From 82a17c9fb3d64ccdd474c3bedf564368f77e84a4 Mon Sep 17 00:00:00 2001 From: Repo Admin Date: Sat, 19 Oct 2002 07:55:27 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- ABOUT-NLS | 324 -- BUGS | 12 - INSTALL | 231 -- NOTES | 46 - OBUGS | 102 - PROJECTS | 46 - THOUGHTS | 275 -- agent/ChangeLog | 419 -- agent/Makefile.am | 62 - agent/agent.h | 197 - agent/cache.c | 314 -- agent/call-scd.c | 592 --- agent/command.c | 697 ---- agent/divert-scd.c | 305 -- agent/findkey.c | 350 -- agent/genkey.c | 200 - agent/gpg-agent.c | 916 ----- agent/learncard.c | 380 -- agent/minip12.c | 1146 ------ agent/minip12.h | 32 - agent/pkdecrypt.c | 138 - agent/pksign.c | 183 - agent/protect-tool.c | 977 ----- agent/protect.c | 967 ----- agent/query.c | 460 --- agent/sexp-parse.h | 98 - agent/simple-pwquery.c | 485 --- agent/trustlist.c | 304 -- assuan/ChangeLog | 250 -- assuan/Makefile.am | 49 - assuan/assuan-buffer.c | 443 --- assuan/assuan-client.c | 225 -- assuan/assuan-connect.c | 54 - assuan/assuan-defs.h | 144 - assuan/assuan-handler.c | 708 ---- assuan/assuan-inquire.c | 239 -- assuan/assuan-listen.c | 132 - assuan/assuan-pipe-connect.c | 288 -- assuan/assuan-pipe-server.c | 124 - assuan/assuan-socket-connect.c | 150 - assuan/assuan-socket-server.c | 169 - assuan/assuan-util.c | 210 - assuan/assuan.h | 234 -- assuan/mkerrors | 71 - checks/ChangeLog | 171 - checks/Makefile.am | 107 - checks/armdetach.test | 11 - checks/armdetachm.test | 9 - checks/armencrypt.test | 11 - checks/armencryptp.test | 12 - checks/armsignencrypt.test | 13 - checks/armsigs.test | 11 - checks/challenge-1 | 42 - checks/clearsig.test | 103 - checks/conventional-mdc.test | 21 - checks/conventional.test | 24 - checks/decrypt-dsa.test | 10 - checks/decrypt.test | 10 - checks/defs.inc | 106 - checks/detach.test | 10 - checks/detachm.test | 9 - checks/encrypt-dsa.test | 19 - checks/encrypt.test | 16 - checks/encryptp.test | 10 - checks/genkey1024.test | 26 - checks/mds.test | 40 - checks/mkdemodirs | 37 - checks/multisig.test | 145 - checks/options.in | 6 - checks/pgp263-test.pub.asc | 14 - checks/pgp263-test.sec.asc | 18 - checks/plain-1-pgp.asc | 29 - checks/plain-1.asc | 32 - checks/plain-1o.asc | 28 - checks/plain-2.asc | 41 - checks/plain-2o.asc | 36 - checks/plain-3.asc | 13 - checks/plain-3o.asc | 10 - checks/pubdemo.asc | 566 --- checks/pubring.asc | 734 ---- checks/pubring.pkr.asc | 28 - checks/seat.test | 11 - checks/secdemo.asc | 737 ---- checks/secring.asc | 57 - checks/secring.skr.asc | 27 - checks/signdemokey | 16 - checks/signencrypt-dsa.test | 22 - checks/signencrypt.test | 13 - checks/sigs-dsa.test | 22 - checks/sigs.test | 26 - checks/version.test | 9 - cipher/ChangeLog | 1027 ----- cipher/Makefile.am | 63 - cipher/algorithms.h | 118 - cipher/bithelp.h | 41 - cipher/blowfish.c | 632 --- cipher/cast5.c | 654 --- cipher/cipher.c | 678 ---- cipher/des.c | 1024 ----- cipher/dsa.c | 483 --- cipher/dsa.h | 32 - cipher/dynload.c | 103 - cipher/elgamal.c | 666 ---- cipher/elgamal.h | 35 - cipher/g10c.c | 46 - cipher/gost.c | 76 - cipher/gost.h | 46 - cipher/idea-stub.c | 198 - cipher/md.c | 505 --- cipher/md5.c | 367 -- cipher/primegen.c | 583 --- cipher/pubkey.c | 559 --- cipher/rand-internal.h | 38 - cipher/random.c | 749 ---- cipher/random.h | 41 - cipher/rijndael.c | 2234 ----------- cipher/rmd.h | 35 - cipher/rmd160.c | 588 --- cipher/rmd160test.c | 63 - cipher/rndegd.c | 229 -- cipher/rndlinux.c | 164 - cipher/rndriscos.c | 95 - cipher/rndunix.c | 869 ---- cipher/rndw32.c | 706 ---- cipher/rsa.c | 494 --- cipher/rsa.h | 36 - cipher/sha1.c | 359 -- cipher/smallprime.c | 114 - cipher/tiger.c | 930 ----- cipher/twofish.c | 1135 ------ common/ChangeLog | 139 - common/Makefile.am | 52 - common/README | 14 - common/errors.h | 192 - common/gettime.c | 87 - common/maperror.c | 271 -- common/signal.c | 226 -- common/util.h | 117 - contrib/UTF-8-test.txt | Bin 16921 -> 0 bytes contrib/changes-in-2000 | 114 - contrib/why-gnupg | 80 - debian/README.Debian | 28 - debian/changelog | 402 -- debian/control | 24 - debian/copyright | 29 - debian/distfiles | 6 - debian/lintian.override | 1 - debian/preinst | 47 - debian/rules | 85 - doc/ChangeLog | 500 --- doc/DETAILS | 990 ----- doc/HACKING | 301 -- doc/OpenPGP | 108 - doc/README.W32 | 100 - doc/credits-1.0 | 41 - doc/faq.raw | 1019 ----- doc/fr/ChangeLog | 17 - doc/fr/DETAILS | 945 ----- doc/fr/FAQ | 1111 ------ doc/fr/README.fr | 10 - doc/gnupg-w32.reg | 8 - doc/gnupg.7 | 14 - doc/gpg.sgml | 2461 ------------ doc/gpg.texi | 1531 ------- doc/gpgv.sgml | 225 -- doc/gpgv.texi | 119 - doc/gph/ChangeLog | 9 - doc/gph/Makefile.am | 54 - doc/gph/c1.sgml | 627 --- doc/gph/c2.sgml | 345 -- doc/gph/c3.sgml | 885 ----- doc/gph/c4.sgml | 433 -- doc/gph/c5.sgml | 38 - doc/gph/c6.sgml | 804 ---- doc/gph/c7.sgml | 251 -- doc/gph/manual.sgml | 71 - doc/gph/signatures.fig | 44 - doc/gph/signatures.jpg.asc | 232 -- doc/samplekeys.asc | 624 --- g10/ChangeLog | 7014 --------------------------------- g10/Makefile.am | 123 - g10/armor.c | 1322 ------- g10/build-packet.c | 1167 ------ g10/cipher.c | 152 - g10/compress.c | 310 -- g10/decrypt.c | 138 - g10/delkey.c | 221 -- g10/encode.c | 798 ---- g10/exec.c | 617 --- g10/exec.h | 23 - g10/export.c | 350 -- g10/filter.h | 142 - g10/free-packet.c | 547 --- g10/g10.c | 2816 ------------- g10/getkey.c | 2476 ------------ g10/gpgv.c | 374 -- g10/import.c | 1796 --------- g10/kbnode.c | 399 -- g10/keydb.c | 686 ---- g10/keydb.h | 265 -- g10/keyedit.c | 3281 --------------- g10/keygen.c | 2429 ------------ g10/keyid.c | 502 --- g10/keylist.c | 1116 ------ g10/keyring.c | 1558 -------- g10/keyring.h | 45 - g10/keyserver.c | 1264 ------ g10/main.h | 224 -- g10/mainproc.c | 1656 -------- g10/misc.c | 548 --- g10/openfile.c | 362 -- g10/options.h | 208 - g10/options.skel | 203 - g10/packet.h | 494 --- g10/parse-packet.c | 2260 ----------- g10/passphrase.c | 1164 ------ g10/photoid.c | 332 -- g10/photoid.h | 14 - g10/pkclist.c | 1303 ------ g10/plaintext.c | 418 -- g10/pubkey-enc.c | 296 -- g10/revoke.c | 717 ---- g10/seckey-cert.c | 382 -- g10/sig-check.c | 619 --- g10/sign.c | 1300 ------ g10/signal.c | 217 - g10/status.c | 693 ---- g10/status.h | 126 - g10/tdbio.c | 1578 -------- g10/tdbio.h | 111 - g10/textfilter.c | 235 -- g10/trustdb.c | 1642 -------- g10/trustdb.h | 76 - g10/verify.c | 189 - gnupg.txt | 98 - include/ChangeLog | 310 -- include/cipher.h | 198 - include/distfiles | 14 - include/http.h | 81 - include/i18n.h | 54 - include/iobuf.h | 161 - include/memory.h | 95 - include/mpi.h | 197 - include/ttyio.h | 39 - include/types.h | 131 - include/util.h | 296 -- intl/ChangeLog | 4 - intl/Makefile.in | 313 -- intl/VERSION | 1 - intl/bindtextdom.c | 369 -- intl/config.charset | 438 -- intl/dcgettext.c | 58 - intl/dcigettext.c | 1259 ------ intl/dcngettext.c | 60 - intl/dgettext.c | 59 - intl/dngettext.c | 61 - intl/finddomain.c | 198 - intl/gettext.c | 64 - intl/gettext.h | 102 - intl/gettextP.h | 252 -- intl/hash-string.h | 59 - intl/intl-compat.c | 166 - intl/l10nflist.c | 405 -- intl/libgettext.h | 49 - intl/loadinfo.h | 109 - intl/loadmsgcat.c | 567 --- intl/localcharset.c | 271 -- intl/localealias.c | 404 -- intl/ngettext.c | 68 - intl/plural.c | 1326 ------- intl/plural.y | 413 -- intl/textdomain.c | 142 - kbx/ChangeLog | 102 - kbx/Makefile.am | 53 - kbx/kbxutil.c | 338 -- kbx/keybox-blob.c | 1007 ----- kbx/keybox-defs.h | 179 - kbx/keybox-dump.c | 346 -- kbx/keybox-file.c | 102 - kbx/keybox-init.c | 127 - kbx/keybox-search.c | 810 ---- kbx/keybox-update.c | 433 -- kbx/keybox.h | 125 - keyserver/ChangeLog | 291 -- keyserver/Makefile.am | 34 - keyserver/gpgkeys_hkp.c | 1062 ----- keyserver/gpgkeys_ldap.c | 1107 ------ keyserver/gpgkeys_mailto.in | 202 - keyserver/gpgkeys_test.in | 79 - mpi/ChangeLog | 390 -- mpi/Makefile.am | 79 - mpi/alpha/README | 53 - mpi/alpha/distfiles | 11 - mpi/alpha/mpih-add1.S | 124 - mpi/alpha/mpih-lshift.S | 123 - mpi/alpha/mpih-mul1.S | 90 - mpi/alpha/mpih-mul2.S | 97 - mpi/alpha/mpih-mul3.S | 95 - mpi/alpha/mpih-rshift.S | 120 - mpi/alpha/mpih-sub1.S | 124 - mpi/alpha/udiv-qrnnd.S | 161 - mpi/config.links | 328 -- mpi/g10m.c | 95 - mpi/generic/distfiles | 10 - mpi/generic/mpi-asm-defs.h | 10 - mpi/generic/mpih-add1.c | 65 - mpi/generic/mpih-lshift.c | 69 - mpi/generic/mpih-mul1.c | 61 - mpi/generic/mpih-mul2.c | 66 - mpi/generic/mpih-mul3.c | 67 - mpi/generic/mpih-rshift.c | 68 - mpi/generic/mpih-sub1.c | 65 - mpi/generic/udiv-w-sdiv.c | 133 - mpi/hppa/README | 84 - mpi/hppa/distfiles | 7 - mpi/hppa/mpih-add1.S | 72 - mpi/hppa/mpih-lshift.S | 77 - mpi/hppa/mpih-rshift.S | 73 - mpi/hppa/mpih-sub1.S | 80 - mpi/hppa/udiv-qrnnd.S | 298 -- mpi/hppa1.1/distfiles | 5 - mpi/hppa1.1/mpih-mul1.S | 115 - mpi/hppa1.1/mpih-mul2.S | 117 - mpi/hppa1.1/mpih-mul3.S | 127 - mpi/hppa1.1/udiv-qrnnd.S | 90 - mpi/i386-openbsd/README | 3 - mpi/i386-openbsd/distfiles | 9 - mpi/i386-openbsd/mpih-add1.S | 118 - mpi/i386-openbsd/mpih-lshift.S | 96 - mpi/i386-openbsd/mpih-mul1.S | 86 - mpi/i386-openbsd/mpih-mul2.S | 88 - mpi/i386-openbsd/mpih-mul3.S | 88 - mpi/i386-openbsd/mpih-rshift.S | 99 - mpi/i386-openbsd/mpih-sub1.S | 119 - mpi/i386-openbsd/syntax.h | 68 - mpi/i386/distfiles | 9 - mpi/i386/mpih-add1.S | 118 - mpi/i386/mpih-lshift.S | 96 - mpi/i386/mpih-mul1.S | 86 - mpi/i386/mpih-mul2.S | 88 - mpi/i386/mpih-mul3.S | 88 - mpi/i386/mpih-rshift.S | 99 - mpi/i386/mpih-sub1.S | 119 - mpi/i386/syntax.h | 68 - mpi/i586/README | 26 - mpi/i586/distfiles | 9 - mpi/i586/mpih-add1.S | 135 - mpi/i586/mpih-lshift.S | 231 -- mpi/i586/mpih-mul1.S | 91 - mpi/i586/mpih-mul2.S | 95 - mpi/i586/mpih-mul3.S | 95 - mpi/i586/mpih-rshift.S | 230 -- mpi/i586/mpih-sub1.S | 144 - mpi/longlong.h | 1499 ------- mpi/m68k/distfiles | 8 - mpi/m68k/mc68020/distfiles | 3 - mpi/m68k/mc68020/mpih-mul1.S | 106 - mpi/m68k/mc68020/mpih-mul2.S | 96 - mpi/m68k/mc68020/mpih-mul3.S | 99 - mpi/m68k/mpih-add1.S | 94 - mpi/m68k/mpih-lshift.S | 166 - mpi/m68k/mpih-rshift.S | 164 - mpi/m68k/mpih-sub1.S | 93 - mpi/m68k/syntax.h | 187 - mpi/mips3/README | 23 - mpi/mips3/distfiles | 10 - mpi/mips3/mpi-asm-defs.h | 10 - mpi/mips3/mpih-add1.S | 124 - mpi/mips3/mpih-lshift.S | 97 - mpi/mips3/mpih-mul1.S | 89 - mpi/mips3/mpih-mul2.S | 101 - mpi/mips3/mpih-mul3.S | 101 - mpi/mips3/mpih-rshift.S | 95 - mpi/mips3/mpih-sub1.S | 125 - mpi/mpi-add.c | 247 -- mpi/mpi-bit.c | 255 -- mpi/mpi-cmp.c | 74 - mpi/mpi-div.c | 322 -- mpi/mpi-gcd.c | 54 - mpi/mpi-inline.c | 36 - mpi/mpi-inline.h | 128 - mpi/mpi-internal.h | 259 -- mpi/mpi-inv.c | 270 -- mpi/mpi-mpow.c | 101 - mpi/mpi-mul.c | 215 - mpi/mpi-pow.c | 294 -- mpi/mpi-scan.c | 132 - mpi/mpicoder.c | 447 --- mpi/mpih-cmp.c | 62 - mpi/mpih-div.c | 537 --- mpi/mpih-mul.c | 528 --- mpi/mpiutil.c | 471 --- mpi/pa7100/distfiles | 3 - mpi/pa7100/mpih-lshift.S | 96 - mpi/pa7100/mpih-rshift.S | 92 - mpi/power/distfiles | 7 - mpi/power/mpih-add1.S | 86 - mpi/power/mpih-lshift.S | 64 - mpi/power/mpih-mul1.S | 115 - mpi/power/mpih-mul2.S | 130 - mpi/power/mpih-mul3.S | 135 - mpi/power/mpih-rshift.S | 64 - mpi/power/mpih-sub1.S | 88 - mpi/powerpc32/distfiles | 9 - mpi/powerpc32/mpih-add1.S | 136 - mpi/powerpc32/mpih-lshift.S | 198 - mpi/powerpc32/mpih-mul1.S | 120 - mpi/powerpc32/mpih-mul2.S | 127 - mpi/powerpc32/mpih-mul3.S | 130 - mpi/powerpc32/mpih-rshift.S | 131 - mpi/powerpc32/mpih-sub1.S | 132 - mpi/powerpc32/syntax.h | 75 - mpi/powerpc64/distfiles | 0 mpi/sparc32/distfiles | 6 - mpi/sparc32/mpih-add1.S | 239 -- mpi/sparc32/mpih-lshift.S | 97 - mpi/sparc32/mpih-rshift.S | 93 - mpi/sparc32/udiv.S | 197 - mpi/sparc32v8/distfiles | 5 - mpi/sparc32v8/mpih-mul1.S | 111 - mpi/sparc32v8/mpih-mul2.S | 134 - mpi/sparc32v8/mpih-mul3.S | 69 - mpi/supersparc/distfiles | 3 - mpi/supersparc/udiv.S | 120 - po/Makefile.in.in | 196 - po/ca.po | 4944 ----------------------- po/cs.po | 4716 ---------------------- po/da.po | 4565 --------------------- po/de.glo | 238 -- po/de.po | 5158 ------------------------ po/el.po | 4673 ---------------------- po/eo.po | 4938 ----------------------- po/es.po | 5228 ------------------------ po/et.po | 4646 ---------------------- po/fr.po | 4750 ---------------------- po/gl.po | 5002 ----------------------- po/id.po | 4707 ---------------------- po/it.po | 4704 ---------------------- po/ja.po | 4671 ---------------------- po/nl.po | 5017 ----------------------- po/pl.po | 5358 ------------------------- po/pt.po | 4720 ---------------------- po/pt_BR.po | 5222 ------------------------ po/sv.po | 4987 ----------------------- po/tr.po | 4658 ---------------------- scd/ChangeLog | 91 - scd/Makefile.am | 42 - scd/card-common.h | 73 - scd/card-dinsig.c | 256 -- scd/card-p15.c | 498 --- scd/card.c | 540 --- scd/command.c | 651 --- scd/scdaemon.c | 633 --- scd/scdaemon.h | 104 - scripts/ChangeLog | 285 -- scripts/autogen.sh | 148 - scripts/build-riscos | 11 - scripts/build-w32 | 6 - scripts/commit | 63 - scripts/conf-riscos/Makefile | 466 --- scripts/conf-riscos/include/config.h | 390 -- scripts/conf-riscos/include/g10defs.h | 42 - scripts/config.guess | 1317 ------- scripts/config.sub | 1411 ------- scripts/distfiles | 6 - scripts/gnupg.spec.in | 177 - scripts/gnupgbug | 185 - scripts/log_accum | 595 --- scripts/mail-to-translators | 70 - scripts/mk-gpg-texi | 46 - scripts/mk-w32-dist | 90 - scripts/mkdiff | 115 - scripts/mkinstalldirs | 101 - scripts/mksnapshot | 79 - scripts/mkwebpage | 105 - sm/ChangeLog | 741 ---- sm/Makefile.am | 57 - sm/base64.c | 624 --- sm/call-agent.c | 751 ---- sm/call-dirmngr.c | 495 --- sm/certchain.c | 786 ---- sm/certcheck.c | 301 -- sm/certdump.c | 457 --- sm/certlist.c | 313 -- sm/certreqgen.c | 699 ---- sm/decrypt.c | 502 --- sm/delete.c | 165 - sm/encrypt.c | 549 --- sm/export.c | 248 -- sm/fingerprint.c | 271 -- sm/gpgsm.c | 1388 ------- sm/gpgsm.h | 261 -- sm/import.c | 349 -- sm/keydb.c | 1282 ------ sm/keylist.c | 616 --- sm/server.c | 1057 ----- sm/sign.c | 622 --- sm/verify.c | 510 --- stamp-h.in | 1 - tests/ChangeLog | 52 - tests/Makefile.am | 78 - tests/asschk.c | 1046 ----- tests/inittests | 96 - tools/ChangeLog | 102 - tools/Makefile.am | 45 - tools/bftest.c | 112 - tools/clean-sat.c | 34 - tools/crlf.c | 53 - tools/gpgsplit.c | 553 --- tools/lspgpot | 23 - tools/mail-signed-keys | 114 - tools/mk-tdata.c | 43 - tools/mpicalc.c | 390 -- tools/ring-a-party | 118 - tools/shmtest.c | 206 - tools/signmany | 33 - util/ChangeLog | 1021 ----- util/Makefile.am | 37 - util/argparse.c | 1000 ----- util/dotlock.c | 420 -- util/errors.c | 113 - util/fileutil.c | 242 -- util/g10u.c | 40 - util/http.c | 903 ----- util/iobuf.c | 2189 ---------- util/logger.c | 334 -- util/memory.c | 634 --- util/miscutil.c | 361 -- util/riscos.c | 299 -- util/secmem.c | 470 --- util/simple-gettext.c | 497 --- util/strgutil.c | 955 ----- util/ttyio.c | 481 --- util/w32reg.c | 171 - zlib/ChangeLog | 505 --- zlib/Makefile.am | 28 - zlib/README | 148 - zlib/adler32.c | 48 - zlib/algorithm.doc | 105 - zlib/compress.c | 68 - zlib/crc32.c | 162 - zlib/deflate.c | 1350 ------- zlib/deflate.h | 318 -- zlib/example.c | 556 --- zlib/infblock.c | 403 -- zlib/infblock.h | 39 - zlib/infcodes.c | 251 -- zlib/infcodes.h | 27 - zlib/inffast.c | 183 - zlib/inffast.h | 17 - zlib/inffixed.h | 151 - zlib/inflate.c | 366 -- zlib/inftrees.c | 454 --- zlib/inftrees.h | 58 - zlib/infutil.c | 87 - zlib/infutil.h | 98 - zlib/trees.c | 1214 ------ zlib/trees.h | 128 - zlib/uncompr.c | 58 - zlib/zconf.h | 279 -- zlib/zlib.h | 893 ----- zlib/zutil.c | 225 -- zlib/zutil.h | 220 -- 563 files changed, 267875 deletions(-) delete mode 100644 ABOUT-NLS delete mode 100644 BUGS delete mode 100644 INSTALL delete mode 100644 NOTES delete mode 100644 OBUGS delete mode 100644 PROJECTS delete mode 100644 THOUGHTS delete mode 100644 agent/ChangeLog delete mode 100644 agent/Makefile.am delete mode 100644 agent/agent.h delete mode 100644 agent/cache.c delete mode 100644 agent/call-scd.c delete mode 100644 agent/command.c delete mode 100644 agent/divert-scd.c delete mode 100644 agent/findkey.c delete mode 100644 agent/genkey.c delete mode 100644 agent/gpg-agent.c delete mode 100644 agent/learncard.c delete mode 100644 agent/minip12.c delete mode 100644 agent/minip12.h delete mode 100644 agent/pkdecrypt.c delete mode 100644 agent/pksign.c delete mode 100644 agent/protect-tool.c delete mode 100644 agent/protect.c delete mode 100644 agent/query.c delete mode 100644 agent/sexp-parse.h delete mode 100644 agent/simple-pwquery.c delete mode 100644 agent/trustlist.c delete mode 100644 assuan/ChangeLog delete mode 100644 assuan/Makefile.am delete mode 100644 assuan/assuan-buffer.c delete mode 100644 assuan/assuan-client.c delete mode 100644 assuan/assuan-connect.c delete mode 100644 assuan/assuan-defs.h delete mode 100644 assuan/assuan-handler.c delete mode 100644 assuan/assuan-inquire.c delete mode 100644 assuan/assuan-listen.c delete mode 100644 assuan/assuan-pipe-connect.c delete mode 100644 assuan/assuan-pipe-server.c delete mode 100644 assuan/assuan-socket-connect.c delete mode 100644 assuan/assuan-socket-server.c delete mode 100644 assuan/assuan-util.c delete mode 100644 assuan/assuan.h delete mode 100755 assuan/mkerrors delete mode 100644 checks/ChangeLog delete mode 100644 checks/Makefile.am delete mode 100755 checks/armdetach.test delete mode 100755 checks/armdetachm.test delete mode 100755 checks/armencrypt.test delete mode 100755 checks/armencryptp.test delete mode 100755 checks/armsignencrypt.test delete mode 100755 checks/armsigs.test delete mode 100644 checks/challenge-1 delete mode 100755 checks/clearsig.test delete mode 100755 checks/conventional-mdc.test delete mode 100755 checks/conventional.test delete mode 100755 checks/decrypt-dsa.test delete mode 100755 checks/decrypt.test delete mode 100755 checks/defs.inc delete mode 100755 checks/detach.test delete mode 100755 checks/detachm.test delete mode 100755 checks/encrypt-dsa.test delete mode 100755 checks/encrypt.test delete mode 100755 checks/encryptp.test delete mode 100755 checks/genkey1024.test delete mode 100755 checks/mds.test delete mode 100755 checks/mkdemodirs delete mode 100755 checks/multisig.test delete mode 100644 checks/options.in delete mode 100644 checks/pgp263-test.pub.asc delete mode 100644 checks/pgp263-test.sec.asc delete mode 100644 checks/plain-1-pgp.asc delete mode 100644 checks/plain-1.asc delete mode 100644 checks/plain-1o.asc delete mode 100644 checks/plain-2.asc delete mode 100644 checks/plain-2o.asc delete mode 100644 checks/plain-3.asc delete mode 100644 checks/plain-3o.asc delete mode 100644 checks/pubdemo.asc delete mode 100644 checks/pubring.asc delete mode 100644 checks/pubring.pkr.asc delete mode 100755 checks/seat.test delete mode 100644 checks/secdemo.asc delete mode 100644 checks/secring.asc delete mode 100644 checks/secring.skr.asc delete mode 100755 checks/signdemokey delete mode 100755 checks/signencrypt-dsa.test delete mode 100755 checks/signencrypt.test delete mode 100755 checks/sigs-dsa.test delete mode 100755 checks/sigs.test delete mode 100755 checks/version.test delete mode 100644 cipher/ChangeLog delete mode 100644 cipher/Makefile.am delete mode 100644 cipher/algorithms.h delete mode 100644 cipher/bithelp.h delete mode 100644 cipher/blowfish.c delete mode 100644 cipher/cast5.c delete mode 100644 cipher/cipher.c delete mode 100644 cipher/des.c delete mode 100644 cipher/dsa.c delete mode 100644 cipher/dsa.h delete mode 100644 cipher/dynload.c delete mode 100644 cipher/elgamal.c delete mode 100644 cipher/elgamal.h delete mode 100644 cipher/g10c.c delete mode 100644 cipher/gost.c delete mode 100644 cipher/gost.h delete mode 100644 cipher/idea-stub.c delete mode 100644 cipher/md.c delete mode 100644 cipher/md5.c delete mode 100644 cipher/primegen.c delete mode 100644 cipher/pubkey.c delete mode 100644 cipher/rand-internal.h delete mode 100644 cipher/random.c delete mode 100644 cipher/random.h delete mode 100644 cipher/rijndael.c delete mode 100644 cipher/rmd.h delete mode 100644 cipher/rmd160.c delete mode 100644 cipher/rmd160test.c delete mode 100644 cipher/rndegd.c delete mode 100644 cipher/rndlinux.c delete mode 100644 cipher/rndriscos.c delete mode 100644 cipher/rndunix.c delete mode 100644 cipher/rndw32.c delete mode 100644 cipher/rsa.c delete mode 100644 cipher/rsa.h delete mode 100644 cipher/sha1.c delete mode 100644 cipher/smallprime.c delete mode 100644 cipher/tiger.c delete mode 100644 cipher/twofish.c delete mode 100644 common/ChangeLog delete mode 100644 common/Makefile.am delete mode 100644 common/README delete mode 100644 common/errors.h delete mode 100644 common/gettime.c delete mode 100644 common/maperror.c delete mode 100644 common/signal.c delete mode 100644 common/util.h delete mode 100644 contrib/UTF-8-test.txt delete mode 100644 contrib/changes-in-2000 delete mode 100644 contrib/why-gnupg delete mode 100644 debian/README.Debian delete mode 100644 debian/changelog delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100644 debian/distfiles delete mode 100644 debian/lintian.override delete mode 100644 debian/preinst delete mode 100644 debian/rules delete mode 100644 doc/ChangeLog delete mode 100644 doc/DETAILS delete mode 100644 doc/HACKING delete mode 100644 doc/OpenPGP delete mode 100644 doc/README.W32 delete mode 100644 doc/credits-1.0 delete mode 100644 doc/faq.raw delete mode 100644 doc/fr/ChangeLog delete mode 100644 doc/fr/DETAILS delete mode 100644 doc/fr/FAQ delete mode 100644 doc/fr/README.fr delete mode 100644 doc/gnupg-w32.reg delete mode 100644 doc/gnupg.7 delete mode 100644 doc/gpg.sgml delete mode 100644 doc/gpg.texi delete mode 100644 doc/gpgv.sgml delete mode 100644 doc/gpgv.texi delete mode 100644 doc/gph/ChangeLog delete mode 100644 doc/gph/Makefile.am delete mode 100644 doc/gph/c1.sgml delete mode 100644 doc/gph/c2.sgml delete mode 100644 doc/gph/c3.sgml delete mode 100644 doc/gph/c4.sgml delete mode 100644 doc/gph/c5.sgml delete mode 100644 doc/gph/c6.sgml delete mode 100644 doc/gph/c7.sgml delete mode 100644 doc/gph/manual.sgml delete mode 100644 doc/gph/signatures.fig delete mode 100644 doc/gph/signatures.jpg.asc delete mode 100644 doc/samplekeys.asc delete mode 100644 g10/ChangeLog delete mode 100644 g10/Makefile.am delete mode 100644 g10/armor.c delete mode 100644 g10/build-packet.c delete mode 100644 g10/cipher.c delete mode 100644 g10/compress.c delete mode 100644 g10/decrypt.c delete mode 100644 g10/delkey.c delete mode 100644 g10/encode.c delete mode 100644 g10/exec.c delete mode 100644 g10/exec.h delete mode 100644 g10/export.c delete mode 100644 g10/filter.h delete mode 100644 g10/free-packet.c delete mode 100644 g10/g10.c delete mode 100644 g10/getkey.c delete mode 100644 g10/gpgv.c delete mode 100644 g10/import.c delete mode 100644 g10/kbnode.c delete mode 100644 g10/keydb.c delete mode 100644 g10/keydb.h delete mode 100644 g10/keyedit.c delete mode 100644 g10/keygen.c delete mode 100644 g10/keyid.c delete mode 100644 g10/keylist.c delete mode 100644 g10/keyring.c delete mode 100644 g10/keyring.h delete mode 100644 g10/keyserver.c delete mode 100644 g10/main.h delete mode 100644 g10/mainproc.c delete mode 100644 g10/misc.c delete mode 100644 g10/openfile.c delete mode 100644 g10/options.h delete mode 100644 g10/options.skel delete mode 100644 g10/packet.h delete mode 100644 g10/parse-packet.c delete mode 100644 g10/passphrase.c delete mode 100644 g10/photoid.c delete mode 100644 g10/photoid.h delete mode 100644 g10/pkclist.c delete mode 100644 g10/plaintext.c delete mode 100644 g10/pubkey-enc.c delete mode 100644 g10/revoke.c delete mode 100644 g10/seckey-cert.c delete mode 100644 g10/sig-check.c delete mode 100644 g10/sign.c delete mode 100644 g10/signal.c delete mode 100644 g10/status.c delete mode 100644 g10/status.h delete mode 100644 g10/tdbio.c delete mode 100644 g10/tdbio.h delete mode 100644 g10/textfilter.c delete mode 100644 g10/trustdb.c delete mode 100644 g10/trustdb.h delete mode 100644 g10/verify.c delete mode 100644 gnupg.txt delete mode 100644 include/ChangeLog delete mode 100644 include/cipher.h delete mode 100644 include/distfiles delete mode 100644 include/http.h delete mode 100644 include/i18n.h delete mode 100644 include/iobuf.h delete mode 100644 include/memory.h delete mode 100644 include/mpi.h delete mode 100644 include/ttyio.h delete mode 100644 include/types.h delete mode 100644 include/util.h delete mode 100644 intl/ChangeLog delete mode 100644 intl/Makefile.in delete mode 100644 intl/VERSION delete mode 100644 intl/bindtextdom.c delete mode 100755 intl/config.charset delete mode 100644 intl/dcgettext.c delete mode 100644 intl/dcigettext.c delete mode 100644 intl/dcngettext.c delete mode 100644 intl/dgettext.c delete mode 100644 intl/dngettext.c delete mode 100644 intl/finddomain.c delete mode 100644 intl/gettext.c delete mode 100644 intl/gettext.h delete mode 100644 intl/gettextP.h delete mode 100644 intl/hash-string.h delete mode 100644 intl/intl-compat.c delete mode 100644 intl/l10nflist.c delete mode 100644 intl/libgettext.h delete mode 100644 intl/loadinfo.h delete mode 100644 intl/loadmsgcat.c delete mode 100644 intl/localcharset.c delete mode 100644 intl/localealias.c delete mode 100644 intl/ngettext.c delete mode 100644 intl/plural.c delete mode 100644 intl/plural.y delete mode 100644 intl/textdomain.c delete mode 100644 kbx/ChangeLog delete mode 100644 kbx/Makefile.am delete mode 100644 kbx/kbxutil.c delete mode 100644 kbx/keybox-blob.c delete mode 100644 kbx/keybox-defs.h delete mode 100644 kbx/keybox-dump.c delete mode 100644 kbx/keybox-file.c delete mode 100644 kbx/keybox-init.c delete mode 100644 kbx/keybox-search.c delete mode 100644 kbx/keybox-update.c delete mode 100644 kbx/keybox.h delete mode 100644 keyserver/ChangeLog delete mode 100644 keyserver/Makefile.am delete mode 100644 keyserver/gpgkeys_hkp.c delete mode 100644 keyserver/gpgkeys_ldap.c delete mode 100755 keyserver/gpgkeys_mailto.in delete mode 100755 keyserver/gpgkeys_test.in delete mode 100644 mpi/ChangeLog delete mode 100644 mpi/Makefile.am delete mode 100644 mpi/alpha/README delete mode 100644 mpi/alpha/distfiles delete mode 100644 mpi/alpha/mpih-add1.S delete mode 100644 mpi/alpha/mpih-lshift.S delete mode 100644 mpi/alpha/mpih-mul1.S delete mode 100644 mpi/alpha/mpih-mul2.S delete mode 100644 mpi/alpha/mpih-mul3.S delete mode 100644 mpi/alpha/mpih-rshift.S delete mode 100644 mpi/alpha/mpih-sub1.S delete mode 100644 mpi/alpha/udiv-qrnnd.S delete mode 100644 mpi/config.links delete mode 100644 mpi/g10m.c delete mode 100644 mpi/generic/distfiles delete mode 100644 mpi/generic/mpi-asm-defs.h delete mode 100644 mpi/generic/mpih-add1.c delete mode 100644 mpi/generic/mpih-lshift.c delete mode 100644 mpi/generic/mpih-mul1.c delete mode 100644 mpi/generic/mpih-mul2.c delete mode 100644 mpi/generic/mpih-mul3.c delete mode 100644 mpi/generic/mpih-rshift.c delete mode 100644 mpi/generic/mpih-sub1.c delete mode 100644 mpi/generic/udiv-w-sdiv.c delete mode 100644 mpi/hppa/README delete mode 100644 mpi/hppa/distfiles delete mode 100644 mpi/hppa/mpih-add1.S delete mode 100644 mpi/hppa/mpih-lshift.S delete mode 100644 mpi/hppa/mpih-rshift.S delete mode 100644 mpi/hppa/mpih-sub1.S delete mode 100644 mpi/hppa/udiv-qrnnd.S delete mode 100644 mpi/hppa1.1/distfiles delete mode 100644 mpi/hppa1.1/mpih-mul1.S delete mode 100644 mpi/hppa1.1/mpih-mul2.S delete mode 100644 mpi/hppa1.1/mpih-mul3.S delete mode 100644 mpi/hppa1.1/udiv-qrnnd.S delete mode 100644 mpi/i386-openbsd/README delete mode 100644 mpi/i386-openbsd/distfiles delete mode 100644 mpi/i386-openbsd/mpih-add1.S delete mode 100644 mpi/i386-openbsd/mpih-lshift.S delete mode 100644 mpi/i386-openbsd/mpih-mul1.S delete mode 100644 mpi/i386-openbsd/mpih-mul2.S delete mode 100644 mpi/i386-openbsd/mpih-mul3.S delete mode 100644 mpi/i386-openbsd/mpih-rshift.S delete mode 100644 mpi/i386-openbsd/mpih-sub1.S delete mode 100644 mpi/i386-openbsd/syntax.h delete mode 100644 mpi/i386/distfiles delete mode 100644 mpi/i386/mpih-add1.S delete mode 100644 mpi/i386/mpih-lshift.S delete mode 100644 mpi/i386/mpih-mul1.S delete mode 100644 mpi/i386/mpih-mul2.S delete mode 100644 mpi/i386/mpih-mul3.S delete mode 100644 mpi/i386/mpih-rshift.S delete mode 100644 mpi/i386/mpih-sub1.S delete mode 100644 mpi/i386/syntax.h delete mode 100644 mpi/i586/README delete mode 100644 mpi/i586/distfiles delete mode 100644 mpi/i586/mpih-add1.S delete mode 100644 mpi/i586/mpih-lshift.S delete mode 100644 mpi/i586/mpih-mul1.S delete mode 100644 mpi/i586/mpih-mul2.S delete mode 100644 mpi/i586/mpih-mul3.S delete mode 100644 mpi/i586/mpih-rshift.S delete mode 100644 mpi/i586/mpih-sub1.S delete mode 100644 mpi/longlong.h delete mode 100644 mpi/m68k/distfiles delete mode 100644 mpi/m68k/mc68020/distfiles delete mode 100644 mpi/m68k/mc68020/mpih-mul1.S delete mode 100644 mpi/m68k/mc68020/mpih-mul2.S delete mode 100644 mpi/m68k/mc68020/mpih-mul3.S delete mode 100644 mpi/m68k/mpih-add1.S delete mode 100644 mpi/m68k/mpih-lshift.S delete mode 100644 mpi/m68k/mpih-rshift.S delete mode 100644 mpi/m68k/mpih-sub1.S delete mode 100644 mpi/m68k/syntax.h delete mode 100644 mpi/mips3/README delete mode 100644 mpi/mips3/distfiles delete mode 100644 mpi/mips3/mpi-asm-defs.h delete mode 100644 mpi/mips3/mpih-add1.S delete mode 100644 mpi/mips3/mpih-lshift.S delete mode 100644 mpi/mips3/mpih-mul1.S delete mode 100644 mpi/mips3/mpih-mul2.S delete mode 100644 mpi/mips3/mpih-mul3.S delete mode 100644 mpi/mips3/mpih-rshift.S delete mode 100644 mpi/mips3/mpih-sub1.S delete mode 100644 mpi/mpi-add.c delete mode 100644 mpi/mpi-bit.c delete mode 100644 mpi/mpi-cmp.c delete mode 100644 mpi/mpi-div.c delete mode 100644 mpi/mpi-gcd.c delete mode 100644 mpi/mpi-inline.c delete mode 100644 mpi/mpi-inline.h delete mode 100644 mpi/mpi-internal.h delete mode 100644 mpi/mpi-inv.c delete mode 100644 mpi/mpi-mpow.c delete mode 100644 mpi/mpi-mul.c delete mode 100644 mpi/mpi-pow.c delete mode 100644 mpi/mpi-scan.c delete mode 100644 mpi/mpicoder.c delete mode 100644 mpi/mpih-cmp.c delete mode 100644 mpi/mpih-div.c delete mode 100644 mpi/mpih-mul.c delete mode 100644 mpi/mpiutil.c delete mode 100644 mpi/pa7100/distfiles delete mode 100644 mpi/pa7100/mpih-lshift.S delete mode 100644 mpi/pa7100/mpih-rshift.S delete mode 100644 mpi/power/distfiles delete mode 100644 mpi/power/mpih-add1.S delete mode 100644 mpi/power/mpih-lshift.S delete mode 100644 mpi/power/mpih-mul1.S delete mode 100644 mpi/power/mpih-mul2.S delete mode 100644 mpi/power/mpih-mul3.S delete mode 100644 mpi/power/mpih-rshift.S delete mode 100644 mpi/power/mpih-sub1.S delete mode 100644 mpi/powerpc32/distfiles delete mode 100644 mpi/powerpc32/mpih-add1.S delete mode 100644 mpi/powerpc32/mpih-lshift.S delete mode 100644 mpi/powerpc32/mpih-mul1.S delete mode 100644 mpi/powerpc32/mpih-mul2.S delete mode 100644 mpi/powerpc32/mpih-mul3.S delete mode 100644 mpi/powerpc32/mpih-rshift.S delete mode 100644 mpi/powerpc32/mpih-sub1.S delete mode 100644 mpi/powerpc32/syntax.h delete mode 100644 mpi/powerpc64/distfiles delete mode 100644 mpi/sparc32/distfiles delete mode 100644 mpi/sparc32/mpih-add1.S delete mode 100644 mpi/sparc32/mpih-lshift.S delete mode 100644 mpi/sparc32/mpih-rshift.S delete mode 100644 mpi/sparc32/udiv.S delete mode 100644 mpi/sparc32v8/distfiles delete mode 100644 mpi/sparc32v8/mpih-mul1.S delete mode 100644 mpi/sparc32v8/mpih-mul2.S delete mode 100644 mpi/sparc32v8/mpih-mul3.S delete mode 100644 mpi/supersparc/distfiles delete mode 100644 mpi/supersparc/udiv.S delete mode 100644 po/Makefile.in.in delete mode 100644 po/ca.po delete mode 100644 po/cs.po delete mode 100644 po/da.po delete mode 100644 po/de.glo delete mode 100644 po/de.po delete mode 100644 po/el.po delete mode 100644 po/eo.po delete mode 100644 po/es.po delete mode 100644 po/et.po delete mode 100644 po/fr.po delete mode 100644 po/gl.po delete mode 100644 po/id.po delete mode 100644 po/it.po delete mode 100644 po/ja.po delete mode 100644 po/nl.po delete mode 100644 po/pl.po delete mode 100644 po/pt.po delete mode 100644 po/pt_BR.po delete mode 100644 po/sv.po delete mode 100644 po/tr.po delete mode 100644 scd/ChangeLog delete mode 100644 scd/Makefile.am delete mode 100644 scd/card-common.h delete mode 100644 scd/card-dinsig.c delete mode 100644 scd/card-p15.c delete mode 100644 scd/card.c delete mode 100644 scd/command.c delete mode 100644 scd/scdaemon.c delete mode 100644 scd/scdaemon.h delete mode 100644 scripts/ChangeLog delete mode 100755 scripts/autogen.sh delete mode 100644 scripts/build-riscos delete mode 100755 scripts/build-w32 delete mode 100755 scripts/commit delete mode 100644 scripts/conf-riscos/Makefile delete mode 100644 scripts/conf-riscos/include/config.h delete mode 100644 scripts/conf-riscos/include/g10defs.h delete mode 100755 scripts/config.guess delete mode 100755 scripts/config.sub delete mode 100644 scripts/distfiles delete mode 100644 scripts/gnupg.spec.in delete mode 100644 scripts/gnupgbug delete mode 100755 scripts/log_accum delete mode 100755 scripts/mail-to-translators delete mode 100755 scripts/mk-gpg-texi delete mode 100755 scripts/mk-w32-dist delete mode 100755 scripts/mkdiff delete mode 100755 scripts/mkinstalldirs delete mode 100755 scripts/mksnapshot delete mode 100755 scripts/mkwebpage delete mode 100644 sm/ChangeLog delete mode 100644 sm/Makefile.am delete mode 100644 sm/base64.c delete mode 100644 sm/call-agent.c delete mode 100644 sm/call-dirmngr.c delete mode 100644 sm/certchain.c delete mode 100644 sm/certcheck.c delete mode 100644 sm/certdump.c delete mode 100644 sm/certlist.c delete mode 100644 sm/certreqgen.c delete mode 100644 sm/decrypt.c delete mode 100644 sm/delete.c delete mode 100644 sm/encrypt.c delete mode 100644 sm/export.c delete mode 100644 sm/fingerprint.c delete mode 100644 sm/gpgsm.c delete mode 100644 sm/gpgsm.h delete mode 100644 sm/import.c delete mode 100644 sm/keydb.c delete mode 100644 sm/keylist.c delete mode 100644 sm/server.c delete mode 100644 sm/sign.c delete mode 100644 sm/verify.c delete mode 100644 stamp-h.in delete mode 100644 tests/ChangeLog delete mode 100644 tests/Makefile.am delete mode 100644 tests/asschk.c delete mode 100755 tests/inittests delete mode 100644 tools/ChangeLog delete mode 100644 tools/Makefile.am delete mode 100644 tools/bftest.c delete mode 100644 tools/clean-sat.c delete mode 100644 tools/crlf.c delete mode 100644 tools/gpgsplit.c delete mode 100755 tools/lspgpot delete mode 100755 tools/mail-signed-keys delete mode 100644 tools/mk-tdata.c delete mode 100644 tools/mpicalc.c delete mode 100755 tools/ring-a-party delete mode 100644 tools/shmtest.c delete mode 100644 tools/signmany delete mode 100644 util/ChangeLog delete mode 100644 util/Makefile.am delete mode 100644 util/argparse.c delete mode 100644 util/dotlock.c delete mode 100644 util/errors.c delete mode 100644 util/fileutil.c delete mode 100644 util/g10u.c delete mode 100644 util/http.c delete mode 100644 util/iobuf.c delete mode 100644 util/logger.c delete mode 100644 util/memory.c delete mode 100644 util/miscutil.c delete mode 100644 util/riscos.c delete mode 100644 util/secmem.c delete mode 100644 util/simple-gettext.c delete mode 100644 util/strgutil.c delete mode 100644 util/ttyio.c delete mode 100644 util/w32reg.c delete mode 100644 zlib/ChangeLog delete mode 100644 zlib/Makefile.am delete mode 100644 zlib/README delete mode 100644 zlib/adler32.c delete mode 100644 zlib/algorithm.doc delete mode 100644 zlib/compress.c delete mode 100644 zlib/crc32.c delete mode 100644 zlib/deflate.c delete mode 100644 zlib/deflate.h delete mode 100644 zlib/example.c delete mode 100644 zlib/infblock.c delete mode 100644 zlib/infblock.h delete mode 100644 zlib/infcodes.c delete mode 100644 zlib/infcodes.h delete mode 100644 zlib/inffast.c delete mode 100644 zlib/inffast.h delete mode 100644 zlib/inffixed.h delete mode 100644 zlib/inflate.c delete mode 100644 zlib/inftrees.c delete mode 100644 zlib/inftrees.h delete mode 100644 zlib/infutil.c delete mode 100644 zlib/infutil.h delete mode 100644 zlib/trees.c delete mode 100644 zlib/trees.h delete mode 100644 zlib/uncompr.c delete mode 100644 zlib/zconf.h delete mode 100644 zlib/zlib.h delete mode 100644 zlib/zutil.c delete mode 100644 zlib/zutil.h diff --git a/ABOUT-NLS b/ABOUT-NLS deleted file mode 100644 index 5fde45a0b..000000000 --- a/ABOUT-NLS +++ /dev/null @@ -1,324 +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. - - 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 September -2001. 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 bg cs da de el en eo es et fi fr gl he hr id it ja - +----------------------------------------------------+ - a2ps | [] [] [] | - bash | [] [] [] [] | - bfd | | - binutils | [] | - bison | [] [] [] [] [] | - clisp | [] [] [] [] | - cpio | [] [] [] [] [] | - diffutils | [] [] [] [] [] [] [] | - enscript | [] [] | - error | [] [] | - fetchmail | | - fileutils | [] [] [] [] [] [] [] [] | - findutils | [] [] [] [] [] [] [] [] | - flex | [] [] [] | - freetype | | - gas | | - gawk | [] [] | - gcal | | - gcc | | - gettext | [] [] [] [] [] [] [] [] [] [] | - gnupg | [] [] [] [] [] [] [] | - gprof | | - grep | [] [] [] [] [] [] [] [] | - hello | [] [] [] [] [] [] [] [] [] [] [] | - id-utils | [] [] [] | - indent | [] [] [] [] [] | - jpilot | [] | - kbd | | - ld | [] | - libc | [] [] [] [] [] [] [] [] | - lilypond | [] | - lynx | [] [] [] [] | - m4 | [] [] [] [] [] [] [] [] | - make | [] [] [] [] [] [] | - mysecretdiary | [] | - nano | [] [] [] | - opcodes | | - parted | [] [] [] | - ptx | [] [] [] [] [] [] [] | - python | | - recode | [] [] [] [] [] [] [] [] [] | - sed | [] [] [] [] [] [] [] [] [] [] [] [] | - sh-utils | [] [] [] [] [] [] [] [] [] [] | - sharutils | [] [] [] [] [] [] [] [] | - sketch | | - soundtracker | [] [] [] | - sp | | - tar | [] [] [] [] [] [] [] [] | - texinfo | [] [] [] [] [] [] | - textutils | [] [] [] [] [] [] [] [] | - util-linux | [] [] | - wdiff | [] [] [] | - wget | [] [] [] [] [] [] [] [] [] [] | - +----------------------------------------------------+ - bg cs da de el en eo es et fi fr gl he hr id it ja - 0 14 24 32 11 1 8 23 13 1 33 22 4 0 7 9 18 - - ko lv nb nl nn no pl pt pt_BR ru sk sl sv tr uk zh - +----------------------------------------------------+ - a2ps | [] [] [] | 6 - bash | | 4 - bfd | | 0 - binutils | | 1 - bison | [] | 6 - clisp | [] | 5 - cpio | [] [] [] [] [] | 10 - diffutils | [] [] [] [] | 11 - enscript | [] [] [] | 5 - error | [] [] | 4 - fetchmail | | 0 - fileutils | [] [] [] [] [] [] [] [] [] | 17 - findutils | [] [] [] [] [] [] [] [] | 16 - flex | [] [] [] | 6 - freetype | | 0 - gas | | 0 - gawk | [] | 3 - gcal | | 0 - gcc | | 0 - gettext | [] [] [] [] [] [] [] [] | 18 - gnupg | [] [] [] | 10 - gprof | | 0 - grep | [] [] [] [] | 12 - hello | [] [] [] [] [] [] [] [] [] [] [] | 22 - id-utils | [] [] [] | 6 - indent | [] [] [] [] [] [] [] | 12 - jpilot | | 1 - kbd | [] | 1 - ld | | 1 - libc | [] [] [] [] [] [] [] [] | 16 - lilypond | [] [] | 3 - lynx | [] [] [] [] | 8 - m4 | [] [] [] [] | 12 - make | [] [] [] [] [] [] | 12 - mysecretdiary | | 1 - nano | [] | 4 - opcodes | [] | 1 - parted | [] [] | 5 - ptx | [] [] [] [] [] [] [] [] | 15 - python | | 0 - recode | [] [] [] [] | 13 - sed | [] [] [] [] [] [] [] | 19 - sh-utils | [] [] [] [] [] [] [] [] [] [] [] | 21 - sharutils | [] [] [] | 11 - sketch | | 0 - soundtracker | | 3 - sp | | 0 - tar | [] [] [] [] [] [] [] | 15 - texinfo | [] | 7 - textutils | [] [] [] [] [] [] [] [] | 16 - util-linux | [] [] | 4 - wdiff | [] [] [] [] | 7 - wget | [] [] [] [] [] [] [] | 17 - +----------------------------------------------------+ - 33 teams ko lv nb nl nn no pl pt pt_BR ru sk sl sv tr uk zh - 53 domains 9 1 6 20 0 6 17 1 13 25 10 11 23 21 2 2 387 - - 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 September 2001 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 -to 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. - diff --git a/BUGS b/BUGS deleted file mode 100644 index 9cfdcd98e..000000000 --- a/BUGS +++ /dev/null @@ -1,12 +0,0 @@ -Please see - - http://www.gnupg.org/buglist.html - -for a list of know bugs in GnuPG. We don't distribute this list anymore -with the package because a more current one with notes in which version -the bug is fixed can be found online. - -For security related bugs, please contact which -directs mails only to the core developers. If you need to encrypt the -report you should use the public keys of the maintainer and of 2 or 3 -other active developers (consult the ChangeLog and AUTHORS). diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 62ea076c1..000000000 --- a/INSTALL +++ /dev/null @@ -1,231 +0,0 @@ -Copyright 1994, 1995, 1996, 1999, 2000, 2001 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 variables by setting -them in the environment. You can do that on the command line like this: - - ./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 host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it cannot guess the host 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 host 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'. In this case, you should also specify the -build platform with `--build=TYPE', because, in this case, it may not -be possible to guess the build platform (it sometimes involves -compiling and running simple test programs, and this can't be done if -the compiler is a cross compiler). - -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. - diff --git a/NOTES b/NOTES deleted file mode 100644 index 346dfa9fb..000000000 --- a/NOTES +++ /dev/null @@ -1,46 +0,0 @@ -Checking ElGamal signatures is really slow and the reason for the long -running time on parts o my keyring. Because somekeys are also checked at startup, this is even worser. I should invalidate my self signature with algo 16 or 20. - - -SCO UnixWare/7.1.0 reported by Allan Clark for 0.9.8 - - -Some other reported cpu-vendor-os strings: - - hppa1.1-hp-hpux10.20 - mips-sgi-irix6.2 - sparc-sun-solaris5.4 - sparc-sun-sunos4.1.2 - i386-pc-sysv4.2 (USL Unixware v1.1.2) - powerpc-ibm-aix4.3.2.0 John Payne - -gpg 1.0.1 okay with MP-RAS 3.02.01 Edition 5 using gcc 2.95.2 and EGD - By - -gpg 1.0.1 okay with 4.0.1 BSDI BSD/OS 4.0 i386 - - -rndw32 tested on: - - Windows 98 4.10.1998 mit einem AMD-K6-2-450 - Michael Engels ) - - Windows 95 4.00.950a - - Windows NT 4.00.1381 - - - - -tried to compile GnuPG on AIX 4.3 on a power CPU based machine. It -doesn't work out of the box but i found a way to do so: - - PowerPC based machines: - CFLAGS="-g -O2 -mcpu=powerpc" ./configure --disable-asm --disable-dynload -+--enable-static-rnd=egd - - Power1 and Power2 machines: - CFLAGS="-g -O2 -mcpu=power" ./configure --disable-asm --disable-dynload -+--enable-static-rnd=egd - - diff --git a/OBUGS b/OBUGS deleted file mode 100644 index 226514e00..000000000 --- a/OBUGS +++ /dev/null @@ -1,102 +0,0 @@ - List of fixed bugs - -------------------- - -(format: severity: [ *] to [***], no, first reported, by, version) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -[ *] #1 - pgp263in works fine even with a source file with CR,LF but GnuPG - and pgp263in has problems if the clearsign has been created by - pgp263ia. The reason for this problem is that pgp2 sometimes - converts CR,LF to CR,CR,LF and to fix for this it hashes both - versions. I was able to reproduce such a problem, that PGP263in - was not able to verify it's own signature. - FIX: 1999-05-19 (Most cases are now handled) - -[***] #2 1999-02-21 - Problem while importing or deleting public keys in 0.9.3 - 0.9.2 - worked fine. Error message: - gpg:[stdin]: key A6A59DB9: secret key not found: public key not found - FIX: 1999-02-22 wk - -[ *] #5 - /home/jam/.gnupg/pubring.gpg: can't open gdbm file: Can't be writer - keyblock resource `/home/jam/.gnupg/pubring.gpg': file open error - OOPS in close enum_keyblocks - ignored - [gdbm is experimental and will be replaced by the new keybox code] - FIX: 1999-07-22 (Fixed the second error, there will be no fix for - the first one, because GDBM is to be replaced) - -[ *] #7 1999-02-22 0.9.3 - Conventional encryption incompatibility: - $ gpg -c --cipher-algo cast5 --compress-algo 1 --no-comment secrets.txt - Creates a file that gpg can decrypt, but PGP 5.5 has problems with it. - PGP decrypts 6416k out of 6424k, then complains with "PGP Warning", - "The keyring contains a bad (corrupted) PGP packet". The resulting - file is missing information from the front. - FIX: 1999-02-26 temporary fix in encrypt_simple() - - -[ *] #8 1999-02-25 0.9.3 - %gpg --encrypt -r kazu@iijlab.net --batch foo - gpg: Warning: using insecure memory! - gpg: 11C23F61: no info to calculate a trust probability - This creates a symmetrically encrypted message WITHOUT a session key - encrypted with public cryptographic(i.e. foo.gpg). This is probably - FIX: 199-02-26 wk - -[ **] #9 1999-02-25 - Misalignment in md5.c#md5_write. - FIX: 1999-02-26 wk - -[ **] #10 1999-03-01 - Armor detection code is broken. Direct import of keyrings is not possible. - FIX: 1999-03-02 wk - -[***] #11 1999-02-25 - "cipher algo 10 not found". - FIX: 1999-02-25 wk - -[ **] #12 1999-03-10 - gpg --list-secret-keys --with-colon SEGVs - FIX: 1999-03-10 - -[ *] #13 1999-04-05 - Trying to generate very large keys fails with a BUG in read_pool() - FIX: 1999-04-06 - - -[ *] #14 1999-04-05 - If you use --s2k-cipher-algo twofish, the the program crashes with - a BUG at line 226 of passphrase.c. - FIX: 1999-04-06 - - -[ **] #15 1999-04-05 - Hash calculation for subkey bindings is not according to rfc2440 if - a 4 byte length header is used for the subkey. - FIX: 1999-04-06 - -[***] #16 1999-03-23 - Verifying detached signatures with an empty file yields a rc of 0. - FIX: 1999-05-06 - -[ **] #17 1999-05-18 0.9.6 - Import does not detect identical user IDs. - FIX: 1999-05-22 - -[ **] #19 1999-06-11 - "trustdb transaction too large" with about 500 signatures on a key - FAEBD5FC. - FIX: 1999-07-12 (less memory requirement and increased the limit) - -[ **] #20 1999-06-16 0.9.7 - Using "addkey" in the edit menu with more than 1 subkey leads to - "out of secure memory" in some cases. - FIX: 1999-06-17 (Twofish uses too much memory and the memory - becomes fragmented - workaround is using CAST5 to protect passphrases) - -[ *] #21 1999-06-17 - Ctrl-D does not work correct for messages entered at the tty. - FIX: 1999-06-18 (Better EOF detection on terminals) - diff --git a/PROJECTS b/PROJECTS deleted file mode 100644 index d6725f7a9..000000000 --- a/PROJECTS +++ /dev/null @@ -1,46 +0,0 @@ - - * Change the internal representation of keyid into a struct which - can also hold the localid and extend the localid to hold information - of the subkey number because two subkeys may have the same keyid. - - * Add a way to override the current cipher/md implementations - by others (using extensions) - - * Not GnuPG related: What about option completion in bash? - Can "--dump-options" be used for this or should we place the - options in an ELF note section? - - * Split key support (n-out-of-m). Use our own protocol or figure out - how PGP does it. - - * add an option to re-create a public key from a secret key; we - can do this in trustdb.c:verify_own_keys. (special tool?) - Hmmm, we better drop the duplication of the public part and just keep - the secrets in the "secring" - this has the additional that we can - put those secrets on a hardware token. - - * write a tool to extract selected keys from a file. - - * Change the buffering to a mbuf like scheme? See Michael's proposal. - - * Keep a list of duplicate, faked or unwanted keyids. - - * The current code has knowledge about the structure of a keyblock. - We should add an abstraction layer so that adding support for - different certificate structures will become easier. - - * "Michael T. Babcock" suggested to write - an event log so that other software can display a key history or - alike with GnuPG results. This should be connected to the keyrings. - - - - Copyright 1998, 1999, 2000, 2001 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. diff --git a/THOUGHTS b/THOUGHTS deleted file mode 100644 index 25707c447..000000000 --- a/THOUGHTS +++ /dev/null @@ -1,275 +0,0 @@ -How often have we to do a key lookup by mailaddress?. -can this be accomplished by an external program? - - - -What about using S-Exp to describe the interface to the ciphers instead -of simply iterating over them. This way we can easy register a name which -can be used as the "hintstr" for --load-extension. - -EGD -==== -Oh, and on embedding egd into the gpg package: I think if you just unpack it -into, say, util/egd/* then you can put something like this into configure.in: - -AC_CHECK_PROG(perl_present, perl, true, false) -if $perl_present; then - AC_PATH_PROG(PERL, perl) - (cd util/egd; $PERL Makefile.PL FULLPERL=$PERL INSTALLBIN=$sbindir) -fi -AM_CONDITIONAL(WITH_EGD, $perl_present) - -and add util/egd to the top-level Makefile directory list inside a WITH_EGD -conditional. - - * What shall we do if we have a valid subkey revocation certificate - but no subkey binding? Is this a valid but revoked key? - - * use a mmaped file for secure memory if mlock does not work and - make sure that this file is always wiped out. Is this really - more secure than swapping out to the swap disk? I don't - believe so because if an attacker has access to the physical - box (and he needs this to look at the swap area) he can also - leave a Trojan horse which is far more easier than to analyze - memory dumps. Question: Is it possible that a Unix pages - an old (left over by some other process) swap page in for - another process - this should be considered a serious design - flow/bug. - -Date: Mon, 4 Jan 1999 19:34:29 -0800 (PST) -From: Matthew Skala - -- Signing with an expired key doesn't work by default, does work with a - special option. -- Verifying a signature that appears to have been made by an expired key - after its expiry date but is otherwise good reports the signature as BAD, - preferably with a message indicating that it's a key-expiry problem rather - than a cryptographically bad signature. -- Verifying a signature from a key that is now expired, where the - signature was made before the expiry date, reports the signature as - GOOD, possibly with a warning that the key has since expired. -- Encrypting to an expired key doesn't work by default, does work with a - special option. -- Decrypting always works, if you have the appropriate secret key and - passphrase. - - - -============================== -[ "-->" indicates a comment by me (wk) ] - -Hi Werner.. - -I was looking at some of the PROJECTS items in the recent gpg CVS and wanted -to comment on one of them: - - * Add a way to override the current cipher/md implementations - by others (using extensions) - -As you know I've been thinking about how to use a PalmPilot or an iButton in -some useful way in GPG. The two things that seem reasonable are: - 1) keep the secret key in the device, only transferring it to the host - computer for the duration of the secret-key operation (sign or decrypt). - The key is never kept on disk, only in RAM. This removes the chance that - casual snooping on your office workstation will reveal your key (it - doesn't help against an active attack, but the attacker must leave a - tampered version of GPG around or otherwise get their code to run while - the key-storage device is attached to attack the key) - 2) perform the secret-key operation on the device, so the secret key never - leaves the confines of that device. There are still attacks possible, - based upon talking to the device while it is connected and trying to - convince the device (and possibly the user) that it is the real GPG, - but in general this protects the key pretty strongly. Any individual - message is still vulnerable, but that's a tradeoff of the convenience of - composing that message on a full-sized screen+keyboard (plus the added - speed of encryption) vs. the security of writing the message on a - secure device. - -I think there are a variety of ways of implementing these things, but a few -extension mechanisms in GPG should be enough to try various ways later on. - -1) pass an argument string to loadable extension modules (maybe - gpg --load-extension foofish=arg1,arg2,arg3 ?) - --> could also be achived by S-Exps - -2) allow multiple instances of the same extension module (presumably with - different arguments) - --> set an alias name when loading them -3) allow extension modules to use stdin/stdout/stderr as normal (probably - already in there), for giving feedback to the user, or possibly asking them - for a password of some sort - --> there should really be some kind of callback mechanism. - -4) have an extension to provide secret keys: - - It looks like most of the hooks for this are already in place, it just - needs an extension module which can register itself as a keyblock resource. - - I'm thinking of a module for this that is given an external program name as - an argument. When the keyblock resource is asked to enumerate its keys, it - runs the external program (first with a "0" argument, then a "1", and so on - until the program reports that no more keys are available). The external ---> better use a cookie: This way we are also stateless but have a more - general interface. - - program returns one (possibly armored) secret key block each time. The - program might have some kind of special protocol to talk to the storage - device. One thing that comes to mind is to simply include a random number - in the message sent over the serial port: the program would display this - number, the Pilot at the other end would display the number it receives, if - the user sees that both are the same they instruct the Pilot to release the - key, as basic protection against someone else asking for the key while it - is attached. More sophisticated schemes are possible depending upon how - much processing power and IO is available on the device. But the same - extension module should be able to handle as complex a scheme as one could - wish. - --> authenticate the session on startup, using DH and the mentioned - cookie/screen/keyboard authentication. - - The current keyblock-resource interface would work fine, although it - might be more convenient if a resource could be asked for a key by id - instead of enumerating all of them and then searching through the resulting - list for a match. A module that provided public keys would have to work this - way (imagine a module that could automatically do an http fetch for a - particular key.. easily-added automatic key fetching). Without that ability - to fetch by id (which would require it to fall back to the other keyblock - resources if it failed), the user's device might be asked to release the - key even though some other secret key was the one needed. - --> Right. - - -5) have an extension to perform a secret-key operation without the actual - secret key material - --> Define a clear interface to do this and in the first step write - a daemon which does exactly this. - - basically something to indicate that any decrypt or sign operations that - occur for a specific keyid should call the extension module instead. The - secret key would not be extracted (it wouldn't be available anyway). The - module is given the keyid and the MPI of the block it is supposed to sign - or decrypt. - - The module could then run an external program to do the operation. I'm - imagining a Pilot program which receives the data, asks the user if it can go - along with the operation (after displaying a hash of the request, which is - also displayed by the extension module's program to make sure the Pilot is - being asked to do the right operation), performs the signature or decryption, - then returns the data. This protocol could be made arbitrarily complex, with - a D-H key to encrypt the link, and both sides signing requests to - authenticate one to the other (although this transforms the the problem of - getting your secret key off your office workstation into the problem of - your workstation holding a key tells your Pilot that it is allowed to perform - the secret key operation, and if someone gets a hold of that key they may - be able to trick your pilot [plugged in somewhere else] to do the same thing - for them). - - This is basically red/black separation, with the Pilot or iButton having the - perimeter beyond which the red data doesn't pass. Better than the secret-key - storage device but requires a lot more power on the device (the new iButtons - with the exponentiator could do it, but it would take way too much code space - on the old ones, although they would be fine for just carrying the keys). - -The signature code might need to be extended to verify the signature you just -made, since an active intruder pretending to the the Pilot wouldn't be able to -make a valid signature (but they might sign your message with a different key -just to be annoying). - -Anyway, just wanted to share my thoughts on some possibilities. I've been -carrying this little Java iButton on my keyring for months now, looking for -something cool to do with it, and I think that secure storage for my GPG key -would be just the right application. - -cheers, - -Brian - ------BEGIN PGP SIGNATURE----- -Version: GnuPG v0.4.5 (GNU/Linux) -Comment: For info finger gcrypt@ftp.guug.de - -iD8DBQE2c5oZkDmgv9E5zEwRArAwAKDWV5fpTtbGPiMPgl2Bpp0gvhbfQgCgzJuY -AmIQTk4s62/y2zMAHDdOzK0= -=jr7m ------END PGP SIGNATURE----- - - - -About a new Keyserver (discussion with Allan Clark ): -===================== - -Some ideas: - -o the KS should verify signatures and only accept those - which are good. - -o Keep a blacklist of known bad signatures to minimize - the time needed to check them - -o Should be fast - I'm currently designing a new storage - system called keybox which takes advantage of the fact - that the keyID is highly random and can directly be - used as a hash value and this keyID is (for v4 keys) - part of the fingerprint: So it is possible to use the - fingerprint as key but do an lookup by the keyID. - -o To be used as the "public keyring" in a LAN so that there - is no need to keep one on every machine. - -o Allow more that one file for key storage. - -o Use the HKS protocol and enhance it in a way that binary - keyrings can be transmitted. (I already wrote some - http server and client code which can be used for this) - And extend it to allow reuse of a connection. - -o Keep a checksum (hash) of the entire keyblock so that a - client can easy check whether this keyblock has changed. - (keyblock = the entire key with all certificates etc.) - Transmitted in the HEAD info. - -o Allow efficient propagation of new keys and revocation - certificates. - - -Probably more things but this keyserver is not a goal for the -1.0 release. Someone should be able to fix some of the limitations -of the existing key servers (I think they bail out on some rfc2440 -packet formats). - - -DJGPP -===== -Don't use symlinks but try to do the preprocessing in the config-links script. -DJPGG has problems to distinguish betwen .s and .S becaus the FAT filesystem -is not case sensitive (Mark Elbrecht). -Well, it runs only on one architecture and therefor it might be possible -to add a special case for it, completely bypassing the symlink autselection -trick. - -Special procmail addresses -========================== - * foo+bar@example.net: Try to match the address without the "+bar". - Should be done by the MUA, but maybe we can do this. - --> Yep. Another reason to utilize a directory service or something - else for keylookup. - - - -Suggested things which I will not do: -===================================== - * Let take --help an option to select some topics. - Using grep is much easier - * Check if an object (a message, detached sign, public key, or whatever) - is signed by definite user, i.e. define user - (userid, or any other unique identification) on command line. - --> Use a script and --status-fd - - - Copyright 1998, 1999, 2000, 2001 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. diff --git a/agent/ChangeLog b/agent/ChangeLog deleted file mode 100644 index c19193b23..000000000 --- a/agent/ChangeLog +++ /dev/null @@ -1,419 +0,0 @@ -2002-09-25 Werner Koch - - * gpg-agent.c (handle_signal): Flush cache on SIGHUP. - * cache.c (agent_flush_cache): New. - - * gpg-agent.c, agent.h: Add --keep-display and --keep-tty. - * query.c (start_pinentry): Implement them. The option passing - needs more thoughts. - -2002-09-09 Werner Koch - - * gpg-agent.c (create_private_keys_directory) - (create_directories): New. - (main): Try to create a home directory. - -2002-09-04 Neal H. Walfield - - * gpg-agent.c (main): Use sigaction, not signal. - -2002-09-03 Neal H. Walfield - - * findkey.c: Include . - (agent_write_private_key): Prefer POSIX compatibity, open and - fdopen, over the simplicity of GNU extensions, fopen(file, "x"). - -2002-08-22 Werner Koch - - * query.c (agent_askpin): Provide the default desc text depending - on the pininfo. Do the basic PIN verification only when - min_digits is set. - -2002-08-21 Werner Koch - - * query.c (agent_askpin): Hack to show the right default prompt. - (agent_get_passphrase): Ditto. - - * trans.c: Removed and replaced all usages with standard _() - - * divert-scd.c (getpin_cb): Pass a more descritive text to the - pinentry. - - * Makefile.am: Renamed the binary protect-tool to gpg-protect-tool. - * protect-tool.c: Removed the note about internal use only. - - * gpg-agent.c (main): New option --daemon so that the program is - not accidently started in the background. - -2002-08-16 Werner Koch - - * call-scd.c (learn_status_cb): Handle CERTINFO status. - (agent_card_learn): Add args for certinfo cb. - * learncard.c (release_certinfo,certinfo_cb): New. - (send_cert_back): New. With factored out code from .. - (agent_handle_learn): here. Return certinfo stuff. - -2002-07-26 Werner Koch - - * gpg-agent.c (main): New option --ignore-cache-for-signing. - * command.c (option_handler): New server option - use-cache-for-signing defaulting to true. - (cmd_pksign): handle global and per session option. - * findkey.c (agent_key_from_file, unprotect): New arg - ignore_cache. Changed all callers. - * pksign.c (agent_pksign): Likewise. - -2002-06-29 Werner Koch - - * query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY. - * call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON. - -2002-06-28 Werner Koch - - * protect-tool.c (export_p12_file): New. - (main): New command --p12-export. - * minip12.c (create_final,p12_build,compute_tag_length): New. - (store_tag_length): New. - -2002-06-27 Werner Koch - - * minip12.c (crypt_block): Renamed from decrypt_block, add arg to - allow encryption. - - * Makefile.am (pkglib_PROGRAMS): Put protect-tool there. - - * findkey.c (agent_write_private_key,agent_key_from_file) - (agent_key_available): Use GNUPG_PRIVATE_KEYS_DIR constant. - * gpg-agent.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. - - * protect-tool.c (store_private_key): New. - (import_p12_file): Store the new file if requested. - (main): New options --force and --store. - - * gpg-agent.c (main): Set a global flag when running detached. - * query.c (start_pinentry): Pass the list of FD to keep in the - child when not running detached. - * call-scd.c (start_scd): Ditto. - -2002-06-26 Werner Koch - - * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted) - (cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_get_passphrase) - (cmd_learn): Print an error message for a failed operation. - - * simple-pwquery.c, simple-pwquery.h: New. - * protect-tool. (get_passphrase): New, used to get a passphrase - from the agent if none was given on the command line. - -2002-06-25 Werner Koch - - * protect-tool.c (rsa_key_check): New. - (import_p12_file): New. - (main): New command --p12-import. - * minip12.c, minip12.h: New. - -2002-06-24 Werner Koch - - * protect-tool.c (read_file): New. - (read_key): Factored most code out to read_file. - -2002-06-17 Werner Koch - - * agent.h: Add a callback function to the pin_entry_info structure. - * query.c (agent_askpin): Use the callback to check for a correct - PIN. Removed the start_err_text argument because it is not - anymore needed; changed callers. - * findkey.c (unprotect): Replace our own check loop by a callback. - (try_unprotect_cb): New. - * genkey.c (reenter_compare_cb): New. - (agent_genkey): Use this callback here. Fixed setting of the pi2 - variable and a segv in case of an empty PIN. - - * divert-scd.c (getpin_cb): Removed some unused stuff and - explained what we still have to change. - -2002-06-12 Werner Koch - - * gpg-agent.c (main): New option --disable-pth. - -2002-06-11 Werner Koch - - * protect-tool.c: Add command --show-keygrip - (show_keygrip): New. - -2002-05-23 Werner Koch - - * call-scd.c: Seirialized all scdaeom access when using Pth. - - * cache.c: Made the cache Pth-thread-safe. - (agent_unlock_cache_entry): New. - * findkey.c (unprotect): Unlock the returned cache value. - * command.c (cmd_get_passphrase): Ditto. - - * gpg-agent.c (main): Register pth_read/write with Assuan. - -2002-05-22 Werner Koch - - * query.c: Serialized all pinentry access when using Pth. - - * gpg-agent.c (handle_signal,start_connection_thread) - (handle_connections): New - (main): Use the new Pth stuff to allow concurrent connections. - * command.c (start_command_handler): Add new arg FD so that the - fucntion can also be used for an already connected socket. - * Makefile.am: Link with Pth. - -2002-05-14 Werner Koch - - * cache.c (housekeeping, agent_put_cache): Use our time() wrapper. - -2002-04-26 Werner Koch - - * cache.c (agent_put_cache): Reinitialize the creation time and - the ttl when reusing a slot. - - * call-scd.c (start_scd): Print debug messages only with debug - flags set. - * query.c (start_pinentry): Ditto. - -2002-04-25 Marcus Brinkmann - - * agent.h (agent_get_confirmation): Replace paramter prompt with - two parameters ok and cancel. - * query.c (agent_get_confirmation): Likewise. Implement this. - * trustlist.c (agent_marktrusted): Fix invocation of - agent_get_confirmation. - * divert-scd.c (ask_for_card): Likewise. - -2002-04-24 Marcus Brinkmann - - * agent.h (struct opt): Add members display, ttyname, ttytype, - lc_ctype, and lc_messages. - * gpg-agent.c (enum cmd_and_opt_values): Add oDisplay, oTTYname, - oTTYtype, oLCctype, and LCmessages. - (main): Handle these options. - * command.c (option_handler): New function. - (register_commands): Register option handler. - * query.c (start_pinentry): Pass the various display and tty - options to the pinentry. - -2002-04-05 Werner Koch - - * protect-tool.c (show_file): New. Used as default action. - -2002-03-28 Werner Koch - - * divert-scd.c (encode_md_for_card): Don't do the pkcs-1 padding, - the scdaemon should take care of it. - (ask_for_card): Hack to not display the trailing zero. - -2002-03-11 Werner Koch - - * learncard.c (kpinfo_cb): Remove the content restrictions from - the keyID. - -2002-03-06 Werner Koch - - * learncard.c: New. - * divert-scd.c (ask_for_card): The serial number is binary so - convert it to hex here. - * findkey.c (agent_write_private_key): New. - * genkey.c (store_key): And use it here. - - * pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done. - * divert-scd.c (divert_pkdecrypt): Changed interface and - implemented it. - -2002-03-05 Werner Koch - - * call-scd.c (inq_needpin): New. - (agent_card_pksign): Add getpin_cb args. - (agent_card_pkdecrypt): New. - -2002-03-04 Werner Koch - - * pksign.c (agent_pksign): Changed how the diversion is done. - * divert-scd.c (divert_pksign): Changed interface and implemented it. - (encode_md_for_card): New. - * call-scd.c (agent_card_pksign): New. - -2002-02-28 Werner Koch - - * pksign.c (agent_pksign): Detect whether a Smartcard is to be - used and divert the operation in this case. - * pkdecrypt.c (agent_pkdecrypt): Likewise - * findkey.c (agent_key_from_file): Add optional arg shadow_info - and have it return information about a shadowed key. - * protect.c (agent_get_shadow_info): New. - - * protect.c (snext,sskip,smatch): Moved to - * sexp-parse.h: new file. - * divert-scd.c: New. - -2002-02-27 Werner Koch - - * protect.c (agent_shadow_key): New. - - * command.c (cmd_learn): New command LEARN. - * gpg-agent.c: New option --scdaemon-program. - * call-scd.c (start_scd): New. Based on query.c - * query.c: Add 2 more arguments to all uses of assuan_transact. - -2002-02-18 Werner Koch - - * findkey.c (unprotect): Show an error message for a bad passphrase. - - * command.c (cmd_marktrusted): Implemented. - * trustlist.c (agent_marktrusted): New. - (open_list): Add APPEND arg. - - * query.c (agent_get_confirmation): New. - -2002-02-06 Werner Koch - - * cache.c (housekeeping): Fixed linking in the remove case. - -2002-02-01 Werner Koch - - * gpg-agent.c: New option --default-cache-ttl. - * cache.c (agent_put_cache): Use it. - - * cache.c: Add a few debug outputs. - - * protect.c (agent_private_key_type): New. - * agent.h: Add PRIVATE_KEY_ enums. - * findkey.c (agent_key_from_file): Use it to decide whether we - have to unprotect a key. - (unprotect): Cache the passphrase. - - * findkey.c (agent_key_from_file,agent_key_available): The key - files do now require a ".key" suffix to make a script's life - easier. - * genkey.c (store_key): Ditto. - -2002-01-31 Werner Koch - - * genkey.c (store_key): Protect the key. - (agent_genkey): Ask for the passphrase. - * findkey.c (unprotect): Actually unprotect the key. - * query.c (agent_askpin): Add an optional start_err_text. - -2002-01-30 Werner Koch - - * protect.c: New. - (hash_passphrase): Based on the GnuPG 1.0.6 version. - * protect-tool.c: New - -2002-01-29 Werner Koch - - * findkey.c (agent_key_available): New. - * command.c (cmd_havekey): New. - (register_commands): And register new command. - -2002-01-20 Werner Koch - - * command.c (cmd_get_passphrase): Remove the plus signs. - - * query.c (start_pinentry): Send no-grab option to pinentry - * gpg-agent.c (main): Move variable grab as no_grab to agent.h. - -2002-01-19 Werner Koch - - * gpg-agent.c (main): Disable core dumps. - - * cache.c: New. - * command.c (cmd_get_passphrase): Use the cache. - (cmd_clear_passphrase): Ditto. - - * gpg-agent.c: Removed unused cruft and implement the socket - based server. - (my_strusage): Take bug report address from configure.ac. - * command.c (start_command_handler): Add an argument to start as - regular server. - (start_command_handler): Enable Assuan logging. - -2002-01-15 Werner Koch - - * trustlist.c: New. - * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New. - -2002-01-07 Werner Koch - - * genkey.c: Store the secret part and return the public part. - -2002-01-03 Werner Koch - - * command.c (cmd_get_passphrase): New. - (cmd_clear_passphrase): New. - * query.c (agent_get_passphrase): New. - -2002-01-02 Werner Koch - - * genkey.c: New. - * command.c (cmd_genkey): New. - - * command.c (rc_to_assuan_status): Removed and changed all callers - to use map_to_assuan_status. - -2001-12-19 Werner Koch - - * keyformat.txt: New. - -2001-12-19 Marcus Brinkmann - - * query.c (start_pinentry): Add new argument to assuan_pipe_connect. - -2001-12-18 Werner Koch - - * Makefile.am: Use LIBGCRYPT macros - -2001-12-14 Werner Koch - - * gpg-agent.c (main): New option --batch. New option --debug-wait - n, so that it is possible to attach gdb when used in server mode. - * query.c (agent_askpin): Don't ask in batch mode. - - * command.c: Removed the conversion macros as they are now in - ../common/util.h. - -2001-12-14 Marcus Brinkmann - - * query.c (LINELENGTH): Removed. - (agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH. - -2001-11-19 Werner Koch - - * gpg-agent.c: Removed all GUI code, removed code for old - protocol. New code to use the Assuan protocol as a server and - also to communicate with a new ask-passphrase utility. - -2000-11-22 Werner Koch - - * gpg-agent.c (main): csh support by Dan Winship, new options --sh - and --csh and set default by consulting $SHELL. - -Mon Aug 21 17:59:17 CEST 2000 Werner Koch - - * gpg-agent.c (passphrase_dialog): Cleanup the window and added the - user supplied text to the window. - (main): Fixed segv in gtk_init when used without a command to start. - - * gpg-agent.c: --flush option. - (req_flush): New. - (req_clear_passphrase): Implemented. - -Fri Aug 18 14:27:14 CEST 2000 Werner Koch - - * gpg-agent.c: New. - * Makefile.am: 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. diff --git a/agent/Makefile.am b/agent/Makefile.am deleted file mode 100644 index 89000cf35..000000000 --- a/agent/Makefile.am +++ /dev/null @@ -1,62 +0,0 @@ -# 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 - -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - -bin_PROGRAMS = gpg-agent -pkglib_PROGRAMS = gpg-protect-tool - -AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS) $(PTH_CFLAGS) -LDFLAGS = @LDFLAGS@ - -gpg_agent_SOURCES = \ - gpg-agent.c agent.h \ - command.c \ - query.c \ - cache.c \ - trans.c \ - findkey.c \ - pksign.c \ - pkdecrypt.c \ - genkey.c \ - protect.c \ - trustlist.c \ - divert-scd.c \ - call-scd.c \ - learncard.c \ - sexp-parse.h - - -gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \ - ../common/libcommon.a $(LIBGCRYPT_LIBS) $(PTH_LIBS) - -gpg_protect_tool_SOURCES = \ - protect-tool.c \ - protect.c \ - minip12.c minip12.h \ - simple-pwquery.c simple-pwquery.h - -gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \ - ../common/libcommon.a $(LIBGCRYPT_LIBS) - - - - diff --git a/agent/agent.h b/agent/agent.h deleted file mode 100644 index 24267b06a..000000000 --- a/agent/agent.h +++ /dev/null @@ -1,197 +0,0 @@ -/* agent.h - Global definitions for the agent - * 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 AGENT_H -#define AGENT_H - -#include -#include "../common/util.h" -#include "../common/errors.h" - -#define MAX_DIGEST_LEN 24 - -/* A large struct name "opt" to keep global flags */ -struct { - unsigned int debug; /* debug flags (DBG_foo_VALUE) */ - int verbose; /* verbosity level */ - int quiet; /* be as quiet as possible */ - int dry_run; /* don't change any persistent data */ - int batch; /* batch mode */ - const char *homedir; /* configuration directory name */ - const char *pinentry_program; - char *display; - char *ttyname; - char *ttytype; - char *lc_ctype; - char *lc_messages; - const char *scdaemon_program; - int no_grab; /* don't let the pinentry grab the keyboard */ - unsigned long def_cache_ttl; - - int running_detached; /* we are running detached from the tty. */ - - int ignore_cache_for_signing; - int keep_tty; /* don't switch the TTY (for pinentry) on request */ - int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ -} opt; - - -#define DBG_COMMAND_VALUE 1 /* debug commands i/o */ -#define DBG_MPI_VALUE 2 /* debug mpi details */ -#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ -#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ -#define DBG_CACHE_VALUE 64 /* debug the caching */ -#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ -#define DBG_HASHING_VALUE 512 /* debug hashing operations */ -#define DBG_ASSUAN_VALUE 1024 - -#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE) -#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) -#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) -#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) -#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) -#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) - -struct server_local_s; - -struct server_control_s { - struct server_local_s *server_local; - struct { - int algo; - unsigned char value[MAX_DIGEST_LEN]; - int valuelen; - } digest; - char keygrip[20]; - int have_keygrip; - -}; -typedef struct server_control_s *CTRL; - - -struct pin_entry_info_s { - int min_digits; /* min. number of digits required or 0 for freeform entry */ - int max_digits; /* max. number of allowed digits allowed*/ - int max_tries; - int failed_tries; - int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */ - void *check_cb_arg; /* optional argument which might be of use in the CB */ - const char *cb_errtext; /* used by the cb to displaye a specific error */ - size_t max_length; /* allocated length of the buffer */ - char pin[1]; -}; - - -enum { - PRIVATE_KEY_UNKNOWN = 0, - PRIVATE_KEY_CLEAR = 1, - PRIVATE_KEY_PROTECTED = 2, - PRIVATE_KEY_SHADOWED = 3 -}; - -/*-- gpg-agent.c --*/ -void agent_exit (int rc); /* also implemented in other tools */ - -/*-- command.c --*/ -void start_command_handler (int, int); - -/*-- findkey.c --*/ -int agent_write_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force); -GCRY_SEXP agent_key_from_file (const unsigned char *grip, - unsigned char **shadow_info, int ignore_cache); -int agent_key_available (const unsigned char *grip); - -/*-- query.c --*/ -int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo); -int agent_get_passphrase (char **retpass, - const char *desc, const char *prompt, - const char *errtext); -int agent_get_confirmation (const char *desc, const char *ok, - const char *cancel); - -/*-- cache.c --*/ -void agent_flush_cache (void); -int agent_put_cache (const char *key, const char *data, int ttl); -const char *agent_get_cache (const char *key, void **cache_id); -void agent_unlock_cache_entry (void **cache_id); - - -/*-- pksign.c --*/ -int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache); - -/*-- pkdecrypt.c --*/ -int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, - FILE *outfp); - -/*-- genkey.c --*/ -int agent_genkey (CTRL ctrl, - const char *keyparam, size_t keyparmlen, FILE *outfp); - -/*-- protect.c --*/ -int agent_protect (const unsigned char *plainkey, const char *passphrase, - unsigned char **result, size_t *resultlen); -int agent_unprotect (const unsigned char *protectedkey, const char *passphrase, - unsigned char **result, size_t *resultlen); -int agent_private_key_type (const unsigned char *privatekey); -int agent_shadow_key (const unsigned char *pubkey, - const unsigned char *shadow_info, - unsigned char **result); -int agent_get_shadow_info (const unsigned char *shadowkey, - unsigned char const **shadow_info); - - -/*-- trustlist.c --*/ -int agent_istrusted (const char *fpr); -int agent_listtrusted (void *assuan_context); -int agent_marktrusted (const char *name, const char *fpr, int flag); - - -/*-- divert-scd.c --*/ -int divert_pksign (const unsigned char *digest, size_t digestlen, int algo, - const unsigned char *shadow_info, unsigned char **r_sig); -int divert_pkdecrypt (const unsigned char *cipher, - const unsigned char *shadow_info, - char **r_buf, size_t *r_len); - -/*-- call-scd.c --*/ -int agent_card_learn (void (*kpinfo_cb)(void*, const char *), - void *kpinfo_cb_arg, - void (*certinfo_cb)(void*, const char *), - void *certinfo_cb_arg); -int agent_card_serialno (char **r_serialno); -int agent_card_pksign (const char *keyid, - int (*getpin_cb)(void *, const char *, char*, size_t), - void *getpin_cb_arg, - const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen); -int agent_card_pkdecrypt (const char *keyid, - int (*getpin_cb)(void *, const char *, char*,size_t), - void *getpin_cb_arg, - const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen); -int agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen); -int agent_card_readkey (const char *id, unsigned char **r_buf); - - -/*-- learncard.c --*/ -int agent_handle_learn (void *assuan_context); - - -#endif /*AGENT_H*/ diff --git a/agent/cache.c b/agent/cache.c deleted file mode 100644 index 8f5bf9d3d..000000000 --- a/agent/cache.c +++ /dev/null @@ -1,314 +0,0 @@ -/* cache.c - keep a cache of passphrases - * 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 - */ - -#include - -#include -#include -#include -#include -#include - -#include "agent.h" - -struct secret_data_s { - int totallen; /* this includes the padding */ - int datalen; /* actual data length */ - char data[1]; -}; - -typedef struct cache_item_s *ITEM; -struct cache_item_s { - ITEM next; - time_t created; - time_t accessed; - int ttl; /* max. lifetime given in seonds */ - int lockcount; - struct secret_data_s *pw; - char key[1]; -}; - - -static ITEM thecache; - - -static void -release_data (struct secret_data_s *data) -{ - xfree (data); -} - -static struct secret_data_s * -new_data (const void *data, size_t length) -{ - struct secret_data_s *d; - int total; - - /* we pad the data to 32 bytes so that it get more complicated - finding something out by watching allocation patterns. This is - usally not possible but we better assume nothing about our - secure storage provider*/ - total = length + 32 - (length % 32); - - d = gcry_malloc_secure (sizeof d + total - 1); - if (d) - { - d->totallen = total; - d->datalen = length; - memcpy (d->data, data, length); - } - return d; -} - - -/* check whether there are items to expire */ -static void -housekeeping (void) -{ - ITEM r, rprev; - time_t current = gnupg_get_time (); - - /* first expire the actual data */ - for (r=thecache; r; r = r->next) - { - if (!r->lockcount && r->pw && r->accessed + r->ttl < current) - { - if (DBG_CACHE) - log_debug (" expired `%s' (%ds after last access)\n", - r->key, r->ttl); - release_data (r->pw); - r->pw = NULL; - r->accessed = current; - } - } - - /* second, make sure that we also remove them based on the created stamp so - that the user has to enter it from time to time. We do this every hour */ - for (r=thecache; r; r = r->next) - { - if (!r->lockcount && r->pw && r->created + 60*60 < current) - { - if (DBG_CACHE) - log_debug (" expired `%s' (1h after creation)\n", r->key); - release_data (r->pw); - r->pw = NULL; - r->accessed = current; - } - } - - /* third, make sure that we don't have too many items in the list. - Expire old and unused entries after 30 minutes */ - for (rprev=NULL, r=thecache; r; ) - { - if (!r->pw && r->accessed + 60*30 < current) - { - if (r->lockcount) - { - log_error ("can't remove unused cache entry `%s' due to" - " lockcount=%d\n", - r->key, r->lockcount); - r->accessed += 60*10; /* next error message in 10 minutes */ - rprev = r; - r = r->next; - } - else - { - ITEM r2 = r->next; - if (DBG_CACHE) - log_debug (" removed `%s' (slot not used for 30m)\n", r->key); - xfree (r); - if (!rprev) - thecache = r2; - else - rprev->next = r2; - r = r2; - } - } - else - { - rprev = r; - r = r->next; - } - } -} - - -void -agent_flush_cache (void) -{ - ITEM r; - - if (DBG_CACHE) - log_debug ("agent_flush_cache\n"); - - for (r=thecache; r; r = r->next) - { - if (!r->lockcount && r->pw) - { - if (DBG_CACHE) - log_debug (" flushing `%s'\n", r->key); - release_data (r->pw); - r->pw = NULL; - r->accessed = 0; - } - else if (r->lockcount && r->pw) - { - if (DBG_CACHE) - log_debug (" marked `%s' for flushing\n", r->key); - r->accessed = 0; - r->ttl = 0; - } - } -} - - - -/* Store DATA of length DATALEN in the cache under KEY and mark it - with a maximum lifetime of TTL seconds. If there is already data - under this key, it will be replaced. Using a DATA of NULL deletes - the entry */ -int -agent_put_cache (const char *key, const char *data, int ttl) -{ - ITEM r; - - if (DBG_CACHE) - log_debug ("agent_put_cache `%s'\n", key); - housekeeping (); - - if (ttl < 1) - ttl = opt.def_cache_ttl; - if (!ttl) - return 0; - - for (r=thecache; r; r = r->next) - { - if (!r->lockcount && !strcmp (r->key, key)) - break; - } - if (r) - { /* replace */ - if (r->pw) - { - release_data (r->pw); - r->pw = NULL; - } - if (data) - { - r->created = r->accessed = gnupg_get_time (); - r->ttl = ttl; - r->pw = new_data (data, strlen (data)+1); - if (!r->pw) - log_error ("out of core while allocating new cache item\n"); - } - } - else if (data) - { /* simply insert */ - r = xtrycalloc (1, sizeof *r + strlen (key)); - if (!r) - log_error ("out of core while allocating new cache control\n"); - else - { - strcpy (r->key, key); - r->created = r->accessed = gnupg_get_time (); - r->ttl = ttl; - r->pw = new_data (data, strlen (data)+1); - if (!r->pw) - { - log_error ("out of core while allocating new cache item\n"); - xfree (r); - } - else - { - r->next = thecache; - thecache = r; - } - } - } - return 0; -} - - -/* Try to find an item in the cache */ -const char * -agent_get_cache (const char *key, void **cache_id) -{ - ITEM r; - - if (DBG_CACHE) - log_debug ("agent_get_cache `%s'...\n", key); - housekeeping (); - - /* first try to find one with no locks - this is an updated cache - entry: We might have entries with a lockcount and without a - lockcount. */ - for (r=thecache; r; r = r->next) - { - if (!r->lockcount && r->pw && !strcmp (r->key, key)) - { - /* put_cache does only put strings into the cache, so we - don't need the lengths */ - r->accessed = gnupg_get_time (); - if (DBG_CACHE) - log_debug ("... hit\n"); - r->lockcount++; - *cache_id = r; - return r->pw->data; - } - } - /* again, but this time get even one with a lockcount set */ - for (r=thecache; r; r = r->next) - { - if (r->pw && !strcmp (r->key, key)) - { - r->accessed = gnupg_get_time (); - if (DBG_CACHE) - log_debug ("... hit (locked)\n"); - r->lockcount++; - *cache_id = r; - return r->pw->data; - } - } - if (DBG_CACHE) - log_debug ("... miss\n"); - - *cache_id = NULL; - return NULL; -} - - -void -agent_unlock_cache_entry (void **cache_id) -{ - ITEM r; - - for (r=thecache; r; r = r->next) - { - if (r == *cache_id) - { - if (!r->lockcount) - log_error ("trying to unlock non-locked cache entry `%s'\n", - r->key); - else - r->lockcount--; - return; - } - } -} diff --git a/agent/call-scd.c b/agent/call-scd.c deleted file mode 100644 index a9123daca..000000000 --- a/agent/call-scd.c +++ /dev/null @@ -1,592 +0,0 @@ -/* call-scd.c - fork of the scdaemon to do SC operations - * 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 - */ - -/* Fixme: For now we have serialized all access to the scdaemon which - make sense becuase the scdaemon can't handle concurrent connections - right now. We should however keep a list of connections and lock - just that connection - it migth make sense to implemtn parts of - this in Assuan.*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef USE_GNU_PTH -# include -#endif - -#include "agent.h" -#include "../assuan/assuan.h" - -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif - -static ASSUAN_CONTEXT scd_ctx = NULL; -#ifdef USE_GNU_PTH -static pth_mutex_t scd_lock = PTH_MUTEX_INIT; -#endif - -/* callback parameter for learn card */ -struct learn_parm_s { - void (*kpinfo_cb)(void*, const char *); - void *kpinfo_cb_arg; - void (*certinfo_cb)(void*, const char *); - void *certinfo_cb_arg; -}; - -struct inq_needpin_s { - ASSUAN_CONTEXT ctx; - int (*getpin_cb)(void *, const char *, char*, size_t); - void *getpin_cb_arg; -}; - -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; -}; - - - -/* 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. */ - -static void -init_membuf (struct membuf *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 = 1; -} - -static void -put_membuf (struct membuf *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 = 1; - return; - } - mb->buf = p; - } - memcpy (mb->buf + mb->len, buf, len); - mb->len += len; -} - -static void * -get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ - return p; -} - - - - -static int -unlock_scd (int rc) -{ -#ifdef USE_GNU_PTH - if (!pth_mutex_release (&scd_lock)) - { - log_error ("failed to release the SCD lock\n"); - if (!rc) - rc = GNUPG_Internal_Error; - } -#endif - return rc; -} - -/* Fork off the SCdaemon if this has not already been done */ -static int -start_scd (void) -{ - int rc; - const char *pgmname; - ASSUAN_CONTEXT ctx; - const char *argv[3]; - int no_close_list[3]; - int i; - -#ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&scd_lock, 0, NULL)) - { - log_error ("failed to acquire the SCD lock\n"); - return GNUPG_Internal_Error; - } -#endif - - if (scd_ctx) - return 0; /* No need to serialize things because the agent is - expected to tun as a single-thread (or may be in - future using libpth) */ - - if (opt.verbose) - log_info ("no running SCdaemon - starting it\n"); - - if (fflush (NULL)) - { - log_error ("error flushing pending output: %s\n", strerror (errno)); - return unlock_scd (seterr (Write_Error)); - } - - if (!opt.scdaemon_program || !*opt.scdaemon_program) - opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON; - if ( !(pgmname = strrchr (opt.scdaemon_program, '/'))) - pgmname = opt.scdaemon_program; - else - pgmname++; - - argv[0] = pgmname; - argv[1] = "--server"; - argv[2] = NULL; - - i=0; - if (!opt.running_detached) - { - 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 pinentry and perform initial handshaking */ - rc = assuan_pipe_connect (&ctx, opt.scdaemon_program, (char**)argv, - no_close_list); - if (rc) - { - log_error ("can't connect to the SCdaemon: %s\n", - assuan_strerror (rc)); - return unlock_scd (seterr (No_Scdaemon)); - } - scd_ctx = ctx; - - if (DBG_ASSUAN) - log_debug ("connection to SCdaemon established\n"); - return 0; -} - - - -static AssuanError -learn_status_cb (void *opaque, const char *line) -{ - struct learn_parm_s *parm = opaque; - const char *keyword = line; - int keywordlen; - - for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) - ; - while (spacep (line)) - line++; - if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen)) - { - parm->certinfo_cb (parm->certinfo_cb_arg, line); - } - else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen)) - { - parm->kpinfo_cb (parm->kpinfo_cb_arg, line); - } - else if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) - { - log_debug ("learn_status_cb: serialno `%s'\n", line); - } - else - log_debug ("learn_status_cb: ignoring `%.*s'\n", keywordlen, keyword); - - return 0; -} - -/* Perform the learn command and return a list of all private keys - stored on the card. */ -int -agent_card_learn (void (*kpinfo_cb)(void*, const char *), - void *kpinfo_cb_arg, - void (*certinfo_cb)(void*, const char *), - void *certinfo_cb_arg) -{ - int rc; - struct learn_parm_s parm; - - rc = start_scd (); - if (rc) - return rc; - - memset (&parm, 0, sizeof parm); - parm.kpinfo_cb = kpinfo_cb; - parm.kpinfo_cb_arg = kpinfo_cb_arg; - parm.certinfo_cb = certinfo_cb; - parm.certinfo_cb_arg = certinfo_cb_arg; - rc = assuan_transact (scd_ctx, "LEARN --force", - NULL, NULL, NULL, NULL, - learn_status_cb, &parm); - if (rc) - return unlock_scd (map_assuan_err (rc)); - - return unlock_scd (0); -} - - - -static AssuanError -get_serialno_cb (void *opaque, const char *line) -{ - char **serialno = opaque; - const char *keyword = line; - const char *s; - int keywordlen, n; - - for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) - ; - while (spacep (line)) - line++; - - if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) - { - if (*serialno) - return ASSUAN_Unexpected_Status; - for (n=0,s=line; hexdigitp (s); s++, n++) - ; - if (!n || (n&1)|| !(spacep (s) || !*s) ) - return ASSUAN_Invalid_Status; - *serialno = xtrymalloc (n+1); - if (!*serialno) - return ASSUAN_Out_Of_Core; - memcpy (*serialno, line, n); - (*serialno)[n] = 0; - } - - return 0; -} - -/* Return the serial number of the card or an appropriate error. The - serial number is returned as a hexstring. */ -int -agent_card_serialno (char **r_serialno) -{ - int rc; - char *serialno = NULL; - - rc = start_scd (); - if (rc) - return rc; - - /* Hmm, do we really need this reset - scddaemon should do this or - we can do this if we for some reason figure out that the - operation might have failed due to a missing RESET. Hmmm, I feel - this is really SCdaemon's duty */ - rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_scd (map_assuan_err (rc)); - - rc = assuan_transact (scd_ctx, "SERIALNO", - NULL, NULL, NULL, NULL, - get_serialno_cb, &serialno); - if (rc) - { - xfree (serialno); - return unlock_scd (map_assuan_err (rc)); - } - *r_serialno = serialno; - return unlock_scd (0); -} - - -static AssuanError -membuf_data_cb (void *opaque, const void *buffer, size_t length) -{ - struct membuf *data = opaque; - - if (buffer) - put_membuf (data, buffer, length); - return 0; -} - -/* Handle the NEEDPIN inquiry. */ -static AssuanError -inq_needpin (void *opaque, const char *line) -{ - struct inq_needpin_s *parm = opaque; - char *pin; - size_t pinlen; - int rc; - - if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))) - { - log_error ("unsupported inquiry `%s'\n", line); - return ASSUAN_Inquire_Unknown; - } - line += 7; - - pinlen = 90; - pin = gcry_malloc_secure (pinlen); - if (!pin) - return ASSUAN_Out_Of_Core; - - rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen); - if (rc) - rc = ASSUAN_Canceled; - if (!rc) - rc = assuan_send_data (parm->ctx, pin, pinlen); - xfree (pin); - - return rc; -} - - - -/* Create a signature using the current card */ -int -agent_card_pksign (const char *keyid, - int (*getpin_cb)(void *, const char *, char*, size_t), - void *getpin_cb_arg, - const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen) -{ - int rc, i; - char *p, line[ASSUAN_LINELENGTH]; - struct membuf data; - struct inq_needpin_s inqparm; - size_t len; - unsigned char *sigbuf; - size_t sigbuflen; - - *r_buf = NULL; - rc = start_scd (); - if (rc) - return rc; - - if (indatalen*2 + 50 > DIM(line)) - return unlock_scd (seterr (General_Error)); - - sprintf (line, "SETDATA "); - p = line + strlen (line); - for (i=0; i < indatalen ; i++, p += 2 ) - sprintf (p, "%02X", indata[i]); - rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_scd (map_assuan_err (rc)); - - init_membuf (&data, 1024); - inqparm.ctx = scd_ctx; - inqparm.getpin_cb = getpin_cb; - inqparm.getpin_cb_arg = getpin_cb_arg; - snprintf (line, DIM(line)-1, "PKSIGN %s", keyid); - line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, - membuf_data_cb, &data, - inq_needpin, &inqparm, - NULL, NULL); - if (rc) - { - xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); - } - sigbuf = get_membuf (&data, &sigbuflen); - - /* create an S-expression from it which is formatted like this: - "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */ - *r_buflen = 21 + 11 + sigbuflen + 4; - *r_buf = xtrymalloc (*r_buflen); - if (!*r_buf) - { - xfree (*r_buf); - return unlock_scd (GNUPG_Out_Of_Core); - } - p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" ); - sprintf (p, "%u:", (unsigned int)sigbuflen); - p += strlen (p); - memcpy (p, sigbuf, sigbuflen); - p += sigbuflen; - strcpy (p, ")))"); - xfree (sigbuf); - - assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL)); - return unlock_scd (0); -} - -/* Decipher INDATA using the current card. Note that the returned value is */ -int -agent_card_pkdecrypt (const char *keyid, - int (*getpin_cb)(void *, const char *, char*, size_t), - void *getpin_cb_arg, - const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen) -{ - int rc, i; - char *p, line[ASSUAN_LINELENGTH]; - struct membuf data; - struct inq_needpin_s inqparm; - size_t len; - - *r_buf = NULL; - rc = start_scd (); - if (rc) - return rc; - - /* FIXME: use secure memory where appropriate */ - if (indatalen*2 + 50 > DIM(line)) - return unlock_scd (seterr (General_Error)); - - sprintf (line, "SETDATA "); - p = line + strlen (line); - for (i=0; i < indatalen ; i++, p += 2 ) - sprintf (p, "%02X", indata[i]); - rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_scd (map_assuan_err (rc)); - - init_membuf (&data, 1024); - inqparm.ctx = scd_ctx; - inqparm.getpin_cb = getpin_cb; - inqparm.getpin_cb_arg = getpin_cb_arg; - snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid); - line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, - membuf_data_cb, &data, - inq_needpin, &inqparm, - NULL, NULL); - if (rc) - { - xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); - } - *r_buf = get_membuf (&data, r_buflen); - if (!*r_buf) - return unlock_scd (GNUPG_Out_Of_Core); - - return unlock_scd (0); -} - - - -/* Read a certificate with ID into R_BUF and R_BUFLEN. */ -int -agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - struct membuf data; - size_t len; - - *r_buf = NULL; - rc = start_scd (); - if (rc) - return rc; - - init_membuf (&data, 1024); - snprintf (line, DIM(line)-1, "READCERT %s", id); - line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, - membuf_data_cb, &data, - NULL, NULL, - NULL, NULL); - if (rc) - { - xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); - } - *r_buf = get_membuf (&data, r_buflen); - if (!*r_buf) - return unlock_scd (GNUPG_Out_Of_Core); - - return unlock_scd (0); -} - - - -/* Read a key with ID and return it in an allocate buffer pointed to - by r_BUF as a valid S-expression. */ -int -agent_card_readkey (const char *id, unsigned char **r_buf) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - struct membuf data; - size_t len, buflen; - - *r_buf = NULL; - rc = start_scd (); - if (rc) - return rc; - - init_membuf (&data, 1024); - snprintf (line, DIM(line)-1, "READKEY %s", id); - line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, - membuf_data_cb, &data, - NULL, NULL, - NULL, NULL); - if (rc) - { - xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); - } - *r_buf = get_membuf (&data, &buflen); - if (!*r_buf) - return unlock_scd (GNUPG_Out_Of_Core); - - if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL)) - { - xfree (*r_buf); *r_buf = NULL; - return unlock_scd (GNUPG_Invalid_Value); - } - - return unlock_scd (0); -} - - - diff --git a/agent/command.c b/agent/command.c deleted file mode 100644 index 55ee8b84a..000000000 --- a/agent/command.c +++ /dev/null @@ -1,697 +0,0 @@ -/* command.c - gpg-agent command handler - * 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 - */ - -/* FIXME: we should not use the default assuan buffering but setup - some buffering in secure mempory to protect session keys etc. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" -#include "../assuan/assuan.h" - -/* maximum allowed size of the inquired ciphertext */ -#define MAXLEN_CIPHERTEXT 4096 -/* maximum allowed size of the key parameters */ -#define MAXLEN_KEYPARAM 1024 - -#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) - - -#if MAX_DIGEST_LEN < 20 -#error MAX_DIGEST_LEN shorter than keygrip -#endif - -/* Data used to associate an Assuan context with local server data */ -struct server_local_s { - ASSUAN_CONTEXT assuan_ctx; - int message_fd; - int use_cache_for_signing; -}; - - - - - -static void -reset_notify (ASSUAN_CONTEXT ctx) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - memset (ctrl->keygrip, 0, 20); - ctrl->have_keygrip = 0; - ctrl->digest.valuelen = 0; -} - - -/* Check whether the option NAME appears in LINE */ -static int -has_option (const char *line, const char *name) -{ - const char *s; - int n = strlen (name); - - s = strstr (line, name); - return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); -} - - - - -/* ISTRUSTED - - Return OK when we have an entry with this fingerprint in our - trustlist */ -static int -cmd_istrusted (ASSUAN_CONTEXT ctx, char *line) -{ - int rc, n, i; - char *p; - char fpr[41]; - - /* parse the fingerprint value */ - for (p=line,n=0; hexdigitp (p); p++, n++) - ; - if (*p || !(n == 40 || n == 32)) - return set_error (Parameter_Error, "invalid fingerprint"); - i = 0; - if (n==32) - { - strcpy (fpr, "00000000"); - i += 8; - } - for (p=line; i < 40; p++, i++) - fpr[i] = *p >= 'a'? (*p & 0xdf): *p; - fpr[i] = 0; - rc = agent_istrusted (fpr); - if (!rc) - return 0; - else if (rc == -1) - return ASSUAN_Not_Trusted; - else - { - log_error ("command is_trusted failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); - } -} - -/* LISTTRUSTED - - List all entries from the trustlist */ -static int -cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line) -{ - int rc = agent_listtrusted (ctx); - if (rc) - log_error ("command listtrusted failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - - -/* MARKTRUSTED - - Store a new key in into the trustlist*/ -static int -cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line) -{ - int rc, n, i; - char *p; - char fpr[41]; - int flag; - - /* parse the fingerprint value */ - for (p=line,n=0; hexdigitp (p); p++, n++) - ; - if (!spacep (p) || !(n == 40 || n == 32)) - return set_error (Parameter_Error, "invalid fingerprint"); - i = 0; - if (n==32) - { - strcpy (fpr, "00000000"); - i += 8; - } - for (p=line; i < 40; p++, i++) - fpr[i] = *p >= 'a'? (*p & 0xdf): *p; - fpr[i] = 0; - - while (spacep (p)) - p++; - flag = *p++; - if ( (flag != 'S' && flag != 'P') || !spacep (p) ) - return set_error (Parameter_Error, "invalid flag - must be P or S"); - while (spacep (p)) - p++; - - rc = agent_marktrusted (p, fpr, flag); - if (rc) - log_error ("command marktrusted failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - - - - -/* HAVEKEY - - Return success when the secret key is available */ -static int -cmd_havekey (ASSUAN_CONTEXT ctx, char *line) -{ - int n; - char *p; - unsigned char buf[20]; - - /* parse the hash value */ - for (p=line,n=0; hexdigitp (p); p++, n++) - ; - if (*p) - return set_error (Parameter_Error, "invalid hexstring"); - if ((n&1)) - return set_error (Parameter_Error, "odd number of digits"); - n /= 2; - if (n != 20) - return set_error (Parameter_Error, "invalid length of keygrip"); - - for (p=line, n=0; n < 20; p += 2, n++) - buf[n] = xtoi_2 (p); - - if (agent_key_available (buf)) - return ASSUAN_No_Secret_Key; - - return 0; -} - - -/* SIGKEY - SETKEY - - Set the key used for a sign or decrypt operation */ -static int -cmd_sigkey (ASSUAN_CONTEXT ctx, char *line) -{ - int n; - char *p; - CTRL ctrl = assuan_get_pointer (ctx); - unsigned char *buf; - - /* parse the hash value */ - for (p=line,n=0; hexdigitp (p); p++, n++) - ; - if (*p) - return set_error (Parameter_Error, "invalid hexstring"); - if ((n&1)) - return set_error (Parameter_Error, "odd number of digits"); - n /= 2; - if (n != 20) - return set_error (Parameter_Error, "invalid length of keygrip"); - - buf = ctrl->keygrip; - for (p=line, n=0; n < 20; p += 2, n++) - buf[n] = xtoi_2 (p); - ctrl->have_keygrip = 1; - return 0; -} - -/* SETHASH - - The client can use this command to tell the server about the data - (which usually is a hash) to be signed. */ -static int -cmd_sethash (ASSUAN_CONTEXT ctx, char *line) -{ - int n; - char *p; - CTRL ctrl = assuan_get_pointer (ctx); - unsigned char *buf; - char *endp; - int algo; - - /* parse the algo number and check it */ - algo = (int)strtoul (line, &endp, 10); - for (line = endp; *line == ' ' || *line == '\t'; line++) - ; - if (!algo || gcry_md_test_algo (algo)) - return set_error (Unsupported_Algorithm, NULL); - ctrl->digest.algo = algo; - - /* parse the hash value */ - for (p=line,n=0; hexdigitp (p); p++, n++) - ; - if (*p) - return set_error (Parameter_Error, "invalid hexstring"); - if ((n&1)) - return set_error (Parameter_Error, "odd number of digits"); - n /= 2; - if (n != 16 && n != 20 && n != 24 && n != 32) - return set_error (Parameter_Error, "unsupported length of hash"); - if (n > MAX_DIGEST_LEN) - return set_error (Parameter_Error, "hash value to long"); - - buf = ctrl->digest.value; - ctrl->digest.valuelen = n; - for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++) - buf[n] = xtoi_2 (p); - for (; n < ctrl->digest.valuelen; n++) - buf[n] = 0; - return 0; -} - - -/* PKSIGN - - Perform the actual sign operation. Neither input nor output are - sensitive to eavesdropping */ -static int -cmd_pksign (ASSUAN_CONTEXT ctx, char *line) -{ - int rc; - int ignore_cache = 0; - CTRL ctrl = assuan_get_pointer (ctx); - - if (opt.ignore_cache_for_signing) - ignore_cache = 1; - else if (!ctrl->server_local->use_cache_for_signing) - ignore_cache = 1; - - rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache); - if (rc) - log_error ("command pksign failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - -/* PKDECRYPT - - Perform the actual decrypt operation. Input is not - sensitive to eavesdropping */ -static int -cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) -{ - int rc; - CTRL ctrl = assuan_get_pointer (ctx); - char *value; - size_t valuelen; - - /* First inquire the data to decrypt */ - rc = assuan_inquire (ctx, "CIPHERTEXT", - &value, &valuelen, MAXLEN_CIPHERTEXT); - if (rc) - return rc; - - rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx)); - xfree (value); - if (rc) - log_error ("command pkdecrypt failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - - -/* GENKEY - - Generate a new key, store the secret part and return the public - part. Here is an example transaction: - - 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 -*/ - -static int -cmd_genkey (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - char *value; - size_t valuelen; - - /* First inquire the parameters */ - rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM); - if (rc) - return rc; - - rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx)); - xfree (value); - if (rc) - log_error ("command genkey failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - - -static void -plus_to_blank (char *s) -{ - for (; *s; s++) - { - if (*s == '+') - *s = ' '; - } -} - -/* GET_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 specal handling of passphrases. This command uses a syntax - which helps clients to use the agent with minimum effort. 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. -*/ - -static int -cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line) -{ - int rc; - const char *pw; - char *response; - char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL; - char *p; - void *cache_marker; - - /* parse the stuff */ - for (p=line; *p == ' '; p++) - ; - cacheid = p; - p = strchr (cacheid, ' '); - if (p) - { - *p++ = 0; - while (*p == ' ') - p++; - errtext = p; - p = strchr (errtext, ' '); - if (p) - { - *p++ = 0; - while (*p == ' ') - p++; - prompt = p; - p = strchr (prompt, ' '); - if (p) - { - *p++ = 0; - while (*p == ' ') - p++; - desc = p; - p = strchr (desc, ' '); - if (p) - *p = 0; /* ignore garbage */ - } - } - } - if (!cacheid || !*cacheid || strlen (cacheid) > 50) - return set_error (Parameter_Error, "invalid length of cacheID"); - if (!desc) - return set_error (Parameter_Error, "no description given"); - - if (!strcmp (cacheid, "X")) - cacheid = NULL; - if (!strcmp (errtext, "X")) - errtext = NULL; - if (!strcmp (prompt, "X")) - prompt = NULL; - if (!strcmp (desc, "X")) - desc = NULL; - - /* Note: we store the hexified versions in the cache. */ - pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL; - if (pw) - { - assuan_begin_confidential (ctx); - rc = assuan_set_okay_line (ctx, pw); - agent_unlock_cache_entry (&cache_marker); - } - else - { - /* Note, that we only need to replace the + characters and - should leave the other escaping in place because the escaped - string is send verbatim to the pinentry which does the - unescaping (but not the + replacing) */ - if (errtext) - plus_to_blank (errtext); - if (prompt) - plus_to_blank (prompt); - if (desc) - plus_to_blank (desc); - - rc = agent_get_passphrase (&response, desc, prompt, errtext); - if (!rc) - { - if (cacheid) - agent_put_cache (cacheid, response, 0); - assuan_begin_confidential (ctx); - rc = assuan_set_okay_line (ctx, response); - xfree (response); - } - } - - if (rc) - log_error ("command get_passphrase failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - - -/* CLEAR_PASSPHRASE - - may be used to invalidate the cache entry for a passphrase. The - function returns with OK even when there is no cached passphrase. -*/ - -static int -cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line) -{ - char *cacheid = NULL; - char *p; - - /* parse the stuff */ - for (p=line; *p == ' '; p++) - ; - cacheid = p; - p = strchr (cacheid, ' '); - if (p) - *p = 0; /* ignore garbage */ - if (!cacheid || !*cacheid || strlen (cacheid) > 50) - return set_error (Parameter_Error, "invalid length of cacheID"); - - agent_put_cache (cacheid, NULL, 0); - return 0; -} - - -/* LEARN [--send] - - Learn something about the currently inserted smartcard. With - --send the new certificates are send back. */ -static int -cmd_learn (ASSUAN_CONTEXT ctx, char *line) -{ - int rc; - - rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL); - if (rc) - log_error ("command learn failed: %s\n", gnupg_strerror (rc)); - return map_to_assuan_status (rc); -} - - - -static int -option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - /* FIXME: We should not change opt. here. It is not a problem right - now but as soon as we are allowing concurrent connections we mess - things up */ - if (!strcmp (key, "display")) - { - if (opt.display) - free (opt.display); - opt.display = strdup (value); - if (!opt.display) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "ttyname")) - { - if (opt.ttyname) - free (opt.ttyname); - opt.ttyname = strdup (value); - if (!opt.ttyname) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "ttytype")) - { - if (opt.ttytype) - free (opt.ttytype); - opt.ttytype = strdup (value); - if (!opt.ttytype) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "lc-ctype")) - { - if (opt.lc_ctype) - free (opt.lc_ctype); - opt.lc_ctype = strdup (value); - if (!opt.lc_ctype) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "lc-messages")) - { - if (opt.lc_messages) - free (opt.lc_messages); - opt.lc_messages = strdup (value); - if (!opt.lc_messages) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "use-cache-for-signing")) - ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0; - else - return ASSUAN_Invalid_Option; - - return 0; -} - - -/* Tell the assuan library about our commands */ -static int -register_commands (ASSUAN_CONTEXT ctx) -{ - static struct { - const char *name; - int cmd_id; - int (*handler)(ASSUAN_CONTEXT, char *line); - } table[] = { - { "ISTRUSTED", 0, cmd_istrusted }, - { "HAVEKEY", 0, cmd_havekey }, - { "SIGKEY", 0, cmd_sigkey }, - { "SETKEY", 0, cmd_sigkey }, - { "SETHASH", 0, cmd_sethash }, - { "PKSIGN", 0, cmd_pksign }, - { "PKDECRYPT", 0, cmd_pkdecrypt }, - { "GENKEY", 0, cmd_genkey }, - { "GET_PASSPHRASE",0, cmd_get_passphrase }, - { "CLEAR_PASSPHRASE",0, cmd_clear_passphrase }, - { "LISTTRUSTED", 0, cmd_listtrusted }, - { "MARKTRUSTED", 0, cmd_marktrusted }, - { "LEARN", 0, cmd_learn }, - { "", ASSUAN_CMD_INPUT, NULL }, - { "", ASSUAN_CMD_OUTPUT, NULL }, - { NULL } - }; - int i, j, rc; - - for (i=j=0; table[i].name; i++) - { - rc = assuan_register_command (ctx, - table[i].cmd_id? table[i].cmd_id - : (ASSUAN_CMD_USER + j++), - table[i].name, table[i].handler); - if (rc) - return rc; - } - assuan_register_reset_notify (ctx, reset_notify); - assuan_register_option_handler (ctx, option_handler); - return 0; -} - - -/* Startup the server. If LISTEN_FD and FD is given as -1, this is a simple - piper server, otherwise it is a regular server */ -void -start_command_handler (int listen_fd, int fd) -{ - int rc; - ASSUAN_CONTEXT ctx; - struct server_control_s ctrl; - - memset (&ctrl, 0, sizeof ctrl); - - if (listen_fd == -1 && fd == -1) - { - int filedes[2]; - - filedes[0] = 0; - filedes[1] = 1; - rc = assuan_init_pipe_server (&ctx, filedes); - } - else if (listen_fd != -1) - { - rc = assuan_init_socket_server (&ctx, listen_fd); - } - else - { - rc = assuan_init_connected_socket_server (&ctx, fd); - } - if (rc) - { - log_error ("failed to initialize the server: %s\n", - assuan_strerror(rc)); - agent_exit (2); - } - rc = register_commands (ctx); - if (rc) - { - log_error ("failed to register commands with Assuan: %s\n", - assuan_strerror(rc)); - agent_exit (2); - } - - assuan_set_pointer (ctx, &ctrl); - ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); - ctrl.server_local->assuan_ctx = ctx; - ctrl.server_local->message_fd = -1; - ctrl.server_local->use_cache_for_signing = 1; - - if (DBG_ASSUAN) - assuan_set_log_stream (ctx, log_get_stream ()); - - for (;;) - { - rc = assuan_accept (ctx); - if (rc == -1) - { - break; - } - else if (rc) - { - log_info ("Assuan accept problem: %s\n", assuan_strerror (rc)); - break; - } - - rc = assuan_process (ctx); - if (rc) - { - log_info ("Assuan processing failed: %s\n", assuan_strerror (rc)); - continue; - } - } - - - assuan_deinit_server (ctx); -} - diff --git a/agent/divert-scd.c b/agent/divert-scd.c deleted file mode 100644 index 40b6bcfa3..000000000 --- a/agent/divert-scd.c +++ /dev/null @@ -1,305 +0,0 @@ -/* divert-scd.c - divert operations to the scdaemon - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" -#include "sexp-parse.h" -#include "i18n.h" - - -static int -ask_for_card (const unsigned char *shadow_info, char **r_kid) -{ - int rc, i; - const unsigned char *s; - size_t n; - char *serialno; - int no_card = 0; - char *desc; - char *want_sn, *want_kid; - int want_sn_displen; - - *r_kid = NULL; - s = shadow_info; - if (*s != '(') - return GNUPG_Invalid_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - want_sn = xtrymalloc (n*2+1); - if (!want_sn) - return GNUPG_Out_Of_Core; - for (i=0; i < n; i++) - sprintf (want_sn+2*i, "%02X", s[i]); - s += n; - /* We assume that a 20 byte serial number is a standard one which - seems to have the property to have a zero in the last nibble. We - don't display this '0' because it may confuse the user */ - want_sn_displen = strlen (want_sn); - if (want_sn_displen == 20 && want_sn[19] == '0') - want_sn_displen--; - - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - want_kid = xtrymalloc (n+1); - if (!want_kid) - { - xfree (want_sn); - return GNUPG_Out_Of_Core; - } - memcpy (want_kid, s, n); - want_kid[n] = 0; - - for (;;) - { - rc = agent_card_serialno (&serialno); - if (!rc) - { - log_debug ("detected card with S/N %s\n", serialno); - i = strcmp (serialno, want_sn); - xfree (serialno); - serialno = NULL; - if (!i) - { - xfree (want_sn); - *r_kid = want_kid; - return 0; /* yes, we have the correct card */ - } - } - else if (rc == GNUPG_Card_Not_Present) - { - log_debug ("no card present\n"); - rc = 0; - no_card = 1; - } - else - { - log_error ("error accesing card: %s\n", gnupg_strerror (rc)); - } - - if (!rc) - { - if (asprintf (&desc, - "%s:%%0A%%0A" - " \"%.*s\"", - no_card? "Please insert the card with serial number" - : "Please remove the current card and " - "insert the one with serial number", - want_sn_displen, want_sn) < 0) - { - rc = GNUPG_Out_Of_Core; - } - else - { - rc = agent_get_confirmation (desc, NULL, NULL); - free (desc); - } - } - if (rc) - { - xfree (want_sn); - xfree (want_kid); - return rc; - } - } -} - - -/* Put the DIGEST into an DER encoded comtainer and return it in R_VAL. */ -static int -encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo, - unsigned char **r_val, size_t *r_len) -{ - byte *frame; - byte asn[100]; - size_t asnlen; - - asnlen = DIM(asn); - if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) - { - log_error ("no object identifier for algo %d\n", algo); - return GNUPG_Internal_Error; - } - - frame = xtrymalloc (asnlen + digestlen); - if (!frame) - return GNUPG_Out_Of_Core; - memcpy (frame, asn, asnlen); - memcpy (frame+asnlen, digest, digestlen); - if (DBG_CRYPTO) - log_printhex ("encoded hash:", frame, asnlen+digestlen); - - *r_val = frame; - *r_len = asnlen+digestlen; - return 0; -} - - -/* Callback used to ask for the PIN which should be set into BUF. The - buf has been allocated by the caller and is of size MAXBUF which - includes the terminating null. The function should return an UTF-8 - string with the passphrase, the buffer may optionally be padded - with arbitrary characters */ -static int -getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) -{ - struct pin_entry_info_s *pi; - int rc; - char *desc; - - assert (!opaque); - - if (maxbuf < 2) - return GNUPG_Invalid_Value; - - - /* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole - mess because we should call the card's verify function from the - pinentry check pin CB. */ - pi = gcry_calloc_secure (1, sizeof (*pi) + 100); - pi->max_length = maxbuf-1; - pi->min_digits = 0; /* we want a real passphrase */ - pi->max_digits = 8; - pi->max_tries = 3; - - if ( asprintf (&desc, _("Please enter the PIN%s%s%s to unlock the card"), - info? " (`":"", - info? info:"", - info? "')":"") < 0) - desc = NULL; - rc = agent_askpin (desc?desc:info, pi); - free (desc); - if (!rc) - { - strncpy (buf, pi->pin, maxbuf-1); - buf[maxbuf-1] = 0; - } - xfree (pi); - return rc; -} - - - - -int -divert_pksign (const unsigned char *digest, size_t digestlen, int algo, - const unsigned char *shadow_info, unsigned char **r_sig) -{ - int rc; - char *kid; - size_t siglen; - char *sigval; - unsigned char *data; - size_t ndata; - - rc = ask_for_card (shadow_info, &kid); - if (rc) - return rc; - - rc = encode_md_for_card (digest, digestlen, algo, - &data, &ndata); - if (rc) - return rc; - - rc = agent_card_pksign (kid, getpin_cb, NULL, - data, ndata, &sigval, &siglen); - if (!rc) - *r_sig = sigval; - xfree (data); - xfree (kid); - - return rc; -} - - -/* Decrypt the the value given asn an S-expression in CIPHER using the - key identified by SHADOW_INFO and return the plaintext in an - allocated buffer in R_BUF. */ -int -divert_pkdecrypt (const unsigned char *cipher, - const unsigned char *shadow_info, - char **r_buf, size_t *r_len) -{ - int rc; - char *kid; - const unsigned char *s; - size_t n; - const unsigned char *ciphertext; - size_t ciphertextlen; - char *plaintext; - size_t plaintextlen; - - s = cipher; - if (*s != '(') - return GNUPG_Invalid_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "enc-val")) - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Unknown_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "rsa")) - return GNUPG_Unsupported_Algorithm; - if (*s != '(') - return GNUPG_Unknown_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "a")) - return GNUPG_Unknown_Sexp; - n = snext (&s); - if (!n) - return GNUPG_Unknown_Sexp; - ciphertext = s; - ciphertextlen = n; - - rc = ask_for_card (shadow_info, &kid); - if (rc) - return rc; - - rc = agent_card_pkdecrypt (kid, getpin_cb, NULL, - ciphertext, ciphertextlen, - &plaintext, &plaintextlen); - if (!rc) - { - *r_buf = plaintext; - *r_len = plaintextlen; - } - xfree (kid); - return rc; -} diff --git a/agent/findkey.c b/agent/findkey.c deleted file mode 100644 index 8ec230fa0..000000000 --- a/agent/findkey.c +++ /dev/null @@ -1,350 +0,0 @@ -/* findkey.c - locate the secret key - * Copyright (C) 2001,02 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" - -/* Helper to pass data to the check callback of the unprotect function. */ -struct try_unprotect_arg_s { - const unsigned char *protected_key; - unsigned char *unprotected_key; -}; - - - -int -agent_write_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force) -{ - int i; - char *fname; - FILE *fp; - char hexgrip[40+4+1]; - - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); - strcpy (hexgrip+40, ".key"); - - fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); - if (force) - fp = fopen (fname, "wb"); - else - { - int fd; - - if (!access (fname, F_OK)) - { - log_error ("secret key file `%s' already exists\n", fname); - xfree (fname); - return seterr (General_Error); - } - - /* We would like to create FNAME but only if it does not already - exist. We cannot make this guarantee just using POSIX (GNU - provides the "x" opentype for fopen, however, this is not - portable). Thus, we use the more flexible open function and - then use fdopen to obtain a stream. - - The mode parameter to open is what fopen uses. It will be - combined with the process' umask automatically. */ - fd = open (fname, O_CREAT | O_EXCL | O_RDWR, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if (fd < 0) - fp = 0; - else - { - fp = fdopen (fd, "wb"); - if (! fp) - close (fd); - } - } - - if (!fp) - { - log_error ("can't create `%s': %s\n", fname, strerror (errno)); - xfree (fname); - return seterr (File_Create_Error); - } - - if (fwrite (buffer, length, 1, fp) != 1) - { - log_error ("error writing `%s': %s\n", fname, strerror (errno)); - fclose (fp); - remove (fname); - xfree (fname); - return seterr (File_Create_Error); - } - if ( fclose (fp) ) - { - log_error ("error closing `%s': %s\n", fname, strerror (errno)); - remove (fname); - xfree (fname); - return seterr (File_Create_Error); - } - - xfree (fname); - return 0; -} - - -/* Callback function to try the unprotection from the passpharse query - code. */ -static int -try_unprotect_cb (struct pin_entry_info_s *pi) -{ - struct try_unprotect_arg_s *arg = pi->check_cb_arg; - size_t dummy; - - assert (!arg->unprotected_key); - return agent_unprotect (arg->protected_key, pi->pin, - &arg->unprotected_key, &dummy); -} - - -/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP - should be the hex encoded keygrip of that key to be used with the - cahing mechanism. */ -static int -unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache) -{ - struct pin_entry_info_s *pi; - struct try_unprotect_arg_s arg; - int rc, i; - unsigned char *result; - size_t resultlen; - char hexgrip[40+1]; - - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); - hexgrip[40] = 0; - - /* first try to get it from the cache - if there is none or we can't - unprotect it, we fall back to ask the user */ - if (!ignore_cache) - { - void *cache_marker; - const char *pw = agent_get_cache (hexgrip, &cache_marker); - if (pw) - { - rc = agent_unprotect (*keybuf, pw, &result, &resultlen); - agent_unlock_cache_entry (&cache_marker); - if (!rc) - { - xfree (*keybuf); - *keybuf = result; - return 0; - } - rc = 0; - } - } - - pi = gcry_calloc_secure (1, sizeof (*pi) + 100); - pi->max_length = 100; - pi->min_digits = 0; /* we want a real passphrase */ - pi->max_digits = 8; - pi->max_tries = 3; - pi->check_cb = try_unprotect_cb; - arg.protected_key = *keybuf; - arg.unprotected_key = NULL; - pi->check_cb_arg = &arg; - - rc = agent_askpin (NULL, pi); - if (!rc) - { - assert (arg.unprotected_key); - agent_put_cache (hexgrip, pi->pin, 0); - xfree (*keybuf); - *keybuf = arg.unprotected_key; - } - xfree (pi); - return rc; -} - - - -/* Return the secret key as an S-Exp after locating it using the grip. - Returns NULL if key is not available or the operation should be - diverted to a token. In the latter case shadow_info will point to - an allocated S-Expression with the shadow_info part from the file. - With IGNORE_CACHE passed as true the passphrase is not taken from - the cache.*/ -GCRY_SEXP -agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info, - int ignore_cache) -{ - int i, rc; - char *fname; - FILE *fp; - struct stat st; - unsigned char *buf; - size_t len, buflen, erroff; - GCRY_SEXP s_skey; - char hexgrip[40+4+1]; - - if (shadow_info) - *shadow_info = NULL; - - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); - strcpy (hexgrip+40, ".key"); - - fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); - fp = fopen (fname, "rb"); - if (!fp) - { - log_error ("can't open `%s': %s\n", fname, strerror (errno)); - xfree (fname); - return NULL; - } - - if (fstat (fileno(fp), &st)) - { - log_error ("can't stat `%s': %s\n", fname, strerror (errno)); - xfree (fname); - fclose (fp); - return NULL; - } - - buflen = st.st_size; - buf = xmalloc (buflen+1); - if (fread (buf, buflen, 1, fp) != 1) - { - log_error ("error reading `%s': %s\n", fname, strerror (errno)); - xfree (fname); - fclose (fp); - xfree (buf); - return NULL; - } - - rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); - xfree (fname); - fclose (fp); - xfree (buf); - if (rc) - { - log_error ("failed to build S-Exp (off=%u): %s\n", - (unsigned int)erroff, gcry_strerror (rc)); - return NULL; - } - len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xtrymalloc (len); - if (!buf) - { - gcry_sexp_release (s_skey); - return NULL; - } - len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - gcry_sexp_release (s_skey); - - switch (agent_private_key_type (buf)) - { - case PRIVATE_KEY_CLEAR: - break; /* no unprotection needed */ - case PRIVATE_KEY_PROTECTED: - rc = unprotect (&buf, grip, ignore_cache); - if (rc) - log_error ("failed to unprotect the secret key: %s\n", - gnupg_strerror (rc)); - break; - case PRIVATE_KEY_SHADOWED: - if (shadow_info) - { - const unsigned char *s; - size_t n; - - rc = agent_get_shadow_info (buf, &s); - if (!rc) - { - n = gcry_sexp_canon_len (s, 0, NULL,NULL); - assert (n); - *shadow_info = xtrymalloc (n); - if (!*shadow_info) - rc = GNUPG_Out_Of_Core; - else - { - memcpy (*shadow_info, s, n); - rc = 0; - } - } - if (rc) - log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc)); - } - rc = -1; /* ugly interface: we return an error but keep a value - in shadow_info. */ - break; - default: - log_error ("invalid private key format\n"); - rc = GNUPG_Bad_Secret_Key; - break; - } - if (rc) - { - xfree (buf); - return NULL; - } - - /* arggg FIXME: does scan support secure memory? */ - rc = gcry_sexp_sscan (&s_skey, &erroff, - buf, gcry_sexp_canon_len (buf, 0, NULL, NULL)); - xfree (buf); - if (rc) - { - log_error ("failed to build S-Exp (off=%u): %s\n", - (unsigned int)erroff, gcry_strerror (rc)); - return NULL; - } - - return s_skey; -} - -/* Return the secret key as an S-Exp after locating it using the grip. - Returns NULL if key is not available. 0 = key is available */ -int -agent_key_available (const unsigned char *grip) -{ - int i; - char *fname; - char hexgrip[40+4+1]; - - for (i=0; i < 20; i++) - sprintf (hexgrip+2*i, "%02X", grip[i]); - strcpy (hexgrip+40, ".key"); - - fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); - i = !access (fname, R_OK)? 0 : -1; - xfree (fname); - return i; -} - - - diff --git a/agent/genkey.c b/agent/genkey.c deleted file mode 100644 index dccac94da..000000000 --- a/agent/genkey.c +++ /dev/null @@ -1,200 +0,0 @@ -/* pksign.c - Generate a keypair - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" -#include "i18n.h" - -static int -store_key (GCRY_SEXP private, const char *passphrase) -{ - int rc; - char *buf; - size_t len; - unsigned char grip[20]; - - if ( !gcry_pk_get_keygrip (private, grip) ) - { - log_error ("can't calculate keygrip\n"); - return seterr (General_Error); - } - - len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = gcry_malloc_secure (len); - if (!buf) - return seterr (Out_Of_Core); - len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - - if (passphrase) - { - unsigned char *p; - - rc = agent_protect (buf, passphrase, &p, &len); - if (rc) - { - xfree (buf); - return rc; - } - xfree (buf); - buf = p; - } - - rc = agent_write_private_key (grip, buf, len, 0); - xfree (buf); - return rc; -} - -/* Callback function to compare the first entered PIN with the one - currently beeing entered. */ -static int -reenter_compare_cb (struct pin_entry_info_s *pi) -{ - const char *pin1 = pi->check_cb_arg; - - if (!strcmp (pin1, pi->pin)) - return 0; /* okay */ - pi->cb_errtext = _("does not match - try again"); - return -1; -} - - - -/* Generate a new keypair according to the parameters given in - KEYPARAM */ -int -agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, - FILE *outfp) -{ - GCRY_SEXP s_keyparam, s_key, s_private, s_public; - struct pin_entry_info_s *pi, *pi2; - int rc; - size_t len; - char *buf; - - rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen); - if (rc) - { - log_error ("failed to convert keyparam: %s\n", gcry_strerror (rc)); - return seterr (Invalid_Data); - } - - /* Get the passphrase now, cause key generation may take a while. */ - { - const char *text1 = _("Please enter the passphrase to%0A" - "to protect your new key"); - const char *text2 = _("Please re-enter this passphrase"); - - pi = gcry_calloc_secure (2, sizeof (*pi) + 100); - pi2 = pi + (sizeof *pi + 100); - pi->max_length = 100; - pi->max_tries = 3; - pi2->max_length = 100; - pi2->max_tries = 3; - pi2->check_cb = reenter_compare_cb; - pi2->check_cb_arg = pi->pin; - - rc = agent_askpin (text1, pi); - if (!rc) - rc = agent_askpin (text2, pi2); - if (rc) - return rc; - if (!*pi->pin) - { - xfree (pi); - pi = NULL; /* User does not want a passphrase. */ - } - } - - rc = gcry_pk_genkey (&s_key, s_keyparam ); - gcry_sexp_release (s_keyparam); - if (rc) - { - log_error ("key generation failed: %s\n", gcry_strerror (rc)); - xfree (pi); - return map_gcry_err (rc); - } - - /* break out the parts */ - s_private = gcry_sexp_find_token (s_key, "private-key", 0); - if (!s_private) - { - log_error ("key generation failed: invalid return value\n"); - gcry_sexp_release (s_key); - xfree (pi); - return seterr (Invalid_Data); - } - s_public = gcry_sexp_find_token (s_key, "public-key", 0); - if (!s_public) - { - log_error ("key generation failed: invalid return value\n"); - gcry_sexp_release (s_private); - gcry_sexp_release (s_key); - xfree (pi); - return seterr (Invalid_Data); - } - gcry_sexp_release (s_key); s_key = NULL; - - /* store the secret key */ - log_debug ("storing private key\n"); - rc = store_key (s_private, pi? pi->pin:NULL); - xfree (pi); pi = NULL; - gcry_sexp_release (s_private); - if (rc) - { - gcry_sexp_release (s_public); - return rc; - } - - /* return the public key */ - log_debug ("returning public key\n"); - len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xmalloc (len); - if (!buf) - { - gcry_sexp_release (s_private); - gcry_sexp_release (s_public); - return seterr (Out_Of_Core); - } - len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - if (fwrite (buf, len, 1, outfp) != 1) - { - log_error ("error writing public key: %s\n", strerror (errno)); - gcry_sexp_release (s_private); - gcry_sexp_release (s_public); - xfree (buf); - return seterr (File_Create_Error); - } - gcry_sexp_release (s_public); - xfree (buf); - - return 0; -} - diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c deleted file mode 100644 index 3c823e5f6..000000000 --- a/agent/gpg-agent.c +++ /dev/null @@ -1,916 +0,0 @@ -/* gpg-agent.c - The GnuPG Agent - * Copyright (C) 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef USE_GNU_PTH -# include -#endif - -#include - -#define JNLIB_NEED_LOG_LOGV -#include "agent.h" -#include "../assuan/assuan.h" /* malloc hooks */ - -#include "i18n.h" -#include "sysutils.h" - - -enum cmd_and_opt_values -{ aNull = 0, - oCsh = 'c', - oQuiet = 'q', - oSh = 's', - oVerbose = 'v', - - oNoVerbose = 500, - oOptions, - oDebug, - oDebugAll, - oDebugWait, - oNoGreeting, - oNoOptions, - oHomedir, - oNoDetach, - oNoGrab, - oLogFile, - oServer, - oDaemon, - oBatch, - - oPinentryProgram, - oDisplay, - oTTYname, - oTTYtype, - oLCctype, - oLCmessages, - oScdaemonProgram, - oDefCacheTTL, - oDisablePth, - - oIgnoreCacheForSigning, - oKeepTTY, - oKeepDISPLAY, - -aTest }; - - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, N_("@Options:\n ") }, - - { oServer, "server", 0, N_("run in server mode (foreground)") }, - { oDaemon, "daemon", 0, N_("run in daemon mode (background)") }, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oSh, "sh", 0, N_("sh-style command output") }, - { oCsh, "csh", 0, N_("csh-style command output") }, - { oOptions, "options" , 2, N_("read options from file")}, - { oDebug, "debug" ,4|16, N_("set debugging flags")}, - { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, - { oDebugWait,"debug-wait",1, "@"}, - { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, - { oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")}, - { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - { oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")}, - - { oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" }, - { oDisplay, "display", 2, "set the display" }, - { oTTYname, "ttyname", 2, "set the tty terminal node name" }, - { oTTYtype, "ttytype", 2, "set the tty terminal type" }, - { oLCctype, "lc-ctype", 2, "set the tty LC_CTYPE value" }, - { oLCmessages, "lc-messages", 2, "set the tty LC_MESSAGES value" }, - - { oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" }, - { oDefCacheTTL, "default-cache-ttl", 4, - "|N|expire cached PINs after N seconds"}, - { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, - "do not use the PIN cache when signing"}, - { oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")}, - { oKeepDISPLAY, "keep-display", - 0, N_("ignore requests to change the X display")}, - {0} -}; - - -static volatile int caught_fatal_sig = 0; - -/* flag to indicate that a shutdown was requested */ -static int shutdown_pending; - - -/* It is possible that we are currently running under setuid permissions */ -static int maybe_setuid = 1; - -/* Name of the communication socket */ -static char socket_name[128]; - -static void create_directories (void); -#ifdef USE_GNU_PTH -static void handle_connections (int listen_fd); -#endif - - - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "gpg-agent (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: gpg-agent [options] (-h for help)"); - break; - case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n" - "Secret key management for GnuPG\n"); - break; - - default: p = NULL; - } - return p; -} - - - -static void -i18n_init (void) -{ -#ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); -#else -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -#endif -#endif -} - - - -/* Used by gcry for logging */ -static void -my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) -{ - /* translate the log levels */ - switch (level) - { - case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; - case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; - case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; - case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; - case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; - case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; - case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; - default: level = JNLIB_LOG_ERROR; break; - } - log_logv (level, fmt, arg_ptr); -} - - -static void -cleanup (void) -{ - if (*socket_name) - { - char *p; - - remove (socket_name); - p = strrchr (socket_name, '/'); - if (p) - { - *p = 0; - rmdir (socket_name); - *p = '/'; - } - *socket_name = 0; - } -} - - -static RETSIGTYPE -cleanup_sh (int sig) -{ - if (caught_fatal_sig) - raise (sig); - caught_fatal_sig = 1; - - /* gcry_control( GCRYCTL_TERM_SECMEM );*/ - cleanup (); - -#ifndef HAVE_DOSISH_SYSTEM - { /* reset action to default action and raise signal again */ - struct sigaction nact; - nact.sa_handler = SIG_DFL; - sigemptyset( &nact.sa_mask ); - nact.sa_flags = 0; - sigaction( sig, &nact, NULL); - } -#endif - raise( sig ); -} - -int -main (int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - int orig_argc; - int may_coredump; - char **orig_argv; - FILE *configfp = NULL; - char *configname = NULL; - const char *shell; - unsigned configlineno; - int parse_debug = 0; - int default_config =1; - int greeting = 0; - int nogreeting = 0; - int pipe_server = 0; - int is_daemon = 0; - int nodetach = 0; - int csh_style = 0; - char *logfile = NULL; - int debug_wait = 0; - int disable_pth = 0; - - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - /* Please note that we may running SUID(ROOT), so be very CAREFUL - when adding any stuff between here and the call to INIT_SECMEM() - somewhere after the option parsing */ - log_set_prefix ("gpg-agent", 1|4); - i18n_init (); - - /* check that the libraries are suitable. Do it here because - the option parsing may need services of the library */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - - assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); -#ifdef USE_GNU_PTH - assuan_set_io_func (pth_read, pth_write); -#endif - - gcry_set_log_handler (my_gcry_logger, NULL); - gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); - - may_coredump = disable_core_dumps (); - - shell = getenv ("SHELL"); - if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) - csh_style = 1; - - opt.homedir = getenv("GNUPGHOME"); - if (!opt.homedir || !*opt.homedir) - opt.homedir = GNUPG_DEFAULT_HOMEDIR; - opt.def_cache_ttl = 10*60; /* default to 10 minutes */ - - - /* check whether we have a config file on the commandline */ - orig_argc = argc; - orig_argv = argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ - while (arg_parse( &pargs, opts)) - { - if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) - parse_debug++; - else if (pargs.r_opt == oOptions) - { /* yes there is one, so we do not try the default one, but - read the option file when it is encountered at the - commandline */ - default_config = 0; - } - else if (pargs.r_opt == oNoOptions) - default_config = 0; /* --no-options */ - else if (pargs.r_opt == oHomedir) - opt.homedir = pargs.r.ret_str; - } - - /* initialize the secure memory. */ - gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); - maybe_setuid = 0; - - /* - Now we are now working under our real uid - */ - - - if (default_config) - configname = make_filename (opt.homedir, "gpg-agent.conf", NULL ); - - argc = orig_argc; - argv = orig_argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - next_pass: - if (configname) - { - configlineno = 0; - configfp = fopen (configname, "r"); - if (!configfp) - { - if (default_config) - { - if( parse_debug ) - log_info (_("NOTE: no default option file `%s'\n"), - configname ); - } - else - { - log_error (_("option file `%s': %s\n"), - configname, strerror(errno) ); - exit(2); - } - xfree (configname); - configname = NULL; - } - if (parse_debug && configname ) - log_info (_("reading options from `%s'\n"), configname ); - default_config = 0; - } - - while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) - { - switch (pargs.r_opt) - { - case oQuiet: opt.quiet = 1; break; - case oVerbose: opt.verbose++; break; - case oBatch: opt.batch=1; break; - - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - case oDebugWait: debug_wait = pargs.r.ret_int; break; - - case oOptions: - /* config files may not be nested (silently ignore them) */ - if (!configfp) - { - xfree(configname); - configname = xstrdup(pargs.r.ret_str); - goto next_pass; - } - break; - case oNoGreeting: nogreeting = 1; break; - case oNoVerbose: opt.verbose = 0; break; - case oNoOptions: break; /* no-options */ - case oHomedir: opt.homedir = pargs.r.ret_str; break; - case oNoDetach: nodetach = 1; break; - case oNoGrab: opt.no_grab = 1; break; - case oLogFile: logfile = pargs.r.ret_str; break; - case oCsh: csh_style = 1; break; - case oSh: csh_style = 0; break; - case oServer: pipe_server = 1; break; - case oDaemon: is_daemon = 1; break; - case oDisablePth: disable_pth = 1; break; - - case oPinentryProgram: opt.pinentry_program = pargs.r.ret_str; break; - case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break; - case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break; - case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break; - case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break; - case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break; - case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break; - case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break; - - case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; - case oKeepTTY: opt.keep_tty = 1; break; - case oKeepDISPLAY: opt.keep_display = 1; break; - - default : pargs.err = configfp? 1:2; break; - } - } - if (configfp) - { - fclose( configfp ); - configfp = NULL; - xfree(configname); - configname = NULL; - goto next_pass; - } - xfree (configname); - configname = NULL; - if (log_get_errorcount(0)) - exit(2); - if (nogreeting ) - greeting = 0; - - if (greeting) - { - fprintf (stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - fprintf (stderr, "%s\n", strusage(15) ); - } -#ifdef IS_DEVELOPMENT_VERSION - log_info ("NOTE: this is a development version!\n"); -#endif - - - if (atexit (cleanup)) - { - log_error ("atexit failed\n"); - cleanup (); - exit (1); - } - - create_directories (); - - if (debug_wait && pipe_server) - { - log_debug ("waiting for debugger - my pid is %u .....\n", - (unsigned int)getpid()); - sleep (debug_wait); - log_debug ("... okay\n"); - } - - /* now start with logging to a file if this is desired */ - if (logfile) - { - log_set_file (logfile); - log_set_prefix (NULL, 1|2|4); - } - - - if (pipe_server) - { /* this is the simple pipe based server */ - start_command_handler (-1, -1); - } - else if (!is_daemon) - { - log_info (_("please use the option `--daemon'" - " to run the program in the background\n")); - } - else - { /* regular server mode */ - int fd; - pid_t pid; - int len; - struct sockaddr_un serv_addr; - char *p; - - *socket_name = 0; - snprintf (socket_name, DIM(socket_name)-1, - "/tmp/gpg-XXXXXX/S.gpg-agent"); - socket_name[DIM(socket_name)-1] = 0; - p = strrchr (socket_name, '/'); - if (!p) - BUG (); - *p = 0;; - if (!mkdtemp(socket_name)) - { - log_error ("can't create directory `%s': %s\n", - socket_name, strerror(errno) ); - exit (1); - } - *p = '/'; - - if (strchr (socket_name, ':') ) - { - log_error ("colons are not allowed in the socket name\n"); - exit (1); - } - if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) - { - log_error ("name of socket too long\n"); - exit (1); - } - - - fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror(errno) ); - exit (1); - } - - memset (&serv_addr, 0, sizeof serv_addr); - serv_addr.sun_family = AF_UNIX; - strcpy (serv_addr.sun_path, socket_name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen(serv_addr.sun_path) + 1); - - if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1) - { - log_error ("error binding socket to `%s': %s\n", - serv_addr.sun_path, strerror (errno) ); - close (fd); - exit (1); - } - - if (listen (fd, 5 ) == -1) - { - log_error ("listen() failed: %s\n", strerror (errno)); - close (fd); - exit (1); - } - - if (opt.verbose) - log_info ("listening on socket `%s'\n", socket_name ); - - - fflush (NULL); - pid = fork (); - if (pid == (pid_t)-1) - { - log_fatal ("fork failed: %s\n", strerror (errno) ); - exit (1); - } - else if (pid) - { /* we are the parent */ - char *infostr; - - close (fd); - - /* create the info string: :: */ - if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1", - socket_name, (ulong)pid ) < 0) - { - log_error ("out of core\n"); - kill (pid, SIGTERM); - exit (1); - } - *socket_name = 0; /* don't let cleanup() remove the socket - - the child should do this from now on */ - if (argc) - { /* run the program given on the commandline */ - if (putenv (infostr)) - { - log_error ("failed to set environment: %s\n", - strerror (errno) ); - kill (pid, SIGTERM ); - exit (1); - } - execvp (argv[0], argv); - log_error ("failed to run the command: %s\n", strerror (errno)); - kill (pid, SIGTERM); - exit (1); - } - else - { - /* print the environment string, so that the caller can use - shell's eval to set it */ - if (csh_style) - { - *strchr (infostr, '=') = ' '; - printf ( "setenv %s\n", infostr); - } - else - { - printf ( "%s; export GPG_AGENT_INFO;\n", infostr); - } - free (infostr); - exit (0); - } - /*NEVER REACHED*/ - } /* end parent */ - - - /* this is the child */ - - /* detach from tty and put process into a new session */ - if (!nodetach ) - { - int i; - - /* close stdin, stdout and stderr unless it is the log stream */ - for (i=0; i <= 2; i++) - { - if ( log_get_fd () != i) - close (i); - } - if (setsid() == -1) - { - log_error ("setsid() failed: %s\n", strerror(errno) ); - cleanup (); - exit (1); - } - opt.running_detached = 1; - } - - if (chdir("/")) - { - log_error ("chdir to / failed: %s\n", strerror (errno)); - exit (1); - } - - -#ifdef USE_GNU_PTH - if (!disable_pth) - { - struct sigaction sa; - - if (!pth_init ()) - { - log_error ("failed to initialize the Pth library\n"); - exit (1); - } - - sa.sa_handler = SIG_IGN; - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sigaction (SIGPIPE, &sa, NULL); - handle_connections (fd); - } - else -#endif /*!USE_GNU_PTH*/ - /* setup signals */ - { - struct sigaction oact, nact; - - nact.sa_handler = cleanup_sh; - sigemptyset (&nact.sa_mask); - nact.sa_flags = 0; - - sigaction (SIGHUP, NULL, &oact); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGHUP, &nact, NULL); - sigaction( SIGTERM, NULL, &oact ); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGTERM, &nact, NULL); - nact.sa_handler = SIG_IGN; - sigaction (SIGPIPE, &nact, NULL); - sigaction (SIGINT, &nact, NULL); - - start_command_handler (fd, -1); - } - close (fd); - } - - return 0; -} - -void -agent_exit (int rc) -{ - /*FIXME: update_random_seed_file();*/ -#if 1 - /* at this time a bit annoying */ - if (opt.debug & DBG_MEMSTAT_VALUE) - { - gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); - gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); - } - if (opt.debug) - gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); -#endif - gcry_control (GCRYCTL_TERM_SECMEM ); - rc = rc? rc : log_get_errorcount(0)? 2 : 0; - exit (rc); -} - - -static void -reread_configuration (void) -{ - /* FIXME: Move parts of the option parsing to here. */ -} - - -static void -create_private_keys_directory (const char *home) -{ - char *fname; - struct stat statbuf; - - fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL); - if (stat (fname, &statbuf) && errno == ENOENT) - { - if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR )) - log_error (_("can't create directory `%s': %s\n"), - fname, strerror(errno) ); - else if (!opt.quiet) - log_info (_("directory `%s' created\n"), fname); - } - xfree (fname); -} - -/* Create the directory only if the supplied directory name is the - same as the default one. This way we avoid to create arbitrary - directories when a non-default home directory is used. To cope - with HOME, we compare only the suffix if we see that the default - homedir does start with a tilde. We don't stop here in case of - problems because other functions will throw an error anyway.*/ -static void -create_directories (void) -{ - struct stat statbuf; - const char *defhome = GNUPG_DEFAULT_HOMEDIR; - char *home; - - home = make_filename (opt.homedir, NULL); - if ( stat (home, &statbuf) ) - { - if (errno == ENOENT) - { - if ( (*defhome == '~' - && (strlen (home) >= strlen (defhome+1) - && !strcmp (home + strlen(home) - - strlen (defhome+1), defhome+1))) - || (*defhome != '~' && !strcmp (home, defhome) ) - ) - { - if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR )) - log_error (_("can't create directory `%s': %s\n"), - home, strerror(errno) ); - else - { - if (!opt.quiet) - log_info (_("directory `%s' created\n"), home); - create_private_keys_directory (home); - } - } - } - else - log_error ("error stat-ing `%s': %s\n", home, strerror (errno)); - } - else if ( !S_ISDIR(statbuf.st_mode)) - { - log_error ("can't use `%s' as home directory\n", home); - } - else /* exists and is a directory. */ - { - create_private_keys_directory (home); - } - xfree (home); -} - - - -#ifdef USE_GNU_PTH -static void -handle_signal (int signo) -{ - switch (signo) - { - case SIGHUP: - log_info ("SIGHUP received - " - "re-reading configuration and flushing cache\n"); - agent_flush_cache (); - reread_configuration (); - break; - - case SIGUSR1: - if (opt.verbose < 5) - opt.verbose++; - log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose); - break; - - case SIGUSR2: - if (opt.verbose) - opt.verbose--; - log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose ); - break; - - case SIGTERM: - if (!shutdown_pending) - log_info ("SIGTERM received - shutting down ...\n"); - else - log_info ("SIGTERM received - still %ld running threads\n", - pth_ctrl( PTH_CTRL_GETTHREADS )); - shutdown_pending++; - if (shutdown_pending > 2) - { - log_info ("shutdown forced\n"); - log_info ("%s %s stopped\n", strusage(11), strusage(13) ); - cleanup (); - agent_exit (0); - } - break; - - case SIGINT: - log_info ("SIGINT received - immediate shutdown\n"); - log_info( "%s %s stopped\n", strusage(11), strusage(13)); - cleanup (); - agent_exit (0); - break; - - default: - log_info ("signal %d received - no action defined\n", signo); - } -} - - -static void * -start_connection_thread (void *arg) -{ - int fd = (int)arg; - - if (opt.verbose) - log_info ("handler for fd %d started\n", fd); - start_command_handler (-1, fd); - if (opt.verbose) - log_info ("handler for fd %d terminated\n", fd); - - return NULL; -} - - -static void -handle_connections (int listen_fd) -{ - pth_attr_t tattr; - pth_event_t ev; - sigset_t sigs; - int signo; - struct sockaddr_un paddr; - socklen_t plen = sizeof( paddr ); - int fd; - - tattr = pth_attr_new(); - pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); - pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024); - pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent"); - - sigemptyset (&sigs ); - sigaddset (&sigs, SIGHUP); - sigaddset (&sigs, SIGUSR1); - sigaddset (&sigs, SIGUSR2); - sigaddset (&sigs, SIGINT); - sigaddset (&sigs, SIGTERM); - ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); - - for (;;) - { - if (shutdown_pending) - { - if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1) - break; /* ready */ - - /* Do not accept anymore connections and wait for existing - connections to terminate */ - signo = 0; - pth_wait (ev); - if (pth_event_occurred (ev) && signo) - handle_signal (signo); - continue; - } - - fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); - if (fd == -1) - { - if (pth_event_occurred (ev)) - { - handle_signal (signo); - continue; - } - log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); - pth_sleep(1); - continue; - } - - if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) - { - log_error ("error spawning connection handler: %s\n", - strerror (errno) ); - close (fd); - } - } - - pth_event_free (ev, PTH_FREE_ALL); - cleanup (); - log_info ("%s %s stopped\n", strusage(11), strusage(13)); -} -#endif /*USE_GNU_PTH*/ diff --git a/agent/learncard.c b/agent/learncard.c deleted file mode 100644 index 93229f4cf..000000000 --- a/agent/learncard.c +++ /dev/null @@ -1,380 +0,0 @@ -/* learncard.c - Handle the LEARN command - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" -#include "../assuan/assuan.h" - -struct keypair_info_s { - struct keypair_info_s *next; - int no_cert; - char *id; /* points into grip */ - char hexgrip[1]; -}; -typedef struct keypair_info_s *KEYPAIR_INFO; - -struct kpinfo_cb_parm_s { - int error; - KEYPAIR_INFO info; -}; - - -struct certinfo_s { - struct certinfo_s *next; - int type; - int done; - char id[1]; -}; -typedef struct certinfo_s *CERTINFO; - -struct certinfo_cb_parm_s { - int error; - CERTINFO info; -}; - - -static void -release_keypair_info (KEYPAIR_INFO info) -{ - while (info) - { - KEYPAIR_INFO tmp = info->next; - xfree (info); - info = tmp; - } -} - -static void -release_certinfo (CERTINFO info) -{ - while (info) - { - CERTINFO tmp = info->next; - xfree (info); - info = tmp; - } -} - - - -/* This callback is used by agent_card_leanr and passed the content of - all KEYPAIRINFO lines. It merely stores this data away */ -static void -kpinfo_cb (void *opaque, const char *line) -{ - struct kpinfo_cb_parm_s *parm = opaque; - KEYPAIR_INFO item; - char *p; - - if (parm->error) - return; /* no need to gather data after an error coccured */ - item = xtrycalloc (1, sizeof *item + strlen (line)); - if (!item) - { - parm->error = GNUPG_Out_Of_Core; - return; - } - strcpy (item->hexgrip, line); - for (p = item->hexgrip; hexdigitp (p); p++) - ; - if (p == item->hexgrip && *p == 'X' && spacep (p+1)) - { - item->no_cert = 1; - p++; - } - else if ((p - item->hexgrip) != 40 || !spacep (p)) - { /* not a 20 byte hex keygrip or not followed by a space */ - parm->error = GNUPG_Invalid_Response; - xfree (item); - return; - } - *p++ = 0; - while (spacep (p)) - p++; - item->id = p; - while (*p && !spacep (p)) - p++; - if (p == item->id) - { /* invalid ID string */ - parm->error = GNUPG_Invalid_Response; - xfree (item); - return; - } - *p = 0; /* ignore trailing stuff */ - - /* store it */ - item->next = parm->info; - parm->info = item; -} - - -/* This callback is used by agent_card_leanr and passed the content of - all CERTINFO lines. It merely stores this data away */ -static void -certinfo_cb (void *opaque, const char *line) -{ - struct certinfo_cb_parm_s *parm = opaque; - CERTINFO item; - int type; - char *p, *pend; - - if (parm->error) - return; /* no need to gather data after an error coccured */ - - type = strtol (line, &p, 10); - while (spacep (p)) - p++; - for (pend = p; *pend && !spacep (pend); pend++) - ; - if (p == pend || !*p) - { - parm->error = GNUPG_Invalid_Response; - return; - } - *pend = 0; /* ignore trailing stuff */ - - item = xtrycalloc (1, sizeof *item + strlen (p)); - if (!item) - { - parm->error = GNUPG_Out_Of_Core; - return; - } - item->type = type; - strcpy (item->id, p); - /* store it */ - item->next = parm->info; - parm->info = item; -} - - -/* Create an S-expression with the shadow info. */ -static unsigned char * -make_shadow_info (const char *serialno, const char *idstring) -{ - const char *s; - unsigned char *info, *p; - char numbuf[21]; - int n; - - for (s=serialno, n=0; *s && s[1]; s += 2) - n++; - - info = p = xtrymalloc (1 + 21 + n - + 21 + strlen (idstring) + 1 + 1); - *p++ = '('; - sprintf (numbuf, "%d:", n); - p = stpcpy (p, numbuf); - for (s=serialno; *s && s[1]; s += 2) - *p++ = xtoi_2 (s); - sprintf (numbuf, "%d:", strlen (idstring)); - p = stpcpy (p, numbuf); - p = stpcpy (p, idstring); - *p++ = ')'; - *p = 0; - return info; -} - -static int -send_cert_back (const char *id, void *assuan_context) -{ - int rc; - char *derbuf; - size_t derbuflen; - - rc = agent_card_readcert (id, &derbuf, &derbuflen); - if (rc) - { - log_error ("error reading certificate: %s\n", - gnupg_strerror (rc)); - return rc; - } - - rc = assuan_send_data (assuan_context, derbuf, derbuflen); - xfree (derbuf); - if (!rc) - rc = assuan_send_data (assuan_context, NULL, 0); - if (!rc) - rc = assuan_write_line (assuan_context, "END"); - if (rc) - { - log_error ("sending certificate failed: %s\n", - assuan_strerror (rc)); - return map_assuan_err (rc); - } - return 0; -} - -/* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new - certificates are send via Assuan */ -int -agent_handle_learn (void *assuan_context) -{ - int rc; - struct kpinfo_cb_parm_s parm; - struct certinfo_cb_parm_s cparm; - char *serialno = NULL; - KEYPAIR_INFO item; - unsigned char grip[20]; - char *p; - int i; - static int certtype_list[] = { - 101, /* trusted */ - 102, /* useful */ - 100, /* regular */ - -1 /* end of list */ - }; - - - memset (&parm, 0, sizeof parm); - memset (&cparm, 0, sizeof cparm); - - /* Check whether a card is present and get the serial number */ - rc = agent_card_serialno (&serialno); - if (rc) - goto leave; - - /* now gather all the availabe info */ - rc = agent_card_learn (kpinfo_cb, &parm, certinfo_cb, &cparm); - if (!rc && (parm.error || cparm.error)) - rc = parm.error? parm.error : cparm.error; - if (rc) - { - log_debug ("agent_card_learn failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - log_info ("card has S/N: %s\n", serialno); - - /* Write out the certificates in a standard order. */ - for (i=0; certtype_list[i] != -1; i++) - { - CERTINFO citem; - for (citem = cparm.info; citem; citem = citem->next) - { - if (certtype_list[i] != citem->type) - continue; - - if (opt.verbose) - log_info (" id: %s (type=%d)\n", - citem->id, citem->type); - - if (assuan_context) - { - rc = send_cert_back (citem->id, assuan_context); - if (rc) - goto leave; - citem->done = 1; - } - } - } - - for (item = parm.info; item; item = item->next) - { - unsigned char *pubkey, *shdkey; - size_t n; - - if (opt.verbose) - log_info (" id: %s (grip=%s)\n", item->id, item->hexgrip); - - if (item->no_cert) - continue; /* no public key yet available */ - - for (p=item->hexgrip, i=0; i < 20; p += 2, i++) - grip[i] = xtoi_2 (p); - - if (!agent_key_available (grip)) - continue; - - /* unknown - store it */ - rc = agent_card_readkey (item->id, &pubkey); - if (rc) - { - log_debug ("agent_card_readkey failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - { - unsigned char *shadow_info = make_shadow_info (serialno, item->id); - if (!shadow_info) - { - rc = GNUPG_Out_Of_Core; - xfree (pubkey); - goto leave; - } - rc = agent_shadow_key (pubkey, shadow_info, &shdkey); - xfree (shadow_info); - } - xfree (pubkey); - if (rc) - { - log_error ("shadowing the key failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - n = gcry_sexp_canon_len (shdkey, 0, NULL, NULL); - assert (n); - - rc = agent_write_private_key (grip, shdkey, n, 0); - xfree (shdkey); - if (rc) - { - log_error ("error writing key: %s\n", gnupg_strerror (rc)); - goto leave; - } - - if (opt.verbose) - log_info ("stored\n"); - - if (assuan_context) - { - CERTINFO citem; - - /* only send the certificate if we have not done so before */ - for (citem = cparm.info; citem; citem = citem->next) - { - if (!strcmp (citem->id, item->id)) - break; - } - if (!citem) - { - rc = send_cert_back (item->id, assuan_context); - if (rc) - goto leave; - } - } - } - - - leave: - xfree (serialno); - release_keypair_info (parm.info); - release_certinfo (cparm.info); - return rc; -} - - diff --git a/agent/minip12.c b/agent/minip12.c deleted file mode 100644 index d8d47336c..000000000 --- a/agent/minip12.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* minip12.c - A minilam pkcs-12 implementation. - * 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 -#endif -#include -#include -#include -#include -#include - -#undef TEST - -#ifdef TEST -#include -#include -#include -#endif - -#include "../jnlib/logging.h" -#include "minip12.h" - -#ifndef DIM -#define DIM(v) (sizeof(v)/sizeof((v)[0])) -#endif - -enum -{ - UNIVERSAL = 0, - APPLICATION = 1, - CONTEXT = 2, - PRIVATE = 3 -}; - - -enum -{ - TAG_NONE = 0, - TAG_BOOLEAN = 1, - TAG_INTEGER = 2, - TAG_BIT_STRING = 3, - TAG_OCTET_STRING = 4, - TAG_NULL = 5, - TAG_OBJECT_ID = 6, - TAG_OBJECT_DESCRIPTOR = 7, - TAG_EXTERNAL = 8, - TAG_REAL = 9, - TAG_ENUMERATED = 10, - TAG_EMBEDDED_PDV = 11, - TAG_UTF8_STRING = 12, - TAG_REALTIVE_OID = 13, - TAG_SEQUENCE = 16, - TAG_SET = 17, - TAG_NUMERIC_STRING = 18, - TAG_PRINTABLE_STRING = 19, - TAG_TELETEX_STRING = 20, - TAG_VIDEOTEX_STRING = 21, - TAG_IA5_STRING = 22, - TAG_UTC_TIME = 23, - TAG_GENERALIZED_TIME = 24, - TAG_GRAPHIC_STRING = 25, - TAG_VISIBLE_STRING = 26, - TAG_GENERAL_STRING = 27, - TAG_UNIVERSAL_STRING = 28, - TAG_CHARACTER_STRING = 29, - TAG_BMP_STRING = 30 -}; - - -static unsigned char const oid_data[9] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; -static unsigned char const oid_encryptedData[9] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; -static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 }; -static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 }; - -static unsigned char const oid_rsaEncryption[9] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; - - -static unsigned char const data_3desiter1024[30] = { - 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E, - 0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x02, 0x02, 0x04, 0x00 }; -#define DATA_3DESITER1024_SALT_OFF 18 - - -struct buffer_s -{ - unsigned char *buffer; - size_t length; -}; - - -struct tag_info -{ - int class; - int is_constructed; - unsigned long tag; - unsigned long length; /* length part of the TLV */ - int nhdr; - int ndef; /* It is an indefinite length */ -}; - - -/* Parse the buffer at the address BUFFER which is of SIZE and return - the tag and the length part from the TLV triplet. Update BUFFER - and SIZE on success. */ -static int -parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti) -{ - int c; - unsigned long tag; - const unsigned char *buf = *buffer; - size_t length = *size; - - ti->length = 0; - ti->ndef = 0; - ti->nhdr = 0; - - /* Get the tag */ - if (!length) - return -1; /* premature eof */ - c = *buf++; length--; - ti->nhdr++; - - ti->class = (c & 0xc0) >> 6; - ti->is_constructed = !!(c & 0x20); - tag = c & 0x1f; - - if (tag == 0x1f) - { - tag = 0; - do - { - tag <<= 7; - if (!length) - return -1; /* premature eof */ - c = *buf++; length--; - ti->nhdr++; - tag |= c & 0x7f; - } - while (c & 0x80); - } - ti->tag = tag; - - /* Get the length */ - if (!length) - return -1; /* prematureeof */ - c = *buf++; length--; - ti->nhdr++; - - if ( !(c & 0x80) ) - ti->length = c; - else if (c == 0x80) - ti->ndef = 1; - else if (c == 0xff) - return -1; /* forbidden length value */ - else - { - unsigned long len = 0; - int count = c & 0x7f; - - for (; count; count--) - { - len <<= 8; - if (!length) - return -1; /* premature_eof */ - c = *buf++; length--; - ti->nhdr++; - len |= c & 0xff; - } - ti->length = len; - } - - if (ti->class == UNIVERSAL && !ti->tag) - ti->length = 0; - - if (ti->length > length) - return -1; /* data larger than buffer. */ - - *buffer = buf; - *size = length; - return 0; -} - - -static int -string_to_key (int id, char *salt, int iter, const char *pw, - int req_keylen, unsigned char *keybuf) -{ - int rc, i, j; - GcryMDHd md; - GcryMPI num_b1 = NULL; - int pwlen; - unsigned char hash[20], buf_b[64], buf_i[128], *p; - size_t cur_keylen; - size_t n; - - cur_keylen = 0; - pwlen = strlen (pw); - if (pwlen > 63/2) - { - log_error ("password too long\n"); - return -1; - } - - /* Store salt and password in BUF_I */ - p = buf_i; - for(i=0; i < 64; i++) - *p++ = salt [i%8]; - for(i=j=0; i < 64; i += 2) - { - *p++ = 0; - *p++ = pw[j]; - if (++j > pwlen) /* Note, that we include the trailing zero */ - j = 0; - } - - for (;;) - { - md = gcry_md_open (GCRY_MD_SHA1, 0); - if (!md) - { - log_error ( "gcry_md_open failed: %s\n", gcry_strerror (-1)); - return -1; - } - for(i=0; i < 64; i++) - gcry_md_putc (md, id); - gcry_md_write (md, buf_i, 128); - memcpy (hash, gcry_md_read (md, 0), 20); - gcry_md_close (md); - for (i=1; i < iter; i++) - gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20); - - for (i=0; i < 20 && cur_keylen < req_keylen; i++) - keybuf[cur_keylen++] = hash[i]; - if (cur_keylen == req_keylen) - { - gcry_mpi_release (num_b1); - return 0; /* ready */ - } - - /* need more bytes. */ - for(i=0; i < 64; i++) - buf_b[i] = hash[i % 20]; - n = 64; - rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, &n); - if (rc) - { - log_error ( "gcry_mpi_scan failed: %s\n", gcry_strerror (rc)); - return -1; - } - gcry_mpi_add_ui (num_b1, num_b1, 1); - for (i=0; i < 128; i += 64) - { - GcryMPI num_ij; - - n = 64; - rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, &n); - if (rc) - { - log_error ( "gcry_mpi_scan failed: %s\n", - gcry_strerror (rc)); - return -1; - } - gcry_mpi_add (num_ij, num_ij, num_b1); - gcry_mpi_clear_highbit (num_ij, 64*8); - n = 64; - rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, &n, num_ij); - if (rc) - { - log_error ( "gcry_mpi_print failed: %s\n", - gcry_strerror (rc)); - return -1; - } - gcry_mpi_release (num_ij); - } - } -} - - -static int -set_key_iv (GcryCipherHd chd, char *salt, int iter, const char *pw) -{ - unsigned char keybuf[24]; - int rc; - - if (string_to_key (1, salt, iter, pw, 24, keybuf)) - return -1; - rc = gcry_cipher_setkey (chd, keybuf, 24); - if (rc) - { - log_error ( "gcry_cipher_setkey failed: %s\n", gcry_strerror (rc)); - return -1; - } - - if (string_to_key (2, salt, iter, pw, 8, keybuf)) - return -1; - rc = gcry_cipher_setiv (chd, keybuf, 8); - if (rc) - { - log_error ("gcry_cipher_setiv failed: %s\n", gcry_strerror (rc)); - return -1; - } - return 0; -} - - -static void -crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, - const char *pw, int encrypt) -{ - GcryCipherHd chd; - int rc; - - chd = gcry_cipher_open (GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); - if (!chd) - { - log_error ( "gcry_cipher_open failed: %s\n", gcry_strerror(-1)); - return; - } - if (set_key_iv (chd, salt, iter, pw)) - goto leave; - - rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0) - : gcry_cipher_decrypt (chd, buffer, length, NULL, 0); - - if (rc) - { - log_error ( "en/de-crytion failed: %s\n", gcry_strerror (rc)); - goto leave; - } - -/* { */ -/* FILE *fp = fopen("inner.der", "wb"); */ -/* fwrite (buffer, 1, length, fp); */ -/* fclose (fp); */ -/* } */ - - leave: - gcry_cipher_close (chd); -} - - - - -static int -parse_bag_encrypted_data (const unsigned char *buffer, size_t length, - int startoffset) -{ - struct tag_info ti; - const unsigned char *p = buffer; - size_t n = length; - const char *where; - - where = "start"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != CONTEXT || ti.tag) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_SEQUENCE) - goto bailout; - - where = "bag.encryptedData.version"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 0) - goto bailout; - p++; n--; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_SEQUENCE) - goto bailout; - - where = "bag.encryptedData.data"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data) - || memcmp (p, oid_data, DIM(oid_data))) - goto bailout; - p += DIM(oid_data); - n -= DIM(oid_data); - - /* fixme: continue parsing */ - - return 0; - bailout: - log_error ("encrptedData error at \"%s\", offset %u\n", - where, (p - buffer)+startoffset); - return -1; -} - -static GcryMPI * -parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, - const char *pw) -{ - int rc; - struct tag_info ti; - const unsigned char *p = buffer; - size_t n = length; - const char *where; - char salt[8]; - unsigned int iter; - int len; - unsigned char *plain = NULL; - GcryMPI *result = NULL; - int result_count, i; - - where = "start"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != CONTEXT || ti.tag) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING) - goto bailout; - - where = "data.outerseqs"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - - where = "data.objectidentifier"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_OBJECT_ID - || ti.length != DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag) - || memcmp (p, oid_pkcs_12_pkcs_8ShroudedKeyBag, - DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag))) - goto bailout; - p += DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag); - n -= DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag); - - where = "shrouded,outerseqs"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != CONTEXT || ti.tag) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_OBJECT_ID - || ti.length != DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC) - || memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC, - DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC))) - goto bailout; - p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC); - n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC); - - where = "3des-params"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 ) - goto bailout; - memcpy (salt, p, 8); - p += 8; - n -= 8; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_INTEGER || !ti.length ) - goto bailout; - for (iter=0; ti.length; ti.length--) - { - iter <<= 8; - iter |= (*p++) & 0xff; - n--; - } - - where = "3des-ciphertext"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length ) - goto bailout; - - log_info ("%lu bytes of 3DES encrypted text\n", ti.length); - - plain = gcry_malloc_secure (ti.length); - if (!plain) - { - log_error ("error allocating decryption buffer\n"); - goto bailout; - } - memcpy (plain, p, ti.length); - crypt_block (plain, ti.length, salt, iter, pw, 0); - n = ti.length; - startoffset = 0; - buffer = p = plain; - - where = "decrypted-text"; - if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER - || ti.length != 1 || *p) - goto bailout; - p++; n--; - if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - len = ti.length; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (len < ti.nhdr) - goto bailout; - len -= ti.nhdr; - if (ti.class || ti.tag != TAG_OBJECT_ID - || ti.length != DIM(oid_rsaEncryption) - || memcmp (p, oid_rsaEncryption, - DIM(oid_rsaEncryption))) - goto bailout; - p += DIM (oid_rsaEncryption); - n -= DIM (oid_rsaEncryption); - if (len < ti.length) - goto bailout; - len -= ti.length; - if (n < len) - goto bailout; - p += len; - n -= len; - if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_OCTET_STRING) - goto bailout; - if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - len = ti.length; - - result = gcry_calloc (10, sizeof *result); - if (!result) - { - log_error ( "error allocating result array\n"); - goto bailout; - } - result_count = 0; - - where = "reading.key-parameters"; - for (result_count=0; len && result_count < 9;) - { - int dummy_n; - - if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER) - goto bailout; - if (len < ti.nhdr) - goto bailout; - len -= ti.nhdr; - if (len < ti.length) - goto bailout; - len -= ti.length; - dummy_n = ti.length; - if (!result_count && ti.length == 1 && !*p) - ; /* ignore the very first one if it is a 0 */ - else - { - rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p, - &dummy_n); - if (rc) - { - log_error ("error parsing key parameter: %s\n", - gcry_strerror (rc)); - goto bailout; - } - result_count++; - } - p += ti.length; - n -= ti.length; - } - if (len) - goto bailout; - - return result; - - bailout: - gcry_free (plain); - if (result) - { - for (i=0; result[i]; i++) - gcry_mpi_release (result[i]); - gcry_free (result); - } - log_error ( "data error at \"%s\", offset %u\n", - where, (p - buffer) + startoffset); - return NULL; -} - - -/* Parse a PKCS12 object and return an array of MPI representing the - secret key parameters. This is a very limited inplementation in - that it is only able to look for 3DES encoded enctyptedData and - tries to extract the first private key object it finds. In case of - an error NULL is returned. */ -GcryMPI * -p12_parse (const unsigned char *buffer, size_t length, const char *pw) -{ - struct tag_info ti; - const unsigned char *p = buffer; - size_t n = length; - const char *where; - int bagseqlength, len; - - where = "pfx"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_SEQUENCE) - goto bailout; - - where = "pfxVersion"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 3) - goto bailout; - p++; n--; - - where = "authSave"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data) - || memcmp (p, oid_data, DIM(oid_data))) - goto bailout; - p += DIM(oid_data); - n -= DIM(oid_data); - - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != CONTEXT || ti.tag) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING) - goto bailout; - - where = "bags"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE) - goto bailout; - bagseqlength = ti.length; - while (bagseqlength) - { - /*log_debug ( "at offset %u\n", (p - buffer));*/ - where = "bag-sequence"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE) - goto bailout; - - if (bagseqlength < ti.nhdr) - goto bailout; - bagseqlength -= ti.nhdr; - if (bagseqlength < ti.length) - goto bailout; - bagseqlength -= ti.length; - len = ti.length; - - if (parse_tag (&p, &n, &ti)) - goto bailout; - len -= ti.nhdr; - if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData) - && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData))) - { - p += DIM(oid_encryptedData); - n -= DIM(oid_encryptedData); - len -= DIM(oid_encryptedData); - where = "bag.encryptedData"; - if (parse_bag_encrypted_data (p, n, (p - buffer))) - goto bailout; - } - else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data) - && !memcmp (p, oid_data, DIM(oid_data))) - { - p += DIM(oid_data); - n -= DIM(oid_data); - len -= DIM(oid_data); - return parse_bag_data (p, n, (p-buffer), pw); - } - else - log_info ( "unknown bag type - skipped\n"); - - if (len < 0 || len > n) - goto bailout; - p += len; - n -= len; - } - - return NULL; - bailout: - log_error ("error at \"%s\", offset %u\n", where, (p - buffer)); - return NULL; -} - - - -static size_t -compute_tag_length (size_t n) -{ - int needed = 0; - - if (n < 128) - needed += 2; /* tag and one length byte */ - else if (n < 256) - needed += 3; /* tag, number of length bytes, 1 length byte */ - else if (n < 65536) - needed += 4; /* tag, number of length bytes, 2 length bytes */ - else - { - log_error ("object too larger to encode\n"); - return 0; - } - return needed; -} - -static unsigned char * -store_tag_length (unsigned char *p, int tag, size_t n) -{ - if (tag == TAG_SEQUENCE) - tag |= 0x20; /* constructed */ - - *p++ = tag; - if (n < 128) - *p++ = n; - else if (n < 256) - { - *p++ = 0x81; - *p++ = n; - } - else if (n < 65536) - { - *p++ = 0x82; - *p++ = n >> 8; - *p++ = n; - } - - return p; -} - - -/* Create the final PKCS-12 object from the sequences contained in - SEQLIST. That array is terminated with an NULL object */ -static unsigned char * -create_final (struct buffer_s *sequences, size_t *r_length) -{ - int i; - size_t needed = 0; - size_t n, outseqlen, notsooutseqlen, out0taglen, octstrlen, inseqlen; - unsigned char *result, *p; - size_t resultlen; - - for (i=0; sequences[i].buffer; i++) - needed += sequences[i].length; - /* This goes into a sequences. */ - inseqlen = needed; - n = compute_tag_length (needed); - needed += n; - /* And encapsulate all in an octet string. */ - octstrlen = needed; - n = compute_tag_length (needed); - needed += n; - /* And tag it with [0]. */ - out0taglen = needed; - n = compute_tag_length (needed); - needed += n; - /* Prepend an data OID. */ - needed += 2 + DIM (oid_data); - /* This all into a sequences. */ - notsooutseqlen = needed; - n = compute_tag_length (needed); - needed += n; - /* Prepend the version integer 3. */ - needed += 3; - /* And the final sequence. */ - outseqlen = needed; - n = compute_tag_length (needed); - needed += n; - - result = gcry_malloc (needed); - if (!result) - { - log_error ("error allocating buffer\n"); - return NULL; - } - p = result; - - /* Store the very outer sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, outseqlen); - /* Store the version integer 3. */ - *p++ = TAG_INTEGER; - *p++ = 1; - *p++ = 3; - /* Store another sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, notsooutseqlen); - /* Store the data OID. */ - p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); - memcpy (p, oid_data, DIM (oid_data)); - p += DIM (oid_data); - /* Next comes a context tag. */ - p = store_tag_length (p, 0xa0, out0taglen); - /* And an octet string. */ - p = store_tag_length (p, TAG_OCTET_STRING, octstrlen); - /* And the inner sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, inseqlen); - /* And append all the buffers. */ - for (i=0; sequences[i].buffer; i++) - { - memcpy (p, sequences[i].buffer, sequences[i].length); - p += sequences[i].length; - } - - /* Ready. */ - resultlen = p - result; - if (needed != resultlen) - log_debug ("length mismatch: %u, %u\n", needed, resultlen); - - *r_length = resultlen; - return result; -} - - -/* Expect the RSA key parameters in KPARMS and a password in - PW. Create a PKCS structure from it and return it as well as the - length in R_LENGTH; return NULL in case of an error. */ -unsigned char * -p12_build (GcryMPI *kparms, const char *pw, size_t *r_length) -{ - int rc, i; - size_t needed, n; - unsigned char *plain, *p, *cipher; - size_t plainlen, cipherlen; - size_t outseqlen, oidseqlen, octstrlen, inseqlen; - size_t out0taglen, in0taglen, outoctstrlen; - size_t aseq1len, aseq2len, aseq3len; - char salt[8]; - - needed = 3; /* The version(?) integer of value 0. */ - for (i=0; kparms[i]; i++) - { - n = 0; - rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, &n, kparms[i]); - if (rc) - { - log_error ("error formatting parameter: %s\n", gcry_strerror (rc)); - return NULL; - } - needed += n; - n = compute_tag_length (n); - if (!n) - return NULL; - needed += n; - } - if (i != 8) - { - log_error ("invalid paramters for p12_build\n"); - return NULL; - } - /* Now this all goes into a sequence. */ - inseqlen = needed; - n = compute_tag_length (needed); - if (!n) - return NULL; - needed += n; - /* Encapsulate all into an octet string. */ - octstrlen = needed; - n = compute_tag_length (needed); - if (!n) - return NULL; - needed += n; - /* Prepend the object identifier sequence. */ - oidseqlen = 2 + DIM (oid_rsaEncryption) + 2; - needed += 2 + oidseqlen; - /* The version number. */ - needed += 3; - /* And finally put the whole thing into a sequence. */ - outseqlen = needed; - n = compute_tag_length (needed); - if (!n) - return NULL; - needed += n; - - /* allocate 8 extra bytes for padding */ - plain = gcry_malloc_secure (needed+8); - if (!plain) - { - log_error ("error allocating encryption buffer\n"); - return NULL; - } - - /* And now fill the plaintext buffer. */ - p = plain; - p = store_tag_length (p, TAG_SEQUENCE, outseqlen); - /* Store version. */ - *p++ = TAG_INTEGER; - *p++ = 1; - *p++ = 0; - /* Store object identifier sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, oidseqlen); - p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption)); - memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption)); - p += DIM (oid_rsaEncryption); - *p++ = TAG_NULL; - *p++ = 0; - /* Start with the octet string. */ - p = store_tag_length (p, TAG_OCTET_STRING, octstrlen); - p = store_tag_length (p, TAG_SEQUENCE, inseqlen); - /* Store the key parameters. */ - *p++ = TAG_INTEGER; - *p++ = 1; - *p++ = 0; - for (i=0; kparms[i]; i++) - { - n = 0; - rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, &n, kparms[i]); - if (rc) - { - log_error ("oops: error formatting parameter: %s\n", - gcry_strerror (rc)); - gcry_free (plain); - return NULL; - } - p = store_tag_length (p, TAG_INTEGER, n); - - n = plain + needed - p; - rc = gcry_mpi_print (GCRYMPI_FMT_STD, p, &n, kparms[i]); - if (rc) - { - log_error ("oops: error storing parameter: %s\n", - gcry_strerror (rc)); - gcry_free (plain); - return NULL; - } - p += n; - } - - plainlen = p - plain; - assert (needed == plainlen); - /* Append some pad characters; we already allocated extra space. */ - n = 8 - plainlen % 8; - for (;(plainlen % 8); plainlen++) - *p++ = n; - - { - FILE *fp = fopen("inner-out.der", "wb"); - fwrite (plain, 1, plainlen, fp); - fclose (fp); - } - - - /* Encrypt it and prepend a lot of stupid things. */ - gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); - crypt_block (plain, plainlen, salt, 1024, pw, 1); - /* the data goes into an octet string. */ - needed = compute_tag_length (plainlen); - needed += plainlen; - /* we prepend the the algorithm identifier (we use a pre-encoded one)*/ - needed += DIM (data_3desiter1024); - /* we put a sequence around. */ - aseq3len = needed; - needed += compute_tag_length (needed); - /* Prepend it with a [0] tag. */ - in0taglen = needed; - needed += compute_tag_length (needed); - /* Prepend that shroudedKeyBag OID. */ - needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); - /* Put it all into two sequence. */ - aseq2len = needed; - needed += compute_tag_length ( needed); - aseq1len = needed; - needed += compute_tag_length (needed); - /* This all goes into an octet string. */ - outoctstrlen = needed; - needed += compute_tag_length (needed); - /* Prepend it with a [0] tag. */ - out0taglen = needed; - needed += compute_tag_length (needed); - /* Prepend the data OID. */ - needed += 2 + DIM (oid_data); - /* And a sequence. */ - outseqlen = needed; - needed += compute_tag_length (needed); - - cipher = gcry_malloc (needed); - if (!cipher) - { - log_error ("error allocating buffer\n"); - gcry_free (plain); - return NULL; - } - p = cipher; - /* Store the first sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, outseqlen); - /* Store the data OID. */ - p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); - memcpy (p, oid_data, DIM (oid_data)); - p += DIM (oid_data); - /* Next comes a context tag. */ - p = store_tag_length (p, 0xa0, out0taglen); - /* And an octet string. */ - p = store_tag_length (p, TAG_OCTET_STRING, outoctstrlen); - /* Two sequences. */ - p = store_tag_length (p, TAG_SEQUENCE, aseq1len); - p = store_tag_length (p, TAG_SEQUENCE, aseq2len); - /* Store the shroudedKeyBag OID. */ - p = store_tag_length (p, TAG_OBJECT_ID, - DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); - memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag, - DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); - p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); - /* Next comes a context tag. */ - p = store_tag_length (p, 0xa0, in0taglen); - /* And a sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, aseq3len); - /* Now for the pre-encoded algorithm indentifier and the salt. */ - memcpy (p, data_3desiter1024, DIM (data_3desiter1024)); - memcpy (p + DATA_3DESITER1024_SALT_OFF, salt, 8); - p += DIM (data_3desiter1024); - /* And finally the octet string with the encrypted data. */ - p = store_tag_length (p, TAG_OCTET_STRING, plainlen); - memcpy (p, plain, plainlen); - p += plainlen; - cipherlen = p - cipher; - - if (needed != cipherlen) - log_debug ("length mismatch: %u, %u\n", needed, cipherlen); - gcry_free (plain); - - { - struct buffer_s seqlist[2]; - - seqlist[0].buffer = cipher; - seqlist[0].length = cipherlen; - seqlist[1].buffer = NULL; - seqlist[1].length = 0; - - cipher = create_final (seqlist, &cipherlen); - gcry_free (seqlist[0].buffer); - } - - *r_length = cipherlen; - return cipher; -} - - -#ifdef TEST -int -main (int argc, char **argv) -{ - FILE *fp; - struct stat st; - char *buf; - size_t buflen; - GcryMPI *result; - - if (argc != 3) - { - fprintf (stderr, "usage: testp12 file passphrase\n"); - return 1; - } - - gcry_control (GCRYCTL_DISABLE_SECMEM, NULL); - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL); - - fp = fopen (argv[1], "rb"); - if (!fp) - { - fprintf (stderr, "can't open `%s': %s\n", argv[1], strerror (errno)); - return 1; - } - - if (fstat (fileno(fp), &st)) - { - fprintf (stderr, "can't stat `%s': %s\n", argv[1], strerror (errno)); - return 1; - } - - buflen = st.st_size; - buf = gcry_malloc (buflen+1); - if (!buf || fread (buf, buflen, 1, fp) != 1) - { - fprintf (stderr, "error reading `%s': %s\n", argv[1], strerror (errno)); - return 1; - } - fclose (fp); - - result = p12_parse (buf, buflen, argv[2]); - if (result) - { - int i, rc; - char *buf; - - for (i=0; result[i]; i++) - { - rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, - NULL, result[i]); - if (rc) - printf ("%d: [error printing number: %s]\n", - i, gcry_strerror (rc)); - else - { - printf ("%d: %s\n", i, buf); - gcry_free (buf); - } - } - } - - return 0; - -} -#endif /* TEST */ diff --git a/agent/minip12.h b/agent/minip12.h deleted file mode 100644 index 8573a2db0..000000000 --- a/agent/minip12.h +++ /dev/null @@ -1,32 +0,0 @@ -/* minip12.h - Global definitions for the minimal pkcs-12 implementation. - * 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 MINIP12_H -#define MINIP12_H - -#include - -GcryMPI *p12_parse (const unsigned char *buffer, size_t length, - const char *pw); - -unsigned char *p12_build (GcryMPI *kparms, const char *pw, size_t *r_length); - - -#endif /*MINIP12_H*/ diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c deleted file mode 100644 index 6add3d467..000000000 --- a/agent/pkdecrypt.c +++ /dev/null @@ -1,138 +0,0 @@ -/* pkdecrypt.c - public key decryption (well, acually using a secret key) - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" - - -/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp. - Try to get the key from CTRL and write the decoded stuff back to - OUTFP. */ -int -agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, - FILE *outfp) -{ - GCRY_SEXP s_skey = NULL, s_cipher = NULL, s_plain = NULL; - unsigned char *shadow_info = NULL; - int rc; - char *buf = NULL; - size_t len; - - if (!ctrl->have_keygrip) - { - log_error ("speculative decryption not yet supported\n"); - rc = seterr (No_Secret_Key); - goto leave; - } - - rc = gcry_sexp_sscan (&s_cipher, NULL, ciphertext, ciphertextlen); - if (rc) - { - log_error ("failed to convert ciphertext: %s\n", gcry_strerror (rc)); - rc = seterr (Invalid_Data); - goto leave; - } - - if (DBG_CRYPTO) - { - log_printhex ("keygrip:", ctrl->keygrip, 20); - log_printhex ("cipher: ", ciphertext, ciphertextlen); - } - s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, 0); - if (!s_skey && !shadow_info) - { - log_error ("failed to read the secret key\n"); - rc = seterr (No_Secret_Key); - goto leave; - } - - if (!s_skey) - { /* divert operation to the smartcard */ - - if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL)) - { - rc = GNUPG_Invalid_Sexp; - goto leave; - } - - rc = divert_pkdecrypt (ciphertext, shadow_info, &buf, &len ); - if (rc) - { - log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - /* FIXME: don't use buffering and change the protocol to return - a complete S-expression and not just a part. */ - fprintf (outfp, "%u:", (unsigned int)len); - fwrite (buf, 1, len, outfp); - putc (0, outfp); - } - else - { /* no smartcard, but a private key */ - if (DBG_CRYPTO) - { - log_debug ("skey: "); - gcry_sexp_dump (s_skey); - } - - rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey); - if (rc) - { - log_error ("decryption failed: %s\n", gcry_strerror (rc)); - rc = map_gcry_err (rc); - goto leave; - } - - if (DBG_CRYPTO) - { - log_debug ("plain: "); - gcry_sexp_dump (s_plain); - } - len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xmalloc (len); - len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - /* FIXME: we must make sure that no buffering takes place or we are - in full control of the buffer memory (easy to do) - should go - into assuan. */ - fwrite (buf, 1, len, outfp); - } - - - leave: - gcry_sexp_release (s_skey); - gcry_sexp_release (s_plain); - gcry_sexp_release (s_cipher); - xfree (buf); - xfree (shadow_info); - return rc; -} - - diff --git a/agent/pksign.c b/agent/pksign.c deleted file mode 100644 index 2acc63dd9..000000000 --- a/agent/pksign.c +++ /dev/null @@ -1,183 +0,0 @@ -/* pksign.c - public key signing (well, acually using a secret key) - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" - - -static int -do_encode_md (const unsigned char *digest, size_t digestlen, int algo, - unsigned int nbits, GCRY_MPI *r_val) -{ - int nframe = (nbits+7) / 8; - byte *frame; - int i, n; - byte asn[100]; - size_t asnlen; - - asnlen = DIM(asn); - if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) - { - log_error ("no object identifier for algo %d\n", algo); - return GNUPG_Internal_Error; - } - - if (digestlen + asnlen + 4 > nframe ) - { - log_error ("can't encode a %d bit MD into a %d bits frame\n", - (int)(digestlen*8), (int)nbits); - return GNUPG_Internal_Error; - } - - /* We encode the MD in this way: - * - * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = xtrymalloc (nframe); - if (!frame) - return GNUPG_Out_Of_Core; - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - digestlen - asnlen -3 ; - assert ( i > 1 ); - memset ( frame+n, 0xff, i ); n += i; - frame[n++] = 0; - memcpy ( frame+n, asn, asnlen ); n += asnlen; - memcpy ( frame+n, digest, digestlen ); n += digestlen; - assert ( n == nframe ); - if (DBG_CRYPTO) - log_printhex ("encoded hash:", frame, nframe); - - gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe); - xfree (frame); - return 0; -} - - -/* SIGN whatever information we have accumulated in CTRL and write it - back to OUTFP. */ -int -agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) -{ - GCRY_SEXP s_skey = NULL, s_hash = NULL, s_sig = NULL; - GCRY_MPI frame = NULL; - unsigned char *shadow_info = NULL; - int rc; - char *buf = NULL; - size_t len; - - if (!ctrl->have_keygrip) - return seterr (No_Secret_Key); - - s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, ignore_cache); - if (!s_skey && !shadow_info) - { - log_error ("failed to read the secret key\n"); - rc = seterr (No_Secret_Key); - goto leave; - } - - if (!s_skey) - { /* divert operation to the smartcard */ - unsigned char *sigbuf; - - rc = divert_pksign (ctrl->digest.value, - ctrl->digest.valuelen, - ctrl->digest.algo, - shadow_info, &sigbuf); - if (rc) - { - log_error ("smartcard signing failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL); - assert (len); - buf = sigbuf; - } - else - { /* no smartcard, but a private key */ - - /* put the hash into a sexp */ - rc = do_encode_md (ctrl->digest.value, - ctrl->digest.valuelen, - ctrl->digest.algo, - gcry_pk_get_nbits (s_skey), - &frame); - if (rc) - goto leave; - if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) - BUG (); - - if (DBG_CRYPTO) - { - log_debug ("skey: "); - gcry_sexp_dump (s_skey); - } - - /* sign */ - rc = gcry_pk_sign (&s_sig, s_hash, s_skey); - if (rc) - { - log_error ("signing failed: %s\n", gcry_strerror (rc)); - rc = map_gcry_err (rc); - goto leave; - } - - if (DBG_CRYPTO) - { - log_debug ("result: "); - gcry_sexp_dump (s_sig); - } - - len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xmalloc (len); - len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - } - - /* FIXME: we must make sure that no buffering takes place or we are - in full control of the buffer memory (easy to do) - should go - into assuan. */ - fwrite (buf, 1, len, outfp); - - leave: - gcry_sexp_release (s_skey); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_sig); - gcry_mpi_release (frame); - xfree (buf); - xfree (shadow_info); - return rc; -} - - diff --git a/agent/protect-tool.c b/agent/protect-tool.c deleted file mode 100644 index 1d706ea2b..000000000 --- a/agent/protect-tool.c +++ /dev/null @@ -1,977 +0,0 @@ -/* protect-tool.c - A tool to test the secret key protection - * 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 - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define JNLIB_NEED_LOG_LOGV -#include "agent.h" -#include "minip12.h" -#include "simple-pwquery.h" -#include "i18n.h" - -enum cmd_and_opt_values -{ aNull = 0, - oVerbose = 'v', - oArmor = 'a', - oPassphrase = 'P', - - oProtect = 'p', - oUnprotect = 'u', - - oNoVerbose = 500, - oShadow, - oShowShadowInfo, - oShowKeygrip, - - oP12Import, - oP12Export, - oStore, - oForce, - -aTest }; - -struct rsa_secret_key_s - { - MPI n; /* public modulus */ - MPI e; /* public exponent */ - MPI d; /* exponent */ - MPI p; /* prime p. */ - MPI q; /* prime q. */ - MPI u; /* inverse of p mod q. */ - }; - - -static int opt_armor; -static int opt_store; -static int opt_force; -static const char *passphrase; - -static const char *get_passphrase (void); -static int store_private_key (const unsigned char *grip, - const void *buffer, size_t length, int force); - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, N_("@Options:\n ") }, - - { oVerbose, "verbose", 0, "verbose" }, - { oArmor, "armor", 0, "write output in advanced format" }, - { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, - { oProtect, "protect", 256, "protect a private key"}, - { oUnprotect, "unprotect", 256, "unprotect a private key"}, - { oShadow, "shadow", 256, "create a shadow entry for a priblic key"}, - { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"}, - { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""}, - - { oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"}, - { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"}, - { oStore, "store", 0, "store the created key in the appropriate place"}, - { oForce, "force", 0, "force overwriting"}, - {0} -}; - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "gpg-protect-tool (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n"); - break; - case 41: p = _("Syntax: gpg-protect-tool [options] [args]]\n" - "Secret key maintenance tool\n"); - break; - - default: p = NULL; - } - return p; -} - - - -static void -i18n_init (void) -{ -#ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); -#else -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -#endif -#endif -} - - - -/* Used by gcry for logging */ -static void -my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) -{ - /* translate the log levels */ - switch (level) - { - case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; - case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; - case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; - case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; - case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; - case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; - case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; - default: level = JNLIB_LOG_ERROR; break; } - log_logv (level, fmt, arg_ptr); -} - - -/* static void */ -/* print_mpi (const char *text, GcryMPI a) */ -/* { */ -/* char *buf; */ -/* void *bufaddr = &buf; */ -/* int rc; */ - -/* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */ -/* if (rc) */ -/* log_info ("%s: [error printing number: %s]\n", text, gcry_strerror (rc)); */ -/* else */ -/* { */ -/* log_info ("%s: %s\n", text, buf); */ -/* gcry_free (buf); */ -/* } */ -/* } */ - - - -static unsigned char * -make_canonical (const char *fname, const char *buf, size_t buflen) -{ - int rc; - size_t erroff, len; - GCRY_SEXP sexp; - unsigned char *result; - - rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); - if (rc) - { - log_error ("invalid S-Expression in `%s' (off=%u): %s\n", - fname, (unsigned int)erroff, gcry_strerror (rc)); - return NULL; - } - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - result = xmalloc (len); - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len); - assert (len); - gcry_sexp_release (sexp); - return result; -} - -static char * -make_advanced (const unsigned char *buf, size_t buflen) -{ - int rc; - size_t erroff, len; - GCRY_SEXP sexp; - unsigned char *result; - - rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); - if (rc) - { - log_error ("invalid canonical S-Expression (off=%u): %s\n", - (unsigned int)erroff, gcry_strerror (rc)); - return NULL; - } - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); - assert (len); - result = xmalloc (len); - len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len); - assert (len); - gcry_sexp_release (sexp); - return result; -} - - -static char * -read_file (const char *fname, size_t *r_length) -{ - FILE *fp; - struct stat st; - char *buf; - size_t buflen; - - fp = fopen (fname, "rb"); - if (!fp) - { - log_error ("can't open `%s': %s\n", fname, strerror (errno)); - return NULL; - } - - if (fstat (fileno(fp), &st)) - { - log_error ("can't stat `%s': %s\n", fname, strerror (errno)); - fclose (fp); - return NULL; - } - - buflen = st.st_size; - buf = xmalloc (buflen+1); - if (fread (buf, buflen, 1, fp) != 1) - { - log_error ("error reading `%s': %s\n", fname, strerror (errno)); - fclose (fp); - xfree (buf); - return NULL; - } - fclose (fp); - - *r_length = buflen; - return buf; -} - - -static unsigned char * -read_key (const char *fname) -{ - char *buf; - size_t buflen; - unsigned char *key; - - buf = read_file (fname, &buflen); - key = make_canonical (fname, buf, buflen); - xfree (buf); - return key; -} - - - -static void -read_and_protect (const char *fname) -{ - int rc; - unsigned char *key; - unsigned char *result; - size_t resultlen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_protect (key, get_passphrase (), &result, &resultlen); - xfree (key); - if (rc) - { - log_error ("protecting the key failed: %s\n", gnupg_strerror (rc)); - return; - } - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - fwrite (result, resultlen, 1, stdout); - xfree (result); -} - - -static void -read_and_unprotect (const char *fname) -{ - int rc; - unsigned char *key; - unsigned char *result; - size_t resultlen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_unprotect (key, get_passphrase (), &result, &resultlen); - xfree (key); - if (rc) - { - log_error ("unprotecting the key failed: %s\n", gnupg_strerror (rc)); - return; - } - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - fwrite (result, resultlen, 1, stdout); - xfree (result); -} - - - -static void -read_and_shadow (const char *fname) -{ - int rc; - unsigned char *key; - unsigned char *result; - size_t resultlen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_shadow_key (key, "(8:313233342:43)", &result); - xfree (key); - if (rc) - { - log_error ("shadowing the key failed: %s\n", gnupg_strerror (rc)); - return; - } - resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL); - assert (resultlen); - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - fwrite (result, resultlen, 1, stdout); - xfree (result); -} - -static void -show_shadow_info (const char *fname) -{ - int rc; - unsigned char *key; - const unsigned char *info; - size_t infolen; - - key = read_key (fname); - if (!key) - return; - - rc = agent_get_shadow_info (key, &info); - xfree (key); - if (rc) - { - log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc)); - return; - } - infolen = gcry_sexp_canon_len (info, 0, NULL,NULL); - assert (infolen); - - if (opt_armor) - { - char *p = make_advanced (info, infolen); - if (!p) - return; - fwrite (p, strlen (p), 1, stdout); - xfree (p); - } - else - fwrite (info, infolen, 1, stdout); -} - - -static void -show_file (const char *fname) -{ - unsigned char *key; - size_t keylen; - char *p; - - key = read_key (fname); - if (!key) - return; - - keylen = gcry_sexp_canon_len (key, 0, NULL,NULL); - assert (keylen); - - p = make_advanced (key, keylen); - xfree (key); - if (p) - { - fwrite (p, strlen (p), 1, stdout); - xfree (p); - } -} - -static void -show_keygrip (const char *fname) -{ - unsigned char *key; - GcrySexp private; - unsigned char grip[20]; - int i; - - key = read_key (fname); - if (!key) - return; - - if (gcry_sexp_new (&private, key, 0, 0)) - { - log_error ("gcry_sexp_new failed\n"); - return; - } - xfree (key); - - if (!gcry_pk_get_keygrip (private, grip)) - { - log_error ("can't calculate keygrip\n"); - return; - } - gcry_sexp_release (private); - - for (i=0; i < 20; i++) - printf ("%02X", grip[i]); - putchar ('\n'); -} - - -static int -rsa_key_check (struct rsa_secret_key_s *skey) -{ - int err = 0; - MPI t = gcry_mpi_snew (0); - MPI t1 = gcry_mpi_snew (0); - MPI t2 = gcry_mpi_snew (0); - MPI phi = gcry_mpi_snew (0); - - /* check that n == p * q */ - gcry_mpi_mul (t, skey->p, skey->q); - if (gcry_mpi_cmp( t, skey->n) ) - { - log_error ("RSA oops: n != p * q\n"); - err++; - } - - /* check that p is less than q */ - if (gcry_mpi_cmp (skey->p, skey->q) > 0) - { - GcryMPI tmp; - - log_info ("swapping secret primes\n"); - tmp = gcry_mpi_copy (skey->p); - gcry_mpi_set (skey->p, skey->q); - gcry_mpi_set (skey->q, tmp); - gcry_mpi_release (tmp); - /* and must recompute u of course */ - gcry_mpi_invm (skey->u, skey->p, skey->q); - } - - /* check that e divides neither p-1 nor q-1 */ - gcry_mpi_sub_ui (t, skey->p, 1 ); - gcry_mpi_div (NULL, t, t, skey->e, 0); - if (!gcry_mpi_cmp_ui( t, 0) ) - { - log_error ("RSA oops: e divides p-1\n"); - err++; - } - gcry_mpi_sub_ui (t, skey->q, 1); - gcry_mpi_div (NULL, t, t, skey->e, 0); - if (!gcry_mpi_cmp_ui( t, 0)) - { - log_info ( "RSA oops: e divides q-1\n" ); - err++; - } - - /* check that d is correct. */ - gcry_mpi_sub_ui (t1, skey->p, 1); - gcry_mpi_sub_ui (t2, skey->q, 1); - gcry_mpi_mul (phi, t1, t2); - gcry_mpi_invm (t, skey->e, phi); - if (gcry_mpi_cmp (t, skey->d)) - { /* no: try universal exponent. */ - gcry_mpi_gcd (t, t1, t2); - gcry_mpi_div (t, NULL, phi, t, 0); - gcry_mpi_invm (t, skey->e, t); - if (gcry_mpi_cmp (t, skey->d)) - { - log_error ("RSA oops: bad secret exponent\n"); - err++; - } - } - - /* check for correctness of u */ - gcry_mpi_invm (t, skey->p, skey->q); - if (gcry_mpi_cmp (t, skey->u)) - { - log_info ( "RSA oops: bad u parameter\n"); - err++; - } - - if (err) - log_info ("RSA secret key check failed\n"); - - gcry_mpi_release (t); - gcry_mpi_release (t1); - gcry_mpi_release (t2); - gcry_mpi_release (phi); - - return err? -1:0; -} - - -static void -import_p12_file (const char *fname) -{ - char *buf; - unsigned char *result; - size_t buflen, resultlen; - int i; - int rc; - GcryMPI *kparms; - struct rsa_secret_key_s sk; - GcrySexp s_key; - unsigned char *key; - unsigned char grip[20]; - - /* fixme: we should release some stuff on error */ - - buf = read_file (fname, &buflen); - if (!buf) - return; - - kparms = p12_parse (buf, buflen, get_passphrase ()); - xfree (buf); - if (!kparms) - { - log_error ("error parsing or decrypting the PKCS-1 file\n"); - return; - } - for (i=0; kparms[i]; i++) - ; - if (i != 8) - { - log_error ("invalid structure of private key\n"); - return; - } - - -/* print_mpi (" n", kparms[0]); */ -/* print_mpi (" e", kparms[1]); */ -/* print_mpi (" d", kparms[2]); */ -/* print_mpi (" p", kparms[3]); */ -/* print_mpi (" q", kparms[4]); */ -/* print_mpi ("dmp1", kparms[5]); */ -/* print_mpi ("dmq1", kparms[6]); */ -/* print_mpi (" u", kparms[7]); */ - - sk.n = kparms[0]; - sk.e = kparms[1]; - sk.d = kparms[2]; - sk.q = kparms[3]; - sk.p = kparms[4]; - sk.u = kparms[7]; - if (rsa_key_check (&sk)) - return; -/* print_mpi (" n", sk.n); */ -/* print_mpi (" e", sk.e); */ -/* print_mpi (" d", sk.d); */ -/* print_mpi (" p", sk.p); */ -/* print_mpi (" q", sk.q); */ -/* print_mpi (" u", sk.u); */ - - /* Create an S-expresion from the parameters. */ - rc = gcry_sexp_build (&s_key, NULL, - "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", - sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL); - for (i=0; i < 8; i++) - gcry_mpi_release (kparms[i]); - gcry_free (kparms); - if (rc) - { - log_error ("failed to created S-expression from key: %s\n", - gcry_strerror (rc)); - return; - } - - /* Compute the keygrip. */ - if (!gcry_pk_get_keygrip (s_key, grip)) - { - log_error ("can't calculate keygrip\n"); - return; - } - log_info ("keygrip: "); - for (i=0; i < 20; i++) - log_printf ("%02X", grip[i]); - log_printf ("\n"); - - /* convert to canonical encoding */ - buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, NULL, 0); - assert (buflen); - key = gcry_xmalloc_secure (buflen); - buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, key, buflen); - assert (buflen); - gcry_sexp_release (s_key); - - - rc = agent_protect (key, get_passphrase (), &result, &resultlen); - xfree (key); - if (rc) - { - log_error ("protecting the key failed: %s\n", gnupg_strerror (rc)); - return; - } - - if (opt_armor) - { - char *p = make_advanced (result, resultlen); - xfree (result); - if (!p) - return; - result = p; - resultlen = strlen (p); - } - - if (opt_store) - store_private_key (grip, result, resultlen, opt_force); - else - fwrite (result, resultlen, 1, stdout); - - xfree (result); -} - - - -static GcryMPI * -sexp_to_kparms (GCRY_SEXP sexp) -{ - GcrySexp list, l2; - const char *name; - const char *s; - size_t n; - int i, idx; - const char *elems; - GcryMPI *array; - - list = gcry_sexp_find_token (sexp, "private-key", 0 ); - if(!list) - return NULL; - l2 = gcry_sexp_cadr (list); - gcry_sexp_release (list); - list = l2; - name = gcry_sexp_nth_data (list, 0, &n); - if(!name || n != 3 || memcmp (name, "rsa", 3)) - { - gcry_sexp_release (list); - return NULL; - } - - /* Paramter names used with RSA. */ - elems = "nedpqu"; - array = xcalloc (strlen(elems) + 1, sizeof *array); - for (idx=0, s=elems; *s; s++, idx++ ) - { - l2 = gcry_sexp_find_token (list, s, 1); - if (!l2) - { - for (i=0; i -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" - -#include "sexp-parse.h" - -#define PROT_CIPHER GCRY_CIPHER_AES -#define PROT_CIPHER_STRING "aes" -#define PROT_CIPHER_KEYLEN (128/8) - - -/* A table containing the information needed to create a protected - private key */ -static struct { - const char *algo; - const char *parmlist; - int prot_from, prot_to; -} protect_info[] = { - { "rsa", "nedpqu", 2, 5 }, - { NULL } -}; - - -static int -hash_passphrase (const char *passphrase, int hashalgo, - int s2kmode, - const unsigned char *s2ksalt, unsigned long s2kcount, - unsigned char *key, size_t keylen); - - - -/* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to - a 20 byte buffer. This function is suitable for any algorithms. */ -static int -calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) -{ - const unsigned char *hash_begin, *hash_end; - const unsigned char *s; - size_t n; - - s = plainkey; - if (*s != '(') - return GNUPG_Invalid_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "private-key")) - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Unknown_Sexp; - hash_begin = s; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s += n; /* skip over the algorithm name */ - - while (*s == '(') - { - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s += n; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s += n; - if ( *s != ')' ) - return GNUPG_Invalid_Sexp; - s++; - } - if (*s != ')') - return GNUPG_Invalid_Sexp; - s++; - hash_end = s; - - gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash, - hash_begin, hash_end - hash_begin); - - return 0; -} - - - -/* Encrypt the parameter block starting at PROTBEGIN with length - PROTLEN using the utf8 encoded key PASSPHRASE and return the entire - encrypted block in RESULT or ereturn with an error code. SHA1HASH - is the 20 byte SHA-1 hash required for the integrity code. - - The parameter block is expected to be an incomplete S-Expression of - the form (example in advanced format): - - (d #046129F..[some bytes not shown]..81#) - (p #00e861b..[some bytes not shown]..f1#) - (q #00f7a7c..[some bytes not shown]..61#) - (u #304559a..[some bytes not shown]..9b#) - - the returned block is the S-Expression: - - (protected mode (parms) encrypted_octet_string) - -*/ -static int -do_encryption (const char *protbegin, size_t protlen, - const char *passphrase, const unsigned char *sha1hash, - unsigned char **result, size_t *resultlen) -{ - GCRY_CIPHER_HD hd; - const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"; - int blklen, enclen, outlen; - char *iv = NULL; - int rc = 0; - char *outbuf = NULL; - char *p; - int saltpos, ivpos, encpos; - - hd = gcry_cipher_open (PROT_CIPHER, GCRY_CIPHER_MODE_CBC, - GCRY_CIPHER_SECURE); - if (!hd) - return map_gcry_err (gcry_errno()); - - - /* We need to work on a copy of the data because this makes it - easier to add the trailer and the padding and more important we - have to prefix the text with 2 parenthesis, so we have to - allocate enough space for: - - (()(4:hash4:sha120:)) + padding - - We always append a full block of random bytes as padding but - encrypt only what is needed for a full blocksize */ - blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER); - outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen; - enclen = outlen/blklen * blklen; - outbuf = gcry_malloc_secure (outlen); - if (!outbuf) - rc = GNUPG_Out_Of_Core; - if (!rc) - { - /* allocate random bytes to be used as IV, padding and s2k salt*/ - iv = gcry_random_bytes (blklen*2+8, GCRY_WEAK_RANDOM); - if (!iv) - rc = GNUPG_Out_Of_Core; - else - rc = gcry_cipher_setiv (hd, iv, blklen); - } - if (!rc) - { - unsigned char *key; - size_t keylen = PROT_CIPHER_KEYLEN; - - key = gcry_malloc_secure (keylen); - if (!key) - rc = GNUPG_Out_Of_Core; - else - { - rc = hash_passphrase (passphrase, GCRY_MD_SHA1, - 3, iv+2*blklen, 96, key, keylen); - if (!rc) - rc = gcry_cipher_setkey (hd, key, keylen); - xfree (key); - } - } - if (!rc) - { - p = outbuf; - *p++ = '('; - *p++ = '('; - memcpy (p, protbegin, protlen); - p += protlen; - memcpy (p, ")(4:hash4:sha120:", 17); - p += 17; - memcpy (p, sha1hash, 20); - p += 20; - *p++ = ')'; - *p++ = ')'; - memcpy (p, iv+blklen, blklen); - p += blklen; - assert ( p - outbuf == outlen); - rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0); - } - gcry_cipher_close (hd); - if (rc) - { - xfree (iv); - xfree (outbuf); - return rc; - } - - /* Now allocate the buffer we want to return. This is - - (protected openpgp-s2k3-sha1-aes-cbc - ((sha1 salt no_of_iterations) 16byte_iv) - encrypted_octet_string) - - in canoncical format of course. We use asprintf and %n modifier - and spaces as palceholders. */ - asprintf (&p, - "(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)", - (int)strlen (modestr), modestr, - &saltpos, - blklen, &ivpos, blklen, "", - enclen, &encpos, enclen, ""); - if (p) - { /* asprintf does not use out malloc system */ - char *psave = p; - p = xtrymalloc (strlen (psave)+1); - if (p) - strcpy (p, psave); - free (psave); - } - if (!p) - { - xfree (iv); - xfree (outbuf); - return GNUPG_Out_Of_Core; - } - *resultlen = strlen (p); - *result = p; - memcpy (p+saltpos, iv+2*blklen, 8); - memcpy (p+ivpos, iv, blklen); - memcpy (p+encpos, outbuf, enclen); - xfree (iv); - xfree (outbuf); - return 0; -} - - - -/* Protect the key encoded in canonical format in plainkey. We assume - a valid S-Exp here. */ -int -agent_protect (const unsigned char *plainkey, const char *passphrase, - unsigned char **result, size_t *resultlen) -{ - int rc; - const unsigned char *s; - const unsigned char *hash_begin, *hash_end; - const unsigned char *prot_begin, *prot_end, *real_end; - size_t n; - int c, infidx, i; - unsigned char hashvalue[20]; - unsigned char *protected; - size_t protectedlen; - int depth = 0; - unsigned char *p; - - s = plainkey; - if (*s != '(') - return GNUPG_Invalid_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "private-key")) - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Unknown_Sexp; - depth++; - hash_begin = s; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - - for (infidx=0; protect_info[infidx].algo - && !smatch (&s, n, protect_info[infidx].algo); infidx++) - ; - if (!protect_info[infidx].algo) - return GNUPG_Unsupported_Algorithm; - - prot_begin = prot_end = NULL; - for (i=0; (c=protect_info[infidx].parmlist[i]); i++) - { - if (i == protect_info[infidx].prot_from) - prot_begin = s; - if (*s != '(') - return GNUPG_Invalid_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (n != 1 || c != *s) - return GNUPG_Invalid_Sexp; - s += n; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s +=n; /* skip value */ - if (*s != ')') - return GNUPG_Invalid_Sexp; - depth--; - if (i == protect_info[infidx].prot_to) - prot_end = s; - s++; - } - if (*s != ')' || !prot_begin || !prot_end ) - return GNUPG_Invalid_Sexp; - depth--; - hash_end = s; - s++; - /* skip to the end of the S-exp */ - assert (depth == 1); - rc = sskip (&s, &depth); - if (rc) - return rc; - assert (!depth); - real_end = s-1; - - gcry_md_hash_buffer (GCRY_MD_SHA1, hashvalue, - hash_begin, hash_end - hash_begin + 1); - - rc = do_encryption (prot_begin, prot_end - prot_begin + 1, - passphrase, hashvalue, - &protected, &protectedlen); - if (rc) - return rc; - - /* Now create the protected version of the key. Note that the 10 - extra bytes are for for the inserted "protected-" string (the - beginning of the plaintext reads: "((11:private-key(" ). */ - *resultlen = (10 - + (prot_begin-plainkey) - + protectedlen - + (real_end-prot_end)); - *result = p = xtrymalloc (*resultlen); - if (!p) - { - xfree (protected); - return GNUPG_Out_Of_Core; - } - memcpy (p, "(21:protected-", 14); - p += 14; - memcpy (p, plainkey+4, prot_begin - plainkey - 4); - p += prot_begin - plainkey - 4; - memcpy (p, protected, protectedlen); - p += protectedlen; - memcpy (p, prot_end+1, real_end - prot_end); - p += real_end - prot_end; - assert ( p - *result == *resultlen); - xfree (protected); - return 0; -} - - -/* Do the actual decryption and check the return list for consistency. */ -static int -do_decryption (const unsigned char *protected, size_t protectedlen, - const char *passphrase, - const unsigned char *s2ksalt, unsigned long s2kcount, - const unsigned char *iv, size_t ivlen, - unsigned char **result) -{ - int rc = 0; - int blklen; - GCRY_CIPHER_HD hd; - unsigned char *outbuf; - size_t reallen; - - blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER); - if (protectedlen < 4 || (protectedlen%blklen)) - return GNUPG_Corrupted_Protection; - - hd = gcry_cipher_open (PROT_CIPHER, GCRY_CIPHER_MODE_CBC, - GCRY_CIPHER_SECURE); - if (!hd) - return map_gcry_err (gcry_errno()); - - outbuf = gcry_malloc_secure (protectedlen); - if (!outbuf) - rc = GNUPG_Out_Of_Core; - if (!rc) - rc = gcry_cipher_setiv (hd, iv, ivlen); - if (!rc) - { - unsigned char *key; - size_t keylen = PROT_CIPHER_KEYLEN; - - key = gcry_malloc_secure (keylen); - if (!key) - rc = GNUPG_Out_Of_Core; - else - { - rc = hash_passphrase (passphrase, GCRY_MD_SHA1, - 3, s2ksalt, s2kcount, key, keylen); - if (!rc) - rc = gcry_cipher_setkey (hd, key, keylen); - xfree (key); - } - } - if (!rc) - rc = gcry_cipher_decrypt (hd, outbuf, protectedlen, - protected, protectedlen); - gcry_cipher_close (hd); - if (rc) - { - xfree (outbuf); - return rc; - } - /* do a quick check first */ - if (*outbuf != '(' && outbuf[1] != '(') - { - xfree (outbuf); - return GNUPG_Bad_Passphrase; - } - /* check that we have a consistent S-Exp */ - reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL); - if (!reallen || (reallen + blklen < protectedlen) ) - { - xfree (outbuf); - return GNUPG_Bad_Passphrase; - } - *result = outbuf; - return 0; -} - - -/* Merge the parameter list contained in CLEARTEXT with the original - protect lists PROTECTEDKEY by replacing the list at REPLACEPOS. - Return the new list in RESULT and the MIC value in the 20 byte - buffer SHA1HASH. */ -static int -merge_lists (const unsigned char *protectedkey, - size_t replacepos, - const unsigned char *cleartext, - unsigned char *sha1hash, unsigned char **result) -{ - size_t n, newlistlen; - unsigned char *newlist, *p; - const unsigned char *s; - const unsigned char *startpos, *endpos; - int i, rc; - - if (replacepos < 26) - return GNUPG_Bug; - - /* Estimate the required size of the resulting list. We have a large - safety margin of >20 bytes (MIC hash from CLEARTEXT and the - removed "protected-" */ - newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL); - if (!newlistlen) - return GNUPG_Bug; - n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL); - if (!n) - return GNUPG_Bug; - newlistlen += n; - newlist = gcry_malloc_secure (newlistlen); - if (!newlist) - return GNUPG_Out_Of_Core; - - /* Copy the initial segment */ - strcpy (newlist, "(11:private-key"); - p = newlist + 15; - memcpy (p, protectedkey+15+10, replacepos-15-10); - p += replacepos-15-10; - - /* copy the cleartext */ - s = cleartext; - if (*s != '(' && s[1] != '(') - return GNUPG_Bug; /*we already checked this */ - s += 2; - startpos = s; - while ( *s == '(' ) - { - s++; - n = snext (&s); - if (!n) - goto invalid_sexp; - s += n; - n = snext (&s); - if (!n) - goto invalid_sexp; - s += n; - if ( *s != ')' ) - goto invalid_sexp; - s++; - } - if ( *s != ')' ) - goto invalid_sexp; - endpos = s; - s++; - /* short intermezzo: Get the MIC */ - if (*s != '(') - goto invalid_sexp; - s++; - n = snext (&s); - if (!smatch (&s, n, "hash")) - goto invalid_sexp; - n = snext (&s); - if (!smatch (&s, n, "sha1")) - goto invalid_sexp; - n = snext (&s); - if (n != 20) - goto invalid_sexp; - memcpy (sha1hash, s, 20); - s += n; - if (*s != ')') - goto invalid_sexp; - /* end intermezzo */ - - /* append the parameter list */ - memcpy (p, startpos, endpos - startpos); - p += endpos - startpos; - - /* skip overt the protected list element in the original list */ - s = protectedkey + replacepos; - assert (*s == '('); - s++; - i = 1; - rc = sskip (&s, &i); - if (rc) - goto failure; - startpos = s; - i = 2; /* we are inside this level */ - rc = sskip (&s, &i); - if (rc) - goto failure; - assert (s[-1] == ')'); - endpos = s; /* one behind the end of the list */ - - /* append the rest */ - memcpy (p, startpos, endpos - startpos); - p += endpos - startpos; - - /* ready */ - *result = newlist; - return 0; - - failure: - xfree (newlist); - return rc; - - invalid_sexp: - xfree (newlist); - return GNUPG_Invalid_Sexp; -} - - - -/* Unprotect the key encoded in canonical format. We assume a valid - S-Exp here. */ -int -agent_unprotect (const unsigned char *protectedkey, const char *passphrase, - unsigned char **result, size_t *resultlen) -{ - int rc; - const unsigned char *s; - size_t n; - int infidx, i; - unsigned char sha1hash[20], sha1hash2[20]; - const unsigned char *s2ksalt; - unsigned long s2kcount; - const unsigned char *iv; - const unsigned char *prot_begin; - unsigned char *cleartext; - unsigned char *final; - - s = protectedkey; - if (*s != '(') - return GNUPG_Invalid_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "protected-private-key")) - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Unknown_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - - for (infidx=0; protect_info[infidx].algo - && !smatch (&s, n, protect_info[infidx].algo); infidx++) - ; - if (!protect_info[infidx].algo) - return GNUPG_Unsupported_Algorithm; - - /* now find the list with the protected information. Here is an - example for such a list: - (protected openpgp-s2k3-sha1-aes-cbc - ((sha1 ) ) - ) - */ - for (;;) - { - if (*s != '(') - return GNUPG_Invalid_Sexp; - prot_begin = s; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (smatch (&s, n, "protected")) - break; - s += n; - i = 1; - rc = sskip (&s, &i); - if (rc) - return rc; - } - /* found */ - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc")) - return GNUPG_Unsupported_Protection; - if (*s != '(' || s[1] != '(') - return GNUPG_Invalid_Sexp; - s += 2; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "sha1")) - return GNUPG_Unsupported_Protection; - n = snext (&s); - if (n != 8) - return GNUPG_Corrupted_Protection; - s2ksalt = s; - s += n; - n = snext (&s); - if (!n) - return GNUPG_Corrupted_Protection; - /* We expect a list close as next, so we can simply use strtoul() - here. We might want to check that we only have digits - but this - is nothing we should worry about */ - if (s[n] != ')' ) - return GNUPG_Invalid_Sexp; - s2kcount = strtoul (s, NULL, 10); - if (!s2kcount) - return GNUPG_Corrupted_Protection; - s += n; - s++; /* skip list end */ - - n = snext (&s); - if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */ - return GNUPG_Corrupted_Protection; - iv = s; - s += n; - if (*s != ')' ) - return GNUPG_Invalid_Sexp; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - - rc = do_decryption (s, n, - passphrase, s2ksalt, s2kcount, - iv, 16, - &cleartext); - if (rc) - return rc; - - rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext, - sha1hash, &final); - xfree (cleartext); - if (rc) - return rc; - - rc = calculate_mic (final, sha1hash2); - if (!rc && memcmp (sha1hash, sha1hash2, 20)) - rc = GNUPG_Corrupted_Protection; - if (rc) - { - xfree (final); - return rc; - } - - *result = final; - *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL); - return 0; -} - -/* Check the type of the private key, this is one of the constants: - PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the - value 0), PRIVATE_KEY_CLEAR for an unprotected private key. - PRIVATE_KEY_PROTECTED for an protected private key or - PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored - elsewhere. */ -int -agent_private_key_type (const unsigned char *privatekey) -{ - const unsigned char *s; - size_t n; - - s = privatekey; - if (*s != '(') - return PRIVATE_KEY_UNKNOWN; - s++; - n = snext (&s); - if (!n) - return PRIVATE_KEY_UNKNOWN; - if (smatch (&s, n, "protected-private-key")) - return PRIVATE_KEY_PROTECTED; - if (smatch (&s, n, "shadowed-private-key")) - return PRIVATE_KEY_SHADOWED; - if (smatch (&s, n, "private-key")) - return PRIVATE_KEY_CLEAR; - return PRIVATE_KEY_UNKNOWN; -} - - - -/* Transform a passphrase into a suitable key of length KEYLEN and - store this key in the caller provided buffer KEY. The caller must - provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on - that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable - value is 96). - - Returns an error code on failure. */ -static int -hash_passphrase (const char *passphrase, int hashalgo, - int s2kmode, - const unsigned char *s2ksalt, - unsigned long s2kcount, - unsigned char *key, size_t keylen) -{ - GCRY_MD_HD md; - int pass, i; - int used = 0; - int pwlen = strlen (passphrase); - - if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3) - || !hashalgo || !keylen || !key || !passphrase) - return GNUPG_Invalid_Value; - if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt) - return GNUPG_Invalid_Value; - - md = gcry_md_open (hashalgo, GCRY_MD_FLAG_SECURE); - if (!md) - return map_gcry_err (gcry_errno()); - - for (pass=0; used < keylen; pass++) - { - if (pass) - { - gcry_md_reset (md); - for (i=0; i < pass; i++) /* preset the hash context */ - gcry_md_putc (md, 0); - } - - if (s2kmode == 1 || s2kmode == 3) - { - int len2 = pwlen + 8; - unsigned long count = len2; - - if (s2kmode == 3) - { - count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6); - if (count < len2) - count = len2; - } - - while (count > len2) - { - gcry_md_write (md, s2ksalt, 8); - gcry_md_write (md, passphrase, pwlen); - count -= len2; - } - if (count < 8) - gcry_md_write (md, s2ksalt, count); - else - { - gcry_md_write (md, s2ksalt, 8); - count -= 8; - gcry_md_write (md, passphrase, count); - } - } - else - gcry_md_write (md, passphrase, pwlen); - - gcry_md_final (md); - i = gcry_md_get_algo_dlen (hashalgo); - if (i > keylen - used) - i = keylen - used; - memcpy (key+used, gcry_md_read (md, hashalgo), i); - used += i; - } - gcry_md_close(md); - return 0; -} - - - -/* Create a shadow key from a public key. We use the shadow protocol - "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting - S-expression is returned in an allocated buffer RESULT will point - to. The input parameters are expected to be valid canonilized - S-expressions */ -int -agent_shadow_key (const unsigned char *pubkey, - const unsigned char *shadow_info, - unsigned char **result) -{ - const unsigned char *s; - const unsigned char *point; - size_t n; - int depth = 0; - unsigned char *p; - size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL); - size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL); - - if (!pubkey_len || !shadow_info_len) - return GNUPG_Invalid_Value; - s = pubkey; - if (*s != '(') - return GNUPG_Invalid_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "public-key")) - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Unknown_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s += n; /* skip over the algorithm name */ - - while (*s != ')') - { - if (*s != '(') - return GNUPG_Invalid_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s += n; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s +=n; /* skip value */ - if (*s != ')') - return GNUPG_Invalid_Sexp; - depth--; - s++; - } - point = s; /* insert right before the point */ - depth--; - s++; - assert (depth == 1); - - /* calculate required length by taking in account: the "shadowed-" - prefix, the "shadowed", "t1-v1" as well as some parenthesis */ - n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1; - *result = p = xtrymalloc (n); - if (!p) - return GNUPG_Out_Of_Core; - p = stpcpy (p, "(20:shadowed-private-key"); - /* (10:public-key ...)*/ - memcpy (p, pubkey+14, point - (pubkey+14)); - p += point - (pubkey+14); - p = stpcpy (p, "(8:shadowed5:t1-v1"); - memcpy (p, shadow_info, shadow_info_len); - p += shadow_info_len; - *p++ = ')'; - memcpy (p, point, pubkey_len - (point - pubkey)); - p += pubkey_len - (point - pubkey); - - return 0; -} - -/* Parse a canonical encoded shadowed key and return a pointer to the - inner list with the shadow_info */ -int -agent_get_shadow_info (const unsigned char *shadowkey, - unsigned char const **shadow_info) -{ - const unsigned char *s; - size_t n; - int depth = 0; - - s = shadowkey; - if (*s != '(') - return GNUPG_Invalid_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (!smatch (&s, n, "shadowed-private-key")) - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Unknown_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s += n; /* skip over the algorithm name */ - - for (;;) - { - if (*s == ')') - return GNUPG_Unknown_Sexp; - if (*s != '(') - return GNUPG_Invalid_Sexp; - depth++; - s++; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (smatch (&s, n, "shadowed")) - break; - s += n; - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - s +=n; /* skip value */ - if (*s != ')') - return GNUPG_Invalid_Sexp; - depth--; - s++; - } - /* found the shadowed list, s points to the protocol */ - n = snext (&s); - if (!n) - return GNUPG_Invalid_Sexp; - if (smatch (&s, n, "t1-v1")) - { - if (*s != '(') - return GNUPG_Invalid_Sexp; - *shadow_info = s; - } - else - return GNUPG_Unsupported_Protocol; - return 0; -} - diff --git a/agent/query.c b/agent/query.c deleted file mode 100644 index ee18a1483..000000000 --- a/agent/query.c +++ /dev/null @@ -1,460 +0,0 @@ -/* query.c - fork of the pinentry to query stuff from the user - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef USE_GNU_PTH -# include -#endif - -#include "agent.h" -#include "i18n.h" -#include "../assuan/assuan.h" - -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif - -static ASSUAN_CONTEXT entry_ctx = NULL; -#ifdef USE_GNU_PTH -static pth_mutex_t entry_lock = PTH_MUTEX_INIT; -#endif - -/* data to be passed to our callbacks */ -struct entry_parm_s { - int lines; - size_t size; - char *buffer; -}; - - - - -static int -unlock_pinentry (int rc) -{ -#ifdef USE_GNU_PTH - if (!pth_mutex_release (&entry_lock)) - { - log_error ("failed to release the entry lock\n"); - if (!rc) - rc = GNUPG_Internal_Error; - } -#endif - return rc; -} - -/* Fork off the pin entry if this has not already been done. Note, - that this function must always be used to aquire the lock for the - pinentry - we will serialize _all_ pinentry calls. - */ -static int -start_pinentry (void) -{ - int rc; - const char *pgmname; - ASSUAN_CONTEXT ctx; - const char *argv[5]; - int no_close_list[3]; - int i; - -#ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&entry_lock, 0, NULL)) - { - log_error ("failed to acquire the entry lock\n"); - return GNUPG_Internal_Error; - } -#endif - - if (entry_ctx) - return 0; - - if (opt.verbose) - log_info ("no running PIN Entry - starting it\n"); - - if (fflush (NULL)) - { - log_error ("error flushing pending output: %s\n", strerror (errno)); - return unlock_pinentry (seterr (Write_Error)); - } - - if (!opt.pinentry_program || !*opt.pinentry_program) - opt.pinentry_program = GNUPG_DEFAULT_PINENTRY; - if ( !(pgmname = strrchr (opt.pinentry_program, '/'))) - pgmname = opt.pinentry_program; - else - pgmname++; - - /* FIXME: We must do this thread specific */ - argv[0] = pgmname; - if (opt.display && !opt.keep_display) - { - argv[1] = "--display"; - argv[2] = opt.display; - argv[3] = NULL; - } - else - argv[1] = NULL; - - i=0; - if (!opt.running_detached) - { - 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 pinentry and perform initial handshaking */ - rc = assuan_pipe_connect (&ctx, opt.pinentry_program, (char**)argv, - no_close_list); - if (rc) - { - log_error ("can't connect to the PIN entry module: %s\n", - assuan_strerror (rc)); - return unlock_pinentry (seterr (No_PIN_Entry)); - } - entry_ctx = ctx; - - if (DBG_ASSUAN) - log_debug ("connection to PIN entry established\n"); - - rc = assuan_transact (entry_ctx, - opt.no_grab? "OPTION no-grab":"OPTION grab", - NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - if (opt.ttyname && !opt.keep_tty) - { - char *optstr; - if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 ) - return unlock_pinentry (GNUPG_Out_Of_Core); - rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - if (opt.ttytype && !opt.keep_tty) - { - char *optstr; - if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 ) - return unlock_pinentry (GNUPG_Out_Of_Core); - rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - if (opt.lc_ctype) - { - char *optstr; - if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 ) - return unlock_pinentry (GNUPG_Out_Of_Core); - rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - if (opt.lc_messages) - { - char *optstr; - if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 ) - return unlock_pinentry (GNUPG_Out_Of_Core); - rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - return 0; -} - - -static AssuanError -getpin_cb (void *opaque, const void *buffer, size_t length) -{ - struct entry_parm_s *parm = opaque; - - if (!buffer) - return 0; - - /* we expect the pin to fit on one line */ - if (parm->lines || length >= parm->size) - return ASSUAN_Too_Much_Data; - - /* fixme: we should make sure that the assuan buffer is allocated in - secure memory or read the response byte by byte */ - memcpy (parm->buffer, buffer, length); - parm->buffer[length] = 0; - parm->lines++; - return 0; -} - - -static int -all_digitsp( const char *s) -{ - for (; *s && *s >= '0' && *s <= '9'; s++) - ; - return !*s; -} - - - -/* Call the Entry and ask for the PIN. We do check for a valid PIN - number here and repeat it as long as we have invalid formed - numbers. */ -int -agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - struct entry_parm_s parm; - const char *errtext = NULL; - int is_pin = 0; - - if (opt.batch) - return 0; /* fixme: we should return BAD PIN */ - - if (!pininfo || pininfo->max_length < 1) - return seterr (Invalid_Value); - if (!desc_text && pininfo->min_digits) - desc_text = _("Please enter your PIN, so that the secret key " - "can be unlocked for this session"); - else if (!desc_text) - desc_text = _("Please enter your passphrase, so that the secret key " - "can be unlocked for this session"); - - is_pin = desc_text && strstr (desc_text, "PIN"); - - rc = start_pinentry (); - if (rc) - return rc; - - snprintf (line, DIM(line)-1, "SETDESC %s", desc_text); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - - rc = assuan_transact (entry_ctx, - is_pin? "SETPROMPT PIN:" - : "SETPROMPT Passphrase:", - NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - - for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++) - { - memset (&parm, 0, sizeof parm); - parm.size = pininfo->max_length; - parm.buffer = pininfo->pin; - - if (errtext) - { - /* fixme: should we show the try count? It must be translated */ - snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)", - errtext, pininfo->failed_tries+1, pininfo->max_tries); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - errtext = NULL; - } - - rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, - NULL, NULL, NULL, NULL); - if (rc == ASSUAN_Too_Much_Data) - errtext = is_pin? _("PIN too long") - : _("Passphrase too long"); - else if (rc) - return unlock_pinentry (map_assuan_err (rc)); - - if (!errtext && pininfo->min_digits) - { - /* do some basic checks on the entered PIN. */ - if (!all_digitsp (pininfo->pin)) - errtext = _("Invalid characters in PIN"); - else if (pininfo->max_digits - && strlen (pininfo->pin) > pininfo->max_digits) - errtext = _("PIN too long"); - else if (strlen (pininfo->pin) < pininfo->min_digits) - errtext = _("PIN too short"); - } - - if (!errtext && pininfo->check_cb) - { - /* More checks by utilizing the optional callback. */ - pininfo->cb_errtext = NULL; - rc = pininfo->check_cb (pininfo); - if (rc == -1 && pininfo->cb_errtext) - errtext = pininfo->cb_errtext; - else if (rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN) - errtext = (is_pin? _("Bad PIN") - : _("Bad Passphrase")); - else if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - - if (!errtext) - return unlock_pinentry (0); /* okay, got a PIN or passphrase */ - } - - return unlock_pinentry (pininfo->min_digits? GNUPG_Bad_PIN - : GNUPG_Bad_Passphrase); -} - - - -/* Ask for the passphrase using the supplied arguments. The - passphrase is returned in RETPASS as an hex encoded string to be - freed by the caller */ -int -agent_get_passphrase (char **retpass, const char *desc, const char *prompt, - const char *errtext) -{ - - int rc; - char line[ASSUAN_LINELENGTH]; - struct entry_parm_s parm; - unsigned char *p, *hexstring; - int i; - - *retpass = NULL; - if (opt.batch) - return GNUPG_Bad_Passphrase; - - rc = start_pinentry (); - if (rc) - return rc; - - if (!prompt) - prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase"); - - - if (desc) - snprintf (line, DIM(line)-1, "SETDESC %s", desc); - else - snprintf (line, DIM(line)-1, "RESET"); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - - snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - - if (errtext) - { - snprintf (line, DIM(line)-1, "SETERROR %s", errtext); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - - memset (&parm, 0, sizeof parm); - parm.size = ASSUAN_LINELENGTH/2 - 5; - parm.buffer = gcry_malloc_secure (parm.size+10); - if (!parm.buffer) - return unlock_pinentry (seterr (Out_Of_Core)); - - assuan_begin_confidential (entry_ctx); - rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL); - if (rc) - { - xfree (parm.buffer); - return unlock_pinentry (map_assuan_err (rc)); - } - - hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1); - if (!hexstring) - { - xfree (parm.buffer); - return unlock_pinentry (seterr (Out_Of_Core)); - } - - for (i=0, p=parm.buffer; *p; p++, i += 2) - sprintf (hexstring+i, "%02X", *p); - - xfree (parm.buffer); - *retpass = hexstring; - return unlock_pinentry (0); -} - - - -/* Pop up the PIN-entry, display the text and the prompt and ask the - user to confirm this. We return 0 for success, ie. the used - confirmed it, GNUPG_Not_Confirmed for what the text says or an - other error. */ -int -agent_get_confirmation (const char *desc, const char *ok, const char *cancel) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - - rc = start_pinentry (); - if (rc) - return rc; - - if (desc) - snprintf (line, DIM(line)-1, "SETDESC %s", desc); - else - snprintf (line, DIM(line)-1, "RESET"); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - - if (ok) - { - snprintf (line, DIM(line)-1, "SETOK %s", ok); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - if (cancel) - { - snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel); - line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return unlock_pinentry (map_assuan_err (rc)); - } - - rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL); - return unlock_pinentry (map_assuan_err (rc)); -} - - - diff --git a/agent/sexp-parse.h b/agent/sexp-parse.h deleted file mode 100644 index 6baca08cf..000000000 --- a/agent/sexp-parse.h +++ /dev/null @@ -1,98 +0,0 @@ -/* sexp-parse.h - S-Exp helper functions - * 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 SEXP_PARSE_H -#define SEXP_PARSE_H - -#include "../common/util.h" - -/* Return the length of the next S-Exp part and update the pointer to - the first data byte. 0 is return on error */ -static inline size_t -snext (unsigned char const **buf) -{ - const unsigned char *s; - int n; - - s = *buf; - for (n=0; *s && *s != ':' && digitp (s); s++) - n = n*10 + atoi_1 (s); - 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 int -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 GNUPG_Invalid_Sexp; - n = snext (&s); - if (!n) - return GNUPG_Invalid_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. */ -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*/ diff --git a/agent/simple-pwquery.c b/agent/simple-pwquery.c deleted file mode 100644 index 5bb08afec..000000000 --- a/agent/simple-pwquery.c +++ /dev/null @@ -1,485 +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 -#endif -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_LOCALE_H -#include -#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; - } - - if (ttyname (1)) - dft_ttyname = ttyname (1); - if (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 ) - { -#ifdef SPWQ_USE_LOGGING - log_error (_("gpg-agent is not available in this session\n")); -#endif - return SPWQ_NO_AGENT; - } - - 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 poiinter 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; - char *p = buffer; - - for (i=0; text[i]; i++) - { - if (text[i] < ' ' || text[i] == '+') - { - sprintf (p, "%%%02X", text[i]); - p += 3; - } - else if (text[i] == ' ') - *p++ = '+'; - else - *p++ = text[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; -} diff --git a/agent/trustlist.c b/agent/trustlist.c deleted file mode 100644 index b6545f7de..000000000 --- a/agent/trustlist.c +++ /dev/null @@ -1,304 +0,0 @@ -/* trustlist.c - Maintain the list of trusted keys - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "agent.h" -#include "../assuan/assuan.h" /* fixme: need a way to avoid assuan - calls here */ - -static const char headerblurb[] = -"# This is the list of trusted keys. Comments like this one and empty\n" -"# lines are allowed but keep in mind that the entire file is integrity\n" -"# protected by the use of a MAC, so changing the file does not make\n" -"# much sense without the knowledge of the MAC key. Lines do have a\n" -"# length limit but this is not serious limitation as the format of the\n" -"# entries is fixed and checked by gpg-agent: A non-comment line starts\n" -"# with optional white spaces, followed by exactly 40 hex character,\n" -"# optioanlly followed by a flag character which my either be 'P', 'S'\n" -"# or '*'. Additional data delimited with by a white space is ignored.\n" -"\n"; - - -static FILE *trustfp; - - -static int -open_list (int append) -{ - char *fname; - - fname = make_filename (opt.homedir, "trustlist.txt", NULL); - trustfp = fopen (fname, append? "a+":"r"); - if (!trustfp && errno == ENOENT) - { - trustfp = fopen (fname, "wx"); - if (!trustfp) - { - log_error ("can't create `%s': %s\n", fname, strerror (errno)); - xfree (fname); - return seterr (File_Create_Error); - } - fputs (headerblurb, trustfp); - fclose (trustfp); - trustfp = fopen (fname, append? "a+":"r"); - } - - if (!trustfp) - { - log_error ("can't open `%s': %s\n", fname, strerror (errno)); - xfree (fname); - return seterr (File_Open_Error); - } - - /*FIXME: check the MAC */ - - return 0; -} - - - -/* Read the trustlist and return entry by entry. KEY must point to a - buffer of at least 41 characters. KEYFLAG does return either 'P', - 'S' or '*'. - - Reading a valid entry return 0, EOF returns -1 any other error - returns the appropriate error code. */ -static int -read_list (char *key, int *keyflag) -{ - int rc; - int c, i; - char *p, line[256]; - - if (!trustfp) - { - rc = open_list (0); - if (rc) - return rc; - } - - do - { - if (!fgets (line, DIM(line)-1, trustfp) ) - { - if (feof (trustfp)) - return -1; - return GNUPG_Read_Error; - } - - if (!*line || line[strlen(line)-1] != '\n') - { - /* eat until end of line */ - while ( (c=getc (trustfp)) != EOF && c != '\n') - ; - return *line? GNUPG_Line_Too_Long: GNUPG_Incomplete_Line; - } - - /* Allow for emty lines and spaces */ - for (p=line; spacep (p); p++) - ; - } - while (!*p || *p == '\n' || *p == '#'); - - for (i=0; hexdigitp (p+i) && i < 40; i++) - key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i]; - key[i] = 0; - if (i!=40 || !(spacep (p+i) || p[i] == '\n')) - { - log_error ("invalid formatted fingerprint in trustlist\n"); - return GNUPG_Bad_Data; - } - assert (p[i]); - if (p[i] == '\n') - *keyflag = '*'; - else - { - i++; - if ( p[i] == 'P' || p[i] == 'p') - *keyflag = 'P'; - else if ( p[i] == 'S' || p[i] == 's') - *keyflag = 'S'; - else if ( p[i] == '*') - *keyflag = '*'; - else - { - log_error ("invalid keyflag in trustlist\n"); - return GNUPG_Bad_Data; - } - i++; - if ( !(spacep (p+i) || p[i] == '\n')) - { - log_error ("invalid keyflag in trustlist\n"); - return GNUPG_Bad_Data; - } - } - - return 0; -} - -/* check whether the given fpr is in our trustdb. We expect FPR to be - an all uppercase hexstring of 40 characters. */ -int -agent_istrusted (const char *fpr) -{ - int rc; - static char key[41]; - int keyflag; - - if (trustfp) - rewind (trustfp); - while (!(rc=read_list (key, &keyflag))) - { - if (!strcmp (key, fpr)) - return 0; - } - if (rc != -1) - { - /* error in the trustdb - close it to give the user a chance for - correction */ - fclose (trustfp); - trustfp = NULL; - } - return rc; -} - - -/* write all trust entries to FP */ -int -agent_listtrusted (void *assuan_context) -{ - int rc; - static char key[51]; - int keyflag; - - if (trustfp) - rewind (trustfp); - while (!(rc=read_list (key, &keyflag))) - { - key[40] = ' '; - key[41] = keyflag; - key[42] = '\n'; - assuan_send_data (assuan_context, key, 43); - assuan_send_data (assuan_context, NULL, 0); /* flush */ - } - if (rc == -1) - rc = 0; - if (rc) - { - /* error in the trustdb - close it to give the user a chance for - correction */ - fclose (trustfp); - trustfp = NULL; - } - return rc; -} - - -/* Insert the given fpr into our trustdb. We expect FPR to be an all - uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'. - This function does first check whether that key has alreay ben put - into the trustdb and returns success in this case. Before a FPR - actually gets inserted, the user is asked by means of the pin-entry - whether this is actual wants he want to do. -*/ -int -agent_marktrusted (const char *name, const char *fpr, int flag) -{ - int rc; - static char key[41]; - int keyflag; - char *desc; - - if (trustfp) - rewind (trustfp); - while (!(rc=read_list (key, &keyflag))) - { - if (!strcmp (key, fpr)) - return 0; - } - fclose (trustfp); - trustfp = NULL; - if (rc != -1) - return rc; /* error in the trustdb */ - - /* insert a new one */ - if (asprintf (&desc, - "Please verify that the certificate identified as:%%0A" - " \"%s\"%%0A" - "has the fingerprint:%%0A" - " %s", name, fpr) < 0 ) - return GNUPG_Out_Of_Core; - rc = agent_get_confirmation (desc, "Correct", "No"); - free (desc); - if (rc) - return rc; - - if (asprintf (&desc, - "Do you ultimately trust%%0A" - " \"%s\"%%0A" - "to correctly certify user certificates?", - name) < 0 ) - return GNUPG_Out_Of_Core; - rc = agent_get_confirmation (desc, "Yes", "No"); - free (desc); - if (rc) - return rc; - - /* now check again to avoid duplicates. Also open in append mode now */ - rc = open_list (1); - if (rc) - return rc; - rewind (trustfp); - while (!(rc=read_list (key, &keyflag))) - { - if (!strcmp (key, fpr)) - return 0; - } - if (rc != -1) - { - fclose (trustfp); - trustfp = NULL; - return rc; /* error in the trustdb */ - } - rc = 0; - - /* append the key */ - fflush (trustfp); - fputs ("\n# ", trustfp); - print_sanitized_string (trustfp, name, 0); - fprintf (trustfp, "\n%s %c\n", fpr, flag); - if (ferror (trustfp)) - rc = GNUPG_Write_Error; - - /* close because we are in append mode */ - if (fclose (trustfp)) - rc = GNUPG_File_Error; - trustfp = NULL; - return rc; -} diff --git a/assuan/ChangeLog b/assuan/ChangeLog deleted file mode 100644 index 670f7ef75..000000000 --- a/assuan/ChangeLog +++ /dev/null @@ -1,250 +0,0 @@ -2002-08-16 Werner Koch - - * assuan.h: Renamed Bad_Certificate_Path to Bad_Certificate_Chain. - -2002-07-30 Werner Koch - - Changed the license from GPL to LGPL. - -2002-07-23 Werner Koch - - * assuan-handler.c (_IO_cookie_io_functions_t): Define it here if - it does not exists. - -2002-06-27 Werner Koch - - * assuan-pipe-connect.c (assuan_pipe_connect): No special handling - for the log_fd and stderr. Connect stderr to /dev/null if it - should not be retained. - -2002-06-26 Werner Koch - - * assuan-buffer.c (assuan_write_line): Make sure we never - accidently print an extra LF. - -2002-05-23 Werner Koch - - * assuan-util.c (assuan_set_io_func): New. - * assuan-buffer.c (writen, readline): Use the new functions - instead of pth. - * assuan-socket-server.c (accept_connection): Don't use the - pth_accept - using the assuan included accept code would be a bad - idea within Pth so we don't need a replacement function. - -2002-05-22 Werner Koch - - * assuan-socket-server.c (assuan_init_connected_socket_server): New. - (accept_connection): Factored most code out to.. - (accept_connection_bottom): .. new function. - -2002-04-04 Werner Koch - - * assuan-buffer.c (my_log_prefix): New. Use it for all i/o debug - output. - -2002-03-06 Werner Koch - - * assuan-client.c (_assuan_read_from_server): Detect END. - (assuan_transact): Pass it to the data callback. - -2002-02-27 Werner Koch - - * assuan-client.c (assuan_transact): Add 2 more arguments to - support status lines. Passing NULL yields the old behaviour. - - * assuan-handler.c (process_request): Flush data lines send - without using the data fp. - -2002-02-14 Werner Koch - - * assuan-inquire.c (assuan_inquire): Check for a cancel command - and return ASSUAN_Canceled. Allow for non-data inquiry. - - * assuan.h: Add a few token specific error codes. - -2002-02-13 Werner Koch - - * assuan-defs.h (assuan_context_s): New var CLIENT_PID. - * assuan-pipe-server.c (_assuan_new_context): set default value. - * assuan-socket-server.c (accept_connection): get the actual pid. - -2002-02-12 Werner Koch - - * assuan-buffer.c (writen,readline) [USE_GNU_PT]: Use pth_read/write. - * assuan-socket-server.c (accept_connection) [USE_GNU_PTH]: Ditto. - -2002-02-01 Marcus Brinkmann - - * Makefile.am (MOSTLYCLEANFILES): New variable. - -2002-01-23 Werner Koch - - * assuan-socket-connect.c (LOGERRORX): and removed typo. - -2002-01-22 Marcus Brinkmann - - * assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs. - -2002-01-21 Werner Koch - - * assuan-connect.c: Move all except assuan_get_pid to... - * assuan-pipe-connect.c: this. - (assuan_pipe_disconnect): Removed. - (do_finish, do_deinit): New - (assuan_pipe_connect): and set them into the context. - * assuan-socket-connect.c: New. - - * assuan-util.c (_assuan_log_sanitized_string): New. - - * assuan-pipe-server.c (assuan_init_pipe_server): Factored most - code out to ... - (_assuan_new_context): new func. - (_assuan_release_context): New - * assuan-connect.c (assuan_pipe_connect): Use the new functions. - -2002-01-20 Werner Koch - - * assuan.h: Added Invalid Option error code. - - * assuan-handler.c (std_handler_option): New. - (std_cmd_tbl): Add OPTION as standard command. - (assuan_register_option_handler): New. - (dispatch_command): Use case insensitive matching as a fallback. - (my_strcasecmp): New. - -2002-01-19 Werner Koch - - * assuan-buffer.c (_assuan_read_line): Add output logging. - (assuan_write_line): Ditto. - (_assuan_cookie_write_data): Ditto. - (_assuan_cookie_write_flush): Ditto. - * assuan-util.c (_assuan_log_print_buffer): New. - (assuan_set_log_stream): New. - (assuan_begin_confidential): New. - (assuan_end_confidential): New. - - * assuan-defs.h: Add a few handler variables. - * assuan-pipe-server.c (assuan_deinit_pipe_server): Removed. - (deinit_pipe_server): New. - (assuan_deinit_server): New. Changed all callers to use this. - * assuan-listen.c (assuan_accept): Use the accept handler. - * assuan-handler.c (process_request): Use the close Handler. - * assuan-socket-server.c: New. - -2002-01-14 Werner Koch - - * assuan-client.c (_assuan_read_from_server): Skip spaces after - the keyword. - -2002-01-03 Werner Koch - - * assuan-handler.c (assuan_set_okay_line): New. - (process_request): And use it here. - -2002-01-02 Werner Koch - - * assuan-inquire.c (init_membuf,put_membuf,get_membuf): Apply a - hidden 0 behind the buffer so that the buffer can be used as a - string in certain contexts. - -2001-12-14 Marcus Brinkmann - - * assuan-connect.c (assuan_pipe_connect): New argument - FD_CHILD_LIST. Don't close those fds. - * assuan.h: Likewise for prototype. - -2001-12-14 Werner Koch - - * assuan-listen.c (assuan_close_input_fd): New. - (assuan_close_output_fd): New. - * assuan-handler.c (std_handler_reset): Always close them after a - reset command. - (std_handler_bye): Likewise. - -2001-12-14 Marcus Brinkmann - - * assuan-buffer.c (_assuan_read_line): New variable ATTICLEN, use - it to save the length of the attic line. - Rediddle the code a bit to make it more clear what happens. - -2001-12-14 Marcus Brinkmann - - * assuan-defs.h (LINELENGTH): Define as ASSUAN_LINELENGTH. - assuan.h: Define ASSUAN_LINELENGTH. - -2001-12-13 Marcus Brinkmann - - * assuan-buffer.c (assuan_read_line): Fix order of execution to - get correct return values. - -2001-12-13 Werner Koch - - * assuan-handler.c (assuan_get_active_fds): Fixed silly bug, - pretty obvious that nobody ever tested this function. - -2001-12-12 Werner Koch - - * assuan-connect.c (assuan_pipe_connect): Implemented the inital - handshake. - * assuan-client.c (read_from_server): Renamed to - (_assuan_read_from_server): this and made external. - - * assuan-listen.c (assuan_set_hello_line): New. - (assuan_accept): Use a custom hello line is available. - - * assuan-buffer.c (assuan_read_line): New. - (assuan_pending_line): New. - (_assuan_write_line): Renamed to .. - (assuan_write_line): this, made public and changed all callers. - -2001-12-04 Werner Koch - - * assuan-connect.c (assuan_pipe_connect): Add more error reporting. - * assuan-client.c: New. - - * assuan-inquire.c: New. - * assuan-handler.c (process_request): Check for nested invocations. - -2001-11-27 Werner Koch - - * assuan-handler.c (assuan_register_input_notify): New. - (assuan_register_output_notify): New. - -2001-11-26 Werner Koch - - * assuan.h: Added more status codes. - -2001-11-25 Werner Koch - - * assuan-handler.c (assuan_register_bye_notify) - (assuan_register_reset_notify) - (assuan_register_cancel_notify): New and call them from the - standard handlers. - (assuan_process): Moved bulk of function to .. - (process_request): .. new. - (assuan_process_next): One shot version of above. - (assuan_get_active_fds): New. - -2001-11-24 Werner Koch - - * assuan-connect.c (assuan_get_pid): New. - - * assuan-buffer.c (_assuan_read_line): Deal with reads of more - than a line. - * assuan-defs.h: Add space in the context for this. - - - *********************************************************** - * Please note that Assuan is maintained as part of GnuPG. * - * You may find it source-copied in other packages. * - *********************************************************** - - 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. diff --git a/assuan/Makefile.am b/assuan/Makefile.am deleted file mode 100644 index 71560c9e3..000000000 --- a/assuan/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -# Assuan Makefile -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. -# -# This file is part of Assuan. -# -# Assuan is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of -# the License, or (at your option) any later version. -# -# Assuan 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser 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 -INCLUDES = -I.. -I$(top_srcdir)/include -BUILT_SOURCES = assuan-errors.c -MOSTLYCLEANFILES = assuan-errors.c - -noinst_LIBRARIES = libassuan.a - - -#libassuan_a_LDFLAGS = -libassuan_a_SOURCES = \ - assuan.h \ - assuan-defs.h \ - assuan-util.c \ - assuan-errors.c \ - assuan-buffer.c \ - assuan-handler.c \ - assuan-inquire.c \ - assuan-listen.c \ - assuan-connect.c \ - assuan-client.c \ - assuan-pipe-server.c \ - assuan-socket-server.c \ - assuan-pipe-connect.c \ - assuan-socket-connect.c - - -assuan-errors.c : assuan.h - $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c deleted file mode 100644 index df5057543..000000000 --- a/assuan/assuan-buffer.c +++ /dev/null @@ -1,443 +0,0 @@ -/* assuan-buffer.c - read and send data - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include -#include -#include "assuan-defs.h" - -#ifdef HAVE_JNLIB_LOGGING -#include "../jnlib/logging.h" -#endif - - -static const char * -my_log_prefix (void) -{ -#ifdef HAVE_JNLIB_LOGGING - return log_get_prefix (NULL); -#else - return ""; -#endif -} - - -static int -writen ( int fd, const char *buffer, size_t length ) -{ - while (length) - { - int nwritten = _assuan_write_wrapper? - _assuan_write_wrapper (fd, buffer, length): - write (fd, buffer, length); - - if (nwritten < 0) - { - if (errno == EINTR) - continue; - return -1; /* write error */ - } - length -= nwritten; - buffer += nwritten; - } - return 0; /* okay */ -} - -/* read an entire line */ -static int -readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof) -{ - size_t nleft = buflen; - char *p; - - *eof = 0; - *r_nread = 0; - while (nleft > 0) - { - int n = _assuan_read_wrapper? - _assuan_read_wrapper (fd, buf, nleft): - read (fd, buf, nleft); - - if (n < 0) - { - if (errno == EINTR) - continue; - return -1; /* read error */ - } - else if (!n) - { - *eof = 1; - break; /* allow incomplete lines */ - } - p = buf; - nleft -= n; - buf += n; - *r_nread += n; - - for (; n && *p != '\n'; n--, p++) - ; - if (n) - break; /* at least one full line available - that's enough for now */ - } - - return 0; -} - - -int -_assuan_read_line (ASSUAN_CONTEXT ctx) -{ - char *line = ctx->inbound.line; - int n, nread, atticlen; - int rc; - - if (ctx->inbound.eof) - return -1; - - atticlen = ctx->inbound.attic.linelen; - if (atticlen) - { - memcpy (line, ctx->inbound.attic.line, atticlen); - ctx->inbound.attic.linelen = 0; - for (n=0; n < atticlen && line[n] != '\n'; n++) - ; - if (n < atticlen) - { - rc = 0; /* found another line in the attic */ - nread = atticlen; - atticlen = 0; - } - else - { /* read the rest */ - assert (atticlen < LINELENGTH); - rc = readline (ctx->inbound.fd, line + atticlen, - LINELENGTH - atticlen, &nread, &ctx->inbound.eof); - } - } - else - rc = readline (ctx->inbound.fd, line, LINELENGTH, - &nread, &ctx->inbound.eof); - if (rc) - { - if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n", - my_log_prefix (), ctx, strerror (errno)); - return ASSUAN_Read_Error; - } - if (!nread) - { - assert (ctx->inbound.eof); - if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n", my_log_prefix (),ctx); - return -1; - } - - ctx->inbound.attic.pending = 0; - nread += atticlen; - for (n=0; n < nread; n++) - { - if (line[n] == '\n') - { - if (n+1 < nread) - { - char *s, *d; - int i; - - n++; - /* we have to copy the rest because the handlers are - allowed to modify the passed buffer */ - for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--) - { - if (*s=='\n') - ctx->inbound.attic.pending = 1; - *d++ = *s++; - } - ctx->inbound.attic.linelen = nread-n; - n--; - } - if (n && line[n-1] == '\r') - n--; - line[n] = 0; - ctx->inbound.linelen = n; - if (ctx->log_fp) - { - fprintf (ctx->log_fp, "%s[%p] <- ", my_log_prefix (), ctx); - if (ctx->confidential) - fputs ("[Confidential data not shown]", ctx->log_fp); - else - _assuan_log_print_buffer (ctx->log_fp, - ctx->inbound.line, - ctx->inbound.linelen); - putc ('\n', ctx->log_fp); - } - return 0; - } - } - - if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n", my_log_prefix (), ctx); - *line = 0; - ctx->inbound.linelen = 0; - return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long; -} - - -/* Read the next line from the client or server and return a pointer - to a buffer with holding that line. linelen returns the length of - the line. This buffer is valid until another read operation is - done on this buffer. The caller is allowed to modify this buffer. - He should only use the buffer if the function returns without an - error. - - Returns: 0 on success or an assuan error code - See also: assuan_pending_line(). -*/ -AssuanError -assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen) -{ - AssuanError err; - - if (!ctx) - return ASSUAN_Invalid_Value; - - err = _assuan_read_line (ctx); - *line = ctx->inbound.line; - *linelen = ctx->inbound.linelen; - return err; -} - - -/* Return true when a full line is pending for a read, without the need - for actual IO */ -int -assuan_pending_line (ASSUAN_CONTEXT ctx) -{ - return ctx && ctx->inbound.attic.pending; -} - - -AssuanError -assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ) -{ - int rc; - size_t len; - const char *s; - - if (!ctx) - return ASSUAN_Invalid_Value; - - /* Make sure that we never take a LF from the user - this might - violate the protocol. */ - s = strchr (line, '\n'); - len = s? (s-line) : strlen (line); - - /* fixme: we should do some kind of line buffering. */ - if (ctx->log_fp) - { - fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx); - if (s) - fputs ("[supplied line contained a LF]", ctx->log_fp); - if (ctx->confidential) - fputs ("[Confidential data not shown]", ctx->log_fp); - else - _assuan_log_print_buffer (ctx->log_fp, line, len); - putc ('\n', ctx->log_fp); - } - - rc = writen (ctx->outbound.fd, line, len); - if (rc) - rc = ASSUAN_Write_Error; - if (!rc) - { - rc = writen (ctx->outbound.fd, "\n", 1); - if (rc) - rc = ASSUAN_Write_Error; - } - - return rc; -} - - - -/* Write out the data in buffer as datalines with line wrapping and - percent escaping. This fucntion is used for GNU's custom streams */ -int -_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size) -{ - ASSUAN_CONTEXT ctx = cookie; - char *line; - size_t linelen; - - if (ctx->outbound.data.error) - return 0; - - line = ctx->outbound.data.line; - linelen = ctx->outbound.data.linelen; - line += linelen; - while (size) - { - /* insert data line header */ - if (!linelen) - { - *line++ = 'D'; - *line++ = ' '; - linelen += 2; - } - - /* copy data, keep some space for the CRLF and to escape one character */ - while (size && linelen < LINELENGTH-2-2) - { - if (*buffer == '%' || *buffer == '\r' || *buffer == '\n') - { - sprintf (line, "%%%02X", *(unsigned char*)buffer); - line += 3; - linelen += 3; - buffer++; - } - else - { - *line++ = *buffer++; - linelen++; - } - size--; - } - - if (linelen >= LINELENGTH-2-2) - { - if (ctx->log_fp) - { - fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx); - if (ctx->confidential) - fputs ("[Confidential data not shown]", ctx->log_fp); - else - _assuan_log_print_buffer (ctx->log_fp, - ctx->outbound.data.line, - linelen); - putc ('\n', ctx->log_fp); - } - *line++ = '\n'; - linelen++; - if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen)) - { - ctx->outbound.data.error = ASSUAN_Write_Error; - return 0; - } - line = ctx->outbound.data.line; - linelen = 0; - } - } - - ctx->outbound.data.linelen = linelen; - return 0; -} - - -/* Write out any buffered data - This fucntion is used for GNU's custom streams */ -int -_assuan_cookie_write_flush (void *cookie) -{ - ASSUAN_CONTEXT ctx = cookie; - char *line; - size_t linelen; - - if (ctx->outbound.data.error) - return 0; - - line = ctx->outbound.data.line; - linelen = ctx->outbound.data.linelen; - line += linelen; - if (linelen) - { - if (ctx->log_fp) - { - fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx); - if (ctx->confidential) - fputs ("[Confidential data not shown]", ctx->log_fp); - else - _assuan_log_print_buffer (ctx->log_fp, - ctx->outbound.data.line, - linelen); - putc ('\n', ctx->log_fp); - } - *line++ = '\n'; - linelen++; - if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen)) - { - ctx->outbound.data.error = ASSUAN_Write_Error; - return 0; - } - ctx->outbound.data.linelen = 0; - } - return 0; -} - - -/** - * assuan_send_data: - * @ctx: An assuan context - * @buffer: Data to send or NULL to flush - * @length: length of the data to send/ - * - * This function may be used by the server or the client to send data - * lines. The data will be escaped as required by the Assuan protocol - * and may get buffered until a line is full. To force sending the - * data out @buffer may be passed as NULL (in which case @length must - * also be 0); however when used by a client this flush operation does - * also send the terminating "END" command to terminate the reponse on - * a INQUIRE response. However, when assuan_transact() is used, this - * function takes care of sending END itself. - * - * Return value: 0 on success or an error code - **/ - -AssuanError -assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - if (!buffer && length) - return ASSUAN_Invalid_Value; - - if (!buffer) - { /* flush what we have */ - _assuan_cookie_write_flush (ctx); - if (ctx->outbound.data.error) - return ctx->outbound.data.error; - if (!ctx->is_server) - return assuan_write_line (ctx, "END"); - } - else - { - _assuan_cookie_write_data (ctx, buffer, length); - if (ctx->outbound.data.error) - return ctx->outbound.data.error; - } - - return 0; -} - - - - diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c deleted file mode 100644 index d5c0ec819..000000000 --- a/assuan/assuan-client.c +++ /dev/null @@ -1,225 +0,0 @@ -/* assuan-client.c - client functions - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include - -#include "assuan-defs.h" - -#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)) - - -AssuanError -_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) -{ - char *line; - int linelen; - AssuanError rc; - - *okay = 0; - *off = 0; - do - { - rc = _assuan_read_line (ctx); - if (rc) - return rc; - line = ctx->inbound.line; - linelen = ctx->inbound.linelen; - } - while (*line == '#' || !linelen); - - if (linelen >= 1 - && line[0] == 'D' && line[1] == ' ') - { - *okay = 2; /* data line */ - *off = 2; - } - else if (linelen >= 1 - && line[0] == 'S' - && (line[1] == '\0' || line[1] == ' ')) - { - *okay = 4; - *off = 1; - while (line[*off] == ' ') - ++*off; - } - else if (linelen >= 2 - && line[0] == 'O' && line[1] == 'K' - && (line[2] == '\0' || line[2] == ' ')) - { - *okay = 1; - *off = 2; - while (line[*off] == ' ') - ++*off; - } - else if (linelen >= 3 - && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' - && (line[3] == '\0' || line[3] == ' ')) - { - *okay = 0; - *off = 3; - while (line[*off] == ' ') - ++*off; - } - else if (linelen >= 7 - && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' - && line[3] == 'U' && line[4] == 'I' && line[5] == 'R' - && line[6] == 'E' - && (line[7] == '\0' || line[7] == ' ')) - { - *okay = 3; - *off = 7; - while (line[*off] == ' ') - ++*off; - } - else if (linelen >= 3 - && line[0] == 'E' && line[1] == 'N' && line[2] == 'D' - && (line[3] == '\0' || line[3] == ' ')) - { - *okay = 5; /* end line */ - *off = 3; - } - else - rc = ASSUAN_Invalid_Response; - return rc; -} - - - -/** - * assuan_transact: - * @ctx: The Assuan context - * @command: Coimmand line to be send to server - * @data_cb: Callback function for data lines - * @data_cb_arg: first argument passed to @data_cb - * @inquire_cb: Callback function for a inquire response - * @inquire_cb_arg: first argument passed to @inquire_cb - * @status_cb: Callback function for a status response - * @status_cb_arg: first argument passed to @status_cb - * - * FIXME: Write documentation - * - * Return value: 0 on success or error code. The error code may be - * the one one returned by the server in error lines or from the - * callback functions. - **/ -AssuanError -assuan_transact (ASSUAN_CONTEXT ctx, - const char *command, - AssuanError (*data_cb)(void *, const void *, size_t), - void *data_cb_arg, - AssuanError (*inquire_cb)(void*, const char *), - void *inquire_cb_arg, - AssuanError (*status_cb)(void*, const char *), - void *status_cb_arg) -{ - int rc, okay, off; - unsigned char *line; - int linelen; - - rc = assuan_write_line (ctx, command); - if (rc) - return rc; - - again: - rc = _assuan_read_from_server (ctx, &okay, &off); - if (rc) - return rc; /* error reading from server */ - - line = ctx->inbound.line + off; - linelen = ctx->inbound.linelen - off; - - if (!okay) - { - rc = atoi (line); - if (rc < 100) - rc = ASSUAN_Server_Fault; - } - else if (okay == 2) - { - if (!data_cb) - rc = ASSUAN_No_Data_Callback; - else - { - unsigned char *s, *d; - - for (s=d=line; linelen; linelen--) - { - if (*s == '%' && linelen > 2) - { /* handle escaping */ - s++; - *d++ = xtoi_2 (s); - s += 2; - linelen -= 2; - } - else - *d++ = *s++; - } - *d = 0; /* add a hidden string terminator */ - rc = data_cb (data_cb_arg, line, d - line); - if (!rc) - goto again; - } - } - else if (okay == 3) - { - if (!inquire_cb) - { - assuan_write_line (ctx, "END"); /* get out of inquire mode */ - _assuan_read_from_server (ctx, &okay, &off); /* dummy read */ - rc = ASSUAN_No_Inquire_Callback; - } - else - { - rc = inquire_cb (inquire_cb_arg, line); - if (!rc) - rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */ - if (!rc) - goto again; - } - } - else if (okay == 4) - { - if (status_cb) - rc = status_cb (status_cb_arg, line); - if (!rc) - goto again; - } - else if (okay == 5) - { - if (!data_cb) - rc = ASSUAN_No_Data_Callback; - else - { - rc = data_cb (data_cb_arg, NULL, 0); - if (!rc) - goto again; - } - } - - return rc; -} - diff --git a/assuan/assuan-connect.c b/assuan/assuan-connect.c deleted file mode 100644 index 009aaab43..000000000 --- a/assuan/assuan-connect.c +++ /dev/null @@ -1,54 +0,0 @@ -/* assuan-connect.c - Establish a connection (client) - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "assuan-defs.h" - -/* Disconnect and release the context CTX. */ -void -assuan_disconnect (ASSUAN_CONTEXT ctx) -{ - if (ctx) - { - assuan_write_line (ctx, "BYE"); - ctx->finish_handler (ctx); - ctx->deinit_handler (ctx); - ctx->deinit_handler = NULL; - _assuan_release_context (ctx); - } -} - -pid_t -assuan_get_pid (ASSUAN_CONTEXT ctx) -{ - return ctx ? ctx->pid : -1; -} diff --git a/assuan/assuan-defs.h b/assuan/assuan-defs.h deleted file mode 100644 index 3e408b179..000000000 --- a/assuan/assuan-defs.h +++ /dev/null @@ -1,144 +0,0 @@ -/* assuan-defs.c - Internal definitions to Assuan - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 ASSUAN_DEFS_H -#define ASSUAN_DEFS_H - -#include -#include "assuan.h" - -#define LINELENGTH ASSUAN_LINELENGTH - -struct cmdtbl_s { - const char *name; - int cmd_id; - int (*handler)(ASSUAN_CONTEXT, char *line); -}; - -struct assuan_context_s { - AssuanError err_no; - const char *err_str; - int os_errno; /* last system error number used with certain error codes*/ - - int confidential; - int is_server; /* set if this is context belongs to a server */ - int in_inquire; - char *hello_line; - char *okay_line; /* see assan_set_okay_line() */ - - void *user_pointer; /* for assuan_[gs]et_pointer () */ - - FILE *log_fp; - - struct { - int fd; - int eof; - char line[LINELENGTH]; - int linelen; /* w/o CR, LF - might not be the same as - strlen(line) due to embedded nuls. However a nul - is always written at this pos */ - struct { - char line[LINELENGTH]; - int linelen ; - int pending; /* i.e. at least one line is available in the attic */ - } attic; - } inbound; - - struct { - int fd; - struct { - FILE *fp; - char line[LINELENGTH]; - int linelen; - int error; - } data; - } outbound; - - int pipe_mode; /* We are in pipe mode, i.e. we can handle just one - connection and must terminate then */ - pid_t pid; /* In pipe mode, the pid of the child server process. - In socket mode, the pid of the server */ - int listen_fd; /* The fd we are listening on (used by socket servers) */ - int connected_fd; /* helper */ - - pid_t client_pid; /* for a socket server the PID of the client or -1 - if not available */ - - void (*deinit_handler)(ASSUAN_CONTEXT); - int (*accept_handler)(ASSUAN_CONTEXT); - int (*finish_handler)(ASSUAN_CONTEXT); - - struct cmdtbl_s *cmdtbl; - size_t cmdtbl_used; /* used entries */ - size_t cmdtbl_size; /* allocated size of table */ - - void (*bye_notify_fnc)(ASSUAN_CONTEXT); - void (*reset_notify_fnc)(ASSUAN_CONTEXT); - void (*cancel_notify_fnc)(ASSUAN_CONTEXT); - int (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*); - void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *); - void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *); - - int input_fd; /* set by INPUT command */ - int output_fd; /* set by OUTPUT command */ - -}; - - - -/*-- assuan-pipe-server.c --*/ -int _assuan_new_context (ASSUAN_CONTEXT *r_ctx); -void _assuan_release_context (ASSUAN_CONTEXT ctx); - - -/*-- assuan-handler.c --*/ -int _assuan_register_std_commands (ASSUAN_CONTEXT ctx); - -/*-- assuan-buffer.c --*/ -int _assuan_read_line (ASSUAN_CONTEXT ctx); -int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size); -int _assuan_cookie_write_flush (void *cookie); - -/*-- assuan-client.c --*/ -AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off); - - -/*-- assuan-util.c --*/ -extern ssize_t (*_assuan_read_wrapper)(int,void*,size_t); -extern ssize_t (*_assuan_write_wrapper)(int,const void*,size_t); - -void *_assuan_malloc (size_t n); -void *_assuan_calloc (size_t n, size_t m); -void *_assuan_realloc (void *p, size_t n); -void _assuan_free (void *p); - -#define xtrymalloc(a) _assuan_malloc ((a)) -#define xtrycalloc(a,b) _assuan_calloc ((a),(b)) -#define xtryrealloc(a,b) _assuan_realloc((a),(b)) -#define xfree(a) _assuan_free ((a)) - -#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t)) - -void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); -void _assuan_log_sanitized_string (const char *string); - - -#endif /*ASSUAN_DEFS_H*/ - diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c deleted file mode 100644 index 6ddfe8899..000000000 --- a/assuan/assuan-handler.c +++ /dev/null @@ -1,708 +0,0 @@ -/* assuan-handler.c - dispatch commands - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include - -#include "assuan-defs.h" - -#define spacep(p) (*(p) == ' ' || *(p) == '\t') -#define digitp(a) ((a) >= '0' && (a) <= '9') - - -#if !HAVE_FOPENCOOKIE -/* Provide structure for our dummy replacement function. Usually this - is defined in ../common/util.h but assuan should be self - contained. */ -/* Fixme: Remove fopencoookie :-(( */ -typedef struct -{ - ssize_t (*read)(void*,char*,size_t); - ssize_t (*write)(void*,const char*,size_t); - int (*seek)(void*,off_t*,int); - int (*close)(void*); -} _IO_cookie_io_functions_t; -typedef _IO_cookie_io_functions_t cookie_io_functions_t; -FILE *fopencookie (void *cookie, const char *opentype, - cookie_io_functions_t funclist); -#endif /*!HAVE_FOPENCOOKIE*/ - - - - -static int -dummy_handler (ASSUAN_CONTEXT ctx, char *line) -{ - return set_error (ctx, Server_Fault, "no handler registered"); -} - - -static int -std_handler_nop (ASSUAN_CONTEXT ctx, char *line) -{ - return 0; /* okay */ -} - -static int -std_handler_cancel (ASSUAN_CONTEXT ctx, char *line) -{ - if (ctx->cancel_notify_fnc) - ctx->cancel_notify_fnc (ctx); - return set_error (ctx, Not_Implemented, NULL); -} - -static int -std_handler_option (ASSUAN_CONTEXT ctx, char *line) -{ - char *key, *value, *p; - - for (key=line; spacep (key); key++) - ; - if (!*key) - return set_error (ctx, Syntax_Error, "argument required"); - if (*key == '=') - return set_error (ctx, Syntax_Error, "no option name given"); - for (value=key; *value && !spacep (value) && *value != '='; value++) - ; - if (*value) - { - if (spacep (value)) - *value++ = 0; /* terminate key */ - for (; spacep (value); value++) - ; - if (*value == '=') - { - *value++ = 0; /* terminate key */ - for (; spacep (value); value++) - ; - if (!*value) - return set_error (ctx, Syntax_Error, "option argument expected"); - } - if (*value) - { - for (p = value + strlen(value) - 1; p > value && spacep (p); p--) - ; - if (p > value) - *++p = 0; /* strip trailing spaces */ - } - } - - if (*key == '-' && key[1] == '-' && key[2]) - key += 2; /* the double dashes are optional */ - if (*key == '-') - return set_error (ctx, Syntax_Error, - "option should not begin with one dash"); - - if (ctx->option_handler_fnc) - return ctx->option_handler_fnc (ctx, key, value); - return 0; -} - -static int -std_handler_bye (ASSUAN_CONTEXT ctx, char *line) -{ - if (ctx->bye_notify_fnc) - ctx->bye_notify_fnc (ctx); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - return -1; /* pretty simple :-) */ -} - -static int -std_handler_auth (ASSUAN_CONTEXT ctx, char *line) -{ - return set_error (ctx, Not_Implemented, NULL); -} - -static int -std_handler_reset (ASSUAN_CONTEXT ctx, char *line) -{ - if (ctx->reset_notify_fnc) - ctx->reset_notify_fnc (ctx); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - return 0; -} - -static int -std_handler_end (ASSUAN_CONTEXT ctx, char *line) -{ - return set_error (ctx, Not_Implemented, NULL); -} - -static int -parse_cmd_input_output (ASSUAN_CONTEXT ctx, char *line, int *rfd) -{ - char *endp; - - if (strncmp (line, "FD=", 3)) - return set_error (ctx, Syntax_Error, "FD= expected"); - line += 3; - if (!digitp (*line)) - return set_error (ctx, Syntax_Error, "number required"); - *rfd = strtoul (line, &endp, 10); - /* remove that argument so that a notify handler won't see it */ - memset (line, ' ', endp? (endp-line):strlen(line)); - - if (*rfd == ctx->inbound.fd) - return set_error (ctx, Parameter_Conflict, "fd same as inbound fd"); - if (*rfd == ctx->outbound.fd) - return set_error (ctx, Parameter_Conflict, "fd same as outbound fd"); - return 0; -} - -/* Format is INPUT FD= */ -static int -std_handler_input (ASSUAN_CONTEXT ctx, char *line) -{ - int rc, fd; - - rc = parse_cmd_input_output (ctx, line, &fd); - if (rc) - return rc; - ctx->input_fd = fd; - if (ctx->input_notify_fnc) - ctx->input_notify_fnc (ctx, line); - return 0; -} - -/* Format is OUTPUT FD= */ -static int -std_handler_output (ASSUAN_CONTEXT ctx, char *line) -{ - int rc, fd; - - rc = parse_cmd_input_output (ctx, line, &fd); - if (rc) - return rc; - ctx->output_fd = fd; - if (ctx->output_notify_fnc) - ctx->output_notify_fnc (ctx, line); - return 0; -} - - - - - -/* This is a table with the standard commands and handler for them. - The table is used to initialize a new context and assuciate strings - and handlers with cmd_ids */ -static struct { - const char *name; - int cmd_id; - int (*handler)(ASSUAN_CONTEXT, char *line); - int always; /* always initialize this command */ -} std_cmd_table[] = { - { "NOP", ASSUAN_CMD_NOP, std_handler_nop, 1 }, - { "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 1 }, - { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 }, - { "BYE", ASSUAN_CMD_BYE, std_handler_bye, 1 }, - { "AUTH", ASSUAN_CMD_AUTH, std_handler_auth, 1 }, - { "RESET", ASSUAN_CMD_RESET, std_handler_reset, 1 }, - { "END", ASSUAN_CMD_END, std_handler_end, 1 }, - - { "INPUT", ASSUAN_CMD_INPUT, std_handler_input }, - { "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output }, - { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 }, - { NULL } -}; - - -/** - * assuan_register_command: - * @ctx: the server context - * @cmd_id: An ID value for the command - * @cmd_name: A string with the command name - * @handler: The handler function to be called - * - * Register a handler to be used for a given command. - * - * The @cmd_name must be %NULL or an empty string for all @cmd_ids - * below %ASSUAN_CMD_USER because predefined values are used. - * - * Return value: - **/ -int -assuan_register_command (ASSUAN_CONTEXT ctx, - int cmd_id, const char *cmd_name, - int (*handler)(ASSUAN_CONTEXT, char *)) -{ - int i; - - if (cmd_name && !*cmd_name) - cmd_name = NULL; - - if (cmd_id < ASSUAN_CMD_USER) - { - if (cmd_name) - return ASSUAN_Invalid_Value; /* must be NULL for these values*/ - - for (i=0; std_cmd_table[i].name; i++) - { - if (std_cmd_table[i].cmd_id == cmd_id) - { - cmd_name = std_cmd_table[i].name; - if (!handler) - handler = std_cmd_table[i].handler; - break; - } - } - if (!std_cmd_table[i].name) - return ASSUAN_Invalid_Value; /* not a pre-registered one */ - } - - if (!handler) - handler = dummy_handler; - - if (!cmd_name) - return ASSUAN_Invalid_Value; - -/* fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name); */ - - if (!ctx->cmdtbl) - { - ctx->cmdtbl_size = 50; - ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl); - if (!ctx->cmdtbl) - return ASSUAN_Out_Of_Core; - ctx->cmdtbl_used = 0; - } - else if (ctx->cmdtbl_used >= ctx->cmdtbl_size) - { - struct cmdtbl_s *x; - - x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x); - if (!x) - return ASSUAN_Out_Of_Core; - ctx->cmdtbl = x; - ctx->cmdtbl_size += 50; - } - - ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name; - ctx->cmdtbl[ctx->cmdtbl_used].cmd_id = cmd_id; - ctx->cmdtbl[ctx->cmdtbl_used].handler = handler; - ctx->cmdtbl_used++; - return 0; -} - -int -assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - ctx->bye_notify_fnc = fnc; - return 0; -} - -int -assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - ctx->reset_notify_fnc = fnc; - return 0; -} - -int -assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT)) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - ctx->cancel_notify_fnc = fnc; - return 0; -} - -int -assuan_register_option_handler (ASSUAN_CONTEXT ctx, - int (*fnc)(ASSUAN_CONTEXT, - const char*, const char*)) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - ctx->option_handler_fnc = fnc; - return 0; -} - -int -assuan_register_input_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT, const char *)) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - ctx->input_notify_fnc = fnc; - return 0; -} - -int -assuan_register_output_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT, const char *)) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - ctx->output_notify_fnc = fnc; - return 0; -} - - -/* Helper to register the standards commands */ -int -_assuan_register_std_commands (ASSUAN_CONTEXT ctx) -{ - int i, rc; - - for (i=0; std_cmd_table[i].name; i++) - { - if (std_cmd_table[i].always) - { - rc = assuan_register_command (ctx, std_cmd_table[i].cmd_id, - NULL, NULL); - if (rc) - return rc; - } - } - return 0; -} - - - -/* Process the special data lines. The "D " has already been removed - from the line. As all handlers this function may modify the line. */ -static int -handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen) -{ - return set_error (ctx, Not_Implemented, NULL); -} - -/* like ascii_strcasecmp but assume that B is already uppercase */ -static int -my_strcasecmp (const char *a, const char *b) -{ - if (a == b) - return 0; - - for (; *a && *b; a++, b++) - { - if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b) - break; - } - return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b); -} - -/* Parse the line, break out the command, find it in the command - table, remove leading and white spaces from the arguments, all the - handler with the argument line and return the error */ -static int -dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen) -{ - char *p; - const char *s; - int shift, i; - - if (*line == 'D' && line[1] == ' ') /* divert to special handler */ - return handle_data_line (ctx, line+2, linelen-2); - - for (p=line; *p && *p != ' ' && *p != '\t'; p++) - ; - if (p==line) - return set_error (ctx, Invalid_Command, "leading white-space"); - if (*p) - { /* Skip over leading WS after the keyword */ - *p++ = 0; - while ( *p == ' ' || *p == '\t') - p++; - } - shift = p - line; - - for (i=0; (s=ctx->cmdtbl[i].name); i++) - { - if (!strcmp (line, s)) - break; - } - if (!s) - { /* and try case insensitive */ - for (i=0; (s=ctx->cmdtbl[i].name); i++) - { - if (!my_strcasecmp (line, s)) - break; - } - } - if (!s) - return set_error (ctx, Unknown_Command, NULL); - line += shift; - linelen -= shift; - -/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */ - return ctx->cmdtbl[i].handler (ctx, line); -} - - - - -static int -process_request (ASSUAN_CONTEXT ctx) -{ - int rc; - - if (ctx->in_inquire) - return ASSUAN_Nested_Commands; - - rc = _assuan_read_line (ctx); - if (rc) - return rc; - if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) - return 0; /* comment line - ignore */ - - ctx->outbound.data.error = 0; - ctx->outbound.data.linelen = 0; - /* dispatch command and return reply */ - rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen); - /* check from data write errors */ - if (ctx->outbound.data.fp) - { /* Flush the data lines */ - fclose (ctx->outbound.data.fp); - ctx->outbound.data.fp = NULL; - if (!rc && ctx->outbound.data.error) - rc = ctx->outbound.data.error; - } - else /* flush any data send w/o using the data fp */ - { - assuan_send_data (ctx, NULL, 0); - if (!rc && ctx->outbound.data.error) - rc = ctx->outbound.data.error; - } - /* Error handling */ - if (!rc) - { - rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK"); - } - else if (rc == -1) - { /* No error checking because the peer may have already disconnect */ - assuan_write_line (ctx, "OK closing connection"); - ctx->finish_handler (ctx); - } - else - { - char errline[256]; - - if (rc < 100) - sprintf (errline, "ERR %d server fault (%.50s)", - ASSUAN_Server_Fault, assuan_strerror (rc)); - else - { - const char *text = ctx->err_no == rc? ctx->err_str:NULL; - - sprintf (errline, "ERR %d %.50s%s%.100s", - rc, assuan_strerror (rc), text? " - ":"", text?text:""); - } - rc = assuan_write_line (ctx, errline); - } - - ctx->confidential = 0; - if (ctx->okay_line) - { - xfree (ctx->okay_line); - ctx->okay_line = NULL; - } - return rc; -} - -/** - * assuan_process: - * @ctx: assuan context - * - * This fucntion is used to handle the assuan protocol after a - * connection has been established using assuan_accept(). This is the - * main protocol handler. - * - * Return value: 0 on success or an error code if the assuan operation - * failed. Note, that no error is returned for operational errors. - **/ -int -assuan_process (ASSUAN_CONTEXT ctx) -{ - int rc; - - do { - rc = process_request (ctx); - } while (!rc); - - if (rc == -1) - rc = 0; - - return rc; -} - - -/** - * assuan_process_next: - * @ctx: Assuan context - * - * Same as assuan_process() but the user has to provide the outer - * loop. He should loop as long as the return code is zero and stop - * otherwise; -1 is regular end. - * - * See also: assuan_get_active_fds() - * Return value: -1 for end of server, 0 on success or an error code - **/ -int -assuan_process_next (ASSUAN_CONTEXT ctx) -{ - return process_request (ctx); -} - - -/** - * assuan_get_active_fds: - * @ctx: Assuan context - * @what: 0 for read fds, 1 for write fds - * @fdarray: Caller supplied array to store the FDs - * @fdarraysize: size of that array - * - * Return all active filedescriptors for the given context. This - * function can be used to select on the fds and call - * assuan_process_next() if there is an active one. The first fd in - * the array is the one used for the command connection. - * - * Note, that write FDs are not yet supported. - * - * Return value: number of FDs active and put into @fdarray or -1 on - * error which is most likely a too small fdarray. - **/ -int -assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what, - int *fdarray, int fdarraysize) -{ - int n = 0; - - if (!ctx || fdarraysize < 2 || what < 0 || what > 1) - return -1; - - if (!what) - { - if (ctx->inbound.fd != -1) - fdarray[n++] = ctx->inbound.fd; - } - else - { - if (ctx->outbound.fd != -1) - fdarray[n++] = ctx->outbound.fd; - if (ctx->outbound.data.fp) - fdarray[n++] = fileno (ctx->outbound.data.fp); - } - - return n; -} - -/* Return a FP to be used for data output. The FILE pointer is valid - until the end of a handler. So a close is not needed. Assuan does - all the buffering needed to insert the status line as well as the - required line wappping and quoting for data lines. - - We use GNU's custom streams here. There should be an alternative - implementaion for systems w/o a glibc, a simple implementation - could use a child process */ -FILE * -assuan_get_data_fp (ASSUAN_CONTEXT ctx) -{ - cookie_io_functions_t cookie_fnc; - - if (ctx->outbound.data.fp) - return ctx->outbound.data.fp; - - cookie_fnc.read = NULL; - cookie_fnc.write = _assuan_cookie_write_data; - cookie_fnc.seek = NULL; - cookie_fnc.close = _assuan_cookie_write_flush; - - ctx->outbound.data.fp = fopencookie (ctx, "wb", cookie_fnc); - ctx->outbound.data.error = 0; - return ctx->outbound.data.fp; -} - - -/* Set the text used for the next OK reponse. This string is - automatically reset to NULL after the next command. */ -AssuanError -assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - if (!line) - { - xfree (ctx->okay_line); - ctx->okay_line = NULL; - } - else - { - /* FIXME: we need to use gcry_is_secure() to test whether - we should allocate the entire line in secure memory */ - char *buf = xtrymalloc (3+strlen(line)+1); - if (!buf) - return ASSUAN_Out_Of_Core; - strcpy (buf, "OK "); - strcpy (buf+3, line); - xfree (ctx->okay_line); - ctx->okay_line = buf; - } - return 0; -} - - - -void -assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text) -{ - char buffer[256]; - char *helpbuf; - size_t n; - - if ( !ctx || !keyword) - return; - if (!text) - text = ""; - - n = 2 + strlen (keyword) + 1 + strlen (text) + 1; - if (n < sizeof (buffer)) - { - strcpy (buffer, "S "); - strcat (buffer, keyword); - if (*text) - { - strcat (buffer, " "); - strcat (buffer, text); - } - assuan_write_line (ctx, buffer); - } - else if ( (helpbuf = xtrymalloc (n)) ) - { - strcpy (helpbuf, "S "); - strcat (helpbuf, keyword); - if (*text) - { - strcat (helpbuf, " "); - strcat (helpbuf, text); - } - assuan_write_line (ctx, helpbuf); - xfree (helpbuf); - } -} diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c deleted file mode 100644 index 197e21019..000000000 --- a/assuan/assuan-inquire.c +++ /dev/null @@ -1,239 +0,0 @@ -/* assuan-inquire.c - handle inquire stuff - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include - -#include "assuan-defs.h" - -#define digitp(a) ((a) >= '0' && (a) <= '9') -#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)) - - -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; - int too_large; - size_t maxlen; -}; - - - -/* A simple implemnation 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. */ - -static void -init_membuf (struct membuf *mb, int initiallen, size_t maxlen) -{ - mb->len = 0; - mb->size = initiallen; - mb->out_of_core = 0; - mb->too_large = 0; - mb->maxlen = maxlen; - /* we need to allocate one byte more for get_membuf */ - mb->buf = xtrymalloc (initiallen+1); - if (!mb->buf) - mb->out_of_core = 1; -} - -static void -put_membuf (struct membuf *mb, const void *buf, size_t len) -{ - if (mb->out_of_core || mb->too_large) - return; - - if (mb->maxlen && mb->len + len > mb->maxlen) - { - mb->too_large = 1; - return; - } - - if (mb->len + len >= mb->size) - { - char *p; - - mb->size += len + 1024; - /* we need to allocate one byte more for get_membuf */ - p = xtryrealloc (mb->buf, mb->size+1); - if (!p) - { - mb->out_of_core = 1; - return; - } - mb->buf = p; - } - memcpy (mb->buf + mb->len, buf, len); - mb->len += len; -} - -static void * -get_membuf (struct membuf *mb, size_t *len) -{ - char *p; - - if (mb->out_of_core || mb->too_large) - { - xfree (mb->buf); - mb->buf = NULL; - return NULL; - } - - mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */ - p = mb->buf; - *len = mb->len; - mb->buf = NULL; - mb->out_of_core = 1; /* don't allow a reuse */ - return p; -} - -static void -free_membuf (struct membuf *mb) -{ - xfree (mb->buf); - mb->buf = NULL; -} - - -/** - * assuan_inquire: - * @ctx: An assuan context - * @keyword: The keyword used for the inquire - * @r_buffer: Returns an allocated buffer - * @r_length: Returns the length of this buffer - * @maxlen: If not 0, the size limit of the inquired data. - * - * A Server may use this to Send an inquire. r_buffer, r_length and - * maxlen may all be NULL/0 to indicate that no real data is expected. - * - * Return value: 0 on success or an ASSUAN error code - **/ -AssuanError -assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, - char **r_buffer, size_t *r_length, size_t maxlen) -{ - AssuanError rc; - struct membuf mb; - char cmdbuf[100]; - unsigned char *line, *p; - int linelen; - int nodataexpected; - - if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) - return ASSUAN_Invalid_Value; - nodataexpected = !r_buffer && !r_length && !maxlen; - if (!nodataexpected && (!r_buffer || !r_length)) - return ASSUAN_Invalid_Value; - if (!ctx->is_server) - return ASSUAN_Not_A_Server; - if (ctx->in_inquire) - return ASSUAN_Nested_Commands; - - ctx->in_inquire = 1; - if (nodataexpected) - memset (&mb, 0, sizeof mb); /* avoid compiler warnings */ - else - init_membuf (&mb, maxlen? maxlen:1024, maxlen); - - strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); - rc = assuan_write_line (ctx, cmdbuf); - if (rc) - goto leave; - - for (;;) - { - do - { - rc = _assuan_read_line (ctx); - if (rc) - goto leave; - line = ctx->inbound.line; - linelen = ctx->inbound.linelen; - } - while (*line == '#' || !linelen); - if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' - && (!line[3] || line[3] == ' ')) - break; /* END command received*/ - if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N') - { - rc = ASSUAN_Canceled; - goto leave; - } - if (line[0] != 'D' || line[1] != ' ' || nodataexpected) - { - rc = ASSUAN_Unexpected_Command; - goto leave; - } - if (linelen < 3) - continue; - line += 2; - linelen -= 2; - - p = line; - while (linelen) - { - for (;linelen && *p != '%'; linelen--, p++) - ; - put_membuf (&mb, line, p-line); - if (linelen > 2) - { /* handle escaping */ - unsigned char tmp[1]; - p++; - *tmp = xtoi_2 (p); - p += 2; - linelen -= 3; - put_membuf (&mb, tmp, 1); - } - line = p; - } - if (mb.too_large) - { - rc = ASSUAN_Too_Much_Data; - goto leave; - } - } - - if (!nodataexpected) - { - *r_buffer = get_membuf (&mb, r_length); - if (!*r_buffer) - rc = ASSUAN_Out_Of_Core; - } - - leave: - if (!nodataexpected) - free_membuf (&mb); - ctx->in_inquire = 0; - return rc; -} - - - - - - diff --git a/assuan/assuan-listen.c b/assuan/assuan-listen.c deleted file mode 100644 index 3d4ee5f60..000000000 --- a/assuan/assuan-listen.c +++ /dev/null @@ -1,132 +0,0 @@ -/* assuan-listen.c - Wait for a connection (server) - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include - -#include "assuan-defs.h" - -AssuanError -assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line) -{ - if (!ctx) - return ASSUAN_Invalid_Value; - if (!line) - { - xfree (ctx->hello_line); - ctx->hello_line = NULL; - } - else - { - char *buf = xtrymalloc (3+strlen(line)+1); - if (!buf) - return ASSUAN_Out_Of_Core; - strcpy (buf, "OK "); - strcpy (buf+3, line); - xfree (ctx->hello_line); - ctx->hello_line = buf; - } - return 0; -} - - -/** - * assuan_accept: - * @ctx: context - * - * Cancel any existing connectiion and wait for a connection from a - * client. The initial handshake is performed which may include an - * initial authentication or encryption negotiation. - * - * Return value: 0 on success or an error if the connection could for - * some reason not be established. - **/ -AssuanError -assuan_accept (ASSUAN_CONTEXT ctx) -{ - int rc; - - if (!ctx) - return ASSUAN_Invalid_Value; - - if (ctx->pipe_mode > 1) - return -1; /* second invocation for pipemode -> terminate */ - ctx->finish_handler (ctx); - - rc = ctx->accept_handler (ctx); - if (rc) - return rc; - - /* send the hello */ - rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line - : "OK Your orders please"); - if (rc) - return rc; - - if (ctx->pipe_mode) - ctx->pipe_mode = 2; - - return 0; -} - - - -int -assuan_get_input_fd (ASSUAN_CONTEXT ctx) -{ - return ctx? ctx->input_fd : -1; -} - - -int -assuan_get_output_fd (ASSUAN_CONTEXT ctx) -{ - return ctx? ctx->output_fd : -1; -} - - -/* Close the fd descriptor set by the command INPUT FD=n. We handle - this fd inside assuan so that we can do some initial checks */ -AssuanError -assuan_close_input_fd (ASSUAN_CONTEXT ctx) -{ - if (!ctx || ctx->input_fd == -1) - return ASSUAN_Invalid_Value; - close (ctx->input_fd); - ctx->input_fd = -1; - return 0; -} - -/* Close the fd descriptor set by the command OUTPUT FD=n. We handle - this fd inside assuan so that we can do some initial checks */ -AssuanError -assuan_close_output_fd (ASSUAN_CONTEXT ctx) -{ - if (!ctx || ctx->output_fd == -1) - return ASSUAN_Invalid_Value; - - close (ctx->output_fd); - ctx->output_fd = -1; - return 0; -} - diff --git a/assuan/assuan-pipe-connect.c b/assuan/assuan-pipe-connect.c deleted file mode 100644 index 0cb48ca1a..000000000 --- a/assuan/assuan-pipe-connect.c +++ /dev/null @@ -1,288 +0,0 @@ -/* assuan-pipe-connect.c - Establish a pipe connection (client) - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "assuan-defs.h" - -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif - -#ifdef HAVE_JNLIB_LOGGING -#include "../jnlib/logging.h" -#define LOGERROR1(a,b) log_error ((a), (b)) -#else -#define LOGERROR1(a,b) fprintf (stderr, (a), (b)) -#endif - - - -static int -writen ( int fd, const char *buffer, size_t length ) -{ - while (length) - { - int nwritten = write (fd, buffer, length); - - if (nwritten < 0) - { - if (errno == EINTR) - continue; - return -1; /* write error */ - } - length -= nwritten; - buffer += nwritten; - } - return 0; /* okay */ -} - - -static int -do_finish (ASSUAN_CONTEXT ctx) -{ - if (ctx->inbound.fd != -1) - { - close (ctx->inbound.fd); - ctx->inbound.fd = -1; - } - if (ctx->outbound.fd != -1) - { - close (ctx->outbound.fd); - ctx->outbound.fd = -1; - } - if (ctx->pid != -1) - { - waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ - ctx->pid = -1; - } - return 0; -} - -static void -do_deinit (ASSUAN_CONTEXT ctx) -{ - do_finish (ctx); -} - - - -/* Connect to a server over a pipe, creating the assuan context and - returning it in CTX. The server filename is NAME, the argument - vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file - descriptors not to close in the child. */ -AssuanError -assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[], - int *fd_child_list) -{ - static int fixed_signals = 0; - AssuanError err; - int rp[2]; - int wp[2]; - - if (!ctx || !name || !argv || !argv[0]) - return ASSUAN_Invalid_Value; - - if (!fixed_signals) - { - struct sigaction act; - - sigaction (SIGPIPE, NULL, &act); - if (act.sa_handler == SIG_DFL) - { - act.sa_handler = SIG_IGN; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; - sigaction (SIGPIPE, &act, NULL); - } - fixed_signals = 1; - /* FIXME: This is not MT safe */ - } - - if (pipe (rp) < 0) - return ASSUAN_General_Error; - - if (pipe (wp) < 0) - { - close (rp[0]); - close (rp[1]); - return ASSUAN_General_Error; - } - - err = _assuan_new_context (ctx); - if (err) - { - close (rp[0]); - close (rp[1]); - close (wp[0]); - close (wp[1]); - return err; - } - (*ctx)->pipe_mode = 1; - (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ - (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ - (*ctx)->deinit_handler = do_deinit; - (*ctx)->finish_handler = do_finish; - - (*ctx)->pid = fork (); - if ((*ctx)->pid < 0) - { - close (rp[0]); - close (rp[1]); - close (wp[0]); - close (wp[1]); - _assuan_release_context (*ctx); - return ASSUAN_General_Error; - } - - if ((*ctx)->pid == 0) - { - int i, n; - char errbuf[512]; - int *fdp; - - /* Close all files which will not be duped and are not in the - fd_child_list. */ - n = sysconf (_SC_OPEN_MAX); - if (n < 0) - n = MAX_OPEN_FDS; - for (i=0; i < n; i++) - { - fdp = fd_child_list; - if (fdp) - { - while (*fdp != -1 && *fdp != i) - fdp++; - } - - if (!(fdp && *fdp != -1) - && i != rp[1] && i != wp[0]) - close(i); - } - errno = 0; - - /* Dup stderr to /dev/null unless it is in the list of FDs to be - passed to the child. */ - fdp = fd_child_list; - if (fdp) - { - for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++) - ; - } - if (!fdp || *fdp == -1) - { - int fd = open ("/dev/null", O_WRONLY); - if (fd == -1) - { - LOGERROR1 ("can't open `/dev/null': %s\n", strerror (errno)); - _exit (4); - } - if (dup2 (fd, STDERR_FILENO) == -1) - { - LOGERROR1 ("dup2(dev/null, 2) failed: %s\n", strerror (errno)); - _exit (4); - } - close (fd); - } - - /* Dup handles and to stdin/stdout and exec. */ - if (rp[1] != STDOUT_FILENO) - { - if (dup2 (rp[1], STDOUT_FILENO) == -1) - { - LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); - _exit (4); - } - close (rp[1]); - } - if (wp[0] != STDIN_FILENO) - { - if (dup2 (wp[0], STDIN_FILENO) == -1) - { - LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno)); - _exit (4); - } - close (wp[0]); - } - - execv (name, argv); - /* oops - use the pipe to tell the parent about it */ - snprintf (errbuf, sizeof(errbuf)-1, "ERR %d can't exec `%s': %.50s\n", - ASSUAN_Problem_Starting_Server, name, strerror (errno)); - errbuf[sizeof(errbuf)-1] = 0; - writen (1, errbuf, strlen (errbuf)); - _exit (4); - } - - close (rp[1]); - close (wp[0]); - - /* initial handshake */ - { - int okay, off; - - err = _assuan_read_from_server (*ctx, &okay, &off); - if (err) - { - LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err)); - } - else if (okay != 1) - { - LOGERROR1 ("can't connect server: `%s'\n", (*ctx)->inbound.line); - err = ASSUAN_Connect_Failed; - } - } - - if (err) - { - assuan_disconnect (*ctx); - *ctx = NULL; - } - - return err; -} - - - - - - - - - - - - - - diff --git a/assuan/assuan-pipe-server.c b/assuan/assuan-pipe-server.c deleted file mode 100644 index 82bb3228a..000000000 --- a/assuan/assuan-pipe-server.c +++ /dev/null @@ -1,124 +0,0 @@ -/* assuan-pipe-server.c - Assuan server working over a pipe - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include - -#include "assuan-defs.h" - -static void -deinit_pipe_server (ASSUAN_CONTEXT ctx) -{ - /* nothing to do for this simple server */ -} - -static int -accept_connection (ASSUAN_CONTEXT ctx) -{ - /* This is a NOP for a pipe server */ - return 0; -} - -static int -finish_connection (ASSUAN_CONTEXT ctx) -{ - /* This is a NOP for a pipe server */ - return 0; -} - - -/* Create a new context. Note that the handlers are set up for a pipe - server/client - this way we don't need extra dummy functions */ -int -_assuan_new_context (ASSUAN_CONTEXT *r_ctx) -{ - ASSUAN_CONTEXT ctx; - int rc; - - *r_ctx = NULL; - ctx = xtrycalloc (1, sizeof *ctx); - if (!ctx) - return ASSUAN_Out_Of_Core; - ctx->input_fd = -1; - ctx->output_fd = -1; - - ctx->inbound.fd = -1; - ctx->outbound.fd = -1; - - ctx->listen_fd = -1; - ctx->client_pid = (pid_t)-1; - /* use the pipe server handler as a default */ - ctx->deinit_handler = deinit_pipe_server; - ctx->accept_handler = accept_connection; - ctx->finish_handler = finish_connection; - - rc = _assuan_register_std_commands (ctx); - if (rc) - xfree (ctx); - else - *r_ctx = ctx; - return rc; -} - - - -int -assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]) -{ - int rc; - - rc = _assuan_new_context (r_ctx); - if (!rc) - { - ASSUAN_CONTEXT ctx = *r_ctx; - - ctx->is_server = 1; - ctx->inbound.fd = filedes[0]; - ctx->outbound.fd = filedes[1]; - ctx->pipe_mode = 1; - } - return rc; -} - - -void -_assuan_release_context (ASSUAN_CONTEXT ctx) -{ - if (ctx) - { - xfree (ctx->hello_line); - xfree (ctx->okay_line); - xfree (ctx); - } -} - -void -assuan_deinit_server (ASSUAN_CONTEXT ctx) -{ - if (ctx) - { - /* We use this function pointer to avoid linking other server - when not needed but still allow for a generic deinit function */ - ctx->deinit_handler (ctx); - ctx->deinit_handler = NULL; - _assuan_release_context (ctx); - } -} diff --git a/assuan/assuan-socket-connect.c b/assuan/assuan-socket-connect.c deleted file mode 100644 index 53f4a02d0..000000000 --- a/assuan/assuan-socket-connect.c +++ /dev/null @@ -1,150 +0,0 @@ -/* assuan-socket-connect.c - Assuan socket based client - * Copyright (C) 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include -#include -#include - -#include "assuan-defs.h" - -#ifdef HAVE_JNLIB_LOGGING -#include "../jnlib/logging.h" -#define LOGERROR(a) log_error ((a)) -#define LOGERROR1(a,b) log_error ((a), (b)) -#define LOGERROR2(a,b,c) log_error ((a), (b), (c)) -#define LOGERRORX(a) log_printf ((a)) -#else -#define LOGERROR(a) fprintf (stderr, (a)) -#define LOGERROR1(a,b) fprintf (stderr, (a), (b)) -#define LOGERROR2(a,b,c) fprintf (stderr, (a), (b), (c)) -#define LOGERRORX(a) fputs ((a), stderr) -#endif - - - -static int -do_finish (ASSUAN_CONTEXT ctx) -{ - if (ctx->inbound.fd != -1) - { - close (ctx->inbound.fd); - } - ctx->inbound.fd = -1; - ctx->outbound.fd = -1; - return 0; -} - -static void -do_deinit (ASSUAN_CONTEXT ctx) -{ - do_finish (ctx); -} - - - -/* Make a connection to the Unix domain socket NAME and return a new - Assuan context in CTX. SERVER_PID is currently not used but may - becode handy in future. */ -AssuanError -assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, - const char *name, pid_t server_pid) -{ - AssuanError err; - ASSUAN_CONTEXT ctx; - int fd; - struct sockaddr_un srvr_addr; - size_t len; - - if (!r_ctx || !name) - return ASSUAN_Invalid_Value; - *r_ctx = NULL; - - /* we require that the name starts with a slash, so that we can - alter reuse this function for other socket types */ - if (*name != '/') - return ASSUAN_Invalid_Value; - if (strlen (name)+1 >= sizeof srvr_addr.sun_path) - return ASSUAN_Invalid_Value; - - err = _assuan_new_context (&ctx); - if (err) - return err; - ctx->pid = server_pid; /* save it in case we need it later */ - ctx->deinit_handler = do_deinit; - ctx->finish_handler = do_finish; - - fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - { - LOGERROR1 ("can't create socket: %s\n", strerror (errno)); - _assuan_release_context (ctx); - return ASSUAN_General_Error; - } - - memset (&srvr_addr, 0, sizeof srvr_addr ); - srvr_addr.sun_family = AF_UNIX; - strcpy (srvr_addr.sun_path, name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen (srvr_addr.sun_path) + 1); - - if (connect (fd, (struct sockaddr*)&srvr_addr, len) == -1) - { - LOGERROR2 ("can't connect to `%s': %s\n", name, strerror (errno)); - _assuan_release_context (ctx); - close (fd ); - return ASSUAN_Connect_Failed; - } - - ctx->inbound.fd = fd; - ctx->outbound.fd = fd; - - /* initial handshake */ - { - int okay, off; - - err = _assuan_read_from_server (ctx, &okay, &off); - if (err) - { - LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err)); - } - else if (okay != 1) - { - LOGERROR ("can't connect server: `"); - _assuan_log_sanitized_string (ctx->inbound.line); - LOGERRORX ("'\n"); - err = ASSUAN_Connect_Failed; - } - } - - if (err) - { - assuan_disconnect (ctx); - } - else - *r_ctx = ctx; - return 0; -} - - diff --git a/assuan/assuan-socket-server.c b/assuan/assuan-socket-server.c deleted file mode 100644 index bfa9cfa79..000000000 --- a/assuan/assuan-socket-server.c +++ /dev/null @@ -1,169 +0,0 @@ -/* assuan-socket-server.c - Assuan socket based server - * Copyright (C) 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include -#include - -#include "assuan-defs.h" - -static int -accept_connection_bottom (ASSUAN_CONTEXT ctx) -{ - int fd = ctx->connected_fd; - - ctx->client_pid = (pid_t)-1; -#ifdef HAVE_SO_PEERCRED - { - struct ucred cr; - int cl = sizeof cr; - - if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) ) - ctx->client_pid = cr.pid; - } -#endif - - ctx->inbound.fd = fd; - ctx->inbound.eof = 0; - ctx->inbound.linelen = 0; - ctx->inbound.attic.linelen = 0; - ctx->inbound.attic.pending = 0; - - ctx->outbound.fd = fd; - ctx->outbound.data.linelen = 0; - ctx->outbound.data.error = 0; - - ctx->confidential = 0; - - return 0; -} - - -static int -accept_connection (ASSUAN_CONTEXT ctx) -{ - int fd; - struct sockaddr_un clnt_addr; - size_t len = sizeof clnt_addr; - - ctx->client_pid = (pid_t)-1; - fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len ); - if (fd == -1) - { - ctx->os_errno = errno; - return ASSUAN_Accept_Failed; - } - - ctx->connected_fd = fd; - return accept_connection_bottom (ctx); -} - -static int -finish_connection (ASSUAN_CONTEXT ctx) -{ - if (ctx->inbound.fd != -1) - { - close (ctx->inbound.fd); - } - ctx->inbound.fd = -1; - ctx->outbound.fd = -1; - return 0; -} - - -static void -deinit_socket_server (ASSUAN_CONTEXT ctx) -{ - finish_connection (ctx); -} - - - -/* Initialize a server for the socket LISTEN_FD which has already be - put into listen mode */ -int -assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd) -{ - ASSUAN_CONTEXT ctx; - int rc; - - *r_ctx = NULL; - ctx = xtrycalloc (1, sizeof *ctx); - if (!ctx) - return ASSUAN_Out_Of_Core; - ctx->is_server = 1; - ctx->input_fd = -1; - ctx->output_fd = -1; - - ctx->inbound.fd = -1; - ctx->outbound.fd = -1; - - ctx->listen_fd = listen_fd; - ctx->connected_fd = -1; - ctx->deinit_handler = deinit_socket_server; - ctx->accept_handler = accept_connection; - ctx->finish_handler = finish_connection; - - rc = _assuan_register_std_commands (ctx); - if (rc) - xfree (ctx); - else - *r_ctx = ctx; - return rc; -} - -/* Initialize a server using the already accepted socket FD. */ -int -assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd) -{ - ASSUAN_CONTEXT ctx; - int rc; - - *r_ctx = NULL; - ctx = xtrycalloc (1, sizeof *ctx); - if (!ctx) - return ASSUAN_Out_Of_Core; - ctx->is_server = 1; - ctx->pipe_mode = 1; /* we wan't a second accept to indicate EOF */ - ctx->input_fd = -1; - ctx->output_fd = -1; - - ctx->inbound.fd = -1; - ctx->outbound.fd = -1; - - ctx->listen_fd = -1; - ctx->connected_fd = fd; - ctx->deinit_handler = deinit_socket_server; - ctx->accept_handler = accept_connection_bottom; - ctx->finish_handler = finish_connection; - - rc = _assuan_register_std_commands (ctx); - if (rc) - xfree (ctx); - else - *r_ctx = ctx; - return rc; -} - - diff --git a/assuan/assuan-util.c b/assuan/assuan-util.c deleted file mode 100644 index a335b09f7..000000000 --- a/assuan/assuan-util.c +++ /dev/null @@ -1,210 +0,0 @@ -/* assuan-util.c - Utility functions for Assuan - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 -#include -#include -#include - -#include "assuan-defs.h" - -#ifdef HAVE_JNLIB_LOGGING -#include "../jnlib/logging.h" -#endif - -ssize_t (*_assuan_read_wrapper)(int,void*,size_t) = NULL; -ssize_t (*_assuan_write_wrapper)(int,const void*,size_t) = NULL; - - -static void *(*alloc_func)(size_t n) = malloc; -static void *(*realloc_func)(void *p, size_t n) = realloc; -static void (*free_func)(void*) = free; - - - -void -assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), - void *(*new_realloc_func)(void *p, size_t n), - void (*new_free_func)(void*) ) -{ - alloc_func = new_alloc_func; - realloc_func = new_realloc_func; - free_func = new_free_func; -} - -void * -_assuan_malloc (size_t n) -{ - return alloc_func (n); -} - -void * -_assuan_realloc (void *a, size_t n) -{ - return realloc_func (a, n); -} - -void * -_assuan_calloc (size_t n, size_t m) -{ - void *p = _assuan_malloc (n*m); - if (p) - memset (p, 0, n* m); - return p; -} - -void -_assuan_free (void *p) -{ - if (p) - free_func (p); -} - -/* For use with Pth it is required to have special read and write - functions. We can't assume an ELF based system so we have to - explicitly set them if we are going to use Pth. */ -void -assuan_set_io_func (ssize_t (*r)(int,void*,size_t), - ssize_t (*w)(int,const void*,size_t)) -{ - _assuan_read_wrapper = r; - _assuan_write_wrapper = w; -} - - - -/* Store the error in the context so that the error sending function - can take out a descriptive text. Inside the assuan code, use the - macro set_error instead of this function. */ -int -assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text) -{ - ctx->err_no = err; - ctx->err_str = text; - return err; -} - -void -assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer) -{ - if (ctx) - ctx->user_pointer = pointer; -} - -void * -assuan_get_pointer (ASSUAN_CONTEXT ctx) -{ - return ctx? ctx->user_pointer : NULL; -} - - -void -assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp) -{ - if (ctx) - { - if (ctx->log_fp) - fflush (ctx->log_fp); - ctx->log_fp = fp; - } -} - - -void -assuan_begin_confidential (ASSUAN_CONTEXT ctx) -{ - if (ctx) - { - ctx->confidential = 1; - } -} - -void -assuan_end_confidential (ASSUAN_CONTEXT ctx) -{ - if (ctx) - { - ctx->confidential = 0; - } -} - -void -_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) -{ - const unsigned char *s; - int n; - - for (n=length,s=buffer; n; n--, s++) - { - if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0)) - break; - } - s = buffer; - if (!n && *s != '[') - fwrite (buffer, length, 1, fp); - else - { - putc ('[', fp); - for (n=0; n < length; n++, s++) - fprintf (fp, " %02x", *s); - putc (' ', fp); - putc (']', fp); - } -} - - -/* print a user supplied string after filtering out potential bad - characters*/ -void -_assuan_log_sanitized_string (const char *string) -{ - const unsigned char *s = string; -#ifdef HAVE_JNLIB_LOGGING - FILE *fp = log_get_stream (); -#else - FILE *fp = stderr; -#endif - - for (; *s; s++) - { - if (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)) - { - putc ('\\', fp); - if (*s == '\n') - putc ('n', fp); - else if (*s == '\r') - putc ('r', fp); - else if (*s == '\f') - putc ('f', fp); - else if (*s == '\v') - putc ('v', fp); - else if (*s == '\b') - putc ('b', fp); - else if (!*s) - putc ('0', fp); - else - fprintf (fp, "x%02x", *s ); - } - else - putc (*s, fp); - } -} - - diff --git a/assuan/assuan.h b/assuan/assuan.h deleted file mode 100644 index 51f648a3a..000000000 --- a/assuan/assuan.h +++ /dev/null @@ -1,234 +0,0 @@ -/* assuan.c - Definitions for the Assuan protocol - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. - * - * This file is part of Assuan. - * - * Assuan is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * Assuan 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 ASSUAN_H -#define ASSUAN_H - -#include -#include -#include /* for ssize_t */ - -#ifdef __cplusplus -extern "C" { -#if 0 - } -#endif -#endif - -typedef enum { - ASSUAN_No_Error = 0, - ASSUAN_General_Error = 1, - ASSUAN_Out_Of_Core = 2, - ASSUAN_Invalid_Value = 3, - ASSUAN_Timeout = 4, - ASSUAN_Read_Error = 5, - ASSUAN_Write_Error = 6, - ASSUAN_Problem_Starting_Server = 7, - ASSUAN_Not_A_Server = 8, - ASSUAN_Not_A_Client = 9, - ASSUAN_Nested_Commands = 10, - ASSUAN_Invalid_Response = 11, - ASSUAN_No_Data_Callback = 12, - ASSUAN_No_Inquire_Callback = 13, - ASSUAN_Connect_Failed = 14, - ASSUAN_Accept_Failed = 15, - - /* error codes above 99 are meant as status codes */ - ASSUAN_Not_Implemented = 100, - ASSUAN_Server_Fault = 101, - ASSUAN_Invalid_Command = 102, - ASSUAN_Unknown_Command = 103, - ASSUAN_Syntax_Error = 104, - ASSUAN_Parameter_Error = 105, - ASSUAN_Parameter_Conflict = 106, - ASSUAN_Line_Too_Long = 107, - ASSUAN_Line_Not_Terminated = 108, - ASSUAN_No_Input = 109, - ASSUAN_No_Output = 110, - ASSUAN_Canceled = 111, - ASSUAN_Unsupported_Algorithm = 112, - ASSUAN_Server_Resource_Problem = 113, - ASSUAN_Server_IO_Error = 114, - ASSUAN_Server_Bug = 115, - ASSUAN_No_Data_Available = 116, - ASSUAN_Invalid_Data = 117, - ASSUAN_Unexpected_Command = 118, - ASSUAN_Too_Much_Data = 119, - ASSUAN_Inquire_Unknown = 120, - ASSUAN_Inquire_Error = 121, - ASSUAN_Invalid_Option = 122, - ASSUAN_Invalid_Index = 123, - ASSUAN_Unexpected_Status = 124, - ASSUAN_Unexpected_Data = 125, - ASSUAN_Invalid_Status = 126, - - ASSUAN_Not_Confirmed = 128, - - ASSUAN_Bad_Certificate = 201, - ASSUAN_Bad_Certificate_Chain = 202, - ASSUAN_Missing_Certificate = 203, - ASSUAN_Bad_Signature = 204, - ASSUAN_No_Agent = 205, - ASSUAN_Agent_Error = 206, - ASSUAN_No_Public_Key = 207, - ASSUAN_No_Secret_Key = 208, - ASSUAN_Invalid_Name = 209, - - ASSUAN_Cert_Revoked = 301, - ASSUAN_No_CRL_For_Cert = 302, - ASSUAN_CRL_Too_Old = 303, - ASSUAN_Not_Trusted = 304, - - ASSUAN_Card_Error = 401, - ASSUAN_Invalid_Card = 402, - ASSUAN_No_PKCS15_App = 403, - ASSUAN_Card_Not_Present = 404, - ASSUAN_Invalid_Id = 405 - -} AssuanError; - -/* This is a list of pre-registered ASSUAN commands */ -typedef enum { - ASSUAN_CMD_NOP = 0, - ASSUAN_CMD_CANCEL, /* cancel the current request */ - ASSUAN_CMD_BYE, - ASSUAN_CMD_AUTH, - ASSUAN_CMD_RESET, - ASSUAN_CMD_OPTION, - ASSUAN_CMD_DATA, - ASSUAN_CMD_END, - ASSUAN_CMD_INPUT, - ASSUAN_CMD_OUTPUT, - - ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/ -} AssuanCommand; - -#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */ - -struct assuan_context_s; -typedef struct assuan_context_s *ASSUAN_CONTEXT; - -/*-- assuan-handler.c --*/ -int assuan_register_command (ASSUAN_CONTEXT ctx, - int cmd_id, const char *cmd_string, - int (*handler)(ASSUAN_CONTEXT, char *)); -int assuan_register_bye_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT)); -int assuan_register_reset_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT)); -int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT)); -int assuan_register_input_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT, const char *)); -int assuan_register_output_notify (ASSUAN_CONTEXT ctx, - void (*fnc)(ASSUAN_CONTEXT, const char *)); - -int assuan_register_option_handler (ASSUAN_CONTEXT ctx, - int (*fnc)(ASSUAN_CONTEXT, - const char*, const char*)); - -int assuan_process (ASSUAN_CONTEXT ctx); -int assuan_process_next (ASSUAN_CONTEXT ctx); -int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what, - int *fdarray, int fdarraysize); - - -FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx); -AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line); -void assuan_write_status (ASSUAN_CONTEXT ctx, - const char *keyword, const char *text); - - -/*-- assuan-listen.c --*/ -AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line); -AssuanError assuan_accept (ASSUAN_CONTEXT ctx); -int assuan_get_input_fd (ASSUAN_CONTEXT ctx); -int assuan_get_output_fd (ASSUAN_CONTEXT ctx); -AssuanError assuan_close_input_fd (ASSUAN_CONTEXT ctx); -AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx); - - -/*-- assuan-pipe-server.c --*/ -int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]); -void assuan_deinit_server (ASSUAN_CONTEXT ctx); - -/*-- assuan-socket-server.c --*/ -int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd); -int assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd); - - -/*-- assuan-pipe-connect.c --*/ -AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, - char *const argv[], int *fd_child_list); -/*-- assuan-socket-connect.c --*/ -AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name, - pid_t server_pid); - -/*-- assuan-connect.c --*/ -void assuan_disconnect (ASSUAN_CONTEXT ctx); -pid_t assuan_get_pid (ASSUAN_CONTEXT ctx); - -/*-- assuan-client.c --*/ -AssuanError -assuan_transact (ASSUAN_CONTEXT ctx, - const char *command, - AssuanError (*data_cb)(void *, const void *, size_t), - void *data_cb_arg, - AssuanError (*inquire_cb)(void*, const char *), - void *inquire_cb_arg, - AssuanError (*status_cb)(void*, const char *), - void *status_cb_arg); - - -/*-- assuan-inquire.c --*/ -AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword, - char **r_buffer, size_t *r_length, size_t maxlen); - -/*-- assuan-buffer.c --*/ -AssuanError assuan_read_line (ASSUAN_CONTEXT ctx, - char **line, size_t *linelen); -int assuan_pending_line (ASSUAN_CONTEXT ctx); -AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line ); -AssuanError assuan_send_data (ASSUAN_CONTEXT ctx, - const void *buffer, size_t length); - - -/*-- assuan-util.c --*/ -void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), - void *(*new_realloc_func)(void *p, size_t n), - void (*new_free_func)(void*) ); -void assuan_set_io_func (ssize_t (*r)(int,void*,size_t), - ssize_t (*w)(int,const void*,size_t)); -void assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp); -int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text); -void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer); -void *assuan_get_pointer (ASSUAN_CONTEXT ctx); - -void assuan_begin_confidential (ASSUAN_CONTEXT ctx); -void assuan_end_confidential (ASSUAN_CONTEXT ctx); - -/*-- assuan-errors.c (built) --*/ -const char *assuan_strerror (AssuanError err); - - -#ifdef __cplusplus -} -#endif -#endif /*ASSUAN_H*/ diff --git a/assuan/mkerrors b/assuan/mkerrors deleted file mode 100755 index d0c59ff38..000000000 --- a/assuan/mkerrors +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -# mkerrors - Extract error strings from assuan.h -# and create C source for assuan_strerror -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. -# -# This file is part of Assuan. -# -# Assuan is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of -# the License, or (at your option) any later version. -# -# Assuan 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser 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 < -#include "assuan.h" - -/** - * assuan_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 * -assuan_strerror (AssuanError err) -{ - const char *s; - static char buf[25]; - - switch (err) - { -EOF - -awk ' -/ASSUAN_No_Error/ { okay=1 } -!okay {next} -/}/ { exit 0 } -/ASSUAN_[A-Za-z_]*/ { print_code($1) } - - -function print_code( s ) -{ -printf " case %s: s=\"", s ; -gsub(/_/, " ", s ); -printf "%s\"; break;\n", tolower(substr(s,8)); -} -' - -cat < - - * Makefile.am: Add gpg_dearmor to all targets where it is used. - Noted by Andreas Haumer. - -2002-04-19 Werner Koch - - * signencrypt-dsa.test, sigs-dsa.test: Don't check with MD5 as - this is not valid with DSA signatures. - -2001-12-22 Werner Koch - - * options.in: Add no-permission-warning. - -2001-12-21 Werner Koch - - * Makefile.am (distclean-local): prefix mkdemodirs with srcdir - (DISTCLEANFILES): Add random_seed. - -2001-12-19 Werner Koch - - * options.in: Remove load-extension tiger - * Makefile.am (./options): append it if there is such a module. - -2001-10-23 Werner Koch - - * defs.inc, Makefile.am: Do not use $srcdir when invoking gpg. - Write the logfile to the current directory. - -2001-09-28 Werner Koch - - * defs.inc: Write a log file for each test. - * run-gpg, run-gpgm, run-gpg.patterns: Removed. Replaced in all - tests by a simple macro from defs.inc. - * Makefile.am (CLEANFILES): Remove log files. - (./gpg_dearmor): create it and use it instead of the macro. - This is needed in multisig.test due to IFS tricks. - - * armsignencrypt.test, signencrypt-dsa.test, signencrypt.test, - armencryptp.test, armencrypt.test, encryptp.test, seat.test, - encrypt-dsa.test, encrypt.test: Use --always-trust because the - test are not designed to check the validity. - -2001-09-06 Werner Koch - - * genkey1024.test: Simplified by using a parameter file. - -2001-05-30 Werner Koch - - * multisig.test (IFS): Reset IFS just before the test. - -2001-04-30 Werner Koch - - * multisig.test: Add an set +x to avoid ksh problems - -2001-04-28 Werner Koch - - * run-gpg.patterns: a v3 test key expired yesterday, suppress the - messages. - -2001-03-27 Werner Koch - - * defs.inc: Removed creation of options file. - * options.in: New. - * Makefile.am: Create options file and fixed import of pubdemo.asc. - - * run-gpg.patterns (gpg): Add some more patterns. - -2001-03-20 Werner Koch - - * Makefile.am: Import the pubdemo.asc file - - * sigs.test (hash_algo_list): s/tiger/tiger192/ - -2001-03-19 Werner Koch - - * mkdemodirs (GPGDEMO): Add --allow-secret-key-import to all gpg - invocations. Use echon -n instead of an argument with \c. - -2001-02-12 Werner Koch - - * multisig.test: new - * Makefile.am (TESTS): Added. - -2000-10-18 Werner Koch - - * conventional-mdc.test: Add Rijndael and fix for empty plain texts. - -Thu Feb 10 17:39:44 CET 2000 Werner Koch - - * mkdemodirs: Fixed the --clean loop. - -Thu Jan 13 19:31:58 CET 2000 Werner Koch - - * defs.inc (chdir): Removed becuase it is unsused an plain old sh - does not like this name. Reported by Alec Habig. - -Tue Oct 26 20:02:23 1999 Werner Koch (wk@gnupg.org) - - * Makefile.am (GPG_DEARMOR): New and use --no-options. - -Tue Aug 31 17:20:44 CEST 1999 Werner Koch - - * defs.inc: set LC_ALL empty - -Wed Aug 4 10:34:18 CEST 1999 Werner Koch - - * defs.inc (echo_n): New and used instead of /bin/echo "\c" - -Sun Apr 18 10:11:28 CEST 1999 Werner Koch - - * mkdemodirs: New - * signdemokey: New. - * Makefile.am (distclean-local): New. - -Wed Mar 17 13:09:03 CET 1999 Werner Koch - - * mds.test: replaced the "echo -n" - -Mon Mar 8 20:47:17 CET 1999 Werner Koch - - * pubdemo.asc, secdemo.asc: New. - -Fri Feb 19 15:49:15 CET 1999 Werner Koch - - * genkey1024.test: Be really quiet. - -1999-01-01 Geoff Keating - - * Makefile.am (CLEANFILES): Also delete trustdb and any leftover - lockfiles. - -Fri Nov 27 15:30:24 CET 1998 Werner Koch - - * clearsig.test: Some more test cases. - -Sun Oct 25 18:19:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mds.test: Check whether TIGER is available. - * sigs.tesr: Ditto. - -Wed Sep 23 12:25:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * run-gpg.patterns: New (because Solaris fgrep does not like -f -). - -Mon Aug 10 21:33:38 1998 Werner Koch (wk@(none)) - - * genkey1024.test: Ariel fixed this. - -Wed Jul 8 10:43:47 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seat.test: New. - -Mon May 18 15:40:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am: Now uses mk-tdata to produce random test data. - - * ChangeLog: New. - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/checks/Makefile.am b/checks/Makefile.am deleted file mode 100644 index ed779a432..000000000 --- a/checks/Makefile.am +++ /dev/null @@ -1,107 +0,0 @@ -# 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 - -# Process this file with automake to create Makefile.in - -GPG_IMPORT = ../g10/gpg --homedir . --quiet --yes --import - -TESTS = version.test mds.test \ - decrypt.test decrypt-dsa.test \ - sigs.test sigs-dsa.test \ - encrypt.test encrypt-dsa.test \ - seat.test clearsig.test encryptp.test detach.test \ - armsigs.test armencrypt.test armencryptp.test \ - signencrypt.test signencrypt-dsa.test \ - armsignencrypt.test armdetach.test \ - armdetachm.test detachm.test genkey1024.test \ - conventional.test conventional-mdc.test \ - multisig.test - - -TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \ - plain-1.asc plain-2.asc plain-3.asc plain-1-pgp.asc \ - pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc options.in - -DATA_FILES = data-500 data-9000 data-32000 data-80000 plain-large - -EXTRA_DIST = defs.inc $(TESTS) $(TEST_FILES) \ - mkdemodirs signdemokey -CLEANFILES = prepared.stamp x y yy z out err $(DATA_FILES) \ - plain-1 plain-2 plain-3 trustdb.gpg *.lock .\#lk* \ - *.test.log options gpg_dearmor \ - pubring.gpg secring.gpg pubring.pkr secring.skr -DISTCLEANFILES = pubring.gpg~ random_seed - - -all-local: prepared.stamp - -distclean-local: - $(srcdir)/mkdemodirs --clean - -prepared.stamp: ./pubring.gpg ./secring.gpg ./plain-1 ./plain-2 ./plain-3 \ - ./pubring.pkr ./secring.skr ./options ./gpg_dearmor \ - $(DATA_FILES) - $(GPG_IMPORT) $(srcdir)/pubdemo.asc - echo timestamp >./prepared.stamp - -./options: $(srcdir)/options.in - cat $(srcdir)/options.in >./options - @set -e; if echo "@DYNAMIC_CIPHER_MODS@" |grep tiger >/dev/null ;then \ - echo load-extension ../cipher/tiger >>./options; fi - -./gpg_dearmor: - echo '#!/bin/sh' >./gpg_dearmor - echo "../g10/gpg --no-options --no-greeting \ - --no-secmem-warning --batch --dearmor" >>./gpg_dearmor - chmod 755 ./gpg_dearmor - -./pubring.gpg: $(srcdir)/pubring.asc $(srcdir)/pubdemo.asc ./gpg_dearmor - ./gpg_dearmor > ./pubring.gpg < $(srcdir)/pubring.asc - -./secring.gpg: $(srcdir)/secring.asc ./gpg_dearmor - ./gpg_dearmor > ./secring.gpg < $(srcdir)/secring.asc - -./pubring.pkr: $(srcdir)/pubring.pkr.asc ./gpg_dearmor - ./gpg_dearmor > ./pubring.pkr < $(srcdir)/pubring.pkr.asc - -./secring.skr: $(srcdir)/secring.skr.asc ./gpg_dearmor - ./gpg_dearmor > ./secring.skr < $(srcdir)/secring.skr.asc - -./plain-1: $(srcdir)/plain-1o.asc ./gpg_dearmor - ./gpg_dearmor > ./plain-1 < $(srcdir)/plain-1o.asc - -./plain-2: $(srcdir)/plain-2o.asc ./gpg_dearmor - ./gpg_dearmor > ./plain-2 < $(srcdir)/plain-2o.asc - -./plain-3: $(srcdir)/plain-3o.asc ./gpg_dearmor - ./gpg_dearmor > ./plain-3 < $(srcdir)/plain-3o.asc - - -data-500: - ../tools/mk-tdata 500 >data-500 -data-9000: - ../tools/mk-tdata 9000 >data-9000 -data-32000: - ../tools/mk-tdata 32000 >data-32000 -data-80000: - ../tools/mk-tdata 80000 >data-80000 -plain-large: - cat $(srcdir)/../doc/HACKING \ - $(srcdir)/../doc/DETAILS \ - $(srcdir)/../doc/FAQ >plain-large - diff --git a/checks/armdetach.test b/checks/armdetach.test deleted file mode 100755 index c445d6ce6..000000000 --- a/checks/armdetach.test +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - - -#info Checking armored detached signatures -for i in $plain_files $data_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 -sab -o x --yes $i - $GPG -o /dev/null --yes x <$i || error "$i: bad signature" -done - diff --git a/checks/armdetachm.test b/checks/armdetachm.test deleted file mode 100755 index f1958424c..000000000 --- a/checks/armdetachm.test +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking armored detached signatures of multiple files -i="$plain_files $data_files" -echo "$usrpass1" | $GPG --passphrase-fd 0 -sab -o x --yes $i -cat $i | $GPG -o /dev/null --yes x || error "$i: bad signature" - diff --git a/checks/armencrypt.test b/checks/armencrypt.test deleted file mode 100755 index 356d1bda7..000000000 --- a/checks/armencrypt.test +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking armored encryption -for i in $plain_files $data_files ; do - $GPG --always-trust -ea -o x --yes -r "$usrname2" $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/armencryptp.test b/checks/armencryptp.test deleted file mode 100755 index d18c56b7e..000000000 --- a/checks/armencryptp.test +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking armored encryption with a pipe -for i in $plain_files $data_files ; do - $GPG --always-trust -ea --yes -r "$usrname2" < $i | tee x | $GPG -o y --yes - cmp $i y || error "$i: mismatch" - $GPG --yes < x > y - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/armsignencrypt.test b/checks/armsignencrypt.test deleted file mode 100755 index 24b9575ad..000000000 --- a/checks/armsignencrypt.test +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - - -#info Checking armored signing and encryption -for i in $plain_files $data_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust \ - -sae -o x --yes -r "$usrname2" $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/armsigs.test b/checks/armsigs.test deleted file mode 100755 index aecc06429..000000000 --- a/checks/armsigs.test +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking armored signatures -for i in $plain_files $data_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 -sa -o x --yes $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/challenge-1 b/checks/challenge-1 deleted file mode 100644 index 6f97880d6..000000000 --- a/checks/challenge-1 +++ /dev/null @@ -1,42 +0,0 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: RIPEMD160 - -I promise to delivery 8 bottles of "Fchschen" to the first one who tells me -the plaintext of the following message or is able to forge the signature -on this file. Don't try to get my secret key, it does not exist any longer. -For those who don't know: Fchschen is a beer brewed here in Dsseldorf. -This promise is valid for 2 years from now (29.5.1998). - - -Good luck, - - Werner - - -- -----BEGIN PGP MESSAGE----- -Version: GNUPG v0.2.19 (GNU/Linux) -Comment: This is an alpha version! - -hQEOA+Pk8EXQYMj+FAP/V8XiybbbGVReNAKbknj9nqaHHVOjPdwBXyOBLRBEC5TiMhe/APmq -XN3esJ/MU97eN9lZMVBLIwG4/jqzT/g2ULd3rZtWwgcyV1cDehGVun8cp0CbsM6QH8lhItLo -fEqQ8u44q4ZO9drcswcA24Bn0j9dkX7sbyJTEtipj1LGjoUD/i5+e1sIQEWb5esA1WXIPWVS -b8e8d/JnH4acQbTFH+1mrE2PtGD18IbM2PdTilcC/l4KNKcyWfsuoJmwoG5x/ciQUhpqn/fW -WBjH99tbK8kIHSbgQ4FrMhS+I6Z3pH0EbViDC20f7TgZgGShVHUM/0BGcavVdd1vjUK4MZag -kwJwpwBNGRPSazs8NKyjiAQupIC+xbZG+Qcz67xmOWU92qmfr3h6wrk8JJGsPOynGExJFNKv -PwKckh3z7surZLhPeDMuZykGcEtFmJJbVBK+cIcAAA== -=o6Ev -- -----END PGP MESSAGE----- - - ------BEGIN PGP SIGNATURE----- -Version: GNUPG v0.2.19 (GNU/Linux) -Comment: This is an alpha version! - -iQEXAwUBNW6hBuPk8EXQYMj+FAN5GQP+NhSpe3WmGfWYYQSOM4CxlgNv+EmpDvvDBCmxyKT6 -oVw+YD1b6q0XCkSx5u1b/ykwPbPS8VUxPqEKFBOtVWNQbCfmMRujUtPYWm8eomIHO3k7l0DF -H8nah5gdwvOheB5YMUfhtuKQRk8/d8QRrsoc44OmB7znkLvQEMMaHxrgb5AD/31/TocHnNj6 -iC61cQrwTDSj2nLFWHn2yQ7uX5j9fBxCJgbQq6Aku17Z6LHDu6FfaMigS9l6s5VT2n4XuzFl -qV2GMe20HU5JgrprU1cTULtr1yc3KUctnI3tcGt4UoF0Rt/IcPDdPTIcWScmUd01v4x1zVV9 -n6Qxh+yxRMwl+Oo+ -=gI9G ------END PGP SIGNATURE----- diff --git a/checks/clearsig.test b/checks/clearsig.test deleted file mode 100755 index 89d323317..000000000 --- a/checks/clearsig.test +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/sh - - -# Fixme: we should not only do a --verify but also the output. - - - -. $srcdir/defs.inc || exit 3 - - -# ====================================== -# I can't compare the out because plain-3 has no LF as last charcater -# but the output has always one. I do not thinkl this is a bug, because -# it is clear text and not binary text. -# ====================================== -for i in $plain_files plain-large ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 -sat -o x --yes $i - $GPG --verify x -done - -# ====================================== -# and once more to check rfc1991 -# ====================================== -for i in $plain_files plain-large ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 \ - --rfc1991 --digest-algo md5 -sat -o x --yes $i - $GPG --verify x -done - -# ====================================== -# and one with long lines -# ====================================== -cat >y <y <y <y <y -echo_n " " >>y -echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y -$GPG --verify x - - -# ====================================== -# check our special diff mode -# ====================================== -cat >y <mfx.md, n1->pkt->pkt.signature->digest_algo); - } - /* ask for file and hash it */ -- if( c->sigs_only ) { -+ if( c->sigs_only ) - rc = hash_datafiles( c->mfx.md, NULL, - c->signed_data, c->sigfilename, - n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); -EOF -echo "$usrpass1" | $GPG --passphrase-fd 0 \ - --not-dash-escaped --clearsign -o x --yes y -$GPG --verify x - - - - diff --git a/checks/conventional-mdc.test b/checks/conventional-mdc.test deleted file mode 100755 index 463e0c49f..000000000 --- a/checks/conventional-mdc.test +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking conventional encryption -for i in 0 1 2 3 9 10 11 19 20 21 22 23 39 40 41 8192 32000 ; do - for ciph in 3des cast5 blowfish twofish rijndael; do - # *BSD's dd can't cope with a count of 0 - if test "$i" = "0"; then - : >z - else - dd if=data-80000 of=z bs=1 count=$i 2>/dev/null - fi - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \ - --force-mdc --cipher $ciph -c -o x --yes z - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \ - -o y --yes x - cmp z y || error "$ciph/$i: mismatch" - done -done - diff --git a/checks/conventional.test b/checks/conventional.test deleted file mode 100755 index 87aeb9c56..000000000 --- a/checks/conventional.test +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -# temp. hack cause the format for 128 bit blocksize messages may change -GNUPG_ENABLE_TWOFISH=1 -export GNUPG_ENABLE_TWOFISH - -#info Checking conventional encryption -for i in plain-2 data-32000 ; do - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -c -o x --yes $i - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x - cmp $i y || error "$i: mismatch" -done - -for a in cast5 3des twofish; do - for i in plain-1 data-80000 ; do - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \ - --cipher-algo $a -c -o x --yes $i - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x - cmp $i y || error "$i: ($a) mismatch" - done -done - diff --git a/checks/decrypt-dsa.test b/checks/decrypt-dsa.test deleted file mode 100755 index 6dc7dc459..000000000 --- a/checks/decrypt-dsa.test +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking decryption of supplied DSA encrypted file -for i in "plain-1" ; do - $GPG $dsa_keyrings -o y --yes $srcdir/$i-pgp.asc - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/decrypt.test b/checks/decrypt.test deleted file mode 100755 index aab416750..000000000 --- a/checks/decrypt.test +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking decryption of supplied files -for i in $plain_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 -o y --yes $srcdir/$i.asc - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/defs.inc b/checks/defs.inc deleted file mode 100755 index 2eb25c7f1..000000000 --- a/checks/defs.inc +++ /dev/null @@ -1,106 +0,0 @@ -# definitions for the check scripts - -#-------------------------------- -#------ constants --------------- -#-------------------------------- - -# Note that usrpass1 is also used in Makefile.am -usrname1="one" -usrpass1="def" -usrname2="two" -usrpass2="" -usrname3="three" -usrpass3="abc" - - -dsa_usrname1="pgp5" -# we use the sub key because we do not yet have the logic to -# to derive the first encryption key from a keyblock (I guess) -dsa_usrname2="0xCB879DE9" - -dsa_keyrings="--keyring ./pubring.pkr --secret-keyring ./secring.skr" - - -plain_files="plain-1 plain-2 plain-3" -data_files="data-500 data-9000 data-32000 data-80000" -exp_files="" - -# The testscripts expect the original language -LANG= -LANGUAGE= -LC_ALL= -LC_MESSAGES= - -#-------------------------------- -#------ utility functions ------- -#-------------------------------- - -fatal () { - echo "$pgmname: fatal:" $* >&2 - exit 1; -} - -error () { - echo "$pgmname:" $* >&2 - exit 1 -} - -info () { - echo "$pgmname:" $* >&2 -} - - -echo_n_init=no -echo_n () { - if test "$echo_n_init" = "no"; then - if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - echo_n_n= - echo_n_c=' -' - else - echo_n_n='-n' - echo_n_c= - fi - else - echo_n_n= - echo_n_c='\c' - fi - echo_n_init=yes - fi - echo $echo_n_n "${1}$echo_n_c" -} - - -#cleanup () { -# rm $cleanup_files 2>/dev/null || true -# echo "#empty" >./options -#} - - -#add_cleanup () { -# cleanup_files="$cleanup_files $*" -#} - - -have_hash_algo () { - if ../g10/gpg --homedir . --version | grep "Hash:.*$1" >/dev/null - then - true - else - false - fi -} - -set -e -pgmname=`basename $0` -#trap cleanup SIGHUP SIGINT SIGQUIT - -[ -z "$srcdir" ] && fatal "not called from make" - -GPG="../g10/gpg --homedir . " - -exec 2> ${pgmname}.log - -: -# end \ No newline at end of file diff --git a/checks/detach.test b/checks/detach.test deleted file mode 100755 index 6a3ae05c5..000000000 --- a/checks/detach.test +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking detached signatures -for i in $plain_files $data_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 -sb -o x --yes $i - $GPG -o /dev/null --yes x <$i || error "$i: bad signature" -done - diff --git a/checks/detachm.test b/checks/detachm.test deleted file mode 100755 index dc60bb239..000000000 --- a/checks/detachm.test +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking detached signatures of multiple files -i="$plain_files $data_files" -echo "$usrpass1" | $GPG --passphrase-fd 0 -sb -o x --yes $i -cat $i | $GPG -o /dev/null --yes x || error "$i: bad signature" - diff --git a/checks/encrypt-dsa.test b/checks/encrypt-dsa.test deleted file mode 100755 index 27891bf01..000000000 --- a/checks/encrypt-dsa.test +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking encryption -for i in $plain_files $data_files ; do - $GPG $dsa_keyrings --always-trust -e -o x --yes -r "$dsa_usrname2" $i - $GPG $dsa_keyrings -o y --yes x - cmp $i y || error "$i: mismatch" -done - -# and with cast -for i in $plain_files $data_files ; do - $GPG $dsa_keyrings --always-trust --cipher-algo cast5 -e \ - -o x --yes -r "$dsa_usrname2" $i - $GPG $dsa_keyrings -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/encrypt.test b/checks/encrypt.test deleted file mode 100755 index 4e5c5c042..000000000 --- a/checks/encrypt.test +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking encryption -for i in $plain_files $data_files ; do - $GPG --always-trust -e -o x --yes -r "$usrname2" $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done -for i in $plain_files $data_files ; do - $GPG --always-trust -e -o x --yes -r "$usrname2" --cipher-algo cast5 $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/encryptp.test b/checks/encryptp.test deleted file mode 100755 index 7df24efec..000000000 --- a/checks/encryptp.test +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking encryption with a pipe -for i in $plain_files $data_files ; do - $GPG --always-trust -e --yes -r "$usrname2" <$i | $GPG --yes > y - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/genkey1024.test b/checks/genkey1024.test deleted file mode 100755 index e9852d7b6..000000000 --- a/checks/genkey1024.test +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -../g10/gpg --quiet --batch --quick-random --homedir . --gen-key <y -test_one "MD5" "D41D8CD98F00B204E9800998ECF8427E" -test_one "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" -test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31" -if have_hash_algo "TIGER"; then - test_one "TIGER" "24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A" -else - echo "Hash algorithm TIGER/192 is not installed" -fi - -[ "$failed" != "" ] && error "$failed failed for empty string" - -echo_n "abcdefghijklmnopqrstuvwxyz" | $GPG --print-mds >y -test_one "MD5" "C3FCD3D76192E4007DFB496CCA67E13B" -test_one "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89" -test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC" -if have_hash_algo "TIGER"; then - test_one "TIGER" "307DE5EE72A414172A0355CCBF120404E9EE7BF32F60110B" -fi - - -[ "$failed" != "" ] && error "$failed failed for a..z" - -exit 0 - diff --git a/checks/mkdemodirs b/checks/mkdemodirs deleted file mode 100755 index d6b7d7c4c..000000000 --- a/checks/mkdemodirs +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -set -e - -GPG="../g10/gpg --batch --quiet --no-secmem-warning --allow-secret-key-import" -NAMES='Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India - Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo - Sierra Tango Uniform Victor Whisky XRay Yankee Zulu' - -if [ "$1" = "--clean" ]; then - (for i in $NAMES; do - [ -d $i ] && rm -r $i - done) || true - exit 0 -fi - -$GPG --dearmor -o secdemo.gpg --yes ../checks/secdemo.asc -$GPG --dearmor -o pubdemo.gpg --yes ../checks/pubdemo.asc -[ -f ./tdb.tmp ] && rm ./tdb.tmp -GPGDEMO="$GPG --homedir . --trustdb-name ./tdb.tmp --no-default-keyring - --keyring pubdemo.gpg --secret-keyring secdemo.gpg" -echo -n "Creating:" -for name in $NAMES; do - echo -n " $name" - [ -d $name ] && rm -r $name - mkdir $name - $GPGDEMO --export-secret-key -o - $name > $name/Secret.gpg - $GPG --homedir $name --import $name/Secret.gpg - $GPGDEMO --export -o - $name > $name/Public.gpg - $GPG --homedir $name --import $name/Public.gpg - [ -f $name/pubring.gpg~ ] && rm $name/pubring.gpg~ -done -echo "." -[ -f ./tdb.tmp ] && rm ./tdb.tmp -rm pubdemo.gpg secdemo.gpg - - diff --git a/checks/multisig.test b/checks/multisig.test deleted file mode 100755 index c391f6fdc..000000000 --- a/checks/multisig.test +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/sh -# Check that gpg verifies only signatures where there is no ambiguity -# in the order of packets. Needs the Demo Keys Lima and Mike. - -. $srcdir/defs.inc || exit 3 - -# (variable intialization was created using: -# for i in files; do echo "`echo $i | sed 's,[.-],_,g'`='"; \ -# gpg --no-version --enarmor <$i | grep -v ^Comment:; echo "'" ; done -# ) - -sig_1ls1ls_valid=' ------BEGIN PGP ARMORED FILE----- - -kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg -ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e -8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOZANAwACETfKtR+3kQP4AawnYgV0ZXh0 -MTqIKvRJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCr0N8q1H7eR -A/gRAto6AKCWkmlzmRLUmakO/NByFxu+3vDwewCeMAqa5mhUztHwWk3Fw7hDgXQF -pzk= -=8jSC ------END PGP ARMORED FILE----- -' -sig_ls_valid=' ------BEGIN PGP ARMORED FILE----- - -rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI -K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT -QDUFTH2PvZRxjw== -=J+lb ------END PGP ARMORED FILE----- -' -sig_sl_valid=' ------BEGIN PGP ARMORED FILE----- - -iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU -tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n -dCBkbyB0aGF0Cg== -=N9MP ------END PGP ARMORED FILE----- -' -sig_11lss_valid_but_is_not=' ------BEGIN PGP ARMORED FILE----- - -kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g -c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT -mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy -XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB -Q341WRXKS/at -=Ekrs ------END PGP ARMORED FILE----- -' -sig_11lss11lss_valid_but_is_not=' ------BEGIN PGP ARMORED FILE----- - -kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g -c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT -mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy -XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB -Q341WRXKS/atkA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQx -OogyXUkgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED -+BECwQAAnRXTmXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp -5Yg/AwUAOogyXTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0 -P01WmbgZJoZBQ341WRXKS/at -=P1Mu ------END PGP ARMORED FILE----- -' -sig_ssl_valid_but_is_not=' ------BEGIN PGP ARMORED FILE----- - -iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU -tH60PslLE0A1BUx9j72UcY+IPwMFADqIK0s3yrUft5ED+BECLQMAn2jZUNOpB4Ou -urSQkc2TRfg6ek02AJ9+oJS0frQ+yUsTQDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJ -IGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQK -=Zven ------END PGP ARMORED FILE----- -' -sig_1lsls_invalid=' ------BEGIN PGP ARMORED FILE----- - -kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg -ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e -8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOawnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5 -LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeD -rrq0kJHNk0X4OnpNNgCffqCUtH60PslLE0A1BUx9j72UcY8= -=nkeu ------END PGP ARMORED FILE----- -' -sig_lsls_invalid=' ------BEGIN PGP ARMORED FILE----- - -rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI -K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT -QDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRo -YXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCf -fqCUtH60PslLE0A1BUx9j72UcY8= -=BlZH ------END PGP ARMORED FILE----- -' -sig_lss_invalid=' ------BEGIN PGP ARMORED FILE----- - -rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI -K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT -QDUFTH2PvZRxj4g/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF -+Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGP -=jmt6 ------END PGP ARMORED FILE----- -' -sig_slsl_invalid=' ------BEGIN PGP ARMORED FILE----- - -iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU -tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n -dCBkbyB0aGF0Cog/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF -+Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGPrCdiBXRleHQxOogrS0kgYW0gc29y -cnksIEkgY2FuJ3QgZG8gdGhhdAo= -=phBF ------END PGP ARMORED FILE----- -' - -save_IFS="${IFS}" -IFS="" -for i in "$sig_1ls1ls_valid" "$sig_ls_valid" "$sig_sl_valid"; do - echo "$i" | ./gpg_dearmor >x - IFS="${save_IFS}" - $GPG --verify x 2>/dev/null || error "valid is invalid" - IFS="" -done -#for i in "$sig_11lss_valid_but_is_not" "$sig_11lss11lss_valid_but_is_not" \ -# "$sig_ssl_valid_but_is_not"; do -# echo "$i" | $GPG --dearmor >x -# $GPG --verify /dev/null || error "valid is invalid" -#done - -# without the +e ksh seems to terminate the for loop -set +e -for i in "$sig_1lsls_invalid" "$sig_lsls_invalid" \ - "$sig_lss_invalid" "$sig_slsl_invalid" ; do - echo "$i" | ./gpg_dearmor >x - IFS="${save_IFS}" - $GPG --verify /dev/null && error "invalid is valid" - IFS="" -done -IFS="${save_IFS}" diff --git a/checks/options.in b/checks/options.in deleted file mode 100644 index c789164aa..000000000 --- a/checks/options.in +++ /dev/null @@ -1,6 +0,0 @@ -no-greeting -no-secmem-warning -no-permission-warning -batch -emulate-md-encode-bug -no-auto-check-trustdb diff --git a/checks/pgp263-test.pub.asc b/checks/pgp263-test.pub.asc deleted file mode 100644 index 53310d778..000000000 --- a/checks/pgp263-test.pub.asc +++ /dev/null @@ -1,14 +0,0 @@ -Type Bits/KeyID Date User ID -pub 888/A50283F1 2001/11/08 pgp2.6.3-test-key - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: 2.6.3a - -mQB8AzvqRosAAAEDeNMKLJMJQeGC2RG5Nec6R2mzC12N1wGLiYYJCsmSQd1Y8mht -A2Sc+4k/q5+l6GHtfqUR/RTCIIudAZUzrQVIMhHDKF+5de9lsE5QxQS1u43QGVCb -/9IYrOLOizYQ2pkBtD9LCrf7W2DccMEkpQKD8QAFE7QRcGdwMi42LjMtdGVzdC1r -ZXmJAIQDBRA76kaL3HDBJKUCg/EBAZMoA3Yqqdix6B2RAzywi9bKSLqwAFVL+MMw -W+BnYeBXF9u+bPpQvtyxgi0vx8F9r84B3HAhZNEjBWODF6vctIQhXhAhXIniDTSj -HNzQ/+nbWnebQn18XUV2SdM1PzMOblD+nISte7+WUfWzlD7YUJPkFPw= -=b498 ------END PGP PUBLIC KEY BLOCK----- diff --git a/checks/pgp263-test.sec.asc b/checks/pgp263-test.sec.asc deleted file mode 100644 index 78992e3b7..000000000 --- a/checks/pgp263-test.sec.asc +++ /dev/null @@ -1,18 +0,0 @@ -Type Bits/KeyID Date User ID -sec 888/A50283F1 2001/11/08 pgp2.6.3-test-key - ------BEGIN PGP SECRET KEY BLOCK----- -Version: 2.6.3a - -lQGdAzvqRosAAAEDeNMKLJMJQeGC2RG5Nec6R2mzC12N1wGLiYYJCsmSQd1Y8mht -A2Sc+4k/q5+l6GHtfqUR/RTCIIudAZUzrQVIMhHDKF+5de9lsE5QxQS1u43QGVCb -/9IYrOLOizYQ2pkBtD9LCrf7W2DccMEkpQKD8QAFEwADd0Kk5aeyFM3zbPgfikkE -7iFg9h2LG3nARmA4wAnCZaQ3CS5zRHCdXOf5KLkm6xFza1yMat4iWx6ULvuuNpIc -RmkHccyXYkRi3Hvacd5A9VCNw1UKtCdaCKgacsfplU0s1xYWGZd4J8Jg8boSfW5W -gwG8Dc9R20HHno8uD2vfr5rg8ElWvbFyJI/j4eCVAd+NYAGNvB8I3VP38IIYcavh -YYcGjrpxbGVRybsBvA9IJltpGaVulxwpeCp5NecCGgoAUsN4Ktf42Pg7HXDlQL6r -Xs/YggMztj4NzEgBHXAOLShdKKhDAbEByVSKXZD9A8J+RejXBl6VbuJmD/5qOvph -GAPKS3ahPDj8438HyD7yIDLYYVRKfxjWHLubc46Pgui0EXBncDIuNi4zLXRlc3Qt -a2V5 -=l/aV ------END PGP SECRET KEY BLOCK----- diff --git a/checks/plain-1-pgp.asc b/checks/plain-1-pgp.asc deleted file mode 100644 index 10e50884d..000000000 --- a/checks/plain-1-pgp.asc +++ /dev/null @@ -1,29 +0,0 @@ -This is an encrypted version of plain-1 for -the PGP test key 0xCB879DE9 using CAST. - - ------BEGIN PGP MESSAGE----- -Version: PGPfreeware 5.0i for non-commercial use -MessageID: D0P6k4cfvaTDkyRQM+/MpOoQW6xT5Swm - -qANQR1DBwA4DW3oC8MuHnekQAwDj3tkgY6XU+e1k9XOlSSzIPGenxgOZ8VSvuEUd -L+/1E9T2KJmH5CGyH4Hz6wIOLtFSd1A13yYRyHNhxD/nGgcjg6etZNVQnjPuRp5k -O4jYz2BCstkjz793ZjPzgXgdpt0C/0zmlQz8clT+/cswAj0t1famcz/Ai4gexfkI -pojmFHewdYs6FT0XbwxjaYUyw955KBEUwJ4uJ6VTR5ab4GxUmpHn/S7HfoWVPjXl -j7R8Xw/5bsrOCjA5hd2XcpE95lTHzcnB9Fr57OMFlFC/FSwUaDsArZ/V8sUJnD+l -aWyrDhzuiwVy2XSYiX55qCL3zuZsiElo6AS7ITkI8onL2FIFtC3L5LecPprNlE68 -XJLxNZUSAel7OcnwqUNtM1lEK6bfYfiXr0BBEkg1Jfx/KucHMIara0CVEh+V0aGj -I8rKt3MS+T7KMYgJzf47ipTtf0Q3qZph28fRirn8gKBlEIRz62WU9Jjz/GrNqbuD -meixSq3JprnK2kDZ00oqSZVCjFEc6pQoZqZc0cGT6IDpYEsNghfeyCxzUB17QzJC -gisd5k0uSCIWO8lwbWInnDzmV8XTfG5o4u88S89ioGydxMlCcNNX2cNp/MH/chgk -iSI+BAZ6mVcKdH2x6NpFJDGcogIM9phsnUC8NkOUH2FtjnCxDJyKSfML4lrEIi3x -QCAFEx+dYq4xcT8AnEQcTJ4ppoUJwfbtqXxYh2TKSWSkXnNz6sp2AGlx/uc99CyB -BjurpFQzseceTbxfJySm3LMJ470jSmwXSl3byryfiwTVV7BYoKkYfpVaXK4VHVMS -bw15DEH8PqjkxRabokwhIpWsJ4ta+FCgaDYhdOvrBAztwm9edsYYiNdrwjn8zFzw -QpOqh7h0uCksU5/ULmadIAYgejPyGJM6lv2m7o0xay4TOqyRMzkdcu0WyR3PVFAE -iwk/uYIonNCJc3pFS8k4b3CYnSiso0z1ugJR5YcPoOuxrbdly1om4ZC0is+euQZN -kzSGwfbabKY3mvRWGTGpZil43BRMK7nzL6oN0f7Y+/DTRp4Vzc0NTyfV2QkU25Il -ARs4Cxa138Nw4fmfvenCvv2QL2Ks/HCM7lybhq2IvbRVRiOEgcPxvRtZ5VKrqbkM -rrzzqi2PxlVrinR2GAkNu75ef+FP/KWP4NFYvEMpDxqXNS7Ju1sfcyFaTnm9 -=TpZW ------END PGP MESSAGE----- diff --git a/checks/plain-1.asc b/checks/plain-1.asc deleted file mode 100644 index 638a15bf9..000000000 --- a/checks/plain-1.asc +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN PGP MESSAGE----- -Version: GNUPG v0.2.15a (Linux) -Comment: This is an alpha version! - -0CIjY3JlYXRlZCBieSBHTlVQRyB2MC4yLjE1YSAoTGludXgpowJ4nAFBBb76hM4DPGu75p0m -bg8QAwCx58y5eWLvOyIPG+OzRE9RCA9ZAC+9/A7Zy0u6KfUx4FaGZEMaxECYVK7l4qOmsNG+ -FQB25V+OX9P3nfJ9IFs+AlvhEzv6mBGuoyIErMsXe9XHVGCTV2mceKqmE959zH8DAL8a0GEo -fgtyvu8KC8GdJi4SgTvKXKC9cBdU14RSsk5G3KFYl+qCRP8fcoZ2AkZUf2+LOGk1c1h1eGF5 -8C5EdFbCQNM+EUVTsYc4nOpMwGl4B2TQ6Jmn4LB+qVGgFzbZsKUEbhM0CbsTTbGimyGAWMEh -LAp7hFrR7hWaY3nmbMd3xUc3OIvOgF8TqbcnbyHKGUIgH9UiRshTFIVNGaWJbbemVk9zQi50 -v6+unuYtQmaghBSZ/OPcFvThdfkLFQbSVsVJ21N/6mblUrHpv4TsEmeHSeBMdfhhdf2a0f03 -7uHxITOSr53iSi3A5K9/7mvLznMrAJ/W7fMx37imdsvxNc3TZFbPoau5auqG4PJMGMqucFH1 -6bOkq/jbAbNhaOhU1pLazYVjAL+iqW1wVDc4NTfqJjaf/gI4E+4WTjddAbUYtmuqEhx8UGwU -tW0B7gVNhKvMUE2EtTCtC5kCW6qridVOFx2W42xrrAEGyG84oHuMmsE0K9QB0OJBRLwFUzPS -4JVW+sdv26XkReiNKQeD5I5Vwu5oYY36MdQFdnGDmKhTwt6/+NLzyJ7bSPFhAKHwYkPoDCuI -nMVWUrrt6HsXY2cszTP403bbdp4vI0OIHCT7yBS2kRVygD2/N9E66O0vvOWEPKaHuZUIhJi5 -pNFVrhBDUoYxRGbdcLq4RNYrexYBNdnD4IuhJfmnqJfv4HxSoyHy4llXY2AieNtOscBzA7nU -jHrvqykyFVmyLUGcG1w9a72xl2XG8cKvL2BNpMbt+Xv+8mxst85TrFTjmoPdGDAHcMzgr/ds -yKcw0yOgX2PumuAxQ8ND1BXxctS5R8ZQlsOQgY7StvnfSwKPLXXJ1Xdmo/pn8mncPrzbEl/X -d07bZZ1vzE6/NkGkLpHo3WKuiNTu9FtwuO6DsqzsM1yZ4AOiDMG4uIxQplPa/mv31eEkYY3/ -9F5K3mzFh9phK3lKk0bdp29d8pO44A7tXt+yS5/QeDojykarAwAz2EvEA+F8dLvprJ4ku9Qv -T/2ubr8I+9pRwtA69BevNd80qKQr2q1Exi/Y5d2Lvcp6x6kSwXKO65rLYQ/2RlCOHzlkFNvn -r9RJ/H/c8COYhjFbTeVymgviRyGABdxeLEMOSFFRa4EQL0L7Kbu6obX2NLbuQA+UlQ3bFKMn -r2P5+6qxIIS6bgDxmb3xRnOCsVl8X4/Y14oOY0HbcBY3VmiXUqVG4zMaPChSFn5vGXaCH3uC -J9lETUeh+2q5L+nvoRW6wGax4smtNBIVKkCTDGnuaiYQ5L+24MJQzn5OXnkeoe09cNp4FR+s -SxaVfLyJW+TkMppd1v6rswSrCeh1zh+baamOmKOyS/RcwkRH+hoRECvVxQ7mm5QLm6Wyl22B -CFns6pzKQFeh9KgK4w+PgaNuiSI8UKqD/MJ4y3aylAfgX8izODd4grqYt/KrLgfFJ7mESDdP -3uL8PcX7iIhq47YRGPk0mDyCRNni6xC27xeaYy2pGeEr3NJ+nZceUsYZxBCvdoiejFxQ+Hog -dA9saADuqORjQuQEybej8Eq2LXeg62TvcSzBF4nbVATG2N9/U5PVtTx/hv26Ime8hmrsTA7M -2Wm+9xHoWHsZIyj5tkWdgChIZQ+4ZBi3w6f4M9yGmb4kf73bVkimI4d8r48= -=a0yS ------END PGP MESSAGE----- diff --git a/checks/plain-1o.asc b/checks/plain-1o.asc deleted file mode 100644 index 973b29395..000000000 --- a/checks/plain-1o.asc +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PGP ARMORED FILE----- -Version: GNUPG v0.3.4 (GNU/Linux) -Comment: Get GNUPG from ftp://ftp.guug.de/pub/gcrypt/ -Comment: Use "gpgm --dearmor" for unpacking - -PCEtLSBEaWVzIGlzdCBTZWl0ZSAzLCBkb3J0IGlzdCBrZWluZSBTZWl0ZW56YWhsIGFuZ2Vn -ZWJlbiwKICAgICBvYmVuIHJlY2h0cyBpc3Qgd2llZGVyIGRlciBTdGVtcGVsIHZvbiBtZWlu -ZW0gT3BhIHp1IGZpbmRlbiAtLT4KCjxzZWN0MT5OYW1lIDxxPkdyb98tQmFydGxvZmY8Lz4K -CjxwPgpEZXIgTmFtZSA8cS9CYXJ0bG9mZi8gaXN0IHNjaHdlciB6dSBkZXV0ZW4uIE1hbiBo -YXQgdmllbGUgTXV0bWHfdW5nZW4KYW5nZXN0ZWxsdCwgdm9uIGRlbmVuIG1hbiBhYmVyIGJp -c2xhbmcga2VpbmUgZWluemlnZSBhbHMgdW5iZWRpbmd0CnJpY2h0aWcgZXJrbORyZW4ga2Fu -bi4KPGZvbnRpbmZvIHJlbT0ibWl0IExlZXJ6ZWljaGVuIGdlc2NocmllYmVuIj5Vcmt1bmRs -aWNoPC8+IHdpcmQgZGFzCkRvcmYgYmlzIHp1ciBSZWZvcm1hdGlvbiBzdGV0cyA8cS9CYXJ0 -b3JmLyAoYW5ubyAxMjUzKSB1bmQKPHEvQmFyZG9yZi8gKDEzMDYsIDEzMTgsIDEzMjksIDE0 -MjkpIGdlbmFubnQgdW5kIGRhc18gc293b2hsIEtsZWluLQp3aWUgR3Jv32JhcnRsb2ZmLiBF -cnN0IDE1ODYgaW0gQmlzY2hvZnNzdGVpbmVyIEp1cmlzZGlrdGlvbmFsYnVjaApoZWnfdCB1 -bnNlciBEb3JmIDxxL0JhcnR0ZWxvZmYvIHVuZCBzbyBhdWNoIGluIGRlciDkbHRlc3RlbiBu -b2NoCnZvcmhhbmRlbmVuIEtpcmNoZW5yZWNobnVuZyB2b20gSmFocmUgMTY1MS4gTkFjaCBk -ZW0gSmFocmUgMTcwMCB3aXJkCmluIGRlbiBVcmt1bmRlbiBiZWdvbm5lbiwgZGVuIHZvbGxl -biBOYW1lbiA8cS9Hcm/fLUJhcnRsb2ZmLyB1bmQKPHEvS2xlaW4tQmFydGxvZmYvIHp1IHNj -aHJlaWJlbi4KLS0tLS0tLS0tLS0tLS0tLSBbd2VnZW4gZGFzaGVkIGVzY2FwZWQgdGV4dF0K -PHA+Ck5pbW10IG1hbiBhbiwgZGHfIGRpZSB1cmt1bmRsaWNoZSwg5Gx0ZXN0ZSBCZXplaWNo -bnVuZyBCYXJ0b3JmIGRpZQp1cnNwcvxuZ2xpY2hlIGlzdCB1bmQgbmljaHQgZGllIG11bmRh -cnRsaWNoZSBCYXJ0bG9mZiwgc28ga/ZubnRlIGRlcgpOYW1lIGd1dCBnZWRldXRldCB3ZXJk -ZW4gYWxzIERvcmYgYW4gZGVyIDxxL0JvcmRlLyBvZGVyIGFtIFJhbmRlCm9kZXIgYW4gZGVy -IEdyZW56ZSBlbnR3ZWRlciBkZXMgV2FsZGVzCg== -=m1k/ ------END PGP ARMORED FILE----- diff --git a/checks/plain-2.asc b/checks/plain-2.asc deleted file mode 100644 index 207607d74..000000000 --- a/checks/plain-2.asc +++ /dev/null @@ -1,41 +0,0 @@ ------BEGIN PGP MESSAGE----- -Version: GNUPG v0.2.15a (Linux) -Comment: This is an alpha version! - -0CIjY3JlYXRlZCBieSBHTlVQRyB2MC4yLjE1YSAoTGludXgpowJ4nAECB/34hM4DPGu75p0m -bg8QAv9ZdGiPPhSW1kYoNUFU5RQxPQ3F/uRyhWV6ZZFh5A970v4CRjZilbiqBORpSodscyxb -hu0zaC65x+VTeSdcJMA09cgIrAP0ffRTzh5NINdxRwFr0F4G03RLlMQoJifd+zQC/0XYC5bL -nWnSA3so1fOQikBTG+aopEQ1ap/Hy1rfIVWhtVnkteZG0y0BH/LvOnzV4F5Vm/mUOi3VPRKO -qb3THQzraRj5h9tm8CXyWg+gGgauE7npa7jT/pwW/zPz9dkB1KUGL0vaUus283IXmCR+u7U3 -2N5yQw3EehF5Yvlo+MpXWuaEBkQRwwZzhKn/JYxecxrCHlXAcTU7nV4vS/Gy7j9X6TPxVdgq -E8Ub6k5VID/nfx5H3qY09uOOP0vGhkdI63F02Cfic5n6g2KC3+v7KpQSbxPxgc22q9puzAGi -o4T9XII1uGn+WL5bIdfP+wfrqKwsRvlEBSYfiVzPAuJ7nzx2SHuJ1YEL9LCpNwFaswmilNXm -0sa1Cjo9uNd6Li+HNVUidl1rIsl6ZZBfilA9YK3KMPrJnmzK7KQ7UY8//XB7Cdfv7tGrUgzo -lJA+JBUKC6mL95qbxB96DYAaoOzXYL0KLTdXVrusVWHP/+fJvAicmFD+B0hepdg2Aq0qdJoI -9Zl6IB58YbRX4MX6bMaz0aFkibeLgsyHBOCvQeKe64H/E3Rc/CosJ+/OsdV+xl6nBrJ9loU4 -94vwidvq0Rm20Zm4YEjsgClX/ZXTDfdnKkSLUANe76RJzS/tJciKludV1pFpT23am8mwRl5M -kP5DJotIBT3EUUyCjqCgpWUi0yt/dM2Oc3i/BQAOPd0dOZhAcmCAZVyVbYA7WjMfqZLH9sz7 -COU1quvuSotTwwJPRksuHQDan8azLIPU1gbVqPo7eHXmfUW9DWg3DLk7x5A8BTTyqfgEZgXn -DWTS+FqJDdvc0UgMFH1JZ3WW/+Fg9U6MvT7+gw2nrnBpw/Yqqj/9qCeeORyrg/BgUEf7Jsk7 -isns8ji1xrpUVLCSgxx5Kk8ComuX+jAN3aTwkA/CSSg0D6aHyZINiezFSIY71CovYDIjGsf2 -wG8xNzN0vvyVkfXbUpgpL+cbjezZSyWde2C2Rsu8rvdLfWDrW4BJp33nS6F3XlX9d6kd2y19 -Nv/erweqvZWHTi2LcIl4gYstnhJdcNNtcRKxwwThE+T2skJg0tJYnybAasH14Ej3eroD8kb3 -Lo6U1bIkEwO6gi/rNdWziioWa3+dwdh/WzplwEJy+81mnR4mkkhJltPI7B6QR2SUq2iPaZN0 -8Q9ys5BpS88HbuZKOab2BO6CrthbTe7l89yrIIcK5+SWNMCb8vnIyw3+1TGkP3h35Y07uEeI -eoipSxI+Cmio7gnE8pIulTLnACW0clMFR9r6k08t/UmuM5skBsvFbn2h7VpXRtjI0UbP/OTO -EtQYl/CcNa1fhPbDCb9lhqJrZWPDh7cv0bwXIDYzVAm5NQnF9zy5cQRlQgTdPgOOAT8N7OgL -zsySBBZk4aDucZnrRSC4hpseZ6iv1IBUwT6kkaUpXVqJ4ujlthzjNSixiwYXeNir9mMYB3qj -LvYq7oZOvgO9gca5RUmNKc+aj/dOT/3cO3+gkGrPJhlwwMaZNLg63jFJD7kon1oh+uFJEquN -gDEQ6a3fKhszdukxD43oGmi8GX9I3/dr53KcQ08GYLELyoC7Py9nc74KGgjWGY+HNkCMQUyA -JMe7xJVBg/0tvtH+HoGRU764MDM2BvbmrUXAfZHGfXCLyXdEPQDj5KnmQlV+L6v6ecrkUS0Z -ktxlZAgogC5OeSC0HMADhZxmkrXMKbMl5TpfB03jrHgyqU5kmVA4mBe0PnE4HTSJQjSLouy1 -l2Cs48ljGRVQbcAilXiV8alFGFeIoG3u6MrXeDEDbryJ2V0gVb3RQ9Agyt7ZZlmAhFRutk+z -UdALvDThOnvhI4q+ABV3OHkwjQann3bUNEFvCqGE+b5Osg/nQZLGTk0E60LidpZNMor0sYDc -SJcRn/1OZ/gufh/Npa4h3EL0Nyc3RvoUHHjQMqGXnwUvEzg7EdbuaBfmv67t2hAq808GXnP1 -ButTODVwgxqD1G/Xupg5rwxSHr9cYIgGuhCysbyFytrxuZvICD8cDi8FtKb3KiftCEuxHK7o -d3Dl+0/Y/+wDOgQrdkrIl4VVZXtssD/4Lo8NZKo5mxQj5JcuE+RQo8ufXqp+7it8QuVKYYH6 -hR9LwLzW5nu4Uk1bnsP84XvWoLmTUAU5O/ke/4cOJ8FN3jo1gPZqVrvWH4rGxsRZMZ5LNeSL -w4qCZ7ZV9phJbUGPJzAtD7d4+j8rpl4BGBRUNc1E98Ilp+NRq8ltlu9TIEP8N31FS8YXn25S -suFI5P95Yw== -=08za ------END PGP MESSAGE----- diff --git a/checks/plain-2o.asc b/checks/plain-2o.asc deleted file mode 100644 index 562e5f06e..000000000 --- a/checks/plain-2o.asc +++ /dev/null @@ -1,36 +0,0 @@ ------BEGIN PGP ARMORED FILE----- -Version: GNUPG v0.3.4 (GNU/Linux) -Comment: Get GNUPG from ftp://ftp.guug.de/pub/gcrypt/ -Comment: Use "gpgm --dearmor" for unpacking - -Cgo8c2VjdD5Wb3J3b3J0CjxwPgpEZXIgV2VydCBlaW5lciBPcnRzY2hyb25payBpc3Qgb2Zm -ZW5iYXIgdW5kIGJlZGFyZiBrZWluZXIgRXL2cnRlcnVuZy4KTWl0IEF1c2JydWNoIGRlcyBX -ZWx0a3JpZWdlc18sIGlubWl0dGVuIGRlciBnZXdhbHRpZ2VuIEdlc2NoZWhuaXNzZSwgZvxo -bHRlCmRlciBLbGVydXNfIHVuc2VyZXNfIEVpY2hzX2ZlbGRlc18gZGFzXyBtZWhyIHdpZSBm -cvxoZXIgdW5kIHNvCmVyc3Rhcmt0ZSBkYXNfIFN0cmViZW4sIGVpbmUgc29sY2hlIE9ydHNf -Z2VzY2hpY2h0ZSB6dSBzY2FoZmZlbiwgdW0KdW5zZXJlbiBOYWNoa29tbWVuIHp1IGJlcmlj -aHRlbiwgd2FzXyBhdWNoIGRpZSBrbGVpbnN0ZW4gRPZyZmVyIGluCmRlciBncm/fZW4gWmVp -dCBnZWxlaXN0ZXQsIGVybGVidCB1bmQgZXJsaXR0ZW4gaGFiZW4uCjxwPgpVbmQgc28gYmVn -YW5uIGF1Y2ggaWNoIGltIERlemVtYmVyIDE5MTQsIGRlbiA/Pz8/Pz8/Pz8KU3RvZmYsIHdv -IGltbWVyIGljaCBpaG4gYXVjaCBudXIgc28gc3DkcmxpY2ggZmluZGVuIGtvbm50ZSwgenUK -c2FtbWVsbiwgaWNoIGJlZnJhZ3RlIHp1buRjaHN0IGVtc2lnIGRpZSDkbHRlc3RlbiBMZXV0 -ZSwKZHVyY2hmb3JzY2h0ZSBzb2Rhbm4gZGFzIGdhbnplIFBmYXJyYXJjaGl2LCBkYXMgU2No -dWx6ZW5hcmNoaXYKYmVpZGVyIFBmYXJyZPZyZmVyLCBkYXMgS29tbWlzc2FyaWF0c19hcmNo -aXYgenUgSGVpbGlnZW5zdGFkdCwKZW5kbGljaCBhdWNoIDE5MTYgZGFzIFN0YWF0c19hcmNo -aXYgenUgTWFnZGVidXJnLiBTZWxic3R2ZXJzdORuZGxpY2gKYXJiZWl0ZXRlIGljaCBhdWNo -IGRpZSBlaW5zY2hs5GdpZ2UgTGl0ZXJhdHVyIGR1cmNoLiBHYXIgdmllbGUgWmVpdAp1bmQg -TfxoZSBoYXQgZXNfIGdla29zdGV0IHVtIG5hY2ggbWVociBhbHMgOCBKYWhyZW4gZGllIE9y -dHNjaHJvbmlrIHZvbgpHcm/fYmFydGxvZmYgdW5kIHZvbSBGaWxpYWxkb3JmIFdpbGJpY2gg -Z2Vzb25kZXJ0IHp1IHNjaGFmZmVuLgo8cCB2c3BhY2U9IjJleCI+CjxiZj5Hcm/fYmFydGxv -ZmYsPC8+IGRlbiAyMy4gTeRyeiAxOTIzLgo8cCB2c3BhY2U9IjNleCIgYWxpZ249cmlnaHQ+ -CjxiZi9OaWtvbGF1cyBH9nJpbmcsLyBQZmFycmVyLgo8L3A+Cgo8IS0tIEhpZXIgZm9sZ3Qg -ZWluIFN0ZW1wZWwgdm9uIG1laW5lbSBPcGE6CgkgIFJ1ZC4gS29jaAogICAgIEdyb99iYXJ0 -bG9mZi9FaWNoc2ZlbGQKCUFuZ2VyIDE2MQotLT4KPCEtLSBGSVhNRTogaGllciBrb21tdCBl -aW5lbiBaaWVybGluaWUgLS0+Cgo8cCB2c3BhY2U9ZmlsbD4gPCEtLSBEZXIgUmVzdCBrYW0g -YW0gRW5kZSBkZXIgU2VpdGUgLS0+CjxwIGFsaWduPWNlbnRlcj4gTGl0ZXJhdHVyOiA8L3A+ -CjEpIEpvaC4gV29sZjogUG9saXRpc2NoZSBHZXNjaGljaHRlIGRlcyBFaWNoc2YuIEf2dHQu -IDE3OTIgdW5kCkz2ZmZsZXIgMTkyMS4gMikgSy4gR2VzY2hpY2h0ZSwgV29sZiAxODE2IEf2 -dHQuICAzKSBLbmllYjogR2VzY2guCmRlciBSZWYuIHUuIEdlZ2VucmVmPz8/Cgo8IS0tIEZJ -WE1FOiBEZXIgUmVzdCBmZWhsdCBub2NoIC0tPgoKCgoKCgoKCjwvc2VjdD4K -=9nnj ------END PGP ARMORED FILE----- diff --git a/checks/plain-3.asc b/checks/plain-3.asc deleted file mode 100644 index 3b7382760..000000000 --- a/checks/plain-3.asc +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN PGP MESSAGE----- -Version: GNUPG v0.2.15a (Linux) -Comment: This is an alpha version! - -0CIjY3JlYXRlZCBieSBHTlVQRyB2MC4yLjE1YSAoTGludXgpowJ4nAEYAef+hM4DPGu75p0m -bg8QAwDAGvCZWrqo7Rt8DNg7tDI8ckhL1XfN0OZuy/tJjD8o1K1JuXPfCpAX2WI69PvlVhPC -RO9F2WaBTqyo/fY5XVSzNlfin9TMe56gFjhT3vhK0IgZ1gjBuowY4TktVq4cG/YC/0hX3u6L -7M9D0H0ye0YgRof82sRHKQBSeuFn5iHc6hSB7fFXsyDLqmEvclDV0exY1a3giTGwUX81fknR -EwzB2weemUnf1DQ8rGhw/dBiarOMjjWz0ypyfhWqV/U3RNZRIaRGjBtl0Qbr51KIvg3UnaGD -YX8DXWpV61kkRX+DsQ27tuQvW6V8lKcsElipIFXPhCpfdSnGGVjx69gGDSFEhMLcSy3s4i4X -MMVwiy8= -=MnS6 ------END PGP MESSAGE----- diff --git a/checks/plain-3o.asc b/checks/plain-3o.asc deleted file mode 100644 index 409b9c2e4..000000000 --- a/checks/plain-3o.asc +++ /dev/null @@ -1,10 +0,0 @@ -Stored by G10, because diff/patch have problems with -files not having a trailing LF - and this one has none. - ------BEGIN PGP ARMORED FILE----- -Version: G10 v0.2.6a (Linux) -Comment: This is an alpha version! - -RGllcyBpc3QgZWluZSBlaW5mYWNoZSBaZWlsZSBvaG5lIExGIGFtIEVuZGUu -=ZQ6m ------END PGP ARMORED FILE----- diff --git a/checks/pubdemo.asc b/checks/pubdemo.asc deleted file mode 100644 index d550f1af7..000000000 --- a/checks/pubdemo.asc +++ /dev/null @@ -1,566 +0,0 @@ -26 demo keys: - -pub 1024D/68697734 1999-03-08 Alpha Test (demo key) -uid Alice (demo key) -uid Alfa Test (demo key) -sub 1024g/46A871F8 1999-03-08 -pub 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) -sub 1024g/BC43DA60 1999-03-08 -pub 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) -uid Eve (demo key) -uid Echelon (demo key) -sub 1024g/7272144D 1999-03-08 -pub 1024D/8FC282E6 1999-03-08 Golf Test (demo key) -sub 1024g/9DCAD354 1999-03-08 -pub 1024D/04259677 1999-03-08 India Test (demo key) -sub 1024g/61F76C73 1999-03-08 -pub 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) -sub 1024g/9AF64D02 1999-03-08 -pub 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) -uid Bob (demo key) -sub 1024g/E29BA37F 1999-03-08 -pub 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) -sub 1024g/B0C45424 1999-03-08 -pub 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) -sub 1024g/EE45198E 1999-03-08 -pub 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) -sub 1024g/D622AD0A 1999-03-08 -pub 1024D/D2699313 1999-03-08 Juliet Test (demo key) -sub 1024g/35F8F136 1999-03-08 -pub 1024D/B79103F8 1999-03-08 Lima Test (demo key) -sub 1024g/FE56350C 1999-03-08 -pub 1024D/BE5CF886 1999-03-08 Mike Test (demo key) -uid Mallory (demo key) -sub 1024g/4F31EAE8 1999-03-08 -pub 1024D/30CEC684 1999-03-08 November Test (demo key) -sub 1024g/8B70E472 1999-03-08 -pub 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) -sub 1024g/2681619F 1999-03-08 -pub 1024D/3FF13206 1999-03-08 Papa test (demo key) -sub 1024g/63330D9C 1999-03-08 -pub 1024D/3C661C84 1999-03-08 Quebec Test (demo key) -sub 1024g/A029ACF4 1999-03-08 -pub 1024D/777FBED3 1999-03-08 Romeo Test (demo key) -sub 1024g/11D102EA 1999-03-08 -pub 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) -sub 1024g/0F1B50B4 1999-03-08 -pub 1024D/85A81F38 1999-03-08 Tango Test (demo key) -sub 1024g/101C0402 1999-03-08 -pub 1024D/653244D6 1999-03-08 Uniform Test (demo key) -sub 1024g/5522BDB9 1999-03-08 -pub 1024D/61F04784 1999-03-08 Victor Test (demo key) -sub 1024g/07287134 1999-03-08 -pub 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) -sub 1024g/FD6E27F6 1999-03-08 -pub 1024D/567FB34A 1999-03-08 XRay Test (demo key) -sub 1024g/41E408BE 1999-03-08 -pub 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) -sub 1024g/F7B080AD 1999-03-08 -pub 1024D/54ACD246 1999-03-08 Zulu Test (demo key) -sub 1024g/A172C881 1999-03-08 - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v0.9.3 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -mQGiBDbjjp4RBAC2ZbFDX0wmJI8yLDYQdIiZeAuHLmfyHsqXaLGUMZtWiAvn/hNp -ctwahmzKm5oXinHUvUkLOQ0s8rOlu15nhw4azc30rTP1LsIkn5zORNnFdgYC6RKy -hOeim/63+/yGtdnTm49lVfaCqwsEmBCEkXaeWDGq+ie1b89J89T6n/JquwCgoQkj -VeVGG+B/SzJ6+yifdHWQVkcD/RXDyLXX4+WHGP2aet51XlKojWGwsZmc9LPPYhwU -/RcUO7ce1QQb0XFlUVFBhY0JQpM/ty/kNi+aGWFzigbQ+HAWZkUvA8+VIAVneN+p -+SHhGIyLTXKpAYTq46AwvllZ5Cpvf02Cp/+W1aVyA0qnBWMyeIxXmR9HOi6lxxn5 -cjajA/9VZufOXWqCXkBvz4Oy3Q5FbjQQ0/+ty8rDn8OTaiPi41FyUnEi6LO+qyBS -09FjnZj++PkcRcXW99SNxmEJRY7MuNHt5wIvEH2jNEOJ9lszzZFBDbuwsjXHK35+ -lPbGEy69xCP26iEafysKKbRXJhE1C+tk8SnK+Gm62sivmK/5arQpQWxwaGEgVGVz -dCAoZGVtbyBrZXkpIDxhbHBoYUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOOngML -CgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NDl4AKCBLmRplv/8ZfSqep5IjqEAuaXv -WwCgl6NEzT+/WewPTGcwZY+pLkycLv20EEFsaWNlIChkZW1vIGtleSmIVQQTEQIA -FQUCNuO2qwMLCgMDFQMCAxYCAQIXgAAKCRAtcnzHaGl3NCeMAJ9MeUVrago5Jc6P -dwdeN5OMwby37QCghW65cZTQlD1bBlIq/QM8bz9AN4G0J0FsZmEgVGVzdCAoZGVt -byBrZXkpIDxhbGZhQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247hYAwsKAwMVAwID -FgIBAheAAAoJEC1yfMdoaXc0t8IAoJPwa6j+Vm5Vi3Nvuo8JZri4PJ/DAJ9dqbma -JdB8FdJnHfGh1rXK3y/JcrkBDQQ2448PEAQAnI3XH1f0uyN9fZnw72zsHMw706g7 -EW29nD4UDQG4OzRZViSrUa5n39eI7QrfTO+1meVvs0y8F/PvFst5jH68rPLnGSrX -z4sTl1T4cop1FBkquvCAKwPLy0lE7jjtCyItOSwIOo8xoTfY4JEEXmcqsbm+KHv9 -yYSF/YK4Cf7bIzcAAwcD/Rnl5jKxoucDA96pD2829TKsLFQSau+Xiy8bvOSSDdly -ABsOkNBSaeKO3eAQEKgDM7dzjVNTnAlpQ0EQ8Y9Z8pxOWYEQYlaMrnRBC4DZ2Iad -zEhLlIOz5BVp/jfhrr8oVVBwKZXsrz9PZLz+e4Yn+siUUvlei9boD9L2ZgSOHakP -iEYEGBECAAYFAjbjjw8ACgkQLXJ8x2hpdzQgqQCfcDXmD8uNVdKg/C9vqI3JSndq -knsAnRxzVeHi/iJ73OCKtvFrHbV9GogqmQGiBDbjkGcRBAC/DCQungO2iJ7j9+9q -d2crjBU8K+AmQhs27JBkJqtAbC/xFqkHBsA1Pi8Zb6TLa/OCm2PbXFiM5x00wiEn -VKNzuGOzU8uHB6kwWtLj8+V7VOWOkSDEtnlTF6u0y9JOvs7GwDvqOM5C3QH7La+z -nNeAu1527Hj6l0XGSAzyvp+NkwCgnktU11VFpKSIdoplZBayN9OzT8sD/Awc/890 -fiSMWYNGo4+n6IHxhjBBM9lL+DAe1RtCEtwUSWNrGsIxFnDRkMxvMpaT4GusG+DP -haTddrDBSyFiCLxKDBYgMbSO6wQ9g6zWEEh1ZMTMVU/akr81DOEColXn/f3Q4sRj -xI3hu2z8tjVewAPNTuWETQ6iHHoVqdpkK4aABACfbMrnfK6TujxSs91MfKBWfYxy -w9hjM6+VV8cJJdDXiheMKzWcrVecwgYYzukmNinO//BRmQcs1wdfi5UdfHLNFDig -w96SdyZpHx+79ghD3NqDmzYakoRIoDKcZAIrAjgfl5if6vIiA4c1LjhSdcVTBsSy -ic/mkk01EgztWKY0abQtQ2hhcmxpZSBUZXN0IChkZW1vIGtleSkgPGNoYXJsaWVA -ZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjkGcDCwoDAxUDAgMWAgECF4AACgkQQT9K -8xr9q2w+RACfX3AwFwPu5+mr/f1Sa/Wv0m9T57gAn1TBIoUErMqJehQZu73N0u93 -fqSKuQENBDbjkIIQBAChY8NSvu6sK0p4D0AVBsRz8iVXYqbRlRTZAHS4LCXwx/i8 -FmfdIXnaNLOoyi44YruSCnlZdh4YWquCx2mgywG589AzcFhahmqElNbKb7m4F//E -GIZK0zTgW13tQwG9hTXOhYeqchnOOaDDwPEK1Gr+2o/5ANqhqrin0TFFBWLgdwAD -BwP/R009s61X/FkUUAh8w4Tua6qndN/2GsqXsyPYjdF5E3gErK8jDcDLniOHqksw -V17bJG81czCRE5JcVFLLWQJg9cpeoTpP+YcF+m9whtswaOJ/LPrx888i/OmluSD8 -1VP+6zBhhTUbpazfLEdt3XczpW7CNdNbyiEcgT+6Cr+W2GaIRgQYEQIABgUCNuOQ -ggAKCRBBP0rzGv2rbLWtAJwNtSGPYjbesLSTeRwKGA5ffZiFDgCfTPC6I+XyGavj -HJraHTgS/bSCN0OZAaIENuORzREEAIrOxkw6rRDOpbqKenlrMRYvfqoVFafTekvs -ZW8M0GVQOBYwqn9VUfSV/H8Iy3nJsU+cU4UFXEaoHhVWgspMtjYHvxXBTD2UHmj+ -Y7+RkVnOT7x/UsPKbxjkweeleGXkeHECwwZuQhebSrtQQllqtjCx33Le013ukAs2 -SnI83cPLAKDfVb6yjfhG0Avkx83VmlFqXXH1pwQAhVhMi1T06SNYzbKAmdNBfBWr -v9m2l5PJnUTpSWUum6ueJLHzkEM0XgVnHt+YdFuzXgUafsnqEn+2N4tI0zuJqzoi -/9DQnEvKijZxihtYq3S3rN6UIQ2aXFHthvVtxZxocZeluYaWHPeedJlI9h9yObZn -0mLFXFY6TUiHQYs8RNgD/0iNbequyxzEKdIdzD0Ns+3WjIVBlYl51Zdvqyo2+U+2 -70hXVdIssrsqKr1DwRlsCRSwMY+nrB0ZUOlvLaIB7qCQke3C9myu/fJoGDhMZOYA -XsatVR0EGTdXnSuCxqNhEiqwlbZGMAcwFO+oWBSgGyjFPHTMSOw0XS42d73UNxTa -tCdFY2hvIFRlc3QgKGRlbW8ga2V5KSA8ZWNob0BleGFtcGxlLm5ldD6IVQQTEQIA -FQUCNuOkfwMLCgMDFQMCAxYCAQIXgAAKCRAxjB+u+u9tG2cDAKCzaFoiAm79QSmY -ISeiM7XMKhoHDACaA8CU1j8+20C7rNipOHYz3KfUMhe0DkV2ZSAoZGVtbyBrZXkp -iFUEExECABUFAjbjuAADCwoDAxUDAgMWAgECF4AACgkQMYwfrvrvbRsg3QCeOMf0 -g3znbc8IBiTrIPUgUz9p3WoAoJ6eRZTZk7z+hTyx4JDceReQbYlGtBJFY2hlbG9u -IChkZW1vIGtleSmIVQQTEQIAFQUCNuO4HwMLCgMDFQMCAxYCAQIXgAAKCRAxjB+u -+u9tG16mAJ46lQbmtWRZUldQtp4ZnOptP7ZJtQCfceYMZfMAnqUKJiHk2tMhvwDv -Ah25AQ0ENuOR/xAEALSl7SaNEf8mYovea5tJNEwoZx3vv6XymyXga1wDqKo2PeDr -nRDbHGBb5BvWIv1J6Igk/wq4R+Pq989UpkcqREB+yOeluE3zPPtZBrbLySSaqiMe -gYiHnAAPc0TqjH7UPZa+fJKZTUk64BCUQN9ELkL2FKtAGQ7RNQJYvbCq4O/XAAMF -BACXdO4a3ZIK5hJejhHZ01mkHa6Sqoc6PuedNC7tlWiLU62BljGiv/DvzcbMsnvk -991AxJ3pP4ZvKr5CClqIG+WZa1zmtwXdmCfGJb2fbNSVD4zp16e5slPr8Cp+fvIv -2/SyvwruROs+oAzSVvoMAzAGSk3yj5nT5oikbn+M62fC5IhGBBgRAgAGBQI245H/ -AAoJEDGMH676720bj5AAnRH+1me1/iHDnS5ltXysOdl24/BMAKCPThApQ7lJe8LY -r61+lXUUwr1TKZkBogQ245LREQQAubUOd0B7cFzJHF5vo5NwiMZ1JXPjyNqL2OWE -/XfaeJiB55oMmVEPmK1JF69wU7ZBpo1l4PEIWcP7WRMqvBEFl+8LnelRkSW95kwF -r3D8TRnarZy3kfiBF1t33dnkVTaZYxCDKOBdZ/ZiRvLa6gZ/KHhITfzaS7h36G2M -bAlGlj8AoKQPFsEPjByKYdx72m5/2Ju/4d4jA/oCNAKaJH7N8Y3HLis1ShhpytJP -1yC9GJjtec3ugzYSC7RKV3NJcBeCX4om3KhiDSN6YYVICf4wdqz6TAocoqPzR2t7 -Fz6+upxIgh5WGnnCs2e7uO1eXUCSXONfiDEDzRKGTQjkdvwFo+880DkiGln/qmRr -cILA568dwNnOrBio5QP/dbkpUBhqGDr2LchpkoYyQlqzbvUpXJ1xlfZim1jfrmdf -sk83dE3iBzvmT8ByIZcMoqDEHil95LmJp3qw1yVeApP/ZWR+0XiBLEF9GhcAOc5i -hH2ACSXLWiRXpyMmK2/erTvTX3QkAcqoQ1cFWCwNNCrlgycB84Hdm5GXdajp7cC0 -J0dvbGYgVGVzdCAoZGVtbyBrZXkpIDxnb2xmQGV4YW1wbGUubmV0PohVBBMRAgAV -BQI245LRAwsKAwMVAwIDFgIBAheAAAoJEBaEEKSPwoLmIuMAn222gK7ibwOXzIKd -/gZP09JC/3+eAKCOelaqqYqNNbku0gA84+O7d1kMqrkBDQQ245L8EAQAtsGp/UnA -1y4AqjewlkkTOQevLwtzwm3pmLLjl2Y3TfGn8Ni0h8Wd27kV32MUZyTaNaZuDxpD -EO2aUIpGWVQmWvlqCFV2F0Z2AI8R4bx1tC2kD758hUvR+S2hn9lK7E1lQPuvec2L -Eml+uvVxW/Vm4iDBgeMlIlz70MFC9LUnfpMAAwUD/At7Clo7D4dNk43BMvhQ8VgJ -+INy37Dj8PHX2sCZZ/tIfSwNIU3m2ygSVreTlDKo406v6Qmefs/m9dH9lsBE/8QL -40Ek3SY6xV/QzTVN44QgnpRKWpfaMbGzWJVXeczlNkTeIZZo/nhDm+aMucMu/e7E -KbG64BnrQk7Lz6LSKb2xiEYEGBECAAYFAjbjkvwACgkQFoQQpI/Cgub37ACgicCk -6XvTqEv34RXVSkhf+EcDHOMAn3krqPc5ZeSJGa7RfRcVhm5QtcvymQGiBDbjlLER -BADIbiZFRBlqCMOCXTECdpJssJDnAmpir+yfAKX4hsOVdygepdA071Ams8rApABS -/c2+Tuaplad8w+iyQs4BKuzqeQK/YWj0DDqyY2LM7qJbvFd6nC/GOGjiEucTTSgY -8IOFScBTTks7alMGjHAdWzSjq+1ppWJeTSzp04UKhV1/0wCguOIaUr/cMVahSuoi -K4Tdot+CR10EAKunWycnUG2IaGYqO3sCfpChzktWdTjUn9ESJAjKK1QUC89f5+Kr -MPITdUPypf++9MumBkJi+8R0GVJ8zwhwKfX9CHhrD0kfO68pCDxZyW+dDzOr/tFX -0nuH9pL8oiEMkikaGLph+N+N1Ip8thh+vdLhNUr3EPRlrcAfv+WtOpbyA/9+kpa7 -x8nIn2SofJisj+PjKS3lAoGPe0eOoK/sVBvgVjy3Gc3d8vMG29r+2WRIpGwuhuLG -NlQYX65BHV1MK/TjYvFnpoRSqtTK3GpRzTmkJIC8RlXxtfYf/n66VLB3EoTOzWHY -29JMCJnnjPMoaMc2YSK10Bo8P/27nF0CKo8XEbQpSW5kaWEgVGVzdCAoZGVtbyBr -ZXkpIDxpbmRpYUBleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOUsQMLCgMDFQMCAxYC -AQIXgAAKCRAf6PxvBCWWd1pYAKCVZ7DfK+i/YZGyEu18DnWq0ixligCghGwDoMGg -LnenSjyShMZ+1Ecekia5AQ0ENuOVEhAEAIMMgk/e8lsV/KEkd4/jNK4yFj5iy/Fa -on800I3GUzETuQA2AT3getR+GuV4pbZWE/80b9hnNW50UJGiP1+SXfVtY5vT8p/g -NFwn5d0O/pq3bpgFRJmoawTzx8SFDwCVPHEcwOHE2j5LvfrvRBOyKU32tr976ri+ -Uowt0+92LuA7AAMFA/0Yo9dDqhjR2UoNcYfEZwWhRHaaJenP3z3QbzjJkASb5H84 -xCTEpv0dqEtVTJUoIo8Lh5VjbiCwok4QPLVSbQFeHqTKb7N96PjevkZ1Co6OrLCN -OcPRvXxgCwSGbuuLMkQJEutnXLu0DOKquY94KXXh79La7lTgjReE/1Wzbgc1+ohG -BBgRAgAGBQI245USAAoJEB/o/G8EJZZ3CXgAoI5oimsZs8ZKmLb5sPB4AZzngCyz -AJ9og9spt3EYXAB95XmfzqgJBRv04ZkBogQ245UlEQQAnKdAaILozJ04V6Z+FIwQ -EY/aF4EFrJJIc+uewF7ukZl/7uUZqSxqmzZjbqigyMFGybJSMa6TpwN0BKG5CJe0 -4R/mVCIRsz1Jx5YXezN3UFsNVNE36R8l8dxWG+wgj2m60gu4VlodcpVMc/kRiSUg -KUfg/xmPnRe3SJZSlG2lBm8AoNc/r5DW86om3MHWK8AoyhvVXhWvA/wOcjx6gfTT -KftzpQBhOF0U0fC3npQC6bvjLjTBhQjC3WX5rfwJqMmrudRbEO1sFqzTOQPtb9xa -tMeVqTcOi6+x2zfXes4nTfi9Lgq1z8HhE/LnktwxZxyPeOXqXu9N023IyQTv7mC5 -9C1xMZk4POOv9WZUGz4C85s2/9iTJCfkMwP+MRW0S9mHmisruCY6TDVFc12KIFMI -PSmWav6gW6bCAA+wIHfmcSyR6MHiLV2gtJ0vQuqgyWfeTiaxPof07dg9pZsV7Hk1 -ZUhEmloeOcfZmwtHkRhWGEbEsd89IWMDJlwNJ7Y9JZ3QvK7vB42bQVvyhdFQdEXH -0slvlvsgKtCcaOa0J0tpbG8gVGVzdCAoZGVtbyBrZXkpIDxraWxvQGV4YW1wbGUu -bmV0PohVBBMRAgAVBQI245UlAwsKAwMVAwIDFgIBAheAAAoJEK0bD61DwtDH1RIA -n1kxWuxGwCS1+i7Fp1cFzzZCHycLAJwJq+RG7ux9sQEmop2V2mKdjBZmkrkBDQQ2 -45VIEAQAuZli0/vYbs6h1HhF9HbvRHFMePjQ99Sk8h/dTx7PI7eSqMHXYh0PZghc -hlbrMSPnemxfwMbJrmdK9WN0Wh9BJUe2ycH8ftUcGRo5CdESgiceziF6Vg4PQz9F -lxtEhvrl7q8R6y7O+j03QAJKUGwBdt540oZ8YYKiDvgZUZxnoecAAwcD/1b2fYzA -nuWrQZXhXQQ4cNVxMBVFKHScH24oFVbuEWLgM/tdgF+CPw2Vtzba8ySR1K80VSgs -Qfs6n2wyCVd+II8lKHTZT/pfICFcPJlHKs4ge+JNn1IcxBAiq0QRNW5hGTO9KdJ8 -MFWrWn2Bbp5k32roAzuCagoielFo4MVFZTsNiEYEGBECAAYFAjbjlUgACgkQrRsP -rUPC0MeO/QCfaGt8NeCm0zbssmOrXZ6v9zFk8xEAnj3SpjLTyqemniHSJ9KEzIKJ -CdiDmQGiBDbjouIRBACKncc4Ueec7dWaVARy2SmNVufeSenYs4AsIPP0v59jEl7J -I0rb+4JbIJoAzW/hcm26GS/UbbpQwig8/PgMUV5QfBST4CEOlf7/x2a4HKk9tDV4 -An7q2aNr1beW+twxfUGWWV5I0o1b/iKVk/LiQRiaMr8pJXY266m6/2Pn9LmDtwCg -+Iqfx8gsK2PZCWv87uEKAOLzHXsD/1eRxLqCt1hT98gdDLykRTlI3kMq6EK3I+z/ -8pDIMDuPIJq1eM68YdFZr8s7i1ye1QpDltPYHgWnUC733ujAKANdyybm3HrA3TSB -jEAhNfcu8nkrVorvASQUDCLJatWRWJTUVrPH+GXIXMA/Oi6LDsgNDOJanwzzvDCC -m8hWQqW9A/4xYAZ4NVFrQq8gtQPJWuMIfSFSvpZWNgQgYZntiXSUGYOVs28T/87R -oRx02tsVDw2PA8z68q/XRuM9NdetxbUXQHB9eszFLi3W1idsXhd/C4SyiTgEFXG8 -Y8s94Eadgk1PAYHN6Gd3SY7jmevqYGVLmBp7qfj5Y9XSM5SE0Th+fLQpQnJhdm8g -VGVzdCAoZGVtbyBrZXkpIDxicmF2b0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOi -4gMLCgMDFQMCAxYCAQIXgAAKCRD+GAsdqeOwsvruAJ4iU4M5s1xsZiXa0wLnX4FB -Bl9abgCfflNpwyEp6KEhKCPWwPRG9WJc0qi0DkJvYiAoZGVtbyBrZXkpiFUEExEC -ABUFAjbjtzsDCwoDAxUDAgMWAgECF4AACgkQ/hgLHanjsLIa4QCgityK8zajBOqA -N0ZZTq8fOzgiEYIAn1ZEfjX+jefZUuY+4zFzrpO/fX0OuQENBDbjowcQBACVSdXx -UWlz81FjqHgR4b1EtmhmW89CmpsHfKlSwlYvBtbB/y7TFIfvAr4ZFbpuqew6Jvtj -IEZoXvolTWwHVPEFkuG0LAa03olaYpzC6ZBDuLkb09RukCD4zdY6xwbAMRsOzZgv -597LZXtOLLLnmOyTpsjRDLztWsuNglm5rffOTwADBwP/SyVZvFEdEVn5/dQTp7eA -tXdrbZEM379ctCJ2663RbTZd55lIBev1fTnKQkvDTY2e58yIQ4E+Nzr99qg9Cyf6 -e3OhErTUqEBOhusBge4/7E5LrIVMvo6AFU9qgn0Sgsnu/ww2txVw3XEjqL8Hgl+4 -Q/57YRvJOe+q29Ye9LL8eaiIRgQYEQIABgUCNuOjBwAKCRD+GAsdqeOwsjK5AJ9p -ek7H6yt3ZHAJ+7nn7sGmxYxb5ACg1INFN4AMzqEUjbZ51KTVdAvyKlSZAaIENuOj -hxEEAN5nO1c81jCmgh/oF+p6kiZmqFV3ape5kEmcS/BoWgCXt6vjaldctmFYi7v+ -BY4N9zI3GxQqAxt5D6dY7aN1xlC236CZEAaXUXktvGw/ppHDjdbs8CRuZiA9jm1j -92GAUY/mm6hX2aGKOkVwr9yN6DrA2CaO4SwK/wEXkVfj+nazAKDCaBzHzwSkkXf8 -QOtOTj/xevpnzwQAv30laCeXTDZM2I/1Pdzma1V1xizfae0kfzZOJBDQtHQDvNFj -mu6iM1kL0uxOG3krr0AlqSsMD8W7mavbFigUlxbhvuul4pTL/BiJ946FhjlPY0Ni -9pmdAldno7yUYsWADEKadkQ3ghEVqEqz+ACYbzp3p8K+5KuiFJm9D4uyvToEAIVP -i2N+4voxnRWGwKXF4E+fLYAzXT5sMMzl46Xk4Ms303F/5JG7kB0iiPPY6oP0l3nl -ahulRcbNMj7SDbfrfoi4m4ftUYIX3acXCSN0gNuVGipg8CwlGQyILgWRFp6oXQOm -AlpxhIGcd1jdh3sj5y+CQrugGPNOJT9mzmFkB4rxtClEZWx0YSBUZXN0IChkZW1v -IGtleSkgPGRlbHRhQGV4YW1wbGUubmV0PohVBBMRAgAVBQI246OHAwsKAwMVAwID -FgIBAheAAAoJEOup8kDrncnmriYAoJdBwMXGVRTFlfw1u4XimCRPVFRNAJ9WFXys -x0ugWaIaLJ3tyNZQHWoARrkBDQQ246OqEAQAj7WdaOJjzJNs2G8rvrDZvD/uaALQ -9PtdvYAp/Drp7xMH5T62+KKTlKdO3s8IQBPiuFocJNir5st/nm8Xl+gcOZOvtr45 -c/cl54fGO1gOjBZOfgbkdBVK/LMwuQWIebK4qCZnAOlDLYNGVUguGLnEQBSfnhhk -gh0WA0kqt7fYvpcAAwUD/3cOEqPlMdYeLnGEG4wPxtyVIchwGOv0YRW5apbz2fdO -7otj1AFUN5WzFw0A5+WHza1OIUhg50Zco6HnwKx6F+LbZ5aOc37EAvaFgPuMxBfk -aWYagCof3jBF0CbTWUXV/D5/dFmIeuGTuUMNsGVH+OSMW2hBN/7+aJK5LLHL+hzp -iEYEGBECAAYFAjbjo6oACgkQ66nyQOudyeZzTQCgmr4mT/wPN2ppg5x75E3cXn6q -B28An2hO/hgIPkf/rSSydA72ZZc/MWM6mQGiBDbjpSYRBADdWzld1lyDWDqGPSzG -OsehXyTSa0pOfVTLckpJpDpErcn8jS8cKrXkVUowI7SlZhPRmYI+5pqGaG5FZ5VJ -d1TfKWihc7O+JDHoK3yamOnh6OFQFPZUF1+WlAGiFXLc+WODzbgOSMy/8yXA6n0z -e+v3et5n9Kzib3sDGjw5DMmiYwCgmUwnofqskHVv1S6tDg08mXALKKMEAIVGyf9i -j3BzNb0fVYGUOLU07nqQ3RpNQPaKtPQpBobRknQ/ZSdzuiALcCB+Q664f1cKGA+O -gtm0L/f1xUmKRW3rT9lzMtcCy6kcudCI2OHm/gOcPzKqjj5onpD84fgR4BdbsehT -8+urmxFiK/bFFI6eC1L5edBQcRLs7TF2jY3SBACdXy9yHg6iDTJhysvR7UuLWE/1 -s9ysirhZgPb0vyIFwHfRzM96AYIPpLZr/jvkrDawTxYGfGIZrj7UyGePu7RCeFRV -VX55B6evNv3fAqbmwQ1GHTX7WHCNdAkP07yTxZ/wnZudPAzQwRkEfZ39TdccbOhH -fHvbv3RNQ0VxbWtQUrQtRm94dHJvdCBUZXN0IChkZW1vIGtleSkgPGZveHRyb3RA -ZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjpSYDCwoDAxUDAgMWAgECF4AACgkQ1L9X -83Ny4kN3LQCfZhlov9Ux6LofeSt5g2hVijDdX0gAnRc7adixQ2hpprv4vNoKvmum -F/D4uQENBDbjpVAQBADfVCPYwZ59MKgXTH4P71QzFnpG4E/MjqDNfW3NxQ9ZjLfw -0ir6U1gGDuEsWRR+fS5OwCbfeHZDzPj8MZPuOZBamgiDvI1OvrrzUv+BijkWGEL6 -oRFnWI8zJ8zDAPuuvP1u2FQZOoKFXaHo2I9Q8zuJz8P2vEkgJfLx2yiPR1Dp2wAD -BQP/SCCKZBNQIaY0cfKmiv8ZjRcAAvhXLyMCwLQUfVRqoNVOtMMfWpYtGdL27ESw -4kgZIsxJ3ELQVkRiriMKbsJiNM4dMe+9gNuGz1CG9b2vhUPZ59sREVIRgyIfr0BJ -AsYOn87mQ5lOBA6+XmjHO+ys4xpEVJZyfrq5QAw5GYcrPWCIRgQYEQIABgUCNuOl -UAAKCRDUv1fzc3LiQ475AKCVZupUbMXq9yw03M34RS9YT9MzKQCfUgFd+Fn89xqU -4Owg/MQzYlLreUmZAaIENuOl2hEEAKeOL2pIdZ+zQtehxdL9l/uDBFSTuN9rLb8D -gLiw8Z9j8U5CEH/M38WzH1nHKKlZKjGVZYiyhRfAG83wvHnT83lq+Ad0lgaZTR4z -6nrd5ViOlHPlfqo4RPZPzPe+uF7EfDl792sJerXGAasLosmKnxKAyJyVjh7eZcjT -S/hUhO9zAKDVyLHJ/gQlMYk8vE5XYL7Pw4d28wP/VsKVkjlxsXpcrCQIoKeDXgKN -Vv9L+0Pebspzr2WOah8iBN1QOkbtexIKCbb9mmviEnJU0FFx5MIw4mipvY4EpCaH -3McGwJpCzWmdzID8Z6oISUyKsuP7PXjmASbogV6Iqy2m/2RDtfbIlbwotfbiOT9T -r3IPbH+tHAZByMRyvxID/RN90WOPSpODxr9AH9btmeJD0BfNt99116+qdwvWrTof -cbkBgzvB34vLLDaMKVIyinxz2lYyC7aSpA3uzjZvoPvPrQJFLE0dx7DSkUTtWbQG -ByRabpyrXYdKZzsFXLb+LSTWwF3sQLax0C4cYT7OLPlxjDVq/A0jgztaZVWa37IY -tClIb3RlbCBUZXN0IChkZW1vIGtleSkgPGhvdGVsQGV4YW1wbGUubmV0PohVBBMR -AgAVBQI246XaAwsKAwMVAwIDFgIBAheAAAoJEBPbllU0xuPx7NQAoMhUK7d8mW1F -45Qpwtpbn/EdSuqNAJ94+GVY6GrtMbA8yrZHeD8zSAedrrkBDQQ246YdEAQAzpO6 -UuCWWpP9up5GVhLPoSCBfSIA9JWm5Ap6/hjQ5hia7CcS8E41PjaGl6Pkh5lj2qkS -UBa892SXyQMYqMqEq/h7+BW7+n62SCRMtYOHRYZPA4hvs0d7jznGQlMsltx7qamo -VNP0XF+ws1wHLjyQl3qMnkrAQ8lAJP+jg7P5Hq8AAwcD/A61qQLRXsSFr7LMBnaU -SR0o6+4/HCdh8t+mnAeQBDAkne5DTPiwqzqsjoYekX6JK7wk+mbsJTd/Zw55Jkq9 -xVm6nEUo/JIbN7cPlMqfCLaoS+ttbxZ9fNCO3WTNdWxAr/mGZZiBfy9yTcxUfo5q -Tg0ffWy40CNHaVKk+iIcktGziEYEGBECAAYFAjbjph0ACgkQE9uWVTTG4/EmaACf -U+XRhr/UgvgCfMlOthY327vlI30AoJypWeGLup2DqouZIGkY8bmpDrz9mQGiBDbj -p/8RBACXrm5v2sQpLtexfA2S8a2PUruCeqXYfVsnkYX1sYJaFaYHxYW2wDL1dR4L -dZuty5YWBOxu1N9dnkjuPsdIbq6R/phy6xv5sDUihP4YBAZakV5ahd7XrBdkWXSk -RzaJSfH1OG2hAXR87liVu8ck8RDeS+ipx1vnZY45864IAnFzqwCg2qjnDRjGAn2O -SPsnhyZH44VQQpcD/A7SOu9gTt6Jl4VSMY2JGi3HOFPOHnevG3Pb8NYbcP4gEU63 -iqrHGndYJI07lKcFlZRbnSEOSFPFLuNKax88GYKKeZDoQXkVoU/ItAGrS4rCExpZ -+Jx2tBL2zJcWU+7NDmM5LeRUDE6a0N3sIxMLzz3Z2PTarMATjpA01Qj3WRlcA/48 -g1+gnyFXbO+UZn21WWj4uCyXUE6/G8SCZhXXiDJOYxaBrmw2rtN0x1aLwXPRXLuw -jhL5Ewn3qszCzaJPNYuLaMY7jiK2ha20LCqYYmaVJa6tGy9iFIGC80ItcUYZpCfm -dw7W2oqdZIN/rblScCKmyBbw/gCB3molmLBd8nrseLQrSnVsaWV0IFRlc3QgKGRl -bW8ga2V5KSA8anVsaWV0QGV4YW1wbGUubmV0PohVBBMRAgAVBQI246f/AwsKAwMV -AwIDFgIBAheAAAoJEAyCDHHSaZMTQPYAoKRB8Ey3Ny6TaKaGoL2GNFQEwM1MAJ0W -blK0ScSKbm1BN+2hfDmmKRkgvbkBDQQ246gqEAQAkdlSJYfTiZH/CkfV8tnhI6ID -z+SgiZKcneEBnO+hAJottARGAojdbURlOIeZqRCgKpdTXBK7MdHAz4RKFnAAXPDB -ZgA5q+Coqn580t/O/AKGb8kKn9n52z9lC8A5KnHaRAsOKVyPTIU5vq6FLmsWmMB5 -5iz826Dk9kMhV7mmdQcABA0EAI8Jq3Jnqf0HqqaX7CZuNKHJgag14bTaBw0niZK0 -KSB6FBpzitEoyst5JBPCl0ayQEw0Hn4jhZAqcZybI//pC1CNQBBO47VUi0y1UVjE -xtaNmmWxugzkzWHHx4WmyWsCQwGN4B9riUws4g3dgC007l+aonKzj5QEo1XiiMNT -FFmPiEYEGBECAAYFAjbjqCoACgkQDIIMcdJpkxOPrgCgvrCZO/Txjq3F6U9vxdQq -lrLDgXIAnid5WPrZkh91f3gM+QXTQfmq9V4RmQGiBDbjqN0RBADBWmbmmByw+u1J -TAixxj5NXRXQJ9zLtkxRQ1GHxLQPyQzojWWnD4kEme8yvsFXuulbPX8zZMnl6qcC -8wt+b5E8dCtZuvQL3vS51yGe9M76VRC/1HgriE0YqHMTYJT4J+HciftldHFid+jR -nGZpLwVtLxiLaWAm6SBi82FTn4lVGwCgtjc3u/SMsPgylPRyN/QeH8/OZ5MD/R2y -G/c+ZF4kWcgmlzjJxQUN2wGYeDoOWUMXS8mf6yF+DLtwxo6oOlLaLHVTR6+qH2Vh -z1zaqk1Ir6FJjkuUGvHbVFt2BmvL26StTjJ4zC4UFSWYP3qLvfbPThT+RoD4ea+V -cPxGEGeqs0umImJ6s0reS3KJS9vgHtGo11Is4nP1A/9EzV7QkX5EuEnlUpGV2q29 -aGYx3RpcOhDYixogNHuW+K9KwcluBEEBmT74NwxVzI6qdJVVZn5lxT4IC5G0z/ki -df1Rkgv8Eqj5DIikgnp0asB8FiHSsb+39d4cnk2V0ez/LmknXUl2mpKpk/fb+qXW -TqPDbFUE8dz8zyqRFXIjwbQnTGltYSBUZXN0IChkZW1vIGtleSkgPGxpbWFAZXhh -bXBsZS5uZXQ+iFUEExECABUFAjbjqN0DCwoDAxUDAgMWAgECF4AACgkQN8q1H7eR -A/iKXACgkZY9/w96yK2Oiq/MUs/A74SzJ2MAniQ2eSHT5CQ4G8PPvYfPZueNI9PT -uQENBDbjqPUQBACn8JyfkTPFcgaWMpUpnk+nTEkDe4GhAG9fO7alTgdT6+aDCdfX -fXfH7gGwdURvDv6V/KEqcMPRNLAgAeP/F4T6OtoJNTxfWLB7j14DJNpYXjBPJPN1 -kpD2at8GcWB1aVGMsAtxMwlo4TZlqyfzCAAQeCLhBbIE9LWKX5oUTqiLOwADBgP9 -Gm8md+/xWp9sLE5i3uZ4t9Muu9w+UY3Ke/WcSA2CNthEYhHNtcMPP6PBwtz0x425 -mC1pe9RuxDyzRfV0/q+rjdWZBNA+VTVNDHXSj5hifvem3KFvA6TIgMabJ/q4WE7T -4Hn8xjQpEsLGjSXAzG9WRg13qTzTilIk+rC6xYGbZHSIRgQYEQIABgUCNuOo9QAK -CRA3yrUft5ED+P5vAJ9dQMc2nMpcKuH28xwKl8r7MP3pygCfWHGKFHWIDkUt8RfH -AB9geauEQSKZAaIENuOqZBEEAKLUF5GqBMWJQtBs1t1Sp+NIOGuMLgJOhINbMU6t -k2jzeUt6ooNd+c8P0TexsbSETwhrU4ntpvIISb7I8Twhcled7bi5KCABJOzz7Fw+ -Ydxo5Yjm1DQH7+gEtPx3n4AjZUfRAN0nqcFizDpRYPqVaN1QYiGWn9yPF3pubQhV -n8zzAKCpx1LUlQl2e5t1YJhmom2qy38EeQP+IB45FBfDf5KKtyS64alQ0vHYIssU -p806PQorw/ZOuoiscUQj/WeZ4vn7rCdu60uR1EuHpGp7n0t7igEgAOcxDjrxJmpg -SdD79V+oJAFLATo2msj1IklVvJeI7ZsImyPchIU1lqn/GvpAam9N+FiIB1KUMFqT -Jzc6zUn1Qqag1w0EAIiRHPYRW8ojd9Uh4Ed3X0daAnClyMWL82t2bj/bJRmhupQn -4aVJ5D0pFB9izTiJEWciHpqiMdsi/zExYYIDS1Zu94+WFbNIxyMFfHrJ5fUQtAqL -b7E5LrlxZONUnrRwshqR4X2TmW2mz1Wop542eUQ1UWp4Gr3VlH6giswY0CnQtCdN -aWtlIFRlc3QgKGRlbW8ga2V5KSA8bWlrZUBleGFtcGxlLm5ldD6IVQQTEQIAFQUC -NuOqZAMLCgMDFQMCAxYCAQIXgAAKCRC+eUhSvlz4hvEjAJsEfDLAxH49s9lf0nql -F4tcflpr/wCeJKCP6iVwvhGIdCu+Dbvf6z8/sI60Ek1hbGxvcnkgKGRlbW8ga2V5 -KYhVBBMRAgAVBQI247e3AwsKAwMVAwIDFgIBAheAAAoJEL55SFK+XPiGmdUAoKhr -c+z524neflMpRwJ+NG8KVxOxAJsFZqm7bBtYllrdcTqNqMk49LfBObkBDQQ246p+ -EAQApnvWjY5rMvw9Ly8xFL49pGjAYFb9zFijvgG4tMirI3T9EBLflKLJ8m4KWoRo -T2eNmy/JGLHyZjveaVh8TerDV+uxZkEGvv702nz8NOElQTjHWHoy0n6poci6Fxhf -Jd1bnOjDK2mZEufEQNSn2PhA46gjCLRTAPuwLpitSSL5ubsAAwYD/ij9KRO69/Jx -3+W9DZQxWIQBiKnYHVr1us2WpdpTV4jpCqJOCOgB/hlBmCY1C1/tpsAj1A3ZZamJ -RWVZoNokkReItZLXfGacprGbmmjcg89gFM5V3nEUNCU/mm2BQWp58h4NOCv60dGr -5GAqHDxAStPk388zbxEdyFs57CPQ4ZJtiEYEGBECAAYFAjbjqn4ACgkQvnlIUr5c -+IaRMgCfdcoqwoaTU7rNH0BWaYUfCrQ6TnIAniN+yQaBbwZHMbSaDTBRndjLglsK -mQGiBDbjquMRBACteKaHZ7pcM7Quj8Ec8Sx0fJ3u0NdLso5xn9Ek4FWMLBu6jw7b -/5KjB2WtXOZSWKHOzeTfUAx79NMKJrD9jZW/0kEAFVeZpwZF1l8fBsRELR9cxAaj -E3RvFkgCYAhXsF1Jno+qiU5TNvadGU4SzmP4vOnnjrIWTy83mtZiwoFIcwCggaaa -ClE8Q41NyIfVtjS3f+Nm8x0D/icH9uwM3vpB2QV29IIBqazgaFr7vBoogFoAllaC -QbPLiyHX1Mk3kEZg5xewmDS/tU4rGqj7UcL9OlZx1ICD8cp80yNYfoI7K5XM6sYO -MmfJORGOEsqMtoYbo3lluDgDkg26DZNynUeFHZRrIWz2cKqTuaB3dw09m8sJNus3 -poEtA/9Q1KDsjKPi8+2kUzJoK3V61QglXAVDlfzK6B5KOEZ6GR/gX9M5uyyLjREy -bFSSNPlvLR11+mV4GR5AcrVQOmE0QpFyo1Mr+uDsbqwkzERvRq1r5pOyqM5WPXhl -Xa5oo4na1fBEX76IEzK6xIVG07GnNnaY+dlPgsLq4I8+A20ZG7QvTm92ZW1iZXIg -VGVzdCAoZGVtbyBrZXkpIDxub3ZlbWJlckBleGFtcGxlLm5ldD6IVQQTEQIAFQUC -NuOq4wMLCgMDFQMCAxYCAQIXgAAKCRAlsA/UMM7GhJjYAJ49ENMfPwK1U1ESEYQS -5Yts3SRcAgCdG65G3ZW0dnhnjQAhf/vk+EteMfK5AQ0ENuOrHBAEAOGceVg3PC6F -tgrZrnofohzWnui6FVBzeai1DZ5MMKmdN6/QMv1eeHoMOb33fbfhwA51n+kPuhap -r6QqTzx62RGA/gK1m7vjU2OfYxSO65GN/rSUXN/kE83jR7Hux4MocRXZ+/8ngqL7 -JAjw1LZdJyOniJpeRvrckPNC/bKaua77AAMFA/95VjAjJIAU/gOMwtbqTgV+cmHe -52Aa1CJEalV88yKG86nnqHuL4xxUTTZljyjbbKleJD/Ah7R1BxBhSEDy8WuTuonE -VHVxTcL9Yig4pZ/OzYZf5fkl1eLNaSLb8XZMT0JbP02b//OMpAr29lcaga1o1RtW -vrlUyIYOTm2RcTxkf4hGBBgRAgAGBQI246scAAoJECWwD9QwzsaEIOcAnjt0vZDn -9+3cTNpCuV1ZKIu2t410AJ0Y3CnFBUFBOKk6zkOJnaArwVN3ZZkBogQ246tbEQQA -lWieyQhDso2ZnD2wb+gq6aqk1rRUhcwdBwCTbiE1aLAsnuMl8nLH4fvhaTz2V/Ae -joL00e28duA5or9JiBfmVblrpTAIGWsu0AU6uEQsWgZwRdso3NH/KfH8Z5lxwJtk -Z/hlAiEHohmGoD38mJNsgnm63RXadUH76irO6McvWlcAoONeH7i25AcrMol4O7BZ -wqGq25ibA/9IRhK7AFhfgaRrDTz84PaIssxp1dWKalRruMJYGQK2LDuEl53Q+d1r -nYBPliPbjWr/9Gkjx3K4B0CfWWQC0sUl77bNRFqr8FXkjRZcvkCoxxHG7PIFG77r -Ld2SiQ+eS+dp5QijuuMC8skkvQuuxS6eIk0g+jjGlNhjuu97Ya6xeQP/Zxek37p8 -P1u9TTmN7nPtlzGXGrfKVi9DtJ31E805ruXFqTuoFfcOBRrtfY+DOebX8RxIwQV/ -TEmyxwoXdmkv03EYwD6AJSmx3WuVi5/revcH9nfSEHDy7sFC8CBp4aavAFRQNrho -mSB9lSm5clGLZiD4nljF1EFABwQFch7HhlO0KU9zY2FyIFRlc3QgKGRlbW8ga2V5 -KSA8b3NjYXJAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjq1sDCwoDAxUDAgMWAgEC -F4AACgkQX2NWum2XMqywLwCbBT6UT+lNWMh/jxFu/m5Dy2qMwpMAmwePBu7USi6T -WKaXYRSL2yywJR0HuQENBDbjq44QBACdC1XRPM9CMFrgVUvioU7SShffLnjgWBZ3 -hqbOYrsgtXfuQdv6lAixnNPdnk/k4mjL8w1pqbjUmfmbppVDxzsiiUQlJatzGDfU -1gDc7ksnXpF/vzghbucy8HNO0SHi3uM/GXC574iZ1oxa/A14fKnCVYT1ThqUa1us -C5YQXHm4IwADBQP/f4LZgN3dbL4jLqXHDNpAIEjiTbKXxDKHOnAof//4SE0mpaNV -HLu3nxI57CtXfSI2kMQSm/3pqpTKzaBlM/CbMAJUanhmlLPARDcJ/hQcDtBsF5nF -G7zfLfe0SBwgsM1HxL968Vva7WsbYpSa98+3HSDuy9VwphFp7i4HbnCbSK6IRgQY -EQIABgUCNuOrjgAKCRBfY1a6bZcyrA3hAJ0erCoxKtpc184iLkp5kpXQakDGHgCe -K2WXA5gTOULftladXZn8tNoXM6CZAaIENuOsQxEEAIQRmJhsJniNi/bRff/YGrZ9 -aFWt81G93W8WhV51qq+ntUHgUNY55Yyos4XLOa2tS+K8zP6X15FesVBPYIQa5BIC -10mAsLfJ+1rbnGJPuNBA2U2MoEaRxo/JtXQ//5jiTRlYwLDRnBzuaMCPdsirveu+ -JBw53ytRwjwe7m/D1PPvAKCp2dj1FtDjubTN7kCF0o2KzPwE0wP7BimQxXyPwSzG -qLaHXSEBsh84OQTxPI98BXgq0195/A1B1/pPs356euKlqoefUTHYhbjiMYbjZT+A -6juudf7A2Ucy03G8HDZ4k1f1vmzrj24+6ygGBcxTVr0BaweiC1DwG3LjQoJ1cuFx -RQ8BYJDGIwPrUW5JdlnzW2bJWfdyXOoD/0S7iEVN9txkSKildOeP1YcDCD8MM3hv -F9kUc+1hbmir8SOZ/IYJAyQN+j+mYWsLuKtZ/F9pqiBNTXH2jWCTqldOD/ZYxHVJ -AARnkiVG6yckMLsxHi2LPPBK8xack0y92mKe7za/7fhVgCRSs7M/rzUbzUhyInHS -yxr2SYb+8lbutCdQYXBhIHRlc3QgKGRlbW8ga2V5KSA8cGFwYUBleGFtcGxlLm5l -dD6IVQQTEQIAFQUCNuOsQwMLCgMDFQMCAxYCAQIXgAAKCRBdFeAdP/EyBgb6AJsE -NGQmK4nUrwcbtZ7+av5GDQ2T4wCfYJaV2rBtTR9aWTRQfZOQoIkNF8+5AQ0ENuOs -cRAEAN5hO+fEhqW2pX71oSUqW/TRHWSbybNc5brQ1tzgTbheHiG/LQJ1lHjtZoZQ -syW3H/efEuNARwryo4IjvK0nmiQsqZUR1795XTIbo/waPN08QujC26uWbL1pYL5y -QarwbKOoyAst4jgE1NpZVc/r1+WUp7NuEapicVjvFNzkiVCLAAMGBACWQJYr+h0o -zr7JQ/BqI8vTKuVXb+DIBQjuSzN7LvaiIqMqb9ZdfNNmZ1Atvklo2Ce2VMyliQzV -STZuHJQbfrDTBXBf+Q+AINiHdZEAodzBvDv6p7vsTnoP+A2bS8l6xrWObKt3Ky9+ -GUDkqW3WuagcUKogQgEb/FKec+GegwSgUYhGBBgRAgAGBQI246xxAAoJEF0V4B0/ -8TIGk4cAn1I/jmu7FSgglh9aPmVYAw7HWQMAAJ9PAPPXfqtwza6I8ttGPLYNvEAm -AZkBogQ246zREQQAgcIj/Eo8PrIhEaxKcjc9dNb9/0BZ3BxBk7x9a7HKm6o0/vcf -LH2XFjFxB4Ddfe+O1PC9KNUqIi6GTafGbyqS47XsnOJs5nvsrgmVpUUzAd7p0dxc -c2tJodwhkH4GtOP4i4P9XBrxngQrWQ0ju333EPF6wLWi7qkVyGENCfsvktMAoKYg -M+XYh9UQe7/HX0GiCnk3ExVnA/4ryBxdyBihj02i6s8vAe5mlTrwv85ugouSB95X -EX8GPfvaWIW/TpUWQ6a7o8YzU/kIPa7YzETYX8e/FVr2Zd33HAfeLUNp3OS0NvEb -YJlGDfW7/X7qLVv1o5WCjCHUhK8DCf9Ax9b4z7CbRHptxSE4U79NCCOsXQsObV28 -qlGsFQP+IIaCh7dTqADw/nBmfuXxepPKXS6Xdi0to79LfQtr+TUtJOEVGIbqqQBs -gESFiT5qR0W7qhOnl47TIQyPQnt/V994QwyAGtIgtM5qYFRW70g1FkyDRX57PzTM -uU2BjVI6mHkaUkLaLujbRXiQFm8IXJ4rf297GppKuSgvNcr7Rmq0K1F1ZWJlYyBU -ZXN0IChkZW1vIGtleSkgPHF1ZWJlY0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOs -0QMLCgMDFQMCAxYCAQIXgAAKCRAcZ+wTPGYchNG4AJ98zSyvQ3Rt+Y+AVfawyEoo -sFG5KwCgmMyj4RYhRlXKWCPORBxAfCOYMtW5AQ0ENuOs5BAEAJGi4T/jrY5BtRTM -0psAneQytzzFgH4+LigUXAAb0QDAOkyGNfWHrfHJIS7A3Nc9pMWAdOjWgSKbYyrz -ra0SQ75/SkI5+/S5ev2Fpki+HYo7cNgVXnbCJrIY7k4DAMunqPJ9JCUXc88WxGvK -V5b45htqCPnV2Pgq+AEIKD5aGfLjAAMFA/9+O6ttUbeY2bQHRdThl4HUxQw4lgYN -7stgGZsbHCc0y6ln1HF9vlE4Tl6HI/NR/8OauQrXt8988dh039QNZsOdAeRWTk4P -gSuXq6VDG5WNw6B9bvRPKXe5yeVmNNl6KESBzMcq87kANZWZ68vKJ2JihxPHRAyf -xwGr2JKkVF0S+YhGBBgRAgAGBQI246zkAAoJEBxn7BM8ZhyEiJcAoJTy/pFHvd9y -xAYZBYp7qLG2lUIOAJ9Rlpbjou3wb81vE+Qev1+GQGpaVZkBogQ24644EQQAlNDo -1aAt9iof3VI1z3TehyLrBIR4XmKRSM2Bx02CZhQRIwY/QsK6WBoxlJqfgUtsBUuf -cztjJaUBixq5qPmBgXYqN9/B8HZvG2nknHdiqKrvqFpAqATJtlccW0tzPJKtKaTb -tkORBDv6hssFa1aXwTN7IjN5nLI1Wh8lsvk9SKsAoP5Z4IDSK/mM9h6FPRsAsAYv -d99ZA/40UwQLl06u7wBtmxqSdF/86kjC0kWX8J2Y9vIceiNEiE9MmVNcYIKwIM0m -wduF50EksVjEdgWUJrqT3RztJfMT5+Sgm2KOAvvfmbKa8RF4NPSrVXDDrFeqk6uN -DT0jnUUTQFYTjk4Pxg9Kl+a/c7Qee6qXn5qeDX8ubZqN0noX0QP/Y5HSgi62UbBP -5B+e5BqE+ZLeJ7yVtl909NwTCr7KVZt1o3Za0dCYtMosPT9ObAjCanhSnuEWa3hu -outOgorWaUSEW6Y3zBKvN/M4FA7+1Rhe86gnnWLt+rHqX5M8Y/7JTcrugNtR04DF -sYga5A16CLsTDxSmM2Rgvpwh14FtrqG0KVJvbWVvIFRlc3QgKGRlbW8ga2V5KSA8 -cm9tZW9AZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjrjgDCwoDAxUDAgMWAgECF4AA -CgkQO9vtsXd/vtOr4ACgllMIBb4leDKz61LQiA4TGWQp9+QAn0gF7rrvXtHdEc9k -FQxgfASZH4RZuQENBDbjrmYQBACJ5res4tXRZj36s7P4KZWUf0YC8mtLxxeNEXe5 -ckAtn8gMfcSQJ4Mei4O1EBvrKZ9Dz28Emv0FmDd66DUd4ybRIk1PN8kWry9UuGLA -f/VBAkMIyXhYCEnB7wRsNj4kF5DhYiytep2wekPocZO2GAUoIyY2yMNb2m2g2K8U -nK2QBwADBQP+Ixih3o+++i02Xwi4wOe7aro2xSeBmH9b8nEaJ8v8RVLRO0AgoR4G -LzKeTOfv57FU48tlY7sxth6FOxeJaQkS1nD1LRpb3GUDZr7qM/yOGYp0WhdRgGW+ -c0eYa32g5ajq2zn3+H1L4yrmRSZM4nmZ5ZXe9ijkGs0UNYqmi0gBYxqIRgQYEQIA -BgUCNuOuZgAKCRA72+2xd3++00nRAKCX6f3/mVnEreWCgorUdZh8hg1LEgCg7FUW -Ctn3HWOwgOwxxKzOs/rQm+CZAaIENuOvBBEEAMUtk4AJiXP3jaKpIhbi3B73S2SZ -67rKzBkicjelpwWk6LndsCrbLsIWsDf8fNtih0r9As+2arfApkNlwuCGq1ZlPGGG -Ef18OqPxFvnghVEbDdcosP4bIm3k6G2sgFbMl68xAGnTtkS5Gfz43uTuznPzdZnG -bIjP0uBmPfZk6GW7AKDhi4htuxr3Y+ud9lx1bWM9KqUtAwQAiRYHm605RZVBkdzl -fYx1Iwgn/l8Chq3MsPrfBMslapBnq1an2/nEQPmuIde9C6ALN1t03DHpKonx2Xgj -YVz8pgty2FU7txSSm2EE+975dXp3ov4TfD1KxksOl770PAzixLfNhPW1q4A2cEru -GgO74qEX3/fAa1J0nRKDgmA/mgYD/2TSZKCaFHoc3IHQnkygmGzzZNpVZV2+1kIB -8Z2hNo9V81PYpzlYV8SlG51ajW1G3ePcti7JOIP6MquNUbYR4TOzZy1Dq4+VqqZC -B6fOeIKL40IKKAoMMDYFNLp9zcT+s6+6DTPH27eE1WEt+NQjBgr2ofC/4iAU/nmA -Ymo4xn7YtCtTaWVycmEgVGVzdCAoZGVtbyBrZXkpIDxzaWVycmFAZXhhbXBsZS5u -ZXQ+iFUEExECABUFAjbjrwQDCwoDAxUDAgMWAgECF4AACgkQpeZ/f6OuPqGvfwCg -oevUn2afCdW1bLwbcRs5kYrM1GwAn04Y4r15A7ytYdO2PaxSkSJ4gn5NuQENBDbj -r4AQBAC4cckdPiWgQNkGvAm3q8FxzRLog68/jffvj8Mvt++XQ4NikO0VJ8ezYkVd -+vG3v5RoHTISynmMWZZjT56aFDSDZPOkQs2G0qZgAEgTpzCUBdlnUC8ZrHSTSQjC -n7HtR2cpYCCUBliPtatDvS3Me1XdRfBhXib04TB0ci6DrzFQkwADBQQAje0R1INm -9GkZKAzTECi+lVei7wbXkn4JF6n9r1KL5oULVF8aGHNEJ1Twj7kuq2kacYjc/Di4 -KdESRTZN9szlZnNruvAd9JKHIgbeysene3yRhy+YFaqXm1MtWCdwwaDiDoHDASpl -55RtuCKxz6uW77qhrZ8E6GRDrhI92R88DbmIRgQYEQIABgUCNuOvgAAKCRCl5n9/ -o64+oWsJAJ0XijmoDUP1Iu6lhsSlmGOiNO/l4QCff5G6w6Vkq8d86Ev2IwS9Wf4u -NmaZAaIENuOwChEEAJDhTfBph5G51alEDUaIfFvD0K+oXDXqDB7hDg3stVIpZR99 -d2bo/dPOuVWorwXFBDJeK0c7iJEQrMWKlxdqbRGkH8paFSnL5XWo4xMjknqnJzYu -3gb734ioFHTC4WDM2/voTGuFpLw+eirW+wl12wusHpnNkWxMEIWt2HoGTerfAKD3 -JUBraePb8gHKnXFzyEu8RLp3swP/XaAKje+NAYeqhcAqxv2SEPUj8EMgtX7SDkky -Dv8wuRfcNwMAt4XwHYnnM3bpUwWj2JcDGE9rsNna/HuFAjz/2lrhUKncH0Cywvjh -Ytt1t92j0cPZaeR3pY8R/bm8Ns20tiP7uxVlj+szI2Pf5KiUHhiWHJ2RTXGE2pUm -T6UFhc0D/juyZvINKwkbUSSwpKvsoi15d6e4Wx5PZ2mArT5y+ULitBx4WKIsXV6U -VVaEBNaBe63k9cFGdPEba/HflSd76kLmcSdy+Fr73d3TMIrmwAKMVdKjRAEc3l87 -YaPd2/LdT+TWzCQw33EotexJ7yZzZA2SJx27/jyIgXkWtwvn5UCMtClUYW5nbyBU -ZXN0IChkZW1vIGtleSkgPHRhbmdvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247AK -AwsKAwMVAwIDFgIBAheAAAoJEFjLmkyFqB84JOIAni+c3CDhA3k2Pp2CWgBSFcsT -A59CAJ4gy1+t/Pwk/095y1T6g3rwRbE0zbkBDQQ247CeEAQAnr0w2OcvlUX7E8u2 -C8dJGIj7wRU5qDazxh0tw55/ybJ3/KyhCFfsr2dZ2E7Zw6Yvc1u3WTTf82nH4S+/ -IJFSI+qBi3TrcwVtt8Xa3Po7cIzNvS0bBhqfmOOXJc4ihUlADR2Jukm/QC+f6bO8 -IZBDWr/7LnT4SwEPhPoZNMFb63sAAwYEAJ2kiP3e1zM+zEo2i2jkOny1Igyn0sRi -uw0OXQ9B656zp02G5qtDN+IXhgLdfQqgqyWckP4BLDJ4NtQoEM/Mr2/7oj3h01Xp -bU86R1QFQOXmoWw3q7yqEWIwfOBqClSF0A14sXdjQwadyabTFsW4m8Zn5jLW+1sH -4PrVjHoNEz4CiEYEGBECAAYFAjbjsJ4ACgkQWMuaTIWoHzgImwCfYJ4NGyH/snAB -xoxryuVciL3Cyu8AoMtIZ222A8al4XK0DrQqJAnIZlF+mQGiBDbjsakRBADettZo -8gTOTr1nJXbk5sJfuVSQaMmbgLpZpMs3Q7C+gAX0XX+Q/vcuHp+wV2Nq0S4v+w5K -+sxDF4A8UDf+q+GmNKMA5U27hkcDQvE48EYUghcdWKjWeFwmmJOb0KMoatdeh4iP -T4j8ocGw+i0z6o/e0y0OVWsUvIqp4iZP3UlnOwCggOq5GfPJMq3K3cND3nU7GOR8 -e1EEAMcgH09o68Hbjbwpw+ejPuKwVFa37COX/65FF8PONeleq7Mr3Y8yKqbLIsIW -DaxrlflpbyMz/ShuDdNU8gh+msfwh0+RNzdEPmpJCCVJOdZO46cudgbyAQriH7Py -sSbi7AbmpnMl7kQruhAZWXLtnH1e1kKovB43a3ph8wF4kotyA/45A8bLKEmJvpq/ -amY6VjDnGsxkDjjw2OoVbt8sLdGjpganj3fvy5KRhWeWLKhmtq44tH97m4YDmGCH -Va/Iic4aDPMMvUPWdaY5DyCeerVOb3JN1qLC7o5x2HBt8RE7cXnPJl5VKxc4qzys -5bqQEYYt2dP4cJqKk3OjjCbl6TJ+8bQtVW5pZm9ybSBUZXN0IChkZW1vIGtleSkg -PHVuaWZvcm1AZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjsakDCwoDAxUDAgMWAgEC -F4AACgkQqUwPdWUyRNYzWwCeMxscN9idLHgH2DP2U6tP0tNR0T0An3lfFgidO+z8 -ZeHXzuOM9TAS+jz6uQENBDbjscMQBAC1u+09NP46dPnn6RJtczL3LEroyrcPmHOk -3FbiNfJ8YMnFBeST+U++chi/kKzm+N4y8TZE8sHwGqnkeIBtJX2YmQJFhKi2RR9A -tVn2HV1ZTBYT1q/P7MpZTPMI9EODlCEPJTvX+MdtP8xh0Gsj1i1wujQOJAiXdrqs -Pxen4Sch5wADBQP+NRROzLFq4kBUpgoTyvWzJl96Gdykf+O0AhbTlZ7ix9KtQLfx -Grqzgo0hwDjb2QzeWHfjVhaaaSc5UWNMuIQyHRcsj9x4n25XGE0HUyOVSD46IOAj -fZF+beXOa/NbYcR+zzORfXr1qyW2g4oV8LN4s4uV4dPamQ3l98Lkg8lhWCeIRgQY -EQIABgUCNuOxwwAKCRCpTA91ZTJE1s6YAJ9ZgYjqQ3rScmCwhc3Ihzt2ATANbwCd -FuVgvD2Yh8lsuiWswLDFrNsDk5WZAaIENuOzmhEEAKMDGobMDqPX3SKI3/W8m9Lm -NgtDUffHGHNd1npnGM8mSyVfWjEWoEg2GPMEmdX3/tvUUV7nTz02IJwZRVlrbEPd -W76eItMAY1NB43LpjQTrAR++mVAslulUY6a5V5nJKEc0IqOuxkW1LWavujX1JRvl -BZLeBkdpsVNuaGJtwUFfAKDfqoZUCcZxnO+dRMalHLfGOn7O4QP/apMk2mc+GJwp -KSxXBvoQkVcfuZBJmXJuUCc4BUUzHX0ZSKNbgxY/kVR1xN3krMgOCR6dEsGukIsg -VWRDj9to/+E6IIs6YKhG7fGcXKhE8z8mf3hDLcmjbCKDCSFBT7PI5TkLzlAEP1y2 -Rtin/Sa71unGZhNyEfAPW/d1dRcRVqMD/2WcTPUaIjRvAqmbxUpenRhg/mF5rwmH -l81VvVBbZCoZ35c0edEZKpfmyYbKuz7GhjEPz6O/UWGYZpK/7r6f4kFUrhO5atCl -nRyBkvmNmdfbtM5hd5jh3lgqAT7tk7ntPAIh8X8/qm5+Uab63kZwXCPiSR+iEwRp -42GbVL7F/b2rtCtWaWN0b3IgVGVzdCAoZGVtbyBrZXkpIDx2aWN0b3JAZXhhbXBs -ZS5vcmc+iFUEExECABUFAjbjs5oDCwoDAxUDAgMWAgECF4AACgkQR69LaWHwR4TM -SQCgwD4p9j1sDwR1+9bBrzNQzVIyzmsAoNL7pfcdW4Jou1XHNc6hv4MpsHtvuQEN -BDbjs74QBACHkUCB29pMkveMEZyNiKImizF5NZ/cv91Rj319k3xHf0NJWhQp/1G3 -8SxLkPLBdWcoB4mJRNjDyVsxFUXvRWFIMekwL0q1sHSWTcJwCpQs+LKKtPmD3LA3 -bhbuTSdpYgmKy21SH4epubqBzk/P0193mWXzHgSGLeUoTo3N7eBQ0wADBQP8C1Q3 -WGrBZNOmFVly0erclpQRv1qCa785yx/bj9ur2LxHwVozAEXh8jmoiKZyoAz7YFnp -29kR2qtVplH1oePNyFweZqIjtmZbiCaT4scUVZ/3LuYbxgMoUFeRoG4mnEVvUUh8 -mmZovMmZFrvp0uojcDsfYTx0VBr8waxgJrg2YguIRQQYEQIABgUCNuOzvgAKCRBH -r0tpYfBHhFPdAKCcyVECIa28vmUPgZ2jkXQoQ/nNkQCUDpGL1aZn1eKrDlHcGyD4 -CzywnpkBogQ247Q0EQQAvVX9TJEynPJEsX3X2fGPPDiQK+oB7D1INI9bfID5NKto -o8qybivOLo85i5m7RUiEyhX3E9lUg9buKmtIhas0sJ8sLURmCndIKtXjIWg3Kd0p -mjE8q2zyd7ChQ3ffJ20875wNbR4GQhSO1WTuxwRoL53ft+9JTULJxkQRf71Azm8A -oJZQYphKeLWrLtFjb2WKbYxst54tBACS7C/Vu40euIevp2TZHTtY0U+ObFvJr8jD -rdQZMkUFSuhti7rfO/bf7qTwmCvv6IVmn905ACh9bnKwZvcR5T1yR2b6CAN267fz -riZhu6/FG+9Ddr62ZnV2rP8Oa7uxAXCnoovaafKYupopvHV0z0tUf2+wasrQdHZT -vc0pfY+56AP/WOVJ0KGzP6k9bYjYSRJ1MJb70wdVFiHdlIlEd5P3jQsXOyHVMrWp -6qH10sQLto8gweWJr9aHem0QjTNSTVpzp6laBHf7tnLEwCJGeX5f5BOh87akRjwf -h9J9zW+DBrtpqS6vjlDYU5y6RGbGRl6ndtXhV5FpE4cbLax/pGFWEq20K1doaXNr -eSBUZXN0IChkZW1vIGtleSkgPHdoaXNreUBleGFtcGxlLm5ldD6IVQQTEQIAFQUC -NuO0NAMLCgMDFQMCAxYCAQIXgAAKCRDe8Pe47Gfb3qJqAJ9MbluIqs8qjd1lOkj5 -8xC5K482bACgjeYJadH5StXmbJMGw2ZD29yevzO5AQ0ENuO0VhAEAM9X7EMxDw3O -SqgnI76WuIBSsI0gF/UptzpT8g8AY6gQPVhU9fgQHbu7cr8SZFV3dyUVLTzkNq7m -sUivd3/Fecuf77CpKBCrQlzst+UykiPQ/bT3+gq3owGi9MBCfeU2l5yZZ3yjGIqg -8/XnxmCbuItw69FNyz7+nQoDM28ci9B3AAMFA/wJBLjxXXqWFY5JdXq7ck66Qx5Y -HDpPH7szUKrIGKGZHxk2UXoU8G9WRfQ0VVQfaomfnKvo+bFDFJGcLfIITI8FrjzG -oh2K3PKcxsQiQ1SsVlMT3XmuvST0yvDM8a4t9o+2v8yLLgEjR2dn/lTiGjE/ANun -Ro9TBGpvz5P085NmzohGBBgRAgAGBQI247RWAAoJEN7w97jsZ9ve/yAAn18Lg2NX -AdY6HW0LEurh0Xcv8zlWAJ9ePiLMYxpoW5nv4g4nuOAWoL/KLJkBogQ247TcEQQA -rUqUbiVTMxJhp8bA4vMXAzCuLjys4A44DE+uRFb9AGsZTmw/FTPETO7iU/3frlyY -yTgIvI2zDF1SwHXG06KF3yIu8LF6OCM0N0k7KnKpw8M2tkPiT+D8ANrHU5d178ev -zm40PyNDyKxSGNlIG1N4MIKFtNdMlahLvu91kG04WesAoLPa5zISvsX+Ew95M1o4 -Qti8iYHbA/4wr+eYRywP35eb/F5V9bOLWhWmEDzw4KHXQ7V+OJ7JD5n44S5KLPKw -IogohDlPmrxDTAJ/YAukApUItd30kr0Uq34QgFktAsqgCP7C5KEM1TTxU25Tcs4o -jUHoDyMj14ECuiTCP0ZFRKUivopgjgRhFTKXVVWTySkQ0g9SDaITSgP/a0FyXMQU -YJjuB7GA6r4U6QnIHsxS5xrQgkshb4tp2MVWMhqlhsfOLaj1WZ+oe0DxKw0O3YKT -H/EAzmNelKcMbtTcilLaIdI5l+Ylam/bZe7QvbN2s72Kn2PZjtYqO3Uzqw14bqAJ -Rl0ekleMdZRMMzAsour+iNVPHnlodXnQ2gy0J1hSYXkgVGVzdCAoZGVtbyBrZXkp -IDx4cmF5QGV4YW1wbGUubmV0PohVBBMRAgAVBQI247TcAwsKAwMVAwIDFgIBAheA -AAoJEIl5psVWf7NKt08An0PRqhiMzF+L37DyvcaVl+0zSrmbAJ0fL+8D5Frcp1m3 -YtBMpo+j5dsieLkBDQQ247UFEAQAxuGlBvqoDkxhIDgFZzdHJO+gJym94zgSGHkB -mBIBf5Q2G2O3zkN7SIENI16yg9cxy7zkTbBu9PMgzUe/UuQov9Z6YXKzTj1jLozr -GdljKOcW5YRvlibo7eKXDUkSvT+X6J1BOIVexl05Y4Ncmf7otNDre29QfK8gGBO/ -bdQd7L8ABAsD/R4Nq/JQav4/7d5ETuMZddPAxV4kCnY+7F7oJgHDKJheJxt49rNt -fXSxBZUsJ9P6Xhr46fCRT33DD1P8RyUmmS3/dJl7H/qR3A1rox4FQPWAuk4WGhsf -SXvlZnFWKJhC8TZzFisjiXjw1OFYiF4TArxj9D7d/cHEKIi43rtefpf+iEYEGBEC -AAYFAjbjtQUACgkQiXmmxVZ/s0rskACeKGRhY+fGFtaL1JQxoHdDPRJ+wu8AmwQa -u+u5pPZc9UrBr0UV+pGPpY+emQGiBDbjtVERBADdUAZzhP6+69VdyRrgRNotouUv -XE6I8h0kxZFZZDrQJmpZcNWkUHDqgbYDJ9RmIeEuWZNmyzPxSFcvD9RGw9KmIZu2 -kZYqIuzg4KqOyU3SUfNycarEZYJkmLEyBlrkNxZkmPCp1cRsMKGCbhQs//v6Iq8h -6dNA2EWgJev0y12gcwCguk0KZIqVO7UfkaVaZhMr0Cd1at8D/juKnRViDMi9SEjS -JZwb3mw1+yECnM8vrM+AoGoAKiCz/n8N9Gf2DTsFy4yKEskPQ8s09Wc5epBFo3gN -ruMu4kDnde0uCmiDEbTwzpdSKZO5x9yi+7b39uCNkgoDlzwonaXNdIn2NnFKjL47 -TnV/vKFdtSZgLW902vwYGTr1ArL/BACIcx9TdxsJ9NMyaKD7MEcKQeOrOqv/Mq1H -xFPkDBI4hTZpQiId1XTxqkJ6UHDw9sR/TvtO5YKrZjINkmaBZFiHlx1oyB0B3u6X -UVLXIc9liyFyh9aOBdQkdHgjyI8Kzk6Z0ejYcre5TY4zfplAZKkUDlY3U0Sb0a0x -IGhgo3YRELQrWWFua2VlIFRlc3QgKGRlbW8ga2V5KSA8eWFua2VlQGV4YW1wbGUu -bmV0PohVBBMRAgAVBQI247VRAwsKAwMVAwIDFgIBAheAAAoJEJ7vNM1LEbJfSQQA -oJRRe9UHKHiX2iFczXq6nrvr0NhLAJ99W/I5b2/2QQ01we8i1mcSYPWj47kBDQQ2 -47VnEAQAmuK5RcS0zTyXp6SjW2+WeQIpJnJDflL0+iBe//3SADv01qUmw3jWMAux -G+CcCApksl122V9npEHiLC4Q2A69roLRsbxKBPebustfadLJoVYqPsvjnrBlafe5 -GcrFPnKbE0wV6ZXx/Tp/eSDiQlid4lWz5J+z/mN7KhHANzoRAbsAAwYEAJO5fkCS -dNwkisFXzeKslWxm9Yoe1TOouiSV11hex0j94Hpz5wGWEXF7z+FbDq+4V0UqGkKx -aERsl6HMWNkImj57N/9h1C1YDfiKTimg5tZpKmehXtldpWGCNDZrE0RasrFCKENV -hFMhpc4kAnx6rbA0+LhRvJkvkdxY7pKU//aZiEYEGBECAAYFAjbjtWcACgkQnu80 -zUsRsl/0XACfffuI4IS7cgh0PNghr/0v3L/NhncAoJNwutmN7kkv9n/oPqkByzLx -vZt4mQGiBDbjtcsRBACBDJOGX9C/xxCVZNP6OHz6cL5vM3PimUAhV+9HAVVPQViT -nFKrkYPSQyRfWzjOU8RO1Tp5CHz747oOb6j9P74yH1uy78yFg4UuhXBWinhuCKKq -4IIWwJkCKBFr1U8fu8a6Y6NcjqiDA0KmGRJrMPmXenXkJpFGHG78rUvNi9IMfwCg -ugzNILh/3XZCZU+BUPYeXL+nUAEEAIDXZhj1vFXHgi9lmijKDjJocEBoamN/taQy -6Ox1RRD6HtfAPY5TER1n7xm9hMzE+Ov1IKpH/E872Rha1qu1v7eOa6eTuNWF0Nvm -SR955freRsNuR8JNIb6StI2ER9pzBUfjykC9pg2wPeC7wpQJIF9TF+Ja1BvG2I+h -a2xJ786AA/sHEUvAOsc58YbPlbIPyp2JdEHvXTRT2NISVRuTMQsg8vV99nMYR2CU -h270uPyy2xZaD/kYcJ9/1ngY7C9pbbNWoV70PkEMO/qj67OIViWVPzUhIdURorbp -Ghuc3oBzUxOgial7IbISPRItDgg2oZoY4hqyQNx8Cj2ZZAzDpM2vCrQnWnVsdSBU -ZXN0IChkZW1vIGtleSkgPHp1bHVAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjtcsD -CwoDAxUDAgMWAgECF4AACgkQa8R3gFSs0kZA6wCeJUyRzuFbsZ0uQulvpgOIRTLT -KscAoLd3InVEj20peTUQ5b2NOimSXnKxuQENBDbjtfIQBADMfPDBQoMzv52Mmjb8 -SdaYKKNzqDd9K1oY2hcMSi+LcHag+KJFOyKBf3SoHmcU/vCEN+LyTgljYSKDmEf4 -wZ2+eLfqFgSdBJp2xm55ih+9CHXg3dXx9SbHiGJCIxfJaIsnNz3VmJGPDDjBlaf/ -hjl/7SZvR+MJpVLFPGjj7uOhTwADBQP/Sgv0abeCXVdVXwGEmhdV0VDo833IQRdR -u1yt+QLnWRMGTY1oQapsH6QLwYSZfDJlxbsBA3tfqKStpRSbdGNNTsK+RIehsGdd -i3sWGplRGm5Xt5KpkY/mc/tLFaYJNMqAgfWQcKlZHBp7EoWMgiRiDJUWq0TH1wRD -oPaRc+H5GdqIRgQYEQIABgUCNuO18gAKCRBrxHeAVKzSRn1jAKC5Gp5sHM9sWdZe -M6qfu54F2OwMQACfTjYXfpMApAROPkjhhFNqH0d8x5E= -=1N8S ------END PGP PUBLIC KEY BLOCK----- diff --git a/checks/pubring.asc b/checks/pubring.asc deleted file mode 100644 index b58aa5c11..000000000 --- a/checks/pubring.asc +++ /dev/null @@ -1,734 +0,0 @@ ------BEGIN PGP ARMORED FILE----- -Version: GnuPG v1.0.7 (GNU/Linux) -Comment: Use "gpg --dearmor" for unpacking - -mM8DNUWBuARHEAMA8bSQw1VFSXbgZ+nNXhM9xeDD+OpKQU4hUaCKfuTtRHoY5QxT -Pz3DFWRlFewsA50Ou28jlPWxIKZaaGxMqbDtqyUsm6AEz/vRi5VKiVHf28XUkMry -QSTHvjwJFVb7+6WbAAMFAwDXZiawNtgYsjwVedv/xXdhTsrf0Tn/8HCj3S9N/MAT -0zCnXL0flYeqhqL/okuBcrwMA4amAIWGVW7ws7k7QgrfJoWG2SELxIT9MovMLvq5 -Kh55J7H6Yn6uoFzIOX0A43HQIiNjcmVhdGVkIGJ5IEdOVVBHIHYwLjIuMTVhIChM -aW51eCm0KFRlc3Qgb25lIChwcD1kZWYpIDxvbmVAdGVzdC5ub3doZXJlLm5pbD6I -1wMFEzVFgbg8a7vmnSZuDxADD/4DAK0FELG1gICh/fxO5dXulV+S1CY9YPQwRxQN -7zYlixA7vedTCN9jutMC6fOlmMXqfivF2CMux3uz0oTJgjF/myh+jkcOsE+iUgcO -+fdMIn4oY53Pval5zuCcmqqbszP6mQMAqIYYNtE2BI6acRU8sqwIxx/GiVqELwzX -4QGp5N/4oURoZJ4Ybb8+6eEePI1vzIpLq9TO0ttQzDv9hO8WNyYEPVAoe9gOIoMY -Oh9E0W9Ru0wf4sh67KCrRvc7yrFTMwHtiN8DBRA1RYLMDvng6C5fpPQQAzlHAx4q -EZmAhoAtCfgQmlmqHIwcOa2xI/eOsqexT6eYMty8f/vsNznGhTh5gJ3PDDy8U/Lj -1KRJWPeDSZJ/6tZ/3DUd/x+KjPzVVnm1zlJSflR5AWLS7IQiyJzz7uo2dUiCs2nO -4rZcAyDaLbj/2aWwI92UQzKjWvcS49lWr2wp0QURUomqvNexKkHHDyIRhwspXwT9 -glETyn+focZKRBJTv0QtxOMVQeGaUnIuAcsDgpZuZkXBcdXgPbmj39rN+nNUW1UI -0fKsnBl5cnSgiNcDBRA1RYLaZE80um0R1tMQAwq4Av9rzmMgXgDtJy+mauJJ5FUE -E5GY3bIul1MuIbaMv6T99uWgwD9q2HsV0z9/T552cOTJ/DIkSjdusZ6+PlY8jYDK -4xTYwcglPuMH5/EsKW8zZwcwYiqnGMbmY4F70SxZW2EC/1p760rM7MrNCDAWnEle -gTvEMvutfK+K3DOu+Ba+KxU3zfgWr4z6B74QV2TvHrF0Zgu9UpXOp0FghufA6Jev -CvYhzNDM4VJV24QaF3bt16JoHQyiS9jtYcMl4IzexeeO0JjXAzVFggEAABADINyO -1leIKxvoee6oi0zkI9SCJ6dSTEH7/kETqetNArjqClenO1K0AVd+MqMajl97bg5i -UYGam55PECkkozOlscDzDF9exWY6sey44dBREQhgXLVWE4GZ1G3sy85aD+sVHgxw -lz8AAwUDILAV8w6FL7PpgiedAOHslMtqf7sh1IeNSkCjRdqvMCKgKroSLQto9Wpr -XMUv3KHmTL7TpZNad+8xJUK7R5GHUTR1OIFQMJvTodG8RU6JOaGoeTqWgs61v00f -FgwY6sYO11ckmsfQIiNjcmVhdGVkIGJ5IEdOVVBHIHYwLjIuMTVhIChMaW51eCm0 -J3Rlc3QgdHdvIChubyBwcCkgPHR3b0B0ZXN0Lm5vd2hlcmUubmlsPojfAwUTNUWC -AQ754OguX6T0EAOQsQMfXrBhe1g+hBCwQH94+08VqNGS/+Fs8s4FRmEP1Y0TuT6U -qf9QLHtfbPgKbJL1NwGgy6dn4TfWo2PRj0U8ai+YIIPZopl4hnrj+v1f94V/IbMd -3N77K0F0rJrHzL4egHi95BUVdgMgr00QAYcbbZItd/wIb2TNSu/DRlzEXezA3xRu -CIBnTdsrHMPc2B4lmCQsyx9/fmBlwrVLlaftBTvrOUa/yXf8hHwPv48avRwgClao -ChExhFMdEA9Df5ju4192VldJyJgPVz0Ze4jXAwUQNUWCsTxru+adJm4PEAOeIwMA -hzYyjVb5vlae3V3VO+5+Zsx4SVRB2NeCY74FIN5vXMoWJyt/UjmXC9CmI82PvVD3 -F8RXKUZqZC9gXcGyDYyZ87oooYc9HbQ7lhyOWsv/0dWztX9UQQrHdScQ0TbZcC2a -AvwJF7WESAGhOGssVKWaUkXZJV1sCpyyEtkUP/UJtcGha/OpPlmG6vC9XW5ymtRk -0XhFkvG4dLopbRIZgAI0CmHSloKIL5Y4JzOfc5bccNCB/tiI+3Y1JIr3AYMqaSTj -oGOI1gMFEDVFgwJkTzS6bRHW0xAD83sC93MCuEN8MCJGTZX//I7QVsg5DJ9xJRdy -5Te6MNA1Ie1o7+EJZ1MqDVF/6+HkITqGWFOPD/GYPmgdP5QALfHW6z9YddHOHH6S -kt2fC2NWTip4e+/t8iAOR/ynwocPpyHkAwCHsxTXtRlaCbIt40/3d0LFPoN4JYBV -DM+pWfNgNAWUzgMEMua2P24g4P4NZnW3fsJuYQ6Ro7jqu6oolfFkxVOYd2/KrnH5 -Mggu3D8q+gg68kzXTj62QW9vTBax5Ve0Kk+YzwM1RYJlAAAQAwCWZQsoNJJI8u1n -V+5VZaXZqZBn+uk3fp/my7l9YLQeV5S9U76Ogdw0la/YiWX2m8Aw+hO47pYswsyR -i2lu/FE/dr0o0CB53LB4EnFJPiBHrB8rm3wI142BQeJ9Dj5YU/MAAwYC/1gB0NoF -l2QhbYY83tuLg/UlIkM8CZtxtXR9vfQq0UgrVuDoeLx0/mlnWm8pmJsHR+0r8sL2 -yjl7P0RQ+FJtiaMTVHihJyhXukCO1bPM3PX8L/QsmXFzWcfmavk11xpPNdAiI2Ny -ZWF0ZWQgYnkgR05VUEcgdjAuMi4xNWEgKExpbnV4KbQsdGVzdCB0aHJlZSAocHA9 -YWJjKSA8dGhyZWVAdGVzdC5ub3doZXJlLm5pbD6I1wMFEzVFgmVkTzS6bRHW0xAD -VtEDAIWyFsZZgyT9wLmEsVbLcv2WNK/z7XweyDOV203Z3Po5lo75+c8bFkRPNcD/ -0R/nD5wbyNPACFHxe7VUm+wLHZFq5Hw8TuAegqNq0ZlgeR/vLgs54m1eOi3jbDfy -ZMJASAL/XKRGnGu3oi6SjknKsKhFOprdn7DeMW0q7YP5WtRTnnrJjIhDl0c+mi82 -Yj2OVEOLg3SaILBDZJd9muLPHQLAp95XsKZ0nHfBzlFFsr0V5BvWF4UV+U9JHxyD -uXLWyEDbiNcDBRA1RYK7PGu75p0mbg8QA3mwAvsHXEo6HotEGw0stskTnV/Dp32b -SJ8yRq2kOWfQAgaY1ZZWVRSPtHBDAJZJ/LpfWXPke90M3B72v0a9gAxOx5Vfevaa -XJAdp/ZjrVh1TE90LujbPVNeHt4a1dD0bQa9EbwC/1NTZMfb8LDHxYdsJdDdZxsx -fCDy2U7BWC1e3LLQCJOeNfSx76ICJBLq+HOpCgP2AodGgV9Rx01O3Fz8Gx3iVRgZ -bKnyS8perkS3AFayedGat/6reUI6KJtddro0SIeBxIjfAwUQNUWDEw754OguX6T0 -EAPKMgMeL8YKAj4KvkJBWNxt1W+WTjF2YBj4pYmrWisXxgmRZWEwwyDHYecH1zE2 -L12o82QGprbU8BW+GUXQVxbRt0rvlDqfGPN5HAgdjES7sK3qVZLsVeMcnhpjDDQk -pYkCIsWueCKKRwMfSiqZ1S3oBHIz3CVzbQkdMp6FbpSYXRR55CyzVdUZDb9ynXKx -QCk3Pmn0bTFsRWRFOlRe3oVpS2lM2EQFu5cWheypAt2y86ZuoevHPkcpsR0UXD12 -9IzwOV3cstGm3jCAhdGMmJkBogQ2446eEQQAtmWxQ19MJiSPMiw2EHSImXgLhy5n -8h7Kl2ixlDGbVogL5/4TaXLcGoZsypuaF4px1L1JCzkNLPKzpbteZ4cOGs3N9K0z -9S7CJJ+czkTZxXYGAukSsoTnopv+t/v8hrXZ05uPZVX2gqsLBJgQhJF2nlgxqvon -tW/PSfPU+p/yarsAoKEJI1XlRhvgf0syevson3R1kFZHA/0Vw8i11+Plhxj9mnre -dV5SqI1hsLGZnPSzz2IcFP0XFDu3HtUEG9FxZVFRQYWNCUKTP7cv5DYvmhlhc4oG -0PhwFmZFLwPPlSAFZ3jfqfkh4RiMi01yqQGE6uOgML5ZWeQqb39Ngqf/ltWlcgNK -pwVjMniMV5kfRzoupccZ+XI2owP/VWbnzl1qgl5Ab8+Dst0ORW40ENP/rcvKw5/D -k2oj4uNRclJxIuizvqsgUtPRY52Y/vj5HEXF1vfUjcZhCUWOzLjR7ecCLxB9ozRD -ifZbM82RQQ27sLI1xyt+fpT2xhMuvcQj9uohGn8rCim0VyYRNQvrZPEpyvhputrI -r5iv+Wq0KUFscGhhIFRlc3QgKGRlbW8ga2V5KSA8YWxwaGFAZXhhbXBsZS5uZXQ+ -iF0EExECABUFAjbjjp4DCwoDAxUDAgMWAgECF4AAEgkQLXJ8x2hpdzQHZUdQRwAB -ATl4AKCBLmRplv/8ZfSqep5IjqEAuaXvWwCgl6NEzT+/WewPTGcwZY+pLkycLv20 -EEFsaWNlIChkZW1vIGtleSmIXQQTEQIAFQUCNuO2qwMLCgMDFQMCAxYCAQIXgAAS -CRAtcnzHaGl3NAdlR1BHAAEBJ4wAn0x5RWtqCjklzo93B143k4zBvLftAKCFbrlx -lNCUPVsGUir9AzxvP0A3gbQnQWxmYSBUZXN0IChkZW1vIGtleSkgPGFsZmFAZXhh -bXBsZS5uZXQ+iF0EExECABUFAjbjuFgDCwoDAxUDAgMWAgECF4AAEgkQLXJ8x2hp -dzQHZUdQRwABAbfCAKCT8Guo/lZuVYtzb7qPCWa4uDyfwwCfXam5miXQfBXSZx3x -oda1yt8vyXK5AQ0ENuOPDxAEAJyN1x9X9LsjfX2Z8O9s7BzMO9OoOxFtvZw+FA0B -uDs0WVYkq1GuZ9/XiO0K30zvtZnlb7NMvBfz7xbLeYx+vKzy5xkq18+LE5dU+HKK -dRQZKrrwgCsDy8tJRO447QsiLTksCDqPMaE32OCRBF5nKrG5vih7/cmEhf2CuAn+ -2yM3AAMHA/0Z5eYysaLnAwPeqQ9vNvUyrCxUEmrvl4svG7zkkg3ZcgAbDpDQUmni -jt3gEBCoAzO3c41TU5wJaUNBEPGPWfKcTlmBEGJWjK50QQuA2diGncxIS5SDs+QV -af434a6/KFVQcCmV7K8/T2S8/nuGJ/rIlFL5XovW6A/S9mYEjh2pD4hOBBgRAgAG -BQI2448PABIJEC1yfMdoaXc0B2VHUEcAAQEgqQCfcDXmD8uNVdKg/C9vqI3JSndq -knsAnRxzVeHi/iJ73OCKtvFrHbV9GogqmQGiBDbjkGcRBAC/DCQungO2iJ7j9+9q -d2crjBU8K+AmQhs27JBkJqtAbC/xFqkHBsA1Pi8Zb6TLa/OCm2PbXFiM5x00wiEn -VKNzuGOzU8uHB6kwWtLj8+V7VOWOkSDEtnlTF6u0y9JOvs7GwDvqOM5C3QH7La+z -nNeAu1527Hj6l0XGSAzyvp+NkwCgnktU11VFpKSIdoplZBayN9OzT8sD/Awc/890 -fiSMWYNGo4+n6IHxhjBBM9lL+DAe1RtCEtwUSWNrGsIxFnDRkMxvMpaT4GusG+DP -haTddrDBSyFiCLxKDBYgMbSO6wQ9g6zWEEh1ZMTMVU/akr81DOEColXn/f3Q4sRj -xI3hu2z8tjVewAPNTuWETQ6iHHoVqdpkK4aABACfbMrnfK6TujxSs91MfKBWfYxy -w9hjM6+VV8cJJdDXiheMKzWcrVecwgYYzukmNinO//BRmQcs1wdfi5UdfHLNFDig -w96SdyZpHx+79ghD3NqDmzYakoRIoDKcZAIrAjgfl5if6vIiA4c1LjhSdcVTBsSy -ic/mkk01EgztWKY0abQtQ2hhcmxpZSBUZXN0IChkZW1vIGtleSkgPGNoYXJsaWVA -ZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjkGcDCwoDAxUDAgMWAgECF4AAEgkQQT9K -8xr9q2wHZUdQRwABAT5EAJ9fcDAXA+7n6av9/VJr9a/Sb1PnuACfVMEihQSsyol6 -FBm7vc3S73d+pIq5AQ0ENuOQghAEAKFjw1K+7qwrSngPQBUGxHPyJVdiptGVFNkA -dLgsJfDH+LwWZ90hedo0s6jKLjhiu5IKeVl2Hhhaq4LHaaDLAbnz0DNwWFqGaoSU -1spvubgX/8QYhkrTNOBbXe1DAb2FNc6Fh6pyGc45oMPA8QrUav7aj/kA2qGquKfR -MUUFYuB3AAMHA/9HTT2zrVf8WRRQCHzDhO5rqqd03/YaypezI9iN0XkTeASsryMN -wMueI4eqSzBXXtskbzVzMJETklxUUstZAmD1yl6hOk/5hwX6b3CG2zBo4n8s+vHz -zyL86aW5IPzVU/7rMGGFNRulrN8sR23ddzOlbsI101vKIRyBP7oKv5bYZohOBBgR -AgAGBQI245CCABIJEEE/SvMa/atsB2VHUEcAAQG1rQCcDbUhj2I23rC0k3kcChgO -X32YhQ4An0zwuiPl8hmr4xya2h04Ev20gjdDmQGiBDbjkc0RBACKzsZMOq0QzqW6 -inp5azEWL36qFRWn03pL7GVvDNBlUDgWMKp/VVH0lfx/CMt5ybFPnFOFBVxGqB4V -VoLKTLY2B78VwUw9lB5o/mO/kZFZzk+8f1LDym8Y5MHnpXhl5HhxAsMGbkIXm0q7 -UEJZarYwsd9y3tNd7pALNkpyPN3DywCg31W+so34RtAL5MfN1ZpRal1x9acEAIVY -TItU9OkjWM2ygJnTQXwVq7/ZtpeTyZ1E6UllLpurniSx85BDNF4FZx7fmHRbs14F -Gn7J6hJ/tjeLSNM7ias6Iv/Q0JxLyoo2cYobWKt0t6zelCENmlxR7Yb1bcWcaHGX -pbmGlhz3nnSZSPYfcjm2Z9JixVxWOk1Ih0GLPETYA/9IjW3qrsscxCnSHcw9DbPt -1oyFQZWJedWXb6sqNvlPtu9IV1XSLLK7Kiq9Q8EZbAkUsDGPp6wdGVDpby2iAe6g -kJHtwvZsrv3yaBg4TGTmAF7GrVUdBBk3V50rgsajYRIqsJW2RjAHMBTvqFgUoBso -xTx0zEjsNF0uNne91DcU2rQnRWNobyBUZXN0IChkZW1vIGtleSkgPGVjaG9AZXhh -bXBsZS5uZXQ+iF0EExECABUFAjbjpH8DCwoDAxUDAgMWAgECF4AAEgkQMYwfrvrv -bRsHZUdQRwABAWcDAKCzaFoiAm79QSmYISeiM7XMKhoHDACaA8CU1j8+20C7rNip -OHYz3KfUMhe0DkV2ZSAoZGVtbyBrZXkpiF0EExECABUFAjbjuAADCwoDAxUDAgMW -AgECF4AAEgkQMYwfrvrvbRsHZUdQRwABASDdAJ44x/SDfOdtzwgGJOsg9SBTP2nd -agCgnp5FlNmTvP6FPLHgkNx5F5BtiUa0EkVjaGVsb24gKGRlbW8ga2V5KYhdBBMR -AgAVBQI247gfAwsKAwMVAwIDFgIBAheAABIJEDGMH676720bB2VHUEcAAQFepgCe -OpUG5rVkWVJXULaeGZzqbT+2SbUAn3HmDGXzAJ6lCiYh5NrTIb8A7wIduQENBDbj -kf8QBAC0pe0mjRH/JmKL3mubSTRMKGcd77+l8psl4GtcA6iqNj3g650Q2xxgW+Qb -1iL9SeiIJP8KuEfj6vfPVKZHKkRAfsjnpbhN8zz7WQa2y8kkmqojHoGIh5wAD3NE -6ox+1D2WvnySmU1JOuAQlEDfRC5C9hSrQBkO0TUCWL2wquDv1wADBQQAl3TuGt2S -CuYSXo4R2dNZpB2ukqqHOj7nnTQu7ZVoi1OtgZYxor/w783GzLJ75PfdQMSd6T+G -byq+QgpaiBvlmWtc5rcF3ZgnxiW9n2zUlQ+M6denubJT6/Aqfn7yL9v0sr8K7kTr -PqAM0lb6DAMwBkpN8o+Z0+aIpG5/jOtnwuSITgQYEQIABgUCNuOR/wASCRAxjB+u -+u9tGwdlR1BHAAEBj5AAnRH+1me1/iHDnS5ltXysOdl24/BMAKCPThApQ7lJe8LY -r61+lXUUwr1TKZkBogQ245LREQQAubUOd0B7cFzJHF5vo5NwiMZ1JXPjyNqL2OWE -/XfaeJiB55oMmVEPmK1JF69wU7ZBpo1l4PEIWcP7WRMqvBEFl+8LnelRkSW95kwF -r3D8TRnarZy3kfiBF1t33dnkVTaZYxCDKOBdZ/ZiRvLa6gZ/KHhITfzaS7h36G2M -bAlGlj8AoKQPFsEPjByKYdx72m5/2Ju/4d4jA/oCNAKaJH7N8Y3HLis1ShhpytJP -1yC9GJjtec3ugzYSC7RKV3NJcBeCX4om3KhiDSN6YYVICf4wdqz6TAocoqPzR2t7 -Fz6+upxIgh5WGnnCs2e7uO1eXUCSXONfiDEDzRKGTQjkdvwFo+880DkiGln/qmRr -cILA568dwNnOrBio5QP/dbkpUBhqGDr2LchpkoYyQlqzbvUpXJ1xlfZim1jfrmdf -sk83dE3iBzvmT8ByIZcMoqDEHil95LmJp3qw1yVeApP/ZWR+0XiBLEF9GhcAOc5i -hH2ACSXLWiRXpyMmK2/erTvTX3QkAcqoQ1cFWCwNNCrlgycB84Hdm5GXdajp7cC0 -J0dvbGYgVGVzdCAoZGVtbyBrZXkpIDxnb2xmQGV4YW1wbGUubmV0PohdBBMRAgAV -BQI245LRAwsKAwMVAwIDFgIBAheAABIJEBaEEKSPwoLmB2VHUEcAAQEi4wCfbbaA -ruJvA5fMgp3+Bk/T0kL/f54AoI56Vqqpio01uS7SADzj47t3WQyquQENBDbjkvwQ -BAC2wan9ScDXLgCqN7CWSRM5B68vC3PCbemYsuOXZjdN8afw2LSHxZ3buRXfYxRn -JNo1pm4PGkMQ7ZpQikZZVCZa+WoIVXYXRnYAjxHhvHW0LaQPvnyFS9H5LaGf2Urs -TWVA+695zYsSaX669XFb9WbiIMGB4yUiXPvQwUL0tSd+kwADBQP8C3sKWjsPh02T -jcEy+FDxWAn4g3LfsOPw8dfawJln+0h9LA0hTebbKBJWt5OUMqjjTq/pCZ5+z+b1 -0f2WwET/xAvjQSTdJjrFX9DNNU3jhCCelEpal9oxsbNYlVd5zOU2RN4hlmj+eEOb -5oy5wy797sQpsbrgGetCTsvPotIpvbGITgQYEQIABgUCNuOS/AASCRAWhBCkj8KC -5gdlR1BHAAEB9+wAoInApOl706hL9+EV1UpIX/hHAxzjAJ95K6j3OWXkiRmu0X0X -FYZuULXL8pkBogQ245SxEQQAyG4mRUQZagjDgl0xAnaSbLCQ5wJqYq/snwCl+IbD -lXcoHqXQNO9QJrPKwKQAUv3Nvk7mqZWnfMPoskLOASrs6nkCv2Fo9Aw6smNizO6i -W7xXepwvxjho4hLnE00oGPCDhUnAU05LO2pTBoxwHVs0o6vtaaViXk0s6dOFCoVd -f9MAoLjiGlK/3DFWoUrqIiuE3aLfgkddBACrp1snJ1BtiGhmKjt7An6Qoc5LVnU4 -1J/REiQIyitUFAvPX+fiqzDyE3VD8qX/vvTLpgZCYvvEdBlSfM8IcCn1/Qh4aw9J -HzuvKQg8WclvnQ8zq/7RV9J7h/aS/KIhDJIpGhi6YfjfjdSKfLYYfr3S4TVK9xD0 -Za3AH7/lrTqW8gP/fpKWu8fJyJ9kqHyYrI/j4ykt5QKBj3tHjqCv7FQb4FY8txnN -3fLzBtva/tlkSKRsLobixjZUGF+uQR1dTCv042LxZ6aEUqrUytxqUc05pCSAvEZV -8bX2H/5+ulSwdxKEzs1h2NvSTAiZ54zzKGjHNmEitdAaPD/9u5xdAiqPFxG0KUlu -ZGlhIFRlc3QgKGRlbW8ga2V5KSA8aW5kaWFAZXhhbXBsZS5uZXQ+iF0EExECABUF -AjbjlLEDCwoDAxUDAgMWAgECF4AAEgkQH+j8bwQllncHZUdQRwABAVpYAKCVZ7Df -K+i/YZGyEu18DnWq0ixligCghGwDoMGgLnenSjyShMZ+1Ecekia5AQ0ENuOVEhAE -AIMMgk/e8lsV/KEkd4/jNK4yFj5iy/Faon800I3GUzETuQA2AT3getR+GuV4pbZW -E/80b9hnNW50UJGiP1+SXfVtY5vT8p/gNFwn5d0O/pq3bpgFRJmoawTzx8SFDwCV -PHEcwOHE2j5LvfrvRBOyKU32tr976ri+Uowt0+92LuA7AAMFA/0Yo9dDqhjR2UoN -cYfEZwWhRHaaJenP3z3QbzjJkASb5H84xCTEpv0dqEtVTJUoIo8Lh5VjbiCwok4Q -PLVSbQFeHqTKb7N96PjevkZ1Co6OrLCNOcPRvXxgCwSGbuuLMkQJEutnXLu0DOKq -uY94KXXh79La7lTgjReE/1Wzbgc1+ohOBBgRAgAGBQI245USABIJEB/o/G8EJZZ3 -B2VHUEcAAQEJeACgjmiKaxmzxkqYtvmw8HgBnOeALLMAn2iD2ym3cRhcAH3leZ/O -qAkFG/ThmQGiBDbjlSURBACcp0BogujMnThXpn4UjBARj9oXgQWskkhz657AXu6R -mX/u5RmpLGqbNmNuqKDIwUbJslIxrpOnA3QEobkIl7ThH+ZUIhGzPUnHlhd7M3dQ -Ww1U0TfpHyXx3FYb7CCPabrSC7hWWh1ylUxz+RGJJSApR+D/GY+dF7dIllKUbaUG -bwCg1z+vkNbzqibcwdYrwCjKG9VeFa8D/A5yPHqB9NMp+3OlAGE4XRTR8LeelALp -u+MuNMGFCMLdZfmt/Amoyau51FsQ7WwWrNM5A+1v3Fq0x5WpNw6Lr7HbN9d6zidN -+L0uCrXPweET8ueS3DFnHI945epe703TbcjJBO/uYLn0LXExmTg846/1ZlQbPgLz -mzb/2JMkJ+QzA/4xFbRL2YeaKyu4JjpMNUVzXYogUwg9KZZq/qBbpsIAD7Agd+Zx -LJHoweItXaC0nS9C6qDJZ95OJrE+h/Tt2D2lmxXseTVlSESaWh45x9mbC0eRGFYY -RsSx3z0hYwMmXA0ntj0lndC8ru8HjZtBW/KF0VB0RcfSyW+W+yAq0Jxo5rQnS2ls -byBUZXN0IChkZW1vIGtleSkgPGtpbG9AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbj -lSUDCwoDAxUDAgMWAgECF4AAEgkQrRsPrUPC0McHZUdQRwABAdUSAJ9ZMVrsRsAk -tfouxadXBc82Qh8nCwCcCavkRu7sfbEBJqKdldpinYwWZpK5AQ0ENuOVSBAEALmZ -YtP72G7OodR4RfR270RxTHj40PfUpPIf3U8ezyO3kqjB12IdD2YIXIZW6zEj53ps -X8DGya5nSvVjdFofQSVHtsnB/H7VHBkaOQnREoInHs4helYOD0M/RZcbRIb65e6v -Eesuzvo9N0ACSlBsAXbeeNKGfGGCog74GVGcZ6HnAAMHA/9W9n2MwJ7lq0GV4V0E -OHDVcTAVRSh0nB9uKBVW7hFi4DP7XYBfgj8Nlbc22vMkkdSvNFUoLEH7Op9sMglX -fiCPJSh02U/6XyAhXDyZRyrOIHviTZ9SHMQQIqtEETVuYRkzvSnSfDBVq1p9gW6e -ZN9q6AM7gmoKInpRaODFRWU7DYhOBBgRAgAGBQI245VIABIJEK0bD61DwtDHB2VH -UEcAAQGO/QCfaGt8NeCm0zbssmOrXZ6v9zFk8xEAnj3SpjLTyqemniHSJ9KEzIKJ -CdiDmQGiBDbjouIRBACKncc4Ueec7dWaVARy2SmNVufeSenYs4AsIPP0v59jEl7J -I0rb+4JbIJoAzW/hcm26GS/UbbpQwig8/PgMUV5QfBST4CEOlf7/x2a4HKk9tDV4 -An7q2aNr1beW+twxfUGWWV5I0o1b/iKVk/LiQRiaMr8pJXY266m6/2Pn9LmDtwCg -+Iqfx8gsK2PZCWv87uEKAOLzHXsD/1eRxLqCt1hT98gdDLykRTlI3kMq6EK3I+z/ -8pDIMDuPIJq1eM68YdFZr8s7i1ye1QpDltPYHgWnUC733ujAKANdyybm3HrA3TSB -jEAhNfcu8nkrVorvASQUDCLJatWRWJTUVrPH+GXIXMA/Oi6LDsgNDOJanwzzvDCC -m8hWQqW9A/4xYAZ4NVFrQq8gtQPJWuMIfSFSvpZWNgQgYZntiXSUGYOVs28T/87R -oRx02tsVDw2PA8z68q/XRuM9NdetxbUXQHB9eszFLi3W1idsXhd/C4SyiTgEFXG8 -Y8s94Eadgk1PAYHN6Gd3SY7jmevqYGVLmBp7qfj5Y9XSM5SE0Th+fLQpQnJhdm8g -VGVzdCAoZGVtbyBrZXkpIDxicmF2b0BleGFtcGxlLm5ldD6IXQQTEQIAFQUCNuOi -4gMLCgMDFQMCAxYCAQIXgAASCRD+GAsdqeOwsgdlR1BHAAEB+u4AniJTgzmzXGxm -JdrTAudfgUEGX1puAJ9+U2nDISnooSEoI9bA9Eb1YlzSqLQOQm9iIChkZW1vIGtl -eSmIXQQTEQIAFQUCNuO3OwMLCgMDFQMCAxYCAQIXgAASCRD+GAsdqeOwsgdlR1BH -AAEBGuEAoIrcivM2owTqgDdGWU6vHzs4IhGCAJ9WRH41/o3n2VLmPuMxc66Tv319 -DrkBDQQ246MHEAQAlUnV8VFpc/NRY6h4EeG9RLZoZlvPQpqbB3ypUsJWLwbWwf8u -0xSH7wK+GRW6bqnsOib7YyBGaF76JU1sB1TxBZLhtCwGtN6JWmKcwumQQ7i5G9PU -bpAg+M3WOscGwDEbDs2YL+fey2V7Tiyy55jsk6bI0Qy87VrLjYJZua33zk8AAwcD -/0slWbxRHRFZ+f3UE6e3gLV3a22RDN+/XLQiduut0W02XeeZSAXr9X05ykJLw02N -nufMiEOBPjc6/faoPQsn+ntzoRK01KhATobrAYHuP+xOS6yFTL6OgBVPaoJ9EoLJ -7v8MNrcVcN1xI6i/B4JfuEP+e2EbyTnvqtvWHvSy/HmoiE4EGBECAAYFAjbjowcA -EgkQ/hgLHanjsLIHZUdQRwABATK5AJ9pek7H6yt3ZHAJ+7nn7sGmxYxb5ACg1INF -N4AMzqEUjbZ51KTVdAvyKlSZAaIENuOjhxEEAN5nO1c81jCmgh/oF+p6kiZmqFV3 -ape5kEmcS/BoWgCXt6vjaldctmFYi7v+BY4N9zI3GxQqAxt5D6dY7aN1xlC236CZ -EAaXUXktvGw/ppHDjdbs8CRuZiA9jm1j92GAUY/mm6hX2aGKOkVwr9yN6DrA2CaO -4SwK/wEXkVfj+nazAKDCaBzHzwSkkXf8QOtOTj/xevpnzwQAv30laCeXTDZM2I/1 -Pdzma1V1xizfae0kfzZOJBDQtHQDvNFjmu6iM1kL0uxOG3krr0AlqSsMD8W7mavb -FigUlxbhvuul4pTL/BiJ946FhjlPY0Ni9pmdAldno7yUYsWADEKadkQ3ghEVqEqz -+ACYbzp3p8K+5KuiFJm9D4uyvToEAIVPi2N+4voxnRWGwKXF4E+fLYAzXT5sMMzl -46Xk4Ms303F/5JG7kB0iiPPY6oP0l3nlahulRcbNMj7SDbfrfoi4m4ftUYIX3acX -CSN0gNuVGipg8CwlGQyILgWRFp6oXQOmAlpxhIGcd1jdh3sj5y+CQrugGPNOJT9m -zmFkB4rxtClEZWx0YSBUZXN0IChkZW1vIGtleSkgPGRlbHRhQGV4YW1wbGUubmV0 -PohdBBMRAgAVBQI246OHAwsKAwMVAwIDFgIBAheAABIJEOup8kDrncnmB2VHUEcA -AQGuJgCgl0HAxcZVFMWV/DW7heKYJE9UVE0An1YVfKzHS6BZohosne3I1lAdagBG -uQENBDbjo6oQBACPtZ1o4mPMk2zYbyu+sNm8P+5oAtD0+129gCn8OunvEwflPrb4 -opOUp07ezwhAE+K4Whwk2Kvmy3+ebxeX6Bw5k6+2vjlz9yXnh8Y7WA6MFk5+BuR0 -FUr8szC5BYh5srioJmcA6UMtg0ZVSC4YucRAFJ+eGGSCHRYDSSq3t9i+lwADBQP/ -dw4So+Ux1h4ucYQbjA/G3JUhyHAY6/RhFblqlvPZ907ui2PUAVQ3lbMXDQDn5YfN -rU4hSGDnRlyjoefArHoX4ttnlo5zfsQC9oWA+4zEF+RpZhqAKh/eMEXQJtNZRdX8 -Pn90WYh64ZO5Qw2wZUf45IxbaEE3/v5okrksscv6HOmITgQYEQIABgUCNuOjqgAS -CRDrqfJA653J5gdlR1BHAAEBc00AoJq+Jk/8DzdqaYOce+RN3F5+qgdvAJ9oTv4Y -CD5H/60ksnQO9mWXPzFjOpkBogQ246UmEQQA3Vs5XdZcg1g6hj0sxjrHoV8k0mtK -Tn1Uy3JKSaQ6RK3J/I0vHCq15FVKMCO0pWYT0ZmCPuaahmhuRWeVSXdU3ylooXOz -viQx6Ct8mpjp4ejhUBT2VBdflpQBohVy3Pljg824DkjMv/MlwOp9M3vr93reZ/Ss -4m97Axo8OQzJomMAoJlMJ6H6rJB1b9UurQ4NPJlwCyijBACFRsn/Yo9wczW9H1WB -lDi1NO56kN0aTUD2irT0KQaG0ZJ0P2Unc7ogC3AgfkOuuH9XChgPjoLZtC/39cVJ -ikVt60/ZczLXAsupHLnQiNjh5v4DnD8yqo4+aJ6Q/OH4EeAXW7HoU/Prq5sRYiv2 -xRSOngtS+XnQUHES7O0xdo2N0gQAnV8vch4Oog0yYcrL0e1Li1hP9bPcrIq4WYD2 -9L8iBcB30czPegGCD6S2a/475Kw2sE8WBnxiGa4+1Mhnj7u0QnhUVVV+eQenrzb9 -3wKm5sENRh01+1hwjXQJD9O8k8Wf8J2bnTwM0MEZBH2d/U3XHGzoR3x72790TUNF -cW1rUFK0LUZveHRyb3QgVGVzdCAoZGVtbyBrZXkpIDxmb3h0cm90QGV4YW1wbGUu -bmV0PohdBBMRAgAVBQI246UmAwsKAwMVAwIDFgIBAheAABIJENS/V/NzcuJDB2VH -UEcAAQF3LQCfZhlov9Ux6LofeSt5g2hVijDdX0gAnRc7adixQ2hpprv4vNoKvmum -F/D4uQENBDbjpVAQBADfVCPYwZ59MKgXTH4P71QzFnpG4E/MjqDNfW3NxQ9ZjLfw -0ir6U1gGDuEsWRR+fS5OwCbfeHZDzPj8MZPuOZBamgiDvI1OvrrzUv+BijkWGEL6 -oRFnWI8zJ8zDAPuuvP1u2FQZOoKFXaHo2I9Q8zuJz8P2vEkgJfLx2yiPR1Dp2wAD -BQP/SCCKZBNQIaY0cfKmiv8ZjRcAAvhXLyMCwLQUfVRqoNVOtMMfWpYtGdL27ESw -4kgZIsxJ3ELQVkRiriMKbsJiNM4dMe+9gNuGz1CG9b2vhUPZ59sREVIRgyIfr0BJ -AsYOn87mQ5lOBA6+XmjHO+ys4xpEVJZyfrq5QAw5GYcrPWCITgQYEQIABgUCNuOl -UAASCRDUv1fzc3LiQwdlR1BHAAEBjvkAoJVm6lRsxer3LDTczfhFL1hP0zMpAJ9S -AV34Wfz3GpTg7CD8xDNiUut5SZkBogQ246XaEQQAp44vakh1n7NC16HF0v2X+4ME -VJO432stvwOAuLDxn2PxTkIQf8zfxbMfWccoqVkqMZVliLKFF8AbzfC8edPzeWr4 -B3SWBplNHjPqet3lWI6Uc+V+qjhE9k/M9764XsR8OXv3awl6tcYBqwuiyYqfEoDI -nJWOHt5lyNNL+FSE73MAoNXIscn+BCUxiTy8Tldgvs/Dh3bzA/9WwpWSOXGxelys -JAigp4NeAo1W/0v7Q95uynOvZY5qHyIE3VA6Ru17EgoJtv2aa+ISclTQUXHkwjDi -aKm9jgSkJofcxwbAmkLNaZ3MgPxnqghJTIqy4/s9eOYBJuiBXoirLab/ZEO19siV -vCi19uI5P1Ovcg9sf60cBkHIxHK/EgP9E33RY49Kk4PGv0Af1u2Z4kPQF82333XX -r6p3C9atOh9xuQGDO8Hfi8ssNowpUjKKfHPaVjILtpKkDe7ONm+g+8+tAkUsTR3H -sNKRRO1ZtAYHJFpunKtdh0pnOwVctv4tJNbAXexAtrHQLhxhPs4s+XGMNWr8DSOD -O1plVZrfshi0KUhvdGVsIFRlc3QgKGRlbW8ga2V5KSA8aG90ZWxAZXhhbXBsZS5u -ZXQ+iF0EExECABUFAjbjpdoDCwoDAxUDAgMWAgECF4AAEgkQE9uWVTTG4/EHZUdQ -RwABAezUAKDIVCu3fJltReOUKcLaW5/xHUrqjQCfePhlWOhq7TGwPMq2R3g/M0gH -na65AQ0ENuOmHRAEAM6TulLgllqT/bqeRlYSz6EggX0iAPSVpuQKev4Y0OYYmuwn -EvBONT42hpej5IeZY9qpElAWvPdkl8kDGKjKhKv4e/gVu/p+tkgkTLWDh0WGTwOI -b7NHe485xkJTLJbce6mpqFTT9FxfsLNcBy48kJd6jJ5KwEPJQCT/o4Oz+R6vAAMH -A/wOtakC0V7Eha+yzAZ2lEkdKOvuPxwnYfLfppwHkAQwJJ3uQ0z4sKs6rI6GHpF+ -iSu8JPpm7CU3f2cOeSZKvcVZupxFKPySGze3D5TKnwi2qEvrbW8WfXzQjt1kzXVs -QK/5hmWYgX8vck3MVH6Oak4NH31suNAjR2lSpPoiHJLRs4hOBBgRAgAGBQI246Yd -ABIJEBPbllU0xuPxB2VHUEcAAQEmaACfU+XRhr/UgvgCfMlOthY327vlI30AoJyp -WeGLup2DqouZIGkY8bmpDrz9mQGiBDbjp/8RBACXrm5v2sQpLtexfA2S8a2PUruC -eqXYfVsnkYX1sYJaFaYHxYW2wDL1dR4LdZuty5YWBOxu1N9dnkjuPsdIbq6R/phy -6xv5sDUihP4YBAZakV5ahd7XrBdkWXSkRzaJSfH1OG2hAXR87liVu8ck8RDeS+ip -x1vnZY45864IAnFzqwCg2qjnDRjGAn2OSPsnhyZH44VQQpcD/A7SOu9gTt6Jl4VS -MY2JGi3HOFPOHnevG3Pb8NYbcP4gEU63iqrHGndYJI07lKcFlZRbnSEOSFPFLuNK -ax88GYKKeZDoQXkVoU/ItAGrS4rCExpZ+Jx2tBL2zJcWU+7NDmM5LeRUDE6a0N3s -IxMLzz3Z2PTarMATjpA01Qj3WRlcA/48g1+gnyFXbO+UZn21WWj4uCyXUE6/G8SC -ZhXXiDJOYxaBrmw2rtN0x1aLwXPRXLuwjhL5Ewn3qszCzaJPNYuLaMY7jiK2ha20 -LCqYYmaVJa6tGy9iFIGC80ItcUYZpCfmdw7W2oqdZIN/rblScCKmyBbw/gCB3mol -mLBd8nrseLQrSnVsaWV0IFRlc3QgKGRlbW8ga2V5KSA8anVsaWV0QGV4YW1wbGUu -bmV0PohdBBMRAgAVBQI246f/AwsKAwMVAwIDFgIBAheAABIJEAyCDHHSaZMTB2VH -UEcAAQFA9gCgpEHwTLc3LpNopoagvYY0VATAzUwAnRZuUrRJxIpubUE37aF8OaYp -GSC9uQENBDbjqCoQBACR2VIlh9OJkf8KR9Xy2eEjogPP5KCJkpyd4QGc76EAmi20 -BEYCiN1tRGU4h5mpEKAql1NcErsx0cDPhEoWcABc8MFmADmr4KiqfnzS3878AoZv -yQqf2fnbP2ULwDkqcdpECw4pXI9MhTm+roUuaxaYwHnmLPzboOT2QyFXuaZ1BwAE -DQQAjwmrcmep/QeqppfsJm40ocmBqDXhtNoHDSeJkrQpIHoUGnOK0SjKy3kkE8KX -RrJATDQefiOFkCpxnJsj/+kLUI1AEE7jtVSLTLVRWMTG1o2aZbG6DOTNYcfHhabJ -awJDAY3gH2uJTCziDd2ALTTuX5qicrOPlASjVeKIw1MUWY+ITgQYEQIABgUCNuOo -KgASCRAMggxx0mmTEwdlR1BHAAEBj64AoL6wmTv08Y6txelPb8XUKpayw4FyAJ4n -eVj62ZIfdX94DPkF00H5qvVeEZkBogQ246jdEQQAwVpm5pgcsPrtSUwIscY+TV0V -0Cfcy7ZMUUNRh8S0D8kM6I1lpw+JBJnvMr7BV7rpWz1/M2TJ5eqnAvMLfm+RPHQr -Wbr0C970udchnvTO+lUQv9R4K4hNGKhzE2CU+Cfh3In7ZXRxYnfo0ZxmaS8FbS8Y -i2lgJukgYvNhU5+JVRsAoLY3N7v0jLD4MpT0cjf0Hh/PzmeTA/0dshv3PmReJFnI -Jpc4ycUFDdsBmHg6DllDF0vJn+shfgy7cMaOqDpS2ix1U0evqh9lYc9c2qpNSK+h -SY5LlBrx21RbdgZry9ukrU4yeMwuFBUlmD96i732z04U/kaA+HmvlXD8RhBnqrNL -piJierNK3ktyiUvb4B7RqNdSLOJz9QP/RM1e0JF+RLhJ5VKRldqtvWhmMd0aXDoQ -2IsaIDR7lvivSsHJbgRBAZk++DcMVcyOqnSVVWZ+ZcU+CAuRtM/5InX9UZIL/BKo -+QyIpIJ6dGrAfBYh0rG/t/XeHJ5NldHs/y5pJ11JdpqSqZP32/ql1k6jw2xVBPHc -/M8qkRVyI8G0J0xpbWEgVGVzdCAoZGVtbyBrZXkpIDxsaW1hQGV4YW1wbGUubmV0 -PohdBBMRAgAVBQI246jdAwsKAwMVAwIDFgIBAheAABIJEDfKtR+3kQP4B2VHUEcA -AQGKXACgkZY9/w96yK2Oiq/MUs/A74SzJ2MAniQ2eSHT5CQ4G8PPvYfPZueNI9PT -uQENBDbjqPUQBACn8JyfkTPFcgaWMpUpnk+nTEkDe4GhAG9fO7alTgdT6+aDCdfX -fXfH7gGwdURvDv6V/KEqcMPRNLAgAeP/F4T6OtoJNTxfWLB7j14DJNpYXjBPJPN1 -kpD2at8GcWB1aVGMsAtxMwlo4TZlqyfzCAAQeCLhBbIE9LWKX5oUTqiLOwADBgP9 -Gm8md+/xWp9sLE5i3uZ4t9Muu9w+UY3Ke/WcSA2CNthEYhHNtcMPP6PBwtz0x425 -mC1pe9RuxDyzRfV0/q+rjdWZBNA+VTVNDHXSj5hifvem3KFvA6TIgMabJ/q4WE7T -4Hn8xjQpEsLGjSXAzG9WRg13qTzTilIk+rC6xYGbZHSITgQYEQIABgUCNuOo9QAS -CRA3yrUft5ED+AdlR1BHAAEB/m8An11Axzacylwq4fbzHAqXyvsw/enKAJ9YcYoU -dYgORS3xF8cAH2B5q4RBIpkBogQ246pkEQQAotQXkaoExYlC0GzW3VKn40g4a4wu -Ak6Eg1sxTq2TaPN5S3qig135zw/RN7GxtIRPCGtTie2m8ghJvsjxPCFyV53tuLko -IAEk7PPsXD5h3GjliObUNAfv6AS0/HefgCNlR9EA3SepwWLMOlFg+pVo3VBiIZaf -3I8Xem5tCFWfzPMAoKnHUtSVCXZ7m3VgmGaibarLfwR5A/4gHjkUF8N/koq3JLrh -qVDS8dgiyxSnzTo9CivD9k66iKxxRCP9Z5ni+fusJ27rS5HUS4ekanufS3uKASAA -5zEOOvEmamBJ0Pv1X6gkAUsBOjaayPUiSVW8l4jtmwibI9yEhTWWqf8a+kBqb034 -WIgHUpQwWpMnNzrNSfVCpqDXDQQAiJEc9hFbyiN31SHgR3dfR1oCcKXIxYvza3Zu -P9slGaG6lCfhpUnkPSkUH2LNOIkRZyIemqIx2yL/MTFhggNLVm73j5YVs0jHIwV8 -esnl9RC0CotvsTkuuXFk41SetHCyGpHhfZOZbabPVainnjZ5RDVRangavdWUfqCK -zBjQKdC0J01pa2UgVGVzdCAoZGVtbyBrZXkpIDxtaWtlQGV4YW1wbGUubmV0Pohd -BBMRAgAVBQI246pkAwsKAwMVAwIDFgIBAheAABIJEL55SFK+XPiGB2VHUEcAAQHx -IwCbBHwywMR+PbPZX9J6pReLXH5aa/8AniSgj+olcL4RiHQrvg273+s/P7COtBJN -YWxsb3J5IChkZW1vIGtleSmIXQQTEQIAFQUCNuO3twMLCgMDFQMCAxYCAQIXgAAS -CRC+eUhSvlz4hgdlR1BHAAEBmdUAoKhrc+z524neflMpRwJ+NG8KVxOxAJsFZqm7 -bBtYllrdcTqNqMk49LfBObkBDQQ246p+EAQApnvWjY5rMvw9Ly8xFL49pGjAYFb9 -zFijvgG4tMirI3T9EBLflKLJ8m4KWoRoT2eNmy/JGLHyZjveaVh8TerDV+uxZkEG -vv702nz8NOElQTjHWHoy0n6poci6FxhfJd1bnOjDK2mZEufEQNSn2PhA46gjCLRT -APuwLpitSSL5ubsAAwYD/ij9KRO69/Jx3+W9DZQxWIQBiKnYHVr1us2WpdpTV4jp -CqJOCOgB/hlBmCY1C1/tpsAj1A3ZZamJRWVZoNokkReItZLXfGacprGbmmjcg89g -FM5V3nEUNCU/mm2BQWp58h4NOCv60dGr5GAqHDxAStPk388zbxEdyFs57CPQ4ZJt -iE4EGBECAAYFAjbjqn4AEgkQvnlIUr5c+IYHZUdQRwABAZEyAJ91yirChpNTus0f -QFZphR8KtDpOcgCeI37JBoFvBkcxtJoNMFGd2MuCWwqZAaIENuOq4xEEAK14podn -ulwztC6PwRzxLHR8ne7Q10uyjnGf0STgVYwsG7qPDtv/kqMHZa1c5lJYoc7N5N9Q -DHv00womsP2Nlb/SQQAVV5mnBkXWXx8GxEQtH1zEBqMTdG8WSAJgCFewXUmej6qJ -TlM29p0ZThLOY/i86eeOshZPLzea1mLCgUhzAKCBppoKUTxDjU3Ih9W2NLd/42bz -HQP+Jwf27Aze+kHZBXb0ggGprOBoWvu8GiiAWgCWVoJBs8uLIdfUyTeQRmDnF7CY -NL+1TisaqPtRwv06VnHUgIPxynzTI1h+gjsrlczqxg4yZ8k5EY4Syoy2hhujeWW4 -OAOSDboNk3KdR4UdlGshbPZwqpO5oHd3DT2bywk26zemgS0D/1DUoOyMo+Lz7aRT -MmgrdXrVCCVcBUOV/MroHko4RnoZH+Bf0zm7LIuNETJsVJI0+W8tHXX6ZXgZHkBy -tVA6YTRCkXKjUyv64OxurCTMRG9GrWvmk7KozlY9eGVdrmijidrV8ERfvogTMrrE -hUbTsac2dpj52U+Cwurgjz4DbRkbtC9Ob3ZlbWJlciBUZXN0IChkZW1vIGtleSkg -PG5vdmVtYmVyQGV4YW1wbGUubmV0PohdBBMRAgAVBQI246rjAwsKAwMVAwIDFgIB -AheAABIJECWwD9QwzsaEB2VHUEcAAQGY2ACePRDTHz8CtVNREhGEEuWLbN0kXAIA -nRuuRt2VtHZ4Z40AIX/75PhLXjHyuQENBDbjqxwQBADhnHlYNzwuhbYK2a56H6Ic -1p7ouhVQc3motQ2eTDCpnTev0DL9Xnh6DDm993234cAOdZ/pD7oWqa+kKk88etkR -gP4CtZu741Njn2MUjuuRjf60lFzf5BPN40ex7seDKHEV2fv/J4Ki+yQI8NS2XScj -p4iaXkb63JDzQv2ymrmu+wADBQP/eVYwIySAFP4DjMLW6k4FfnJh3udgGtQiRGpV -fPMihvOp56h7i+McVE02ZY8o22ypXiQ/wIe0dQcQYUhA8vFrk7qJxFR1cU3C/WIo -OKWfzs2GX+X5JdXizWki2/F2TE9CWz9Nm//zjKQK9vZXGoGtaNUbVr65VMiGDk5t -kXE8ZH+ITgQYEQIABgUCNuOrHAASCRAlsA/UMM7GhAdlR1BHAAEBIOcAnjt0vZDn -9+3cTNpCuV1ZKIu2t410AJ0Y3CnFBUFBOKk6zkOJnaArwVN3ZZkBogQ246tbEQQA -lWieyQhDso2ZnD2wb+gq6aqk1rRUhcwdBwCTbiE1aLAsnuMl8nLH4fvhaTz2V/Ae -joL00e28duA5or9JiBfmVblrpTAIGWsu0AU6uEQsWgZwRdso3NH/KfH8Z5lxwJtk -Z/hlAiEHohmGoD38mJNsgnm63RXadUH76irO6McvWlcAoONeH7i25AcrMol4O7BZ -wqGq25ibA/9IRhK7AFhfgaRrDTz84PaIssxp1dWKalRruMJYGQK2LDuEl53Q+d1r -nYBPliPbjWr/9Gkjx3K4B0CfWWQC0sUl77bNRFqr8FXkjRZcvkCoxxHG7PIFG77r -Ld2SiQ+eS+dp5QijuuMC8skkvQuuxS6eIk0g+jjGlNhjuu97Ya6xeQP/Zxek37p8 -P1u9TTmN7nPtlzGXGrfKVi9DtJ31E805ruXFqTuoFfcOBRrtfY+DOebX8RxIwQV/ -TEmyxwoXdmkv03EYwD6AJSmx3WuVi5/revcH9nfSEHDy7sFC8CBp4aavAFRQNrho -mSB9lSm5clGLZiD4nljF1EFABwQFch7HhlO0KU9zY2FyIFRlc3QgKGRlbW8ga2V5 -KSA8b3NjYXJAZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjq1sDCwoDAxUDAgMWAgEC -F4AAEgkQX2NWum2XMqwHZUdQRwABAbAvAJsFPpRP6U1YyH+PEW7+bkPLaozCkwCb -B48G7tRKLpNYppdhFIvbLLAlHQe5AQ0ENuOrjhAEAJ0LVdE8z0IwWuBVS+KhTtJK -F98ueOBYFneGps5iuyC1d+5B2/qUCLGc092eT+TiaMvzDWmpuNSZ+ZumlUPHOyKJ -RCUlq3MYN9TWANzuSydekX+/OCFu5zLwc07RIeLe4z8ZcLnviJnWjFr8DXh8qcJV -hPVOGpRrW6wLlhBcebgjAAMFA/9/gtmA3d1sviMupccM2kAgSOJNspfEMoc6cCh/ -//hITSalo1Ucu7efEjnsK1d9IjaQxBKb/emqlMrNoGUz8JswAlRqeGaUs8BENwn+ -FBwO0GwXmcUbvN8t97RIHCCwzUfEv3rxW9rtaxtilJr3z7cdIO7L1XCmEWnuLgdu -cJtIrohOBBgRAgAGBQI246uOABIJEF9jVrptlzKsB2VHUEcAAQEN4QCdHqwqMSra -XNfOIi5KeZKV0GpAxh4AnitllwOYEzlC37ZWnV2Z/LTaFzOgmQGiBDbjrEMRBACE -EZiYbCZ4jYv20X3/2Bq2fWhVrfNRvd1vFoVedaqvp7VB4FDWOeWMqLOFyzmtrUvi -vMz+l9eRXrFQT2CEGuQSAtdJgLC3yfta25xiT7jQQNlNjKBGkcaPybV0P/+Y4k0Z -WMCw0Zwc7mjAj3bIq73rviQcOd8rUcI8Hu5vw9Tz7wCgqdnY9RbQ47m0ze5AhdKN -isz8BNMD+wYpkMV8j8Esxqi2h10hAbIfODkE8TyPfAV4KtNfefwNQdf6T7N+enri -paqHn1Ex2IW44jGG42U/gOo7rnX+wNlHMtNxvBw2eJNX9b5s649uPusoBgXMU1a9 -AWsHogtQ8Bty40KCdXLhcUUPAWCQxiMD61FuSXZZ81tmyVn3clzqA/9Eu4hFTfbc -ZEiopXTnj9WHAwg/DDN4bxfZFHPtYW5oq/EjmfyGCQMkDfo/pmFrC7irWfxfaaog -TU1x9o1gk6pXTg/2WMR1SQAEZ5IlRusnJDC7MR4tizzwSvMWnJNMvdpinu82v+34 -VYAkUrOzP681G81IciJx0ssa9kmG/vJW7rQnUGFwYSB0ZXN0IChkZW1vIGtleSkg -PHBhcGFAZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjrEMDCwoDAxUDAgMWAgECF4AA -EgkQXRXgHT/xMgYHZUdQRwABAQb6AJsENGQmK4nUrwcbtZ7+av5GDQ2T4wCfYJaV -2rBtTR9aWTRQfZOQoIkNF8+5AQ0ENuOscRAEAN5hO+fEhqW2pX71oSUqW/TRHWSb -ybNc5brQ1tzgTbheHiG/LQJ1lHjtZoZQsyW3H/efEuNARwryo4IjvK0nmiQsqZUR -1795XTIbo/waPN08QujC26uWbL1pYL5yQarwbKOoyAst4jgE1NpZVc/r1+WUp7Nu -EapicVjvFNzkiVCLAAMGBACWQJYr+h0ozr7JQ/BqI8vTKuVXb+DIBQjuSzN7Lvai -IqMqb9ZdfNNmZ1Atvklo2Ce2VMyliQzVSTZuHJQbfrDTBXBf+Q+AINiHdZEAodzB -vDv6p7vsTnoP+A2bS8l6xrWObKt3Ky9+GUDkqW3WuagcUKogQgEb/FKec+GegwSg -UYhOBBgRAgAGBQI246xxABIJEF0V4B0/8TIGB2VHUEcAAQGThwCfUj+Oa7sVKCCW -H1o+ZVgDDsdZAwAAn08A89d+q3DNrojy20Y8tg28QCYBmQGiBDbjrNERBACBwiP8 -Sjw+siERrEpyNz101v3/QFncHEGTvH1rscqbqjT+9x8sfZcWMXEHgN19747U8L0o -1SoiLoZNp8ZvKpLjteyc4mzme+yuCZWlRTMB3unR3Fxza0mh3CGQfga04/iLg/1c -GvGeBCtZDSO7ffcQ8XrAtaLuqRXIYQ0J+y+S0wCgpiAz5diH1RB7v8dfQaIKeTcT -FWcD/ivIHF3IGKGPTaLqzy8B7maVOvC/zm6Ci5IH3lcRfwY9+9pYhb9OlRZDpruj -xjNT+Qg9rtjMRNhfx78VWvZl3fccB94tQ2nc5LQ28RtgmUYN9bv9fuotW/WjlYKM -IdSErwMJ/0DH1vjPsJtEem3FIThTv00II6xdCw5tXbyqUawVA/4ghoKHt1OoAPD+ -cGZ+5fF6k8pdLpd2LS2jv0t9C2v5NS0k4RUYhuqpAGyARIWJPmpHRbuqE6eXjtMh -DI9Ce39X33hDDIAa0iC0zmpgVFbvSDUWTINFfns/NMy5TYGNUjqYeRpSQtou6NtF -eJAWbwhcnit/b3samkq5KC81yvtGarQrUXVlYmVjIFRlc3QgKGRlbW8ga2V5KSA8 -cXVlYmVjQGV4YW1wbGUubmV0PohdBBMRAgAVBQI246zRAwsKAwMVAwIDFgIBAheA -ABIJEBxn7BM8ZhyEB2VHUEcAAQHRuACffM0sr0N0bfmPgFX2sMhKKLBRuSsAoJjM -o+EWIUZVylgjzkQcQHwjmDLVuQENBDbjrOQQBACRouE/462OQbUUzNKbAJ3kMrc8 -xYB+Pi4oFFwAG9EAwDpMhjX1h63xySEuwNzXPaTFgHTo1oEim2Mq862tEkO+f0pC -Ofv0uXr9haZIvh2KO3DYFV52wiayGO5OAwDLp6jyfSQlF3PPFsRryleW+OYbagj5 -1dj4KvgBCCg+Whny4wADBQP/fjurbVG3mNm0B0XU4ZeB1MUMOJYGDe7LYBmbGxwn -NMupZ9Rxfb5ROE5ehyPzUf/DmrkK17fPfPHYdN/UDWbDnQHkVk5OD4Erl6ulQxuV -jcOgfW70Tyl3ucnlZjTZeihEgczHKvO5ADWVmevLyidiYocTx0QMn8cBq9iSpFRd -EvmITgQYEQIABgUCNuOs5AASCRAcZ+wTPGYchAdlR1BHAAEBiJcAoJTy/pFHvd9y -xAYZBYp7qLG2lUIOAJ9Rlpbjou3wb81vE+Qev1+GQGpaVZkBogQ24644EQQAlNDo -1aAt9iof3VI1z3TehyLrBIR4XmKRSM2Bx02CZhQRIwY/QsK6WBoxlJqfgUtsBUuf -cztjJaUBixq5qPmBgXYqN9/B8HZvG2nknHdiqKrvqFpAqATJtlccW0tzPJKtKaTb -tkORBDv6hssFa1aXwTN7IjN5nLI1Wh8lsvk9SKsAoP5Z4IDSK/mM9h6FPRsAsAYv -d99ZA/40UwQLl06u7wBtmxqSdF/86kjC0kWX8J2Y9vIceiNEiE9MmVNcYIKwIM0m -wduF50EksVjEdgWUJrqT3RztJfMT5+Sgm2KOAvvfmbKa8RF4NPSrVXDDrFeqk6uN -DT0jnUUTQFYTjk4Pxg9Kl+a/c7Qee6qXn5qeDX8ubZqN0noX0QP/Y5HSgi62UbBP -5B+e5BqE+ZLeJ7yVtl909NwTCr7KVZt1o3Za0dCYtMosPT9ObAjCanhSnuEWa3hu -outOgorWaUSEW6Y3zBKvN/M4FA7+1Rhe86gnnWLt+rHqX5M8Y/7JTcrugNtR04DF -sYga5A16CLsTDxSmM2Rgvpwh14FtrqG0KVJvbWVvIFRlc3QgKGRlbW8ga2V5KSA8 -cm9tZW9AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjrjgDCwoDAxUDAgMWAgECF4AA -EgkQO9vtsXd/vtMHZUdQRwABAavgAKCWUwgFviV4MrPrUtCIDhMZZCn35ACfSAXu -uu9e0d0Rz2QVDGB8BJkfhFm5AQ0ENuOuZhAEAInmt6zi1dFmPfqzs/gplZR/RgLy -a0vHF40Rd7lyQC2fyAx9xJAngx6Lg7UQG+spn0PPbwSa/QWYN3roNR3jJtEiTU83 -yRavL1S4YsB/9UECQwjJeFgIScHvBGw2PiQXkOFiLK16nbB6Q+hxk7YYBSgjJjbI -w1vabaDYrxScrZAHAAMFA/4jGKHej776LTZfCLjA57tqujbFJ4GYf1vycRony/xF -UtE7QCChHgYvMp5M5+/nsVTjy2VjuzG2HoU7F4lpCRLWcPUtGlvcZQNmvuoz/I4Z -inRaF1GAZb5zR5hrfaDlqOrbOff4fUvjKuZFJkzieZnlld72KOQazRQ1iqaLSAFj -GohOBBgRAgAGBQI2465mABIJEDvb7bF3f77TB2VHUEcAAQFJ0QCgl+n9/5lZxK3l -goKK1HWYfIYNSxIAoOxVFgrZ9x1jsIDsMcSszrP60JvgmQGiBDbjrwQRBADFLZOA -CYlz942iqSIW4twe90tkmeu6yswZInI3pacFpOi53bAq2y7CFrA3/HzbYodK/QLP -tmq3wKZDZcLghqtWZTxhhhH9fDqj8Rb54IVRGw3XKLD+GyJt5OhtrIBWzJevMQBp -07ZEuRn8+N7k7s5z83WZxmyIz9LgZj32ZOhluwCg4YuIbbsa92PrnfZcdW1jPSql -LQMEAIkWB5utOUWVQZHc5X2MdSMIJ/5fAoatzLD63wTLJWqQZ6tWp9v5xED5riHX -vQugCzdbdNwx6SqJ8dl4I2Fc/KYLcthVO7cUkpthBPve+XV6d6L+E3w9SsZLDpe+ -9DwM4sS3zYT1tauANnBK7hoDu+KhF9/3wGtSdJ0Sg4JgP5oGA/9k0mSgmhR6HNyB -0J5MoJhs82TaVWVdvtZCAfGdoTaPVfNT2Kc5WFfEpRudWo1tRt3j3LYuyTiD+jKr -jVG2EeEzs2ctQ6uPlaqmQgenzniCi+NCCigKDDA2BTS6fc3E/rOvug0zx9u3hNVh -LfjUIwYK9qHwv+IgFP55gGJqOMZ+2LQrU2llcnJhIFRlc3QgKGRlbW8ga2V5KSA8 -c2llcnJhQGV4YW1wbGUubmV0PohdBBMRAgAVBQI2468EAwsKAwMVAwIDFgIBAheA -ABIJEKXmf3+jrj6hB2VHUEcAAQGvfwCgoevUn2afCdW1bLwbcRs5kYrM1GwAn04Y -4r15A7ytYdO2PaxSkSJ4gn5NuQENBDbjr4AQBAC4cckdPiWgQNkGvAm3q8FxzRLo -g68/jffvj8Mvt++XQ4NikO0VJ8ezYkVd+vG3v5RoHTISynmMWZZjT56aFDSDZPOk -Qs2G0qZgAEgTpzCUBdlnUC8ZrHSTSQjCn7HtR2cpYCCUBliPtatDvS3Me1XdRfBh -Xib04TB0ci6DrzFQkwADBQQAje0R1INm9GkZKAzTECi+lVei7wbXkn4JF6n9r1KL -5oULVF8aGHNEJ1Twj7kuq2kacYjc/Di4KdESRTZN9szlZnNruvAd9JKHIgbeysen -e3yRhy+YFaqXm1MtWCdwwaDiDoHDASpl55RtuCKxz6uW77qhrZ8E6GRDrhI92R88 -DbmITgQYEQIABgUCNuOvgAASCRCl5n9/o64+oQdlR1BHAAEBawkAnReKOagNQ/Ui -7qWGxKWYY6I07+XhAJ9/kbrDpWSrx3zoS/YjBL1Z/i42ZpkBogQ247AKEQQAkOFN -8GmHkbnVqUQNRoh8W8PQr6hcNeoMHuEODey1UillH313Zuj90865VaivBcUEMl4r -RzuIkRCsxYqXF2ptEaQfyloVKcvldajjEyOSeqcnNi7eBvvfiKgUdMLhYMzb++hM -a4WkvD56Ktb7CXXbC6wemc2RbEwQha3YegZN6t8AoPclQGtp49vyAcqdcXPIS7xE -unezA/9doAqN740Bh6qFwCrG/ZIQ9SPwQyC1ftIOSTIO/zC5F9w3AwC3hfAdiecz -dulTBaPYlwMYT2uw2dr8e4UCPP/aWuFQqdwfQLLC+OFi23W33aPRw9lp5HeljxH9 -ubw2zbS2I/u7FWWP6zMjY9/kqJQeGJYcnZFNcYTalSZPpQWFzQP+O7Jm8g0rCRtR -JLCkq+yiLXl3p7hbHk9naYCtPnL5QuK0HHhYoixdXpRVVoQE1oF7reT1wUZ08Rtr -8d+VJ3vqQuZxJ3L4Wvvd3dMwiubAAoxV0qNEARzeXztho93b8t1P5NbMJDDfcSi1 -7EnvJnNkDZInHbv+PIiBeRa3C+flQIy0KVRhbmdvIFRlc3QgKGRlbW8ga2V5KSA8 -dGFuZ29AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjsAoDCwoDAxUDAgMWAgECF4AA -EgkQWMuaTIWoHzgHZUdQRwABASTiAJ4vnNwg4QN5Nj6dgloAUhXLEwOfQgCeIMtf -rfz8JP9PectU+oN68EWxNM25AQ0ENuOwnhAEAJ69MNjnL5VF+xPLtgvHSRiI+8EV -Oag2s8YdLcOef8myd/ysoQhX7K9nWdhO2cOmL3Nbt1k03/Npx+EvvyCRUiPqgYt0 -63MFbbfF2tz6O3CMzb0tGwYan5jjlyXOIoVJQA0dibpJv0Avn+mzvCGQQ1q/+y50 -+EsBD4T6GTTBW+t7AAMGBACdpIj93tczPsxKNoto5Dp8tSIMp9LEYrsNDl0PQeue -s6dNhuarQzfiF4YC3X0KoKslnJD+ASwyeDbUKBDPzK9v+6I94dNV6W1POkdUBUDl -5qFsN6u8qhFiMHzgagpUhdANeLF3Y0MGncmm0xbFuJvGZ+Yy1vtbB+D61Yx6DRM+ -AohOBBgRAgAGBQI247CeABIJEFjLmkyFqB84B2VHUEcAAQEImwCfYJ4NGyH/snAB -xoxryuVciL3Cyu8AoMtIZ222A8al4XK0DrQqJAnIZlF+mQGiBDbjsakRBADettZo -8gTOTr1nJXbk5sJfuVSQaMmbgLpZpMs3Q7C+gAX0XX+Q/vcuHp+wV2Nq0S4v+w5K -+sxDF4A8UDf+q+GmNKMA5U27hkcDQvE48EYUghcdWKjWeFwmmJOb0KMoatdeh4iP -T4j8ocGw+i0z6o/e0y0OVWsUvIqp4iZP3UlnOwCggOq5GfPJMq3K3cND3nU7GOR8 -e1EEAMcgH09o68Hbjbwpw+ejPuKwVFa37COX/65FF8PONeleq7Mr3Y8yKqbLIsIW -DaxrlflpbyMz/ShuDdNU8gh+msfwh0+RNzdEPmpJCCVJOdZO46cudgbyAQriH7Py -sSbi7AbmpnMl7kQruhAZWXLtnH1e1kKovB43a3ph8wF4kotyA/45A8bLKEmJvpq/ -amY6VjDnGsxkDjjw2OoVbt8sLdGjpganj3fvy5KRhWeWLKhmtq44tH97m4YDmGCH -Va/Iic4aDPMMvUPWdaY5DyCeerVOb3JN1qLC7o5x2HBt8RE7cXnPJl5VKxc4qzys -5bqQEYYt2dP4cJqKk3OjjCbl6TJ+8bQtVW5pZm9ybSBUZXN0IChkZW1vIGtleSkg -PHVuaWZvcm1AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjsakDCwoDAxUDAgMWAgEC -F4AAEgkQqUwPdWUyRNYHZUdQRwABATNbAJ4zGxw32J0seAfYM/ZTq0/S01HRPQCf -eV8WCJ077Pxl4dfO44z1MBL6PPq5AQ0ENuOxwxAEALW77T00/jp0+efpEm1zMvcs -SujKtw+Yc6TcVuI18nxgycUF5JP5T75yGL+QrOb43jLxNkTywfAaqeR4gG0lfZiZ -AkWEqLZFH0C1WfYdXVlMFhPWr8/syllM8wj0Q4OUIQ8lO9f4x20/zGHQayPWLXC6 -NA4kCJd2uqw/F6fhJyHnAAMFA/41FE7MsWriQFSmChPK9bMmX3oZ3KR/47QCFtOV -nuLH0q1At/EaurOCjSHAONvZDN5Yd+NWFpppJzlRY0y4hDIdFyyP3HifblcYTQdT -I5VIPjog4CN9kX5t5c5r81thxH7PM5F9evWrJbaDihXws3izi5Xh09qZDeX3wuSD -yWFYJ4hOBBgRAgAGBQI247HDABIJEKlMD3VlMkTWB2VHUEcAAQHOmACfWYGI6kN6 -0nJgsIXNyIc7dgEwDW8AnRblYLw9mIfJbLolrMCwxazbA5OVmQGiBDbjs5oRBACj -AxqGzA6j190iiN/1vJvS5jYLQ1H3xxhzXdZ6ZxjPJkslX1oxFqBINhjzBJnV9/7b -1FFe5089NiCcGUVZa2xD3Vu+niLTAGNTQeNy6Y0E6wEfvplQLJbpVGOmuVeZyShH -NCKjrsZFtS1mr7o19SUb5QWS3gZHabFTbmhibcFBXwCg36qGVAnGcZzvnUTGpRy3 -xjp+zuED/2qTJNpnPhicKSksVwb6EJFXH7mQSZlyblAnOAVFMx19GUijW4MWP5FU -dcTd5KzIDgkenRLBrpCLIFVkQ4/baP/hOiCLOmCoRu3xnFyoRPM/Jn94Qy3Jo2wi -gwkhQU+zyOU5C85QBD9ctkbYp/0mu9bpxmYTchHwD1v3dXUXEVajA/9lnEz1GiI0 -bwKpm8VKXp0YYP5hea8Jh5fNVb1QW2QqGd+XNHnRGSqX5smGyrs+xoYxD8+jv1Fh -mGaSv+6+n+JBVK4TuWrQpZ0cgZL5jZnX27TOYXeY4d5YKgE+7ZO57TwCIfF/P6pu -flGm+t5GcFwj4kkfohMEaeNhm1S+xf29q7QrVmljdG9yIFRlc3QgKGRlbW8ga2V5 -KSA8dmljdG9yQGV4YW1wbGUub3JnPohdBBMRAgAVBQI247OaAwsKAwMVAwIDFgIB -AheAABIJEEevS2lh8EeEB2VHUEcAAQHMSQCgwD4p9j1sDwR1+9bBrzNQzVIyzmsA -oNL7pfcdW4Jou1XHNc6hv4MpsHtvuQENBDbjs74QBACHkUCB29pMkveMEZyNiKIm -izF5NZ/cv91Rj319k3xHf0NJWhQp/1G38SxLkPLBdWcoB4mJRNjDyVsxFUXvRWFI -MekwL0q1sHSWTcJwCpQs+LKKtPmD3LA3bhbuTSdpYgmKy21SH4epubqBzk/P0193 -mWXzHgSGLeUoTo3N7eBQ0wADBQP8C1Q3WGrBZNOmFVly0erclpQRv1qCa785yx/b -j9ur2LxHwVozAEXh8jmoiKZyoAz7YFnp29kR2qtVplH1oePNyFweZqIjtmZbiCaT -4scUVZ/3LuYbxgMoUFeRoG4mnEVvUUh8mmZovMmZFrvp0uojcDsfYTx0VBr8waxg -Jrg2YguITQQYEQIABgUCNuOzvgASCRBHr0tpYfBHhAdlR1BHAAEBU90AoJzJUQIh -rby+ZQ+BnaORdChD+c2RAJQOkYvVpmfV4qsOUdwbIPgLPLCemQGiBDbjtDQRBAC9 -Vf1MkTKc8kSxfdfZ8Y88OJAr6gHsPUg0j1t8gPk0q2ijyrJuK84ujzmLmbtFSITK -FfcT2VSD1u4qa0iFqzSwnywtRGYKd0gq1eMhaDcp3SmaMTyrbPJ3sKFDd98nbTzv -nA1tHgZCFI7VZO7HBGgvnd+370lNQsnGRBF/vUDObwCgllBimEp4tasu0WNvZYpt -jGy3ni0EAJLsL9W7jR64h6+nZNkdO1jRT45sW8mvyMOt1BkyRQVK6G2Lut879t/u -pPCYK+/ohWaf3TkAKH1ucrBm9xHlPXJHZvoIA3brt/OuJmG7r8Ub70N2vrZmdXas -/w5ru7EBcKeii9pp8pi6mim8dXTPS1R/b7BqytB0dlO9zSl9j7noA/9Y5UnQobM/ -qT1tiNhJEnUwlvvTB1UWId2UiUR3k/eNCxc7IdUytanqofXSxAu2jyDB5Ymv1od6 -bRCNM1JNWnOnqVoEd/u2csTAIkZ5fl/kE6HztqRGPB+H0n3Nb4MGu2mpLq+OUNhT -nLpEZsZGXqd21eFXkWkThxstrH+kYVYSrbQrV2hpc2t5IFRlc3QgKGRlbW8ga2V5 -KSA8d2hpc2t5QGV4YW1wbGUubmV0PohdBBMRAgAVBQI247Q0AwsKAwMVAwIDFgIB -AheAABIJEN7w97jsZ9veB2VHUEcAAQGiagCfTG5biKrPKo3dZTpI+fMQuSuPNmwA -oI3mCWnR+UrV5myTBsNmQ9vcnr8zuQENBDbjtFYQBADPV+xDMQ8NzkqoJyO+lriA -UrCNIBf1Kbc6U/IPAGOoED1YVPX4EB27u3K/EmRVd3clFS085Dau5rFIr3d/xXnL -n++wqSgQq0Jc7LflMpIj0P209/oKt6MBovTAQn3lNpecmWd8oxiKoPP158Zgm7iL -cOvRTcs+/p0KAzNvHIvQdwADBQP8CQS48V16lhWOSXV6u3JOukMeWBw6Tx+7M1Cq -yBihmR8ZNlF6FPBvVkX0NFVUH2qJn5yr6PmxQxSRnC3yCEyPBa48xqIditzynMbE -IkNUrFZTE915rr0k9MrwzPGuLfaPtr/Miy4BI0dnZ/5U4hoxPwDbp0aPUwRqb8+T -9POTZs6ITgQYEQIABgUCNuO0VgASCRDe8Pe47Gfb3gdlR1BHAAEB/yAAn18Lg2NX -AdY6HW0LEurh0Xcv8zlWAJ9ePiLMYxpoW5nv4g4nuOAWoL/KLJkBogQ247TcEQQA -rUqUbiVTMxJhp8bA4vMXAzCuLjys4A44DE+uRFb9AGsZTmw/FTPETO7iU/3frlyY -yTgIvI2zDF1SwHXG06KF3yIu8LF6OCM0N0k7KnKpw8M2tkPiT+D8ANrHU5d178ev -zm40PyNDyKxSGNlIG1N4MIKFtNdMlahLvu91kG04WesAoLPa5zISvsX+Ew95M1o4 -Qti8iYHbA/4wr+eYRywP35eb/F5V9bOLWhWmEDzw4KHXQ7V+OJ7JD5n44S5KLPKw -IogohDlPmrxDTAJ/YAukApUItd30kr0Uq34QgFktAsqgCP7C5KEM1TTxU25Tcs4o -jUHoDyMj14ECuiTCP0ZFRKUivopgjgRhFTKXVVWTySkQ0g9SDaITSgP/a0FyXMQU -YJjuB7GA6r4U6QnIHsxS5xrQgkshb4tp2MVWMhqlhsfOLaj1WZ+oe0DxKw0O3YKT -H/EAzmNelKcMbtTcilLaIdI5l+Ylam/bZe7QvbN2s72Kn2PZjtYqO3Uzqw14bqAJ -Rl0ekleMdZRMMzAsour+iNVPHnlodXnQ2gy0J1hSYXkgVGVzdCAoZGVtbyBrZXkp -IDx4cmF5QGV4YW1wbGUubmV0PohdBBMRAgAVBQI247TcAwsKAwMVAwIDFgIBAheA -ABIJEIl5psVWf7NKB2VHUEcAAQG3TwCfQ9GqGIzMX4vfsPK9xpWX7TNKuZsAnR8v -7wPkWtynWbdi0Eymj6Pl2yJ4uQENBDbjtQUQBADG4aUG+qgOTGEgOAVnN0ck76An -Kb3jOBIYeQGYEgF/lDYbY7fOQ3tIgQ0jXrKD1zHLvORNsG708yDNR79S5Ci/1nph -crNOPWMujOsZ2WMo5xblhG+WJujt4pcNSRK9P5fonUE4hV7GXTljg1yZ/ui00Ot7 -b1B8ryAYE79t1B3svwAECwP9Hg2r8lBq/j/t3kRO4xl108DFXiQKdj7sXugmAcMo -mF4nG3j2s219dLEFlSwn0/peGvjp8JFPfcMPU/xHJSaZLf90mXsf+pHcDWujHgVA -9YC6ThYaGx9Je+VmcVYomELxNnMWKyOJePDU4ViIXhMCvGP0Pt39wcQoiLjeu15+ -l/6ITgQYEQIABgUCNuO1BQASCRCJeabFVn+zSgdlR1BHAAEB7JAAnihkYWPnxhbW -i9SUMaB3Qz0SfsLvAJsEGrvruaT2XPVKwa9FFfqRj6WPnpkBogQ247VREQQA3VAG -c4T+vuvVXcka4ETaLaLlL1xOiPIdJMWRWWQ60CZqWXDVpFBw6oG2AyfUZiHhLlmT -Zssz8UhXLw/URsPSpiGbtpGWKiLs4OCqjslN0lHzcnGqxGWCZJixMgZa5DcWZJjw -qdXEbDChgm4ULP/7+iKvIenTQNhFoCXr9MtdoHMAoLpNCmSKlTu1H5GlWmYTK9An -dWrfA/47ip0VYgzIvUhI0iWcG95sNfshApzPL6zPgKBqACogs/5/DfRn9g07BcuM -ihLJD0PLNPVnOXqQRaN4Da7jLuJA53XtLgpogxG08M6XUimTucfcovu29/bgjZIK -A5c8KJ2lzXSJ9jZxSoy+O051f7yhXbUmYC1vdNr8GBk69QKy/wQAiHMfU3cbCfTT -Mmig+zBHCkHjqzqr/zKtR8RT5AwSOIU2aUIiHdV08apCelBw8PbEf077TuWCq2Yy -DZJmgWRYh5cdaMgdAd7ul1FS1yHPZYshcofWjgXUJHR4I8iPCs5OmdHo2HK3uU2O -M36ZQGSpFA5WN1NEm9GtMSBoYKN2ERC0K1lhbmtlZSBUZXN0IChkZW1vIGtleSkg -PHlhbmtlZUBleGFtcGxlLm5ldD6IXQQTEQIAFQUCNuO1UQMLCgMDFQMCAxYCAQIX -gAASCRCe7zTNSxGyXwdlR1BHAAEBSQQAoJRRe9UHKHiX2iFczXq6nrvr0NhLAJ99 -W/I5b2/2QQ01we8i1mcSYPWj47kBDQQ247VnEAQAmuK5RcS0zTyXp6SjW2+WeQIp -JnJDflL0+iBe//3SADv01qUmw3jWMAuxG+CcCApksl122V9npEHiLC4Q2A69roLR -sbxKBPebustfadLJoVYqPsvjnrBlafe5GcrFPnKbE0wV6ZXx/Tp/eSDiQlid4lWz -5J+z/mN7KhHANzoRAbsAAwYEAJO5fkCSdNwkisFXzeKslWxm9Yoe1TOouiSV11he -x0j94Hpz5wGWEXF7z+FbDq+4V0UqGkKxaERsl6HMWNkImj57N/9h1C1YDfiKTimg -5tZpKmehXtldpWGCNDZrE0RasrFCKENVhFMhpc4kAnx6rbA0+LhRvJkvkdxY7pKU -//aZiE4EGBECAAYFAjbjtWcAEgkQnu80zUsRsl8HZUdQRwABAfRcAJ99+4jghLty -CHQ82CGv/S/cv82GdwCgk3C62Y3uSS/2f+g+qQHLMvG9m3iZAaIENuO1yxEEAIEM -k4Zf0L/HEJVk0/o4fPpwvm8zc+KZQCFX70cBVU9BWJOcUquRg9JDJF9bOM5TxE7V -OnkIfPvjug5vqP0/vjIfW7LvzIWDhS6FcFaKeG4IoqrgghbAmQIoEWvVTx+7xrpj -o1yOqIMDQqYZEmsw+Zd6deQmkUYcbvytS82L0gx/AKC6DM0guH/ddkJlT4FQ9h5c -v6dQAQQAgNdmGPW8VceCL2WaKMoOMmhwQGhqY3+1pDLo7HVFEPoe18A9jlMRHWfv -Gb2EzMT46/Ugqkf8TzvZGFrWq7W/t45rp5O41YXQ2+ZJH3nl+t5Gw25Hwk0hvpK0 -jYRH2nMFR+PKQL2mDbA94LvClAkgX1MX4lrUG8bYj6FrbEnvzoAD+wcRS8A6xznx -hs+Vsg/KnYl0Qe9dNFPY0hJVG5MxCyDy9X32cxhHYJSHbvS4/LLbFloP+Rhwn3/W -eBjsL2lts1ahXvQ+QQw7+qPrs4hWJZU/NSEh1RGitukaG5zegHNTE6CJqXshshI9 -Ei0OCDahmhjiGrJA3HwKPZlkDMOkza8KtCdadWx1IFRlc3QgKGRlbW8ga2V5KSA8 -enVsdUBleGFtcGxlLm5ldD6IXQQTEQIAFQUCNuO1ywMLCgMDFQMCAxYCAQIXgAAS -CRBrxHeAVKzSRgdlR1BHAAEBQOsAniVMkc7hW7GdLkLpb6YDiEUy0yrHAKC3dyJ1 -RI9tKXk1EOW9jTopkl5ysbkBDQQ247XyEAQAzHzwwUKDM7+djJo2/EnWmCijc6g3 -fStaGNoXDEovi3B2oPiiRTsigX90qB5nFP7whDfi8k4JY2Eig5hH+MGdvni36hYE -nQSadsZueYofvQh14N3V8fUmx4hiQiMXyWiLJzc91ZiRjww4wZWn/4Y5f+0mb0fj -CaVSxTxo4+7joU8AAwUD/0oL9Gm3gl1XVV8BhJoXVdFQ6PN9yEEXUbtcrfkC51kT -Bk2NaEGqbB+kC8GEmXwyZcW7AQN7X6ikraUUm3RjTU7CvkSHobBnXYt7FhqZURpu -V7eSqZGP5nP7SxWmCTTKgIH1kHCpWRwaexKFjIIkYgyVFqtEx9cEQ6D2kXPh+Rna -iE4EGBECAAYFAjbjtfIAEgkQa8R3gFSs0kYHZUdQRwABAX1jAKC5Gp5sHM9sWdZe -M6qfu54F2OwMQACfTjYXfpMApAROPkjhhFNqH0d8x5GZAaIEO6cTzxEEAMnukcmm -91KqYvahVQdYaI/Gv//n4YDWL7BHNdArU3MA0xjcmimynR67KIXdsKu/kEVcQJvH -6rlyL2J+BvRopxHRmT+J4FKdQjzb0BdJMoKzxBd/v3ZwinW0fjlvTXabncnbRO3K -fsD6Bd5FFv+0HOFfUJTQCga5YtNYrQZxIz5jAKDrTFXeC0ABRhQNBB/ym2jiJqzD -RQP/ZK9t7tKX2GKmrdn8sFec3j9h1QNnDoP/82xrXZQRICNusMBEhPzD7OAEo0Vi -gpz2Tu++wWci7ghKjCCMqmgYQDGJVmVbJgrqM+4WgPQv7jD2Q/yRUhlkf7/dp0SN -FXfodHxOOD3d5Fj0zBMfprKle56vHjIDfpNwaz8k2XjZMw4D/i1v0WycSLrbSWcC -YavqVEeZtkJ4UMHcjsjQz0VrI7T/DMmMeYoaqs8rzHlDJGuT2Nz4Q3kx8pY/lTLp -k6n6aYq7HTvXHZSX5J0+An/7Vgj3UKH8Ks7/N/dN57ZJY55+6llmQkpg/PV0cdQN -DSbKeVYkeA4tJrDjViGje86h6ZTUtCJIYXJyeSBILiAodGVzdCBrZXkpIDxoaEBA -ZGRvcmYuZGU+iGAEExECACAFAjunE88FCQABUYAFCwcKAwQDFQMCAxYCAQIeAQIX -gAAKCRB/8jC/nVY+ViD9AJsHf9byAEuDOECER69NAm18N2WdpACcDiaOaA3gd01M -kdEz54toKFIpPEa5AQ0EO6cT2BAEAO3Onn+URLuPNsFVz6rrIWenJbpzGYTdNf7n -9kAFIXfFAKL8nPtdne4zL6UQcHAABDOAd4gCI9tQSPHTrX1tSlzDF2xJL5sbFFxk -aN1ivB9oh4+ToMXEGNOHAZ9SRinFqdBotzr84zg/rGVFTzhSuMkPCMUu+1NCKGJ4 -B6wIJ6/LAAMFA/0e7Jom6d9wPQ+LZDRBK7cH/yG+Ylq5ixl86AL3ERZL/JUuUe4B -2iVPx331sY4G5pDC3sqv8FcmItditfFO8FYJFMWD2DfTdbtGU4XRwgd6BQ3192Aa -LcwyjzpuEMrplCFQjTV0OfEFogRchP4x5UGx6gdyXRDi5n73CqQlGS4er4hMBBgR -AgAMBQI7pxPYBQkAAVGAAAoJEH/yML+dVj5WO4MAnRC1ThcLd+ucK3uM0OvaqL4I -B14GAJwNvBDmPEOrXuES/xFiuDa5aRzbyJiLBDunE9kBA/9nslf97u62S2MfyPtD -taRtydoB9/s8KQlYakcTWajVSeoKXqSyyBNmWL1Elkx0q0mm9OoEvFRLjVBHPn4x -CO2M5vZQgnxU8SJcHrVsJnFYu1fSQsa+LRHqToiX3LY7vKaKJ/5o9gTYWpbsX/ZD -kS6UxuRa1BRoFYZdCS8A2/QSGQAFEbQmSGFycnkgQS4gKFJTQSB0ZXN0IGtleSkg -PGhoQEBkZG9yZi5kZT6IuQQTAQEAIwUCO6cT2QIbDwUJAAKjAAULBwoDBAMVAwID -FgIBAh4BAheAAAoJEJ6cEKDO2FT/Ad8D/09Z93LR+W85FFzr+zvPhkp0oJ9MVcnu -OceEzNhT7uPyaf9ZYtgyHdjMnRMMPqZZnP8fwoyrkSoB/vDy/M9t9H2RHGbdU0El -FRdqSWwMkGWzpA1cxMw5QuqznHLrHj6VsOkQ2jpGmY3yBQwJBbF19eGq3V5jJLW0 -Lzyn9HM37ToRmQGhBDuoot4RBADa7tyCsjFl/2zvNQr/r+GH/aCf12wlxsmVE1cs -/GdkO4nvZgzB0m5RKPfsTEf18Op4wZh6y4rQJHCUFxVkG7MbPD2d/aUay1nU7vCo -t6vG89vkUMtuebZY3tXNQfwVrt8lo87DnB/GA0dKPS0SQzbf08Hhahw4EUQDEWI3 -uvf/4wCgombN0n8cpUVPaoDMZkyJWXOd858D+wYzmkIbHk951dsM1wOLQv7athDw -D7YHi/s34V1rWoZVmuT2U3EZiLusYJ5c/bgsRu9+A3Y6rDmh3XL5d9gpp2JEsWgJ -MI4U79/AtyzjiwgO3hw3QuWooh+VB117qM8Sw9XyFhlmSD0ojxgtnrh2YW4Ow/YB -9yU4iLvwP4iaCuH8A/dIqE8xObbkAi3NbyDewi6LTYSnLQkHvUQhBuMBJUfBLHKN -vd28/Y5udS44qQvz8oEQ1zAmo0/y+kHWxfxh3eFHQiML4MS35srPBisCXOpJGoJ0 -dJ8c4y9a9srzeg6ZJGbTwoFQQZbaAIxcciRus7NvnCOEpyKJEba0lxhyVTCftCJI -YXJyeSBILiAodGVzdCBrZXkpIDxoaEBAZGRvcmYuZGU+iGAEExECACAFAjuoot4F -CQABUYAFCwcKAwQDFQMCAxYCAQIeAQIXgAAKCRBCNzY0Y/tTEbmxAJ49YOdvcxh7 -tCPAVPcLWExYS+BesgCfQQhQ1qWjKuLy9yWDfGKS+5Qlsqm5AQ0EO6ii6BAEAKHp -h48Yh6jezPm1Tb2F9UOfgLAEKHXbwv5F3nznYc3/cjCHLXJNISqlq+ZflRMu8lpU -Wf2HQLzVFYXtDWoBrujlOldYy1IWKOvvYPBRIVrbe6r4tnklRN/2DY8DVWSSFovt -NhWtyUGbil+wDAQoDbWQXhjnfr4zOv+gJIjMYbzXAAMFA/93V+ufNG4jqm6OrcMw -f6E1GH0pBlySOwu1O6QrLXx/YlK+cMQqPyy/oZ6Uj8MqUFIJEBbQwe7byubHlYKb -JG6bs4ecOUggATX3Bnby7HwB/xjQI6ECphjxmrGqtvbewG8LGSZNhmfrx44L0gLo -8bp77j8pAaCc1syS8HNue/3K1IhLBBgRAgAMBQI7qKLoBQkAAVGAAAoJEEI3NjRj -+1MRb1kAnRcw4bpKaM7wyUoOK4rJuas+gOfMAJYsoMCmvozGAeeTJE7k8AWm9pLZ -mIsEO6ii6QED/2vr03VB1JAzjQhzifY2ueHye0X/BcjtSFWhN6jIQzHHnRH8oSaN -Mp0d42gvxNp5aypEs72SFO4W580DsxbNdtSJhaC6hnpncAg8yAsZIo3Ix7v738Yk -h4zOB/4RLwmZJzm2gG+soiQAATTOBvnD0IJumU06pCRUHQDJ0daHswrRAAURtCZI -YXJyeSBBLiAoUlNBIHRlc3Qga2V5KSA8aGhAQGRkb3JmLmRlPoi5BBMBAQAjBQI7 -qKLpAhsPBQkAAqMABQsHCgMEAxUDAgMWAgECHgECF4AACgkQg6m004p3Kwg6xAP/ -VgizRHS+2Rxh/kVKI1/PRQpVGCEl9uHB58peMdPl3aAXxBcOoO+74cfb3ce+rD0D -EGhjXKcXDl2dwLl/lSAOdUwHPdLi6Miv4IvoMyMsCyxFIgGnr7qZUFOzEues9H0I -bVbwSv6pJMCgyc0aOnRyCFfT3m9lXL9hIIUVvawatnqZAaIEO7NiKhEEAMlPZPLF -VnBUnc9J2lZRdVmnHWgYCRc2kYgfeLMqY7Q9l/Nd1SxuCt8DpudwVs/8w+6oNIH+ -iH1k4qcZYOt7afw5C5Vn8LEN9NfcTTkvwEqb9z8FNeKTAqGK8lpl25NgANwqtxql -gK9bZUuxzNIizsc/GqgkjwL5TgI6vpicdFoXAKDWyCdU8Q3EK6xoFWxPR5D98VqG -pwP9FdCrFqC/Nt3rJHAq9PNCWJWtTO/TiK8LS8Pym7YRobKLzGAA41uBaEcUxhJA -OJKeW8m4jq9mfmQixGIoDWm1oBbM5ooTySUBweJZUh13IJmocOYE++KxI7RXGmru -aFcCG0pusHLJoanyzh6KeUby9S/PtY9Bo3vc8I239EPhj08D/i9l+cdXCGhGwOWQ -xsCOUcXLV8zbf+lL0Aw/bcwtr6+CSCsW+DdnRsJzcyKsKz/EezJE89LUsmFqZXnH -aSdXQ+UdMAegZoY+hqlnIOxhkM2RlGqO2egcJ8TJrzeuHEHsYkiwQozyhInnXmQd -htDnQ+PrtYgr0BY5niwwB6t8NCGOtCJIYXJyeSBILiAodGVzdCBrZXkpIDxoaEBA -ZGRvcmYuZGU+iGAEExECACAFAjuzYioFCQABUYAFCwcKAwQDFQMCAxYCAQIeAQIX -gAAKCRDIQJy3y8q66ZRzAJwM2w8QpKAMfZsOIPKOiJKICCXlYwCfYKaaJ5LOz6mq -kSbVgDVtpeAZJJWwAgAAuQENBDuzYjUQBACJygT7QnMtfDnFUnixXdXu/vOCqTbX -vmysKnnI4OeDW9QxTr+ugf+f6ROykJFF75zq/53jgDD2cQkUjU2OWbrrqWF/aYHp -YM21TDtIRfRe0llF1kSHPnYW2rjnY4/AeWvPjToevxursEn1J3Ijd6NentxE/FWh -etTEHSWE784/NwAECwP/fpxILkyJUfPdNY5HqN4Aag1g0ZWjVfaWrebZDt0BIHJp -Qd8RvUtQnOzCOZ29KOQKS9LHOJOB2EjysCKTwBDYK5ZonQUtmhdwNZeoLYlLrH1P -Q9WuhddjT6dJWMl2yJ+zchmDRFajf+4AvrbYGnMbMdjCllnDcygSlzUt7KGcjuuI -TAQYEQIADAUCO7NiNQUJAAFRgAAKCRDIQJy3y8q66b5jAJ9ROwHyPzvGq/vgztzs -4972gMuDIQCfeQq3q4tW3qoWyC/TOkvTSeUuzwSwAgAAmIsEO7NiNwED/2S8L4RT -6WxoBdOIu6eqS0McmZO7IDt9rDsXtpGG0CuXHajIgiSgEuYxX7uMHsNvbvV2JQyn -P3ZyKhym5xYcjwt/pu2EpN09ZaTstXryDM2pWl0D2bSfkbjEa0DumA+aZpDXix5N -juWsaQ1KZPFWerfJKrKCjRLe1ODBkvKlgAVpAAUTtCZIYXJyeSBBLiAoUlNBIHRl -c3Qga2V5KSA8aGhAQGRkb3JmLmRlPoi5BBMBAQAjBQI7s2I3AhsPBQkAAqMABQsH -CgMEAxUDAgMWAgECHgECF4AACgkQn5OQvjVwcDdcLwP+KHNNbeyiJbRnQ8lN12MM -wPUn5mukWYb9zHnTNF8R5xFui9ZSIRzOOilw7DkbpoIlFz1Wwk9TfOQMtYD2U+Ts -u/2a2jxDJuxS82ugY2LjsZpUY9HZ6x7v7xZpY64xpWD88zcqIrenMWTrG1pU/xr+ -mCQywk9dFARsoeRrZWH7fHKwAgAAmQGiBDu0KcsRBAD9+Zd8zw33dyY80G7qcBZD -kw56//8J8ivxH2EZEfcVXxs7vnyAUuQdfZF/+5FzKjxkd4vDVwjRR/MLcDtMmvrY -wCgsFLZ+f3CADN3sqyckVwqakpVCpRfQQ3SL6TiqenWPIwIs0BV1PBVe4xOkEoSB -gAjnFc0roWeWYrhEBDjYzwCgpEMYeOKONrccun/7g/z+HAdh3xED/0aOuwx/L3HK -dLaj32jsuQhoTiyQns5h4lV+5n0boXtDslEihN13g6ocx4i8sgyh2JPSmuapFR3A -RBLpCLwdXACyJR00v2h2V5Y5vfzQW3pC6OfjOGy6/K3tLn9y1Tgk+k4KiSKH/YPS -MfNIw7lE8EqrvBCORT8LddKbT2+xai7rA/9pJ0HoibbLjuqIb2YehSwIqX0Jolfp -b6GXk+2j04tbpCRg+h8yzrWGbNcoRkSXoZuqG77WtR3/fnFqG+H6GCO1Gxbdcdx3 -tWsA/CQSu4WA4zTWr76xmD/glc8MtWEAdiLteKe8GwoC85e8waqGAHK/Iz1VLptw -gXuSCQi9K6h1jLQiSGFycnkgSC4gKHRlc3Qga2V5KSA8aGhAQGRkb3JmLmRlPohg -BBMRAgAgBQI7tCnLBQkAAVGABQsHCgMEAxUDAgMWAgECHgECF4AACgkQBAwmnIJS -W2YqwgCgnm7EYwm08AAYQEWJ1PJtDjguT8AAn2mHZZSIkVNR41htlr1gdyDWCTb7 -sAIAALkBDQQ7tCnREAQAvkwf0DiD1zbcqiBajDGZhDvE0cb5BUbMcuJvSH0FBXop -IIniYcmnfu5q393y8WPc/rVrJVHrAU2RyHTAoX8vI14Hvc4HUFDdnoj6Wk/xSiuY -P8C4VN0NX3G+S+C4Pa1Er2s/m4X9PRz/YA0bMVynp7f9QM18aN++OpWV2jVBRd8A -AwUD/3cuV7jHchUeZ7h6Upagzj7quky9o6o5lB///Pk9QZ5HEBQTCJDvmu13xCaa -O9II4XFwjYntYbPOxOTJ1aEBKQubkUo0SIj8i5rhLTeDkkHB5M/rO40gS/MFNMVW -qFCvUIQk7yBkum+MFcJFSEz7OMpL3K5X93W9twllqtUZqjvuiEwEGBECAAwFAju0 -KdEFCQABUYAACgkQBAwmnIJSW2YNEwCfbPwQzlrLRCUuJM2inVLcz/3jijIAoJWg -gcMT69FfppDw3sA2h2PtAdOAsAIAAJiLBDu0KdIBBADLr2l43qiQ89pgGz1gEa8i -JyrLvkiYjgbMjT3V9liCUwAXEYexXJD9OyKHXgzxRoeBIEvxRJQ2UbDJS+Uln+hY -/NCVF7sq2yzZr79KlJQzVcNbiaHmLpSMqVNWW7hkqvrA1cmLqzw5F05QX6bTBiCO -2LrvkOV5Nwl8prw7EDW7JQAFEbQmSGFycnkgQS4gKFJTQSB0ZXN0IGtleSkgPGho -QEBkZG9yZi5kZT6IuQQTAQEAIwUCO7Qp0gIbDwUJAAKjAAULBwoDBAMVAwIDFgIB -Ah4BAheAAAoJEJsH4rxTFNch1x0D/2WcB2ranNdpej5/YmsJlJha7vI5zoTCQMwk -Px/oFJXZjfarEkFdKRY/nz+zZDVxDzr5DuA0vjBP5h3JuycQwuGdDGW7eF5ZIX34 -ntCepMLohLkqEO9JWUMWzBN3/pQXDSUyIbE7qSRLKqn9zGgvsrbx7vwnBPFJE/Qz -0gREuUJ9sAIAAJkBogQ7tCz5EQQAtqJpy5L5ipND1euXjra9IDoCG+iGbo9Rbx2D -eQw62EQxWfT5+JCLsy98OuDCznWB4qSU+gc/Acpmz39PuGKbZ1ysfM2y6Ht7yLqR -UZJfIs8slQKeGSXPEOcEQSOddQbW5lDPfTov/AT2hf9vvpi3TyBuQ9rfeVh56nRv -C87igEcAoJgCFriL+cHkx1XTdemk5462nlRvBACwLOfshZJfof2hgg2fJgEo6nUG -meJ2axHzvy3NEd0zToDaUEaoX074m3sfu+WqiBfbgtG4TvLD1pRNYrGLD/pQ/5AQ -ocBHdEBs+/1ODiurIwPAeHOR5uRzXtUnJVJosgQSjpNKQ6X60KoG9XVPmqr7PmUb -NxpapFgKRcQm7djfaAQApjae7+WszMEIddG6c24xuFKRwhvw6mVtZzggN+vHDvjS -IKyDnCHYY3OYS0/PDLdrLqxCGQau5XqlilSKLkyzbh7zO1KfznHua4uLUSF2qkTE -q3njvBfPxKFdKE/YWy3ptV+xoZsVTlreRf/sEQzPNGtxJ3qDzloIZbFr9N3oXwO0 -IkhhcnJ5IEguICh0ZXN0IGtleSkgPGhoQEBkZG9yZi5kZT6IYAQTEQIAIAUCO7Qs -+QUJAAFRgAULBwoDBAMVAwIDFgIBAh4BAheAAAoJEAzxRunkmECDz9MAn08okktW -vgrAJ600zYVZH7Qt26D/AJ9uA9PUHta29AzO1Owmibj2xzWsaLACAAC5AQ0EO7Qt -ABAEAM1AVhC7V3EnU5XF7M7OPozDnk9fOgGpCh4HeD8Emuqh4TRVWSmCSA+YqWt5 -r1L4TpV4QQX+vUDHet2i/IieIFKOrowuwiONln+YGToxXSB8tOKKr4p0qJ/w4ozi -jJZ6NVBmsGeXZIpu5LB2Ar4K3z3HZmwNSlDznVNwXJXNpfIXAAMHA/48d7y3W9y7 -jHD6QatVl68EelxV/x7BWHQF0JEltwHCKN65H5yV6IhUn84VNJazS5jVwYUvbmbQ -u09Ndm7iKX/Gfwo5EyPxGzbLl/W5fA3vn1USXJFX2Tk7wALQ5SAZHHbrluIp/660 -zvXn3E+466KchiRCdOfqFpCd3Rxgrv/hAohMBBgRAgAMBQI7tC0ABQkAAVGAAAoJ -EAzxRunkmECDFXwAn0NXK//V3U3k1LNXeU0mz6GYmaPRAJ9eRstO6/n170QF3Q7b -kGNUvtPVdbACAACYiwQ7tC0BAQP/d9zC0s9/3Arm1Wul0feKO5jPA0pk/iZdcCDQ -WYqoMflu2d9j3vIqFNN/tq9JDlvUXtdc4119Pr5Mgh7pVnSaQtYqbih8fbYgNUbX -1NrqqtgeI7n28S5W+SMfR/uLCpdGSRoch/gvmKz2u7pnyQL/Tcm5ffMP0gkgjNVG -a0ok/1MABRG0JkhhcnJ5IEEuIChSU0EgdGVzdCBrZXkpIDxoaEBAZGRvcmYuZGU+ -iLkEEwEBACMFAju0LQECGw8FCQACowAFCwcKAwQDFQMCAxYCAQIeAQIXgAAKCRBq -3kKidAP1iVhsA/9q+o0L8lqSELMitAcEe8q74t+gaoQgOzIdWZp0G4GYaxyHU6xU -AuWt18WAOJdf1WG+vmlz5kVX4OvlTQFl0oeVEfCEvNTaOJsUlPEajB8o3RrKzhxr -rJ+nJGZV7SYs7CbF2cfrnuLMZ3vc07YlGMAxZU5QDTT4sKZ0hkEBhGqylrACAACZ -AaIEO7Qv2REEAPz8+IF8X/cOgaxp1lafMWamZoGa7JaLvAbtQJZV8JZ/2au1iAXn -j/C5f7BS8fQk4uE94mQy6cj1TBkNCJEARCrGRUQ3cSMBrFD/7WKneU9OLuTbG6cv -B6LRBZv+LauSi2+I7OD+1k4VhZrYyISGIzHStJAFQezNLe+Md9zlNVrvAKCT0YGS -v2bgvlU4D4+f9Li+20NGMwP/UKayvNs6H4TxWJipMNQep1rDOUDKNTyIJWaPAzA7 -5l+iFuyrBAw3cN4NTsDKRdNCCOfmlrC21j0eSDcizy3jVeXAdkKszQSLKCsrbGq4 -yL+ZIgHlfQdL8smSMIl6C0X746Ez9VU95acjjjhvh8WTw12jkbIR1RL9HP8LX62+ -r/MD/1ixh16oBvtK0l8QOVrbm/H6FwTZspf5bLb5G0RRBX1VJbKH4GCzlLyQ34fA -Wl1xen6Pf5beJP5CMnG2eWYCrS6AluUuIJgo1w+vx4MGvq9OMdKyJZcYLbWUnx7C -DbOo/1m+vZsXikA8z+GFfRsOLwL+HSdSQVxEZbG6hWJ+jRMutCJIYXJyeSBILiAo -dGVzdCBrZXkpIDxoaEBAZGRvcmYuZGU+iGAEExECACAFAju0L9kFCQABUYAFCwcK -AwQDFQMCAxYCAQIeAQIXgAAKCRBwEnpBKosIQEDhAJ0cAahtG1+/4gMMWltbitSq -bTNBrACdEUWzmwEVSOrX/nMbvhAejSljTtqwAgAAuQENBDu0L94QBADW/R4I4DMQ -vkGlvP6jxWLz6TgkPMAAfEyxIJoZYLJggau4XJYyElmUGVFVH36DPE0453yN7j3g -BxVbOCZamUOINyehuBy8Gxom36Oegzvr/43TcNPTHZnVl9wJVCFmOsAR3L8A617l -AguvUzlj4e7GwV5yCwwlNtBGO27Lq/dISwADBgP+JB4l+2Bdx9wMs1zVDGQj0BER -tyHmwSVzLn3BG0pAM9wf6Me5/o633rOOQYl1mwmXXjUWZasmjegqWLUFPEkCyFMH -R0CWWI9CdBOQROBFb6jK9Oq2jYoGxTJ4kCtMGo3z/pNsAGdNtgj5s0AgUIoQHw+L -7u6XF8De/Sww56eyuKOITAQYEQIADAUCO7Qv3gUJAAFRgAAKCRBwEnpBKosIQNT/ -AJ9z794Z40YOapyZWN3NyQPI1zM0vwCfZIkY3c9J7WVXDqO+FlXWrb9L722wAgAA -mIsEO7Qv4AED/1NZpI/iOHgQiAqloxQaiXvOL9X5hbtXPbFMN8J1S+78cRxBKtcb -z4HXz5V0OrTKXG7aXu521hrlOeeAjBFhf2SvfYmPi5/s6RtQlv26+mLUFgptXy8M -NViaADZaFIpmbPQfaRbY1RjVg8kSPKt35cOa3DqO2gjNfgbTUITTOUQvAAUTtCZI -YXJyeSBBLiAoUlNBIHRlc3Qga2V5KSA8aGhAQGRkb3JmLmRlPoi5BBMBAQAjBQI7 -tC/gAhsPBQkAAqMABQsHCgMEAxUDAgMWAgECHgECF4AACgkQR6zxLyoSmJnf1wP+ -Lianh9lizALW8bgEWU7A8K6H9WnVSqVYJ/yihZXv8iHeHKNA5nhUumvx2xz2FbZU -Nk1lgElbuoHjaG7mt+jJxvbx7NluGJkBk0jvE9zFz+LDqfaIp8Lb3IGVvlxnwl+D -wGQ6MR1MDf1FcBpIlMEY5UFV99b5D8WQ0dlAaB4wWA6wAgAA -=Xw/z ------END PGP ARMORED FILE----- diff --git a/checks/pubring.pkr.asc b/checks/pubring.pkr.asc deleted file mode 100644 index e8eaabb93..000000000 --- a/checks/pubring.pkr.asc +++ /dev/null @@ -1,28 +0,0 @@ -This is a test pubring generated by pgp 5 beta - -Type Bits KeyID Created Expires Algorithm Use -sec+ 768 439F02CA 1998-03-17 ---------- DSS Sign and Encrypt -sub 768 CB879DE9 1998-03-17 ---------- Diffie-Hellman -uid pgp5 test - - ------BEGIN PGP ARMORED FILE----- -Version: GNUPG v0.2.13a (Linux) -Comment: This is an alpha version! -Comment: Use "gpgm --dearmor" for unpacking - -mQFCBDUOrE4RAwDbbxWAbWsheUJprK6VryMTpwDiYwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEm -Sppp/6/Ygp+N3n32Kznq7PjHXiuWLlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUAoP+KBFly -qNMdsK8j+ZO0A8rnImGrAwC1ddDme5iZFkTEWHhrtU97sEu2GDkSQB8HdX8CoRcrOz/B2WliF6qf -BKhcZPFVBIhKNzjTfY7SEYAZk2zcsCm8elnwSLaGEzxKFNFBqKDNXP+a35spcqsHSGzDVw4VuKMD -AJNnAP6skpHlhVAmecLZT9eRzVoOq1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXv -dCT24hlfoGoXzkoDInkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLbABh7QZcGdwNSB0ZXN0IDxw -Z3A1QGRldi5udWxsPrABA4kASwQQEQIACwUCNQ6sTgQLAwECAAoJENY0E25DnwLKxIoAoPSyM/Mw -BogpyMU5YY+Sj74k3UIfAJ0RopQa8ciickDVzoSVPrGysrnOkLABZ7kAzQQ1DqxWEAMA/wVrlNsP -qTxWZbUiMrUN8MjTFR2xUhuTw3cdvRgiVPUT/q1l1+I3CpopVBx/XuAkg5sHB80zc6pZg652YFV3 -dLoTceS7ridb5k23sHa2hZGCeTo6AdxIOy53giCPDP9FAAICAv9Oh5/OVxUqI+6hsp9ccOEhRA9N -8aJzYDPjvCQyhgej2P1kTsBZqWIx0/PiMvIt+qqhT2YfyD68mHIBztScAXZKTnjroUPKl0+bkX09 -NbdyqojAkzhaCRKUzwnaHEfhi2WwAYeJAD8DBRg1DqxW1jQTbkOfAsoRAnaPAJ0Z/k6Y2ypgDhXo -qBLeW7Lq/AKYEACeLTod6Nt117DkqDz9epmIqwWOE1ewAWc= -=6BrN ------END PGP ARMORED FILE----- diff --git a/checks/seat.test b/checks/seat.test deleted file mode 100755 index 72ab27f41..000000000 --- a/checks/seat.test +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -for i in $plain_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust -seat \ - -r two -o x --yes $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/secdemo.asc b/checks/secdemo.asc deleted file mode 100644 index 343453c45..000000000 --- a/checks/secdemo.asc +++ /dev/null @@ -1,737 +0,0 @@ -26 demo keys (passphrase is "abc"): - -sec 1024D/68697734 1999-03-08 Alpha Test (demo key) -uid Alice (demo key) -uid Alfa Test (demo key) -ssb 1024g/46A871F8 1999-03-08 -sec 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) -ssb 1024g/BC43DA60 1999-03-08 -sec 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) -uid Eve (demo key) -uid Echelon (demo key) -ssb 1024g/7272144D 1999-03-08 -sec 1024D/8FC282E6 1999-03-08 Golf Test (demo key) -ssb 1024g/9DCAD354 1999-03-08 -sec 1024D/04259677 1999-03-08 India Test (demo key) -ssb 1024g/61F76C73 1999-03-08 -sec 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) -ssb 1024g/9AF64D02 1999-03-08 -sec 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) -uid Bob (demo key) -ssb 1024g/E29BA37F 1999-03-08 -sec 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) -ssb 1024g/B0C45424 1999-03-08 -sec 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) -ssb 1024g/EE45198E 1999-03-08 -sec 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) -ssb 1024g/D622AD0A 1999-03-08 -sec 1024D/D2699313 1999-03-08 Juliet Test (demo key) -ssb 1024g/35F8F136 1999-03-08 -sec 1024D/B79103F8 1999-03-08 Lima Test (demo key) -ssb 1024g/FE56350C 1999-03-08 -sec 1024D/BE5CF886 1999-03-08 Mike Test (demo key) -uid Mallory (demo key) -ssb 1024g/4F31EAE8 1999-03-08 -sec 1024D/30CEC684 1999-03-08 November Test (demo key) -ssb 1024g/8B70E472 1999-03-08 -sec 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) -ssb 1024g/2681619F 1999-03-08 -sec 1024D/3FF13206 1999-03-08 Papa test (demo key) -ssb 1024g/63330D9C 1999-03-08 -sec 1024D/3C661C84 1999-03-08 Quebec Test (demo key) -ssb 1024g/A029ACF4 1999-03-08 -sec 1024D/777FBED3 1999-03-08 Romeo Test (demo key) -ssb 1024g/11D102EA 1999-03-08 -sec 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) -ssb 1024g/0F1B50B4 1999-03-08 -sec 1024D/85A81F38 1999-03-08 Tango Test (demo key) -ssb 1024g/101C0402 1999-03-08 -sec 1024D/653244D6 1999-03-08 Uniform Test (demo key) -ssb 1024g/5522BDB9 1999-03-08 -sec 1024D/61F04784 1999-03-08 Victor Test (demo key) -ssb 1024g/07287134 1999-03-08 -sec 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) -ssb 1024g/FD6E27F6 1999-03-08 -sec 1024D/567FB34A 1999-03-08 XRay Test (demo key) -ssb 1024g/41E408BE 1999-03-08 -sec 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) -ssb 1024g/F7B080AD 1999-03-08 -sec 1024D/54ACD246 1999-03-08 Zulu Test (demo key) -ssb 1024g/A172C881 1999-03-08 - ------BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v0.9.3 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -lQHOBDbjjp4RBAC2ZbFDX0wmJI8yLDYQdIiZeAuHLmfyHsqXaLGUMZtWiAvn/hNp -ctwahmzKm5oXinHUvUkLOQ0s8rOlu15nhw4azc30rTP1LsIkn5zORNnFdgYC6RKy -hOeim/63+/yGtdnTm49lVfaCqwsEmBCEkXaeWDGq+ie1b89J89T6n/JquwCgoQkj -VeVGG+B/SzJ6+yifdHWQVkcD/RXDyLXX4+WHGP2aet51XlKojWGwsZmc9LPPYhwU -/RcUO7ce1QQb0XFlUVFBhY0JQpM/ty/kNi+aGWFzigbQ+HAWZkUvA8+VIAVneN+p -+SHhGIyLTXKpAYTq46AwvllZ5Cpvf02Cp/+W1aVyA0qnBWMyeIxXmR9HOi6lxxn5 -cjajA/9VZufOXWqCXkBvz4Oy3Q5FbjQQ0/+ty8rDn8OTaiPi41FyUnEi6LO+qyBS -09FjnZj++PkcRcXW99SNxmEJRY7MuNHt5wIvEH2jNEOJ9lszzZFBDbuwsjXHK35+ -lPbGEy69xCP26iEafysKKbRXJhE1C+tk8SnK+Gm62sivmK/5av8EAQNuYiCeVh4Q -pF3i4v6LDa82cNBI92zOHLJAu1nbeJ6bl86f/lrm6DuH/SYjOkRTQV9mYWN0b3I6 -AACvUW2sEdiVCzqYu9QdI92LJQd2HLYgKf0mIzpEU0FfZmFjdG9yOgAAr3LeP6n0 -SUaQqSNKJPx1Wes66+3KH0n9JiM6RFNBX2ZhY3RvcjoAAK9/tmRCQsDGIXRnEJZM -rvRjIUE4qvtztClBbHBoYSBUZXN0IChkZW1vIGtleSkgPGFscGhhQGV4YW1wbGUu -bmV0PohVBBMRAgAVBQI2446eAwsKAwMVAwIDFgIBAheAAAoJEC1yfMdoaXc0OXgA -niui4cH4ukKQ2LkLn2McRrWRsA3MAKCZ122s1KPXI/JMLBTBGCE9SiYQJLQQQWxp -Y2UgKGRlbW8ga2V5KYhVBBMRAgAVBQI247arAwsKAwMVAwIDFgIBAheAAAoJEC1y -fMdoaXc0J4wAn0x5RWtqCjklzo93B143k4zBvLftAKCFbrlxlNCUPVsGUir9Azxv -P0A3gbQnQWxmYSBUZXN0IChkZW1vIGtleSkgPGFsZmFAZXhhbXBsZS5uZXQ+iFUE -ExECABUFAjbjuFgDCwoDAxUDAgMWAgECF4AACgkQLXJ8x2hpdzS3wgCgk/BrqP5W -blWLc2+6jwlmuLg8n8MAn12puZol0HwV0mcd8aHWtcrfL8lynQGlBDbjjw8QBACc -jdcfV/S7I319mfDvbOwczDvTqDsRbb2cPhQNAbg7NFlWJKtRrmff14jtCt9M77WZ -5W+zTLwX8+8Wy3mMfrys8ucZKtfPixOXVPhyinUUGSq68IArA8vLSUTuOO0LIi05 -LAg6jzGhN9jgkQReZyqxub4oe/3JhIX9grgJ/tsjNwADBwP9GeXmMrGi5wMD3qkP -bzb1MqwsVBJq75eLLxu85JIN2XIAGw6Q0FJp4o7d4BAQqAMzt3ONU1OcCWlDQRDx -j1nynE5ZgRBiVoyudEELgNnYhp3MSEuUg7PkFWn+N+GuvyhVUHApleyvP09kvP57 -hif6yJRS+V6L1ugP0vZmBI4dqQ//BAEDbmIgnlYeEKRd4uL+iw2vNnOO9Y3cRSEx -yy8unuzNvx5GFG6KNtxoFCDzMMzUa0EDH1x/QJA3CgqMpS282nLdk/5O+AphiEVe -Gv8+c6pL/t7falIfSgKZ0j2nvCKH12SobwiNflTGJB+jLnnesjqYJD7h0SVLjToP -/vtKPYlXOU1ZpKzDwP5YcQQuRhF9Tj8SUxScIIhGBBgRAgAGBQI2448PAAoJEC1y -fMdoaXc0IKkAoJ/NQGlvFv5clcDIf1AXjLlTFG9uAJ9rs8IOzHfNWuUSNxdhRvO+ -O7fYF5UBzgQ245BnEQQAvwwkLp4Dtoie4/fvandnK4wVPCvgJkIbNuyQZCarQGwv -8RapBwbANT4vGW+ky2vzgptj21xYjOcdNMIhJ1Sjc7hjs1PLhwepMFrS4/Ple1Tl -jpEgxLZ5UxertMvSTr7OxsA76jjOQt0B+y2vs5zXgLtedux4+pdFxkgM8r6fjZMA -oJ5LVNdVRaSkiHaKZWQWsjfTs0/LA/wMHP/PdH4kjFmDRqOPp+iB8YYwQTPZS/gw -HtUbQhLcFEljaxrCMRZw0ZDMbzKWk+BrrBvgz4Wk3XawwUshYgi8SgwWIDG0jusE -PYOs1hBIdWTEzFVP2pK/NQzhAqJV5/390OLEY8SN4bts/LY1XsADzU7lhE0Oohx6 -FanaZCuGgAQAn2zK53yuk7o8UrPdTHygVn2McsPYYzOvlVfHCSXQ14oXjCs1nK1X -nMIGGM7pJjYpzv/wUZkHLNcHX4uVHXxyzRQ4oMPekncmaR8fu/YIQ9zag5s2GpKE -SKAynGQCKwI4H5eYn+ryIgOHNS44UnXFUwbEsonP5pJNNRIM7VimNGn/BAEDIkls -jKh5E70pJ77zKAq/uP+EnBQq0tCcyqQgQiG1n28iMQy45N5zv/0mIzpEU0FfZmFj -dG9yOgAAr2cvUYCyL3NVUcfw3gGkK+A8ZyTfoBH9JiM6RFNBX2ZhY3RvcjoAAK9H -YClNyCyakk4UDrW4qn8YgsdvZcxN/SYjOkRTQV9mYWN0b3I6AACvZ5Ed3zcwNvmF -Ptb2h6OhMGgwrNan67QtQ2hhcmxpZSBUZXN0IChkZW1vIGtleSkgPGNoYXJsaWVA -ZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjkGcDCwoDAxUDAgMWAgECF4AACgkQQT9K -8xr9q2w+RACghpiwPnn7F3HJsm9VXM8SwBjWThIAnjHZulQw9Tee9XDT5STui+ZG -+WN3nQGlBDbjkIIQBAChY8NSvu6sK0p4D0AVBsRz8iVXYqbRlRTZAHS4LCXwx/i8 -FmfdIXnaNLOoyi44YruSCnlZdh4YWquCx2mgywG589AzcFhahmqElNbKb7m4F//E -GIZK0zTgW13tQwG9hTXOhYeqchnOOaDDwPEK1Gr+2o/5ANqhqrin0TFFBWLgdwAD -BwP/R009s61X/FkUUAh8w4Tua6qndN/2GsqXsyPYjdF5E3gErK8jDcDLniOHqksw -V17bJG81czCRE5JcVFLLWQJg9cpeoTpP+YcF+m9whtswaOJ/LPrx888i/OmluSD8 -1VP+6zBhhTUbpazfLEdt3XczpW7CNdNbyiEcgT+6Cr+W2Gb/BAEDIklsjKh5E70p -J77zKAq/uPsbfaq2h50JWrb/wQiufxaUrYRvo5FjMBLnoUE+L/yG/Hp2ZRZuA5Ez -BpZ3ON5LaFadahL98oQe/W3IXFZwxyYfGCtVrV16zx6cFTJQK/iIqp3TNp/fA6TR -E3syS1FQZIZMiFLvgSy4Tsu4vAadP290Tc62LP9ivC3PiIxt3aqW2l/NLohGBBgR -AgAGBQI245CCAAoJEEE/SvMa/atsta0An3ZMmv9EVWVwEvf/Rwf7nbFsgGhuAJ0b -P+lAOCRSYziWSIDf+BJ9F19H3ZUBzgQ245HNEQQAis7GTDqtEM6luop6eWsxFi9+ -qhUVp9N6S+xlbwzQZVA4FjCqf1VR9JX8fwjLecmxT5xThQVcRqgeFVaCyky2Nge/ -FcFMPZQeaP5jv5GRWc5PvH9Sw8pvGOTB56V4ZeR4cQLDBm5CF5tKu1BCWWq2MLHf -ct7TXe6QCzZKcjzdw8sAoN9VvrKN+EbQC+THzdWaUWpdcfWnBACFWEyLVPTpI1jN -soCZ00F8Fau/2baXk8mdROlJZS6bq54ksfOQQzReBWce35h0W7NeBRp+yeoSf7Y3 -i0jTO4mrOiL/0NCcS8qKNnGKG1irdLes3pQhDZpcUe2G9W3FnGhxl6W5hpYc9550 -mUj2H3I5tmfSYsVcVjpNSIdBizxE2AP/SI1t6q7LHMQp0h3MPQ2z7daMhUGViXnV -l2+rKjb5T7bvSFdV0iyyuyoqvUPBGWwJFLAxj6esHRlQ6W8togHuoJCR7cL2bK79 -8mgYOExk5gBexq1VHQQZN1edK4LGo2ESKrCVtkYwBzAU76hYFKAbKMU8dMxI7DRd -LjZ3vdQ3FNr/BAED+xylaHWcBOTZBCd4ui6NIsLkQLv5uFW66tWYKvc2APAe8oKx -h5YMp/0mIzpEU0FfZmFjdG9yOgAAr0tuCtmJhCp9PoSOTFA2ssaMB7jl+5H9JiM6 -RFNBX2ZhY3RvcjoAAK9Ilc3l2agIgR5iIQnvOgyYUe4duz+d/SYjOkRTQV9mYWN0 -b3I6AACvfQ0dS/51Esd9E/rbG/m1C3qIenSthbQnRWNobyBUZXN0IChkZW1vIGtl -eSkgPGVjaG9AZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjpH8DCwoDAxUDAgMWAgEC -F4AACgkQMYwfrvrvbRtnAwCgs2haIgJu/UEpmCEnojO1zCoaBwwAmgPAlNY/PttA -u6zYqTh2M9yn1DIXtA5FdmUgKGRlbW8ga2V5KYhVBBMRAgAVBQI247gAAwsKAwMV -AwIDFgIBAheAAAoJEDGMH676720bIN0AnjjH9IN8523PCAYk6yD1IFM/ad1qAKCe -nkWU2ZO8/oU8seCQ3HkXkG2JRrQSRWNoZWxvbiAoZGVtbyBrZXkpiFUEExECABUF -AjbjuB8DCwoDAxUDAgMWAgECF4AACgkQMYwfrvrvbRtepgCeOpUG5rVkWVJXULae -GZzqbT+2SbUAn3HmDGXzAJ6lCiYh5NrTIb8A7wIdnQGlBDbjkf8QBAC0pe0mjRH/ -JmKL3mubSTRMKGcd77+l8psl4GtcA6iqNj3g650Q2xxgW+Qb1iL9SeiIJP8KuEfj -6vfPVKZHKkRAfsjnpbhN8zz7WQa2y8kkmqojHoGIh5wAD3NE6ox+1D2WvnySmU1J -OuAQlEDfRC5C9hSrQBkO0TUCWL2wquDv1wADBQQAl3TuGt2SCuYSXo4R2dNZpB2u -kqqHOj7nnTQu7ZVoi1OtgZYxor/w783GzLJ75PfdQMSd6T+Gbyq+QgpaiBvlmWtc -5rcF3ZgnxiW9n2zUlQ+M6denubJT6/Aqfn7yL9v0sr8K7kTrPqAM0lb6DAMwBkpN -8o+Z0+aIpG5/jOtnwuT/BAED+xylaHWcBOTZBCd4ui6NIsGHGb+xn5M8RwQblStX -KFu07GugiONqnqNgB+sywt1otn4dFUWo/4FzJzvEtBQ6EjchWAVKoVYj5H7ExOP4 -BKNDNb9JfOzu9ItHk8TvQ5X7HoV/r9eM0i6MRzNOlvchB1P3Hjw4a2Pj6TwpEBGZ -uuYqe14UAGPlUjHSn+LuhtGpE06zuYhGBBgRAgAGBQI245H/AAoJEDGMH676720b -j5AAn2T9b/n1T2CTa+Q5oGKLAsBIcgeGAJ9kC4ETWfY8itary77dKmyVJetgl5UB -zgQ245LREQQAubUOd0B7cFzJHF5vo5NwiMZ1JXPjyNqL2OWE/XfaeJiB55oMmVEP -mK1JF69wU7ZBpo1l4PEIWcP7WRMqvBEFl+8LnelRkSW95kwFr3D8TRnarZy3kfiB -F1t33dnkVTaZYxCDKOBdZ/ZiRvLa6gZ/KHhITfzaS7h36G2MbAlGlj8AoKQPFsEP -jByKYdx72m5/2Ju/4d4jA/oCNAKaJH7N8Y3HLis1ShhpytJP1yC9GJjtec3ugzYS -C7RKV3NJcBeCX4om3KhiDSN6YYVICf4wdqz6TAocoqPzR2t7Fz6+upxIgh5WGnnC -s2e7uO1eXUCSXONfiDEDzRKGTQjkdvwFo+880DkiGln/qmRrcILA568dwNnOrBio -5QP/dbkpUBhqGDr2LchpkoYyQlqzbvUpXJ1xlfZim1jfrmdfsk83dE3iBzvmT8By -IZcMoqDEHil95LmJp3qw1yVeApP/ZWR+0XiBLEF9GhcAOc5ihH2ACSXLWiRXpyMm -K2/erTvTX3QkAcqoQ1cFWCwNNCrlgycB84Hdm5GXdajp7cD/BAEDMzjCY4kr/Q3j -hyianLh3vPRtiNtOM1BAXVlyCFrMAWM4wvd1NvQzOv0mIzpEU0FfZmFjdG9yOgAA -r2YMtXCKQcwejpJAvOyUDQkN7pMthHn9JiM6RFNBX2ZhY3RvcjoAAK9Jr4qS3ZZl -PdL7YV1+Phgvnly8701B/SYjOkRTQV9mYWN0b3I6AACvUexSWiUCxWbF+aprVRlc -r9OTu8iDIbQnR29sZiBUZXN0IChkZW1vIGtleSkgPGdvbGZAZXhhbXBsZS5uZXQ+ -iFUEExECABUFAjbjktEDCwoDAxUDAgMWAgECF4AACgkQFoQQpI/CguYi4wCgmXVE -CJyjkfpJJBTdGzCjhUq4N/sAn3Cguw1R4rX0391e1pAUuyM4OsFnnQGlBDbjkvwQ -BAC2wan9ScDXLgCqN7CWSRM5B68vC3PCbemYsuOXZjdN8afw2LSHxZ3buRXfYxRn -JNo1pm4PGkMQ7ZpQikZZVCZa+WoIVXYXRnYAjxHhvHW0LaQPvnyFS9H5LaGf2Urs -TWVA+695zYsSaX669XFb9WbiIMGB4yUiXPvQwUL0tSd+kwADBQP8C3sKWjsPh02T -jcEy+FDxWAn4g3LfsOPw8dfawJln+0h9LA0hTebbKBJWt5OUMqjjTq/pCZ5+z+b1 -0f2WwET/xAvjQSTdJjrFX9DNNU3jhCCelEpal9oxsbNYlVd5zOU2RN4hlmj+eEOb -5oy5wy797sQpsbrgGetCTsvPotIpvbH/BAEDMzjCY4kr/Q3jhyianLh3vPDNvR6M -j3Bba3JZVQTKkPeSB3XBJgQ8ssznZMvxlNdGPl6SOlpBYPcmUuo2u69fS+LUzqxM -0unjLC/WRRPWr5QCyg3kJFXpZ5DcsdXUPikfaRD4XWuVPTStcu7NC3YRt+QN0y4m -dadZMjSAwMyHg/oqZHF6HoK/TA5ZTVHNlabj+zNpyYhGBBgRAgAGBQI245L9AAoJ -EBaEEKSPwoLmSuUAnRcjDyrjIbOCDkQfCrpPvbqiHoQMAKCYSE1DVqBk+RlVUp8R -uPmgvzIKC5UBzgQ245SxEQQAyG4mRUQZagjDgl0xAnaSbLCQ5wJqYq/snwCl+IbD -lXcoHqXQNO9QJrPKwKQAUv3Nvk7mqZWnfMPoskLOASrs6nkCv2Fo9Aw6smNizO6i -W7xXepwvxjho4hLnE00oGPCDhUnAU05LO2pTBoxwHVs0o6vtaaViXk0s6dOFCoVd -f9MAoLjiGlK/3DFWoUrqIiuE3aLfgkddBACrp1snJ1BtiGhmKjt7An6Qoc5LVnU4 -1J/REiQIyitUFAvPX+fiqzDyE3VD8qX/vvTLpgZCYvvEdBlSfM8IcCn1/Qh4aw9J -HzuvKQg8WclvnQ8zq/7RV9J7h/aS/KIhDJIpGhi6YfjfjdSKfLYYfr3S4TVK9xD0 -Za3AH7/lrTqW8gP/fpKWu8fJyJ9kqHyYrI/j4ykt5QKBj3tHjqCv7FQb4FY8txnN -3fLzBtva/tlkSKRsLobixjZUGF+uQR1dTCv042LxZ6aEUqrUytxqUc05pCSAvEZV -8bX2H/5+ulSwdxKEzs1h2NvSTAiZ54zzKGjHNmEitdAaPD/9u5xdAiqPFxH/BAED -CYhWuhxneJYv2ZhcXqW11qNlLO3tHf4QWPYOZ9bRChm0UzW5CRik8f0mIzpEU0Ff -ZmFjdG9yOgAAr2JqCOINgV2LqfCiK4s7X0mqwBz/uAX9JiM6RFNBX2ZhY3RvcjoA -AK9CmjU0rQ5lHrAdn3TtY6fEEyaU9UBx/SYjOkRTQV9mYWN0b3I6AACvdPZBZuBl -tFtFIRj0/+lL7Cm9daq3wbQpSW5kaWEgVGVzdCAoZGVtbyBrZXkpIDxpbmRpYUBl -eGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOUsQMLCgMDFQMCAxYCAQIXgAAKCRAf6Pxv -BCWWd1pYAJ4lvyDCV/l9oXkJOzNeGL3Df5u87gCfWm5F7YsIhi+PR7BVafFUBsWT -w+udAaUENuOVEhAEAIMMgk/e8lsV/KEkd4/jNK4yFj5iy/Faon800I3GUzETuQA2 -AT3getR+GuV4pbZWE/80b9hnNW50UJGiP1+SXfVtY5vT8p/gNFwn5d0O/pq3bpgF -RJmoawTzx8SFDwCVPHEcwOHE2j5LvfrvRBOyKU32tr976ri+Uowt0+92LuA7AAMF -A/0Yo9dDqhjR2UoNcYfEZwWhRHaaJenP3z3QbzjJkASb5H84xCTEpv0dqEtVTJUo -Io8Lh5VjbiCwok4QPLVSbQFeHqTKb7N96PjevkZ1Co6OrLCNOcPRvXxgCwSGbuuL -MkQJEutnXLu0DOKquY94KXXh79La7lTgjReE/1Wzbgc1+v8EAQMJiFa6HGd4li/Z -mFxepbXWoDrmIq/iTdsieZ9YRYA+rJ4OBtb2sjqV2L6WYNOqc2qDSj9QDIRJ8yiD -ysA/4Yiur+UNBqRtJQGroegDXG4+NHsudnVzGXaQsgEqAjZ9PZEtsrEf8D89NeZ0 -3yQFkAXQ3n+aCf69jmau/Yf2YAX7D8brkxgQp3PCUcOgGv8EPo9r+AeRiEYEGBEC -AAYFAjbjlRIACgkQH+j8bwQllncJeACaAqT6TL4N3gG2lLQNzV6gMd/p3dgAn2/2 -mEgFb3CkorWwdW++wf/YThe0lQHOBDbjlSURBACcp0BogujMnThXpn4UjBARj9oX -gQWskkhz657AXu6RmX/u5RmpLGqbNmNuqKDIwUbJslIxrpOnA3QEobkIl7ThH+ZU -IhGzPUnHlhd7M3dQWw1U0TfpHyXx3FYb7CCPabrSC7hWWh1ylUxz+RGJJSApR+D/ -GY+dF7dIllKUbaUGbwCg1z+vkNbzqibcwdYrwCjKG9VeFa8D/A5yPHqB9NMp+3Ol -AGE4XRTR8LeelALpu+MuNMGFCMLdZfmt/Amoyau51FsQ7WwWrNM5A+1v3Fq0x5Wp -Nw6Lr7HbN9d6zidN+L0uCrXPweET8ueS3DFnHI945epe703TbcjJBO/uYLn0LXEx -mTg846/1ZlQbPgLzmzb/2JMkJ+QzA/4xFbRL2YeaKyu4JjpMNUVzXYogUwg9KZZq -/qBbpsIAD7Agd+ZxLJHoweItXaC0nS9C6qDJZ95OJrE+h/Tt2D2lmxXseTVlSESa -Wh45x9mbC0eRGFYYRsSx3z0hYwMmXA0ntj0lndC8ru8HjZtBW/KF0VB0RcfSyW+W -+yAq0Jxo5v8EAQNzQpmchsGqHF94WG/VI+1oYlA4rI/KYT/DB+zHXBquIl2KZoUR -ebyb/SYjOkRTQV9mYWN0b3I6AACvUJB07mtW6/9i6mmuR9JtC7USM0AP//0mIzpE -U0FfZmFjdG9yOgAAr2EW7SJ8fPMvmLE8+Kb56tIqW9FrYAP9JiM6RFNBX2ZhY3Rv -cjoAAK9VpNLwU8ljMnpHbTNr6de2pplMjS3ztCdLaWxvIFRlc3QgKGRlbW8ga2V5 -KSA8a2lsb0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOVJQMLCgMDFQMCAxYCAQIX -gAAKCRCtGw+tQ8LQx9USAJ4sELIj8IZxlvkwqmmEMXtm1kIhQgCfZEpMtTpkRbT+ -rEHMssei72JJi+OdAaUENuOVSBAEALmZYtP72G7OodR4RfR270RxTHj40PfUpPIf -3U8ezyO3kqjB12IdD2YIXIZW6zEj53psX8DGya5nSvVjdFofQSVHtsnB/H7VHBka -OQnREoInHs4helYOD0M/RZcbRIb65e6vEesuzvo9N0ACSlBsAXbeeNKGfGGCog74 -GVGcZ6HnAAMHA/9W9n2MwJ7lq0GV4V0EOHDVcTAVRSh0nB9uKBVW7hFi4DP7XYBf -gj8Nlbc22vMkkdSvNFUoLEH7Op9sMglXfiCPJSh02U/6XyAhXDyZRyrOIHviTZ9S -HMQQIqtEETVuYRkzvSnSfDBVq1p9gW6eZN9q6AM7gmoKInpRaODFRWU7Df8EAQNz -QpmchsGqHF94WG/VI+1oYTZm8S4dmnYvEY77B6haPMQN5nCjubqfHGGIMJxRRG/I -HzXq0tNi4fusoLILtVbUgta+94uzgnsrUJqZbfmwrId96U52nG82ZMhLpX41lZ/d -LZouCr/jMO0uvF+WYMjO04ffBfcnNkeQv0p7WDH0zZZjuJ0aoUwBM9xxU3lYTgzl -aZi8iEYEGBECAAYFAjbjlUgACgkQrRsPrUPC0MeO/QCeNYtFDXrr21NZlLu0OfAe -lPBM51AAoKglouZG0f49sm9tHg1Gc/nwjzzhlQHOBDbjouIRBACKncc4Ueec7dWa -VARy2SmNVufeSenYs4AsIPP0v59jEl7JI0rb+4JbIJoAzW/hcm26GS/UbbpQwig8 -/PgMUV5QfBST4CEOlf7/x2a4HKk9tDV4An7q2aNr1beW+twxfUGWWV5I0o1b/iKV -k/LiQRiaMr8pJXY266m6/2Pn9LmDtwCg+Iqfx8gsK2PZCWv87uEKAOLzHXsD/1eR -xLqCt1hT98gdDLykRTlI3kMq6EK3I+z/8pDIMDuPIJq1eM68YdFZr8s7i1ye1QpD -ltPYHgWnUC733ujAKANdyybm3HrA3TSBjEAhNfcu8nkrVorvASQUDCLJatWRWJTU -VrPH+GXIXMA/Oi6LDsgNDOJanwzzvDCCm8hWQqW9A/4xYAZ4NVFrQq8gtQPJWuMI -fSFSvpZWNgQgYZntiXSUGYOVs28T/87RoRx02tsVDw2PA8z68q/XRuM9NdetxbUX -QHB9eszFLi3W1idsXhd/C4SyiTgEFXG8Y8s94Eadgk1PAYHN6Gd3SY7jmevqYGVL -mBp7qfj5Y9XSM5SE0Th+fP8EAQNn55Peu081+nAbRC00SOkO5P3aJwu7AIvXN9Ng -rJdUW7TQmQK+cHyT/SYjOkRTQV9mYWN0b3I6AACvbK2QUpz29Yo72wl9Cy/TCjWc -O22z5f0mIzpEU0FfZmFjdG9yOgAAr3et3apzZ+S3o9ywcdaosE2TLfNzuX/9JiM6 -RFNBX2ZhY3RvcjoAAK9PHpBSB/T7wKTGFBngy9sOwtS7ZM3ptClCcmF2byBUZXN0 -IChkZW1vIGtleSkgPGJyYXZvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI246LjAwsK -AwMVAwIDFgIBAheAAAoJEP4YCx2p47CybMcAnj/BlcF5gdhj8huiFijkgZZi/YgA -AKDxpmP4JCksz+UPKsQ8UbtuTPbpPbQOQm9iIChkZW1vIGtleSmIVQQTEQIAFQUC -NuO3OwMLCgMDFQMCAxYCAQIXgAAKCRD+GAsdqeOwshrhAKCK3IrzNqME6oA3RllO -rx87OCIRggCfVkR+Nf6N59lS5j7jMXOuk799fQ6dAaUENuOjBxAEAJVJ1fFRaXPz -UWOoeBHhvUS2aGZbz0Kamwd8qVLCVi8G1sH/LtMUh+8CvhkVum6p7Dom+2MgRmhe -+iVNbAdU8QWS4bQsBrTeiVpinMLpkEO4uRvT1G6QIPjN1jrHBsAxGw7NmC/n3stl -e04ssueY7JOmyNEMvO1ay42CWbmt985PAAMHA/9LJVm8UR0RWfn91BOnt4C1d2tt -kQzfv1y0InbrrdFtNl3nmUgF6/V9OcpCS8NNjZ7nzIhDgT43Ov32qD0LJ/p7c6ES -tNSoQE6G6wGB7j/sTkushUy+joAVT2qCfRKCye7/DDa3FXDdcSOovweCX7hD/nth -G8k576rb1h70svx5qP8EAQNn55Peu081+nAbRC00SOkO55yVYRTuqV1cyTx/djMo -oC9B9hYiXA8kcUn/RO3hztHVFGSYQWYNhOGBPe+FrUFfY6yjGeS9rlLKQ3oaGCr6 -pvZYdIBdzktW+TItDPYmRaaBTKrBw8jmccsn7xnEriVcgkSTTMd706I8cCIQh/iK -iM5pFZGPPghQPn6paS6L+ydP0ZNliEYEGBECAAYFAjbjowcACgkQ/hgLHanjsLIy -uQCdFkPnvUpYurVoPjhg1pw4UzuaVYwAnROb93OSUP9PZxf4XVJwHKU2PnCUlQHO -BDbjo4cRBADeZztXPNYwpoIf6BfqepImZqhVd2qXuZBJnEvwaFoAl7er42pXXLZh -WIu7/gWODfcyNxsUKgMbeQ+nWO2jdcZQtt+gmRAGl1F5LbxsP6aRw43W7PAkbmYg -PY5tY/dhgFGP5puoV9mhijpFcK/cjeg6wNgmjuEsCv8BF5FX4/p2swCgwmgcx88E -pJF3/EDrTk4/8Xr6Z88EAL99JWgnl0w2TNiP9T3c5mtVdcYs32ntJH82TiQQ0LR0 -A7zRY5ruojNZC9LsTht5K69AJakrDA/Fu5mr2xYoFJcW4b7rpeKUy/wYifeOhYY5 -T2NDYvaZnQJXZ6O8lGLFgAxCmnZEN4IRFahKs/gAmG86d6fCvuSrohSZvQ+Lsr06 -BACFT4tjfuL6MZ0VhsClxeBPny2AM10+bDDM5eOl5ODLN9Nxf+SRu5AdIojz2OqD -9Jd55WobpUXGzTI+0g23636IuJuH7VGCF92nFwkjdIDblRoqYPAsJRkMiC4FkRae -qF0DpgJacYSBnHdY3Yd7I+cvgkK7oBjzTiU/Zs5hZAeK8f8EAQNhroQ8vAawUbBJ -GAm7E5zNoXK3ly9yV45/SohVZDzODvOlo6LWymLq/SYjOkRTQV9mYWN0b3I6AACv -VTx87uYeuay/ZhQKJudCoAgGZGdML/0mIzpEU0FfZmFjdG9yOgAAr34g7RZNSO3G -bdz8PNLxVgFG9ZaKo7X9JiM6RFNBX2ZhY3RvcjoAAK9YCrkTYjGM3LHB50POLDFY -Z1O3Mu9jtClEZWx0YSBUZXN0IChkZW1vIGtleSkgPGRlbHRhQGV4YW1wbGUubmV0 -PohVBBMRAgAVBQI246OHAwsKAwMVAwIDFgIBAheAAAoJEOup8kDrncnmriYAoLZf -OyE8KQbqCKZA2lLbxnCXr2G1AKCnWAeL/6RLjuyT7ddG3qd+ggEnB50BpQQ246Oq -EAQAj7WdaOJjzJNs2G8rvrDZvD/uaALQ9PtdvYAp/Drp7xMH5T62+KKTlKdO3s8I -QBPiuFocJNir5st/nm8Xl+gcOZOvtr45c/cl54fGO1gOjBZOfgbkdBVK/LMwuQWI -ebK4qCZnAOlDLYNGVUguGLnEQBSfnhhkgh0WA0kqt7fYvpcAAwUD/3cOEqPlMdYe -LnGEG4wPxtyVIchwGOv0YRW5apbz2fdO7otj1AFUN5WzFw0A5+WHza1OIUhg50Zc -o6HnwKx6F+LbZ5aOc37EAvaFgPuMxBfkaWYagCof3jBF0CbTWUXV/D5/dFmIeuGT -uUMNsGVH+OSMW2hBN/7+aJK5LLHL+hzp/wQBA2GuhDy8BrBRsEkYCbsTnM2iEIZ+ -jDx69i6vtiK2mS5+ud0+9/XEd1foHMXoByohTsJeUvbwXvAu7FvDdfroq3XGvSjZ -+czTMIekzBbYRxC+pPYENNuBn/e6LTKQD4oVW+uQYcPax5AvZeR5tm9RPxuQ1EYN -AmHR2OEtmE4zSbqGtrnsp/a097bTCnmxH6PsQ19HSseIRgQYEQIABgUCNuOjqgAK -CRDrqfJA653J5nNNAJ9Se4OBQyISgG6RMM2e6+frY01H+wCeJmn1SGKVrWnZeIBE -j+jR5OSAMDCVAc4ENuOlJhEEAN1bOV3WXINYOoY9LMY6x6FfJNJrSk59VMtySkmk -OkStyfyNLxwqteRVSjAjtKVmE9GZgj7mmoZobkVnlUl3VN8paKFzs74kMegrfJqY -6eHo4VAU9lQXX5aUAaIVctz5Y4PNuA5IzL/zJcDqfTN76/d63mf0rOJvewMaPDkM -yaJjAKCZTCeh+qyQdW/VLq0ODTyZcAsoowQAhUbJ/2KPcHM1vR9VgZQ4tTTuepDd -Gk1A9oq09CkGhtGSdD9lJ3O6IAtwIH5Drrh/VwoYD46C2bQv9/XFSYpFbetP2XMy -1wLLqRy50IjY4eb+A5w/MqqOPmiekPzh+BHgF1ux6FPz66ubEWIr9sUUjp4LUvl5 -0FBxEuztMXaNjdIEAJ1fL3IeDqINMmHKy9HtS4tYT/Wz3KyKuFmA9vS/IgXAd9HM -z3oBgg+ktmv+O+SsNrBPFgZ8YhmuPtTIZ4+7tEJ4VFVVfnkHp682/d8CpubBDUYd -NftYcI10CQ/TvJPFn/Cdm508DNDBGQR9nf1N1xxs6Ed8e9u/dE1DRXFta1BS/wQB -A7n3lqEldy5uprCBgI7BwpM0ElWN+2D2a9LgElCF6MeTnG4Ycamo4Gb9JiM6RFNB -X2ZhY3RvcjoAAK9TlqT8l+FZ3rsTboSXkdYnCZZwh4rd/SYjOkRTQV9mYWN0b3I6 -AACvZXMVrb4dxU2h5sKMOGXEpcHs+DuVW/0mIzpEU0FfZmFjdG9yOgAAr3vtqeEa -itcXHtaGrkSx+21NoZaKkS+0LUZveHRyb3QgVGVzdCAoZGVtbyBrZXkpIDxmb3h0 -cm90QGV4YW1wbGUubmV0PohVBBMRAgAVBQI246UmAwsKAwMVAwIDFgIBAheAAAoJ -ENS/V/NzcuJDdy0An1AXntULu0eTFfoqIj2gIoRR6l/kAJ0VIXasNn5cMC6DtduH -/Cl3BCFW250BpQQ246VQEAQA31Qj2MGefTCoF0x+D+9UMxZ6RuBPzI6gzX1tzcUP -WYy38NIq+lNYBg7hLFkUfn0uTsAm33h2Q8z4/DGT7jmQWpoIg7yNTr6681L/gYo5 -FhhC+qERZ1iPMyfMwwD7rrz9bthUGTqChV2h6NiPUPM7ic/D9rxJICXy8dsoj0dQ -6dsAAwUD/0ggimQTUCGmNHHypor/GY0XAAL4Vy8jAsC0FH1UaqDVTrTDH1qWLRnS -9uxEsOJIGSLMSdxC0FZEYq4jCm7CYjTOHTHvvYDbhs9QhvW9r4VD2efbERFSEYMi -H69ASQLGDp/O5kOZTgQOvl5oxzvsrOMaRFSWcn66uUAMORmHKz1g/wQBA7n3lqEl -dy5uprCBgI7BwpMwsmLANtSNhKe+VmFkvN9msymkZ/XyA43Ts3EpgI/RoP2B4GS9 -LyuCC26DEqGnsats++yae/wDoWz1mM9tq4UcML4hSHIbZnG2OEZDIiu1q5aS1I27 -UeWhA8+qPhPosw9cJ3Y3sQIgdIEiKzAdfsjhmE78aSpljhGnFumTVv9p/lCNuAGI -RgQYEQIABgUCNuOlUAAKCRDUv1fzc3LiQ475AJ9aAil0KqenoLziTexEcc2EnFmR -uwCdEjwBOoJFx6qltIM/tJcxqRi7qu2VAc4ENuOl2hEEAKeOL2pIdZ+zQtehxdL9 -l/uDBFSTuN9rLb8DgLiw8Z9j8U5CEH/M38WzH1nHKKlZKjGVZYiyhRfAG83wvHnT -83lq+Ad0lgaZTR4z6nrd5ViOlHPlfqo4RPZPzPe+uF7EfDl792sJerXGAasLosmK -nxKAyJyVjh7eZcjTS/hUhO9zAKDVyLHJ/gQlMYk8vE5XYL7Pw4d28wP/VsKVkjlx -sXpcrCQIoKeDXgKNVv9L+0Pebspzr2WOah8iBN1QOkbtexIKCbb9mmviEnJU0FFx -5MIw4mipvY4EpCaH3McGwJpCzWmdzID8Z6oISUyKsuP7PXjmASbogV6Iqy2m/2RD -tfbIlbwotfbiOT9Tr3IPbH+tHAZByMRyvxID/RN90WOPSpODxr9AH9btmeJD0BfN -t99116+qdwvWrTofcbkBgzvB34vLLDaMKVIyinxz2lYyC7aSpA3uzjZvoPvPrQJF -LE0dx7DSkUTtWbQGByRabpyrXYdKZzsFXLb+LSTWwF3sQLax0C4cYT7OLPlxjDVq -/A0jgztaZVWa37IY/wQBA4atrlwHD2LVQWW8aUn17IvjZxnp2Z5Em6q1rszts7m9 -rXCv+fKUFF/9JiM6RFNBX2ZhY3RvcjoAAK9hYwqxHjc6iHxWUSLF376lmCzbsJxV -/SYjOkRTQV9mYWN0b3I6AACvYBDzN17V2d/ZXmycyHFyOyxqAighH/0mIzpEU0Ff -ZmFjdG9yOgAAr1pTL8K2pO6rbaqNJoTiKU0q6XdGAj+0KUhvdGVsIFRlc3QgKGRl -bW8ga2V5KSA8aG90ZWxAZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjpdoDCwoDAxUD -AgMWAgECF4AACgkQE9uWVTTG4/Hs1ACdFOYsQ4pNSdT9grdhmONXKXgVRzkAoImb -lC/iwRti3/yZ8Ljc0tEc4HTPnQGlBDbjph0QBADOk7pS4JZak/26nkZWEs+hIIF9 -IgD0labkCnr+GNDmGJrsJxLwTjU+NoaXo+SHmWPaqRJQFrz3ZJfJAxioyoSr+Hv4 -Fbv6frZIJEy1g4dFhk8DiG+zR3uPOcZCUyyW3HupqahU0/RcX7CzXAcuPJCXeoye -SsBDyUAk/6ODs/kerwADBwP8DrWpAtFexIWvsswGdpRJHSjr7j8cJ2Hy36acB5AE -MCSd7kNM+LCrOqyOhh6RfokrvCT6ZuwlN39nDnkmSr3FWbqcRSj8khs3tw+Uyp8I -tqhL621vFn180I7dZM11bECv+YZlmIF/L3JNzFR+jmpODR99bLjQI0dpUqT6IhyS -0bP/BAEDhq2uXAcPYtVBZbxpSfXsi+AHAuizXUm/50gOqDPn9/AvgQnPzxgeV71O -aUzUKvZEVIC7A8eNbmLXooM3Kc6ppaVOy1l6BVNcHA+iAdEOnGL9e46NALwFz+DH -rt2umY2banvt6kYyWqChnp6vnk8O4CD8ufKnQ4c3zfSul69uuUA+l4e5ZG8V5yUo -ikTP7kb7/7PSMohGBBgRAgAGBQI246YdAAoJEBPbllU0xuPxJmgAnjzxkJIErPw9 -iJ/WlLv4gvPY/IhLAJ9WR725AmIjPEe8YqhNfx5b+Va9CpUBzgQ246f/EQQAl65u -b9rEKS7XsXwNkvGtj1K7gnql2H1bJ5GF9bGCWhWmB8WFtsAy9XUeC3WbrcuWFgTs -btTfXZ5I7j7HSG6ukf6Ycusb+bA1IoT+GAQGWpFeWoXe16wXZFl0pEc2iUnx9Tht -oQF0fO5YlbvHJPEQ3kvoqcdb52WOOfOuCAJxc6sAoNqo5w0YxgJ9jkj7J4cmR+OF -UEKXA/wO0jrvYE7eiZeFUjGNiRotxzhTzh53rxtz2/DWG3D+IBFOt4qqxxp3WCSN -O5SnBZWUW50hDkhTxS7jSmsfPBmCinmQ6EF5FaFPyLQBq0uKwhMaWficdrQS9syX -FlPuzQ5jOS3kVAxOmtDd7CMTC8892dj02qzAE46QNNUI91kZXAP+PINfoJ8hV2zv -lGZ9tVlo+Lgsl1BOvxvEgmYV14gyTmMWga5sNq7TdMdWi8Fz0Vy7sI4S+RMJ96rM -ws2iTzWLi2jGO44itoWttCwqmGJmlSWurRsvYhSBgvNCLXFGGaQn5ncO1tqKnWSD -f625UnAipsgW8P4Agd5qJZiwXfJ67Hj/BAEDu6tMael+rX7E/usFH0MyFQczfHWC -g6VkC9TYfdLwbBVtdcq/lugvQP0mIzpEU0FfZmFjdG9yOgAAr030xCMZovqQobPR -re1kY7ZER8BZq7H9JiM6RFNBX2ZhY3RvcjoAAK91zg0swEPwYMWjD9p9kHpjle8c -eWvt/SYjOkRTQV9mYWN0b3I6AACvbxuq5MH2Yu4E6hH46k0+/KnqrsrS0bQrSnVs -aWV0IFRlc3QgKGRlbW8ga2V5KSA8anVsaWV0QGV4YW1wbGUubmV0PohVBBMRAgAV -BQI246f/AwsKAwMVAwIDFgIBAheAAAoJEAyCDHHSaZMTQPYAnj5F4su5N516+dcX -YBl7cLVDPp1JAJ9d2mO76rlmINaaTtH5lhApIjQjEZ0BpQQ246gqEAQAkdlSJYfT -iZH/CkfV8tnhI6IDz+SgiZKcneEBnO+hAJottARGAojdbURlOIeZqRCgKpdTXBK7 -MdHAz4RKFnAAXPDBZgA5q+Coqn580t/O/AKGb8kKn9n52z9lC8A5KnHaRAsOKVyP -TIU5vq6FLmsWmMB55iz826Dk9kMhV7mmdQcABA0EAI8Jq3Jnqf0HqqaX7CZuNKHJ -gag14bTaBw0niZK0KSB6FBpzitEoyst5JBPCl0ayQEw0Hn4jhZAqcZybI//pC1CN -QBBO47VUi0y1UVjExtaNmmWxugzkzWHHx4WmyWsCQwGN4B9riUws4g3dgC007l+a -onKzj5QEo1XiiMNTFFmP/wQBA7urTGnpfq1+xP7rBR9DMhUEbuQV+5mF3JEYDt0d -r9Ej9Ccl8GT/tOi0QsPNbtaWED6pY70iZMVJSk0TG7pZ47FNx8UHI2bJKWWjCF1n -uXV+mW/xLMM1GgFMwK44bX2IsEJVqFjB7alBd/uj0ugnj2feFeTao2xDuSQ71IjG -y/lFtOkcdJOov7L4tNh2/8ag6bbuZKiIRgQYEQIABgUCNuOoKgAKCRAMggxx0mmT -E4+uAJ4+JbldpmIpRDEuE8tFCnHacQr0/QCeLU0G5RaI4jZI+QUKtYiXq0ITUnGV -Ac4ENuOo3REEAMFaZuaYHLD67UlMCLHGPk1dFdAn3Mu2TFFDUYfEtA/JDOiNZacP -iQSZ7zK+wVe66Vs9fzNkyeXqpwLzC35vkTx0K1m69Ave9LnXIZ70zvpVEL/UeCuI -TRiocxNglPgn4dyJ+2V0cWJ36NGcZmkvBW0vGItpYCbpIGLzYVOfiVUbAKC2Nze7 -9Iyw+DKU9HI39B4fz85nkwP9HbIb9z5kXiRZyCaXOMnFBQ3bAZh4Og5ZQxdLyZ/r -IX4Mu3DGjqg6UtosdVNHr6ofZWHPXNqqTUivoUmOS5Qa8dtUW3YGa8vbpK1OMnjM -LhQVJZg/eou99s9OFP5GgPh5r5Vw/EYQZ6qzS6YiYnqzSt5LcolL2+Ae0ajXUizi -c/UD/0TNXtCRfkS4SeVSkZXarb1oZjHdGlw6ENiLGiA0e5b4r0rByW4EQQGZPvg3 -DFXMjqp0lVVmfmXFPggLkbTP+SJ1/VGSC/wSqPkMiKSCenRqwHwWIdKxv7f13hye -TZXR7P8uaSddSXaakqmT99v6pdZOo8NsVQTx3PzPKpEVciPB/wQBA3B94sZ4BXVU -UYZFifR1y3VNINM8s1ZkPHDNwxOmQwK5PkcxqfpPpGv9JiM6RFNBX2ZhY3RvcjoA -AK95UQT4zAahgt0Z7gBkqnFPjSb7Fn9j/SYjOkRTQV9mYWN0b3I6AACvZij2NXRN -N8KfYKoU+00zOAYGp8PcUf0mIzpEU0FfZmFjdG9yOgAAr2BTPmLEX46yXGfFOW40 -pPQsV5wHy6+0J0xpbWEgVGVzdCAoZGVtbyBrZXkpIDxsaW1hQGV4YW1wbGUubmV0 -PohVBBMRAgAVBQI246jdAwsKAwMVAwIDFgIBAheAAAoJEDfKtR+3kQP4ilwAn2q9 -qdnkpFPi1neWFi0OEOr5le7lAJ40e+wQHgKIE+Fn7sjYQ0Liwn7oip0BpQQ246j1 -EAQAp/Ccn5EzxXIGljKVKZ5Pp0xJA3uBoQBvXzu2pU4HU+vmgwnX1313x+4BsHVE -bw7+lfyhKnDD0TSwIAHj/xeE+jraCTU8X1iwe49eAyTaWF4wTyTzdZKQ9mrfBnFg -dWlRjLALcTMJaOE2Zasn8wgAEHgi4QWyBPS1il+aFE6oizsAAwYD/RpvJnfv8Vqf -bCxOYt7meLfTLrvcPlGNynv1nEgNgjbYRGIRzbXDDz+jwcLc9MeNuZgtaXvUbsQ8 -s0X1dP6vq43VmQTQPlU1TQx10o+YYn73ptyhbwOkyIDGmyf6uFhO0+B5/MY0KRLC -xo0lwMxvVkYNd6k804pSJPqwusWBm2R0/wQBA3B94sZ4BXVUUYZFifR1y3VOfk4w -3PRZvIRE/y8bsqADpUHOrpzhg45mVJx0XUD9jUsufCzZg7wHdE3KlnZW2cJ+HHoh -up28Ie38bbaUVgfofuur31BiAVojpu8KhTncGAMb64oNfdRJapHzzBcuUigQ9ETt -6OPgUE/thuHws+GpxQe8KhGQcVfJwuRernhyJhW+BEeIRgQYEQIABgUCNuOo9gAK -CRA3yrUft5ED+PJaAKCkicGM/NGxdTvpyHhtVSSkTRV/6gCgsnKOr6ziNIo/Bbdf -RfYDd1dL4lOVAc4ENuOqZBEEAKLUF5GqBMWJQtBs1t1Sp+NIOGuMLgJOhINbMU6t -k2jzeUt6ooNd+c8P0TexsbSETwhrU4ntpvIISb7I8Twhcled7bi5KCABJOzz7Fw+ -Ydxo5Yjm1DQH7+gEtPx3n4AjZUfRAN0nqcFizDpRYPqVaN1QYiGWn9yPF3pubQhV -n8zzAKCpx1LUlQl2e5t1YJhmom2qy38EeQP+IB45FBfDf5KKtyS64alQ0vHYIssU -p806PQorw/ZOuoiscUQj/WeZ4vn7rCdu60uR1EuHpGp7n0t7igEgAOcxDjrxJmpg -SdD79V+oJAFLATo2msj1IklVvJeI7ZsImyPchIU1lqn/GvpAam9N+FiIB1KUMFqT -Jzc6zUn1Qqag1w0EAIiRHPYRW8ojd9Uh4Ed3X0daAnClyMWL82t2bj/bJRmhupQn -4aVJ5D0pFB9izTiJEWciHpqiMdsi/zExYYIDS1Zu94+WFbNIxyMFfHrJ5fUQtAqL -b7E5LrlxZONUnrRwshqR4X2TmW2mz1Wop542eUQ1UWp4Gr3VlH6giswY0CnQ/wQB -A5YOFNcg/BY3BMnzmbEa9r4DVqdF0faqHCAPM1GU/o1rZ++VSNJruLP9JiM6RFNB -X2ZhY3RvcjoAAK9h5T6r3UXJdRJYgiPBeltuXDZLCq03/SYjOkRTQV9mYWN0b3I6 -AACvXXkGa4lux84ceaJy3CpOkPW9NxGnh/0mIzpEU0FfZmFjdG9yOgAAr2H8Yr3s -FEe3lYbWaVBMe1xHDnsfH0u0J01pa2UgVGVzdCAoZGVtbyBrZXkpIDxtaWtlQGV4 -YW1wbGUubmV0PohVBBMRAgAVBQI246pkAwsKAwMVAwIDFgIBAheAAAoJEL55SFK+ -XPiG8SMAmQEeRej4CyoP+wmpdhNm+c9famN9AJ9nKsCqRWJ/ufezi0YqAcbgbaNQ -5rQSTWFsbG9yeSAoZGVtbyBrZXkpiFUEExECABUFAjbjt7cDCwoDAxUDAgMWAgEC -F4AACgkQvnlIUr5c+IaZ1QCgqGtz7Pnbid5+UylHAn40bwpXE7EAmwVmqbtsG1iW -Wt1xOo2oyTj0t8E5nQGlBDbjqn4QBACme9aNjmsy/D0vLzEUvj2kaMBgVv3MWKO+ -Abi0yKsjdP0QEt+UosnybgpahGhPZ42bL8kYsfJmO95pWHxN6sNX67FmQQa+/vTa -fPw04SVBOMdYejLSfqmhyLoXGF8l3Vuc6MMraZkS58RA1KfY+EDjqCMItFMA+7Au -mK1JIvm5uwADBgP+KP0pE7r38nHf5b0NlDFYhAGIqdgdWvW6zZal2lNXiOkKok4I -6AH+GUGYJjULX+2mwCPUDdllqYlFZVmg2iSRF4i1ktd8ZpymsZuaaNyDz2AUzlXe -cRQ0JT+abYFBannyHg04K/rR0avkYCocPEBK0+TfzzNvER3IWznsI9Dhkm3/BAED -lg4U1yD8FjcEyfOZsRr2vgAw2DSsek1WQcJVSrTcrl4DmC6JoYKNZxcZxkz+azXG -MzU6P/gruBQX4ldaWq8ObvjrdF+g032GXju9Olh9Wx82E+lc4O2K5kwNe0fveQQG -7vFrmajyXnIB4myEx8jSGNcEUcl/6pMmwjzIOMcU1lPVYNkZU8cFQpZHJ2dY0OO9 -MXpawIhGBBgRAgAGBQI246p+AAoJEL55SFK+XPiGkTIAnj6CpWQaP+vvx+HhzcjT -cL/VKlZQAJ9Nk+d40+pCqkNEZDcV/xO6vXHbbZUBzgQ246rjEQQArXimh2e6XDO0 -Lo/BHPEsdHyd7tDXS7KOcZ/RJOBVjCwbuo8O2/+SowdlrVzmUlihzs3k31AMe/TT -Ciaw/Y2Vv9JBABVXmacGRdZfHwbERC0fXMQGoxN0bxZIAmAIV7BdSZ6PqolOUzb2 -nRlOEs5j+Lzp546yFk8vN5rWYsKBSHMAoIGmmgpRPEONTciH1bY0t3/jZvMdA/4n -B/bsDN76QdkFdvSCAams4Gha+7waKIBaAJZWgkGzy4sh19TJN5BGYOcXsJg0v7VO -Kxqo+1HC/TpWcdSAg/HKfNMjWH6COyuVzOrGDjJnyTkRjhLKjLaGG6N5Zbg4A5IN -ug2Tcp1HhR2UayFs9nCqk7mgd3cNPZvLCTbrN6aBLQP/UNSg7Iyj4vPtpFMyaCt1 -etUIJVwFQ5X8yugeSjhGehkf4F/TObssi40RMmxUkjT5by0ddfpleBkeQHK1UDph -NEKRcqNTK/rg7G6sJMxEb0ata+aTsqjOVj14ZV2uaKOJ2tXwRF++iBMyusSFRtOx -pzZ2mPnZT4LC6uCPPgNtGRv/BAEDsc7YSdD9O4gyqEDz+24vfhBH5b1jnJJ9MOul -ZipNjfbpG+Tocn1wYf0mIzpEU0FfZmFjdG9yOgAAr1WRiijedefkEEOQBUrN2HOs -xDW9NIX9JiM6RFNBX2ZhY3RvcjoAAK9CxfX5lmHbWFcJfFHEQCfpabmW2/on/SYj -OkRTQV9mYWN0b3I6AACvV5X9PayElGU3atpQ//cE3jl3tHEfhbQvTm92ZW1iZXIg -VGVzdCAoZGVtbyBrZXkpIDxub3ZlbWJlckBleGFtcGxlLm5ldD6IVQQTEQIAFQUC -NuOq4wMLCgMDFQMCAxYCAQIXgAAKCRAlsA/UMM7GhJjYAJ96+gRNnRtFX68Wbsix -2VqHsXeLugCfVbbEonL55bC9BBQ89XY+6AFNSgGdAaUENuOrHBAEAOGceVg3PC6F -tgrZrnofohzWnui6FVBzeai1DZ5MMKmdN6/QMv1eeHoMOb33fbfhwA51n+kPuhap -r6QqTzx62RGA/gK1m7vjU2OfYxSO65GN/rSUXN/kE83jR7Hux4MocRXZ+/8ngqL7 -JAjw1LZdJyOniJpeRvrckPNC/bKaua77AAMFA/95VjAjJIAU/gOMwtbqTgV+cmHe -52Aa1CJEalV88yKG86nnqHuL4xxUTTZljyjbbKleJD/Ah7R1BxBhSEDy8WuTuonE -VHVxTcL9Yig4pZ/OzYZf5fkl1eLNaSLb8XZMT0JbP02b//OMpAr29lcaga1o1RtW -vrlUyIYOTm2RcTxkf/8EAQOxzthJ0P07iDKoQPP7bi9+FNgB92LCXMeilHSPeArG -JblD4lyK8pp+jwjSCaWJrWQO/OJJOzhTh6Betn6H6C6bapoEaQ8TuKbHEnOMUfax -tx/yzDtWu4EWGMyG9sSPjXRr/lChDsi5OMcYnrxK3foQYMEHBMb1fIqqtRZmqWPc -FixNLKLjBalB2cMRuYaY8o2V3ZyKiEYEGBECAAYFAjbjqxwACgkQJbAP1DDOxoQg -5wCfbgzOK8WkgR8iruUOQagMIqwMr6gAn1iBQ2TJM5znLHzYgLX+D0k5IG/plQHO -BDbjq1sRBACVaJ7JCEOyjZmcPbBv6CrpqqTWtFSFzB0HAJNuITVosCye4yXycsfh -++FpPPZX8B6OgvTR7bx24Dmiv0mIF+ZVuWulMAgZay7QBTq4RCxaBnBF2yjc0f8p -8fxnmXHAm2Rn+GUCIQeiGYagPfyYk2yCebrdFdp1QfvqKs7oxy9aVwCg414fuLbk -BysyiXg7sFnCoarbmJsD/0hGErsAWF+BpGsNPPzg9oiyzGnV1YpqVGu4wlgZArYs -O4SXndD53WudgE+WI9uNav/0aSPHcrgHQJ9ZZALSxSXvts1EWqvwVeSNFly+QKjH -Ecbs8gUbvust3ZKJD55L52nlCKO64wLyySS9C67FLp4iTSD6OMaU2GO673thrrF5 -A/9nF6Tfunw/W71NOY3uc+2XMZcat8pWL0O0nfUTzTmu5cWpO6gV9w4FGu19j4M5 -5tfxHEjBBX9MSbLHChd2aS/TcRjAPoAlKbHda5WLn+t69wf2d9IQcPLuwULwIGnh -pq8AVFA2uGiZIH2VKblyUYtmIPieWMXUQUAHBAVyHseGU/8EAQMb786noBSUDw4m -7xGDnWduktairbapLv/ColtFylU7mo8tzwPJ9N6M/SYjOkRTQV9mYWN0b3I6AACv -V0SyyziakJ764L9AWGhvZl0VDNCEff0mIzpEU0FfZmFjdG9yOgAAr2aAgfc/R0ZI -X1er4E/LYM2tthHZ54n9JiM6RFNBX2ZhY3RvcjoAAK9vCoy6yI44r9RAQQdGiriB -nWdRPg35tClPc2NhciBUZXN0IChkZW1vIGtleSkgPG9zY2FyQGV4YW1wbGUubmV0 -PohVBBMRAgAVBQI246tbAwsKAwMVAwIDFgIBAheAAAoJEF9jVrptlzKssC8An32a -3EYMFU3dvYtqymOZk1G6qdElAJ9XrILycL0GM22u75KkQfVlZReszp0BpQQ246uO -EAQAnQtV0TzPQjBa4FVL4qFO0koX3y544FgWd4amzmK7ILV37kHb+pQIsZzT3Z5P -5OJoy/MNaam41Jn5m6aVQ8c7IolEJSWrcxg31NYA3O5LJ16Rf784IW7nMvBzTtEh -4t7jPxlwue+ImdaMWvwNeHypwlWE9U4alGtbrAuWEFx5uCMAAwUD/3+C2YDd3Wy+ -Iy6lxwzaQCBI4k2yl8QyhzpwKH//+EhNJqWjVRy7t58SOewrV30iNpDEEpv96aqU -ys2gZTPwmzACVGp4ZpSzwEQ3Cf4UHA7QbBeZxRu83y33tEgcILDNR8S/evFb2u1r -G2KUmvfPtx0g7svVcKYRae4uB25wm0iu/wQBAxvvzqegFJQPDibvEYOdZ26Rt9Gj -Nyo0jdE5rAxUvk0VBw7TW+V6uxtqp+fKrP3W/ewR4mUXo1jq29kicdAtO/nI0uEW -iMuascrL4lCWWcrEK2n4AX7KbzJ9W3HDupQhHHwYga7LFg+ZAc+6m9k+cn6M8Syc -sbQt90IMqon/jpYnSialNZilcMpFfYCnqBDTVKpBReiIRgQYEQIABgUCNuOrjgAK -CRBfY1a6bZcyrA3hAKCPwFgK2ukTx/0R6o/BN6HFJh7Y+ACeIB2LqEi2uOknmyef -7JveVqldPTyVAc4ENuOsQxEEAIQRmJhsJniNi/bRff/YGrZ9aFWt81G93W8WhV51 -qq+ntUHgUNY55Yyos4XLOa2tS+K8zP6X15FesVBPYIQa5BIC10mAsLfJ+1rbnGJP -uNBA2U2MoEaRxo/JtXQ//5jiTRlYwLDRnBzuaMCPdsirveu+JBw53ytRwjwe7m/D -1PPvAKCp2dj1FtDjubTN7kCF0o2KzPwE0wP7BimQxXyPwSzGqLaHXSEBsh84OQTx -PI98BXgq0195/A1B1/pPs356euKlqoefUTHYhbjiMYbjZT+A6juudf7A2Ucy03G8 -HDZ4k1f1vmzrj24+6ygGBcxTVr0BaweiC1DwG3LjQoJ1cuFxRQ8BYJDGIwPrUW5J -dlnzW2bJWfdyXOoD/0S7iEVN9txkSKildOeP1YcDCD8MM3hvF9kUc+1hbmir8SOZ -/IYJAyQN+j+mYWsLuKtZ/F9pqiBNTXH2jWCTqldOD/ZYxHVJAARnkiVG6yckMLsx -Hi2LPPBK8xack0y92mKe7za/7fhVgCRSs7M/rzUbzUhyInHSyxr2SYb+8lbu/wQB -A3vncg3S/0EKhZRFb/E5MzbPjleeF5fQn4SvP7U30kDoHyI3LH6KymD9JiM6RFNB -X2ZhY3RvcjoAAK9Gv/oavNniW7Yqm+70mldjom2X6ztd/SYjOkRTQV9mYWN0b3I6 -AACvTc6M6Pazxb3BIBjtK8lUhha6Ei7BOf0mIzpEU0FfZmFjdG9yOgAAr3SSQHcy -6mye2mjpCNKs/FezOQKbDUe0J1BhcGEgdGVzdCAoZGVtbyBrZXkpIDxwYXBhQGV4 -YW1wbGUubmV0PohVBBMRAgAVBQI246xEAwsKAwMVAwIDFgIBAheAAAoJEF0V4B0/ -8TIG4YwAn2L7BGoJE1q7g/ePfsIhAc0nacGKAJ4iBZV69HtWtOryudH1sG7zEoaR -KZ0BpQQ246xxEAQA3mE758SGpbalfvWhJSpb9NEdZJvJs1zlutDW3OBNuF4eIb8t -AnWUeO1mhlCzJbcf958S40BHCvKjgiO8rSeaJCyplRHXv3ldMhuj/Bo83TxC6MLb -q5ZsvWlgvnJBqvBso6jICy3iOATU2llVz+vX5ZSns24RqmJxWO8U3OSJUIsAAwYE -AJZAliv6HSjOvslD8Gojy9Mq5Vdv4MgFCO5LM3su9qIioypv1l1802ZnUC2+SWjY -J7ZUzKWJDNVJNm4clBt+sNMFcF/5D4Ag2Id1kQCh3MG8O/qnu+xOeg/4DZtLyXrG -tY5sq3crL34ZQOSpbda5qBxQqiBCARv8Up5z4Z6DBKBR/wQBA3vncg3S/0EKhZRF -b/E5MzbLEL6CTR0ywkrjR5f4P+KFRNbVixP74rOGEYga1Uy8PrUOMDBIjbtKVWQy -6ly4hnMv7ZPtIZSJFpeofg7k/kTNJB0W0BcJhWfg5CbiWncJYH+IZT6+/0aJfmhe -y7gMlkoXOqH7y1MlLXHLriVzNOpapAK4Q7vwzzfRL8kXP8zC+u1noiuIRgQYEQIA -BgUCNuOscgAKCRBdFeAdP/EyBhuTAJ4zaeXrBSUA3s0m0MV04WJxDDGwWgCeKwYd -KMH/CO2Eaetd28XWxnxJHO6VAc4ENuOs0REEAIHCI/xKPD6yIRGsSnI3PXTW/f9A -WdwcQZO8fWuxypuqNP73Hyx9lxYxcQeA3X3vjtTwvSjVKiIuhk2nxm8qkuO17Jzi -bOZ77K4JlaVFMwHe6dHcXHNrSaHcIZB+BrTj+IuD/Vwa8Z4EK1kNI7t99xDxesC1 -ou6pFchhDQn7L5LTAKCmIDPl2IfVEHu/x19Bogp5NxMVZwP+K8gcXcgYoY9NourP -LwHuZpU68L/OboKLkgfeVxF/Bj372liFv06VFkOmu6PGM1P5CD2u2MxE2F/HvxVa -9mXd9xwH3i1DadzktDbxG2CZRg31u/1+6i1b9aOVgowh1ISvAwn/QMfW+M+wm0R6 -bcUhOFO/TQgjrF0LDm1dvKpRrBUD/iCGgoe3U6gA8P5wZn7l8XqTyl0ul3YtLaO/ -S30La/k1LSThFRiG6qkAbIBEhYk+akdFu6oTp5eO0yEMj0J7f1ffeEMMgBrSILTO -amBUVu9INRZMg0V+ez80zLlNgY1SOph5GlJC2i7o20V4kBZvCFyeK39vexqaSrko -LzXK+0Zq/wQBA0GK22cdg+tRJk3gYcN/JjZjdGbyparZK4zFc6L9X+dZtsC9gBVh -D2j9JiM6RFNBX2ZhY3RvcjoAAK9XLx987T5u+PQj0za48diNtMwF5HRv/SYjOkRT -QV9mYWN0b3I6AACvZ+sSQxavyXXTvVtvSZ9DrB2hdoyR5f0mIzpEU0FfZmFjdG9y -OgAAr2TiK/D9hNwmBtF5JxEuKwCv5DBmY920K1F1ZWJlYyBUZXN0IChkZW1vIGtl -eSkgPHF1ZWJlY0BleGFtcGxlLm5ldD6IVQQTEQIAFQUCNuOs0QMLCgMDFQMCAxYC -AQIXgAAKCRAcZ+wTPGYchNG4AKCjSqAGZAKs7NstyNXe0qmxdjqhgACfUIFuQ0RA -vRxngnEfGZJiTL7vHBmdAaUENuOs5BAEAJGi4T/jrY5BtRTM0psAneQytzzFgH4+ -LigUXAAb0QDAOkyGNfWHrfHJIS7A3Nc9pMWAdOjWgSKbYyrzra0SQ75/SkI5+/S5 -ev2Fpki+HYo7cNgVXnbCJrIY7k4DAMunqPJ9JCUXc88WxGvKV5b45htqCPnV2Pgq -+AEIKD5aGfLjAAMFA/9+O6ttUbeY2bQHRdThl4HUxQw4lgYN7stgGZsbHCc0y6ln -1HF9vlE4Tl6HI/NR/8OauQrXt8988dh039QNZsOdAeRWTk4PgSuXq6VDG5WNw6B9 -bvRPKXe5yeVmNNl6KESBzMcq87kANZWZ68vKJ2JihxPHRAyfxwGr2JKkVF0S+f8E -AQNBittnHYPrUSZN4GHDfyY2YCjm88CdmfBmhTozr+i8fBZaKPsQQkAz4Ybhdf+d -CkGOyQjOvI9qUX4wNF1n9/2af6a9A9TJNYGpdQ3AQUyyH1AXIfYLeZhAKR8oHgP3 -r5L4DDGmyAG/I47Ziko9nyyRjEkT5B17n0HedUtHH0+v6vtjNc4OA0XtbY0SCvuF -MpLRF9guiEYEGBECAAYFAjbjrOQACgkQHGfsEzxmHISIlwCfZ8SYKvVQnWcUbLR4 -pdAC/SDm0XwAnAqTsdVw9qkF0c5EwGnsst/qiAqalQHOBDbjrjgRBACU0OjVoC32 -Kh/dUjXPdN6HIusEhHheYpFIzYHHTYJmFBEjBj9CwrpYGjGUmp+BS2wFS59zO2Ml -pQGLGrmo+YGBdio338Hwdm8baeScd2Koqu+oWkCoBMm2VxxbS3M8kq0ppNu2Q5EE -O/qGywVrVpfBM3siM3mcsjVaHyWy+T1IqwCg/lnggNIr+Yz2HoU9GwCwBi9331kD -/jRTBAuXTq7vAG2bGpJ0X/zqSMLSRZfwnZj28hx6I0SIT0yZU1xggrAgzSbB24Xn -QSSxWMR2BZQmupPdHO0l8xPn5KCbYo4C+9+ZsprxEXg09KtVcMOsV6qTq40NPSOd -RRNAVhOOTg/GD0qX5r9ztB57qpefmp4Nfy5tmo3SehfRA/9jkdKCLrZRsE/kH57k -GoT5kt4nvJW2X3T03BMKvspVm3WjdlrR0Ji0yiw9P05sCMJqeFKe4RZreG6i606C -itZpRIRbpjfMEq838zgUDv7VGF7zqCedYu36sepfkzxj/slNyu6A21HTgMWxiBrk -DXoIuxMPFKYzZGC+nCHXgW2uof8EAQOPMKazZfwtUoJ7eB74i789uCp+H+yM1KRO -CEcmSW/T7ago8wfbaRdC/SYjOkRTQV9mYWN0b3I6AACvTozOxPOPjYlU7v7vhyL4 -rFswiNRORf0mIzpEU0FfZmFjdG9yOgAAr0jn/8fzbG+geTnYS5NG4g227pXLeTn9 -JiM6RFNBX2ZhY3RvcjoAAK9spiY0wOlyucxM1H39jlMftXgj0GA/tClSb21lbyBU -ZXN0IChkZW1vIGtleSkgPHJvbWVvQGV4YW1wbGUubmV0PohVBBMRAgAVBQI24644 -AwsKAwMVAwIDFgIBAheAAAoJEDvb7bF3f77Tq+AAn10WjJmAMcn1pBFwE28eIqtU -z5bsAKCoNi7oa/HFVQZRypKR7SChjez90p0BpQQ2465mEAQAiea3rOLV0WY9+rOz -+CmVlH9GAvJrS8cXjRF3uXJALZ/IDH3EkCeDHouDtRAb6ymfQ89vBJr9BZg3eug1 -HeMm0SJNTzfJFq8vVLhiwH/1QQJDCMl4WAhJwe8EbDY+JBeQ4WIsrXqdsHpD6HGT -thgFKCMmNsjDW9ptoNivFJytkAcAAwUD/iMYod6PvvotNl8IuMDnu2q6NsUngZh/ -W/JxGifL/EVS0TtAIKEeBi8ynkzn7+exVOPLZWO7MbYehTsXiWkJEtZw9S0aW9xl -A2a+6jP8jhmKdFoXUYBlvnNHmGt9oOWo6ts59/h9S+Mq5kUmTOJ5meWV3vYo5BrN -FDWKpotIAWMa/wQBA48wprNl/C1Sgnt4HviLvz27SydCgapMV/zUfdQL64nYYQj/ -00crVG3e1cAN2iOPRNsjnczkYXjFfSxTxoVvQEOvScRoOF1LQ6doAGGSJmSkyIGZ -wxb4VLD8GhqmCX30XxOcTRG6EiLq9+kDGL5gAnBUTviRF6Tc+y9N79L+nxc4lawj -36d0ZXeIG2fm8RycxA2E4ICIRgQYEQIABgUCNuOuZgAKCRA72+2xd3++00nRAKCQ -vRyQt5pNoWbpj8btfqGK00jpOACgjSITGzCNURjHPCPEBAPqgOVDh4CVAc4ENuOv -BBEEAMUtk4AJiXP3jaKpIhbi3B73S2SZ67rKzBkicjelpwWk6LndsCrbLsIWsDf8 -fNtih0r9As+2arfApkNlwuCGq1ZlPGGGEf18OqPxFvnghVEbDdcosP4bIm3k6G2s -gFbMl68xAGnTtkS5Gfz43uTuznPzdZnGbIjP0uBmPfZk6GW7AKDhi4htuxr3Y+ud -9lx1bWM9KqUtAwQAiRYHm605RZVBkdzlfYx1Iwgn/l8Chq3MsPrfBMslapBnq1an -2/nEQPmuIde9C6ALN1t03DHpKonx2XgjYVz8pgty2FU7txSSm2EE+975dXp3ov4T -fD1KxksOl770PAzixLfNhPW1q4A2cEruGgO74qEX3/fAa1J0nRKDgmA/mgYD/2TS -ZKCaFHoc3IHQnkygmGzzZNpVZV2+1kIB8Z2hNo9V81PYpzlYV8SlG51ajW1G3ePc -ti7JOIP6MquNUbYR4TOzZy1Dq4+VqqZCB6fOeIKL40IKKAoMMDYFNLp9zcT+s6+6 -DTPH27eE1WEt+NQjBgr2ofC/4iAU/nmAYmo4xn7Y/wQBAw1YC6sO6OK1YqygeAug -0cwEFM97WACPFwv/yo59kPUn2OPV90GqWcP9JiM6RFNBX2ZhY3RvcjoAAK9kgTY3 -bsST11j0XtHaORe84A/oRwpP/SYjOkRTQV9mYWN0b3I6AACvXbfs2GvacmwUsN1h -JIJ6o5Tv41Oiif0mIzpEU0FfZmFjdG9yOgAAr34DrRWil2lE06jH9gI775+twQFW -Zp+0K1NpZXJyYSBUZXN0IChkZW1vIGtleSkgPHNpZXJyYUBleGFtcGxlLm5ldD6I -VQQTEQIAFQUCNuOvBAMLCgMDFQMCAxYCAQIXgAAKCRCl5n9/o64+oa9/AKCaJbj4 -sc17CLwMOuvFVejk4mwUQQCfcrpQGZox97B60MgQRs/wklSEVWedAaUENuOvgBAE -ALhxyR0+JaBA2Qa8CberwXHNEuiDrz+N9++Pwy+375dDg2KQ7RUnx7NiRV368be/ -lGgdMhLKeYxZlmNPnpoUNINk86RCzYbSpmAASBOnMJQF2WdQLxmsdJNJCMKfse1H -ZylgIJQGWI+1q0O9Lcx7Vd1F8GFeJvThMHRyLoOvMVCTAAMFBACN7RHUg2b0aRko -DNMQKL6VV6LvBteSfgkXqf2vUovmhQtUXxoYc0QnVPCPuS6raRpxiNz8OLgp0RJF -Nk32zOVmc2u68B30kociBt7Kx6d7fJGHL5gVqpebUy1YJ3DBoOIOgcMBKmXnlG24 -IrHPq5bvuqGtnwToZEOuEj3ZHzwNuf8EAQMNWAurDujitWKsoHgLoNHMAI9CpJsg -3p5r1/2dTbN+h0CJ+lqHoo70wkoAb+gaM+7jq/FWce/7mNExPIYobdgkvZ2rbKJP -x8o0zJqu77IkMLTb/eh8z+dEaC9X0S/uYgN6AUJl/DsEU+XwOd+JY8Es0wJda+M0 -qvSGaH6+kTYy4pO5QD1BrfdPTOVNxcFna7HAItZPiEYEGBECAAYFAjbjr4EACgkQ -peZ/f6OuPqEzHwCgo3fuvctqBR1zM+lGiitaCcoRH98AoM2iZsG2q1yiU3MebUWD -xcPCiuRMlQHOBDbjsAoRBACQ4U3waYeRudWpRA1GiHxbw9CvqFw16gwe4Q4N7LVS -KWUffXdm6P3TzrlVqK8FxQQyXitHO4iREKzFipcXam0RpB/KWhUpy+V1qOMTI5J6 -pyc2Lt4G+9+IqBR0wuFgzNv76ExrhaS8Pnoq1vsJddsLrB6ZzZFsTBCFrdh6Bk3q -3wCg9yVAa2nj2/IByp1xc8hLvES6d7MD/12gCo3vjQGHqoXAKsb9khD1I/BDILV+ -0g5JMg7/MLkX3DcDALeF8B2J5zN26VMFo9iXAxhPa7DZ2vx7hQI8/9pa4VCp3B9A -ssL44WLbdbfdo9HD2Wnkd6WPEf25vDbNtLYj+7sVZY/rMyNj3+SolB4YlhydkU1x -hNqVJk+lBYXNA/47smbyDSsJG1EksKSr7KIteXenuFseT2dpgK0+cvlC4rQceFii -LF1elFVWhATWgXut5PXBRnTxG2vx35Une+pC5nEncvha+93d0zCK5sACjFXSo0QB -HN5fO2Gj3dvy3U/k1swkMN9xKLXsSe8mc2QNkicdu/48iIF5FrcL5+VAjP8EAQOk -qTnVSVlDNyanmeWCbHT5y1XDf7flXnKwAlPvRhV71WMkqrgQyZSO/SYjOkRTQV9m -YWN0b3I6AACvYMiOr13riT9DyF8K7MAH9rFUqh5JY/0mIzpEU0FfZmFjdG9yOgAA -r1ZK4vMwe7MVGkYsBl0OFJFhJWf+nD/9JiM6RFNBX2ZhY3RvcjoAAK9tanjl+Ggi -icD8mvH2FEnlCyuiB9iHtClUYW5nbyBUZXN0IChkZW1vIGtleSkgPHRhbmdvQGV4 -YW1wbGUubmV0PohVBBMRAgAVBQI247AKAwsKAwMVAwIDFgIBAheAAAoJEFjLmkyF -qB84JOIAn1w8JVmBDp+6A35ia9SqWpt52ZiiAKCIHwczU5eSjSlPSm5W8C7dlk+B -CZ0BpQQ247CeEAQAnr0w2OcvlUX7E8u2C8dJGIj7wRU5qDazxh0tw55/ybJ3/Kyh -CFfsr2dZ2E7Zw6Yvc1u3WTTf82nH4S+/IJFSI+qBi3TrcwVtt8Xa3Po7cIzNvS0b -BhqfmOOXJc4ihUlADR2Jukm/QC+f6bO8IZBDWr/7LnT4SwEPhPoZNMFb63sAAwYE -AJ2kiP3e1zM+zEo2i2jkOny1Igyn0sRiuw0OXQ9B656zp02G5qtDN+IXhgLdfQqg -qyWckP4BLDJ4NtQoEM/Mr2/7oj3h01XpbU86R1QFQOXmoWw3q7yqEWIwfOBqClSF -0A14sXdjQwadyabTFsW4m8Zn5jLW+1sH4PrVjHoNEz4C/wQBA6SpOdVJWUM3JqeZ -5YJsdPnICDfLPDsLTp+mSJOvz8ZkqbdjjI/q3Kptusm2FbDk07+WCtgfeKcaeJZH -FNDb0PYRG9S22OGNlhDTmZluNPmUG5syMkoyycBX+4RTirp7LNS+VBIOHa6d1wD1 -k8lANIjD/ilD8pW0pAyqN5oJLDgGD9892G7eeE9Vy4XGRmBB6TbFMF2IRgQYEQIA -BgUCNuOwngAKCRBYy5pMhagfOAibAKCS4dbgdlteoklBNH9XU3+trecmqgCg4u4N -x5RLyPVJoOlZhb87WTBcW5+VAc4ENuOxqREEAN621mjyBM5OvWclduTmwl+5VJBo -yZuAulmkyzdDsL6ABfRdf5D+9y4en7BXY2rRLi/7Dkr6zEMXgDxQN/6r4aY0owDl -TbuGRwNC8TjwRhSCFx1YqNZ4XCaYk5vQoyhq116HiI9PiPyhwbD6LTPqj97TLQ5V -axS8iqniJk/dSWc7AKCA6rkZ88kyrcrdw0PedTsY5Hx7UQQAxyAfT2jrwduNvCnD -56M+4rBUVrfsI5f/rkUXw8416V6rsyvdjzIqpssiwhYNrGuV+WlvIzP9KG4N01Ty -CH6ax/CHT5E3N0Q+akkIJUk51k7jpy52BvIBCuIfs/KxJuLsBuamcyXuRCu6EBlZ -cu2cfV7WQqi8HjdremHzAXiSi3ID/jkDxssoSYm+mr9qZjpWMOcazGQOOPDY6hVu -3ywt0aOmBqePd+/LkpGFZ5YsqGa2rji0f3ubhgOYYIdVr8iJzhoM8wy9Q9Z1pjkP -IJ56tU5vck3WosLujnHYcG3xETtxec8mXlUrFzirPKzlupARhi3Z0/hwmoqTc6OM -JuXpMn7x/wQBAwH5EiW2ICr1W3T/Rx6Cb3eG3/JG8Sjo3rpEYlaApMS+d4oM/9V8 -3kr9JiM6RFNBX2ZhY3RvcjoAAK9AzQba8DH0bAE2s5RGAEJ5VAWk/+g1/SYjOkRT -QV9mYWN0b3I6AACveVUvbR4gGYzhP/+FIlqbM8KFSN9EM/0mIzpEU0FfZmFjdG9y -OgAAr239YwqXBe1eAtTrlPkM+BZQS5iCzKm0LVVuaWZvcm0gVGVzdCAoZGVtbyBr -ZXkpIDx1bmlmb3JtQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247GpAwsKAwMVAwID -FgIBAheAAAoJEKlMD3VlMkTWM1sAn0eideyWSJxrd/trrimzJpapYrQPAJ99nNzM -TsSCQwsfLaq0E7kkkS7KtZ0BpQQ247HDEAQAtbvtPTT+OnT55+kSbXMy9yxK6Mq3 -D5hzpNxW4jXyfGDJxQXkk/lPvnIYv5Cs5vjeMvE2RPLB8Bqp5HiAbSV9mJkCRYSo -tkUfQLVZ9h1dWUwWE9avz+zKWUzzCPRDg5QhDyU71/jHbT/MYdBrI9YtcLo0DiQI -l3a6rD8Xp+EnIecAAwUD/jUUTsyxauJAVKYKE8r1syZfehncpH/jtAIW05We4sfS -rUC38Rq6s4KNIcA429kM3lh341YWmmknOVFjTLiEMh0XLI/ceJ9uVxhNB1MjlUg+ -OiDgI32Rfm3lzmvzW2HEfs8zkX169asltoOKFfCzeLOLleHT2pkN5ffC5IPJYVgn -/wQBAwH5EiW2ICr1W3T/Rx6Cb3eFuP+IvpNCP9FJtq/cHx/aNtVczSNEk2ParqkE -bsZoGgIF0fZStEWeTda8b2/P8dt8E/hZL8YE86A6y26jjzhIQBnThCdlxYXCI+f3 -rwXSdBJYBu6jvOA6Cp7VJkBGBUknV3c26VN6mF0tq2xw8EdB0Z94SBwIObsUJxUX -GSx6F9n/BIaIRgQYEQIABgUCNuOxwwAKCRCpTA91ZTJE1s6YAJ90NN6PZ4hYojIq -GPHLsoXLX4ZQqwCeNI8dzekcdK9ZkqXRxIfFj4cQH5+VAc4ENuOzmhEEAKMDGobM -DqPX3SKI3/W8m9LmNgtDUffHGHNd1npnGM8mSyVfWjEWoEg2GPMEmdX3/tvUUV7n -Tz02IJwZRVlrbEPdW76eItMAY1NB43LpjQTrAR++mVAslulUY6a5V5nJKEc0IqOu -xkW1LWavujX1JRvlBZLeBkdpsVNuaGJtwUFfAKDfqoZUCcZxnO+dRMalHLfGOn7O -4QP/apMk2mc+GJwpKSxXBvoQkVcfuZBJmXJuUCc4BUUzHX0ZSKNbgxY/kVR1xN3k -rMgOCR6dEsGukIsgVWRDj9to/+E6IIs6YKhG7fGcXKhE8z8mf3hDLcmjbCKDCSFB -T7PI5TkLzlAEP1y2Rtin/Sa71unGZhNyEfAPW/d1dRcRVqMD/2WcTPUaIjRvAqmb -xUpenRhg/mF5rwmHl81VvVBbZCoZ35c0edEZKpfmyYbKuz7GhjEPz6O/UWGYZpK/ -7r6f4kFUrhO5atClnRyBkvmNmdfbtM5hd5jh3lgqAT7tk7ntPAIh8X8/qm5+Uab6 -3kZwXCPiSR+iEwRp42GbVL7F/b2r/wQBA+smNbHH+mT2ogDvwebUEYQ5u7AjqZvU -WkfnZPKAVQwghkIrT1Vq21v9JiM6RFNBX2ZhY3RvcjoAAK90DxORhCauJg3tbEH5 -zO25GERe8T2L/SYjOkRTQV9mYWN0b3I6AACvW0fayFNyPj0o3kQ0YOk+vZDnV7i/ -4/0mIzpEU0FfZmFjdG9yOgAAr1sEI+EYL25Oh+V/MAHMZ3nfeIm133O0K1ZpY3Rv -ciBUZXN0IChkZW1vIGtleSkgPHZpY3RvckBleGFtcGxlLm9yZz6IVQQTEQIAFQUC -NuOzmgMLCgMDFQMCAxYCAQIXgAAKCRBHr0tpYfBHhMxJAJ91JH/X2uIsYSrKJmI/ -S1Zgwoz1/wCfdQoDeGHzNwPI5NaxIZH0XYr+O22dAaUENuOzvhAEAIeRQIHb2kyS -94wRnI2IoiaLMXk1n9y/3VGPfX2TfEd/Q0laFCn/UbfxLEuQ8sF1ZygHiYlE2MPJ -WzEVRe9FYUgx6TAvSrWwdJZNwnAKlCz4soq0+YPcsDduFu5NJ2liCYrLbVIfh6m5 -uoHOT8/TX3eZZfMeBIYt5ShOjc3t4FDTAAMFA/wLVDdYasFk06YVWXLR6tyWlBG/ -WoJrvznLH9uP26vYvEfBWjMAReHyOaiIpnKgDPtgWenb2RHaq1WmUfWh483IXB5m -oiO2ZluIJpPixxRVn/cu5hvGAyhQV5GgbiacRW9RSHyaZmi8yZkWu+nS6iNwOx9h -PHRUGvzBrGAmuDZiC/8EAQPrJjWxx/pk9qIA78Hm1BGEOtrTuBDDiXmHnTN7vG9T -7F+vQT/JusPW4EJHYO4E2e1J6gyPEGOqrAsLW97WTEN+LW1bdTdY7dhM4jSI+Unv -ZqZ71xW06WXE2lxGD4ayXuzP6Q0KQT7YcMnrkqBluRJTfGKdjX0RPXt/5+KWd7H3 -VEst836l75/lYfLrbWxaArFjztISiEYEGBECAAYFAjbjs74ACgkQR69LaWHwR4RT -3QCfcsKGxTTd4f5S/liM5MfnCtlAU9QAnia0uQcnuH/aodTQqspKUGN3Z04+lQHO -BDbjtDQRBAC9Vf1MkTKc8kSxfdfZ8Y88OJAr6gHsPUg0j1t8gPk0q2ijyrJuK84u -jzmLmbtFSITKFfcT2VSD1u4qa0iFqzSwnywtRGYKd0gq1eMhaDcp3SmaMTyrbPJ3 -sKFDd98nbTzvnA1tHgZCFI7VZO7HBGgvnd+370lNQsnGRBF/vUDObwCgllBimEp4 -tasu0WNvZYptjGy3ni0EAJLsL9W7jR64h6+nZNkdO1jRT45sW8mvyMOt1BkyRQVK -6G2Lut879t/upPCYK+/ohWaf3TkAKH1ucrBm9xHlPXJHZvoIA3brt/OuJmG7r8Ub -70N2vrZmdXas/w5ru7EBcKeii9pp8pi6mim8dXTPS1R/b7BqytB0dlO9zSl9j7no -A/9Y5UnQobM/qT1tiNhJEnUwlvvTB1UWId2UiUR3k/eNCxc7IdUytanqofXSxAu2 -jyDB5Ymv1od6bRCNM1JNWnOnqVoEd/u2csTAIkZ5fl/kE6HztqRGPB+H0n3Nb4MG -u2mpLq+OUNhTnLpEZsZGXqd21eFXkWkThxstrH+kYVYSrf8EAQMsrHk/oVe3Xf3i -4RPIB3bwsBoWGrA4kRK7mm5a6M/pBLavd6wy89rv/SYjOkRTQV9mYWN0b3I6AACv -ehBH0gU1mDQlnrZJH1j9rE7y0RQQ7f0mIzpEU0FfZmFjdG9yOgAAr0wMh+wQ/T3L -5WOeVMHnGH1mSba/DcX9JiM6RFNBX2ZhY3RvcjoAAK9nFbd0J8gWcTtZNckFwvKi -KKj15fB9tCtXaGlza3kgVGVzdCAoZGVtbyBrZXkpIDx3aGlza3lAZXhhbXBsZS5u -ZXQ+iFUEExECABUFAjbjtDQDCwoDAxUDAgMWAgECF4AACgkQ3vD3uOxn296iagCf -SizgYr94GzIrMWbc6H1ha7gFOX4An2oeiUql9DoXgvph82AUGtmv9TuRnQGlBDbj -tFYQBADPV+xDMQ8NzkqoJyO+lriAUrCNIBf1Kbc6U/IPAGOoED1YVPX4EB27u3K/ -EmRVd3clFS085Dau5rFIr3d/xXnLn++wqSgQq0Jc7LflMpIj0P209/oKt6MBovTA -Qn3lNpecmWd8oxiKoPP158Zgm7iLcOvRTcs+/p0KAzNvHIvQdwADBQP8CQS48V16 -lhWOSXV6u3JOukMeWBw6Tx+7M1CqyBihmR8ZNlF6FPBvVkX0NFVUH2qJn5yr6Pmx -QxSRnC3yCEyPBa48xqIditzynMbEIkNUrFZTE915rr0k9MrwzPGuLfaPtr/Miy4B -I0dnZ/5U4hoxPwDbp0aPUwRqb8+T9POTZs7/BAEDLKx5P6FXt1394uETyAd28LN6 -Abjx+ozpGMN36+SHvBm1QBbee0EWJ9LYnatmavOGPgEn7HZFbgk/QaUQiMRMNQIE -ykHjoKU1C5uWEDR+P/wuEYX0+pQ1UhUUZ8v+/wZjAC+X5WymJmjKW2l4LXfq0RpO -U3DedzHl5+zcuhfZN03MhxX4mcTHdGNSLqWzikj/1HWl3ohGBBgRAgAGBQI247RW -AAoJEN7w97jsZ9ve/yAAnROeKraABkL+JUAzQwMcNm+0JCezAJ0Uz6p+tN5wt6yw -yH09JfENI3F77ZUBzgQ247TcEQQArUqUbiVTMxJhp8bA4vMXAzCuLjys4A44DE+u -RFb9AGsZTmw/FTPETO7iU/3frlyYyTgIvI2zDF1SwHXG06KF3yIu8LF6OCM0N0k7 -KnKpw8M2tkPiT+D8ANrHU5d178evzm40PyNDyKxSGNlIG1N4MIKFtNdMlahLvu91 -kG04WesAoLPa5zISvsX+Ew95M1o4Qti8iYHbA/4wr+eYRywP35eb/F5V9bOLWhWm -EDzw4KHXQ7V+OJ7JD5n44S5KLPKwIogohDlPmrxDTAJ/YAukApUItd30kr0Uq34Q -gFktAsqgCP7C5KEM1TTxU25Tcs4ojUHoDyMj14ECuiTCP0ZFRKUivopgjgRhFTKX -VVWTySkQ0g9SDaITSgP/a0FyXMQUYJjuB7GA6r4U6QnIHsxS5xrQgkshb4tp2MVW -MhqlhsfOLaj1WZ+oe0DxKw0O3YKTH/EAzmNelKcMbtTcilLaIdI5l+Ylam/bZe7Q -vbN2s72Kn2PZjtYqO3Uzqw14bqAJRl0ekleMdZRMMzAsour+iNVPHnlodXnQ2gz/ -BAED36GMDF6APjbzsvUK+yk64h67FO9lD4i0FiXAE3DtfiBKzYh3jEV1uv0mIzpE -U0FfZmFjdG9yOgAAr3nDQWlricc0AeWTgJNI54Z91WZHkBP9JiM6RFNBX2ZhY3Rv -cjoAAK9OjHQxUQz8Wnpik8iZguVXD27lXLi9/SYjOkRTQV9mYWN0b3I6AACvX6xO -WYl810CKCu/QJGFZWsNhMV3iibQnWFJheSBUZXN0IChkZW1vIGtleSkgPHhyYXlA -ZXhhbXBsZS5uZXQ+iFUEExECABUFAjbjtNwDCwoDAxUDAgMWAgECF4AACgkQiXmm -xVZ/s0q3TwCgnrUiygc8NmP/EDsgHOweLy5+oMUAoJCz7S9Q/1f2X7xXU9Xs2xka -KazvnQGlBDbjtQUQBADG4aUG+qgOTGEgOAVnN0ck76AnKb3jOBIYeQGYEgF/lDYb -Y7fOQ3tIgQ0jXrKD1zHLvORNsG708yDNR79S5Ci/1nphcrNOPWMujOsZ2WMo5xbl -hG+WJujt4pcNSRK9P5fonUE4hV7GXTljg1yZ/ui00Ot7b1B8ryAYE79t1B3svwAE -CwP9Hg2r8lBq/j/t3kRO4xl108DFXiQKdj7sXugmAcMomF4nG3j2s219dLEFlSwn -0/peGvjp8JFPfcMPU/xHJSaZLf90mXsf+pHcDWujHgVA9YC6ThYaGx9Je+VmcVYo -mELxNnMWKyOJePDU4ViIXhMCvGP0Pt39wcQoiLjeu15+l/7/BAED36GMDF6APjbz -svUK+yk64h3k1cEq5Vaa4ZpvzNmxRxEEMST+XLJ7leRFzngFM7CJLENe3+ZTqaS7 -d9/a0p9ocVwP2NHOBTLSUiKi8PacU3qtr5A79M2AtUrlnwJca4opneBLJgNGJLyR -Gsv6WEWrPZ1PhR7v6SkUfj8jQ/Tzb1lj6DpOApZFH9fHv5btLU+JITTR+ohGBBgR -AgAGBQI247UFAAoJEIl5psVWf7NK7JAAnRosvXTK0JTDng87kaiXLAT3t2H8AJ95 -wwtp1x0eP4rcO45yUsgGIoWoU5UBzgQ247VREQQA3VAGc4T+vuvVXcka4ETaLaLl -L1xOiPIdJMWRWWQ60CZqWXDVpFBw6oG2AyfUZiHhLlmTZssz8UhXLw/URsPSpiGb -tpGWKiLs4OCqjslN0lHzcnGqxGWCZJixMgZa5DcWZJjwqdXEbDChgm4ULP/7+iKv -IenTQNhFoCXr9MtdoHMAoLpNCmSKlTu1H5GlWmYTK9AndWrfA/47ip0VYgzIvUhI -0iWcG95sNfshApzPL6zPgKBqACogs/5/DfRn9g07BcuMihLJD0PLNPVnOXqQRaN4 -Da7jLuJA53XtLgpogxG08M6XUimTucfcovu29/bgjZIKA5c8KJ2lzXSJ9jZxSoy+ -O051f7yhXbUmYC1vdNr8GBk69QKy/wQAiHMfU3cbCfTTMmig+zBHCkHjqzqr/zKt -R8RT5AwSOIU2aUIiHdV08apCelBw8PbEf077TuWCq2YyDZJmgWRYh5cdaMgdAd7u -l1FS1yHPZYshcofWjgXUJHR4I8iPCs5OmdHo2HK3uU2OM36ZQGSpFA5WN1NEm9Gt -MSBoYKN2ERD/BAEDE+RZ21hlj9nFUQKkDf2E3ET88XB3l0M1bCxCv2UAfGp+pESW -bFZsBv0mIzpEU0FfZmFjdG9yOgAAr1wtpFPolwbaQUa/5Qmzo2/e2AAZMSX9JiM6 -RFNBX2ZhY3RvcjoAAK9Sfv2nvtEYMQvNNDd0DvnBNBoxlAS5/SYjOkRTQV9mYWN0 -b3I6AACvZ5hJ+Tl0FtvDC+JX0swooQzPDGNCObQrWWFua2VlIFRlc3QgKGRlbW8g -a2V5KSA8eWFua2VlQGV4YW1wbGUubmV0PohVBBMRAgAVBQI247VSAwsKAwMVAwID -FgIBAheAAAoJEJ7vNM1LEbJfV7EAoJAAKzgeRH40g+m1xX5ZfP6QnCcoAKCbTZMS -o0H79g6Zn2wZbdEVGwmj+p0BpQQ247VnEAQAmuK5RcS0zTyXp6SjW2+WeQIpJnJD -flL0+iBe//3SADv01qUmw3jWMAuxG+CcCApksl122V9npEHiLC4Q2A69roLRsbxK -BPebustfadLJoVYqPsvjnrBlafe5GcrFPnKbE0wV6ZXx/Tp/eSDiQlid4lWz5J+z -/mN7KhHANzoRAbsAAwYEAJO5fkCSdNwkisFXzeKslWxm9Yoe1TOouiSV11hex0j9 -4Hpz5wGWEXF7z+FbDq+4V0UqGkKxaERsl6HMWNkImj57N/9h1C1YDfiKTimg5tZp -KmehXtldpWGCNDZrE0RasrFCKENVhFMhpc4kAnx6rbA0+LhRvJkvkdxY7pKU//aZ -/wQBAxPkWdtYZY/ZxVECpA39hNxHnMEofjVNfhE0JAv3KTJRZHOCbzCkO+DxKgcS -IsZVSJizzudmVLYbQWMKc0ykAvbJot4k6PgNiWwUyY8HxQs0F+5YYtQkMs8VdIQN -ez+5E2RCoB+VflUVq4qhWUxXB737maUEsSc220yeEj04n59OlPILb+A/XvwoCE/F -+kCQdlS7BA2IRgQYEQIABgUCNuO1ZwAKCRCe7zTNSxGyX/RcAJ9X3N2PPlX0KeNx -UHefqmpPYDF6GgCfZmyC/OlrmmSulJ6NAHxiQNT4D/aVAc4ENuO1yxEEAIEMk4Zf -0L/HEJVk0/o4fPpwvm8zc+KZQCFX70cBVU9BWJOcUquRg9JDJF9bOM5TxE7VOnkI -fPvjug5vqP0/vjIfW7LvzIWDhS6FcFaKeG4IoqrgghbAmQIoEWvVTx+7xrpjo1yO -qIMDQqYZEmsw+Zd6deQmkUYcbvytS82L0gx/AKC6DM0guH/ddkJlT4FQ9h5cv6dQ -AQQAgNdmGPW8VceCL2WaKMoOMmhwQGhqY3+1pDLo7HVFEPoe18A9jlMRHWfvGb2E -zMT46/Ugqkf8TzvZGFrWq7W/t45rp5O41YXQ2+ZJH3nl+t5Gw25Hwk0hvpK0jYRH -2nMFR+PKQL2mDbA94LvClAkgX1MX4lrUG8bYj6FrbEnvzoAD+wcRS8A6xznxhs+V -sg/KnYl0Qe9dNFPY0hJVG5MxCyDy9X32cxhHYJSHbvS4/LLbFloP+Rhwn3/WeBjs -L2lts1ahXvQ+QQw7+qPrs4hWJZU/NSEh1RGitukaG5zegHNTE6CJqXshshI9Ei0O -CDahmhjiGrJA3HwKPZlkDMOkza8K/wQBA3GTFCmP28PloZW7fHe9ipQH0TkH+yp2 -IXXRWNHjhcbOrwkv7+jedHX9JiM6RFNBX2ZhY3RvcjoAAK9nd2gdDGXr+aS4H9RN -o21VL8OsKJBj/SYjOkRTQV9mYWN0b3I6AACvXT7TUKyg8va6X0RToEWg4+feDJFE -n/0mIzpEU0FfZmFjdG9yOgAAr0s/BxXRDWjjCqZNI5VKmGD3EQ2CCWO0J1p1bHUg -VGVzdCAoZGVtbyBrZXkpIDx6dWx1QGV4YW1wbGUubmV0PohVBBMRAgAVBQI247XL -AwsKAwMVAwIDFgIBAheAAAoJEGvEd4BUrNJGQOsAnjgUjTj9/yeCyzBgwu2Fs1Z2 -HB9aAKCYdUx3OscN3QmqVVre3pwZY5GmSJ0BpQQ247XyEAQAzHzwwUKDM7+djJo2 -/EnWmCijc6g3fStaGNoXDEovi3B2oPiiRTsigX90qB5nFP7whDfi8k4JY2Eig5hH -+MGdvni36hYEnQSadsZueYofvQh14N3V8fUmx4hiQiMXyWiLJzc91ZiRjww4wZWn -/4Y5f+0mb0fjCaVSxTxo4+7joU8AAwUD/0oL9Gm3gl1XVV8BhJoXVdFQ6PN9yEEX -UbtcrfkC51kTBk2NaEGqbB+kC8GEmXwyZcW7AQN7X6ikraUUm3RjTU7CvkSHobBn -XYt7FhqZURpuV7eSqZGP5nP7SxWmCTTKgIH1kHCpWRwaexKFjIIkYgyVFqtEx9cE -Q6D2kXPh+Rna/wQBA3GTFCmP28PloZW7fHe9ipQEjson+R8J0cZFxO8B2k6Fas1C -pLvP8P0NdTIyitaiBUatIGDI8N22I6mqelpWZpTKZZymrDKe0n8h+rTNqb0uIt8F -R+6/1qFnL1k3E/+QxqS7VGkRz6xnT+la7OVrexXz18ynbpvzJMPe2SAPyqY+RSzW -wf5Z/bgM+A/ftNFfEencn7KIRgQYEQIABgUCNuO18gAKCRBrxHeAVKzSRn1jAJsF -3zuwZ09o7T0yZNm4zWcRGZvteACgroLrVdUuNxbdEllH4BbcvFB06zA= -=P9+G ------END PGP PRIVATE KEY BLOCK----- diff --git a/checks/secring.asc b/checks/secring.asc deleted file mode 100644 index 09e059d6f..000000000 --- a/checks/secring.asc +++ /dev/null @@ -1,57 +0,0 @@ -This is a test secret keyring simply stored by GNUPG so that -it is easier to make diff files. - -sec 768G/9D266E0F 1998-04-28 Test one (pp=def) -sec 800G/2E5FA4F4 1998-04-28 test two (no pp) -sec 768G/6D11D6D3 1998-04-28 test three (pp=abc) - ------BEGIN PGP ARMORED FILE----- -Version: GNUPG v0.2.19b (GNU/Linux) -Comment: This is an alpha version! -Comment: Use "gpgm --dearmor" for unpacking - -lQFHAzVFgbgERxADAPG0kMNVRUl24GfpzV4TPcXgw/jqSkFOIVGgin7k7UR6GOUMUz89wxVk -ZRXsLAOdDrtvI5T1sSCmWmhsTKmw7aslLJugBM/70YuVSolR39vF1JDK8kEkx748CRVW+/ul -mwADBQMA12YmsDbYGLI8FXnb/8V3YU7K39E5//Bwo90vTfzAE9Mwp1y9H5WHqoai/6JLgXK8 -DAOGpgCFhlVu8LO5O0IK3yaFhtkhC8SE/TKLzC76uSoeeSex+mJ+rqBcyDl9AONx/wQBA1ax -FAGSVKH6no4iMVtLeiYDACtVsQ4oTGIR7wAakh4QkO5j81Vg0+v3AGMNvTMlTmwtlGtmKv2M -01WryUpzA9dKe8RBhe4Uofa7OVOAaN8RujSNXMM2XWCoH+Om8oGSzmMvT2MTOa4rrk6+Noer -tShKnDDI/SojOkVMR19mYWN0b3I6AADKAiaJiV+4kJIpYCgbjafKyy11LI3mgHQV8Hf9KiM6 -RUxHX2ZhY3RvcjoAAMoDjg2kuv69NwxJNr89un9g6yT/mlXDM36tFf0qIzpFTEdfZmFjdG9y -OgAAygPBg2CM/6uXiIHWF2kf/4p3sDJXQ3jZm8bH/SIjY3JlYXRlZCBieSBHTlVQRyB2MC4y -LjE1YSAoTGludXgptChUZXN0IG9uZSAocHA9ZGVmKSA8b25lQHRlc3Qubm93aGVyZS5uaWw+ -iNcDBRM1RYG4PGu75p0mbg8QAw/+AwDfK2nbX4uztjrEzVY0KkyEj/QCeDozbAVjeb9WbVg+ -MfL47ag5OcEt6kjJNv+u0QCANaNQ/3T5rHOaJdZzHUaelVUTRVbLI22FnpEZ8baud+EGglUw -av9P+DB6MHBKqYsC/2Xih+3YOHjVDcAPaZPWUVuBISe3qP+NMNOSJsxZB31oHyWmSEzTvTwI -yBLlV1N8NG4GzmIrzs27Hfo9nbW+vd/ktfVfelUVIhpvVJQcO2qhtV2LEhI/tiOpvIJLEccj -jZUBQAM1RYIBAAAQAyDcjtZXiCsb6HnuqItM5CPUgienUkxB+/5BE6nrTQK46gpXpztStAFX -fjKjGo5fe24OYlGBmpueTxApJKMzpbHA8wxfXsVmOrHsuOHQUREIYFy1VhOBmdRt7MvOWg/r -FR4McJc/AAMFAyCwFfMOhS+z6YInnQDh7JTLan+7IdSHjUpAo0XarzAioCq6Ei0LaPVqa1zF -L9yh5ky+06WTWnfvMSVCu0eRh1E0dTiBUDCb06HRvEVOiTmhqHk6loLOtb9NHxYMGOrGDtdX -JJrHAAMfaR/MS44PJRtwrFDIBTOJWqjdX1Mu3wzB3443rS+hv9onUUjeLNbXFzXAxxHTLm4Z -0JQ1Um2Yi4XGTYZkFNRPq5jE+Imoj/trN+T2rri1f+m/Y5ugSH/Zx7hurhc/3yJ//oCGYTNb -/SsjOkVMR19mYWN0b3I6AADVEOrdw68kJz/XyG9/nJZ40oqzBklaf+BeatFD/SsjOkVMR19m -YWN0b3I6AADVF7ggxjMhZ+iMjbJxRSS5vmro7mbuP+5W5gLR/SsjOkVMR19mYWN0b3I6AADV -F5fMXChN1OIqFi7DHiaDKWyRJcNk6EaDu0BF/SIjY3JlYXRlZCBieSBHTlVQRyB2MC4yLjE1 -YSAoTGludXgptCd0ZXN0IHR3byAobm8gcHApIDx0d29AdGVzdC5ub3doZXJlLm5pbD6I3wMF -EzVFggEO+eDoLl+k9BADkLEDHR+OG+ItBNWQE75V5vFHruJ0blRPEPaJL0GnVW/Lgi8jcUaM -7RwJyZ2XeMiCeJHU1kgHTa/E5VSUZJM5q/w1c1vcy76Izxqgnx19TEFEcGxzbzHLyT3APQVg -eRtXsy3Mr5kfdCsDH36a6npXeeHPPkpteGg7IkOoeHKWqQdI7O84akhPyCg79VZYcuhxszM3 -BHjafWliyB7IcgfCdmmcmG39SkmAIvRAW2DAIxmGHzd7jA+NOro9O+s1to31hEyyWvq6x+wr -tGRBuqSVAUcDNUWCZQAAEAMAlmULKDSSSPLtZ1fuVWWl2amQZ/rpN36f5su5fWC0HleUvVO+ -joHcNJWv2Ill9pvAMPoTuO6WLMLMkYtpbvxRP3a9KNAgedyweBJxST4gR6wfK5t8CNeNgUHi -fQ4+WFPzAAMGAv9YAdDaBZdkIW2GPN7bi4P1JSJDPAmbcbV0fb30KtFIK1bg6Hi8dP5pZ1pv -KZibB0ftK/LC9so5ez9EUPhSbYmjE1R4oScoV7pAjtWzzNz1/C/0LJlxc1nH5mr5NdcaTzX/ -BAEDG+unPjMgny2Egnnpj+C75wL9WMnkY/0W6WbEnAa5AQisByWpoBmEox4n3ujQqonm6UXY -/gjQXe4Xc7ZwNOvDMo7FpSb22HAbXM0RX7WYSYiH3bFTS8ZbodTx9xhDK0rMPE/Ci7wbYMWZ -YyTuRz49WOO1MMb9KiM6RUxHX2ZhY3RvcjoAAMoCbaGz3MaDbSFTmKdOGCSNFFsowjco3mWH -U/0qIzpFTEdfZmFjdG9yOgAAygLi9An6HulYgRcvIO1/Rn1ZAcrG447MbdxD/SojOkVMR19m -YWN0b3I6AADKAo2787sJdMSkDQ6ENCcVlu+yXsVSWa++zWH9IiNjcmVhdGVkIGJ5IEdOVVBH -IHYwLjIuMTVhIChMaW51eCm0LHRlc3QgdGhyZWUgKHBwPWFiYykgPHRocmVlQHRlc3Qubm93 -aGVyZS5uaWw+iNcDBRM1RYJlZE80um0R1tMQA1bRAv9mehnmJtPFKcQ+S9AzBHDNF77nk58l -37bQ05uA5H6L5+HzBolCFFR5ehfXYkzwYb6g6PsrP7N+Nrbtw5xDZq38hZK1G0f5/InOIfxQ -dYdmlrSD+53gOH91KGeqpSrd7l0C/2ZhobXCxF03goKfNENvjej4HAGnzN0q0mpfu7L2wsCG -4/kXKv8W6Z2JtYpnszyw6xJCh0dyup2RSYKbfZMrb1BfjwlrZE03Ah4QRmat5byprwl9oosJ -tW5GlGnLFCLsPQ== -=VGBx ------END PGP ARMORED FILE----- diff --git a/checks/secring.skr.asc b/checks/secring.skr.asc deleted file mode 100644 index 0081b59c1..000000000 --- a/checks/secring.skr.asc +++ /dev/null @@ -1,27 +0,0 @@ -This is a test secring generated by pgp 5 beta - -Type Bits KeyID Created Expires Algorithm Use -sec+ 768 439F02CA 1998-03-17 ---------- DSS Sign and Encrypt -sub 768 CB879DE9 1998-03-17 ---------- Diffie-Hellman -uid pgp5 test - -There is no password on the key - ------BEGIN PGP ARMORED FILE----- -Version: GNUPG v0.2.13a (Linux) -Comment: This is an alpha version! -Comment: Use "gpgm --dearmor" for unpacking - -lQFbBDUOrE4RAwDbbxWAbWsheUJprK6VryMTpwDiYwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEm -Sppp/6/Ygp+N3n32Kznq7PjHXiuWLlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUAoP+KBFly -qNMdsK8j+ZO0A8rnImGrAwC1ddDme5iZFkTEWHhrtU97sEu2GDkSQB8HdX8CoRcrOz/B2WliF6qf -BKhcZPFVBIhKNzjTfY7SEYAZk2zcsCm8elnwSLaGEzxKFNFBqKDNXP+a35spcqsHSGzDVw4VuKMD -AJNnAP6skpHlhVAmecLZT9eRzVoOq1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXv -dCT24hlfoGoXzkoDInkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLQAAn3GbgsWo+7E/hWakzstp -TXzI2kDIDIm0GXBncDUgdGVzdCA8cGdwNUBkZXYubnVsbD6dAO8ENQ6sVhADAP8Fa5TbD6k8VmW1 -IjK1DfDI0xUdsVIbk8N3Hb0YIlT1E/6tZdfiNwqaKVQcf17gJIObBwfNM3OqWYOudmBVd3S6E3Hk -u64nW+ZNt7B2toWRgnk6OgHcSDsud4Igjwz/RQACAgL/ToefzlcVKiPuobKfXHDhIUQPTfGic2Az -47wkMoYHo9j9ZE7AWaliMdPz4jLyLfqqoU9mH8g+vJhyAc7UnAF2Sk5466FDypdPm5F9PTW3cqqI -wJM4WgkSlM8J2hxH4YtlAADlG+pxFXNFuDPmcq6jL6dug2ikZ7hcHLAy7DddSS8OAA== -=1UWo ------END PGP ARMORED FILE----- diff --git a/checks/signdemokey b/checks/signdemokey deleted file mode 100755 index e387446c2..000000000 --- a/checks/signdemokey +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -set -e - -if [ $# != 3 ]; then - echo "Usage: signdemokey name user_id user_id_no" - exit 1 -fi -name="$1" -user_id="$2" -user_id_no="$3" - -echo "abc" | ../g10/gpg --options ./options --homedir $name \ - --sign-key --batch --yes --passphrase-fd 0 $user_id \ - $user_id_no sign save - diff --git a/checks/signencrypt-dsa.test b/checks/signencrypt-dsa.test deleted file mode 100755 index 41bf83164..000000000 --- a/checks/signencrypt-dsa.test +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking signing and encryption for DSA -for i in $plain_files $data_files ; do - $GPG $dsa_keyrings --always-trust -se -o x --yes \ - -u "$dsa_usrname1" -r "$dsa_usrname2" $i - $GPG $dsa_keyrings -o y --yes x - cmp $i y || error "$i: mismatch" -done - -for da in ripemd160 sha1; do - for i in $plain_files; do - $GPG $dsa_keyrings --always-trust -se -o x --yes --digest-algo $da \ - -u "$dsa_usrname1" -r "$dsa_usrname2" $i - $GPG $dsa_keyrings -o y --yes x - cmp $i y || error "$i: mismatch" - # process only the first one - break - done -done diff --git a/checks/signencrypt.test b/checks/signencrypt.test deleted file mode 100755 index 1d05990fc..000000000 --- a/checks/signencrypt.test +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - - -#info Checking signing and encryption -for i in $plain_files $data_files ; do - echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust \ - -se -o x --yes -r "$usrname2" $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - diff --git a/checks/sigs-dsa.test b/checks/sigs-dsa.test deleted file mode 100755 index 2294cf55a..000000000 --- a/checks/sigs-dsa.test +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking DSA signatures (default digest algo) -for i in $plain_files $data_files; do - $GPG $dsa_keyrings -s -o x --yes -u $dsa_usrname1 $i - $GPG $dsa_keyrings -o y --yes x - cmp $i y || error "$i: mismatch" -done - -for da in ripemd160 sha1; do - for i in $plain_files; do - $GPG $dsa_keyrings --digest-algo $da \ - -s -o x --yes -u $dsa_usrname1 $i - $GPG $dsa_keyrings -o y --yes x - cmp $i y || error "$i: mismatch" - # process only the first one - break - done -done - diff --git a/checks/sigs.test b/checks/sigs.test deleted file mode 100755 index 7a8f998c1..000000000 --- a/checks/sigs.test +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -#info Checking signatures -for i in $plain_files $data_files; do - echo "$usrpass1" | $GPG --passphrase-fd 0 -s -o x --yes $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" -done - -hash_algo_list="ripemd160 sha1 md5" -if have_hash_algo "TIGER192"; then - hash_algo_list="$hash_algo_list tiger192" -fi - -for da in $hash_algo_list ; do - for i in $plain_files; do - echo "$usrpass1" | $GPG --passphrase-fd 0 --digest-algo $da \ - -s -o x --yes $i - $GPG -o y --yes x - cmp $i y || error "$i: mismatch" - # process only the first one - break - done -done diff --git a/checks/version.test b/checks/version.test deleted file mode 100755 index f1fd7284f..000000000 --- a/checks/version.test +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -. $srcdir/defs.inc || exit 3 - -# print the GPG version -$GPG --version - -#fixme: check that the output is correct - diff --git a/cipher/ChangeLog b/cipher/ChangeLog deleted file mode 100644 index b47340064..000000000 --- a/cipher/ChangeLog +++ /dev/null @@ -1,1027 +0,0 @@ -2002-10-12 Werner Koch - - * rndunix.c (my_popen): Make sure that stdin and stderr are - connected to a file. This is to avoid NetBSD to complain about - set{u,g}id programs invoked with fd 0, 2 closed. Reported by - Cristian Biere. - (start_gatherer): Likewise. Reordered code. - -2002-10-02 David Shaw - - * tiger.c (tiger_get_info): Select the OID to use for TIGER at - compile time. - -2002-09-27 David Shaw - - * Makefile.am, md.c (load_digest_module): TIGER is now always - enabled. - -2002-09-26 Werner Koch - - * tiger.c (tiger_get_info): Use a regular OID. Note that this - breaks all TIGER generated signatures; if we want to do something - about it we have to do it in ../g10/sig-check.c . - -2002-09-17 Werner Koch - - * rndw32.c (SIZEOF_DISK_PERFORMANCE_STRUCT): Increased to 256. - -2002-09-12 Stefan Bellon - - * rand-internal.h (rndriscos_gather_random): Added prototype. - -2002-08-30 Werner Koch - - * random.c: Automagically detect the entropy gatherer when - this feature is configured. - * rndegd.c (rndegd_connect_socket): New. Factored out from .. - (rndegd_gather_random): here and call it. - (do_read): Update the counter variables correctly. This was not a - problem due to the way EGD works. Bug found by Christian Biere. - -2002-08-20 Werner Koch - - * primegen.c (generate_elg_prime): Return all factors for mode 1. - Bug reported by Bob Mathews. - -2002-08-12 Werner Koch - - * cipher.c: Include the DUMMY cipher only when the new ALLOW_DUMMY - is defined. It should only be defined for hard core debugging. - -2002-08-08 David Shaw - - * Makefile.am, md.c (load_digest_module): Allow switching TIGER on - and off via configure. - -2002-08-07 David Shaw - - * md.c (md_algo_present): New function to check if a given algo is - in use for a given MD_HANDLE. - -2002-08-04 Werner Koch - - * blowfish.h, cast5.h, des.h: Removed after moving all prototypes to - * algorithms.h: here. Changed all sources to use this one. - -2002-08-03 Stefan Bellon - - * idea-stub.c (idea_get_info): RISC OS' Norcroft C needs a cast. - * random.c (getfnc_gather_random): Added RISC OS support. - * rndriscos.c: Removed dynload code and tidied up a bit. - -2002-08-03 Werner Koch - - * rndegd.c (do_read): Handle case when read returns 0 to avoid - gpg hanging when EGD died. By Christian Biere. - -2002-08-02 Werner Koch - - The big extension removal. - - * Makefile.am: Removed all extension stuff. - * dynload.c: Removed everything except for - register_cipher_extension. - (dynload_enum_module_names): New. - * dynload.h: Removed. - * random.c (getfnc_gather_random,getfnc_fast_random_poll): - New. Replaced all dynload functions with these ones. - * rndunix.c (rndunix_gather_random): Renamed from - gather_random. Made global. Removed all dynload stuff. - * rndlinux.c (rndlinux_gather_random): Likewise. - * rndegd.c (rndegd_gather_random): Likewise. - * rndw32.c (rndw32_gather_random) - (rndw32_gather_random_fast): Likewise. Also removed the unsued - entropy dll code. - * md.c (new_list_item): Changed return value to indicate whether - an algorithms was loaded. - (load_digest_module): Simplified by removing all the dynload code. - * algorithms.h: New. - * md5.c (md5_get_info): Made global. Removed all dynload stuff. - * rmd160.c (rmd160_get_info): Likewise. - * sha1.c (sha1_get_info): Likewise. - * tiger.c (tiger_get_info): Likewise. Return NULL if we can't use - this module. - * idea-stub.c: New. - * blowfish.h (idea_get_info): Add prototype. - * cipher.c (setup_cipher_table): Try to load IDEA. - (load_cipher_modules): Removed all dynload code. - * pubkey.c (load_pubkey_modules): Removed the dynloading code. - -2002-07-25 David Shaw - - * random.c: "warning" -> "WARNING" - -2002-07-02 Werner Koch - - * rndw32.c (slow_gatherer_windowsNT): Use a simple array for the - disk performance structure and increase it to the size required by - W2000. - -2002-06-29 Werner Koch - - * rndlinux.c: Removed HAVE_LINUX_RANDOM_H conditional because it - was never used and the configure test did set the wrong macro - anyway. - -2002-05-07 Stefan Bellon - - * md.c (md_start_debug): Use EXTSEP_S instead of ".". - -2002-04-24 Werner Koch - - * tiger.c (tiger_final): Removed superfluous token pasting operators. - * md5.c (md5_final): Ditto. - -2002-04-22 Stefan Bellon - - * rndriscos.c (func_table): Made func a function pointer. - (init_device): Improved loading of CryptRandom module. - -2002-04-18 Werner Koch - - * rndlinux.c, rndegd.c, rndunix.c (func_table): Made func a - function pointer. Note that we still need to change the module - interface to cope with data vs function pointer problems. Hmmm, - even dlsym has a problem with this. - -2002-04-10 David Shaw - - * cipher.c (setup_cipher_table, cipher_open, cipher_encrypt, - cipher_decrypt, dummy_setkey, dummy_encrypt_block, - dummy_decrypt_block): the dummy cipher should only be built on - development versions. - -2002-04-06 Werner Koch - - * rijndael.c (rijndael_get_info): We do only support a 128 bit - blocksize so it makes sense to change the algorithm strings to - AES. - * cipher.c (string_to_cipher_algo): Map "RIJNDAEL" to "AES". - -2002-02-14 Werner Koch - - * random.c (mix_pool): Removed the failsafe stuff again. It makes - the code more complicate and may give the path to more bugs. - -2002-02-10 Werner Koch - - * random.c (mix_pool): Carry an extra failsafe_digest buffer - around to make the function more robust. - -2002-02-08 Werner Koch - - * random.c (add_randomness): Xor new data into the pool and not - just copy it. This avoids any choosen input attacks which are not - serious in our setting because an outsider won't be able to mix - data in and even then we keep going with a PRNG. Thanks to Stefan - Keller for pointing this out. - -2002-01-02 Stefan Bellon - - * rndriscos.c [__riscos__]: Updated include file name. - -2001-12-21 Werner Koch - - * Makefile.am (DISCLEANFILES): Add construct.c - -2001-12-19 Werner Koch - - * rndw32.c [CYGWIN32]: Include winioctl.h. By Disastry. - -2001-11-08 Werner Koch - - * primegen.c (gen_prime): Set 2 high order bits for secret primes. - * rsa.c (generate): Loop until we find the exact modulus size. - Changed the exponent to 41. - -2001-10-22 Werner Koch - - * Makefile.am: Need to use $(EXEEXT) where approriate. - -2001-09-09 Werner Koch - - * rsa.c (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings. - -2001-08-24 Werner Koch - - * md.c (md_write): Made buf arg const. - -2001-08-22 Werner Koch - - * random.c (fast_random_poll): Don't use gethrtime if it is broken. - -2001-08-20 Werner Koch - - Applied patches from Stefan Bellon to support - RISC OS. Nearly all of these patches are identified by the - __riscos__ macro. - * blowfish.c, twofish.c: Added pragmas for use with a Norcraft - compiler. - * dynload.c, md5.c, rmd160.c, sha1.c: Minor patches for RISC OS. - * rndriscos.c: New. - * rnd-internal.h: Added prototype. - * random.c (fast_random_poll): Use '#if defined' instead of just - 'defined'; needed for RISC OS. - * primegen.c (gen_prime): count? are now ints for consistence - with is_prime(). - -2001-08-08 Werner Koch - - * rndw32.c (gather_random): Use toolhelp in addition to the NT - gatherer for Windows2000. Suggested by Sami Tolvanen. - - * random.c (read_pool): Fixed length check, this used to be one - byte to strict. Made an assert out of it because the caller has - already made sure that only poolsize bytes are requested. - Reported by Marcus Brinkmann. - -2001-07-18 Werner Koch - - * rndlinux.c (gather_random): casted a size_t arg to int so that - the format string is correct. Casting is okay here and avoids - translation changes. - -2001-06-12 Werner Koch - - * cipher.c (string_to_cipher_algo): Use ascii_strcasecmp(). - * md.c (string_to_digest_algo): Ditto. - * pubkey.c (string_to_pubkey_algo): Ditto. - * rndw32.c (slow_gatherer_windowsNT): Ditto. Not really needed - here but anyway. - -2001-04-29 Werner Koch - - * random.c (fast_random_poll): Do not check the return code of - getrusage. - -2001-04-17 Werner Koch - - * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 - and 8. - -2001-04-16 Werner Koch - - * dynload.c [__MINGW32__]: Applied patch from Timo Schulz to make - it work under W32. This patches is based on the one from - Disastry@saiknes.lv - -2001-04-06 Werner Koch - - * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c (burn_stack): - New. Add wrappers for most functions to be able to call - burn_stack after the function invocation. This methods seems to be - the most portable way to zeroise the stack used. It does only work - on stack frame based machines but it is highly portable and has no - side effects. Just setting the automatic variables at the end of - a function to zero does not work well because the compiler will - optimize them away - marking them as volatile would be bad for - performance. - * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. - * random.c (burn_stack): New. - (mix_pool): Use it here to burn the stack of the mixblock function. - -2001-04-02 Werner Koch - - * primegen.c (generate_elg_prime): I was not initialized for mode - != 1. Freed q at 3 places. Thanks to Tommi Komulainen. - -2001-03-28 Werner Koch - - * md5.c (md5_final): Fixed calculation of hashed length. Thanks - to disastry@saiknes.lv for pointing out that it was horrible wrong - for more than 512MB of input. - * sha1.c (sha1_final): Ditto. - * rmd160.c (rmd160_final): Ditto. - * tiger.c (tiger_final): Ditto. - -2001-03-19 Werner Koch - - * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to - avoid name clahses with an encrypt function in stdlib.h of - Dynix/PIX. Thanks to Gene Carter. - * elgamal.c (encrypt,do_encrypt): Ditto. - -2001-03-12 Werner Koch - - * twofish.c (gnupgext_enum_func): Add some static when comnpiled - as a module. - - * tiger.c (tiger_get_info): Return "TIGER192" and not just - "TIGER". By Edwin Woudt. - -2001-03-08 Werner Koch - - * random.c: Always include time.h - standard requirement. Thanks - to James Troup. - -2001-01-18 Werner Koch - - * rndw32.c: Fixed typo and wrong ifdef for VER_PLATFORM* macro - -2001-01-12 Werner Koch - - * cipher.c (cipher_encrypt,cipher_encrypt): Use blocksize and - not 8 for CBC mode (However: we don't use CBS in OpenPGP). - -2000-11-22 Werner Koch - - * rndegd.c (gather_random): Fixed default socket to be '=entropy'. - Thanks to Tomasz Kozlowski. - -2000-10-12 Werner Koch - - * rijndael.c: New. - * cipher.c: Add Rijndael support. - -Wed Oct 4 15:50:18 CEST 2000 Werner Koch - - * sha1.c (transform): Use rol() macro. Actually this is not needed - for a newer gcc but there are still aoter compilers. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch - - * random.c (fast_random_poll): Check ENOSYS for getrusage. - * rndunix.c: Add 2 sources for QNX. By Sam Roberts. - -Wed Sep 13 18:12:34 CEST 2000 Werner Koch - - * rsa.c (secret): Speed up by using the CRT. For a 2k keys this - is about 3 times faster. - (stronger_key_check): New but unused code to check the secret key. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch - - * rsa.c: Changed the comment about the patent. - * Makefile.am: Included rsa.[ch]. - * pubkey.c: Enabled RSA support. - (pubkey_get_npkey): Removed RSA workaround. - -Fri Aug 25 16:05:38 CEST 2000 Werner Koch - - * rndlinux.c (open_device): Loose random device checking. - By Nils Ellmenreich. - - * rndegd.c (gather_random): Name of socket is nom configurable. - -Wed Jun 28 11:54:44 CEST 2000 Werner Koch - - * rsa.c, rsa.h: New based on the old module version (only in CVS for now). - * pubkey.c (setup_pubkey_table): Added commented support for RSA. - -Fri Jun 9 10:09:52 CEST 2000 Werner Koch - - * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. - (my_popen): Do the FD_CLOEXEC only if it is available - (start_gatherer): Cope with missing _SC_OPEN_MAX - -Sun May 28 13:55:17 CEST 2000 Werner Koch - - * random.c (read_seed_file): Binary open for DOSish system - (update_random_seed_file): Ditto. - - * rndw32.c: Add some debuging code enabled by an environment variable. - -Tue May 23 09:19:00 CEST 2000 Werner Koch - - * rndw32.c: Started with alternative code to replace entropy.dll - -Thu May 18 11:38:54 CEST 2000 Werner Koch - - * primegen.c (register_primegen_progress): New. - * dsa.c (register_pk_dsa_progress): New. - * elgamal.c (register_pk_elg_progress): New. - -Fri Apr 14 19:37:08 CEST 2000 Werner Koch - - * twofish.c (twofish_get_info): Fixed warning about cast. - -Tue Mar 28 14:26:58 CEST 2000 Werner Koch - - * random.c [MINGW32]: Include process.h for getpid. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch - - * random.c (fast_random_poll): Add clock_gettime() as fallback for - system which support this POSIX.4 fucntion. By Sam Roberts. - - * rndunix.c: Add some more headers for QNX. By Sam Roberts. - - * random.c (read_seed_file): Removed the S_ISLNK test becuase it - is already covered by !S_ISREG and is not defined in Unixware. - Reported by Dave Dykstra. - - * sha1.c (sha1_get_info): Removed those stupid double lines. Dave - is really a good lint. - -Wed Feb 23 10:07:57 CET 2000 Werner Koch - - * twofish.c (twofish_get_info): Add some const to the casts. By Martin - Kahlert. - -Mon Feb 14 14:30:20 CET 2000 Werner Koch - - (update_random_seed_file): Silently ignore update request when pool - is not filled. - -Fri Feb 11 17:44:40 CET 2000 Werner Koch - - * random.c (read_seed_file): New. - (set_random_seed_file): New. - (read_pool): Try to read the seeding file. - (update_random_seed_file): New. - - (read_pool): Do an initial extra seeding when level 2 quality random - is requested the first time. This requestes at least POOLSIZE/2 bytes - of entropy. Compined with the seeding file this should make normal - random bytes cheaper and increase the quality of the random bytes - used for key generation. - - * rndegd.c (gather_random): Shortcut level 0. - * rndunix.c (gather_random): Ditto. - * rndw32.c (gather_random): Ditto. - -Fri Jan 14 18:32:01 CET 2000 Werner Koch - - * rmd160.c (rmd160_get_info): Moved casting to the left side due to a - problem with UTS4.3. Suggested by Dave Dykstra. - * sha1.c (sha1_get_info): Ditto. - * tiger.c (tiger_get_info): Ditto. - * md5.c (md5_get_info): Ditto - * des.c (des_get_info): Ditto. - * blowfish.c (blowfish_get_info): Ditto. - * cast5.c (cast5_get_info): Ditto. - * twofish.c (twofish_get_info): Ditto. - -Thu Jan 13 19:31:58 CET 2000 Werner Koch - - * elgamal.c (wiener_map): New. - (gen_k): Use a much smaller k. - (generate): Calculate the qbits using the wiener map and - choose an x at a size comparable to the one choosen in gen_k - - * random.c (read_pool): Print a more friendly error message in - cases when too much random is requested in one call. - - * Makefile.am (tiger): Replaced -O1 by -O. Suggested by Alec Habig. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch - - * primegen.c (generate_elg_prime): All primes are now generated with - the lowest random quality level. Becuase they are public anyway we - don't need stronger random and by this we do not drain the systems - entropy so much. - -Thu Oct 28 16:08:20 CEST 1999 Werner Koch - - * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; - this is not the case for some ESIX and Unixware, although they have - getrusage(). - - * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). - -Mon Oct 11 09:24:12 CEST 1999 Werner Koch - - * rndw32.c (gather_random): Handle PCP_SEEDER_TOO_SMALL. - -Sat Oct 9 20:34:41 CEST 1999 Werner Koch - - * Makefile.am: Tweaked module build and removed libtool - -Fri Oct 8 20:32:01 CEST 1999 Werner Koch - - * rndw32.c (load_and_init_winseed): Use the Registry to locate the DLL - -Mon Oct 4 21:23:04 CEST 1999 Werner Koch - - * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for - fixing this bug. - -Sat Sep 18 12:51:51 CEST 1999 Werner Koch - - * Makefile.am: Never compile mingw32 as module - -Wed Sep 15 14:39:59 CEST 1999 Michael Roth - - * des.c: Various speed improvements: One bit pre rotation - trick after initial permutation (Richard Outerbridge). - Finished test of SSLeay Tripple-DES patterns. - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch - - * rndw32.c: New. - -Mon Sep 13 10:51:29 CEST 1999 Werner Koch - - * bithelp.h: New. - * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h - -Tue Sep 7 16:23:36 CEST 1999 Werner Koch - - * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. - -Mon Sep 6 19:59:08 CEST 1999 Werner Koch - - * des.c (selftest): Add some testpattern - -Mon Aug 30 20:38:33 CEST 1999 Werner Koch - - * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using - in place encryption. Pointed out by Frank Stajano. - -Mon Jul 26 09:34:46 CEST 1999 Werner Koch - - * md5.c (md5_final): Fix for a SCO cpp bug. - -Thu Jul 15 10:15:35 CEST 1999 Werner Koch - - * elgamal.c (elg_check_secret_key,elg_encrypt - elg_decrypt,elg_sign,elg_verify): Sanity check on the args. - * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. - - * pubkey.c (disable_pubkey_algo): New. - (check_pubkey_algo2): Look at disabled algo table. - * cipher.c (disable_cipher_algo): New. - (check_cipher_algo): Look at disabled algo table. - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch - - * Makefile.am: Support for libtool. - -Fri Jul 2 11:45:54 CEST 1999 Werner Koch - - * dsa.c (gen_k): Changed algorithm to consume less random bytes - * elgamal.c (gen_k): Ditto. - - * random.c (random_dump_stats): New. - -Thu Jul 1 12:47:31 CEST 1999 Werner Koch - - * primegen.c, elgamal.c, dsa.c (progess): New and replaced all - fputc with a call to this function. - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch - - * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. - - * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. - - * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). - * Makefile.am (install-exec-hook): Removed. - -Sun May 23 14:20:22 CEST 1999 Werner Koch - - * cipher.c (setup_cipher_table): Enable Twofish - - * random.c (fast_random_poll): Disable use of times() for mingw32. - -Mon May 17 21:54:43 CEST 1999 Werner Koch - - * dynload.c (register_internal_cipher_extension): Minor init fix. - -Tue May 4 15:47:53 CEST 1999 Werner Koch - - * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug - that we didn't correct for step when passing the prime to the - Rabin-Miller test which led to bad performance (Stefan Keller). - (check_prime): Add a first Fermat test. - -Sun Apr 18 10:11:28 CEST 1999 Werner Koch - - * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. - - * random.c (randomize_buffer): alway use secure memory because - we can't use m_is_secure() on a statically allocated buffer. - - * twofish.c: Replaced some macros by a loop to reduce text size. - * Makefile.am (twofish): No more need for sed editing. - -Fri Apr 9 12:26:25 CEST 1999 Werner Koch - - * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. - - * blowfish.c: Dropped the Blowfish 160 mode. - * cipher.c (cipher_open): Ditto. - (setup_cipher_table): Ditto. And removed support of twofish128 - -Wed Apr 7 20:51:39 CEST 1999 Werner Koch - - * random.c (get_random_bits): Can now handle requests > POOLSIZE - - * cipher.c (cipher_open): Now uses standard CFB for automode if - the blocksize is gt 8 (according to rfc2440). - - * twofish.c: Applied Matthew Skala's patches for 256 bit key. - -Tue Apr 6 19:58:12 CEST 1999 Werner Koch - - * random.c (get_random_bits): Can now handle requests > POOLSIZE - - * cipher.c (cipher_open): Now uses standard CFB for automode if - the blocksize is gt 8 (according to rfc2440). - -Sat Mar 20 11:44:21 CET 1999 Werner Koch - - * rndlinux.c (tty_printf) [IS_MODULE]: Removed. - - * rndegd.c (gather_random): Some fixes. - -Wed Mar 17 13:09:03 CET 1999 Werner Koch - - * rndegd.c (do_read): New. - (gather_random): Changed the implementation. - -Mon Mar 8 20:47:17 CET 1999 Werner Koch - - * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. - -Fri Feb 26 17:55:41 CET 1999 Werner Koch - - * md.c: Nearly a total rewrote. - -Wed Feb 24 11:07:27 CET 1999 Werner Koch - - * cipher.c (context): Fixed alignment - * md.c: Ditto. - - * rndegd.c: New - -Mon Feb 22 20:04:00 CET 1999 Werner Koch - - * rndegd.c: New. - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - * Makefile.am: Modules are now figured out by configure - * construct.c: New. Generated by configure. Changed all modules - to work with that. - * sha1.h: Removed. - * md5.h: Removed. - - * twofish.c: Changed interface to allow Twofish/256 - - * rndunix.c (start_gatherer): Die on SIGPIPE. - -Wed Jan 20 18:59:49 CET 1999 Werner Koch - - * rndunix.c (gather_random): Fix to avoid infinite loop. - -Sun Jan 17 11:04:33 CET 1999 Werner Koch - - * des.c (is_weak_key): Replace system memcmp due to bugs - in SunOS's memcmp. - (des_get_info): Return error on failed selftest. - * twofish.c (twofish_setkey): Return error on failed selftest or - invalid keylength. - * cast5.c (cast_setkey): Ditto. - * blowfish.c (bf_setkey): Return error on failed selftest. - -Tue Jan 12 11:17:18 CET 1999 Werner Koch - - * random.c (random_is_faked): New. - - * tiger.c: Only compile if we have the u64 type - -Sat Jan 9 16:02:23 CET 1999 Werner Koch - - * rndunix.c (gather_random): check for setuid. - - * Makefile.am: Add a way to staically link random modules - -Thu Jan 7 18:00:58 CET 1999 Werner Koch - - * md.c (md_stop_debug): Do a flush first. - (md_open): size of buffer now depends on the secure parameter - -Sun Jan 3 15:28:44 CET 1999 Werner Koch - - * rndunix.c (start_gatherer): Fixed stupid ==/= bug - -1998-12-31 Geoff Keating - - * des.c (is_weak_key): Rewrite loop end condition. - -Tue Dec 29 14:41:47 CET 1998 Werner Koch - - * random.c: add unistd.h for getpid(). - (RAND_MAX): Fallback value for Sun. - -Wed Dec 23 17:12:24 CET 1998 Werner Koch - - * md.c (md_copy): Reset debug. - -Mon Dec 14 21:18:49 CET 1998 Werner Koch - - * random.c (read_random_source): Changed the interface to the - random gathering function. - (gather_faked): Use new interface. - * dynload.c (dynload_getfnc_fast_random_poll): Ditto. - (dynload_getfnc_gather_random): Ditto. - * rndlinux.c (gather_random): Ditto. - * rndunix.c (gather_random): Ditto. - -Sat Dec 12 18:40:32 CET 1998 Werner Koch - - * dynload.c (SYMBOL_VERSION): New to cope with system which needs - underscores. - - * rndunix.c: Rewrote large parts - -Thu Dec 10 20:15:36 CET 1998 Werner Koch - - * dynload.c (load_extension): increased needed verbosity level. - - * random.c (fast_random_poll): Fallback to a default fast random - poll function. - (read_random_source): Always use the faked entroy gatherer if no - gather module is available. - * rndlinux.c (fast_poll): Removed. - * rndunix.c (fast_poll): Removed. - - -Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rand-*.c: Removed. - * rndlinux.c : New. - * rndunix.c : New. - * random.c : Restructured the interface to the gather modules. - (intialize): Call constructor functions - (read_radnom_source): Moved to here. - * dynload.c (dynload_getfnc_gather_random): New. - (dynload_getfnc_fast_random_poll): New. - (register_internal_cipher_extension): New. - (register_cipher_extension): Support of internal modules. - -Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rand-unix.c (read_random_source): Removed the assert. - -Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) - - * pubkey.c: Hack to allow us to give some info about RSA keys back. - -Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * dynload.c: Support for DLD - -Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rand-unix.c: Now uses names from configure for /dev/random. - -1998-10-10 SL Baur - - * Makefile.am: fix sed -O substitutions to catch -O6, etc. - -Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) - * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. - -Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md.c (md_digest): New. - (md_reset): New. - -Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. - -Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) - - * des.c: Some patches from Michael. - -Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) - - * des.c : New file from Michael Roth - -Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) - - * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. - -Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) - - * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. - -Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) - - * Makefile.am: Fixes to allow a different build directory - -Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) - - * random.c (get_random_byte): Removed and changed all callers - to use get_random_bits() - -Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) - - * cipher.c : Support for other blocksizes - (cipher_get_blocksize): New. - * twofish.c: New. - * Makefile.am: Add twofish module. - -Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * random.c (read_pool): Simple alloc if secure_alloc is not set. - (get_random_bits): Ditto. - -Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) - - * dynload.c (load_extension): Function now nbails out if - the program is run setuid. - -Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rmd160.c (rmd160_hash_buffer): New. - -Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c (cipher_open): algos >=100 use standard CFB - -Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am: Support for extensions - -Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) - - * random.c (mix_pool): simpler handling for level 0 - -Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * tiger.c: Removed from dist, will reappear as dynload module - -Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * pubkey.c: Major changes to allow extensions. Changed the inteface - of all public key ciphers and added the ability to load extensions - on demand. - - * misc.c: Removed. - -Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) - - * dynload.c: New. - * cipher.c: Major changes to allow extensions. - -Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c: Major internal chnages to support extensions. - * blowfish.c (blowfish_get_info): New and made all internal - functions static, changed heder. - * cast5.c (cast5_get_info): Likewise. - -Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * tiger.c (transform): Fix for big endian - - * cipher.c (do_cfb_decrypt): Big endian fix. - -Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md.c (md_get_oid): Add a new one for TIGER. - -Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c: Add support for a dummy cipher - -Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rmd160.c (transform): fixed sigbus - I should better - add Christian von Roques's new implemenation of rmd160_write. - -Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New - * random.c: Moved system specific functions to rand-****.c - -Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) - - * random.c (fast_random_poll): add call to gethrtime. - -Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * elgamal.c (elg_generate): choosing x was not correct, could - yield 6 bytes which are not from the random pool, tsss, tsss.. - -Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) - - * primegen.c (generate_elg_prime): Add arg mode, changed all - callers and implemented mode 1. - -Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c (cipher_get_keylen): New. - -Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * tiger.c, tiger.h: New. - -Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) - - * misc.c (check_pubkey_algo2): New. - -Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c: New - * misc.c (check_cipher_algo): Moved to cipher.c - * cast5.c: Moved many functions to cipher.c - * blowfish.c: Likewise. - -Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cast5.c: Implemented and tested. - -Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) - - * elgamal.c (elg_generate): Faster generation of x in some cases. - -Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * blowfish.c (blowfish_decode_cfb): changed XOR operation - (blowfish_encode_cfb): Ditto. - -Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sha1.c (transform): Rewrote - - * blowfish.c (encrypt): Unrolled for rounds == 16 - (decrypt): Ditto. - -Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rmd160.c (transform): Unrolled the loop. - -Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) - - * random.c (read_pool): Add pool_balance stuff. - (get_random_bits): New. - - * elgamal.c (elg_generate): Now uses get_random_bits to generate x. - - -Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md.c (md_digest_length): New. - -Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) - - * dsa.c (dsa_verify): Works. - -Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) - - * dsa.c, dsa.h: Removed some unused code. - -Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md.c (md_open): Add call to fast_random_poll. - blowfish.c (blowfish_setkey): Ditto. - -Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) - - * rmd160.c (rmd160_mixblock): New. - * random.c: Restructured to start with a new RNG implementation. - * random.h: New. - -Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) - - * gost.c, gost.h: Removed because they did only conatin trash. - -Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * random.c (fill_buffer): removed error message if n == -1. - -Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md.c (md_enable): No init if called twice. - -Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * primegen.c (generate_elg_prime): Changed the progress printing. - (gen_prime): Ditto. - -Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md5.c, md.5 : Replaced by a modified version of md5.c from - GNU textutils 1.22. - -Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) - - * md.c, md.h : New debugging support - -Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) - - * misc.c (cipher_algo_to_string): New - (pubkey_algo_to_string): New. - (digest_algo_to_string): New. - - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/cipher/Makefile.am b/cipher/Makefile.am deleted file mode 100644 index 4f06a8091..000000000 --- a/cipher/Makefile.am +++ /dev/null @@ -1,63 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - -INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl - -noinst_LIBRARIES = libcipher.a - -libcipher_a_SOURCES = cipher.c \ - pubkey.c \ - md.c \ - dynload.c \ - bithelp.h \ - des.c \ - twofish.c \ - blowfish.c \ - cast5.c \ - rijndael.c \ - elgamal.c \ - elgamal.h \ - rsa.c rsa.h \ - primegen.c \ - random.h \ - random.c \ - rand-internal.h \ - rmd.h \ - dsa.h \ - dsa.c \ - g10c.c \ - smallprime.c \ - algorithms.h \ - rndlinux.c \ - rndunix.c \ - rndegd.c \ - rndw32.c \ - md5.c \ - rmd160.c \ - sha1.c \ - tiger.c - -EXTRA_libcipher_a_SOURCES = idea-stub.c - -libcipher_a_DEPENDENCIES = @IDEA_O@ -libcipher_a_LIBADD = @IDEA_O@ - -tiger.o: $(srcdir)/tiger.c - `echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' ` diff --git a/cipher/algorithms.h b/cipher/algorithms.h deleted file mode 100644 index 694a7e35c..000000000 --- a/cipher/algorithms.h +++ /dev/null @@ -1,118 +0,0 @@ -/* algorithms.h - prototypes for algorithm functions. - * 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_ALGORITHMS_H -#define GNUPG_ALGORITHMS_H 1 - -const char *dynload_enum_module_names (int seq); - - - -const char * -md5_get_info (int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ); - - -const char * -rmd160_get_info (int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ); - -const char * -sha1_get_info (int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ); - -const char * -tiger_get_info (int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ); - - -const char * -des_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ); - -const char * -cast5_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ); - - -const char * -blowfish_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ); - -const char * -twofish_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ); - -/* this is just a kludge for the time we have not yet changed the cipher - * stuff to the scheme we use for random and digests */ -const char * -rijndael_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ); - -const char * -idea_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**setkeyf)( void *c, byte *key, unsigned keylen ), - void (**encryptf)( void *c, byte *outbuf, byte *inbuf ), - void (**decryptf)( void *c, byte *outbuf, byte *inbuf ) - ); - - - -#endif /*GNUPG_ALGORITHMS_H*/ diff --git a/cipher/bithelp.h b/cipher/bithelp.h deleted file mode 100644 index 188db168a..000000000 --- a/cipher/bithelp.h +++ /dev/null @@ -1,41 +0,0 @@ -/* bithelp.h - Some bit manipulation helpers - * Copyright (C) 1999 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_BITHELP_H -#define G10_BITHELP_H - - -/**************** - * Rotate a 32 bit integer by n bytes - */ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol( u32 x, int n) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n)); - return x; -} -#else - #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - - -#endif /*G10_BITHELP_H*/ diff --git a/cipher/blowfish.c b/cipher/blowfish.c deleted file mode 100644 index bf00fc462..000000000 --- a/cipher/blowfish.c +++ /dev/null @@ -1,632 +0,0 @@ -/* blowfish.c - Blowfish encryption - * 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 - * - * For a description of the algorithm, see: - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. - * ISBN 0-471-11709-9. Pages 336 ff. - */ - -/* Test values: - * key "abcdefghijklmnopqrstuvwxyz"; - * plain "BLOWFISH" - * cipher 32 4E D0 FE F4 13 A2 03 - * - */ - -#include -#include -#include -#include -#include -#include "types.h" -#include "errors.h" -#include "algorithms.h" - - - -#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ - -#define BLOWFISH_BLOCKSIZE 8 -#define BLOWFISH_ROUNDS 16 - -typedef struct { - u32 s0[256]; - u32 s1[256]; - u32 s2[256]; - u32 s3[256]; - u32 p[BLOWFISH_ROUNDS+2]; -} BLOWFISH_context; - -static int bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ); -static void encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); -static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); - - -/* precomputed S boxes */ -static const u32 ks0[256] = { - 0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96, - 0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16, - 0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658, - 0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013, - 0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E, - 0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60, - 0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6, - 0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A, - 0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C, - 0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193, - 0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1, - 0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239, - 0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A, - 0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3, - 0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176, - 0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE, - 0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706, - 0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B, - 0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B, - 0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463, - 0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C, - 0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3, - 0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A, - 0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8, - 0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760, - 0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB, - 0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8, - 0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B, - 0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33, - 0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4, - 0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0, - 0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C, - 0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777, - 0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299, - 0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705, - 0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF, - 0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E, - 0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA, - 0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9, - 0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915, - 0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F, - 0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664, - 0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A }; - -static const u32 ks1[256] = { - 0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D, - 0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1, - 0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65, - 0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1, - 0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9, - 0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737, - 0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D, - 0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD, - 0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC, - 0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41, - 0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908, - 0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF, - 0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124, - 0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C, - 0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908, - 0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD, - 0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B, - 0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E, - 0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA, - 0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A, - 0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D, - 0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66, - 0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5, - 0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84, - 0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96, - 0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14, - 0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA, - 0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7, - 0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77, - 0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99, - 0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054, - 0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73, - 0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA, - 0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105, - 0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646, - 0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285, - 0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA, - 0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB, - 0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E, - 0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC, - 0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD, - 0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20, - 0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 }; - -static const u32 ks2[256] = { - 0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7, - 0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF, - 0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF, - 0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504, - 0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4, - 0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE, - 0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC, - 0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B, - 0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332, - 0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527, - 0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58, - 0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C, - 0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22, - 0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17, - 0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60, - 0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115, - 0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99, - 0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0, - 0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74, - 0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D, - 0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3, - 0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3, - 0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979, - 0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C, - 0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA, - 0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A, - 0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086, - 0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC, - 0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24, - 0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2, - 0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84, - 0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C, - 0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09, - 0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10, - 0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE, - 0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027, - 0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0, - 0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634, - 0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188, - 0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC, - 0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8, - 0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837, - 0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 }; - -static const u32 ks3[256] = { - 0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742, - 0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B, - 0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79, - 0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6, - 0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A, - 0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4, - 0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1, - 0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59, - 0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797, - 0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28, - 0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6, - 0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28, - 0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA, - 0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A, - 0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5, - 0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F, - 0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE, - 0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680, - 0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD, - 0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB, - 0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB, - 0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370, - 0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC, - 0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048, - 0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC, - 0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9, - 0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A, - 0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F, - 0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A, - 0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1, - 0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B, - 0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E, - 0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E, - 0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F, - 0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623, - 0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC, - 0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A, - 0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6, - 0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3, - 0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060, - 0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C, - 0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F, - 0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 }; - -static const u32 ps[BLOWFISH_ROUNDS+2] = { - 0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0, - 0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C, - 0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B }; - - - -#if BLOWFISH_ROUNDS != 16 -static inline u32 -function_F( BLOWFISH_context *bc, u32 x ) -{ - u16 a, b, c, d; - - #ifdef BIG_ENDIAN_HOST - a = ((byte*)&x)[0]; - b = ((byte*)&x)[1]; - c = ((byte*)&x)[2]; - d = ((byte*)&x)[3]; - #else - a = ((byte*)&x)[3]; - b = ((byte*)&x)[2]; - c = ((byte*)&x)[1]; - d = ((byte*)&x)[0]; - #endif - - return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d]; -} -#endif - -#ifdef BIG_ENDIAN_HOST - #define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \ - ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] ) -#else - #define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \ - ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] ) -#endif -#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0) - -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void -do_encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) -{ - #if BLOWFISH_ROUNDS == 16 - u32 xl, xr, *s0, *s1, *s2, *s3, *p; - - xl = *ret_xl; - xr = *ret_xr; - p = bc->p; - s0 = bc->s0; - s1 = bc->s1; - s2 = bc->s2; - s3 = bc->s3; - - R( xl, xr, 0); - R( xr, xl, 1); - R( xl, xr, 2); - R( xr, xl, 3); - R( xl, xr, 4); - R( xr, xl, 5); - R( xl, xr, 6); - R( xr, xl, 7); - R( xl, xr, 8); - R( xr, xl, 9); - R( xl, xr, 10); - R( xr, xl, 11); - R( xl, xr, 12); - R( xr, xl, 13); - R( xl, xr, 14); - R( xr, xl, 15); - - xl ^= p[BLOWFISH_ROUNDS]; - xr ^= p[BLOWFISH_ROUNDS+1]; - - *ret_xl = xr; - *ret_xr = xl; - - #else - u32 xl, xr, temp, *p; - int i; - - xl = *ret_xl; - xr = *ret_xr; - p = bc->p; - - for(i=0; i < BLOWFISH_ROUNDS; i++ ) { - xl ^= p[i]; - xr ^= function_F(bc, xl); - temp = xl; - xl = xr; - xr = temp; - } - temp = xl; - xl = xr; - xr = temp; - - xr ^= p[BLOWFISH_ROUNDS]; - xl ^= p[BLOWFISH_ROUNDS+1]; - - *ret_xl = xl; - *ret_xr = xr; - #endif -} - - -static void -decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) -{ - #if BLOWFISH_ROUNDS == 16 - u32 xl, xr, *s0, *s1, *s2, *s3, *p; - - xl = *ret_xl; - xr = *ret_xr; - p = bc->p; - s0 = bc->s0; - s1 = bc->s1; - s2 = bc->s2; - s3 = bc->s3; - - R( xl, xr, 17); - R( xr, xl, 16); - R( xl, xr, 15); - R( xr, xl, 14); - R( xl, xr, 13); - R( xr, xl, 12); - R( xl, xr, 11); - R( xr, xl, 10); - R( xl, xr, 9); - R( xr, xl, 8); - R( xl, xr, 7); - R( xr, xl, 6); - R( xl, xr, 5); - R( xr, xl, 4); - R( xl, xr, 3); - R( xr, xl, 2); - - xl ^= p[1]; - xr ^= p[0]; - - *ret_xl = xr; - *ret_xr = xl; - - #else - u32 xl, xr, temp, *p; - int i; - - xl = *ret_xl; - xr = *ret_xr; - p = bc->p; - - for(i=BLOWFISH_ROUNDS+1; i > 1; i-- ) { - xl ^= p[i]; - xr ^= function_F(bc, xl); - temp = xl; - xl = xr; - xr = temp; - } - - temp = xl; - xl = xr; - xr = temp; - - xr ^= p[1]; - xl ^= p[0]; - - *ret_xl = xl; - *ret_xr = xr; - #endif -} - -#undef F -#undef R - -static void -do_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) -{ - u32 d1, d2; - - d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - do_encrypt( bc, &d1, &d2 ); - outbuf[0] = (d1 >> 24) & 0xff; - outbuf[1] = (d1 >> 16) & 0xff; - outbuf[2] = (d1 >> 8) & 0xff; - outbuf[3] = d1 & 0xff; - outbuf[4] = (d2 >> 24) & 0xff; - outbuf[5] = (d2 >> 16) & 0xff; - outbuf[6] = (d2 >> 8) & 0xff; - outbuf[7] = d2 & 0xff; -} - -static void -encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) -{ - do_encrypt_block (bc, outbuf, inbuf); - burn_stack (64); -} - -static void -do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) -{ - u32 d1, d2; - - d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - decrypt( bc, &d1, &d2 ); - outbuf[0] = (d1 >> 24) & 0xff; - outbuf[1] = (d1 >> 16) & 0xff; - outbuf[2] = (d1 >> 8) & 0xff; - outbuf[3] = d1 & 0xff; - outbuf[4] = (d2 >> 24) & 0xff; - outbuf[5] = (d2 >> 16) & 0xff; - outbuf[6] = (d2 >> 8) & 0xff; - outbuf[7] = d2 & 0xff; -} - -static void -decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) -{ - do_decrypt_block (bc, outbuf, inbuf); - burn_stack (64); -} - - -static const char* -selftest(void) -{ - BLOWFISH_context c; - byte plain[] = "BLOWFISH"; - byte buffer[8]; - byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; - byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; - byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; - - bf_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 ); - encrypt_block( &c, buffer, plain ); - if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) ) - return "Blowfish selftest failed (1)."; - decrypt_block( &c, buffer, buffer ); - if( memcmp( buffer, plain, 8 ) ) - return "Blowfish selftest failed (2)."; - - bf_setkey( &c, key3, 8 ); - encrypt_block( &c, buffer, plain3 ); - if( memcmp( buffer, cipher3, 8 ) ) - return "Blowfish selftest failed (3)."; - decrypt_block( &c, buffer, buffer ); - if( memcmp( buffer, plain3, 8 ) ) - return "Blowfish selftest failed (4)."; - return NULL; -} - -#ifdef __riscos__ -/* need to switch off CSE optimisation for Norcroft C (Acorn/Pace) */ -#pragma no_optimise_cse -#endif /* __riscos__ */ - -static int -do_bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) -{ - int i, j; - u32 data, datal, datar; - static int initialized; - static const char *selftest_failed; - - if( !initialized ) { - initialized = 1; - selftest_failed = selftest(); - if( selftest_failed ) - fprintf(stderr,"%s\n", selftest_failed ); - } - if( selftest_failed ) - return G10ERR_SELFTEST_FAILED; - - for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) - c->p[i] = ps[i]; - for(i=0; i < 256; i++ ) { - c->s0[i] = ks0[i]; - c->s1[i] = ks1[i]; - c->s2[i] = ks2[i]; - c->s3[i] = ks3[i]; - } - - for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) { - #ifdef BIG_ENDIAN_HOST - ((byte*)&data)[0] = key[j]; - ((byte*)&data)[1] = key[(j+1)%keylen]; - ((byte*)&data)[2] = key[(j+2)%keylen]; - ((byte*)&data)[3] = key[(j+3)%keylen]; - #else - ((byte*)&data)[3] = key[j]; - ((byte*)&data)[2] = key[(j+1)%keylen]; - ((byte*)&data)[1] = key[(j+2)%keylen]; - ((byte*)&data)[0] = key[(j+3)%keylen]; - #endif - c->p[i] ^= data; - j = (j+4) % keylen; - } - - datal = datar = 0; - for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) { - do_encrypt( c, &datal, &datar ); - c->p[i] = datal; - c->p[i+1] = datar; - } - for(i=0; i < 256; i += 2 ) { - do_encrypt( c, &datal, &datar ); - c->s0[i] = datal; - c->s0[i+1] = datar; - } - for(i=0; i < 256; i += 2 ) { - do_encrypt( c, &datal, &datar ); - c->s1[i] = datal; - c->s1[i+1] = datar; - } - for(i=0; i < 256; i += 2 ) { - do_encrypt( c, &datal, &datar ); - c->s2[i] = datal; - c->s2[i+1] = datar; - } - for(i=0; i < 256; i += 2 ) { - do_encrypt( c, &datal, &datar ); - c->s3[i] = datal; - c->s3[i+1] = datar; - } - - - /* Check for weak key. A weak key is a key in which a value in */ - /* the P-array (here c) occurs more than once per table. */ - for(i=0; i < 255; i++ ) { - for( j=i+1; j < 256; j++) { - if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) || - (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) ) - return G10ERR_WEAK_KEY; - } - } - - return 0; -} - -#ifdef __riscos__ -#pragma optimise_cse -#endif /* __riscos__ */ - -static int -bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) -{ - int rc = do_bf_setkey (c, key, keylen); - burn_stack (64); - return rc; -} - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -const char * -blowfish_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**r_setkey)( void *c, byte *key, unsigned keylen ), - void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), - void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) - ) -{ - *keylen = 128; - *blocksize = BLOWFISH_BLOCKSIZE; - *contextsize = sizeof(BLOWFISH_context); - *(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey - = bf_setkey; - *(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt - = encrypt_block; - *(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt - = decrypt_block; - - if( algo == CIPHER_ALGO_BLOWFISH ) - return "BLOWFISH"; - return NULL; -} - diff --git a/cipher/cast5.c b/cipher/cast5.c deleted file mode 100644 index 6373886f5..000000000 --- a/cipher/cast5.c +++ /dev/null @@ -1,654 +0,0 @@ -/* cast5.c - CAST5 cipher (RFC2144) - * 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 - */ - -/* Test vectors: - * - * 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A - * plaintext = 01 23 45 67 89 AB CD EF - * ciphertext = 23 8B 4F E5 84 7E 44 B2 - * - * 80-bit key = 01 23 45 67 12 34 56 78 23 45 - * = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00 - * plaintext = 01 23 45 67 89 AB CD EF - * ciphertext = EB 6A 71 1A 2C 02 27 1B - * - * 40-bit key = 01 23 45 67 12 - * = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00 - * plaintext = 01 23 45 67 89 AB CD EF - * ciphertext = 7A C8 16 D1 6E 9B 30 2E - */ - -#include -#include -#include -#include -#include "types.h" -#include "errors.h" -#include "algorithms.h" - - -#define CIPHER_ALGO_CAST5 3 - -#define CAST5_BLOCKSIZE 8 - -typedef struct { - u32 Km[16]; - byte Kr[16]; -} CAST5_context; - -static int cast_setkey( CAST5_context *c, byte *key, unsigned keylen ); -static void encrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf ); -static void decrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf ); - - - - -static const u32 s1[256] = { -0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, -0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, -0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, -0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, -0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, -0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, -0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, -0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, -0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, -0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, -0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, -0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, -0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, -0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, -0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, -0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, -0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, -0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, -0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, -0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, -0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, -0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, -0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, -0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, -0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, -0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, -0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, -0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, -0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, -0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, -0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, -0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf -}; -static const u32 s2[256] = { -0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, -0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, -0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, -0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, -0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, -0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, -0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, -0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, -0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, -0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, -0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, -0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, -0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, -0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, -0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, -0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, -0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, -0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, -0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, -0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, -0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, -0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, -0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, -0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, -0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, -0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, -0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, -0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, -0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, -0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, -0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, -0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 -}; -static const u32 s3[256] = { -0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, -0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, -0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, -0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, -0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, -0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, -0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, -0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, -0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, -0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, -0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, -0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, -0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, -0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, -0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, -0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, -0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, -0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, -0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, -0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, -0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, -0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, -0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, -0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, -0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, -0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, -0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, -0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, -0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, -0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, -0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, -0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 -}; -static const u32 s4[256] = { -0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, -0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, -0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, -0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, -0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, -0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, -0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, -0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, -0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, -0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, -0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, -0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, -0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, -0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, -0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, -0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, -0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, -0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, -0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, -0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, -0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, -0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, -0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, -0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, -0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, -0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, -0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, -0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, -0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, -0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, -0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, -0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 -}; -static const u32 s5[256] = { -0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, -0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, -0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, -0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, -0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, -0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, -0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, -0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, -0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, -0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, -0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, -0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, -0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, -0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, -0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, -0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, -0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, -0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, -0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, -0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, -0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, -0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, -0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, -0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, -0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, -0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, -0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, -0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, -0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, -0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, -0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, -0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 -}; -static const u32 s6[256] = { -0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, -0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, -0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, -0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, -0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, -0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, -0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, -0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, -0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, -0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, -0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, -0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, -0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, -0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, -0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, -0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, -0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, -0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, -0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, -0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, -0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, -0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, -0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, -0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, -0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, -0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, -0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, -0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, -0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, -0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, -0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, -0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f -}; -static const u32 s7[256] = { -0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, -0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, -0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, -0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, -0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, -0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, -0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, -0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, -0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, -0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, -0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, -0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, -0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, -0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, -0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, -0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, -0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, -0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, -0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, -0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, -0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, -0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, -0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, -0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, -0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, -0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, -0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, -0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, -0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, -0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, -0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, -0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 -}; -static const u32 s8[256] = { -0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, -0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, -0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, -0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, -0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, -0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, -0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, -0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, -0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, -0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, -0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, -0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, -0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, -0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, -0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, -0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, -0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, -0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, -0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, -0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, -0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, -0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, -0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, -0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, -0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, -0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, -0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, -0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, -0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, -0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, -0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, -0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e -}; - - -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol(int n, u32 x) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n)); - return x; -} -#else - #define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - -#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ - (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) -#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ - (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) -#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ - (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) - -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -static void -do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) -{ - u32 l, r, t; - u32 I; /* used by the Fx macros */ - u32 *Km; - byte *Kr; - - Km = c->Km; - Kr = c->Kr; - - /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and - * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) - */ - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - - /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: - * Li = Ri-1; - * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 - * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. - * Rounds 2, 5, 8, 11, and 14 use f function Type 2. - * Rounds 3, 6, 9, 12, and 15 use f function Type 3. - */ - - t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); - t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); - t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); - t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); - t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); - t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); - t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); - t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); - t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); - t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); - t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); - t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); - t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); - t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); - t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); - t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); - - /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and - * concatenate to form the ciphertext.) */ - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; -} - -static void -encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) -{ - do_encrypt_block (c, outbuf, inbuf); - burn_stack (20+4*sizeof(void*)); -} - -static void -do_decrypt_block (CAST5_context *c, byte *outbuf, byte *inbuf ) -{ - u32 l, r, t; - u32 I; - u32 *Km; - byte *Kr; - - Km = c->Km; - Kr = c->Kr; - - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - - t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); - t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); - t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); - t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); - t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); - t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); - t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); - t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); - t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); - t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); - t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); - t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); - t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); - t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); - t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); - t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); - - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; -} - -static void -decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) -{ - do_decrypt_block (c, outbuf, inbuf); - burn_stack (20+4*sizeof(void*)); -} - - -static const char* -selftest(void) -{ - CAST5_context c; - byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, - 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; - byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; - byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; - byte buffer[8]; - - cast_setkey( &c, key, 16 ); - encrypt_block( &c, buffer, plain ); - if( memcmp( buffer, cipher, 8 ) ) - return "1"; - decrypt_block( &c, buffer, buffer ); - if( memcmp( buffer, plain, 8 ) ) - return "2"; - - #if 0 /* full maintenance test */ - { - int i; - byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, - 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; - byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, - 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; - byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6, - 0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 }; - byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71, - 0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E }; - - for(i=0; i < 1000000; i++ ) { - cast_setkey( &c, b0, 16 ); - encrypt_block( &c, a0, a0 ); - encrypt_block( &c, a0+8, a0+8 ); - cast_setkey( &c, a0, 16 ); - encrypt_block( &c, b0, b0 ); - encrypt_block( &c, b0+8, b0+8 ); - } - if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) ) - return "3"; - - } - #endif - return NULL; -} - - -static void -key_schedule( u32 *x, u32 *z, u32 *k ) -{ - - #define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff) - #define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff) - - z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; - z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; - z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; - z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; - k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)]; - k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)]; - k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)]; - k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)]; - - x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; - x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; - x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; - x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; - k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)]; - k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)]; - k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)]; - k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)]; - - z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; - z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; - z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; - z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; - k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)]; - k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)]; - k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)]; - k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)]; - - x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; - x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; - x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; - x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; - k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)]; - k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)]; - k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)]; - k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)]; - - #undef xi - #undef zi -} - - -static int -do_cast_setkey( CAST5_context *c, byte *key, unsigned keylen ) -{ - static int initialized; - static const char* selftest_failed; - int i; - u32 x[4]; - u32 z[4]; - u32 k[16]; - - if( !initialized ) { - initialized = 1; - selftest_failed = selftest(); - if( selftest_failed ) - fprintf(stderr,"CAST5 selftest failed (%s).\n", selftest_failed ); - } - if( selftest_failed ) - return G10ERR_SELFTEST_FAILED; - - if( keylen != 16 ) - return G10ERR_WRONG_KEYLEN; - - x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; - x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; - x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; - x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; - - key_schedule( x, z, k ); - for(i=0; i < 16; i++ ) - c->Km[i] = k[i]; - key_schedule( x, z, k ); - for(i=0; i < 16; i++ ) - c->Kr[i] = k[i] & 0x1f; - - memset(&x,0, sizeof x); - memset(&z,0, sizeof z); - memset(&k,0, sizeof k); - - #undef xi - #undef zi - return 0; -} - -static int -cast_setkey( CAST5_context *c, byte *key, unsigned keylen ) -{ - int rc = do_cast_setkey (c, key, keylen); - burn_stack (96+7*sizeof(void*)); - return rc; -} - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -const char * -cast5_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**r_setkey)( void *c, byte *key, unsigned keylen ), - void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), - void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) - ) -{ - *keylen = 128; - *blocksize = CAST5_BLOCKSIZE; - *contextsize = sizeof(CAST5_context); - *(int (**)(CAST5_context*, byte*, unsigned))r_setkey - = cast_setkey; - *(void (**)(CAST5_context*, byte*, byte*))r_encrypt - = encrypt_block; - *(void (**)(CAST5_context*, byte*, byte*))r_decrypt - = decrypt_block; - - - if( algo == CIPHER_ALGO_CAST5 ) - return "CAST5"; - return NULL; -} - diff --git a/cipher/cipher.c b/cipher/cipher.c deleted file mode 100644 index 9a774cf85..000000000 --- a/cipher/cipher.c +++ /dev/null @@ -1,678 +0,0 @@ -/* cipher.c - cipher dispatcher - * 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 -#include -#include -#include -#include -#include -#include "util.h" -#include "errors.h" -#include "cipher.h" -#include "algorithms.h" - -/* We have support for a DUMMY encryption cipher which comes handy to - debug MDCs and similar things. Because this is a bit dangerous it - is not enabled. */ -/*#define ALLOW_DUMMY 1 */ - -#define MAX_BLOCKSIZE 16 -#define TABLE_SIZE 14 - -struct cipher_table_s { - const char *name; - int algo; - size_t blocksize; - size_t keylen; - size_t contextsize; /* allocate this amount of context */ - int (*setkey)( void *c, byte *key, unsigned keylen ); - void (*encrypt)( void *c, byte *outbuf, byte *inbuf ); - void (*decrypt)( void *c, byte *outbuf, byte *inbuf ); -}; - -static struct cipher_table_s cipher_table[TABLE_SIZE]; -static int disabled_algos[TABLE_SIZE]; - - -struct cipher_handle_s { - int algo; - int mode; - size_t blocksize; - byte iv[MAX_BLOCKSIZE]; /* (this should be ulong aligned) */ - byte lastiv[MAX_BLOCKSIZE]; - int unused; /* in IV */ - int (*setkey)( void *c, byte *key, unsigned keylen ); - void (*encrypt)( void *c, byte *outbuf, byte *inbuf ); - void (*decrypt)( void *c, byte *outbuf, byte *inbuf ); - PROPERLY_ALIGNED_TYPE context; -}; - - -#ifdef ALLOW_DUMMY -static int -dummy_setkey( void *c, byte *key, unsigned keylen ) { return 0; } -static void -dummy_encrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); } -static void -dummy_decrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); } -#ifdef __GNUC__ -# warning DUMMY cipher module is enabled -#endif -#endif - - -/**************** - * Put the static entries into the table. - */ -static void -setup_cipher_table(void) -{ - - int i; - - i = 0; - cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL; - cipher_table[i].name = rijndael_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL192; - cipher_table[i].name = rijndael_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL256; - cipher_table[i].name = rijndael_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_TWOFISH; - cipher_table[i].name = twofish_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_BLOWFISH; - cipher_table[i].name = blowfish_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_CAST5; - cipher_table[i].name = cast5_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_3DES; - cipher_table[i].name = des_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if( !cipher_table[i].name ) - BUG(); - i++; - cipher_table[i].algo = CIPHER_ALGO_IDEA; - cipher_table[i].name = idea_get_info( cipher_table[i].algo, - &cipher_table[i].keylen, - &cipher_table[i].blocksize, - &cipher_table[i].contextsize, - &cipher_table[i].setkey, - &cipher_table[i].encrypt, - &cipher_table[i].decrypt ); - if (cipher_table[i].name) - i++; /* Note that IDEA is usually not available. */ - -#ifdef ALLOW_DUMMY - cipher_table[i].algo = CIPHER_ALGO_DUMMY; - cipher_table[i].name = "DUMMY"; - cipher_table[i].blocksize = 8; - cipher_table[i].keylen = 128; - cipher_table[i].contextsize = 0; - cipher_table[i].setkey = dummy_setkey; - cipher_table[i].encrypt = dummy_encrypt_block; - cipher_table[i].decrypt = dummy_decrypt_block; - i++; -#endif - - for( ; i < TABLE_SIZE; i++ ) - cipher_table[i].name = NULL; -} - - -/**************** - * Try to load all modules and return true if new modules are available - */ -static int -load_cipher_modules(void) -{ - static int initialized = 0; - - if (!initialized ) - { - setup_cipher_table(); /* load static modules on the first call */ - initialized = 1; - return 1; - } - return 0; -} - - - - - - - -/**************** - * Map a string to the cipher algo - */ -int -string_to_cipher_algo( const char *string ) -{ - int i; - const char *s; - - /* kludge to alias RIJNDAEL to AES */ - if ( *string == 'R' || *string == 'r') - { - if (!ascii_strcasecmp (string, "RIJNDAEL")) - string = "AES"; - else if (!ascii_strcasecmp (string, "RIJNDAEL192")) - string = "AES192"; - else if (!ascii_strcasecmp (string, "RIJNDAEL256")) - string = "AES256"; - } - - do - { - for(i=0; (s=cipher_table[i].name); i++ ) - { - if( !ascii_strcasecmp( s, string ) ) - return cipher_table[i].algo; - } - } while( load_cipher_modules() ); - return 0; -} - -/**************** - * Map a cipher algo to a string - */ -const char * -cipher_algo_to_string( int algo ) -{ - int i; - - do { - for(i=0; cipher_table[i].name; i++ ) - if( cipher_table[i].algo == algo ) - return cipher_table[i].name; - } while( load_cipher_modules() ); - return NULL; -} - - -void -disable_cipher_algo( int algo ) -{ - int i; - - for(i=0; i < DIM(disabled_algos); i++ ) { - if( !disabled_algos[i] || disabled_algos[i] == algo ) { - disabled_algos[i] = algo; - return; - } - } - /* fixme: we should use a linked list */ - log_fatal("can't disable cipher algo %d: table full\n", algo ); -} - -/**************** - * Return 0 if the cipher algo is available - */ -int -check_cipher_algo( int algo ) -{ - int i; - - do { - for(i=0; cipher_table[i].name; i++ ) - if( cipher_table[i].algo == algo ) { - for(i=0; i < DIM(disabled_algos); i++ ) { - if( disabled_algos[i] == algo ) - return G10ERR_CIPHER_ALGO; - } - return 0; /* okay */ - } - } while( load_cipher_modules() ); - return G10ERR_CIPHER_ALGO; -} - - -unsigned -cipher_get_keylen( int algo ) -{ - int i; - unsigned len = 0; - - do { - for(i=0; cipher_table[i].name; i++ ) { - if( cipher_table[i].algo == algo ) { - len = cipher_table[i].keylen; - if( !len ) - log_bug("cipher %d w/o key length\n", algo ); - return len; - } - } - } while( load_cipher_modules() ); - log_bug("cipher %d not found\n", algo ); - return 0; -} - -unsigned -cipher_get_blocksize( int algo ) -{ - int i; - unsigned len = 0; - - do { - for(i=0; cipher_table[i].name; i++ ) { - if( cipher_table[i].algo == algo ) { - len = cipher_table[i].blocksize; - if( !len ) - log_bug("cipher %d w/o blocksize\n", algo ); - return len; - } - } - } while( load_cipher_modules() ); - log_bug("cipher %d not found\n", algo ); - return 0; -} - - -/**************** - * Open a cipher handle for use with algorithm ALGO, in mode MODE - * and put it into secure memory if SECURE is true. - */ -CIPHER_HANDLE -cipher_open( int algo, int mode, int secure ) -{ - CIPHER_HANDLE hd; - int i; - - fast_random_poll(); - do { - for(i=0; cipher_table[i].name; i++ ) - if( cipher_table[i].algo == algo ) - break; - } while( !cipher_table[i].name && load_cipher_modules() ); - if( !cipher_table[i].name ) { - log_fatal("cipher_open: algorithm %d not available\n", algo ); - return NULL; - } - - /* ? perform selftest here and mark this with a flag in cipher_table ? */ - - hd = secure ? m_alloc_secure_clear( sizeof *hd - + cipher_table[i].contextsize - - sizeof(PROPERLY_ALIGNED_TYPE) ) - : m_alloc_clear( sizeof *hd + cipher_table[i].contextsize - - sizeof(PROPERLY_ALIGNED_TYPE) ); - hd->algo = algo; - hd->blocksize = cipher_table[i].blocksize; - hd->setkey = cipher_table[i].setkey; - hd->encrypt = cipher_table[i].encrypt; - hd->decrypt = cipher_table[i].decrypt; - - if( mode == CIPHER_MODE_AUTO_CFB ) { - if( algo >= 100 ) - hd->mode = CIPHER_MODE_CFB; - else - hd->mode = CIPHER_MODE_PHILS_CFB; - } - else - hd->mode = mode; - -#ifdef ALLOW_DUMMY - if( algo == CIPHER_ALGO_DUMMY ) - hd->mode = CIPHER_MODE_DUMMY; -#endif - - return hd; -} - - -void -cipher_close( CIPHER_HANDLE c ) -{ - m_free(c); -} - - -int -cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ) -{ - return (*c->setkey)( &c->context.c, key, keylen ); -} - - - -void -cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ) -{ - memset( c->iv, 0, c->blocksize ); - if( iv ) { - if( ivlen != c->blocksize ) - log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n", - ivlen, (unsigned)c->blocksize ); - if( ivlen > c->blocksize ) - ivlen = c->blocksize; - memcpy( c->iv, iv, ivlen ); - } - c->unused = 0; -} - - - -static void -do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - (*c->encrypt)( &c->context.c, outbuf, inbuf ); - inbuf += c->blocksize; - outbuf += c->blocksize; - } -} - -static void -do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - (*c->decrypt)( &c->context.c, outbuf, inbuf ); - inbuf += c->blocksize; - outbuf += c->blocksize; - } -} - -static void -do_cbc_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ - unsigned int n; - byte *ivp; - int i; - size_t blocksize = c->blocksize; - - for(n=0; n < nblocks; n++ ) { - /* fixme: the xor should works on words and not on - * bytes. Maybe it is a good idea to enhance the cipher backend - * API to allow for CBC handling in the backend */ - for(ivp=c->iv,i=0; i < blocksize; i++ ) - outbuf[i] = inbuf[i] ^ *ivp++; - (*c->encrypt)( &c->context.c, outbuf, outbuf ); - memcpy(c->iv, outbuf, blocksize ); - inbuf += c->blocksize; - outbuf += c->blocksize; - } -} - -static void -do_cbc_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ - unsigned int n; - byte *ivp; - int i; - size_t blocksize = c->blocksize; - - for(n=0; n < nblocks; n++ ) { - /* because outbuf and inbuf might be the same, we have - * to save the original ciphertext block. We use lastiv - * for this here because it is not used otherwise */ - memcpy(c->lastiv, inbuf, blocksize ); - (*c->decrypt)( &c->context.c, outbuf, inbuf ); - for(ivp=c->iv,i=0; i < blocksize; i++ ) - outbuf[i] ^= *ivp++; - memcpy(c->iv, c->lastiv, blocksize ); - inbuf += c->blocksize; - outbuf += c->blocksize; - } -} - - -static void -do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) -{ - byte *ivp; - size_t blocksize = c->blocksize; - - if( nbytes <= c->unused ) { - /* short enough to be encoded by the remaining XOR mask */ - /* XOR the input with the IV and store input into IV */ - for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- ) - *outbuf++ = (*ivp++ ^= *inbuf++); - return; - } - - if( c->unused ) { - /* XOR the input with the IV and store input into IV */ - nbytes -= c->unused; - for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) - *outbuf++ = (*ivp++ ^= *inbuf++); - } - - /* now we can process complete blocks */ - while( nbytes >= blocksize ) { - int i; - /* encrypt the IV (and save the current one) */ - memcpy( c->lastiv, c->iv, blocksize ); - (*c->encrypt)( &c->context.c, c->iv, c->iv ); - /* XOR the input with the IV and store input into IV */ - for(ivp=c->iv,i=0; i < blocksize; i++ ) - *outbuf++ = (*ivp++ ^= *inbuf++); - nbytes -= blocksize; - } - if( nbytes ) { /* process the remaining bytes */ - /* encrypt the IV (and save the current one) */ - memcpy( c->lastiv, c->iv, blocksize ); - (*c->encrypt)( &c->context.c, c->iv, c->iv ); - c->unused = blocksize; - /* and apply the xor */ - c->unused -= nbytes; - for(ivp=c->iv; nbytes; nbytes-- ) - *outbuf++ = (*ivp++ ^= *inbuf++); - } -} - -static void -do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) -{ - byte *ivp; - ulong temp; - size_t blocksize = c->blocksize; - - if( nbytes <= c->unused ) { - /* short enough to be encoded by the remaining XOR mask */ - /* XOR the input with the IV and store input into IV */ - for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){ - temp = *inbuf++; - *outbuf++ = *ivp ^ temp; - *ivp++ = temp; - } - return; - } - - if( c->unused ) { - /* XOR the input with the IV and store input into IV */ - nbytes -= c->unused; - for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) { - temp = *inbuf++; - *outbuf++ = *ivp ^ temp; - *ivp++ = temp; - } - } - - /* now we can process complete blocks */ - while( nbytes >= blocksize ) { - int i; - /* encrypt the IV (and save the current one) */ - memcpy( c->lastiv, c->iv, blocksize ); - (*c->encrypt)( &c->context.c, c->iv, c->iv ); - /* XOR the input with the IV and store input into IV */ - for(ivp=c->iv,i=0; i < blocksize; i++ ) { - temp = *inbuf++; - *outbuf++ = *ivp ^ temp; - *ivp++ = temp; - } - nbytes -= blocksize; - } - if( nbytes ) { /* process the remaining bytes */ - /* encrypt the IV (and save the current one) */ - memcpy( c->lastiv, c->iv, blocksize ); - (*c->encrypt)( &c->context.c, c->iv, c->iv ); - c->unused = blocksize; - /* and apply the xor */ - c->unused -= nbytes; - for(ivp=c->iv; nbytes; nbytes-- ) { - temp = *inbuf++; - *outbuf++ = *ivp ^ temp; - *ivp++ = temp; - } - } -} - - -/**************** - * Encrypt INBUF to OUTBUF with the mode selected at open. - * inbuf and outbuf may overlap or be the same. - * Depending on the mode some some contraints apply to NBYTES. - */ -void -cipher_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) -{ - switch( c->mode ) { - case CIPHER_MODE_ECB: - assert(!(nbytes%c->blocksize)); - do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); - break; - case CIPHER_MODE_CBC: - assert(!(nbytes%c->blocksize)); - do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize ); - break; - case CIPHER_MODE_CFB: - case CIPHER_MODE_PHILS_CFB: - do_cfb_encrypt(c, outbuf, inbuf, nbytes ); - break; -#ifdef ALLOW_DUMMY - case CIPHER_MODE_DUMMY: - if( inbuf != outbuf ) - memmove( outbuf, inbuf, nbytes ); - break; -#endif - default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode ); - } -} - - -/**************** - * Decrypt INBUF to OUTBUF with the mode selected at open. - * inbuf and outbuf may overlap or be the same. - * Depending on the mode some some contraints apply to NBYTES. - */ -void -cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) -{ - switch( c->mode ) { - case CIPHER_MODE_ECB: - assert(!(nbytes%c->blocksize)); - do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); - break; - case CIPHER_MODE_CBC: - assert(!(nbytes%c->blocksize)); - do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize ); - break; - case CIPHER_MODE_CFB: - case CIPHER_MODE_PHILS_CFB: - do_cfb_decrypt(c, outbuf, inbuf, nbytes ); - break; -#ifdef ALLOW_DUMMY - case CIPHER_MODE_DUMMY: - if( inbuf != outbuf ) - memmove( outbuf, inbuf, nbytes ); - break; -#endif - default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode ); - } -} - - - -/**************** - * Used for PGP's somewhat strange CFB mode. Only works if - * the handle is in PHILS_CFB mode - */ -void -cipher_sync( CIPHER_HANDLE c ) -{ - if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) { - memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused ); - memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused); - c->unused = 0; - } -} - diff --git a/cipher/des.c b/cipher/des.c deleted file mode 100644 index 36383d2c0..000000000 --- a/cipher/des.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* des.c - DES and Triple-DES encryption/decryption Algorithm - * 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 - * - * - * According to the definition of DES in FIPS PUB 46-2 from December 1993. - * For a description of triple encryption, see: - * Bruce Schneier: Applied Cryptography. Second Edition. - * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. - */ - - -/* - * Written by Michael Roth , September 1998 - */ - - -/* - * U S A G E - * =========== - * - * For DES or Triple-DES encryption/decryption you must initialize a proper - * encryption context with a key. - * - * A DES key is 64bit wide but only 56bits of the key are used. The remaining - * bits are parity bits and they will _not_ checked in this implementation, but - * simply ignored. - * - * For Tripple-DES you could use either two 64bit keys or three 64bit keys. - * The parity bits will _not_ checked, too. - * - * After initializing a context with a key you could use this context to - * encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode. - * - * (In the examples below the slashes at the beginning and ending of comments - * are omited.) - * - * DES Example - * ----------- - * unsigned char key[8]; - * unsigned char plaintext[8]; - * unsigned char ciphertext[8]; - * unsigned char recoverd[8]; - * des_ctx context; - * - * * Fill 'key' and 'plaintext' with some data * - * .... - * - * * Set up the DES encryption context * - * des_setkey(context, key); - * - * * Encrypt the plaintext * - * des_ecb_encrypt(context, plaintext, ciphertext); - * - * * To recover the orginal plaintext from ciphertext use: * - * des_ecb_decrypt(context, ciphertext, recoverd); - * - * - * Triple-DES Example - * ------------------ - * unsigned char key1[8]; - * unsigned char key2[8]; - * unsigned char key3[8]; - * unsigned char plaintext[8]; - * unsigned char ciphertext[8]; - * unsigned char recoverd[8]; - * tripledes_ctx context; - * - * * If you would like to use two 64bit keys, fill 'key1' and'key2' - * then setup the encryption context: * - * tripledes_set2keys(context, key1, key2); - * - * * To use three 64bit keys with Triple-DES use: * - * tripledes_set3keys(context, key1, key2, key3); - * - * * Encrypting plaintext with Triple-DES * - * tripledes_ecb_encrypt(context, plaintext, ciphertext); - * - * * Decrypting ciphertext to recover the plaintext with Triple-DES * - * tripledes_ecb_decrypt(context, ciphertext, recoverd); - * - * - * Selftest - * -------- - * char *error_msg; - * - * * To perform a selftest of this DES/Triple-DES implementation use the - * function selftest(). It will return an error string if their are - * some problems with this library. * - * - * if ( (error_msg = selftest()) ) - * { - * fprintf(stderr, "An error in the DES/Tripple-DES implementation occured: %s\n", error_msg); - * abort(); - * } - */ - - -#include -#include -#include /* memcpy, memcmp */ -#include "types.h" /* for byte and u32 typedefs */ -#include "errors.h" -#include "algorithms.h" - -#if defined(__GNUC__) && defined(__GNU_LIBRARY__) -#define working_memcmp memcmp -#else -/* - * According to the SunOS man page, memcmp returns indeterminate sign - * depending on whether characters are signed or not. - */ -int -working_memcmp( const char *a, const char *b, size_t n ) -{ - for( ; n; n--, a++, b++ ) - if( *a != *b ) - return (int)(*(byte*)a) - (int)(*(byte*)b); - return 0; -} -#endif - - - -/* Some defines/checks to support standalone modules */ - -#ifndef CIPHER_ALGO_3DES - #define CIPHER_ALGO_3DES 2 -#elif CIPHER_ALGO_3DES != 2 - #error CIPHER_ALGO_3DES is defined to a wrong value. -#endif - - - - -/* - * Encryption/Decryption context of DES - */ -typedef struct _des_ctx - { - u32 encrypt_subkeys[32]; - u32 decrypt_subkeys[32]; - } -des_ctx[1]; - -/* - * Encryption/Decryption context of Triple-DES - */ -typedef struct _tripledes_ctx - { - u32 encrypt_subkeys[96]; - u32 decrypt_subkeys[96]; - } -tripledes_ctx[1]; - -static const char *selftest_failed; - -static void des_key_schedule (const byte *, u32 *); -static int des_setkey (struct _des_ctx *, const byte *); -static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int); -static int tripledes_set2keys (struct _tripledes_ctx *, const byte *, const byte *); -static int tripledes_set3keys (struct _tripledes_ctx *, const byte *, const byte *, const byte *); -static int tripledes_ecb_crypt (struct _tripledes_ctx *, const byte *, byte *, int); -static int is_weak_key ( const byte *key ); -static const char *selftest (void); - - - - - - -/* - * The s-box values are permuted according to the 'primitive function P' - * and are rotated one bit to the left. - */ -static u32 sbox1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static u32 sbox2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static u32 sbox3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static u32 sbox4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static u32 sbox5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static u32 sbox6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static u32 sbox7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static u32 sbox8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - - -/* - * These two tables are part of the 'permuted choice 1' function. - * In this implementation several speed improvements are done. - */ -u32 leftkey_swap[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -u32 rightkey_swap[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - - - -/* - * Numbers of left shifts per round for encryption subkeys. - * To calculate the decryption subkeys we just reverse the - * ordering of the calculated encryption subkeys. So their - * is no need for a decryption rotate tab. - */ -static byte encrypt_rotate_tab[16] = -{ - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 -}; - - - -/* - * Table with weak DES keys sorted in ascending order. - * In DES their are 64 known keys wich are weak. They are weak - * because they produce only one, two or four different - * subkeys in the subkey scheduling process. - * The keys in this table have all their parity bits cleared. - */ -static byte weak_keys[64][8] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e }, - { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe }, - { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 }, - { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 }, - { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe }, - { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e }, - { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 }, - { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 }, - { 0x0e, 0x0e, 0x0e, 0x0e, 0xf0, 0xf0, 0xf0, 0xf0 }, { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e }, - { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe }, - { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 }, - { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 }, - { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe }, - { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e }, - { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 }, - { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 }, - { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 }, - { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, - { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe }, - { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, - { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 }, - { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe }, - { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 }, - { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 }, - { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 }, - { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, - { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe }, - { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, - { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 }, - { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, - { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e }, - { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe } -}; - - - - - - -/* - * Macro to swap bits across two words. - */ -#define DO_PERMUTATION(a, temp, b, offset, mask) \ - temp = ((a>>offset) ^ b) & mask; \ - b ^= temp; \ - a ^= temp<> 31); \ - temp = (left ^ right) & 0xaaaaaaaa; \ - right ^= temp; \ - left ^= temp; \ - left = (left << 1) | (left >> 31); - -/* - * The 'inverse initial permutation'. - */ -#define FINAL_PERMUTATION(left, temp, right) \ - left = (left << 31) | (left >> 1); \ - temp = (left ^ right) & 0xaaaaaaaa; \ - left ^= temp; \ - right ^= temp; \ - right = (right << 31) | (right >> 1); \ - DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ - DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ - DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ - DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) - - -/* - * A full DES round including 'expansion function', 'sbox substitution' - * and 'primitive function P' but without swapping the left and right word. - * Please note: The data in 'from' and 'to' is already rotated one bit to - * the left, done in the initial permutation. - */ -#define DES_ROUND(from, to, work, subkey) \ - work = from ^ *subkey++; \ - to ^= sbox8[ work & 0x3f ]; \ - to ^= sbox6[ (work>>8) & 0x3f ]; \ - to ^= sbox4[ (work>>16) & 0x3f ]; \ - to ^= sbox2[ (work>>24) & 0x3f ]; \ - work = ((from << 28) | (from >> 4)) ^ *subkey++; \ - to ^= sbox7[ work & 0x3f ]; \ - to ^= sbox5[ (work>>8) & 0x3f ]; \ - to ^= sbox3[ (work>>16) & 0x3f ]; \ - to ^= sbox1[ (work>>24) & 0x3f ]; - -/* - * Macros to convert 8 bytes from/to 32bit words. - */ -#define READ_64BIT_DATA(data, left, right) \ - left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ - right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; - -#define WRITE_64BIT_DATA(data, left, right) \ - data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ - data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ - data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ - data[6] = (right >> 8) &0xff; data[7] = right &0xff; - -/* - * Handy macros for encryption and decryption of data - */ -#define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0) -#define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1) -#define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 0) -#define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 1) - - -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - -/* - * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for - * 16 encryption rounds. - * To calculate subkeys for decryption the caller - * have to reorder the generated subkeys. - * - * rawkey: 8 Bytes of key data - * subkey: Array of at least 32 u32s. Will be filled - * with calculated subkeys. - * - */ -static void -des_key_schedule (const byte * rawkey, u32 * subkey) -{ - u32 left, right, work; - int round; - - READ_64BIT_DATA (rawkey, left, right) - - DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) - DO_PERMUTATION (right, work, left, 0, 0x10101010) - - left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) - | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) - | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) - | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); - - left &= 0x0fffffff; - - right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) - | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) - | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) - | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); - - right &= 0x0fffffff; - - for (round = 0; round < 16; ++round) - { - left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; - - *subkey++ = ((left << 4) & 0x24000000) - | ((left << 28) & 0x10000000) - | ((left << 14) & 0x08000000) - | ((left << 18) & 0x02080000) - | ((left << 6) & 0x01000000) - | ((left << 9) & 0x00200000) - | ((left >> 1) & 0x00100000) - | ((left << 10) & 0x00040000) - | ((left << 2) & 0x00020000) - | ((left >> 10) & 0x00010000) - | ((right >> 13) & 0x00002000) - | ((right >> 4) & 0x00001000) - | ((right << 6) & 0x00000800) - | ((right >> 1) & 0x00000400) - | ((right >> 14) & 0x00000200) - | (right & 0x00000100) - | ((right >> 5) & 0x00000020) - | ((right >> 10) & 0x00000010) - | ((right >> 3) & 0x00000008) - | ((right >> 18) & 0x00000004) - | ((right >> 26) & 0x00000002) - | ((right >> 24) & 0x00000001); - - *subkey++ = ((left << 15) & 0x20000000) - | ((left << 17) & 0x10000000) - | ((left << 10) & 0x08000000) - | ((left << 22) & 0x04000000) - | ((left >> 2) & 0x02000000) - | ((left << 1) & 0x01000000) - | ((left << 16) & 0x00200000) - | ((left << 11) & 0x00100000) - | ((left << 3) & 0x00080000) - | ((left >> 6) & 0x00040000) - | ((left << 15) & 0x00020000) - | ((left >> 4) & 0x00010000) - | ((right >> 2) & 0x00002000) - | ((right << 8) & 0x00001000) - | ((right >> 14) & 0x00000808) - | ((right >> 9) & 0x00000400) - | ((right) & 0x00000200) - | ((right << 7) & 0x00000100) - | ((right >> 7) & 0x00000020) - | ((right >> 3) & 0x00000011) - | ((right << 2) & 0x00000004) - | ((right >> 21) & 0x00000002); - } -} - - - -/* - * Fill a DES context with subkeys calculated from a 64bit key. - * Does not check parity bits, but simply ignore them. - * Does not check for weak keys. - */ -static int -des_setkey (struct _des_ctx *ctx, const byte * key) -{ - int i; - - if( selftest_failed ) - return G10ERR_SELFTEST_FAILED; - - des_key_schedule (key, ctx->encrypt_subkeys); - burn_stack (32); - - for(i=0; i<32; i+=2) - { - ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; - ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; - } - - return 0; -} - - - -/* - * Electronic Codebook Mode DES encryption/decryption of data according - * to 'mode'. - */ -static int -des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode) -{ - u32 left, right, work; - u32 *keys; - - keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; - - READ_64BIT_DATA (from, left, right) - INITIAL_PERMUTATION (left, work, right) - - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - - FINAL_PERMUTATION (right, work, left) - WRITE_64BIT_DATA (to, right, left) - - return 0; -} - - - -/* - * Fill a Triple-DES context with subkeys calculated from two 64bit keys. - * Does not check the parity bits of the keys, but simply ignore them. - * Does not check for weak keys. - */ -static int -tripledes_set2keys (struct _tripledes_ctx *ctx, - const byte * key1, - const byte * key2) -{ - int i; - - des_key_schedule (key1, ctx->encrypt_subkeys); - des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); - burn_stack (32); - - for(i=0; i<32; i+=2) - { - ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; - ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; - - ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; - ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; - - ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i]; - ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1]; - - ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i]; - ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1]; - } - - return 0; -} - - - -/* - * Fill a Triple-DES context with subkeys calculated from three 64bit keys. - * Does not check the parity bits of the keys, but simply ignore them. - * Does not check for weak keys. - */ -static int -tripledes_set3keys (struct _tripledes_ctx *ctx, - const byte * key1, - const byte * key2, - const byte * key3) -{ - int i; - - des_key_schedule (key1, ctx->encrypt_subkeys); - des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); - des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); - burn_stack (32); - - for(i=0; i<32; i+=2) - { - ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i]; - ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i]; - - ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; - ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; - - ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i]; - ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i]; - } - - return 0; -} - - - -/* - * Electronic Codebook Mode Triple-DES encryption/decryption of data according to 'mode'. - * Sometimes this mode is named 'EDE' mode (Encryption-Decryption-Encryption). - */ -static int -tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, byte * to, int mode) -{ - u32 left, right, work; - u32 *keys; - - keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; - - READ_64BIT_DATA (from, left, right) - INITIAL_PERMUTATION (left, work, right) - - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) - - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) - - FINAL_PERMUTATION (right, work, left) - WRITE_64BIT_DATA (to, right, left) - - return 0; -} - - - - - -/* - * Check whether the 8 byte key is weak. - * Dose not check the parity bits of the key but simple ignore them. - */ -static int -is_weak_key ( const byte *key ) -{ - byte work[8]; - int i, left, right, middle, cmp_result; - - /* clear parity bits */ - for(i=0; i<8; ++i) - work[i] = key[i] & 0xfe; - - /* binary search in the weak key table */ - left = 0; - right = 63; - while(left <= right) - { - middle = (left + right) / 2; - - if ( !(cmp_result=working_memcmp(work, weak_keys[middle], 8)) ) - return -1; - - if ( cmp_result > 0 ) - left = middle + 1; - else - right = middle - 1; - } - - return 0; -} - - - -/* - * Performs a selftest of this DES/Triple-DES implementation. - * Returns an string with the error text on failure. - * Returns NULL if all is ok. - */ -static const char * -selftest (void) -{ - /* - * Check if 'u32' is really 32 bits wide. This DES / 3DES implementation - * need this. - */ - if (sizeof (u32) != 4) - return "Wrong word size for DES configured."; - - /* - * DES Maintenance Test - */ - { - int i; - byte key[8] = - {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; - byte input[8] = - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - byte result[8] = - {0x24, 0x6e, 0x9d, 0xb9, 0xc5, 0x50, 0x38, 0x1a}; - byte temp1[8], temp2[8], temp3[8]; - des_ctx des; - - for (i = 0; i < 64; ++i) - { - des_setkey (des, key); - des_ecb_encrypt (des, input, temp1); - des_ecb_encrypt (des, temp1, temp2); - des_setkey (des, temp2); - des_ecb_decrypt (des, temp1, temp3); - memcpy (key, temp3, 8); - memcpy (input, temp1, 8); - } - if (memcmp (temp3, result, 8)) - return "DES maintenance test failed."; - } - - - /* - * Self made Triple-DES test (Does somebody known an official test?) - */ - { - int i; - byte input[8] = - {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; - byte key1[8] = - {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; - byte key2[8] = - {0x11, 0x22, 0x33, 0x44, 0xff, 0xaa, 0xcc, 0xdd}; - byte result[8] = - {0x7b, 0x38, 0x3b, 0x23, 0xa2, 0x7d, 0x26, 0xd3}; - - tripledes_ctx des3; - - for (i = 0; i < 16; ++i) - { - tripledes_set2keys (des3, key1, key2); - tripledes_ecb_encrypt (des3, input, key1); - tripledes_ecb_decrypt (des3, input, key2); - tripledes_set3keys (des3, key1, input, key2); - tripledes_ecb_encrypt (des3, input, input); - } - if (memcmp (input, result, 8)) - return "Triple-DES test failed."; - } - - /* - * More Triple-DES test. These are testvectors as used by SSLeay, - * thanks to Jeroen C. van Gelderen. - */ - { struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { - { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, - { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, - { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } - }, - - { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, - { 0x9D,0x64,0x55,0x5A,0x9A,0x10,0xB8,0x52, }, - { 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00 } - }, - { { 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, - 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, - 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E }, - { 0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A }, - { 0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A } - }, - { { 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, - 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, - 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6 }, - { 0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2 }, - { 0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95 } - }, - { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, - 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, - 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, - { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, - { 0x3D,0x12,0x4F,0xE2,0x19,0x8B,0xA3,0x18 } - }, - { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, - 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, - 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, - { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, - { 0xFB,0xAB,0xA1,0xFF,0x9D,0x05,0xE9,0xB1 } - }, - { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, - 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, - 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }, - { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, - { 0x18,0xd7,0x48,0xe5,0x63,0x62,0x05,0x72 } - }, - { { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, - 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, - 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, - { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, - { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 } - }, - { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0xe6,0xe6,0xdd,0x5b,0x7e,0x72,0x29,0x74 } - }, - { { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, - 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, - 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } - } - }; - - byte result[8]; - int i; - static char error[80]; - tripledes_ctx des3; - - for (i=0; i -#include -#include -#include -#include -#include "util.h" -#include "mpi.h" -#include "cipher.h" -#include "dsa.h" - -typedef struct { - MPI p; /* prime */ - MPI q; /* group order */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ -} DSA_public_key; - - -typedef struct { - MPI p; /* prime */ - MPI q; /* group order */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ - MPI x; /* secret exponent */ -} DSA_secret_key; - - -static MPI gen_k( MPI q ); -static void test_keys( DSA_secret_key *sk, unsigned qbits ); -static int check_secret_key( DSA_secret_key *sk ); -static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ); -static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey); -static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey); - - -static void (*progress_cb) ( void *, int ); -static void *progress_cb_data; - -void -register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data ) -{ - progress_cb = cb; - progress_cb_data = cb_data; -} - - -static void -progress( int c ) -{ - if ( progress_cb ) - progress_cb ( progress_cb_data, c ); - else - fputc( c, stderr ); -} - - - -/**************** - * Generate a random secret exponent k less than q - */ -static MPI -gen_k( MPI q ) -{ - MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) ); - unsigned int nbits = mpi_get_nbits(q); - unsigned int nbytes = (nbits+7)/8; - char *rndbuf = NULL; - - if( DBG_CIPHER ) - log_debug("choosing a random k "); - for(;;) { - if( DBG_CIPHER ) - progress('.'); - - if( !rndbuf || nbits < 32 ) { - m_free(rndbuf); - rndbuf = get_random_bits( nbits, 1, 1 ); - } - else { /* change only some of the higher bits */ - /* we could imporove this by directly requesting more memory - * at the first call to get_random_bits() and use this the here - * maybe it is easier to do this directly in random.c */ - char *pp = get_random_bits( 32, 1, 1 ); - memcpy( rndbuf,pp, 4 ); - m_free(pp); - } - mpi_set_buffer( k, rndbuf, nbytes, 0 ); - if( mpi_test_bit( k, nbits-1 ) ) - mpi_set_highbit( k, nbits-1 ); - else { - mpi_set_highbit( k, nbits-1 ); - mpi_clear_bit( k, nbits-1 ); - } - - if( !(mpi_cmp( k, q ) < 0) ) { /* check: k < q */ - if( DBG_CIPHER ) - progress('+'); - continue; /* no */ - } - if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ - if( DBG_CIPHER ) - progress('-'); - continue; /* no */ - } - break; /* okay */ - } - m_free(rndbuf); - if( DBG_CIPHER ) - progress('\n'); - - return k; -} - - -static void -test_keys( DSA_secret_key *sk, unsigned qbits ) -{ - DSA_public_key pk; - MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); - MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); - MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB ); - - pk.p = sk->p; - pk.q = sk->q; - pk.g = sk->g; - pk.y = sk->y; - /*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/ - { char *p = get_random_bits( qbits, 0, 0 ); - mpi_set_buffer( test, p, (qbits+7)/8, 0 ); - m_free(p); - } - - sign( out1_a, out1_b, test, sk ); - if( !verify( out1_a, out1_b, test, &pk ) ) - log_fatal("DSA:: sign, verify failed\n"); - - mpi_free( test ); - mpi_free( out1_a ); - mpi_free( out1_b ); -} - - - -/**************** - * Generate a DSA key pair with a key of size NBITS - * Returns: 2 structures filled with all needed values - * and an array with the n-1 factors of (p-1) - */ -static void -generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors ) -{ - MPI p; /* the prime */ - MPI q; /* the 160 bit prime factor */ - MPI g; /* the generator */ - MPI y; /* g^x mod p */ - MPI x; /* the secret exponent */ - MPI h, e; /* helper */ - unsigned qbits; - byte *rndbuf; - - assert( nbits >= 512 && nbits <= 1024 ); - - qbits = 160; - p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors ); - /* get q out of factors */ - q = mpi_copy((*ret_factors)[0]); - if( mpi_get_nbits(q) != qbits ) - BUG(); - - /* find a generator g (h and e are helpers)*/ - /* e = (p-1)/q */ - e = mpi_alloc( mpi_get_nlimbs(p) ); - mpi_sub_ui( e, p, 1 ); - mpi_fdiv_q( e, e, q ); - g = mpi_alloc( mpi_get_nlimbs(p) ); - h = mpi_alloc_set_ui( 1 ); /* we start with 2 */ - do { - mpi_add_ui( h, h, 1 ); - /* g = h^e mod p */ - mpi_powm( g, h, e, p ); - } while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */ - - /* select a random number which has these properties: - * 0 < x < q-1 - * This must be a very good random number because this - * is the secret part. */ - if( DBG_CIPHER ) - log_debug("choosing a random x "); - assert( qbits >= 160 ); - x = mpi_alloc_secure( mpi_get_nlimbs(q) ); - mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ - rndbuf = NULL; - do { - if( DBG_CIPHER ) - progress('.'); - if( !rndbuf ) - rndbuf = get_random_bits( qbits, 2, 1 ); - else { /* change only some of the higher bits (= 2 bytes)*/ - char *r = get_random_bits( 16, 2, 1 ); - memcpy(rndbuf, r, 16/8 ); - m_free(r); - } - mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); - mpi_clear_highbit( x, qbits+1 ); - } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); - m_free(rndbuf); - mpi_free( e ); - mpi_free( h ); - - /* y = g^x mod p */ - y = mpi_alloc( mpi_get_nlimbs(p) ); - mpi_powm( y, g, x, p ); - - if( DBG_CIPHER ) { - progress('\n'); - log_mpidump("dsa p= ", p ); - log_mpidump("dsa q= ", q ); - log_mpidump("dsa g= ", g ); - log_mpidump("dsa y= ", y ); - log_mpidump("dsa x= ", x ); - } - - /* copy the stuff to the key structures */ - sk->p = p; - sk->q = q; - sk->g = g; - sk->y = y; - sk->x = x; - - /* now we can test our keys (this should never fail!) */ - test_keys( sk, qbits ); -} - - - -/**************** - * Test whether the secret key is valid. - * Returns: if this is a valid key. - */ -static int -check_secret_key( DSA_secret_key *sk ) -{ - int rc; - MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); - - mpi_powm( y, sk->g, sk->x, sk->p ); - rc = !mpi_cmp( y, sk->y ); - mpi_free( y ); - return rc; -} - - - -/**************** - * Make a DSA signature from HASH and put it into r and s. - * - * Without generating the k this function runs in - * about 26ms on a 300 Mhz Mobile Pentium - */ - -static void -sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey ) -{ - MPI k; - MPI kinv; - MPI tmp; - - /* select a random k with 0 < k < q */ - k = gen_k( skey->q ); - - /* r = (a^k mod p) mod q */ - mpi_powm( r, skey->g, k, skey->p ); - mpi_fdiv_r( r, r, skey->q ); - - /* kinv = k^(-1) mod q */ - kinv = mpi_alloc( mpi_get_nlimbs(k) ); - mpi_invm(kinv, k, skey->q ); - - /* s = (kinv * ( hash + x * r)) mod q */ - tmp = mpi_alloc( mpi_get_nlimbs(skey->p) ); - mpi_mul( tmp, skey->x, r ); - mpi_add( tmp, tmp, hash ); - mpi_mulm( s , kinv, tmp, skey->q ); - - mpi_free(k); - mpi_free(kinv); - mpi_free(tmp); -} - - -/**************** - * Returns true if the signature composed from R and S is valid. - * - * Without the checks this function runs in - * about 31ms on a 300 Mhz Mobile Pentium - */ -static int -verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey ) -{ - int rc; - MPI w, u1, u2, v; - MPI base[3]; - MPI exp[3]; - - - if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) ) - return 0; /* assertion 0 < r < q failed */ - if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) ) - return 0; /* assertion 0 < s < q failed */ - - w = mpi_alloc( mpi_get_nlimbs(pkey->q) ); - u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); - u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) ); - v = mpi_alloc( mpi_get_nlimbs(pkey->p) ); - - /* w = s^(-1) mod q */ - mpi_invm( w, s, pkey->q ); - - /* u1 = (hash * w) mod q */ - mpi_mulm( u1, hash, w, pkey->q ); - - /* u2 = r * w mod q */ - mpi_mulm( u2, r, w, pkey->q ); - - /* v = g^u1 * y^u2 mod p mod q */ - base[0] = pkey->g; exp[0] = u1; - base[1] = pkey->y; exp[1] = u2; - base[2] = NULL; exp[2] = NULL; - mpi_mulpowm( v, base, exp, pkey->p ); - mpi_fdiv_r( v, v, pkey->q ); - - rc = !mpi_cmp( v, r ); - - mpi_free(w); - mpi_free(u1); - mpi_free(u2); - mpi_free(v); - return rc; -} - - -/********************************************* - ************** interface ****************** - *********************************************/ - -int -dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) -{ - DSA_secret_key sk; - - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - - generate( &sk, nbits, retfactors ); - skey[0] = sk.p; - skey[1] = sk.q; - skey[2] = sk.g; - skey[3] = sk.y; - skey[4] = sk.x; - return 0; -} - - -int -dsa_check_secret_key( int algo, MPI *skey ) -{ - DSA_secret_key sk; - - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] ) - return G10ERR_BAD_MPI; - - sk.p = skey[0]; - sk.q = skey[1]; - sk.g = skey[2]; - sk.y = skey[3]; - sk.x = skey[4]; - if( !check_secret_key( &sk ) ) - return G10ERR_BAD_SECKEY; - - return 0; -} - - - -int -dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ) -{ - DSA_secret_key sk; - - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] ) - return G10ERR_BAD_MPI; - - sk.p = skey[0]; - sk.q = skey[1]; - sk.g = skey[2]; - sk.y = skey[3]; - sk.x = skey[4]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - sign( resarr[0], resarr[1], data, &sk ); - return 0; -} - -int -dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ) -{ - DSA_public_key pk; - - if( algo != PUBKEY_ALGO_DSA ) - return G10ERR_PUBKEY_ALGO; - if( !data[0] || !data[1] || !hash - || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] ) - return G10ERR_BAD_MPI; - - pk.p = pkey[0]; - pk.q = pkey[1]; - pk.g = pkey[2]; - pk.y = pkey[3]; - if( !verify( data[0], data[1], hash, &pk ) ) - return G10ERR_BAD_SIGN; - return 0; -} - - - -unsigned -dsa_get_nbits( int algo, MPI *pkey ) -{ - if( algo != PUBKEY_ALGO_DSA ) - return 0; - return mpi_get_nbits( pkey[0] ); -} - - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - * Usage: Bit 0 set : allows signing - * 1 set : allows encryption - */ -const char * -dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, - int *use ) -{ - *npkey = 4; - *nskey = 5; - *nenc = 0; - *nsig = 2; - - switch( algo ) { - case PUBKEY_ALGO_DSA: *use = PUBKEY_USAGE_SIG; return "DSA"; - default: *use = 0; return NULL; - } -} - - diff --git a/cipher/dsa.h b/cipher/dsa.h deleted file mode 100644 index 89fd1f5a0..000000000 --- a/cipher/dsa.h +++ /dev/null @@ -1,32 +0,0 @@ -/* dsa.h - DSA signature algorithm - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_DSA_H -#define G10_DSA_H - -int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); -int dsa_check_secret_key( int algo, MPI *skey ); -int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ); -int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ); -unsigned dsa_get_nbits( int algo, MPI *pkey ); -const char *dsa_get_info( int algo, int *npkey, int *nskey, - int *nenc, int *nsig, int *use ); - -#endif /*G10_DSA_H*/ diff --git a/cipher/dynload.c b/cipher/dynload.c deleted file mode 100644 index 38c6a0c35..000000000 --- a/cipher/dynload.c +++ /dev/null @@ -1,103 +0,0 @@ -/* dynload.c - load cipher extensions - * Copyright (C) 1998, 1999, 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 -#include -#include -#include -#include -#include "util.h" -#include "cipher.h" -#include "algorithms.h" - - -typedef struct ext_list { - struct ext_list *next; - char name[1]; -} *EXTLIST; - -static EXTLIST extensions; - -/* This is actually not used anymore but we keep a list of already - * set extensions modules here. - * - * Here is the ancient comment: - * Register an extension module. The last registered module will - * be loaded first. A name may have a list of classes - * appended; e.g: - * mymodule.so(1:17,3:20,3:109) - * means that this module provides digest algorithm 17 and public key - * algorithms 20 and 109. This is only a hint but if it is there the - * loader may decide to only load a module which claims to have a - * requested algorithm. - * - * mainpgm is the path to the program which wants to load a module - * it is only used in some environments. - */ -void -register_cipher_extension( const char *mainpgm, const char *fname ) -{ - EXTLIST r, el, intex; - char *p, *pe; - - if( *fname != DIRSEP_C ) { /* do tilde expansion etc */ - char *tmp; - - if( strchr(fname, DIRSEP_C) ) - tmp = make_filename(fname, NULL); - else - tmp = make_filename(GNUPG_LIBDIR, fname, NULL); - el = m_alloc_clear( sizeof *el + strlen(tmp) ); - strcpy(el->name, tmp ); - m_free(tmp); - } - else { - el = m_alloc_clear( sizeof *el + strlen(fname) ); - strcpy(el->name, fname ); - } - /* check whether we have a class hint */ - if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) - *p = *pe = 0; - - /* check that it is not already registered */ - intex = NULL; - for(r = extensions; r; r = r->next ) { - if( !compare_filenames(r->name, el->name) ) { - log_info("extension `%s' already registered\n", el->name ); - m_free(el); - return; - } - } - /* and register */ - el->next = extensions; - extensions = el; -} - -/* Return the module name with index SEQ, return NULL as as indication - for end of list. */ -const char * -dynload_enum_module_names (int seq) -{ - EXTLIST el = extensions; - - for (; el && el->name && seq; el = el->next, seq--) - ; - return el? el->name:NULL; -} diff --git a/cipher/elgamal.c b/cipher/elgamal.c deleted file mode 100644 index b4563cd58..000000000 --- a/cipher/elgamal.c +++ /dev/null @@ -1,666 +0,0 @@ -/* elgamal.c - ElGamal Public Key encryption - * Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. - * - * For a description of the algorithm, see: - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. - * ISBN 0-471-11709-9. Pages 476 ff. - * - * 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 -#include -#include -#include -#include "util.h" -#include "mpi.h" -#include "cipher.h" -#include "elgamal.h" - -typedef struct { - MPI p; /* prime */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ -} ELG_public_key; - - -typedef struct { - MPI p; /* prime */ - MPI g; /* group generator */ - MPI y; /* g^x mod p */ - MPI x; /* secret exponent */ -} ELG_secret_key; - - -static void test_keys( ELG_secret_key *sk, unsigned nbits ); -static MPI gen_k( MPI p ); -static void generate( ELG_secret_key *sk, unsigned nbits, MPI **factors ); -static int check_secret_key( ELG_secret_key *sk ); -static void do_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ); -static void decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ); -static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey); -static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey); - - -static void (*progress_cb) ( void *, int ); -static void *progress_cb_data; - -void -register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data ) -{ - progress_cb = cb; - progress_cb_data = cb_data; -} - - -static void -progress( int c ) -{ - if ( progress_cb ) - progress_cb ( progress_cb_data, c ); - else - fputc( c, stderr ); -} - - -/**************** - * Michael Wiener's table about subgroup sizes to match field sizes - * (floating around somewhere - Fixme: need a reference) - */ -static unsigned int -wiener_map( unsigned int n ) -{ - static struct { unsigned int p_n, q_n; } t[] = - { /* p q attack cost */ - { 512, 119 }, /* 9 x 10^17 */ - { 768, 145 }, /* 6 x 10^21 */ - { 1024, 165 }, /* 7 x 10^24 */ - { 1280, 183 }, /* 3 x 10^27 */ - { 1536, 198 }, /* 7 x 10^29 */ - { 1792, 212 }, /* 9 x 10^31 */ - { 2048, 225 }, /* 8 x 10^33 */ - { 2304, 237 }, /* 5 x 10^35 */ - { 2560, 249 }, /* 3 x 10^37 */ - { 2816, 259 }, /* 1 x 10^39 */ - { 3072, 269 }, /* 3 x 10^40 */ - { 3328, 279 }, /* 8 x 10^41 */ - { 3584, 288 }, /* 2 x 10^43 */ - { 3840, 296 }, /* 4 x 10^44 */ - { 4096, 305 }, /* 7 x 10^45 */ - { 4352, 313 }, /* 1 x 10^47 */ - { 4608, 320 }, /* 2 x 10^48 */ - { 4864, 328 }, /* 2 x 10^49 */ - { 5120, 335 }, /* 3 x 10^50 */ - { 0, 0 } - }; - int i; - - for(i=0; t[i].p_n; i++ ) { - if( n <= t[i].p_n ) - return t[i].q_n; - } - /* not in table - use some arbitrary high number ;-) */ - return n / 8 + 200; -} - -static void -test_keys( ELG_secret_key *sk, unsigned nbits ) -{ - ELG_public_key pk; - MPI test = mpi_alloc( 0 ); - MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); - MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); - MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB ); - - pk.p = sk->p; - pk.g = sk->g; - pk.y = sk->y; - - /*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/ - { char *p = get_random_bits( nbits, 0, 0 ); - mpi_set_buffer( test, p, (nbits+7)/8, 0 ); - m_free(p); - } - - do_encrypt( out1_a, out1_b, test, &pk ); - decrypt( out2, out1_a, out1_b, sk ); - if( mpi_cmp( test, out2 ) ) - log_fatal("ElGamal operation: encrypt, decrypt failed\n"); - - sign( out1_a, out1_b, test, sk ); - if( !verify( out1_a, out1_b, test, &pk ) ) - log_fatal("ElGamal operation: sign, verify failed\n"); - - mpi_free( test ); - mpi_free( out1_a ); - mpi_free( out1_b ); - mpi_free( out2 ); -} - - -/**************** - * generate a random secret exponent k from prime p, so - * that k is relatively prime to p-1 - */ -static MPI -gen_k( MPI p ) -{ - MPI k = mpi_alloc_secure( 0 ); - MPI temp = mpi_alloc( mpi_get_nlimbs(p) ); - MPI p_1 = mpi_copy(p); - unsigned int orig_nbits = mpi_get_nbits(p); - unsigned int nbits; - unsigned int nbytes; - char *rndbuf = NULL; - - /* IMO using a k much lesser than p is sufficient and it greatly - * improves the encryption performance. We use Wiener's table - * and add a large safety margin. - */ - nbits = wiener_map( orig_nbits ) * 3 / 2; - if( nbits >= orig_nbits ) - BUG(); - - nbytes = (nbits+7)/8; - if( DBG_CIPHER ) - log_debug("choosing a random k of %u bits", nbits); - mpi_sub_ui( p_1, p, 1); - for(;;) { - if( !rndbuf || nbits < 32 ) { - m_free(rndbuf); - rndbuf = get_random_bits( nbits, 1, 1 ); - } - else { /* change only some of the higher bits */ - /* we could impprove this by directly requesting more memory - * at the first call to get_random_bits() and use this the here - * maybe it is easier to do this directly in random.c - * Anyway, it is highly inlikely that we will ever reach this code - */ - char *pp = get_random_bits( 32, 1, 1 ); - memcpy( rndbuf,pp, 4 ); - m_free(pp); - log_debug("gen_k: tsss, never expected to reach this\n"); - } - mpi_set_buffer( k, rndbuf, nbytes, 0 ); - - for(;;) { - /* Hmm, actually we don't need this step here - * because we use k much smaller than p - we do it anyway - * just in case the keep on adding a one to k ;) */ - if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */ - if( DBG_CIPHER ) - progress('+'); - break; /* no */ - } - if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */ - if( DBG_CIPHER ) - progress('-'); - break; /* no */ - } - if( mpi_gcd( temp, k, p_1 ) ) - goto found; /* okay, k is relatively prime to (p-1) */ - mpi_add_ui( k, k, 1 ); - if( DBG_CIPHER ) - progress('.'); - } - } - found: - m_free(rndbuf); - if( DBG_CIPHER ) - progress('\n'); - mpi_free(p_1); - mpi_free(temp); - - return k; -} - -/**************** - * Generate a key pair with a key of size NBITS - * Returns: 2 structures filles with all needed values - * and an array with n-1 factors of (p-1) - */ -static void -generate( ELG_secret_key *sk, unsigned int nbits, MPI **ret_factors ) -{ - MPI p; /* the prime */ - MPI p_min1; - MPI g; - MPI x; /* the secret exponent */ - MPI y; - MPI temp; - unsigned int qbits; - unsigned int xbits; - byte *rndbuf; - - p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - qbits = wiener_map( nbits ); - if( qbits & 1 ) /* better have a even one */ - qbits++; - g = mpi_alloc(1); - p = generate_elg_prime( 0, nbits, qbits, g, ret_factors ); - mpi_sub_ui(p_min1, p, 1); - - - /* select a random number which has these properties: - * 0 < x < p-1 - * This must be a very good random number because this is the - * secret part. The prime is public and may be shared anyway, - * so a random generator level of 1 is used for the prime. - * - * I don't see a reason to have a x of about the same size - * as the p. It should be sufficient to have one about the size - * of q or the later used k plus a large safety margin. Decryption - * will be much faster with such an x. - */ - xbits = qbits * 3 / 2; - if( xbits >= nbits ) - BUG(); - x = mpi_alloc_secure( xbits/BITS_PER_MPI_LIMB ); - if( DBG_CIPHER ) - log_debug("choosing a random x of size %u", xbits ); - rndbuf = NULL; - do { - if( DBG_CIPHER ) - progress('.'); - if( rndbuf ) { /* change only some of the higher bits */ - if( xbits < 16 ) {/* should never happen ... */ - m_free(rndbuf); - rndbuf = get_random_bits( xbits, 2, 1 ); - } - else { - char *r = get_random_bits( 16, 2, 1 ); - memcpy(rndbuf, r, 16/8 ); - m_free(r); - } - } - else - rndbuf = get_random_bits( xbits, 2, 1 ); - mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); - mpi_clear_highbit( x, xbits+1 ); - } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); - m_free(rndbuf); - - y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); - mpi_powm( y, g, x, p ); - - if( DBG_CIPHER ) { - progress('\n'); - log_mpidump("elg p= ", p ); - log_mpidump("elg g= ", g ); - log_mpidump("elg y= ", y ); - log_mpidump("elg x= ", x ); - } - - /* copy the stuff to the key structures */ - sk->p = p; - sk->g = g; - sk->y = y; - sk->x = x; - - /* now we can test our keys (this should never fail!) */ - test_keys( sk, nbits - 64 ); - - mpi_free( p_min1 ); - mpi_free( temp ); -} - - -/**************** - * Test whether the secret key is valid. - * Returns: if this is a valid key. - */ -static int -check_secret_key( ELG_secret_key *sk ) -{ - int rc; - MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) ); - - mpi_powm( y, sk->g, sk->x, sk->p ); - rc = !mpi_cmp( y, sk->y ); - mpi_free( y ); - return rc; -} - - -static void -do_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey ) -{ - MPI k; - - /* Note: maybe we should change the interface, so that it - * is possible to check that input is < p and return an - * error code. - */ - - k = gen_k( pkey->p ); - mpi_powm( a, pkey->g, k, pkey->p ); - /* b = (y^k * input) mod p - * = ((y^k mod p) * (input mod p)) mod p - * and because input is < p - * = ((y^k mod p) * input) mod p - */ - mpi_powm( b, pkey->y, k, pkey->p ); - mpi_mulm( b, b, input, pkey->p ); - #if 0 - if( DBG_CIPHER ) { - log_mpidump("elg encrypted y= ", pkey->y); - log_mpidump("elg encrypted p= ", pkey->p); - log_mpidump("elg encrypted k= ", k); - log_mpidump("elg encrypted M= ", input); - log_mpidump("elg encrypted a= ", a); - log_mpidump("elg encrypted b= ", b); - } - #endif - mpi_free(k); -} - - - - -static void -decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey ) -{ - MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); - - /* output = b/(a^x) mod p */ - mpi_powm( t1, a, skey->x, skey->p ); - mpi_invm( t1, t1, skey->p ); - mpi_mulm( output, b, t1, skey->p ); - #if 0 - if( DBG_CIPHER ) { - log_mpidump("elg decrypted x= ", skey->x); - log_mpidump("elg decrypted p= ", skey->p); - log_mpidump("elg decrypted a= ", a); - log_mpidump("elg decrypted b= ", b); - log_mpidump("elg decrypted M= ", output); - } - #endif - mpi_free(t1); -} - - -/**************** - * Make an Elgamal signature out of INPUT - */ - -static void -sign(MPI a, MPI b, MPI input, ELG_secret_key *skey ) -{ - MPI k; - MPI t = mpi_alloc( mpi_get_nlimbs(a) ); - MPI inv = mpi_alloc( mpi_get_nlimbs(a) ); - MPI p_1 = mpi_copy(skey->p); - - /* - * b = (t * inv) mod (p-1) - * b = (t * inv(k,(p-1),(p-1)) mod (p-1) - * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) - * - */ - mpi_sub_ui(p_1, p_1, 1); - k = gen_k( skey->p ); - mpi_powm( a, skey->g, k, skey->p ); - mpi_mul(t, skey->x, a ); - mpi_subm(t, input, t, p_1 ); - while( mpi_is_neg(t) ) { - BUG(); /* That is nonsense code - left over from a very early test?*/ - mpi_add(t, t, p_1); - } - mpi_invm(inv, k, p_1 ); - mpi_mulm(b, t, inv, p_1 ); - - #if 0 - if( DBG_CIPHER ) { - log_mpidump("elg sign p= ", skey->p); - log_mpidump("elg sign g= ", skey->g); - log_mpidump("elg sign y= ", skey->y); - log_mpidump("elg sign x= ", skey->x); - log_mpidump("elg sign k= ", k); - log_mpidump("elg sign M= ", input); - log_mpidump("elg sign a= ", a); - log_mpidump("elg sign b= ", b); - } - #endif - mpi_free(k); - mpi_free(t); - mpi_free(inv); - mpi_free(p_1); -} - - -/**************** - * Returns true if the signature composed of A and B is valid. - */ -static int -verify(MPI a, MPI b, MPI input, ELG_public_key *pkey ) -{ - int rc; - MPI t1; - MPI t2; - MPI base[4]; - MPI exp[4]; - - if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) - return 0; /* assertion 0 < a < p failed */ - - t1 = mpi_alloc( mpi_get_nlimbs(a) ); - t2 = mpi_alloc( mpi_get_nlimbs(a) ); - - #if 0 - /* t1 = (y^a mod p) * (a^b mod p) mod p */ - mpi_powm( t1, pkey->y, a, pkey->p ); - mpi_powm( t2, a, b, pkey->p ); - mpi_mulm( t1, t1, t2, pkey->p ); - - /* t2 = g ^ input mod p */ - mpi_powm( t2, pkey->g, input, pkey->p ); - - rc = !mpi_cmp( t1, t2 ); - #elif 0 - /* t1 = (y^a mod p) * (a^b mod p) mod p */ - base[0] = pkey->y; exp[0] = a; - base[1] = a; exp[1] = b; - base[2] = NULL; exp[2] = NULL; - mpi_mulpowm( t1, base, exp, pkey->p ); - - /* t2 = g ^ input mod p */ - mpi_powm( t2, pkey->g, input, pkey->p ); - - rc = !mpi_cmp( t1, t2 ); - #else - /* t1 = g ^ - input * y ^ a * a ^ b mod p */ - mpi_invm(t2, pkey->g, pkey->p ); - base[0] = t2 ; exp[0] = input; - base[1] = pkey->y; exp[1] = a; - base[2] = a; exp[2] = b; - base[3] = NULL; exp[3] = NULL; - mpi_mulpowm( t1, base, exp, pkey->p ); - rc = !mpi_cmp_ui( t1, 1 ); - - #endif - - mpi_free(t1); - mpi_free(t2); - return rc; -} - -/********************************************* - ************** interface ****************** - *********************************************/ - -int -elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) -{ - ELG_secret_key sk; - - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - - generate( &sk, nbits, retfactors ); - skey[0] = sk.p; - skey[1] = sk.g; - skey[2] = sk.y; - skey[3] = sk.x; - return 0; -} - - -int -elg_check_secret_key( int algo, MPI *skey ) -{ - ELG_secret_key sk; - - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !skey[0] || !skey[1] || !skey[2] || !skey[3] ) - return G10ERR_BAD_MPI; - - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - if( !check_secret_key( &sk ) ) - return G10ERR_BAD_SECKEY; - - return 0; -} - - - -int -elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) -{ - ELG_public_key pk; - - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data || !pkey[0] || !pkey[1] || !pkey[2] ) - return G10ERR_BAD_MPI; - - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) ); - do_encrypt( resarr[0], resarr[1], data, &pk ); - return 0; -} - -int -elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) -{ - ELG_secret_key sk; - - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data[0] || !data[1] - || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) - return G10ERR_BAD_MPI; - - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - *result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) ); - decrypt( *result, data[0], data[1], &sk ); - return 0; -} - -int -elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ) -{ - ELG_secret_key sk; - - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] ) - return G10ERR_BAD_MPI; - - sk.p = skey[0]; - sk.g = skey[1]; - sk.y = skey[2]; - sk.x = skey[3]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) ); - sign( resarr[0], resarr[1], data, &sk ); - return 0; -} - -int -elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ) -{ - ELG_public_key pk; - - if( !is_ELGAMAL(algo) ) - return G10ERR_PUBKEY_ALGO; - if( !data[0] || !data[1] || !hash - || !pkey[0] || !pkey[1] || !pkey[2] ) - return G10ERR_BAD_MPI; - - pk.p = pkey[0]; - pk.g = pkey[1]; - pk.y = pkey[2]; - if( !verify( data[0], data[1], hash, &pk ) ) - return G10ERR_BAD_SIGN; - return 0; -} - - - -unsigned int -elg_get_nbits( int algo, MPI *pkey ) -{ - if( !is_ELGAMAL(algo) ) - return 0; - return mpi_get_nbits( pkey[0] ); -} - - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - * Usage: Bit 0 set : allows signing - * 1 set : allows encryption - * NOTE: This function allows signing also for ELG-E, which is not - * okay but a bad hack to allow to work with old gpg keys. The real check - * is done in the gnupg ocde depending on the packet version. - */ -const char * -elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig, - int *use ) -{ - *npkey = 3; - *nskey = 4; - *nenc = 2; - *nsig = 2; - - switch( algo ) { - case PUBKEY_ALGO_ELGAMAL: - *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; - return "ELG"; - case PUBKEY_ALGO_ELGAMAL_E: - *use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC; - return "ELG-E"; - default: *use = 0; return NULL; - } -} - - diff --git a/cipher/elgamal.h b/cipher/elgamal.h deleted file mode 100644 index f104c2a52..000000000 --- a/cipher/elgamal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* elgamal.h - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_ELGAMAL_H -#define G10_ELGAMAL_H - -int elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); -int elg_check_secret_key( int algo, MPI *skey ); -int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); -int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); -int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey ); -int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ); -unsigned elg_get_nbits( int algo, MPI *pkey ); -const char *elg_get_info( int algo, int *npkey, int *nskey, - int *nenc, int *nsig, int *use ); - - -#endif /*G10_ELGAMAL_H*/ diff --git a/cipher/g10c.c b/cipher/g10c.c deleted file mode 100644 index 7b0f4fa61..000000000 --- a/cipher/g10c.c +++ /dev/null @@ -1,46 +0,0 @@ -/* g10c.c - Wrapper for cipher functions - * Copyright (C) 1998, 1999 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 -#include -#include -#include "mpi.h" -#include "random.h" -#include "cipher.h" - - -/* FIXME: The modules should use functions from libgcrypt */ - - -const char *g10c_revision_string(int dummy) { return "$Revision$"; } - -MPI -g10c_generate_secret_prime( unsigned nbits ) -{ - return generate_secret_prime( nbits ); -} - - -char * -g10c_get_random_bits( unsigned nbits, int level, int secure ) -{ - return (char*)get_random_bits( nbits, level, secure ); -} - diff --git a/cipher/gost.c b/cipher/gost.c deleted file mode 100644 index 4a527722f..000000000 --- a/cipher/gost.c +++ /dev/null @@ -1,76 +0,0 @@ -/* gost.c - GOST encryption - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * The description of GOST (and the used S-boxes) are taken from: - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. - * ISBN 0-471-11709-9. . - * - * 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 -#include -#include -#include -#include "util.h" -#include "types.h" -#include "gost.h" - -#error don't use this - - -void -gost_setkey( GOST_context *c, byte *key ) -{ -} - -void -gost_setiv( GOST_context *c, byte *iv ) -{ -} - - -void -gost_encode( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ -} - - -void -gost_decode( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ -} - - -static void -cfbshift( byte *iv, byte *buf, unsigned count) -{ -} - - - -void -gost_encode_cfb( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nbytes) -{ -} - - -void -gost_decode_cfb( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nbytes) -{ -} - diff --git a/cipher/gost.h b/cipher/gost.h deleted file mode 100644 index d8e7ebfc5..000000000 --- a/cipher/gost.h +++ /dev/null @@ -1,46 +0,0 @@ -/* gost.h - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef G10_GOST_H -#define G10_GOST_H - -#include "types.h" - -#define GOST_KEYSIZE 16 -#define GOST_BLOCKSIZE 8 -#define GOST_ROUNDS 8 -#define GOST_KEYLEN (6*GOST_ROUNDS+4) - -typedef struct { - u16 ek[GOST_KEYLEN]; - u16 dk[GOST_KEYLEN]; - byte iv[GOST_BLOCKSIZE]; -} GOST_context; - -void gost_setkey( GOST_context *c, byte *key ); -void gost_setiv( GOST_context *c, byte *iv ); -void gost_encode( GOST_context *c, byte *out, byte *in, unsigned nblocks ); -void gost_decode( GOST_context *c, byte *out, byte *in, unsigned nblocks ); -void gost_encode_cfb( GOST_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); -void gost_decode_cfb( GOST_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); - - -#endif /*G10_GOST_H*/ diff --git a/cipher/idea-stub.c b/cipher/idea-stub.c deleted file mode 100644 index 9dd0ced30..000000000 --- a/cipher/idea-stub.c +++ /dev/null @@ -1,198 +0,0 @@ -/* idea-stub.c - Dummy module for the deprecated IDEA cipher. - * 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 - */ - -/* IDEA is a patented algorithm and therefore the use of IDEA in - countries where this patent is valid can not be allowed due to the - terms of the GNU General Public License. Those restrictions are - there to help protecting the freedom of software. For more - information on the nonsense of software patents and the general - problem with this, please see http://www.noepatents.org. - - However for research purposes and in certain situations it might be - useful to use this algorithm anyway. - - We provide this stub which will dynload a idea module and is only - used if the configure run did't found statically linked file. - See http://www.gnupg.org/why-not-dea.html for details. -*/ - -#include -#include -#include -#include -#include -#ifdef HAVE_DL_DLOPEN - #include -#endif -#ifdef __MINGW32__ - #include -#endif -#include "util.h" -#include "algorithms.h" - -#ifndef RTLD_NOW - #define RTLD_NOW 1 -#endif - - -#ifdef __MINGW32__ -#define HAVE_DL_DLOPEN -#define USE_DYNAMIC_LINKING - -static int last_error = 0; - -void* -dlopen (const char *pathname, int mode) -{ - void *h = LoadLibrary (pathname); - if (!h) - { - log_error ("LoadLibrary failed ec=%d\n", (int)GetLastError()); - last_error = 1; - return NULL; - } - return h; -} - -int -dlclose ( void *handle ) -{ - last_error = 0; - return FreeLibrary (handle); -} - -char* -dlerror (void) -{ - static char dlerrstr[10]; - if (last_error) - { - sprintf(dlerrstr, "%d", (int)GetLastError() ); - return dlerrstr; - } - return NULL; -} - -void* -dlsym ( void *handle, const char *name ) -{ - void *h = GetProcAddress (handle, name); - if (!h) - { - log_error ("GetProcAddress failed ec=%d\n", (int)GetLastError()); - last_error = 1; - } - return h; -} -#endif /*__MINGW32__*/ - -/* We do only support dlopen and the Windows emulation of it. */ -#ifndef HAVE_DL_DLOPEN -#undef USE_DYNAMIC_LINKING -#endif - - -static void * -load_module (const char *name) -{ -#ifdef USE_DYNAMIC_LINKING - const char *err; - void *handle; - void *sym; - -#ifndef __MINGW32__ - /* Make sure we are not setuid. */ - if (getuid() != geteuid()) - log_bug("trying to load an extension while still setuid\n"); -#endif - - handle = dlopen (name, RTLD_NOW); - if (!name) - { - /*log_error ("error loading module `%s': %s\n", name, dlerror());*/ - goto failure; - } - - sym = dlsym (handle, "idea_get_info"); - if (dlerror ()) - sym = dlsym (handle, "_idea_get_info"); - if ((err=dlerror())) - { - log_info ("invalid module `%s': %s\n", name, err); - goto failure; - } - - return sym; - - failure: - if (handle) - dlclose (handle); -#endif /*USE_DYNAMIC_LINKING*/ - return NULL; -} - -#ifdef __riscos__ -typedef -const char *(*INFO_CAST)(int, size_t*, size_t*, size_t*, - int (**)( void *, byte *, unsigned), - void (**)( void *, byte *, byte *), - void (**)( void *, byte *, byte *)); -#endif /* __riscos__ */ - -const char * -idea_get_info( int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**r_setkey)( void *c, byte *key, unsigned keylen ), - void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ), - void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf ) - ) -{ - static int initialized; - static const char * (*info_fnc)(int, size_t*, size_t*, size_t*, - int (**)( void *, byte *, unsigned), - void (**)( void *, byte *, byte *), - void (**)( void *, byte *, byte *)); - const char *rstr; - int i; - - if (!initialized) - { - initialized = 1; - for (i=0; (rstr = dynload_enum_module_names (i)); i++) - { -#ifndef __riscos__ - info_fnc = load_module (rstr); -#else /* __riscos__ */ - info_fnc = (INFO_CAST) load_module (rstr); -#endif /* __riscos__ */ - if (info_fnc) - break; - } - } - if (!info_fnc) - return NULL; /* dynloadable module not found. */ - rstr = info_fnc (algo, keylen, blocksize, contextsize, - r_setkey, r_encrypt, r_decrypt); - if (rstr && *keylen == 128 && *blocksize == 8 - && *r_setkey && *r_encrypt && r_decrypt) - return rstr; - return NULL; -} - diff --git a/cipher/md.c b/cipher/md.c deleted file mode 100644 index d0811e254..000000000 --- a/cipher/md.c +++ /dev/null @@ -1,505 +0,0 @@ -/* md.c - message digest dispatcher - * Copyright (C) 1998, 1999, 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 -#include -#include -#include -#include -#include -#include "util.h" -#include "cipher.h" -#include "errors.h" -#include "algorithms.h" - -/**************** - * This structure is used for the list of available algorithms - * and for the list of algorithms in MD_HANDLE. - */ -struct md_digest_list_s { - struct md_digest_list_s *next; - const char *name; - int algo; - byte *asnoid; - int asnlen; - int mdlen; - void (*init)( void *c ); - void (*write)( void *c, byte *buf, size_t nbytes ); - void (*final)( void *c ); - byte *(*read)( void *c ); - size_t contextsize; /* allocate this amount of context */ - PROPERLY_ALIGNED_TYPE context; -}; - -static struct md_digest_list_s *digest_list; - - -static struct md_digest_list_s * -new_list_item (int algo, - const char *(*get_info)( int, size_t*,byte**, int*, int*, - void (**)(void*), - void (**)(void*,byte*,size_t), - void (**)(void*),byte *(**)(void*))) -{ - struct md_digest_list_s *r; - - r = m_alloc_clear (sizeof *r ); - r->algo = algo; - r->name = (*get_info)( algo, &r->contextsize, - &r->asnoid, &r->asnlen, &r->mdlen, - &r->init, &r->write, &r->final, &r->read ); - if (!r->name ) - { - m_free(r); - r = NULL; - } - if (r) - { - r->next = digest_list; - digest_list = r; - } - return r; -} - - - -/* - Load all available hash algorithms and return true. Subsequent - calls will return 0. - */ -static int -load_digest_module (void) -{ - static int initialized = 0; - - if (initialized) - return 0; - initialized = 1; - - /* We load them in reverse order so that the most - frequently used are the first in the list. */ - if (!new_list_item (DIGEST_ALGO_TIGER, tiger_get_info)) - BUG(); - if (!new_list_item (DIGEST_ALGO_MD5, md5_get_info)) - BUG (); - if (!new_list_item (DIGEST_ALGO_RMD160, rmd160_get_info)) - BUG (); - if (!new_list_item (DIGEST_ALGO_SHA1, sha1_get_info)) - BUG (); - - return 1; -} - - -/**************** - * Map a string to the digest algo */ -int -string_to_digest_algo( const char *string ) -{ - struct md_digest_list_s *r; - - do { - for(r = digest_list; r; r = r->next ) - if( !ascii_strcasecmp( r->name, string ) ) - return r->algo; - } while( !r && load_digest_module () ); - return 0; -} - - -/**************** - * Map a digest algo to a string - */ -const char * -digest_algo_to_string( int algo ) -{ - struct md_digest_list_s *r; - - do { - for(r = digest_list; r; r = r->next ) - if( r->algo == algo ) - return r->name; - } while( !r && load_digest_module () ); - return NULL; -} - - -int -check_digest_algo( int algo ) -{ - struct md_digest_list_s *r; - - do { - for(r = digest_list; r; r = r->next ) - if( r->algo == algo ) - return 0; - } while( !r && load_digest_module () ); - return G10ERR_DIGEST_ALGO; -} - - - -/**************** - * Open a message digest handle for use with algorithm ALGO. - * More algorithms may be added by md_enable(). The initial algorithm - * may be 0. - */ -MD_HANDLE -md_open( int algo, int secure ) -{ - MD_HANDLE hd; - int bufsize; - - if( secure ) { - bufsize = 512 - sizeof( *hd ); - hd = m_alloc_secure_clear( sizeof *hd + bufsize ); - } - else { - bufsize = 1024 - sizeof( *hd ); - hd = m_alloc_clear( sizeof *hd + bufsize ); - } - - hd->bufsize = bufsize+1; /* hd has already one byte allocated */ - hd->secure = secure; - if( algo ) - md_enable( hd, algo ); - fast_random_poll(); - return hd; -} - -void -md_enable( MD_HANDLE h, int algo ) -{ - struct md_digest_list_s *r, *ac; - - for( ac=h->list; ac; ac = ac->next ) - if( ac->algo == algo ) - return ; /* already enabled */ - /* find the algorithm */ - do { - for(r = digest_list; r; r = r->next ) - if( r->algo == algo ) - break; - } while( !r && load_digest_module () ); - if( !r ) { - log_error("md_enable: algorithm %d not available\n", algo ); - return; - } - /* and allocate a new list entry */ - ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize - - sizeof(r->context) ) - : m_alloc( sizeof *ac + r->contextsize - - sizeof(r->context) ); - *ac = *r; - ac->next = h->list; - h->list = ac; - /* and init this instance */ - (*ac->init)( &ac->context.c ); -} - - -MD_HANDLE -md_copy( MD_HANDLE a ) -{ - MD_HANDLE b; - struct md_digest_list_s *ar, *br; - - if( a->bufcount ) - md_write( a, NULL, 0 ); - b = a->secure ? m_alloc_secure( sizeof *b + a->bufsize - 1 ) - : m_alloc( sizeof *b + a->bufsize - 1 ); - memcpy( b, a, sizeof *a + a->bufsize - 1 ); - b->list = NULL; - b->debug = NULL; - /* and now copy the complete list of algorithms */ - /* I know that the copied list is reversed, but that doesn't matter */ - for( ar=a->list; ar; ar = ar->next ) { - br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize - - sizeof(ar->context) ) - : m_alloc( sizeof *br + ar->contextsize - - sizeof(ar->context) ); - memcpy( br, ar, sizeof(*br) + ar->contextsize - - sizeof(ar->context) ); - br->next = b->list; - b->list = br; - } - - if( a->debug ) - md_start_debug( b, "unknown" ); - return b; -} - - -/**************** - * Reset all contexts and discard any buffered stuff. This may be used - * instead of a md_close(); md_open(). - */ -void -md_reset( MD_HANDLE a ) -{ - struct md_digest_list_s *r; - - a->bufcount = a->finalized = 0; - for( r=a->list; r; r = r->next ) { - memset( r->context.c, 0, r->contextsize ); - (*r->init)( &r->context.c ); - } -} - - -void -md_close(MD_HANDLE a) -{ - struct md_digest_list_s *r, *r2; - - if( !a ) - return; - if( a->debug ) - md_stop_debug(a); - for(r=a->list; r; r = r2 ) { - r2 = r->next; - m_free(r); - } - m_free(a); -} - - -void -md_write( MD_HANDLE a, const byte *inbuf, size_t inlen) -{ - struct md_digest_list_s *r; - - if( a->debug ) { - if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 ) - BUG(); - if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 ) - BUG(); - } - for(r=a->list; r; r = r->next ) { - (*r->write)( &r->context.c, a->buffer, a->bufcount ); - /* Fixme: all ->write fnc should take a const byte* */ - (*r->write)( &r->context.c, (byte*)inbuf, inlen ); - } - a->bufcount = 0; -} - - - -void -md_final(MD_HANDLE a) -{ - struct md_digest_list_s *r; - - if( a->finalized ) - return; - - if( a->bufcount ) - md_write( a, NULL, 0 ); - - for(r=a->list; r; r = r->next ) { - (*r->final)( &r->context.c ); - } - a->finalized = 1; -} - - -/**************** - * if ALGO is null get the digest for the used algo (which should be only one) - */ -byte * -md_read( MD_HANDLE a, int algo ) -{ - struct md_digest_list_s *r; - - if( !algo ) { /* return the first algorithm */ - if( (r=a->list) ) { - if( r->next ) - log_debug("more than algorithm in md_read(0)\n"); - return (*r->read)( &r->context.c ); - } - } - else { - for(r=a->list; r; r = r->next ) - if( r->algo == algo ) - return (*r->read)( &r->context.c ); - } - BUG(); - return NULL; -} - - -/**************** - * This function combines md_final and md_read but keeps the context - * intact. This function can be used to calculate intermediate - * digests. The digest is copied into buffer and the digestlength is - * returned. If buffer is NULL only the needed size for buffer is returned. - * buflen gives the max size of buffer. If the buffer is too shourt to - * hold the complete digest, the buffer is filled with as many bytes are - * possible and this value is returned. - */ -int -md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen ) -{ - struct md_digest_list_s *r = NULL; - char *context; - char *digest; - - if( a->bufcount ) - md_write( a, NULL, 0 ); - - if( !algo ) { /* return digest for the first algorithm */ - if( (r=a->list) && r->next ) - log_debug("more than algorithm in md_digest(0)\n"); - } - else { - for(r=a->list; r; r = r->next ) - if( r->algo == algo ) - break; - } - if( !r ) - BUG(); - - if( !buffer ) - return r->mdlen; - - /* I don't want to change the interface, so I simply work on a copy - * the context (extra overhead - should be fixed)*/ - context = a->secure ? m_alloc_secure( r->contextsize ) - : m_alloc( r->contextsize ); - memcpy( context, r->context.c, r->contextsize ); - (*r->final)( context ); - digest = (*r->read)( context ); - - if( buflen > r->mdlen ) - buflen = r->mdlen; - memcpy( buffer, digest, buflen ); - - m_free(context); - return buflen; -} - - -int -md_get_algo( MD_HANDLE a ) -{ - struct md_digest_list_s *r; - - if( (r=a->list) ) { - if( r->next ) - log_error("WARNING: more than algorithm in md_get_algo()\n"); - return r->algo; - } - return 0; -} - -/* Returns true if a given algo is in use in a md */ -int -md_algo_present( MD_HANDLE a, int algo ) -{ - struct md_digest_list_s *r=a->list; - - while(r) - { - if(r->algo==algo) - return 1; - - r=r->next; - } - - return 0; -} - -/**************** - * Return the length of the digest - */ -int -md_digest_length( int algo ) -{ - struct md_digest_list_s *r; - - do { - for(r = digest_list; r; r = r->next ) { - if( r->algo == algo ) - return r->mdlen; - } - } while( !r && load_digest_module () ); - log_error("WARNING: no length for md algo %d\n", algo); - return 0; -} - - -/* Hmmm: add a mode to enumerate the OIDs - * to make g10/sig-check.c more portable */ -const byte * -md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ) -{ - struct md_digest_list_s *r; - - do { - for(r = digest_list; r; r = r->next ) { - if( r->algo == algo ) { - if( asnlen ) - *asnlen = r->asnlen; - if( mdlen ) - *mdlen = r->mdlen; - return r->asnoid; - } - } - } while( !r && load_digest_module () ); - log_bug("no asn for md algo %d\n", algo); - return NULL; -} - - -void -md_start_debug( MD_HANDLE md, const char *suffix ) -{ - static int idx=0; - char buf[25]; - - if( md->debug ) { - log_debug("Oops: md debug already started\n"); - return; - } - idx++; - sprintf(buf, "dbgmd-%05d" EXTSEP_S "%.10s", idx, suffix ); - md->debug = fopen(buf, "w"); - if( !md->debug ) - log_debug("md debug: can't open %s\n", buf ); -} - -void -md_stop_debug( MD_HANDLE md ) -{ - if( md->debug ) { - if( md->bufcount ) - md_write( md, NULL, 0 ); - fclose(md->debug); - md->debug = NULL; - } -#ifdef HAVE_U64_TYPEDEF - { /* a kludge to pull in the __muldi3 for Solaris */ - volatile u32 a = (u32)(ulong)md; - volatile u64 b = 42; - volatile u64 c; - c = a * b; - } -#endif -} diff --git a/cipher/md5.c b/cipher/md5.c deleted file mode 100644 index ca605b6fd..000000000 --- a/cipher/md5.c +++ /dev/null @@ -1,367 +0,0 @@ -/* md5.c - MD5 Message-Digest Algorithm - * Copyright (C) 1995, 1996, 1998, 1999, - * 2000, 2001 Free Software Foundation, Inc. - * - * 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, 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. - * - * According to the definition of MD5 in RFC 1321 from April 1992. - * NOTE: This is *not* the same file as the one from glibc. - */ -/* Written by Ulrich Drepper , 1995. */ -/* Heavily modified for GnuPG by */ - -/* Test values: - * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E - * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 - * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 - * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 - */ - -#include -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "algorithms.h" - -#include "bithelp.h" - - -typedef struct { - u32 A,B,C,D; /* chaining variables */ - u32 nblocks; - byte buf[64]; - int count; -} MD5_CONTEXT; - - -static void -md5_init( MD5_CONTEXT *ctx ) -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - - ctx->nblocks = 0; - ctx->count = 0; -} - - - - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (as found in Colin Plumbs public domain implementation). */ -/* #define FF(b, c, d) ((b & c) | (~b & d)) */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - - -/**************** - * transform n*64 bytes - */ -static void -/*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/ -transform( MD5_CONTEXT *ctx, byte *data ) -{ - u32 correct_words[16]; - u32 A = ctx->A; - u32 B = ctx->B; - u32 C = ctx->C; - u32 D = ctx->D; - u32 *cwp = correct_words; - - #ifdef BIG_ENDIAN_HOST - { int i; - byte *p2, *p1; - for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } - #else - memcpy( correct_words, data, 64 ); - #endif - - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++) + T; \ - a = rol(a, s); \ - a += b; \ - } \ - while (0) - - /* Before we start, one word about the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - */ - - /* Round 1. */ - OP (A, B, C, D, 7, 0xd76aa478); - OP (D, A, B, C, 12, 0xe8c7b756); - OP (C, D, A, B, 17, 0x242070db); - OP (B, C, D, A, 22, 0xc1bdceee); - OP (A, B, C, D, 7, 0xf57c0faf); - OP (D, A, B, C, 12, 0x4787c62a); - OP (C, D, A, B, 17, 0xa8304613); - OP (B, C, D, A, 22, 0xfd469501); - OP (A, B, C, D, 7, 0x698098d8); - OP (D, A, B, C, 12, 0x8b44f7af); - OP (C, D, A, B, 17, 0xffff5bb1); - OP (B, C, D, A, 22, 0x895cd7be); - OP (A, B, C, D, 7, 0x6b901122); - OP (D, A, B, C, 12, 0xfd987193); - OP (C, D, A, B, 17, 0xa679438e); - OP (B, C, D, A, 22, 0x49b40821); - -#undef OP -#define OP(f, a, b, c, d, k, s, T) \ - do \ - { \ - a += f (b, c, d) + correct_words[k] + T; \ - a = rol(a, s); \ - a += b; \ - } \ - while (0) - - /* Round 2. */ - OP (FG, A, B, C, D, 1, 5, 0xf61e2562); - OP (FG, D, A, B, C, 6, 9, 0xc040b340); - OP (FG, C, D, A, B, 11, 14, 0x265e5a51); - OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP (FG, A, B, C, D, 5, 5, 0xd62f105d); - OP (FG, D, A, B, C, 10, 9, 0x02441453); - OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP (FG, D, A, B, C, 14, 9, 0xc33707d6); - OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP (FG, B, C, D, A, 8, 20, 0x455a14ed); - OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP (FG, C, D, A, B, 7, 14, 0x676f02d9); - OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP (FH, A, B, C, D, 5, 4, 0xfffa3942); - OP (FH, D, A, B, C, 8, 11, 0x8771f681); - OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP (FH, B, C, D, A, 14, 23, 0xfde5380c); - OP (FH, A, B, C, D, 1, 4, 0xa4beea44); - OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP (FH, B, C, D, A, 6, 23, 0x04881d05); - OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP (FI, A, B, C, D, 0, 6, 0xf4292244); - OP (FI, D, A, B, C, 7, 10, 0x432aff97); - OP (FI, C, D, A, B, 14, 15, 0xab9423a7); - OP (FI, B, C, D, A, 5, 21, 0xfc93a039); - OP (FI, A, B, C, D, 12, 6, 0x655b59c3); - OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP (FI, C, D, A, B, 10, 15, 0xffeff47d); - OP (FI, B, C, D, A, 1, 21, 0x85845dd1); - OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP (FI, C, D, A, B, 6, 15, 0xa3014314); - OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP (FI, A, B, C, D, 4, 6, 0xf7537e82); - OP (FI, D, A, B, C, 11, 10, 0xbd3af235); - OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP (FI, B, C, D, A, 9, 21, 0xeb86d391); - - /* Put checksum in context given as argument. */ - ctx->A += A; - ctx->B += B; - ctx->C += C; - ctx->D += D; -} - - - -/* The routine updates the message-digest context to - * account for the presence of each of the characters inBuf[0..inLen-1] - * in the message whose digest is being computed. - */ -static void -md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen) -{ - if( hd->count == 64 ) { /* flush the buffer */ - transform( hd, hd->buf ); - burn_stack (80+6*sizeof(void*)); - hd->count = 0; - hd->nblocks++; - } - if( !inbuf ) - return; - if( hd->count ) { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; - md5_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - - while( inlen >= 64 ) { - transform( hd, inbuf ); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - burn_stack (80+6*sizeof(void*)); - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; -} - - - -/* The routine final terminates the message-digest computation and - * ends with the desired message digest in mdContext->digest[0...15]. - * The handle is prepared for a new MD5 cycle. - * Returns 16 bytes representing the digest. - */ - -static void -md5_final( MD5_CONTEXT *hd ) -{ - u32 t, msb, lsb; - byte *p; - - md5_write(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if( (lsb += hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if( hd->count < 56 ) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] = 0; - md5_write(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = lsb ; - hd->buf[57] = lsb >> 8; - hd->buf[58] = lsb >> 16; - hd->buf[59] = lsb >> 24; - hd->buf[60] = msb ; - hd->buf[61] = msb >> 8; - hd->buf[62] = msb >> 16; - hd->buf[63] = msb >> 24; - transform( hd, hd->buf ); - burn_stack (80+6*sizeof(void*)); - - p = hd->buf; - #ifdef BIG_ENDIAN_HOST - #define X(a) do { *p++ = hd-> a ; *p++ = hd-> a >> 8; \ - *p++ = hd-> a >> 16; *p++ = hd-> a >> 24; } while(0) - #else /* little endian */ - #define X(a) do { *(u32*)p = hd-> a ; p += 4; } while(0) - #endif - X(A); - X(B); - X(C); - X(D); - #undef X - -} - -static byte * -md5_read( MD5_CONTEXT *hd ) -{ - return hd->buf; -} - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -const char * -md5_get_info( int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ) -{ - static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ - { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, - 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; - - if( algo != 1 ) - return NULL; - - *contextsize = sizeof(MD5_CONTEXT); - *r_asnoid = asn; - *r_asnlen = DIM(asn); - *r_mdlen = 16; - *(void (**)(MD5_CONTEXT *))r_init = md5_init; - *(void (**)(MD5_CONTEXT *, byte*, size_t))r_write = md5_write; - *(void (**)(MD5_CONTEXT *))r_final = md5_final; - *(byte *(**)(MD5_CONTEXT *))r_read = md5_read; - - return "MD5"; -} - diff --git a/cipher/primegen.c b/cipher/primegen.c deleted file mode 100644 index 1f3095751..000000000 --- a/cipher/primegen.c +++ /dev/null @@ -1,583 +0,0 @@ -/* primegen.c - prime number generator - * 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 - * - * *********************************************************************** - * The algorithm used to generate practically save primes is due to - * Lim and Lee as described in the CRYPTO '97 proceedings (ISBN3540633847) - * page 260. - */ - -#include -#include -#include -#include -#include -#include "util.h" -#include "mpi.h" -#include "cipher.h" - -static int no_of_small_prime_numbers; -static MPI gen_prime( unsigned nbits, int mode, int randomlevel ); -static int check_prime( MPI prime, MPI val_2 ); -static int is_prime( MPI n, int steps, int *count ); -static void m_out_of_n( char *array, int m, int n ); - -static void (*progress_cb) ( void *, int ); -static void *progress_cb_data; - -void -register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) -{ - progress_cb = cb; - progress_cb_data = cb_data; -} - - -static void -progress( int c ) -{ - if ( progress_cb ) - progress_cb ( progress_cb_data, c ); - else - fputc( c, stderr ); -} - - -/**************** - * Generate a prime number (stored in secure memory) - */ -MPI -generate_secret_prime( unsigned nbits ) -{ - MPI prime; - - prime = gen_prime( nbits, 1, 2 ); - progress('\n'); - return prime; -} - -MPI -generate_public_prime( unsigned nbits ) -{ - MPI prime; - - prime = gen_prime( nbits, 0, 2 ); - progress('\n'); - return prime; -} - - -/**************** - * We do not need to use the strongest RNG because we gain no extra - * security from it - The prime number is public and we could also - * offer the factors for those who are willing to check that it is - * indeed a strong prime. - * - * mode 0: Standard - * 1: Make sure that at least one factor is of size qbits. - */ -MPI -generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **ret_factors ) -{ - int n; /* number of factors */ - int m; /* number of primes in pool */ - unsigned fbits; /* length of prime factors */ - MPI *factors; /* current factors */ - MPI *pool; /* pool of primes */ - MPI q; /* first prime factor (variable)*/ - MPI prime; /* prime test value */ - MPI q_factor; /* used for mode 1 */ - byte *perms = NULL; - int i, j; - int count1, count2; - unsigned nprime; - unsigned req_qbits = qbits; /* the requested q bits size */ - MPI val_2 = mpi_alloc_set_ui( 2 ); - - /* find number of needed prime factors */ - for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) - ; - n--; - if( !n || (mode==1 && n < 2) ) - log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits ); - if( mode == 1 ) { - n--; - fbits = (pbits - 2*req_qbits -1) / n; - qbits = pbits - req_qbits - n*fbits; - } - else { - fbits = (pbits - req_qbits -1) / n; - qbits = pbits - n*fbits; - } - if( DBG_CIPHER ) - log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", - pbits, req_qbits, qbits, fbits, n ); - prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); - q = gen_prime( qbits, 0, 0 ); - q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL; - - /* allocate an array to hold the factors + 2 for later usage */ - factors = m_alloc_clear( (n+2) * sizeof *factors ); - - /* make a pool of 3n+5 primes (this is an arbitrary value) */ - m = n*3+5; - if( mode == 1 ) - m += 5; /* need some more for DSA */ - if( m < 25 ) - m = 25; - pool = m_alloc_clear( m * sizeof *pool ); - - /* permutate over the pool of primes */ - count1=count2=0; - do { - next_try: - if( !perms ) { - /* allocate new primes */ - for(i=0; i < m; i++ ) { - mpi_free(pool[i]); - pool[i] = NULL; - } - /* init m_out_of_n() */ - perms = m_alloc_clear( m ); - for(i=0; i < n; i++ ) { - perms[i] = 1; - pool[i] = gen_prime( fbits, 0, 0 ); - factors[i] = pool[i]; - } - } - else { - m_out_of_n( perms, n, m ); - for(i=j=0; i < m && j < n ; i++ ) - if( perms[i] ) { - if( !pool[i] ) - pool[i] = gen_prime( fbits, 0, 0 ); - factors[j++] = pool[i]; - } - if( i == n ) { - m_free(perms); perms = NULL; - progress('!'); - goto next_try; /* allocate new primes */ - } - } - - mpi_set( prime, q ); - mpi_mul_ui( prime, prime, 2 ); - if( mode == 1 ) - mpi_mul( prime, prime, q_factor ); - for(i=0; i < n; i++ ) - mpi_mul( prime, prime, factors[i] ); - mpi_add_ui( prime, prime, 1 ); - nprime = mpi_get_nbits(prime); - if( nprime < pbits ) { - if( ++count1 > 20 ) { - count1 = 0; - qbits++; - progress('>'); - mpi_free (q); - q = gen_prime( qbits, 0, 0 ); - goto next_try; - } - } - else - count1 = 0; - if( nprime > pbits ) { - if( ++count2 > 20 ) { - count2 = 0; - qbits--; - progress('<'); - mpi_free (q); - q = gen_prime( qbits, 0, 0 ); - goto next_try; - } - } - else - count2 = 0; - } while( !(nprime == pbits && check_prime( prime, val_2 )) ); - - if( DBG_CIPHER ) { - progress('\n'); - log_mpidump( "prime : ", prime ); - log_mpidump( "factor q: ", q ); - if( mode == 1 ) - log_mpidump( "factor q0: ", q_factor ); - for(i=0; i < n; i++ ) - log_mpidump( "factor pi: ", factors[i] ); - log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) ); - if( mode == 1 ) - fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) ); - for(i=0; i < n; i++ ) - fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); - progress('\n'); - } - - if( ret_factors ) { /* caller wants the factors */ - *ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors); - i = 0; - if( mode == 1 ) { - (*ret_factors)[i++] = mpi_copy( q_factor ); - for(; i <= n; i++ ) - (*ret_factors)[i] = mpi_copy( factors[i-1] ); - } - else { - for(; i < n; i++ ) - (*ret_factors)[i] = mpi_copy( factors[i] ); - } - } - - if( g ) { /* create a generator (start with 3)*/ - MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) ); - MPI b = mpi_alloc( mpi_get_nlimbs(prime) ); - MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) ); - - if( mode == 1 ) - BUG(); /* not yet implemented */ - factors[n] = q; - factors[n+1] = mpi_alloc_set_ui(2); - mpi_sub_ui( pmin1, prime, 1 ); - mpi_set_ui(g,2); - do { - mpi_add_ui(g, g, 1); - if( DBG_CIPHER ) { - log_debug("checking g: "); - mpi_print( stderr, g, 1 ); - } - else - progress('^'); - for(i=0; i < n+2; i++ ) { - /*fputc('~', stderr);*/ - mpi_fdiv_q(tmp, pmin1, factors[i] ); - /* (no mpi_pow(), but it is okay to use this with mod prime) */ - mpi_powm(b, g, tmp, prime ); - if( !mpi_cmp_ui(b, 1) ) - break; - } - if( DBG_CIPHER ) - progress('\n'); - } while( i < n+2 ); - mpi_free(factors[n+1]); - mpi_free(tmp); - mpi_free(b); - mpi_free(pmin1); - } - if( !DBG_CIPHER ) - progress('\n'); - - m_free( factors ); /* (factors are shallow copies) */ - for(i=0; i < m; i++ ) - mpi_free( pool[i] ); - m_free( pool ); - m_free(perms); - mpi_free(val_2); - mpi_free(q); - return prime; -} - - - -static MPI -gen_prime( unsigned nbits, int secret, int randomlevel ) -{ - unsigned nlimbs; - MPI prime, ptest, pminus1, val_2, val_3, result; - int i; - unsigned x, step; - int count1, count2; - int *mods; - - if( 0 && DBG_CIPHER ) - log_debug("generate a prime of %u bits ", nbits ); - - if( !no_of_small_prime_numbers ) { - for(i=0; small_prime_numbers[i]; i++ ) - no_of_small_prime_numbers++; - } - mods = m_alloc( no_of_small_prime_numbers * sizeof *mods ); - /* make nbits fit into MPI implementation */ - nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; - val_2 = mpi_alloc_set_ui( 2 ); - val_3 = mpi_alloc_set_ui( 3); - prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs ); - result = mpi_alloc_like( prime ); - pminus1= mpi_alloc_like( prime ); - ptest = mpi_alloc_like( prime ); - count1 = count2 = 0; - for(;;) { /* try forvever */ - int dotcount=0; - - /* generate a random number */ - { char *p = get_random_bits( nbits, randomlevel, secret ); - mpi_set_buffer( prime, p, (nbits+7)/8, 0 ); - m_free(p); - } - - /* Set high order bit to 1, set low order bit to 0. - If we are generating a secret prime we are most probably - doing that for RSA, to make sure that the modulus does have - the requested keysize we set the 2 high order bits */ - mpi_set_highbit( prime, nbits-1 ); - if (secret) - mpi_set_bit (prime, nbits-2); - mpi_set_bit( prime, 0 ); - - /* calculate all remainders */ - for(i=0; (x = small_prime_numbers[i]); i++ ) - mods[i] = mpi_fdiv_r_ui(NULL, prime, x); - - /* now try some primes starting with prime */ - for(step=0; step < 20000; step += 2 ) { - /* check against all the small primes we have in mods */ - count1++; - for(i=0; (x = small_prime_numbers[i]); i++ ) { - while( mods[i] + step >= x ) - mods[i] -= x; - if( !(mods[i] + step) ) - break; - } - if( x ) - continue; /* found a multiple of an already known prime */ - - mpi_add_ui( ptest, prime, step ); - - /* do a faster Fermat test */ - count2++; - mpi_sub_ui( pminus1, ptest, 1); - mpi_powm( result, val_2, pminus1, ptest ); - if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */ - /* perform stronger tests */ - if( is_prime(ptest, 5, &count2 ) ) { - if( !mpi_test_bit( ptest, nbits-1 ) ) { - progress('\n'); - log_debug("overflow in prime generation\n"); - break; /* step loop, continue with a new prime */ - } - - mpi_free(val_2); - mpi_free(val_3); - mpi_free(result); - mpi_free(pminus1); - mpi_free(prime); - m_free(mods); - return ptest; - } - } - if( ++dotcount == 10 ) { - progress('.'); - dotcount = 0; - } - } - progress(':'); /* restart with a new random value */ - } -} - -/**************** - * Returns: true if this may be a prime - */ -static int -check_prime( MPI prime, MPI val_2 ) -{ - int i; - unsigned x; - int count=0; - - /* check against small primes */ - for(i=0; (x = small_prime_numbers[i]); i++ ) { - if( mpi_divisible_ui( prime, x ) ) - return 0; - } - - /* a quick fermat test */ - { - MPI result = mpi_alloc_like( prime ); - MPI pminus1 = mpi_alloc_like( prime ); - mpi_sub_ui( pminus1, prime, 1); - mpi_powm( result, val_2, pminus1, prime ); - mpi_free( pminus1 ); - if( mpi_cmp_ui( result, 1 ) ) { /* if composite */ - mpi_free( result ); - progress('.'); - return 0; - } - mpi_free( result ); - } - - /* perform stronger tests */ - if( is_prime(prime, 5, &count ) ) - return 1; /* is probably a prime */ - progress('.'); - return 0; -} - - -/**************** - * Return true if n is probably a prime - */ -static int -is_prime( MPI n, int steps, int *count ) -{ - MPI x = mpi_alloc( mpi_get_nlimbs( n ) ); - MPI y = mpi_alloc( mpi_get_nlimbs( n ) ); - MPI z = mpi_alloc( mpi_get_nlimbs( n ) ); - MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) ); - MPI a2 = mpi_alloc_set_ui( 2 ); - MPI q; - unsigned i, j, k; - int rc = 0; - unsigned nbits = mpi_get_nbits( n ); - - mpi_sub_ui( nminus1, n, 1 ); - - /* find q and k, so that n = 1 + 2^k * q */ - q = mpi_copy( nminus1 ); - k = mpi_trailing_zeros( q ); - mpi_tdiv_q_2exp(q, q, k); - - for(i=0 ; i < steps; i++ ) { - ++*count; - if( !i ) { - mpi_set_ui( x, 2 ); - } - else { - /*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/ - { char *p = get_random_bits( nbits, 0, 0 ); - mpi_set_buffer( x, p, (nbits+7)/8, 0 ); - m_free(p); - } - /* make sure that the number is smaller than the prime - * and keep the randomness of the high bit */ - if( mpi_test_bit( x, nbits-2 ) ) { - mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */ - } - else { - mpi_set_highbit( x, nbits-2 ); - mpi_clear_bit( x, nbits-2 ); - } - assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 ); - } - mpi_powm( y, x, q, n); - if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) { - for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) { - mpi_powm(y, y, a2, n); - if( !mpi_cmp_ui( y, 1 ) ) - goto leave; /* not a prime */ - } - if( mpi_cmp( y, nminus1 ) ) - goto leave; /* not a prime */ - } - progress('+'); - } - rc = 1; /* may be a prime */ - - leave: - mpi_free( x ); - mpi_free( y ); - mpi_free( z ); - mpi_free( nminus1 ); - mpi_free( q ); - - return rc; -} - - -static void -m_out_of_n( char *array, int m, int n ) -{ - int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0; - - if( !m || m >= n ) - return; - - if( m == 1 ) { /* special case */ - for(i=0; i < n; i++ ) - if( array[i] ) { - array[i++] = 0; - if( i >= n ) - i = 0; - array[i] = 1; - return; - } - BUG(); - } - - for(j=1; j < n; j++ ) { - if( array[n-1] == array[n-j-1] ) - continue; - j1 = j; - break; - } - - if( m & 1 ) { /* m is odd */ - if( array[n-1] ) { - if( j1 & 1 ) { - k1 = n - j1; - k2 = k1+2; - if( k2 > n ) - k2 = n; - goto leave; - } - goto scan; - } - k2 = n - j1 - 1; - if( k2 == 0 ) { - k1 = i; - k2 = n - j1; - } - else if( array[k2] && array[k2-1] ) - k1 = n; - else - k1 = k2 + 1; - } - else { /* m is even */ - if( !array[n-1] ) { - k1 = n - j1; - k2 = k1 + 1; - goto leave; - } - - if( !(j1 & 1) ) { - k1 = n - j1; - k2 = k1+2; - if( k2 > n ) - k2 = n; - goto leave; - } - scan: - jp = n - j1 - 1; - for(i=1; i <= jp; i++ ) { - i1 = jp + 2 - i; - if( array[i1-1] ) { - if( array[i1-2] ) { - k1 = i1 - 1; - k2 = n - j1; - } - else { - k1 = i1 - 1; - k2 = n + 1 - j1; - } - goto leave; - } - } - k1 = 1; - k2 = n + 1 - m; - } - leave: - array[k1-1] = !array[k1-1]; - array[k2-1] = !array[k2-1]; -} - diff --git a/cipher/pubkey.c b/cipher/pubkey.c deleted file mode 100644 index 853c518be..000000000 --- a/cipher/pubkey.c +++ /dev/null @@ -1,559 +0,0 @@ -/* pubkey.c - pubkey dispatcher - * 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 -#include -#include -#include -#include -#include -#include "util.h" -#include "errors.h" -#include "mpi.h" -#include "cipher.h" -#include "elgamal.h" -#include "dsa.h" -#include "rsa.h" - -#define TABLE_SIZE 10 - -struct pubkey_table_s { - const char *name; - int algo; - int npkey; - int nskey; - int nenc; - int nsig; - int use; - int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); - int (*check_secret_key)( int algo, MPI *skey ); - int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ); - int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey ); - int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey ); - int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ); - unsigned (*get_nbits)( int algo, MPI *pkey ); -}; - -static struct pubkey_table_s pubkey_table[TABLE_SIZE]; -static int disabled_algos[TABLE_SIZE]; - - -#if 0 -static int -dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) -{ log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } - -static int -dummy_check_secret_key( int algo, MPI *skey ) -{ log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } -#endif - -static int -dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) -{ log_bug("no encrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } - -static int -dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) -{ log_bug("no decrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } - -static int -dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey ) -{ log_bug("no sign() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } - -static int -dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ) -{ log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; } - -#if 0 -static unsigned -dummy_get_nbits( int algo, MPI *pkey ) -{ log_bug("no get_nbits() for %d\n", algo ); return 0; } -#endif - -/**************** - * Put the static entries into the table. - * This is out constructor function which fill the table - * of algorithms with the one we have statically linked. - */ -static void -setup_pubkey_table(void) -{ - int i; - - i = 0; - pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL; - pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, - &pubkey_table[i].npkey, - &pubkey_table[i].nskey, - &pubkey_table[i].nenc, - &pubkey_table[i].nsig, - &pubkey_table[i].use ); - pubkey_table[i].generate = elg_generate; - pubkey_table[i].check_secret_key = elg_check_secret_key; - pubkey_table[i].encrypt = elg_encrypt; - pubkey_table[i].decrypt = elg_decrypt; - pubkey_table[i].sign = elg_sign; - pubkey_table[i].verify = elg_verify; - pubkey_table[i].get_nbits = elg_get_nbits; - if( !pubkey_table[i].name ) - BUG(); - i++; - pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E; - pubkey_table[i].name = elg_get_info( pubkey_table[i].algo, - &pubkey_table[i].npkey, - &pubkey_table[i].nskey, - &pubkey_table[i].nenc, - &pubkey_table[i].nsig, - &pubkey_table[i].use ); - pubkey_table[i].generate = elg_generate; - pubkey_table[i].check_secret_key = elg_check_secret_key; - pubkey_table[i].encrypt = elg_encrypt; - pubkey_table[i].decrypt = elg_decrypt; - pubkey_table[i].sign = elg_sign; - pubkey_table[i].verify = elg_verify; - pubkey_table[i].get_nbits = elg_get_nbits; - if( !pubkey_table[i].name ) - BUG(); - i++; - pubkey_table[i].algo = PUBKEY_ALGO_DSA; - pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo, - &pubkey_table[i].npkey, - &pubkey_table[i].nskey, - &pubkey_table[i].nenc, - &pubkey_table[i].nsig, - &pubkey_table[i].use ); - pubkey_table[i].generate = dsa_generate; - pubkey_table[i].check_secret_key = dsa_check_secret_key; - pubkey_table[i].encrypt = dummy_encrypt; - pubkey_table[i].decrypt = dummy_decrypt; - pubkey_table[i].sign = dsa_sign; - pubkey_table[i].verify = dsa_verify; - pubkey_table[i].get_nbits = dsa_get_nbits; - if( !pubkey_table[i].name ) - BUG(); - i++; - - pubkey_table[i].algo = PUBKEY_ALGO_RSA; - pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo, - &pubkey_table[i].npkey, - &pubkey_table[i].nskey, - &pubkey_table[i].nenc, - &pubkey_table[i].nsig, - &pubkey_table[i].use ); - pubkey_table[i].generate = rsa_generate; - pubkey_table[i].check_secret_key = rsa_check_secret_key; - pubkey_table[i].encrypt = rsa_encrypt; - pubkey_table[i].decrypt = rsa_decrypt; - pubkey_table[i].sign = rsa_sign; - pubkey_table[i].verify = rsa_verify; - pubkey_table[i].get_nbits = rsa_get_nbits; - if( !pubkey_table[i].name ) - BUG(); - i++; - pubkey_table[i].algo = PUBKEY_ALGO_RSA_E; - pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo, - &pubkey_table[i].npkey, - &pubkey_table[i].nskey, - &pubkey_table[i].nenc, - &pubkey_table[i].nsig, - &pubkey_table[i].use ); - pubkey_table[i].generate = rsa_generate; - pubkey_table[i].check_secret_key = rsa_check_secret_key; - pubkey_table[i].encrypt = rsa_encrypt; - pubkey_table[i].decrypt = rsa_decrypt; - pubkey_table[i].sign = dummy_sign; - pubkey_table[i].verify = dummy_verify; - pubkey_table[i].get_nbits = rsa_get_nbits; - if( !pubkey_table[i].name ) - BUG(); - i++; - pubkey_table[i].algo = PUBKEY_ALGO_RSA_S; - pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo, - &pubkey_table[i].npkey, - &pubkey_table[i].nskey, - &pubkey_table[i].nenc, - &pubkey_table[i].nsig, - &pubkey_table[i].use ); - pubkey_table[i].generate = rsa_generate; - pubkey_table[i].check_secret_key = rsa_check_secret_key; - pubkey_table[i].encrypt = dummy_encrypt; - pubkey_table[i].decrypt = dummy_decrypt; - pubkey_table[i].sign = rsa_sign; - pubkey_table[i].verify = rsa_verify; - pubkey_table[i].get_nbits = rsa_get_nbits; - if( !pubkey_table[i].name ) - BUG(); - i++; - - for( ; i < TABLE_SIZE; i++ ) - pubkey_table[i].name = NULL; -} - - -/**************** - * Try to load all modules and return true if new modules are available - */ -static int -load_pubkey_modules(void) -{ - static int initialized = 0; - - if( !initialized ) { - setup_pubkey_table(); - initialized = 1; - return 1; - } - return 0; -} - - -/**************** - * Map a string to the pubkey algo - */ -int -string_to_pubkey_algo( const char *string ) -{ - int i; - const char *s; - - do { - for(i=0; (s=pubkey_table[i].name); i++ ) - if( !ascii_strcasecmp( s, string ) ) - return pubkey_table[i].algo; - } while( load_pubkey_modules() ); - return 0; -} - - -/**************** - * Map a pubkey algo to a string - */ -const char * -pubkey_algo_to_string( int algo ) -{ - int i; - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return pubkey_table[i].name; - } while( load_pubkey_modules() ); - return NULL; -} - - -void -disable_pubkey_algo( int algo ) -{ - int i; - - for(i=0; i < DIM(disabled_algos); i++ ) { - if( !disabled_algos[i] || disabled_algos[i] == algo ) { - disabled_algos[i] = algo; - return; - } - } - log_fatal("can't disable pubkey algo %d: table full\n", algo ); -} - - -int -check_pubkey_algo( int algo ) -{ - return check_pubkey_algo2( algo, 0 ); -} - -/**************** - * a use of 0 means: don't care - */ -int -check_pubkey_algo2( int algo, unsigned use ) -{ - int i; - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) { - if( (use & PUBKEY_USAGE_SIG) - && !(pubkey_table[i].use & PUBKEY_USAGE_SIG) ) - return G10ERR_WR_PUBKEY_ALGO; - if( (use & PUBKEY_USAGE_ENC) - && !(pubkey_table[i].use & PUBKEY_USAGE_ENC) ) - return G10ERR_WR_PUBKEY_ALGO; - - for(i=0; i < DIM(disabled_algos); i++ ) { - if( disabled_algos[i] == algo ) - return G10ERR_PUBKEY_ALGO; - } - return 0; /* okay */ - } - } while( load_pubkey_modules() ); - return G10ERR_PUBKEY_ALGO; -} - - - - -/**************** - * Return the number of public key material numbers - */ -int -pubkey_get_npkey( int algo ) -{ - int i; - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return pubkey_table[i].npkey; - } while( load_pubkey_modules() ); - return 0; -} - -/**************** - * Return the number of secret key material numbers - */ -int -pubkey_get_nskey( int algo ) -{ - int i; - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return pubkey_table[i].nskey; - } while( load_pubkey_modules() ); - if( is_RSA(algo) ) /* special hack, so that we are able to */ - return 6; /* see the RSA keyids */ - return 0; -} - -/**************** - * Return the number of signature material numbers - */ -int -pubkey_get_nsig( int algo ) -{ - int i; - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return pubkey_table[i].nsig; - } while( load_pubkey_modules() ); - if( is_RSA(algo) ) /* special hack, so that we are able to */ - return 1; /* see the RSA keyids */ - return 0; -} - -/**************** - * Return the number of encryption material numbers - */ -int -pubkey_get_nenc( int algo ) -{ - int i; - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return pubkey_table[i].nenc; - } while( load_pubkey_modules() ); - if( is_RSA(algo) ) /* special hack, so that we are able to */ - return 1; /* see the RSA keyids */ - return 0; -} - -/**************** - * Get the number of nbits from the public key - */ -unsigned -pubkey_nbits( int algo, MPI *pkey ) -{ - int i; - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return (*pubkey_table[i].get_nbits)( algo, pkey ); - } while( load_pubkey_modules() ); - if( is_RSA(algo) ) /* we always wanna see the length of a key :-) */ - return mpi_get_nbits( pkey[0] ); - return 0; -} - - -int -pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) -{ - int i; - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return (*pubkey_table[i].generate)( algo, nbits, - skey, retfactors ); - } while( load_pubkey_modules() ); - return G10ERR_PUBKEY_ALGO; -} - - -int -pubkey_check_secret_key( int algo, MPI *skey ) -{ - int i; - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) - return (*pubkey_table[i].check_secret_key)( algo, skey ); - } while( load_pubkey_modules() ); - return G10ERR_PUBKEY_ALGO; -} - - -/**************** - * This is the interface to the public key encryption. - * Encrypt DATA with PKEY and put it into RESARR which - * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the - * algorithm allows this - check with pubkey_get_nenc() ) - */ -int -pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) -{ - int i, rc; - - if( DBG_CIPHER ) { - log_debug("pubkey_encrypt: algo=%d\n", algo ); - for(i=0; i < pubkey_get_npkey(algo); i++ ) - log_mpidump(" pkey:", pkey[i] ); - log_mpidump(" data:", data ); - } - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey ); - goto ready; - } - } while( load_pubkey_modules() ); - rc = G10ERR_PUBKEY_ALGO; - ready: - if( !rc && DBG_CIPHER ) { - for(i=0; i < pubkey_get_nenc(algo); i++ ) - log_mpidump(" encr:", resarr[i] ); - } - return rc; -} - - - -/**************** - * This is the interface to the public key decryption. - * ALGO gives the algorithm to use and this implicitly determines - * the size of the arrays. - * result is a pointer to a mpi variable which will receive a - * newly allocated mpi or NULL in case of an error. - */ -int -pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) -{ - int i, rc; - - *result = NULL; /* so the caller can always do an mpi_free */ - if( DBG_CIPHER ) { - log_debug("pubkey_decrypt: algo=%d\n", algo ); - for(i=0; i < pubkey_get_nskey(algo); i++ ) - log_mpidump(" skey:", skey[i] ); - for(i=0; i < pubkey_get_nenc(algo); i++ ) - log_mpidump(" data:", data[i] ); - } - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].decrypt)( algo, result, data, skey ); - goto ready; - } - } while( load_pubkey_modules() ); - rc = G10ERR_PUBKEY_ALGO; - ready: - if( !rc && DBG_CIPHER ) { - log_mpidump(" plain:", *result ); - } - return rc; -} - - -/**************** - * This is the interface to the public key signing. - * Sign data with skey and put the result into resarr which - * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the - * algorithm allows this - check with pubkey_get_nsig() ) - */ -int -pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey ) -{ - int i, rc; - - if( DBG_CIPHER ) { - log_debug("pubkey_sign: algo=%d\n", algo ); - for(i=0; i < pubkey_get_nskey(algo); i++ ) - log_mpidump(" skey:", skey[i] ); - log_mpidump(" data:", data ); - } - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].sign)( algo, resarr, data, skey ); - goto ready; - } - } while( load_pubkey_modules() ); - rc = G10ERR_PUBKEY_ALGO; - ready: - if( !rc && DBG_CIPHER ) { - for(i=0; i < pubkey_get_nsig(algo); i++ ) - log_mpidump(" sig:", resarr[i] ); - } - return rc; -} - -/**************** - * Verify a public key signature. - * Return 0 if the signature is good - */ -int -pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ) -{ - int i, rc; - - do { - for(i=0; pubkey_table[i].name; i++ ) - if( pubkey_table[i].algo == algo ) { - rc = (*pubkey_table[i].verify)( algo, hash, data, pkey, - cmp, opaquev ); - goto ready; - } - } while( load_pubkey_modules() ); - rc = G10ERR_PUBKEY_ALGO; - ready: - return rc; -} - diff --git a/cipher/rand-internal.h b/cipher/rand-internal.h deleted file mode 100644 index ab01bc6db..000000000 --- a/cipher/rand-internal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* rand-internal.h - header to glue the random 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 - */ -#ifndef G10_RAND_INTERNAL_H -#define G10_RAND_INTERNAL_H - -int rndunix_gather_random (void (*add)(const void*, size_t, int), - int requester, size_t length, int level); -int rndlinux_gather_random (void (*add)(const void*, size_t, int), - int requester, size_t length, int level); -int rndegd_connect_socket (int nofail); -int rndegd_gather_random (void (*add)(const void*, size_t, int), - int requester, size_t length, int level ); -int rndw32_gather_random (void (*add)(const void*, size_t, int), - int requester, size_t length, int level); -int rndw32_gather_random_fast (void (*add)(const void*, size_t, int), - int requester ); -int rndriscos_gather_random (void (*add)(const void*, size_t, int), - int requester, size_t length, int level); - - -#endif /*G10_RAND_INTERNAL_H*/ diff --git a/cipher/random.c b/cipher/random.c deleted file mode 100644 index c2dea9c28..000000000 --- a/cipher/random.c +++ /dev/null @@ -1,749 +0,0 @@ -/* random.c - random number generator - * 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 - */ - - -/**************** - * This random number generator is modelled after the one described - * in Peter Gutmann's Paper: "Software Generation of Practically - * Strong Random Numbers". - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_GETHRTIME - #include -#endif -#ifdef HAVE_GETTIMEOFDAY - #include -#endif -#ifdef HAVE_GETRUSAGE - #include -#endif -#ifdef __MINGW32__ - #include -#endif -#include "util.h" -#include "rmd.h" -#include "ttyio.h" -#include "i18n.h" -#include "random.h" -#include "rand-internal.h" -#include "algorithms.h" - -#ifndef RAND_MAX /* for SunOS */ - #define RAND_MAX 32767 -#endif - - -#if SIZEOF_UNSIGNED_LONG == 8 - #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 -#elif SIZEOF_UNSIGNED_LONG == 4 - #define ADD_VALUE 0xa5a5a5a5 -#else - #error weird size for an unsigned long -#endif - -#define BLOCKLEN 64 /* hash this amount of bytes */ -#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ -/* poolblocks is the number of digests which make up the pool - * and poolsize must be a multiple of the digest length - * to make the AND operations faster, the size should also be - * a multiple of ulong - */ -#define POOLBLOCKS 30 -#define POOLSIZE (POOLBLOCKS*DIGESTLEN) -#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) - #error Please make sure that poolsize is a multiple of ulong -#endif -#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) - - -static int is_initialized; -#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) -static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ -static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ -static size_t pool_readpos; -static size_t pool_writepos; -static int pool_filled; -static int pool_balance; -static int just_mixed; -static int did_initial_extra_seeding; -static char *seed_file_name; -static int allow_seed_file_update; - -static int secure_alloc; -static int quick_test; -static int faked_rng; - - -static void read_pool( byte *buffer, size_t length, int level ); -static void add_randomness( const void *buffer, size_t length, int source ); -static void random_poll(void); -static void read_random_source( int requester, size_t length, int level); -static int gather_faked( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ); - -static struct { - ulong mixrnd; - ulong mixkey; - ulong slowpolls; - ulong fastpolls; - ulong getbytes1; - ulong ngetbytes1; - ulong getbytes2; - ulong ngetbytes2; - ulong addbytes; - ulong naddbytes; -} rndstats; - - -static int (* -getfnc_gather_random (void))(void (*)(const void*, size_t, int), int, - size_t, int) -{ -#ifdef USE_ALL_RANDOM_MODULES - static int (*fnc)(void (*)(const void*, size_t, int), int, size_t, int); - - if (fnc) - return fnc; -# ifdef USE_RNDLINUX - if ( !access (NAME_OF_DEV_RANDOM, R_OK) - && !access (NAME_OF_DEV_RANDOM, R_OK)) - { - fnc = rndlinux_gather_random; - return fnc; - } -# endif -# ifdef USE_RNDEGD - if ( rndegd_connect_socket (1) != -1 ) - { - fnc = rndegd_gather_random; - return fnc; - } -# endif -# ifdef USE_RNDUNIX - fnc = rndunix_gather_random; - return fnc; -# endif - - log_fatal (_("no entropy gathering module detected\n")); - -#else -# ifdef USE_RNDLINUX - return rndlinux_gather_random; -# endif -# ifdef USE_RNDUNIX - return rndunix_gather_random; -# endif -# ifdef USE_RNDEGD - return rndegd_gather_random; -# endif -# ifdef USE_RNDW32 - return rndw32_gather_random; -# endif -# ifdef USE_RNDRISCOS - return rndriscos_gather_random; -# endif -#endif - return NULL; -} - -static void (* -getfnc_fast_random_poll (void))( void (*)(const void*, size_t, int), int) -{ -#ifdef USE_RNDW32 - return rndw32_gather_random_fast; -#endif - return NULL; -} - - - -static void -initialize(void) -{ - /* The data buffer is allocated somewhat larger, so that - * we can use this extra space (which is allocated in secure memory) - * as a temporary hash buffer */ - rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) - : m_alloc_clear(POOLSIZE+BLOCKLEN); - keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) - : m_alloc_clear(POOLSIZE+BLOCKLEN); - is_initialized = 1; -} - -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - -void -random_dump_stats() -{ - fprintf(stderr, - "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" - " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", - POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, - rndstats.naddbytes, rndstats.addbytes, - rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, - rndstats.ngetbytes2, rndstats.getbytes2 ); -} - -void -secure_random_alloc() -{ - secure_alloc = 1; -} - - -int -quick_random_gen( int onoff ) -{ - int last; - - read_random_source(0,0,0); /* init */ - last = quick_test; - if( onoff != -1 ) - quick_test = onoff; - return faked_rng? 1 : last; -} - - -/**************** - * Fill the buffer with LENGTH bytes of cryptographically strong - * random bytes. level 0 is not very strong, 1 is strong enough - * for most usage, 2 is good for key generation stuff but may be very slow. - */ -void -randomize_buffer( byte *buffer, size_t length, int level ) -{ - char *p = get_random_bits( length*8, level, 1 ); - memcpy( buffer, p, length ); - m_free(p); -} - - -int -random_is_faked() -{ - if( !is_initialized ) - initialize(); - return faked_rng || quick_test; -} - -/**************** - * Return a pointer to a randomized buffer of level 0 and LENGTH bits - * caller must free the buffer. - * Note: The returned value is rounded up to bytes. - */ -byte * -get_random_bits( size_t nbits, int level, int secure ) -{ - byte *buf, *p; - size_t nbytes = (nbits+7)/8; - - if( quick_test && level > 1 ) - level = 1; - MASK_LEVEL(level); - if( level == 1 ) { - rndstats.getbytes1 += nbytes; - rndstats.ngetbytes1++; - } - else if( level >= 2 ) { - rndstats.getbytes2 += nbytes; - rndstats.ngetbytes2++; - } - - buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes ); - for( p = buf; nbytes > 0; ) { - size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; - read_pool( p, n, level ); - nbytes -= n; - p += n; - } - return buf; -} - - -/**************** - * Mix the pool - */ -static void -mix_pool(byte *pool) -{ - char *hashbuf = pool + POOLSIZE; - char *p, *pend; - int i, n; - RMD160_CONTEXT md; - - rmd160_init( &md ); - #if DIGESTLEN != 20 - #error must have a digest length of 20 for ripe-md-160 - #endif - /* loop over the pool */ - pend = pool + POOLSIZE; - memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); - memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); - rmd160_mixblock( &md, hashbuf); - memcpy(pool, hashbuf, 20 ); - - p = pool; - for( n=1; n < POOLBLOCKS; n++ ) { - memcpy(hashbuf, p, DIGESTLEN ); - - p += DIGESTLEN; - if( p+DIGESTLEN+BLOCKLEN < pend ) - memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); - else { - char *pp = p+DIGESTLEN; - for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { - if( pp >= pend ) - pp = pool; - hashbuf[i] = *pp++; - } - } - - rmd160_mixblock( &md, hashbuf); - memcpy(p, hashbuf, 20 ); - } - burn_stack (384); /* for the rmd160_mixblock() */ -} - - -void -set_random_seed_file( const char *name ) -{ - if( seed_file_name ) - BUG(); - seed_file_name = m_strdup( name ); -} - -/**************** - * Read in a seed form the random_seed file - * and return true if this was successful - */ -static int -read_seed_file(void) -{ - int fd; - struct stat sb; - unsigned char buffer[POOLSIZE]; - int n; - - if( !seed_file_name ) - return 0; - - #ifdef HAVE_DOSISH_SYSTEM - fd = open( seed_file_name, O_RDONLY | O_BINARY ); - #else - fd = open( seed_file_name, O_RDONLY ); - #endif - if( fd == -1 && errno == ENOENT) { - allow_seed_file_update = 1; - return 0; - } - - if( fd == -1 ) { - log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); - return 0; - } - if( fstat( fd, &sb ) ) { - log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); - close(fd); - return 0; - } - if( !S_ISREG(sb.st_mode) ) { - log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); - close(fd); - return 0; - } - if( !sb.st_size ) { - log_info(_("note: random_seed file is empty\n") ); - close(fd); - allow_seed_file_update = 1; - return 0; - } - if( sb.st_size != POOLSIZE ) { - log_info(_("WARNING: invalid size of random_seed file - not used\n") ); - close(fd); - return 0; - } - do { - n = read( fd, buffer, POOLSIZE ); - } while( n == -1 && errno == EINTR ); - if( n != POOLSIZE ) { - log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); - close(fd); - return 0; - } - - close(fd); - - add_randomness( buffer, POOLSIZE, 0 ); - /* add some minor entropy to the pool now (this will also force a mixing) */ - { pid_t x = getpid(); - add_randomness( &x, sizeof(x), 0 ); - } - { time_t x = time(NULL); - add_randomness( &x, sizeof(x), 0 ); - } - { clock_t x = clock(); - add_randomness( &x, sizeof(x), 0 ); - } - /* And read a few bytes from our entropy source. By using - * a level of 0 this will not block and might not return anything - * with some entropy drivers, however the rndlinux driver will use - * /dev/urandom and return some stuff - Do not read to much as we - * want to be friendly to the scare system entropy resource. */ - read_random_source( 0, 16, 0 ); - - allow_seed_file_update = 1; - return 1; -} - -void -update_random_seed_file() -{ - ulong *sp, *dp; - int fd, i; - - if( !seed_file_name || !is_initialized || !pool_filled ) - return; - if( !allow_seed_file_update ) { - log_info(_("note: random_seed file not updated\n")); - return; - } - - - /* copy the entropy pool to a scratch pool and mix both of them */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) { - *dp = *sp + ADD_VALUE; - } - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - - #ifdef HAVE_DOSISH_SYSTEM - fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, - S_IRUSR|S_IWUSR ); - #else - fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); - #endif - if( fd == -1 ) { - log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); - return; - } - do { - i = write( fd, keypool, POOLSIZE ); - } while( i == -1 && errno == EINTR ); - if( i != POOLSIZE ) { - log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); - } - if( close(fd) ) - log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); -} - - -static void -read_pool( byte *buffer, size_t length, int level ) -{ - int i; - ulong *sp, *dp; - - if( length > POOLSIZE ) { - log_bug("too many random bits requested\n"); - } - - if( !pool_filled ) { - if( read_seed_file() ) - pool_filled = 1; - } - - /* For level 2 quality (key generation) we alwas make - * sure that the pool has been seeded enough initially */ - if( level == 2 && !did_initial_extra_seeding ) { - size_t needed; - - pool_balance = 0; - needed = length - pool_balance; - if( needed < POOLSIZE/2 ) - needed = POOLSIZE/2; - else if( needed > POOLSIZE ) - BUG(); - read_random_source( 3, needed, 2 ); - pool_balance += needed; - did_initial_extra_seeding=1; - } - - /* for level 2 make sure that there is enough random in the pool */ - if( level == 2 && pool_balance < length ) { - size_t needed; - - if( pool_balance < 0 ) - pool_balance = 0; - needed = length - pool_balance; - if( needed > POOLSIZE ) - BUG(); - read_random_source( 3, needed, 2 ); - pool_balance += needed; - } - - /* make sure the pool is filled */ - while( !pool_filled ) - random_poll(); - - /* do always a fast random poll */ - fast_random_poll(); - - if( !level ) { /* no need for cryptographic strong random */ - /* create a new pool */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; - /* must mix both pools */ - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - memcpy( buffer, keypool, length ); - } - else { - /* mix the pool (if add_randomness() didn't it) */ - if( !just_mixed ) { - mix_pool(rndpool); - rndstats.mixrnd++; - } - /* create a new pool */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; - /* and mix both pools */ - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - /* read the required data - * we use a readpoiter to read from a different postion each - * time */ - while( length-- ) { - *buffer++ = keypool[pool_readpos++]; - if( pool_readpos >= POOLSIZE ) - pool_readpos = 0; - pool_balance--; - } - if( pool_balance < 0 ) - pool_balance = 0; - /* and clear the keypool */ - memset( keypool, 0, POOLSIZE ); - } -} - - -/**************** - * Add LENGTH bytes of randomness from buffer to the pool. - * source may be used to specify the randomness source. - * Source is: - * 0 - used ony for initialization - * 1 - fast random poll function - * 2 - normal poll function - * 3 - used when level 2 random quality has been requested - * to do an extra pool seed. - */ -static void -add_randomness( const void *buffer, size_t length, int source ) -{ - const byte *p = buffer; - - if( !is_initialized ) - initialize(); - rndstats.addbytes += length; - rndstats.naddbytes++; - while( length-- ) { - rndpool[pool_writepos++] ^= *p++; - if( pool_writepos >= POOLSIZE ) { - if( source > 1 ) - pool_filled = 1; - pool_writepos = 0; - mix_pool(rndpool); rndstats.mixrnd++; - just_mixed = !length; - } - } -} - - - -static void -random_poll() -{ - rndstats.slowpolls++; - read_random_source( 2, POOLSIZE/5, 1 ); -} - - -void -fast_random_poll() -{ - static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; - static int initialized = 0; - - rndstats.fastpolls++; - if( !initialized ) { - if( !is_initialized ) - initialize(); - initialized = 1; - fnc = getfnc_fast_random_poll(); - } - if( fnc ) { - (*fnc)( add_randomness, 1 ); - return; - } - - /* fall back to the generic function */ - #if defined(HAVE_GETHRTIME) && !defined(HAVE_BROKEN_GETHRTIME) - { hrtime_t tv; - /* On some Solaris and HPUX system gethrtime raises an SIGILL, but we - * checked this with configure */ - tv = gethrtime(); - add_randomness( &tv, sizeof(tv), 1 ); - } - #elif defined (HAVE_GETTIMEOFDAY) - { struct timeval tv; - if( gettimeofday( &tv, NULL ) ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); - add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); - } - #elif defined (HAVE_CLOCK_GETTIME) - { struct timespec tv; - if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); - add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); - } - #else /* use times */ - #ifndef HAVE_DOSISH_SYSTEM - { struct tms buf; - times( &buf ); - add_randomness( &buf, sizeof buf, 1 ); - } - #endif - #endif - #ifdef HAVE_GETRUSAGE - #ifndef RUSAGE_SELF - #ifdef __GCC__ - #warning There is no RUSAGE_SELF on this system - #endif - #else - { struct rusage buf; - /* QNX/Neutrino does return ENOSYS - so we just ignore it and - * add whatever is in buf. In a chroot environment it might not - * work at all (i.e. because /proc/ is not accessible), so we better - * ignore all error codes and hope for the best - */ - getrusage( RUSAGE_SELF, &buf ); - - add_randomness( &buf, sizeof buf, 1 ); - memset( &buf, 0, sizeof buf ); - } - #endif - #endif - /* time and clock are available on all systems - so - * we better do it just in case one of the above functions - * didn't work */ - { time_t x = time(NULL); - add_randomness( &x, sizeof(x), 1 ); - } - { clock_t x = clock(); - add_randomness( &x, sizeof(x), 1 ); - } -} - - - -static void -read_random_source( int requester, size_t length, int level ) -{ - static int (*fnc)(void (*)(const void*, size_t, int), int, - size_t, int) = NULL; - if( !fnc ) { - if( !is_initialized ) - initialize(); - fnc = getfnc_gather_random(); - if( !fnc ) { - faked_rng = 1; - fnc = gather_faked; - } - if( !requester && !length && !level ) - return; /* init only */ - } - if( (*fnc)( add_randomness, requester, length, level ) < 0 ) - log_fatal("No way to gather entropy for the RNG\n"); -} - - -static int -gather_faked( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - static int initialized=0; - size_t n; - char *buffer, *p; - - if( !initialized ) { - log_info(_("WARNING: using insecure random number generator!!\n")); - tty_printf(_("The random number generator is only a kludge to let\n" - "it run - it is in no way a strong RNG!\n\n" - "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); - initialized=1; - #ifdef HAVE_RAND - srand(make_timestamp()*getpid()); - #else - srandom(make_timestamp()*getpid()); - #endif - } - - p = buffer = m_alloc( length ); - n = length; - #ifdef HAVE_RAND - while( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); - #else - while( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); - #endif - add_randomness( buffer, length, requester ); - m_free(buffer); - return 0; /* okay */ -} - - diff --git a/cipher/random.h b/cipher/random.h deleted file mode 100644 index f4ba918bd..000000000 --- a/cipher/random.h +++ /dev/null @@ -1,41 +0,0 @@ -/* random.h - random 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 - */ -#ifndef G10_RANDOM_H -#define G10_RANDOM_H - -#include "types.h" - -/*-- random.c --*/ -void random_dump_stats(void); -void secure_random_alloc(void); -void set_random_seed_file(const char *); -void update_random_seed_file(void); -int quick_random_gen( int onoff ); -int random_is_faked(void); -void randomize_buffer( byte *buffer, size_t length, int level ); -byte *get_random_bits( size_t nbits, int level, int secure ); -void fast_random_poll( void ); - -/*-- rndw32.c --*/ -#ifdef USE_STATIC_RNDW32 -void rndw32_set_dll_name( const char *name ); -#endif - -#endif /*G10_RANDOM_H*/ diff --git a/cipher/rijndael.c b/cipher/rijndael.c deleted file mode 100644 index 62c5bc23a..000000000 --- a/cipher/rijndael.c +++ /dev/null @@ -1,2234 +0,0 @@ -/* Rijndael (AES) for GnuPG - * Copyright (C) 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 - ******************************************************************* - * The code here is based on the optimized implementation taken from - * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000, - * which carries this notice: - *------------------------------------------ - * rijndael-alg-fst.c v2.3 April '2000 - * - * Optimised ANSI C code - * - * authors: v1.0: Antoon Bosselaers - * v2.0: Vincent Rijmen - * v2.3: Paulo Barreto - * - * This code is placed in the public domain. - *------------------------------------------ - */ - -#include -#include -#include -#include /* for memcmp() */ - -#include "types.h" /* for byte and u32 typedefs */ -#include "util.h" -#include "errors.h" -#include "algorithms.h" - -#define MAXKC (256/32) -#define MAXROUNDS 14 - - -static const char *selftest(void); - -typedef struct { - int ROUNDS; /* key-length-dependent number of rounds */ - int decryption_prepared; - byte keySched[MAXROUNDS+1][4][4]; /* key schedule */ - byte keySched2[MAXROUNDS+1][4][4]; /* key schedule */ -} RIJNDAEL_context; - - -static const byte S[256] = { - 99, 124, 119, 123, 242, 107, 111, 197, - 48, 1, 103, 43, 254, 215, 171, 118, - 202, 130, 201, 125, 250, 89, 71, 240, - 173, 212, 162, 175, 156, 164, 114, 192, - 183, 253, 147, 38, 54, 63, 247, 204, - 52, 165, 229, 241, 113, 216, 49, 21, - 4, 199, 35, 195, 24, 150, 5, 154, - 7, 18, 128, 226, 235, 39, 178, 117, - 9, 131, 44, 26, 27, 110, 90, 160, - 82, 59, 214, 179, 41, 227, 47, 132, - 83, 209, 0, 237, 32, 252, 177, 91, - 106, 203, 190, 57, 74, 76, 88, 207, - 208, 239, 170, 251, 67, 77, 51, 133, - 69, 249, 2, 127, 80, 60, 159, 168, - 81, 163, 64, 143, 146, 157, 56, 245, - 188, 182, 218, 33, 16, 255, 243, 210, - 205, 12, 19, 236, 95, 151, 68, 23, - 196, 167, 126, 61, 100, 93, 25, 115, - 96, 129, 79, 220, 34, 42, 144, 136, - 70, 238, 184, 20, 222, 94, 11, 219, - 224, 50, 58, 10, 73, 6, 36, 92, - 194, 211, 172, 98, 145, 149, 228, 121, - 231, 200, 55, 109, 141, 213, 78, 169, - 108, 86, 244, 234, 101, 122, 174, 8, - 186, 120, 37, 46, 28, 166, 180, 198, - 232, 221, 116, 31, 75, 189, 139, 138, - 112, 62, 181, 102, 72, 3, 246, 14, - 97, 53, 87, 185, 134, 193, 29, 158, - 225, 248, 152, 17, 105, 217, 142, 148, - 155, 30, 135, 233, 206, 85, 40, 223, - 140, 161, 137, 13, 191, 230, 66, 104, - 65, 153, 45, 15, 176, 84, 187, 22 -}; - - -static const byte T1[256][4] = { - { 0xc6,0x63,0x63,0xa5 }, { 0xf8,0x7c,0x7c,0x84 }, - { 0xee,0x77,0x77,0x99 }, { 0xf6,0x7b,0x7b,0x8d }, - { 0xff,0xf2,0xf2,0x0d }, { 0xd6,0x6b,0x6b,0xbd }, - { 0xde,0x6f,0x6f,0xb1 }, { 0x91,0xc5,0xc5,0x54 }, - { 0x60,0x30,0x30,0x50 }, { 0x02,0x01,0x01,0x03 }, - { 0xce,0x67,0x67,0xa9 }, { 0x56,0x2b,0x2b,0x7d }, - { 0xe7,0xfe,0xfe,0x19 }, { 0xb5,0xd7,0xd7,0x62 }, - { 0x4d,0xab,0xab,0xe6 }, { 0xec,0x76,0x76,0x9a }, - { 0x8f,0xca,0xca,0x45 }, { 0x1f,0x82,0x82,0x9d }, - { 0x89,0xc9,0xc9,0x40 }, { 0xfa,0x7d,0x7d,0x87 }, - { 0xef,0xfa,0xfa,0x15 }, { 0xb2,0x59,0x59,0xeb }, - { 0x8e,0x47,0x47,0xc9 }, { 0xfb,0xf0,0xf0,0x0b }, - { 0x41,0xad,0xad,0xec }, { 0xb3,0xd4,0xd4,0x67 }, - { 0x5f,0xa2,0xa2,0xfd }, { 0x45,0xaf,0xaf,0xea }, - { 0x23,0x9c,0x9c,0xbf }, { 0x53,0xa4,0xa4,0xf7 }, - { 0xe4,0x72,0x72,0x96 }, { 0x9b,0xc0,0xc0,0x5b }, - { 0x75,0xb7,0xb7,0xc2 }, { 0xe1,0xfd,0xfd,0x1c }, - { 0x3d,0x93,0x93,0xae }, { 0x4c,0x26,0x26,0x6a }, - { 0x6c,0x36,0x36,0x5a }, { 0x7e,0x3f,0x3f,0x41 }, - { 0xf5,0xf7,0xf7,0x02 }, { 0x83,0xcc,0xcc,0x4f }, - { 0x68,0x34,0x34,0x5c }, { 0x51,0xa5,0xa5,0xf4 }, - { 0xd1,0xe5,0xe5,0x34 }, { 0xf9,0xf1,0xf1,0x08 }, - { 0xe2,0x71,0x71,0x93 }, { 0xab,0xd8,0xd8,0x73 }, - { 0x62,0x31,0x31,0x53 }, { 0x2a,0x15,0x15,0x3f }, - { 0x08,0x04,0x04,0x0c }, { 0x95,0xc7,0xc7,0x52 }, - { 0x46,0x23,0x23,0x65 }, { 0x9d,0xc3,0xc3,0x5e }, - { 0x30,0x18,0x18,0x28 }, { 0x37,0x96,0x96,0xa1 }, - { 0x0a,0x05,0x05,0x0f }, { 0x2f,0x9a,0x9a,0xb5 }, - { 0x0e,0x07,0x07,0x09 }, { 0x24,0x12,0x12,0x36 }, - { 0x1b,0x80,0x80,0x9b }, { 0xdf,0xe2,0xe2,0x3d }, - { 0xcd,0xeb,0xeb,0x26 }, { 0x4e,0x27,0x27,0x69 }, - { 0x7f,0xb2,0xb2,0xcd }, { 0xea,0x75,0x75,0x9f }, - { 0x12,0x09,0x09,0x1b }, { 0x1d,0x83,0x83,0x9e }, - { 0x58,0x2c,0x2c,0x74 }, { 0x34,0x1a,0x1a,0x2e }, - { 0x36,0x1b,0x1b,0x2d }, { 0xdc,0x6e,0x6e,0xb2 }, - { 0xb4,0x5a,0x5a,0xee }, { 0x5b,0xa0,0xa0,0xfb }, - { 0xa4,0x52,0x52,0xf6 }, { 0x76,0x3b,0x3b,0x4d }, - { 0xb7,0xd6,0xd6,0x61 }, { 0x7d,0xb3,0xb3,0xce }, - { 0x52,0x29,0x29,0x7b }, { 0xdd,0xe3,0xe3,0x3e }, - { 0x5e,0x2f,0x2f,0x71 }, { 0x13,0x84,0x84,0x97 }, - { 0xa6,0x53,0x53,0xf5 }, { 0xb9,0xd1,0xd1,0x68 }, - { 0x00,0x00,0x00,0x00 }, { 0xc1,0xed,0xed,0x2c }, - { 0x40,0x20,0x20,0x60 }, { 0xe3,0xfc,0xfc,0x1f }, - { 0x79,0xb1,0xb1,0xc8 }, { 0xb6,0x5b,0x5b,0xed }, - { 0xd4,0x6a,0x6a,0xbe }, { 0x8d,0xcb,0xcb,0x46 }, - { 0x67,0xbe,0xbe,0xd9 }, { 0x72,0x39,0x39,0x4b }, - { 0x94,0x4a,0x4a,0xde }, { 0x98,0x4c,0x4c,0xd4 }, - { 0xb0,0x58,0x58,0xe8 }, { 0x85,0xcf,0xcf,0x4a }, - { 0xbb,0xd0,0xd0,0x6b }, { 0xc5,0xef,0xef,0x2a }, - { 0x4f,0xaa,0xaa,0xe5 }, { 0xed,0xfb,0xfb,0x16 }, - { 0x86,0x43,0x43,0xc5 }, { 0x9a,0x4d,0x4d,0xd7 }, - { 0x66,0x33,0x33,0x55 }, { 0x11,0x85,0x85,0x94 }, - { 0x8a,0x45,0x45,0xcf }, { 0xe9,0xf9,0xf9,0x10 }, - { 0x04,0x02,0x02,0x06 }, { 0xfe,0x7f,0x7f,0x81 }, - { 0xa0,0x50,0x50,0xf0 }, { 0x78,0x3c,0x3c,0x44 }, - { 0x25,0x9f,0x9f,0xba }, { 0x4b,0xa8,0xa8,0xe3 }, - { 0xa2,0x51,0x51,0xf3 }, { 0x5d,0xa3,0xa3,0xfe }, - { 0x80,0x40,0x40,0xc0 }, { 0x05,0x8f,0x8f,0x8a }, - { 0x3f,0x92,0x92,0xad }, { 0x21,0x9d,0x9d,0xbc }, - { 0x70,0x38,0x38,0x48 }, { 0xf1,0xf5,0xf5,0x04 }, - { 0x63,0xbc,0xbc,0xdf }, { 0x77,0xb6,0xb6,0xc1 }, - { 0xaf,0xda,0xda,0x75 }, { 0x42,0x21,0x21,0x63 }, - { 0x20,0x10,0x10,0x30 }, { 0xe5,0xff,0xff,0x1a }, - { 0xfd,0xf3,0xf3,0x0e }, { 0xbf,0xd2,0xd2,0x6d }, - { 0x81,0xcd,0xcd,0x4c }, { 0x18,0x0c,0x0c,0x14 }, - { 0x26,0x13,0x13,0x35 }, { 0xc3,0xec,0xec,0x2f }, - { 0xbe,0x5f,0x5f,0xe1 }, { 0x35,0x97,0x97,0xa2 }, - { 0x88,0x44,0x44,0xcc }, { 0x2e,0x17,0x17,0x39 }, - { 0x93,0xc4,0xc4,0x57 }, { 0x55,0xa7,0xa7,0xf2 }, - { 0xfc,0x7e,0x7e,0x82 }, { 0x7a,0x3d,0x3d,0x47 }, - { 0xc8,0x64,0x64,0xac }, { 0xba,0x5d,0x5d,0xe7 }, - { 0x32,0x19,0x19,0x2b }, { 0xe6,0x73,0x73,0x95 }, - { 0xc0,0x60,0x60,0xa0 }, { 0x19,0x81,0x81,0x98 }, - { 0x9e,0x4f,0x4f,0xd1 }, { 0xa3,0xdc,0xdc,0x7f }, - { 0x44,0x22,0x22,0x66 }, { 0x54,0x2a,0x2a,0x7e }, - { 0x3b,0x90,0x90,0xab }, { 0x0b,0x88,0x88,0x83 }, - { 0x8c,0x46,0x46,0xca }, { 0xc7,0xee,0xee,0x29 }, - { 0x6b,0xb8,0xb8,0xd3 }, { 0x28,0x14,0x14,0x3c }, - { 0xa7,0xde,0xde,0x79 }, { 0xbc,0x5e,0x5e,0xe2 }, - { 0x16,0x0b,0x0b,0x1d }, { 0xad,0xdb,0xdb,0x76 }, - { 0xdb,0xe0,0xe0,0x3b }, { 0x64,0x32,0x32,0x56 }, - { 0x74,0x3a,0x3a,0x4e }, { 0x14,0x0a,0x0a,0x1e }, - { 0x92,0x49,0x49,0xdb }, { 0x0c,0x06,0x06,0x0a }, - { 0x48,0x24,0x24,0x6c }, { 0xb8,0x5c,0x5c,0xe4 }, - { 0x9f,0xc2,0xc2,0x5d }, { 0xbd,0xd3,0xd3,0x6e }, - { 0x43,0xac,0xac,0xef }, { 0xc4,0x62,0x62,0xa6 }, - { 0x39,0x91,0x91,0xa8 }, { 0x31,0x95,0x95,0xa4 }, - { 0xd3,0xe4,0xe4,0x37 }, { 0xf2,0x79,0x79,0x8b }, - { 0xd5,0xe7,0xe7,0x32 }, { 0x8b,0xc8,0xc8,0x43 }, - { 0x6e,0x37,0x37,0x59 }, { 0xda,0x6d,0x6d,0xb7 }, - { 0x01,0x8d,0x8d,0x8c }, { 0xb1,0xd5,0xd5,0x64 }, - { 0x9c,0x4e,0x4e,0xd2 }, { 0x49,0xa9,0xa9,0xe0 }, - { 0xd8,0x6c,0x6c,0xb4 }, { 0xac,0x56,0x56,0xfa }, - { 0xf3,0xf4,0xf4,0x07 }, { 0xcf,0xea,0xea,0x25 }, - { 0xca,0x65,0x65,0xaf }, { 0xf4,0x7a,0x7a,0x8e }, - { 0x47,0xae,0xae,0xe9 }, { 0x10,0x08,0x08,0x18 }, - { 0x6f,0xba,0xba,0xd5 }, { 0xf0,0x78,0x78,0x88 }, - { 0x4a,0x25,0x25,0x6f }, { 0x5c,0x2e,0x2e,0x72 }, - { 0x38,0x1c,0x1c,0x24 }, { 0x57,0xa6,0xa6,0xf1 }, - { 0x73,0xb4,0xb4,0xc7 }, { 0x97,0xc6,0xc6,0x51 }, - { 0xcb,0xe8,0xe8,0x23 }, { 0xa1,0xdd,0xdd,0x7c }, - { 0xe8,0x74,0x74,0x9c }, { 0x3e,0x1f,0x1f,0x21 }, - { 0x96,0x4b,0x4b,0xdd }, { 0x61,0xbd,0xbd,0xdc }, - { 0x0d,0x8b,0x8b,0x86 }, { 0x0f,0x8a,0x8a,0x85 }, - { 0xe0,0x70,0x70,0x90 }, { 0x7c,0x3e,0x3e,0x42 }, - { 0x71,0xb5,0xb5,0xc4 }, { 0xcc,0x66,0x66,0xaa }, - { 0x90,0x48,0x48,0xd8 }, { 0x06,0x03,0x03,0x05 }, - { 0xf7,0xf6,0xf6,0x01 }, { 0x1c,0x0e,0x0e,0x12 }, - { 0xc2,0x61,0x61,0xa3 }, { 0x6a,0x35,0x35,0x5f }, - { 0xae,0x57,0x57,0xf9 }, { 0x69,0xb9,0xb9,0xd0 }, - { 0x17,0x86,0x86,0x91 }, { 0x99,0xc1,0xc1,0x58 }, - { 0x3a,0x1d,0x1d,0x27 }, { 0x27,0x9e,0x9e,0xb9 }, - { 0xd9,0xe1,0xe1,0x38 }, { 0xeb,0xf8,0xf8,0x13 }, - { 0x2b,0x98,0x98,0xb3 }, { 0x22,0x11,0x11,0x33 }, - { 0xd2,0x69,0x69,0xbb }, { 0xa9,0xd9,0xd9,0x70 }, - { 0x07,0x8e,0x8e,0x89 }, { 0x33,0x94,0x94,0xa7 }, - { 0x2d,0x9b,0x9b,0xb6 }, { 0x3c,0x1e,0x1e,0x22 }, - { 0x15,0x87,0x87,0x92 }, { 0xc9,0xe9,0xe9,0x20 }, - { 0x87,0xce,0xce,0x49 }, { 0xaa,0x55,0x55,0xff }, - { 0x50,0x28,0x28,0x78 }, { 0xa5,0xdf,0xdf,0x7a }, - { 0x03,0x8c,0x8c,0x8f }, { 0x59,0xa1,0xa1,0xf8 }, - { 0x09,0x89,0x89,0x80 }, { 0x1a,0x0d,0x0d,0x17 }, - { 0x65,0xbf,0xbf,0xda }, { 0xd7,0xe6,0xe6,0x31 }, - { 0x84,0x42,0x42,0xc6 }, { 0xd0,0x68,0x68,0xb8 }, - { 0x82,0x41,0x41,0xc3 }, { 0x29,0x99,0x99,0xb0 }, - { 0x5a,0x2d,0x2d,0x77 }, { 0x1e,0x0f,0x0f,0x11 }, - { 0x7b,0xb0,0xb0,0xcb }, { 0xa8,0x54,0x54,0xfc }, - { 0x6d,0xbb,0xbb,0xd6 }, { 0x2c,0x16,0x16,0x3a } -}; - -static const byte T2[256][4] = { - { 0xa5,0xc6,0x63,0x63 }, { 0x84,0xf8,0x7c,0x7c }, - { 0x99,0xee,0x77,0x77 }, { 0x8d,0xf6,0x7b,0x7b }, - { 0x0d,0xff,0xf2,0xf2 }, { 0xbd,0xd6,0x6b,0x6b }, - { 0xb1,0xde,0x6f,0x6f }, { 0x54,0x91,0xc5,0xc5 }, - { 0x50,0x60,0x30,0x30 }, { 0x03,0x02,0x01,0x01 }, - { 0xa9,0xce,0x67,0x67 }, { 0x7d,0x56,0x2b,0x2b }, - { 0x19,0xe7,0xfe,0xfe }, { 0x62,0xb5,0xd7,0xd7 }, - { 0xe6,0x4d,0xab,0xab }, { 0x9a,0xec,0x76,0x76 }, - { 0x45,0x8f,0xca,0xca }, { 0x9d,0x1f,0x82,0x82 }, - { 0x40,0x89,0xc9,0xc9 }, { 0x87,0xfa,0x7d,0x7d }, - { 0x15,0xef,0xfa,0xfa }, { 0xeb,0xb2,0x59,0x59 }, - { 0xc9,0x8e,0x47,0x47 }, { 0x0b,0xfb,0xf0,0xf0 }, - { 0xec,0x41,0xad,0xad }, { 0x67,0xb3,0xd4,0xd4 }, - { 0xfd,0x5f,0xa2,0xa2 }, { 0xea,0x45,0xaf,0xaf }, - { 0xbf,0x23,0x9c,0x9c }, { 0xf7,0x53,0xa4,0xa4 }, - { 0x96,0xe4,0x72,0x72 }, { 0x5b,0x9b,0xc0,0xc0 }, - { 0xc2,0x75,0xb7,0xb7 }, { 0x1c,0xe1,0xfd,0xfd }, - { 0xae,0x3d,0x93,0x93 }, { 0x6a,0x4c,0x26,0x26 }, - { 0x5a,0x6c,0x36,0x36 }, { 0x41,0x7e,0x3f,0x3f }, - { 0x02,0xf5,0xf7,0xf7 }, { 0x4f,0x83,0xcc,0xcc }, - { 0x5c,0x68,0x34,0x34 }, { 0xf4,0x51,0xa5,0xa5 }, - { 0x34,0xd1,0xe5,0xe5 }, { 0x08,0xf9,0xf1,0xf1 }, - { 0x93,0xe2,0x71,0x71 }, { 0x73,0xab,0xd8,0xd8 }, - { 0x53,0x62,0x31,0x31 }, { 0x3f,0x2a,0x15,0x15 }, - { 0x0c,0x08,0x04,0x04 }, { 0x52,0x95,0xc7,0xc7 }, - { 0x65,0x46,0x23,0x23 }, { 0x5e,0x9d,0xc3,0xc3 }, - { 0x28,0x30,0x18,0x18 }, { 0xa1,0x37,0x96,0x96 }, - { 0x0f,0x0a,0x05,0x05 }, { 0xb5,0x2f,0x9a,0x9a }, - { 0x09,0x0e,0x07,0x07 }, { 0x36,0x24,0x12,0x12 }, - { 0x9b,0x1b,0x80,0x80 }, { 0x3d,0xdf,0xe2,0xe2 }, - { 0x26,0xcd,0xeb,0xeb }, { 0x69,0x4e,0x27,0x27 }, - { 0xcd,0x7f,0xb2,0xb2 }, { 0x9f,0xea,0x75,0x75 }, - { 0x1b,0x12,0x09,0x09 }, { 0x9e,0x1d,0x83,0x83 }, - { 0x74,0x58,0x2c,0x2c }, { 0x2e,0x34,0x1a,0x1a }, - { 0x2d,0x36,0x1b,0x1b }, { 0xb2,0xdc,0x6e,0x6e }, - { 0xee,0xb4,0x5a,0x5a }, { 0xfb,0x5b,0xa0,0xa0 }, - { 0xf6,0xa4,0x52,0x52 }, { 0x4d,0x76,0x3b,0x3b }, - { 0x61,0xb7,0xd6,0xd6 }, { 0xce,0x7d,0xb3,0xb3 }, - { 0x7b,0x52,0x29,0x29 }, { 0x3e,0xdd,0xe3,0xe3 }, - { 0x71,0x5e,0x2f,0x2f }, { 0x97,0x13,0x84,0x84 }, - { 0xf5,0xa6,0x53,0x53 }, { 0x68,0xb9,0xd1,0xd1 }, - { 0x00,0x00,0x00,0x00 }, { 0x2c,0xc1,0xed,0xed }, - { 0x60,0x40,0x20,0x20 }, { 0x1f,0xe3,0xfc,0xfc }, - { 0xc8,0x79,0xb1,0xb1 }, { 0xed,0xb6,0x5b,0x5b }, - { 0xbe,0xd4,0x6a,0x6a }, { 0x46,0x8d,0xcb,0xcb }, - { 0xd9,0x67,0xbe,0xbe }, { 0x4b,0x72,0x39,0x39 }, - { 0xde,0x94,0x4a,0x4a }, { 0xd4,0x98,0x4c,0x4c }, - { 0xe8,0xb0,0x58,0x58 }, { 0x4a,0x85,0xcf,0xcf }, - { 0x6b,0xbb,0xd0,0xd0 }, { 0x2a,0xc5,0xef,0xef }, - { 0xe5,0x4f,0xaa,0xaa }, { 0x16,0xed,0xfb,0xfb }, - { 0xc5,0x86,0x43,0x43 }, { 0xd7,0x9a,0x4d,0x4d }, - { 0x55,0x66,0x33,0x33 }, { 0x94,0x11,0x85,0x85 }, - { 0xcf,0x8a,0x45,0x45 }, { 0x10,0xe9,0xf9,0xf9 }, - { 0x06,0x04,0x02,0x02 }, { 0x81,0xfe,0x7f,0x7f }, - { 0xf0,0xa0,0x50,0x50 }, { 0x44,0x78,0x3c,0x3c }, - { 0xba,0x25,0x9f,0x9f }, { 0xe3,0x4b,0xa8,0xa8 }, - { 0xf3,0xa2,0x51,0x51 }, { 0xfe,0x5d,0xa3,0xa3 }, - { 0xc0,0x80,0x40,0x40 }, { 0x8a,0x05,0x8f,0x8f }, - { 0xad,0x3f,0x92,0x92 }, { 0xbc,0x21,0x9d,0x9d }, - { 0x48,0x70,0x38,0x38 }, { 0x04,0xf1,0xf5,0xf5 }, - { 0xdf,0x63,0xbc,0xbc }, { 0xc1,0x77,0xb6,0xb6 }, - { 0x75,0xaf,0xda,0xda }, { 0x63,0x42,0x21,0x21 }, - { 0x30,0x20,0x10,0x10 }, { 0x1a,0xe5,0xff,0xff }, - { 0x0e,0xfd,0xf3,0xf3 }, { 0x6d,0xbf,0xd2,0xd2 }, - { 0x4c,0x81,0xcd,0xcd }, { 0x14,0x18,0x0c,0x0c }, - { 0x35,0x26,0x13,0x13 }, { 0x2f,0xc3,0xec,0xec }, - { 0xe1,0xbe,0x5f,0x5f }, { 0xa2,0x35,0x97,0x97 }, - { 0xcc,0x88,0x44,0x44 }, { 0x39,0x2e,0x17,0x17 }, - { 0x57,0x93,0xc4,0xc4 }, { 0xf2,0x55,0xa7,0xa7 }, - { 0x82,0xfc,0x7e,0x7e }, { 0x47,0x7a,0x3d,0x3d }, - { 0xac,0xc8,0x64,0x64 }, { 0xe7,0xba,0x5d,0x5d }, - { 0x2b,0x32,0x19,0x19 }, { 0x95,0xe6,0x73,0x73 }, - { 0xa0,0xc0,0x60,0x60 }, { 0x98,0x19,0x81,0x81 }, - { 0xd1,0x9e,0x4f,0x4f }, { 0x7f,0xa3,0xdc,0xdc }, - { 0x66,0x44,0x22,0x22 }, { 0x7e,0x54,0x2a,0x2a }, - { 0xab,0x3b,0x90,0x90 }, { 0x83,0x0b,0x88,0x88 }, - { 0xca,0x8c,0x46,0x46 }, { 0x29,0xc7,0xee,0xee }, - { 0xd3,0x6b,0xb8,0xb8 }, { 0x3c,0x28,0x14,0x14 }, - { 0x79,0xa7,0xde,0xde }, { 0xe2,0xbc,0x5e,0x5e }, - { 0x1d,0x16,0x0b,0x0b }, { 0x76,0xad,0xdb,0xdb }, - { 0x3b,0xdb,0xe0,0xe0 }, { 0x56,0x64,0x32,0x32 }, - { 0x4e,0x74,0x3a,0x3a }, { 0x1e,0x14,0x0a,0x0a }, - { 0xdb,0x92,0x49,0x49 }, { 0x0a,0x0c,0x06,0x06 }, - { 0x6c,0x48,0x24,0x24 }, { 0xe4,0xb8,0x5c,0x5c }, - { 0x5d,0x9f,0xc2,0xc2 }, { 0x6e,0xbd,0xd3,0xd3 }, - { 0xef,0x43,0xac,0xac }, { 0xa6,0xc4,0x62,0x62 }, - { 0xa8,0x39,0x91,0x91 }, { 0xa4,0x31,0x95,0x95 }, - { 0x37,0xd3,0xe4,0xe4 }, { 0x8b,0xf2,0x79,0x79 }, - { 0x32,0xd5,0xe7,0xe7 }, { 0x43,0x8b,0xc8,0xc8 }, - { 0x59,0x6e,0x37,0x37 }, { 0xb7,0xda,0x6d,0x6d }, - { 0x8c,0x01,0x8d,0x8d }, { 0x64,0xb1,0xd5,0xd5 }, - { 0xd2,0x9c,0x4e,0x4e }, { 0xe0,0x49,0xa9,0xa9 }, - { 0xb4,0xd8,0x6c,0x6c }, { 0xfa,0xac,0x56,0x56 }, - { 0x07,0xf3,0xf4,0xf4 }, { 0x25,0xcf,0xea,0xea }, - { 0xaf,0xca,0x65,0x65 }, { 0x8e,0xf4,0x7a,0x7a }, - { 0xe9,0x47,0xae,0xae }, { 0x18,0x10,0x08,0x08 }, - { 0xd5,0x6f,0xba,0xba }, { 0x88,0xf0,0x78,0x78 }, - { 0x6f,0x4a,0x25,0x25 }, { 0x72,0x5c,0x2e,0x2e }, - { 0x24,0x38,0x1c,0x1c }, { 0xf1,0x57,0xa6,0xa6 }, - { 0xc7,0x73,0xb4,0xb4 }, { 0x51,0x97,0xc6,0xc6 }, - { 0x23,0xcb,0xe8,0xe8 }, { 0x7c,0xa1,0xdd,0xdd }, - { 0x9c,0xe8,0x74,0x74 }, { 0x21,0x3e,0x1f,0x1f }, - { 0xdd,0x96,0x4b,0x4b }, { 0xdc,0x61,0xbd,0xbd }, - { 0x86,0x0d,0x8b,0x8b }, { 0x85,0x0f,0x8a,0x8a }, - { 0x90,0xe0,0x70,0x70 }, { 0x42,0x7c,0x3e,0x3e }, - { 0xc4,0x71,0xb5,0xb5 }, { 0xaa,0xcc,0x66,0x66 }, - { 0xd8,0x90,0x48,0x48 }, { 0x05,0x06,0x03,0x03 }, - { 0x01,0xf7,0xf6,0xf6 }, { 0x12,0x1c,0x0e,0x0e }, - { 0xa3,0xc2,0x61,0x61 }, { 0x5f,0x6a,0x35,0x35 }, - { 0xf9,0xae,0x57,0x57 }, { 0xd0,0x69,0xb9,0xb9 }, - { 0x91,0x17,0x86,0x86 }, { 0x58,0x99,0xc1,0xc1 }, - { 0x27,0x3a,0x1d,0x1d }, { 0xb9,0x27,0x9e,0x9e }, - { 0x38,0xd9,0xe1,0xe1 }, { 0x13,0xeb,0xf8,0xf8 }, - { 0xb3,0x2b,0x98,0x98 }, { 0x33,0x22,0x11,0x11 }, - { 0xbb,0xd2,0x69,0x69 }, { 0x70,0xa9,0xd9,0xd9 }, - { 0x89,0x07,0x8e,0x8e }, { 0xa7,0x33,0x94,0x94 }, - { 0xb6,0x2d,0x9b,0x9b }, { 0x22,0x3c,0x1e,0x1e }, - { 0x92,0x15,0x87,0x87 }, { 0x20,0xc9,0xe9,0xe9 }, - { 0x49,0x87,0xce,0xce }, { 0xff,0xaa,0x55,0x55 }, - { 0x78,0x50,0x28,0x28 }, { 0x7a,0xa5,0xdf,0xdf }, - { 0x8f,0x03,0x8c,0x8c }, { 0xf8,0x59,0xa1,0xa1 }, - { 0x80,0x09,0x89,0x89 }, { 0x17,0x1a,0x0d,0x0d }, - { 0xda,0x65,0xbf,0xbf }, { 0x31,0xd7,0xe6,0xe6 }, - { 0xc6,0x84,0x42,0x42 }, { 0xb8,0xd0,0x68,0x68 }, - { 0xc3,0x82,0x41,0x41 }, { 0xb0,0x29,0x99,0x99 }, - { 0x77,0x5a,0x2d,0x2d }, { 0x11,0x1e,0x0f,0x0f }, - { 0xcb,0x7b,0xb0,0xb0 }, { 0xfc,0xa8,0x54,0x54 }, - { 0xd6,0x6d,0xbb,0xbb }, { 0x3a,0x2c,0x16,0x16 } -}; - -static const byte T3[256][4] = { - { 0x63,0xa5,0xc6,0x63 }, { 0x7c,0x84,0xf8,0x7c }, - { 0x77,0x99,0xee,0x77 }, { 0x7b,0x8d,0xf6,0x7b }, - { 0xf2,0x0d,0xff,0xf2 }, { 0x6b,0xbd,0xd6,0x6b }, - { 0x6f,0xb1,0xde,0x6f }, { 0xc5,0x54,0x91,0xc5 }, - { 0x30,0x50,0x60,0x30 }, { 0x01,0x03,0x02,0x01 }, - { 0x67,0xa9,0xce,0x67 }, { 0x2b,0x7d,0x56,0x2b }, - { 0xfe,0x19,0xe7,0xfe }, { 0xd7,0x62,0xb5,0xd7 }, - { 0xab,0xe6,0x4d,0xab }, { 0x76,0x9a,0xec,0x76 }, - { 0xca,0x45,0x8f,0xca }, { 0x82,0x9d,0x1f,0x82 }, - { 0xc9,0x40,0x89,0xc9 }, { 0x7d,0x87,0xfa,0x7d }, - { 0xfa,0x15,0xef,0xfa }, { 0x59,0xeb,0xb2,0x59 }, - { 0x47,0xc9,0x8e,0x47 }, { 0xf0,0x0b,0xfb,0xf0 }, - { 0xad,0xec,0x41,0xad }, { 0xd4,0x67,0xb3,0xd4 }, - { 0xa2,0xfd,0x5f,0xa2 }, { 0xaf,0xea,0x45,0xaf }, - { 0x9c,0xbf,0x23,0x9c }, { 0xa4,0xf7,0x53,0xa4 }, - { 0x72,0x96,0xe4,0x72 }, { 0xc0,0x5b,0x9b,0xc0 }, - { 0xb7,0xc2,0x75,0xb7 }, { 0xfd,0x1c,0xe1,0xfd }, - { 0x93,0xae,0x3d,0x93 }, { 0x26,0x6a,0x4c,0x26 }, - { 0x36,0x5a,0x6c,0x36 }, { 0x3f,0x41,0x7e,0x3f }, - { 0xf7,0x02,0xf5,0xf7 }, { 0xcc,0x4f,0x83,0xcc }, - { 0x34,0x5c,0x68,0x34 }, { 0xa5,0xf4,0x51,0xa5 }, - { 0xe5,0x34,0xd1,0xe5 }, { 0xf1,0x08,0xf9,0xf1 }, - { 0x71,0x93,0xe2,0x71 }, { 0xd8,0x73,0xab,0xd8 }, - { 0x31,0x53,0x62,0x31 }, { 0x15,0x3f,0x2a,0x15 }, - { 0x04,0x0c,0x08,0x04 }, { 0xc7,0x52,0x95,0xc7 }, - { 0x23,0x65,0x46,0x23 }, { 0xc3,0x5e,0x9d,0xc3 }, - { 0x18,0x28,0x30,0x18 }, { 0x96,0xa1,0x37,0x96 }, - { 0x05,0x0f,0x0a,0x05 }, { 0x9a,0xb5,0x2f,0x9a }, - { 0x07,0x09,0x0e,0x07 }, { 0x12,0x36,0x24,0x12 }, - { 0x80,0x9b,0x1b,0x80 }, { 0xe2,0x3d,0xdf,0xe2 }, - { 0xeb,0x26,0xcd,0xeb }, { 0x27,0x69,0x4e,0x27 }, - { 0xb2,0xcd,0x7f,0xb2 }, { 0x75,0x9f,0xea,0x75 }, - { 0x09,0x1b,0x12,0x09 }, { 0x83,0x9e,0x1d,0x83 }, - { 0x2c,0x74,0x58,0x2c }, { 0x1a,0x2e,0x34,0x1a }, - { 0x1b,0x2d,0x36,0x1b }, { 0x6e,0xb2,0xdc,0x6e }, - { 0x5a,0xee,0xb4,0x5a }, { 0xa0,0xfb,0x5b,0xa0 }, - { 0x52,0xf6,0xa4,0x52 }, { 0x3b,0x4d,0x76,0x3b }, - { 0xd6,0x61,0xb7,0xd6 }, { 0xb3,0xce,0x7d,0xb3 }, - { 0x29,0x7b,0x52,0x29 }, { 0xe3,0x3e,0xdd,0xe3 }, - { 0x2f,0x71,0x5e,0x2f }, { 0x84,0x97,0x13,0x84 }, - { 0x53,0xf5,0xa6,0x53 }, { 0xd1,0x68,0xb9,0xd1 }, - { 0x00,0x00,0x00,0x00 }, { 0xed,0x2c,0xc1,0xed }, - { 0x20,0x60,0x40,0x20 }, { 0xfc,0x1f,0xe3,0xfc }, - { 0xb1,0xc8,0x79,0xb1 }, { 0x5b,0xed,0xb6,0x5b }, - { 0x6a,0xbe,0xd4,0x6a }, { 0xcb,0x46,0x8d,0xcb }, - { 0xbe,0xd9,0x67,0xbe }, { 0x39,0x4b,0x72,0x39 }, - { 0x4a,0xde,0x94,0x4a }, { 0x4c,0xd4,0x98,0x4c }, - { 0x58,0xe8,0xb0,0x58 }, { 0xcf,0x4a,0x85,0xcf }, - { 0xd0,0x6b,0xbb,0xd0 }, { 0xef,0x2a,0xc5,0xef }, - { 0xaa,0xe5,0x4f,0xaa }, { 0xfb,0x16,0xed,0xfb }, - { 0x43,0xc5,0x86,0x43 }, { 0x4d,0xd7,0x9a,0x4d }, - { 0x33,0x55,0x66,0x33 }, { 0x85,0x94,0x11,0x85 }, - { 0x45,0xcf,0x8a,0x45 }, { 0xf9,0x10,0xe9,0xf9 }, - { 0x02,0x06,0x04,0x02 }, { 0x7f,0x81,0xfe,0x7f }, - { 0x50,0xf0,0xa0,0x50 }, { 0x3c,0x44,0x78,0x3c }, - { 0x9f,0xba,0x25,0x9f }, { 0xa8,0xe3,0x4b,0xa8 }, - { 0x51,0xf3,0xa2,0x51 }, { 0xa3,0xfe,0x5d,0xa3 }, - { 0x40,0xc0,0x80,0x40 }, { 0x8f,0x8a,0x05,0x8f }, - { 0x92,0xad,0x3f,0x92 }, { 0x9d,0xbc,0x21,0x9d }, - { 0x38,0x48,0x70,0x38 }, { 0xf5,0x04,0xf1,0xf5 }, - { 0xbc,0xdf,0x63,0xbc }, { 0xb6,0xc1,0x77,0xb6 }, - { 0xda,0x75,0xaf,0xda }, { 0x21,0x63,0x42,0x21 }, - { 0x10,0x30,0x20,0x10 }, { 0xff,0x1a,0xe5,0xff }, - { 0xf3,0x0e,0xfd,0xf3 }, { 0xd2,0x6d,0xbf,0xd2 }, - { 0xcd,0x4c,0x81,0xcd }, { 0x0c,0x14,0x18,0x0c }, - { 0x13,0x35,0x26,0x13 }, { 0xec,0x2f,0xc3,0xec }, - { 0x5f,0xe1,0xbe,0x5f }, { 0x97,0xa2,0x35,0x97 }, - { 0x44,0xcc,0x88,0x44 }, { 0x17,0x39,0x2e,0x17 }, - { 0xc4,0x57,0x93,0xc4 }, { 0xa7,0xf2,0x55,0xa7 }, - { 0x7e,0x82,0xfc,0x7e }, { 0x3d,0x47,0x7a,0x3d }, - { 0x64,0xac,0xc8,0x64 }, { 0x5d,0xe7,0xba,0x5d }, - { 0x19,0x2b,0x32,0x19 }, { 0x73,0x95,0xe6,0x73 }, - { 0x60,0xa0,0xc0,0x60 }, { 0x81,0x98,0x19,0x81 }, - { 0x4f,0xd1,0x9e,0x4f }, { 0xdc,0x7f,0xa3,0xdc }, - { 0x22,0x66,0x44,0x22 }, { 0x2a,0x7e,0x54,0x2a }, - { 0x90,0xab,0x3b,0x90 }, { 0x88,0x83,0x0b,0x88 }, - { 0x46,0xca,0x8c,0x46 }, { 0xee,0x29,0xc7,0xee }, - { 0xb8,0xd3,0x6b,0xb8 }, { 0x14,0x3c,0x28,0x14 }, - { 0xde,0x79,0xa7,0xde }, { 0x5e,0xe2,0xbc,0x5e }, - { 0x0b,0x1d,0x16,0x0b }, { 0xdb,0x76,0xad,0xdb }, - { 0xe0,0x3b,0xdb,0xe0 }, { 0x32,0x56,0x64,0x32 }, - { 0x3a,0x4e,0x74,0x3a }, { 0x0a,0x1e,0x14,0x0a }, - { 0x49,0xdb,0x92,0x49 }, { 0x06,0x0a,0x0c,0x06 }, - { 0x24,0x6c,0x48,0x24 }, { 0x5c,0xe4,0xb8,0x5c }, - { 0xc2,0x5d,0x9f,0xc2 }, { 0xd3,0x6e,0xbd,0xd3 }, - { 0xac,0xef,0x43,0xac }, { 0x62,0xa6,0xc4,0x62 }, - { 0x91,0xa8,0x39,0x91 }, { 0x95,0xa4,0x31,0x95 }, - { 0xe4,0x37,0xd3,0xe4 }, { 0x79,0x8b,0xf2,0x79 }, - { 0xe7,0x32,0xd5,0xe7 }, { 0xc8,0x43,0x8b,0xc8 }, - { 0x37,0x59,0x6e,0x37 }, { 0x6d,0xb7,0xda,0x6d }, - { 0x8d,0x8c,0x01,0x8d }, { 0xd5,0x64,0xb1,0xd5 }, - { 0x4e,0xd2,0x9c,0x4e }, { 0xa9,0xe0,0x49,0xa9 }, - { 0x6c,0xb4,0xd8,0x6c }, { 0x56,0xfa,0xac,0x56 }, - { 0xf4,0x07,0xf3,0xf4 }, { 0xea,0x25,0xcf,0xea }, - { 0x65,0xaf,0xca,0x65 }, { 0x7a,0x8e,0xf4,0x7a }, - { 0xae,0xe9,0x47,0xae }, { 0x08,0x18,0x10,0x08 }, - { 0xba,0xd5,0x6f,0xba }, { 0x78,0x88,0xf0,0x78 }, - { 0x25,0x6f,0x4a,0x25 }, { 0x2e,0x72,0x5c,0x2e }, - { 0x1c,0x24,0x38,0x1c }, { 0xa6,0xf1,0x57,0xa6 }, - { 0xb4,0xc7,0x73,0xb4 }, { 0xc6,0x51,0x97,0xc6 }, - { 0xe8,0x23,0xcb,0xe8 }, { 0xdd,0x7c,0xa1,0xdd }, - { 0x74,0x9c,0xe8,0x74 }, { 0x1f,0x21,0x3e,0x1f }, - { 0x4b,0xdd,0x96,0x4b }, { 0xbd,0xdc,0x61,0xbd }, - { 0x8b,0x86,0x0d,0x8b }, { 0x8a,0x85,0x0f,0x8a }, - { 0x70,0x90,0xe0,0x70 }, { 0x3e,0x42,0x7c,0x3e }, - { 0xb5,0xc4,0x71,0xb5 }, { 0x66,0xaa,0xcc,0x66 }, - { 0x48,0xd8,0x90,0x48 }, { 0x03,0x05,0x06,0x03 }, - { 0xf6,0x01,0xf7,0xf6 }, { 0x0e,0x12,0x1c,0x0e }, - { 0x61,0xa3,0xc2,0x61 }, { 0x35,0x5f,0x6a,0x35 }, - { 0x57,0xf9,0xae,0x57 }, { 0xb9,0xd0,0x69,0xb9 }, - { 0x86,0x91,0x17,0x86 }, { 0xc1,0x58,0x99,0xc1 }, - { 0x1d,0x27,0x3a,0x1d }, { 0x9e,0xb9,0x27,0x9e }, - { 0xe1,0x38,0xd9,0xe1 }, { 0xf8,0x13,0xeb,0xf8 }, - { 0x98,0xb3,0x2b,0x98 }, { 0x11,0x33,0x22,0x11 }, - { 0x69,0xbb,0xd2,0x69 }, { 0xd9,0x70,0xa9,0xd9 }, - { 0x8e,0x89,0x07,0x8e }, { 0x94,0xa7,0x33,0x94 }, - { 0x9b,0xb6,0x2d,0x9b }, { 0x1e,0x22,0x3c,0x1e }, - { 0x87,0x92,0x15,0x87 }, { 0xe9,0x20,0xc9,0xe9 }, - { 0xce,0x49,0x87,0xce }, { 0x55,0xff,0xaa,0x55 }, - { 0x28,0x78,0x50,0x28 }, { 0xdf,0x7a,0xa5,0xdf }, - { 0x8c,0x8f,0x03,0x8c }, { 0xa1,0xf8,0x59,0xa1 }, - { 0x89,0x80,0x09,0x89 }, { 0x0d,0x17,0x1a,0x0d }, - { 0xbf,0xda,0x65,0xbf }, { 0xe6,0x31,0xd7,0xe6 }, - { 0x42,0xc6,0x84,0x42 }, { 0x68,0xb8,0xd0,0x68 }, - { 0x41,0xc3,0x82,0x41 }, { 0x99,0xb0,0x29,0x99 }, - { 0x2d,0x77,0x5a,0x2d }, { 0x0f,0x11,0x1e,0x0f }, - { 0xb0,0xcb,0x7b,0xb0 }, { 0x54,0xfc,0xa8,0x54 }, - { 0xbb,0xd6,0x6d,0xbb }, { 0x16,0x3a,0x2c,0x16 } -}; - -static const byte T4[256][4] = { - { 0x63,0x63,0xa5,0xc6 }, { 0x7c,0x7c,0x84,0xf8 }, - { 0x77,0x77,0x99,0xee }, { 0x7b,0x7b,0x8d,0xf6 }, - { 0xf2,0xf2,0x0d,0xff }, { 0x6b,0x6b,0xbd,0xd6 }, - { 0x6f,0x6f,0xb1,0xde }, { 0xc5,0xc5,0x54,0x91 }, - { 0x30,0x30,0x50,0x60 }, { 0x01,0x01,0x03,0x02 }, - { 0x67,0x67,0xa9,0xce }, { 0x2b,0x2b,0x7d,0x56 }, - { 0xfe,0xfe,0x19,0xe7 }, { 0xd7,0xd7,0x62,0xb5 }, - { 0xab,0xab,0xe6,0x4d }, { 0x76,0x76,0x9a,0xec }, - { 0xca,0xca,0x45,0x8f }, { 0x82,0x82,0x9d,0x1f }, - { 0xc9,0xc9,0x40,0x89 }, { 0x7d,0x7d,0x87,0xfa }, - { 0xfa,0xfa,0x15,0xef }, { 0x59,0x59,0xeb,0xb2 }, - { 0x47,0x47,0xc9,0x8e }, { 0xf0,0xf0,0x0b,0xfb }, - { 0xad,0xad,0xec,0x41 }, { 0xd4,0xd4,0x67,0xb3 }, - { 0xa2,0xa2,0xfd,0x5f }, { 0xaf,0xaf,0xea,0x45 }, - { 0x9c,0x9c,0xbf,0x23 }, { 0xa4,0xa4,0xf7,0x53 }, - { 0x72,0x72,0x96,0xe4 }, { 0xc0,0xc0,0x5b,0x9b }, - { 0xb7,0xb7,0xc2,0x75 }, { 0xfd,0xfd,0x1c,0xe1 }, - { 0x93,0x93,0xae,0x3d }, { 0x26,0x26,0x6a,0x4c }, - { 0x36,0x36,0x5a,0x6c }, { 0x3f,0x3f,0x41,0x7e }, - { 0xf7,0xf7,0x02,0xf5 }, { 0xcc,0xcc,0x4f,0x83 }, - { 0x34,0x34,0x5c,0x68 }, { 0xa5,0xa5,0xf4,0x51 }, - { 0xe5,0xe5,0x34,0xd1 }, { 0xf1,0xf1,0x08,0xf9 }, - { 0x71,0x71,0x93,0xe2 }, { 0xd8,0xd8,0x73,0xab }, - { 0x31,0x31,0x53,0x62 }, { 0x15,0x15,0x3f,0x2a }, - { 0x04,0x04,0x0c,0x08 }, { 0xc7,0xc7,0x52,0x95 }, - { 0x23,0x23,0x65,0x46 }, { 0xc3,0xc3,0x5e,0x9d }, - { 0x18,0x18,0x28,0x30 }, { 0x96,0x96,0xa1,0x37 }, - { 0x05,0x05,0x0f,0x0a }, { 0x9a,0x9a,0xb5,0x2f }, - { 0x07,0x07,0x09,0x0e }, { 0x12,0x12,0x36,0x24 }, - { 0x80,0x80,0x9b,0x1b }, { 0xe2,0xe2,0x3d,0xdf }, - { 0xeb,0xeb,0x26,0xcd }, { 0x27,0x27,0x69,0x4e }, - { 0xb2,0xb2,0xcd,0x7f }, { 0x75,0x75,0x9f,0xea }, - { 0x09,0x09,0x1b,0x12 }, { 0x83,0x83,0x9e,0x1d }, - { 0x2c,0x2c,0x74,0x58 }, { 0x1a,0x1a,0x2e,0x34 }, - { 0x1b,0x1b,0x2d,0x36 }, { 0x6e,0x6e,0xb2,0xdc }, - { 0x5a,0x5a,0xee,0xb4 }, { 0xa0,0xa0,0xfb,0x5b }, - { 0x52,0x52,0xf6,0xa4 }, { 0x3b,0x3b,0x4d,0x76 }, - { 0xd6,0xd6,0x61,0xb7 }, { 0xb3,0xb3,0xce,0x7d }, - { 0x29,0x29,0x7b,0x52 }, { 0xe3,0xe3,0x3e,0xdd }, - { 0x2f,0x2f,0x71,0x5e }, { 0x84,0x84,0x97,0x13 }, - { 0x53,0x53,0xf5,0xa6 }, { 0xd1,0xd1,0x68,0xb9 }, - { 0x00,0x00,0x00,0x00 }, { 0xed,0xed,0x2c,0xc1 }, - { 0x20,0x20,0x60,0x40 }, { 0xfc,0xfc,0x1f,0xe3 }, - { 0xb1,0xb1,0xc8,0x79 }, { 0x5b,0x5b,0xed,0xb6 }, - { 0x6a,0x6a,0xbe,0xd4 }, { 0xcb,0xcb,0x46,0x8d }, - { 0xbe,0xbe,0xd9,0x67 }, { 0x39,0x39,0x4b,0x72 }, - { 0x4a,0x4a,0xde,0x94 }, { 0x4c,0x4c,0xd4,0x98 }, - { 0x58,0x58,0xe8,0xb0 }, { 0xcf,0xcf,0x4a,0x85 }, - { 0xd0,0xd0,0x6b,0xbb }, { 0xef,0xef,0x2a,0xc5 }, - { 0xaa,0xaa,0xe5,0x4f }, { 0xfb,0xfb,0x16,0xed }, - { 0x43,0x43,0xc5,0x86 }, { 0x4d,0x4d,0xd7,0x9a }, - { 0x33,0x33,0x55,0x66 }, { 0x85,0x85,0x94,0x11 }, - { 0x45,0x45,0xcf,0x8a }, { 0xf9,0xf9,0x10,0xe9 }, - { 0x02,0x02,0x06,0x04 }, { 0x7f,0x7f,0x81,0xfe }, - { 0x50,0x50,0xf0,0xa0 }, { 0x3c,0x3c,0x44,0x78 }, - { 0x9f,0x9f,0xba,0x25 }, { 0xa8,0xa8,0xe3,0x4b }, - { 0x51,0x51,0xf3,0xa2 }, { 0xa3,0xa3,0xfe,0x5d }, - { 0x40,0x40,0xc0,0x80 }, { 0x8f,0x8f,0x8a,0x05 }, - { 0x92,0x92,0xad,0x3f }, { 0x9d,0x9d,0xbc,0x21 }, - { 0x38,0x38,0x48,0x70 }, { 0xf5,0xf5,0x04,0xf1 }, - { 0xbc,0xbc,0xdf,0x63 }, { 0xb6,0xb6,0xc1,0x77 }, - { 0xda,0xda,0x75,0xaf }, { 0x21,0x21,0x63,0x42 }, - { 0x10,0x10,0x30,0x20 }, { 0xff,0xff,0x1a,0xe5 }, - { 0xf3,0xf3,0x0e,0xfd }, { 0xd2,0xd2,0x6d,0xbf }, - { 0xcd,0xcd,0x4c,0x81 }, { 0x0c,0x0c,0x14,0x18 }, - { 0x13,0x13,0x35,0x26 }, { 0xec,0xec,0x2f,0xc3 }, - { 0x5f,0x5f,0xe1,0xbe }, { 0x97,0x97,0xa2,0x35 }, - { 0x44,0x44,0xcc,0x88 }, { 0x17,0x17,0x39,0x2e }, - { 0xc4,0xc4,0x57,0x93 }, { 0xa7,0xa7,0xf2,0x55 }, - { 0x7e,0x7e,0x82,0xfc }, { 0x3d,0x3d,0x47,0x7a }, - { 0x64,0x64,0xac,0xc8 }, { 0x5d,0x5d,0xe7,0xba }, - { 0x19,0x19,0x2b,0x32 }, { 0x73,0x73,0x95,0xe6 }, - { 0x60,0x60,0xa0,0xc0 }, { 0x81,0x81,0x98,0x19 }, - { 0x4f,0x4f,0xd1,0x9e }, { 0xdc,0xdc,0x7f,0xa3 }, - { 0x22,0x22,0x66,0x44 }, { 0x2a,0x2a,0x7e,0x54 }, - { 0x90,0x90,0xab,0x3b }, { 0x88,0x88,0x83,0x0b }, - { 0x46,0x46,0xca,0x8c }, { 0xee,0xee,0x29,0xc7 }, - { 0xb8,0xb8,0xd3,0x6b }, { 0x14,0x14,0x3c,0x28 }, - { 0xde,0xde,0x79,0xa7 }, { 0x5e,0x5e,0xe2,0xbc }, - { 0x0b,0x0b,0x1d,0x16 }, { 0xdb,0xdb,0x76,0xad }, - { 0xe0,0xe0,0x3b,0xdb }, { 0x32,0x32,0x56,0x64 }, - { 0x3a,0x3a,0x4e,0x74 }, { 0x0a,0x0a,0x1e,0x14 }, - { 0x49,0x49,0xdb,0x92 }, { 0x06,0x06,0x0a,0x0c }, - { 0x24,0x24,0x6c,0x48 }, { 0x5c,0x5c,0xe4,0xb8 }, - { 0xc2,0xc2,0x5d,0x9f }, { 0xd3,0xd3,0x6e,0xbd }, - { 0xac,0xac,0xef,0x43 }, { 0x62,0x62,0xa6,0xc4 }, - { 0x91,0x91,0xa8,0x39 }, { 0x95,0x95,0xa4,0x31 }, - { 0xe4,0xe4,0x37,0xd3 }, { 0x79,0x79,0x8b,0xf2 }, - { 0xe7,0xe7,0x32,0xd5 }, { 0xc8,0xc8,0x43,0x8b }, - { 0x37,0x37,0x59,0x6e }, { 0x6d,0x6d,0xb7,0xda }, - { 0x8d,0x8d,0x8c,0x01 }, { 0xd5,0xd5,0x64,0xb1 }, - { 0x4e,0x4e,0xd2,0x9c }, { 0xa9,0xa9,0xe0,0x49 }, - { 0x6c,0x6c,0xb4,0xd8 }, { 0x56,0x56,0xfa,0xac }, - { 0xf4,0xf4,0x07,0xf3 }, { 0xea,0xea,0x25,0xcf }, - { 0x65,0x65,0xaf,0xca }, { 0x7a,0x7a,0x8e,0xf4 }, - { 0xae,0xae,0xe9,0x47 }, { 0x08,0x08,0x18,0x10 }, - { 0xba,0xba,0xd5,0x6f }, { 0x78,0x78,0x88,0xf0 }, - { 0x25,0x25,0x6f,0x4a }, { 0x2e,0x2e,0x72,0x5c }, - { 0x1c,0x1c,0x24,0x38 }, { 0xa6,0xa6,0xf1,0x57 }, - { 0xb4,0xb4,0xc7,0x73 }, { 0xc6,0xc6,0x51,0x97 }, - { 0xe8,0xe8,0x23,0xcb }, { 0xdd,0xdd,0x7c,0xa1 }, - { 0x74,0x74,0x9c,0xe8 }, { 0x1f,0x1f,0x21,0x3e }, - { 0x4b,0x4b,0xdd,0x96 }, { 0xbd,0xbd,0xdc,0x61 }, - { 0x8b,0x8b,0x86,0x0d }, { 0x8a,0x8a,0x85,0x0f }, - { 0x70,0x70,0x90,0xe0 }, { 0x3e,0x3e,0x42,0x7c }, - { 0xb5,0xb5,0xc4,0x71 }, { 0x66,0x66,0xaa,0xcc }, - { 0x48,0x48,0xd8,0x90 }, { 0x03,0x03,0x05,0x06 }, - { 0xf6,0xf6,0x01,0xf7 }, { 0x0e,0x0e,0x12,0x1c }, - { 0x61,0x61,0xa3,0xc2 }, { 0x35,0x35,0x5f,0x6a }, - { 0x57,0x57,0xf9,0xae }, { 0xb9,0xb9,0xd0,0x69 }, - { 0x86,0x86,0x91,0x17 }, { 0xc1,0xc1,0x58,0x99 }, - { 0x1d,0x1d,0x27,0x3a }, { 0x9e,0x9e,0xb9,0x27 }, - { 0xe1,0xe1,0x38,0xd9 }, { 0xf8,0xf8,0x13,0xeb }, - { 0x98,0x98,0xb3,0x2b }, { 0x11,0x11,0x33,0x22 }, - { 0x69,0x69,0xbb,0xd2 }, { 0xd9,0xd9,0x70,0xa9 }, - { 0x8e,0x8e,0x89,0x07 }, { 0x94,0x94,0xa7,0x33 }, - { 0x9b,0x9b,0xb6,0x2d }, { 0x1e,0x1e,0x22,0x3c }, - { 0x87,0x87,0x92,0x15 }, { 0xe9,0xe9,0x20,0xc9 }, - { 0xce,0xce,0x49,0x87 }, { 0x55,0x55,0xff,0xaa }, - { 0x28,0x28,0x78,0x50 }, { 0xdf,0xdf,0x7a,0xa5 }, - { 0x8c,0x8c,0x8f,0x03 }, { 0xa1,0xa1,0xf8,0x59 }, - { 0x89,0x89,0x80,0x09 }, { 0x0d,0x0d,0x17,0x1a }, - { 0xbf,0xbf,0xda,0x65 }, { 0xe6,0xe6,0x31,0xd7 }, - { 0x42,0x42,0xc6,0x84 }, { 0x68,0x68,0xb8,0xd0 }, - { 0x41,0x41,0xc3,0x82 }, { 0x99,0x99,0xb0,0x29 }, - { 0x2d,0x2d,0x77,0x5a }, { 0x0f,0x0f,0x11,0x1e }, - { 0xb0,0xb0,0xcb,0x7b }, { 0x54,0x54,0xfc,0xa8 }, - { 0xbb,0xbb,0xd6,0x6d }, { 0x16,0x16,0x3a,0x2c } -}; - -static const byte T5[256][4] = { - { 0x51,0xf4,0xa7,0x50 }, { 0x7e,0x41,0x65,0x53 }, - { 0x1a,0x17,0xa4,0xc3 }, { 0x3a,0x27,0x5e,0x96 }, - { 0x3b,0xab,0x6b,0xcb }, { 0x1f,0x9d,0x45,0xf1 }, - { 0xac,0xfa,0x58,0xab }, { 0x4b,0xe3,0x03,0x93 }, - { 0x20,0x30,0xfa,0x55 }, { 0xad,0x76,0x6d,0xf6 }, - { 0x88,0xcc,0x76,0x91 }, { 0xf5,0x02,0x4c,0x25 }, - { 0x4f,0xe5,0xd7,0xfc }, { 0xc5,0x2a,0xcb,0xd7 }, - { 0x26,0x35,0x44,0x80 }, { 0xb5,0x62,0xa3,0x8f }, - { 0xde,0xb1,0x5a,0x49 }, { 0x25,0xba,0x1b,0x67 }, - { 0x45,0xea,0x0e,0x98 }, { 0x5d,0xfe,0xc0,0xe1 }, - { 0xc3,0x2f,0x75,0x02 }, { 0x81,0x4c,0xf0,0x12 }, - { 0x8d,0x46,0x97,0xa3 }, { 0x6b,0xd3,0xf9,0xc6 }, - { 0x03,0x8f,0x5f,0xe7 }, { 0x15,0x92,0x9c,0x95 }, - { 0xbf,0x6d,0x7a,0xeb }, { 0x95,0x52,0x59,0xda }, - { 0xd4,0xbe,0x83,0x2d }, { 0x58,0x74,0x21,0xd3 }, - { 0x49,0xe0,0x69,0x29 }, { 0x8e,0xc9,0xc8,0x44 }, - { 0x75,0xc2,0x89,0x6a }, { 0xf4,0x8e,0x79,0x78 }, - { 0x99,0x58,0x3e,0x6b }, { 0x27,0xb9,0x71,0xdd }, - { 0xbe,0xe1,0x4f,0xb6 }, { 0xf0,0x88,0xad,0x17 }, - { 0xc9,0x20,0xac,0x66 }, { 0x7d,0xce,0x3a,0xb4 }, - { 0x63,0xdf,0x4a,0x18 }, { 0xe5,0x1a,0x31,0x82 }, - { 0x97,0x51,0x33,0x60 }, { 0x62,0x53,0x7f,0x45 }, - { 0xb1,0x64,0x77,0xe0 }, { 0xbb,0x6b,0xae,0x84 }, - { 0xfe,0x81,0xa0,0x1c }, { 0xf9,0x08,0x2b,0x94 }, - { 0x70,0x48,0x68,0x58 }, { 0x8f,0x45,0xfd,0x19 }, - { 0x94,0xde,0x6c,0x87 }, { 0x52,0x7b,0xf8,0xb7 }, - { 0xab,0x73,0xd3,0x23 }, { 0x72,0x4b,0x02,0xe2 }, - { 0xe3,0x1f,0x8f,0x57 }, { 0x66,0x55,0xab,0x2a }, - { 0xb2,0xeb,0x28,0x07 }, { 0x2f,0xb5,0xc2,0x03 }, - { 0x86,0xc5,0x7b,0x9a }, { 0xd3,0x37,0x08,0xa5 }, - { 0x30,0x28,0x87,0xf2 }, { 0x23,0xbf,0xa5,0xb2 }, - { 0x02,0x03,0x6a,0xba }, { 0xed,0x16,0x82,0x5c }, - { 0x8a,0xcf,0x1c,0x2b }, { 0xa7,0x79,0xb4,0x92 }, - { 0xf3,0x07,0xf2,0xf0 }, { 0x4e,0x69,0xe2,0xa1 }, - { 0x65,0xda,0xf4,0xcd }, { 0x06,0x05,0xbe,0xd5 }, - { 0xd1,0x34,0x62,0x1f }, { 0xc4,0xa6,0xfe,0x8a }, - { 0x34,0x2e,0x53,0x9d }, { 0xa2,0xf3,0x55,0xa0 }, - { 0x05,0x8a,0xe1,0x32 }, { 0xa4,0xf6,0xeb,0x75 }, - { 0x0b,0x83,0xec,0x39 }, { 0x40,0x60,0xef,0xaa }, - { 0x5e,0x71,0x9f,0x06 }, { 0xbd,0x6e,0x10,0x51 }, - { 0x3e,0x21,0x8a,0xf9 }, { 0x96,0xdd,0x06,0x3d }, - { 0xdd,0x3e,0x05,0xae }, { 0x4d,0xe6,0xbd,0x46 }, - { 0x91,0x54,0x8d,0xb5 }, { 0x71,0xc4,0x5d,0x05 }, - { 0x04,0x06,0xd4,0x6f }, { 0x60,0x50,0x15,0xff }, - { 0x19,0x98,0xfb,0x24 }, { 0xd6,0xbd,0xe9,0x97 }, - { 0x89,0x40,0x43,0xcc }, { 0x67,0xd9,0x9e,0x77 }, - { 0xb0,0xe8,0x42,0xbd }, { 0x07,0x89,0x8b,0x88 }, - { 0xe7,0x19,0x5b,0x38 }, { 0x79,0xc8,0xee,0xdb }, - { 0xa1,0x7c,0x0a,0x47 }, { 0x7c,0x42,0x0f,0xe9 }, - { 0xf8,0x84,0x1e,0xc9 }, { 0x00,0x00,0x00,0x00 }, - { 0x09,0x80,0x86,0x83 }, { 0x32,0x2b,0xed,0x48 }, - { 0x1e,0x11,0x70,0xac }, { 0x6c,0x5a,0x72,0x4e }, - { 0xfd,0x0e,0xff,0xfb }, { 0x0f,0x85,0x38,0x56 }, - { 0x3d,0xae,0xd5,0x1e }, { 0x36,0x2d,0x39,0x27 }, - { 0x0a,0x0f,0xd9,0x64 }, { 0x68,0x5c,0xa6,0x21 }, - { 0x9b,0x5b,0x54,0xd1 }, { 0x24,0x36,0x2e,0x3a }, - { 0x0c,0x0a,0x67,0xb1 }, { 0x93,0x57,0xe7,0x0f }, - { 0xb4,0xee,0x96,0xd2 }, { 0x1b,0x9b,0x91,0x9e }, - { 0x80,0xc0,0xc5,0x4f }, { 0x61,0xdc,0x20,0xa2 }, - { 0x5a,0x77,0x4b,0x69 }, { 0x1c,0x12,0x1a,0x16 }, - { 0xe2,0x93,0xba,0x0a }, { 0xc0,0xa0,0x2a,0xe5 }, - { 0x3c,0x22,0xe0,0x43 }, { 0x12,0x1b,0x17,0x1d }, - { 0x0e,0x09,0x0d,0x0b }, { 0xf2,0x8b,0xc7,0xad }, - { 0x2d,0xb6,0xa8,0xb9 }, { 0x14,0x1e,0xa9,0xc8 }, - { 0x57,0xf1,0x19,0x85 }, { 0xaf,0x75,0x07,0x4c }, - { 0xee,0x99,0xdd,0xbb }, { 0xa3,0x7f,0x60,0xfd }, - { 0xf7,0x01,0x26,0x9f }, { 0x5c,0x72,0xf5,0xbc }, - { 0x44,0x66,0x3b,0xc5 }, { 0x5b,0xfb,0x7e,0x34 }, - { 0x8b,0x43,0x29,0x76 }, { 0xcb,0x23,0xc6,0xdc }, - { 0xb6,0xed,0xfc,0x68 }, { 0xb8,0xe4,0xf1,0x63 }, - { 0xd7,0x31,0xdc,0xca }, { 0x42,0x63,0x85,0x10 }, - { 0x13,0x97,0x22,0x40 }, { 0x84,0xc6,0x11,0x20 }, - { 0x85,0x4a,0x24,0x7d }, { 0xd2,0xbb,0x3d,0xf8 }, - { 0xae,0xf9,0x32,0x11 }, { 0xc7,0x29,0xa1,0x6d }, - { 0x1d,0x9e,0x2f,0x4b }, { 0xdc,0xb2,0x30,0xf3 }, - { 0x0d,0x86,0x52,0xec }, { 0x77,0xc1,0xe3,0xd0 }, - { 0x2b,0xb3,0x16,0x6c }, { 0xa9,0x70,0xb9,0x99 }, - { 0x11,0x94,0x48,0xfa }, { 0x47,0xe9,0x64,0x22 }, - { 0xa8,0xfc,0x8c,0xc4 }, { 0xa0,0xf0,0x3f,0x1a }, - { 0x56,0x7d,0x2c,0xd8 }, { 0x22,0x33,0x90,0xef }, - { 0x87,0x49,0x4e,0xc7 }, { 0xd9,0x38,0xd1,0xc1 }, - { 0x8c,0xca,0xa2,0xfe }, { 0x98,0xd4,0x0b,0x36 }, - { 0xa6,0xf5,0x81,0xcf }, { 0xa5,0x7a,0xde,0x28 }, - { 0xda,0xb7,0x8e,0x26 }, { 0x3f,0xad,0xbf,0xa4 }, - { 0x2c,0x3a,0x9d,0xe4 }, { 0x50,0x78,0x92,0x0d }, - { 0x6a,0x5f,0xcc,0x9b }, { 0x54,0x7e,0x46,0x62 }, - { 0xf6,0x8d,0x13,0xc2 }, { 0x90,0xd8,0xb8,0xe8 }, - { 0x2e,0x39,0xf7,0x5e }, { 0x82,0xc3,0xaf,0xf5 }, - { 0x9f,0x5d,0x80,0xbe }, { 0x69,0xd0,0x93,0x7c }, - { 0x6f,0xd5,0x2d,0xa9 }, { 0xcf,0x25,0x12,0xb3 }, - { 0xc8,0xac,0x99,0x3b }, { 0x10,0x18,0x7d,0xa7 }, - { 0xe8,0x9c,0x63,0x6e }, { 0xdb,0x3b,0xbb,0x7b }, - { 0xcd,0x26,0x78,0x09 }, { 0x6e,0x59,0x18,0xf4 }, - { 0xec,0x9a,0xb7,0x01 }, { 0x83,0x4f,0x9a,0xa8 }, - { 0xe6,0x95,0x6e,0x65 }, { 0xaa,0xff,0xe6,0x7e }, - { 0x21,0xbc,0xcf,0x08 }, { 0xef,0x15,0xe8,0xe6 }, - { 0xba,0xe7,0x9b,0xd9 }, { 0x4a,0x6f,0x36,0xce }, - { 0xea,0x9f,0x09,0xd4 }, { 0x29,0xb0,0x7c,0xd6 }, - { 0x31,0xa4,0xb2,0xaf }, { 0x2a,0x3f,0x23,0x31 }, - { 0xc6,0xa5,0x94,0x30 }, { 0x35,0xa2,0x66,0xc0 }, - { 0x74,0x4e,0xbc,0x37 }, { 0xfc,0x82,0xca,0xa6 }, - { 0xe0,0x90,0xd0,0xb0 }, { 0x33,0xa7,0xd8,0x15 }, - { 0xf1,0x04,0x98,0x4a }, { 0x41,0xec,0xda,0xf7 }, - { 0x7f,0xcd,0x50,0x0e }, { 0x17,0x91,0xf6,0x2f }, - { 0x76,0x4d,0xd6,0x8d }, { 0x43,0xef,0xb0,0x4d }, - { 0xcc,0xaa,0x4d,0x54 }, { 0xe4,0x96,0x04,0xdf }, - { 0x9e,0xd1,0xb5,0xe3 }, { 0x4c,0x6a,0x88,0x1b }, - { 0xc1,0x2c,0x1f,0xb8 }, { 0x46,0x65,0x51,0x7f }, - { 0x9d,0x5e,0xea,0x04 }, { 0x01,0x8c,0x35,0x5d }, - { 0xfa,0x87,0x74,0x73 }, { 0xfb,0x0b,0x41,0x2e }, - { 0xb3,0x67,0x1d,0x5a }, { 0x92,0xdb,0xd2,0x52 }, - { 0xe9,0x10,0x56,0x33 }, { 0x6d,0xd6,0x47,0x13 }, - { 0x9a,0xd7,0x61,0x8c }, { 0x37,0xa1,0x0c,0x7a }, - { 0x59,0xf8,0x14,0x8e }, { 0xeb,0x13,0x3c,0x89 }, - { 0xce,0xa9,0x27,0xee }, { 0xb7,0x61,0xc9,0x35 }, - { 0xe1,0x1c,0xe5,0xed }, { 0x7a,0x47,0xb1,0x3c }, - { 0x9c,0xd2,0xdf,0x59 }, { 0x55,0xf2,0x73,0x3f }, - { 0x18,0x14,0xce,0x79 }, { 0x73,0xc7,0x37,0xbf }, - { 0x53,0xf7,0xcd,0xea }, { 0x5f,0xfd,0xaa,0x5b }, - { 0xdf,0x3d,0x6f,0x14 }, { 0x78,0x44,0xdb,0x86 }, - { 0xca,0xaf,0xf3,0x81 }, { 0xb9,0x68,0xc4,0x3e }, - { 0x38,0x24,0x34,0x2c }, { 0xc2,0xa3,0x40,0x5f }, - { 0x16,0x1d,0xc3,0x72 }, { 0xbc,0xe2,0x25,0x0c }, - { 0x28,0x3c,0x49,0x8b }, { 0xff,0x0d,0x95,0x41 }, - { 0x39,0xa8,0x01,0x71 }, { 0x08,0x0c,0xb3,0xde }, - { 0xd8,0xb4,0xe4,0x9c }, { 0x64,0x56,0xc1,0x90 }, - { 0x7b,0xcb,0x84,0x61 }, { 0xd5,0x32,0xb6,0x70 }, - { 0x48,0x6c,0x5c,0x74 }, { 0xd0,0xb8,0x57,0x42 } -}; - -static const byte T6[256][4] = { - { 0x50,0x51,0xf4,0xa7 }, { 0x53,0x7e,0x41,0x65 }, - { 0xc3,0x1a,0x17,0xa4 }, { 0x96,0x3a,0x27,0x5e }, - { 0xcb,0x3b,0xab,0x6b }, { 0xf1,0x1f,0x9d,0x45 }, - { 0xab,0xac,0xfa,0x58 }, { 0x93,0x4b,0xe3,0x03 }, - { 0x55,0x20,0x30,0xfa }, { 0xf6,0xad,0x76,0x6d }, - { 0x91,0x88,0xcc,0x76 }, { 0x25,0xf5,0x02,0x4c }, - { 0xfc,0x4f,0xe5,0xd7 }, { 0xd7,0xc5,0x2a,0xcb }, - { 0x80,0x26,0x35,0x44 }, { 0x8f,0xb5,0x62,0xa3 }, - { 0x49,0xde,0xb1,0x5a }, { 0x67,0x25,0xba,0x1b }, - { 0x98,0x45,0xea,0x0e }, { 0xe1,0x5d,0xfe,0xc0 }, - { 0x02,0xc3,0x2f,0x75 }, { 0x12,0x81,0x4c,0xf0 }, - { 0xa3,0x8d,0x46,0x97 }, { 0xc6,0x6b,0xd3,0xf9 }, - { 0xe7,0x03,0x8f,0x5f }, { 0x95,0x15,0x92,0x9c }, - { 0xeb,0xbf,0x6d,0x7a }, { 0xda,0x95,0x52,0x59 }, - { 0x2d,0xd4,0xbe,0x83 }, { 0xd3,0x58,0x74,0x21 }, - { 0x29,0x49,0xe0,0x69 }, { 0x44,0x8e,0xc9,0xc8 }, - { 0x6a,0x75,0xc2,0x89 }, { 0x78,0xf4,0x8e,0x79 }, - { 0x6b,0x99,0x58,0x3e }, { 0xdd,0x27,0xb9,0x71 }, - { 0xb6,0xbe,0xe1,0x4f }, { 0x17,0xf0,0x88,0xad }, - { 0x66,0xc9,0x20,0xac }, { 0xb4,0x7d,0xce,0x3a }, - { 0x18,0x63,0xdf,0x4a }, { 0x82,0xe5,0x1a,0x31 }, - { 0x60,0x97,0x51,0x33 }, { 0x45,0x62,0x53,0x7f }, - { 0xe0,0xb1,0x64,0x77 }, { 0x84,0xbb,0x6b,0xae }, - { 0x1c,0xfe,0x81,0xa0 }, { 0x94,0xf9,0x08,0x2b }, - { 0x58,0x70,0x48,0x68 }, { 0x19,0x8f,0x45,0xfd }, - { 0x87,0x94,0xde,0x6c }, { 0xb7,0x52,0x7b,0xf8 }, - { 0x23,0xab,0x73,0xd3 }, { 0xe2,0x72,0x4b,0x02 }, - { 0x57,0xe3,0x1f,0x8f }, { 0x2a,0x66,0x55,0xab }, - { 0x07,0xb2,0xeb,0x28 }, { 0x03,0x2f,0xb5,0xc2 }, - { 0x9a,0x86,0xc5,0x7b }, { 0xa5,0xd3,0x37,0x08 }, - { 0xf2,0x30,0x28,0x87 }, { 0xb2,0x23,0xbf,0xa5 }, - { 0xba,0x02,0x03,0x6a }, { 0x5c,0xed,0x16,0x82 }, - { 0x2b,0x8a,0xcf,0x1c }, { 0x92,0xa7,0x79,0xb4 }, - { 0xf0,0xf3,0x07,0xf2 }, { 0xa1,0x4e,0x69,0xe2 }, - { 0xcd,0x65,0xda,0xf4 }, { 0xd5,0x06,0x05,0xbe }, - { 0x1f,0xd1,0x34,0x62 }, { 0x8a,0xc4,0xa6,0xfe }, - { 0x9d,0x34,0x2e,0x53 }, { 0xa0,0xa2,0xf3,0x55 }, - { 0x32,0x05,0x8a,0xe1 }, { 0x75,0xa4,0xf6,0xeb }, - { 0x39,0x0b,0x83,0xec }, { 0xaa,0x40,0x60,0xef }, - { 0x06,0x5e,0x71,0x9f }, { 0x51,0xbd,0x6e,0x10 }, - { 0xf9,0x3e,0x21,0x8a }, { 0x3d,0x96,0xdd,0x06 }, - { 0xae,0xdd,0x3e,0x05 }, { 0x46,0x4d,0xe6,0xbd }, - { 0xb5,0x91,0x54,0x8d }, { 0x05,0x71,0xc4,0x5d }, - { 0x6f,0x04,0x06,0xd4 }, { 0xff,0x60,0x50,0x15 }, - { 0x24,0x19,0x98,0xfb }, { 0x97,0xd6,0xbd,0xe9 }, - { 0xcc,0x89,0x40,0x43 }, { 0x77,0x67,0xd9,0x9e }, - { 0xbd,0xb0,0xe8,0x42 }, { 0x88,0x07,0x89,0x8b }, - { 0x38,0xe7,0x19,0x5b }, { 0xdb,0x79,0xc8,0xee }, - { 0x47,0xa1,0x7c,0x0a }, { 0xe9,0x7c,0x42,0x0f }, - { 0xc9,0xf8,0x84,0x1e }, { 0x00,0x00,0x00,0x00 }, - { 0x83,0x09,0x80,0x86 }, { 0x48,0x32,0x2b,0xed }, - { 0xac,0x1e,0x11,0x70 }, { 0x4e,0x6c,0x5a,0x72 }, - { 0xfb,0xfd,0x0e,0xff }, { 0x56,0x0f,0x85,0x38 }, - { 0x1e,0x3d,0xae,0xd5 }, { 0x27,0x36,0x2d,0x39 }, - { 0x64,0x0a,0x0f,0xd9 }, { 0x21,0x68,0x5c,0xa6 }, - { 0xd1,0x9b,0x5b,0x54 }, { 0x3a,0x24,0x36,0x2e }, - { 0xb1,0x0c,0x0a,0x67 }, { 0x0f,0x93,0x57,0xe7 }, - { 0xd2,0xb4,0xee,0x96 }, { 0x9e,0x1b,0x9b,0x91 }, - { 0x4f,0x80,0xc0,0xc5 }, { 0xa2,0x61,0xdc,0x20 }, - { 0x69,0x5a,0x77,0x4b }, { 0x16,0x1c,0x12,0x1a }, - { 0x0a,0xe2,0x93,0xba }, { 0xe5,0xc0,0xa0,0x2a }, - { 0x43,0x3c,0x22,0xe0 }, { 0x1d,0x12,0x1b,0x17 }, - { 0x0b,0x0e,0x09,0x0d }, { 0xad,0xf2,0x8b,0xc7 }, - { 0xb9,0x2d,0xb6,0xa8 }, { 0xc8,0x14,0x1e,0xa9 }, - { 0x85,0x57,0xf1,0x19 }, { 0x4c,0xaf,0x75,0x07 }, - { 0xbb,0xee,0x99,0xdd }, { 0xfd,0xa3,0x7f,0x60 }, - { 0x9f,0xf7,0x01,0x26 }, { 0xbc,0x5c,0x72,0xf5 }, - { 0xc5,0x44,0x66,0x3b }, { 0x34,0x5b,0xfb,0x7e }, - { 0x76,0x8b,0x43,0x29 }, { 0xdc,0xcb,0x23,0xc6 }, - { 0x68,0xb6,0xed,0xfc }, { 0x63,0xb8,0xe4,0xf1 }, - { 0xca,0xd7,0x31,0xdc }, { 0x10,0x42,0x63,0x85 }, - { 0x40,0x13,0x97,0x22 }, { 0x20,0x84,0xc6,0x11 }, - { 0x7d,0x85,0x4a,0x24 }, { 0xf8,0xd2,0xbb,0x3d }, - { 0x11,0xae,0xf9,0x32 }, { 0x6d,0xc7,0x29,0xa1 }, - { 0x4b,0x1d,0x9e,0x2f }, { 0xf3,0xdc,0xb2,0x30 }, - { 0xec,0x0d,0x86,0x52 }, { 0xd0,0x77,0xc1,0xe3 }, - { 0x6c,0x2b,0xb3,0x16 }, { 0x99,0xa9,0x70,0xb9 }, - { 0xfa,0x11,0x94,0x48 }, { 0x22,0x47,0xe9,0x64 }, - { 0xc4,0xa8,0xfc,0x8c }, { 0x1a,0xa0,0xf0,0x3f }, - { 0xd8,0x56,0x7d,0x2c }, { 0xef,0x22,0x33,0x90 }, - { 0xc7,0x87,0x49,0x4e }, { 0xc1,0xd9,0x38,0xd1 }, - { 0xfe,0x8c,0xca,0xa2 }, { 0x36,0x98,0xd4,0x0b }, - { 0xcf,0xa6,0xf5,0x81 }, { 0x28,0xa5,0x7a,0xde }, - { 0x26,0xda,0xb7,0x8e }, { 0xa4,0x3f,0xad,0xbf }, - { 0xe4,0x2c,0x3a,0x9d }, { 0x0d,0x50,0x78,0x92 }, - { 0x9b,0x6a,0x5f,0xcc }, { 0x62,0x54,0x7e,0x46 }, - { 0xc2,0xf6,0x8d,0x13 }, { 0xe8,0x90,0xd8,0xb8 }, - { 0x5e,0x2e,0x39,0xf7 }, { 0xf5,0x82,0xc3,0xaf }, - { 0xbe,0x9f,0x5d,0x80 }, { 0x7c,0x69,0xd0,0x93 }, - { 0xa9,0x6f,0xd5,0x2d }, { 0xb3,0xcf,0x25,0x12 }, - { 0x3b,0xc8,0xac,0x99 }, { 0xa7,0x10,0x18,0x7d }, - { 0x6e,0xe8,0x9c,0x63 }, { 0x7b,0xdb,0x3b,0xbb }, - { 0x09,0xcd,0x26,0x78 }, { 0xf4,0x6e,0x59,0x18 }, - { 0x01,0xec,0x9a,0xb7 }, { 0xa8,0x83,0x4f,0x9a }, - { 0x65,0xe6,0x95,0x6e }, { 0x7e,0xaa,0xff,0xe6 }, - { 0x08,0x21,0xbc,0xcf }, { 0xe6,0xef,0x15,0xe8 }, - { 0xd9,0xba,0xe7,0x9b }, { 0xce,0x4a,0x6f,0x36 }, - { 0xd4,0xea,0x9f,0x09 }, { 0xd6,0x29,0xb0,0x7c }, - { 0xaf,0x31,0xa4,0xb2 }, { 0x31,0x2a,0x3f,0x23 }, - { 0x30,0xc6,0xa5,0x94 }, { 0xc0,0x35,0xa2,0x66 }, - { 0x37,0x74,0x4e,0xbc }, { 0xa6,0xfc,0x82,0xca }, - { 0xb0,0xe0,0x90,0xd0 }, { 0x15,0x33,0xa7,0xd8 }, - { 0x4a,0xf1,0x04,0x98 }, { 0xf7,0x41,0xec,0xda }, - { 0x0e,0x7f,0xcd,0x50 }, { 0x2f,0x17,0x91,0xf6 }, - { 0x8d,0x76,0x4d,0xd6 }, { 0x4d,0x43,0xef,0xb0 }, - { 0x54,0xcc,0xaa,0x4d }, { 0xdf,0xe4,0x96,0x04 }, - { 0xe3,0x9e,0xd1,0xb5 }, { 0x1b,0x4c,0x6a,0x88 }, - { 0xb8,0xc1,0x2c,0x1f }, { 0x7f,0x46,0x65,0x51 }, - { 0x04,0x9d,0x5e,0xea }, { 0x5d,0x01,0x8c,0x35 }, - { 0x73,0xfa,0x87,0x74 }, { 0x2e,0xfb,0x0b,0x41 }, - { 0x5a,0xb3,0x67,0x1d }, { 0x52,0x92,0xdb,0xd2 }, - { 0x33,0xe9,0x10,0x56 }, { 0x13,0x6d,0xd6,0x47 }, - { 0x8c,0x9a,0xd7,0x61 }, { 0x7a,0x37,0xa1,0x0c }, - { 0x8e,0x59,0xf8,0x14 }, { 0x89,0xeb,0x13,0x3c }, - { 0xee,0xce,0xa9,0x27 }, { 0x35,0xb7,0x61,0xc9 }, - { 0xed,0xe1,0x1c,0xe5 }, { 0x3c,0x7a,0x47,0xb1 }, - { 0x59,0x9c,0xd2,0xdf }, { 0x3f,0x55,0xf2,0x73 }, - { 0x79,0x18,0x14,0xce }, { 0xbf,0x73,0xc7,0x37 }, - { 0xea,0x53,0xf7,0xcd }, { 0x5b,0x5f,0xfd,0xaa }, - { 0x14,0xdf,0x3d,0x6f }, { 0x86,0x78,0x44,0xdb }, - { 0x81,0xca,0xaf,0xf3 }, { 0x3e,0xb9,0x68,0xc4 }, - { 0x2c,0x38,0x24,0x34 }, { 0x5f,0xc2,0xa3,0x40 }, - { 0x72,0x16,0x1d,0xc3 }, { 0x0c,0xbc,0xe2,0x25 }, - { 0x8b,0x28,0x3c,0x49 }, { 0x41,0xff,0x0d,0x95 }, - { 0x71,0x39,0xa8,0x01 }, { 0xde,0x08,0x0c,0xb3 }, - { 0x9c,0xd8,0xb4,0xe4 }, { 0x90,0x64,0x56,0xc1 }, - { 0x61,0x7b,0xcb,0x84 }, { 0x70,0xd5,0x32,0xb6 }, - { 0x74,0x48,0x6c,0x5c }, { 0x42,0xd0,0xb8,0x57 } -}; - -static const byte T7[256][4] = { - { 0xa7,0x50,0x51,0xf4 }, { 0x65,0x53,0x7e,0x41 }, - { 0xa4,0xc3,0x1a,0x17 }, { 0x5e,0x96,0x3a,0x27 }, - { 0x6b,0xcb,0x3b,0xab }, { 0x45,0xf1,0x1f,0x9d }, - { 0x58,0xab,0xac,0xfa }, { 0x03,0x93,0x4b,0xe3 }, - { 0xfa,0x55,0x20,0x30 }, { 0x6d,0xf6,0xad,0x76 }, - { 0x76,0x91,0x88,0xcc }, { 0x4c,0x25,0xf5,0x02 }, - { 0xd7,0xfc,0x4f,0xe5 }, { 0xcb,0xd7,0xc5,0x2a }, - { 0x44,0x80,0x26,0x35 }, { 0xa3,0x8f,0xb5,0x62 }, - { 0x5a,0x49,0xde,0xb1 }, { 0x1b,0x67,0x25,0xba }, - { 0x0e,0x98,0x45,0xea }, { 0xc0,0xe1,0x5d,0xfe }, - { 0x75,0x02,0xc3,0x2f }, { 0xf0,0x12,0x81,0x4c }, - { 0x97,0xa3,0x8d,0x46 }, { 0xf9,0xc6,0x6b,0xd3 }, - { 0x5f,0xe7,0x03,0x8f }, { 0x9c,0x95,0x15,0x92 }, - { 0x7a,0xeb,0xbf,0x6d }, { 0x59,0xda,0x95,0x52 }, - { 0x83,0x2d,0xd4,0xbe }, { 0x21,0xd3,0x58,0x74 }, - { 0x69,0x29,0x49,0xe0 }, { 0xc8,0x44,0x8e,0xc9 }, - { 0x89,0x6a,0x75,0xc2 }, { 0x79,0x78,0xf4,0x8e }, - { 0x3e,0x6b,0x99,0x58 }, { 0x71,0xdd,0x27,0xb9 }, - { 0x4f,0xb6,0xbe,0xe1 }, { 0xad,0x17,0xf0,0x88 }, - { 0xac,0x66,0xc9,0x20 }, { 0x3a,0xb4,0x7d,0xce }, - { 0x4a,0x18,0x63,0xdf }, { 0x31,0x82,0xe5,0x1a }, - { 0x33,0x60,0x97,0x51 }, { 0x7f,0x45,0x62,0x53 }, - { 0x77,0xe0,0xb1,0x64 }, { 0xae,0x84,0xbb,0x6b }, - { 0xa0,0x1c,0xfe,0x81 }, { 0x2b,0x94,0xf9,0x08 }, - { 0x68,0x58,0x70,0x48 }, { 0xfd,0x19,0x8f,0x45 }, - { 0x6c,0x87,0x94,0xde }, { 0xf8,0xb7,0x52,0x7b }, - { 0xd3,0x23,0xab,0x73 }, { 0x02,0xe2,0x72,0x4b }, - { 0x8f,0x57,0xe3,0x1f }, { 0xab,0x2a,0x66,0x55 }, - { 0x28,0x07,0xb2,0xeb }, { 0xc2,0x03,0x2f,0xb5 }, - { 0x7b,0x9a,0x86,0xc5 }, { 0x08,0xa5,0xd3,0x37 }, - { 0x87,0xf2,0x30,0x28 }, { 0xa5,0xb2,0x23,0xbf }, - { 0x6a,0xba,0x02,0x03 }, { 0x82,0x5c,0xed,0x16 }, - { 0x1c,0x2b,0x8a,0xcf }, { 0xb4,0x92,0xa7,0x79 }, - { 0xf2,0xf0,0xf3,0x07 }, { 0xe2,0xa1,0x4e,0x69 }, - { 0xf4,0xcd,0x65,0xda }, { 0xbe,0xd5,0x06,0x05 }, - { 0x62,0x1f,0xd1,0x34 }, { 0xfe,0x8a,0xc4,0xa6 }, - { 0x53,0x9d,0x34,0x2e }, { 0x55,0xa0,0xa2,0xf3 }, - { 0xe1,0x32,0x05,0x8a }, { 0xeb,0x75,0xa4,0xf6 }, - { 0xec,0x39,0x0b,0x83 }, { 0xef,0xaa,0x40,0x60 }, - { 0x9f,0x06,0x5e,0x71 }, { 0x10,0x51,0xbd,0x6e }, - { 0x8a,0xf9,0x3e,0x21 }, { 0x06,0x3d,0x96,0xdd }, - { 0x05,0xae,0xdd,0x3e }, { 0xbd,0x46,0x4d,0xe6 }, - { 0x8d,0xb5,0x91,0x54 }, { 0x5d,0x05,0x71,0xc4 }, - { 0xd4,0x6f,0x04,0x06 }, { 0x15,0xff,0x60,0x50 }, - { 0xfb,0x24,0x19,0x98 }, { 0xe9,0x97,0xd6,0xbd }, - { 0x43,0xcc,0x89,0x40 }, { 0x9e,0x77,0x67,0xd9 }, - { 0x42,0xbd,0xb0,0xe8 }, { 0x8b,0x88,0x07,0x89 }, - { 0x5b,0x38,0xe7,0x19 }, { 0xee,0xdb,0x79,0xc8 }, - { 0x0a,0x47,0xa1,0x7c }, { 0x0f,0xe9,0x7c,0x42 }, - { 0x1e,0xc9,0xf8,0x84 }, { 0x00,0x00,0x00,0x00 }, - { 0x86,0x83,0x09,0x80 }, { 0xed,0x48,0x32,0x2b }, - { 0x70,0xac,0x1e,0x11 }, { 0x72,0x4e,0x6c,0x5a }, - { 0xff,0xfb,0xfd,0x0e }, { 0x38,0x56,0x0f,0x85 }, - { 0xd5,0x1e,0x3d,0xae }, { 0x39,0x27,0x36,0x2d }, - { 0xd9,0x64,0x0a,0x0f }, { 0xa6,0x21,0x68,0x5c }, - { 0x54,0xd1,0x9b,0x5b }, { 0x2e,0x3a,0x24,0x36 }, - { 0x67,0xb1,0x0c,0x0a }, { 0xe7,0x0f,0x93,0x57 }, - { 0x96,0xd2,0xb4,0xee }, { 0x91,0x9e,0x1b,0x9b }, - { 0xc5,0x4f,0x80,0xc0 }, { 0x20,0xa2,0x61,0xdc }, - { 0x4b,0x69,0x5a,0x77 }, { 0x1a,0x16,0x1c,0x12 }, - { 0xba,0x0a,0xe2,0x93 }, { 0x2a,0xe5,0xc0,0xa0 }, - { 0xe0,0x43,0x3c,0x22 }, { 0x17,0x1d,0x12,0x1b }, - { 0x0d,0x0b,0x0e,0x09 }, { 0xc7,0xad,0xf2,0x8b }, - { 0xa8,0xb9,0x2d,0xb6 }, { 0xa9,0xc8,0x14,0x1e }, - { 0x19,0x85,0x57,0xf1 }, { 0x07,0x4c,0xaf,0x75 }, - { 0xdd,0xbb,0xee,0x99 }, { 0x60,0xfd,0xa3,0x7f }, - { 0x26,0x9f,0xf7,0x01 }, { 0xf5,0xbc,0x5c,0x72 }, - { 0x3b,0xc5,0x44,0x66 }, { 0x7e,0x34,0x5b,0xfb }, - { 0x29,0x76,0x8b,0x43 }, { 0xc6,0xdc,0xcb,0x23 }, - { 0xfc,0x68,0xb6,0xed }, { 0xf1,0x63,0xb8,0xe4 }, - { 0xdc,0xca,0xd7,0x31 }, { 0x85,0x10,0x42,0x63 }, - { 0x22,0x40,0x13,0x97 }, { 0x11,0x20,0x84,0xc6 }, - { 0x24,0x7d,0x85,0x4a }, { 0x3d,0xf8,0xd2,0xbb }, - { 0x32,0x11,0xae,0xf9 }, { 0xa1,0x6d,0xc7,0x29 }, - { 0x2f,0x4b,0x1d,0x9e }, { 0x30,0xf3,0xdc,0xb2 }, - { 0x52,0xec,0x0d,0x86 }, { 0xe3,0xd0,0x77,0xc1 }, - { 0x16,0x6c,0x2b,0xb3 }, { 0xb9,0x99,0xa9,0x70 }, - { 0x48,0xfa,0x11,0x94 }, { 0x64,0x22,0x47,0xe9 }, - { 0x8c,0xc4,0xa8,0xfc }, { 0x3f,0x1a,0xa0,0xf0 }, - { 0x2c,0xd8,0x56,0x7d }, { 0x90,0xef,0x22,0x33 }, - { 0x4e,0xc7,0x87,0x49 }, { 0xd1,0xc1,0xd9,0x38 }, - { 0xa2,0xfe,0x8c,0xca }, { 0x0b,0x36,0x98,0xd4 }, - { 0x81,0xcf,0xa6,0xf5 }, { 0xde,0x28,0xa5,0x7a }, - { 0x8e,0x26,0xda,0xb7 }, { 0xbf,0xa4,0x3f,0xad }, - { 0x9d,0xe4,0x2c,0x3a }, { 0x92,0x0d,0x50,0x78 }, - { 0xcc,0x9b,0x6a,0x5f }, { 0x46,0x62,0x54,0x7e }, - { 0x13,0xc2,0xf6,0x8d }, { 0xb8,0xe8,0x90,0xd8 }, - { 0xf7,0x5e,0x2e,0x39 }, { 0xaf,0xf5,0x82,0xc3 }, - { 0x80,0xbe,0x9f,0x5d }, { 0x93,0x7c,0x69,0xd0 }, - { 0x2d,0xa9,0x6f,0xd5 }, { 0x12,0xb3,0xcf,0x25 }, - { 0x99,0x3b,0xc8,0xac }, { 0x7d,0xa7,0x10,0x18 }, - { 0x63,0x6e,0xe8,0x9c }, { 0xbb,0x7b,0xdb,0x3b }, - { 0x78,0x09,0xcd,0x26 }, { 0x18,0xf4,0x6e,0x59 }, - { 0xb7,0x01,0xec,0x9a }, { 0x9a,0xa8,0x83,0x4f }, - { 0x6e,0x65,0xe6,0x95 }, { 0xe6,0x7e,0xaa,0xff }, - { 0xcf,0x08,0x21,0xbc }, { 0xe8,0xe6,0xef,0x15 }, - { 0x9b,0xd9,0xba,0xe7 }, { 0x36,0xce,0x4a,0x6f }, - { 0x09,0xd4,0xea,0x9f }, { 0x7c,0xd6,0x29,0xb0 }, - { 0xb2,0xaf,0x31,0xa4 }, { 0x23,0x31,0x2a,0x3f }, - { 0x94,0x30,0xc6,0xa5 }, { 0x66,0xc0,0x35,0xa2 }, - { 0xbc,0x37,0x74,0x4e }, { 0xca,0xa6,0xfc,0x82 }, - { 0xd0,0xb0,0xe0,0x90 }, { 0xd8,0x15,0x33,0xa7 }, - { 0x98,0x4a,0xf1,0x04 }, { 0xda,0xf7,0x41,0xec }, - { 0x50,0x0e,0x7f,0xcd }, { 0xf6,0x2f,0x17,0x91 }, - { 0xd6,0x8d,0x76,0x4d }, { 0xb0,0x4d,0x43,0xef }, - { 0x4d,0x54,0xcc,0xaa }, { 0x04,0xdf,0xe4,0x96 }, - { 0xb5,0xe3,0x9e,0xd1 }, { 0x88,0x1b,0x4c,0x6a }, - { 0x1f,0xb8,0xc1,0x2c }, { 0x51,0x7f,0x46,0x65 }, - { 0xea,0x04,0x9d,0x5e }, { 0x35,0x5d,0x01,0x8c }, - { 0x74,0x73,0xfa,0x87 }, { 0x41,0x2e,0xfb,0x0b }, - { 0x1d,0x5a,0xb3,0x67 }, { 0xd2,0x52,0x92,0xdb }, - { 0x56,0x33,0xe9,0x10 }, { 0x47,0x13,0x6d,0xd6 }, - { 0x61,0x8c,0x9a,0xd7 }, { 0x0c,0x7a,0x37,0xa1 }, - { 0x14,0x8e,0x59,0xf8 }, { 0x3c,0x89,0xeb,0x13 }, - { 0x27,0xee,0xce,0xa9 }, { 0xc9,0x35,0xb7,0x61 }, - { 0xe5,0xed,0xe1,0x1c }, { 0xb1,0x3c,0x7a,0x47 }, - { 0xdf,0x59,0x9c,0xd2 }, { 0x73,0x3f,0x55,0xf2 }, - { 0xce,0x79,0x18,0x14 }, { 0x37,0xbf,0x73,0xc7 }, - { 0xcd,0xea,0x53,0xf7 }, { 0xaa,0x5b,0x5f,0xfd }, - { 0x6f,0x14,0xdf,0x3d }, { 0xdb,0x86,0x78,0x44 }, - { 0xf3,0x81,0xca,0xaf }, { 0xc4,0x3e,0xb9,0x68 }, - { 0x34,0x2c,0x38,0x24 }, { 0x40,0x5f,0xc2,0xa3 }, - { 0xc3,0x72,0x16,0x1d }, { 0x25,0x0c,0xbc,0xe2 }, - { 0x49,0x8b,0x28,0x3c }, { 0x95,0x41,0xff,0x0d }, - { 0x01,0x71,0x39,0xa8 }, { 0xb3,0xde,0x08,0x0c }, - { 0xe4,0x9c,0xd8,0xb4 }, { 0xc1,0x90,0x64,0x56 }, - { 0x84,0x61,0x7b,0xcb }, { 0xb6,0x70,0xd5,0x32 }, - { 0x5c,0x74,0x48,0x6c }, { 0x57,0x42,0xd0,0xb8 } -}; - -static const byte T8[256][4] = { - { 0xf4,0xa7,0x50,0x51 }, { 0x41,0x65,0x53,0x7e }, - { 0x17,0xa4,0xc3,0x1a }, { 0x27,0x5e,0x96,0x3a }, - { 0xab,0x6b,0xcb,0x3b }, { 0x9d,0x45,0xf1,0x1f }, - { 0xfa,0x58,0xab,0xac }, { 0xe3,0x03,0x93,0x4b }, - { 0x30,0xfa,0x55,0x20 }, { 0x76,0x6d,0xf6,0xad }, - { 0xcc,0x76,0x91,0x88 }, { 0x02,0x4c,0x25,0xf5 }, - { 0xe5,0xd7,0xfc,0x4f }, { 0x2a,0xcb,0xd7,0xc5 }, - { 0x35,0x44,0x80,0x26 }, { 0x62,0xa3,0x8f,0xb5 }, - { 0xb1,0x5a,0x49,0xde }, { 0xba,0x1b,0x67,0x25 }, - { 0xea,0x0e,0x98,0x45 }, { 0xfe,0xc0,0xe1,0x5d }, - { 0x2f,0x75,0x02,0xc3 }, { 0x4c,0xf0,0x12,0x81 }, - { 0x46,0x97,0xa3,0x8d }, { 0xd3,0xf9,0xc6,0x6b }, - { 0x8f,0x5f,0xe7,0x03 }, { 0x92,0x9c,0x95,0x15 }, - { 0x6d,0x7a,0xeb,0xbf }, { 0x52,0x59,0xda,0x95 }, - { 0xbe,0x83,0x2d,0xd4 }, { 0x74,0x21,0xd3,0x58 }, - { 0xe0,0x69,0x29,0x49 }, { 0xc9,0xc8,0x44,0x8e }, - { 0xc2,0x89,0x6a,0x75 }, { 0x8e,0x79,0x78,0xf4 }, - { 0x58,0x3e,0x6b,0x99 }, { 0xb9,0x71,0xdd,0x27 }, - { 0xe1,0x4f,0xb6,0xbe }, { 0x88,0xad,0x17,0xf0 }, - { 0x20,0xac,0x66,0xc9 }, { 0xce,0x3a,0xb4,0x7d }, - { 0xdf,0x4a,0x18,0x63 }, { 0x1a,0x31,0x82,0xe5 }, - { 0x51,0x33,0x60,0x97 }, { 0x53,0x7f,0x45,0x62 }, - { 0x64,0x77,0xe0,0xb1 }, { 0x6b,0xae,0x84,0xbb }, - { 0x81,0xa0,0x1c,0xfe }, { 0x08,0x2b,0x94,0xf9 }, - { 0x48,0x68,0x58,0x70 }, { 0x45,0xfd,0x19,0x8f }, - { 0xde,0x6c,0x87,0x94 }, { 0x7b,0xf8,0xb7,0x52 }, - { 0x73,0xd3,0x23,0xab }, { 0x4b,0x02,0xe2,0x72 }, - { 0x1f,0x8f,0x57,0xe3 }, { 0x55,0xab,0x2a,0x66 }, - { 0xeb,0x28,0x07,0xb2 }, { 0xb5,0xc2,0x03,0x2f }, - { 0xc5,0x7b,0x9a,0x86 }, { 0x37,0x08,0xa5,0xd3 }, - { 0x28,0x87,0xf2,0x30 }, { 0xbf,0xa5,0xb2,0x23 }, - { 0x03,0x6a,0xba,0x02 }, { 0x16,0x82,0x5c,0xed }, - { 0xcf,0x1c,0x2b,0x8a }, { 0x79,0xb4,0x92,0xa7 }, - { 0x07,0xf2,0xf0,0xf3 }, { 0x69,0xe2,0xa1,0x4e }, - { 0xda,0xf4,0xcd,0x65 }, { 0x05,0xbe,0xd5,0x06 }, - { 0x34,0x62,0x1f,0xd1 }, { 0xa6,0xfe,0x8a,0xc4 }, - { 0x2e,0x53,0x9d,0x34 }, { 0xf3,0x55,0xa0,0xa2 }, - { 0x8a,0xe1,0x32,0x05 }, { 0xf6,0xeb,0x75,0xa4 }, - { 0x83,0xec,0x39,0x0b }, { 0x60,0xef,0xaa,0x40 }, - { 0x71,0x9f,0x06,0x5e }, { 0x6e,0x10,0x51,0xbd }, - { 0x21,0x8a,0xf9,0x3e }, { 0xdd,0x06,0x3d,0x96 }, - { 0x3e,0x05,0xae,0xdd }, { 0xe6,0xbd,0x46,0x4d }, - { 0x54,0x8d,0xb5,0x91 }, { 0xc4,0x5d,0x05,0x71 }, - { 0x06,0xd4,0x6f,0x04 }, { 0x50,0x15,0xff,0x60 }, - { 0x98,0xfb,0x24,0x19 }, { 0xbd,0xe9,0x97,0xd6 }, - { 0x40,0x43,0xcc,0x89 }, { 0xd9,0x9e,0x77,0x67 }, - { 0xe8,0x42,0xbd,0xb0 }, { 0x89,0x8b,0x88,0x07 }, - { 0x19,0x5b,0x38,0xe7 }, { 0xc8,0xee,0xdb,0x79 }, - { 0x7c,0x0a,0x47,0xa1 }, { 0x42,0x0f,0xe9,0x7c }, - { 0x84,0x1e,0xc9,0xf8 }, { 0x00,0x00,0x00,0x00 }, - { 0x80,0x86,0x83,0x09 }, { 0x2b,0xed,0x48,0x32 }, - { 0x11,0x70,0xac,0x1e }, { 0x5a,0x72,0x4e,0x6c }, - { 0x0e,0xff,0xfb,0xfd }, { 0x85,0x38,0x56,0x0f }, - { 0xae,0xd5,0x1e,0x3d }, { 0x2d,0x39,0x27,0x36 }, - { 0x0f,0xd9,0x64,0x0a }, { 0x5c,0xa6,0x21,0x68 }, - { 0x5b,0x54,0xd1,0x9b }, { 0x36,0x2e,0x3a,0x24 }, - { 0x0a,0x67,0xb1,0x0c }, { 0x57,0xe7,0x0f,0x93 }, - { 0xee,0x96,0xd2,0xb4 }, { 0x9b,0x91,0x9e,0x1b }, - { 0xc0,0xc5,0x4f,0x80 }, { 0xdc,0x20,0xa2,0x61 }, - { 0x77,0x4b,0x69,0x5a }, { 0x12,0x1a,0x16,0x1c }, - { 0x93,0xba,0x0a,0xe2 }, { 0xa0,0x2a,0xe5,0xc0 }, - { 0x22,0xe0,0x43,0x3c }, { 0x1b,0x17,0x1d,0x12 }, - { 0x09,0x0d,0x0b,0x0e }, { 0x8b,0xc7,0xad,0xf2 }, - { 0xb6,0xa8,0xb9,0x2d }, { 0x1e,0xa9,0xc8,0x14 }, - { 0xf1,0x19,0x85,0x57 }, { 0x75,0x07,0x4c,0xaf }, - { 0x99,0xdd,0xbb,0xee }, { 0x7f,0x60,0xfd,0xa3 }, - { 0x01,0x26,0x9f,0xf7 }, { 0x72,0xf5,0xbc,0x5c }, - { 0x66,0x3b,0xc5,0x44 }, { 0xfb,0x7e,0x34,0x5b }, - { 0x43,0x29,0x76,0x8b }, { 0x23,0xc6,0xdc,0xcb }, - { 0xed,0xfc,0x68,0xb6 }, { 0xe4,0xf1,0x63,0xb8 }, - { 0x31,0xdc,0xca,0xd7 }, { 0x63,0x85,0x10,0x42 }, - { 0x97,0x22,0x40,0x13 }, { 0xc6,0x11,0x20,0x84 }, - { 0x4a,0x24,0x7d,0x85 }, { 0xbb,0x3d,0xf8,0xd2 }, - { 0xf9,0x32,0x11,0xae }, { 0x29,0xa1,0x6d,0xc7 }, - { 0x9e,0x2f,0x4b,0x1d }, { 0xb2,0x30,0xf3,0xdc }, - { 0x86,0x52,0xec,0x0d }, { 0xc1,0xe3,0xd0,0x77 }, - { 0xb3,0x16,0x6c,0x2b }, { 0x70,0xb9,0x99,0xa9 }, - { 0x94,0x48,0xfa,0x11 }, { 0xe9,0x64,0x22,0x47 }, - { 0xfc,0x8c,0xc4,0xa8 }, { 0xf0,0x3f,0x1a,0xa0 }, - { 0x7d,0x2c,0xd8,0x56 }, { 0x33,0x90,0xef,0x22 }, - { 0x49,0x4e,0xc7,0x87 }, { 0x38,0xd1,0xc1,0xd9 }, - { 0xca,0xa2,0xfe,0x8c }, { 0xd4,0x0b,0x36,0x98 }, - { 0xf5,0x81,0xcf,0xa6 }, { 0x7a,0xde,0x28,0xa5 }, - { 0xb7,0x8e,0x26,0xda }, { 0xad,0xbf,0xa4,0x3f }, - { 0x3a,0x9d,0xe4,0x2c }, { 0x78,0x92,0x0d,0x50 }, - { 0x5f,0xcc,0x9b,0x6a }, { 0x7e,0x46,0x62,0x54 }, - { 0x8d,0x13,0xc2,0xf6 }, { 0xd8,0xb8,0xe8,0x90 }, - { 0x39,0xf7,0x5e,0x2e }, { 0xc3,0xaf,0xf5,0x82 }, - { 0x5d,0x80,0xbe,0x9f }, { 0xd0,0x93,0x7c,0x69 }, - { 0xd5,0x2d,0xa9,0x6f }, { 0x25,0x12,0xb3,0xcf }, - { 0xac,0x99,0x3b,0xc8 }, { 0x18,0x7d,0xa7,0x10 }, - { 0x9c,0x63,0x6e,0xe8 }, { 0x3b,0xbb,0x7b,0xdb }, - { 0x26,0x78,0x09,0xcd }, { 0x59,0x18,0xf4,0x6e }, - { 0x9a,0xb7,0x01,0xec }, { 0x4f,0x9a,0xa8,0x83 }, - { 0x95,0x6e,0x65,0xe6 }, { 0xff,0xe6,0x7e,0xaa }, - { 0xbc,0xcf,0x08,0x21 }, { 0x15,0xe8,0xe6,0xef }, - { 0xe7,0x9b,0xd9,0xba }, { 0x6f,0x36,0xce,0x4a }, - { 0x9f,0x09,0xd4,0xea }, { 0xb0,0x7c,0xd6,0x29 }, - { 0xa4,0xb2,0xaf,0x31 }, { 0x3f,0x23,0x31,0x2a }, - { 0xa5,0x94,0x30,0xc6 }, { 0xa2,0x66,0xc0,0x35 }, - { 0x4e,0xbc,0x37,0x74 }, { 0x82,0xca,0xa6,0xfc }, - { 0x90,0xd0,0xb0,0xe0 }, { 0xa7,0xd8,0x15,0x33 }, - { 0x04,0x98,0x4a,0xf1 }, { 0xec,0xda,0xf7,0x41 }, - { 0xcd,0x50,0x0e,0x7f }, { 0x91,0xf6,0x2f,0x17 }, - { 0x4d,0xd6,0x8d,0x76 }, { 0xef,0xb0,0x4d,0x43 }, - { 0xaa,0x4d,0x54,0xcc }, { 0x96,0x04,0xdf,0xe4 }, - { 0xd1,0xb5,0xe3,0x9e }, { 0x6a,0x88,0x1b,0x4c }, - { 0x2c,0x1f,0xb8,0xc1 }, { 0x65,0x51,0x7f,0x46 }, - { 0x5e,0xea,0x04,0x9d }, { 0x8c,0x35,0x5d,0x01 }, - { 0x87,0x74,0x73,0xfa }, { 0x0b,0x41,0x2e,0xfb }, - { 0x67,0x1d,0x5a,0xb3 }, { 0xdb,0xd2,0x52,0x92 }, - { 0x10,0x56,0x33,0xe9 }, { 0xd6,0x47,0x13,0x6d }, - { 0xd7,0x61,0x8c,0x9a }, { 0xa1,0x0c,0x7a,0x37 }, - { 0xf8,0x14,0x8e,0x59 }, { 0x13,0x3c,0x89,0xeb }, - { 0xa9,0x27,0xee,0xce }, { 0x61,0xc9,0x35,0xb7 }, - { 0x1c,0xe5,0xed,0xe1 }, { 0x47,0xb1,0x3c,0x7a }, - { 0xd2,0xdf,0x59,0x9c }, { 0xf2,0x73,0x3f,0x55 }, - { 0x14,0xce,0x79,0x18 }, { 0xc7,0x37,0xbf,0x73 }, - { 0xf7,0xcd,0xea,0x53 }, { 0xfd,0xaa,0x5b,0x5f }, - { 0x3d,0x6f,0x14,0xdf }, { 0x44,0xdb,0x86,0x78 }, - { 0xaf,0xf3,0x81,0xca }, { 0x68,0xc4,0x3e,0xb9 }, - { 0x24,0x34,0x2c,0x38 }, { 0xa3,0x40,0x5f,0xc2 }, - { 0x1d,0xc3,0x72,0x16 }, { 0xe2,0x25,0x0c,0xbc }, - { 0x3c,0x49,0x8b,0x28 }, { 0x0d,0x95,0x41,0xff }, - { 0xa8,0x01,0x71,0x39 }, { 0x0c,0xb3,0xde,0x08 }, - { 0xb4,0xe4,0x9c,0xd8 }, { 0x56,0xc1,0x90,0x64 }, - { 0xcb,0x84,0x61,0x7b }, { 0x32,0xb6,0x70,0xd5 }, - { 0x6c,0x5c,0x74,0x48 }, { 0xb8,0x57,0x42,0xd0 } -}; - -static const byte S5[256] = { - 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, - 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, - 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, - 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, - 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, - 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, - 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, - 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, - 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, - 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, - 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, - 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, - 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, - 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, - 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, - 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, - 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, - 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, - 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, - 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, - 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, - 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, - 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, - 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, - 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, - 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, - 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, - 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, - 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, - 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, - 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, - 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d -}; - -static const byte U1[256][4] = { - { 0x00,0x00,0x00,0x00 }, { 0x0e,0x09,0x0d,0x0b }, - { 0x1c,0x12,0x1a,0x16 }, { 0x12,0x1b,0x17,0x1d }, - { 0x38,0x24,0x34,0x2c }, { 0x36,0x2d,0x39,0x27 }, - { 0x24,0x36,0x2e,0x3a }, { 0x2a,0x3f,0x23,0x31 }, - { 0x70,0x48,0x68,0x58 }, { 0x7e,0x41,0x65,0x53 }, - { 0x6c,0x5a,0x72,0x4e }, { 0x62,0x53,0x7f,0x45 }, - { 0x48,0x6c,0x5c,0x74 }, { 0x46,0x65,0x51,0x7f }, - { 0x54,0x7e,0x46,0x62 }, { 0x5a,0x77,0x4b,0x69 }, - { 0xe0,0x90,0xd0,0xb0 }, { 0xee,0x99,0xdd,0xbb }, - { 0xfc,0x82,0xca,0xa6 }, { 0xf2,0x8b,0xc7,0xad }, - { 0xd8,0xb4,0xe4,0x9c }, { 0xd6,0xbd,0xe9,0x97 }, - { 0xc4,0xa6,0xfe,0x8a }, { 0xca,0xaf,0xf3,0x81 }, - { 0x90,0xd8,0xb8,0xe8 }, { 0x9e,0xd1,0xb5,0xe3 }, - { 0x8c,0xca,0xa2,0xfe }, { 0x82,0xc3,0xaf,0xf5 }, - { 0xa8,0xfc,0x8c,0xc4 }, { 0xa6,0xf5,0x81,0xcf }, - { 0xb4,0xee,0x96,0xd2 }, { 0xba,0xe7,0x9b,0xd9 }, - { 0xdb,0x3b,0xbb,0x7b }, { 0xd5,0x32,0xb6,0x70 }, - { 0xc7,0x29,0xa1,0x6d }, { 0xc9,0x20,0xac,0x66 }, - { 0xe3,0x1f,0x8f,0x57 }, { 0xed,0x16,0x82,0x5c }, - { 0xff,0x0d,0x95,0x41 }, { 0xf1,0x04,0x98,0x4a }, - { 0xab,0x73,0xd3,0x23 }, { 0xa5,0x7a,0xde,0x28 }, - { 0xb7,0x61,0xc9,0x35 }, { 0xb9,0x68,0xc4,0x3e }, - { 0x93,0x57,0xe7,0x0f }, { 0x9d,0x5e,0xea,0x04 }, - { 0x8f,0x45,0xfd,0x19 }, { 0x81,0x4c,0xf0,0x12 }, - { 0x3b,0xab,0x6b,0xcb }, { 0x35,0xa2,0x66,0xc0 }, - { 0x27,0xb9,0x71,0xdd }, { 0x29,0xb0,0x7c,0xd6 }, - { 0x03,0x8f,0x5f,0xe7 }, { 0x0d,0x86,0x52,0xec }, - { 0x1f,0x9d,0x45,0xf1 }, { 0x11,0x94,0x48,0xfa }, - { 0x4b,0xe3,0x03,0x93 }, { 0x45,0xea,0x0e,0x98 }, - { 0x57,0xf1,0x19,0x85 }, { 0x59,0xf8,0x14,0x8e }, - { 0x73,0xc7,0x37,0xbf }, { 0x7d,0xce,0x3a,0xb4 }, - { 0x6f,0xd5,0x2d,0xa9 }, { 0x61,0xdc,0x20,0xa2 }, - { 0xad,0x76,0x6d,0xf6 }, { 0xa3,0x7f,0x60,0xfd }, - { 0xb1,0x64,0x77,0xe0 }, { 0xbf,0x6d,0x7a,0xeb }, - { 0x95,0x52,0x59,0xda }, { 0x9b,0x5b,0x54,0xd1 }, - { 0x89,0x40,0x43,0xcc }, { 0x87,0x49,0x4e,0xc7 }, - { 0xdd,0x3e,0x05,0xae }, { 0xd3,0x37,0x08,0xa5 }, - { 0xc1,0x2c,0x1f,0xb8 }, { 0xcf,0x25,0x12,0xb3 }, - { 0xe5,0x1a,0x31,0x82 }, { 0xeb,0x13,0x3c,0x89 }, - { 0xf9,0x08,0x2b,0x94 }, { 0xf7,0x01,0x26,0x9f }, - { 0x4d,0xe6,0xbd,0x46 }, { 0x43,0xef,0xb0,0x4d }, - { 0x51,0xf4,0xa7,0x50 }, { 0x5f,0xfd,0xaa,0x5b }, - { 0x75,0xc2,0x89,0x6a }, { 0x7b,0xcb,0x84,0x61 }, - { 0x69,0xd0,0x93,0x7c }, { 0x67,0xd9,0x9e,0x77 }, - { 0x3d,0xae,0xd5,0x1e }, { 0x33,0xa7,0xd8,0x15 }, - { 0x21,0xbc,0xcf,0x08 }, { 0x2f,0xb5,0xc2,0x03 }, - { 0x05,0x8a,0xe1,0x32 }, { 0x0b,0x83,0xec,0x39 }, - { 0x19,0x98,0xfb,0x24 }, { 0x17,0x91,0xf6,0x2f }, - { 0x76,0x4d,0xd6,0x8d }, { 0x78,0x44,0xdb,0x86 }, - { 0x6a,0x5f,0xcc,0x9b }, { 0x64,0x56,0xc1,0x90 }, - { 0x4e,0x69,0xe2,0xa1 }, { 0x40,0x60,0xef,0xaa }, - { 0x52,0x7b,0xf8,0xb7 }, { 0x5c,0x72,0xf5,0xbc }, - { 0x06,0x05,0xbe,0xd5 }, { 0x08,0x0c,0xb3,0xde }, - { 0x1a,0x17,0xa4,0xc3 }, { 0x14,0x1e,0xa9,0xc8 }, - { 0x3e,0x21,0x8a,0xf9 }, { 0x30,0x28,0x87,0xf2 }, - { 0x22,0x33,0x90,0xef }, { 0x2c,0x3a,0x9d,0xe4 }, - { 0x96,0xdd,0x06,0x3d }, { 0x98,0xd4,0x0b,0x36 }, - { 0x8a,0xcf,0x1c,0x2b }, { 0x84,0xc6,0x11,0x20 }, - { 0xae,0xf9,0x32,0x11 }, { 0xa0,0xf0,0x3f,0x1a }, - { 0xb2,0xeb,0x28,0x07 }, { 0xbc,0xe2,0x25,0x0c }, - { 0xe6,0x95,0x6e,0x65 }, { 0xe8,0x9c,0x63,0x6e }, - { 0xfa,0x87,0x74,0x73 }, { 0xf4,0x8e,0x79,0x78 }, - { 0xde,0xb1,0x5a,0x49 }, { 0xd0,0xb8,0x57,0x42 }, - { 0xc2,0xa3,0x40,0x5f }, { 0xcc,0xaa,0x4d,0x54 }, - { 0x41,0xec,0xda,0xf7 }, { 0x4f,0xe5,0xd7,0xfc }, - { 0x5d,0xfe,0xc0,0xe1 }, { 0x53,0xf7,0xcd,0xea }, - { 0x79,0xc8,0xee,0xdb }, { 0x77,0xc1,0xe3,0xd0 }, - { 0x65,0xda,0xf4,0xcd }, { 0x6b,0xd3,0xf9,0xc6 }, - { 0x31,0xa4,0xb2,0xaf }, { 0x3f,0xad,0xbf,0xa4 }, - { 0x2d,0xb6,0xa8,0xb9 }, { 0x23,0xbf,0xa5,0xb2 }, - { 0x09,0x80,0x86,0x83 }, { 0x07,0x89,0x8b,0x88 }, - { 0x15,0x92,0x9c,0x95 }, { 0x1b,0x9b,0x91,0x9e }, - { 0xa1,0x7c,0x0a,0x47 }, { 0xaf,0x75,0x07,0x4c }, - { 0xbd,0x6e,0x10,0x51 }, { 0xb3,0x67,0x1d,0x5a }, - { 0x99,0x58,0x3e,0x6b }, { 0x97,0x51,0x33,0x60 }, - { 0x85,0x4a,0x24,0x7d }, { 0x8b,0x43,0x29,0x76 }, - { 0xd1,0x34,0x62,0x1f }, { 0xdf,0x3d,0x6f,0x14 }, - { 0xcd,0x26,0x78,0x09 }, { 0xc3,0x2f,0x75,0x02 }, - { 0xe9,0x10,0x56,0x33 }, { 0xe7,0x19,0x5b,0x38 }, - { 0xf5,0x02,0x4c,0x25 }, { 0xfb,0x0b,0x41,0x2e }, - { 0x9a,0xd7,0x61,0x8c }, { 0x94,0xde,0x6c,0x87 }, - { 0x86,0xc5,0x7b,0x9a }, { 0x88,0xcc,0x76,0x91 }, - { 0xa2,0xf3,0x55,0xa0 }, { 0xac,0xfa,0x58,0xab }, - { 0xbe,0xe1,0x4f,0xb6 }, { 0xb0,0xe8,0x42,0xbd }, - { 0xea,0x9f,0x09,0xd4 }, { 0xe4,0x96,0x04,0xdf }, - { 0xf6,0x8d,0x13,0xc2 }, { 0xf8,0x84,0x1e,0xc9 }, - { 0xd2,0xbb,0x3d,0xf8 }, { 0xdc,0xb2,0x30,0xf3 }, - { 0xce,0xa9,0x27,0xee }, { 0xc0,0xa0,0x2a,0xe5 }, - { 0x7a,0x47,0xb1,0x3c }, { 0x74,0x4e,0xbc,0x37 }, - { 0x66,0x55,0xab,0x2a }, { 0x68,0x5c,0xa6,0x21 }, - { 0x42,0x63,0x85,0x10 }, { 0x4c,0x6a,0x88,0x1b }, - { 0x5e,0x71,0x9f,0x06 }, { 0x50,0x78,0x92,0x0d }, - { 0x0a,0x0f,0xd9,0x64 }, { 0x04,0x06,0xd4,0x6f }, - { 0x16,0x1d,0xc3,0x72 }, { 0x18,0x14,0xce,0x79 }, - { 0x32,0x2b,0xed,0x48 }, { 0x3c,0x22,0xe0,0x43 }, - { 0x2e,0x39,0xf7,0x5e }, { 0x20,0x30,0xfa,0x55 }, - { 0xec,0x9a,0xb7,0x01 }, { 0xe2,0x93,0xba,0x0a }, - { 0xf0,0x88,0xad,0x17 }, { 0xfe,0x81,0xa0,0x1c }, - { 0xd4,0xbe,0x83,0x2d }, { 0xda,0xb7,0x8e,0x26 }, - { 0xc8,0xac,0x99,0x3b }, { 0xc6,0xa5,0x94,0x30 }, - { 0x9c,0xd2,0xdf,0x59 }, { 0x92,0xdb,0xd2,0x52 }, - { 0x80,0xc0,0xc5,0x4f }, { 0x8e,0xc9,0xc8,0x44 }, - { 0xa4,0xf6,0xeb,0x75 }, { 0xaa,0xff,0xe6,0x7e }, - { 0xb8,0xe4,0xf1,0x63 }, { 0xb6,0xed,0xfc,0x68 }, - { 0x0c,0x0a,0x67,0xb1 }, { 0x02,0x03,0x6a,0xba }, - { 0x10,0x18,0x7d,0xa7 }, { 0x1e,0x11,0x70,0xac }, - { 0x34,0x2e,0x53,0x9d }, { 0x3a,0x27,0x5e,0x96 }, - { 0x28,0x3c,0x49,0x8b }, { 0x26,0x35,0x44,0x80 }, - { 0x7c,0x42,0x0f,0xe9 }, { 0x72,0x4b,0x02,0xe2 }, - { 0x60,0x50,0x15,0xff }, { 0x6e,0x59,0x18,0xf4 }, - { 0x44,0x66,0x3b,0xc5 }, { 0x4a,0x6f,0x36,0xce }, - { 0x58,0x74,0x21,0xd3 }, { 0x56,0x7d,0x2c,0xd8 }, - { 0x37,0xa1,0x0c,0x7a }, { 0x39,0xa8,0x01,0x71 }, - { 0x2b,0xb3,0x16,0x6c }, { 0x25,0xba,0x1b,0x67 }, - { 0x0f,0x85,0x38,0x56 }, { 0x01,0x8c,0x35,0x5d }, - { 0x13,0x97,0x22,0x40 }, { 0x1d,0x9e,0x2f,0x4b }, - { 0x47,0xe9,0x64,0x22 }, { 0x49,0xe0,0x69,0x29 }, - { 0x5b,0xfb,0x7e,0x34 }, { 0x55,0xf2,0x73,0x3f }, - { 0x7f,0xcd,0x50,0x0e }, { 0x71,0xc4,0x5d,0x05 }, - { 0x63,0xdf,0x4a,0x18 }, { 0x6d,0xd6,0x47,0x13 }, - { 0xd7,0x31,0xdc,0xca }, { 0xd9,0x38,0xd1,0xc1 }, - { 0xcb,0x23,0xc6,0xdc }, { 0xc5,0x2a,0xcb,0xd7 }, - { 0xef,0x15,0xe8,0xe6 }, { 0xe1,0x1c,0xe5,0xed }, - { 0xf3,0x07,0xf2,0xf0 }, { 0xfd,0x0e,0xff,0xfb }, - { 0xa7,0x79,0xb4,0x92 }, { 0xa9,0x70,0xb9,0x99 }, - { 0xbb,0x6b,0xae,0x84 }, { 0xb5,0x62,0xa3,0x8f }, - { 0x9f,0x5d,0x80,0xbe }, { 0x91,0x54,0x8d,0xb5 }, - { 0x83,0x4f,0x9a,0xa8 }, { 0x8d,0x46,0x97,0xa3 } -}; - -static const byte U2[256][4] = { - { 0x00,0x00,0x00,0x00 }, { 0x0b,0x0e,0x09,0x0d }, - { 0x16,0x1c,0x12,0x1a }, { 0x1d,0x12,0x1b,0x17 }, - { 0x2c,0x38,0x24,0x34 }, { 0x27,0x36,0x2d,0x39 }, - { 0x3a,0x24,0x36,0x2e }, { 0x31,0x2a,0x3f,0x23 }, - { 0x58,0x70,0x48,0x68 }, { 0x53,0x7e,0x41,0x65 }, - { 0x4e,0x6c,0x5a,0x72 }, { 0x45,0x62,0x53,0x7f }, - { 0x74,0x48,0x6c,0x5c }, { 0x7f,0x46,0x65,0x51 }, - { 0x62,0x54,0x7e,0x46 }, { 0x69,0x5a,0x77,0x4b }, - { 0xb0,0xe0,0x90,0xd0 }, { 0xbb,0xee,0x99,0xdd }, - { 0xa6,0xfc,0x82,0xca }, { 0xad,0xf2,0x8b,0xc7 }, - { 0x9c,0xd8,0xb4,0xe4 }, { 0x97,0xd6,0xbd,0xe9 }, - { 0x8a,0xc4,0xa6,0xfe }, { 0x81,0xca,0xaf,0xf3 }, - { 0xe8,0x90,0xd8,0xb8 }, { 0xe3,0x9e,0xd1,0xb5 }, - { 0xfe,0x8c,0xca,0xa2 }, { 0xf5,0x82,0xc3,0xaf }, - { 0xc4,0xa8,0xfc,0x8c }, { 0xcf,0xa6,0xf5,0x81 }, - { 0xd2,0xb4,0xee,0x96 }, { 0xd9,0xba,0xe7,0x9b }, - { 0x7b,0xdb,0x3b,0xbb }, { 0x70,0xd5,0x32,0xb6 }, - { 0x6d,0xc7,0x29,0xa1 }, { 0x66,0xc9,0x20,0xac }, - { 0x57,0xe3,0x1f,0x8f }, { 0x5c,0xed,0x16,0x82 }, - { 0x41,0xff,0x0d,0x95 }, { 0x4a,0xf1,0x04,0x98 }, - { 0x23,0xab,0x73,0xd3 }, { 0x28,0xa5,0x7a,0xde }, - { 0x35,0xb7,0x61,0xc9 }, { 0x3e,0xb9,0x68,0xc4 }, - { 0x0f,0x93,0x57,0xe7 }, { 0x04,0x9d,0x5e,0xea }, - { 0x19,0x8f,0x45,0xfd }, { 0x12,0x81,0x4c,0xf0 }, - { 0xcb,0x3b,0xab,0x6b }, { 0xc0,0x35,0xa2,0x66 }, - { 0xdd,0x27,0xb9,0x71 }, { 0xd6,0x29,0xb0,0x7c }, - { 0xe7,0x03,0x8f,0x5f }, { 0xec,0x0d,0x86,0x52 }, - { 0xf1,0x1f,0x9d,0x45 }, { 0xfa,0x11,0x94,0x48 }, - { 0x93,0x4b,0xe3,0x03 }, { 0x98,0x45,0xea,0x0e }, - { 0x85,0x57,0xf1,0x19 }, { 0x8e,0x59,0xf8,0x14 }, - { 0xbf,0x73,0xc7,0x37 }, { 0xb4,0x7d,0xce,0x3a }, - { 0xa9,0x6f,0xd5,0x2d }, { 0xa2,0x61,0xdc,0x20 }, - { 0xf6,0xad,0x76,0x6d }, { 0xfd,0xa3,0x7f,0x60 }, - { 0xe0,0xb1,0x64,0x77 }, { 0xeb,0xbf,0x6d,0x7a }, - { 0xda,0x95,0x52,0x59 }, { 0xd1,0x9b,0x5b,0x54 }, - { 0xcc,0x89,0x40,0x43 }, { 0xc7,0x87,0x49,0x4e }, - { 0xae,0xdd,0x3e,0x05 }, { 0xa5,0xd3,0x37,0x08 }, - { 0xb8,0xc1,0x2c,0x1f }, { 0xb3,0xcf,0x25,0x12 }, - { 0x82,0xe5,0x1a,0x31 }, { 0x89,0xeb,0x13,0x3c }, - { 0x94,0xf9,0x08,0x2b }, { 0x9f,0xf7,0x01,0x26 }, - { 0x46,0x4d,0xe6,0xbd }, { 0x4d,0x43,0xef,0xb0 }, - { 0x50,0x51,0xf4,0xa7 }, { 0x5b,0x5f,0xfd,0xaa }, - { 0x6a,0x75,0xc2,0x89 }, { 0x61,0x7b,0xcb,0x84 }, - { 0x7c,0x69,0xd0,0x93 }, { 0x77,0x67,0xd9,0x9e }, - { 0x1e,0x3d,0xae,0xd5 }, { 0x15,0x33,0xa7,0xd8 }, - { 0x08,0x21,0xbc,0xcf }, { 0x03,0x2f,0xb5,0xc2 }, - { 0x32,0x05,0x8a,0xe1 }, { 0x39,0x0b,0x83,0xec }, - { 0x24,0x19,0x98,0xfb }, { 0x2f,0x17,0x91,0xf6 }, - { 0x8d,0x76,0x4d,0xd6 }, { 0x86,0x78,0x44,0xdb }, - { 0x9b,0x6a,0x5f,0xcc }, { 0x90,0x64,0x56,0xc1 }, - { 0xa1,0x4e,0x69,0xe2 }, { 0xaa,0x40,0x60,0xef }, - { 0xb7,0x52,0x7b,0xf8 }, { 0xbc,0x5c,0x72,0xf5 }, - { 0xd5,0x06,0x05,0xbe }, { 0xde,0x08,0x0c,0xb3 }, - { 0xc3,0x1a,0x17,0xa4 }, { 0xc8,0x14,0x1e,0xa9 }, - { 0xf9,0x3e,0x21,0x8a }, { 0xf2,0x30,0x28,0x87 }, - { 0xef,0x22,0x33,0x90 }, { 0xe4,0x2c,0x3a,0x9d }, - { 0x3d,0x96,0xdd,0x06 }, { 0x36,0x98,0xd4,0x0b }, - { 0x2b,0x8a,0xcf,0x1c }, { 0x20,0x84,0xc6,0x11 }, - { 0x11,0xae,0xf9,0x32 }, { 0x1a,0xa0,0xf0,0x3f }, - { 0x07,0xb2,0xeb,0x28 }, { 0x0c,0xbc,0xe2,0x25 }, - { 0x65,0xe6,0x95,0x6e }, { 0x6e,0xe8,0x9c,0x63 }, - { 0x73,0xfa,0x87,0x74 }, { 0x78,0xf4,0x8e,0x79 }, - { 0x49,0xde,0xb1,0x5a }, { 0x42,0xd0,0xb8,0x57 }, - { 0x5f,0xc2,0xa3,0x40 }, { 0x54,0xcc,0xaa,0x4d }, - { 0xf7,0x41,0xec,0xda }, { 0xfc,0x4f,0xe5,0xd7 }, - { 0xe1,0x5d,0xfe,0xc0 }, { 0xea,0x53,0xf7,0xcd }, - { 0xdb,0x79,0xc8,0xee }, { 0xd0,0x77,0xc1,0xe3 }, - { 0xcd,0x65,0xda,0xf4 }, { 0xc6,0x6b,0xd3,0xf9 }, - { 0xaf,0x31,0xa4,0xb2 }, { 0xa4,0x3f,0xad,0xbf }, - { 0xb9,0x2d,0xb6,0xa8 }, { 0xb2,0x23,0xbf,0xa5 }, - { 0x83,0x09,0x80,0x86 }, { 0x88,0x07,0x89,0x8b }, - { 0x95,0x15,0x92,0x9c }, { 0x9e,0x1b,0x9b,0x91 }, - { 0x47,0xa1,0x7c,0x0a }, { 0x4c,0xaf,0x75,0x07 }, - { 0x51,0xbd,0x6e,0x10 }, { 0x5a,0xb3,0x67,0x1d }, - { 0x6b,0x99,0x58,0x3e }, { 0x60,0x97,0x51,0x33 }, - { 0x7d,0x85,0x4a,0x24 }, { 0x76,0x8b,0x43,0x29 }, - { 0x1f,0xd1,0x34,0x62 }, { 0x14,0xdf,0x3d,0x6f }, - { 0x09,0xcd,0x26,0x78 }, { 0x02,0xc3,0x2f,0x75 }, - { 0x33,0xe9,0x10,0x56 }, { 0x38,0xe7,0x19,0x5b }, - { 0x25,0xf5,0x02,0x4c }, { 0x2e,0xfb,0x0b,0x41 }, - { 0x8c,0x9a,0xd7,0x61 }, { 0x87,0x94,0xde,0x6c }, - { 0x9a,0x86,0xc5,0x7b }, { 0x91,0x88,0xcc,0x76 }, - { 0xa0,0xa2,0xf3,0x55 }, { 0xab,0xac,0xfa,0x58 }, - { 0xb6,0xbe,0xe1,0x4f }, { 0xbd,0xb0,0xe8,0x42 }, - { 0xd4,0xea,0x9f,0x09 }, { 0xdf,0xe4,0x96,0x04 }, - { 0xc2,0xf6,0x8d,0x13 }, { 0xc9,0xf8,0x84,0x1e }, - { 0xf8,0xd2,0xbb,0x3d }, { 0xf3,0xdc,0xb2,0x30 }, - { 0xee,0xce,0xa9,0x27 }, { 0xe5,0xc0,0xa0,0x2a }, - { 0x3c,0x7a,0x47,0xb1 }, { 0x37,0x74,0x4e,0xbc }, - { 0x2a,0x66,0x55,0xab }, { 0x21,0x68,0x5c,0xa6 }, - { 0x10,0x42,0x63,0x85 }, { 0x1b,0x4c,0x6a,0x88 }, - { 0x06,0x5e,0x71,0x9f }, { 0x0d,0x50,0x78,0x92 }, - { 0x64,0x0a,0x0f,0xd9 }, { 0x6f,0x04,0x06,0xd4 }, - { 0x72,0x16,0x1d,0xc3 }, { 0x79,0x18,0x14,0xce }, - { 0x48,0x32,0x2b,0xed }, { 0x43,0x3c,0x22,0xe0 }, - { 0x5e,0x2e,0x39,0xf7 }, { 0x55,0x20,0x30,0xfa }, - { 0x01,0xec,0x9a,0xb7 }, { 0x0a,0xe2,0x93,0xba }, - { 0x17,0xf0,0x88,0xad }, { 0x1c,0xfe,0x81,0xa0 }, - { 0x2d,0xd4,0xbe,0x83 }, { 0x26,0xda,0xb7,0x8e }, - { 0x3b,0xc8,0xac,0x99 }, { 0x30,0xc6,0xa5,0x94 }, - { 0x59,0x9c,0xd2,0xdf }, { 0x52,0x92,0xdb,0xd2 }, - { 0x4f,0x80,0xc0,0xc5 }, { 0x44,0x8e,0xc9,0xc8 }, - { 0x75,0xa4,0xf6,0xeb }, { 0x7e,0xaa,0xff,0xe6 }, - { 0x63,0xb8,0xe4,0xf1 }, { 0x68,0xb6,0xed,0xfc }, - { 0xb1,0x0c,0x0a,0x67 }, { 0xba,0x02,0x03,0x6a }, - { 0xa7,0x10,0x18,0x7d }, { 0xac,0x1e,0x11,0x70 }, - { 0x9d,0x34,0x2e,0x53 }, { 0x96,0x3a,0x27,0x5e }, - { 0x8b,0x28,0x3c,0x49 }, { 0x80,0x26,0x35,0x44 }, - { 0xe9,0x7c,0x42,0x0f }, { 0xe2,0x72,0x4b,0x02 }, - { 0xff,0x60,0x50,0x15 }, { 0xf4,0x6e,0x59,0x18 }, - { 0xc5,0x44,0x66,0x3b }, { 0xce,0x4a,0x6f,0x36 }, - { 0xd3,0x58,0x74,0x21 }, { 0xd8,0x56,0x7d,0x2c }, - { 0x7a,0x37,0xa1,0x0c }, { 0x71,0x39,0xa8,0x01 }, - { 0x6c,0x2b,0xb3,0x16 }, { 0x67,0x25,0xba,0x1b }, - { 0x56,0x0f,0x85,0x38 }, { 0x5d,0x01,0x8c,0x35 }, - { 0x40,0x13,0x97,0x22 }, { 0x4b,0x1d,0x9e,0x2f }, - { 0x22,0x47,0xe9,0x64 }, { 0x29,0x49,0xe0,0x69 }, - { 0x34,0x5b,0xfb,0x7e }, { 0x3f,0x55,0xf2,0x73 }, - { 0x0e,0x7f,0xcd,0x50 }, { 0x05,0x71,0xc4,0x5d }, - { 0x18,0x63,0xdf,0x4a }, { 0x13,0x6d,0xd6,0x47 }, - { 0xca,0xd7,0x31,0xdc }, { 0xc1,0xd9,0x38,0xd1 }, - { 0xdc,0xcb,0x23,0xc6 }, { 0xd7,0xc5,0x2a,0xcb }, - { 0xe6,0xef,0x15,0xe8 }, { 0xed,0xe1,0x1c,0xe5 }, - { 0xf0,0xf3,0x07,0xf2 }, { 0xfb,0xfd,0x0e,0xff }, - { 0x92,0xa7,0x79,0xb4 }, { 0x99,0xa9,0x70,0xb9 }, - { 0x84,0xbb,0x6b,0xae }, { 0x8f,0xb5,0x62,0xa3 }, - { 0xbe,0x9f,0x5d,0x80 }, { 0xb5,0x91,0x54,0x8d }, - { 0xa8,0x83,0x4f,0x9a }, { 0xa3,0x8d,0x46,0x97 } -}; - -static const byte U3[256][4] = { - { 0x00,0x00,0x00,0x00 }, { 0x0d,0x0b,0x0e,0x09 }, - { 0x1a,0x16,0x1c,0x12 }, { 0x17,0x1d,0x12,0x1b }, - { 0x34,0x2c,0x38,0x24 }, { 0x39,0x27,0x36,0x2d }, - { 0x2e,0x3a,0x24,0x36 }, { 0x23,0x31,0x2a,0x3f }, - { 0x68,0x58,0x70,0x48 }, { 0x65,0x53,0x7e,0x41 }, - { 0x72,0x4e,0x6c,0x5a }, { 0x7f,0x45,0x62,0x53 }, - { 0x5c,0x74,0x48,0x6c }, { 0x51,0x7f,0x46,0x65 }, - { 0x46,0x62,0x54,0x7e }, { 0x4b,0x69,0x5a,0x77 }, - { 0xd0,0xb0,0xe0,0x90 }, { 0xdd,0xbb,0xee,0x99 }, - { 0xca,0xa6,0xfc,0x82 }, { 0xc7,0xad,0xf2,0x8b }, - { 0xe4,0x9c,0xd8,0xb4 }, { 0xe9,0x97,0xd6,0xbd }, - { 0xfe,0x8a,0xc4,0xa6 }, { 0xf3,0x81,0xca,0xaf }, - { 0xb8,0xe8,0x90,0xd8 }, { 0xb5,0xe3,0x9e,0xd1 }, - { 0xa2,0xfe,0x8c,0xca }, { 0xaf,0xf5,0x82,0xc3 }, - { 0x8c,0xc4,0xa8,0xfc }, { 0x81,0xcf,0xa6,0xf5 }, - { 0x96,0xd2,0xb4,0xee }, { 0x9b,0xd9,0xba,0xe7 }, - { 0xbb,0x7b,0xdb,0x3b }, { 0xb6,0x70,0xd5,0x32 }, - { 0xa1,0x6d,0xc7,0x29 }, { 0xac,0x66,0xc9,0x20 }, - { 0x8f,0x57,0xe3,0x1f }, { 0x82,0x5c,0xed,0x16 }, - { 0x95,0x41,0xff,0x0d }, { 0x98,0x4a,0xf1,0x04 }, - { 0xd3,0x23,0xab,0x73 }, { 0xde,0x28,0xa5,0x7a }, - { 0xc9,0x35,0xb7,0x61 }, { 0xc4,0x3e,0xb9,0x68 }, - { 0xe7,0x0f,0x93,0x57 }, { 0xea,0x04,0x9d,0x5e }, - { 0xfd,0x19,0x8f,0x45 }, { 0xf0,0x12,0x81,0x4c }, - { 0x6b,0xcb,0x3b,0xab }, { 0x66,0xc0,0x35,0xa2 }, - { 0x71,0xdd,0x27,0xb9 }, { 0x7c,0xd6,0x29,0xb0 }, - { 0x5f,0xe7,0x03,0x8f }, { 0x52,0xec,0x0d,0x86 }, - { 0x45,0xf1,0x1f,0x9d }, { 0x48,0xfa,0x11,0x94 }, - { 0x03,0x93,0x4b,0xe3 }, { 0x0e,0x98,0x45,0xea }, - { 0x19,0x85,0x57,0xf1 }, { 0x14,0x8e,0x59,0xf8 }, - { 0x37,0xbf,0x73,0xc7 }, { 0x3a,0xb4,0x7d,0xce }, - { 0x2d,0xa9,0x6f,0xd5 }, { 0x20,0xa2,0x61,0xdc }, - { 0x6d,0xf6,0xad,0x76 }, { 0x60,0xfd,0xa3,0x7f }, - { 0x77,0xe0,0xb1,0x64 }, { 0x7a,0xeb,0xbf,0x6d }, - { 0x59,0xda,0x95,0x52 }, { 0x54,0xd1,0x9b,0x5b }, - { 0x43,0xcc,0x89,0x40 }, { 0x4e,0xc7,0x87,0x49 }, - { 0x05,0xae,0xdd,0x3e }, { 0x08,0xa5,0xd3,0x37 }, - { 0x1f,0xb8,0xc1,0x2c }, { 0x12,0xb3,0xcf,0x25 }, - { 0x31,0x82,0xe5,0x1a }, { 0x3c,0x89,0xeb,0x13 }, - { 0x2b,0x94,0xf9,0x08 }, { 0x26,0x9f,0xf7,0x01 }, - { 0xbd,0x46,0x4d,0xe6 }, { 0xb0,0x4d,0x43,0xef }, - { 0xa7,0x50,0x51,0xf4 }, { 0xaa,0x5b,0x5f,0xfd }, - { 0x89,0x6a,0x75,0xc2 }, { 0x84,0x61,0x7b,0xcb }, - { 0x93,0x7c,0x69,0xd0 }, { 0x9e,0x77,0x67,0xd9 }, - { 0xd5,0x1e,0x3d,0xae }, { 0xd8,0x15,0x33,0xa7 }, - { 0xcf,0x08,0x21,0xbc }, { 0xc2,0x03,0x2f,0xb5 }, - { 0xe1,0x32,0x05,0x8a }, { 0xec,0x39,0x0b,0x83 }, - { 0xfb,0x24,0x19,0x98 }, { 0xf6,0x2f,0x17,0x91 }, - { 0xd6,0x8d,0x76,0x4d }, { 0xdb,0x86,0x78,0x44 }, - { 0xcc,0x9b,0x6a,0x5f }, { 0xc1,0x90,0x64,0x56 }, - { 0xe2,0xa1,0x4e,0x69 }, { 0xef,0xaa,0x40,0x60 }, - { 0xf8,0xb7,0x52,0x7b }, { 0xf5,0xbc,0x5c,0x72 }, - { 0xbe,0xd5,0x06,0x05 }, { 0xb3,0xde,0x08,0x0c }, - { 0xa4,0xc3,0x1a,0x17 }, { 0xa9,0xc8,0x14,0x1e }, - { 0x8a,0xf9,0x3e,0x21 }, { 0x87,0xf2,0x30,0x28 }, - { 0x90,0xef,0x22,0x33 }, { 0x9d,0xe4,0x2c,0x3a }, - { 0x06,0x3d,0x96,0xdd }, { 0x0b,0x36,0x98,0xd4 }, - { 0x1c,0x2b,0x8a,0xcf }, { 0x11,0x20,0x84,0xc6 }, - { 0x32,0x11,0xae,0xf9 }, { 0x3f,0x1a,0xa0,0xf0 }, - { 0x28,0x07,0xb2,0xeb }, { 0x25,0x0c,0xbc,0xe2 }, - { 0x6e,0x65,0xe6,0x95 }, { 0x63,0x6e,0xe8,0x9c }, - { 0x74,0x73,0xfa,0x87 }, { 0x79,0x78,0xf4,0x8e }, - { 0x5a,0x49,0xde,0xb1 }, { 0x57,0x42,0xd0,0xb8 }, - { 0x40,0x5f,0xc2,0xa3 }, { 0x4d,0x54,0xcc,0xaa }, - { 0xda,0xf7,0x41,0xec }, { 0xd7,0xfc,0x4f,0xe5 }, - { 0xc0,0xe1,0x5d,0xfe }, { 0xcd,0xea,0x53,0xf7 }, - { 0xee,0xdb,0x79,0xc8 }, { 0xe3,0xd0,0x77,0xc1 }, - { 0xf4,0xcd,0x65,0xda }, { 0xf9,0xc6,0x6b,0xd3 }, - { 0xb2,0xaf,0x31,0xa4 }, { 0xbf,0xa4,0x3f,0xad }, - { 0xa8,0xb9,0x2d,0xb6 }, { 0xa5,0xb2,0x23,0xbf }, - { 0x86,0x83,0x09,0x80 }, { 0x8b,0x88,0x07,0x89 }, - { 0x9c,0x95,0x15,0x92 }, { 0x91,0x9e,0x1b,0x9b }, - { 0x0a,0x47,0xa1,0x7c }, { 0x07,0x4c,0xaf,0x75 }, - { 0x10,0x51,0xbd,0x6e }, { 0x1d,0x5a,0xb3,0x67 }, - { 0x3e,0x6b,0x99,0x58 }, { 0x33,0x60,0x97,0x51 }, - { 0x24,0x7d,0x85,0x4a }, { 0x29,0x76,0x8b,0x43 }, - { 0x62,0x1f,0xd1,0x34 }, { 0x6f,0x14,0xdf,0x3d }, - { 0x78,0x09,0xcd,0x26 }, { 0x75,0x02,0xc3,0x2f }, - { 0x56,0x33,0xe9,0x10 }, { 0x5b,0x38,0xe7,0x19 }, - { 0x4c,0x25,0xf5,0x02 }, { 0x41,0x2e,0xfb,0x0b }, - { 0x61,0x8c,0x9a,0xd7 }, { 0x6c,0x87,0x94,0xde }, - { 0x7b,0x9a,0x86,0xc5 }, { 0x76,0x91,0x88,0xcc }, - { 0x55,0xa0,0xa2,0xf3 }, { 0x58,0xab,0xac,0xfa }, - { 0x4f,0xb6,0xbe,0xe1 }, { 0x42,0xbd,0xb0,0xe8 }, - { 0x09,0xd4,0xea,0x9f }, { 0x04,0xdf,0xe4,0x96 }, - { 0x13,0xc2,0xf6,0x8d }, { 0x1e,0xc9,0xf8,0x84 }, - { 0x3d,0xf8,0xd2,0xbb }, { 0x30,0xf3,0xdc,0xb2 }, - { 0x27,0xee,0xce,0xa9 }, { 0x2a,0xe5,0xc0,0xa0 }, - { 0xb1,0x3c,0x7a,0x47 }, { 0xbc,0x37,0x74,0x4e }, - { 0xab,0x2a,0x66,0x55 }, { 0xa6,0x21,0x68,0x5c }, - { 0x85,0x10,0x42,0x63 }, { 0x88,0x1b,0x4c,0x6a }, - { 0x9f,0x06,0x5e,0x71 }, { 0x92,0x0d,0x50,0x78 }, - { 0xd9,0x64,0x0a,0x0f }, { 0xd4,0x6f,0x04,0x06 }, - { 0xc3,0x72,0x16,0x1d }, { 0xce,0x79,0x18,0x14 }, - { 0xed,0x48,0x32,0x2b }, { 0xe0,0x43,0x3c,0x22 }, - { 0xf7,0x5e,0x2e,0x39 }, { 0xfa,0x55,0x20,0x30 }, - { 0xb7,0x01,0xec,0x9a }, { 0xba,0x0a,0xe2,0x93 }, - { 0xad,0x17,0xf0,0x88 }, { 0xa0,0x1c,0xfe,0x81 }, - { 0x83,0x2d,0xd4,0xbe }, { 0x8e,0x26,0xda,0xb7 }, - { 0x99,0x3b,0xc8,0xac }, { 0x94,0x30,0xc6,0xa5 }, - { 0xdf,0x59,0x9c,0xd2 }, { 0xd2,0x52,0x92,0xdb }, - { 0xc5,0x4f,0x80,0xc0 }, { 0xc8,0x44,0x8e,0xc9 }, - { 0xeb,0x75,0xa4,0xf6 }, { 0xe6,0x7e,0xaa,0xff }, - { 0xf1,0x63,0xb8,0xe4 }, { 0xfc,0x68,0xb6,0xed }, - { 0x67,0xb1,0x0c,0x0a }, { 0x6a,0xba,0x02,0x03 }, - { 0x7d,0xa7,0x10,0x18 }, { 0x70,0xac,0x1e,0x11 }, - { 0x53,0x9d,0x34,0x2e }, { 0x5e,0x96,0x3a,0x27 }, - { 0x49,0x8b,0x28,0x3c }, { 0x44,0x80,0x26,0x35 }, - { 0x0f,0xe9,0x7c,0x42 }, { 0x02,0xe2,0x72,0x4b }, - { 0x15,0xff,0x60,0x50 }, { 0x18,0xf4,0x6e,0x59 }, - { 0x3b,0xc5,0x44,0x66 }, { 0x36,0xce,0x4a,0x6f }, - { 0x21,0xd3,0x58,0x74 }, { 0x2c,0xd8,0x56,0x7d }, - { 0x0c,0x7a,0x37,0xa1 }, { 0x01,0x71,0x39,0xa8 }, - { 0x16,0x6c,0x2b,0xb3 }, { 0x1b,0x67,0x25,0xba }, - { 0x38,0x56,0x0f,0x85 }, { 0x35,0x5d,0x01,0x8c }, - { 0x22,0x40,0x13,0x97 }, { 0x2f,0x4b,0x1d,0x9e }, - { 0x64,0x22,0x47,0xe9 }, { 0x69,0x29,0x49,0xe0 }, - { 0x7e,0x34,0x5b,0xfb }, { 0x73,0x3f,0x55,0xf2 }, - { 0x50,0x0e,0x7f,0xcd }, { 0x5d,0x05,0x71,0xc4 }, - { 0x4a,0x18,0x63,0xdf }, { 0x47,0x13,0x6d,0xd6 }, - { 0xdc,0xca,0xd7,0x31 }, { 0xd1,0xc1,0xd9,0x38 }, - { 0xc6,0xdc,0xcb,0x23 }, { 0xcb,0xd7,0xc5,0x2a }, - { 0xe8,0xe6,0xef,0x15 }, { 0xe5,0xed,0xe1,0x1c }, - { 0xf2,0xf0,0xf3,0x07 }, { 0xff,0xfb,0xfd,0x0e }, - { 0xb4,0x92,0xa7,0x79 }, { 0xb9,0x99,0xa9,0x70 }, - { 0xae,0x84,0xbb,0x6b }, { 0xa3,0x8f,0xb5,0x62 }, - { 0x80,0xbe,0x9f,0x5d }, { 0x8d,0xb5,0x91,0x54 }, - { 0x9a,0xa8,0x83,0x4f }, { 0x97,0xa3,0x8d,0x46 } -}; - -static const byte U4[256][4] = { - { 0x00,0x00,0x00,0x00 }, { 0x09,0x0d,0x0b,0x0e }, - { 0x12,0x1a,0x16,0x1c }, { 0x1b,0x17,0x1d,0x12 }, - { 0x24,0x34,0x2c,0x38 }, { 0x2d,0x39,0x27,0x36 }, - { 0x36,0x2e,0x3a,0x24 }, { 0x3f,0x23,0x31,0x2a }, - { 0x48,0x68,0x58,0x70 }, { 0x41,0x65,0x53,0x7e }, - { 0x5a,0x72,0x4e,0x6c }, { 0x53,0x7f,0x45,0x62 }, - { 0x6c,0x5c,0x74,0x48 }, { 0x65,0x51,0x7f,0x46 }, - { 0x7e,0x46,0x62,0x54 }, { 0x77,0x4b,0x69,0x5a }, - { 0x90,0xd0,0xb0,0xe0 }, { 0x99,0xdd,0xbb,0xee }, - { 0x82,0xca,0xa6,0xfc }, { 0x8b,0xc7,0xad,0xf2 }, - { 0xb4,0xe4,0x9c,0xd8 }, { 0xbd,0xe9,0x97,0xd6 }, - { 0xa6,0xfe,0x8a,0xc4 }, { 0xaf,0xf3,0x81,0xca }, - { 0xd8,0xb8,0xe8,0x90 }, { 0xd1,0xb5,0xe3,0x9e }, - { 0xca,0xa2,0xfe,0x8c }, { 0xc3,0xaf,0xf5,0x82 }, - { 0xfc,0x8c,0xc4,0xa8 }, { 0xf5,0x81,0xcf,0xa6 }, - { 0xee,0x96,0xd2,0xb4 }, { 0xe7,0x9b,0xd9,0xba }, - { 0x3b,0xbb,0x7b,0xdb }, { 0x32,0xb6,0x70,0xd5 }, - { 0x29,0xa1,0x6d,0xc7 }, { 0x20,0xac,0x66,0xc9 }, - { 0x1f,0x8f,0x57,0xe3 }, { 0x16,0x82,0x5c,0xed }, - { 0x0d,0x95,0x41,0xff }, { 0x04,0x98,0x4a,0xf1 }, - { 0x73,0xd3,0x23,0xab }, { 0x7a,0xde,0x28,0xa5 }, - { 0x61,0xc9,0x35,0xb7 }, { 0x68,0xc4,0x3e,0xb9 }, - { 0x57,0xe7,0x0f,0x93 }, { 0x5e,0xea,0x04,0x9d }, - { 0x45,0xfd,0x19,0x8f }, { 0x4c,0xf0,0x12,0x81 }, - { 0xab,0x6b,0xcb,0x3b }, { 0xa2,0x66,0xc0,0x35 }, - { 0xb9,0x71,0xdd,0x27 }, { 0xb0,0x7c,0xd6,0x29 }, - { 0x8f,0x5f,0xe7,0x03 }, { 0x86,0x52,0xec,0x0d }, - { 0x9d,0x45,0xf1,0x1f }, { 0x94,0x48,0xfa,0x11 }, - { 0xe3,0x03,0x93,0x4b }, { 0xea,0x0e,0x98,0x45 }, - { 0xf1,0x19,0x85,0x57 }, { 0xf8,0x14,0x8e,0x59 }, - { 0xc7,0x37,0xbf,0x73 }, { 0xce,0x3a,0xb4,0x7d }, - { 0xd5,0x2d,0xa9,0x6f }, { 0xdc,0x20,0xa2,0x61 }, - { 0x76,0x6d,0xf6,0xad }, { 0x7f,0x60,0xfd,0xa3 }, - { 0x64,0x77,0xe0,0xb1 }, { 0x6d,0x7a,0xeb,0xbf }, - { 0x52,0x59,0xda,0x95 }, { 0x5b,0x54,0xd1,0x9b }, - { 0x40,0x43,0xcc,0x89 }, { 0x49,0x4e,0xc7,0x87 }, - { 0x3e,0x05,0xae,0xdd }, { 0x37,0x08,0xa5,0xd3 }, - { 0x2c,0x1f,0xb8,0xc1 }, { 0x25,0x12,0xb3,0xcf }, - { 0x1a,0x31,0x82,0xe5 }, { 0x13,0x3c,0x89,0xeb }, - { 0x08,0x2b,0x94,0xf9 }, { 0x01,0x26,0x9f,0xf7 }, - { 0xe6,0xbd,0x46,0x4d }, { 0xef,0xb0,0x4d,0x43 }, - { 0xf4,0xa7,0x50,0x51 }, { 0xfd,0xaa,0x5b,0x5f }, - { 0xc2,0x89,0x6a,0x75 }, { 0xcb,0x84,0x61,0x7b }, - { 0xd0,0x93,0x7c,0x69 }, { 0xd9,0x9e,0x77,0x67 }, - { 0xae,0xd5,0x1e,0x3d }, { 0xa7,0xd8,0x15,0x33 }, - { 0xbc,0xcf,0x08,0x21 }, { 0xb5,0xc2,0x03,0x2f }, - { 0x8a,0xe1,0x32,0x05 }, { 0x83,0xec,0x39,0x0b }, - { 0x98,0xfb,0x24,0x19 }, { 0x91,0xf6,0x2f,0x17 }, - { 0x4d,0xd6,0x8d,0x76 }, { 0x44,0xdb,0x86,0x78 }, - { 0x5f,0xcc,0x9b,0x6a }, { 0x56,0xc1,0x90,0x64 }, - { 0x69,0xe2,0xa1,0x4e }, { 0x60,0xef,0xaa,0x40 }, - { 0x7b,0xf8,0xb7,0x52 }, { 0x72,0xf5,0xbc,0x5c }, - { 0x05,0xbe,0xd5,0x06 }, { 0x0c,0xb3,0xde,0x08 }, - { 0x17,0xa4,0xc3,0x1a }, { 0x1e,0xa9,0xc8,0x14 }, - { 0x21,0x8a,0xf9,0x3e }, { 0x28,0x87,0xf2,0x30 }, - { 0x33,0x90,0xef,0x22 }, { 0x3a,0x9d,0xe4,0x2c }, - { 0xdd,0x06,0x3d,0x96 }, { 0xd4,0x0b,0x36,0x98 }, - { 0xcf,0x1c,0x2b,0x8a }, { 0xc6,0x11,0x20,0x84 }, - { 0xf9,0x32,0x11,0xae }, { 0xf0,0x3f,0x1a,0xa0 }, - { 0xeb,0x28,0x07,0xb2 }, { 0xe2,0x25,0x0c,0xbc }, - { 0x95,0x6e,0x65,0xe6 }, { 0x9c,0x63,0x6e,0xe8 }, - { 0x87,0x74,0x73,0xfa }, { 0x8e,0x79,0x78,0xf4 }, - { 0xb1,0x5a,0x49,0xde }, { 0xb8,0x57,0x42,0xd0 }, - { 0xa3,0x40,0x5f,0xc2 }, { 0xaa,0x4d,0x54,0xcc }, - { 0xec,0xda,0xf7,0x41 }, { 0xe5,0xd7,0xfc,0x4f }, - { 0xfe,0xc0,0xe1,0x5d }, { 0xf7,0xcd,0xea,0x53 }, - { 0xc8,0xee,0xdb,0x79 }, { 0xc1,0xe3,0xd0,0x77 }, - { 0xda,0xf4,0xcd,0x65 }, { 0xd3,0xf9,0xc6,0x6b }, - { 0xa4,0xb2,0xaf,0x31 }, { 0xad,0xbf,0xa4,0x3f }, - { 0xb6,0xa8,0xb9,0x2d }, { 0xbf,0xa5,0xb2,0x23 }, - { 0x80,0x86,0x83,0x09 }, { 0x89,0x8b,0x88,0x07 }, - { 0x92,0x9c,0x95,0x15 }, { 0x9b,0x91,0x9e,0x1b }, - { 0x7c,0x0a,0x47,0xa1 }, { 0x75,0x07,0x4c,0xaf }, - { 0x6e,0x10,0x51,0xbd }, { 0x67,0x1d,0x5a,0xb3 }, - { 0x58,0x3e,0x6b,0x99 }, { 0x51,0x33,0x60,0x97 }, - { 0x4a,0x24,0x7d,0x85 }, { 0x43,0x29,0x76,0x8b }, - { 0x34,0x62,0x1f,0xd1 }, { 0x3d,0x6f,0x14,0xdf }, - { 0x26,0x78,0x09,0xcd }, { 0x2f,0x75,0x02,0xc3 }, - { 0x10,0x56,0x33,0xe9 }, { 0x19,0x5b,0x38,0xe7 }, - { 0x02,0x4c,0x25,0xf5 }, { 0x0b,0x41,0x2e,0xfb }, - { 0xd7,0x61,0x8c,0x9a }, { 0xde,0x6c,0x87,0x94 }, - { 0xc5,0x7b,0x9a,0x86 }, { 0xcc,0x76,0x91,0x88 }, - { 0xf3,0x55,0xa0,0xa2 }, { 0xfa,0x58,0xab,0xac }, - { 0xe1,0x4f,0xb6,0xbe }, { 0xe8,0x42,0xbd,0xb0 }, - { 0x9f,0x09,0xd4,0xea }, { 0x96,0x04,0xdf,0xe4 }, - { 0x8d,0x13,0xc2,0xf6 }, { 0x84,0x1e,0xc9,0xf8 }, - { 0xbb,0x3d,0xf8,0xd2 }, { 0xb2,0x30,0xf3,0xdc }, - { 0xa9,0x27,0xee,0xce }, { 0xa0,0x2a,0xe5,0xc0 }, - { 0x47,0xb1,0x3c,0x7a }, { 0x4e,0xbc,0x37,0x74 }, - { 0x55,0xab,0x2a,0x66 }, { 0x5c,0xa6,0x21,0x68 }, - { 0x63,0x85,0x10,0x42 }, { 0x6a,0x88,0x1b,0x4c }, - { 0x71,0x9f,0x06,0x5e }, { 0x78,0x92,0x0d,0x50 }, - { 0x0f,0xd9,0x64,0x0a }, { 0x06,0xd4,0x6f,0x04 }, - { 0x1d,0xc3,0x72,0x16 }, { 0x14,0xce,0x79,0x18 }, - { 0x2b,0xed,0x48,0x32 }, { 0x22,0xe0,0x43,0x3c }, - { 0x39,0xf7,0x5e,0x2e }, { 0x30,0xfa,0x55,0x20 }, - { 0x9a,0xb7,0x01,0xec }, { 0x93,0xba,0x0a,0xe2 }, - { 0x88,0xad,0x17,0xf0 }, { 0x81,0xa0,0x1c,0xfe }, - { 0xbe,0x83,0x2d,0xd4 }, { 0xb7,0x8e,0x26,0xda }, - { 0xac,0x99,0x3b,0xc8 }, { 0xa5,0x94,0x30,0xc6 }, - { 0xd2,0xdf,0x59,0x9c }, { 0xdb,0xd2,0x52,0x92 }, - { 0xc0,0xc5,0x4f,0x80 }, { 0xc9,0xc8,0x44,0x8e }, - { 0xf6,0xeb,0x75,0xa4 }, { 0xff,0xe6,0x7e,0xaa }, - { 0xe4,0xf1,0x63,0xb8 }, { 0xed,0xfc,0x68,0xb6 }, - { 0x0a,0x67,0xb1,0x0c }, { 0x03,0x6a,0xba,0x02 }, - { 0x18,0x7d,0xa7,0x10 }, { 0x11,0x70,0xac,0x1e }, - { 0x2e,0x53,0x9d,0x34 }, { 0x27,0x5e,0x96,0x3a }, - { 0x3c,0x49,0x8b,0x28 }, { 0x35,0x44,0x80,0x26 }, - { 0x42,0x0f,0xe9,0x7c }, { 0x4b,0x02,0xe2,0x72 }, - { 0x50,0x15,0xff,0x60 }, { 0x59,0x18,0xf4,0x6e }, - { 0x66,0x3b,0xc5,0x44 }, { 0x6f,0x36,0xce,0x4a }, - { 0x74,0x21,0xd3,0x58 }, { 0x7d,0x2c,0xd8,0x56 }, - { 0xa1,0x0c,0x7a,0x37 }, { 0xa8,0x01,0x71,0x39 }, - { 0xb3,0x16,0x6c,0x2b }, { 0xba,0x1b,0x67,0x25 }, - { 0x85,0x38,0x56,0x0f }, { 0x8c,0x35,0x5d,0x01 }, - { 0x97,0x22,0x40,0x13 }, { 0x9e,0x2f,0x4b,0x1d }, - { 0xe9,0x64,0x22,0x47 }, { 0xe0,0x69,0x29,0x49 }, - { 0xfb,0x7e,0x34,0x5b }, { 0xf2,0x73,0x3f,0x55 }, - { 0xcd,0x50,0x0e,0x7f }, { 0xc4,0x5d,0x05,0x71 }, - { 0xdf,0x4a,0x18,0x63 }, { 0xd6,0x47,0x13,0x6d }, - { 0x31,0xdc,0xca,0xd7 }, { 0x38,0xd1,0xc1,0xd9 }, - { 0x23,0xc6,0xdc,0xcb }, { 0x2a,0xcb,0xd7,0xc5 }, - { 0x15,0xe8,0xe6,0xef }, { 0x1c,0xe5,0xed,0xe1 }, - { 0x07,0xf2,0xf0,0xf3 }, { 0x0e,0xff,0xfb,0xfd }, - { 0x79,0xb4,0x92,0xa7 }, { 0x70,0xb9,0x99,0xa9 }, - { 0x6b,0xae,0x84,0xbb }, { 0x62,0xa3,0x8f,0xb5 }, - { 0x5d,0x80,0xbe,0x9f }, { 0x54,0x8d,0xb5,0x91 }, - { 0x4f,0x9a,0xa8,0x83 }, { 0x46,0x97,0xa3,0x8d } -}; - -static const u32 rcon[30] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, - 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, - 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 -}; - - - -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -/* Perform the key setup. - */ -static int -do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) -{ - static int initialized = 0; - static const char *selftest_failed=0; - int ROUNDS; - byte k[MAXKC][4]; - int i,j, r, t, rconpointer = 0; - byte tk[MAXKC][4]; - int KC; - /* space for automatic variables is about 64 + 11*int */ - - if (!initialized) { - initialized = 1; - selftest_failed = selftest (); - if( selftest_failed ) - fprintf(stderr, "%s\n", selftest_failed ); - } - if( selftest_failed ) - return G10ERR_SELFTEST_FAILED; - - if( keylen == 128/8 ) { - ROUNDS = 10; - KC = 4; - } - else if ( keylen == 192/8 ) { - ROUNDS = 12; - KC = 6; - } - else if ( keylen == 256/8 ) { - ROUNDS = 14; - KC = 8; - } - else - return G10ERR_WRONG_KEYLEN; - - ctx->ROUNDS = ROUNDS; - ctx->decryption_prepared = 0; - - for (i = 0; i < keylen; i++) { - k[i >> 2][i & 3] = key[i]; - } - #define W (ctx->keySched) - - for (j = KC-1; j >= 0; j--) { - *((u32*)tk[j]) = *((u32*)k[j]); - } - r = 0; - t = 0; - /* copy values into round key array */ - for (j = 0; (j < KC) && (r < ROUNDS + 1); ) { - for (; (j < KC) && (t < 4); j++, t++) { - *((u32*)W[r][t]) = *((u32*)tk[j]); - } - if (t == 4) { - r++; - t = 0; - } - } - - while (r < ROUNDS + 1) { - /* while not enough round key material calculated */ - /* calculate new values */ - tk[0][0] ^= S[tk[KC-1][1]]; - tk[0][1] ^= S[tk[KC-1][2]]; - tk[0][2] ^= S[tk[KC-1][3]]; - tk[0][3] ^= S[tk[KC-1][0]]; - tk[0][0] ^= rcon[rconpointer++]; - - if (KC != 8) { - for (j = 1; j < KC; j++) { - *((u32*)tk[j]) ^= *((u32*)tk[j-1]); - } - } else { - for (j = 1; j < KC/2; j++) { - *((u32*)tk[j]) ^= *((u32*)tk[j-1]); - } - tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; - tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; - tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; - tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; - for (j = KC/2 + 1; j < KC; j++) { - *((u32*)tk[j]) ^= *((u32*)tk[j-1]); - } - } - /* copy values into round key array */ - for (j = 0; (j < KC) && (r < ROUNDS + 1); ) { - for (; (j < KC) && (t < 4); j++, t++) { - *((u32*)W[r][t]) = *((u32*)tk[j]); - } - if (t == 4) { - r++; - t = 0; - } - } - } - - #undef W - return 0; -} - -static int -rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) -{ - int rc = do_setkey (ctx, key, keylen); - burn_stack ( 100 + 16*sizeof(int)); - return rc; -} - -/* make a decryption key from an encryption key */ -static void -prepare_decryption( RIJNDAEL_context *ctx ) -{ - int r; - byte *w; - - for (r=0; r < MAXROUNDS+1; r++ ) { - *((u32*)ctx->keySched2[r][0]) = *((u32*)ctx->keySched[r][0]); - *((u32*)ctx->keySched2[r][1]) = *((u32*)ctx->keySched[r][1]); - *((u32*)ctx->keySched2[r][2]) = *((u32*)ctx->keySched[r][2]); - *((u32*)ctx->keySched2[r][3]) = *((u32*)ctx->keySched[r][3]); - } - #define W (ctx->keySched2) - for (r = 1; r < ctx->ROUNDS; r++) { - w = W[r][0]; - *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) - ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); - - w = W[r][1]; - *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) - ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); - - w = W[r][2]; - *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) - ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); - - w = W[r][3]; - *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]]) - ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]); - } - #undef W -} - - - -/* Encrypt one block. A and B may be the same. */ -static void -do_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a) -{ - int r; - byte temp[4][4]; - int ROUNDS = ctx->ROUNDS; - #define rk (ctx->keySched) - - *((u32*)temp[0]) = *((u32*)(a )) ^ *((u32*)rk[0][0]); - *((u32*)temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[0][1]); - *((u32*)temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[0][2]); - *((u32*)temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[0][3]); - *((u32*)(b )) = *((u32*)T1[temp[0][0]]) - ^ *((u32*)T2[temp[1][1]]) - ^ *((u32*)T3[temp[2][2]]) - ^ *((u32*)T4[temp[3][3]]); - *((u32*)(b + 4)) = *((u32*)T1[temp[1][0]]) - ^ *((u32*)T2[temp[2][1]]) - ^ *((u32*)T3[temp[3][2]]) - ^ *((u32*)T4[temp[0][3]]); - *((u32*)(b + 8)) = *((u32*)T1[temp[2][0]]) - ^ *((u32*)T2[temp[3][1]]) - ^ *((u32*)T3[temp[0][2]]) - ^ *((u32*)T4[temp[1][3]]); - *((u32*)(b +12)) = *((u32*)T1[temp[3][0]]) - ^ *((u32*)T2[temp[0][1]]) - ^ *((u32*)T3[temp[1][2]]) - ^ *((u32*)T4[temp[2][3]]); - for (r = 1; r < ROUNDS-1; r++) { - *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]); - *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]); - *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]); - *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]); - - *((u32*)(b )) = *((u32*)T1[temp[0][0]]) - ^ *((u32*)T2[temp[1][1]]) - ^ *((u32*)T3[temp[2][2]]) - ^ *((u32*)T4[temp[3][3]]); - *((u32*)(b + 4)) = *((u32*)T1[temp[1][0]]) - ^ *((u32*)T2[temp[2][1]]) - ^ *((u32*)T3[temp[3][2]]) - ^ *((u32*)T4[temp[0][3]]); - *((u32*)(b + 8)) = *((u32*)T1[temp[2][0]]) - ^ *((u32*)T2[temp[3][1]]) - ^ *((u32*)T3[temp[0][2]]) - ^ *((u32*)T4[temp[1][3]]); - *((u32*)(b +12)) = *((u32*)T1[temp[3][0]]) - ^ *((u32*)T2[temp[0][1]]) - ^ *((u32*)T3[temp[1][2]]) - ^ *((u32*)T4[temp[2][3]]); - } - /* last round is special */ - *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[ROUNDS-1][0]); - *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[ROUNDS-1][1]); - *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[ROUNDS-1][2]); - *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[ROUNDS-1][3]); - b[ 0] = T1[temp[0][0]][1]; - b[ 1] = T1[temp[1][1]][1]; - b[ 2] = T1[temp[2][2]][1]; - b[ 3] = T1[temp[3][3]][1]; - b[ 4] = T1[temp[1][0]][1]; - b[ 5] = T1[temp[2][1]][1]; - b[ 6] = T1[temp[3][2]][1]; - b[ 7] = T1[temp[0][3]][1]; - b[ 8] = T1[temp[2][0]][1]; - b[ 9] = T1[temp[3][1]][1]; - b[10] = T1[temp[0][2]][1]; - b[11] = T1[temp[1][3]][1]; - b[12] = T1[temp[3][0]][1]; - b[13] = T1[temp[0][1]][1]; - b[14] = T1[temp[1][2]][1]; - b[15] = T1[temp[2][3]][1]; - *((u32*)(b )) ^= *((u32*)rk[ROUNDS][0]); - *((u32*)(b+ 4)) ^= *((u32*)rk[ROUNDS][1]); - *((u32*)(b+ 8)) ^= *((u32*)rk[ROUNDS][2]); - *((u32*)(b+12)) ^= *((u32*)rk[ROUNDS][3]); - #undef rk -} - -static void -rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a) -{ - do_encrypt (ctx, b, a); - burn_stack (16 + 2*sizeof(int)); -} - - -/* Decrypt one block. a and b may be the same. */ -static void -do_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) -{ - #define rk (ctx->keySched2) - int ROUNDS = ctx->ROUNDS; - int r; - byte temp[4][4]; - - if ( !ctx->decryption_prepared ) { - prepare_decryption ( ctx ); - burn_stack (64); - ctx->decryption_prepared = 1; - } - - *((u32*)temp[0]) = *((u32*)(a )) ^ *((u32*)rk[ROUNDS][0]); - *((u32*)temp[1]) = *((u32*)(a+ 4)) ^ *((u32*)rk[ROUNDS][1]); - *((u32*)temp[2]) = *((u32*)(a+ 8)) ^ *((u32*)rk[ROUNDS][2]); - *((u32*)temp[3]) = *((u32*)(a+12)) ^ *((u32*)rk[ROUNDS][3]); - - *((u32*)(b )) = *((u32*)T5[temp[0][0]]) - ^ *((u32*)T6[temp[3][1]]) - ^ *((u32*)T7[temp[2][2]]) - ^ *((u32*)T8[temp[1][3]]); - *((u32*)(b+ 4)) = *((u32*)T5[temp[1][0]]) - ^ *((u32*)T6[temp[0][1]]) - ^ *((u32*)T7[temp[3][2]]) - ^ *((u32*)T8[temp[2][3]]); - *((u32*)(b+ 8)) = *((u32*)T5[temp[2][0]]) - ^ *((u32*)T6[temp[1][1]]) - ^ *((u32*)T7[temp[0][2]]) - ^ *((u32*)T8[temp[3][3]]); - *((u32*)(b+12)) = *((u32*)T5[temp[3][0]]) - ^ *((u32*)T6[temp[2][1]]) - ^ *((u32*)T7[temp[1][2]]) - ^ *((u32*)T8[temp[0][3]]); - for (r = ROUNDS-1; r > 1; r--) { - *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[r][0]); - *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[r][1]); - *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[r][2]); - *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[r][3]); - *((u32*)(b )) = *((u32*)T5[temp[0][0]]) - ^ *((u32*)T6[temp[3][1]]) - ^ *((u32*)T7[temp[2][2]]) - ^ *((u32*)T8[temp[1][3]]); - *((u32*)(b+ 4)) = *((u32*)T5[temp[1][0]]) - ^ *((u32*)T6[temp[0][1]]) - ^ *((u32*)T7[temp[3][2]]) - ^ *((u32*)T8[temp[2][3]]); - *((u32*)(b+ 8)) = *((u32*)T5[temp[2][0]]) - ^ *((u32*)T6[temp[1][1]]) - ^ *((u32*)T7[temp[0][2]]) - ^ *((u32*)T8[temp[3][3]]); - *((u32*)(b+12)) = *((u32*)T5[temp[3][0]]) - ^ *((u32*)T6[temp[2][1]]) - ^ *((u32*)T7[temp[1][2]]) - ^ *((u32*)T8[temp[0][3]]); - } - /* last round is special */ - *((u32*)temp[0]) = *((u32*)(b )) ^ *((u32*)rk[1][0]); - *((u32*)temp[1]) = *((u32*)(b+ 4)) ^ *((u32*)rk[1][1]); - *((u32*)temp[2]) = *((u32*)(b+ 8)) ^ *((u32*)rk[1][2]); - *((u32*)temp[3]) = *((u32*)(b+12)) ^ *((u32*)rk[1][3]); - b[ 0] = S5[temp[0][0]]; - b[ 1] = S5[temp[3][1]]; - b[ 2] = S5[temp[2][2]]; - b[ 3] = S5[temp[1][3]]; - b[ 4] = S5[temp[1][0]]; - b[ 5] = S5[temp[0][1]]; - b[ 6] = S5[temp[3][2]]; - b[ 7] = S5[temp[2][3]]; - b[ 8] = S5[temp[2][0]]; - b[ 9] = S5[temp[1][1]]; - b[10] = S5[temp[0][2]]; - b[11] = S5[temp[3][3]]; - b[12] = S5[temp[3][0]]; - b[13] = S5[temp[2][1]]; - b[14] = S5[temp[1][2]]; - b[15] = S5[temp[0][3]]; - *((u32*)(b )) ^= *((u32*)rk[0][0]); - *((u32*)(b+ 4)) ^= *((u32*)rk[0][1]); - *((u32*)(b+ 8)) ^= *((u32*)rk[0][2]); - *((u32*)(b+12)) ^= *((u32*)rk[0][3]); - #undef rk -} - -static void -rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a) -{ - do_decrypt (ctx, b, a); - burn_stack (16+2*sizeof(int)); -} - -/* Test a single encryption and decryption with each key size. */ - -static const char* -selftest (void) -{ - RIJNDAEL_context ctx; - byte scratch[16]; - - /* The test vectors are from the AES supplied ones; more or less - * randomly taken from ecb_tbl.txt (I=42,81,14) - */ - static const byte plaintext[16] = { - 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33, - 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A - }; - static const byte key[16] = { - 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0, - 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA - }; - static const byte ciphertext[16] = { - 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2, - 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD - }; - - static const byte plaintext_192[16] = { - 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4, - 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72 - }; - static const byte key_192[24] = { - 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C, - 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16, - 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20 - }; - static const byte ciphertext_192[16] = { - 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC, - 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA - }; - - static const byte plaintext_256[16] = { - 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, - 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 - }; - static const byte key_256[32] = { - 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10, - 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A, - 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24, - 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E - }; - static const byte ciphertext_256[16] = { - 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71, - 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3 - }; - - rijndael_setkey (&ctx, key, sizeof(key)); - rijndael_encrypt (&ctx, scratch, plaintext); - if (memcmp (scratch, ciphertext, sizeof (ciphertext))) - return "Rijndael-128 test encryption failed."; - rijndael_decrypt (&ctx, scratch, scratch); - if (memcmp (scratch, plaintext, sizeof (plaintext))) - return "Rijndael-128 test decryption failed."; - - rijndael_setkey (&ctx, key_192, sizeof(key_192)); - rijndael_encrypt (&ctx, scratch, plaintext_192); - if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192))) - return "Rijndael-192 test encryption failed."; - rijndael_decrypt (&ctx, scratch, scratch); - if (memcmp (scratch, plaintext_192, sizeof (plaintext_192))) - return "Rijndael-192 test decryption failed."; - - rijndael_setkey (&ctx, key_256, sizeof(key_256)); - rijndael_encrypt (&ctx, scratch, plaintext_256); - if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) - return "Rijndael-256 test encryption failed."; - rijndael_decrypt (&ctx, scratch, scratch); - if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) - return "Rijndael-256 test decryption failed."; - - return NULL; -} - -#ifdef IS_MODULE -static -#endif - const char * -rijndael_get_info (int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**r_setkey) (void *c, byte *key, unsigned keylen), - void (**r_encrypt) (void *c, byte *outbuf, byte *inbuf), - void (**r_decrypt) (void *c, byte *outbuf, byte *inbuf) - ) -{ - *keylen = algo==7? 128 : algo==8? 192 : 256; - *blocksize = 16; - *contextsize = sizeof (RIJNDAEL_context); - - *(int (**)(RIJNDAEL_context*, const byte*, const unsigned))r_setkey - = rijndael_setkey; - *(void (**)(const RIJNDAEL_context*, byte*, const byte*))r_encrypt - = rijndael_encrypt; - *(void (**)(RIJNDAEL_context*, byte*, const byte*))r_decrypt - = rijndael_decrypt; - - if( algo == 7 ) - return "AES"; - if (algo == 8) - return "AES192"; - if (algo == 9) - return "AES256"; - return NULL; -} - - -#ifdef IS_MODULE -static -const char * const gnupgext_version = "RIJNDAEL ($Revision$)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 20, 1, 0, (void(*)(void))rijndael_get_info }, - { 21, 1, 7 }, - { 21, 1, 8 }, - { 21, 1, 9 }, -}; - - - -/**************** - * Enumerate the names of the functions together with information about - * this function. Set sequence to an integer with a initial value of 0 and - * do not change it. - * If what is 0 all kind of functions are returned. - * Return values: class := class of function: - * 10 = message digest algorithm info function - * 11 = integer with available md algorithms - * 20 = cipher algorithm info function - * 21 = integer with available cipher algorithms - * 30 = public key algorithm info function - * 31 = integer with available pubkey algorithms - * version = interface version of the function/pointer - * (currently this is 1 for all functions) - */ -static -void * -gnupgext_enum_func ( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if ( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - switch( *class ) { - case 11: - case 21: - case 31: - ret = &func_table[i].value; - break; - default: - ret = func_table[i].func; - break; - } - i++; - } while ( what && what != *class ); - - *sequence = i; - return ret; -} -#endif - - - - - - - - - diff --git a/cipher/rmd.h b/cipher/rmd.h deleted file mode 100644 index 917e04a26..000000000 --- a/cipher/rmd.h +++ /dev/null @@ -1,35 +0,0 @@ -/* rmd.h - RIPE-MD hash 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 - */ -#ifndef G10_RMD_H -#define G10_RMD_H - - -/* we need this here because random.c must have direct access */ -typedef struct { - u32 h0,h1,h2,h3,h4; - u32 nblocks; - byte buf[64]; - int count; -} RMD160_CONTEXT; - -void rmd160_init( RMD160_CONTEXT *hd ); -void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); - -#endif /*G10_RMD_H*/ diff --git a/cipher/rmd160.c b/cipher/rmd160.c deleted file mode 100644 index 54dec6a15..000000000 --- a/cipher/rmd160.c +++ /dev/null @@ -1,588 +0,0 @@ -/* rmd160.c - RIPE-MD160 - * 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 -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "rmd.h" -#include "cipher.h" /* for rmd160_hash_buffer */ -#include "algorithms.h" - -#include "bithelp.h" - -/********************************* - * RIPEMD-160 is not patented, see (as of 25.10.97) - * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html - * Note that the code uses Little Endian byteorder, which is good for - * 386 etc, but we must add some conversion when used on a big endian box. - * - * - * Pseudo-code for RIPEMD-160 - * - * RIPEMD-160 is an iterative hash function that operates on 32-bit words. - * The round function takes as input a 5-word chaining variable and a 16-word - * message block and maps this to a new chaining variable. All operations are - * defined on 32-bit words. Padding is identical to that of MD4. - * - * - * RIPEMD-160: definitions - * - * - * nonlinear functions at bit level: exor, mux, -, mux, - - * - * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) - * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) - * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) - * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) - * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) - * - * - * added constants (hexadecimal) - * - * K(j) = 0x00000000 (0 <= j <= 15) - * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) - * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) - * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) - * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) - * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) - * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) - * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) - * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) - * K'(j) = 0x00000000 (64 <= j <= 79) - * - * - * selection of message word - * - * r(j) = j (0 <= j <= 15) - * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 - * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 - * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 - * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 - * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 - * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 - * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 - * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - * - * - * amount for rotate left (rol) - * - * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 - * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 - * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 - * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 - * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 - * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 - * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 - * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 - * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - * - * - * initial value (hexadecimal) - * - * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; - * h4 = 0xC3D2E1F0; - * - * - * RIPEMD-160: pseudo-code - * - * It is assumed that the message after padding consists of t 16-word blocks - * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. - * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left - * shift (rotate) over s positions. - * - * - * for i := 0 to t-1 { - * A := h0; B := h1; C := h2; D = h3; E = h4; - * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; - * for j := 0 to 79 { - * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; - * A := E; E := D; D := rol_10(C); C := B; B := T; - * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] - [+] K'(j)) [+] E'; - * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; - * } - * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; - * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; - * } - */ - -/* Some examples: - * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 - * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe - * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc - * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 - * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc - * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b - * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 - * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb - * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 - */ - -static void -burn_stack (int bytes) -{ - char buf[150]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - - -void -rmd160_init( RMD160_CONTEXT *hd ) -{ - hd->h0 = 0x67452301; - hd->h1 = 0xEFCDAB89; - hd->h2 = 0x98BADCFE; - hd->h3 = 0x10325476; - hd->h4 = 0xC3D2E1F0; - hd->nblocks = 0; - hd->count = 0; -} - - - -/**************** - * Transform the message X which consists of 16 32-bit-words - */ -static void -transform( RMD160_CONTEXT *hd, byte *data ) -{ - u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; - #ifdef BIG_ENDIAN_HOST - u32 x[16]; - { int i; - byte *p2, *p1; - for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } - #else - #if 0 - u32 *x =(u32*)data; - #else - /* this version is better because it is always aligned; - * The performance penalty on a 586-100 is about 6% which - * is acceptable - because the data is more local it might - * also be possible that this is faster on some machines. - * This function (when compiled with -02 on gcc 2.7.2) - * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; - * [measured with a 4MB data and "gpgm --print-md rmd160"] */ - u32 x[16]; - memcpy( x, data, 64 ); - #endif - #endif - - -#define K0 0x00000000 -#define K1 0x5A827999 -#define K2 0x6ED9EBA1 -#define K3 0x8F1BBCDC -#define K4 0xA953FD4E -#define KK0 0x50A28BE6 -#define KK1 0x5C4DD124 -#define KK2 0x6D703EF3 -#define KK3 0x7A6D76E9 -#define KK4 0x00000000 -#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) -#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) -#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) -#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) -#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) -#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ - a = rol(t,s) + e; \ - c = rol(c,10); \ - } while(0) - - /* left lane */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - R( a, b, c, d, e, F0, K0, 0, 11 ); - R( e, a, b, c, d, F0, K0, 1, 14 ); - R( d, e, a, b, c, F0, K0, 2, 15 ); - R( c, d, e, a, b, F0, K0, 3, 12 ); - R( b, c, d, e, a, F0, K0, 4, 5 ); - R( a, b, c, d, e, F0, K0, 5, 8 ); - R( e, a, b, c, d, F0, K0, 6, 7 ); - R( d, e, a, b, c, F0, K0, 7, 9 ); - R( c, d, e, a, b, F0, K0, 8, 11 ); - R( b, c, d, e, a, F0, K0, 9, 13 ); - R( a, b, c, d, e, F0, K0, 10, 14 ); - R( e, a, b, c, d, F0, K0, 11, 15 ); - R( d, e, a, b, c, F0, K0, 12, 6 ); - R( c, d, e, a, b, F0, K0, 13, 7 ); - R( b, c, d, e, a, F0, K0, 14, 9 ); - R( a, b, c, d, e, F0, K0, 15, 8 ); - R( e, a, b, c, d, F1, K1, 7, 7 ); - R( d, e, a, b, c, F1, K1, 4, 6 ); - R( c, d, e, a, b, F1, K1, 13, 8 ); - R( b, c, d, e, a, F1, K1, 1, 13 ); - R( a, b, c, d, e, F1, K1, 10, 11 ); - R( e, a, b, c, d, F1, K1, 6, 9 ); - R( d, e, a, b, c, F1, K1, 15, 7 ); - R( c, d, e, a, b, F1, K1, 3, 15 ); - R( b, c, d, e, a, F1, K1, 12, 7 ); - R( a, b, c, d, e, F1, K1, 0, 12 ); - R( e, a, b, c, d, F1, K1, 9, 15 ); - R( d, e, a, b, c, F1, K1, 5, 9 ); - R( c, d, e, a, b, F1, K1, 2, 11 ); - R( b, c, d, e, a, F1, K1, 14, 7 ); - R( a, b, c, d, e, F1, K1, 11, 13 ); - R( e, a, b, c, d, F1, K1, 8, 12 ); - R( d, e, a, b, c, F2, K2, 3, 11 ); - R( c, d, e, a, b, F2, K2, 10, 13 ); - R( b, c, d, e, a, F2, K2, 14, 6 ); - R( a, b, c, d, e, F2, K2, 4, 7 ); - R( e, a, b, c, d, F2, K2, 9, 14 ); - R( d, e, a, b, c, F2, K2, 15, 9 ); - R( c, d, e, a, b, F2, K2, 8, 13 ); - R( b, c, d, e, a, F2, K2, 1, 15 ); - R( a, b, c, d, e, F2, K2, 2, 14 ); - R( e, a, b, c, d, F2, K2, 7, 8 ); - R( d, e, a, b, c, F2, K2, 0, 13 ); - R( c, d, e, a, b, F2, K2, 6, 6 ); - R( b, c, d, e, a, F2, K2, 13, 5 ); - R( a, b, c, d, e, F2, K2, 11, 12 ); - R( e, a, b, c, d, F2, K2, 5, 7 ); - R( d, e, a, b, c, F2, K2, 12, 5 ); - R( c, d, e, a, b, F3, K3, 1, 11 ); - R( b, c, d, e, a, F3, K3, 9, 12 ); - R( a, b, c, d, e, F3, K3, 11, 14 ); - R( e, a, b, c, d, F3, K3, 10, 15 ); - R( d, e, a, b, c, F3, K3, 0, 14 ); - R( c, d, e, a, b, F3, K3, 8, 15 ); - R( b, c, d, e, a, F3, K3, 12, 9 ); - R( a, b, c, d, e, F3, K3, 4, 8 ); - R( e, a, b, c, d, F3, K3, 13, 9 ); - R( d, e, a, b, c, F3, K3, 3, 14 ); - R( c, d, e, a, b, F3, K3, 7, 5 ); - R( b, c, d, e, a, F3, K3, 15, 6 ); - R( a, b, c, d, e, F3, K3, 14, 8 ); - R( e, a, b, c, d, F3, K3, 5, 6 ); - R( d, e, a, b, c, F3, K3, 6, 5 ); - R( c, d, e, a, b, F3, K3, 2, 12 ); - R( b, c, d, e, a, F4, K4, 4, 9 ); - R( a, b, c, d, e, F4, K4, 0, 15 ); - R( e, a, b, c, d, F4, K4, 5, 5 ); - R( d, e, a, b, c, F4, K4, 9, 11 ); - R( c, d, e, a, b, F4, K4, 7, 6 ); - R( b, c, d, e, a, F4, K4, 12, 8 ); - R( a, b, c, d, e, F4, K4, 2, 13 ); - R( e, a, b, c, d, F4, K4, 10, 12 ); - R( d, e, a, b, c, F4, K4, 14, 5 ); - R( c, d, e, a, b, F4, K4, 1, 12 ); - R( b, c, d, e, a, F4, K4, 3, 13 ); - R( a, b, c, d, e, F4, K4, 8, 14 ); - R( e, a, b, c, d, F4, K4, 11, 11 ); - R( d, e, a, b, c, F4, K4, 6, 8 ); - R( c, d, e, a, b, F4, K4, 15, 5 ); - R( b, c, d, e, a, F4, K4, 13, 6 ); - - aa = a; bb = b; cc = c; dd = d; ee = e; - - /* right lane */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - R( a, b, c, d, e, F4, KK0, 5, 8); - R( e, a, b, c, d, F4, KK0, 14, 9); - R( d, e, a, b, c, F4, KK0, 7, 9); - R( c, d, e, a, b, F4, KK0, 0, 11); - R( b, c, d, e, a, F4, KK0, 9, 13); - R( a, b, c, d, e, F4, KK0, 2, 15); - R( e, a, b, c, d, F4, KK0, 11, 15); - R( d, e, a, b, c, F4, KK0, 4, 5); - R( c, d, e, a, b, F4, KK0, 13, 7); - R( b, c, d, e, a, F4, KK0, 6, 7); - R( a, b, c, d, e, F4, KK0, 15, 8); - R( e, a, b, c, d, F4, KK0, 8, 11); - R( d, e, a, b, c, F4, KK0, 1, 14); - R( c, d, e, a, b, F4, KK0, 10, 14); - R( b, c, d, e, a, F4, KK0, 3, 12); - R( a, b, c, d, e, F4, KK0, 12, 6); - R( e, a, b, c, d, F3, KK1, 6, 9); - R( d, e, a, b, c, F3, KK1, 11, 13); - R( c, d, e, a, b, F3, KK1, 3, 15); - R( b, c, d, e, a, F3, KK1, 7, 7); - R( a, b, c, d, e, F3, KK1, 0, 12); - R( e, a, b, c, d, F3, KK1, 13, 8); - R( d, e, a, b, c, F3, KK1, 5, 9); - R( c, d, e, a, b, F3, KK1, 10, 11); - R( b, c, d, e, a, F3, KK1, 14, 7); - R( a, b, c, d, e, F3, KK1, 15, 7); - R( e, a, b, c, d, F3, KK1, 8, 12); - R( d, e, a, b, c, F3, KK1, 12, 7); - R( c, d, e, a, b, F3, KK1, 4, 6); - R( b, c, d, e, a, F3, KK1, 9, 15); - R( a, b, c, d, e, F3, KK1, 1, 13); - R( e, a, b, c, d, F3, KK1, 2, 11); - R( d, e, a, b, c, F2, KK2, 15, 9); - R( c, d, e, a, b, F2, KK2, 5, 7); - R( b, c, d, e, a, F2, KK2, 1, 15); - R( a, b, c, d, e, F2, KK2, 3, 11); - R( e, a, b, c, d, F2, KK2, 7, 8); - R( d, e, a, b, c, F2, KK2, 14, 6); - R( c, d, e, a, b, F2, KK2, 6, 6); - R( b, c, d, e, a, F2, KK2, 9, 14); - R( a, b, c, d, e, F2, KK2, 11, 12); - R( e, a, b, c, d, F2, KK2, 8, 13); - R( d, e, a, b, c, F2, KK2, 12, 5); - R( c, d, e, a, b, F2, KK2, 2, 14); - R( b, c, d, e, a, F2, KK2, 10, 13); - R( a, b, c, d, e, F2, KK2, 0, 13); - R( e, a, b, c, d, F2, KK2, 4, 7); - R( d, e, a, b, c, F2, KK2, 13, 5); - R( c, d, e, a, b, F1, KK3, 8, 15); - R( b, c, d, e, a, F1, KK3, 6, 5); - R( a, b, c, d, e, F1, KK3, 4, 8); - R( e, a, b, c, d, F1, KK3, 1, 11); - R( d, e, a, b, c, F1, KK3, 3, 14); - R( c, d, e, a, b, F1, KK3, 11, 14); - R( b, c, d, e, a, F1, KK3, 15, 6); - R( a, b, c, d, e, F1, KK3, 0, 14); - R( e, a, b, c, d, F1, KK3, 5, 6); - R( d, e, a, b, c, F1, KK3, 12, 9); - R( c, d, e, a, b, F1, KK3, 2, 12); - R( b, c, d, e, a, F1, KK3, 13, 9); - R( a, b, c, d, e, F1, KK3, 9, 12); - R( e, a, b, c, d, F1, KK3, 7, 5); - R( d, e, a, b, c, F1, KK3, 10, 15); - R( c, d, e, a, b, F1, KK3, 14, 8); - R( b, c, d, e, a, F0, KK4, 12, 8); - R( a, b, c, d, e, F0, KK4, 15, 5); - R( e, a, b, c, d, F0, KK4, 10, 12); - R( d, e, a, b, c, F0, KK4, 4, 9); - R( c, d, e, a, b, F0, KK4, 1, 12); - R( b, c, d, e, a, F0, KK4, 5, 5); - R( a, b, c, d, e, F0, KK4, 8, 14); - R( e, a, b, c, d, F0, KK4, 7, 6); - R( d, e, a, b, c, F0, KK4, 6, 8); - R( c, d, e, a, b, F0, KK4, 2, 13); - R( b, c, d, e, a, F0, KK4, 13, 6); - R( a, b, c, d, e, F0, KK4, 14, 5); - R( e, a, b, c, d, F0, KK4, 0, 15); - R( d, e, a, b, c, F0, KK4, 3, 13); - R( c, d, e, a, b, F0, KK4, 9, 11); - R( b, c, d, e, a, F0, KK4, 11, 11); - - - t = hd->h1 + d + cc; - hd->h1 = hd->h2 + e + dd; - hd->h2 = hd->h3 + a + ee; - hd->h3 = hd->h4 + b + aa; - hd->h4 = hd->h0 + c + bb; - hd->h0 = t; -} - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -static void -rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) -{ - if( hd->count == 64 ) { /* flush the buffer */ - transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); - hd->count = 0; - hd->nblocks++; - } - if( !inbuf ) - return; - if( hd->count ) { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; - rmd160_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - - while( inlen >= 64 ) { - transform( hd, inbuf ); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - burn_stack (108+5*sizeof(void*)); - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; -} - -/**************** - * Apply the rmd160 transform function on the buffer which must have - * a length 64 bytes. Do not use this function together with the - * other functions, use rmd160_init to initialize internal variables. - * Returns: 16 bytes in buffer with the mixed contentes of buffer. - */ -void -rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) -{ - char *p = buffer; - transform( hd, buffer ); - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X -} - - -/* The routine terminates the computation - */ - -static void -rmd160_final( RMD160_CONTEXT *hd ) -{ - u32 t, msb, lsb; - byte *p; - - rmd160_write(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if( (lsb += hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if( hd->count < 56 ) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] = 0; - rmd160_write(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = lsb ; - hd->buf[57] = lsb >> 8; - hd->buf[58] = lsb >> 16; - hd->buf[59] = lsb >> 24; - hd->buf[60] = msb ; - hd->buf[61] = msb >> 8; - hd->buf[62] = msb >> 16; - hd->buf[63] = msb >> 24; - transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); - - p = hd->buf; - #ifdef BIG_ENDIAN_HOST - #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ - *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) - #else /* little endian */ - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - #endif - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X -} - -static byte * -rmd160_read( RMD160_CONTEXT *hd ) -{ - return hd->buf; -} - - - -/**************** - * Shortcut functions which puts the hash value of the supplied buffer - * into outbuf which must have a size of 20 bytes. - */ -void -rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) -{ - RMD160_CONTEXT hd; - - rmd160_init( &hd ); - rmd160_write( &hd, (byte*)buffer, length ); - rmd160_final( &hd ); - memcpy( outbuf, hd.buf, 20 ); -} - - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -const char * -rmd160_get_info( int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ) -{ - static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, - 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; - - if( algo != 3 ) - return NULL; - - *contextsize = sizeof(RMD160_CONTEXT); - *r_asnoid = asn; - *r_asnlen = DIM(asn); - *r_mdlen = 20; - *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; - *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; - *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; - *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; - - return "RIPEMD160"; -} - diff --git a/cipher/rmd160test.c b/cipher/rmd160test.c deleted file mode 100644 index 14afb435b..000000000 --- a/cipher/rmd160test.c +++ /dev/null @@ -1,63 +0,0 @@ -/* rmd160test.c - ripe md160 test program - * 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 -#include -#include -#include - -#include "util.h" -#include "rmd.h" - -static void -usage(void) -{ - fprintf(stderr, "usage: rmd160test\n"); - exit(1); -} - - -int -main(int argc, char **argv) -{ - RMDHANDLE rmdhd; - int i, n; - byte buf[100], *p; - - if( argc > 1 ) - usage(); - - rmdhd = rmd160_open(0); - #if 1 - while( (n = fread( buf, 1, 100, stdin )) > 0 ) - rmd160_write(rmdhd, buf, n); - #else - for(i=0; i < 1000000; i++ ) - rmd160_putchar(rmdhd, 'a'); - #endif - p = rmd160_final(rmdhd); - for(i=0; i < 20; i++, p++ ) - printf("%02x", *p ); - putchar('\n'); - - rmd160_close(rmdhd); - return 0; -} - diff --git a/cipher/rndegd.c b/cipher/rndegd.c deleted file mode 100644 index 5f71ab858..000000000 --- a/cipher/rndegd.c +++ /dev/null @@ -1,229 +0,0 @@ -/* rndegd.c - interface to the EGD - * Copyright (C) 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 - -#ifdef USE_RNDEGD - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "types.h" -#include "util.h" -#include "ttyio.h" -#include "algorithms.h" -#include "cipher.h" -#include "i18n.h" - - -#ifndef offsetof -#define offsetof(type, member) ((size_t) &((type *)0)->member) -#endif - -static int egd_socket = -1; - -static int -do_write( int fd, 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 ) - continue; - return -1; - } - nleft -= nwritten; - buf = (char*)buf + nwritten; - } - return 0; -} - -static int -do_read( int fd, void *buf, size_t nbytes ) -{ - int n, nread = 0; - - while (nbytes) - { - do { - n = read(fd, (char*)buf + nread, nbytes ); - } while( n == -1 && errno == EINTR ); - if( n == -1 ) - return nread? nread:-1; - else if( n == 0 ) { - /* EGD probably died. */ - errno = ECONNRESET; - return -1; - } - nread += n; - nbytes -= n; - } - return nread; -} - -/* Connect to the EGD and return the file descriptor. Return -1 on - error. With NOFAIL set to true, silently fail and return the - error, otherwise print an error message and die. */ -int -rndegd_connect_socket (int nofail) -{ - int fd; - const char *bname = NULL; - char *name; - struct sockaddr_un addr; - int addr_len; - - if (egd_socket != -1) - { - close (egd_socket); - egd_socket = -1; - } - -#ifdef EGD_SOCKET_NAME - bname = EGD_SOCKET_NAME; -#endif - if ( !bname || !*bname ) - bname = "=entropy"; - - if ( *bname == '=' && bname[1] ) - name = make_filename( g10_opt_homedir, bname+1 , NULL ); - else - name = make_filename( bname , NULL ); - - if ( strlen(name)+1 >= sizeof addr.sun_path ) - g10_log_fatal ("EGD socketname is too long\n"); - - memset( &addr, 0, sizeof addr ); - addr.sun_family = AF_UNIX; - strcpy( addr.sun_path, name ); - addr_len = (offsetof( struct sockaddr_un, sun_path ) - + strlen( addr.sun_path )); - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1 && !nofail) - g10_log_fatal("can't create unix domain socket: %s\n", - strerror(errno) ); - else if (connect (fd, (struct sockaddr*)&addr, addr_len) == -1) - { - if (!nofail) - g10_log_fatal("can't connect to `%s': %s\n", - name, strerror(errno) ); - close (fd); - fd = -1; - } - m_free(name); - if (fd != -1) - egd_socket = fd; - return fd; -} - - -/**************** - * Note: we always use the highest level. - * TO boost the performance we may want to add some - * additional code for level 1 - * - * Using a level of 0 should never block and better add nothing - * to the pool. So this is just a dummy for EGD. - */ -int -rndegd_gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - int fd = egd_socket; - int n; - byte buffer[256+2]; - int nbytes; - int do_restart = 0; - - if( !length ) - return 0; - if( !level ) - return 0; - - restart: - if (fd == -1 || do_restart) - fd = rndegd_connect_socket (0); - - do_restart = 0; - - nbytes = length < 255? length : 255; - /* first time we do it with a non blocking request */ - buffer[0] = 1; /* non blocking */ - buffer[1] = nbytes; - if( do_write( fd, buffer, 2 ) == -1 ) - g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) ); - n = do_read( fd, buffer, 1 ); - if( n == -1 ) { - g10_log_error("read error on EGD: %s\n", strerror(errno)); - do_restart = 1; - goto restart; - } - n = buffer[0]; - if( n ) { - n = do_read( fd, buffer, n ); - if( n == -1 ) { - g10_log_error("read error on EGD: %s\n", strerror(errno)); - do_restart = 1; - goto restart; - } - (*add)( buffer, n, requester ); - length -= n; - } - - if( length ) { - tty_printf( - _("Please wait, entropy is being gathered. Do some work if it would\n" - "keep you from getting bored, because it will improve the quality\n" - "of the entropy.\n") ); - } - while( length ) { - nbytes = length < 255? length : 255; - - buffer[0] = 2; /* blocking */ - buffer[1] = nbytes; - if( do_write( fd, buffer, 2 ) == -1 ) - g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) ); - n = do_read( fd, buffer, nbytes ); - if( n == -1 ) { - g10_log_error("read error on EGD: %s\n", strerror(errno)); - do_restart = 1; - goto restart; - } - (*add)( buffer, n, requester ); - length -= n; - } - memset(buffer, 0, sizeof(buffer) ); - - return 0; /* success */ -} - -#endif /*USE_RNDEGD*/ diff --git a/cipher/rndlinux.c b/cipher/rndlinux.c deleted file mode 100644 index c31b7f71c..000000000 --- a/cipher/rndlinux.c +++ /dev/null @@ -1,164 +0,0 @@ -/* rndlinux.c - raw random number for OSes with /dev/random - * 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 - -#ifdef USE_RNDLINUX - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_GETTIMEOFDAY - #include -#endif -#include -#include -#include -#if 0 - #include - #include - #include -#endif -#include "types.h" -#include "util.h" -#include "ttyio.h" -#include "algorithms.h" - -#include "i18n.h" - -static int open_device( const char *name, int minor ); - - -#if 0 -#ifdef HAVE_DEV_RANDOM_IOCTL -static ulong -get_entropy_count( int fd ) -{ - ulong count; - - if( ioctl( fd, RNDGETENTCNT, &count ) == -1 ) - g10_log_fatal("ioctl(RNDGETENTCNT) failed: %s\n", strerror(errno) ); - return count; -} -#endif -#endif - -/**************** - * Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists), ...) - */ -static int -open_device( const char *name, int minor ) -{ - int fd; - struct stat sb; - - fd = open( name, O_RDONLY ); - if( fd == -1 ) - g10_log_fatal("can't open %s: %s\n", name, strerror(errno) ); - if( fstat( fd, &sb ) ) - g10_log_fatal("stat() off %s failed: %s\n", name, strerror(errno) ); - /* Don't check device type for better portability */ - /* if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) ) - g10_log_fatal("invalid random device!\n" ); */ - return fd; -} - - -/**************** - * Note: Using a level of 0 should never block and better add nothing - * to the pool. This is easy to accomplish with /dev/urandom. - */ -int -rndlinux_gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - static int fd_urandom = -1; - static int fd_random = -1; - int fd; - int n; - int warn=0; - byte buffer[768]; - - if( level >= 2 ) { - if( fd_random == -1 ) - fd_random = open_device( NAME_OF_DEV_RANDOM, 8 ); - fd = fd_random; - } - else { - /* this will also be used for elve 0 but by using /dev/urandom - * we can be sure that oit will never block. */ - if( fd_urandom == -1 ) - fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 ); - fd = fd_urandom; - } - - #if 0 - #ifdef HAVE_DEV_RANDOM_IOCTL - g10_log_info("entropy count of %d is %lu\n", fd, get_entropy_count(fd) ); - #endif - #endif - while( length ) { - fd_set rfds; - struct timeval tv; - int rc; - - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - tv.tv_sec = 3; - tv.tv_usec = 0; - if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) { - if( !warn ) - tty_printf( -_("\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n"), (int)length ); - warn = 1; - continue; - } - else if( rc == -1 ) { - tty_printf( - "select() error: %s\n", strerror(errno)); - continue; - } - - do { - int nbytes = length < sizeof(buffer)? length : sizeof(buffer); - n = read(fd, buffer, nbytes ); - if( n >= 0 && n > nbytes ) { - g10_log_error("bogus read from random device (n=%d)\n", n ); - n = nbytes; - } - } while( n == -1 && errno == EINTR ); - if( n == -1 ) - g10_log_fatal("read error on random device: %s\n", strerror(errno)); - (*add)( buffer, n, requester ); - length -= n; - } - memset(buffer, 0, sizeof(buffer) ); - - return 0; /* success */ -} - -#endif /*USE_RNDLINUX*/ diff --git a/cipher/rndriscos.c b/cipher/rndriscos.c deleted file mode 100644 index 98142b313..000000000 --- a/cipher/rndriscos.c +++ /dev/null @@ -1,95 +0,0 @@ -/* rndriscos.c - raw random number for RISC OS - * 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 - */ - -#include - -#ifdef USE_RNDRISCOS - -#include -#include -#include -#include "util.h" - -static int init_device(void); - -#define CryptRandom_Byte 0x51980 - -static const char * const path[] = { - "GnuPG:CryptRandom", - "GnuPG:CryptRand", - "System:Modules.CryptRandom" - "System:Modules.CryptRand", - NULL -}; - -/**************** - * Used to load the CryptRandom module if it isn't already loaded - */ -static int -init_device(void) -{ - int i; - - /* Is CryptRandom already loaded? */ - if (!_swix(OS_Module, _INR(0,1), 18, "CryptRandom")) - return 1; - - /* Check all the places where the module could be located */ - for (i=0; path[i]; ++i) - if (!_swix(OS_Module, _INR(0,1), 1, path[i])) - return 1; - - /* Can't find CryptRandom in the default locations */ - g10_log_fatal("Can't load module CryptRandom.\n"); - - return 0; /* never reached, but don't throw a warning */ -} - - -/**************** - * Get the random bytes from module - */ -int -rndriscos_gather_random(void (*add)(const void*, size_t, int), int requester, - size_t length, int level) -{ - static int initialized = 0; - int n; - byte buffer[768]; - - if (!initialized) - initialized = init_device(); - - while (length) { - int nbytes = length < sizeof(buffer) ? length : sizeof(buffer); - - for (n = 0; n < nbytes; ++n) - if (_swix(CryptRandom_Byte, _OUT(0), &buffer[n])) - g10_log_fatal("CryptRandom module isn't working as expected!\n"); - - (*add)(buffer, n, requester); - length -= n; - } - memset(buffer, 0, sizeof(buffer)); - - return 0; /* success */ -} - -#endif /*USE_RNDRISCOS */ diff --git a/cipher/rndunix.c b/cipher/rndunix.c deleted file mode 100644 index 4c8aeaefa..000000000 --- a/cipher/rndunix.c +++ /dev/null @@ -1,869 +0,0 @@ -/**************************************************************************** - * * - * * - * Unix Randomness-Gathering Code * - * * - * Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. * - * Heavily modified for GnuPG by Werner Koch * - * * - * * - ****************************************************************************/ - -/* This module is part of the cryptlib continuously seeded pseudorandom - number generator. For usage conditions, see lib_rand.c - - [Here is the notice from lib_rand.c:] - - This module and the misc/rnd*.c modules represent the cryptlib - continuously seeded pseudorandom number generator (CSPRNG) as described in - my 1998 Usenix Security Symposium paper "The generation of random numbers - for cryptographic purposes". - - The CSPRNG code is copyright Peter Gutmann (and various others) 1996, - 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG - modules and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice - and this permission notice in its entirety. - - 2. Redistributions in binary form must reproduce the copyright notice in - the documentation and/or other materials provided with the distribution. - - 3. A copy of any bugfixes or enhancements made must be provided to the - author, to allow them to be added to the - baseline version of the code. - - ALTERNATIVELY, the code may be distributed under the terms of the GNU - General Public License, version 2 or any later version published by the - Free Software Foundation, in which case the provisions of the GNU GPL are - required INSTEAD OF the above restrictions. - - Although not required under the terms of the GPL, it would still be nice if - you could make any changes available to the author to allow a consistent - code base to be maintained */ - - - -/* General includes */ - -#include - -#ifdef USE_RNDUNIX - -#include -#include -#include -#include - -/* OS-specific includes */ - -#ifdef __osf__ - /* Somewhere in the morass of system-specific cruft which OSF/1 pulls in - * via the following includes are various endianness defines, so we - * undefine the cryptlib ones, which aren't really needed for this module - * anyway */ -#undef BIG_ENDIAN -#undef LITTLE_ENDIAN -#endif /* __osf__ */ - -#include -#include -#include -#ifndef __QNX__ -#include -#include -#endif /* __QNX__ */ -#include /* SCO and SunOS need this before resource.h */ -#ifndef __QNX__ -#include -#endif /* __QNX__ */ -#if defined( _AIX ) || defined( __QNX__ ) -#include -#endif /* _AIX || __QNX__ */ -#ifndef __QNX__ -#include -#include -#include -#endif /* __QNX__ */ -#include -#include /* Verschiedene komische Typen */ -#if defined( __hpux ) && ( OS_VERSION == 9 ) -#include -#endif /* __hpux 9.x, after that it's in unistd.h */ -#include -/* #include */ -#ifdef __QNX__ -#include -#include -#endif /* __QNX__ */ -#include - -#include "types.h" /* for byte and u32 typedefs */ -#ifndef IS_MODULE -#include "algorithms.h" -#endif -#include "util.h" - -#ifndef EAGAIN -#define EAGAIN EWOULDBLOCK -#endif -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */ - -/* The structure containing information on random-data sources. Each - * record contains the source and a relative estimate of its usefulness - * (weighting) which is used to scale the number of kB of output from the - * source (total = data_bytes / usefulness). Usually the weighting is in the - * range 1-3 (or 0 for especially useless sources), resulting in a usefulness - * rating of 1...3 for each kB of source output (or 0 for the useless - * sources). - * - * If the source is constantly changing (certain types of network statistics - * have this characteristic) but the amount of output is small, the weighting - * is given as a negative value to indicate that the output should be treated - * as if a minimum of 1K of output had been obtained. If the source produces - * a lot of output then the scale factor is fractional, resulting in a - * usefulness rating of < 1 for each kB of source output. - * - * In order to provide enough randomness to satisfy the requirements for a - * slow poll, we need to accumulate at least 20 points of usefulness (a - * typical system should get about 30 points). - * - * Some potential options are missed out because of special considerations. - * pstat -i and pstat -f can produce amazing amounts of output (the record - * is 600K on an Oracle server) which floods the buffer and doesn't yield - * anything useful (apart from perhaps increasing the entropy of the vmstat - * output a bit), so we don't bother with this. pstat in general produces - * quite a bit of output, but it doesn't change much over time, so it gets - * very low weightings. netstat -s produces constantly-changing output but - * also produces quite a bit of it, so it only gets a weighting of 2 rather - * than 3. The same holds for netstat -in, which gets 1 rather than 2. - * - * Some binaries are stored in different locations on different systems so - * alternative paths are given for them. The code sorts out which one to - * run by itself, once it finds an exectable somewhere it moves on to the - * next source. The sources are arranged roughly in their order of - * usefulness, occasionally sources which provide a tiny amount of - * relatively useless data are placed ahead of ones which provide a large - * amount of possibly useful data because another 100 bytes can't hurt, and - * it means the buffer won't be swamped by one or two high-output sources. - * All the high-output sources are clustered towards the end of the list - * for this reason. Some binaries are checked for in a certain order, for - * example under Slowaris /usr/ucb/ps understands aux as an arg, but the - * others don't. Some systems have conditional defines enabling alternatives - * to commands which don't understand the usual options but will provide - * enough output (in the form of error messages) to look like they're the - * real thing, causing alternative options to be skipped (we can't check the - * return either because some commands return peculiar, non-zero status even - * when they're working correctly). - * - * In order to maximise use of the buffer, the code performs a form of run- - * length compression on its input where a repeated sequence of bytes is - * replaced by the occurrence count mod 256. Some commands output an awful - * lot of whitespace, this measure greatly increases the amount of data we - * can fit in the buffer. - * - * When we scale the weighting using the SC() macro, some preprocessors may - * give a division by zero warning for the most obvious expression - * 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero - * trap), so we define a value SC_0 which evaluates to zero when fed to - * '1024 / SC_0' */ - -#define SC( weight ) ( 1024 / weight ) /* Scale factor */ -#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */ - -static struct RI { - const char *path; /* Path to check for existence of source */ - const char *arg; /* Args for source */ - const int usefulness; /* Usefulness of source */ - FILE *pipe; /* Pipe to source as FILE * */ - int pipeFD; /* Pipe to source as FD */ - pid_t pid; /* pid of child for waitpid() */ - int length; /* Quantity of output produced */ - const int hasAlternative; /* Whether source has alt.location */ -} dataSources[] = { - - { "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0}, - { "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0}, - { "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0}, - { "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0}, - { "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1}, - { "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0}, - { "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0}, - { "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 }, - { "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1}, - { "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0}, - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0", - SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */ - { "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 }, - { "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 }, - { "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, - { "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 }, - { "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 }, - { "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 }, -#if defined( __sgi ) || defined( __hpux ) - { "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 }, -#endif /* __sgi || __hpux */ - { "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, - { "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 }, - { "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 }, - { "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/ - { "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 }, - /* Unreliable source, depends on system usage */ - { "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 }, - { "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, - /* pstat is your friend */ - { "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 }, -#ifdef __sgi - { "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, -#endif /* __sgi */ -#ifdef __hpux - { "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 }, -#endif /* __hpux */ - { "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 }, - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0", - SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ - { "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0", - SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */ - { "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 }, - { "/usr/sbin/ripquery", "-nw 1 127.0.0.1", - SC(0.1), NULL, 0, 0, 0, 0 }, - { "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 }, - { "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 }, - { "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 }, - /* This is very environment-dependant. If network traffic is low, it'll - * probably time out before delivering 5 packets, which is OK because - * it'll probably be fixed stuff like ARP anyway */ - { "/usr/sbin/advfsstat", "-b usr_domain", - SC(SC_0), NULL, 0, 0, 0, 0}, - { "/usr/sbin/advfsstat", "-l 2 usr_domain", - SC(0.5), NULL, 0, 0, 0, 0}, - { "/usr/sbin/advfsstat", "-p usr_domain", - SC(SC_0), NULL, 0, 0, 0, 0}, - /* This is a complex and screwball program. Some systems have things - * like rX_dmn, x = integer, for RAID systems, but the statistics are - * pretty dodgy */ -#ifdef __QNXNTO__ - { "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3), - NULL, 0, 0, 0, 0 }, -#endif -#if 0 - /* The following aren't enabled since they're somewhat slow and not very - * unpredictable, however they give an indication of the sort of sources - * you can use (for example the finger might be more useful on a - * firewalled internal network) */ - { "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 }, - { "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html", - SC(0.9), NULL, 0, 0, 0, 0 }, - { "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 }, -#endif /* 0 */ - { NULL, NULL, 0, NULL, 0, 0, 0, 0 } -}; - -static byte *gather_buffer; /* buffer for gathering random noise */ -static int gather_buffer_size; /* size of the memory buffer */ -static uid_t gatherer_uid; - -/* The message structure used to communicate with the parent */ -typedef struct { - int usefulness; /* usefulness of data */ - int ndata; /* valid bytes in data */ - char data[500]; /* gathered data */ -} GATHER_MSG; - - -#ifndef HAVE_WAITPID -pid_t -waitpid(pid_t pid, int *statptr, int options) -{ - #ifdef HAVE_WAIT4 - return wait4(pid, statptr, options, NULL); - #else - /* If wait4 is also not available, try wait3 for SVR3 variants */ - /* Less ideal because can't actually request a specific pid */ - /* For that reason, first check to see if pid is for an */ - /* existing process. */ - int tmp_pid, dummystat;; - if (kill(pid, 0) == -1) { - errno = ECHILD; - return -1; - } - if (statptr == NULL) - statptr = &dummystat; - while (((tmp_pid = wait3(statptr, options, 0)) != pid) && - (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) - ; - return tmp_pid; - #endif -} -#endif - - -/* Under SunOS popen() doesn't record the pid of the child process. When - * pclose() is called, instead of calling waitpid() for the correct child, it - * calls wait() repeatedly until the right child is reaped. The problem is - * that this reaps any other children that happen to have died at that - * moment, and when their pclose() comes along, the process hangs forever. - * The fix is to use a wrapper for popen()/pclose() which saves the pid in - * the dataSources structure (code adapted from GNU-libc's popen() call). - * - * Aut viam inveniam aut faciam */ - -static FILE * -my_popen(struct RI *entry) -{ - - int pipedes[2]; - FILE *stream; - - /* Create the pipe */ - if (pipe(pipedes) < 0) - return (NULL); - - /* Fork off the child ("vfork() is like an OS orgasm. All OS's want to - * do it, but most just end up faking it" - Chris Wedgwood). If your OS - * supports it, you should try to use vfork() here because it's somewhat - * more efficient */ -#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \ - defined(__hpux) - entry->pid = vfork(); -#else /* */ - entry->pid = fork(); -#endif /* Unixen which have vfork() */ - if (entry->pid == (pid_t) - 1) { - /* The fork failed */ - close(pipedes[0]); - close(pipedes[1]); - return (NULL); - } - - if (entry->pid == (pid_t) 0) { - struct passwd *passwd; - int fd; - - /* We are the child. Make the read side of the pipe be stdout */ - if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0) - exit(127); - /* Connect the other standard handles to the bit bucket. */ - if ((fd = open ("/dev/null", O_RDWR)) != -1) { - dup2 (fd, STDIN_FILENO); - dup2 (fd, STDERR_FILENO); - close (fd); - } - - /* Now that everything is set up, give up our permissions to make - * sure we don't read anything sensitive. If the getpwnam() fails, - * we default to -1, which is usually nobody */ - if (gatherer_uid == (uid_t)-1 && \ - (passwd = getpwnam("nobody")) != NULL) - gatherer_uid = passwd->pw_uid; - - setuid(gatherer_uid); - - /* Close the pipe descriptors. */ - close(pipedes[STDIN_FILENO]); - close(pipedes[STDOUT_FILENO]); - - /* Try and exec the program */ - execl(entry->path, entry->path, entry->arg, NULL); - - /* Die if the exec failed */ - exit(127); - } - - /* We are the parent. Close the irrelevant side of the pipe and open - * the relevant side as a new stream. Mark our side of the pipe to - * close on exec, so new children won't see it */ - close(pipedes[STDOUT_FILENO]); - -#ifdef FD_CLOEXEC - fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC); -#endif - - stream = fdopen(pipedes[STDIN_FILENO], "r"); - - if (stream == NULL) { - int savedErrno = errno; - - /* The stream couldn't be opened or the child structure couldn't be - * allocated. Kill the child and close the other side of the pipe */ - kill(entry->pid, SIGKILL); - if (stream == NULL) - close(pipedes[STDOUT_FILENO]); - else - fclose(stream); - - waitpid(entry->pid, NULL, 0); - - entry->pid = 0; - errno = savedErrno; - return (NULL); - } - - return (stream); -} - -static int -my_pclose(struct RI *entry) -{ - int status = 0; - - if (fclose(entry->pipe)) - return (-1); - - /* We ignore the return value from the process because some programs - * return funny values which would result in the input being discarded - * even if they executed successfully. This isn't a problem because the - * result data size threshold will filter out any programs which exit - * with a usage message without producing useful output */ - if (waitpid(entry->pid, NULL, 0) != entry->pid) - status = -1; - - entry->pipe = NULL; - entry->pid = 0; - return (status); -} - - -/* Unix slow poll (without special support for Linux) - * - * If a few of the randomness sources create a large amount of output then - * the slowPoll() stops once the buffer has been filled (but before all the - * randomness sources have been sucked dry) so that the 'usefulness' factor - * remains below the threshold. For this reason the gatherer buffer has to - * be fairly sizeable on moderately loaded systems. This is something of a - * bug since the usefulness should be influenced by the amount of output as - * well as the source type */ - - -static int -slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes ) -{ - int moreSources; - struct timeval tv; - fd_set fds; - #if defined( __hpux ) - size_t maxFD = 0; - #else - int maxFD = 0; - #endif /* OS-specific brokenness */ - int bufPos, i, usefulness = 0; - - - /* Fire up each randomness source */ - FD_ZERO(&fds); - for (i = 0; dataSources[i].path != NULL; i++) { - /* Since popen() is a fairly heavy function, we check to see whether - * the executable exists before we try to run it */ - if (access(dataSources[i].path, X_OK)) { - if( dbgfp && dbgall ) - fprintf(dbgfp, "%s not present%s\n", dataSources[i].path, - dataSources[i].hasAlternative ? - ", has alternatives" : ""); - dataSources[i].pipe = NULL; - } - else - dataSources[i].pipe = my_popen(&dataSources[i]); - - if (dataSources[i].pipe != NULL) { - dataSources[i].pipeFD = fileno(dataSources[i].pipe); - if (dataSources[i].pipeFD > maxFD) - maxFD = dataSources[i].pipeFD; - #ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */ - fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK); - #endif - FD_SET(dataSources[i].pipeFD, &fds); - dataSources[i].length = 0; - - /* If there are alternatives for this command, don't try and - * execute them */ - while (dataSources[i].hasAlternative) { - if( dbgfp && dbgall ) - fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path); - i++; - } - } - } - - - /* Suck all the data we can get from each of the sources */ - bufPos = 0; - moreSources = 1; - while (moreSources && bufPos <= gather_buffer_size) { - /* Wait for data to become available from any of the sources, with a - * timeout of 10 seconds. This adds even more randomness since data - * becomes available in a nondeterministic fashion. Kudos to HP's QA - * department for managing to ship a select() which breaks its own - * prototype */ - tv.tv_sec = 10; - tv.tv_usec = 0; - - #if defined( __hpux ) && ( OS_VERSION == 9 ) - if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1) - #else /* */ - if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1) - #endif /* __hpux */ - break; - - /* One of the sources has data available, read it into the buffer */ - for (i = 0; dataSources[i].path != NULL; i++) { - if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) { - size_t noBytes; - - if ((noBytes = fread(gather_buffer + bufPos, 1, - gather_buffer_size - bufPos, - dataSources[i].pipe)) == 0) { - if (my_pclose(&dataSources[i]) == 0) { - int total = 0; - - /* Try and estimate how much entropy we're getting - * from a data source */ - if (dataSources[i].usefulness) { - if (dataSources[i].usefulness < 0) - total = (dataSources[i].length + 999) - / -dataSources[i].usefulness; - else - total = dataSources[i].length - / dataSources[i].usefulness; - } - if( dbgfp ) - fprintf(dbgfp, - "%s %s contributed %d bytes, " - "usefulness = %d\n", dataSources[i].path, - (dataSources[i].arg != NULL) ? - dataSources[i].arg : "", - dataSources[i].length, total); - if( dataSources[i].length ) - usefulness += total; - } - dataSources[i].pipe = NULL; - } - else { - int currPos = bufPos; - int endPos = bufPos + noBytes; - - /* Run-length compress the input byte sequence */ - while (currPos < endPos) { - int ch = gather_buffer[currPos]; - - /* If it's a single byte, just copy it over */ - if (ch != gather_buffer[currPos + 1]) { - gather_buffer[bufPos++] = ch; - currPos++; - } - else { - int count = 0; - - /* It's a run of repeated bytes, replace them - * with the byte count mod 256 */ - while ((ch == gather_buffer[currPos]) - && currPos < endPos) { - count++; - currPos++; - } - gather_buffer[bufPos++] = count; - noBytes -= count - 1; - } - } - - /* Remember the number of (compressed) bytes of input we - * obtained */ - dataSources[i].length += noBytes; - } - } - } - - /* Check if there is more input available on any of the sources */ - moreSources = 0; - FD_ZERO(&fds); - for (i = 0; dataSources[i].path != NULL; i++) { - if (dataSources[i].pipe != NULL) { - FD_SET(dataSources[i].pipeFD, &fds); - moreSources = 1; - } - } - } - - if( dbgfp ) { - fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness); - fflush(dbgfp); - } - *nbytes = bufPos; - return usefulness; -} - -/**************** - * Start the gatherer process which writes messages of - * type GATHERER_MSG to pipedes - */ -static void -start_gatherer( int pipefd ) -{ - FILE *dbgfp = NULL; - int dbgall; - - { - const char *s = getenv("GNUPG_RNDUNIX_DBG"); - if( s ) { - dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a"); - if( !dbgfp ) - g10_log_info("can't open debug file `%s': %s\n", - s, strerror(errno) ); - else - fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid()); - } - dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL"); - } - - - /* Set up the buffer */ - gather_buffer_size = GATHER_BUFSIZE; - gather_buffer = malloc( gather_buffer_size ); - if( !gather_buffer ) { - g10_log_error("out of core while allocating the gatherer buffer\n"); - exit(2); - } - - /* Reset the SIGC(H)LD handler to the system default. This is necessary - * because if the program which cryptlib is a part of installs its own - * SIGC(H)LD handler, it will end up reaping the cryptlib children before - * cryptlib can. As a result, my_pclose() will call waitpid() on a - * process which has already been reaped by the installed handler and - * return an error, so the read data won't be added to the randomness - * pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and - * the BSD/Posix SIGCHLD, so we need to handle either possibility */ - #ifdef SIGCLD - signal(SIGCLD, SIG_DFL); - #else - signal(SIGCHLD, SIG_DFL); - #endif - - fflush (stderr); - /* Arrghh!! It's Stuart code!! */ - /* (close all files but the ones we need) */ - { int nmax, n1, i; - #ifdef _SC_OPEN_MAX - if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) { - #ifdef _POSIX_OPEN_MAX - nmax = _POSIX_OPEN_MAX; - #else - nmax = 20; /* assume a reasonable value */ - #endif - } - #else - nmax = 20; /* assume a reasonable value */ - #endif - { - int fd; - if ((fd = open ("/dev/null", O_RDWR)) != -1) { - dup2 (fd, STDIN_FILENO); - dup2 (fd, STDOUT_FILENO); - dup2 (fd, STDERR_FILENO); - close (fd); - } - } - n1 = dbgfp? fileno (dbgfp) : -1; - for(i=0; i < nmax; i++ ) { - if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO - && i != n1 && i != pipefd ) - close(i); - } - errno = 0; - } - - - for(;;) { - GATHER_MSG msg; - size_t nbytes; - const char *p; - - msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes ); - p = gather_buffer; - while( nbytes ) { - msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes; - memcpy( msg.data, p, msg.ndata ); - nbytes -= msg.ndata; - p += msg.ndata; - - while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) { - if( errno == EINTR ) - continue; - if( errno == EAGAIN ) { - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 50000; - select(0, NULL, NULL, NULL, &tv); - continue; - } - if( errno == EPIPE ) /* parent has exited, so give up */ - exit(0); - - /* we can't do very much here because stderr is closed */ - if( dbgfp ) - fprintf(dbgfp, "gatherer can't write to pipe: %s\n", - strerror(errno) ); - /* we start a new poll to give the system some time */ - nbytes = 0; - break; - } - } - } - /* we are killed when the parent dies */ -} - - -static int -read_a_msg( int fd, GATHER_MSG *msg ) -{ - char *buffer = (char*)msg; - size_t length = sizeof( *msg ); - int n; - - do { - do { - n = read(fd, buffer, length ); - } while( n == -1 && errno == EINTR ); - if( n == -1 ) - return -1; - buffer += n; - length -= n; - } while( length ); - return 0; -} - - -/**************** - * Using a level of 0 should never block and better add nothing - * to the pool. So this is just a dummy for this gatherer. - */ -int -rndunix_gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - static pid_t gatherer_pid = 0; - static int pipedes[2]; - GATHER_MSG msg; - size_t n; - - if( !level ) - return 0; - - if( !gatherer_pid ) { - /* make sure we are not setuid */ - if( getuid() != geteuid() ) - BUG(); - /* time to start the gatherer process */ - if( pipe( pipedes ) ) { - g10_log_error("pipe() failed: %s\n", strerror(errno)); - return -1; - } - gatherer_pid = fork(); - if( gatherer_pid == -1 ) { - g10_log_error("can't for gatherer process: %s\n", strerror(errno)); - return -1; - } - if( !gatherer_pid ) { - start_gatherer( pipedes[1] ); - /* oops, can't happen */ - return -1; - } - } - - /* now read from the gatherer */ - while( length ) { - int goodness; - ulong subtract; - - if( read_a_msg( pipedes[0], &msg ) ) { - g10_log_error("reading from gatherer pipe failed: %s\n", - strerror(errno)); - return -1; - } - - - if( level > 1 ) { - if( msg.usefulness > 30 ) - goodness = 100; - else if ( msg.usefulness ) - goodness = msg.usefulness * 100 / 30; - else - goodness = 0; - } - else if( level ) { - if( msg.usefulness > 15 ) - goodness = 100; - else if ( msg.usefulness ) - goodness = msg.usefulness * 100 / 15; - else - goodness = 0; - } - else - goodness = 100; /* goodness of level 0 is always 100 % */ - - n = msg.ndata; - if( n > length ) - n = length; - (*add)( msg.data, n, requester ); - - /* this is the trick how e cope with the goodness */ - subtract = (ulong)n * goodness / 100; - /* subtract at least 1 byte to avoid infinite loops */ - length -= subtract ? subtract : 1; - } - - return 0; -} - -#endif /*USE_RNDUNIX*/ diff --git a/cipher/rndw32.c b/cipher/rndw32.c deleted file mode 100644 index c5f855ca6..000000000 --- a/cipher/rndw32.c +++ /dev/null @@ -1,706 +0,0 @@ -/* rndw32.c - W32 entropy gatherer - * Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - * Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999 - * - * 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 - * - ************************************************************************* - * The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann. - * Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this - * copyright notice: - * - * This module is part of the cryptlib continuously seeded pseudorandom - * number generator. For usage conditions, see lib_rand.c - * - * [Here is the notice from lib_rand.c, which is now called dev_sys.c] - * - * This module and the misc/rnd*.c modules represent the cryptlib - * continuously seeded pseudorandom number generator (CSPRNG) as described in - * my 1998 Usenix Security Symposium paper "The generation of random numbers - * for cryptographic purposes". - * - * The CSPRNG code is copyright Peter Gutmann (and various others) 1996, - * 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG - * modules and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice - * and this permission notice in its entirety. - * - * 2. Redistributions in binary form must reproduce the copyright notice in - * the documentation and/or other materials provided with the distribution. - * - * 3. A copy of any bugfixes or enhancements made must be provided to the - * author, to allow them to be added to the - * baseline version of the code. - * - * ALTERNATIVELY, the code may be distributed under the terms of the GNU - * General Public License, version 2 or any later version published by the - * Free Software Foundation, in which case the provisions of the GNU GPL are - * required INSTEAD OF the above restrictions. - * - * Although not required under the terms of the GPL, it would still be nice if - * you could make any changes available to the author to allow a consistent - * code base to be maintained - ************************************************************************* - */ - -#include - -#ifdef USE_RNDW32 - -#include -#include -#include -#include -#include - -#include -#ifdef __CYGWIN32__ -# include -#endif - - -#include "types.h" -#include "util.h" -#include "algorithms.h" - -#include "i18n.h" - - -static int debug_me; - -/* - * Definitions which are missing from the current GNU Windows32Api - */ - -#ifndef TH32CS_SNAPHEAPLIST -#define TH32CS_SNAPHEAPLIST 1 -#define TH32CS_SNAPPROCESS 2 -#define TH32CS_SNAPTHREAD 4 -#define TH32CS_SNAPMODULE 8 -#define TH32CS_SNAPALL (1|2|4|8) -#define TH32CS_INHERIT 0x80000000 -#endif /*TH32CS_SNAPHEAPLIST*/ - -#ifndef IOCTL_DISK_PERFORMANCE -#define IOCTL_DISK_PERFORMANCE 0x00070020 -#endif -#ifndef VER_PLATFORM_WIN32_WINDOWS -#define VER_PLATFORM_WIN32_WINDOWS 1 -#endif - -/* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger - value in a newer release. So we use a far larger value. */ -#define SIZEOF_DISK_PERFORMANCE_STRUCT 256 - - -typedef struct { - DWORD dwSize; - DWORD th32ProcessID; - DWORD th32HeapID; - DWORD dwFlags; -} HEAPLIST32; - -typedef struct { - DWORD dwSize; - HANDLE hHandle; - DWORD dwAddress; - DWORD dwBlockSize; - DWORD dwFlags; - DWORD dwLockCount; - DWORD dwResvd; - DWORD th32ProcessID; - DWORD th32HeapID; -} HEAPENTRY32; - -typedef struct { - DWORD dwSize; - DWORD cntUsage; - DWORD th32ProcessID; - DWORD th32DefaultHeapID; - DWORD th32ModuleID; - DWORD cntThreads; - DWORD th32ParentProcessID; - LONG pcPriClassBase; - DWORD dwFlags; - char szExeFile[260]; -} PROCESSENTRY32; - -typedef struct { - DWORD dwSize; - DWORD cntUsage; - DWORD th32ThreadID; - DWORD th32OwnerProcessID; - LONG tpBasePri; - LONG tpDeltaPri; - DWORD dwFlags; -} THREADENTRY32; - -typedef struct { - DWORD dwSize; - DWORD th32ModuleID; - DWORD th32ProcessID; - DWORD GlblcntUsage; - DWORD ProccntUsage; - BYTE *modBaseAddr; - DWORD modBaseSize; - HMODULE hModule; - char szModule[256]; - char szExePath[260]; -} MODULEENTRY32; - - - -/* Type definitions for function pointers to call Toolhelp32 functions - * used with the windows95 gatherer */ -typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, MODULEENTRY32 *lpme); -typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, THREADENTRY32 *lpte); -typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, PROCESSENTRY32 *lppe); -typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, HEAPLIST32 *lphl); -typedef BOOL (WINAPI * HEAPFIRST) (HEAPENTRY32 *lphe, DWORD th32ProcessID, - DWORD th32HeapID); -typedef BOOL (WINAPI * HEAPNEXT) (HEAPENTRY32 *lphe); -typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID); - -/* Type definitions for function pointers to call NetAPI32 functions */ -typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService, - DWORD dwLevel, DWORD dwOptions, - LPBYTE * lpBuffer); -typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer); -typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer); - - -/* When we query the performance counters, we allocate an initial buffer and - * then reallocate it as required until RegQueryValueEx() stops returning - * ERROR_MORE_DATA. The following values define the initial buffer size and - * step size by which the buffer is increased - */ -#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */ -#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */ - - -static void -slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester ) -{ - static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; - static MODULEWALK pModule32First = NULL; - static MODULEWALK pModule32Next = NULL; - static PROCESSWALK pProcess32First = NULL; - static PROCESSWALK pProcess32Next = NULL; - static THREADWALK pThread32First = NULL; - static THREADWALK pThread32Next = NULL; - static HEAPLISTWALK pHeap32ListFirst = NULL; - static HEAPLISTWALK pHeap32ListNext = NULL; - static HEAPFIRST pHeap32First = NULL; - static HEAPNEXT pHeap32Next = NULL; - HANDLE hSnapshot; - - - /* initialize the Toolhelp32 function pointers */ - if ( !pCreateToolhelp32Snapshot ) { - HANDLE hKernel; - - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_95: init toolkit\n" ); - - /* Obtain the module handle of the kernel to retrieve the addresses - * of the Toolhelp32 functions */ - if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) { - g10_log_fatal ( "rndw32: can't get module handle\n" ); - } - - /* Now get pointers to the functions */ - pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel, - "CreateToolhelp32Snapshot"); - pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First"); - pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next"); - pProcess32First = (PROCESSWALK) GetProcAddress (hKernel, - "Process32First"); - pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel, - "Process32Next"); - pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First"); - pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next"); - pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel, - "Heap32ListFirst"); - pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel, - "Heap32ListNext"); - pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First"); - pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next"); - - if ( !pCreateToolhelp32Snapshot - || !pModule32First || !pModule32Next - || !pProcess32First || !pProcess32Next - || !pThread32First || !pThread32Next - || !pHeap32ListFirst || !pHeap32ListNext - || !pHeap32First || !pHeap32Next ) { - g10_log_fatal ( "rndw32: failed to get a toolhep function\n" ); - } - } - - /* Take a snapshot of everything we can get to which is currently - * in the system */ - if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) { - g10_log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" ); - } - - /* Walk through the local heap */ - { HEAPLIST32 hl32; - hl32.dwSize = sizeof (HEAPLIST32); - if (pHeap32ListFirst (hSnapshot, &hl32)) { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_95: walk heap\n" ); - do { - HEAPENTRY32 he32; - - /* First add the information from the basic Heaplist32 struct */ - (*add) ( &hl32, sizeof (hl32), requester ); - - /* Now walk through the heap blocks getting information - * on each of them */ - he32.dwSize = sizeof (HEAPENTRY32); - if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){ - do { - (*add) ( &he32, sizeof (he32), requester ); - } while (pHeap32Next (&he32)); - } - } while (pHeap32ListNext (hSnapshot, &hl32)); - } - } - - - /* Walk through all processes */ - { PROCESSENTRY32 pe32; - pe32.dwSize = sizeof (PROCESSENTRY32); - if (pProcess32First (hSnapshot, &pe32)) { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_95: walk processes\n" ); - do { - (*add) ( &pe32, sizeof (pe32), requester ); - } while (pProcess32Next (hSnapshot, &pe32)); - } - } - - /* Walk through all threads */ - { THREADENTRY32 te32; - te32.dwSize = sizeof (THREADENTRY32); - if (pThread32First (hSnapshot, &te32)) { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_95: walk threads\n" ); - do { - (*add) ( &te32, sizeof (te32), requester ); - } while (pThread32Next (hSnapshot, &te32)); - } - } - - /* Walk through all modules associated with the process */ - { MODULEENTRY32 me32; - me32.dwSize = sizeof (MODULEENTRY32); - if (pModule32First (hSnapshot, &me32)) { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_95: walk modules\n" ); - do { - (*add) ( &me32, sizeof (me32), requester ); - } while (pModule32Next (hSnapshot, &me32)); - } - } - - CloseHandle (hSnapshot); -} - - - -static void -slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester ) -{ - static int is_initialized = 0; - static NETSTATISTICSGET pNetStatisticsGet = NULL; - static NETAPIBUFFERSIZE pNetApiBufferSize = NULL; - static NETAPIBUFFERFREE pNetApiBufferFree = NULL; - static int is_workstation = 1; - - static int cbPerfData = PERFORMANCE_BUFFER_SIZE; - PERF_DATA_BLOCK *pPerfData; - HANDLE hDevice, hNetAPI32 = NULL; - DWORD dwSize, status; - int nDrive; - - if ( !is_initialized ) { - HKEY hKey; - - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" ); - /* Find out whether this is an NT server or workstation if necessary */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", - 0, KEY_READ, &hKey) == ERROR_SUCCESS) { - BYTE szValue[32]; - dwSize = sizeof (szValue); - - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: check product options\n" ); - status = RegQueryValueEx (hKey, "ProductType", 0, NULL, - szValue, &dwSize); - if (status == ERROR_SUCCESS - && ascii_strcasecmp (szValue, "WinNT")) { - /* Note: There are (at least) three cases for ProductType: - * WinNT = NT Workstation, ServerNT = NT Server, LanmanNT = - * NT Server acting as a Domain Controller */ - is_workstation = 0; - if ( debug_me ) - log_debug ("rndw32: this is a NT server\n"); - } - RegCloseKey (hKey); - } - - /* Initialize the NetAPI32 function pointers if necessary */ - if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" ); - pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32, - "NetStatisticsGet"); - pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32, - "NetApiBufferSize"); - pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32, - "NetApiBufferFree"); - - if ( !pNetStatisticsGet - || !pNetApiBufferSize || !pNetApiBufferFree ) { - FreeLibrary (hNetAPI32); - hNetAPI32 = NULL; - g10_log_debug ("rndw32: No NETAPI found\n" ); - } - } - - is_initialized = 1; - } - - /* Get network statistics. Note: Both NT Workstation and NT Server by - * default will be running both the workstation and server services. The - * heuristic below is probably useful though on the assumption that the - * majority of the network traffic will be via the appropriate service. - * In any case the network statistics return almost no randomness */ - { LPBYTE lpBuffer; - if (hNetAPI32 && !pNetStatisticsGet (NULL, - is_workstation ? L"LanmanWorkstation" : - L"LanmanServer", 0, 0, &lpBuffer) ) { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: get netstats\n" ); - pNetApiBufferSize (lpBuffer, &dwSize); - (*add) ( lpBuffer, dwSize,requester ); - pNetApiBufferFree (lpBuffer); - } - } - - /* Get disk I/O statistics for all the hard drives */ - for (nDrive = 0;; nDrive++) { - char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT]; - char szDevice[50]; - - /* Check whether we can access this device */ - sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive); - hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) - break; - - /* Note: This only works if you have turned on the disk performance - * counters with 'diskperf -y'. These counters are off by default */ - if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, - diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT, - &dwSize, NULL)) - { - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n", - nDrive ); - (*add) (diskPerformance, dwSize, requester ); - } - else { - log_info ("NOTE: you should run 'diskperf -y' " - "to enable the disk statistics\n"); - } - CloseHandle (hDevice); - } - - #if 0 /* we don't need this in GnuPG */ - /* Wait for any async keyset driver binding to complete. You may be - * wondering what this call is doing here... the reason it's necessary is - * because RegQueryValueEx() will hang indefinitely if the async driver - * bind is in progress. The problem occurs in the dynamic loading and - * linking of driver DLL's, which work as follows: - * - * hDriver = LoadLibrary( DRIVERNAME ); - * pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 ); - * pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 ); - * - * If RegQueryValueEx() is called while the GetProcAddress()'s are in - * progress, it will hang indefinitely. This is probably due to some - * synchronisation problem in the NT kernel where the GetProcAddress() - * calls affect something like a module reference count or function - * reference count while RegQueryValueEx() is trying to take a snapshot - * of the statistics, which include the reference counts. Because of - * this, we have to wait until any async driver bind has completed - * before we can call RegQueryValueEx() */ - waitSemaphore (SEMAPHORE_DRIVERBIND); - #endif - - /* Get information from the system performance counters. This can take - * a few seconds to do. In some environments the call to - * RegQueryValueEx() can produce an access violation at some random time - * in the future, adding a short delay after the following code block - * makes the problem go away. This problem is extremely difficult to - * reproduce, I haven't been able to get it to occur despite running it - * on a number of machines. The best explanation for the problem is that - * on the machine where it did occur, it was caused by an external driver - * or other program which adds its own values under the - * HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external - * modules to map in the data, if there's a synchronisation problem the - * external module would write its data at an inappropriate moment, - * causing the access violation. A low-level memory checker indicated - * that ExpandEnvironmentStrings() in KERNEL32.DLL, called an - * interminable number of calls down inside RegQueryValueEx(), was - * overwriting memory (it wrote twice the allocated size of a buffer to a - * buffer allocated by the NT kernel). This may be what's causing the - * problem, but since it's in the kernel there isn't much which can be - * done. - * - * In addition to these problems the code in RegQueryValueEx() which - * estimates the amount of memory required to return the performance - * counter information isn't very accurate, since it always returns a - * worst-case estimate which is usually nowhere near the actual amount - * required. For example it may report that 128K of memory is required, - * but only return 64K of data */ - { pPerfData = m_alloc (cbPerfData); - for (;;) { - dwSize = cbPerfData; - if ( debug_me ) - log_debug ("rndw32#slow_gatherer_nt: get perf data\n" ); - status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL, - NULL, (LPBYTE) pPerfData, &dwSize); - if (status == ERROR_SUCCESS) { - if (!memcmp (pPerfData->Signature, L"PERF", 8)) { - (*add) ( pPerfData, dwSize, requester ); - } - else - g10_log_debug ( "rndw32: no PERF signature\n"); - break; - } - else if (status == ERROR_MORE_DATA) { - cbPerfData += PERFORMANCE_BUFFER_STEP; - pPerfData = m_realloc (pPerfData, cbPerfData); - } - else { - g10_log_debug ( "rndw32: get performance data problem\n"); - break; - } - } - m_free (pPerfData); - } - /* Although this isn't documented in the Win32 API docs, it's necessary - to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's - implicitly opened on the first call to RegQueryValueEx()). If this - isn't done then any system components which provide performance data - can't be removed or changed while the handle remains active */ - RegCloseKey (HKEY_PERFORMANCE_DATA); -} - - -int -rndw32_gather_random (void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - static int is_initialized; - static int is_windowsNT, has_toolhelp; - - - if( !level ) - return 0; - /* We don't differentiate between level 1 and 2 here because - * there is no nternal entropy pool as a scary resource. It may - * all work slower, but because our entropy source will never - * block but deliver some not easy to measure entropy, we assume level 2 - */ - - - if ( !is_initialized ) { - OSVERSIONINFO osvi = { sizeof( osvi ) }; - DWORD platform; - - GetVersionEx( &osvi ); - platform = osvi.dwPlatformId; - is_windowsNT = platform == VER_PLATFORM_WIN32_NT; - has_toolhelp = (platform == VER_PLATFORM_WIN32_WINDOWS - || (is_windowsNT && osvi.dwMajorVersion >= 5)); - - if ( platform == VER_PLATFORM_WIN32s ) { - g10_log_fatal("can't run on a W32s platform\n" ); - } - is_initialized = 1; - if ( debug_me ) - log_debug ("rndw32#gather_random: platform=%d\n", (int)platform ); - } - - - if ( debug_me ) - log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n", - requester, (unsigned int)length, level ); - - if ( has_toolhelp ) { - slow_gatherer_windows95 ( add, requester ); - } - if ( is_windowsNT ) { - slow_gatherer_windowsNT ( add, requester ); - } - - return 0; -} - - - -int -rndw32_gather_random_fast( void (*add)(const void*, size_t, int), int requester ) -{ - static int addedFixedItems = 0; - - if ( debug_me ) - log_debug ("rndw32#gather_random_fast: req=%d\n", requester ); - - /* Get various basic pieces of system information: Handle of active - * window, handle of window with mouse capture, handle of clipboard owner - * handle of start of clpboard viewer list, pseudohandle of current - * process, current process ID, pseudohandle of current thread, current - * thread ID, handle of desktop window, handle of window with keyboard - * focus, whether system queue has any events, cursor position for last - * message, 1 ms time for last message, handle of window with clipboard - * open, handle of process heap, handle of procs window station, types of - * events in input queue, and milliseconds since Windows was started */ - { byte buffer[20*sizeof(ulong)], *bufptr; - bufptr = buffer; - #define ADD(f) do { ulong along = (ulong)(f); \ - memcpy (bufptr, &along, sizeof (along) ); \ - bufptr += sizeof (along); } while (0) - ADD ( GetActiveWindow ()); - ADD ( GetCapture ()); - ADD ( GetClipboardOwner ()); - ADD ( GetClipboardViewer ()); - ADD ( GetCurrentProcess ()); - ADD ( GetCurrentProcessId ()); - ADD ( GetCurrentThread ()); - ADD ( GetCurrentThreadId ()); - ADD ( GetDesktopWindow ()); - ADD ( GetFocus ()); - ADD ( GetInputState ()); - ADD ( GetMessagePos ()); - ADD ( GetMessageTime ()); - ADD ( GetOpenClipboardWindow ()); - ADD ( GetProcessHeap ()); - ADD ( GetProcessWindowStation ()); - ADD ( GetQueueStatus (QS_ALLEVENTS)); - ADD ( GetTickCount ()); - - assert ( bufptr-buffer < sizeof (buffer) ); - (*add) ( buffer, bufptr-buffer, requester ); - #undef ADD - } - - /* Get multiword system information: Current caret position, current - * mouse cursor position */ - { POINT point; - GetCaretPos (&point); - (*add) ( &point, sizeof (point), requester ); - GetCursorPos (&point); - (*add) ( &point, sizeof (point), requester ); - } - - /* Get percent of memory in use, bytes of physical memory, bytes of free - * physical memory, bytes in paging file, free bytes in paging file, user - * bytes of address space, and free user bytes */ - { MEMORYSTATUS memoryStatus; - memoryStatus.dwLength = sizeof (MEMORYSTATUS); - GlobalMemoryStatus (&memoryStatus); - (*add) ( &memoryStatus, sizeof (memoryStatus), requester ); - } - - /* Get thread and process creation time, exit time, time in kernel mode, - and time in user mode in 100ns intervals */ - { HANDLE handle; - FILETIME creationTime, exitTime, kernelTime, userTime; - DWORD minimumWorkingSetSize, maximumWorkingSetSize; - - handle = GetCurrentThread (); - GetThreadTimes (handle, &creationTime, &exitTime, - &kernelTime, &userTime); - (*add) ( &creationTime, sizeof (creationTime), requester ); - (*add) ( &exitTime, sizeof (exitTime), requester ); - (*add) ( &kernelTime, sizeof (kernelTime), requester ); - (*add) ( &userTime, sizeof (userTime), requester ); - - handle = GetCurrentProcess (); - GetProcessTimes (handle, &creationTime, &exitTime, - &kernelTime, &userTime); - (*add) ( &creationTime, sizeof (creationTime), requester ); - (*add) ( &exitTime, sizeof (exitTime), requester ); - (*add) ( &kernelTime, sizeof (kernelTime), requester ); - (*add) ( &userTime, sizeof (userTime), requester ); - - /* Get the minimum and maximum working set size for the current process */ - GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, - &maximumWorkingSetSize); - (*add) ( &minimumWorkingSetSize, - sizeof (&minimumWorkingSetSize), requester ); - (*add) ( &maximumWorkingSetSize, - sizeof (&maximumWorkingSetSize), requester ); - } - - - /* The following are fixed for the lifetime of the process so we only - * add them once */ - if (!addedFixedItems) { - STARTUPINFO startupInfo; - - /* Get name of desktop, console window title, new window position and - * size, window flags, and handles for stdin, stdout, and stderr */ - startupInfo.cb = sizeof (STARTUPINFO); - GetStartupInfo (&startupInfo); - (*add) ( &startupInfo, sizeof (STARTUPINFO), requester ); - addedFixedItems = 1; - } - - /* The performance of QPC varies depending on the architecture it's - * running on and on the OS. Under NT it reads the CPU's 64-bit timestamp - * counter (at least on a Pentium and newer '486's, it hasn't been tested - * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC - * timer. There are vague mumblings in the docs that it may fail if the - * appropriate hardware isn't available (possibly '386's or MIPS machines - * running NT), but who's going to run NT on a '386? */ - { LARGE_INTEGER performanceCount; - if (QueryPerformanceCounter (&performanceCount)) { - if ( debug_me ) - log_debug ("rndw32#gather_random_fast: perf data\n"); - (*add) (&performanceCount, sizeof (&performanceCount), requester); - } - else { /* Millisecond accuracy at best... */ - DWORD aword = GetTickCount (); - (*add) (&aword, sizeof (aword), requester ); - } - } - - return 0; -} - - -#endif /*USE_RNDW32*/ diff --git a/cipher/rsa.c b/cipher/rsa.c deleted file mode 100644 index e438b39cf..000000000 --- a/cipher/rsa.c +++ /dev/null @@ -1,494 +0,0 @@ -/* rsa.c - RSA function - * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) - * Copyright (C) 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 - */ - -/* This code uses an algorithm protected by U.S. Patent #4,405,829 - which expires on September 20, 2000. The patent holder placed that - patent into the public domain on Sep 6th, 2000. -*/ - -#include -#include -#include -#include -#include "util.h" -#include "mpi.h" -#include "cipher.h" -#include "rsa.h" - - -typedef struct { - MPI n; /* modulus */ - MPI e; /* exponent */ -} RSA_public_key; - - -typedef struct { - MPI n; /* public modulus */ - MPI e; /* public exponent */ - MPI d; /* exponent */ - MPI p; /* prime p. */ - MPI q; /* prime q. */ - MPI u; /* inverse of p mod q. */ -} RSA_secret_key; - - -static void test_keys( RSA_secret_key *sk, unsigned nbits ); -static void generate( RSA_secret_key *sk, unsigned nbits ); -static int check_secret_key( RSA_secret_key *sk ); -static void public(MPI output, MPI input, RSA_public_key *skey ); -static void secret(MPI output, MPI input, RSA_secret_key *skey ); - - -static void -test_keys( RSA_secret_key *sk, unsigned nbits ) -{ - RSA_public_key pk; - MPI test = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - MPI out1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - MPI out2 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - - pk.n = sk->n; - pk.e = sk->e; - { char *p = get_random_bits( nbits, 0, 0 ); - mpi_set_buffer( test, p, (nbits+7)/8, 0 ); - m_free(p); - } - - public( out1, test, &pk ); - secret( out2, out1, sk ); - if( mpi_cmp( test, out2 ) ) - log_fatal("RSA operation: public, secret failed\n"); - secret( out1, test, sk ); - public( out2, out1, &pk ); - if( mpi_cmp( test, out2 ) ) - log_fatal("RSA operation: secret, public failed\n"); - mpi_free( test ); - mpi_free( out1 ); - mpi_free( out2 ); -} - -/**************** - * Generate a key pair with a key of size NBITS - * Returns: 2 structures filled with all needed values - */ -static void -generate( RSA_secret_key *sk, unsigned nbits ) -{ - MPI p, q; /* the two primes */ - MPI d; /* the private key */ - MPI u; - MPI t1, t2; - MPI n; /* the public key */ - MPI e; /* the exponent */ - MPI phi; /* helper: (p-1)(q-1) */ - MPI g; - MPI f; - - /* make sure that nbits is even so that we generate p, q of equal size */ - if ( (nbits&1) ) - nbits++; - - n = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - - p = q = NULL; - do { - /* select two (very secret) primes */ - if (p) - mpi_free (p); - if (q) - mpi_free (q); - p = generate_secret_prime( nbits / 2 ); - q = generate_secret_prime( nbits / 2 ); - if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q (for calc of u)*/ - mpi_swap(p,q); - /* calculate the modulus */ - mpi_mul( n, p, q ); - } while ( mpi_get_nbits(n) != nbits ); - - /* calculate Euler totient: phi = (p-1)(q-1) */ - t1 = mpi_alloc_secure( mpi_get_nlimbs(p) ); - t2 = mpi_alloc_secure( mpi_get_nlimbs(p) ); - phi = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - g = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - f = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - mpi_sub_ui( t1, p, 1 ); - mpi_sub_ui( t2, q, 1 ); - mpi_mul( phi, t1, t2 ); - mpi_gcd(g, t1, t2); - mpi_fdiv_q(f, phi, g); - - /* find an public exponent. - We use 41 as this is quite fast and more secure than the - commonly used 17. Benchmarking the RSA verify function - with a 1024 bit key yields (2001-11-08): - e=17 0.54 ms - e=41 0.75 ms - e=257 0.95 ms - e=65537 1.80 ms - */ - e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - mpi_set_ui( e, 41); - if( !mpi_gcd(t1, e, phi) ) { - mpi_set_ui( e, 257); - if( !mpi_gcd(t1, e, phi) ) { - mpi_set_ui( e, 65537); - while( !mpi_gcd(t1, e, phi) ) /* (while gcd is not 1) */ - mpi_add_ui( e, e, 2); - } - } - - /* calculate the secret key d = e^1 mod phi */ - d = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - mpi_invm(d, e, f ); - /* calculate the inverse of p and q (used for chinese remainder theorem)*/ - u = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); - mpi_invm(u, p, q ); - - if( DBG_CIPHER ) { - log_mpidump(" p= ", p ); - log_mpidump(" q= ", q ); - log_mpidump("phi= ", phi ); - log_mpidump(" g= ", g ); - log_mpidump(" f= ", f ); - log_mpidump(" n= ", n ); - log_mpidump(" e= ", e ); - log_mpidump(" d= ", d ); - log_mpidump(" u= ", u ); - } - - mpi_free(t1); - mpi_free(t2); - mpi_free(phi); - mpi_free(f); - mpi_free(g); - - sk->n = n; - sk->e = e; - sk->p = p; - sk->q = q; - sk->d = d; - sk->u = u; - - /* now we can test our keys (this should never fail!) */ - test_keys( sk, nbits - 64 ); -} - - -/**************** - * Test wether the secret key is valid. - * Returns: true if this is a valid key. - */ -static int -check_secret_key( RSA_secret_key *sk ) -{ - int rc; - MPI temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 ); - - mpi_mul(temp, sk->p, sk->q ); - rc = mpi_cmp( temp, sk->n ); - mpi_free(temp); - return !rc; -} - - - -/**************** - * Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT. - * - * c = m^e mod n - * - * Where c is OUTPUT, m is INPUT and e,n are elements of PKEY. - */ -static void -public(MPI output, MPI input, RSA_public_key *pkey ) -{ - if( output == input ) { /* powm doesn't like output and input the same */ - MPI x = mpi_alloc( mpi_get_nlimbs(input)*2 ); - mpi_powm( x, input, pkey->e, pkey->n ); - mpi_set(output, x); - mpi_free(x); - } - else - mpi_powm( output, input, pkey->e, pkey->n ); -} - -#if 0 -static void -stronger_key_check ( RSA_secret_key *skey ) -{ - MPI t = mpi_alloc_secure ( 0 ); - MPI t1 = mpi_alloc_secure ( 0 ); - MPI t2 = mpi_alloc_secure ( 0 ); - MPI phi = mpi_alloc_secure ( 0 ); - - /* check that n == p * q */ - mpi_mul( t, skey->p, skey->q); - if (mpi_cmp( t, skey->n) ) - log_info ( "RSA Oops: n != p * q\n" ); - - /* check that p is less than q */ - if( mpi_cmp( skey->p, skey->q ) > 0 ) - log_info ("RSA Oops: p >= q\n"); - - - /* check that e divides neither p-1 nor q-1 */ - mpi_sub_ui(t, skey->p, 1 ); - mpi_fdiv_r(t, t, skey->e ); - if ( !mpi_cmp_ui( t, 0) ) - log_info ( "RSA Oops: e divides p-1\n" ); - mpi_sub_ui(t, skey->q, 1 ); - mpi_fdiv_r(t, t, skey->e ); - if ( !mpi_cmp_ui( t, 0) ) - log_info ( "RSA Oops: e divides q-1\n" ); - - /* check that d is correct */ - mpi_sub_ui( t1, skey->p, 1 ); - mpi_sub_ui( t2, skey->q, 1 ); - mpi_mul( phi, t1, t2 ); - mpi_gcd(t, t1, t2); - mpi_fdiv_q(t, phi, t); - mpi_invm(t, skey->e, t ); - if ( mpi_cmp(t, skey->d ) ) - log_info ( "RSA Oops: d is wrong\n"); - - /* check for crrectness of u */ - mpi_invm(t, skey->p, skey->q ); - if ( mpi_cmp(t, skey->u ) ) - log_info ( "RSA Oops: u is wrong\n"); - - log_info ( "RSA secret key check finished\n"); - - mpi_free (t); - mpi_free (t1); - mpi_free (t2); - mpi_free (phi); -} -#endif - - -/**************** - * Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT. - * - * m = c^d mod n - * - * Or faster: - * - * m1 = c ^ (d mod (p-1)) mod p - * m2 = c ^ (d mod (q-1)) mod q - * h = u * (m2 - m1) mod q - * m = m1 + h * p - * - * Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY. - */ -static void -secret(MPI output, MPI input, RSA_secret_key *skey ) -{ - #if 0 - mpi_powm( output, input, skey->d, skey->n ); - #else - MPI m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); - MPI m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); - MPI h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 ); - - /* m1 = c ^ (d mod (p-1)) mod p */ - mpi_sub_ui( h, skey->p, 1 ); - mpi_fdiv_r( h, skey->d, h ); - mpi_powm( m1, input, h, skey->p ); - /* m2 = c ^ (d mod (q-1)) mod q */ - mpi_sub_ui( h, skey->q, 1 ); - mpi_fdiv_r( h, skey->d, h ); - mpi_powm( m2, input, h, skey->q ); - /* h = u * ( m2 - m1 ) mod q */ - mpi_sub( h, m2, m1 ); - if ( mpi_is_neg( h ) ) - mpi_add ( h, h, skey->q ); - mpi_mulm( h, skey->u, h, skey->q ); - /* m = m2 + h * p */ - mpi_mul ( h, h, skey->p ); - mpi_add ( output, m1, h ); - /* ready */ - - mpi_free ( h ); - mpi_free ( m1 ); - mpi_free ( m2 ); - #endif -} - - -/********************************************* - ************** interface ****************** - *********************************************/ - -int -rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ) -{ - RSA_secret_key sk; - - if( !is_RSA(algo) ) - return G10ERR_PUBKEY_ALGO; - - generate( &sk, nbits ); - skey[0] = sk.n; - skey[1] = sk.e; - skey[2] = sk.d; - skey[3] = sk.p; - skey[4] = sk.q; - skey[5] = sk.u; - /* make an empty list of factors */ - *retfactors = m_alloc_clear( 1 * sizeof **retfactors ); - return 0; -} - - -int -rsa_check_secret_key( int algo, MPI *skey ) -{ - RSA_secret_key sk; - - if( !is_RSA(algo) ) - return G10ERR_PUBKEY_ALGO; - - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - if( !check_secret_key( &sk ) ) - return G10ERR_BAD_SECKEY; - - return 0; -} - - - -int -rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ) -{ - RSA_public_key pk; - - if( algo != 1 && algo != 2 ) - return G10ERR_PUBKEY_ALGO; - - pk.n = pkey[0]; - pk.e = pkey[1]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.n ) ); - public( resarr[0], data, &pk ); - return 0; -} - -int -rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey ) -{ - RSA_secret_key sk; - - if( algo != 1 && algo != 2 ) - return G10ERR_PUBKEY_ALGO; - - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - *result = mpi_alloc_secure( mpi_get_nlimbs( sk.n ) ); - secret( *result, data[0], &sk ); - return 0; -} - -int -rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ) -{ - RSA_secret_key sk; - - if( algo != 1 && algo != 3 ) - return G10ERR_PUBKEY_ALGO; - - sk.n = skey[0]; - sk.e = skey[1]; - sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; - resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.n ) ); - secret( resarr[0], data, &sk ); - - return 0; -} - -int -rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *opaque, MPI tmp), void *opaquev ) -{ - RSA_public_key pk; - MPI result; - int rc; - - if( algo != 1 && algo != 3 ) - return G10ERR_PUBKEY_ALGO; - pk.n = pkey[0]; - pk.e = pkey[1]; - result = mpi_alloc( (160+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB); - public( result, data[0], &pk ); - /*rc = (*cmp)( opaquev, result );*/ - rc = mpi_cmp( result, hash )? G10ERR_BAD_SIGN:0; - mpi_free(result); - - return rc; -} - - -unsigned int -rsa_get_nbits( int algo, MPI *pkey ) -{ - if( !is_RSA(algo) ) - return 0; - return mpi_get_nbits( pkey[0] ); -} - - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - * Usage: Bit 0 set : allows signing - * 1 set : allows encryption - */ -const char * -rsa_get_info( int algo, - int *npkey, int *nskey, int *nenc, int *nsig, int *r_usage ) -{ - *npkey = 2; - *nskey = 6; - *nenc = 1; - *nsig = 1; - - switch( algo ) { - case 1: *r_usage = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; return "RSA"; - case 2: *r_usage = PUBKEY_USAGE_ENC; return "RSA-E"; - case 3: *r_usage = PUBKEY_USAGE_SIG; return "RSA-S"; - default:*r_usage = 0; return NULL; - } -} - - - diff --git a/cipher/rsa.h b/cipher/rsa.h deleted file mode 100644 index 350a373ec..000000000 --- a/cipher/rsa.h +++ /dev/null @@ -1,36 +0,0 @@ -/* rsa.h - * Copyright (C) 1997,1998 by Werner Koch (dd9jn) - * Copyright (C) 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_RSA_H -#define G10_RSA_H - -int rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); -int rsa_check_secret_key( int algo, MPI *skey ); -int rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); -int rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); -int rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey ); -int rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev ); -unsigned rsa_get_nbits( int algo, MPI *pkey ); -const char *rsa_get_info( int algo, int *npkey, int *nskey, - int *nenc, int *nsig, int *use ); - - -#endif /*G10_RSA_H*/ diff --git a/cipher/sha1.c b/cipher/sha1.c deleted file mode 100644 index 06ca2532b..000000000 --- a/cipher/sha1.c +++ /dev/null @@ -1,359 +0,0 @@ -/* sha1.c - SHA1 hash function - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * Please see below for more legal information! - * - * 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 - */ - - -/* Test vectors: - * - * "abc" - * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D - * - * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 - */ - - -#include -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "algorithms.h" -#include "bithelp.h" - - -typedef struct { - u32 h0,h1,h2,h3,h4; - u32 nblocks; - byte buf[64]; - int count; -} SHA1_CONTEXT; - -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - -void -sha1_init( SHA1_CONTEXT *hd ) -{ - hd->h0 = 0x67452301; - hd->h1 = 0xefcdab89; - hd->h2 = 0x98badcfe; - hd->h3 = 0x10325476; - hd->h4 = 0xc3d2e1f0; - hd->nblocks = 0; - hd->count = 0; -} - - -/**************** - * Transform the message X which consists of 16 32-bit-words - */ -static void -transform( SHA1_CONTEXT *hd, byte *data ) -{ - u32 a,b,c,d,e,tm; - u32 x[16]; - - /* get values from the chaining vars */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - - #ifdef BIG_ENDIAN_HOST - memcpy( x, data, 64 ); - #else - { int i; - byte *p2; - for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) { - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } - #endif - - -#define K1 0x5A827999L -#define K2 0x6ED9EBA1L -#define K3 0x8F1BBCDCL -#define K4 0xCA62C1D6L -#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) -#define F2(x,y,z) ( x ^ y ^ z ) -#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) -#define F4(x,y,z) ( x ^ y ^ z ) - - -#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ - ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ - , (x[i&0x0f] = rol(tm,1)) ) - -#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ - + f( b, c, d ) \ - + k \ - + m; \ - b = rol( b, 30 ); \ - } while(0) - R( a, b, c, d, e, F1, K1, x[ 0] ); - R( e, a, b, c, d, F1, K1, x[ 1] ); - R( d, e, a, b, c, F1, K1, x[ 2] ); - R( c, d, e, a, b, F1, K1, x[ 3] ); - R( b, c, d, e, a, F1, K1, x[ 4] ); - R( a, b, c, d, e, F1, K1, x[ 5] ); - R( e, a, b, c, d, F1, K1, x[ 6] ); - R( d, e, a, b, c, F1, K1, x[ 7] ); - R( c, d, e, a, b, F1, K1, x[ 8] ); - R( b, c, d, e, a, F1, K1, x[ 9] ); - R( a, b, c, d, e, F1, K1, x[10] ); - R( e, a, b, c, d, F1, K1, x[11] ); - R( d, e, a, b, c, F1, K1, x[12] ); - R( c, d, e, a, b, F1, K1, x[13] ); - R( b, c, d, e, a, F1, K1, x[14] ); - R( a, b, c, d, e, F1, K1, x[15] ); - R( e, a, b, c, d, F1, K1, M(16) ); - R( d, e, a, b, c, F1, K1, M(17) ); - R( c, d, e, a, b, F1, K1, M(18) ); - R( b, c, d, e, a, F1, K1, M(19) ); - R( a, b, c, d, e, F2, K2, M(20) ); - R( e, a, b, c, d, F2, K2, M(21) ); - R( d, e, a, b, c, F2, K2, M(22) ); - R( c, d, e, a, b, F2, K2, M(23) ); - R( b, c, d, e, a, F2, K2, M(24) ); - R( a, b, c, d, e, F2, K2, M(25) ); - R( e, a, b, c, d, F2, K2, M(26) ); - R( d, e, a, b, c, F2, K2, M(27) ); - R( c, d, e, a, b, F2, K2, M(28) ); - R( b, c, d, e, a, F2, K2, M(29) ); - R( a, b, c, d, e, F2, K2, M(30) ); - R( e, a, b, c, d, F2, K2, M(31) ); - R( d, e, a, b, c, F2, K2, M(32) ); - R( c, d, e, a, b, F2, K2, M(33) ); - R( b, c, d, e, a, F2, K2, M(34) ); - R( a, b, c, d, e, F2, K2, M(35) ); - R( e, a, b, c, d, F2, K2, M(36) ); - R( d, e, a, b, c, F2, K2, M(37) ); - R( c, d, e, a, b, F2, K2, M(38) ); - R( b, c, d, e, a, F2, K2, M(39) ); - R( a, b, c, d, e, F3, K3, M(40) ); - R( e, a, b, c, d, F3, K3, M(41) ); - R( d, e, a, b, c, F3, K3, M(42) ); - R( c, d, e, a, b, F3, K3, M(43) ); - R( b, c, d, e, a, F3, K3, M(44) ); - R( a, b, c, d, e, F3, K3, M(45) ); - R( e, a, b, c, d, F3, K3, M(46) ); - R( d, e, a, b, c, F3, K3, M(47) ); - R( c, d, e, a, b, F3, K3, M(48) ); - R( b, c, d, e, a, F3, K3, M(49) ); - R( a, b, c, d, e, F3, K3, M(50) ); - R( e, a, b, c, d, F3, K3, M(51) ); - R( d, e, a, b, c, F3, K3, M(52) ); - R( c, d, e, a, b, F3, K3, M(53) ); - R( b, c, d, e, a, F3, K3, M(54) ); - R( a, b, c, d, e, F3, K3, M(55) ); - R( e, a, b, c, d, F3, K3, M(56) ); - R( d, e, a, b, c, F3, K3, M(57) ); - R( c, d, e, a, b, F3, K3, M(58) ); - R( b, c, d, e, a, F3, K3, M(59) ); - R( a, b, c, d, e, F4, K4, M(60) ); - R( e, a, b, c, d, F4, K4, M(61) ); - R( d, e, a, b, c, F4, K4, M(62) ); - R( c, d, e, a, b, F4, K4, M(63) ); - R( b, c, d, e, a, F4, K4, M(64) ); - R( a, b, c, d, e, F4, K4, M(65) ); - R( e, a, b, c, d, F4, K4, M(66) ); - R( d, e, a, b, c, F4, K4, M(67) ); - R( c, d, e, a, b, F4, K4, M(68) ); - R( b, c, d, e, a, F4, K4, M(69) ); - R( a, b, c, d, e, F4, K4, M(70) ); - R( e, a, b, c, d, F4, K4, M(71) ); - R( d, e, a, b, c, F4, K4, M(72) ); - R( c, d, e, a, b, F4, K4, M(73) ); - R( b, c, d, e, a, F4, K4, M(74) ); - R( a, b, c, d, e, F4, K4, M(75) ); - R( e, a, b, c, d, F4, K4, M(76) ); - R( d, e, a, b, c, F4, K4, M(77) ); - R( c, d, e, a, b, F4, K4, M(78) ); - R( b, c, d, e, a, F4, K4, M(79) ); - - /* update chainig vars */ - hd->h0 += a; - hd->h1 += b; - hd->h2 += c; - hd->h3 += d; - hd->h4 += e; -} - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -static void -sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen) -{ - if( hd->count == 64 ) { /* flush the buffer */ - transform( hd, hd->buf ); - burn_stack (88+4*sizeof(void*)); - hd->count = 0; - hd->nblocks++; - } - if( !inbuf ) - return; - if( hd->count ) { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; - sha1_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - - while( inlen >= 64 ) { - transform( hd, inbuf ); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - burn_stack (88+4*sizeof(void*)); - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; -} - - -/* The routine final terminates the computation and - * returns the digest. - * The handle is prepared for a new cycle, but adding bytes to the - * handle will the destroy the returned buffer. - * Returns: 20 bytes representing the digest. - */ - -static void -sha1_final(SHA1_CONTEXT *hd) -{ - u32 t, msb, lsb; - byte *p; - - sha1_write(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if( (lsb += hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if( hd->count < 56 ) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] = 0; - sha1_write(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = msb >> 24; - hd->buf[57] = msb >> 16; - hd->buf[58] = msb >> 8; - hd->buf[59] = msb ; - hd->buf[60] = lsb >> 24; - hd->buf[61] = lsb >> 16; - hd->buf[62] = lsb >> 8; - hd->buf[63] = lsb ; - transform( hd, hd->buf ); - burn_stack (88+4*sizeof(void*)); - - p = hd->buf; - #ifdef BIG_ENDIAN_HOST - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - #else /* little endian */ - #define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) - #endif - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X - -} - -static byte * -sha1_read( SHA1_CONTEXT *hd ) -{ - return hd->buf; -} - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -const char * -sha1_get_info( int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ) -{ - static byte asn[15] = /* Object ID is 1.3.14.3.2.26 */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, - 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; - if( algo != 2 ) - return NULL; - - *contextsize = sizeof(SHA1_CONTEXT); - *r_asnoid = asn; - *r_asnlen = DIM(asn); - *r_mdlen = 20; - *(void (**)(SHA1_CONTEXT *))r_init = sha1_init; - *(void (**)(SHA1_CONTEXT *, byte*, size_t))r_write = sha1_write; - *(void (**)(SHA1_CONTEXT *))r_final = sha1_final; - *(byte *(**)(SHA1_CONTEXT *))r_read = sha1_read; - - return "SHA1"; -} diff --git a/cipher/smallprime.c b/cipher/smallprime.c deleted file mode 100644 index 941f4ce9a..000000000 --- a/cipher/smallprime.c +++ /dev/null @@ -1,114 +0,0 @@ -/* smallprime.c - List of small primes - * 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 -#include -#include -#include "util.h" -#include "types.h" - -/* Note: 2 is not included because it can be tested more easily - * by looking at bit 0. The last entry in this list is marked by a zero - */ -ushort -small_prime_numbers[] = { - 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, - 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, - 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, - 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, - 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, - 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, - 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, - 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, - 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, - 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, - 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, - 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, - 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, - 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, - 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, - 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, - 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, - 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, - 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, - 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, - 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, - 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, - 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, - 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, - 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, - 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, - 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, - 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, - 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, - 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, - 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, - 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, - 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, - 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, - 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, - 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, - 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, - 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, - 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, - 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, - 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, - 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, - 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, - 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, - 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, - 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, - 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, - 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, - 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, - 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, - 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, - 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, - 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, - 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, - 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, - 4957, 4967, 4969, 4973, 4987, 4993, 4999, - 0 -}; - - diff --git a/cipher/tiger.c b/cipher/tiger.c deleted file mode 100644 index 1bb3375ed..000000000 --- a/cipher/tiger.c +++ /dev/null @@ -1,930 +0,0 @@ -/* tiger.c - The TIGER hash function - * 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 -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "algorithms.h" - -#ifdef HAVE_U64_TYPEDEF - -/* we really need it here, but as this is only experiment we - * can live without Tiger */ - -typedef struct { - u64 a, b, c; - byte buf[64]; - int count; - u32 nblocks; -} TIGER_CONTEXT; - - -/********************************* - * Okay, okay, this is not the fastest code - improvements are welcome. - * - */ - -/* Some test vectors: - * "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A - * "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 - * "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF - * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" - * 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 - * "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" - * 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 - * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" - * 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 - * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" - * "eedings of Fast Software Encryption 3, Cambridge." - * EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 - * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" - * "eedings of Fast Software Encryption 3, Cambridge, 1996." - * 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC - * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF" - * "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" - * 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 - */ - - -static u64 sbox1[256] = { - 0x02aab17cf7e90c5eLL /* 0 */, 0xac424b03e243a8ecLL /* 1 */, - 0x72cd5be30dd5fcd3LL /* 2 */, 0x6d019b93f6f97f3aLL /* 3 */, - 0xcd9978ffd21f9193LL /* 4 */, 0x7573a1c9708029e2LL /* 5 */, - 0xb164326b922a83c3LL /* 6 */, 0x46883eee04915870LL /* 7 */, - 0xeaace3057103ece6LL /* 8 */, 0xc54169b808a3535cLL /* 9 */, - 0x4ce754918ddec47cLL /* 10 */, 0x0aa2f4dfdc0df40cLL /* 11 */, - 0x10b76f18a74dbefaLL /* 12 */, 0xc6ccb6235ad1ab6aLL /* 13 */, - 0x13726121572fe2ffLL /* 14 */, 0x1a488c6f199d921eLL /* 15 */, - 0x4bc9f9f4da0007caLL /* 16 */, 0x26f5e6f6e85241c7LL /* 17 */, - 0x859079dbea5947b6LL /* 18 */, 0x4f1885c5c99e8c92LL /* 19 */, - 0xd78e761ea96f864bLL /* 20 */, 0x8e36428c52b5c17dLL /* 21 */, - 0x69cf6827373063c1LL /* 22 */, 0xb607c93d9bb4c56eLL /* 23 */, - 0x7d820e760e76b5eaLL /* 24 */, 0x645c9cc6f07fdc42LL /* 25 */, - 0xbf38a078243342e0LL /* 26 */, 0x5f6b343c9d2e7d04LL /* 27 */, - 0xf2c28aeb600b0ec6LL /* 28 */, 0x6c0ed85f7254bcacLL /* 29 */, - 0x71592281a4db4fe5LL /* 30 */, 0x1967fa69ce0fed9fLL /* 31 */, - 0xfd5293f8b96545dbLL /* 32 */, 0xc879e9d7f2a7600bLL /* 33 */, - 0x860248920193194eLL /* 34 */, 0xa4f9533b2d9cc0b3LL /* 35 */, - 0x9053836c15957613LL /* 36 */, 0xdb6dcf8afc357bf1LL /* 37 */, - 0x18beea7a7a370f57LL /* 38 */, 0x037117ca50b99066LL /* 39 */, - 0x6ab30a9774424a35LL /* 40 */, 0xf4e92f02e325249bLL /* 41 */, - 0x7739db07061ccae1LL /* 42 */, 0xd8f3b49ceca42a05LL /* 43 */, - 0xbd56be3f51382f73LL /* 44 */, 0x45faed5843b0bb28LL /* 45 */, - 0x1c813d5c11bf1f83LL /* 46 */, 0x8af0e4b6d75fa169LL /* 47 */, - 0x33ee18a487ad9999LL /* 48 */, 0x3c26e8eab1c94410LL /* 49 */, - 0xb510102bc0a822f9LL /* 50 */, 0x141eef310ce6123bLL /* 51 */, - 0xfc65b90059ddb154LL /* 52 */, 0xe0158640c5e0e607LL /* 53 */, - 0x884e079826c3a3cfLL /* 54 */, 0x930d0d9523c535fdLL /* 55 */, - 0x35638d754e9a2b00LL /* 56 */, 0x4085fccf40469dd5LL /* 57 */, - 0xc4b17ad28be23a4cLL /* 58 */, 0xcab2f0fc6a3e6a2eLL /* 59 */, - 0x2860971a6b943fcdLL /* 60 */, 0x3dde6ee212e30446LL /* 61 */, - 0x6222f32ae01765aeLL /* 62 */, 0x5d550bb5478308feLL /* 63 */, - 0xa9efa98da0eda22aLL /* 64 */, 0xc351a71686c40da7LL /* 65 */, - 0x1105586d9c867c84LL /* 66 */, 0xdcffee85fda22853LL /* 67 */, - 0xccfbd0262c5eef76LL /* 68 */, 0xbaf294cb8990d201LL /* 69 */, - 0xe69464f52afad975LL /* 70 */, 0x94b013afdf133e14LL /* 71 */, - 0x06a7d1a32823c958LL /* 72 */, 0x6f95fe5130f61119LL /* 73 */, - 0xd92ab34e462c06c0LL /* 74 */, 0xed7bde33887c71d2LL /* 75 */, - 0x79746d6e6518393eLL /* 76 */, 0x5ba419385d713329LL /* 77 */, - 0x7c1ba6b948a97564LL /* 78 */, 0x31987c197bfdac67LL /* 79 */, - 0xde6c23c44b053d02LL /* 80 */, 0x581c49fed002d64dLL /* 81 */, - 0xdd474d6338261571LL /* 82 */, 0xaa4546c3e473d062LL /* 83 */, - 0x928fce349455f860LL /* 84 */, 0x48161bbacaab94d9LL /* 85 */, - 0x63912430770e6f68LL /* 86 */, 0x6ec8a5e602c6641cLL /* 87 */, - 0x87282515337ddd2bLL /* 88 */, 0x2cda6b42034b701bLL /* 89 */, - 0xb03d37c181cb096dLL /* 90 */, 0xe108438266c71c6fLL /* 91 */, - 0x2b3180c7eb51b255LL /* 92 */, 0xdf92b82f96c08bbcLL /* 93 */, - 0x5c68c8c0a632f3baLL /* 94 */, 0x5504cc861c3d0556LL /* 95 */, - 0xabbfa4e55fb26b8fLL /* 96 */, 0x41848b0ab3baceb4LL /* 97 */, - 0xb334a273aa445d32LL /* 98 */, 0xbca696f0a85ad881LL /* 99 */, - 0x24f6ec65b528d56cLL /* 100 */, 0x0ce1512e90f4524aLL /* 101 */, - 0x4e9dd79d5506d35aLL /* 102 */, 0x258905fac6ce9779LL /* 103 */, - 0x2019295b3e109b33LL /* 104 */, 0xf8a9478b73a054ccLL /* 105 */, - 0x2924f2f934417eb0LL /* 106 */, 0x3993357d536d1bc4LL /* 107 */, - 0x38a81ac21db6ff8bLL /* 108 */, 0x47c4fbf17d6016bfLL /* 109 */, - 0x1e0faadd7667e3f5LL /* 110 */, 0x7abcff62938beb96LL /* 111 */, - 0xa78dad948fc179c9LL /* 112 */, 0x8f1f98b72911e50dLL /* 113 */, - 0x61e48eae27121a91LL /* 114 */, 0x4d62f7ad31859808LL /* 115 */, - 0xeceba345ef5ceaebLL /* 116 */, 0xf5ceb25ebc9684ceLL /* 117 */, - 0xf633e20cb7f76221LL /* 118 */, 0xa32cdf06ab8293e4LL /* 119 */, - 0x985a202ca5ee2ca4LL /* 120 */, 0xcf0b8447cc8a8fb1LL /* 121 */, - 0x9f765244979859a3LL /* 122 */, 0xa8d516b1a1240017LL /* 123 */, - 0x0bd7ba3ebb5dc726LL /* 124 */, 0xe54bca55b86adb39LL /* 125 */, - 0x1d7a3afd6c478063LL /* 126 */, 0x519ec608e7669eddLL /* 127 */, - 0x0e5715a2d149aa23LL /* 128 */, 0x177d4571848ff194LL /* 129 */, - 0xeeb55f3241014c22LL /* 130 */, 0x0f5e5ca13a6e2ec2LL /* 131 */, - 0x8029927b75f5c361LL /* 132 */, 0xad139fabc3d6e436LL /* 133 */, - 0x0d5df1a94ccf402fLL /* 134 */, 0x3e8bd948bea5dfc8LL /* 135 */, - 0xa5a0d357bd3ff77eLL /* 136 */, 0xa2d12e251f74f645LL /* 137 */, - 0x66fd9e525e81a082LL /* 138 */, 0x2e0c90ce7f687a49LL /* 139 */, - 0xc2e8bcbeba973bc5LL /* 140 */, 0x000001bce509745fLL /* 141 */, - 0x423777bbe6dab3d6LL /* 142 */, 0xd1661c7eaef06eb5LL /* 143 */, - 0xa1781f354daacfd8LL /* 144 */, 0x2d11284a2b16affcLL /* 145 */, - 0xf1fc4f67fa891d1fLL /* 146 */, 0x73ecc25dcb920adaLL /* 147 */, - 0xae610c22c2a12651LL /* 148 */, 0x96e0a810d356b78aLL /* 149 */, - 0x5a9a381f2fe7870fLL /* 150 */, 0xd5ad62ede94e5530LL /* 151 */, - 0xd225e5e8368d1427LL /* 152 */, 0x65977b70c7af4631LL /* 153 */, - 0x99f889b2de39d74fLL /* 154 */, 0x233f30bf54e1d143LL /* 155 */, - 0x9a9675d3d9a63c97LL /* 156 */, 0x5470554ff334f9a8LL /* 157 */, - 0x166acb744a4f5688LL /* 158 */, 0x70c74caab2e4aeadLL /* 159 */, - 0xf0d091646f294d12LL /* 160 */, 0x57b82a89684031d1LL /* 161 */, - 0xefd95a5a61be0b6bLL /* 162 */, 0x2fbd12e969f2f29aLL /* 163 */, - 0x9bd37013feff9fe8LL /* 164 */, 0x3f9b0404d6085a06LL /* 165 */, - 0x4940c1f3166cfe15LL /* 166 */, 0x09542c4dcdf3defbLL /* 167 */, - 0xb4c5218385cd5ce3LL /* 168 */, 0xc935b7dc4462a641LL /* 169 */, - 0x3417f8a68ed3b63fLL /* 170 */, 0xb80959295b215b40LL /* 171 */, - 0xf99cdaef3b8c8572LL /* 172 */, 0x018c0614f8fcb95dLL /* 173 */, - 0x1b14accd1a3acdf3LL /* 174 */, 0x84d471f200bb732dLL /* 175 */, - 0xc1a3110e95e8da16LL /* 176 */, 0x430a7220bf1a82b8LL /* 177 */, - 0xb77e090d39df210eLL /* 178 */, 0x5ef4bd9f3cd05e9dLL /* 179 */, - 0x9d4ff6da7e57a444LL /* 180 */, 0xda1d60e183d4a5f8LL /* 181 */, - 0xb287c38417998e47LL /* 182 */, 0xfe3edc121bb31886LL /* 183 */, - 0xc7fe3ccc980ccbefLL /* 184 */, 0xe46fb590189bfd03LL /* 185 */, - 0x3732fd469a4c57dcLL /* 186 */, 0x7ef700a07cf1ad65LL /* 187 */, - 0x59c64468a31d8859LL /* 188 */, 0x762fb0b4d45b61f6LL /* 189 */, - 0x155baed099047718LL /* 190 */, 0x68755e4c3d50baa6LL /* 191 */, - 0xe9214e7f22d8b4dfLL /* 192 */, 0x2addbf532eac95f4LL /* 193 */, - 0x32ae3909b4bd0109LL /* 194 */, 0x834df537b08e3450LL /* 195 */, - 0xfa209da84220728dLL /* 196 */, 0x9e691d9b9efe23f7LL /* 197 */, - 0x0446d288c4ae8d7fLL /* 198 */, 0x7b4cc524e169785bLL /* 199 */, - 0x21d87f0135ca1385LL /* 200 */, 0xcebb400f137b8aa5LL /* 201 */, - 0x272e2b66580796beLL /* 202 */, 0x3612264125c2b0deLL /* 203 */, - 0x057702bdad1efbb2LL /* 204 */, 0xd4babb8eacf84be9LL /* 205 */, - 0x91583139641bc67bLL /* 206 */, 0x8bdc2de08036e024LL /* 207 */, - 0x603c8156f49f68edLL /* 208 */, 0xf7d236f7dbef5111LL /* 209 */, - 0x9727c4598ad21e80LL /* 210 */, 0xa08a0896670a5fd7LL /* 211 */, - 0xcb4a8f4309eba9cbLL /* 212 */, 0x81af564b0f7036a1LL /* 213 */, - 0xc0b99aa778199abdLL /* 214 */, 0x959f1ec83fc8e952LL /* 215 */, - 0x8c505077794a81b9LL /* 216 */, 0x3acaaf8f056338f0LL /* 217 */, - 0x07b43f50627a6778LL /* 218 */, 0x4a44ab49f5eccc77LL /* 219 */, - 0x3bc3d6e4b679ee98LL /* 220 */, 0x9cc0d4d1cf14108cLL /* 221 */, - 0x4406c00b206bc8a0LL /* 222 */, 0x82a18854c8d72d89LL /* 223 */, - 0x67e366b35c3c432cLL /* 224 */, 0xb923dd61102b37f2LL /* 225 */, - 0x56ab2779d884271dLL /* 226 */, 0xbe83e1b0ff1525afLL /* 227 */, - 0xfb7c65d4217e49a9LL /* 228 */, 0x6bdbe0e76d48e7d4LL /* 229 */, - 0x08df828745d9179eLL /* 230 */, 0x22ea6a9add53bd34LL /* 231 */, - 0xe36e141c5622200aLL /* 232 */, 0x7f805d1b8cb750eeLL /* 233 */, - 0xafe5c7a59f58e837LL /* 234 */, 0xe27f996a4fb1c23cLL /* 235 */, - 0xd3867dfb0775f0d0LL /* 236 */, 0xd0e673de6e88891aLL /* 237 */, - 0x123aeb9eafb86c25LL /* 238 */, 0x30f1d5d5c145b895LL /* 239 */, - 0xbb434a2dee7269e7LL /* 240 */, 0x78cb67ecf931fa38LL /* 241 */, - 0xf33b0372323bbf9cLL /* 242 */, 0x52d66336fb279c74LL /* 243 */, - 0x505f33ac0afb4eaaLL /* 244 */, 0xe8a5cd99a2cce187LL /* 245 */, - 0x534974801e2d30bbLL /* 246 */, 0x8d2d5711d5876d90LL /* 247 */, - 0x1f1a412891bc038eLL /* 248 */, 0xd6e2e71d82e56648LL /* 249 */, - 0x74036c3a497732b7LL /* 250 */, 0x89b67ed96361f5abLL /* 251 */, - 0xffed95d8f1ea02a2LL /* 252 */, 0xe72b3bd61464d43dLL /* 253 */, - 0xa6300f170bdc4820LL /* 254 */, 0xebc18760ed78a77aLL /* 255 */ -}; -static u64 sbox2[256] = { - 0xe6a6be5a05a12138LL /* 256 */, 0xb5a122a5b4f87c98LL /* 257 */, - 0x563c6089140b6990LL /* 258 */, 0x4c46cb2e391f5dd5LL /* 259 */, - 0xd932addbc9b79434LL /* 260 */, 0x08ea70e42015aff5LL /* 261 */, - 0xd765a6673e478cf1LL /* 262 */, 0xc4fb757eab278d99LL /* 263 */, - 0xdf11c6862d6e0692LL /* 264 */, 0xddeb84f10d7f3b16LL /* 265 */, - 0x6f2ef604a665ea04LL /* 266 */, 0x4a8e0f0ff0e0dfb3LL /* 267 */, - 0xa5edeef83dbcba51LL /* 268 */, 0xfc4f0a2a0ea4371eLL /* 269 */, - 0xe83e1da85cb38429LL /* 270 */, 0xdc8ff882ba1b1ce2LL /* 271 */, - 0xcd45505e8353e80dLL /* 272 */, 0x18d19a00d4db0717LL /* 273 */, - 0x34a0cfeda5f38101LL /* 274 */, 0x0be77e518887caf2LL /* 275 */, - 0x1e341438b3c45136LL /* 276 */, 0xe05797f49089ccf9LL /* 277 */, - 0xffd23f9df2591d14LL /* 278 */, 0x543dda228595c5cdLL /* 279 */, - 0x661f81fd99052a33LL /* 280 */, 0x8736e641db0f7b76LL /* 281 */, - 0x15227725418e5307LL /* 282 */, 0xe25f7f46162eb2faLL /* 283 */, - 0x48a8b2126c13d9feLL /* 284 */, 0xafdc541792e76eeaLL /* 285 */, - 0x03d912bfc6d1898fLL /* 286 */, 0x31b1aafa1b83f51bLL /* 287 */, - 0xf1ac2796e42ab7d9LL /* 288 */, 0x40a3a7d7fcd2ebacLL /* 289 */, - 0x1056136d0afbbcc5LL /* 290 */, 0x7889e1dd9a6d0c85LL /* 291 */, - 0xd33525782a7974aaLL /* 292 */, 0xa7e25d09078ac09bLL /* 293 */, - 0xbd4138b3eac6edd0LL /* 294 */, 0x920abfbe71eb9e70LL /* 295 */, - 0xa2a5d0f54fc2625cLL /* 296 */, 0xc054e36b0b1290a3LL /* 297 */, - 0xf6dd59ff62fe932bLL /* 298 */, 0x3537354511a8ac7dLL /* 299 */, - 0xca845e9172fadcd4LL /* 300 */, 0x84f82b60329d20dcLL /* 301 */, - 0x79c62ce1cd672f18LL /* 302 */, 0x8b09a2add124642cLL /* 303 */, - 0xd0c1e96a19d9e726LL /* 304 */, 0x5a786a9b4ba9500cLL /* 305 */, - 0x0e020336634c43f3LL /* 306 */, 0xc17b474aeb66d822LL /* 307 */, - 0x6a731ae3ec9baac2LL /* 308 */, 0x8226667ae0840258LL /* 309 */, - 0x67d4567691caeca5LL /* 310 */, 0x1d94155c4875adb5LL /* 311 */, - 0x6d00fd985b813fdfLL /* 312 */, 0x51286efcb774cd06LL /* 313 */, - 0x5e8834471fa744afLL /* 314 */, 0xf72ca0aee761ae2eLL /* 315 */, - 0xbe40e4cdaee8e09aLL /* 316 */, 0xe9970bbb5118f665LL /* 317 */, - 0x726e4beb33df1964LL /* 318 */, 0x703b000729199762LL /* 319 */, - 0x4631d816f5ef30a7LL /* 320 */, 0xb880b5b51504a6beLL /* 321 */, - 0x641793c37ed84b6cLL /* 322 */, 0x7b21ed77f6e97d96LL /* 323 */, - 0x776306312ef96b73LL /* 324 */, 0xae528948e86ff3f4LL /* 325 */, - 0x53dbd7f286a3f8f8LL /* 326 */, 0x16cadce74cfc1063LL /* 327 */, - 0x005c19bdfa52c6ddLL /* 328 */, 0x68868f5d64d46ad3LL /* 329 */, - 0x3a9d512ccf1e186aLL /* 330 */, 0x367e62c2385660aeLL /* 331 */, - 0xe359e7ea77dcb1d7LL /* 332 */, 0x526c0773749abe6eLL /* 333 */, - 0x735ae5f9d09f734bLL /* 334 */, 0x493fc7cc8a558ba8LL /* 335 */, - 0xb0b9c1533041ab45LL /* 336 */, 0x321958ba470a59bdLL /* 337 */, - 0x852db00b5f46c393LL /* 338 */, 0x91209b2bd336b0e5LL /* 339 */, - 0x6e604f7d659ef19fLL /* 340 */, 0xb99a8ae2782ccb24LL /* 341 */, - 0xccf52ab6c814c4c7LL /* 342 */, 0x4727d9afbe11727bLL /* 343 */, - 0x7e950d0c0121b34dLL /* 344 */, 0x756f435670ad471fLL /* 345 */, - 0xf5add442615a6849LL /* 346 */, 0x4e87e09980b9957aLL /* 347 */, - 0x2acfa1df50aee355LL /* 348 */, 0xd898263afd2fd556LL /* 349 */, - 0xc8f4924dd80c8fd6LL /* 350 */, 0xcf99ca3d754a173aLL /* 351 */, - 0xfe477bacaf91bf3cLL /* 352 */, 0xed5371f6d690c12dLL /* 353 */, - 0x831a5c285e687094LL /* 354 */, 0xc5d3c90a3708a0a4LL /* 355 */, - 0x0f7f903717d06580LL /* 356 */, 0x19f9bb13b8fdf27fLL /* 357 */, - 0xb1bd6f1b4d502843LL /* 358 */, 0x1c761ba38fff4012LL /* 359 */, - 0x0d1530c4e2e21f3bLL /* 360 */, 0x8943ce69a7372c8aLL /* 361 */, - 0xe5184e11feb5ce66LL /* 362 */, 0x618bdb80bd736621LL /* 363 */, - 0x7d29bad68b574d0bLL /* 364 */, 0x81bb613e25e6fe5bLL /* 365 */, - 0x071c9c10bc07913fLL /* 366 */, 0xc7beeb7909ac2d97LL /* 367 */, - 0xc3e58d353bc5d757LL /* 368 */, 0xeb017892f38f61e8LL /* 369 */, - 0xd4effb9c9b1cc21aLL /* 370 */, 0x99727d26f494f7abLL /* 371 */, - 0xa3e063a2956b3e03LL /* 372 */, 0x9d4a8b9a4aa09c30LL /* 373 */, - 0x3f6ab7d500090fb4LL /* 374 */, 0x9cc0f2a057268ac0LL /* 375 */, - 0x3dee9d2dedbf42d1LL /* 376 */, 0x330f49c87960a972LL /* 377 */, - 0xc6b2720287421b41LL /* 378 */, 0x0ac59ec07c00369cLL /* 379 */, - 0xef4eac49cb353425LL /* 380 */, 0xf450244eef0129d8LL /* 381 */, - 0x8acc46e5caf4deb6LL /* 382 */, 0x2ffeab63989263f7LL /* 383 */, - 0x8f7cb9fe5d7a4578LL /* 384 */, 0x5bd8f7644e634635LL /* 385 */, - 0x427a7315bf2dc900LL /* 386 */, 0x17d0c4aa2125261cLL /* 387 */, - 0x3992486c93518e50LL /* 388 */, 0xb4cbfee0a2d7d4c3LL /* 389 */, - 0x7c75d6202c5ddd8dLL /* 390 */, 0xdbc295d8e35b6c61LL /* 391 */, - 0x60b369d302032b19LL /* 392 */, 0xce42685fdce44132LL /* 393 */, - 0x06f3ddb9ddf65610LL /* 394 */, 0x8ea4d21db5e148f0LL /* 395 */, - 0x20b0fce62fcd496fLL /* 396 */, 0x2c1b912358b0ee31LL /* 397 */, - 0xb28317b818f5a308LL /* 398 */, 0xa89c1e189ca6d2cfLL /* 399 */, - 0x0c6b18576aaadbc8LL /* 400 */, 0xb65deaa91299fae3LL /* 401 */, - 0xfb2b794b7f1027e7LL /* 402 */, 0x04e4317f443b5bebLL /* 403 */, - 0x4b852d325939d0a6LL /* 404 */, 0xd5ae6beefb207ffcLL /* 405 */, - 0x309682b281c7d374LL /* 406 */, 0xbae309a194c3b475LL /* 407 */, - 0x8cc3f97b13b49f05LL /* 408 */, 0x98a9422ff8293967LL /* 409 */, - 0x244b16b01076ff7cLL /* 410 */, 0xf8bf571c663d67eeLL /* 411 */, - 0x1f0d6758eee30da1LL /* 412 */, 0xc9b611d97adeb9b7LL /* 413 */, - 0xb7afd5887b6c57a2LL /* 414 */, 0x6290ae846b984fe1LL /* 415 */, - 0x94df4cdeacc1a5fdLL /* 416 */, 0x058a5bd1c5483affLL /* 417 */, - 0x63166cc142ba3c37LL /* 418 */, 0x8db8526eb2f76f40LL /* 419 */, - 0xe10880036f0d6d4eLL /* 420 */, 0x9e0523c9971d311dLL /* 421 */, - 0x45ec2824cc7cd691LL /* 422 */, 0x575b8359e62382c9LL /* 423 */, - 0xfa9e400dc4889995LL /* 424 */, 0xd1823ecb45721568LL /* 425 */, - 0xdafd983b8206082fLL /* 426 */, 0xaa7d29082386a8cbLL /* 427 */, - 0x269fcd4403b87588LL /* 428 */, 0x1b91f5f728bdd1e0LL /* 429 */, - 0xe4669f39040201f6LL /* 430 */, 0x7a1d7c218cf04adeLL /* 431 */, - 0x65623c29d79ce5ceLL /* 432 */, 0x2368449096c00bb1LL /* 433 */, - 0xab9bf1879da503baLL /* 434 */, 0xbc23ecb1a458058eLL /* 435 */, - 0x9a58df01bb401eccLL /* 436 */, 0xa070e868a85f143dLL /* 437 */, - 0x4ff188307df2239eLL /* 438 */, 0x14d565b41a641183LL /* 439 */, - 0xee13337452701602LL /* 440 */, 0x950e3dcf3f285e09LL /* 441 */, - 0x59930254b9c80953LL /* 442 */, 0x3bf299408930da6dLL /* 443 */, - 0xa955943f53691387LL /* 444 */, 0xa15edecaa9cb8784LL /* 445 */, - 0x29142127352be9a0LL /* 446 */, 0x76f0371fff4e7afbLL /* 447 */, - 0x0239f450274f2228LL /* 448 */, 0xbb073af01d5e868bLL /* 449 */, - 0xbfc80571c10e96c1LL /* 450 */, 0xd267088568222e23LL /* 451 */, - 0x9671a3d48e80b5b0LL /* 452 */, 0x55b5d38ae193bb81LL /* 453 */, - 0x693ae2d0a18b04b8LL /* 454 */, 0x5c48b4ecadd5335fLL /* 455 */, - 0xfd743b194916a1caLL /* 456 */, 0x2577018134be98c4LL /* 457 */, - 0xe77987e83c54a4adLL /* 458 */, 0x28e11014da33e1b9LL /* 459 */, - 0x270cc59e226aa213LL /* 460 */, 0x71495f756d1a5f60LL /* 461 */, - 0x9be853fb60afef77LL /* 462 */, 0xadc786a7f7443dbfLL /* 463 */, - 0x0904456173b29a82LL /* 464 */, 0x58bc7a66c232bd5eLL /* 465 */, - 0xf306558c673ac8b2LL /* 466 */, 0x41f639c6b6c9772aLL /* 467 */, - 0x216defe99fda35daLL /* 468 */, 0x11640cc71c7be615LL /* 469 */, - 0x93c43694565c5527LL /* 470 */, 0xea038e6246777839LL /* 471 */, - 0xf9abf3ce5a3e2469LL /* 472 */, 0x741e768d0fd312d2LL /* 473 */, - 0x0144b883ced652c6LL /* 474 */, 0xc20b5a5ba33f8552LL /* 475 */, - 0x1ae69633c3435a9dLL /* 476 */, 0x97a28ca4088cfdecLL /* 477 */, - 0x8824a43c1e96f420LL /* 478 */, 0x37612fa66eeea746LL /* 479 */, - 0x6b4cb165f9cf0e5aLL /* 480 */, 0x43aa1c06a0abfb4aLL /* 481 */, - 0x7f4dc26ff162796bLL /* 482 */, 0x6cbacc8e54ed9b0fLL /* 483 */, - 0xa6b7ffefd2bb253eLL /* 484 */, 0x2e25bc95b0a29d4fLL /* 485 */, - 0x86d6a58bdef1388cLL /* 486 */, 0xded74ac576b6f054LL /* 487 */, - 0x8030bdbc2b45805dLL /* 488 */, 0x3c81af70e94d9289LL /* 489 */, - 0x3eff6dda9e3100dbLL /* 490 */, 0xb38dc39fdfcc8847LL /* 491 */, - 0x123885528d17b87eLL /* 492 */, 0xf2da0ed240b1b642LL /* 493 */, - 0x44cefadcd54bf9a9LL /* 494 */, 0x1312200e433c7ee6LL /* 495 */, - 0x9ffcc84f3a78c748LL /* 496 */, 0xf0cd1f72248576bbLL /* 497 */, - 0xec6974053638cfe4LL /* 498 */, 0x2ba7b67c0cec4e4cLL /* 499 */, - 0xac2f4df3e5ce32edLL /* 500 */, 0xcb33d14326ea4c11LL /* 501 */, - 0xa4e9044cc77e58bcLL /* 502 */, 0x5f513293d934fcefLL /* 503 */, - 0x5dc9645506e55444LL /* 504 */, 0x50de418f317de40aLL /* 505 */, - 0x388cb31a69dde259LL /* 506 */, 0x2db4a83455820a86LL /* 507 */, - 0x9010a91e84711ae9LL /* 508 */, 0x4df7f0b7b1498371LL /* 509 */, - 0xd62a2eabc0977179LL /* 510 */, 0x22fac097aa8d5c0eLL /* 511 */ -}; -static u64 sbox3[256] = { - 0xf49fcc2ff1daf39bLL /* 512 */, 0x487fd5c66ff29281LL /* 513 */, - 0xe8a30667fcdca83fLL /* 514 */, 0x2c9b4be3d2fcce63LL /* 515 */, - 0xda3ff74b93fbbbc2LL /* 516 */, 0x2fa165d2fe70ba66LL /* 517 */, - 0xa103e279970e93d4LL /* 518 */, 0xbecdec77b0e45e71LL /* 519 */, - 0xcfb41e723985e497LL /* 520 */, 0xb70aaa025ef75017LL /* 521 */, - 0xd42309f03840b8e0LL /* 522 */, 0x8efc1ad035898579LL /* 523 */, - 0x96c6920be2b2abc5LL /* 524 */, 0x66af4163375a9172LL /* 525 */, - 0x2174abdcca7127fbLL /* 526 */, 0xb33ccea64a72ff41LL /* 527 */, - 0xf04a4933083066a5LL /* 528 */, 0x8d970acdd7289af5LL /* 529 */, - 0x8f96e8e031c8c25eLL /* 530 */, 0xf3fec02276875d47LL /* 531 */, - 0xec7bf310056190ddLL /* 532 */, 0xf5adb0aebb0f1491LL /* 533 */, - 0x9b50f8850fd58892LL /* 534 */, 0x4975488358b74de8LL /* 535 */, - 0xa3354ff691531c61LL /* 536 */, 0x0702bbe481d2c6eeLL /* 537 */, - 0x89fb24057deded98LL /* 538 */, 0xac3075138596e902LL /* 539 */, - 0x1d2d3580172772edLL /* 540 */, 0xeb738fc28e6bc30dLL /* 541 */, - 0x5854ef8f63044326LL /* 542 */, 0x9e5c52325add3bbeLL /* 543 */, - 0x90aa53cf325c4623LL /* 544 */, 0xc1d24d51349dd067LL /* 545 */, - 0x2051cfeea69ea624LL /* 546 */, 0x13220f0a862e7e4fLL /* 547 */, - 0xce39399404e04864LL /* 548 */, 0xd9c42ca47086fcb7LL /* 549 */, - 0x685ad2238a03e7ccLL /* 550 */, 0x066484b2ab2ff1dbLL /* 551 */, - 0xfe9d5d70efbf79ecLL /* 552 */, 0x5b13b9dd9c481854LL /* 553 */, - 0x15f0d475ed1509adLL /* 554 */, 0x0bebcd060ec79851LL /* 555 */, - 0xd58c6791183ab7f8LL /* 556 */, 0xd1187c5052f3eee4LL /* 557 */, - 0xc95d1192e54e82ffLL /* 558 */, 0x86eea14cb9ac6ca2LL /* 559 */, - 0x3485beb153677d5dLL /* 560 */, 0xdd191d781f8c492aLL /* 561 */, - 0xf60866baa784ebf9LL /* 562 */, 0x518f643ba2d08c74LL /* 563 */, - 0x8852e956e1087c22LL /* 564 */, 0xa768cb8dc410ae8dLL /* 565 */, - 0x38047726bfec8e1aLL /* 566 */, 0xa67738b4cd3b45aaLL /* 567 */, - 0xad16691cec0dde19LL /* 568 */, 0xc6d4319380462e07LL /* 569 */, - 0xc5a5876d0ba61938LL /* 570 */, 0x16b9fa1fa58fd840LL /* 571 */, - 0x188ab1173ca74f18LL /* 572 */, 0xabda2f98c99c021fLL /* 573 */, - 0x3e0580ab134ae816LL /* 574 */, 0x5f3b05b773645abbLL /* 575 */, - 0x2501a2be5575f2f6LL /* 576 */, 0x1b2f74004e7e8ba9LL /* 577 */, - 0x1cd7580371e8d953LL /* 578 */, 0x7f6ed89562764e30LL /* 579 */, - 0xb15926ff596f003dLL /* 580 */, 0x9f65293da8c5d6b9LL /* 581 */, - 0x6ecef04dd690f84cLL /* 582 */, 0x4782275fff33af88LL /* 583 */, - 0xe41433083f820801LL /* 584 */, 0xfd0dfe409a1af9b5LL /* 585 */, - 0x4325a3342cdb396bLL /* 586 */, 0x8ae77e62b301b252LL /* 587 */, - 0xc36f9e9f6655615aLL /* 588 */, 0x85455a2d92d32c09LL /* 589 */, - 0xf2c7dea949477485LL /* 590 */, 0x63cfb4c133a39ebaLL /* 591 */, - 0x83b040cc6ebc5462LL /* 592 */, 0x3b9454c8fdb326b0LL /* 593 */, - 0x56f56a9e87ffd78cLL /* 594 */, 0x2dc2940d99f42bc6LL /* 595 */, - 0x98f7df096b096e2dLL /* 596 */, 0x19a6e01e3ad852bfLL /* 597 */, - 0x42a99ccbdbd4b40bLL /* 598 */, 0xa59998af45e9c559LL /* 599 */, - 0x366295e807d93186LL /* 600 */, 0x6b48181bfaa1f773LL /* 601 */, - 0x1fec57e2157a0a1dLL /* 602 */, 0x4667446af6201ad5LL /* 603 */, - 0xe615ebcacfb0f075LL /* 604 */, 0xb8f31f4f68290778LL /* 605 */, - 0x22713ed6ce22d11eLL /* 606 */, 0x3057c1a72ec3c93bLL /* 607 */, - 0xcb46acc37c3f1f2fLL /* 608 */, 0xdbb893fd02aaf50eLL /* 609 */, - 0x331fd92e600b9fcfLL /* 610 */, 0xa498f96148ea3ad6LL /* 611 */, - 0xa8d8426e8b6a83eaLL /* 612 */, 0xa089b274b7735cdcLL /* 613 */, - 0x87f6b3731e524a11LL /* 614 */, 0x118808e5cbc96749LL /* 615 */, - 0x9906e4c7b19bd394LL /* 616 */, 0xafed7f7e9b24a20cLL /* 617 */, - 0x6509eadeeb3644a7LL /* 618 */, 0x6c1ef1d3e8ef0edeLL /* 619 */, - 0xb9c97d43e9798fb4LL /* 620 */, 0xa2f2d784740c28a3LL /* 621 */, - 0x7b8496476197566fLL /* 622 */, 0x7a5be3e6b65f069dLL /* 623 */, - 0xf96330ed78be6f10LL /* 624 */, 0xeee60de77a076a15LL /* 625 */, - 0x2b4bee4aa08b9bd0LL /* 626 */, 0x6a56a63ec7b8894eLL /* 627 */, - 0x02121359ba34fef4LL /* 628 */, 0x4cbf99f8283703fcLL /* 629 */, - 0x398071350caf30c8LL /* 630 */, 0xd0a77a89f017687aLL /* 631 */, - 0xf1c1a9eb9e423569LL /* 632 */, 0x8c7976282dee8199LL /* 633 */, - 0x5d1737a5dd1f7abdLL /* 634 */, 0x4f53433c09a9fa80LL /* 635 */, - 0xfa8b0c53df7ca1d9LL /* 636 */, 0x3fd9dcbc886ccb77LL /* 637 */, - 0xc040917ca91b4720LL /* 638 */, 0x7dd00142f9d1dcdfLL /* 639 */, - 0x8476fc1d4f387b58LL /* 640 */, 0x23f8e7c5f3316503LL /* 641 */, - 0x032a2244e7e37339LL /* 642 */, 0x5c87a5d750f5a74bLL /* 643 */, - 0x082b4cc43698992eLL /* 644 */, 0xdf917becb858f63cLL /* 645 */, - 0x3270b8fc5bf86ddaLL /* 646 */, 0x10ae72bb29b5dd76LL /* 647 */, - 0x576ac94e7700362bLL /* 648 */, 0x1ad112dac61efb8fLL /* 649 */, - 0x691bc30ec5faa427LL /* 650 */, 0xff246311cc327143LL /* 651 */, - 0x3142368e30e53206LL /* 652 */, 0x71380e31e02ca396LL /* 653 */, - 0x958d5c960aad76f1LL /* 654 */, 0xf8d6f430c16da536LL /* 655 */, - 0xc8ffd13f1be7e1d2LL /* 656 */, 0x7578ae66004ddbe1LL /* 657 */, - 0x05833f01067be646LL /* 658 */, 0xbb34b5ad3bfe586dLL /* 659 */, - 0x095f34c9a12b97f0LL /* 660 */, 0x247ab64525d60ca8LL /* 661 */, - 0xdcdbc6f3017477d1LL /* 662 */, 0x4a2e14d4decad24dLL /* 663 */, - 0xbdb5e6d9be0a1eebLL /* 664 */, 0x2a7e70f7794301abLL /* 665 */, - 0xdef42d8a270540fdLL /* 666 */, 0x01078ec0a34c22c1LL /* 667 */, - 0xe5de511af4c16387LL /* 668 */, 0x7ebb3a52bd9a330aLL /* 669 */, - 0x77697857aa7d6435LL /* 670 */, 0x004e831603ae4c32LL /* 671 */, - 0xe7a21020ad78e312LL /* 672 */, 0x9d41a70c6ab420f2LL /* 673 */, - 0x28e06c18ea1141e6LL /* 674 */, 0xd2b28cbd984f6b28LL /* 675 */, - 0x26b75f6c446e9d83LL /* 676 */, 0xba47568c4d418d7fLL /* 677 */, - 0xd80badbfe6183d8eLL /* 678 */, 0x0e206d7f5f166044LL /* 679 */, - 0xe258a43911cbca3eLL /* 680 */, 0x723a1746b21dc0bcLL /* 681 */, - 0xc7caa854f5d7cdd3LL /* 682 */, 0x7cac32883d261d9cLL /* 683 */, - 0x7690c26423ba942cLL /* 684 */, 0x17e55524478042b8LL /* 685 */, - 0xe0be477656a2389fLL /* 686 */, 0x4d289b5e67ab2da0LL /* 687 */, - 0x44862b9c8fbbfd31LL /* 688 */, 0xb47cc8049d141365LL /* 689 */, - 0x822c1b362b91c793LL /* 690 */, 0x4eb14655fb13dfd8LL /* 691 */, - 0x1ecbba0714e2a97bLL /* 692 */, 0x6143459d5cde5f14LL /* 693 */, - 0x53a8fbf1d5f0ac89LL /* 694 */, 0x97ea04d81c5e5b00LL /* 695 */, - 0x622181a8d4fdb3f3LL /* 696 */, 0xe9bcd341572a1208LL /* 697 */, - 0x1411258643cce58aLL /* 698 */, 0x9144c5fea4c6e0a4LL /* 699 */, - 0x0d33d06565cf620fLL /* 700 */, 0x54a48d489f219ca1LL /* 701 */, - 0xc43e5eac6d63c821LL /* 702 */, 0xa9728b3a72770dafLL /* 703 */, - 0xd7934e7b20df87efLL /* 704 */, 0xe35503b61a3e86e5LL /* 705 */, - 0xcae321fbc819d504LL /* 706 */, 0x129a50b3ac60bfa6LL /* 707 */, - 0xcd5e68ea7e9fb6c3LL /* 708 */, 0xb01c90199483b1c7LL /* 709 */, - 0x3de93cd5c295376cLL /* 710 */, 0xaed52edf2ab9ad13LL /* 711 */, - 0x2e60f512c0a07884LL /* 712 */, 0xbc3d86a3e36210c9LL /* 713 */, - 0x35269d9b163951ceLL /* 714 */, 0x0c7d6e2ad0cdb5faLL /* 715 */, - 0x59e86297d87f5733LL /* 716 */, 0x298ef221898db0e7LL /* 717 */, - 0x55000029d1a5aa7eLL /* 718 */, 0x8bc08ae1b5061b45LL /* 719 */, - 0xc2c31c2b6c92703aLL /* 720 */, 0x94cc596baf25ef42LL /* 721 */, - 0x0a1d73db22540456LL /* 722 */, 0x04b6a0f9d9c4179aLL /* 723 */, - 0xeffdafa2ae3d3c60LL /* 724 */, 0xf7c8075bb49496c4LL /* 725 */, - 0x9cc5c7141d1cd4e3LL /* 726 */, 0x78bd1638218e5534LL /* 727 */, - 0xb2f11568f850246aLL /* 728 */, 0xedfabcfa9502bc29LL /* 729 */, - 0x796ce5f2da23051bLL /* 730 */, 0xaae128b0dc93537cLL /* 731 */, - 0x3a493da0ee4b29aeLL /* 732 */, 0xb5df6b2c416895d7LL /* 733 */, - 0xfcabbd25122d7f37LL /* 734 */, 0x70810b58105dc4b1LL /* 735 */, - 0xe10fdd37f7882a90LL /* 736 */, 0x524dcab5518a3f5cLL /* 737 */, - 0x3c9e85878451255bLL /* 738 */, 0x4029828119bd34e2LL /* 739 */, - 0x74a05b6f5d3ceccbLL /* 740 */, 0xb610021542e13ecaLL /* 741 */, - 0x0ff979d12f59e2acLL /* 742 */, 0x6037da27e4f9cc50LL /* 743 */, - 0x5e92975a0df1847dLL /* 744 */, 0xd66de190d3e623feLL /* 745 */, - 0x5032d6b87b568048LL /* 746 */, 0x9a36b7ce8235216eLL /* 747 */, - 0x80272a7a24f64b4aLL /* 748 */, 0x93efed8b8c6916f7LL /* 749 */, - 0x37ddbff44cce1555LL /* 750 */, 0x4b95db5d4b99bd25LL /* 751 */, - 0x92d3fda169812fc0LL /* 752 */, 0xfb1a4a9a90660bb6LL /* 753 */, - 0x730c196946a4b9b2LL /* 754 */, 0x81e289aa7f49da68LL /* 755 */, - 0x64669a0f83b1a05fLL /* 756 */, 0x27b3ff7d9644f48bLL /* 757 */, - 0xcc6b615c8db675b3LL /* 758 */, 0x674f20b9bcebbe95LL /* 759 */, - 0x6f31238275655982LL /* 760 */, 0x5ae488713e45cf05LL /* 761 */, - 0xbf619f9954c21157LL /* 762 */, 0xeabac46040a8eae9LL /* 763 */, - 0x454c6fe9f2c0c1cdLL /* 764 */, 0x419cf6496412691cLL /* 765 */, - 0xd3dc3bef265b0f70LL /* 766 */, 0x6d0e60f5c3578a9eLL /* 767 */ -}; -static u64 sbox4[256] = { - 0x5b0e608526323c55LL /* 768 */, 0x1a46c1a9fa1b59f5LL /* 769 */, - 0xa9e245a17c4c8ffaLL /* 770 */, 0x65ca5159db2955d7LL /* 771 */, - 0x05db0a76ce35afc2LL /* 772 */, 0x81eac77ea9113d45LL /* 773 */, - 0x528ef88ab6ac0a0dLL /* 774 */, 0xa09ea253597be3ffLL /* 775 */, - 0x430ddfb3ac48cd56LL /* 776 */, 0xc4b3a67af45ce46fLL /* 777 */, - 0x4ececfd8fbe2d05eLL /* 778 */, 0x3ef56f10b39935f0LL /* 779 */, - 0x0b22d6829cd619c6LL /* 780 */, 0x17fd460a74df2069LL /* 781 */, - 0x6cf8cc8e8510ed40LL /* 782 */, 0xd6c824bf3a6ecaa7LL /* 783 */, - 0x61243d581a817049LL /* 784 */, 0x048bacb6bbc163a2LL /* 785 */, - 0xd9a38ac27d44cc32LL /* 786 */, 0x7fddff5baaf410abLL /* 787 */, - 0xad6d495aa804824bLL /* 788 */, 0xe1a6a74f2d8c9f94LL /* 789 */, - 0xd4f7851235dee8e3LL /* 790 */, 0xfd4b7f886540d893LL /* 791 */, - 0x247c20042aa4bfdaLL /* 792 */, 0x096ea1c517d1327cLL /* 793 */, - 0xd56966b4361a6685LL /* 794 */, 0x277da5c31221057dLL /* 795 */, - 0x94d59893a43acff7LL /* 796 */, 0x64f0c51ccdc02281LL /* 797 */, - 0x3d33bcc4ff6189dbLL /* 798 */, 0xe005cb184ce66af1LL /* 799 */, - 0xff5ccd1d1db99beaLL /* 800 */, 0xb0b854a7fe42980fLL /* 801 */, - 0x7bd46a6a718d4b9fLL /* 802 */, 0xd10fa8cc22a5fd8cLL /* 803 */, - 0xd31484952be4bd31LL /* 804 */, 0xc7fa975fcb243847LL /* 805 */, - 0x4886ed1e5846c407LL /* 806 */, 0x28cddb791eb70b04LL /* 807 */, - 0xc2b00be2f573417fLL /* 808 */, 0x5c9590452180f877LL /* 809 */, - 0x7a6bddfff370eb00LL /* 810 */, 0xce509e38d6d9d6a4LL /* 811 */, - 0xebeb0f00647fa702LL /* 812 */, 0x1dcc06cf76606f06LL /* 813 */, - 0xe4d9f28ba286ff0aLL /* 814 */, 0xd85a305dc918c262LL /* 815 */, - 0x475b1d8732225f54LL /* 816 */, 0x2d4fb51668ccb5feLL /* 817 */, - 0xa679b9d9d72bba20LL /* 818 */, 0x53841c0d912d43a5LL /* 819 */, - 0x3b7eaa48bf12a4e8LL /* 820 */, 0x781e0e47f22f1ddfLL /* 821 */, - 0xeff20ce60ab50973LL /* 822 */, 0x20d261d19dffb742LL /* 823 */, - 0x16a12b03062a2e39LL /* 824 */, 0x1960eb2239650495LL /* 825 */, - 0x251c16fed50eb8b8LL /* 826 */, 0x9ac0c330f826016eLL /* 827 */, - 0xed152665953e7671LL /* 828 */, 0x02d63194a6369570LL /* 829 */, - 0x5074f08394b1c987LL /* 830 */, 0x70ba598c90b25ce1LL /* 831 */, - 0x794a15810b9742f6LL /* 832 */, 0x0d5925e9fcaf8c6cLL /* 833 */, - 0x3067716cd868744eLL /* 834 */, 0x910ab077e8d7731bLL /* 835 */, - 0x6a61bbdb5ac42f61LL /* 836 */, 0x93513efbf0851567LL /* 837 */, - 0xf494724b9e83e9d5LL /* 838 */, 0xe887e1985c09648dLL /* 839 */, - 0x34b1d3c675370cfdLL /* 840 */, 0xdc35e433bc0d255dLL /* 841 */, - 0xd0aab84234131be0LL /* 842 */, 0x08042a50b48b7eafLL /* 843 */, - 0x9997c4ee44a3ab35LL /* 844 */, 0x829a7b49201799d0LL /* 845 */, - 0x263b8307b7c54441LL /* 846 */, 0x752f95f4fd6a6ca6LL /* 847 */, - 0x927217402c08c6e5LL /* 848 */, 0x2a8ab754a795d9eeLL /* 849 */, - 0xa442f7552f72943dLL /* 850 */, 0x2c31334e19781208LL /* 851 */, - 0x4fa98d7ceaee6291LL /* 852 */, 0x55c3862f665db309LL /* 853 */, - 0xbd0610175d53b1f3LL /* 854 */, 0x46fe6cb840413f27LL /* 855 */, - 0x3fe03792df0cfa59LL /* 856 */, 0xcfe700372eb85e8fLL /* 857 */, - 0xa7be29e7adbce118LL /* 858 */, 0xe544ee5cde8431ddLL /* 859 */, - 0x8a781b1b41f1873eLL /* 860 */, 0xa5c94c78a0d2f0e7LL /* 861 */, - 0x39412e2877b60728LL /* 862 */, 0xa1265ef3afc9a62cLL /* 863 */, - 0xbcc2770c6a2506c5LL /* 864 */, 0x3ab66dd5dce1ce12LL /* 865 */, - 0xe65499d04a675b37LL /* 866 */, 0x7d8f523481bfd216LL /* 867 */, - 0x0f6f64fcec15f389LL /* 868 */, 0x74efbe618b5b13c8LL /* 869 */, - 0xacdc82b714273e1dLL /* 870 */, 0xdd40bfe003199d17LL /* 871 */, - 0x37e99257e7e061f8LL /* 872 */, 0xfa52626904775aaaLL /* 873 */, - 0x8bbbf63a463d56f9LL /* 874 */, 0xf0013f1543a26e64LL /* 875 */, - 0xa8307e9f879ec898LL /* 876 */, 0xcc4c27a4150177ccLL /* 877 */, - 0x1b432f2cca1d3348LL /* 878 */, 0xde1d1f8f9f6fa013LL /* 879 */, - 0x606602a047a7ddd6LL /* 880 */, 0xd237ab64cc1cb2c7LL /* 881 */, - 0x9b938e7225fcd1d3LL /* 882 */, 0xec4e03708e0ff476LL /* 883 */, - 0xfeb2fbda3d03c12dLL /* 884 */, 0xae0bced2ee43889aLL /* 885 */, - 0x22cb8923ebfb4f43LL /* 886 */, 0x69360d013cf7396dLL /* 887 */, - 0x855e3602d2d4e022LL /* 888 */, 0x073805bad01f784cLL /* 889 */, - 0x33e17a133852f546LL /* 890 */, 0xdf4874058ac7b638LL /* 891 */, - 0xba92b29c678aa14aLL /* 892 */, 0x0ce89fc76cfaadcdLL /* 893 */, - 0x5f9d4e0908339e34LL /* 894 */, 0xf1afe9291f5923b9LL /* 895 */, - 0x6e3480f60f4a265fLL /* 896 */, 0xeebf3a2ab29b841cLL /* 897 */, - 0xe21938a88f91b4adLL /* 898 */, 0x57dfeff845c6d3c3LL /* 899 */, - 0x2f006b0bf62caaf2LL /* 900 */, 0x62f479ef6f75ee78LL /* 901 */, - 0x11a55ad41c8916a9LL /* 902 */, 0xf229d29084fed453LL /* 903 */, - 0x42f1c27b16b000e6LL /* 904 */, 0x2b1f76749823c074LL /* 905 */, - 0x4b76eca3c2745360LL /* 906 */, 0x8c98f463b91691bdLL /* 907 */, - 0x14bcc93cf1ade66aLL /* 908 */, 0x8885213e6d458397LL /* 909 */, - 0x8e177df0274d4711LL /* 910 */, 0xb49b73b5503f2951LL /* 911 */, - 0x10168168c3f96b6bLL /* 912 */, 0x0e3d963b63cab0aeLL /* 913 */, - 0x8dfc4b5655a1db14LL /* 914 */, 0xf789f1356e14de5cLL /* 915 */, - 0x683e68af4e51dac1LL /* 916 */, 0xc9a84f9d8d4b0fd9LL /* 917 */, - 0x3691e03f52a0f9d1LL /* 918 */, 0x5ed86e46e1878e80LL /* 919 */, - 0x3c711a0e99d07150LL /* 920 */, 0x5a0865b20c4e9310LL /* 921 */, - 0x56fbfc1fe4f0682eLL /* 922 */, 0xea8d5de3105edf9bLL /* 923 */, - 0x71abfdb12379187aLL /* 924 */, 0x2eb99de1bee77b9cLL /* 925 */, - 0x21ecc0ea33cf4523LL /* 926 */, 0x59a4d7521805c7a1LL /* 927 */, - 0x3896f5eb56ae7c72LL /* 928 */, 0xaa638f3db18f75dcLL /* 929 */, - 0x9f39358dabe9808eLL /* 930 */, 0xb7defa91c00b72acLL /* 931 */, - 0x6b5541fd62492d92LL /* 932 */, 0x6dc6dee8f92e4d5bLL /* 933 */, - 0x353f57abc4beea7eLL /* 934 */, 0x735769d6da5690ceLL /* 935 */, - 0x0a234aa642391484LL /* 936 */, 0xf6f9508028f80d9dLL /* 937 */, - 0xb8e319a27ab3f215LL /* 938 */, 0x31ad9c1151341a4dLL /* 939 */, - 0x773c22a57bef5805LL /* 940 */, 0x45c7561a07968633LL /* 941 */, - 0xf913da9e249dbe36LL /* 942 */, 0xda652d9b78a64c68LL /* 943 */, - 0x4c27a97f3bc334efLL /* 944 */, 0x76621220e66b17f4LL /* 945 */, - 0x967743899acd7d0bLL /* 946 */, 0xf3ee5bcae0ed6782LL /* 947 */, - 0x409f753600c879fcLL /* 948 */, 0x06d09a39b5926db6LL /* 949 */, - 0x6f83aeb0317ac588LL /* 950 */, 0x01e6ca4a86381f21LL /* 951 */, - 0x66ff3462d19f3025LL /* 952 */, 0x72207c24ddfd3bfbLL /* 953 */, - 0x4af6b6d3e2ece2ebLL /* 954 */, 0x9c994dbec7ea08deLL /* 955 */, - 0x49ace597b09a8bc4LL /* 956 */, 0xb38c4766cf0797baLL /* 957 */, - 0x131b9373c57c2a75LL /* 958 */, 0xb1822cce61931e58LL /* 959 */, - 0x9d7555b909ba1c0cLL /* 960 */, 0x127fafdd937d11d2LL /* 961 */, - 0x29da3badc66d92e4LL /* 962 */, 0xa2c1d57154c2ecbcLL /* 963 */, - 0x58c5134d82f6fe24LL /* 964 */, 0x1c3ae3515b62274fLL /* 965 */, - 0xe907c82e01cb8126LL /* 966 */, 0xf8ed091913e37fcbLL /* 967 */, - 0x3249d8f9c80046c9LL /* 968 */, 0x80cf9bede388fb63LL /* 969 */, - 0x1881539a116cf19eLL /* 970 */, 0x5103f3f76bd52457LL /* 971 */, - 0x15b7e6f5ae47f7a8LL /* 972 */, 0xdbd7c6ded47e9ccfLL /* 973 */, - 0x44e55c410228bb1aLL /* 974 */, 0xb647d4255edb4e99LL /* 975 */, - 0x5d11882bb8aafc30LL /* 976 */, 0xf5098bbb29d3212aLL /* 977 */, - 0x8fb5ea14e90296b3LL /* 978 */, 0x677b942157dd025aLL /* 979 */, - 0xfb58e7c0a390acb5LL /* 980 */, 0x89d3674c83bd4a01LL /* 981 */, - 0x9e2da4df4bf3b93bLL /* 982 */, 0xfcc41e328cab4829LL /* 983 */, - 0x03f38c96ba582c52LL /* 984 */, 0xcad1bdbd7fd85db2LL /* 985 */, - 0xbbb442c16082ae83LL /* 986 */, 0xb95fe86ba5da9ab0LL /* 987 */, - 0xb22e04673771a93fLL /* 988 */, 0x845358c9493152d8LL /* 989 */, - 0xbe2a488697b4541eLL /* 990 */, 0x95a2dc2dd38e6966LL /* 991 */, - 0xc02c11ac923c852bLL /* 992 */, 0x2388b1990df2a87bLL /* 993 */, - 0x7c8008fa1b4f37beLL /* 994 */, 0x1f70d0c84d54e503LL /* 995 */, - 0x5490adec7ece57d4LL /* 996 */, 0x002b3c27d9063a3aLL /* 997 */, - 0x7eaea3848030a2bfLL /* 998 */, 0xc602326ded2003c0LL /* 999 */, - 0x83a7287d69a94086LL /* 1000 */, 0xc57a5fcb30f57a8aLL /* 1001 */, - 0xb56844e479ebe779LL /* 1002 */, 0xa373b40f05dcbce9LL /* 1003 */, - 0xd71a786e88570ee2LL /* 1004 */, 0x879cbacdbde8f6a0LL /* 1005 */, - 0x976ad1bcc164a32fLL /* 1006 */, 0xab21e25e9666d78bLL /* 1007 */, - 0x901063aae5e5c33cLL /* 1008 */, 0x9818b34448698d90LL /* 1009 */, - 0xe36487ae3e1e8abbLL /* 1010 */, 0xafbdf931893bdcb4LL /* 1011 */, - 0x6345a0dc5fbbd519LL /* 1012 */, 0x8628fe269b9465caLL /* 1013 */, - 0x1e5d01603f9c51ecLL /* 1014 */, 0x4de44006a15049b7LL /* 1015 */, - 0xbf6c70e5f776cbb1LL /* 1016 */, 0x411218f2ef552bedLL /* 1017 */, - 0xcb0c0708705a36a3LL /* 1018 */, 0xe74d14754f986044LL /* 1019 */, - 0xcd56d9430ea8280eLL /* 1020 */, 0xc12591d7535f5065LL /* 1021 */, - 0xc83223f1720aef96LL /* 1022 */, 0xc3a0396f7363a51fLL /* 1023 */ -}; - - -static void -print_abc( const char *text, u64 a, u64 b, u64 c ) -{ -/*printf("%s: %08X%08X %08X%08X %08X%08X\n", - text, - (u32)(a>>32), - (u32)(a), - (u32)(b>>32), - (u32)(b), - (u32)(c>>32), - (u32)(c) );*/ -} - -static void -print_data( const char *text, u64 a, u64 b, u64 c, - u64 d, u64 e, u64 f, - u64 g, u64 h ) -{ -/*printf("%s: %08X%08X %08X%08X %08X%08X %08X%08X\n" - "%s %08X%08X %08X%08X %08X%08X %08X%08X\n", - text, - (u32)(a>>32), - (u32)(a), - (u32)(b>>32), - (u32)(b), - (u32)(c>>32), - (u32)(c), - (u32)(d>>32), - (u32)(d), - text, - (u32)(e>>32), - (u32)(e), - (u32)(f>>32), - (u32)(f), - (u32)(g>>32), - (u32)(g), - (u32)(h>>32), - (u32)(h) );*/ -} - - -static void -burn_stack (int bytes) -{ - char buf[256]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - - -static void -tiger_init( TIGER_CONTEXT *hd ) -{ - hd->a = 0x0123456789abcdefLL; - hd->b = 0xfedcba9876543210LL; - hd->c = 0xf096a5b4c3b2e187LL; - hd->nblocks = 0; - hd->count = 0; -} - -static void -round( u64 *ra, u64 *rb, u64 *rc, u64 x, int mul ) -{ - u64 a = *ra; - u64 b = *rb; - u64 c = *rc; - - c ^= x; - a -= sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ] - ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ]; - b += sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ] - ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ]; - b *= mul; - - *ra = a; - *rb = b; - *rc = c; -} - - -static void -pass( u64 *ra, u64 *rb, u64 *rc, u64 *x, int mul ) -{ - u64 a = *ra; - u64 b = *rb; - u64 c = *rc; - - round( &a, &b, &c, x[0], mul ); - round( &b, &c, &a, x[1], mul ); - round( &c, &a, &b, x[2], mul ); - round( &a, &b, &c, x[3], mul ); - round( &b, &c, &a, x[4], mul ); - round( &c, &a, &b, x[5], mul ); - round( &a, &b, &c, x[6], mul ); - round( &b, &c, &a, x[7], mul ); - - *ra = a; - *rb = b; - *rc = c; -} - - -static void -key_schedule( u64 *x ) -{ - x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; - x[1] ^= x[0]; - x[2] += x[1]; - x[3] -= x[2] ^ ((~x[1]) << 19 ); - x[4] ^= x[3]; - x[5] += x[4]; - x[6] -= x[5] ^ ((~x[4]) >> 23 ); - x[7] ^= x[6]; - x[0] += x[7]; - x[1] -= x[0] ^ ((~x[7]) << 19 ); - x[2] ^= x[1]; - x[3] += x[2]; - x[4] -= x[3] ^ ((~x[2]) >> 23 ); - x[5] ^= x[4]; - x[6] += x[5]; - x[7] -= x[6] ^ 0x0123456789abcdefLL; -} - - -/**************** - * Transform the message DATA which consists of 512 bytes (8 words) - */ -static void -transform( TIGER_CONTEXT *hd, byte *data ) -{ - u64 a,b,c,aa,bb,cc; - u64 x[8]; - #ifdef BIG_ENDIAN_HOST - #define MKWORD(d,n) \ - ( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \ - | ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \ - | ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \ - | ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) ) - x[0] = MKWORD(data, 0); - x[1] = MKWORD(data, 1); - x[2] = MKWORD(data, 2); - x[3] = MKWORD(data, 3); - x[4] = MKWORD(data, 4); - x[5] = MKWORD(data, 5); - x[6] = MKWORD(data, 6); - x[7] = MKWORD(data, 7); - #undef MKWORD - #else - memcpy( &x[0], data, 64 ); - #endif - - /* save */ - a = aa = hd->a; - b = bb = hd->b; - c = cc = hd->c; - - print_data(" key0", x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] ); - print_abc(" init", a, b, c ); - pass( &a, &b, &c, x, 5); - print_abc("pass1", a, b, c ); - key_schedule( x ); - pass( &c, &a, &b, x, 7); - print_abc("pass2", a, b, c ); - key_schedule( x ); - pass( &b, &c, &a, x, 9); - print_abc("pass3", a, b, c ); - - - /* feedforward */ - a ^= aa; - b -= bb; - c += cc; - /* store */ - hd->a = a; - hd->b = b; - hd->c = c; -} - - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -static void -tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen) -{ - if( hd->count == 64 ) { /* flush the buffer */ - transform( hd, hd->buf ); - burn_stack (21*8+11*sizeof(void*)); - hd->count = 0; - hd->nblocks++; - } - if( !inbuf ) - return; - if( hd->count ) { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; - tiger_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - - while( inlen >= 64 ) { - transform( hd, inbuf ); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - burn_stack (21*8+11*sizeof(void*)); - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; -} - - - -/* The routine terminates the computation - */ - -static void -tiger_final( TIGER_CONTEXT *hd ) -{ - u32 t, msb, lsb; - byte *p; - - tiger_write(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if( (lsb += hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if( hd->count < 56 ) { /* enough room */ - hd->buf[hd->count++] = 0x01; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x01; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] = 0; - tiger_write(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = lsb ; - hd->buf[57] = lsb >> 8; - hd->buf[58] = lsb >> 16; - hd->buf[59] = lsb >> 24; - hd->buf[60] = msb ; - hd->buf[61] = msb >> 8; - hd->buf[62] = msb >> 16; - hd->buf[63] = msb >> 24; - transform( hd, hd->buf ); - burn_stack (21*8+11*sizeof(void*)); - - p = hd->buf; - #ifdef BIG_ENDIAN_HOST - #define X(a) do { *(u64*)p = hd-> a ; p += 8; } while(0) - #else /* little endian */ - #define X(a) do { *p++ = hd-> a >> 56; *p++ = hd-> a >> 48; \ - *p++ = hd-> a >> 40; *p++ = hd-> a >> 32; \ - *p++ = hd-> a >> 24; *p++ = hd-> a >> 16; \ - *p++ = hd-> a >> 8; *p++ = hd-> a; } while(0) - #endif - X(a); - X(b); - X(c); - #undef X -} - -static byte * -tiger_read( TIGER_CONTEXT *hd ) -{ - return hd->buf; -} - -#endif /*HAVE_U64_TYPEDEF*/ - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -const char * -tiger_get_info( int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ) -{ -#ifdef HAVE_U64_TYPEDEF - -#ifdef USE_OLD_TIGER - /* This is the old fake OID */ - static byte asn[18] = - { 0x30, 0x28, 0x30, 0x0c, 0x04, 0x08, 0x54, 0x49, 0x47, - 0x45, 0x52, 0x31, 0x39, 0x32, 0x05, 0x00, 0x04, 0x18 }; -#else /* !USE_OLD_TIGER */ - /* This is the new correct OID */ - static byte asn[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */ - { 0x30, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, - 0x01, 0x04, 0x01, 0xda, 0x47, 0x0c, 0x02, - 0x05, 0x00, 0x04, 0x18 }; -#endif - - if( algo != 6 ) - return NULL; - - *contextsize = sizeof(TIGER_CONTEXT); - *r_asnoid = asn; - *r_asnlen = DIM(asn); - *r_mdlen = 24; - *(void (**)(TIGER_CONTEXT *))r_init = tiger_init; - *(void (**)(TIGER_CONTEXT *, byte*, size_t))r_write = tiger_write; - *(void (**)(TIGER_CONTEXT *))r_final = tiger_final; - *(byte *(**)(TIGER_CONTEXT *))r_read = tiger_read; - - return "TIGER192"; -#else /*!HAVE_U64_TYPEDEF*/ - return NULL; /* Alorithm not available. */ -#endif -} diff --git a/cipher/twofish.c b/cipher/twofish.c deleted file mode 100644 index 5ed44872c..000000000 --- a/cipher/twofish.c +++ /dev/null @@ -1,1135 +0,0 @@ -/* Twofish for GPG - * By Matthew Skala , July 26, 1998 - * 256-bit key length added March 20, 1999 - * Some modifications to reduce the text size by Werner Koch, April, 1998 - * - * The original author has disclaimed all copyright interest in this - * code and thus putting it in the public domain. - * - * This code is a "clean room" implementation, written from the paper - * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, - * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available - * through http://www.counterpane.com/twofish.html - * - * For background information on multiplication in finite fields, used for - * the matrix operations in the key schedule, see the book _Contemporary - * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the - * Third Edition. - * - * Only the 128- and 256-bit key sizes are supported. This code is intended - * for GNU C on a 32-bit system, but it should work almost anywhere. Loops - * are unrolled, precomputation tables are used, etc., for maximum speed at - * some cost in memory consumption. */ - -#include -#include -#include -#include /* for memcmp() */ - -#include "types.h" /* for byte and u32 typedefs */ -#include "util.h" -#include "errors.h" -#include "algorithms.h" - -/* Prototype for the self-test function. */ -static const char *selftest(void); - -/* Structure for an expanded Twofish key. s contains the key-dependent - * S-boxes composed with the MDS matrix; w contains the eight "whitening" - * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note - * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ -typedef struct { - u32 s[4][256], w[8], k[32]; -} TWOFISH_context; - -/* These two tables are the q0 and q1 permutations, exactly as described in - * the Twofish paper. */ - -static const byte q0[256] = { - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, - 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, - 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, - 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, - 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, - 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, - 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, - 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, - 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, - 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, - 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, - 0x4A, 0x5E, 0xC1, 0xE0 -}; - -static const byte q1[256] = { - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, - 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, - 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, - 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, - 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, - 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, - 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, - 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, - 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, - 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, - 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, - 0x55, 0x09, 0xBE, 0x91 -}; - -/* These MDS tables are actually tables of MDS composed with q0 and q1, - * because it is only ever used that way and we can save some time by - * precomputing. Of course the main saving comes from precomputing the - * GF(2^8) multiplication involved in the MDS matrix multiply; by looking - * things up in these tables we reduce the matrix multiply to four lookups - * and three XORs. Semi-formally, the definition of these tables is: - * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T - * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T - * where ^T means "transpose", the matrix multiply is performed in GF(2^8) - * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described - * by Schneier et al, and I'm casually glossing over the byte/word - * conversion issues. */ - -static const u32 mds[4][256] = { - {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, - 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, - 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, - 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, - 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, - 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, - 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, - 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, - 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, - 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, - 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, - 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, - 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, - 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, - 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, - 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, - 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, - 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, - 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, - 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, - 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, - 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, - 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, - 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, - 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, - 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, - 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, - 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, - 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, - 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, - 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, - 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, - 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, - 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, - 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, - 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, - 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, - 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, - 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, - 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, - 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, - 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, - 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, - - {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, - 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, - 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, - 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, - 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, - 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, - 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, - 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, - 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, - 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, - 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, - 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, - 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, - 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, - 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, - 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, - 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, - 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, - 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, - 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, - 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, - 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, - 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, - 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, - 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, - 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, - 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, - 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, - 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, - 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, - 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, - 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, - 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, - 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, - 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, - 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, - 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, - 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, - 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, - 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, - 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, - 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, - 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, - - {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, - 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, - 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, - 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, - 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, - 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, - 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, - 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, - 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, - 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, - 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, - 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, - 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, - 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, - 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, - 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, - 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, - 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, - 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, - 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, - 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, - 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, - 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, - 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, - 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, - 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, - 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, - 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, - 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, - 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, - 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, - 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, - 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, - 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, - 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, - 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, - 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, - 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, - 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, - 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, - 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, - 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, - 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, - - {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, - 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, - 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, - 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, - 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, - 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, - 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, - 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, - 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, - 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, - 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, - 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, - 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, - 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, - 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, - 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, - 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, - 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, - 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, - 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, - 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, - 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, - 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, - 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, - 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, - 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, - 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, - 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, - 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, - 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, - 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, - 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, - 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, - 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, - 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, - 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, - 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, - 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, - 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, - 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, - 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, - 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, - 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} -}; - -/* The exp_to_poly and poly_to_exp tables are used to perform efficient - * operations in GF(2^8) represented as GF(2)[x]/w(x) where - * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the - * definition of the RS matrix in the key schedule. Elements of that field - * are polynomials of degree not greater than 7 and all coefficients 0 or 1, - * which can be represented naturally by bytes (just substitute x=2). In that - * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) - * multiplication is inefficient without hardware support. To multiply - * faster, I make use of the fact x is a generator for the nonzero elements, - * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for - * some n in 0..254. Note that that caret is exponentiation in GF(2^8), - * *not* polynomial notation. So if I want to compute pq where p and q are - * in GF(2^8), I can just say: - * 1. if p=0 or q=0 then pq=0 - * 2. otherwise, find m and n such that p=x^m and q=x^n - * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq - * The translations in steps 2 and 3 are looked up in the tables - * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this - * in action, look at the CALC_S macro. As additional wrinkles, note that - * one of my operands is always a constant, so the poly_to_exp lookup on it - * is done in advance; I included the original values in the comments so - * readers can have some chance of recognizing that this *is* the RS matrix - * from the Twofish paper. I've only included the table entries I actually - * need; I never do a lookup on a variable input of zero and the biggest - * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll - * never sum to more than 491. I'm repeating part of the exp_to_poly table - * so that I don't have to do mod-255 reduction in the exponent arithmetic. - * Since I know my constant operands are never zero, I only have to worry - * about zero values in the variable operand, and I do it with a simple - * conditional branch. I know conditionals are expensive, but I couldn't - * see a non-horrible way of avoiding them, and I did manage to group the - * statements so that each if covers four group multiplications. */ - -static const byte poly_to_exp[255] = { - 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, - 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, - 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, - 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, - 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, - 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, - 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, - 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, - 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, - 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, - 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, - 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, - 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, - 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, - 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, - 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, - 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, - 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, - 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, - 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, - 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, - 0x85, 0xC8, 0xA1 -}; - -static const byte exp_to_poly[492] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, - 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, - 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, - 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, - 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, - 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, - 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, - 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, - 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, - 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, - 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, - 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, - 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, - 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, - 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, - 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, - 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, - 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, - 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, - 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, - 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, - 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, - 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, - 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, - 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, - 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, - 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, - 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, - 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, - 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, - 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, - 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, - 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, - 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, - 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, - 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, - 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, - 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, - 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, - 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, - 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB -}; - - -/* The table constants are indices of - * S-box entries, preprocessed through q0 and q1. */ -static byte calc_sb_tbl[512] = { - 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, - 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, - 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, - 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, - 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, - 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, - 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, - 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, - 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, - 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, - 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, - 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, - 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, - 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, - 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, - 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, - 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, - 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, - 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, - 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, - 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, - 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, - 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, - 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, - 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, - 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, - 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, - 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, - 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, - 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, - 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, - 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, - 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, - 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, - 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, - 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, - 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, - 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, - 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, - 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, - 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, - 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, - 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, - 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, - 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, - 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, - 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, - 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, - 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, - 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, - 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, - 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, - 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, - 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, - 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, - 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, - 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, - 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, - 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, - 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, - 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, - 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, - 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, - 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 -}; -/* Macro to perform one column of the RS matrix multiplication. The - * parameters a, b, c, and d are the four bytes of output; i is the index - * of the key bytes, and w, x, y, and z, are the column of constants from - * the RS matrix, preprocessed through the poly_to_exp table. */ - -#define CALC_S(a, b, c, d, i, w, x, y, z) \ - if (key[i]) { \ - tmp = poly_to_exp[key[i] - 1]; \ - (a) ^= exp_to_poly[tmp + (w)]; \ - (b) ^= exp_to_poly[tmp + (x)]; \ - (c) ^= exp_to_poly[tmp + (y)]; \ - (d) ^= exp_to_poly[tmp + (z)]; \ - } - -/* Macros to calculate the key-dependent S-boxes for a 128-bit key using - * the S vector from CALC_S. CALC_SB_2 computes a single entry in all - * four S-boxes, where i is the index of the entry to compute, and a and b - * are the index numbers preprocessed through the q0 and q1 tables - * respectively. CALC_SB is simply a convenience to make the code shorter; - * it calls CALC_SB_2 four times with consecutive indices from i to i+3, - * using the remaining parameters two by two. */ - -#define CALC_SB_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ - ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ - ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ - ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] - -#define CALC_SB(i, a, b, c, d, e, f, g, h) \ - CALC_SB_2 (i, a, b); CALC_SB_2 ((i)+1, c, d); \ - CALC_SB_2 ((i)+2, e, f); CALC_SB_2 ((i)+3, g, h) - -/* Macros exactly like CALC_SB and CALC_SB_2, but for 256-bit keys. */ - -#define CALC_SB256_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ - ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ - ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ - ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; - -#define CALC_SB256(i, a, b, c, d, e, f, g, h) \ - CALC_SB256_2 (i, a, b); CALC_SB256_2 ((i)+1, c, d); \ - CALC_SB256_2 ((i)+2, e, f); CALC_SB256_2 ((i)+3, g, h) - -/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the - * last two stages of the h() function for a given index (either 2i or 2i+1). - * a, b, c, and d are the four bytes going into the last two stages. For - * 128-bit keys, this is the entire h() function and a and c are the index - * preprocessed through q0 and q1 respectively; for longer keys they are the - * output of previous stages. j is the index of the first key byte to use. - * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 - * twice, doing the Psuedo-Hadamard Transform, and doing the necessary - * rotations. Its parameters are: a, the array to write the results into, - * j, the index of the first output entry, k and l, the preprocessed indices - * for index 2i, and m and n, the preprocessed indices for index 2i+1. - * CALC_K256_2 expands CALC_K_2 to handle 256-bit keys, by doing two - * additional lookup-and-XOR stages. The parameters a and b are the index - * preprocessed through q0 and q1 respectively; j is the index of the first - * key byte to use. CALC_K256 is identical to CALC_K but for using the - * CALC_K256_2 macro instead of CALC_K_2. */ - -#define CALC_K_2(a, b, c, d, j) \ - mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ - ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ - ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ - ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] - -#define CALC_K(a, j, k, l, m, n) \ - x = CALC_K_2 (k, l, k, l, 0); \ - y = CALC_K_2 (m, n, m, n, 4); \ - y = (y << 8) + (y >> 24); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = (y << 9) + (y >> 23) - -#define CALC_K256_2(a, b, j) \ - CALC_K_2 (q0[q1[b ^ key[(j) + 24]] ^ key[(j) + 16]], \ - q1[q1[a ^ key[(j) + 25]] ^ key[(j) + 17]], \ - q0[q0[a ^ key[(j) + 26]] ^ key[(j) + 18]], \ - q1[q0[b ^ key[(j) + 27]] ^ key[(j) + 19]], j) - -#define CALC_K256(a, j, k, l, m, n) \ - x = CALC_K256_2 (k, l, 0); \ - y = CALC_K256_2 (m, n, 4); \ - y = (y << 8) + (y >> 24); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = (y << 9) + (y >> 23) - - -static void -burn_stack (int bytes) -{ - char buf[64]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - - -/* Perform the key setup. Note that this works only with 128- and 256-bit - * keys, despite the API that looks like it might support other sizes. */ - -#ifdef __riscos__ -/* need to switch off CSE optimisation for Norcroft C (Acorn/Pace) */ -#pragma no_optimise_cse -#endif /* __riscos__ */ - -static int -do_twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen) -{ - int i, j, k; - - /* Temporaries for CALC_K. */ - u32 x, y; - - /* The S vector used to key the S-boxes, split up into individual bytes. - * 128-bit keys use only sa through sh; 256-bit use all of them. */ - byte sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; - byte si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; - - /* Temporary for CALC_S. */ - byte tmp; - - /* Flags for self-test. */ - static int initialized = 0; - static const char *selftest_failed=0; - - /* Check key length. */ - if( ( ( keylen - 16 ) | 16 ) != 16 ) - return G10ERR_WRONG_KEYLEN; - - /* Do self-test if necessary. */ - if (!initialized) { - initialized = 1; - selftest_failed = selftest (); - if( selftest_failed ) - fprintf(stderr, "%s\n", selftest_failed ); - } - if( selftest_failed ) - return G10ERR_SELFTEST_FAILED; - - /* Compute the first two words of the S vector. The magic numbers are - * the entries of the RS matrix, preprocessed through poly_to_exp. The - * numbers in the comments are the original (polynomial form) matrix - * entries. */ - CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - - if (keylen == 32) { /* 256-bit key */ - /* Calculate the remaining two words of the S vector */ - CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - - /* Compute the S-boxes. */ - for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } - else { - /* Compute the S-boxes. */ - for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } - - return 0; -} - -#ifdef __riscos__ -#pragma optimise_cse -#endif /* __riscos__ */ - -static int -twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen) -{ - int rc = do_twofish_setkey (ctx, key, keylen); - burn_stack (23+6*sizeof(void*)); - return rc; -} - - - -/* Macros to compute the g() function in the encryption and decryption - * rounds. G1 is the straight g() function; G2 includes the 8-bit - * rotation for the high 32-bit word. */ - -#define G1(a) \ - (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ - ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) - -#define G2(b) \ - (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ - ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) - -/* Encryption and decryption Feistel rounds. Each one calls the two g() - * macros, does the PHT, and performs the XOR and the appropriate bit - * rotations. The parameters are the round number (used to select subkeys), - * and the four 32-bit chunks of the text. */ - -#define ENCROUND(n, a, b, c, d) \ - x = G1 (a); y = G2 (b); \ - x += y; y += x + ctx->k[2 * (n) + 1]; \ - (c) ^= x + ctx->k[2 * (n)]; \ - (c) = ((c) >> 1) + ((c) << 31); \ - (d) = (((d) << 1)+((d) >> 31)) ^ y - -#define DECROUND(n, a, b, c, d) \ - x = G1 (a); y = G2 (b); \ - x += y; y += x; \ - (d) ^= y + ctx->k[2 * (n) + 1]; \ - (d) = ((d) >> 1) + ((d) << 31); \ - (c) = (((c) << 1)+((c) >> 31)); \ - (c) ^= (x + ctx->k[2 * (n)]) - -/* Encryption and decryption cycles; each one is simply two Feistel rounds - * with the 32-bit chunks re-ordered to simulate the "swap" */ - -#define ENCCYCLE(n) \ - ENCROUND (2 * (n), a, b, c, d); \ - ENCROUND (2 * (n) + 1, c, d, a, b) - -#define DECCYCLE(n) \ - DECROUND (2 * (n) + 1, c, d, a, b); \ - DECROUND (2 * (n), a, b, c, d) - -/* Macros to convert the input and output bytes into 32-bit words, - * and simultaneously perform the whitening step. INPACK packs word - * number n into the variable named by x, using whitening subkey number m. - * OUTUNPACK unpacks word number n from the variable named by x, using - * whitening subkey number m. */ - -#define INPACK(n, x, m) \ - x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ - ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] - -#define OUTUNPACK(n, x, m) \ - x ^= ctx->w[m]; \ - out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ - out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 - -/* Encrypt one block. in and out may be the same. */ - -#ifdef __riscos__ -/* need to switch off CSE optimisation for Norcroft C (Acorn/Pace) */ -#pragma no_optimise_cse -#endif /* __riscos__ */ - -static void -do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) -{ - /* The four 32-bit chunks of the text. */ - u32 a, b, c, d; - - /* Temporaries used by the round function. */ - u32 x, y; - - /* Input whitening and packing. */ - INPACK (0, a, 0); - INPACK (1, b, 1); - INPACK (2, c, 2); - INPACK (3, d, 3); - - /* Encryption Feistel cycles. */ - ENCCYCLE (0); - ENCCYCLE (1); - ENCCYCLE (2); - ENCCYCLE (3); - ENCCYCLE (4); - ENCCYCLE (5); - ENCCYCLE (6); - ENCCYCLE (7); - - /* Output whitening and unpacking. */ - OUTUNPACK (0, c, 4); - OUTUNPACK (1, d, 5); - OUTUNPACK (2, a, 6); - OUTUNPACK (3, b, 7); -} - -#ifdef __riscos__ -#pragma optimise_cse -#endif /* __riscos__ */ - -static void -twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) -{ - do_twofish_encrypt (ctx, out, in); - burn_stack (24+3*sizeof (void*)); -} - -/* Decrypt one block. in and out may be the same. */ - -#ifdef __riscos__ -/* need to switch off CSE optimisation for Norcroft C (Acorn/Pace) - bug */ -#pragma no_optimise_cse -#endif /* __riscos__ */ - -static void -do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) -{ - /* The four 32-bit chunks of the text. */ - u32 a, b, c, d; - - /* Temporaries used by the round function. */ - u32 x, y; - - /* Input whitening and packing. */ - INPACK (0, c, 4); - INPACK (1, d, 5); - INPACK (2, a, 6); - INPACK (3, b, 7); - - /* Encryption Feistel cycles. */ - DECCYCLE (7); - DECCYCLE (6); - DECCYCLE (5); - DECCYCLE (4); - DECCYCLE (3); - DECCYCLE (2); - DECCYCLE (1); - DECCYCLE (0); - - /* Output whitening and unpacking. */ - OUTUNPACK (0, a, 0); - OUTUNPACK (1, b, 1); - OUTUNPACK (2, c, 2); - OUTUNPACK (3, d, 3); -} - -#ifdef __riscos__ -#pragma optimise_cse -#endif /* __riscos__ */ - -static void -twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) -{ - do_twofish_decrypt (ctx, out, in); - burn_stack (24+3*sizeof (void*)); -} - -/* Test a single encryption and decryption with each key size. */ - -static const char* -selftest (void) -{ - TWOFISH_context ctx; /* Expanded key. */ - byte scratch[16]; /* Encryption/decryption result buffer. */ - - /* Test vectors for single encryption/decryption. Note that I am using - * the vectors from the Twofish paper's "known answer test", I=3 for - * 128-bit and I=4 for 256-bit, instead of the all-0 vectors from the - * "intermediate value test", because an all-0 key would trigger all the - * special cases in the RS matrix multiply, leaving the math untested. */ - static const byte plaintext[16] = { - 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, - 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 - }; - static const byte key[16] = { - 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, - 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A - }; - static const byte ciphertext[16] = { - 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, - 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 - }; - static const byte plaintext_256[16] = { - 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, - 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 - }; - static const byte key_256[32] = { - 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, - 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, - 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, - 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F - }; - static const byte ciphertext_256[16] = { - 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, - 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA - }; - - twofish_setkey (&ctx, key, sizeof(key)); - twofish_encrypt (&ctx, scratch, plaintext); - if (memcmp (scratch, ciphertext, sizeof (ciphertext))) - return "Twofish-128 test encryption failed."; - twofish_decrypt (&ctx, scratch, scratch); - if (memcmp (scratch, plaintext, sizeof (plaintext))) - return "Twofish-128 test decryption failed."; - - twofish_setkey (&ctx, key_256, sizeof(key_256)); - twofish_encrypt (&ctx, scratch, plaintext_256); - if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) - return "Twofish-256 test encryption failed."; - twofish_decrypt (&ctx, scratch, scratch); - if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) - return "Twofish-256 test decryption failed."; - - return NULL; -} - -/* More complete test program. This does 1000 encryptions and decryptions - * with each of 250 128-bit keys and 2000 encryptions and decryptions with - * each of 125 256-bit keys, using a feedback scheme similar to a Feistel - * cipher, so as to be sure of testing all the table entries pretty - * thoroughly. We keep changing the keys so as to get a more meaningful - * performance number, since the key setup is non-trivial for Twofish. */ - -#ifdef TEST - -#include -#include -#include - -int -main() -{ - TWOFISH_context ctx; /* Expanded key. */ - int i, j; /* Loop counters. */ - - const char *encrypt_msg; /* Message to print regarding encryption test; - * the printf is done outside the loop to avoid - * stuffing up the timing. */ - clock_t timer; /* For computing elapsed time. */ - - /* Test buffer. */ - byte buffer[4][16] = { - {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, - {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, - 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, - {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, - {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, - 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} - }; - - /* Expected outputs for the million-operation test */ - static const byte test_encrypt[4][16] = { - {0xC8, 0x23, 0xB8, 0xB7, 0x6B, 0xFE, 0x91, 0x13, - 0x2F, 0xA7, 0x5E, 0xE6, 0x94, 0x77, 0x6F, 0x6B}, - {0x90, 0x36, 0xD8, 0x29, 0xD5, 0x96, 0xC2, 0x8E, - 0xE4, 0xFF, 0x76, 0xBC, 0xE5, 0x77, 0x88, 0x27}, - {0xB8, 0x78, 0x69, 0xAF, 0x42, 0x8B, 0x48, 0x64, - 0xF7, 0xE9, 0xF3, 0x9C, 0x42, 0x18, 0x7B, 0x73}, - {0x7A, 0x88, 0xFB, 0xEB, 0x90, 0xA4, 0xB4, 0xA8, - 0x43, 0xA3, 0x1D, 0xF1, 0x26, 0xC4, 0x53, 0x57} - }; - static const byte test_decrypt[4][16] = { - {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, - {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, - 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, - {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, - {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, - 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} - }; - - /* Start the timer ticking. */ - timer = clock (); - - /* Encryption test. */ - for (i = 0; i < 125; i++) { - twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); - for (j = 0; j < 1000; j++) - twofish_encrypt (&ctx, buffer[2], buffer[2]); - twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); - for (j = 0; j < 1000; j++) - twofish_encrypt (&ctx, buffer[3], buffer[3]); - twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); - for (j = 0; j < 1000; j++) { - twofish_encrypt (&ctx, buffer[0], buffer[0]); - twofish_encrypt (&ctx, buffer[1], buffer[1]); - } - } - encrypt_msg = memcmp (buffer, test_encrypt, sizeof (test_encrypt)) ? - "encryption failure!\n" : "encryption OK!\n"; - - /* Decryption test. */ - for (i = 0; i < 125; i++) { - twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); - for (j = 0; j < 1000; j++) { - twofish_decrypt (&ctx, buffer[0], buffer[0]); - twofish_decrypt (&ctx, buffer[1], buffer[1]); - } - twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); - for (j = 0; j < 1000; j++) - twofish_decrypt (&ctx, buffer[3], buffer[3]); - twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); - for (j = 0; j < 1000; j++) - twofish_decrypt (&ctx, buffer[2], buffer[2]); - } - - /* Stop the timer, and print results. */ - timer = clock () - timer; - printf (encrypt_msg); - printf (memcmp (buffer, test_decrypt, sizeof (test_decrypt)) ? - "decryption failure!\n" : "decryption OK!\n"); - printf ("elapsed time: %.1f s.\n", (float) timer / CLOCKS_PER_SEC); - - return 0; -} - -#endif /* TEST */ - -#ifdef IS_MODULE -static -#endif - const char * -twofish_get_info (int algo, size_t *keylen, - size_t *blocksize, size_t *contextsize, - int (**r_setkey) (void *c, byte *key, unsigned keylen), - void (**r_encrypt) (void *c, byte *outbuf, byte *inbuf), - void (**r_decrypt) (void *c, byte *outbuf, byte *inbuf) - ) -{ - *keylen = algo==10? 256 : 128; - *blocksize = 16; - *contextsize = sizeof (TWOFISH_context); - - *(int (**)(TWOFISH_context*, const byte*, const unsigned))r_setkey - = twofish_setkey; - *(void (**)(const TWOFISH_context*, byte*, const byte*))r_encrypt - = twofish_encrypt; - *(void (**)(const TWOFISH_context*, byte*, const byte*))r_decrypt - = twofish_decrypt; - - if( algo == 10 ) - return "TWOFISH"; - if (algo == 102) /* This algorithm number is assigned for - * experiments, so we can use it */ - return "TWOFISH128"; - return NULL; -} - - -#ifdef IS_MODULE -static -const char * const gnupgext_version = "TWOFISH ($Revision$)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 20, 1, 0, (void(*)(void))twofish_get_info }, - { 21, 1, 10 }, - { 21, 1, 102 }, -}; - - - -/**************** - * Enumerate the names of the functions together with information about - * this function. Set sequence to an integer with a initial value of 0 and - * do not change it. - * If what is 0 all kind of functions are returned. - * Return values: class := class of function: - * 10 = message digest algorithm info function - * 11 = integer with available md algorithms - * 20 = cipher algorithm info function - * 21 = integer with available cipher algorithms - * 30 = public key algorithm info function - * 31 = integer with available pubkey algorithms - * version = interface version of the function/pointer - * (currently this is 1 for all functions) - */ -static void * -gnupgext_enum_func ( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if ( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - switch( *class ) { - case 11: - case 21: - case 31: - ret = &func_table[i].value; - break; - default: -#ifndef __riscos__ - ret = func_table[i].func; -#else /* __riscos__ */ - ret = (void *) func_table[i].func; -#endif /* __riscos__ */ - break; - } - i++; - } while ( what && what != *class ); - - *sequence = i; - return ret; -} -#endif diff --git a/common/ChangeLog b/common/ChangeLog deleted file mode 100644 index ff886650d..000000000 --- a/common/ChangeLog +++ /dev/null @@ -1,139 +0,0 @@ -2002-09-04 Neal H. Walfield - - * 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 - - * errors.h: Added STATUS_IMPORT_PROBLEM. - -2002-08-20 Werner Koch - - * vasprintf.c: Hack to handle NULL for %s. - -2002-08-09 Werner Koch - - * signal.c: New. Taken from GnuPG 1.1.91. - -2002-07-23 Werner Koch - - * util.h (_IO_cookie_io_functions_t): Fixed typo. Noted by - Richard Lefebvre. - -2002-07-22 Werner Koch - - * fseeko.c, ftello.c: New. - -2002-06-28 Werner Koch - - * maperror.c (map_to_assuan_status): Map more errorcodes to Bad - Certificate. - -2002-06-26 Werner Koch - - * maperror.c (map_to_assuan_status): Map EOF to No_Data_Available. - -2002-06-10 Werner Koch - - * 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 - - * maperror.c (map_to_assuan_status): Map Bad_CA_Certificate. - -2002-05-23 Werner Koch - - * no-pth.c, Makefile.am: Removed. - -2002-05-22 Werner Koch - - * mkdtemp.c: Replaced byte by unsigned char because it is no longer - defined in gcrypt.h. - -2002-05-21 Werner Koch - - * maperror.c (map_gcry_err): Add libgcrypt's new S-expression errors. - (map_ksba_err): Add a few mappings. - -2002-05-14 Werner Koch - - * gettime.c: New. - -2002-05-03 Werner Koch - - * errors.h: Added STARUS_EXPSIG and STATUS_EXPKEYSIG. - -2002-04-15 Werner Koch - - * cryptmiss.c: New. - -2002-02-14 Werner Koch - - * maperror.c: Add more assuan<->gnupg mappings. - -2002-02-12 Werner Koch - - * 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 - - * mkdtemp.c: Copied from gnupg-1.0.6c and changed to use libgcrypt. - -2002-01-19 Werner Koch - - * 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 - - * maperror.c: Add mapping for Not_Trusted. - -2002-01-11 Werner Koch - - * maperror.c (map_assuan_err): Codes for CRL - -2002-01-08 Werner Koch - - * util.h (spacep): New. - -2002-01-02 Werner Koch - - * maperror.c (map_to_assuan_status): New. Merged from ../agent - and ../sm. - -2001-12-20 Werner Koch - - * maperror.c (map_gcry_err): Add some mappings. - -2001-12-18 Werner Koch - - * Makefile.am (AM_CPPFLAGS): Include flags for gcrypt and ksba - -2001-12-14 Werner Koch - - * 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. - - diff --git a/common/Makefile.am b/common/Makefile.am deleted file mode 100644 index 8f8209afd..000000000 --- a/common/Makefile.am +++ /dev/null @@ -1,52 +0,0 @@ -# Makefile for common gnupg modules -# 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 - -EXTRA_DIST = mkerrors mkerrtok -#INCLUDES = -BUILT_SOURCES = errors.c - -noinst_LIBRARIES = libcommon.a - -AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) - -libcommon_a_SOURCES = \ - util.h i18n.h \ - errors.c errors.h \ - maperror.c \ - sysutils.c sysutils.h \ - cryptmiss.c \ - gettime.c \ - signal.c - - -libcommon_a_LIBADD = @LIBOBJS@ - -errors.c : errors.h mkerrors mkerrtok - $(srcdir)/mkerrors < $(srcdir)/errors.h > errors.c - $(srcdir)/mkerrtok < $(srcdir)/errors.h >> errors.c - - - - - - - - diff --git a/common/README b/common/README deleted file mode 100644 index d3927d869..000000000 --- a/common/README +++ /dev/null @@ -1,14 +0,0 @@ -Stuff used by several modules of GnuPG. This way we can share error -codes and serveral other things. - - -These directories use it: - -gpg -sm -agent - -These directories don't use it: - -assuan -kbx \ No newline at end of file diff --git a/common/errors.h b/common/errors.h deleted file mode 100644 index c28149fb6..000000000 --- a/common/errors.h +++ /dev/null @@ -1,192 +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" - -/* Error numbers */ -enum { - GNUPG_EOF = -1, - GNUPG_No_Error = 0, - GNUPG_General_Error = 1, - GNUPG_Out_Of_Core = 2, - GNUPG_Invalid_Value = 3, - GNUPG_IO_Error = 4, - GNUPG_Resource_Limit = 5, - GNUPG_Internal_Error = 6, - GNUPG_Bad_Certificate = 7, - GNUPG_Bad_Certificate_Chain = 8, - GNUPG_Missing_Certificate = 9, - GNUPG_No_Data = 10, - GNUPG_Bad_Signature = 11, - GNUPG_Not_Implemented = 12, - GNUPG_Conflict = 13, - GNUPG_Bug = 14, - GNUPG_Read_Error = 15, - GNUPG_Write_Error = 16, - GNUPG_Incomplete_Line = 17, - GNUPG_Invalid_Response = 18, - GNUPG_No_Agent = 19, - GNUPG_Agent_Error = 20, - GNUPG_No_Public_Key = 21, - GNUPG_No_Secret_Key = 22, - GNUPG_File_Open_Error = 23, - GNUPG_File_Create_Error = 24, - GNUPG_File_Error = 25, - GNUPG_Not_Supported = 26, - GNUPG_Invalid_Data = 27, - GNUPG_Assuan_Server_Fault = 28, - GNUPG_Assuan_Error = 29, /* catch all assuan error */ - GNUPG_Invalid_Session_Key = 30, - GNUPG_Invalid_Sexp = 31, - GNUPG_Unsupported_Algorithm = 32, - GNUPG_No_PIN_Entry = 33, - GNUPG_PIN_Entry_Error = 34, - GNUPG_Bad_PIN = 35, - GNUPG_Bad_Passphrase = 36, - GNUPG_Invalid_Name = 37, - GNUPG_Bad_Public_Key = 38, - GNUPG_Bad_Secret_Key = 39, - GNUPG_Bad_Data = 40, - GNUPG_Invalid_Parameter = 41, - GNUPG_Tribute_to_D_A = 42, - GNUPG_No_Dirmngr = 43, - GNUPG_Dirmngr_Error = 44, - GNUPG_Certificate_Revoked = 45, - GNUPG_No_CRL_Known = 46, - GNUPG_CRL_Too_Old = 47, - GNUPG_Line_Too_Long = 48, - GNUPG_Not_Trusted = 49, - GNUPG_Canceled = 50, - GNUPG_Bad_CA_Certificate = 51, - GNUPG_Certificate_Expired = 52, - GNUPG_Certificate_Too_Young = 53, - GNUPG_Unsupported_Certificate = 54, - GNUPG_Unknown_Sexp = 55, - GNUPG_Unsupported_Protection = 56, - GNUPG_Corrupted_Protection = 57, - GNUPG_Ambiguous_Name = 58, - GNUPG_Card_Error = 59, - GNUPG_Card_Reset = 60, - GNUPG_Card_Removed = 61, - GNUPG_Invalid_Card = 62, - GNUPG_Card_Not_Present = 63, - GNUPG_No_PKCS15_App = 64, - GNUPG_Not_Confirmed = 65, - GNUPG_Configuration_Error = 66, - GNUPG_No_Policy_Match = 67, - GNUPG_Invalid_Index = 68, - GNUPG_Invalid_Id = 69, - GNUPG_No_Scdaemon = 70, - GNUPG_Scdaemon_Error = 71, - GNUPG_Unsupported_Protocol = 72, - GNUPG_Bad_PIN_Method = 73, - GNUPG_Card_Not_Initialized = 74, - GNUPG_Unsupported_Operation = 75, - GNUPG_Wrong_Key_Usage = 76, -}; - -/* 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_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 -}; - - -/*-- 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*/ diff --git a/common/gettime.c b/common/gettime.c deleted file mode 100644 index 6f656c8e4..000000000 --- a/common/gettime.c +++ /dev/null @@ -1,87 +0,0 @@ -/* gettime.c - Wrapper for time functions - * 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 - */ - -#include -#include -#include - -#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; -} - -/* 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; -} - - - - diff --git a/common/maperror.c b/common/maperror.c deleted file mode 100644 index ab03669ae..000000000 --- a/common/maperror.c +++ /dev/null @@ -1,271 +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 -#include -#include -#include -#include -#include -#include - -#include - -#include "util.h" -#include "errors.h" -#include "../assuan/assuan.h" - -/* Note: we might want to wrap this in a macro to get our hands on - the line and file where the error occured */ -int -map_ksba_err (int err) -{ - switch (err) - { - case -1: - case 0: - break; - - case KSBA_Out_Of_Core: err = GNUPG_Out_Of_Core; break; - case KSBA_Invalid_Value: err = GNUPG_Invalid_Value; break; - case KSBA_Not_Implemented: err = GNUPG_Not_Implemented; break; - case KSBA_Conflict: err = GNUPG_Conflict; break; - case KSBA_Read_Error: err = GNUPG_Read_Error; break; - case KSBA_Write_Error: err = GNUPG_Write_Error; break; - case KSBA_No_Data: err = GNUPG_No_Data; break; - case KSBA_Bug: err = GNUPG_Bug; break; - case KSBA_Unsupported_Algorithm: err = GNUPG_Unsupported_Algorithm; break; - case KSBA_Invalid_Index: err = GNUPG_Invalid_Index; break; - case KSBA_Invalid_Sexp: err = GNUPG_Invalid_Sexp; break; - case KSBA_Unknown_Sexp: err = GNUPG_Unknown_Sexp; break; - - default: - err = seterr (General_Error); - break; - } - return err; -} - - -int -map_gcry_err (int err) -{ - switch (err) - { - case GCRYERR_EOF: - case -1: - err = -1; - break; - - case 0: - break; - - case GCRYERR_WRONG_PK_ALGO: - case GCRYERR_INV_PK_ALGO: - case GCRYERR_INV_MD_ALGO: - case GCRYERR_INV_CIPHER_ALGO: - err = GNUPG_Unsupported_Algorithm; - break; - case GCRYERR_INV_KEYLEN: - case GCRYERR_WEAK_KEY: - case GCRYERR_BAD_PUBLIC_KEY: err = GNUPG_Bad_Public_Key; break; - case GCRYERR_BAD_SECRET_KEY: err = GNUPG_Bad_Secret_Key; break; - case GCRYERR_BAD_SIGNATURE: err = GNUPG_Bad_Signature; break; - - case GCRYERR_BAD_MPI: - err = GNUPG_Bad_Data; - break; - - case GCRYERR_INV_ARG: - case GCRYERR_INV_OP: - case GCRYERR_INTERNAL: - case GCRYERR_INV_CIPHER_MODE: - err = GNUPG_Invalid_Value; - break; - - case GCRYERR_SELFTEST: - err = GNUPG_Bug; - break; - - case GCRYERR_SEXP_INV_LEN_SPEC : - case GCRYERR_SEXP_STRING_TOO_LONG : - case GCRYERR_SEXP_UNMATCHED_PAREN : - case GCRYERR_SEXP_NOT_CANONICAL : - case GCRYERR_SEXP_BAD_CHARACTER : - case GCRYERR_SEXP_BAD_QUOTATION : - case GCRYERR_SEXP_ZERO_PREFIX : - case GCRYERR_SEXP_NESTED_DH : - case GCRYERR_SEXP_UNMATCHED_DH : - case GCRYERR_SEXP_UNEXPECTED_PUNC : - case GCRYERR_SEXP_BAD_HEX_CHAR : - case GCRYERR_SEXP_ODD_HEX_NUMBERS : - case GCRYERR_SEXP_BAD_OCT_CHAR : - err = GNUPG_Invalid_Sexp; - break; - - case GCRYERR_NO_MEM: err = GNUPG_Out_Of_Core; break; - - case GCRYERR_NOT_IMPL: err = GNUPG_Not_Implemented; break; - case GCRYERR_CONFLICT: err = GNUPG_Conflict; break; - - case GCRYERR_INV_OBJ: /* an object is not valid */ - case GCRYERR_TOO_SHORT: /* provided buffer too short */ - case GCRYERR_TOO_LARGE: /* object is too large */ - case GCRYERR_NO_OBJ: /* Missing item in an object */ - default: - err = seterr (General_Error); - break; - } - return err; -} - -int -map_kbx_err (int err) -{ - switch (err) - { - case -1: - case 0: - break; - - default: - err = seterr (General_Error); - break; - } - return err; -} - - -int -map_assuan_err (int err) -{ - switch (err) - { - case -1: - case 0: - break; - - case ASSUAN_Canceled: err = GNUPG_Canceled; break; - case ASSUAN_Invalid_Index: err = GNUPG_Invalid_Index; break; - - case ASSUAN_Not_Implemented: err = GNUPG_Not_Implemented; break; - case ASSUAN_Server_Fault: err = GNUPG_Assuan_Server_Fault; break; - case ASSUAN_No_Public_Key: err = GNUPG_No_Public_Key; break; - case ASSUAN_No_Secret_Key: err = GNUPG_No_Secret_Key; break; - - case ASSUAN_Cert_Revoked: err = GNUPG_Certificate_Revoked; break; - case ASSUAN_No_CRL_For_Cert: err = GNUPG_No_CRL_Known; break; - case ASSUAN_CRL_Too_Old: err = GNUPG_CRL_Too_Old; break; - - case ASSUAN_Not_Trusted: err = GNUPG_Not_Trusted; break; - - case ASSUAN_Card_Error: err = GNUPG_Card_Error; break; - case ASSUAN_Invalid_Card: err = GNUPG_Invalid_Card; break; - case ASSUAN_No_PKCS15_App: err = GNUPG_No_PKCS15_App; break; - case ASSUAN_Card_Not_Present: err= GNUPG_Card_Not_Present; break; - case ASSUAN_Not_Confirmed: err = GNUPG_Not_Confirmed; break; - case ASSUAN_Invalid_Id: err = GNUPG_Invalid_Id; break; - - default: - err = err < 100? GNUPG_Assuan_Server_Fault : GNUPG_Assuan_Error; - break; - } - return err; -} - -/* Map GNUPG_xxx error codes to Assuan status codes */ -int -map_to_assuan_status (int rc) -{ - switch (rc) - { - case -1: - rc = ASSUAN_No_Data_Available; - break; - case 0: break; - case GNUPG_Bad_CA_Certificate: - case GNUPG_Bad_Certificate: - case GNUPG_Wrong_Key_Usage: - case GNUPG_Certificate_Revoked: - case GNUPG_No_CRL_Known: - case GNUPG_CRL_Too_Old: - case GNUPG_No_Policy_Match: - case GNUPG_Certificate_Expired: - rc = ASSUAN_Bad_Certificate; - break; - case GNUPG_Bad_Certificate_Chain: rc = ASSUAN_Bad_Certificate_Chain; break; - case GNUPG_Missing_Certificate: rc = ASSUAN_Missing_Certificate; break; - case GNUPG_No_Data: rc = ASSUAN_No_Data_Available; break; - case GNUPG_Bad_Signature: rc = ASSUAN_Bad_Signature; break; - case GNUPG_Not_Implemented: rc = ASSUAN_Not_Implemented; break; - case GNUPG_No_Agent: rc = ASSUAN_No_Agent; break; - case GNUPG_Agent_Error: rc = ASSUAN_Agent_Error; break; - case GNUPG_No_Public_Key: rc = ASSUAN_No_Public_Key; break; - case GNUPG_No_Secret_Key: rc = ASSUAN_No_Secret_Key; break; - case GNUPG_Invalid_Data: rc = ASSUAN_Invalid_Data; break; - case GNUPG_Invalid_Name: rc = ASSUAN_Invalid_Name; break; - case GNUPG_Not_Trusted: rc = ASSUAN_Not_Trusted; break; - case GNUPG_Canceled: rc = ASSUAN_Canceled; break; - case GNUPG_Invalid_Index: rc = ASSUAN_Invalid_Index; break; - - case GNUPG_Card_Error: - case GNUPG_Card_Reset: - rc = ASSUAN_Card_Error; - break; - case GNUPG_Card_Removed: - case GNUPG_Card_Not_Present: - rc = ASSUAN_Card_Not_Present; - break; - case GNUPG_Invalid_Card: rc = ASSUAN_Invalid_Card; break; - case GNUPG_No_PKCS15_App: rc = ASSUAN_No_PKCS15_App; break; - case GNUPG_Not_Confirmed: rc = ASSUAN_Not_Confirmed; break; - case GNUPG_Invalid_Id: rc = ASSUAN_Invalid_Id; break; - - case GNUPG_Bad_PIN: - case GNUPG_Bad_Passphrase: - rc = ASSUAN_No_Secret_Key; - break; - - case GNUPG_Read_Error: - case GNUPG_Write_Error: - case GNUPG_IO_Error: - rc = ASSUAN_Server_IO_Error; - break; - case GNUPG_Out_Of_Core: - case GNUPG_Resource_Limit: - rc = ASSUAN_Server_Resource_Problem; - break; - case GNUPG_Bug: - case GNUPG_Internal_Error: - rc = ASSUAN_Server_Bug; - break; - default: - rc = ASSUAN_Server_Fault; - break; - } - return rc; -} - - - - - - - diff --git a/common/signal.c b/common/signal.c deleted file mode 100644 index b150fa90a..000000000 --- a/common/signal.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" - - -static volatile int caught_fatal_sig = 0; -static volatile int caught_sigusr1 = 0; -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); -} diff --git a/common/util.h b/common/util.h deleted file mode 100644 index a863f2078..000000000 --- a/common/util.h +++ /dev/null @@ -1,117 +0,0 @@ -/* util.h - Utility functions for Gnupg - * 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 - */ - -#ifndef GNUPG_COMMON_UTIL_H -#define GNUPG_COMMON_UTIL_H - -#include /* we need this for the memory function protos */ -#include /* we need time_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" - -/* handy malloc macros - use only them */ -#define xtrymalloc(a) gcry_malloc ((a)) -#define xtrycalloc(a,b) gcry_calloc ((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 xcalloc(a,b) gcry_xcalloc ((a),(b)) -#define xrealloc(a,b) gcry_xrealloc ((a),(b)) -#define xstrdup(a) gcry_xstrdup ((a)) - -#define seterr(a) (GNUPG_ ## a) - -/*-- maperror.c --*/ -int map_ksba_err (int err); -int map_gcry_err (int err); -int map_kbx_err (int err); -int map_assuan_err (int err); -int map_to_assuan_status (int rc); - -/*-- gettime.c --*/ -time_t gnupg_get_time (void); -void gnupg_set_time (time_t newtime, int freeze); -int gnupg_faked_time_p (void); - -/*-- 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); - - -/*-- replacement functions from funcname.c --*/ -#if !HAVE_VASPRINTF -#include -int vasprintf (char **result, const char *format, va_list *args); -int asprintf (char **result, const char *format, ...); -#endif - -#if !HAVE_FOPENCOOKIE -typedef struct -{ - ssize_t (*read)(void*,char*,size_t); - ssize_t (*write)(void*,const char*,size_t); - int (*seek)(void*,off_t*,int); - int (*close)(void*); -} _IO_cookie_io_functions_t; -typedef _IO_cookie_io_functions_t cookie_io_functions_t; -FILE *fopencookie (void *cookie, const char *opentype, - cookie_io_functions_t funclist); -#endif /*!HAVE_FOPENCOOKIE*/ - - - -/*-- 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')) -/* 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)) - - - -#endif /*GNUPG_COMMON_UTIL_H*/ - - - - - - - - diff --git a/contrib/UTF-8-test.txt b/contrib/UTF-8-test.txt deleted file mode 100644 index 2510f779c..000000000 Binary files a/contrib/UTF-8-test.txt and /dev/null differ diff --git a/contrib/changes-in-2000 b/contrib/changes-in-2000 deleted file mode 100644 index d9a18d09f..000000000 --- a/contrib/changes-in-2000 +++ /dev/null @@ -1,114 +0,0 @@ -New features since 1.0.0 ------------------------- - - * The default symmetric cipher algorithm is now AES (aka - Rijndael). OpenPGP uses preferences to figure out the algorithm - to use, so this is only used if the recipient knows how to - handles AES. - - * RSA keys can now be used (either old PGP 2 or new OpenPGP ones). - RSA key generation is not yet available. - - * Unattended key generation. - - * Faster and more robust random number generator under W32. - - * Encryption is now much faster: About 2 times for 1k bit keys - and 8 times for 4k keys. - - * New encryption keys are generated in a way which allows a much - faster decryption. - - * GnuPG knows what the primary user ID is. - - * Large File Support (LFS) is working. - - * Ability to run gpg as a full controlled inferior process to speed up - mass verification of signatures. - - * Rewritten key selection code so that GnuPG can better cope with - multiple subkeys, expiration dates and so on. The drawback is that it - is slower. - - * New utility gpgv which is a stripped down version of gpg to - be used to verify signatures against a list of trusted keys. - - * New command --export-secret-subkeys which outputs the - the _primary_ key with it's secret parts deleted. This is - useful for automated decryption/signature creation as it - allows to keep the real secret primary key offline and - thereby protecting the key certificates and allowing to - create revocations for the subkeys. See the FAQ for a - procedure to install such secret keys. - - * New options --show-session-key and --override-session-key - to help the British folks to somewhat minimize the danger - of this Orwellian RIP bill. - - * New option --no-auto-key-retrieve to disable retrieving of a - missing public key from a keyserver, even when a keyserver has - been configured. Useful for dial-up connections. - - * HTTP proxy support for keyservers. - - * Keyserver support is how also available for W32 platforms (MS - Windows 95, 98, 2000, NT, ME). - - * Experimental gpg-agent support to get the passphrase from a - daemon which can pop up a query window. - - -rfc2440bis support (PGP 6.5.8 does also handle them) -------------------- - - * MDC enhanced encryption is now used with the AES and Twofish - algorithms to detect manipulated messages. - - * The user is now asked for the reason of a revocation. - - -Translations: ------------- - - * Enhanced UTF-8 support - - * New translations: Danish, Estonian, Indonesian, Portuguese and - Turkish. - -Serious bug fixes: ------------------- - - * Fixed a serious bug which could lead to false signature - verification results when more than one signature is fed to gpg. - This is the primary reason for releasing this version. - - * Protection against the recent Klima/Rosa attck on secret key - rings. - - * Corrected hash calculation for input data larger than 512M - it - was just wrong, so you might notice bad signature in some very - big files. It may be wise to keep an old copy of GnuPG around. - - * Secret keys are no longer imported unless you use the new option - --allow-secret-key-import. - -PGP quirks ----------- - - * Can handle (but not display) PGP's photo IDs. - - * Better default values to increase compatibilty with PGP. - - * Many other small enhancements to support the not fully-OpenPGP - compliant PGP versions. - -Manual ------- - - * The manual called GNU Privacy Handbook (GPH) is a separate - package and available preformatted in English, German, Italian, - Russian and Spanish at http://www.gnupg.org/docs.html. - [Due to the complicated build process, the source is currently - on available from CVS] - - diff --git a/contrib/why-gnupg b/contrib/why-gnupg deleted file mode 100644 index 289b9af8c..000000000 --- a/contrib/why-gnupg +++ /dev/null @@ -1,80 +0,0 @@ -Why to use GnuPG and not PGP. ------------------------------ - - * PGP 2 is nearly Free Software but encumbered by the IDEA patent. - - * PGP 2 is old, hard to maintain and limited to one set of - encryption algorithms (RSA + IDEA) - - * PGP 2 is not a GNU or Unix Program and threfore not easy to use in - those environments - - * PGP 2 has a couple of minor security flaws - - * PGP 5 and 6 are more or less OpenPGP conform but proprietray - software. Source code is available but there is no way to be sure - that the distributed binary versions do match the source code. - Parts of the source code are not published. It is illegal to - build versions of PGP from source and distribute them (IIRC, there - is an exception for private users). - - * PGP 5 and 6 are not fullty OpenPGP compliant - - * PGP 7 is claimed to be OpenPGP compliant but the source code is - not anymore published. - - * At least versions before 6.5.8 had severe coding bugs. We don't - know about PGP 7. - - * PGP 5, 6 and 7 implement complicated methods for key recovering in - corporate environments. Although this is not a hidden feature, - this leads to more code and bugs. - - * NAI as the vendor of PGP seems to be a major government contractor. - - * Given the history of known backdoors in other proprietary software - (e.g. Lotus Notes), some folks claim that there might also be - backdoors in PGP 5, 6 and 7. Now there are even more rumors after - Phil Zimmermann left NAI. - - * GnuPG is Free Software under the GNU GPL. It does not use - patented algorithms. - - * Everyone is able to scrutinize the source code, build, distribute - and use versions of his own or from a trusted party he chooses. - - * The build environment is also Free Software and therefore less - likely tampered with malicious code. The exception here is the MS - Windows version of GnuPG where the OS is proprietary. The binary - version however is build using an entirely Free Software OS and - toolchain (cross-platfrom development under GNU/Linux). - - * Security fixes are provided very fast. - - * GnuPG is a standard tool in all GNU/Linux systems and used in many - different environments. - - * GnuPG gives reasonable messages and not just "Error encrypting". - - * GnuPG supports most of the optional features of the OpenPGP standard. - - * GnuPG comes with internationalization support for 16 languages. - - * Graphical frontends are available and they divert the task of - the actual cryptographic operations to GnuPG as a specialized tool - for this. A library called GPGME is available which makes - interfacing of GnuPG with other programs quite easy. - - * GnuPG is available for all GNU and Unix platforms as well as for - all MS Windows Operating systems. Porting to VMS, MAC OSX and - OS/2 is nearly finished. - - - - - - - - - - diff --git a/debian/README.Debian b/debian/README.Debian deleted file mode 100644 index 854a2e43a..000000000 --- a/debian/README.Debian +++ /dev/null @@ -1,28 +0,0 @@ -GDBM keyring support --------------------- - -GDBM-based keyring support is (and always) was an experimental feature -which is likely to be removed in future versions. For that reason it -is not compiled into the Debian package and won't be until and unless -GDBM support stabilises. - -Upgrading from old (<= 0.3.3) versions GnuPG --------------------------------------------- - -Due to a bug in the way secret keys were encrypted in versions prior -to 0.3.3, later version of GnuPG are not backwards compatible and you -will have to convert your secret keys before using old secret keys -with recent versions of GnuPG. - -The upgrade strategy is described in /usr/doc/gnupg/NEWS.gz, please -refer to it for more details, but it requires an old copy of the gpg -and gpgm binaries. They may be on your system as gpg.old and -gpgm.old, but if they're not you can find gnupg 0.3.2 source and -binaries for i386, m68k, alpha, powerpc and hurd-i386 at: - - - --- -James Troup , Horsforth, UK -Sun, 1 Oct 2000 13:53:12 +0100 - diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 8d33a87ae..000000000 --- a/debian/changelog +++ /dev/null @@ -1,402 +0,0 @@ -gnupg (1.0.5-1) unstable; urgency=low - - * New upstream version. - * debian/README.Debian: fix spelling and update URL. - * debian/rules (binary): remove the new info files. - * scripts/config.{guess,sub}: sync with subversions, closes: #95729. - - -- James Troup Mon, 30 Apr 2001 02:12:38 +0100 - -gnupg (1.0.4-4) unstable; urgency=low - - * po/ru.po: patch by Ilya Martynov to replace German - entries and add missing translations, closes: #93987. - * g10/revoke.c (ask_revocation_reason): typo fix (s/non longer/no - longer/g); noticed by Colin Watson , closes: - #93664. - - * Deprecated depreciated; noticed by Vincent Broman - . - - * Following two patches are from Vincent Broman. - * g10/mainproc.c (proc_tree): use iobuf_get_real_fname() in preference - to iobuf_get_fname(). - * g10/openfile.c (open_sigfile): handle .sign prefixed files correctly. - - -- James Troup Fri, 20 Apr 2001 23:32:44 +0100 - -gnupg (1.0.4-3) unstable; urgency=medium - - * debian/rules (binary): make gpg binary suid, closes: #86433. - * debian/postinst: don't use suidregister. - * debian/postrm: removed (only called suidunregister). - * debian/control: conflict with suidmanager << 0.50. - * mpi/longlong.h: apply fix for ARM long long artimetic from Philip - Blundell , closes: #87487. - * debian/preinst: the old GnuPG debs have moved to people.debian.org. - * cipher/random.c: #include as well as - * g10/misc.c: likewise. - * debian/rules: define a strip alias which removes the .comment and - .note sections. - * debian/rules (binary-arch): use it. - * debian/lintian.override: new file; override the SUID warning from - lintian. - * debian/rules (binary-arch): install it. - - -- James Troup Sun, 25 Feb 2001 05:24:58 +0000 - -gnupg (1.0.4-2) stable unstable; urgency=high - - * Apply security fix patch from Werner. - * Apply another patch from Werner to fix bogus warning on Rijndael - usage. - * Change section to 'non-US'. - - -- James Troup Mon, 12 Feb 2001 07:47:02 +0000 - -gnupg (1.0.4-1) stable unstable; urgency=high - - * New upstream version. - * Fixes a serious bug which could lead to false signature verification - results when more than one signature is fed to gpg. - - -- James Troup Tue, 17 Oct 2000 17:26:17 +0100 - -gnupg (1.0.3b-1) unstable; urgency=low - - * New upstream snapshot version. - - -- James Troup Fri, 13 Oct 2000 18:08:14 +0100 - -gnupg (1.0.3-2) unstable; urgency=low - - * debian/control: Conflict, Replace and Provide gpg-rsa & gpg-rsaref. - Fix long description to reflect the fact that RSA is no longer - patented and now included. [#72177] - * debian/rules: move faq.html to /usr/share/doc/gnupg/ and remove FAQ - from /usr/share/gnupg/. Thanks to Robert Luberda - for noticing. [#72151] - * debian/control: Suggest new package gnupg-doc. [#64323, #65560] - * utils/secmem.c (lock_pool): don't bomb out if mlock() returns ENOMEM, - as Linux will do this if resource limits (or other reasons) prevent - memory from being locked, instead treat it like permission was denied - and warn but continue. Thanks to Topi Miettinen - . [#70446] - * g10/hkp.c (not_implemented): s/ist/is/ in error message. - * debian/README.Debian: add a note about GDBM support and why it is - disabled. Upstream already fixed the manpage. [#65913] - * debian/rules (binary-arch): fix the Spanish translation to be 'es' not - 'es_ES' at Nicols Lichtmaier 's request. [#57314] - - -- James Troup Sun, 1 Oct 2000 14:55:03 +0100 - -gnupg (1.0.3-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Mon, 18 Sep 2000 15:56:54 +0100 - -gnupg (1.0.2-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Thu, 13 Jul 2000 20:26:50 +0100 - -gnupg (1.0.1-2) unstable; urgency=low - - * debian/control (Build-Depends): added. - * debian/copyright: corrected location of copyright file. Removed - references to Linux. Removed warnings about beta nature of GnuPG. - * debian/rules (binary-arch): install documentation into - /usr/share/doc/gnupg/ and pass mandir to make install to ensure the - manpages go to /usr/share/man/. - * debian/postinst: create /usr/doc/gnupg symlink. - * debian/prerm: new file; remove /usr/doc/gnupg symlink. - * debian/rules (binary-arch): install prerm. - * debian/control (Standards-Version): updated to 3.1.1.1. - - -- James Troup Thu, 30 Dec 1999 16:16:49 +0000 - -gnupg (1.0.1-1) unstable; urgency=low - - * New upstream version. - * doc/gpg.1: updated to something usable from - ftp://ftp.gnupg.org/pub/gcrypt/gnupg/gpg.1.gz. - - -- James Troup Sun, 19 Dec 1999 23:47:10 +0000 - -gnupg (1.0.0-3) unstable; urgency=low - - * debian/rules (build): remove the stunningly ill-advised --host option - to configure. [#44698, #48212, #48281] - - -- James Troup Tue, 26 Oct 1999 01:12:59 +0100 - -gnupg (1.0.0-2) unstable; urgency=low - - * debian/rules (binary-arch): fix the permissions on the - modules. [#47280] - * debian/postinst, debian/postrm: fix the package name passed to - suidregister. [#45013] - * debian/control: update long description. [#44636] - * debian/rules (build): pass the host explicitly to configure to avoid - problems on sparc64. [(Should fix) #44698]. - - -- James Troup Wed, 20 Oct 1999 23:39:05 +0100 - -gnupg (1.0.0-1) unstable; urgency=low - - * New upstream release. [#44545] - - -- James Troup Wed, 8 Sep 1999 00:53:02 +0100 - -gnupg (0.9.10-2) unstable; urgency=low - - * debian/rules (binary-arch): install lspgpot. Requested by Kai - Henningsen . [#42288] - * debian/rules (binary-arch): correct the path where modules are looked - for. Reported by Karl M. Hegbloom . [#40881] - * debian/postinst, debian/postrm: under protest, register gpg the - package with suidmanager and make it suid by default. - [#29780,#32590,#40391] - - -- James Troup Tue, 10 Aug 1999 00:12:40 +0100 - -gnupg (0.9.10-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Fri, 6 Aug 1999 01:16:21 +0100 - -gnupg (0.9.9-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Sun, 25 Jul 1999 01:06:31 +0100 - -gnupg (0.9.8-1) unstable; urgency=low - - * New upstream version. - * debian/rules (binary-arch): don't create a gpgm manpage as the binary - no longer exists. Noticed by Wichert Akkerman - . [#38864] - - -- James Troup Sun, 27 Jun 1999 01:07:58 +0100 - -gnupg (0.9.7-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Tue, 25 May 1999 13:23:24 +0100 - -gnupg (0.9.6-1) unstable; urgency=low - - * New upstream version. - * debian/copyright: update version number, noticed by Lazarus Long - . - * debian/control (Depends): depend on makedev (>= 2.3.1-13) to ensure - that /dev/urandom exists; reported by Steffen Markert - . [#32076] - - -- James Troup Tue, 11 May 1999 21:06:27 +0100 - -gnupg (0.9.5-1) unstable; urgency=low - - * New upstream version. - * debian/control (Description): no tabs. [Lintian] - - -- James Troup Wed, 24 Mar 1999 22:37:40 +0000 - -gnupg (0.9.4-1) unstable; urgency=low - - * New version. - * debian/control: s/GNUPG/GnuPG/ - - -- Werner Koch Mon, 8 Mar 1999 19:58:28 +0100 - -gnupg (0.9.3-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Mon, 22 Feb 1999 22:55:04 +0000 - -gnupg (0.9.2-1) unstable; urgency=low - - * New version. - * debian/rules (build): Removed CFLAGS as the default is now sufficient. - * debian/rules (clean): remove special handling cleanup in intl. - - -- Werner Koch Wed, 20 Jan 1999 21:23:11 +0100 - -gnupg (0.9.1-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Sat, 9 Jan 1999 22:29:11 +0000 - -gnupg (0.9.0-1) unstable; urgency=low - - * New upstream version. - * g10/armor.c (armor_filter): add missing new line in comment string; as - noticed by Stainless Steel Rat . - - -- James Troup Tue, 29 Dec 1998 20:22:43 +0000 - -gnupg (0.4.5-1) unstable; urgency=low - - * New upstream version. - * debian/rules (clean): force removal of intl/libintl.h which the - Makefiles fail to remove properly. - - -- James Troup Tue, 8 Dec 1998 22:40:23 +0000 - -gnupg (0.4.4-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Sat, 21 Nov 1998 01:34:29 +0000 - -gnupg (0.4.3-1) unstable; urgency=low - - * New upstream version. - * debian/README.Debian: new file; contains same information as is in the - preinst. Suggested by Wichert Akkerman . - * debian/rules (binary-arch): install `README.Debian' - * debian/control (Standards-Version): updated to 2.5.0.0. - - -- James Troup Sun, 8 Nov 1998 19:08:12 +0000 - -gnupg (0.4.2-1) unstable; urgency=low - - * New upstream version. - * debian/preinst: improve message about the NEWS file which isn't - actually installed when it's referred to, thanks to Martin Mitchell - . - * debian/rules (binary-arch): don't install the now non-existent `rfcs', - but do install `OpenPGP'. - - -- James Troup Sun, 18 Oct 1998 22:48:34 +0100 - -gnupg (0.4.1-1) unstable; urgency=low - - * New upstream version. - * debian/rules (binary-arch): fix the gpgm manpage symlink now installed - by `make install'. - - -- James Troup Sun, 11 Oct 1998 17:01:21 +0100 - -gnupg (0.4.0-1) unstable; urgency=high - - * New upstream version. [#26717] - * debian/copyright: tone down warning about alpha nature of gnupg. - * debian/copyright: new maintainer address. - * debian/control: update extended description. - * debian/rules (binary-arch): install FAQ and all ChangeLogs. - * debian/preinst: new; check for upgrade from (<= 0.3.2-1) and warn about - incompatibilities in keyring format and offer to move old copy out of - gpg out of the way for transition strategy and inform the user about - the old copies of gnupg available on my web page. - * debian/rules (binary-arch) install preinst. - * debian/rules (binary-arch): don't depend on the test target as it is - now partially interactive (tries to generate a key, which requires - someone else to be using the computer). - - -- James Troup Thu, 8 Oct 1998 00:47:07 +0100 - -gnupg (0.3.2-1) unstable; urgency=low - - * New upstream version. - * debian/control (Maintainer): new address. - * debian/copyright: updated list of changes. - - -- James Troup Thu, 9 Jul 1998 21:06:07 +0200 - -gnupg (0.3.1-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Tue, 7 Jul 1998 00:26:21 +0200 - -gnupg (0.3.0-2) unstable; urgency=low - - * Applied bug-fix patch from Werner. - - -- James Troup Fri, 26 Jun 1998 12:18:29 +0200 - -gnupg (0.3.0-1) unstable; urgency=low - - * New upstream version. - * debian/control: rewrote short and long description. - * cipher/Makefile.am: link tiger with -lc. - * debian/rules (binary-arch): strip loadable modules. - * util/secmem.c (lock_pool): get rid of errant test code; fix from - Werner Koch . - * debian/rules (test): new target which runs gnupg's test suite. - binary-arch depends on it, to ensure it's run whenever the package is - built. - - -- James Troup Thu, 25 Jun 1998 16:04:57 +0200 - -gnupg (0.2.19-1) unstable; urgency=low - - * New upstream version. - * debian/control: Updated long description. - - -- James Troup Sat, 30 May 1998 12:12:35 +0200 - -gnupg (0.2.18-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Sat, 16 May 1998 11:52:47 +0200 - -gnupg (0.2.17-1) unstable; urgency=high - - * New upstream version. - * debian/control (Standards-Version): updated to 2.4.1.0. - * debian/control: tone down warning about alpha nature of gnupg, as per - README. - * debian/copyright: ditto. - - -- James Troup Mon, 4 May 1998 22:36:51 +0200 - -gnupg (0.2.15-1) unstable; urgency=high - - * New upstream version. - - -- James Troup Fri, 10 Apr 1998 01:12:20 +0100 - -gnupg (0.2.13-1) unstable; urgency=high - - * New upstream version. - - -- James Troup Wed, 11 Mar 1998 01:52:51 +0000 - -gnupg (0.2.12-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Sat, 7 Mar 1998 13:52:40 +0000 - -gnupg (0.2.11-1) unstable; urgency=low - - * New upstream version. - - -- James Troup Wed, 4 Mar 1998 01:32:12 +0000 - -gnupg (0.2.10-1) unstable; urgency=low - - * New upstream version. - * Name changed upstream. - - -- James Troup Mon, 2 Mar 1998 07:32:05 +0000 - -g10 (0.2.7-1) unstable; urgency=low - - * Initial release. - - -- James Troup Fri, 20 Feb 1998 02:05:34 +0000 - -Local variables: -mode: debian-changelog -End: diff --git a/debian/control b/debian/control deleted file mode 100644 index 5b158daf5..000000000 --- a/debian/control +++ /dev/null @@ -1,24 +0,0 @@ -Source: gnupg -Section: non-US -Priority: optional -Maintainer: James Troup -Standards-Version: 3.1.1.1 -Build-Depends: gettext, libgdbmg1-dev, libz-dev - -Package: gnupg -Architecture: any -Depends: ${shlibs:Depends}, makedev (>= 2.3.1-13) -Suggests: gnupg-doc -Conflicts: gpg-rsa, gpg-rsaref, suidmanager (<< 0.50) -Replaces: gpg-rsa, gpg-rsaref -Provides: gpg-rsa, gpg-rsaref -Description: GNU privacy guard - a free PGP replacement. - GnuPG is GNU's tool for secure communication and data storage. - It can be used to encrypt data and to create digital signatures. - It includes an advanced key management facility and is compliant - with the proposed OpenPGP Internet standard as described in RFC2440. - . - GnuPG does not use use any patented algorithms so it cannot be - compatible with PGP2 because it uses IDEA (which is patented - worldwide) and RSA. RSA's patent expired on the 20th September 2000, - and it is now included in GnuPG. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index e5d99f688..000000000 --- a/debian/copyright +++ /dev/null @@ -1,29 +0,0 @@ -This is Debian GNU's prepackaged version of GnuPG, a free PGP -replacement. - -This package was put together by me, James Troup , -from the sources, which I obtained from -ftp://ftp.gnupg.org/pub/gcrypt/gnupg/gnupg-1.0.5.tar.gz. The changes -were minimal, namely: - -- adding support for the Debian package maintenance scheme, by adding - various debian/* files. - -Program Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -Modifications for Debian Copyright (C) 1998, 1999, 2000, 2001 James Troup. - -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, 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 with -your Debian GNU system, in /usr/share/common-licenses/GPL, or with the -Debian GNU gnupg source package as the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place, Suite 330, -Boston, MA 02111-1307, USA. diff --git a/debian/distfiles b/debian/distfiles deleted file mode 100644 index f7f226104..000000000 --- a/debian/distfiles +++ /dev/null @@ -1,6 +0,0 @@ -README.Debian -changelog -control -copyright -preinst -rules diff --git a/debian/lintian.override b/debian/lintian.override deleted file mode 100644 index c35ed27b3..000000000 --- a/debian/lintian.override +++ /dev/null @@ -1 +0,0 @@ -gnupg: setuid-binary usr/bin/gpg 4755 root/root diff --git a/debian/preinst b/debian/preinst deleted file mode 100644 index 607944c7c..000000000 --- a/debian/preinst +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh - -set -e - -case "$1" in - upgrade|install) - # Try to gracefully handle upgrades from a pre-0.3.3 version - - if [ ! -z $2 ]; then - set +e - dpkg --compare-versions $2 \<= 0.3.2-1 - result=$? - set -e - if [ $result = 0 ]; then - cat < debian/tmp/usr/bin/lspgpot - chmod 755 debian/tmp/usr/bin/lspgpot - $(STRIP) --strip-unneeded debian/tmp/usr/lib/gnupg/* - # In response to #53714... no idea if it's correct, will check with upstream - mv debian/tmp/usr/share/locale/es_ES debian/tmp/usr/share/locale/es - sed -e "s#/usr/local/#/usr/#" < debian/tmp/usr/share/man/man1/gpg.1 \ - > debian/tmp/usr/share/man/man1/gpg.1.new - mv debian/tmp/usr/share/man/man1/gpg.1.new debian/tmp/usr/share/man/man1/gpg.1 - gzip -9v debian/tmp/usr/share/man/man1/* - # Remove from /usr/share/gnupg that we install into /usr/share/doc/gnupg/ - rm debian/tmp/usr/share/gnupg/FAQ debian/tmp/usr/share/gnupg/faq.html - install -d debian/tmp/usr/share/doc/gnupg/ - install -m 644 debian/changelog debian/tmp/usr/share/doc/gnupg/changelog.Debian - install -m 644 debian/README.Debian README NEWS THANKS TODO doc/DETAILS \ - doc/FAQ doc/faq.html doc/OpenPGP debian/tmp/usr/share/doc/gnupg/ - for i in po util mpi cipher tools g10 checks include; do \ - install -m 644 $$i/ChangeLog debian/tmp/usr/share/doc/gnupg/changelog.$$i; done - install -m 644 ChangeLog debian/tmp/usr/share/doc/gnupg/changelog.toplevel - gzip -9v debian/tmp/usr/share/doc/gnupg/* - ln -s changelog.g10.gz debian/tmp/usr/share/doc/gnupg/changelog.gz - install -m 644 debian/copyright debian/tmp/usr/share/doc/gnupg/ - install -d debian/tmp/usr/share/lintian/overrides/ - install -m 644 debian/lintian.override debian/tmp/usr/share/lintian/overrides/gnupg - dpkg-shlibdeps g10/gpg - dpkg-gencontrol -isp - chown -R root.root debian/tmp - chmod -R go=rX debian/tmp - dpkg --build debian/tmp .. - -define checkdir - test -f g10/g10.c -a -f debian/rules -endef - -# Below here is fairly generic really - -binary: binary-indep binary-arch - -checkroot: - $(checkdir) - test root = "`whoami`" - -.PHONY: binary binary-arch binary-indep clean checkroot diff --git a/doc/ChangeLog b/doc/ChangeLog deleted file mode 100644 index 7c200a409..000000000 --- a/doc/ChangeLog +++ /dev/null @@ -1,500 +0,0 @@ -2002-10-12 Werner Koch - - * DETAILS (KEY_CREATED): Enhanced by fingerprint. - -2002-10-03 David Shaw - - * gpg.sgml: Note that '#' means secret-key-unavailable, and that - keyserver schemes are case-insensitive. - -2002-09-30 David Shaw - - * gpg.sgml: Note that --pgp2 disables --textmode when encrypting. - -2002-09-20 David Shaw - - * gpg.sgml: Some minor language cleanup. - -2002-09-20 Werner Koch - - * DETAILS: s/XORed/ORed/. - -2002-09-15 Werner Koch - - * gpg.sgml: Add rebuild-keydb-caches. - -2002-09-12 David Shaw - - * DETAILS: Fix batch key generation example. - -2002-09-11 Werner Koch - - * Makefile.am (EXTRA_DIST): Include gnupg-32.reg - -2002-09-02 Werner Koch - - * gpg.sgml: Updated the charset option. - - * DETAILS: Added status IMPORT_OK. - - * gnupg.7: New mini man page. - -2002-08-30 David Shaw - - * gpg.sgml: Document keyserver-option include-subkeys. Note that - honor-http-proxy is a keyserver-option now. - - * DETAILS: Add "Key not trusted" to INV_RECP status code. - -2002-08-23 Werner Koch - - * faq.raw: Updated. New Maintainer is David D. Scribner. - -2002-08-22 David Shaw - - * gpg.sgml: Clarify meaning of keyserver option include-revoked. - -2002-08-21 Werner Koch - - * DETAILS: Added IMPORT_PROBLEM. - -2002-08-20 David Shaw - - * DETAILS: Clarify that trust letters 'q' and '-' can be treated - identically. - - * gpg.sgml: Document --ignore-mdc-error. - -2002-08-06 David Shaw - - * gpg.sgml: Clarify that only long-form options can go in the - config file. - -2002-08-06 Werner Koch - - * gpg.sgml: Fixed doc regarding the name change of the option - file. - -2002-07-30 David Shaw - - * gpg.sgml: Clarify --edit/addrevoker (sensitive), and - --keyserver-options (--import/export-options may be used as well). - Document --import-options and --export-options with their various - options. --show-photos now works during signature verification as - well. Document --exec-path. Note in --simple-sk-checksum that - the passphrase must be changed for this to take effect. Note that - --pgp7 does not disable MDC. Document --no-mdc-warning. - -2002-07-25 Werner Koch - - * gpg.sgml: Document new --delete behaviour. - -2002-07-25 David Shaw - - * gpg.sgml: Clarify the differences between "pref" and "showpref". - Note in "setpref" that a list of available algorithms can be - printed with "gpg -v --version". Note in "updpref" that we don't - select keys via attribute uids, so preferences there will be - ignored. - -2002-07-01 David Shaw - - * gpg.sgml: Clarify "group". - -2002-07-01 Werner Koch - - * Makefile.am: Due to problems with VPATH builds we don't try to - build the texi vesions of the manual pages anymore automatically. - -2002-06-30 Werner Koch - - * README.W32: Adjusted some descriptions. Fixed the regsitry - entry descriptions. - -2002-06-21 David Shaw - - * DETAILS: Document "uat". - - * gpg.sgml: Document - --personal-{compress|digest|compress}-preferences, --group, and - add comments to --expert. - -2002-06-17 Werner Koch - - * gpg.sgml: Grammar fix. - -2002-06-03 David Shaw - - * DETAILS: Details of ATTRIBUTE. - - * gpg.sgml: Document --attribute-fd - -2002-06-03 Timo Schulz - - * DETAILS: Add ATTRIBUTE. - -2002-05-31 David Shaw - - * gpg.sgml: Add "edit/addrevoker". Document --desig-revoke. Note - that -z and --compress are the same option. Note that - --digest-algo can no longer violate OpenPGP with a non-160 bit - hash with DSA. Document --cert-digest-algo with suitable warnings - not to use it. Note the default s2k-cipher-algo is now CAST5. - Note that --force-v3-sigs overrides --ask-sig-expire. Revise - --expert documentation, as it is now definitely legal to have more - than one photo ID on a key. --preference-list is now - --default-preference-list with the new meaning. Document - --personal-preference-list. - - * DETAILS: Document "Revoker" for batch key generation. - -2002-05-22 Werner Koch - - * gpg.sgml: sgml syntax fix. - -2002-05-12 Werner Koch - - * gpg.sgml: Fixed URL in the description section. - - * faq.raw: Minor typo fixes noted by kromJx@myrealbox.com. - -2002-05-11 Werner Koch - - * gpg.sgml: Typo fix. - -2002-05-07 David Shaw - - * gpg.sgml: Add entries for --sk-comments, --no-sk-comments, - --pgp7, and --no-pgp7. Fix --pgp2 and --pgp6: the proper name is - --escape-from-lines and not --escape-from. - -2002-04-30 Timo Schulz - - * gpg.sgml: Add an entry for --encrypt-files and --decrypt-files. - -2002-04-29 David Shaw - - * gpg.sgml: Fix minor error in --pgp6 documentation: it does not - imply --digest-algo MD5 - -2002-04-29 Werner Koch - - * samplekeys.asc: Added gnupg distribution key 57548DCD. - - * faq.raw: Inserted Douglas Calvert as new maintainer. Acknowledge - Nils. Add entry about trust packet parsing problems. - -2002-04-24 David Shaw - - * gpg.sgml: Add some documentation for - --edit/{addphoto|showphoto|nrsign|nrlsign}, and the difference - between %t and %T in photo viewer command lines. - -2002-04-23 Stefan Bellon - - * gpg.sgml: Moved options from section "COMMANDS" to - section "OPTIONS". - -2002-04-20 David Shaw - - * samplekeys.asc: Added 0x5B0358A2 - -2002-04-19 David Shaw - - * gpg.sgml: Add "%t" flag for photo IDs, a note about primary - having different meanings for photo and regular IDs, rename - --default-check-level to --default-cert-check-level, add - --auto-check-trustdb, and --pgp6. - - * DETAILS: Add EXPSIG, EXPKEYSIG, and KEYEXPIRED. Add notes to - SIGEXPIRED (deprecated), and VALIDSIG (added expiration date). - Add "Preferences" command to unattended key generation - instructions. Also fixed a few typos. - - * samplekeys.asc: new (added to EXTRA_DIST in Makefile.am as well) - -2002-01-31 Marcus Brinkmann - - * DETAILS: Fix a spelling error, correct IMPORTED_RES to IMPORT_RES, - correct INV_RECP (the second occurence) to NO_RECP. - -2002-04-03 David Shaw - - * gpg.sgml: auto-key-retrieve is a keyserver-option (noted by - Roger Sondermann). - -2002-03-27 David Shaw - - * gpg.sgml: --pgp2 also means --disable-mdc, --no-ask-sig-expire, - and --no-ask-cert-expire. It does not mean --no-force-v3-sigs - (noted by Timo). - -2002-03-27 David Shaw - - * gpg.sgml: Add a few notes about --pgp2 meaning MIT PGP 2.6.2, - and keyserver details about HKP and NAI HKP. - -2002-03-18 David Shaw - - * gpg.sgml: Change meaning of --allow-non-selfsigned-uid to match - change in code, and add --no-allow-non-selfsigned-uid. - -2002-03-13 Werner Koch - - * faq.raw: Due to a lack of time Nils can't serve anymore as a - maintainer. Removed his address and setup a generic address. - -2002-03-06 Werner Koch - - * gpg.sgml: Add an entry for --export-ownertrust. Suggested by - Bernhard Reiter. - -2002-01-26 Timo Schulz - - * gnupg-w32.reg: New. Registry file for W32 in registry format. - -2002-01-26 Werner Koch - - * gpg.sgml: A few words about --gpg-agent-info and GPG_AGENT_INFO. - -2002-01-25 Timo Schulz - - * README.W32: Modify the filename because now the .exe extension - is automatically added to the binary. - -2002-01-14 Werner Koch - - * gpg.sgml: Talk about PGP 5 and higher. - -2002-01-11 David Shaw - - * gpg.sgml: Added documentation for --{no-}ask-cert-expire, - --{no-}ask-sig-expire, and revise --expert (it doesn't switch on - the expiration prompt anymore) and --default-check-level (to be - clearer as to what makes a good key check before signing). - -2002-01-07 Werner Koch - - * DETAILS: Removed the comment that unattended key generation is - experimental. It is now a standard feature. - -2001-12-22 David Shaw - - * gpg.sgml: Fixed a few typos. - - * gpg.sgml: Added documentation for --show-photos, - --no-show-photos, --photo-viewer, --nrsign-key, - --default-check-level, --search-keys, --keyserver-options, - --show-notation, --no-show-notation, --show-policy-url, - --no-show-policy-url, --for-your-eyes-only, - --no-for-your-eyes-only, --pgp2, --no-pgp2, - --no-permission-warning, --expert, --no-expert. - -2001-10-31 Werner Koch - - * gpg.sgml: Add a remark on how to get the long key ID. Suggested - by Sebastian Klemke. - -2001-10-23 Werner Koch - - * gpg.sgml: Add missing tag. - -2001-09-28 Werner Koch - - * gpg.sgml: Add a note on option parsing. - -2001-09-24 Werner Koch - - * gpg.sgml: Described --{update,check}-trustdb. - -2001-09-03 Werner Koch - - * gpg.sgml, gpgv.sgml: Removed GDBM stuff. - -2001-08-29 Werner Koch - - * faq.raw: Described how to delete a secret key w/o a public key - and changed the entry on updating the preferences. - -2001-08-08 Werner Koch - - * gpg.sgml: Documented --print-mds and marked the --print-md * as - deprecated because it does not work in the W32 version. Suggested - by John Kane. - (WARNINGS): Typo fix. - (--with-colons): Clarified that the output is in UTF-8. - -2001-08-01 Werner Koch - - * gpg.sgml: Added --ignore-valid-from - -2001-04-20 Werner Koch - - * faq.raw (Maintained-by): Removed note that load-extension is not - available under Windoze. - - * gpg.sgml: Add new --charset UTF-8. - -2001-04-19 Werner Koch - - * faq.raw: Add a note about dates displayed as ????-??-??. - -2001-04-17 Werner Koch - - * Makefile.am (%.texi): Add rules to create .texi from .sgml. - However we can't automate this because automake does not like - .texi files as BUILT_SOURCES. - (%.dvi,%.ps): Removed these rules, because they are not needed - and get in the way of automake's dvi target - - * HACKING: Changed CVS description. - -2001-04-06 Werner Koch - - * gpg.sgml: Small typo fixes by Florian Weimer. - -2001-03-27 Werner Koch - - * gpg.sgml: Add --no-sig-cache and --no-sig-create-check. - -2001-03-23 Werner Koch - - * DETAILS: New status UNEXPECTED. - -2001-03-13 Werner Koch - - * gpg.sgml: Described --fixed-list-mode. - -2001-03-06 Werner Koch - - * gpgv.sgml: Changed some gpg to gpgv. Thanks to John A. Murdie. - -2001-03-03 Werner Koch - - * gpg.sgml: Tell something about the 0x12345678! key ID syntax. - -2001-01-18 Werner Koch - - * README.W32: Changed building instructions for MinGW32/CPD 0.3 - -2001-01-09 Werner Koch - - * DETAILS: Fixed docs for NEED_PASSPHRASE and added USERID_HINT. - -2000-11-30 Werner Koch - - * gpg.sgml: Fixed the description of --verify. Add a short note - the warnings sections. - -2000-10-19 Werner Koch - - * gpg.sgml: Fixed doc for --allow-non-selfsigned-uid. - Add entry for --ignore-crc-error. - -2000-10-18 Werner Koch - - * OpenPGP: Dropped the paragraph that RSA is not implemented. - -2000-10-14 Werner Koch - - * faq.raw: Add an answer to the problem of multiple signatures. - -Wed Oct 4 15:50:18 CEST 2000 Werner Koch - - * gpgv.sgml: New. - * Makefile.am: build it. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch - - * faq.raw: New. - * Makefile.am: Support to build FAQs - -Wed Jul 12 13:32:06 CEST 2000 Werner Koch - - * gpg.sgml: Add a note about the availability of the GPH. - -2000-07-03 13:59:24 Werner Koch (wk@habibti.openit.de) - - * DETAILS, FAQ: Typo fixes by Yosiaki IIDA. - -2000-05-12 10:57:21 Werner Koch (wk@habibti.openit.de) - - * gpg.sgml: Documented --no-tty. - -2000-03-09 15:01:51 Werner Koch (wk@habibti.openit.de) - - * DETAILS: Ad a short blurb about unattended key generation. - -Wed Feb 9 15:33:44 CET 2000 Werner Koch - - * gpg.sgml: Describe --ignore-time-conflict. - - * gpg.sgml: Fixed a few typos. Thanks to Holger Trapp. - -Wed Jan 5 11:51:17 CET 2000 Werner Koch - - * FAQ: Enhanced answer for the 3des-s2k bug. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch - - * gpg.sgml: Add section about the user ID - -Mon Nov 22 11:14:53 CET 1999 Werner Koch - - * gph: Removed the directory from the dist becuase it will - go into it's own package. - -Thu Sep 23 09:52:58 CEST 1999 Werner Koch - - * README.W32: New. - -Mon Sep 6 19:59:08 CEST 1999 Werner Koch - - - * Makefile.am (SUBDIRS): New subdir gph for the manual. - -Thu Jul 22 20:03:03 CEST 1999 Werner Koch - - - * gpg.sgml (--always-trust): Added. - -Wed Jul 14 19:42:08 CEST 1999 Werner Koch - - - * Makefile.am: Create a dummy man page if docbook-to-man is missing. - -Wed Jun 16 20:16:21 CEST 1999 Werner Koch - - - * gpg1.pod: Removed. - * gpg.sgml: New. Replaces the pod file - * Makefile.am: Add rule to make a man file from sgml - -Tue Jun 15 12:21:08 CEST 1999 Werner Koch - - - * Makefile.in.in: Use DESTDIR. - -Mon May 31 19:41:10 CEST 1999 Werner Koch - - * gpg.1pod: Enhanced the Bugs section (Michael). - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - - * gpg.1pod: Spelling and grammar corrections (John A. Martin) - * FAQ: Ditto. - * DETAILS: Ditto. - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/doc/DETAILS b/doc/DETAILS deleted file mode 100644 index 1ba9df159..000000000 --- a/doc/DETAILS +++ /dev/null @@ -1,990 +0,0 @@ - -Format of colon listings -======================== -First an example: - -$ gpg --fixed-list-mode --with-colons --list-keys \ - --with-fingerprint --with-fingerprint wk@gnupg.org - -pub:f:1024:17:6C7EE1B8621CC013:899817715:1055898235::m:::scESC: -fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013: -uid:f::::::::Werner Koch : -uid:f::::::::Werner Koch : -sub:f:1536:16:06AD222CADF6A6E1:919537416:1036177416:::::e: -fpr:::::::::CF8BCC4B18DE08FCD8A1615906AD222CADF6A6E1: -sub:r:1536:20:5CE086B5B5A18FF4:899817788:1025961788:::::esc: -fpr:::::::::AB059359A3B81F410FCFF97F5CE086B5B5A18FF4: - -The double --with-fingerprint prints the fingerprint for the subkeys -too, --fixed-list-mode is themodern listing way printing dates in -seconds since Epoch and does not merge the first userID with the pub -record. - - - 1. Field: Type of record - pub = public key - crt = X.509 certificate - crs = X.509 certificate and private key available - sub = subkey (secondary key) - sec = secret key - ssb = secret subkey (secondary key) - uid = user id (only field 10 is used). - uat = user attribute (same as user id except for field 10). - sig = signature - rev = revocation signature - fpr = fingerprint: (fingerprint is in field 10) - pkd = public key data (special field format, see below) - grp = reserved for gpgsm - rvk = revocation key - - 2. Field: A letter describing the calculated trust. This is a single - letter, but be prepared that additional information may follow - in some future versions. (not used for secret keys) - o = Unknown (this key is new to the system) - i = The key is invalid (e.g. due to a missing self-signature) - d = The key has been disabled - r = The key has been revoked - e = The key has expired - - = Unknown trust (i.e. no value assigned) - q = Undefined trust - '-' and 'q' may safely be treated as the same - value for most purposes - n = Don't trust this key at all - m = There is marginal trust in this key - f = The key is full trusted. - u = The key is ultimately trusted; this is only used for - keys for which the secret key is also available. - 3. Field: length of key in bits. - 4. Field: Algorithm: 1 = RSA - 16 = ElGamal (encrypt only) - 17 = DSA (sometimes called DH, sign only) - 20 = ElGamal (sign and encrypt) - (for other id's see include/cipher.h) - 5. Field: KeyID either of - 6. Field: Creation Date (in UTC) - 7. Field: Key expiration date or empty if none. - 8. Field: Used for serial number in crt records (used to be the Local-ID) - 9. Field: Ownertrust (primary public keys only) - This is a single letter, but be prepared that additional - information may follow in some future versions. -10. Field: User-ID. The value is quoted like a C string to avoid - control characters (the colon is quoted "\x3a"). - This is not used with --fixed-list-mode in gpg. - A UAT record puts the attribute subpacket count here, a - space, and then the total attribute subpacket size. - In gpgsm the issuer name comes here - An FPR record stores the fingerprint here. - The fingerprint of an revocation key is stored here. -11. Field: Signature class. This is a 2 digit hexnumber followed by - either the letter 'x' for an exportable signature or the - letter 'l' for a local-only signature. - The class byte of an revocation key is also given here, - 'x' and 'l' ist used the same way. -12. Field: Key capabilities: - e = encrypt - s = sign - c = certify - A key may have any combination of them. The primary key has in - addition to these letters, uppercase version of the letter to - denote the _usable_ capabilities of the entire key. -13. Field: Used in FPR records for S/MIME keys to store the fingerprint of - the issuer certificate. This is useful to build the - certificate path based on certificates stored in the local - keyDB; it is only filled if the issue certificate is - available. The advantage of using this value is that it is - guaranteed to have been been build by the same lookup - algorithm as gpgsm uses. - For "uid" recods this lists the preferences n the sameway the - -edit menu does. -14. Field Flag field used in the --edit menu output: - - -All dates are displayed in the format yyyy-mm-dd unless you use the -option --fixed-list-mode in which case they are displayed as seconds -since Epoch. More fields may be added later, so parsers should be -prepared for this. When parsing a number the parser should stop at the -first non-number character so that additional information can later be -added. - -If field 1 has the tag "pkd", a listing looks like this: -pkd:0:1024:B665B1435F4C2 .... FF26ABB: - ! ! !-- the value - ! !------ for information number of bits in the value - !--------- index (eg. DSA goes from 0 to 3: p,q,g,y) - - - -Format of the "--status-fd" output -================================== -Every line is prefixed with "[GNUPG:] ", followed by a keyword with -the type of the status line and a some arguments depending on the -type (maybe none); an application should always be prepared to see -more arguments in future versions. - - - GOODSIG - The signature with the keyid is good. For each signature only - one of the three codes GOODSIG, BADSIG or ERRSIG will be - emitted and they may be used as a marker for a new signature. - The username is the primary one encoded in UTF-8 and %XX - escaped. - - EXPSIG - The signature with the keyid is good, but the signature is - expired. The username is the primary one encoded in UTF-8 and - %XX escaped. - - EXPKEYSIG - The signature with the keyid is good, but the signature was - made by an expired key. The username is the primary one - encoded in UTF-8 and %XX escaped. - - BADSIG - The signature with the keyid has not been verified okay. - The username is the primary one encoded in UTF-8 and %XX - escaped. - - ERRSIG \ - - It was not possible to check the signature. This may be - caused by a missing public key or an unsupported algorithm. - A RC of 4 indicates unknown algorithm, a 9 indicates a missing - public key. The other fields give more information about - this signature. sig_class is a 2 byte hex-value. - - VALIDSIG - - - The signature with the keyid is good. This is the same - as GOODSIG but has the fingerprint as the argument. Both - status lines are emitted for a good signature. - sig-timestamp is the signature creation time in seconds after - the epoch. expire-timestamp is the signature expiration time - in seconds after the epoch (zero means "does not expire"). - - SIG_ID - This is emitted only for signatures of class 0 or 1 which - have been verified okay. The string is a signature id - and may be used in applications to detect replay attacks - of signed messages. Note that only DLP algorithms give - unique ids - others may yield duplicated ones when they - have been created in the same second. - - ENC_TO - The message is encrypted to this keyid. - keytype is the numerical value of the public key algorithm, - keylength is the length of the key or 0 if it is not known - (which is currently always the case). - - NODATA - No data has been found. Codes for what are: - 1 - No armored data. - 2 - Expected a packet but did not found one. - 3 - Invalid packet found, this may indicate a non OpenPGP message. - You may see more than one of these status lines. - - UNEXPECTED - Unexpected data has been encountered - 0 - not further specified 1 - - - TRUST_UNDEFINED - TRUST_NEVER - TRUST_MARGINAL - TRUST_FULLY - TRUST_ULTIMATE - For good signatures one of these status lines are emitted - to indicate how trustworthy the signature is. The error token - values are currently only emiited by gpgsm. - - SIGEXPIRED - This is deprecated in favor of KEYEXPIRED. - - KEYEXPIRED - The key has expired. expire-timestamp is the expiration time - in seconds after the epoch. - - KEYREVOKED - The used key has been revoked by its owner. No arguments yet. - - BADARMOR - The ASCII armor is corrupted. No arguments yet. - - RSA_OR_IDEA - The IDEA algorithms has been used in the data. A - program might want to fallback to another program to handle - the data if GnuPG failed. This status message used to be emitted - also for RSA but this has been dropped after the RSA patent expired. - However we can't change the name of the message. - - SHM_INFO - SHM_GET - SHM_GET_BOOL - SHM_GET_HIDDEN - - GET_BOOL - GET_LINE - GET_HIDDEN - GOT_IT - - NEED_PASSPHRASE - Issued whenever a passphrase is needed. - keytype is the numerical value of the public key algorithm - or 0 if this is not applicable, keylength is the length - of the key or 0 if it is not known (this is currently always the case). - - NEED_PASSPHRASE_SYM - Issued whenever a passphrase for symmetric encryption is needed. - - MISSING_PASSPHRASE - No passphrase was supplied. An application which encounters this - message may want to stop parsing immediately because the next message - will probably be a BAD_PASSPHRASE. However, if the application - is a wrapper around the key edit menu functionality it might not - make sense to stop parsing but simply ignoring the following - BAD_PASSPHRASE. - - BAD_PASSPHRASE - The supplied passphrase was wrong or not given. In the latter case - you may have seen a MISSING_PASSPHRASE. - - GOOD_PASSPHRASE - The supplied passphrase was good and the secret key material - is therefore usable. - - DECRYPTION_FAILED - The symmetric decryption failed - one reason could be a wrong - passphrase for a symmetrical encrypted message. - - DECRYPTION_OKAY - The decryption process succeeded. This means, that either the - correct secret key has been used or the correct passphrase - for a conventional encrypted message was given. The program - itself may return an errorcode because it may not be possible to - verify a signature for some reasons. - - NO_PUBKEY - NO_SECKEY - The key is not available - - IMPORTED - The keyid and name of the signature just imported - - IMPORT_OK [] - The key with the primary key's FINGERPRINT has been imported. - Reason flags: - 0 := Not actually changed - 1 := Entirely new key. - 2 := New user IDs - 4 := New signatures - 8 := New subkeys - 16 := Contains private key. - The flags may be ORed. - - IMPORT_PROBLEM [] - Issued for each import failure. Reason codes are: - 0 := "No specific reason given". - 1 := "Invalid Certificate". - 2 := "Issuer Certificate missing". - 3 := "Certificate Chain too long". - 4 := "Error storing certificate". - - IMPORT_RES - - Final statistics on import process (this is one long line) - - FILE_START - Start processing a file . indicates the performed - operation: - 1 - verify - 2 - encrypt - 3 - decrypt - - FILE_DONE - Marks the end of a file processing which has been started - by FILE_START. - - BEGIN_DECRYPTION - END_DECRYPTION - Mark the start and end of the actual decryption process. These - are also emitted when in --list-only mode. - - BEGIN_ENCRYPTION - END_ENCRYPTION - Mark the start and end of the actual encryption process. - - DELETE_PROBLEM reason_code - Deleting a key failed. Reason codes are: - 1 - No such key - 2 - Must delete secret key first - 3 - Ambigious specification - - PROGRESS what char cur total - Used by the primegen and Public key functions to indicate progress. - "char" is the character displayed with no --status-fd enabled, with - the linefeed replaced by an 'X'. "cur" is the current amount - done and "total" is amount to be done; a "total" of 0 indicates that - the total amount is not known. 100/100 may be used to detect the - end of operation. - - SIG_CREATED - A signature has been created using these parameters. - type: 'D' = detached - 'C' = cleartext - 'S' = standard - (only the first character should be checked) - class: 2 hex digits with the signature class - - KEY_CREATED - A key has been created - type: 'B' = primary and subkey - 'P' = primary - 'S' = subkey - The fingerprint is one of the primary key for type B and P and - the one of the subkey for S. - - SESSION_KEY : - The session key used to decrypt the message. This message will - only be emmited when the special option --show-session-key - is used. The format is suitable to be passed to the option - --override-session-key - - NOTATION_NAME - NOTATION_DATA - name and string are %XX escaped; the data may be splitted - among several notation_data lines. - - USERID_HINT - Give a hint about the user ID for a certain keyID. - - POLICY_URL - string is %XX escaped - - BEGIN_STREAM - END_STREAM - Issued by pipemode. - - INV_RECP - Issued for each unusable recipient. The reasons codes - currently in use are: - 0 := "No specific reason given". - 1 := "Not Found" - 2 := "Ambigious specification" - 3 := "Wrong key usage" - 4 := "Key revoked" - 5 := "Key expired" - 6 := "No CRL known" - 7 := "CRL too old" - 8 := "Policy mismatch" - 9 := "Not a secret key" - 10 := "Key not trusted" - - Note that this status is also used for gpgsm's SIGNER command - where it relates to signer's of course. - - NO_RECP - Issued when no recipients are usable. - - ALREADY_SIGNED - Warning: This is experimental and might be removed at any time. - - TRUNCATED - The output was truncated to MAXNO items. This status code is issued - for certain external requests - - ERROR - This is a generic error status message, it might be followed - by error location specific data. and - should not contain a space. - - ATTRIBUTE - - This is one long line issued for each attribute subpacket when - an attribute packet is seen during key listing. is the - fingerprint of the key. is the length of the - attribute subpacket. is the attribute type - (1==image). / indicates that this is the Nth - indexed subpacket of count total subpackets in this attribute - packet. and are from the - self-signature on the attribute packet. If the attribute - packet does not have a valid self-signature, then the - timestamp is 0. are a bitwise OR of: - 0x01 = this attribute packet is a primary uid - 0x02 = this attribute packet is revoked - 0x04 = this attribute packet is expired - - -Key generation -============== - Key generation shows progress by printing different characters to - stderr: - "." Last 10 Miller-Rabin tests failed - "+" Miller-Rabin test succeeded - "!" Reloading the pool with fresh prime numbers - "^" Checking a new value for the generator - "<" Size of one factor decreased - ">" Size of one factor increased - - The prime number for ElGamal is generated this way: - - 1) Make a prime number q of 160, 200, 240 bits (depending on the keysize) - 2) Select the length of the other prime factors to be at least the size - of q and calculate the number of prime factors needed - 3) Make a pool of prime numbers, each of the length determined in step 2 - 4) Get a new permutation out of the pool or continue with step 3 - if we have tested all permutations. - 5) Calculate a candidate prime p = 2 * q * p[1] * ... * p[n] + 1 - 6) Check that this prime has the correct length (this may change q if - it seems not to be possible to make a prime of the desired length) - 7) Check whether this is a prime using trial divisions and the - Miller-Rabin test. - 8) Continue with step 4 if we did not find a prime in step 7. - 9) Find a generator for that prime. - - This algorithm is based on Lim and Lee's suggestion from the - Crypto '97 proceedings p. 260. - - -Unattended key generation -========================= -This feature allows unattended generation of keys controlled by a -parameter file. To use this feature, you use --gen-key together with ---batch and feed the parameters either from stdin or from a file given -on the commandline. - -The format of this file is as follows: - o Text only, line length is limited to about 1000 chars. - o You must use UTF-8 encoding to specify non-ascii characters. - o Empty lines are ignored. - o Leading and trailing spaces are ignored. - o A hash sign as the first non white space character indicates a comment line. - o Control statements are indicated by a leading percent sign, the - arguments are separated by white space from the keyword. - o Parameters are specified by a keyword, followed by a colon. Arguments - are separated by white space. - o The first parameter must be "Key-Type", control statements - may be placed anywhere. - o Key generation takes place when either the end of the parameter file - is reached, the next "Key-Type" parameter is encountered or at the - control statement "%commit" - o Control statements: - %echo - Print . - %dry-run - Suppress actual key generation (useful for syntax checking). - %commit - Perform the key generation. An implicit commit is done - at the next "Key-Type" parameter. - %pubring - %secring - Do not write the key to the default or commandline given - keyring but to . This must be given before the first - commit to take place, duplicate specification of the same filename - is ignored, the last filename before a commit is used. - The filename is used until a new filename is used (at commit points) - and all keys are written to that file. If a new filename is given, - this file is created (and overwrites an existing one). - Both control statements must be given. - o The order of the parameters does not matter except for "Key-Type" - which must be the first parameter. The parameters are only for the - generated keyblock and parameters from previous key generations are not - used. Some syntactically checks may be performed. - The currently defined parameters are: - Key-Type: | - Starts a new parameter block by giving the type of the - primary key. The algorithm must be capable of signing. - This is a required parameter. - Key-Length: - Length of the key in bits. Default is 1024. - Key-Usage: - Space or comma delimited list of key usage, allowed values are - "encrypt" and "sign". This is used to generate the key flags. - Please make sure that the algorithm is capable of this usage. - Subkey-Type: | - This generates a secondary key. Currently only one subkey - can be handled. - Subkey-Length: - Length of the subkey in bits. Default is 1024. - Subkey-Usage: - Similar to Key-Usage. - Passphrase: - If you want to specify a passphrase for the secret key, - enter it here. Default is not to use any passphrase. - Name-Real: - Name-Comment: - Name-Email: - The 3 parts of a key. Remember to use UTF-8 here. - If you don't give any of them, no user ID is created. - Expire-Date: |([d|w|m|y]) - Set the expiration date for the key (and the subkey). It - may either be entered in ISO date format (2000-08-15) or as - number of days, weeks, month or years. Without a letter days - are assumed. - Preferences: - Set the cipher, hash, and compression preference values for - this key. This expects the same type of string as "setpref" - in the --edit menu. - Revoker: : [sensitive] - Add a designated revoker to the generated key. Algo is the - public key algorithm of the designated revoker (i.e. RSA=1, - DSA=17, etc.) Fpr is the fingerprint of the designated - revoker. The optional "sensitive" flag marks the designated - revoker as sensitive information. Only v4 keys may be - designated revokers. - -Here is an example: -$ cat >foo < -ssb 1024g/8F70E2C0 2000-03-09 - - - -Layout of the TrustDB -===================== -The TrustDB is built from fixed length records, where the first byte -describes the record type. All numeric values are stored in network -byte order. The length of each record is 40 bytes. The first record of -the DB is always of type 1 and this is the only record of this type. - -FIXME: The layout changed, document it here. - - Record type 0: - -------------- - Unused record, can be reused for any purpose. - - Record type 1: - -------------- - Version information for this TrustDB. This is always the first - record of the DB and the only one with type 1. - 1 byte value 1 - 3 bytes 'gpg' magic value - 1 byte Version of the TrustDB (2) - 1 byte marginals needed - 1 byte completes needed - 1 byte max_cert_depth - The three items are used to check whether the cached - validity value from the dir record can be used. - 1 u32 locked flags - 1 u32 timestamp of trustdb creation - 1 u32 timestamp of last modification which may affect the validity - of keys in the trustdb. This value is checked against the - validity timestamp in the dir records. - 1 u32 timestamp of last validation - (Used to keep track of the time, when this TrustDB was checked - against the pubring) - 1 u32 record number of keyhashtable - 1 u32 first free record - 1 u32 record number of shadow directory hash table - It does not make sense to combine this table with the key table - because the keyid is not in every case a part of the fingerprint. - 1 u32 record number of the trusthashtbale - - - Record type 2: (directory record) - -------------- - Informations about a public key certificate. - These are static values which are never changed without user interaction. - - 1 byte value 2 - 1 byte reserved - 1 u32 LID . (This is simply the record number of this record.) - 1 u32 List of key-records (the first one is the primary key) - 1 u32 List of uid-records - 1 u32 cache record - 1 byte ownertrust - 1 byte dirflag - 1 byte maximum validity of all the user ids - 1 u32 time of last validity check. - 1 u32 Must check when this time has been reached. - (0 = no check required) - - - Record type 3: (key record) - -------------- - Informations about a primary public key. - (This is mainly used to lookup a trust record) - - 1 byte value 3 - 1 byte reserved - 1 u32 LID - 1 u32 next - next key record - 7 bytes reserved - 1 byte keyflags - 1 byte pubkey algorithm - 1 byte length of the fingerprint (in bytes) - 20 bytes fingerprint of the public key - (This is the value we use to identify a key) - - Record type 4: (uid record) - -------------- - Informations about a userid - We do not store the userid but the hash value of the userid because that - is sufficient. - - 1 byte value 4 - 1 byte reserved - 1 u32 LID points to the directory record. - 1 u32 next next userid - 1 u32 pointer to preference record - 1 u32 siglist list of valid signatures - 1 byte uidflags - 1 byte validity of the key calculated over this user id - 20 bytes ripemd160 hash of the username. - - - Record type 5: (pref record) - -------------- - This record type is not anymore used. - - 1 byte value 5 - 1 byte reserved - 1 u32 LID; points to the directory record (and not to the uid record!). - (or 0 for standard preference record) - 1 u32 next - 30 byte preference data - - Record type 6 (sigrec) - ------------- - Used to keep track of key signatures. Self-signatures are not - stored. If a public key is not in the DB, the signature points to - a shadow dir record, which in turn has a list of records which - might be interested in this key (and the signature record here - is one). - - 1 byte value 6 - 1 byte reserved - 1 u32 LID points back to the dir record - 1 u32 next next sigrec of this uid or 0 to indicate the - last sigrec. - 6 times - 1 u32 Local_id of signatures dir or shadow dir record - 1 byte Flag: Bit 0 = checked: Bit 1 is valid (we have a real - directory record for this) - 1 = valid is set (but may be revoked) - - - - Record type 8: (shadow directory record) - -------------- - This record is used to reserve a LID for a public key. We - need this to create the sig records of other keys, even if we - do not yet have the public key of the signature. - This record (the record number to be more precise) will be reused - as the dir record when we import the real public key. - - 1 byte value 8 - 1 byte reserved - 1 u32 LID (This is simply the record number of this record.) - 2 u32 keyid - 1 byte pubkey algorithm - 3 byte reserved - 1 u32 hintlist A list of records which have references to - this key. This is used for fast access to - signature records which are not yet checked. - Note, that this is only a hint and the actual records - may not anymore hold signature records for that key - but that the code cares about this. - 18 byte reserved - - - - Record Type 10 (hash table) - -------------- - Due to the fact that we use fingerprints to lookup keys, we can - implement quick access by some simple hash methods, and avoid - the overhead of gdbm. A property of fingerprints is that they can be - used directly as hash values. (They can be considered as strong - random numbers.) - What we use is a dynamic multilevel architecture, which combines - hashtables, record lists, and linked lists. - - This record is a hashtable of 256 entries; a special property - is that all these records are stored consecutively to make one - big table. The hash value is simple the 1st, 2nd, ... byte of - the fingerprint (depending on the indirection level). - - When used to hash shadow directory records, a different table is used - and indexed by the keyid. - - 1 byte value 10 - 1 byte reserved - n u32 recnum; n depends on the record length: - n = (reclen-2)/4 which yields 9 for the current record length - of 40 bytes. - - the total number of such record which makes up the table is: - m = (256+n-1) / n - which is 29 for a record length of 40. - - To look up a key we use the first byte of the fingerprint to get - the recnum from this hashtable and look up the addressed record: - - If this record is another hashtable, we use 2nd byte - to index this hash table and so on. - - if this record is a hashlist, we walk all entries - until we found one a matching one. - - if this record is a key record, we compare the - fingerprint and to decide whether it is the requested key; - - - Record type 11 (hash list) - -------------- - see hash table for an explanation. - This is also used for other purposes. - - 1 byte value 11 - 1 byte reserved - 1 u32 next next hash list record - n times n = (reclen-5)/5 - 1 u32 recnum - - For the current record length of 40, n is 7 - - - - Record type 254 (free record) - --------------- - All these records form a linked list of unused records. - 1 byte value 254 - 1 byte reserved (0) - 1 u32 next_free - - - -Packet Headers -=============== - -GNUPG uses PGP 2 packet headers and also understands OpenPGP packet header. -There is one enhancement used with the old style packet headers: - - CTB bits 10, the "packet-length length bits", have values listed in - the following table: - - 00 - 1-byte packet-length field - 01 - 2-byte packet-length field - 10 - 4-byte packet-length field - 11 - no packet length supplied, unknown packet length - - As indicated in this table, depending on the packet-length length - bits, the remaining 1, 2, 4, or 0 bytes of the packet structure field - are a "packet-length field". The packet-length field is a whole - number field. The value of the packet-length field is defined to be - the value of the whole number field. - - A value of 11 is currently used in one place: on compressed data. - That is, a compressed data block currently looks like , - where , binary 10 1000 11, is an indefinite-length packet. The - proper interpretation is "until the end of the enclosing structure", - although it should never appear outermost (where the enclosing - structure is a file). - -+ This will be changed with another version, where the new meaning of -+ the value 11 (see below) will also take place. -+ -+ A value of 11 for other packets enables a special length encoding, -+ which is used in case, where the length of the following packet can -+ not be determined prior to writing the packet; especially this will -+ be used if large amounts of data are processed in filter mode. -+ -+ It works like this: After the CTB (with a length field of 11) a -+ marker field is used, which gives the length of the following datablock. -+ This is a simple 2 byte field (MSB first) containing the amount of data -+ following this field, not including this length field. After this datablock -+ another length field follows, which gives the size of the next datablock. -+ A value of 0 indicates the end of the packet. The maximum size of a -+ data block is limited to 65534, thereby reserving a value of 0xffff for -+ future extensions. These length markers must be inserted into the data -+ stream just before writing the data out. -+ -+ This 2 byte field is large enough, because the application must buffer -+ this amount of data to prepend the length marker before writing it out. -+ Data block sizes larger than about 32k doesn't make any sense. Note -+ that this may also be used for compressed data streams, but we must use -+ another packet version to tell the application that it can not assume, -+ that this is the last packet. - - -GNU extensions to the S2K algorithm -=================================== -S2K mode 101 is used to identify these extensions. -After the hash algorithm the 3 bytes "GNU" are used to make -clear that these are extensions for GNU, the next bytes gives the -GNU protection mode - 1000. Defined modes are: - 1001 - do not store the secret part at all - - -Usage of gdbm files for keyrings -================================ - The key to store the keyblock is its fingerprint, other records - are used for secondary keys. Fingerprints are always 20 bytes - where 16 bit fingerprints are appended with zero. - The first byte of the key gives some information on the type of the - key. - 1 = key is a 20 bit fingerprint (16 bytes fpr are padded with zeroes) - data is the keyblock - 2 = key is the complete 8 byte keyid - data is a list of 20 byte fingerprints - 3 = key is the short 4 byte keyid - data is a list of 20 byte fingerprints - 4 = key is the email address - data is a list of 20 byte fingerprints - - Data is prepended with a type byte: - 1 = keyblock - 2 = list of 20 byte padded fingerprints - 3 = list of list fingerprints (but how to we key them?) - - - -Pipemode -======== -This mode can be used to perform multiple operations with one call to -gpg. It comes handy in cases where you have to verify a lot of -signatures. Currently we support only detached signatures. This mode -is a kludge to avoid running gpg n daemon mode and using Unix Domain -Sockets to pass the data to it. There is no easy portable way to do -this under Windows, so we use plain old pipes which do work well under -Windows. Because there is no way to signal multiple EOFs in a pipe we -have to embed control commands in the data stream: We distinguish -between a data state and a control state. Initially the system is in -data state but it won't accept any data. Instead it waits for -transition to control state which is done by sending a single '@' -character. While in control state the control command os expected and -this command is just a single byte after which the system falls back -to data state (but does not necesary accept data now). The simplest -control command is a '@' which just inserts this character into the -data stream. - -Here is the format we use for detached signatures: -"@<" - Begin of new stream -"@B" - Detached signature follows. - This emits a control packet (1,'B') - -"@t" - Signed text follows. - This emits the control packet (2, 'B') - -"@." - End of operation. The final control packet forces signature - verification -"@>" - End of stream - - - - - - -Other Notes -=========== - * For packet version 3 we calculate the keyids this way: - RSA := low 64 bits of n - ELGAMAL := build a v3 pubkey packet (with CTB 0x99) and calculate - a rmd160 hash value from it. This is used as the - fingerprint and the low 64 bits are the keyid. - - * Revocation certificates consist only of the signature packet; - "import" knows how to handle this. The rationale behind it is - to keep them small. - - - - - - - -Keyserver Message Format -========================= - -The keyserver may be contacted by a Unix Domain socket or via TCP. - -The format of a request is: - -==== -command-tag -"Content-length:" digits -CRLF -======= - -Where command-tag is - -NOOP -GET -PUT -DELETE - - -The format of a response is: - -====== -"GNUPG/1.0" status-code status-text -"Content-length:" digits -CRLF -============ -followed by bytes of data - - -Status codes are: - - o 1xx: Informational - Request received, continuing process - - o 2xx: Success - The action was successfully received, understood, - and accepted - - o 4xx: Client Error - The request contains bad syntax or cannot be - fulfilled - - o 5xx: Server Error - The server failed to fulfill an apparently - valid request - - - -Documentation on HKP (the http keyserver protocol): - -A minimalistic HTTP server on port 11371 recognizes a GET for /pks/lookup. -The standard http URL encoded query parameters are this (always key=value): - -- op=index (like pgp -kv), op=vindex (like pgp -kvv) and op=get (like - pgp -kxa) - -- search=. This is a list of words that must occur in the key. - The words are delimited with space, points, @ and so on. The delimiters - are not searched for and the order of the words doesn't matter (but see - next option). - -- exact=on. This switch tells the hkp server to only report exact matching - keys back. In this case the order and the "delimiters" are important. - -- fingerprint=on. Also reports the fingerprints when used with 'index' or - 'vindex' - -The keyserver also recognizes http-POSTs to /pks/add. Use this to upload -keys. - - -A better way to do this would be a request like: - - /pks/lookup/?op= - -This can be implemented using Hurd's translator mechanism. -However, I think the whole key server stuff has to be re-thought; -I have some ideas and probably create a white paper. - diff --git a/doc/HACKING b/doc/HACKING deleted file mode 100644 index 811179e53..000000000 --- a/doc/HACKING +++ /dev/null @@ -1,301 +0,0 @@ - A Hacker's Guide to GNUPG - ================================ - (Some notes on GNUPG internals.) - - - ===> Under construction <======= - - -CVS Access -========== -Anonymous read-only CVS access is available: - - cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg login - -use the password "anoncvs". To check out the the complete -archive use: - - cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg \ - checkout -R STABLE-BRANCH-1-0 gnupg - -This service is provided to help you in hunting bugs and not to deliver -stable snapshots; it may happen that it even does not compile, so please -don't complain. CVS may put a high load on a server, so please don't poll -poll for new updates but wait for an announcement; to receive this you may -want to subscribe to: - - gnupg-commit-watchers@gnupg.org - -by sending a mail with subject "subscribe" to - - gnupg-commit-watchers-request@gnupg.org - - -You must run scripts/autogen.sh before doing the ./configure, -as this creates some needed while which are not in the CVS. -autogen.sh should checks that you have all required tools -installed. - - -RSYNC access -============ -The FTP archive is also available by anonymous rsync. A daily snapshot -of the CVS head revision is also available. See rsync(1) and try -"rsync ftp.gnupg.org::" to see available resources. - - - -Special Tools -============= -Documentation is based on the docbook DTD. Actually we have only the -man page for now. To build a man page you need the docbook-to-man -tool and all the other thinks needed for SGML processing. Debian -comes with the docbook tools and you only need this docbook-to-man -script which is comes with gtk-doc or download it from -ftp.openit.de:/pub/devel/sgml. If you don't have it everything -should still work fine but you will have only a dummy man page. - - -RFCs -==== - -1423 Privacy Enhancement for Internet Electronic Mail: - Part III: Algorithms, Modes, and Identifiers. - -1489 Registration of a Cyrillic Character Set. - -1750 Randomness Recommendations for Security. - -1991 PGP Message Exchange Formats. - -2015 MIME Security with Pretty Good Privacy (PGP). - -2144 The CAST-128 Encryption Algorithm. - -2279 UTF-8, a transformation format of ISO 10646. - -2440 OpenPGP. - - - -Debug Flags ------------ -Use the option "--debug n" to output debug information. This option -can be used multiple times, all values are ORed; n maybe prefixed with -0x to use hex-values. - - value used for - ----- ---------------------------------------------- - 1 packet reading/writing - 2 MPI details - 4 ciphers and primes (may reveal sensitive data) - 8 iobuf filter functions - 16 iobuf stuff - 32 memory allocation stuff - 64 caching - 128 show memory statistics at exit - 256 trust verification stuff - - - - -Directory Layout ----------------- - ./ Readme, configure - ./scripts Scripts needed by configure and others - ./doc Documentation - ./util General purpose utility function - ./mpi Multi precision integer library - ./cipher Cryptographic functions - ./g10 GnuPG application - ./tools Some helper and demo programs - ./keybox The keybox library (under construction) - ./gcrypt Stuff needed to build libgcrypt (under construction) - - -Detailed Roadmap ----------------- -g10/g10.c Main module with option parsing and all the stuff you have - to do on startup. Also has the exout handler and some - helper functions. -g10/sign.c Create signature and optionally encrypt - -g10/parse-packet.c -g10/build-packet.c -g10/free-packet.c - Parsing and creating of OpenPGP message packets. - -g10/getkey.c Key selection code -g10/pkclist.c Build a list of public keys -g10/skclist.c Build a list of secret keys -g10/ringedit.c Keyring I/O -g10/keydb.h - -g10/keyid.c Helper functions to get the keyid, fingerprint etc. - - -g10/trustdb.c -g10/trustdb.h -g10/tdbdump.c - Management of the trustdb.gpg - -g10/compress.c Filter to handle compression -g10/filter.h Declarations for all filter functions -g10/delkey.c Delete a key -g10/kbnode.c Helper for the KBNODE linked list -g10/main.h Prototypes and some constants -g10/mainproc.c Message processing -g10/armor.c Ascii armor filter -g10/mdfilter.c Filter to calculate hashs -g10/textfilter.c Filter to handle CR/LF and trailing white space -g10/cipher.c En-/Decryption filter -g10/misc.c Utlity functions -g10/options.h Structure with all the command line options - and related constants -g10/openfile.c Create/Open Files -g10/tdbio.c I/O handling for the trustdb.gpg -g10/tdbio.h -g10/hkp.h Keyserver access -g10/hkp.c -g10/packet.h Defintion of OpenPGP structures. -g10/passphrase.c Passphrase handling code -g10/pubkey-enc.c -g10/seckey-cert.c -g10/seskey.c -g10/import.c -g10/export.c -g10/comment.c -g10/status.c -g10/status.h -g10/sign.c -g10/plaintext.c -g10/encr-data.c -g10/encode.c -g10/revoke.c -g10/keylist.c -g10/sig-check.c -g10/signal.c -g10/helptext.c -g10/verify.c -g10/decrypt.c -g10/keyedit.c -g10/dearmor.c -g10/keygen.c - - - -Memory allocation ------------------ -Use only the functions: - - m_alloc() - m_alloc_clear() - m_strdup() - m_free() - -If you want to store a passphrase or some other sensitive data you may -want to use m_alloc_secure() instead of m_alloc(), as this puts the data -into a memory region which is protected from swapping (on some platforms). -m_free() works for both. This functions will not return if there is not -enough memory available. - - - -Logging -------- - - - - - - -Option parsing ---------------- -GNUPG does not use getopt or GNU getopt but functions of it's own. See -util/argparse.c for details. The advantage of these functions is that -it is more easy to display and maintain the help texts for the options. -The same option table is also used to parse resource files. - - - -What is an IOBUF ----------------- -This is the data structure used for most I/O of gnupg. It is similar -to System V Streams but much simpler. Because OpenPGP messages are nested -in different ways; the use of such a system has big advantages. Here is -an example, how it works: If the parser sees a packet header with a partial -length, it pushes the block_filter onto the IOBUF to handle these partial -length packets: from now on you don't have to worry about this. When it sees -a compressed packet it pushes the uncompress filter and the next read byte -is one which has already been uncompressed by this filter. Same goes for -enciphered packet, plaintext packets and so on. The file g10/encode.c -might be a good staring point to see how it is used - actually this is -the other way: constructing messages using pushed filters but it may be -easier to understand. - - -How to use the message digest functions ---------------------------------------- -cipher/md.c implements an interface to hash (message digest functions). - -a) If you have a common part of data and some variable parts - and you need to hash of the concatenated parts, you can use this: - md = md_open(...) - md_write( md, common_part ) - md1 = md_copy( md ) - md_write(md1, part1) - md_final(md1); - digest1 = md_read(md1) - md2 = md_copy( md ) - md_write(md2, part2) - md_final(md2); - digest2 = md_read(md2) - - An example are key signatures; the key packet is the common part - and the user-id packets are the variable parts. - -b) If you need a running digest you should use this: - md = md_open(...) - md_write( md, part1 ) - digest_of_part1 = md_digest( md ); - md_write( md, part2 ) - digest_of_part1_cat_part2 = md_digest( md ); - .... - -Both methods may be combined. [Please see the source for the real syntax] - - - - -How to use the cipher functions -------------------------------- -cipher/cipher.c implements the interface to symmetric encryption functions. -As usual you have a function to open a cipher (which returns a handle to be used -with all other functions), some functions to set the key and other stuff and -a encrypt and decrypt function which does the real work. You probably know -how to work with files - so it should really be easy to work with these -functions. Here is an example: - - CIPHER_HANDLE hd; - - hd = cipher_open( CIPHER_ALGO_TWOFISH, CIPHER_MODE_CFB, 0 ); - if( !hd ) - oops( use other function to check for the real error ); - rc = cipher_setkey( hd, key256bit, 32 ) ) - if( rc ) - oops( weak key or something like this ); - cipher_setiv( hd, some_IV_or_NULL_for_all_zeroes ); - cipher_encrypt( hd, plain, cipher, size ); - cipher_close( hd ); - - - -How to use the public key functions ------------------------------------ -cipher/pubkey.c implements the interface to asymmetric encryption and -signature functions. This is basically the same as with the symmetric -counterparts, but due to their nature it is a little bit more complicated. - - [Give an example] - - diff --git a/doc/OpenPGP b/doc/OpenPGP deleted file mode 100644 index a511ad7fd..000000000 --- a/doc/OpenPGP +++ /dev/null @@ -1,108 +0,0 @@ - GnuPG and OpenPGP - ================= - - See RFC2440 for a description of OpenPGP. We have an annotated version - of this RFC online: http://www.gnupg.org/rfc2440.html - - - - Compatibility Notes - =================== - GnuPG (>=1.0.3) is in compliance with RFC2440 despite these exceptions: - - * (9.2) states that IDEA SHOULD be implemented. This is not done - due to patent problems. - - - All MAY features are implemented with this exception: - - * multi-part armored messages are not supported. - MIME (rfc2015) should be used instead. - - Most of the OPTIONAL stuff is implemented. - - There are a couple of options which can be used to override some - RFC requirements. This is always mentioned with the description - of that options. - - A special format of partial packet length exists for v3 packets - which can be considered to be in compliance with RFC1991; this - format is only created if a special option is active. - - GnuPG uses a S2K mode of 101 for GNU extensions to the secret key - protection algorithms. This number is not defined in OpenPGP, but - given the fact that this number is in a range which used at many - other places in OpenPGP for private/experimenat algorithm identifiers, - this should be not a so bad choice. The 3 bytes "GNU" are used - to identify this as a GNU extension - see the file DETAILS for a - definition of the used data formats. - - - - Some Notes on OpenPGP / PGP Compatibility: - ========================================== - - * PGP 5.x does not accept V4 signatures for anything other than - key material. The GnuPG option --force-v3-sigs mimics this - behavior. - - * PGP 5.x does not recognize the "five-octet" lengths in - new-format headers or in signature subpacket lengths. - - * PGP 5.0 rejects an encrypted session key if the keylength - differs from the S2K symmetric algorithm. This is a bug in its - validation function. - - * PGP 5.0 does not handle multiple one-pass signature headers and - trailers. Signing one will compress the one-pass signed literal - and prefix a V3 signature instead of doing a nested one-pass - signature. - - * When exporting a private key, PGP 2.x generates the header - "BEGIN PGP SECRET KEY BLOCK" instead of "BEGIN PGP PRIVATE KEY - BLOCK". All previous versions ignore the implied data type, and - look directly at the packet data type. - - * In a clear-signed signature, PGP 5.0 will figure out the correct - hash algorithm if there is no "Hash:" header, but it will reject - a mismatch between the header and the actual algorithm used. The - "standard" (i.e. Zimmermann/Finney/et al.) version of PGP 2.x - rejects the "Hash:" header and assumes MD5. There are a number - of enhanced variants of PGP 2.6.x that have been modified for - SHA-1 signatures. - - * PGP 5.0 can read an RSA key in V4 format, but can only recognize - it with a V3 keyid, and can properly use only a V3 format RSA - key. - - * Neither PGP 5.x nor PGP 6.0 recognize ElGamal Encrypt and Sign - keys. They only handle ElGamal Encrypt-only keys. - - - Parts of this document are taken from: - ====================================== - - OpenPGP Message Format - draft-ietf-openpgp-formats-07.txt - - - Copyright 1998 by The Internet Society. All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph - are included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - diff --git a/doc/README.W32 b/doc/README.W32 deleted file mode 100644 index 61aa05f0e..000000000 --- a/doc/README.W32 +++ /dev/null @@ -1,100 +0,0 @@ -This is a binary version of GnuPG for MS-Windows 95, 98, WNT and W2000. - -A FAQ comes with this package and a probably more recent one can be -found online at http://www.gnupg.org/faq.html. See -http://www.gnupg.org/docs-mls.html for a list of mailing lists. In -particular the list gnupg-users@gnupg.org might be useful to answer -questions - but please read the FAQ first. - -Installation instructions: --------------------------- - 1. Unpack the ZIP archive (alright, you already did this). - 2. Copy "gpg.exe" and "gpgv.exe" to some place where you - usually store your binaries. - 3. Create a directory "c:\gnupg" (or any other as you like) - 4. If you did not use the default directory "c:\gnupg", you - should enter a string with the directory into the Registry - under the key: - HKEY_CURRENT_USER -> Software -> GNU -> GnuPG - (you probably need to create the keys GNU and GnuPG) and insert a - new string under the name "HomeDir" with the value of the default - directory you want to use. Please use forward slashes and not the - backslashes when setting filenames for GnuPG into the Registry. - 5. Enter "gpg" and see what happens - 6. Read the file README and the online HOWTOs - - -Internationalization support: ------------------------------ - 1. Decide where to store the translation files for your language. - Here we assume the directory "c:/gnu/locale/fr" - - 2. Set the directory with the translations into the Registry under - the key: - HKEY_CURRENT_USER -> Control Panel -> Mingw32 -> NLS - (you probably need to create the keys Mingw32 and NLS) using a string - entry with the name "MoDir". - 3. Select which language to use and copy the currect translation file - under the name "gnupg.mo" into the directory set in step 2 - (Example: "copy fr.mo c:\gnu\locale\fr\gnupg.mo") - 4. Done. - -Currently we only support the Codepages 437, 850 und Latin1. If you have -problems, either delete the gnupg.mo file or don't set the environment -variable - - - -How to build it from the source: --------------------------------- -This version has been build with the Mingw32/CPD kit using the latest -stable version of GnuPG. - -First get the source: It has to be available at the same location you -found this binary package - if not you should have received a written -offer to get the source delivered to you See the file COPYING (section -3) for details. - -If you got this package from its canonical place (ftp.gnupg.org), the -source is available at: - - ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-1.2.n.tar.gz - -or for development snapshots - - ftp://ftp.gnupg.org/gcrypt/alpha/gnupg/gnupg-1.x.n.tar.gz - -this is the same source as for the Unix version. If your binary -version of GnuPG is called something like gnupg-w32-1.0.4-1.zip, you -should find a patch file named gnupg-w32-1.0.4-1.0.4-1.diff.gz at the -same location, which has to be applied to the stock gpg source file. -Instructions are at the top of this file. - -To build it, you need the MingW32/CPD kit, which is available at - - ftp://ftp.gnupg.org/people/werner/cpd/mingw32-cpd-0.3.0.tar.gz - ftp://ftp.gnupg.org/people/werner/cpd/gcc-core-2.95.2.tar.gz - ftp://ftp.gnupg.org/people/werner/cpd/binutils-2.9.1.tar.gz - -gcc and binutils are stock GNU source which are available -at every GNU mirror. - -After you have installed this environment you should be able to do this: - - $ scripts/autogen.sh --build-w32 - $ make - $ mingw32 strip g10/gpg.exe - $ cp g10/gpg.exe /some_windows_drive/ - -And everything hopefully works. - - -Don't forget that MS-Windows ist just a temporary workaround until -you can switch to a GNU system ;-) - -Be the source always with you. - - Werner - - - diff --git a/doc/credits-1.0 b/doc/credits-1.0 deleted file mode 100644 index 977910652..000000000 --- a/doc/credits-1.0 +++ /dev/null @@ -1,41 +0,0 @@ -The GNU Privacy Guard has been created by the GnuPG team: -Matthew Skala, Michael Roth, Niklas Hernaeus, Rmi Guyomarch -and Werner Koch. Gael Queri, Gregory Steuck, Janusz A. Urbanowicz, -Marco d'Itri, Thiago Jung Bauermann, Urko Lusa and Walter Koch -did the official translations. Mike Ashley is working on the -GNU Privacy Handbook. - -The following people helped greatly by suggesting improvements, -testing, fixing bugs, providing resources and doing other important -tasks: Allan Clark, Anand Kumria, Ariel T Glenn, Bodo Moeller, -Bryan Fullerton, Brian Moore, Brian Warner, Caskey L. Dickson, -Cees van de Griend, Charles Levert, Christian von Roques, -Christopher Oliver, Christian Recktenwald, Daniel Eisenbud, -Daniel Koenig, David Ellement, Detlef Lannert, Dirk Lattermann, -Ed Boraas, Enzo Michelangeli, Ernst Molitor, Fabio Coatti, -Felix von Leitner, Frank Heckenbach, Frank Stajano, Gal Quri, -Greg Louis, Greg Troxel, Gregory Steuck, Geoff Keating, Harald Denker, -Hendrik Buschkamp, Holger Schurig, Hugh Daniel, Ian McKellar, -Janusz A. Urbanowicz, James Troup, Jean-loup Gailly, Jens Bachem, -Joachim Backes, John A. Martin, Johnny Teveen, Jrg Schilling, -Jun Kuriyama, Karl Fogel, Karsten Thygesen, Katsuhiro Kondou, -Kazu Yamamoto, Lars Kellogg-Stedman, Marco d'Itri, Mark Adler, -Mark Elbrecht, Markus Friedl, Martin Kahlert, Martin Hamilton, -Martin Schulte, Matthew Skala, Max Valianskiy, Michael Roth, -Michael Sobolev, Nicolas Graner, NIIBE Yutaka, Niklas Hernaeus, -Nimrod Zimerman, N J Doye, Oliver Haakert, Oskari Jskelinen, -Paul D. Smith, Philippe Laliberte, Peter Gutmann, QingLong, -Ralph Gillen, Rat, Reinhard Wobst, Rmi Guyomarch, Reuben Sumner, -Roland Rosenfeld, Ross Golder, Serge Munhoven, SL Baur, Stefan Karrmann, -Stefan Keller, Steffen Ullrich, Steffen Zahn, Steven Bakker, -Susanne Schultz, Thiago Jung Bauermann, Thomas Roessler, Tom Spindler, -Tom Zerucha, Tomas Fasth, Thomas Mikkelsen, Ulf Mller, Urko Lusa, -Walter Koch, Wim Vandeputte 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. - diff --git a/doc/faq.raw b/doc/faq.raw deleted file mode 100644 index ec4212326..000000000 --- a/doc/faq.raw +++ /dev/null @@ -1,1019 +0,0 @@ -[$htmltitle=GnuPG FAQ] -[$sfaqheader=The GnuPG FAQ says:] -[$sfaqfooter= -The most recent version of the FAQ is available from - -] -[$usenetheader= -] -[$maintainer=David D. Scribner, ] -[$hGPG=http://www.gnupg.org] - -[H body bgcolor=#ffffff text=#000000 link=#1f00ff alink=#ff0000 vlink=#9900dd] -[H H1]GnuPG Frequently Asked Questions[H /H1] - - -[H p] -Version: 1.5.7[H br] -Last-Modified: Aug 21, 2002[H br] -Maintained-by: [$maintainer] -[H /p] - - -This is the GnuPG FAQ. The latest HTML version is available -[H a href=[$hGPG]/faq.html]here[H/a]. - -The index is generated automatically, so there may be errors here. Not -all questions may be in the section they belong to. Suggestions about -how to improve the structure of this FAQ are welcome. - -Please send additions and corrections to the maintainer. It would be -most convenient if you could provide the answer to be included here -as well. Your help is very much appreciated. - -Please, don't send message like "This should be a FAQ - what's the answer?". -If it hasn't been asked before, it isn't a FAQ. In that case you could -search in the mailing list archive. - -[H HR] - -[H HR] - - - GENERAL - - What is GnuPG? - - [H a href=[$hGPG]]GnuPG[H /a] stands for GNU Privacy Guard and - is GNU's tool for secure communication and data storage. It can be - used to encrypt data and to create digital signatures. It includes - an advanced key management facility and is compliant with the - proposed OpenPGP Internet standard as described in [H a href=http://www.gnupg.org/rfc2440.html]RFC 2440[H/a]. - As such, it is aimed to be compatible with PGP from NAI, Inc. - - Is GnuPG compatible with PGP? - - In general, yes. GnuPG and newer PGP releases should be implementing - the OpenPGP standard. But there are some interoperability - problems. See question for details. - - - SOURCES of INFORMATION - - Where can I find more information? - - Here's a list of on-line resources: - - [H UL] - [H LI]The documentation page is located at [H a href=[$hGPG]/docs.html]<[$hGPG]/docs.html>[H/a]. - Have a look at the HOWTOs and the GNU Privacy Handbook (GPH, available - in English, Spanish and Russian). The latter provides a detailed user's - guide to GnuPG. You'll also find a document about how to convert from - PGP 2.x to GnuPG. - - [H LI]On [H a href=http://lists.gnupg.org][H/a] you'll find an online archive of the - GnuPG mailing lists. Most interesting should be gnupg-users for all - user-related issues and gnupg-devel if you want to get in touch with - the developers. - - In addition, searchable archives can be found on MARC, e.g.: [H br] - GnuPG-users: [H a href=http://marc.theaimsgroup.com/?l=gnupg-users&r=1&w=2][H/a],[H br] - GnuPG-devel: [H a href=http://marc.theaimsgroup.com/?l=gnupg-devel&r=1&w=2][H/a].[H br] - - [H B]PLEASE:[H/B] - Before posting to a list, read this FAQ and the available - documentation. In addition, search the list archive - maybe your - question has already been discussed. This way you help people focus - on topics that have not yet been resolved. - - [H LI]The GnuPG source distribution contains a subdirectory: - - [H PRE] - ./doc - [H /PRE] - - where some additional documentation is located (mainly interesting - for hackers, not the casual user). - [H /UL] - - Where do I get GnuPG? - - You can download the GNU Privacy Guard from its primary FTP server - [H a href=ftp://ftp.gnupg.org/pub/gcrypt]ftp.gnupg.org[H /a] or from one of the mirrors: - - [H a href=[$hGPG]/mirrors.html] - <[$hGPG]/mirror.html> - [H /a] - - The current version is 1.0.4, please upgrade to this version as it - fixes a security bug regarding the verification of multiple signatures. - - - INSTALLATION - - Which OSes does GnuPG run on? - - It should run on most Unices as well as Windows 95 and Windows NT. A - list of OSes reported to be OK is presented at: - - [H a href=http://www.gnupg.org/backend.html#supsys] - - [H /a] - - Which random gatherer should I use? - - "Good" random numbers are crucial for the security of your encryption. - Different operating systems provide a variety of more or less quality - random data. Linux and *BSD provide kernel generated random data - through /dev/random - this should be the preferred choice on these - systems. Also Solaris users with the SUNWski package installed have - a /dev/random. In these cases, use the configure option: - - [H pre] - --enable-static-rnd=linux - [H/pre] - - In addition, there's also the kernel random device by Andi Maier - [H a href= http://www.cosy.sbg.ac.at/~andi][H /a], but it's still beta. Use at your - own risk! - - On other systems, the Entropy Gathering Daemon (EGD) is a good choice. - It is a perl-daemon that monitors system activity and hashes it into - random data. See the download page [H a href=http://www.gnupg.org/download.html][H /a] - to obtain egd. Use: - - [H pre] - --enable-static-rnd=egd - [H/pre] - - here. - - If the above options do not work, you can use the random number - generator "unix". This is [H B]very[H /B] slow and should be avoiced. The - random quality isn't very good so don't use it on sensitive data. - - - How do I include support for RSA and IDEA? - - RSA is included as of GnuPG 1.0.3. - - The official GnuPG distribution does not contain IDEA due to a - patent restriction. The patent does not expire before 2007 so don't - expect official support before then. - - However, there is an unofficial module to include it even - in earlier versions of GnuPG. It's available from - [H a href=ftp://ftp.gnupg.org/pub/gcrypt/contrib/][H /a]. Look for: - - [H pre] - idea.c - [H /pre] - - Compilation directives are in the headers of these files. Then add - the following line to your ~/.gnupg/options: - - [H pre] - load-extension idea - [H /pre] - - - USAGE - - What is the recommended key size? - - 1024 bit for DSA signatures; even for plain ElGamal signatures - this is sufficient as the size of the hash is probably the weakest - link if the key size is larger than 1024 bits. Encryption keys may - have greater sizes, but you should then check the fingerprint of - this key: - - [H pre] - gpg --fingerprint - [H /pre] - - As for the key algorithms, you should stick with the default (i.e., - DSA signature and ElGamal encryption). A ElGamal signing key has the - following disadvantages: the signature is larger, it is hard to - create such a key useful for signatures which can withstand some - real world attacks, you don't get any extra security compared to - DSA, and there might be compatibility problems with certain PGP - versions. It has only been introduced because at the time it was - not clear whether there was a patent on DSA. - - Why does it sometimes take so long to create keys? - - The problem here is that we need a lot of random bytes and for that - we (on Linux the /dev/random device) must collect some random data. - It is really not easy to fill the Linux internal entropy buffer; I - talked to Ted Ts'o and he commented that the best way to fill the - buffer is to play with your keyboard. Good security has its price. - What I do is to hit several times on the shift, control, alternate, - and caps lock keys, because these keys do not produce output to the - screen. This way you get your keys really fast (it's the same thing - PGP2 does). - - Another problem might be another program which eats up your random - bytes (a program (look at your daemons) that reads from /dev/random). - - And it really takes long when I work on a remote system. Why? - - Don't do this at all! You should never create keys or even use GnuPG - on a remote system because you normally have no physical control - over your secret key ring (which is in most cases vulnerable to - advanced dictionary attacks) - I strongly encourage everyone to only - create keys on a local computer (a disconnected laptop is probably - the best choice) and if you need it on your connected box (I know: - We all do this) be sure to have a strong password for your account - and for your secret key and that you can trust your system - administrator. - - When I check GnuPG on a remote system via ssh (I have no Alpha here - ;-) I have the same problem. It takes a *very* long time to create - the keys, so I use a special option, --quick-random, to generate - insecure keys which are only good for some tests. - - What is the difference between options and commands? - - If you do a 'gpg --help', you will get two separate lists. The first - is a list of commands. The second is a list of options. Whenever you - run GPG, you [H B]must[H /B] pick exactly one command (with one exception, - see below). You [H B]may[H /B] pick one or more options. The command should, - just by convention, come at the end of the argument list, after all - the options. If the command takes a file (all the basic ones do), - the filename comes at the very end. So the basic way to run gpg is: - - [H pre] - gpg [--option something] [--option2] [--option3 something] --command file - [H/pre] - - Some options take arguments. For example, the --output option (which - can be abbreviated -o) is an option that takes a filename. The - option's argument must follow immediately after the option itself, - otherwise gpg doesn't know which option the argument is supposed to - go with. As an option, --output and its filename must come before - the command. The --recipient (-r) option takes a name or keyid to - encrypt the message to, which must come right after the -r argument. - The --encrypt (or -e) command comes after all the options followed - by the file you wish to encrypt. So use: - - [H pre] - gpg -r alice -o secret.txt -e test.txt - [H/pre] - - If you write the options out in full, it is easier to read: - - [H pre] - gpg --recipient alice --output secret.txt --encrypt test.txt - [H/pre] - - If you're saving it in a file called ".txt" then you'd probably - expect to see ASCII-armored text in there, so you need to add the - --armor (-a) option, which doesn't take any arguments: - - [H pre] - gpg --armor --recipient alice --output secret.txt --encrypt test.txt - [H/pre] - - If you imagine square brackets around the optional parts, it becomes - a bit clearer: - - [H pre] - gpg [--armor] [--recipient alice] [--output secret.txt] --encrypt test.txt - [H/pre] - - The optional parts can be rearranged any way you want: - - [H pre] - gpg --output secret.txt --recipient alice --armor --encrypt test.txt - [H/pre] - - If your filename begins with a hyphen (e.g. "-a.txt"), GnuPG assumes - this is an option and may complain. To avoid this you have either - to use "./-a.txt" or stop the option and command processing with two - hyphens: "-- -a.txt". [H B]The exception:[H /B] signing and encrypting at the - same time. Use: - - [H pre] - gpg [--options] --sign --encrypt foo.txt - [H/pre] - - I can't delete a user ID because it is already deleted on my public - keyring? - - Because you can only select from the public key ring, there is no - direct way to do this. However it is not very complicated to do - anyway. Create a new user ID with exactly the same name and you - will see that there are now two identical user IDs on the secret - ring. Now select this user ID and delete it. Both user IDs will be - removed from the secret ring. - - I can't delete the secret key because my public key disappeared? - - To select a key a search is always done on the public keyring, - therefore it is not possible to select an secret key without - having the public key. Normally it shoud never happen that the - public key got lost but the secret key is still available. The - reality is different, so GnuPG implements a special way to deal - with it: Simply use the long keyid which can be obtained by using - the --with-colons options (it is the fifth field in the lines - beginning with "sec"). - - What are trust, validity and ownertrust? - - "ownertrust" is used instead of "trust" to make clear that this is - the value you have assigned to a key to express how much you trust - the owner of this key to correctly sign (and so introduce) other - keys. "validity", or calculated trust, is a value which says how - much GnuPG thinks a key is valid (that it really belongs to the one - who claims to be the owner of the key). For more see the chapter - "The Web of Trust" in the Manual. - - How do I sign a patch file? - - Use "gpg --clearsign --not-dash-escaped ...". The problem with - --clearsign is that all lines starting with a dash are quoted with - "- "; obviously diff produces many lines starting with a dash and - these are then quoted and that is not good for a patch ;-). To use a - patch file without removing the cleartext signature, the special - option --not-dash-escaped may be used to suppress generation of - these escape sequences. You should not mail such a patch because - spaces and line endings are also subject to the signature and a - mailer may not preserve these. If you want to mail a file you can - simply sign it using your MUA. - - Where is the "encrypt-to-self" option? - - Use "--encrypt-to your_keyid". You can use more than one of these - options. To temporarily override the use of this additional key, - you can use the option "--no-encrypt-to". - - How can I get rid of the Version and Comment headers in armored - messages? - - Use "--no-version --comment ''". Note that the left over blank line - is required by the protocol. - - What does the "You are using the xxxx character set." mean? - - This note is printed when UTF8 mapping has to be done. Make sure - that the displayed charset is the one you have activated on your - system. Since "iso-8859-1" is the charset most used, this is the - default. You can change the charset with the option "--charset". - It is important that your active character set matches the one - displayed - if not, restrict yourself to plain 7 bit ASCII and no - mapping has to be done. - - How can a get list of key IDs used to encrypt a message? - - [H pre] - gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \ - awk '/^\[GNUPG:\] ENC_TO / { print $3 }' - [H /pre] - - I can't decrypt my symmetrical only (-c) encrypted message with - a new version of GnuPG. - - There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES - or Twofish has been used for symmetric only encryption (this has - never been the default). The bug has been fixed but to enable you - to decrypt old messages, you should run gpg with the option - "--emulate-3des-s2k-bug", decrypt the message and encrypt it again - without this option. The option will be removed in 1.1, so better - re-encrypt your message now. - - How can I use GnuPG in an automated environment? - - You should use the option --batch and don't use pass phrases as - there is usually no way to store it more secure than the secret - keyring itself. The suggested way to create the keys for the - automated environment is: - - On a secure machine: - [H OL] - [H LI] If you want to do automatic signing, create a signing - subkey for your key (edit menu, choose "addkey" and the DSA). - [H LI] Make sure that you use a passphrase (needed by the current - implementation). - [H LI] gpg --export-secret-subkeys --no-comment foo >secring.auto - [H LI] Copy secring.auto and the public keyring to a test directory. - [H LI] Change to this directory. - [H LI] gpg --homedir . --edit foo and use "passwd" to remove the - passphrase from the subkeys. You may also want to remove all - unused subkeys. - [H LI] Copy secring.auto to a floppy and carry it to the target box. - [H /OL] - - On the target machine: - [H OL] - [H LI] Install secring.auto as secret keyring. - [H LI] Now you can start your new service. It is a good idea to - install some intrusion detection system so that you hopefully - get a notice of an successful intrusion, so that you in turn - can revoke all the subkeys installed on that machine and - install new subkeys. - [H /OL] - - Which email-client can I use with GnuPG? - - Using GnuPG to encrypt email is one of the most popular uses. - Several mail clients or mail user-agents (MUA) support GnuPG at - varying degrees. Simplifying a bit, there are two ways mail can be - encrypted with GnuPG: the "old style" ASCII armor, i.e. plain text - encryption, and RFC2015 style (previously PGP/MIME, now OpenPGP). - The latter has full MIME support. Some MUAs support only one of - them, so whichever you actually use depends on your needs as well - as the capabilities of your addressee. - - The following list is probably not exhaustive: - - OpenPGP: Mutt (Unix), Emacs/Mew, Becky2 (Windows, with plugin), - TkRat (Unix). There is effort for a Mozilla plugin and - Emacs/GNUS has support in the current CVS. - - ASCII: Emacs/{VM,GNUS}/MailCrypt, Mutt(Unix), Pine(Unix), and - probably many more. - - Good overviews of OpenPGP-support can be found at - [H a href=http://cryptorights.org/pgp-users/pgp-mail-clients.html]http://cryptorights.org/pgp-users/pgp-mail-clients.html[H /a] - and [H a href=http://www.geocities.com/openpgp/courrier_en.html]http://www.geocities.com/openpgp/courrier_en.html[H /a]. - - Can't we have a gpg library? - - This has been frequently requested. However, the current viewpoint - of the GnuPG maintainers is that this would lead to several security - issues and will therefore not be implemented in the foreseeable - future. However, for some areas of application gpgme could do the - trick. You'll find it at [H a href=ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme]ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme[H /a]. - - I have successfully generated a revocation certificate, but I don't - understand how to send it to the key servers. - - Most keyservers don't accept a 'bare' revocation certificate. You - have to import the certificate into gpg first: - - [H pre] - gpg --import my-revocation.asc - [H /pre] - - then send the revoked key to the keyservers: - - [H pre] - gpg --keyserver certserver.pgp.com --send-keys mykeyid - [H /pre] - - (or use a keyserver web interface for this). - - How do I put my keyring in a different directory? - - GnuPG keeps several files in a special homedir directory. These - include the options file, pubring.gpg, secring.gpg, trustdb.gpg, - and others. GnuPG will always create and use these files. On unices, - the homedir is usually ~/.gnupg; on Windows "C:\gnupg\". - - If you want to put your keyrings somewhere else, use: - - [H pre] - --homedir /my/path/ - [H /pre] - - to make GnuPG create all its files in that directory. Your keyring - will be "/my/path/pubring.gpg". This way you can store your secrets - on a floppy disk. Don't use "--keyring" as its purpose is to specify - additional keyring files. - - - COMPATIBILITY ISSUES - - - How can I encrypt a message with GnuPG so that PGP is able to decrypt it? - - It depends on the PGP version. - - [H UL] - [H LI]PGP 2.x[H br] - You can't do that because PGP 2.x normally uses IDEA which is not - supported by GnuPG as it is patented (see ), but if you have a - modified version of PGP you can try this: - - [H pre] - gpg --rfc1991 --cipher-algo 3des ... - [H/pre] - - Please don't pipe the data to encrypt to gpg but provide it using a - filename; otherwise, PGP 2 will not be able to handle it. - - As for conventional encryption, you can't do this for PGP 2. - - [H LI]PGP 5.x and higher[H br] - You need to provide two additional options: - - [H pre] - --compress-algo 1 --cipher-algo cast5 - [H/pre] - - You may also use "3des" instead of "cast5", and "blowfish" does not - work with all versions of PGP 5. You may also want to put: - - [H pre] - compress-algo 1 - [H/pre] - - into your ~/.gnupg/options file - this does not affect normal GnuPG - operation. - - This applies to conventional encryption as well. - [H /UL] - - How do I migrate from PGP 2.x to GnuPG? - - PGP 2 uses the RSA and IDEA encryption algorithms. Whereas the RSA - patent has expired and RSA is included as of GnuPG 1.0.3, the IDEA - algorithm is still patented until 2007. Under certain conditions you - may use IDEA even today. In that case, you may refer to Question - about how to add IDEA support to GnuPG and read - [H a href=http://www.gnupg.org/gph/en/pgp2x.html]http://www.gnupg.org/gph/en/pgp2x.html[H /a] to perform the migration. - - (removed) - - (empty) - - Why is PGP 5.x not able to encrypt messages with some keys? - - PGP, Inc. refuses to accept ElGamal keys of type 20 even for - encryption. They only support type 16 (which is identical at least - for decryption). To be more inter-operable, GnuPG (starting with - version 0.3.3) now also uses type 16 for the ElGamal subkey which is - created if the default key algorithm is chosen. You may add a type - 16 ElGamal key to your public key, which is easy as your key - signatures are still valid. - - Why is PGP 5.x not able to verify my messages? - - PGP 5.x does not accept v4 signatures for data material but OpenPGP - requests generation of v4 signatures for all kind of data, that's why - GnuPG defaults to them. Use the option "--force-v3-sigs" to generate - v3 signatures for data. - - How do I transfer owner trust values from PGP to GnuPG? - - There is a script in the tools directory to help you. After you have - imported the PGP keyring you can give this command: - - [H pre] - $ lspgpot pgpkeyring | gpg --import-ownertrust - [H /pre] - - where pgpkeyring is the original keyring and not the GnuPG keyring - you might have created in the first step. - - PGP does not like my secret key. - - Older PGPs probably bail out on some private comment packets used by - GnuPG. These packets are fully in compliance with OpenPGP; however - PGP is not really OpenPGP aware. A workaround is to export the - secret keys with this command: - - [H pre] - $ gpg --export-secret-keys --no-comment -a your-key-id - [H /pre] - - Another possibility is this: by default, GnuPG encrypts your secret - key using the Blowfish symmetric algorithm. Older PGPs will only - understand 3DES, CAST5, or IDEA symmetric algorithms. Using the - following method you can re-encrypt your secret gpg key with a - different algo: - - [H pre] - $ gpg --s2k-cipher-algo=CAST5 --s2k-digest-algo=SHA1 \ - --compress-algo=1 --edit-key - [H /pre] - - Then use passwd to change the password (just change it to the same - thing, but it will encrypt the key with CAST5 this time). - - Now you can export it and PGP should be able to handle it. - - For PGP 6.x the following options work to export a key: - - [H pre] - $ gpg --s2k-cipher-algo 3des --compress-algo 1 --rfc1991 \ - --export-secret-keys - [H /pre] - - - PROBLEMS and ERROR MESSAGES - - Why do I get "gpg: Warning: using insecure memory!" - - On many systems this program should be installed as setuid(root). - This is necessary to lock memory pages. Locking memory pages prevents - the operating system from writing them to disk and thereby keeping your - secret keys really secret. If you get no warning message about insecure - memory your operating system supports locking without being root. The - program drops root privileges as soon as locked memory is allocated. - - On UnixWare 2.x and 7.x you should install GnuPG with the 'plock' - privilege to get the same effect: - - [H pre] - filepriv -f plock /path/to/gpg - [H /pre] - - If you can't or don't want to install GnuPG setuid(root), you can - use the option "--no-secmem-warning" or put: - - [H pre] - no-secmem-warning - [H /pre] - - in your ~/.gnupg/options file (this disables the warning). - - On some systems (e.g., Windows) GnuPG does not lock memory pages - and older GnuPG versions (<=1.0.4) issue the warning: - - [H pre] - gpg: Please note that you don't have secure memory - [H /pre] - - This warning can't be switched off by the above option because it - was thought to be too serious an issue. However, it confused users - too much, so the warning was eventually removed. - - Large File Support doesn't work ... - - LFS is correctly working in post-1.0.4 CVS. If configure doesn't - detect it correctly, try a different (i.e., better) compiler. egcs - 1.1.2 works fine, other gccs sometimes don't. BTW, several - compilation problems of GnuPG 1.0.3 and 1.0.4 on HP-UX and Solaris - were due to broken LFS support. - - In the edit menu the trust values is not displayed correctly after - signing uids - why? - - This happens because some information is stored immediately in - the trustdb, but the actual trust calculation can be done after the - save command. This is a "not easy to fix" design bug which will be - addressed in some future release. - - What does "skipping pubkey 1: already loaded" mean? - - As of GnuPG 1.0.3, the RSA algorithm is included. If you still have - a "load-extension rsa" in your options file, the above message - occurs. Just remove the load command from the options file. - - GnuPG 1.0.4 doesn't create ~/.gnupg ... - - That's a known bug, already fixed in newer versions. - - An ElGamal signature does not verify anymore since version 1.0.2 ... - - Use the option --emulate-md-encode-bug. - - Old versions of GnuPG can't verify ElGamal signatures - - Update to GnuPG 1.0.2 or newer. - - When I use --clearsign, the plain text has sometimes extra dashes - in it - why? - - This is called dash-escaped text and is required by OpenPGP. - It always happens when a line starts with a dash ("-") and is - needed to make the lines that structure signature and text - (i.e., "-----BEGIN PGP SIGNATURE-----") to be the only lines - that start with two dashes. - - If you use GnuPG to process those messages, the extra dashes - are removed. Good mail clients remove those extra dashes when - displaying such a message. - - What is the thing with "can't handle multiple signatures"? - - Due to different message formats GnuPG is not always able to split - a file with multiple signatures unambiguously into its parts. This - error message informs you that there is something wrong with the input. - - The only way to have multiple signatures in a file is by using the - OpenPGP format with one-pass-signature packets (which is GnuPG's - default) or the cleartext signed format. - - If I submit a key to a keyserver, nothing happens ... - - You are most likely using GnuPG 1.0.2 or older on Windows. That's - feature isn't yet implemented, but it's a bug not to say it. Newer - versions issue a warning. Upgrade to 1.0.4 or newer. - - I get "gpg: waiting for lock ..." - - A previous gpg has most likely exited abnormally and left a lock - file. Go to ~/.gnupg and look for .*.lock files and remove them. - - Older gpg's (e.g., 1.0) have problems with keys from newer gpgs ... - - As of 1.0.3, keys generated with gpg are created with preferences to - TWOFISH (and AES since 1.0.4) and that also means that they have the - capability to use the new MDC encryption method. This will go into - OpenPGP soon and is also suppoted by PGP 7. This new method avoids - a (not so new) attack on all email encryption systems. - - This in turn means that pre-1.0.3 gpg's have problems with newer - keys. Because of security fixes, you should keep your GnuPG - installation in a recent state anyway. As a workaround, you can - force gpg to use a previous default cipher algo by putting: - - [H pre] - cipher-algo cast5 - [H /pre] - - into your options file. - - With 1.0.4, I get "this cipher algorithm is deprecated ..." - - If you just generated a new key and get this message while - encrypting, you've witnessed a bug in 1.0.4. It uses the new AES - cipher Rijndael that is incorrectly being referred as "deprecated". - Ignore this warning, more recent versions of gpg are corrected. - - Some dates are displayed as ????-??-??, why? - - Due to constraints in most libc implementations, dates beyond - 2038-01-19 can't be displayed correctly. 64 bit OSes are not - affected by this problem. To avoid printing wrong dates, GnuPG - instead prints some question marks. To see the correct value, you - can use the options --with-colons and --fixed-list-mode. - - I still have a problem. How do I report a bug? - - Are you sure that it's not been mentioned somewhere on the mailing - lists? Did you have a look at the bug list (you'll find a link to - the list of reported bugs on the documentation page). If you're not - sure about it being a bug, you can send mail to the gnupg-devel - list. Otherwise, use the GUUG bug tracking system - [H a href=http://bugs.guug.de/Reporting.html]http://bugs.guug.de/Reporting.html[H /a]. - - Why doesn't GnuPG support X509 certificates? - - GnuPG, first and foremost, is an implementation of the OpenPGP - standard (RFC 2440), which is a competing infrastructure, different - from X509. - - They are both public-key cryptosystems, but how the public keys are - actually handled is different. - - Why do national characters in my user ID look funny? - - According to OpenPGP, GnuPG encodes user ID strings (and other - things) using UTF-8. In this encoding of Unicode, most national - characters get encoded as two- or three-byte sequences. For - example, å (0xE5 in ISO-8859-1) becomes Ã¥ (0xC3, - 0xA5). This might also be the reason why keyservers can't find - your key. - - I get 'sed' errors when running ./configure on Mac OS X ... - - This will be fixed after GnuPG has been upgraded to autoconf-2.50. - Until then, find the line setting CDPATH in the configure script - and place a: - - [H pre] - unset CDPATH - [H /pre] - - statement below it. - - Why does GnuPG 1.0.6 bail out on keyrings used with 1.0.7? - - There is a small bug in 1.0.6 which didn't parse trust packets - correctly. You may want to apply this patch if you can't upgrade: - - [H pre] - http://www.gnupg.org/developer/gpg-woody-fix.txt - [H /pre] - - - ADVANCED TOPICS - - How does this whole thing work? - - To generate a secret/public keypair, run: - - [H pre] - gpg --gen-key - [H/pre] - - and choose the default values. - - Data that is encrypted with a public key can only be decrypted by - the matching secret key. The secret key is protected by a password, - the public key is not. - - So to send your friend a message, you would encrypt your message - with his public key, and he would only be able to decrypt it by - having the secret key and putting in the password to use his secret - key. - - GnuPG is also useful for signing things. Things that are encrypted - with the secret key can be decrypted with the public key. To sign - something, a hash is taken of the data, and then the hash is in some - form encoded with the secret key. If someone has your public key, they - can verify that it is from you and that it hasn't changed by checking - the encoded form of the hash with the public key. - - A keyring is just a large file that stores keys. You have a public - keyring where you store yours and your friend's public keys. You have - a secret keyring that you keep your secret key on, and should be very - careful with. Never ever give anyone else access to it and use a *good* - passphrase to protect the data in it. - - You can 'conventionally' encrypt something by using the option 'gpg -c'. - It is encrypted using a passphrase, and does not use public and secret - keys. If the person you send the data to knows that passphrase, they - can decrypt it. This is usually most useful for encrypting things to - yourself, although you can encrypt things to your own public key in the - same way. It should be used for communication with partners you know - and where it is easy to exchange the passphrases (e.g. with your boy - friend or your wife). The advantage is that you can change the - passphrase from time to time and decrease the risk, that many old - messages may be decrypted by people who accidently got your passphrase. - - You can add and copy keys to and from your keyring with the 'gpg - --import' and 'gpg --export' option. 'gpg --export-secret-keys' will - export secret keys. This is normally not useful, but you can generate - the key on one machine then move it to another machine. - - Keys can be signed under the 'gpg --edit-key' option. When you sign a - key, you are saying that you are certain that the key belongs to the - person it says it comes from. You should be very sure that is really - that person: You should verify the key fingerprint with: - - [H pre] - gpg --fingerprint user-id - [H/pre] - - over the phone (if you really know the voice of the other person), at a - key signing party (which are often held at computer conferences), or at - a meeting of your local GNU/Linux User Group. - - Hmm, what else. You may use the option "-o filename" to force output - to this filename (use "-" to force output to stdout). "-r" just lets - you specify the recipient (which public key you encrypt with) on the - command line instead of typing it interactively. - - Oh yeah, this is important. By default all data is encrypted in some - weird binary format. If you want to have things appear in ASCII text - that is readable, just add the '-a' option. But the preferred method - is to use a MIME aware mail reader (Mutt, Pine and many more). - - There is a small security glitch in the OpenPGP (and therefore GnuPG) - system; to avoid this you should always sign and encrypt a message - instead of only encrypting it. - - Why are some signatures with an ELG-E key valid? - - These are ElGamal keys generated by GnuPG in v3 (RFC 1991) packets. - The OpenPGP draft later changed the algorithm identifier for ElGamal - keys which are usable for signatures and encryption from 16 to 20. - GnuPG now uses 20 when it generates new ElGamal keys but still - accepts 16 (which is according to OpenPGP "encryption only") if this - key is in a v3 packet. GnuPG is the only program which had used - these v3 ElGamal keys - so this assumption is quite safe. - - How does the whole trust thing work? - - It works more or less like PGP. The difference is that the trust is - computed at the time it is needed. This is one of the reasons for - the trustdb which holds a list of valid key signatures. If you are - not running in batch mode you will be asked to assign a trust - parameter (ownertrust) to a key. - - You can see the validity (calculated trust value) using this - command. - - [H pre] - gpg --list-keys --with-colons - [H/pre] - - If the first field is "pub" or "uid", the second field shows you the - trust: - - [H pre] - o = Unknown (this key is new to the system) - e = The key has expired - q = Undefined (no value assigned) - n = Don't trust this key at all - m = There is marginal trust in this key - f = The key is full trusted - u = The key is ultimately trusted; this is only used - for keys for which the secret key is also available. - r = The key has been revoked - d = The key has been disabled - [H/pre] - - The value in the "pub" record is the best one of all "uid" records. - You can get a list of the assigned trust values (how much you trust - the owner to correctly sign another person's key) with: - - [H pre] - gpg --list-ownertrust - [H/pre] - - The first field is the fingerprint of the primary key, the second - field is the assigned value: - - [H pre] - - = No Ownertrust value yet assigned. - n = Never trust this keyholder to correctly verify others signatures. - m = Have marginal trust in the keyholders capability to sign other - keys. - f = Assume that the key holder really knows how to sign keys. - u = No need to trust ourself because we have the secret key. - [H/pre] - - Keep these values confidential because they express your opinions - about others. PGP stores this information with the keyring thus it - is not a good idea to publish a PGP keyring instead of exporting the - keyring. GnuPG stores the trust in the trustdb.gpg file so it is okay - to give a gpg keyring away (but we have a --export command too). - - What kind of output is this: "key C26EE891.298, uid 09FB: ...."? - - This is the internal representation of a user ID in the trustdb. - "C26EE891" is the keyid, "298" is the local ID (a record number in - the trustdb) and "09FB" is the last two bytes of a ripe-md-160 hash - of the user ID for this key. - - How do I interpret some of the informational outputs? - - While checking the validity of a key, GnuPG sometimes prints some - information which is prefixed with information about the checked - item. - - [H pre] - "key 12345678.3456" - [H/pre] - - This is about the key with key ID 12345678 and the internal number - 3456, which is the record number of the so called directory record - in the trustdb. - - [H pre] - "uid 12345678.3456/ACDE" - [H/pre] - - This is about the user ID for the same key. To identify the user ID - the last two bytes of a ripe-md-160 over the user ID ring is printed. - - [H pre] - "sig 12345678.3456/ACDE/9A8B7C6D" - [H/pre] - - This is about the signature with key ID 9A8B7C6D for the above key - and user ID, if it is a signature which is direct on a key, the user - ID part is empty (..//..). - - Are the header lines of a cleartext signature part of the signed - material? - - No. For example you can add or remove "Comment:" lines. They have - a purpose like the mail header lines. However a "Hash:" line is - needed for OpenPGP signatures to tell the parser which hash - algorithm to use. - - What is the list of preferred algorithms? - - The list of preferred algorithms is a list of cipher, hash and - compression algorithms stored in the self-signature of a key during - key generation. When you encrypt a document, GnuPG uses this list - (which is then part of a public key) to determine which algorithms - to use. Basically it tells other people what algorithms the - recipient is able to handle and provides an order of preference. - - How do I change the list of preferred algorithms? - - In version 1.0.7 or later, you can use the edit menu and set the - new list of preference using the command "setpref"; the format of - this command resembles the output of the command "pref". The - preference is not changed immediately but the set preference will - be used when a new user ID is created. If you want to update the - preferences for existing user IDs, select those user IDs (or select - none to update all) and enter the command "updpref". Note that the - timestamp of the self-signature is increased by one second when - running this command. - - - ACKNOWLEDGEMENTS - - Many thanks to Nils Ellmenreich for maintaining this FAQ file for - a long time, Werner Koch for the original FAQ file, and to all - posters to gnupg-users and gnupg-devel. They all provided most - of the answers. - - Also thanks to Casper Dik for providing us with a script to generate - this FAQ (he uses it for the excellent Solaris2 FAQ). - -[H HR] - -Copyright (C) 2000-2002 Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111, USA - -Verbatim copying and distribution of this entire article is permitted in -any medium, provided this notice is preserved. diff --git a/doc/fr/ChangeLog b/doc/fr/ChangeLog deleted file mode 100644 index 167093dcc..000000000 --- a/doc/fr/ChangeLog +++ /dev/null @@ -1,17 +0,0 @@ -2001-09-10 Gilbert Fernandes - - * Traduction en français des documents doc/* - - -Copyright 2001 Free Software Foundation, Inc. - -Ce fichier est un logiciel libre ; l'auteur vous donne une autorisation -spéciale de copies illimitées et/ou distribution illimitée avec ou sans -modifications attendu que cette notice de copyright et note associée -se trouve conservée dans le document. - -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. - - diff --git a/doc/fr/DETAILS b/doc/fr/DETAILS deleted file mode 100644 index 5c7246c9d..000000000 --- a/doc/fr/DETAILS +++ /dev/null @@ -1,945 +0,0 @@ - -Format des listings "---with-colons" -==================================== - -sec::1024:17:6C7EE1B8621CC013:1998-07-07:0:::Werner Koch : -ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0::: - - 1. Champ: Type d'enregistrement - pub = clef publique - sub = sous-clef (clef secondaire) - sec = clef secrète - ssb = sous-clef secrète (clef secondaire) - uid = id d'utilisateur (seul le champ 10 est utilisé) - sig = signature - fpr = fingerprint: (le champ 10 est le fingerprint) - pkd = données publiques de la clef - (champ au format spécial, voir ci-dessous) - - 2. Champ: Une lettre décrivant la confiance calculée. Ce n'est qu'une - seule lettre, mais elle fera peut-être l'objet d'une information - supplémentaire pour les versions futures, comme décrit ici - (ceci ne sera pas utilisé pour les clefs privées) - o = Inconnu (cette clef est nouvelle au système) - i = La clef est invalide (eg. il manque sa propre signature) - d = La clef a été désactivée - r = La clef a été révoquée - e = La clef a expiré - q = Non-défini (pas de valeur attribuée) - n = Ne jamais faire confiance à cette clef - m = Cette clef dispose d'une confiance marginale - f = Cette clef dispose d'une confiance totale - u = Cette clef dispose d'une confiance ultime. Cette valeur - n'est utilisée que pour les clefs où la clef secrète est - également disponibles. - 3. Champ: taille de la clef en bits. - 4. Champ: Algorithme utilisé: 1 = RSA - 16 = ElGamal (chiffrement uniquement) - 17 = DSA (parfois appellé DH, signature seulement) - 20 = ElGamal (signe et chiffre) - (pour d'autres is, consultez include/cipher.h) - 5. Champ: ID de clef (KeyID) - 6. Champ: Date de création (en UTC) - 7. Champ: Date d'expiration de la clef, vide si aucune. - 8. Champ: ID local : numéro d'enregistrement du répertoire dans la - trustdb. Cette valeur n'est valide que tant que la - trustdb n'est pas effacée. Vous pouvez utiliser - "#" comme id d'utilisateur lorsque vous spécifiez - la clef. Ceci est requis puisque les id de clef ne sont pas - toujours uniques - un programme peut donc utiliser ce numéro - pour accéder aux clefs ultérieurement. - 9. Champ: Confiance propre (clef publiques primaires uniquement) - C'est une simple lettre, mais une information supplémentaire pourrait - se voir ajoutée dans les versions futures. -10. Champ: ID utilisateur. La valeur est placée entre guillemets comme une - chaîne en C, par exemple : "\x3a". -11. Champ: Classe de signature. C'est un nombre hexadécimal à deux chiffres - suivi par la lettre "x" si la signature peut être exportée ou la - lettre "l" si la signature est uniquement locale. -12. Champ: Capacités de la clef : - e = chiffrement - s = signature - c = certification - Une clef peut disposer de toute combinaison de ces caractéristiques. - La clef primaire dispose, en plus de ces lettres, une version en - majuscule des lettres pour marquer les capacités "d'utilisation" - de la totalité de la clef. - -Toutes les dates sont affichées dans le format : - -yyyy-mm-dd - -Sauf si vous utilisez l'option --fixed-list-mode où dans ce cas précis les -dates sont affichées en secondes depuis Epoch. Plus de champs feront l'objet -d'additions dans les futures versions et les parsers doivent y être préparés. -Lorsque le parser traitera ces données, il devra s'arrêter au premier -caractère non-numérique afin que des informations supplémentaires soient -ajoutées à l'avenir. - -Le champ 1 dispose d'un tag "pkd" dont le listing ressemble à ceci : - -pkd:0:1024:B665B1435F4C2 .... FF26ABB: - ! ! !-- la valeur - ! !------ indicateur du nombre de bits de la valeur - !--------- index (eg. DSA va de 0 à 3 : p,q,g,y) - - - -Format de la sortie "--status-fd" -================================= - -Chaque ligne dispose d'un préfixe : - -"[GNUPG:] " - -Suivie par un mot clef indiquant le type de la ligne de statut, -et quelques arguments selon le type (probablement aucun) ; une application -devrait toujours assumer que des arguments supplémentaires seront -présents dans les versions futures. - - GOODSIG - La signature keyid est valide. - Pour chaque signature seul l'un des trois codes GOODSIG, BADSIG ou - ERRSIG seront produits et ils pourront être utilisés comme - marqueurs pour les nouvelles signatures. - - BADSIG - La signature keyid n'a pas été vérifiée correctement. - - ERRSIG \ - - Il n'a pas été possible de vérifier la signature. Ceci peut provenir - d'une clef publique manquante, ou bien à cause d'un algorithme non- - supporté. Un RC de 4 indique un algorithme inconnu, un 9 indique - une clef publique manquante. Les autres champs donnent plus d'information - sur la signature. sig_class est une valeur hexadécimale de 2 octets. - - VALIDSIG - La signature keyid est valide. C'est ici la même chose que GOODSIG - mais avec le fingerprint comme argument. Les lignes de statut seront - émises pour une bonne signature. - sig-timestamp est la date de création de la signature en secondes - depuis Epoch. - - SIG_ID - N'est émis que pour les signatures de classe 0 ou 1 qui ont été - vérifiées comme valides. Le chaîne est un identifiant d'utilisateur - et peut être utilisée dans les applications pour détecter les - attaques par rejeu de messages signés. Notez que seuls les - algorithmes DLP offrent des identifiants uniques ; les autres peuvent - produire des id dupliqués lorsqu'ils furent créés à la même seconde. - - ENC_TO - Le message est chiffré avec ce keyid. - keytype est une valeur numérique de l'algorithme à clef publique, - keylength est la taille de la clef ou 0 si elle n'est pas connue - (ce qui est toujours le cas). - - NODATA - Aucune donnée n'a été trouvée. Les codes suivants sont utilisés : - 1 - Pas de données sous ARMOR. - 2 - Un paquet attendu n'a pas été trouvé. - 3 - Paquet invalide trouvé ; ceci peut indiquer un message - non-OpenPGP. Vous devez vous attendre à une extension - de ces lignes de statu à l'avenir. - - UNEXPECTED - Des données innatendues ont été rencontrées - 0 - pas de détail supplémentaire - - TRUST_UNDEFINED - TRUST_NEVER - TRUST_MARGINAL - TRUST_FULLY - TRUST_ULTIMATE - Pour les signatures valides, l'une de ces lignes de statut sera produite - pour indiquer le niveau de confiance attribué à la clef. Pas d'arguments - pour l'instant. - - SIGEXPIRED - La clef de signature a expiré. Pas d'arguments pour l'instant. - - KEYREVOKED - L'utilisateur a révoqué sa clef. Pas d'arguments pour l'instant. - - BADARMOR - L'ARMOR ASCII est corrompu. Pas d'arguments pour l'instant. - - RSA_OR_IDEA - Les algorithmes IDEA ont été utilisés sur les données. Un programme - pourra basculer sur un autre programme de traitement si GnuPG échoue. - Ce message de statut sera affiché pour le RSA aussi, mais ceci a été - abandonné puisque le brevêt sur le RSA a expiré. - Toutefois, nous ne pouvons modifier le nom du message. - - SHM_INFO - SHM_GET - SHM_GET_BOOL - SHM_GET_HIDDEN - - GET_BOOL - GET_LINE - GET_HIDDEN - GOT_IT - - NEED_PASSPHRASE - Sera affiché à chaque fois qu'une phrase passe sera requise. - keytype est la valeur numérique de l'algorithme à clef publique - ou bien 0 si cela n'est pas applicable. keylength est la taille de la - clef ou 0 si la taille n'est pas connue (ceci est actuellement - toujours le cas). - - NEED_PASSPHRASE_SYM - Affiché à chaque fois qu'une phrase passe pour un chiffrement - symétrique sera requise. - - MISSING_PASSPHRASE - Aucune phrase passe n'a été fournie. Une application qui rencontre - ce message devrait stopper immédiatement le parsing car le prochain - message sera probablement BAD_PASSPHRASE. Toutefois, si l'application - n'est qu'un wrapper autour de la fonctionnalité d'édition de clefs, - ceci pourrait avoir un autre sens et stopper le parsing pourrait - être incorrect, et il faudra ignorer le BAD_PASSPHRASE. - - BAD_PASSPHRASE - La phrase passe fournie est soit invalide, soit n'a pas été fournie. - Dans le seconde cas vous devriez voir un MISSING_PASSPHRASE. - - GOOD_PASSPHRASE - La phrase passe fournie est valide et le matériel de clefs secrète - est utilisable. - - DECRYPTION_FAILED - La déchiffrement symétrique a échoué. Il s'agit généralement d'une - mauvaise phrase passe ne correspondant pas au message chiffré. - - DECRYPTION_OKAY - Succès du déchiffrement. Ceci signifie que soit la clef secrète - adaptée a été utilisée avec succès, soit que la phrase passe - valide pour un chiffrement symétrique aura conduit au déchiffrement. - Le programme pourait toutefois renvoyer un message d'erreur s'il - n'a pas été possible de vérifier la signature. - - NO_PUBKEY - NO_SECKEY - La clef n'est pas utilisable. - - IMPORTED - Le keyid et la signature ont été importés. - - IMPORTED_RES - - Statistiques finales sur le processus d'importation (cette ligne est longue!) - - FILE_START - Début de traitement du fichier . indique l'opération - réalisée : - 1 - vérifier - - FILE_DONE - Marque la fin de traitement d'un fichier, ayant débuté avec FILE_START. - - BEGIN_DECRYPTION - END_DECRYPTION - Marque le début et la fin du processus de déchiffrement. Ces messages - seront également produits lors de l'utilisation du mode --list-only. - - BEGIN_ENCRYPTION - END_ENCRYPTION - Marque le début et la fin du processus de chiffrement. - - DELETE_PROBLEM reason_code - L'effacement d'une clef a échoué. Un code indique la raison de l'erreur : - 1 - La clef spécifiée n'existe pas - 2 - La clef privée doit être détruite avant ! - - PROGRESS what char cur total - Utilisé par les fonctions primegen et de clef publique pour indiquer - la progression de l'opération. "char" est le caractère affiché sans - --status-fd avec les retours à la ligne marqués par "X". "cur" indique - la quantitité de traitement terminée et "total" indique la valeur - finale à atteindre. Un total de 0 indique que le total n'est pas - connu. 100/100 peut être utilisé pour détecter la fin de l'opération. - - SIG_CREATED - Une signature a été créée à l'aide de ces paramètres. - type: 'D' = détachée - 'C' = en texte clair - 'S' = standard - (seul le premier caractère doit être vérifié) - class: 2 chiffres hexadécimaux avec la classe de signature - - KEY_CREATED - Une clef a été créée - type: 'B' = primaire et sous-clef - 'P' = primaire - 'S' = sous-clef - - SESSION_KEY : - La clef de session utilisée pour déchiffrer le message. Ce message - sera seulement affiché si l'option --show-session est utilisée. - Le format est utilisable pour un passage direct à la fonction - --override-session-key. - - NOTATION_NAME - NOTATION_DATA - Le nom et la chaîne sont "escaped" à l'aide de %XX et les données - peuvent être découpées sur plusieurs lignes notation_data. - - USERID_HINT - Donne un indice sur l'ID utilisateur pour un keyID donné. - - POLICY_URL - La chaîne est "escaped" en %XX - - BEGIN_STREAM - END_STREAM - Produit par pipemode. - - -Génération de clef -================== - -La génération de clef marque sa progression à l'aide de différents caractères, dont -voici la signification : - -"." : les 10 derniers tests Miller-Rabin ont échoué. -"+" : réussite du test Miller-Rabin. -"!" : Rechargement du pool avec des nombres premiers frais. -"^" : Vérification d'une nouvelle valeur pour le générateur. -"<" : La taille d'un facteur a été réduite. -">" : La taille d'un facteur a été augmentée. - -Le nombre premier pour l'ElGamal est généré de la manière suivante : - -1. On crée un nombre premier q de 160, 200 ou 240 bits (selon la taille - de la clef). -2. On sélectionne la taille de l'autre facteur premier, afin qu'elle soit - au moins de la taille de q et on calcule le nombre de facteurs premiers - requis. -3. On crée un pool de nombres premiers, chacun dont la longueur fut déterminée - à l'étape 2. -4. On obtient une nouvelle permutation du pool et nous continuons avec - l'étape 3 une fois toutes les permutations testées. -5. Le premier cancidat est calculé par p = 2 * q * p[1] * ... * p[n] + 1 -6. On vérifie que ce premier dispose de la taille désirée (ceci peut changer - q s'il ne semble pas possible de produire un premier de la taille voulue) -7. On vérifie si ce nombre est premier à l'aide de divisions d'essai et par - le test de Miller-Rabin. -8. On continue à l'étape 4 si on n'a pas trouvé de premier à l'étape 7. -9. On trouve un générateur pour ce premier. - -Cet algorithme se base sur la suggestion de Lim et Lee du Crypto' 97 (p. 260). - -Génération de clef innatendue -============================= - -Cette fonction est actuellement expérimentale et permet la production de -clefs innatendues avec un contrôle depuis un fichier de paramètres. -Cette fonctionnalité n'a pas fait l'objet de tests poussés ! Veuillez ne -PAS vous plaindre si nous décidons d'apporter des modifications importantes -à cette commande. - -Pour utiliser cette fonctionnalité, vous devez utiliser --gen-key en -combinaison avec --batch et fournir les paramètres soit depuis stdin, -soit depuis un fichier dont le nom est fourni en ligne de commande. - -Ce fichier devra utiliser le format suivant : - - o En texte uniquement, chaque ligne étant limitée à environ 1000 caractères. - o Vous devez utiliser un codage UTF-8 pour marquer les caractères non ASCII. - o Les lignes vides seront ignorées. - o Les espaces en début et fin de ligne seront ignorés. - o Un signe "-" en tant que premier caractère "non white space" marque - une ligne de commentaire. - o Les commandes sont marquées par un signe "%" en début de ligne, - suivi par la commande et ses arguments sont séparés par des espaces. - o Les paramètres sont indiqués par un mot clef, suivi par un ":". Les - arguments sont séparés par des espaces. - o Le premier paramètre doit être "Key-Type" et ses contrôles peuvent - être placés à votre discrétion. - o La génération de clef aura lieu soit à la fin du fichier de paramètres, - soit lorsque le premier "Key-Type" est rencontré au sein du fichier, - dans un ensenble de contrôle "%commit". - o Les ensembles de contrôle sont : - %echo - Affiche - - %dry-run - Ne réalise pas la production de clef (pratique pour vérifier la - syntaxe). - - %commit - Réalise la production de clef. Un commit implicite est produit - à chaque rencontre de "Key-Type". - - %pubring - %secring - Ne renvoie pas la clef vers le sortie par défaut ou dans le keyring - indiqué en ligne de commande, mais vers le fichier . Ce - contrôle doit être utilisé avant que le commit ne soit rencontré. - Toute double mention sera ignorée et le dernier nom de fichier - rencontré sera celui utilisé. Le fichier sera utilisé jusqu'à ce - qu'un nouveau fichier soit spécifié (au points de commit) sinon - toutes les clefs seront placées dans le même fichier. Si un nouveau - nom de fichier est indiqué, le fichier sera créé (et tout ancien - fichier sera alors écrasé). Les deux indications doivent être - fournies au contrôle. - - o L'ordre des paramètres n'a pas d'importance, sauf pour "Key-Type" qui - doit être le premier paramètre rencontré. Les paramètres ne sont - destinés qu'au bloc keybloc généré et les paramètres des productions - précédentes de clefs ne seront pas pris en compte. Certaines - vérifications syntaxiques seront mises en place et peuvent être - ou non actives. Les paramètres actuellement définis sont : - - Key-Type: | - Débute un nouveau bloc de paramètres indiquant le type de la clef - primaire à produire. L'algorithme doit être capable de produire - des signatures. Ce paramètre est indispensable ! - - Key-Length: - Indique la taille de la clef, en bits. La valeur par défaut est - 1024. - - Subkey-Type: | - Permet de produire une clef secondaire. Actuellement, seule une - sous-clef peut être gérée. - - Subkey-Length: - Taille de la sous-clef en bits. La valeur par défaut est - 1024. - - Passphrase: - Si vous souhaitez spécifier une phrase passe pour la clef - secrète vous pouvez utiliser cette commande. Par défaut, - aucune phrase passe ne sera associée aux clefs privées. - - Name-Real: - Name-Comment: - Name-Email: - Voici les trois composantes d'une clef. Vous devez ici - n'utiliser que de l'UTF-8. Si vous ne fournissez aucune - de ces indications, aucun ID d'utilisateur ne sera créé. - - Expire-Date: |([d|w|m|y]) - Spécifie la date d'expiration de la clef (et de sa sous-clef) - La date doit être entrée sous la forme d'une date au format - ISO (année-mois-jour) ou bien sous forme d'un nombre de - jours, de semaines, de mois ou d'années. Si vous n'utilisez - pas de lettre pour indiquer la durée, des "jours" sont - assumés par défaut. - -Voici un exemple : -$ cat >foo < -ssb 1024g/8F70E2C0 2000-03-09 - - - -Composition de la TrustDB -========================= - -La TrustDB est construire à partir d'enregistrements à taille fixe, où le premier -octet décrit le type d'enregistrement. Toutes les valeurs numériques sont -conservées dans un réseau d'ordre d'octets. La longueur de chaque enregistrement -est de 40 octets. Le premier enregistrement de la TrustDB est toujours de type 1 -et c'est le seul enregistrement de ce type. - - Record type 0: - -------------- - - Cet enregistrement n'est pas utilisé. Il peut être utilisé - à votre discrétion. - - Record type 1: - -------------- - - Indique la version de la TrustDB. Cet enregistrement doit toujours être - le premier enregistrement de la base de données et c'est le seul - enregistrement de type 1. - - 1 octet valeur : 1 - 3 octets 'gpg' valeur "magic" - 1 octet Version de la TrustDB (2) - 1 octet marginales requises - 1 octet complètes requises - 1 octet max_cert_depth - - Ces trois éléments sont utilisés pour vérifier si la valeur de validité - mise en cache dans l'enregistrement du répertoire peut être utilisée : - - 1 u32 locked flags - 1 u32 datation de la création de la trustdb - 1 u32 datation de la dernière modification - - Cette datation pourrait affecter la validité des clefs dans la base de - données. Cette valeur sera comparée à celle de la datation de validité - des enregistrements dir : - - 1 u32 datation de la dernière validation - - Cette valeur sera utilisée pour stocker le passage du temps, lorsque - cette TrustDB sera comparée au trousseau de clefs publiques : - - 1 u32 numéro de l'enregistrement du keyhashtable - 1 u32 premier enregistrement libre - 1 u32 numéro de l'enregistrement répertoire shadow de la table de hachage - - Cette table ne devrait pas être combinée avec la table de clefs car le - keyid n'est pas dans chaque cas un élément du fingerprint. - - 4 bytes réservés pour l'enregistrement d'extension de version - - - Record type 2: (enregistrement répertoire) - -------------- - - Regroupe les informations sur un certificat de clef publique. - Ces valeur sont statiques et ne sont jamais modifiées sans une - interaction avec l'utilisateur : - - 1 octet valeur : 2 - 1 octet réservé - 1 u32 LID . (numéro d'enregistrement de cet enregistrement) - 1 u32 Liste de key-records (le premier est la clef primaire) - 1 u32 Liste de uid-records - 1 u32 cache record - 1 octet ownertrust - 1 octet dirflag - 1 octet validité maximale de tous les id utilisateurs - 1 u32 datation de la dernière vérification de validité - 1 u32 Vérification requise lorsque cette datation sera atteinte - (0 = pas de vérification requise) - - - Record type 3: (enregistrement de clef) - -------------- - - Regroupe les informations sur une clef publique primaire. - (ces informations sont principalement utilisées pour réaliser les lookup - dans l'enregistrement trust) - - 1 octet valeur : 3 - 1 octet réservé - 1 u32 LID - 1 u32 next - prochain enregistrement - 7 octets réservés - 1 octet keyflags - 1 octet algorithme de la clef publique - 1 octet taille du fingerprint (en octets) - 20 octets fingerprint de la clef publique - (Cette valeur est utilisée pour identifier toute clef) - - Record type 4: (enregistrement uid) - -------------- - - Regroupe les informations sur un id utilisateur (un "uid"). - Nous ne stockons par l'uid mais un hachage de l'uid : cela semble suffire. - - 1 octet valeur : 4 - 1 octet réservé - 1 u32 LID pointe vers l'enregistrement directory - 1 u32 next le userid suivant - 1 u32 pointeur vers l'enregistrement preference - 1 u32 siglist liste de signatures valides - 1 octet uidflags - 1 octet validité de la clef calculée pour cet userid - 20 bytes ripemd160 hachage du nom de l'utilisateur - - - Record type 5: (enregistrement pref) - -------------- - - Regroupe les informations formant les préférences. - - 1 octet valeur : 5 - 1 octet réservé - 1 u32 LID; pointe vers l'enregistrement directory (et PAS vers le uid !!!) - (égal à 0 pour un enregistrement de préférences standard) - 1 u32 suivant - 30 byte données de préférences - - Record type 6 (sigrec) - ------------- - - Cet enregistrement est utilisé pour traquer les signatures de clefs. Les - auto-signatures ne sont pas conservées. Si une clef publique ne se trouve - pas dans la TrustDB, la signature pointe vers un enregistrement dir fantôme, - lequel contient une liste des enregistrements qui seraient intéressés - par cette clef (et l'enregistrement signature en fait partie). - - 1 octet valeur : 6 - 1 octet réservé - 1 u32 LID pointe en retour vers l'enregistrment dir - 1 u32 next prochain sigrec de cet uid ou bien 0 pour indiquer que ce - sigrec est le dernier. - 6 times - 1 u32 Local_id des dir signatures ou de l'enregistrement dir fantôme - 1 octet Flag: Bit 0 = vérifié: Bit 1 est valide (nous avons un - véritable enregistrement directory) - 1 = valide est vrai (mais pourrait être révoqué) - - - - Record type 8: (enregistrement répertoire (dir) fantôme) - -------------- - - Cet enregistrement est utilisé pour réserver un LID pour une clef publique. - Nous avons besoin de cet enregistrement pour créer les enregistrements sigs - des autres clefs, même si nous ne disposons pas d'une signature de la clef - publique. - Cet enregistrement (le numéro d'enregistrement pour être plus précis) - sera réutilisé dans l'enregistrement dir lorsque nous importerons la - véritable clef publique. - - 1 octet valeur : 8 - 1 octet réservé - 1 u32 LID (Ceci est simplement le numéro d'enregistrement de ce record.) - 2 u32 keyid - 1 octet algorithme de la clef publique - 3 octets réservé - 1 u32 hintlist - - hintlist contient la liste des enregistrements qui ont des références qui pointent - vers cette clef. Nous utilisons cet élément pour augmenter la vitesse d'accès - des enregistrements de signature qui ne sont pas encore vérifiés. Notez que ces - données ne sont qu'un indice, une indication ("hint") mais les enregistrements actuels - pourraient ne pas détenir d'enregistrement de signature pour la clef, mais le - code du programme saura prendre soin de tout cela. - - 18 octets réservés - - - - Record Type 10 (table de hachage) - -------------- - - Comme nous utilisons les fingerprint pour accéder aux clefs, nous devons - implémenter un accès rapide en utilisant des méthodes de hachages simples, - afin d'éviter une surcharge de gdbm. La propriété des fingerprint - est qu'ils permettent un usage direct en tant que valeurs hachées (ils - peuvent être considérés comme des nombres aléatoires cryptographiquement - forts). - Nous utilisons une architecture à multiples niveaux dynamique, qui combine - les tables de hachage, les listes d'enregistrements et les listes - chaînées. - - Cet enregistrement est une table de hachages de 256 entrées ; une propriété - spéciale est que tous les enregistrements sont stockés consécutivement - pour produire une grande table. La valeur hachée est simplement le 1er, - 2nd.. octet du fingerprint (selon le niveau d'indirection). - - Lorsque nous les utilisons pour hacher les enregistrements de répertoires - shadow, une différente table est utilisée, et elle se trouve indexée - par le keyid. - - 1 octet valeur : 10 - 1 octet réservé - n u32 recnum; n dépend de la taille de l'enregistrement : - n = (reclen-2)/4 ce qui donne 9 pour la taille actuelle - d'enregistrement de 40 octets. - - Le nombre total de ces enregistrements constituant la table est : - - m = (256+n-1) / n - - ce qui donne 29 pour une taille d'enregistrement de 40. - - Pour rechercher une clef, nous utilisons le premier octet du fingerprint - pour obtenir le recnum de la table de hachage et nous étudions l'enregistrement - adressé : - - o Si cet enregistrement est une autre table de hachage, nous pouvons - utiliser le second octet pour indexer cette table de hachage et continuer. - - o Si cet enregistrement est une liste de hachages, nous pouvons parcourir - toutes les entrées jusqu'à trouver la bonne. - - o Si cet enregistrement est un enregistrement de clef, nous comparons - le fingerprint avec celui recherché et nous déterminons s'il s'agit - de la clef recherchée. - - - - Record type 11 (liste hachée) - -------------- - - Consultez la table hachée pour une explication. - Ceci sera également utilisé à d'autres fins. - - 1 octet valeur : 11 - 1 octet réservé - 1 u32 next enregistrement de liste hachée suivant - n times n = (reclen-5)/5 - 1 u32 recnum - - Pour la taille actuelle utilisée par les enregistrements (taille 40) nous avons n = 7. - - - - - Record type 254 (enregistrement libre) - --------------- - -Tous ces enregistrements forment une liste chaînée d'enregistrements non-utilisés. - - 1 octet valeur 254 - 1 octet réservé (0) - 1 u32 next_free - - - -En-têtes de paquets -=================== - -GnuPG utilise des en-têtes PGP 2 et il est aussi capable de comprendre -les en-têtes de type OpenPGP. C'est une amélioration utilisée sur les anciens -en-têtes de paquets : - -Les CTB bits 10, les "packet-length length bits" ont leurs valeurs listées -dans la table suivante : - - 00 - 1-octet champ packet-length - 01 - 2-octets champ packet-length - 10 - 4-octets champ packet-length - 11 - pas de taille de paquet fournie, taille inconnue - -Comme indiqué dans cette table, selon la taille du packet-length les -octets restants (1, 2, 4 ou 0) du champ de structure de paquets sont -un "champ packet-length". Ce champ est une valeur numérique à part entière. -La valeur du champ packet-length est définie par la valeur de la -totalité du champ numérique. - -La valeur 11 est actuellement utilisée dans un cas : les données -compressées. C''est à dire qu'un bloc de données compressées -ressemble à : où A3 est le binaire "10 1000 11" et -produit ici un paquet de taille non-définie. L'interprétation -correcte en est : "jusqu'à la fin de la structure englobante" -bien qu'en fait la structure englobante soit généralement -le fichier. - -+ Ceci sera modifié dans une future version, où la signification de la -+ valeur 11 (voir ci-dessous) aura aussi sa place. -+ -+ Une valeur de 11 pour d'autres paquets active un codage spécial -+ de la taille, où la taille du paquet suivant ne pourra pas être -+ déterminée avant l'écriture du paquet, en particulier ceci sera -+ utilisé si de grande quantités de données sont à traiter dans -+ un mode filtre. -+ -+ Ceci fonctionne de la manière suivante : après le CTB (qui est un -+ champ de longueur de 11) un champ marqueur sera utilisé, il indiquera -+ alors la taille du bloc de données suivant. C'est un simple champ -+ de deux octets (MSB en premier) contenant la quantité de données qui -+ suivent le champ, sans inclure le champ de taille toutefois. Après -+ ce bloc de données un autre champ de taille suivra, qui donnera la taille -+ du bloc de données suivant. Une valeur de 0 indique une fin de paquet. -+ La taille maximale d'un bloc de données est limitée à 65534, ce qui -+ réserve la valeur 0xffff pour des extensions futures. Ces marqueurs de -+ taille devront être insérés dans le flux de données avant que les -+ données ne soient envoyées en sortie. -+ -+ Ce champ de deux octets est largement suffisant, car l'application -+ doit placer en tampon cette quantité de données pour précéder le -+ marqueur de taille avant de produire une sortie. Les blocs de données -+ d'une taille supérieure à 32 Ko n'ont aucun sens. Notez que ceci pourra -+ également être utilisé pour les flux de données compressées, mais -+ nous devrons alors utiliser une autre version de paquet afin de dire à -+ l'application qu'elle ne peut assumer qu'il s'agit du dernier paquet. - - -Extensions GNU à l'algorithme S2K -================================= - -Le S2K mode 101 est utilisé pour identifier ces extensions. -Après l'algorithme de hachage les trois octets "GNU" sont utilisés -pour indiquer clairement qu'il s'agit d'extensions GNU et les octets -qui suivent donnent le mode de protection GNU utilisé : 1000. Les -modes définis sont : - - 1001 - ne pas conserver du tout de partie secrète - - - -Usage des fichiers gdbm pour les trousseaux de clefs -==================================================== - -La clef utilisé pour stocker le keyblock est son propre fingerprint, -les autres enregistrements sont utilisés pour les clefs secondaires. -Les fingerprint font toujours 20 octets où 16 bits de fingerprint -sont suivis par 0. Le premier octet de chaque clef indique une -information sur le type de clef : - - 1 = la clef est un fingerprint de 20 octets (16 octets fpr "paddés" de 0) - les données sont le keyblock - 2 = la clef est un keyid complet de 8 octets - les données sont une liste de 20 octets fingerprints - 3 = la clef est un keyid court de 4 octets - les données sont une liste de 20 octets fingerprints - 4 = la clef est une adresse email - les données sont une liste de 20 octets fingerprints - - Les données sont pre-appended (précédées) par un octet de type : - - 1 = keyblock - 2 = liste de 20 octets fingerprints "paddés" - 3 = liste de liste de fingerprints ("but how to we key them?") - - - -Pipemode -======== - -Ce mode est utilisé pour réaliser des opérations multiples avec un -unique appel à gpg. C'est assez pratique lorsqu'il faut pouvoir vérifier -un grand nombre de signatures. Actuellement nous n'avons qu'un support -des signatures détachées. Ce mode est une astuce qui permet d'éviter -de faire fonctionner gpg n en daemon mode et d'utiliser les Unix Domain -Sockets pour lui faire passer les données. Il n'existe aucun moyen -pratique de portabilité de ce concept sous Windows, alors nous utilisons -des pipes simples pour faire fonctionner ce mode sous Windows. Comme nous -n'avons aucun moyen de signaler des EOF multiples dans un pipe nous -devons laisser le contrôle s'insérer dans le flux de données lui-même. -Nous réalisons alors une distinction entre les données du flux et un -état de contrôle. A son lancement, le système se trouve dans un état -de données mais n'acceptera aucune donnée. Il attend en fait une -transition vers un mode de contrôle qui s'obtient en envoyant un simple -caractère '@'. Une fois dans le mode de contrôle, des commandes sont -attendues et ces commandes sont à un octet après lequel le système -revient au mode de données (mais cela n'implique pas qu'il acceptera -des données immédiatement). La commande de contrôle la plus simple -est '@' qui permet d'insérer ce caractère dans le flux de données. - -Voici le format que nous utilisons pour les signatures détachées : - -"@<" - Début d'un nouveau flux -"@B" - La signature détachée suit. - Ceci émet le paquet de contrôle (1,'B') - -"@t" - Le texte signé suit. - Ceci émet le paquet de contrôle (2, 'B') - -"@." - Fin de l'opération. Le paquet de contrôle final force la - vérification de la signature. -"@>" - Fin du flux. - - - -Autres notes -============ - -Dans la version* 3 de version de paquet nous calculons les keyid de cette manière : - -RSA : les 64 bits de poids faible de n -ELGAMAL : nous construisons un paquet de clef publique v3 (avec CTB 0x99) - et nous calculons une valeur hachée rmd160 à partir de ce paquet. - Il est utilisé comme fingerprint avec les 64 bits de poids faible - qui produisent le keyid. - -* Les certificats de révocation ne comportent qu'un paquet de signature ; -"import" sait comment traiter ces paquets. L'idée derrière ce principe -est de conserver une petite taille de paquet. - - - -Format des messages Keyserver -============================= - -Le serveur de clef peut être contacté par un Unix Domain Socket ou via TCP. - -Le format des requêtes est : - -==== -command-tag -"Content-length:" digits -CRLF -======= - -Où le command-tag est : - -NOOP -GET -PUT -DELETE - - -Le format de réponse utilisé est : - -====== -"GNUPG/1.0" status-code status-text -"Content-length:" digits -CRLF -============ - -suivi par octets de données. - - -Les codes de statut utilisés sont : - - o 1xx: Information: requête reçue, traitement en cours. - - o 2xx: Succès - L'action a été reçue, comprise et acceptée. - - o 4xx: Erreur client : la requête contient une erreur, mauvaise syntaxe - ou demande irréalisable. - - o 5xx: Erreur serveur - Le serveur n'a pu traiter une demande - qui semble valide. - - -Documentation sur HKP (le protocol de serveurs de clefs http) -============================================================= - -Un serveur HTTP minimal sur port 11371 reconnaît les requêtes GET -pour /pks/lookup. Les paramètres standard encodés URL de la requête -sont toujours ceux-ci : (toujours key=valeur) - -- op=index (comme pgp -kv), op=vindex (comme pgp -kvv) and op=get (comme - pgp -kxa) - -- search=. Nous avons ici une liste de mots qui doivent - apparaître dans la clef. Ces mots sont séparés par des espaces, - points, @, etc. Les délimiteurs ne feront pas partie de la - recherche et l'ordre des mots n'a aucune importance (mais consultez - l'option suivante). - -- exact=on. Ce switch permet d'indiquer au serveur hkp qu'il ne doit - rechercher que les correspondances exactes. Dans ce cas, les - délimiteurs et l'ordre des mots sera considéré. - -- fingerprint=on. Renvoie également les fingerprint, lorsque utilisé - avec 'index' ou 'vindex' - -Les serveurs de clefs savent aussi reconnaître le format http-POST vers /pks/add. -Vous utilisez ceci pour envoyer des clefs au serveur. - -Le mieux pour produire une requête reste : - - /pks/lookup/?op= - -Ceci peut être implémenté en utilisant le mécanisme de traduction Hurd. -Toutefois, nous pensons que les traitements du serveur de clef doivent -faire l'objet d'une refonte. diff --git a/doc/fr/FAQ b/doc/fr/FAQ deleted file mode 100644 index 48c28ae76..000000000 --- a/doc/fr/FAQ +++ /dev/null @@ -1,1111 +0,0 @@ - -GNUPG : FOIRE AUX QUESTIONS - -Version : 1.2 -Dernière modification : 10 septembre 2001 -Maintenu par : Nils Ellmenreich -Traduction : Gilbert Fernandes - -Ce document est la FAQ de GnuPG. La dernière version HTML est -disponble ici : - -L'index est produit automatiquement. Des erreurs peuvent donc -s'y trouver. Toutes les questions ne seront pas situées dans leurs -sections afférentes. Les suggestions quand à l'amélioration de cette -FAQ seront les bienvenues. - -Veuilez envoyer vos additions et corrections au mainteneur de la FAQ. -Il serait plus pratique si vous pouviez fournir une réponse à inclure -directement dans la FAQ. Toute aide sera fortement appréciée. - -Veuillez ne pas nous envoyer de message du type : "Ceci devrait -être une FAQ, quelle est la réponse ?". Si la réponse ne se trouve -pas dans la FAQ c'est que la question n'a pas été considérée. -Dans ce cas, recherchez dans les archives de la liste de -distribution par email. - - - - - 1. GENERAL - 1.1) Qu'est-ce que GnuPG ? - 1.2) GnuPG est-il compatible avec PGP ? - - 2. SOURCES D'INFORMATION - 2.1) Où puis-je trouver plus d'informations ? - 2.2) Où puis-je obtenir GnuPG ? - - 3. INSTALLATION - 3.1) Sur quels systèmes fonctionne GnuPG ? - 3.2) Quel collecteur d'entropie dois-je utiliser ? - 3.3) Comment puis-je inclure le support du RSA et de l'IDEA ? - - 4. UTILISATION - 4.1) Quelle est la taille de clef recommandée ? - 4.2) Pourquoi la création de clefs est-elle aussi longue ? - 4.3) Pourquoi tout est si lent quand je travaille sur un système distant ? - 4.4) Quelle est la différence entre options et commandes ? - 4.5) Je ne peux pas effacer un userid car il a déjà été effacé dans mon - trousseau de clefs publiques ? - 4.6) Que sont la confiance, la validité et l'ownertrust ? - 4.7) Comment puis-je signer un fichier de patch ? - 4.8) Où se trouve l'option "encrypt-to-self" ? - 4.9) Comment puis-je me débarasser de la version et du champ de commentaire - dans la version "armor" des messages ? - 4.10) Que signifie le message "You are using the xxxx character set" ? - 4.11) Comment puis-je obtenir la liste des keyid ayant servi à - chiffrer un message ? - 4.12) Je ne peux plus déchiffrer mon message chiffré symétriquement (-c) avec la nouvelle -version de GnuPG ? - 4.13) Comment puis-je utiliser GnuPG en environnement automatisé ? - 4.14) Quel client email puis-je utiliser avec GnuPG ? - 4.15) On ne peut pas avoir une librairie gpg ? - 4.16) J'ai produit avec succès un certificat de révocation, mais comment dois-je - le transmettre aux serveurs de clefs ? - - 5. QUESTIONS SUR LA COMPATIBILITE - 5.1) Comment puis-je chiffrer un message avec GnuPG pour que PGP soit capable de le déchiffrer ? - 5.2) Comment migrer de PGP 2.x vers GnuPG ? - 5.3) (supprimé) - 5.4) Pourquoi PGP 5.x n'est pas capable de déchiffrer les messages pour certaines clefs ? - 5.5) Pourquoi PGP 5.x ne peut vérifier mes messages ? - 5.6) Comment puis-je transférer mes valeurs de confiance de PGP vers GnuPG ? - 5.7) PGP n'aime pas ma clef privée. - - 6. PROBLEMES ET MESSAGES D'ERREUR - 6.1) Pourquoi GnupG me dit sans cesse "Warning : using insecure memory!" ? - 6.2) Le support des fichiers de grande taille ne fonctionne pas .. - 6.3) Dans le menu d'édition les valeurs de confiance ne sont pas affichées - correctement après la signature des uid : pourquoi ? - 6.4) Que signifie "skipping pubkey 1: already loaded" ? - 6.5) GnuPG 1.0.4 ne tient pas compte de ~/.gnupg ... - 6.6) Une signature ElGamal ne vérifie plus rien depuis la 1.0.2 .. - 6.7) Les anciennes versions de GnuPG ne vérifient pas les anciennes - signatures ElGamal - 6.8) Lorsque j'utilise --clearsign le texte en clair comporte parfois des - tirets supplémentaires : pourquoi ? - 6.9) Que signifie "can't handle multiple signatures" ? - 6.10) Si je soumet une clef au serveur de clefs, rien ne survient ! - 6.11) J'obtiens un "gpg: waiting for lock ..." - 6.12) Les anciennes versions de GnuPG (e.g. 1.0) ont des problèmes - avec les clefs de GnuPG récents .. - 6.13) Avec GnuPG 1.0.4 j'obtiens un "this cipher algorithm is deprecated ..." - 6.14) Les dates sont affichées par ????-??-??, pourquoi ? - 6.15) J'ai encore un problème, dois-je produire un message de bogue ? - 6.16) Pourquoi GnuPG ne supporte pas les certificats X.509 ? - - 7. SUJETS AVANCES - 7.1) Comment tout cela fonctionne-t-il ? - 7.2) Pourquoi certaines signatures avec une clef ELG-E sont valides ? - 7.3) Comment tout le système de confiance fonctionne au juste ? - 7.4) Quel est ce genre de sortie : "key C26EE891.298, uid 09FB: ...."? - 7.5) Comment interpréter certaines sorties informatives ? - 7.6) Les lignes d'en-tête des messages font-elles parties des éléments signés ? - 7.7) Quelle est la liste des algorithmes préférés ? - 7.8) Comment puis-je changer la liste des algorithmes préférés ? - - 8. REMERCIEMENTS - - - -1. GENERAL - -1.1) Qu'est-ce que GnuPG ? - -GnuPG signifie GNU Privacy Guard et est -l'outil GNU destiné aux communications protégées par chiffrement, -ainsi que le stockage protégé d'informations. Ce programme peut -être utilisé pour chiffrer des données et produire des signatures -numériques. Il comprend une gestion avancée des clefs et respecte -le standard Internet proposé OpenPGP comme décrit dans le -RFC 2440 : et il se destine -à une parfaite compatibilité avec le PGP produit par NAI Inc. - -1.2) GnuPG est-il compatible avec PGP ? - -En règle générale, oui. GnuPG et les distributions récentes de PGP -devraient respecter le standard OpenPGP et fonctionner de concert. -Il existe toutefois quelques problèmes d'interopérabilité. Consultez -les questions 5.1ff pour plus de détails. - -2. SOURCES D'INFORMATION - -2.1) Où puis-je trouver plus d'informations ? - -Voici une liste de ressources en ligne : - - - -Cette page regroupe la page de documentation GnuPG. Vous pouvez consulter -les HOWTO ainsi que le manuel de GnuPG : le GNU Privacy Handbook -actuellement disponible en anglais, espagnol et russe. Ce dernier offre par -ailleurs une présentation étendue de GnuPG. Vous trouverez aussi des -documentations expliquant la conversion de PGP 2.x vers GnuPG. - - - -Vous trouverez ici une archive en ligne des listes de distribution par -courrier électronique de GnuPG. La liste la plus intéressante sera -probablement gnupg-users où toutes les questions en rapport avec -l'utilisation de GnuPG se trouvent rassemblées. Si le développement -vous intéresse vous consulterez avec joie la liste gnupg-devel et -vous pourrez également prendre contact avec les développeurs. - -S'IL-VOUS-PLAIT ! - -Avant de poster sur une liste, veuillez lire avec attention la FAQ et -toutes les documentations disponibles. D'autre part, vous devez ensuite -consulter les archives afin de découvrir si votre question n'a pas été -déjà posée et résolue. Vous épargnerez des pertes de temps et la -liste pourra se concentrer sur les problèmes qui n'ont pas encore -été résolus. - -La distribution des sources de GnuPG comprend également un -sous-répertoire /doc qui contient des documentations supplémentaires -et ces informations seront précieuses aux hackers (pas beaucoup aux -utilisateurs habituels, sauf les plus curieux). - -2.2) Où puis-je obtenir GnuPG ? - -Vous pouvez télécharger GNU Privacy Guard depuis son FTP primaire : - - - -Ou depuis l'un des mirroirs : - - - -La version actuelle est la version 1.0.6 et nous vous encourageons à migrer -vers cette version rapidement : elle corrige des bogues et améliore le -fonctionnement du programme, ainsi que votre sécurité de fait. - - -3. INSTALLATION - -3.1) Sur quels systèmes fonctionne GnuPG ? - -GnuPG devrait fonctionner sur tous les Unices ainsi que Windows (95, 98..) et les variantes -NT. Une liste de systèmes d'exploitation fonctionnels se trouve à : - - - -3.2) Quel collecteur d'entropie dois-je utiliser ? - -Les "bons" générateurs de nombres aléatoires sont cruciaux pour la sécurité de vos -chiffrements. Les différents systèmes d'exploitation proposent des valeurs -aléatoires de qualité variable. Linux et les systèmes *BSD produisent généralement -de bonnes valeurs grâce au /dev/random et cette méthode devrait rester la -méthode de choix pour ces systèmes. Les utilisateurs de Solaris devraient opter -pour pe paquetage SUNWski afin de disposer d'un /dev/random. Dans ces cas, -vous devriez utiliser l'option --enable-static-rnd=linux. D'autre part, il existe également -un dispositif au niveau kernel pour la production de valeurs aléatoires développé -par Andi Maier : - -< http://www.cosy.sbg.ac.at/~andi> - -Ce logiciel est au stade de beta : vous ne l'utilisez que sous votre seule -responsabilité ! - -Sur les autres systèmes, l'utilisation de l'EGC ou "Entropy Gathering Daemon" -se montre un bon choix. C'est un daemon écrit en Perl qui surveille l'activité du -système et produit des hachages permettant d'obtenir des valeurs aléatoires. -Vous devriez en consulter la page de téléchargement depuis : - - - -Pour l'utiliser vous devrez utiliser l'option --enable-static-rnd=egd - -Si les options ci-dessus ne fonctionne pas, vous pourrez utiliser le producteur -d'entropie "unix". Il est *TRES* lent et il devrait être évité lorsque possible. -Sa qualité d'entropie laisse vraiment à désirer et vous ne devrez jamais -l'utiliser dans la protection de données sensibles. - -3.3) Comment puis-je inclure le support du RSA et de l'IDEA ? - -RSA se trouve inclus dans GnuPG depuis la version 1.0.3 et supérieures. - -La distribution officielle de GnuPG ne comprend pas l'IDEA à cause -d'une restriction par brevêt. Le brevêt devrait expirer en 2007 et nous -attendons cette date pour l'inclure dans GnuPG. - -Toutefois, il existe des modules officieux qui permettent de l'inclure -même dans les versions de GnuPG avant cette date. Ces modules -sont disponibles depuis : - - - -Recherchez 'idea.c' - -Les directives de compilation se trouvent dans les fichiers "headers" de -ces fichiers. Vous pourrez ensuite ajouter la ligne suivante à votre -fichier ~/.gnupg/options : - - load-extension idea - -4. USAGE - -4.1) Quelle est la taille de clef recommandée ? - -Nous vous recommandons un minimum de 1024 bits pour les clefs de type -DSA et également pour les signatures simples de type ElGamal. La taille -du hachage est probablement le lien le plus faible si la taille de la clef -augmente à plus de 1024 bits. Les clefs de chiffrement peuvent avoir -des tailles supérieures, mais vous devriez alors vérifier le fingerprint -de la clef de cette manière : - -gpg --fingerprint --fingerprint - -Comme pour les algorithmes de clef, vous devriez vous en tenir aux -valeurs par défaut (i.e. les chiffrements ElGamal avec signature -DSA). Une clef de signature ElGamal comporte les désavantages -suivants : si la signature est grosse, il est difficile de créer une -clef correspondante utile pour les signatures et capable de résister -aux attaques réelles, et vous n'obtiendrez pas de sécurité -supplémentaire face au DSA. Il pourrait y avoir des problèmes -de compatibilité avec certaines versions de PGP. Il n'aura été -introduit que parce à l'époque, il n'était pas clair de savoir si -un brevêt s'appliquait ou non au DSA. - -4.2) Pourquoi la création de clefs est-elle aussi longue ? - -Le problème est ici que nous avons besoin d'une grande quantité d'octets aléatoires et que -nous devons pour ce faire collecter une certaine quantité d'entropie depuis, sous Linux, -le /dev/random. Il n'est pas vraiment facile de remplir l'entropie de Linux ; nous en avons -discuté avec Ted Ts'o et il a expliqué que la meilleure méthode pour remplir le buffer -n'est autre que de jouer avec votre clavier. Une bonne sécurité implique un coût. -Vous pouvez utiliser les touches Shift, Control, Alt en appuyant dessus de manière aléatoire, -d'autant que ces touches ne produisent aucune sortie à l'écran et vous pourrez accélérer -la production des clefs. - -Un autre programme pourrait également consommer une partie de l'entropie du système -dont vous avez besoin (jettez un oeil à vos daemons actifs). - -4.3) Pourquoi tout est si lent quand je travaille sur un système distant ? - -Vous ne devez SURTOUT pas faire cela ! Vous ne devez jamais créer de -clef GnuPG sur un système distant car vous n'aurez alors aucun contrôle -physique sur votre clef privée, ni même votre trousseau de clefs privées. -Ces clefs seront alors suspectibles de subir une attaque par dictionnaire. -Nous vous encourageons vivement à ne produire vos clefs que sur une -machine personnelle (un portable déconnecté de toute alimentation -et connexion réseau est le meilleur choix) et si vous devez conserver -votre clef privée sur une machine fixe, assurez-vous qu'une phrase -passe solide en protège le contenu et que vous pouvez faire confiance -à votre administrateur système. - -Lorsque nous devons utiliser GnuPG à distance c'est au-travers de SSH -et nous rencontrons le même problème. Il faut *beaucoup* de temps -pour produire des clefs de toute manière. Il ne faut pas créer de clefs -à distance. Si vous avez juste besoin de clefs à fins de tests, vous -pouvez utiliser l'optoin --quick-random pour produire rapidement des -clefs *faibles* qui permettent de vérifier quelques tests. - -4.4) Quelle est la différence entre options et commandes ? - -Si vous tapez 'gpg --help' vous obtiendrez deux listes séparées. La première -liste vous répertorie les commandes. La seconde liste regroupe elle les -options. A chaque fois que vous utiliserez GnuPG vous devrez utiliser -*UNE* commande (avec une exception, voir ci-dessous) et vous pourrez -utiliser une ou *plusieurs* options en combinaison avec la commande. - -Par convention, la commande doit se trouver à la fin de la liste d'arguments -après toutes les options. Si la commande requiert un nom de fichier, -ce dernier sera donné à GnuPG en *dernier* sur la ligne de commande. - -L'usage basique de GnuPG est donc : - - gpg [--option something] [--option2] [--option3 something] --command file - -Certaines options demandent des arguments. Par exemple, l'option ---output (que l'on peut raccourcir par -o) requiert un nom de fichier -en argument. L'argument de l'option doit suivre celle-ci immédiatement ! -GnuPG ne sera sinon pas capable de différencier le nom de fichier comme -option. Comme option, --output et son nom de fichier doivent se trouver -avant la commande donnée à GnuPG. L'option --recipient (ou -r) demande -un nom ou un keyID pour chiffrer le message et ces informations devront -imméditamenet suivre l'option --recipient/-r. La commande --encrypt ou --e sera fournie après ces options, avec en final le nom du fichier à -chiffrer. En voici un exemple : - - gpg -r alice -o secret.txt -e test.txt - -Mais l'utilisation des options sous leur forme longue permet de simplifier -la compréhension des lignes de commande : - - gpg --recipient alice --output secret.txt --encrypt test.txt - -Si vous sauvez dans un fichier nommé ".txt" alors vous devriez probablement -utiliser l'option ARMOR en ajoutant l'option --armor ou -a qui ne prend aucun -argument : - - gpg --armor --recipient alice --output secret.txt --encrypt test.txt - -Si nous plaçons des crochets autour des parties optionnelles, les choses -deviennent plus claires : - - gpg [--armor] [--recipient alice] [--output secret.txt] --encrypt test.txt - -Les parties entre crochets peuvent être placées dans l'ordre de votre -choix : - - gpg --output secret.txt --recipient alice --armor --encrypt test.txt - -Si votre nom de fichier commence par un tiret, GnuPG risque de penser -qu'il s'agit d'un paramètre et pour éviter cette situation vous pouvez -soit utiliser un "./-a.txt" soit utiliser un double-tiret comme ceci : - --- -a.txt - -* L'exception concerne le chiffrement ET la signature au même moment. -On utilise alors gpg [--options] --sign --encrypt foo.txt - -4.5) Je ne peux pas effacer un userid car il a déjà été effacé dans mon - trousseau de clefs publiques ? - -Comme vous ne pouvez sélectionner que depuis le trousseau de clefs -publiques, vous ne pouvez pas directement effacer le userid. Toutefois, -ce n'est pas très compliqué à faire. Vous devez créer un nouvel -utilisateur, disposant du même userid ce qui vous permet d'obtenir deux -utilisateurs identiques avec un seul disposant d'une correspondance -dans la clef privée. Vous pouvez désormais sélectionner cet utilisateur -et l'effacer. Les deux identifiants seront affacés du trousseau de clefs -privées. - -4.6) Que sont la confiance, la validité et l'ownertrust ? - -Le terme "ownertrust" est utilisé en remplacement de "trust" lorsqu'il -s'agit de la valeur que vous avez attribuée à une clef en fonction -du degré de confiance que vous accordez à son propriétaire, et si -vous l'autorisez à introduire de nouvelles clefs avec votre signature -jointe. La "validité" est un terme de confiance calculée, une valeur -numérique calculée par GnuPG en fonction des paramètres de -confiance des clefs et vous donne une idée de la confiance que -GnuPG attribue ou n'attribue pas à une clef et s'il estime que la clef -est valide pour un usage de chiffrement. Pour plus de détails consultez -le chapître "The web of trust" - -4.7) Comment puis-je signer un fichier de patch ? - -Vous pouvez utiliser : - -gpg --clearsign --not-dash-espaced ... - -Le problème avec --clearsign c'est que toutes les lignes qui -commençent par un tiret sont "quotées" avec "- " et comme diff -produit beaucoup de lignes de ce type, le patch risque d'être -détruit par la signature. Pour utiliser un fichier patch en le signant -et sans perdre la signature claire, l'option spéciale : - ---not-dash-escaped - -Permet de supprimer la production de ces séquences d'échappement. -Vous ne devriez pas transmettre par courrier électronique un patch -de ce type car les espaces et les fins de ligne font également -partie de la signature et un logiciel de messagerie risque de modifier -l'espacement et/ou les tailles de lignes, invalidant la signature. Si vous -souhaitez transmettre le fichier, le plus simple reste de le signer à l'aide -de votre MUA. - -4.8) Où se trouve l'option "encrypt-to-self" ? - -Utilisez l'option : - ---encrypt-to - -Vous pouvez utiliser une combinaison de cette option pour spécifier -plus d'un keyID. Pour désactiver temporairement l'utilisation de clefs -additionnelles, vous pouvez utiliser l'option : --no-encrypt-to. - -4.9) Comment puis-je me débarasser de la version et du champ de commentaire - dans la version "armor" des messages ? - -Utilisez l'option --no-version --comment "" - -Veuillez noter que la ligne vide laissée en place est *requise* par le format -et le protocole. - -4.10) Que signifie le message "You are using the xxxx character set" ? - -Cette note est affichée lorsque une conversion UTF-8 a été réalisée. -Veuillez vous assurer que le jeu de caractères utilisé pour l'affichage -correspond bien à celui du système. Le plus utilisé reste "iso-8859-1" et -c'est le jeu de caractères par défaut. Vous pouvez modifier ce jeu -de caractères à l'aide de l'option "--charset". Il faut que le jeu de -caractères utilisé corresponde à celui de votre affichage ou des -caractères pourraient ne plus correspondre dans le message une -fois transmis. Sinon, n'utilisez que de l'ASCII 7 bits pour qu'aucune -conversion ne puisse survenir. - -4.11) Comment puis-je obtenir la liste des keyid ayant servi à - chiffrer un message ? - - gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \ - awk '/^\[GNUPG:\] ENC_TO / { print $3 }' - -4.12) Je ne peux plus déchiffrer mon message chiffré symétriquement - (-c) avec la nouvelle version de GnuPG ? - -Il existait un bogue dans les versions 1.0.1 et antérieures de GnuPG -qui surveniait lorsque 3DES ou Twofish avaient été utilisé pour des -chiffrements symétriques (ce qui n'a jamais été le cas par défaut). -Ce bogue a été corrigé afin de permettre le déchiffrement des anciens -messages, en utilisant l'option : - ----emulate-3des-s2k-bug - -Vous devriez déchiffrer puis rechiffrer (correctement) le ou les -messages concernés. Cette option sera retirée dans la version 1.1 -de GnuPG : n'attendez pas pour convertir vos messages ! - -4.13) Comment puis-je utiliser GnuPG en environnement automatisé ? - -Vous devriez utiliser l'option --batch et ne pas utiliser de phrase -passe car il n'existe alors aucun moyen de conserver cette -information de manière plus secrète que le trousseau de clefs -lui-même. Nous vous suggérons de créer vos clefs, en environnement -automatisé, de la manière suivante : - -Sur une machine protégée : - -Créez une sous-clef de signature pour votre clef, en utilisant le menu -edit et en utilisant l'option "addkeu" puis DSA. Vous devez ensuite -vous assurer que vous utilisez une phrase passe (requise par -l'implémentation actuelle) puis utiliser : - -gpg --export-secret-subkeys --no-comment foo - >secring.auto - -Copiez secring.auto et le trousseau de clefs publiques dans un -répertoire test. Entrez dans le répertoire, puis : - -gpg --homedir . --edit foo - -Et utilisez "passwd" pour retirer la phrase passe des sous-clefs. -Vous devriez également retirer toutes les sous-clefs qui ne sont -pas utilisées et copier secring.auto sur une disquette et la -porter jusqu'à la machine cible. - -Sur celle-ci, installez secring.auto comme trousseau de clefs -secrètes. Vous pouvez maintenant faire démarrer votre -nouveau service. C'est aussi une bonne idée que d'installer -un système de détection d'intrusions afin de pouvoir repérer -les intrusions ce qui vous permettra alors de révoquer toutes -les sous-clefs installées sur cette machine et de procéder à une -nouvelle installation de sous-clefs. - -4.14) Quel client email puis-je utiliser avec GnuPG ? - -Utiliser GnuPG pour le chiffrement de courrier électronique est -probablement l'usage le plus répandu. De nombreux logiciels de -messagerie (les "MUA") supportent GnuPG à divers degrés. Pour simplifier, -il existe deux moyens de chiffrer les emails avec GnuPG : l'ancien style -qui repose sur l'utilisation de l'ASCII Armor (un chiffrement classique -suivi par une conversion selon le RFC2015) ce qu'on appellait le -PGP/MIME et qui s'appelle désormais l'OpenPGP. Ce dernier supporte -d'autre part le MIME. Certains MUA ne supportent qu'un seul de ces -formats et vous devrez utiliser ce qui correspond aux capacités -de votre client de messagerie. - -La liste suivante n'est probablement pas exhaustive : - - OpenPGP: Mutt (Unix), Emacs/Mew, Becky2 (Windows avec plugin), - TkRat (Unix). Il y a un effort pour disposer d'un plug-in - Mozilla et Emacs/GNUS dispose d'un support en CVS. - - ASCII: Emacs/{VM,GNUS}/MailCrypt, Mutt(Unix), Pine(Unix), et - probablement beaucoup d'autres. - -Un bon aperçu du support de PGP se trouve à l'adresse : - -http://cryptorights.org/pgp-users/pgp-mail-clients.html - -Le support direct de GnuPG n'est pas indiqué, toutefois dans certains -cas il doit être possible d'utiliser un "wrapper". - -4.15) On ne peut pas avoir une librairie gpg ? - -Cette question aura souvent été posée. Toutefois, le point de vue -actuel est que GnuPG en tant que librairie risque de conduire à des -problèmes de sécurité. Dans un futur proche, GnuPG ne sera pas -implémenté sous forme de librairie. Toutefois, pour quelques domaines -d'application le programme gpgme doit pouvoir assurer ces questions. -Vous pouvez obtenir ce programme depuis : - -ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme - - -4.16) J'ai produit avec succès un certificat de révocation, mais comment - dois-je le transmettre aux serveurs de clefs ? - -La plupart des serveurs de clefs n'accepteront pas une simple et "dure" -révocation. Vous devez d'abord importer le certificat dans GnuPG : - - gpg --import my-revocation.asc - -Puis transmettre la révocation au serveurs de clefs : - - gpg --keyserver certserver.pgp.com --send-keys mykeyid - -5. COMPATIBILITY ISSUES - -5.1) Comment puis-je chiffrer un message avec GnuPG pour que PGP - soit capable de le déchiffrer ? - -Tout ceci dépend de la version de PGP. - - PGP 2.x - -Vous ne pourrez pas dans ce cas, car PGP 2.x utilise l'IDEA qui n'est -pas un algorithme supporté par GnuPG à cause de son brevêt (voir -la section 3.3) mais si vous disposez d'une version modifiée de PGP -vous pouvez essayer ceci : - - gpg --rfc1991 --cipher-algo 3des ... - -Attention ! N'utlisez pas de pipe des données à chiffrer vers gpg, -mais donnez à gpg un nom de fichier sinon PGP 2 ne sera pas -capable de le prendre en charge. - -Quand à ce qui concerne le chiffrement conventionnel, vous ne -pouvez l'obtenir avec PGP 2. - - - PGP 5.x et ultérieurs - -Vous devrez utiliser deux options additionnelles : - - --compress-algo 1 --cipher-algo cast5 - -Vous devrez parfois utiliser "3des" au lieu de "cast5". PGP 5 ne -supporte pas l'algorithme "blowfish". Vous devrez aussi insérer -un "compress-algo 1" au sein de votre fichier ~/.gnupg/options -et ceci n'affectera pas le fonctionnement général de GnuPG. - -Ceci s'applique également au chiffrement conventionnel. - -5.2) Comment migrer de PGP 2.x vers GnuPG ? - -PGP 2 utilise les algorithmes RSA et IDEA pour le chiffrement. Depuis que le -brevêt sur le RSA a expiré GnuPG incorpore ce dernier, depuis la version -1.0.3 et ultérieures. L'algorithme IDEA reste sous brevêt jusqu'en 2007. -Sous certaines conditions vous pouvez utiliser l'IDEA, même aujourd'hui. -Dans ce cas, vous devriez consulter la réponse à la question 3.3 qui -explique l'ajout du support de l'IDEA à GnuPG et également lire ce -document : - -http://www.gnupg.org/gph/en/pgp2x.html - -Pour procéder à la migration. - -5.3) (supprimé) - - (vide) - -5.4) Pourquoi PGP 5.x n'est pas capable de déchiffrer les messages - pour certaines clefs ? - -PGP Inc refuse d'accepter les clefs ElGamal de type 20 même pour -le chiffrement. Ils ne supportent que le type 16 (qui est identifique en tout -cas en ce qui concerne le déchiffrement). Pour être plus inter-opérable, -GnuPG (depuis la version 0.3.3) utilise également le type 16 pour la sous- -clef ElGamal qui est créée par l'algorithme par défaut. Vous pouvez -aussi ajouter une clef de type 16 à votre trousseau de clefs publiques -tout en assurant que vos signatures sont valides. - -5.5) Pourquoi PGP 5.x ne peut vérifier mes messages ? - -PGP 5.x n'accepte pas les signatures en version 4 pour les données -mais OpenPGP demande la production de clefs V4 pour tous les types -de données et c'est pourquoi GnuPG les utilise... Vous devrez utiliser -l'option --force-v3-sigs pour produir'e des signatures V3 sur les -données. - -5.6) Comment puis-je transférer mes valeurs de confiance de - PGP vers GnuPG ? - -Il existe un script au sein du répertoire tools qui pourra vous aider. Après -avoir importé le trousseau de clefs publiques PGP vous pouvez utiliser -cette commande : - - $ lspgpot pgpkeyring | gpg --import-ownertrust - -où "pgpkeyring" est le trousseau de clefs originels et NON celui de GnuPG -que vous avez produit à la première étape. - -5.7) PGP n'aime pas ma clef privée. - -Les anciens PGP échouent parfois au traitement des commentaires privés -sur les paquets utilisés par GnuPG. Ces paquets sont en *totale* conformité -avec OpenPGP mais vous l'aurez compris, PGP n'est pas vraiment soucieux -d'OpenPGP. Pour contourner ce problème il faut exporter les clefs privées -à l'aide de cette commande : - - $ gpg --export-secret-keys --no-comment -a your-key-id - -Une autre possibilité : par défaut, GnuPG chiffre votre clef privée à l'aide -de l'algorithme symétrique Blowfish. Les anciennes versions de PGP -ne peuvent comprendre que le 3DES, CAST5 ou l'IDEA sous leurs formes -symétriques. L'utilisation de la méthode suivante permet de rechiffrer -vos clefs privées à l'aide d'un algorithme différent : - - $ gpg --s2k-cipher-algo=CAST5 --s2k-digest-algo=SHA1 \ - --compress-algo=1 --edit-key - -Vous utiliserez alors l'option passwd pour modifier le mot de passe ; il suffit -de choisir la même phrase passe mais cette fois la clef sera chiffrée -symétriquement par du CAST5. - -Vous pouvez maintenant exporter la clef et PGP devrait pouvoir la gérer. - -Pour PGP 6.x les options suivantes permettent d'exporter une clef : - - $ gpg --s2k-cipher-algo 3des --compress-algo 1 --rfc1991 \ - --export-secret-keys - -6. PROBLEMS and ERROR MESSAGES - -6.1) Pourquoi GnupG me dit sans cesse "Warning : using insecure memory!" ? - -Sur beaucoup de systèmes, ce programme doit être installé en tant que -setuid(root). Ceci est requis afin de pouvoir produire un blocage en mémoire -des pages utilisées (et d'éviter tout transfert en swap ou sur disque). Ce "lock" -permet de verrouiller dans la pratique les informations sensibles en RAM -afin de conserver ces données comme secrètes. Si vous n'obtenez aucun -message d'erreur c'est que votre système supporte le verrouillage de pages -mémoire depuis l'accès root (le programme s'exécute en tant que root grâce -à son setuid). Le programme quitte le mode d'exécution "root" dès que les -pages sont verrouillées en mémoire qui plus est. - -Sur Unixware 2.x et 7.x vous devriez installer GnuPG avec le privilège -"plock" pour obtenir le même effet : - - filepriv -f plock /path/to/gpg - -Si vous ne pouvez pas installer GnuPG en tant que setuid(root) ou si vous -ne voulez pas, vous pouvez utiliser l'option : - ---no-secmem-warning - -Ou bien le placer en tant qu'option (sans les deux tirets) dans votre -fichier ~/.gnupg/options ce qui permet de désactiver le warning. - -Sur quelques systèmes (e.g; Windows) GnuPG ne verrouille pas les -pages en mémoire (ce n'est pas toujours possible selon les systèmes) -et les anciennes versions de GnuPG (1.0.4 et antérieures) produisent -sur ces systèmes le message d'erreur suivant : - - gpg: Please note that you don't have secure memory - -Cet avertissement ne peut être désactivé en utilisant l'option décrite -ci-dessus car nous considérons que cet avertissement forme une -faille de sécurité importante. Toutefois, comme il provoquait une trop -forte confusion auprès des utilisateurs de ces systèmes, le message -d'avertissement a été retiré. - -6.2) Le support des fichiers de grande taille ne fonctionne pas .. - -Le LFS fonctionne correctement depuis les versions 1.0.4 et ultérieures. -Si le configure ne le détecte pas correctement, essayez un autre -compilateur : egcs 1.1.2 fonctionne parfaitement mais d'autres -versions semblent poser problème. D'autre part, certains problèmes -de compilation rencontrés dans GnuPG 1.0.3 et 1.0.4 sur HP-UX et -Solaris étaient provoqués par un support "cassé" du LFS dans les -sources ... - -6.3) Dans le menu d'édition les valeurs de confiance ne sont pas affichées - correctement après la signature des uid : pourquoi ? - -Ceci survient car certaines informations sont stockées immédiatement -dans la TrustDB, mais le calcul ne se réalisé qu'au moment de la -sauvegarde effective. Ce n'est pas un bogue vraiment facile à corriger -mais nous pensons régler ce problème dans une future version. - -6.4) Que signifie "skipping pubkey 1: already loaded" ? - -Depuis la version 1.0.3 de GnuPG l'algorithme RSA est inclus. Si vous -avez toujours l'option : - -load-extension rsa - -Dans votre fichier .options le message en question apparaîtra. -Il vous suffira de retirer la commande qui n'est plus requise -du fichier .options pour que le message cesse. - -6.5) GnuPG 1.0.4 ne tient pas compte de ~/.gnupg ... - -Ce bogue est connu et il a été corrigé dans les versions ultérieures. - -6.6) Une signature ElGamal ne vérifie plus rien depuis la 1.0.2 .. - -Utilisez l'option : - ---emulate-md-encode-bug - - Use the option --emulate-md-encode-bug. - -6.7) Les anciennes versions de GnuPG ne vérifient pas les anciennes - signatures ElGamal - -Veuillez migrer vers la version 1.0.2 au minimum, et de préférence -une version ultérieure (1.0.6 par exemple). - -6.8) Lorsque j'utilise --clearsign le texte en clair comporte parfois des - tirets supplémentaires : pourquoi ? - -Ceci s'appelle le "dash-escaped" et il est requis par le format -OpenPGP. A chaque fois qu'une ligne commence par un tiret, ceci -risque de survenir. Cela permet aux programmes de retrouver -sans difficulté les lignes de marquage du format, comme : - ------BEGIN PGP SIGNATURE----- - -Seules ces lignes doivent pouvoir commencer par deux tirets. Si vous -utilisez GnuPG pour traiter ces messages, les tirets supplémentaires -seront retirés et les clients de messagerie "corrects" devraient -également retirer ces tirets lorsqu'ils affichent le message. - -6.9) Que signifie "can't handle multiple signatures" ? - -A cause des différents formats de messages, GnuPG n'est pas toujours -capable de découper un fichier contenant des signatures multiples. -Ce message d'erreur vous informe que les données en entrée -comportent un problème. Le seul moyen pour disposer correctement -de signatures multiples revient à utiliser le standard : le format -OpenPGP avec les paquets "one-pass-signature" qui sont utilisés -par défaut par GnuPG ou bien de recourir au format de texte en clair. - -6.10) Si je soumet une clef au serveur de clefs, rien ne survient ! - -Vous utilisez probablement GnuPG sur Windows en version 1.0.2 ou -antérieure. Cette fonctionnalité n'était alors pas encore disponible, -et il ne s'agit pas d'un bogue. Vous devriez adopter une version -plus récente, qui dispose de toutes les fonctionnalités :-) - -6.11) J'obtiens un "gpg: waiting for lock ..." - -Les anciennes versions de GnuPG ne quittaient pas correctement -et laissaient un fichier "lock". Allez dans le répertoire ~/.gnupg et -effacez les fichiers *.lock qui s'y trouvent pour continuer. - -6.12) Les anciennes versions de GnuPG (e.g. 1.0) ont des problèmes - avec les clefs de GnuPG récents .. - -Depuis la version 1.0.3 les clefs produites par GnuPG sont créées avec -une préférence pour Twofish (et l'AES depuis la version 1.0.4 à savoir, -l'algorithme Rijndael) et ceci signifie également qu'elles disposent de la -capacité d'utilisation de la nouvelle méthode de chiffrement MDC. Ceci -sera disponible dans OpenPGP très rapidement et sera supporté en -tout logique par PGP 7. Cette nouvelle méthode de chiffrement permet -de se protéger votre des attaques (des anciennes attaques en fait) -contre les systèmes de chiffrement du courrier électronique. - -Ceci signifie également que les versions 1.0.3 et antérieures de GnuPG -auront des problèmes avec les clefs plus récentes. A cause des -correctifs de sécurité, vous devriez conserver votre installation -de GnuPG à jour de toute manière. Comme manière de régler le -problème vous devriez demander à GnuPG de n'utiliser que l'ancien -algorithme de chiffrement en utilisant la ligne : - -cipher-algo cast5 - -dans votre fichiers d'options. - -6.13) Avec GnuPG 1.0.4 j'obtiens un "this cipher algorithm is deprecated ..." - -Si vous venez de produire une nouvelle clef et que vous obtenez ce message -pendant un chiffrement, il s'agit d'un bogue de la version 1.0.4 ; le nouvel -algorithme AES Rijndael est utilisé mais il n'est pas enregistré sous le bon -numéro d'algorithme ce qui produit ce message d'erreur "deprecated". -Vous pouvez ignorer cet avertissement et les versions plus récentes -de GnuPG sont corrigées sur ce point. - -6.14) Les dates sont affichées par ????-??-??, pourquoi ? - -A cause de contraintes dans la plupart des implémentations de la libc, -les dates au-delà de 2038-01-19 ne seront pas affichées correctement. -Les systèmes 64-bit ne sont pas affectés par ce problème. Pour éviter -d'afficher les dates de manière incorrecte, GnuPG utilise des signes -"?" au lieu des chiffres. Pour obtenir la valeur correcte vous devrez -utiliser l'option : - ---with-colons --fixed-list-mode - -6.15) J'ai encore un problème, dois-je produire un message de bogue ? - -Si vous êtes sûr(e) que le problème n'est mentionné nulle part, ni dans -cette FAQ ni dans aucune liste de distribution GnuPG, commencez -par consulter la liste de bogues qui sont en cours de traitement (la page -de documentation dispose d'un lien vers la page de bogues). Si vous -ne savez pas trop s'il s'agit d'un bogue, envoyez un courrier -électronique à la liste : gnupg-devel. Sinon, vous pouvez utiliser -le système de suivi de bogues GUUG à l'adresse : - -http://bugs.guug.de/Reporting.html. - -6.16) Pourquoi GnuPG ne supporte pas les certificats X.509 ? - -GnuPG est avant tout une implémentation du standard OpenPGP, -défini dans le RFC 2440. Ce standard propose une infrastructure -complète et différente du X.509 - -Ces deux systèmes sont des cryptosystèmes à clef publique, mais -la manière dont les clefs sont traitées diffèrent. - -7. SUJETS AVANCES - -7.1) Comment tout cela fonctionne-t-il ? - -Pour produire une paire de clefs publique/privée, utilisez la commande - -gpg --gen-key - -Puis répondez aux questions en adoptant de préférence les valeurs -par défaut. - -Les données qui sont chiffrées par une clef publique ne peuvent être -déchiffrées que par la clef privée correspondante. La clef secrète -est d'autre part protégée par une phrase-passe ce qui n'est pas le cas -de la clef publique, librement distribuable. - -Pour transmettre à vos amis un message, il vous suffit de le chiffrer -à l'aide de leurs clefs publiques. Seules leurs clefs privées seront -capables de déchiffrer le message. - -GnuPG est pratique pour signer de manière numérique les choses. -Les éléments qui sont chiffrés à l'aide de la clef publique ne peuvent -être déchiffrés que par la clef publique, ce qui permet de signer -des documents. On commence par produire un hachage, une sorte -d'empreinte à taille fixe d'un document (de taille variable). Ensuite, -votre clef privée est utilisée pour chiffrer ce hachage. Par la suite, -toute personne disposant de votre clef publique et du document -peut vérifier si le hachage du document correspond bien au -déchiffrement du hachage, obtenu par votre clef publique dont -disposent vos destinataires. - -Un trousseau de clefs n'est qu'un gros fichier (selon le nombre de -clefs qu'il contient). Vous avez un trousseau de clefs publiques -qui contient vos clefs publiques et celles de vos amis. Vous avez -également un trousseau de clefs privées qui ne contient que vos -clefs privées (chiffrées et protégées par votre phrase-passe). Vous -devez faire très *attention* à ce fichier. Personne ne devra jamais -y avoir accès et la phrase-passe qui le protège devra être -complexe, et longue afin de bien protéger le secret. - -Vous pouvez aussi chiffrer des données de manière conventionnelle, -en utilisant l'option "-c" de GnuPG. Dans ce cas, la phrase-passe -utilisée servira de clef pour protéger le message. Aucun usage -de clef publique ou de clef privée ici : il s'agit d'un chiffrement -classique où il n'existe qu'une seule clef, utilisée pour chiffrer et -déchiffrer les données. Généralement, on utilise cette méthode -pour chiffrer ses propres documents à l'aide d'une phrase-passe -secrète qui vous est propre. Cette méthode de chiffrement ne -doit être utilisée pour des communications que si vous avez -physiquement rencontré vos destinataires et que vous partagez -dans le plus grand secret la phrase-passe (votre propre époux ou -épouse, ou un ami de confiance). L'avantage est que vous pouvez -changer de temps en temps la phrase-passe et en réduire le -risque afin qu'en cas de découverte de la phrase-passe toutes -vos données ne soient pas lisibles ;-) - -Vous pouvez ajouter et copier des clefs depuis votre trousseau -de clefs publiques à l'aide des commandes "gpg --import" et -"gpg --export". Vous pouvez également (ATTENTION !!) exporter -vos clefs privées à l'aide de la commande : "gpg --export-secret-keys" -mais ce n'est généralement pas utile sauf si vous devez déplacer -vos clefs privées d'une machine à l'autre. - -Les clefs peuvent être signées à l'aide de l'option "gpg --edit-key". Lorsque -vous signez une clef, vous certifiez que la clef appartient selon vous -à la personne dont l'identité se trouve mentionnée dans la clef. Vous -devez absolument être sûr(e) que la clef appartient bien à cette -personne, sans le moindre doute. Vous devez vérifier son fingerprint -à l'aide de la commande : - -gpg --fingerprint userid - -Et recevoir le même finger par téléphone ou de visu par la personne -concernée. Généralement, on procède à des "fêtes" où chaque personne -amène sa pièce d'identité, une carte de visite comprenant le fingerprint -et l'on procède à un échange des fingerprint, ou directement des clefs. - -Vous pouvez également utiliser l'option "-o filename" pour forcer -la sortie vers le fichier "filename". Pour forcer une sortie en console -par défaut on utilise un tiret. La commande "-r" permet de spécifier -le destinataire (avec quelle clef publique vous allez chiffrer) en ligne -de commande au lieu d'avoir à taper le nom du destinataire dans -le mode interactif. - -Autre chose d'importance. Par défaut, TOUTES les données sont chiffrées -dans un format binaire particulier; Si vous souhaitez transmettre les données -par courrier électronique (par exemple) vous devez les protéger dans -un format d'amure qu'on appelle ASCII ARMOR. Ce format sera obtenu -en utilisant l'option "-a" mais la méthode préférée reste d'utiliser -un client de messagerie respectueux du format MIME comme Mutt, Pine -et bien d'autres. - -Enfin, il existe une petite faille de sécurité dans OpenPGP (et donc dans PGP) -et vous devriez TOUJOURS chiffrer PUIS signer un message. Il ne faut -pas seulement chiffrer afin d'être totalement protégé. N'oubliez jamais. - -7.2) Pourquoi certaines signatures avec une clef ELG-E sont valides ? - -Ces clefs ElGamal furent produites par GnuPG en version 3 de paquets -(selon le RFC 1991). Le brouillon OpenPGP a été modifié par la suite -afin de modifier l'identifiant d'algorithme pour les clefs ElGamal qui est -utilisable pour les signatures et le chiffrement des modes 16 à 20. -GnuPG utilise le mode 20 quand il produit ses nouvelles clefs ElGamal -mais il accepte toujours les clefs de type 16 qui selon le standard -OpenPGP ne peuvent servir qu'au chiffrement, si la clef se trouve -dans un paquet en version 3 du format. GnuPG est le seul programme -ayant jamais utilisé les clefs au sein de paquets v3 - vous ne risquez -donc pas grand chose. - -7.3) Comment tout le système de confiance fonctionne au juste ? - -Il fonctionne d'une manière proche de PGP. La différence c'est que -la confiance est calculée uniquement lorsqu'elle est requise. C'est -pourquoi la TrustDB contient une liste des signatures de clefs -valides. Si vous ne fonctionnez pas en mode batch, vous devrez -assigner un paramètre de confiance aux clefs (un ownertrust). - -Vous pouvez consulter la validité (la valeur de confiance -calculée) en utilisant cette commande : - - gpg --list-keys --with-colons - -Si le premier champ est "pub" ou "uid" le second champ vous -indiquera le niveau de confiance : - -o = Inconnu (cette clef est nouvelle au système) -i = La clef est invalide (eg. il manque sa propre signature) -d = La clef a été désactivée -r = La clef a été révoquée -e = La clef a expiré -q = Non-défini (pas de valeur attribuée) -n = Ne jamais faire confiance à cette clef -m = Cette clef dispose d'une confiance marginale -f = Cette clef dispose d'une confiance totale -u = Cette clef dispose d'une confiance ultime. Cette valeur - n'est utilisée que pour les clefs où la clef secrète est - également disponibles. - -La valeur dans l'enregistrement "pub" est la meilleure valeur -obtenue depuis les enregistrements "uid". - -Vous pouvez obtenir la liste des valeurs de confiance attribuées ; -i.e. la confiance que vous accordez aux autres lorsqu'il s'agit -de signer la clef d'un autre individu) : - - gpg --list-ownertrust - -Le premier champ est le fingerprint de la clef primaire, le second -champ est la valeur assignée : - -_ = Aucune valeur d'ownertrust assignée -n = Ne jamais faire confiance au propriétaire de cette clef - lorsqu'il s'agit de vérifier d'autres signatures. -m = Une confiance marginale est accordée au détenteur de cette clef - lorsqu'il s'agit de signer d'autres clefs. -f = Assumer que le détenteur de cette clef est une personne de confiance - lorsqu'il s'agit de signer des clefs. -u = Nous n'avons pas besoin de nous faire confiance à nous-même puisque - nous détenons notre propre clef privée. - -Vous devez conserver ces valeurs confidentielles, car elles représentent -la confiance que vous accordez ou non à d'autres individus. PGP stocke -cette information au sein de trousseau de clefs et le publier n'est PAS -une bonne idée. Vous devez utiliser la commande d'exportation pour -transmettre des clefs. Quoi qu'il en soit, GnuPG -évite ces problèmes en ne conservant ces valeurs qu'aun sein de sa -TrustDB donc vous pouvez copier un trousseau de clefs publiques -si vous utilisez GnuPG (et nous disposons aussi de la commande -d'exportation). - -7.4) Quel est ce genre de sortie : "key C26EE891.298, uid 09FB: ...."? - -Cette sortie est la représentation interne d'un userid au sein -de la TrustDB. Le keyid est "C26EE891" et le "298" est le keyid local, -un simple numéro d'enregistrement dans la TrustDB. Enfin, le "09FB" -sont les deux derniers octets d'un ripe-md-160 de l'identifiant de -l'utilisateur pour cette clef. - -7.5) Comment interpréter certaines sorties informatives ? - -Lorsque vous vérifiez la validité d'une clef, GnuPG affiche -parfois une information préfixée par l'information en rapport -avec le sujet vérifié. Par exemple : "key 12345678.3456" indique -que la clef disposant de l'ID 12345678, et du numéro interne 3456 -est considérée au sein de la TrustDB au sein de ce qu'on -appelle un enregistrement "directory". Un "uid 12345678.3456/ACDE" -indique quel est l'identifiant d'utilisateur qui correspond -à cette clef. Il s'agit d'une information sur la signature de la -clef 9A8B7C6D disposant de cet ID et s'il s'agit d'une signature -directe sur la clef, la partie User ID sera vide : - -(..//..) - -7.6) Les lignes d'en-tête des messages font-elles parties des - éléments signés ? - -Non. Par exemple, vous pouvez retirer les lignes "Comment:" -Elles n'ont pas vraiment d'objet comme les lignes "header" des -courriers électroniques. Toutefois, une ligne qui débute par -"Hash: ..." est requise par les signatures OpenPGP afin de permettre -au parser de déterminer quel algorithme de hachage utiliser. - -7.7) Quelle est la liste des algorithmes préférés ? - -La liste des algorithmes préférés est une liste d'algorithmes -de chiffrement, de hachage et de compression stockés dans -la signature propre de la clef durant sa production. Lorsque -vous chiffrez un document, GnuPG utilise cette liste (elle fait -partie de la clef publique) pour déterminer quels algorithmes -doivent être utilisés. De manière basique, ces indications -expliquent aux autres utilisateurs quels algorithmes vous -acceptez en entrée avec un ordre de préférence. - -7.8) Comment puis-je changer la liste des algorithmes préférés ? - -Actuellement la liste et les préférences sont directement intégrées -dans les codes sources de GnuPG. Vous devrez modifier le fichier -g10/keygen afin de modifier cette liste et procéder à une -nouvelle compilation. La fonction que vous devrez modifier est -keygen_add_std_prefs. Le code est d'ailleurs assez simple à -comprendre. Les constantes utilisées pour différencier les -algorithmes sont définies au sein du fichier include/cipher.h - -Après avoir modifié ces fichiers, générez une nouvelle paire -de clefs (ou une nouvelle sous-clef de chiffrement) avec -la version modifiée de l'exécutable. La nouvelle clef disposera -des nouvelles préférences et pourra être utilisée depuis des -exécutables non modifiés. - -Pour modifier les préférénces d'une clef existante, vous devrez -utiliser un exécutable modifié (voir ci-dessus) afin de modifier -la date d'expiration puis sauvegardez les changements. Les -préférences seront automatiquement modifiées lors de la -sauvegarde et vous pouvez désormais utiliser la clef modifiée -avec tout exécutable, modifié ou non. - -La modification de la liste de préférences à l'aide d'une -version non-modifiée de GnuPG (probablement depuis le menu -d'édition) fait partie de la liste TODO (A FAIRE) prévue -pour les prochaines versions de GnuPG. - - -8. REMERCIEMENTS - -Nous souhaitons remercier Werker Kosh pour la rédaction de la -première FAQ originelle et pour tous les participants aux listes -de discussion gnupg-users et gnupg-devel. La quasi-totalité -des réponses de ce document proviennent de leurs efforts. - -Nous souhaitons également remercier Casper Dik pour nous -avoir fourni le script permettant de générer cette FAQ, -qu'il utilise d'autre part pour son excellente FAQ Solaris2 ;-) - -Copyright (C) 2000 Free Software Foundation, Inc. , -59 Temple Place - Suite 330, Boston, MA 02111, USA - -Verbatim copying and distribution of this entire article is permitted in -any medium, provided this notice is preserved. diff --git a/doc/fr/README.fr b/doc/fr/README.fr deleted file mode 100644 index 3a5d8485e..000000000 --- a/doc/fr/README.fr +++ /dev/null @@ -1,10 +0,0 @@ -You find here translations to French of some of the documents in -../doc. Those translations are not necessary up-to-date and should -not be used as reference without checking the original English -versions. - -Gilbert Fernandes kindly contributed thses translatons. - - - - diff --git a/doc/gnupg-w32.reg b/doc/gnupg-w32.reg deleted file mode 100644 index 7a6e346a8..000000000 --- a/doc/gnupg-w32.reg +++ /dev/null @@ -1,8 +0,0 @@ -REGEDIT4 - -[HKEY_CURRENT_USER\Software\GNU\GNUPG] -"HomeDir"="C:\\GnuPG" -"gpgProgram"="C:\\GnuPG\\gpg.exe" - -[HKEY_CURRENT_USER\Control Panel\Mingw32\NLS] -"MODir"="C:\\GnuPG\\Locale" diff --git a/doc/gnupg.7 b/doc/gnupg.7 deleted file mode 100644 index d11a4c94a..000000000 --- a/doc/gnupg.7 +++ /dev/null @@ -1,14 +0,0 @@ -.TH GNUPG 7 2002-09-02 GNU "GNU Privacy Guard" -.SH NAME -GnuPG \- The GNU Privacy Guard suite of programs -.SH DESCRIPTION -GnuPG is a set of programs for public key encryption and digital -signatures. The program most users want to use is -the OpenPGP command line tool, named \fBgpg\fP. \fBgpgv\fP -is a stripped down version of \fBgpg\fP to verify signatures -against a trusted keyring. There is also a tool called -\fBgpgsplit\fP to split OpenPGP messages or keyrings into their packets. -.SH "SEE ALSO" -.BR gpg (1), -.BR gpgv (1), - diff --git a/doc/gpg.sgml b/doc/gpg.sgml deleted file mode 100644 index 83a286172..000000000 --- a/doc/gpg.sgml +++ /dev/null @@ -1,2461 +0,0 @@ - - - - -directory"> -file"> -&ParmFile;"> -files"> -&ParmFiles;"> -names"> -&ParmNames;"> -name"> -&ParmName;"> -key IDs"> -n"> -flags"> -string"> -value"> -name=value"> -name=value1 value2 value3 ..."> -]> - - - - gpg - 1 - GNU Tools - - - encryption and signing tool - - - -gpg - --homedir - --options - - command - - - - - - DESCRIPTION - - - -This man page only lists the commands and options available. -For more verbose documentation get the GNU Privacy Handbook (GPH) or -one of the other documents at http://www.gnupg.org/docs.html . - - -Please remember that option parsing stops as soon as a non option is -encountered, you can explicitly stop option parsing by using the -special option "--". - - - - -COMMANDS - - - - - - --s, --sign - -Make a signature. This command may be combined -with --encrypt. - - - - ---clearsign - -Make a clear text signature. - - - - --b, --detach-sign - -Make a detached signature. - - - - --e, --encrypt - -Encrypt data. This option may be combined with --sign. - - - - --c, --symmetric - -Encrypt with symmetric cipher only. -This command asks for a passphrase. - - - ---store - -Store only (make a simple RFC1991 packet). - - - - ---decrypt &OptParmFile; - -Decrypt &ParmFile; (or stdin if no file is specified) and -write it to stdout (or the file specified with ---output). If the decrypted file is signed, the -signature is also verified. 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. - - - - ---verify - - -Assume that - as the second filename. -For security reasons a detached signature cannot read the signed -material from stdin without denoting it in the above way. - - - ---verify-files - -This is a special version of the --verify command which does not work with -detached signatures. The command expects the files to be verified either -on the command line or reads the filenames from stdin; each name must be on -separate line. The command is intended for quick checking of many files. - - - ---encrypt-files - -This is a special version of the --encrypt command. The command expects -the files to be encrypted either on the command line or reads the filenames -from stdin; each name must be on separate line. The command is intended -for a quick encryption of multiple files. - - - ---decrypt-files - -The same as --encrypt-files with the difference that files will be -decrypted. The syntax or the filenames is the same. - - - - - ---list-keys &OptParmNames; ---list-public-keys &OptParmNames; - -List all keys from the public keyrings, or just the -ones given on the command line. - - - - ---list-secret-keys &OptParmNames; - -List all keys from the secret keyrings, or just the ones given on the -command line. A '#' after the letters 'sec' means that the secret key -is not usable (for example, if it was created via ---export-secret-subkeys). - - - - ---list-sigs &OptParmNames; - -Same as --list-keys, but the signatures are listed too. - - - - ---check-sigs &OptParmNames; - -Same as --list-sigs, but the signatures are verified. - - - ---fingerprint &OptParmNames; - -List all keys with their fingerprints. This is the -same output as --list-keys but with the additional output -of a line with the fingerprint. May also be combined -with --list-sigs or --check-sigs. -If this command is given twice, the fingerprints of all -secondary keys are listed too. - - - - ---list-packets - -List only the sequence of packets. This is mainly -useful for debugging. - - - - ---gen-key - -Generate a new key pair. This command is normally only used -interactively. - - -There is an experimental feature which allows you to create keys -in batch mode. See the file doc/DETAILS -in the source distribution on how to use this. - - - - ---edit-key &ParmName; - -Present a menu which enables you to do all key -related tasks: - - - - sign - -Make a signature on key of user &ParmName; -If the key is not yet signed by the default -user (or the users given with -u), the -program displays the information of the key -again, together with its fingerprint and -asks whether it should be signed. This -question is repeated for all users specified -with -u. - - lsign - -Same as --sign but the signature is marked as -non-exportable and will therefore never be used -by others. This may be used to make keys valid -only in the local environment. - - nrsign - -Same as --sign but the signature is marked as non-revocable and can -therefore never be revoked. - - nrlsign - -Combines the functionality of nrsign and lsign to make a signature -that is both non-revocable and -non-exportable. - - revsig - -Revoke a signature. For every signature which has been generated by -one of the secret keys, GnuPG asks whether a revocation certificate -should be generated. - - - trust - -Change the owner trust value. This updates the -trust-db immediately and no save is required. - - disable - enable - -Disable or enable an entire key. A disabled key can normally not be used -for encryption. - - adduid - -Create an alternate user id. - - addphoto - -Create a photographic user id. - - deluid - -Delete a user id. - - addkey - -Add a subkey to this key. - - delkey - -Remove a subkey. - - addrevoker - -Add a designated revoker. This takes one optional argument: -"sensitive". If a designated revoker is marked as sensitive, it will -not be exported by default (see -export-options). - - revkey - -Revoke a subkey. - - expire - -Change the key expiration time. If a subkey is selected, the -expiration time of this subkey will be changed. With no selection, -the key expiration of the primary key is changed. - - - passwd - -Change the passphrase of the secret key. - - primary - -Flag the current user id as the primary one, removes the primary user -id flag from all other user ids and sets the timestamp of all affected -self-signatures one second ahead. Note that setting a photo user ID -as primary makes it primary over other photo user IDs, and setting a -regular user ID as primary makes it primary over other regular user -IDs. - - - uid &ParmN; - -Toggle selection of user id with index &ParmN;. -Use 0 to deselect all. - - key &ParmN; - -Toggle selection of subkey with index &ParmN;. -Use 0 to deselect all. - - check - -Check all selected user ids. - - showphoto - -Display the selected photographic user -id. - - pref - -List preferences from the selected user ID. This shows the actual -preferences, without including any implied preferences. - - - showpref - -More verbose preferences listing for the selected user ID. This shows -the preferences in effect by including the implied preferences of -3DES (cipher), SHA-1 (digest), and Uncompressed (compression) if they -are not already included in the preference list. - - - setpref &ParmString; - -Set the list of user ID preferences to &ParmString;, this should be a -string similar to the one printed by "pref". Using an empty string -will set the default preference string, using "none" will set the -preferences to nil. Use "gpg -v --version" to get a list of available -algorithms. This command just initializes an internal list and does -not change anything unless another command (such as "updpref") which -changes the self-signatures is used. - - - updpref - -Change the preferences of all user IDs (or just of the selected ones -to the current list of preferences. The timestamp of all affected -self-signatures will be advanced by one second. Note that while you -can change the preferences on an attribute user ID (aka "photo ID"), -GnuPG does not select keys via attribute user IDs so these preferences -will not be used by GnuPG. - - - toggle - -Toggle between public and secret key listing. - - save - -Save all changes to the key rings and quit. - - quit - -Quit the program without updating the -key rings. - - -The listing shows you the key with its secondary -keys and all user ids. Selected keys or user ids -are indicated by an asterisk. The trust value is -displayed with the primary key: the first is the -assigned owner trust and the second is the calculated -trust value. Letters are used for the values: - - -No ownertrust assigned / not yet calculated. - eTrust -calculation has failed; probably due to an expired key. - qNot enough information for calculation. - nNever trust this key. - mMarginally trusted. - fFully trusted. - uUltimately trusted. - - - - ---sign-key &ParmName; - -Signs a public key with your secret key. This is a shortcut version of -the subcommand "sign" from --edit. - - - ---lsign-key &ParmName; - -Signs a public key with your secret key but marks it as -non-exportable. This is a shortcut version of the subcommand "lsign" -from --edit. - - - ---nrsign-key &ParmName; - -Signs a public key with your secret key but marks it as non-revocable. -This is a shortcut version of the subcommand "nrsign" from --edit. - - - ---delete-key &ParmName; - -Remove key from the public keyring. In batch mode either --yes is -required or the key must be specified by fingerprint. This is a -safeguard against accidental deletion of multiple keys. - - - ---delete-secret-key &ParmName; - -Remove key from the secret and public keyring. In batch mode the key -must be specified by fingerprint. - - - ---delete-secret-and-public-key &ParmName; - -Same as --delete-key, but if a secret key exists, it will be removed -first. In batch mode the key must be specified by fingerprint. - - - ---gen-revoke - -Generate a revocation certificate for the complete key. To revoke -a subkey or a signature, use the --edit command. - - - ---desig-revoke - -Generate a designated revocation certificate for a key. This allows a -user (with the permission of the keyholder) to revoke someone elses -key. - - - ---export &OptParmNames; - -Either export all keys from all keyrings (default -keyrings and those registered via option --keyring), -or if at least one name is given, those of the given -name. The new keyring is written to stdout or to -the file given with option "output". Use together -with --armor to mail those keys. - - - - ---send-keys &OptParmNames; - -Same as --export but sends the keys to a keyserver. -Option --keyserver must be used to give the name -of this keyserver. Don't send your complete keyring -to a keyserver - select only those keys which are new -or changed by you. - - - - ---export-all &OptParmNames; - -Same as --export, but also exports keys which -are not compatible with OpenPGP. - - - - ---export-secret-keys &OptParmNames; ---export-secret-subkeys &OptParmNames; - -Same as --export, but exports the secret keys instead. -This is normally not very useful and a security risk. -The second form of the command has the special property to -render the secret part of the primary key useless; this is -a GNU extension to OpenPGP and other implementations can -not be expected to successfully import such a key. - -See the option --simple-sk-checksum if you want to import such an -exported key with an older OpenPGP implementation. - - - - ---import &OptParmFiles; ---fast-import &OptParmFiles; - -Import/merge keys. This adds the given keys to the -keyring. The fast version is currently just a synonym. - - -There are a few other options which control how this command works. -Most notable here is the --merge-only option which does not insert new keys -but does only the merging of new signatures, user-IDs and subkeys. - - - - ---recv-keys &ParmKeyIDs; - -Import the keys with the given key IDs from a keyserver. Option ---keyserver must be used to give the name of this keyserver. - - - ---search-keys &OptParmNames; - -Search the keyserver for the given names. Multiple names given here -will be joined together to create the search string for the keyserver. -Option --keyserver must be used to give the name of this keyserver. - - - ---update-trustdb - -Do trust DB maintenance. This command goes over all keys and builds -the Web-of-Trust. This is an interactive command because it may has to -ask for the "ownertrust" values of keys. The user has to give an -estimation in how far she trusts the owner of the displayed key to -correctly certify (sign) other keys. It does only ask for that value -if it has not yet been assigned to a key. Using the edit menu, that -value can be changed at any time later. - - - ---check-trustdb - -Do trust DB maintenance without user interaction. Form time to time -the trust database must be updated so that expired keys and resulting -changes in the Web-of-Trust can be tracked. GnuPG tries to figure -when this is required and then does it implicitly; this command can be -used to force such a check. The processing is identically to that of ---update-trustdb but it skips keys with a not yet defined "ownertrust". - - -For use with cron jobs, this command can be used together with --batch -in which case the check is only done when it is due. To force a run -even in batch mode add the option --yes. - - - - ---export-ownertrust &OptParmFile; - -Store the ownertrust values into -&ParmFile; (or stdin if not given). This is useful for backup -purposes as these values are the only ones which can't be re-created -from a corrupted trust DB. - - - ---import-ownertrust &OptParmFiles; - -Update the trustdb with the ownertrust values stored -in &ParmFiles; (or stdin if not given); existing -values will be overwritten. - - - ---rebuild-keydb-caches - -When updating from version 1.0.6 to 1.0.7 this command should be used -to create signature caches in the keyring. It might be handy in other -situations too. - - - ---print-md algo &OptParmFiles; ---print-mds &OptParmFiles; - -Print message digest of algorithm ALGO for all given files or stdin. -With the second form (or a deprecated "*" as algo) digests for all -available algorithms are printed. - - - - ---gen-random 0|1|2 - count - -Emit COUNT random bytes of the given quality level. If count is not given -or zero, an endless sequence of random bytes will be emitted. -PLEASE, don't use this command unless you know what you are doing; it may -remove precious entropy from the system! - - - ---gen-prime mode - bits - qbits - -Use the source, Luke :-). The output format is still subject to change. - - - - ---version - -Print version information along with a list -of supported algorithms. - - - - ---warranty - -Print warranty information. - - - - --h, --help - -Print usage information. This is a really long list even though it doesn't list -all options. - - - - - - - - -OPTIONS - -Long options can be put in an options file (default -"~/.gnupg/gpg.conf"). Short option names will not work - for example, -"armor" is a valid option for the options file, while "a" is not. Do -not write the 2 dashes, but simply the name of the option and any -required arguments. Lines with a hash ('#') as the first -non-white-space character are ignored. Commands may be put in this -file too, but that does not make sense. - - - - - - - - --a, --armor - -Create ASCII armored output. - - - - --o, --output &ParmFile; - -Write output to &ParmFile;. - - - - --u, --local-user &ParmName; - -Use &ParmName as the user ID to sign. -This option is silently ignored for the list commands, -so that it can be used in an options file. - - - - ---default-key &ParmName; - -Use &ParmName; as default user ID for signatures. If this -is not used the default user ID is the first user ID -found in the secret keyring. - - - - --r, --recipient &ParmName; - - -Encrypt for user id &ParmName;. If this option is not -specified, GnuPG asks for the user-id unless --default-recipient is given - - - ---default-recipient &ParmName; - -Use &ParmName; as default recipient if option --recipient is not used and -don't ask if this is a valid one. &ParmName; must be non-empty. - - - ---default-recipient-self - -Use the default key as default recipient if option --recipient is not used and -don't ask if this is a valid one. The default key is the first one from the -secret keyring or the one set with --default-key. - - - - ---no-default-recipient - -Reset --default-recipient and --default-recipient-self. - - - ---encrypt-to &ParmName; - -Same as --recipient but this one is intended for use -in the options file and may be used with -your own user-id as an "encrypt-to-self". These keys -are only used when there are other recipients given -either by use of --recipient or by the asked user id. -No trust checking is performed for these user ids and -even disabled keys can be used. - - - - ---no-encrypt-to - -Disable the use of all --encrypt-to keys. - - - - --v, --verbose - -Give more information during processing. If used -twice, the input data is listed in detail. - - - - --q, --quiet - -Try to be as quiet as possible. - - - - --z &ParmN;, --compress &ParmN; - -Set compression level to &ParmN;. A value of 0 for &ParmN; -disables compression. Default is to use the default -compression level of zlib (normally 6). - - - - --t, --textmode - -Use canonical text mode. If -t (but not ---textmode) is used together with armoring -and signing, this enables clearsigned messages. -This kludge is needed for PGP compatibility; -normally you would use --sign or --clearsign -to selected the type of the signature. - - - - --n, --dry-run - -Don't make any changes (this is not completely implemented). - - - - --i, --interactive - -Prompt before overwriting any files. - - - - ---batch - -Use batch mode. Never ask, do not allow interactive -commands. - - - ---no-tty - -Make sure that the TTY (terminal) is never used for any output. -This option is needed in some cases because GnuPG sometimes prints -warnings to the TTY if --batch is used. - - - - ---no-batch - -Disable batch mode. This may be of use if --batch -is enabled from an options file. - - - - ---yes - -Assume "yes" on most questions. - - - - ---no - - Assume "no" on most questions. - - - ---default-cert-check-level &ParmN; - -The default to use for the check level when signing a key. - -0 means you make no particular claim as to how carefully you verified -the key. - -1 means you believe the key is owned by the person who claims to own -it but you could not, or did not verify the key at all. This is -useful for a "persona" verification, where you sign the key of a -pseudonymous user. - -2 means you did casual verification of the key. For example, this -could mean that you verified that the key fingerprint and checked the -user ID on the key against a photo ID. - -3 means you did extensive verification of the key. For example, this -could mean that you verified the key fingerprint with the owner of the -key in person, and that you checked, by means of a hard to forge -document with a photo ID (such as a passport) that the name of the key -owner matches the name in the user ID on the key, and finally that you -verified (by exchange of email) that the email address on the key -belongs to the key owner. - -Note that the examples given above for levels 2 and 3 are just that: -examples. In the end, it is up to you to decide just what "casual" -and "extensive" mean to you. - -This option defaults to 0. - - - - - ---trusted-key long key ID - -Assume that the specified key (which must be given -as a full 8 byte key ID) is as trustworthy as one of -your own secret keys. This option is useful if you -don't want to keep your secret keys (or one of them) -online but still want to be able to check the validity of a given -recipient's or signator's key. - - - ---always-trust - -Skip key validation and assume that used keys are always fully trusted. -You won't use this unless you have installed some external validation -scheme. This option also suppresses the "[uncertain]" tag printed -with signature checks when there is no evidence that the user ID -is bound to the key. - - - - ---keyserver &ParmName; - -Use &ParmName as your keyserver. This is the server that --recv-keys, ---send-keys, and --search-keys will communicate with to receive keys -from, send keys to, and search for keys on. The format of the -&ParmName is a URI: `scheme:[//]keyservername[:port]' The scheme is -the type of keyserver: "hkp" for the Horowitz (or compatible) -keyservers, "ldap" for the NAI LDAP keyserver, or "mailto" for the -Horowitz email keyserver. Note that your particular installation of -GnuPG may have other keyserver types available as well. Keyserver -schemes are case-insensitive. - -Most keyservers synchronize with each other, so there is generally no -need to send keys to more than one server. Using the command "host -l -pgp.net | grep wwwkeys" gives you a list of HKP keyservers. When -using one of the wwwkeys servers, due to load balancing using -round-robin DNS you may notice that you get a different key server -each time. - - - ---keyserver-options parameters - -This is a space or comma delimited string that gives options for the -keyserver. Options can be prepended with a `no-' to give the opposite -meaning. Valid import-options or export-options may be used here as -well to apply to importing (--recv-key) or exporting (--send-key) a -key from a keyserver. While not all options are available for all -keyserver types, some common options are: - - - -include-revoked - -When searching for a key, include keys that are marked on the -keyserver as revoked. Note that this option is always set when using -the NAI HKP keyserver, as this keyserver does not differentiate -between revoked and unrevoked keys. When using the LDAP keyserver, -this applies to both searching (--search-keys) and receiving -(--recv-keys). - - - -include-disabled - -When receiving or searching for a key, include keys that are marked on -the keyserver as disabled. Note that this option is not used with HKP -keyservers, as they do not support disabling keys. - - - -include-subkeys - -When receiving a key, include subkeys in the search. Note that this -option is not used with HKP keyservers, as they do not support -retrieving keys by subkey id. - - - -use-temp-files - -On most Unix-like platforms, GnuPG communicates with the keyserver -helper program via pipes, which is the most efficient method. This -option forces GnuPG to use temporary files to communicate. On some -platforms (such as Win32 and RISC OS), this option is always enabled. - - - -keep-temp-files - -If using `use-temp-files', do not delete the temp files after using -them. This option is useful to learn the keyserver communication -protocol by reading the temporary files. - - - -verbose - -Tell the keyserver helper program to be more verbose. This option can -be repeated multiple times to increase the verbosity level. - - - -honor-http-proxy - -For keyserver schemes that use HTTP (such as HKP), try to access the -keyserver over the proxy set with the environment variable -"http_proxy". - - - -auto-key-retrieve - -This option enables the automatic retrieving of keys from a keyserver -when verifying signatures made by keys that are not on the local -keyring. - - - - - - ---import-options parameters - -This is a space or comma delimited string that gives options for -importing keys. Options can be prepended with a `no-' to give the -opposite meaning. The options are: - - - -allow-local-sigs - -Allow importing key signatures marked as "local". This is not -generally useful unless a shared keyring scheme is being used. -Defaults to no. - - - -repair-hkp-subkey-bug - -During import, attempt to repair the HKP keyserver mangling multiple -subkeys bug. Note that this cannot completely repair the damaged key -as some crucial data is removed by the keyserver, but it does at least -give you back one subkey. Defaults to no for regular --import and to -yes for keyserver --recv-keys. - - - - - - ---export-options parameters - -This is a space or comma delimited string that gives options for -exporting keys. Options can be prepended with a `no-' to give the -opposite meaning. The options are: - - - -include-non-rfc - -Include non-RFC compliant keys in the export. Defaults to yes. - - - -include-local-sigs - -Allow exporting key signatures marked as "local". This is not -generally useful unless a shared keyring scheme is being used. -Defaults to no. - - - -include-attributes - -Include attribute user IDs (photo IDs) while exporting. This is -useful to export keys if they are going to be used by an OpenPGP -program that does not accept attribute user IDs. Defaults to yes. - - - -include-sensitive-revkeys - -Include designated revoker information that was marked as -"sensitive". Defaults to no. - - - - - - ---show-photos - -Causes --list-keys, --list-sigs, --list-public-keys, ---list-secret-keys, and verifying a signature to also display the -photo ID attached to the key, if any. -See also --photo-viewer. - - - ---no-show-photos - -Resets the --show-photos flag. - - - ---photo-viewer &ParmString; - -This is the command line that should be run to view a photo ID. "%i" -will be expanded to a filename containing the photo. "%I" does the -same, except the file will not be deleted once the viewer exits. -Other flags are "%k" for the key ID, "%K" for the long key ID, "%f" -for the key fingerprint, "%t" for the extension of the image type -(e.g. "jpg"), "%T" for the MIME type of the image (e.g. "image/jpeg"), -and "%%" for an actual percent sign. If neither %i or %I are present, -then the photo will be supplied to the viewer on standard input. - -The default viewer is "xloadimage -fork -quiet -title 'KeyID 0x%k' -stdin" - - - ---exec-path &ParmString; - -Sets a list of directories to search for photo viewers and keyserver -helpers. If not provided, keyserver helpers use the compiled-in -default directory, and photo viewers use the $PATH environment -variable. - - - ---show-keyring - -Causes --list-keys, --list-public-keys, and --list-secret-keys to -display the name of the keyring a given key resides on. This is only -useful when you're listing a specific key or set of keys. It has no -effect when listing all keys. - - - ---keyring &ParmFile; - -Add &ParmFile to the list of keyrings. -If &ParmFile begins with a tilde and a slash, these -are replaced by the HOME directory. If the filename -does not contain a slash, it is assumed to be in the -home-directory ("~/.gnupg" if --homedir is not used). -The filename may be prefixed with a scheme: -"gnupg-ring:" is the default one. -It might make sense to use it together with --no-default-keyring. - - - - ---secret-keyring &ParmFile; - -Same as --keyring but for the secret keyrings. - - - - ---homedir &ParmDir; - -Set the name of the home directory to &ParmDir; If this -option is not used it defaults to "~/.gnupg". It does -not make sense to use this in a options file. This -also overrides the environment variable "GNUPGHOME". - - - - ---charset &ParmName; - -Set the name of the native character set. This is used -to convert some strings to proper UTF-8 encoding. If this option is not used, the default character set is determined -from the current locale. A verbosity level of 3 shows the used one. -Valid values for &ParmName; are: - - -iso-8859-1This is the Latin 1 set. - - -iso-8859-2The Latin 2 set. - - -iso-8859-15This is currently an alias for -the Latin 1 set. - - -koi8-rThe usual Russian set (rfc1489). - - -utf-8Bypass all translations and assume -that the OS uses native UTF-8 encoding. - - - - - - ---utf8-strings ---no-utf8-strings - -Assume that the arguments are already given as UTF8 strings. The default -(--no-utf8-strings) -is to assume that arguments are encoded in the character set as specified -by --charset. These options affect all following arguments. Both options may -be used multiple times. - - - - ---options &ParmFile; - -Read options from &ParmFile; and do not try to read -them from the default options file in the homedir -(see --homedir). This option is ignored if used -in an options file. - - - - ---no-options - -Shortcut for "--options /dev/null". This option is -detected before an attempt to open an option file. -Using this option will also prevent the creation of a -"~./gnupg" homedir. - - - - ---load-extension &ParmName; - -Load an extension module. If &ParmName; does not contain a slash it is -searched for in the directory configured when GnuPG was built -(generally "/usr/local/lib/gnupg"). Extensions are not generally -useful anymore, and the use of this option is deprecated. - - - - ---debug &ParmFlags; - -Set debugging flags. All flags are or-ed and &ParmFlags; may -be given in C syntax (e.g. 0x0042). - - - - ---debug-all - - Set all useful debugging flags. - - - - ---status-fd &ParmN; - -Write special status strings to the file descriptor &ParmN;. -See the file DETAILS in the documentation for a listing of them. - - - - ---logger-fd &ParmN; - -Write log output to file descriptor &ParmN; and not to stderr. - - - - ---attribute-fd &ParmN; - -Write attribute subpackets to the file descriptor &ParmN;. This is -most useful for use with --status-fd, since the status messages are -needed to separate out the various subpackets from the stream -delivered to the file descriptor. - - - - ---sk-comments - -Include secret key comment packets when exporting secret keys. This -is a GnuPG extension to the OpenPGP standard, and is off by default. -Please note that this has nothing to do with the comments in clear -text signatures or armor headers. - - - ---no-sk-comments - -Resets the --sk-comments option. - - - ---no-comment - -See --sk-comments. This option is deprecated and may be removed soon. - - - - ---comment &ParmString; - -Use &ParmString; as comment string in clear text signatures. -The default is not do write a comment string. - - - - ---default-comment - -Force to write the standard comment string in clear -text signatures. Use this to overwrite a --comment -from a config file. This option is now obsolete because there is no -default comment string anymore. - - - - ---no-version - -Omit the version string in clear text signatures. - - - - ---emit-version - -Force to write the version string in clear text -signatures. Use this to overwrite a previous ---no-version from a config file. - - - - --N, --notation-data &ParmNameValue; - -Put the name value pair into the signature as notation data. -&ParmName; must consist only of alphanumeric characters, digits -or the underscore; the first character must not be a digit. -&ParmValue; may be any printable string; it will be encoded in UTF8, -so you should check that your --charset is set correctly. -If you prefix &ParmName; with an exclamation mark, the notation -data will be flagged as critical (rfc2440:5.2.3.15). - - - ---show-notation - -Show key signature notations in the --list-sigs or --check-sigs -listings. - - - ---no-show-notation - -Do not show key signature notations in the --list-sigs or --check-sigs -listings. - - - ---set-policy-url &ParmString; - -Use &ParmString; as Policy URL for signatures (rfc2440:5.2.3.19). -If you prefix it with an exclamation mark, the policy URL -packet will be flagged as critical. - - - ---show-policy-url - -Show any policy URLs set in the --list-sigs or --check-sigs listings. - - - ---no-show-policy-url - -Do not show any policy URLs set in the --list-sigs or --check-sigs -listings. - - - ---set-filename &ParmString; - -Use &ParmString; as the name of file which is stored in -messages. - - - ---for-your-eyes-only - -Set the `for your eyes only' flag in the message. This causes GnuPG -to refuse to save the file unless the --output option is given, and -PGP to use the "secure viewer" with a Tempest-resistant font to -display the message. This option overrides --set-filename. - ---no-for-your-eyes-only - -Resets the --for-your-eyes-only flag. - ---use-embedded-filename - -Try to create a file with a name as embedded in the data. -This can be a dangerous option as it allows to overwrite files. - - - - ---completes-needed &ParmN; - -Number of completely trusted users to introduce a new -key signer (defaults to 1). - - - - ---marginals-needed &ParmN; - -Number of marginally trusted users to introduce a new -key signer (defaults to 3) - - - - ---max-cert-depth &ParmN; - -Maximum depth of a certification chain (default is 5). - - - - ---cipher-algo &ParmName; - -Use &ParmName; as cipher algorithm. Running the program -with the command --version yields a list of supported -algorithms. If this is not used the cipher algorithm is -selected from the preferences stored with the key. - - - - ---digest-algo &ParmName; - -Use &ParmName; as the message digest algorithm. Running the program -with the command --version yields a list of supported algorithms. - - - - ---cert-digest-algo &ParmName; - -Use &ParmName; as the message digest algorithm used when signing a -key. Running the program with the command --version yields a list of -supported algorithms. Be aware that if you choose an algorithm that -GnuPG supports but other OpenPGP implementations do not, then some -users will not be able to use the key signatures you make, or quite -possibly your entire key. - - - - ---s2k-cipher-algo &ParmName; - -Use &ParmName; as the cipher algorithm used to protect secret keys. -The default cipher is CAST5. This cipher is also used for -conventional encryption if --cipher-algo is not given. - - - - ---s2k-digest-algo &ParmName; - -Use &ParmName; as the digest algorithm used to mangle the -passphrases. The default algorithm is RIPE-MD-160. -This digest algorithm is also used for conventional -encryption if --digest-algo is not given. - - - - ---s2k-mode &ParmN; - -Selects how passphrases are mangled. If &ParmN; is 0 -a plain passphrase (which is not recommended) will be used, -a 1 (default) adds a salt to the passphrase and -a 3 iterates the whole process a couple of times. -Unless --rfc1991 is used, this mode is also used -for conventional encryption. - - - - ---simple-sk-checksum - -Secret keys are integrity protected by using a SHA-1 checksum. This -method will be part of an enhanced OpenPGP specification but GnuPG -already uses it as a countermeasure against certain attacks. Old -applications don't understand this new format, so this option may be -used to switch back to the old behaviour. Using this this option -bears a security risk. Note that using this option only takes effect -when the secret key is encrypted - the simplest way to make this -happen is to change the passphrase on the key (even changing it to the -same value is acceptable). - - - - ---compress-algo &ParmN; - -Use compression algorithm &ParmN;. Default is 2 which is RFC1950 -compression. You may use 1 to use the old zlib version (RFC1951) which -is used by PGP. 0 disables compression. The default algorithm may give -better results because the window size is not limited to 8K. If this -is not used the OpenPGP behavior is used, i.e. the compression -algorithm is selected from the preferences; note, that this can't be -done if you do not encrypt the data. - - - - ---disable-cipher-algo &ParmName; - -Never allow the use of &ParmName; as cipher algorithm. -The given name will not be checked so that a later loaded algorithm -will still get disabled. - - - ---disable-pubkey-algo &ParmName; - -Never allow the use of &ParmName; as public key algorithm. -The given name will not be checked so that a later loaded algorithm -will still get disabled. - - - ---no-sig-cache - -Do not cache the verification status of key signatures. -Caching gives a much better performance in key listings. However, if -you suspect that your public keyring is not save against write -modifications, you can use this option to disable the caching. It -probably does not make sense to disable it because all kind of damage -can be done if someone else has write access to your public keyring. - - - ---no-sig-create-check - -GnuPG normally verifies each signature right after creation to protect -against bugs and hardware malfunctions which could leak out bits from -the secret key. This extra verification needs some time (about 115% -for DSA keys), and so this option can be used to disable it. -However, due to the fact that the signature creation needs manual -interaction, this performance penalty does not matter in most settings. - - - ---auto-check-trustdb - -If GnuPG feels that its information about the Web-of-Trust has to be -updated, it automatically runs the --check-trustdb command -internally. This may be a time consuming process. - - - ---no-auto-check-trustdb - -Resets the --auto-check-trustdb option. - - - ---throw-keyid - -Do not put the keyid into encrypted packets. This option -hides the receiver of the message and is a countermeasure -against traffic analysis. It may slow down the decryption -process because all available secret keys are tried. - - - - ---not-dash-escaped - -This option changes the behavior of cleartext signatures -so that they can be used for patch files. You should not -send such an armored file via email because all spaces -and line endings are hashed too. You can not use this -option for data which has 5 dashes at the beginning of a -line, patch files don't have this. A special armor header -line tells GnuPG about this cleartext signature option. - - - - ---escape-from-lines - -Because some mailers change lines starting with "From " -to "<From " it is good to handle such lines in a special -way when creating cleartext signatures. All other PGP -versions do it this way too. This option is not enabled -by default because it would violate rfc2440. - - - - ---passphrase-fd &ParmN; - -Read the passphrase from file descriptor &ParmN;. If you use -0 for &ParmN;, the passphrase will be read from stdin. This -can only be used if only one passphrase is supplied. - -Don't use this option if you can avoid it. - - - ---command-fd &ParmN; - -This is a replacement for the deprecated shared-memory IPC mode. -If this option is enabled, user input on questions is not expected -from the TTY but from the given file descriptor. It should be used -together with --status-fd. See the file doc/DETAILS in the source -distribution for details on how to use it. - - - ---use-agent - -Try to use the GnuPG-Agent. Please note that this agent is still under -development. With this option, GnuPG first tries to connect to the -agent before it asks for a passphrase. - - - ---gpg-agent-info - -Override the value of the environment variable -GPG_AGENT_INFO. This is only used when --use-agent has been given - - - - ---rfc1991 - -Try to be more RFC1991 (PGP 2.x) compliant. - - - ---pgp2 - -Set up all options to be as PGP 2.x compliant as possible, and warn if -an action is taken (e.g. encrypting to a non-RSA key) that will create -a message that PGP 2.x will not be able to handle. Note that `PGP -2.x' here means `MIT PGP 2.6.2'. There are other versions of PGP 2.x -available, but the MIT release is a good common baseline. - -This option implies `--rfc1991 --no-openpgp --disable-mdc ---no-force-v4-certs --no-comment --escape-from-lines --force-v3-sigs ---no-ask-sig-expire --no-ask-cert-expire --cipher-algo IDEA ---digest-algo MD5 --compress-algo 1'. It also disables --textmode -when encrypting. - - - ---no-pgp2 - -Resets the --pgp2 option. - - - ---pgp6 - -Set up all options to be as PGP 6 compliant as possible. This -restricts you to the ciphers IDEA (if the IDEA plugin is installed), -3DES, and CAST5, the hashes MD5, SHA1 and RIPEMD160, and the -compression algorithms none and ZIP. This also disables making -signatures with signing subkeys as PGP 6 does not understand -signatures made by signing subkeys. - -This option implies `--disable-mdc --no-comment --escape-from-lines ---force-v3-sigs --no-ask-sig-expire --compress-algo 1' - - - ---no-pgp6 - -Resets the --pgp6 option. - - - ---pgp7 - -Set up all options to be as PGP 7 compliant as possible. This is -identical to --pgp6 except that MDCs are not disabled, and the list of -allowable ciphers is expanded to add AES128, AES192, AES256, and -TWOFISH. - - - ---no-pgp7 - -Resets the --pgp7 option. - - - ---openpgp - -Reset all packet, cipher and digest options to OpenPGP behavior. Use -this option to reset all previous options like --rfc1991, ---force-v3-sigs, --s2k-*, --cipher-algo, --digest-algo and ---compress-algo to OpenPGP compliant values. All PGP workarounds are -also disabled. - - - - ---force-v3-sigs - -OpenPGP states that an implementation should generate v4 signatures -but PGP versions 5 and higher only recognize v4 signatures on key -material. This option forces v3 signatures for signatures on data. -Note that this option overrides --ask-sig-expire, as v3 signatures -cannot have expiration dates. - - - ---no-force-v3-sigs - -Reset the --force-v3-sigs option. - - - ---force-v4-certs - -Always use v4 key signatures even on v3 keys. This option also -changes the default hash algorithm for v3 RSA keys from MD5 to SHA-1. - - - ---no-force-v4-certs - -Reset the --force-v4-certs option. - - - - ---force-mdc - -Force the use of encryption with appended manipulation code. This is -always used with the newer ciphers (those with a blocksize greater -than 64 bit). - - - ---allow-non-selfsigned-uid - -Allow the import and use of keys with user IDs which are not -self-signed. This is not recommended, as a non self-signed user ID is -trivial to forge. - - - ---no-allow-non-selfsigned-uid - -Reset the --allow-non-selfsigned-uid option. - - - ---allow-freeform-uid - -Disable all checks on the form of the user ID while generating a new -one. This option should only be used in very special environments as -it does not ensure the de-facto standard format of user IDs. - - - - ---ignore-time-conflict - -GnuPG normally checks that the timestamps associated with keys and -signatures have plausible values. However, sometimes a signature seems to -be older than the key due to clock problems. This option makes these -checks just a warning. - - - ---ignore-valid-from - -GnuPG normally does not select and use subkeys created in the future. This -option allows the use of such keys and thus exhibits the pre-1.0.7 -behaviour. You should not use this option unless you there is some -clock problem. - - - ---ignore-crc-error - -The ASCII armor used by OpenPGP is protected by a CRC checksum against -transmission errors. Sometimes it happens that the CRC gets mangled -somewhere on the transmission channel but the actual content (which is -protected by the OpenPGP protocol anyway) is still okay. This option -will let gpg ignore CRC errors. - - - ---ignore-mdc-error - -This option changes a MDC integrity protection failure into a warning. -This can be useful if a message is partially corrupt, but it is -necessary to get as much data as possible out of the corrupt message. -However, be aware that a MDC protection failure may also mean that the -message was tampered with intentionally by an attacker. - - - ---lock-once - -Lock the databases the first time a lock is requested -and do not release the lock until the process -terminates. - - - - ---lock-multiple - -Release the locks every time a lock is no longer -needed. Use this to override a previous --lock-once -from a config file. - - - ---lock-never - -Disable locking entirely. This option should be used only in very -special environments, where it can be assured that only one process -is accessing those files. A bootable floppy with a stand-alone -encryption system will probably use this. Improper usage of this -option may lead to data and key corruption. - - - ---no-random-seed-file - -GnuPG uses a file to store its internal random pool over invocations. -This makes random generation faster; however sometimes write operations -are not desired. This option can be used to achieve that with the cost of -slower random generation. - - - - ---no-verbose - -Reset verbose level to 0. - - - - ---no-greeting - -Suppress the initial copyright message but do not -enter batch mode. - - - ---no-secmem-warning - -Suppress the warning about "using insecure memory". - - - ---no-permission-warning - -Suppress the warning about unsafe file permissions. - - - ---no-mdc-warning - -Suppress the warning about missing MDC integrity protection. - - - - ---no-armor - -Assume the input data is not in ASCII armored format. - - - - ---no-default-keyring - -Do not add the default keyrings to the list of -keyrings. - - - - ---skip-verify - -Skip the signature verification step. This may be -used to make the decryption faster if the signature -verification is not needed. - - - - ---with-colons - -Print key listings delimited by colons. Note, that the output will be -encoded in UTF-8 regardless of any --charset setting. - - - - ---with-key-data - -Print key listings delimited by colons (like --with-colons) and print the public key data. - - - ---with-fingerprint - -Same as the command --fingerprint but changes only the format of the output -and may be used together with another command. - - - ---fast-list-mode - -Changes the output of the list commands to work faster; this is achieved -by leaving some parts empty. Some applications don't need the user ID and -the trust information given in the listings. By using this options they -can get a faster listing. The exact behaviour of this option may change -in future versions. - - - ---fixed-list-mode - -Do not merge user ID and primary key in --with-colon listing mode and -print all timestamps as seconds since 1970-01-01. - - - ---list-only - -Changes the behaviour of some commands. This is like --dry-run but -different in some cases. The semantic of this command may be extended in -the future. Currently it only skips the actual decryption pass and -therefore enables a fast listing of the encryption keys. - - - ---no-literal - -This is not for normal use. Use the source to see for what it might be useful. - - - ---set-filesize - -This is not for normal use. Use the source to see for what it might be useful. - - - ---emulate-md-encode-bug - -GnuPG versions prior to 1.0.2 had a bug in the way a signature was encoded. -This options enables a workaround by checking faulty signatures again with -the encoding used in old versions. This may only happen for ElGamal signatures -which are not widely used. - - - ---show-session-key - -Display the session key used for one message. See --override-session-key -for the counterpart of this option. - - -We think that Key-Escrow is a Bad Thing; however the user should -have the freedom to decide whether to go to prison or to reveal the content of -one specific message without compromising all messages ever encrypted for one -secret key. DON'T USE IT UNLESS YOU ARE REALLY FORCED TO DO SO. - - - ---override-session-key &ParmString; - -Don't use the public key but the session key &ParmString;. The format of this -string is the same as the one printed by --show-session-key. This option -is normally not used but comes handy in case someone forces you to reveal the -content of an encrypted message; using this option you can do this without -handing out the secret key. - - - ---ask-sig-expire - -When making a data signature, prompt for an expiration time. If this -option is not specified, the expiration time is "never". - ---no-ask-sig-expire - -Resets the --ask-sig-expire option. - ---ask-cert-expire - -When making a key signature, prompt for an expiration time. If this -option is not specified, the expiration time is "never". - ---no-ask-cert-expire - -Resets the --ask-cert-expire option. - ---expert - -Allow the user to do certain nonsensical or "silly" things like -signing an expired or revoked key, or certain potentially incompatible -things like generating deprecated key types. This also disables -certain warning messages about potentially incompatible actions. As -the name implies, this option is for experts only. If you don't fully -understand the implications of what it allows you to do, leave this -off. - ---no-expert - -Resets the --expert option. - ---merge-only - -Don't insert new keys into the keyrings while doing an import. - - - ---allow-secret-key-import - -This is an obsolete option and is not used anywhere. - - - ---try-all-secrets - -Don't look at the key ID as stored in the message but try all secret keys in -turn to find the right decryption key. This option forces the behaviour as -used by anonymous recipients (created by using --throw-keyid) and might come -handy in case where an encrypted message contains a bogus key ID. - - - ---enable-special-filenames - -This options enables a mode in which filenames of the form --&n, where n is a non-negative decimal number, -refer to the file descriptor n and not to a file with that name. - - - ---no-expensive-trust-checks - -Experimental use only. - - - ---group &ParmNameValues; - -Sets up a named group, which is similar to aliases in email programs. -Any time the group name is a receipient (-r or --recipient), it will -be expanded to the values specified. - -The values are &ParmKeyIDs; or fingerprints, but any key description -is accepted. Note that a value with spaces in it will be treated as -two different values. Note also there is only one level of expansion -- you cannot make an group that points to another group. - - - ---preserve-permissions - -Don't change the permissions of a secret keyring back to user -read/write only. Use this option only if you really know what you are doing. - - - ---personal-cipher-preferences &ParmString; - -Set the list of personal cipher preferences to &ParmString;, this list -should be a string similar to the one printed by the command "pref" in -the edit menu. This allows the user to factor in their own preferred -algorithms when algorithms are chosen via recipient key preferences. - - - ---personal-digest-preferences &ParmString; - -Set the list of personal digest preferences to &ParmString;, this list -should be a string similar to the one printed by the command "pref" in -the edit menu. This allows the user to factor in their own preferred -algorithms when algorithms are chosen via recipient key preferences. - - - ---personal-compress-preferences &ParmString; - -Set the list of personal compression preferences to &ParmString;, this -list should be a string similar to the one printed by the command -"pref" in the edit menu. This allows the user to factor in their own -preferred algorithms when algorithms are chosen via recipient key -preferences. - - - ---default-preference-list &ParmString; - -Set the list of default preferences to &ParmString;, this list should -be a string similar to the one printed by the command "pref" in the -edit menu. This affects both key generation and "updpref" in the edit -menu. - - - - - - - - - How to specify a user ID - -There are different ways on how to specify a user ID to GnuPG; -here are some examples: - - - - - - - - - -234567C4 -0F34E556E -01347A56A -0xAB123456 - -Here the key ID is given in the usual short form. - - - - -234AABBCC34567C4 -0F323456784E56EAB -01AB3FED1347A5612 -0x234AABBCC34567C4 - -Here the key ID is given in the long form as used by OpenPGP -(you can get the long key ID using the option --with-colons). - - - - -1234343434343434C434343434343434 -123434343434343C3434343434343734349A3434 -0E12343434343434343434EAB3484343434343434 -0xE12343434343434343434EAB3484343434343434 - -The best way to specify a key ID is by using the fingerprint of -the key. This avoids any ambiguities in case that there are duplicated -key IDs (which are really rare for the long key IDs). - - - - -=Heinrich Heine <heinrichh@uni-duesseldorf.de> - -Using an exact to match string. The equal sign indicates this. - - - - -<heinrichh@uni-duesseldorf.de> - -Using the email address part which must match exactly. The left angle bracket -indicates this email address mode. - - - - -+Heinrich Heine duesseldorf - -All words must match exactly (not case sensitive) but can appear in -any order in the user ID. Words are any sequences of letters, -digits, the underscore and all characters with bit 7 set. - - - - -Heine -*Heine - -By case insensitive substring matching. This is the default mode but -applications may want to explicitly indicate this by putting the asterisk -in front. - - - - - - -Note that you can append an exclamation mark to key IDs or -fingerprints. This flag tells GnuPG to use exactly the given primary -or secondary key and not to try to figure out which secondary or -primary key to use. - - - - - - - RETURN VALUE - -The program returns 0 if everything was fine, 1 if at least -a signature was bad, and other error codes for fatal errors. - - - - - EXAMPLES - - - -gpg -se -r -sign and encrypt for user Bob - - - -gpg --clearsign &ParmFile; -make a clear text signature - - - -gpg -sb &ParmFile; -make a detached signature - - - -gpg --list-keys -show keys - - - -gpg --fingerprint -show fingerprint - - - -gpg --verify -gpg --verify - -Verify the signature of the file but do not output the data. The second form -is used for detached signatures, where - - - - - - - ENVIRONMENT - - - -HOME -Used to locate the default home directory. - - -GNUPGHOME -If set directory used instead of "~/.gnupg". - - -GPG_AGENT_INFO -Used to locate the gpg-agent; only honored when ---use-agent is set. The value consists of 3 colon delimited fields: -The first is the path to the Unix Domain Socket, the second the PID of -the gpg-agent and the protocol version which should be set to 1. When -starting the gpg-agent as described in its documentation, this -variable is set to the correct value. The option --gpg-agent-info can -be used to override it. - - -http_proxy -Only honored when the keyserver-option -honor-http-proxy is set. - - - - - - - FILES - - - -~/.gnupg/secring.gpg -The secret keyring - - - -~/.gnupg/secring.gpg.lock -and the lock file - - - -~/.gnupg/pubring.gpg -The public keyring - - - -~/.gnupg/pubring.gpg.lock -and the lock file - - - -~/.gnupg/trustdb.gpg -The trust database - - - -~/.gnupg/trustdb.gpg.lock -and the lock file - - - -~/.gnupg/random_seed -used to preserve the internal random pool - - - -~/.gnupg/gpg.conf -Default configuration file - - - -~/.gnupg/options -Old style configuration file; only used when gpg.conf -is not found - - - -/usr[/local]/share/gnupg/options.skel -Skeleton options file - - - -/usr[/local]/lib/gnupg/ -Default location for extensions - - - - - - - - - WARNINGS - -Use a *good* password for your user account and a *good* passphrase -to protect your secret key. This passphrase is the weakest part of the -whole system. Programs to do dictionary attacks on your secret keyring -are very easy to write and so you should protect your "~/.gnupg/" -directory very well. - - -Keep in mind that, if this program is used over a network (telnet), it -is *very* easy to spy out your passphrase! - - -If you are going to verify detached signatures, make sure that the -program knows about it; either be giving both filenames on the -command line or using - to specify stdin. - - - - - - BUGS - -On many systems this program should be installed as setuid(root). This -is necessary to lock memory pages. Locking memory pages prevents the -operating system from writing memory pages to disk. If you get no -warning message about insecure memory your operating system supports -locking without being root. The program drops root privileges as soon -as locked memory is allocated. - - - - - diff --git a/doc/gpg.texi b/doc/gpg.texi deleted file mode 100644 index 88cf053f1..000000000 --- a/doc/gpg.texi +++ /dev/null @@ -1,1531 +0,0 @@ -\input texinfo -@c This Texinfo document has been automatically generated by -@c docbook2texi from a DocBook documentation. The tool used -@c can be found at: -@c -@c Please send any bug reports, improvements, comments, -@c patches, etc. to Steve Cheng . - -@setfilename gpg.info -@dircategory GnuPG -@direntry -* gpg: (gpg). GnuPG encryption and signing tool. -@end direntry - -@node top -@top gpg -@menu -@end menu - -@majorheading Name -gpg ---- encryption and signing tool - -@majorheading Synopsis - -@majorheading DESCRIPTION -@code{gpg} is the main program for the GnuPG system. - -This man page only lists the commands and options available. -For more verbose documentation get the GNU Privacy Handbook (GPH) or -one of the other documents at http://www.gnupg.org/docs.html . - -Please remember that option parsing stops as soon as a non option is -encountered, you can explicitly stop option parsing by using the -special option "---". - -@majorheading COMMANDS -@code{gpg} recognizes these commands: - -@table @asis -@item -s, ---sign -Make a signature. This command may be combined -with ---encrypt. - -@item ---clearsign -Make a clear text signature. - -@item -b, ---detach-sign -Make a detached signature. - -@item -e, ---encrypt -Encrypt data. This option may be combined with ---sign. - -@item -c, ---symmetric -Encrypt with symmetric cipher only. -This command asks for a passphrase. - -@item ---store -Store only (make a simple RFC1991 packet). - -@item ---decrypt @code{file} -Decrypt @code{file} (or stdin if no file is specified) and -write it to stdout (or the file specified with ----output). If the decrypted file is signed, the -signature is also verified. 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. - -@item ---verify @code{sigfile} @code{signed-files} -Assume that @code{sigfile} is a signature and verify it -without generating any output. With no arguments, -the signature packet is read from stdin. If -only a sigfile is given, it may be a complete -signature or a detached signature, in which case -the signed stuff is expected in a file without the -".sig" or ".asc" extension. -With more than -1 argument, the first should be a detached signature -and the remaining files are the signed stuff. To read the signed -stuff from stdin, use @samp{-} as the second filename. -For security reasons a detached signature cannot read the signed -material from stdin without denoting it in the above way. - -@item ---verify-files @code{files} -This is a special version of the ---verify command which does not work with -detached signatures. The command expects the files to be verified either -on the command line or reads the filenames from stdin; each name must be on -separate line. The command is intended for quick checking of many files. - -@item ---encrypt-files @code{files} -This is a special version of the ---encrypt command. The command expects -the files to be encrypted either on the command line or reads the filenames -from stdin; each name must be on separate line. The command is intended -for a quick encryption of multiple files. - -@item ---decrypt-files @code{files} -The same as ---encrypt-files with the difference that files will be -decrypted. The syntax or the filenames is the same. - -@item ---list-keys @code{names} -@itemx ---list-public-keys @code{names} -List all keys from the public keyrings, or just the -ones given on the command line. - -@item ---list-secret-keys @code{names} -List all keys from the secret keyrings, or just the -ones given on the command line. - -@item ---list-sigs @code{names} -Same as ---list-keys, but the signatures are listed too. - -@item ---check-sigs @code{names} -Same as ---list-sigs, but the signatures are verified. - -@item ---fingerprint @code{names} -List all keys with their fingerprints. This is the -same output as ---list-keys but with the additional output -of a line with the fingerprint. May also be combined -with ---list-sigs or --check-sigs. -If this command is given twice, the fingerprints of all -secondary keys are listed too. - -@item ---list-packets -List only the sequence of packets. This is mainly -useful for debugging. - -@item ---gen-key -Generate a new key pair. This command is normally only used -interactively. - -There is an experimental feature which allows you to create keys -in batch mode. See the file @file{doc/DETAILS} -in the source distribution on how to use this. - -@item ---edit-key @code{name} -Present a menu which enables you to do all key -related tasks: - -@table @asis -@item sign -Make a signature on key of user @code{name} -If the key is not yet signed by the default -user (or the users given with -u), the -program displays the information of the key -again, together with its fingerprint and -asks whether it should be signed. This -question is repeated for all users specified -with -u. - -@item lsign -Same as ---sign but the signature is marked as -non-exportable and will therefore never be used -by others. This may be used to make keys valid -only in the local environment. - -@item nrsign -Same as ---sign but the signature is marked as non-revocable and can -therefore never be revoked. - -@item nrlsign -Combines the functionality of nrsign and lsign to make a signature -that is both non-revocable and -non-exportable. - -@item revsig -Revoke a signature. GnuPG asks for every -signature which has been done by one of -the secret keys, whether a revocation -certificate should be generated. - -@item trust -Change the owner trust value. This updates the -trust-db immediately and no save is required. - -@item disable -@itemx enable -Disable or enable an entire key. A disabled key can normally not be used -for encryption. - -@item adduid -Create an alternate user id. - -@item addphoto -Create a photographic user id. - -@item deluid -Delete a user id. - -@item addkey -Add a subkey to this key. - -@item delkey -Remove a subkey. - -@item addrevoker -Add a designated revoker. This takes one optional argument: -"sensitive". If a designated revoker is marked as sensitive, it will -not be exported by default (see -export-options). - -@item revkey -Revoke a subkey. - -@item expire -Change the key expiration time. If a key is -selected, the time of this key will be changed. -With no selection the key expiration of the -primary key is changed. - -@item passwd -Change the passphrase of the secret key. - -@item primary -Flag the current user id as the primary one, removes the primary user -id flag from all other user ids and sets the timestamp of all affected -self-signatures one second ahead. Note that setting a photo user ID -as primary makes it primary over other photo user IDs, and setting a -regular user ID as primary makes it primary over other regular user -IDs. - -@item uid @code{n} -Toggle selection of user id with index @code{n}. -Use 0 to deselect all. - -@item key @code{n} -Toggle selection of subkey with index @code{n}. -Use 0 to deselect all. - -@item check -Check all selected user ids. - -@item showphoto -Display the selected photographic user -id. - -@item pref -List preferences from the selected user ID. This shows the actual -preferences, without including any implied preferences. - -@item showpref -More verbose preferences listing for the selected user ID. This shows -the preferences in effect by including the implied preferences of -3DES (cipher), SHA-1 (digest), and Uncompressed (compression) if they -are not already included in the preference list. - -@item setpref @code{string} -Set the list of user ID preferences to @code{string}, this should be a -string similar to the one printed by "pref". Using an empty string -will set the default preference string, using "none" will set the -preferences to nil. Use "gpg -v ---version" to get a list of available -algorithms. This command just initializes an internal list and does -not change anything unless another command (such as "updpref") which -changes the self-signatures is used. - -@item updpref -Change the preferences of all user IDs (or just of the selected ones -to the current list of preferences. The timestamp of all affected -self-signatures will be advanced by one second. Note that while you -can change the preferences on an attribute user ID (aka "photo ID"), -GnuPG does not select keys via attribute user IDs so these preferences -will not be used by GnuPG. - -@item toggle -Toggle between public and secret key listing. - -@item save -Save all changes to the key rings and quit. - -@item quit -Quit the program without updating the -key rings. - -@end table - -The listing shows you the key with its secondary -keys and all user ids. Selected keys or user ids -are indicated by an asterisk. The trust value is -displayed with the primary key: the first is the -assigned owner trust and the second is the calculated -trust value. Letters are used for the values: - -@table @asis -@item - -No ownertrust assigned / not yet calculated. - -@item e -Trust -calculation has failed; probably due to an expired key. - -@item q -Not enough information for calculation. - -@item n -Never trust this key. - -@item m -Marginally trusted. - -@item f -Fully trusted. - -@item u -Ultimately trusted. - -@end table - -@item ---sign-key @code{name} -Signs a public key with your secret key. This is a shortcut version of -the subcommand "sign" from ---edit. - -@item ---lsign-key @code{name} -Signs a public key with your secret key but marks it as -non-exportable. This is a shortcut version of the subcommand "lsign" -from ---edit. - -@item ---nrsign-key @code{name} -Signs a public key with your secret key but marks it as non-revocable. -This is a shortcut version of the subcommand "nrsign" from ---edit. - -@item ---delete-key @code{name} -Remove key from the public keyring. In batch mode either ---yes is -required or the key must be specified by fingerprint. This is a -safeguard against accidental deletion of multiple keys. - -@item ---delete-secret-key @code{name} -Remove key from the secret and public keyring. In batch mode the key -must be specified by fingerprint. - -@item ---delete-secret-and-public-key @code{name} -Same as ---delete-key, but if a secret key exists, it will be removed -first. In batch mode the key must be specified by fingerprint. - -@item ---gen-revoke -Generate a revocation certificate for the complete key. To revoke -a subkey or a signature, use the ---edit command. - -@item ---desig-revoke -Generate a designated revocation certificate for a key. This allows a -user (with the permission of the keyholder) to revoke someone elses -key. - -@item ---export @code{names} -Either export all keys from all keyrings (default -keyrings and those registered via option ---keyring), -or if at least one name is given, those of the given -name. The new keyring is written to stdout or to -the file given with option "output". Use together -with ---armor to mail those keys. - -@item ---send-keys @code{names} -Same as ---export but sends the keys to a keyserver. -Option ---keyserver must be used to give the name -of this keyserver. Don't send your complete keyring -to a keyserver - select only those keys which are new -or changed by you. - -@item ---export-all @code{names} -Same as ---export, but also exports keys which -are not compatible with OpenPGP. - -@item ---export-secret-keys @code{names} -@itemx ---export-secret-subkeys @code{names} -Same as ---export, but exports the secret keys instead. -This is normally not very useful and a security risk. -The second form of the command has the special property to -render the secret part of the primary key useless; this is -a GNU extension to OpenPGP and other implementations can -not be expected to successfully import such a key. -See the option ---simple-sk-checksum if you want to import such an -exported key with an older OpenPGP implementation. - -@item ---import @code{files} -@itemx ---fast-import @code{files} -Import/merge keys. This adds the given keys to the -keyring. The fast version is currently just a synonym. - -There are a few other options which control how this command works. -Most notable here is the ---merge-only option which does not insert new keys -but does only the merging of new signatures, user-IDs and subkeys. - -@item ---recv-keys @code{key IDs} -Import the keys with the given key IDs from a keyserver. Option ----keyserver must be used to give the name of this keyserver. - -@item ---search-keys @code{names} -Search the keyserver for the given names. Multiple names given here -will be joined together to create the search string for the keyserver. -Option ---keyserver must be used to give the name of this keyserver. - -@item ---update-trustdb -Do trust DB maintenance. This command goes over all keys and builds -the Web-of-Trust. This is an interactive command because it may has to -ask for the "ownertrust" values of keys. The user has to give an -estimation in how far she trusts the owner of the displayed key to -correctly certify (sign) other keys. It does only ask for that value -if it has not yet been assigned to a key. Using the edit menu, that -value can be changed at any time later. - -@item ---check-trustdb -Do trust DB maintenance without user interaction. Form time to time -the trust database must be updated so that expired keys and resulting -changes in the Web-of-Trust can be tracked. GnuPG tries to figure -when this is required and then does it implicitly; this command can be -used to force such a check. The processing is identically to that of ----update-trustdb but it skips keys with a not yet defined "ownertrust". - -For use with cron jobs, this command can be used together with ---batch -in which case the check is only done when it is due. To force a run -even in batch mode add the option ---yes. - -@item ---export-ownertrust @code{file} -Store the ownertrust values into -@code{file} (or stdin if not given). This is useful for backup -purposes as these values are the only ones which can't be re-created -from a corrupted trust DB. - -@item ---import-ownertrust @code{files} -Update the trustdb with the ownertrust values stored -in @code{files} (or stdin if not given); existing -values will be overwritten. - -@item ---print-md @code{algo} @code{files} -@itemx ---print-mds @code{files} -Print message digest of algorithm ALGO for all given files or stdin. -With the second form (or a deprecated "*" as algo) digests for all -available algorithms are printed. - -@item ---gen-random @code{0|1|2} @code{count} -Emit COUNT random bytes of the given quality level. If count is not given -or zero, an endless sequence of random bytes will be emitted. -PLEASE, don't use this command unless you know what you are doing; it may -remove precious entropy from the system! - -@item ---gen-prime @code{mode} @code{bits} @code{qbits} -Use the source, Luke :-). The output format is still subject to change. - -@item ---version -Print version information along with a list -of supported algorithms. - -@item ---warranty -Print warranty information. - -@item -h, ---help -Print usage information. This is a really long list even though it doesn't list -all options. - -@end table - -@majorheading OPTIONS -Long options can be put in an options file (default -"~/.gnupg/gpg.conf"). Short option names will not work - for example, -"armor" is a valid option for the options file, while "a" is not. Do -not write the 2 dashes, but simply the name of the option and any -required arguments. Lines with a hash ('#') as the first -non-white-space character are ignored. Commands may be put in this -file too, but that does not make sense. - -@code{gpg} recognizes these options: - -@table @asis -@item -a, ---armor -Create ASCII armored output. - -@item -o, ---output @code{file} -Write output to @code{file}. - -@item -u, ---local-user @code{name} -Use @code{name} as the user ID to sign. -This option is silently ignored for the list commands, -so that it can be used in an options file. - -@item ---default-key @code{name} -Use @code{name} as default user ID for signatures. If this -is not used the default user ID is the first user ID -found in the secret keyring. - -@item -r, ---recipient @code{name} -@itemx -Encrypt for user id @code{name}. If this option is not -specified, GnuPG asks for the user-id unless ---default-recipient is given - -@item ---default-recipient @code{name} -Use @code{name} as default recipient if option ---recipient is not used and -don't ask if this is a valid one. @code{name} must be non-empty. - -@item ---default-recipient-self -Use the default key as default recipient if option ---recipient is not used and -don't ask if this is a valid one. The default key is the first one from the -secret keyring or the one set with ---default-key. - -@item ---no-default-recipient -Reset ---default-recipient and --default-recipient-self. - -@item ---encrypt-to @code{name} -Same as ---recipient but this one is intended for use -in the options file and may be used with -your own user-id as an "encrypt-to-self". These keys -are only used when there are other recipients given -either by use of ---recipient or by the asked user id. -No trust checking is performed for these user ids and -even disabled keys can be used. - -@item ---no-encrypt-to -Disable the use of all ---encrypt-to keys. - -@item -v, ---verbose -Give more information during processing. If used -twice, the input data is listed in detail. - -@item -q, ---quiet -Try to be as quiet as possible. - -@item -z @code{n}, ---compress @code{n} -Set compression level to @code{n}. A value of 0 for @code{n} -disables compression. Default is to use the default -compression level of zlib (normally 6). - -@item -t, ---textmode -Use canonical text mode. If -t (but not ----textmode) is used together with armoring -and signing, this enables clearsigned messages. -This kludge is needed for PGP compatibility; -normally you would use ---sign or --clearsign -to selected the type of the signature. - -@item -n, ---dry-run -Don't make any changes (this is not completely implemented). - -@item -i, ---interactive -Prompt before overwriting any files. - -@item ---batch -Use batch mode. Never ask, do not allow interactive -commands. - -@item ---no-tty -Make sure that the TTY (terminal) is never used for any output. -This option is needed in some cases because GnuPG sometimes prints -warnings to the TTY if ---batch is used. - -@item ---no-batch -Disable batch mode. This may be of use if ---batch -is enabled from an options file. - -@item ---yes -Assume "yes" on most questions. - -@item ---no -Assume "no" on most questions. - -@item ---default-cert-check-level @code{n} -The default to use for the check level when signing a key. - -0 means you make no particular claim as to how carefully you verified -the key. - -1 means you believe the key is owned by the person who claims to own -it but you could not, or did not verify the key at all. This is -useful for a "persona" verification, where you sign the key of a -pseudonymous user. - -2 means you did casual verification of the key. For example, this -could mean that you verified that the key fingerprint and checked the -user ID on the key against a photo ID. - -3 means you did extensive verification of the key. For example, this -could mean that you verified the key fingerprint with the owner of the -key in person, and that you checked, by means of a hard to forge -document with a photo ID (such as a passport) that the name of the key -owner matches the name in the user ID on the key, and finally that you -verified (by exchange of email) that the email address on the key -belongs to the key owner. - -Note that the examples given above for levels 2 and 3 are just that: -examples. In the end, it is up to you to decide just what "casual" -and "extensive" mean to you. - -This option defaults to 0. - -@item ---trusted-key @code{long key ID} -Assume that the specified key (which must be given -as a full 8 byte key ID) is as trustworthy as one of -your own secret keys. This option is useful if you -don't want to keep your secret keys (or one of them) -online but still want to be able to check the validity of a given -recipient's or signator's key. - -@item ---always-trust -Skip key validation and assume that used keys are always fully trusted. -You won't use this unless you have installed some external validation -scheme. This option also suppresses the "[uncertain]" tag printed -with signature checks when there is no evidence that the user ID -is bound to the key. - -@item ---keyserver @code{name} -Use @code{name} as your keyserver. This is the server that ---recv-keys, ----send-keys, and --search-keys will communicate with to receive keys -from, send keys to, and search for keys on. The format of the -@code{name} is a URI: `scheme:[//]keyservername[:port]' The scheme is -the type of keyserver: "hkp" for the Horowitz (or compatible) -keyservers, "ldap" for the NAI LDAP keyserver, or "mailto" for the -Horowitz email keyserver. Note that your particular installation of -GnuPG may have other keyserver types available as well. - -Most keyservers synchronize with each other, so there is generally no -need to send keys to more than one server. Using the command "host -l -pgp.net | grep wwwkeys" gives you a list of HKP keyservers. When -using one of the wwwkeys servers, due to load balancing using -round-robin DNS you may notice that you get a different key server -each time. - -@item ---keyserver-options @code{parameters} -This is a space or comma delimited string that gives options for the -keyserver. Options can be prepended with a `no-' to give the opposite -meaning. Valid import-options or export-options may be used here as -well to apply to importing (---recv-key) or exporting (--send-key) a -key from a keyserver. While not all options are available for all -keyserver types, some common options are: - -@table @asis -@item include-revoked -When searching for a key, include keys that are marked on the -keyserver as revoked. Note that this option is always set when using -the NAI HKP keyserver, as this keyserver does not differentiate -between revoked and unrevoked keys. When using the LDAP keyserver, -this applies to both searching (---search-keys) and receiving -(---recv-keys). - -@item include-disabled -When receiving or searching for a key, include keys that are marked on -the keyserver as disabled. Note that this option is not used with HKP -keyservers, as they do not support disabling keys. - -@item include-subkeys -When receiving a key, include subkeys in the search. Note that this -option is not used with HKP keyservers, as they do not support -retrieving keys by subkey id. - -@item use-temp-files -On most Unix-like platforms, GnuPG communicates with the keyserver -helper program via pipes, which is the most efficient method. This -option forces GnuPG to use temporary files to communicate. On some -platforms (such as Win32 and RISC OS), this option is always enabled. - -@item keep-temp-files -If using `use-temp-files', do not delete the temp files after using -them. This option is useful to learn the keyserver communication -protocol by reading the temporary files. - -@item verbose -Tell the keyserver helper program to be more verbose. This option can -be repeated multiple times to increase the verbosity level. - -@item honor-http-proxy -For keyserver schemes that use HTTP (such as HKP), try to access the -keyserver over the proxy set with the environment variable -"http_proxy". - -@item auto-key-retrieve -This option enables the automatic retrieving of keys from a keyserver -when verifying signatures made by keys that are not on the local -keyring. - -@end table - -@item ---import-options @code{parameters} -This is a space or comma delimited string that gives options for -importing keys. Options can be prepended with a `no-' to give the -opposite meaning. The options are: - -@table @asis -@item allow-local-sigs -Allow importing key signatures marked as "local". This is not -generally useful unless a shared keyring scheme is being used. -Defaults to no. - -@item repair-hkp-subkey-bug -During import, attempt to repair the HKP keyserver mangling multiple -subkeys bug. Note that this cannot completely repair the damaged key -as some crucial data is removed by the keyserver, but it does at least -give you back one subkey. Defaults to no for regular ---import and to -yes for keyserver ---recv-keys. - -@end table - -@item ---export-options @code{parameters} -This is a space or comma delimited string that gives options for -exporting keys. Options can be prepended with a `no-' to give the -opposite meaning. The options are: - -@table @asis -@item include-non-rfc -Include non-RFC compliant keys in the export. Defaults to yes. - -@item include-local-sigs -Allow exporting key signatures marked as "local". This is not -generally useful unless a shared keyring scheme is being used. -Defaults to no. - -@item include-attributes -Include attribute user IDs (photo IDs) while exporting. This is -useful to export keys if they are going to be used by an OpenPGP -program that does not accept attribute user IDs. Defaults to yes. - -@item include-sensitive-revkeys -Include designated revoker information that was marked as -"sensitive". Defaults to no. - -@end table - -@item ---show-photos -Causes ---list-keys, --list-sigs, --list-public-keys, ----list-secret-keys, and verifying a signature to also display the -photo ID attached to the key, if any. -See also ---photo-viewer. - -@item ---no-show-photos -Resets the ---show-photos flag. - -@item ---photo-viewer @code{string} -This is the command line that should be run to view a photo ID. "%i" -will be expanded to a filename containing the photo. "%I" does the -same, except the file will not be deleted once the viewer exits. -Other flags are "%k" for the key ID, "%K" for the long key ID, "%f" -for the key fingerprint, "%t" for the extension of the image type -(e.g. "jpg"), "%T" for the MIME type of the image (e.g. "image/jpeg"), -and "%%" for an actual percent sign. If neither %i or %I are present, -then the photo will be supplied to the viewer on standard input. - -The default viewer is "xloadimage -fork -quiet -title 'KeyID 0x%k' -stdin" - -@item ---exec-path @code{string} -Sets a list of directories to search for photo viewers and keyserver -helpers. If not provided, keyserver helpers use the compiled-in -default directory, and photo viewers use the $PATH environment -variable. - -@item ---show-keyring -Causes ---list-keys, --list-public-keys, and --list-secret-keys to -display the name of the keyring a given key resides on. This is only -useful when you're listing a specific key or set of keys. It has no -effect when listing all keys. - -@item ---keyring @code{file} -Add @code{file} to the list of keyrings. -If @code{file} begins with a tilde and a slash, these -are replaced by the HOME directory. If the filename -does not contain a slash, it is assumed to be in the -home-directory ("~/.gnupg" if ---homedir is not used). -The filename may be prefixed with a scheme: - -"gnupg-ring:" is the default one. - -It might make sense to use it together with ---no-default-keyring. - -@item ---secret-keyring @code{file} -Same as ---keyring but for the secret keyrings. - -@item ---homedir @code{directory} -Set the name of the home directory to @code{directory} If this -option is not used it defaults to "~/.gnupg". It does -not make sense to use this in a options file. This -also overrides the environment variable "GNUPGHOME". - -@item ---charset @code{name} -Set the name of the native character set. This is used -to convert some strings to proper UTF-8 encoding. If this option is not used, the default character set is determined -from the current locale. A verbosity level of 3 shows the used one. -Valid values for @code{name} are: - -@table @asis -@item iso-8859-1 -This is the Latin 1 set. - -@item iso-8859-2 -The Latin 2 set. - -@item iso-8859-15 -This is currently an alias for -the Latin 1 set. - -@item koi8-r -The usual Russian set (rfc1489). - -@item utf-8 -Bypass all translations and assume -that the OS uses native UTF-8 encoding. - -@end table - -@item ---utf8-strings -@itemx ---no-utf8-strings -Assume that the arguments are already given as UTF8 strings. The default -(---no-utf8-strings) -is to assume that arguments are encoded in the character set as specified -by ---charset. These options affect all following arguments. Both options may -be used multiple times. - -@item ---options @code{file} -Read options from @code{file} and do not try to read -them from the default options file in the homedir -(see ---homedir). This option is ignored if used -in an options file. - -@item ---no-options -Shortcut for "---options /dev/null". This option is -detected before an attempt to open an option file. -Using this option will also prevent the creation of a -"~./gnupg" homedir. - -@item ---load-extension @code{name} -Load an extension module. If @code{name} does not -contain a slash it is searched in "/usr/local/lib/gnupg" -Extension are in gernal not useful anymore; the use of this -option is deprecated. - -@item ---debug @code{flags} -Set debugging flags. All flags are or-ed and @code{flags} may -be given in C syntax (e.g. 0x0042). - -@item ---debug-all -Set all useful debugging flags. - -@item ---status-fd @code{n} -Write special status strings to the file descriptor @code{n}. -See the file DETAILS in the documentation for a listing of them. - -@item ---logger-fd @code{n} -Write log output to file descriptor @code{n} and not to stderr. - -@item ---attribute-fd @code{n} -Write attribute subpackets to the file descriptor @code{n}. This is -most useful for use with ---status-fd, since the status messages are -needed to separate out the various subpackets from the stream -delivered to the file descriptor. - -@item ---sk-comments -Include secret key comment packets when exporting secret keys. This -is a GnuPG extension to the OpenPGP standard, and is off by default. -Please note that this has nothing to do with the comments in clear -text signatures or armor headers. - -@item ---no-sk-comments -Resets the ---sk-comments option. - -@item ---no-comment -See ---sk-comments. This option is deprecated and may be removed soon. - -@item ---comment @code{string} -Use @code{string} as comment string in clear text signatures. -The default is not do write a comment string. - -@item ---default-comment -Force to write the standard comment string in clear -text signatures. Use this to overwrite a ---comment -from a config file. This option is now obsolete because there is no -default comment string anymore. - -@item ---no-version -Omit the version string in clear text signatures. - -@item ---emit-version -Force to write the version string in clear text -signatures. Use this to overwrite a previous ----no-version from a config file. - -@item -N, ---notation-data @code{name=value} -Put the name value pair into the signature as notation data. -@code{name} must consist only of alphanumeric characters, digits -or the underscore; the first character must not be a digit. -@code{value} may be any printable string; it will be encoded in UTF8, -so you should check that your ---charset is set correctly. -If you prefix @code{name} with an exclamation mark, the notation -data will be flagged as critical (rfc2440:5.2.3.15). - -@item ---show-notation -Show key signature notations in the ---list-sigs or --check-sigs -listings. - -@item ---no-show-notation -Do not show key signature notations in the ---list-sigs or --check-sigs -listings. - -@item ---set-policy-url @code{string} -Use @code{string} as Policy URL for signatures (rfc2440:5.2.3.19). -If you prefix it with an exclamation mark, the policy URL -packet will be flagged as critical. - -@item ---show-policy-url -Show any policy URLs set in the ---list-sigs or --check-sigs listings. - -@item ---no-show-policy-url -Do not show any policy URLs set in the ---list-sigs or --check-sigs -listings. - -@item ---set-filename @code{string} -Use @code{string} as the name of file which is stored in -messages. - -@item ---for-your-eyes-only -Set the `for your eyes only' flag in the message. This causes GnuPG -to refuse to save the file unless the ---output option is given, and -PGP to use the "secure viewer" with a Tempest-resistant font to -display the message. This option overrides ---set-filename. - -@item ---no-for-your-eyes-only -Resets the ---for-your-eyes-only flag. - -@item ---use-embedded-filename -Try to create a file with a name as embedded in the data. -This can be a dangerous option as it allows to overwrite files. - -@item ---completes-needed @code{n} -Number of completely trusted users to introduce a new -key signer (defaults to 1). - -@item ---marginals-needed @code{n} -Number of marginally trusted users to introduce a new -key signer (defaults to 3) - -@item ---max-cert-depth @code{n} -Maximum depth of a certification chain (default is 5). - -@item ---cipher-algo @code{name} -Use @code{name} as cipher algorithm. Running the program -with the command ---version yields a list of supported -algorithms. If this is not used the cipher algorithm is -selected from the preferences stored with the key. - -@item ---digest-algo @code{name} -Use @code{name} as the message digest algorithm. Running the program -with the command ---version yields a list of supported algorithms. - -@item ---cert-digest-algo @code{name} -Use @code{name} as the message digest algorithm used when signing a -key. Running the program with the command ---version yields a list of -supported algorithms. Be aware that if you choose an algorithm that -GnuPG supports but other OpenPGP implementations do not, then some -users will not be able to use the key signatures you make, or quite -possibly your entire key. - -@item ---s2k-cipher-algo @code{name} -Use @code{name} as the cipher algorithm used to protect secret keys. -The default cipher is CAST5. This cipher is also used for -conventional encryption if ---cipher-algo is not given. - -@item ---s2k-digest-algo @code{name} -Use @code{name} as the digest algorithm used to mangle the -passphrases. The default algorithm is RIPE-MD-160. -This digest algorithm is also used for conventional -encryption if ---digest-algo is not given. - -@item ---s2k-mode @code{n} -Selects how passphrases are mangled. If @code{n} is 0 -a plain passphrase (which is not recommended) will be used, -a 1 (default) adds a salt to the passphrase and -a 3 iterates the whole process a couple of times. -Unless ---rfc1991 is used, this mode is also used -for conventional encryption. - -@item ---simple-sk-checksum -Secret keys are integrity protected by using a SHA-1 checksum. This -method will be part of an enhanced OpenPGP specification but GnuPG -already uses it as a countermeasure against certain attacks. Old -applications don't understand this new format, so this option may be -used to switch back to the old behaviour. Using this this option -bears a security risk. Note that using this option only takes effect -when the secret key is encrypted - the simplest way to make this -happen is to change the passphrase on the key (even changing it to the -same value is acceptable). - -@item ---compress-algo @code{n} -Use compression algorithm @code{n}. Default is 2 which is RFC1950 -compression. You may use 1 to use the old zlib version (RFC1951) which -is used by PGP. 0 disables compression. The default algorithm may give -better results because the window size is not limited to 8K. If this -is not used the OpenPGP behavior is used, i.e. the compression -algorithm is selected from the preferences; note, that this can't be -done if you do not encrypt the data. - -@item ---disable-cipher-algo @code{name} -Never allow the use of @code{name} as cipher algorithm. -The given name will not be checked so that a later loaded algorithm -will still get disabled. - -@item ---disable-pubkey-algo @code{name} -Never allow the use of @code{name} as public key algorithm. -The given name will not be checked so that a later loaded algorithm -will still get disabled. - -@item ---no-sig-cache -Do not cache the verification status of key signatures. -Caching gives a much better performance in key listings. However, if -you suspect that your public keyring is not save against write -modifications, you can use this option to disable the caching. It -probably does not make sense to disable it because all kind of damage -can be done if someone else has write access to your public keyring. - -@item ---no-sig-create-check -GnuPG normally verifies each signature right after creation to protect -against bugs and hardware malfunctions which could leak out bits from -the secret key. This extra verification needs some time (about 115% -for DSA keys), and so this option can be used to disable it. -However, due to the fact that the signature creation needs manual -interaction, this performance penalty does not matter in most settings. - -@item ---auto-check-trustdb -If GnuPG feels that its information about the Web-of-Trust has to be -updated, it automatically runs the ---check-trustdb command -internally. This may be a time consuming process. - -@item ---no-auto-check-trustdb -Resets the ---auto-check-trustdb option. - -@item ---throw-keyid -Do not put the keyid into encrypted packets. This option -hides the receiver of the message and is a countermeasure -against traffic analysis. It may slow down the decryption -process because all available secret keys are tried. - -@item ---not-dash-escaped -This option changes the behavior of cleartext signatures -so that they can be used for patch files. You should not -send such an armored file via email because all spaces -and line endings are hashed too. You can not use this -option for data which has 5 dashes at the beginning of a -line, patch files don't have this. A special armor header -line tells GnuPG about this cleartext signature option. - -@item ---escape-from-lines -Because some mailers change lines starting with "From " -to " -Using an exact to match string. The equal sign indicates this. - -@item -Using the email address part which must match exactly. The left angle bracket -indicates this email address mode. - -@item +Heinrich Heine duesseldorf -All words must match exactly (not case sensitive) but can appear in -any order in the user ID. Words are any sequences of letters, -digits, the underscore and all characters with bit 7 set. - -@item Heine -@itemx *Heine -By case insensitive substring matching. This is the default mode but -applications may want to explicitly indicate this by putting the asterisk -in front. - -@end table - -Note that you can append an exclamation mark to key IDs or -fingerprints. This flag tells GnuPG to use exactly the given primary -or secondary key and not to try to figure out which secondary or -primary key to use. - -@majorheading RETURN VALUE -The program returns 0 if everything was fine, 1 if at least -a signature was bad, and other error codes for fatal errors. - -@majorheading EXAMPLES -@table @asis -@item gpg -se -r @code{Bob} @code{file} -sign and encrypt for user Bob - -@item gpg ---clearsign @code{file} -make a clear text signature - -@item gpg -sb @code{file} -make a detached signature - -@item gpg ---list-keys @code{user_ID} -show keys - -@item gpg ---fingerprint @code{user_ID} -show fingerprint - -@item gpg ---verify @code{pgpfile} -@itemx gpg ---verify @code{sigfile} @code{files} -Verify the signature of the file but do not output the data. The second form -is used for detached signatures, where @code{sigfile} is the detached -signature (either ASCII armored of binary) and @code{files} are the signed -data; if this is not given the name of the file holding the signed data is -constructed by cutting off the extension (".asc" or ".sig") of -@code{sigfile} or by asking the user for the filename. - -@end table - -@majorheading ENVIRONMENT -@table @asis -@item HOME -Used to locate the default home directory. - -@item GNUPGHOME -If set directory used instead of "~/.gnupg". - -@item GPG_AGENT_INFO -Used to locate the gpg-agent; only honored when ----use-agent is set. The value consists of 3 colon delimited fields: -The first is the path to the Unix Domain Socket, the second the PID of -the gpg-agent and the protocol version which should be set to 1. When -starting the gpg-agent as described in its documentation, this -variable is set to the correct value. The option ---gpg-agent-info can -be used to overide it. - -@item http_proxy -Only honored when the keyserver-option -honor-http-proxy is set. - -@end table - -@majorheading FILES -@table @asis -@item ~/.gnupg/secring.gpg -The secret keyring - -@item ~/.gnupg/secring.gpg.lock -and the lock file - -@item ~/.gnupg/pubring.gpg -The public keyring - -@item ~/.gnupg/pubring.gpg.lock -and the lock file - -@item ~/.gnupg/trustdb.gpg -The trust database - -@item ~/.gnupg/trustdb.gpg.lock -and the lock file - -@item ~/.gnupg/random_seed -used to preserve the internal random pool - -@item ~/.gnupg/gpg.conf -Default configuration file - -@item ~/.gnupg/options -Old style configuration file; only used when gpg.conf -is not found - -@item /usr[/local]/share/gnupg/options.skel -Skeleton options file - -@item /usr[/local]/lib/gnupg/ -Default location for extensions - -@end table - -@majorheading WARNINGS -Use a *good* password for your user account and a *good* passphrase -to protect your secret key. This passphrase is the weakest part of the -whole system. Programs to do dictionary attacks on your secret keyring -are very easy to write and so you should protect your "~/.gnupg/" -directory very well. - -Keep in mind that, if this program is used over a network (telnet), it -is *very* easy to spy out your passphrase! - -If you are going to verify detached signatures, make sure that the -program knows about it; either be giving both filenames on the -commandline or using @samp{-} to specify stdin. - -@majorheading BUGS -On many systems this program should be installed as setuid(root). This -is necessary to lock memory pages. Locking memory pages prevents the -operating system from writing memory pages to disk. If you get no -warning message about insecure memory your operating system supports -locking without being root. The program drops root privileges as soon -as locked memory is allocated. - -@bye diff --git a/doc/gpgv.sgml b/doc/gpgv.sgml deleted file mode 100644 index 4119b41dc..000000000 --- a/doc/gpgv.sgml +++ /dev/null @@ -1,225 +0,0 @@ - - - - -directory"> -file"> -&ParmFile;"> -files"> -&ParmFiles;"> -names"> -&ParmNames;"> -name"> -&ParmName;"> -key IDs"> -n"> -flags"> -string"> -value"> -name=value"> -]> - - - - gpgv - 1 - GNU Tools - - - signature verification tool - - - -gpgv - - - - - - - DESCRIPTION - - - -This program is a stripped down version of - - - - - -OPTIONS - - - - - - - --v, --verbose - -Give more information during processing. If used -twice, the input data is listed in detail. - - - - --q, --quiet - -Try to be as quiet as possible. - - - - ---keyring &ParmFile; - -Add &ParmFile to the list of keyrings. -If &ParmFile begins with a tilde and a slash, these -are replaced by the HOME directory. If the filename -does not contain a slash, it is assumed to be in the -home-directory ("~/.gnupg" if --homedir is not used). -The filename may be prefixed with a scheme: -"gnupg-ring:" is the default one. -It might make sense to use it together with --no-default-keyring. - - - - ---homedir &ParmDir; - -Set the name of the home directory to &ParmDir; If this -option is not used it defaults to "~/.gnupg". It does -not make sense to use this in a options file. This -also overrides the environment variable "GNUPGHOME". - - - - ---status-fd &ParmN; - -Write special status strings to the file descriptor &ParmN;. -See the file DETAILS in the documentation for a listing of them. - - - - ---logger-fd &ParmN; - -Write log output to file descriptor &ParmN; and not to stderr. - - - - ---ignore-time-conflict - -GnuPG normally checks that the timestamps associated with keys and -signatures have plausible values. However, sometimes a signature seems to -be older than the key due to clock problems. This option makes these -checks just a warning. - - - - - - - - - RETURN VALUE - -The program returns 0 if everything was fine, 1 if at least -one signature was bad, and other error codes for fatal errors. - - - - - EXAMPLES - - - -gpgv -gpgv - -Verify the signature of the file. The second form -is used for detached signatures, where - - - - - - - ENVIRONMENT - - - -HOME -Used to locate the default home directory. - - -GNUPGHOME -If set directory used instead of "~/.gnupg". - - - - - - - - FILES - - - -~/.gnupg/trustedkeys.gpg -The default keyring with the allowed keys - - - - - - - - - diff --git a/doc/gpgv.texi b/doc/gpgv.texi deleted file mode 100644 index 91e2fcadf..000000000 --- a/doc/gpgv.texi +++ /dev/null @@ -1,119 +0,0 @@ -\input texinfo -@c This Texinfo document has been automatically generated by -@c docbook2texi from a DocBook documentation. The tool used -@c can be found at: -@c -@c Please send any bug reports, improvements, comments, -@c patches, etc. to Steve Cheng . - -@setfilename gpgv.info -@dircategory GnuPG -@direntry -* gpgv: (gpgv). GnuPG signature verification tool. -@end direntry - -@node top -@top gpgv -@menu -@end menu - -@majorheading Name -gpgv ---- signature verification tool - -@majorheading Synopsis - -@majorheading DESCRIPTION -@code{gpgv} is the OpenPGP signature checking tool. - -This program is a stripped down version of @code{gpg} which is only -able -to check signatures. It is somewhat smaller than the full blown -@code{gpg} and uses a different (and more simple way) to check that -the public keys used to made the signature are trustworth. There is -no options files and only very few options are implemented. - -@code{gpgv} assumes that all keys in the keyring are trustworty. -It uses by default a keyring named @file{trustedkeys.gpg} which is -assumed to be in the home directory as defined by GnuPG or set by an -option or an environment variable. An option may be used to specify -another keyring or even multiple keyrings. - -@majorheading OPTIONS -@code{gpgv} recognizes these options: - -@table @asis -@item -v, ---verbose -Give more information during processing. If used -twice, the input data is listed in detail. - -@item -q, ---quiet -Try to be as quiet as possible. - -@item ---keyring @code{file} -Add @code{file} to the list of keyrings. -If @code{file} begins with a tilde and a slash, these -are replaced by the HOME directory. If the filename -does not contain a slash, it is assumed to be in the -home-directory ("~/.gnupg" if ---homedir is not used). -The filename may be prefixed with a scheme: - -"gnupg-ring:" is the default one. - -It might make sense to use it together with ---no-default-keyring. - -@item ---homedir @code{directory} -Set the name of the home directory to @code{directory} If this -option is not used it defaults to "~/.gnupg". It does -not make sense to use this in a options file. This -also overrides the environment variable "GNUPGHOME". - -@item ---status-fd @code{n} -Write special status strings to the file descriptor @code{n}. -See the file DETAILS in the documentation for a listing of them. - -@item ---logger-fd @code{n} -Write log output to file descriptor @code{n} and not to stderr. - -@item ---ignore-time-conflict -GnuPG normally checks that the timestamps associated with keys and -signatures have plausible values. However, sometimes a signature seems to -be older than the key due to clock problems. This option makes these -checks just a warning. - -@end table - -@majorheading RETURN VALUE -The program returns 0 if everything was fine, 1 if at least -one signature was bad, and other error codes for fatal errors. - -@majorheading EXAMPLES -@table @asis -@item gpgv @code{pgpfile} -@itemx gpgv @code{sigfile} @code{files} -Verify the signature of the file. The second form -is used for detached signatures, where @code{sigfile} is the detached -signature (either ASCII armored or binary) and @code{files} are the signed -data; if this is not given the name of the file holding the signed data is -constructed by cutting off the extension (".asc", ".sig" or ".sign") from -@code{sigfile}. - -@end table - -@majorheading ENVIRONMENT -@table @asis -@item HOME -Used to locate the default home directory. - -@item GNUPGHOME -If set directory used instead of "~/.gnupg". - -@end table - -@majorheading FILES -@table @asis -@item ~/.gnupg/trustedkeys.gpg -The default keyring with the allowed keys - -@end table - -@bye diff --git a/doc/gph/ChangeLog b/doc/gph/ChangeLog deleted file mode 100644 index 0d42fa163..000000000 --- a/doc/gph/ChangeLog +++ /dev/null @@ -1,9 +0,0 @@ -Tue Sep 7 16:18:03 1999 Werner Koch (wk@gnupg.org) - - * Makefile.am: Ugly workarounds to do a VPATH build. - -Fri Sep 3 13:24:45 1999 Werner Koch (wk@gnupg.org) - - * Makefile.am: New - - diff --git a/doc/gph/Makefile.am b/doc/gph/Makefile.am deleted file mode 100644 index d36b0013a..000000000 --- a/doc/gph/Makefile.am +++ /dev/null @@ -1,54 +0,0 @@ -# GPH - GNU Privacy Handbook - -PARTS = manual.sgml c1.sgml c2.sgml c3.sgml c4.sgml c5.sgml c6.sgml c7.sgml \ - signatures.fig signatures.jpg.asc - -EXTRA_DIST = $(PARTS) index.html -#BUILT_SOURCES = index.html - -all-local: ./signatures.jpg - -./signatures.jpg: $(srcdir)/signatures.jpg.asc - ../../g10/gpg --yes --dearmor \ - -o ./signatures.jpg $(srcdir)/signatures.jpg.asc - -test -d manual && cp ./signatures.jpg ./manual/signatures.jpg - - -index.html: $(PARTS) - @set -e; \ - for i in $(PARTS); do \ - [ -f $$i ] || cat /dev/null $(srcdir)/$$i >./$$i ; \ - done - db2html manual.sgml - echo '' >index.html - echo '' >>index.html - echo '' >>index.html - -rm -r manual.junk - -rm manual/signatures.jpg -## (cd manual; rm -r stylesheet-images; ls | grep -v distfiles >distfiles) - - -dist-hook: index.html - - -%.dvi: %.sgml - db2dvi $< - -%.ps: %.dvi - dvips -o $@ $< - -%/%.html: %.sgml - db2html $< - - -%.png: %.fig - fig2dev -L png $< $@ - -%.jpg: %.fig - fig2dev -L jpeg $< $@ - -%.eps: %.fig - fig2dev -L ps $< $@ - diff --git a/doc/gph/c1.sgml b/doc/gph/c1.sgml deleted file mode 100644 index 2839f7c62..000000000 --- a/doc/gph/c1.sgml +++ /dev/null @@ -1,627 +0,0 @@ - - - -$Id$ - - - -Getting Started - - - -&Gnupg; is a tool for secure communication. -This chapter is a quick-start guide that covers the core functionality -of &gnupg;. -This includes keypair creation, exchanging and verifying keys, encrypting -and decrypting documents, and making and verifying signatures. -It does not explain in detail the concepts behind public-key cryptography, -encryption, and digital signatures. -This is covered in Chapter . -It also does not explain how to use &gnupg; wisely. -This is covered in Chapters and -. - - - -&Gnupg; uses public-key cryptography so that users may communicate securely. -In a public-key system, each user has a public/private keypair. -A user's private key is kept secret; it need never be revealed. -The public key may be given to anyone with whom the user wants to -communicate. -&Gnupg; uses a somewhat more sophisticated scheme in which a user has -a primary keypair and then zero or more additional subordinate keypairs. -The primary and subordinate keypairs are bundled to facilitate key -management and the bundle can often be considered simply as one keypair. - - - - -Generating a new keypair - - - -The command-line option -is used to create a new primary keypair. - - -alice% gpg --gen-key -gpg (GnuPG) 0.9.4; Copyright (C) 1999 Free Software Foundation, Inc. -This program comes with ABSOLUTELY NO WARRANTY. -This is free software, and you are welcome to redistribute it -under certain conditions. See the file COPYING for details. - -Please select what kind of key you want: - (1) DSA and ElGamal (default) - (2) DSA (sign only) - (4) ElGamal (sign and encrypt) -Your selection? - - - - -&Gnupg; is able to create several different types of keypairs, but a primary -key must be capable of making signatures. -There are therefore only three options. -Option 1 actually creates two keypairs. -A DSA keypair is the primary keypair usable only for making signatures. -An ElGamal subordinate keypair is also created for encryption. -Option 2 is similar but creates only a DSA keypair. -Option 4Option 3 is to generate an ElGamal keypair that is -not usable for making signatures. creates a single ElGamal -keypair usable for both making signatures and performing encryption. -In all cases it is possible to later add additional subkeys for encryption -and signing. -For most users the default option is fine. - - - -You must also choose a key size. -The size of a DSA key must be between 512 and 1024 bits, and an ElGamal -key may be of any size. -&Gnupg;, however, requires that keys be no smaller than 768 bits. -Therefore, if Option 1 was chosen and you choose a keysize larger than -1024 bits, the ElGamal key will have the requested size, but the DSA -key will be 1024 bits. - - -About to generate a new ELG-E keypair. - minimum keysize is 768 bits - default keysize is 1024 bits - highest suggested keysize is 2048 bits -What keysize do you want? (1024) - - -The longer the key the more secure it is against brute-force attacks, -but for almost all purposes the default keysize is adequate since -it would be cheaper to circumvent the encryption than try to break it. -Also, encryption and decryption will be slower as the -key size is increased, and a larger keysize may affect signature length. -Once selected, the keysize can never be changed. - - - -Finally, you must choose an expiration date. -If Option 1 was chosen, the expiration date will be used for both the -ElGamal and DSA keypairs. - - -Please specify how long the key should be valid. - 0 = key does not expire - <n> = key expires in n days - <n>w = key expires in n weeks - <n>m = key expires in n months - <n>y = key expires in n years -Key is valid for? (0) - - -For most users a key that does not expire is adequate. -The expiration time should be chosen with care, however, -since although it is possible to change the expiration date after the key -is created, it may be difficult to communicate a change -to users who have your public key. - - - -You must provide a user ID in addition to the key parameters. -The user ID is used to associate the key being created with a real -person. - - -You need a User-ID to identify your key; the software constructs the user id -from Real Name, Comment and Email Address in this form: - "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>" - -Real name: - - -Only one user ID is created when a key is created, but it is possible -to create additional user IDs if you want to use the key in two or -more contexts, ⪚, as an employee at work and a political activist -on the side. -A user ID should be created carefully since it cannot be edited after -it is created. - - - -&Gnupg; needs a passphrase to protect the primary and subordinate -private keys that you keep in your possession. - - -You need a Passphrase to protect your private key. - -Enter passphrase: - - -There is no limit on the length of a passphrase, and it should be -carefully chosen. -From the perspective of security, the passphrase to unlock the private -key is one of the weakest points in &gnupg; (and other public-key -encryption systems as well) since it is the only protection you -have if another individual gets your private key. -Ideally, the passphrase should not use words from a dictionary and -should mix the case of alphabetic characters as well as use -non-alphabetic characters. -A good passphrase is crucial to the secure use of &gnupg;. - - - - -Generating a revocation certificate - - - -After your keypair is created you should immediately generate a revocation -certificate for the primary public key using the option -. -If you forget your passphrase or if your private key is compromised -or lost, this revocation certificate may be published to notify others -that the public key should no longer be used. -A revoked public key can still be used to verify signatures made -by you in the past, but it cannot be used to encrypt future messages -to you. -It also does not affect your ability to decrypt messages sent to -you in the past if you still do have access to the private key. - - -alice% gpg --output revoke.asc --gen-revoke mykey -[...] - - -The argument mykey must be a key -specifier, -either the key ID of your primary keypair or any part of a user ID -that identifies your keypair. -The generated certificate will be left in the file -revoke.asc. -If the option is -omitted, the result will be placed on standard output. -Since the certificate is short, you may wish to print a hardcopy of -the certificate to store somewhere safe such as your safe deposit box. -The certificate should not be stored where others can access it since -anybody can publish the revocation certificate and render the -corresponding public key useless. - - - - - - -Exchanging keys - - - -To communicate with others you must exchange public keys. -To list the keys on your public keyring use the command-line -option . - - - -alice% gpg --list-keys -/users/alice/.gnupg/pubring.gpg ---------------------------------------- -pub 1024D/BB7576AC 1999-06-04 Alice (Judge) <alice@cyb.org> -sub 1024g/78E9A8FA 1999-06-04 - - - - -Exporting a public key - - - -To send your public key to a correspondent you must first export it. -The command-line option -is used to do this. -It takes an additional argument identifying the public key to export. -As with the option, either the key ID or any part of -the user ID may be used to identify the key to export. - - - -alice% gpg --output alice.gpg --export alice@cyb.org - - - -The key is exported in a binary format, but this can be inconvenient -when the key is to be sent though email or published on a web page. -&Gnupg; therefore supports a command-line option - -Many -command-line options that are frequently used can also be set in a -configuration file. - - -that that -causes output to be generated in an ASCII-armored format similar to -uuencoded documents. -In general, any output from &gnupg;, ⪚, keys, encrypted documents, and -signatures, can be ASCII-armored by adding the option. - - - -alice% gpg --armor --export alice@cyb.org ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v0.9.7 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -[...] ------END PGP PUBLIC KEY BLOCK----- - - - - - -Importing a public key - - - -A public key may be added to your public keyring with the - option. - - - -alice% gpg --import blake.gpg -gpg: key 9E98BC16: public key imported -gpg: Total number processed: 1 -gpg: imported: 1 -alice% gpg --list-keys -/users/alice/.gnupg/pubring.gpg ---------------------------------------- -pub 1024D/BB7576AC 1999-06-04 Alice (Judge) <alice@cyb.org> -sub 1024g/78E9A8FA 1999-06-04 - -pub 1024D/9E98BC16 1999-06-04 Blake (Executioner) <blake@cyb.org> -sub 1024g/5C8CBD41 1999-06-04 - - - -Once a key is imported it should be validated. -&Gnupg; uses a powerful and flexible trust model that does not require -you to personally validate each key you import. -Some keys may need to be personally validated, however. -A key is validated by verifying the key's fingerprint and then signing -the key to certify it as a valid key. -A key's fingerprint can be quickly viewed with the - -command-line option, but in order to certify the key you must edit it. - - -alice% gpg --edit-key blake@cyb.org - -pub 1024D/9E98BC16 created: 1999-06-04 expires: never trust: -/q -sub 1024g/5C8CBD41 created: 1999-06-04 expires: never -(1) Blake (Executioner) <blake@cyb.org> - -Command> fpr -pub 1024D/9E98BC16 1999-06-04 Blake (Executioner) <blake@cyb.org> - Fingerprint: 268F 448F CCD7 AF34 183E 52D8 9BDE 1A08 9E98 BC16 - - -Key verification is a weak point in public-key cryptography, so you -must be sure that the fingerprint is correct. -The fingerprint displayed should be checked with the key's owner. -This may be done in person or over the phone or through any other means -as long as you can guarantee that you are communicating with the key's -true owner. -Once verified you may sign the key to validate it. - - - -Command> sign - -pub 1024D/9E98BC16 created: 1999-06-04 expires: never trust: -/q - Fingerprint: 268F 448F CCD7 AF34 183E 52D8 9BDE 1A08 9E98 BC16 - - Blake (Executioner) <blake@cyb.org> - -Are you really sure that you want to sign this key -with your key: "Alice (Judge) <alice@cyb.org>" - -Really sign? - - - -Once signed you can check the key to list the signatures on it and -see the signature that you have added. -Every user ID on the key will have one or more self-signatures as well -as a signature for each user that has validated the key. - - - -Command> check -uid Blake (Executioner) <blake@cyb.org> -sig! 9E98BC16 1999-06-04 [self-signature] -sig! BB7576AC 1999-06-04 Alice (Judge) <alice@cyb.org> - - - - - - -Encrypting and decrypting documents - - - -To encrypt a document the option - is used. -You must have the public keys of the intended recipients. -The software expects the name of the document to encrypt as input or, if -omitted, on standard input. -The encrypted result is placed on standard output or as specified using -the option . -The document is compressed for additional security in addition to -encrypting it. - - -alice% gpg --output doc.gpg --encrypt --recipient blake@cyb.org doc - - -The option -is used once for each recipient and takes an extra argument specifying -the public key to which the document should be encrypted. -The encrypted document can only be decrypted by someone with a private -key that complements one of the recipients' public keys. -In particular, you cannot decrypt a document encrypted by you unless -you included your own public key in the recipient list. - - - -To decrypt a message the option - is used. -You need the private key to which the message was encrypted. -Similar to the encryption process, the document to decrypt is -input, and the decrypted result is output. - - - -blake% gpg --output doc --decrypt doc.gpg - -You need a passphrase to unlock the secret key for -user: "Blake (Executioner) <blake@cyb.org>" -1024-bit ELG-E key, ID 5C8CBD41, created 1999-06-04 (main key ID 9E98BC16) - -Enter passphrase: - - - -Documents may also be encrypted without using public-key cryptography. -Instead, only a symmetric cipher is used to encrypt the document. -The key used to drive the symmetric cipher is derived from a passphrase -supplied when the document is encrypted, and for good security, it -should not be the same passphrase that you use to protect your private key. -Symmetric encryption is useful for securing documents when the -passphrase does not need to be communicated to others. -A document can be encrypted with a symmetric cipher by using the - option. - - - -alice% gpg --output doc.gpg --symmetric doc -Enter passphrase: - - - - - -Making and verifying signatures - - - -A digital signature certifies and timestamps a document. -If the document is subsequently modified in any way, a verification -of the signature will fail. -A digital signature can serve the same purpose as a hand-written signature -with the additional benefit of being tamper-resistant. -The &gnupg; source distribution, for example, is signed so that users can -verify that the source code has not been modified since it was packaged. - - - -Creating and verifying signatures uses the public/private keypair -in an operation different from encryption and decryption. -A signature is created using the private key of the signer. -The signature is verified using the corresponding public key. -A consequence is that it is difficult to deny that you made a digital -signature since that would imply your private key had been compromised. - - - -The command-line option is -used to make a digital signature. -The document to sign is input, and the signed document is output. - - -alice% gpg --output doc.sig --sign doc - -You need a passphrase to unlock the private key for -user: "Alice (Judge) <alice@cyb.org>" -1024-bit DSA key, ID BB7576AC, created 1999-06-04 - -Enter passphrase: - - -The document is compressed before signed, and the output is in binary -format. - - - -Given a signed document, you can either check the signature or -check the signature and recover the original document. -To check the signature use the - option. -To verify the signature and extract the document use the - -option. -The signed document to verify and recover is input and the recovered -document is output. - - - -blake% gpg --output doc --decrypt doc.sig -gpg: Signature made Fri Jun 4 12:02:38 1999 CDT using DSA key ID BB7576AC -gpg: Good signature from "Alice (Judge) <alice@cyb.org>" - - - - -Clearsigned documents - - - -A common use of digital signatures is to sign usenet postings or -email messages. -In such situations it is undesirable to compress the document while -signing it. -The option - -causes the document to be wrapped in an ASCII-armored signature but -otherwise does not modify the document. - - - -alice% gpg --clearsign doc - -You need a passphrase to unlock the secret key for -user: "Alice (Judge) <alice@cyb.org>" -1024-bit DSA key, ID BB7576AC, created 1999-06-04 - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -[...] ------BEGIN PGP SIGNATURE----- -Version: GnuPG v0.9.7 (GNU/Linux) -Comment: For info see http://www.gnupg.org - -iEYEARECAAYFAjdYCQoACgkQJ9S6ULt1dqz6IwCfQ7wP6i/i8HhbcOSKF4ELyQB1 -oCoAoOuqpRqEzr4kOkQqHRLE/b8/Rw2k -=y6kj ------END PGP SIGNATURE----- - - - - - -Detached signatures - - - -A signed document has limited usefulness. -Other users must recover the original document from the signed -version, and even with clearsigned documents, the signed document -must be edited to recover the original. -Therefore, there is a third method for signing a document that -creates a detached signature. -A detached signature is created using the - -option. - - - -alice% gpg --output doc.sig --detach-sig doc - -You need a passphrase to unlock the secret key for -user: "Alice (Judge) <alice@cyb.org>" -1024-bit DSA key, ID BB7576AC, created 1999-06-04 - -Enter passphrase: - - - -Both the document and detached signature are needed to verify -the signature. -The option can be to check the -signature. - - - -blake% gpg --verify doc.sig doc -gpg: Signature made Fri Jun 4 12:38:46 1999 CDT using DSA key ID BB7576AC -gpg: Good signature from "Alice (Judge) <alice@cyb.org>" - - - - - - - - - diff --git a/doc/gph/c2.sgml b/doc/gph/c2.sgml deleted file mode 100644 index b045ed4ee..000000000 --- a/doc/gph/c2.sgml +++ /dev/null @@ -1,345 +0,0 @@ - - - -$Id$ - - - -Concepts - - - -&Gnupg; makes uses of several cryptographic concepts including -symmetric ciphers, -public-key ciphers, and -one-way hashing. -You can make basic use &gnupg; without fully understanding these concepts, -but in order to use it wisely some understanding of them is necessary. - - - -This chapter introduces the basic cryptographic concepts used in GnuPG. -Other books cover these topics in much more detail. -A good book with which to pursue further study is -Bruce -Schneier's -"Applied -Cryptography". - - - - -Symmetric ciphers - - - -A symmetric cipher is a cipher that uses the same key for both encryption -and decryption. -Two parties communicating using a symmetric cipher must agree on the -key beforehand. -Once they agree, the sender encrypts a message using the key, sends it -to the receiver, and the receiver decrypts the message using the key. -As an example, the German Enigma is a symmetric cipher, and daily keys -were distributed as code books. -Each day, a sending or receiving radio operator would consult his copy -of the code book to find the day's key. -Radio traffic for that day was then encrypted and decrypted using the -day's key. -Modern examples of symmetric ciphers include 3DES, Blowfish, and IDEA. - - - -A good cipher puts all the security in the key and none in the algorithm. -In other words, it should be no help to an attacker if he knows which -cipher is being used. -Only if he obtains the key would knowledge of the algorithm be needed. -The ciphers used in &gnupg; have this property. - - - -Since all the security is in the key, then it is important that it be -very difficult to guess the key. -In other words, the set of possible keys, &ie;, the key -space, needs -to be large. -While at Los Alamos, Richard Feynman was famous for his ability to -crack safes. -To encourage the mystique he even carried around a set of tools -including an old stethoscope. -In reality, he used a variety of tricks to reduce the number of -combinations he had to try to a small number and then simply guessed -until he found the right combination. -In other words, he reduced the size of the key space. - - - -Britain used machines to guess keys during World War 2. -The German Enigma had a very large key space, but the British built -speciailzed computing engines, the Bombes, to mechanically try -keys until the day's key was found. -This meant that sometimes they found the day's key within hours of -the new key's use, but it also meant that on some days they never -did find the right key. -The Bombes were not general-purpose computers but were precursors -to modern-day computers. - - - -Today, computers can guess keys very quickly, and this is why key -size is important in modern cryptosystems. -The cipher DES uses a 56-bit key, which means that there are - -256 possible keys. - -256 is 72,057,594,037,927,936 keys. -This is a lot of keys, but a general-purpose computer can check the -entire key space in a matter of days. -A specialized computer can check it in hours. -On the other hand, more recently designed ciphers such as 3DES, -Blowfish, and IDEA - -all use 128-bit keys, which means there are 2128 -possible keys. -This is many, many more keys, and even if all the computers on the -planet cooperated, it could still take more time than the age of -the universe to find the key. - - - - - -Public-key ciphers - - - -The primary problem with symmetric ciphers is not their security but -with key exchange. -Once the sender and receiver have exchanged keys, that key can be -used to securely communicate, but what secure communication channel -was used to communicate the key itself? -In particular, it would probably be much easier for an attacker to work -to intercept the key than it is to try all the keys in the key space. -Another problem is the number of keys needed. - -If there are n people who need to communicate, then - -n(n-1)/2 keys -are needed for each pair of people to communicate privately. -This may be ok for a small number of people but quickly becomes unwieldly -for large groups of people. - - - -Public-key ciphers were invented to avoid the key-exchange problem -entirely. -A public-key cipher uses a pair of keys for sending messages. -The two keys belong to the person receiving the message. -One key is a public key and may be given to anybody. -The other key is a private key and is kept -secret by the owner. -A sender encrypts a message using the public key and once encrypted, -only the private key may be used to decrypt it. - - - -This protocol solves the key-exchange problem inherent with symmetric -ciphers. -There is no need for the sender and receiver to agree -upon a key. -All that is required is that some time before secret communication the -sender gets a copy of the receiver's public key. -Furthermore, the one public key can be used by anybody wishing to -communicate with the receiver. - -So only n keypairs are needed for n -people to communicate secretly -with one another, - - - -Public-key ciphers are based on one-way trapdoor functions. -A one-way function is a function that is easy to compute, -but the inverse is hard to compute. -For example, it is easy to multiply two prime numbers together to get -a composite, but it is difficult to factor a composite into its prime -components.a -A one-way trapdoor function is similar, but it has a trapdoor. -That is, if some piece of information is known, it becomes easy -to compute the inverse. -For example, if you have a number made of two prime factors, then knowing -one of the factors makes it easy to compute the second. -Given a public-key cipher based on prime factorization, the public -key contains a composite number made from two large prime factors, and -the encryption algorithm uses that composite to encrypt the -message. -The algorithm to decrypt the message requires knowing the prime factors, -so decryption is easy if you have the private key containing one of the -factors but extremely difficult if you do not have it. - - - -As with good symmetric ciphers, with a good public-key cipher all of the -security rests with the key. -Therefore, key size is a measure of the system's security, but -one cannot compare the size of a symmetric cipher key and a public-key -cipher key as a measure of their relative security. -In a brute-force attack on a symmetric cipher with a key size of 80 bits, - -the attacker must enumerate up to 281-1 keys to -find the right key. -In a brute-force attack on a public-key cipher with a key size of 512 bits, -the attacker must factor a composite number encoded in 512 bits (up to -155 decimal digits). -The workload for the attacker is fundamentally different depending on -the cipher he is attacking. -While 128 bits is sufficient for symmetric ciphers, given today's factoring -technology public keys with 1024 bits are recommended for most purposes. - - - - - -Hybrid ciphers - - - -Public-key ciphers are no panacea. -Many symmetric ciphers are stronger from a security standpoint, -and public-key encryption and decryption are more expensive than the -corresponding operations in symmetric systems. -Public-key ciphers are nevertheless an effective tool for distributing -symmetric cipher keys, and that is how they are used in hybrid cipher -systems. - - - -A hybrid cipher uses both a symmetric cipher and a public-key cipher. -It works by using a public-key cipher to share a key for the symmetric -cipher. -The actual message being sent is then encrypted using the key and sent -to the recipient. -Since symmetric key sharing is secure, the symmetric key used is different -for each message sent. -Hence it is sometimes called a session key. - - - -Both PGP and &gnupg; use hybrid ciphers. -The session key, encrypted using the public-key cipher, and the message -being sent, encrypted with the symmetric cipher, are automatically -combined in one package. -The recipient uses his private-key to decrypt the session key and the -session key is then used to decrypt the message. - - - -A hybrid cipher is no stronger than the public-key cipher or symmetric -cipher it uses, whichever is weaker. -In PGP and &gnupg;, the public-key cipher is probably the weaker of -the pair. -Fortunately, however, if an attacker could decrypt a session key it -would only be useful for reading the one message encrypted with that -session key. -The attacker would have to start over and decrypt another session -key in order to read any other message. - - - - - -Digital signatures - - - -A hash function is a many-to-one function that maps its input to a -value in a finite set. -Typically this set is a range of natural numbers. - -A simple ehash function is f(x) = 0 -for all integers x. -A more interesting hash function is -f(x) = x -mod 37, which -maps x to the remainder of dividing x by 37. - - - -A document's digital signature is the result of applying a hash -function to the document. -To be useful, however, the hash function needs to satisfy two -important properties. -First, it should be hard to find two documents that hash to the -same value. -Second, given a hash value it should be hard to recover the document -that produced that value. - - - -Some public-key ciphers -The cipher must have the property that the actual public key or private -key could be used by the encryption algorithm as the public key. -RSA is an example of such an algorithm while ElGamal is not an example. - - could be used to sign documents. -The signer encrypts the document with his private key. -Anybody wishing to check the signature and see the document simply -uses the signer's public key to decrypt the document. -This algorithm does satisfy the two properties needed from a good hash -function, but in practice, this algorithm is too slow to be useful. - - - -An alternative is to use hash functions designed to satisfy these -two important properties. -SHA and MD5 are examples of such algorithms. -Using such an algorithm, a document is signed by hashing it, and -the hash value is the signature. -Another person can check the signature by also hashing their copy of the -document and comparing the hash value they get with the hash value of -the original document. -If they match, it is almost certain that the documents are identical. - - - -Of course, the problem now is using a hash function for digital -signatures without permitting an attacker to interfere with signature -checking. -If the document and signature are sent unencrypted, an attacker could -modify the document and generate a corresponding signature without the -recipient's knowledge. -If only the document is encrypted, an attacker could tamper with the -signature and cause a signature check to fail. -A third option is to use a hybrid public-key encryption to encrypt both -the signature and document. -The signer uses his private key, and anybody can use his public key -to check the signature and document. -This sounds good but is actually nonsense. -If this algorithm truly secured the document it would also -secure it from tampering and there would be no need for the signature. -The more serious problem, however, is that this does not protect either -the signature or document from tampering. -With this algorithm, only the session key for the symmetric cipher -is encrypted using the signer's private key. -Anybody can use the public key to recover the session key. -Therefore, it is straightforward for an attacker to recover the session -key and use it to encrypt substitute documents and signatures to send -to others in the sender's name. - - - -An algorithm that does work is to use a public key algorithm to -encrypt only the signature. -In particular, the hash value is encrypted using the signer's private -key, and anbody can check the signature using the public key. -The signed document can be sent using any other encryption algorithm -including none if it is a public document. -If the document is modified the signature check will fail, but this -is precisely what the signature check is supposed to catch. -The Digital Signature Standard (DSA) is a public key signature -algorithm that works as just described. -DSA is the primary signing algorithm used in &Gnupg;. - - - - - diff --git a/doc/gph/c3.sgml b/doc/gph/c3.sgml deleted file mode 100644 index 541cf6c9d..000000000 --- a/doc/gph/c3.sgml +++ /dev/null @@ -1,885 +0,0 @@ - - - -$Id$ - - - -Key Management - - - -Key tampering is a major security weakness with public-key cryptography. -An eavesdropper may tamper with a user's keyrings or forge a -user's public key and post it for others to download and use. -For example, suppose Chloe wants to monitor the messages that Alice -sends to Blake. -She could mount what is called a man in the -middle attack. -In this attack, Chloe creates a new public/private keypair. -She replaces Alice's copy of Blake's public key with the new public key. -She then intercepts the messages that Alice sends to Blake. -For each intercept, she decrypts it using the new private key, reencrypts -it using Blake's true public key, and forwards the reencrypted -message to Blake. -All messages sent from Alice to Blake can now be read by Chloe. - - - -Good key management is crucial in order to ensure not just the integrity -of your keyrings but the integrity of other users' keyrings as well. -The core of key management in &gnupg; is the notion of signing keys. -Key signing has two main purposes: it permits you to detect tampering -on your keyring, and it allows you to certify that a key truly belongs -to the person named by a user ID on the key. -Key signatures are also used in a scheme known as the web of -trust to extend certification to keys not directly signed by you -but signed by others you trust. -Responsible users who practice good key management can defeat key -tampering as a practical attack on secure communication with &gnupg;. - - - - -Managing your own keypair - - - -A keypair has a public key and a private key. -A public key consists of -the public portion of the master signing key, -the public portions of the subordinate signing and encryption subkeys, and -a set of user IDs used to associate the public key with a real person. -Each piece has data about itself. -For a key, this data includes its ID, when it was created, when it -will expire, etc. -For a user ID, this data includes the name of the real person it identifies, -an optional comment, and an email address. -The structure of the private key is similar, except that it contains only -the private portions of the keys, and there is no user ID information. - - - -The command-line option - -may be used to view a keypair. -For example, - - -chloe% gpg --edit-key chloe@cyb.org -Secret key is available. - -pub 1024D/26B6AAE1 created: 1999-06-15 expires: never trust: -/u -sub 2048g/0CF8CB7A created: 1999-06-15 expires: never -sub 1792G/08224617 created: 1999-06-15 expires: 2002-06-14 -sub 960D/B1F423E7 created: 1999-06-15 expires: 2002-06-14 -(1) Chloe (Jester) <chloe@cyb.org> -(2) Chloe (Plebian) <chloe@tel.net> -Command> - - -The public key is displayed along with an indication of whether -or not the private key is available. -Information about each component of the public key is then listed. -The first column indicates the type of the key. -The keyword pub identifies the public master signing key, -and the keyword sub identifies a public subordinate key. -The second column indicates the key's bit length, type, and ID. -The type is D for a DSA key, g for an -encryption-only -ElGamal key, and G for an ElGamal key that may be used for -both encryption and signing. -The creation date and expiration date are given in columns three and four. -The user IDs are listed following the keys. - - - -More information about the key can be obtained with interactive commands. -The command toggle -switches between the public and private -components of a keypair if indeed both components are available. - - -Command> toggle - -sec 1024D/26B6AAE1 created: 1999-06-15 expires: never -sbb 2048g/0CF8CB7A created: 1999-06-15 expires: never -sbb 1792G/08224617 created: 1999-06-15 expires: 2002-06-14 -sbb 960D/B1F423E7 created: 1999-06-15 expires: 2002-06-14 -(1) Chloe (Jester) <chloe@cyb.org> -(2) Chloe (Plebian) <chloe@tel.net> - - -The information provided is similar to the listing for the public-key -component. -The keyword sec identifies the private master signing key, -and the keyword sbb identifies the private subordinates keys. -The user IDs from the public key are also listed for convenience. - - - - -Key integrity - - - -When you distribute your public key, you are distributing the public -components of your master and subordinate keys as well as the user IDs. -Distributing this material alone, however, is a security risk since -it is possible for an attacker to tamper with the key. -The public key can be modified by adding or substituting keys, or by -adding or changing user IDs. -By tampering with a user ID, the attacker could change the user ID's email -address to have email redirected to himself. -By changing one of the encryption keys, the attacker would -also be able to decrypt the messages redirected to him. - - - -Using digital signatures is a solution to this problem. -When data is signed by a private key, the corresponding public key -is bound to the signed data. -In other words, only the corresponding public key can be used to -verify the signature and ensure that the data has not been modified. -A public key can be protected from tampering by using its corresponding -private master key to sign the public key components and user IDs, thus -binding the components to the public master key. -Signing public key components with the corresponding private master -signing key is called self-signing, and a public key that has -self-signed user IDs bound to it is called a certificate. - - - - - -As an example, Chloe has two user IDs and three subkeys. -The signatures on the user IDs can be checked with the command -check from the key edit menu. - - -chloe% gpg --edit-key chloe -Secret key is available. - -pub 1024D/26B6AAE1 created: 1999-06-15 expires: never trust: -/u -sub 2048g/0CF8CB7A created: 1999-06-15 expires: never -sub 1792G/08224617 created: 1999-06-15 expires: 2002-06-14 -sub 960D/B1F423E7 created: 1999-06-15 expires: 2002-06-14 -(1) Chloe (Jester) <chloe@cyb.org> -(2) Chloe (Plebian) <chloe@tel.net> - -Command> check -uid Chloe (Jester) <chloe@cyb.org> -sig! 26B6AAE1 1999-06-15 [self-signature] -uid Chloe (Plebian) <chloe@tel.net> -sig! 26B6AAE1 1999-06-15 [self-signature] - - -As expected, the signing key for each signature is the master signing -key with key ID 0x26B6AAE1. -The self-signatures on the subkeys are present in the public key, but -they are not shown by the &gnupg; interface. - - - - - -Adding and deleting key components - - - -Both new subkeys and new user IDs may be added to your keypair after -it has been created. -A user ID is added using the command -adduid. -You are prompted for a real name, email address, and comment just -as when you create an initial keypair. -A subkey is added using the command -addkey. -The interface is similar to the interface used when creating an initial -keypair. -The subkey may be a DSA signing key, and encrypt-only ElGamal -key, or a sign-and-encrypt ElGamal key. -When a subkey or user ID is generated it is self-signed using your -master signing key, which is why you must supply your passphrase -when the key is generated. - - - -Additional user IDs are useful when you need multiple identities. -For example, you may have an identity for your job and an identity -for your work as a political activist. -Coworkers will know you by your work user ID. -Coactivists will know you by your activist user ID. -Since those groups of people may not overlap, though, each group -may not trust the other user ID. -Both user IDs are therefore necessary. - - - -Additional subkeys are also useful. -The user IDs associated with your public master key are validated by -the people with whom you -communicate, and changing the master key therefore requires recertification. -This may be difficult and time consuming if you communicate with -many people. -On the other hand, it is good to periodically change encryption subkeys. -If a key is broken, all the data encrypted with that key will be -vulnerable. -By changing keys, however, only the data encrypted with the one broken -key will be revealed. - - - -Subkeys and user IDs may also be deleted. -To delete a subkey or user ID you must first select it using the -key or -uid commands respectively. -These commands are toggles. -For example, the command key 2 -selects the second subkey, -and invoking key 2 again -deselects it. -If no extra argument is given, all subkeys or user IDs are deselected. -Once the user IDs to be deleted are selected, the command -deluid -actually deletes the user IDs from your key. -Similarly, the command delkey -deletes all selected subkeys from both your public and private keys. - - - -For local keyring management, deleting key components is a good way -to trim other people's public keys of unnecessary material. -Deleting user IDs and subkeys on your own key, however, is not always -wise since it complicates key distribution. -By default, when a user imports your updated public key it will be merged -with the old copy of your public key on his ring if it exists. -The components from both keys are combined in the merge, and this -effectively restores any components you deleted. -To properly update the key, the user must first delete the old version -of your key and then import the new version. -This puts an extra burden on the people with whom you communicate. -Furthermore, if you send your key to a keyserver, the merge will -happen regardless, and anybody who downloads your key from a keyserver -will never see your key with components deleted. -Consequently, for updating your own key it is better to revoke key -components instead of deleting them. - - - - - -Revoking key components - - - -To revoke a subkey it must be selected. -Once selected it may be revoked with the -revkey command. -The key is revoked by adding a revocation self-signature to the key. -Unlike the command-line option , the effect of -revoking a subkey is immediate. - - - -Command> revkey -Do you really want to revoke this key? y - -You need a passphrase to unlock the secret key for -user: "Chloe (Jester) <chloe@cyb.org>" -1024-bit DSA key, ID B87DBA93, created 1999-06-28 - - -pub 1024D/B87DBA93 created: 1999-06-28 expires: never trust: -/u -sub 2048g/B7934539 created: 1999-06-28 expires: never -sub 1792G/4E3160AD created: 1999-06-29 expires: 2000-06-28 -rev! subkey has been revoked: 1999-06-29 -sub 960D/E1F56448 created: 1999-06-29 expires: 2000-06-28 -(1) Chloe (Jester) <chloe@cyb.org> -(2) Chloe (Plebian) <chloe@tel.net> - - - -A user ID is revoked differently. -Normally, a user ID collects signatures that attest that the user ID -describes the person who actually owns the associated key. -In theory, a user ID describes a person forever, since that person will -never change. -In practice, though, elements of the user ID such as the email address -and comment may change over time, thus invalidating the user ID. - - - -The OpenPGP -First reference to OpenPGP -specification does not support user ID revocation, but -a user ID can effectively be revoked by revoking the self-signature -on the user ID. -For the security reasons described -previously, -correspondents will not trust a user ID with no valid self-signature. - - - -A signature is revoked by using the command -revsig. -Since you may have signed any number of user IDs, the user interface -prompts you to decide for each signature whether or not to revoke it. - - - -Command> revsig -You have signed these user IDs: - Chloe (Jester) <chloe@cyb.org> - signed by B87DBA93 at 1999-06-28 - Chloe (Plebian) <chloe@tel.net> - signed by B87DBA93 at 1999-06-28 -user ID: "Chloe (Jester) <chloe@cyb.org>" -signed with your key B87DBA93 at 1999-06-28 -Create a revocation certificate for this signature? (y/N)n -user ID: "Chloe (Plebian) <chloe@tel.net>" -signed with your key B87DBA93 at 1999-06-28 -Create a revocation certificate for this signature? (y/N)y -You are about to revoke these signatures: - Chloe (Plebian) <chloe@tel.net> - signed by B87DBA93 at 1999-06-28 -Really create the revocation certificates? (y/N)y - -You need a passphrase to unlock the secret key for -user: "Chloe (Jester) <chloe@cyb.org>" -1024-bit DSA key, ID B87DBA93, created 1999-06-28 - - -pub 1024D/B87DBA93 created: 1999-06-28 expires: never trust: -/u -sub 2048g/B7934539 created: 1999-06-28 expires: never -sub 1792G/4E3160AD created: 1999-06-29 expires: 2000-06-28 -rev! subkey has been revoked: 1999-06-29 -sub 960D/E1F56448 created: 1999-06-29 expires: 2000-06-28 -(1) Chloe (Jester) <chloe@cyb.org> -(2) Chloe (Plebian) <chloe@tel.net> - - - -A revoked user ID is indicated by the revocation signature on -the ID when the signatures on the key's user IDs are listed. - - - -Command> check -uid Chloe (Jester) <chloe@cyb.org> -sig! B87DBA93 1999-06-28 [self-signature] -uid Chloe (Plebian) <chloe@tel.net> -rev! B87DBA93 1999-06-29 [revocation] -sig! B87DBA93 1999-06-28 [self-signature] - - - -Revoking both subkeys and self-signatures on user IDs adds revocation -self-signatures to the key. -Since signatures are being added and no material is deleted, a -revocation will always be visible to others when your updated public -key is distributed and merged with older copies of it. -Revocation therefore guarantees that everybody has a consistent -copy of your public key. - - - - - -Updating a key's expiration time - - - -The expiration time of a key may be updated with the command -expire from the key edit menu. -If no key is selected the expiration time of the primary key -is updated. -Otherwise the expiration time of the selected subordinate key -is updated. - - - -A key's expiration time is associated with the key's self-signature. -The expiration time is updated by deleting the old self-signature -and adding a new self-signature. -Since correspondents will not have deleted the old self-signature, they -will see an additional self-signature on the key when they update -their copy of your key. -The latest self-signature takes precedence, however, so all correspondents -will unambiguously know the expiration times of your keys. - - - - - - -Validating other keys on your public keyring - - - -In Chapter a procedure was given to validate your -correspondents' public keys: a correspondent's key is validated by -personally checking his key's fingerprint and then signing his public -key with your private key. -By personally checking the fingerprint you can be sure that the -key really does belong to him, and since you have signed they key, you -can be sure to detect any tampering with it in the future. -Unfortunately, this procedure is awkward when either you must validate -a large number of keys or communicate with people whom you do not -know personally. - - - -&Gnupg; addresses this problem with a mechanism popularly known -as the web of trust. -In the web of trust model, responsibility for validating public -keys is delegated to people you trust. -For example, suppose - - - -Alice has signed Blake's key, and - - - - -Blake has signed Chloe's key and Dharma's key. - - - - -If Alice trusts Blake to properly validate keys that he signs, then -Alice can infer that Chloe's and Dharma's keys are valid without -having to personally check them. -She simply uses her validated copy of Blake's public key to -check that Blake's signatures on Chloe's and Dharma's are good. -In general, assuming that Alice fully trusts everybody to properly -validate keys they sign, then any key signed by a valid key is also -considered valid. -The root is Alice's key, which is axiomatically assumed to be valid. - - - - -Trust in a key's owner - - - -In practice trust is subjective. -For example, Blake's key is valid to Alice since she signed it, but she -may not trust Blake to properly validate keys that he signs. -In that case, she would not take Chloe's and Dharma's key as valid -based on Blake's signatures alone. -The web of trust model accounts for this by associating with each -public key on your keyring an indication of how much you trust the -key's owner. -There are four trust levels. - - - - -unknown - - - -Nothing is known about the owner's judgement in key signing. -Keys on your public keyring that you do not own initially have -this trust level. - - - - - -none - - - -The owner is known to improperly sign other keys. - - - - - -marginal - - - -The owner understands the implications of key signing and -properly validates keys before signing them. - - - - - -full - - - -The owner has an excellent understanding of key signing, -and his signature on a key would be as good as your own. - - - - - -A key's trust level is something that you alone assign to the -key, and it is considered private information. -It is not packaged with the key when it is exported; it is even -stored separately from your keyrings in a separate database. - - - -The &gnupg; key editor may be used to adjust your trust in a key's owner. -The command is trust. -In this example Alice edits her trust in Blake and then updates -the trust database to recompute which keys are valid based on her new -trust in Blake. - - -alice% gpg --edit-key blake - -pub 1024D/8B927C8A created: 1999-07-02 expires: never trust: q/f -sub 1024g/C19EA233 created: 1999-07-02 expires: never -(1) Blake (Executioner) <blake@cyb.org> - -Command> trust -pub 1024D/8B927C8A created: 1999-07-02 expires: never trust: q/f -sub 1024g/C19EA233 created: 1999-07-02 expires: never -(1) Blake (Executioner) <blake@cyb.org> - -Please decide how far you trust this user to correctly -verify other users' keys (by looking at passports, -checking fingerprints from different sources...)? - - 1 = Don't know - 2 = I do NOT trust - 3 = I trust marginally - 4 = I trust fully - s = please show me more information - m = back to the main menu - -Your decision? 3 - -pub 1024D/8B927C8A created: 1999-07-02 expires: never trust: m/f -sub 1024g/C19EA233 created: 1999-07-02 expires: never -(1) Blake (Executioner) <blake@cyb.org> - -Command> quit -[...] - - -Trust in the key's owner and the key's validity are indicated to the -right when the key is displayed. -Trust in the owner is displayed first and the key's validity is - -second - -&Gnupg; overloads the word "trust" by using it to mean -trust in an owner and trust in a key. -This can be confusing. -Sometimes trust in an owner is referred to as -owner-trust to -distinguish it from trust in a key. - -Throughout this manual, however, "trust" is used to -mean trust in a key's - -owner, and "validity" is used to mean trust that a key -belongs to the human associated with the key ID. - -. -The four trust/validity levels are abbreviated: unknown (q), -none (n), marginal (m), and -full (f). -In this case, Blake's key is fully valid since Alice signed it herself. -She initially has an unknown trust in Blake to properly sign other keys -but decides to trust him marginally. - - - - - -Using trust to validate keys - - - -The web of trust allows a more elaborate algorithm to be used to -validate a key. -Formerly, a key was considered valid only if you signed it personally. - -A more flexible algorithm can now be used: a key K is considered valid -if it meets two conditions: - - - -it is signed by enough valid keys, meaning - - - -you have signed it personally, - - - - -it has been signed by one fully trusted key, or - - - - -it has been signed by three marginally trusted keys; and - - - - - - - - -the path of signed keys leading from K back -to your own key is five steps or shorter. - - - - -The path length, number of marginally trusted keys required, and number -of fully trusted keys required may be adjusted. -The numbers given above are the default values used by &gnupg;. - - - - shows a web of trust rooted at Alice. -The graph illustrates who has signed who's keys. -The table shows which keys Alice considers valid based on her -trust in the other members of the web. -Potential bug: on command -line seems to be ignored when combined with . -Value is taken correctly if put in options file, however. -This example assumes that two marginally-trusted keys or one -fully-trusted key is needed to validate another key. -The maximum path length is three. - - - -When computing valid keys in the example, Blake and Dharma's are -always considered fully valid since they were signed directly -by Alice. -The validity of the other keys depends on trust. -In the first case, Dharma is trusted fully, which implies -that Chloe's and Francis's keys will be considered valid. -In the second example, Blake and Dharma are trusted marginally. -Since two marginally trusted keys are needed to fully validate a -key, Chloe's key will be considered fully valid, but Francis's -key will be considered only marginally valid. -In the case where Chloe and Dharma are marginally trusted, -Chloe's key will be marginally valid since Dharma's key is -fully valid. -Francis's key, however, will also be considered marginally -valid since only a fully valid key can be used to validate -other keys, and Dharma's key is the only fully valid key -that has been used to sign Francis's key. -When marginal trust in Blake is added, Chloe's key becomes -fully valid and can then be used to fully validate Francis's -key and marginally validate Elena's key. -Lastly, when Blake, Chloe, and Elena are fully trusted, this is -still insufficient to validate Geoff's key since the maximum -certification path is three, but the path length from Geoff -back to Alice is four. - - - -The web of trust model is a flexible approach to the problem of safe -public key exchange. -It permits you to tune &gnupg; to reflect how you use it. -At one extreme you may insist on multiple, short paths from your - -key to another key K in order to trust it. -On the other hand, you may be satisfied with longer paths and - -perhaps as little as one path from your key to the other -key K. - -Requiring multiple, short paths is a strong guarantee -that K belongs to whom your think it does. -The price, of course, is that it is more difficult to validate keys -since you must personally sign more keys than if you accepted fewer -and longer paths. - - -
- -A hypothetical web of trust - - - - - - - - - - - - - - - - -trust -validity - - -marginal -full -marginal -full - - - - - -Dharma - -Blake, Chloe, Dharma, Francis - - - -Blake, Dharma - -Francis -Blake, Chloe, Dharma - - - -Chloe, Dharma - -Chloe, Francis -Blake, Dharma - - - -Blake, Chloe, Dharma - -Elena -Blake, Chloe, Dharma, Francis - - - - -Blake, Chloe, Elena - -Blake, Chloe, Elena, Francis - - - - -
-
-
- - - -Distributing keys - - - -Ideally, you distribute your key by personally giving it to your -correspondents. -In practice, however, keys are often distributed by email or some -other electronic communication medium. -Distribution by email is good practice when you have only a few -correspondents, and even if you have many correspondents, you can use -an alternative means such as posting your public key on your World Wide -Web homepage. -This is unacceptable, however, if people who need your public key do -not know where to find it on the Web. - - - -To solve this problem public key servers are used to collect -and distribute public keys. -A public key received by the server is either added to the server's -database or merged with the existing key if already present. -When a key request comes to the server, the server consults its -database and returns the requested public key if found. - - - -A keyserver is also valuable when many people are frequently signing other -people's keys. -Without a keyserver, when Blake sign's Alice's key then Blake would send -Alice a copy of her public key signed by him so that Alice could -add the updated key to her ring as well as distribute it to all of her -correspondents. -Going through this effort fulfills Alice's and Blake's responsibility -to the community at large in building tight webs of trust and thus -improving the security of PGP. -It is nevertheless a nuisance if key signing is frequent. - - - -Using a keyserver makes the process somewhat easier. -When Blake signs Alice's key he sends the signed key to the key server. -The key server adds Blake's signature to its copy of Alice's key. -Individuals interested in updating their copy of Alice's key then consult -the keyserver on their own initiative to retrieve the updated key. -Alice need never be involved with distribution and can retrieve signatures -on her key simply by querying a keyserver. - must come before - or . -This appears to be a bug. - - - -One or more keys may be sent to a keyserver using the command-line -option . -The option takes one or more key specifiers and sends the specified -keys to the key server. -The key server to which to send the keys is specified with the -command-line option . -Similarly, the option - is used -to retrieve keys from a keyserver, but the option -requires a key ID be used to specify the key. -In the following example Alice sends her public key to the keyserver -certserver.pgp.com and then updates her copy -of Blake's key from the same keyserver. - - -alice% gpg --keyserver certserver.pgp.com --recv-key 0xBB7576AC -gpg: requesting key BB7576AC from certserver.pgp.com ... -gpg: key BB7576AC: 1 new signature - -gpg: Total number processed: 1 -gpg: new signatures: 1 -alice% gpg --keyserver certserver.pgp.com --send-key blake@cyb.org -gpg: success sending to 'certserver.pgp.com' (status=200) - - -There are several popular keyservers in use around the world. -The major keyservers synchronize themselves, so it is fine to -pick a keyserver close to you on the Internet and then use it -regularly for sending and receiving keys. - - - -
- diff --git a/doc/gph/c4.sgml b/doc/gph/c4.sgml deleted file mode 100644 index 1932da7ae..000000000 --- a/doc/gph/c4.sgml +++ /dev/null @@ -1,433 +0,0 @@ - - - -$Id$ - - - -Daily use of &Gnupg; - - - -&Gnupg; is a complex tool with technical, social, and legal issues -surrounding it. -Technically, it has been designed to be used in situations having -drastically different security needs. -This complicates key management. -Socially, using &gnupg; is not strictly a personal decision. -To use &gnupg effectively both parties communicating must use it. -Finally, as of 1999, laws regarding digital encryption, and in particular -whether or not using &gnupg; is legal, vary from country to country and -is currently being debated by many national governments. - - - -This chapter addresses these issues. -It gives practical advice on how to use &gnupg; to meet your security needs. -It also suggests ways to promote the use of &gnupg; for secure -communication between yourself and your colleagues when your colleagues -are not currently using &gnupg;. -Finally, the legal status of &gnupg; is outlined given the current status -of encryption laws in the world. - - - - -Defining your security needs - - - -&Gnupg; is a tool you use to protect your privacy. -Your privacy is protected if you can correspond with others without -eavesdroppers reading those messages. - - - -How you should use &gnupg; depends on the determination and resourcefulness -of those who might want to read your encrypted messages. -An eavesdropper may be an unscrupulous system administrator casually -scanning your mail, it might be an industrial spy trying to collect -your company's secrets, or it might be a law enforcement agency trying -to prosecute you. -Using &gnupg; to protect against casual eavesdropping is going to be -different than using &gnupg; to protect against a determined adversary. -Your goal, ultimately, is to make it more expensive to recover the -unencrypted data than that data is worth. - - - -Customizing your use of &gnupg; revolves around three issues: - - - -the key size of your public/private keypair, - - - - - -protecting your private key, and - - - - - -managing your web of trust. - - - - -A well-chosen key size protects you against brute-force attacks on -encrypted messages. -Protecting your private key prevents an attacker from simply using your -private key to decrypt encrypted messages and sign messages in your name. -Correctly managing your web of trust prevents attackers from masquarading -as people with whom you communicate. -Ultimately, addressing these issues with respect to your own security -needs is how you balance the extra work required to use &gnupg; with -the privacy it gives you. - - - - -Choosing a key size - - - -Selecting a key size depends on the key. -In OpenPGP, a public/private keypair usually has multiple keys. -At the least it has a master signing key, and it probably has one or -more additional subkeys for encryption. -Using default key generation parameters with &gnupg;, the master -key will be a DSA key, and the subkeys will be ElGamal keys. - - - -DSA allows a key size up to 1024 bits. -This is not especially good given today's factoring technology, but -that is what the standard specifies. -Without question, you should use 1024 bit DSA keys. - - - -ElGamal keys, on the other hand, may be of any size. -Since &gnupg; is a hybrid public-key system, the public key is used -to encrypt a 128-bit session key, and the private key is used to -decrypt it. -Key size nevertheless affects encryption and decryption speed -since the cost of these algorithms is exponential in the size of -the key. -Larger keys also take more time to generate and take more space -to store. -Ultimately, there are diminishing returns on the extra security -a large key provides you. -After all, if the key is large enough to resist a brute-force -attack, an eavesdropper will merely switch to some other method for -obtaining your plaintext data. -Examples of other methods include robbing your home or office -and mugging you. -1024 bits is thus the recommended key size. -If you genuinely need a larger key size then you probably already -know this and should be consulting an expert in data security. - - - - - -Protecting your private key - - - -Protecting your private key is the most important job you have to -use &gnupg; correctly. -If someone obtains your private key, then all data encrypted to -the private key can be decrypted and signatures can be made in your name. -If you lose your private key, then you will no longer be able to -decrypt documents encrypted to you in the future or in the past, -and you will not be able to make signatures. -Losing sole possession of your private key is catastrophic. - - - -Regardless of how you use &gnupg; you should store the public -key's revocation certificate -and a backup of your private key on write-protected media in a safe place. -For example, you could burn them on a CD-ROM and store them in your -safe deposit box at the bank in a sealed envelope. -Alternatively, you could store them on a floppy and hide it in your -house. -Whatever you do, they should be put on media that is safe to store -for as long as you expect to keep the key, and you should store -them more carefully than the copy of your private key you use daily. - - - -To help safeguard your key, &Gnupg; does not store your raw -private key on disk. -Instead it encrypts it using a symmetric encryption algorithm. -That is why you need a passphrase to access the key. -Thus there are two barriers an attacker must cross to access your private -key: (1) he must actually acquire the key, and (2) he must get past -the encryption. - - - -Safely storing your private key is important, but there is a cost. -Ideally, you would keep the private key on a removable, write-protected disk -such as a floppy disk, and you would use it on a single-user machine -not connected to a network. -This may be inconvenient or impossible for you to do. -For example, you may not own your own machine and must use a computer -at work or school, or it may mean you have to physically disconnect -your computer from your cable modem every time you want to use &gnupg; - - - -This does not mean you cannot or should not use &gnupg;. -It means only that you have decided that the data you are protecting is -important enough to encrypt but not so important as to take extra -steps to make the first barrier stronger. -It is your choice. - - - -A good passphrase is absolutely critical when using &gnupg;. -Any attacker who gains access to your private key must bypass the -encryption on the private key. -Instead of brute-force guessing the key, an attacker will almost -certainly instead try to guess the passphrase. - - - -The motivation for trying passphrases is that most people choose -a passphrase that is easier to guess than a random 128-bit key. -If the passphrase is a word, it is much cheaper to try all the -words in the dictionaries of the world's languages. -Even if the word is permuted, &eg, k3wldood, it is still easier -to try dictionary words with a catalog of permutations. -The same problem applies to quotations. -In general, passphrases based on natural-language utterances -are poor passphrases since there is little randomness and lots -of redundancy in natural language. -You should avoid natural language passphrases if you can. - - - -A good passphrase is one that you can remember but is hard for -someone to guess. -It should include characters from the whole range of printable characters -on your keyboard. -This includes uppercase alphabetics characters, numbers, and special -characters such as } and |. -Be creative and spend a little time considering your passphrase; a -good choice is important to ensure your privacy. - - - - - - - -Managing your web of trust - - - -As with protecting your private key, managing your web of trust is -another aspect of using &gnupg; that requires balancing security against -ease of use. -If you are using &gnupg; to protect against casual eavesdropping and -forgeries then you can afford to be relatively trusting of other -people's signatures. -On the other hand, if you are concerned that there may be a determined -attacker interested in invading your privacy, then -you should be much less trusting of other signatures and spend more time -personally verifying signatures. - - - -Regardless of your own security needs, through, you should -always be careful when signing other keys. -It is selfish to sign a key with just enough confidence in the key's -validity to satisfy your own security needs. -Others, with more stringent security needs, may want to depend on -your signature. -If they cannot depend on you then that weakens the web of trust -and makes it more difficult for all &gnupg; users to communicate. -Use the same care in signing keys that you would like others to use when -you depend on their signatures. - - - -In practice, managing your web of trust reduces to assigning trust to -others and tuning the options - -and -. -Any key you personally sign will be considered valid, but except for small -groups, it will not be practical to personally sign the key of every person -with whom you communicate. -You will therefore have to assign trust to others. - - - -It is probably wise to be accurate when assigning trust and then -use the options to tune how careful &gnupg; is with key validation. -As a concrete example, you may fully trust a few close friends that -you know are careful with key signing and then marginally -trust all others on your keyring. -From there, you may set to -1 and to -2. -If you are more concerned with security you might choose values of -1 and 3 or 2 -and 3 respectively. -If you are less concerned with privacy attacks and just want some -reasonable confidence about validity, set the values to 1 -and 1. -In general, higher numbers for these options imply that more people -would be needed to conspire against you in order to have a key validated -that does not actually belong to the person whom you think it does. - - - - - - -Building your web of trust - - - -Wanting to use &gnupg; yourself is not enough. -In order to use to communicate securely with others you must have -a web of trust. -At first glance, however, building a web of trust is a daunting task. -The people with whom you communicate need to use -&gnupg;In this section, &gnupg; refers to the -&gnupg; implementation of OpenPGP as well as other implementations -such as NAI's PGP product., and there needs to be enough -key signing so that keys can be considered valid. -These are not technical problems; they are social problems. -Nevertheless, you must overcome these problems if you want to -use &gnupg;. - - - -When getting started using &gnupg; it is important to realize that you -need not securely communicate with every one of your correspondents. -Start with a small circle of people, perhaps just yourself and -one or two others who also want to exercise their right -to privacy. -Generate your keys and sign each other's public keys. -This is your initial web of trust. -By doing this you will appreciate the value of a small, robust -web of trust and will be more cautious as you grow your web -in the future. - - - -In addition to those in your initial web of trust, you may want to -communicate securely with others who are also using &gnupg;. -Doing so, however, can be awkward for two reasons: -(1) you do not always know when someone uses or is willing to use -&gnupg;, and (2) if you do know of someone who uses it, you may still have -trouble validating their key. -The first reason occurs because people do not always advertise that -they use &gnupg;. -The way to change this behavior is to set the example and advertise -that you use &gnupg;. -There are at least three ways to do this: you can sign messages you mail -to others or post to message boards, you can put your public key on your -web page, or, if you put your key on a keyserver, you can put your key -ID in your email signature. -If you advertise your key then you make it that much more acceptable -for others to advertise their keys. -Furthermore, you make it easier for others to start communicating -with you securely since you have taken the initiative and made it clear -that you use &gnupg;. - - - -Key validation is more difficult. -If you do not personally know the person whose key you want to sign, -then it is not possible to sign the key yourself. -You must rely on the signatures of others and hope to find a chain -of signatures leading from the key in question back to your own. -To have any chance of finding a chain, you must take the intitive -and get your key signed by others outside of your intitial web of trust. -An effective way to accomplish this is to participate in key -signing parties. -If you are going to a conference look ahead of time for a key -signing party, and if you do not see one being held, offer to -hold one. -You can also be more passive and carry your fingerprint with you -for impromptu key exchanges. -In such a situation the person to whom you gave the fingerprint -would verify it and sign your public key once he returned home. - - - -Keep in mind, though, that this is optional. -You have no obligation to either publically advertise your key or -sign other people's keys. -The power of &gnupg; is that it is flexible enough to adapt to your -security needs whatever they may be. -The social reality, however, is that you will need to take the initiative -if you want to grow your web of trust and use &gnupg; for as much of -your communication as possible. - - - - - -Using &Gnupg; legally - - - -The legal status of encryption software varies from country to country, -and law regarding encryption software is rapidly evolving. -Bert-Japp -Koops has an excellent -Crypto -Law Survey to which you should refer for the legal status of -encryption software in your country. - - - - - diff --git a/doc/gph/c5.sgml b/doc/gph/c5.sgml deleted file mode 100644 index b847e5853..000000000 --- a/doc/gph/c5.sgml +++ /dev/null @@ -1,38 +0,0 @@ - - - -$Id$ - - - -Programming with &Gnupg; - - -... - - - -Using &gpg in batch mode - - -... - - - -Invoking &gpg from mail clients - - -... - - - - - -Writing extension modules - - -... - - - - diff --git a/doc/gph/c6.sgml b/doc/gph/c6.sgml deleted file mode 100644 index 1b82a8c9a..000000000 --- a/doc/gph/c6.sgml +++ /dev/null @@ -1,804 +0,0 @@ - - - -$Id$ - - - -Command Reference - - - - - -Key specifiers - - - -Many commands and options require a key specifier. -A key specifier is the key ID or any portion of ther user ID of -a key. -Consider the following example. - - -alice% gpg --list-keys chloe -pub 1024D/B87DBA93 1999-06-28 Chloe (Jester) <chloe@cyb.org> -uid Chloe (Plebian) <chloe@tel.net> -sub 2048g/B7934539 1999-06-28 - - -For this key, 0xB87DBA93, -Chloe, -Plebian, and -oe@tel -are all examples of key specifiers that match the above key. - - - - - - - -send-keys - - -send keys to a key server - - - - - - -send-keys key - - - - - -Description - - - -This command sends a public key to a keyserver. -The parameter key specifies -the public key that should be uploaded. -The command requires the option - to specify -to which keyserver &gpg; should send the keys. - - - - - - - -recv-keys - - -retrieve keys from a key server - - - - - key-id key-id ... - - - - - -Description - - - -This command downloads one or more public keys from a keyserver. -Each key-id is a key ID. -The command requires the option - to -specify from which keyserver &gpg; should download the keys. - - - - - - - -encrypt - - -encrypt a document - - - - - filename - - - - - -Description - - - -This command encrypts the document -filename to -recipients specified using the -option . -If the parameter filename -is omitted, then the document to encrypt is taken from standard input. -If the option is omitted, -&gpg; will prompt for a recipient. -If the option is used, -&gpg; will output the encrypted information to the specified file. - - - - - - - -decrypt - - -decrypt an encrypted document - - - - - filename - - - - - -Description - - - -This command decrypts filename -and puts the result on standard output. -If the parameter filename -is omitted, then the document to decrypt is taken from standard input. -Use the option -to output the decrypted message to a file instead. - - - - - - - - -clearsign - - -make a cleartext signature - - - - - filename - - - - - -Description - - - -This command signs a message that can be verified to ensure that the -original message has not been changed. -Verification of the signed message is done using the command -. - - - - - - - - -fingerprint - - -display key fingerprints - - - - - name ... - - - - - -Description - - - -This command prints the fingerprints of the specified public keys. -The parameter name is a -key specifier. -If no parameter name is -provided, &gpg; will print the fingerprints of all the keys on -your public keyring. - - - - - - - -detach-sig - - -make a detached signature - - - - - filename - - - - - -Description - - - -This command creates a signature file that can be used -to verify that the orginal file -filename has not -been changed. -Verification of the file using a detached signature is done using the -command . - - - - - - - -gen-key - - -generate a new keypair - - - - - - - - - - -Description - - - -This command generates a private/public key pair for use in encrypting, -decrypting, and signing of messages. -You will br prompted for the kind of key you wish to create, the key -size, and the key's expiration date. - - - - - - - -symmetric - - -encrypt a document using only a symmetric encryption algorithm - - - - - filename - - - - - -Description - - - -This command encrypts a document using a symmetric algorithm with -a key derived from a passphrase supplied by you during execution. -The key should be selected to make it difficult to randomly guess the key. -To decrypt a document encrypted in this manner use the command. -. - - - - - - - -list-keys - - -list information about the specified keys - - - - - key ... - - - - - -Description - - - -This command lists the public key specified by the key specifiers on the -command line. -If no key specifier is given, &gpg; will print all of the keys on the -public keyring. - - - - - - - -import - - -import keys to a local keyring - - - - - filename - - - - - -Description - - - -This command imports one or more public keys onto the user's public -keyring from the file filename. - - - - - - - -verify - - -verify a signed document - - - - - signature document - - - - - -Description - - - -This command verifies a document against a signature -to ensure that the document has not been altered since the signature -was created. -If signature is omitted, -&gpg; will look in document -for a clearsign signature. - - - - - - - -gen-revoke - - -generate a revocation certificate for a public/private keypair - - - - - key - - - - - -Description - - - -This command generates a revocation certificate for a public/private -key pair. -The parameter key is -a key specifier. - - - - - - - -export - - -export keys from a local keyring - - - - - key key ... - - - - - -Description - - - -This command exports the public keys components of the keys specified -by the key specifiers key key .... -The export command by default sends its output to standard output. -This key file can later be imported into another keyring using the command -. - - - - - - - -edit-key - - -presents a menu for operating on keys - - - - - key - - - - - -Description - - - -This command presents a menu which enables you to perform -key-related taskes. -The key specifier key -specifies the key pair to be edited. -If the specifier matches more than one key pair, &gpg; issues -an error and exits. - - - -Key listings displayed during key editing show the key with its -secondary keys and all user ids. -Selected keys or user ids are indicated by an asterisk. -The trust and validity values are displayed with the primary key: -the first is the assigned trust and the second is the -calculated validity. -Letters are used for the values: - - - - - -Letter -Meaning - - - - - -- - - -No ownertrust assigned / not yet calculated. - - - - -e - - -Trust calculation has failed. - - - - - -q - - -Not enough information for calculation. - - - - - -n - - -Never trust this key. - - - - - -m - - -Marginally trusted. - - - - - -f - - -Fully trusted. - - - - - -u - - -Ultimately trusted. - - - - - - - - -The following lists each key editing command and a description -of its behavior. - - - - -sign - - - -Makes a signature on the current key. -If th key is not yet signed by the default user or the user -given with the option -, -the program displays the information of the key again, together with -its fingerprint and asks whether it should be signed. -This question is repeated for all users specified with the option -. - - - - - -lsign - - - -Same as sign, but the signature is -marked as non-exportable and will therefore never be used by others. -This may be used to make keys valid only in the local environment. - - - - - -revsig - - - -Revoke a signature. -Asks for each signature makde by a one of the private keys whether -a revocation certificate should be generated. - - - - - -trust - - - -Change the owner trust value. -This updates the trust database immediately and no save is required. - - - - - -disable - - - -Disable the key. -A disabled key cannot normally be used for encryption. - - - - - -enable - - - -Enable a key that has been previously -disabled. - - - - - -adduid - - - -Add a new user id to the current key. - - - - - -deluid - - - -Delete a user id from the current key. - - - - - -addkey - - - -Add a new subkey to the current key. - - - - - -delkey - - - -Delete a subkey from the current key. - - - - - -revkey - - - -Revoke a subkey of the current key. - - - - - -expire - - - -Change a key expiration time. -If a subkey is selected, the time of that key will be changed. -With no selection the expiration time of the current primary key is changed. - - - - - -key n - - - -Toggle selection of subkey with index n. -Use 0 to deselect all. - - - - - -uid n - - - -Toggle selection of user id with index n. -Use 0 to deselect all. - - - - - -toggle - - - -Change the passphrase of the private key of the selected key pair. - - - - - -toggle - - - -Toggle between public and private key listings. - - - - - -check - - - -Check all selected user ids. - - - - - -pref - - - -List preferences. - - - - - -save - - - -Save all changes to the current key and quit. - - - - - -save - - - -Quit without updating the current key. - - - - - - diff --git a/doc/gph/c7.sgml b/doc/gph/c7.sgml deleted file mode 100644 index 17f3186f1..000000000 --- a/doc/gph/c7.sgml +++ /dev/null @@ -1,251 +0,0 @@ - - - -$Id$ - - - -Options Reference - - - - - -Setting options - - - -Options may be specified on the command line or in an options file. -The default location of the options file is -~/.gnupg/options. -When specifying options in the options file, omit the leading two -dashes and instead use simply the option name followed by any -arguments. -Lines in the file with a hash (#) as the -first non-white-space character are ignored. - - - - - - - -keyserver - - -specify the keyserver to use to locate keys - - - - - server-name - - - - - -Description - - - -This option is used in conjunction with either - or - to specify a -keyserver to manage public key distribution. - - - - - - - -output - - -specify the file in which to place output - - - - - file-name - - - - - -Description - - - -This is a description. - - - - - - - -recipient - - -specify the recipient of a public-key encrypted document - - - - - - - - - -Description - - - -This is a description. - - - - - - - -armor - - -ASCII-armor encrypted or signed output - - - - - - - - - -Description - - - -This is a description. - - - - - - - -no-greeting - - -suppress the opening copyright notice but do not enter batch mode - - - - - - - - - -Description - - - -This is a description. - - - - - - - -local-user - - -specifies a user id to use for signing - - - - - name - - - - - -Description - - - -Use name as the user ID to sign. -This option is silently ignored for the list commands, so that it can be -used in an options file. - - - - - - - -completes-needed - - -specifies the number of fully-trusted people needed to validate a new key. - - - - - n - - - - - -Description - - - -A public key on your keyring is validated using those signatures on -the key that were made by other valid keys on your keyring. -The option specifies the number of signatures needed if you fully -trust the owners of the keys that made the signatures. -Your trust in a key's owner is set with the command -. - - - - - - - -marginals-needed - - -specifies the number of marginally-trusted people needed to validate -a new key. - - - - - n - - - - - -Description - - - -A public key on your keyring is validated using those signatures on -the key that were made by other valid keys on your keyring. -The option specifies the number of signatures needed if you marginally -trust the owners of the keys that made the signatures. -Your trust in a key's owner is set with the command -. - - - - - diff --git a/doc/gph/manual.sgml b/doc/gph/manual.sgml deleted file mode 100644 index f573bfd4f..000000000 --- a/doc/gph/manual.sgml +++ /dev/null @@ -1,71 +0,0 @@ - - - - -gpg"> - - - - - - - - - - - -]> - - -The GNU Privacy Handbook - -August 25, 1999 - - -1999 -Free Software Foundation - - - -Please direct questions, bug reports, or suggesstions concerning -this manual to the maintainer, Mike Ashley (jashley@acm.org). -Contributors to this manual also include Matthew Copeland and -Joergen Grahn. - - - -This manual may be redistributed under the terms of the -GNU General Public -License. - - -PLEASE NOTE, THAT THIS IS A DRAFT VERSION OF THE MANUAL AND NOT A COMPLETE -AND CORRECT MANUAL. CONSIDER IT AS WORK IN PROGRESS. The latest draft of -the manual should be available online; -www.gnupg.org has a link -to it. - - - - - - -&chapter1 -&chapter2 -&chapter3 -&chapter4 -&chapter5 -&chapter6 -&chapter7 - - diff --git a/doc/gph/signatures.fig b/doc/gph/signatures.fig deleted file mode 100644 index 57fdfe6f6..000000000 --- a/doc/gph/signatures.fig +++ /dev/null @@ -1,44 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single --2 -1200 2 -6 600 300 9450 2625 -6 1500 300 9450 2625 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 1575 1050 2475 1950 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 3675 1950 4575 1050 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 5775 1050 6675 1050 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 7875 1050 8475 1050 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 3600 525 4500 1050 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 3675 1950 5100 2550 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 5175 1200 5625 2325 -4 0 0 100 0 14 18 0.0000 4 180 825 6825 1125 Elena\001 -4 0 0 100 0 14 18 0.0000 4 180 825 8625 1125 Geoff\001 -4 0 0 100 0 14 18 0.0000 4 180 825 4725 1125 Chloe\001 -4 0 0 100 0 14 18 0.0000 4 180 825 2625 525 Blake\001 -4 0 0 100 0 14 18 0.0000 4 180 990 2550 2025 Dharma\001 -4 0 0 100 0 14 18 0.0000 4 180 1155 5175 2625 Francis\001 --6 -2 1 0 3 0 7 100 0 -1 0.000 0 0 -1 1 0 2 - 1 1 3.00 90.00 180.00 - 1575 1050 2475 450 -4 0 0 100 0 14 18 0.0000 4 180 825 600 1125 Alice\001 --6 diff --git a/doc/gph/signatures.jpg.asc b/doc/gph/signatures.jpg.asc deleted file mode 100644 index 99f04e394..000000000 --- a/doc/gph/signatures.jpg.asc +++ /dev/null @@ -1,232 +0,0 @@ ------BEGIN PGP ARMORED FILE----- -Version: GnuPG v0.9.11 (GNU/Linux) -Comment: For info see http://www.gnupg.org -Comment: Use "gpg --dearmor" for unpacking - -/9j/4AAQSkZJRgABAQEAUABQAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkS -Ew8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJ -CQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy -MjIyMjIyMjIyMjIyMjL/wAARCACxAogDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEA -AAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh -MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6 -Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZ -mqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx -8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREA -AgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV -YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hp -anN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPE -xcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3 -+iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiub8Z+MrbwRpaan -f6bqV1Zl9kktlGjiEnG3fudSAScA8jPBwSM5+i/Emx1bxBa6LcaH4g0i7vEka1/t -Sx8lZig3MqnceQvPpx1yQCAdpRXH6V4y1G7+Id74U1HQPsHk2kl7b3X2xZftEIlE -atsC/Lu5OCcjGMV0Gp67o+ieV/a2q2Nh52fL+13CRb8YzjcRnGR09RQBoUVyfi7x -NfWfgO78Q+EhpuqmBDN5jT7ovKQnzGUqcOQFPG4dDySNpuaF4x0fW7XTF/tCxh1O -+tIrn+zvtaNMm+ISbdvDHCnOcDjmgDoKKy9S8S6Do1wtvqmt6bYzsgdY7q6SJiuS -MgMQcZBGfY1qUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFF -FFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFF -FFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFF -FFABRRRQAVz/AIk8ceGvCPljXNXgtJJMFYcNJIQc4bYgLbflI3YxkYzmjxZ400Lw -Vpy3mtXflebuEEKKXkmZRkhVH4DJwoJGSMivnTxl4Z8X/EB5/Htr4TktLS6SDZbw -ytNPOu3YJQnUj5V6KvylSAw3PQB29/8AHy+1zVLPSfAnh2S5vLhwoOoDlj82VCI2 -AAMNvL4ADZAAzXsmh2+o2mh2UGr3v23UliX7TOAoDyHltoVVG0HIHAOAM85Ncn8M -/hnY+ANLLuY7nWrhALq7A4A6+XHnkID36sRk9AF7ygDzf41zXlx4EuNDsNF1XUbr -Utux7G1MyReXLG58wjlcjOODnBrj/B2j6jL8XNI1a1s/GUlnFaTR3lx4qtlLxLtb -b5Up9WYDaoDD5uSrNj3iigDxf/hMLz/haf8AwlH/AAg/jL7D/Yn9n+X/AGSfM8zz -/MzjdjbjvnOe1SfFZtc1PWdHNrpF3Popsmljnh8ORalOJmYZR45sGIbQh6Kc5BBx -8vslFAHgfhNtS0n4UeNtKufDfiD7Xe3E4tUXRmiM32iLYpEacIF2EsB8qgqASSBR -4A0G58I+ILCDxD4Ru9bfUreyuLbVhYPLJpr4VRDJv4iEeOqkEBVyDwE98ooA+ZNZ -8JeKbbVNYg16DWdQnvLiVhfWvhi21EzxH5FcSl90JwvEYI2DGMZr2/4aWs1j8PNI -tJ21IvCkiD+0rcwThRIwUNGWbaAuAoyflA6dB1lFAGXrniPSPDVvbXGs30dnBcXC -20ckgO3zGBIBIGFGFJ3HAGOSK0IJ4bq3iuLeWOaCVA8ckbBldSMggjggjnNU9Z0P -S/EOnPYavYQXtq2TsmTO0kEblPVWwThhgjPBryufwV43+G1vLd+BdZk1bSYULtou -oqZGAA/5Z7cZO5nchPLJwB854oA9korh/B3xS0Lxdef2UVn0zXU3LLpt4hVwyAbw -p6Ng7hg4b5WJUAV3FABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFF -FABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFF -FABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUVz/izx -poXgrTlvNau/K83cIIUUvJMyjJCqPwGThQSMkZFAHQV5P4i+LFxq2oyeGvhxZ/2z -q7xSFr1SBDalTgsC4Cv3wxITJTBfO2stNN8afGZEm1dpPDfg6ZIporOMrJLd4bOS -2AcHkgsNv+rIRvvV6xoHhzSPC2lrpui2MdpaBy+xSWLMepZmJLHoMkngAdAKAOL8 -J/Ce307WG8S+Kbz+3fEskq3H2iQERwOFxhFzhsHoSBgKm1UxXpFFFABRRRQAUUUU -AFFFFABRRRQAUUUUAFFFFAHJ+M/hz4c8dIjavbSLdxJsivLd9kqLuBxnBDDrwwON -zYwTmuHGpeP/AIWXDrrC3fi/wuqKft0Y/wBItuS0jMCWYgAN94lcbPnTla9kooAw -/C/i7RfGOlpf6PexzAorSwFgJYCcjbImcqcq3scZBI5rcrzPxR8G9IvnfVfC0knh -3Xo0YwTWMhhiLbQuGVfuAqCMpj7xJDdDn2fxQ1rwdqkGi/EzTo7QSI/kazaAvFOE -wMlFBOSQScYI3plFBzQB65RXPt458LLqOmWA16xkuNT3fYxFKHWXBK/eXKjLAqMk -ZYEDJGK6CgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA -KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA -KKKKACiiigAqnqt+2maXcXyWN3fGBN/2e0VWlcd9oYgE45xnJxgZOAblcf8AE7Vd -Y0vwNe/2BYX15qd1/osP2KF5Hh3A7pPkIZcKGww6MVoAj8D/ABP0Hx9cXlvpcd3B -PaortHdhFZ1JIyoV2JAIAJ7bl9aku/GWo2PxH07wxc6BssdS837JqX2xT5nlw+Y/ -7oLkYJ28kZ6ivLLHTPEfw88S+FdYtLfWdetH0z7Pc2dtoP2d7W1Y71Rtu5TLvZnI -yGymGbDZro/FfiW8k+Jnh3UYfB3iua10CW+iuJItMLCbzEEatEQcMuRnJxwRQB6Z -4h1y28PaNPf3E1ojqjCCO6ukt1nl2krGHc4BbHXtye1WNJvW1LRrG/eKOJ7m3jma -OOZZlUsoOA68OBn7w4PUVwfxB1q31fwCsR8H65qU2p2k5tov7JLvYzhCqtKrcxsC -5wwBzhiCRgk8J6pf618PG8MW+k65omr2uiLaxXOoWclvGZRF5e5JBnGGwezYOQDg -4AOsn8aeFbW4lt7jxLo0M8TlJI5L+JWRgcEEFsgg8Yq5qeu6Ponlf2tqtjYedny/ -tdwkW/GM43EZxkdPUV4fYabo48IW3hnUPhLrjazFshluILJAk8ySA5N4eVjcj5mH -CqxCnABpnjbw34ph8eavqF/FqWo2d26iwmt/DttqoWJRny9jtmEKX25wPMIZjzQB -7/BPDdW8VxbyxzQSoHjkjYMrqRkEEcEEc5qSvO/gxpk2j+CprKX+2Qkd7IYk1axN -o6KVQ4RN7/JuLHIIyS3Hc7nxC8LXHjPwXfaJa332Oaba6sygpIVIYI/BIUkDleRg -HkZUgHH+IvixcatqMnhr4cWf9s6u8Uha9UgQ2pU4LAuAr98MSEyUwXztrQ8J/Ce3 -07WG8S+Kbz+3fEskq3H2iQERwOFxhFzhsHoSBgKm1UxWX8G/EVjptvJ4C1DS49E8 -Q2DsZID/AMvhxkyAknc+3BIyQVAK/LwvrlABRRRQAUUUUAFFFFABRRRQAUUUUAFF -FFABRRRQAUUUUAFFFFABVe+sLPU7OSzv7SC7tZMb4Z4xIjYIIyp4OCAfwqxRQB8c -eMPh54p0u8uNRfwdPpmmvvkSG1lN2lvGgGd8gZiOOSzYB5wABger/B74w/2r9n8M -+Jrn/iYcR2V9I3/Hz6RyH/np6N/F0Pzff9wrj/H9h4G/sd9R8aWlj9n+SAXMsZ87 -725URk/edcnC9t2eM0AdhRXl/gXx1qnjrxGBotlPZeEdNiCvc3i+ZPdS7MCIuXOM -bg5I3N8g3MPMxXqFAHn9/wDFjTv9JXw9oeueJPJ3x/aNMsmktvOGf3Zl/wC+TuUM -MMCM1n3/AMVrhYPCev2OnQJ4V1i7NpdXN9MI5oH3sgJAJVVGxnzlsgEHZwTn+Dtc -134caDB4V1rwVrl59i3mC90eIXcdwrSyMScbdnUYBO4jkheMx+Pr6bVPD/hC2XwR -rPkQ6nDfzabDpxmWKzjLosbhRsDshB8r+HkNjjIB6xpurabrNu1xpeoWl9ArlGkt -ZllUNgHBKkjOCDj3Fc34N8Zaj4j1jW9J1bQP7GvtJ8jzIvti3G7zVZhyqgDgA8E9 -e2K5PwncL4a+IfjloPCWs2mmzpG1kttpTLFKbaNw6ptG3LnJToGz1BIBr+G/FlzZ -fEPxPrF14N8XRWetPZLC50hyYRFGUdpACTjJz8u44HTPFAHqmp67o+ieV/a2q2Nh -52fL+13CRb8YzjcRnGR09RVj7fZ/2d/aP2uD7D5Xn/afMHl+Xjdv3dNuOc9MV5P4 -j07+yfihqes+IPBl94p0y/tIo9Pe0tvtv2PYAHjMTfKu5stu+uM7nxzk/gnxoPhl -ZpaW93aWJ1iTUG0JQt08FmQrorJKR5hRkY+TzvMgLAMCAAe56Zruj635v9k6rY3/ -AJOPM+yXCS7M5xnaTjOD19DWhXz/APDvRL23+Jmm6lJbeI7X91LDIH8Lx6bbOmxy -BI0Um372CMqckKOwx9AUAFFZ+t6V/bejz6d9vvrDztv+k2E3lTJhg3ytg4zjB9ia -4/8A4VZ/1Pvjn/wcf/YUAegUV5//AMKs/wCp98c/+Dj/AOwo/wCFWf8AU++Of/Bx -/wDYUAegUV5//wAKs/6n3xz/AODj/wCwo/4VZ/1Pvjn/AMHH/wBhQBqJ8TfBbazd -6S/iC0t7y0d0mW63QKrI21gHcBSc9gTnkjgV1EE8N1bxXFvLHNBKgeOSNgyupGQQ -RwQRzmvli6+CfjTVvFWofZ7WQWD3twI9R1O5XdIquwDuBlyWxnOzncD0Oa7fwl8A -dS0a4ivbvxhd2M7IyXEejFomK54AmJBxkISCnbHoaAPdK5vxn4ytvBGlpqd/pupX -VmX2SS2UaOIScbd+51IBJwDyM8HBIzsaVYNpml29i99d3xgTZ9ou2VpXHbcVABOO -M4ycZOTkng/jXNeXHgS40Ow0XVdRutS27HsbUzJF5csbnzCOVyM44OcGgC5ofxV0 -3XPEFhow0LxBYT3zzJBJf2ixRs0IYyDO8nKlSpABweDirmleMtRu/iHe+FNR0D7B -5NpJe2919sWX7RCJRGrbAvy7uTgnIxjFcH8OJtS0fxPa6XaeH/ED2d9e3t1eapr2 -lNFPErxoVQShyCWaEb2IG47eAak/4TC8/wCFp/8ACUf8IP4y+w/2J/Z/l/2SfM8z -z/MzjdjbjvnOe1AHrmpatpujW63GqahaWMDOEWS6mWJS2CcAsQM4BOPY1H/buj/2 -P/a/9q2P9mf8/v2hPJ+9t+/nb97jr14rxv4l6J4kv/GMOuompX2gy2SLaRRaFDft -au2CyG2mYFSdm4yFQRkIelUPD+lzaX8PvHFpNpHie9Opoot7G48PG3UXDiTDxRI7 -qApCMSAoXYgGTtFAHt+m+JdB1m4a30vW9Nvp1Qu0drdJKwXIGSFJOMkDPuKjvvFn -hvTLySzv/EGlWl1HjfDPexxuuQCMqTkZBB/GvH9Esv7P8R/DK6tPBGq2cltaSRap -PHpXlkyOn2cNKw9GVnJbkI4bqSKyPHlh4n1PxH4k+1aDfGR5ZIrQ2XhSC7SaEIFi -Y3RPmKxGMkZKdsEbQAfR9Fc38P3mb4faAlxZXdlPBZR28kF3EY5FaMeWSVPIBK5H -qCDXSUAFFcfrfgD+29Yn1H/hLfFdh523/RrDUvKhTChflXacZxk+5NZ//CrP+p98 -c/8Ag4/+woA9Ark0+JvgttZu9JfxBaW95aO6TLdboFVkbawDuApOewJzyRwKy/8A -hVn/AFPvjn/wcf8A2FeKXXwT8aat4q1D7PayCwe9uBHqOp3K7pFV2AdwMuS2M52c -7gehzQB9TwTw3VvFcW8sc0EqB45I2DK6kZBBHBBHOakrwvwl8AdS0a4ivbvxhd2M -7IyXEejFomK54AmJBxkISCnbHoa9o0qwbTNLt7F767vjAmz7RdsrSuO24qACccZx -k4ycnJIBl+K/GOl+D7O3lv8Az57i6lENrZWieZPcOSBhEyM4yM89wOpAOHpHxPh1 -PxZZaDceGfEGlvfoxtZtRtRCJGRWeQYJ6BQuCM5LcgYBJ48sNXi8T+FfFOm6ZJqc -Givdfa7WBwJzHLGFLRqeHICn5Qck7QOpI5PTtV+IfiTxp9msr7xHpekT/aZXfUfD -9vbizXB8lVZt3m4YqCOGIBPqVAPVJvEug22qDS59b02LUC6oLR7pFlLNjaNhOcnI -wMc5FWNS1bTdGt1uNU1C0sYGcIsl1MsSlsE4BYgZwCcexr5gn8H+IVsJdM17TPEB -vHcvcy2nha3vmZmffkXgkDuTkZOeMlegr0PXNKvLfWPCGv614d1XxTo0OiJaSWrQ -GW5guiu4zS2zEgswwrZJwRycqmQD1yHVtNudLOqQahaS6eEZzdpMrRBVzuO8HGBg -5OeMGvN/DnxfvPFOs2drpvhu0NpdXBRHk123W4WIMQ0ht/v5CgttGeBwSOar+DdK -Wx0vxjrGo+E7u28N6hcRzWXh17Vp5SUyGb7NghS7bCB0XaOQiq1U/hAlnplno2lX -/gHVbTXY/P36xPo4jRcmRhmY/MMoQnTvjpQB0njP4pxeGfEqaDYafaaheLb/AGi4 -NxqsNkkIJAVd0nBcj5tvBwVIyCcdh4c1O71nw/Z6je2MdjPcIX8iO6S5ULk7SJE+ -Vgy4bI9a8j1yPS7b4v3upS/DrVdU0kae1tJ5Gg+Yk12Zt7TAMAG4JXf1PbIIJ9k0 -l4ZNGsXt7KSxga3jMdpJEImgXaMIUHClRxjtjFAFyiiigAooooAKKKKACiiigAoo -ooAKKKKACiiigAooooA4f4ifDu38a2cV3aTfYPENjh7G/QlSpB3BGI5255BHKnkd -w2f8O/iJcaveS+FPFcP2DxZY5SSNwFF2AM71xxuxyQOCPmX5chfSK4f4ifDu38a2 -cV3aTfYPENjh7G/QlSpB3BGI5255BHKnkdwwB3FFeb/Dv4iXGr3kvhTxXD9g8WWO -UkjcBRdgDO9ccbsckDgj5l+XIX0igAooooAKKKKACiiigAooooAKKKKACiiigAoo -ooAKKKKACiio554bW3luLiWOGCJC8kkjBVRQMkkngADnNAEd/N9n065n+0wWvlxO -/n3AzHFgE7nGV+UdTyOB1HWviTUrvWvF3ipYrjUZNY1C5uBbQSs5CyFnO0JvC7EL -NkDCgZ6Cvc76+1T4465JpWlST2HgWxlAu7wLte9cYIVQfwIU/d4dhnYg9csPDei6 -Xb6dBZ6XaRJpqMlmfKBaAMMNtY8gt/Ec5bvmgCn4L8J2fgrwva6LZv5vlZeacoEa -aRjlmIH4AZyQoUZOM10FFFABRRRQAVy/j/xZceCfC765BpX9pRwyok6faBD5aMcB -8kHPzFRgD+LPQGuoqnq2mw6zo19pdw0iwXtvJbyNGQGCupUkZBGcH0NAElhfW+p6 -dbX9nJ5lrdRJNC+0jcjAFTg8jII61Yryv4H6lNDomreD7tYzd+G72S3aSEHY6s7n -IJOSd6ydhxt75r1SgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiii -gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiii -gAooooAKKKKACiiigAooooAKKKKAOH+Inw7t/GtnFd2k32DxDY4exv0JUqQdwRiO -dueQRyp5HcNn/Dv4iXGr3kvhTxXD9g8WWOUkjcBRdgDO9ccbsckDgj5l+XIX0iuH -+Inw7t/GtnFd2k32DxDY4exv0JUqQdwRiOdueQRyp5HcMAdxRXm/w7+Ilxq95L4U -8Vw/YPFljlJI3AUXYAzvXHG7HJA4I+ZflyF9IoAKKKKACiiigAooooAKKKKACiii -gAooooAKKKjnnhtbeW4uJY4YIkLySSMFVFAySSeAAOc0AE88Nrby3FxLHDBEheSS -RgqooGSSTwABzmvE76+1T4465JpWlST2HgWxlAu7wLte9cYIVQfwIU/d4dhnYgL6 -+1T4465JpWlST2HgWxlAu7wLte9cYIVQfwIU/d4dhnYg9k0rSrHQ9Lt9M0y2jtrO -3TZFEnRR/MknJJPJJJOSaADStKsdD0u30zTLaO2s7dNkUSdFH8ySckk8kkk5Jq5R -RQAUUUUAFFFFABRRRQB4/wCLv+KI+NuieLW/caRrMX9n6jMOQJMYUuz/ACxrxCcg -g4ic4659gri/ir4XXxZ8PtRtFjke7tkN5aCNGdjLGCQoUEbiylk7/ezgkCrHw28U -N4v8B6bqs8kbXmww3e11J81DtJYAAKWAD7cDAcdsGgDrKKKKACiiigAooooAKKKK -ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKK -ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA4f4i -fDu38a2cV3aTfYPENjh7G/QlSpB3BGI5255BHKnkdw2f8O/iJcaveS+FPFcP2DxZ -Y5SSNwFF2AM71xxuxyQOCPmX5chfSK8H/aH0XVNR+wXtl4b8+1tIi0+qw/PIo+Ym -NlU5EahSxZgQC3BXncAe4WN/Z6nZx3lhdwXdrJnZNBIJEbBIOGHBwQR+FWK+aPgD -46TR9Yk8K3xxa6nL5lrIWVVjn24IOcE7wqqOT8yqAPmJH0vQAUUVX+32f9o/2d9r -g+3eV5/2bzB5nl5279vXbnjPTNAFiiiigAooooAKKKKACiio554bW3luLiWOGCJC -8kkjBVRQMkkngADnNABPPDa28txcSxwwRIXkkkYKqKBkkk8AAc5rxO+vtU+OOuSa -VpUk9h4FsZQLu8C7XvXGCFUH8CFP3eHYZ2IC+vtU+OOuSaVpUk9h4FsZQLu8C7Xv -XGCFUH8CFP3eHYZ2IPZNK0qx0PS7fTNMto7azt02RRJ0UfzJJySTySSTkmgA0rSr -HQ9Lt9M0y2jtrO3TZFEnRR/MknJJPJJJOSauUUUAFFFFABRRRQAUUUUAFFFFABXj -/gr/AIoX4w6/4Qn+Sx1r/iZaWqfLGv3iyLGuQvAZcnbkQDjlQPYK8n+NtjcaXZ6P -460mPbqeh3aCSQMFDQOcbXxhmXeVXaD0lfjkkAHrFFV7C+t9T062v7OTzLW6iSaF -9pG5GAKnB5GQR1qxQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRR -QAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRR -QAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB5X4z+CWkaw6al4YaPw/rEL+aj26lYn -ZVGz5VI8shlU7kHGWJDEjHcaXbavf+DlsdekktdUe3e2ubizmG4sMp50bBQFLACQ -cDbuAxxW5Ve/tft2nXNn9ont/PieLzrd9kke4EbkbswzkHsaAPC/D+ja1ffB/wD4 -TZPHHiePVre3uLxY5L4y25MEj/KY26grHjkkZPII4NzXEv7/AMY/DXxPoVnpUHib -WdPmlne5EiwSEWyH5gpLcK7gHr90EkAY6SD4JaLDYRaY/iHxPPpKOGbTZNQAt3Af -ftKKg4Lc8YOeQQea3L/4d2F/4o0rXf7V1W2bSdgsbK1ljitoEUAFFQJnawGG55HG -cAAAGfonjq/ufA3iTUtaOlWGpaJd3VjJNuk+yNLGBtbH39pZlXAyx7ckKOb8FfFz -VNd8b6doV3ceH9QgvkmHmaXFdRNAyIXBbz1AYEKRgfXIxg9JZfCPR7XR9a0mbWNc -vbHWPnuoru5Rv324MJgQgIkyAckkNgbg2BgtvhPZwa5purzeKvFd7dadL5tv9r1A -SAZxuXlM7WAwwBGRxQBl6r4t+I1t4/uPC2naV4fvHlt/tlpLvkQQW5n2B5ssNxCg -5VBnLAjOCpk1nxJ8R9M1zw1oaR+FGv8AV4rjc5W4MSyRbnODnIUxmPHBO7d0GK0L -/wCE9nfeIbnXP+Eq8V299PvXfb6gE8uNnL+Uh2ZEYJ4XOBWpqfgK21bxLomvXWta -z9s0hFWERzoiSEHLs6hMZcfK+3aCABgCgDg/Cvxe1vUrG+l1xNDslbRJdUsrkeas -cZSZoAsq5YtucDAQ5xgDJbAk8FfFzVNd8b6doV3ceH9QgvkmHmaXFdRNAyIXBbz1 -AYEKRgfXIxg6i/Arw35EdvLquuS28Vo9msRuI0Xy2dpADsjBbEjeYNxI3BcggYrQ -tvhPZwa5purzeKvFd7dadL5tv9r1ASAZxuXlM7WAwwBGRxQB6BXz/wDEfxV/wlHx -FHgXWtT/AOEc8O2sqfapHOXvGO1lyVyqqdwI3EKv3m5AQfQFZ+s6HpfiHTnsNXsI -L21bJ2TJnaSCNynqrYJwwwRng0AGh2Ol6dodla6JHBHpiRKbYQNuQoeQwbndnOd2 -TnOcnNaFeT3Pwj1Tw9uufh74rvtKk815fsF5J5toxbC9MHGFzyyuTheQRmo4Pit4 -j8L3EUHxH8KyadBO4Eeo2A8yBNxwFYBmGQFkY4YtgDCd6APXKKx/D3irQvFdmbrQ -9TgvY1++EJDx5JA3IcMudpxkDOMjitigAooooAKKKKACiiigAooooAKp6tpsOs6N -faXcNIsF7byW8jRkBgrqVJGQRnB9DVyigDyv4H6lNDomreD7tYzd+G72S3aSEHY6 -s7nIJOSd6ydhxt75r1SvF/G99b/D3426N4rnk8jTNYtHtdQMamR2KADcVPRRm3Py -c/u24Ofm9Y0TW9O8R6PBq2k3H2ixn3eXLsZN21ip4YAjkEcigDQooooAKKKKACii -igAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACii -igAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACii -igAooooAKKKKACiiigAooooAKKKKACiiigAooooA871v4N+HL6//ALU0WS78Oaoi -OI7jSpPKUMU2glBwAB1CFN25snnNYf8AaHxa8C/ubrToPGGkQdLmAlbtk+4ikD5i -wwrMdkn3jlz1HsFFAHD+GPi34O8VSw21rqf2W+m4W0vV8pyd20KDyjMSRhVYk56c -HHcVzfivwH4c8Z25TWdOjknCbY7uP5J4+GxhxyQCxO05XPJBrh5vBfj/AMDuJ/BP -iCTWtPRFQaPrD7iqqoVQjEgADczYUx8Ko+bpQB65RXlem/Gi00+4bS/HmlXfhzVI -kJZmieSCbBC7k2gtgsHxgMuF++a9Msb+z1OzjvLC7gu7WTOyaCQSI2CQcMODggj8 -KALFFFFABRRRQAUUUUAfP/7QPgD/AJnTTo/7sephpf8AdSJ1U/gpwf7px941ufs3 -zwt4F1O3WWMzpqbO8YYblVoowpI6gEqwB77T6V7BPBDdW8tvcRRzQSoUkjkUMrqR -ggg8EEcYrzf4deCz4E8a+KbCJJDp9+kF1YusMmxIw0oMTOcjeu5RgsSwIb1AAPTK -KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK -KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK -KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAr -31hZ6nZyWd/aQXdrJjfDPGJEbBBGVPBwQD+FeZ3nwaXSXnvvAniDUvD94zpILfz2 -ktZCinarg/MQW5JYuACw2kHFeqUUAeP/APCxPHPgj/kffDH2nTE/d/2rpWG+78u9 -1ztG9imM+V1OAfuiSP8AaC8LnxZNp0qSLo4TMWrLvYM20HDRbA6jO5cjPIHGDkeu -V88az+zjrEu+6s/FMF/fTSl5jfQPFuzksxcM5LZx1HOSc+oB9BwTw3VvFcW8sc0E -qB45I2DK6kZBBHBBHOakrw/wj4S+KPw22/ZvsPiHTGzG2lR37J5edzB0aVVVPmPO -M7t3I6MvsF9Zf25oclrM99p7XMQyYJ/KngY4PDoSAwPoSpxjkHkA0KK+YPAq+JPG -9wNLi8WeK7O/fTxeLdT6jIIDtuvLkKJ1kXyyMfMv7xGBODx6n408W+OtA8Z2OlaP -pWjalb6qkw0+Eu6T7o4gzGRmYIAGbOB1UYyCc0AemUVwer+I/EvhbwHe6l4kvvDF -pqwuFS1dRcNaspK8MoBkZ8eYcKDwAegNY/w2+J2oeLfFV3ot7Jo12iWX2uO60tLi -NVIcIUZZgCT8wORgDHfPAB6pRXibfEn4g2Wia1r15Z+GJdP0PUzp97DD9oSWVldE -byySQAd4wT7/AC9j2ninxT4gj8W2XhTwpY2MupyWhv7i51JmEEUAYoOEO4sXAHHT -I4OSVAO4org9Kv8A4lXNv4gtb2x8Pw6haPAmn3AWcWs5YBpc5O8hVIAIAG7I5wcS -fCC4iu/hbo08NlBZRt5+IIC5RMTyDguzNz15J6+nFAHcUV4f4q+LnivRvEOo2EVr -odj5V2YLK01OG5Sa5j37BMJPlhEbHccllAAPJxk+4UAFFFFABRRRQAUUUUAFFFFA -BRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFA -BRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFA -BRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAVn63pX9t6PPp32++sPO2/6TYTe -VMmGDfK2DjOMH2JrQooA5PwZ4CtvA6PBp+tazc2bJtWzvZ0kijO4tuQBAVOS2cHB -zyCQCKfiH4ZWfiPxGNcm8R+I7S6j/wCPdLO+EaW2UCN5QKEpuA+bB5ya7iigDl9V -8D2et+F7LRNR1TVZmsZY57fUftAW7SRCdr7woBYAkZKk9/vfNWXpfwuttK8QLrie -KfE9xqCW72yy3d6k3yMDwd0fIVjvAORuAJBrvKKAPN/+FM6O2h6hpEniDxHJa6hd -peXO+8QmSRd2SfkwdxYFsgklEOflrY1r4c6XrkWkyS3+q22p6ZEIYdWtbnZeOm0q -Q8mDuzkk8dScY3MD2FFAHDp8M7ePTprdfFPisXU0sbyah/aZ+0siBwsW7bjywZHb -GOp68CpPCXw4tvBlxE2neIfEEtpGjILC6uke3wxycJsG07ucrg5z2JB7SigDzf8A -4UtoXkfYf7b8R/2N5vmf2R/aJ+ybd+/Zt2525993fOea9IoooAKKKKACiiigAooo -oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooo -oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooo -oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooo -oAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooo -oAKKKKACiiigAooooAKKKKACiiigAooooA//2Q== -=ao7I ------END PGP ARMORED FILE----- diff --git a/doc/samplekeys.asc b/doc/samplekeys.asc deleted file mode 100644 index 04599e895..000000000 --- a/doc/samplekeys.asc +++ /dev/null @@ -1,624 +0,0 @@ - - pub 1024D/621CC013 1998-07-07 Werner Koch - uid Werner Koch - sub 1536g/ADF6A6E1 1999-02-20 [expires: 2002-11-01] - - pub 1024D/5B0358A2 1999-03-15 Werner Koch - - pub 4096R/99242560 2002-01-28 David M. Shaw - sub 2048g/1643B926 2002-01-28 [expires: 2012-01-26] - - pub 1024D/B2D7795E 2001-01-04 - uid Philip R. Zimmermann - uid Philip R. Zimmermann - uid [image of size 3457] - sub 3072g/A8E92834 2001-01-04 - - pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) - - ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.0.6e-cvs (GNU/Linux) - -mQGiBDWiIPMRBAC2D3tFzbD48fop00PiM8+du2SZ6HOgYVopP+Gtm2WBDUjkFwDC -kw0DL9pS3iNIunHgfeuzDbm4R3lXTXjlmBxUjNVBkX4ZmRESEoaN26fsFWb1RvBg -VcKcN+DyY4GFP9LQ8JyWifAc1+o9HnE0k40D52lBLXSf7v4JhvY9NtfE8wCg4oXT -aCiRFPSClIko3RqJkrnpv1cEAKx32rnEog5mPPs8mW1Sy5yulCTKrbCL9S7wINtM -cF6FJNm2PB97Vy+FGfGHKEl2KM8AC6t3CKOVGSdKvTn+9ZiPFiytohUmFaZaU19F -jApQHZBrdx4FW+8bToRrdZhCnkUIzWdi7XlEK0Qw/TE0Pl8XLxDdCKQI+JASXvW0 -eh8wA/4nnAphsEpR1GWa4Kls7+/KO/V8Q3XLi3ZeItny+5MBDn/Y7A3u4RrNu8q3 -SRJgBvUBfUzhfSyRZhNQqpIFvhKSsbGNNVo5tARSQdUe4j1GlLRUWcWKn4F2q5j4 -6pdogYvnFYy8xrvuAUqI1QD4D/4YXJyKMH+DOHnT4iAjD9RlY7QaV2VybmVyIEtv -Y2ggPHdrQGdudXBnLm9yZz6IRgQQEQIABgUCOdeQqgAKCRBd4kmWWwNYouphAKDJ -YHGt9SdQTwe0FODk/1aOJap13QCdF/Y83Ku5blk0l7p9H8cicg+JPySIVwQTEQIA -FwUCOhpQtgULBwoDBAMVAwIDFgIBAheAAAoJEGx+4bhiHMATm7kAoMBBag8scWbt -Xcs7lhrjQOIzd2onAJ4oIuIPWnArE+6EOQBk8vceoMb/lbQhV2VybmVyIEtvY2gg -PHdlcm5lci5rb2NoQGd1dWcuZGU+iQFfAwUQNaInDgNvEbj/PqoLEAMH3AUfSLqa -afqtZgoV6kmFfKETjBapE8kCe9+iJZSe0OnhohDKzqU5GKBVchajiThIr8Ufn1if -MXvnvyqtNlb9FwDRsiomrOpqqw51NgQVrj1wKO8ucFbg55smUtNSz+eeZTQVYpbw -7DAv6kK7x3t8tJKeCAGytRDBt6m7DRwmhy0U8DPlPWdAmJ5ApWwdoI3AvZ27Rd58 -6AXm6MHWMrWrenhTKwX2ERwFH2W0TdMev6K/iO1leYLU/hq31bksVaxi7CvRTfIl -xopIqnS//AYRZ7Yn+AVBnSEHX7flGsJk+CJawS/zsIdobpe1D7ceGKsEImxiGY6K -RUqgRqfo+FRVHWqVcTK2kC3fz1MGe/Jx4BfyFwc4Td2K4a8gsSBh6zeDDezlmYzt -tRfeObYGtfxZyF7FQVRAi4pbZwvfv0wVdHxNvGlXGuxFgT/iMdkFiQB1AwUQNaN3 -FB0Z9MEMmFelAQE98wL/RzGj7jFhUCmUU7SchjKNCA/sPw7S5/M+wjAXeS9vtvkU -02N+n4MCE3obQc4iCQvcaxa0J8flQdqWL6a00UgoOlO2v4X+U+lk/c4/POwtlLiF -hOqYyzU78AKrxrEqACKViEYEEBECAAYFAjvjfbkACgkQH+0kqpJl+vsaiQCdF17S -Tq6vDmL904W0mD0m3m66ZOkAnjXUF+7U4s14zHRn+oR/DTG+yKI8iEYEEBECAAYF -AjnPUbEACgkQNfZhfFE679kjigCfcLUFU4HwC2iqbCUxcIHoCg2xFPcAn2x8nlUi -2uXjwgT2OA5sifc3XQq2iEYEEBECAAYFAjlqZ8EACgkQRxYpGYKVe2ahiACdHELx -vEtYuKiUAuP7N2p6PB+s6R8AniXxK1c1qIsyN8S3D4hv5ygXQApOiEYEEBECAAYF -Ajiy8lYACgkQSBf5O8XogRIOMACgpDCmckpZHGgzyzgdGb/q+YrAtPEAnjDbzLSt -tKJxIQDqVQwZf/qZOF9HiEYEEBECAAYFAjbtTgsACgkQXeJJllsDWKJ8mgCgsSwb -LXqFX8J+YOS7oPUIFQjFe+kAn0YECl0L/c5eKDuwGtUJY5vcxDNwiD8DBRA3blnc -ZKpl/bHMA6oRAulaAJ9dQ/nN1j/mr7DdbZiVjg70OC1cSwCgsn1NrNKqoCoCU3TP -mcjvDFxoWS+IWwQTEQIAGwUCNs8JNwUJCCCxRAMLCgMDFQMCAxYCAQIXgAAKCRBs -fuG4YhzAE2kgAJ92JKU+YcYHoRhX51+4s3fnPIyNEgCfaiWeoyb15xgdO6etGiD2 -MYCWy5m5AY0ENs8HCBAGAPc1hCpuXmaTDAUbIqS9CFHkihMnilIwAV+L2Dbq5eOP -toemPKx5+6xtZfzzY9/VCVwZCxY9Y5PEN9r/twUA478L/FOXv5E4BpX+4R91klt/ -EZGcNfDl2Ar56FpGJ3iLg4+vxx9m1TV5k2nNOUZAVD1L+MoapWhaZFXLMChrhDUc -bo7/1Fr1Rfv9j/LkkIJJhqf3G8HzE5AvCQVSywUayYZdbmqdiY2bklZJVFAXs1X9 -zSTGoFc8eOxz6i1ZeMq+GwADBgX/T7o5R+SOTlJ72ac/g121f1kFX1dbRkQq2pCI -95qTehp1AxdSwG3ur2slFCfi8ZDNUqkFXJrsv5mh1yfqq7zS5T6lGT5lOXCDZbAO -2wqNZY1VKeeCdcvD2VMeh8XxJfy8y1ZK/iE1p8qnokYpA3nFH+JIsdrXk5ceiN3n -Kk+aDamUkV1sJzeEm5F7QHe60oBKbVGIUF4EhGq6daVyeCeK4KhWuPYyiEgyaq5/ -xJZbR3uRcdW6X5AiGJWJOOQoGvWziEwEGBECAAwFAjbPBwgFCQbzyQAACgkQbH7h -uGIcwBN5FQCggakIOYzLX3lNq2WWgcAkSNm7kpoAnA69b3z2E5vxyD3bhggVUDX7 -j8hrmQGiBDbtSOkRBACURhKnGIFyXIeX61GAY9hJA5FgG4UalV55ohdz4whBgDzD -GLE3XYlO8HCn4ggKilll6MOwY0yZeg6PEU9Y3SqTzpQSV6qj2M7MgcS8xOpi6bNC -u0iyZUik0KklUXMdI8e/CVmBpQJT9CofbD1dsP6z4dC6z3jil0+5Wbfw6yIXzwCg -y/7Fagq5mN0H760/JEiiXILS1n0D/3H26lTaxo1vGput9Td1FQN7Vn6YDP0/To5i -psOODROV3zyUwF5QleY+8zTFJA3qD5KxRfA726WELOF1mB6Mw44UdkPniOoGdMH5 -oSx6qnNnlVZBBu3U+e1qfQwLQjHu0WX4Z2q00DKpWLThGv7Loh5NKi6OfTbMhfHo -evCAzQnmA/wKc6J8GqthENThKXxZaei3Ep0t+PlBmbUzuAYCXZhI6/0KyD6emyQ7 -LYIaPv9qEfMkMLhxicG0v/AAwOCBRKS3bkqc6wAYaO0bjUHJvem3HkWPux82t83+ -6YPyRnVjm/mwt0uEyKSvt7Md2DVrO3lEcKRkRHiYuf0nonPhl5Rs5bQaV2VybmVy -IEtvY2ggPHdrQGdudXBnLm9yZz6IWwQTEQIAGwUCNxrPkAUJDMl8gAMLCgMDFQMC -AxYCAQIXgAAKCRBd4kmWWwNYol3CAJ47+zjeQIsMwiwcJvYfcsLn1yULlQCfUTKu -paT6pw5culAis/pBrdBKZciIRgQQEQIABgUCNxrRPQAKCRBsfuG4YhzAE4X0AJ43 -A7wbYbR6LTfPSD+fdBkimNvO8QCdFoSpfY+4FsKVagg/qH3KtGUARtSJAHUDBRA3 -GtFjHRn0wQyYV6UBAdGuAv9AM0o9XkmBbOLLNse8Qp9MjD8TC/oSXYxp1W9AjyRs -83iqQ+vaZlbA/O5z2ud4I9DV4vwA50Lz5nLFbPHa+yuT8VxTl2icw5u9rZy3iSok -3rGXzGOzENMmEFIVFqIEmPGIRgQQEQIABgUCNxrRowAKCRBot6uJV1SNzS34AKCE -rfsfa9Nh5deJ40nxpmSI8lK17gCfRYcU6i1B1Nbg2Zkkr5SqTnBtaWCIRgQQEQIA -BgUCN08fXQAKCRD27t8gGEvE2S2+AJ4udDl47EAnP4K+RvsWcv8qjqpzlgCeOFZZ -blzWjeie8oQfYl7bBBrxPqKIRgQQEQIABgUCN6cm/gAKCRCYNGXbIUOUIn7JAJ9L -LXMt+0R8u4gdmxQeKz1TQyWoswCfYQh/tMjUzk4rKxBy4UtELnwJ9x+IRQQQEQIA -BgUCN+FBMwAKCRA2Z2DxfS7XiHnnAJ93k5kJXcvwCGLhBb8mhdRT5kHQzQCY97a7 -DtZgMs7O/jwfvq2bpzL3nohGBBARAgAGBQI4KmIPAAoJEOPyWFQSjw55Gx0An0Ue -6lGJsE8ba3/hcOoX7GIwsv/wAJ9XkXZJHQhMTiT8L6xxLWcnUplQNYhGBBARAgAG -BQI4PoQFAAoJEDy4klAvo7wt7aQAn0CBYasE7gZZZ7lDpIDGuq7pV/v2AKCpZLWB -dON2nqkq1MOIkvxNo+I8BIhGBBARAgAGBQI46dJKAAoJEE3WcVrMxTeC+m8AoMKb -rmutaoALaWkjmB1+31rex+O5AKCp/Ki0pDcTZBmCDd3jd9cE6u0qjIhGBBARAgAG -BQI5Kja7AAoJEIG908QOH5t5ZekAn2uNClagsId37o8FesrYI0S8x+gNAJ93DOXd -KR8kjoD7ft0rs04pj9rlE4hGBBARAgAGBQI5KnG3AAoJED4gT8kqkIcsTW8AoNSH -nitUbZpwTUzEHSxC+nfZRvIGAJ9bPJqRoloYIvsBZWiN5Log3A4zH4hGBBARAgAG -BQI5LjG8AAoJED2K8bIJrApqqE0AoL3BDQMJ3/ZQwwQq3I4qZvlGOFYcAJwNEQDy -LsZGAt3GHJeBpJGwAxm+v4g/AwUQOS4q0J6y5PNpFshzEQLgTACgilmE66iRYTSJ -nkJZPl+W9cXNaGsAmgM6Uf8sn9EnYbnThlMHgGx5E6KfiEYEEBECAAYFAjksKEYA -CgkQs+2ENZ0bx8g7MwCfX/8HTK842/fulLtfElcW0RW9a8wAn18MUa7KTA79a6EV -Krqa3qNLt2v1iQEcBBABAQAGBQI5Kv6BAAoJEAWcfuLwhsu1Iz8H/3KXi/WE7Oe1 -Huw2h0A1JGyl+zKI23po+RenuSKC1NX821NRyrIN1U6CKzyBdMKeiWd4/bNaD9vQ -Ft3SKK4CgjRqs694TV1ue1c5+iY3TtjTSR2vAyxACScl6csIm4TAJXuSMDSeuE17 -1QsXSJa5CEXBSnHTOPd5B+47hAr+0G16fgWFH9WLjZNA8s3JBZNg69hQSDiZC1FI -oP0SuBUJk47hmZpjIzNGKGRxWzfK82tAk3eS1smnq+V1LvDLWJXkG/XVJeX5SsT6 -WyIBcXsq9eMk/t8mDyVxE5SbCFu7TNIMEL8f49bEQk77xf+t/5nzDOY1iA/q2H1l -o/0ncauofCyJARUDBRA5Lpn1EcKB1QApK4EBARqvB/9Nk6Edg2z5stFyag8CqlOc -iVURGdZpH/kR/OtlZkIHva4fgF9chC2F/wd2rMfoG/Begl1jvt4aOAR2Eq/qECHl -kWeMIMr4yWVJqhYg7WT+dir2MsZOcS5FRpzMyVDuauY/KmBQKE7Eg1J7mVI9CgRZ -TvkkQusDh85pUhOla7b2n4QLCrbicLpC/MBlHE1nfcxDEiYxwA+rJSTnLg8wI+7q -OX6fqjd3zV3LgKd9HwFZ7ws8Hgaog35HJpIFfev/cOpcFMOl42cQxZII45wcQT4j -I32lwSjAOMWYMbAUSIEjDs1Sfowkcu0cvtTZTDly0UvTJjQ+OjDe0+oJOofrmKuf -iQCVAwUQOUX4pCt4HizjmvPpAQE86gP/Yf56qY6Qe5nCOa1ex73/ZMPvOELl7yKT -ohPZRxPWHsy63Ff/CyC6A6dPZfNiUdfxYO4BsitGh76unRmeFjf/awwWjfOqvx62 -bYpWMb7E4QQt2KesNjgK/yNaVHPGtsKa4E2gWo/+rWQHgfq14igx8w+KOoyqRhUZ -N019GyLMN+qJAJUDBRA5LpoJe390GVLRyrEBAUxgA/0dWRrv3KBVNJXHtYjDlHH1 -zBh+x7i8TI2aAPEN2bz3zWI9XWiknNudVm7xtsp61iMJ/xXvlD0Jasxhk8/JHRPa -wNO8kWR3UfKYsnIR7WBxrlNNBic3MTMrUCyRszLqGA2d8nJqHQ5HBNkhT3sZJFzm -0EshmypsmN5bbkTquvTYiYhGBBARAgAGBQI5Mb/DAAoJEL1YtpICkSxThskAoKv3 -X28MpPW09UhfjuQ9rexmubuRAJ9EJLu2mUpM7BdXKi10HmC0ui4m/ohMBBARAgAM -BQI5Ln4fBQMJZ1MAAAoJENeMvOVmp0sxywsAoLtChkYFfkT2YJGGmfrW24orSShr -AJ97CvRlJ3C5VFlnME/r3feAmv4Di4hGBBARAgAGBQI5So3XAAoJEFy3t/Kgqlwe -CicAoO+D5CGVRJIto2n33aXYU1yuxhiEAKC++kE+wyq5BAbi8YX0BAUxfRXtmokA -lQMFEDljXQjvbYJB8IEZXQEB1d0D/iNMwOG2MJMrziMiIokV6UvbgqtG3AEltb5E -8CGTS3wO8cbqrx+yIv3ZKLn3HAR8vt5KRkQe7qxi/hFaIpPuMXky85TrbXyZGvib -Y0siHFyrAem/jP/EVU04Bl59nLbBRF3vU6nQP8MRn6v49p66oDtAAPNRQcmFjz+s -XGMZfFBAiEYEEBECAAYFAjlqA18ACgkQh9ag3dpKERaGCQCguc0ldTZL7+j6Avlp -5VIV1Cn+DC0AoI6PBkWkwmfFeNbWPgRZxOuQ+uZoiEYEEBECAAYFAjnKOwoACgkQ -K7tDpvCerwpRBACdF1rqU4MpphmY3GWtamI9yWKCEs0An2weHB1LSl/xnAeK+Lfs -mOobg2vKiEYEEBECAAYFAjnL/fEACgkQMsNbgEe6k1dzowCfQuX1VDigeNBsCcxK -vdmPU54QyhwAoKqychYr/hLHqQgfVU2sETcOY/YTiEYEEBECAAYFAjnKnW8ACgkQ -NfZhfFE679nDAQCcD20GISMXSvMu1f95S7nZipLmUbEAn3LITRjm7w/b3uqAgmgj -KeAQqH9OiEYEEBECAAYFAjnLMiYACgkQUaz2rXW+gJep8gCgvcTvQjtCjp2vPCQ+ -9LvriWkgryYAoLWJ/1lhi6jPLY6Nlm4NVrFG+WzviEYEEBECAAYFAjnM3EcACgkQ -3nqvbpTAnH+xDgCfU3V2BpK9VFMI8d0P/RQ7qDPU5a0AniMxEJFV0F7OySIez+aX -KlFLHYIFiEYEEBECAAYFAjnPDvUACgkQC2MP3CMjttIBqACfc9B562R+9fgL+PV+ -VGjASJzP85MAn1rJQVVVQSLrP6SdHHbxtbPr41HGiEYEEBECAAYFAjnPykwACgkQ -E9QuGvaKeLzbXQCgokt9SjQxh7tIOg9oJ+LckPQ6ua0An0cbFCxj+1YPvMXEG2Sb -wMe7XmeuiEYEEBECAAYFAjnKizMACgkQF6ZBbfeUj9otwQCfUxI+VUJNs6D4216e -mqnxhvYn3N4AoJFV214unHmOO+IieX463D7tMG0niQEVAwUQOcqYWBpPhku+30gx -AQEmKQgAmnTtDlJoTHIJVpMR3WXl5aiRmy+FOlUvrXjrtWhYM9YZS91t4QIgnMB2 -AptITQYBcQ4FJ7jYRbpk8zig0i0GyYDjD3lmrE2+XgluhxO9qSAGuXsOUQsuq6/f -Q0WqbnBtUQZ/CJW0CydpFfE5x8uA1TC8wrGCfPRcmfVrc8e93UtKSwWWgo4xOkiJ -QXT0s5V/iR09pUduScTpgjLjZonAzR2NKojay2Php27GHBO/HU6Rb2ZGOVZfIsdd -Fj9M9YNwO8L/qjnUNv48igA1yxYxybO/iDaK/6M0LjKWckPOJhUI2bDU12jpe7jA -ui2/FwdRBLCZK9L86AcKigUfSSGXiohGBBARAgAGBQI5zFCsAAoJECDmcbCsS9oo -iBoAmweFLJPySJaIGv2aMspXbPlppl2aAJ9faAb7oaICLW2zdvqraYpRo+09BohG -BBARAgAGBQI50N/bAAoJEG8ji8JP2loMxJMAnRXmIq/pekWpI5w7hJg9NU6yUCrg -AJ0XyfLgd6v6nGyRwQpx6Aza7iuIfIhGBBARAgAGBQI50gqvAAoJEL/hIGVrIUia -opoAnjLR00eLkd2TWTNleRoUY6qQTgRsAKCQoNcdBZYYtsfF+uGIjkNwuDXQhYhG -BBARAgAGBQI5zndTAAoJEOFd2FexXDfRWIIAn2Jx1qya4qH5U6r8drlhAPhXAOh3 -AJ9i0WYu9oGWjEAcmN7qVtzqamIKOohGBBARAgAGBQI5yjg1AAoJEPC/nJckksmN -3fcAn07g5lMJoyO8DmpDm8oTuasN5YZCAJ0UnrVLSJw4GM71RFkRKixzIObuj4hG -BBARAgAGBQI51EpUAAoJECnvS20UZCjxm9wAn24zywUnORPNEQlnivNU4un91BQW -AJ4u7ej3KRtOXR6QfKTeN5ZY4Cm4lYhGBBARAgAGBQI51EpaAAoJEH6Lq0fkCp16 -ShoAnj9kolr8EMCMutP7vkv8MS/wsiH7AKCzbC4C1+igyQ0Lm3I9FyCl0VVbxYhG -BBARAgAGBQI51EpYAAoJEPz0IFPX+kUSTLcAoIGt9RQkhVgz3lEUA1zn5D9W0cYt -AJ9iyirYXCX63tNY3cqMg6gWQA0+cYhGBBARAgAGBQI54GWRAAoJEJ/Oxj5lCIC0 -w4IAnjVo0u/3WFb53v2pVwetMugjH9qeAJ4u1VsvgSUTtkS/8o6+Bx7sDjs5dohG -BBARAgAGBQI5z6dKAAoJEJFazEWo9ML9kc4AniStFstXJoQolnooDIMzDzS+ADr3 -AKCkE4tq6WjxfLSV0MHIFLvXg7If2YhGBBARAgAGBQI52lYiAAoJECYzIbZBaZVr -nfEAoPSPjJ2qNNhaTN5bz2omXssehuDrAJ4x3M0HsV3vg3YI6xToTg8bTiuBBohG -BBARAgAGBQI5zvUmAAoJEHMKa4Nqhe7d53MAoLQ4MuRp2VN91lOciN2/oIppP/P4 -AKDDSwJvp04Dml0S4+9D/xcBwqKVY4kAlQMFEDnQ+N2248PGUGh5LQEBw1cD/0XW -PC0AvGn5xQpjCUFSYvpx4EuUnnOMukKEYnqzFs2wtKCO8Pbb3IyHJ6VGUftYCemM -L1OL8NQgw6AdiHqWm/lKXhbe1vbO+3+EoHbDyIdne4RFK4mulRBUFx/yovwkg9z5 -EWJVsrzS/fUuAg5kX/c+hdRtdDi8QYQjPSIwLWrkiEYEEBECAAYFAjgUDgoACgkQ -YAeQgHPH80+3bgCfWl/hh0/ZW4u4OEW1KtIOiU7OjosAnRIisuZdS0ht51jdjrbI -Uq7lRXDhiEYEEBECAAYFAjrBCNIACgkQt1anjIgqbEvnSACbBze4BqULiimEcIUM -4lkErCnDocwAn18tJqdhoZgyD0B0ouLbfgJCJplKiEYEEBECAAYFAjrB0SMACgkQ -0vCiU5+ISsi/SgCfar7RT9JPw/V1MO0rREx2SfDSIfoAoNcgtmpLWgU3kbf8wb4A -ESQIu30xiQEVAwUQOS2iwwFVuuKglNolAQH1NggAjNw4Cg/0z+6FqCv5b/opI0E3 -oc2Z1wh+ovL6jsA9hKiq2MiQ0bdd2GmjgiojVNE5wYYm1DYjAnLVUMgKuMNQDCSn -pFe7jghGHJZgnyT3CG2X0TdiN1FNGt1MQwyetIUH/KSIHWPf70OHQvw9BRvkHZa0 -9bk9N+WTrDzyhKuZmbLBN2O+wC19O4s64bk39+SsZZ8iDUuMONCg8HTJ2JF1aRH2 -i1wpXoWpQ6UXnVPXIWmA31PdzsJ6j/mDgnlVbH0rL24po9kB3ig2IA16rKrMC8H5 -mKnM9lvA2VDBr/0WX7LGlscRKD9NXlNjoL7a+CSO7TxLnAdq3+Yi+sQJPINro4kB -GQQQAQEABgUCOS2T2gAKCRCVYGGm3ZNBOfDAB+MGwzHvzV0zSoFSWevq9l+prNU0 -yHKdv39AAONHvo8e/AsNTltPk3LKiXdkKxkGl6e7UkHawJoOgd+8DCmUStVv3Srd -POSovqqce6KC9UfsmbLOf18mx7bP5OYpeTleF1fvBMvFhW9jrmTKFpO22uLScpmo -qXmz0J4/dOnrPmPP71gi4Y04AZE8DYtnARVUScEYiZCiLP00+QocjtkIJRLhNTYM -NW91oAW4KYz5Sz1wxyczyfSq03mLBBan9vr3G9WGzUCWpBDic45dpoX2osgImPjn -bRf/yQJ6+GKRT7UlMRFI5rWbK3JSBXOGvjNZlKQcG5uA5OM8zEpW0xbwiEYEEBEC -AAYFAjr1eYkACgkQ7A6vcTZ3gCW+HQCeM7uVjDTOpJequ0Z3BVeKA9V3OFcAnRZV -ML+f+ZmH5tx+BV1TgSlXOA2TiEYEEBECAAYFAjr1mvgACgkQLBigKrTF83/VqACe -M0Aik+REDgVsgu0cyR+2oXw808EAoJM0ojjxIgtWFWsCJUh/nyHQsleJiEYEEBEC -AAYFAjssp/UACgkQlTDIHyPR99S8oQCfdIzgvLTu4E2h5iZ6eSzt99ASFP4AnieH -MW2mdukyzJuddTiu1II1NksPiQEVAwUQO0HCUNImKUTOasbBAQFLZwgAkgMC/xim -skOjL/CxghgdkSWkDFdpEr3XYhzUdLesWgN4AM28mGZZKA9la7dXXRrKYkxhX8mp -L4C3Q9LnrafP+Zn1c8mTuNIxX86j7iZAIksoZ4D2csN8NSMYT9pKK6jZP1IOckCF -BBI0W/yMGUGulDitWj4TwIArf2xQkV73zMKYJFhW5mSjWDx//F1zrn+x1B0pNoZW -CPQ0gDLdEtnWO2x/aiocqkEorHwNfkWusHvEmx4MkarXPDZuLqumEWOpW6v4xOl4 -49Z9au384FST6xf9c6QjXngaSQAc3VcwC6AuTjbmiQ6+H6WGwjss5GzRNRg/LD8L -uqaKb12tkfrZmIhGBBARAgAGBQI7RW00AAoJEOd14yTbQbOHdAsAmwXs1mCo2SJL -911EsKPE7/sgZJw4AJwO96IG44Gh+XlQnsqM0J2GnD8qp4hGBBARAgAGBQI7SxcH -AAoJEA6nVrUUSEP1OCcAn3HchOcEeuCeLzCYi1U7JwjsC9iEAKCoelaC999gohQn -O/x50vgUsskGJ4hGBBARAgAGBQI7Rdj9AAoJECP6tfsIFswbylQAnR3Ea24SlXoM -JbSnEOamFTuesu+CAJ0XOHaDol1jnHssyX917HZ8bZ94NohGBBARAgAGBQI7RfEO -AAoJECeGwkR/ikAX5soAn1tP8xYpXSQTPrTrcwaXK3m7wqLZAJ9G3yh6wapy2NZL -D5ZgeEPwDrGggohGBBARAgAGBQI7ScGaAAoJEFCP02O8k2g5qqQAnjyt7fxDX7sa -l/ppjksajqFlOCmBAKDHqKC5h3R0jNUR95ZhwwVrynKFJYhGBBARAgAGBQI7TBe1 -AAoJENcNX1hgPNB4c0wAn0/S027VD6x7S2FBGyiD3GP4FC+iAJwNtcPDbyiugiNn -SDQnSmSxSBbubYhGBBARAgAGBQI7SCdaAAoJENdZXTdLcpYlWi8AnRLlddW/rueL -z6igUbjJq5ATAX1kAJ4l9Ej4Mw3WpASDoEQS8SNMpaj1AYhGBBARAgAGBQI7ShVN -AAoJEJYkg+FWYsc0dG4AnRx0d9Ti17jNFMLeigC/MCr+QSviAJ9kb2IuGhw1bUi1 -KINM8q2bQQAaqohGBBARAgAGBQI7UblhAAoJEOQ7FTzLRn4nHrgAn2fkDVwZqjcN -olNGNE5LjdblbNXEAJ9Vy61tZ/s0H/l7mZOigbreJDIhGYhGBBARAgAGBQI7V0Jb -AAoJEHkWLzb39qrZbrEAoKFjjHUPomPUu1gAnuk2qqm1p3CZAKDtB/PvqBb2C0rV -mmfpg1pXj/nU2IhGBBARAgAGBQI7ZzpQAAoJEMALDTYh5T69uBEAnjTka8BHWuhK -MmPW52PQJ7cmJ9tUAJ9zGIqA/3/nk1ZS0pgyLfnKPJvRQYhGBBARAgAGBQI7SZO8 -AAoJEHgz7PG1REgVUUkAn35FdEAplXfFwa+ENMPRNagzdA8LAKCFTXbGeSjirdjM -21dFNIToh8S7NYkAlQMFEDwGr3MXPHHnE9mHPQEBv60D/iZt13tGPf3PqtZDQqqB -Ej7TlHtqmRWJ41qETo5ix0CHCw0OsDF1Y1kzjwfax5Fte49YLGVlcfYhldAQ+D3q -ha0MceKQPtVFg0rcBij72QcMznYXSDtEYD7TAlNtcAPCr/VjHQBziBN6dAok2Tt8 -sztsdcwJfk+9LANB2vX2qaJNiEYEEBECAAYFAjxw4+EACgkQGM0lpSLzivOYuACe -IyfkTvjVxQnVP21FOVKscS3n/Q0Ani/K4IFki5Uqe9zk5MYN3TI8mj2jiEYEEBEC -AAYFAjwlvGUACgkQLbySPj3b3eohlACfXuiyTRw8ObbNLCLAPQrAJGVjclQAn20M -uHHrNq77H1SgBw/Xn7fadKKwiEYEEBECAAYFAjtSxDgACgkQO/YJxouvzb1SXgCe -IKzHXwuDNHmz56JZApYo2QOFFUoAoLDQT7AFQT/vlXq1GkO+hKtzeuXfiEYEEBEC -AAYFAjwjtU4ACgkQRHJT9Ar9DKjy/QCffSBJW6EJF7eqTae4LxD8zPet6iEAoIWI -REsh6zjEbITlfWWGhWSrs5yYiQCVAwUQO4Hbo1Ks6y7TpCxhAQFTLwP/ZOBttIDu -MJPRxSNnJvNoSlstaYxqH42+33XtwxvUai2LCVIKHC8kgavSqn5psK+j9sVLqibn -PebK2QN8Xwid9ZG6FGF6c46T1STOhrhJyYcj4la7WBg1ggd70Q1gOn9OmzWtmYDu -7VoxTYhwG51IGrasgEOFzJrvb0hV5bzGc6iIRgQQEQIABgUCOomB3AAKCRBiiATb -IPxs9iv7AKCaonJLi5A4q952Lf1IAZSWbvaV6wCgpq1Iw+gUkhgr2UX/7dKrBA/2 -hseIRgQQEQIABgUCPAgRzwAKCRBqWILfhEBGApEcAJ9RIFv5APNz7Z0xfXWl/fVH -PnUyrACfamdeFPVrHL101BILgIFOEUNbGXyIRgQQEQIABgUCPA6XmgAKCRCLup94 -YAy/5zEQAJ9W0yasRJlv6ClDJffKiJfQMyFQlgCeI1wR3sdVisKpHVpclKui+3cK -SECIRgQQEQIABgUCO5hEjgAKCRCQLb2RjDipCsToAJ0YYpBpdCpAuxlvsOCVqJFD -ha2mjgCeIVf0M4eRHrZSjzUNPegY0c31fOCIRgQQEQIABgUCPAui2wAKCRCqz7OG -IRtu7wv+AJwOBT2jCTvg4DmCK6ia3Ch+4RAwIgCghK9NjNrz+yqCYR0BBtLmrFwU -cHGIRgQQEQIABgUCPAf7VwAKCRDa0rBdXzwxhQUdAKCzI6mRsmewgoxBtCiMO2yw -DI0X/QCgqJLsS94ezwllI7uvWix2qO1qt0CIRgQQEQIABgUCPF2rOgAKCRDu8Ns0 -syEmAwy4AJ48w1kK9bn3eclkd3PEJ6DuHJsDTwCeNEq79cwbEEzUGX1mySe4QuPq -qwOIRgQQEQIABgUCPHFBegAKCRA6GqY1kJpUBuDEAJ4wQq/nnv52HnpLeS/Y/g0w -cp6+zQCdH5DVjozROk45axTNDiJrI+sTpZyIRgQQEQIABgUCPHN4gQAKCRCj4LnS -ejT63p/YAKCc9dxuOjoejjPjv4/bJBfE9Bb3AACeLS91AYIJCSvYhT7BI/FsNpim -WEyJARwEEAEBAAYFAjyFr5YACgkQEq14jk8L6rswwAgAmYoP9jbj4yzxZiLRwaT0 -v1di1Zz5ip862ETNkr8JQGu0F57+aSlECj3BPnc/A93AnEHvw12Xryb1bAZxgKNS -t5GowTTKCm0zUvwY+6HQ+T7R3VIOGzfkzV867tt7pO2QsS+4yYwvo9gVHczV9PSF -OeCGjme1Q3yoEp1/r6VvH0fi1JgkYoKFLw0UBuu+gv2XdeXY9FWXKHm/u88nsBSc -8PJ+B6I3u0/E7B2Pu29u8apY4VCtY4BUwoALBBjUYLFzEh/xJTi7qPD5NLZQSFog -6Z3aju+0MqYsrBiQpZpSiWBgPqxQwz/DZdUH0Y/wMNU19gsjkpy2+L6uAEQYfSIW -0IhGBBARAgAGBQI8tzrnAAoJEGNFXT5qgEC9YbsAoPZcSYh+baeE+o46yDhhBV5W -4VynAKCiJAby2fHjNyOANqOs+AbJ366jhYhGBBARAgAGBQI8f3SNAAoJEG3yVZ9B -pWcPTCAAoNRGmdH4SpTKSGMu22mHq5O5B4PMAJ9q8l/Td+8yLzQZKJV7DCD2o4+F -rIhGBBARAgAGBQI8lzY1AAoJEINou1lm+8GMz1UAn1e3vrSf7b0HHMO3NgHD4Zfx -2vbiAJ0bg3QKT2sa2j6RDsQ2SOjirPZunYhGBBARAgAGBQI8foHxAAoJEI47c57d -K8ydixoAnjC8sjBGNb/0bckMNegrZUgNFBXXAJsHnBic+JYFJxX5cAM0d3YVEM4Y -LIhGBBARAgAGBQI8lzQ5AAoJEKHoAnDadDOW1DQAn3Pb1VX9+0CLtOOHaAQX3weS -BT2cAJ4+TXEmmOpYYGzgT8pXZsjGyw42fIhGBBARAgAGBQI8gGO+AAoJENeDa2wM -2SDnmrUAn0WufO0MQO/wKk0PMZsgz3gq3GkjAKDGHpOyOl0Sr5L6UwmufJHmsTju -dokAlQMFEDyCLHLlFSglMxzaXQEBOCoD/1duqEnfsCjE+0B2pzKh9h3/IPi4dIaC -qlCTjDZ/tWU4xVGmaMfU1I6TVRDUtPBOt9XW4xdew+ntJNHd8E7g2fVjRSyQYLwZ -EQ/jG2jjowfAEUMJzQSPm2C6E8uIxuvD4gP4N3/mj4l1WHp8aexGhbeSqF9BbHYu -7ri93Tz3TdJ0iEYEExECAAYFAjyvU4gACgkQ6pxm6rn41tlvcACgjPRZmULJnaVf -apXamMzoPhtFAIkAnAuIhaMOKBqsiGzpWxkAkCUh1qJ+iEYEEBECAAYFAjyxOCwA -CgkQJXt5TsZsoD0UnACePAR8wWLkY8ZdEVwJyHOztnk91oMAnA1OZbHhmMwN+bYj -mazn9dYOddvqiEYEEBECAAYFAjyxjiwACgkQocWSfM5dzg6zaACfQky2IN8wQyZA -DGCZ384YlBgRzDEAn1Ivzmi/vBUfmlAUrk91d9q1EgUxiEYEEBECAAYFAjyxgtgA -CgkQeuuK7Uc6ScmBaQCfZ9ogU30ZhDBB0JZzo7dJBqq1pu0An2aNVIoZ9KKjEiLD -+HaKMha1Q8bPiEYEEBECAAYFAjyyhzcACgkQVlEzpFDUq7kRIACg3C8msuOW4fDW -M7McRIFT5AY/084AoKUUviYD6wezVBn4NUIOKMxM6Ay4iEYEEBECAAYFAjyz7a8A -CgkQJltdGckHlEx4bgCgzog5Mv7LJUDZziSGgv+hzyvkCR0Anic4FduBfWg/zuyB -kgOhT8QzyUmCmQILBDxUyXkBEACgg6vxNPigg9FQz14CkPtR/dEq3sCjK1r4+2oy -eoRno+pqZ6Z7ZfphgA/q5woweFAGOg17KD2WXegoQ5pXbFvP+w9j9zm3g59XzTRS -zZgScelTibPnKy6g8r8GDAY6IQraR6pxe4297/NznqvRvKpTt5g1XP5LyjVBsEv9 -HAYJE1vyy10qSQRtEz3QunUzfELNC4kiYNMZOnmgaFeW4APIIhWDtrrxqW3Ofjp1 -K4DAhqcnayrfvYbOtqh0sxJ246kvVc3Bc9pH6wDw/yub2deuPq6BZBLBJwrtu/20 -qD0nsZ9is/5j0aL1MZuVmr7xKYqeehyzJ1WdpJK52qng9natYedS+GefKDIw1Jq7 -ppQNWfVduTNITFTF0JswggjQuPqKT8Td5GCywQWN/kGHbp6EdybiUXZ+9fp4eek0 -UB5M+srSwbkF4hQ0mBrqlsaoji4CuXjc0c+Zx1D0pGfqqBCmvEV1tLul3U8h0TzR -4opUA8mLKegQp5cjh/dHz7zTPDxVgSr3blJ9FxI1Z69th/+jJj3q6joo3uW/5y8q -QCrzdSCzs+TDEWwucZtJIuIhTct8AMPY/Ayt+Pf9jXfI+xSQgz3r7Eu5o+rEu02/ -cthaOc4b3KYDtNkjLKszgiext1BYOq06R+Yyh2qgsg9azzkfudvvpwhCpJ7EOxcd -aP3bxwAGKbQlRGF2aWQgTS4gU2hhdyA8ZHNoYXdAamFiYmVyd29ja3kuY29tPokC -NAQTAQIAHgUCPFTJeQIbAwYLBwoDBAIDFQMCAxYCAQIeAQIXgAAKCRDbaY1xmSQl -YH7aD/wMq9ksbvAf9drjVP2u4rjZhLkHyc1zCp7rMXc5CdNgDNVyhl7+co/qMeQB -wk8SYEVedrZZ5Q7qjygjkKWp3qrLlw5PSydwCHaf5mlVg5E+5gt+RTkOi6FXdE/5 -c0IrIB+MNI3jt3IeOqEhITWcnjDk4gIxm4z43tvXvf/fY33ohrQknApN9uYISoEl -zYGgnEZqX6P3p/8FB2+27A3t/Eshr6lLvVNEMgOlBY8te9TFvMJTMeSJXIQVpvbz -/LMF8uEboWVzRC77y7RcD8p+JP9V97qZGsiOYB+2MPGEvAhEPHxQZAbaBF+eBFLz -ev+xmI36fHlFnAFiWikp0tYVLROgBhVGJUOJlDK+olfpxUqF+N8MfjeS01aHLy+Y -6rkzC26AC/9j+Adka9mBXEiiA1vQcBfO4U45QhgDAl00yUW1gV4oNGZ9YqslOhS/ -VHB61CjWwjnV3Jwkhscxux3rjj6TAwn5QmoO9kr3CqH1rzQXxTVruCJuwyuI6aNe -ywINoubgDhqhOCPfqyzgdxfp5UAhy54ge9dqjfgHI2Q3WxxhD3mCdYgN89GZNpuH -2lJkJZrRl7BimjqDeTlKYscZ1anrRgRpSoFDdUcMncySzW6cB1WSImj1aNWpq58F -xoJWcTy6lNesINeRjZ/r1eJBeN55P8+7DKGIsGkpftsqgXAqVYhGBBARAgAGBQI8 -WhCrAAoJEM3PhoWgyT97OYoAnRFHu9zcFMaNxojhWfZSlc32F8P3AJ4wp9uyTSnJ -pCDW7b4lcyUEX+fMiYkBFQMFEDxaMf7/7ryp5VOhtwEBMsMH/1O0rOOp5nFiivB6 -9+IbPSc0lxeLjPfmb/wQArJXWXZsWDbBuby3yL5+wwwMFyLLDGV/kPiC6qPHfC21 -oI7sui/TgBe5XblSkx19wAUgyuHrAw/YJTgqhXKmaZFgkcVKhFcc81HU1w7HiGvM -oWA+4VMFHdqKmGsqYkegvfroYWsxbDxbQ1OQ4GHVwJ8pHYVdfWX5xKTRjuKTC1GH -esfA4lorrs/zC/clQuJHMV/TrE9OyvP39vq5zBbG5iOerU/VO4w96yxiHoA2J4YD -SSmEZaCTqjleH1u6Jt/YrL41RaRBayNOoyF/AM6rrmai7agTlutY5kjMjWyZ4YNp -za3E4Q+IRgQQEQIABgUCPF2uXwAKCRC98g3l6mjvU3yBAJ92Uc/XTOt69hteH6JT -CvcFJE3NEACdG1gNdn1xkCU4cIjx4NZJty4vFF+IRgQQEQIABgUCPFyBgwAKCRDq -vxOyCxdw2+H+AJ4/oSxuFQVqj1SS3Z6nufW+4UKpxgCfUFd5h+48RyHC4prnHd2X -wTwDFYaIRgQQEQIABgUCPF7gdAAKCRCc69apC10naM32AKCypWJPQ+Y7y8odeJfa -MsjZgrN+XgCff6aipzB501CUUc/PlaKhL3KanVWIRgQQEQIABgUCPGBsXgAKCRDa -2nnNeIo/TL/wAJ9fXFgw4gF89C0G22XZBFgddadIJACeP8RBT6kShayJrX1TK6SG -o3aw3GaIRgQQEQIABgUCPH0qxgAKCRDWFJDobGH8qhA3AJ9QBuhppkcU1dO+qUDE -FDmeKGlJeQCeNIHejRJbsqRlsJjWKhU0xDW6TKaIRgQQEQIABgUCPJfc9wAKCRAH -lNKuLBMRcSkdAKCKG/h17odvnPFMdJD2/MofAmLt/wCePQBItnFwcWsaoECtHVhA -Xkor806IRgQQEQIABgUCPJ9y1AAKCRCDaLtZZvvBjN43AKCazWmPGOA8Q0oUrjF4 -QvOUFM/bDACdHDw6m42VYtjIGqZGudhZiam3PBuIRgQQEQIABgUCPL9PngAKCRBE -slvUW9U99zyHAJ45DoDcb7HPXjgOAv00OHNIvDheMwCgsd3fo9m9BHyyxWz8QrCT -0aLAcv2IRgQQEQIABgUCPF4i7wAKCRAIBXUxEzAHMTr/AJ44sNlp+qn9bVY56sXE -3/iTZ+bTIgCeM16g9RACeNezFD2z+1EzCg852Oq5Ag0EPFTLBBAIAO5SrjR8+omG -/tqQGW8a46eQB1fOqW7VSUAVqRlpBixERm+sNoWEy/GF6+yYLXgZstWv/peWWI52 -RUPOtN3mUQtYPv5K67lpn4icRPx7R1XFUg1MVzSYhOuw6UnRj3/InCMd3PdV5Lov -Yn0t1TEo9Xs1i5ufzmBdbrU0OUIsK7807mgrPI1g1M8SO+xXM0GEBC7g5h3r3XuC -nuujHlgiWm7PTkOoutb7qya49VkEPab1zs3G3aEBbQBf7xivNq569KeXA8nrN0uZ -QiguJyIb6JB6LQn+t2FFOmnxvTi6fwEpXKdodtb5rQ6e8UoOg+yL5+XB7R5wbwoR -ur40PSDuYHcAAwUIAJzRe8+VXFdNC22EMTdb1++4isCdWhGVUmDKyZ77YbSTzOWp -QLDkEUXvOaYGbAX3dsYCmw2RbEGj3ovp+fZzD08ZevGLK2DlmgXvSEZxCgWCB0lc -AwBrBHccjioKYTTu3ECnKUVnXqovRUNdXFlS2a0qgoZk/WermBiw2mysAIWJek6x -ENifTszOfOiwEWR2/JtjDnBq5Wvl2WWp54xFX2nouaJ/CLoTi2pcf78e+Atai4vQ -dXyPycgrCZTELo5A66c/NIcCMmr7rSwfU3UGZ/E7jai/5u3KVNWDGzSGv9TsNgoq -O864a/xb01+CoDGhqurpMe6lgw2zBPegReeyDLSJAiIEGAECAAwFAjxUywQFCRLM -AwAACgkQ22mNcZkkJWDxrA/+NILMckL+DPARXz4JzxDmJUhAcKYm6/l0Xau6vfJ9 -xfWZV4yR6u+EYV+mqLS9dMKXjG+n3BSoZmjLvDYceD1D/foddSOxMJjHi59qaxv7 -Em7IAmOLbBFtPDWw83F3Y+vir3pKROpWJjmuDkUExDg8fNXfUfA8XKlAmB2J/omD -GxA5wWZh4D3OYZBrwTY9hfnRrOJ9Igb8RUgaE0sx2/V5LBt/3KvA3VufTHCcNf50 -8jdpCyLxozaknlftj9qHoeTUSQB7PV+VvmWq/rKr5Rw2tXtI6tkqzIVnTg9aoE19 -wcxcroVltyCS3XMhRKejbAvy9niXZFsHJU9cYRL5vCxLAdtZ3RNlDaSIzlHHRbxJ -2GvOA4vGaSLxL54BuqvbZuSteA12WEHM7Dfq6zl4E2H8WxLgs6RQoNQ2WkUJlpF3 -MsM6OxdmFIMNZxXvU5SKyyYF2XI4PoaN1DZqrla/qjVdSM2ApBOiO9Cf0N37lzn1 -XTNldCUE2lnwTlBaMMFTcsyOV0pfE08LJbBjfK6BABgUd9ycIQcuk5XYRK50daby -DlbdJJBl2xKiCGDjb37HXdiyBWVH8noIfKBQiTQ5ijmyp7lcmR+d0N24E59Og+U3 -QWgivbrFalHviWdSuFS8vttJEogami5Hpd+Ne6Pm6naS91LvIF8tW7DocqPZu/bo -PKKZAaIEOlToJxEEAMJP+0akG7QQemN3cbXVC2RNZieKFkMF16eNhXYS+i2BFkCP -mHh7CmurW7/OrMYFimJgv/2P7lcMVyhYXbhvOxSYdexsNKK/5cTJA0PUZR3HjBVw -Rjms2OQCtfTpe5nM5u9cVc6+pGPouyR4+3DfEt/m6PyM83Q1/pgqeF8YgdFZAKD/ -RQCveEwrrNwD96C9ZEayb10l5wP/XxdZ6TO3kkl4rd95sk7/czB7jc7pU07GYykZ -Y5hOuGK/I5v9kuAt52pf4x5ccZ0augBFn6TFir9r3LmM1yK8P4TI34iI0M8PriuX -TQU1mSzHt2KMPz09shQsMK1SmmzYnSCTmKdH7LOKd/6MPIWeflQQcjas8UtRtdYc -lclynRQEAIGTMN16w+MRVdl1NFMuTSx+JYR1wEz/kak2zAyUrgDsDqKomhI0nik7 -lCro9g7AMWoaKvX1YR+hPIdbSTGKmdVu+rira8CFIgo6o0QkbGDgNMQp5x/fEJ0n -SRbx1VKiAcMf9z5Dj5EVCr/fVp6/ccPLbRhrLEAT3gFYiwqSFozKiGEEHxECACEF -AjpU8FsCBwAXDIARP8cyBB0j6epm3bUAnJ28Id903GEACgkQx0Y2ObLXeV5XuACg -odXarRcQ/wYmTKnT9XmWBvAGYEwAn1O1V/DaSGhpncs1Xa0g1KOPQCWntCJQaGls -aXAgUi4gWmltbWVybWFubiA8cHJ6QG1pdC5lZHU+iFUEEBECABUFAjpU6CcFCwkI -BwMCGQEFGwMAAAAACgkQx0Y2ObLXeV5WUQCfWWfTDHzSezrDawgN2Z4Qb7dHKooA -oJyVnm61utdRsdLr2e6QnV5Z0yjjiEYEEBECAAYFAjpU6RIACgkQY8tpHfrr1fwk -9wCeKbj4dzSi15Bms1R64xK6Ks1VSvsAoLVZckjuDAyrQCDPTuFCz7484kEyiEYE -EBECAAYFAjpXKG0ACgkQ14y85WanSzFQbQCg2uVT3G+jVR+rVXhAyVL/rQY6eqAA -ni6DbX27Nq7yZICgx1hCA5iXYMthiD8DBRA6WP4Y8CBzV/QUlSsRAkmdAKC3TfkS -Seh+poPFnMfW+LRuQJm8hgCdGacEslDd1xCQSYyYcSVbJEVFo0qIRgQQEQIABgUC -OlrmsgAKCRBnkE+tCnkWEPSUAKDpWL9v2omScHt8go1AkjlpBG0ZawCdE0H8UBXf -KW4QVCZHAoM8Ms1J4tiIRgQQEQIABgUCOleFogAKCRCsuxZLz3PsTI1gAJ0ZT2DR -scaui0RLxHsTRdhjQED8xgCgpx/V/+LCiztzXI1f0hGVIROAKV+IRgQQEQIABgUC -Oz6yWAAKCRAToEwwnJOdb4xJAJ91WRvsYFJrpNYIIRIUxvzJrTghPgCdHazYP0SQ -h4c5PNtAW1YHA5RkOPqIRgQQEQIABgUCO9lQJgAKCRAn/j6KBbyBDt7xAJ9IFWcl -fzF6xnhv1GpDKMCKeI4CQQCeLd0VBn/44vdt3H/8zzgKy5JlRS6IRgQQEQIABgUC -PFnfQQAKCRAqK7rFw91p1ajHAJ9w3XdBtInEbKaiJhIqe3lW1jNNVwCfevWYQ7j0 -B2t2N617SBsbbGkDg2+JARwEEAEBAAYFAjwuoDwACgkQLRPpBcN2PZPEKQf/R58v -HmZBgp7V8mgEKCJfX8TCOqJrNYJ8Xt81IH0bXv1k4gGXVwIaavHLHPcf31Hau2sQ -/hJm9KI71budHSBbWt4tnwNMFapI55xWWKPirM2TKnfoj+4kOOK4WuDjsTsjY0m4 -v9RE8XmocZHR53YkSyryPy2b/Ti3nQKsloUpC/kezmU8XBtP3cQfaZEEbnWKHQ+Y -mkc3nrbIraEINULNu5kP2T4scMRPe7D97vQR+6K2Vc5o20n942Pzb8u7BAgN43Bw -GAVS1KcoXT+lZrch5bLgF1u5liSsn6FsHLTpOL3SecqF88tiiM+4V+bklXjZuXbr -DU4Dl6gz/M4jF8TRiohGBBARAgAGBQI8O2hdAAoJEC27dr+t1MkzaFIAnRrW4uU4 -nwxzc2VHICu7nanqvIAAAJ9G4MFHT4y6ZR3prjQWjpWeQX3YYohGBBARAgAGBQI7 -hGqgAAoJEDDVfYbZ1NUsLgcAn1JmhZaKQYAe7Ah59k6xNPUpZRnvAJ4/uM3HHFiR -VhArbe1vx2BjqadO/ohKBBARAgAKBQI7ty0LAwUIeAAKCRA2ttlJOTQkckVDAJ9s -mqnAjJE/VqWMhmvWVcFKdeG0cACg29PJ3V37M+lx6Z1NWsUBaC5qhZmIRgQQEQIA -BgUCPCu1uQAKCRA/sA/yl51MG59IAJsGzjndfoJFTA2uzbQCMcWeLUFnWQCgtXP+ -MIuRVK6bCGdbN1WVg0wlGHSIRgQQEQIABgUCO7+BdwAKCRA/zigQ4zaxBsdMAJ9n -/toag3d/RKUMBrkYM5CahuSHwQCdEDx8+v9R85EdIXWIua+NAIxDJkSIRgQQEQIA -BgUCPCIDJwAKCRBH07jLEUv/CMmjAKDFe/lsmnnnNQzsAg732GEGBOkgxwCfdcvt -9mtxU64JWSdB7GGOGDyMSiyIRgQQEQIABgUCO8Nu2gAKCRBI1eMI/ua3cshMAJ9f -LUz4VSTpfEhJsNulV4FxsCWnkACgtKDn6Br3ncYiMCv0I1wKohwY9ciIRgQQEQIA -BgUCPESMCgAKCRBU3b7cPKNJbJ+fAJ9ith4zBy4mGX8PN2OSBxuHMBBYpwCeJSc1 -wP6OgatNXzZfgERyC5tG1JGIRgQQEQIABgUCPJq0qgAKCRBh+N6vwPlo3JqPAKCj -J+WVShKpcHEv42g7TIFRx19DJgCeJaEC5PHJEpAEpJ1R135pcuMUNoSIRgQQEQIA -BgUCO6bRVAAKCRBiGZ/lFRHt+Bj5AKCx28nM8btX06i1M+M0sl7rE1g30ACfbv5n -ZYUnvB/ltVlq4Upd+suWX+uIRgQQEQIABgUCO8vVQgAKCRBj+Xyfj9I1PDMIAJ4j -6Ysm4A7vidqast/lbQ82WEy68gCeN6Edwm8GttOsqHbI98LYMQ9aIAOIRgQQEQIA -BgUCO7EVnwAKCRBn2bOMCRwxhzkeAJ0aRutcMPoywIRtM+cSDgBFtpyP7ACgz/Q7 -VDZq9tNtnUVODuzQ9BbNFZGIRgQQEQIABgUCO/Hq/wAKCRBojqAxWqujDBYMAJ9e -4nWFjVYSK3NXt+XYG5ByewNKPACePp/Yd8ui91ViuNSbhHiwCAyYli6IRgQQEQIA -BgUCPB8wXQAKCRBqRzoxcSFero3PAKDzhIRGCfFfnuvcPTJs63q2rTiYmgCfS6Ct -YOMQyaYbjsCA2uNKod1h8wmIRgQQEQIABgUCO/MZBgAKCRB8MVegZEc1dpe6AJ9o -nHdaU9zxdk10LVzDS8iQfJIl3wCgkQ3PHxJACbWq550Nuu6GLcyB6JOIRgQQEQIA -BgUCPHSv2gAKCRCMnNnnGBSTGUrmAJwOG7kZGIUFwcEnd3RtUE6QXy/eUwCgluH6 -J77g/pyyki767QxcWkSEXOmIRgQQEQIABgUCOyiObQAKCRCPrQIss6QEWVYBAKDO -++09sRU/5u3rlpMuUo9F4bzKbgCePw6JPtErRjAt8zfk8maUM0inwheIRgQQEQIA -BgUCPC6hGwAKCRCQ3qzudismmon3AJ0RJDe8fCYq0Sv4Q+23UZqFBkSwRgCgx/Mc -nOoHqTP5NdOWpZiekDuO2kKJASAEEAEBAAoFAjqkA6MDBQF4AAoJEJ7v5Ejutjqx -+WYH/RIGqKU1KjIonGFv6l6f+YLuiP83imKXSOHVd5r/Wu1fOhodGOkbIvCPhwgq -+xwnjNsbFNTC8KshWIaTjtz77Sgu4qp0aQzQt5ebmJliB6YN45Tq/7SdZZKP1OTk -GUFcyl2GafjRp71uHvD+eqtXTxTKfee5Dlh6vi+ha6ouBybMdB9B0OYzhU2Xi0Dm -GqtcnDDavGostWCvtzFtKEtg4yzu2tR8nUgV5kMCz3osglgr7d8WQ+aZxgMOblFf -gcCRELeBWh4zjEh9wrH/7KMcr6REiXgp0YTpm18JH+UKbvsL05sJgvnJEoDncP8P -G4IkMR0JN8KRcYhZ8E2SNV6Rn/mISgQQEQIACgUCO8+CVwMFAXgACgkQp22qG2je -6vanXQCg+p5+GfFkymKzjUML9zip1f2dVEUAni4ysdlyH3A3oxKV7RWyXj1PgCGO -iEUEEBECAAYFAjtUcBcACgkQp4aCct/T12ngEACXYfv/a7NuPFA3zpRUc0QpWCv3 -LQCfd/aNbpLY3QNAGdWIrLsKTKF9IEmIRQQQEQIABgUCOt/u9QAKCRCsdttzJR81 -wWSNAKDFrGzAtuKoODKe6DDKx+sOoBL/MgCYi3X66YcHE5oExf+99xwTmzMsEIhG -BBARAgAGBQI8C8rhAAoJELSC37AZpFlD+bUAoPXlGhIUXF6mARtpxetRaG7fO8Vm -AJ96IIXSJfps2fO3AUS38An/8PdmLIhGBBARAgAGBQI7zcfhAAoJEL01r7GgoJ3c -vXkAoN5CbbjJXjI5byD1iis9G+H0cCMFAJ9Mqk1scRTGFajVipyjoC61eLoEJ4hG -BBARAgAGBQI7FfJNAAoJEMR6qYKMZW0Ott4An1qoDfLV3fUHFeDlpP9OtxYLXV2c -AKCNMkaY04vqNNIvJy0c/nnsrog7GIhGBBARAgAGBQI7ztdAAAoJEMS3xe6ePjec -bb8AnA6N6qCXWvfqxZTWW8i31bnm5gMYAJwLDIRUW00lahMf3L/84nrZmHx5HIhG -BBARAgAGBQI7wo3iAAoJEMZN/hnNBj2mK0MAoONXqgCWmOwY1kuCKmMYcpXHCjgw -AKC0hG5DBo0EcCSQ9xuXN2OySrGyGYhMBBARAgAMBQI7yJIHBQMB4TOAAAoJEMtT -PRy1z8BdctkAoKLJRxjLZ02ddy73NoMS3PwTU8HEAJ9xPD9OTf3NctADtorKsf0y -dCyvcYhGBBARAgAGBQI76umKAAoJENDQZPuFwYBQPikAoMzuIMloKscZ6GTuEx83 -WSozA7KIAKCDgWXCiaxSEhsJOvOLdu1C525f6IhGBBARAgAGBQI8BunhAAoJENEG -RJeBUhtCpPEAnRqnpqhWbQUGExxxlJqawSqPqA1cAJ4pRGh/F+3ALSFrH3SYv84u -MmcuHIicBBABAQAGBQI6ektkAAoJENEdYC5Hk8UppFYEAJI0VWk6aMSh4r1vT4sQ -ZZNnszlsPiXq9HFts1o0GK0BBNgN7PRcVxQYXroDajSlUGhr3pBmx8LzIS1VQcIk -GS5aMHed+UifhhdIbWDrPz4driXOQnAcB+isMeRfw1tf+5Quyp1BhrYyzSerwN3D -wZC80Uq066Bhok9bQw/Onwr2iEYEEBECAAYFAjuzGgEACgkQ1LqD795zV/I43ACg -xwwecFuPr1I4wAawRXPTvz+2iLcAnjqju6l6jGS42flmgIQhYR8IbbpOiEYEEBEC -AAYFAjuzZNQACgkQ5hUbwVnPhdbNIwCgiR88Ff9WiqZu03JUD8xg1eABomMAoMrm -WytXRamVMAgfKd/hIFBY76DEiEYEEBECAAYFAjqqoAMACgkQ7tDfcL9n0utnlACe -IB7BHKg9ajYIyf61OCLETHioqAsAmwXzodEuj1Vmkanes5VwctoPzUM7iEYEEBEC -AAYFAjvaGf0ACgkQ+8k1yjhw7+0uAgCaAztlqJo9gtpS9BfZnuQb/bK5IKUAnjLo -TJE+INlQq0PbMPFGvhS1aGn0tCJQaGlsaXAgUi4gWmltbWVybWFubiA8cHJ6QGFj -bS5vcmc+iEYEEBECAAYFAjpU6LcACgkQx0Y2ObLXeV4TyQCg5ii9gHqOjlsHGSsq -kliw+Ha0MX4AoLie5O1xLkK/rS9J3aIp9EUkE5AhiEYEEBECAAYFAjpU6WkACgkQ -Y8tpHfrr1fykfgCeLP0tqVZ8D9lU2EVrKZkdauwst50AoIQsSo6PBhfNwwb5zDLK -O/PGftGhiEYEEBECAAYFAjpXKUkACgkQ14y85WanSzGqnQCePrJJrLngH0MDYrDU -qrK1ju2/BHUAnieEItKJUoN9FXzacVsEFW1D0UwQiD8DBRA6WP4q8CBzV/QUlSsR -Ap0RAJwPSxTAIb6M1TM8LSNgnvYigYZXwwCfZzVNckHKo7WtpZ1lWN+4W80eKJyI -RgQQEQIABgUCOlrmuwAKCRBnkE+tCnkWEOpjAKDeibXDKCIMiNZafH0nzDD/CRU+ -pACglr+BhEKX68HeW4QnooPxoFwlviKIRgQQEQIABgUCOleFogAKCRCsuxZLz3Ps -TDo9AJ97srZSNDeiQUHoiGsETRMKG6Uf+ACgwsiJIzN2rVgvAgCfq89g/efv8hTR -zNf/AAANkgEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD -AAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEEx -NDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7 -Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCACPAHUD -ASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAA -AgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAk -M2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlq -c3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG -x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEB -AQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx -BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5 -OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaX -mJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq -8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD2aiiigAooooAKyNb8S6boUZN1Lulx8sS/ -eP8Ah+NZXjbxcdCt/sdjh7+UdcjES+p968fvLyW6leaa4mmlY5kkL4AP1qXLsaQh -fVnc6l8TdSncrYRRW6Zx03t/L+lYsvjjXnA8zUZY8nI2kr/QVzlu0b8+S2R/HvJN -WFgAYuwDFuvJ/lzms2/M2UbdDrLPxlrETK51CRxn7sm1gfzrs9F8b2d8ix3v+jyn -+Ij5T/hXkQj8gZX5hnlCMZq9YShm8vzDt7HuDQm0KUUz3ZHWRQ6MGU9CDkGnV5VZ -6xf6FJ5qTlY8/Mh5Vh9K77QNfi1uEkJskUZI7EeorRSuYyjY16KKKogKKKKACiii -gArO17VU0XR575sFkXCKf4mPQVo1wHxXvfJ0yztw+N8hdh3IHA/nSew4q7PNdT1G -a9vpLi4kaaaRyWY8KDRYWCXkuG5Qc+gzWe8mWAUYz19TW9pbGJAScZ6msJuyO2nG -7NOPTrcxhAMdOmOKp3eg36OWsw0qY4x2rVgkynIyfrite0bKDBrBNo3aOOtvDWr3 -dwPPjEKDOS1dJbeFJYY/3UqKxGC5TJ/Wt+Fdx4HNaMUSlM9yK1TbMJ2RwWo+GtXe -MiaZLlByCo2mpvCOpTaDrKpdEmA/KxIwVz612rR4PPWue13T4RcwXBUBWYI5A6Z6 -GmpNMmyasejghgCDkHkGlrD8J3ck+lfZ5m3SWreXu/vL/Cfy/lW5XQnc5GrMKKKK -YgooooAK8j+LF4ZNchtmACQQjGDySefy6V6jqeowaVp099cnEcK7j7+grwXxjq1x -r2ovqYRUV8DaCTtA7VMmtjWnBv3jMgjM0wAUnFbcCtHGFHOevtUek2RisUmkwS3O -4HIqeWTaP3e0HPzMemfwrmk7s7oWSuatk7BQG71v28OFUpjHt2rj7XWreH91NLGW -PQ7W/qK6bTdYs5IgFuI8njGajlsPmubtrmMGVuAo5q7GxWMcZBH51nmVDaIqMpEr -DJB7VcWf98Y+wXg9jVowlqTtIpGP6Vj+KNv/AAj1y4xuUAr9cjFajHnHWsvxG6DS -ij8h3H6c0yUW/Aju/n7xg7Rn6gkV2Fc14Lg22MszD53IBPf1rpa6I7HNLcKKKKok -KKKKAOQ+JchHhuOIMR5twufoATXkjOkjqqAHLYAzxXq3xLikl0uzKAkCYg49SvFe -YR2htbqKJyN3JODnNc837zO6l/DSNOLeijyuy7cEZzVG50jUbsmWKTamTny1GRzV -4TAPtUZ+la2nyJbBWmZogScBhgfnWN7G9jmrfR7/AM7ZJdq8GDw8Suf6VRtXubfU -FjMZR8jATjP0r0jfbMM7ULHvgVyl3BFPreICruTglTwvPr60+buKK1NeKe5S3W5l -iaNmHBTgKfU//WpJ/E13bYVJxM+MnEYyK25LKNtPtkPCK4U/TNYF94IinuWfcUVj -uDxnBBpITa7GppvitLnalxZzRseN6pkE/TtUviOVbmC0jhdSGk+b26VlGz1PSpkE -Vz9sthgGN/vr7hq6PT7Qajq9os4ZI0BfYB1AOcH/AD3rSOrsYzVlc6bQrZrXR4Ed -drldzD3P+RWjRRXUcQUUUUAFFFFAGN4r06bU9Blhtl3TIQ6qOrY7D8K8fvraW31J -VmR0ZQPlYYI/Cvea8q+IVi0PiFrgnImjBUY/P+VZTj1OijP7JyP2n/SMnPB9eldX -pV/5kIRsbfQ9K4yTMbhmyMnvUg1FoGYyI4THAXoPT+dYONztckkb2v69ZwSJa29q -gLf6ybYPlHt7+9Q6JdWA1NWgYBMdBXOzTf2id0aFg3anW+l3Fkv2tmcL1A/wo5VY -Sl9x6+ghnswgcEOOcdvemWs7zQHgSMjFGK+oNcZpd/Kl5Ct1JMIVAOA+M/WtGzu1 -0nXHWObdbXZ8xCT3PVTSuRyHTymN1QeUSwYcba1dHt1W5Z2xvVOg9z/9YVmC583G -OM9BWtoTectzN/CZNi+4H/661p2uc9S6ia1FFFdBzBRRRQAUUVi6x4v0HQwft2ox -K4/5ZodzfkOn40AbVcX8SrHdo6akg+e2ba2P7p/+v/OsDVvjhYws0elaZLO3Z5m2 -g/gM/wA6525+I+t+IQ+n3ywQ290rDy0jwQMZHJOetS9jSKdzm7i+USAlhkZ56Dr1 -rd0vy5o9r4cuvzcg54rjLzNvcFMY55xW3od8FKx4GR8zMemazlG6N4zfMap02KC6 -bEcTJ6Nx+tbumPYyRrb/AL+Jc/dBEig+wYcU20FtqSguuMcZ7mtCx8PrDMZGkJVG -yB/Kuf1Oly7Ej6XcyebgQ3IZTtdl2OD26cViw2lxeSrayYTyzklTnbg9veun1LUU -021IDb5Dwi+vvXOaVfIJZJN4LF8YHuadmTzHTqZEt/3eTIFwg7lu1dnpdn9g06K3 -7gZb6nrXn0mvWujeVqOoI8ltG6/LHyS3b/Gu20TxRo3iCMNp16kj4yYm+Vx/wE10 -U1ZHJWd3oa9FFFamAUUUUAeF+KPijqurI0Fq32K3PaJvmP1avPbi5kuZCWJOTyfW -mzOzNinwxBRuPXtSNCe3hSIBiMv/ACp1vcbdThkbp5gz9KYzEL9agcE7vXND1Hex -s6raecSVA3jkZ71nWdy1qWjkG3sQRWlBdi8tQ+cuvyuPcVFMsc3yyrz2P/16yi2t -GdE4p+8jWsfEMNsU3H7vf+92rdt/FyiI4Zcnt6GvPmsyv3HB46k4zUiQTRKF3gAH -Od3ehwi9SVOSVrHT6nrjzSYMgJUjknOKgsZnS4MrMVRerY/zk1mafAly2W3SAclg -NoNWPNaW+kUDbFF8qovQHufr/hVqFkTzXNG+v3v5T5oxGq4WM9AKxlMlheCS1leN -kO5CrYI59a0XOPvAfX1rN1OPPIB5TB+lUSekeF/ipNEqWutKbhBwJ1Hzj6jv/nrX -pWnaxp2rRCSxu4pwRnCtyPqOor5ht5G3Dca2bW+mtXEkEzxsDkMuQaCeVM+kqK8W -sPiPr1rB5bXImx0MqbiPxoouTyM80jh8xyxHyg1KVx1qxEEeNfK5FI6euKZViq5I -FJDGZA+Occ0sik9BVaYMqZUkFecjjFIksQtJZT7+iEjcPSt63W1mUNIRjFc9ZXhu -D5FwQSwwre/oa3raW3+xlGwWPr1FRUj1RtSl0GmW1jdlWCNz2Y/40yCBNQZijq0a -NtKp/X/P51nXk4RJdqYBPJJHJq74a2x6XM4I3NJyM46f5NaQgkyZVG9DRv7hNPsW -8pQP4VA7k/8A66g06Hy7dcnJbkk9yetU9TZpr+KHnKfO2fXoK0LYqYh1x6ZqpPUm -JKy45z+XaqV8AUQ89x06VeccHA6896rXSbrZj3Ug1JRjYKsQfXrVxX+Xg+4qCVQQ -D0NOhJYcdTSEtGWVkIyFU/gtFJGEywbA568c0UFmUomil/dAtk9B3q/nzBjHTqKW -BVjIPU45NMPDn3pkLQY6jBwRxTIoxJIE7HjmpW4/OmQcXC+maBdTG2FHdckFDxWp -p7yyyu+eMcD/AGj3qpdLsvpAMdTWxpkQjsVfpn5j+NVFXZCIL6N5YhG5GeWA6laT -w/c+TJLYy4Al5TI/iHb8v5VYlwblAW6qMZ9c1mztgSleCzAKR26c1T0dwL1sDNPN -Oed7HafYcCr8MnlSAZwrdSfWobSLZCij0xRLlXHHDVBojSLZGSTz29KYFDK6nncM -VHbTCSMqx+739RUJvWz+5A4/jbp+VIZSnGFOAOKbC3zZzjr0pbjvnkk9qihyZAB3 -4oFfU0IEO05BH9f0oq1hIkXIySKKBn//2YhGBBARAgAGBQI8ZiQyAAoJEMdGNjmy -13leJSIAoIx0Ql/m4Gf4ZZeFQ1Of+zq6499DAKCHBzmIEtE740kuUl5HGNvCJ4Qb -MIhGBBARAgAGBQI8ZiXuAAoJEGPLaR3669X8OzwAoKHGtOZfI1nc4NEGzRLorYzu -HN2YAKC6koYnTdhlsiEOJxiaUxTGi+Vv4rkDDQQ6VOgnEAwAzB13VyQ4SuLE8OiO -E2eXTpITYfbb6yUOF/32mPfIfHmwch04dfv2wXPEgxEmK0Ngw+Po1gr9oSgmC66p -rrNlD6IAUwGgfNaroxIe+g8qzh90hE/K8xfzpEDp19J3tkItAjbBJstoXp18mAkK -jX4t7eRdefXUkk+bGI78KqdLfDL2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4 -INoBp1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3b -zpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9G -AFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67 -VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM -2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpTDJvAAICDACNUV4K2PS6 -h574Z3NaBsIQe5jkVO48MSohjC6s29CjPhlU79cQIYWmBpuNfwroZ6zltyz6Y2Fm -65V0IfvVicR7zvFFCOhahMuk1cr+Qp936OMEq9sLZGxTjClgwrHGS7YpMSZrEC7b -pOmERjo4F/n5YmCHJCH8QzCOc9+80gjVEsHiJVABrC8yykjKL5x1V/PSArE4QtML -bkBPGmQYOw8bx6jCHoO43QjUzbqRfBMHZqWVJyoIIZCp+n13XM4+NO/cDVsZ8bjc -h0LIOyMrT85n24yfXRlP0s7BFjLm59Jjhf4djuJWikJawWETlypAy86OYRRuwCbI -yNauBeTKy+avZvF2oLvpwH4UnudpC06/O0jkj2lQpn9EEUw11RwO6sq9zYTwAUyK -erN00cbCfyiZl01CIo0btcTO6hQK3c67PaloJ9lVH8/mH7LuqkMLDH5ugkpzmed/ -8SorfqVkakne6b4mRySFCBXaVZoKmDHzcH2oSSMhM9exyh6dzi1bGu6ITAQYEQIA -DAUCOlToJwUbDAAAAAAKCRDHRjY5std5XuVtAKD4358jdvOoX358HnQnmwUdUczu -FgCfT70B8OXmdyevgPtF4wOVighnBFGZAaIENaIeHhEEAP6XSuDmn2tbgzewq+Z7 -LOGzaYPGFEoNNVVSdPCkwhHaQgD2lPjc2j9yg9qMO+FlNoMz+9LPbkhkNlYnuAS7 -zpGmgR22v94rwa4NyCxa8Wzn5ikIPBYbZ3Hf0wTsM35JG8QTXFSbgT0bY2d3ZQ20 -uCDzbCCL9krgiH0JgPKjRr1rAKCKyfdG9n8xEQmZCrX5KMmAPH5zawQA4SfEZiKy -ogpw5N085NOJ7ujvH6d6ba5pzu45brw37BFbGEY8jGw5254whrtT3haD9h2fh/Za -eAmkG8o1odiZbyPVDnO9ldekhZFdK/JNHrjUFx4Yc11iJH8+IMEmwZDdpzufunCF -Xip7HchWJEMlbPkPOvzzH46O7rcq3Fi6tQgEAKLt3WtSUeviiTuIFGVYdhdTaGlQ -hDwL5Q4TVddP4cHuZktJE41CdYzJeepsABb4RRRfbGlvngJ68CDh46KW3R6zwZky -ZTpzTB1SycxZao4ocEUWUMi/Ijbtpn2q5/TK9vLreQUJqdApzRCeoZdArO5dsWoF -hbZRCtiCNeOLyt3xtCdXZXJuZXIgS29jaCAoZ251cGcgc2lnKSA8ZGQ5am5AZ251 -Lm9yZz6IXQQTEQIAHQUCNlWgpgUJCG0MiAMLBAMFFQMCBgEDFgIBAheAAAoJEGi3 -q4lXVI3NLj4AoId15gcyYpBX2YLtEQTlXPp3mtEGAJ9UxzJE/t3EHCHK2bAIOkBw -IW8ItIkBXwMFEDWiHkMDbxG4/z6qCxADYzIFHR6I9Si9gzPQNRcFs2znrTp5pV5M -k6f1aqRgZxL3E4qUZ3xePQhwAo3fSy3kCwLmFGqvzautSMHn8K5V1u+T5CSHqLFY -Kqj5FGtuB/xwoKDXH6UOP0+l5IP8H1RTjme3Fhqahec+zPG3NT57vc2Ru2t6PmuA -wry2BMuSFMBs7wzXkyC3DbI54MV+IKPjHMORivK8uI8jmna9hdNVyBifCk1GcxkH -BSCFvU8xJePsA/Q//zCelvrnrIiMfY4CQTmKzke9MSzbAZQIRddgrGAsiX1tE8Z3 -YMd8lDpuujHLVEdWZo6s54OJuynHrtFFObdapu0uIrT+dEXSASMUbEuNCLL3aCnr -EtGJCwxB2TPQvCCvR2BKzol6MGWxA+nmddeQib2r+GXoKXLdnHcpsAjA7lkXk3IF -yJ7MLFK6uDrjGbGJs2FKSduUjS/Ib4hGBBARAgAGBQI1oic8AAoJEGx+4bhiHMAT -ftYAn1fOaKDUOt+dS38rB+CJ2Q+iElWJAKDRPpp8q5GylbM8DPlMpClWN3TYqYhG -BBARAgAGBQI27U5sAAoJEF3iSZZbA1iiarYAn35qU3ZOlVECELE/3V6q98Q30eAa -AKCtO+lacH0Qq1E6v4BP/9y6MoLIhohGBBARAgAGBQI5TM2WAAoJEAJx6COq/B+4 -jTYAnjOMlKc5tuqspHgAUgAVmBda5XNGAKCIqZ3Fu33suLyRABGZ+tN3tJ1QZ4hG -BBARAgAGBQI1pysWAAoJEAQ1xdJF3KZpeMoAmwZEvOS95jEKj/HnbFBDDp5C4dw0 -AJ4nsZgDnGDAG7FCEJI6+LoIIUit44hGBBARAgAGBQI26PrdAAoJEAcDKpaJBMji -EpgAoM3IisrN7XXdhnP9lmx0UJKE7SsFAJwMWIBnGK93ojuWXh9YgDRySZKZqIhG -BBARAgAGBQI7JUB0AAoJEB3TgN9DaBQASVsAn28snlWv8ljqxPsS2e7xqJxzND3G -AKCsObLMGdGyED2YKlu0sSa4E7cE+4hGBBARAgAGBQI6xKZNAAoJECAsPjFYbhLl -DsgAn0tfgJSaxWUd5s0ZGmKob7b84onEAKC15V+DRTrE1tArKxy/itSNiMtQG4hG -BDARAgAGBQI4no7wAAoJECShvswraT6/w8oAn0XLPn0F4s9wQ4pGXNPCm7MJ6E5z -AJ9CbanRlaKAXoD1LP5bmADGkRBqfYhGBBARAgAGBQI4vt9pAAoJEC5ArMtkcKsm -HDkAoL3TIizomIuEKO6vwHMFcFndsaAaAKCJAkq+I2mjYimFE7ajlaL0jyecGohM -BBARAgAMBQI6IYGCBQMD7eiAAAoJEDJKcxqmfO/9aXgAoOumahVFuBTuZsv5ma2x -G3dVPZczAKC1viEIhAakthEb+Pi0SRyeK7cqqYhGBBARAgAGBQI5zA88AAoJEDLD -W4BHupNX9vwAn1ZRUYyIWV5XoRUIq7Epz1id+hDVAKDMZSo15h9vfGAjrytpxOs5 -clW+G4hGBBARAgAGBQI5bedgAAoJEDLGkzuo7SAfxjMAn2I7CSRyEz8mkaD3emaM -1WYxvbb5AKCFOlNjoxNmu3SSWfgrW1EESYPQY4hGBBARAgAGBQI4q/0WAAoJEDW6 -YX9GCEVakzQAmgNaF00/D/eOgHmtLEjE0IH1H2yUAJ9EKs47I9s8U7IYJOGoQRy7 -LD1JRYhGBBARAgAGBQI7ScU3AAoJEDeckqFodBLoiG0AoItVFw4742i3VVL75rHp -S/iRTyXXAJ46OJxgMvJ9knQ0l4so5JiBotS/8IkAdQMFMDifLTk7IqtjPG8o8QEB -gOEDAJEaFnJ11GJlMpSIkxT4kU1DpXJGc+w5vhX8xjqjTlkbCS1AeryM2FGz/wPK -DjHtG97Ybptmeigrx5ZZ9O/wp96sTYpKiKk93YRyzPOtJ4GhahMR48LBu6YnHppJ -nxCyg4hGBBARAgAGBQI4XUq+AAoJEEPM0G/dqdt2qekAoN1HvYZQ6AxvNVLx3M06 -s/ytk21NAKDNn0RgGyCBiyQeLuV3Gkuqxke7kIhGBBARAgAGBQI5Zs0MAAoJEEcW -KRmClXtmuPEAoJe7siEXNYVflP+Glf71M2xvkSa3AKCerd0dwvhmi4Ao4ujBnuZI -4YUIhIkBFQMFEDfZA2RNwxExOP7mwwEByhEH/2zbTPiXuaff02Xj7QqSIwjo0O47 -sgxNHbuUMJB7pvD0q8g/T+jX0ux6Ci16m42aOUjp254G33RN679BdjiHG47DOric -TvdLq9uWtqg+irQosJen+e0pIsFTfmj1zA1G8rrbADqVCEz4SpibDLB5wXDhVdqa -R3sAteIAZti1xoTiFc12KrarkLn+BaWUtvBbi93bsD+ySTE/kIeeCGLW9IEHok8d -id1QMWXNM2VuzSdKSoxaiuJOkuZ2Aui0HAdEycY5fhOqIo4B/rtxGpdBXBBCxNi+ -VRaq0CWn13BiII2BvNOmCn879R89qMxuj10X3RnRQIHgj4mg/X7zni684FOIRgQQ -EQIABgUCOQ0ojwAKCRBS/u9nIH5xmceVAJ9VIlMfbC6Gni3jLXZs7VEX5NWQCQCg -id47hulygTIy5ePkpgjOO1ZDP/aIRgQQEQIABgUCO1X9UgAKCRBW05T8JNULxIz6 -AJ9tUSb17Etq+1C6V7YiiHCt//vY2ACgt6hl1q6z2ZhSgJLBV6N6wss0GWGIRgQQ -EQIABgUCOJj9UAAKCRBl3EK31OWAJovMAJ4oWYv+ThvQp8zMdVCnbQQL77eLdgCf -ZV/ownqDt0xfEMpHTF0hSHQxy96IRgQQEQIABgUCOpP0TgAKCRBpwYMr+Tra7NWk -AKDQEafW/9gKnUNFINJqEkYUXsYlLgCZAcGWOePrrM7PEOz/h03kqllYt86IRgQQ -EQIABgUCOFjPGgAKCRBxLQsX0D2KT22cAJ0a+519NvXqtRND7/RcEK4LN2bvpwCe -LNuUSotPPf2r7FVap5vO3oAMwdmIRgQQEQIABgUCOGDD6AAKCRBxRvDjMHApSKW9 -AJ9R/bMcCRef9myi9B2bC1zuN2qtbACfc+1NHDhmDSK0TaR5Seu2TyV9LceIRgQQ -EQIABgUCOUbNKQAKCRB/4u1e9RQ7Ki5KAJ4r4dNSN7kLq1nOW52+309RiDpn8gCc -DhPygqyVfPUZKOtVwvttHZcysxqIRgQQEQIABgUCOPN6JwAKCRCEP1fXrLWNT4SW -AJ9IRICEmPNdhoYWUc7hP7HOUVhHfgCfUsR4bR9KCTaynBmKvAKA/ciTBh6IRgQQ -EQIABgUCNacrcQAKCRCE5PiUAeWZaBjoAJ41XKqKVxMjGBGXxffEkyprrSj4igCf -cR5sWVtyrVUk0X/yE0jUrP9IApSIRgQQEQIABgUCOnNH4AAKCRCI98SPIjWV9R3S -AJwLoPyJ8dzW1f2ubzYBEkkHN41p9QCeKbvAZQNRcsMKTJCAuhlwFnh7KGqJARUD -BRA21moYjl8DByup3WkBAZ0tB/9v5kOKdh7rwDaPHFLxvG7flsD8XOvMM/LH0uAx -smUebXYwIRWDziZqDmFHpnzTt5LM7nyaPJjggfSCmlLKtx5ZgIgXM9D7WrwPRgcX -g3SHbuKbXTeiSQRP8goMeADlQFd+sX8l40mwKF9klQXR7/02CT+LM5A/KnXM4mqQ -1cjFLiCwhx2G+Rsx4PEDTDoBL3W6ME/pxIzn0NJuhp9oDVvKuWmKtwKPWSHRj8CR -56OBxeZG+sPK3UySM/ZEdEL0iEZvgYRwpf/t8vnS8/Li/M6pem6FnwLalQwv/vMF -FQvBiHJqRJ1VxsdHVDMbap1LO7A2QGghPkeDnAN4jyCsqXVtiEYEEBECAAYFAjt4 -2yAACgkQj8C3jQmzMQbrmgCfeBACKTFlOsTcbhhlvIjZJ9ZUT10An0NHUHnoktA4 -GMdxW5vR+t1uhGcWiEYEEBECAAYFAjbWagEACgkQkrJ6leQEE6q4FwCg2WMRtIdc -wsfnj8ngeK0CyIjXxqYAoOsMufELOYL7yb85M27iZlqZ48/eiEYEEBECAAYFAjnK -lgsACgkQnznd8F4pxsIVuACfc+MHLblJgJcI5Z42D4d5ufs+LsYAoMq1/GdeKCtx -028BGZm1Yc0zO8cwiEYEEBECAAYFAjnPNIIACgkQpll1bT9NtmnSywCfWpns8kIg -d/oStQbXXVzltaMJtbcAoL/cJ/9k1kraYpk6Z8IJGf2wEGVFiEYEEBECAAYFAjqW -fQEACgkQq79czSEmG4giGACg/qNL4huhd12Jyya3qTJeFYFgMm0AoOWNXs1CepYM -GZ1HNhbcJiH+G8/IiEYEEBECAAYFAjoZ9rYACgkQvhpT6zI73uZHuQCeNJfhA/uB -HrHUFhMILz27aBJcBC0An2dF4AKA1T8P5MuqKaUxL1OqdPJkiEYEEBECAAYFAjmS -plwACgkQx+D2lKJNi05V5QCgxOAE1SMP4BhATMhTXNiSJbU2BmEAoNbcbOwM+rOz -ecX6aQyeCBg8WcSeiEYEEBECAAYFAjfZA0MACgkQzTbgIX48jquOOQCgqjyYGNri -U4Zb6aKW4GHcuJNoM0kAoNCupziSR9pBxWVeMNVhVp6XvigmiEYEEBECAAYFAjm0 -32EACgkQ0Y4PDnuqkPpwSQCgubij+epzZINnZ4qvmFgNNR9YGUIAn2Dwom8wzr7/ -W0Q9qiUz+FVYoHHqiEYEEBECAAYFAjgmg+4ACgkQ1eiHQ5R2ErMIAwCdF+TWZ/T7 -KJR0y5IQ2EoxfLKxnawAoK8xJ0QSYaiZYKCxB8tYzMItHv7liEYEEBECAAYFAjfX -jLIACgkQ1rb6S4yOnyPYrACgr35M5uneN/5PCc9Uh9caSYdJtwwAoOjzOz6KwrKd -c4wXaDnRJNnBpZMdiEYEEBECAAYFAjpCNWEACgkQ30kDp8mywsCuGACgw405ZqhW -MrgNewU0gPllz+S9V68AoLer9gdEcr3aHhxZxmZpjsRy4w/tiEYEEBECAAYFAjrO -IywACgkQ4HkONspwutzZoQCdHVZOvgnh2kW4229FOwRdtVybZGUAoOhlsIEL0j5W -4YJCGQrhd7vxuo0viEYEEBECAAYFAjnzJCIACgkQ5jU8OLhSiwGGrwCg304/n0hg -n41Bgmal2jI8WAmK098Ani2W7uoOHSWlBQEkoisKMbSh3jIhiEYEEBECAAYFAjqQ -EYkACgkQ86QzvnxWxe/4rwCfSXD8N6MhMzfKqZ6b6X/kag/dS/QAn2QM9U4dCrUl -8kOTdZbP+NC+Hcx0iEYEEBECAAYFAjnND5cACgkQ93111w6M5IHPxgCfZrmMKTTn -ZT5+uv6wVFDUyoqavEoAn0nvU51E1kt5+QPuKEnZiZyjwayniEYEEBECAAYFAjqe -VPUACgkQ+qVJWkKzL8lzvACfXa4hgEv1Z+GZLZKHQ76Yg7aPnzQAn2cm8G7PirTu -WSANQVUlCWu4PUh8 -=9VIS ------END PGP PUBLIC KEY BLOCK----- diff --git a/g10/ChangeLog b/g10/ChangeLog deleted file mode 100644 index d4221d1c3..000000000 --- a/g10/ChangeLog +++ /dev/null @@ -1,7014 +0,0 @@ -2002-10-17 Werner Koch - - * pkclist.c (do_edit_ownertrust): Show all user IDs. This should - be enhanced to also show the current trust level. Suggested by - Florian Weimer. - -2002-10-17 David Shaw - - * g10.c (main): Handle --strict and --no-strict from the command - line before the options file is loaded. - -2002-10-15 David Shaw - - * g10.c (main): Disable --textmode when encrypting (symmetric or - pk) in --pgp2 mode as PGP 2 can't handle the unknown length - literal packet. Reported by Michael Richardson. - -2002-10-14 David Shaw - - * keyserver-internal.h, keyserver.c (print_keyrec, parse_keyrec, - show_prompt, keyserver_search_prompt, keyserver_spawn): Go to - version 1 of the keyserver protocol. This is a better design, - similar to --with-colons, that allows for keys with multiple user - IDs rather than using multiple keys. It also matches the machine - readable pksd format. Also use a prettier --search-keys listing - format that can fill different size windows (currently set at 24 - lines). - -2002-10-12 Werner Koch - - * keygen.c (print_status_key_created): New. - (do_generate_keypair): Use it to print the fingerprint. - (generate_subkeypair): Likewise. - -2002-10-11 David Shaw - - * keyedit.c (menu_addrevoker): Properly back out if the signature - fails. Also, do not allow appointing the same revoker twice, and - report ALREADY_SIGNED if the user tries it. - -2002-10-07 David Shaw - - * import.c (import_keys_internal): Missed one s/inp/inp2/. - - * keylist.c (print_capabilities): Properly indicate per-key - capabilities of sign&encrypt primary keys that have - secret-parts-missing (i.e. no capabilities at all) - - * mainproc.c (symkey_decrypt_sesskey): Fix compiler warning. - -2002-10-04 David Shaw - - * getkey.c (get_pubkey_direct): Don't cache keys retrieved via - this function as they may not have all their fields filled in. - - * sig-check.c (signature_check2): Use new is_primary flag to check - rather than comparing main_keyid with keyid as this still works in - the case of a not fully filled in pk. - -2002-10-04 Werner Koch - - * import.c (import_keys_internal): s/inp/inp2/ to avoid shadowing - warning. - - * passphrase.c (agent_get_passphrase): Fixed signed/unsigned char - problem in %-escaping. Noted by Ingo Klcker. - -2002-10-03 David Shaw - - * options.h, g10.c (main): Add --strict and --no-strict to switch - the log_warning severity level from info to error. - - * keylist.c (print_capabilities): Secret-parts-missing keys should - show that fact in the capabilities, and only primary signing keys - can certify other keys. - - * packet.h, parse_packet.c (parse_key): Add is_primary flag for - public keys (it already exists for secret keys). - -2002-10-02 David Shaw - - * import.c (import_secret_one): Check for an illegal (>110) - protection cipher when importing a secret key. - - * keylist.c (list_keyblock_print): Show a '#' for a - secret-parts-missing key. - - * parse_packet.c (parse_key): Some comments. - - * revoke.c (gen_revoke): Remove some debugging code. - - * trustdb.c (verify_own_keys): Make trusted-key a non-deprecated - option again. - - * seckey-cert.c (do_check): Don't give the IDEA warning unless the - cipher in question is in fact IDEA. - -2002-10-01 David Shaw - - * import.c (import_one): Make sure that a newly imported key - starts with a clean ownertrust. - -2002-10-01 Werner Koch - - * getkey.c (get_pubkey_direct): New. - (merge_selfsigs_main): Use it here to look for an ultimately - trusted key. Using the full get_pubkey might lead to an - infinitive recursion. - -2002-09-29 David Shaw - - * keyserver.c (parse_keyserver_uri): Force the keyserver URI - scheme to lowercase to be case-insensitive. - -2002-09-28 David Shaw - - * export.c (do_export_stream): Comment. - - * sig-check.c (check_key_signature2): Properly handle a - non-designated revocation import. - -2002-09-26 Werner Koch - - * g10.c (set_homedir): New. Changed all direct assignments to use - this. - * gpgv.c (set_homedir): Ditto. - -2002-09-25 David Shaw - - * Makefile.am: Link gpg with EGDLIBS (i.e. NETLIBS) as EGD uses - sockets. Remove the old NETLIBS variable since the keyserver - stuff is no longer internal. - -2002-09-24 David Shaw - - * import.c (import_keys_stream): Fix compiler type warning. - - * keyring.c (keyring_rebuild_cache), sig-check.c - (check_key_signature2), import.c (import, chk_self_sigs): Minor - language cleanups. - -2002-09-23 Stefan Bellon - - * main.h: Introduced fast-import as import option. Removed - fast as separate option from prototypes. - * import.c (parse_import_options): Added fast-import option. - (import_*): Removed fast as separate option. - * g10.c (main): Added option fast-import, removed old fast - as separate argument. - * keyserver.c (keyserver_spawn): Removed old fast as separate - argument. - -2002-09-22 Stefan Bellon - - * import.c (import_keys, import_keys_stream, - import_keys_internal): Added trustdb update/check to key import if - not fast-import and interactive set/no-auto-check-trustdb unset. - Avoided function clone by introducing import_keys_internal. - -2002-09-19 David Shaw - - * keyserver.c (keyserver_spawn): Properly handle line truncation. - Don't leak memory (~10-20 bytes) on searches. - (keyserver_search_prompt): Cleanup. - - * keylist.c (list_keyblock_colon): Show 1F direct key signatures - in --with-colons listing. - -2002-09-16 David Shaw - - * keyedit.c (menu_addrevoker): The direct key signature for - revocation keys must be at least v4 to carry the revocation key - subpacket. Add a PGP 2.x warning for revocation keys. - -2002-09-14 David Shaw - - * g10.c (check_permissions): Rearrange strings to make translating - easier (don't incorporate string parts). - - * keyedit.c (sign_uids): Make strings translatable. - - * sig-check.c (check_key_signature2): Make string translatable. - -2002-09-13 David Shaw - - * getkey.c (check_revocation_keys): Move.... - * main.h, sig-check.c (check_revocation_keys): to here. Also - return the signature_check error code rather than 0/1 and cache - the sig result. - - * sig-check.c (check_key_signature2): Divert to - check_revocation_keys if a revocation sig is made by someone other - than the pk owner. - - * getkey.c (merge_selfsigs_main): Tidy. - -2002-09-13 Werner Koch - - * g10.c (main) [__MINGW32__]: Activate oLoadExtension. - -2002-09-12 David Shaw - - * Makefile.am, hkp.c, hkp.h, keyserver.c (keyserver_work): Remove - internal HKP support. - - * keyserver.c (keyserver_spawn): Remove whitespace after keyserver - commands. - -2002-09-10 David Shaw - - * exec.c (expand_args): Remove loop left over from earlier - implementation. - (exec_write): Missed one tick. - -2002-09-10 Werner Koch - - * g10.c, options.h: Removed option --emulate-checksum-bug. - * misc.c (checksum_u16_nobug): Removed. - (checksum_u16): Removed the bug emulation. - (checksum_mpi): Ditto. - (checksum_mpi_counted_nbits): Removed and replaced all calls - with checksum_mpi. - - * parse-packet.c (read_protected_v3_mpi): New. - (parse_key): Use it here to store it as an opaque MPI. - * seckey-cert.c (do_check): Changed the v3 unprotection to the new - why to store these keys. - (protect_secret_key): Likewise. - * build-packet.c (do_secret_key): And changed the writing. - - * tdbio.c (tdbio_set_dbname, open_db): Use new macro MY_O_BINARY - to avoid silly ifdefs. - (open_db): Fallback to RDONLY so that gpg may be used from a - RO-medium. - - * encode.c (encode_simple): Make sure we don't use an ESK packet - when we don't have a salt in the S2K. - - * misc.c (pct_expando) : Make sure that LEN is initialized. - - * exec.c (exec_finish): Use ticks to denote filenames in messages. - (make_tempdir, exec_write): Changed format of messages. - - * keyserver.c (print_keyinfo): Release USERID in on error. - (keyserver_work) [!DISABLE_KEYSERVER_HELPERS]: Exclude the unused - code. - -2002-09-09 Werner Koch - - * parse-packet.c (make_attribute_uidname): Add new ar MAX_NAMELEN - for sanity checks. Changed both callers. Limit the size of an %s. - - * options.skel: Comment lock-once out, so that this file does not - change anything when copied to a new home directory. - * openfile.c (try_make_homedir): Don't exit after copying the - option skeleton. - - * options.h: Don't use a comma when declaring variables over more - than one line. - - * mainproc.c (symkey_decrypt_sesskey): Check length of the session - key. - - * hkp.c (dehtmlize): Use ascii_tolower to protect against weird - locales. Cast the argument for isspace for the sake of broken - HP/UXes. - (parse_hkp_index): s/ascii_memcasecmp/ascii_strncasecmp/. - - * g10.c: Removed option --emulate-3des-s2k-bug. - - * passphrase.c (hash_passphrase): Was used here. - - * export.c (parse_export_options) - * keyserver.c (parse_keyserver_options) - * import.c (parse_import_options) - * g10.c (check_permissions): s/ascii_memcasecmp/ascii_strncasecmp/. - -2002-09-09 David Shaw - - * g10.c (add_group): Use '=' to separate group name from group - members. Use a better error message for when no = is found. - - * hkp.c (hkp_export): Use CRLF in headers. - -2002-09-03 David Shaw - - * mainproc.c (print_pkenc_list): Don't increment the error counter - when printing the list of keys a message was encrypted to. This - would make gpg give a non-zero exit code even for completely valid - messages if the message was encrypted to more than one key that - the user owned. - -2002-09-02 Werner Koch - - * g10.c (main): Try to set a default character set. Print the - used one in verbosity level 3. - * gpgv.c (main): Try to set a default character set. - - * status.c, status.h (STATUS_IMPORT_OK): New. - * import.c (import_one,import_secret_one): Print new status. - -2002-08-30 David Shaw - - * pkclist.c (build_pk_list): Add new status code to indicate an - untrusted user. This (or a disabled key) fail with "unavailable - pubkey" (G10ERR_UNU_PUBKEY). - - * pkclist.c (build_pk_list): Fail if any recipient keys are - unusable. - - * options.skel: The PGP LDAP keyserver is back. Use MIT keyserver - as a sample rather than cryptnet as cryptnet does not support - searching yet. - - * keyedit.c (show_key_with_all_names): Fix error message - (preferences are userid/selfsig and not key specific). - -2002-08-30 Werner Koch - - * pkclist.c (do_we_trust_pre): Changed the wording of a warning. - - * encode.c (encode_simple,encode_crypt): Use new style CTB for - compressssed packets when using MDC. We need to do this so that - concatenated messages are properly decrypted. Old style - compression assumes that it is the last packet; given that we - can't determine the length in advance, the uncompressor does not - know where to start. Actually we should use the new CTB always - but this would break PGP 2 compatibility. - - * parse-packet.c (parse): Special treatment for new style CTB - compressed packets. - - * build-packet.c (do_mdc): Removed. Was not used. - (do_encrypted_mdc): Count in the version number and the MDC packet. - -2002-08-28 David Shaw - - * sig-check.c (do_check_messages, do_check): Show keyid in error - messages. - - * keyserver.c (print_keyinfo): More readable key listings for - --search-keys responses. - -2002-08-26 David Shaw - - * hkp.c (parse_hkp_index, dehtmlize): Move HTML functionality into - new "dehtmlize" function. Remove HTML before trying to parse each - line from the keyserver. If the keyserver provides key type - information in the listing, use it. - -2002-08-23 David Shaw - - * sig-check.c (do_check, do_check_messages): Emit the usual sig - warnings even for cached sigs. This also serves to protect - against missing a sig expiring while cached. - - * getkey.c (merge_selfsigs_main): Don't check UID self-sigs twice. - -2002-08-22 David Shaw - - * import.c (clean_subkeys, chk_self_sigs): Merge clean_subkeys - into chk_self_sigs. This improves efficiency as the same - signatures are not checked multiple times. Clarify when a subkey - is revoked (any revocation signature, even if it is dated before - the binding signature). - - * getkey.c (merge_selfsigs_subkey): Subkey revocation comments. - - * keylist.c (list_one): Stats are only for public key listings. - - * g10.c (main), options.skel: Default should be include-revoked - for keyserver operations. - -2002-08-21 Werner Koch - - * import.c (import_print_stats): Print new non_imported counter - which is currently not used because we terminate on errors. - -2002-08-20 David Shaw - - * options.skel: Document no-include-attributes for - keyserver-options. - - * keylist.c, keyedit.c, keyserver.c, sign.c: Some TODOs and - comments. - - * export.c (do_export_stream): Fix noop bug in exporting sensitive - revocation keys. - - * pkclist.c (do_edit_ownertrust): Comment out the option for - showing trust paths until it can be implemented. - -2002-08-19 Werner Koch - - * getkey.c (get_user_id_native): Renamed to .. - (get_user_id_printable): this. Filter out all dangerous - characters. Checked all usages. - (get_user_id_string_native): Renamed to.. - (get_user_id_string_printable): this. Filter out all dangerous - characters. Checked all usages. - * keyedit.c (show_basic_key_info): New. - * keylist.c (print_fingerprint): New mode 3. - * import.c (import_one): Use new function to display the user ID. - -2002-08-16 Timo Schulz - - * g10.c (main): Enable opt.interactive. - - * import.c (import_one): Ask the user if the key shall be - imported when the interactive mode is used. Useful to extract - selected keys from a file. - -2002-08-16 Werner Koch - - * seckey-cert.c: Workaround to allow decryption of v3 keys created - with a bug in the mpi_get_secure_buffer. - -2002-08-14 David Shaw - - * hkp.c (parse_hkp_index): Properly handle really large keys - (5 digit key length) in HKP searches. - -2002-08-13 David Shaw - - * encode.c (encode_simple): Fix problem with using compression - algo 2 and symmetric compressed files. - - * encode.c (encode_simple, encode_crypt): If we are not using a - MDC, compress even if a file is already compressed. This is to - help against the chosen ciphertext attack. - - * pkclist.c (select_algo_from_prefs): Fix requested algorithm bug - so the request succeeds even if the requested algorithm is not the - first found. - - * cipher.c (write_header), encode.c (use_mdc, encode_simple, - encode_crypt, encrypt_filter), g10.c (main): Be more eager to use - a MDC. We use a MDC if the keys directly support it, if the keys - list AES (any) or TWOFISH anywhere in the prefs, or if the cipher - chosen does not have a 64 bit blocksize. - -2002-08-08 David Shaw - - * options.skel: Some language tweaks, and remove the - load-extension section for random gatherers. - - * keyring.c (create_tmp_file, rename_tmp_file): Create tmp files - with user-only permissions, but restore the original permissions - if the user has something special set. - - * openfile.c (copy_options_file): Create new options file - (gpg.conf) with user-only permissions. - - * keydb.c (keydb_add_resource): Create new keyrings with user-only - permissions. - - * tdbio.c (tdbio_set_dbname): Create new trustdbs with user-only - permissions. - -2002-08-07 David Shaw - - * sig-check.c (signature_check2): Sanity check that the md has a - context for the hash that the sig is expecting. This can happen - if a onepass sig header does not match the actual sig, and also if - the clearsign "Hash:" header is missing or does not match the - actual sig. - - * keyedit.c (menu_revsig): Properly show a uid is revoked without - restarting gpg. This is Debian bug 124219, though their supplied - patch will not do the right thing. - - * main.h, tdbio.c (tdbio_set_dbname), misc.c (removed - check_permissions), keydb.c (keydb_add_resource), g10.c (main, - check_permissions): Significant reworking of the permission check - mechanism. The new behavior is to check everything in the homedir - by checking the homedir itself. If the user wants to put - (possibly shared) keyrings outside the homedir, they are not - checked. The options file and any extension files are checked - wherever they are, as well as their enclosing directories. This - is Debian bug 147760. - -2002-08-06 Stefan Bellon - - * g10.c (main): Use of EXTSEP_S in new gpg.conf string. - * openfile.c (copy_options_file): Ditto. - -2002-08-06 David Shaw - - * options.h, g10.c (main), mainproc.c (proc_encrypted): - --ignore-mdc-error option to turn a MDC check error into a - warning. - - * encode.c (encode_crypt), g10.c (main), sign.c (sign_file, - clearsign_file): Use the same --pgpX warning string everywhere to - ease translations. - - * encode.c (write_pubkey_enc_from_list): Warn when using - --throw-keyid with --pgpX. Noted by Vedaal Nistar. - - * revoke.c (export_minimal_pk, gen_desig_revoke, gen_revoke): - Export a minimal pk along with the revocation cert when in --pgpX - mode so that PGP can import it. - -2002-08-06 Werner Koch - - * options.skel: Changed comments. - - * g10.c (main): Try to use "gpg.conf" as default option file. - * openfile.c (copy_options_file): Changed name of created file. - -2002-08-02 Werner Koch - - * Makefile.am (LDFLAGS): Removed DYNLINK_LDFLAGS. - -2002-07-30 David Shaw - - * options.h, g10.c (main), mainproc.c (proc_encrypted): Return a - decryption failed error if a MDC does not verify. Warn if a MDC - is not present (can disable via --no-mdc-warning). - - * exec.c (exec_write), g10.c (main), keyserver.c - (keyserver_spawn): Use new DISABLE_KEYSERVER_PATH rather than - FIXED_EXEC_PATH. - -2002-07-28 David Shaw - - * sig-check.c (do_check): Properly validate v4 sigs with no hashed - section at all. - -2002-07-25 Werner Koch - - * delkey.c (do_delete_key): Always allow to delete a key in batch mode - when specified by fingerprint. Suggested by Enzo Michelangeli. - -2002-07-25 David Shaw - - * keyedit.c (menu_revsig): Change "revsig" to honor selected uids - so the user can revoke sigs from particular uids only. - - * keylist.c (list_keyblock_print): Don't display expired uids in - --list-keys unless -v and not --list-sigs (just like revoked - uids). - - * exec.c, export.c, import.c, keyedit.c, keyserver.c, misc.c: - "Warning" -> "WARNING" - -2002-07-24 David Shaw - - * main.h, import.c (parse_import_options, fix_hkp_corruption, - import_one, delete_inv_parts), g10.c (main): New import-option - "repair-hkp-subkey-bug", which repairs as much as possible the HKP - mangling multiple subkeys bug. It is on by default for keyserver - receives, and off by default for regular --import. - - * main.h, import.c (import, import_one, delete_inv_parts), hkp.c - (hkp_ask_import), keyserver.c (keyserver_spawn): Use keyserver - import options when doing keyserver receives. - - * options.h, exec.h, exec.c (set_exec_path, exec_write), g10.c - (main), keyserver.c (keyserver_spawn): If the user does not use - "exec-path", completely replace $PATH with GNUPG_LIBEXECDIR before - calling the keyserver helper. If the user does use "exec-path", - append GNUPG_LIBEXECDIR after the specified path. - -2002-07-23 David Shaw - - * import.c (parse_import_options), export.c - (parse_export_options): Fix offset problem with reversed ("no-") - meanings. - - * import.c (delete_inv_parts): Discard subkey signatures (0x18 and - 0x28) if found in the userid section of the key. - - * sig-check.c (signature_check2): Signatures made by invalid - subkeys (bad/missing binding sig) are also invalid. - - * keylist.c (print_fingerprint): Show the primary as well as the - secondary key fingerprint in modes 1 & 2. - -2002-07-22 David Shaw - - * options.h, main.h, g10.c (main), import.c - (parse_import_options, delete_inv_parts), keyserver.c - (parse_keyserver_options): add new --import-options option. The - only current flag is "allow-local-sigs". - - * g10.c (main): Don't disable MDC in pgp7 mode. - - * options.h, g10.c (main), keyserver.c (parse_keyserver_options): - Remove old keyserver-option include-attributes now that there is - an export-option for the same thing. - - * options.h, main.h, export.c (parse_export_options, - do_export_stream), g10.c (main): add new --export-options option. - Current flags are "include-non-rfc", "include-local-sigs", - "include-attributes", and "include-sensitive-revkeys". - - * options.h, hkp.c (hkp_export), keyserver.c - (parse_keyserver_options, keyserver_spawn): try passing unknown - keyserver options to export options, and if successful, use them - when doing a keyserver --send-key. - - * build-packet.c (build_sig_subpkt): We do not generate - SIGSUBPKT_PRIV_VERIFY_CACHE anymore. - - * revoke.c (gen_desig_revoke): Lots more comments about including - sensitive revkeys along with the revocation sig itself. - - * keyserver.c (parse_keyserver_options): Simpler implementation - that can skip one pass over the options. - -2002-07-18 David Shaw - - * keyedit.c (keyedit_menu, menu_addrevoker): Allow specifying - "sensitive" as an argument to an addrevoker command. This sets - the 0x40 sensitive revoker flag. - - * revoke.c (gen_desig_revoke): When generating a designated - revocation, include the direct key sig that contains the - designated revoker subpacket. This allows sensitive designated - revocation subpackets to be exported. Also indicate which - revokers are sensitive in the first place. - -2002-07-17 David Shaw - - * keyedit.c (show_key_with_all_names_colon): The 0x40 class bit in - a designated revoker means "sensitive", not "local". It's - exportable under the right circumstances. - - * main.h, options.h, export.c (do_export_stream), g10.c (main), - hkp.c (hkp_export), keyserver.c (keyserver_spawn: Add a flag to - skip attribute packets and their signatures while exporting. This - is to accomodate keyservers (pksd again) that choke on attributes. - Use keyserver-option "include-attributes" to control it. This - defaults to ON (i.e. don't skip). - -2002-07-09 David Shaw - - * options.h, keyserver.c (parse_keyserver_uri, keyserver_spawn, - keyserver_work), hkp.c (hkp_ask_import, hkp_export, hkp_search): - Use a much more strict reading of RFC-2396 for the keyserver URIs. - Specifically, don't try and be smart about checking the value of - ":port" so long as it is all digits, and properly handle opaque - data (those scheme specific parts that do not start with "//"). - -2002-07-04 David Shaw - - * photoid.c (get_default_photo_command, show_photos): Honor - FIXED_PHOTO_VIEWER and DISABLE_PHOTO_VIEWER. - - * mainproc.c (check_sig_and_print): Use --show-photos to show - photos when verifying a sig made by a key with a photo. - - * keyserver.c (parse_keyserver_uri): Properly parse a URI with no - :port section and an empty file path, but with a terminating '/'. - (keyserver_work): Honor DISABLE_KEYSERVER_HELPERS. - - * hkp.c (hkp_ask_import): Display keyserver URI as a URI, but only - if verbose. - - * exec.c, g10.c: USE_EXEC_PATH -> FIXED_EXEC_PATH - -2002-07-03 David Shaw - - * exec.h, exec.c (set_exec_path, exec_write), g10.c (main): If - USE_EXEC_PATH is defined at compile time, use it to lock the - exec-path and not allow the user to change it. - -2002-07-02 David Shaw - - * options.h, g10.c (main), keyserver.c (keyserver_refresh): - Maintain and use the original keyserver URI for cosmetics rather - than trying to recreate it when needed. - - * mainproc.c (check_sig_and_print): Properly disregard expired - uids. Make sure that the first uid listed is a real uid and not - an attribute (attributes should only be listed in the "aka" - section). When there are no valid textual userids, try for an - invalid textual userid before using any attribute uid. - -2002-07-01 David Shaw - - * options.skel: Fix a few typos, clarify "group", and remove - sample photo viewers for Win32 since they are the defaults now. - - * parse-packet.c (make_attribute_uidname), keylist.c - (dump_attribs): Fix two typecast warnings. - - * packet.h, build-packet.c (build_attribute_subpkt), exec.c - (expand_args), mkdtemp.c (mkdtemp), photoid.c - (parse_image_header): Fix some signedness compiler warnings. - -2002-07-01 Werner Koch - - * photoid.c (get_default_photo_command): Also use __MINGW32__ - instead of HAVE_DOSISH_SYSTEM. - - * encode.c (encode_symmetric): Do not use the new encryption code. - -2002-06-30 Werner Koch - - * photoid.c: Use __MINGW32__ to include windows because - HAVE_DOSISH_SYSTEM is also set for OS/2 and plain DOS. Provide - constant missing in older mingw installations. - -2002-06-21 Stefan Bellon - - * g10.c [__riscos__]: Moved RISC OS specific stuff to util/riscos.c - and include/util.h. - - * gpgv.c [__riscos__]: Likewise. - -2002-06-20 David Shaw - - * keydb.h, pkclist.c (select_algo_from_prefs): Allow passing a - suggested algorithm which will be used if available. - - * encode.c (encode_crypt, encrypt_filter), sign.c (sign_file): Use - new select_algo_from_prefs feature to check if forcing an - algorithm would violate the recipient preferences. - - * photoid.c (get_default_photo_command, show_photos): Use - different default viewers on different platforms. Currently we - have Win 9x, Win NT (2k, xp), Mac OSX, RISC OS, and "everybody - else". These are #ifdefs as much as possible to avoid clutter. - - * g10.c (strusage, build_list), keyedit.c (show_prefs), main.h, - misc.c (compress_algo_to_string, check_compress_algo), pkclist.c - (algo_available), keygen.c (keygen_set_std_prefs): New - algo_to_string and check functions for compress algorithms. - -2002-06-20 Werner Koch - - * misc.c (setsysinfo): Removed a #warning for Alpha's uniligedn - trap disabling - it is quite possible that this is a debug relict. - -2002-06-20 Stefan Bellon - - * g10.c [__riscos__]: Added image file system feature. - - * gpgv.c [__riscos__]: Added image file system feature. - - * photoid.c (show_photos) [__riscos__]: Set RISC OS filetype of - photo id according to MIME type. - -2002-06-19 David Shaw - - * hkp.c (parse_hkp_index): Don't leak memory when failing out of a - bad HKP keyserver. - - * g10.c (add_notation_data): Relax slightly the rules as to what - can go into a notation name - 2440 allows "@", for example. - -2002-06-17 David Shaw - - * import.c (clean_subkeys, import_one): Only allow at most 1 - binding sig and at most 1 revocation sig on a subkey, as per - 2440:11.1. - - * hkp.c (parse_hkp_index, hkp_search): Error if the keyserver - returns an unparseable HKP response. - -2002-06-15 David Shaw - - * keyedit.c (show_key_with_all_names), keylist.c - (list_keyblock_print): Show "[expired]" before expired uids. - - * keyedit.c (show_key_with_all_names_colon), mainproc.c - (list_node), keylist.c (list_keyblock_colon): Show flag 'e' for - expired user ids. Use "uat" for user attribute packets instead of - "uid". Also use ' ' rather than the fake user id - string on attributes. - - * keygen.c (keygen_add_revkey): Remove unused code. - - * misc.c (check_permissions): Check directory permissions - properly - they are not special files. - - * pkclist.c (expand_id, expand_group, build_pk_list): When - expanding groups before building a pk list, inherit flags from the - original pre-expanded string. - - * pubkey-enc.c (is_algo_in_prefs): Don't use prefs from expired - uids. - -2002-06-14 David Shaw - - * free-packet.c (copy_signature): Properly copy a signature that - carries a revocation key on it. - - * pkclist.c (expand_id, expand_group, build_pk_list): Groups now - work properly when used in the "Enter the user ID" prompt. - -2002-06-14 David Shaw - - * keyedit.c (show_key_with_all_names): Display warning if a user - tries to show prefs on a v3 key with a v3 selfsig. - - * kbnode.c (dump_kbnode): Show if a uid is expired. - - * import.c (merge_blocks, import_revoke_cert): Show user ID - receiving a revocation certificate. - - * free-packet.c (cmp_user_ids): Properly compare attribute ids. - - * pkclist.c (expand_groups): Maintain the strlist flags while - expanding. Members of an expansion inherit their flags from the - expansion key. - - * options.h, cipher.c (write_header), g10.c (main), keygen.c - (keygen_set_std_prefs): remove the personal_mdc flag. It no - longer serves a purpose now that the personal preference lists are - split into cipher/digest/zip. - -2002-06-14 Timo Schulz - - * skclist.c (is_insecure): Implemented. - -2002-06-12 David Shaw - - * keyserver.c (keyserver_spawn): Properly handle PROGRAM responses - when they have a CRLF ending. Noted by Keith Ray. - - * keyserver.c (keyserver_spawn): Handle CRLF endings from - keyserver helpers. Also don't leak the last line worth of memory - from the keyserver response. - - * main.h, misc.c (deprecated_warning): New function to warn about - deprecated options and commands. - - * g10.c (main), keyserver-internal.h, keyserver.c - (parse_keyserver_uri): Use new deprecated function to warn about - honor-http-proxy, auto-key-retrieve, and x-broken-hkp. - -2002-06-11 David Shaw - - * Makefile.am: link gpg with NETLIBS for the built-in HKP access. - -2002-06-10 David Shaw - - * options.h, keyserver.c (keyserver_opts), g10.c (main): New - keyserver option "include-subkeys". This feature already existed, - but now can be turned off. It defaults to on. - - * options.h, keyserver.c (parse_keyserver_options, - keyserver_spawn): There are now enough options to justify making a - structure for the keyserver options rather than a page of - if-then-else-if-then-etc. - - * getkey.c (merge_keys_and_selfsig, merge_selfsigs_main): Fix bug - in calculating key expiration dates. - -2002-06-09 David Shaw - - * keydb.h, getkey.c (get_user_id_native), import.c (import_one): - Display user ID while importing a key. Note this applies to both - --import and keyserver --recv-keys. - - * exec.c (exec_finish): Log unnatural exit (core dump, killed - manually, etc) for fork/exec/pipe child processes. - -2002-06-08 Timo Schulz - - * encode.c (encode_symmetric): Disable the compat flag - when the expert mode is enabled. - -2002-06-07 David Shaw - - * options.skel, options.h, main.h, keydb.h, pkclist.c - (build_pk_list, expand_groups), g10.c (main, add_group): Add new - "group" command to allow one name to expand into multiple keys. - For simplicity, and to avoid potential loops, we only expand once - - you can't make an alias that points to an alias. - - * main.h, g10.c (main), keygen.c (build_personal_digest_list): - Simplify the default digest list - there is really no need for the - other hashes since they will never be used after SHA-1 in the - list. - - * options.skel, options.h, g10.c (main), hkp.c (hkp_ask_import, - hkp_export, hkp_search), keyserver.c (parse_keyserver_options, - parse_keyserver_uri, keyserver_work, keyserver_refresh): Make the - "x-broken-hkp" keyserver scheme into keyserver-option - "broken-http-proxy". Move honor_http_proxy into - keyserver_options. Canonicalize the three variations of "hkp", - "x-hkp", and "x-broken-hkp" into "hkp". - -2002-06-07 Stefan Bellon - - * g10.c [__riscos__]: Added --attribute-file to do the same as - --attribute-fd, but with a filename not a fd as argument. - Added magic symbol for RISC OS to use different memory management. - - * gpgv.c [__riscos__]: Added magic symbol for RISC OS to use - different memory management. - -2002-06-06 David Shaw - - * main.h, g10.c (main), keygen.c (build_personal_digest_list): Put - in a default digest preference list consisting of SHA-1, followed - by every other installed digest except MD5. Note this is the same - as having no digest preference at all except for SHA-1 being - favored. - - * options.h, g10.c (main), keygen.c (keygen_set_std_prefs), - pkclist.c (select_algo_from_prefs): Split - --personal-preference-list into three: - --personal-{cipher|digest|compress}-preferences. This allows a - user to set one without affecting another (i.e. setting only a - digest pref doesn't imply an empty cipher pref). - - * exec.c (exec_read): This is a safer way of guessing the return - value of system(). Noted by Stefan Bellon. - -2002-06-05 David Shaw - - * hkp.c (parse_hkp_index): Be more robust with keyservers - returning very unparseable responses. - - * exec.c (exec_read): Catch and display an error when the remote - process exits unnaturally (i.e. segfault) so the user knows what - happened. Also fix exec_write stub which has a different number - of arguments now. - -2002-06-05 Timo Schulz - - * encode.c (encode_simple): Ignore the new mode for RFC1991. - * mainproc.c (symkey_decrypt_sesskey): Better check for weird - keysizes. - -2002-06-05 Timo Schulz - - * encode.c (encode_sesskey): New. - (encode_simple): Use it here. But by default we use the compat - mode which supress to generate encrypted session keys. - -2002-06-05 Timo Schulz - - * mainproc.c (symkey_decrypt_sesskey): New. - (proc_symkey_enc): Support for encrypted session keys. - -2002-06-04 David Shaw - - * sign.c (hash_for, sign_file): When encrypting and signing at the - same time, consult the various hash prefs to pick a hash algorithm - to use. Pass in a 160-bit hint if any of the signing keys are - DSA. - - * keydb.h, pkclist.c (select_algo_from_prefs, algo_available): - Pass a "hints" opaque pointer in to let the caller give hints as - to what algorithms would be acceptable. The only current hint is - for PREFTYPE_HASH to require a 160-bit hash for DSA. Change all - callers in encode.c (encode_crypt, encrypt_filter) and sign.c - (sign_file). If we settle on MD5 as the best algorithm based - solely on recepient keys and SHA1 is also a possibility, use SHA1 - unless the user intentionally chose MD5. This is as per 2440:13. - - * exec.c (make_tempdir): Fix duplicated filename problem. - -2002-06-03 David Shaw - - * packet.h, parse-packet.c (enum_sig_subpkt): Report back from - enum_sig_subpkt when a subpacket is critical and change all - callers in keylist.c (show_policy_url, show_notation), mainproc.c - (print_notation_data), and pkclist.c (do_show_revocation_reason). - - * keylist.c (show_policy_url, show_notation): Display if the - policy or notation is critical. - -2002-06-03 David Shaw - - * main.h, g10.c (main), keylist.c (dump_attribs, set_attrib_fd, - list_keyblock_print, list_keyblock_colon), status.h, status.c - (get_status_string): New --attribute-fd feature to dump the - contents of attribute subpackets for frontends. If --status-fd is - also used, then a new status tag ATTRIBUTE is provided for each - subpacket. - - * packet.h, getkey.c (fixup_uidnode, merge_selfsigs_main, - merge_selfsigs_subkey), parse-packet.c (setup_user_id): Keep track - of the expiration time of a user ID, and while we're at it, use - the expired flag from the selfsig rather than reparsing the - SIG_EXPIRE subpacket. - - * photoid.c (generate_photo_id): When adding a new photo ID, - showing the photo for confirmation is not safe when noninteractive - since the "user" may not be able to dismiss a viewer window. - Noted by Timo Schulz. - -2002-06-03 David Shaw - - * options.skel: Sample photo viewers for Win32. - - * misc.c (pct_expando): Use the seckey for %k/%K if the pubkey is - not available. - - * photoid.h, photoid.c (show_photos): Include the seckey in case a - user tries to view a photo on a secret key, and change all callers - in keyedit.c (menu_showphoto), keylist.c (list_keyblock_print), - and photoid.c (generate_photo_id). - -2002-06-02 David Shaw - - * photoid.c (show_photos): Work properly when not called with a - public key. - -2002-05-31 David Shaw - - * sign.c (mk_notation_and_policy): Free unneeded buffer. - - * hkp.c (parse_hkp_index): Properly handle the '&' character - (i.e. "&") in HKP responses. - - * getkey.c (merge_selfsigs_main): Fix reversed expiration time - check with self-sigs. - - * keyedit.c (sign_uids): When making a new self-sig on a v3 key, - make a v3 self-sig unless it is currently a v3 self-sig being - promoted to v4. - -2002-05-31 Timo Schulz - - * pkclist.c (do_show_revocation_reason): Don't use capital - letters for non-interactive output. - (show_revocation_reason): Now it is global. - * pubkey-enc.c (get_it): Show if the key has been revoked. - -2002-05-30 David Shaw - - * sign.c (write_signature_packets, sign_file, clearsign_file, - sign_symencrypt_file): Make a v4 signature if a policy URL or - notation is set, unless v3 sigs are forced via rfc1991 or - force-v3-sigs. Also remove some doubled code and clarify an error - message (we don't sign in PGP2 mode - just detach-sign). - - * parse-packet.c (parse_one_sig_subpkt): Add KS_FLAGS to the "any - size" section. - -2002-05-29 David Shaw - - * keygen.c (keygen_set_std_prefs, add_feature_mdc): Use "mdc" and - "no-mdc" in the prefs string to allow switching on and off the MDC - feature. This is needed to properly export a key from GnuPG for - use on PGP which does not support MDC - without this, MDC-capable - implementations will still try and generate MDCs which will break - PGP. - - * keygen.c (keygen_get_std_prefs): Show "[mdc]" in prefs string if - it is enabled. - - * options.h, g10.c (main), cipher.c (write_header), keygen.c - (keygen_set_std_prefs): For consistency, allow the user to specify - mdc/no-mdc in the --personal-preference-list. If disabled, it - acts just like --disable-mdc. - -2002-05-29 David Shaw - - * options.h, exec.c: Add some debugging info, using the 1024 debug - flag. - - * exec.c (win_system): New system()-like function for win32 that - does not return until the child process terminates. Of course, - this doesn't help if the process itself exits before it is - finished. - -2002-05-29 Werner Koch - - * encode.c (encode_simple): Intialize PKT when --no-literal is used. - - * keyedit.c (show_key_with_all_names_colon): Renamed the record - for revocation keys to "rvk". - -2002-05-27 Werner Koch - - * keyedit.c (show_key_with_all_names_colon): New. - (show_key_with_all_names): Divert to new function when required. - Sanitize printing of revoker name. - -2002-05-27 David Shaw - - * build-packet.c (build_sig_subpkt): Handle setting sig flags for - certain subpacket types (notation, policy url, exportable, - revocable). keyedit.c (sign_mk_attrib): Flags no longer need to - be set here. - - * packet.h, parse-packet.c (parse_one_sig_subpkt), build-packet.c - (build_sig_subpkt): Call parse_one_sig_subpkt to sanity check - buffer lengths before building a sig subpacket. - -2002-05-26 David Shaw - - * sign.c (mk_notation_and_policy): Include secret key to enable %s - expandos, and pass notations through pct_expando as well. - - * main.h, misc.c (pct_expando): Add %s and %S expandos for - signer's keyid. - -2002-05-25 David Shaw - - * g10.c (strusage, build_list): Add compress algorithms to - --version list. Show algorithm numbers when --verbose --version - is done. - -2002-05-22 David Shaw - - * options.h, main.h, keygen.c (keygen_set_set_prefs, - keygen_get_std_prefs, keygen_upd_std_prefs), keyedit.c - (keyedit_menu), g10.c (main), pkclist.c (select_algo_from_prefs): - Add --personal-preference-list which allows the user to factor in - their own preferred algorithms when the preference lists are - consulted. Obviously, this does not let the user violate a - recepient's preferences (and the RFC) - this only influences the - ranking of the agreed-on (and available) algorithms from the - recepients. Suggested by David Hollenberg. - - * options.h, keygen.c (keygen_set_std_prefs), g10.c (main): Rename - --preference-list to --default-preference-list (as that is what it - really is), and make it a true default in that if the user selects - "default" they get this list and not the compiled-in list. - -2002-05-22 Werner Koch - - * g10.c (main): Add missing LF in a info printout and made it - translatable. Noted by Michael Tokarev. - -2002-05-21 Werner Koch - - * g10.c (main): Removed the undef of USE_SHM_COPROCESSING which - was erroneously introduced on 2002-01-09. - - * signal.c (got_fatal_signal): Don't write the Nul to stderr. - Reported by David Hollenberg. - -2002-05-18 David Shaw - - * main.h, g10.c (main), revoke.c (gen_desig_revoke): Generate a - designated revocation via --desig-revoke - - * keyedit.c (keyedit_menu, menu_addrevoker): New "addrevoker" - command to add a designated revoker to a key. - -2002-05-17 David Shaw - - * gpgv.c: Add stub for get_ownertrust(). - - * g10.c (main): --allow-freeform-uid should be implied by - OpenPGP. Add --no-allow-freeform-uid. - - * keyedit.c (sign_uids): Issue a warning when signing a - non-selfsigned uid. - - * getkey.c (merge_selfsigs_main): If a key has no selfsigs, and - allow-non-selfsigned-uid is not set, still try and make the key - valid by checking all uids for a signature from an ultimately - trusted key. - -2002-05-16 David Shaw - - * main.h, keygen.c (keygen_add_revkey): Add revocation key - subpackets to a signature (callable by - make_keysig_packet). (write_direct_sig): Write a 1F direct key - signature. (parse_revocation_key): Parse a string in - algo:fpr:sensitive format into a revocation - key. (get_parameter_revkey, do_generate_keypair): Call above - functions when prompted from a batch key generation file. - - * build-packet.c (build_sig_subpkt): Allow multiple revocation key - subpackets in a single sig. - - * keydb.h, getkey.c (get_seckey_byfprint): Same as - get_pubkey_byfprint, except for secret keys. We only know the - fingerprint of a revocation key, so this is needed to retrieve the - secret key needed to issue a revokation. - - * packet.h, parse-packet.c (parse_signature, parse_revkeys): Split - revkey parsing off into a new function that can be used to reparse - after manipulating the revkey list. - - * sign.c (make_keysig_packet): Ability to make 1F direct key - signatures. - -2002-05-15 David Shaw - - * options.skel: keyserver.pgp.com is gone, so list pgp.surfnet.nl - as a sample LDAP server instead. - - * getkey.c (merge_selfsigs_main): Properly handle multiple - revocation keys in a single packet. Properly handle revocation - keys that are in out-of-order packets. Remove duplicates in - revocation key list. - -2002-05-14 Timo Schulz - - * exec.c (make_tempdir) [MINGW32]: Added missing '\'. - -2002-05-14 Stefan Bellon - - * exec.c (make_tempdir): Make use of EXTSEP_S instead of hardcoded - dot as extension separator. - -2002-05-13 David Shaw - - * photoid.c (show_photos): Use the long keyid as the filename for - the photo. Use the short keyid as the filename on 8.3 systems. - - * exec.h, exec.c (make_tempdir, exec_write, exec_finish): Allow - caller to specify filename. This should make things easier on - windows and macs where the file extension is required, but a whole - filename is even better. - - * keyedit.c (show_key_with_all_names, show_prefs): Show proper - prefs for a v4 key uid with no selfsig at all. - - * misc.c (check_permissions): Don't check permissions on - non-normal files (pipes, character devices, etc.) - -2002-05-11 Werner Koch - - * mainproc.c (proc_symkey_enc): Avoid segv in case the parser - encountered an invalid packet. - - * keyserver.c (keyserver_export): Get confirmation before sending - all keys. - -2002-05-10 Stefan Bellon - - * g10.c, hkp.c, keyedit.c, keyserver.c: Replaced all occurrances - of strcasecmp with ascii_strcasecmp and all occurrances of - strncasecmp with ascii_memcasecmp. - -2002-05-10 David Shaw - - * packet.h, getkey.c (fixup_uidnode), keyedit.c (show_prefs): Show - assumed prefs for hash and compression as well as the cipher pref. - Show assumed prefs if there are no prefs at all on a v4 - self-signed key. - - * options.h, g10.c (main), sign.c (make_keysig_packet): New - --cert-digest-algo function to override the default key signing - hash algorithm. - -2002-05-09 David Shaw - - * getkey.c (merge_selfsigs_main): Make sure the revocation key - list starts clean as this function may be called more than once - (e.g. from functions in --edit). - - * g10.c, encode.c (encode_crypt), sign.c (sign_file, - sign_symencrypt_file): Make --compress-algo work like the - documentation says. It should be like --cipher-algo and - --digest-algo in that it can override the preferences calculation - and impose the setting the user wants. No --compress-algo setting - allows the usual preferences calculation to take place. - - * main.h, compress.c (compress_filter): use new - DEFAULT_COMPRESS_ALGO define, and add a sanity check for compress - algo value. - -2002-05-08 David Shaw - - * pkclist.c (select_algo_from_prefs): There is an assumed - compression preference for uncompressed data. - -2002-05-07 David Shaw - - * options.h, g10.c (main), getkey.c (finish_lookup), pkclist.c - (algo_available): --pgp7, identical to --pgp6 except that it - permits a few algorithms that PGP 7 added: AES128, AES192, AES256, - and TWOFISH. Any more of these --pgpX flags, and it'll be time to - start looking at a generic --emulate-pgp X option. - - * export.c (do_export_stream): Warn the user when exporting a - secret key if it or any of its secret subkeys are protected with - SHA1 while simple_sk_checksum is set. - - * parse-packet.c (parse_key): Show when the SHA1 protection is - used in --list-packets. - - * options.h, build-packet.c (do_comment), g10.c (main): Rename - --no-comment as --sk-comments/--no-sk-comments (--no-comment still - works) and make the default be --no-sk-comments. - -2002-05-07 Werner Koch - - * keygen.c (get_parameter_algo): Never allow generation of the - deprecated RSA-E or RSA-S flavors of PGP RSA. - (ask_algo): Allow generation of RSA sign and encrypt in expert - mode. Don't allow ElGamal S+E unless in expert mode. - * helptext.c: Added entry keygen.algo.rsa_se. - -2002-05-07 David Shaw - - * keyedit.c (sign_uids): If --expert is set, allow re-signing a - uid to promote a v3 self-sig to a v4 one. This essentially - deletes the old v3 self-sig and replaces it with a v4 one. - - * packet.h, parse-packet.c (parse_key), getkey.c - (merge_keys_and_selfsig, merge_selfsigs_main): a v3 key with a v4 - self-sig must never let the v4 self-sig express a key expiration - time that extends beyond the original v3 expiration time. - -2002-05-06 David Shaw - - * keyedit.c (sign_uids): When making a self-signature via "sign" - don't ask about sig level or expiration, and include the usual - preferences and such for v4 self-sigs. (menu_set_preferences): - Convert uids from UTF8 to native before printing. - - * keyedit.c (sign_uids): Convert uids from UTF8 to native before - printing. (menu_set_primary_uid): Show error if the user tries to - make a uid with a v3 self-sig primary. - -2002-05-05 David Shaw - - * import.c (import_one): When merging with a key we already have, - don't let a key conflict (same keyid but different key) stop the - import: just skip the bad key and continue. - - * exec.c (make_tempdir): Under Win32, don't try environment - variables for temp directories - GetTempDir tries environment - variables internally, and it's better not to second-guess it in - case MS adds some sort of temp dir handling to Windows at some - point. - -2002-05-05 Timo Schulz - - * mainproc.c (proc_symkey_enc): Don't ask for a passphrase - in the list only mode. - -2002-05-05 David Shaw - - * keyserver.c (keyserver_refresh): --refresh-keys implies - --merge-only so as not to import keys with keyids that match the - ones being refreshed. Noted by Florian Weimer. - -2002-05-04 Stefan Bellon - - * free-packet.c (copy_public_key): Don't call m_alloc(0), therefore - added consistency check for revkey and numrefkeys. - - * getkey.c (check_revocation_keys): Added consistency check for - revkey and numrefkeys. - - * keyedit.c (show_key_with_all_names): Likewise. - -2002-05-03 David Shaw - - * photoid.c: Provide default image viewer for Win32. - - * misc.c (pct_expando): %t means extension, not name ("jpg", not - "jpeg"). - - * keyserver.c (keyserver_spawn), photoid.c (show_photos), exec.h, - exec.c: Allow the caller to determine the temp file extension when - starting an exec_write and change all callers. - - * keyedit.c (sign_uids): Nonrevocable key signatures cause an - automatic promotion to v4. - - * exec.c: Provide stubs for exec_ functions when NO_EXEC is - defined. - -2002-05-02 David Shaw - - * photoid.h, photoid.c (parse_image_header, image_type_to_string): - Useful functions to return data about an image. - - * packet.h, parse-packet.c (make_attribute_uidname, - parse_attribute_subpkts, parse_attribute), photoid.h, photoid.c - (show_photos): Handle multiple images in a single attribute - packet. - - * main.h, misc.c (pct_expando), sign.c (mk_notation_and_policy), - photoid.c (show_photos): Simpler expando code that does not - require using compile-time string sizes. Call - image_type_to_string to get image strings (i.e. "jpg", - "image/jpeg"). Change all callers. - - * keyedit.c (menu_showphoto), keylist.c (list_keyblock_print): - Allow viewing multiple images within a single attribute packet. - - * gpgv.c: Various stubs for link happiness. - -2002-05-02 David Shaw - - * build-packet.c (build_sig_subpkt), keyedit.c (sign_uids), - options.h, sign.c (mk_notation_and_policy), g10.c (main, - add_notation_data, add_policy_url (new), check_policy_url - (removed)): Allow multiple policy URLs on a given signature. - Split "--notation-data" into "--cert-notation" and - "--sig-notation" so the user can set different policies for key - and data signing. For backwards compatibility, "--notation-data" - sets both, as before. - -2002-05-02 Werner Koch - - * options.skel: Removed the comment on trusted-keys because this - option is now deprecated. - -2002-05-01 David Shaw - - * keyedit.c (menu_adduid): 2440bis04 says that multiple attribute - packets on a given key are legal. - - * keyserver.c (keyserver_refresh): the fake v3 keyid hack applies - to "mailto" URLs as well since they are also served by pksd. - -2002-04-29 Werner Koch - - Added a copyright year for files changed this year. - -2002-04-25 Werner Koch - - * g10.c, options.h: New options --display, --ttyname, --ttytype, - --lc-ctype, --lc-messages to be used with future versions of the - gpg-agent. - * passphrase.c (agent_send_option,agent_send_all_options): New. - (agent_open): Send options to the agent. - - * trustdb.c (update_ownertrust, clear_ownertrust): Do an explicit - do_sync because revalidation_mark does it only if when the - timestamp actually changes. - -2002-04-23 David Shaw - - * main.h, keygen.c (do_generate_keypair), keylist.c - (print_signature_stats, list_all, list_one, list_keyblock, - list_keyblock_print, list_keyblock_colon): After generating a new - key, show the key information (name, keyid, fingerprint, etc.) - Also do not print uncheckable signatures (missing key..) in - --check-sigs. Print statistics (N missing keys, etc.) after - --check-sigs. - - * keyedit.c (sign_uids): When signing a key with an expiration - date on it, the "Do you want your signature to expire at the same - time?" question should default to YES. - -2002-04-22 David Shaw - - * parse-packet.c (parse_plaintext), packet.h, plaintext.c - (handle_plaintext): Fix bug in handling literal packets with - zero-length data (no data was being confused with partial body - length). - - * misc.c (pct_expando), options.skel: %t means extension ("jpg"). - %T means MIME type ("image/jpeg"). - - * import.c (import_one): Only trigger trust update if the keyring - is actually changed. - - * export.c (do_export_stream): Missing a m_free. - -2002-04-22 Stefan Bellon - - * keyid.c (expirestr_from_sk, expirestr_from_sig): Added _() to - string constant. - - * exec.c (make_tempdir) [__riscos__]: Better placement of - temporary file. - -2002-04-20 David Shaw - - * keygen.c (generate_subkeypair): 2440bis04 adds that creating - subkeys on v3 keys is a MUST NOT. - - * getkey.c (finish_lookup): The --pgp6 "use the primary key" - behavior should only apply while data signing and not encryption. - Noted by Roger Sondermann. - -2002-04-19 Werner Koch - - * keygen.c (keygen_set_std_prefs): Put back 3DES because the RFC - says it is good form to do so. - -2002-04-19 David Shaw - - * keyedit.c (menu_deluid): Only cause a trust update if we delete - a non-revoked user id. - - * hkp.c (hkp_ask_import), keyserver.c (parse_keyserver_options, - keyserver_spawn), options.h: Remove fast-import keyserver option - (no longer meaningful). - - * g10.c (main), keyedit.c (sign_uids), options.h: Change - --default-check-level to --default-cert-check-level as it makes - clear what it operates on. - - * g10.c (main): --pgp6 also implies --no-ask-sig-expire. - - * delkey.c (do_delete_key): Comment. - - * keyedit.c (sign_uids, keyedit_menu, menu_deluid, menu_delsig, - menu_expire, menu_revsig, menu_revkey): Only force a trustdb check - if we did something that changes it. - - * g10.c: add "--auto-check-trustdb" to override a - "--no-auto-check-trustdb" - -2002-04-19 Werner Koch - - * tdbio.c (tdbio_write_nextcheck): Return a status whether the - stamp was actually changed. - * trustdb.c (revalidation_mark): Sync the changes. Removed the - sync operation done by its callers. - (get_validity): Add logic for maintaining a pending_check flag. - (clear_ownertrust): New. - - * keyedit.c (sign_uids): Don't call revalidation_mark depending on - primary_pk. - (keyedit_menu): Call revalidation_mark after "trust". - (show_key_with_all_names): Print a warning on the wrong listed key - validity. - - * delkey.c (do_delete_key): Clear the owenertrust information when - deleting a public key. - -2002-04-18 Werner Koch - - * seskey.c (encode_md_value): Print an error message if a wrong - digest algorithm is used with DSA. Changed all callers to cope - with a NULL return. Problem noted by Imad R. Faiad. - -2002-04-18 David Shaw - - * trustdb.c (mark_usable_uid_certs): Properly handle nonrevocable - signatures that can expire. In short, the only thing that can - override an unexpired nonrevocable signature is another unexpired - nonrevocable signature. - - * getkey.c (finish_lookup): Always use primary signing key for - signatures when --pgp6 is on since pgp6 and 7 do not understand - signatures made by signing subkeys. - -2002-04-18 Werner Koch - - * trustdb.c (validate_keys): Never schedule a nextcheck into the - past. - (validate_key_list): New arg curtime use it to set next_expire. - (validate_one_keyblock): Take the current time from the caller. - (clear_validity, reset_unconnected_keys): New. - (validate_keys): Reset all unconnected keys. - - * getkey.c (premerge_public_with_secret): Fixed 0x12345678! syntax - for use with secret keys. - (lookup): Advance the searchmode after a search FIRST. - - * seckey-cert.c (do_check): Always calculate the old checksum for - use after unprotection. - - * g10.c, options.skel: New option --no-escape-from. Made - --escape-from and --force-v3-sigs the default and removed them - from the options skeleton. - -2002-04-16 Werner Koch - - * parse-packet.c (parse_key): Support a SHA1 checksum as per - draft-rfc2440-bis04. - * packet.h (PKT_secret_key): Add field sha1chk. - * seckey-cert.c (do_check): Check the SHA1 checksum - (protect_secret_key): And create it. - * build-packet.c (do_secret_key): Mark it as sha-1 protected. - * g10.c, options.h: New option --simple-sk-checksum. - -2002-04-13 David Shaw - - * parse-packet.c (parse_signature): Minor fix - signatures should - expire at their expiration time and not one second later. - - * keygen.c (proc_parameter_file): Allow specifying preferences - string (i.e. "s5 s2 z1 z2", etc) in a batchmode key generation - file. - - * keyedit.c (keyedit_menu): Print standard error message when - signing a revoked key (no new translation). - - * getkey.c (merge_selfsigs): Get the default set of key prefs from - the real (not attribute) primary uid. - -2002-04-12 David Shaw - - * pkclist.c (build_pk_list): Fix bug that allowed a key to be - selected twice in batch mode if one instance was the default - recipient and the other was an encrypt-to. Noted by Stefan - Bellon. - - * parse-packet.c (dump_sig_subpkt): Show data in trust and regexp - sig subpackets. - - * keyedit.c (keyedit_menu): Use new function real_uids_left to - prevent deleting the last real (i.e. non-attribute) uid. Again, - according to the attribute draft. (menu_showphoto): Make another - string translatable. - -2002-04-11 David Shaw - - * build-packet.c (build_sig_subpkt): Delete subpackets from both - hashed and unhashed area on update. (find_subpkt): No longer - needed. - - * keyedit.c (sign_uids): With --pgp2 on, refuse to sign a v3 key - with a v4 signature. As usual, --expert overrides. Try to tweak - some strings to a closer match so they can all be translated in - one place. Use different helptext keys to allow different help - text for different questions. - - * keygen.c (keygen_upd_std_prefs): Remove preferences from both - hashed and unhashed areas if they are not going to be used. - -2002-04-10 David Shaw - - * misc.c (pct_expando), options.skel: Use %t to indicate type of a - photo ID (in this version, it's always "jpeg"). Also tweak string - expansion loop to minimize reallocs. - - * mainproc.c (do_check_sig): Variable type fix. - - * keyedit.c (menu_set_primary_uid): Differentiate between true - user IDs and attribute user IDs when making one of them primary. - That is, if we are making a user ID primary, we alter user IDs. - If we are making an attribute packet primary, we alter attribute - packets. This matches the language in the latest attribute packet - draft. - - * keyedit.c (sign_uids): No need for the empty string hack. - - * getkey.c (fixup_uidnode): Only accept preferences from the - hashed segment of the self-sig. - -2002-04-10 Werner Koch - - * tdbio.c (migrate_from_v2): Fixed the offset to read the old - ownertrust value and only add entries to the table if we really - have a value. - -2002-04-08 David Shaw - - * status.h, status.c (get_status_string): Add KEYEXPIRED, EXPSIG, - and EXPKEYSIG. Add "deprecated-use-keyexpired-instead" to - SIGEXPIRED. - - * sig-check.c (do_check): Start transition from SIGEXPIRED to - KEYEXPIRED, since the actual event is signature verification by an - expired key and not an expired signature. (do_signature_check, - packet.h): Rename as signature_check2, make public, and change all - callers. - - * mainproc.c (check_sig_and_print, do_check_sig): Use status - EXPSIG for an expired, but good, signature. Add the expiration - time (or 0) to the VALIDSIG status line. Use status KEYEXPSIG for - a good signature from an expired key. - - * g10.c (main): remove checks for no arguments now that argparse - does it. - -2002-04-06 Werner Koch - - * keyring.c (keyring_get_keyblock): Disable the keylist mode here. - - * encode.c (encode_simple, encode_crypt): Only test on compressed - files if a compress level was not explicity set. - - * keygen.c (keygen_set_std_prefs): Removed Blowfish and Twofish - from the list of default preferences, swapped the preferences of - RMD160 and SHA1. Don't include a preference to 3DES unless the - IDEA kludge gets used. - - * free-packet.c (free_packet): call free_encrypted also for - PKT_ENCRYPTED_MDC. - - * compress.c (release_context): New. - (handle_compressed): Allocate the context and setup a closure to - release the context. This is required because there is no - guarabntee that the filter gets popped from the chain at the end - of the function. Problem noted by Timo and probably also the - cause for a couple of other reports. - (compress_filter): Use the release function if set. - - * tdbio.c [__CYGWIN32__]: Don't rename ftruncate. Noted by - Disastry. - - * parse-packet.c (parse_signature): Put parens around a bit test. - - * exec.c (make_tempdir): Double backslash for TMP directory - creation under Windows. Better strlen the DIRSEP_S constants for - allocation measurements. - - * decrypt.c (decrypt_messages): Release the passphrase aquired - by get_last_passphrase. - -2002-04-02 Werner Koch - - * Makefile.am (EXTRA_DIST): Removed OPTIONS an pubring.asc - they - are no longer of any use. - -2002-04-03 David Shaw - - * keyserver.c (parse_keyserver_options): fix auto-key-retrieve to - actually work as a keyserver-option (noted by Roger Sondermann). - - * keylist.c (reorder_keyblock): do not reorder the primary - attribute packet - the first user ID must be a genuine one. - -2002-03-31 David Shaw - - * keylist.c (list_keyblock_colon): Fix ownertrust display with - --with-colons. - - * keygen.c (generate_user_id), photoid.c (generate_photo_id): - Properly initialize the user ID refcount. A few more "y/n" -> - "y/N" in photoid.c. - - * keyedit.c (ask_revoke_sig): Warn the user if they are about to - revoke an expired sig (not a problem, but they should know). Also - tweak a few prompts to change "y/n" to "y/N", which is how most - other prompts are written. - - * keyserver.c (keyserver_search_prompt): Control-d escapes the - keyserver search prompt. - - * pkclist.c (show_revocation_reason & callers): If a subkey is - considered revoked solely because the parent key is revoked, print - the revocation reason from the parent key. - - * trustdb.c (get_validity): Allow revocation/expiration to apply - to a uid/key with no entry in the trustdb. - -2002-03-29 David Shaw - - * keyserver.c (printunquoted): unquote backslashes from keyserver - searches - - * hkp.c (write_quoted): quote backslashes from keyserver searches - -2002-03-26 Werner Koch - - * keygen.c (ask_keysize): Removed the warning for key sizes > 1536. - -2002-03-25 Werner Koch - - * keyedit.c (sign_uids): Use 2 strings and not a %s so that - translations can be done the right way. - * helptext.c: Fixed small typo. - -2002-03-23 David Shaw - - * import.c (append_uid, merge_sigs): it is okay to import - completely non-signed uids now (with --allow-non-selfsigned-uid). - - * getkey.c (get_primary_uid, merge_selfsigs_main): do not choose - an attribute packet (i.e. photo) as primary uid. This prevents - oddities like "Good signature from [image of size 2671]". This is - still not perfect (one can still select an attribute packet as - primary in --edit), but is closer to the way the draft is going. - - * g10.c (build_list): algorithms should include 110. - - * g10.c (main): --pgp2 implies --no-ask-sig-expire and - --no-ask-cert-expire as those would cause a v4 sig/cert. - - * armor.c (is_armor_header): be more lenient in what constitutes a - valid armor header (i.e. -----BEGIN blah blah-----) as some - Windows programs seem to add spaces at the end. --openpgp makes - it strict again. - -2002-03-18 David Shaw - - * keyserver.c (keyserver_search_prompt): Properly handle a "no - keys found" case from the internal HKP code (external HKP is ok). - Also, make a COUNT -1 (i.e. streamed) keyserver response a little - more efficient. - - * g10.c (main): Add --no-allow-non-selfsigned-uid - -2002-03-17 David Shaw - - * g10.c (main): --openpgp implies --allow-non-selfsigned-uid. - - * getkey.c (merge_selfsigs_main): If none of the uids are primary - (because none are valid) then pick the first to be primary (but - still invalid). This is for cosmetics in case some display needs - to print a user ID from a non-selfsigned key. Also use - --allow-non-selfsigned-uid to make such a key valid and not - --always-trust. The key is *not* automatically trusted via - --allow-non-selfsigned-uid. - - * mainproc.c (check_sig_and_print): Make sure non-selfsigned uids - print [uncertain] on verification even though one is primary now. - - * getkey.c (merge_selfsigs): If the main key is not valid, then - neither are the subkeys. - - * import.c (import_one): Allow --allow-non-selfsigned-uid to work - on completely unsigned keys. Print the uids in UTF8. Remove - mark_non_selfsigned_uids_valid(). - - * keyedit.c (show_key_with_all_names): Show revocation key as - UTF8. - - * sign.c (clearsign_file): Allow --not-dash-escaped to work with - v3 keys. - -2002-03-14 Werner Koch - - * main.h: Changed the default algorithms to CAST5 and SHA1. - -2002-03-13 David Shaw - - * import.c (chk_self_sigs): Show which user ID a bad self-sig - (invald sig or unsupported public key algorithm) resides on. - - * import.c (chk_self_sigs): any valid self-sig should mark a user - ID or subkey as valid - otherwise, an attacker could DoS the user - by inventing a bogus invalid self-signature. - -2002-03-07 David Shaw - - * g10.c (main): make a few more strings translatable. - - * options.h, options.skel, g10.c (main), gpgv.c, mainproc.c - (check_sig_and_print), keyserver.c (parse_keyserver_options): - --auto-key-retrieve should really be a keyserver-option variable. - - * import.c (revocation_present): new function to print a warning - if a key is imported that has been revoked by designated revoker, - but the designated revoker is not present to verify the - revocation. If keyserver-options auto-key-retrieve is set, try - and fetch the designated revoker from the keyserver. - - * import.c (import_one): call revocation_present after importing a - new key. Note that this applies to --import, --recv-keys, and - --search-keys. - - * keyserver-internal.h, keyserver.c (keyserver_import_fprint): - import via fingerprint (for revocation keys). - - * keyserver.c (keyserver_import_keyid): much simpler - implementation now that we're using KEYDB_SEARCH_DESC internally. - -2002-03-04 David Shaw - - * revoke.c (gen_revoke): do not prompt for revocation reason for - v3 revocations (unless force-v4-certs is on) since they wouldn't - be used anyway. - - * keyedit.c (menu_revsig): show the status of the sigs - (exportable? revocable?) to the user before prompting for which - sig to revoke. Also, make sure that local signatures get local - revocations. - - * keyedit.c (ask_revoke_sig): remind the user which sigs are - local. - - * g10.c (main): Add "exec-path" variable to override PATH for - execing programs. - - * export.c (do_export_stream): properly check return code from - classify_user_id to catch unclassifiable keys. - -2002-03-03 David Shaw - - * parse-packet.c (parse_signature): variable type tweak for RISC - OS (from Stefan) - -2002-02-28 David Shaw - - * getkey.c (check_revocation_keys): New function to check a - revocation against a list of potential revocation keys. Note the - loop-breaking code here. This is to prevent blowing up if A is - B's revocation key, while B is also A's. Note also that this is - written so that a revoked revoker can still issue revocations: - i.e. If A revokes B, but A is revoked, B is still revoked. I'm - not completely convinced this is the proper behavior, but it - matches how PGP does it. It does at least have the advantage of - much simpler code - my first version of this had lots of loop - maintaining code so you could chain revokers many levels deep and - if D was revoked, C was not, which meant that B was, and so on. - It was sort of scary, actually. - - * getkey.c (merge_selfsigs_main): Add any revocation keys onto the - pk. This is particularly interesting since we normally only get - data from the most recent 1F signature, but you need multiple 1F - sigs to properly handle revocation keys (PGP does it this way, and - a revocation key could be marked "sensitive" and hence in a - different signature). Also, if a pk has a revocation key set, - check for revocation sigs that were not made by us - if made by a - valid revocation key, mark the pk revoked. - - * packet.h, getkey.c (cache_public_key): do not cache key if - "dont_cache" is set. This allows the revocation key code to look - up a key and return information that may be inaccurate to prevent - loops without caching the fake data. - - * packet.h, sig-check.c (do_signature_check): Record if a - signature was made by a revoked pk. - - * packet.h, parse-packet.c (parse_one_sig_subpkt, - can_handle_critical, parse_signature): Get revocation key - information out of direct sigs. - - * keylist.c (list_keyblock_print): don't assume that the presence - of a 0x20 signature means the key is revoked. With revocation - keys, this may not be true if the revocation key is not around to - verify it or if verification failed. Also, 0x1F should get listed - as "sig", and not "unexpected signature class". - - * keyedit.c (show_key_with_all_names): Add a flag for printing - revoker information and change all callers. - - * import.c (merge_blocks): merge in any new direct key (0x1F) - sigs. - - * import.c (import_revoke_cert): don't keep processing after a - revocation is rejected. - - * import.c (delete_inv_parts): Allow importing a revocation - signature even if it was not issued by the key. This allows a - revocation key to issue it. Of course, the sig still needs to be - checked before we trust it. - - * free-packet.c (copy_public_key): Include a new copy of the - revocation keys when duping a pk. - - * free-packet.c (free_seckey_enc, release_public_key_parts): Free - any revocation keys that are attached to a sig or pk. - - * export.c (do_export_stream): Do not export signatures with - "sensitive" revocation keys in them. - -2002-02-27 David Shaw - - * export.c (do_export_stream): Do not include v3 keys in a - --export-secret-subkeys export. - - * getkey.c (merge_selfsigs_main): If a key isn't valid (say, - because of no self-signature), allow --always-trust to force it - valid so it can be trusted. - -2002-02-25 David Shaw - - * hkp.c (hkp_ask_import), hkp.h, keyserver.c (all): treat key - lists internally as fingerprints when possible. All this is via - KEYDB_SEARCH_DESC - no point in reinventing the wheel. This allows - the helper program to search the keyserver by fingerprint if - desired (and the keyserver supports it). Note that automatic - fingerprint promotion during refresh only applies to v4 keys as a - v4 fingerprint can be easily changed into a long or short key id, - and a v3 cannot. - - * pubkey-enc.c, getkey.c, misc.c, main.h: Take two copies of - hextobyte() from pubkey-enc.c and getkey.c and make them into one - copy in misc.c. - -2002-02-22 David Shaw - - * keyserver.c (keyserver_search_prompt): Detect a "no keys found" - case even if the helper program does not explicitly say how many - keys were found. - - * hkp.c (parse_hkp_index): Bug fix - don't report non-revoked keys - as revoked in HKP key searches. - -2002-02-19 Werner Koch - - * parse-packet.c (parse_trust): Made parsing more robust. - -2002-02-19 David Shaw - - * hkp.c (parse_hkp_index): Catch corruption in HKP index lines - (can be caused by broken or malicious keyservers). - - * keyserver.c (keyserver_work): Add KEYSERVER_NOT_SUPPORTED for - unsupported actions (say, a keyserver that has no way to search, - or a readonly keyserver that has no way to add). Also add a - USE_EXTERNAL_HKP define to disable the internal HKP keyserver - code. - -2002-02-14 Werner Koch - - * g10.c: New option --no-use-agent. - - * pkclist.c (check_signatures_trust): Always print the warning for - unknown and undefined trust. Removed the did_add cruft. Reported - by Janusz A. Urbanowicz. - -2002-02-11 David Shaw - - * hkp.c (parse_hkp_index): Bug fix - properly handle user IDs with - colons (":") in them while HKP searching. - -2002-02-09 David Shaw - - * misc.c (pct_expando): More comments. - - * keydb.h, sign.c (mk_notation_and_policy): Clarify what is a sig - and what is a cert. A sig has sigclass 0x00, 0x01, 0x02, or 0x40, - and everything else is a cert. - - * g10.c (main), keyedit.c (keyedit_menu): Add a "nrlsign" for - nonrevocable and local key signatures. - - * g10.c (main): Add a --no-force-mdc to undo --force-mdc. - - * options.h, g10.c (main), cipher.c (write_header): Add a knob to - --disable-mdc/--no-disable-mdc. Off by default, of course, but is - used in --pgp2 and --pgp6 modes. - - * pkclist.c (build_pk_list): Allow specifying multiple users in - the "Enter the user ID" loop. Enter a blank line to stop. Show - each key+id as it is added. - - * keylist.c (show_policy_url), mainproc.c (print_notation_data): - It is not illegal (though possibly silly) to have multiple policy - URLs in a given signature, so print all that are present. - - * hkp.c (hkp_search): More efficient implementation of URL-ifying - code. - -2002-02-04 David Shaw - - * main.h, misc.c (pct_expando): New function to generalize - %-expando processing in any arbitrary string. - - * photoid.c (show_photo): Call the new pct_expando function rather - than expand strings internally. - - * sign.c (mk_notation_and_policy): Show policy URLs and notations - when making a signature if show-policy/show-notation is on. - %-expand policy URLs during generation. This lets the user have - policy URLs of the form "http://notary.jabberwocky.com/keysign/%K" - which will generate a per-signature policy URL. - - * main.h, keylist.c (show_policy_url, show_notation): Add amount - to indent so the same function can be used in key listings as well - as during sig generation. Change all callers. - -2002-02-04 David Shaw - - * keyserver.c, options.h (parse_keyserver_options, keyidlist): - Workaround for the pksd and OKS keyserver bug that calculates v4 - RSA keyids as if they were v3. The workaround/hack is to fetch - both the v4 (e.g. 99242560) and v3 (e.g. 68FDDBC7) keyids. This - only happens for key refresh while using the HKP scheme and the - refresh-add-fake-v3-keyids keyserver option must be set. This - should stay off by default. - -2002-02-03 David Shaw - - * keyserver.c (keyserver_spawn): Bug fix - do not append keys to - each other when --sending more than one. - -2002-02-02 David Shaw - - * options.h, g10.c (main), keyedit.c (sign_uids), sign.c - (mk_notation_and_policy): Split "--set-policy-url" into - "--cert-policy-url" and "--sig-policy-url" so the user can set - different policies for key and data signing. For backwards - compatibility, "--set-policy-url" sets both, as before. - -2002-01-30 Werner Koch - - * g10.c (main): --gen-random --armor does now output a base64 - encoded string. - -2002-01-28 David Shaw - - * g10.c (main), options.h, pkclist.c (algo_available): --pgp6 - flag. This is not nearly as involved as --pgp2. In short, it - turns off force_mdc, turns on no_comment, escape_from, and - force_v3_sigs, and sets compression to 1. It also restricts the - user to IDEA (if present), 3DES, CAST5, MD5, SHA1, and RIPEMD160. - See the comments above algo_available() for lots of discussion on - why you would want to do this. - -2002-01-27 David Shaw - - * keygen.c (keygen_set_std_prefs): Comment - - * keyedit.c (sign_uids): Bug fix - when signing with multiple - secret keys at the same time, make sure each key gets the sigclass - prompt. - - * exec.c (exec_finish): Close the iobuf and FILE before trying to - waitpid, so the remote process will get a SIGPIPE and exit. This - is only a factor when using a pipe to communicate. - - * exec.c (exec_write): Disable cache-on-close of the fd iobuf (is - this right? Why is a fd iobuf cached at all?) - -2002-01-26 Werner Koch - - * g10.c, options.h: New option --gpg-agent-info - * passphrase.c (agent_open): Let it override the environment info. - * seckey-cert.c (check_secret_key): Always try 3 times when the - agent is enabled. - * options.skel: Describe --use-agent. - -2002-01-24 David Shaw - - * pubkey-enc.c (is_algo_in_prefs, get_it): Only check preferences - against keys with v4 self sigs - there is really little point in - warning for every single non-IDEA message encrypted to an old key. - - * pkclist.c (select_algo_from_prefs): Only put in the fake IDEA - preference if --pgp2 is on. - - * mainproc.c (check_sig_and_print): Print "Expired" for expired - but good signatures (this still prints "BAD" for expired but bad - signatures). - -2002-01-23 David Shaw - - * keygen.c (ask_keysize): Cosmetic: don't present a RSA signing - key as a "keypair" which can be 768 bits long (as RSA minimum is - 1024). - - * pubkey-enc.c (is_algo_in_prefs): Allow IDEA as a fake preference - for v3 keys with v3 selfsigs. - -2002-01-22 David Shaw - - * packet.h, getkey.c (merge_selfsigs_main), pkclist.c - (select_algo_from_prefs): Implement the fake IDEA preference as - per RFC2440:12.1. This doesn't mean that IDEA will be used (the - plugin may not be present), but it does mean that a v3 key with a - v3 selfsig has an implicit IDEA preference instead of 3DES. v3 - keys with v4 selfsigs use preferences as normal. - - * encode.c (encode_crypt): if select_algo_from_prefs fails, this - means that we could not find a cipher that both keys like. Since - all v4 keys have an implicit 3DES preference, this means there is - a v3 key with a v3 selfsig in the list. Use 3DES in this case as - it is the safest option (we know the v4 key can handle it, and - we'll just hope the v3 key is being used in an implementation that - can handle it). If --pgp2 is on, warn the user what we're doing - since it'll probably break PGP2 compatibility. - - * g10.c (main): Do not force using IDEA for encrypted files in - --pgp2 mode - let the fake IDEA preference choose this for us for - better compatibility when encrypting to multiple keys, only some - of which are v3. - - * keygen.c (keygen_set_std_prefs): Put 3DES on the end of the - default cipher pref list (RFC2440: "...it is good form to place it - there explicitly."). If the user has the IDEA plugin installed, - put a preference for IDEA *after* 3DES to effectively disable its - use for everything except encrypting along with v3 keys. - - * encode.c, g10.c, sign.c: Change the PGP2 warning line from - "... will not be usable ..." to "... may not be usable ..." as the - user could be using one of the enhanced PGP2 variations. - - * helptext.c: Revise the sign_uid.class help text as suggested by - Stefan. - -2002-01-20 Werner Koch - - * passphrase.c (passphrase_to_dek): Add tryagain_text arg to be - used with the agent. Changed all callers. - (agent_get_passphrase): Likewise and send it to the agent - * seckey-cert.c (do_check): New arg tryagain_text. - (check_secret_key): Pass the string to do_check. - * keygen.c (ask_passphrase): Set the error text is required. - * keyedit.c (change_passphrase): Ditto. - - * passphrase.c (agent_open): Disable opt.use_agent in case of a - problem with the agent. - (agent_get_passphrase): Ditto. - (passphrase_clear_cache): Ditto. - -2002-01-19 Werner Koch - - * passphrase.c (agent_open): Add support for the new Assuan based - gpg-agent. New arg to return the used protocol version. - (agent_get_passphrase): Implemented new protocol here. - (passphrase_clear_cache): Ditto. - (readline): New. - -2002-01-15 Timo Schulz - - * encode.c (encode_crypt_files): Fail if --output is used. - - * g10.c: New command --decrypt-files. - - * decrypt.c (decrypt_messages): New. - -2002-01-09 David Shaw - - * g10.c, misc.c, gpgv.c: move idea_cipher_warn to misc.c so gpgv.c - doesn't need a stub for it any longer. - - * g10.c (get_temp_dir), main.h: no longer used (it's in exec.c now) - - * g10.c (main), delkey.c (delete_keys), main.h : Allow - --delete-key (now --delete-keys, though --delete-key still works, - of course) to delete multiple keys in one go. This applies to - --delete-secret-key(s) and --delete-secret-and-public-key(s) as - well. - -2002-01-09 Timo Schulz - - * encode.c (encode_crypt_files): Now it behaves like verify_files. - - * g10.c (main): We don't need to check argc for encode_crypt_files - any longer. - -2002-01-09 Timo Schulz - - * exec.c: Include windows.h for dosish systems. - -2002-01-08 Timo Schulz - - * g10.c (main): New description for --encrypt-files. - -2002-01-08 Werner Koch - - * g10.c (main): Must register the secring for encryption because - it is needed to figure out the default recipient. Reported by - Roger Sondermann. - -2002-01-05 David Shaw - - * keyedit.c (menu_adduid): Require --expert before adding a photo - ID to a v3 key, and before adding a second photo ID to any key. - - * keyedit.c (keyedit_menu): Don't allow adding photo IDs in - rfc1991 or pgp2 mode. - - * getkey.c (merge_selfsigs_subkey): Permit v3 subkeys. Believe it - or not, this is allowed by rfc 2440, and both PGP 6 and PGP 7 work - fine with them. - - * g10.c, options.h, keyedit.c, sign.c: Move the "ask for - expiration" switch off of --expert, which was getting quite - overloaded, and onto ask-sig-expire and ask-cert-expire. Both - default to off. - - * g10.c (main): Change the default compression algo to 1, to be - more OpenPGP compliant (PGP also uses this, so it'll help with - interoperability problems as well). - - * encode.c (encode_crypt): Handle compression algo 2, since the - default is now 1. - - * build-packet.c (build_attribute_subpkt): Fix off-by-one error. - -2002-01-05 Werner Koch - - * g10.c (main): Do not register the secret keyrings for certain - commands. - - * keydb.c (keydb_add_resource): Use access to test for keyring - existence. This avoids cached opened files which are bad under - RISC OS. - -2002-01-04 David Shaw - - * sign.c (sign_file, sign_symencrypt_file): always use one-pass - packets unless rfc1991 is enabled. This allows a signature made - with a v3 key to work in PGP 6 and 7. Signatures made with v4 - keys are unchanged. - - * g10.c (main): Disallow non-detached signatures in PGP2 mode. - Move the "you must use files and not pipes" PGP2 warning up so all - the PGP2 stuff is together. - - * encode.c (encode_simple): Use the actual filesize instead of - partial length packets in the internal literal packet from a - symmetric message. This breaks PGP5(?), but fixes PGP2, 6, and 7. - It's a decent tradeoff. Note there was only an issue with - old-style RFC1991 symmetric messages. 2440-style messages in 6 - and 7 work with or without partial length packets. - -2002-01-03 David Shaw - - * g10.c (main): Removed --no-default-check-level option, as it is - not consistent with other "default" options. Plus, it is the same - as saying --default-check-level 0. - - * exec.c (exec_read): Disallow caching tempfile from child - process, as this keeps the file handle open and can cause unlink - problems on some platforms. - - * keyserver.c (keyserver_search_prompt): Minor tweak - don't - bother to transform keyids into textual form if they're just going - to be transformed back to numbers. - -2002-01-03 Timo Schulz - - * g10.c: New command --encrypt-files. - - * verify.c (print_file_status): Removed the static because - encode_crypt_files also uses this function. - - * main.h (print_files_status): New. - (encode_crypt_files): New. - - * encode.c (encode_crypt_files): New. - -2002-01-02 Stefan Bellon - - * keyserver.c: Moved util.h include down in order to avoid - redefinition problems on RISC OS. - - * keyring.c (keyring_lock): Only lock keyrings that are writable. - - * keyring.c (keyring_update_keyblock): Close unused iobuf. - - * hkp.c (parse_hkp_index, hkp_search) [__riscos__]: Changed - unsigned char* to char* because of compiler issues. - - * exec.c (exec_finish) [__riscos__]: Invalidate close cache so - that file can be unlinked. - -2001-12-28 David Shaw - - * g10.c (main): Use a different strlist to check extensions since - they need to be handled seperately now. - - * misc.c,main.h (check_permissions): Properly handle permission - and ownership checks on files in the lib directory - (e.g. /usr/local/lib/gnupg), which are owned by root and are - world-readable, and change all callers to specify extension or - per-user file. - - * photoid.c (show_photo), keyserver.c (keyserver_spawn): Bug fix - - don't call exec_finish if exec_write fails. - - * keyserver.c (keyserver_spawn): Look for OPTIONS from the - keyserver helper - specifically, a "OUTOFBAND" option for the - email keyserver. - - * mainproc.c (list_node), keylist.c (list_keyblock_colon), - import.c (delete_inv_parts), export.c (do_export_stream): Use - signature flags for exportability check rather than re-parsing the - subpacket. - - * keyid.c, keydb.h (get_lsign_letter): No longer needed. - -2001-12-27 David Shaw - - * exec.c (exec_finish): Show errors when temp files cannot be - deleted for whatever reason. - - * exec.c (exec_read): Don't rely on WEXITSTATUS being present. - - * exec.c (make_tempdir): Add temp file creator for win32. Don't - create an incoming temp file if the exec is write-only. - - * keyserver.c (keyserver_spawn): Clean up error handling, for when - the spawn fails. - - * photoid.c (show_photo): Clean up error handling. - - * misc.c (check_permissions): Neaten. - -2001-12-25 David Shaw - - * mkdtemp.c (mkdtemp): Add copyleft info and tweak the 'X' counter - to be a bit simpler. - - * keyserver.c, photoid.c: Remove unused headers left over from - when the exec functions lived there. - -2001-12-23 Timo Schulz - - * misc.c (check_permissions): Do not use it for W32 systems. - - * tdbio.c (migrate_from_v2): Define ftruncate as chsize() for W32. - - * mkdtemp.c: W32 support. - - * photoid.c: Ditto. - - * exec.c: Ditto. - -2001-12-22 David Shaw - - * exec.c (make_tempdir): avoid compiler warning with const - - * mkdtemp.c (mkdtemp): catch the empty ("") string case in case - someone repurposes mkdtemp at some point. - - * photoid.c (generate_photo_id, show_photo): some type changes - from Stefan Bellon. - - * exec.c (make_tempdir): handle Win32 systems, suggested by Timo - Schulz. - -2001-12-22 Werner Koch - - * encode.c (encode_simple, encode_crypt): i18n 2 strings. - -2001-12-22 Timo Schulz - - * encode.c (encode_simple, encode_crypt): Use is_file_compressed - to avoid to compress compressed files. - -2001-12-22 Werner Koch - - * keyserver.c (keyserver_spawn): Removed some variables - declaration due to shadowing warnings. - - * build-packet.c (build_attribute_subpkt): s/index/idx/ to avoid - compiler warnig due to index(3). - - * getkey.c (get_ctx_handle): Use KEYDB_HANDLE as return value. - * keylist.c (list_one): Made resname const. - - * keyedit.c (keyedit_menu): Allow "addphoto" only when --openpgp is - not used. - - * options.skel: Changed one example photo viewer to qiv. - -2001-12-21 David Shaw - - * Makefile.am: add exec.c, exec.h, photoid.c, and photoid.h - - * build-packet.c (build_attribute_subpkt): new function to build - the raw attribute subpacket. Note that attribute subpackets have - the same format as signature subpackets. - - * exec.c: new file with generic exec-a-program functionality. - Used by both photo IDs and keyserver helpers. This is pretty much - the same code that used to be keyserver specific, with some - changes to be usable generically. - - * free-packet.c (free_attributes (new)): function to free an - attribute packet. - - * gpgv.c: added stub show_photo - - * keyedit.c (keyedit_menu, menu_adduid, menu_showphoto): can add a - photo (calls generate_photo_id), or display a photo (calls - show_photo) from the --edit menu. New commands are "addphoto", - and "delphoto" (same as "deluid"). - - * keylist.c (list_keyblock_print): show photos during key list if - --show-photos enabled. - - * keyserver.c (keyserver_spawn): use the generic exec_xxx - functions to call keyserver helper. - - * g10.c, options.h: three new options - --{no-}show-photos, and - --photo-viewer to give the command line to display a picture. - - * options.skel: instructions for the photo viewer - - * parse-packet.c (parse_user_id, setup_user_id (new)): common code - for both user IDs and attribute IDs moved to setup_user_id. - - * parse-packet.c (make_attribute_uidname (new)): constructs a fake - "name" for attribute packets (e.g. "[image of size ...]") - - * parse-packet.c (parse_attribute (replaces parse_photo_id), - parse_attribute_subpkts): Builds an array of individual - attributes. Currently only handles attribute image / type jpeg - subpackets. - - * sign.c (hash_uid): Fix bug in signing attribute (formerly - photo_id) packets. - - * packet.h, and callers: globally change "photo_id" to "attribute" - and add structures for attributes. The packet format is generic - attributes, even though the only attribute type thus far defined - is jpeg. - -2001-12-21 David Shaw - - * parse-packet.c (can_handle_critical): Can handle critical - revocation subpackets now. - - * trustdb.c (mark_usable_uid_certs): Disregard revocations for - nonrevocable sigs. Note that this allows a newer revocable - signature to override an older nonrevocable signature. - - * sign.c (make_keysig_packet): add a duration field and change all - callers. This makes make_keysig_packet closer to - write_signature_packets and removes some duplicated expiration - code. - - * keyedit.c (keyedit_menu, menu_revsig, sign_uids, - sign_mk_attrib): Add nrsign command, don't allow revoking a - nonrevocable signature, - - * g10.c (main): Add --nrsign option to nonrevocably sign a key - from the command line. - - * build-packet.c (build_sig_subpkt_from_sig): Comment to explain - the use of CRITICAL. - -2001-12-21 Werner Koch - - * g10.c. options.h : New option --show-keyring - * getkey.c (get_ctx_handle): New. - * keylist.c (list_one): Implement option here. By David Champion. - -2001-12-20 David Shaw - - * keyserver.c (keyserver_spawn): Use mkdtemp() to make temp - directory. - - * mkdtemp.c: replacement function for those platforms that don't - have mkdtemp (make a temp directory securely). - -2001-12-19 David Shaw - - * misc.c (check_permissions): New function to stat() and ensure - the permissions of GNUPGHOME and the files have safe permissions. - - * keydb.c (keydb_add_resource): Check keyring permissions. - - * tdbio.c (tdbio_set_dbname): Check permissions of trustdb.gpg - - * keyserver.c (keyserver_spawn): Disable keyserver schemes that - involve running external programs if the options file has unsafe - permissions or ownership. - - * g10.c, options.h: New option --no-permission-warning to disable - the permission warning message(s). This also permits use of the - keyserver if it had been disabled (see above). Also check the - permissions/ownership of random_seed. - - * keyserver.c (keyserver_spawn): The new glibc prints a warning - when using mktemp() (the code was already secure, but the warning - was bound to cause confusion). Use a different implementation - based on get_random_bits() instead. Also try a few times to get - the temp dir before giving up. - -2001-12-19 Werner Koch - - * g10.c, passphrase.c [CYGWIN32]: Allow this as an alias for MINGW32. - -2001-12-18 David Shaw - - * g10.c (idea_cipher_warn): Add a flag to show the warning always - or once per session and change all callers (show always except for - the secret key protection and unknown cipher from an encrypted - message errors). Also make the strings translatable. - - * pubkey-enc.c (get_it): Add the IDEA cipher warning if the user - tries to decrypt an IDEA encrypted message without the IDEA - plugin. - - * keyserver.c (parse_keyserver_uri): More strict checking of the - keyserver URI. Specifically, fail if the ":port" section is - anything except a number between 1 and 65535. - -2001-12-17 David Shaw - - * keyserver.c (print_keyinfo): No need to check for - control/illegal characters, as utf8_to_native does this for us. - - * mainproc.c (proc_encrypted): Use generic IDEA warning. - - * gpgv.c: add stub for idea_cipher_warn - - * g10.c, hkp.c, keyserver.c: Fix capitalization and plural issues. - - * encode.c (encode_crypt), sign.c (sign_file, clearsign_file): - disable pgp2 mode after the message is no longer pgp2 compatible. - - * g10.c (main): Tweak the PGP2.x IDEA warning to use the generic - warning, and not merely fail if the IDEA plugin isn't there. - - * g10.c (main, idea_cipher_warn), keygen.c (set_one_pref), - seckey-cert.c (do_check): Add a generic IDEA warning for when the - IDEA plugin is not present. This pops up when the user uses - "--cipher-algo idea", when setpref is used to set a "S1" - preference, and when a secret key protected with IDEA is used. - -2001-12-15 Werner Koch - - * keyserver.c (keyserver_spawn): Assert that we have dropped privs. - -2001-12-13 Werner Koch - - * pubkey-enc.c (get_session_key): Check that the public key - algorithm is indeed usable for en/decryption. This avoid a - strange error message from pubkey_decrypt if for some reasons a - bad algorithm indentifier is passed. - -2001-12-12 David Shaw - - * Fixed some types for portability. Noted by Stefan Bellon. - -2001-12-11 Werner Koch - - * hkp.c (hkp_export): Do not print possible control characters - from a keyserver response. - (parse_hkp_index): Made uid an unsigned char* because it is passed to - isspace(). - (hkp_search): Ditto for the char* vars. - - * g10.c (main): Print the IDEA warning also for -c and -se. - - * g10.c (get_temp_dir): Assert that we have dropped privs - - * encode.c (encode_crypt): Include the first key into the --pgp2 - check. - -2001-12-07 David Shaw - - * g10.c, options.h: New option --pgp2. This is identical to - "--rfc1991 --cipher-algo idea --compress-algo 1 --digest-algo md5 - --force_v3_sigs" with the addition of an warning to advise the - user not to use a pipe (which would break pgp2 compatibility). - - * encode.c (encode_crypt): warn if the user tries to encrypt to - any key that is not RSA and <= 2048 bits when the --pgp2 option is - used. - - * sign.c (sign_file, clearsign_file): When using --pgp2, make a v3 - sig, and warn if the signature is made with a non-v3 key. - -2001-12-05 David Shaw - - * sign.c (sign_file, clearsign_file, sign_symencrypt_file): Prompt - for sig expiration if --expert is set and --force-v3-sigs is not - set (v3 sigs cannot expire). - - * mainproc.c (check_sig_and_print): After checking a sig, print - expiration status. This causes a error return if the sig is - expired. - - * build-packet.c (build_sig_subpkt_from_sig): Include a critical - sig expiration subpacket if the sig is to expire. - - * keyedit.c (sign_uids): Do not sign an expired key unless - --expert is set, in which case prompt. Also, offer to expire a - signature when the key the user is signing expires. - - * keygen.c (ask_expire_interval): Add a value to determine whether - to prompt for a key or sig expiration and change all callers. - - * keyid.c: New functions: expirestr_from_sig and - colon_expirestr_from_sig. - - * keylist.c (list_keyblock_colon): Show sig expiration date in the - --with-colons listing. - - * sign.c (make_keysig_packet, write_signature_packets): Pass in an - optional timestamp for the signature packet, and change all - callers. - - * keyedit.c (sign_mk_attrib): Include a critical expiration - subpacket in the signature if an expiration date is given. - -2001-12-04 David Shaw - - * keyedit.c (sign_uids): If the user tries to sign a - locally-signed key, allow the cert to be promoted to a full - exportable signature. This essentially deletes the old - non-exportable sig, and replaces it with a new exportable one. - -2001-12-04 David Shaw - - * keyedit.c (keyedit_menu): Do not allow signing a revoked key - unless --expert is set, and ask even then. - - * keyedit.c (sign_uids): Do not allow signing a revoked UID unless - --expert is set, and ask even then. - - * g10.c, options.h : New option --expert - -2001-11-16 David Shaw - - * Allow the user to select no compression via "--compress-algo 0" - on the command line. - - * keyedit.c (show_prefs): Show compression preferences in the - long-form "showpref" style. - - * keygen.c (set_one_pref): Permit setting a no-compression ("Z0") - preference. - - * getkey.c (fixup_uidnode): Fix compression preference corruption - bug. - -2001-12-02 David Shaw - - * g10.c: Add advisory --for-your-eyes-only option as per section - 5.9 of 2440. - -2001-12-05 David Shaw - - * Force a V4 sig if the user has a notation or policy URL set. - -2001-12-04 David Shaw - - * g10.c: Add options --keyserver-options, --temp-directory, and - auto-key-retrieve (the opposite of no-auto-key-retrieve). - - * hkp.c (hkp_search): New function to handle searching a HKP - keyserver for a key - - * hkp.c (hkp_ask_import, hkp_export): Pretty large changes to make - them communicate via the generic functions in keyserver.c - - * keyserver.c: new file with generic keyserver routines for - getting keys from a keyserver, sending keys to a keyserver, and - searching for keys on a keyserver. Calls the internal HKP stuff - in hkp.c for HKP keyserver functions. Other calls are handled by - an external program which is spawned and written to and read from - via pipes. Platforms that don't have pipes use temp files. - -2001-11-20 David Shaw - - * options.h, g10.c: New options show-notation, no-show-notation, - default-check-level, no-default-check-level, show-policy-url, - no-show-policy-url. - - * packet.h, sign.c (make_keysig_packet), parse-packet.c - (parse_signature), free-packet.c (free_seckey_enc): Fill in - structures for notation, policy, sig class, exportability, etc. - - * keyedit.c, keylist.c (print_and_check_one_sig, - list_keyblock_print): Show flags in signature display for cert - details (class, local, notation, policy, revocable). If selected, - show the notation and policy url. - - * keyedit.c (sign_uids): Prompt for and use different key sig - classes. - - * helptext.c (helptexts): Add help text to explain different - key signature classes - -2001-11-26 David Shaw - - * trustdb.c (mark_usable_uid_certs): Fix segfault from bad - initialization and fix reversed key signature expiration check. - -2001-11-09 Werner Koch - - * export.c (do_export_stream): Put all given names into a search - description and change the loop so that all matching names are - returned. - -2001-11-08 Werner Koch - - * pubkey-enc.c (get_it): To reduce the number of questions on the - MLs print the the name of cipher algorithm 1 with the error message. - - * mainproc.c: Changed the way old rfc1991 encryption cipher is - selected. Based on a patch by W Lewis. - - * pkclist.c (do_edit_ownertrust): Allow to skip over keys, the non - working "show info" is now assigned to "i" - * trustdb.c (ask_ownertrust, validate_keys): Implement a real quit - here. Both are by David Shaw. - - * trustdb.c (validate_keys): Make sure next_exipire is initialized. - - * sign.c (make_keysig_packet): Use SHA-1 with v4 RSA keys. - - * g10.c, options.h : New option --[no-]froce-v4-certs. - * sign.c (make_keysig_packet): Create v4 sigs on v4 keys even with - a v3 key. Use that new option. By David Shaw - - * revoke.c (ask_revocation_reason): Allow to select "no reason". - By David Shaw. - - * keyid.c (fingerprint_from_sk): Calculation of an v3 fpr was - plain wrong - nearly the same code in fingerprint_from_pk is correct. - - * build-packet.c (do_secret_key): Added a few comments to the code. - -2001-11-07 Werner Koch - - * g10.c (main): Print a warning when -r is used w/o encryption. - Suggested by Pascal Scheffers. - -2001-10-23 Werner Koch - - * keyedit.c (keyedit_menu): Changed helptext for showpref - command. Suggested by Reinhard Wobst. - - * keyring.c (keyring_search): When marking the offtbl ready, take - into account that we may have more than one keyring. - -2001-10-22 Werner Koch - - * Makefile.am: Do not use OMIT_DEPENDENCIES - - * build-packet.c (build_sig_subpkt): Default is now to put all - types of subpackets into the hashed area and only list those which - should go into the unhashed area. - -2001-10-18 Werner Koch - - * keydb.c (keydb_add_resource): Rearranged the way we keep track - of the resource. There will now be an entry for each keyring here - and not in keyring.c itself. Store a token to allow creation of a - keyring handle. Changed all functions to utilize this new design. - (keydb_locate_writable): Make a real implementation. - * keyring.c (next_kr): Removed and changed all callers to set the - resource directly from the one given with the handle. - (keyring_is_writable): New. - (keyring_rebuild_cache): Add an arg to pass the token from keydb. - -2001-10-17 Werner Koch - - * keyring.c (keyring_search): Enabled word search mode but print a - warning that it is buggy. - -2001-10-11 Werner Koch - - * hkp.c (hkp_ask_import): No more need to set the port number for - the x-hkp scheme. - (hkp_export): Ditto. - -2001-10-06 Stefan Bellon - - * passphrase.c [__riscos__]: Disabled agent specific stuff. - * g10.c: New option --no-force-v3-sigs. - -2001-10-04 Werner Koch - - * export.c (do_export_stream): Do not push the compress filter - here because the context would run out of scope due to the - iobuf_close done by the caller. - (do_export): Do it here instead. - -2001-09-28 Werner Koch - - * keyedit.c (sign_uids): Always use the primary key to sign keys. - * getkey.c (finish_lookup): Hack to return only the primary key if - a certification key has been requested. - - * trustdb.c (cmp_kid_for_make_key_array): Renamed to - (validate_one_keyblock): this and changed arg for direct calling. - (make_key_array): Renamed to - (validate_one_keyblock): this and changed args for direct calling. - (mark_usable_uid_certs, validate_one_keyblock) - (validate_key_list): Add next_expire arg to keep track of - expiration times. - (validate_keys): Ditto for UTKs and write the stamp. - - * tdbio.c (migrate_from_v2): Check return code of tbdio_sync. - - * tdbdump.c (import_ownertrust): Do a tdbio_sync(). - - * keyring.c: Made the offtbl an global object. - -2001-09-27 Werner Koch - - * pkclist.c (do_edit_ownertrust): Allow settin of ultimate trust. - - * trustdb.c (mark_keyblock_seen): New. - (make_key_array): Use it to mark the subkeys too. - (validate_keys): Store validity for ultimatly trusted keys. - -2001-09-26 Werner Koch - - * pkclist.c (check_signatures_trust, do_we_trust): Removed the - invocation of add_ownertrust. Minor changes to the wording. - (add_ownertrust, add_ownertrust_cb): Removed. - - * trustdb.c (get_validity): Allow to lookup the validity using a - subkey. - - * trustdb.c (new_key_hash_table): Increased the table size to 1024 - and changed the masks accordingly. - (validate): Changed stats printing. - (mark_usable_uid_certs): New. - (cmp_kid_for_make_key_array): Does now check the signatures and - figures out a usable one. - -2001-09-25 Werner Koch - - * keyring.c (new_offset_item,release_offset_items) - (new_offset_hash_table, lookup_offset_hash_table) - (update_offset_hash_table, update_offset_hash_table_from_kb): New. - (keyring_search): Use a offset table to optimize search for - unknown keys. - (keyring_update_keyblock, keyring_insert_keyblock): Insert new - offsets. - * getkey.c (MAX_UNK_CACHE_ENTRIES): Removed the unknown keys - caching code. - - * g10.c, options.h, import.c: Removed the entire - allow-secret-key-import stuff because the validity is now - controlled by other means. - - * g10.c: New command --rebuild-keydb-caches. - * keydb.c (keydb_rebuild_caches): New. - * keyring.c (do_copy): Moved some code to - (create_tmp_file, rename_tmp_file, write_keyblock): new functions. - (keyring_rebuild_cache): New. - - * packet.h (PKT_ring_trust): Add sigcache field. - * parse-packet.c (parse_trust): Parse sigcache. - * keyring.c (do_copy): Always insert a sigcache packet. - (keyring_get_keyblock): Copy the sigcache packet to the signature. - * sig-check.c (cache_sig_result): Renamed from - cache_selfsig_result. Changed implementation to use the flag bits - and changed all callers. - (mdc_kludge_check): Removed this unused code. - (do_check): Do not set the sig flags here. - - * import.c (read_block): Make sure that ring_trust packets are - never imported. - * export.c (do_export_stream): and never export them. - - * trustdb.c (make_key_array): Skip revoked and expired keys. - -2001-09-24 Werner Koch - - * g10.c, options.h: New option --no-auto-check-trustdb. - - * keygen.c (do_generate_keypair): Set newly created keys to - ultimately trusted. - - * tdbio.h, tdbio.c: Removed all support for records DIR, KEY, UID, - PREF, SIG, SDIR and CACH. Changed migration function to work - direct on the file. - (tdbio_read_nextcheck): New. - (tdbio_write_nextcheck): New. - -2001-09-21 Werner Koch - - Revamped the entire key validation system. - * trustdb.c: Complete rewrite. No more validation on demand, - removed some functions, adjusted to all callers to use the new - and much simpler interface. Does not use the LID anymore. - * tdbio.c, tdbio.h: Add new record types trust and valid. Wrote a - migration function to convert to the new trustdb layout. - * getkey.c (classify_user_id2): Do not allow the use of the "#" - prefix. - * keydb.h: Removed the TDBIDX mode add a skipfnc to the - descriptor. - * keyring.c (keyring_search): Implemented skipfnc. - - * passphrase.c (agent_open): Add missing bracket. Include windows.h. - -2001-09-19 Werner Koch - - * keylist.c (print_fingerprint): Renamed from fingerprint, made - global available. Added new arg to control the print style. - * mainproc.c (print_fingerprint): Removed. - * pkclist.c (print_fpr, fpr_info): Removed and changed callers to - use print_fingerprint. - * keyedit.c (show_fingerprint): Ditto. - - * passphrase.c (writen, readn) - (agent_open, agent_close) - (agent_get_passphrase) - (passphrase_clear_cache): Support for W32. Contributed by Timo. - - * import.c (import_one): Release keydb handles at 2 more places. - - * keyring.c (keyring_release): Close the iobuf. - (keyring_get_keyblock): Init ret_kb to NULL and store error contidion. - - * import.c (import_new_stats_handle): New. - (import_release_stats_handle): New. - (import_print_stats): Renamed from static fnc print_stats. - (import_keys, import_keys_stream): Add an optional status handle - arg and changed all callers. - * hkp.c (hkp_ask_import): Add an stats_handle arg and changed all - callers. - - * mainproc.c (print_pkenc_list): Use print_utf8_string2(). - -2001-09-18 Werner Koch - - * g10.c: New command --refresh-keys. - * hkp.c (hkp_refresh_keys): New. Contributed by Timo Schulz. - - * parse-packet.c (parse): Stop on impossible packet lengths. - -2001-09-17 Werner Koch - - * mainproc.c (print_notation_data): Wrap notation data status lines - after 50 chars. - - * mainproc.c (proc_pubkey_enc): Make option try-all-secrets work. - By disastry@saiknes.lv. - -2001-09-14 Werner Koch - - * parse-packet.c (dump_sig_subpkt): List key server preferences - and show the revocable flag correctly. Contributed by David Shaw. - -2001-09-09 Werner Koch - - * keyedit.c (keyedit_menu): No need to define another p. - - * keylist.c (print_capabilities): s/used/use/ so that it - does not shadow a global. - * sign.c (sign_file): Renamed arg encrypt to encryptflag - * keygen.c: Replaced all "usage" by "use". - * misc.c (openpgp_pk_algo_usage): Ditto. - - * pubkey-enc.c (get_it): Renamed arg k to enc so that the later - defined k does not shadow it. - - * parse-packet.c (parse_gpg_control): No need to define another i. - - * getkey.c (get_pubkey_byfprint): Must use the enum values and not - the fprint_len. - * keyring.c (keyring_search): Removed a non-sense break. Both - bugs pointed out by Stefan. - -2001-09-07 Werner Koch - - * status.c, status.h: Added NO_RECP and ALREADY_SIGNED. - * pkclist.c (build_pk_list): Issue NO_RECP. - * keyedit.c (sign_uids): Added experimental ALREADY_SIGNED - - * hkp.c (hkp_import): Use log_error. Bug reported by Neal H - Walfield. - - * getkey.c (classify_user_id2): Change args to take the desc union - direct. It was a stupid idea to pass the individual fields of an - union to this function. Changed all callers. - (classify_user_id): Ditto and allow to pass NULL as the description. - -2001-09-06 Werner Koch - - * getkey.c (fixup_uidnode): Features flag is now a bit vector. - * keygen.c (add_feature_mdc): Ditto. - - Revamped the entire key I/O code to be prepared for other ways of - key storages and to get rid of the existing shit. GDBM support has - gone. - * keydb.c: New - * keyring.c, keyring.h: New. - * ringedit.c: Removed. Moved some stuff to keyring.c - * getkey.c: Changed everything related to the key retrieving - functions which are now using the keydb_ functions. - (prepare_search, word_match_chars, word_match) - (prepare_word_match, compare_name): Moved to keyring.c - (get_pubkey_byname): Removed ctx arg and add ret_kdbhd - arg. Changed all callers. - (key_byname): Use get_pubkey_end to release the context and take - new ret_kbdhd arg. Changed all callers. - (classify_user_id2): Fill the 16 byte fingerprint up with 4 null - bytes not with zero bytes of value 4, tsss. - * import.c (import_one): Updated to use the new keydb interface. - (import_secret_one): Ditto. - (import_revoke_cert): Ditto. - * delkey.c (do_delete_key): Ditto. - * keyedit.c (keyedit_menu): Ditto. - (get_keyblock_byname): Removed. - * revoke.c (gen_revoke): Ditto. - * export.c (do_export_stream): Ditto. - * trustdb.c (update_trustdb): Ditto. - * g10.c, gpgv.c (main): Renamed add_keyblock_resource to - keydb_add_resource. - * Makefile.am: Added and removed files. - - * keydb.h: Moved KBNODE typedef and MAX_FINGERPRINT_LEN to - * global.h: this new header. - -2001-09-03 Werner Koch - - * passphrase.c (agent_get_passphrase): Changed nread to size_t. - (passphrase_clear_cache): Ditto. - - * keyid.c (mk_datestr): Avoid trigraphs. - (fingerprint_from_pk): Cache the keyid in the pk. - - * options.h: Add opt.with_fingerprint so that we know whether the - corresponding options was used. - * g10.c (main): Set it here. - * pkclist.c (check_signatures_trust): Always print fingerprint - when this option is used. Mixed a minor memory leak. - - * status.c, status.h: New status INV_RECP. - * pkclist.c (build_pk_list): Issue this status. - -2001-08-31 Werner Koch - - * parse-packet.c (parse_key,parse_pubkeyenc) - (parse_signature): Return error on reading bad MPIs. - - * mainproc.c (check_sig_and_print): Always print the user ID even - if it is not bound by a signature. Use the primary UID in the - status messages and encode them in UTF-8 - * status.c (write_status_text_and_buffer): New. - -2001-08-30 Werner Koch - - * packet.h (sigsubpkttype_t): Add SIGSUBPKT_FEATURES. - (PKT_public_key, PKT_user_id): Add a flag for it. - * parse-packet.c, build-packet.c: Add support for them. - * getkey.c (fixup_uidnode, merge_selfsigs): Set the MDC flags. - * keygen.c (add_feature_mdc): New. - (keygen_upd_std_prefs): Always set the MDC feature. - * keyedit.c (show_prefs): List the MDC flag - * pkclist.c (select_mdc_from_pklist): New. - * encode.c (encode_crypt, encrypt_filter): Test whether MDC - should be used. - * cipher.c (write_header): Set MDC use depending on the above test. - Print more status info. - - * delkey.c (do_delete_key): Kludge to delete a secret key with no - public key available. - - * ringedit.c (find_secret_keyblock_direct): New. - * getkey.c (seckey_available): Simplified. - - * ringedit.c (cmp_seckey): Now compares the secret key against the - public key while ignoring all secret parts. - (keyring_search): Use a public key packet as arg. Allow to search - for subnkeys - (search): Likewise. Changed all callers. - (find_secret_keyblock_bypk): New. - (find_secret_keyblock_byname): First locate the pubkey and then - find the correponding secret key. - * parse-packet.c (parse): Renamed pkttype arg to onlykeypkts and - changed code accordingly. Changed all callers. - (search_packet): Removed pkttype arg. - * keyedit.c (keyedit_menu): First locate the public key and then - try to locate a secret key. - - * ringedit.c (locate_keyblock_by_fpr): Removed. - (locate_keyblock_by_keyid): Removed. - (find_keyblock_bysk): Removed. - - * sig-check.c (check_key_signature2): Print the keyid along with - the wrong sig class errors. - -2001-08-24 Werner Koch - - * sign.c (sign_file): Stripped the disabled comment packet code. - (sign_file, sign_symencrypt_file): Moved common code to .. - (write_onepass_sig_packets): .. this new function. - (sign_file, clearsign_file, sign_symencrypt_file): Moved common - code to - (write_signature_packets): this new function. - (write_signature_packets, make_keysig_packet) - (update_keysig_packet): Moved common code to - (hash_uid, hash_sigclass_to_magic): these new functions - (sign_file, sign_symencrypt_file): Moved common code to - (write_plaintext_packet): this new function. - -2001-08-21 Stefan Bellon - - * trustdb.c (query_trust_info): Changed trustlevel to signed int. - * g10.c [__riscos__]: Fixed handling of --use-agent --lock-multiple. - -2001-08-20 Werner Koch - - * encr-data.c (decrypt_data): Keep track on whether we already - printed information about the used algorithm. - * mainproc.c (proc_encrypted): Removed the non-working IDEA hack - and print a message about the assumed algorithm. - * passphrase.c (passphrase_to_dek): Use the same algorithm as above. - (proc_symkey_enc): Print the algorithm, so that the user knows it - before entering the passphrase. - (proc_pubkey_enc, proc_pubkey_enc): Zero the DEK out. - * encode.c (encode_crypt, encrypt_filter): Ditto. - - * g10.c: Allow for --sign --symmetric. - * sign.c (sign_and_symencrypt): New. - - Applied patches from Stefan Bellon to support - RISC OS. Nearly all of these patches are identified by the - __riscos__ macro. - * compress.c: Added a couple of casts. - * g10.c [__riscos__]: Some patches and new options foo-file similar - to all foo-fd options. - * gpgv.c, openfile.c, ringedit.c, tdbio.c: Minor fixes. Mainly - replaced hardcoded path separators with EXTSEP_S like macros. - * passprase.c [__riscos__]: Disabled agent stuff - * trustdb.c (check_trust): Changed r_trustlevel to signed int to - avoid mismatch problems in pkclist.c - * pkclist.c (add_ownertrust): Ditto. - * plaintext.c (handle_plaintext) [__riscos__]: Print a note when - file can't be created. - * options.h [__riscos__]: Use an extern unless included from the - main module. - * signal.c (got_fatal_signal) [__riscos__]: Close all files. - -2001-08-14 Werner Koch - - * keygen.c (ask_algo): New arg r_usage. Allow for RSA keys. - (gen_rsa): Enabled the code. - (do_create): Enabled RSA branch. - (parse_parameter_usage): New. - (proc_parameter_file): Handle usage parameter. - (read_parameter_file): Ditto. - (generate_keypair): Ditto. - (generate_subkeypair): Ditto. - (do_generate_keypair): Ditto. - (do_add_key_flags): New. - (keygen_add_std_prefs): Use the new function. - (keygen_add_key_flags_and_expire): New. - (write_selfsig, write_keybinding): Handle new usage arg. - * build-packet.c (build_sig_subpkt): Make sure that key flags go - into the hashed area. - - * keygen.c (write_uid): Initialize the reference cunter. - - * keyedit.c (keyedit_menu): No more need to update the trustdb for - preferences. Added calls to merge keblock. - - * kbnode.c (dump_kbnode): Print some more flags. - -2001-08-10 Werner Koch - - Revamped the preference handling. - - * packet.h (prefitem_t, preftype_t): New. - (PKT_public_key): Added a uid field. - (PKT_user_id): Added field to store preferences and a reference - counter. - * parse-packet.c (parse_user_id,parse_photo_id): Initialize them - * free-packet.c (free_user_id): Free them. - (copy_user_id): Removed. - (scopy_user_id): New. - (cmp_user_ids): Optimized for identical pointers. - (release_public_key_parts): Release the uid. - (copy_public_key_with_new_namehash): Removed. - (copy_prefs): New. - * keyedit.c (menu_adduid): Use the new shallow copy user id. - (show_prefs): Adjusted implementation. - (keyedit_menu): No more need to update the trustdb after changing - preferences. - * getkey.c (fixup_uidnode): Store preferences. - (find_by_name): Return a user id packet and remove namehash stuff. - (lookup): Removed the unused namehash stuff. - (finish_lookup): Added foundu arg. - (pk_from_block): Removed the namehash arg and changed all callers. - (merge_selfsigs): Copy prefs to all keys. - * trustdb.c (get_pref_data): Removed. - (is_algo_in_prefs): Removed. - (make_pref_record): Deleted and removed all class. - * pkclist.c (select_algo_from_prefs): Adjusted for the new - preference implementation. - * pubkey-enc.c (is_algo_in_prefs): New. - (get_it): Use that new function. - -2001-08-09 Werner Koch - - * build-packet.c (build_sig_subpkt): Fixed calculation of - newarea->size. - - * g10.c (main): New option "--preference-list" - * keyedit.c (keyedit_menu): New commands "setpref" and "updpref". - (menu_set_preferences): New. - * keygen.c (keygen_set_std_prefs): New. - (set_one_pref): New. - (check_zip_algo): New. - (keygen_get_std_prefs): New. - (keygen_upd_std_prefs): New - (keygen_add_std_prefs): Move the pref setting code into the above fnc. - * build-packet.c (build_sig_subpkt): Updated the list of allowed - to update subpackets. - -2001-08-08 Werner Koch - - * packet.h (subpktarea_t): New. - (PKT_signature): Use that type for hashed_data and unhashed_data and - removed the _data prefix from those fields. Changed all users. - * parse-packet.c (parse_signature): Changed allocation for that. - (parse_sig_subpkt): Changed declaration - (enum_sig_subpkt): Ditto and changed implementation accordingly. - * free-packet.c (cp_subpktarea): Renamed from cp_data_block and - adjusted implementation. Changed caller. - * sig-check.c (mdc_kludge_check): Adjusted the hashing. - (do_check): Ditto. - * sign.c (sign_file, clearsign_file, make_keysig_packet, - update_keysig_packet): Ditto. - * build-packet.c (build_sig_subpkt): Partial rewrite. - (find_subpkt): Adjusted and made static. - (delete_sig_subpkt): Adjusted. - (do_signature): Ditto. - - * keygen.c (ask_keysize): Do not print the notes about suggested - key sizes if just a DSA key is generated. - - * trustdb.c (add_ultimate_key): s/log_error/log_info/ for - duplicated inserted trusted keys. - -2001-08-07 Werner Koch - - * sign.c (sleep): Redefine for W32. - - * g10.c, options.h: Set new flag opt.no_homedir_creation when - --no-options is given. - * openfile.c (try_make_homedir): Don't create the homedir in that case. - -2001-08-03 Werner Koch - - * armor.c (armor_filter): Removed the default comment string - because it could get us in trouble due to translations using non - ascii characters. - -2001-08-01 Werner Koch - - * keylist.c (list_keyblock_print): Do not list revoked UIDs unless - in verbose mode and we do no signature listing. - - * getkey.c (finish_lookup): Skip subkeys which are not yet valid. - * g10.c, options.h: New option --ignore-valid-from. - - * sign.c (make_keysig_packet): Added new sigversion argument to - allow the caller to force generation of required signature - version. Changed all callers. Suggested by Thomas Roessler. - - * keyedit.c (sign_uids): Force v4 signature generation for local - sigs. Removed the check for local signature and pre-v4 keys. - -2001-07-27 Werner Koch - - * keyedit.c (sign_uids): Check that we are not trying to to a - lsign with a pre-v4 key. Bug noticed by Thomas Roessler. - -2001-07-26 Werner Koch - - * parse-packet.c (parse_photo_id): Reset all variables. - * getkey.c (merge_selfsigs_main): Removed checks on PHOTO_ID - because this is handled identically to a user ID. - -2001-07-06 Werner Koch - - * cipher.c (write_header): Don't use MDC with --rfc1991. Suggested - by disastry@saiknes.lv. - -2001-07-05 Werner Koch - - * g10.c, options.h: New option --preserve-permissions. - * ringedit.c (add_keyblock_resource): Use it here - (keyring_copy): and here. - - * trustdb.c (verify_own_keys): Be more silent on --quiet. - Suggested by Thomas Roessler. - * sig-check.c (check_key_signature2): Ditto. - * mainproc.c (proc_encrypted, proc_tree): Ditto - * getkey.c (lookup): Ditto. - -2001-07-04 Werner Koch - - * ringedit.c (add_keyblock_resource): Restore filename in case of error. - -2001-06-25 Werner Koch - - * kbnode.c (dump_kbnode): Print the signature timestamp. - - * keyedit.c (keyedit_menu): New menu point "primary". - (change_primary_uid_cb): New. - (menu_set_primary_uid): New. - * sign.c (update_keysig_packet): New. - * build-packet.c (build_sig_subpkt): Put the primary UID flag into - the hashed area. Allow update of some more packets. - -2001-06-15 Werner Koch - - * getkey.c (merge_selfsigs): Exit gracefully when a secret key is - encountered. May happen if a secret key is in public keyring. - Reported by Francesco Potorti. - -2001-06-12 Werner Koch - - * getkey.c (compare_name): Use ascii_memistr(), ascii_memcasecmp() - * keyedit.c (keyedit_menu): Use ascii_strcasecmp(). - * armor.c (radix64_read): Use ascii_toupper(). - * ringedit.c (do_bm_search): Ditto. - * keygen.c (read_parameter_file): Ditto. - * openfile.c (CMP_FILENAME): Ditto. - * g10.c (i18n_init): We can now use just LC_ALL. - -2001-05-29 Werner Koch - - * keygen.c (generate_subkeypair): Print a warning if a subkey is - created on a v3 key. Suggested by Brian M. Carlson. - -2001-05-27 Werner Koch - - * keyid.c (get_lsign_letter): New. - * keylist.c (list_keyblock_colon): Use it here. - * mainproc.c (list_node): and here. - - * getkey.c, packet.h, free-packet.c: Removed that useless key - created field; I dunno why I introducded this at all - the - creation time is always bound to the key packet and subject to - fingerprint calculation etc. - - * getkey.c (fixup_uidnode): Add keycreated arg and use this - instead of the signature timestamp to calculate the - help_key_expire. Bug reported by David R. Bergstein. - (merge_selfsigs_main): Correct key expiration time calculation. - (merge_selfsigs_subkey): Ditto. - -2001-05-25 Werner Koch - - * revoke.c (gen_revoke): Add a cast to a tty_printf arg. - * delkey.c (do_delete_key): Ditto. - * keyedit.c (print_and_check_one_sig): Ditto. - (ask_revoke_sig): Ditto. - (menu_revsig): Ditto. - (check_all_keysigs): Removed unused arg. - -2001-05-23 Werner Koch - - * g10.c (opts): Typo fix by Robert C. Ames. - -2001-05-06 Werner Koch - - * revoke.c: Small typo fix - -2001-05-04 Werner Koch - - * passphrase.c (passphrase_clear_cache): Shortcut if agent usage - is not enabled. - -2001-05-01 Werner Koch - - * passphrase.c (writen): Replaced ssize_t by int. Thanks to - to Robert Joop for reporting that SunOS 4.1.4 does not have it. - -2001-04-28 Werner Koch - - * getkey.c (merge_public_with_secret): pkttype was not set to subkey. - -2001-04-27 Werner Koch - - * skclist.c (build_sk_list): Changed one log_debug to log_info. - -2001-04-25 Werner Koch - - * keyedit.c (show_prefs): Add a verbose mode. - (show_key_with_all_names): Pass verbose flag for special value of - with_pref. - (keyedit_menu): New command "showpref" - (show_key_with_all_names): Mark revoked uids and the primary key. - -2001-04-24 Werner Koch - - * getkey.c (get_primary_uid): Return a different string in case of - error and made it translatable. - - * build-packet.c (do_secret_key): Ugly, we wrote a zero - instead of the computed ndays. Thanks to M Taylor for complaining - about a secret key import problem. - -2001-04-23 Werner Koch - - * hkp.c (hkp_ask_import): Allow to specify a port number for the - keyserver. Add a kudge to set the no_shutdown flag. - (hkp_export): Ditto. - * options.skel: Document the changes - -2001-04-20 Werner Koch - - * options.skel: Add some more comments. - -2001-04-19 Werner Koch - - * keyid.c (mk_datestr): New. Handles negative times. We must do - this because Windoze segvs on negative times passed to gmtime(). - Changed all datestr_from function to use this one. - - * keyid.c, keyid.h (colon_strtime): New. To implement the - fixed-list-mode. - (colon_datestr_from_pk): New. - (colon_datestr_from_sk): New. - (colon_datestr_from_sig): New. - * keylist.c (list_keyblock_colon): Use these functions here. - * mainproc.c (list_node): Ditto. - -2001-04-18 Werner Koch - - * openfile.c (open_sigfile): Fixed the handling of ".sign". - * mainproc.c (proc_tree): Use iobuf_get_real_fname. - Both are by Vincent Broman. - -2001-04-14 Werner Koch - - * getkey.c (fixup_uidnode): Removed check for !sig which is - pointless here. Thanks to Jan Niehusmann. - -2001-04-10 Werner Koch - - * sig-check.c (check_key_signature2): Use log_info instead of - log_error so that messed up keys do not let gpg return an error. - Suggested by Christian Kurz. - - * getkey.c (merge_selfsigs_main): Do a fixup_uidnode only if we - have both, uid and sig. Thanks to M Taylor. - -2001-04-05 Werner Koch - - * armor.c (unarmor_pump_new,unarmor_pump_release): New. - (unarmor_pump): New. - * pipemode.c (pipemode_filter): Use the unarmor_pump to handle - armored or non-armored detached signatures. We can't use the - regular armor_filter becuase this does only chack for armored - signatures the very first time. In pipemode we may have a mix of - armored and binary detached signatures. - * mainproc.c (proc_tree): Do not print the "old style" notice when - this is a pipemode processes detached signature. - (proc_plaintext): Special handling of pipemode detached sigs. - - * packet.h (CTRLPKT_PLAINTEXT_MARK): New. - * parse-packet.c (create_gpg_control): New. - * kbnode.c (dump_kbnode): Support it here. - * mainproc.c (check_sig_and_print): Fixed the check for bad - sequences of multiple signatures. - (proc_plaintext): Add the marker packet. - (proc_tree): We can now check multiple detached signatures. - -2001-04-02 Werner Koch - - The length of encrypted packets for blocksizes != 8 was not - correct encoded. I think this is a minor problem, because we - usually use partial length packets. Kudos to Kahil D. Jallad for - pointing this out. - * packet.h: Add extralen to PKT_encrypted. - * cipher.c (write_header): Set extralen. - * build-packet.c (do_encrypted): Use extralen instead of const 10. - (do_encrypted_mdc): Ditto. - * parse-packet.c (parse_encrypted): Set extralen to 0 because we - don't know it here. - -2001-03-30 Werner Koch - - * getkey.c (premerge_public_with_secret): Changed wording an add - the keyID to the info message. - -2001-03-29 Werner Koch - - * getkey.c (premerge_public_with_secret): Use log_info instead of - log_error when no secret key was found for a public one. - Fix the usage if the secret parts of a key are not available. - - * openfile.c (ask_outfile_name): Trim spaces. - (open_outfile): Allow to enter an alternate filename. Thanks to - Stefan Bellon. - * plaintext.c (handle_plaintext): Ditto. - -2001-03-28 Werner Koch - - * mainproc.c (do_check_sig): Allow direct key and subkey - revocation signature. - * sig-check.c (check_key_signature2): Check direct key signatures. - Print the signature class along with an error. - -2001-03-27 Werner Koch - - * packet.h: Add a missing typedef to an enum. Thanks to Stefan Bellon. - - * g10.c: New option --no-sig-create-check. - * sign.c (do_sign): Implement it here. - * g10.c: New option --no-sig-cache. - * sig-check.c (check_key_signature2): Implement it here. - (cache_selfsig_result): and here. - - * keylist.c (list_keyblock): Removed debugging stuff. - - * getkey.c (cache_public_key): Made global. - * keygen.c (write_selfsig, write_keybinding): Cache the new key. - - * getkey.c (key_byname): Add new arg secmode and changed all - callers to request explicitly the mode. Deriving this information - from the other supplied parameters does not work if neither pk nor - sk are supplied. - -2001-03-25 Werner Koch - - * packet.h (ctrlpkttype_t): New. - * mainproc.c (add_gpg_control,proc_plaintext,proc_tree): Use the - new enum values. - * pipemode.c (make_control): Ditto. - * armor.c (armor_filter): Ditto. - -2001-03-24 Werner Koch - - * sign.c (do_sign): Verify the signature right after creation. - -2001-03-23 Werner Koch - - * status.c, status.h (STATUS_UNEXPECTED): New. - * mainproc.c (do_proc_packets): And emit it here. - -2001-03-21 Werner Koch - - * status.c: Add sys/types.h so that it runs on Ultrix. Reported - by Georg Schwarz.x - - * build-packet.c (build_sig_subpkt): Fixed generaton of packet - length header in case where 2 bytes headers are needed. Thanks to - Piotr Krukowiecki. - -2001-03-19 Werner Koch - - * g10.c (main): the default keyring is no always used unless - --no-default-keyring is given. - - * ringedit.c (add_keyblock_resource): invalidate cache after file - creation. - -2001-03-15 Werner Koch - - * keygen.c (ask_algo): Changed the warning of the ElGamal S+E Algo. - - * keylist.c (print_capabilities): New. - (list_keyblock_colon): and use it here. - -2001-03-13 Werner Koch - - * main.c, options.h: New option --fixed_list_mode. - * keylist.c (list_keyblock_colon): use it here. - - * getkey.c (merge_keys_and_selfsig): Divert merging of public keys - to the function used in key selection.. - * keylist.c (is_uid_valid): Removed. - (list_keyblock): Splitted into .. - (list_keyblock_print, list_keyblock_colon): .. these. - functions. Changed them to use the flags set in the key lookup code. - (reorder_keyblock): New, so that primary user IDs are listed first. - - * ringedit.c (keyring_copy): flush the new iobuf chaces before - rename or remove operations. This is mainly needed for W32. - - * hkp.c [HAVE_DOSISH_SYSTEM]: Removed the disabled code because we - have now W32 socket support in ../util/http.c - - * skclist.c (key_present_in_sk_list): New. - (is_duplicated_entry): New. - (build_sk_list): Check for duplicates and do that before unlocking. - -2001-03-12 Werner Koch - - * armor.c (parse_header_line): Removed double empty line check. - (parse_header_line): Replaced trim_trailing_ws with a counting - function so that we can adjust for the next read. - - * options.skel: Fixed 3 typos. By Thomas Klausner. Replaced the - keyserver example by a better working server. - - * parse-packet.c (parse_symkeyenc): Return Invalid_Packet on error. - (parse_pubkeyenc): Ditto. - (parse_onepass_sig): Ditto. - (parse_plaintext): Ditto. - (parse_encrypted): Ditto. - (parse_signature): Return error at other places too. - (parse_key): Ditto. - * g10.c (main): Set opt.list_packets to another value when invoked - with the --list-packets command. - * mainproc.c (do_proc_packets): Don's stop processing when running - under --list-packets command. - - * signal.c (do_sigaction): Removed. - (init_one_signal): New to replace the above. Needed to support - systems without sigactions. Suggested by Dave Dykstra. - (got_fatal_signal,init_signals): Use the above here. - (do_block): Use sigset() if sigprocmask() is not available. - - * armor.c (parse_hash_header): Test on TIGER192, which is the - correct value as per rfc2440. By Edwin Woudt. - -2001-03-08 Werner Koch - - * misc.c: Include time.h. By James Troup. - - * getkey.c: Re-enabled the unknown user Id and PK caches and - increased their sizes. - - * getkey.c (merge_selfsigs_main): Set expire date and continue - processing even if we found a revoked key. - (merge_selfsigs_subkeys): Ditto. - - * packet.h: Add an is_revoked flag to the user_id packet. - * getkey.c (fixup_uidnode): Set that flag here. - (merge_selfsigs_main): Fix so that the latest signature is used to - find the self-signature for an UID. - * parse-packet.c (parse_user_id): Zero out all fields. - * mainproc.c (check_sig_and_print): Print the primary user ID - according the the node flag and then all other non-revoked user IDs. - (is_uid_revoked): Removed; it is now handled by the key selection code. - - Changed the year list of all copyright notices. - -2001-03-07 Werner Koch - - * getkey.c (finish_lookup): Print an info message only in verbose mode. - -2001-03-05 Werner Koch - - * packet.h: Replaced sigsubpkt_t value 101 by PRIV_VERIFY_CACHE. - We have never used the old value, so we can do this without any harm. - * parse-packet.c (dump_sig_subpkt): Ditto. - (parse_one_sig_subpkt): Parse that new sub packet. - * build-packet.c (build_sig_subpkt): Removed the old one from the - hashed area. - (delete_sig_subpkt): New. - (build_sig_subpkt): Allow an update of that new subpkt. - * sig-check.c (check_key_signature2): Add verification caching - (cache_selfsig_result): New. - * export.c (do_export_stream): Delete that sig subpkt before exporting. - * import.c (remove_bad_stuff): New. - (import): Apply that function to all imported data - -2001-03-03 Werner Koch - - * getkey.c: Introduced a new lookup context flag "exact" and used - it in all place where we once used primary. - (classify_user_id2): Replaced the old function and add an extra - argument to return whether an exact keyID has been requested. - (key_byname): Removed the unused ctx.primary flag - (get_seckey_byname2): Ditto. - (finish_lookup): Changed debugging output. - -2001-03-02 Werner Koch - - * keylist.c (list_one): Remove the merge key calls. - -2001-03-01 Werner Koch - - * getkey.c (finish_lookup): Don't use it if we no specific usage - has been requested. - (merge_selfsigs_main): fix UID only if we have an signature. - (lookup): Return UNU_PUBKEY etc. instead of NO_PUBKEY if we found - a key but the requested usage does not allow this key. - * import.c (import_one): Take UNU_PUBKEY into account. - * mainproc.c (list_node): Ditto. - * keylist.c (list_keyblock): Ditto. - * keyedit.c (print_and_check_one_sig): Ditto. - -2001-02-09 Werner Koch - - * delkey.c (delete_key): Removed that silly assert which rendered - the whole new stuff meaningless. - -2001-02-08 Werner Koch - - * getkey.c (key_byname): It can happen that we have both, sk and pk - NULL, fix for that. - - * parse-packet.c (parse_one_sig_subpkt): Add support for - primary_uid and key_flags. - (can_handle_critical): Ditto - - * parse-packet.c (parse_encrypted): Fixed listing of pktlen for - MDC packets. - - * getkey.c: Backported the version of this file from gpg 1.1. this - involved some changes in other files too. - * parse-packet.c (parse_key): Clear req_usage. - * skclist.c (build_sk_list): Use req_usage to pass the usage - information to the lookup function. - * pkclist.c (build_pk_list): Ditto. - * free-packet.c (copy_public_parts_to_secret_key): New. - * keydb.h: Add IS_* macros to check the sig_class. - * misc.c (openpgp_cipher_test_algo): New. - (openpgp_pk_test_algo): New. - (openpgp_pk_algo_usage): New. - (openpgp_md_test_algo): New. - * packet.h: Add a few fields to PKT_{public,secret}_key and - PKT_user_id. - * seckey-cert.c (do_check): Use the new main_keyid field. - -2001-02-04 Werner Koch - - * encr-data.c (decrypt_data): Catch error when we had problems to - parse the encrypted packet. By Timo. - -2001-01-29 Werner Koch - - * g10.c (main): --batch does now set nogreeting. - - * delkey.c (do_delete_key): Fixed delete-both functionality. - -2001-01-22 Werner Koch - - * g10.c: New command --delete-secret-and-public-key. - * delkey.c (delete_key): Add new arg allow_both. - (do_delete_key): Move most stuff from above to this new function. - -2001-01-12 Werner Koch - - * passphrase.c (passphrase_to_dek): Use MD5 when IDEA is installed - and we have no S2K. - * mainproc.c (proc_encrypted): Likewise - -2001-01-11 Werner Koch - - * sig-check.c (do_check): Print the signature key expire message - only in verbose mode and added the keyID. - -2001-01-09 Werner Koch - - * status.c, status.h: New status USERID_HINT. - (write_status_text): Replace LF and CR int text by C-escape sequence. - - * passphrase.c (passphrase_to_dek): Fixed the NEED_PASSPHRASE - output. It does now always print 2 keyIDs. Emit the new - USERID_HINT. - -2001-01-08 Werner Koch - - * g10.c, options.h: New option --no-expensive-trust-checks. - * keylist.c (list_keyblock): Act on this option. - -2001-01-04 Werner Koch - - * g10.c (main): Set homedir only in the pre-parsing phase and - replace backslashes in the W32 version. - -2001-01-03 Werner Koch - - * status.c, status.h : New status KEY_CREATED - * keygen.c (do_generate_keypair,generate_subkeypair): Emit it. - -2000-12-28 Werner Koch - - * signal.c (got_fatal_signal): Remove lockfiles here because the - atexit stuff does not work due to the use of raise. Suggested by - Peter Fales. - * gpgv.c (remove_lockfiles): New stub. - -2000-12-19 Werner Koch - - * status.c, status.h (cpr_get_no_help): New. - * keyedit.c (keyedit_menu): Use it here because we have our own - help list here. - -2000-12-18 Werner Koch - - * mainproc.c (print_failed_pkenc): Don't print the sometimes - confusing message about unavailabe secret key. Renamed ... - (print_pkenc_list): ... to this and introduced failed arg. - (proc_encrypted): Print the failed encryption keys and then - the one to be used. - (proc_pubkey_enc): Store also the key we are going to use. - - * mainproc.c (check_sig_and_print): Don't list revoked user IDs. - (is_uid_revoked): New. - -2000-12-08 Werner Koch - - * pipemode.c: Made the command work. Currently only for - non-armored detached signatures. - * mainproc.c (release_list): Reset the new pipemode vars. - (add_gpg_control): Handle the control packets for pipemode - * status.c, status.h: New stati {BEGIN,END}_STREAM. - -2000-12-07 Werner Koch - - * g10.c: New option --allow-secret-key-import. - * import.c (import_keys,import_keys_stream): Honor this option. - (import): New arg allow_secret and pass that arg down to ... - (import_secret_one): to this and print a warning if secret key - importing is not allowed. - -2000-12-05 Werner Koch - - * cipher.c (cipher_filter): Moved the end_encryption status ... - * encode.c (encode_simple,encode_crypt): to here - * sign.c (sign_file): and here. - - * status.c (mywrite): Removed. - (get_status_string): Removed the LFs from the strings. - (set_status_fd,is_status_enabed,write_status_text, - write_status_buffer): Replaced all mywrite by stdio calls and use - fdopen to create a strem. This is needed to make things smoother - in the W32 version. - -2000-12-04 Werner Koch - - * import.c (merge_blocks): Increment n_sigs for revocations. - -2000-11-30 Werner Koch - - * g10.c (main): Use iobuf_translate_file_handle for all options - with filehandles as arguments. This is function does some magic - for the W32 API. - - * verify.c (verify_signatures): Add a comment rant about the - detached signature problem. - * mainproc.c (proc_tree): Issue an error if a detached signature - is assumed but a standard one was found. - * plaintext.c (hash_datafiles): Don't fall back to read signature - from stdin. - * openfile.c (open_sigfile): Print verbose message only if the - file could be accessed. - -2000-11-24 Werner Koch - - * passphrase.c [HAVE_DOSISH_SYSTEM]: Disabled all the agent stuff. - -2000-11-16 Werner Koch - - * g10.c: New option --use-agent - * passphrase.c (agent_open,agent_close): New. - (agent_get_passphrase,agent_clear_passphrase): New. - (passphrase_clear_cache): New. - (passphrase_to_dek): Use the agent here. - * seckey-cert.c (do_check): Clear cached passphrases. - -2000-11-15 Werner Koch - - * status.c (write_status_text): Moved the big switch to ... - (get_status_string): ... new function. - (write_status_buffer): New. - - * status.c (mywrite): New and replaced all write() by this. - - * status.c, status.h: Add 3 status lcodes for notaions and policy. - * mainproc.c (print_notation_data): Do status output of notations. - -2000-11-13 Werner Koch - - * sign.c (clearsign_file): Use LF macro to print linefeed. - -2000-11-11 Paul Eggert - - Clean up the places in the code that incorrectly use "long" or - "unsigned long" for file offsets. The correct type to use is - "off_t". The difference is important on large-file hosts, - where "off_t" is longer than "long". - - * keydb.h (struct keyblock_pos_struct.offset): - Use off_t, not ulong, for file offsets. - * packet.h (dbg_search_packet, dbg_copy_some_packets, - search_packet, copy_some_packets): Likewise. - * parse-packet.c (parse, dbg_search_packet, search_packet, - dbg_copy_some_packets, copy_some_packets): Likewise. - * ringedit.c (keyring_search): Likewise. - - * parse-packet.c (parse): Do not use %lu to report file - offsets in error diagnostics; it's not portable. - * ringedit.c (keyring_search): Likewise. - -2000-11-09 Werner Koch - - * g10.c (main): New option --enable-special-filenames. - -2000-11-07 Werner Koch - - * g10.c (main): New command --pipemode. - * pipemode.c: New. - -2000-10-23 Werner Koch - - * armor.c (armor_filter): Changed output of hdrlines, so that a CR - is emitted for DOS systems. - - * keygen.c (read_parameter_file): Add a cast for isspace(). - - * status.c (myread): Use SIGINT instead of SIGHUP for DOS. - -2000-10-19 Werner Koch - - * g10.c: New option --ignore-crc-error - * armor.c (invalid_crc): New. - (radix64_read): Act on new option. - - * openfile.c (try_make_homedir): Klaus Singvogel fixed a stupid - error introduced on Sep 6th. - -2000-10-18 Werner Koch - - * misc.c (print_cipher_algo_note): Don't print the note for AES. - Changed wording. - -2000-10-16 Werner Koch - - * mainproc.c (do_proc_packets): Hack to fix the problem that - signatures are not detected when there is a MDC packet but no - compression packet. - - * g10.c (print_hashline): New. - (print_mds): Use above func with --with-colons. - - * mainproc.c (check_sig_and_print): Detect multiple signatures - and don't verify them. - -2000-10-14 Werner Koch - - * mainproc.c (add_onepass_sig): There is an easier solution to the - error fixed yesterday; just check that we only have onepass - packets. However, the other solution provides an cleaner - interface and opens the path to get access to other information - from the armore headers. - (release_list): Reset some more variables. - -2000-10-13 Werner Koch - - * mainproc.c (add_gpg_control): New. - (do_proc_packets): use it. - (proc_plaintext): Changed logic to detect clearsigns. - (proc_tree): Check the cleartext sig with some new code. - - * packet.h: New packet PKT_GPG_CONTROL. - * parse-packet.c (parse_gpg_control): New. - * misc.c (get_session_marker): New. - * armor.c (armor_filter): Replaced the faked 1-pass packet by the - new control packet. - - * keyedit.c (keyedit_menu): Allow batchmode with a command_fd. - * status.c (my_read): New. - (do_get_from_fd): use it. - -2000-10-12 Werner Koch - - * keygen.c (keygen_add_std_prefs): Add Rijndael to the prefs. - -2000-10-07 Werner Koch - - * gpgv.c: Add more stubs for ununsed code to make the binary smaller. - -Wed Oct 4 15:50:18 CEST 2000 Werner Koch - - * sign.c (hash_for): New arg to take packet version in account, changed - call callers. - - * gpgv.c: New. - * Makefile.am: Rearranged source files so that gpgv can be build with - at least files as possible. - -Mon Sep 18 12:13:52 CEST 2000 Werner Koch - - * hkp.c (not_implemented): Print a notice for W32 - -Fri Sep 15 18:40:36 CEST 2000 Werner Koch - - * keygen.c (keygen_add_std_prefs): Changed order of preferences to - twofish, cast5, blowfish. - - * pkclist.c (algo_available): Removed hack to disable Twofish. - -Thu Sep 14 17:45:11 CEST 2000 Werner Koch - - * parse-packet.c (dump_sig_subpkt): Dump key flags. Print special - warning in case of faked ARRs. - - * getkey.c (finsih_lookup): Hack so that for v4 RSA keys the subkey - is used for encryption. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch - - * g10.c (main): Default S2K algorithms are now SHA1 and CAST5 - this - should solve a lot of compatibility problems with other OpenPGP - apps because those algorithms are SHOULD and not optional. The old - way to force it was by using the --openpgp option whith the drawback - that this would disable a couple of workarounds for PGP. - - * g10.c (main): Don't set --quite along with --no-tty. By Frank Tobin. - - * misc.c (disable_core_dump): Don't display a warning here but a return - a status value and ... - * g10.c (main): ...print warnining here. Suggested by Sam Roberts. - -Wed Sep 13 18:12:34 CEST 2000 Werner Koch - - * keyedit.c (keyedit_menu): Allow to use "debug" on the secret key. - - * ringedit.c (cmp_seckey): Fix for v4 RSA keys. - * seckey-cert.c (do_check): Workaround for PGP 7 bug. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch - - * misc.c (print_pubkey_algo_note): Do not print the RSA notice. - * sig-check.c (do_signature_check): Do not emit the RSA status message. - * pubkey-enc.c (get_session_key): Ditto. - - * encode.c (encode_simple, encode_crypt): Fix for large files. - * sign.c (sign_file): Ditto. - -Wed Sep 6 14:59:09 CEST 2000 Werner Koch - - * passphrase.c (hash_passphrase): Removed funny assert. Reported by - David Mathog. - - * openfile.c (try_make_homedir): Changes for non-Posix systems. - * g10.c (main): Take the default homedir from macro. - - * g10.c: The --trusted-key option is back. - * trustdb.c (verify_own_key): Handle this option. - (add_ultimate_key): Moved stuff from verify_own_key to this new func. - (register_trusted_key): New. - -Fri Aug 25 16:05:38 CEST 2000 Werner Koch - - * parse-packet.c (dump_sig_subpkt): Print info about the ARR. - - * openfile.c (overwrite_filep): Always return okay if the file is - called /dev/null. - (make_outfile_name): Add ".sign" to the list of know extensions. - (open_sigfile): Ditto. - -Wed Aug 23 19:52:51 CEST 2000 Werner Koch - - * g10.c: New option --allow-freeform-uid. By Jeroen C. van Gelderen. - * keygen.c (ask_user_id): Implemented here. - -Fri Aug 4 14:23:05 CEST 2000 Werner Koch - - * status.c (do_get_from_fd): Ooops, we used fd instead of opt.command_fd. - Thanks to Michael Tokarev. - -Tue Aug 1 20:06:23 CEST 2000 Werner Koch - - * g10.c: New opttion --try-all-secrets on suggestion from Matthias Urlichs. - * pubkey-enc.c (get_session_key): Quite easy to implement here. - -Thu Jul 27 17:33:04 CEST 2000 Werner Koch - - * g10.c: New option --merge-only. Suggested by Brendan O'Dea. - * import.c (import_one): Implemented it here - (import_secret_one): Ditto. - (print_stats): and give some stats. - -Thu Jul 27 12:01:00 CEST 2000 Werner Koch - - * g10.c: New options --show-session-key and --override-session-key - * pubkey-enc.c (hextobyte): New. - (get_override_session_key): New. - * mainproc.c (proc_pubkey_enc): Add session-key stuff. - * status.h, status.c (STATUS_SESSION_KEY): New. - -Thu Jul 27 10:02:38 CEST 2000 Werner Koch - - * g10.c (main): Use setmode(O_BINARY) for MSDOS while generating random bytes - (print_mds): Likewise for stdin. - * plaintext.c (handle_plaintext): Likewise for stdout. - -Mon Jul 24 10:30:17 CEST 2000 Werner Koch - - * keyedit.c (menu_expire): expire date for primary key can be set again. - -Wed Jul 19 11:26:43 CEST 2000 Werner Koch - - * keylist.c (is_uid_valid): New. - (list_keyblock): Print validity information for all user IDs. Note, this - has to be done at other places too; for now we have only minimal support. - -Wed Jul 12 13:32:06 CEST 2000 Werner Koch - - * helptext.c, pkclist.c: s/superseeded/superseded/ - -Mon Jul 10 16:08:57 CEST 2000 Werner Koch - - * parse-packet.c (enum_sig_subpkt): Fixed testing on crtitical bit in case - of a NULL buffer. Reported by Peter Marschall. - -Wed Jul 5 13:28:45 CEST 2000 Werner Koch - - * keyedit.c, keyid.c: Add some _() - - * argparse.c: Changed the flag to suppress --version handling to also - suppress --help. - -Wed Jun 28 11:54:44 CEST 2000 Werner Koch - - * armor.c (armor_filter): Set sigclass to 0 in case of non-dash-escaped - clearsig. This makes this mode work again. - - * mainproc.c (proc_tree): Fixed handling of one-pass-sig packets in textmode. - Disabled the ugly workaround for PGP 5 - let's see whether thi breaks less - cases. Found by Ted Cabeen. - - * options.h (DBG_HASHING): New. All commented md_start_debug are now - controlled by this debug option. - - * sign.c (print_status_sig_created): New and called from 2 places. - - * keygen.c (gen_rsa): New, but commented. - (ask_algo): Commented support for RSA. - - * seckey-cert.c (protect_secret_key): Started to fix the code for v4 RSA - keys - it is not solved yet. However, we have time until, Sep 20th ;) - -Wed Jun 14 12:27:09 CEST 2000 Werner Koch - - * status.c (init_shm_coprocessing): Changed the sequence of the get,attach - to cope with the changes in newer Linux kernels. This bug has been found - by who also proposed this solution. Hopefully - this does not break gpg on to many systems. - - * cipher.c (write_header): Protect the IV with the MDC too. - * encr-data.c (decrypt_data): Likewise. - -Fri Jun 9 10:09:52 CEST 2000 Werner Koch - - * g10.c: New options --no-auto-key-retrieve - * options.h (auto_key_retrieve): New. - * mainproc.c (check_sig_and_print): Implemented that. - -Wed Jun 7 19:19:09 CEST 2000 Werner Koch - - * sig-check.c (do_check): Use EMULATE_MDENCODE also on v4 packets. - -Wed Jun 7 17:25:38 CEST 2000 Werner Koch - - * cipher.c (write_header): Use plain CFB mode for MDC encrypted packets. - * encr-data.c (decrypt_data): Ditto. - -Mon Jun 5 23:41:54 CEST 2000 Werner Koch - - * seskey.c (do_encode_md, encode_md_value): Add new arg v3compathack to work - around a bug in old versions. - * sig-check.c (do_check): use the aboved workaround when enabled. - * g10.c: New option --emulate-md-decode-bug - -Mon Jun 5 12:37:43 CEST 2000 Werner Koch - - * build-packet.c (do_mdc): New. - (do_encrypted_mdc): Changed for the new proposal. - * parse-packet.c (parse_mdc): New. - (parse_encrypted): Fixed for the new proposal. - * packet.h (PKT_MDC): New. - * cipher.c (cipher_filter): Build the MDC packet here. - * g10.c (main): Enable --force-mdc. - * encr-data.c (mdc_decode_filter): Fixed for new MDC method - - * options.h(rfc2440): New. - * g10.c (main): Changed the selected values for --openpgp to not include - optional algorithms. - -Thu May 18 11:38:54 CEST 2000 Werner Koch - - * keyedit.c (keyedit_menu): Add a keyword arg to the prompt. - - * status.c, status.h: Added 3 new status tokens. - * status.c (do_get_from_fd): New. - (cpr_enabled,cpr_get,cpr_get_hidden,cpr_kill_prompt, - cpr_get_answer_is_yes,cpr_get_answer_yes_no_quit): Modified to work - with the new function. - * g10.c: Add new option --command-fd. - - * status.c (progress_cb): New. - (set_status_fd): Register progress functions - -Fri May 12 14:01:20 CEST 2000 Werner Koch - - * delkey.c (delete_key): Add 2 new status messages - * status.c, status.h (STATUS_DELETE_PROBLEM): New. - - Fixed years of copyright in all source files. - -Mon May 1 17:08:14 CEST 2000 Werner Koch - - * trustdb.c (propagate_validity): Fixed the bug that only one uid - gets fully trusted even when all are signed by an ultimate key. - -Mon May 1 15:38:04 CEST 2000 Werner Koch - - * getkey.c (key_byname): Always returned a defined context. Fixed - a segv for invalid user id specifications. Reported by Walter Koch. - - * getkey.c (get_user_id): I18ned "no user id" string. By Walter. - - * pkclist.c (do_show_revocation_reason): Typo fixes. - * helptext.c: Ditto. - - * armor.c (armor_filter): Fixed some CRLF issues. By Mike McEwan. - -Fri Apr 14 19:37:08 CEST 2000 Werner Koch - - * pkclist.c (do_show_revocation_reason): New. - (show_revocation_reason): New and called at various places. - - * g10.c (main): Fixed small typo. - - * pkclist.c (do_we_trust): Act on always_trust but not for revoked - keys. Suggested by Chip Salzenberg. - - * g10.c: New option --lock-never. - - * ringedit.c (get_writable_keyblock_file): New. - * keygen.c (do_generate_keypair): Use this instead of the hardwired one. - - * keygen.c (ask_user_id): Check that the email address is in the - correct field. Suggested by Christian Kurz. - -Mon Apr 10 13:34:19 CEST 2000 Werner Koch - - * keyedit.c (show_key_with_all_names): s/sbb/ssb/ - -Tue Mar 28 14:26:58 CEST 2000 Werner Koch - - * trustdb.c (verify_own_keys): Do not print warning about unprotected - key when in quiet mode. - -Wed Mar 22 13:50:24 CET 2000 Werner Koch - - * mainproc.c (print_userid): Do UTF8 conversion before printing. - * import.c (import_one): Ditto. - (import_secret_one): Ditto. - (delete_inv_parts): Ditto. - -Thu Mar 16 16:20:23 CET 2000 Werner Koch - - * keylist.c (print_key_data): Handle a NULL pk gracefully. - - * getkey.c (merge_one_pk_and_selfsig): Fixed silly code for - getting the primary keys keyID but kept using the one from the - subkey. - * pubkey-enc.c (get_it): Print a note for expired subkeys. - - * getkey.c (has_expired): New. - (subkeys_expiretime): New. - (finish_lookup): Check for expired subkeys needed for encryption. - (merge_keys_and_selfsig): Fixed expiration date merging for subkeys. - - * keylist.c (list_keyblock): Print expiration time for "sub". - (list_one): Add missing merging for public keys. - * mainproc.c (list_node): Ditto. - -2000-03-14 13:49:38 Werner Koch (wk@habibti.openit.de) - - * keygen.c (keyedit_menu): Do not allow to use certain commands - while the secret key is selected. - -2000-03-09 12:53:09 Werner Koch (wk@habibti.openit.de) - - * keygen.c (ask_expire_interval): Movede parsig to ... - (parse_expire_string): ... this new function. And some new control - commands. - (proc_parameter_file): Add expire date parsing. - (do_generate_keypair): Allow the use of specified output files. - -2000-03-08 10:38:38 Werner Koch (wk@habibti.openit.de) - - * keygen.c (ask_algo): Removed is_v4 return value and the commented - code to create Elg keys in a v3 packet. Removed the rounding - of key sizes here. - (do_create): Likewise removed arg v4_packet. - (gen_elg): Likewise removed arg version. Now rounding keysizes here. - (gen_dsa): Rounding keysize now here. - (release_parameter_list): New - (get_parameter*): New. - (proc_parameter_file): New. - (read_parameter_file): New. - (generate_keypair): Splitted. Now uses read_parameter_file when in - batch mode. Additional argument to specify a parameter file. - (do_generate_keypair): Main bulk of above fucntion and uses the - parameter list. - (do_create): Don't print long notice in batch mode. - * g10.c (main): Allow batched key generation. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch - - * pubkey-enc.c (get_it): Print a note about unknown cipher algos. - - * g10.c (opts): Add a note to the help listing about the man page - and removed some options from the help listing. - - * keyedit.c (print_and_check_one_sig): Use a new function to truncate - the output of the user ID. Suggested by Jan-Benedict Glaw. - -Wed Feb 23 10:07:57 CET 2000 Werner Koch - - * helptext.c: typo fix. - -Thu Feb 17 13:39:32 CET 2000 Werner Koch - - * revoke.c: Removed a bunch of commented code. - - * packet.h (SIGSUBPKT_REVOC_REASON): New. - * build-packet.c (build_sig_subpkt): Support new sub packet. - * parse-packet.c (parse_one_sig_subpkt): Ditto. - (dump_sig_subpkt): Ditto. - * revoke.c (ask_revocation_reason): New. - (release_revocation_reason_info): New. - (revocation_reason_build_cb): New. - (gen_revoke): Ask for reason. - * main.h (struct revocation_reason_info): Add declaration. - * keyedit.c (menu_revsig): Add support for revocation reason. - (menu_revkey): Ditto. - (sign_uid_mk_attrib): Renamed to ... - (sign_mk_attrib): ... this, made static and add support for reasons. - -Tue Feb 15 08:48:13 CET 2000 Werner Koch - - * build-packet.c (build_packet): Fixed fixing of old comment packets. - - * import.c (import_keys): Fixed importing from stdin when called with - nnames set to zero as it normally happens. - -Mon Feb 14 14:30:20 CET 2000 Werner Koch - - * sig-check.c (check_key_signature2): Add new arg r_expired. - (do_signature_check): New arg to pass it down to ... - (do_check): New arg r-expire which is set when the signature - has expired. - * trustdb.c (check_sig_record): Set SIGF_EXPIRED flag and set - the expiretime to zero so that thi signature will not be checked - anymore. - -Fri Feb 11 17:44:40 CET 2000 Werner Koch - - * g10.c (g10_exit): Update the random seed_file. - (main): Set the random seed file. New option --no-random-seed-file. - -Thu Feb 10 17:39:44 CET 2000 Werner Koch - - * keyedit.c (menu_expire): Fixed segv due to unitialized sub_pk. - By Rmi. - -Thu Feb 10 11:39:41 CET 2000 Werner Koch - - * keylist.c (list_keyblock): Don't print warnings in the middle of - regulat output lines. By Rmi. - - * sig-check.c: Include options.h - -Wed Feb 9 15:33:44 CET 2000 Werner Koch - - * gpg.c: New option --ignore-time-conflict - * sig-check.c (do_check): Implemented this option. - * trustdb.c (check_trust): Ditto. - * sign.c (do_sign): Ditto. - * keygen.c (generate_subkeypair): Ditto. - - * encode.c (encode_simple): use iobuf_cancel after open failure. - Reported by Huy Le. - -Fri Jan 14 18:32:01 CET 2000 Werner Koch - - * packet.h (STRING2KEY): Changed mode from byte to int. - * parse-packet.c (parse_key): Add the special GNU protection stuff - * build-packet.c (so_secret_key): Ditto. - * seckey-cert.c (do_check): Ditto. - * keyedit.c (change_passphrase): Ditto. - * export.c (export_secsubkeys): New. - (do_export_stream): Hack to export the primary key using mode 1001. - * g10.c: New command --export-secret-subkeys - -Thu Jan 13 19:31:58 CET 2000 Werner Koch - - * armor.c (is_armored): Check for 1-pass-sig packets. Reported by - David Hallinan . - (armor_filter): Replaced one LF by the LF macro. Reported by - Wolfgang Redtenbacher. - -Wed Jan 5 11:51:17 CET 2000 Werner Koch - - * g10.c (main): Reset new global flag opt.pgp2_workarounds - when --openpgp is used. - * mainproc.c (proc_plaintext): Do the PGP2,5 workarounds only - when the global flag is set. - (proc_tree): Ditto. - * textfilter.c (copy_clearsig_text): Ditto. - * armor.c (armor_filter): Ditto. - - * g10.c: New option --list-only - * mainproc.c (proc_tree): Don't do it if opt.list_only is active. - (proc_pubkey_enc): Implement option. - - * status.h, status.c ({BEGIN,END}_{EN,DE}CRYPTION): New. - * cipher.c (cipher_filter): New status outputs. - * mainproc.c (proc_encrypted): New status outputs. - -Fri Dec 31 14:08:15 CET 1999 Werner Koch - - * armor.c (armor_filter): Made the "Comment:" header translatable. - - * hkp.c (hkp_import): Make sure that the program does not return - success when there is a connection problem. Reported by Phillip Jones. - -Sun Dec 19 15:22:26 CET 1999 Werner Koch - - * armor.c (LF): Use this new macro at all places where a line LF - is needed. This way DOSish textfiles should be created when the - input data is also in dos mode. - * sign.c (LF): Ditto. - * textfilter.c (LF): Ditto. - (copy_clearsig_text): Disabled the forcing of CR,LF sequences - for DOS systems. - - * plaintext.c (handle_plaintext): Fixes for line endings on DOS. - and react on a LF in cleartext. - * armor.c (fake_packet): Restore the original line ending after - removing trailing spaces. - - * signal.c (got_fatal_signal): DOS fix. - -Thu Dec 16 10:07:58 CET 1999 Werner Koch - - * mainproc.c (print_failed_pkenc): Fix for unknown algorithm. - Found by fygrave@epr0.org. - -Thu Dec 9 10:31:05 CET 1999 Werner Koch - - * hkp.c: i18n the strings. - -Sat Dec 4 15:32:20 CET 1999 Werner Koch - - * trustdb.c (verify_key): Shortcut for ultimately trusted keys. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch - - * pkclist.c (build_pk_list): Validate the trust using the namehash - if this one has been set by the key lookup. - - * g10.c: Add --delete-secret-key to the help page. - - * openfile.c (copy_options_file): Made static. - (try_make_homedir): New. - * ringedit.c (add_keyblock_resource): Use the try_make_hoemdir logic. - * tdbio.c (tdbio_set_dbname): Likewise. - - * keygen.c (generate_user_id): Use m_alloc_clear() here. We should - better use an allocation function specific to the user_id packet. - - * keygen.c (keygen_add_std_prefs): Changed symmetric preferences - to include Blowfish again. This is due to it's better speed compared - to CAST5. - - * g10.c (strusage): Print the home directory. - - * armor.c (armor_filter): Take action on the cancel control msg. - * filter.h (armor_filter_context_t): Add cancel flag. - -Mon Nov 29 21:52:11 CET 1999 Werner Koch - - * g10.c: New option --fast-list-mode .. - * keylist.c (list_keyblock): .. and implemented. - * mainproc.c (list_node): Ditto. - - * import.c (mark_non_selfsigned_uids_valid): Fixed the case that there - is a uid without any packet following. - -Mon Nov 22 11:14:53 CET 1999 Werner Koch - - * mainproc.c (proc_plaintext): Never enable the hash processing - when skip_verify is active. - - * armor.c (parse_header_line): Stop parsing on a WS line too. - Suggested by Aric Cyr. - - * tdbdump.c (HEXTOBIN): Changed the name of the argument, so that - traditional cpp don't mess up the macros. Suggested by Jos Backus. - - * mainproc.c (list_node): Print the PK algo in the --with-colon mode. - * keylist.c (list_keyblock): Ditto. - - * signal.c (got_fatal_signal): Found the reason why exit(8) did not - work - it is better to set the disposition back to default before - raising the signal. Print the notice on stderr always. - -Fri Nov 12 20:33:19 CET 1999 Werner Koch - - * g10.c (make_username): Swapped the logic. - * keylist.c (public_key_list): Now takes a STRLIST as arg and moved - the creation ot this list to the caller, so that he can copy with - UTF-conversion of user IDs. Changed all callers. - (secret_key_list): Likewise. - - * getkey.c (get_user_id_string_native): New and ... - * encode.c (write_pubkey_enc_from_list): ... use it here. - - * pubring.asc: Updated. - - * packet.h (PKT_PHOTO_ID): New. - * parse-packet.c (parse_photo_id): New. - * build-packet.c (do_user_id: Handle photo IDs. - (build_packet): Change CTB for photo IDs - * free-packet.c (free_user_id): Release memory used for photo IDs - * sig-check.c (hash_uid_node): Handle photo IDs too. - * trustdb.c (print_uid_from_keyblock): Hash photo ID. - (make_uid_records): Ditto. - * getkey.c (find_by_name): Ditto. - * keyedit.c (show_prefs): Ditto. - * keylist.c (list_keyblock): Ditto. - -Thu Oct 28 16:08:20 CEST 1999 Werner Koch - - * keygen.c (ask_expire_interval): Print a warning for systems - with a signed 32 time_t if the exiration time is beyoind 2038. - -Fri Oct 8 20:40:50 CEST 1999 Werner Koch - - * ringedit.c (enum_keyblocks): The last fix way really stupid; - reverted and set rt to Unknown. - -Fri Oct 8 20:32:01 CEST 1999 Werner Koch - - * ringedit.c (enum_keyblocks): Zero the entire kbpos out on open. - - * g10.c (oEntropyDLL): Removed option. - (main): Made the warning on development versions more verbose. - - * g10.c (oHonorHttpProxy): New option. - * hkp.c (hkp_ask_import,hkp_export): Implement this option. - * options.skel: Enable this option for new installations - -Mon Oct 4 21:23:04 CEST 1999 Werner Koch - - * import.c (import_keys): Changed calling interface, adjusted caller. - (import): Moved printing of stats out ... - (print_stats): New. ... to here. - (import_keys_stream): Call stats print here. - (import_keys): Print stats as totals for all files. - - * tdbio.h (DIRF_NEWKEYS): New - * tdbio.c (tdbio_dump_record): Print the new flag. - * trustdb.c (check_trust_record): New arg sigs_only. Adapted all - callers. - (do_update_trust_record): Removed recheck arg and add a new sigs_only - do we can later improve on the performance. Changed all callers too. - (check_trustdb): Evalutate the new flag and add a status output. - Do a check when the dir record has not been checked. - (build_cert_tree): Evaluate the new flag. - (check_trust): Ditto. Do a trust_record check, when the dir record - is not marked as checked. - (mark_fresh_keys): New. - (clear_lid_table): New. - (sync_trustdb): New. - * import.c (import_keys): Call sync_trustdb() after processing. - (import_keys_stream): Ditto. - * tdbdump.c (import_ownertrust): Ditto. - - * import.c (import_revoke_cert): Notify the trust DB. - (do_update_trust_record): Use |= to set the REVOKED bit and not &=; - shame on me for this bad copy+paste introduced bug. - (do_we_trust): Add trustmask to allow revoked key override to work. - Chnaged are to allow return of a mofified trustlevel. Adapted the - one caller. - - * g10.c: New options --emulate-3des-s2k-bug - * passphrase.c (hash_passphrase): Implemented above. - - * mainproc.c (proc_tree): Check for standalone signatures. - (do_check_sig): Print a notice for a standalone revocation - (check_sig_and_print): Do not print an error for unchecked standalone - revocations. - -Tue Sep 28 20:54:37 CEST 1999 Werner Koch - - * encode.c (encode_simple): Use new CTB when we don't have the - length of the file. This is somewhat strange as the comment above - indicates that this part is actually fixed for PGP 5 - maybe I simply - lost the source line, tsss. - - * armor.c (armor_filter): Set a flag if no OpenPGP data has been found. - * verify.c (verify_signatures): Add an error helptext. - -Thu Sep 23 19:24:30 CEST 1999 Werner Koch - - * openfile.c (open_outfile): Fixed the 8dot3 handling. - - * passphrase.c (passphrase_to_dek): Print uid using utf8 func. - * delkey.c (delete_key): Ditto. - * pkclist.c (show_paths,do_edit_ownertrust,do_we_trust): Ditto - (do_we_trust_pre): Ditto. - * trustdb.c (print_user_id,check_uidsigs): Ditto. - * revoke.c (gen_revoke,ask_revoke_sig): Ditto. - -Thu Sep 23 09:52:58 CEST 1999 Werner Koch - - * verify.c (print_file_status): New. - (verify_one_file): Moved status print to th new fnc. Add error status. - * status.c, status.h (STATUS_FILE_ERROR): New - -Wed Sep 22 10:14:17 CEST 1999 Werner Koch - - * openfile.c (make_outfile_name): Use case-insenstive compare for - DOS systems. Add ".pgp" to the list of know extensions. - (open_outfile): For DOS systems try to replace the suffiy instead of - appending it. - - * status.c, status.h: Add STATUS_FILE_{START,DONE}. - * verify.c (verify_one_file): Emit these new stati. - - * sign.c (clearsign_file): Avoid duplicated Entries in the "Hash:" - line. Those headers are now only _not_ printed when there are - only old-style keys _and_ all hashs are MD5. - -Mon Sep 20 12:24:41 CEST 1999 Werner Koch - - - * verify.c (verify_files, ferify_one_file): New. - * g10.c: New command --verify-files - -Fri Sep 17 12:56:42 CEST 1999 Werner Koch - - * g10.c: Add UK spelling as alias for armor options ;-) - - * import.c (append_uid): Fixed a SEGV when there is no selfsig and - no subkey. - (merge_sigs): Ditto. Removed the assertion. - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch - - * g10.c: New option --entropy-dll-name - -Mon Sep 13 10:51:29 CEST 1999 Werner Koch - - * signal.c (got_fatal_signal): Print message using write(2) and - only for development versions. - -Mon Sep 6 19:59:08 CEST 1999 Werner Koch - - * tdbio.c (tdbio_set_dbname): Use mkdir macro - * ringedit.c (add_keyblock_resource): Ditto. - -Fri Sep 3 10:04:45 CEST 1999 Werner Koch - - * pkclist.c (build_pk_list): Skip keys set with --encrypt-to also - when asking for a key. - - * plaintext.c (handle_plaintext): Make sure that we don't read a - second EOF in the read loop for partial length packets. - - * mainproc.c (check_sig_and_print): print user ID as utf-8. - -Thu Sep 2 16:40:55 CEST 1999 Werner Koch - - * import.c (merge_blocks): First add new subkeys, then merge subkey - certificates. - (merge_sigs): Don't merge subkey signatures here. - -Wed Sep 1 15:30:44 CEST 1999 Werner Koch - - * keygen.c (ask_expire_interval): Fixed bug related to cpr_xx (tnx - Francis J. Lacoste). - -Tue Aug 31 17:20:44 CEST 1999 Werner Koch - - * plaintext.c (do_hash): Hash CR,LF for a single CR. - (ask_for_detached_datafile): Changed arguments to be closer to - those of hash_datafiles and cleanup the code a bit. - * mainproc.c (proc_tree): Workaround for pgp5 textmode detached - signatures. Changed behavior of asking for data file to be the same - as with provided data files. - - * keylist.c (list_keyblock): Use UTF8 print functions. - -Mon Aug 30 20:38:33 CEST 1999 Werner Koch - - * import.c (chk_self_sigs): some s/log_error/log_info/ so that gpg - does not return an error if a key has some invalid packets. - - * helptext.c: Fixed some typos and changed the way the - translation works. The english text is now the keyword for gettext - and not anymore the keyword supplied to the function. Done after - some discussion with Walter who thinks this is much easier for the - translators. - - * misc.c (disable_core_dumps): Don't do it for DOSish systems. - - * signal.c (signal_name): Bounds check on signum. - -Wed Aug 4 10:34:18 CEST 1999 Werner Koch - - * pubring.asc: Updated. - - * pkclist.c (do_we_trust_pre,check_signatures_trust): Do not print - the warning about --always_trust when --quiet is used. - - * pkclist.c (fpr_info): New and called at several places. - - * parse-packet.c (dump_sig_subpkt): List revocation key contents. - -Mon Jul 26 09:34:46 CEST 1999 Werner Koch - - * pkclist.c (build_pk_list): Fixed typo in format string. - - * trustdb.c (create_shadow_dir): Don't translate the error string. - - * g10.c (main): Fixed spelling of user-id. - * getkey.c (find_by_name_pk,find_by_name_sk, - find_by_keyid,find_by_keyid_sk): Ditto and translate it. - * import.c (mark_non_selfsigned_uids_valid,delete_inv_parts): Ditto. - - -Mon Jul 26 01:01:39 CEST 1999 Michael Roth - - * g10.c, options.h: New options --no-literal and --set-filesize - - * encode.c (encode_simple, encode_crypt): Support for the options - --no-literal and --set-filesize. - - * sign.c (sign_file): ditto. - -Fri Jul 23 13:53:03 CEST 1999 Werner Koch - - - * ringedit.c (enum_keyblocks): Removed annoying error message in cases - when we have no keyring at all to enum. - - * getkey.c (classify_user_id): Rewrote to relax the recognition of - keyIDs and fingerprints (Michael). - - * mainproc.c (check_sig_and_print): Print status NO_PUBKEY. - (print_failed_pkenc): Print status NO_SECKEY. - - * import.c (mark_non_selfsigned_uids_valid): New. - * g10.c: New option --allow-non-selfsigned-uid. - - * pkclist.c (print_fpr): New. - (do_we_trust_pre): Print the fpr before asking whether to use the key - anyway. - (do_edit_ownertrust): Likewise. - -Thu Jul 22 20:03:03 CEST 1999 Werner Koch - - - * ringedit.c (enum_keyblocks): Removed annoying error message in cases - when we have no keyring at all to enum. - - * getkey.c (classify_user_id): Rewrote to relax the recognition of - keyIDs and fingerprints (Michael). - - * mainproc.c (check_sig_and_print): Print status NO_PUBKEY. - (print_failed_pkenc): Print status NO_SECKEY. - - * import.c (mark_non_selfsigned_uids_valid): New. - * g10.c: New option --allow-non-selfsigned-uid. - -Thu Jul 15 10:15:35 CEST 1999 Werner Koch - - * g10.c: New options --disable-{cipher,pubkey}-algo. - -Wed Jul 14 19:42:08 CEST 1999 Werner Koch - - * status.h (STATUS_IMPORTED): New. - * import.c (import): Print some status information (Holger Schurig). - - * g10.c (main): Make --no-greeting work again. Add a warning when - --force-mds is used. - -Tue Jul 13 17:39:25 CEST 1999 Werner Koch - - * pkclist.c (do_edit_ownertrust): Changed the way help works. - (build_pk_list): Implemented default recipient stuff. - * g10.c: New options --default-recipient[-self] - (main): Suppress greeting in most cases, entering a passphrase or - a missing value is not considered to be interactive use. - Merged --print-md and --print-mds; the latter is now obsolete. - Changed the way --gen-random works and documented it. - Changed the way --gen-prime works and add a man entry. - * g10.c (MAINTAINER_OPTIONS): Removed. - -Mon Jul 12 18:45:57 CEST 1999 Werner Koch - - * keyedit.c (keyedit_menu): Add arg sign_mode and changed callers - * g10.c (main): New command --lsign-key. - -Mon Jul 12 14:55:34 CEST 1999 Werner Koch - - * mainproc.c (kidlist_item): New. - (release_list): Release failed pk-enc-list. - (print_failed_pkenc): New - (proc_encrypted): Print info about failed PK enc. - - * openfile.c (make_outfile_name): s/error/info/ - - * passphrase.c (passphrase_to_dek): Return an empty passphrase when - in batch mode and don't make the warning message fatal - * seckey-cert.c (check_secret_key): Try only once when in batch mode. - - * g10.c (make_username): New. - -Thu Jul 8 16:21:27 CEST 1999 Werner Koch - - - * packet.h (PKT_ring_trust): New - * parse-packet.c (parse_trust): Store trust value - * build-packet (build_packet): Ignore ring trust packets. - * mainproc.c (add_ring_trust): New. - (list_node): Print "rtv" records. - * g10.c: New option --with-fingerprint. - - * trustdb.c (verify_own_keys): Don't insert if we are dry running - (check_trust): Ditto. - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch - - * Makefile.am: Support for libtool. - - * keygen.c (ask_expire_interval): Hack to allow for an expire date. - - * trustdb.c (do_update_trust_record,update_trust_record): Splitted. - (check_trust_record): New. - (check_trust,build_cert_tree): Check the dir record as needed. - (upd_pref_record): Removed. - (make_pref_record): New. - (propagate_validity): Stop as soon as we have enough validity. - - * tbdio.c (MAX_CACHE_ENTRIES_HARD): Increased the limit. - - -Fri Jul 2 11:45:54 CEST 1999 Werner Koch - - * g10.c (g10_exit): Dump random stats. - - * sig-check.c (check_key_signature,check_key_signature2): Enhanced - version and wrapper for old function. - (do_signature_check,signature_check): Ditto. - -Thu Jul 1 12:47:31 CEST 1999 Werner Koch - - - * keyedit.c (show_key_with_all_names): Print a notice for disabled keys. - (enable_disable_keys): Add functionality - * pkclist.c (edit_ownertrust): preserve disabled state. - (build_pk_list): Skip disabled keys. - * trustdb.c (upd_one_ownertrust): Ditto. - (build_cert_tree): Mask the ownertrust. - (trust_letter): Mask the value. - (do_check): Take disabled flag into account. - - * passphrase.c (passphrase_to_dek): Add a pubkey_algo arg and changed - all callers. - - * g10.c (utf8_strings): 2 new options. - - * trustdb.c (insert_trust_record_by_pk): New, replaces the next one. - (insert_trust_record): Now takes a keyblock as arg. Changed all - callers to use the appropritae function. - - * openfile.c (ask_outfile_name): New. - * plaintext.c (handle_plaintext): Ask for filename if there is - no valid syntax. Don't use fname varbatim but filter it. - -Tue Jun 29 21:44:25 CEST 1999 Werner Koch - - - * trustdb.h (TRUST_FLAG_DISABLED): New. - - * status.c (USE_CAPABILITIES): Capabilities support (Remi). - - * tdbio.c : Added new fields to the DIR record. - (tdbio_write_record): Fixed the update of the hash tables. - (tdbio_delete_record): Drop the record from the hash tables. - (drop_from_hashtbl): New. - - * status.c (cpr_get): Special online help mode. - * helptext.c ("keyedit.cmd"): Removed. - * keyedit.c (keyedit_menu): Use only help system. - (enable_disable_key): New bit doies not yet work. - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch - - - * dearmor.c (enarmor_file): Fixed comment string. - * tdbdump.c (export_ownertrust): Text fix. - * tbio.c (tdbio_invalid): Ditto. - - * parse-packet.c (parse_key): Made temp buffer larger. - - * Makefile.am (install-data-local): Add missing backslashes - -Tue Jun 15 12:21:08 CEST 1999 Werner Koch - - * g10.c (main): Made iterated+salted the default S2K method. - - * Makefile.am (install-data-local): Use DESTDIR. - - * passphrase.c (passphrase_to_dek): Emit missing-passphrase while in - batchmode. - - * parse-packet.c (parse_pubkeyenc): Fixed a SEGV. - -Mon Jun 14 21:18:54 CEST 1999 Michael Roth - - * g10.c: New options --openpgp, --no-tty, --emit-version, - --default-comment and --lock-multiple - -Thu Jun 10 14:18:23 CEST 1999 Werner Koch - - * free-packet.c (free_encrypted): Fixed EOF case (Remi). - (free_plaintext): Ditto. - - * helptext.c (keyedit.delsig.unknown): New (Remi). - * keyedit.c (print_and_check_one_sig): Add arg print_without_key and - changed all callers to make use of it (Remi): - -Tue Jun 8 13:36:25 CEST 1999 Werner Koch - - * keylist.c (print_key_data): New and called elsewhere. - * g10.c: New option --with-key-data - -Wed Jun 2 14:17:19 CEST 1999 Werner Koch - - * mainproc.c (proc_tree): Yet another bad hack to cope with - broken pgp2 created detached messages in textmode. - -Tue Jun 1 16:01:46 CEST 1999 Werner Koch - - * openfile.c (make_outfile_name): New. - * plaintext.c (handle_plaintext): Outputfile is now the inputfile - without the suffix. - * g10.c: New option --use-embedded-filename - -Mon May 31 19:41:10 CEST 1999 Werner Koch - - * g10.c (main): Fix for SHM init (Michael). - - * compress.c, encr-data.c, mdfilter.c, - plaintext.c, free-packet.c: Speed patches (Rmi). - -Thu May 27 09:40:55 CEST 1999 Werner Koch - - * status.c (cpr_get_answer_yes_no_quit): New. - * keyedit.c (menu_delsig): New. - (check_all_keysigs): Splitted. - (print_and_check_one_sig): New. - -Wed May 26 14:36:29 CEST 1999 Werner Koch - - * build-packet.c (build_sig_subpkt): Support large packets. - * parse-packet.c (enum_sig_subpkt): Replaces parse_sig_subpkt. - * mainproc.c (print_notation_data): Print all notation packets. - * g10.c (add_notation_data): Add a way to specify the critical flag. - (main): Add option --set-policy-url. - (check_policy_url): Basic checks. - * sign.c (mk_notation_and_policy): Replaces mk_notation. - - * parse-packet.c (can_handle_critical): Moved decision whether we can - handle critical subpacket to an extra function. - -Tue May 25 19:50:32 CEST 1999 Werner Koch - - * sign.c (sign_file): Always use compression algo 1 for signed - onyl file becuase we can be sure the the verifier supports other - algorithms. - - * build-packet.c (build_sig_subpkt): Support for notation data. - * sign.c (sign_file,clearsign_file,make_keysig_packet): Ditto. - (mk_notation): New. - * g10.c (add_notation_data): New and add option -N - * mainproc.c (print_notation_data): New. - (check_sig_and_print): Print any notation data of the signed text. - -Sun May 23 14:20:22 CEST 1999 Werner Koch - - * pkclist.c (check_signatures_trust): Print a warning and return - immediateley if opt.always_trust is true. - - * g10.c (main): Corrected handling of no-default-keyring - - * pkclist.c (algo_available): Disable Twofish until we have settled - how to do the MDC. - - * hkp.c: Disable everything for mingw32 - -Sat May 22 22:47:26 CEST 1999 Werner Koch - - * mainproc.c (check_sig_and_print): Add sig creation time to the - VALIDSIG status output. Add more info to the ERRSIG output. - * sig-check.c (signature_check): Add sig time after epoch to SIG_ID. - - * import.c (import_one): Merge duplicate user IDs. - (collapse_uids): New. - * kbnode.c (move_kbnode): New. - (remove_kbnode): New. - * keyedit.c (keyedit_menu): Call collapse_uids. - - * g10.c: new option --logger-fd. - - * import.c: s/log_*_f/log_*/ - -Thu May 20 14:04:08 CEST 1999 Werner Koch - - * misc.c (pull_in_libs): do the volatile only for gcc - - * sig-check (signature_check): Emit SIG_iD only for classes 0 and 1. - - * armor.c (armor_filter): Add detection of PGP2 created clearsigs. - (fake_packet): A tab is not a WS for pgp2 - handle this. - * textfilter.c (len_without_trailing_chars): New. - (copy_clearsig_text): Add pgp2mode arg. - * sign.c (clearsign_file): pass old_style to the above fnc. - - -Wed May 19 16:04:30 CEST 1999 Werner Koch - - * g10.c: New option --interactive. - - * mainproc.c (proc_plaintext): Add workaround for pgp2 bug - (do_check_sig): Ditto. - (proc_tree): Ditto. - * plaintext.c (do_hash): Ditto. - (hash_datafiles): Ditto, add an arg, changed all callers. - * mdfilter.c (md_filter): Add support for the alternate hash context. - -Mon May 17 21:54:43 CEST 1999 Werner Koch - - * parse-packet.c (parse_encrypted): Support for PKT_ENCRYPTED_MDC. - * build-packet.c (do_encrypted_mdc): Ditto. - * cipher.c (write_header): Add mdc hashing. - (cipher_filter): write out the hash. - * mainproc.c (do_proc_packets): Add PKT_ENCRYPTED_MDC. - * encr-data.c (decrypt_data): Add mdc hashing. - (mdc_decode_filter): New. - - * parse-packet.c (parse_sig_subpkt): Fixed stupid bug for subpkt - length calculation - (parse_signature): Fixed even more stupid bug. - -Sat May 8 19:28:08 CEST 1999 Werner Koch - - * build-packet.c (do_signature): Removed MDC hack. - * encode.c (encode_crypt_mdc): Removed. - * mainproc.c (do_check_sig): Removed MDC hack. - (check_sig_and_print): Ditto. - * parse-packet.c (parse_signature): Ditto. - * sig-check.c (mdc_kludge_check): Ditto. - * free-packte.c (copy_signature, free_seckey_enc): Ditto. - - * parse-packet.c (parse_signature,parse_key): Store data of - unknown algorithms with mpi_set_opaque inseatd of the old - faked data stuff. - (read_rest): Removed. - (read_rest2): Renamed to read_rest - * build-packet.c (write_fake_data): Use mpi_get_opaque. - * free-packet.c (cp_fake_data): Removed and cahnged all callers - to use mpi_copy. - (free_pubkey_enc,free_seckey_enc,release_public_key_parts, - release_secret_key_parts): Use mpi_free for opaque data. - -Thu May 6 14:18:17 CEST 1999 Werner Koch - - * trustdb.c (check_trust): Check for revoked subkeys. - * pkclist.c (do_we_trust): Handled revoked subkeys. - (do_we_trust_pre): Ditto. - (check_signatures_trust): Ditto. - - * build-packet.c (hash_public_key): Fix for ancient g10 keys. - - * mainproc.c (do_proc_packets): Return EOF if no data has been read. - * g10.c (main): Catch errors for default operation. - -Thu Apr 29 12:29:22 CEST 1999 Werner Koch - - * sign.c (sign_file): Fixed hashing in case of no subpackets. - (clearsign_file): Ditto. - (make_keysig_packet): Ditto. - -Wed Apr 28 13:03:03 CEST 1999 Werner Koch - - * keyedit.c (keyedit_menu): Add new command revkey. - * (menu_revkey): New. - - -Mon Apr 26 17:48:15 CEST 1999 Werner Koch - - * parse-packet.c (parse_signature): Add the MDC hack. - * build-packet.c (do_signature): Ditto. - * free-packet.c (free_seckey_enc,copy_signature,cmp_signatures): Ditto. - * mainproc.c (do_check_sig): Ditto. - * sig-check.c (mdc_kludge_check): New. - * encode.c (encrypt_mdc_file): New. - - * keyedit.c (check_all_keysigs): List revocations. - * (menu_revsig): New. - * sign (make_keysig_packet): Support for class 0x30. - -Sun Apr 18 20:48:15 CEST 1999 Werner Koch - - * pkclist.c (select_algo_from_prefs): Fixed the case that one key - has no preferences (Remi Guyomarch). - - keylist.c (list_keyblock): ulti_hack to propagate trust to all uids. - -Sun Apr 18 10:11:28 CEST 1999 Werner Koch - - * seckey-cert.c (do_check): Use real IV instead of a 0 one, so that - it works even if the length of the IV doesn't match the blocksize. - Removed the save_iv stuff. - (protect_secret_key): Likewise. Create the IV here. - * packet.h (PKT_secret_key): Increased size of IV field and add a - ivlen field. - * parse-packet.c (parse_key): Use the len protect.ivlen. - * build-packet.c (do_secret_key). Ditto. - - * getkey.c (key_byname): Close keyblocks. - - * Makefile.am (gpgm): Removed this - * g10.c: Merged gpg and gpgm - - * import.c (import): Utilize option quiet. - * tdbio.c (tdbio_set_dbname): Ditto. - * ringedit.c (add_keyblock_resource,keyring_copy): Ditto. - - * keyedit.c (sign_uids): Add some batch support. - - * g10.c (main): add call to tty_batchmode. - -Fri Apr 9 12:26:25 CEST 1999 Werner Koch - - * status.c (write_status_text): Some more status codes. - * passphrase_to_dek (passphrase_to_dek): add a status code. - * seckey_cert.c (check_secret_key): Likewise. - - * encr-data.c (decrypt_data): Reverse the last changes - * cipher.c (write_header): Ditto. - - * parse-packet.c (parse_key): Dropped kludge for ancient blowfish mode. - -Thu Apr 8 09:35:53 CEST 1999 Werner Koch - - * mainproc.c (proc_encrypted): Add a new status output - * passphrase.c (passphrase_to_dek): Ditto. - * status.h status.c: Add new status tokens. - -Wed Apr 7 20:51:39 CEST 1999 Werner Koch - - * encr-data.c (decrypt_data): Fixes for 128 bit blocksize - * cipher.c (write_header): Ditto. - * seckey-cert.c (do_check): Ditto. - (protect_secret_key). Ditto. - * misc.c (print_cipher_algo_note): Twofish is now a standard algo. - - * keygen.c (do_create): Fixed spelling (Gal Quri) - (ask_keysize): Only allow keysizes up to 4096 - - * ringedit.c (add_keyblock_resource): chmod newly created secrings. - - * import.c (delete_inv_parts): Fixed accidently deleted subkeys. - -Tue Apr 6 19:58:12 CEST 1999 Werner Koch - - * armor.c: Removed duped include (John Bley) - * mainproc.c: Ditto. - - * build-packet.c (hash_public_key): Fixed hashing of the header. - - * import.c (delete_inv_parts): Allow import of own non-exportable sigs. - -Sat Mar 20 13:59:47 CET 1999 Werner Koch - - * armor.c (fake_packet): Fix for not not-dash-escaped - -Sat Mar 20 11:44:21 CET 1999 Werner Koch - - * g10.c (main): Added command --recv-keys - * hkp.c (hkp_import): New. - -Wed Mar 17 13:09:03 CET 1999 Werner Koch - - * trustdb.c (check_trust): add new arg add_fnc and changed all callers. - (do_check): Ditto. - (verify_key): Ditto. - (propagate_validity): Use the new add_fnc arg. - (print_user_id): Add the FILE arg. - (propagate_ownertrust): New. - * pkclist.c (add_ownertrust_cb): New and changed the add_ownertrust - logic. - - * getkey.c (get_keyblock_bylid): New. - * trustdb.c (print_uid_from_keyblock): New. - (dump_tn_tree_with_colons): New. - (list_trust_path): Add colon print mode. - - * trustdb.c (insert_trust_record): Always use the primary key. - - * encode.c (encode_simple): Added text_mode filter (Rmi Guyomarch) - (encode_crypt): Ditto. - - * mainproc.c (proc_pubkey_enc): Added status ENC_TO. - * armor.c (armor_filter): Added status NODATA. - * passphrase.c (passphrase_to_dek): Always print NEED_PASSPHRASE - * seckey_cert.c (check_secret_key): Added BAD_PASS status. - - * g10.c (main): Set g10_opt_homedir. - -Sun Mar 14 19:34:36 CET 1999 Werner Koch - - * keygen.c (do_create): Changed wording of the note (Hugh Daniel) - -Thu Mar 11 16:39:46 CET 1999 Werner Koch - - * tdbdump.c: New - - * trustdb.c (walk_sigrecs,do_list_sigs,list_sigs, - list_records,list_trustdb,export_ownertrust,import_ownertrust): Moved - to tdbdump.c - (init_trustdb): renamed to setup_trustdb. Changed all callers. - (do_init_trustdb): renamed to init_trustdb(). - * trustdb.c (die_invalid_db): replaced by tdbio_invalid. - * tdbio.c (tdbio_invalid): New. - - * import.c (delete_inv_parts): Skip non exportable signatures. - * keyedit.c (sign_uid_mk_attrib): New. - (sign_uids): Add the local argument. - (keyedit_menu): New "lsign" command. - * trustdb.c (register_trusted_key): Removed this and all related stuff. - * g10.c (oTrustedKey): Removed option. - - * tdbio.h (dir.valcheck): New trustdb field. - * tdbio.c: Add support for this field - (tdbio_read_modify_stamp): New. - (tdbio_write_modify_stamp): New. - * trustdb.c (do_check): Check against this field. Removed cache update. - (verify_key): Add cache update. - (upd_uid_record): Some functional changes. - (upd_cert_record): Ditto - -Wed Mar 10 11:26:18 CET 1999 Werner Koch - - * keylist.c (list_keyblock): Fixed segv in uid. Print 'u' as - validity of sks. - -Mon Mar 8 20:47:17 CET 1999 Werner Koch - - * getkey.c (classify_user_id): Add new mode 12 (#). - - * seckey-cert.c (check_secret_key): replaced error by info. - - * trustdb.c (query_trust_info): Add another arg, changed all callers. - (check_trust): Ditto. - (do_check): Ditto. - (verify_key): Handle namehash. - * keylist.c (list_keyblock): print trust info for user ids. - - * sig-check.c (signature_check): Add sig-created to status output. - -Tue Mar 2 16:44:57 CET 1999 Werner Koch - - * textfilter.c (copy_clearsig_text): New. - (clearsign): Removed. - * sign.c (clearsign_file): does not use textfiler anymore. - - * keygen.c (ask_user_id): print a note about the used charset. - -Tue Mar 2 10:38:42 CET 1999 Werner Koch - - * sig-check.c (signature_check): sig-id now works for all algos. - - * armor.c (armor_filter): Fixed armor bypassing. - -Sun Feb 28 19:11:00 CET 1999 Werner Koch - - * keygen.c (ask_user_id): Don't change the case of email addresses. - (has_invalid_email_chars): Adjusted. - - * keylist.c (list_one): Really list serect keys (Remi Guyomarch) - - * keyedit.c (menu_select_uid): Add some braces to make egcs happy. - (menu_select_key): Ditto. - - * mainproc.c (do_proc_packets): List sym-enc packets (Remi Guyomarch) - -Fri Feb 26 17:55:41 CET 1999 Werner Koch - - * pkclist.c (build_pk_list): Return error if there are no recipients. - - * sig-check.c (signature_check): New signature id feature. - * armor.c (make_radic64_string): New. - - * mainproc.c (proc_pubkey_enc): early check for seckey availability. - - * pkclist.c (do_we_trust_pre): print user id before asking. - - * ringedit.c (add_keyblock_resource,get_keyblock_handle): Cleaner - handling of default resource. - - -Thu Feb 25 18:47:39 CET 1999 Werner Koch - - * pkclist.c (algo_available): New. - (select_algo_from_prefs): Check whether algo is available. - - * ringedit.c (keyring_copy): Take care of opt.dry_run. - (do_gdbm_store): Ditto. - * openfile.c (open_outfile). Ditto. - (copy_options_file): Ditto. - * trustdb.c (update_trustdb): Ditto. - (clear_trust_checked_flag): Ditto. - (update_trust_record): Ditto. - (insert_trust_record): Ditto. - -Wed Feb 24 11:07:27 CET 1999 Werner Koch - - * keylist.c (secret_key_list): Now really list the secret key. - - * trustdb.c (do_init_trustdb): New. Init is now deferred. - -Mon Feb 22 20:04:00 CET 1999 Werner Koch - - * getkey.c (lookup_sk): Return G10ERR_NO_SECKEY and not x_PUBKEY. - -Fri Feb 19 15:49:15 CET 1999 Werner Koch - - * pkclist.c (select_algo_from_prefs): retrieve LID if not there. - - * armor.c (fake_packet): Replaced ugly lineending handling. - - * g10.c (oNoEncryptTo): New. - * pkclist.c (build_pk_list): Implemented this option. - - * g10.c (main): Greeting is now printed to stderr and not to tty. - Use add_to_strlist() instead of direct coding. - - * import.c (import): Use iobuf_push_filter2. - - * mainproc.c (check_sig_and_print): Print all user ids - for good signatures. - * getkey.c (get_pubkeyblock): New. - - * import.c (chk_self_sigs): Fixed SEGV for unbounded class 0x18 keys. - (delete_inv_parts): Delete special marked packets. - -Tue Feb 16 14:10:02 CET 1999 Werner Koch - - * g10.c (main): New option --encrypt-to - - * pkclist.c (build_pk_list): Implemented encrypt-to. - - * parse-packet.c (parse_user_id): Removed the hack to work with - utf-8 strings. - - * g10.c (main): Install lockfile cleanup handler. - * tdbio.c (cleanup): Removed: this is now handled by dotlock. - -Sat Feb 13 14:13:04 CET 1999 Werner Koch - - * tdbio.c (tdbio_set_dbname): Init lockhandle for a new trustdb - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - * g10.c (main): check for development version now in configure - - * tdbio.c (tdbio_write_record): Add uid.validity - (tdbio_read_record) : Ditto. - (tdbio_dump_record) : Ditto. - - * keygen.c (keygen_add_std_prefs): Replaced Blowfish by Twofish, - removed MD5 and Tiger. - * pubkey-enc.c (get_it): Suppress warning about missing Blowfish - in preferences in certain cases. - - * ringedit.c (lock_rentry,unlock_rentry): New. - - * getkey.c (key_byname): Pass ret_kb down to lookup_xx. - - * armor.c (armor_filter): No output of of empty comment lines. - Add option --no-version to suppress the output of the version string. - - * getkey.c: Release the getkey context for auto context variables. - -Sun Jan 24 18:16:26 CET 1999 Werner Koch - - * getkey.c: Changed the internal design to allow simultaneous - lookup of multible user ids - (get_pubkey_bynames): New. - (get_seckey_bynames): New. - (get_seckey_next): New. - (get_seckey_end): New. - * keylist.c (list_one): Use the new functions. - - * keylist.c (list_keyblock): add a newline for normal listings. - - * g10.c (--recipient): New option name to replace --remote-user - - -Wed Jan 20 18:59:49 CET 1999 Werner Koch - - * textfilter.c: Mostly rewritten - * plaintext.c (handle_plaintext): Use now text_filter semantics. - -Tue Jan 19 19:34:58 CET 1999 Werner Koch - - * export.c (export_pubkeys_stream): New. - (do_export_stream): New. - * g10.c (aSendKeys): New command. - * hkp.c (hkp_export): New. - - * compress.c (do_uncompress): Hack for algo 1 and 1.1.3 - -Sun Jan 17 11:04:33 CET 1999 Werner Koch - - * textfilter.c (text_filter): Now uses iobuf_read_line(). - (read_line): Removed. - - * armor.c (trim_trailing_spaces): Removed and replaced - by trim_trailing_ws from libutil - -Sat Jan 16 12:03:27 CET 1999 Werner Koch - - * hkp.c (hkp_ask_import): Use only the short keyid - -Sat Jan 16 09:27:30 CET 1999 Werner Koch - - * import.c (import_key_stream): New - (import): New, moved most of import_keys here. - * g10.c: New option --keyserver - * mainproc.c (check_sig_and_print): Hook to import a pubkey. - - * pref.c pref.h : Removed - - * hkp.c hkp.h: New - -Wed Jan 13 14:10:15 CET 1999 Werner Koch - - * armor.c (radix64_read): Print an error if a bad armor was detected. - -Wed Jan 13 12:49:36 CET 1999 Werner Koch - - * armor.c (radix64_read): Now handles malformed armors produced - by some buggy MUAs. - -Tue Jan 12 11:17:18 CET 1999 Werner Koch - - * ringedit.c (find_keyblock_bysk): New. - - * skc_list.c (is_insecure): New. - (build_sk_list): usage check for insecure keys. - - * import.c (chk_self_sigs): Add handling for subkeys. - (delete_inv_parts): Skip unsigned subkeys - - * sig-check.c (do_check): Print info if the signature is older - than the key. - * keygen.c (generate_subkeypair): Fail on time warp. - * sign.c (do_sign): Ditto. - -Sun Jan 10 15:10:02 CET 1999 Werner Koch - - * armor.c (fake_packet): Fixed not-dash-escaped bug. - -Sat Jan 9 16:02:23 CET 1999 Werner Koch - - * sig-check.c (do_check): Output time diff on error - - * status.c (STATUS_VALIDSIG): New. - (is_status_enabled): New. - * mainproc.c (check_sig_and_print): Issue that status message. - - * plaintext.c (special_md_putc): Removed - - * armor.c (armor_filter): print error for truncated lines. - - * free-packet.c (free_encrypted): Revomed call to set_block_mode. - (free_plaintext): Ditto. - -Thu Jan 7 18:00:58 CET 1999 Werner Koch - - * pkclist.c (add_ownertrust): Fixed return value. - - * encr-data.c (decrypt_data): Disabled iobuf_set_limit and - iobuf_pop_filter stuff. - * compress.c (handle_compressed): Disabled iobuf_pop_filter. - - * packet.h (PKT_secret_key): Add is_primary flag. - * parse-packet.c (parse_key): Set this flag. - * passphrase.c (passphrase_to_dek): Kludge to print the primary - keyid - changed the API: keyid must now hold 2 keyids. - * getkey.c (get_primary_seckey): New. - * seckey-cert.c (do_check): pass primary keyid to passphrase query - - * tbdio.c (open_db): removed the atexit - (tdbio_set_dbname): and moved it to here. - - * armor.c: Rewrote large parts. - -Tue Dec 29 19:55:38 CET 1998 Werner Koch - - * revoke.c (gen_revoke): Removed compression. - - * pkclist.c (do_we_trust_pre): special check for revoked keys - - * trustdb.c (update_trust_record): Fixed revoke flag. - -Tue Dec 29 14:41:47 CET 1998 Werner Koch - - * misc.c (disable_core_dumps): Check for EINVAL (Atari) - - * getkey (merge_one_pk_and_selfsig): Fixed search of expiredate. - (merge_keys_and_selfsig): Ditto. - - * free-packet.c (cmp_public_keys): cmp expire only for v3 packets - (cmp_secret_keys): Ditto. - (cmp_public_secret_key): Ditto. - -Wed Dec 23 17:12:24 CET 1998 Werner Koch - - * armor.c (find_header): Reset not_dashed at every header - -Wed Dec 23 13:18:14 CET 1998 Werner Koch - - * pkclist.c (add_ownertrust): Refresh validity values. - - * trustdb.c (enum_cert_paths_print): New arg refresh. - - * ringedit.c: Fixed problems fix keyrings - * parse-packet.c (dbg_parse_packet): New debug functions. - - * getkey.c (getkey_disable_caches): New. - * import.c (import_keys): Disable caches. - -Thu Dec 17 18:31:15 CET 1998 Werner Koch - - * misc.c (trap_unaligned): Only for glibc 1 - - * sign.c (write_dash_escaped): Now escapes "From " lines - * g10.c: New option --escape-from-lines - - * trustdb.c (sort_tsl_list): New - (list_trust_path): Now prints sorted list. - (enum_cert_paths): Likewise. - (enum_cert_paths_print): New. - (print_paths): New printing format. - * pkclist.c (add_ownertrust): New arg quit. - (edit_ownertrust): New quit selection and does not query - the recipients ownertrust anymore. - (add_ownertrust): Print the ceritficate path. - - -Mon Dec 14 21:18:49 CET 1998 Werner Koch - - * parse-packet.c (parse_signature): Now checks for critical bit - (parse_sig_subpkt): Splitted. - (parse_one_sig_subpkt): New. - * sig-check.c (do_check): handle critical bit. - -Sun Dec 13 14:10:56 CET 1998 Werner Koch - - * pcklist.c (select_algo_from_prefs): Preferences should - now work (lost the != ? ) - -Thu Dec 10 20:15:36 CET 1998 Werner Koch - - * ringedit.c (gdbm_store): Fix for inserts - - * g10.c (main): New option --export-all - * export.c (export_pubkeys): New arg. - (do_export): Now may skip old keys. - - * status.c: Minor patches for Sun's cc - - * keygen.c (ask_algo): Disabled v3 ElGamal choice, rearranged - the numbers. Add a warning question when a sign+encrypt key - is selected. - - * g10.c (do_not_use_RSA): Removed. - * misc.c (print_pubkey_algo_note): New as replacement for the - do_not_use_RSA() and chnaged all callers. - (print_cipher_algo_note): New. - (print_hash_algo_note): New. - - * cipher.c (write_header): Add a call to print_cipher_algo_note. - * seckey-cert.c (protect_secret_key): Ditto - * sign.c (do_sign): Add a call to print_digest_algo_note. - - * getkey.c (get_long_user_id_string): New. - * mainproc.c (check_sig_and_print): Changed the format of the - status output. - - * encrypt.c (write_pubkey_enc_from_list): print used symmetric cipher. - - * pkclist.c (do_we_trust): Changed a message. - -Wed Dec 9 13:41:06 CET 1998 Werner Koch - - * misc.c (trap_unaligned) [ALPHA]: Only if UAC_SIGBUS is defined. - - * sign.c (write_dash_escaped): Add the forgotten patch by Brian Moore. - - * compress.c (do_uncompress): Fixed the inflating bug. - - -Tue Dec 8 13:15:16 CET 1998 Werner Koch - - * trustdb.c (upd_uid_record): Now uses the newest self-signature - (insert_trust_record): Now calls update with recheck set to true. - (register_trusted_key): New. - (verify_own_keys): Enhanced by list of trusted keys. - - * g10.c (main): Print a warning when a devel version is used. - (main): New option --trusted-key - - * import.c (merge_blocks): Fixed merging of new user ids and - added merging of subkeys. - (append_uid): Ditto. - (merge_keysig): New. - (append_key): New. - * getkey.c (merge_one_pk_and_selfsig): Get the expiration time - from the newest self-signature. - (merge_keys_and_selfsig): Ditto. - - * free-packet.c (cmp_secret_key): New. - - -Fri Nov 27 21:37:41 CET 1998 Werner Koch - - * g10.c: New option --lock-once - * tdbio.c (open_db): Add an atexit - (cleanup): New. - (tdbio_sync): Add locking. - (tdbio_end_transaction): Ditto. - (put_record_into_cache): Ditto. - * ringedit.c (keyring_copy): Ditto. - (cleanup): New. - (add_keyblock_resource): Add an atexit. - -Fri Nov 27 15:30:24 CET 1998 Werner Koch - - * armor.c (find_header): Another fix for clearsigs. - -Fri Nov 27 12:39:29 CET 1998 Werner Koch - - - * status.c (display_help): Removed. - * helptext.c: New and removed the N_() from all cpr_gets. - - -Fri Nov 20 16:54:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): New option --not-dash-escaped - * sign.c (write_dashed_escaped): Ditto. - * armor.c (find_header): Support for NotDashEscaped header. - - * getkey.c: print "disabled cache.." only if verbose is used. - -Thu Nov 19 07:17:31 1998 Werner Koch - - * parse-packet.c (dump_sig_subpkt): Fixed expire listing - * getkey.c (merge_keys_and_selfsig): Fixed expire calculation. - (merge_one_pk_and_selfsig): Ditto. - * keyedit.c (menu_expire). Ditto. - * keygen.c (keygen_add_key_expire): Ditto. - (ask_expire_interval): New and changed all local function to use - this instead. - (keygen_add_key_expire): Opaque should now be a public key; - changed all callers. - - * parse.packet.c (parse): use skip_rest to skip packets. - - * keyedit.c (keyedit_menu): New arg for cmdline cmds. - -Wed Nov 18 20:33:50 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (check_trustdb): Now rechecks all gived userids. - (collect_paths): Some fixes. - (upd_pref_records): Skips empty items, evaluate all items. - - * parse-packet.c (dump_sig_subpkt): Better listing of prefs. - (skip_packet): Now knows about marker packet - - * g10.c: removed cmd "--edit-sig". - - * pubring.asc: Updated. - -Sat Nov 14 14:01:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Changed syntax of --list-trust-path - * trustdb.c (list_trust_path): Replaced max_depth by - opt.max_cert_depth - -Fri Nov 13 07:39:58 1998 Werner Koch - - * trustdb.c (collect_paths): Removed a warning message. - (enum_trust_web): Removed. - (enum_cert_paths): New. - * pkclist.c (add_ownertrust): Changed to use enum_cert_paths. - (edit_ownertrust): Now list ceritficates on request. - (show_paths): New. - -Wed Nov 11 18:05:44 1998 Werner Koch - - * g10.c (main): New option --max-cert-depth - * tdbio.h: add new fields to ver and dir record. - * tdbio.c: read/write/dump of these fields. - (tdbio_db_matches_options): New. - * trustdb.c: replaced MAC_CERT_DEPTH by opt.max_cert_depth. - (do_check): cache validity and changed other functions - to reset the cached value. - - * keylist.c (list_one): Now lists the ownertrust. - * mainproc.c (list_node): Ditto. - -Tue Nov 10 10:08:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (g10_exit): Now looks at the new g10_errors_seen. - * mainproc.c (check_sig_and_print): Sets g10_errors_seen. - - * *.c : i18n many more strings. - - * ringedit.c (locate_keyblock_by_keyid): Add HAVE_LIBGDBM - (locate_keyblock_by_fpr): Ditto. - - * g10.c (main): removed unsused "int errors". - (main): Add new option --charset. - - * g10.c (main): special message for the unix newbie. - -Mon Nov 9 07:17:42 1998 Werner Koch - - * getkey.c (finish_lookup): Kludge to prefere algo 16. - - * trustdb.c (new_lid_table): Clear cached item. - - * status.c (cpr_get_utf8): New. - * pkclist.c (build_pk_list): Uses this. - -Sun Nov 8 17:20:39 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mainproc.c (check_sig_and_print): Why did I use strlen()-1 - in the printf? - This truncated the TZ. - -Sat Nov 7 15:57:28 1998 me,,, (wk@tobold) - - * getkey.c (lookup): Changes to support a read_next. - (get_pubkey): Fixed a memory leak. - - * keylist.c (list_one): Now lists all matching user IDs. - -Tue Nov 3 16:19:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (ask_user_id): Now converted to UTF-8 - - * g10.c (main): Kludge for pgp clearsigs and textmode. - -Fri Oct 30 16:40:39 1998 me,,, (wk@tobold) - - * signal.c (block_all_signals): New. - (unblock_all_signals): New - * tdbio.c (tdbio_end_transaction): Now blocks all signals. - - * trustdb.c (new_lid_table): Changed the representation of the - former local_lid_info stuff. - - * trustdb.c (update_trust_record): Reorganized the whole thing. - * sig-check.c (check_key_signature): Now handles class 0x28 - - -Wed Oct 28 18:56:33 1998 me,,, (wk@tobold) - - * export.c (do_export): Takes care of the exportable sig flag. - -Tue Oct 27 14:53:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (update_trust_record): New "fast" parameter. - -Sun Oct 25 19:32:05 1998 Werner Koch (wk@isil.d.shuttle.de) - - * openfile.c (copy_options_File): New. - * ringedit.c (add_keyblock_resource): Creates options file - * tdbio.c (tdbio_set_dbname): Ditto. - -Sat Oct 24 14:10:53 1998 brian moore - - * mainproc.c (proc_pubkey_enc): Don't release the DEK - (do_proc_packets): Ditto. - -Fri Oct 23 06:49:38 1998 me,,, (wk@tobold) - - * keyedit.c (keyedit_menu): Comments are now allowed - - * trustdb.c: Rewrote large parts. - - -Thu Oct 22 15:56:45 1998 Michael Roth (mroth@nessie.de) - - * encode.c: (encode_simple): Only the plain filename without - a given directory is stored in generated packets. - (encode_crypt): Ditto. - - * sign.c: (sign_file) Ditto. - - -Thu Oct 22 10:53:41 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (update_trust_record): Add new optional arg. - - * import.c (import_keys): Add statistics output - * trustdb.c (update_trustdb): Ditto. - (insert_trustdb): Ditto. - - * tdbio.c (tdbio_begin_transaction): New. - (tdbio_end_transaction): New. - (tdbio_cancel_transaction): New. - - * g10.c (main): New option --quit. - - * trustdb.c (check_hint_sig): No tests for user-id w/o sig. - This caused an assert while checking the sigs. - - * trustdb.c (upd_sig_record): Splitted into several functions. - - * import.c (import_keys): New arg "fast". - * g10.c (main): New command --fast-import. - -Wed Oct 21 18:19:36 1998 Michael Roth - - * ringedit.c (add_keyblock_resource): Directory is now created. - * tdbio.c (tdbio_set_dbname): New info message. - -Wed Oct 21 11:52:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (update_trustdb): released keyblock in loop. - - * keylist.c (list_block): New. - (list_all): Changed to use list_block. - - * trustdb.c: Completed support for GDBM - - * sign.c (only_old_style): Changed the way force_v3 is handled - (sign_file): Ditto. - (clearsign_file): Ditto. - - * keygen.c (has_invalid_email_chars): Splitted into mailbox and - host part. - - * keylist.c (list_one): Add a merge_keys_and_selfsig. - * mainproc.c (proc_tree): Ditto. - -Sun Oct 18 11:49:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sign.c (only_old_style): Add option force_v3_sigs - (sign_file): Fixed a bug in sig->version - (clearsign_file): Ditto. - - * parse-packet.c (dump_sig_subpkt): New - - * keyedit.c (menu_expire): New. - * free-packet.c (cmp_signatures): New - - -Sat Oct 17 10:22:39 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c: changed output line length from 72 to 64. - - * keyedit.c (fix_keyblock): New. - -Fri Oct 16 10:24:47 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c: Rewrote most. - * tdbio.c: Add cache and generalized hash tables. - - * options.h (ENABLE_COMMENT_PACKETS): New but undef'ed. - * encode.c, sign.c, keygen.c: Disabled comment packets. - * export.c (do_export): Comment packets are never exported, - except for those in the secret keyring. - - * g10.c (main): Removed option do-no-export-rsa; should be - be replaced by a secpial tool. - * export.c (do_export): Removed the code for the above option. - - * armor.c (find_header): Support for new only_keyblocks. - * import.c (import_keys): Only looks for keyblock armors. - - * packet.h: replaced valid_days by expiredate and changed all users. - * build-packet.c (do_public_key): calculates valid-days - (do_secret_key): Ditto. - * parse-packet.c (parse_key): expiredate is calucated from the - valid_period in v3 packets. - * keyid.c (do_fingerprint_md): calculates valid_dates. - - * keygen.c (add_key_expire): fixed key expiration time for v4 packets. - - * armor.c (find_header): A LF in the first 28 bytes - was skipped for non-armored data. - -Thu Oct 8 11:35:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (is_armored): Add test on old comment packets. - - * tdbio.c (tdbio_search_dir_bypk): fixed memory leak. - - * getkey.c: Changed the caching algorithms. - -Wed Oct 7 19:33:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * kbnodes.c (unused_nodes): New. - -Wed Oct 7 11:15:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keyedit.c (sign_uids): Fixed a problem with SK which could caused - a save of an unprotected key. - (menu_adduid): Ditto. - - * keyedit.c (keyedit_menu): Prefs are now correctly listed for - new user ids. - - * trustdb.c (update_trust_record): New. - (insert_trust_record): Now makes use of update_trust_record. - -Tue Oct 6 16:18:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (read_record): replaces most of the tdbio_read_records. - (write_record): Ditto. - -Sat Oct 3 11:01:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (ask_alogo): enable ElGamal enc-only only for addmode. - -Wed Sep 30 10:15:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * import.c (import_one): Fixed update of wrong keyblock. - -Tue Sep 29 08:32:08 1998 me,,, (wk@tobold) - - * mainproc.c (proc_plaintext): Display note for special filename. - * plaintext.c (handle_plaintext): Suppress output of special file. - -Mon Sep 28 12:57:12 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (verify_own_keys): Add warning if a key is not protected. - - * passphrase (hash_passphrase): Fixed iterated+salted mode and - setup for keysizes > hashsize. - - * g10.c (main): New options: --s2k-{cipher,digest,mode}. - -Fri Sep 25 09:34:23 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c: Chnaged some help texts. - -Tue Sep 22 19:34:39 1998 Werner Koch (wk@isil.d.shuttle.de) - - * passphrase.c (read_passphrase_from_fd): fixed bug for long - passphrases. - -Mon Sep 21 11:28:05 1998 Werner Koch (wk@(none)) - - * getkey.c (lookup): Add code to use the sub key if the primary one - does not match the usage. - - * armor.c (armor_filter): New error message: no valid data found. - (radix64_read): Changes to support multiple messages. - (i18n.h): New. - * mainproc.c (add_onepass_sig): bug fix. - -Mon Sep 21 08:03:16 1998 Werner Koch (wk@isil.d.shuttle.de) - - * pkclist.c (do_we_trust): Add keyid to most messages. - - * passphrase.c (read_passphrase_from_fd): New. - (have_static_passphrase): New - (get_passphrase_fd): Removed. - (set_passphrase_fd): Removed. - * g10.c (main): passphrase is now read here. - - * keyedit.c (keyedit_menu): "help" texts should now translate fine. - -Mon Sep 21 06:40:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * encode.c (encode_simple): Now disables compression - when --rfc1991 is used. - (encode_crypt): Ditto. - -Fri Sep 18 16:50:32 1998 Werner Koch (wk@isil.d.shuttle.de) - - * getkey.c (merge_key_and_selfsig): New. - -Fri Sep 18 10:20:11 1998 Werner Koch (wk@isil.d.shuttle.de) - - * pkclist.c (select_algo_from_prefs): Removed 3DES kludge. - - * seskey.c (make_session_key): Fixed SERIOUS bug introduced - by adding the weak key detection code. - - * sign.c (sign_file): Changed aremor header in certain cases. - -Tue Sep 15 17:52:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mainproc.c (check_sig_and_print): Replaced ascime by asctimestamp. - -Mon Sep 14 11:40:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seskey.c (make_session_key): Now detects weak keys. - - * trustdb (clear_trust_checked_flag): New. - - * plaintext.c (handle_plaintext): Does no anymore suppress CR from - cleartext signed messages. - -Sun Sep 13 12:54:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (insert_trust_record): Fixed a stupid bug in the free - liunked list loops. - -Sat Sep 12 15:49:16 1998 Werner Koch (wk@isil.d.shuttle.de) - - * status.c (remove_shmid): New. - (init_shm_comprocess): Now sets permission to the real uid. - -Wed Sep 9 11:15:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h (PKT_pubkey_enc): New flah throw_keyid, and add logic to - implement it. - * g10.c (main): New Option --throw-keyid - - * getkey.c (enum_secret_keys): Add new ar and changed all callers. - -Tue Sep 8 20:04:09 1998 Werner Koch (wk@isil.d.shuttle.de) - - * delkey.c (delete_key): Moved from keyedit.c. - -Mon Sep 7 16:37:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * build-packet.c (calc_length_header): New arg new_ctb to correctly - calculate the length of new style packets. - - * armor.c (is_armored): Checks for symkey_enc packets. - - * pkclist.c (select_algo_from_prefs): 3DEs substitute is now CAST5. - -Tue Aug 11 17:54:50 1998 Werner Koch (wk@isil.d.shuttle.de) - - * build-packet.c (do_secret_key): Fixed handling of old keys. - - * getkey.c (compare_name): Fixed exact and email matching - - * openfile.c (open_outfile): Changed arguments and all callers. - -Tue Aug 11 09:14:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * encode.c (encode_simple): Applied option set-filename and comment. - (encode_crypt): Ditto. - * sign.c (sign_file): Ditto. - * armor.c (armor_filter): Applied option comment. - - * encode.c (encode_crypt): Moved init_packet to the begin. - (encode_simple): add an init_packet(). - - * comment (write_comment): Now enforces a hash sign as the 1st byte. - - * import.c (import_one): Add explanation for "no user ids". - - * compress.c (do_uncompress): Applied Brian Warner's patch to support - zlib 1.1.3 etc. - - * trustdb.c (check_trust): Fixed a problem after inserting new keys. - - * getkey (lookup): do not return the primary key if usage is given - (lookup_sk): Ditto and take usage into account. - - * status.c (cpr_get_answer_is_yes): add display_help. - -Mon Aug 10 10:11:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * getkey.c (lookup_sk): Now always returns the primary if arg - primary is true. - (lookup): Likewise. - (get_pubkey_byname): Now returns the primary key - (get_seckey_byname): Ditto. - - -Mon Aug 10 08:34:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keyid.c (pubkey_letter): ELG_E is now a small g. - -Sat Aug 8 17:26:12 1998 Werner Koch (wk@isil.d.shuttle.de) - - * openfile (overwrite_filep): Changed semantics and all callers. - -Sat Aug 8 12:17:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * status.c (display_help): New. - -Thu Aug 6 16:30:41 1998 Werner Koch,mobil,,, (wk@tobold) - - * seskey.c (encode_session_key): Now uses get_random_bits(). - -Thu Aug 6 07:34:56 1998 Werner Koch,mobil,,, (wk@tobold) - - * ringedit.c (keyring_copy): No more backupfiles for - secret keyrings and add additional warning in case of - a failed secret keyring operation. - -Wed Aug 5 11:54:37 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (check_opts): Moved to main. Changed def_cipher_algo - semantics and chnaged all users. - - * pubkey-enc.c (get_sssion_key): New informational output - about preferences. - - * parse-packet.c (parse_symkeyenc): Fixed salted+iterated S2K - (parse_key): Ditto. - * build-packet.c (do_secret_key): Ditto. - (do_symkey_enc): Ditto. - -Tue Aug 4 08:59:10 1998 Werner Koch (wk@isil.d.shuttle.de) - - * getkey.c (enum_secret_keys): Now returns only primary keys. - - * getkey (lookup): Now sets the new namehash field. - - * parse-packet.c (parse_sig_subpkt2): New. - - * sign.c (sign_file): one-pass sigs are now emiited reverse. - Preference data is considered when selecting the compress algo. - -Wed Jul 29 12:53:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * free-packet.c (copy_signature): New. - - * keygen.c (generate_subkeypair): rewritten - * g10.c (aKeyadd): Removed option --add-key - -Mon Jul 27 10:37:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seckey-cert.c (do_check): Additional check on cipher blocksize. - (protect_secret_key): Ditto. - * encr-data.c: Support for other blocksizes. - * cipher.c (write_header): Ditto. - -Fri Jul 24 16:47:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * kbnode.c (insert_kbnode): Changed semantics and all callers. - * keyedit.c : More or less a complete rewrite - -Wed Jul 22 17:10:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * build-packet.c (write_sign_packet_header): New. - -Tue Jul 21 14:37:09 1998 Werner Koch (wk@isil.d.shuttle.de) - - * import.c (import_one): Now creates a trustdb record. - - * g10.c (main): New command --check-trustdb - -Mon Jul 20 11:15:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * genkey.c (generate_keypair): Default key is now DSA with - encryption only ElGamal subkey. - -Thu Jul 16 10:58:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keyid.c (keyid_from_fingerprint): New. - * getkey.c (get_pubkey_byfprint): New. - -Tue Jul 14 18:09:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keyid.c (fingerprint_from_pk): Add argument and changed all callers. - (fingerprint_from_sk): Ditto. - -Tue Jul 14 10:10:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * plaintext.c (handle_plaintext): Now returns create error if - the file could not be created or the user responded not to overwrite - the file. - * mainproc.c (proc_plaintext): Tries again if the file could not - be created to check the signature without output. - - * misc.c (disable_core_dumps): New. - * g10.c (main): disable coredumps for gpg - - * g10.c (MAINTAINER_OPTIONS): New to disable some options - -Mon Jul 13 16:47:54 1998 Werner Koch (wk@isil.d.shuttle.de) - - * plaintext.c (hash_datafiles): New arg for better support of - detached sigs. Changed all callers. - * mainproc.c (proc_signature_packets): Ditto. - - * g10.c (main): New option "compress-sigs" - * sig.c (sign_file): detached signatures are not anymore compressed - unless the option --compress-sigs is used. - -Thu Jul 9 19:54:54 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c: Fixes to allow zero length cleartext signatures - -Thu Jul 9 14:52:47 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (build_list): Now drops setuid. - (main): Changed the way keyrings and algorithms are registered . - -Wed Jul 8 14:17:30 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h (PKT_public_key): Add field keyid. - * parse-packet.c (parse_key): Reset the above field. - * keyid.c (keyid_from_pk): Use above field as cache. - - * tdbio.c, tdbio.h: New - * trustdb.c: Moved some functions to tdbio.c. - (print_keyid): New. - - * pkclist.c (check_signatures_trust): New. - -Wed Jul 8 10:45:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * plaintext.c (special_md_putc): New. - (handle_plaintext): add clearsig argument - * mainproc.c (proc_plaintext): detection of clearsig - * sign.c (write_dased_escaped): Changed clearsig format - -Tue Jul 7 18:56:19 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (find_header): Now makes sure that there is only one - empty line for clearsigs, as this is what OP now says. - -Mon Jul 6 13:09:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): New option default-secret-key - * getkey.c (get_seckey_byname): support for this option. - -Mon Jul 6 09:03:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * getkey.c (add_keyring): Keyrings are now added to end of the - list of keyrings. The first added keyringwill be created. - (add_secret_keyring): Likewise. - - * ringedit.c (add_keyblock_resource): Files are created here. - - * g10.c (aNOP): Removed - - * getkey.c (lookup): Add checking of usage for name lookups - * packet.h (pubkey_usage): Add a field which may be used to store - usage capabilities. - * pkclist.c (build_pk_list): getkey now called with usage arg. - * skclist.c (build_sk_list): Ditto. - - * sign.c (clearsign_file): Fixed "Hash:" headers - -Sat Jul 4 13:33:31 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (list_ownertrust): New. - * g10.c (aListOwnerTrust): New. - - * g10.c (def_pubkey_algo): Removed. - - * trustdb.c (verify_private_data): Removed and also the call to it. - (sign_private_data): Removed. - -Fri Jul 3 13:26:10 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (aEditKey): was aEditSig. Changed usage msg. - - * keyedit.c: Done some i18n stuff. - - * g10.c (do_not_use_RSA): New. - * sign.c (do_sign): Add call to above function. - * encode.c (write_pubkey_enc_from_list): Ditto. - -Thu Jul 2 21:01:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c: Now is able sto store data of unknown - algorithms. - * free-packet.c: Support for this. - * build-packet.c: Can write data of packet with unknown algos. - -Thu Jul 2 11:46:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c (parse): fixed 4 byte length header - -Wed Jul 1 12:36:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h (new_ctb): New field for some packets - * build-packet.c (build_packet): Support for new_ctb - * parse-packet.c (parse): Ditto. - -Mon Jun 29 12:54:45 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h: changed all "_cert" to "_key", "subcert" to "subkey". - - * free-packet.c (free_packet): Removed memory leak for subkeys. - -Sun Jun 28 18:32:27 1998 Werner Koch (wk@isil.d.shuttle.de) - - * import.c (import_keys): Renamed from import_pubkeys. - (import_secret_one): New. - - * g10.c (aExportSecret): New. - - * export.c (export_seckeys): New. - - * parse-packet.c (parse_certificate): Cleaned up. - (parse_packet): Trust packets are now considered as unknown. - (parse_pubkey_warning): New. - -Fri Jun 26 10:37:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (has_invalid_email_chars): New. - -Wed Jun 24 16:40:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (armor_filter): Now creates valid onepass_sig packets - with all detected hash algorithms. - * mainproc.c (proc_plaintext): Now uses the hash algos as specified - in the onepass_sig packets (if there are any) - -Mon Jun 22 11:54:08 1998 Werner Koch (wk@isil.d.shuttle.de) - - * plaintext.c (handle_plaintext): add arg to disable outout - * mainproc.c (proc_plaintext): disable output when in sigs_only mode. - -Thu Jun 18 13:17:27 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c: Removed all rsa packet stuff, chnaged defaults - for key generation. - -Sun Jun 14 21:28:31 1998 Werner Koch (wk@isil.d.shuttle.de) - - * misc.c (checksum_u16): Fixed a stupid bug which caused a - wrong checksum calculation for the secret key protection and - add a backward compatibility option. - * g10.c (main): Add option --emulate-checksum-bug. - -Thu Jun 11 13:26:44 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h: Major changes to the structure of public key material - which is now stored in an array and not anaymore in a union of - algorithm specific structures. These is needed to make the system - more extendable and makes a lot of stuff much simpler. Changed - all over the system. - - * dsa.c, rsa.c, elg.c: Removed. - -Wed Jun 10 07:22:02 1998 Werner Koch,mobil,,, (wk@tobold) - - * g10.c ("load-extension"): New option. - -Mon Jun 8 22:23:37 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seckey-cert.c (do_check): Removed cipher constants - (protect_secret_key): Ditto. - -Fri May 29 10:00:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (query_trust_info): New. - * keylist.c (list_one): Add output of trust info - * mainproc (list_node): ditto. - * g10.c (main): full trustdb init if -with-colons and any of the - key list modes. - -Thu May 28 10:34:42 1998 Werner Koch (wk@isil.d.shuttle.de) - - * status.c (STATUS_RSA_OR_IDEA): New. - * sig-check.c (check_signature): Output special status message. - * pubkey-enc.c (get_session_key): Ditto. - - * mainproc.c (check_sig_and_print): Changed format of output. - * passpharse.c (passphrase_to_dek): Likewise. - -Wed May 27 13:46:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (aListSecretKeys): New option --list-secret-keys - * keylist.c (std_key_list): Renamed to public_key_list. - (secret_key_list): New - (list_one, list_all): Add support for secret keys. - * getkey.c (get_secret_keyring): New. - * mainproc.c (list_node): Add option --with-colons for secret keys - - * sig-check.c (check_key_signature): detection of selfsigs - * mainproc.c (list_node): fixed listing. - - * g10.c (aListSecretKeys): New option --always-trust - * pkclist.c (do_we_trust): Override per option added - - * status.c (write_status_text): Add a prefix to every output line. - -Wed May 27 07:49:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10 (--compress-keys): New. - * options.h (compress_keys): New. - * export.c (export_pubkeys): Only compresses with the new option. - -Tue May 26 11:24:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * passphrase.c (get_last_passphrase): New - (set_next_passphrase): New. - (passphrase_to_dek): add support for the above functions. - * keyedit.c (make_keysig_packet): Add sigclass 0x18, - changed all callers due to a new argument. - * keygen.c (write_keybinding): New - (generate_subkeypair): Add functionality - (ask_algo, ask_keysize, ask_valid_days): Broke out of generate_keypair - (ask_user_id, ask_passphrase): Ditto. - -Thu May 21 11:26:13 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c,gpgd.c (main): Does now return an int, so that egcs does - not complain. - - * armor.c (fake_packet): Removed erro message and add a noticed - that this part should be fixed. - - * sign.c (sign_file): Compression now comes in front of encryption. - * encode.c (encode_simple): Ditto. - (encode_crypt): Ditto. - -Tue May 19 16:18:19 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (fake_packet): Changed assertion to log_error - -Sat May 16 16:02:06 1998 Werner Koch (wk@isil.d.shuttle.de) - - * build-packet.c (build_packet): Add SUBKEY packets. - -Fri May 15 17:57:23 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sign.c (hash_for): New and used in all places here. - * main.h (DEFAULT_): new macros. - * g10.c (opt.def_digest_algo): Now set to 0 - - * compress.c (init_compress): Add support for algo 1 - * options.h (def_compress_algo): New - * g10.c (main): New option --compress-algo - -Fri May 15 13:23:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (print_mds): New feature to print only one hash, - chnaged formatting. - -Thu May 14 15:36:24 1998 Werner Koch (wk@isil.d.shuttle.de) - - * misc.c (trap_unaligned) [__alpha__]: New - * g10.c (trap_unaligned): Add call to this to track down SIGBUS - on Alphas (to avoid the slow emulation code). - -Wed May 13 11:48:27 1998 Werner Koch (wk@isil.d.shuttle.de) - - * build-packet.c (do_signature): Support for v4 pakets. - * keyedit.c (make_keysig_packet): Ditto. - * build-packet.c (build_sig_subpkt_from_sig): New. - (build_sig_subpkt): New. - - * elg.c (g10_elg_sign): removed keyid_from_skc. - * dsa.c (g10_dsa_sign): Ditto. - * rsa.c (g10_rsa_sign): Ditto. - * keyedit.c (make_keysig_packet): Add call to keyid_from_skc - - * sign.c (clearsign_file): Support for v4 signatures. - (sign_file): Ditto. - -Wed May 6 09:31:24 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c (do_parse): add support for 5 byte length leader. - (parse_subpkt): Ditto. - * build-packet.c (write_new_header): Ditto. - - * packet.h (SIGSUBPKT_): New constants. - * parse-packet.c (parse_sig_subpkt): Changed name, made global, - and arg to return packet length, chnaged all callers - - -Tue May 5 22:11:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (gen_dsa): New. - * build_packet.c (do_secret_cert): Support for DSA - -Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * compress.c: doubled buffer sizes - * parse-packet.c (do_plaintext): now uses iobuf_read/write. - -Mon May 4 09:35:53 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seskey.c (encode_md_value): Add optional argument hash_algo, - changed all callers. - - * passphrase.c (make_dek_from_passphrase): Removed - * (get_passhrase_hash): Changed name to passphrase_to_dek, add arg, - changed all callers. - - * all: Introduced the new ELG identifier and added support for the - encryption only one (which is okay to use by GNUPG for signatures). - -Sun May 3 17:50:26 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h (PKT_OLD_COMMENT): New name for type 16. - * parse-packet.c (parse_comment): Now uses type 61 - -Fri May 1 12:44:39 1998 Werner Koch,mobil,,, (wk@tobold) - - * packet.h (count): Chnaged s2k count from byte to u32. - * seckey-cert.c (do_check): Changed s2k algo 3 to 4, changed - reading of count. - * build-packet.c (do_secret_cert): ditto. - * parse-packet.c (parse_certificate): ditto. - - * parse-packet.c (parse_symkeyenc): New. - * build-packet.c (do_symkey_enc): New. - -Thu Apr 30 16:33:34 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sign.c (clearsign_file): Fixed "Hash: " armor line. - -Tue Apr 28 14:27:42 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c (parse_subpkt): Some new types. - -Mon Apr 27 12:53:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Add option --skip-verify. - * mainproc.c (check_sig_and_print): Ditto. - - * g10.c (print_mds): Add output for Tiger. - - * sign.c (sign_file): Now uses partial length headers if used - in canonical textmode (kludge to fix a bug). - - * parse-packet.c (parse_certificate): Changed BLOWFISH id. - * pubkey-enc.c (get_session_key): Ditto. - * seskey.c (make_session_key): Ditto. - * seckey-cert.c (protect_secret_key,do_check): Add BLOWFISH160. - -Fri Apr 24 17:38:48 1998 Werner Koch,mobil,,, (wk@tobold) - - * sig-check.c (check_key_signature): Add sig-class 0x14..0x17 - * keyedit.c (sign-key): Some changes to start with support of - the above new sig-classes. - -Wed Apr 22 09:01:57 1998 Werner Koch,mobil,,, (wk@tobold) - - * getkey.c (compare_name): add email matching - -Tue Apr 21 16:17:12 1998 Werner Koch,mobil,,, (wk@tobold) - - * armor.c (armor_filter): fixed missing last LF before CSUM. - -Thu Apr 9 11:35:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seckey-cert.c (do_check): New; combines all the check functions - into one. - - * sign.c: removed all key management functions - * keyedit.c: New. - -Thu Apr 9 09:49:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * import.c (chk_self_sigs): Changed an error message. - -Wed Apr 8 16:19:39 1998 Werner Koch (wk@isil.d.shuttle.de) - - * packet.h: packet structs now uses structs from the pubkey, - removed all copy operations from packet to pubkey structs. - -Wed Apr 8 13:40:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (verify_own_certs): Fixed "public key not found". - - * getkey.c (key_byname): New, combines public and secret key search. - - * pkclist.c (build_pkc_list): Add new arg usage, changed all callers. - * skclist.c (build_skc_list): Likewise. - - * ringedit.c (find_keyblock, keyring_search2): Removed. - -Wed Apr 8 09:47:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sig-check.c (do_check): Applied small fix from Ulf Mller. - -Tue Apr 7 19:28:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c, encr-data.c, seckey-cert.c: Now uses cipher_xxxx - functions instead of blowfish_xxx or cast_xxx - -Tue Apr 7 11:04:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am (g10maint.o): Changed the way it is created. - -Mon Apr 6 11:17:08 1998 Werner Koch (wk@isil.d.shuttle.de) - - * misc.c: New. - * keygen.c (checksum,checksum_u16,checksum_mpi): Moved to misc.c - * seckey-cert.c: Kludge for wrong ELG checksum implementation. - -Sat Apr 4 20:07:01 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.c (cipher_filter): Support for CAST5 - * encr-data.c (decode_filter): Ditto. - (decrypt_data): Ditto. - * seskey.c (make_session_key): Ditto. - * seckey-cert.c (check_elg, check_dsa): Ditto, - (protect_secret_key): Ditto. - * pubkey-enc.c (get_session_key): Ditto. - * passphrase.c (hash_passphrase): Ditto. - -Thu Apr 2 20:22:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * gpgd.c: New - -Thu Apr 2 10:38:16 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (generate_keypair): Add valid_days stuff. - * trustdb.c (check_trust): Add check for valid_days. - -Wed Apr 1 16:15:58 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (generate_keypair): Addional question whether the - selected large keysize is really needed. - -Wed Apr 1 15:56:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * seckey-cert.c (protect_secret_key): merged protect_xxx to here. - -Wed Apr 1 10:34:46 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am (g10maint.c): Changed creation rule, so that it works - on FreeBSD (missing CFLAGS). - - * parse-packet.c (parse_subkey): Removed. - -Thu Mar 19 15:22:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ringedit.c (keyring_enum): Fixed problem with reading too - many packets. Add support to read secret keyrings. - - * getkey.c (scan_keyring): Removed - (lookup): New to replace scan_keyring. - (scan_secret_keyring): Removed. - (lookup_skc): New. - -Wed Mar 18 11:47:34 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ringedit.c (enum_keyblocks): New read mode 11. - - * keyid.c (elg_fingerprint_md): New and changed all other functions - to call this if the packet version is 4 or above. - -Tue Mar 17 20:46:16 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c (parse_certificate): Add listing support for subkeys. - -Tue Mar 17 20:32:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (is_armored): Allow marker packet. - -Thu Mar 12 13:36:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (check_trust): Checks timestamp of pubkey. - * sig-check. (do_check): Compares timestamps. - -Tue Mar 10 17:01:56 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Add call to init_signals. - * signal.c: New. - -Mon Mar 9 12:43:42 1998 Werner Koch (wk@isil.d.shuttle.de) - - * dsa.c: New - * packet.h, free-packet.c, parse-packet.c : Add support for DSA - * sig-check.c, getkey.c, keyid.c, ringedit.c: Ditto. - * seckey-cert.c: Ditto. - - * packet.h : Moved .digest_algo of signature packets to outer - structure. Changed all references - -Sun Mar 8 13:06:42 1998 Werner Koch (wk@isil.d.shuttle.de) - - * openfile.c : Support for stdout filename "-". - - * mainproc.c (check_sig_and_print): Enhanced status output: - * status.c (write_status_text): New. - -Fri Mar 6 16:10:54 1998 Werner Koch (wk@isil.d.shuttle.de) - - * kbnode.c (clone_kbnode): Fixed private_flag. - - * mainproc.c (list_node): Output of string "Revoked" as user-id. - -Fri Mar 6 14:26:39 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Add userids to "-kv" and cleaned up this stuff. - -Fri Mar 6 12:45:58 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Changed semantics of the list-... commands - and added a new one. Removed option "-d" - - * decrypt.c: New. - - * trustdb.c (init_trustdb): Autocreate directory only if it ends - in "/.gnupg". - -Thu Mar 5 12:12:11 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mainproc.c (do_proc_packets): New. Common part of proc_packet. - (proc_signature_packets): special version to handle signature data. - * verify.c: New. - * g10.c (aVerify): New. - * plaintext.c (hash_datafiles): New. - * compress.c (handle_compressed): Add callback arg, changed caller. - -Thu Mar 5 10:20:06 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c: Is nom the common source for gpg and gpgm - * g10maint.c: Removed - * Makefile.am: Add rule to build g10maint.c - -Thu Mar 5 08:43:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Changed the way clear text sigs are faked. - -Wed Mar 4 19:47:37 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10maint.c (aMuttKeyList): New - * keylist.c: New. - -Wed Mar 4 17:20:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * getkey.c (get_pubkey_byname): Kludge to allow 0x prefix. - -Tue Mar 3 13:46:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10maint.c (main): New option --gen-random. - -Tue Mar 3 09:50:08 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (aDeleteSecretKey): New. - (aEditSig): Add option "--edit-key" as synonym for "--edit-sig". - (aDeleteSecretKey): New. - * getkey.c (seckey_available): New. - * sign.c (delete_key): Enhanced to delete secret keys, changed all - callers. - -Mon Mar 2 21:23:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * pkc_list.c (build_pkc_list): Add interactive input of user ID. - -Mon Mar 2 20:54:05 1998 Werner Koch (wk@isil.d.shuttle.de) - - * pkclist.c (do_we_trust_pre): New. - (add_ownertrust): Add message. - * trustdb.c (enum_trust_web): Quick fix. - -Mon Mar 2 13:50:53 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): New action aDeleteKey - * sign.c (delete_key): New. - -Sun Mar 1 16:38:58 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (do_check): No returns TRUST_UNDEFINED instead of - eof error. - -Fri Feb 27 18:14:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (find_header): Removed trailing CR on headers. - -Fri Feb 27 18:02:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ringedit.c (keyring_search) [MINGW32]: Open and close file here - because rename does not work on open files. Chnaged callers. - -Fri Feb 27 16:43:11 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sig-check.c (do_check): Add an md_enable. - * mainproc.c (do_check_sig): Use md_open in case of detached sig - (proc_tree): Take detached sigs into account. - -Fri Feb 27 15:22:46 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): Make use of GNUPGHOME envvar. - * g10main.c (main): Ditto. - -Wed Feb 25 11:40:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * plaintext.c (ask_for_detached_datafile): add opt.verbose to - info output. - - * openfile.c (open_sigfile): Try also name ending in ".asc" - -Wed Feb 25 08:41:00 1998 Werner Koch (wk@isil.d.shuttle.de) - - * keygen.c (generate_keypair): Fixed memory overflow. - -Tue Feb 24 15:51:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c (parse_certificate): Support for S2K. - * build-packet.c (do_secret_cert): Ditto. - * keygen.c (gen_elg): Ditto. - * seckey-cert.c (check_elg): Ditto - (protect_elg): Ditto. - * sign.c (chnage_passphrase): Ditto. - * passphrase.c (get_passphrase_hash): Support for a salt and - changed all callers. - (make_dek_from_passphrase): Ditto. - -Tue Feb 24 12:30:56 1998 Werner Koch (wk@isil.d.shuttle.de) - - * build-packet.c (hash_public_cert): Disabled debug output. - -Fri Feb 20 17:22:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (init_trustdb) [MINGW32]: Removed 2nd mkdir arg. - (keyring_copy) [MINGW32]: Add a remove prior to the renames. - -Wed Feb 18 18:39:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am (OMIT_DEPENDENCIES): New. - - * rsa.c: Replaced log_bug by BUG. - -Wed Feb 18 13:35:58 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mainproc.c (do_check_sig): Now uses hash_public_cert. - * parse-packet.c (parse_certificate): Removed hashing. - * packet.h (public_cert): Removed hash variable. - * free-packet.c (copy_public_cert, free_public_cert): Likewise. - - * sig-check.c (check_key_signatures): Changed semantics. - -Wed Feb 18 12:11:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * trustdb.c (do_check): Add handling for revocation certificates. - (build_sigrecs): Ditto. - (check_sigs): Ditto. - -Wed Feb 18 09:31:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (armor_filter): Add afx->hdrlines. - * revoke.c (gen_revoke): Add comment line. - * dearmor.c (enarmor_file): Ditto. - - * sig-check.c (check_key_signature): Add handling for class 0x20. - * mainproc.c : Ditto. - -Tue Feb 17 21:24:17 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c : Add header lines "...ARMORED FILE .." - * dearmor.c (enarmor_file): New. - * g10maint.c (main): New option "--enarmor" - -Tue Feb 17 19:03:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mainproc.c : Changed a lot, because the packets are now stored - a simple linlked list and not anymore in a complicatd tree structure. - -Tue Feb 17 10:14:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * free_packet.c (cmp_public_certs): New. - (cmp_user_ids): New. - - * kbnode.c (clone_kbnode): New. - (release_kbnode): Add clone support. - - * ringedit.c (find_keyblock_bypkc): New. - - * sign.c (remove_keysigs): Self signatures are now skipped, - changed arguments and all callers. - - * import.c : Add functionality. - -Tue Feb 17 09:31:40 1998 Werner Koch (wk@isil.d.shuttle.de) - - * options.h (homedir): New option. - * g10.c, g10maint.c, getkey.c, keygen.c, trustdb.c (opt.homedir): New. - - * trustdb.c (init_trustdb): mkdir for hoem directory - (sign_private_data): Renamed "sig" to "g10.sig" - -Mon Feb 16 20:02:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * kbnode.c (commit_kbnode): New. - (delete_kbnode): removed unused first arg. Changed all Callers. - - * ringedit.c (keyblock_resource_name): New. - (get_keyblock_handle): NULL for filename returns default resource. - -Mon Feb 16 19:38:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * sig-check.s (check_key_signature): Now uses the supplied - public key to check the signature and not any more the one - from the getkey.c - (do_check): New. - (check_signature): Most work moved to do_check. - -Mon Feb 16 14:48:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (find_header): Fixed another bug. - -Mon Feb 16 12:18:34 1998 Werner Koch (wk@isil.d.shuttle.de) - - * getkey.c (scan_keyring): Add handling of compressed keyrings. - -Mon Feb 16 10:44:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c, g10maint.c (strusage): Rewrote. - (build_list): New - -Mon Feb 16 08:58:41 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (use_armor): New. - -Sat Feb 14 14:30:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mainproc.c (proc_tree): Sigclass fix. - -Sat Feb 14 14:16:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * armor.c (armor_filter): Changed version and comment string. - * encode.c, sign.c, keygen.c: Changed all comment packet strings. - -Sat Feb 14 12:39:24 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (aGenRevoke): New command. - * revoke.c: New. - * sign.c (make_keysig_packet): Add support for sigclass 0x20. - -Fri Feb 13 20:18:14 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ringedit.c (enum_keyblocks, keyring_enum): New. - -Fri Feb 13 19:33:40 1998 Werner Koch (wk@isil.d.shuttle.de) - - * export.c: Add functionality. - - * keygen.c (generate_keypair): Moved the leading comment behind the - key packet. - * kbnode.c (walk_kbnode): Fixed. - - * g10.c (main): listing armored keys now work. - -Fri Feb 13 16:17:43 1998 Werner Koch (wk@isil.d.shuttle.de) - - * parse-packet.c (parse_publickey, parse_signature): Fixed calls - to mpi_read used for ELG b. - -Fri Feb 13 15:13:23 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10.c (main): changed formatting of help output. - -Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo) - - * pubkey-enc.c (get_session_key): rewritten - - - Copyright 1998,1999,2000,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. diff --git a/g10/Makefile.am b/g10/Makefile.am deleted file mode 100644 index d84707af8..000000000 --- a/g10/Makefile.am +++ /dev/null @@ -1,123 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - -INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl -EXTRA_DIST = options.skel -# it seems that we can't use this with automake 1.5 -#OMIT_DEPENDENCIES = zlib.h zconf.h -LDFLAGS = @LDFLAGS@ -needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a - -#noinst_PROGRAMS = gpgd -bin_PROGRAMS = gpg gpgv - -common_source = \ - global.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 \ - 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 \ - signal.c - -gpg_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 \ - exec.c exec.h - - - -gpgv_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) @ZLIBS@ @INTLLIBS@ -# gpg gets LIBOBJS to add in mkdtemp if the platform doesn't have it -gpg_LDADD = @LIBOBJS@ $(LDADD) @EGDLIBS@ - -$(PROGRAMS): $(needed_libs) - -install-data-local: - $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) - $(INSTALL_DATA) $(srcdir)/options.skel \ - $(DESTDIR)$(pkgdatadir)/options.skel - @set -e;\ - if test -f $(DESTDIR)$(bindir)/gpgm ; then \ - echo "removing obsolete gpgm binary" ; \ - rm $(DESTDIR)$(bindir)/gpgm ; \ - fi diff --git a/g10/armor.c b/g10/armor.c deleted file mode 100644 index 9c7858fe6..000000000 --- a/g10/armor.c +++ /dev/null @@ -1,1322 +0,0 @@ -/* armor.c - Armor flter - * 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 -#include -#include -#include -#include -#include -#include - -#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" -#include "i18n.h" - -#ifdef HAVE_DOSISH_SYSTEM - #define LF "\r\n" -#else - #define LF "\n" -#endif - -#define MAX_LINELEN 20000 - -#define CRCINIT 0xB704CE -#define CRCPOLY 0X864CFB -#define CRCUPDATE(a,c) do { \ - a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \ - a &= 0x00ffffff; \ - } while(0) -static u32 crc_table[256]; -static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; -static byte asctobin[256]; /* runtime initialized */ -static int is_initialized; - - -typedef enum { - fhdrHASArmor = 0, - fhdrNOArmor, - fhdrINIT, - fhdrINITCont, - fhdrINITSkip, - fhdrCHECKBegin, - fhdrWAITHeader, - fhdrWAITClearsig, - fhdrSKIPHeader, - fhdrCLEARSIG, - fhdrREADClearsig, - fhdrNullClearsig, - fhdrEMPTYClearsig, - fhdrCHECKClearsig, - fhdrCHECKClearsig2, - fhdrCHECKDashEscaped, - fhdrCHECKDashEscaped2, - fhdrCHECKDashEscaped3, - fhdrREADClearsigNext, - fhdrENDClearsig, - fhdrENDClearsigHelp, - fhdrTESTSpaces, - fhdrCLEARSIGSimple, - fhdrCLEARSIGSimpleNext, - fhdrTEXT, - fhdrTEXTSimple, - fhdrERROR, - fhdrERRORShow, - fhdrEOF -} fhdr_state_t; - - -/* if we encounter this armor string with this index, go - * into a mode which fakes packets and wait for the next armor */ -#define BEGIN_SIGNATURE 2 -#define BEGIN_SIGNED_MSG_IDX 3 -static char *head_strings[] = { - "BEGIN PGP MESSAGE", - "BEGIN PGP PUBLIC KEY BLOCK", - "BEGIN PGP SIGNATURE", - "BEGIN PGP SIGNED MESSAGE", - "BEGIN PGP ARMORED FILE", /* gnupg extension */ - "BEGIN PGP PRIVATE KEY BLOCK", - "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */ - NULL -}; -static char *tail_strings[] = { - "END PGP MESSAGE", - "END PGP PUBLIC KEY BLOCK", - "END PGP SIGNATURE", - "END dummy", - "END PGP ARMORED FILE", - "END PGP PRIVATE KEY BLOCK", - "END PGP SECRET KEY BLOCK", - NULL -}; - - - -static void -initialize(void) -{ - int i, j; - u32 t; - byte *s; - - /* init the crc lookup table */ - crc_table[0] = 0; - for(i=j=0; j < 128; j++ ) { - t = crc_table[j]; - if( t & 0x00800000 ) { - t <<= 1; - crc_table[i++] = t ^ CRCPOLY; - crc_table[i++] = t; - } - else { - t <<= 1; - crc_table[i++] = t; - crc_table[i++] = t ^ CRCPOLY; - } - } - /* build the helptable for radix64 to bin conversion */ - for(i=0; i < 256; i++ ) - asctobin[i] = 255; /* used to detect invalid characters */ - for(s=bintoasc,i=0; *s; s++,i++ ) - asctobin[*s] = i; - - is_initialized=1; -} - -/**************** - * Check whether this is an armored file or not See also - * parse-packet.c for details on this code For unknown historic - * reasons we use a string here but only the first byte will be used. - * Returns: True if it seems to be armored - */ -static int -is_armored( const byte *buf ) -{ - int ctb, pkttype; - - ctb = *buf; - if( !(ctb & 0x80) ) - return 1; /* invalid packet: assume it is armored */ - pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf); - switch( pkttype ) { - case PKT_MARKER: - case PKT_SYMKEY_ENC: - case PKT_ONEPASS_SIG: - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - case PKT_PUBKEY_ENC: - case PKT_SIGNATURE: - case PKT_COMMENT: - case PKT_OLD_COMMENT: - case PKT_PLAINTEXT: - case PKT_COMPRESSED: - case PKT_ENCRYPTED: - return 0; /* seems to be a regular packet: not armored */ - } - - return 1; -} - - -/**************** - * Try to check whether the iobuf is armored - * Returns true if this may be the case; the caller should use the - * filter to do further processing. - */ -int -use_armor_filter( IOBUF a ) -{ - byte buf[1]; - int n; - - /* fixme: there might be a problem with iobuf_peek */ - n = iobuf_peek(a, buf, 1 ); - if( n == -1 ) - return 0; /* EOF, doesn't matter whether armored or not */ - if( !n ) - return 1; /* can't check it: try armored */ - return is_armored(buf); -} - - - - -static void -invalid_armor(void) -{ - write_status(STATUS_BADARMOR); - g10_exit(1); /* stop here */ -} - - -/**************** - * check whether the armor header is valid on a signed message. - * this is for security reasons: the header lines are not included in the - * hash and by using some creative formatting rules, Mallory could fake - * any text at the beginning of a document; assuming it is read with - * a simple viewer. We only allow the Hash Header. - */ -static int -parse_hash_header( const char *line ) -{ - const char *s, *s2; - unsigned found = 0; - - if( strlen(line) < 6 || strlen(line) > 60 ) - return 0; /* too short or too long */ - if( memcmp( line, "Hash:", 5 ) ) - return 0; /* invalid header */ - s = line+5; - for(s=line+5;;s=s2) { - for(; *s && (*s==' ' || *s == '\t'); s++ ) - ; - if( !*s ) - break; - for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ ) - ; - if( !strncmp( s, "RIPEMD160", s2-s ) ) - found |= 1; - else if( !strncmp( s, "SHA1", s2-s ) ) - found |= 2; - else if( !strncmp( s, "MD5", s2-s ) ) - found |= 4; - else if( !strncmp( s, "TIGER192", s2-s ) ) - found |= 8; - else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */ - found |= 8; - else - return 0; - for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) - ; - if( *s2 && *s2 != ',' ) - return 0; - if( *s2 ) - s2++; - } - return found; -} - - - -/**************** - * Check whether this is a armor line. - * returns: -1 if it is not a armor header or the index number of the - * armor header. - */ -static int -is_armor_header( byte *line, unsigned len ) -{ - const char *s; - byte *save_p, *p; - int save_c; - int i; - - if( len < 15 ) - return -1; /* too short */ - if( memcmp( line, "-----", 5 ) ) - return -1; /* no */ - p = strstr( line+5, "-----"); - if( !p ) - return -1; - save_p = p; - p += 5; - - /* Some mail programs on Windows seem to add spaces to the end of - the line. This becomes strict if --openpgp is set. */ - - if(!opt.rfc2440) - while(*p==' ') - p++; - - if( *p == '\r' ) - p++; - if( *p == '\n' ) - p++; - if( *p ) - return -1; /* garbage after dashes */ - save_c = *save_p; *save_p = 0; - p = line+5; - for(i=0; (s=head_strings[i]); i++ ) - if( !strcmp(s, p) ) - break; - *save_p = save_c; - if( !s ) - return -1; /* unknown armor line */ - - if( opt.verbose > 1 ) - log_info(_("armor: %s\n"), head_strings[i]); - return i; -} - - - -/**************** - * Parse a header lines - * Return 0: Empty line (end of header lines) - * -1: invalid header line - * >0: Good header line - */ -static int -parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) -{ - byte *p; - int hashes=0; - unsigned int len2; - - len2 = check_trailing_ws( line, len ); - if( !len2 ) { - afx->buffer_pos = len2; /* (it is not the fine way to do it here) */ - return 0; /* WS only: same as empty line */ - } - len = len2; - line[len2] = 0; - - p = strchr( line, ':'); - if( !p || !p[1] ) { - log_error(_("invalid armor header: ")); - print_string( stderr, line, len, 0 ); - putc('\n', stderr); - return -1; - } - - if( opt.verbose ) { - log_info(_("armor header: ")); - print_string( stderr, line, len, 0 ); - putc('\n', stderr); - } - - if( afx->in_cleartext ) { - if( (hashes=parse_hash_header( line )) ) - afx->hashes |= hashes; - else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) ) - afx->not_dash_escaped = 1; - else { - log_error(_("invalid clearsig header\n")); - return -1; - } - } - return 1; -} - - - -/* figure out whether the data is armored or not */ -static int -check_input( armor_filter_context_t *afx, IOBUF a ) -{ - int rc = 0; - int i; - byte *line; - unsigned len; - unsigned maxlen; - int hdr_line = -1; - - /* read the first line to see whether this is armored data */ - maxlen = MAX_LINELEN; - len = afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - line = afx->buffer; - if( !maxlen ) { - /* line has been truncated: assume not armored */ - afx->inp_checked = 1; - afx->inp_bypass = 1; - return 0; - } - - if( !len ) { - return -1; /* eof */ - } - - /* (the line is always a C string but maybe longer) */ - if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) ) - ; - else if( !is_armored( line ) ) { - afx->inp_checked = 1; - afx->inp_bypass = 1; - return 0; - } - - /* find the armor header */ - while(len) { - i = is_armor_header( line, len ); - if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) { - hdr_line = i; - if( hdr_line == BEGIN_SIGNED_MSG_IDX ) { - if( afx->in_cleartext ) { - log_error(_("nested clear text signatures\n")); - rc = G10ERR_INVALID_ARMOR; - } - afx->in_cleartext = 1; - } - break; - } - /* read the next line (skip all truncated lines) */ - do { - maxlen = MAX_LINELEN; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - line = afx->buffer; - len = afx->buffer_len; - } while( !maxlen ); - } - - /* parse the header lines */ - while(len) { - /* read the next line (skip all truncated lines) */ - do { - maxlen = MAX_LINELEN; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - line = afx->buffer; - len = afx->buffer_len; - } while( !maxlen ); - - i = parse_header_line( afx, line, len ); - if( i <= 0 ) { - if( i ) - rc = G10ERR_INVALID_ARMOR; - break; - } - } - - - if( rc ) - invalid_armor(); - else if( afx->in_cleartext ) - afx->faked = 1; - else { - afx->inp_checked = 1; - afx->crc = CRCINIT; - afx->idx = 0; - afx->radbuf[0] = 0; - } - - return rc; -} - - - -/**************** - * Fake a literal data packet and wait for the next armor line - * fixme: empty line handling and null length clear text signature are - * not implemented/checked. - */ -static int -fake_packet( armor_filter_context_t *afx, IOBUF a, - size_t *retn, byte *buf, size_t size ) -{ - int rc = 0; - size_t len = 0; - int lastline = 0; - unsigned maxlen, n; - byte *p; - - len = 2; /* reserve 2 bytes for the length header */ - size -= 2; /* and 2 for the terminating header */ - while( !rc && len < size ) { - /* copy what we have in the line buffer */ - if( afx->faked == 1 ) - afx->faked++; /* skip the first (empty) line */ - else { - while( len < size && afx->buffer_pos < afx->buffer_len ) - buf[len++] = afx->buffer[afx->buffer_pos++]; - if( len >= size ) - continue; - } - - /* read the next line */ - maxlen = MAX_LINELEN; - afx->buffer_pos = 0; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - if( !afx->buffer_len ) { - rc = -1; /* eof (should not happen) */ - continue; - } - if( !maxlen ) - afx->truncated++; - if( !afx->not_dash_escaped ) { - int crlf; - p = afx->buffer; - n = afx->buffer_len; - crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n'; - - /* PGP2 does not treat a tab as white space character */ - afx->buffer_len = trim_trailing_chars( p, n, - afx->pgp2mode ? " \r\n" : " \t\r\n"); - /* the buffer is always allocated with enough space to append - * the removed [CR], LF and a Nul - * The reason for this complicated procedure is to keep at least - * the original type of lineending - handling of the removed - * trailing spaces seems to be impossible in our method - * of faking a packet; either we have to use a temporary file - * or calculate the hash here in this module and somehow find - * a way to send the hash down the processing line (well, a special - * faked packet could do the job). - */ - if( crlf ) - afx->buffer[afx->buffer_len++] = '\r'; - afx->buffer[afx->buffer_len++] = '\n'; - afx->buffer[afx->buffer_len] = 0; - } - p = afx->buffer; - n = afx->buffer_len; - - if( n > 2 && *p == '-' ) { - /* check for dash escaped or armor header */ - if( p[1] == ' ' && !afx->not_dash_escaped ) { - /* issue a warning if it is not regular encoded */ - if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) { - log_info(_("invalid dash escaped line: ")); - print_string( stderr, p, n, 0 ); - putc('\n', stderr); - } - afx->buffer_pos = 2; /* skip */ - } - else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) { - int type = is_armor_header( p, n ); - if( afx->not_dash_escaped && type != BEGIN_SIGNATURE ) - ; /* this is okay */ - else { - if( type != BEGIN_SIGNATURE ) { - log_info(_("unexpected armor:")); - print_string( stderr, p, n, 0 ); - putc('\n', stderr); - } - lastline = 1; - rc = -1; - } - } - } - } - - buf[0] = (len-2) >> 8; - buf[1] = (len-2); - if( lastline ) { /* write last (ending) length header */ - if( buf[0] || buf[1] ) { /* only if we have some text */ - buf[len++] = 0; - buf[len++] = 0; - } - rc = 0; - afx->faked = 0; - afx->in_cleartext = 0; - /* and now read the header lines */ - afx->buffer_pos = 0; - for(;;) { - int i; - - /* read the next line (skip all truncated lines) */ - do { - maxlen = MAX_LINELEN; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - } while( !maxlen ); - p = afx->buffer; - n = afx->buffer_len; - if( !n ) { - rc = -1; - break; /* eof */ - } - i = parse_header_line( afx, p , n ); - if( i <= 0 ) { - if( i ) - invalid_armor(); - break; - } - } - afx->inp_checked = 1; - afx->crc = CRCINIT; - afx->idx = 0; - afx->radbuf[0] = 0; - } - - *retn = len; - return rc; -} - - -static int -invalid_crc(void) -{ - if ( opt.ignore_crc_error ) - return 0; - log_inc_errorcount(); - return G10ERR_INVALID_ARMOR; -} - - -static int -radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, - byte *buf, size_t size ) -{ - byte val; - int c=0, c2; /*init c because gcc is not clever enough for the continue*/ - int checkcrc=0; - int rc = 0; - size_t n = 0; - int idx, i; - u32 crc; - - crc = afx->crc; - idx = afx->idx; - val = afx->radbuf[0]; - for( n=0; n < size; ) { - - if( afx->buffer_pos < afx->buffer_len ) - c = afx->buffer[afx->buffer_pos++]; - else { /* read the next line */ - unsigned maxlen = MAX_LINELEN; - afx->buffer_pos = 0; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - if( !maxlen ) - afx->truncated++; - if( !afx->buffer_len ) - break; /* eof */ - continue; - } - - again: - if( c == '\n' || c == ' ' || c == '\r' || c == '\t' ) - continue; - else if( c == '=' ) { /* pad character: stop */ - /* some mailers leave quoted-printable encoded characters - * so we try to workaround this */ - if( afx->buffer_pos+2 < afx->buffer_len ) { - int cc1, cc2, cc3; - cc1 = afx->buffer[afx->buffer_pos]; - cc2 = afx->buffer[afx->buffer_pos+1]; - cc3 = afx->buffer[afx->buffer_pos+2]; - if( isxdigit(cc1) && isxdigit(cc2) - && strchr( "=\n\r\t ", cc3 )) { - /* well it seems to be the case - adjust */ - c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10); - c <<= 4; - c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10); - afx->buffer_pos += 2; - afx->qp_detected = 1; - goto again; - } - } - - if( idx == 1 ) - buf[n++] = val; - checkcrc++; - break; - } - else if( (c = asctobin[(c2=c)]) == 255 ) { - log_error(_("invalid radix64 character %02x skipped\n"), c2); - continue; - } - switch(idx) { - case 0: val = c << 2; break; - case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break; - case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break; - case 3: val |= c&0x3f; buf[n++] = val; break; - } - idx = (idx+1) % 4; - } - - for(i=0; i < n; i++ ) - crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]]; - crc &= 0x00ffffff; - afx->crc = crc; - afx->idx = idx; - afx->radbuf[0] = val; - - if( checkcrc ) { - afx->any_data = 1; - afx->inp_checked=0; - afx->faked = 0; - for(;;) { /* skip lf and pad characters */ - if( afx->buffer_pos < afx->buffer_len ) - c = afx->buffer[afx->buffer_pos++]; - else { /* read the next line */ - unsigned maxlen = MAX_LINELEN; - afx->buffer_pos = 0; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, &maxlen ); - if( !maxlen ) - afx->truncated++; - if( !afx->buffer_len ) - break; /* eof */ - continue; - } - if( c == '\n' || c == ' ' || c == '\r' - || c == '\t' || c == '=' ) - continue; - break; - } - if( c == -1 ) - log_error(_("premature eof (no CRC)\n")); - else { - u32 mycrc = 0; - idx = 0; - do { - if( (c = asctobin[c]) == 255 ) - break; - switch(idx) { - case 0: val = c << 2; break; - case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break; - case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break; - case 3: val |= c&0x3f; mycrc |= val; break; - } - for(;;) { - if( afx->buffer_pos < afx->buffer_len ) - c = afx->buffer[afx->buffer_pos++]; - else { /* read the next line */ - unsigned maxlen = MAX_LINELEN; - afx->buffer_pos = 0; - afx->buffer_len = iobuf_read_line( a, &afx->buffer, - &afx->buffer_size, - &maxlen ); - if( !maxlen ) - afx->truncated++; - if( !afx->buffer_len ) - break; /* eof */ - continue; - } - break; - } - if( !afx->buffer_len ) - break; /* eof */ - } while( ++idx < 4 ); - if( c == -1 ) { - log_info(_("premature eof (in CRC)\n")); - rc = invalid_crc(); - } - else if( idx != 4 ) { - log_info(_("malformed CRC\n")); - rc = invalid_crc(); - } - else if( mycrc != afx->crc ) { - log_info (_("CRC error; %06lx - %06lx\n"), - (ulong)afx->crc, (ulong)mycrc); - rc = invalid_crc(); - } - else { - rc = 0; - /* FIXME: Here we should emit another control packet, - * so that we know in mainproc that we are processing - * a clearsign message */ - #if 0 - for(rc=0;!rc;) { - rc = 0 /*check_trailer( &fhdr, c )*/; - if( !rc ) { - if( (c=iobuf_get(a)) == -1 ) - rc = 2; - } - } - if( rc == -1 ) - rc = 0; - else if( rc == 2 ) { - log_error(_("premature eof (in Trailer)\n")); - rc = G10ERR_INVALID_ARMOR; - } - else { - log_error(_("error in trailer line\n")); - rc = G10ERR_INVALID_ARMOR; - } - #endif - } - } - } - - if( !n ) - rc = -1; - - *retn = n; - return rc; -} - -/**************** - * This filter is used to handle the armor stuff - */ -int -armor_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) -{ - size_t size = *ret_len; - armor_filter_context_t *afx = opaque; - int rc=0, i, c; - byte radbuf[3]; - int idx, idx2; - size_t n=0; - u32 crc; - #if 0 - static FILE *fp ; - - if( !fp ) { - fp = fopen("armor.out", "w"); - assert(fp); - } - #endif - - if( DBG_FILTER ) - log_debug("armor-filter: control: %d\n", control ); - if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) { - n = 0; - if( afx->buffer_len ) { - for(; n < size && afx->buffer_pos < afx->buffer_len; n++ ) - buf[n++] = afx->buffer[afx->buffer_pos++]; - if( afx->buffer_pos >= afx->buffer_len ) - afx->buffer_len = 0; - } - for(; n < size; n++ ) { - if( (c=iobuf_get(a)) == -1 ) - break; - buf[n] = c & 0xff; - } - if( !n ) - rc = -1; - *ret_len = n; - } - else if( control == IOBUFCTRL_UNDERFLOW ) { - /* We need some space for the faked packet. The minmum required - * size is ~18 + length of the session marker */ - if( size < 50 ) - BUG(); /* supplied buffer too short */ - - if( afx->faked ) - rc = fake_packet( afx, a, &n, buf, size ); - else if( !afx->inp_checked ) { - rc = check_input( afx, a ); - if( afx->inp_bypass ) { - for(n=0; n < size && afx->buffer_pos < afx->buffer_len; ) - buf[n++] = afx->buffer[afx->buffer_pos++]; - if( afx->buffer_pos >= afx->buffer_len ) - afx->buffer_len = 0; - if( !n ) - rc = -1; - } - else if( afx->faked ) { - unsigned int hashes = afx->hashes; - const byte *sesmark; - size_t sesmarklen; - - sesmark = get_session_marker( &sesmarklen ); - if ( sesmarklen > 20 ) - BUG(); - - /* the buffer is at least 15+n*15 bytes long, so it - * is easy to construct the packets */ - - hashes &= 1|2|4|8; - if( !hashes ) { - hashes |= 4; /* default to MD 5 */ - if( opt.pgp2_workarounds ) - afx->pgp2mode = 1; - } - n=0; - /* first a gpg control packet */ - buf[n++] = 0xff; /* new format, type 63, 1 length byte */ - n++; /* see below */ - memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen; - buf[n++] = CTRLPKT_CLEARSIGN_START; - buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */ - if( hashes & 1 ) - buf[n++] = DIGEST_ALGO_RMD160; - if( hashes & 2 ) - buf[n++] = DIGEST_ALGO_SHA1; - if( hashes & 4 ) - buf[n++] = DIGEST_ALGO_MD5; - if( hashes & 8 ) - buf[n++] = DIGEST_ALGO_TIGER; - buf[1] = n - 2; - - /* followed by a plaintext packet */ - buf[n++] = 0xaf; /* old packet format, type 11, var length */ - buf[n++] = 0; /* set the length header */ - buf[n++] = 6; - buf[n++] = 't'; /* canonical text mode */ - buf[n++] = 0; /* namelength */ - memset(buf+n, 0, 4); /* timestamp */ - n += 4; - } - else if( !rc ) - rc = radix64_read( afx, a, &n, buf, size ); - } - else - rc = radix64_read( afx, a, &n, buf, size ); - #if 0 - if( n ) - if( fwrite(buf, n, 1, fp ) != 1 ) - BUG(); - #endif - *ret_len = n; - } - else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) { - if( !afx->status ) { /* write the header line */ - const char *s; - - if( afx->what >= DIM(head_strings) ) - log_bug("afx->what=%d", afx->what); - iobuf_writestr(a, "-----"); - iobuf_writestr(a, head_strings[afx->what] ); - iobuf_writestr(a, "-----" LF ); - if( !opt.no_version ) - iobuf_writestr(a, "Version: GnuPG v" VERSION " (" - PRINTABLE_OS_NAME ")" LF ); - - /* write the comment string or a default one */ - s = opt.comment_string; - if( s && *s ) { - iobuf_writestr(a, "Comment: " ); - for( ; *s; s++ ) { - if( *s == '\n' ) - iobuf_writestr(a, "\\n" ); - else if( *s == '\r' ) - iobuf_writestr(a, "\\r" ); - else if( *s == '\v' ) - iobuf_writestr(a, "\\v" ); - else - iobuf_put(a, *s ); - } - iobuf_writestr(a, LF ); - } - - if ( afx->hdrlines ) { - for ( s = afx->hdrlines; *s; s++ ) { - #ifdef HAVE_DOSISH_SYSTEM - if ( *s == '\n' ) - iobuf_put( a, '\r'); - #endif - iobuf_put(a, *s ); - } - } - iobuf_writestr(a, LF ); - afx->status++; - afx->idx = 0; - afx->idx2 = 0; - afx->crc = CRCINIT; - - } - crc = afx->crc; - idx = afx->idx; - idx2 = afx->idx2; - for(i=0; i < idx; i++ ) - radbuf[i] = afx->radbuf[i]; - - for(i=0; i < size; i++ ) - crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]]; - crc &= 0x00ffffff; - - for( ; size; buf++, size-- ) { - radbuf[idx++] = *buf; - if( idx > 2 ) { - idx = 0; - c = bintoasc[(*radbuf >> 2) & 077]; - iobuf_put(a, c); - c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; - iobuf_put(a, c); - c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; - iobuf_put(a, c); - c = bintoasc[radbuf[2]&077]; - iobuf_put(a, c); - if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ - iobuf_writestr(a, LF ); - idx2=0; - } - } - } - for(i=0; i < idx; i++ ) - afx->radbuf[i] = radbuf[i]; - afx->idx = idx; - afx->idx2 = idx2; - afx->crc = crc; - } - else if( control == IOBUFCTRL_INIT ) { - if( !is_initialized ) - initialize(); - } - else if( control == IOBUFCTRL_CANCEL ) { - afx->cancel = 1; - } - else if( control == IOBUFCTRL_FREE ) { - if( afx->cancel ) - ; - else if( afx->status ) { /* pad, write cecksum, and bottom line */ - crc = afx->crc; - idx = afx->idx; - idx2 = afx->idx2; - for(i=0; i < idx; i++ ) - radbuf[i] = afx->radbuf[i]; - if( idx ) { - c = bintoasc[(*radbuf>>2)&077]; - iobuf_put(a, c); - if( idx == 1 ) { - c = bintoasc[((*radbuf << 4) & 060) & 077]; - iobuf_put(a, c); - iobuf_put(a, '='); - iobuf_put(a, '='); - } - else { /* 2 */ - c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; - iobuf_put(a, c); - c = bintoasc[((radbuf[1] << 2) & 074) & 077]; - iobuf_put(a, c); - iobuf_put(a, '='); - } - if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ - iobuf_writestr(a, LF ); - idx2=0; - } - } - /* may need a linefeed */ - if( idx2 ) - iobuf_writestr(a, LF ); - /* write the CRC */ - iobuf_put(a, '='); - radbuf[0] = crc >>16; - radbuf[1] = crc >> 8; - radbuf[2] = crc; - c = bintoasc[(*radbuf >> 2) & 077]; - iobuf_put(a, c); - c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; - iobuf_put(a, c); - c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; - iobuf_put(a, c); - c = bintoasc[radbuf[2]&077]; - iobuf_put(a, c); - iobuf_writestr(a, LF ); - /* and the the trailer */ - if( afx->what >= DIM(tail_strings) ) - log_bug("afx->what=%d", afx->what); - iobuf_writestr(a, "-----"); - iobuf_writestr(a, tail_strings[afx->what] ); - iobuf_writestr(a, "-----" LF ); - } - else if( !afx->any_data && !afx->inp_bypass ) { - log_error(_("no valid OpenPGP data found.\n")); - afx->no_openpgp_data = 1; - write_status_text( STATUS_NODATA, "1" ); - } - if( afx->truncated ) - log_info(_("invalid armor: line longer than %d characters\n"), - MAX_LINELEN ); - /* issue an error to enforce dissemination of correct software */ - if( afx->qp_detected ) - log_error(_("quoted printable character in armor - " - "probably a buggy MTA has been used\n") ); - m_free( afx->buffer ); - afx->buffer = NULL; - } - else if( control == IOBUFCTRL_DESC ) - *(char**)buf = "armor_filter"; - return rc; -} - - -/**************** - * create a radix64 encoded string. - */ -char * -make_radix64_string( const byte *data, size_t len ) -{ - char *buffer, *p; - - buffer = p = m_alloc( (len+2)/3*4 + 1 ); - for( ; len >= 3 ; len -= 3, data += 3 ) { - *p++ = bintoasc[(data[0] >> 2) & 077]; - *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; - *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077]; - *p++ = bintoasc[data[2]&077]; - } - if( len == 2 ) { - *p++ = bintoasc[(data[0] >> 2) & 077]; - *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; - *p++ = bintoasc[((data[1]<<2)&074)]; - } - else if( len == 1 ) { - *p++ = bintoasc[(data[0] >> 2) & 077]; - *p++ = bintoasc[(data[0] <<4)&060]; - } - *p = 0; - return buffer; -} - - -/*********************************************** - * For the pipemode command we can't use the armor filter for various - * reasons, so we use this new unarmor_pump stuff to remove the armor - */ - -enum unarmor_state_e { - STA_init = 0, - STA_bypass, - STA_wait_newline, - STA_wait_dash, - STA_first_dash, - STA_compare_header, - STA_found_header_wait_newline, - STA_skip_header_lines, - STA_skip_header_lines_non_ws, - STA_read_data, - STA_wait_crc, - STA_read_crc, - STA_ready -}; - -struct unarmor_pump_s { - enum unarmor_state_e state; - byte val; - int checkcrc; - int pos; /* counts from 0..3 */ - u32 crc; - u32 mycrc; /* the one store in the data */ -}; - - - -UnarmorPump -unarmor_pump_new (void) -{ - UnarmorPump x; - - if( !is_initialized ) - initialize(); - x = m_alloc_clear (sizeof *x); - return x; -} - -void -unarmor_pump_release (UnarmorPump x) -{ - m_free (x); -} - -/* - * Get the next character from the ascii armor taken from the IOBUF - * created earlier by unarmor_pump_new(). - * Return: c = Character - * 256 = ignore this value - * -1 = End of current armor - * -2 = Premature EOF (not used) - * -3 = Invalid armor - */ -int -unarmor_pump (UnarmorPump x, int c) -{ - int rval = 256; /* default is to ignore the return value */ - - switch (x->state) { - case STA_init: - { - byte tmp[1]; - tmp[0] = c; - if ( is_armored (tmp) ) - x->state = c == '-'? STA_first_dash : STA_wait_newline; - else { - x->state = STA_bypass; - return c; - } - } - break; - case STA_bypass: - return c; /* return here to avoid crc calculation */ - case STA_wait_newline: - if (c == '\n') - x->state = STA_wait_dash; - break; - case STA_wait_dash: - x->state = c == '-'? STA_first_dash : STA_wait_newline; - break; - case STA_first_dash: /* just need for initalization */ - x->pos = 0; - x->state = STA_compare_header; - case STA_compare_header: - if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) { - if ( x->pos == 28 ) - x->state = STA_found_header_wait_newline; - } - else - x->state = c == '\n'? STA_wait_dash : STA_wait_newline; - break; - case STA_found_header_wait_newline: - /* to make CR,LF issues easier we simply allow for white space - behind the 5 dashes */ - if ( c == '\n' ) - x->state = STA_skip_header_lines; - else if ( c != '\r' && c != ' ' && c != '\t' ) - x->state = STA_wait_dash; /* garbage after the header line */ - break; - case STA_skip_header_lines: - /* i.e. wait for one empty line */ - if ( c == '\n' ) { - x->state = STA_read_data; - x->crc = CRCINIT; - x->val = 0; - x->pos = 0; - } - else if ( c != '\r' && c != ' ' && c != '\t' ) - x->state = STA_skip_header_lines_non_ws; - break; - case STA_skip_header_lines_non_ws: - /* like above but we already encountered non white space */ - if ( c == '\n' ) - x->state = STA_skip_header_lines; - break; - case STA_read_data: - /* fixme: we don't check for the trailing dash lines but rely - * on the armor stop characters */ - if( c == '\n' || c == ' ' || c == '\r' || c == '\t' ) - break; /* skip all kind of white space */ - - if( c == '=' ) { /* pad character: stop */ - if( x->pos == 1 ) /* in this case val has some value */ - rval = x->val; - x->state = STA_wait_crc; - break; - } - - { - int c2; - if( (c = asctobin[(c2=c)]) == 255 ) { - log_error(_("invalid radix64 character %02x skipped\n"), c2); - break; - } - } - - switch(x->pos) { - case 0: - x->val = c << 2; - break; - case 1: - x->val |= (c>>4)&3; - rval = x->val; - x->val = (c<<4)&0xf0; - break; - case 2: - x->val |= (c>>2)&15; - rval = x->val; - x->val = (c<<6)&0xc0; - break; - case 3: - x->val |= c&0x3f; - rval = x->val; - break; - } - x->pos = (x->pos+1) % 4; - break; - case STA_wait_crc: - if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' ) - break; /* skip ws and pad characters */ - /* assume that we are at the next line */ - x->state = STA_read_crc; - x->pos = 0; - x->mycrc = 0; - case STA_read_crc: - if( (c = asctobin[c]) == 255 ) { - rval = -1; /* ready */ - if( x->crc != x->mycrc ) { - log_info (_("CRC error; %06lx - %06lx\n"), - (ulong)x->crc, (ulong)x->mycrc); - if ( invalid_crc() ) - rval = -3; - } - x->state = STA_ready; /* not sure whether this is correct */ - break; - } - - switch(x->pos) { - case 0: - x->val = c << 2; - break; - case 1: - x->val |= (c>>4)&3; - x->mycrc |= x->val << 16; - x->val = (c<<4)&0xf0; - break; - case 2: - x->val |= (c>>2)&15; - x->mycrc |= x->val << 8; - x->val = (c<<6)&0xc0; - break; - case 3: - x->val |= c&0x3f; - x->mycrc |= x->val; - break; - } - x->pos = (x->pos+1) % 4; - break; - case STA_ready: - rval = -1; - break; - } - - if ( !(rval & ~255) ) { /* compute the CRC */ - x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval]; - x->crc &= 0x00ffffff; - } - - return rval; -} - - diff --git a/g10/build-packet.c b/g10/build-packet.c deleted file mode 100644 index da1cbbe39..000000000 --- a/g10/build-packet.c +++ /dev/null @@ -1,1167 +0,0 @@ -/* build-packet.c - assemble packets and write them - * 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 -#include -#include -#include -#include - -#include "packet.h" -#include "errors.h" -#include "iobuf.h" -#include "mpi.h" -#include "util.h" -#include "cipher.h" -#include "memory.h" -#include "options.h" - - -static int do_comment( IOBUF out, int ctb, PKT_comment *rem ); -static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); -static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); -static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk ); -static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); -static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); -static u32 calc_plaintext( PKT_plaintext *pt ); -static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); -static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); -static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); -static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); -static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); -static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); - -static int calc_header_length( u32 len, int new_ctb ); -static int write_16(IOBUF inp, u16 a); -static int write_32(IOBUF inp, u32 a); -static int write_header( IOBUF out, int ctb, u32 len ); -static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); -static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ); -static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); -static int write_version( IOBUF out, int ctb ); - -/**************** - * Build a packet and write it to INP - * Returns: 0 := okay - * >0 := error - * Note: Caller must free the packet - */ -int -build_packet( IOBUF out, PACKET *pkt ) -{ - int new_ctb=0, rc=0, ctb; - int pkttype; - - if( DBG_PACKET ) - log_debug("build_packet() type=%d\n", pkt->pkttype ); - assert( pkt->pkt.generic ); - - switch( (pkttype = pkt->pkttype) ) { - case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break; - case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; - case PKT_ENCRYPTED: - case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; - case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; - case PKT_USER_ID: - if( pkt->pkt.user_id->attrib_data ) - pkttype = PKT_ATTRIBUTE; - break; - default: break; - } - - if( new_ctb || pkttype > 15 ) /* new format */ - ctb = 0xc0 | (pkttype & 0x3f); - else - ctb = 0x80 | ((pkttype & 15)<<2); - switch( pkttype ) { - case PKT_ATTRIBUTE: - case PKT_USER_ID: - rc = do_user_id( out, ctb, pkt->pkt.user_id ); - break; - case PKT_COMMENT: - rc = do_comment( out, ctb, pkt->pkt.comment ); - break; - case PKT_PUBLIC_SUBKEY: - case PKT_PUBLIC_KEY: - rc = do_public_key( out, ctb, pkt->pkt.public_key ); - break; - case PKT_SECRET_SUBKEY: - case PKT_SECRET_KEY: - rc = do_secret_key( out, ctb, pkt->pkt.secret_key ); - break; - case PKT_SYMKEY_ENC: - rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc ); - break; - case PKT_PUBKEY_ENC: - rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc ); - break; - case PKT_PLAINTEXT: - rc = do_plaintext( out, ctb, pkt->pkt.plaintext ); - break; - case PKT_ENCRYPTED: - rc = do_encrypted( out, ctb, pkt->pkt.encrypted ); - break; - case PKT_ENCRYPTED_MDC: - rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted ); - break; - case PKT_COMPRESSED: - rc = do_compressed( out, ctb, pkt->pkt.compressed ); - break; - case PKT_SIGNATURE: - rc = do_signature( out, ctb, pkt->pkt.signature ); - break; - case PKT_ONEPASS_SIG: - rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig ); - break; - case PKT_RING_TRUST: - break; /* ignore it (keyring.c does write it directly)*/ - case PKT_MDC: /* we write it directly, so we should never see it here. */ - default: - log_bug("invalid packet type in build_packet()\n"); - break; - } - - return rc; -} - -/**************** - * calculate the length of a packet described by PKT - */ -u32 -calc_packet_length( PACKET *pkt ) -{ - u32 n=0; - int new_ctb = 0; - - assert( pkt->pkt.generic ); - switch( pkt->pkttype ) { - case PKT_PLAINTEXT: - n = calc_plaintext( pkt->pkt.plaintext ); - new_ctb = pkt->pkt.plaintext->new_ctb; - break; - case PKT_ATTRIBUTE: - case PKT_USER_ID: - case PKT_COMMENT: - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - case PKT_SYMKEY_ENC: - case PKT_PUBKEY_ENC: - case PKT_ENCRYPTED: - case PKT_SIGNATURE: - case PKT_ONEPASS_SIG: - case PKT_RING_TRUST: - case PKT_COMPRESSED: - default: - log_bug("invalid packet type in calc_packet_length()"); - break; - } - - n += calc_header_length(n, new_ctb); - return n; -} - -static void -write_fake_data( IOBUF out, MPI a ) -{ - if( a ) { - int i; - void *p; - - p = mpi_get_opaque( a, &i ); - iobuf_write( out, p, i ); - } -} - - -static int -do_comment( IOBUF out, int ctb, PKT_comment *rem ) -{ - if( opt.sk_comments ) { - write_header(out, ctb, rem->len); - if( iobuf_write( out, rem->data, rem->len ) ) - return G10ERR_WRITE_FILE; - } - return 0; -} - -static int -do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) -{ - if( uid->attrib_data ) { - write_header(out, ctb, uid->attrib_len); - if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) ) - return G10ERR_WRITE_FILE; - } - else { - write_header(out, ctb, uid->len); - if( iobuf_write( out, uid->name, uid->len ) ) - return G10ERR_WRITE_FILE; - } - return 0; -} - -static int -do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) -{ - int rc = 0; - int n, i; - IOBUF a = iobuf_temp(); - - if( !pk->version ) - iobuf_put( a, 3 ); - else - iobuf_put( a, pk->version ); - write_32(a, pk->timestamp ); - if( pk->version < 4 ) { - u16 ndays; - if( pk->expiredate ) - ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); - else - ndays = 0; - write_16(a, ndays ); - } - iobuf_put(a, pk->pubkey_algo ); - n = pubkey_get_npkey( pk->pubkey_algo ); - if( !n ) - write_fake_data( a, pk->pkey[0] ); - for(i=0; i < n; i++ ) - mpi_write(a, pk->pkey[i] ); - - write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; - - iobuf_close(a); - return rc; -} - - -/**************** - * Make a hash value from the public key certificate - */ -void -hash_public_key( MD_HANDLE md, PKT_public_key *pk ) -{ - PACKET pkt; - int rc = 0; - int ctb; - ulong pktlen; - int c; - IOBUF a = iobuf_temp(); - #if 0 - FILE *fp = fopen("dump.pk", "a"); - int i=0; - - fprintf(fp, "\nHashing PK (v%d):\n", pk->version); - #endif - - /* build the packet */ - init_packet(&pkt); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - if( (rc = build_packet( a, &pkt )) ) - log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc)); - - if( !(pk->version == 3 && pk->pubkey_algo == 16) ) { - /* skip the constructed header but don't do this for our very old - * v3 ElG keys */ - ctb = iobuf_get_noeof(a); - pktlen = 0; - if( (ctb & 0x40) ) { - c = iobuf_get_noeof(a); - if( c < 192 ) - pktlen = c; - else if( c < 224 ) { - pktlen = (c - 192) * 256; - c = iobuf_get_noeof(a); - pktlen += c + 192; - } - else if( c == 255 ) { - pktlen = iobuf_get_noeof(a) << 24; - pktlen |= iobuf_get_noeof(a) << 16; - pktlen |= iobuf_get_noeof(a) << 8; - pktlen |= iobuf_get_noeof(a); - } - } - else { - int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); - for( ; lenbytes; lenbytes-- ) { - pktlen <<= 8; - pktlen |= iobuf_get_noeof(a); - } - } - /* hash a header */ - md_putc( md, 0x99 ); - pktlen &= 0xffff; /* can't handle longer packets */ - md_putc( md, pktlen >> 8 ); - md_putc( md, pktlen & 0xff ); - } - /* hash the packet body */ - while( (c=iobuf_get(a)) != -1 ) { - #if 0 - fprintf( fp," %02x", c ); - if( (++i == 24) ) { - putc('\n', fp); - i=0; - } - #endif - md_putc( md, c ); - } - #if 0 - putc('\n', fp); - fclose(fp); - #endif - iobuf_cancel(a); -} - - -static int -do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) -{ - int rc = 0; - int i, nskey, npkey; - IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */ - - /* Write the version number - if none is specified, use 3 */ - if( !sk->version ) - iobuf_put( a, 3 ); - else - iobuf_put( a, sk->version ); - write_32(a, sk->timestamp ); - - /* v3 needs the expiration time */ - if( sk->version < 4 ) { - u16 ndays; - if( sk->expiredate ) - ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); - else - ndays = 0; - write_16(a, ndays); - } - - iobuf_put(a, sk->pubkey_algo ); - - /* get number of secret and public parameters. They are held in - one array first the public ones, then the secret ones */ - nskey = pubkey_get_nskey( sk->pubkey_algo ); - npkey = pubkey_get_npkey( sk->pubkey_algo ); - - /* If we don't have any public parameters - which is the case if - we don't know the algorithm used - the parameters are stored as - one blob in a faked (opaque) MPI */ - if( !npkey ) { - write_fake_data( a, sk->skey[0] ); - goto leave; - } - assert( npkey < nskey ); - - /* Writing the public parameters is easy */ - for(i=0; i < npkey; i++ ) - mpi_write(a, sk->skey[i] ); - - /* build the header for protected (encrypted) secret parameters */ - if( sk->is_protected ) { - if( is_RSA(sk->pubkey_algo) && sk->version < 4 - && !sk->protect.s2k.mode ) { - /* the simple rfc1991 (v3) way */ - iobuf_put(a, sk->protect.algo ); - iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); - } - else { - /* OpenPGP protection according to rfc2440 */ - iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff ); - iobuf_put(a, sk->protect.algo ); - if( sk->protect.s2k.mode >= 1000 ) { - /* These modes are not possible in OpenPGP, we use them - to implement our extensions, 101 can be seen as a - private/experimental extension (this is not - specified in rfc2440 but the same scheme is used - for all other algorithm identifiers) */ - iobuf_put(a, 101 ); - iobuf_put(a, sk->protect.s2k.hash_algo ); - iobuf_write(a, "GNU", 3 ); - iobuf_put(a, sk->protect.s2k.mode - 1000 ); - } - else { - iobuf_put(a, sk->protect.s2k.mode ); - iobuf_put(a, sk->protect.s2k.hash_algo ); - } - if( sk->protect.s2k.mode == 1 - || sk->protect.s2k.mode == 3 ) - iobuf_write(a, sk->protect.s2k.salt, 8 ); - if( sk->protect.s2k.mode == 3 ) - iobuf_put(a, sk->protect.s2k.count ); - - /* For out special mode 1001 we do not need an IV */ - if( sk->protect.s2k.mode != 1001 ) - iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); - } - } - else - iobuf_put(a, 0 ); - - if( sk->protect.s2k.mode == 1001 ) - ; /* GnuPG extension - don't write a secret key at all */ - else if( sk->is_protected && sk->version >= 4 ) { - /* The secret key is protected - write it out as it is */ - byte *p; - assert( mpi_is_opaque( sk->skey[npkey] ) ); - p = mpi_get_opaque( sk->skey[npkey], &i ); - iobuf_write(a, p, i ); - } - else if( sk->is_protected ) { - /* The secret key is protected te old v4 way. */ - for( ; i < nskey; i++ ) { - byte *p; - int ndata; - - assert (mpi_is_opaque (sk->skey[i])); - p = mpi_get_opaque (sk->skey[i], &ndata); - iobuf_write (a, p, ndata); - } - write_16(a, sk->csum ); - } - else { - /* non-protected key */ - for( ; i < nskey; i++ ) - mpi_write(a, sk->skey[i] ); - write_16(a, sk->csum ); - } - - leave: - /* Build the header of the packet - which we must do after writing all - the other stuff, so that we know the length of the packet */ - write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); - /* And finally write it out the real stream */ - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; - - iobuf_close(a); /* close the remporary buffer */ - return rc; -} - -static int -do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) -{ - int rc = 0; - IOBUF a = iobuf_temp(); - - assert( enc->version == 4 ); - switch( enc->s2k.mode ) { - case 0: case 1: case 3: break; - default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); - } - iobuf_put( a, enc->version ); - iobuf_put( a, enc->cipher_algo ); - iobuf_put( a, enc->s2k.mode ); - iobuf_put( a, enc->s2k.hash_algo ); - if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { - iobuf_write(a, enc->s2k.salt, 8 ); - if( enc->s2k.mode == 3 ) - iobuf_put(a, enc->s2k.count); - } - if( enc->seskeylen ) - iobuf_write(a, enc->seskey, enc->seskeylen ); - - write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; - - iobuf_close(a); - return rc; -} - - - - -static int -do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) -{ - int rc = 0; - int n, i; - IOBUF a = iobuf_temp(); - - write_version( a, ctb ); - if( enc->throw_keyid ) { - write_32(a, 0 ); /* don't tell Eve who can decrypt the message */ - write_32(a, 0 ); - } - else { - write_32(a, enc->keyid[0] ); - write_32(a, enc->keyid[1] ); - } - iobuf_put(a,enc->pubkey_algo ); - n = pubkey_get_nenc( enc->pubkey_algo ); - if( !n ) - write_fake_data( a, enc->data[0] ); - for(i=0; i < n; i++ ) - mpi_write(a, enc->data[i] ); - - write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; - - iobuf_close(a); - return rc; -} - - - - -static u32 -calc_plaintext( PKT_plaintext *pt ) -{ - return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; -} - -static int -do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) -{ - int i, rc = 0; - u32 n; - byte buf[1000]; /* this buffer has the plaintext! */ - int nbytes; - - write_header(out, ctb, calc_plaintext( pt ) ); - iobuf_put(out, pt->mode ); - iobuf_put(out, pt->namelen ); - for(i=0; i < pt->namelen; i++ ) - iobuf_put(out, pt->name[i] ); - if( write_32(out, pt->timestamp ) ) - rc = G10ERR_WRITE_FILE; - - n = 0; - while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { - if( iobuf_write(out, buf, nbytes) == -1 ) { - rc = G10ERR_WRITE_FILE; - break; - } - n += nbytes; - } - memset(buf,0,1000); /* at least burn the buffer */ - if( !pt->len ) - iobuf_set_block_mode(out, 0 ); /* write end marker */ - else if( n != pt->len ) - log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", - (ulong)n, (ulong)pt->len ); - - return rc; -} - - - -static int -do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) -{ - int rc = 0; - u32 n; - - n = ed->len ? (ed->len + ed->extralen) : 0; - write_header(out, ctb, n ); - - /* This is all. The caller has to write the real data */ - - return rc; -} - -static int -do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) -{ - int rc = 0; - u32 n; - - assert( ed->mdc_method ); - - /* Take version number and the following MDC packet in account. */ - n = ed->len ? (ed->len + ed->extralen + 1 + 22) : 0; - write_header(out, ctb, n ); - iobuf_put(out, 1 ); /* version */ - - /* This is all. The caller has to write the real data */ - - return rc; -} - - -static int -do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) -{ - int rc = 0; - - /* We must use the old convention and don't use blockmode for tyhe - sake of PGP 2 compatibility. However if the new_ctb flag was - set, CTB is already formatted as new style and write_header2 - does create a partial length encoding using new the new - style. */ - write_header2(out, ctb, 0, 0, 0 ); - iobuf_put(out, cd->algorithm ); - - /* This is all. The caller has to write the real data */ - - return rc; -} - - -/**************** - * Delete all subpackets of type REQTYPE and return a bool whether a packet - * was deleted. - */ -int -delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype ) -{ - int buflen; - sigsubpkttype_t type; - byte *buffer, *bufstart; - size_t n; - size_t unused = 0; - int okay = 0; - - if( !area ) - return 0; - buflen = area->len; - buffer = area->data; - for(;;) { - if( !buflen ) { - okay = 1; - break; - } - bufstart = buffer; - n = *buffer++; buflen--; - if( n == 255 ) { - if( buflen < 4 ) - break; - n = (buffer[0] << 24) | (buffer[1] << 16) - | (buffer[2] << 8) | buffer[3]; - buffer += 4; - buflen -= 4; - } - else if( n >= 192 ) { - if( buflen < 2 ) - break; - n = (( n - 192 ) << 8) + *buffer + 192; - buffer++; - buflen--; - } - if( buflen < n ) - break; - - type = *buffer & 0x7f; - if( type == reqtype ) { - buffer++; - buflen--; - n--; - if( n > buflen ) - break; - buffer += n; /* point to next subpkt */ - buflen -= n; - memmove (bufstart, buffer, buflen); /* shift */ - unused += buffer - bufstart; - buffer = bufstart; - } - else { - buffer += n; buflen -=n; - } - } - - if (!okay) - log_error ("delete_subpkt: buffer shorter than subpacket\n"); - assert (unused <= area->len); - area->len -= unused; - return !!unused; -} - - -/**************** - * Create or update a signature subpacket for SIG of TYPE. This - * functions knows where to put the data (hashed or unhashed). The - * function may move data from the unhashed part to the hashed one. - * Note: All pointers into sig->[un]hashed (e.g. returned by - * parse_sig_subpkt) are not valid after a call to this function. The - * data to put into the subpaket should be in a buffer with a length - * of buflen. - */ -void -build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, - const byte *buffer, size_t buflen ) -{ - byte *p; - int critical, hashed; - subpktarea_t *oldarea, *newarea; - size_t nlen, n, n0; - - critical = (type & SIGSUBPKT_FLAG_CRITICAL); - type &= ~SIGSUBPKT_FLAG_CRITICAL; - - /* Sanity check buffer sizes */ - if(parse_one_sig_subpkt(buffer,buflen,type)<0) - BUG(); - - switch(type) - { - case SIGSUBPKT_NOTATION: - case SIGSUBPKT_POLICY: - case SIGSUBPKT_REV_KEY: - /* we do allow multiple subpackets */ - break; - - default: - /* we don't allow multiple subpackets */ - delete_sig_subpkt(sig->hashed,type); - delete_sig_subpkt(sig->unhashed,type); - break; - } - - /* Any special magic that needs to be done for this type so the - packet doesn't need to be reparsed? */ - switch(type) - { - case SIGSUBPKT_NOTATION: - sig->flags.notation=1; - break; - - case SIGSUBPKT_POLICY: - sig->flags.policy_url=1; - break; - - case SIGSUBPKT_EXPORTABLE: - if(buffer[0]) - sig->flags.exportable=1; - else - sig->flags.exportable=0; - break; - - case SIGSUBPKT_REVOCABLE: - if(buffer[0]) - sig->flags.revocable=1; - else - sig->flags.revocable=0; - break; - - default: - break; - } - - if( (buflen+1) >= 8384 ) - nlen = 5; /* write 5 byte length header */ - else if( (buflen+1) >= 192 ) - nlen = 2; /* write 2 byte length header */ - else - nlen = 1; /* just a 1 byte length header */ - - switch( type ) { - case SIGSUBPKT_PRIV_VERIFY_CACHE: /*(obsolete)*/ - BUG(); - break; - case SIGSUBPKT_ISSUER: - hashed = 0; - break; - default: - hashed = 1; - break; - } - - if( critical ) - type |= SIGSUBPKT_FLAG_CRITICAL; - - oldarea = hashed? sig->hashed : sig->unhashed; - - /* Calculate new size of the area and allocate */ - n0 = oldarea? oldarea->len : 0; - n = n0 + nlen + 1 + buflen; /* length, type, buffer */ - if (oldarea && n <= oldarea->size) { /* fits into the unused space */ - newarea = oldarea; - /*log_debug ("updating area for type %d\n", type );*/ - } - else if (oldarea) { - newarea = m_realloc (oldarea, sizeof (*newarea) + n - 1); - newarea->size = n; - /*log_debug ("reallocating area for type %d\n", type );*/ - } - else { - newarea = m_alloc (sizeof (*newarea) + n - 1); - newarea->size = n; - /*log_debug ("allocating area for type %d\n", type );*/ - } - newarea->len = n; - - p = newarea->data + n0; - if (nlen == 5) { - *p++ = 255; - *p++ = (buflen+1) >> 24; - *p++ = (buflen+1) >> 16; - *p++ = (buflen+1) >> 8; - *p++ = (buflen+1); - *p++ = type; - memcpy (p, buffer, buflen); - } - else if (nlen == 2) { - *p++ = (buflen+1-192) / 256 + 192; - *p++ = (buflen+1-192) % 256; - *p++ = type; - memcpy (p, buffer, buflen); - } - else { - *p++ = buflen+1; - *p++ = type; - memcpy (p, buffer, buflen); - } - - if (hashed) - sig->hashed = newarea; - else - sig->unhashed = newarea; -} - -/**************** - * Put all the required stuff from SIG into subpackets of sig. - * Hmmm, should we delete those subpackets which are in a wrong area? - */ -void -build_sig_subpkt_from_sig( PKT_signature *sig ) -{ - u32 u; - byte buf[8]; - - u = sig->keyid[0]; - buf[0] = (u >> 24) & 0xff; - buf[1] = (u >> 16) & 0xff; - buf[2] = (u >> 8) & 0xff; - buf[3] = u & 0xff; - u = sig->keyid[1]; - buf[4] = (u >> 24) & 0xff; - buf[5] = (u >> 16) & 0xff; - buf[6] = (u >> 8) & 0xff; - buf[7] = u & 0xff; - build_sig_subpkt( sig, SIGSUBPKT_ISSUER, buf, 8 ); - - u = sig->timestamp; - buf[0] = (u >> 24) & 0xff; - buf[1] = (u >> 16) & 0xff; - buf[2] = (u >> 8) & 0xff; - buf[3] = u & 0xff; - build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 ); - - if(sig->expiredate) - { - u = sig->expiredate-sig->timestamp; - buf[0] = (u >> 24) & 0xff; - buf[1] = (u >> 16) & 0xff; - buf[2] = (u >> 8) & 0xff; - buf[3] = u & 0xff; - - /* Mark this CRITICAL, so if any implementation doesn't - understand sigs that can expire, it'll just disregard this - sig altogether. */ - - build_sig_subpkt( sig, SIGSUBPKT_SIG_EXPIRE | SIGSUBPKT_FLAG_CRITICAL, - buf, 4 ); - } -} - -void -build_attribute_subpkt(PKT_user_id *uid,byte type, - const void *buf,u32 buflen, - const void *header,u32 headerlen) -{ - byte *attrib; - int idx; - - if(1+headerlen+buflen>8383) - idx=5; - else if(1+headerlen+buflen>191) - idx=2; - else - idx=1; - - /* realloc uid->attrib_data to the right size */ - - uid->attrib_data=m_realloc(uid->attrib_data, - uid->attrib_len+idx+1+headerlen+buflen); - - attrib=&uid->attrib_data[uid->attrib_len]; - - if(idx==5) - { - attrib[0]=255; - attrib[1]=(1+headerlen+buflen) >> 24; - attrib[2]=(1+headerlen+buflen) >> 16; - attrib[3]=(1+headerlen+buflen) >> 8; - attrib[4]=1+headerlen+buflen; - } - else if(idx==2) - { - attrib[0]=(1+headerlen+buflen-192) / 256 + 192; - attrib[1]=(1+headerlen+buflen-192) % 256; - } - else - attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */ - - attrib[idx++]=type; - - /* Tack on our data at the end */ - - if(headerlen>0) - memcpy(&attrib[idx],header,headerlen); - memcpy(&attrib[idx+headerlen],buf,buflen); - uid->attrib_len+=idx+headerlen+buflen; -} - -static int -do_signature( IOBUF out, int ctb, PKT_signature *sig ) -{ - int rc = 0; - int n, i; - IOBUF a = iobuf_temp(); - - if( !sig->version ) - iobuf_put( a, 3 ); - else - iobuf_put( a, sig->version ); - if( sig->version < 4 ) - iobuf_put(a, 5 ); /* constant */ - iobuf_put(a, sig->sig_class ); - if( sig->version < 4 ) { - write_32(a, sig->timestamp ); - write_32(a, sig->keyid[0] ); - write_32(a, sig->keyid[1] ); - } - iobuf_put(a, sig->pubkey_algo ); - iobuf_put(a, sig->digest_algo ); - if( sig->version >= 4 ) { - size_t nn; - /* timestamp and keyid must have been packed into the - * subpackets prior to the call of this function, because - * these subpackets are hashed */ - nn = sig->hashed? sig->hashed->len : 0; - write_16(a, nn); - if( nn ) - iobuf_write( a, sig->hashed->data, nn ); - nn = sig->unhashed? sig->unhashed->len : 0; - write_16(a, nn); - if( nn ) - iobuf_write( a, sig->unhashed->data, nn ); - } - iobuf_put(a, sig->digest_start[0] ); - iobuf_put(a, sig->digest_start[1] ); - n = pubkey_get_nsig( sig->pubkey_algo ); - if( !n ) - write_fake_data( a, sig->data[0] ); - for(i=0; i < n; i++ ) - mpi_write(a, sig->data[i] ); - - if( is_RSA(sig->pubkey_algo) && sig->version < 4 ) - write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); - else - write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; - - iobuf_close(a); - return rc; -} - - -static int -do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) -{ - int rc = 0; - IOBUF a = iobuf_temp(); - - write_version( a, ctb ); - iobuf_put(a, ops->sig_class ); - iobuf_put(a, ops->digest_algo ); - iobuf_put(a, ops->pubkey_algo ); - write_32(a, ops->keyid[0] ); - write_32(a, ops->keyid[1] ); - iobuf_put(a, ops->last ); - - write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; - - iobuf_close(a); - return rc; -} - - -static int -write_16(IOBUF out, u16 a) -{ - iobuf_put(out, a>>8); - if( iobuf_put(out,a) ) - return -1; - return 0; -} - -static int -write_32(IOBUF out, u32 a) -{ - iobuf_put(out, a>> 24); - iobuf_put(out, a>> 16); - iobuf_put(out, a>> 8); - if( iobuf_put(out, a) ) - return -1; - return 0; -} - - -/**************** - * calculate the length of a header - */ -static int -calc_header_length( u32 len, int new_ctb ) -{ - if( !len ) - return 1; /* only the ctb */ - - if( new_ctb ) { - if( len < 192 ) - return 2; - if( len < 8384 ) - return 3; - else - return 6; - } - if( len < 256 ) - return 2; - if( len < 65536 ) - return 3; - - return 5; -} - -/**************** - * Write the CTB and the packet length - */ -static int -write_header( IOBUF out, int ctb, u32 len ) -{ - return write_header2( out, ctb, len, 0, 1 ); -} - - -static int -write_sign_packet_header( IOBUF out, int ctb, u32 len ) -{ - /* work around a bug in the pgp read function for signature packets, - * which are not correctly coded and silently assume at some - * point 2 byte length headers.*/ - iobuf_put(out, 0x89 ); - iobuf_put(out, len >> 8 ); - return iobuf_put(out, len ) == -1 ? -1:0; -} - -/**************** - * if HDRLEN is > 0, try to build a header of this length. - * we need this, so that we can hash packets without reading them again. - */ -static int -write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ) -{ - if( ctb & 0x40 ) - return write_new_header( out, ctb, len, hdrlen ); - - if( hdrlen ) { - if( !len ) - ctb |= 3; - else if( hdrlen == 2 && len < 256 ) - ; - else if( hdrlen == 3 && len < 65536 ) - ctb |= 1; - else - ctb |= 2; - } - else { - if( !len ) - ctb |= 3; - else if( len < 256 ) - ; - else if( len < 65536 ) - ctb |= 1; - else - ctb |= 2; - } - if( iobuf_put(out, ctb ) ) - return -1; - if( !len ) { - if( blkmode ) - iobuf_set_block_mode(out, 8196 ); - } - else { - if( ctb & 2 ) { - iobuf_put(out, len >> 24 ); - iobuf_put(out, len >> 16 ); - } - if( ctb & 3 ) - iobuf_put(out, len >> 8 ); - if( iobuf_put(out, len ) ) - return -1; - } - return 0; -} - - -static int -write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) -{ - if( hdrlen ) - log_bug("can't cope with hdrlen yet\n"); - - if( iobuf_put(out, ctb ) ) - return -1; - if( !len ) { - iobuf_set_partial_block_mode(out, 512 ); - } - else { - if( len < 192 ) { - if( iobuf_put(out, len ) ) - return -1; - } - else if( len < 8384 ) { - len -= 192; - if( iobuf_put( out, (len / 256) + 192) ) - return -1; - if( iobuf_put( out, (len % 256) ) ) - return -1; - } - else { - if( iobuf_put( out, 0xff ) ) - return -1; - if( iobuf_put( out, (len >> 24)&0xff ) ) - return -1; - if( iobuf_put( out, (len >> 16)&0xff ) ) - return -1; - if( iobuf_put( out, (len >> 8)&0xff ) ) - return -1; - if( iobuf_put( out, len & 0xff ) ) - return -1; - } - } - return 0; -} - -static int -write_version( IOBUF out, int ctb ) -{ - if( iobuf_put( out, 3 ) ) - return -1; - return 0; -} - diff --git a/g10/cipher.c b/g10/cipher.c deleted file mode 100644 index cb9f14916..000000000 --- a/g10/cipher.c +++ /dev/null @@ -1,152 +0,0 @@ -/* cipher.c - En-/De-ciphering filter - * 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 -#include -#include -#include -#include -#include - -#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 a ) -{ - PACKET pkt; - PKT_encrypted ed; - byte temp[18]; - unsigned blocksize; - unsigned nprefix; - - blocksize = cipher_get_blocksize( 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 && !opt.rfc1991; - if( cfx->dek->use_mdc ) { - ed.mdc_method = DIGEST_ALGO_SHA1; - cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 ); - if ( DBG_HASHING ) - 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; - randomize_buffer( temp, nprefix, 1 ); - temp[nprefix] = temp[nprefix-2]; - temp[nprefix+1] = temp[nprefix-1]; - print_cipher_algo_note( cfx->dek->algo ); - cfx->cipher_hd = cipher_open( cfx->dek->algo, - cfx->dek->use_mdc? CIPHER_MODE_CFB - : CIPHER_MODE_AUTO_CFB, 1 ); -/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/ - cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); - cipher_setiv( cfx->cipher_hd, NULL, 0 ); -/* log_hexdump( "prefix", temp, nprefix+2 ); */ - if( cfx->mdc_hash ) /* hash the "IV" */ - md_write( cfx->mdc_hash, temp, nprefix+2 ); - cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2); - 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 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 ) - md_write( cfx->mdc_hash, buf, size ); - cipher_encrypt( cfx->cipher_hd, buf, buf, size); - if( iobuf_write( a, buf, size ) ) - rc = G10ERR_WRITE_FILE; - } - else if( control == IOBUFCTRL_FREE ) { - if( cfx->mdc_hash ) { - byte *hash; - int hashlen = md_digest_length( 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; - md_putc( cfx->mdc_hash, temp[0] ); - md_putc( cfx->mdc_hash, temp[1] ); - - md_final( cfx->mdc_hash ); - hash = md_read( cfx->mdc_hash, 0 ); - memcpy(temp+2, hash, 20); - cipher_encrypt( cfx->cipher_hd, temp, temp, 22 ); - md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL; - if( iobuf_write( a, temp, 22 ) ) - log_error("writing MDC packet failed\n" ); - } - cipher_close(cfx->cipher_hd); - } - else if( control == IOBUFCTRL_DESC ) { - *(char**)buf = "cipher_filter"; - } - return rc; -} diff --git a/g10/compress.c b/g10/compress.c deleted file mode 100644 index 6ea84f6cd..000000000 --- a/g10/compress.c +++ /dev/null @@ -1,310 +0,0 @@ -/* compress.c - compress filter - * 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 -#include -#include -#include -#include -#include -#include -#include - -#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; - - 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 = m_alloc( zfx->outbufsize ); -} - -static int -do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) -{ - 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 ); - - if( iobuf_write( a, zfx->outbuf, n ) ) { - log_debug("deflate: iobuf_write failed\n"); - return G10ERR_WRITE_FILE; - } - } 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. - */ - if( (rc = zfx->algo == 1? inflateInit2( zs, -13) - : 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 = m_alloc( zfx->inbufsize ); - zs->avail_in = 0; -} - -static int -do_uncompress( compress_filter_context_t *zfx, z_stream *zs, - IOBUF 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 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 = m_alloc_clear( 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 = m_alloc_clear( 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); - m_free(zs); - zfx->opaque = NULL; - m_free(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); - m_free(zs); - zfx->opaque = NULL; - m_free(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) -{ - m_free (ctx); -} - -/**************** - * Handle a compressed packet - */ -int -handle_compressed( void *procctx, PKT_compressed *cd, - int (*callback)(IOBUF, void *), void *passthru ) -{ - compress_filter_context_t *cfx; - int rc; - - if( cd->algorithm < 1 || cd->algorithm > 2 ) - return G10ERR_COMPR_ALGO; - cfx = m_alloc_clear (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; -} - diff --git a/g10/decrypt.c b/g10/decrypt.c deleted file mode 100644 index 297ee3418..000000000 --- a/g10/decrypt.c +++ /dev/null @@ -1,138 +0,0 @@ -/* decrypt.c - verify signed data - * 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 -#include -#include -#include -#include -#include - -#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 fp; - armor_filter_context_t afx; - int rc; - int no_out=0; - - /* open the message file */ - fp = iobuf_open(filename); - if( !fp ) { - log_error(_("can't open `%s'\n"), print_fname_stdin(filename)); - return G10ERR_OPEN_FILE; - } - - 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 fp; - armor_filter_context_t afx; - 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) - continue; - fp = iobuf_open(*files); - if (!fp) - { - log_error(_("can't open `%s'\n"), print_fname_stdin(*files)); - continue; - } - 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), - g10_errstr(rc)); - p = get_last_passphrase(); - set_next_passphrase(p); - m_free (p); - files++; - m_free(output); - write_status( STATUS_FILE_DONE ); - } - set_next_passphrase(NULL); -} - - - - - - - - diff --git a/g10/delkey.c b/g10/delkey.c deleted file mode 100644 index ca578a590..000000000 --- a/g10/delkey.c +++ /dev/null @@ -1,221 +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 -#include -#include -#include -#include -#include -#include - -#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):G10ERR_INV_USER_ID; - if (rc) { - log_error (_("key `%s' not found: %s\n"), username, g10_errstr (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"), g10_errstr(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 = G10ERR_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 != G10ERR_NO_SECKEY ) { - log_error("%s: get secret key: %s\n", username, g10_errstr(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 { - char *p; - size_t n; - - if( secret ) - tty_printf("sec %4u%c/%08lX %s ", - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid[1], datestr_from_sk(sk) ); - else - tty_printf("pub %4u%c/%08lX %s ", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk(pk) ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\n\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"), g10_errstr(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_ownertrust (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, g10_errstr(rc) ); - return rc; - } - } - - return 0; -} diff --git a/g10/encode.c b/g10/encode.c deleted file mode 100644 index 89d94278f..000000000 --- a/g10/encode.c +++ /dev/null @@ -1,798 +0,0 @@ -/* encode.c - encode data - * 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 -#include -#include -#include -#include -#include - -#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" - -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 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 = m_alloc_clear( sizeof *c ); - c->keylen = dek->keylen; - c->algo = dek->algo; - make_session_key( c ); - /*log_hexdump( "thekey", c->key, c->keylen );*/ - - buf[0] = c->algo; - memcpy( buf + 1, c->key, c->keylen ); - - hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); - cipher_setkey( hd, dek->key, dek->keylen ); - cipher_setiv( hd, NULL, 0 ); - cipher_encrypt( hd, buf, buf, c->keylen + 1 ); - cipher_close( hd ); - - memcpy( enckey, buf, c->keylen + 1 ); - memset( buf, 0, 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) -{ - /* --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. */ - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_AES,NULL)==CIPHER_ALGO_AES) - return 1; - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_AES192,NULL)==CIPHER_ALGO_AES192) - return 1; - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_AES256,NULL)==CIPHER_ALGO_AES256) - return 1; - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_TWOFISH,NULL)==CIPHER_ALGO_TWOFISH) - return 1; - - /* Last try. Use MDC for the modern ciphers. */ - - if(cipher_get_blocksize(algo)!=8) - return 1; - - return 0; /* No MDC */ -} - -static int -encode_simple( const char *filename, int mode, int compat ) -{ - IOBUF 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; - int do_compress = opt.compress && !opt.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)) ) { - log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]", - strerror(errno) ); - return G10ERR_OPEN_FILE; - } - - 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 ( opt.rfc1991 && !compat ) - compat = 1; - - cfx.dek = NULL; - if( mode ) { - s2k = m_alloc_clear( sizeof *s2k ); - s2k->mode = opt.rfc1991? 0:opt.s2k_mode; - s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo - : opt.s2k_digest_algo; - cfx.dek = passphrase_to_dek( NULL, 0, - opt.def_cipher_algo ? opt.def_cipher_algo - : opt.s2k_cipher_algo , s2k, 2, NULL ); - if( !cfx.dek || !cfx.dek->keylen ) { - rc = G10ERR_PASSPHRASE; - m_free(cfx.dek); - m_free(s2k); - iobuf_close(inp); - log_error(_("error creating passphrase: %s\n"), g10_errstr(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 = cipher_get_keylen( opt.def_cipher_algo ? - opt.def_cipher_algo: - opt.s2k_cipher_algo ) / 8; - encode_sesskey( cfx.dek, &dek, enckey ); - m_free( 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); - m_free(cfx.dek); - m_free(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 && !opt.rfc1991 ) { - PKT_symkey_enc *enc = m_alloc_clear( 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", g10_errstr(rc) ); - m_free(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 ); - pt = m_alloc( sizeof *pt + strlen(s) - 1 ); - pt->namelen = strlen(s); - memcpy(pt->name, s, pt->namelen ); - m_free(s); - } - else { /* no filename */ - pt = m_alloc( 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 && !opt.textmode ) { - if( !(filesize = iobuf_get_filelength(inp)) ) - log_info(_("%s: WARNING: empty file\n"), filename ); - /* we can't yet encode the length of very large files, - * so we switch to partial lengthn encoding in this case */ - if ( filesize >= IOBUF_FILELENGTH_LIMIT ) - 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 && !opt.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=opt.def_compress_algo; - if(zfx.algo==-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", g10_errstr(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 (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", g10_errstr(rc) ); - break; - } - memset(copy_buffer, 0, 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); - m_free(cfx.dek); - m_free(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 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; - PK_LIST pk_list,work_list; - int do_compress = opt.compress && !opt.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(opt.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")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; - break; - } - } - - /* prepare iobufs */ - if( !(inp = iobuf_open(filename)) ) { - log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]", - strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; - } - else if( opt.verbose ) - log_info(_("reading from `%s'\n"), filename? filename: "[stdin]"); - - 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 = m_alloc_secure_clear (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( opt.pgp2 ) { - log_info(_("unable to use the IDEA cipher for all of the keys " - "you are encrypting to.\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; - } - } - } - 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"), - cipher_algo_to_string(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_hexdump("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 ); - pt = m_alloc( sizeof *pt + strlen(s) - 1 ); - pt->namelen = strlen(s); - memcpy(pt->name, s, pt->namelen ); - m_free(s); - } - else { /* no filename */ - pt = m_alloc( sizeof *pt - 1 ); - pt->namelen = 0; - } - } - - if( filename && !opt.textmode ) { - if( !(filesize = iobuf_get_filelength(inp)) ) - log_info(_("%s: WARNING: empty file\n"), filename ); - /* we can't yet encode the length of very large files, - * so we switch to partial length encoding in this case */ - if ( filesize >= IOBUF_FILELENGTH_LIMIT ) - 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 && !opt.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; - } - 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", g10_errstr(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 (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", - g10_errstr(rc) ); - break; - } - memset(copy_buffer, 0, 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); - m_free(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 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 = m_alloc_secure_clear( 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"), - cipher_algo_to_string(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_hexdump("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 out ) -{ - PACKET pkt; - PKT_public_key *pk; - PKT_pubkey_enc *enc; - int rc; - - for( ; pk_list; pk_list = pk_list->next ) { - MPI frame; - - pk = pk_list->pk; - - print_pubkey_algo_note( pk->pubkey_algo ); - enc = m_alloc_clear( sizeof *enc ); - enc->pubkey_algo = pk->pubkey_algo; - keyid_from_pk( pk, enc->keyid ); - enc->throw_keyid = opt.throw_keyid; - - if(opt.throw_keyid && (opt.pgp2 || opt.pgp6 || opt.pgp7)) - { - log_info(_("you may not use %s while in %s mode\n"), - "--throw-keyid", - opt.pgp2?"--pgp2":opt.pgp6?"--pgp6":"--pgp7"); - - log_info(_("this message may not be usable by %s\n"), - opt.pgp2?"PGP 2.x":opt.pgp6?"PGP 6.x":"PGP 7.x"); - - opt.pgp2=opt.pgp6=opt.pgp7=0; - } - - /* 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 = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey ); - mpi_free( frame ); - if( rc ) - log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) ); - else { - if( opt.verbose ) { - char *ustr = get_user_id_string_printable (enc->keyid); - log_info(_("%s/%s encrypted for: \"%s\"\n"), - pubkey_algo_to_string(enc->pubkey_algo), - cipher_algo_to_string(dek->algo), ustr ); - m_free(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", g10_errstr(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), g10_errstr(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), g10_errstr(rc) ); - write_status( STATUS_FILE_DONE ); - files++; - } - } -} diff --git a/g10/exec.c b/g10/exec.c deleted file mode 100644 index f220dd30f..000000000 --- a/g10/exec.c +++ /dev/null @@ -1,617 +0,0 @@ -/* exec.c - generic call-a-program code - * 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 -#include -#include -#include -#include -#include -#ifndef EXEC_TEMPFILE_ONLY -#include -#endif -#ifdef HAVE_DOSISH_SYSTEM -#include -#endif -#include -#include -#include -#include -#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 G10ERR_GENERAL; -} - -int exec_read(struct exec_info *info) { return G10ERR_GENERAL; } -int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; } -int set_exec_path(const char *path,int method) { return G10ERR_GENERAL; } - -#else /* ! NO_EXEC */ - -#ifndef HAVE_MKDTEMP -char *mkdtemp(char *template); -#endif - -#if defined (__MINGW32__) || defined (__CYGWIN32__) -/* 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=m_strdup(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); - m_free(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=m_alloc(5+curlen+strlen(path)+1); - strcpy(p,"PATH="); - - if(curpath) - { - strcat(p,curpath); - strcat(p,":"); - } - - strcat(p,path); - - /* 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 G10ERR_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 (__MINGW32__) || defined (__CYGWIN32__) - tmp=m_alloc(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=".GnuPG"; - mkdir(tmp,0700); /* Error checks occur later on */ -#else - tmp="/tmp"; -#endif - } - } -#endif - } - - info->tempdir=m_alloc(strlen(tmp)+strlen(DIRSEP_S)+10+1); - - sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); - -#if defined (__MINGW32__) || defined (__CYGWIN32__) - m_free(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=m_alloc(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=m_alloc(strlen(info->tempdir)+ - strlen(DIRSEP_S)+strlen(nameout)+1); - sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout); - } - } - - return info->madedir?0:G10ERR_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=m_alloc(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=m_realloc(info->command,size); - } - - strcat(info->command,append); - len+=strlen(append); - } - } - else - { - if(len==size-1) /* leave room for the \0 */ - { - size+=100; - info->command=m_realloc(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: - - m_free(info->command); - info->command=NULL; - - return G10ERR_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=G10ERR_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=m_alloc_clear(sizeof(struct exec_info)); - - if(name) - (*info)->name=m_strdup(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,NULL); - } - else - { - if(DBG_EXTPROG) - log_debug("execlp: %s -c %s\n",shell,(*info)->command); - - execlp(shell,shell,"-c",(*info)->command,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) - { - close(to[1]); - ret=G10ERR_WRITE_FILE; - goto fail; - } - - close(from[1]); - - (*info)->fromchild=iobuf_fdopen(from[0],"r"); - if((*info)->fromchild==NULL) - { - close(from[0]); - ret=G10ERR_READ_FILE; - 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) - { - log_error(_("can't create `%s': %s\n"), - (*info)->tempfile_in,strerror(errno)); - ret=G10ERR_WRITE_FILE; - goto fail; - } - - ret=0; - - fail: - return ret; -} - -int exec_read(struct exec_info *info) -{ - int ret=G10ERR_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 (__MINGW32__) || defined (__CYGWIN32__) - 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) - { - log_error(_("unable to read external program response: %s\n"), - strerror(errno)); - ret=G10ERR_READ_FILE; - 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)); - } - - m_free(info->command); - m_free(info->name); - m_free(info->tempdir); - m_free(info->tempfile_in); - m_free(info->tempfile_out); - m_free(info); - - return ret; -} -#endif /* ! NO_EXEC */ - diff --git a/g10/exec.h b/g10/exec.h deleted file mode 100644 index 427f25810..000000000 --- a/g10/exec.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _EXEC_H_ -#define _EXEC_H_ - -#include -#include -#include "iobuf.h" - -struct exec_info -{ - int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files; - pid_t child; - FILE *tochild; - IOBUF 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_ */ diff --git a/g10/export.c b/g10/export.c deleted file mode 100644 index 5f6eadcd5..000000000 --- a/g10/export.c +++ /dev/null @@ -1,350 +0,0 @@ -/* export.c - * 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 -#include -#include -#include -#include -#include - -#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 out, STRLIST users, - int secret, unsigned int options, int *any ); - -int -parse_export_options(char *str,unsigned int *options) -{ - char *tok; - int hit=0; - struct - { - char *name; - unsigned int bit; - } 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}, - {NULL,0} - /* add tags for include revoked and disabled? */ - }; - - while((tok=strsep(&str," ,"))) - { - int i,rev=0; - - if(ascii_strncasecmp("no-",tok,3)==0) - { - rev=1; - tok+=3; - } - - for(i=0;export_opts[i].name;i++) - { - if(ascii_strcasecmp(export_opts[i].name,tok)==0) - { - if(rev) - *options&=~export_opts[i].bit; - else - *options|=export_opts[i].bit; - hit=1; - break; - } - } - - if(!hit && !export_opts[i].name) - return 0; - } - - return hit; -} - -/**************** - * 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 out, STRLIST users, unsigned int options ) -{ - int any, rc; - - rc = do_export_stream( out, users, 0, options, &any ); - if( !rc && !any ) - rc = -1; - return rc; -} - -int -export_seckeys( STRLIST users ) -{ - return do_export( users, 1, 0 ); -} - -int -export_secsubkeys( STRLIST users ) -{ - return do_export( users, 2, 0 ); -} - -static int -do_export( STRLIST users, int secret, unsigned int options ) -{ - IOBUF 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( 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, options, &any ); - - if( rc || !any ) - iobuf_cancel(out); - else - iobuf_close(out); - return rc; -} - - -static int -do_export_stream( IOBUF out, STRLIST users, int secret, - unsigned int options, int *any ) -{ - int rc = 0; - PACKET pkt; - KBNODE keyblock = NULL; - KBNODE kbctx, node; - int ndesc; - KEYDB_SEARCH_DESC *desc = NULL; - KEYDB_HANDLE kdbhd; - STRLIST sl; - - *any = 0; - init_packet( &pkt ); - kdbhd = keydb_new (secret); - - if (!users) { - ndesc = 1; - desc = m_alloc_clear ( ndesc * sizeof *desc); - desc[0].mode = KEYDB_SEARCH_MODE_FIRST; - } - else { - for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) - ; - desc = m_alloc ( 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, g10_errstr (G10ERR_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_search (kdbhd, desc, ndesc))) { - int sha1_warned=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"), g10_errstr(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 )); ) { - /* 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( 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;ipkt->pkt.signature->numrevkeys;i++) - if(node->pkt->pkt.signature->revkey[i]->class & 0x40) - break; - - if(ipkt->pkt.signature->numrevkeys) - continue; - } - - /* delete our verification cache */ - delete_sig_subpkt (node->pkt->pkt.signature->unhashed, - SIGSUBPKT_PRIV_VERIFY_CACHE); - } - - /* 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; - 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; - } - - rc = build_packet( out, node->pkt ); - } - - if( rc ) { - log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - rc = G10ERR_WRITE_FILE; - goto leave; - } - } - ++*any; - } - if( rc == -1 ) - rc = 0; - - leave: - m_free(desc); - keydb_release (kdbhd); - release_kbnode( keyblock ); - if( !*any ) - log_info(_("WARNING: nothing exported\n")); - return rc; -} - diff --git a/g10/filter.h b/g10/filter.h deleted file mode 100644 index c933d2383..000000000 --- a/g10/filter.h +++ /dev/null @@ -1,142 +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" - -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; - - -/* encrypt_filter_context_t defined in main.h */ - -/*-- mdfilter.c --*/ -int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); -void free_md_filter_context( md_filter_context_t *mfx ); - -/*-- armor.c --*/ -int use_armor_filter( IOBUF a ); -int armor_filter( void *opaque, int control, - IOBUF 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 chain, byte *buf, size_t *ret_len); - -/*-- cipher.c --*/ -int cipher_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); - -/*-- textfilter.c --*/ -int text_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); -int copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, - int escape_dash, int escape_from, int pgp2mode ); - - - -#endif /*G10_FILTER_H*/ diff --git a/g10/free-packet.c b/g10/free-packet.c deleted file mode 100644 index e760999be..000000000 --- a/g10/free-packet.c +++ /dev/null @@ -1,547 +0,0 @@ -/* free-packet.c - cleanup stuff for packets - * 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 -#include -#include -#include -#include - -#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 ) -{ - m_free(enc); -} - -void -free_pubkey_enc( PKT_pubkey_enc *enc ) -{ - int n, i; - n = pubkey_get_nenc( enc->pubkey_algo ); - if( !n ) - mpi_free(enc->data[0]); - for(i=0; i < n; i++ ) - mpi_free( enc->data[i] ); - m_free(enc); -} - -void -free_seckey_enc( PKT_signature *sig ) -{ - int n, i; - - n = pubkey_get_nsig( sig->pubkey_algo ); - if( !n ) - mpi_free(sig->data[0]); - for(i=0; i < n; i++ ) - mpi_free( sig->data[i] ); - - m_free(sig->revkey); - m_free(sig->hashed); - m_free(sig->unhashed); - m_free(sig); -} - - - -void -release_public_key_parts( PKT_public_key *pk ) -{ - int n, i; - n = pubkey_get_npkey( pk->pubkey_algo ); - if( !n ) - mpi_free(pk->pkey[0]); - for(i=0; i < n; i++ ) { - mpi_free( pk->pkey[i] ); - pk->pkey[i] = NULL; - } - if (pk->prefs) { - m_free (pk->prefs); - pk->prefs = NULL; - } - if( pk->namehash ) { - m_free(pk->namehash); - pk->namehash = NULL; - } - if (pk->user_id) { - free_user_id (pk->user_id); - pk->user_id = NULL; - } - if (pk->revkey) { - m_free(pk->revkey); - pk->revkey=NULL; - pk->numrevkeys=0; - } -} - - -void -free_public_key( PKT_public_key *pk ) -{ - release_public_key_parts( pk ); - m_free(pk); -} - - -static subpktarea_t * -cp_subpktarea (subpktarea_t *s ) -{ - subpktarea_t *d; - - if( !s ) - return NULL; - d = m_alloc (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 = m_alloc ( 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 = m_alloc(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 = m_alloc(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 = m_alloc(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_free(sk->skey[0]); - for(i=0; i < n; i++ ) { - mpi_free( sk->skey[i] ); - sk->skey[i] = NULL; - } -} - -void -free_secret_key( PKT_secret_key *sk ) -{ - release_secret_key_parts( sk ); - m_free(sk); -} - -PKT_secret_key * -copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ) -{ - int n, i; - - if( !d ) - d = m_alloc(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 ) -{ - m_free(rem); -} - -void -free_attributes(PKT_user_id *uid) -{ - m_free(uid->attribs); - m_free(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); - - if (uid->prefs) - m_free (uid->prefs); - m_free (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 ) - ; - } - m_free(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; - } - } - } - m_free(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; - } - } - } - m_free(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: - m_free( 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; -} diff --git a/g10/g10.c b/g10/g10.c deleted file mode 100644 index c2e095bf9..000000000 --- a/g10/g10.c +++ /dev/null @@ -1,2816 +0,0 @@ -/* g10.c - The GnuPG utility (main for gpg) - * 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 -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM - #include /* for setmode() */ -#endif -#ifdef HAVE_STAT -#include /* for stat() */ -#endif - -#define INCLUDED_BY_MAIN_MODULE 1 -#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" -#include "g10defs.h" -#include "keyserver-internal.h" -#include "exec.h" - -enum cmd_and_opt_values { aNull = 0, - oArmor = 'a', - aDetachedSign = 'b', - aSym = 'c', - aDecrypt = 'd', - aEncr = 'e', - aEncrFiles, - oInteractive = 'i', - oKOption = 'k', - oDryRun = 'n', - oOutput = 'o', - oQuiet = 'q', - oRecipient = 'r', - aSign = 's', - oTextmodeShort= 't', - oUser = 'u', - oVerbose = 'v', - oCompress = 'z', - oNotation = 'N', - oBatch = 500, - oSigNotation, - oCertNotation, - oShowNotation, - oNoShowNotation, - aDecryptFiles, - aClearsign, - aStore, - aKeygen, - aSignEncr, - aSignSym, - aSignKey, - aLSignKey, - aNRSignKey, - aNRLSignKey, - aListPackets, - aEditKey, - aDeleteKeys, - aDeleteSecretKeys, - aDeleteSecretAndPublicKeys, - aKMode, - aKModeC, - aImport, - aFastImport, - aVerify, - aVerifyFiles, - aListKeys, - aListSigs, - aListSecretKeys, - aSendKeys, - aRecvKeys, - aSearchKeys, - aExport, - aExportAll, - aExportSecret, - aExportSecretSub, - aCheckKeys, - aGenRevoke, - aDesigRevoke, - aPrimegen, - aPrintMD, - aPrintMDs, - aCheckTrustDB, - aUpdateTrustDB, - aFixTrustDB, - aListTrustDB, - aListTrustPath, - aExportOwnerTrust, - aImportOwnerTrust, - aDeArmor, - aEnArmor, - aGenRandom, - aPipeMode, - aRebuildKeydbCaches, - aRefreshKeys, - - oTextmode, - oExpert, - oNoExpert, - oAskSigExpire, - oNoAskSigExpire, - oAskCertExpire, - oNoAskCertExpire, - oFingerprint, - oWithFingerprint, - oAnswerYes, - oAnswerNo, - oDefCertCheckLevel, - oKeyring, - oSecretKeyring, - oShowKeyring, - oDefaultKey, - oDefRecipient, - oDefRecipientSelf, - oNoDefRecipient, - oOptions, - oDebug, - oDebugAll, - oStatusFD, -#ifdef __riscos__ - oStatusFile, -#endif /* __riscos__ */ - oAttributeFD, -#ifdef __riscos__ - oAttributeFile, -#endif /* __riscos__ */ - oSKComments, - oNoSKComments, - oNoVersion, - oEmitVersion, - oCompletesNeeded, - oMarginalsNeeded, - oMaxCertDepth, - oLoadExtension, - oRFC1991, - oOpenPGP, - oPGP2, - oNoPGP2, - oPGP6, - oNoPGP6, - oPGP7, - oNoPGP7, - oCipherAlgo, - oDigestAlgo, - oCertDigestAlgo, - oCompressAlgo, - oPasswdFD, -#ifdef __riscos__ - oPasswdFile, -#endif /* __riscos__ */ - oCommandFD, -#ifdef __riscos__ - oCommandFile, -#endif /* __riscos__ */ - oQuickRandom, - oNoVerbose, - oTrustDBName, - oNoSecmemWarn, - oNoPermissionWarn, - oNoMDCWarn, - oNoArmor, - oNoDefKeyring, - oNoGreeting, - oNoTTY, - oNoOptions, - oNoBatch, - oHomedir, - oWithColons, - oWithKeyData, - oSkipVerify, - oCompressKeys, - oCompressSigs, - oAlwaysTrust, - oEmuChecksumBug, - oRunAsShmCP, - oSetFilename, - oForYourEyesOnly, - oNoForYourEyesOnly, - oSetPolicyURL, - oSigPolicyURL, - oCertPolicyURL, - oShowPolicyURL, - oNoShowPolicyURL, - oUseEmbeddedFilename, - oComment, - oDefaultComment, - oThrowKeyid, - oShowPhotos, - oNoShowPhotos, - oPhotoViewer, - oForceV3Sigs, - oNoForceV3Sigs, - oForceV4Certs, - oNoForceV4Certs, - oForceMDC, - oNoForceMDC, - oDisableMDC, - oNoDisableMDC, - oS2KMode, - oS2KDigest, - oS2KCipher, - oSimpleSKChecksum, - oCharset, - oNotDashEscaped, - oEscapeFrom, - oNoEscapeFrom, - oLockOnce, - oLockMultiple, - oLockNever, - oKeyServer, - oKeyServerOptions, - oImportOptions, - oExportOptions, - oTempDir, - oExecPath, - oEncryptTo, - oNoEncryptTo, - oLoggerFD, -#ifdef __riscos__ - oLoggerFile, -#endif /* __riscos__ */ - oUtf8Strings, - oNoUtf8Strings, - oDisableCipherAlgo, - oDisablePubkeyAlgo, - oAllowNonSelfsignedUID, - oNoAllowNonSelfsignedUID, - oAllowFreeformUID, - oNoAllowFreeformUID, - oAllowSecretKeyImport, - oEnableSpecialFilenames, - oNoLiteral, - oSetFilesize, - oHonorHttpProxy, - oFastListMode, - oListOnly, - oIgnoreTimeConflict, - oIgnoreValidFrom, - oIgnoreCrcError, - oIgnoreMDCError, - oShowSessionKey, - oOverrideSessionKey, - oNoRandomSeedFile, - oAutoKeyRetrieve, - oNoAutoKeyRetrieve, - oUseAgent, - oNoUseAgent, - oGpgAgentInfo, - oMergeOnly, - oTryAllSecrets, - oTrustedKey, - oNoExpensiveTrustChecks, - oFixedListMode, - oNoSigCache, - oNoSigCreateCheck, - oAutoCheckTrustDB, - oNoAutoCheckTrustDB, - oPreservePermissions, - oDefaultPreferenceList, - oPersonalCipherPreferences, - oPersonalDigestPreferences, - oPersonalCompressPreferences, - oEmuMDEncodeBug, - oDisplay, - oTTYname, - oTTYtype, - oLCctype, - oLCmessages, - oGroup, - oStrict, - oNoStrict, -aTest }; - - -static ARGPARSE_OPTS opts[] = { - - { 300, NULL, 0, N_("@Commands:\n ") }, - - { aSign, "sign", 256, N_("|[file]|make a signature")}, - { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, - { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, - { aEncr, "encrypt", 256, N_("encrypt data")}, - { aEncrFiles, "encrypt-files", 256, N_("|[files]|encrypt files")}, - { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, - { aStore, "store", 256, N_("store only")}, - { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, - { aDecryptFiles, "decrypt-files", 256, N_("|[files]|decrypt files")}, - { aVerify, "verify" , 256, N_("verify a signature")}, - { aVerifyFiles, "verify-files" , 256, "@" }, - { aListKeys, "list-keys", 256, N_("list keys")}, - { aListKeys, "list-public-keys", 256, "@" }, - { aListSigs, "list-sigs", 256, N_("list keys and signatures")}, - { aCheckKeys, "check-sigs",256, N_("check key signatures")}, - { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, - { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, - { aKeygen, "gen-key", 256, N_("generate a new key pair")}, - { aDeleteKeys,"delete-keys",256,N_("remove keys from the public keyring")}, - { aDeleteSecretKeys, "delete-secret-keys",256, - N_("remove keys from the secret keyring")}, - { aSignKey, "sign-key" ,256, N_("sign a key")}, - { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, - { aNRSignKey, "nrsign-key" ,256, N_("sign a key non-revocably")}, - { aNRLSignKey, "nrlsign-key" ,256, N_("sign a key locally and non-revocably")}, - { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, - { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, - { aDesigRevoke, "desig-revoke",256, "@" }, - { aExport, "export" , 256, N_("export keys") }, - { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, - { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, - { aSearchKeys, "search-keys" , 256, - N_("search for keys on a key server") }, - { aRefreshKeys, "refresh-keys", 256, - N_("update all keys from a keyserver")}, - { aExportAll, "export-all" , 256, "@" }, - { aExportSecret, "export-secret-keys" , 256, "@" }, - { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, - { aImport, "import", 256 , N_("import/merge keys")}, - { aFastImport, "fast-import", 256 , "@"}, - { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, - { aExportOwnerTrust, - "export-ownertrust", 256, N_("export the ownertrust values")}, - { aImportOwnerTrust, - "import-ownertrust", 256 , N_("import ownertrust values")}, - { aUpdateTrustDB, - "update-trustdb",0 , N_("update the trust database")}, - { aCheckTrustDB, - "check-trustdb",0 , N_("unattended trust database update")}, - { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, - { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") }, - { aDeArmor, "dearmour", 256, "@" }, - { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") }, - { aEnArmor, "enarmour", 256, "@" }, - { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, - { aPrimegen, "gen-prime" , 256, "@" }, - { aGenRandom, "gen-random" , 256, "@" }, - - { 301, NULL, 0, N_("@\nOptions:\n ") }, - - { oArmor, "armor", 0, N_("create ascii armored output")}, - { oArmor, "armour", 0, "@" }, - { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, - { oRecipient, "remote-user", 2, "@"}, /* old option name */ - { oDefRecipient, "default-recipient" ,2, - N_("|NAME|use NAME as default recipient")}, - { oDefRecipientSelf, "default-recipient-self" ,0, - N_("use the default key as default recipient")}, - { oNoDefRecipient, "no-default-recipient", 0, "@" }, - { oTempDir, "temp-directory", 2, "@" }, - { oExecPath, "exec-path", 2, "@" }, - { oEncryptTo, "encrypt-to", 2, "@" }, - { oNoEncryptTo, "no-encrypt-to", 0, "@" }, - { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, - { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, - { oTextmodeShort, NULL, 0, "@"}, - { oTextmode, "textmode", 0, N_("use canonical text mode")}, - { oExpert, "expert", 0, "@"}, - { oNoExpert, "no-expert", 0, "@"}, - { oAskSigExpire, "ask-sig-expire", 0, "@"}, - { oNoAskSigExpire, "no-ask-sig-expire", 0, "@"}, - { oAskCertExpire, "ask-cert-expire", 0, "@"}, - { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, - { oOutput, "output", 2, N_("use as output file")}, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, - { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, - { oNoForceV3Sigs, "no-force-v3-sigs", 0, N_("do not force v3 signatures") }, - { oForceV4Certs, "force-v4-certs", 0, N_("force v4 key signatures") }, - { oNoForceV4Certs, "no-force-v4-certs", 0, N_("do not force v4 key signatures") }, - { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, - { oNoForceMDC, "no-force-mdc", 0, "@" }, - { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") }, - { oNoDisableMDC, "no-disable-mdc", 0, "@" }, - { oDryRun, "dry-run", 0, N_("do not make any changes") }, - { oInteractive, "interactive", 0, N_("prompt before overwriting") }, - { oUseAgent, "use-agent",0, N_("use the gpg-agent")}, - { oNoUseAgent, "no-use-agent",0, "@"}, - { oGpgAgentInfo, "gpg-agent-info",2, "@"}, - { oBatch, "batch", 0, N_("batch mode: never ask")}, - { oAnswerYes, "yes", 0, N_("assume yes on most questions")}, - { oAnswerNo, "no", 0, N_("assume no on most questions")}, - { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, - { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, - { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")}, - { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, - { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, - { oKeyServerOptions, "keyserver-options",2,"@"}, - { oImportOptions, "import-options",2,"@"}, - { oExportOptions, "export-options",2,"@"}, - { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, - { oOptions, "options" , 2, N_("read options from file")}, - - { oDebug, "debug" ,4|16, "@"}, - { oDebugAll, "debug-all" ,0, "@"}, - { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, -#ifdef __riscos__ - { oStatusFile, "status-file" ,2, N_("|[file]|write status info to file") }, -#endif /* __riscos__ */ - { oAttributeFD, "attribute-fd" ,1, "@" }, -#ifdef __riscos__ - { oAttributeFile, "attribute-file" ,2, "@" }, -#endif /* __riscos__ */ - { oNoSKComments, "no-comment", 0, "@"}, - { oNoSKComments, "no-sk-comments", 0, "@"}, - { oSKComments, "sk-comments", 0, "@"}, - { oCompletesNeeded, "completes-needed", 1, "@"}, - { oMarginalsNeeded, "marginals-needed", 1, "@"}, - { oMaxCertDepth, "max-cert-depth", 1, "@" }, - { oTrustedKey, "trusted-key", 2, N_("|KEYID|ultimately trust this key")}, - { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")}, - { oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")}, - { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")}, - { oPGP2, "pgp2", 0, N_("set all packet, cipher and digest options to PGP 2.x behavior")}, - { oNoPGP2, "no-pgp2", 0, "@"}, - { oPGP6, "pgp6", 0, "@"}, - { oNoPGP6, "no-pgp6", 0, "@"}, - { oPGP7, "pgp7", 0, "@"}, - { oNoPGP7, "no-pgp7", 0, "@"}, - { oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")}, - { oS2KDigest, "s2k-digest-algo",2, - N_("|NAME|use message digest algorithm NAME for passphrases")}, - { oS2KCipher, "s2k-cipher-algo",2, - N_("|NAME|use cipher algorithm NAME for passphrases")}, - { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, - { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, - { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")}, - { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, - { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")}, - { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")}, - { oShowPhotos, "show-photos", 0, N_("Show Photo IDs")}, - { oNoShowPhotos, "no-show-photos", 0, N_("Don't show Photo IDs")}, - { oPhotoViewer, "photo-viewer", 2, N_("Set command line to view Photo IDs")}, - { oNotation, "notation-data", 2, "@" }, - { oSigNotation, "sig-notation", 2, "@" }, - { oCertNotation, "cert-notation", 2, "@" }, - - { 302, NULL, 0, N_( - "@\n(See the man page for a complete listing of all commands and options)\n" - )}, - - { 303, NULL, 0, N_("@\nExamples:\n\n" - " -se -r Bob [file] sign and encrypt for user Bob\n" - " --clearsign [file] make a clear text signature\n" - " --detach-sign [file] make a detached signature\n" - " --list-keys [names] show keys\n" - " --fingerprint [names] show fingerprints\n" ) }, - - /* hidden options */ - { aExportOwnerTrust, "list-ownertrust",0 , "@"}, /* alias */ - { aPrintMDs, "print-mds" , 256, "@"}, /* old */ - { aListTrustDB, "list-trustdb",0 , "@"}, - { aListTrustPath, "list-trust-path",0, "@"}, - { aPipeMode, "pipemode", 0, "@" }, - { oKOption, NULL, 0, "@"}, - { oPasswdFD, "passphrase-fd",1, "@" }, -#ifdef __riscos__ - { oPasswdFile, "passphrase-file",2, "@" }, -#endif /* __riscos__ */ - { oCommandFD, "command-fd",1, "@" }, -#ifdef __riscos__ - { oCommandFile, "command-file",2, "@" }, -#endif /* __riscos__ */ - { oQuickRandom, "quick-random", 0, "@"}, - { oNoVerbose, "no-verbose", 0, "@"}, - { oTrustDBName, "trustdb-name", 2, "@" }, - { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */ - { oNoPermissionWarn, "no-permission-warning", 0, "@" }, - { oNoMDCWarn, "no-mdc-warning", 0, "@" }, - { oNoArmor, "no-armor", 0, "@"}, - { oNoArmor, "no-armour", 0, "@"}, - { oNoDefKeyring, "no-default-keyring", 0, "@" }, - { oNoGreeting, "no-greeting", 0, "@" }, - { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */ - { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ - { oNoBatch, "no-batch", 0, "@" }, - { oWithColons, "with-colons", 0, "@"}, - { oWithKeyData,"with-key-data", 0, "@"}, - { aListKeys, "list-key", 0, "@" }, /* alias */ - { aListSigs, "list-sig", 0, "@" }, /* alias */ - { aCheckKeys, "check-sig",0, "@" }, /* alias */ - { oSkipVerify, "skip-verify",0, "@" }, - { oCompressKeys, "compress-keys",0, "@"}, - { oCompressSigs, "compress-sigs",0, "@"}, - { oDefCertCheckLevel, "default-cert-check-level", 1, "@"}, - { oAlwaysTrust, "always-trust", 0, "@"}, - { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"}, - { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" }, - { oSetFilename, "set-filename", 2, "@" }, - { oForYourEyesOnly, "for-your-eyes-only", 0, "@" }, - { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" }, - { oSetPolicyURL, "set-policy-url", 2, "@" }, - { oSigPolicyURL, "sig-policy-url", 2, "@" }, - { oCertPolicyURL, "cert-policy-url", 2, "@" }, - { oShowPolicyURL, "show-policy-url", 0, "@" }, - { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, - { oShowNotation, "show-notation", 0, "@" }, - { oNoShowNotation, "no-show-notation", 0, "@" }, - { oComment, "comment", 2, "@" }, - { oDefaultComment, "default-comment", 0, "@" }, - { oNoVersion, "no-version", 0, "@"}, - { oEmitVersion, "emit-version", 0, "@"}, - { oNotDashEscaped, "not-dash-escaped", 0, "@" }, - { oEscapeFrom, "escape-from-lines", 0, "@" }, - { oNoEscapeFrom, "no-escape-from-lines", 0, "@" }, - { oLockOnce, "lock-once", 0, "@" }, - { oLockMultiple, "lock-multiple", 0, "@" }, - { oLockNever, "lock-never", 0, "@" }, - { oLoggerFD, "logger-fd",1, "@" }, -#ifdef __riscos__ - { oLoggerFile, "logger-file",2, "@" }, -#endif /* __riscos__ */ - { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" }, - { oUtf8Strings, "utf8-strings", 0, "@" }, - { oNoUtf8Strings, "no-utf8-strings", 0, "@" }, - { oWithFingerprint, "with-fingerprint", 0, "@" }, - { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, - { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, - { oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" }, - { oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", 0, "@" }, - { oAllowFreeformUID, "allow-freeform-uid", 0, "@" }, - { oNoAllowFreeformUID, "no-allow-freeform-uid", 0, "@" }, - { oNoLiteral, "no-literal", 0, "@" }, - { oSetFilesize, "set-filesize", 20, "@" }, - { oHonorHttpProxy,"honor-http-proxy", 0, "@" }, - { oFastListMode,"fast-list-mode", 0, "@" }, - { oFixedListMode,"fixed-list-mode", 0, "@" }, - { oListOnly, "list-only", 0, "@"}, - { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, - { oIgnoreValidFrom, "ignore-valid-from", 0, "@" }, - { oIgnoreCrcError, "ignore-crc-error", 0,"@" }, - { oIgnoreMDCError, "ignore-mdc-error", 0,"@" }, - { oShowSessionKey, "show-session-key", 0, "@" }, - { oOverrideSessionKey, "override-session-key", 2, "@" }, - { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, - { oAutoKeyRetrieve, "auto-key-retrieve", 0, "@" }, - { oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" }, - { oNoSigCache, "no-sig-cache", 0, "@" }, - { oNoSigCreateCheck, "no-sig-create-check", 0, "@" }, - { oAutoCheckTrustDB, "auto-check-trustdb", 0, "@"}, - { oNoAutoCheckTrustDB, "no-auto-check-trustdb", 0, "@"}, - { oMergeOnly, "merge-only", 0, "@" }, - { oAllowSecretKeyImport, "allow-secret-key-import", 0, "@" }, - { oTryAllSecrets, "try-all-secrets", 0, "@" }, - { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" }, - { oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" }, - { aDeleteSecretAndPublicKeys, "delete-secret-and-public-keys",256, "@" }, - { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"}, - { oPreservePermissions, "preserve-permissions", 0, "@"}, - { oDefaultPreferenceList, "default-preference-list", 2, "@"}, - { oPersonalCipherPreferences, "personal-cipher-preferences", 2, "@"}, - { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, - { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, - { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, - { oDisplay, "display", 2, "@" }, - { oTTYname, "ttyname", 2, "@" }, - { oTTYtype, "ttytype", 2, "@" }, - { oLCctype, "lc-ctype", 2, "@" }, - { oLCmessages, "lc-messages", 2, "@" }, - { oGroup, "group", 2, "@" }, - { oStrict, "strict", 0, "@" }, - { oNoStrict, "no-strict", 0, "@" }, -{0} }; - - - -int g10_errors_seen = 0; - -static int utf8_strings = 0; -static int maybe_setuid = 1; - -static char *build_list( const char *text, char letter, - const char *(*mapf)(int), int (*chkf)(int) ); -static void set_cmd( enum cmd_and_opt_values *ret_cmd, - enum cmd_and_opt_values new_cmd ); -static void print_hex( byte *p, size_t n ); -static void print_mds( const char *fname, int algo ); -static void add_notation_data( const char *string, int which ); -static void add_policy_url( const char *string, int which ); - -#ifdef __riscos__ -RISCOS_GLOBAL_STATICS("GnuPG Heap") -#endif /* __riscos__ */ - -const char * -strusage( int level ) -{ - static char *digests, *pubkeys, *ciphers, *zips; - const char *p; - switch( level ) { - case 11: p = "gpg (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = - _("Please report bugs to .\n"); - break; - case 1: - case 40: p = - _("Usage: gpg [options] [files] (-h for help)"); - break; - case 41: p = - _("Syntax: gpg [options] [files]\n" - "sign, check, encrypt or decrypt\n" - "default operation depends on the input data\n"); - break; - - case 31: p = "\nHome: "; break; -#ifndef __riscos__ - case 32: p = opt.homedir; break; -#else /* __riscos__ */ - case 32: p = make_filename(opt.homedir, NULL); break; -#endif /* __riscos__ */ - case 33: p = _("\nSupported algorithms:\n"); break; - case 34: - if( !pubkeys ) - pubkeys = build_list("Pubkey: ", 0, pubkey_algo_to_string, - check_pubkey_algo ); - p = pubkeys; - break; - case 35: - if( !ciphers ) - ciphers = build_list("Cipher: ", 'S', cipher_algo_to_string, - check_cipher_algo ); - p = ciphers; - break; - case 36: - if( !digests ) - digests = build_list("Hash: ", 'H', digest_algo_to_string, - check_digest_algo ); - p = digests; - break; - case 37: - if( !zips ) - zips = build_list("Compress: ",'Z',compress_algo_to_string, - check_compress_algo); - p = zips; - break; - - default: p = default_strusage(level); - } - return p; -} - - -static char * -build_list( const char *text, char letter, - const char * (*mapf)(int), int (*chkf)(int) ) -{ - int i; - const char *s; - size_t n=strlen(text)+2; - char *list, *p, *line=NULL; - - if( maybe_setuid ) - secmem_init( 0 ); /* drop setuid */ - - for(i=0; i <= 110; i++ ) - if( !chkf(i) && (s=mapf(i)) ) - n += strlen(s) + 7 + 2; - list = m_alloc( 21 + n ); *list = 0; - for(p=NULL, i=0; i <= 110; i++ ) { - if( !chkf(i) && (s=mapf(i)) ) { - if( !p ) { - p = stpcpy( list, text ); - line=p; - } - else - p = stpcpy( p, ", "); - - if(strlen(line)>60) { - int spaces=strlen(text); - - list=m_realloc(list,n+spaces+1); - /* realloc could move the block, so find the end again */ - p=list; - while(*p) - p++; - - p=stpcpy(p, "\n"); - line=p; - for(;spaces;spaces--) - p=stpcpy(p, " "); - } - - p = stpcpy(p, s ); - if(opt.verbose && letter) - { - char num[8]; - sprintf(num," (%c%d)",letter,i); - p = stpcpy(p,num); - } - } - } - if( p ) - p = stpcpy(p, "\n" ); - return list; -} - - -static void -i18n_init(void) -{ - #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); - #else - #ifdef ENABLE_NLS - setlocale( LC_ALL, "" ); - bindtextdomain( PACKAGE, G10_LOCALEDIR ); - textdomain( PACKAGE ); - #endif - #endif -} - -static void -wrong_args( const char *text) -{ - fputs(_("usage: gpg [options] "),stderr); - fputs(text,stderr); - putc('\n',stderr); - g10_exit(2); -} - - -static char * -make_username( const char *string ) -{ - char *p; - if( utf8_strings ) - p = m_strdup(string); - else - p = native_to_utf8( string ); - return p; -} - - -static void -set_debug(void) -{ - if( opt.debug & DBG_MEMORY_VALUE ) - memory_debug_mode = 1; - if( opt.debug & DBG_MEMSTAT_VALUE ) - memory_stat_debug_mode = 1; - if( opt.debug & DBG_MPI_VALUE ) - mpi_debug_mode = 1; - if( opt.debug & DBG_CIPHER_VALUE ) - g10c_debug_mode = 1; - if( opt.debug & DBG_IOBUF_VALUE ) - iobuf_debug_mode = 1; - -} - - -/* We need the home directory also in some other directories, so make - sure that both variables are always in sync. */ -static void -set_homedir (char *dir) -{ - if (!dir) - dir = ""; - g10_opt_homedir = opt.homedir = dir; -} - - -static void -set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) -{ - enum cmd_and_opt_values cmd = *ret_cmd; - - if( !cmd || cmd == new_cmd ) - cmd = new_cmd; - else if( cmd == aSign && new_cmd == aEncr ) - cmd = aSignEncr; - else if( cmd == aEncr && new_cmd == aSign ) - cmd = aSignEncr; - else if( cmd == aSign && new_cmd == aSym ) - cmd = aSignSym; - else if( cmd == aSym && new_cmd == aSign ) - cmd = aSignSym; - else if( cmd == aKMode && new_cmd == aSym ) - cmd = aKModeC; - else if( ( cmd == aSign && new_cmd == aClearsign ) - || ( cmd == aClearsign && new_cmd == aSign ) ) - cmd = aClearsign; - else { - log_error(_("conflicting commands\n")); - g10_exit(2); - } - - *ret_cmd = cmd; -} - - -static void add_group(char *string) -{ - char *name,*value; - struct groupitem *item; - STRLIST values=NULL; - - /* Break off the group name */ - name=strsep(&string,"="); - if(string==NULL) - { - log_error(_("no = sign found in group definition \"%s\"\n"),name); - return; - } - - /* Break apart the values */ - while((value=strsep(&string," ")) && *value!='\0') - add_to_strlist2(&values,value,utf8_strings); - - item=m_alloc(sizeof(struct groupitem)); - item->name=name; - item->values=values; - item->next=opt.grouplist; - - opt.grouplist=item; -} - -/* We need to check three things. - - 0) The homedir. It must be x00, a directory, and owned by the - user. - - 1) The options file. Okay unless it or its containing directory is - group or other writable or not owned by us. disable exec in this - case. - - 2) Extensions. Same as #2. - - Returns true if the item is unsafe. */ -static int -check_permissions(const char *path,int item) -{ -#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM) - static int homedir_cache=-1; - char *tmppath,*dir; - struct stat statbuf,dirbuf; - int homedir=0,ret=0,checkonly=0; - int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0; - - if(opt.no_perm_warn) - return 0; - - assert(item==0 || item==1 || item==2); - - /* extensions may attach a path */ - if(item==2 && 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); - - /* If the item is located in the homedir, but isn't the homedir, - don't continue if we already checked the homedir itself. This is - to avoid user confusion with an extra options file warning which - could be rectified if the homedir itself had proper - permissions. */ - if(item!=0 && homedir_cache>-1 - && ascii_strncasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0) - { - ret=homedir_cache; - goto end; - } - - /* It's okay if the file or directory doesn't exist */ - if(stat(tmppath,&statbuf)!=0) - { - ret=0; - goto end; - } - - /* Now check the enclosing directory. 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,&dirbuf)!=0 || !S_ISDIR(dirbuf.st_mode)) - { - /* Weird error */ - ret=1; - goto end; - } - - m_free(dir); - - /* Assume failure */ - ret=1; - - if(item==0) - { - /* The homedir must be x00, a directory, and owned by the user. */ - - if(S_ISDIR(statbuf.st_mode)) - { - if(statbuf.st_uid==getuid()) - { - if((statbuf.st_mode & (S_IRWXG|S_IRWXO))==0) - ret=0; - else - perm=1; - } - else - own=1; - - homedir_cache=ret; - } - } - else if(item==1 || item==2) - { - /* The options or extension file. Okay unless it or its - containing directory is group or other writable or not owned - by us or root. */ - - if(S_ISREG(statbuf.st_mode)) - { - if(statbuf.st_uid==getuid() || statbuf.st_uid==0) - { - if((statbuf.st_mode & (S_IWGRP|S_IWOTH))==0) - { - /* it's not writable, so make sure the enclosing - directory is also not writable */ - if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) - { - if((dirbuf.st_mode & (S_IWGRP|S_IWOTH))==0) - ret=0; - else - enc_dir_perm=1; - } - else - enc_dir_own=1; - } - else - { - /* it's writable, so the enclosing directory had - better not let people get to it. */ - if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) - { - if((dirbuf.st_mode & (S_IRWXG|S_IRWXO))==0) - ret=0; - else - perm=enc_dir_perm=1; /* unclear which one to fix! */ - } - else - enc_dir_own=1; - } - } - else - own=1; - } - } - else - BUG(); - - if(!checkonly) - { - if(own) - { - if(item==0) - log_info(_("WARNING: unsafe ownership on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe ownership on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe ownership on " - "extension \"%s\"\n"),tmppath); - } - if(perm) - { - if(item==0) - log_info(_("WARNING: unsafe permissions on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe permissions on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe permissions on " - "extension \"%s\"\n"),tmppath); - } - if(enc_dir_own) - { - if(item==0) - log_info(_("WARNING: unsafe enclosing directory ownership on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe enclosing directory ownership on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe enclosing directory ownership on " - "extension \"%s\"\n"),tmppath); - } - if(enc_dir_perm) - { - if(item==0) - log_info(_("WARNING: unsafe enclosing directory permissions on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe enclosing directory permissions on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe enclosing directory permissions on " - "extension \"%s\"\n"),tmppath); - } - } - - end: - m_free(tmppath); - - if(homedir) - homedir_cache=ret; - - return ret; - -#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */ - - return 0; -} - -int -main( int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - IOBUF a; - int rc=0; - int orig_argc; - char **orig_argv; - const char *fname; - char *username; - int may_coredump; - STRLIST sl, remusr= NULL, locusr=NULL; - STRLIST nrings=NULL, sec_nrings=NULL; - armor_filter_context_t afx; - int detached_sig = 0; - FILE *configfp = NULL; - char *configname = NULL; - unsigned configlineno; - int parse_debug = 0; - int default_config = 1; - int default_keyring = 1; - int greeting = 0; - int nogreeting = 0; - int use_random_seed = 1; - enum cmd_and_opt_values cmd = 0; - const char *trustdb_name = NULL; - char *def_cipher_string = NULL; - char *def_digest_string = NULL; - char *cert_digest_string = NULL; - char *s2k_cipher_string = NULL; - char *s2k_digest_string = NULL; - char *pers_cipher_list = NULL; - char *pers_digest_list = NULL; - char *pers_compress_list = NULL; - int eyes_only=0; - int pwfd = -1; - int with_fpr = 0; /* make an option out of --fingerprint */ - int any_explicit_recipient = 0; - #ifdef USE_SHM_COPROCESSING - ulong requested_shm_size=0; - #endif - - #ifdef __riscos__ - riscos_global_defaults(); - opt.lock_once = 1; - #endif /* __riscos__ */ - - trap_unaligned(); - secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */ - /* Please note that we may running SUID(ROOT), so be very CAREFUL - * when adding any stuff between here and the call to - * secmem_init() somewhere after the option parsing - */ - log_set_name("gpg"); - secure_random_alloc(); /* put random number into secure memory */ - may_coredump = disable_core_dumps(); - init_signals(); - create_dotlock(NULL); /* register locking cleanup */ - i18n_init(); - opt.command_fd = -1; /* no command fd */ - opt.compress = -1; /* defaults to standard compress level */ - /* note: if you change these lines, look at oOpenPGP */ - opt.def_cipher_algo = 0; - opt.def_digest_algo = 0; - opt.cert_digest_algo = 0; - opt.def_compress_algo = -1; - opt.s2k_mode = 3; /* iterated+salted */ - opt.s2k_digest_algo = DIGEST_ALGO_SHA1; - opt.s2k_cipher_algo = CIPHER_ALGO_CAST5; - opt.completes_needed = 1; - opt.marginals_needed = 3; - opt.max_cert_depth = 5; - opt.pgp2_workarounds = 1; - opt.force_v3_sigs = 1; - opt.escape_from = 1; - opt.import_options=0; - opt.export_options= - EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; - opt.keyserver_options.import_options=IMPORT_REPAIR_HKP_SUBKEY_BUG; - opt.keyserver_options.export_options= - EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; - opt.keyserver_options.include_subkeys=1; - opt.keyserver_options.include_revoked=1; -#if defined (__MINGW32__) || defined (__CYGWIN32__) - set_homedir ( read_w32_registry_string( NULL, - "Software\\GNU\\GnuPG", "HomeDir" )); -#else - set_homedir ( getenv("GNUPGHOME") ); -#endif - if( !*opt.homedir ) - set_homedir ( GNUPG_HOMEDIR ); - - /* check whether we have a config file on the commandline */ - orig_argc = argc; - orig_argv = argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ - while( arg_parse( &pargs, opts) ) { - if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll ) - parse_debug++; - else if( pargs.r_opt == oOptions ) { - /* yes there is one, so we do not try the default one, but - * read the option file when it is encountered at the commandline - */ - default_config = 0; - } - else if( pargs.r_opt == oNoOptions ) - default_config = 0; /* --no-options */ - else if( pargs.r_opt == oHomedir ) - set_homedir ( pargs.r.ret_str ); - else if( pargs.r_opt == oNoPermissionWarn ) - opt.no_perm_warn=1; - else if (pargs.r_opt == oStrict ) - { - opt.strict=1; - log_set_strict(1); - } - else if (pargs.r_opt == oNoStrict ) - { - opt.strict=0; - log_set_strict(0); - } - #ifdef USE_SHM_COPROCESSING - else if( pargs.r_opt == oRunAsShmCP ) { - /* does not make sense in a options file, we do it here, - * so that we are the able to drop setuid as soon as possible */ - opt.shm_coprocess = 1; - requested_shm_size = pargs.r.ret_ulong; - } - else if ( pargs.r_opt == oStatusFD ) { - /* this is needed to ensure that the status-fd filedescriptor is - * initialized when init_shm_coprocessing() is called */ - set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); - } - #endif - } - -#ifdef HAVE_DOSISH_SYSTEM - if ( strchr (opt.homedir,'\\') ) { - char *d, *buf = m_alloc (strlen (opt.homedir)+1); - const char *s = opt.homedir; - for (d=buf,s=opt.homedir; *s; s++) - *d++ = *s == '\\'? '/': *s; - *d = 0; - set_homedir (buf); - } -#endif -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) { - init_shm_coprocessing(requested_shm_size, 1 ); - } -#endif - /* initialize the secure memory. */ - secmem_init( 16384 ); - maybe_setuid = 0; - /* Okay, we are now working under our real uid */ - - set_native_charset (NULL); /* Try to auto set the character set */ - - if( default_config ) - { - configname = make_filename(opt.homedir, "gpg" EXTSEP_S "conf", NULL ); - if (!access (configname, R_OK)) - { /* Print a warning when both config files are present. */ - char *p = make_filename(opt.homedir, "options", NULL ); - if (!access (p, R_OK)) - log_info (_("NOTE: old default options file `%s' ignored\n"), p); - m_free (p); - } - else - { /* Keep on using the old default one. */ - m_free (configname); - configname = make_filename(opt.homedir, "options", NULL ); - } - } - argc = orig_argc; - argv = orig_argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - - /* By this point we have a homedir, and cannot change it. */ - check_permissions(opt.homedir,0); - - next_pass: - if( configname ) { - if(check_permissions(configname,1)) - { - /* If any options file is unsafe, then disable any external - programs for keyserver calls or photo IDs. Since the - external program to call is set in the options file, a - unsafe options file can lead to an arbitrary program - being run. */ - - opt.exec_disable=1; - } - - configlineno = 0; - configfp = fopen( configname, "r" ); - if( !configfp ) { - if( default_config ) { - if( parse_debug ) - log_info(_("NOTE: no default option file `%s'\n"), - configname ); - } - else { - log_error(_("option file `%s': %s\n"), - configname, strerror(errno) ); - g10_exit(2); - } - m_free(configname); configname = NULL; - } - if( parse_debug && configname ) - log_info(_("reading options from `%s'\n"), configname ); - default_config = 0; - } - - while( optfile_parse( configfp, configname, &configlineno, - &pargs, opts) ) { - switch( pargs.r_opt ) { - case aCheckKeys: set_cmd( &cmd, aCheckKeys); break; - case aListPackets: set_cmd( &cmd, aListPackets); break; - case aImport: set_cmd( &cmd, aImport); break; - case aFastImport: set_cmd( &cmd, aFastImport); break; - case aSendKeys: set_cmd( &cmd, aSendKeys); break; - case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; - case aSearchKeys: set_cmd( &cmd, aSearchKeys); break; - case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; - case aExport: set_cmd( &cmd, aExport); break; - case aExportAll: set_cmd( &cmd, aExportAll); break; - case aListKeys: set_cmd( &cmd, aListKeys); break; - case aListSigs: set_cmd( &cmd, aListSigs); break; - case aExportSecret: set_cmd( &cmd, aExportSecret); break; - case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break; - case aDeleteSecretKeys: set_cmd( &cmd, aDeleteSecretKeys); - greeting=1; break; - case aDeleteSecretAndPublicKeys: - set_cmd( &cmd, aDeleteSecretAndPublicKeys); - greeting=1; - break; - case aDeleteKeys: set_cmd( &cmd, aDeleteKeys); greeting=1; break; - - case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; - case aSym: set_cmd( &cmd, aSym); break; - - case aDecrypt: set_cmd( &cmd, aDecrypt); break; - case aDecryptFiles: set_cmd( &cmd, aDecryptFiles); break; - - case aEncr: set_cmd( &cmd, aEncr); break; - case aEncrFiles: set_cmd( &cmd, aEncrFiles ); break; - case aSign: set_cmd( &cmd, aSign ); break; - case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; - case aSignKey: set_cmd( &cmd, aSignKey); break; - case aLSignKey: set_cmd( &cmd, aLSignKey); break; - case aNRSignKey: set_cmd( &cmd, aNRSignKey); break; - case aNRLSignKey: set_cmd( &cmd, aNRLSignKey); break; - case aStore: set_cmd( &cmd, aStore); break; - case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break; - case aClearsign: set_cmd( &cmd, aClearsign); break; - case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; - case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; - case aVerify: set_cmd( &cmd, aVerify); break; - case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break; - case aPrimegen: set_cmd( &cmd, aPrimegen); break; - case aGenRandom: set_cmd( &cmd, aGenRandom); break; - case aPrintMD: set_cmd( &cmd, aPrintMD); break; - case aPrintMDs: set_cmd( &cmd, aPrintMDs); break; - case aListTrustDB: set_cmd( &cmd, aListTrustDB); break; - case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break; - case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break; - case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break; - case aListTrustPath: set_cmd( &cmd, aListTrustPath); break; - case aDeArmor: set_cmd( &cmd, aDeArmor); break; - case aEnArmor: set_cmd( &cmd, aEnArmor); break; - case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break; - case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break; - case aPipeMode: set_cmd( &cmd, aPipeMode); break; - case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; - - case oArmor: opt.armor = 1; opt.no_armor=0; break; - case oOutput: opt.outfile = pargs.r.ret_str; break; - case oQuiet: opt.quiet = 1; break; - case oNoTTY: tty_no_terminal(1); break; - case oDryRun: opt.dry_run = 1; break; - case oInteractive: opt.interactive = 1; break; - case oVerbose: g10_opt_verbose++; - opt.verbose++; opt.list_sigs=1; break; - case oKOption: set_cmd( &cmd, aKMode ); break; - - case oBatch: opt.batch = 1; nogreeting = 1; break; - case oUseAgent: -#ifndef __riscos__ - opt.use_agent = 1; -#else /* __riscos__ */ - opt.use_agent = 0; - not_implemented("use-agent"); -#endif /* __riscos__ */ - break; - case oNoUseAgent: opt.use_agent = 0; break; - case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break; - case oAnswerYes: opt.answer_yes = 1; break; - case oAnswerNo: opt.answer_no = 1; break; - case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break; - case oShowKeyring: opt.show_keyring = 1; break; - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - case oStatusFD: - set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); - break; -#ifdef __riscos__ - case oStatusFile: - set_status_fd( iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) ); - break; -#endif /* __riscos__ */ - case oAttributeFD: - set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1)); - break; -#ifdef __riscos__ - case oAttributeFile: - set_attrib_fd(iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) ); - break; -#endif /* __riscos__ */ - case oLoggerFD: - log_set_logfile( NULL, - iobuf_translate_file_handle (pargs.r.ret_int, 1) ); - break; -#ifdef __riscos__ - case oLoggerFile: - log_set_logfile( NULL, - iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) ); - break; -#endif /* __riscos__ */ - case oWithFingerprint: - opt.with_fingerprint = 1; - with_fpr=1; /*fall thru*/ - case oFingerprint: opt.fingerprint++; break; - case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break; - case oOptions: - /* config files may not be nested (silently ignore them) */ - if( !configfp ) { - m_free(configname); - configname = m_strdup(pargs.r.ret_str); - goto next_pass; - } - break; - case oNoArmor: opt.no_armor=1; opt.armor=0; break; - case oNoDefKeyring: default_keyring = 0; break; - case oDefCertCheckLevel: opt.def_cert_check_level=pargs.r.ret_int; break; - case oNoGreeting: nogreeting = 1; break; - case oNoVerbose: g10_opt_verbose = 0; - opt.verbose = 0; opt.list_sigs=0; break; - case oQuickRandom: quick_random_gen(1); break; - case oSKComments: opt.sk_comments=1; break; - case oNoSKComments: opt.sk_comments=0; break; - case oNoVersion: opt.no_version=1; break; - case oEmitVersion: opt.no_version=0; break; - case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; - case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break; - case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break; - case oTrustDBName: trustdb_name = pargs.r.ret_str; break; - case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break; - case oDefRecipient: - if( *pargs.r.ret_str ) - opt.def_recipient = make_username(pargs.r.ret_str); - break; - case oDefRecipientSelf: - m_free(opt.def_recipient); opt.def_recipient = NULL; - opt.def_recipient_self = 1; - break; - case oNoDefRecipient: - m_free(opt.def_recipient); opt.def_recipient = NULL; - opt.def_recipient_self = 0; - break; - case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */ - case oHomedir: break; - case oNoBatch: opt.batch = 0; break; - case oWithKeyData: opt.with_key_data=1; /* fall thru */ - case oWithColons: opt.with_colons=':'; break; - - case oSkipVerify: opt.skip_verify=1; break; - case oCompressAlgo: opt.def_compress_algo = pargs.r.ret_int; break; - case oCompressKeys: opt.compress_keys = 1; break; - case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; - case oAlwaysTrust: opt.always_trust = 1; break; - case oLoadExtension: -#ifndef __riscos__ -#if defined(USE_DYNAMIC_LINKING) || defined(__MINGW32__) - if(check_permissions(pargs.r.ret_str,2)) - log_info(_("cipher extension \"%s\" not loaded due to " - "unsafe permissions\n"),pargs.r.ret_str); - else - register_cipher_extension(orig_argc? *orig_argv:NULL, - pargs.r.ret_str); -#endif -#else /* __riscos__ */ - not_implemented("load-extension"); -#endif /* __riscos__ */ - break; - case oRFC1991: - opt.rfc1991 = 1; - opt.rfc2440 = 0; - opt.force_v4_certs = 0; - opt.disable_mdc = 1; - opt.escape_from = 1; - break; - case oOpenPGP: - /* TODO: When 2440bis becomes a RFC, these may need - changing. */ - opt.rfc1991 = 0; - opt.rfc2440 = 1; - opt.disable_mdc = 1; - opt.allow_non_selfsigned_uid = 1; - opt.allow_freeform_uid = 1; - opt.pgp2_workarounds = 0; - opt.escape_from = 0; - opt.force_v3_sigs = 0; - opt.compress_keys = 0; /* not mandated but we do it */ - opt.compress_sigs = 0; /* ditto. */ - opt.not_dash_escaped = 0; - opt.def_cipher_algo = 0; - opt.def_digest_algo = 0; - opt.cert_digest_algo = 0; - opt.def_compress_algo = 1; - opt.s2k_mode = 3; /* iterated+salted */ - opt.s2k_digest_algo = DIGEST_ALGO_SHA1; - opt.s2k_cipher_algo = CIPHER_ALGO_CAST5; - break; - case oPGP2: opt.pgp2 = 1; break; - case oNoPGP2: opt.pgp2 = 0; break; - case oPGP6: opt.pgp6 = 1; break; - case oNoPGP6: opt.pgp6 = 0; break; - case oPGP7: opt.pgp7 = 1; break; - case oNoPGP7: opt.pgp7 = 0; break; - case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; - case oCompressSigs: opt.compress_sigs = 1; break; - case oRunAsShmCP: -#ifndef __riscos__ -# ifndef USE_SHM_COPROCESSING - /* not possible in the option file, - * but we print the warning here anyway */ - log_error("shared memory coprocessing is not available\n"); -# endif -#else /* __riscos__ */ - not_implemented("run-as-shm-coprocess"); -#endif /* __riscos__ */ - break; - case oSetFilename: opt.set_filename = pargs.r.ret_str; break; - case oForYourEyesOnly: eyes_only = 1; break; - case oNoForYourEyesOnly: eyes_only = 0; break; - case oSetPolicyURL: - add_policy_url(pargs.r.ret_str,0); - add_policy_url(pargs.r.ret_str,1); - break; - case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break; - case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break; - case oShowPolicyURL: opt.show_policy_url=1; break; - case oNoShowPolicyURL: opt.show_policy_url=0; break; - case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; - case oComment: opt.comment_string = pargs.r.ret_str; break; - case oDefaultComment: opt.comment_string = NULL; break; - case oThrowKeyid: opt.throw_keyid = 1; break; - case oShowPhotos: opt.show_photos = 1; break; - case oNoShowPhotos: opt.show_photos = 0; break; - case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break; - case oForceV3Sigs: opt.force_v3_sigs = 1; break; - case oNoForceV3Sigs: opt.force_v3_sigs = 0; break; - case oForceV4Certs: opt.force_v4_certs = 1; break; - case oNoForceV4Certs: opt.force_v4_certs = 0; break; - case oForceMDC: opt.force_mdc = 1; break; - case oNoForceMDC: opt.force_mdc = 0; break; - case oDisableMDC: opt.disable_mdc = 1; break; - case oNoDisableMDC: opt.disable_mdc = 0; break; - case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; - case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break; - case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break; - case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break; - case oNoEncryptTo: opt.no_encrypt_to = 1; break; - case oEncryptTo: /* store the recipient in the second list */ - sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); - sl->flags = 1; - break; - case oRecipient: /* store the recipient */ - add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); - any_explicit_recipient = 1; - break; - case oTextmodeShort: opt.textmode = 2; break; - case oTextmode: opt.textmode=1; break; - case oExpert: opt.expert = 1; break; - case oNoExpert: opt.expert = 0; break; - case oAskSigExpire: opt.ask_sig_expire = 1; break; - case oNoAskSigExpire: opt.ask_sig_expire = 0; break; - case oAskCertExpire: opt.ask_cert_expire = 1; break; - case oNoAskCertExpire: opt.ask_cert_expire = 0; break; - case oUser: /* store the local users */ - add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings ); - break; - case oCompress: opt.compress = pargs.r.ret_int; break; - case oPasswdFD: - pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); - break; -#ifdef __riscos__ - case oPasswdFile: - pwfd = iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 0), 0); - break; -#endif /* __riscos__ */ - case oCommandFD: - opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0); - break; -#ifdef __riscos__ - case oCommandFile: - opt.command_fd = iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 0), 0); - break; -#endif /* __riscos__ */ - case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break; - case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break; - case oCertDigestAlgo: cert_digest_string = m_strdup(pargs.r.ret_str); break; - case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break; - case oNoPermissionWarn: opt.no_perm_warn=1; break; - case oNoMDCWarn: opt.no_mdc_warn=1; break; - case oCharset: - if( set_native_charset( pargs.r.ret_str ) ) - log_error(_("%s is not a valid character set\n"), - pargs.r.ret_str); - break; - case oNotDashEscaped: opt.not_dash_escaped = 1; break; - case oEscapeFrom: opt.escape_from = 1; break; - case oNoEscapeFrom: opt.escape_from = 0; break; - case oLockOnce: opt.lock_once = 1; break; - case oLockNever: disable_dotlock(); break; - case oLockMultiple: -#ifndef __riscos__ - opt.lock_once = 0; -#else /* __riscos__ */ - not_implemented("lock-multiple"); -#endif /* __riscos__ */ - break; - case oKeyServer: - opt.keyserver_uri=m_strdup(pargs.r.ret_str); - if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno)) - log_error(_("could not parse keyserver URI\n")); - break; - case oKeyServerOptions: - parse_keyserver_options(pargs.r.ret_str); - break; - case oImportOptions: - if(!parse_import_options(pargs.r.ret_str,&opt.import_options)) - { - if(configname) - log_error(_("%s:%d: invalid import options\n"), - configname,configlineno); - else - log_error(_("invalid import options\n")); - } - break; - case oExportOptions: - if(!parse_export_options(pargs.r.ret_str,&opt.export_options)) - { - if(configname) - log_error(_("%s:%d: invalid export options\n"), - configname,configlineno); - else - log_error(_("invalid export options\n")); - } - break; - case oTempDir: opt.temp_dir=pargs.r.ret_str; break; - case oExecPath: - if(set_exec_path(pargs.r.ret_str,0)) - log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str); - else - opt.exec_path_set=1; - break; - case oNotation: - add_notation_data( pargs.r.ret_str, 0 ); - add_notation_data( pargs.r.ret_str, 1 ); - break; - case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break; - case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break; - case oShowNotation: opt.show_notation=1; break; - case oNoShowNotation: opt.show_notation=0; break; - case oUtf8Strings: utf8_strings = 1; break; - case oNoUtf8Strings: utf8_strings = 0; break; - case oDisableCipherAlgo: - disable_cipher_algo( string_to_cipher_algo(pargs.r.ret_str) ); - break; - case oDisablePubkeyAlgo: - disable_pubkey_algo( string_to_pubkey_algo(pargs.r.ret_str) ); - break; - case oNoSigCache: opt.no_sig_cache = 1; break; - case oNoSigCreateCheck: opt.no_sig_create_check = 1; break; - case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break; - case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; - case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; - case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; - case oNoLiteral: opt.no_literal = 1; break; - case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; - case oHonorHttpProxy: - opt.keyserver_options.honor_http_proxy = 1; - deprecated_warning(configname,configlineno, - "--honor-http-proxy", - "--keyserver-options ", - "honor-http-proxy"); - break; - case oFastListMode: opt.fast_list_mode = 1; break; - case oFixedListMode: opt.fixed_list_mode = 1; break; - case oListOnly: opt.list_only=1; break; - case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; - case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; - case oIgnoreCrcError: opt.ignore_crc_error = 1; break; - case oIgnoreMDCError: opt.ignore_mdc_error = 1; break; - case oNoRandomSeedFile: use_random_seed = 0; break; - case oAutoKeyRetrieve: - case oNoAutoKeyRetrieve: - opt.keyserver_options.auto_key_retrieve= - (pargs.r_opt==oAutoKeyRetrieve); - deprecated_warning(configname,configlineno, - pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve": - "--no-auto-key-retrieve","--keyserver-options ", - pargs.r_opt==oAutoKeyRetrieve?"auto-key-retrieve": - "no-auto-key-retrieve"); - break; - case oShowSessionKey: opt.show_session_key = 1; break; - case oOverrideSessionKey: - opt.override_session_key = pargs.r.ret_str; - break; - case oMergeOnly: opt.merge_only = 1; break; - case oAllowSecretKeyImport: /* obsolete */ break; - case oTryAllSecrets: opt.try_all_secrets = 1; break; - case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break; - case oEnableSpecialFilenames: - iobuf_enable_special_filenames (1); - break; - case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break; - case oAutoCheckTrustDB: opt.no_auto_check_trustdb=0; break; - case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break; - case oPreservePermissions: opt.preserve_permissions=1; break; - case oDefaultPreferenceList: - opt.def_preference_list = pargs.r.ret_str; - break; - case oPersonalCipherPreferences: - pers_cipher_list=pargs.r.ret_str; - break; - case oPersonalDigestPreferences: - pers_digest_list=pargs.r.ret_str; - break; - case oPersonalCompressPreferences: - pers_compress_list=pargs.r.ret_str; - break; - case oDisplay: opt.display = pargs.r.ret_str; break; - case oTTYname: opt.ttyname = pargs.r.ret_str; break; - case oTTYtype: opt.ttytype = pargs.r.ret_str; break; - case oLCctype: opt.lc_ctype = pargs.r.ret_str; break; - case oLCmessages: opt.lc_messages = pargs.r.ret_str; break; - case oGroup: add_group(pargs.r.ret_str); break; - case oStrict: opt.strict=1; log_set_strict(1); break; - case oNoStrict: opt.strict=0; log_set_strict(0); break; - default : pargs.err = configfp? 1:2; break; - } - } - - if( configfp ) { - fclose( configfp ); - configfp = NULL; - m_free(configname); configname = NULL; - goto next_pass; - } - m_free( configname ); configname = NULL; - if( log_get_errorcount(0) ) - g10_exit(2); - if( nogreeting ) - greeting = 0; - - if( greeting ) { - fprintf(stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - fprintf(stderr, "%s\n", strusage(15) ); - } - #ifdef IS_DEVELOPMENT_VERSION - if( !opt.batch ) { - log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); - log_info("It is only intended for test purposes and should NOT be\n"); - log_info("used in a production environment or with production keys!\n"); - } - #endif - - if (opt.verbose > 2) - log_info ("using character set `%s'\n", get_native_charset ()); - - if( may_coredump && !opt.quiet ) - log_info(_("WARNING: program may create a core file!\n")); - - if (eyes_only) { - if (opt.set_filename) - log_info(_("WARNING: %s overrides %s\n"), - "--for-your-eyes-only","--set-filename"); - - opt.set_filename="_CONSOLE"; - } - - if (opt.no_literal) { - log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal"); - if (opt.textmode) - log_error(_("%s not allowed with %s!\n"), - "--textmode", "--no-literal" ); - if (opt.set_filename) - log_error(_("%s makes no sense with %s!\n"), - eyes_only?"--for-your-eyes-only":"--set-filename", - "--no-literal" ); - } - - if (opt.set_filesize) - log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize"); - if( opt.batch ) - tty_batchmode( 1 ); - - secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ - - set_debug(); - - /* Do these after the switch(), so they can override settings. */ - if(opt.pgp2 && (opt.pgp6 || opt.pgp7)) - log_error(_("%s not allowed with %s!\n"), - "--pgp2",opt.pgp6?"--pgp6":"--pgp7"); - else - { - if(opt.pgp2) - { - int unusable=0; - - if(cmd==aSign && !detached_sig) - { - log_info(_("you can only make detached or clear signatures " - "while in --pgp2 mode\n")); - unusable=1; - } - else if(cmd==aSignEncr || cmd==aSignSym) - { - log_info(_("you can't sign and encrypt at the " - "same time while in --pgp2 mode\n")); - unusable=1; - } - else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym)) - { - log_info(_("you must use files (and not a pipe) when " - "working with --pgp2 enabled.\n")); - unusable=1; - } - else if(cmd==aEncr || cmd==aSym) - { - /* Everything else should work without IDEA (except using - a secret key encrypted with IDEA and setting an IDEA - preference, but those have their own error - messages). */ - - if(check_cipher_algo(CIPHER_ALGO_IDEA)) - { - log_info(_("encrypting a message in --pgp2 mode requires " - "the IDEA cipher\n")); - idea_cipher_warn(1); - unusable=1; - } - else if(cmd==aSym) - { - /* This only sets IDEA for symmetric encryption - since it is set via select_algo_from_prefs for - pk encryption. */ - m_free(def_cipher_string); - def_cipher_string = m_strdup("idea"); - } - - /* PGP2 can't handle the output from the textmode - filter, so we disable it for anything that could - create a literal packet (only encryption and - symmetric encryption, since we disable signing - above). */ - if(!unusable) - opt.textmode=0; - } - - if(unusable) - { - log_info(_("this message may not be usable by %s\n"), - "PGP 2.x"); - opt.pgp2=0; - } - else - { - opt.rfc1991 = 1; - opt.rfc2440 = 0; - opt.force_mdc = 0; - opt.disable_mdc = 1; - opt.force_v4_certs = 0; - opt.sk_comments = 0; - opt.escape_from = 1; - opt.force_v3_sigs = 1; - opt.pgp2_workarounds = 1; - opt.ask_sig_expire = 0; - opt.ask_cert_expire = 0; - m_free(def_digest_string); - def_digest_string = m_strdup("md5"); - opt.def_compress_algo = 1; - } - } - - if(opt.pgp6 || opt.pgp7) - { - opt.sk_comments=0; - opt.escape_from=1; - opt.force_v3_sigs=1; - opt.ask_sig_expire=0; - opt.def_compress_algo=1; - - if(opt.pgp6) /* pgp7 has MDC */ - { - opt.force_mdc=0; - opt.disable_mdc=1; - } - } - } - - /* must do this after dropping setuid, because string_to... - * may try to load an module */ - if( def_cipher_string ) { - opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string); - if(opt.def_cipher_algo==0 && - ascii_strcasecmp(def_cipher_string,"idea")==0) - idea_cipher_warn(1); - m_free(def_cipher_string); def_cipher_string = NULL; - if( check_cipher_algo(opt.def_cipher_algo) ) - log_error(_("selected cipher algorithm is invalid\n")); - } - if( def_digest_string ) { - opt.def_digest_algo = string_to_digest_algo(def_digest_string); - m_free(def_digest_string); def_digest_string = NULL; - if( check_digest_algo(opt.def_digest_algo) ) - log_error(_("selected digest algorithm is invalid\n")); - } - if( cert_digest_string ) { - opt.cert_digest_algo = string_to_digest_algo(cert_digest_string); - m_free(cert_digest_string); cert_digest_string = NULL; - if( check_digest_algo(opt.cert_digest_algo) ) - log_error(_("selected certification digest algorithm is invalid\n")); - } - if( s2k_cipher_string ) { - opt.s2k_cipher_algo = string_to_cipher_algo(s2k_cipher_string); - m_free(s2k_cipher_string); s2k_cipher_string = NULL; - if( check_cipher_algo(opt.s2k_cipher_algo) ) - log_error(_("selected cipher algorithm is invalid\n")); - } - if( s2k_digest_string ) { - opt.s2k_digest_algo = string_to_digest_algo(s2k_digest_string); - m_free(s2k_digest_string); s2k_digest_string = NULL; - if( check_digest_algo(opt.s2k_digest_algo) ) - log_error(_("selected digest algorithm is invalid\n")); - } - if( opt.def_compress_algo < -1 || opt.def_compress_algo > 2 ) - log_error(_("compress algorithm must be in range %d..%d\n"), 0, 2); - if( opt.completes_needed < 1 ) - log_error(_("completes-needed must be greater than 0\n")); - if( opt.marginals_needed < 2 ) - log_error(_("marginals-needed must be greater than 1\n")); - if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 ) - log_error(_("max-cert-depth must be in range 1 to 255\n")); - switch( opt.s2k_mode ) { - case 0: - log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n")); - break; - case 1: case 3: break; - default: - log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); - } - - if(opt.def_cert_check_level<0 || opt.def_cert_check_level>3) - log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n")); - - /* This isn't actually needed, but does serve to error out if the - string is invalid. */ - if(opt.def_preference_list && - keygen_set_std_prefs(opt.def_preference_list,0)) - log_error(_("invalid default preferences\n")); - - /* We provide defaults for the personal digest list */ - if(!pers_digest_list) - pers_digest_list="h2"; - - if(pers_cipher_list && - keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM)) - log_error(_("invalid personal cipher preferences\n")); - - if(pers_digest_list && - keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH)) - log_error(_("invalid personal digest preferences\n")); - - if(pers_compress_list && - keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) - log_error(_("invalid personal compress preferences\n")); - - if( log_get_errorcount(0) ) - g10_exit(2); - - /* set the random seed file */ - if( use_random_seed ) { - char *p = make_filename(opt.homedir, "random_seed", NULL ); - set_random_seed_file(p); - m_free(p); - } - - if( !cmd && opt.fingerprint && !with_fpr ) { - set_cmd( &cmd, aListKeys); - } - - if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */ - if( cmd == aKModeC ) { - opt.fingerprint = 1; - cmd = aKMode; - } - opt.list_sigs = 0; - if( opt.verbose > 2 ) - opt.check_sigs++; - if( opt.verbose > 1 ) - opt.list_sigs++; - - opt.verbose = opt.verbose > 1; - g10_opt_verbose = opt.verbose; - } - - /* Compression algorithm 0 means no compression at all */ - if( opt.def_compress_algo == 0) - opt.compress = 0; - - /* kludge to let -sat generate a clear text signature */ - if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign ) - cmd = aClearsign; - - if( opt.verbose > 1 ) - set_packet_list_mode(1); - - /* Add the keyrings, but not for some special commands and not in - case of "-kvv userid keyring". Also avoid adding the secret - keyring for a couple of commands to avoid unneeded access in - case the secrings are stored on a floppy */ - if( cmd != aDeArmor && cmd != aEnArmor - && !(cmd == aKMode && argc == 2 ) ) - { - if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys - && cmd != aVerify && cmd != aVerifyFiles - && cmd != aSym) - { - if (!sec_nrings || default_keyring) /* add default secret rings */ - keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); - for (sl = sec_nrings; sl; sl = sl->next) - keydb_add_resource ( sl->d, 0, 1 ); - } - if( !nrings || default_keyring ) /* add default ring */ - keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0); - for(sl = nrings; sl; sl = sl->next ) - keydb_add_resource ( sl->d, 0, 0 ); - } - FREE_STRLIST(nrings); - FREE_STRLIST(sec_nrings); - - - if( pwfd != -1 ) /* read the passphrase now. */ - read_passphrase_from_fd( pwfd ); - - fname = argc? *argv : NULL; - - switch( cmd ) { - case aPrimegen: - case aPrintMD: - case aPrintMDs: - case aGenRandom: - case aDeArmor: - case aEnArmor: - case aFixTrustDB: - break; - case aKMode: - case aListKeys: - case aListSecretKeys: - case aCheckKeys: - if( opt.with_colons ) /* need this to list the trust */ - rc = setup_trustdb(1, trustdb_name ); - break; - case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; - case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; - default: rc = setup_trustdb(1, trustdb_name ); break; - } - if( rc ) - log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc)); - - - switch (cmd) { - case aStore: - case aSym: - case aSign: - case aSignSym: - case aClearsign: - if (!opt.quiet && any_explicit_recipient) - log_info (_("WARNING: recipients (-r) given " - "without using public key encryption\n")); - break; - default: - break; - } - - switch( cmd ) { - case aStore: /* only store the file */ - if( argc > 1 ) - wrong_args(_("--store [filename]")); - if( (rc = encode_store(fname)) ) - log_error_f( print_fname_stdin(fname), - "store failed: %s\n", g10_errstr(rc) ); - break; - case aSym: /* encrypt the given file only with the symmetric cipher */ - if( argc > 1 ) - wrong_args(_("--symmetric [filename]")); - if( (rc = encode_symmetric(fname)) ) - log_error_f(print_fname_stdin(fname), - "symmetric encryption failed: %s\n",g10_errstr(rc) ); - break; - - case aEncr: /* encrypt the given file */ - if( argc > 1 ) - wrong_args(_("--encrypt [filename]")); - if( (rc = encode_crypt(fname,remusr)) ) - log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); - break; - - case aEncrFiles: /* encrypt the given files */ - encode_crypt_files(argc, argv, remusr); - break; - - case aSign: /* sign the given file */ - sl = NULL; - if( detached_sig ) { /* sign all files */ - for( ; argc; argc--, argv++ ) - add_to_strlist( &sl, *argv ); - } - else { - if( argc > 1 ) - wrong_args(_("--sign [filename]")); - if( argc ) { - sl = m_alloc_clear( sizeof *sl + strlen(fname)); - strcpy(sl->d, fname); - } - } - if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) - log_error("signing failed: %s\n", g10_errstr(rc) ); - free_strlist(sl); - break; - - case aSignEncr: /* sign and encrypt the given file */ - if( argc > 1 ) - wrong_args(_("--sign --encrypt [filename]")); - if( argc ) { - sl = m_alloc_clear( sizeof *sl + strlen(fname)); - strcpy(sl->d, fname); - } - else - sl = NULL; - if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) - log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); - free_strlist(sl); - break; - - case aSignSym: /* sign and conventionally encrypt the given file */ - if (argc > 1) - wrong_args(_("--sign --symmetric [filename]")); - rc = sign_symencrypt_file (fname, locusr); - if (rc) - log_error("%s: sign+symmetric failed: %s\n", - print_fname_stdin(fname), g10_errstr(rc) ); - break; - - case aClearsign: /* make a clearsig */ - if( argc > 1 ) - wrong_args(_("--clearsign [filename]")); - if( (rc = clearsign_file(fname, locusr, NULL)) ) - log_error("%s: clearsign failed: %s\n", - print_fname_stdin(fname), g10_errstr(rc) ); - break; - - case aVerify: - if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", g10_errstr(rc) ); - break; - - case aVerifyFiles: - if( (rc = verify_files( argc, argv ) )) - log_error("verify files failed: %s\n", g10_errstr(rc) ); - break; - - case aDecrypt: - if( argc > 1 ) - wrong_args(_("--decrypt [filename]")); - if( (rc = decrypt_message( fname ) )) - log_error("decrypt_message failed: %s\n", g10_errstr(rc) ); - break; - - case aDecryptFiles: - decrypt_messages(argc, argv); - break; - - case aSignKey: /* sign the key given as argument */ - if( argc != 1 ) - wrong_args(_("--sign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 1 ); - m_free(username); - break; - - case aLSignKey: - if( argc != 1 ) - wrong_args(_("--lsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 2 ); - m_free(username); - break; - - case aNRSignKey: - if( argc != 1 ) - wrong_args(_("--nrsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 3 ); - m_free(username); - break; - - case aNRLSignKey: - if( argc != 1 ) - wrong_args(_("--nrlsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 4 ); - m_free(username); - break; - - case aEditKey: /* Edit a key signature */ - if( !argc ) - wrong_args(_("--edit-key user-id [commands]")); - username = make_username( fname ); - if( argc > 1 ) { - sl = NULL; - for( argc--, argv++ ; argc; argc--, argv++ ) - append_to_strlist( &sl, *argv ); - keyedit_menu( username, locusr, sl, 0 ); - free_strlist(sl); - } - else - keyedit_menu(username, locusr, NULL, 0 ); - m_free(username); - break; - - case aDeleteKeys: - case aDeleteSecretKeys: - case aDeleteSecretAndPublicKeys: - sl = NULL; - /* I'm adding these in reverse order as add_to_strlist2 - reverses them again, and it's easier to understand in the - proper order :) */ - for( ; argc; argc-- ) - add_to_strlist2( &sl, argv[argc-1], utf8_strings ); - delete_keys(sl,cmd==aDeleteSecretKeys,cmd==aDeleteSecretAndPublicKeys); - free_strlist(sl); - break; - - case aCheckKeys: - opt.check_sigs = 1; - case aListSigs: - opt.list_sigs = 1; - case aListKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - public_key_list( sl ); - free_strlist(sl); - break; - case aListSecretKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - secret_key_list( sl ); - free_strlist(sl); - break; - - case aKMode: /* list keyring -- NOTE: This will be removed soon */ - if( argc < 2 ) { /* -kv [userid] */ - sl = NULL; - if (argc && **argv) - add_to_strlist2( &sl, *argv, utf8_strings ); - public_key_list( sl ); - free_strlist(sl); - } - else if( argc == 2 ) { /* -kv userid keyring */ - if( access( argv[1], R_OK ) ) { - log_error(_("can't open %s: %s\n"), - print_fname_stdin(argv[1]), strerror(errno)); - } - else { - /* add keyring (default keyrings are not registered in this - * special case */ - keydb_add_resource( argv[1], 0, 0 ); - sl = NULL; - if (**argv) - add_to_strlist2( &sl, *argv, utf8_strings ); - public_key_list( sl ); - free_strlist(sl); - } - } - else - wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") ); - break; - - case aKeygen: /* generate a key */ - if( opt.batch ) { - if( argc > 1 ) - wrong_args("--gen-key [parameterfile]"); - generate_keypair( argc? *argv : NULL ); - } - else { - if( argc ) - wrong_args("--gen-key"); - generate_keypair(NULL); - } - break; - - case aFastImport: - opt.import_options |= IMPORT_FAST_IMPORT; - case aImport: - import_keys( argc? argv:NULL, argc, NULL, opt.import_options ); - break; - - case aExport: - case aExportAll: - case aSendKeys: - case aRecvKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - if( cmd == aSendKeys ) - keyserver_export( sl ); - else if( cmd == aRecvKeys ) - keyserver_import( sl ); - else - export_pubkeys( sl, opt.export_options ); - free_strlist(sl); - break; - - case aSearchKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - append_to_strlist2( &sl, *argv, utf8_strings ); - - keyserver_search( sl ); - free_strlist(sl); - break; - - case aRefreshKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - keyserver_refresh(sl); - free_strlist(sl); - break; - - case aExportSecret: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - export_seckeys( sl ); - free_strlist(sl); - break; - - case aExportSecretSub: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - export_secsubkeys( sl ); - free_strlist(sl); - break; - - case aGenRevoke: - if( argc != 1 ) - wrong_args("--gen-revoke user-id"); - username = make_username(*argv); - gen_revoke( username ); - m_free( username ); - break; - - case aDesigRevoke: - if( argc != 1 ) - wrong_args("--desig-revoke user-id"); - username = make_username(*argv); - gen_desig_revoke( username ); - m_free( username ); - break; - - case aDeArmor: - if( argc > 1 ) - wrong_args("--dearmor [file]"); - rc = dearmor_file( argc? *argv: NULL ); - if( rc ) - log_error(_("dearmoring failed: %s\n"), g10_errstr(rc)); - break; - - case aEnArmor: - if( argc > 1 ) - wrong_args("--enarmor [file]"); - rc = enarmor_file( argc? *argv: NULL ); - if( rc ) - log_error(_("enarmoring failed: %s\n"), g10_errstr(rc)); - break; - - - case aPrimegen: - { int mode = argc < 2 ? 0 : atoi(*argv); - - if( mode == 1 && argc == 2 ) { - mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1); - } - else if( mode == 2 && argc == 3 ) { - mpi_print( stdout, generate_elg_prime( - 0, atoi(argv[1]), - atoi(argv[2]), NULL,NULL ), 1); - } - else if( mode == 3 && argc == 3 ) { - MPI *factors; - mpi_print( stdout, generate_elg_prime( - 1, atoi(argv[1]), - atoi(argv[2]), NULL,&factors ), 1); - putchar('\n'); - mpi_print( stdout, factors[0], 1 ); /* print q */ - } - else if( mode == 4 && argc == 3 ) { - MPI g = mpi_alloc(1); - mpi_print( stdout, generate_elg_prime( - 0, atoi(argv[1]), - atoi(argv[2]), g, NULL ), 1); - putchar('\n'); - mpi_print( stdout, g, 1 ); - mpi_free(g); - } - else - wrong_args("--gen-prime mode bits [qbits] "); - putchar('\n'); - } - break; - - case aGenRandom: - { - int level = argc ? atoi(*argv):0; - int count = argc > 1 ? atoi(argv[1]): 0; - int endless = !count; - - if( argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0 ) - wrong_args("--gen-random 0|1|2 [count]"); - - while( endless || count ) { - byte *p; - /* Wee need a multiple of 3, so that in case of - armored output we get a correct string. No - linefolding is done, as it is best to levae this to - other tools */ - size_t n = !endless && count < 99? count : 99; - - p = get_random_bits( n*8, level, 0); - #ifdef HAVE_DOSISH_SYSTEM - setmode ( fileno(stdout), O_BINARY ); - #endif - if (opt.armor) { - char *tmp = make_radix64_string (p, n); - fputs (tmp, stdout); - m_free (tmp); - if (n%3 == 1) - putchar ('='); - if (n%3) - putchar ('='); - } else { - fwrite( p, n, 1, stdout ); - } - m_free(p); - if( !endless ) - count -= n; - } - if (opt.armor) - putchar ('\n'); - } - break; - - case aPrintMD: - if( argc < 1) - wrong_args("--print-md algo [files]"); - { - int all_algos = (**argv=='*' && !(*argv)[1]); - int algo = all_algos? 0 : string_to_digest_algo(*argv); - - if( !algo && !all_algos ) - log_error(_("invalid hash algorithm `%s'\n"), *argv ); - else { - argc--; argv++; - if( !argc ) - print_mds(NULL, algo); - else { - for(; argc; argc--, argv++ ) - print_mds(*argv, algo); - } - } - } - break; - - case aPrintMDs: /* old option */ - if( !argc ) - print_mds(NULL,0); - else { - for(; argc; argc--, argv++ ) - print_mds(*argv,0); - } - break; - - case aListTrustDB: - if( !argc ) - list_trustdb(NULL); - else { - for( ; argc; argc--, argv++ ) - list_trustdb( *argv ); - } - break; - - case aUpdateTrustDB: - if( argc ) - wrong_args("--update-trustdb"); - update_trustdb(); - break; - - case aCheckTrustDB: - /* Old versions allowed for arguments - ignore them */ - check_trustdb(); - break; - - case aFixTrustDB: - log_error("this command is not yet implemented.\n"); - log_error("A workaround is to use \"--export-ownertrust\", remove\n"); - log_error("the trustdb file and do an \"--import-ownertrust\".\n" ); - break; - - case aListTrustPath: - if( !argc ) - wrong_args("--list-trust-path "); - for( ; argc; argc--, argv++ ) { - username = make_username( *argv ); - list_trust_path( username ); - m_free(username); - } - break; - - case aExportOwnerTrust: - if( argc ) - wrong_args("--export-ownertrust"); - export_ownertrust(); - break; - - case aImportOwnerTrust: - if( argc > 1 ) - wrong_args("--import-ownertrust [file]"); - import_ownertrust( argc? *argv:NULL ); - break; - - case aPipeMode: - if ( argc ) - wrong_args ("--pipemode"); - run_in_pipemode (); - break; - - case aRebuildKeydbCaches: - if (argc) - wrong_args ("--rebuild-keydb-caches"); - keydb_rebuild_caches (); - break; - - case aListPackets: - opt.list_packets=2; - default: - if( argc > 1 ) - wrong_args(_("[filename]")); - /* Issue some output for the unix newbie */ - if( !fname && !opt.outfile && isatty( fileno(stdin) ) - && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) ) - log_info(_("Go ahead and type your message ...\n")); - - if( !(a = iobuf_open(fname)) ) - log_error(_("can't open `%s'\n"), print_fname_stdin(fname)); - else { - - if( !opt.no_armor ) { - if( use_armor_filter( a ) ) { - memset( &afx, 0, sizeof afx); - iobuf_push_filter( a, armor_filter, &afx ); - } - } - if( cmd == aListPackets ) { - set_packet_list_mode(1); - opt.list_packets=1; - } - rc = proc_packets(NULL, a ); - if( rc ) - log_error("processing message failed: %s\n", g10_errstr(rc) ); - iobuf_close(a); - } - break; - } - - /* cleanup */ - FREE_STRLIST(remusr); - FREE_STRLIST(locusr); - g10_exit(0); - return 8; /*NEVER REACHED*/ -} - - -void -g10_exit( int rc ) -{ - update_random_seed_file(); - if( opt.debug & DBG_MEMSTAT_VALUE ) { - m_print_stats("on exit"); - random_dump_stats(); - } - if( opt.debug ) - secmem_dump_stats(); - secmem_term(); - rc = rc? rc : log_get_errorcount(0)? 2 : - g10_errors_seen? 1 : 0; - exit(rc ); -} - - - - -static void -print_hex( byte *p, size_t n ) -{ - int i; - - if( n == 20 ) { - for(i=0; i < n ; i++, i++, p += 2 ) { - if( i ) - putchar(' '); - if( i == 10 ) - putchar(' '); - printf("%02X%02X", *p, p[1] ); - } - } - else if( n == 24 ) { - for(i=0; i < n ; i += 4, p += 4 ) { - if( i ) - putchar(' '); - if( i == 12 ) - putchar(' '); - printf("%02X%02X%02X%02X", *p, p[1], p[2], p[3] ); - } - } - else { - for(i=0; i < n ; i++, p++ ) { - if( i ) - putchar(' '); - if( i && !(i%8) ) - putchar(' '); - printf("%02X", *p ); - } - } -} - -static void -print_hashline( MD_HANDLE md, int algo, const char *fname ) -{ - int i, n; - const byte *p; - - if ( fname ) { - for (p = fname; *p; p++ ) { - if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) - printf("%%%02X", *p ); - else - putchar( *p ); - } - } - putchar(':'); - printf("%d:", algo ); - p = md_read( md, algo ); - n = md_digest_length(algo); - for(i=0; i < n ; i++, p++ ) - printf("%02X", *p ); - putchar(':'); - putchar('\n'); -} - -static void -print_mds( const char *fname, int algo ) -{ - FILE *fp; - char buf[1024]; - size_t n; - MD_HANDLE md; - char *pname; - - if( !fname ) { - fp = stdin; - #ifdef HAVE_DOSISH_SYSTEM - setmode ( fileno(fp) , O_BINARY ); - #endif - pname = m_strdup("[stdin]: "); - } - else { - pname = m_alloc(strlen(fname)+3); - strcpy(stpcpy(pname,fname),": "); - fp = fopen( fname, "rb" ); - } - if( !fp ) { - log_error("%s%s\n", pname, strerror(errno) ); - m_free(pname); - return; - } - - md = md_open( 0, 0 ); - if( algo ) - md_enable( md, algo ); - else { - md_enable( md, DIGEST_ALGO_MD5 ); - md_enable( md, DIGEST_ALGO_SHA1 ); - md_enable( md, DIGEST_ALGO_RMD160 ); - if( !check_digest_algo(DIGEST_ALGO_TIGER) ) - md_enable( md, DIGEST_ALGO_TIGER ); - } - - while( (n=fread( buf, 1, DIM(buf), fp )) ) - md_write( md, buf, n ); - if( ferror(fp) ) - log_error("%s%s\n", pname, strerror(errno) ); - else { - md_final(md); - if ( opt.with_colons ) { - if ( algo ) - print_hashline( md, algo, fname ); - else { - print_hashline( md, DIGEST_ALGO_MD5, fname ); - print_hashline( md, DIGEST_ALGO_SHA1, fname ); - print_hashline( md, DIGEST_ALGO_RMD160, fname ); - if( !check_digest_algo(DIGEST_ALGO_TIGER) ) - print_hashline( md, DIGEST_ALGO_TIGER, fname ); - } - } - else { - if( algo ) { - if( fname ) - fputs( pname, stdout ); - print_hex(md_read(md, algo), md_digest_length(algo) ); - } - else { - printf( "%s MD5 = ", fname?pname:"" ); - print_hex(md_read(md, DIGEST_ALGO_MD5), 16 ); - printf("\n%s SHA1 = ", fname?pname:"" ); - print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 ); - printf("\n%sRMD160 = ", fname?pname:"" ); - print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 ); - if( !check_digest_algo(DIGEST_ALGO_TIGER) ) { - printf("\n%s TIGER = ", fname?pname:"" ); - print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 ); - } - } - putchar('\n'); - } - } - md_close(md); - - if( fp != stdin ) - fclose(fp); -} - - -/**************** - * Check the supplied name,value string and add it to the notation - * data to be used for signatures. which==0 for sig notations, and 1 - * for cert notations. -*/ -static void -add_notation_data( const char *string, int which ) -{ - const char *s; - STRLIST sl,*notation_data; - int critical=0; - int highbit=0; - - if(which) - notation_data=&opt.cert_notation_data; - else - notation_data=&opt.sig_notation_data; - - if( *string == '!' ) { - critical = 1; - string++; - } - - for( s=string ; *s != '='; s++ ) { - if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) ) { - log_error(_("a notation name must have only printable characters " - "or spaces, and end with an '='\n") ); - return; - } - } - /* we only support printable text - therefore we enforce the use - * of only printable characters (an empty value is valid) */ - for( s++; *s ; s++ ) { - if( iscntrl(*s) ) { - log_error(_("a notation value must not use " - "any control characters\n") ); - return; - } - else if( *s & 0x80 ) - highbit = 1; - } - - if( highbit ) /* must use UTF8 encoding */ - sl = add_to_strlist2( notation_data, string, utf8_strings ); - else - sl = add_to_strlist( notation_data, string ); - - if( critical ) - sl->flags |= 1; -} - - -static void -add_policy_url( const char *string, int which ) -{ - int i,critical=0; - STRLIST sl; - - if(*string=='!') - { - string++; - critical=1; - } - - for(i=0;iflags |= 1; -} diff --git a/g10/getkey.c b/g10/getkey.c deleted file mode 100644 index 991b98d2f..000000000 --- a/g10/getkey.c +++ /dev/null @@ -1,2476 +0,0 @@ -/* getkey.c - Get a key from the database - * 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 -#include -#include -#include -#include -#include -#include "util.h" -#include "packet.h" -#include "memory.h" -#include "iobuf.h" -#include "keydb.h" -#include "options.h" -#include "main.h" -#include "trustdb.h" -#include "i18n.h" - -#define MAX_PK_CACHE_ENTRIES 200 -#define MAX_UID_CACHE_ENTRIES 200 - -#if MAX_PK_CACHE_ENTRIES < 2 - #error We need the cache for key creation -#endif - - -struct getkey_ctx_s { - int exact; - KBNODE keyblock; - KBPOS kbpos; - KBNODE found_key; /* pointer into some keyblock */ - int last_rc; - int req_usage; - int req_algo; - KEYDB_HANDLE kr_handle; - int not_allocated; - int nitems; - KEYDB_SEARCH_DESC items[1]; -}; - -#if 0 -static struct { - int any; - int okay_count; - int nokey_count; - int error_count; -} lkup_stats[21]; -#endif - -typedef struct keyid_list { - struct keyid_list *next; - u32 keyid[2]; -} *keyid_list_t; - - -#if MAX_PK_CACHE_ENTRIES - typedef struct pk_cache_entry { - struct pk_cache_entry *next; - u32 keyid[2]; - PKT_public_key *pk; - } *pk_cache_entry_t; - static pk_cache_entry_t pk_cache; - static int pk_cache_entries; /* number of entries in pk cache */ - static int pk_cache_disabled; -#endif - -#if MAX_UID_CACHE_ENTRIES < 5 - #error we really need the userid cache -#endif -typedef struct user_id_db { - struct user_id_db *next; - keyid_list_t keyids; - int len; - char name[1]; -} *user_id_db_t; -static user_id_db_t user_id_db; -static int uid_cache_entries; /* number of entries in uid cache */ - -static void merge_selfsigs( KBNODE keyblock ); -static int lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ); - -#if 0 -static void -print_stats() -{ - int i; - for(i=0; i < DIM(lkup_stats); i++ ) { - if( lkup_stats[i].any ) - fprintf(stderr, - "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n", - i, - lkup_stats[i].okay_count, - lkup_stats[i].nokey_count, - lkup_stats[i].error_count ); - } -} -#endif - - -void -cache_public_key( PKT_public_key *pk ) -{ - #if MAX_PK_CACHE_ENTRIES - pk_cache_entry_t ce; - u32 keyid[2]; - - if( pk_cache_disabled ) - return; - - if( pk->dont_cache ) - return; - - if( is_ELGAMAL(pk->pubkey_algo) - || pk->pubkey_algo == PUBKEY_ALGO_DSA - || is_RSA(pk->pubkey_algo) ) { - keyid_from_pk( pk, keyid ); - } - else - return; /* don't know how to get the keyid */ - - for( ce = pk_cache; ce; ce = ce->next ) - if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { - if( DBG_CACHE ) - log_debug("cache_public_key: already in cache\n"); - return; - } - - if( pk_cache_entries >= MAX_PK_CACHE_ENTRIES ) { - /* fixme: use another algorithm to free some cache slots */ - pk_cache_disabled=1; - if( opt.verbose > 1 ) - log_info(_("too many entries in pk cache - disabled\n")); - return; - } - pk_cache_entries++; - ce = m_alloc( sizeof *ce ); - ce->next = pk_cache; - pk_cache = ce; - ce->pk = copy_public_key( NULL, pk ); - ce->keyid[0] = keyid[0]; - ce->keyid[1] = keyid[1]; - #endif -} - - -/* - * Return the user ID from the given keyblock. - * We use the primary uid flag which has been set by the merge_selfsigs - * function. The returned value is only valid as long as then given - * keyblock is not changed - */ -static const char * -get_primary_uid ( KBNODE keyblock, size_t *uidlen ) -{ - KBNODE k; - const char *s; - - for (k=keyblock; k; k=k->next ) { - if ( k->pkt->pkttype == PKT_USER_ID - && !k->pkt->pkt.user_id->attrib_data - && k->pkt->pkt.user_id->is_primary ) { - *uidlen = k->pkt->pkt.user_id->len; - return k->pkt->pkt.user_id->name; - } - } - /* fixme: returning translatable constants instead of a user ID is - * not good because they are probably not utf-8 encoded. */ - s = _("[User id not found]"); - *uidlen = strlen (s); - return s; -} - - -static void -release_keyid_list ( keyid_list_t k ) -{ - while ( k ) { - keyid_list_t k2 = k->next; - m_free (k); - k = k2; - } -} - -/**************** - * Store the association of keyid and userid - * Feed only public keys to this function. - */ -static void -cache_user_id( KBNODE keyblock ) -{ - user_id_db_t r; - const char *uid; - size_t uidlen; - keyid_list_t keyids = NULL; - KBNODE k; - - for (k=keyblock; k; k = k->next ) { - if ( k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - keyid_list_t a = m_alloc_clear ( sizeof *a ); - /* Hmmm: For a long list of keyids it might be an advantage - * to append the keys */ - keyid_from_pk( k->pkt->pkt.public_key, a->keyid ); - /* first check for duplicates */ - for(r=user_id_db; r; r = r->next ) { - keyid_list_t b = r->keyids; - for ( b = r->keyids; b; b = b->next ) { - if( b->keyid[0] == a->keyid[0] - && b->keyid[1] == a->keyid[1] ) { - if( DBG_CACHE ) - log_debug("cache_user_id: already in cache\n"); - release_keyid_list ( keyids ); - m_free ( a ); - return; - } - } - } - /* now put it into the cache */ - a->next = keyids; - keyids = a; - } - } - if ( !keyids ) - BUG (); /* No key no fun */ - - - uid = get_primary_uid ( keyblock, &uidlen ); - - if( uid_cache_entries >= MAX_UID_CACHE_ENTRIES ) { - /* fixme: use another algorithm to free some cache slots */ - r = user_id_db; - user_id_db = r->next; - release_keyid_list ( r->keyids ); - m_free(r); - uid_cache_entries--; - } - r = m_alloc( sizeof *r + uidlen-1 ); - r->keyids = keyids; - r->len = uidlen; - memcpy(r->name, uid, r->len); - r->next = user_id_db; - user_id_db = r; - uid_cache_entries++; -} - - -void -getkey_disable_caches() -{ - #if MAX_PK_CACHE_ENTRIES - { - pk_cache_entry_t ce, ce2; - - for( ce = pk_cache; ce; ce = ce2 ) { - ce2 = ce->next; - free_public_key( ce->pk ); - m_free( ce ); - } - pk_cache_disabled=1; - pk_cache_entries = 0; - pk_cache = NULL; - } - #endif - /* fixme: disable user id cache ? */ -} - - -static void -pk_from_block ( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE keyblock ) -{ - KBNODE a = ctx->found_key ? ctx->found_key : keyblock; - - assert ( a->pkt->pkttype == PKT_PUBLIC_KEY - || a->pkt->pkttype == PKT_PUBLIC_SUBKEY ); - - copy_public_key ( pk, a->pkt->pkt.public_key ); -} - -static void -sk_from_block ( GETKEY_CTX ctx, - PKT_secret_key *sk, KBNODE keyblock ) -{ - KBNODE a = ctx->found_key ? ctx->found_key : keyblock; - - assert ( a->pkt->pkttype == PKT_SECRET_KEY - || a->pkt->pkttype == PKT_SECRET_SUBKEY ); - - copy_secret_key( sk, a->pkt->pkt.secret_key); -} - - -/**************** - * Get a public key and store it into the allocated pk - * can be called with PK set to NULL to just read it into some - * internal structures. - */ -int -get_pubkey( PKT_public_key *pk, u32 *keyid ) -{ - int internal = 0; - int rc = 0; - - #if MAX_PK_CACHE_ENTRIES - { /* Try to get it from the cache */ - pk_cache_entry_t ce; - for( ce = pk_cache; ce; ce = ce->next ) { - if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { - if( pk ) - copy_public_key( pk, ce->pk ); - return 0; - } - } - } - #endif - /* more init stuff */ - if( !pk ) { - pk = m_alloc_clear( sizeof *pk ); - internal++; - } - - - /* do a lookup */ - { struct getkey_ctx_s ctx; - KBNODE kb = NULL; - memset( &ctx, 0, sizeof ctx ); - ctx.exact = 1; /* use the key ID exactly as given */ - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); - ctx.nitems = 1; - ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; - ctx.items[0].u.kid[0] = keyid[0]; - ctx.items[0].u.kid[1] = keyid[1]; - ctx.req_algo = pk->req_algo; - ctx.req_usage = pk->req_usage; - rc = lookup( &ctx, &kb, 0 ); - if ( !rc ) { - pk_from_block ( &ctx, pk, kb ); - } - get_pubkey_end( &ctx ); - release_kbnode ( kb ); - } - if( !rc ) - goto leave; - - rc = G10ERR_NO_PUBKEY; - - leave: - if( !rc ) - cache_public_key( pk ); - if( internal ) - free_public_key(pk); - return rc; -} - - -/* Get a public key and store it into the allocated pk. This function - differs from get_pubkey() in that it does not do a check of the key - to avoid recursion. It should be used only in very certain cases. */ -static int -get_pubkey_direct (PKT_public_key *pk, u32 *keyid) -{ - int rc = 0; - KEYDB_HANDLE hd; - KBNODE keyblock; - - assert (pk); -#if MAX_PK_CACHE_ENTRIES - { /* Try to get it from the cache */ - pk_cache_entry_t ce; - - for (ce = pk_cache; ce; ce = ce->next) - { - if (ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1]) - { - if (pk) - copy_public_key (pk, ce->pk); - return 0; - } - } - } -#endif - - hd = keydb_new (0); - rc = keydb_search_kid (hd, keyid); - if (rc == -1) - { - keydb_release (hd); - return G10ERR_NO_PUBKEY; - } - rc = keydb_get_keyblock (hd, &keyblock); - keydb_release (hd); - if (rc) - { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - return G10ERR_NO_PUBKEY; - } - - assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY - || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY ); - copy_public_key (pk, keyblock->pkt->pkt.public_key ); - release_kbnode (keyblock); - - /* Not caching key here since it won't have all of the fields - properly set. */ - - return 0; -} - - - -KBNODE -get_pubkeyblock( u32 *keyid ) -{ - struct getkey_ctx_s ctx; - int rc = 0; - KBNODE keyblock = NULL; - - memset( &ctx, 0, sizeof ctx ); - /* no need to set exact here because we want the entire block */ - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); - ctx.nitems = 1; - ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; - ctx.items[0].u.kid[0] = keyid[0]; - ctx.items[0].u.kid[1] = keyid[1]; - rc = lookup( &ctx, &keyblock, 0 ); - get_pubkey_end( &ctx ); - - return rc ? NULL : keyblock; -} - - - - -/**************** - * Get a secret key and store it into sk - */ -int -get_seckey( PKT_secret_key *sk, u32 *keyid ) -{ - int rc; - struct getkey_ctx_s ctx; - KBNODE kb = NULL; - - memset( &ctx, 0, sizeof ctx ); - ctx.exact = 1; /* use the key ID exactly as given */ - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); - ctx.nitems = 1; - ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; - ctx.items[0].u.kid[0] = keyid[0]; - ctx.items[0].u.kid[1] = keyid[1]; - ctx.req_algo = sk->req_algo; - ctx.req_usage = sk->req_usage; - rc = lookup( &ctx, &kb, 1 ); - if ( !rc ) { - sk_from_block ( &ctx, sk, kb ); - } - get_seckey_end( &ctx ); - release_kbnode ( kb ); - - if( !rc ) { - /* check the secret key (this may prompt for a passprase to - * unlock the secret key - */ - rc = check_secret_key( sk, 0 ); - } - - return rc; -} - - -/**************** - * Check whether the secret key is available. This is just a fast - * check and does not tell us whether the secret key is valid. It - * merely tells other whether there is some secret key. - * Returns: 0 := key is available - * G10ERR_NO_SECKEY := not availabe - */ -int -seckey_available( u32 *keyid ) -{ - int rc; - KEYDB_HANDLE hd = keydb_new (1); - - rc = keydb_search_kid (hd, keyid); - if ( rc == -1 ) - rc = G10ERR_NO_SECKEY; - keydb_release (hd); - return rc; -} - - -/**************** - * Return the type of the user id: - * - * Please use the constants KEYDB_SERCH_MODE_xxx - * 0 = Invalid user ID - * 1 = exact match - * 2 = match a substring - * 3 = match an email address - * 4 = match a substring of an email address - * 5 = match an email address, but compare from end - * 6 = word match mode - * 10 = it is a short KEYID (don't care about keyid[0]) - * 11 = it is a long KEYID - * 12 = it is a trustdb index (keyid is looked up) - * 16 = it is a 16 byte fingerprint - * 20 = it is a 20 byte fingerprint - * 21 = Unified fingerprint :fpr:pk_algo: - * (We don't use pk_algo yet) - * - * Rules used: - * - If the username starts with 8,9,16 or 17 hex-digits (the first one - * must be in the range 0..9), this is considered a keyid; depending - * on the length a short or complete one. - * - If the username starts with 32,33,40 or 41 hex-digits (the first one - * must be in the range 0..9), this is considered a fingerprint. - * - If the username starts with a left angle, we assume it is a complete - * email address and look only at this part. - * - If the username starts with a colon we assume it is a unified - * key specfification. - * - If the username starts with a '.', we assume it is the ending - * part of an email address - * - If the username starts with an '@', we assume it is a part of an - * email address - * - If the userid start with an '=' an exact compare is done. - * - If the userid starts with a '*' a case insensitive substring search is - * done (This is the default). - * - If the userid starts with a '+' we will compare individual words - * and a match requires that all the words are in the userid. - * Words are delimited by white space or "()<>[]{}.@-+_,;/&!" - * (note that you can't search for these characters). Compare - * is not case sensitive. - */ - -static int -classify_user_id2( const char *name, - KEYDB_SEARCH_DESC *desc, - int *force_exact ) -{ - const char *s; - int hexprefix = 0; - int hexlength; - int mode = 0; - - /* clear the structure so that the mode field is set to zero unless - * we set it to the correct value right at the end of this function */ - memset (desc, 0, sizeof *desc); - *force_exact = 0; - /* skip leading spaces. Fixme: what is with trailing spaces? */ - for(s = name; *s && isspace(*s); s++ ) - ; - - switch (*s) { - case 0: /* empty string is an error */ - return 0; - - case '.': /* an email address, compare from end */ - mode = KEYDB_SEARCH_MODE_MAILEND; - s++; - desc->u.name = s; - break; - - case '<': /* an email address */ - mode = KEYDB_SEARCH_MODE_MAIL; - desc->u.name = s; - break; - - case '@': /* part of an email address */ - mode = KEYDB_SEARCH_MODE_MAILSUB; - s++; - desc->u.name = s; - break; - - case '=': /* exact compare */ - mode = KEYDB_SEARCH_MODE_EXACT; - s++; - desc->u.name = s; - break; - - case '*': /* case insensitive substring search */ - mode = KEYDB_SEARCH_MODE_SUBSTR; - s++; - desc->u.name = s; - break; - - case '+': /* compare individual words */ - mode = KEYDB_SEARCH_MODE_WORDS; - s++; - desc->u.name = s; - break; - - case '#': /* local user id */ - return 0; /* This is now obsolete and van't not be used anymore*/ - - case ':': /*Unified fingerprint */ - { - const char *se, *si; - int i; - - se = strchr( ++s,':'); - if ( !se ) - return 0; - for (i=0,si=s; si < se; si++, i++ ) { - if ( !strchr("01234567890abcdefABCDEF", *si ) ) - return 0; /* invalid digit */ - } - if (i != 32 && i != 40) - return 0; /* invalid length of fpr*/ - for (i=0,si=s; si < se; i++, si +=2) - desc->u.fpr[i] = hextobyte(si); - for ( ; i < 20; i++) - desc->u.fpr[i]= 0; - s = se + 1; - mode = KEYDB_SEARCH_MODE_FPR; - } - break; - - default: - if (s[0] == '0' && s[1] == 'x') { - hexprefix = 1; - s += 2; - } - - hexlength = strspn(s, "0123456789abcdefABCDEF"); - if (hexlength >= 8 && s[hexlength] =='!') { - *force_exact = 1; - hexlength++; /* just for the following check */ - } - - /* check if a hexadecimal number is terminated by EOS or blank */ - if (hexlength && s[hexlength] && !isspace(s[hexlength])) { - if (hexprefix) /* a "0x" prefix without correct */ - return 0; /* termination is an error */ - else /* The first chars looked like */ - hexlength = 0; /* a hex number, but really were not. */ - } - - if (*force_exact) - hexlength--; - - if (hexlength == 8 - || (!hexprefix && hexlength == 9 && *s == '0')){ - /* short keyid */ - if (hexlength == 9) - s++; - desc->u.kid[0] = 0; - desc->u.kid[1] = strtoul( s, NULL, 16 ); - mode = KEYDB_SEARCH_MODE_SHORT_KID; - } - else if (hexlength == 16 - || (!hexprefix && hexlength == 17 && *s == '0')) { - /* complete keyid */ - char buf[9]; - if (hexlength == 17) - s++; - mem2str(buf, s, 9 ); - desc->u.kid[0] = strtoul( buf, NULL, 16 ); - desc->u.kid[1] = strtoul( s+8, NULL, 16 ); - mode = KEYDB_SEARCH_MODE_LONG_KID; - } - else if (hexlength == 32 || (!hexprefix && hexlength == 33 - && *s == '0')) { - /* md5 fingerprint */ - int i; - if (hexlength == 33) - s++; - memset(desc->u.fpr+16, 0, 4); - for (i=0; i < 16; i++, s+=2) { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR16; - } - else if (hexlength == 40 || (!hexprefix && hexlength == 41 - && *s == '0')) { - /* sha1/rmd160 fingerprint */ - int i; - if (hexlength == 41) - s++; - for (i=0; i < 20; i++, s+=2) { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR20; - } - else { - if (hexprefix) /* This was a hex number with a prefix */ - return 0; /* and a wrong length */ - - *force_exact = 0; - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_SUBSTR; /* default mode */ - } - } - - desc->mode = mode; - return mode; -} - -int -classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc) -{ - int dummy; - KEYDB_SEARCH_DESC dummy_desc; - - if (!desc) - desc = &dummy_desc; - return classify_user_id2 (name, desc, &dummy); -} - -/**************** - * Try to get the pubkey by the userid. This function looks for the - * first pubkey certificate which has the given name in a user_id. - * if pk/sk has the pubkey algo set, the function will only return - * a pubkey with that algo. - * The caller should provide storage for either the pk or the sk. - * If ret_kb is not NULL the function will return the keyblock there. - */ - -static int -key_byname( GETKEY_CTX *retctx, STRLIST namelist, - PKT_public_key *pk, PKT_secret_key *sk, int secmode, - KBNODE *ret_kb, KEYDB_HANDLE *ret_kdbhd ) -{ - int rc = 0; - int n; - STRLIST r; - GETKEY_CTX ctx; - KBNODE help_kb = NULL; - int exact; - - if( retctx ) {/* reset the returned context in case of error */ - assert (!ret_kdbhd); /* not allowed because the handle is - stored in the context */ - *retctx = NULL; - } - if (ret_kdbhd) - *ret_kdbhd = NULL; - - /* build the search context */ - for(n=0, r=namelist; r; r = r->next ) - n++; - ctx = m_alloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items ); - ctx->nitems = n; - - for(n=0, r=namelist; r; r = r->next, n++ ) { - classify_user_id2 (r->d, &ctx->items[n], &exact); - - if (exact) - ctx->exact = 1; - if (!ctx->items[n].mode) { - m_free (ctx); - return G10ERR_INV_USER_ID; - } - } - - ctx->kr_handle = keydb_new (secmode); - if ( !ret_kb ) - ret_kb = &help_kb; - - if( secmode ) { - if (sk) { - ctx->req_algo = sk->req_algo; - ctx->req_usage = sk->req_usage; - } - rc = lookup( ctx, ret_kb, 1 ); - if ( !rc && sk ) { - sk_from_block ( ctx, sk, *ret_kb ); - } - } - else { - if (pk) { - ctx->req_algo = pk->req_algo; - ctx->req_usage = pk->req_usage; - } - rc = lookup( ctx, ret_kb, 0 ); - if ( !rc && pk ) { - pk_from_block ( ctx, pk, *ret_kb ); - } - } - - release_kbnode ( help_kb ); - - if (retctx) /* caller wants the context */ - *retctx = ctx; - else { - if (ret_kdbhd) { - *ret_kdbhd = ctx->kr_handle; - ctx->kr_handle = NULL; - } - get_pubkey_end (ctx); - } - - return rc; -} - -/* - * Find a public key from NAME and returh the keyblock or the key. - * If ret_kdb is not NULL, the KEYDB handle used to locate this keyblock is - * returned and the caller is responsible for closing it. - */ -int -get_pubkey_byname (PKT_public_key *pk, - const char *name, KBNODE *ret_keyblock, - KEYDB_HANDLE *ret_kdbhd ) -{ - int rc; - STRLIST namelist = NULL; - - add_to_strlist( &namelist, name ); - rc = key_byname( NULL, namelist, pk, NULL, 0, ret_keyblock, ret_kdbhd); - free_strlist( namelist ); - return rc; -} - -int -get_pubkey_bynames( GETKEY_CTX *retctx, PKT_public_key *pk, - STRLIST names, KBNODE *ret_keyblock ) -{ - return key_byname( retctx, names, pk, NULL, 0, ret_keyblock, NULL); -} - -int -get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) -{ - int rc; - - rc = lookup( ctx, ret_keyblock, 0 ); - if ( !rc && pk && ret_keyblock ) - pk_from_block ( ctx, pk, *ret_keyblock ); - - return rc; -} - - -void -get_pubkey_end( GETKEY_CTX ctx ) -{ - if( ctx ) { - memset (&ctx->kbpos, 0, sizeof ctx->kbpos); - keydb_release (ctx->kr_handle); - if( !ctx->not_allocated ) - m_free( ctx ); - } -} - - - - -/**************** - * Search for a key with the given fingerprint. - * FIXME: - * We should replace this with the _byname function. Thiscsan be done - * by creating a userID conforming to the unified fingerprint style. - */ -int -get_pubkey_byfprint( PKT_public_key *pk, - const byte *fprint, size_t fprint_len) -{ - int rc; - - if( fprint_len == 20 || fprint_len == 16 ) { - struct getkey_ctx_s ctx; - KBNODE kb = NULL; - - memset( &ctx, 0, sizeof ctx ); - ctx.exact = 1 ; - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); - ctx.nitems = 1; - ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16 - : KEYDB_SEARCH_MODE_FPR20; - memcpy( ctx.items[0].u.fpr, fprint, fprint_len ); - rc = lookup( &ctx, &kb, 0 ); - if (!rc && pk ) - pk_from_block ( &ctx, pk, kb ); - release_kbnode ( kb ); - get_pubkey_end( &ctx ); - } - else - rc = G10ERR_GENERAL; /* Oops */ - return rc; -} - -/**************** - * Search for a key with the given fingerprint and return the - * complete keyblock which may have more than only this key. - */ -int -get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, - size_t fprint_len ) -{ - int rc; - - if( fprint_len == 20 || fprint_len == 16 ) { - struct getkey_ctx_s ctx; - - memset( &ctx, 0, sizeof ctx ); - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); - ctx.nitems = 1; - ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16 - : KEYDB_SEARCH_MODE_FPR20; - memcpy( ctx.items[0].u.fpr, fprint, fprint_len ); - rc = lookup( &ctx, ret_keyblock, 0 ); - get_pubkey_end( &ctx ); - } - else - rc = G10ERR_GENERAL; /* Oops */ - - return rc; -} - - -/**************** - * Get a secret key by name and store it into sk - * If NAME is NULL use the default key - */ -static int -get_seckey_byname2( GETKEY_CTX *retctx, - PKT_secret_key *sk, const char *name, int unprotect, - KBNODE *retblock ) -{ - STRLIST namelist = NULL; - int rc; - - if( !name && opt.def_secret_key && *opt.def_secret_key ) { - add_to_strlist( &namelist, opt.def_secret_key ); - rc = key_byname( retctx, namelist, NULL, sk, 1, retblock, NULL ); - } - else if( !name ) { /* use the first one as default key */ - struct getkey_ctx_s ctx; - KBNODE kb = NULL; - - assert (!retctx ); /* do we need this at all */ - assert (!retblock); - memset( &ctx, 0, sizeof ctx ); - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); - ctx.nitems = 1; - ctx.items[0].mode = KEYDB_SEARCH_MODE_FIRST; - rc = lookup( &ctx, &kb, 1 ); - if (!rc && sk ) - sk_from_block ( &ctx, sk, kb ); - release_kbnode ( kb ); - get_seckey_end( &ctx ); - } - else { - add_to_strlist( &namelist, name ); - rc = key_byname( retctx, namelist, NULL, sk, 1, retblock, NULL ); - } - - free_strlist( namelist ); - - if( !rc && unprotect ) - rc = check_secret_key( sk, 0 ); - - return rc; -} - -int -get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ) -{ - return get_seckey_byname2 ( NULL, sk, name, unlock, NULL ); -} - - -int -get_seckey_bynames( GETKEY_CTX *retctx, PKT_secret_key *sk, - STRLIST names, KBNODE *ret_keyblock ) -{ - return key_byname( retctx, names, NULL, sk, 1, ret_keyblock, NULL ); -} - - -int -get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ) -{ - int rc; - - rc = lookup( ctx, ret_keyblock, 1 ); - if ( !rc && sk && ret_keyblock ) - sk_from_block ( ctx, sk, *ret_keyblock ); - - return rc; -} - - -void -get_seckey_end( GETKEY_CTX ctx ) -{ - get_pubkey_end( ctx ); -} - - -/**************** - * Search for a key with the given fingerprint. - * FIXME: - * We should replace this with the _byname function. Thiscsan be done - * by creating a userID conforming to the unified fingerprint style. - */ -int -get_seckey_byfprint( PKT_secret_key *sk, - const byte *fprint, size_t fprint_len) -{ - int rc; - - if( fprint_len == 20 || fprint_len == 16 ) { - struct getkey_ctx_s ctx; - KBNODE kb = NULL; - - memset( &ctx, 0, sizeof ctx ); - ctx.exact = 1 ; - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); - ctx.nitems = 1; - ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16 - : KEYDB_SEARCH_MODE_FPR20; - memcpy( ctx.items[0].u.fpr, fprint, fprint_len ); - rc = lookup( &ctx, &kb, 1 ); - if (!rc && sk ) - sk_from_block ( &ctx, sk, kb ); - release_kbnode ( kb ); - get_pubkey_end( &ctx ); - } - else - rc = G10ERR_GENERAL; /* Oops */ - return rc; -} - - -/************************************************ - ************* Merging stuff ******************** - ************************************************/ - -/**************** - * merge all selfsignatures with the keys. - * FIXME: replace this at least for the public key parts - * by merge_selfsigs. - * It is still used in keyedit.c and - * at 2 or 3 other places - check whether it is really needed. - * It might be needed by the key edit and import stuff because - * the keylock is changed. - */ -void -merge_keys_and_selfsig( KBNODE keyblock ) -{ - PKT_public_key *pk = NULL; - PKT_secret_key *sk = NULL; - PKT_signature *sig; - KBNODE k; - u32 kid[2] = { 0, 0 }; - u32 sigdate = 0; - - if (keyblock && keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) { - /* divert to our new function */ - merge_selfsigs (keyblock); - return; - } - /* still need the old one because the new one can't handle secret keys */ - - for(k=keyblock; k; k = k->next ) { - if( k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - pk = k->pkt->pkt.public_key; sk = NULL; - if( pk->version < 4 ) - pk = NULL; /* not needed for old keys */ - else if( k->pkt->pkttype == PKT_PUBLIC_KEY ) - keyid_from_pk( pk, kid ); - else if( !pk->expiredate ) { /* and subkey */ - /* insert the expiration date here */ - /*FIXME!!! pk->expiredate = subkeys_expiretime( k, kid );*/ - } - sigdate = 0; - } - else if( k->pkt->pkttype == PKT_SECRET_KEY - || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { - pk = NULL; sk = k->pkt->pkt.secret_key; - if( sk->version < 4 ) - sk = NULL; - else if( k->pkt->pkttype == PKT_SECRET_KEY ) - keyid_from_sk( sk, kid ); - sigdate = 0; - } - else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE - && (sig=k->pkt->pkt.signature)->sig_class >= 0x10 - && sig->sig_class <= 0x30 && sig->version > 3 - && !(sig->sig_class == 0x18 || sig->sig_class == 0x28) - && sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) { - /* okay this is a self-signature which can be used. - * This is not used for subkey binding signature, becuase this - * is done above. - * FIXME: We should only use this if the signature is valid - * but this is time consuming - we must provide another - * way to handle this - */ - const byte *p; - u32 ed; - - p = parse_sig_subpkt( sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL ); - if( pk ) { - ed = p? pk->timestamp + buffer_to_u32(p):0; - if( sig->timestamp > sigdate ) { - pk->expiredate = ed; - sigdate = sig->timestamp; - } - } - else { - ed = p? sk->timestamp + buffer_to_u32(p):0; - if( sig->timestamp > sigdate ) { - sk->expiredate = ed; - sigdate = sig->timestamp; - } - } - } - - if(pk && (pk->expiredate==0 || - (pk->max_expiredate && pk->expiredate>pk->max_expiredate))) - pk->expiredate=pk->max_expiredate; - - if(sk && (sk->expiredate==0 || - (sk->max_expiredate && sk->expiredate>sk->max_expiredate))) - sk->expiredate=sk->max_expiredate; - } -} - -/* - * Apply information from SIGNODE (which is the valid self-signature - * associated with that UID) to the UIDNODE: - * - wether the UID has been revoked - * - assumed creation date of the UID - * - temporary store the keyflags here - * - temporary store the key expiration time here - * - mark whether the primary user ID flag hat been set. - * - store the preferences - */ -static void -fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) -{ - PKT_user_id *uid = uidnode->pkt->pkt.user_id; - PKT_signature *sig = signode->pkt->pkt.signature; - const byte *p, *sym, *hash, *zip; - size_t n, nsym, nhash, nzip; - - uid->created = 0; /* not created == invalid */ - if ( IS_UID_REV ( sig ) ) { - uid->is_revoked = 1; - return; /* has been revoked */ - } - - uid->created = sig->timestamp; /* this one is okay */ - uid->selfsigversion = sig->version; - /* If we got this far, it's not expired :) */ - uid->is_expired = 0; - uid->expiredate = sig->expiredate; - - /* store the key flags in the helper variable for later processing */ - uid->help_key_usage = 0; - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); - if ( p && n ) { - /* first octet of the keyflags */ - if ( (*p & 3) ) - uid->help_key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 12) ) - uid->help_key_usage |= PUBKEY_USAGE_ENC; - /* Note: we do not set the CERT flag here because it can be assumed - * that thre is no real policy to set it. */ - } - - /* ditto or the key expiration */ - uid->help_key_expire = 0; - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) { - uid->help_key_expire = keycreated + buffer_to_u32(p); - } - - /* Set the primary user ID flag - we will later wipe out some - * of them to only have one in our keyblock */ - uid->is_primary = 0; - p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL ); - if ( p && *p ) - uid->is_primary = 1; - /* We could also query this from the unhashed area if it is not in - * the hased area and then later try to decide which is the better - * there should be no security problem with this. - * For now we only look at the hashed one. - */ - - /* Now build the preferences list. These must come from the - hashed section so nobody can modify the ciphers a key is - willing to accept. */ - p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_SYM, &n ); - sym = p; nsym = p?n:0; - p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_HASH, &n ); - hash = p; nhash = p?n:0; - p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_COMPR, &n ); - zip = p; nzip = p?n:0; - if (uid->prefs) - m_free (uid->prefs); - n = nsym + nhash + nzip; - if (!n) - uid->prefs = NULL; - else { - uid->prefs = m_alloc (sizeof (*uid->prefs) * (n+1)); - n = 0; - for (; nsym; nsym--, n++) { - uid->prefs[n].type = PREFTYPE_SYM; - uid->prefs[n].value = *sym++; - } - for (; nhash; nhash--, n++) { - uid->prefs[n].type = PREFTYPE_HASH; - uid->prefs[n].value = *hash++; - } - for (; nzip; nzip--, n++) { - uid->prefs[n].type = PREFTYPE_ZIP; - uid->prefs[n].value = *zip++; - } - uid->prefs[n].type = PREFTYPE_NONE; /* end of list marker */ - uid->prefs[n].value = 0; - } - - /* see whether we have the MDC feature */ - uid->mdc_feature = 0; - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n); - if (p && n && (p[0] & 0x01)) - uid->mdc_feature = 1; - -} - -static void -merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) -{ - PKT_public_key *pk = NULL; - KBNODE k; - u32 kid[2]; - u32 sigdate = 0, uiddate=0, uiddate2; - KBNODE signode, uidnode, uidnode2; - u32 curtime = make_timestamp (); - unsigned int key_usage = 0; - u32 keytimestamp = 0; - u32 key_expire = 0; - int key_expire_seen = 0; - byte sigversion = 0; - - *r_revoked = 0; - if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) - BUG (); - pk = keyblock->pkt->pkt.public_key; - keytimestamp = pk->timestamp; - - keyid_from_pk( pk, kid ); - pk->main_keyid[0] = kid[0]; - pk->main_keyid[1] = kid[1]; - - if ( pk->version < 4 ) { - /* before v4 the key packet itself contains the expiration - * date and there was no way to change it, so we start with - * the one from the key packet */ - key_expire = pk->max_expiredate; - key_expire_seen = 1; - } - - /* first pass: find the latest direct key self-signature. - * We assume that the newest one overrides all others - */ - - /* In case this key was already merged */ - m_free(pk->revkey); - pk->revkey=NULL; - pk->numrevkeys=0; - - signode = NULL; - sigdate = 0; /* helper to find the latest signature */ - for(k=keyblock; k && k->pkt->pkttype != PKT_USER_ID; k = k->next ) { - if ( k->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = k->pkt->pkt.signature; - if ( sig->keyid[0] == kid[0] && sig->keyid[1]==kid[1] ) { - if ( check_key_signature( keyblock, k, NULL ) ) - ; /* signature did not verify */ - else if ( IS_KEY_REV (sig) ){ - /* key has been revoked - there is no way to override - * such a revocation, so we theoretically can stop now. - * We should not cope with expiration times for revocations - * here because we have to assume that an attacker can - * generate all kinds of signatures. However due to the - * fact that the key has been revoked it does not harm - * either and by continuing we gather some more info on - * that key. - */ - *r_revoked = 1; - } - else if ( IS_KEY_SIG (sig) ) { - /* Add any revocation keys onto the pk. This is - particularly interesting since we normally only - get data from the most recent 1F signature, but - you need multiple 1F sigs to properly handle - revocation keys (PGP does it this way, and a - revocation key could be sensitive and hence in a - different signature). */ - if(sig->revkey) { - int i; - - pk->revkey= - m_realloc(pk->revkey,sizeof(struct revocation_key)* - (pk->numrevkeys+sig->numrevkeys)); - - for(i=0;inumrevkeys;i++) - memcpy(&pk->revkey[pk->numrevkeys++], - sig->revkey[i], - sizeof(struct revocation_key)); - } - - if( sig->timestamp >= sigdate ) { - if(sig->flags.expired) - ; /* signature has expired - ignore it */ - else { - sigdate = sig->timestamp; - signode = k; - sigversion = sig->version; - - } - } - } - } - } - } - - /* Remove dupes from the revocation keys */ - - if(pk->revkey) - { - int i,j,x,changed=0; - - for(i=0;inumrevkeys;i++) - { - for(j=i+1;jnumrevkeys;j++) - { - if(memcmp(&pk->revkey[i],&pk->revkey[j], - sizeof(struct revocation_key))==0) - { - /* remove j */ - - for(x=j;xnumrevkeys-1;x++) - pk->revkey[x]=pk->revkey[x+1]; - - pk->numrevkeys--; - j--; - changed=1; - } - } - } - - if(changed) - pk->revkey=m_realloc(pk->revkey, - pk->numrevkeys*sizeof(struct revocation_key)); - } - - if ( signode ) { - /* some information from a direct key signature take precedence - * over the same information given in UID sigs. - */ - PKT_signature *sig = signode->pkt->pkt.signature; - const byte *p; - size_t n; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); - if ( p && n ) { - /* first octet of the keyflags */ - if ( (*p & 3) ) - key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 12) ) - key_usage |= PUBKEY_USAGE_ENC; - } - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) { - key_expire = keytimestamp + buffer_to_u32(p); - key_expire_seen = 1; - } - - /* mark that key as valid: one direct key signature should - * render a key as valid */ - pk->is_valid = 1; - } - - /* pass 1.5: look for key revocation signatures that were not made - by the key (i.e. did a revocation key issue a revocation for - us?). Only bother to do this if there is a revocation key in - the first place. */ - - if(pk->revkey) - for(k=keyblock; k && k->pkt->pkttype != PKT_USER_ID; k = k->next ) - { - if ( k->pkt->pkttype == PKT_SIGNATURE ) - { - PKT_signature *sig = k->pkt->pkt.signature; - - if(IS_KEY_REV(sig) && - (sig->keyid[0]!=kid[0] || sig->keyid[1]!=kid[1])) - { - /* Failure here means the sig did not verify, is was - not issued by a revocation key, or a revocation - key loop was broken. */ - - if(check_revocation_keys(pk,sig)==0) - *r_revoked=1; - - /* In the future handle subkey and cert revocations? - PGP doesn't, but it's in 2440. */ - } - } - } - - /* second pass: look at the self-signature of all user IDs */ - signode = uidnode = NULL; - sigdate = 0; /* helper to find the latest signature in one user ID */ - uiddate = 0; /* and over of all user IDs */ - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next ) { - if ( k->pkt->pkttype == PKT_USER_ID ) { - if ( uidnode && signode ) - fixup_uidnode ( uidnode, signode, keytimestamp ); - uidnode = k; - signode = NULL; - if ( sigdate > uiddate ) - uiddate = sigdate; - sigdate = 0; - } - else if ( k->pkt->pkttype == PKT_SIGNATURE && uidnode ) { - PKT_signature *sig = k->pkt->pkt.signature; - if ( sig->keyid[0] == kid[0] && sig->keyid[1]==kid[1] ) { - if ( check_key_signature( keyblock, k, NULL ) ) - ; /* signature did not verify */ - else if ( (IS_UID_SIG (sig) || IS_UID_REV (sig)) - && sig->timestamp >= sigdate ) { - /* Note: we allow to invalidate cert revocations - * by a newer signature. An attacker can't use this - * because a key should be revoced with a key revocation. - * The reason why we have to allow for that is that at - * one time an email address may become invalid but later - * the same email address may become valid again (hired, - * fired, hired again). - */ - if(sig->flags.expired) { - /* Expired uids don't get to be primary unless - they are the only uid there is. */ - uidnode->pkt->pkt.user_id->is_primary=0; - uidnode->pkt->pkt.user_id->is_expired=1; - uidnode->pkt->pkt.user_id->expiredate=sig->expiredate; - } - else { - sigdate = sig->timestamp; - signode = k; - if( sig->version > sigversion ) - sigversion = sig->version; - } - } - } - } - } - if ( uidnode && signode ) { - fixup_uidnode ( uidnode, signode, keytimestamp ); - pk->is_valid = 1; - } - - /* If the key isn't valid yet, and we have - --allow-non-selfsigned-uid set, then force it valid. */ - if(!pk->is_valid && opt.allow_non_selfsigned_uid) - { - if(opt.verbose) - log_info(_("Invalid key %08lX made valid by " - "--allow-non-selfsigned-uid\n"), - (ulong)keyid_from_pk(pk,NULL)); - - pk->is_valid = 1; - } - - /* The key STILL isn't valid, so try and find an ultimately - trusted signature. */ - if(!pk->is_valid) - { - uidnode=NULL; - - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k=k->next) - { - if ( k->pkt->pkttype == PKT_USER_ID ) - uidnode = k; - else if ( k->pkt->pkttype == PKT_SIGNATURE && uidnode ) - { - PKT_signature *sig = k->pkt->pkt.signature; - - if(sig->keyid[0] != kid[0] || sig->keyid[1]!=kid[1]) - { - PKT_public_key *ultimate_pk; - - ultimate_pk=m_alloc_clear(sizeof(*ultimate_pk)); - - /* We don't want to use the full get_pubkey to - avoid infinite recursion in certain cases. - There is no reason to check that an ultimately - trusted key is still valid - if it has been - revoked or the user should also renmove the - ultimate trust flag. */ - if(get_pubkey_direct(ultimate_pk,sig->keyid)==0 && - check_key_signature(keyblock,k,NULL)==0 && - get_ownertrust(ultimate_pk)==TRUST_ULTIMATE) - { - free_public_key(ultimate_pk); - pk->is_valid=1; - break; - } - - free_public_key(ultimate_pk); - } - } - } - } - - /* Record the highest selfsigversion so we know if this is a v3 - key through and through, or a v3 key with a v4 selfsig, which - means we can trust the preferences (if any). */ - pk->selfsigversion=sigversion; - - /* Now that we had a look at all user IDs we can now get some information - * from those user IDs. - */ - - if ( !key_usage ) { - /* find the latest user ID with key flags set */ - uiddate = 0; /* helper to find the latest user ID */ - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; - k = k->next ) { - if ( k->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = k->pkt->pkt.user_id; - if ( uid->help_key_usage && uid->created > uiddate ) { - key_usage = uid->help_key_usage; - uiddate = uid->created; - } - } - } - } - if ( !key_usage ) { /* no key flags at all: get it from the algo */ - key_usage = openpgp_pk_algo_usage ( pk->pubkey_algo ); - } - else { /* check that the usage matches the usage as given by the algo */ - int x = openpgp_pk_algo_usage ( pk->pubkey_algo ); - if ( x ) /* mask it down to the actual allowed usage */ - key_usage &= x; - } - pk->pubkey_usage = key_usage; - - if ( !key_expire_seen ) { - /* find the latest valid user ID with a key expiration set - * Note, that this may be a different one from the above because - * some user IDs may have no expiration date set */ - uiddate = 0; - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; - k = k->next ) { - if ( k->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = k->pkt->pkt.user_id; - if ( uid->help_key_expire && uid->created > uiddate ) { - key_expire = uid->help_key_expire; - uiddate = uid->created; - } - } - } - } - - /* Currently only v3 keys have a maximum expiration date, but I'll - bet v5 keys get this feature again. */ - if(key_expire==0 || (pk->max_expiredate && key_expire>pk->max_expiredate)) - key_expire=pk->max_expiredate; - - pk->has_expired = key_expire >= curtime? 0 : key_expire; - pk->expiredate = key_expire; - - /* Fixme: we should see how to get rid of the expiretime fields but - * this needs changes at other places too. */ - - /* and now find the real primary user ID and delete all others */ - uiddate = uiddate2 = 0; - uidnode = uidnode2 = NULL; - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next ) { - if ( k->pkt->pkttype == PKT_USER_ID && - !k->pkt->pkt.user_id->attrib_data) { - PKT_user_id *uid = k->pkt->pkt.user_id; - if ( uid->is_primary && uid->created > uiddate ) { - uiddate = uid->created; - uidnode = k; - } - if ( !uid->is_primary && uid->created > uiddate2 ) { - uiddate2 = uid->created; - uidnode2 = k; - } - } - } - if ( uidnode ) { - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; - k = k->next ) { - if ( k->pkt->pkttype == PKT_USER_ID && - !k->pkt->pkt.user_id->attrib_data) { - PKT_user_id *uid = k->pkt->pkt.user_id; - if ( k != uidnode ) - uid->is_primary = 0; - } - } - } - else if( uidnode2 ) { - /* none is flagged primary - use the latest user ID we have */ - uidnode2->pkt->pkt.user_id->is_primary = 1; - } - else - { - /* None of our uids were self-signed, so pick the first one to - be the primary. This is the best we can do here since - there are no self sigs to date the uids. */ - - for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; - k = k->next ) - { - if(k->pkt->pkttype==PKT_USER_ID && - !k->pkt->pkt.user_id->attrib_data) - { - k->pkt->pkt.user_id->is_primary=1; - break; - } - } - } -} - - -static void -merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) -{ - PKT_public_key *mainpk = NULL, *subpk = NULL; - PKT_signature *sig; - KBNODE k; - u32 mainkid[2]; - u32 sigdate = 0; - KBNODE signode; - u32 curtime = make_timestamp (); - unsigned int key_usage = 0; - u32 keytimestamp = 0; - u32 key_expire = 0; - const byte *p; - size_t n; - - if ( subnode->pkt->pkttype != PKT_PUBLIC_SUBKEY ) - BUG (); - mainpk = keyblock->pkt->pkt.public_key; - if ( mainpk->version < 4 ) - return; /* (actually this should never happen) */ - keyid_from_pk( mainpk, mainkid ); - subpk = subnode->pkt->pkt.public_key; - keytimestamp = subpk->timestamp; - - subpk->is_valid = 0; - subpk->main_keyid[0] = mainpk->main_keyid[0]; - subpk->main_keyid[1] = mainpk->main_keyid[1]; - - /* find the latest key binding self-signature. */ - signode = NULL; - sigdate = 0; /* helper to find the latest signature */ - for(k=subnode->next; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; - k = k->next ) { - if ( k->pkt->pkttype == PKT_SIGNATURE ) { - sig = k->pkt->pkt.signature; - if ( sig->keyid[0] == mainkid[0] && sig->keyid[1]==mainkid[1] ) { - if ( check_key_signature( keyblock, k, NULL ) ) - ; /* signature did not verify */ - else if ( IS_SUBKEY_REV (sig) ) { - /* Note that this means that the date on a - revocation sig does not matter - even if the - binding sig is dated after the revocation sig, - the subkey is still marked as revoked. This - seems ok, as it is just as easy to make new - subkeys rather than re-sign old ones as the - problem is in the distribution. Plus, PGP (7) - does this the same way. */ - subpk->is_revoked = 1; - /* although we could stop now, we continue to - * figure out other information like the old expiration - * time */ - } - else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) { - if(sig->flags.expired) - ; /* signature has expired - ignore it */ - else { - sigdate = sig->timestamp; - signode = k; - } - } - } - } - } - - if ( !signode ) { - return; /* no valid key binding */ - } - - subpk->is_valid = 1; - sig = signode->pkt->pkt.signature; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); - if ( p && n ) { - /* first octet of the keyflags */ - if ( (*p & 3) ) - key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 12) ) - key_usage |= PUBKEY_USAGE_ENC; - } - if ( !key_usage ) { /* no key flags at all: get it from the algo */ - key_usage = openpgp_pk_algo_usage ( subpk->pubkey_algo ); - } - else { /* check that the usage matches the usage as given by the algo */ - int x = openpgp_pk_algo_usage ( subpk->pubkey_algo ); - if ( x ) /* mask it down to the actual allowed usage */ - key_usage &= x; - } - subpk->pubkey_usage = key_usage; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) - key_expire = keytimestamp + buffer_to_u32(p); - else - key_expire = 0; - subpk->has_expired = key_expire >= curtime? 0 : key_expire; - subpk->expiredate = key_expire; -} - - - -/* - * Merge information from the self-signatures with the key, so that - * we can later use them more easy. - * The function works by first applying the self signatures to the - * primary key and the to each subkey. - * Here are the rules we use to decide which inormation from which - * self-signature is used: - * We check all self signatures or validity and ignore all invalid signatures. - * All signatures are then ordered by their creation date .... - * For the primary key: - * FIXME the docs - */ -static void -merge_selfsigs( KBNODE keyblock ) -{ - KBNODE k; - int revoked; - PKT_public_key *main_pk; - prefitem_t *prefs; - int mdc_feature; - - if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) { - if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) { - log_error ("expected public key but found secret key " - "- must stop\n"); - /* we better exit here becuase a public key is expected at - other places too. FIXME: Figure this out earlier and - don't get to here at all */ - g10_exit (1); - } - BUG (); - } - - merge_selfsigs_main ( keyblock, &revoked ); - main_pk = keyblock->pkt->pkt.public_key; - if ( revoked ) { - /* if the primary key has been revoked we better set the revoke - * flag on that key and all subkeys */ - for(k=keyblock; k; k = k->next ) { - if ( k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - PKT_public_key *pk = k->pkt->pkt.public_key; - pk->is_revoked = 1; - pk->main_keyid[0] = main_pk->main_keyid[0]; - pk->main_keyid[1] = main_pk->main_keyid[1]; - } - } - return; - } - - /* now merge in the data from each of the subkeys */ - for(k=keyblock; k; k = k->next ) { - if ( k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - merge_selfsigs_subkey ( keyblock, k ); - } - } - - /* If the main key is not valid, then the subkeys aren't either, - even if they have binding sigs. */ - if(!main_pk->is_valid) - for(k=keyblock; k; k=k->next) - if(k->pkt->pkttype==PKT_PUBLIC_SUBKEY) - k->pkt->pkt.public_key->is_valid=0; - - /* set the preference list of all keys to those of the primary real - * user ID. Note: we use these preferences when we don't know by - * which user ID the key has been selected. - * fixme: we should keep atoms of commonly used preferences or - * use reference counting to optimize the preference lists storage. - * FIXME: it might be better to use the intersection of - * all preferences. - * Do a similar thing for the MDC feature flag. - */ - prefs = NULL; - mdc_feature = 0; - for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) { - if (k->pkt->pkttype == PKT_USER_ID - && !k->pkt->pkt.user_id->attrib_data - && k->pkt->pkt.user_id->is_primary) { - prefs = k->pkt->pkt.user_id->prefs; - mdc_feature = k->pkt->pkt.user_id->mdc_feature; - break; - } - } - for(k=keyblock; k; k = k->next ) { - if ( k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - PKT_public_key *pk = k->pkt->pkt.public_key; - if (pk->prefs) - m_free (pk->prefs); - pk->prefs = copy_prefs (prefs); - pk->mdc_feature = mdc_feature; - } - } -} - - -/* - * Merge the secret keys from secblock into the pubblock thereby - * replacing the public (sub)keys with their secret counterparts Hmmm: - * It might be better to get away from the concept of entire secret - * keys at all and have a way to store just the real secret parts - * from the key. - */ -static void -merge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) -{ - KBNODE pub; - - assert ( pubblock->pkt->pkttype == PKT_PUBLIC_KEY ); - assert ( secblock->pkt->pkttype == PKT_SECRET_KEY ); - - for (pub=pubblock; pub; pub = pub->next ) { - if ( pub->pkt->pkttype == PKT_PUBLIC_KEY ) { - PKT_public_key *pk = pub->pkt->pkt.public_key; - PKT_secret_key *sk = secblock->pkt->pkt.secret_key; - assert ( pub == pubblock ); /* only in the first node */ - /* there is nothing to compare in this case, so just replace - * some information */ - copy_public_parts_to_secret_key ( pk, sk ); - free_public_key ( pk ); - pub->pkt->pkttype = PKT_SECRET_KEY; - pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); - } - else if ( pub->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - KBNODE sec; - PKT_public_key *pk = pub->pkt->pkt.public_key; - - /* this is more complicated: it may happen that the sequence - * of the subkeys dosn't match, so we have to find the - * appropriate secret key */ - for (sec=secblock->next; sec; sec = sec->next ) { - if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *sk = sec->pkt->pkt.secret_key; - if ( !cmp_public_secret_key ( pk, sk ) ) { - copy_public_parts_to_secret_key ( pk, sk ); - free_public_key ( pk ); - pub->pkt->pkttype = PKT_SECRET_SUBKEY; - pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); - break; - } - } - } - if ( !sec ) - BUG(); /* already checked in premerge */ - } - } -} - -/* This function checks that for every public subkey a corresponding - * secret subkey is available and deletes the public subkey otherwise. - * We need this function because we can't delete it later when we - * actually merge the secret parts into the pubring. - * The function also plays some games with the node flags. - */ -static void -premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) -{ - KBNODE last, pub; - - assert ( pubblock->pkt->pkttype == PKT_PUBLIC_KEY ); - assert ( secblock->pkt->pkttype == PKT_SECRET_KEY ); - - for (pub=pubblock,last=NULL; pub; last = pub, pub = pub->next ) { - pub->flag &= ~3; /* reset bits 0 and 1 */ - if ( pub->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - KBNODE sec; - PKT_public_key *pk = pub->pkt->pkt.public_key; - - for (sec=secblock->next; sec; sec = sec->next ) { - if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *sk = sec->pkt->pkt.secret_key; - if ( !cmp_public_secret_key ( pk, sk ) ) { - if ( sk->protect.s2k.mode == 1001 ) { - /* The secret parts are not available so - we can't use that key for signing etc. - Fix the pubkey usage */ - pk->pubkey_usage &= ~PUBKEY_USAGE_SIG; - } - /* transfer flag bits 0 and 1 to the pubblock */ - pub->flag |= (sec->flag &3); - break; - } - } - } - if ( !sec ) { - KBNODE next, ll; - - log_info ( "no secret subkey " - "for public subkey %08lX - ignoring\n", - (ulong)keyid_from_pk (pk,NULL) ); - /* we have to remove the subkey in this case */ - assert ( last ); - /* find the next subkey */ - for (next=pub->next,ll=pub; - next && pub->pkt->pkttype != PKT_PUBLIC_SUBKEY; - ll = next, next = next->next ) - ; - /* make new link */ - last->next = next; - /* release this public subkey with all sigs */ - ll->next = NULL; - release_kbnode( pub ); - /* let the loop continue */ - pub = last; - } - } - } - /* We need to copy the found bits (0 and 1) from the secret key to - the public key. This has already been done for the subkeys but - got lost on the primary key - fix it here *. */ - pubblock->flag |= (secblock->flag & 3); -} - - - - -/* See see whether the key fits - * our requirements and in case we do not - * request the primary key, we should select - * a suitable subkey. - * FIXME: Check against PGP 7 whether we still need a kludge - * to favor type 16 keys over type 20 keys when type 20 - * has not been explitely requested. - * Returns: True when a suitable key has been found. - * - * We have to distinguish four cases: FIXME! - * 1. No usage and no primary key requested - * Examples for this case are that we have a keyID to be used - * for decrytion or verification. - * 2. No usage but primary key requested - * This is the case for all functions which work on an - * entire keyblock, e.g. for editing or listing - * 3. Usage and primary key requested - * FXME - * 4. Usage but no primary key requested - * FIXME - * FIXME: Tell what is going to happen here and something about the rationale - * Note: We don't use this function if no specific usage is requested; - * This way the getkey functions can be used for plain key listings. - * - * CTX ist the keyblock we are investigating, if FOUNDK is not NULL this - * is the key we actually found by looking at the keyid or a fingerprint and - * may eitehr point to the primary or one of the subkeys. - */ - -static int -finish_lookup (GETKEY_CTX ctx) -{ - KBNODE keyblock = ctx->keyblock; - KBNODE k; - KBNODE foundk = NULL; - PKT_user_id *foundu = NULL; - #define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC) - unsigned int req_usage = ( ctx->req_usage & USAGE_MASK ); - /* Request the primary if we're certifying another key, and also - if signing data while --pgp6 or --pgp7 is on since pgp 6 and 7 - do not understand signatures made by a signing subkey. */ - int req_prim = (ctx->req_usage & PUBKEY_USAGE_CERT) || - ((opt.pgp6 || opt.pgp7) && (ctx->req_usage & PUBKEY_USAGE_SIG)); - u32 latest_date; - KBNODE latest_key; - u32 curtime = make_timestamp (); - - assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ); - - ctx->found_key = NULL; - - if (ctx->exact) { - for (k=keyblock; k; k = k->next) { - if ( (k->flag & 1) ) { - assert ( k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ); - foundk = k; - break; - } - } - } - - for (k=keyblock; k; k = k->next) { - if ( (k->flag & 2) ) { - assert (k->pkt->pkttype == PKT_USER_ID); - foundu = k->pkt->pkt.user_id; - break; - } - } - - if ( DBG_CACHE ) - log_debug( "finish_lookup: checking key %08lX (%s)(req_usage=%x)\n", - (ulong)keyid_from_pk( keyblock->pkt->pkt.public_key, NULL), - foundk? "one":"all", req_usage); - - if (!req_usage) { - latest_key = foundk? foundk:keyblock; - goto found; - } - - if (!req_usage) { - PKT_public_key *pk = foundk->pkt->pkt.public_key; - if (pk->user_id) - free_user_id (pk->user_id); - pk->user_id = scopy_user_id (foundu); - ctx->found_key = foundk; - cache_user_id( keyblock ); - return 1; /* found */ - } - - latest_date = 0; - latest_key = NULL; - /* do not look at subkeys if a certification key is requested */ - if ((!foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY) && !req_prim) { - KBNODE nextk; - /* either start a loop or check just this one subkey */ - for (k=foundk?foundk:keyblock; k; k = nextk ) { - PKT_public_key *pk; - nextk = k->next; - if ( k->pkt->pkttype != PKT_PUBLIC_SUBKEY ) - continue; - if ( foundk ) - nextk = NULL; /* what a hack */ - pk = k->pkt->pkt.public_key; - if (DBG_CACHE) - log_debug( "\tchecking subkey %08lX\n", - (ulong)keyid_from_pk( pk, NULL)); - if ( !pk->is_valid ) { - if (DBG_CACHE) - log_debug( "\tsubkey not valid\n"); - continue; - } - if ( pk->is_revoked ) { - if (DBG_CACHE) - log_debug( "\tsubkey has been revoked\n"); - continue; - } - if ( pk->has_expired ) { - if (DBG_CACHE) - log_debug( "\tsubkey has expired\n"); - continue; - } - if ( pk->timestamp > curtime && !opt.ignore_valid_from ) { - if (DBG_CACHE) - log_debug( "\tsubkey not yet valid\n"); - continue; - } - - if ( !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) { - if (DBG_CACHE) - log_debug( "\tusage does not match: want=%x have=%x\n", - req_usage, pk->pubkey_usage ); - continue; - } - - if (DBG_CACHE) - log_debug( "\tsubkey looks fine\n"); - if ( pk->timestamp > latest_date ) { - latest_date = pk->timestamp; - latest_key = k; - } - } - } - - /* Okay now try the primary key unless we want an exact - * key ID match on a subkey */ - if ((!latest_key && !(ctx->exact && foundk != keyblock)) || req_prim) { - PKT_public_key *pk; - if (DBG_CACHE && !foundk && !req_prim ) - log_debug( "\tno suitable subkeys found - trying primary\n"); - pk = keyblock->pkt->pkt.public_key; - if ( !pk->is_valid ) { - if (DBG_CACHE) - log_debug( "\tprimary key not valid\n"); - } - else if ( pk->is_revoked ) { - if (DBG_CACHE) - log_debug( "\tprimary key has been revoked\n"); - } - else if ( pk->has_expired ) { - if (DBG_CACHE) - log_debug( "\tprimary key has expired\n"); - } - else if ( !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) { - if (DBG_CACHE) - log_debug( "\tprimary key usage does not match: " - "want=%x have=%x\n", - req_usage, pk->pubkey_usage ); - } - else { /* okay */ - if (DBG_CACHE) - log_debug( "\tprimary key may be used\n"); - latest_key = keyblock; - latest_date = pk->timestamp; - } - } - - if ( !latest_key ) { - if (DBG_CACHE) - log_debug("\tno suitable key found - giving up\n"); - return 0; - } - - found: - if (DBG_CACHE) - log_debug( "\tusing key %08lX\n", - (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL) ); - - if (latest_key) { - PKT_public_key *pk = latest_key->pkt->pkt.public_key; - if (pk->user_id) - free_user_id (pk->user_id); - pk->user_id = scopy_user_id (foundu); - } - - ctx->found_key = latest_key; - - if (latest_key != keyblock && opt.verbose) { - log_info(_("using secondary key %08lX " - "instead of primary key %08lX\n"), - (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL), - (ulong)keyid_from_pk( keyblock->pkt->pkt.public_key, NULL) ); - } - - cache_user_id( keyblock ); - - return 1; /* found */ -} - - -static int -lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) -{ - int rc; - KBNODE secblock = NULL; /* helper */ - int no_suitable_key = 0; - - rc = 0; - while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems))) { - /* If we are searching for the first key we have to make sure - that the next interation does not no an implicit reset. - This can be triggered by an empty key ring. */ - if (ctx->nitems && ctx->items->mode == KEYDB_SEARCH_MODE_FIRST) - ctx->items->mode = KEYDB_SEARCH_MODE_NEXT; - - rc = keydb_get_keyblock (ctx->kr_handle, &ctx->keyblock); - if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - rc = 0; - goto skip; - } - - if ( secmode ) { - /* find the correspondig public key and use this - * this one for the selection process */ - u32 aki[2]; - KBNODE k = ctx->keyblock; - - if (k->pkt->pkttype != PKT_SECRET_KEY) - BUG(); - - keyid_from_sk (k->pkt->pkt.secret_key, aki); - k = get_pubkeyblock (aki); - if( !k ) { - if (!opt.quiet) - log_info(_("key %08lX: secret key without public key " - "- skipped\n"), (ulong)aki[1] ); - goto skip; - } - secblock = ctx->keyblock; - ctx->keyblock = k; - - premerge_public_with_secret ( ctx->keyblock, secblock ); - } - - /* warning: node flag bits 0 and 1 should be preserved by - * merge_selfsigs. For secret keys, premerge did tranfer the - * keys to the keyblock */ - merge_selfsigs ( ctx->keyblock ); - if ( finish_lookup (ctx) ) { - no_suitable_key = 0; - if ( secmode ) { - merge_public_with_secret ( ctx->keyblock, - secblock); - release_kbnode (secblock); - secblock = NULL; - } - goto found; - } - else - no_suitable_key = 1; - - skip: - /* release resources and continue search */ - if ( secmode ) { - release_kbnode( secblock ); - secblock = NULL; - } - release_kbnode( ctx->keyblock ); - ctx->keyblock = NULL; - } - - found: - if( rc && rc != -1 ) - log_error("keydb_search failed: %s\n", g10_errstr(rc)); - - if( !rc ) { - *ret_keyblock = ctx->keyblock; /* return the keyblock */ - ctx->keyblock = NULL; - } - else if (rc == -1 && no_suitable_key) - rc = secmode ? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; - else if( rc == -1 ) - rc = secmode ? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; - - if ( secmode ) { - release_kbnode( secblock ); - secblock = NULL; - } - release_kbnode( ctx->keyblock ); - ctx->keyblock = NULL; - - ctx->last_rc = rc; - return rc; -} - - - - -/**************** - * FIXME: Replace by the generic function - * It does not work as it is right now - it is used at - * 2 places: a) to get the key for an anonyous recipient - * b) to get the ultimately trusted keys. - * The a) usage might have some problems. - * - * Enumerate all primary secret keys. Caller must use these procedure: - * 1) create a void pointer and initialize it to NULL - * 2) pass this void pointer by reference to this function - * and provide space for the secret key (pass a buffer for sk) - * 3) call this function as long as it does not return -1 - * to indicate EOF. - * 4) Always call this function a last time with SK set to NULL, - * so that can free it's context. - */ -int -enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ) -{ - int rc=0; - struct { - int eof; - int first; - KEYDB_HANDLE hd; - KBNODE keyblock; - KBNODE node; - } *c = *context; - - - if( !c ) { /* make a new context */ - c = m_alloc_clear( sizeof *c ); - *context = c; - c->hd = keydb_new (1); - c->first = 1; - c->keyblock = NULL; - c->node = NULL; - } - - if( !sk ) { /* free the context */ - keydb_release (c->hd); - release_kbnode (c->keyblock); - m_free( c ); - *context = NULL; - return 0; - } - - if( c->eof ) - return -1; - - do { - /* get the next secret key from the current keyblock */ - for (; c->node; c->node = c->node->next) { - if (c->node->pkt->pkttype == PKT_SECRET_KEY - || (with_subkeys - && c->node->pkt->pkttype == PKT_SECRET_SUBKEY) ) { - copy_secret_key (sk, c->node->pkt->pkt.secret_key ); - c->node = c->node->next; - return 0; /* found */ - } - } - release_kbnode (c->keyblock); - c->keyblock = c->node = NULL; - - rc = c->first? keydb_search_first (c->hd) : keydb_search_next (c->hd); - c->first = 0; - if (rc) { - keydb_release (c->hd); c->hd = NULL; - c->eof = 1; - return -1; /* eof */ - } - - rc = keydb_get_keyblock (c->hd, &c->keyblock); - c->node = c->keyblock; - } while (!rc); - - return rc; /* error */ -} - - - -/********************************************* - *********** user ID printing helpers ******* - *********************************************/ - -/**************** - * Return a string with a printable representation of the user_id. - * this string must be freed by m_free. - */ -char* -get_user_id_string( u32 *keyid ) -{ - user_id_db_t r; - char *p; - int pass=0; - /* try it two times; second pass reads from key resources */ - do { - for(r=user_id_db; r; r = r->next ) { - keyid_list_t a; - for (a=r->keyids; a; a= a->next ) { - if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = m_alloc( r->len + 10 ); - sprintf(p, "%08lX %.*s", - (ulong)keyid[1], r->len, r->name ); - return p; - } - } - } - } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = m_alloc( 15 ); - sprintf(p, "%08lX [?]", (ulong)keyid[1] ); - return p; -} - - -char* -get_user_id_string_printable ( u32 *keyid ) -{ - char *p = get_user_id_string( keyid ); - char *p2 = utf8_to_native( p, strlen(p), 0 ); - m_free(p); - p = make_printable_string (p2, strlen (p2), 0); - m_free (p2); - return p; -} - - -char* -get_long_user_id_string( u32 *keyid ) -{ - user_id_db_t r; - char *p; - int pass=0; - /* try it two times; second pass reads from key resources */ - do { - for(r=user_id_db; r; r = r->next ) { - keyid_list_t a; - for (a=r->keyids; a; a= a->next ) { - if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = m_alloc( r->len + 20 ); - sprintf(p, "%08lX%08lX %.*s", - (ulong)keyid[0], (ulong)keyid[1], - r->len, r->name ); - return p; - } - } - } - } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = m_alloc( 25 ); - sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] ); - return p; -} - -char* -get_user_id( u32 *keyid, size_t *rn ) -{ - user_id_db_t r; - char *p; - int pass=0; - - /* try it two times; second pass reads from key resources */ - do { - for(r=user_id_db; r; r = r->next ) { - keyid_list_t a; - for (a=r->keyids; a; a= a->next ) { - if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = m_alloc( r->len ); - memcpy(p, r->name, r->len ); - *rn = r->len; - return p; - } - } - } - } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = m_strdup( _("[User id not found]") ); - *rn = strlen(p); - return p; -} - -char* -get_user_id_printable( u32 *keyid ) -{ - size_t rn; - char *p = get_user_id( keyid, &rn ); - char *p2 = utf8_to_native( p, rn, 0 ); - m_free(p); - p = make_printable_string (p2, strlen (p2), 0); - m_free (p2); - return p; -} - -KEYDB_HANDLE -get_ctx_handle(GETKEY_CTX ctx) -{ - return ctx->kr_handle; -} diff --git a/g10/gpgv.c b/g10/gpgv.c deleted file mode 100644 index dcb2a9d94..000000000 --- a/g10/gpgv.c +++ /dev/null @@ -1,374 +0,0 @@ -/* gpgv.c - The GnuPG signature verify utility - * 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 -#include -#include -#include -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM - #include /* for setmode() */ -#endif - -#define INCLUDED_BY_MAIN_MODULE 1 -#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" -#include "g10defs.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__ */ - -const char * -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 .\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 = default_strusage(level); - } - return p; -} - - - - -static void -i18n_init(void) -{ - #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); - #else - #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_TIME, "" ); - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif - bindtextdomain( PACKAGE, G10_LOCALEDIR ); - textdomain( PACKAGE ); - #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__ */ - - log_set_name("gpgv"); - init_signals(); - i18n_init(); - opt.command_fd = -1; /* no command fd */ - opt.pgp2_workarounds = 1; - opt.keyserver_options.auto_key_retrieve = 1; - opt.always_trust = 1; - opt.batch = 1; - - #if defined (__MINGW32__) || defined (__CYGWIN32__) - 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_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_logfile( NULL, pargs.r.ret_int ); break; - case oHomedir: opt.homedir = pargs.r.ret_str; 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", g10_errstr(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 ); -} - - -/* 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 -get_validity_info (PKT_public_key *pk, const byte *namehash ) -{ - return '?'; -} - -/* 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 G10ERR_GENERAL; -} -/* Stub: */ -int -get_override_session_key( DEK *dek, const char *string ) -{ - return G10ERR_GENERAL; -} -/* Stub: */ -int -decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) -{ - return G10ERR_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 G10ERR_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) -{ - 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 ../cipher/random.c */ -void random_dump_stats(void) {} -int quick_random_gen( int onoff ) { return -1;} -void randomize_buffer( byte *buffer, size_t length, int level ) {} -int random_is_faked() { return -1;} -byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;} -void set_random_seed_file( const char *name ) {} -void update_random_seed_file() {} -void fast_random_poll() {} - -/* Stubs to avoid linking of ../cipher/primegen.c */ -void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {} -MPI generate_secret_prime( unsigned nbits ) { return NULL;} -MPI generate_public_prime( unsigned nbits ) { return NULL;} -MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **ret_factors ) { return NULL;} - -/* Do not link to ../cipher/rndlinux.c */ -void rndlinux_constructor(void) {} - - -/* 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( byte *p, size_t n ) { } -void tty_print_utf8_string( byte *p, size_t n ) {} -void tty_print_utf8_string2( 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 remove_lockfiles(void) {} diff --git a/g10/import.c b/g10/import.c deleted file mode 100644 index 1fa22d174..000000000 --- a/g10/import.c +++ /dev/null @@ -1,1796 +0,0 @@ -/* import.c - * 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 -#include -#include -#include -#include -#include - -#include "options.h" -#include "packet.h" -#include "errors.h" -#include "keydb.h" -#include "memory.h" -#include "util.h" -#include "trustdb.h" -#include "main.h" -#include "i18n.h" -#include "ttyio.h" -#include "status.h" -#include "keyserver-internal.h" - -struct stats_s { - ulong count; - ulong no_user_id; - ulong imported; - ulong imported_rsa; - ulong n_uids; - ulong n_sigs; - ulong n_subk; - ulong unchanged; - ulong n_revoc; - ulong secret_read; - ulong secret_imported; - ulong secret_dups; - ulong skipped_new_keys; - ulong not_imported; -}; - - -static int import( IOBUF inp, const char* fname, - struct stats_s *stats, unsigned int options ); -static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); -static void revocation_present(KBNODE keyblock); -static void remove_bad_stuff (KBNODE keyblock); -static int import_one( const char *fname, KBNODE keyblock, - struct stats_s *stats, unsigned int options); -static int import_secret_one( const char *fname, KBNODE keyblock, - struct stats_s *stats ); -static int import_revoke_cert( const char *fname, KBNODE node, - struct stats_s *stats); -static int chk_self_sigs( const char *fname, KBNODE keyblock, - PKT_public_key *pk, u32 *keyid ); -static int delete_inv_parts( const char *fname, KBNODE keyblock, - u32 *keyid, unsigned int options ); -static int merge_blocks( const char *fname, KBNODE keyblock_orig, - KBNODE keyblock, u32 *keyid, - int *n_uids, int *n_sigs, int *n_subk ); -static int append_uid( KBNODE keyblock, KBNODE node, int *n_sigs, - const char *fname, u32 *keyid ); -static int append_key( KBNODE keyblock, KBNODE node, int *n_sigs, - const char *fname, u32 *keyid ); -static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, - const char *fname, u32 *keyid ); -static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, - const char *fname, u32 *keyid ); - - -int -parse_import_options(char *str,unsigned int *options) -{ - char *tok; - int hit=0; - struct - { - char *name; - unsigned int bit; - } import_opts[]= - { - {"allow-local-sigs",IMPORT_ALLOW_LOCAL_SIGS}, - {"repair-hkp-subkey-bug",IMPORT_REPAIR_HKP_SUBKEY_BUG}, - {"fast-import",IMPORT_FAST_IMPORT}, - {NULL,0} - }; - - while((tok=strsep(&str," ,"))) - { - int i,rev=0; - - if(ascii_strncasecmp("no-",tok,3)==0) - { - rev=1; - tok+=3; - } - - for(i=0;import_opts[i].name;i++) - { - if(ascii_strcasecmp(import_opts[i].name,tok)==0) - { - if(rev) - *options&=~import_opts[i].bit; - else - *options|=import_opts[i].bit; - hit=1; - break; - } - } - - if(!hit && !import_opts[i].name) - return 0; - } - - return hit; -} - -void * -import_new_stats_handle (void) -{ - return m_alloc_clear ( sizeof (struct stats_s) ); -} - -void -import_release_stats_handle (void *p) -{ - m_free (p); -} - -/**************** - * Import the public keys from the given filename. Input may be armored. - * This function rejects all keys which are not validly self signed on at - * least one userid. Only user ids which are self signed will be imported. - * Other signatures are not checked. - * - * Actually this function does a merge. It works like this: - * - * - get the keyblock - * - check self-signatures and remove all userids and their signatures - * without/invalid self-signatures. - * - reject the keyblock, if we have no valid userid. - * - See whether we have this key already in one of our pubrings. - * If not, simply add it to the default keyring. - * - Compare the key and the self-signatures of the new and the one in - * our keyring. If they are different something weird is going on; - * ask what to do. - * - See whether we have only non-self-signature on one user id; if not - * ask the user what to do. - * - compare the signatures: If we already have this signature, check - * that they compare okay; if not, issue a warning and ask the user. - * (consider looking at the timestamp and use the newest?) - * - Simply add the signature. Can't verify here because we may not have - * the signature's public key yet; verification is done when putting it - * into the trustdb, which is done automagically as soon as this pubkey - * is used. - * - Proceed with next signature. - * - * Key revocation certificates have special handling. - * - */ -static int -import_keys_internal( IOBUF inp, char **fnames, int nnames, - void *stats_handle, unsigned int options ) -{ - int i, rc = 0; - struct stats_s *stats = stats_handle; - - if (!stats) - stats = import_new_stats_handle (); - - if (inp) { - rc = import( inp, "[stream]", stats, options); - } - else { - if( !fnames && !nnames ) - nnames = 1; /* Ohh what a ugly hack to jump into the loop */ - - for(i=0; i < nnames; i++ ) { - const char *fname = fnames? fnames[i] : NULL; - IOBUF inp2 = iobuf_open(fname); - if( !fname ) - fname = "[stdin]"; - if( !inp2 ) - log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); - else { - rc = import( inp2, fname, stats, options ); - iobuf_close(inp2); - if( rc ) - log_error("import from `%s' failed: %s\n", fname, - g10_errstr(rc) ); - } - if( !fname ) - break; - } - } - if (!stats_handle) { - import_print_stats (stats); - import_release_stats_handle (stats); - } - /* If no fast import and we really added new keys or merged new - user ids, signatures or revocations, then update/check the - trustdb if the user specified by setting interactive or by - not setting no-auto-check-trustdb */ - if (!(options&IMPORT_FAST_IMPORT) && - (stats->imported || stats->n_uids || - stats->n_sigs || stats->n_revoc)) { - if (opt.interactive) - update_trustdb(); - else if (!opt.no_auto_check_trustdb) - check_trustdb(); - } - return rc; -} - -void -import_keys( char **fnames, int nnames, - void *stats_handle, unsigned int options ) -{ - import_keys_internal( NULL, fnames, nnames, stats_handle, options); -} - -int -import_keys_stream( IOBUF inp, void *stats_handle, unsigned int options ) -{ - return import_keys_internal( inp, NULL, 0, stats_handle, options); -} - -static int -import( IOBUF inp, const char* fname, - struct stats_s *stats, unsigned int options ) -{ - PACKET *pending_pkt = NULL; - KBNODE keyblock; - int rc = 0; - - getkey_disable_caches(); - - if( !opt.no_armor ) { /* armored reading is not disabled */ - armor_filter_context_t *afx = m_alloc_clear( sizeof *afx ); - afx->only_keyblocks = 1; - iobuf_push_filter2( inp, armor_filter, afx, 1 ); - } - - while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { - remove_bad_stuff (keyblock); - if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) - rc = import_one( fname, keyblock, stats, options ); - else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) - rc = import_secret_one( fname, keyblock, stats ); - else if( keyblock->pkt->pkttype == PKT_SIGNATURE - && keyblock->pkt->pkt.signature->sig_class == 0x20 ) - rc = import_revoke_cert( fname, keyblock, stats ); - else { - log_info( _("skipping block of type %d\n"), - keyblock->pkt->pkttype ); - } - release_kbnode(keyblock); - /* fixme: we should increment the not imported counter but this - does only make sense if we keep on going despite of errors. */ - if( rc ) - break; - if( !(++stats->count % 100) && !opt.quiet ) - log_info(_("%lu keys processed so far\n"), stats->count ); - } - if( rc == -1 ) - rc = 0; - else if( rc && rc != G10ERR_INV_KEYRING ) - log_error( _("error reading `%s': %s\n"), fname, g10_errstr(rc)); - - return rc; -} - - -void -import_print_stats (void *hd) -{ - struct stats_s *stats = hd; - - if( !opt.quiet ) { - log_info(_("Total number processed: %lu\n"), stats->count ); - if( stats->skipped_new_keys ) - log_info(_(" skipped new keys: %lu\n"), - stats->skipped_new_keys ); - if( stats->no_user_id ) - log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id ); - if( stats->imported || stats->imported_rsa ) { - log_info(_(" imported: %lu"), stats->imported ); - if( stats->imported_rsa ) - fprintf(stderr, " (RSA: %lu)", stats->imported_rsa ); - putc('\n', stderr); - } - if( stats->unchanged ) - log_info(_(" unchanged: %lu\n"), stats->unchanged ); - if( stats->n_uids ) - log_info(_(" new user IDs: %lu\n"), stats->n_uids ); - if( stats->n_subk ) - log_info(_(" new subkeys: %lu\n"), stats->n_subk ); - if( stats->n_sigs ) - log_info(_(" new signatures: %lu\n"), stats->n_sigs ); - if( stats->n_revoc ) - log_info(_(" new key revocations: %lu\n"), stats->n_revoc ); - if( stats->secret_read ) - log_info(_(" secret keys read: %lu\n"), stats->secret_read ); - if( stats->secret_imported ) - log_info(_(" secret keys imported: %lu\n"), stats->secret_imported ); - if( stats->secret_dups ) - log_info(_(" secret keys unchanged: %lu\n"), stats->secret_dups ); - if( stats->not_imported ) - log_info(_(" not imported: %lu\n"), stats->not_imported ); - } - - if( is_status_enabled() ) { - char buf[14*20]; - sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", - stats->count, - stats->no_user_id, - stats->imported, - stats->imported_rsa, - stats->unchanged, - stats->n_uids, - stats->n_subk, - stats->n_sigs, - stats->n_revoc, - stats->secret_read, - stats->secret_imported, - stats->secret_dups, - stats->skipped_new_keys, - stats->not_imported ); - write_status_text( STATUS_IMPORT_RES, buf ); - } -} - - -/**************** - * Read the next keyblock from stream A. - * PENDING_PKT should be initialzed to NULL - * and not chnaged form the caller. - * Retunr: 0 = okay, -1 no more blocks or another errorcode. - */ -static int -read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) -{ - int rc; - PACKET *pkt; - KBNODE root = NULL; - int in_cert; - - if( *pending_pkt ) { - root = new_kbnode( *pending_pkt ); - *pending_pkt = NULL; - in_cert = 1; - } - else - in_cert = 0; - pkt = m_alloc( sizeof *pkt ); - init_packet(pkt); - while( (rc=parse_packet(a, pkt)) != -1 ) { - if( rc ) { /* ignore errors */ - if( rc != G10ERR_UNKNOWN_PACKET ) { - log_error("read_block: read error: %s\n", g10_errstr(rc) ); - rc = G10ERR_INV_KEYRING; - goto ready; - } - free_packet( pkt ); - init_packet(pkt); - continue; - } - - if( !root && pkt->pkttype == PKT_SIGNATURE - && pkt->pkt.signature->sig_class == 0x20 ) { - /* this is a revocation certificate which is handled - * in a special way */ - root = new_kbnode( pkt ); - pkt = NULL; - goto ready; - } - - /* make a linked list of all packets */ - switch( pkt->pkttype ) { - case PKT_COMPRESSED: - if( pkt->pkt.compressed->algorithm < 1 - || pkt->pkt.compressed->algorithm > 2 ) { - rc = G10ERR_COMPR_ALGO; - goto ready; - } - { - compress_filter_context_t *cfx = m_alloc_clear( sizeof *cfx ); - cfx->algo = pkt->pkt.compressed->algorithm; - pkt->pkt.compressed->buf = NULL; - iobuf_push_filter2( a, compress_filter, cfx, 1 ); - } - free_packet( pkt ); - init_packet(pkt); - break; - - case PKT_RING_TRUST: - /* skip those packets */ - free_packet( pkt ); - init_packet(pkt); - break; - - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - if( in_cert ) { /* store this packet */ - *pending_pkt = pkt; - pkt = NULL; - goto ready; - } - in_cert = 1; - default: - if( in_cert ) { - if( !root ) - root = new_kbnode( pkt ); - else - add_kbnode( root, new_kbnode( pkt ) ); - pkt = m_alloc( sizeof *pkt ); - } - init_packet(pkt); - break; - } - } - ready: - if( rc == -1 && root ) - rc = 0; - - if( rc ) - release_kbnode( root ); - else - *ret_root = root; - free_packet( pkt ); - m_free( pkt ); - return rc; -} - - -static void -remove_bad_stuff (KBNODE keyblock) -{ - KBNODE node; - - for (node=keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_SIGNATURE ) { - /* delete the subpackets we used to use for the - verification cache */ - delete_sig_subpkt (node->pkt->pkt.signature->unhashed, - SIGSUBPKT_PRIV_VERIFY_CACHE); - } - } -} - -/* Walk through the subkeys on a pk to find if we have the HKP - disease: multiple subkeys with their binding sigs stripped, and the - sig for the first subkey placed after the last subkey. That is, - instead of "pk uid sig sub1 bind1 sub2 bind2 sub3 bind3" we have - "pk uid sig sub1 sub2 sub3 bind1". We can't do anything about sub2 - and sub3, as they are already lost, but we can try and rescue sub1 - by reordering the keyblock so that it reads "pk uid sig sub1 bind1 - sub2 sub3". Returns TRUE if the keyblock was modified. */ - -static int -fix_hkp_corruption(KBNODE keyblock) -{ - int changed=0,keycount=0; - KBNODE node,last=NULL,sknode=NULL; - - /* First determine if we have the problem at all. Look for 2 or - more subkeys in a row, followed by a single binding sig. */ - for(node=keyblock;node;last=node,node=node->next) - { - if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY) - { - keycount++; - if(!sknode) - sknode=node; - } - else if(node->pkt->pkttype==PKT_SIGNATURE && - node->pkt->pkt.signature->sig_class==0x18 && - keycount>=2 && node->next==NULL) - { - /* We might have the problem, as this key has two subkeys in - a row without any intervening packets. */ - - /* Sanity check */ - if(last==NULL) - break; - - /* Temporarily attach node to sknode. */ - node->next=sknode->next; - sknode->next=node; - last->next=NULL; - - if(check_key_signature(keyblock,node,NULL)) - { - /* Not a match, so undo the changes. */ - sknode->next=node->next; - last->next=node; - node->next=NULL; - break; - } - else - { - sknode->flag |= 1; /* Mark it good so we don't need to - check it again */ - changed=1; - break; - } - } - else - keycount=0; - } - - return changed; -} - - -static void -print_import_ok (PKT_public_key *pk, PKT_secret_key *sk, unsigned int reason) -{ - byte array[MAX_FINGERPRINT_LEN], *s; - char buf[MAX_FINGERPRINT_LEN*2+30], *p; - size_t i, n; - - sprintf (buf, "%u ", reason); - p = buf + strlen (buf); - - if (pk) - fingerprint_from_pk (pk, array, &n); - else - fingerprint_from_sk (sk, array, &n); - s = array; - for (i=0; i < n ; i++, s++, p += 2) - sprintf (p, "%02X", *s); - - write_status_text (STATUS_IMPORT_OK, buf); -} - - -/**************** - * Try to import one keyblock. Return an error only in serious cases, but - * never for an invalid keyblock. It uses log_error to increase the - * internal errorcount, so that invalid input can be detected by programs - * which called g10. - */ -static int -import_one( const char *fname, KBNODE keyblock, - struct stats_s *stats, unsigned int options ) -{ - PKT_public_key *pk; - PKT_public_key *pk_orig; - KBNODE node, uidnode; - KBNODE keyblock_orig = NULL; - u32 keyid[2]; - int rc = 0; - int new_key = 0; - int mod_key = 0; - - /* get the key and print some info about it */ - node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); - if( !node ) - BUG(); - - pk = node->pkt->pkt.public_key; - keyid_from_pk( pk, keyid ); - uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); - - if( opt.verbose ) { - log_info( "pub %4u%c/%08lX %s ", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk(pk) ); - if( uidnode ) - print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, - uidnode->pkt->pkt.user_id->len ); - putc('\n', stderr); - } - if( !uidnode ) { - log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]); - return 0; - } - - if (opt.interactive) { - tty_printf ("\n"); - show_basic_key_info (keyblock); - tty_printf ("\n"); - if (!cpr_get_answer_is_yes ("import.okay", - "Do you want to import this key? (y/N) ")) - return 0; - } - - clear_kbnode_flags( keyblock ); - - if((options&IMPORT_REPAIR_HKP_SUBKEY_BUG) && fix_hkp_corruption(keyblock)) - log_info(_("key %08lX: HKP subkey corruption repaired\n"), - (ulong)keyid[1]); - - rc = chk_self_sigs( fname, keyblock , pk, keyid ); - if( rc ) - return rc== -1? 0:rc; - - /* If we allow such a thing, mark unsigned uids as valid */ - if( opt.allow_non_selfsigned_uid ) - for( node=keyblock; node; node = node->next ) - if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) ) - { - char *user=utf8_to_native(node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len,0); - node->flag |= 1; - log_info( _("key %08lX: accepted non self-signed user ID '%s'\n"), - (ulong)keyid[1],user); - m_free(user); - } - - if( !delete_inv_parts( fname, keyblock, keyid, options ) ) { - if( !opt.quiet ) { - log_info( _("key %08lX: no valid user IDs\n"), - (ulong)keyid[1]); - log_info(_("this may be caused by a missing self-signature\n")); - } - stats->no_user_id++; - return 0; - } - - /* do we have this key already in one of our pubrings ? */ - pk_orig = m_alloc_clear( sizeof *pk_orig ); - rc = get_pubkey( pk_orig, keyid ); - if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY ) { - log_error( _("key %08lX: public key not found: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - } - else if ( rc && opt.merge_only ) { - if( opt.verbose ) - log_info( _("key %08lX: new key - skipped\n"), (ulong)keyid[1] ); - rc = 0; - stats->skipped_new_keys++; - } - else if( rc ) { /* insert this key */ - KEYDB_HANDLE hd = keydb_new (0); - - rc = keydb_locate_writable (hd, NULL); - if (rc) { - log_error (_("no writable keyring found: %s\n"), g10_errstr (rc)); - keydb_release (hd); - return G10ERR_GENERAL; - } - if( opt.verbose > 1 ) - log_info (_("writing to `%s'\n"), keydb_get_resource_name (hd) ); - rc = keydb_insert_keyblock (hd, keyblock ); - if (rc) - log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc)); - else - { - /* This should not be possible since we delete the - ownertrust when a key is deleted, but it can happen if - the keyring and trustdb are out of sync. It can also - be made to happen with the trusted-key command. */ - - clear_ownertrust (pk); - revalidation_mark (); - } - keydb_release (hd); - - /* we are ready */ - if( !opt.quiet ) { - char *p=get_user_id_printable (keyid); - log_info( _("key %08lX: public key \"%s\" imported\n"), - (ulong)keyid[1],p); - m_free(p); - } - if( is_status_enabled() ) { - char *us = get_long_user_id_string( keyid ); - write_status_text( STATUS_IMPORTED, us ); - m_free(us); - print_import_ok (pk,NULL, 1); - } - stats->imported++; - if( is_RSA( pk->pubkey_algo ) ) - stats->imported_rsa++; - new_key = 1; - } - else { /* merge */ - KEYDB_HANDLE hd; - int n_uids, n_sigs, n_subk; - - /* Compare the original against the new key; just to be sure nothing - * weird is going on */ - if( cmp_public_keys( pk_orig, pk ) ) { - log_error( _("key %08lX: doesn't match our copy\n"), - (ulong)keyid[1]); - goto leave; - } - - /* now read the original keyblock */ - hd = keydb_new (0); - { - byte afp[MAX_FINGERPRINT_LEN]; - size_t an; - - fingerprint_from_pk (pk_orig, afp, &an); - while (an < MAX_FINGERPRINT_LEN) - afp[an++] = 0; - rc = keydb_search_fpr (hd, afp); - } - if( rc ) { - log_error (_("key %08lX: can't locate original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - keydb_release (hd); - goto leave; - } - rc = keydb_get_keyblock (hd, &keyblock_orig ); - if (rc) { - log_error (_("key %08lX: can't read original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - keydb_release (hd); - goto leave; - } - - collapse_uids( &keyblock ); - /* and try to merge the block */ - clear_kbnode_flags( keyblock_orig ); - clear_kbnode_flags( keyblock ); - n_uids = n_sigs = n_subk = 0; - rc = merge_blocks( fname, keyblock_orig, keyblock, - keyid, &n_uids, &n_sigs, &n_subk ); - if( rc ) { - keydb_release (hd); - goto leave; - } - if( n_uids || n_sigs || n_subk ) { - mod_key = 1; - /* keyblock_orig has been updated; write */ - rc = keydb_update_keyblock (hd, keyblock_orig); - if (rc) - log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc) ); - else - revalidation_mark (); - - /* we are ready */ - if( !opt.quiet ) { - char *p=get_user_id_printable(keyid); - if( n_uids == 1 ) - log_info( _("key %08lX: \"%s\" 1 new user ID\n"), - (ulong)keyid[1], p); - else if( n_uids ) - log_info( _("key %08lX: \"%s\" %d new user IDs\n"), - (ulong)keyid[1], p, n_uids ); - if( n_sigs == 1 ) - log_info( _("key %08lX: \"%s\" 1 new signature\n"), - (ulong)keyid[1], p); - else if( n_sigs ) - log_info( _("key %08lX: \"%s\" %d new signatures\n"), - (ulong)keyid[1], p, n_sigs ); - if( n_subk == 1 ) - log_info( _("key %08lX: \"%s\" 1 new subkey\n"), - (ulong)keyid[1], p); - else if( n_subk ) - log_info( _("key %08lX: \"%s\" %d new subkeys\n"), - (ulong)keyid[1], p, n_subk ); - m_free(p); - } - - stats->n_uids +=n_uids; - stats->n_sigs +=n_sigs; - stats->n_subk +=n_subk; - - if (is_status_enabled ()) - print_import_ok (pk, NULL, - ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0))); - } - else { - if (is_status_enabled ()) - print_import_ok (pk, NULL, 0); - - if( !opt.quiet ) { - char *p=get_user_id_printable(keyid); - log_info( _("key %08lX: \"%s\" not changed\n"), - (ulong)keyid[1],p); - m_free(p); - } - stats->unchanged++; - } - keydb_release (hd); hd = NULL; - } - - leave: - release_kbnode( keyblock_orig ); - free_public_key( pk_orig ); - - revocation_present(keyblock); - - return rc; -} - - -/**************** - * Ditto for secret keys. Handling is simpler than for public keys. - * We allow secret key importing only when allow is true, this is so - * that a secret key can not be imported accidently and thereby tampering - * with the trust calculation. - */ -static int -import_secret_one( const char *fname, KBNODE keyblock, - struct stats_s *stats) -{ - PKT_secret_key *sk; - KBNODE node, uidnode; - u32 keyid[2]; - int rc = 0; - - /* get the key and print some info about it */ - node = find_kbnode( keyblock, PKT_SECRET_KEY ); - if( !node ) - BUG(); - - sk = node->pkt->pkt.secret_key; - keyid_from_sk( sk, keyid ); - uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); - - if( opt.verbose ) { - log_info( "sec %4u%c/%08lX %s ", - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid[1], datestr_from_sk(sk) ); - if( uidnode ) - print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, - uidnode->pkt->pkt.user_id->len ); - putc('\n', stderr); - } - stats->secret_read++; - - if( !uidnode ) { - log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]); - return 0; - } - - if(sk->protect.algo>110) - { - log_error(_("key %08lX: secret key with invalid cipher %d " - "- skipped\n"),(ulong)keyid[1],sk->protect.algo); - return 0; - } - - clear_kbnode_flags( keyblock ); - - /* do we have this key already in one of our secrings ? */ - rc = seckey_available( keyid ); - if( rc == G10ERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */ - KEYDB_HANDLE hd = keydb_new (1); - - /* get default resource */ - rc = keydb_locate_writable (hd, NULL); - if (rc) { - log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); - keydb_release (hd); - return G10ERR_GENERAL; - } - rc = keydb_insert_keyblock (hd, keyblock ); - if (rc) - log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc) ); - keydb_release (hd); - /* we are ready */ - if( !opt.quiet ) - log_info( _("key %08lX: secret key imported\n"), (ulong)keyid[1]); - stats->secret_imported++; - if (is_status_enabled ()) - print_import_ok (NULL, sk, 1|16); - } - else if( !rc ) { /* we can't merge secret keys */ - log_error( _("key %08lX: already in secret keyring\n"), - (ulong)keyid[1]); - stats->secret_dups++; - if (is_status_enabled ()) - print_import_ok (NULL, sk, 16); - } - else - log_error( _("key %08lX: secret key not found: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - - return rc; -} - - -/**************** - * Import a revocation certificate; this is a single signature packet. - */ -static int -import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) -{ - PKT_public_key *pk=NULL; - KBNODE onode, keyblock = NULL; - KEYDB_HANDLE hd = NULL; - u32 keyid[2]; - int rc = 0; - - assert( !node->next ); - assert( node->pkt->pkttype == PKT_SIGNATURE ); - assert( node->pkt->pkt.signature->sig_class == 0x20 ); - - keyid[0] = node->pkt->pkt.signature->keyid[0]; - keyid[1] = node->pkt->pkt.signature->keyid[1]; - - pk = m_alloc_clear( sizeof *pk ); - rc = get_pubkey( pk, keyid ); - if( rc == G10ERR_NO_PUBKEY ) { - log_info( _("key %08lX: no public key - " - "can't apply revocation certificate\n"), (ulong)keyid[1]); - rc = 0; - goto leave; - } - else if( rc ) { - log_error( _("key %08lX: public key not found: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - goto leave; - } - - /* read the original keyblock */ - hd = keydb_new (0); - { - byte afp[MAX_FINGERPRINT_LEN]; - size_t an; - - fingerprint_from_pk (pk, afp, &an); - while (an < MAX_FINGERPRINT_LEN) - afp[an++] = 0; - rc = keydb_search_fpr (hd, afp); - } - if (rc) { - log_error (_("key %08lX: can't locate original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - goto leave; - } - rc = keydb_get_keyblock (hd, &keyblock ); - if (rc) { - log_error (_("key %08lX: can't read original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); - goto leave; - } - - - /* it is okay, that node is not in keyblock because - * check_key_signature works fine for sig_class 0x20 in this - * special case. */ - rc = check_key_signature( keyblock, node, NULL); - if( rc ) { - log_error( _("key %08lX: invalid revocation certificate" - ": %s - rejected\n"), (ulong)keyid[1], g10_errstr(rc)); - goto leave; - } - - - /* check whether we already have this */ - for(onode=keyblock->next; onode; onode=onode->next ) { - if( onode->pkt->pkttype == PKT_USER_ID ) - break; - else if( onode->pkt->pkttype == PKT_SIGNATURE - && onode->pkt->pkt.signature->sig_class == 0x20 - && keyid[0] == onode->pkt->pkt.signature->keyid[0] - && keyid[1] == onode->pkt->pkt.signature->keyid[1] ) { - rc = 0; - goto leave; /* yes, we already know about it */ - } - } - - - /* insert it */ - insert_kbnode( keyblock, clone_kbnode(node), 0 ); - - /* and write the keyblock back */ - rc = keydb_update_keyblock (hd, keyblock ); - if (rc) - log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc) ); - keydb_release (hd); hd = NULL; - /* we are ready */ - if( !opt.quiet ) { - char *p=get_user_id_printable (keyid); - log_info( _("key %08lX: \"%s\" revocation certificate imported\n"), - (ulong)keyid[1],p); - m_free(p); - } - stats->n_revoc++; - revalidation_mark (); - - leave: - keydb_release (hd); - release_kbnode( keyblock ); - free_public_key( pk ); - return rc; -} - - -/**************** - * loop over the keyblock and check all self signatures. - * Mark all user-ids with a self-signature by setting flag bit 0. - * Mark all user-ids with an invalid self-signature by setting bit 1. - * This works also for subkeys, here the subkey is marked. Invalid or - * extra subkey sigs (binding or revocation) are marked for deletion. - */ -static int -chk_self_sigs( const char *fname, KBNODE keyblock, - PKT_public_key *pk, u32 *keyid ) -{ - KBNODE n,knode=NULL; - PKT_signature *sig; - int rc; - u32 bsdate=0,rsdate=0; - KBNODE bsnode=NULL,rsnode=NULL; - - for( n=keyblock; (n = find_next_kbnode(n, 0)); ) { - if(n->pkt->pkttype==PKT_PUBLIC_SUBKEY) - { - knode=n; - bsdate=0; - rsdate=0; - bsnode=NULL; - rsnode=NULL; - } - else if( n->pkt->pkttype != PKT_SIGNATURE ) - continue; - sig = n->pkt->pkt.signature; - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { - if( (sig->sig_class&~3) == 0x10 ) { - KBNODE unode = find_prev_kbnode( keyblock, n, PKT_USER_ID ); - if( !unode ) { - log_error( _("key %08lX: no user ID for signature\n"), - (ulong)keyid[1]); - return -1; /* the complete keyblock is invalid */ - } - - /* If it hasn't been marked valid yet, keep trying */ - if(!(unode->flag&1)) { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) - { - char *p=utf8_to_native(unode->pkt->pkt.user_id->name, - strlen(unode->pkt->pkt.user_id->name),0); - log_info( rc == G10ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key " - "algorithm on user id \"%s\"\n"): - _("key %08lX: invalid self-signature " - "on user id \"%s\"\n"), - (ulong)keyid[1],p); - m_free(p); - } - else - unode->flag |= 1; /* mark that signature checked */ - } - } - else if( sig->sig_class == 0x18 ) { - /* Note that this works based solely on the timestamps - like the rest of gpg. If the standard gets - revocation targets, this may need to be revised. */ - - if( !knode ) { - log_info( _("key %08lX: no subkey for subkey " - "binding signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ - } - else { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) { - log_info( rc == G10ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key algorithm\n"): - _("key %08lX: invalid subkey binding\n"), - (ulong)keyid[1]); - n->flag|=4; - } - else { - /* It's valid, so is it newer? */ - if(sig->timestamp>=bsdate) { - knode->flag |= 1; /* the subkey is valid */ - if(bsnode) { - bsnode->flag|=4; /* Delete the last binding - sig since this one is - newer */ - log_info(_("key %08lX: removed multiple subkey " - "binding\n"),(ulong)keyid[1]); - } - - bsnode=n; - bsdate=sig->timestamp; - } - else - n->flag|=4; /* older */ - } - } - } - else if( sig->sig_class == 0x28 ) { - /* We don't actually mark the subkey as revoked right - now, so just check that the revocation sig is the - most recent valid one. Note that we don't care if - the binding sig is newer than the revocation sig. - See the comment in getkey.c:merge_selfsigs_subkey for - more */ - if( !knode ) { - log_info( _("key %08lX: no subkey for subkey " - "revocation signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ - } - else { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) { - log_info( rc == G10ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key algorithm\n"): - _("key %08lX: invalid subkey revocation\n"), - (ulong)keyid[1]); - n->flag|=4; - } - else { - /* It's valid, so is it newer? */ - if(sig->timestamp>=rsdate) { - if(rsnode) { - rsnode->flag|=4; /* Delete the last revocation - sig since this one is - newer */ - log_info(_("key %08lX: removed multiple subkey " - "revocation signatures\n"),(ulong)keyid[1]); - } - - rsnode=n; - rsdate=sig->timestamp; - } - else - n->flag|=4; /* older */ - } - } - } - } - } - - return 0; -} - -/**************** - * delete all parts which are invalid and those signatures whose - * public key algorithm is not available in this implemenation; - * but consider RSA as valid, because parse/build_packets knows - * about it. - * returns: true if at least one valid user-id is left over. - */ -static int -delete_inv_parts( const char *fname, KBNODE keyblock, - u32 *keyid, unsigned int options) -{ - KBNODE node; - int nvalid=0, uid_seen=0, subkey_seen=0; - - for(node=keyblock->next; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - uid_seen = 1; - if( (node->flag & 2) || !(node->flag & 1) ) { - if( opt.verbose ) { - log_info( _("key %08lX: skipped user ID '"), - (ulong)keyid[1]); - print_utf8_string( stderr, node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len ); - fputs("'\n", stderr ); - } - delete_kbnode( node ); /* the user-id */ - /* and all following packets up to the next user-id */ - while( node->next - && node->next->pkt->pkttype != PKT_USER_ID - && node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY - && node->next->pkt->pkttype != PKT_SECRET_SUBKEY ){ - delete_kbnode( node->next ); - node = node->next; - } - } - else - nvalid++; - } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - if( (node->flag & 2) || !(node->flag & 1) ) { - if( opt.verbose ) { - log_info( _("key %08lX: skipped subkey\n"), - (ulong)keyid[1]); - } - delete_kbnode( node ); /* the subkey */ - /* and all following signature packets */ - while( node->next - && node->next->pkt->pkttype == PKT_SIGNATURE ) { - delete_kbnode( node->next ); - node = node->next; - } - } - else - subkey_seen = 1; - } - else if( node->pkt->pkttype == PKT_SIGNATURE - && check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo) - && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA ) - delete_kbnode( node ); /* build_packet() can't handle this */ - else if( node->pkt->pkttype == PKT_SIGNATURE && - !node->pkt->pkt.signature->flags.exportable && - !(options&IMPORT_ALLOW_LOCAL_SIGS) && - seckey_available( node->pkt->pkt.signature->keyid ) ) { - /* here we violate the rfc a bit by still allowing - * to import non-exportable signature when we have the - * the secret key used to create this signature - it - * seems that this makes sense */ - log_info( _("key %08lX: non exportable signature " - "(class %02x) - skipped\n"), - (ulong)keyid[1], - node->pkt->pkt.signature->sig_class ); - delete_kbnode( node ); - } - else if( node->pkt->pkttype == PKT_SIGNATURE - && node->pkt->pkt.signature->sig_class == 0x20 ) { - if( uid_seen ) { - log_error( _("key %08lX: revocation certificate " - "at wrong place - skipped\n"), - (ulong)keyid[1]); - delete_kbnode( node ); - } - else { - /* If the revocation cert is from a different key than - the one we're working on don't check it - it's - probably from a revocation key and won't be - verifiable with this key anyway. */ - - if(node->pkt->pkt.signature->keyid[0]==keyid[0] && - node->pkt->pkt.signature->keyid[1]==keyid[1]) - { - int rc = check_key_signature( keyblock, node, NULL); - if( rc ) - { - log_error( _("key %08lX: invalid revocation " - "certificate: %s - skipped\n"), - (ulong)keyid[1], g10_errstr(rc)); - delete_kbnode( node ); - } - } - } - } - else if( node->pkt->pkttype == PKT_SIGNATURE && - (node->pkt->pkt.signature->sig_class == 0x18 || - node->pkt->pkt.signature->sig_class == 0x28) && - !subkey_seen ) { - log_error( _("key %08lX: subkey signature " - "in wrong place - skipped\n"), - (ulong)keyid[1]); - delete_kbnode( node ); - } - else if( (node->flag & 4) ) /* marked for deletion */ - delete_kbnode( node ); - } - - /* note: because keyblock is the public key, it is never marked - * for deletion and so keyblock cannot change */ - commit_kbnode( &keyblock ); - return nvalid; -} - - -/**************** - * It may happen that the imported keyblock has duplicated user IDs. - * We check this here and collapse those user IDs together with their - * sigs into one. - * Returns: True if the keyblock hash changed. - */ -int -collapse_uids( KBNODE *keyblock ) -{ - KBNODE n, n2; - int in_uid; - int any=0; - u32 kid1; - - restart: - for( n = *keyblock; n; n = n->next ) { - if( n->pkt->pkttype != PKT_USER_ID ) - continue; - for( n2 = n->next; n2; n2 = n2->next ) { - if( n2->pkt->pkttype == PKT_USER_ID - && !cmp_user_ids( n->pkt->pkt.user_id, - n2->pkt->pkt.user_id ) ) { - /* found a duplicate */ - any = 1; - if( !n2->next - || n2->next->pkt->pkttype == PKT_USER_ID - || n2->next->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->next->pkt->pkttype == PKT_SECRET_SUBKEY ) { - /* no more signatures: delete the user ID - * and start over */ - remove_kbnode( keyblock, n2 ); - } - else { - /* The simple approach: Move one signature and - * then start over to delete the next one :-( */ - move_kbnode( keyblock, n2->next, n->next ); - } - goto restart; - } - } - } - if( !any ) - return 0; - - restart_sig: - /* now we may have duplicate signatures on one user ID: fix this */ - for( in_uid = 0, n = *keyblock; n; n = n->next ) { - if( n->pkt->pkttype == PKT_USER_ID ) - in_uid = 1; - else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n->pkt->pkttype == PKT_SECRET_SUBKEY ) - in_uid = 0; - else if( in_uid ) { - n2 = n; - do { - KBNODE ncmp = NULL; - for( ; n2; n2 = n2->next ) { - if( n2->pkt->pkttype == PKT_USER_ID - || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->pkt->pkttype == PKT_SECRET_SUBKEY ) - break; - if( n2->pkt->pkttype != PKT_SIGNATURE ) - ; - else if( !ncmp ) - ncmp = n2; - else if( !cmp_signatures( ncmp->pkt->pkt.signature, - n2->pkt->pkt.signature )) { - remove_kbnode( keyblock, n2 ); - goto restart_sig; - } - } - n2 = ncmp? ncmp->next : NULL; - } while( n2 ); - } - } - - if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) - kid1 = keyid_from_pk( n->pkt->pkt.public_key, NULL ); - else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) - kid1 = keyid_from_sk( n->pkt->pkt.secret_key, NULL ); - else - kid1 = 0; - log_info(_("key %08lX: duplicated user ID detected - merged\n"), - (ulong)kid1); - - return 1; -} - -/* Check for a 0x20 revocation from a revocation key that is not - present. This gets called without the benefit of merge_xxxx so you - can't rely on pk->revkey and friends. */ -static void -revocation_present(KBNODE keyblock) -{ - KBNODE onode,inode; - PKT_public_key *pk=keyblock->pkt->pkt.public_key; - - for(onode=keyblock->next;onode;onode=onode->next) - { - /* If we reach user IDs, we're done. */ - if(onode->pkt->pkttype==PKT_USER_ID) - break; - - if(onode->pkt->pkttype==PKT_SIGNATURE && - onode->pkt->pkt.signature->sig_class==0x1F && - onode->pkt->pkt.signature->revkey) - { - int idx; - PKT_signature *sig=onode->pkt->pkt.signature; - - for(idx=0;idxnumrevkeys;idx++) - { - u32 keyid[2]; - - keyid_from_fingerprint(sig->revkey[idx]->fpr, - MAX_FINGERPRINT_LEN,keyid); - - for(inode=keyblock->next;inode;inode=inode->next) - { - /* If we reach user IDs, we're done. */ - if(inode->pkt->pkttype==PKT_USER_ID) - break; - - if(inode->pkt->pkttype==PKT_SIGNATURE && - inode->pkt->pkt.signature->sig_class==0x20 && - inode->pkt->pkt.signature->keyid[0]==keyid[0] && - inode->pkt->pkt.signature->keyid[1]==keyid[1]) - { - /* Okay, we have a revocation key, and a - revocation issued by it. Do we have the key - itself? */ - int rc; - - rc=get_pubkey_byfprint(NULL,sig->revkey[idx]->fpr, - MAX_FINGERPRINT_LEN); - if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) - { - /* No, so try and get it */ - if(opt.keyserver_scheme && - opt.keyserver_options.auto_key_retrieve) - { - log_info(_("WARNING: key %08lX may be revoked: " - "fetching revocation key %08lX\n"), - (ulong)keyid_from_pk(pk,NULL), - (ulong)keyid[1]); - keyserver_import_fprint(sig->revkey[idx]->fpr, - MAX_FINGERPRINT_LEN); - - /* Do we have it now? */ - rc=get_pubkey_byfprint(NULL, - sig->revkey[idx]->fpr, - MAX_FINGERPRINT_LEN); - } - - if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) - log_info(_("WARNING: key %08lX may be revoked: " - "revocation key %08lX not present.\n"), - (ulong)keyid_from_pk(pk,NULL), - (ulong)keyid[1]); - } - } - } - } - } - } -} - -/**************** - * compare and merge the blocks - * - * o compare the signatures: If we already have this signature, check - * that they compare okay; if not, issue a warning and ask the user. - * o Simply add the signature. Can't verify here because we may not have - * the signature's public key yet; verification is done when putting it - * into the trustdb, which is done automagically as soon as this pubkey - * is used. - * Note: We indicate newly inserted packets with flag bit 0 - */ -static int -merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, - u32 *keyid, int *n_uids, int *n_sigs, int *n_subk ) -{ - KBNODE onode, node; - int rc, found; - - /* 1st: handle revocation certificates */ - for(node=keyblock->next; node; node=node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) - break; - else if( node->pkt->pkttype == PKT_SIGNATURE - && node->pkt->pkt.signature->sig_class == 0x20 ) { - /* check whether we already have this */ - found = 0; - for(onode=keyblock_orig->next; onode; onode=onode->next ) { - if( onode->pkt->pkttype == PKT_USER_ID ) - break; - else if( onode->pkt->pkttype == PKT_SIGNATURE - && onode->pkt->pkt.signature->sig_class == 0x20 - && node->pkt->pkt.signature->keyid[0] - == onode->pkt->pkt.signature->keyid[0] - && node->pkt->pkt.signature->keyid[1] - == onode->pkt->pkt.signature->keyid[1] ) { - found = 1; - break; - } - } - if( !found ) { - char *p=get_user_id_printable (keyid); - KBNODE n2 = clone_kbnode(node); - insert_kbnode( keyblock_orig, n2, 0 ); - n2->flag |= 1; - ++*n_sigs; - log_info(_("key %08lX: \"%s\" revocation certificate added\n"), - (ulong)keyid[1],p); - m_free(p); - } - } - } - - /* 2nd: merge in any direct key (0x1F) sigs */ - for(node=keyblock->next; node; node=node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) - break; - else if( node->pkt->pkttype == PKT_SIGNATURE - && node->pkt->pkt.signature->sig_class == 0x1F ) { - /* check whether we already have this */ - found = 0; - for(onode=keyblock_orig->next; onode; onode=onode->next ) { - if( onode->pkt->pkttype == PKT_USER_ID ) - break; - else if( onode->pkt->pkttype == PKT_SIGNATURE - && onode->pkt->pkt.signature->sig_class == 0x1F - && !cmp_signatures(onode->pkt->pkt.signature, - node->pkt->pkt.signature)) { - found = 1; - break; - } - } - if( !found ) { - KBNODE n2 = clone_kbnode(node); - insert_kbnode( keyblock_orig, n2, 0 ); - n2->flag |= 1; - ++*n_sigs; - log_info( _("key %08lX: direct key signature added\n"), - (ulong)keyid[1]); - } - } - } - - /* 3rd: try to merge new certificates in */ - for(onode=keyblock_orig->next; onode; onode=onode->next ) { - if( !(onode->flag & 1) && onode->pkt->pkttype == PKT_USER_ID) { - /* find the user id in the imported keyblock */ - for(node=keyblock->next; node; node=node->next ) - if( node->pkt->pkttype == PKT_USER_ID - && !cmp_user_ids( onode->pkt->pkt.user_id, - node->pkt->pkt.user_id ) ) - break; - if( node ) { /* found: merge */ - rc = merge_sigs( onode, node, n_sigs, fname, keyid ); - if( rc ) - return rc; - } - } - } - - /* 4th: add new user-ids */ - for(node=keyblock->next; node; node=node->next ) { - if( node->pkt->pkttype == PKT_USER_ID) { - /* do we have this in the original keyblock */ - for(onode=keyblock_orig->next; onode; onode=onode->next ) - if( onode->pkt->pkttype == PKT_USER_ID - && !cmp_user_ids( onode->pkt->pkt.user_id, - node->pkt->pkt.user_id ) ) - break; - if( !onode ) { /* this is a new user id: append */ - rc = append_uid( keyblock_orig, node, n_sigs, fname, keyid); - if( rc ) - return rc; - ++*n_uids; - } - } - } - - /* 5th: add new subkeys */ - for(node=keyblock->next; node; node=node->next ) { - onode = NULL; - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - /* do we have this in the original keyblock? */ - for(onode=keyblock_orig->next; onode; onode=onode->next ) - if( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY - && !cmp_public_keys( onode->pkt->pkt.public_key, - node->pkt->pkt.public_key ) ) - break; - if( !onode ) { /* this is a new subkey: append */ - rc = append_key( keyblock_orig, node, n_sigs, fname, keyid); - if( rc ) - return rc; - ++*n_subk; - } - } - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - /* do we have this in the original keyblock? */ - for(onode=keyblock_orig->next; onode; onode=onode->next ) - if( onode->pkt->pkttype == PKT_SECRET_SUBKEY - && !cmp_secret_keys( onode->pkt->pkt.secret_key, - node->pkt->pkt.secret_key ) ) - break; - if( !onode ) { /* this is a new subkey: append */ - rc = append_key( keyblock_orig, node, n_sigs, fname, keyid); - if( rc ) - return rc; - ++*n_subk; - } - } - } - - /* 6th: merge subkey certificates */ - for(onode=keyblock_orig->next; onode; onode=onode->next ) { - if( !(onode->flag & 1) - && ( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY - || onode->pkt->pkttype == PKT_SECRET_SUBKEY) ) { - /* find the subkey in the imported keyblock */ - for(node=keyblock->next; node; node=node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - && !cmp_public_keys( onode->pkt->pkt.public_key, - node->pkt->pkt.public_key ) ) - break; - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY - && !cmp_secret_keys( onode->pkt->pkt.secret_key, - node->pkt->pkt.secret_key ) ) - break; - } - if( node ) { /* found: merge */ - rc = merge_keysigs( onode, node, n_sigs, fname, keyid ); - if( rc ) - return rc; - } - } - } - - - return 0; -} - - -/**************** - * append the userid starting with NODE and all signatures to KEYBLOCK. - */ -static int -append_uid( KBNODE keyblock, KBNODE node, int *n_sigs, - const char *fname, u32 *keyid ) -{ - KBNODE n, n_where=NULL; - - assert(node->pkt->pkttype == PKT_USER_ID ); - - /* find the position */ - for( n = keyblock; n; n_where = n, n = n->next ) { - if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n->pkt->pkttype == PKT_SECRET_SUBKEY ) - break; - } - if( !n ) - n_where = NULL; - - /* and append/insert */ - while( node ) { - /* we add a clone to the original keyblock, because this - * one is released first */ - n = clone_kbnode(node); - if( n_where ) { - insert_kbnode( n_where, n, 0 ); - n_where = n; - } - else - add_kbnode( keyblock, n ); - n->flag |= 1; - node->flag |= 1; - if( n->pkt->pkttype == PKT_SIGNATURE ) - ++*n_sigs; - - node = node->next; - if( node && node->pkt->pkttype != PKT_SIGNATURE ) - break; - } - - return 0; -} - - -/**************** - * Merge the sigs from SRC onto DST. SRC and DST are both a PKT_USER_ID. - * (how should we handle comment packets here?) - */ -static int -merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, - const char *fname, u32 *keyid ) -{ - KBNODE n, n2; - int found=0; - - assert(dst->pkt->pkttype == PKT_USER_ID ); - assert(src->pkt->pkttype == PKT_USER_ID ); - - for(n=src->next; n && n->pkt->pkttype != PKT_USER_ID; n = n->next ) { - if( n->pkt->pkttype != PKT_SIGNATURE ) - continue; - if( n->pkt->pkt.signature->sig_class == 0x18 - || n->pkt->pkt.signature->sig_class == 0x28 ) - continue; /* skip signatures which are only valid on subkeys */ - found = 0; - for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next){ - if( n2->pkt->pkttype == PKT_SIGNATURE - && n->pkt->pkt.signature->keyid[0] - == n2->pkt->pkt.signature->keyid[0] - && n->pkt->pkt.signature->keyid[1] - == n2->pkt->pkt.signature->keyid[1] - && n->pkt->pkt.signature->timestamp - <= n2->pkt->pkt.signature->timestamp - && n->pkt->pkt.signature->sig_class - == n2->pkt->pkt.signature->sig_class ) { - found++; - break; - } - } - if( !found ) { - /* This signature is new or newer, append N to DST. - * We add a clone to the original keyblock, because this - * one is released first */ - n2 = clone_kbnode(n); - insert_kbnode( dst, n2, PKT_SIGNATURE ); - n2->flag |= 1; - n->flag |= 1; - ++*n_sigs; - } - } - - return 0; -} - -/**************** - * Merge the sigs from SRC onto DST. SRC and DST are both a PKT_xxx_SUBKEY. - */ -static int -merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, - const char *fname, u32 *keyid ) -{ - KBNODE n, n2; - int found=0; - - assert( dst->pkt->pkttype == PKT_PUBLIC_SUBKEY - || dst->pkt->pkttype == PKT_SECRET_SUBKEY ); - - for(n=src->next; n ; n = n->next ) { - if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n->pkt->pkttype == PKT_PUBLIC_KEY ) - break; - if( n->pkt->pkttype != PKT_SIGNATURE ) - continue; - found = 0; - for(n2=dst->next; n2; n2 = n2->next){ - if( n2->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->pkt->pkttype == PKT_PUBLIC_KEY ) - break; - if( n2->pkt->pkttype == PKT_SIGNATURE - && n->pkt->pkt.signature->keyid[0] - == n2->pkt->pkt.signature->keyid[0] - && n->pkt->pkt.signature->keyid[1] - == n2->pkt->pkt.signature->keyid[1] - && n->pkt->pkt.signature->timestamp - <= n2->pkt->pkt.signature->timestamp - && n->pkt->pkt.signature->sig_class - == n2->pkt->pkt.signature->sig_class ) { - found++; - break; - } - } - if( !found ) { - /* This signature is new or newer, append N to DST. - * We add a clone to the original keyblock, because this - * one is released first */ - n2 = clone_kbnode(n); - insert_kbnode( dst, n2, PKT_SIGNATURE ); - n2->flag |= 1; - n->flag |= 1; - ++*n_sigs; - } - } - - return 0; -} - -/**************** - * append the subkey starting with NODE and all signatures to KEYBLOCK. - * Mark all new and copied packets by setting flag bit 0. - */ -static int -append_key( KBNODE keyblock, KBNODE node, int *n_sigs, - const char *fname, u32 *keyid ) -{ - KBNODE n; - - assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ); - - while( node ) { - /* we add a clone to the original keyblock, because this - * one is released first */ - n = clone_kbnode(node); - add_kbnode( keyblock, n ); - n->flag |= 1; - node->flag |= 1; - if( n->pkt->pkttype == PKT_SIGNATURE ) - ++*n_sigs; - - node = node->next; - if( node && node->pkt->pkttype != PKT_SIGNATURE ) - break; - } - - return 0; -} diff --git a/g10/kbnode.c b/g10/kbnode.c deleted file mode 100644 index 06d28f844..000000000 --- a/g10/kbnode.c +++ /dev/null @@ -1,399 +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 -#include -#include -#include -#include -#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 = m_alloc( 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 - m_free( 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 ); - m_free( 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 ); - m_free( 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 ); - m_free( 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); - } -} diff --git a/g10/keydb.c b/g10/keydb.c deleted file mode 100644 index d8dd83fe6..000000000 --- a/g10/keydb.c +++ /dev/null @@ -1,686 +0,0 @@ -/* keydb.c - key database dispatcher - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#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 20 - -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; - -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. - */ -int -keydb_add_resource (const char *url, int force, int secret) -{ - static int any_secret, any_public; - const char *resname = url; - IOBUF iobuf = NULL; - char *filename = NULL; - 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 = G10ERR_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 = m_strdup (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 = G10ERR_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 = G10ERR_OPEN_FILE; - 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 in this case the process will be - terminated, so that on the next invocation it can - read the options file in on startup */ - try_make_homedir (filename); - rc = G10ERR_OPEN_FILE; - *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 = G10ERR_OPEN_FILE; - 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 */ - - token = keyring_register_filename (filename, secret); - if (!token) - ; /* already registered - ignore it */ - else if (used_resources >= MAX_KEYDB_RESOURCES) - rc = G10ERR_RESOURCE_LIMIT; - else - { - 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++; - } - break; - - default: - log_error ("resource type of `%s' not supported\n", url); - rc = G10ERR_GENERAL; - goto leave; - } - - /* fixme: check directory permissions and print a warning */ - - leave: - if (rc) - log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc)); - else if (secret) - any_secret = 1; - else - any_public = 1; - m_free (filename); - return rc; -} - - - - -KEYDB_HANDLE -keydb_new (int secret) -{ - KEYDB_HANDLE hd; - int i, j; - - hd = m_alloc_clear (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) { - m_free (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; - } - } - - m_free (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 G10ERR_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 = G10ERR_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 G10ERR_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 = G10ERR_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 G10ERR_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 G10ERR_GENERAL; - - rc = lock_all (hd); - if (rc) - return rc; - - switch (hd->active[idx].type) { - case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_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 G10ERR_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 = G10ERR_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 G10ERR_INV_ARG; - - 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"), - g10_errstr (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 G10ERR_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_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) -{ - int rc = -1; - - if (!hd) - return G10ERR_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); - 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); -} - - - diff --git a/g10/keydb.h b/g10/keydb.h deleted file mode 100644 index ea9e48e6d..000000000 --- a/g10/keydb.h +++ /dev/null @@ -1,265 +0,0 @@ -/* keydb.h - Key database - * 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_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_SIG(s) (((s)->sig_class==0x00) || ((s)->sig_class==0x01) || \ - ((s)->sig_class==0x02) || ((s)->sig_class==0x40)) -#define IS_CERT(s) (!IS_SIG(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 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 mark; -}; - -/* 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; -}; - -/* 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; -}; - -/*-- keydb.c --*/ -int keydb_add_resource (const char *url, int force, 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); -int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); -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 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); -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 ); -KBNODE get_pubkeyblock( u32 *keyid ); -int get_pubkey_byname( PKT_public_key *pk, const char *name, - KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd); -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_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 ); -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 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 ); -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 ); - -/*-- 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*/ diff --git a/g10/keyedit.c b/g10/keyedit.c deleted file mode 100644 index 71d2858b7..000000000 --- a/g10/keyedit.c +++ /dev/null @@ -1,3281 +0,0 @@ -/* keyedit.c - keyedit stuff - * 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 -#include -#include -#include -#include -#include -#include - -#include "options.h" -#include "packet.h" -#include "errors.h" -#include "iobuf.h" -#include "keydb.h" -#include "memory.h" -#include "photoid.h" -#include "util.h" -#include "main.h" -#include "trustdb.h" -#include "filter.h" -#include "ttyio.h" -#include "status.h" -#include "i18n.h" - -static void show_prefs( PKT_user_id *uid, int verbose ); -static void show_key_with_all_names( KBNODE keyblock, int only_marked, - int with_revoker, int with_fpr, int with_subkeys, int with_prefs ); -static void show_key_and_fingerprint( KBNODE keyblock ); -static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo ); -static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_delsig( KBNODE pub_keyblock ); -static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_addrevoker( KBNODE pub_keyblock, - KBNODE sec_keyblock, int sensitive ); -static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_select_uid( KBNODE keyblock, int idx ); -static int menu_select_key( KBNODE keyblock, int idx ); -static int count_uids( KBNODE keyblock ); -static int count_uids_with_flag( KBNODE keyblock, unsigned flag ); -static int count_keys_with_flag( KBNODE keyblock, unsigned flag ); -static int count_selected_uids( KBNODE keyblock ); -static int real_uids_left( KBNODE keyblock ); -static int count_selected_keys( KBNODE keyblock ); -static int menu_revsig( KBNODE keyblock ); -static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int enable_disable_key( KBNODE keyblock, int disable ); -static void menu_showphoto( KBNODE keyblock ); - -static int update_trust=0; - -#define CONTROL_D ('D' - 'A' + 1) - -#define NODFLG_BADSIG (1<<0) /* bad signature */ -#define NODFLG_NOKEY (1<<1) /* no public key */ -#define NODFLG_SIGERR (1<<2) /* other sig error */ - -#define NODFLG_MARK_A (1<<4) /* temporary mark */ -#define NODFLG_DELSIG (1<<5) /* to be deleted */ - -#define NODFLG_SELUID (1<<8) /* indicate the selected userid */ -#define NODFLG_SELKEY (1<<9) /* indicate the selected key */ -#define NODFLG_SELSIG (1<<10) /* indicate a selected signature */ - -struct sign_attrib { - int non_exportable,non_revocable; - struct revocation_reason_info *reason; -}; - -/**************** - * Print information about a signature, check it and return true - * if the signature is okay. NODE must be a signature packet. - */ -static int -print_and_check_one_sig( KBNODE keyblock, KBNODE node, - int *inv_sigs, int *no_key, int *oth_err, - int *is_selfsig, int print_without_key ) -{ - PKT_signature *sig = node->pkt->pkt.signature; - int rc, sigrc; - int is_rev = sig->sig_class == 0x30; - - /* TODO: Make sure a cached sig record here still has the pk that - issued it. See also keylist.c:list_keyblock_print */ - - switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) { - case 0: - node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); - sigrc = '!'; - break; - case G10ERR_BAD_SIGN: - node->flag = NODFLG_BADSIG; - sigrc = '-'; - if( inv_sigs ) - ++*inv_sigs; - break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: - node->flag = NODFLG_NOKEY; - sigrc = '?'; - if( no_key ) - ++*no_key; - break; - default: - node->flag = NODFLG_SIGERR; - sigrc = '%'; - if( oth_err ) - ++*oth_err; - break; - } - if( sigrc != '?' || print_without_key ) { - tty_printf("%s%c%c %c%c%c%c%c %08lX %s ", - is_rev? "rev":"sig",sigrc, - (sig->sig_class-0x10>0 && - sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', - sig->flags.exportable?' ':'L', - sig->flags.revocable?' ':'R', - sig->flags.policy_url?'P':' ', - sig->flags.notation?'N':' ', - sig->flags.expired?'X':' ', - (ulong)sig->keyid[1], datestr_from_sig(sig)); - if( sigrc == '%' ) - tty_printf("[%s] ", g10_errstr(rc) ); - else if( sigrc == '?' ) - ; - else if( *is_selfsig ) { - tty_printf( is_rev? _("[revocation]") - : _("[self-signature]") ); - } - else { - size_t n; - char *p = get_user_id( sig->keyid, &n ); - tty_print_utf8_string2( p, n, 40 ); - m_free(p); - } - tty_printf("\n"); - - if(sig->flags.policy_url && opt.show_policy_url) - show_policy_url(sig,3); - - if(sig->flags.notation && opt.show_notation) - show_notation(sig,3); - } - - return (sigrc == '!'); -} - - - -/**************** - * Check the keysigs and set the flags to indicate errors. - * Returns true if error found. - */ -static int -check_all_keysigs( KBNODE keyblock, int only_selected ) -{ - KBNODE kbctx; - KBNODE node; - int inv_sigs = 0; - int no_key = 0; - int oth_err = 0; - int has_selfsig = 0; - int mis_selfsig = 0; - int selected = !only_selected; - int anyuid = 0; - - for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - - if( only_selected ) - selected = (node->flag & NODFLG_SELUID); - if( selected ) { - tty_printf("uid "); - tty_print_utf8_string( uid->name, uid->len ); - tty_printf("\n"); - if( anyuid && !has_selfsig ) - mis_selfsig++; - has_selfsig = 0; - anyuid = 1; - } - } - else if( selected && node->pkt->pkttype == PKT_SIGNATURE - && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10 - || node->pkt->pkt.signature->sig_class == 0x30 ) ) { - int selfsig; - - if( print_and_check_one_sig( keyblock, node, &inv_sigs, - &no_key, &oth_err, &selfsig, 0 ) ) { - if( selfsig ) - has_selfsig = 1; - } - /* Hmmm: should we update the trustdb here? */ - } - } - if( !has_selfsig ) - mis_selfsig++; - if( inv_sigs == 1 ) - tty_printf(_("1 bad signature\n") ); - else if( inv_sigs ) - tty_printf(_("%d bad signatures\n"), inv_sigs ); - if( no_key == 1 ) - tty_printf(_("1 signature not checked due to a missing key\n") ); - else if( no_key ) - tty_printf(_("%d signatures not checked due to missing keys\n"), no_key ); - if( oth_err == 1 ) - tty_printf(_("1 signature not checked due to an error\n") ); - else if( oth_err ) - tty_printf(_("%d signatures not checked due to errors\n"), oth_err ); - if( mis_selfsig == 1 ) - tty_printf(_("1 user ID without valid self-signature detected\n")); - else if( mis_selfsig ) - tty_printf(_("%d user IDs without valid self-signatures detected\n"), - mis_selfsig); - - return inv_sigs || no_key || oth_err || mis_selfsig; -} - - - - -static int -sign_mk_attrib( PKT_signature *sig, void *opaque ) -{ - struct sign_attrib *attrib = opaque; - byte buf[8]; - - if( attrib->non_exportable ) { - buf[0] = 0; /* not exportable */ - build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 ); - } - - if( attrib->non_revocable ) { - buf[0] = 0; /* not revocable */ - build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 ); - } - - if( attrib->reason ) - revocation_reason_build_cb( sig, attrib->reason ); - - return 0; -} - - - -/**************** - * Loop over all locusr and and sign the uids after asking. - * If no user id is marked, all user ids will be signed; - * if some user_ids are marked those will be signed. - */ -static int -sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, - int local , int nonrevocable ) -{ - int rc = 0; - SK_LIST sk_list = NULL; - SK_LIST sk_rover = NULL; - PKT_secret_key *sk = NULL; - KBNODE node, uidnode; - PKT_public_key *primary_pk=NULL; - int select_all = !count_selected_uids(keyblock); - int all_v3=1; - - /* Are there any non-v3 sigs on this key already? */ - if(opt.pgp2) - for(node=keyblock;node;node=node->next) - if(node->pkt->pkttype==PKT_SIGNATURE && - node->pkt->pkt.signature->version>3) - { - all_v3=0; - break; - } - - /* build a list of all signators. - * - * We use the CERT flag to request the primary which must always - * be one which is capable of signing keys. I can't see a reason - * why to sign keys using a subkey. Implementation of USAGE_CERT - * is just a hack in getkey.c and does not mean that a subkey - * marked as certification capable will be used */ - rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT); - if( rc ) - goto leave; - - /* loop over all signators */ - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - u32 sk_keyid[2],pk_keyid[2]; - size_t n; - char *p; - int force_v4=0,class=0,selfsig=0; - u32 duration=0,timestamp=0; - - if(local || nonrevocable || - opt.cert_policy_url || opt.cert_notation_data) - force_v4=1; - - /* we have to use a copy of the sk, because make_keysig_packet - * may remove the protection from sk and if we did other - * changes to the secret key, we would save the unprotected - * version */ - if( sk ) - free_secret_key(sk); - sk = copy_secret_key( NULL, sk_rover->sk ); - keyid_from_sk( sk, sk_keyid ); - /* set mark A for all selected user ids */ - for( node=keyblock; node; node = node->next ) { - if( select_all || (node->flag & NODFLG_SELUID) ) - node->flag |= NODFLG_MARK_A; - else - node->flag &= ~NODFLG_MARK_A; - } - /* reset mark for uids which are already signed */ - uidnode = NULL; - for( node=keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - primary_pk=node->pkt->pkt.public_key; - keyid_from_pk( primary_pk, pk_keyid ); - - /* Is this a self-sig? */ - if(pk_keyid[0]==sk_keyid[0] && pk_keyid[1]==sk_keyid[1]) - { - selfsig=1; - /* Do not force a v4 sig here, otherwise it would - be difficult to remake a v3 selfsig. If this - is a v3->v4 promotion case, then we set - force_v4 later anyway. */ - force_v4=0; - } - } - else if( node->pkt->pkttype == PKT_USER_ID ) { - uidnode = (node->flag & NODFLG_MARK_A)? node : NULL; - if(uidnode) - { - char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, - uidnode->pkt->pkt.user_id->len, - 0); - - if(uidnode->pkt->pkt.user_id->is_revoked) - { - tty_printf(_("User ID \"%s\" is revoked."),user); - - if(opt.expert) - { - tty_printf("\n"); - /* No, so remove the mark and continue */ - if(!cpr_get_answer_is_yes("sign_uid.revoke_okay", - _("Are you sure you " - "still want to sign " - "it? (y/N) "))) - uidnode->flag &= ~NODFLG_MARK_A; - } - else - { - uidnode->flag &= ~NODFLG_MARK_A; - tty_printf(_(" Unable to sign.\n")); - } - } - else if(!uidnode->pkt->pkt.user_id->created) - { - tty_printf(_("WARNING: user ID \"%s\" is not " - "self-signed.\n"),user); - } - - m_free(user); - } - } - else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE - && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { - if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0] - && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) { - char buf[50]; - char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, - uidnode->pkt->pkt.user_id->len, - 0); - - /* It's a v3 self-sig. Make it into a v4 self-sig? */ - if(node->pkt->pkt.signature->version<4 && selfsig) - { - tty_printf(_("The self-signature on \"%s\"\n" - "is a PGP 2.x-style signature.\n"),user); - - /* Note that the regular PGP2 warning below - still applies if there are no v4 sigs on - this key at all. */ - - if(opt.expert) - if(cpr_get_answer_is_yes("sign_uid.v4_promote_okay", - _("Do you want to promote " - "it to an OpenPGP self-" - "signature? (y/N) "))) - { - force_v4=1; - node->flag|=NODFLG_DELSIG; - continue; - } - } - - if(!node->pkt->pkt.signature->flags.exportable && !local) - { - /* It's a local sig, and we want to make a - exportable sig. */ - tty_printf(_("Your current signature on \"%s\"\n" - "is a local signature.\n"),user); - - if(cpr_get_answer_is_yes("sign_uid.local_promote_okay", - _("Do you want to promote " - "it to a full exportable " - "signature? (y/N) "))) - { - /* Mark these for later deletion. We - don't want to delete them here, just in - case the replacement signature doesn't - happen for some reason. We only delete - these after the replacement is already - in place. */ - - node->flag|=NODFLG_DELSIG; - continue; - } - } - - /* Fixme: see whether there is a revocation in which - * case we should allow to sign it again. */ - if (!node->pkt->pkt.signature->flags.exportable && local) - tty_printf(_( - "\"%s\" was already locally signed by key %08lX\n"), - user,(ulong)sk_keyid[1] ); - else - tty_printf(_( - "\"%s\" was already signed by key %08lX\n"), - user,(ulong)sk_keyid[1] ); - sprintf (buf, "%08lX%08lX", - (ulong)sk->keyid[0], (ulong)sk->keyid[1] ); - write_status_text (STATUS_ALREADY_SIGNED, buf); - uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */ - - m_free(user); - } - } - } - /* check whether any uids are left for signing */ - if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) { - tty_printf(_("Nothing to sign with key %08lX\n"), - (ulong)sk_keyid[1] ); - continue; - } - /* Ask whether we really should sign these user id(s) */ - tty_printf("\n"); - show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 ); - tty_printf("\n"); - - if(primary_pk->expiredate && !selfsig) - { - u32 now=make_timestamp(); - - if(primary_pk->expiredate<=now) - { - tty_printf(_("This key has expired!")); - - if(opt.expert) - { - tty_printf(" "); - if(!cpr_get_answer_is_yes("sign_uid.expired_okay", - _("Are you sure you still " - "want to sign it? (y/N) "))) - continue; - } - else - { - tty_printf(_(" Unable to sign.\n")); - continue; - } - } - else - { - char *answer; - - tty_printf(_("This key is due to expire on %s.\n"), - expirestr_from_pk(primary_pk)); - - answer=cpr_get("sign_uid.expire", - _("Do you want your signature to " - "expire at the same time? (Y/n) ")); - if(answer_is_yes_no_default(answer,1)) - { - /* This fixes the signature timestamp we're going - to make as now. This is so the expiration date - is exactly correct, and not a few seconds off - (due to the time it takes to answer the - questions, enter the passphrase, etc). */ - timestamp=now; - duration=primary_pk->expiredate-now; - force_v4=1; - } - - cpr_kill_prompt(); - m_free(answer); - } - } - - /* Only ask for duration if we haven't already set it to match - the expiration of the pk */ - if(opt.ask_cert_expire && !duration && !selfsig) - duration=ask_expire_interval(1); - - if(duration) - force_v4=1; - - /* Is --pgp2 on, it's a v3 key, all the sigs on the key are - currently v3 and we're about to sign it with a v4 sig? If - so, danger! */ - if(opt.pgp2 && all_v3 && - (sk->version>3 || force_v4) && primary_pk->version<=3) - { - tty_printf(_("You may not make an OpenPGP signature on a " - "PGP 2.x key while in --pgp2 mode.\n")); - tty_printf(_("This would make the key unusable in PGP 2.x.\n")); - - if(opt.expert) - { - if(!cpr_get_answer_is_yes("sign_uid.v4_on_v3_okay", - _("Are you sure you still " - "want to sign it? (y/N) "))) - continue; - - all_v3=0; - } - else - continue; - } - - if(selfsig) - ; - else if(opt.batch) - class=0x10+opt.def_cert_check_level; - else - { - char *answer; - - tty_printf(_("How carefully have you verified the key you are " - "about to sign actually belongs\nto the person named " - "above? If you don't know what to answer, enter \"0\".\n")); - tty_printf("\n"); - tty_printf(_(" (0) I will not answer.%s\n"), - opt.def_cert_check_level==0?_(" (default)"):""); - tty_printf(_(" (1) I have not checked at all.%s\n"), - opt.def_cert_check_level==1?_(" (default)"):""); - tty_printf(_(" (2) I have done casual checking.%s\n"), - opt.def_cert_check_level==2?_(" (default)"):""); - tty_printf(_(" (3) I have done very careful checking.%s\n"), - opt.def_cert_check_level==3?_(" (default)"):""); - tty_printf("\n"); - - while(class==0) - { - answer = cpr_get("sign_uid.class",_("Your selection? ")); - - if(answer[0]=='\0') - class=0x10+opt.def_cert_check_level; /* Default */ - else if(ascii_strcasecmp(answer,"0")==0) - class=0x10; /* Generic */ - else if(ascii_strcasecmp(answer,"1")==0) - class=0x11; /* Persona */ - else if(ascii_strcasecmp(answer,"2")==0) - class=0x12; /* Casual */ - else if(ascii_strcasecmp(answer,"3")==0) - class=0x13; /* Positive */ - else - tty_printf(_("Invalid selection.\n")); - - m_free(answer); - } - } - - tty_printf(_("Are you really sure that you want to sign this key\n" - "with your key: \"")); - p = get_user_id( sk_keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); p = NULL; - tty_printf("\"\n"); - - if(selfsig) - { - tty_printf(_("\nThis will be a self-signature.\n")); - - if( local ) - tty_printf( - _("\nWARNING: the signature will not be marked " - "as non-exportable.\n")); - - if( nonrevocable ) - tty_printf( - _("\nWARNING: the signature will not be marked " - "as non-revocable.\n")); - } - else - { - if( local ) - tty_printf( - _("\nThe signature will be marked as non-exportable.\n")); - - if( nonrevocable ) - tty_printf( - _("\nThe signature will be marked as non-revocable.\n")); - - switch(class) - { - case 0x11: - tty_printf(_("\nI have not checked this key at all.\n")); - break; - - case 0x12: - tty_printf(_("\nI have checked this key casually.\n")); - break; - - case 0x13: - tty_printf(_("\nI have checked this key very carefully.\n")); - break; - } - } - - tty_printf("\n"); - - if( opt.batch && opt.answer_yes ) - ; - else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) ) - continue; - - /* now we can sign the user ids */ - reloop: /* (must use this, because we are modifing the list) */ - primary_pk = NULL; - for( node=keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) - primary_pk = node->pkt->pkt.public_key; - else if( node->pkt->pkttype == PKT_USER_ID - && (node->flag & NODFLG_MARK_A) ) { - PACKET *pkt; - PKT_signature *sig; - struct sign_attrib attrib; - - assert( primary_pk ); - memset( &attrib, 0, sizeof attrib ); - attrib.non_exportable = local; - attrib.non_revocable = nonrevocable; - node->flag &= ~NODFLG_MARK_A; - - /* we force creation of a v4 signature for local - * signatures, otherwise we would not generate the - * subpacket with v3 keys and the signature becomes - * exportable */ - - if(selfsig) - rc = make_keysig_packet( &sig, primary_pk, - node->pkt->pkt.user_id, - NULL, - sk, - 0x13, 0, force_v4?4:0, 0, 0, - keygen_add_std_prefs, primary_pk); - else - rc = make_keysig_packet( &sig, primary_pk, - node->pkt->pkt.user_id, - NULL, - sk, - class, 0, force_v4?4:0, - timestamp, duration, - sign_mk_attrib, &attrib ); - if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); - goto leave; - } - - *ret_modified = 1; /* we changed the keyblock */ - update_trust = 1; - - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE ); - goto reloop; - } - } - - /* Delete any sigs that got promoted */ - for( node=keyblock; node; node = node->next ) - if( node->flag & NODFLG_DELSIG) - delete_kbnode(node); - } /* end loop over signators */ - - leave: - release_sk_list( sk_list ); - if( sk ) - free_secret_key(sk); - return rc; -} - - - -/**************** - * Change the passphrase of the primary and all secondary keys. - * We use only one passphrase for all keys. - */ -static int -change_passphrase( KBNODE keyblock ) -{ - int rc = 0; - int changed=0; - KBNODE node; - PKT_secret_key *sk; - char *passphrase = NULL; - int no_primary_secrets = 0; - - node = find_kbnode( keyblock, PKT_SECRET_KEY ); - if( !node ) { - log_error("Oops; secret key not found anymore!\n"); - goto leave; - } - sk = node->pkt->pkt.secret_key; - - switch( is_secret_key_protected( sk ) ) { - case -1: - rc = G10ERR_PUBKEY_ALGO; - break; - case 0: - tty_printf(_("This key is not protected.\n")); - break; - default: - if( sk->protect.s2k.mode == 1001 ) { - tty_printf(_("Secret parts of primary key are not available.\n")); - no_primary_secrets = 1; - } - else { - tty_printf(_("Key is protected.\n")); - rc = check_secret_key( sk, 0 ); - if( !rc ) - passphrase = get_last_passphrase(); - } - break; - } - - /* unprotect all subkeys (use the supplied passphrase or ask)*/ - for(node=keyblock; !rc && node; node = node->next ) { - if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *subsk = node->pkt->pkt.secret_key; - set_next_passphrase( passphrase ); - rc = check_secret_key( subsk, 0 ); - if( !rc && !passphrase ) - passphrase = get_last_passphrase(); - } - } - - if( rc ) - tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc)); - else { - DEK *dek = NULL; - STRING2KEY *s2k = m_alloc_secure( sizeof *s2k ); - const char *errtext = NULL; - - tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); - - set_next_passphrase( NULL ); - for(;;) { - s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, - s2k, 2, errtext); - if( !dek ) { - errtext = _("passphrase not correctly repeated; try again"); - tty_printf ("%s.\n", errtext); - } - else if( !dek->keylen ) { - rc = 0; - tty_printf(_( "You don't want a passphrase -" - " this is probably a *bad* idea!\n\n")); - if( cpr_get_answer_is_yes("change_passwd.empty.okay", - _("Do you really want to do this? "))) - changed++; - break; - } - else { /* okay */ - rc = 0; - if( !no_primary_secrets ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - } - for(node=keyblock; !rc && node; node = node->next ) { - if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *subsk = node->pkt->pkt.secret_key; - subsk->protect.algo = dek->algo; - subsk->protect.s2k = *s2k; - rc = protect_secret_key( subsk, dek ); - } - } - if( rc ) - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); - else - changed++; - break; - } - } - m_free(s2k); - m_free(dek); - } - - leave: - m_free( passphrase ); - set_next_passphrase( NULL ); - return changed && !rc; -} - - -/**************** - * There are some keys out (due to a bug in gnupg), where the sequence - * of the packets is wrong. This function fixes that. - * Returns: true if the keyblock has been fixed. - * - * Note: This function does not work if there is more than one user ID. - */ -static int -fix_keyblock( KBNODE keyblock ) -{ - KBNODE node, last, subkey; - int fixed=0; - - /* locate key signatures of class 0x10..0x13 behind sub key packets */ - for( subkey=last=NULL, node = keyblock; node; - last=node, node = node->next ) { - switch( node->pkt->pkttype ) { - case PKT_PUBLIC_SUBKEY: - case PKT_SECRET_SUBKEY: - if( !subkey ) - subkey = last; /* actually it is the one before the subkey */ - break; - case PKT_SIGNATURE: - if( subkey ) { - PKT_signature *sig = node->pkt->pkt.signature; - if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) { - log_info(_( - "moving a key signature to the correct place\n")); - last->next = node->next; - node->next = subkey->next; - subkey->next = node; - node = last; - fixed=1; - } - } - break; - default: break; - } - } - - return fixed; -} - -/**************** - * Menu driven key editor. If sign_mode is true semi-automatical signing - * will be performed. commands are ignore in this case - * - * Note: to keep track of some selection we use node->mark MARKBIT_xxxx. - */ - -void -keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, - int sign_mode ) -{ - enum cmdids { cmdNONE = 0, - cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, - cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG, - cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, - cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, - cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY, - cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, cmdINVCMD, - cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP }; - static struct { const char *name; - enum cmdids id; - int need_sk; - int not_with_sk; - int signmode; - const char *desc; - } cmds[] = { - { N_("quit") , cmdQUIT , 0,0,1, N_("quit this menu") }, - { N_("q") , cmdQUIT , 0,0,1, NULL }, - { N_("save") , cmdSAVE , 0,0,1, N_("save and quit") }, - { N_("help") , cmdHELP , 0,0,1, N_("show this help") }, - { "?" , cmdHELP , 0,0,1, NULL }, - { N_("fpr") , cmdFPR , 0,0,1, N_("show fingerprint") }, - { N_("list") , cmdLIST , 0,0,1, N_("list key and user IDs") }, - { N_("l") , cmdLIST , 0,0,1, NULL }, - { N_("uid") , cmdSELUID , 0,0,1, N_("select user ID N") }, - { N_("key") , cmdSELKEY , 0,0,0, N_("select secondary key N") }, - { N_("check") , cmdCHECK , 0,0,1, N_("list signatures") }, - { N_("c") , cmdCHECK , 0,0,1, NULL }, - { N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") }, - { N_("s") , cmdSIGN , 0,1,1, NULL }, - { N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") }, - { N_("nrsign") , cmdNRSIGN , 0,1,1, N_("sign the key non-revocably") }, - { N_("nrlsign") , cmdNRLSIGN , 0,1,1, N_("sign the key locally and non-revocably") }, - { N_("debug") , cmdDEBUG , 0,0,0, NULL }, - { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") }, - { N_("addphoto"), cmdADDPHOTO , 1,1,0, N_("add a photo ID") }, - { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") }, - /* delphoto is really deluid in disguise */ - { N_("delphoto"), cmdDELUID , 0,1,0, NULL }, - { N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") }, - { N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") }, - { N_("addrevoker"),cmdADDREVOKER,1,1,0, N_("add a revocation key") }, - { N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") }, - { N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") }, - { N_("primary") , cmdPRIMARY , 1,1,0, N_("flag user ID as primary")}, - { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret " - "and public key listing") }, - { N_("t" ) , cmdTOGGLE , 1,0,0, NULL }, - { N_("pref") , cmdPREF , 0,1,0, N_("list preferences (expert)") }, - { N_("showpref"), cmdSHOWPREF , 0,1,0, N_("list preferences (verbose)") }, - { N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") }, - { N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") }, - { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") }, - { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") }, - { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") }, - { N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") }, - { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") }, - { N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") }, - { N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") }, - - { NULL, cmdNONE } }; - enum cmdids cmd = 0; - int rc = 0; - KBNODE keyblock = NULL; - KEYDB_HANDLE kdbhd = NULL; - KBNODE sec_keyblock = NULL; - KEYDB_HANDLE sec_kdbhd = NULL; - KBNODE cur_keyblock; - char *answer = NULL; - int redisplay = 1; - int modified = 0; - int sec_modified = 0; - int toggle; - int have_commands = !!commands; - - if ( opt.command_fd != -1 ) - ; - else if( opt.batch && !have_commands ) { - log_error(_("can't do that in batchmode\n")); - goto leave; - } - - if( sign_mode ) { - commands = NULL; - append_to_strlist( &commands, sign_mode == 1? "sign": - sign_mode == 2?"lsign": - sign_mode == 3?"nrsign":"nrlsign"); - have_commands = 1; - } - - /* get the public key */ - rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd); - if( rc ) - goto leave; - if( fix_keyblock( keyblock ) ) - modified++; - if( collapse_uids( &keyblock ) ) - modified++; - - if( !sign_mode ) {/* see whether we have a matching secret key */ - PKT_public_key *pk = keyblock->pkt->pkt.public_key; - - sec_kdbhd = keydb_new (1); - { - byte afp[MAX_FINGERPRINT_LEN]; - size_t an; - - fingerprint_from_pk (pk, afp, &an); - while (an < MAX_FINGERPRINT_LEN) - afp[an++] = 0; - rc = keydb_search_fpr (sec_kdbhd, afp); - } - if (!rc) { - rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock); - if (rc) { - log_error (_("error reading secret keyblock `%s': %s\n"), - username, g10_errstr(rc)); - } - else { - merge_keys_and_selfsig( sec_keyblock ); - if( fix_keyblock( sec_keyblock ) ) - sec_modified++; - } - } - - if (rc) { - sec_keyblock = NULL; - keydb_release (sec_kdbhd); sec_kdbhd = NULL; - rc = 0; - } - } - - if( sec_keyblock ) { - tty_printf(_("Secret key is available.\n")); - } - - toggle = 0; - cur_keyblock = keyblock; - for(;;) { /* main loop */ - int i, arg_number, photo; - const char *arg_string = ""; - char *p; - PKT_public_key *pk=keyblock->pkt->pkt.public_key; - - tty_printf("\n"); - if( redisplay ) { - show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 ); - tty_printf("\n"); - redisplay = 0; - } - do { - m_free(answer); - if( have_commands ) { - if( commands ) { - answer = m_strdup( commands->d ); - commands = commands->next; - } - else if( opt.batch ) { - answer = m_strdup("quit"); - } - else - have_commands = 0; - } - if( !have_commands ) { - answer = cpr_get_no_help("keyedit.prompt", _("Command> ")); - cpr_kill_prompt(); - } - trim_spaces(answer); - } while( *answer == '#' ); - - arg_number = 0; /* Yes, here is the init which egcc complains about */ - photo = 0; /* This too */ - if( !*answer ) - cmd = cmdLIST; - else if( *answer == CONTROL_D ) - cmd = cmdQUIT; - else if( isdigit( *answer ) ) { - cmd = cmdSELUID; - arg_number = atoi(answer); - } - 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; - } - if( sign_mode && !cmds[i].signmode ) - cmd = cmdINVCMD; - else if( cmds[i].need_sk && !sec_keyblock ) { - tty_printf(_("Need the secret key to do this.\n")); - cmd = cmdNOP; - } - else if( cmds[i].not_with_sk && sec_keyblock && toggle ) { - tty_printf(_("Please use the command \"toggle\" first.\n")); - cmd = cmdNOP; - } - else - cmd = cmds[i].id; - } - switch( cmd ) { - case cmdHELP: - for(i=0; cmds[i].name; i++ ) { - if( sign_mode && !cmds[i].signmode ) - ; - else if( cmds[i].need_sk && !sec_keyblock ) - ; /* skip if we do not have the secret key */ - else if( cmds[i].desc ) - tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); - } - break; - - case cmdLIST: - redisplay = 1; - break; - - case cmdFPR: - show_key_and_fingerprint( keyblock ); - break; - - case cmdSELUID: - if( menu_select_uid( cur_keyblock, arg_number ) ) - redisplay = 1; - break; - - case cmdSELKEY: - if( menu_select_key( cur_keyblock, arg_number ) ) - redisplay = 1; - break; - - case cmdCHECK: - /* we can only do this with the public key becuase the - * check functions can't cope with secret keys and it - * is questionable whether this would make sense at all */ - check_all_keysigs( keyblock, count_selected_uids(keyblock) ); - break; - - case cmdSIGN: /* sign (only the public key) */ - case cmdLSIGN: /* sign (only the public key) */ - case cmdNRSIGN: /* sign (only the public key) */ - case cmdNRLSIGN: /* sign (only the public key) */ - if( pk->is_revoked ) - { - tty_printf(_("Key is revoked.")); - - if(opt.expert) - { - tty_printf(" "); - if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay", - _("Are you sure you still want " - "to sign it? (y/N) "))) - break; - } - else - { - tty_printf(_(" Unable to sign.\n")); - break; - } - } - - if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) { - if( !cpr_get_answer_is_yes("keyedit.sign_all.okay", - _("Really sign all user IDs? ")) ) { - tty_printf(_("Hint: Select the user IDs to sign\n")); - break; - } - } - if( !sign_uids( keyblock, locusr, &modified, - (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN), - (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN)) - && sign_mode ) - goto do_cmd_save; - break; - - case cmdDEBUG: - dump_kbnode( cur_keyblock ); - break; - - case cmdTOGGLE: - toggle = !toggle; - cur_keyblock = toggle? sec_keyblock : keyblock; - redisplay = 1; - break; - - case cmdADDPHOTO: - if (opt.rfc2440 || opt.rfc1991 || opt.pgp2) - { - tty_printf( - _("This command is not allowed while in %s mode.\n"), - opt.rfc2440?"OpenPGP":opt.pgp2?"PGP2":"RFC-1991"); - break; - } - photo=1; - /* fall through */ - - case cmdADDUID: - if( menu_adduid( keyblock, sec_keyblock, photo ) ) { - redisplay = 1; - sec_modified = modified = 1; - merge_keys_and_selfsig( sec_keyblock ); - merge_keys_and_selfsig( keyblock ); - } - break; - - case cmdDELUID: { - int n1; - - if( !(n1=count_selected_uids(keyblock)) ) - tty_printf(_("You must select at least one user ID.\n")); - else if( real_uids_left(keyblock) < 1 ) - tty_printf(_("You can't delete the last user ID!\n")); - else if( cpr_get_answer_is_yes( - "keyedit.remove.uid.okay", - n1 > 1? _("Really remove all selected user IDs? ") - : _("Really remove this user ID? ") - ) ) { - menu_deluid( keyblock, sec_keyblock ); - redisplay = 1; - modified = 1; - if( sec_keyblock ) - sec_modified = 1; - } - } - break; - - case cmdDELSIG: { - int n1; - - if( !(n1=count_selected_uids(keyblock)) ) - tty_printf(_("You must select at least one user ID.\n")); - else if( menu_delsig( keyblock ) ) { - /* no redisplay here, because it may scroll away some - * status output of delsig */ - modified = 1; - } - } - break; - - case cmdADDKEY: - if( generate_subkeypair( keyblock, sec_keyblock ) ) { - redisplay = 1; - sec_modified = modified = 1; - merge_keys_and_selfsig( sec_keyblock ); - merge_keys_and_selfsig( keyblock ); - } - break; - - - case cmdDELKEY: { - int n1; - - if( !(n1=count_selected_keys( keyblock )) ) - tty_printf(_("You must select at least one key.\n")); - else if( sec_keyblock && !cpr_get_answer_is_yes( - "keyedit.remove.subkey.okay", - n1 > 1? - _("Do you really want to delete the selected keys? "): - _("Do you really want to delete this key? ") - )) - ; - else { - menu_delkey( keyblock, sec_keyblock ); - redisplay = 1; - modified = 1; - if( sec_keyblock ) - sec_modified = 1; - } - } - break; - - case cmdADDREVOKER: - { - int sensitive=0; - - if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0) - sensitive=1; - if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) { - redisplay = 1; - sec_modified = modified = 1; - merge_keys_and_selfsig( sec_keyblock ); - merge_keys_and_selfsig( keyblock ); - } - } - break; - - case cmdREVKEY: { - int n1; - - if( !(n1=count_selected_keys( keyblock )) ) - tty_printf(_("You must select at least one key.\n")); - else if( sec_keyblock && !cpr_get_answer_is_yes( - "keyedit.revoke.subkey.okay", - n1 > 1? - _("Do you really want to revoke the selected keys? "): - _("Do you really want to revoke this key? ") - )) - ; - else { - if( menu_revkey( keyblock, sec_keyblock ) ) { - modified = 1; - /*sec_modified = 1;*/ - } - redisplay = 1; - } - } - break; - - case cmdEXPIRE: - if( menu_expire( keyblock, sec_keyblock ) ) { - merge_keys_and_selfsig( sec_keyblock ); - merge_keys_and_selfsig( keyblock ); - sec_modified = 1; - modified = 1; - redisplay = 1; - } - break; - - case cmdPRIMARY: - if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) { - merge_keys_and_selfsig( keyblock ); - modified = 1; - redisplay = 1; - } - break; - - case cmdPASSWD: - if( change_passphrase( sec_keyblock ) ) - sec_modified = 1; - break; - - case cmdTRUST: - show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 ); - tty_printf("\n"); - if( edit_ownertrust( find_kbnode( keyblock, - PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) ) { - redisplay = 1; - /* No real need to set update_trust here as - edit_ownertrust() calls revalidation_mark() - anyway. */ - update_trust=1; - } - break; - - case cmdPREF: - show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 ); - break; - - case cmdSHOWPREF: - show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 ); - break; - - case cmdSETPREF: - keygen_set_std_prefs ( !*arg_string? "default" : arg_string, 0); - break; - - case cmdUPDPREF: - { - p = keygen_get_std_prefs (); - tty_printf (("Current preference list: %s\n"), p); - m_free (p); - } - if (cpr_get_answer_is_yes ("keyedit.updpref.okay", - count_selected_uids (keyblock)? - _("Really update the preferences" - " for the selected user IDs? "): - _("Really update the preferences? "))){ - - if ( menu_set_preferences (keyblock, sec_keyblock) ) { - merge_keys_and_selfsig (keyblock); - modified = 1; - redisplay = 1; - } - } - break; - - case cmdNOP: - break; - - case cmdREVSIG: - if( menu_revsig( keyblock ) ) { - redisplay = 1; - modified = 1; - } - break; - - case cmdENABLEKEY: - case cmdDISABLEKEY: - if( enable_disable_key( keyblock, cmd == cmdDISABLEKEY ) ) { - redisplay = 1; - modified = 1; - } - break; - - case cmdSHOWPHOTO: - menu_showphoto(keyblock); - break; - - case cmdQUIT: - if( have_commands ) - goto leave; - if( !modified && !sec_modified ) - goto leave; - if( !cpr_get_answer_is_yes("keyedit.save.okay", - _("Save changes? ")) ) { - if( cpr_enabled() - || cpr_get_answer_is_yes("keyedit.cancel.okay", - _("Quit without saving? ")) ) - goto leave; - break; - } - /* fall thru */ - case cmdSAVE: - do_cmd_save: - if( modified || sec_modified ) { - if( modified ) { - rc = keydb_update_keyblock (kdbhd, keyblock); - if( rc ) { - log_error(_("update failed: %s\n"), g10_errstr(rc) ); - break; - } - } - if( sec_modified ) { - rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock ); - if( rc ) { - log_error( _("update secret failed: %s\n"), - g10_errstr(rc) ); - break; - } - } - } - else - tty_printf(_("Key not changed so no update needed.\n")); - - if( update_trust ) - { - revalidation_mark (); - update_trust=0; - } - goto leave; - - case cmdINVCMD: - default: - tty_printf("\n"); - tty_printf(_("Invalid command (try \"help\")\n")); - break; - } - } /* end main loop */ - - leave: - release_kbnode( keyblock ); - release_kbnode( sec_keyblock ); - keydb_release (kdbhd); - m_free(answer); -} - - -/**************** - * show preferences of a public keyblock. - */ -static void -show_prefs (PKT_user_id *uid, int verbose) -{ - const prefitem_t fake={0,0}; - const prefitem_t *prefs; - int i; - - if( !uid ) - return; - - if( uid->prefs ) - prefs=uid->prefs; - else if(verbose) - prefs=&fake; - else - return; - - if (verbose) { - int any, des_seen=0, sha1_seen=0, uncomp_seen=0; - tty_printf (" Cipher: "); - for(i=any=0; prefs[i].type; i++ ) { - if( prefs[i].type == PREFTYPE_SYM ) { - const char *s = cipher_algo_to_string (prefs[i].value); - - if (any) - tty_printf (", "); - any = 1; - /* We don't want to display strings for experimental algos */ - if (s && prefs[i].value < 100 ) - tty_printf ("%s", s ); - else - tty_printf ("[%d]", prefs[i].value); - if (prefs[i].value == CIPHER_ALGO_3DES ) - des_seen = 1; - } - } - if (!des_seen) { - if (any) - tty_printf (", "); - tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES)); - } - tty_printf ("\n Hash: "); - for(i=any=0; prefs[i].type; i++ ) { - if( prefs[i].type == PREFTYPE_HASH ) { - const char *s = digest_algo_to_string (prefs[i].value); - - if (any) - tty_printf (", "); - any = 1; - /* We don't want to display strings for experimental algos */ - if (s && prefs[i].value < 100 ) - tty_printf ("%s", s ); - else - tty_printf ("[%d]", prefs[i].value); - if (prefs[i].value == DIGEST_ALGO_SHA1 ) - sha1_seen = 1; - } - } - if (!sha1_seen) { - if (any) - tty_printf (", "); - tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1)); - } - tty_printf ("\n Compression: "); - for(i=any=0; prefs[i].type; i++ ) { - if( prefs[i].type == PREFTYPE_ZIP ) { - const char *s=compress_algo_to_string(prefs[i].value); - - if (any) - tty_printf (", "); - any = 1; - /* We don't want to display strings for experimental algos */ - if (s && prefs[i].value < 100 ) - tty_printf ("%s", s ); - else - tty_printf ("[%d]", prefs[i].value); - if (prefs[i].value == 0 ) - uncomp_seen = 1; - } - } - if (!uncomp_seen) { - if (any) - tty_printf (", "); - else { - tty_printf ("%s",compress_algo_to_string(1)); - tty_printf (", "); - } - tty_printf ("%s",compress_algo_to_string(0)); - } - tty_printf ("\n Features: "); - if(uid->mdc_feature) - tty_printf ("MDC"); - tty_printf("\n"); - } - else { - tty_printf(" "); - for(i=0; prefs[i].type; i++ ) { - tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' : - prefs[i].type == PREFTYPE_HASH ? 'H' : - prefs[i].type == PREFTYPE_ZIP ? 'Z':'?', - prefs[i].value); - } - if (uid->mdc_feature) - tty_printf (" [mdc]"); - tty_printf("\n"); - } -} - - -/* This is the version of show_key_with_all_names used when - opt.with_colons is used. It prints all available data in a easy to - parse format and does not translate utf8 */ -static void -show_key_with_all_names_colon (KBNODE keyblock) -{ - KBNODE node; - int i, j; - byte pk_version=0; - - /* the keys */ - for ( node = keyblock; node; node = node->next ) - { - if (node->pkt->pkttype == PKT_PUBLIC_KEY - || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) - { - PKT_public_key *pk = node->pkt->pkt.public_key; - int otrust=0, trust=0; - u32 keyid[2]; - - if (node->pkt->pkttype == PKT_PUBLIC_KEY) - { - trust = get_validity_info (pk, NULL); - otrust = get_ownertrust_info (pk); - pk_version = pk->version; - } - - keyid_from_pk (pk, keyid); - - fputs (node->pkt->pkttype == PKT_PUBLIC_KEY?"pub:":"sub:", stdout); - if (!pk->is_valid) - putchar ('i'); - else if (pk->is_revoked) - putchar ('r'); - else if (pk->has_expired) - putchar ('e'); - else - putchar (trust); - printf (":%u:%d:%08lX%08lX:%lu:%lu:", - nbits_from_pk (pk), - pk->pubkey_algo, - (ulong)keyid[0], (ulong)keyid[1], - (ulong)pk->timestamp, - (ulong)pk->expiredate ); - if (pk->local_id) - printf ("%lu", pk->local_id); - putchar (':'); - putchar (otrust); - putchar(':'); - putchar('\n'); - - print_fingerprint (pk, NULL, 0); - - /* print the revoker record */ - if( !pk->revkey && pk->numrevkeys ) - BUG(); - else - { - for (i=0; i < pk->numrevkeys; i++) - { - byte *p; - - printf ("rvk:::%d::::::", pk->revkey[i].algid); - p = pk->revkey[i].fpr; - for (j=0; j < 20; j++, p++ ) - printf ("%02X", *p); - printf (":%02x%s:\n", pk->revkey[i].class, - (pk->revkey[i].class&0x40)?"s":""); - } - } - } - } - - /* the user ids */ - i = 0; - for (node = keyblock; node; node = node->next) - { - if ( node->pkt->pkttype == PKT_USER_ID ) - { - PKT_user_id *uid = node->pkt->pkt.user_id; - int trustletter = '?'; - - ++i; - if(uid->attrib_data) - { - printf ("uat:%c::::::::%u %lu", trustletter, - uid->numattribs,uid->attrib_len); - } - else - { - printf ("uid:%c::::::::", trustletter); - print_string (stdout, uid->name, uid->len, ':'); - } - putchar (':'); - /* signature class */ - putchar (':'); - /* capabilities */ - putchar (':'); - /* preferences */ - if (pk_version>3 || uid->selfsigversion>3) - { - const prefitem_t *prefs = uid->prefs; - - for (j=0; prefs && prefs[j].type; j++) - { - if (j) - putchar (' '); - printf ("%c%d", prefs[j].type == PREFTYPE_SYM ? 'S' : - prefs[j].type == PREFTYPE_HASH ? 'H' : - prefs[j].type == PREFTYPE_ZIP ? 'Z':'?', - prefs[j].value); - } - if (uid->mdc_feature) - printf (",mdc"); - } - putchar (':'); - /* flags */ - printf ("%d,", i); - if (uid->is_primary) - putchar ('p'); - if (uid->is_revoked) - putchar ('r'); - if (uid->is_expired) - putchar ('e'); - if ((node->flag & NODFLG_SELUID)) - putchar ('s'); - if ((node->flag & NODFLG_MARK_A)) - putchar ('m'); - putchar (':'); - putchar('\n'); - } - } -} - - -/**************** - * Display the key a the user ids, if only_marked is true, do only - * so for user ids with mark A flag set and dont display the index number - */ -static void -show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, - int with_fpr, int with_subkeys, int with_prefs ) -{ - KBNODE node; - int i, rc; - int do_warn = 0; - byte pk_version=0; - - if (opt.with_colons) - { - show_key_with_all_names_colon (keyblock); - return; - } - - /* the keys */ - for( node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY - || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) { - PKT_public_key *pk = node->pkt->pkt.public_key; - int otrust=0, trust=0; - - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - /* do it here, so that debug messages don't clutter the - * output */ - static int did_warn = 0; - - trust = get_validity_info (pk, NULL); - otrust = get_ownertrust_info (pk); - - /* Show a warning once */ - if (!did_warn - && (get_validity (pk, NULL) & TRUST_FLAG_PENDING_CHECK)) { - did_warn = 1; - do_warn = 1; - } - - pk_version=pk->version; - } - - if(with_revoker) { - if( !pk->revkey && pk->numrevkeys ) - BUG(); - else - for(i=0;inumrevkeys;i++) { - u32 r_keyid[2]; - char *user; - - keyid_from_fingerprint(pk->revkey[i].fpr, - MAX_FINGERPRINT_LEN,r_keyid); - - user=get_user_id_string (r_keyid); - tty_printf (_("This key may be revoked by %s key "), - pubkey_algo_to_string (pk->revkey[i].algid)); - tty_print_utf8_string (user, strlen (user)); - if ((pk->revkey[i].class&0x40)) - tty_printf (_(" (sensitive)")); - tty_printf ("\n"); - m_free(user); - } - } - - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", - (node->flag & NODFLG_SELKEY)? '*':' ', - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk), - expirestr_from_pk(pk) ); - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - tty_printf(_(" trust: %c/%c"), otrust, trust ); - if( node->pkt->pkttype == PKT_PUBLIC_KEY - && (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) { - tty_printf("\n*** "); - tty_printf(_("This key has been disabled")); - } - - if( with_fpr ) { - tty_printf("\n"); - print_fingerprint ( pk, NULL, 2 ); - } - } - tty_printf("\n"); - } - else if( node->pkt->pkttype == PKT_SECRET_KEY - || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) { - PKT_secret_key *sk = node->pkt->pkt.secret_key; - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", - (node->flag & NODFLG_SELKEY)? '*':' ', - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid_from_sk(sk,NULL), - datestr_from_sk(sk), - expirestr_from_sk(sk) ); - tty_printf("\n"); - } - else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE - && node->pkt->pkt.signature->sig_class == 0x28 ) { - PKT_signature *sig = node->pkt->pkt.signature; - - rc = check_key_signature( keyblock, node, NULL ); - if( !rc ) - tty_printf( _("rev! subkey has been revoked: %s\n"), - datestr_from_sig( sig ) ); - else if( rc == G10ERR_BAD_SIGN ) - tty_printf( _("rev- faked revocation found\n") ); - else if( rc ) - tty_printf( _("rev? problem checking revocation: %s\n"), - g10_errstr(rc) ); - } - } - /* the user ids */ - i = 0; - for( node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - ++i; - if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){ - if( only_marked ) - tty_printf(" "); - else if( node->flag & NODFLG_SELUID ) - tty_printf("(%d)* ", i); - else if( uid->is_primary ) - tty_printf("(%d). ", i); - else - tty_printf("(%d) ", i); - if ( uid->is_revoked ) - tty_printf ("[revoked] "); - if ( uid->is_expired ) - tty_printf ("[expired] "); - tty_print_utf8_string( uid->name, uid->len ); - tty_printf("\n"); - if( with_prefs ) - { - if(pk_version>3 || uid->selfsigversion>3) - show_prefs (uid, with_prefs == 2); - else - tty_printf(_("There are no preferences on a " - "PGP 2.x-style user ID.\n")); - } - } - } - } - - if (do_warn) - tty_printf (_("Please note that the shown key validity " - "is not necessarily correct\n" - "unless you restart the program.\n")); - -} - - -/* Display basic key information. This fucntion is suitable to show - information on the key without any dependencies on the trustdb or - any other internal GnuPG stuff. KEYBLOCK may either be a public or - a secret key.*/ -void -show_basic_key_info ( KBNODE keyblock ) -{ - KBNODE node; - int i; - - /* The primary key */ - for (node = keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_PUBLIC_KEY) - { - PKT_public_key *pk = node->pkt->pkt.public_key; - - /* Note, we use the same format string as in other show - functions to make the translation job easier. */ - tty_printf (_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", - ' ', - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk), - expirestr_from_pk(pk) ); - tty_printf("\n"); - print_fingerprint ( pk, NULL, 3 ); - tty_printf("\n"); - } - else if (node->pkt->pkttype == PKT_SECRET_KEY) - { - PKT_secret_key *sk = node->pkt->pkt.secret_key; - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", - ' ', - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid_from_sk(sk,NULL), - datestr_from_sk(sk), - expirestr_from_sk(sk) ); - tty_printf("\n"); - print_fingerprint (NULL, sk, 3 ); - tty_printf("\n"); - } - } - - /* The user IDs. */ - for (i=0, node = keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID) - { - PKT_user_id *uid = node->pkt->pkt.user_id; - ++i; - - tty_printf (" "); - if (uid->is_revoked) - tty_printf ("[revoked] "); - if ( uid->is_expired ) - tty_printf ("[expired] "); - tty_print_utf8_string (uid->name, uid->len); - tty_printf ("\n"); - } - } -} - -static void -show_key_and_fingerprint( KBNODE keyblock ) -{ - KBNODE node; - PKT_public_key *pk = NULL; - - for( node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - pk = node->pkt->pkt.public_key; - tty_printf("pub %4u%c/%08lX %s ", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk) ); - } - else if( node->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - tty_print_utf8_string( uid->name, uid->len ); - break; - } - } - tty_printf("\n"); - if( pk ) - print_fingerprint( pk, NULL, 2 ); -} - - - -/**************** - * Ask for a new user id, do the selfsignature and put it into - * both keyblocks. - * Return true if there is a new user id - */ -static int -menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) -{ - PKT_user_id *uid; - PKT_public_key *pk=NULL; - PKT_secret_key *sk=NULL; - PKT_signature *sig=NULL; - PACKET *pkt; - KBNODE node; - KBNODE pub_where=NULL, sec_where=NULL; - int rc; - - for( node = pub_keyblock; node; pub_where = node, node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) - pk = node->pkt->pkt.public_key; - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - break; - } - if( !node ) /* no subkey */ - pub_where = NULL; - for( node = sec_keyblock; node; sec_where = node, node = node->next ) { - if( node->pkt->pkttype == PKT_SECRET_KEY ) - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) - break; - } - if( !node ) /* no subkey */ - sec_where = NULL; - assert(pk && sk); - - if(photo) { - int hasattrib=0; - - for( node = pub_keyblock; node; node = node->next ) - if( node->pkt->pkttype == PKT_USER_ID && - node->pkt->pkt.user_id->attrib_data!=NULL) - { - hasattrib=1; - break; - } - - /* It is legal but bad for compatibility to add a photo ID to a - v3 key as it means that PGP2 will not be able to use that key - anymore. Also, PGP may not expect a photo on a v3 key. - Don't bother to ask this if the key already has a photo - any - damage has already been done at that point. -dms */ - if(pk->version==3 && !hasattrib) - { - if(opt.expert) - { - tty_printf(_("WARNING: This is a PGP2-style key. " - "Adding a photo ID may cause some versions\n" - " of PGP to reject this key.\n")); - - if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay", - _("Are you sure you still want " - "to add it? (y/N) "))) - return 0; - } - else - { - tty_printf(_("You may not add a photo ID to " - "a PGP2-style key.\n")); - return 0; - } - } - - uid = generate_photo_id(pk); - } else - uid = generate_user_id(); - if( !uid ) - return 0; - - rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, - keygen_add_std_prefs, pk ); - free_secret_key( sk ); - if( rc ) { - log_error("signing failed: %s\n", g10_errstr(rc) ); - free_user_id(uid); - return 0; - } - - /* insert/append to secret keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_USER_ID; - pkt->pkt.user_id = scopy_user_id(uid); - node = new_kbnode(pkt); - if( sec_where ) - insert_kbnode( sec_where, node, 0 ); - else - add_kbnode( sec_keyblock, node ); - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = copy_signature(NULL, sig); - if( sec_where ) - insert_kbnode( node, new_kbnode(pkt), 0 ); - else - add_kbnode( sec_keyblock, new_kbnode(pkt) ); - /* insert/append to public keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_USER_ID; - pkt->pkt.user_id = uid; - node = new_kbnode(pkt); - if( pub_where ) - insert_kbnode( pub_where, node, 0 ); - else - add_kbnode( pub_keyblock, node ); - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = copy_signature(NULL, sig); - if( pub_where ) - insert_kbnode( node, new_kbnode(pkt), 0 ); - else - add_kbnode( pub_keyblock, new_kbnode(pkt) ); - return 1; -} - - -/**************** - * Remove all selceted userids from the keyrings - */ -static void -menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - KBNODE node; - int selected=0; - - for( node = pub_keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - selected = node->flag & NODFLG_SELUID; - if( selected ) { - /* Only cause a trust update if we delete a - non-revoked user id */ - if(!node->pkt->pkt.user_id->is_revoked) - update_trust=1; - delete_kbnode( node ); - if( sec_keyblock ) { - KBNODE snode; - int s_selected = 0; - PKT_user_id *uid = node->pkt->pkt.user_id; - for( snode = sec_keyblock; snode; snode = snode->next ) { - if( snode->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *suid = snode->pkt->pkt.user_id; - - s_selected = - (uid->len == suid->len - && !memcmp( uid->name, suid->name, uid->len)); - if( s_selected ) - delete_kbnode( snode ); - } - else if( s_selected - && snode->pkt->pkttype == PKT_SIGNATURE ) - delete_kbnode( snode ); - else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) - s_selected = 0; - } - } - } - } - else if( selected && node->pkt->pkttype == PKT_SIGNATURE ) - delete_kbnode( node ); - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - selected = 0; - } - commit_kbnode( &pub_keyblock ); - if( sec_keyblock ) - commit_kbnode( &sec_keyblock ); -} - - -static int -menu_delsig( KBNODE pub_keyblock ) -{ - KBNODE node; - PKT_user_id *uid = NULL; - int changed=0; - - for( node = pub_keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL; - } - else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) { - int okay, valid, selfsig, inv_sig, no_key, other_err; - - tty_printf("uid "); - tty_print_utf8_string( uid->name, uid->len ); - tty_printf("\n"); - - okay = inv_sig = no_key = other_err = 0; - valid = print_and_check_one_sig( pub_keyblock, node, - &inv_sig, &no_key, &other_err, - &selfsig, 1 ); - - if( valid ) { - okay = cpr_get_answer_yes_no_quit( - "keyedit.delsig.valid", - _("Delete this good signature? (y/N/q)")); - - /* Only update trust if we delete a good signature. - The other two cases do not affect trust. */ - if(okay) - update_trust=1; - } - else if( inv_sig || other_err ) - okay = cpr_get_answer_yes_no_quit( - "keyedit.delsig.invalid", - _("Delete this invalid signature? (y/N/q)")); - else if( no_key ) - okay = cpr_get_answer_yes_no_quit( - "keyedit.delsig.unknown", - _("Delete this unknown signature? (y/N/q)")); - - if( okay == -1 ) - break; - if( okay && selfsig && !cpr_get_answer_is_yes( - "keyedit.delsig.selfsig", - _("Really delete this self-signature? (y/N)") )) - okay = 0; - if( okay ) { - delete_kbnode( node ); - changed++; - } - - } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - uid = NULL; - } - - if( changed ) { - commit_kbnode( &pub_keyblock ); - tty_printf( changed == 1? _("Deleted %d signature.\n") - : _("Deleted %d signatures.\n"), changed ); - } - else - tty_printf( _("Nothing deleted.\n") ); - - return changed; -} - - -/**************** - * Remove some of the secondary keys - */ -static void -menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - KBNODE node; - int selected=0; - - for( node = pub_keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - selected = node->flag & NODFLG_SELKEY; - if( selected ) { - delete_kbnode( node ); - if( sec_keyblock ) { - KBNODE snode; - int s_selected = 0; - u32 ki[2]; - - keyid_from_pk( node->pkt->pkt.public_key, ki ); - for( snode = sec_keyblock; snode; snode = snode->next ) { - if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) { - u32 ki2[2]; - - keyid_from_sk( snode->pkt->pkt.secret_key, ki2 ); - s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]); - if( s_selected ) - delete_kbnode( snode ); - } - else if( s_selected - && snode->pkt->pkttype == PKT_SIGNATURE ) - delete_kbnode( snode ); - else - s_selected = 0; - } - } - } - } - else if( selected && node->pkt->pkttype == PKT_SIGNATURE ) - delete_kbnode( node ); - else - selected = 0; - } - commit_kbnode( &pub_keyblock ); - if( sec_keyblock ) - commit_kbnode( &sec_keyblock ); - - /* No need to set update_trust here since signing keys no longer - are used to certify other keys, so there is no change in trust - when revoking/removing them */ -} - - -/**************** - * Ask for a new revoker, do the selfsignature and put it into - * both keyblocks. - * Return true if there is a new revoker - */ -static int -menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) -{ - PKT_public_key *pk=NULL,*revoker_pk=NULL; - PKT_secret_key *sk=NULL; - PKT_signature *sig=NULL; - PACKET *pkt; - struct revocation_key revkey; - size_t fprlen; - int rc; - - assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY); - assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY); - - pk=pub_keyblock->pkt->pkt.public_key; - - if(pk->numrevkeys==0 && pk->version==3) - { - /* It is legal but bad for compatibility to add a revoker to a - v3 key as it means that PGP2 will not be able to use that key - anymore. Also, PGP may not expect a revoker on a v3 key. - Don't bother to ask this if the key already has a revoker - - any damage has already been done at that point. -dms */ - if(opt.expert) - { - tty_printf(_("WARNING: This is a PGP 2.x-style key. " - "Adding a designated revoker may cause\n" - " some versions of PGP to reject this key.\n")); - - if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay", - _("Are you sure you still want " - "to add it? (y/N) "))) - return 0; - } - else - { - tty_printf(_("You may not add a designated revoker to " - "a PGP 2.x-style key.\n")); - return 0; - } - } - - sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key); - - for(;;) - { - char *answer; - u32 keyid[2]; - char *p; - size_t n; - - if(revoker_pk) - free_public_key(revoker_pk); - - revoker_pk=m_alloc_clear(sizeof(*revoker_pk)); - - tty_printf("\n"); - - answer=cpr_get_utf8("keyedit.add_revoker", - _("Enter the user ID of the designated revoker: ")); - if(answer[0]=='\0' || answer[0]=='\004') - goto fail; - - rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL); - - if(rc) - { - log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc)); - continue; - } - - fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen); - if(fprlen!=20) - { - log_error(_("cannot appoint a PGP 2.x style key as a " - "designated revoker\n")); - continue; - } - - revkey.class=0x80; - if(sensitive) - revkey.class|=0x40; - revkey.algid=revoker_pk->pubkey_algo; - - if(cmp_public_keys(revoker_pk,pk)==0) - { - /* This actually causes no harm (after all, a key that - designates itself as a revoker is the same as a - regular key), but it's easy enough to check. */ - log_error(_("you cannot appoint a key as its own " - "designated revoker\n")); - - continue; - } - - keyid_from_pk(pk,NULL); - - /* Does this revkey already exist? */ - if(!pk->revkey && pk->numrevkeys) - BUG(); - else - { - int i; - - for(i=0;inumrevkeys;i++) - { - if(memcmp(&pk->revkey[i],&revkey, - sizeof(struct revocation_key))==0) - { - char buf[50]; - - log_error(_("this key has already been designated " - "as a revoker\n")); - - sprintf(buf,"%08lX%08lX", - (ulong)pk->keyid[0],(ulong)pk->keyid[1]); - write_status_text(STATUS_ALREADY_SIGNED,buf); - - break; - } - } - - if(inumrevkeys) - continue; - } - - keyid_from_pk(revoker_pk,keyid); - - tty_printf("\npub %4u%c/%08lX %s ", - nbits_from_pk( revoker_pk ), - pubkey_letter( revoker_pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk(pk) ); - - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\n"); - print_fingerprint(revoker_pk,NULL,2); - tty_printf("\n"); - - tty_printf("WARNING: appointing a key as a designated revoker " - "cannot be undone!\n"); - - tty_printf("\n"); - - if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay", - "Are you sure you want to appoint this " - "key as a designated revoker? (y/N): ")) - continue; - - free_public_key(revoker_pk); - revoker_pk=NULL; - break; - } - - /* The 1F signature must be at least v4 to carry the revocation key - subpacket. */ - rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0, - keygen_add_revkey,&revkey ); - if( rc ) - { - log_error("signing failed: %s\n", g10_errstr(rc) ); - goto fail; - } - - free_secret_key(sk); - sk=NULL; - - /* insert into secret keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = copy_signature(NULL, sig); - insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); - - /* insert into public keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); - - return 1; - - fail: - if(sk) - free_secret_key(sk); - if(sig) - free_seckey_enc(sig); - if(revoker_pk) - free_public_key(revoker_pk); - - return 0; -} - - -static int -menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - int n1, signumber, rc; - u32 expiredate; - int mainkey=0; - PKT_secret_key *sk; /* copy of the main sk */ - PKT_public_key *main_pk, *sub_pk; - PKT_user_id *uid; - KBNODE node; - u32 keyid[2]; - - if( count_selected_keys( sec_keyblock ) ) { - tty_printf(_("Please remove selections from the secret keys.\n")); - return 0; - } - - n1 = count_selected_keys( pub_keyblock ); - if( n1 > 1 ) { - tty_printf(_("Please select at most one secondary key.\n")); - return 0; - } - else if( n1 ) - tty_printf(_("Changing expiration time for a secondary key.\n")); - else { - tty_printf(_("Changing expiration time for the primary key.\n")); - mainkey=1; - } - - expiredate = ask_expiredate(); - node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); - - /* Now we can actually change the self signature(s) */ - main_pk = sub_pk = NULL; - uid = NULL; - signumber = 0; - for( node=pub_keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - main_pk = node->pkt->pkt.public_key; - keyid_from_pk( main_pk, keyid ); - main_pk->expiredate = expiredate; - } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - && (node->flag & NODFLG_SELKEY ) ) { - sub_pk = node->pkt->pkt.public_key; - sub_pk->expiredate = expiredate; - } - else if( node->pkt->pkttype == PKT_USER_ID ) - uid = node->pkt->pkt.user_id; - else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE - && ( mainkey || sub_pk ) ) { - PKT_signature *sig = node->pkt->pkt.signature; - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && ( (mainkey && uid && (sig->sig_class&~3) == 0x10) - || (!mainkey && sig->sig_class == 0x18) ) ) { - /* this is a selfsignature which is to be replaced */ - PKT_signature *newsig; - PACKET *newpkt; - KBNODE sn; - int signumber2 = 0; - - signumber++; - - if( (mainkey && main_pk->version < 4) - || (!mainkey && sub_pk->version < 4 ) ) { - log_info(_( - "You can't change the expiration date of a v3 key\n")); - free_secret_key( sk ); - return 0; - } - - /* find the corresponding secret self-signature */ - for( sn=sec_keyblock; sn; sn = sn->next ) { - if( sn->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *b = sn->pkt->pkt.signature; - if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1] - && sig->sig_class == b->sig_class - && ++signumber2 == signumber ) - break; - } - } - if( !sn ) - log_info(_("No corresponding signature in secret ring\n")); - - /* create new self signature */ - if( mainkey ) - rc = make_keysig_packet( &newsig, main_pk, uid, NULL, - sk, 0x13, 0, 0, 0, 0, - keygen_add_std_prefs, main_pk ); - else - rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk, - sk, 0x18, 0, 0, 0, 0, - keygen_add_key_expire, sub_pk ); - if( rc ) { - log_error("make_keysig_packet failed: %s\n", - g10_errstr(rc)); - free_secret_key( sk ); - return 0; - } - /* replace the packet */ - newpkt = m_alloc_clear( sizeof *newpkt ); - newpkt->pkttype = PKT_SIGNATURE; - newpkt->pkt.signature = newsig; - free_packet( node->pkt ); - m_free( node->pkt ); - node->pkt = newpkt; - if( sn ) { - newpkt = m_alloc_clear( sizeof *newpkt ); - newpkt->pkttype = PKT_SIGNATURE; - newpkt->pkt.signature = copy_signature( NULL, newsig ); - free_packet( sn->pkt ); - m_free( sn->pkt ); - sn->pkt = newpkt; - } - sub_pk = NULL; - } - } - } - - free_secret_key( sk ); - update_trust=1; - return 1; -} - -static int -change_primary_uid_cb ( PKT_signature *sig, void *opaque ) -{ - byte buf[1]; - - /* first clear all primary uid flags so that we are sure none are - * lingering around */ - delete_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID); - delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID); - - /* if opaque is set,we want to set the primary id */ - if (opaque) { - buf[0] = 1; - build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 ); - } - - return 0; -} - - -/* - * Set the primary uid flag for the selected UID. We will also reset - * all other primary uid flags. For this to work with have to update - * all the signature timestamps. If we would do this with the current - * time, we lose quite a lot of information, so we use a a kludge to - * do this: Just increment the timestamp by one second which is - * sufficient to updated a signature during import. - */ -static int -menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - PKT_secret_key *sk; /* copy of the main sk */ - PKT_public_key *main_pk; - PKT_user_id *uid; - KBNODE node; - u32 keyid[2]; - int selected; - int attribute = 0; - int modified = 0; - - if ( count_selected_uids (pub_keyblock) != 1 ) { - tty_printf(_("Please select exactly one user ID.\n")); - return 0; - } - - node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); - - /* Now we can actually change the self signature(s) */ - main_pk = NULL; - uid = NULL; - selected = 0; - - /* Is our selected uid an attribute packet? */ - for ( node=pub_keyblock; node; node = node->next ) - if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID) - attribute = (node->pkt->pkt.user_id->attrib_data!=NULL); - - for ( node=pub_keyblock; node; node = node->next ) { - if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - break; /* ready */ - - if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - main_pk = node->pkt->pkt.public_key; - keyid_from_pk( main_pk, keyid ); - } - else if ( node->pkt->pkttype == PKT_USER_ID ) { - uid = node->pkt->pkt.user_id; - selected = node->flag & NODFLG_SELUID; - } - else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && (uid && (sig->sig_class&~3) == 0x10) - && attribute == (uid->attrib_data!=NULL)) { - if(sig->version < 4) { - char *user=utf8_to_native(uid->name,strlen(uid->name),0); - - log_info(_("skipping v3 self-signature on user id \"%s\"\n"), - user); - m_free(user); - } - else { - /* This is a selfsignature which is to be replaced. - We can just ignore v3 signatures because they are - not able to carry the primary ID flag. We also - ignore self-sigs on user IDs that are not of the - same type that we are making primary. That is, if - we are making a user ID primary, we alter user IDs. - If we are making an attribute packet primary, we - alter attribute packets. */ - - /* FIXME: We must make sure that we only have one - self-signature per user ID here (not counting - revocations) */ - PKT_signature *newsig; - PACKET *newpkt; - const byte *p; - int action; - - /* see whether this signature has the primary UID flag */ - p = parse_sig_subpkt (sig->hashed, - SIGSUBPKT_PRIMARY_UID, NULL ); - if ( !p ) - p = parse_sig_subpkt (sig->unhashed, - SIGSUBPKT_PRIMARY_UID, NULL ); - if ( p && *p ) /* yes */ - action = selected? 0 : -1; - else /* no */ - action = selected? 1 : 0; - - if (action) { - int rc = update_keysig_packet (&newsig, sig, - main_pk, uid, - sk, - change_primary_uid_cb, - action > 0? "x":NULL ); - if( rc ) { - log_error ("update_keysig_packet failed: %s\n", - g10_errstr(rc)); - free_secret_key( sk ); - return 0; - } - /* replace the packet */ - newpkt = m_alloc_clear( sizeof *newpkt ); - newpkt->pkttype = PKT_SIGNATURE; - newpkt->pkt.signature = newsig; - free_packet( node->pkt ); - m_free( node->pkt ); - node->pkt = newpkt; - modified = 1; - } - } - } - } - } - - free_secret_key( sk ); - return modified; -} - - -/* - * Set preferences to new values for the selected user IDs - */ -static int -menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - PKT_secret_key *sk; /* copy of the main sk */ - PKT_public_key *main_pk; - PKT_user_id *uid; - KBNODE node; - u32 keyid[2]; - int selected, select_all; - int modified = 0; - - select_all = !count_selected_uids (pub_keyblock); - - node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); - - /* Now we can actually change the self signature(s) */ - main_pk = NULL; - uid = NULL; - selected = 0; - for ( node=pub_keyblock; node; node = node->next ) { - if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - break; /* ready */ - - if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - main_pk = node->pkt->pkt.public_key; - keyid_from_pk( main_pk, keyid ); - } - else if ( node->pkt->pkttype == PKT_USER_ID ) { - uid = node->pkt->pkt.user_id; - selected = select_all || (node->flag & NODFLG_SELUID); - } - else if ( main_pk && uid && selected - && node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && (uid && (sig->sig_class&~3) == 0x10) ) { - if( sig->version < 4 ) { - char *user=utf8_to_native(uid->name,strlen(uid->name),0); - - log_info(_("skipping v3 self-signature on user id \"%s\"\n"), - user); - m_free(user); - } - else { - /* This is a selfsignature which is to be replaced - * We have to ignore v3 signatures because they are - * not able to carry the preferences */ - PKT_signature *newsig; - PACKET *newpkt; - int rc; - - rc = update_keysig_packet (&newsig, sig, - main_pk, uid, - sk, - keygen_upd_std_prefs, - NULL ); - if( rc ) { - log_error ("update_keysig_packet failed: %s\n", - g10_errstr(rc)); - free_secret_key( sk ); - return 0; - } - /* replace the packet */ - newpkt = m_alloc_clear( sizeof *newpkt ); - newpkt->pkttype = PKT_SIGNATURE; - newpkt->pkt.signature = newsig; - free_packet( node->pkt ); - m_free( node->pkt ); - node->pkt = newpkt; - modified = 1; - } - } - } - } - - free_secret_key( sk ); - return modified; -} - - -/**************** - * Select one user id or remove all selection if index is 0. - * Returns: True if the selection changed; - */ -static int -menu_select_uid( KBNODE keyblock, int idx ) -{ - KBNODE node; - int i; - - /* first check that the index is valid */ - if( idx ) { - for( i=0, node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - if( ++i == idx ) - break; - } - } - if( !node ) { - tty_printf(_("No user ID with index %d\n"), idx ); - return 0; - } - } - else { /* reset all */ - for( i=0, node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) - node->flag &= ~NODFLG_SELUID; - } - return 1; - } - /* and toggle the new index */ - for( i=0, node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - if( ++i == idx ) { - if( (node->flag & NODFLG_SELUID) ) - node->flag &= ~NODFLG_SELUID; - else - node->flag |= NODFLG_SELUID; - } - } - } - - return 1; -} - -/**************** - * Select secondary keys - * Returns: True if the selection changed; - */ -static int -menu_select_key( KBNODE keyblock, int idx ) -{ - KBNODE node; - int i; - - /* first check that the index is valid */ - if( idx ) { - for( i=0, node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - if( ++i == idx ) - break; - } - } - if( !node ) { - tty_printf(_("No secondary key with index %d\n"), idx ); - return 0; - } - } - else { /* reset all */ - for( i=0, node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) - node->flag &= ~NODFLG_SELKEY; - } - return 1; - } - /* and set the new index */ - for( i=0, node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - if( ++i == idx ) { - if( (node->flag & NODFLG_SELKEY) ) - node->flag &= ~NODFLG_SELKEY; - else - node->flag |= NODFLG_SELKEY; - } - } - } - - return 1; -} - - -static int -count_uids_with_flag( KBNODE keyblock, unsigned flag ) -{ - KBNODE node; - int i=0; - - for( node = keyblock; node; node = node->next ) - if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) ) - i++; - return i; -} - -static int -count_keys_with_flag( KBNODE keyblock, unsigned flag ) -{ - KBNODE node; - int i=0; - - for( node = keyblock; node; node = node->next ) - if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY) - && (node->flag & flag) ) - i++; - return i; -} - -static int -count_uids( KBNODE keyblock ) -{ - KBNODE node; - int i=0; - - for( node = keyblock; node; node = node->next ) - if( node->pkt->pkttype == PKT_USER_ID ) - i++; - return i; -} - - -/**************** - * Returns true if there is at least one selected user id - */ -static int -count_selected_uids( KBNODE keyblock ) -{ - return count_uids_with_flag( keyblock, NODFLG_SELUID); -} - -static int -count_selected_keys( KBNODE keyblock ) -{ - return count_keys_with_flag( keyblock, NODFLG_SELKEY); -} - -/* returns how many real (i.e. not attribute) uids are unmarked */ -static int -real_uids_left( KBNODE keyblock ) -{ - KBNODE node; - int real=0; - - for(node=keyblock;node;node=node->next) - if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) && - !node->pkt->pkt.user_id->attrib_data) - real++; - - return real; -} - -/* - * Ask whether the signature should be revoked. If the user commits this, - * flag bit MARK_A is set on the signature and the user ID. - */ -static void -ask_revoke_sig( KBNODE keyblock, KBNODE node ) -{ - int doit=0; - PKT_signature *sig = node->pkt->pkt.signature; - KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID ); - - if( !unode ) { - log_error("Oops: no user ID for signature\n"); - return; - } - - tty_printf(_("user ID: \"")); - tty_print_utf8_string( unode->pkt->pkt.user_id->name, - unode->pkt->pkt.user_id->len ); - - if(sig->flags.exportable) - tty_printf(_("\"\nsigned with your key %08lX at %s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig) ); - else - tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig) ); - - if(sig->flags.expired) - { - tty_printf(_("This signature expired on %s.\n"), - expirestr_from_sig(sig)); - /* Use a different question so we can have different help text */ - doit=cpr_get_answer_is_yes("ask_revoke_sig.expired", - _("Are you sure you still want to revoke it? (y/N) ")); - } - else - doit=cpr_get_answer_is_yes("ask_revoke_sig.one", - _("Create a revocation certificate for this signature? (y/N) ")); - - if(doit) { - node->flag |= NODFLG_MARK_A; - unode->flag |= NODFLG_MARK_A; - } -} - -/**************** - * Display all user ids of the current public key together with signatures - * done by one of our keys. Then walk over all this sigs and ask the user - * whether he wants to revoke this signature. - * Return: True when the keyblock has changed. - */ -static int -menu_revsig( KBNODE keyblock ) -{ - PKT_signature *sig; - PKT_public_key *primary_pk; - KBNODE node; - int changed = 0; - int rc, any, skip=1, all=!count_selected_uids(keyblock); - struct revocation_reason_info *reason = NULL; - - /* FIXME: detect duplicates here */ - tty_printf(_("You have signed these user IDs:\n")); - for( node = keyblock; node; node = node->next ) { - node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A); - if( node->pkt->pkttype == PKT_USER_ID ) { - if( node->flag&NODFLG_SELUID || all ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - /* Hmmm: Should we show only UIDs with a signature? */ - tty_printf(" "); - tty_print_utf8_string( uid->name, uid->len ); - tty_printf("\n"); - skip=0; - } - else - skip=1; - } - else if( !skip && node->pkt->pkttype == PKT_SIGNATURE - && ((sig = node->pkt->pkt.signature), - !seckey_available(sig->keyid) ) ) { - if( (sig->sig_class&~3) == 0x10 ) { - tty_printf(_(" signed by %08lX at %s%s%s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig), - sig->flags.exportable?"":" (non-exportable)", - sig->flags.revocable?"":" (non-revocable)"); - if(sig->flags.revocable) - node->flag |= NODFLG_SELSIG; - } - else if( sig->sig_class == 0x30 ) { - tty_printf(_(" revoked by %08lX at %s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig) ); - } - } - } - - /* ask */ - for( node = keyblock; node; node = node->next ) { - if( !(node->flag & NODFLG_SELSIG) ) - continue; - ask_revoke_sig( keyblock, node ); - } - - /* present selected */ - any = 0; - for( node = keyblock; node; node = node->next ) { - if( !(node->flag & NODFLG_MARK_A) ) - continue; - if( !any ) { - any = 1; - tty_printf(_("You are about to revoke these signatures:\n")); - } - if( node->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - tty_printf(" "); - tty_print_utf8_string( uid->name, uid->len ); - tty_printf("\n"); - } - else if( node->pkt->pkttype == PKT_SIGNATURE ) { - sig = node->pkt->pkt.signature; - tty_printf(_(" signed by %08lX at %s%s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig), - sig->flags.exportable?"":_(" (non-exportable)") ); - } - } - if( !any ) - return 0; /* none selected */ - - if( !cpr_get_answer_is_yes("ask_revoke_sig.okay", - _("Really create the revocation certificates? (y/N) ")) ) - return 0; /* forget it */ - - reason = ask_revocation_reason( 0, 1, 0 ); - if( !reason ) { /* user decided to cancel */ - return 0; - } - - /* now we can sign the user ids */ - reloop: /* (must use this, because we are modifing the list) */ - primary_pk = keyblock->pkt->pkt.public_key; - for( node=keyblock; node; node = node->next ) { - KBNODE unode; - PACKET *pkt; - struct sign_attrib attrib; - PKT_secret_key *sk; - - if( !(node->flag & NODFLG_MARK_A) - || node->pkt->pkttype != PKT_SIGNATURE ) - continue; - unode = find_prev_kbnode( keyblock, node, PKT_USER_ID ); - assert( unode ); /* we already checked this */ - - memset( &attrib, 0, sizeof attrib ); - attrib.reason = reason; - attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable; - - node->flag &= ~NODFLG_MARK_A; - sk = m_alloc_secure_clear( sizeof *sk ); - if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) { - log_info(_("no secret key\n")); - continue; - } - rc = make_keysig_packet( &sig, primary_pk, - unode->pkt->pkt.user_id, - NULL, - sk, - 0x30, 0, 0, 0, 0, - sign_mk_attrib, - &attrib ); - free_secret_key(sk); - if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); - release_revocation_reason_info( reason ); - return changed; - } - changed = 1; /* we changed the keyblock */ - update_trust = 1; - /* Are we revoking our own uid? */ - if(primary_pk->keyid[0]==sig->keyid[0] && - primary_pk->keyid[1]==sig->keyid[1]) - unode->pkt->pkt.user_id->is_revoked=1; - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - insert_kbnode( unode, new_kbnode(pkt), 0 ); - goto reloop; - } - - release_revocation_reason_info( reason ); - return changed; -} - -/**************** - * Revoke some of the secondary keys. - * Hmmm: Should we add a revocation to the secret keyring too? - * Does its all make sense to duplicate most of the information? - */ -static int -menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - PKT_public_key *mainpk; - KBNODE node; - int changed = 0; - int rc; - struct revocation_reason_info *reason = NULL; - - reason = ask_revocation_reason( 1, 0, 0 ); - if( !reason ) { /* user decided to cancel */ - return 0; - } - - - reloop: /* (better this way because we are modifing the keyring) */ - mainpk = pub_keyblock->pkt->pkt.public_key; - for( node = pub_keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY - && (node->flag & NODFLG_SELKEY) ) { - PACKET *pkt; - PKT_signature *sig; - PKT_secret_key *sk; - PKT_public_key *subpk = node->pkt->pkt.public_key; - struct sign_attrib attrib; - - memset( &attrib, 0, sizeof attrib ); - attrib.reason = reason; - - node->flag &= ~NODFLG_SELKEY; - sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key ); - rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk, - 0x28, 0, 0, 0, 0, - sign_mk_attrib, &attrib ); - free_secret_key(sk); - if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); - release_revocation_reason_info( reason ); - return changed; - } - changed = 1; /* we changed the keyblock */ - - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - insert_kbnode( node, new_kbnode(pkt), 0 ); - goto reloop; - } - } - commit_kbnode( &pub_keyblock ); - /*commit_kbnode( &sec_keyblock );*/ - - /* No need to set update_trust here since signing keys no longer - are used to certify other keys, so there is no change in trust - when revoking/removing them */ - - release_revocation_reason_info( reason ); - return changed; -} - - -static int -enable_disable_key( KBNODE keyblock, int disable ) -{ - PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY ) - ->pkt->pkt.public_key; - unsigned int trust, newtrust; - - trust = newtrust = get_ownertrust (pk); - newtrust &= ~TRUST_FLAG_DISABLED; - if( disable ) - newtrust |= TRUST_FLAG_DISABLED; - if( trust == newtrust ) - return 0; /* already in that state */ - update_ownertrust(pk, newtrust ); - return 0; -} - - -static void -menu_showphoto( KBNODE keyblock ) -{ - KBNODE node; - int select_all = !count_selected_uids(keyblock); - int count=0; - PKT_public_key *pk=NULL; - u32 keyid[2]; - - /* Look for the public key first. We have to be really, really, - explicit as to which photo this is, and what key it is a UID on - since people may want to sign it. */ - - for( node = keyblock; node; node = node->next ) - { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) - { - pk = node->pkt->pkt.public_key; - keyid_from_pk(pk, keyid); - } - else if( node->pkt->pkttype == PKT_USER_ID ) - { - PKT_user_id *uid = node->pkt->pkt.user_id; - count++; - - if((select_all || (node->flag & NODFLG_SELUID)) && - uid->attribs!=NULL) - { - int i; - - for(i=0;inumattribs;i++) - { - byte type; - u32 size; - - if(uid->attribs[i].type==ATTRIB_IMAGE && - parse_image_header(&uid->attribs[i],&type,&size)) - { - tty_printf(_("Displaying %s photo ID of size %ld for " - "key 0x%08lX (uid %d)\n"), - image_type_to_string(type,1), - (ulong)size,(ulong)keyid[1],count); - show_photos(&uid->attribs[i],1,pk,NULL); - } - } - } - } - } -} diff --git a/g10/keygen.c b/g10/keygen.c deleted file mode 100644 index 7582805fa..000000000 --- a/g10/keygen.c +++ /dev/null @@ -1,2429 +0,0 @@ -/* keygen.c - generate a key pair - * 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 -#include -#include -#include -#include -#include -#include -#include "util.h" -#include "main.h" -#include "packet.h" -#include "cipher.h" -#include "ttyio.h" -#include "options.h" -#include "keydb.h" -#include "trustdb.h" -#include "status.h" -#include "i18n.h" - -#define MAX_PREFS 30 - - -enum para_name { - pKEYTYPE, - pKEYLENGTH, - pKEYUSAGE, - pSUBKEYTYPE, - pSUBKEYLENGTH, - pSUBKEYUSAGE, - pNAMEREAL, - pNAMEEMAIL, - pNAMECOMMENT, - pPREFERENCES, - pREVOKER, - pUSERID, - pEXPIREDATE, - pKEYEXPIRE, /* in n seconds */ - pSUBKEYEXPIRE, /* in n seconds */ - pPASSPHRASE, - pPASSPHRASE_DEK, - pPASSPHRASE_S2K -}; - -struct para_data_s { - struct para_data_s *next; - int lnr; - enum para_name key; - union { - DEK *dek; - STRING2KEY *s2k; - u32 expire; - unsigned int usage; - struct revocation_key revkey; - char value[1]; - } u; -}; - -struct output_control_s { - int lnr; - int dryrun; - int use_files; - struct { - char *fname; - char *newfname; - IOBUF stream; - armor_filter_context_t afx; - } pub; - struct { - char *fname; - char *newfname; - IOBUF stream; - armor_filter_context_t afx; - } sec; -}; - - -struct opaque_data_usage_and_pk { - unsigned int usage; - PKT_public_key *pk; -}; - - -static int prefs_initialized = 0; -static byte sym_prefs[MAX_PREFS]; -static int nsym_prefs; -static byte hash_prefs[MAX_PREFS]; -static int nhash_prefs; -static byte zip_prefs[MAX_PREFS]; -static int nzip_prefs; -static int mdc_available; - -static void do_generate_keypair( struct para_data_s *para, - struct output_control_s *outctrl ); -static int write_keyblock( IOBUF out, KBNODE node ); - - -static void -write_uid( KBNODE root, const char *s ) -{ - PACKET *pkt = m_alloc_clear(sizeof *pkt ); - size_t n = strlen(s); - - pkt->pkttype = PKT_USER_ID; - pkt->pkt.user_id = m_alloc_clear( sizeof *pkt->pkt.user_id + n - 1 ); - pkt->pkt.user_id->len = n; - pkt->pkt.user_id->ref = 1; - strcpy(pkt->pkt.user_id->name, s); - add_kbnode( root, new_kbnode( pkt ) ); -} - -static void -do_add_key_flags (PKT_signature *sig, unsigned int use) -{ - byte buf[1]; - - if (!use) - return; - - buf[0] = 0; - if (use & PUBKEY_USAGE_SIG) - buf[0] |= 0x01 | 0x02; - if (use & PUBKEY_USAGE_ENC) - buf[0] |= 0x04 | 0x08; - build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1); -} - - -int -keygen_add_key_expire( PKT_signature *sig, void *opaque ) -{ - PKT_public_key *pk = opaque; - byte buf[8]; - u32 u; - - if( pk->expiredate ) { - u = pk->expiredate > pk->timestamp? pk->expiredate - pk->timestamp - : pk->timestamp; - buf[0] = (u >> 24) & 0xff; - buf[1] = (u >> 16) & 0xff; - buf[2] = (u >> 8) & 0xff; - buf[3] = u & 0xff; - build_sig_subpkt( sig, SIGSUBPKT_KEY_EXPIRE, buf, 4 ); - } - - return 0; -} - -static int -keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque) -{ - struct opaque_data_usage_and_pk *oduap = opaque; - - do_add_key_flags (sig, oduap->usage); - return keygen_add_key_expire (sig, oduap->pk); -} - -static int -set_one_pref (ulong val, int type, int (*cf)(int), byte *buf, int *nbuf) -{ - int i; - - if (cf (val)) { - log_info (_("preference %c%lu is not valid\n"), type, val); - if(type=='S' && val==CIPHER_ALGO_IDEA) - idea_cipher_warn(1); - return -1; - } - for (i=0; i < *nbuf; i++ ) { - if (buf[i] == val) { - log_info (_("preference %c%lu duplicated\n"), type, val); - return -1; - } - } - if (*nbuf >= MAX_PREFS) { - log_info (_("too many `%c' preferences\n"), type); - return -1; - } - buf[(*nbuf)++] = val; - return 0; -} - - -/* - * Parse the supplied string and use it to set the standard preferences. - * The String is expected to be in a forma like the one printed by "prefs", - * something like: "S10 S3 H3 H2 Z2 Z1". Use NULL to set the default - * preferences. - * Returns: 0 = okay - */ -int -keygen_set_std_prefs (const char *string,int personal) -{ - byte sym[MAX_PREFS], hash[MAX_PREFS], zip[MAX_PREFS]; - int nsym=0, nhash=0, nzip=0, mdc=1; /* mdc defaults on */ - ulong val; - const char *s, *s2; - int rc = 0; - - if (!string || !ascii_strcasecmp (string, "default")) { - if (opt.def_preference_list) - string=opt.def_preference_list; - else if ( !check_cipher_algo(CIPHER_ALGO_IDEA) ) - string = "S7 S3 S2 S1 H2 H3 Z2 Z1"; - else - string = "S7 S3 S2 H2 H3 Z2 Z1"; - - /* If we have it, IDEA goes *after* 3DES so it won't be used - unless we're encrypting along with a V3 key. Ideally, we - would only put the S1 preference in if the key was RSA and - <=2048 bits, as that is what won't break PGP2, but that is - difficult with the current code, and not really worth - checking as a non-RSA <=2048 bit key wouldn't be usable by - PGP2 anyway -dms */ - } - else if (!ascii_strcasecmp (string, "none")) - string = ""; - - for (s=string; *s; s = s2) { - if ((*s=='s' || *s == 'S') && isdigit(s[1]) ) { - val = strtoul (++s, (char**)&s2, 10); - if (set_one_pref (val, 'S', check_cipher_algo, sym, &nsym)) - rc = -1; - } - else if ((*s=='h' || *s == 'H') && isdigit(s[1]) ) { - val = strtoul (++s, (char**)&s2, 10); - if (set_one_pref (val, 'H', check_digest_algo, hash, &nhash)) - rc = -1; - } - else if ((*s=='z' || *s == 'Z') && isdigit(s[1]) ) { - val = strtoul (++s, (char**)&s2, 10); - if (set_one_pref (val, 'Z', check_compress_algo, zip, &nzip)) - rc = -1; - } - else if (ascii_strcasecmp(s,"mdc")==0) { - mdc=1; - s2=s+3; - } - else if (ascii_strcasecmp(s,"no-mdc")==0) { - mdc=0; - s2=s+6; - } - else if (isspace (*s)) - s2 = s+1; - else { - log_info (_("invalid character in preference string\n")); - return -1; - } - } - - if (!rc) - { - if(personal) - { - if(personal==PREFTYPE_SYM) - { - m_free(opt.personal_cipher_prefs); - - if(nsym==0) - opt.personal_cipher_prefs=NULL; - else - { - int i; - - opt.personal_cipher_prefs= - m_alloc(sizeof(prefitem_t *)*(nsym+1)); - - for (i=0; ihashed, SIGSUBPKT_FEATURES, &n ); - /* Already set or cleared */ - if (s && n && - ((enabled && (s[0] & 0x01)) || (!enabled && !(s[0] & 0x01)))) - return; - - if (!s || !n) { /* create a new one */ - n = 1; - buf = m_alloc_clear (n); - } - else { - buf = m_alloc (n); - memcpy (buf, s, n); - } - - if(enabled) - buf[0] |= 0x01; /* MDC feature */ - else - buf[0] &= ~0x01; - - /* Are there any bits set? */ - for(i=0;ihashed, SIGSUBPKT_FEATURES); - else - build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n); - - m_free (buf); -} - -int -keygen_upd_std_prefs( PKT_signature *sig, void *opaque ) -{ - if (!prefs_initialized) - keygen_set_std_prefs (NULL, 0); - - if (nsym_prefs) - build_sig_subpkt (sig, SIGSUBPKT_PREF_SYM, sym_prefs, nsym_prefs); - else - { - delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM); - delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_SYM); - } - - if (nhash_prefs) - build_sig_subpkt (sig, SIGSUBPKT_PREF_HASH, hash_prefs, nhash_prefs); - else - { - delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_HASH); - delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_HASH); - } - - if (nzip_prefs) - build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs); - else - { - delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR); - delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_COMPR); - } - - /* Make sure that the MDC feature flag is set if needed */ - add_feature_mdc (sig,mdc_available); - - return 0; -} - - -/**************** - * Add preference to the self signature packet. - * This is only called for packets with version > 3. - - */ -int -keygen_add_std_prefs( PKT_signature *sig, void *opaque ) -{ - PKT_public_key *pk = opaque; - byte buf[8]; - - do_add_key_flags (sig, pk->pubkey_usage); - keygen_add_key_expire( sig, opaque ); - keygen_upd_std_prefs (sig, opaque); - - buf[0] = 0x80; /* no modify - It is reasonable that a key holder - * has the possibility to reject signatures from users - * who are known to sign everything without any - * validation - so a signed key should be send - * to the holder who in turn can put it on a keyserver - */ - build_sig_subpkt( sig, SIGSUBPKT_KS_FLAGS, buf, 1 ); - - return 0; -} - -int -keygen_add_revkey(PKT_signature *sig, void *opaque) -{ - struct revocation_key *revkey=opaque; - byte buf[2+MAX_FINGERPRINT_LEN]; - - buf[0]=revkey->class; - buf[1]=revkey->algid; - memcpy(&buf[2],revkey->fpr,MAX_FINGERPRINT_LEN); - - build_sig_subpkt(sig,SIGSUBPKT_REV_KEY,buf,2+MAX_FINGERPRINT_LEN); - - /* All sigs with revocation keys set are nonrevocable */ - sig->flags.revocable=0; - buf[0] = 0; - build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 ); - - parse_revkeys(sig); - - return 0; -} - -static int -write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, - struct revocation_key *revkey ) -{ - PACKET *pkt; - PKT_signature *sig; - int rc=0; - KBNODE node; - PKT_public_key *pk; - - if( opt.verbose ) - log_info(_("writing direct signature\n")); - - /* get the pk packet from the pub_tree */ - node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); - if( !node ) - BUG(); - pk = node->pkt->pkt.public_key; - - /* we have to cache the key, so that the verification of the signature - * creation is able to retrieve the public key */ - cache_public_key (pk); - - /* and make the signature */ - rc = make_keysig_packet(&sig,pk,NULL,NULL,sk,0x1F,0,0,0,0, - keygen_add_revkey,revkey); - if( rc ) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); - return rc; - } - - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - add_kbnode( root, new_kbnode( pkt ) ); - return rc; -} - -static int -write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, - unsigned int use ) -{ - PACKET *pkt; - PKT_signature *sig; - PKT_user_id *uid; - int rc=0; - KBNODE node; - PKT_public_key *pk; - - if( opt.verbose ) - log_info(_("writing self signature\n")); - - /* get the uid packet from the list */ - node = find_kbnode( root, PKT_USER_ID ); - if( !node ) - BUG(); /* no user id packet in tree */ - uid = node->pkt->pkt.user_id; - /* get the pk packet from the pub_tree */ - node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); - if( !node ) - BUG(); - pk = node->pkt->pkt.public_key; - pk->pubkey_usage = use; - /* we have to cache the key, so that the verification of the signature - * creation is able to retrieve the public key */ - cache_public_key (pk); - - /* and make the signature */ - rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, - keygen_add_std_prefs, pk ); - if( rc ) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); - return rc; - } - - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - add_kbnode( root, new_kbnode( pkt ) ); - return rc; -} - -static int -write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, - unsigned int use ) -{ - PACKET *pkt; - PKT_signature *sig; - int rc=0; - KBNODE node; - PKT_public_key *pk, *subpk; - struct opaque_data_usage_and_pk oduap; - - if( opt.verbose ) - log_info(_("writing key binding signature\n")); - - /* get the pk packet from the pub_tree */ - node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); - if( !node ) - BUG(); - pk = node->pkt->pkt.public_key; - /* we have to cache the key, so that the verification of the signature - * creation is able to retrieve the public key */ - cache_public_key (pk); - - /* find the last subkey */ - subpk = NULL; - for(node=pub_root; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - subpk = node->pkt->pkt.public_key; - } - if( !subpk ) - BUG(); - - /* and make the signature */ - oduap.usage = use; - oduap.pk = subpk; - rc = make_keysig_packet( &sig, pk, NULL, subpk, sk, 0x18, 0, 0, 0, 0, - keygen_add_key_flags_and_expire, &oduap ); - if( rc ) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); - return rc; - } - - pkt = m_alloc_clear( sizeof *pkt ); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - add_kbnode( root, new_kbnode( pkt ) ); - return rc; -} - - -static int -gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) -{ - int rc; - int i; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - MPI skey[4]; - MPI *factors; - - assert( is_ELGAMAL(algo) ); - - if( nbits < 512 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); - } - - if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - log_info(_("keysize rounded up to %u bits\n"), nbits ); - } - - rc = pubkey_generate( algo, nbits, skey, &factors ); - if( rc ) { - log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); - return rc; - } - - sk = m_alloc_clear( sizeof *sk ); - pk = m_alloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = algo; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - pk->pkey[2] = mpi_copy( skey[2] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi( sk->skey[3] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - if( dek ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - if( rc ) { - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - } - - pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - /* don't know whether it makes sense to have the factors, so for now - * we store them in the secret keyring (but they are not secret) */ - pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - for(i=0; factors[i]; i++ ) - add_kbnode( sec_root, - make_mpi_comment_node("#:ELG_factor:", factors[i] )); - - return 0; -} - - -/**************** - * Generate a DSA key - */ -static int -gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) -{ - int rc; - int i; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - MPI skey[5]; - MPI *factors; - - if( nbits > 1024 || nbits < 512 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); - } - - if( (nbits % 64) ) { - nbits = ((nbits + 63) / 64) * 64; - log_info(_("keysize rounded up to %u bits\n"), nbits ); - } - - rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors ); - if( rc ) { - log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); - return rc; - } - - sk = m_alloc_clear( sizeof *sk ); - pk = m_alloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - pk->pkey[2] = mpi_copy( skey[2] ); - pk->pkey[3] = mpi_copy( skey[3] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->skey[4] = skey[4]; - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi ( sk->skey[4] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - if( dek ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - if( rc ) { - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - } - - pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - /* don't know whether it makes sense to have the factors, so for now - * we store them in the secret keyring (but they are not secret) - * p = 2 * q * f1 * f2 * ... * fn - * We store only f1 to f_n-1; fn can be calculated because p and q - * are known. - */ - pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - for(i=1; factors[i]; i++ ) /* the first one is q */ - add_kbnode( sec_root, - make_mpi_comment_node("#:DSA_factor:", factors[i] )); - - return 0; -} - - -/* - * Generate an RSA key. - */ -static int -gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) -{ - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - MPI skey[6]; - MPI *factors; - - assert( is_RSA(algo) ); - - if( nbits < 1024 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); - } - - if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - log_info(_("keysize rounded up to %u bits\n"), nbits ); - } - - rc = pubkey_generate( algo, nbits, skey, &factors ); - if( rc ) { - log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); - return rc; - } - - sk = m_alloc_clear( sizeof *sk ); - pk = m_alloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = algo; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->skey[4] = skey[4]; - sk->skey[5] = skey[5]; - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi (sk->skey[2] ); - sk->csum += checksum_mpi (sk->skey[3] ); - sk->csum += checksum_mpi (sk->skey[4] ); - sk->csum += checksum_mpi (sk->skey[5] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - if( dek ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - if( rc ) { - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } - } - - pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - pkt = m_alloc_clear(sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - - return 0; -} - - -/**************** - * check valid days: - * return 0 on error or the multiplier - */ -static int -check_valid_days( const char *s ) -{ - if( !isdigit(*s) ) - return 0; - for( s++; *s; s++) - if( !isdigit(*s) ) - break; - if( !*s ) - return 1; - if( s[1] ) - return 0; /* e.g. "2323wc" */ - if( *s == 'd' || *s == 'D' ) - return 1; - if( *s == 'w' || *s == 'W' ) - return 7; - if( *s == 'm' || *s == 'M' ) - return 30; - if( *s == 'y' || *s == 'Y' ) - return 365; - return 0; -} - - -/**************** - * Returns: 0 to create both a DSA and a ElGamal key. - * and only if key flags are to be written the desired usage. - */ -static int -ask_algo (int addmode, unsigned int *r_usage) -{ - char *answer; - int algo; - - *r_usage = 0; - tty_printf(_("Please select what kind of key you want:\n")); - if( !addmode ) - tty_printf(_(" (%d) DSA and ElGamal (default)\n"), 1 ); - tty_printf( _(" (%d) DSA (sign only)\n"), 2 ); - if( addmode ) - tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 ); - if (opt.expert) - tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 4 ); - tty_printf( _(" (%d) RSA (sign only)\n"), 5 ); - if (addmode) - tty_printf( _(" (%d) RSA (encrypt only)\n"), 6 ); - if (opt.expert) - tty_printf( _(" (%d) RSA (sign and encrypt)\n"), 7 ); - - for(;;) { - answer = cpr_get("keygen.algo",_("Your selection? ")); - cpr_kill_prompt(); - algo = *answer? atoi(answer): 1; - m_free(answer); - if( algo == 1 && !addmode ) { - algo = 0; /* create both keys */ - break; - } - else if( algo == 7 && opt.expert ) { - if (cpr_get_answer_is_yes ("keygen.algo.rsa_se",_( - "The use of this algorithm is deprecated - create anyway? "))){ - algo = PUBKEY_ALGO_RSA; - *r_usage = PUBKEY_USAGE_ENC | PUBKEY_USAGE_SIG; - break; - } - } - else if( algo == 6 && addmode ) { - algo = PUBKEY_ALGO_RSA; - *r_usage = PUBKEY_USAGE_ENC; - break; - } - else if( algo == 5 ) { - algo = PUBKEY_ALGO_RSA; - *r_usage = PUBKEY_USAGE_SIG; - break; - } - else if( algo == 4 && opt.expert) { - if( cpr_get_answer_is_yes("keygen.algo.elg_se",_( - "The use of this algorithm is deprecated - create anyway? "))){ - algo = PUBKEY_ALGO_ELGAMAL; - break; - } - } - else if( algo == 3 && addmode ) { - algo = PUBKEY_ALGO_ELGAMAL_E; - break; - } - else if( algo == 2 ) { - algo = PUBKEY_ALGO_DSA; - break; - } - else - tty_printf(_("Invalid selection.\n")); - } - return algo; -} - - -static unsigned -ask_keysize( int algo ) -{ - char *answer; - unsigned nbits; - - if (algo != PUBKEY_ALGO_DSA && algo != PUBKEY_ALGO_RSA) { - tty_printf (_("About to generate a new %s keypair.\n" - " minimum keysize is 768 bits\n" - " default keysize is 1024 bits\n" - " highest suggested keysize is 2048 bits\n"), - pubkey_algo_to_string(algo) ); - } - - for(;;) { - answer = cpr_get("keygen.size", - _("What keysize do you want? (1024) ")); - cpr_kill_prompt(); - nbits = *answer? atoi(answer): 1024; - m_free(answer); - if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) ) - tty_printf(_("DSA only allows keysizes from 512 to 1024\n")); - else if( algo == PUBKEY_ALGO_RSA && nbits < 1024 ) - tty_printf(_("keysize too small;" - " 1024 is smallest value allowed for RSA.\n")); - else if( nbits < 768 ) - tty_printf(_("keysize too small;" - " 768 is smallest value allowed.\n")); - else if( nbits > 4096 ) { - /* It is ridiculous and an annoyance to use larger key sizes! - * GnuPG can handle much larger sizes; but it takes an eternity - * to create such a key (but less than the time the Sirius - * Computer Corporation needs to process one of the usual - * complaints) and {de,en}cryption although needs some time. - * So, before you complain about this limitation, I suggest that - * you start a discussion with Marvin about this theme and then - * do whatever you want. */ - tty_printf(_("keysize too large; %d is largest value allowed.\n"), - 4096); - } - else if( nbits > 2048 && !cpr_enabled() ) { - tty_printf( - _("Keysizes larger than 2048 are not suggested because\n" - "computations take REALLY long!\n")); - if( cpr_get_answer_is_yes("keygen.size.huge.okay",_( - "Are you sure that you want this keysize? ")) ) { - tty_printf(_("Okay, but keep in mind that your monitor " - "and keyboard radiation is also very vulnerable " - "to attacks!\n")); - break; - } - } - else - break; - } - tty_printf(_("Requested keysize is %u bits\n"), nbits ); - if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) { - nbits = ((nbits + 63) / 64) * 64; - tty_printf(_("rounded up to %u bits\n"), nbits ); - } - else if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - tty_printf(_("rounded up to %u bits\n"), nbits ); - } - return nbits; -} - - -/**************** - * Parse an expire string and return it's value in days. - * Returns -1 on error. - */ -static int -parse_expire_string( const char *string ) -{ - int mult; - u32 abs_date=0; - u32 curtime = make_timestamp(); - int valid_days; - - if( !*string ) - valid_days = 0; - else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime ) { - /* This calculation is not perfectly okay because we - * are later going to simply multiply by 86400 and don't - * correct for leapseconds. A solution would be to change - * the whole implemenation to work with dates and not intervals - * which are required for v3 keys. - */ - valid_days = abs_date/86400-curtime/86400+1; - } - else if( (mult=check_valid_days(string)) ) { - valid_days = atoi(string) * mult; - if( valid_days < 0 || valid_days > 39447 ) - valid_days = 0; - } - else { - valid_days = -1; - } - return valid_days; -} - -/* object == 0 for a key, and 1 for a sig */ -u32 -ask_expire_interval(int object) -{ - char *answer; - int valid_days=0; - u32 interval = 0; - - switch(object) - { - case 0: - tty_printf(_("Please specify how long the key should be valid.\n" - " 0 = key does not expire\n" - " = key expires in n days\n" - " w = key expires in n weeks\n" - " m = key expires in n months\n" - " y = key expires in n years\n")); - break; - - case 1: - tty_printf(_("Please specify how long the signature should be valid.\n" - " 0 = signature does not expire\n" - " = signature expires in n days\n" - " w = signature expires in n weeks\n" - " m = signature expires in n months\n" - " y = signature expires in n years\n")); - break; - - default: - BUG(); - } - - /* Note: The elgamal subkey for DSA has no expiration date because - * it must be signed with the DSA key and this one has the expiration - * date */ - - answer = NULL; - for(;;) { - u32 curtime=make_timestamp(); - - m_free(answer); - if(object==0) - answer = cpr_get("keygen.valid",_("Key is valid for? (0) ")); - else - answer = cpr_get("siggen.valid",_("Signature is valid for? (0) ")); - cpr_kill_prompt(); - trim_spaces(answer); - valid_days = parse_expire_string( answer ); - if( valid_days < 0 ) { - tty_printf(_("invalid value\n")); - continue; - } - - if( !valid_days ) { - tty_printf(_("%s does not expire at all\n"), - object==0?"Key":"Signature"); - interval = 0; - } - else { - interval = valid_days * 86400L; - /* print the date when the key expires */ - tty_printf(_("%s expires at %s\n"), - object==0?"Key":"Signature", - asctimestamp((ulong)(curtime + interval) ) ); - /* FIXME: This check yields warning on alhas: - write a configure check and to this check here only for 32 bit machines */ - if( (time_t)((ulong)(curtime+interval)) < 0 ) - tty_printf(_("Your system can't display dates beyond 2038.\n" - "However, it will be correctly handled up to 2106.\n")); - } - - if( cpr_enabled() || cpr_get_answer_is_yes("keygen.valid.okay", - _("Is this correct (y/n)? ")) ) - break; - } - m_free(answer); - return interval; -} - -u32 -ask_expiredate() -{ - u32 x = ask_expire_interval(0); - return x? make_timestamp() + x : 0; -} - -static int -has_invalid_email_chars( const char *s ) -{ - int at_seen=0; - static char valid_chars[] = "01234567890_-." - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - for( ; *s; s++ ) { - if( *s & 0x80 ) - return 1; - if( *s == '@' ) - at_seen=1; - else if( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) ) - return 1; - else if( at_seen && !strchr( valid_chars, *s ) ) - return 1; - } - return 0; -} - - -static char * -ask_user_id( int mode ) -{ - char *answer; - char *aname, *acomment, *amail, *uid; - - if( !mode ) - tty_printf( _("\n" -"You need a User-ID to identify your key; the software constructs the user id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n\n") ); - uid = aname = acomment = amail = NULL; - for(;;) { - char *p; - int fail=0; - - if( !aname ) { - for(;;) { - m_free(aname); - aname = cpr_get("keygen.name",_("Real name: ")); - trim_spaces(aname); - cpr_kill_prompt(); - - if( opt.allow_freeform_uid ) - break; - - if( strpbrk( aname, "<>" ) ) - tty_printf(_("Invalid character in name\n")); - else if( isdigit(*aname) ) - tty_printf(_("Name may not start with a digit\n")); - else if( strlen(aname) < 5 ) - tty_printf(_("Name must be at least 5 characters long\n")); - else - break; - } - } - if( !amail ) { - for(;;) { - m_free(amail); - amail = cpr_get("keygen.email",_("Email address: ")); - trim_spaces(amail); - cpr_kill_prompt(); - if( !*amail ) - break; /* no email address is okay */ - else if( has_invalid_email_chars(amail) - || string_count_chr(amail,'@') != 1 - || *amail == '@' - || amail[strlen(amail)-1] == '@' - || amail[strlen(amail)-1] == '.' - || strstr(amail, "..") ) - tty_printf(_("Not a valid email address\n")); - else - break; - } - } - if( !acomment ) { - for(;;) { - m_free(acomment); - acomment = cpr_get("keygen.comment",_("Comment: ")); - trim_spaces(acomment); - cpr_kill_prompt(); - if( !*acomment ) - break; /* no comment is okay */ - else if( strpbrk( acomment, "()" ) ) - tty_printf(_("Invalid character in comment\n")); - else - break; - } - } - - - m_free(uid); - uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10); - p = stpcpy(p, aname ); - if( *acomment ) - p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")"); - if( *amail ) - p = stpcpy(stpcpy(stpcpy(p," <"), amail),">"); - - /* append a warning if we do not have dev/random - * or it is switched into quick testmode */ - if( quick_random_gen(-1) ) - strcpy(p, " (INSECURE!)" ); - - /* print a note in case that UTF8 mapping has to be done */ - for(p=uid; *p; p++ ) { - if( *p & 0x80 ) { - tty_printf(_("You are using the `%s' character set.\n"), - get_native_charset() ); - break; - } - } - - tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid); - /* fixme: add a warning if this user-id already exists */ - if( !*amail && (strchr( aname, '@' ) || strchr( acomment, '@'))) { - fail = 1; - tty_printf(_("Please don't put the email address " - "into the real name or the comment\n") ); - } - - for(;;) { - const char *ansstr = _("NnCcEeOoQq"); - - if( strlen(ansstr) != 10 ) - BUG(); - if( cpr_enabled() ) { - answer = m_strdup(ansstr+6); - answer[1] = 0; - } - else { - answer = cpr_get("keygen.userid.cmd", fail? - _("Change (N)ame, (C)omment, (E)mail or (Q)uit? ") : - _("Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? ")); - cpr_kill_prompt(); - } - if( strlen(answer) > 1 ) - ; - else if( *answer == ansstr[0] || *answer == ansstr[1] ) { - m_free(aname); aname = NULL; - break; - } - else if( *answer == ansstr[2] || *answer == ansstr[3] ) { - m_free(acomment); acomment = NULL; - break; - } - else if( *answer == ansstr[4] || *answer == ansstr[5] ) { - m_free(amail); amail = NULL; - break; - } - else if( *answer == ansstr[6] || *answer == ansstr[7] ) { - if( fail ) { - tty_printf(_("Please correct the error first\n")); - } - else { - m_free(aname); aname = NULL; - m_free(acomment); acomment = NULL; - m_free(amail); amail = NULL; - break; - } - } - else if( *answer == ansstr[8] || *answer == ansstr[9] ) { - m_free(aname); aname = NULL; - m_free(acomment); acomment = NULL; - m_free(amail); amail = NULL; - m_free(uid); uid = NULL; - break; - } - m_free(answer); - } - m_free(answer); - if( !amail && !acomment && !amail ) - break; - m_free(uid); uid = NULL; - } - if( uid ) { - char *p = native_to_utf8( uid ); - m_free( uid ); - uid = p; - } - return uid; -} - - -static DEK * -ask_passphrase( STRING2KEY **ret_s2k ) -{ - DEK *dek = NULL; - STRING2KEY *s2k; - const char *errtext = NULL; - - tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); - - s2k = m_alloc_secure( sizeof *s2k ); - for(;;) { - s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2,errtext); - if( !dek ) { - errtext = _("passphrase not correctly repeated; try again"); - tty_printf(_("%s.\n"), errtext); - } - else if( !dek->keylen ) { - m_free(dek); dek = NULL; - m_free(s2k); s2k = NULL; - tty_printf(_( - "You don't want a passphrase - this is probably a *bad* idea!\n" - "I will do it anyway. You can change your passphrase at any time,\n" - "using this program with the option \"--edit-key\".\n\n")); - break; - } - else - break; /* okay */ - } - *ret_s2k = s2k; - return dek; -} - - -static int -do_create( int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root, - DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate ) -{ - int rc=0; - - if( !opt.batch ) - tty_printf(_( -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n") ); - - if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E ) - rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate); - else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate); - else if( algo == PUBKEY_ALGO_RSA ) - rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate); - else - BUG(); - - #ifdef ENABLE_COMMENT_PACKETS - if( !rc ) { - add_kbnode( pub_root, - make_comment_node("#created by GNUPG v" VERSION " (" - PRINTABLE_OS_NAME ")")); - add_kbnode( sec_root, - make_comment_node("#created by GNUPG v" VERSION " (" - PRINTABLE_OS_NAME ")")); - } - #endif - return rc; -} - - -/**************** - * Generate a new user id packet, or return NULL if canceled - */ -PKT_user_id * -generate_user_id() -{ - PKT_user_id *uid; - char *p; - size_t n; - - p = ask_user_id( 1 ); - if( !p ) - return NULL; - n = strlen(p); - uid = m_alloc_clear( sizeof *uid + n - 1 ); - uid->len = n; - strcpy(uid->name, p); - uid->ref = 1; - return uid; -} - - -static void -release_parameter_list( struct para_data_s *r ) -{ - struct para_data_s *r2; - - for( ; r ; r = r2 ) { - r2 = r->next; - if( r->key == pPASSPHRASE_DEK ) - m_free( r->u.dek ); - else if( r->key == pPASSPHRASE_S2K ) - m_free( r->u.s2k ); - - m_free(r); - } -} - -static struct para_data_s * -get_parameter( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r; - - for( r = para; r && r->key != key; r = r->next ) - ; - return r; -} - -static const char * -get_parameter_value( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - return (r && *r->u.value)? r->u.value : NULL; -} - -static int -get_parameter_algo( struct para_data_s *para, enum para_name key ) -{ - int i; - struct para_data_s *r = get_parameter( para, key ); - if( !r ) - return -1; - if( isdigit( *r->u.value ) ) - i = atoi( r->u.value ); - else - i = string_to_pubkey_algo( r->u.value ); - if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S) - i = 0; /* we don't want to allow generation of these algorithms */ - return i; -} - -/* - * parse the usage parameter and set the keyflags. Return true on error. - */ -static int -parse_parameter_usage (const char *fname, - struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r = get_parameter( para, key ); - char *p, *pn; - unsigned int use; - - if( !r ) - return 0; /* none (this is an optional parameter)*/ - - use = 0; - pn = r->u.value; - while ( (p = strsep (&pn, " \t,")) ) { - if ( !*p) - ; - else if ( !ascii_strcasecmp (p, "sign") ) - use |= PUBKEY_USAGE_SIG; - else if ( !ascii_strcasecmp (p, "encrypt") ) - use |= PUBKEY_USAGE_ENC; - else { - log_error("%s:%d: invalid usage list\n", fname, r->lnr ); - return -1; /* error */ - } - } - r->u.usage = use; - return 0; -} - -static int -parse_revocation_key (const char *fname, - struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r = get_parameter( para, key ); - struct revocation_key revkey; - char *pn; - int i; - - if( !r ) - return 0; /* none (this is an optional parameter) */ - - pn = r->u.value; - - revkey.class=0x80; - revkey.algid=atoi(pn); - if(!revkey.algid) - goto fail; - - /* Skip to the fpr */ - while(*pn && *pn!=':') - pn++; - - if(*pn!=':') - goto fail; - - pn++; - - for(i=0;iu.revkey,&revkey,sizeof(struct revocation_key)); - - return 0; - - fail: - log_error("%s:%d: invalid revocation key\n", fname, r->lnr ); - return -1; /* error */ -} - - -static u32 -get_parameter_u32( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - - if( !r ) - return 0; - if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE ) - return r->u.expire; - if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE ) - return r->u.usage; - - return (unsigned int)strtoul( r->u.value, NULL, 10 ); -} - -static unsigned int -get_parameter_uint( struct para_data_s *para, enum para_name key ) -{ - return get_parameter_u32( para, key ); -} - -static DEK * -get_parameter_dek( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - return r? r->u.dek : NULL; -} - -static STRING2KEY * -get_parameter_s2k( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - return r? r->u.s2k : NULL; -} - -static struct revocation_key * -get_parameter_revkey( struct para_data_s *para, enum para_name key ) -{ - struct para_data_s *r = get_parameter( para, key ); - return r? &r->u.revkey : NULL; -} - -static int -proc_parameter_file( struct para_data_s *para, const char *fname, - struct output_control_s *outctrl ) -{ - struct para_data_s *r; - const char *s1, *s2, *s3; - size_t n; - char *p; - int i; - - /* check that we have all required parameters */ - assert( get_parameter( para, pKEYTYPE ) ); - i = get_parameter_algo( para, pKEYTYPE ); - if( i < 1 || check_pubkey_algo2( i, PUBKEY_USAGE_SIG ) ) { - r = get_parameter( para, pKEYTYPE ); - log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); - return -1; - } - - if (parse_parameter_usage (fname, para, pKEYUSAGE)) - return -1; - - i = get_parameter_algo( para, pSUBKEYTYPE ); - if( i > 0 && check_pubkey_algo( i ) ) { - r = get_parameter( para, pSUBKEYTYPE ); - log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); - return -1; - } - if (i > 0 && parse_parameter_usage (fname, para, pSUBKEYUSAGE)) - return -1; - - - if( !get_parameter_value( para, pUSERID ) ) { - /* create the formatted user ID */ - s1 = get_parameter_value( para, pNAMEREAL ); - s2 = get_parameter_value( para, pNAMECOMMENT ); - s3 = get_parameter_value( para, pNAMEEMAIL ); - if( s1 || s2 || s3 ) { - n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0); - r = m_alloc_clear( sizeof *r + n + 20 ); - r->key = pUSERID; - p = r->u.value; - if( s1 ) - p = stpcpy(p, s1 ); - if( s2 ) - p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")"); - if( s3 ) - p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">"); - r->next = para; - para = r; - } - } - - /* Set preferences, if any. */ - keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0); - - /* Set revoker, if any. */ - if (parse_revocation_key (fname, para, pREVOKER)) - return -1; - - /* make DEK and S2K from the Passphrase */ - r = get_parameter( para, pPASSPHRASE ); - if( r && *r->u.value ) { - /* we have a plain text passphrase - create a DEK from it. - * It is a little bit ridiculous to keep it ih secure memory - * but becuase we do this alwasy, why not here */ - STRING2KEY *s2k; - DEK *dek; - - s2k = m_alloc_secure( sizeof *s2k ); - s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; - set_next_passphrase( r->u.value ); - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL ); - set_next_passphrase( NULL ); - assert( dek ); - memset( r->u.value, 0, strlen(r->u.value) ); - - r = m_alloc_clear( sizeof *r ); - r->key = pPASSPHRASE_S2K; - r->u.s2k = s2k; - r->next = para; - para = r; - r = m_alloc_clear( sizeof *r ); - r->key = pPASSPHRASE_DEK; - r->u.dek = dek; - r->next = para; - para = r; - } - - /* make KEYEXPIRE from Expire-Date */ - r = get_parameter( para, pEXPIREDATE ); - if( r && *r->u.value ) { - i = parse_expire_string( r->u.value ); - if( i < 0 ) { - log_error("%s:%d: invalid expire date\n", fname, r->lnr ); - return -1; - } - r->u.expire = i * 86400L; - r->key = pKEYEXPIRE; /* change hat entry */ - /* also set it for the subkey */ - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pSUBKEYEXPIRE; - r->u.expire = i * 86400L; - r->next = para; - para = r; - } - - if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) { - log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr ); - return -1; - } - - do_generate_keypair( para, outctrl ); - return 0; -} - - -/**************** - * Kludge to allow non interactive key generation controlled - * by a parameter file (which currently is only stdin) - * Note, that string parameters are expected to be in UTF-8 - */ -static void -read_parameter_file( const char *fname ) -{ - static struct { const char *name; - enum para_name key; - } keywords[] = { - { "Key-Type", pKEYTYPE}, - { "Key-Length", pKEYLENGTH }, - { "Key-Usage", pKEYUSAGE }, - { "Subkey-Type", pSUBKEYTYPE }, - { "Subkey-Length", pSUBKEYLENGTH }, - { "Subkey-Usage", pSUBKEYUSAGE }, - { "Name-Real", pNAMEREAL }, - { "Name-Email", pNAMEEMAIL }, - { "Name-Comment", pNAMECOMMENT }, - { "Expire-Date", pEXPIREDATE }, - { "Passphrase", pPASSPHRASE }, - { "Preferences", pPREFERENCES }, - { "Revoker", pREVOKER }, - { NULL, 0 } - }; - FILE *fp; - char line[1024], *p; - int lnr; - const char *err = NULL; - struct para_data_s *para, *r; - int i; - struct output_control_s outctrl; - - memset( &outctrl, 0, sizeof( outctrl ) ); - - if( !fname || !*fname || !strcmp(fname,"-") ) { - fp = stdin; - fname = "-"; - } - else { - fp = fopen( fname, "r" ); - if( !fp ) { - log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); - return; - } - } - - lnr = 0; - err = NULL; - para = NULL; - while( fgets( line, DIM(line)-1, fp ) ) { - char *keyword, *value; - - lnr++; - if( *line && line[strlen(line)-1] != '\n' ) { - err = "line too long"; - break; - } - for( p = line; isspace(*(byte*)p); p++ ) - ; - if( !*p || *p == '#' ) - continue; - keyword = p; - if( *keyword == '%' ) { - for( ; !isspace(*(byte*)p); p++ ) - ; - if( *p ) - *p++ = 0; - for( ; isspace(*(byte*)p); p++ ) - ; - value = p; - trim_trailing_ws( value, strlen(value) ); - if( !ascii_strcasecmp( keyword, "%echo" ) ) - log_info("%s\n", value ); - else if( !ascii_strcasecmp( keyword, "%dry-run" ) ) - outctrl.dryrun = 1; - else if( !ascii_strcasecmp( keyword, "%commit" ) ) { - outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl ); - release_parameter_list( para ); - para = NULL; - } - else if( !ascii_strcasecmp( keyword, "%pubring" ) ) { - if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) ) - ; /* still the same file - ignore it */ - else { - m_free( outctrl.pub.newfname ); - outctrl.pub.newfname = m_strdup( value ); - outctrl.use_files = 1; - } - } - else if( !ascii_strcasecmp( keyword, "%secring" ) ) { - if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) ) - ; /* still the same file - ignore it */ - else { - m_free( outctrl.sec.newfname ); - outctrl.sec.newfname = m_strdup( value ); - outctrl.use_files = 1; - } - } - else - log_info("skipping control `%s' (%s)\n", keyword, value ); - - - continue; - } - - - if( !(p = strchr( p, ':' )) || p == keyword ) { - err = "missing colon"; - break; - } - if( *p ) - *p++ = 0; - for( ; isspace(*(byte*)p); p++ ) - ; - if( !*p ) { - err = "missing argument"; - break; - } - value = p; - trim_trailing_ws( value, strlen(value) ); - - for(i=0; keywords[i].name; i++ ) { - if( !ascii_strcasecmp( keywords[i].name, keyword ) ) - break; - } - if( !keywords[i].name ) { - err = "unknown keyword"; - break; - } - if( keywords[i].key != pKEYTYPE && !para ) { - err = "parameter block does not start with \"Key-Type\""; - break; - } - - if( keywords[i].key == pKEYTYPE && para ) { - outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl ); - release_parameter_list( para ); - para = NULL; - } - else { - for( r = para; r; r = r->next ) { - if( r->key == keywords[i].key ) - break; - } - if( r ) { - err = "duplicate keyword"; - break; - } - } - r = m_alloc_clear( sizeof *r + strlen( value ) ); - r->lnr = lnr; - r->key = keywords[i].key; - strcpy( r->u.value, value ); - r->next = para; - para = r; - } - if( err ) - log_error("%s:%d: %s\n", fname, lnr, err ); - else if( ferror(fp) ) { - log_error("%s:%d: read error: %s\n", fname, lnr, strerror(errno) ); - } - else if( para ) { - outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl ); - } - - if( outctrl.use_files ) { /* close open streams */ - iobuf_close( outctrl.pub.stream ); - iobuf_close( outctrl.sec.stream ); - m_free( outctrl.pub.fname ); - m_free( outctrl.pub.newfname ); - m_free( outctrl.sec.fname ); - m_free( outctrl.sec.newfname ); - } - - release_parameter_list( para ); - if( strcmp( fname, "-" ) ) - fclose(fp); -} - - -/**************** - * Generate a keypair - * (fname is only used in batch mode) - */ -void -generate_keypair( const char *fname ) -{ - unsigned int nbits; - char *uid = NULL; - DEK *dek; - STRING2KEY *s2k; - int algo; - unsigned int use; - int both = 0; - u32 expire; - struct para_data_s *para = NULL; - struct para_data_s *r; - struct output_control_s outctrl; - - memset( &outctrl, 0, sizeof( outctrl ) ); - - if( opt.batch ) { - read_parameter_file( fname ); - return; - } - - algo = ask_algo( 0, &use ); - if( !algo ) { /* default: DSA with ElG subkey of the specified size */ - both = 1; - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); - r->next = para; - para = r; - tty_printf(_("DSA keypair will have 1024 bits.\n")); - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pKEYLENGTH; - strcpy( r->u.value, "1024" ); - r->next = para; - para = r; - - algo = PUBKEY_ALGO_ELGAMAL_E; - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pSUBKEYTYPE; - sprintf( r->u.value, "%d", algo ); - r->next = para; - para = r; - } - else { - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo ); - r->next = para; - para = r; - - if (use) { - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pKEYUSAGE; - sprintf( r->u.value, "%s%s", - (use & PUBKEY_USAGE_SIG)? "sign ":"", - (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); - r->next = para; - para = r; - } - - } - - nbits = ask_keysize( algo ); - r = m_alloc_clear( sizeof *r + 20 ); - r->key = both? pSUBKEYLENGTH : pKEYLENGTH; - sprintf( r->u.value, "%u", nbits); - r->next = para; - para = r; - - expire = ask_expire_interval(0); - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pKEYEXPIRE; - r->u.expire = expire; - r->next = para; - para = r; - r = m_alloc_clear( sizeof *r + 20 ); - r->key = pSUBKEYEXPIRE; - r->u.expire = expire; - r->next = para; - para = r; - - uid = ask_user_id(0); - if( !uid ) { - log_error(_("Key generation canceled.\n")); - release_parameter_list( para ); - return; - } - r = m_alloc_clear( sizeof *r + strlen(uid) ); - r->key = pUSERID; - strcpy( r->u.value, uid ); - r->next = para; - para = r; - - dek = ask_passphrase( &s2k ); - if( dek ) { - r = m_alloc_clear( sizeof *r ); - r->key = pPASSPHRASE_DEK; - r->u.dek = dek; - r->next = para; - para = r; - r = m_alloc_clear( sizeof *r ); - r->key = pPASSPHRASE_S2K; - r->u.s2k = s2k; - r->next = para; - para = r; - } - - proc_parameter_file( para, "[internal]", &outctrl ); - release_parameter_list( para ); -} - - -static void -print_status_key_created (int letter, PKT_public_key *pk) -{ - byte array[MAX_FINGERPRINT_LEN], *s; - char buf[MAX_FINGERPRINT_LEN*2+30], *p; - size_t i, n; - - p = buf; - *p++ = letter; - *p++ = ' '; - fingerprint_from_pk (pk, array, &n); - s = array; - for (i=0; i < n ; i++, s++, p += 2) - sprintf (p, "%02X", *s); - *p = 0; - write_status_text (STATUS_KEY_CREATED, buf); -} - -static void -do_generate_keypair( struct para_data_s *para, - struct output_control_s *outctrl ) -{ - KBNODE pub_root = NULL; - KBNODE sec_root = NULL; - PKT_secret_key *sk = NULL; - const char *s; - struct revocation_key *revkey; - int rc; - int did_sub = 0; - - if( outctrl->dryrun ) { - log_info("dry-run mode - key generation skipped\n"); - return; - } - - - if( outctrl->use_files ) { - if( outctrl->pub.newfname ) { - iobuf_close(outctrl->pub.stream); - outctrl->pub.stream = NULL; - m_free( outctrl->pub.fname ); - outctrl->pub.fname = outctrl->pub.newfname; - outctrl->pub.newfname = NULL; - - outctrl->pub.stream = iobuf_create( outctrl->pub.fname ); - if( !outctrl->pub.stream ) { - log_error("can't create `%s': %s\n", outctrl->pub.newfname, - strerror(errno) ); - return; - } - if( opt.armor ) { - outctrl->pub.afx.what = 1; - iobuf_push_filter( outctrl->pub.stream, armor_filter, - &outctrl->pub.afx ); - } - } - if( outctrl->sec.newfname ) { - iobuf_close(outctrl->sec.stream); - outctrl->sec.stream = NULL; - m_free( outctrl->sec.fname ); - outctrl->sec.fname = outctrl->sec.newfname; - outctrl->sec.newfname = NULL; - - outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); - if( !outctrl->sec.stream ) { - log_error("can't create `%s': %s\n", outctrl->sec.newfname, - strerror(errno) ); - return; - } - if( opt.armor ) { - outctrl->sec.afx.what = 5; - iobuf_push_filter( outctrl->sec.stream, armor_filter, - &outctrl->sec.afx ); - } - } - assert( outctrl->pub.stream ); - assert( outctrl->sec.stream ); - if( opt.verbose ) { - log_info(_("writing public key to `%s'\n"), outctrl->pub.fname ); - log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname ); - } - } - - - /* we create the packets as a tree of kbnodes. Because the structure - * we create is known in advance we simply generate a linked list - * The first packet is a dummy comment packet which we flag - * as deleted. The very first packet must always be a KEY packet. - */ - pub_root = make_comment_node("#"); delete_kbnode(pub_root); - sec_root = make_comment_node("#"); delete_kbnode(sec_root); - - rc = do_create( get_parameter_algo( para, pKEYTYPE ), - get_parameter_uint( para, pKEYLENGTH ), - pub_root, sec_root, - get_parameter_dek( para, pPASSPHRASE_DEK ), - get_parameter_s2k( para, pPASSPHRASE_S2K ), - &sk, - get_parameter_u32( para, pKEYEXPIRE ) ); - - if(!rc && (revkey=get_parameter_revkey(para,pREVOKER))) - { - rc=write_direct_sig(pub_root,pub_root,sk,revkey); - if(!rc) - write_direct_sig(sec_root,pub_root,sk,revkey); - } - - if( !rc && (s=get_parameter_value(para, pUSERID)) ) { - write_uid(pub_root, s ); - if( !rc ) - write_uid(sec_root, s ); - if( !rc ) - rc = write_selfsig(pub_root, pub_root, sk, - get_parameter_uint (para, pKEYUSAGE)); - if( !rc ) - rc = write_selfsig(sec_root, pub_root, sk, - get_parameter_uint (para, pKEYUSAGE)); - } - - if( get_parameter( para, pSUBKEYTYPE ) ) { - rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ), - get_parameter_uint( para, pSUBKEYLENGTH ), - pub_root, sec_root, - get_parameter_dek( para, pPASSPHRASE_DEK ), - get_parameter_s2k( para, pPASSPHRASE_S2K ), - NULL, - get_parameter_u32( para, pSUBKEYEXPIRE ) ); - if( !rc ) - rc = write_keybinding(pub_root, pub_root, sk, - get_parameter_uint (para, pSUBKEYUSAGE)); - if( !rc ) - rc = write_keybinding(sec_root, pub_root, sk, - get_parameter_uint (para, pSUBKEYUSAGE)); - did_sub = 1; - } - - - if( !rc && outctrl->use_files ) { /* direct write to specified files */ - rc = write_keyblock( outctrl->pub.stream, pub_root ); - if( rc ) - log_error("can't write public key: %s\n", g10_errstr(rc) ); - if( !rc ) { - rc = write_keyblock( outctrl->sec.stream, sec_root ); - if( rc ) - log_error("can't write secret key: %s\n", g10_errstr(rc) ); - } - - } - else if( !rc ) { /* write to the standard keyrings */ - KEYDB_HANDLE pub_hd = keydb_new (0); - KEYDB_HANDLE sec_hd = keydb_new (1); - - /* FIXME: we may have to create the keyring first */ - rc = keydb_locate_writable (pub_hd, NULL); - if (rc) - log_error (_("no writable public keyring found: %s\n"), - g10_errstr (rc)); - - if (!rc) { - rc = keydb_locate_writable (sec_hd, NULL); - if (rc) - log_error (_("no writable secret keyring found: %s\n"), - g10_errstr (rc)); - } - - if (!rc && opt.verbose) { - log_info(_("writing public key to `%s'\n"), - keydb_get_resource_name (pub_hd)); - log_info(_("writing secret key to `%s'\n"), - keydb_get_resource_name (sec_hd)); - } - - if (!rc) { - rc = keydb_insert_keyblock (pub_hd, pub_root); - if (rc) - log_error (_("error writing public keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), g10_errstr(rc)); - } - - if (!rc) { - rc = keydb_insert_keyblock (sec_hd, sec_root); - if (rc) - log_error (_("error writing secret keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), g10_errstr(rc)); - } - - keydb_release (pub_hd); - keydb_release (sec_hd); - - if (!rc) { - int no_enc_rsa = - get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA - && get_parameter_uint( para, pKEYUSAGE ) - && !(get_parameter_uint( para,pKEYUSAGE) & PUBKEY_USAGE_ENC); - PKT_public_key *pk = find_kbnode (pub_root, - PKT_PUBLIC_KEY)->pkt->pkt.public_key; - - update_ownertrust (pk, - ((get_ownertrust (pk) & ~TRUST_MASK) - | TRUST_ULTIMATE )); - - if (!opt.batch) { - tty_printf(_("public and secret key created and signed.\n") ); - tty_printf(_("key marked as ultimately trusted.\n") ); - tty_printf("\n"); - list_keyblock(pub_root,0,1,NULL); - } - - - if( !opt.batch - && ( get_parameter_algo( para, pKEYTYPE ) == PUBKEY_ALGO_DSA - || no_enc_rsa ) - && !get_parameter( para, pSUBKEYTYPE ) ) - { - tty_printf(_("Note that this key cannot be used for " - "encryption. You may want to use\n" - "the command \"--edit-key\" to generate a " - "secondary key for this purpose.\n") ); - } - } - } - - if( rc ) { - if( opt.batch ) - log_error("key generation failed: %s\n", g10_errstr(rc) ); - else - tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) ); - } - else { - PKT_public_key *pk = find_kbnode (pub_root, - PKT_PUBLIC_KEY)->pkt->pkt.public_key; - print_status_key_created (did_sub? 'B':'P', pk); - } - release_kbnode( pub_root ); - release_kbnode( sec_root ); - if( sk ) /* the unprotected secret key */ - free_secret_key(sk); -} - - -/**************** - * add a new subkey to an existing key. - * Returns true if a new key has been generated and put into the keyblocks. - */ -int -generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) -{ - int okay=0, rc=0; - KBNODE node; - PKT_secret_key *sk = NULL; /* this is the primary sk */ - int algo; - unsigned int use; - u32 expire; - unsigned nbits; - char *passphrase = NULL; - DEK *dek = NULL; - STRING2KEY *s2k = NULL; - u32 cur_time; - - /* break out the primary secret key */ - node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); - if( !node ) { - log_error("Oops; secret key not found anymore!\n"); - goto leave; - } - - /* make a copy of the sk to keep the protected one in the keyblock */ - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key ); - - cur_time = make_timestamp(); - if( sk->timestamp > cur_time ) { - ulong d = sk->timestamp - cur_time; - log_info( d==1 ? _("key has been created %lu second " - "in future (time warp or clock problem)\n") - : _("key has been created %lu seconds " - "in future (time warp or clock problem)\n"), d ); - if( !opt.ignore_time_conflict ) { - rc = G10ERR_TIME_CONFLICT; - goto leave; - } - } - - if (sk->version < 4) { - log_info (_("NOTE: creating subkeys for v3 keys " - "is not OpenPGP compliant\n")); - goto leave; - } - - /* unprotect to get the passphrase */ - switch( is_secret_key_protected( sk ) ) { - case -1: - rc = G10ERR_PUBKEY_ALGO; - break; - case 0: - tty_printf("This key is not protected.\n"); - break; - default: - tty_printf("Key is protected.\n"); - rc = check_secret_key( sk, 0 ); - if( !rc ) - passphrase = get_last_passphrase(); - break; - } - if( rc ) - goto leave; - - - algo = ask_algo( 1, &use ); - assert(algo); - nbits = ask_keysize( algo ); - expire = ask_expire_interval(0); - if( !cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay", - _("Really create? ") ) ) - goto leave; - - if( passphrase ) { - s2k = m_alloc_secure( sizeof *s2k ); - s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; - set_next_passphrase( passphrase ); - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL ); - } - - rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, - dek, s2k, NULL, expire ); - if( !rc ) - rc = write_keybinding(pub_keyblock, pub_keyblock, sk, use); - if( !rc ) - rc = write_keybinding(sec_keyblock, pub_keyblock, sk, use); - if( !rc ) { - okay = 1; - write_status_text (STATUS_KEY_CREATED, "S"); - } - - leave: - if( rc ) - log_error(_("Key generation failed: %s\n"), g10_errstr(rc) ); - m_free( passphrase ); - m_free( dek ); - m_free( s2k ); - if( sk ) /* release the copy of the (now unprotected) secret key */ - free_secret_key(sk); - set_next_passphrase( NULL ); - return okay; -} - -/**************** - * Write a keyblock to an output stream - */ -static int -write_keyblock( IOBUF out, KBNODE node ) -{ - for( ; node ; node = node->next ) { - int rc = build_packet( out, node->pkt ); - if( rc ) { - log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - return G10ERR_WRITE_FILE; - } - } - return 0; -} diff --git a/g10/keyid.c b/g10/keyid.c deleted file mode 100644 index 43e531e3e..000000000 --- a/g10/keyid.c +++ /dev/null @@ -1,502 +0,0 @@ -/* keyid.c - key ID and fingerprint handling - * 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 -#include -#include -#include -#include -#include -#include -#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 MD_HANDLE -do_fingerprint_md( PKT_public_key *pk ) -{ - MD_HANDLE md; - unsigned n; - unsigned nb[PUBKEY_MAX_NPKEY]; - unsigned nn[PUBKEY_MAX_NPKEY]; - byte *pp[PUBKEY_MAX_NPKEY]; - int i; - int npkey = pubkey_get_npkey( pk->pubkey_algo ); - - md = md_open( pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); - n = pk->version < 4 ? 8 : 6; - for(i=0; i < npkey; i++ ) { - nb[i] = mpi_get_nbits(pk->pkey[i]); - pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL ); - n += 2 + nn[i]; - } - - md_putc( md, 0x99 ); /* ctb */ - md_putc( md, n >> 8 ); /* 2 byte length header */ - md_putc( md, n ); - if( pk->version < 4 ) - md_putc( md, 3 ); - else - md_putc( md, 4 ); - - { u32 a = pk->timestamp; - md_putc( md, a >> 24 ); - md_putc( md, a >> 16 ); - md_putc( md, a >> 8 ); - md_putc( md, a ); - } - if( pk->version < 4 ) { - u16 a; - - if( pk->expiredate ) - a = (u16)((pk->expiredate - pk->timestamp) / 86400L); - else - a = 0; - md_putc( md, a >> 8 ); - md_putc( md, a ); - } - md_putc( md, pk->pubkey_algo ); - for(i=0; i < npkey; i++ ) { - md_putc( md, nb[i]>>8); - md_putc( md, nb[i] ); - md_write( md, pp[i], nn[i] ); - m_free(pp[i]); - } - md_final( md ); - - return md; -} - -static MD_HANDLE -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 ); -} - - -/**************** - * 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) ) { - lowbits = pubkey_get_npkey(sk->pubkey_algo) ? - mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */ - } - else { - const byte *dp; - MD_HANDLE md; - md = do_fingerprint_md_sk(sk); - dp = 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]; - 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) ) { - lowbits = pubkey_get_npkey(pk->pubkey_algo) ? - mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */ - pk->keyid[0] = keyid[0]; - pk->keyid[1] = keyid[1]; - } - else { - const byte *dp; - MD_HANDLE md; - md = do_fingerprint_md(pk); - dp = 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]; - 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]; -} - -/**************** - * 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 *p, *buf; - const byte *dp; - size_t len; - unsigned int n; - - if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) { - /* RSA in version 3 packets is special */ - MD_HANDLE md; - - md = md_open( DIGEST_ALGO_MD5, 0); - if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) { - p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL ); - md_write( md, p, n ); - m_free(buf); - p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL ); - md_write( md, p, n ); - m_free(buf); - } - md_final(md); - if( !array ) - array = m_alloc( 16 ); - len = 16; - memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); - md_close(md); - } - else { - MD_HANDLE md; - md = do_fingerprint_md(pk); - dp = md_read( md, 0 ); - len = md_digest_length( md_get_algo( md ) ); - assert( len <= MAX_FINGERPRINT_LEN ); - if( !array ) - array = m_alloc( 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] ; - md_close(md); - } - - *ret_len = len; - return array; -} - -byte * -fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) -{ - byte *p, *buf; - const char *dp; - size_t len; - unsigned n; - - if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) { - /* RSA in version 3 packets is special */ - MD_HANDLE md; - - md = md_open( DIGEST_ALGO_MD5, 0); - if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) { - p = buf = mpi_get_buffer( sk->skey[0], &n, NULL ); - md_write( md, p, n ); - m_free(buf); - p = buf = mpi_get_buffer( sk->skey[1], &n, NULL ); - md_write( md, p, n ); - m_free(buf); - } - md_final(md); - if( !array ) - array = m_alloc( 16 ); - len = 16; - memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); - md_close(md); - } - else { - MD_HANDLE md; - md = do_fingerprint_md_sk(sk); - dp = md_read( md, 0 ); - len = md_digest_length( md_get_algo( md ) ); - assert( len <= MAX_FINGERPRINT_LEN ); - if( !array ) - array = m_alloc( len ); - memcpy(array, dp, len ); - md_close(md); - } - - *ret_len = len; - return array; -} - - - diff --git a/g10/keylist.c b/g10/keylist.c deleted file mode 100644 index a1a0e4c13..000000000 --- a/g10/keylist.c +++ /dev/null @@ -1,1116 +0,0 @@ -/* keylist.c - * 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 -#include -#include -#include -#include -#include - -#include "options.h" -#include "packet.h" -#include "errors.h" -#include "keydb.h" -#include "memory.h" -#include "photoid.h" -#include "util.h" -#include "ttyio.h" -#include "trustdb.h" -#include "main.h" -#include "i18n.h" -#include "status.h" - -static void list_all(int); -static void list_one( STRLIST names, int secret); - -struct sig_stats -{ - int inv_sigs; - int no_key; - int oth_err; -}; - -static FILE *attrib_fp=NULL; - -/**************** - * List the keys - * If list is NULL, all available keys are listed - */ -void -public_key_list( STRLIST list ) -{ - if( !list ) - list_all(0); - else - list_one( list, 0 ); -} - -void -secret_key_list( STRLIST list ) -{ - if( !list ) - list_all(1); - else /* List by user id */ - list_one( list, 1 ); -} - -void -show_policy_url(PKT_signature *sig,int indent) -{ - const byte *p; - size_t len; - int seq=0,crit; - - while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit))) - { - int i; - - for(i=0;ihashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) - if(len>=8) - { - int n1,n2,i; - - n1=(p[4]<<8)|p[5]; - n2=(p[6]<<8)|p[7]; - - if(8+n1+n2!=len) - { - log_info(_("WARNING: invalid notation data found\n")); - return; - } - - for(i=0;iinv_sigs == 1 ) - tty_printf(_("1 bad signature\n") ); - else if( s->inv_sigs ) - tty_printf(_("%d bad signatures\n"), s->inv_sigs ); - if( s->no_key == 1 ) - tty_printf(_("1 signature not checked due to a missing key\n") ); - else if( s->no_key ) - tty_printf(_("%d signatures not checked due to missing keys\n"),s->no_key); - if( s->oth_err == 1 ) - tty_printf(_("1 signature not checked due to an error\n") ); - else if( s->oth_err ) - tty_printf(_("%d signatures not checked due to errors\n"), s->oth_err ); -} - -static void -list_all( int secret ) -{ - KEYDB_HANDLE hd; - KBNODE keyblock = NULL; - int rc=0; - const char *lastresname, *resname; - struct sig_stats stats; - - memset(&stats,0,sizeof(stats)); - - hd = keydb_new (secret); - if (!hd) - rc = G10ERR_GENERAL; - else - rc = keydb_search_first (hd); - if( rc ) { - if( rc != -1 ) - log_error("keydb_search_first failed: %s\n", g10_errstr(rc) ); - goto leave; - } - - lastresname = NULL; - do { - rc = keydb_get_keyblock (hd, &keyblock); - if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - goto leave; - } - resname = keydb_get_resource_name (hd); - if (lastresname != resname ) { - int i; - - printf("%s\n", resname ); - for(i=strlen(resname); i; i-- ) - putchar('-'); - putchar('\n'); - lastresname = resname; - } - merge_keys_and_selfsig( keyblock ); - list_keyblock( keyblock, secret, opt.fingerprint, - opt.check_sigs?&stats:NULL); - release_kbnode( keyblock ); - keyblock = NULL; - } while (!(rc = keydb_search_next (hd))); - if( rc && rc != -1 ) - log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); - - if(opt.check_sigs && !opt.with_colons) - print_signature_stats(&stats); - - leave: - release_kbnode (keyblock); - keydb_release (hd); -} - - -static void -list_one( STRLIST names, int secret ) -{ - int rc = 0; - KBNODE keyblock = NULL; - GETKEY_CTX ctx; - const char *resname; - char *keyring_str = N_("Keyring"); - int i; - struct sig_stats stats; - - memset(&stats,0,sizeof(stats)); - - /* fixme: using the bynames function has the disadvantage that we - * don't know wether one of the names given was not found. OTOH, - * this function has the advantage to list the names in the - * sequence as defined by the keyDB and does not duplicate - * outputs. A solution could be do test whether all given have - * been listed (this needs a way to use the keyDB search - * functions) or to have the search function return indicators for - * found names. Yet another way is to use the keydb search - * facilities directly. */ - if( secret ) { - rc = get_seckey_bynames( &ctx, NULL, names, &keyblock ); - if( rc ) { - log_error("error reading key: %s\n", g10_errstr(rc) ); - get_seckey_end( ctx ); - return; - } - do { - if (opt.show_keyring) { - resname = keydb_get_resource_name (get_ctx_handle(ctx)); - printf("%s: %s\n", keyring_str, resname); - for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- ) - putchar('-'); - putchar('\n'); - } - list_keyblock( keyblock, 1, opt.fingerprint, NULL ); - release_kbnode( keyblock ); - } while( !get_seckey_next( ctx, NULL, &keyblock ) ); - get_seckey_end( ctx ); - } - else { - rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock ); - if( rc ) { - log_error("error reading key: %s\n", g10_errstr(rc) ); - get_pubkey_end( ctx ); - return; - } - do { - if (opt.show_keyring) { - resname = keydb_get_resource_name (get_ctx_handle(ctx)); - printf("%s: %s\n", keyring_str, resname); - for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- ) - putchar('-'); - putchar('\n'); - } - list_keyblock( keyblock, 0, opt.fingerprint, - opt.check_sigs?&stats:NULL ); - release_kbnode( keyblock ); - } while( !get_pubkey_next( ctx, NULL, &keyblock ) ); - get_pubkey_end( ctx ); - } - - if(opt.check_sigs && !opt.with_colons) - print_signature_stats(&stats); -} - -static void -print_key_data( PKT_public_key *pk, u32 *keyid ) -{ - int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; - int i; - - for(i=0; i < n; i++ ) { - printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) ); - mpi_print(stdout, pk->pkey[i], 1 ); - putchar(':'); - putchar('\n'); - } -} - -static void -print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) -{ - if(pk || (sk && sk->protect.s2k.mode!=1001)) - { - unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage; - - if ( use & PUBKEY_USAGE_ENC ) - putchar ('e'); - - if ( use & PUBKEY_USAGE_SIG ) - { - putchar ('s'); - if( pk? pk->is_primary : sk->is_primary ) - putchar ('c'); - } - } - - if ( keyblock ) { /* figure our the usable capabilities */ - KBNODE k; - int enc=0, sign=0, cert=0; - - for (k=keyblock; k; k = k->next ) { - if ( k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - pk = k->pkt->pkt.public_key; - if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) { - if ( pk->pubkey_usage & PUBKEY_USAGE_ENC ) - enc = 1; - if ( pk->pubkey_usage & PUBKEY_USAGE_SIG ) - { - sign = 1; - if(pk->is_primary) - cert = 1; - } - } - } - else if ( k->pkt->pkttype == PKT_SECRET_KEY - || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { - sk = k->pkt->pkt.secret_key; - if ( sk->is_valid && !sk->is_revoked && !sk->has_expired - && sk->protect.s2k.mode!=1001 ) { - if ( sk->pubkey_usage & PUBKEY_USAGE_ENC ) - enc = 1; - if ( sk->pubkey_usage & PUBKEY_USAGE_SIG ) - { - sign = 1; - if(sk->is_primary) - cert = 1; - } - } - } - } - if (enc) - putchar ('E'); - if (sign) - putchar ('S'); - if (cert) - putchar ('C'); - } - putchar(':'); -} - -static void dump_attribs(const PKT_user_id *uid, - PKT_public_key *pk,PKT_secret_key *sk) -{ - int i; - - if(!attrib_fp) - BUG(); - - for(i=0;inumattribs;i++) - { - if(is_status_enabled()) - { - byte array[MAX_FINGERPRINT_LEN], *p; - char buf[(MAX_FINGERPRINT_LEN*2)+90]; - size_t j,n; - - if(pk) - fingerprint_from_pk( pk, array, &n ); - else if(sk) - fingerprint_from_sk( sk, array, &n ); - else - BUG(); - - p = array; - for(j=0; j < n ; j++, p++ ) - sprintf(buf+2*j, "%02X", *p ); - - sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u", - (ulong)uid->attribs[i].len,uid->attribs[i].type,i+1, - uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate, - ((uid->is_primary?0x01:0)| - (uid->is_revoked?0x02:0)| - (uid->is_expired?0x04:0))); - write_status_text(STATUS_ATTRIBUTE,buf); - } - - fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp); - } -} - -static void -list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) -{ - int rc = 0; - KBNODE kbctx; - KBNODE node; - PKT_public_key *pk; - PKT_secret_key *sk; - u32 keyid[2]; - int any=0; - struct sig_stats *stats=opaque; - - /* get the keyid from the keyblock */ - node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); - if( !node ) { - log_error("Oops; key lost!\n"); - dump_kbnode( keyblock ); - return; - } - - if( secret ) { - pk = NULL; - sk = node->pkt->pkt.secret_key; - keyid_from_sk( sk, keyid ); - printf("sec%c %4u%c/%08lX %s ", (sk->protect.s2k.mode==1001)?'#':' ', - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid[1], - datestr_from_sk( sk ) ); - } - else { - pk = node->pkt->pkt.public_key; - sk = NULL; - keyid_from_pk( pk, keyid ); - printf("pub %4u%c/%08lX %s ", nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], - datestr_from_pk( pk ) ); - } - - for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { - if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { - if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) - dump_attribs(node->pkt->pkt.user_id,pk,sk); - /* don't list revoked or expired UIDS unless we are in - * verbose mode and signature listing has not been - * requested */ - if ( !opt.verbose && !opt.list_sigs && - (node->pkt->pkt.user_id->is_revoked || - node->pkt->pkt.user_id->is_expired )) - continue; - - if( any ) - printf("uid%*s", 28, ""); - - if ( node->pkt->pkt.user_id->is_revoked ) - fputs ("[revoked] ", stdout); - if ( node->pkt->pkt.user_id->is_expired ) - fputs ("[expired] ", stdout); - print_utf8_string( stdout, node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len ); - putchar('\n'); - if( !any ) { - if( fpr ) - print_fingerprint( pk, sk, 0 ); - if( opt.with_key_data ) - print_key_data( pk, keyid ); - any = 1; - } - - if(opt.show_photos && node->pkt->pkt.user_id->attribs!=NULL) - show_photos(node->pkt->pkt.user_id->attribs, - node->pkt->pkt.user_id->numattribs,pk,sk); - } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - u32 keyid2[2]; - PKT_public_key *pk2 = node->pkt->pkt.public_key; - - if( !any ) { - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); /* of the main key */ - any = 1; - } - - keyid_from_pk( pk2, keyid2 ); - printf("sub %4u%c/%08lX %s", nbits_from_pk( pk2 ), - pubkey_letter( pk2->pubkey_algo ), - (ulong)keyid2[1], - datestr_from_pk( pk2 ) ); - if( pk2->expiredate ) { - printf(_(" [expires: %s]"), expirestr_from_pk( pk2 ) ); - } - putchar('\n'); - if( fpr > 1 ) - print_fingerprint( pk2, NULL, 0 ); - if( opt.with_key_data ) - print_key_data( pk2, keyid2 ); - } - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - u32 keyid2[2]; - PKT_secret_key *sk2 = node->pkt->pkt.secret_key; - - if( !any ) { - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); /* of the main key */ - any = 1; - } - - keyid_from_sk( sk2, keyid2 ); - printf("ssb %4u%c/%08lX %s\n", nbits_from_sk( sk2 ), - pubkey_letter( sk2->pubkey_algo ), - (ulong)keyid2[1], - datestr_from_sk( sk2 ) ); - if( fpr > 1 ) - print_fingerprint( NULL, sk2, 0 ); - } - else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - int sigrc; - char *sigstr; - - if( stats ) { - /*fflush(stdout);*/ - rc = check_key_signature( keyblock, node, NULL ); - switch( rc ) { - case 0: sigrc = '!'; break; - case G10ERR_BAD_SIGN: stats->inv_sigs++; sigrc = '-'; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: stats->no_key++; continue; - default: stats->oth_err++; sigrc = '%'; break; - } - - /* TODO: Make sure a cached sig record here still has - the pk that issued it. See also - keyedit.c:print_and_check_one_sig */ - - } - else { - rc = 0; - sigrc = ' '; - } - - if( !any ) { /* no user id, (maybe a revocation follows)*/ - /* Check if the pk is really revoked - there could be a - 0x20 sig packet there even if we are not revoked - (say, if a revocation key issued the packet, but the - revocation key isn't present to verify it.) */ - if( sig->sig_class == 0x20 && pk->is_revoked ) - puts("[revoked]"); - else if( sig->sig_class == 0x18 ) - puts("[key binding]"); - else if( sig->sig_class == 0x28 ) - puts("[subkey revoked]"); - else - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); - any=1; - } - - if( sig->sig_class == 0x20 || sig->sig_class == 0x28 - || sig->sig_class == 0x30 ) - sigstr = "rev"; - else if( (sig->sig_class&~3) == 0x10 ) - sigstr = "sig"; - else if( sig->sig_class == 0x18 ) - sigstr = "sig"; - else if( sig->sig_class == 0x1F ) - sigstr = "sig"; - else { - printf("sig " - "[unexpected signature class 0x%02x]\n",sig->sig_class ); - continue; - } - - fputs( sigstr, stdout ); - printf("%c%c %c%c%c%c%c %08lX %s ", - sigrc,(sig->sig_class-0x10>0 && - sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', - sig->flags.exportable?' ':'L', - sig->flags.revocable?' ':'R', - sig->flags.policy_url?'P':' ', - sig->flags.notation?'N':' ', - sig->flags.expired?'X':' ', - (ulong)sig->keyid[1], datestr_from_sig(sig)); - if( sigrc == '%' ) - printf("[%s] ", g10_errstr(rc) ); - else if( sigrc == '?' ) - ; - else if ( !opt.fast_list_mode ) { - size_t n; - char *p = get_user_id( sig->keyid, &n ); - print_utf8_string( stdout, p, n ); - m_free(p); - } - putchar('\n'); - - if(sig->flags.policy_url && opt.show_policy_url) - show_policy_url(sig,3); - - if(sig->flags.notation && opt.show_notation) - show_notation(sig,3); - - /* fixme: check or list other sigs here */ - } - } - putchar('\n'); -} - - -static void -list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) -{ - int rc = 0; - KBNODE kbctx; - KBNODE node; - PKT_public_key *pk; - PKT_secret_key *sk; - u32 keyid[2]; - int any=0; - int trustletter = 0; - int ulti_hack = 0; - - /* get the keyid from the keyblock */ - node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); - if( !node ) { - log_error("Oops; key lost!\n"); - dump_kbnode( keyblock ); - return; - } - - if( secret ) { - pk = NULL; - sk = node->pkt->pkt.secret_key; - keyid_from_sk( sk, keyid ); - printf("sec:u:%u:%d:%08lX%08lX:%s:%s:::", - nbits_from_sk( sk ), - sk->pubkey_algo, - (ulong)keyid[0],(ulong)keyid[1], - colon_datestr_from_sk( sk ), - colon_strtime (sk->expiredate) - /* fixme: add LID here */ ); - } - else { - pk = node->pkt->pkt.public_key; - sk = NULL; - keyid_from_pk( pk, keyid ); - fputs( "pub:", stdout ); - trustletter = 0; - if ( !pk->is_valid ) - putchar ('i'); - else if ( pk->is_revoked ) - putchar ('r'); - else if ( pk->has_expired ) - putchar ('e'); - else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) - ; - else { - trustletter = get_validity_info ( pk, NULL ); - if( trustletter == 'u' ) - ulti_hack = 1; - putchar(trustletter); - } - printf(":%u:%d:%08lX%08lX:%s:%s:", - nbits_from_pk( pk ), - pk->pubkey_algo, - (ulong)keyid[0],(ulong)keyid[1], - colon_datestr_from_pk( pk ), - colon_strtime (pk->expiredate) ); - if( pk->local_id ) - printf("%lu", pk->local_id ); - putchar(':'); - if( !opt.fast_list_mode && !opt.no_expensive_trust_checks ) - putchar( get_ownertrust_info(pk) ); - putchar(':'); - } - - if (opt.fixed_list_mode) { - /* do not merge the first uid with the primary key */ - putchar(':'); - putchar(':'); - print_capabilities (pk, sk, keyblock); - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); - if( opt.with_key_data ) - print_key_data( pk, keyid ); - any = 1; - } - - - for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { - if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { - if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) - dump_attribs(node->pkt->pkt.user_id,pk,sk); - /* - * Fixme: We need a is_valid flag here too - */ - if( any ) { - char *str=node->pkt->pkt.user_id->attrib_data?"uat":"uid"; - if ( node->pkt->pkt.user_id->is_revoked ) - printf("%s:r::::::::",str); - else if ( node->pkt->pkt.user_id->is_expired ) - printf("%s:e::::::::",str); - else if ( opt.no_expensive_trust_checks ) { - printf("%s:::::::::",str); - } - else { - byte namehash[20]; - - if( pk && !ulti_hack ) { - if( node->pkt->pkt.user_id->attrib_data ) - rmd160_hash_buffer( namehash, - node->pkt->pkt.user_id->attrib_data, - node->pkt->pkt.user_id->attrib_len); - else - rmd160_hash_buffer( namehash, - node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len ); - trustletter = get_validity_info( pk, namehash ); - } - else - trustletter = 'u'; - printf("%s:%c::::::::",str,trustletter); - } - } - if(node->pkt->pkt.user_id->attrib_data) - printf("%u %lu", - node->pkt->pkt.user_id->numattribs, - node->pkt->pkt.user_id->attrib_len); - else - print_string( stdout, node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len, ':' ); - putchar(':'); - if (any) - putchar('\n'); - else { - putchar(':'); - print_capabilities (pk, sk, keyblock); - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); - if( opt.with_key_data ) - print_key_data( pk, keyid ); - any = 1; - } - } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - u32 keyid2[2]; - PKT_public_key *pk2 = node->pkt->pkt.public_key; - - if( !any ) { - putchar(':'); - putchar(':'); - print_capabilities (pk, sk, keyblock); - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); /* of the main key */ - any = 1; - } - - keyid_from_pk( pk2, keyid2 ); - fputs ("sub:", stdout ); - if ( !pk2->is_valid ) - putchar ('i'); - else if ( pk2->is_revoked ) - putchar ('r'); - else if ( pk2->has_expired ) - putchar ('e'); - else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) - ; - else { - printf("%c", trustletter ); - } - printf(":%u:%d:%08lX%08lX:%s:%s:", - nbits_from_pk( pk2 ), - pk2->pubkey_algo, - (ulong)keyid2[0],(ulong)keyid2[1], - colon_datestr_from_pk( pk2 ), - colon_strtime (pk2->expiredate) - /* fixme: add LID and ownertrust here */ - ); - if( pk->local_id ) /* use the local_id of the main key??? */ - printf("%lu", pk->local_id ); - putchar(':'); - putchar(':'); - putchar(':'); - putchar(':'); - print_capabilities (pk2, NULL, NULL); - putchar('\n'); - if( fpr > 1 ) - print_fingerprint( pk2, NULL, 0 ); - if( opt.with_key_data ) - print_key_data( pk2, keyid2 ); - } - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - u32 keyid2[2]; - PKT_secret_key *sk2 = node->pkt->pkt.secret_key; - - if( !any ) { - putchar(':'); - putchar(':'); - print_capabilities (pk, sk, keyblock); - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); /* of the main key */ - any = 1; - } - - keyid_from_sk( sk2, keyid2 ); - printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::", - nbits_from_sk( sk2 ), - sk2->pubkey_algo, - (ulong)keyid2[0],(ulong)keyid2[1], - colon_datestr_from_sk( sk2 ), - colon_strtime (sk2->expiredate) - /* fixme: add LID */ ); - print_capabilities (NULL, sk2, NULL); - putchar ('\n'); - if( fpr > 1 ) - print_fingerprint( NULL, sk2, 0 ); - } - else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - int sigrc; - char *sigstr; - - if( !any ) { /* no user id, (maybe a revocation follows)*/ - if( sig->sig_class == 0x20 ) - fputs("[revoked]:", stdout); - else if( sig->sig_class == 0x18 ) - fputs("[key binding]:", stdout); - else if( sig->sig_class == 0x28 ) - fputs("[subkey revoked]:", stdout); - else - putchar (':'); - putchar(':'); - print_capabilities (pk, sk, keyblock); - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); - any=1; - } - - if( sig->sig_class == 0x20 || sig->sig_class == 0x28 - || sig->sig_class == 0x30 ) - sigstr = "rev"; - else if( (sig->sig_class&~3) == 0x10 ) - sigstr = "sig"; - else if( sig->sig_class == 0x18 ) - sigstr = "sig"; - else if( sig->sig_class == 0x1F ) - sigstr = "sig"; - else { - printf ("sig::::::::::%02x%c:\n", - sig->sig_class, sig->flags.exportable?'x':'l'); - continue; - } - if( opt.check_sigs ) { - fflush(stdout); - rc = check_key_signature( keyblock, node, NULL ); - switch( rc ) { - case 0: sigrc = '!'; break; - case G10ERR_BAD_SIGN: sigrc = '-'; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: sigrc = '?'; break; - default: sigrc = '%'; break; - } - } - else { - rc = 0; - sigrc = ' '; - } - fputs( sigstr, stdout ); - putchar(':'); - if( sigrc != ' ' ) - putchar(sigrc); - printf("::%d:%08lX%08lX:%s:%s:::", sig->pubkey_algo, - (ulong)sig->keyid[0], - (ulong)sig->keyid[1], colon_datestr_from_sig(sig), - colon_expirestr_from_sig(sig)); - if( sigrc == '%' ) - printf("[%s] ", g10_errstr(rc) ); - else if( sigrc == '?' ) - ; - else if ( !opt.fast_list_mode ) { - size_t n; - char *p = get_user_id( sig->keyid, &n ); - print_string( stdout, p, n, ':' ); - m_free(p); - } - printf(":%02x%c:\n", sig->sig_class,sig->flags.exportable?'x':'l'); - /* fixme: check or list other sigs here */ - } - } - if( !any ) {/* oops, no user id */ - putchar(':'); - putchar(':'); - print_capabilities (pk, sk, keyblock); - putchar('\n'); - } -} - -/* - * Reorder the keyblock so that the primary user ID (and not attribute - * packet) comes first. Fixme: Replace this by a generic sort - * function. */ -static void -reorder_keyblock (KBNODE keyblock) -{ - KBNODE primary = NULL, primary0 = NULL, primary2 = NULL; - KBNODE last, node; - - for (node=keyblock; node; primary0=node, node = node->next) { - if( node->pkt->pkttype == PKT_USER_ID && - !node->pkt->pkt.user_id->attrib_data && - node->pkt->pkt.user_id->is_primary ) { - primary = primary2 = node; - for (node=node->next; node; primary2=node, node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - break; - } - } - break; - } - } - if ( !primary ) - return; /* no primary key flag found (should not happen) */ - - for (last=NULL, node=keyblock; node; last = node, node = node->next) { - if( node->pkt->pkttype == PKT_USER_ID ) - break; - } - assert (node); - assert (last); /* the user ID is never the first packet */ - assert (primary0); /* ditto (this is the node before primary) */ - if ( node == primary ) - return; /* already the first one */ - - last->next = primary; - primary0->next = primary2->next; - primary2->next = node; -} - -void -list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ) -{ - reorder_keyblock (keyblock); - if (opt.with_colons) - list_keyblock_colon (keyblock, secret, fpr ); - else - list_keyblock_print (keyblock, secret, fpr, opaque ); -} - -/* - * standard function to print the finperprint. - * mode 0: as used in key listings, opt.with_colons is honored - * 1: print using log_info () - * 2: direct use of tty - * 3: direct use of tty but only primary key. - * modes 1 and 2 will try and print both subkey and primary key fingerprints - */ -void -print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) -{ - byte array[MAX_FINGERPRINT_LEN], *p; - size_t i, n; - FILE *fp; - const char *text; - int primary=0; - - if(sk) - { - if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1]) - primary=1; - } - else - { - if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1]) - primary=1; - } - - /* Just to be safe */ - if(mode&0x80 && !primary) - { - log_error("primary key is not really primary!\n"); - return; - } - - mode&=~0x80; - - if(!primary && (mode==1 || mode==2)) - { - if(sk) - { - PKT_secret_key *primary_sk=m_alloc_clear(sizeof(*primary_sk)); - get_seckey(primary_sk,sk->main_keyid); - print_fingerprint(NULL,primary_sk,mode|0x80); - free_secret_key(primary_sk); - } - else - { - PKT_public_key *primary_pk=m_alloc_clear(sizeof(*primary_pk)); - get_pubkey(primary_pk,pk->main_keyid); - print_fingerprint(primary_pk,NULL,mode|0x80); - free_public_key(primary_pk); - } - } - - if (mode == 1) { - fp = log_stream (); - if(primary) - text = _("Primary key fingerprint:"); - else - text = _(" Subkey fingerprint:"); - } - else if (mode == 2) { - fp = NULL; /* use tty */ - /* Translators: this should fit into 24 bytes to that the fingerprint - * data is properly aligned with the user ID */ - if(primary) - text = _(" Primary key fingerprint:"); - else - text = _(" Subkey fingerprint:"); - } - else if (mode == 3) { - fp = NULL; /* use tty */ - text = _(" Key fingerprint ="); - } - else { - fp = stdout; - text = _(" Key fingerprint ="); - } - - if (sk) - fingerprint_from_sk (sk, array, &n); - else - fingerprint_from_pk (pk, array, &n); - p = array; - if (opt.with_colons && !mode) { - fprintf (fp, "fpr:::::::::"); - for (i=0; i < n ; i++, p++ ) - fprintf (fp, "%02X", *p ); - putc(':', fp); - } - else { - if (fp) - fputs (text, fp); - else - tty_printf ("%s", text); - if (n == 20) { - for (i=0; i < n ; i++, i++, p += 2 ) { - if (fp) { - if (i == 10 ) - putc(' ', fp); - fprintf (fp, " %02X%02X", *p, p[1] ); - } - else { - if (i == 10 ) - tty_printf (" "); - tty_printf (" %02X%02X", *p, p[1]); - } - } - } - else { - for (i=0; i < n ; i++, p++ ) { - if (fp) { - if (i && !(i%8) ) - putc (' ', fp); - fprintf (fp, " %02X", *p ); - } - else { - if (i && !(i%8) ) - tty_printf (" "); - tty_printf (" %02X", *p ); - } - } - } - } - if (fp) - putc ('\n', fp); - else - tty_printf ("\n"); -} - -void set_attrib_fd(int fd) -{ - static int last_fd=-1; - - if ( fd != -1 && last_fd == fd ) - return; - - if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr ) - fclose (attrib_fp); - attrib_fp = NULL; - if ( fd == -1 ) - return; - - if( fd == 1 ) - attrib_fp = stdout; - else if( fd == 2 ) - attrib_fp = stderr; - else - attrib_fp = fdopen( fd, "w" ); - if( !attrib_fp ) { - log_fatal("can't open fd %d for attribute output: %s\n", - fd, strerror(errno)); - } - last_fd = fd; -} diff --git a/g10/keyring.c b/g10/keyring.c deleted file mode 100644 index 3160b1c37..000000000 --- a/g10/keyring.c +++ /dev/null @@ -1,1558 +0,0 @@ -/* keyring.c - keyring file handling - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "keyring.h" -#include "packet.h" -#include "keydb.h" -#include "options.h" -#include "main.h" /*for check_key_signature()*/ -#include "i18n.h" - -/* off_item is a funny named for an object used to keep track of known - * keys. The idea was to use the offset to seek to the known keyblock, but - * this is not possible if more than one process is using the keyring. - */ -struct off_item { - struct off_item *next; - u32 kid[2]; - /*off_t off;*/ -}; - -typedef struct off_item **OffsetHashTable; - - -typedef struct keyring_name *KR_NAME; -struct keyring_name { - struct keyring_name *next; - int secret; - DOTLOCK lockhd; - int is_locked; - int did_full_scan; - char fname[1]; -}; -typedef struct keyring_name const * CONST_KR_NAME; - -static KR_NAME kr_names; -static int active_handles; - -static OffsetHashTable kr_offtbl; -static int kr_offtbl_ready; - - -struct keyring_handle { - CONST_KR_NAME resource; - int secret; /* this is for a secret keyring */ - struct { - CONST_KR_NAME kr; - IOBUF iobuf; - int eof; - int error; - } current; - struct { - CONST_KR_NAME kr; - off_t offset; - size_t pk_no; - size_t uid_no; - unsigned int n_packets; /*used for delete and update*/ - } found; - struct { - char *name; - char *pattern; - } word_match; -}; - - - -static int do_copy (int mode, const char *fname, KBNODE root, int secret, - off_t start_offset, unsigned int n_packets ); - - - -static struct off_item * -new_offset_item (void) -{ - struct off_item *k; - - k = m_alloc_clear (sizeof *k); - return k; -} - -#if 0 -static void -release_offset_items (struct off_item *k) -{ - struct off_item *k2; - - for (; k; k = k2) - { - k2 = k->next; - m_free (k); - } -} -#endif - -static OffsetHashTable -new_offset_hash_table (void) -{ - struct off_item **tbl; - - tbl = m_alloc_clear (2048 * sizeof *tbl); - return tbl; -} - -#if 0 -static void -release_offset_hash_table (OffsetHashTable tbl) -{ - int i; - - if (!tbl) - return; - for (i=0; i < 2048; i++) - release_offset_items (tbl[i]); - m_free (tbl); -} -#endif - -static struct off_item * -lookup_offset_hash_table (OffsetHashTable tbl, u32 *kid) -{ - struct off_item *k; - - for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next) - if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) - return k; - return NULL; -} - -static void -update_offset_hash_table (OffsetHashTable tbl, u32 *kid, off_t off) -{ - struct off_item *k; - - for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next) - { - if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) - { - /*k->off = off;*/ - return; - } - } - - k = new_offset_item (); - k->kid[0] = kid[0]; - k->kid[1] = kid[1]; - /*k->off = off;*/ - k->next = tbl[(kid[1] & 0x07ff)]; - tbl[(kid[1] & 0x07ff)] = k; -} - -static void -update_offset_hash_table_from_kb (OffsetHashTable tbl, KBNODE node, off_t off) -{ - for (; node; node = node->next) - { - if (node->pkt->pkttype == PKT_PUBLIC_KEY - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) - { - u32 aki[2]; - keyid_from_pk (node->pkt->pkt.public_key, aki); - update_offset_hash_table (tbl, aki, off); - } - } -} - - - - -/* - * Register a filename for plain keyring files. Returns a pointer to - * be used to create a handles etc or NULL to indicate that it has - * already been registered */ -void * -keyring_register_filename (const char *fname, int secret) -{ - KR_NAME kr; - - if (active_handles) - BUG (); /* We don't allow that */ - - for (kr=kr_names; kr; kr = kr->next) { - if ( !compare_filenames (kr->fname, fname) ) - return NULL; /* already registered */ - } - - kr = m_alloc (sizeof *kr + strlen (fname)); - strcpy (kr->fname, fname); - kr->secret = !!secret; - kr->lockhd = NULL; - kr->is_locked = 0; - kr->did_full_scan = 0; - /* keep a list of all issued pointers */ - kr->next = kr_names; - kr_names = kr; - - /* create the offset table the first time a function here is used */ - if (!kr_offtbl) - kr_offtbl = new_offset_hash_table (); - - return kr; -} - -int -keyring_is_writable (void *token) -{ - KR_NAME r = token; - - return r? !access (r->fname, W_OK) : 0; -} - - - -/* Create a new handle for the resource associated with TOKEN. SECRET - is just just as a cross-check. - - The returned handle must be released using keyring_release (). */ -KEYRING_HANDLE -keyring_new (void *token, int secret) -{ - KEYRING_HANDLE hd; - KR_NAME resource = token; - - assert (resource && !resource->secret == !secret); - - hd = m_alloc_clear (sizeof *hd); - hd->resource = resource; - hd->secret = !!secret; - active_handles++; - return hd; -} - -void -keyring_release (KEYRING_HANDLE hd) -{ - if (!hd) - return; - assert (active_handles > 0); - active_handles--; - m_free (hd->word_match.name); - m_free (hd->word_match.pattern); - iobuf_close (hd->current.iobuf); - m_free (hd); -} - - -const char * -keyring_get_resource_name (KEYRING_HANDLE hd) -{ - if (!hd || !hd->resource) - return NULL; - return hd->resource->fname; -} - - -/* - * Lock the keyring with the given handle, or unlok if yes is false. - * We ignore the handle and lock all registered files. - */ -int -keyring_lock (KEYRING_HANDLE hd, int yes) -{ - KR_NAME kr; - int rc = 0; - - if (yes) { - /* first make sure the lock handles are created */ - for (kr=kr_names; kr; kr = kr->next) { - if (!keyring_is_writable(kr)) - continue; - if (!kr->lockhd) { - kr->lockhd = create_dotlock( kr->fname ); - if (!kr->lockhd) { - log_info ("can't allocate lock for `%s'\n", kr->fname ); - rc = G10ERR_GENERAL; - } - } - } - if (rc) - return rc; - - /* and now set the locks */ - for (kr=kr_names; kr; kr = kr->next) { - if (!keyring_is_writable(kr)) - continue; - if (kr->is_locked) - ; - else if (make_dotlock (kr->lockhd, -1) ) { - log_info ("can't lock `%s'\n", kr->fname ); - rc = G10ERR_GENERAL; - } - else - kr->is_locked = 1; - } - } - - if (rc || !yes) { - for (kr=kr_names; kr; kr = kr->next) { - if (!keyring_is_writable(kr)) - continue; - if (!kr->is_locked) - ; - else if (release_dotlock (kr->lockhd)) - log_info ("can't unlock `%s'\n", kr->fname ); - else - kr->is_locked = 0; - } - } - - return rc; -} - - - -/* - * 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 -keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) -{ - PACKET *pkt; - int rc; - KBNODE keyblock = NULL, node, lastnode; - IOBUF a; - int in_cert = 0; - int pk_no = 0; - int uid_no = 0; - int save_mode; - - if (ret_kb) - *ret_kb = NULL; - - if (!hd->found.kr) - return -1; /* no successful search */ - - a = iobuf_open (hd->found.kr->fname); - if (!a) { - log_error ("can't open `%s'\n", hd->found.kr->fname); - return G10ERR_KEYRING_OPEN; - } - - if (iobuf_seek (a, hd->found.offset) ) { - log_error ("can't seek `%s'\n", hd->found.kr->fname); - iobuf_close(a); - return G10ERR_KEYRING_OPEN; - } - - pkt = m_alloc (sizeof *pkt); - init_packet (pkt); - hd->found.n_packets = 0;; - lastnode = NULL; - save_mode = set_packet_list_mode(0); - while ((rc=parse_packet (a, pkt)) != -1) { - hd->found.n_packets++; - if (rc == G10ERR_UNKNOWN_PACKET) { - free_packet (pkt); - init_packet (pkt); - continue; - } - if (rc) { - log_error ("keyring_get_keyblock: read error: %s\n", - g10_errstr(rc) ); - rc = G10ERR_INV_KEYRING; - break; - } - if (pkt->pkttype == PKT_COMPRESSED) { - log_error ("skipped compressed packet in keyring\n"); - free_packet(pkt); - init_packet(pkt); - continue; - } - - if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY - || pkt->pkttype == PKT_SECRET_KEY)) { - hd->found.n_packets--; /* fix counter */ - break; /* ready */ - } - - in_cert = 1; - if (pkt->pkttype == PKT_RING_TRUST) { - /*(this code is duplicated after the loop)*/ - if ( lastnode - && lastnode->pkt->pkttype == PKT_SIGNATURE - && (pkt->pkt.ring_trust->sigcache & 1) ) { - /* this is a ring trust packet with a checked signature - * status cache following directly a signature paket. - * Set the cache status into that signature packet */ - PKT_signature *sig = lastnode->pkt->pkt.signature; - - sig->flags.checked = 1; - sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); - } - /* reset lastnode, so that we set the cache status only from - * the ring trust packet immediately folling a signature */ - lastnode = NULL; - } - else { - node = lastnode = new_kbnode (pkt); - if (!keyblock) - keyblock = node; - else - add_kbnode (keyblock, node); - - if ( pkt->pkttype == PKT_PUBLIC_KEY - || pkt->pkttype == PKT_PUBLIC_SUBKEY - || pkt->pkttype == PKT_SECRET_KEY - || pkt->pkttype == PKT_SECRET_SUBKEY) { - if (++pk_no == hd->found.pk_no) - node->flag |= 1; - } - else if ( pkt->pkttype == PKT_USER_ID) { - if (++uid_no == hd->found.uid_no) - node->flag |= 2; - } - } - - pkt = m_alloc (sizeof *pkt); - init_packet(pkt); - } - set_packet_list_mode(save_mode); - - if (rc == -1 && keyblock) - rc = 0; /* got the entire keyblock */ - - if (rc || !ret_kb) - release_kbnode (keyblock); - else { - /*(duplicated form the loop body)*/ - if ( pkt && pkt->pkttype == PKT_RING_TRUST - && lastnode - && lastnode->pkt->pkttype == PKT_SIGNATURE - && (pkt->pkt.ring_trust->sigcache & 1) ) { - PKT_signature *sig = lastnode->pkt->pkt.signature; - sig->flags.checked = 1; - sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); - } - *ret_kb = keyblock; - } - free_packet (pkt); - m_free (pkt); - iobuf_close(a); - - /* Make sure that future search operations fail immediately when - * we know that we are working on a invalid keyring - */ - if (rc == G10ERR_INV_KEYRING) - hd->current.error = rc; - - return rc; -} - -int -keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb) -{ - int rc; - - if (!hd->found.kr) - return -1; /* no successful prior search */ - - if (!hd->found.n_packets) { - /* need to know the number of packets - do a dummy get_keyblock*/ - rc = keyring_get_keyblock (hd, NULL); - if (rc) { - log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); - return rc; - } - if (!hd->found.n_packets) - BUG (); - } - - /* The open iobuf isn't needed anymore and in fact is a problem when - it comes to renaming the keyring files on some operating systems, - so close it here */ - iobuf_close(hd->current.iobuf); - hd->current.iobuf = NULL; - - /* do the update */ - rc = do_copy (3, hd->found.kr->fname, kb, hd->secret, - hd->found.offset, hd->found.n_packets ); - if (!rc) { - if (!hd->secret && kr_offtbl) - { - update_offset_hash_table_from_kb (kr_offtbl, kb, 0); - } - /* better reset the found info */ - hd->found.kr = NULL; - hd->found.offset = 0; - } - return rc; -} - -int -keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) -{ - int rc; - const char *fname; - - if (!hd) - fname = NULL; - else if (hd->found.kr) - fname = hd->found.kr->fname; - else if (hd->current.kr) - fname = hd->current.kr->fname; - else - fname = hd->resource? hd->resource->fname:NULL; - - if (!fname) - return G10ERR_GENERAL; - - /* close this one otherwise we will lose the position for - * a next search. Fixme: it would be better to adjust the position - * after the write opertions. - */ - iobuf_close (hd->current.iobuf); - hd->current.iobuf = NULL; - - /* do the insert */ - rc = do_copy (1, fname, kb, hd->secret, 0, 0 ); - if (!rc && !hd->secret && kr_offtbl) - { - update_offset_hash_table_from_kb (kr_offtbl, kb, 0); - } - - return rc; -} - - -int -keyring_delete_keyblock (KEYRING_HANDLE hd) -{ - int rc; - - if (!hd->found.kr) - return -1; /* no successful prior search */ - - if (!hd->found.n_packets) { - /* need to know the number of packets - do a dummy get_keyblock*/ - rc = keyring_get_keyblock (hd, NULL); - if (rc) { - log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); - return rc; - } - if (!hd->found.n_packets) - BUG (); - } - - /* close this one otherwise we will lose the position for - * a next search. Fixme: it would be better to adjust the position - * after the write opertions. - */ - iobuf_close (hd->current.iobuf); - hd->current.iobuf = NULL; - - /* do the delete */ - rc = do_copy (2, hd->found.kr->fname, NULL, hd->secret, - hd->found.offset, hd->found.n_packets ); - if (!rc) { - /* better reset the found info */ - hd->found.kr = NULL; - hd->found.offset = 0; - /* Delete is a rare operations, so we don't remove the keys - * from the offset table */ - } - return rc; -} - - - -/* - * Start the next search on this handle right at the beginning - */ -int -keyring_search_reset (KEYRING_HANDLE hd) -{ - assert (hd); - - hd->current.kr = NULL; - iobuf_close (hd->current.iobuf); - hd->current.iobuf = NULL; - hd->current.eof = 0; - hd->current.error = 0; - - hd->found.kr = NULL; - hd->found.offset = 0; - return 0; -} - - -static int -prepare_search (KEYRING_HANDLE hd) -{ - if (hd->current.error) - return hd->current.error; /* still in error state */ - - if (hd->current.kr && !hd->current.eof) { - if ( !hd->current.iobuf ) - return G10ERR_GENERAL; /* position invalid after a modify */ - return 0; /* okay */ - } - - if (!hd->current.kr && hd->current.eof) - return -1; /* still EOF */ - - if (!hd->current.kr) { /* start search with first keyring */ - hd->current.kr = hd->resource; - if (!hd->current.kr) { - hd->current.eof = 1; - return -1; /* keyring not available */ - } - assert (!hd->current.iobuf); - } - else { /* EOF */ - iobuf_close (hd->current.iobuf); - hd->current.iobuf = NULL; - hd->current.kr = NULL; - hd->current.eof = 1; - return -1; - } - - hd->current.eof = 0; - hd->current.iobuf = iobuf_open (hd->current.kr->fname); - if (!hd->current.iobuf) { - log_error ("can't open `%s'\n", hd->current.kr->fname ); - return (hd->current.error = G10ERR_OPEN_FILE); - } - - return 0; -} - - -/* A map of the all characters valid used for word_match() - * Valid characters are in in this table converted to uppercase. - * because the upper 128 bytes have special meaning, we assume - * that they are all valid. - * Note: We must use numerical values here in case that this program - * will be converted to those little blue HAL9000s with their strange - * EBCDIC character set (user ids are UTF-8). - * wk 2000-04-13: Hmmm, does this really make sense, given the fact that - * we can run gpg now on a S/390 running GNU/Linux, where the code - * translation is done by the device drivers? - */ -static const byte word_match_chars[256] = { - /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - /* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 40 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - /* 48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - /* 58 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 60 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - /* 68 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - /* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - /* 78 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - /* 88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - /* 90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - /* 98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - /* a0 */ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - /* a8 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - /* b0 */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - /* b8 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - /* c0 */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - /* c8 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - /* d0 */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - /* d8 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - /* e0 */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - /* e8 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - /* f0 */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - /* f8 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -/**************** - * Do a word match (original user id starts with a '+'). - * The pattern is already tokenized to a more suitable format: - * There are only the real words in it delimited by one space - * and all converted to uppercase. - * - * Returns: 0 if all words match. - * - * Note: This algorithm is a straightforward one and not very - * fast. It works for UTF-8 strings. The uidlen should - * be removed but due to the fact that old versions of - * pgp don't use UTF-8 we still use the length; this should - * be fixed in parse-packet (and replace \0 by some special - * UTF-8 encoding) - */ -static int -word_match( const byte *uid, size_t uidlen, const byte *pattern ) -{ - size_t wlen, n; - const byte *p; - const byte *s; - - for( s=pattern; *s; ) { - do { - /* skip leading delimiters */ - while( uidlen && !word_match_chars[*uid] ) - uid++, uidlen--; - /* get length of the word */ - n = uidlen; p = uid; - while( n && word_match_chars[*p] ) - p++, n--; - wlen = p - uid; - /* and compare against the current word from pattern */ - for(n=0, p=uid; n < wlen && s[n] != ' ' && s[n] ; n++, p++ ) { - if( word_match_chars[*p] != s[n] ) - break; - } - if( n == wlen && (s[n] == ' ' || !s[n]) ) - break; /* found */ - uid += wlen; - uidlen -= wlen; - } while( uidlen ); - if( !uidlen ) - return -1; /* not found */ - - /* advance to next word in pattern */ - for(; *s != ' ' && *s ; s++ ) - ; - if( *s ) - s++ ; - } - return 0; /* found */ -} - -/**************** - * prepare word word_match; that is parse the name and - * build the pattern. - * caller has to free the returned pattern - */ -static char* -prepare_word_match (const byte *name) -{ - byte *pattern, *p; - int c; - - /* the original length is always enough for the pattern */ - p = pattern = m_alloc(strlen(name)+1); - do { - /* skip leading delimiters */ - while( *name && !word_match_chars[*name] ) - name++; - /* copy as long as we don't have a delimiter and convert - * to uppercase. - * fixme: how can we handle utf8 uppercasing */ - for( ; *name && (c=word_match_chars[*name]); name++ ) - *p++ = c; - *p++ = ' '; /* append pattern delimiter */ - } while( *name ); - p[-1] = 0; /* replace last pattern delimiter by EOS */ - - return pattern; -} - - - - -static int -compare_name (int mode, const char *name, const char *uid, size_t uidlen) -{ - int i; - const char *s, *se; - - if (mode == KEYDB_SEARCH_MODE_EXACT) { - for (i=0; name[i] && uidlen; i++, uidlen--) - if (uid[i] != name[i]) - break; - if (!uidlen && !name[i]) - return 0; /* found */ - } - else if (mode == KEYDB_SEARCH_MODE_SUBSTR) { - if (ascii_memistr( uid, uidlen, name )) - return 0; - } - else if ( mode == KEYDB_SEARCH_MODE_MAIL - || mode == KEYDB_SEARCH_MODE_MAILSUB - || mode == KEYDB_SEARCH_MODE_MAILEND) { - for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++) - ; - if (i < uidlen) { - /* skip opening delim and one char and look for the closing one*/ - s++; i++; - for (se=s+1, i++; i < uidlen && *se != '>'; se++, i++) - ; - if (i < uidlen) { - i = se - s; - if (mode == KEYDB_SEARCH_MODE_MAIL) { - if( strlen(name)-2 == i - && !ascii_memcasecmp( s, name+1, i) ) - return 0; - } - else if (mode == KEYDB_SEARCH_MODE_MAILSUB) { - if( ascii_memistr( s, i, name ) ) - return 0; - } - else { /* email from end */ - /* nyi */ - } - } - } - } - else if (mode == KEYDB_SEARCH_MODE_WORDS) - return word_match (uid, uidlen, name); - else - BUG(); - - return -1; /* not found */ -} - - -/* - * Search through the keyring(s), starting at the current position, - * for a keyblock which contains one of the keys described in the DESC array. - */ -int -keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) -{ - int rc; - PACKET pkt; - int save_mode; - off_t offset, main_offset; - size_t n; - int need_uid, need_words, need_keyid, need_fpr, any_skip; - int pk_no, uid_no; - int initial_skip; - int use_offtbl; - PKT_user_id *uid = NULL; - PKT_public_key *pk = NULL; - PKT_secret_key *sk = NULL; - - /* figure out what information we need */ - need_uid = need_words = need_keyid = need_fpr = any_skip = 0; - for (n=0; n < ndesc; n++) - { - switch (desc[n].mode) - { - case KEYDB_SEARCH_MODE_EXACT: - case KEYDB_SEARCH_MODE_SUBSTR: - case KEYDB_SEARCH_MODE_MAIL: - case KEYDB_SEARCH_MODE_MAILSUB: - case KEYDB_SEARCH_MODE_MAILEND: - need_uid = 1; - break; - case KEYDB_SEARCH_MODE_WORDS: - need_uid = 1; - need_words = 1; - break; - case KEYDB_SEARCH_MODE_SHORT_KID: - case KEYDB_SEARCH_MODE_LONG_KID: - need_keyid = 1; - break; - case KEYDB_SEARCH_MODE_FPR16: - case KEYDB_SEARCH_MODE_FPR20: - case KEYDB_SEARCH_MODE_FPR: - need_fpr = 1; - break; - case KEYDB_SEARCH_MODE_FIRST: - /* always restart the search in this mode */ - keyring_search_reset (hd); - break; - default: break; - } - if (desc[n].skipfnc) - { - any_skip = 1; - need_keyid = 1; - } - } - - rc = prepare_search (hd); - if (rc) - return rc; - - use_offtbl = !hd->secret && kr_offtbl; - if (!use_offtbl) - ; - else if (!kr_offtbl_ready) - need_keyid = 1; - else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID) - { - struct off_item *oi; - - oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid); - if (!oi) - { /* We know that we don't have this key */ - hd->found.kr = NULL; - hd->current.eof = 1; - return -1; - } - /* We could now create a positive search status and return. - * However the problem is that another instance of gpg may - * have changed the keyring so that the offsets are not valid - * anymore - therefore we don't do it - */ - } - - if (need_words) - { - const char *name = NULL; - - log_debug ("word search mode does not yet work\n"); - /* FIXME: here is a long standing bug in our function and in addition we - just use the first search description */ - for (n=0; n < ndesc && !name; n++) - { - if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS) - name = desc[n].u.name; - } - assert (name); - if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) - { - /* name changed */ - m_free (hd->word_match.name); - m_free (hd->word_match.pattern); - hd->word_match.name = m_strdup (name); - hd->word_match.pattern = prepare_word_match (name); - } - name = hd->word_match.pattern; - } - - init_packet(&pkt); - save_mode = set_packet_list_mode(0); - - hd->found.kr = NULL; - main_offset = 0; - pk_no = uid_no = 0; - initial_skip = 1; /* skip until we see the start of a keyblock */ - while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid))) - { - byte afp[MAX_FINGERPRINT_LEN]; - size_t an; - u32 aki[2]; - - if (pkt.pkttype == PKT_PUBLIC_KEY || pkt.pkttype == PKT_SECRET_KEY) - { - main_offset = offset; - pk_no = uid_no = 0; - initial_skip = 0; - } - if (initial_skip) - { - free_packet (&pkt); - continue; - } - - pk = NULL; - sk = NULL; - uid = NULL; - if ( pkt.pkttype == PKT_PUBLIC_KEY - || pkt.pkttype == PKT_PUBLIC_SUBKEY) - { - pk = pkt.pkt.public_key; - ++pk_no; - - if (need_fpr) { - fingerprint_from_pk (pk, afp, &an); - while (an < 20) /* fill up to 20 bytes */ - afp[an++] = 0; - } - if (need_keyid) - keyid_from_pk (pk, aki); - - if (use_offtbl && !kr_offtbl_ready) - update_offset_hash_table (kr_offtbl, aki, main_offset); - } - else if (pkt.pkttype == PKT_USER_ID) - { - uid = pkt.pkt.user_id; - ++uid_no; - } - else if ( pkt.pkttype == PKT_SECRET_KEY - || pkt.pkttype == PKT_SECRET_SUBKEY) - { - sk = pkt.pkt.secret_key; - ++pk_no; - - if (need_fpr) { - fingerprint_from_sk (sk, afp, &an); - while (an < 20) /* fill up to 20 bytes */ - afp[an++] = 0; - } - if (need_keyid) - keyid_from_sk (sk, aki); - - } - - for (n=0; n < ndesc; n++) - { - switch (desc[n].mode) { - case KEYDB_SEARCH_MODE_NONE: - BUG (); - break; - case KEYDB_SEARCH_MODE_EXACT: - case KEYDB_SEARCH_MODE_SUBSTR: - case KEYDB_SEARCH_MODE_MAIL: - case KEYDB_SEARCH_MODE_MAILSUB: - case KEYDB_SEARCH_MODE_MAILEND: - case KEYDB_SEARCH_MODE_WORDS: - if ( uid && !compare_name (desc[n].mode, - desc[n].u.name, - uid->name, uid->len)) - goto found; - break; - - case KEYDB_SEARCH_MODE_SHORT_KID: - if ((pk||sk) && desc[n].u.kid[1] == aki[1]) - goto found; - break; - case KEYDB_SEARCH_MODE_LONG_KID: - if ((pk||sk) && desc[n].u.kid[0] == aki[0] - && desc[n].u.kid[1] == aki[1]) - goto found; - break; - case KEYDB_SEARCH_MODE_FPR16: - if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 16)) - goto found; - break; - case KEYDB_SEARCH_MODE_FPR20: - case KEYDB_SEARCH_MODE_FPR: - if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20)) - goto found; - break; - case KEYDB_SEARCH_MODE_FIRST: - if (pk||sk) - goto found; - break; - case KEYDB_SEARCH_MODE_NEXT: - if (pk||sk) - goto found; - break; - default: - rc = G10ERR_INV_ARG; - goto found; - } - } - free_packet (&pkt); - continue; - found: - for (n=any_skip?0:ndesc; n < ndesc; n++) - { - if (desc[n].skipfnc - && desc[n].skipfnc (desc[n].skipfncvalue, aki)) - break; - } - if (n == ndesc) - goto real_found; - free_packet (&pkt); - } - real_found: - if (!rc) - { - hd->found.offset = main_offset; - hd->found.kr = hd->current.kr; - hd->found.pk_no = (pk||sk)? pk_no : 0; - hd->found.uid_no = uid? uid_no : 0; - } - else if (rc == -1) - { - hd->current.eof = 1; - /* if we scanned all keyrings, we are sure that - * all known key IDs are in our offtbl, mark that. */ - if (use_offtbl && !kr_offtbl_ready) - { - KR_NAME kr; - - /* First set the did_full_scan flag for this keyring (ignore - secret keyrings) */ - for (kr=kr_names; kr; kr = kr->next) - { - if (!kr->secret && hd->resource == kr) - { - kr->did_full_scan = 1; - break; - } - } - /* Then check whether all flags are set and if so, mark the - offtbl ready */ - for (kr=kr_names; kr; kr = kr->next) - { - if (!kr->secret && !kr->did_full_scan) - break; - } - if (!kr) - kr_offtbl_ready = 1; - } - } - else - hd->current.error = rc; - - free_packet(&pkt); - set_packet_list_mode(save_mode); - return rc; -} - - -static int -create_tmp_file (const char *template, - char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) -{ - char *bakfname, *tmpfname; - mode_t oldmask; - - *r_bakfname = NULL; - *r_tmpfname = NULL; - -# ifdef USE_ONLY_8DOT3 - /* Here is another Windoze bug?: - * you cant rename("pubring.gpg.tmp", "pubring.gpg"); - * but rename("pubring.gpg.tmp", "pubring.aaa"); - * works. So we replace .gpg by .bak or .tmp - */ - if (strlen (template) > 4 - && !strcmp (template+strlen(template)-4, EXTSEP_S "gpg") ) - { - bakfname = m_alloc (strlen (template) + 1); - strcpy (bakfname, template); - strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak"); - - tmpfname = m_alloc (strlen( template ) + 1 ); - strcpy (tmpfname,template); - strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp"); - } - else - { /* file does not end with gpg; hmmm */ - bakfname = m_alloc (strlen( template ) + 5); - strcpy (stpcpy(bakfname, template), EXTSEP_S "bak"); - - tmpfname = m_alloc (strlen( template ) + 5); - strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp"); - } -# else /* Posix file names */ - bakfname = m_alloc (strlen( template ) + 2); - strcpy (stpcpy (bakfname,template),"~"); - - tmpfname = m_alloc (strlen( template ) + 5); - strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp"); -# endif /* Posix filename */ - - /* Create the temp file with limited access */ - oldmask=umask(077); - *r_fp = iobuf_create (tmpfname); - umask(oldmask); - if (!*r_fp) { - log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) ); - m_free (tmpfname); - m_free (bakfname); - return G10ERR_OPEN_FILE; - } - - *r_bakfname = bakfname; - *r_tmpfname = tmpfname; - return 0; -} - - -static int -rename_tmp_file (const char *bakfname, const char *tmpfname, - const char *fname, int secret ) -{ - int rc=0; - - /* invalidate close caches*/ - iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); - iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); - iobuf_ioctl (NULL, 2, 0, (char*)fname ); - - /* first make a backup file except for secret keyrings */ - if (!secret) - { -#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - remove (bakfname); -#endif - if (rename (fname, bakfname) ) - { - log_error ("renaming `%s' to `%s' failed: %s\n", - fname, bakfname, strerror(errno) ); - return G10ERR_RENAME_FILE; - } - } - - /* then rename the file */ -#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - remove( fname ); -#endif - if (rename (tmpfname, fname) ) - { - log_error ("renaming `%s' to `%s' failed: %s\n", - tmpfname, fname, strerror(errno) ); - rc = G10ERR_RENAME_FILE; - if (secret) - { - log_info(_("WARNING: 2 files with confidential" - " information exists.\n")); - log_info(_("%s is the unchanged one\n"), fname ); - log_info(_("%s is the new one\n"), tmpfname ); - log_info(_("Please fix this possible security flaw\n")); - } - return rc; - } - - /* Now make sure the file has the same permissions as the original */ - -#ifndef HAVE_DOSISH_SYSTEM - { - struct stat statbuf; - - statbuf.st_mode=S_IRUSR | S_IWUSR; - - if(((secret && !opt.preserve_permissions) || - (stat(bakfname,&statbuf)==0)) && - (chmod(fname,statbuf.st_mode)==0)) - ; - else - log_error("WARNING: unable to restore permissions to `%s': %s", - fname,strerror(errno)); - } -#endif - - return 0; -} - - -static int -write_keyblock (IOBUF fp, KBNODE keyblock) -{ - KBNODE kbctx = NULL, node; - int rc; - - while ( (node = walk_kbnode (keyblock, &kbctx, 0)) ) - { - if (node->pkt->pkttype == PKT_RING_TRUST) - continue; /* we write it later on our own */ - - if ( (rc = build_packet (fp, node->pkt) )) - { - log_error ("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - return rc; - } - if (node->pkt->pkttype == PKT_SIGNATURE) - { /* always write a signature cache packet */ - PKT_signature *sig = node->pkt->pkt.signature; - unsigned int cacheval = 0; - - if (sig->flags.checked) - { - cacheval |= 1; - if (sig->flags.valid) - cacheval |= 2; - } - iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/ - iobuf_put (fp, 2); /* 2 bytes */ - iobuf_put (fp, 0); /* unused */ - if (iobuf_put (fp, cacheval)) { - log_error ("writing sigcache packet failed\n"); - return G10ERR_WRITE_FILE; - } - } - } - return 0; -} - -/* - * Walk over all public keyrings, check the signatures and replace the - * keyring with a new one where the signature cache is then updated. - * This is only done for the public keyrings. - */ -int -keyring_rebuild_cache (void *token) -{ - KEYRING_HANDLE hd; - KEYDB_SEARCH_DESC desc; - KBNODE keyblock = NULL, node; - const char *lastresname = NULL, *resname; - IOBUF tmpfp = NULL; - char *tmpfilename = NULL; - char *bakfilename = NULL; - int rc; - ulong count = 0, sigcount = 0; - - hd = keyring_new (token, 0); - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - - while ( !(rc = keyring_search (hd, &desc, 1)) ) - { - desc.mode = KEYDB_SEARCH_MODE_NEXT; - resname = keyring_get_resource_name (hd); - if (lastresname != resname ) - { /* we have switched to a new keyring - commit changes */ - if (tmpfp) - { - if (iobuf_close (tmpfp)) - { - log_error ("error closing `%s': %s\n", - tmpfilename, strerror (errno)); - rc = G10ERR_CLOSE_FILE; - goto leave; - } - /* because we have switched resources, we can be sure that - * the original file is closed */ - tmpfp = NULL; - } - rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, - lastresname, 0) : 0; - m_free (tmpfilename); tmpfilename = NULL; - m_free (bakfilename); bakfilename = NULL; - if (rc) - goto leave; - lastresname = resname; - if (!opt.quiet) - log_info (_("checking keyring `%s'\n"), resname); - rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp); - if (rc) - goto leave; - } - - release_kbnode (keyblock); - rc = keyring_get_keyblock (hd, &keyblock); - if (rc) - { - log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc)); - goto leave; - } - assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY); - - /* check all signature to set the signature's cache flags */ - for (node=keyblock; node; node=node->next) - { - if (node->pkt->pkttype == PKT_SIGNATURE) - { - check_key_signature (keyblock, node, NULL); - sigcount++; - } - } - - /* write the keyblock to the temporary file */ - rc = write_keyblock (tmpfp, keyblock); - if (rc) - goto leave; - - if ( !(++count % 50) && !opt.quiet) - log_info(_("%lu keys checked so far (%lu signatures)\n"), - count, sigcount ); - - } /* end main loop */ - if (rc == -1) - rc = 0; - if (rc) - { - log_error ("keyring_search failed: %s\n", g10_errstr(rc)); - goto leave; - } - log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount ); - if (tmpfp) - { - if (iobuf_close (tmpfp)) - { - log_error ("error closing `%s': %s\n", - tmpfilename, strerror (errno)); - rc = G10ERR_CLOSE_FILE; - goto leave; - } - /* because we have switched resources, we can be sure that - * the original file is closed */ - tmpfp = NULL; - } - rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, - lastresname, 0) : 0; - m_free (tmpfilename); tmpfilename = NULL; - m_free (bakfilename); bakfilename = NULL; - - leave: - if (tmpfp) - iobuf_cancel (tmpfp); - m_free (tmpfilename); - m_free (bakfilename); - release_kbnode (keyblock); - keyring_release (hd); - return rc; -} - - -/**************** - * Perform insert/delete/update operation. - * mode 1 = insert - * 2 = delete - * 3 = update - */ -static int -do_copy (int mode, const char *fname, KBNODE root, int secret, - off_t start_offset, unsigned int n_packets ) -{ - IOBUF fp, newfp; - int rc=0; - char *bakfname = NULL; - char *tmpfname = NULL; - - /* Open the source file. Because we do a rname, we have to check the - permissions of the file */ - if (access (fname, W_OK)) - return G10ERR_WRITE_FILE; - - fp = iobuf_open (fname); - if (mode == 1 && !fp && errno == ENOENT) { - /* insert mode but file does not exist: create a new file */ - KBNODE kbctx, node; - mode_t oldmask; - - oldmask=umask(077); - newfp = iobuf_create (fname); - umask(oldmask); - if( !newfp ) { - log_error (_("%s: can't create: %s\n"), - fname, strerror(errno)); - return G10ERR_OPEN_FILE; - } - if( !opt.quiet ) - log_info(_("%s: keyring created\n"), fname ); - - kbctx=NULL; - while ( (node = walk_kbnode( root, &kbctx, 0 )) ) { - if( (rc = build_packet( newfp, node->pkt )) ) { - log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - iobuf_cancel(newfp); - return G10ERR_WRITE_FILE; - } - } - if( iobuf_close(newfp) ) { - log_error ("%s: close failed: %s\n", fname, strerror(errno)); - return G10ERR_CLOSE_FILE; - } - return 0; /* ready */ - } - - if( !fp ) { - log_error ("%s: can't open: %s\n", fname, strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; - } - - /* create the new file */ - rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); - if (rc) { - iobuf_close(fp); - goto leave; - } - if( mode == 1 ) { /* insert */ - /* copy everything to the new file */ - rc = copy_all_packets (fp, newfp); - if( rc != -1 ) { - log_error("%s: copy to `%s' failed: %s\n", - fname, tmpfname, g10_errstr(rc) ); - iobuf_close(fp); - iobuf_cancel(newfp); - goto leave; - } - rc = 0; - } - - if( mode == 2 || mode == 3 ) { /* delete or update */ - /* copy first part to the new file */ - rc = copy_some_packets( fp, newfp, start_offset ); - if( rc ) { /* should never get EOF here */ - log_error ("%s: copy to `%s' failed: %s\n", - fname, tmpfname, g10_errstr(rc) ); - iobuf_close(fp); - iobuf_cancel(newfp); - goto leave; - } - /* skip this keyblock */ - assert( n_packets ); - rc = skip_some_packets( fp, n_packets ); - if( rc ) { - log_error("%s: skipping %u packets failed: %s\n", - fname, n_packets, g10_errstr(rc)); - iobuf_close(fp); - iobuf_cancel(newfp); - goto leave; - } - } - - if( mode == 1 || mode == 3 ) { /* insert or update */ - rc = write_keyblock (newfp, root); - if (rc) { - iobuf_close(fp); - iobuf_cancel(newfp); - goto leave; - } - } - - if( mode == 2 || mode == 3 ) { /* delete or update */ - /* copy the rest */ - rc = copy_all_packets( fp, newfp ); - if( rc != -1 ) { - log_error("%s: copy to `%s' failed: %s\n", - fname, tmpfname, g10_errstr(rc) ); - iobuf_close(fp); - iobuf_cancel(newfp); - goto leave; - } - rc = 0; - } - - /* close both files */ - if( iobuf_close(fp) ) { - log_error("%s: close failed: %s\n", fname, strerror(errno) ); - rc = G10ERR_CLOSE_FILE; - goto leave; - } - if( iobuf_close(newfp) ) { - log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); - rc = G10ERR_CLOSE_FILE; - goto leave; - } - - rc = rename_tmp_file (bakfname, tmpfname, fname, secret); - - leave: - m_free(bakfname); - m_free(tmpfname); - return rc; -} diff --git a/g10/keyring.h b/g10/keyring.h deleted file mode 100644 index cb8e404a4..000000000 --- a/g10/keyring.h +++ /dev/null @@ -1,45 +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; - -void *keyring_register_filename (const char *fname, int secret); -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); -int keyring_rebuild_cache (void *); - -#endif /*GPG_KEYRING_H*/ diff --git a/g10/keyserver.c b/g10/keyserver.c deleted file mode 100644 index 59d67e32d..000000000 --- a/g10/keyserver.c +++ /dev/null @@ -1,1264 +0,0 @@ -/* keyserver.c - generic keyserver code - * 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 -#include -#include -#include -#include -#include -#include "filter.h" -#include "keydb.h" -#include "status.h" -#include "exec.h" -#include "main.h" -#include "i18n.h" -#include "iobuf.h" -#include "memory.h" -#include "ttyio.h" -#include "options.h" -#include "packet.h" -#include "keyserver-internal.h" -#include "util.h" - -#define GET 0 -#define SEND 1 -#define SEARCH 2 - -struct keyrec -{ - KEYDB_SEARCH_DESC desc; - time_t createtime,expiretime; - int size,flags; - byte type; - IOBUF uidbuf; - int lines; -}; - -struct kopts -{ - char *name; - int tell; /* tell remote process about this one */ - int *flag; -} keyserver_opts[]= -{ - {"include-revoked",1,&opt.keyserver_options.include_revoked}, - {"include-disabled",1,&opt.keyserver_options.include_disabled}, - {"include-subkeys",1,&opt.keyserver_options.include_subkeys}, - {"keep-temp-files",0,&opt.keyserver_options.keep_temp_files}, - {"honor-http-proxy",1,&opt.keyserver_options.honor_http_proxy}, - {"broken-http-proxy",1,&opt.keyserver_options.broken_http_proxy}, - {"refresh-add-fake-v3-keyids",0,&opt.keyserver_options.fake_v3_keyids}, - {"auto-key-retrieve",0,&opt.keyserver_options.auto_key_retrieve}, - {NULL} -}; - -static int keyserver_work(int action,STRLIST list, - KEYDB_SEARCH_DESC *desc,int count); - -void -parse_keyserver_options(char *options) -{ - char *tok; - - while((tok=strsep(&options," ,"))) - { - int i,hit=0; - - if(tok[0]=='\0') - continue; - - for(i=0;keyserver_opts[i].name;i++) - { - if(ascii_strcasecmp(tok,keyserver_opts[i].name)==0) - { - *(keyserver_opts[i].flag)=1; - hit=1; - break; - } - else if(ascii_strncasecmp("no-",tok,3)==0 && - ascii_strcasecmp(&tok[3],keyserver_opts[i].name)==0) - { - *(keyserver_opts[i].flag)=0; - hit=1; - break; - } - } - - /* These options need more than just a flag */ - if(!hit) - { - if(ascii_strcasecmp(tok,"verbose")==0) - opt.keyserver_options.verbose++; - else if(ascii_strcasecmp(tok,"no-verbose")==0) - opt.keyserver_options.verbose--; -#ifdef EXEC_TEMPFILE_ONLY - else if(ascii_strcasecmp(tok,"use-temp-files")==0 || - ascii_strcasecmp(tok,"no-use-temp-files")==0) - log_info(_("WARNING: keyserver option \"%s\" is not used " - "on this platform\n"),tok); -#else - else if(ascii_strcasecmp(tok,"use-temp-files")==0) - opt.keyserver_options.use_temp_files=1; - else if(ascii_strcasecmp(tok,"no-use-temp-files")==0) - opt.keyserver_options.use_temp_files=0; -#endif - else - if(!parse_import_options(tok, - &opt.keyserver_options.import_options) && - !parse_export_options(tok, - &opt.keyserver_options.export_options)) - add_to_strlist(&opt.keyserver_options.other,tok); - } - } -} - -int -parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) -{ - int assume_hkp=0; - - assert(uri!=NULL); - - opt.keyserver_host=NULL; - opt.keyserver_port=NULL; - opt.keyserver_opaque=NULL; - - /* Get the scheme */ - - opt.keyserver_scheme=strsep(&uri,":"); - if(uri==NULL) - { - /* Assume HKP if there is no scheme */ - assume_hkp=1; - uri=opt.keyserver_scheme; - opt.keyserver_scheme="hkp"; - } - else - { - /* Force to lowercase */ - char *i; - - for(i=opt.keyserver_scheme;*i!='\0';i++) - *i=ascii_tolower(*i); - } - - if(ascii_strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0) - { - deprecated_warning(configname,configlineno,"x-broken-hkp", - "--keyserver-options ","broken-http-proxy"); - opt.keyserver_scheme="hkp"; - opt.keyserver_options.broken_http_proxy=1; - } - else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0) - { - /* Canonicalize this to "hkp" so it works with both the internal - and external keyserver interface. */ - opt.keyserver_scheme="hkp"; - } - - if(assume_hkp || (uri[0]=='/' && uri[1]=='/')) - { - /* Two slashes means network path. */ - - /* Skip over the "//", if any */ - if(!assume_hkp) - uri+=2; - - /* Get the host */ - opt.keyserver_host=strsep(&uri,":/"); - if(opt.keyserver_host[0]=='\0') - return G10ERR_BAD_URI; - - if(uri==NULL || uri[0]=='\0') - opt.keyserver_port=NULL; - else - { - char *ch; - - /* Get the port */ - opt.keyserver_port=strsep(&uri,"/"); - - /* Ports are digits only */ - ch=opt.keyserver_port; - while(*ch!='\0') - { - if(!isdigit(*ch)) - return G10ERR_BAD_URI; - - ch++; - } - } - - /* (any path part of the URI is discarded for now as no keyserver - uses it yet) */ - } - else if(uri[0]!='/') - { - /* No slash means opaque. Just record the opaque blob and get - out. */ - opt.keyserver_opaque=uri; - return 0; - } - else - { - /* One slash means absolute path. We don't need to support that - yet. */ - return G10ERR_BAD_URI; - } - - if(opt.keyserver_scheme[0]=='\0') - return G10ERR_BAD_URI; - - return 0; -} - -static void -print_keyrec(int number,struct keyrec *keyrec) -{ - int i; - - iobuf_writebyte(keyrec->uidbuf,0); - iobuf_flush_temp(keyrec->uidbuf); - printf("(%d)\t%s ",number,iobuf_get_temp_buffer(keyrec->uidbuf)); - - if(keyrec->size>0) - printf("%d bit ",keyrec->size); - - if(keyrec->type) - { - const char *str=pubkey_algo_to_string(keyrec->type); - - if(str) - printf("%s ",str); - else - printf("unknown "); - } - - switch(keyrec->desc.mode) - { - case KEYDB_SEARCH_MODE_SHORT_KID: - printf("key %08lX",(ulong)keyrec->desc.u.kid[1]); - break; - - case KEYDB_SEARCH_MODE_LONG_KID: - printf("key %08lX%08lX",(ulong)keyrec->desc.u.kid[0], - (ulong)keyrec->desc.u.kid[1]); - break; - - case KEYDB_SEARCH_MODE_FPR16: - printf("key "); - for(i=0;i<16;i++) - printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]); - break; - - case KEYDB_SEARCH_MODE_FPR20: - printf("key "); - for(i=0;i<20;i++) - printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]); - break; - - default: - BUG(); - break; - } - - if(keyrec->createtime>0) - printf(", created %s",strtimestamp(keyrec->createtime)); - - if(keyrec->expiretime>0) - printf(", expires %s",strtimestamp(keyrec->expiretime)); - - if(keyrec->flags&1) - printf(" (%s)",("revoked")); - if(keyrec->flags&2) - printf(" (%s)",("disabled")); - if(keyrec->flags&4) - printf(" (%s)",("expired")); - - printf("\n"); -} - -/* Returns a keyrec (which must be freed) once a key is complete, and - NULL otherwise. Call with a NULL keystring once key parsing is - complete to return any unfinished keys. */ -static struct keyrec * -parse_keyrec(char *keystring) -{ - static struct keyrec *work=NULL; - struct keyrec *ret=NULL; - char *record,*tok; - int i; - - if(keystring==NULL) - { - if(work==NULL) - return NULL; - else if(work->desc.mode==KEYDB_SEARCH_MODE_NONE) - { - m_free(work); - return NULL; - } - else - { - ret=work; - work=NULL; - return ret; - } - } - - if(work==NULL) - { - work=m_alloc_clear(sizeof(struct keyrec)); - work->uidbuf=iobuf_temp(); - } - - /* Remove trailing whitespace */ - for(i=strlen(keystring);i>0;i--) - if(isspace(keystring[i-1])) - keystring[i-1]='\0'; - else - break; - - if((record=strsep(&keystring,":"))==NULL) - return ret; - - if(ascii_strcasecmp("pub",record)==0) - { - if(work->desc.mode) - { - ret=work; - work=m_alloc_clear(sizeof(struct keyrec)); - work->uidbuf=iobuf_temp(); - } - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - classify_user_id(tok,&work->desc); - if(work->desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID - && work->desc.mode!=KEYDB_SEARCH_MODE_LONG_KID - && work->desc.mode!=KEYDB_SEARCH_MODE_FPR16 - && work->desc.mode!=KEYDB_SEARCH_MODE_FPR20) - { - work->desc.mode=KEYDB_SEARCH_MODE_NONE; - return ret; - } - - /* Note all items after this are optional. This allows us to - have a pub line as simple as pub:keyid and nothing else. */ - - work->lines++; - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - work->type=atoi(tok); - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - work->size=atoi(tok); - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - work->createtime=atoi(tok); - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - work->expiretime=atoi(tok); - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - while(*tok) - switch(*tok++) - { - case 'r': - case 'R': - work->flags|=1; - break; - - case 'd': - case 'D': - work->flags|=2; - break; - - case 'e': - case 'E': - work->flags|=4; - break; - } - - if(work->expiretime && work->expiretime<=make_timestamp()) - work->flags|=4; - } - else if(ascii_strcasecmp("uid",record)==0 && work->desc.mode) - { - char *userid,*tok,*decoded; - int i=0; - - if((tok=strsep(&keystring,":"))==NULL) - return ret; - - if(strlen(tok)==0) - return ret; - - userid=tok; - - /* By definition, de-%-encoding is always smaller than the - original string so we can decode in place. */ - - while(*tok) - if(tok[0]=='%' && tok[1] && tok[2]) - { - if((userid[i]=hextobyte(&tok[1]))==-1) - userid[i]='?'; - - i++; - tok+=3; - } - else - userid[i++]=*tok++; - - /* We don't care about the other info provided in the uid: line - since no keyserver supports marking userids with timestamps - or revoked/expired/disabled yet. */ - - /* No need to check for control characters, as utf8_to_native - does this for us. */ - - decoded=utf8_to_native(userid,i,0); - iobuf_writestr(work->uidbuf,decoded); - m_free(decoded); - iobuf_writestr(work->uidbuf,"\n\t"); - work->lines++; - } - - /* Ignore any records other than "pri" and "uid" for easy future - growth. */ - - return ret; -} - -/* TODO: do this as a list sent to keyserver_work rather than calling - it once for each key to get the correct counts after the import - (cosmetics, really) and to better take advantage of the keyservers - that can do multiple fetches in one go (LDAP). */ -static int -show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) -{ - char *answer; - - if(count) - { - static int from=1; - tty_printf("Keys %d-%d of %d for \"%s\". ",from,numdesc,count,search); - from=numdesc+1; - } - - answer=cpr_get_no_help("keysearch.prompt", - _("Enter number(s), N)ext, or Q)uit > ")); - /* control-d */ - if(answer[0]=='\x04') - { - printf("Q\n"); - answer[0]='q'; - } - - if(answer[0]=='q' || answer[0]=='Q') - { - m_free(answer); - return 1; - } - else if(atoi(answer)>=1 && atoi(answer)<=numdesc) - { - char *split=answer,*num; - - while((num=strsep(&split," ,"))!=NULL) - if(atoi(num)>=1 && atoi(num)<=numdesc) - keyserver_work(GET,NULL,&desc[atoi(num)-1],1); - - m_free(answer); - return 1; - } - - return 0; -} - -/* Count and searchstr are just for cosmetics. If the count is too - small, it will grow safely. If negative it disables the "Key x-y - of z" messages. */ -static void -keyserver_search_prompt(IOBUF buffer,const char *searchstr) -{ - int i=0,validcount=0,started=0,count=1; - unsigned int maxlen,buflen; - KEYDB_SEARCH_DESC *desc; - byte *line=NULL; - /* TODO: Something other than 23? That's 24-1 (the prompt). */ - int maxlines=23,numlines=0; - - desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC)); - - for(;;) - { - struct keyrec *keyrec; - int rl; - - maxlen=1024; - rl=iobuf_read_line(buffer,&line,&buflen,&maxlen); - - /* Look for an info: line. The only current info: values - defined are the version and key count. */ - if(!started && rl>0 && ascii_strncasecmp("info:",line,5)==0) - { - char *tok,*str=&line[5]; - - if((tok=strsep(&str,":"))!=NULL) - { - int version; - - if(sscanf(tok,"%d",&version)!=1) - version=1; - - if(version!=1) - { - log_error(_("invalid keyserver protocol " - "(us %d!=handler %d)\n"),1,version); - break; - } - } - - if((tok=strsep(&str,":"))!=NULL && sscanf(tok,"%d",&count)==1) - { - if(count==0) - goto notfound; - else if(count<0) - count=10; - else - validcount=1; - - desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); - } - - started=1; - continue; - } - - if(rl==0) - { - keyrec=parse_keyrec(NULL); - - if(keyrec==NULL) - { - if(i==0) - { - count=0; - break; - } - - if(i!=count) - validcount=0; - - for(;;) - { - if(show_prompt(desc,i,validcount?count:0,searchstr)) - break; - validcount=0; - } - - break; - } - } - else - keyrec=parse_keyrec(line); - - if(i==count) - { - /* keyserver helper sent more keys than they claimed in the - info: line. */ - count+=10; - desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); - validcount=0; - } - - if(keyrec) - { - desc[i]=keyrec->desc; - - if(numlines+keyrec->lines>maxlines) - { - if(show_prompt(desc,i,validcount?count:0,searchstr)) - break; - else - numlines=0; - } - - print_keyrec(i+1,keyrec); - numlines+=keyrec->lines; - iobuf_close(keyrec->uidbuf); - m_free(keyrec); - - started=1; - i++; - } - } - - m_free(desc); - m_free(line); - - notfound: - if(count==0) - { - if(searchstr) - log_info(_("key \"%s\" not found on keyserver\n"),searchstr); - else - log_info(_("key not found on keyserver\n")); - return; - } -} - -#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" -#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" - -static int -keyserver_spawn(int action,STRLIST list, - KEYDB_SEARCH_DESC *desc,int count,int *prog) -{ - int ret=0,i,gotversion=0,outofband=0; - STRLIST temp; - unsigned int maxlen,buflen; - char *command=NULL,*searchstr=NULL; - byte *line=NULL; - struct kopts *kopts; - struct exec_info *spawn; - -#ifdef EXEC_TEMPFILE_ONLY - opt.keyserver_options.use_temp_files=1; -#endif - - /* Push the libexecdir into path. If DISABLE_KEYSERVER_PATH is set, - use the 0 arg to replace the path. */ -#ifdef DISABLE_KEYSERVER_PATH - set_exec_path(GNUPG_LIBEXECDIR,0); -#else - set_exec_path(GNUPG_LIBEXECDIR,opt.exec_path_set); -#endif - - /* Build the filename for the helper to execute */ - command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); - strcpy(command,"gpgkeys_"); - strcat(command,opt.keyserver_scheme); - - if(opt.keyserver_options.use_temp_files) - { - if(opt.keyserver_options.keep_temp_files) - { - command=m_realloc(command,strlen(command)+ - strlen(KEYSERVER_ARGS_KEEP)+1); - strcat(command,KEYSERVER_ARGS_KEEP); - } - else - { - command=m_realloc(command,strlen(command)+ - strlen(KEYSERVER_ARGS_NOKEEP)+1); - strcat(command,KEYSERVER_ARGS_NOKEEP); - } - - ret=exec_write(&spawn,NULL,command,NULL,0,0); - } - else - ret=exec_write(&spawn,command,NULL,NULL,0,0); - - if(ret) - return ret; - - fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n"); - fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION); - fprintf(spawn->tochild,"PROGRAM %s\n",VERSION); - - if(opt.keyserver_opaque) - fprintf(spawn->tochild,"OPAQUE %s\n",opt.keyserver_opaque); - else - { - if(opt.keyserver_host) - fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host); - - if(opt.keyserver_port) - fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port); - } - - /* Write options */ - - for(i=0,kopts=keyserver_opts;kopts[i].name;i++) - if(*(kopts[i].flag) && kopts[i].tell) - fprintf(spawn->tochild,"OPTION %s\n",kopts[i].name); - - for(i=0;itochild,"OPTION verbose\n"); - - temp=opt.keyserver_options.other; - - for(;temp;temp=temp->next) - fprintf(spawn->tochild,"OPTION %s\n",temp->d); - - switch(action) - { - case GET: - { - fprintf(spawn->tochild,"COMMAND GET\n\n"); - - /* Which keys do we want? */ - - for(i=0;itochild,"0x"); - - for(f=0;ftochild,"%02X",(byte)desc[i].u.fpr[f]); - - fprintf(spawn->tochild,"\n"); - } - else if(desc[i].mode==KEYDB_SEARCH_MODE_FPR16) - { - int f; - - fprintf(spawn->tochild,"0x"); - - for(f=0;f<16;f++) - fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]); - - fprintf(spawn->tochild,"\n"); - } - else if(desc[i].mode==KEYDB_SEARCH_MODE_LONG_KID) - fprintf(spawn->tochild,"0x%08lX%08lX\n", - (ulong)desc[i].u.kid[0], - (ulong)desc[i].u.kid[1]); - else - fprintf(spawn->tochild,"0x%08lX\n", - (ulong)desc[i].u.kid[1]); - } - - fprintf(spawn->tochild,"\n"); - - break; - } - - case SEND: - { - STRLIST key; - - /* Note the extra \n here to send an empty keylist block */ - fprintf(spawn->tochild,"COMMAND SEND\n\n\n"); - - for(key=list;key!=NULL;key=key->next) - { - armor_filter_context_t afx; - IOBUF buffer=iobuf_temp(); - - temp=NULL; - add_to_strlist(&temp,key->d); - - memset(&afx,0,sizeof(afx)); - afx.what=1; - iobuf_push_filter(buffer,armor_filter,&afx); - - if(export_pubkeys_stream(buffer,temp, - opt.keyserver_options.export_options)==-1) - iobuf_close(buffer); - else - { - iobuf_flush_temp(buffer); - - fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d); - fwrite(iobuf_get_temp_buffer(buffer), - iobuf_get_temp_length(buffer),1,spawn->tochild); - fprintf(spawn->tochild,"KEY %s END\n",key->d); - - iobuf_close(buffer); - } - - free_strlist(temp); - } - - break; - } - - case SEARCH: - { - STRLIST key; - - fprintf(spawn->tochild,"COMMAND SEARCH\n\n"); - - /* Which keys do we want? Remember that the gpgkeys_ program - is going to lump these together into a search string. */ - - for(key=list;key!=NULL;key=key->next) - { - fprintf(spawn->tochild,"%s\n",key->d); - if(key!=list) - { - searchstr=m_realloc(searchstr, - strlen(searchstr)+strlen(key->d)+2); - strcat(searchstr," "); - } - else - { - searchstr=m_alloc(strlen(key->d)+1); - searchstr[0]='\0'; - } - - strcat(searchstr,key->d); - } - - fprintf(spawn->tochild,"\n"); - - break; - } - - default: - log_fatal(_("no keyserver action!\n")); - break; - } - - /* Done sending, so start reading. */ - ret=exec_read(spawn); - if(ret) - goto fail; - - /* Now handle the response */ - - for(;;) - { - int plen; - char *ptr; - - maxlen=1024; - if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) - { - ret=G10ERR_READ_FILE; - goto fail; /* i.e. EOF */ - } - - ptr=line; - - /* remove trailing whitespace */ - plen=strlen(ptr); - while(plen>0 && isspace(ptr[plen-1])) - plen--; - plen[ptr]='\0'; - - if(*ptr=='\0') - break; - - if(ascii_strncasecmp(ptr,"VERSION ",8)==0) - { - gotversion=1; - - if(atoi(&ptr[8])!=KEYSERVER_PROTO_VERSION) - { - log_error(_("invalid keyserver protocol (us %d!=handler %d)\n"), - KEYSERVER_PROTO_VERSION,atoi(&ptr[8])); - goto fail; - } - } - else if(ascii_strncasecmp(ptr,"PROGRAM ",8)==0) - { - if(ascii_strncasecmp(&ptr[8],VERSION,strlen(VERSION))!=0) - log_info(_("WARNING: keyserver handler from a different " - "version of GnuPG (%s)\n"),&ptr[8]); - } - else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0) - outofband=1; /* Currently the only OPTION */ - } - - if(!gotversion) - { - log_error(_("keyserver did not send VERSION\n")); - goto fail; - } - - if(!outofband) - switch(action) - { - case GET: - { - void *stats_handle; - - stats_handle=import_new_stats_handle(); - - /* Slurp up all the key data. In the future, it might be - nice to look for KEY foo OUTOFBAND and FAILED indicators. - It's harmless to ignore them, but ignoring them does make - gpg complain about "no valid OpenPGP data found". One - way to do this could be to continue parsing this - line-by-line and make a temp iobuf for each key. */ - - import_keys_stream(spawn->fromchild,stats_handle, - opt.keyserver_options.import_options); - - import_print_stats(stats_handle); - import_release_stats_handle(stats_handle); - - break; - } - - /* Nothing to do here */ - case SEND: - break; - - case SEARCH: - { - keyserver_search_prompt(spawn->fromchild,searchstr); - - break; - } - - default: - log_fatal(_("no keyserver action!\n")); - break; - } - - fail: - m_free(line); - - *prog=exec_finish(spawn); - - return ret; -} - -static int -keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) -{ - int rc=0,ret=0; - - if(opt.keyserver_scheme==NULL) - { - log_error(_("no keyserver known (use option --keyserver)\n")); - return G10ERR_BAD_URI; - } - -#ifdef DISABLE_KEYSERVER_HELPERS - - log_error(_("external keyserver calls are not supported in this build\n")); - return G10ERR_KEYSERVER; - -#else - /* Spawn a handler */ - - rc=keyserver_spawn(action,list,desc,count,&ret); - if(ret) - { - switch(ret) - { - case KEYSERVER_SCHEME_NOT_FOUND: - log_error(_("no handler for keyserver scheme \"%s\"\n"), - opt.keyserver_scheme); - break; - - case KEYSERVER_NOT_SUPPORTED: - log_error(_("action \"%s\" not supported with keyserver " - "scheme \"%s\"\n"), - action==GET?"get":action==SEND?"send": - action==SEARCH?"search":"unknown", - opt.keyserver_scheme); - break; - - case KEYSERVER_VERSION_ERROR: - log_error(_("gpgkeys_%s does not support handler version %d\n"), - opt.keyserver_scheme,KEYSERVER_PROTO_VERSION); - break; - - case KEYSERVER_INTERNAL_ERROR: - default: - log_error(_("keyserver internal error\n")); - break; - } - - return G10ERR_KEYSERVER; - } - - if(rc) - { - log_error(_("keyserver communications error: %s\n"),g10_errstr(rc)); - - return rc; - } - - return 0; -#endif /* ! DISABLE_KEYSERVER_HELPERS*/ -} - -int -keyserver_export(STRLIST users) -{ - /* We better ask for confirmation when the user entered --send-keys - without arguments. Sending all keys might not be the thing he - intended to do */ - if (users || opt.batch || opt.answer_yes) - ; - else if ( !cpr_get_answer_is_yes - ("keyserver_export.send_all", - _("Do you really want to send all your " - "public keys to the keyserver? (y/N) "))) - return -1; - - return keyserver_work(SEND,users,NULL,0); -} - -int -keyserver_import(STRLIST users) -{ - KEYDB_SEARCH_DESC *desc; - int num=100,count=0; - int rc=0; - - /* Build a list of key ids */ - desc=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); - - for(;users;users=users->next) - { - classify_user_id (users->d, &desc[count]); - if(desc[count].mode!=KEYDB_SEARCH_MODE_SHORT_KID && - desc[count].mode!=KEYDB_SEARCH_MODE_LONG_KID && - desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 && - desc[count].mode!=KEYDB_SEARCH_MODE_FPR20) - { - log_error(_("skipping invalid key ID \"%s\"\n"),users->d); - continue; - } - - count++; - if(count==num) - { - num+=100; - desc=m_realloc(desc,sizeof(KEYDB_SEARCH_DESC)*num); - } - } - - if(count>0) - rc=keyserver_work(GET,NULL,desc,count); - - m_free(desc); - - return rc; -} - -int -keyserver_import_fprint(const byte *fprint,size_t fprint_len) -{ - KEYDB_SEARCH_DESC desc; - - memset(&desc,0,sizeof(desc)); - - if(fprint_len==16) - desc.mode=KEYDB_SEARCH_MODE_FPR16; - else if(fprint_len==20) - desc.mode=KEYDB_SEARCH_MODE_FPR20; - else - return -1; - - memcpy(desc.u.fpr,fprint,fprint_len); - - return keyserver_work(GET,NULL,&desc,1); -} - -int -keyserver_import_keyid(u32 *keyid) -{ - KEYDB_SEARCH_DESC desc; - - memset(&desc,0,sizeof(desc)); - - desc.mode=KEYDB_SEARCH_MODE_LONG_KID; - desc.u.kid[0]=keyid[0]; - desc.u.kid[1]=keyid[1]; - - return keyserver_work(GET,NULL,&desc,1); -} - -/* code mostly stolen from do_export_stream */ -static int -keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) -{ - int rc=0,ndesc,num=100; - KBNODE keyblock=NULL,node; - KEYDB_HANDLE kdbhd; - KEYDB_SEARCH_DESC *desc; - STRLIST sl; - - *count=0; - - *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); - - kdbhd=keydb_new(0); - - if(!users) - { - ndesc = 1; - desc = m_alloc_clear ( ndesc * sizeof *desc); - desc[0].mode = KEYDB_SEARCH_MODE_FIRST; - } - else - { - for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) - ; - desc = m_alloc ( 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, g10_errstr (G10ERR_INV_USER_ID)); - } - } - - while (!(rc = keydb_search (kdbhd, desc, ndesc))) - { - 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"), g10_errstr(rc) ); - goto leave; - } - - if((node=find_kbnode(keyblock,PKT_PUBLIC_KEY))) - { - /* This is to work around a bug in some keyservers (pksd and - OKS) that calculate v4 RSA keyids as if they were v3 RSA. - The answer is to refresh both the correct v4 keyid - (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7). - This only happens for key refresh using the HKP scheme - and if the refresh-add-fake-v3-keyids keyserver option is - set. */ - if(fakev3 && is_RSA(node->pkt->pkt.public_key->pubkey_algo) && - node->pkt->pkt.public_key->version>=4) - { - (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - mpi_get_keyid(node->pkt->pkt.public_key->pkey[0], - (*klist)[*count].u.kid); - (*count)++; - - if(*count==num) - { - num+=100; - *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); - } - } - - /* v4 keys get full fingerprints. v3 keys get long keyids. - This is because it's easy to calculate any sort of key id - from a v4 fingerprint, but not a v3 fingerprint. */ - - if(node->pkt->pkt.public_key->version<4) - { - (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - keyid_from_pk(node->pkt->pkt.public_key, - (*klist)[*count].u.kid); - } - else - { - size_t dummy; - - (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20; - fingerprint_from_pk(node->pkt->pkt.public_key, - (*klist)[*count].u.fpr,&dummy); - } - - (*count)++; - - if(*count==num) - { - num+=100; - *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); - } - } - } - - if(rc==-1) - rc=0; - - leave: - m_free(desc); - keydb_release(kdbhd); - release_kbnode(keyblock); - - return rc; -} - -/* Note this is different than the original HKP refresh. It allows - usernames to refresh only part of the keyring. */ - -int -keyserver_refresh(STRLIST users) -{ - int rc,count,fakev3=0; - KEYDB_SEARCH_DESC *desc; - - /* We switch merge_only on during a refresh, as 'refresh' should - never import new keys, even if their keyids match. Is it worth - preserving the old merge_only value here? */ - opt.merge_only=1; - - /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO - scheme, then enable fake v3 keyid generation. */ - if(opt.keyserver_options.fake_v3_keyids && opt.keyserver_scheme && - (ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0 || - ascii_strcasecmp(opt.keyserver_scheme,"mailto")==0)) - fakev3=1; - - rc=keyidlist(users,&desc,&count,fakev3); - if(rc) - return rc; - - if(count==1) - log_info(_("refreshing 1 key from %s\n"),opt.keyserver_uri); - else - log_info(_("refreshing %d keys from %s\n"),count,opt.keyserver_uri); - - if(count>0) - rc=keyserver_work(GET,NULL,desc,count); - - m_free(desc); - - return 0; -} - -int -keyserver_search(STRLIST tokens) -{ - if(tokens) - return keyserver_work(SEARCH,tokens,NULL,0); - else - return 0; -} diff --git a/g10/main.h b/g10/main.h deleted file mode 100644 index f16355bc8..000000000 --- a/g10/main.h +++ /dev/null @@ -1,224 +0,0 @@ -/* main.h - * 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 - */ -#ifndef G10_MAIN_H -#define G10_MAIN_H -#include "types.h" -#include "iobuf.h" -#include "mpi.h" -#include "cipher.h" -#include "keydb.h" - -#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5 -#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL -#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1 -#define DEFAULT_COMPRESS_ALGO 1 - -typedef struct { - int header_okay; - PK_LIST pk_list; - cipher_filter_context_t cfx; -} encrypt_filter_context_t; - -struct groupitem -{ - char *name; - STRLIST values; - struct groupitem *next; -}; - -/*-- g10.c --*/ -extern int g10_errors_seen; - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) - void g10_exit(int rc) __attribute__ ((noreturn)); -#else - void g10_exit(int rc); -#endif -void print_pubkey_algo_note( int algo ); -void print_cipher_algo_note( int algo ); -void print_digest_algo_note( int algo ); - -/*-- armor.c --*/ -char *make_radix64_string( const byte *data, size_t len ); - -/*-- misc.c --*/ -void trap_unaligned(void); -int disable_core_dumps(void); -u16 checksum_u16( unsigned n ); -u16 checksum( byte *p, unsigned n ); -u16 checksum_mpi( MPI a ); -u32 buffer_to_u32( const byte *buffer ); -const byte *get_session_marker( size_t *rlen ); -int openpgp_cipher_test_algo( int algo ); -int openpgp_pk_test_algo( int algo, unsigned int usage_flags ); -int openpgp_pk_algo_usage ( int algo ); -int openpgp_md_test_algo( int algo ); -void idea_cipher_warn( int show ); - -struct expando_args -{ - PKT_public_key *pk; - PKT_secret_key *sk; - byte imagetype; -}; - -char *pct_expando(const char *string,struct expando_args *args); -int hextobyte( const char *s ); -void deprecated_warning(const char *configname,unsigned int configlineno, - const char *option,const char *repl1,const char *repl2); -const char *compress_algo_to_string(int algo); -int check_compress_algo(int algo); - -/*-- helptext.c --*/ -void display_online_help( const char *keyword ); - -/*-- encode.c --*/ -int encode_symmetric( const char *filename ); -int encode_store( const char *filename ); -int encode_crypt( const char *filename, STRLIST remusr ); -void encode_crypt_files(int nfiles, char **files, STRLIST remusr); -int encrypt_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len); - - -/*-- sign.c --*/ -int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ); -int sign_file( STRLIST filenames, int detached, STRLIST locusr, - int do_encrypt, STRLIST remusr, const char *outfile ); -int clearsign_file( const char *fname, STRLIST locusr, const char *outfile ); -int sign_symencrypt_file (const char *fname, STRLIST locusr); - -/*-- sig-check.c --*/ -int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig); -int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); -int check_key_signature2( KBNODE root, KBNODE node, - int *is_selfsig, u32 *r_expiredate, int *r_expired ); - -/*-- delkey.c --*/ -int delete_keys( STRLIST names, int secret, int allow_both ); - -/*-- keyedit.c --*/ -void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds, - int sign_mode ); -void show_basic_key_info (KBNODE keyblock); - -/*-- keygen.c --*/ -u32 ask_expire_interval(int object); -u32 ask_expiredate(void); -void generate_keypair( const char *fname ); -int keygen_set_std_prefs (const char *string,int personal); -char *keygen_get_std_prefs (void); -int keygen_add_key_expire( PKT_signature *sig, void *opaque ); -int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); -int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); -int keygen_add_revkey(PKT_signature *sig, void *opaque); -int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); - -/*-- openfile.c --*/ -int overwrite_filep( const char *fname ); -char *make_outfile_name( const char *iname ); -char *ask_outfile_name( const char *name, size_t namelen ); -int open_outfile( const char *iname, int mode, IOBUF *a ); -IOBUF open_sigfile( const char *iname ); -void try_make_homedir( const char *fname ); - -/*-- seskey.c --*/ -void make_session_key( DEK *dek ); -MPI encode_session_key( DEK *dek, unsigned nbits ); -MPI encode_md_value( int pubkey_algo, MD_HANDLE md, - int hash_algo, unsigned nbits, int v3compathack ); - -/*-- comment.c --*/ -KBNODE make_comment_node( const char *s ); -KBNODE make_mpi_comment_node( const char *s, MPI a ); - -/*-- import.c --*/ -#define IMPORT_ALLOW_LOCAL_SIGS 1 -#define IMPORT_REPAIR_HKP_SUBKEY_BUG 2 -#define IMPORT_FAST_IMPORT 4 - -int parse_import_options(char *str,unsigned int *options); -void import_keys( char **fnames, int nnames, - void *stats_hd, unsigned int options ); -int import_keys_stream( IOBUF inp, - void *stats_hd, unsigned int options ); -void *import_new_stats_handle (void); -void import_release_stats_handle (void *p); -void import_print_stats (void *hd); - -int collapse_uids( KBNODE *keyblock ); - -/*-- export.c --*/ -#define EXPORT_INCLUDE_NON_RFC 1 -#define EXPORT_INCLUDE_LOCAL_SIGS 2 -#define EXPORT_INCLUDE_ATTRIBUTES 4 -#define EXPORT_INCLUDE_SENSITIVE_REVKEYS 8 - -int parse_export_options(char *str,unsigned int *options); -int export_pubkeys( STRLIST users, unsigned int options ); -int export_pubkeys_stream( IOBUF out, STRLIST users, unsigned int options ); -int export_seckeys( STRLIST users ); -int export_secsubkeys( STRLIST users ); - -/* dearmor.c --*/ -int dearmor_file( const char *fname ); -int enarmor_file( const char *fname ); - -/*-- revoke.c --*/ -struct revocation_reason_info; -int gen_revoke( const char *uname ); -int gen_desig_revoke( const char *uname ); -int revocation_reason_build_cb( PKT_signature *sig, void *opaque ); -struct revocation_reason_info * - ask_revocation_reason( int key_rev, int cert_rev, int hint ); -void release_revocation_reason_info( struct revocation_reason_info *reason ); - -/*-- keylist.c --*/ -void public_key_list( STRLIST list ); -void secret_key_list( STRLIST list ); -void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); -void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); -void show_policy_url(PKT_signature *sig,int indent); -void show_notation(PKT_signature *sig,int indent); -void set_attrib_fd(int fd); - -/*-- verify.c --*/ -void print_file_status( int status, const char *name, int what ); -int verify_signatures( int nfiles, char **files ); -int verify_files( int nfiles, char **files ); - -/*-- decrypt.c --*/ -int decrypt_message( const char *filename ); -void decrypt_messages(int nfiles, char **files); - -/*-- plaintext.c --*/ -int hash_datafiles( MD_HANDLE md, MD_HANDLE md2, - STRLIST files, const char *sigfilename, int textmode ); - -/*-- pipemode.c --*/ -void run_in_pipemode (void); - -/*-- signal.c --*/ -void init_signals(void); -void pause_on_sigusr( int which ); -void block_all_signals(void); -void unblock_all_signals(void); - -#endif /*G10_MAIN_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c deleted file mode 100644 index f9be17600..000000000 --- a/g10/mainproc.c +++ /dev/null @@ -1,1656 +0,0 @@ -/* mainproc.c - handle packets - * 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 -#include -#include -#include -#include -#include - -#include "packet.h" -#include "iobuf.h" -#include "memory.h" -#include "options.h" -#include "util.h" -#include "cipher.h" -#include "keydb.h" -#include "filter.h" -#include "main.h" -#include "status.h" -#include "i18n.h" -#include "trustdb.h" -#include "keyserver-internal.h" -#include "photoid.h" - - -struct kidlist_item { - struct kidlist_item *next; - u32 kid[2]; - int pubkey_algo; - int reason; -}; - - - -/**************** - * Structure to hold the context - */ -typedef struct mainproc_context *CTX; -struct mainproc_context { - struct mainproc_context *anchor; /* may be useful in the future */ - PKT_public_key *last_pubkey; - PKT_secret_key *last_seckey; - PKT_user_id *last_user_id; - md_filter_context_t mfx; - int sigs_only; /* process only signatures and reject all other stuff */ - int encrypt_only; /* process only encrytion messages */ - STRLIST signed_data; - const char *sigfilename; - DEK *dek; - int last_was_session_key; - KBNODE list; /* the current list of packets */ - int have_data; - IOBUF iobuf; /* used to get the filename etc. */ - int trustletter; /* temp usage in list_node */ - ulong local_id; /* ditto */ - struct kidlist_item *pkenc_list; /* list of encryption packets */ - struct { - int op; - int stop_now; - } pipemode; -}; - - -static int do_proc_packets( CTX c, IOBUF a ); - -static void list_node( CTX c, KBNODE node ); -static void proc_tree( CTX c, KBNODE node ); - - -static void -release_list( CTX c ) -{ - if( !c->list ) - return; - proc_tree(c, c->list ); - release_kbnode( c->list ); - while( c->pkenc_list ) { - struct kidlist_item *tmp = c->pkenc_list->next; - m_free( c->pkenc_list ); - c->pkenc_list = tmp; - } - c->pkenc_list = NULL; - c->list = NULL; - c->have_data = 0; - c->last_was_session_key = 0; - c->pipemode.op = 0; - c->pipemode.stop_now = 0; - m_free(c->dek); c->dek = NULL; -} - - -static int -add_onepass_sig( CTX c, PACKET *pkt ) -{ - KBNODE node; - - if( c->list ) { /* add another packet */ - /* We can only append another onepass packet if the list - * does contain only onepass packets */ - for( node=c->list; node && node->pkt->pkttype == PKT_ONEPASS_SIG; - node = node->next ) - ; - if( node ) { - /* this is not the case, so we flush the current thing and - * allow this packet to start a new verification thing */ - release_list( c ); - c->list = new_kbnode( pkt ); - } - else - add_kbnode( c->list, new_kbnode( pkt )); - } - else /* insert the first one */ - c->list = node = new_kbnode( pkt ); - - return 1; -} - - -static int -add_gpg_control( CTX c, PACKET *pkt ) -{ - if ( pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START ) { - /* New clear text signature. - * Process the last one and reset everything */ - release_list(c); - } - else if ( pkt->pkt.gpg_control->control == CTRLPKT_PIPEMODE ) { - /* Pipemode control packet */ - if ( pkt->pkt.gpg_control->datalen < 2 ) - log_fatal ("invalid pipemode control packet length\n"); - if (pkt->pkt.gpg_control->data[0] == 1) { - /* start the whole thing */ - assert ( !c->list ); /* we should be in a pretty virgin state */ - assert ( !c->pipemode.op ); - c->pipemode.op = pkt->pkt.gpg_control->data[1]; - } - else if (pkt->pkt.gpg_control->data[0] == 2) { - /* the signed material follows in a plaintext packet */ - assert ( c->pipemode.op == 'B' ); - } - else if (pkt->pkt.gpg_control->data[0] == 3) { - assert ( c->pipemode.op == 'B' ); - release_list (c); - /* and tell the outer loop to terminate */ - c->pipemode.stop_now = 1; - } - else - log_fatal ("invalid pipemode control packet code\n"); - return 0; /* no need to store the packet */ - } - - if( c->list ) /* add another packet */ - add_kbnode( c->list, new_kbnode( pkt )); - else /* insert the first one */ - c->list = new_kbnode( pkt ); - - return 1; -} - - - -static int -add_user_id( CTX c, PACKET *pkt ) -{ - if( !c->list ) { - log_error("orphaned user ID\n" ); - return 0; - } - add_kbnode( c->list, new_kbnode( pkt ) ); - return 1; -} - -static int -add_subkey( CTX c, PACKET *pkt ) -{ - if( !c->list ) { - log_error("subkey w/o mainkey\n" ); - return 0; - } - add_kbnode( c->list, new_kbnode( pkt ) ); - return 1; -} - -static int -add_ring_trust( CTX c, PACKET *pkt ) -{ - if( !c->list ) { - log_error("ring trust w/o key\n" ); - return 0; - } - add_kbnode( c->list, new_kbnode( pkt ) ); - return 1; -} - - -static int -add_signature( CTX c, PACKET *pkt ) -{ - KBNODE node; - - if( pkt->pkttype == PKT_SIGNATURE && !c->list ) { - /* This is the first signature for the following datafile. - * GPG does not write such packets; instead it always uses - * onepass-sig packets. The drawback of PGP's method - * of prepending the signature to the data is - * that it is not possible to make a signature from data read - * from stdin. (GPG is able to read PGP stuff anyway.) */ - node = new_kbnode( pkt ); - c->list = node; - return 1; - } - else if( !c->list ) - return 0; /* oops (invalid packet sequence)*/ - else if( !c->list->pkt ) - BUG(); /* so nicht */ - - /* add a new signature node id at the end */ - node = new_kbnode( pkt ); - add_kbnode( c->list, node ); - return 1; -} - -static void -symkey_decrypt_sesskey( DEK *dek, byte *sesskey, size_t slen ) -{ - CIPHER_HANDLE hd; - int n; - - if ( slen < 17 || slen > 33 ) { - log_error ( _("weird size for an encrypted session key (%d)\n"), - (int)slen); - return; - } - hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); - cipher_setkey( hd, dek->key, dek->keylen ); - cipher_setiv( hd, NULL, 0 ); - cipher_decrypt( hd, sesskey, sesskey, slen ); - cipher_close( hd ); - /* check first byte (the cipher algo) */ - if ( sesskey[0] > 10 ) { - log_error ( _("invalid symkey algorithm detected (%d)\n"), - sesskey[0] ); - return; - } - n = cipher_get_keylen (sesskey[0]) / 8; - if (n > DIM(dek->key)) - BUG (); - /* now we replace the dek components with the real session key - to decrypt the contents of the sequencing packet. */ - dek->keylen = cipher_get_keylen( sesskey[0] ) / 8; - dek->algo = sesskey[0]; - memcpy( dek->key, sesskey + 1, dek->keylen ); - /*log_hexdump( "thekey", dek->key, dek->keylen );*/ -} - -static void -proc_symkey_enc( CTX c, PACKET *pkt ) -{ - PKT_symkey_enc *enc; - - enc = pkt->pkt.symkey_enc; - if (!enc) - log_error ("invalid symkey encrypted packet\n"); - else { - int algo = enc->cipher_algo; - const char *s; - - s = cipher_algo_to_string (algo); - if( s ) - log_info(_("%s encrypted data\n"), s ); - else - log_info(_("encrypted with unknown algorithm %d\n"), algo ); - - c->last_was_session_key = 2; - if ( opt.list_only ) - goto leave; - c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL ); - if (c->dek) - c->dek->algo_info_printed = 1; - if ( c->dek && enc->seskeylen ) - symkey_decrypt_sesskey( c->dek, enc->seskey, enc->seskeylen ); - } -leave: - free_packet(pkt); -} - -static void -proc_pubkey_enc( CTX c, PACKET *pkt ) -{ - PKT_pubkey_enc *enc; - int result = 0; - - /* check whether the secret key is available and store in this case */ - c->last_was_session_key = 1; - enc = pkt->pkt.pubkey_enc; - /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ - /* Hmmm: why do I have this algo check here - anyway there is - * function to check it. */ - if( opt.verbose ) - log_info(_("public key is %08lX\n"), (ulong)enc->keyid[1] ); - - if( is_status_enabled() ) { - char buf[50]; - sprintf(buf, "%08lX%08lX %d 0", - (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo ); - write_status_text( STATUS_ENC_TO, buf ); - } - - if( !opt.list_only && opt.override_session_key ) { - /* It does not make much sense to store the session key in - * secure memory because it has already been passed on the - * command line and the GCHQ knows about it */ - c->dek = m_alloc_clear( sizeof *c->dek ); - result = get_override_session_key ( c->dek, opt.override_session_key ); - if ( result ) { - m_free(c->dek); c->dek = NULL; - } - } - else if( is_ELGAMAL(enc->pubkey_algo) - || enc->pubkey_algo == PUBKEY_ALGO_DSA - || is_RSA(enc->pubkey_algo) ) { - if ( !c->dek && ((!enc->keyid[0] && !enc->keyid[1]) - || opt.try_all_secrets - || !seckey_available( enc->keyid )) ) { - if( opt.list_only ) - result = -1; - else { - c->dek = m_alloc_secure_clear( sizeof *c->dek ); - if( (result = get_session_key( enc, c->dek )) ) { - /* error: delete the DEK */ - m_free(c->dek); c->dek = NULL; - } - } - } - else - result = G10ERR_NO_SECKEY; - } - else - result = G10ERR_PUBKEY_ALGO; - - if( result == -1 ) - ; - else { - if( !result ) { - if( opt.verbose > 1 ) - log_info( _("public key encrypted data: good DEK\n") ); - if ( opt.show_session_key ) { - int i; - char *buf = m_alloc ( c->dek->keylen*2 + 20 ); - sprintf ( buf, "%d:", c->dek->algo ); - for(i=0; i < c->dek->keylen; i++ ) - sprintf(buf+strlen(buf), "%02X", c->dek->key[i] ); - log_info( "session key: \"%s\"\n", buf ); - write_status_text ( STATUS_SESSION_KEY, buf ); - } - } - /* store it for later display */ - { - struct kidlist_item *x = m_alloc( sizeof *x ); - x->kid[0] = enc->keyid[0]; - x->kid[1] = enc->keyid[1]; - x->pubkey_algo = enc->pubkey_algo; - x->reason = result; - x->next = c->pkenc_list; - c->pkenc_list = x; - } - } - free_packet(pkt); -} - - - -/**************** - * Print the list of public key encrypted packets which we could - * not decrypt. - */ -static void -print_pkenc_list( struct kidlist_item *list, int failed ) -{ - for( ; list; list = list->next ) { - PKT_public_key *pk; - const char *algstr; - - if ( failed && !list->reason ) - continue; - if ( !failed && list->reason ) - continue; - - algstr = pubkey_algo_to_string( list->pubkey_algo ); - pk = m_alloc_clear( sizeof *pk ); - - if( !algstr ) - algstr = "[?]"; - pk->pubkey_algo = list->pubkey_algo; - if( !get_pubkey( pk, list->kid ) ) { - size_t n; - char *p; - log_info( _("encrypted with %u-bit %s key, ID %08lX, created %s\n"), - nbits_from_pk( pk ), algstr, (ulong)list->kid[1], - strtimestamp(pk->timestamp) ); - fputs(" \"", log_stream() ); - p = get_user_id( list->kid, &n ); - print_utf8_string2 ( log_stream(), p, n, '"' ); - m_free(p); - fputs("\"\n", log_stream() ); - } - else { - log_info(_("encrypted with %s key, ID %08lX\n"), - algstr, (ulong) list->kid[1] ); - } - free_public_key( pk ); - - if( list->reason == G10ERR_NO_SECKEY ) { - if( is_status_enabled() ) { - char buf[20]; - sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], - (ulong)list->kid[1] ); - write_status_text( STATUS_NO_SECKEY, buf ); - } - } - else if (list->reason) - log_info(_("public key decryption failed: %s\n"), - g10_errstr(list->reason)); - } -} - - -static void -proc_encrypted( CTX c, PACKET *pkt ) -{ - int result = 0; - - if (!opt.quiet) { - print_pkenc_list ( c->pkenc_list, 1 ); - print_pkenc_list ( c->pkenc_list, 0 ); - } - - write_status( STATUS_BEGIN_DECRYPTION ); - - /*log_debug("dat: %sencrypted data\n", c->dek?"":"conventional ");*/ - if( opt.list_only ) - result = -1; - else if( !c->dek && !c->last_was_session_key ) { - int algo; - STRING2KEY s2kbuf, *s2k = NULL; - - /* assume this is old style conventional encrypted data */ - if ( (algo = opt.def_cipher_algo)) - log_info (_("assuming %s encrypted data\n"), - cipher_algo_to_string(algo)); - else if ( check_cipher_algo(CIPHER_ALGO_IDEA) ) { - algo = opt.def_cipher_algo; - if (!algo) - algo = opt.s2k_cipher_algo; - idea_cipher_warn(1); - log_info (_("IDEA cipher unavailable, " - "optimistically attempting to use %s instead\n"), - cipher_algo_to_string(algo)); - } - else { - algo = CIPHER_ALGO_IDEA; - if (!opt.def_digest_algo) { - /* If no digest is given we assume MD5 */ - s2kbuf.mode = 0; - s2kbuf.hash_algo = DIGEST_ALGO_MD5; - s2k = &s2kbuf; - } - log_info (_("assuming %s encrypted data\n"), "IDEA"); - } - - c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL ); - if (c->dek) - c->dek->algo_info_printed = 1; - } - else if( !c->dek ) - result = G10ERR_NO_SECKEY; - if( !result ) - result = decrypt_data( c, pkt->pkt.encrypted, c->dek ); - - m_free(c->dek); c->dek = NULL; - if( result == -1 ) - ; - else if( !result || (result==G10ERR_BAD_SIGN && opt.ignore_mdc_error)) { - write_status( STATUS_DECRYPTION_OKAY ); - if( opt.verbose > 1 ) - log_info(_("decryption okay\n")); - if( pkt->pkt.encrypted->mdc_method && !result ) - write_status( STATUS_GOODMDC ); - else if(!opt.no_mdc_warn) - log_info ("WARNING: message was not integrity protected\n"); - } - else if( result == G10ERR_BAD_SIGN ) { - log_error(_("WARNING: encrypted message has been manipulated!\n")); - write_status( STATUS_BADMDC ); - write_status( STATUS_DECRYPTION_FAILED ); - } - else { - write_status( STATUS_DECRYPTION_FAILED ); - log_error(_("decryption failed: %s\n"), g10_errstr(result)); - /* Hmmm: does this work when we have encrypted using multiple - * ways to specify the session key (symmmetric and PK)*/ - } - free_packet(pkt); - c->last_was_session_key = 0; - write_status( STATUS_END_DECRYPTION ); -} - - - -static void -proc_plaintext( CTX c, PACKET *pkt ) -{ - PKT_plaintext *pt = pkt->pkt.plaintext; - int any, clearsig, only_md5, rc; - KBNODE n; - - if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) - log_info(_("NOTE: sender requested \"for-your-eyes-only\"\n")); - else if( opt.verbose ) - log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name); - free_md_filter_context( &c->mfx ); - c->mfx.md = md_open( 0, 0); - /* fixme: we may need to push the textfilter if we have sigclass 1 - * and no armoring - Not yet tested - * Hmmm, why don't we need it at all if we have sigclass 1 - * Should we assume that plaintext in mode 't' has always sigclass 1?? - * See: Russ Allbery's mail 1999-02-09 - */ - any = clearsig = only_md5 = 0; - for(n=c->list; n; n = n->next ) { - if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { - if( n->pkt->pkt.onepass_sig->digest_algo ) { - md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); - if( !any && n->pkt->pkt.onepass_sig->digest_algo - == DIGEST_ALGO_MD5 ) - only_md5 = 1; - else - only_md5 = 0; - any = 1; - } - if( n->pkt->pkt.onepass_sig->sig_class != 0x01 ) - only_md5 = 0; - } - else if( n->pkt->pkttype == PKT_GPG_CONTROL - && n->pkt->pkt.gpg_control->control - == CTRLPKT_CLEARSIGN_START ) { - size_t datalen = n->pkt->pkt.gpg_control->datalen; - const byte *data = n->pkt->pkt.gpg_control->data; - - /* check that we have at least the sigclass and one hash */ - if ( datalen < 2 ) - log_fatal("invalid control packet CTRLPKT_CLEARSIGN_START\n"); - /* Note that we don't set the clearsig flag for not-dash-escaped - * documents */ - clearsig = (*data == 0x01); - for( data++, datalen--; datalen; datalen--, data++ ) - md_enable( c->mfx.md, *data ); - any = 1; - break; /* no pass signature pakets are expected */ - } - } - - if( !any && !opt.skip_verify ) { - /* no onepass sig packet: enable all standard algos */ - md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); - md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); - md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); - } - if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) { - /* This is a kludge to work around a bug in pgp2. It does only - * catch those mails which are armored. To catch the non-armored - * pgp mails we could see whether there is the signature packet - * in front of the plaintext. If someone needs this, send me a patch. - */ - c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0); - } - if ( DBG_HASHING ) { - md_start_debug( c->mfx.md, "verify" ); - if ( c->mfx.md2 ) - md_start_debug( c->mfx.md2, "verify2" ); - } - if ( c->pipemode.op == 'B' ) - rc = handle_plaintext( pt, &c->mfx, 1, 0 ); - else { - rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); - if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { - /* can't write output but we hash it anyway to - * check the signature */ - rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); - } - } - if( rc ) - log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); - free_packet(pkt); - c->last_was_session_key = 0; - - /* We add a marker control packet instead of the plaintext packet. - * This is so that we can later detect invalid packet sequences. - */ - n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK, NULL, 0)); - if (c->list) - add_kbnode (c->list, n); - else - c->list = n; -} - - -static int -proc_compressed_cb( IOBUF a, void *info ) -{ - return proc_signature_packets( info, a, ((CTX)info)->signed_data, - ((CTX)info)->sigfilename ); -} - -static int -proc_encrypt_cb( IOBUF a, void *info ) -{ - return proc_encryption_packets( info, a ); -} - -static void -proc_compressed( CTX c, PACKET *pkt ) -{ - PKT_compressed *zd = pkt->pkt.compressed; - int rc; - - /*printf("zip: compressed data packet\n");*/ - if( c->sigs_only ) - rc = handle_compressed( c, zd, proc_compressed_cb, c ); - else if( c->encrypt_only ) - rc = handle_compressed( c, zd, proc_encrypt_cb, c ); - else - rc = handle_compressed( c, zd, NULL, NULL ); - if( rc ) - log_error("uncompressing failed: %s\n", g10_errstr(rc)); - free_packet(pkt); - c->last_was_session_key = 0; -} - -/**************** - * check the signature - * Returns: 0 = valid signature or an error code - */ -static int -do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) -{ - PKT_signature *sig; - MD_HANDLE md = NULL, md2 = NULL; - int algo, rc, dum2; - u32 dummy; - - if(!is_expkey) - is_expkey=&dum2; - - assert( node->pkt->pkttype == PKT_SIGNATURE ); - if( is_selfsig ) - *is_selfsig = 0; - sig = node->pkt->pkt.signature; - - algo = sig->digest_algo; - if( (rc=check_digest_algo(algo)) ) - return rc; - - if( sig->sig_class == 0x00 ) { - if( c->mfx.md ) - md = md_copy( c->mfx.md ); - else /* detached signature */ - md = md_open( 0, 0 ); /* signature_check() will enable the md*/ - } - else if( sig->sig_class == 0x01 ) { - /* how do we know that we have to hash the (already hashed) text - * in canonical mode ??? (calculating both modes???) */ - if( c->mfx.md ) { - md = md_copy( c->mfx.md ); - if( c->mfx.md2 ) - md2 = md_copy( c->mfx.md2 ); - } - else { /* detached signature */ - log_debug("Do we really need this here?"); - md = md_open( 0, 0 ); /* signature_check() will enable the md*/ - md2 = md_open( 0, 0 ); - } - } - else if( (sig->sig_class&~3) == 0x10 - || sig->sig_class == 0x18 - || sig->sig_class == 0x1f - || sig->sig_class == 0x20 - || sig->sig_class == 0x28 - || sig->sig_class == 0x30 ) { - if( c->list->pkt->pkttype == PKT_PUBLIC_KEY - || c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - return check_key_signature( c->list, node, is_selfsig ); - } - else if( sig->sig_class == 0x20 ) { - log_info(_("standalone revocation - " - "use \"gpg --import\" to apply\n")); - return G10ERR_NOT_PROCESSED; - } - else { - log_error("invalid root packet for sigclass %02x\n", - sig->sig_class); - return G10ERR_SIG_CLASS; - } - } - else - return G10ERR_SIG_CLASS; - rc = signature_check2( sig, md, &dummy, is_expkey ); - if( rc == G10ERR_BAD_SIGN && md2 ) - rc = signature_check2( sig, md2, &dummy, is_expkey ); - md_close(md); - md_close(md2); - - return rc; -} - - -static void -print_userid( PACKET *pkt ) -{ - if( !pkt ) - BUG(); - if( pkt->pkttype != PKT_USER_ID ) { - printf("ERROR: unexpected packet type %d", pkt->pkttype ); - return; - } - if( opt.with_colons ) - { - if(pkt->pkt.user_id->attrib_data) - printf("%u %lu", - pkt->pkt.user_id->numattribs, - pkt->pkt.user_id->attrib_len); - else - print_string( stdout, pkt->pkt.user_id->name, - pkt->pkt.user_id->len, ':'); - } - else - print_utf8_string( stdout, pkt->pkt.user_id->name, - pkt->pkt.user_id->len ); -} - - -static void -print_notation_data( PKT_signature *sig ) -{ - size_t n, n1, n2; - const byte *p; - int seq = 0; - - while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&n,&seq,NULL))) { - if( n < 8 ) { - log_info(_("WARNING: invalid notation data found\n")); - return; - } - if( !(*p & 0x80) ) - return; /* not human readable */ - n1 = (p[4] << 8) | p[5]; - n2 = (p[6] << 8) | p[7]; - p += 8; - if( 8+n1+n2 != n ) { - log_info(_("WARNING: invalid notation data found\n")); - return; - } - log_info(_("Notation: ") ); - print_string( log_stream(), p, n1, 0 ); - putc( '=', log_stream() ); - print_string( log_stream(), p+n1, n2, 0 ); - putc( '\n', log_stream() ); - write_status_buffer ( STATUS_NOTATION_NAME, p , n1, 0 ); - write_status_buffer ( STATUS_NOTATION_DATA, p+n1, n2, 50 ); - } - - seq=0; - - while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&n,&seq,NULL))) { - log_info(_("Policy: ") ); - print_string( log_stream(), p, n, 0 ); - putc( '\n', log_stream() ); - write_status_buffer ( STATUS_POLICY_URL, p, n, 0 ); - } - - /* Now check whether the key of this signature has some - * notation data */ - - /* TODO */ -} - - -/**************** - * List the certificate in a user friendly way - */ - -static void -list_node( CTX c, KBNODE node ) -{ - int any=0; - int mainkey; - - if( !node ) - ; - else if( (mainkey = (node->pkt->pkttype == PKT_PUBLIC_KEY) ) - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - PKT_public_key *pk = node->pkt->pkt.public_key; - - if( opt.with_colons ) { - u32 keyid[2]; - keyid_from_pk( pk, keyid ); - if( mainkey ) { - c->local_id = pk->local_id; - c->trustletter = opt.fast_list_mode? - 0 : get_validity_info( pk, NULL ); - } - printf("%s:", mainkey? "pub":"sub" ); - if( c->trustletter ) - putchar( c->trustletter ); - printf(":%u:%d:%08lX%08lX:%s:%s:", - nbits_from_pk( pk ), - pk->pubkey_algo, - (ulong)keyid[0],(ulong)keyid[1], - colon_datestr_from_pk( pk ), - colon_strtime (pk->expiredate) ); - if( c->local_id ) - printf("%lu", c->local_id ); - putchar(':'); - if( mainkey && !opt.fast_list_mode ) - putchar( get_ownertrust_info (pk) ); - putchar(':'); - if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) { - putchar('\n'); any=1; - if( opt.fingerprint ) - print_fingerprint( pk, NULL, 0 ); - printf("rtv:1:%u:\n", - node->next->pkt->pkt.ring_trust->trustval ); - } - } - else - printf("%s %4u%c/%08lX %s ", - mainkey? "pub":"sub", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk( pk, NULL ), - datestr_from_pk( pk ) ); - - if( mainkey ) { - /* and now list all userids with their signatures */ - for( node = node->next; node; node = node->next ) { - if( node->pkt->pkttype == PKT_SIGNATURE ) { - if( !any ) { - if( node->pkt->pkt.signature->sig_class == 0x20 ) - puts("[revoked]"); - else - putchar('\n'); - any = 1; - } - list_node(c, node ); - } - else if( node->pkt->pkttype == PKT_USER_ID ) { - if( any ) { - if( opt.with_colons ) - printf("%s:::::::::", - node->pkt->pkt.user_id->attrib_data?"uat":"uid"); - else - printf( "uid%*s", 28, "" ); - } - print_userid( node->pkt ); - if( opt.with_colons ) - putchar(':'); - putchar('\n'); - if( opt.fingerprint && !any ) - print_fingerprint( pk, NULL, 0 ); - if( node->next - && node->next->pkt->pkttype == PKT_RING_TRUST ) { - printf("rtv:2:%u:\n", - node->next->pkt->pkt.ring_trust->trustval ); - } - any=1; - } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - if( !any ) { - putchar('\n'); - any = 1; - } - list_node(c, node ); - } - } - } - else if( pk->expiredate ) { /* of subkey */ - printf(_(" [expires: %s]"), expirestr_from_pk( pk ) ); - } - - if( !any ) - putchar('\n'); - if( !mainkey && opt.fingerprint > 1 ) - print_fingerprint( pk, NULL, 0 ); - } - else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) ) - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *sk = node->pkt->pkt.secret_key; - - if( opt.with_colons ) { - u32 keyid[2]; - keyid_from_sk( sk, keyid ); - printf("%s::%u:%d:%08lX%08lX:%s:%s:::", - mainkey? "sec":"ssb", - nbits_from_sk( sk ), - sk->pubkey_algo, - (ulong)keyid[0],(ulong)keyid[1], - colon_datestr_from_sk( sk ), - colon_strtime (sk->expiredate) - /* fixme: add LID */ ); - } - else - printf("%s %4u%c/%08lX %s ", - mainkey? "sec":"ssb", - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid_from_sk( sk, NULL ), - datestr_from_sk( sk ) ); - if( mainkey ) { - /* and now list all userids with their signatures */ - for( node = node->next; node; node = node->next ) { - if( node->pkt->pkttype == PKT_SIGNATURE ) { - if( !any ) { - if( node->pkt->pkt.signature->sig_class == 0x20 ) - puts("[revoked]"); - else - putchar('\n'); - any = 1; - } - list_node(c, node ); - } - else if( node->pkt->pkttype == PKT_USER_ID ) { - if( any ) { - if( opt.with_colons ) - printf("%s:::::::::", - node->pkt->pkt.user_id->attrib_data?"uat":"uid"); - else - printf( "uid%*s", 28, "" ); - } - print_userid( node->pkt ); - if( opt.with_colons ) - putchar(':'); - putchar('\n'); - if( opt.fingerprint && !any ) - print_fingerprint( NULL, sk, 0 ); - any=1; - } - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - if( !any ) { - putchar('\n'); - any = 1; - } - list_node(c, node ); - } - } - } - if( !any ) - putchar('\n'); - if( !mainkey && opt.fingerprint > 1 ) - print_fingerprint( NULL, sk, 0 ); - } - else if( node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - int is_selfsig = 0; - int rc2=0; - size_t n; - char *p; - int sigrc = ' '; - - if( !opt.list_sigs ) - return; - - if( sig->sig_class == 0x20 || sig->sig_class == 0x30 ) - fputs("rev", stdout); - else - fputs("sig", stdout); - if( opt.check_sigs ) { - fflush(stdout); - switch( (rc2=do_check_sig( c, node, &is_selfsig, NULL )) ) { - case 0: sigrc = '!'; break; - case G10ERR_BAD_SIGN: sigrc = '-'; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: sigrc = '?'; break; - default: sigrc = '%'; break; - } - } - else { /* check whether this is a self signature */ - u32 keyid[2]; - - if( c->list->pkt->pkttype == PKT_PUBLIC_KEY - || c->list->pkt->pkttype == PKT_SECRET_KEY ) { - if( c->list->pkt->pkttype == PKT_PUBLIC_KEY ) - keyid_from_pk( c->list->pkt->pkt.public_key, keyid ); - else - keyid_from_sk( c->list->pkt->pkt.secret_key, keyid ); - - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) - is_selfsig = 1; - } - } - if( opt.with_colons ) { - putchar(':'); - if( sigrc != ' ' ) - putchar(sigrc); - printf("::%d:%08lX%08lX:%s::::", sig->pubkey_algo, - (ulong)sig->keyid[0], - (ulong)sig->keyid[1], colon_datestr_from_sig(sig)); - } - else - printf("%c %08lX %s ", - sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig)); - if( sigrc == '%' ) - printf("[%s] ", g10_errstr(rc2) ); - else if( sigrc == '?' ) - ; - else if( is_selfsig ) { - if( opt.with_colons ) - putchar(':'); - fputs( sig->sig_class == 0x18? "[keybind]":"[selfsig]", stdout); - if( opt.with_colons ) - putchar(':'); - } - else if( !opt.fast_list_mode ) { - p = get_user_id( sig->keyid, &n ); - print_string( stdout, p, n, opt.with_colons ); - m_free(p); - } - if( opt.with_colons ) - printf(":%02x%c:", sig->sig_class, sig->flags.exportable?'x':'l'); - putchar('\n'); - } - else - log_error("invalid node with packet of type %d\n", node->pkt->pkttype); -} - - - -int -proc_packets( void *anchor, IOBUF a ) -{ - int rc; - CTX c = m_alloc_clear( sizeof *c ); - - c->anchor = anchor; - rc = do_proc_packets( c, a ); - m_free( c ); - return rc; -} - - - -int -proc_signature_packets( void *anchor, IOBUF a, - STRLIST signedfiles, const char *sigfilename ) -{ - CTX c = m_alloc_clear( sizeof *c ); - int rc; - - c->anchor = anchor; - c->sigs_only = 1; - c->signed_data = signedfiles; - c->sigfilename = sigfilename; - rc = do_proc_packets( c, a ); - m_free( c ); - return rc; -} - -int -proc_encryption_packets( void *anchor, IOBUF a ) -{ - CTX c = m_alloc_clear( sizeof *c ); - int rc; - - c->anchor = anchor; - c->encrypt_only = 1; - rc = do_proc_packets( c, a ); - m_free( c ); - return rc; -} - - -int -do_proc_packets( CTX c, IOBUF a ) -{ - PACKET *pkt = m_alloc( sizeof *pkt ); - int rc=0; - int any_data=0; - int newpkt; - - c->iobuf = a; - init_packet(pkt); - while( (rc=parse_packet(a, pkt)) != -1 ) { - any_data = 1; - if( rc ) { - free_packet(pkt); - /* stop processing hwne an invalid packet has been encountered - * but don't do so when we are doing a --list-packet. */ - if( rc == G10ERR_INVALID_PACKET && opt.list_packets != 2 ) - break; - continue; - } - newpkt = -1; - if( opt.list_packets ) { - switch( pkt->pkttype ) { - case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; - case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; - case PKT_ENCRYPTED: - case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; - case PKT_COMPRESSED: proc_compressed( c, pkt ); break; - default: newpkt = 0; break; - } - } - else if( c->sigs_only ) { - switch( pkt->pkttype ) { - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - case PKT_USER_ID: - case PKT_SYMKEY_ENC: - case PKT_PUBKEY_ENC: - case PKT_ENCRYPTED: - case PKT_ENCRYPTED_MDC: - write_status_text( STATUS_UNEXPECTED, "0" ); - rc = G10ERR_UNEXPECTED; - goto leave; - case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; - case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; - case PKT_COMPRESSED: proc_compressed( c, pkt ); break; - case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; - case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; - default: newpkt = 0; break; - } - } - else if( c->encrypt_only ) { - switch( pkt->pkttype ) { - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - case PKT_USER_ID: - write_status_text( STATUS_UNEXPECTED, "0" ); - rc = G10ERR_UNEXPECTED; - goto leave; - case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; - case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; - case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; - case PKT_ENCRYPTED: - case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; - case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; - case PKT_COMPRESSED: proc_compressed( c, pkt ); break; - case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; - case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; - default: newpkt = 0; break; - } - } - else { - switch( pkt->pkttype ) { - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - release_list( c ); - c->list = new_kbnode( pkt ); - newpkt = 1; - break; - case PKT_PUBLIC_SUBKEY: - case PKT_SECRET_SUBKEY: - newpkt = add_subkey( c, pkt ); - break; - case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break; - case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; - case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; - case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; - case PKT_ENCRYPTED: - case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; - case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; - case PKT_COMPRESSED: proc_compressed( c, pkt ); break; - case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; - case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; - case PKT_RING_TRUST: newpkt = add_ring_trust( c, pkt ); break; - default: newpkt = 0; break; - } - } - /* This is a very ugly construct and frankly, I don't remember why - * I used it. Adding the MDC check here is a hack. - * The right solution is to initiate another context for encrypted - * packet and not to reuse the current one ... It works right - * when there is a compression packet inbetween which adds just - * an extra layer. - * Hmmm: Rewrite this whole module here?? - */ - if( pkt->pkttype != PKT_SIGNATURE && pkt->pkttype != PKT_MDC ) - c->have_data = pkt->pkttype == PKT_PLAINTEXT; - - if( newpkt == -1 ) - ; - else if( newpkt ) { - pkt = m_alloc( sizeof *pkt ); - init_packet(pkt); - } - else - free_packet(pkt); - if ( c->pipemode.stop_now ) { - /* we won't get an EOF in pipemode, so we have to - * break the loop here */ - rc = -1; - break; - } - } - if( rc == G10ERR_INVALID_PACKET ) - write_status_text( STATUS_NODATA, "3" ); - if( any_data ) - rc = 0; - else if( rc == -1 ) - write_status_text( STATUS_NODATA, "2" ); - - - leave: - release_list( c ); - m_free(c->dek); - free_packet( pkt ); - m_free( pkt ); - free_md_filter_context( &c->mfx ); - return rc; -} - - -static int -check_sig_and_print( CTX c, KBNODE node ) -{ - PKT_signature *sig = node->pkt->pkt.signature; - const char *astr, *tstr; - int rc, is_expkey=0; - - if( opt.skip_verify ) { - log_info(_("signature verification suppressed\n")); - return 0; - } - - /* It is not in all cases possible to check multiple signatures: - * PGP 2 (which is also allowed by OpenPGP), does use the packet - * sequence: sig+data, OpenPGP does use onepas+data=sig and GnuPG - * sometimes uses (because I did'nt read the specs right) data+sig. - * Because it is possible to create multiple signatures with - * different packet sequence (e.g. data+sig and sig+data) it might - * not be possible to get it right: let's say we have: - * data+sig, sig+data,sig+data and we have not yet encountered the last - * data, we could also see this a one data with 2 signatures and then - * data+sig. - * To protect against this we check that all signatures follow - * without any intermediate packets. Note, that we won't get this - * error when we use onepass packets or cleartext signatures because - * we reset the list every time - * - * FIXME: Now that we have these marker packets, we should create a - * real grammar and check against this. - */ - { - KBNODE n; - int n_sig=0; - - for (n=c->list; n; n=n->next ) { - if ( n->pkt->pkttype == PKT_SIGNATURE ) - n_sig++; - } - if (n_sig > 1) { /* more than one signature - check sequence */ - int tmp, onepass; - - for (tmp=onepass=0,n=c->list; n; n=n->next ) { - if (n->pkt->pkttype == PKT_ONEPASS_SIG) - onepass++; - else if (n->pkt->pkttype == PKT_GPG_CONTROL - && n->pkt->pkt.gpg_control->control - == CTRLPKT_CLEARSIGN_START ) { - onepass++; /* handle the same way as a onepass */ - } - else if ( (tmp && n->pkt->pkttype != PKT_SIGNATURE) ) { - log_error(_("can't handle these multiple signatures\n")); - return 0; - } - else if ( n->pkt->pkttype == PKT_SIGNATURE ) - tmp = 1; - else if (!tmp && !onepass - && n->pkt->pkttype == PKT_GPG_CONTROL - && n->pkt->pkt.gpg_control->control - == CTRLPKT_PLAINTEXT_MARK ) { - /* plaintext before signatures but no one-pass packets*/ - log_error(_("can't handle these multiple signatures\n")); - return 0; - } - } - } - } - - - - tstr = asctimestamp(sig->timestamp); - astr = pubkey_algo_to_string( sig->pubkey_algo ); - log_info(_("Signature made %.*s using %s key ID %08lX\n"), - (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); - - rc = do_check_sig(c, node, NULL, &is_expkey ); - if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { - if( keyserver_import_keyid ( sig->keyid )==0 ) - rc = do_check_sig(c, node, NULL, &is_expkey ); - } - if( !rc || rc == G10ERR_BAD_SIGN ) { - KBNODE un, keyblock; - int count=0, statno; - char keyid_str[50]; - - if(rc) - statno=STATUS_BADSIG; - else if(sig->flags.expired) - statno=STATUS_EXPSIG; - else if(is_expkey) - statno=STATUS_EXPKEYSIG; - else - statno=STATUS_GOODSIG; - - keyblock = get_pubkeyblock( sig->keyid ); - - sprintf (keyid_str, "%08lX%08lX [uncertain] ", - (ulong)sig->keyid[0], (ulong)sig->keyid[1]); - - /* find and print the primary user ID */ - for( un=keyblock; un; un = un->next ) { - if( un->pkt->pkttype != PKT_USER_ID ) - continue; - if ( !un->pkt->pkt.user_id->created ) - continue; - if ( un->pkt->pkt.user_id->is_revoked ) - continue; - if ( un->pkt->pkt.user_id->is_expired ) - continue; - if ( !un->pkt->pkt.user_id->is_primary ) - continue; - /* We want the textual user ID here */ - if ( un->pkt->pkt.user_id->attrib_data ) - continue; - - keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - write_status_text_and_buffer (statno, keyid_str, - un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len, - -1 ); - - log_info(rc? _("BAD signature from \"") - : sig->flags.expired ? _("Expired signature from \"") - : _("Good signature from \"")); - print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len ); - fputs("\"\n", log_stream() ); - count++; - } - if( !count ) { /* just in case that we have no valid textual - userid */ - /* Try for an invalid textual userid */ - for( un=keyblock; un; un = un->next ) { - if( un->pkt->pkttype == PKT_USER_ID && - !un->pkt->pkt.user_id->attrib_data ) - break; - } - - /* Try for any userid at all */ - if(!un) { - for( un=keyblock; un; un = un->next ) { - if( un->pkt->pkttype == PKT_USER_ID ) - break; - } - } - - if (opt.always_trust || !un) - keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - - write_status_text_and_buffer (statno, keyid_str, - un? un->pkt->pkt.user_id->name:"[?]", - un? un->pkt->pkt.user_id->len:3, - -1 ); - - log_info(rc? _("BAD signature from \"") - : sig->flags.expired ? _("Expired signature from \"") - : _("Good signature from \"")); - if (!opt.always_trust && un) { - fputs(_("[uncertain]"), log_stream() ); - putc(' ', log_stream() ); - } - print_utf8_string( log_stream(), - un? un->pkt->pkt.user_id->name:"[?]", - un? un->pkt->pkt.user_id->len:3 ); - fputs("\"\n", log_stream() ); - } - - /* If we have a good signature and already printed - * the primary user ID, print all the other user IDs */ - if ( count && !rc ) { - PKT_public_key *pk=NULL; - for( un=keyblock; un; un = un->next ) { - if(un->pkt->pkttype==PKT_PUBLIC_KEY) - pk=un->pkt->pkt.public_key; - if( un->pkt->pkttype != PKT_USER_ID ) - continue; - if ( un->pkt->pkt.user_id->is_revoked ) - continue; - if ( un->pkt->pkt.user_id->is_expired ) - continue; - /* Only skip textual primaries */ - if ( un->pkt->pkt.user_id->is_primary && - !un->pkt->pkt.user_id->attrib_data ) - continue; - - if(opt.show_photos && un->pkt->pkt.user_id->attrib_data) - show_photos(un->pkt->pkt.user_id->attribs, - un->pkt->pkt.user_id->numattribs,pk,NULL); - - log_info( _(" aka \"")); - print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len ); - fputs("\"\n", log_stream() ); - } - } - release_kbnode( keyblock ); - - if( !rc ) - print_notation_data( sig ); - - if( !rc && is_status_enabled() ) { - /* print a status response with the fingerprint */ - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - - if( !get_pubkey( pk, sig->keyid ) ) { - byte array[MAX_FINGERPRINT_LEN], *p; - char buf[MAX_FINGERPRINT_LEN*2+72]; - size_t i, n; - - fingerprint_from_pk( pk, array, &n ); - p = array; - for(i=0; i < n ; i++, p++ ) - sprintf(buf+2*i, "%02X", *p ); - sprintf(buf+strlen(buf), " %s %lu %lu", - strtimestamp( sig->timestamp ), - (ulong)sig->timestamp, - (ulong)sig->expiredate ); - write_status_text( STATUS_VALIDSIG, buf ); - } - free_public_key( pk ); - } - - if( !rc ) - rc = check_signatures_trust( sig ); - - if(sig->flags.expired) - { - log_info("Signature expired %s\n",asctimestamp(sig->expiredate)); - rc=G10ERR_GENERAL; /* need a better error here? */ - } - else if(sig->expiredate) - log_info("Signature expires %s\n",asctimestamp(sig->expiredate)); - - if( rc ) - g10_errors_seen = 1; - if( opt.batch && rc ) - g10_exit(1); - } - else { - char buf[50]; - sprintf(buf, "%08lX%08lX %d %d %02x %lu %d", - (ulong)sig->keyid[0], (ulong)sig->keyid[1], - sig->pubkey_algo, sig->digest_algo, - sig->sig_class, (ulong)sig->timestamp, rc ); - write_status_text( STATUS_ERRSIG, buf ); - if( rc == G10ERR_NO_PUBKEY ) { - buf[16] = 0; - write_status_text( STATUS_NO_PUBKEY, buf ); - } - if( rc != G10ERR_NOT_PROCESSED ) - log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); - } - return rc; -} - - -/**************** - * Process the tree which starts at node - */ -static void -proc_tree( CTX c, KBNODE node ) -{ - KBNODE n1; - int rc; - - if( opt.list_packets || opt.list_only ) - return; - - /* we must skip our special plaintext marker packets here becuase - they may be the root packet. These packets are only used in - addionla checks and skipping them here doesn't matter */ - while ( node - && node->pkt->pkttype == PKT_GPG_CONTROL - && node->pkt->pkt.gpg_control->control - == CTRLPKT_PLAINTEXT_MARK ) { - node = node->next; - } - if (!node) - return; - - c->local_id = 0; - c->trustletter = ' '; - if( node->pkt->pkttype == PKT_PUBLIC_KEY - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - merge_keys_and_selfsig( node ); - list_node( c, node ); - } - else if( node->pkt->pkttype == PKT_SECRET_KEY ) { - merge_keys_and_selfsig( node ); - list_node( c, node ); - } - else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { - /* check all signatures */ - if( !c->have_data ) { - free_md_filter_context( &c->mfx ); - /* prepare to create all requested message digests */ - c->mfx.md = md_open(0, 0); - - /* fixme: why looking for the signature packet and not 1passpacket*/ - for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { - md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo); - } - /* ask for file and hash it */ - if( c->sigs_only ) { - rc = hash_datafiles( c->mfx.md, NULL, - c->signed_data, c->sigfilename, - n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); - } - else { - rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2, - iobuf_get_real_fname(c->iobuf), - n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); - } - if( rc ) { - log_error("can't hash datafile: %s\n", g10_errstr(rc)); - return; - } - } - else if ( c->signed_data ) { - log_error (_("not a detached signature\n") ); - return; - } - - for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) - check_sig_and_print( c, n1 ); - } - else if( node->pkt->pkttype == PKT_GPG_CONTROL - && node->pkt->pkt.gpg_control->control - == CTRLPKT_CLEARSIGN_START ) { - /* clear text signed message */ - if( !c->have_data ) { - log_error("cleartext signature without data\n" ); - return; - } - else if ( c->signed_data ) { - log_error (_("not a detached signature\n") ); - return; - } - - for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) - check_sig_and_print( c, n1 ); - } - else if( node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - - if( sig->sig_class != 0x00 && sig->sig_class != 0x01 ) - log_info(_("standalone signature of class 0x%02x\n"), - sig->sig_class); - else if( !c->have_data ) { - /* detached signature */ - free_md_filter_context( &c->mfx ); - c->mfx.md = md_open(sig->digest_algo, 0); - if( !opt.pgp2_workarounds ) - ; - else if( sig->digest_algo == DIGEST_ALGO_MD5 - && is_RSA( sig->pubkey_algo ) ) { - /* enable a workaround for a pgp2 bug */ - c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0 ); - } - else if( sig->digest_algo == DIGEST_ALGO_SHA1 - && sig->pubkey_algo == PUBKEY_ALGO_DSA - && sig->sig_class == 0x01 ) { - /* enable the workaround also for pgp5 when the detached - * signature has been created in textmode */ - c->mfx.md2 = md_open( sig->digest_algo, 0 ); - } - #if 0 /* workaround disabled */ - /* Here we have another hack to work around a pgp 2 bug - * It works by not using the textmode for detached signatures; - * this will let the first signature check (on md) fail - * but the second one (on md2) which adds an extra CR should - * then produce the "correct" hash. This is very, very ugly - * hack but it may help in some cases (and break others) - */ - /* c->mfx.md2? 0 :(sig->sig_class == 0x01) */ - #endif - if ( DBG_HASHING ) { - md_start_debug( c->mfx.md, "verify" ); - if ( c->mfx.md2 ) - md_start_debug( c->mfx.md2, "verify2" ); - } - if( c->sigs_only ) { - rc = hash_datafiles( c->mfx.md, c->mfx.md2, - c->signed_data, c->sigfilename, - (sig->sig_class == 0x01) ); - } - else { - rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2, - iobuf_get_real_fname(c->iobuf), - (sig->sig_class == 0x01) ); - } - if( rc ) { - log_error("can't hash datafile: %s\n", g10_errstr(rc)); - return; - } - } - else if ( c->signed_data ) { - log_error (_("not a detached signature\n") ); - return; - } - else if ( c->pipemode.op == 'B' ) - ; /* this is a detached signature trough the pipemode handler */ - else if (!opt.quiet) - log_info(_("old style (PGP 2.x) signature\n")); - - for( n1 = node; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )) ) - check_sig_and_print( c, n1 ); - } - else { - dump_kbnode (c->list); - log_error(_("invalid root packet detected in proc_tree()\n")); - dump_kbnode (node); - } -} - - - - diff --git a/g10/misc.c b/g10/misc.c deleted file mode 100644 index ae553eb47..000000000 --- a/g10/misc.c +++ /dev/null @@ -1,548 +0,0 @@ -/* misc.c - miscellaneous functions - * 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 -#include -#include -#include -#include -#include -#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 - #include - #include -#endif -#ifdef HAVE_SETRLIMIT - #include - #include - #include -#endif -#include "util.h" -#include "main.h" -#include "photoid.h" -#include "options.h" -#include "i18n.h" - - -const char *g10m_revision_string(int); -const char *g10c_revision_string(int); -const char *g10u_revision_string(int); - -#ifdef __GNUC__ -volatile -#endif - void -pull_in_libs(void) -{ - g10m_revision_string(0); - g10c_revision_string(0); - g10u_revision_string(0); -} - - -#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 -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() -{ - #ifdef HAVE_DOSISH_SYSTEM - return 0; - #else - #ifdef HAVE_SETRLIMIT - struct rlimit limit; - - limit.rlim_cur = 0; - limit.rlim_max = 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 -} - - - -u16 -checksum_u16( unsigned n ) -{ - u16 a; - - a = (n >> 8) & 0xff; - a += n & 0xff; - return a; -} - - -u16 -checksum( byte *p, unsigned n ) -{ - u16 a; - - for(a=0; n; n-- ) - a += *p++; - return a; -} - -u16 -checksum_mpi( MPI a ) -{ - u16 csum; - byte *buffer; - unsigned nbytes; - unsigned nbits; - - buffer = mpi_get_buffer( a, &nbytes, NULL ); - nbits = mpi_get_nbits(a); - csum = checksum_u16( nbits ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - return csum; -} - -u32 -buffer_to_u32( const byte *buffer ) -{ - unsigned long a; - a = *buffer << 24; - a |= buffer[1] << 16; - a |= buffer[2] << 8; - a |= buffer[3]; - return a; -} - - -static void -no_exp_algo(void) -{ - static int did_note = 0; - - if( !did_note ) { - did_note = 1; - log_info(_("Experimental algorithms should not be used!\n")); - } -} - -void -print_pubkey_algo_note( int algo ) -{ - if( algo >= 100 && algo <= 110 ) - no_exp_algo(); -} - -void -print_cipher_algo_note( int algo ) -{ - if( algo >= 100 && algo <= 110 ) - no_exp_algo(); - else if( algo == CIPHER_ALGO_3DES - || algo == CIPHER_ALGO_CAST5 - || algo == CIPHER_ALGO_BLOWFISH - || algo == CIPHER_ALGO_TWOFISH - || algo == CIPHER_ALGO_RIJNDAEL - || algo == CIPHER_ALGO_RIJNDAEL192 - || algo == CIPHER_ALGO_RIJNDAEL256 - ) - ; - else { - static int did_note = 0; - - if( !did_note ) { - did_note = 1; - log_info(_("this cipher algorithm is deprecated; " - "please use a more standard one!\n")); - } - } -} - -void -print_digest_algo_note( int algo ) -{ - if( algo >= 100 && algo <= 110 ) - no_exp_algo(); -} - - -/* 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; -} - -/**************** - * Wrapper around the libgcrypt function with addional checks on - * openPGP contraints for the algo ID. - */ -int -openpgp_cipher_test_algo( int algo ) -{ - if( algo < 0 || algo > 110 ) - return G10ERR_CIPHER_ALGO; - return check_cipher_algo(algo); -} - -int -openpgp_pk_test_algo( int algo, unsigned int usage_flags ) -{ - if( algo < 0 || algo > 110 ) - return G10ERR_PUBKEY_ALGO; - return check_pubkey_algo2( algo, usage_flags ); -} - -int -openpgp_pk_algo_usage ( int algo ) -{ - int use = 0; - - /* they are hardwired in gpg 1.0 */ - switch ( algo ) { - case PUBKEY_ALGO_RSA: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; - break; - case PUBKEY_ALGO_RSA_E: - use = PUBKEY_USAGE_ENC; - break; - case PUBKEY_ALGO_RSA_S: - use = PUBKEY_USAGE_SIG; - break; - case PUBKEY_ALGO_ELGAMAL_E: - use = PUBKEY_USAGE_ENC; - break; - case PUBKEY_ALGO_DSA: - use = PUBKEY_USAGE_SIG; - break; - case PUBKEY_ALGO_ELGAMAL: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; - break; - default: - break; - } - return use; -} - -int -openpgp_md_test_algo( int algo ) -{ - if( algo < 0 || algo > 110 ) - return G10ERR_DIGEST_ALGO; - return check_digest_algo(algo); -} - -/* Special warning for the IDEA cipher */ -void -idea_cipher_warn(int show) -{ - static int warned=0; - - if(!warned || show) - { - log_info(_("the IDEA cipher plugin is not present\n")); - log_info(_("please see http://www.gnupg.org/why-not-idea.html " - "for more information\n")); - warned=1; - } -} - -/* Expand %-strings. Returns a string which must be m_freed. Returns - NULL if the string cannot be expanded (too large). */ -char * -pct_expando(const char *string,struct expando_args *args) -{ - const char *ch=string; - int idx=0,maxlen=0,done=0; - u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0}; - char *ret=NULL; - - if(args->pk) - keyid_from_pk(args->pk,pk_keyid); - - if(args->sk) - keyid_from_sk(args->sk,sk_keyid); - - if(!args->pk && args->sk) - keyid_from_sk(args->sk,pk_keyid); - - while(*ch!='\0') - { - char *str=NULL; - - if(!done) - { - /* 8192 is way bigger than we'll need here */ - if(maxlen>=8192) - goto fail; - - maxlen+=1024; - ret=m_realloc(ret,maxlen); - } - - done=0; - - if(*ch=='%') - { - switch(*(ch+1)) - { - case 's': /* short key id */ - if(idx+8pk) - fingerprint_from_pk(args->pk,array,&len); - else - memset(array,0, (len=MAX_FINGERPRINT_LEN)); - - if(idx+(len*2)imagetype,0); - /* fall through */ - - case 'T': /* e.g. "image/jpeg" */ - if(str==NULL) - str=image_type_to_string(args->imagetype,2); - - if(idx+strlen(str)= '0' && *s <= '9' ) - c = 16 * (*s - '0'); - else if( *s >= 'A' && *s <= 'F' ) - c = 16 * (10 + *s - 'A'); - else if( *s >= 'a' && *s <= 'f' ) - c = 16 * (10 + *s - 'a'); - else - return -1; - s++; - if( *s >= '0' && *s <= '9' ) - c += *s - '0'; - else if( *s >= 'A' && *s <= 'F' ) - c += 10 + *s - 'A'; - else if( *s >= 'a' && *s <= 'f' ) - c += 10 + *s - 'a'; - else - return -1; - return c; -} - -void -deprecated_warning(const char *configname,unsigned int configlineno, - const char *option,const char *repl1,const char *repl2) -{ - if(configname) - { - if(strncmp("--",option,2)==0) - option+=2; - - if(strncmp("--",repl1,2)==0) - repl1+=2; - - log_info(_("%s:%d: deprecated option \"%s\"\n"), - configname,configlineno,option); - } - else - log_info(_("WARNING: \"%s\" is a deprecated option\n"),option); - - log_info(_("please use \"%s%s\" instead\n"),repl1,repl2); -} - -const char * -compress_algo_to_string(int algo) -{ - const char *s="?"; - - switch(algo) - { - case 0: - s="Uncompressed"; - break; - - case 1: - s="ZIP"; - break; - - case 2: - s="ZLIB"; - break; - } - - return s; -} - -int -check_compress_algo(int algo) -{ - if(algo>=0 && algo<=2) - return 0; - - return G10ERR_COMPR_ALGO; -} diff --git a/g10/openfile.c b/g10/openfile.c deleted file mode 100644 index 83c734dfd..000000000 --- a/g10/openfile.c +++ /dev/null @@ -1,362 +0,0 @@ -/* openfile.c - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "ttyio.h" -#include "options.h" -#include "main.h" -#include "status.h" -#include "i18n.h" - -#ifdef USE_ONLY_8DOT3 - #define SKELEXT ".skl" -#else - #define SKELEXT EXTSEP_S "skel" -#endif - -#if defined (HAVE_DRIVE_LETTERS) || defined (__riscos__) - #define CMP_FILENAME(a,b) ascii_strcasecmp( (a), (b) ) -#else - #define CMP_FILENAME(a,b) strcmp( (a), (b) ) -#endif - -#ifdef MKDIR_TAKES_ONE_ARG -# undef mkdir -# define mkdir(a,b) mkdir(a) -#endif - -/* FIXME: Implement opt.interactive. */ - -/**************** - * Check whether FNAME exists and ask if it's okay to overwrite an - * existing one. - * Returns: True: it's okay to overwrite or the file does not exist - * False: Do not overwrite - */ -int -overwrite_filep( const char *fname ) -{ - if( !fname || (*fname == '-' && !fname[1]) ) - return 1; /* writing to stdout is always okay */ - - if( access( fname, F_OK ) ) - return 1; /* does not exist */ - -#ifndef HAVE_DOSISH_SYSTEM - if ( !strcmp ( fname, "/dev/null" ) ) - return 1; /* does not do any harm */ -#endif - - /* fixme: add some backup stuff in case of overwrite */ - if( opt.answer_yes ) - return 1; - if( opt.answer_no || opt.batch ) - return 0; /* do not overwrite */ - - tty_printf(_("File `%s' exists. "), fname); - if( cpr_get_answer_is_yes("openfile.overwrite.okay", - _("Overwrite (y/N)? ")) ) - return 1; - return 0; -} - - -/**************** - * Strip know extensions from iname and return a newly allocated - * filename. Return NULL if we can't do that. - */ -char * -make_outfile_name( const char *iname ) -{ - size_t n; - - if( (!iname || (*iname=='-' && !iname[1]) )) - return m_strdup("-"); - - n = strlen(iname); - if( n > 4 && ( !CMP_FILENAME(iname+n-4, EXTSEP_S "gpg") - || !CMP_FILENAME(iname+n-4, EXTSEP_S "pgp") - || !CMP_FILENAME(iname+n-4, EXTSEP_S "sig") - || !CMP_FILENAME(iname+n-4, EXTSEP_S "asc") ) ) { - char *buf = m_strdup( iname ); - buf[n-4] = 0; - return buf; - } - else if( n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign") ) { - char *buf = m_strdup( iname ); - buf[n-5] = 0; - return buf; - } - - log_info(_("%s: unknown suffix\n"), iname ); - return NULL; -} - - -/**************** - * Ask for a outputfilename and use the given one as default. - * Return NULL if no file has been given or it is not possible to - * ask the user. - */ -char * -ask_outfile_name( const char *name, size_t namelen ) -{ - size_t n; - const char *s; - char *prompt; - char *fname; - char *defname; - - if( opt.batch ) - return NULL; - - s = _("Enter new filename"); - - n = strlen(s) + namelen + 10; - defname = name && namelen? make_printable_string( name, namelen, 0): NULL; - prompt = m_alloc(n); - if( defname ) - sprintf(prompt, "%s [%s]: ", s, defname ); - else - sprintf(prompt, "%s: ", s ); - fname = cpr_get("openfile.askoutname", prompt ); - cpr_kill_prompt(); - m_free(prompt); - if( !*fname ) { - m_free( fname ); fname = NULL; - fname = defname; defname = NULL; - } - m_free(defname); - if (fname) - trim_spaces (fname); - return fname; -} - - - -/**************** - * Make an output filename for the inputfile INAME. - * Returns an IOBUF and an errorcode - * Mode 0 = use ".gpg" - * 1 = use ".asc" - * 2 = use ".sig" - */ -int -open_outfile( const char *iname, int mode, IOBUF *a ) -{ - int rc = 0; - - *a = NULL; - if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) { - if( !(*a = iobuf_create(NULL)) ) { - log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) ); - rc = G10ERR_CREATE_FILE; - } - else if( opt.verbose ) - log_info(_("writing to stdout\n")); - } - else { - char *buf=NULL; - const char *name; - - if( opt.dry_run ) - name = "/dev/null"; - else if( opt.outfile ) - name = opt.outfile; - else { - #ifdef USE_ONLY_8DOT3 - /* It is quite common DOS system to have only one dot in a - * a filename So if we have something like this, we simple - * replace the suffix execpt in cases where the suffix is - * larger than 3 characters and not the same as. - * We should really map the filenames to 8.3 but this tends to - * be more complicated and is probaly a duty of the filesystem - */ - char *dot; - const char *newsfx = mode==1 ? ".asc" : - mode==2 ? ".sig" : ".gpg"; - - buf = m_alloc(strlen(iname)+4+1); - strcpy(buf,iname); - dot = strchr(buf, '.' ); - if( dot && dot > buf && dot[1] && strlen(dot) <= 4 - && CMP_FILENAME(newsfx, dot) ) { - strcpy(dot, newsfx ); - } - else if( dot && !dot[1] ) /* don't duplicate a dot */ - strcpy( dot, newsfx+1 ); - else - strcat( buf, newsfx ); - #else - buf = m_alloc(strlen(iname)+4+1); - strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" : - mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"); - #endif - name = buf; - } - - rc = 0; - while( !overwrite_filep (name) ) { - char *tmp = ask_outfile_name (NULL, 0); - if ( !tmp || !*tmp ) { - m_free (tmp); - rc = G10ERR_FILE_EXISTS; - break; - } - m_free (buf); - name = buf = tmp; - } - - if( !rc ) { - if( !(*a = iobuf_create( name )) ) { - log_error(_("%s: can't create: %s\n"), name, strerror(errno) ); - rc = G10ERR_CREATE_FILE; - } - else if( opt.verbose ) - log_info(_("writing to `%s'\n"), name ); - } - m_free(buf); - } - return rc; -} - - - -/**************** - * Try to open a file without the extension ".sig" or ".asc" - * Return NULL if such a file is not available. - */ -IOBUF -open_sigfile( const char *iname ) -{ - IOBUF a = NULL; - size_t len; - - if( iname && !(*iname == '-' && !iname[1]) ) { - len = strlen(iname); - if( len > 4 && ( !strcmp(iname + len - 4, EXTSEP_S "sig") - || ( len > 5 && !strcmp(iname + len - 5, EXTSEP_S "sign") ) - || !strcmp(iname + len - 4, EXTSEP_S "asc")) ) { - char *buf; - buf = m_strdup(iname); - buf[len-(buf[len-1]=='n'?5:4)] = 0 ; - a = iobuf_open( buf ); - if( a && opt.verbose ) - log_info(_("assuming signed data in `%s'\n"), buf ); - m_free(buf); - } - } - return a; -} - - -/**************** - * Copy the option file skeleton to the given directory. - */ -static void -copy_options_file( const char *destdir ) -{ - const char *datadir = GNUPG_DATADIR; - char *fname; - FILE *src, *dst; - int linefeeds=0; - int c; - mode_t oldmask; - - if( opt.dry_run ) - return; - - fname = m_alloc( strlen(datadir) + strlen(destdir) + 15 ); - strcpy(stpcpy(fname, datadir), DIRSEP_S "options" SKELEXT ); - src = fopen( fname, "r" ); - if( !src ) { - log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); - m_free(fname); - return; - } - strcpy(stpcpy(fname, destdir), DIRSEP_S "gpg" EXTSEP_S "conf" ); - oldmask=umask(077); - dst = fopen( fname, "w" ); - umask(oldmask); - if( !dst ) { - log_error(_("%s: can't create: %s\n"), fname, strerror(errno) ); - fclose( src ); - m_free(fname); - return; - } - - while( (c=getc(src)) != EOF ) { - if( linefeeds < 3 ) { - if( c == '\n' ) - linefeeds++; - } - else - putc( c, dst ); - } - fclose( dst ); - fclose( src ); - log_info(_("new configuration file `%s' created\n"), fname ); - m_free(fname); -} - - -void -try_make_homedir( const char *fname ) -{ - const char *defhome = GNUPG_HOMEDIR; - - /* Create the directory only if the supplied directory name - * is the same as the default one. This way we avoid to create - * arbitrary directories when a non-default homedirectory is used. - * To cope with HOME, we do compare only the suffix if we see that - * the default homedir does start with a tilde. - */ - if( opt.dry_run || opt.no_homedir_creation ) - return; - - if ( ( *defhome == '~' - && ( strlen(fname) >= strlen (defhome+1) - && !strcmp(fname+strlen(fname)-strlen(defhome+1), - defhome+1 ) )) - || ( *defhome != '~' - && !compare_filenames( fname, defhome ) ) - ) { - if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) ) - log_fatal( _("%s: can't create directory: %s\n"), - fname, strerror(errno) ); - else if( !opt.quiet ) - log_info( _("%s: directory created\n"), fname ); - copy_options_file( fname ); -/* log_info(_("you have to start GnuPG again, " */ -/* "so it can read the new configuration file\n") ); */ -/* g10_exit(1); */ - } -} diff --git a/g10/options.h b/g10/options.h deleted file mode 100644 index 6be587ab8..000000000 --- a/g10/options.h +++ /dev/null @@ -1,208 +0,0 @@ -/* options.h - * 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 - */ -#ifndef G10_OPTIONS_H -#define G10_OPTIONS_H - -#include -#include "main.h" -#include "packet.h" - -#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */ - -#ifndef EXTERN_UNLESS_MAIN_MODULE -/* Norcraft can't cope with common symbols */ - #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 -struct { - int verbose; - int quiet; - unsigned debug; - int armor; - int compress; - char *outfile; - int dry_run; - int list_only; - int textmode; - int expert; - int ask_sig_expire; - int ask_cert_expire; - int batch; /* run in batch mode */ - int answer_yes; /* answer yes on most questions */ - int answer_no; /* answer no on most questions */ - int check_sigs; /* check key signatures */ - int with_colons; - int with_key_data; - int with_fingerprint; /* opt --with-fingerprint active */ - int fingerprint; /* list fingerprints */ - int list_sigs; /* list signatures */ - int no_armor; - int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/ - int def_cipher_algo; - int force_v3_sigs; - int force_v4_certs; - int force_mdc; - int disable_mdc; - int def_digest_algo; - int cert_digest_algo; - int def_compress_algo; - const char *def_secret_key; - char *def_recipient; - int def_recipient_self; - int def_cert_check_level; - int sk_comments; - int no_version; - int marginals_needed; - int completes_needed; - int max_cert_depth; - const char *homedir; - - char *display; /* 5 options to be passed to the gpg-agent */ - char *ttyname; - char *ttytype; - char *lc_ctype; - char *lc_messages; - - int skip_verify; - int compress_keys; - int compress_sigs; - int always_trust; - int pgp2; - int pgp6; - int pgp7; /* if we get any more of these, it's time to look at a - special emulate_pgp variable... */ - int rfc1991; - int rfc2440; - int pgp2_workarounds; - unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ - int shm_coprocess; - const char *set_filename; - const char *comment_string; - int throw_keyid; - int show_photos; - const char *photo_viewer; - int s2k_mode; - int s2k_digest_algo; - int s2k_cipher_algo; - int simple_sk_checksum; /* create the deprecated rfc2440 secret - key protection*/ - int not_dash_escaped; - int escape_from; - int lock_once; - char *keyserver_uri; - char *keyserver_scheme; - char *keyserver_host; - char *keyserver_port; - char *keyserver_opaque; - struct - { - int verbose; - int include_revoked; - int include_disabled; - int include_subkeys; - int honor_http_proxy; - int broken_http_proxy; - int use_temp_files; - int keep_temp_files; - int fake_v3_keyids; - int auto_key_retrieve; - unsigned int import_options; - unsigned int export_options; - STRLIST other; - } keyserver_options; - int exec_disable; - int exec_path_set; - unsigned int import_options; - unsigned int export_options; - char *def_preference_list; - prefitem_t *personal_cipher_prefs; - prefitem_t *personal_digest_prefs; - prefitem_t *personal_compress_prefs; - int no_perm_warn; - int no_mdc_warn; - char *temp_dir; - int no_encrypt_to; - int interactive; - STRLIST sig_notation_data; - STRLIST cert_notation_data; - int show_notation; - STRLIST sig_policy_url; - STRLIST cert_policy_url; - int show_policy_url; - int use_embedded_filename; - int allow_non_selfsigned_uid; - int allow_freeform_uid; - int no_literal; - ulong set_filesize; - int fast_list_mode; - int fixed_list_mode; - int ignore_time_conflict; - int ignore_valid_from; - int ignore_crc_error; - int ignore_mdc_error; - int command_fd; - const char *override_session_key; - int show_session_key; - int use_agent; - const char *gpg_agent_info; - int merge_only; - int try_all_secrets; - int no_expensive_trust_checks; - int no_sig_cache; - int no_sig_create_check; - int no_auto_check_trustdb; - int preserve_permissions; - int no_homedir_creation; - int show_keyring; - struct groupitem *grouplist; - int strict; -} opt; - - -#define EMUBUG_MDENCODE 4 - -#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ -#define DBG_MPI_VALUE 2 /* debug mpi details */ -#define DBG_CIPHER_VALUE 4 /* debug cipher handling */ - /* (may reveal sensitive data) */ -#define DBG_FILTER_VALUE 8 /* debug internal filter handling */ -#define DBG_IOBUF_VALUE 16 /* debug iobuf stuff */ -#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ -#define DBG_CACHE_VALUE 64 /* debug the cacheing */ -#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ -#define DBG_TRUST_VALUE 256 /* debug the trustdb */ -#define DBG_HASHING_VALUE 512 /* debug hashing operations */ -#define DBG_EXTPROG_VALUE 1024 /* debug external program calls */ - - -#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) -#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) -#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) -#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) -#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) -#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) - - -#endif /*G10_OPTIONS_H*/ diff --git a/g10/options.skel b/g10/options.skel deleted file mode 100644 index cbb7cdf82..000000000 --- a/g10/options.skel +++ /dev/null @@ -1,203 +0,0 @@ -These first three lines are not copied to the gpg.conf file in -the users home directory. -$Id$ -# Options for GnuPG -# Copyright 1998, 1999, 2000, 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. -# -# Unless you specify which option file to use (with the command line -# option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf -# by default. -# -# An options file can contain any long options which are available in -# GnuPG. If the first non white space character of a line is a '#', -# this line is ignored. Empty lines are also ignored. -# -# See the man page for a list of options. - -# Uncomment the following option to get rid of the copyright notice - -#no-greeting - -# If you have more than 1 secret key in your keyring, you may want to -# uncomment the following option and set your preferred keyid. - -#default-key 621CC013 - -# If you do not pass a recipient to gpg, it will ask for one. Using -# this option you can encrypt to a default key. Key validation will -# not be done in this case. The second form uses the default key as -# default recipient. - -#default-recipient some-user-id -#default-recipient-self - -# By default GnuPG creates version 3 signatures for data files. This -# is not strictly OpenPGP compliant but PGP 6 and most versions of PGP -# 7 require them. To disable this behavior, you may use this option -# or --openpgp. - -#no-force-v3-sigs - -# Because some mailers change lines starting with "From " to ">From " -# it is good to handle such lines in a special way when creating -# cleartext signatures; all other PGP versions do it this way too. -# To enable full OpenPGP compliance you may want to use this option. - -#no-escape-from-lines - -# If you do not use the Latin-1 (ISO-8859-1) charset, you should tell -# GnuPG which is the native character set. Please check the man page -# for supported character sets. This character set is only used for -# Meta data and not for the actual message which does not undergo any -# translation. Note that future version of GnuPG will change to UTF-8 -# as default character set. - -#charset utf-8 - -# Group names may be defined like this: -# group mynames paige 0x12345678 joe patti -# -# Any time "mynames" is a recipient (-r or --recipient), it will be -# expanded to the names "paige", "joe", and "patti", and the key ID -# "0x12345678". Note there is only one level of expansion - you -# cannot make an group that points to another group. Note also that -# if there are spaces in the recipient name, this will appear as two -# recipients. In these cases it is better to use the key ID. - -#group mynames paige 0x12345678 joe patti - -# Lock the file only once for the lifetime of a process. If you do -# not define this, the lock will be obtained and released every time -# it is needed - normally this is not needed. - -#lock-once - -# GnuPG can send and receive keys to and from a keyserver. These -# servers can be HKP, email, or LDAP (if GnuPG is built with LDAP -# support). -# -# Example HKP keyserver: -# x-hkp://pgp.mit.edu -# -# Example email keyserver: -# mailto:pgp-public-keys@keys.nl.pgp.net -# -# Example LDAP keyservers: -# ldap://pgp.surfnet.nl:11370 -# ldap://keyserver.pgp.com -# -# Regular URL syntax applies, and you can set an alternate port -# through the usual method: -# x-hkp://keyserver.example.net:22742 -# -# If you have problems connecting to a HKP server through a buggy http -# proxy, you can use keyserver option broken-http-proxy (see below), -# but first you should make sure that you have read the man page -# regarding proxies (keyserver option honor-http-proxy) -# -# Most users just set the name and type of their preferred keyserver. -# Most servers do synchronize with each other and DNS round-robin may -# give you a quasi-random server each time. - -#keyserver x-hkp://pgp.mit.edu -#keyserver mailto:pgp-public-keys@keys.nl.pgp.net -#keyserver ldap://pgp.surfnet.nl:11370 -#keyserver ldap://keyserver.pgp.com - -# Common options for keyserver functions: -# -# include-disabled = when searching, include keys marked as "disabled" -# on the keyserver (not all keyservers support this). -# -# no-include-revoked = when searching, do not include keys marked as -# "revoked" on the keyserver. -# -# verbose = show more information as the keys are fetched. -# Can be used more than once to increase the amount -# of information shown. -# -# use-temp-files = use temporary files instead of a pipe to talk to the -# keyserver. Some platforms (Win32 for one) always -# have this on. -# -# keep-temp-files = do not delete temporary files after using them -# (really only useful for debugging) -# -# honor-http-proxy = if the keyserver uses HTTP, honor the http_proxy -# environment variable -# -# broken-http-proxy = try to work around a buggy HTTP proxy -# -# auto-key-retrieve = automatically fetch keys as needed from the keyserver -# when verifying signatures or when importing keys that -# have been revoked by a revocation key that is not -# present on the keyring. -# -# no-include-attributes = do not include attribute IDs (aka "photo IDs") -# when sending keys to the keyserver. - -#keyserver-options auto-key-retrieve - -# Uncomment this line to display photo user IDs in key listings and -# when a signature from a key with a photo is verified. - -#show-photos - -# Use this program to display photo user IDs -# -# %i is expanded to a temporary file that contains the photo. -# %I is the same as %i, but the file isn't deleted afterwards by GnuPG. -# %k is expanded to the key ID of the key. -# %K is expanded to the long OpenPGP key ID of the key. -# %t is expanded to the extension of the image (e.g. "jpg"). -# %T is expanded to the MIME type of the image (e.g. "image/jpeg"). -# %f is expanded to the fingerprint of the key. -# %% is %, of course. -# -# If %i or %I are not present, then the photo is supplied to the -# viewer on standard input. If your platform supports it, standard -# input is the best way to do this as it avoids the time and effort in -# generating and then cleaning up a secure temp file. -# -# The default program is "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin" -# On Mac OS X and Windows, the default is to use your regular image viewer. -# -# Some other viewers: -# photo-viewer "qiv %i" -# photo-viewer "ee %i" -# photo-viewer "display -title 'KeyID 0x%k'" -# -# This one saves a copy of the photo ID in your home directory: -# photo-viewer "cat > ~/photoid-for-key-%k.%t" -# -# Use your MIME handler to view photos: -# photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG" - - -# Passphrase agent -# -# We support the old experimental passphrase agent protocol as well -# as the new Assuan based one (currently available in the "newpg" package -# at ftp.gnupg.org/gcrypt/alpha/aegypten/). To make use of the agent, you have -# to run an agent as daemon and use the option -# -# use-agent -# -# which tries to use the agent but will fallback to the regular mode -# if there is a problem connecting to the agent. The normal way to -# locate the agent is by looking at the environment variable -# GPG_AGENT_INFO which should have been set during gpg-agent startup. -# In certain situations the use of this variable is not possible, thus -# the option -# -# --gpg-agent-info=::1 -# -# may be used to override it. diff --git a/g10/packet.h b/g10/packet.h deleted file mode 100644 index fdca455a1..000000000 --- a/g10/packet.h +++ /dev/null @@ -1,494 +0,0 @@ -/* packet.h - packet definitions - * 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 - */ - -#ifndef G10_PACKET_H -#define G10_PACKET_H - -#include "types.h" -#include "iobuf.h" -#include "mpi.h" -#include "cipher.h" -#include "filter.h" -#include "global.h" - -#define DEBUG_PARSE_PACKET 1 - -typedef enum { - PKT_NONE =0, - PKT_PUBKEY_ENC =1, /* public key encrypted packet */ - PKT_SIGNATURE =2, /* secret key encrypted packet */ - PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/ - PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/ - PKT_SECRET_KEY =5, /* secret key */ - PKT_PUBLIC_KEY =6, /* public key */ - PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */ - PKT_COMPRESSED =8, /* compressed data packet */ - PKT_ENCRYPTED =9, /* conventional encrypted data */ - PKT_MARKER =10, /* marker packet (OpenPGP) */ - PKT_PLAINTEXT =11, /* plaintext data with filename and mode */ - PKT_RING_TRUST =12, /* keyring trust packet */ - PKT_USER_ID =13, /* user id packet */ - PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */ - PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */ - PKT_ATTRIBUTE =17, /* PGP's attribute packet */ - PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */ - PKT_MDC =19, /* manipulaion detection code packet */ - PKT_COMMENT =61, /* new comment packet (private) */ - PKT_GPG_CONTROL =63 /* internal control packet */ -} pkttype_t; - -typedef struct packet_struct PACKET; - -/* PKT_GPG_CONTROL types */ -typedef enum { - CTRLPKT_CLEARSIGN_START = 1, - CTRLPKT_PIPEMODE = 2, - CTRLPKT_PLAINTEXT_MARK =3 -} ctrlpkttype_t; - -typedef enum { - PREFTYPE_NONE = 0, - PREFTYPE_SYM = 1, - PREFTYPE_HASH = 2, - PREFTYPE_ZIP = 3 -} preftype_t; - -typedef struct { - byte type; - byte value; -} prefitem_t; - -typedef struct { - int mode; - byte hash_algo; - byte salt[8]; - u32 count; -} STRING2KEY; - -typedef struct { - byte version; - byte cipher_algo; /* cipher algorithm used */ - STRING2KEY s2k; - byte seskeylen; /* keylength in byte or 0 for no seskey */ - byte seskey[1]; -} PKT_symkey_enc; - -typedef struct { - u32 keyid[2]; /* 64 bit keyid */ - byte version; - byte pubkey_algo; /* algorithm used for public key scheme */ - byte throw_keyid; - MPI data[PUBKEY_MAX_NENC]; -} PKT_pubkey_enc; - - -typedef struct { - u32 keyid[2]; /* 64 bit keyid */ - byte sig_class; /* sig classification */ - byte digest_algo; /* algorithm used for digest */ - byte pubkey_algo; /* algorithm used for public key scheme */ - byte last; /* a stupid flag */ -} PKT_onepass_sig; - - -typedef struct { - size_t size; /* allocated */ - size_t len; /* used */ - byte data[1]; -} subpktarea_t; - -struct revocation_key { - byte class; - byte algid; - byte fpr[MAX_FINGERPRINT_LEN]; -}; - -typedef struct { - ulong local_id; /* internal use, valid if > 0 */ - struct { - unsigned checked:1; /* signature has been checked */ - unsigned valid:1; /* signature is good (if checked is set) */ - unsigned unknown_critical:1; - unsigned exportable:1; - unsigned revocable:1; - unsigned policy_url:1; /* Policy URL is present */ - unsigned notation:1; /* At least one notation is present */ - unsigned expired:1; - } flags; - u32 keyid[2]; /* 64 bit keyid */ - u32 timestamp; /* signature made */ - u32 expiredate; /* expires at this date or 0 if not at all */ - byte version; - byte sig_class; /* sig classification, append for MD calculation*/ - byte pubkey_algo; /* algorithm used for public key scheme */ - /* (PUBKEY_ALGO_xxx) */ - byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */ - struct revocation_key **revkey; - int numrevkeys; - subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */ - subpktarea_t *unhashed; /* ditto for unhashed data */ - byte digest_start[2]; /* first 2 bytes of the digest */ - MPI data[PUBKEY_MAX_NSIG]; -} PKT_signature; - -#define ATTRIB_IMAGE 1 - -/* This is the cooked form of attributes */ -struct user_attribute { - byte type; - const byte *data; - u32 len; -}; - -typedef struct { - int ref; /* reference counter */ - int len; /* length of the name */ - struct user_attribute *attribs; - int numattribs; - byte *attrib_data; /* if this is not NULL, the packet is an attribute */ - unsigned long attrib_len; - int help_key_usage; - u32 help_key_expire; - int is_primary; - int is_revoked; - int is_expired; - u32 expiredate; /* expires at this date or 0 if not at all */ - prefitem_t *prefs; /* list of preferences (may be NULL)*/ - int mdc_feature; - u32 created; /* according to the self-signature */ - byte selfsigversion; - char name[1]; -} PKT_user_id; - - -/**************** - * Note about the pkey/skey elements: We assume that the secret keys - * has the same elemts as the public key at the begin of the array, so - * that npkey < nskey and it is possible to compare the secret and - * public keys by comparing the first npkey elements of pkey againts skey. - */ -typedef struct { - u32 timestamp; /* key made */ - u32 expiredate; /* expires at this date or 0 if not at all */ - u32 max_expiredate; /* must not expire past this date */ - byte hdrbytes; /* number of header bytes */ - byte version; - byte selfsigversion; /* highest version of all of the self-sigs */ - byte pubkey_algo; /* algorithm used for public key scheme */ - byte pubkey_usage; /* for now only used to pass it to getkey() */ - byte req_usage; /* hack to pass a request to getkey() */ - byte req_algo; /* Ditto */ - u32 has_expired; /* set to the expiration date if expired */ - int is_revoked; /* key has been revoked */ - int is_valid; /* key (especially subkey) is valid */ - int dont_cache; /* do not cache this */ - ulong local_id; /* internal use, valid if > 0 */ - u32 main_keyid[2]; /* keyid of the primary key */ - u32 keyid[2]; /* calculated by keyid_from_pk() */ - byte is_primary; - prefitem_t *prefs; /* list of preferences (may be NULL) */ - int mdc_feature; /* mdc feature set */ - byte *namehash; /* if != NULL: found by this name */ - PKT_user_id *user_id; /* if != NULL: found by that uid */ - struct revocation_key *revkey; - int numrevkeys; - MPI pkey[PUBKEY_MAX_NPKEY]; -} PKT_public_key; - -typedef struct { - u32 timestamp; /* key made */ - u32 expiredate; /* expires at this date or 0 if not at all */ - u32 max_expiredate; /* must not expire past this date */ - byte hdrbytes; /* number of header bytes */ - byte version; - byte pubkey_algo; /* algorithm used for public key scheme */ - byte pubkey_usage; - byte req_usage; - byte req_algo; - u32 has_expired; /* set to the expiration date if expired */ - int is_revoked; /* key has been revoked */ - int is_valid; /* key (especially subkey) is valid */ - u32 main_keyid[2]; /* keyid of the primary key */ - u32 keyid[2]; - byte is_primary; - byte is_protected; /* The secret info is protected and must */ - /* be decrypted before use, the protected */ - /* MPIs are simply (void*) pointers to memory */ - /* and should never be passed to a mpi_xxx() */ - struct { - byte algo; /* cipher used to protect the secret information*/ - byte sha1chk; /* SHA1 is used instead of a 16 bit checksum */ - STRING2KEY s2k; - byte ivlen; /* used length of the iv */ - byte iv[16]; /* initialization vector for CFB mode */ - } protect; - MPI skey[PUBKEY_MAX_NSKEY]; - u16 csum; /* checksum */ -} PKT_secret_key; - - -typedef struct { - int len; /* length of data */ - char data[1]; -} PKT_comment; - -typedef struct { - u32 len; /* reserved */ - byte new_ctb; - byte algorithm; - IOBUF buf; /* IOBUF reference */ -} PKT_compressed; - -typedef struct { - u32 len; /* length of encrypted data */ - int extralen; /* this is (blocksize+2) */ - byte new_ctb; /* uses a new CTB */ - byte mdc_method; /* > 0: integrity protected encrypted data packet */ - IOBUF buf; /* IOBUF reference */ -} PKT_encrypted; - -typedef struct { - byte hash[20]; -} PKT_mdc; - -typedef struct { - unsigned int trustval; - unsigned int sigcache; -} PKT_ring_trust; - -typedef struct { - u32 len; /* length of encrypted data */ - IOBUF buf; /* IOBUF reference */ - byte new_ctb; - byte is_partial; /* partial length encoded */ - int mode; - u32 timestamp; - int namelen; - char name[1]; -} PKT_plaintext; - -typedef struct { - int control; - size_t datalen; - char data[1]; -} PKT_gpg_control; - -/* combine all packets into a union */ -struct packet_struct { - pkttype_t pkttype; - union { - void *generic; - PKT_symkey_enc *symkey_enc; /* PKT_SYMKEY_ENC */ - PKT_pubkey_enc *pubkey_enc; /* PKT_PUBKEY_ENC */ - PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */ - PKT_signature *signature; /* PKT_SIGNATURE */ - PKT_public_key *public_key; /* PKT_PUBLIC_[SUB)KEY */ - PKT_secret_key *secret_key; /* PKT_SECRET_[SUB]KEY */ - PKT_comment *comment; /* PKT_COMMENT */ - PKT_user_id *user_id; /* PKT_USER_ID */ - PKT_compressed *compressed; /* PKT_COMPRESSED */ - PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */ - PKT_mdc *mdc; /* PKT_MDC */ - PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */ - PKT_plaintext *plaintext; /* PKT_PLAINTEXT */ - PKT_gpg_control *gpg_control; /* PKT_GPG_CONTROL */ - } pkt; -}; - -#define init_packet(a) do { (a)->pkttype = 0; \ - (a)->pkt.generic = NULL; \ - } while(0) - -typedef enum { - SIGSUBPKT_TEST_CRITICAL=-3, - SIGSUBPKT_LIST_UNHASHED=-2, - SIGSUBPKT_LIST_HASHED =-1, - SIGSUBPKT_NONE = 0, - SIGSUBPKT_SIG_CREATED = 2, /* signature creation time */ - SIGSUBPKT_SIG_EXPIRE = 3, /* signature expiration time */ - SIGSUBPKT_EXPORTABLE = 4, /* exportable */ - SIGSUBPKT_TRUST = 5, /* trust signature */ - SIGSUBPKT_REGEXP = 6, /* regular expression */ - SIGSUBPKT_REVOCABLE = 7, /* revocable */ - SIGSUBPKT_KEY_EXPIRE = 9, /* key expiration time */ - SIGSUBPKT_ARR =10, /* additional recipient request */ - SIGSUBPKT_PREF_SYM =11, /* preferred symmetric algorithms */ - SIGSUBPKT_REV_KEY =12, /* revocation key */ - SIGSUBPKT_ISSUER =16, /* issuer key ID */ - SIGSUBPKT_NOTATION =20, /* notation data */ - SIGSUBPKT_PREF_HASH =21, /* preferred hash algorithms */ - SIGSUBPKT_PREF_COMPR =22, /* preferred compression algorithms */ - SIGSUBPKT_KS_FLAGS =23, /* key server preferences */ - SIGSUBPKT_PREF_KS =24, /* preferred key server */ - SIGSUBPKT_PRIMARY_UID =25, /* primary user id */ - SIGSUBPKT_POLICY =26, /* policy URL */ - SIGSUBPKT_KEY_FLAGS =27, /* key flags */ - SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ - SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ - SIGSUBPKT_FEATURES =30, /* feature flags */ - SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result (obsolete)*/ - - SIGSUBPKT_FLAG_CRITICAL=128 -} sigsubpkttype_t; - - -/*-- mainproc.c --*/ -int proc_packets( void *ctx, IOBUF a ); -int proc_signature_packets( void *ctx, IOBUF a, - STRLIST signedfiles, const char *sigfile ); -int proc_encryption_packets( void *ctx, IOBUF a ); -int list_packets( IOBUF a ); - -/*-- parse-packet.c --*/ -int set_packet_list_mode( int mode ); - -#if DEBUG_PARSE_PACKET -int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, - const char* file, int lineno ); -int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, - const char* file, int lineno ); -int dbg_copy_all_packets( IOBUF inp, IOBUF out, - const char* file, int lineno ); -int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, - const char* file, int lineno ); -int dbg_skip_some_packets( IOBUF inp, unsigned n, - const char* file, int lineno ); -#define search_packet( a,b,c,d ) \ - dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) -#define parse_packet( a, b ) \ - dbg_parse_packet( (a), (b), __FILE__, __LINE__ ) -#define copy_all_packets( a,b ) \ - dbg_copy_all_packets((a),(b), __FILE__, __LINE__ ) -#define copy_some_packets( a,b,c ) \ - dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ ) -#define skip_some_packets( a,b ) \ - dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) -#else -int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ); -int parse_packet( IOBUF inp, PACKET *ret_pkt); -int copy_all_packets( IOBUF inp, IOBUF out ); -int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ); -int skip_some_packets( IOBUF inp, unsigned n ); -#endif - -const byte *enum_sig_subpkt ( const subpktarea_t *subpkts, - sigsubpkttype_t reqtype, - size_t *ret_n, int *start, int *critical ); -const byte *parse_sig_subpkt ( const subpktarea_t *buffer, - sigsubpkttype_t reqtype, - size_t *ret_n ); -const byte *parse_sig_subpkt2 ( PKT_signature *sig, - sigsubpkttype_t reqtype, - size_t *ret_n ); -int parse_one_sig_subpkt( const byte *buffer, size_t n, int type ); -void parse_revkeys(PKT_signature *sig); -int parse_attribute_subpkts(PKT_user_id *uid); -void make_attribute_uidname(PKT_user_id *uid, size_t max_namelen); -PACKET *create_gpg_control ( ctrlpkttype_t type, - const byte *data, - size_t datalen ); - -/*-- build-packet.c --*/ -int build_packet( IOBUF inp, PACKET *pkt ); -u32 calc_packet_length( PACKET *pkt ); -void hash_public_key( MD_HANDLE md, PKT_public_key *pk ); -void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, - const byte *buffer, size_t buflen ); -void build_sig_subpkt_from_sig( PKT_signature *sig ); -int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); -void build_attribute_subpkt(PKT_user_id *uid,byte type, - const void *buf,u32 buflen, - const void *header,u32 headerlen); - -/*-- free-packet.c --*/ -void free_symkey_enc( PKT_symkey_enc *enc ); -void free_pubkey_enc( PKT_pubkey_enc *enc ); -void free_seckey_enc( PKT_signature *enc ); -int digest_algo_from_sig( PKT_signature *sig ); -void release_public_key_parts( PKT_public_key *pk ); -void free_public_key( PKT_public_key *key ); -void release_secret_key_parts( PKT_secret_key *sk ); -void free_secret_key( PKT_secret_key *sk ); -void free_attributes(PKT_user_id *uid); -void free_user_id( PKT_user_id *uid ); -void free_comment( PKT_comment *rem ); -void free_packet( PACKET *pkt ); -prefitem_t *copy_prefs (const prefitem_t *prefs); -PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); -void copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk ); -PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ); -PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); -PKT_user_id *scopy_user_id (PKT_user_id *sd ); -int cmp_public_keys( PKT_public_key *a, PKT_public_key *b ); -int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b ); -int cmp_signatures( PKT_signature *a, PKT_signature *b ); -int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk ); -int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); - - -/*-- sig-check.c --*/ -int signature_check( PKT_signature *sig, MD_HANDLE digest ); -int signature_check2( PKT_signature *sig, MD_HANDLE digest, - u32 *r_expiredate, int *r_expired ); - -/*-- seckey-cert.c --*/ -int is_secret_key_protected( PKT_secret_key *sk ); -int check_secret_key( PKT_secret_key *sk, int retries ); -int protect_secret_key( PKT_secret_key *sk, DEK *dek ); - -/*-- pubkey-enc.c --*/ -int get_session_key( PKT_pubkey_enc *k, DEK *dek ); -int get_override_session_key( DEK *dek, const char *string ); - -/*-- compress.c --*/ -int handle_compressed( void *ctx, PKT_compressed *cd, - int (*callback)(IOBUF, void *), void *passthru ); - -/*-- encr-data.c --*/ -int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek ); - -/*-- plaintext.c --*/ -int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, - int nooutput, int clearsig ); -int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, - const char *inname, int textmode ); - -/*-- comment.c --*/ -int write_comment( IOBUF out, const char *s ); - -/*-- sign.c --*/ -int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, - PKT_user_id *uid, PKT_public_key *subpk, - PKT_secret_key *sk, int sigclass, int digest_algo, - int sigversion, u32 timestamp, u32 duration, - int (*mksubpkt)(PKT_signature *, void *), - void *opaque ); -int update_keysig_packet( PKT_signature **ret_sig, - PKT_signature *orig_sig, - PKT_public_key *pk, - PKT_user_id *uid, - PKT_secret_key *sk, - int (*mksubpkt)(PKT_signature *, void *), - void *opaque ); - -/*-- keygen.c --*/ -PKT_user_id *generate_user_id(void); - -#endif /*G10_PACKET_H*/ diff --git a/g10/parse-packet.c b/g10/parse-packet.c deleted file mode 100644 index bce3ce308..000000000 --- a/g10/parse-packet.c +++ /dev/null @@ -1,2260 +0,0 @@ -/* parse-packet.c - read packets - * 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 -#include -#include -#include -#include - -#include "packet.h" -#include "iobuf.h" -#include "mpi.h" -#include "util.h" -#include "cipher.h" -#include "memory.h" -#include "filter.h" -#include "photoid.h" -#include "options.h" -#include "main.h" -#include "i18n.h" - -static int mpi_print_mode = 0; -static int list_mode = 0; - -static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts, - off_t *retpos, int *skip, IOBUF out, int do_skip - #ifdef DEBUG_PARSE_PACKET - ,const char *dbg_w, const char *dbg_f, int dbg_l - #endif - ); -static int copy_packet( IOBUF inp, IOBUF out, int pkttype, - unsigned long pktlen ); -static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ); -static void skip_rest( IOBUF inp, unsigned long pktlen ); -static void *read_rest( IOBUF inp, size_t pktlen ); -static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); -static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); -static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, - PKT_signature *sig ); -static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, - PKT_onepass_sig *ops ); -static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, - byte *hdr, int hdrlen, PACKET *packet ); -static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); -static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); -static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); -static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); -static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet, int new_ctb); -static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet, int new_ctb ); -static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet, int new_ctb); -static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet, int new_ctb); -static int parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *packet ); - -static unsigned short -read_16(IOBUF inp) -{ - unsigned short a; - a = iobuf_get_noeof(inp) << 8; - a |= iobuf_get_noeof(inp); - return a; -} - -static unsigned long -read_32(IOBUF inp) -{ - unsigned long a; - a = iobuf_get_noeof(inp) << 24; - a |= iobuf_get_noeof(inp) << 16; - a |= iobuf_get_noeof(inp) << 8; - a |= iobuf_get_noeof(inp); - return a; -} - - -int -set_packet_list_mode( int mode ) -{ - int old = list_mode; - list_mode = mode; - mpi_print_mode = DBG_MPI; - return old; -} - -static void -unknown_pubkey_warning( int algo ) -{ - static byte unknown_pubkey_algos[256]; - - algo &= 0xff; - if( !unknown_pubkey_algos[algo] ) { - if( opt.verbose ) - log_info(_("can't handle public key algorithm %d\n"), algo ); - unknown_pubkey_algos[algo] = 1; - } -} - -/**************** - * Parse a Packet and return it in packet - * Returns: 0 := valid packet in pkt - * -1 := no more packets - * >0 := error - * Note: The function may return an error and a partly valid packet; - * caller must free this packet. - */ -#ifdef DEBUG_PARSE_PACKET -int -dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l ) -{ - int skip, rc; - - do { - rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l ); - } while( skip ); - return rc; -} -#else -int -parse_packet( IOBUF inp, PACKET *pkt ) -{ - int skip, rc; - - do { - rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 ); - } while( skip ); - return rc; -} -#endif - -/**************** - * Like parse packet, but only return secret or public (sub)key packets. - */ -#ifdef DEBUG_PARSE_PACKET -int -dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, - const char *dbg_f, int dbg_l ) -{ - int skip, rc; - - do { - rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l ); - } while( skip ); - return rc; -} -#else -int -search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ) -{ - int skip, rc; - - do { - rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0 ); - } while( skip ); - return rc; -} -#endif - -/**************** - * Copy all packets from INP to OUT, thereby removing unused spaces. - */ -#ifdef DEBUG_PARSE_PACKET -int -dbg_copy_all_packets( IOBUF inp, IOBUF out, - const char *dbg_f, int dbg_l ) -{ - PACKET pkt; - int skip, rc=0; - do { - init_packet(&pkt); - } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l ))); - return rc; -} -#else -int -copy_all_packets( IOBUF inp, IOBUF out ) -{ - PACKET pkt; - int skip, rc=0; - do { - init_packet(&pkt); - } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 ))); - return rc; -} -#endif - -/**************** - * Copy some packets from INP to OUT, thereby removing unused spaces. - * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets) - */ -#ifdef DEBUG_PARSE_PACKET -int -dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, - const char *dbg_f, int dbg_l ) -{ - PACKET pkt; - int skip, rc=0; - do { - if( iobuf_tell(inp) >= stopoff ) - return 0; - init_packet(&pkt); - } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, - "some", dbg_f, dbg_l )) ); - return rc; -} -#else -int -copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ) -{ - PACKET pkt; - int skip, rc=0; - do { - if( iobuf_tell(inp) >= stopoff ) - return 0; - init_packet(&pkt); - } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) ); - return rc; -} -#endif - -/**************** - * Skip over N packets - */ -#ifdef DEBUG_PARSE_PACKET -int -dbg_skip_some_packets( IOBUF inp, unsigned n, - const char *dbg_f, int dbg_l ) -{ - int skip, rc=0; - PACKET pkt; - - for( ;n && !rc; n--) { - init_packet(&pkt); - rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l ); - } - return rc; -} -#else -int -skip_some_packets( IOBUF inp, unsigned n ) -{ - int skip, rc=0; - PACKET pkt; - - for( ;n && !rc; n--) { - init_packet(&pkt); - rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 ); - } - return rc; -} -#endif - - -/**************** - * Parse packet. Set the variable skip points to 1 if the packet - * should be skipped; this is the case if either ONLYKEYPKTS is set - * and the parsed packet isn't one or the - * packet-type is 0, indicating deleted stuff. - * if OUT is not NULL, a special copymode is used. - */ -static int -parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, - int *skip, IOBUF out, int do_skip -#ifdef DEBUG_PARSE_PACKET - ,const char *dbg_w, const char *dbg_f, int dbg_l -#endif - ) -{ - int rc=0, c, ctb, pkttype, lenbytes; - unsigned long pktlen; - byte hdr[8]; - int hdrlen; - int new_ctb = 0; - int with_uid = (onlykeypkts == 2); - - *skip = 0; - assert( !pkt->pkt.generic ); - if( retpos ) - *retpos = iobuf_tell(inp); - - if( (ctb = iobuf_get(inp)) == -1 ) { - rc = -1; - goto leave; - } - hdrlen=0; - hdr[hdrlen++] = ctb; - if( !(ctb & 0x80) ) { - log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - pktlen = 0; - new_ctb = !!(ctb & 0x40); - if( new_ctb ) { - pkttype = ctb & 0x3f; - if( (c = iobuf_get(inp)) == -1 ) { - log_error("%s: 1st length byte missing\n", iobuf_where(inp) ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - if (pkttype == PKT_COMPRESSED) { - iobuf_set_partial_block_mode(inp, c & 0xff); - pktlen = 0;/* to indicate partial length */ - } - else { - hdr[hdrlen++] = c; - if( c < 192 ) - pktlen = c; - else if( c < 224 ) { - pktlen = (c - 192) * 256; - if( (c = iobuf_get(inp)) == -1 ) { - log_error("%s: 2nd length byte missing\n", - iobuf_where(inp) ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - hdr[hdrlen++] = c; - pktlen += c + 192; - } - else if( c == 255 ) { - pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24; - pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16; - pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8; - if( (c = iobuf_get(inp)) == -1 ) { - log_error("%s: 4 byte length invalid\n", - iobuf_where(inp) ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - pktlen |= (hdr[hdrlen++] = c ); - } - else { /* partial body length */ - iobuf_set_partial_block_mode(inp, c & 0xff); - pktlen = 0;/* to indicate partial length */ - } - } - } - else { - pkttype = (ctb>>2)&0xf; - lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); - if( !lenbytes ) { - pktlen = 0; /* don't know the value */ - if( pkttype != PKT_COMPRESSED ) - iobuf_set_block_mode(inp, 1); - } - else { - for( ; lenbytes; lenbytes-- ) { - pktlen <<= 8; - pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp); - } - } - } - - if (pktlen == 0xffffffff) { - /* with a some probability this is caused by a problem in the - * the uncompressing layer - in some error cases it just loops - * and spits out 0xff bytes. */ - log_error ("%s: garbled packet detected\n", iobuf_where(inp) ); - g10_exit (2); - } - - if( out && pkttype ) { - if( iobuf_write( out, hdr, hdrlen ) == -1 ) - rc = G10ERR_WRITE_FILE; - else - rc = copy_packet(inp, out, pkttype, pktlen ); - goto leave; - } - - if (with_uid && pkttype == PKT_USER_ID) - ; - else if( do_skip - || !pkttype - || (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY - && pkttype != PKT_PUBLIC_KEY - && pkttype != PKT_SECRET_SUBKEY - && pkttype != PKT_SECRET_KEY ) ) { - skip_rest(inp, pktlen); - *skip = 1; - rc = 0; - goto leave; - } - - if( DBG_PACKET ) { -#ifdef DEBUG_PARSE_PACKET - log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n", - iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"", - dbg_w, dbg_f, dbg_l ); -#else - log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n", - iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" ); -#endif - } - pkt->pkttype = pkttype; - rc = G10ERR_UNKNOWN_PACKET; /* default error */ - switch( pkttype ) { - case PKT_PUBLIC_KEY: - case PKT_PUBLIC_SUBKEY: - pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key ); - rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); - break; - case PKT_SECRET_KEY: - case PKT_SECRET_SUBKEY: - pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key ); - rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); - break; - case PKT_SYMKEY_ENC: - rc = parse_symkeyenc( inp, pkttype, pktlen, pkt ); - break; - case PKT_PUBKEY_ENC: - rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt ); - break; - case PKT_SIGNATURE: - pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature ); - rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); - break; - case PKT_ONEPASS_SIG: - pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig ); - rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig ); - break; - case PKT_USER_ID: - rc = parse_user_id(inp, pkttype, pktlen, pkt ); - break; - case PKT_ATTRIBUTE: - pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */ - rc = parse_attribute(inp, pkttype, pktlen, pkt); - break; - case PKT_OLD_COMMENT: - case PKT_COMMENT: - rc = parse_comment(inp, pkttype, pktlen, pkt); - break; - case PKT_RING_TRUST: - parse_trust(inp, pkttype, pktlen, pkt); - rc = 0; - break; - case PKT_PLAINTEXT: - rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb ); - break; - case PKT_COMPRESSED: - rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb ); - break; - case PKT_ENCRYPTED: - case PKT_ENCRYPTED_MDC: - rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb ); - break; - case PKT_MDC: - rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb ); - break; - case PKT_GPG_CONTROL: - rc = parse_gpg_control(inp, pkttype, pktlen, pkt ); - break; - default: - skip_packet(inp, pkttype, pktlen); - break; - } - - leave: - if( !rc && iobuf_error(inp) ) - rc = G10ERR_INV_KEYRING; - return rc; -} - -static void -dump_hex_line( int c, int *i ) -{ - if( *i && !(*i%8) ) { - if( *i && !(*i%24) ) - printf("\n%4d:", *i ); - else - putchar(' '); - } - if( c == -1 ) - printf(" EOF" ); - else - printf(" %02x", c ); - ++*i; -} - - -static int -copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen ) -{ - int n; - char buf[100]; - - if( iobuf_in_block_mode(inp) ) { - while( (n = iobuf_read( inp, buf, 100 )) != -1 ) - if( iobuf_write(out, buf, n ) ) - return G10ERR_WRITE_FILE; /* write error */ - } - else if( !pktlen && pkttype == PKT_COMPRESSED ) { - log_debug("copy_packet: compressed!\n"); - /* compressed packet, copy till EOF */ - while( (n = iobuf_read( inp, buf, 100 )) != -1 ) - if( iobuf_write(out, buf, n ) ) - return G10ERR_WRITE_FILE; /* write error */ - } - else { - for( ; pktlen; pktlen -= n ) { - n = pktlen > 100 ? 100 : pktlen; - n = iobuf_read( inp, buf, n ); - if( n == -1 ) - return G10ERR_READ_FILE; - if( iobuf_write(out, buf, n ) ) - return G10ERR_WRITE_FILE; /* write error */ - } - } - return 0; -} - - -static void -skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) -{ - if( list_mode ) { - if( pkttype == PKT_MARKER ) - fputs(":marker packet:\n", stdout ); - else - printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen); - if( pkttype ) { - int c, i=0 ; - if( pkttype != PKT_MARKER ) - fputs("dump:", stdout ); - if( iobuf_in_block_mode(inp) ) { - while( (c=iobuf_get(inp)) != -1 ) - dump_hex_line(c, &i); - } - else { - for( ; pktlen; pktlen-- ) - dump_hex_line(iobuf_get(inp), &i); - } - putchar('\n'); - return; - } - } - skip_rest(inp,pktlen); -} - -static void -skip_rest( IOBUF inp, unsigned long pktlen ) -{ - if( iobuf_in_block_mode(inp) ) { - while( iobuf_get(inp) != -1 ) - ; - } - else { - for( ; pktlen; pktlen-- ) - if( iobuf_get(inp) == -1 ) - break; - } -} - - -static void * -read_rest( IOBUF inp, size_t pktlen ) -{ - byte *p; - int i; - - if( iobuf_in_block_mode(inp) ) { - log_error("read_rest: can't store stream data\n"); - p = NULL; - } - else { - p = m_alloc( pktlen ); - for(i=0; pktlen; pktlen--, i++ ) - p[i] = iobuf_get(inp); - } - return p; -} - - - -static int -parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) -{ - PKT_symkey_enc *k; - int rc = 0; - int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen; - - if( pktlen < 4 ) { - log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - version = iobuf_get_noeof(inp); pktlen--; - if( version != 4 ) { - log_error("packet(%d) with unknown version %d\n", pkttype, version); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */ - log_error("packet(%d) too large\n", pkttype); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - cipher_algo = iobuf_get_noeof(inp); pktlen--; - s2kmode = iobuf_get_noeof(inp); pktlen--; - hash_algo = iobuf_get_noeof(inp); pktlen--; - switch( s2kmode ) { - case 0: /* simple s2k */ - minlen = 0; - break; - case 1: /* salted s2k */ - minlen = 8; - break; - case 3: /* iterated+salted s2k */ - minlen = 9; - break; - default: - log_error("unknown S2K %d\n", s2kmode ); - goto leave; - } - if( minlen > pktlen ) { - log_error("packet with S2K %d too short\n", s2kmode ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - seskeylen = pktlen - minlen; - k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc - + seskeylen - 1 ); - k->version = version; - k->cipher_algo = cipher_algo; - k->s2k.mode = s2kmode; - k->s2k.hash_algo = hash_algo; - if( s2kmode == 1 || s2kmode == 3 ) { - for(i=0; i < 8 && pktlen; i++, pktlen-- ) - k->s2k.salt[i] = iobuf_get_noeof(inp); - } - if( s2kmode == 3 ) { - k->s2k.count = iobuf_get(inp); pktlen--; - } - k->seskeylen = seskeylen; - for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) - k->seskey[i] = iobuf_get_noeof(inp); - assert( !pktlen ); - - if( list_mode ) { - printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n", - version, cipher_algo, s2kmode, hash_algo); - if( s2kmode == 1 || s2kmode == 3 ) { - printf("\tsalt "); - for(i=0; i < 8; i++ ) - printf("%02x", k->s2k.salt[i]); - if( s2kmode == 3 ) - printf(", count %lu\n", (ulong)k->s2k.count ); - printf("\n"); - } - } - - leave: - skip_rest(inp, pktlen); - return rc; -} - -static int -parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) -{ - unsigned int n; - int rc = 0; - int i, ndata; - PKT_pubkey_enc *k; - - k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc); - if( pktlen < 12 ) { - log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - k->version = iobuf_get_noeof(inp); pktlen--; - if( k->version != 2 && k->version != 3 ) { - log_error("packet(%d) with unknown version %d\n", pkttype, k->version); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - k->keyid[0] = read_32(inp); pktlen -= 4; - k->keyid[1] = read_32(inp); pktlen -= 4; - k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; - k->throw_keyid = 0; /* only used as flag for build_packet */ - if( list_mode ) - printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", - k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]); - - ndata = pubkey_get_nenc(k->pubkey_algo); - if( !ndata ) { - if( list_mode ) - printf("\tunsupported algorithm %d\n", k->pubkey_algo ); - unknown_pubkey_warning( k->pubkey_algo ); - k->data[0] = NULL; /* no need to store the encrypted data */ - } - else { - for( i=0; i < ndata; i++ ) { - n = pktlen; - k->data[i] = mpi_read(inp, &n, 0); pktlen -=n; - if( list_mode ) { - printf("\tdata: "); - mpi_print(stdout, k->data[i], mpi_print_mode ); - putchar('\n'); - } - if (!k->data[i]) - rc = G10ERR_INVALID_PACKET; - } - } - - leave: - skip_rest(inp, pktlen); - return rc; -} - - -static void -dump_sig_subpkt( int hashed, int type, int critical, - const byte *buffer, size_t buflen, size_t length ) -{ - const char *p=NULL; - int i; - - /* The CERT has warning out with explains how to use GNUPG to - * detect the ARRs - we print our old message here when it is a faked - * ARR and add an additional notice */ - if ( type == SIGSUBPKT_ARR && !hashed ) { - printf("\tsubpkt %d len %u (additional recipient request)\n" - "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically " - "encrypt to this key and thereby reveal the plaintext to " - "the owner of this ARR key. Detailed info follows:\n", - type, (unsigned)length ); - } - - - printf("\t%s%ssubpkt %d len %u (", /*)*/ - critical ? "critical ":"", - hashed ? "hashed ":"", type, (unsigned)length ); - buffer++; - length--; - if( length > buflen ) { - printf("too short: buffer is only %u)\n", (unsigned)buflen ); - return; - } - switch( type ) { - case SIGSUBPKT_SIG_CREATED: - if( length >= 4 ) - printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) ); - break; - case SIGSUBPKT_SIG_EXPIRE: - if( length >= 4 ) - printf("sig expires after %s", - strtimevalue( buffer_to_u32(buffer) ) ); - break; - case SIGSUBPKT_EXPORTABLE: - if( length ) - printf("%sexportable", *buffer? "":"not "); - break; - case SIGSUBPKT_TRUST: - if(length!=2) - p="[invalid trust signature]"; - else - printf("trust signature of level %d, amount %d",buffer[0],buffer[1]); - break; - case SIGSUBPKT_REGEXP: - if(!length) - p="[invalid regexp]"; - else - printf("regular expression: \"%s\"",buffer); - break; - case SIGSUBPKT_REVOCABLE: - if( length ) - printf("%srevocable", *buffer? "":"not "); - break; - case SIGSUBPKT_KEY_EXPIRE: - if( length >= 4 ) - printf("key expires after %s", - strtimevalue( buffer_to_u32(buffer) ) ); - break; - case SIGSUBPKT_PREF_SYM: - fputs("pref-sym-algos:", stdout ); - for( i=0; i < length; i++ ) - printf(" %d", buffer[i] ); - break; - case SIGSUBPKT_REV_KEY: - fputs("revocation key: ", stdout ); - if( length < 22 ) - p = "[too short]"; - else { - printf("c=%02x a=%d f=", buffer[0], buffer[1] ); - for( i=2; i < length; i++ ) - printf("%02X", buffer[i] ); - } - break; - case SIGSUBPKT_ISSUER: - if( length >= 8 ) - printf("issuer key ID %08lX%08lX", - (ulong)buffer_to_u32(buffer), - (ulong)buffer_to_u32(buffer+4) ); - break; - case SIGSUBPKT_NOTATION: - { - fputs("notation: ", stdout ); - if( length < 8 ) - p = "[too short]"; - else if( !(*buffer & 0x80) ) - p = "[not human readable]"; - else { - const byte *s = buffer; - size_t n1, n2; - - n1 = (s[4] << 8) | s[5]; - n2 = (s[6] << 8) | s[7]; - s += 8; - if( 8+n1+n2 != length ) - p = "[error]"; - else { - print_string( stdout, s, n1, ')' ); - putc( '=', stdout ); - print_string( stdout, s+n1, n2, ')' ); - } - } - } - break; - case SIGSUBPKT_PREF_HASH: - fputs("pref-hash-algos:", stdout ); - for( i=0; i < length; i++ ) - printf(" %d", buffer[i] ); - break; - case SIGSUBPKT_PREF_COMPR: - fputs("pref-zip-algos:", stdout ); - for( i=0; i < length; i++ ) - printf(" %d", buffer[i] ); - break; - case SIGSUBPKT_KS_FLAGS: - fputs("key server preferences:",stdout); - for(i=0;i= 0 offset into buffer - * -1 unknown type - * -2 unsupported type - * -3 subpacket too short - */ -int -parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) -{ - switch( type ) { - case SIGSUBPKT_REV_KEY: - if(n < 22) - break; - return 0; - case SIGSUBPKT_SIG_CREATED: - case SIGSUBPKT_SIG_EXPIRE: - case SIGSUBPKT_KEY_EXPIRE: - if( n < 4 ) - break; - return 0; - case SIGSUBPKT_KEY_FLAGS: - case SIGSUBPKT_KS_FLAGS: - case SIGSUBPKT_PREF_SYM: - case SIGSUBPKT_PREF_HASH: - case SIGSUBPKT_PREF_COMPR: - case SIGSUBPKT_POLICY: - case SIGSUBPKT_FEATURES: - return 0; - case SIGSUBPKT_EXPORTABLE: - case SIGSUBPKT_REVOCABLE: - if( !n ) - break; - return 0; - case SIGSUBPKT_ISSUER: /* issuer key ID */ - if( n < 8 ) - break; - return 0; - case SIGSUBPKT_NOTATION: - if( n < 8 ) /* minimum length needed */ - break; - return 0; - case SIGSUBPKT_REVOC_REASON: - if( !n ) - break; - return 0; - case SIGSUBPKT_PRIMARY_UID: - if ( n != 1 ) - break; - return 0; - case SIGSUBPKT_PRIV_VERIFY_CACHE: - /* We used this in gpg 1.0.5 and 1.0.6 to cache signature - * verification results - it is no longer used. - * "GPG" 0x00 - * where mode == 1: valid data, stat == 0: invalid signature - * stat == 1: valid signature - * (because we use private data, we check our marker) */ - if( n < 6 ) - break; - if( buffer[0] != 'G' || buffer[1] != 'P' - || buffer[2] != 'G' || buffer[3] ) - return -2; - return 4; - default: return -1; - } - return -3; -} - - -static int -can_handle_critical( const byte *buffer, size_t n, int type ) -{ - switch( type ) { - case SIGSUBPKT_NOTATION: - if( n >= 8 && (*buffer & 0x80) ) - return 1; /* human readable is handled */ - return 0; - - case SIGSUBPKT_SIG_CREATED: - case SIGSUBPKT_SIG_EXPIRE: - case SIGSUBPKT_KEY_EXPIRE: - case SIGSUBPKT_EXPORTABLE: - case SIGSUBPKT_REVOCABLE: - case SIGSUBPKT_REV_KEY: - case SIGSUBPKT_ISSUER:/* issuer key ID */ - case SIGSUBPKT_PREF_SYM: - case SIGSUBPKT_PREF_HASH: - case SIGSUBPKT_PREF_COMPR: - case SIGSUBPKT_KEY_FLAGS: - case SIGSUBPKT_PRIMARY_UID: - case SIGSUBPKT_FEATURES: - case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */ - return 1; - - default: - return 0; - } -} - - -const byte * -enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype, - size_t *ret_n, int *start, int *critical ) -{ - const byte *buffer; - int buflen; - int type; - int critical_dummy; - int offset; - size_t n; - int seq = 0; - int reqseq = start? *start: 0; - - if(!critical) - critical=&critical_dummy; - - if( !pktbuf || reqseq == -1 ) { - /* return some value different from NULL to indicate that - * there is no critical bit we do not understand. The caller - * will never use the value. Yes I know, it is an ugly hack */ - return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&pktbuf : NULL; - } - buffer = pktbuf->data; - buflen = pktbuf->len; - while( buflen ) { - n = *buffer++; buflen--; - if( n == 255 ) { /* 4 byte length header */ - if( buflen < 4 ) - goto too_short; - n = (buffer[0] << 24) | (buffer[1] << 16) - | (buffer[2] << 8) | buffer[3]; - buffer += 4; - buflen -= 4; - } - else if( n >= 192 ) { /* 2 byte special encoded length header */ - if( buflen < 2 ) - goto too_short; - n = (( n - 192 ) << 8) + *buffer + 192; - buffer++; - buflen--; - } - if( buflen < n ) - goto too_short; - type = *buffer; - if( type & 0x80 ) { - type &= 0x7f; - *critical = 1; - } - else - *critical = 0; - if( !(++seq > reqseq) ) - ; - else if( reqtype == SIGSUBPKT_TEST_CRITICAL ) { - if( *critical ) { - if( n-1 > buflen+1 ) - goto too_short; - if( !can_handle_critical(buffer+1, n-1, type ) ) { - log_info(_("subpacket of type %d has critical bit set\n"), - type); - if( start ) - *start = seq; - return NULL; /* this is an error */ - } - } - } - else if( reqtype < 0 ) /* list packets */ - dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED, - type, *critical, buffer, buflen, n ); - else if( type == reqtype ) { /* found */ - buffer++; - n--; - if( n > buflen ) - goto too_short; - if( ret_n ) - *ret_n = n; - offset = parse_one_sig_subpkt(buffer, n, type ); - switch( offset ) { - case -3: - log_error("subpacket of type %d too short\n", type); - return NULL; - case -2: - return NULL; - case -1: - BUG(); /* not yet needed */ - default: - break; - } - if( start ) - *start = seq; - return buffer+offset; - } - buffer += n; buflen -=n; - } - if( reqtype == SIGSUBPKT_TEST_CRITICAL ) - return buffer; /* as value true to indicate that there is no */ - /* critical bit we don't understand */ - if( start ) - *start = -1; - return NULL; /* end of packets; not found */ - - too_short: - log_error("buffer shorter than subpacket\n"); - if( start ) - *start = -1; - return NULL; -} - - -const byte * -parse_sig_subpkt (const subpktarea_t *buffer, sigsubpkttype_t reqtype, - size_t *ret_n) -{ - return enum_sig_subpkt( buffer, reqtype, ret_n, NULL, NULL ); -} - -const byte * -parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype, - size_t *ret_n ) -{ - const byte *p; - - p = parse_sig_subpkt (sig->hashed, reqtype, ret_n ); - if( !p ) - p = parse_sig_subpkt (sig->unhashed, reqtype, ret_n ); - return p; -} - -/* Find all revocation keys. Look in hashed area only. */ -void parse_revkeys(PKT_signature *sig) -{ - struct revocation_key *revkey; - int seq=0; - size_t len; - - if(sig->sig_class!=0x1F) - return; - - while((revkey= - (struct revocation_key *)enum_sig_subpkt(sig->hashed, - SIGSUBPKT_REV_KEY, - &len,&seq,NULL))) - { - if(len==sizeof(struct revocation_key) && - (revkey->class&0x80)) /* 0x80 bit must be set */ - { - sig->revkey=m_realloc(sig->revkey, - sizeof(struct revocation_key *)*(sig->numrevkeys+1)); - sig->revkey[sig->numrevkeys]=revkey; - sig->numrevkeys++; - } - } -} - -static int -parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, - PKT_signature *sig ) -{ - int md5_len=0; - unsigned n; - int is_v4=0; - int rc=0; - int i, ndata; - - if( pktlen < 16 ) { - log_error("packet(%d) too short\n", pkttype); - goto leave; - } - sig->version = iobuf_get_noeof(inp); pktlen--; - if( sig->version == 4 ) - is_v4=1; - else if( sig->version != 2 && sig->version != 3 ) { - log_error("packet(%d) with unknown version %d\n", pkttype, sig->version); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - - if( !is_v4 ) { - md5_len = iobuf_get_noeof(inp); pktlen--; - } - sig->sig_class = iobuf_get_noeof(inp); pktlen--; - if( !is_v4 ) { - sig->timestamp = read_32(inp); pktlen -= 4; - sig->keyid[0] = read_32(inp); pktlen -= 4; - sig->keyid[1] = read_32(inp); pktlen -= 4; - } - sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--; - sig->digest_algo = iobuf_get_noeof(inp); pktlen--; - sig->flags.exportable=1; - sig->flags.revocable=1; - if( is_v4 ) { /* read subpackets */ - n = read_16(inp); pktlen -= 2; /* length of hashed data */ - if( n > 10000 ) { - log_error("signature packet: hashed data too long\n"); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - if( n ) { - sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 ); - sig->hashed->size = n; - sig->hashed->len = n; - if( iobuf_read (inp, sig->hashed->data, n ) != n ) { - log_error ("premature eof while reading " - "hashed signature data\n"); - rc = -1; - goto leave; - } - pktlen -= n; - } - n = read_16(inp); pktlen -= 2; /* length of unhashed data */ - if( n > 10000 ) { - log_error("signature packet: unhashed data too long\n"); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - if( n ) { - /* we add 8 extra bytes so that we have space for the signature - * status cache. Well we are wasting this if there is a cache - * packet already, but in the other case it avoids an realloc */ - sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 ); - sig->unhashed->size = n + 8; - sig->unhashed->len = n; - if( iobuf_read(inp, sig->unhashed->data, n ) != n ) { - log_error("premature eof while reading " - "unhashed signature data\n"); - rc = -1; - goto leave; - } - pktlen -= n; - } - } - - if( pktlen < 5 ) { /* sanity check */ - log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - - sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--; - sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--; - - if( is_v4 && sig->pubkey_algo ) { /*extract required information */ - const byte *p; - - /* set sig->flags.unknown_critical if there is a - * critical bit set for packets which we do not understand */ - if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL) - || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL, - NULL) ) - { - sig->flags.unknown_critical = 1; - } - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL ); - if( !p ) - log_error("signature packet without timestamp\n"); - else - sig->timestamp = buffer_to_u32(p); - p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); - if( !p ) - log_error("signature packet without keyid\n"); - else { - sig->keyid[0] = buffer_to_u32(p); - sig->keyid[1] = buffer_to_u32(p+4); - } - - p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL); - if(p) - sig->expiredate=sig->timestamp+buffer_to_u32(p); - if(sig->expiredate && sig->expiredate<=make_timestamp()) - sig->flags.expired=1; - - p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL); - if(p) - sig->flags.policy_url=1; - - p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL); - if(p) - sig->flags.notation=1; - - p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_REVOCABLE,NULL); - if(p && *p==0) - sig->flags.revocable=0; - - /* We accept the exportable subpacket from either the hashed - or unhashed areas as older versions of gpg put it in the - unhashed area. In theory, anyway, we should never see this - packet off of a local keyring. */ - - p=parse_sig_subpkt2(sig,SIGSUBPKT_EXPORTABLE,NULL); - if(p && *p==0) - sig->flags.exportable=0; - - /* Find all revocation keys. */ - if(sig->sig_class==0x1F) - parse_revkeys(sig); - } - - if( list_mode ) { - printf(":signature packet: algo %d, keyid %08lX%08lX\n" - "\tversion %d, created %lu, md5len %d, sigclass %02x\n" - "\tdigest algo %d, begin of digest %02x %02x\n", - sig->pubkey_algo, - (ulong)sig->keyid[0], (ulong)sig->keyid[1], - sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class, - sig->digest_algo, - sig->digest_start[0], sig->digest_start[1] ); - if( is_v4 ) { - parse_sig_subpkt (sig->hashed, SIGSUBPKT_LIST_HASHED, NULL ); - parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL); - } - } - - ndata = pubkey_get_nsig(sig->pubkey_algo); - if( !ndata ) { - if( list_mode ) - printf("\tunknown algorithm %d\n", sig->pubkey_algo ); - unknown_pubkey_warning( sig->pubkey_algo ); - /* we store the plain material in data[0], so that we are able - * to write it back with build_packet() */ - sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen ); - pktlen = 0; - } - else { - for( i=0; i < ndata; i++ ) { - n = pktlen; - sig->data[i] = mpi_read(inp, &n, 0 ); - pktlen -=n; - if( list_mode ) { - printf("\tdata: "); - mpi_print(stdout, sig->data[i], mpi_print_mode ); - putchar('\n'); - } - if (!sig->data[i]) - rc = G10ERR_INVALID_PACKET; - } - } - - leave: - skip_rest(inp, pktlen); - return rc; -} - - -static int -parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, - PKT_onepass_sig *ops ) -{ - int version; - int rc = 0; - - if( pktlen < 13 ) { - log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - version = iobuf_get_noeof(inp); pktlen--; - if( version != 3 ) { - log_error("onepass_sig with unknown version %d\n", version); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - ops->sig_class = iobuf_get_noeof(inp); pktlen--; - ops->digest_algo = iobuf_get_noeof(inp); pktlen--; - ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--; - ops->keyid[0] = read_32(inp); pktlen -= 4; - ops->keyid[1] = read_32(inp); pktlen -= 4; - ops->last = iobuf_get_noeof(inp); pktlen--; - if( list_mode ) - printf(":onepass_sig packet: keyid %08lX%08lX\n" - "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n", - (ulong)ops->keyid[0], (ulong)ops->keyid[1], - version, ops->sig_class, - ops->digest_algo, ops->pubkey_algo, ops->last ); - - - leave: - skip_rest(inp, pktlen); - return rc; -} - - -static MPI -read_protected_v3_mpi (IOBUF inp, unsigned long *length) -{ - int c; - unsigned int nbits, nbytes; - unsigned char *buf, *p; - MPI val; - - if (*length < 2) - { - log_error ("mpi too small\n"); - return NULL; - } - - if ((c=iobuf_get (inp)) == -1) - return NULL; - --*length; - nbits = c << 8; - if ((c=iobuf_get(inp)) == -1) - return NULL; - --*length; - nbits |= c; - - if (nbits > 16384) - { - log_error ("mpi too large (%u bits)\n", nbits); - return NULL; - } - nbytes = (nbits+7) / 8; - buf = p = m_alloc (2 + nbytes); - *p++ = nbits >> 8; - *p++ = nbits; - for (; nbytes && length; nbytes--, --*length) - *p++ = iobuf_get (inp); - if (nbytes) - { - log_error ("packet shorter tham mpi\n"); - m_free (buf); - return NULL; - } - - /* convert buffer into an opaque MPI */ - val = mpi_set_opaque (NULL, buf, p-buf); - return val; -} - - -static int -parse_key( IOBUF inp, int pkttype, unsigned long pktlen, - byte *hdr, int hdrlen, PACKET *pkt ) -{ - int i, version, algorithm; - unsigned n; - unsigned long timestamp, expiredate, max_expiredate; - int npkey, nskey; - int is_v4=0; - int rc=0; - - version = iobuf_get_noeof(inp); pktlen--; - if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) { - /* early versions of G10 use old PGP comments packets; - * luckily all those comments are started by a hash */ - if( list_mode ) { - printf(":rfc1991 comment packet: \"" ); - for( ; pktlen; pktlen-- ) { - int c; - c = iobuf_get_noeof(inp); - if( c >= ' ' && c <= 'z' ) - putchar(c); - else - printf("\\x%02x", c ); - } - printf("\"\n"); - } - skip_rest(inp, pktlen); - return 0; - } - else if( version == 4 ) - is_v4=1; - else if( version != 2 && version != 3 ) { - log_error("packet(%d) with unknown version %d\n", pkttype, version); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - - if( pktlen < 11 ) { - log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - - timestamp = read_32(inp); pktlen -= 4; - if( is_v4 ) { - expiredate = 0; /* have to get it from the selfsignature */ - max_expiredate = 0; - } - else { - unsigned short ndays; - ndays = read_16(inp); pktlen -= 2; - if( ndays ) - expiredate = timestamp + ndays * 86400L; - else - expiredate = 0; - - max_expiredate=expiredate; - } - algorithm = iobuf_get_noeof(inp); pktlen--; - if( list_mode ) - printf(":%s key packet:\n" - "\tversion %d, algo %d, created %lu, expires %lu\n", - pkttype == PKT_PUBLIC_KEY? "public" : - pkttype == PKT_SECRET_KEY? "secret" : - pkttype == PKT_PUBLIC_SUBKEY? "public sub" : - pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??", - version, algorithm, timestamp, expiredate ); - - if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *sk = pkt->pkt.secret_key; - - sk->timestamp = timestamp; - sk->expiredate = expiredate; - sk->max_expiredate = max_expiredate; - sk->hdrbytes = hdrlen; - sk->version = version; - sk->is_primary = pkttype == PKT_SECRET_KEY; - sk->pubkey_algo = algorithm; - sk->req_usage = 0; - sk->pubkey_usage = 0; /* not yet used */ - } - else { - PKT_public_key *pk = pkt->pkt.public_key; - - pk->timestamp = timestamp; - pk->expiredate = expiredate; - pk->max_expiredate = max_expiredate; - pk->hdrbytes = hdrlen; - pk->version = version; - pk->is_primary = pkttype == PKT_PUBLIC_KEY; - pk->pubkey_algo = algorithm; - pk->req_usage = 0; - pk->pubkey_usage = 0; /* not yet used */ - pk->is_revoked = 0; - pk->keyid[0] = 0; - pk->keyid[1] = 0; - } - nskey = pubkey_get_nskey( algorithm ); - npkey = pubkey_get_npkey( algorithm ); - if( !npkey ) { - if( list_mode ) - printf("\tunknown algorithm %d\n", algorithm ); - unknown_pubkey_warning( algorithm ); - } - - - if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { - PKT_secret_key *sk = pkt->pkt.secret_key; - byte temp[16]; - - if( !npkey ) { - sk->skey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen), pktlen ); - pktlen = 0; - goto leave; - } - - for(i=0; i < npkey; i++ ) { - n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; - if( list_mode ) { - printf( "\tskey[%d]: ", i); - mpi_print(stdout, sk->skey[i], mpi_print_mode ); - putchar('\n'); - } - if (!sk->skey[i]) - rc = G10ERR_INVALID_PACKET; - } - if (rc) /* one of the MPIs were bad */ - goto leave; - sk->protect.algo = iobuf_get_noeof(inp); pktlen--; - sk->protect.sha1chk = 0; - if( sk->protect.algo ) { - sk->is_protected = 1; - sk->protect.s2k.count = 0; - if( sk->protect.algo == 254 || sk->protect.algo == 255 ) { - if( pktlen < 3 ) { - rc = G10ERR_INVALID_PACKET; - goto leave; - } - sk->protect.sha1chk = (sk->protect.algo == 254); - sk->protect.algo = iobuf_get_noeof(inp); pktlen--; - /* Note that a sk->protect.algo > 110 is illegal, but - I'm not erroring on it here as otherwise there - would be no way to delete such a key. */ - sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--; - sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--; - /* check for the special GNU extension */ - if( is_v4 && sk->protect.s2k.mode == 101 ) { - for(i=0; i < 4 && pktlen; i++, pktlen-- ) - temp[i] = iobuf_get_noeof(inp); - if( i < 4 || memcmp( temp, "GNU", 3 ) ) { - if( list_mode ) - printf( "\tunknown S2K %d\n", - sk->protect.s2k.mode ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - /* here we know that it is a gnu extension - * What follows is the GNU protection mode: - * All values have special meanings - * and they are mapped in the mode with a base of 1000. - */ - sk->protect.s2k.mode = 1000 + temp[3]; - } - switch( sk->protect.s2k.mode ) { - case 1: - case 3: - for(i=0; i < 8 && pktlen; i++, pktlen-- ) - temp[i] = iobuf_get_noeof(inp); - memcpy(sk->protect.s2k.salt, temp, 8 ); - break; - } - switch( sk->protect.s2k.mode ) { - case 0: if( list_mode ) printf( "\tsimple S2K" ); - break; - case 1: if( list_mode ) printf( "\tsalted S2K" ); - break; - case 3: if( list_mode ) printf( "\titer+salt S2K" ); - break; - case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" ); - break; - default: - if( list_mode ) - printf( "\tunknown %sS2K %d\n", - sk->protect.s2k.mode < 1000? "":"GNU ", - sk->protect.s2k.mode ); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - - if( list_mode ) { - printf(", algo: %d,%s hash: %d", - sk->protect.algo, - sk->protect.sha1chk?" SHA1 protection," - :" simple checksum,", - sk->protect.s2k.hash_algo ); - if( sk->protect.s2k.mode == 1 - || sk->protect.s2k.mode == 3 ) { - printf(", salt: "); - for(i=0; i < 8; i++ ) - printf("%02x", sk->protect.s2k.salt[i]); - } - putchar('\n'); - } - - if( sk->protect.s2k.mode == 3 ) { - if( pktlen < 1 ) { - rc = G10ERR_INVALID_PACKET; - goto leave; - } - sk->protect.s2k.count = iobuf_get(inp); - pktlen--; - if( list_mode ) - printf("\tprotect count: %lu\n", - (ulong)sk->protect.s2k.count); - } - } - /* Note that a sk->protect.algo > 110 is illegal, but I'm - not erroring on it here as otherwise there would be no - way to delete such a key. */ - else { /* old version; no S2K, so we set mode to 0, hash MD5 */ - sk->protect.s2k.mode = 0; - sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5; - if( list_mode ) - printf( "\tprotect algo: %d (hash algo: %d)\n", - sk->protect.algo, sk->protect.s2k.hash_algo ); - } - /* It is really ugly that we don't know the size - * of the IV here in cases we are not aware of the algorithm. - * so a - * sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo); - * won't work. The only solution I see is to hardwire it here. - * NOTE: if you change the ivlen above 16, don't forget to - * enlarge temp. - */ - switch( sk->protect.algo ) { - case 7: case 8: case 9: /* reserved for AES */ - case 10: /* Twofish */ - sk->protect.ivlen = 16; - break; - default: - sk->protect.ivlen = 8; - } - if( sk->protect.s2k.mode == 1001 ) - sk->protect.ivlen = 0; - - if( pktlen < sk->protect.ivlen ) { - rc = G10ERR_INVALID_PACKET; - goto leave; - } - for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- ) - temp[i] = iobuf_get_noeof(inp); - if( list_mode ) { - printf( "\tprotect IV: "); - for(i=0; i < sk->protect.ivlen; i++ ) - printf(" %02x", temp[i] ); - putchar('\n'); - } - memcpy(sk->protect.iv, temp, sk->protect.ivlen ); - } - else - sk->is_protected = 0; - /* It does not make sense to read it into secure memory. - * If the user is so careless, not to protect his secret key, - * we can assume, that he operates an open system :=(. - * So we put the key into secure memory when we unprotect it. */ - if( sk->protect.s2k.mode == 1001 ) { - /* better set some dummy stuff here */ - sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10); - pktlen = 0; - } - else if( is_v4 && sk->is_protected ) { - /* ugly; the length is encrypted too, so we read all - * stuff up to the end of the packet into the first - * skey element */ - sk->skey[npkey] = mpi_set_opaque(NULL, - read_rest(inp, pktlen), pktlen ); - pktlen = 0; - if( list_mode ) { - printf("\tencrypted stuff follows\n"); - } - } - else { /* v3 method: the mpi length is not encrypted */ - for(i=npkey; i < nskey; i++ ) { - if ( sk->is_protected ) { - sk->skey[i] = read_protected_v3_mpi (inp, &pktlen); - if( list_mode ) - printf( "\tskey[%d]: [encrypted]\n", i); - } - else { - n = pktlen; - sk->skey[i] = mpi_read(inp, &n, 0 ); - pktlen -=n; - if( list_mode ) { - printf( "\tskey[%d]: ", i); - mpi_print(stdout, sk->skey[i], mpi_print_mode ); - putchar('\n'); - } - } - - if (!sk->skey[i]) - rc = G10ERR_INVALID_PACKET; - } - if (rc) - goto leave; - - sk->csum = read_16(inp); pktlen -= 2; - if( list_mode ) { - printf("\tchecksum: %04hx\n", sk->csum); - } - } - } - else { - PKT_public_key *pk = pkt->pkt.public_key; - - if( !npkey ) { - pk->pkey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen), pktlen ); - pktlen = 0; - goto leave; - } - - for(i=0; i < npkey; i++ ) { - n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; - if( list_mode ) { - printf( "\tpkey[%d]: ", i); - mpi_print(stdout, pk->pkey[i], mpi_print_mode ); - putchar('\n'); - } - if (!pk->pkey[i]) - rc = G10ERR_INVALID_PACKET; - } - if (rc) - goto leave; - } - - leave: - skip_rest(inp, pktlen); - return rc; -} - -/* Attribute subpackets have the same format as v4 signature - subpackets. This is not part of OpenPGP, but is done in several - versions of PGP nevertheless. */ -int -parse_attribute_subpkts(PKT_user_id *uid) -{ - size_t n; - int count=0; - struct user_attribute *attribs=NULL; - const byte *buffer=uid->attrib_data; - int buflen=uid->attrib_len; - byte type; - - m_free(uid->attribs); - - while(buflen) - { - n = *buffer++; buflen--; - if( n == 255 ) { /* 4 byte length header */ - if( buflen < 4 ) - goto too_short; - n = (buffer[0] << 24) | (buffer[1] << 16) - | (buffer[2] << 8) | buffer[3]; - buffer += 4; - buflen -= 4; - } - else if( n >= 192 ) { /* 2 byte special encoded length header */ - if( buflen < 2 ) - goto too_short; - n = (( n - 192 ) << 8) + *buffer + 192; - buffer++; - buflen--; - } - if( buflen < n ) - goto too_short; - - attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute)); - memset(&attribs[count],0,sizeof(struct user_attribute)); - - type=*buffer; - buffer++; - buflen--; - n--; - - attribs[count].type=type; - attribs[count].data=buffer; - attribs[count].len=n; - buffer+=n; - buflen-=n; - count++; - } - - uid->attribs=attribs; - uid->numattribs=count; - return count; - - too_short: - log_error("buffer shorter than attribute subpacket\n"); - uid->attribs=attribs; - uid->numattribs=count; - return count; -} - -static void setup_user_id(PACKET *packet) -{ - packet->pkt.user_id->ref = 1; - packet->pkt.user_id->attribs = NULL; - packet->pkt.user_id->attrib_data = NULL; - packet->pkt.user_id->attrib_len = 0; - packet->pkt.user_id->is_primary = 0; - packet->pkt.user_id->is_revoked = 0; - packet->pkt.user_id->is_expired = 0; - packet->pkt.user_id->expiredate = 0; - packet->pkt.user_id->created = 0; - packet->pkt.user_id->help_key_usage = 0; - packet->pkt.user_id->help_key_expire = 0; - packet->pkt.user_id->prefs = NULL; -} - -static int -parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) -{ - byte *p; - - packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); - packet->pkt.user_id->len = pktlen; - - setup_user_id(packet); - - p = packet->pkt.user_id->name; - for( ; pktlen; pktlen--, p++ ) - *p = iobuf_get_noeof(inp); - *p = 0; - - if( list_mode ) { - int n = packet->pkt.user_id->len; - printf(":user ID packet: \""); - /* fixme: Hey why don't we replace this with print_string?? */ - for(p=packet->pkt.user_id->name; n; p++, n-- ) { - if( *p >= ' ' && *p <= 'z' ) - putchar(*p); - else - printf("\\x%02x", *p ); - } - printf("\"\n"); - } - return 0; -} - - -void -make_attribute_uidname(PKT_user_id *uid, size_t max_namelen) -{ - assert ( max_namelen > 70 ); - if(uid->numattribs<=0) - sprintf(uid->name,"[bad attribute packet of size %lu]",uid->attrib_len); - else if(uid->numattribs>1) - sprintf(uid->name,"[%d attributes of size %lu]", - uid->numattribs,uid->attrib_len); - else - { - /* Only one attribute, so list it as the "user id" */ - - if(uid->attribs->type==ATTRIB_IMAGE) - { - u32 len; - byte type; - - if(parse_image_header(uid->attribs,&type,&len)) - sprintf(uid->name,"[%.20s image of size %lu]", - image_type_to_string(type,1),(ulong)len); - else - sprintf(uid->name,"[invalid image]"); - } - else - sprintf(uid->name,"[unknown attribute of size %lu]", - (ulong)uid->attribs->len); - } - - uid->len = strlen(uid->name); -} - -static int -parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) -{ - byte *p; - -#define EXTRA_UID_NAME_SPACE 71 - packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id - + EXTRA_UID_NAME_SPACE); - - setup_user_id(packet); - - packet->pkt.user_id->attrib_data = m_alloc(pktlen); - packet->pkt.user_id->attrib_len = pktlen; - p = packet->pkt.user_id->attrib_data; - for( ; pktlen; pktlen--, p++ ) - *p = iobuf_get_noeof(inp); - - /* Now parse out the individual attribute subpackets. This is - somewhat pointless since there is only one currently defined - attribute type (jpeg), but it is correct by the spec. */ - parse_attribute_subpkts(packet->pkt.user_id); - - make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE); - - if( list_mode ) { - printf(":attribute packet: %s\n", packet->pkt.user_id->name ); - } - return 0; -} - - -static int -parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) -{ - byte *p; - - packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1); - packet->pkt.comment->len = pktlen; - p = packet->pkt.comment->data; - for( ; pktlen; pktlen--, p++ ) - *p = iobuf_get_noeof(inp); - - if( list_mode ) { - int n = packet->pkt.comment->len; - printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT? - "OpenPGP draft " : "" ); - for(p=packet->pkt.comment->data; n; p++, n-- ) { - if( *p >= ' ' && *p <= 'z' ) - putchar(*p); - else - printf("\\x%02x", *p ); - } - printf("\"\n"); - } - return 0; -} - - -static void -parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) -{ - int c; - - if (pktlen) - { - c = iobuf_get_noeof(inp); - pktlen--; - pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust ); - pkt->pkt.ring_trust->trustval = c; - pkt->pkt.ring_trust->sigcache = 0; - if (!c && pktlen==1) - { - c = iobuf_get_noeof (inp); - pktlen--; - /* we require that bit 7 of the sigcache is 0 (easier eof handling)*/ - if ( !(c & 0x80) ) - pkt->pkt.ring_trust->sigcache = c; - } - if( list_mode ) - printf(":trust packet: flag=%02x sigcache=%02x\n", - pkt->pkt.ring_trust->trustval, - pkt->pkt.ring_trust->sigcache); - } - else - { - if( list_mode ) - printf(":trust packet: empty\n"); - } - skip_rest (inp, pktlen); -} - - -static int -parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *pkt, int new_ctb ) -{ - int rc = 0; - int mode, namelen, partial=0; - PKT_plaintext *pt; - byte *p; - int c, i; - - if( pktlen && pktlen < 6 ) { - log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - /* A packet length of zero indicates partial body length. A zero - data length isn't a zero length packet due to the header (mode, - name, etc), so this is accurate. */ - if(pktlen==0) - partial=1; - mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; - namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; - pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1); - pt->new_ctb = new_ctb; - pt->mode = mode; - pt->namelen = namelen; - pt->is_partial = partial; - if( pktlen ) { - for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ ) - pt->name[i] = iobuf_get_noeof(inp); - } - else { - for( i=0; i < namelen; i++ ) - if( (c=iobuf_get(inp)) == -1 ) - break; - else - pt->name[i] = c; - } - pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4; - pt->len = pktlen; - pt->buf = inp; - pktlen = 0; - - if( list_mode ) { - printf(":literal data packet:\n" - "\tmode %c, created %lu, name=\"", - mode >= ' ' && mode <'z'? mode : '?', - (ulong)pt->timestamp ); - for(p=pt->name,i=0; i < namelen; p++, i++ ) { - if( *p >= ' ' && *p <= 'z' ) - putchar(*p); - else - printf("\\x%02x", *p ); - } - printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len ); - } - - leave: - return rc; -} - - -static int -parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *pkt, int new_ctb ) -{ - PKT_compressed *zd; - - /* pktlen is here 0, but data follows - * (this should be the last object in a file or - * the compress algorithm should know the length) - */ - zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed ); - zd->algorithm = iobuf_get_noeof(inp); - zd->len = 0; /* not used */ - zd->new_ctb = new_ctb; - zd->buf = inp; - if( list_mode ) - printf(":compressed packet: algo=%d\n", zd->algorithm); - return 0; -} - - -static int -parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *pkt, int new_ctb ) -{ - int rc = 0; - PKT_encrypted *ed; - unsigned long orig_pktlen = pktlen; - - ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); - ed->len = pktlen; - /* we don't know the extralen which is (cipher_blocksize+2) - because the algorithm ist not specified in this packet. - However, it is only important to know this for some sanity - checks on the packet length - it doesn't matter that we can't - do it */ - ed->extralen = 0; - ed->buf = NULL; - ed->new_ctb = new_ctb; - ed->mdc_method = 0; - if( pkttype == PKT_ENCRYPTED_MDC ) { - /* fixme: add some pktlen sanity checks */ - int version; - - version = iobuf_get_noeof(inp); - if (orig_pktlen) - pktlen--; - if( version != 1 ) { - log_error("encrypted_mdc packet with unknown version %d\n", - version); - /*skip_rest(inp, pktlen); should we really do this? */ - rc = G10ERR_INVALID_PACKET; - goto leave; - } - ed->mdc_method = DIGEST_ALGO_SHA1; - } - if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */ - log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; - skip_rest(inp, pktlen); - goto leave; - } - if( list_mode ) { - if( orig_pktlen ) - printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen); - else - printf(":encrypted data packet:\n\tlength: unknown\n"); - if( ed->mdc_method ) - printf("\tmdc_method: %d\n", ed->mdc_method ); - } - - ed->buf = inp; - pktlen = 0; - - leave: - return rc; -} - - -static int -parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, - PACKET *pkt, int new_ctb ) -{ - int rc = 0; - PKT_mdc *mdc; - byte *p; - - mdc = pkt->pkt.mdc= m_alloc(sizeof *pkt->pkt.mdc ); - if( list_mode ) - printf(":mdc packet: length=%lu\n", pktlen); - if( !new_ctb || pktlen != 20 ) { - log_error("mdc_packet with invalid encoding\n"); - rc = G10ERR_INVALID_PACKET; - goto leave; - } - p = mdc->hash; - for( ; pktlen; pktlen--, p++ ) - *p = iobuf_get_noeof(inp); - - leave: - return rc; -} - - -/* - * This packet is internally generated by PGG (by armor.c) to - * transfer some information to the lower layer. To make sure that - * this packet is really a GPG faked one and not one comming from outside, - * we first check that tehre is a unique tag in it. - * The format of such a control packet is: - * n byte session marker - * 1 byte control type CTRLPKT_xxxxx - * m byte control data - */ - -static int -parse_gpg_control( IOBUF inp, - int pkttype, unsigned long pktlen, PACKET *packet ) -{ - byte *p; - const byte *sesmark; - size_t sesmarklen; - int i; - - if ( list_mode ) - printf(":packet 63: length %lu ", pktlen); - - sesmark = get_session_marker ( &sesmarklen ); - if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */ - goto skipit; - for( i=0; i < sesmarklen; i++, pktlen-- ) { - if ( sesmark[i] != iobuf_get_noeof(inp) ) - goto skipit; - } - if ( list_mode ) - puts ("- gpg control packet"); - - packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control - + pktlen - 1); - packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--; - packet->pkt.gpg_control->datalen = pktlen; - p = packet->pkt.gpg_control->data; - for( ; pktlen; pktlen--, p++ ) - *p = iobuf_get_noeof(inp); - - return 0; - - skipit: - if ( list_mode ) { - int c; - - i=0; - printf("- private (rest length %lu)\n", pktlen); - if( iobuf_in_block_mode(inp) ) { - while( (c=iobuf_get(inp)) != -1 ) - dump_hex_line(c, &i); - } - else { - for( ; pktlen; pktlen-- ) - dump_hex_line(iobuf_get(inp), &i); - } - putchar('\n'); - } - skip_rest(inp,pktlen); - return G10ERR_INVALID_PACKET; -} - -/* create a gpg control packet to be used internally as a placeholder */ -PACKET * -create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen ) -{ - PACKET *packet; - byte *p; - - packet = m_alloc( sizeof *packet ); - init_packet(packet); - packet->pkttype = PKT_GPG_CONTROL; - packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control - + datalen - 1); - packet->pkt.gpg_control->control = type; - packet->pkt.gpg_control->datalen = datalen; - p = packet->pkt.gpg_control->data; - for( ; datalen; datalen--, p++ ) - *p = *data++; - - return packet; -} diff --git a/g10/passphrase.c b/g10/passphrase.c deleted file mode 100644 index d84d6e88b..000000000 --- a/g10/passphrase.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* passphrase.c - Get a passphrase - * 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 -#include -#include -#include -#include -#include -#include -#if !defined(HAVE_DOSISH_SYSTEM) && !defined(__riscos__) -#include -#include -#endif -#if defined (__MINGW32__) || defined (__CYGWIN32__) -# include -#endif -#include -#ifdef HAVE_LOCALE_H -#include -#endif - -#include "util.h" -#include "memory.h" -#include "options.h" -#include "ttyio.h" -#include "cipher.h" -#include "keydb.h" -#include "main.h" -#include "i18n.h" -#include "status.h" - - -enum gpga_protocol_codes { - /* Request codes */ - GPGA_PROT_GET_VERSION = 1, - GPGA_PROT_GET_PASSPHRASE = 2, - GPGA_PROT_CLEAR_PASSPHRASE= 3, - GPGA_PROT_SHUTDOWN = 4, - GPGA_PROT_FLUSH = 5, - - /* Reply codes */ - GPGA_PROT_REPLY_BASE = 0x10000, - GPGA_PROT_OKAY = 0x10001, - GPGA_PROT_GOT_PASSPHRASE = 0x10002, - - /* Error codes */ - GPGA_PROT_ERROR_BASE = 0x20000, - GPGA_PROT_PROTOCOL_ERROR = 0x20001, - GPGA_PROT_INVALID_REQUEST= 0x20002, - GPGA_PROT_CANCELED = 0x20003, - GPGA_PROT_NO_PASSPHRASE = 0x20004, - GPGA_PROT_BAD_PASSPHRASE = 0x20005, - GPGA_PROT_INVALID_DATA = 0x20006, - GPGA_PROT_NOT_IMPLEMENTED= 0x20007, - GPGA_PROT_UI_PROBLEM = 0x20008 -}; - - -#define buftou32( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ - (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3))) -#define u32tobuf( p, a ) do { \ - ((byte*)p)[0] = (byte)((a) >> 24); \ - ((byte*)p)[1] = (byte)((a) >> 16); \ - ((byte*)p)[2] = (byte)((a) >> 8); \ - ((byte*)p)[3] = (byte)((a) ); \ - } while(0) - -#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)) - - - -static char *fd_passwd = NULL; -static char *next_pw = NULL; -static char *last_pw = NULL; - -#if defined (__MINGW32__) || defined (__CYGWIN32__) -static int read_fd = 0; -static int write_fd = 0; -#endif - -static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ); - -int -have_static_passphrase() -{ - if ( opt.use_agent ) - return 0; - return !!fd_passwd; -} - -/**************** - * Set the passphrase to be used for the next query and only for the next - * one. - */ -void -set_next_passphrase( const char *s ) -{ - m_free(next_pw); - next_pw = NULL; - if( s ) { - next_pw = m_alloc_secure( strlen(s)+1 ); - strcpy(next_pw, s ); - } -} - -/**************** - * Get the last passphrase used in passphrase_to_dek. - * Note: This removes the passphrase from this modules and - * the caller must free the result. May return NULL: - */ -char * -get_last_passphrase() -{ - char *p = last_pw; - last_pw = NULL; - return p; -} - - -void -read_passphrase_from_fd( int fd ) -{ - int i, len; - char *pw; - - if ( opt.use_agent ) - return; /* not used here */ - - if( !opt.batch ) - tty_printf("Reading passphrase from file descriptor %d ...", fd ); - for( pw = NULL, i = len = 100; ; i++ ) { - if( i >= len-1 ) { - char *pw2 = pw; - len += 100; - pw = m_alloc_secure( len ); - if( pw2 ) - memcpy(pw, pw2, i ); - else - i=0; - } - if( read( fd, pw+i, 1) != 1 || pw[i] == '\n' ) - break; - } - pw[i] = 0; - if( !opt.batch ) - tty_printf("\b\b\b \n" ); - - m_free( fd_passwd ); - fd_passwd = pw; -} - -static int -writen ( int fd, const void *buf, size_t nbytes ) -{ -#if defined (__MINGW32__) || defined (__CYGWIN32__) - DWORD nwritten, nleft = nbytes; - - while (nleft > 0) { - if ( !WriteFile( (HANDLE)write_fd, buf, nleft, &nwritten, NULL) ) { - log_error("write failed: ec=%d\n", (int)GetLastError()); - return -1; - } - /*log_info("** WriteFile fd=%d nytes=%d nwritten=%d\n", - write_fd, nbytes, (int)nwritten);*/ - Sleep(100); - - nleft -= nwritten; - buf = (const BYTE *)buf + nwritten; - } -#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - /* not implemented */ -#else - size_t nleft = nbytes; - int nwritten; - - while( nleft > 0 ) { - nwritten = write( fd, buf, nleft ); - if( nwritten < 0 ) { - if ( errno == EINTR ) - nwritten = 0; - else { - log_error ( "write() failed: %s\n", strerror (errno) ); - return -1; - } - } - nleft -= nwritten; - buf = (const char*)buf + nwritten; - } -#endif - - return 0; -} - - -static int -readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) -{ -#if defined (__MINGW32__) || defined (__CYGWIN32__) - DWORD nread, nleft = buflen; - - while (nleft > 0) { - if ( !ReadFile( (HANDLE)read_fd, buf, nleft, &nread, NULL) ) { - log_error("read() error: ec=%d\n", (int)GetLastError()); - return -1; - } - if (!nread || GetLastError() == ERROR_BROKEN_PIPE) - break; - /*log_info("** ReadFile fd=%d buflen=%d nread=%d\n", - read_fd, buflen, (int)nread);*/ - Sleep(100); - - nleft -= nread; - buf = (BYTE *)buf + nread; - } - if (ret_nread) - *ret_nread = buflen - nleft; - -#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - /* not implemented */ -#else - size_t nleft = buflen; - int nread; - char *p; - - p = buf; - while( nleft > 0 ) { - nread = read ( fd, buf, nleft ); - if( nread < 0 ) { - if (nread == EINTR) - nread = 0; - else { - log_error ( "read() error: %s\n", strerror (errno) ); - return -1; - } - } - else if( !nread ) - break; /* EOF */ - nleft -= nread; - buf = (char*)buf + nread; - } - if( ret_nread ) - *ret_nread = buflen - nleft; -#endif - - return 0; -} - -/* read an entire line */ -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 -1; /* read error */ - } - else if (!n) - { - return -1; /* 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 temporary hack until we use - the assuna lib in gpg. So it is okay to forget - about pending bytes */ - } - } - - return nread; -} - - - -#if !defined (__riscos__) - -#if !defined (__MINGW32__) && !defined (__CYGWIN32__) -/* For the new Assuan protocol we may have to send options */ -static int -agent_send_option (int fd, const char *name, const char *value) -{ - char buf[200]; - int nread; - char *line; - int i; - - line = m_alloc (7 + strlen (name) + 1 + strlen (value) + 2); - strcpy (stpcpy (stpcpy (stpcpy ( - stpcpy (line, "OPTION "), name), "="), value), "\n"); - i = writen (fd, line, strlen (line)); - m_free (line); - if (i) - return -1; - - /* get response */ - nread = readline (fd, buf, DIM(buf)-1); - if (nread < 3) - return -1; - - if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) - return 0; /* okay */ - - return -1; -} - -static int -agent_send_all_options (int fd) -{ - char *dft_display = NULL; - char *dft_ttyname = NULL; - char *dft_ttytype = NULL; - char *old_lc = NULL; - char *dft_lc = NULL; - int rc = 0; - - dft_display = getenv ("DISPLAY"); - if (opt.display || dft_display) - { - if (agent_send_option (fd, "display", - opt.display ? opt.display : dft_display)) - return -1; - } - - if (!opt.ttyname && ttyname (1)) - dft_ttyname = ttyname (1); - if (opt.ttyname || dft_ttyname) - { - if (agent_send_option (fd, "ttyname", - opt.ttyname ? opt.ttyname : dft_ttyname)) - return -1; - } - - dft_ttytype = getenv ("TERM"); - if (opt.ttytype || (dft_ttyname && dft_ttytype)) - { - if (agent_send_option (fd, "ttytype", - opt.ttyname ? opt.ttytype : dft_ttytype)) - return -1; - } - -#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) - old_lc = setlocale (LC_CTYPE, NULL); - if (old_lc) - old_lc = m_strdup (old_lc); - dft_lc = setlocale (LC_CTYPE, ""); -#endif - if (opt.lc_ctype || (dft_ttyname && dft_lc)) - { - rc = agent_send_option (fd, "lc-ctype", - opt.lc_ctype ? opt.lc_ctype : dft_lc); - } -#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) - if (old_lc) - { - setlocale (LC_CTYPE, old_lc); - m_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 = m_strdup (old_lc); - dft_lc = setlocale (LC_MESSAGES, ""); -#endif - if (opt.lc_messages || (dft_ttyname && dft_lc)) - { - rc = agent_send_option (fd, "lc-messages", - opt.lc_messages ? opt.lc_messages : dft_lc); - } -#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) - if (old_lc) - { - setlocale (LC_MESSAGES, old_lc); - m_free (old_lc); - } -#endif - return rc; -} -#endif /*!__MINGW32__ && !__CYGWIN32__*/ - - -/* - * Open a connection to the agent and send the magic string - * Returns: -1 on error or an filedescriptor for urther processing - */ - -static int -agent_open (int *ret_prot) -{ -#if defined (__MINGW32__) || defined (__CYGWIN32__) - int fd; - char *infostr, *p; - HANDLE h; - char pidstr[128]; - - *ret_prot = 0; - if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentPID")) - || *infostr == '0') { - log_error( _("gpg-agent is not available in this session\n")); - return -1; - } - free(infostr); - - sprintf(pidstr, "%u", (unsigned int)GetCurrentProcessId()); - if (write_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentCID", pidstr)) { - log_error( _("can't set client pid for the agent\n") ); - return -1; - } - h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); - SetEvent(h); - Sleep(50); /* some time for the server */ - if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentReadFD")) ) { - log_error( _("can't get server read FD for the agent\n") ); - return -1; - } - read_fd = atol(p); - free(p); - if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentWriteFD")) ) { - log_error ( _("can't get server write FD for the agent\n") ); - return -1; - } - write_fd = atol(p); - free(p); - fd = 0; - - if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { - fd = -1; - } -#else /* Posix */ - - int fd; - char *infostr, *p; - struct sockaddr_un client_addr; - size_t len; - int prot; - - if (opt.gpg_agent_info) - infostr = m_strdup (opt.gpg_agent_info); - else - { - infostr = getenv ( "GPG_AGENT_INFO" ); - if ( !infostr ) { - log_error (_("gpg-agent is not available in this session\n")); - opt.use_agent = 0; - return -1; - } - infostr = m_strdup ( infostr ); - } - - if ( !(p = strchr ( infostr, ':')) || p == infostr - || (p-infostr)+1 >= sizeof client_addr.sun_path ) { - log_error( _("malformed GPG_AGENT_INFO environment variable\n")); - m_free (infostr ); - opt.use_agent = 0; - return -1; - } - *p++ = 0; - /* See whether this is the new gpg-agent using the Assuna protocl. - This agent identifies itself by have an info string with a - version number in the 3rd field. */ - while (*p && *p != ':') - p++; - prot = *p? atoi (p+1) : 0; - if ( prot < 0 || prot > 1) { - log_error (_("gpg-agent protocol version %d is not supported\n"),prot); - m_free (infostr ); - opt.use_agent = 0; - return -1; - } - *ret_prot = prot; - - if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { - log_error ("can't create socket: %s\n", strerror(errno) ); - m_free (infostr ); - opt.use_agent = 0; - return -1; - } - - 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 ) { - log_error ( _("can't connect to `%s': %s\n"), - infostr, strerror (errno) ); - m_free (infostr ); - close (fd ); - opt.use_agent = 0; - return -1; - } - m_free (infostr); - - if (!prot) { - if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { - close (fd); - fd = -1; - } - } - else { /* assuan based gpg-agent */ - char line[200]; - int nread; - - nread = readline (fd, line, DIM(line)); - if (nread < 3 || !(line[0] == 'O' && line[1] == 'K' - && (line[2] == '\n' || line[2] == ' ')) ) { - log_error ( _("communication problem with gpg-agent\n")); - close (fd ); - opt.use_agent = 0; - return -1; - } - - if (agent_send_all_options (fd)) { - log_error (_("problem with the agent - disabling agent use\n")); - close (fd); - opt.use_agent = 0; - return -1; - } - - } -#endif - - return fd; -} - - -static void -agent_close ( int fd ) -{ -#if defined (__MINGW32__) || defined (__CYGWIN32__) - HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); - ResetEvent(h); -#else - close (fd); -#endif -} -#endif /* !__riscos__ */ - - - -/* - * Ask the GPG Agent for the passphrase. - * Mode 0: Allow cached passphrase - * 1: No cached passphrase FIXME: Not really implemented - * 2: Ditto, but change the text to "repeat entry" - */ -static char * -agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text ) -{ -#if defined(__riscos__) - return NULL; -#else - size_t n; - char *atext; - char buf[50]; - int fd = -1; - int nread; - u32 reply; - char *pw = NULL; - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - byte fpr[MAX_FINGERPRINT_LEN]; - int prot; - -#if MAX_FINGERPRINT_LEN < 20 -#error agent needs a 20 byte fingerprint -#endif - - memset (fpr, 0, MAX_FINGERPRINT_LEN ); - if( keyid && get_pubkey( pk, keyid ) ) - pk = NULL; /* oops: no key for some reason */ - - if ( !mode && pk ) - { - char *uid; - size_t uidlen; - const char *algo_name = pubkey_algo_to_string ( pk->pubkey_algo ); - const char *timestr; - char *maink; - const char *fmtstr; - - if ( !algo_name ) - algo_name = "?"; - - fmtstr = _(" (main key ID %08lX)"); - maink = m_alloc ( strlen (fmtstr) + 20 ); - if( keyid[2] && keyid[3] && keyid[0] != keyid[2] - && keyid[1] != keyid[3] ) - sprintf( maink, fmtstr, (ulong)keyid[3] ); - else - *maink = 0; - - uid = get_user_id ( keyid, &uidlen ); - timestr = strtimestamp (pk->timestamp); - fmtstr = _("You need a passphrase to unlock the" - " secret key for user:\n" - "\"%.*s\"\n" - "%u-bit %s key, ID %08lX, created %s%s\n" ); - atext = m_alloc ( 100 + strlen (fmtstr) - + uidlen + 15 + strlen(algo_name) + 8 - + strlen (timestr) + strlen (maink) ); - sprintf (atext, fmtstr, - uidlen, uid, - nbits_from_pk (pk), algo_name, (ulong)keyid[1], timestr, - maink ); - m_free (uid); - m_free (maink); - - { - size_t dummy; - fingerprint_from_pk( pk, fpr, &dummy ); - } - - } - else if (mode == 1 ) - atext = m_strdup ( _("Enter passphrase\n") ); - else - atext = m_strdup ( _("Repeat passphrase\n") ); - - if ( (fd = agent_open (&prot)) == -1 ) - goto failure; - - if (!prot) - { /* old style protocol */ - n = 4 + 20 + strlen (atext); - u32tobuf (buf, n ); - u32tobuf (buf+4, GPGA_PROT_GET_PASSPHRASE ); - memcpy (buf+8, fpr, 20 ); - if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) ) - goto failure; - m_free (atext); atext = NULL; - - /* get response */ - if ( readn ( fd, buf, 12, &nread ) ) - goto failure; - - if ( nread < 8 ) - { - log_error ( "response from agent too short\n" ); - goto failure; - } - n = buftou32 ( buf ); - reply = buftou32 ( buf + 4 ); - if ( reply == GPGA_PROT_GOT_PASSPHRASE ) - { - size_t pwlen; - size_t nn; - - if ( nread < 12 || n < 8 ) - { - log_error ( "response from agent too short\n" ); - goto failure; - } - pwlen = buftou32 ( buf + 8 ); - nread -= 12; - n -= 8; - if ( pwlen > n || n > 1000 ) - { - log_error (_("passphrase too long\n")); - /* or protocol error */ - goto failure; - } - /* we read the whole block in one chunk to give no hints - * on how long the passhrase actually is - this wastes some bytes - * but because we already have this padding we should not loosen - * this by issuing 2 read calls */ - pw = m_alloc_secure ( n+1 ); - if ( readn ( fd, pw, n, &nn ) ) - goto failure; - if ( n != nn ) - { - log_error (_("invalid response from agent\n")); - goto failure; - } - pw[pwlen] = 0; /* make a C String */ - agent_close (fd); - free_public_key( pk ); - return pw; - } - else if ( reply == GPGA_PROT_CANCELED ) - log_info ( _("cancelled by user\n") ); - else - log_error ( _("problem with the agent: agent returns 0x%lx\n"), - (ulong)reply ); - } - else - { /* The new Assuan protocol */ - char *line, *p; - const unsigned char *s; - int i; - - if (!tryagain_text) - tryagain_text = "X"; - - /* We allocate 2 time the needed space for atext so that there - is nenough space for escaping */ - line = m_alloc (15 + 46 - + 3*strlen (tryagain_text) + 3*strlen (atext) + 2); - strcpy (line, "GET_PASSPHRASE "); - p = line+15; - if (!mode) - { - for (i=0; i < 20; i++, p +=2 ) - sprintf (p, "%02X", fpr[i]); - } - else - *p++ = 'X'; /* no caching */ - *p++ = ' '; - for (i=0, s=tryagain_text; *s; s++) - { - if (*s < ' ' || *s == '+') - { - sprintf (p, "%%%02X", *s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } - *p++ = ' '; - *p++ = 'X'; /* Use the standard prompt */ - *p++ = ' '; - /* copy description */ - for (i=0, s= atext; *s; s++) - { - if (*s < ' ' || *s == '+') - { - sprintf (p, "%%%02X", *s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } - *p++ = '\n'; - i = writen (fd, line, p - line); - m_free (line); - if (i) - goto failure; - m_free (atext); atext = NULL; - - /* get response */ - pw = m_alloc_secure (500); - nread = readline (fd, pw, 499); - if (nread < 3) - goto failure; - - 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 */ - agent_close (fd); - free_public_key( pk ); - return pw; - } - else if (nread > 7 && !memcmp (pw, "ERR 111", 7) - && (pw[7] == ' ' || pw[7] == '\n') ) - log_info (_("cancelled by user\n") ); - else - { - log_error (_("problem with the agent - disabling agent use\n")); - opt.use_agent = 0; - } - } - - - failure: - m_free (atext); - if ( fd != -1 ) - agent_close (fd); - m_free (pw ); - free_public_key( pk ); - - return NULL; -#endif /* Posix or W32 */ -} - -/* - * Clear the cached passphrase - */ -void -passphrase_clear_cache ( u32 *keyid, int algo ) -{ -#if defined(__riscos__) - return ; -#else - size_t n; - char buf[200]; - int fd = -1; - size_t nread; - u32 reply; - PKT_public_key *pk; - byte fpr[MAX_FINGERPRINT_LEN]; - int prot; - -#if MAX_FINGERPRINT_LEN < 20 -#error agent needs a 20 byte fingerprint -#endif - - if (!opt.use_agent) - return; - - pk = m_alloc_clear ( sizeof *pk ); - memset (fpr, 0, MAX_FINGERPRINT_LEN ); - if( !keyid || get_pubkey( pk, keyid ) ) - { - log_debug ("oops, no key in passphrase_clear_cache\n"); - goto failure; /* oops: no key for some reason */ - } - - { - size_t dummy; - fingerprint_from_pk( pk, fpr, &dummy ); - } - - if ( (fd = agent_open (&prot)) == -1 ) - goto failure; - - if (!prot) - { - n = 4 + 20; - u32tobuf (buf, n ); - u32tobuf (buf+4, GPGA_PROT_CLEAR_PASSPHRASE ); - memcpy (buf+8, fpr, 20 ); - if ( writen ( fd, buf, 28 ) ) - goto failure; - - /* get response */ - if ( readn ( fd, buf, 8, &nread ) ) - goto failure; - - if ( nread < 8 ) { - log_error ( "response from agent too short\n" ); - goto failure; - } - - reply = buftou32 ( buf + 4 ); - if ( reply != GPGA_PROT_OKAY && reply != GPGA_PROT_NO_PASSPHRASE ) - { - log_error ( _("problem with the agent: agent returns 0x%lx\n"), - (ulong)reply ); - } - } - else - { /* The assuan protocol */ - char *line, *p; - int i; - - line = m_alloc (17 + 40 + 2); - strcpy (line, "CLEAR_PASSPHRASE "); - p = line+17; - for (i=0; i < 20; i++, p +=2 ) - sprintf (p, "%02X", fpr[i]); - *p++ = '\n'; - i = writen (fd, line, p - line); - m_free (line); - if (i) - goto failure; - - /* get response */ - nread = readline (fd, buf, DIM(buf)-1); - if (nread < 3) - goto failure; - - if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) - ; - else - { - log_error (_("problem with the agent - disabling agent use\n")); - opt.use_agent = 0; - } - } - - failure: - if (fd != -1) - agent_close (fd); - free_public_key( pk ); -#endif /* Posix or W32 */ -} - - - - -/**************** - * Get a passphrase for the secret key with KEYID, display TEXT - * if the user needs to enter the passphrase. - * mode 0 = standard, 2 = create new passphrase - * Returns: a DEK with a session key; caller must free - * or NULL if the passphrase was not correctly repeated. - * (only for mode 2) - * a dek->keylen of 0 means: no passphrase entered. - * (only for mode 2) - * pubkey_algo is only informational. - */ -DEK * -passphrase_to_dek( u32 *keyid, int pubkey_algo, - int cipher_algo, STRING2KEY *s2k, int mode, - const char *tryagain_text) -{ - char *pw = NULL; - DEK *dek; - STRING2KEY help_s2k; - - if( !s2k ) { - /* This is used for the old rfc1991 mode - * Note: This must match the code in encode.c with opt.rfc1991 set */ - int algo = opt.def_digest_algo ? opt.def_digest_algo - : opt.s2k_digest_algo; - - s2k = &help_s2k; - s2k->mode = 0; - s2k->hash_algo = algo; - } - - if( !next_pw && is_status_enabled() ) { - char buf[50]; - - if( keyid ) { - u32 used_kid[2]; - char *us; - - if( keyid[2] && keyid[3] ) { - used_kid[0] = keyid[2]; - used_kid[1] = keyid[3]; - } - else { - used_kid[0] = keyid[0]; - used_kid[1] = keyid[1]; - } - - us = get_long_user_id_string( keyid ); - write_status_text( STATUS_USERID_HINT, us ); - m_free(us); - - sprintf( buf, "%08lX%08lX %08lX%08lX %d 0", - (ulong)keyid[0], (ulong)keyid[1], - (ulong)used_kid[0], (ulong)used_kid[1], - pubkey_algo ); - - write_status_text( STATUS_NEED_PASSPHRASE, buf ); - } - else { - sprintf( buf, "%d %d %d", cipher_algo, s2k->mode, s2k->hash_algo ); - write_status_text( STATUS_NEED_PASSPHRASE_SYM, buf ); - } - } - - if( keyid && !opt.batch && !next_pw ) { - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - size_t n; - char *p; - - tty_printf(_("\nYou need a passphrase to unlock the secret key for\n" - "user: \"") ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\"\n"); - - if( !get_pubkey( pk, keyid ) ) { - const char *s = pubkey_algo_to_string( pk->pubkey_algo ); - tty_printf( _("%u-bit %s key, ID %08lX, created %s"), - nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1], - strtimestamp(pk->timestamp) ); - if( keyid[2] && keyid[3] && keyid[0] != keyid[2] - && keyid[1] != keyid[3] ) - tty_printf( _(" (main key ID %08lX)"), (ulong)keyid[3] ); - tty_printf("\n"); - } - - tty_printf("\n"); - free_public_key( pk ); - } - - agent_died: - if( next_pw ) { - pw = next_pw; - next_pw = NULL; - } - else if ( opt.use_agent ) { - pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, tryagain_text ); - if (!pw) - { - if (!opt.use_agent) - goto agent_died; - pw = m_strdup (""); - } - if( *pw && mode == 2 ) { - char *pw2 = agent_get_passphrase ( keyid, 2, NULL ); - if (!pw2) - { - if (!opt.use_agent) - { - m_free (pw); - pw = NULL; - goto agent_died; - } - pw2 = m_strdup (""); - } - if( strcmp(pw, pw2) ) { - m_free(pw2); - m_free(pw); - return NULL; - } - m_free(pw2); - } - } - else if( fd_passwd ) { - pw = m_alloc_secure( strlen(fd_passwd)+1 ); - strcpy( pw, fd_passwd ); - } - else if( opt.batch ) { - log_error(_("can't query password in batchmode\n")); - pw = m_strdup( "" ); /* return an empty passphrase */ - } - else { - pw = cpr_get_hidden("passphrase.enter", _("Enter passphrase: ") ); - tty_kill_prompt(); - if( mode == 2 && !cpr_enabled() ) { - char *pw2 = cpr_get_hidden("passphrase.repeat", - _("Repeat passphrase: ") ); - tty_kill_prompt(); - if( strcmp(pw, pw2) ) { - m_free(pw2); - m_free(pw); - return NULL; - } - m_free(pw2); - } - } - - if( !pw || !*pw ) - write_status( STATUS_MISSING_PASSPHRASE ); - - dek = m_alloc_secure_clear ( sizeof *dek ); - dek->algo = cipher_algo; - if( !*pw && mode == 2 ) - dek->keylen = 0; - else - hash_passphrase( dek, pw, s2k, mode==2 ); - m_free(last_pw); - last_pw = pw; - return dek; -} - - -/**************** - * Hash a passphrase using the supplied s2k. If create is true, create - * a new salt or what else must be filled into the s2k for a new key. - * always needs: dek->algo, s2k->mode, s2k->hash_algo. - */ -static void -hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) -{ - MD_HANDLE md; - int pass, i; - int used = 0; - int pwlen = strlen(pw); - - assert( s2k->hash_algo ); - dek->keylen = cipher_get_keylen( dek->algo ) / 8; - if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) - BUG(); - - md = md_open( s2k->hash_algo, 1); - for(pass=0; used < dek->keylen ; pass++ ) { - if( pass ) { - md_reset(md); - for(i=0; i < pass; i++ ) /* preset the hash context */ - md_putc(md, 0 ); - } - - if( s2k->mode == 1 || s2k->mode == 3 ) { - int len2 = pwlen + 8; - ulong count = len2; - - if( create && !pass ) { - randomize_buffer(s2k->salt, 8, 1); - if( s2k->mode == 3 ) - s2k->count = 96; /* 65536 iterations */ - } - - if( s2k->mode == 3 ) { - count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6); - if( count < len2 ) - count = len2; - } - /* a little bit complicated because we need a ulong for count */ - while( count > len2 ) { /* maybe iterated+salted */ - md_write( md, s2k->salt, 8 ); - md_write( md, pw, pwlen ); - count -= len2; - } - if( count < 8 ) - md_write( md, s2k->salt, count ); - else { - md_write( md, s2k->salt, 8 ); - count -= 8; - md_write( md, pw, count ); - } - } - else - md_write( md, pw, pwlen ); - md_final( md ); - i = md_digest_length( s2k->hash_algo ); - if( i > dek->keylen - used ) - i = dek->keylen - used; - memcpy( dek->key+used, md_read(md, s2k->hash_algo), i ); - used += i; - } - md_close(md); -} - diff --git a/g10/photoid.c b/g10/photoid.c deleted file mode 100644 index c20e20eca..000000000 --- a/g10/photoid.c +++ /dev/null @@ -1,332 +0,0 @@ -/* photoid.c - photo ID handling code - * 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 -#include -#include -#include -#ifdef __MINGW32__ -# include -# ifndef VER_PLATFORM_WIN32_WINDOWS -# define VER_PLATFORM_WIN32_WINDOWS 1 -# endif -#endif -#include "packet.h" -#include "status.h" -#include "exec.h" -#include "keydb.h" -#include "util.h" -#include "i18n.h" -#include "iobuf.h" -#include "memory.h" -#include "options.h" -#include "main.h" -#include "photoid.h" - -/* Generate a new photo id packet, or return NULL if canceled */ -PKT_user_id *generate_photo_id(PKT_public_key *pk) -{ - PKT_user_id *uid; - int error=1,i; - unsigned int len; - char *filename=NULL; - byte *photo=NULL; - byte header[16]; - IOBUF file; - - header[0]=0x10; /* little side of photo header length */ - header[1]=0; /* big side of photo header length */ - header[2]=1; /* 1 == version of photo header */ - header[3]=1; /* 1 == JPEG */ - - for(i=4;i<16;i++) /* The reserved bytes */ - header[i]=0; - -#define EXTRA_UID_NAME_SPACE 71 - uid=m_alloc_clear(sizeof(*uid)+71); - - printf(_("\nPick an image to use for your photo ID. " - "The image must be a JPEG file.\n" - "Remember that the image is stored within your public key. " - "If you use a\n" - "very large picture, your key will become very large as well!\n" - "Keeping the image close to 240x288 is a good size to use.\n")); - - while(photo==NULL) - { - printf("\n"); - - m_free(filename); - - filename=cpr_get("photoid.jpeg.add", - _("Enter JPEG filename for photo ID: ")); - - if(strlen(filename)==0) - goto scram; - - file=iobuf_open(filename); - if(!file) - { - log_error(_("Unable to open photo \"%s\": %s\n"), - filename,strerror(errno)); - continue; - } - - len=iobuf_get_filelength(file); - if(len>6144) - { - printf("This JPEG is really large (%d bytes) !\n",len); - if(!cpr_get_answer_is_yes("photoid.jpeg.size", - _("Are you sure you want to use it (y/N)? "))) - { - iobuf_close(file); - continue; - } - } - - photo=m_alloc(len); - iobuf_read(file,photo,len); - iobuf_close(file); - - /* Is it a JPEG? */ - if(photo[0]!=0xFF || photo[1]!=0xD8 || - photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F') - { - log_error(_("\"%s\" is not a JPEG file\n"),filename); - m_free(photo); - photo=NULL; - continue; - } - - /* Build the packet */ - build_attribute_subpkt(uid,1,photo,len,header,16); - parse_attribute_subpkts(uid); - make_attribute_uidname(uid, EXTRA_UID_NAME_SPACE); - - /* Showing the photo is not safe when noninteractive since the - "user" may not be able to dismiss a viewer window! */ - if(opt.command_fd==-1) - { - show_photos(uid->attribs,uid->numattribs,pk,NULL); - switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay", - _("Is this photo correct (y/N/q)? "))) - { - case -1: - goto scram; - case 0: - free_attributes(uid); - m_free(photo); - photo=NULL; - continue; - } - } - } - - error=0; - uid->ref=1; - - scram: - m_free(filename); - m_free(photo); - - if(error) - { - free_attributes(uid); - m_free(uid); - return NULL; - } - - return uid; -} - -/* Returns 0 for error, 1 for valid */ -int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len) -{ - u16 headerlen; - - if(attr->len<3) - return 0; - - /* For historical reasons (i.e. "oops!"), the header length is - little endian. */ - headerlen=(attr->data[1]<<8) | attr->data[0]; - - if(headerlen>attr->len) - return 0; - - if(type && attr->len>=4) - { - if(attr->data[2]==1) /* header version 1 */ - *type=attr->data[3]; - else - *type=0; - } - - *len=attr->len-headerlen; - - if(*len==0) - return 0; - - return 1; -} - -/* style==0 for extension, 1 for name, 2 for MIME type. Remember that - the "name" style string could be used in a user ID name field, so - make sure it is not too big (see - parse-packet.c:parse_attribute). */ -char *image_type_to_string(byte type,int style) -{ - char *string; - - switch(type) - { - case 1: /* jpeg */ - if(style==0) - string="jpg"; - else if(style==1) - string="jpeg"; - else - string="image/jpeg"; - break; - - default: - if(style==0) - string="bin"; - else if(style==1) - string="unknown"; - else - string="image/x-unknown"; - break; - } - - return string; -} - -#if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER) -static const char *get_default_photo_command(void) -{ -#if defined(__MINGW32__) - OSVERSIONINFO osvi; - - memset(&osvi,0,sizeof(osvi)); - osvi.dwOSVersionInfoSize=sizeof(osvi); - GetVersionEx(&osvi); - - if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS) - return "start /w %i"; - else - return "cmd /c start /w %i"; -#elif defined(__APPLE__) - /* OS X. This really needs more than just __APPLE__. */ - return "open %I"; -#elif defined(__riscos__) - return "Filer_Run %I"; -#else - return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin"; -#endif -} -#endif - -void show_photos(const struct user_attribute *attrs, - int count,PKT_public_key *pk,PKT_secret_key *sk) -{ -#ifndef DISABLE_PHOTO_VIEWER - int i; - struct expando_args args; - u32 len; - u32 kid[2]={0,0}; - - memset(&args,0,sizeof(args)); - args.pk=pk; - args.sk=sk; - - if(pk) - keyid_from_pk(pk,kid); - else if(sk) - keyid_from_sk(sk,kid); - - for(i=0;itempfile_in, - image_type_to_string(args.imagetype,2)); -#endif - - m_free(name); - - fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild); - - if(exec_read(spawn)!=0) - { - exec_finish(spawn); - goto fail; - } - - if(exec_finish(spawn)!=0) - goto fail; - } - - return; - - fail: - log_error("unable to display photo ID!\n"); -#endif -} diff --git a/g10/photoid.h b/g10/photoid.h deleted file mode 100644 index 45d104f8c..000000000 --- a/g10/photoid.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Photo ID functions */ - -#ifndef _PHOTOID_H_ -#define _PHOTOID_H_ - -#include "packet.h" - -PKT_user_id *generate_photo_id(PKT_public_key *pk); -int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len); -char *image_type_to_string(byte type,int style); -void show_photos(const struct user_attribute *attrs, - int count,PKT_public_key *pk,PKT_secret_key *sk); - -#endif /* !_PHOTOID_H_ */ diff --git a/g10/pkclist.c b/g10/pkclist.c deleted file mode 100644 index cb1c506e3..000000000 --- a/g10/pkclist.c +++ /dev/null @@ -1,1303 +0,0 @@ -/* pkclist.c - * 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 -#include -#include -#include -#include -#include - -#include "options.h" -#include "packet.h" -#include "errors.h" -#include "keydb.h" -#include "memory.h" -#include "util.h" -#include "main.h" -#include "trustdb.h" -#include "ttyio.h" -#include "status.h" -#include "photoid.h" -#include "i18n.h" - - -#define CONTROL_D ('D' - 'A' + 1) - - -/**************** - * Show the revocation reason as it is stored with the given signature - */ -static void -do_show_revocation_reason( PKT_signature *sig ) -{ - size_t n, nn; - const byte *p, *pp; - int seq = 0; - const char *text; - - while( (p = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REVOC_REASON, - &n, &seq, NULL )) ) { - if( !n ) - continue; /* invalid - just skip it */ - - if( *p == 0 ) - text = _("No reason specified"); - else if( *p == 0x01 ) - text = _("Key is superseded"); - else if( *p == 0x02 ) - text = _("Key has been compromised"); - else if( *p == 0x03 ) - text = _("Key is no longer used"); - else if( *p == 0x20 ) - text = _("User ID is no longer valid"); - else - text = NULL; - - log_info( _("reason for revocation: ") ); - if( text ) - fputs( text, log_stream() ); - else - fprintf( log_stream(), "code=%02x", *p ); - putc( '\n', log_stream() ); - n--; p++; - pp = NULL; - do { - /* We don't want any empty lines, so skip them */ - while( n && *p == '\n' ) { - p++; - n--; - } - if( n ) { - pp = memchr( p, '\n', n ); - nn = pp? pp - p : n; - log_info( _("revocation comment: ") ); - print_string( log_stream(), p, nn, 0 ); - putc( '\n', log_stream() ); - p += nn; n -= nn; - } - } while( pp ); - } -} - -/* Mode 0: try and find the revocation based on the pk (i.e. check - subkeys, etc.) Mode 1: use only the revocation on the main pk */ - -void -show_revocation_reason( PKT_public_key *pk, int mode ) -{ - /* Hmmm, this is not so easy becuase we have to duplicate the code - * used in the trustbd to calculate the keyflags. We need to find - * a clean way to check revocation certificates on keys and - * signatures. And there should be no duplicate code. Because we - * enter this function only when the trustdb told us that we have - * a revoked key, we could simply look for a revocation cert and - * display this one, when there is only one. Let's try to do this - * until we have a better solution. */ - KBNODE node, keyblock = NULL; - byte fingerprint[MAX_FINGERPRINT_LEN]; - size_t fingerlen; - int rc; - - /* get the keyblock */ - fingerprint_from_pk( pk, fingerprint, &fingerlen ); - rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen ); - if( rc ) { /* that should never happen */ - log_debug( "failed to get the keyblock\n"); - return; - } - - for( node=keyblock; node; node = node->next ) { - if( (mode && node->pkt->pkttype == PKT_PUBLIC_KEY) || - ( ( node->pkt->pkttype == PKT_PUBLIC_KEY - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - && !cmp_public_keys( node->pkt->pkt.public_key, pk ) ) ) - break; - } - if( !node ) { - log_debug("Oops, PK not in keyblock\n"); - release_kbnode( keyblock ); - return; - } - /* now find the revocation certificate */ - for( node = node->next; node ; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - break; - if( node->pkt->pkttype == PKT_SIGNATURE - && (node->pkt->pkt.signature->sig_class == 0x20 - || node->pkt->pkt.signature->sig_class == 0x28 ) ) { - /* FIXME: we should check the signature here */ - do_show_revocation_reason ( node->pkt->pkt.signature ); - break; - } - } - - /* We didn't find it, so check if the whole key is revoked */ - if(!node && !mode) - show_revocation_reason(pk,1); - - release_kbnode( keyblock ); -} - - -static void -show_paths (const PKT_public_key *pk, int only_first ) -{ - log_debug("not yet implemented\n"); -#if 0 - void *context = NULL; - unsigned otrust, validity; - int last_level, level; - - last_level = 0; - while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){ - char *p; - int c, rc; - size_t n; - u32 keyid[2]; - PKT_public_key *pk ; - - if( level < last_level && only_first ) - break; - last_level = level; - - rc = keyid_from_lid( lid, keyid ); - - if( rc ) { - log_error("ooops: can't get keyid for lid %lu\n", lid); - return; - } - - pk = m_alloc_clear( sizeof *pk ); - rc = get_pubkey( pk, keyid ); - if( rc ) { - log_error("key %08lX: public key not found: %s\n", - (ulong)keyid[1], g10_errstr(rc) ); - return; - } - - tty_printf("%*s%4u%c/%08lX.%lu %s \"", - level*2, "", - nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], lid, datestr_from_pk( pk ) ); - - c = trust_letter(otrust); - if( c ) - putchar( c ); - else - printf( "%02x", otrust ); - putchar('/'); - c = trust_letter(validity); - if( c ) - putchar( c ); - else - printf( "%02x", validity ); - putchar(' '); - - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ), - m_free(p); - tty_printf("\"\n"); - free_public_key( pk ); - } - enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */ -#endif - tty_printf("\n"); -} - - - - -/**************** - * mode: 0 = standard - * 1 = Without key info and additional menu option 'm' - * this does also add an option to set the key to ultimately trusted. - * Returns: - * -2 = nothing changed - caller should show some additional info - * -1 = quit operation - * 0 = nothing changed - * 1 = new ownertrust now in new_trust - */ -static int -do_edit_ownertrust (PKT_public_key *pk, int mode, - unsigned *new_trust, int defer_help ) -{ - char *p; - size_t n; - u32 keyid[2]; - int changed=0; - int quit=0; - int show=0; - int did_help=defer_help; - - keyid_from_pk (pk, keyid); - for(;;) { - /* a string with valid answers */ - const char *ans = _("iImMqQsS"); - - if( !did_help ) - { - if( !mode ) - { - KBNODE keyblock, un; - - tty_printf(_("No trust value assigned to:\n" - "%4u%c/%08lX %s \""), - nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk( pk ) ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ), - m_free(p); - tty_printf("\"\n"); - - keyblock = get_pubkeyblock (keyid); - if (!keyblock) - BUG (); - for (un=keyblock; un; un = un->next) { - if (un->pkt->pkttype != PKT_USER_ID ) - continue; - if (un->pkt->pkt.user_id->is_revoked ) - continue; - if (un->pkt->pkt.user_id->is_expired ) - continue; - /* Only skip textual primaries */ - if (un->pkt->pkt.user_id->is_primary && - !un->pkt->pkt.user_id->attrib_data ) - continue; - - if(opt.show_photos && un->pkt->pkt.user_id->attrib_data) - show_photos(un->pkt->pkt.user_id->attribs, - un->pkt->pkt.user_id->numattribs,pk,NULL); - - tty_printf (" %s", _(" aka \"")); - tty_print_utf8_string (un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len ); - tty_printf("\"\n"); - } - - print_fingerprint (pk, NULL, 2); - tty_printf("\n"); - } - tty_printf (_( - "Please decide how far you trust this user to correctly\n" - "verify other users' keys (by looking at passports,\n" - "checking fingerprints from different sources...)?\n\n")); - tty_printf (_(" %d = Don't know\n"), 1); - tty_printf (_(" %d = I do NOT trust\n"), 2); - tty_printf (_(" %d = I trust marginally\n"), 3); - tty_printf (_(" %d = I trust fully\n"), 4); - if (mode) - tty_printf (_(" %d = I trust ultimately\n"), 5); -#if 0 - /* not yet implemented */ - tty_printf (_(" i = please show me more information\n") ); -#endif - if( mode ) - tty_printf(_(" m = back to the main menu\n")); - else - { - tty_printf(_(" s = skip this key\n")); - tty_printf(_(" q = quit\n")); - } - tty_printf("\n"); - did_help = 1; - } - if( strlen(ans) != 8 ) - BUG(); - p = cpr_get("edit_ownertrust.value",_("Your decision? ")); - trim_spaces(p); - cpr_kill_prompt(); - if( !*p ) - did_help = 0; - else if( *p && p[1] ) - ; - else if( !p[1] && (*p >= '1' && *p <= (mode?'5':'4')) ) - { - unsigned int trust; - switch( *p ) - { - case '1': trust = TRUST_UNDEFINED; break; - case '2': trust = TRUST_NEVER ; break; - case '3': trust = TRUST_MARGINAL ; break; - case '4': trust = TRUST_FULLY ; break; - case '5': trust = TRUST_ULTIMATE ; break; - default: BUG(); - } - if (trust == TRUST_ULTIMATE - && !cpr_get_answer_is_yes ("edit_ownertrust.set_ultimate.okay", - _("Do you really want to set this key" - " to ultimate trust? "))) - ; /* no */ - else - { - *new_trust = trust; - changed = 1; - break; - } - } -#if 0 - /* not yet implemented */ - else if( *p == ans[0] || *p == ans[1] ) - { - tty_printf(_("Certificates leading to an ultimately trusted key:\n")); - show = 1; - break; - } -#endif - else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) - { - break ; /* back to the menu */ - } - else if( !mode && (*p == ans[6] || *p == ans[7] ) ) - { - break; /* skip */ - } - else if( !mode && (*p == ans[4] || *p == ans[5] ) ) - { - quit = 1; - break ; /* back to the menu */ - } - m_free(p); p = NULL; - } - m_free(p); - return show? -2: quit? -1 : changed; -} - -/* - * Display a menu to change the ownertrust of the key PK (which should - * be a primary key). - * For mode values see do_edit_ownertrust () - */ -int -edit_ownertrust (PKT_public_key *pk, int mode ) -{ - unsigned int trust; - int no_help = 0; - - for(;;) - { - switch ( do_edit_ownertrust (pk, mode, &trust, no_help ) ) - { - case -1: /* quit */ - return -1; - case -2: /* show info */ - show_paths(pk, 1); - no_help = 1; - break; - case 1: /* trust value set */ - trust &= ~TRUST_FLAG_DISABLED; - trust |= get_ownertrust (pk) & TRUST_FLAG_DISABLED; - update_ownertrust (pk, trust ); - return 1; - default: - return 0; - } - } -} - - -/**************** - * Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL - * Returns: true if we trust. - */ -static int -do_we_trust( PKT_public_key *pk, unsigned int *trustlevel ) -{ - unsigned int trustmask = 0; - - /* FIXME: get_pubkey_byname already checks the validity and won't - * return keys which are either expired or revoked - so these - * question here won't get triggered. We have to find a solution - * for this. It might make sense to have a function in getkey.c - * which does only the basic checks and returns even revoked and - * expired keys. This fnction could then also returhn a list of - * keys if the speicified name is ambiguous - */ - if( (*trustlevel & TRUST_FLAG_REVOKED) ) { - log_info(_("key %08lX: key has been revoked!\n"), - (ulong)keyid_from_pk( pk, NULL) ); - show_revocation_reason( pk, 0 ); - if( opt.batch ) - return 0; /* no */ - - if( !cpr_get_answer_is_yes("revoked_key.override", - _("Use this key anyway? ")) ) - return 0; /* no */ - trustmask |= TRUST_FLAG_REVOKED; - } - if( (*trustlevel & TRUST_FLAG_SUB_REVOKED) ) { - log_info(_("key %08lX: subkey has been revoked!\n"), - (ulong)keyid_from_pk( pk, NULL) ); - show_revocation_reason( pk, 0 ); - if( opt.batch ) - return 0; - - if( !cpr_get_answer_is_yes("revoked_key.override", - _("Use this key anyway? ")) ) - return 0; - trustmask |= TRUST_FLAG_SUB_REVOKED; - } - *trustlevel &= ~trustmask; - - if( opt.always_trust) { - if( opt.verbose ) - log_info("No trust check due to --always-trust option\n"); - return 1; - } - - switch( (*trustlevel & TRUST_MASK) ) { - case TRUST_EXPIRED: - log_info(_("%08lX: key has expired\n"), - (ulong)keyid_from_pk( pk, NULL) ); - return 0; /* no */ - - default: - log_error ("invalid trustlevel %u returned from validation layer\n", - *trustlevel); - /* fall thru */ - case TRUST_UNKNOWN: - case TRUST_UNDEFINED: - log_info(_("%08lX: There is no indication that this key " - "really belongs to the owner\n"), - (ulong)keyid_from_pk( pk, NULL) ); - return 0; /* no */ - - case TRUST_NEVER: - log_info(_("%08lX: We do NOT trust this key\n"), - (ulong)keyid_from_pk( pk, NULL) ); - return 0; /* no */ - - case TRUST_MARGINAL: - log_info( - _("%08lX: It is not sure that this key really belongs to the owner\n" - "but it is accepted anyway\n"), (ulong)keyid_from_pk( pk, NULL) ); - return 1; /* yes */ - - case TRUST_FULLY: - if( opt.verbose ) - log_info(_("This key probably belongs to the owner\n")); - return 1; /* yes */ - - case TRUST_ULTIMATE: - if( opt.verbose ) - log_info(_("This key belongs to us\n")); - return 1; /* yes */ - } - - return 1; /* yes */ -} - - - -/**************** - * wrapper around do_we_trust, so we can ask whether to use the - * key anyway. - */ -static int -do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel ) -{ - int rc; - - rc = do_we_trust( pk, &trustlevel ); - - if( (trustlevel & TRUST_FLAG_REVOKED) && !rc ) - return 0; - if( (trustlevel & TRUST_FLAG_SUB_REVOKED) && !rc ) - return 0; - - if( !opt.batch && !rc ) { - char *p; - u32 keyid[2]; - size_t n; - - keyid_from_pk( pk, keyid); - tty_printf( "%4u%c/%08lX %s \"", - nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk( pk ) ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ), - m_free(p); - tty_printf("\"\n"); - print_fingerprint (pk, NULL, 2); - tty_printf("\n"); - - tty_printf(_( -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n\n")); - - if( cpr_get_answer_is_yes("untrusted_key.override", - _("Use this key anyway? ")) ) - rc = 1; - - /* Hmmm: Should we set a flag to tell the user about - * his decision the next time he encrypts for this recipient? - */ - } - else if( opt.always_trust && !rc ) { - if( !opt.quiet ) - log_info(_("WARNING: Using untrusted key!\n")); - rc = 1; - } - return rc; -} - - - -/**************** - * Check whether we can trust this signature. - * Returns: Error if we shall not trust this signatures. - */ -int -check_signatures_trust( PKT_signature *sig ) -{ - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - unsigned int trustlevel; - int rc=0; - - if ( opt.always_trust) - { - if( !opt.quiet ) - log_info(_("WARNING: Using untrusted key!\n")); - if (opt.with_fingerprint) - print_fingerprint (pk, NULL, 1); - goto leave; - } - - rc = get_pubkey( pk, sig->keyid ); - if (rc) - { /* this should not happen */ - log_error("Ooops; the key vanished - can't check the trust\n"); - rc = G10ERR_NO_PUBKEY; - goto leave; - } - - trustlevel = get_validity (pk, NULL); - - if ( (trustlevel & TRUST_FLAG_REVOKED) ) - { - write_status( STATUS_KEYREVOKED ); - log_info(_("WARNING: This key has been revoked by its owner!\n")); - log_info(_(" This could mean that the signature is forgery.\n")); - show_revocation_reason( pk, 0 ); - } - else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) ) - { - write_status( STATUS_KEYREVOKED ); - log_info(_("WARNING: This subkey has been revoked by its owner!\n")); - show_revocation_reason( pk, 0 ); - } - - if ((trustlevel & TRUST_FLAG_DISABLED)) - log_info (_("Note: This key has been disabled.\n")); - - switch ( (trustlevel & TRUST_MASK) ) - { - case TRUST_EXPIRED: - log_info(_("Note: This key has expired!\n")); - print_fingerprint (pk, NULL, 1); - break; - - default: - log_error ("invalid trustlevel %u returned from validation layer\n", - trustlevel); - /* fall thru */ - case TRUST_UNKNOWN: - case TRUST_UNDEFINED: - write_status( STATUS_TRUST_UNDEFINED ); - log_info(_("WARNING: This key is not certified with" - " a trusted signature!\n")); - log_info(_(" There is no indication that the " - "signature belongs to the owner.\n" )); - print_fingerprint (pk, NULL, 1); - break; - - case TRUST_NEVER: - /* currently we won't get that status */ - write_status( STATUS_TRUST_NEVER ); - log_info(_("WARNING: We do NOT trust this key!\n")); - log_info(_(" The signature is probably a FORGERY.\n")); - if (opt.with_fingerprint) - print_fingerprint (pk, NULL, 1); - rc = G10ERR_BAD_SIGN; - break; - - case TRUST_MARGINAL: - write_status( STATUS_TRUST_MARGINAL ); - log_info(_("WARNING: This key is not certified with" - " sufficiently trusted signatures!\n")); - log_info(_(" It is not certain that the" - " signature belongs to the owner.\n" )); - print_fingerprint (pk, NULL, 1); - break; - - case TRUST_FULLY: - write_status( STATUS_TRUST_FULLY ); - if (opt.with_fingerprint) - print_fingerprint (pk, NULL, 1); - break; - - case TRUST_ULTIMATE: - write_status( STATUS_TRUST_ULTIMATE ); - if (opt.with_fingerprint) - print_fingerprint (pk, NULL, 1); - break; - } - - leave: - free_public_key( pk ); - return rc; -} - - -void -release_pk_list( PK_LIST pk_list ) -{ - PK_LIST pk_rover; - - for( ; pk_list; pk_list = pk_rover ) { - pk_rover = pk_list->next; - free_public_key( pk_list->pk ); - m_free( pk_list ); - } -} - - -static int -key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk) -{ - for( ; pk_list; pk_list = pk_list->next) - if (cmp_public_keys(pk_list->pk, pk) == 0) - return 0; - - return -1; -} - - -/**************** - * Return a malloced string with a default reciepient if there is any - */ -static char * -default_recipient(void) -{ - PKT_secret_key *sk; - byte fpr[MAX_FINGERPRINT_LEN+1]; - size_t n; - char *p; - int i; - - if( opt.def_recipient ) - return m_strdup( opt.def_recipient ); - if( !opt.def_recipient_self ) - return NULL; - sk = m_alloc_clear( sizeof *sk ); - i = get_seckey_byname( sk, NULL, 0 ); - if( i ) { - free_secret_key( sk ); - return NULL; - } - n = MAX_FINGERPRINT_LEN; - fingerprint_from_sk( sk, fpr, &n ); - free_secret_key( sk ); - p = m_alloc( 2*n+3 ); - *p++ = '0'; - *p++ = 'x'; - for(i=0; i < n; i++ ) - sprintf( p+2*i, "%02X", fpr[i] ); - p -= 2; - return p; -} - -static int -expand_id(const char *id,STRLIST *into,unsigned int flags) -{ - struct groupitem *groups; - int count=0; - - for(groups=opt.grouplist;groups;groups=groups->next) - { - /* need strcasecmp() here, as this should be localized */ - if(strcasecmp(groups->name,id)==0) - { - STRLIST each,sl; - - /* this maintains the current utf8-ness */ - for(each=groups->values;each;each=each->next) - { - sl=add_to_strlist(into,each->d); - sl->flags=flags; - count++; - } - - break; - } - } - - return count; -} - -/* For simplicity, and to avoid potential loops, we only expand once - - you can't make an alias that points to an alias. */ -static STRLIST -expand_group(STRLIST input) -{ - STRLIST sl,output=NULL,rover; - - for(rover=input;rover;rover=rover->next) - if(expand_id(rover->d,&output,rover->flags)==0) - { - /* Didn't find any groups, so use the existing string */ - sl=add_to_strlist(&output,rover->d); - sl->flags=rover->flags; - } - - return output; -} - -int -build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) -{ - PK_LIST pk_list = NULL; - PKT_public_key *pk=NULL; - int rc=0; - int any_recipients=0; - STRLIST rov,remusr; - char *def_rec = NULL; - - if(opt.grouplist) - remusr=expand_group(rcpts); - else - remusr=rcpts; - - /* check whether there are any recipients in the list and build the - * list of the encrypt-to ones (we always trust them) */ - for( rov = remusr; rov; rov = rov->next ) { - if( !(rov->flags & 1) ) - any_recipients = 1; - else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { - pk = m_alloc_clear( sizeof *pk ); - pk->req_usage = use; - if( (rc = get_pubkey_byname( pk, rov->d, NULL, NULL )) ) { - free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - rov->d, strlen (rov->d), -1); - goto fail; - } - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { - /* Skip the actual key if the key is already present - * in the list */ - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("%s: skipped: public key already present\n"), - rov->d); - } - else { - PK_LIST r; - r = m_alloc( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->mark = 0; - pk_list = r; - } - } - else { - free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - rov->d, strlen (rov->d), -1); - goto fail; - } - } - } - - if( !any_recipients && !opt.batch ) { /* ask */ - int have_def_rec; - char *answer=NULL; - STRLIST backlog=NULL; - - def_rec = default_recipient(); - have_def_rec = !!def_rec; - if( !have_def_rec ) - tty_printf(_( - "You did not specify a user ID. (you may use \"-r\")\n")); - for(;;) { - rc = 0; - m_free(answer); - if( have_def_rec ) { - answer = def_rec; - def_rec = NULL; - } - else if(backlog) { - answer=pop_strlist(&backlog); - } - else { - answer = cpr_get_utf8("pklist.user_id.enter", - _("\nEnter the user ID. End with an empty line: ")); - trim_spaces(answer); - cpr_kill_prompt(); - } - if( !answer || !*answer ) { - m_free(answer); - break; - } - if(expand_id(answer,&backlog,0)) - continue; - if( pk ) - free_public_key( pk ); - pk = m_alloc_clear( sizeof *pk ); - pk->req_usage = use; - rc = get_pubkey_byname( pk, answer, NULL, NULL ); - if( rc ) - tty_printf(_("No such user ID.\n")); - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { - if( have_def_rec ) { - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("skipped: public key " - "already set as default recipient\n") ); - } - else { - PK_LIST r = m_alloc( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->mark = 0; - pk_list = r; - } - any_recipients = 1; - continue; - } - else { - int trustlevel; - - trustlevel = get_validity (pk, NULL); - if( (trustlevel & TRUST_FLAG_DISABLED) ) { - tty_printf(_("Public key is disabled.\n") ); - } - else if( do_we_trust_pre( pk, trustlevel ) ) { - /* Skip the actual key if the key is already present - * in the list */ - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("skipped: public key already set\n") ); - } - else { - PK_LIST r; - char *p; - size_t n; - u32 keyid[2]; - - keyid_from_pk( pk, keyid); - tty_printf("Added %4u%c/%08lX %s \"", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], - datestr_from_pk( pk ) ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\"\n"); - - r = m_alloc( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->mark = 0; - pk_list = r; - } - any_recipients = 1; - continue; - } - } - } - m_free(def_rec); def_rec = NULL; - have_def_rec = 0; - } - if( pk ) { - free_public_key( pk ); - pk = NULL; - } - } - else if( !any_recipients && (def_rec = default_recipient()) ) { - pk = m_alloc_clear( sizeof *pk ); - pk->req_usage = use; - rc = get_pubkey_byname( pk, def_rec, NULL, NULL ); - if( rc ) - log_error(_("unknown default recipient `%s'\n"), def_rec ); - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { - /* Mark any_recipients here since the default recipient - would have been used if it wasn't already there. It - doesn't really matter if we got this key from the default - recipient or an encrypt-to. */ - any_recipients = 1; - if (key_present_in_pk_list(pk_list, pk) == 0) - log_info(_("skipped: public key already set as default recipient\n")); - else { - PK_LIST r = m_alloc( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->mark = 0; - pk_list = r; - } - } - if( pk ) { - free_public_key( pk ); - pk = NULL; - } - m_free(def_rec); def_rec = NULL; - } - else { - any_recipients = 0; - for(; remusr; remusr = remusr->next ) { - if( (remusr->flags & 1) ) - continue; /* encrypt-to keys are already handled */ - - pk = m_alloc_clear( sizeof *pk ); - pk->req_usage = use; - if( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL )) ) { - free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - remusr->d, strlen (remusr->d), - -1); - goto fail; - } - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { - int trustlevel; - - trustlevel = get_validity (pk, pk->namehash); - if( (trustlevel & TRUST_FLAG_DISABLED) ) { - free_public_key(pk); pk = NULL; - log_info(_("%s: skipped: public key is disabled\n"), - remusr->d); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - remusr->d, - strlen (remusr->d), - -1); - rc=G10ERR_UNU_PUBKEY; - goto fail; - } - else if( do_we_trust_pre( pk, trustlevel ) ) { - /* note: do_we_trust may have changed the trustlevel */ - - /* We have at least one valid recipient. It doesn't matters - * if this recipient is already present. */ - any_recipients = 1; - - /* Skip the actual key if the key is already present - * in the list */ - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("%s: skipped: public key already present\n"), - remusr->d); - } - else { - PK_LIST r; - r = m_alloc( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->mark = 0; - pk_list = r; - } - } - else { /* we don't trust this pk */ - free_public_key( pk ); pk = NULL; - write_status_text_and_buffer (STATUS_INV_RECP, "10 ", - remusr->d, - strlen (remusr->d), - -1); - rc=G10ERR_UNU_PUBKEY; - goto fail; - } - } - else { - free_public_key( pk ); pk = NULL; - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - remusr->d, - strlen (remusr->d), - -1); - log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); - goto fail; - } - } - } - - if( !rc && !any_recipients ) { - log_error(_("no valid addressees\n")); - write_status_text (STATUS_NO_RECP, "0"); - rc = G10ERR_NO_USER_ID; - } - - fail: - - if( rc ) - release_pk_list( pk_list ); - else - *ret_pk_list = pk_list; - if(opt.grouplist) - free_strlist(remusr); - return rc; -} - - -/* In pgp6 mode, disallow all ciphers except IDEA (1), 3DES (2), and - CAST5 (3), all hashes except MD5 (1), SHA1 (2), and RIPEMD160 (3), - and all compressions except none (0) and ZIP (1). pgp7 mode - expands the cipher list to include AES128 (7), AES192 (8), AES256 - (9), and TWOFISH (10). For a true PGP key all of this is unneeded - as they are the only items present in the preferences subpacket, - but checking here covers the weird case of encrypting to a key that - had preferences from a different implementation which was then used - with PGP. I am not completely comfortable with this as the right - thing to do, as it slightly alters the list of what the user is - supposedly requesting. It is not against the RFC however, as the - preference chosen will never be one that the user didn't specify - somewhere ("The implementation may use any mechanism to pick an - algorithm in the intersection"), and PGP has no mechanism to fix - such a broken preference list, so I'm including it. -dms */ - -static int -algo_available( int preftype, int algo, void *hint ) -{ - if( preftype == PREFTYPE_SYM ) { - if( opt.pgp6 && ( algo != 1 && algo != 2 && algo != 3) ) - return 0; - - if( opt.pgp7 && (algo != 1 && algo != 2 && algo != 3 && - algo != 7 && algo != 8 && algo != 9 && algo != 10) ) - return 0; - - return algo && !check_cipher_algo( algo ); - } - else if( preftype == PREFTYPE_HASH ) { - int bits=0; - - if(hint) - bits=*(int *)hint; - - if(bits && (bits != md_digest_length(algo))) - return 0; - - if( (opt.pgp6 || opt.pgp7 ) && ( algo != 1 && algo != 2 && algo != 3) ) - return 0; - - return algo && !check_digest_algo( algo ); - } - else if( preftype == PREFTYPE_ZIP ) { - if ( ( opt.pgp6 || opt.pgp7 ) && ( algo !=0 && algo != 1) ) - return 0; - - return !check_compress_algo( algo ); - } - else - return 0; -} - - - -/**************** - * Return -1 if we could not find an algorithm. - */ -int -select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, void *hint) -{ - PK_LIST pkr; - u32 bits[8]; - const prefitem_t *prefs; - int i, j; - int compr_hack=0; - int any; - - if( !pk_list ) - return -1; - - memset( bits, ~0, 8 * sizeof *bits ); - for( pkr = pk_list; pkr; pkr = pkr->next ) { - u32 mask[8]; - - memset( mask, 0, 8 * sizeof *mask ); - if( preftype == PREFTYPE_SYM ) { - if( opt.pgp2 && - pkr->pk->version < 4 && - pkr->pk->selfsigversion < 4 ) - mask[0] |= (1<<1); /* IDEA is implicitly there for v3 keys - with v3 selfsigs (rfc2440:12.1) if - --pgp2 mode is on. This doesn't - mean it's actually available, of - course. */ - else - mask[0] |= (1<<2); /* 3DES is implicitly there for everyone else */ - } - else if( preftype == PREFTYPE_HASH ) { - /* While I am including this code for completeness, note - that currently --pgp2 mode locks the hash at MD5, so this - function will never even be called. Even if the hash - wasn't locked at MD5, we don't support sign+encrypt in - --pgp2 mode, and that's the only time PREFTYPE_HASH is - used anyway. -dms */ - if( opt.pgp2 && - pkr->pk->version < 4 && - pkr->pk->selfsigversion < 4 ) - mask[0] |= (1<<1); /* MD5 is there for v3 keys with v3 - selfsigs when --pgp2 is on. */ - else - mask[0] |= (1<<2); /* SHA1 is there for everyone else */ - } - else if( preftype == PREFTYPE_ZIP ) - mask[0] |= (1<<0); /* Uncompressed is implicit */ - - if (pkr->pk->user_id) /* selected by user ID */ - prefs = pkr->pk->user_id->prefs; - else - prefs = pkr->pk->prefs; - - any = 0; - if( prefs ) { - for (i=0; prefs[i].type; i++ ) { - if( prefs[i].type == preftype ) { - mask[prefs[i].value/32] |= 1 << (prefs[i].value%32); - any = 1; - } - } - } - - if( (!prefs || !any) && preftype == PREFTYPE_ZIP ) { - mask[0] |= 3; /* asume no_compression and old pgp */ - compr_hack = 1; - } - - #if 0 - log_debug("pref mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", - (ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4], - (ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]); - #endif - for(i=0; i < 8; i++ ) - bits[i] &= mask[i]; - #if 0 - log_debug("pref bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", - (ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4], - (ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]); - #endif - } - /* usable algorithms are now in bits - * We now use the last key from pk_list to select - * the algorithm we want to use. there are no - * preferences for the last key, we select the one - * corresponding to first set bit. - */ - i = -1; - any = 0; - - /* Can we use the requested algorithm? */ - if(request>-1 && (bits[request/32] & (1<<(request%32))) && - algo_available(preftype,request,hint)) - return request; - - /* If we have personal prefs set, use them instead of the last key */ - if(preftype==PREFTYPE_SYM && opt.personal_cipher_prefs) - prefs=opt.personal_cipher_prefs; - else if(preftype==PREFTYPE_HASH && opt.personal_digest_prefs) - prefs=opt.personal_digest_prefs; - else if(preftype==PREFTYPE_ZIP && opt.personal_compress_prefs) - prefs=opt.personal_compress_prefs; - - if( prefs ) { - for(j=0; prefs[j].type; j++ ) { - if( prefs[j].type == preftype ) { - if( (bits[prefs[j].value/32] & (1<<(prefs[j].value%32))) ) { - if( algo_available( preftype, prefs[j].value, hint ) ) { - any = 1; - i = prefs[j].value; - break; - } - } - } - } - } - if( !prefs || !any ) { - for(j=0; j < 256; j++ ) - if( (bits[j/32] & (1<<(j%32))) ) { - if( algo_available( preftype, j, hint ) ) { - i = j; - break; - } - } - } - - #if 0 - log_debug("prefs of type %d: selected %d\n", preftype, i ); - #endif - if( compr_hack && !i ) { - /* selected no compression, but we should check whether - * algorithm 1 is also available (the ordering is not relevant - * in this case). */ - if( bits[0] & (1<<1) ) - i = 1; /* yep; we can use compression algo 1 */ - } - - /* "If you are building an authentication system, the recipient - may specify a preferred signing algorithm. However, the signer - would be foolish to use a weak algorithm simply because the - recipient requests it." RFC2440:13. If we settle on MD5, and - SHA1 is also available, use SHA1 instead. Of course, if the - user intentinally chose MD5 (by putting it in their personal - prefs), then we should do what they say. */ - - if(preftype==PREFTYPE_HASH && - i==DIGEST_ALGO_MD5 && (bits[0] & (1<next) { - int mdc; - - if (pkr->pk->user_id) /* selected by user ID */ - mdc = pkr->pk->user_id->mdc_feature; - else - mdc = pkr->pk->mdc_feature; - if (!mdc) - return 0; /* at least one recipient does not support it */ - } - return 1; /* can be used */ -} diff --git a/g10/plaintext.c b/g10/plaintext.c deleted file mode 100644 index b12fb0f11..000000000 --- a/g10/plaintext.c +++ /dev/null @@ -1,418 +0,0 @@ -/* plaintext.c - process plaintext packets - * 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 -#include -#include -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM - #include /* for setmode() */ -#endif - -#include "util.h" -#include "memory.h" -#include "options.h" -#include "packet.h" -#include "ttyio.h" -#include "filter.h" -#include "main.h" -#include "status.h" -#include "i18n.h" - - - -/**************** - * Handle a plaintext packet. If MFX is not NULL, update the MDs - * Note: we should use the filter stuff here, but we have to add some - * easy mimic to set a read limit, so we calculate only the - * bytes from the plaintext. - */ -int -handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, - int nooutput, int clearsig ) -{ - char *fname = NULL; - FILE *fp = NULL; - int rc = 0; - int c; - int convert = pt->mode == 't'; - - /* create the filename as C string */ - if( nooutput ) - ; - else if( opt.outfile ) { - fname = m_alloc( strlen( opt.outfile ) + 1); - strcpy(fname, opt.outfile ); - } - else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) { - log_info(_("data not saved; use option \"--output\" to save it\n")); - nooutput = 1; - } - else if( !opt.use_embedded_filename ) { - fname = make_outfile_name( iobuf_get_real_fname(pt->buf) ); - if( !fname ) - fname = ask_outfile_name( pt->name, pt->namelen ); - if( !fname ) { - rc = G10ERR_CREATE_FILE; - goto leave; - } - } - else { - fname = make_printable_string( pt->name, pt->namelen, 0 ); - } - - if( nooutput ) - ; - else if( !*fname || (*fname=='-' && !fname[1])) { - /* no filename or "-" given; write to stdout */ - fp = stdout; - #ifdef HAVE_DOSISH_SYSTEM - setmode ( fileno(fp) , O_BINARY ); - #endif - } - else { - while( !overwrite_filep (fname) ) { - char *tmp = ask_outfile_name (NULL, 0); - if ( !tmp || !*tmp ) { - m_free (tmp); - rc = G10ERR_CREATE_FILE; - goto leave; - } - m_free (fname); - fname = tmp; - } - } - - if( fp || nooutput ) - ; - else if( !(fp = fopen(fname,"wb")) ) { - log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - rc = G10ERR_CREATE_FILE; -#ifdef __riscos__ - if (errno == 106) - log_info("perhaps the output file has the same name as the input file?\n"); -#endif /* __riscos__ */ - goto leave; - } - - if( !pt->is_partial ) { - /* we have an actual length (which might be zero). */ - assert( !clearsig ); - if( convert ) { /* text mode */ - for( ; pt->len; pt->len-- ) { - if( (c = iobuf_get(pt->buf)) == -1 ) { - log_error("Problem reading source (%u bytes remaining)\n", - (unsigned)pt->len); - rc = G10ERR_READ_FILE; - goto leave; - } - if( mfx->md ) - md_putc(mfx->md, c ); - #ifndef HAVE_DOSISH_SYSTEM - if( c == '\r' ) /* convert to native line ending */ - continue; /* fixme: this hack might be too simple */ - #endif - if( fp ) { - if( putc( c, fp ) == EOF ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - goto leave; - } - } - } - } - else { /* binary mode */ - byte *buffer = m_alloc( 32768 ); - while( pt->len ) { - int len = pt->len > 32768 ? 32768 : pt->len; - len = iobuf_read( pt->buf, buffer, len ); - if( len == -1 ) { - log_error("Problem reading source (%u bytes remaining)\n", - (unsigned)pt->len); - rc = G10ERR_READ_FILE; - m_free( buffer ); - goto leave; - } - if( mfx->md ) - md_write( mfx->md, buffer, len ); - if( fp ) { - if( fwrite( buffer, 1, len, fp ) != len ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - m_free( buffer ); - goto leave; - } - } - pt->len -= len; - } - m_free( buffer ); - } - } - else if( !clearsig ) { - if( convert ) { /* text mode */ - while( (c = iobuf_get(pt->buf)) != -1 ) { - if( mfx->md ) - md_putc(mfx->md, c ); - #ifndef HAVE_DOSISH_SYSTEM - if( convert && c == '\r' ) - continue; /* fixme: this hack might be too simple */ - #endif - if( fp ) { - if( putc( c, fp ) == EOF ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - goto leave; - } - } - } - } - else { /* binary mode */ - byte *buffer = m_alloc( 32768 ); - int eof; - for( eof=0; !eof; ) { - /* Why do we check for len < 32768: - * If we won't, we would practically read 2 EOFs but - * the first one has already popped the block_filter - * off and therefore we don't catch the boundary. - * So, always assume EOF if iobuf_read returns less bytes - * then requested */ - int len = iobuf_read( pt->buf, buffer, 32768 ); - if( len == -1 ) - break; - if( len < 32768 ) - eof = 1; - if( mfx->md ) - md_write( mfx->md, buffer, len ); - if( fp ) { - if( fwrite( buffer, 1, len, fp ) != len ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - m_free( buffer ); - goto leave; - } - } - } - m_free( buffer ); - } - pt->buf = NULL; - } - else { /* clear text signature - don't hash the last cr,lf */ - int state = 0; - - while( (c = iobuf_get(pt->buf)) != -1 ) { - if( fp ) { - if( putc( c, fp ) == EOF ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - goto leave; - } - } - if( !mfx->md ) - continue; - if( state == 2 ) { - md_putc(mfx->md, '\r' ); - md_putc(mfx->md, '\n' ); - state = 0; - } - if( !state ) { - if( c == '\r' ) - state = 1; - else if( c == '\n' ) - state = 2; - else - md_putc(mfx->md, c ); - } - else if( state == 1 ) { - if( c == '\n' ) - state = 2; - else { - md_putc(mfx->md, '\r' ); - if( c == '\r' ) - state = 1; - else { - state = 0; - md_putc(mfx->md, c ); - } - } - } - } - pt->buf = NULL; - } - - if( fp && fp != stdout && fclose(fp) ) { - log_error("Error closing `%s': %s\n", fname, strerror(errno) ); - fp = NULL; - rc = G10ERR_WRITE_FILE; - goto leave; - } - fp = NULL; - - leave: - if( fp && fp != stdout ) - fclose(fp); - m_free(fname); - return rc; -} - -static void -do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode ) -{ - text_filter_context_t tfx; - int c; - - if( textmode ) { - memset( &tfx, 0, sizeof tfx); - iobuf_push_filter( fp, text_filter, &tfx ); - } - if( md2 ) { /* work around a strange behaviour in pgp2 */ - /* It seems that at least PGP5 converts a single CR to a CR,LF too */ - int lc = -1; - while( (c = iobuf_get(fp)) != -1 ) { - if( c == '\n' && lc == '\r' ) - md_putc(md2, c); - else if( c == '\n' ) { - md_putc(md2, '\r'); - md_putc(md2, c); - } - else if( c != '\n' && lc == '\r' ) { - md_putc(md2, '\n'); - md_putc(md2, c); - } - else - md_putc(md2, c); - - if( md ) - md_putc(md, c ); - lc = c; - } - } - else { - while( (c = iobuf_get(fp)) != -1 ) { - if( md ) - md_putc(md, c ); - } - } -} - - -/**************** - * Ask for the detached datafile and calculate the digest from it. - * INFILE is the name of the input file. - */ -int -ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, - const char *inname, int textmode ) -{ - char *answer = NULL; - IOBUF fp; - int rc = 0; - - fp = open_sigfile( inname ); /* open default file */ - if( !fp && !opt.batch ) { - int any=0; - tty_printf(_("Detached signature.\n")); - do { - m_free(answer); - answer = cpr_get("detached_signature.filename", - _("Please enter name of data file: ")); - cpr_kill_prompt(); - if( any && !*answer ) { - rc = G10ERR_READ_FILE; - goto leave; - } - fp = iobuf_open(answer); - if( !fp && errno == ENOENT ) { - tty_printf("No such file, try again or hit enter to quit.\n"); - any++; - } - else if( !fp ) { - log_error("can't open `%s': %s\n", answer, strerror(errno) ); - rc = G10ERR_READ_FILE; - goto leave; - } - } while( !fp ); - } - - if( !fp ) { - if( opt.verbose ) - log_info(_("reading stdin ...\n")); - fp = iobuf_open( NULL ); - assert(fp); - } - do_hash( md, md2, fp, textmode ); - iobuf_close(fp); - - - leave: - m_free(answer); - return rc; -} - - - -/**************** - * Hash the given files and append the hash to hash context md. - * If FILES is NULL, hash stdin. - */ -int -hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, - const char *sigfilename, int textmode ) -{ - IOBUF fp; - STRLIST sl; - - if( !files ) { - /* check whether we can open the signed material */ - fp = open_sigfile( sigfilename ); - if( fp ) { - do_hash( md, md2, fp, textmode ); - iobuf_close(fp); - return 0; - } - log_error (_("no signed data\n")); - return G10ERR_OPEN_FILE; - } - - - for (sl=files; sl; sl = sl->next ) { - fp = iobuf_open( sl->d ); - if( !fp ) { - log_error(_("can't open signed data `%s'\n"), - print_fname_stdin(sl->d)); - return G10ERR_OPEN_FILE; - } - do_hash( md, md2, fp, textmode ); - iobuf_close(fp); - } - - return 0; -} - - - - - diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c deleted file mode 100644 index 2c8771c27..000000000 --- a/g10/pubkey-enc.c +++ /dev/null @@ -1,296 +0,0 @@ -/* pubkey-enc.c - public key encoded packet 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 -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "packet.h" -#include "mpi.h" -#include "keydb.h" -#include "trustdb.h" -#include "cipher.h" -#include "status.h" -#include "options.h" -#include "main.h" -#include "i18n.h" - -static int get_it( PKT_pubkey_enc *k, - DEK *dek, PKT_secret_key *sk, u32 *keyid ); - - -/* check that the given algo is mentioned in one of the valid user IDs */ -static int -is_algo_in_prefs ( KBNODE keyblock, preftype_t type, int algo ) -{ - KBNODE k; - - for (k=keyblock; k; k=k->next) { - if (k->pkt->pkttype == PKT_USER_ID) { - PKT_user_id *uid = k->pkt->pkt.user_id; - prefitem_t *prefs = uid->prefs; - - if (uid->created && prefs && - !uid->is_revoked && !uid->is_expired ) { - for (; prefs->type; prefs++ ) - if (prefs->type == type && prefs->value == algo) - return 1; - } - } - } - return 0; -} - - -/**************** - * Get the session key from a pubkey enc packet and return - * it in DEK, which should have been allocated in secure memory. - */ -int -get_session_key( PKT_pubkey_enc *k, DEK *dek ) -{ - PKT_secret_key *sk = NULL; - int rc; - - rc = check_pubkey_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC); - if( rc ) - goto leave; - - if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) { - sk = m_alloc_clear( sizeof *sk ); - sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/ - if( !(rc = get_seckey( sk, k->keyid )) ) - rc = get_it( k, dek, sk, k->keyid ); - } - else { /* anonymous receiver: Try all available secret keys */ - void *enum_context = NULL; - u32 keyid[2]; - - for(;;) { - if( sk ) - free_secret_key( sk ); - sk = m_alloc_clear( sizeof *sk ); - rc=enum_secret_keys( &enum_context, sk, 1); - if( rc ) { - rc = G10ERR_NO_SECKEY; - break; - } - if( sk->pubkey_algo != k->pubkey_algo ) - continue; - keyid_from_sk( sk, keyid ); - log_info(_("anonymous recipient; trying secret key %08lX ...\n"), - (ulong)keyid[1] ); - rc = check_secret_key( sk, 1 ); /* ask only once */ - if( !rc ) - rc = get_it( k, dek, sk, keyid ); - if( !rc ) { - log_info(_("okay, we are the anonymous recipient.\n") ); - break; - } - } - enum_secret_keys( &enum_context, NULL, 0 ); /* free context */ - } - - leave: - if( sk ) - free_secret_key( sk ); - return rc; -} - - -static int -get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) -{ - int rc; - MPI plain_dek = NULL; - byte *frame = NULL; - unsigned n, nframe; - u16 csum, csum2; - - rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey ); - if( rc ) - goto leave; - frame = mpi_get_buffer( plain_dek, &nframe, NULL ); - mpi_free( plain_dek ); plain_dek = NULL; - - /* Now get the DEK (data encryption key) from the frame - * - * Old versions encode the DEK in in this format (msb is left): - * - * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 - * - * Later versions encode the DEK like this: - * - * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) - * - * (mpi_get_buffer already removed the leading zero). - * - * RND are non-zero randow bytes. - * A is the cipher algorithm - * DEK is the encryption key (session key) with length k - * CSUM - */ - if( DBG_CIPHER ) - log_hexdump("DEK frame:", frame, nframe ); - n=0; - if( n + 7 > nframe ) - { rc = G10ERR_WRONG_SECKEY; goto leave; } - if( frame[n] == 1 && frame[nframe-1] == 2 ) { - log_info(_("old encoding of the DEK is not supported\n")); - rc = G10ERR_CIPHER_ALGO; - goto leave; - } - if( frame[n] != 2 ) /* somethink is wrong */ - { rc = G10ERR_WRONG_SECKEY; goto leave; } - for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ - ; - n++; /* and the zero byte */ - if( n + 4 > nframe ) - { rc = G10ERR_WRONG_SECKEY; goto leave; } - - dek->keylen = nframe - (n+1) - 2; - dek->algo = frame[n++]; - if( dek->algo == CIPHER_ALGO_IDEA ) - write_status(STATUS_RSA_OR_IDEA); - rc = check_cipher_algo( dek->algo ); - if( rc ) { - if( !opt.quiet && rc == G10ERR_CIPHER_ALGO ) { - log_info(_("cipher algorithm %d%s is unknown or disabled\n"), - dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); - if(dek->algo==CIPHER_ALGO_IDEA) - idea_cipher_warn(0); - } - dek->algo = 0; - goto leave; - } - if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) { - rc = G10ERR_WRONG_SECKEY; - goto leave; - } - - /* copy the key to DEK and compare the checksum */ - csum = frame[nframe-2] << 8; - csum |= frame[nframe-1]; - memcpy( dek->key, frame+n, dek->keylen ); - for( csum2=0, n=0; n < dek->keylen; n++ ) - csum2 += dek->key[n]; - if( csum != csum2 ) { - rc = G10ERR_WRONG_SECKEY; - goto leave; - } - if( DBG_CIPHER ) - log_hexdump("DEK is:", dek->key, dek->keylen ); - /* check that the algo is in the preferences and whether it has expired */ - { - PKT_public_key *pk = NULL; - KBNODE pkb = get_pubkeyblock (keyid); - - if( !pkb ) { - rc = -1; - log_error("oops: public key not found for preference check\n"); - } - else if( pkb->pkt->pkt.public_key->selfsigversion > 3 - && dek->algo != CIPHER_ALGO_3DES - && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) { - /* Don't print a note while we are not on verbose mode, - * the cipher is blowfish and the preferences have twofish - * listed */ - if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH - || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH)) - log_info(_( - "NOTE: cipher algorithm %d not found in preferences\n"), - dek->algo ); - } - - if (!rc) { - KBNODE k; - - for (k=pkb; k; k = k->next) { - if (k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ - u32 aki[2]; - keyid_from_pk(k->pkt->pkt.public_key, aki); - - if (aki[0]==keyid[0] && aki[1]==keyid[1]) { - pk = k->pkt->pkt.public_key; - break; - } - } - } - if (!pk) - BUG (); - if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { - log_info(_("NOTE: secret key %08lX expired at %s\n"), - (ulong)keyid[1], asctimestamp( pk->expiredate) ); - } - } - - if ( pk->is_revoked ) { - log_info( _("NOTE: key has been revoked") ); - putc( '\n', log_stream() ); - show_revocation_reason( pk, 1 ); - } - - release_kbnode (pkb); - rc = 0; - } - - - leave: - mpi_free(plain_dek); - m_free(frame); - return rc; -} - - -/**************** - * Get the session key from the given string. - * String is supposed to be formatted as this: - * : - */ -int -get_override_session_key( DEK *dek, const char *string ) -{ - const char *s; - int i; - - if ( !string ) - return G10ERR_BAD_KEY; - dek->algo = atoi(string); - if ( dek->algo < 1 ) - return G10ERR_BAD_KEY; - if ( !(s = strchr ( string, ':' )) ) - return G10ERR_BAD_KEY; - s++; - for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) { - int c = hextobyte ( s ); - if (c == -1) - return G10ERR_BAD_KEY; - dek->key[i] = c; - } - if ( *s ) - return G10ERR_BAD_KEY; - dek->keylen = i; - return 0; -} - diff --git a/g10/revoke.c b/g10/revoke.c deleted file mode 100644 index b6e9e6398..000000000 --- a/g10/revoke.c +++ /dev/null @@ -1,717 +0,0 @@ -/* revoke.c - * 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 -#include -#include -#include -#include -#include -#include - -#include "options.h" -#include "packet.h" -#include "errors.h" -#include "keydb.h" -#include "memory.h" -#include "util.h" -#include "main.h" -#include "ttyio.h" -#include "status.h" -#include "i18n.h" - - -struct revocation_reason_info { - int code; - char *desc; -}; - - -int -revocation_reason_build_cb( PKT_signature *sig, void *opaque ) -{ - struct revocation_reason_info *reason = opaque; - char *ud = NULL; - byte *buffer; - size_t buflen = 1; - - if(!reason) - return 0; - - if( reason->desc ) { - ud = native_to_utf8( reason->desc ); - buflen += strlen(ud); - } - buffer = m_alloc( buflen ); - *buffer = reason->code; - if( ud ) { - memcpy(buffer+1, ud, strlen(ud) ); - m_free( ud ); - } - - build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen ); - m_free( buffer ); - return 0; -} - -/* Outputs a minimal pk (as defined by 2440) from a keyblock. A - minimal pk consists of the public key packet and a user ID. We try - and pick a user ID that has a uid signature, and include it if - possible. */ -static int -export_minimal_pk(IOBUF out,KBNODE keyblock, - PKT_signature *revsig,PKT_signature *revkey) -{ - KBNODE node; - PACKET pkt; - PKT_user_id *uid=NULL; - PKT_signature *selfsig=NULL; - u32 keyid[2]; - int rc; - - node=find_kbnode(keyblock,PKT_PUBLIC_KEY); - if(!node) - { - log_error(_("key incomplete\n")); - return G10ERR_GENERAL; - } - - keyid_from_pk(node->pkt->pkt.public_key,keyid); - - pkt=*node->pkt; - rc=build_packet(out,&pkt); - if(rc) - { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); - return rc; - } - - init_packet(&pkt); - pkt.pkttype=PKT_SIGNATURE; - - /* the revocation itself, if any. 2440 likes this to come first. */ - if(revsig) - { - pkt.pkt.signature=revsig; - rc=build_packet(out,&pkt); - if(rc) - { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); - return rc; - } - } - - /* If a revkey in a 1F sig is present, include it too */ - if(revkey) - { - pkt.pkt.signature=revkey; - rc=build_packet(out,&pkt); - if(rc) - { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); - return rc; - } - } - - while(!selfsig) - { - KBNODE signode; - - node=find_next_kbnode(node,PKT_USER_ID); - if(!node) - { - /* We're out of user IDs - none were self-signed. */ - if(uid) - break; - else - { - log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]); - return G10ERR_GENERAL; - } - } - - if(node->pkt->pkt.user_id->attrib_data) - continue; - - uid=node->pkt->pkt.user_id; - signode=node; - - while((signode=find_next_kbnode(signode,PKT_SIGNATURE))) - { - if(keyid[0]==signode->pkt->pkt.signature->keyid[0] && - keyid[1]==signode->pkt->pkt.signature->keyid[1] && - IS_UID_SIG(signode->pkt->pkt.signature)) - { - selfsig=signode->pkt->pkt.signature; - break; - } - } - } - - pkt.pkttype=PKT_USER_ID; - pkt.pkt.user_id=uid; - - rc=build_packet(out,&pkt); - if(rc) - { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); - return rc; - } - - if(selfsig) - { - pkt.pkttype=PKT_SIGNATURE; - pkt.pkt.signature=selfsig; - - rc=build_packet(out,&pkt); - if(rc) - { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); - return rc; - } - } - - return 0; -} - -/**************** - * Generate a revocation certificate for UNAME via a designated revoker - */ -int -gen_desig_revoke( const char *uname ) -{ - int rc = 0; - armor_filter_context_t afx; - PKT_public_key *pk = NULL; - PKT_secret_key *sk = NULL; - PKT_signature *sig = NULL; - IOBUF out = NULL; - struct revocation_reason_info *reason = NULL; - KEYDB_HANDLE kdbhd; - KEYDB_SEARCH_DESC desc; - KBNODE keyblock=NULL,node; - u32 keyid[2]; - int i,any=0; - - if( opt.batch ) { - log_error(_("sorry, can't do this in batch mode\n")); - return G10ERR_GENERAL; - } - - memset( &afx, 0, sizeof afx); - - kdbhd = keydb_new (0); - classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; - if (rc) { - log_error (_("key `%s' not found: %s\n"),uname, g10_errstr (rc)); - goto leave; - } - - rc = keydb_get_keyblock (kdbhd, &keyblock ); - if( rc ) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); - goto leave; - } - - /* To parse the revkeys */ - merge_keys_and_selfsig(keyblock); - - /* get the key from the keyblock */ - node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); - if( !node ) - BUG (); - - pk=node->pkt->pkt.public_key; - - keyid_from_pk(pk,keyid); - - /* Are we a designated revoker for this key? */ - - if(!pk->revkey && pk->numrevkeys) - BUG(); - - for(i=0;inumrevkeys;i++) - { - if(sk) - free_secret_key(sk); - - sk=m_alloc_clear(sizeof(*sk)); - - rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN); - - /* We have the revocation key */ - if(!rc) - { - size_t n; - char *p; - u32 sk_keyid[2]; - PKT_signature *revkey=NULL; - - any=1; - keyid_from_sk(sk,sk_keyid); - - tty_printf("\npub %4u%c/%08lX %s ", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk(pk) ); - - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\n\n"); - - tty_printf(_("To be revoked by:\n")); - - tty_printf("\nsec %4u%c/%08lX %s ", - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)sk_keyid[1], datestr_from_sk(sk) ); - - p = get_user_id( sk_keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\n"); - if(pk->revkey[i].class&0x40) - tty_printf(_("(This is a sensitive revocation key)\n")); - tty_printf("\n"); - - if( !cpr_get_answer_is_yes("gen_desig_revoke.okay", - _("Create a revocation certificate for this key? ")) ) - continue; - - /* get the reason for the revocation (this is always v4) */ - reason = ask_revocation_reason( 1, 0, 1 ); - if( !reason ) - continue; - - rc = check_secret_key( sk, 0 ); - if( rc ) - continue; - - if( !opt.armor ) - tty_printf(_("ASCII armored output forced.\n")); - - if( (rc = open_outfile( NULL, 0, &out )) ) - goto leave; - - afx.what = 1; - afx.hdrlines = "Comment: A revocation certificate should follow\n"; - iobuf_push_filter( out, armor_filter, &afx ); - - /* create it */ - rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, - 0, 0, 0, - revocation_reason_build_cb, reason ); - if( rc ) { - log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); - goto leave; - } - - /* Spit out a minimal pk as well, since otherwise there is - no way to know which key to attach this revocation to. - Also include the direct key signature that contains - this revocation key. We're allowed to include - sensitive revocation keys along with a revocation, as - this may be the only time the recipient has seen it. - Note that this means that if we have multiple different - sensitive revocation keys in a given direct key - signature, we're going to include them all here. This - is annoying, but the good outweighs the bad, since - without including this a sensitive revoker can't really - do their job. People should not include multiple - sensitive revocation keys in one signature: 2440 says - "Note that it may be appropriate to isolate this - subpacket within a separate signature so that it is not - combined with other subpackets that need to be - exported." -dms */ - - while(!revkey) - { - KBNODE signode; - - signode=find_next_kbnode(node,PKT_SIGNATURE); - if(!signode) - break; - - node=signode; - - if(keyid[0]==signode->pkt->pkt.signature->keyid[0] && - keyid[1]==signode->pkt->pkt.signature->keyid[1] && - IS_KEY_SIG(signode->pkt->pkt.signature)) - { - int j; - - for(j=0;jpkt->pkt.signature->numrevkeys;j++) - { - if(pk->revkey[i].class== - signode->pkt->pkt.signature->revkey[j]->class && - pk->revkey[i].algid== - signode->pkt->pkt.signature->revkey[j]->algid && - memcmp(pk->revkey[i].fpr, - signode->pkt->pkt.signature->revkey[j]->fpr, - MAX_FINGERPRINT_LEN)==0) - { - revkey=signode->pkt->pkt.signature; - break; - } - } - } - } - - if(!revkey) - BUG(); - - rc=export_minimal_pk(out,keyblock,sig,revkey); - if(rc) - goto leave; - - /* and issue a usage notice */ - tty_printf(_("Revocation certificate created.\n")); - break; - } - } - - if(!any) - log_error(_("no revocation keys found for `%s'\n"),uname); - - leave: - if( pk ) - free_public_key( pk ); - if( sk ) - free_secret_key( sk ); - if( sig ) - free_seckey_enc( sig ); - - if( rc ) - iobuf_cancel(out); - else - iobuf_close(out); - release_revocation_reason_info( reason ); - return rc; -} - - -/**************** - * Generate a revocation certificate for UNAME - */ -int -gen_revoke( const char *uname ) -{ - int rc = 0; - armor_filter_context_t afx; - PACKET pkt; - PKT_secret_key *sk; /* used as pointer into a kbnode */ - PKT_public_key *pk = NULL; - PKT_signature *sig = NULL; - u32 sk_keyid[2]; - IOBUF out = NULL; - KBNODE keyblock = NULL, pub_keyblock = NULL; - KBNODE node; - KEYDB_HANDLE kdbhd; - struct revocation_reason_info *reason = NULL; - KEYDB_SEARCH_DESC desc; - - if( opt.batch ) { - log_error(_("sorry, can't do this in batch mode\n")); - return G10ERR_GENERAL; - } - - memset( &afx, 0, sizeof afx); - init_packet( &pkt ); - - /* search the userid: - * We don't want the whole getkey stuff here but the entire keyblock - */ - kdbhd = keydb_new (1); - classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; - if (rc) { - log_error (_("secret key `%s' not found: %s\n"), - uname, g10_errstr (rc)); - goto leave; - } - - rc = keydb_get_keyblock (kdbhd, &keyblock ); - if( rc ) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); - goto leave; - } - - /* get the keyid from the keyblock */ - node = find_kbnode( keyblock, PKT_SECRET_KEY ); - if( !node ) - BUG (); - - /* fixme: should make a function out of this stuff, - * it's used all over the source */ - sk = node->pkt->pkt.secret_key; - keyid_from_sk( sk, sk_keyid ); - tty_printf("\nsec %4u%c/%08lX %s ", - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)sk_keyid[1], datestr_from_sk(sk) ); - { - size_t n; - char *p = get_user_id( sk_keyid, &n ); - tty_print_utf8_string( p, n ); - m_free(p); - tty_printf("\n"); - } - pk = m_alloc_clear( sizeof *pk ); - - /* FIXME: We should get the public key direct from the secret one */ - - pub_keyblock=get_pubkeyblock(sk_keyid); - if(!pub_keyblock) - { - log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) ); - goto leave; - } - - node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY); - if(!node) - BUG(); - - pk=node->pkt->pkt.public_key; - - if( cmp_public_secret_key( pk, sk ) ) { - log_error(_("public key does not match secret key!\n") ); - rc = G10ERR_GENERAL; - goto leave; - } - - tty_printf("\n"); - if( !cpr_get_answer_is_yes("gen_revoke.okay", - _("Create a revocation certificate for this key? ")) ){ - rc = 0; - goto leave; - } - - if(sk->version>=4 || opt.force_v4_certs) { - /* get the reason for the revocation */ - reason = ask_revocation_reason( 1, 0, 1 ); - if( !reason ) { /* user decided to cancel */ - rc = 0; - goto leave; - } - } - - switch( is_secret_key_protected( sk ) ) { - case -1: - log_error(_("unknown protection algorithm\n")); - rc = G10ERR_PUBKEY_ALGO; - break; - case 0: - tty_printf(_("NOTE: This key is not protected!\n")); - break; - default: - rc = check_secret_key( sk, 0 ); - break; - } - if( rc ) - goto leave; - - - if( !opt.armor ) - tty_printf(_("ASCII armored output forced.\n")); - - if( (rc = open_outfile( NULL, 0, &out )) ) - goto leave; - - afx.what = 1; - afx.hdrlines = "Comment: A revocation certificate should follow\n"; - iobuf_push_filter( out, armor_filter, &afx ); - - /* create it */ - rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, - opt.force_v4_certs?4:0, 0, 0, - revocation_reason_build_cb, reason ); - if( rc ) { - log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); - goto leave; - } - - if(opt.pgp2 || opt.pgp6 || opt.pgp7) - { - /* Use a minimal pk for PGPx mode, since PGP can't import bare - revocation certificates. */ - rc=export_minimal_pk(out,pub_keyblock,sig,NULL); - if(rc) - goto leave; - } - else - { - init_packet( &pkt ); - pkt.pkttype = PKT_SIGNATURE; - pkt.pkt.signature = sig; - - rc = build_packet( out, &pkt ); - if( rc ) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); - goto leave; - } - } - - /* and issue a usage notice */ - tty_printf(_("Revocation certificate created.\n\n" -"Please move it to a medium which you can hide away; if Mallory gets\n" -"access to this certificate he can use it to make your key unusable.\n" -"It is smart to print this certificate and store it away, just in case\n" -"your media become unreadable. But have some caution: The print system of\n" -"your machine might store the data and make it available to others!\n")); - - leave: - if( sig ) - free_seckey_enc( sig ); - release_kbnode( keyblock ); - release_kbnode( pub_keyblock ); - keydb_release (kdbhd); - if( rc ) - iobuf_cancel(out); - else - iobuf_close(out); - release_revocation_reason_info( reason ); - return rc; -} - - - -struct revocation_reason_info * -ask_revocation_reason( int key_rev, int cert_rev, int hint ) -{ - int code=-1; - char *description = NULL; - struct revocation_reason_info *reason; - const char *text_0 = _("No reason specified"); - const char *text_1 = _("Key has been compromised"); - const char *text_2 = _("Key is superseded"); - const char *text_3 = _("Key is no longer used"); - const char *text_4 = _("User ID is no longer valid"); - const char *code_text = NULL; - - do { - m_free(description); - description = NULL; - - tty_printf(_("Please select the reason for the revocation:\n")); - tty_printf( " 0 = %s\n", text_0 ); - if( key_rev ) - tty_printf(" 1 = %s\n", text_1 ); - if( key_rev ) - tty_printf(" 2 = %s\n", text_2 ); - if( key_rev ) - tty_printf(" 3 = %s\n", text_3 ); - if( cert_rev ) - tty_printf(" 4 = %s\n", text_4 ); - tty_printf( " Q = %s\n", _("Cancel") ); - if( hint ) - tty_printf(_("(Probably you want to select %d here)\n"), hint ); - - while(code==-1) { - int n; - char *answer = cpr_get("ask_revocation_reason.code", - _("Your decision? ")); - trim_spaces( answer ); - cpr_kill_prompt(); - if( *answer == 'q' || *answer == 'Q') - return NULL; /* cancel */ - if( hint && !*answer ) - n = hint; - else if(!isdigit( *answer ) ) - n = -1; - else - n = atoi(answer); - m_free(answer); - if( n == 0 ) { - code = 0x00; /* no particular reason */ - code_text = text_0; - } - else if( key_rev && n == 1 ) { - code = 0x02; /* key has been compromised */ - code_text = text_1; - } - else if( key_rev && n == 2 ) { - code = 0x01; /* key is superseded */ - code_text = text_2; - } - else if( key_rev && n == 3 ) { - code = 0x03; /* key is no longer used */ - code_text = text_3; - } - else if( cert_rev && n == 4 ) { - code = 0x20; /* uid is no longer valid */ - code_text = text_4; - } - else - tty_printf(_("Invalid selection.\n")); - } - - tty_printf(_("Enter an optional description; " - "end it with an empty line:\n") ); - for(;;) { - char *answer = cpr_get("ask_revocation_reason.text", "> " ); - trim_trailing_ws( answer, strlen(answer) ); - cpr_kill_prompt(); - if( !*answer ) { - m_free(answer); - break; - } - - { - char *p = make_printable_string( answer, strlen(answer), 0 ); - m_free(answer); - answer = p; - } - - if( !description ) - description = m_strdup(answer); - else { - char *p = m_alloc( strlen(description) + strlen(answer) + 2 ); - strcpy(stpcpy(stpcpy( p, description),"\n"),answer); - m_free(description); - description = p; - } - m_free(answer); - } - - tty_printf(_("Reason for revocation: %s\n"), code_text ); - if( !description ) - tty_printf(_("(No description given)\n") ); - else - tty_printf("%s\n", description ); - - } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay", - _("Is this okay? ")) ); - - reason = m_alloc( sizeof *reason ); - reason->code = code; - reason->desc = description; - return reason; -} - -void -release_revocation_reason_info( struct revocation_reason_info *reason ) -{ - if( reason ) { - m_free( reason->desc ); - m_free( reason ); - } -} diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c deleted file mode 100644 index d19ac683a..000000000 --- a/g10/seckey-cert.c +++ /dev/null @@ -1,382 +0,0 @@ -/* seckey-cert.c - secret key certificate packet 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 -#include -#include -#include -#include -#include "util.h" -#include "memory.h" -#include "packet.h" -#include "mpi.h" -#include "keydb.h" -#include "cipher.h" -#include "main.h" -#include "options.h" -#include "i18n.h" -#include "status.h" - - -static int -do_check( PKT_secret_key *sk, const char *tryagain_text ) -{ - byte *buffer; - u16 csum=0; - int i, res; - unsigned nbytes; - - if( sk->is_protected ) { /* remove the protection */ - DEK *dek = NULL; - u32 keyid[4]; /* 4! because we need two of them */ - CIPHER_HANDLE cipher_hd=NULL; - PKT_secret_key *save_sk; - - if( sk->protect.s2k.mode == 1001 ) { - log_info(_("secret key parts are not available\n")); - return G10ERR_GENERAL; - } - if( sk->protect.algo == CIPHER_ALGO_NONE ) - BUG(); - if( check_cipher_algo( sk->protect.algo ) ) { - log_info(_("protection algorithm %d%s is not supported\n"), - sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" ); - if(sk->protect.algo==CIPHER_ALGO_IDEA) - idea_cipher_warn(0); - return G10ERR_CIPHER_ALGO; - } - keyid_from_sk( sk, keyid ); - keyid[2] = keyid[3] = 0; - if( !sk->is_primary ) { - keyid[2] = sk->main_keyid[0]; - keyid[3] = sk->main_keyid[1]; - } - dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo, - &sk->protect.s2k, 0, tryagain_text ); - cipher_hd = cipher_open( sk->protect.algo, - CIPHER_MODE_AUTO_CFB, 1); - cipher_setkey( cipher_hd, dek->key, dek->keylen ); - m_free(dek); - save_sk = copy_secret_key( NULL, sk ); - cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); - csum = 0; - if( sk->version >= 4 ) { - int ndata; - byte *p, *data; - u16 csumc = 0; - - i = pubkey_get_npkey(sk->pubkey_algo); - assert( mpi_is_opaque( sk->skey[i] ) ); - p = mpi_get_opaque( sk->skey[i], &ndata ); - if ( ndata > 1 ) - csumc = p[ndata-2] << 8 | p[ndata-1]; - data = m_alloc_secure( ndata ); - cipher_decrypt( cipher_hd, data, p, ndata ); - mpi_free( sk->skey[i] ); sk->skey[i] = NULL ; - p = data; - if (sk->protect.sha1chk) { - /* This is the new SHA1 checksum method to detect - tampering with the key as used by the Klima/Rosa - attack */ - sk->csum = 0; - csum = 1; - if( ndata < 20 ) - log_error("not enough bytes for SHA-1 checksum\n"); - else { - MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1); - if (!h) - BUG(); /* algo not available */ - md_write (h, data, ndata - 20); - md_final (h); - if (!memcmp (md_read (h, DIGEST_ALGO_SHA1), - data + ndata - 20, 20) ) { - /* digest does match. We have to keep the old - style checksum in sk->csum, so that the - test used for unprotected keys does work. - This test gets used when we are adding new - keys. */ - sk->csum = csum = checksum (data, ndata-20); - } - md_close (h); - } - } - else { - if( ndata < 2 ) { - log_error("not enough bytes for checksum\n"); - sk->csum = 0; - csum = 1; - } - else { - csum = checksum( data, ndata-2); - sk->csum = data[ndata-2] << 8 | data[ndata-1]; - if ( sk->csum != csum ) { - /* This is a PGP 7.0.0 workaround */ - sk->csum = csumc; /* take the encrypted one */ - } - } - } - - /* must check it here otherwise the mpi_read_xx would fail - because the length may have an arbitrary value */ - if( sk->csum == csum ) { - for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - nbytes = ndata; - sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 ); - ndata -= nbytes; - p += nbytes; - } - /* Note: at this point ndata should be 2 for a simple - checksum or 20 for the sha1 digest */ - } - m_free(data); - } - else { - for(i=pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - byte *p; - int ndata; - unsigned int dummy; - - assert (mpi_is_opaque (sk->skey[i])); - p = mpi_get_opaque (sk->skey[i], &ndata); - assert (ndata >= 2); - assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2); - buffer = m_alloc_secure (ndata); - cipher_sync (cipher_hd); - buffer[0] = p[0]; - buffer[1] = p[1]; - cipher_decrypt (cipher_hd, buffer+2, p+2, ndata-2); - csum += checksum (buffer, ndata); - mpi_free (sk->skey[i]); - dummy = ndata; - sk->skey[i] = mpi_read_from_buffer (buffer, &dummy, 1); - assert (sk->skey[i]); - m_free (buffer); -/* csum += checksum_mpi (sk->skey[i]); */ - } - } - cipher_close( cipher_hd ); - /* now let's see whether we have used the right passphrase */ - if( csum != sk->csum ) { - copy_secret_key( sk, save_sk ); - passphrase_clear_cache ( keyid, sk->pubkey_algo ); - free_secret_key( save_sk ); - return G10ERR_BAD_PASS; - } - /* the checksum may fail, so we also check the key itself */ - res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey ); - if( res ) { - copy_secret_key( sk, save_sk ); - passphrase_clear_cache ( keyid, sk->pubkey_algo ); - free_secret_key( save_sk ); - return G10ERR_BAD_PASS; - } - free_secret_key( save_sk ); - sk->is_protected = 0; - } - else { /* not protected, assume it is okay if the checksum is okay */ - csum = 0; - for(i=pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - csum += checksum_mpi( sk->skey[i] ); - } - if( csum != sk->csum ) - return G10ERR_CHECKSUM; - } - - return 0; -} - - - -/**************** - * Check the secret key - * Ask up to 3 (or n) times for a correct passphrase - */ -int -check_secret_key( PKT_secret_key *sk, int n ) -{ - int rc = G10ERR_BAD_PASS; - int i; - - if( n < 1 ) - n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */ - - for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) { - const char *tryagain = NULL; - if (i) { - tryagain = _("Invalid passphrase; please try again"); - log_info (_("%s ...\n"), tryagain); - } - rc = do_check( sk, tryagain ); - if( rc == G10ERR_BAD_PASS && is_status_enabled() ) { - u32 kid[2]; - char buf[50]; - - keyid_from_sk( sk, kid ); - sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]); - write_status_text( STATUS_BAD_PASSPHRASE, buf ); - } - if( have_static_passphrase() ) - break; - } - - if( !rc ) - write_status( STATUS_GOOD_PASSPHRASE ); - - return rc; -} - -/**************** - * check whether the secret key is protected. - * Returns: 0 not protected, -1 on error or the protection algorithm - */ -int -is_secret_key_protected( PKT_secret_key *sk ) -{ - return sk->is_protected? sk->protect.algo : 0; -} - - - -/**************** - * Protect the secret key with the passphrase from DEK - */ -int -protect_secret_key( PKT_secret_key *sk, DEK *dek ) -{ - int i,j, rc = 0; - byte *buffer; - unsigned nbytes; - u16 csum; - - if( !dek ) - return 0; - - if( !sk->is_protected ) { /* okay, apply the protection */ - CIPHER_HANDLE cipher_hd=NULL; - - if( check_cipher_algo( sk->protect.algo ) ) - rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */ - else { - print_cipher_algo_note( sk->protect.algo ); - cipher_hd = cipher_open( sk->protect.algo, - CIPHER_MODE_AUTO_CFB, 1 ); - if( cipher_setkey( cipher_hd, dek->key, dek->keylen ) ) - log_info(_("WARNING: Weak key detected" - " - please change passphrase again.\n")); - sk->protect.ivlen = cipher_get_blocksize( sk->protect.algo ); - assert( sk->protect.ivlen <= DIM(sk->protect.iv) ); - if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 ) - BUG(); /* yes, we are very careful */ - randomize_buffer(sk->protect.iv, sk->protect.ivlen, 1); - cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); - if( sk->version >= 4 ) { - byte *bufarr[PUBKEY_MAX_NSKEY]; - unsigned narr[PUBKEY_MAX_NSKEY]; - unsigned nbits[PUBKEY_MAX_NSKEY]; - int ndata=0; - byte *p, *data; - - for(j=0, i = pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) { - assert( !mpi_is_opaque( sk->skey[i] ) ); - bufarr[j] = mpi_get_buffer( sk->skey[i], &narr[j], NULL ); - nbits[j] = mpi_get_nbits( sk->skey[i] ); - ndata += narr[j] + 2; - } - for( ; j < PUBKEY_MAX_NSKEY; j++ ) - bufarr[j] = NULL; - ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */ - - data = m_alloc_secure( ndata ); - p = data; - for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) { - p[0] = nbits[j] >> 8 ; - p[1] = nbits[j]; - p += 2; - memcpy(p, bufarr[j], narr[j] ); - p += narr[j]; - m_free(bufarr[j]); - } - - if (opt.simple_sk_checksum) { - log_info (_("generating the deprecated 16-bit checksum" - " for secret key protection\n")); - csum = checksum( data, ndata-2); - sk->csum = csum; - *p++ = csum >> 8; - *p++ = csum; - sk->protect.sha1chk = 0; - } - else { - MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1); - if (!h) - BUG(); /* algo not available */ - md_write (h, data, ndata - 20); - md_final (h); - memcpy (p, md_read (h, DIGEST_ALGO_SHA1), 20); - p += 20; - md_close (h); - sk->csum = csum = 0; - sk->protect.sha1chk = 1; - } - assert( p == data+ndata ); - - cipher_encrypt( cipher_hd, data, data, ndata ); - for(i = pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - mpi_free( sk->skey[i] ); - sk->skey[i] = NULL; - } - i = pubkey_get_npkey(sk->pubkey_algo); - sk->skey[i] = mpi_set_opaque(NULL, data, ndata ); - } - else { - csum = 0; - for(i=pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - byte *data; - unsigned int nbits; - - csum += checksum_mpi (sk->skey[i]); - buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL ); - cipher_sync (cipher_hd); - assert ( !mpi_is_opaque (sk->skey[i]) ); - data = m_alloc (nbytes+2); - nbits = mpi_get_nbits (sk->skey[i]); - assert (nbytes == (nbits + 7)/8); - data[0] = nbits >> 8; - data[1] = nbits; - cipher_encrypt (cipher_hd, data+2, buffer, nbytes); - m_free( buffer ); - - mpi_free (sk->skey[i]); - sk->skey[i] = mpi_set_opaque (NULL, data, nbytes+2); - } - sk->csum = csum; - } - sk->is_protected = 1; - cipher_close( cipher_hd ); - } - } - return rc; -} - diff --git a/g10/sig-check.c b/g10/sig-check.c deleted file mode 100644 index c068e4409..000000000 --- a/g10/sig-check.c +++ /dev/null @@ -1,619 +0,0 @@ -/* sig-check.c - Check a signature - * 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 -#include -#include -#include -#include -#include "util.h" -#include "packet.h" -#include "memory.h" -#include "mpi.h" -#include "keydb.h" -#include "cipher.h" -#include "main.h" -#include "status.h" -#include "i18n.h" -#include "options.h" - -struct cmp_help_context_s { - PKT_signature *sig; - MD_HANDLE md; -}; - -static int do_check( PKT_public_key *pk, PKT_signature *sig, - MD_HANDLE digest, int *r_expired ); - -/**************** - * Check the signature which is contained in SIG. - * The MD_HANDLE should be currently open, so that this function - * is able to append some data, before finalizing the digest. - */ -int -signature_check( PKT_signature *sig, MD_HANDLE digest ) -{ - u32 dummy; - int dum2; - return signature_check2( sig, digest, &dummy, &dum2 ); -} - -int -signature_check2( PKT_signature *sig, MD_HANDLE digest, - u32 *r_expiredate, int *r_expired ) -{ - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - int rc=0; - - *r_expiredate = 0; - - /* Sanity check that the md has a context for the hash that the - sig is expecting. This can happen if a onepass sig header does - not match the actual sig, and also if the clearsign "Hash:" - header is missing or does not match the actual sig. */ - - if(!md_algo_present(digest,sig->digest_algo)) { - log_info(_("WARNING: signature digest conflict in message\n")); - rc=G10ERR_BAD_SIGN; - } - else if( get_pubkey( pk, sig->keyid ) ) - rc = G10ERR_NO_PUBKEY; - else if(!pk->is_valid && !pk->is_primary) - rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an - invalid subkey */ - else { - *r_expiredate = pk->expiredate; - rc = do_check( pk, sig, digest, r_expired ); - } - - free_public_key( pk ); - - if( !rc && sig->sig_class < 2 && is_status_enabled() ) { - /* This signature id works best with DLP algorithms because - * they use a random parameter for every signature. Instead of - * this sig-id we could have also used the hash of the document - * and the timestamp, but the drawback of this is, that it is - * not possible to sign more than one identical document within - * one second. Some remote batch processing applications might - * like this feature here */ - MD_HANDLE md; - u32 a = sig->timestamp; - int i, nsig = pubkey_get_nsig( sig->pubkey_algo ); - byte *p, *buffer; - - md = md_open( DIGEST_ALGO_RMD160, 0); - md_putc( digest, sig->pubkey_algo ); - md_putc( digest, sig->digest_algo ); - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); - for(i=0; i < nsig; i++ ) { - unsigned n = mpi_get_nbits( sig->data[i]); - - md_putc( md, n>>8); - md_putc( md, n ); - p = mpi_get_buffer( sig->data[i], &n, NULL ); - md_write( md, p, n ); - m_free(p); - } - md_final( md ); - p = make_radix64_string( md_read( md, 0 ), 20 ); - buffer = m_alloc( strlen(p) + 60 ); - sprintf( buffer, "%s %s %lu", - p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp ); - write_status_text( STATUS_SIG_ID, buffer ); - m_free(buffer); - m_free(p); - md_close(md); - } - - return rc; -} - - -/**************** - * This function gets called by pubkey_verify() if the algorithm needs it. - */ -static int -cmp_help( void *opaque, MPI result ) -{ - #if 0 /* we do not use this anymore */ - int rc=0, i, j, c, old_enc; - byte *dp; - const byte *asn; - size_t mdlen, asnlen; - struct cmp_help_context_s *ctx = opaque; - PKT_signature *sig = ctx->sig; - MD_HANDLE digest = ctx->md; - - old_enc = 0; - for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) { - if( !j ) { - if( !i && c != 1 ) - break; - else if( i && c == 0xff ) - ; /* skip the padding */ - else if( i && !c ) - j++; - else - break; - } - else if( ++j == 18 && c != 1 ) - break; - else if( j == 19 && c == 0 ) { - old_enc++; - break; - } - } - if( old_enc ) { - log_error("old encoding scheme is not supported\n"); - return G10ERR_GENERAL; - } - - if( (rc=check_digest_algo(sig->digest_algo)) ) - return rc; /* unsupported algo */ - asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen ); - - for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0; - i++, j-- ) - if( asn[j] != c ) - break; - if( j != -1 || mpi_getbyte(result, i) ) - return G10ERR_BAD_PUBKEY; /* ASN is wrong */ - for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) - if( c != 0xff ) - break; - i++; - if( c != sig->digest_algo || mpi_getbyte(result, i) ) { - /* Padding or leading bytes in signature is wrong */ - return G10ERR_BAD_PUBKEY; - } - if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0] - || mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) { - /* Wrong key used to check the signature */ - return G10ERR_BAD_PUBKEY; - } - - dp = md_read( digest, sig->digest_algo ); - for(i=mdlen-1; i >= 0; i--, dp++ ) { - if( mpi_getbyte( result, i ) != *dp ) - return G10ERR_BAD_SIGN; - } - return 0; - #else - return -1; - #endif -} - -static int -do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) -{ - u32 cur_time; - - *r_expired = 0; - if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { - log_info(_("key %08lX: this is a PGP generated " - "ElGamal key which is NOT secure for signatures!\n"), - (ulong)keyid_from_pk(pk,NULL)); - return G10ERR_PUBKEY_ALGO; - } - - if( pk->timestamp > sig->timestamp ) { - ulong d = pk->timestamp - sig->timestamp; - log_info( d==1 - ? _("public key %08lX is %lu second newer than the signature\n") - : _("public key %08lX is %lu seconds newer than the signature\n"), - (ulong)keyid_from_pk(pk,NULL),d ); - if( !opt.ignore_time_conflict ) - return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */ - } - - cur_time = make_timestamp(); - if( pk->timestamp > cur_time ) { - ulong d = pk->timestamp - cur_time; - log_info( d==1 ? _("key %08lX has been created %lu second " - "in future (time warp or clock problem)\n") - : _("key %08lX has been created %lu seconds " - "in future (time warp or clock problem)\n"), - (ulong)keyid_from_pk(pk,NULL),d ); - if( !opt.ignore_time_conflict ) - return G10ERR_TIME_CONFLICT; - } - - if( pk->expiredate && pk->expiredate < cur_time ) { - char buf[11]; - if (opt.verbose) { - u32 tmp_kid[2]; - - keyid_from_pk( pk, tmp_kid ); - log_info(_("NOTE: signature key %08lX expired %s\n"), - (ulong)tmp_kid[1], asctimestamp( pk->expiredate ) ); - } - /* SIGEXPIRED is deprecated. Use KEYEXPIRED. */ - sprintf(buf,"%lu",(ulong)pk->expiredate); - write_status_text(STATUS_KEYEXPIRED,buf); - write_status(STATUS_SIGEXPIRED); - *r_expired = 1; - } - - return 0; -} - - -static int -do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, - int *r_expired ) -{ - MPI result = NULL; - int rc=0; - struct cmp_help_context_s ctx; - - if( (rc=do_check_messages(pk,sig,r_expired)) ) - return rc; - if( (rc=check_digest_algo(sig->digest_algo)) ) - return rc; - if( (rc=check_pubkey_algo(sig->pubkey_algo)) ) - return rc; - - /* make sure the digest algo is enabled (in case of a detached signature)*/ - md_enable( digest, sig->digest_algo ); - - /* complete the digest */ - if( sig->version >= 4 ) - md_putc( digest, sig->version ); - md_putc( digest, sig->sig_class ); - if( sig->version < 4 ) { - u32 a = sig->timestamp; - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); - } - else { - byte buf[6]; - size_t n; - md_putc( digest, sig->pubkey_algo ); - md_putc( digest, sig->digest_algo ); - if( sig->hashed ) { - n = sig->hashed->len; - md_putc (digest, (n >> 8) ); - md_putc (digest, n ); - md_write (digest, sig->hashed->data, n); - n += 6; - } - else { - /* Two octets for the (empty) length of the hashed - section. */ - md_putc (digest, 0); - md_putc (digest, 0); - n = 6; - } - /* add some magic */ - buf[0] = sig->version; - buf[1] = 0xff; - buf[2] = n >> 24; - buf[3] = n >> 16; - buf[4] = n >> 8; - buf[5] = n; - md_write( digest, buf, 6 ); - } - md_final( digest ); - - result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), 0 ); - if (!result) - return G10ERR_GENERAL; - ctx.sig = sig; - ctx.md = digest; - rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, - cmp_help, &ctx ); - mpi_free( result ); - if( (opt.emulate_bugs & EMUBUG_MDENCODE) - && rc == G10ERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) { - /* In this case we try again because old GnuPG versions didn't encode - * the hash right. There is no problem with DSA however */ - result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), (sig->version < 5) ); - if (!result) - rc = G10ERR_GENERAL; - else { - ctx.sig = sig; - ctx.md = digest; - rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, - cmp_help, &ctx ); - } - } - - if( !rc && sig->flags.unknown_critical ) { - log_info(_("assuming bad signature from key %08lX due to an unknown critical bit\n"),(ulong)keyid_from_pk(pk,NULL)); - rc = G10ERR_BAD_SIGN; - } - - return rc; -} - - -static void -hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) -{ - PKT_user_id *uid = unode->pkt->pkt.user_id; - - assert( unode->pkt->pkttype == PKT_USER_ID ); - if( uid->attrib_data ) { - if( sig->version >=4 ) { - byte buf[5]; - buf[0] = 0xd1; /* packet of type 17 */ - buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ - buf[2] = uid->attrib_len >> 16; - buf[3] = uid->attrib_len >> 8; - buf[4] = uid->attrib_len; - md_write( md, buf, 5 ); - } - md_write( md, uid->attrib_data, uid->attrib_len ); - } - else { - if( sig->version >=4 ) { - byte buf[5]; - buf[0] = 0xb4; /* indicates a userid packet */ - buf[1] = uid->len >> 24; /* always use 4 length bytes */ - buf[2] = uid->len >> 16; - buf[3] = uid->len >> 8; - buf[4] = uid->len; - md_write( md, buf, 5 ); - } - md_write( md, uid->name, uid->len ); - } -} - -static void -cache_sig_result ( PKT_signature *sig, int result ) -{ - if ( !result ) { - sig->flags.checked = 1; - sig->flags.valid = 1; - } - else if ( result == G10ERR_BAD_SIGN ) { - sig->flags.checked = 1; - sig->flags.valid = 0; - } - else { - sig->flags.checked = 0; - sig->flags.valid = 0; - } -} - - -/* Check the revocation keys to see if any of them have revoked our - pk. sig is the revocation sig. pk is the key it is on. This code - will need to be modified if gpg ever becomes multi-threaded. Note - that this guarantees that a designated revocation sig will never be - considered valid unless it is actually valid, as well as being - issued by a revocation key in a valid direct signature. Note that - this is written so that a revoked revoker can still issue - revocations: i.e. If A revokes B, but A is revoked, B is still - revoked. I'm not completely convinced this is the proper behavior, - but it matches how PGP does it. -dms */ - -/* Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not - revoked */ -int -check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) -{ - static int busy=0; - int i,rc=G10ERR_GENERAL; - - assert(IS_KEY_REV(sig)); - assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1])); - - if(busy) - { - /* return -1 (i.e. not revoked), but mark the pk as uncacheable - as we don't really know its revocation status until it is - checked directly. */ - - pk->dont_cache=1; - return rc; - } - - busy=1; - - /* printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1], - (ulong)sig->keyid[1]); */ - - /* is the issuer of the sig one of our revokers? */ - if( !pk->revkey && pk->numrevkeys ) - BUG(); - else - for(i=0;inumrevkeys;i++) - { - u32 keyid[2]; - - keyid_from_fingerprint(pk->revkey[i].fpr,MAX_FINGERPRINT_LEN,keyid); - - if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1]) - { - MD_HANDLE md; - - md=md_open(sig->digest_algo,0); - hash_public_key(md,pk); - rc=signature_check(sig,md); - cache_sig_result(sig,rc); - break; - } - } - - busy=0; - - return rc; -} - -/**************** - * check the signature pointed to by NODE. This is a key signature. - * If the function detects a self-signature, it uses the PK from - * ROOT and does not read any public key. - */ -int -check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) -{ - u32 dummy; - int dum2; - return check_key_signature2(root, node, is_selfsig, &dummy, &dum2 ); -} - -int -check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, - u32 *r_expiredate, int *r_expired ) -{ - MD_HANDLE md; - PKT_public_key *pk; - PKT_signature *sig; - int algo; - int rc; - - if( is_selfsig ) - *is_selfsig = 0; - *r_expiredate = 0; - *r_expired = 0; - assert( node->pkt->pkttype == PKT_SIGNATURE ); - assert( root->pkt->pkttype == PKT_PUBLIC_KEY ); - - pk = root->pkt->pkt.public_key; - sig = node->pkt->pkt.signature; - algo = sig->digest_algo; - - /* check whether we have cached the result of a previous signature check.*/ - if ( !opt.no_sig_cache ) { - if (sig->flags.checked) { /*cached status available*/ - if( is_selfsig ) { - u32 keyid[2]; - - keyid_from_pk( pk, keyid ); - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) - *is_selfsig = 1; - } - if((rc=do_check_messages(pk,sig,r_expired))) - return rc; - return sig->flags.valid? 0 : G10ERR_BAD_SIGN; - } - } - - if( (rc=check_digest_algo(algo)) ) - return rc; - - if( sig->sig_class == 0x20 ) { /* key revocation */ - u32 keyid[2]; - keyid_from_pk( pk, keyid ); - - /* is it a designated revoker? */ - if(keyid[0]!=sig->keyid[0] || keyid[1]!=sig->keyid[1]) - rc=check_revocation_keys(pk,sig); - else - { - md = md_open( algo, 0 ); - hash_public_key( md, pk ); - rc = do_check( pk, sig, md, r_expired ); - cache_sig_result ( sig, rc ); - md_close(md); - } - } - else if( sig->sig_class == 0x28 ) { /* subkey revocation */ - KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); - - if( snode ) { - md = md_open( algo, 0 ); - hash_public_key( md, pk ); - hash_public_key( md, snode->pkt->pkt.public_key ); - rc = do_check( pk, sig, md, r_expired ); - cache_sig_result ( sig, rc ); - md_close(md); - } - else { - if (!opt.quiet) - log_info (_("key %08lX: no subkey for subkey " - "revocation signature\n"), - (ulong)keyid_from_pk (pk, NULL)); - rc = G10ERR_SIG_CLASS; - } - } - else if( sig->sig_class == 0x18 ) { /* key binding */ - KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); - - if( snode ) { - if( is_selfsig ) { /* does this make sense????? */ - u32 keyid[2]; /* it should always be a selfsig */ - - keyid_from_pk( pk, keyid ); - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) - *is_selfsig = 1; - } - md = md_open( algo, 0 ); - hash_public_key( md, pk ); - hash_public_key( md, snode->pkt->pkt.public_key ); - rc = do_check( pk, sig, md, r_expired ); - cache_sig_result ( sig, rc ); - md_close(md); - } - else { - if (!opt.quiet) - log_info ("key %08lX: no subkey for subkey " - "binding signature\n",(ulong)keyid_from_pk(pk,NULL)); - rc = G10ERR_SIG_CLASS; - } - } - else if( sig->sig_class == 0x1f ) { /* direct key signature */ - md = md_open( algo, 0 ); - hash_public_key( md, pk ); - rc = do_check( pk, sig, md, r_expired ); - cache_sig_result ( sig, rc ); - md_close(md); - } - else { /* all other classes */ - KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID ); - - if( unode ) { - u32 keyid[2]; - - keyid_from_pk( pk, keyid ); - md = md_open( algo, 0 ); - hash_public_key( md, pk ); - hash_uid_node( unode, md, sig ); - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { - if( is_selfsig ) - *is_selfsig = 1; - rc = do_check( pk, sig, md, r_expired ); - } - else { - rc = signature_check2( sig, md, r_expiredate, r_expired ); - } - cache_sig_result ( sig, rc ); - md_close(md); - } - else { - if (!opt.quiet) - log_info ("key %08lX: no user ID for key signature packet " - "of class %02x\n", - (ulong)keyid_from_pk (pk, NULL), sig->sig_class ); - rc = G10ERR_SIG_CLASS; - } - } - - return rc; -} diff --git a/g10/sign.c b/g10/sign.c deleted file mode 100644 index fe242b8da..000000000 --- a/g10/sign.c +++ /dev/null @@ -1,1300 +0,0 @@ -/* sign.c - sign data - * 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 -#include -#include -#include -#include -#include -#include /* need sleep() */ - -#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 "ttyio.h" -#include "trustdb.h" -#include "status.h" -#include "i18n.h" - - -#ifdef HAVE_DOSISH_SYSTEM - #define LF "\r\n" - void __stdcall Sleep(ulong); - #define sleep(a) Sleep((a)*1000) -#else - #define LF "\n" -#endif - -static int recipient_digest_algo=0; - -/**************** - * Create a notation. It is assumed that the stings in STRLIST - * are already checked to contain only printable data and have a valid - * NAME=VALUE format. - */ -static void -mk_notation_and_policy( PKT_signature *sig, - PKT_public_key *pk, PKT_secret_key *sk ) -{ - const char *string; - char *s=NULL; - byte *buf; - unsigned n1, n2; - STRLIST nd=NULL,pu=NULL; - struct expando_args args; - - memset(&args,0,sizeof(args)); - args.pk=pk; - args.sk=sk; - - /* notation data */ - if(IS_SIG(sig) && opt.sig_notation_data) - { - if(sig->version<4) - log_info("can't put notation data into v3 signatures\n"); - else - nd=opt.sig_notation_data; - } - else if( IS_CERT(sig) && opt.cert_notation_data ) - { - if(sig->version<4) - log_info("can't put notation data into v3 key signatures\n"); - else - nd=opt.cert_notation_data; - } - - for( ; nd; nd = nd->next ) { - char *expanded; - - string = nd->d; - s = strchr( string, '=' ); - if( !s ) - BUG(); /* we have already parsed this */ - n1 = s - string; - s++; - - expanded=pct_expando(s,&args); - if(!expanded) - { - log_error(_("WARNING: unable to %%-expand notation " - "(too large). Using unexpanded.\n")); - expanded=m_strdup(s); - } - - n2 = strlen(expanded); - buf = m_alloc( 8 + n1 + n2 ); - buf[0] = 0x80; /* human readable */ - buf[1] = buf[2] = buf[3] = 0; - buf[4] = n1 >> 8; - buf[5] = n1; - buf[6] = n2 >> 8; - buf[7] = n2; - memcpy(buf+8, string, n1 ); - memcpy(buf+8+n1, expanded, n2 ); - build_sig_subpkt( sig, SIGSUBPKT_NOTATION - | ((nd->flags & 1)? SIGSUBPKT_FLAG_CRITICAL:0), - buf, 8+n1+n2 ); - m_free(expanded); - m_free(buf); - } - - if(opt.show_notation) - show_notation(sig,0); - - /* set policy URL */ - if( IS_SIG(sig) && opt.sig_policy_url ) - { - if(sig->version<4) - log_info("can't put a policy URL into v3 signatures\n"); - else - pu=opt.sig_policy_url; - } - else if( IS_CERT(sig) && opt.cert_policy_url ) - { - if(sig->version<4) - log_info("can't put a policy URL into v3 key signatures\n"); - else - pu=opt.cert_policy_url; - } - - for(;pu;pu=pu->next) - { - string = pu->d; - - s=pct_expando(string,&args); - if(!s) - { - log_error(_("WARNING: unable to %%-expand policy url " - "(too large). Using unexpanded.\n")); - s=m_strdup(string); - } - - build_sig_subpkt(sig,SIGSUBPKT_POLICY| - ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0), - s,strlen(s)); - - m_free(s); - } - - if(opt.show_policy_url) - show_policy_url(sig,0); -} - - -/* - * Helper to hash a user ID packet. - */ -static void -hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid) -{ - if ( sigversion >= 4 ) { - byte buf[5]; - - if(uid->attrib_data) { - buf[0] = 0xd1; /* indicates an attribute packet */ - buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ - buf[2] = uid->attrib_len >> 16; - buf[3] = uid->attrib_len >> 8; - buf[4] = uid->attrib_len; - } - else { - buf[0] = 0xb4; /* indicates a userid packet */ - buf[1] = uid->len >> 24; /* always use 4 length bytes */ - buf[2] = uid->len >> 16; - buf[3] = uid->len >> 8; - buf[4] = uid->len; - } - md_write( md, buf, 5 ); - } - - if(uid->attrib_data) - md_write (md, uid->attrib_data, uid->attrib_len ); - else - md_write (md, uid->name, uid->len ); -} - - -/* - * Helper to hash some parts from the signature - */ -static void -hash_sigversion_to_magic (MD_HANDLE md, const PKT_signature *sig) -{ - if (sig->version >= 4) - md_putc (md, sig->version); - md_putc (md, sig->sig_class); - if (sig->version < 4) { - u32 a = sig->timestamp; - md_putc (md, (a >> 24) & 0xff ); - md_putc (md, (a >> 16) & 0xff ); - md_putc (md, (a >> 8) & 0xff ); - md_putc (md, a & 0xff ); - } - else { - byte buf[6]; - size_t n; - - md_putc (md, sig->pubkey_algo); - md_putc (md, sig->digest_algo); - if (sig->hashed) { - n = sig->hashed->len; - md_putc (md, (n >> 8) ); - md_putc (md, n ); - md_write (md, sig->hashed->data, n ); - n += 6; - } - else { - md_putc (md, 0); /* always hash the length of the subpacket*/ - md_putc (md, 0); - n = 6; - } - /* add some magic */ - buf[0] = sig->version; - buf[1] = 0xff; - buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ - buf[3] = n >> 16; - buf[4] = n >> 8; - buf[5] = n; - md_write (md, buf, 6); - } -} - - -static int -do_sign( PKT_secret_key *sk, PKT_signature *sig, - MD_HANDLE md, int digest_algo ) -{ - MPI frame; - byte *dp; - int rc; - - if( sk->timestamp > sig->timestamp ) { - ulong d = sk->timestamp - sig->timestamp; - log_info( d==1 ? _("key has been created %lu second " - "in future (time warp or clock problem)\n") - : _("key has been created %lu seconds " - "in future (time warp or clock problem)\n"), d ); - if( !opt.ignore_time_conflict ) - return G10ERR_TIME_CONFLICT; - } - - - print_pubkey_algo_note(sk->pubkey_algo); - - if( !digest_algo ) - digest_algo = md_get_algo(md); - - print_digest_algo_note( digest_algo ); - dp = md_read( md, digest_algo ); - sig->digest_algo = digest_algo; - sig->digest_start[0] = dp[0]; - sig->digest_start[1] = dp[1]; - frame = encode_md_value( sk->pubkey_algo, md, - digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); - if (!frame) - return G10ERR_GENERAL; - rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); - mpi_free(frame); - if (!rc && !opt.no_sig_create_check) { - /* check that the signature verification worked and nothing is - * fooling us e.g. by a bug in the signature create - * code or by deliberately introduced faults. */ - PKT_public_key *pk = m_alloc_clear (sizeof *pk); - - if( get_pubkey( pk, sig->keyid ) ) - rc = G10ERR_NO_PUBKEY; - else { - frame = encode_md_value (pk->pubkey_algo, md, - sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), 0); - if (!frame) - rc = G10ERR_GENERAL; - else - rc = pubkey_verify (pk->pubkey_algo, frame, - sig->data, pk->pkey, - NULL, NULL ); - mpi_free (frame); - } - if (rc) - log_error (_("checking created signature failed: %s\n"), - g10_errstr (rc)); - free_public_key (pk); - } - if( rc ) - log_error(_("signing failed: %s\n"), g10_errstr(rc) ); - else { - if( opt.verbose ) { - char *ustr = get_user_id_string_printable (sig->keyid); - log_info(_("%s signature from: \"%s\"\n"), - pubkey_algo_to_string(sk->pubkey_algo), ustr ); - m_free(ustr); - } - } - return rc; -} - - - -int -complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ) -{ - int rc=0; - - if( !(rc=check_secret_key( sk, 0 )) ) - rc = do_sign( sk, sig, md, 0 ); - return rc; -} - -static int -hash_for(int pubkey_algo, int packet_version ) -{ - if( opt.def_digest_algo ) - return opt.def_digest_algo; - if( recipient_digest_algo ) - return recipient_digest_algo; - if( pubkey_algo == PUBKEY_ALGO_DSA ) - return DIGEST_ALGO_SHA1; - if( pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 ) - return DIGEST_ALGO_MD5; - return DEFAULT_DIGEST_ALGO; -} - -static int -only_old_style( SK_LIST sk_list ) -{ - SK_LIST sk_rover = NULL; - int old_style = 0; - - /* if there are only old style capable key we use the old sytle */ - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - if( sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) - old_style = 1; - else - return 0; - } - return old_style; -} - - -static void -print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what ) -{ - byte array[MAX_FINGERPRINT_LEN], *p; - char buf[100+MAX_FINGERPRINT_LEN*2]; - size_t i, n; - - sprintf(buf, "%c %d %d %02x %lu ", - what, sig->pubkey_algo, sig->digest_algo, sig->sig_class, - (ulong)sig->timestamp ); - - fingerprint_from_sk( sk, array, &n ); - p = buf + strlen(buf); - for(i=0; i < n ; i++ ) - sprintf(p+2*i, "%02X", array[i] ); - - write_status_text( STATUS_SIG_CREATED, buf ); -} - - -/* - * Loop over the secret certificates in SK_LIST and build the one pass - * signature packets. OpenPGP says that the data should be bracket by - * the onepass-sig and signature-packet; so we build these onepass - * packet here in reverse order - */ -static int -write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) -{ - int skcount; - SK_LIST sk_rover; - - for (skcount=0, sk_rover=sk_list; sk_rover; sk_rover = sk_rover->next) - skcount++; - - for (; skcount; skcount--) { - PKT_secret_key *sk; - PKT_onepass_sig *ops; - PACKET pkt; - int i, rc; - - for (i=0, sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - if (++i == skcount) - break; - } - - sk = sk_rover->sk; - ops = m_alloc_clear (sizeof *ops); - ops->sig_class = sigclass; - ops->digest_algo = hash_for (sk->pubkey_algo, sk->version); - ops->pubkey_algo = sk->pubkey_algo; - keyid_from_sk (sk, ops->keyid); - ops->last = (skcount == 1); - - init_packet(&pkt); - pkt.pkttype = PKT_ONEPASS_SIG; - pkt.pkt.onepass_sig = ops; - rc = build_packet (out, &pkt); - free_packet (&pkt); - if (rc) { - log_error ("build onepass_sig packet failed: %s\n", - g10_errstr(rc)); - return rc; - } - } - - return 0; -} - -/* - * Helper to write the plaintext (literal data) packet - */ -static int -write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) -{ - PKT_plaintext *pt = NULL; - u32 filesize; - int rc = 0; - - if (!opt.no_literal) { - if (fname || opt.set_filename) { - char *s = make_basename (opt.set_filename? opt.set_filename - : fname); - pt = m_alloc (sizeof *pt + strlen(s) - 1); - pt->namelen = strlen (s); - memcpy (pt->name, s, pt->namelen); - m_free (s); - } - else { /* no filename */ - pt = m_alloc (sizeof *pt - 1); - pt->namelen = 0; - } - } - - /* try to calculate the length of the data */ - if (fname) { - if( !(filesize = iobuf_get_filelength(inp)) ) - log_info (_("WARNING: `%s' is an empty file\n"), fname); - - /* we can't yet encode the length of very large files, - * so we switch to partial length encoding in this case */ - if (filesize >= IOBUF_FILELENGTH_LIMIT) - filesize = 0; - - /* because the text_filter modifies the length of the - * data, it is not possible to know the used length - * without a double read of the file - to avoid that - * we simple use partial length packets. - */ - if ( ptmode == 't' ) - filesize = 0; - } - else { - filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ - } - - if (!opt.no_literal) { - PACKET pkt; - - pt->timestamp = make_timestamp (); - pt->mode = ptmode; - pt->len = filesize; - pt->new_ctb = !pt->len && !opt.rfc1991; - pt->buf = inp; - init_packet(&pkt); - pkt.pkttype = PKT_PLAINTEXT; - pkt.pkt.plaintext = pt; - /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ - if( (rc = build_packet (out, &pkt)) ) - log_error ("build_packet(PLAINTEXT) failed: %s\n", - g10_errstr(rc) ); - pt->buf = NULL; - } - else { - byte copy_buffer[4096]; - int bytes_copied; - - while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; - log_error ("copying input to output failed: %s\n", - g10_errstr(rc)); - break; - } - memset(copy_buffer, 0, 4096); /* burn buffer */ - } - /* fixme: it seems that we never freed pt/pkt */ - - return rc; -} - -/* - * Write the signatures from the SK_LIST to OUT. HASH must be a non-finalized - * hash which will not be changes here. - */ -static int -write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, - int sigclass, u32 timestamp, u32 duration, - int status_letter) -{ - SK_LIST sk_rover; - - /* loop over the secret certificates */ - for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { - PKT_secret_key *sk; - PKT_signature *sig; - MD_HANDLE md; - int rc; - - sk = sk_rover->sk; - - /* build the signature packet */ - sig = m_alloc_clear (sizeof *sig); - if(opt.force_v3_sigs || opt.rfc1991) - sig->version=3; - else if(duration || opt.sig_policy_url || opt.sig_notation_data) - sig->version=4; - else - sig->version=sk->version; - keyid_from_sk (sk, sig->keyid); - sig->digest_algo = hash_for (sk->pubkey_algo, sk->version); - sig->pubkey_algo = sk->pubkey_algo; - if(timestamp) - sig->timestamp = timestamp; - else - sig->timestamp = make_timestamp(); - if(duration) - sig->expiredate = sig->timestamp+duration; - sig->sig_class = sigclass; - - md = md_copy (hash); - - if (sig->version >= 4) - build_sig_subpkt_from_sig (sig); - mk_notation_and_policy (sig, NULL, sk); - - hash_sigversion_to_magic (md, sig); - md_final (md); - - rc = do_sign( sk, sig, md, hash_for (sig->pubkey_algo, sk->version) ); - md_close (md); - - if( !rc ) { /* and write it */ - PACKET pkt; - - init_packet(&pkt); - pkt.pkttype = PKT_SIGNATURE; - pkt.pkt.signature = sig; - rc = build_packet (out, &pkt); - if (!rc && is_status_enabled()) { - print_status_sig_created ( sk, sig, status_letter); - } - free_packet (&pkt); - if (rc) - log_error ("build signature packet failed: %s\n", - g10_errstr(rc) ); - } - if( rc ) - return rc;; - } - - return 0; -} - -/**************** - * Sign the files whose names are in FILENAME. - * If DETACHED has the value true, - * make a detached signature. If FILENAMES->d is NULL read from stdin - * and ignore the detached mode. Sign the file with all secret keys - * which can be taken from LOCUSR, if this is NULL, use the default one - * If ENCRYPTFLAG is true, use REMUSER (or ask if it is NULL) to encrypt the - * signed data for these users. - * If OUTFILE is not NULL; this file is used for output and the function - * does not ask for overwrite permission; output is then always - * uncompressed, non-armored and in binary mode. - */ -int -sign_file( STRLIST filenames, int detached, STRLIST locusr, - int encryptflag, STRLIST remusr, const char *outfile ) -{ - const char *fname; - armor_filter_context_t afx; - compress_filter_context_t zfx; - md_filter_context_t mfx; - text_filter_context_t tfx; - encrypt_filter_context_t efx; - IOBUF inp = NULL, out = NULL; - PACKET pkt; - int rc = 0; - PK_LIST pk_list = NULL; - SK_LIST sk_list = NULL; - SK_LIST sk_rover = NULL; - int multifile = 0; - u32 timestamp=0,duration=0; - - memset( &afx, 0, sizeof afx); - memset( &zfx, 0, sizeof zfx); - memset( &mfx, 0, sizeof mfx); - memset( &tfx, 0, sizeof tfx); - memset( &efx, 0, sizeof efx); - init_packet( &pkt ); - - if( filenames ) { - fname = filenames->d; - multifile = !!filenames->next; - } - else - fname = NULL; - - if( fname && filenames->next && (!detached || encryptflag) ) - log_bug("multiple files can only be detached signed"); - - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !opt.rfc1991) - duration=ask_expire_interval(1); - - if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) - goto leave; - - if(opt.pgp2 && !only_old_style(sk_list)) - { - log_info(_("you can only detach-sign with PGP 2.x style keys " - "while in --pgp2 mode\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; - } - - if(encryptflag && (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC ))) - goto leave; - - /* prepare iobufs */ - if( multifile ) /* have list of filenames */ - inp = NULL; /* we do it later */ - else if( !(inp = iobuf_open(fname)) ) { - log_error("can't open %s: %s\n", fname? fname: "[stdin]", - strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; - } - - if( outfile ) { - if( !(out = iobuf_create( outfile )) ) { - log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); - rc = G10ERR_CREATE_FILE; - goto leave; - } - else if( opt.verbose ) - log_info(_("writing to `%s'\n"), outfile ); - } - else if( (rc = open_outfile( fname, opt.armor? 1: detached? 2:0, &out ))) - goto leave; - - /* prepare to calculate the MD over the input */ - if( opt.textmode && !outfile ) - iobuf_push_filter( inp, text_filter, &tfx ); - mfx.md = md_open(0, 0); - - /* If we're encrypting and signing, it is reasonable to pick the - hash algorithm to use out of the recepient key prefs. */ - if(pk_list) - { - if(opt.def_digest_algo) - { - if(!opt.expert && - select_algo_from_prefs(pk_list,PREFTYPE_HASH, - opt.def_digest_algo, - NULL)!=opt.def_digest_algo) - log_info(_("forcing digest algorithm %s (%d) " - "violates recipient preferences\n"), - digest_algo_to_string(opt.def_digest_algo), - opt.def_digest_algo); - } - else - { - int hashlen=0,algo; - - /* Of course, if the recipient asks for something - unreasonable (like a non-160-bit hash for DSA, for - example), then don't do it. Check all sk's - if any - are DSA, then the hash must be 160-bit. In the future - this can be more complex with different hashes for each - sk, but so long as there is only one signing algorithm - with hash restrictions, this is ok. -dms */ - - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) - if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA) - hashlen=20; - - if((algo= - select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,&hashlen))>0) - recipient_digest_algo=algo; - } - } - - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - md_enable(mfx.md, hash_for(sk->pubkey_algo, sk->version )); - } - - if( !multifile ) - iobuf_push_filter( inp, md_filter, &mfx ); - - if( detached && !encryptflag && !opt.rfc1991 ) - afx.what = 2; - - if( opt.armor && !outfile ) - iobuf_push_filter( out, armor_filter, &afx ); - - if( encryptflag ) { - efx.pk_list = pk_list; - /* fixme: set efx.cfx.datalen if known */ - iobuf_push_filter( out, encrypt_filter, &efx ); - } - - if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) - { - int compr_algo=opt.def_compress_algo; - - /* If not forced by user */ - if(compr_algo==-1) - { - /* If we're not encrypting, then select_algo_from_prefs - will fail and we'll end up with the default. If we are - encrypting, select_algo_from_prefs cannot fail since - there is an assumed preference for uncompressed data. - Still, if it did fail, we'll also end up with the - default. */ - - if((compr_algo= - select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1) - compr_algo=DEFAULT_COMPRESS_ALGO; - } - 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 ) - { - zfx.algo = compr_algo; - iobuf_push_filter( out, compress_filter, &zfx ); - } - } - - /* Write the one-pass signature packets if needed */ - if (!detached && !opt.rfc1991) { - rc = write_onepass_sig_packets (sk_list, out, - opt.textmode && !outfile ? 0x01:0x00); - if (rc) - goto leave; - } - - /* setup the inner packet */ - if( detached ) { - if( multifile ) { - STRLIST sl; - - if( opt.verbose ) - log_info(_("signing:") ); - /* must walk reverse trough this list */ - for( sl = strlist_last(filenames); sl; - sl = strlist_prev( filenames, sl ) ) { - if( !(inp = iobuf_open(sl->d)) ) { - log_error(_("can't open %s: %s\n"), - sl->d, strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; - } - if( opt.verbose ) - fprintf(stderr, " `%s'", sl->d ); - iobuf_push_filter( inp, md_filter, &mfx ); - while( iobuf_get(inp) != -1 ) - ; - iobuf_close(inp); inp = NULL; - } - if( opt.verbose ) - putc( '\n', stderr ); - } - else { - /* read, so that the filter can calculate the digest */ - while( iobuf_get(inp) != -1 ) - ; - } - } - else { - rc = write_plaintext_packet (out, inp, fname, - opt.textmode && !outfile ? 't':'b'); - } - - /* catch errors from above */ - if (rc) - goto leave; - - /* write the signatures */ - rc = write_signature_packets (sk_list, out, mfx.md, - opt.textmode && !outfile? 0x01 : 0x00, - timestamp, duration, detached ? 'D':'S'); - if( rc ) - goto leave; - - - leave: - if( rc ) - iobuf_cancel(out); - else { - iobuf_close(out); - if (encryptflag) - write_status( STATUS_END_ENCRYPTION ); - } - iobuf_close(inp); - md_close( mfx.md ); - release_sk_list( sk_list ); - release_pk_list( pk_list ); - recipient_digest_algo=0; - return rc; -} - - - -/**************** - * make a clear signature. note that opt.armor is not needed - */ -int -clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) -{ - armor_filter_context_t afx; - MD_HANDLE textmd = NULL; - IOBUF inp = NULL, out = NULL; - PACKET pkt; - int rc = 0; - SK_LIST sk_list = NULL; - SK_LIST sk_rover = NULL; - int old_style = opt.rfc1991; - int only_md5 = 0; - u32 timestamp=0,duration=0; - - memset( &afx, 0, sizeof afx); - init_packet( &pkt ); - - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !opt.rfc1991) - duration=ask_expire_interval(1); - - if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) - goto leave; - - if( !old_style && !duration ) - old_style = only_old_style( sk_list ); - - if(!old_style && opt.pgp2) - { - log_info(_("you can only clearsign with PGP 2.x style keys " - "while in --pgp2 mode\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; - } - - /* prepare iobufs */ - if( !(inp = iobuf_open(fname)) ) { - log_error("can't open %s: %s\n", fname? fname: "[stdin]", - strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; - } - - if( outfile ) { - if( !(out = iobuf_create( outfile )) ) { - log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); - rc = G10ERR_CREATE_FILE; - goto leave; - } - else if( opt.verbose ) - log_info(_("writing to `%s'\n"), outfile ); - } - else if( (rc = open_outfile( fname, 1, &out )) ) - goto leave; - - iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF ); - - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - if( hash_for(sk->pubkey_algo, sk->version) == DIGEST_ALGO_MD5 ) - only_md5 = 1; - else { - only_md5 = 0; - break; - } - } - - if( !(old_style && only_md5) ) { - const char *s; - int any = 0; - byte hashs_seen[256]; - - memset( hashs_seen, 0, sizeof hashs_seen ); - iobuf_writestr(out, "Hash: " ); - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - int i = hash_for(sk->pubkey_algo, sk->version); - - if( !hashs_seen[ i & 0xff ] ) { - s = digest_algo_to_string( i ); - if( s ) { - hashs_seen[ i & 0xff ] = 1; - if( any ) - iobuf_put(out, ',' ); - iobuf_writestr(out, s ); - any = 1; - } - } - } - assert(any); - iobuf_writestr(out, LF ); - } - - if( opt.not_dash_escaped ) - iobuf_writestr( out, - "NotDashEscaped: You need GnuPG to verify this message" LF ); - iobuf_writestr(out, LF ); - - textmd = md_open(0, 0); - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk = sk_rover->sk; - md_enable(textmd, hash_for(sk->pubkey_algo, sk->version)); - } - if ( DBG_HASHING ) - md_start_debug( textmd, "clearsign" ); - copy_clearsig_text( out, inp, textmd, - !opt.not_dash_escaped, opt.escape_from, old_style ); - /* fixme: check for read errors */ - - /* now write the armor */ - afx.what = 2; - iobuf_push_filter( out, armor_filter, &afx ); - - /* write the signatures */ - rc = write_signature_packets (sk_list, out, textmd, 0x01, - timestamp, duration, 'C'); - if( rc ) - goto leave; - - leave: - if( rc ) - iobuf_cancel(out); - else - iobuf_close(out); - iobuf_close(inp); - md_close( textmd ); - release_sk_list( sk_list ); - return rc; -} - -/* - * Sign and conventionally encrypt the given file. - * FIXME: Far too much code is duplicated - revamp the whole file. - */ -int -sign_symencrypt_file (const char *fname, STRLIST locusr) -{ - armor_filter_context_t afx; - compress_filter_context_t zfx; - md_filter_context_t mfx; - text_filter_context_t tfx; - cipher_filter_context_t cfx; - IOBUF inp = NULL, out = NULL; - PACKET pkt; - STRING2KEY *s2k = NULL; - int rc = 0; - SK_LIST sk_list = NULL; - SK_LIST sk_rover = NULL; - int algo; - u32 timestamp=0,duration=0; - - memset( &afx, 0, sizeof afx); - memset( &zfx, 0, sizeof zfx); - memset( &mfx, 0, sizeof mfx); - memset( &tfx, 0, sizeof tfx); - memset( &cfx, 0, sizeof cfx); - init_packet( &pkt ); - - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !opt.rfc1991) - duration=ask_expire_interval(1); - - rc = build_sk_list (locusr, &sk_list, 1, PUBKEY_USAGE_SIG); - if (rc) - goto leave; - - /* prepare iobufs */ - inp = iobuf_open(fname); - if( !inp ) { - log_error("can't open %s: %s\n", fname? fname: "[stdin]", - strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; - } - - /* prepare key */ - s2k = m_alloc_clear( sizeof *s2k ); - s2k->mode = opt.rfc1991? 0:opt.s2k_mode; - s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo - : opt.s2k_digest_algo; - - algo = opt.def_cipher_algo ? opt.def_cipher_algo : opt.s2k_cipher_algo; - if (!opt.quiet || !opt.batch) - log_info (_("%s encryption will be used\n"), - cipher_algo_to_string(algo) ); - cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL ); - - if (!cfx.dek || !cfx.dek->keylen) { - rc = G10ERR_PASSPHRASE; - log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); - goto leave; - } - - /* now create the outfile */ - rc = open_outfile (fname, opt.armor? 1:0, &out); - if (rc) - goto leave; - - /* prepare to calculate the MD over the input */ - if (opt.textmode) - iobuf_push_filter (inp, text_filter, &tfx); - mfx.md = md_open(0, 0); - - for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { - PKT_secret_key *sk = sk_rover->sk; - md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version )); - } - - iobuf_push_filter (inp, md_filter, &mfx); - - /* Push armor output filter */ - if (opt.armor) - iobuf_push_filter (out, armor_filter, &afx); - - /* Write the symmetric key packet */ - /*(current filters: armor)*/ - if (!opt.rfc1991) { - PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); - enc->version = 4; - enc->cipher_algo = cfx.dek->algo; - enc->s2k = *s2k; - pkt.pkttype = PKT_SYMKEY_ENC; - pkt.pkt.symkey_enc = enc; - if( (rc = build_packet( out, &pkt )) ) - log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); - m_free(enc); - } - - /* Push the encryption filter */ - iobuf_push_filter( out, cipher_filter, &cfx ); - - /* Push the Zip filter */ - if (opt.compress) - { - int compr_algo=opt.def_compress_algo; - - /* Default */ - if(compr_algo==-1) - compr_algo=DEFAULT_COMPRESS_ALGO; - - if (compr_algo) - { - zfx.algo = compr_algo; - iobuf_push_filter( out, compress_filter, &zfx ); - } - } - - /* Write the one-pass signature packets */ - /*(current filters: zip - encrypt - armor)*/ - if (!opt.rfc1991) { - rc = write_onepass_sig_packets (sk_list, out, - opt.textmode? 0x01:0x00); - if (rc) - goto leave; - } - - /* Pipe data through all filters; i.e. write the signed stuff */ - /*(current filters: zip - encrypt - armor)*/ - rc = write_plaintext_packet (out, inp, fname, opt.textmode ? 't':'b'); - if (rc) - goto leave; - - /* Write the signatures */ - /*(current filters: zip - encrypt - armor)*/ - rc = write_signature_packets (sk_list, out, mfx.md, - opt.textmode? 0x01 : 0x00, - timestamp, duration, 'S'); - if( rc ) - goto leave; - - - leave: - if( rc ) - iobuf_cancel(out); - else { - iobuf_close(out); - write_status( STATUS_END_ENCRYPTION ); - } - iobuf_close(inp); - release_sk_list( sk_list ); - md_close( mfx.md ); - m_free(cfx.dek); - m_free(s2k); - return rc; -} - - -/**************** - * Create a signature packet for the given public key certificate and - * the user id and return it in ret_sig. User signature class SIGCLASS - * user-id is not used (and may be NULL if sigclass is 0x20) If - * DIGEST_ALGO is 0 the function selects an appropriate one. - * SIGVERSION gives the minimal required signature packet version; - * this is needed so that special properties like local sign are not - * applied (actually: dropped) when a v3 key is used. TIMESTAMP is - * the timestamp to use for the signature. 0 means "now" */ -int -make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, - PKT_user_id *uid, PKT_public_key *subpk, - PKT_secret_key *sk, - int sigclass, int digest_algo, - int sigversion, u32 timestamp, u32 duration, - int (*mksubpkt)(PKT_signature *, void *), void *opaque - ) -{ - PKT_signature *sig; - int rc=0; - MD_HANDLE md; - - assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F - || sigclass == 0x20 || sigclass == 0x18 - || sigclass == 0x30 || sigclass == 0x28 ); - - if (opt.force_v4_certs) - sigversion = 4; - - if (sigversion < sk->version) - sigversion = sk->version; - - /* If you are making a signature on a v4 key using your v3 key, it - doesn't make sense to generate a v3 sig. After all, no v3-only - PGP implementation could understand the v4 key in the first - place. Note that this implies that a signature on an attribute - uid is usually going to be v4 as well, since they are not - generally found on v3 keys. */ - if (sigversion < pk->version) - sigversion = pk->version; - - if( !digest_algo ) - { - /* Basically, this means use SHA1 always unless it's a v3 RSA - key making a v3 cert (use MD5), or the user specified - something (use whatever they said). They still must use a - 160-bit hash with DSA, or the signature will fail. Note - that this still allows the caller of make_keysig_packet to - override the user setting if it must. */ - - if(opt.cert_digest_algo) - digest_algo=opt.cert_digest_algo; - else if((sk->pubkey_algo==PUBKEY_ALGO_RSA || - sk->pubkey_algo==PUBKEY_ALGO_RSA_S) && - pk->version<4 && sigversion < 4) - digest_algo = DIGEST_ALGO_MD5; - else - digest_algo = DIGEST_ALGO_SHA1; - } - - md = md_open( digest_algo, 0 ); - - /* hash the public key certificate and the user id */ - hash_public_key( md, pk ); - if( sigclass == 0x18 || sigclass == 0x28 ) { /* subkey binding/revocation*/ - hash_public_key( md, subpk ); - } - else if( sigclass != 0x1F && sigclass != 0x20 ) { - hash_uid (md, sigversion, uid); - } - /* and make the signature packet */ - sig = m_alloc_clear( sizeof *sig ); - sig->version = sigversion; - sig->flags.exportable=1; - sig->flags.revocable=1; - keyid_from_sk( sk, sig->keyid ); - sig->pubkey_algo = sk->pubkey_algo; - sig->digest_algo = digest_algo; - if(timestamp) - sig->timestamp=timestamp; - else - sig->timestamp=make_timestamp(); - if(duration) - sig->expiredate=sig->timestamp+duration; - sig->sig_class = sigclass; - if( sig->version >= 4 ) - build_sig_subpkt_from_sig( sig ); - - if( sig->version >= 4 && mksubpkt ) - rc = (*mksubpkt)( sig, opaque ); - - if( !rc ) { - mk_notation_and_policy( sig, pk, sk ); - hash_sigversion_to_magic (md, sig); - md_final(md); - - rc = complete_sig( sig, sk, md ); - } - - md_close( md ); - if( rc ) - free_seckey_enc( sig ); - else - *ret_sig = sig; - return rc; -} - - - -/**************** - * Create a new signature packet based on an existing one. - * Only user ID signatures are supported for now. - * TODO: Merge this with make_keysig_packet. - */ -int -update_keysig_packet( PKT_signature **ret_sig, - PKT_signature *orig_sig, - PKT_public_key *pk, - PKT_user_id *uid, - PKT_secret_key *sk, - int (*mksubpkt)(PKT_signature *, void *), - void *opaque - ) -{ - PKT_signature *sig; - int rc=0; - MD_HANDLE md; - - if (!orig_sig || !pk || !uid || !sk) - return G10ERR_GENERAL; - if (orig_sig->sig_class < 0x10 || orig_sig->sig_class > 0x13 ) - return G10ERR_GENERAL; - - md = md_open( orig_sig->digest_algo, 0 ); - - /* hash the public key certificate and the user id */ - hash_public_key( md, pk ); - hash_uid (md, orig_sig->version, uid); - - /* create a new signature packet */ - sig = copy_signature (NULL, orig_sig); - if ( sig->version >= 4 && mksubpkt) - rc = (*mksubpkt)(sig, opaque); - - /* we increase the timestamp by one second so that a future import - of this key will replace the existing one. We also make sure that - we don't create a timestamp in the future */ - sig->timestamp++; - while (sig->timestamp >= make_timestamp()) - sleep (1); - /* put the updated timestamp back into the data */ - if( sig->version >= 4 ) - build_sig_subpkt_from_sig( sig ); - - if (!rc) { - hash_sigversion_to_magic (md, sig); - md_final(md); - - rc = complete_sig( sig, sk, md ); - } - - md_close (md); - if( rc ) - free_seckey_enc (sig); - else - *ret_sig = sig; - return rc; -} diff --git a/g10/signal.c b/g10/signal.c deleted file mode 100644 index 0517ba648..000000000 --- a/g10/signal.c +++ /dev/null @@ -1,217 +0,0 @@ -/* signal.c - signal handling - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "options.h" -#include "errors.h" -#include "memory.h" -#include "util.h" -#include "main.h" -#include "ttyio.h" - - -static volatile int caught_fatal_sig = 0; -static volatile int caught_sigusr1 = 0; - -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; - - secmem_term(); - /* better don't transtale these messages */ - write(2, "\n", 1 ); - s = log_get_name(); 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); - remove_lockfiles (); -#ifdef __riscos__ - close_fds (); -#endif /* __riscos__ */ - raise( sig ); -} - - -static RETSIGTYPE -got_usr_signal( int sig ) -{ - caught_sigusr1 = 1; -} - - -void -init_signals() -{ - #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 -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; - sigrelse(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 -block_all_signals() -{ - do_block(1); -} - -void -unblock_all_signals() -{ - do_block(0); -} diff --git a/g10/status.c b/g10/status.c deleted file mode 100644 index 799b42edc..000000000 --- a/g10/status.c +++ /dev/null @@ -1,693 +0,0 @@ -/* status.c - * 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 -#include -#include -#include -#include -#include -#include -#ifdef USE_SHM_COPROCESSING - #ifdef USE_CAPABILITIES - #include - #endif - #ifdef HAVE_SYS_IPC_H - #include - #include - #endif - #ifdef HAVE_SYS_SHM_H - #include - #endif - #if defined(HAVE_MLOCK) - #include - #endif -#endif -#include "util.h" -#include "status.h" -#include "ttyio.h" -#include "options.h" -#include "main.h" -#include "i18n.h" -#include "cipher.h" /* for progress functions */ - -#define CONTROL_D ('D' - 'A' + 1) - - - -static FILE *statusfp; - -#ifdef USE_SHM_COPROCESSING - static int shm_id = -1; - static volatile char *shm_area; - static size_t shm_size; - static int shm_is_locked; -#endif /*USE_SHM_COPROCESSING*/ - - -static void -progress_cb ( void *ctx, int c ) -{ - char buf[50]; - - if ( c == '\n' ) - sprintf ( buf, "%.20s X 100 100", (char*)ctx ); - else - sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c ); - write_status_text ( STATUS_PROGRESS, buf ); -} - -static const char * -get_status_string ( int no ) -{ - const char *s; - - switch( no ) { - case STATUS_ENTER : s = "ENTER"; break; - case STATUS_LEAVE : s = "LEAVE"; break; - case STATUS_ABORT : s = "ABORT"; break; - case STATUS_GOODSIG: s = "GOODSIG"; break; - case STATUS_KEYEXPIRED: s = "KEYEXPIRED"; break; - case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; - case STATUS_BADSIG : s = "BADSIG"; break; - case STATUS_ERRSIG : s = "ERRSIG"; break; - case STATUS_BADARMOR : s = "BADARMOR"; break; - case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; - case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; - case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; - case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; - case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; - case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; - case STATUS_GET_BOOL : s = "GET_BOOL"; break; - case STATUS_GET_LINE : s = "GET_LINE"; break; - case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break; - case STATUS_GOT_IT : s = "GOT_IT"; break; - case STATUS_SHM_INFO : s = "SHM_INFO"; break; - case STATUS_SHM_GET : s = "SHM_GET"; break; - case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; - case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; - case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; - case STATUS_VALIDSIG : s = "VALIDSIG"; break; - case STATUS_SIG_ID : s = "SIG_ID"; break; - case STATUS_ENC_TO : s = "ENC_TO"; break; - case STATUS_NODATA : s = "NODATA"; break; - case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; - case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; - case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; - case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; - case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; - case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; - case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; - case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; - case STATUS_GOODMDC : s = "GOODMDC"; break; - case STATUS_BADMDC : s = "BADMDC"; break; - case STATUS_ERRMDC : s = "ERRMDC"; break; - case STATUS_IMPORTED : s = "IMPORTED"; break; - case STATUS_IMPORT_OK : s = "IMPORT_OK"; break; - case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; - case STATUS_FILE_START : s = "FILE_START"; break; - case STATUS_FILE_DONE : s = "FILE_DONE"; break; - case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; - case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break; - case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break; - case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break; - case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break; - case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break; - case STATUS_PROGRESS : s = "PROGRESS"; break; - case STATUS_SIG_CREATED : s = "SIG_CREATED"; break; - case STATUS_SESSION_KEY : s = "SESSION_KEY"; break; - case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break; - case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break; - case STATUS_POLICY_URL : s = "POLICY_URL" ; break; - case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break; - case STATUS_END_STREAM : s = "END_STREAM"; break; - case STATUS_KEY_CREATED : s = "KEY_CREATED"; break; - case STATUS_USERID_HINT : s = "USERID_HINT"; break; - case STATUS_UNEXPECTED : s = "UNEXPECTED"; break; - case STATUS_INV_RECP : s = "INV_RECP"; break; - case STATUS_NO_RECP : s = "NO_RECP"; break; - case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break; - case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; - case STATUS_EXPSIG : s = "EXPSIG"; break; - case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; - case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; - default: s = "?"; break; - } - return s; -} - -void -set_status_fd ( int fd ) -{ - static int last_fd = -1; - - if ( fd != -1 && last_fd == fd ) - return; - - if ( statusfp && statusfp != stdout && statusfp != stderr ) - fclose (statusfp); - statusfp = NULL; - if ( fd == -1 ) - return; - - if( fd == 1 ) - statusfp = stdout; - else if( fd == 2 ) - statusfp = stderr; - else - statusfp = fdopen( fd, "w" ); - if( !statusfp ) { - log_fatal("can't open fd %d for status output: %s\n", - fd, strerror(errno)); - } - last_fd = fd; - register_primegen_progress ( progress_cb, "primegen" ); - register_pk_dsa_progress ( progress_cb, "pk_dsa" ); - register_pk_elg_progress ( progress_cb, "pk_elg" ); -} - -int -is_status_enabled() -{ - return !!statusfp; -} - -void -write_status ( int no ) -{ - write_status_text( no, NULL ); -} - -void -write_status_text ( int no, const char *text) -{ - if( !statusfp ) - return; /* not enabled */ - - fputs ( "[GNUPG:] ", statusfp ); - fputs ( get_status_string (no), statusfp ); - if( text ) { - putc ( ' ', statusfp ); - for (; *text; text++) { - if (*text == '\n') - fputs ( "\\n", statusfp ); - else if (*text == '\r') - fputs ( "\\r", statusfp ); - else - putc ( *(const byte *)text, statusfp ); - } - } - putc ('\n',statusfp); - fflush (statusfp); -} - - -/* - * Write a status line with a buffer using %XX escapes. If WRAP is > - * 0 wrap the line after this length. If STRING is not NULL it will - * be prepended to the buffer, no escaping is done for string. - * A wrap of -1 forces spaces not to be encoded as %20. - */ -void -write_status_text_and_buffer ( int no, const char *string, - const char *buffer, size_t len, int wrap ) -{ - const char *s, *text; - int esc, first; - int lower_limit = ' '; - size_t n, count, dowrap; - - if( !statusfp ) - return; /* not enabled */ - - if (wrap == -1) { - lower_limit--; - wrap = 0; - } - - text = get_status_string (no); - count = dowrap = first = 1; - do { - if (dowrap) { - fprintf (statusfp, "[GNUPG:] %s ", text ); - count = dowrap = 0; - if (first && string) { - fputs (string, statusfp); - count += strlen (string); - } - first = 0; - } - for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) { - if ( *s == '%' || *(const byte*)s <= lower_limit - || *(const byte*)s == 127 ) - esc = 1; - if ( wrap && ++count > wrap ) { - dowrap=1; - break; - } - } - if (esc) { - s--; n++; - } - if (s != buffer) - fwrite (buffer, s-buffer, 1, statusfp ); - if ( esc ) { - fprintf (statusfp, "%%%02X", *(const byte*)s ); - s++; n--; - } - buffer = s; - len = n; - if ( dowrap && len ) - putc ( '\n', statusfp ); - } while ( len ); - - putc ('\n',statusfp); - fflush (statusfp); -} - -void -write_status_buffer ( int no, const char *buffer, size_t len, int wrap ) -{ - write_status_text_and_buffer (no, NULL, buffer, len, wrap); -} - - - -#ifdef USE_SHM_COPROCESSING - -#ifndef IPC_RMID_DEFERRED_RELEASE -static void -remove_shmid( void ) -{ - if( shm_id != -1 ) { - shmctl ( shm_id, IPC_RMID, 0); - shm_id = -1; - } -} -#endif - -void -init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ) -{ - char buf[100]; - struct shmid_ds shmds; - - #ifndef IPC_RMID_DEFERRED_RELEASE - atexit( remove_shmid ); - #endif - requested_shm_size = (requested_shm_size + 4095) & ~4095; - if ( requested_shm_size > 2 * 4096 ) - log_fatal("too much shared memory requested; only 8k are allowed\n"); - shm_size = 4096 /* one page for us */ + requested_shm_size; - - shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 ); - if ( shm_id == -1 ) - log_fatal("can't get %uk of shared memory: %s\n", - (unsigned)shm_size/1024, strerror(errno)); - - #if !defined(IPC_HAVE_SHM_LOCK) \ - && defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) - /* part of the old code which uses mlock */ - shm_area = shmat( shm_id, 0, 0 ); - if ( shm_area == (char*)-1 ) - log_fatal("can't attach %uk shared memory: %s\n", - (unsigned)shm_size/1024, strerror(errno)); - log_debug("mapped %uk shared memory at %p, id=%d\n", - (unsigned)shm_size/1024, shm_area, shm_id ); - if( lock_mem ) { - #ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); - #endif - /* (need the cast for Solaris with Sun's workshop compilers) */ - if ( mlock ( (char*)shm_area, shm_size) ) - log_info("locking shared memory %d failed: %s\n", - shm_id, strerror(errno)); - else - shm_is_locked = 1; - #ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+p") ); - #endif - } - - #ifdef IPC_RMID_DEFERRED_RELEASE - if( shmctl( shm_id, IPC_RMID, 0) ) - log_fatal("shmctl IPC_RMDID of %d failed: %s\n", - shm_id, strerror(errno)); - #endif - - if( shmctl( shm_id, IPC_STAT, &shmds ) ) - log_fatal("shmctl IPC_STAT of %d failed: %s\n", - shm_id, strerror(errno)); - if( shmds.shm_perm.uid != getuid() ) { - shmds.shm_perm.uid = getuid(); - if( shmctl( shm_id, IPC_SET, &shmds ) ) - log_fatal("shmctl IPC_SET of %d failed: %s\n", - shm_id, strerror(errno)); - } - - #else /* this is the new code which handles the changes in the SHM semantics - * introduced with Linux 2.4. The changes is that we now change the - * permissions and then attach to the memory. - */ - - if( lock_mem ) { - #ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); - #endif - #ifdef IPC_HAVE_SHM_LOCK - if ( shmctl (shm_id, SHM_LOCK, 0) ) - log_info("locking shared memory %d failed: %s\n", - shm_id, strerror(errno)); - else - shm_is_locked = 1; - #else - log_info("Locking shared memory %d failed: No way to do it\n", shm_id ); - #endif - #ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+p") ); - #endif - } - - if( shmctl( shm_id, IPC_STAT, &shmds ) ) - log_fatal("shmctl IPC_STAT of %d failed: %s\n", - shm_id, strerror(errno)); - if( shmds.shm_perm.uid != getuid() ) { - shmds.shm_perm.uid = getuid(); - if( shmctl( shm_id, IPC_SET, &shmds ) ) - log_fatal("shmctl IPC_SET of %d failed: %s\n", - shm_id, strerror(errno)); - } - - shm_area = shmat( shm_id, 0, 0 ); - if ( shm_area == (char*)-1 ) - log_fatal("can't attach %uk shared memory: %s\n", - (unsigned)shm_size/1024, strerror(errno)); - log_debug("mapped %uk shared memory at %p, id=%d\n", - (unsigned)shm_size/1024, shm_area, shm_id ); - - #ifdef IPC_RMID_DEFERRED_RELEASE - if( shmctl( shm_id, IPC_RMID, 0) ) - log_fatal("shmctl IPC_RMDID of %d failed: %s\n", - shm_id, strerror(errno)); - #endif - - #endif - /* write info; Protocol version, id, size, locked size */ - sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(), - shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 ); - write_status_text( STATUS_SHM_INFO, buf ); -} - -/**************** - * Request a string from client - * If bool, returns static string on true (do not free) or NULL for false - */ -static char * -do_shm_get( const char *keyword, int hidden, int bool ) -{ - size_t n; - byte *p; - char *string; - - if( !shm_area ) - BUG(); - - shm_area[0] = 0; /* msb of length of control block */ - shm_area[1] = 32; /* and lsb */ - shm_area[2] = 1; /* indicate that we are waiting on a reply */ - shm_area[3] = 0; /* clear data available flag */ - - write_status_text( bool? STATUS_SHM_GET_BOOL : - hidden? STATUS_SHM_GET_HIDDEN : STATUS_SHM_GET, keyword ); - - do { - pause_on_sigusr(1); - if( shm_area[0] || shm_area[1] != 32 || shm_area[2] != 1 ) - log_fatal("client modified shm control block - abort\n"); - } while( !shm_area[3] ); - shm_area[2] = 0; /* reset request flag */ - p = (byte*)shm_area+32; - n = p[0] << 8 | p[1]; - p += 2; - if( n+32+2+1 > 4095 ) - log_fatal("client returns too large data (%u bytes)\n", (unsigned)n ); - - if( bool ) - return p[0]? "" : NULL; - - string = hidden? m_alloc_secure( n+1 ) : m_alloc( n+1 ); - memcpy(string, p, n ); - string[n] = 0; /* make sure it is a string */ - if( hidden ) /* invalidate the memory */ - memset( p, 0, n ); - - return string; -} - -#endif /* USE_SHM_COPROCESSING */ - -static int -myread(int fd, void *buf, size_t count) -{ - int rc; - do { - rc = read( fd, buf, count ); - } while ( rc == -1 && errno == EINTR ); - if ( !rc && count ) { - static int eof_emmited=0; - if ( eof_emmited < 3 ) { - *(char*)buf = CONTROL_D; - rc = 1; - eof_emmited++; - } - else { /* Ctrl-D not caught - do something reasonable */ - #ifdef HAVE_DOSISH_SYSTEM - raise (SIGINT); /* nothing to hangup under DOS */ - #else - raise (SIGHUP); /* no more input data */ - #endif - } - } - return rc; -} - - - -/**************** - * Request a string from the client over the command-fd - * If bool, returns static string on true (do not free) or NULL for false - */ -static char * -do_get_from_fd( const char *keyword, int hidden, int bool ) -{ - int i, len; - char *string; - - write_status_text( bool? STATUS_GET_BOOL : - hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword ); - - for( string = NULL, i = len = 200; ; i++ ) { - if( i >= len-1 ) { - char *save = string; - len += 100; - string = hidden? m_alloc_secure ( len ) : m_alloc ( len ); - if( save ) - memcpy(string, save, i ); - else - i=0; - } - /* Hmmm: why not use our read_line function here */ - if( myread( opt.command_fd, string+i, 1) != 1 || string[i] == '\n' ) - break; - else if ( string[i] == CONTROL_D ) { - /* found ETX - cancel the line and return a sole ETX */ - string[0] = CONTROL_D; - i=1; - break; - } - } - string[i] = 0; - - write_status( STATUS_GOT_IT ); - - if( bool ) /* Fixme: is this correct??? */ - return string[0] == 'Y' ? "" : NULL; - - return string; -} - - - -int -cpr_enabled() -{ - if( opt.command_fd != -1 ) - return 1; - #ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return 1; - #endif - return 0; -} - -char * -cpr_get_no_help( const char *keyword, const char *prompt ) -{ - char *p; - - if( opt.command_fd != -1 ) - return do_get_from_fd ( keyword, 0, 0 ); - #ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return do_shm_get( keyword, 0, 0 ); - #endif - for(;;) { - p = tty_get( prompt ); - return p; - } -} - -char * -cpr_get( const char *keyword, const char *prompt ) -{ - char *p; - - if( opt.command_fd != -1 ) - return do_get_from_fd ( keyword, 0, 0 ); - #ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return do_shm_get( keyword, 0, 0 ); - #endif - for(;;) { - p = tty_get( prompt ); - if( *p=='?' && !p[1] && !(keyword && !*keyword)) { - m_free(p); - display_online_help( keyword ); - } - else - return p; - } -} - - -char * -cpr_get_utf8( const char *keyword, const char *prompt ) -{ - char *p; - p = cpr_get( keyword, prompt ); - if( p ) { - char *utf8 = native_to_utf8( p ); - m_free( p ); - p = utf8; - } - return p; -} - -char * -cpr_get_hidden( const char *keyword, const char *prompt ) -{ - char *p; - - if( opt.command_fd != -1 ) - return do_get_from_fd ( keyword, 1, 0 ); - #ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return do_shm_get( keyword, 1, 0 ); - #endif - for(;;) { - p = tty_get_hidden( prompt ); - if( *p == '?' && !p[1] ) { - m_free(p); - display_online_help( keyword ); - } - else - return p; - } -} - -void -cpr_kill_prompt(void) -{ - if( opt.command_fd != -1 ) - return; - #ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return; - #endif - tty_kill_prompt(); - return; -} - -int -cpr_get_answer_is_yes( const char *keyword, const char *prompt ) -{ - int yes; - char *p; - - if( opt.command_fd != -1 ) - return !!do_get_from_fd ( keyword, 0, 1 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return !!do_shm_get( keyword, 0, 1 ); -#endif - for(;;) { - p = tty_get( prompt ); - trim_spaces(p); /* it is okay to do this here */ - if( *p == '?' && !p[1] ) { - m_free(p); - display_online_help( keyword ); - } - else { - tty_kill_prompt(); - yes = answer_is_yes(p); - m_free(p); - return yes; - } - } -} - -int -cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) -{ - int yes; - char *p; - - if( opt.command_fd != -1 ) - return !!do_get_from_fd ( keyword, 0, 1 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return !!do_shm_get( keyword, 0, 1 ); -#endif - for(;;) { - p = tty_get( prompt ); - trim_spaces(p); /* it is okay to do this here */ - if( *p == '?' && !p[1] ) { - m_free(p); - display_online_help( keyword ); - } - else { - tty_kill_prompt(); - yes = answer_is_yes_no_quit(p); - m_free(p); - return yes; - } - } -} - diff --git a/g10/status.h b/g10/status.h deleted file mode 100644 index dd913b4bd..000000000 --- a/g10/status.h +++ /dev/null @@ -1,126 +0,0 @@ -/* status.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_STATUS_H -#define G10_STATUS_H - - -#define STATUS_ENTER 1 -#define STATUS_LEAVE 2 -#define STATUS_ABORT 3 - -#define STATUS_GOODSIG 4 -#define STATUS_BADSIG 5 -#define STATUS_ERRSIG 6 - - -#define STATUS_BADARMOR 7 - -#define STATUS_RSA_OR_IDEA 8 -#define STATUS_KEYEXPIRED 9 -#define STATUS_KEYREVOKED 10 - -#define STATUS_TRUST_UNDEFINED 11 -#define STATUS_TRUST_NEVER 12 -#define STATUS_TRUST_MARGINAL 13 -#define STATUS_TRUST_FULLY 14 -#define STATUS_TRUST_ULTIMATE 15 - -#define STATUS_SHM_INFO 16 -#define STATUS_SHM_GET 17 -#define STATUS_SHM_GET_BOOL 18 -#define STATUS_SHM_GET_HIDDEN 19 - -#define STATUS_NEED_PASSPHRASE 20 -#define STATUS_VALIDSIG 21 -#define STATUS_SIG_ID 22 -#define STATUS_ENC_TO 23 -#define STATUS_NODATA 24 -#define STATUS_BAD_PASSPHRASE 25 -#define STATUS_NO_PUBKEY 26 -#define STATUS_NO_SECKEY 27 -#define STATUS_NEED_PASSPHRASE_SYM 28 -#define STATUS_DECRYPTION_FAILED 29 -#define STATUS_DECRYPTION_OKAY 30 -#define STATUS_MISSING_PASSPHRASE 31 -#define STATUS_GOOD_PASSPHRASE 32 -#define STATUS_GOODMDC 33 -#define STATUS_BADMDC 34 -#define STATUS_ERRMDC 35 -#define STATUS_IMPORTED 36 -#define STATUS_IMPORT_RES 37 -#define STATUS_FILE_START 38 -#define STATUS_FILE_DONE 39 -#define STATUS_FILE_ERROR 40 - -#define STATUS_BEGIN_DECRYPTION 41 -#define STATUS_END_DECRYPTION 42 -#define STATUS_BEGIN_ENCRYPTION 43 -#define STATUS_END_ENCRYPTION 44 - -#define STATUS_DELETE_PROBLEM 45 -#define STATUS_GET_BOOL 46 -#define STATUS_GET_LINE 47 -#define STATUS_GET_HIDDEN 48 -#define STATUS_GOT_IT 49 -#define STATUS_PROGRESS 50 -#define STATUS_SIG_CREATED 51 -#define STATUS_SESSION_KEY 52 -#define STATUS_NOTATION_NAME 53 -#define STATUS_NOTATION_DATA 54 -#define STATUS_POLICY_URL 55 -#define STATUS_BEGIN_STREAM 56 -#define STATUS_END_STREAM 57 -#define STATUS_KEY_CREATED 58 -#define STATUS_USERID_HINT 59 -#define STATUS_UNEXPECTED 60 -#define STATUS_INV_RECP 61 -#define STATUS_NO_RECP 62 -#define STATUS_ALREADY_SIGNED 63 -#define STATUS_SIGEXPIRED 64 -#define STATUS_EXPSIG 65 -#define STATUS_EXPKEYSIG 66 -#define STATUS_ATTRIBUTE 67 -#define STATUS_IMPORT_OK 68 - -/*-- status.c --*/ -void set_status_fd ( int fd ); -int is_status_enabled ( void ); -void write_status ( int no ); -void write_status_text ( int no, const char *text ); -void write_status_buffer ( int no, - const char *buffer, size_t len, int wrap ); -void write_status_text_and_buffer ( int no, const char *text, - const char *buffer, size_t len, int wrap ); - -#ifdef USE_SHM_COPROCESSING - void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ); -#endif /*USE_SHM_COPROCESSING*/ - -int cpr_enabled(void); -char *cpr_get( const char *keyword, const char *prompt ); -char *cpr_get_no_help( const char *keyword, const char *prompt ); -char *cpr_get_utf8( const char *keyword, const char *prompt ); -char *cpr_get_hidden( const char *keyword, const char *prompt ); -void cpr_kill_prompt(void); -int cpr_get_answer_is_yes( const char *keyword, const char *prompt ); -int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ); - - -#endif /*G10_STATUS_H*/ diff --git a/g10/tdbio.c b/g10/tdbio.c deleted file mode 100644 index 62ff26774..000000000 --- a/g10/tdbio.c +++ /dev/null @@ -1,1578 +0,0 @@ -/* tdbio.c - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "errors.h" -#include "iobuf.h" -#include "memory.h" -#include "util.h" -#include "options.h" -#include "main.h" -#include "i18n.h" -#include "trustdb.h" -#include "tdbio.h" - -#if defined(HAVE_DOSISH_SYSTEM) && !defined(__CYGWIN32__) -#define ftruncate chsize -#endif - -#ifdef HAVE_DOSISH_SYSTEM -#define MY_O_BINARY O_BINARY -#else -#define MY_O_BINARY 0 -#endif - - -/**************** - * Yes, this is a very simple implementation. We should really - * use a page aligned buffer and read complete pages. - * To implement a simple trannsaction system, this is sufficient. - */ -typedef struct cache_ctrl_struct *CACHE_CTRL; -struct cache_ctrl_struct { - CACHE_CTRL next; - struct { - unsigned used:1; - unsigned dirty:1; - } flags; - ulong recno; - char data[TRUST_RECORD_LEN]; -}; - -#define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased while in a */ -#define MAX_CACHE_ENTRIES_HARD 10000 /* transaction to this one */ -static CACHE_CTRL cache_list; -static int cache_entries; -static int cache_is_dirty; - -/* a type used to pass infomation to cmp_krec_fpr */ -struct cmp_krec_fpr_struct { - int pubkey_algo; - const char *fpr; - int fprlen; -}; - -/* a type used to pass infomation to cmp_[s]dir */ -struct cmp_xdir_struct { - int pubkey_algo; - u32 keyid[2]; -}; - - -static char *db_name; -static DOTLOCK lockhandle; -static int is_locked; -static int db_fd = -1; -static int in_transaction; - -static void open_db(void); -static void migrate_from_v2 (void); - - - -/************************************* - ************* record cache ********** - *************************************/ - -/**************** - * Get the data from therecord cache and return a - * pointer into that cache. Caller should copy - * the return data. NULL is returned on a cache miss. - */ -static const char * -get_record_from_cache( ulong recno ) -{ - CACHE_CTRL r; - - for( r = cache_list; r; r = r->next ) { - if( r->flags.used && r->recno == recno ) - return r->data; - } - return NULL; -} - - -static int -write_cache_item( CACHE_CTRL r ) -{ - int n; - - if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb rec %lu: lseek failed: %s\n"), - r->recno, strerror(errno) ); - return G10ERR_WRITE_FILE; - } - n = write( db_fd, r->data, TRUST_RECORD_LEN); - if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), - r->recno, n, strerror(errno) ); - return G10ERR_WRITE_FILE; - } - r->flags.dirty = 0; - return 0; -} - -/**************** - * Put data into the cache. This function may flush the - * some cache entries if there is not enough space available. - */ -int -put_record_into_cache( ulong recno, const char *data ) -{ - CACHE_CTRL r, unused; - int dirty_count = 0; - int clean_count = 0; - - /* see whether we already cached this one */ - for( unused = NULL, r = cache_list; r; r = r->next ) { - if( !r->flags.used ) { - if( !unused ) - unused = r; - } - else if( r->recno == recno ) { - if( !r->flags.dirty ) { - /* Hmmm: should we use a a copy and compare? */ - if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) { - r->flags.dirty = 1; - cache_is_dirty = 1; - } - } - memcpy( r->data, data, TRUST_RECORD_LEN ); - return 0; - } - if( r->flags.used ) { - if( r->flags.dirty ) - dirty_count++; - else - clean_count++; - } - } - /* not in the cache: add a new entry */ - if( unused ) { /* reuse this entry */ - r = unused; - r->flags.used = 1; - r->recno = recno; - memcpy( r->data, data, TRUST_RECORD_LEN ); - r->flags.dirty = 1; - cache_is_dirty = 1; - cache_entries++; - return 0; - } - /* see whether we reached the limit */ - if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */ - r = m_alloc( sizeof *r ); - r->flags.used = 1; - r->recno = recno; - memcpy( r->data, data, TRUST_RECORD_LEN ); - r->flags.dirty = 1; - r->next = cache_list; - cache_list = r; - cache_is_dirty = 1; - cache_entries++; - return 0; - } - /* cache is full: discard some clean entries */ - if( clean_count ) { - int n = clean_count / 3; /* discard a third of the clean entries */ - if( !n ) - n = 1; - for( unused = NULL, r = cache_list; r; r = r->next ) { - if( r->flags.used && !r->flags.dirty ) { - if( !unused ) - unused = r; - r->flags.used = 0; - cache_entries--; - if( !--n ) - break; - } - } - assert( unused ); - r = unused; - r->flags.used = 1; - r->recno = recno; - memcpy( r->data, data, TRUST_RECORD_LEN ); - r->flags.dirty = 1; - cache_is_dirty = 1; - cache_entries++; - return 0; - } - /* no clean entries: have to flush some dirty entries */ - if( in_transaction ) { - /* but we can't do this while in a transaction - * we increase the cache size instead */ - if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */ - if( opt.debug && !(cache_entries % 100) ) - log_debug("increasing tdbio cache size\n"); - r = m_alloc( sizeof *r ); - r->flags.used = 1; - r->recno = recno; - memcpy( r->data, data, TRUST_RECORD_LEN ); - r->flags.dirty = 1; - r->next = cache_list; - cache_list = r; - cache_is_dirty = 1; - cache_entries++; - return 0; - } - log_info(_("trustdb transaction too large\n")); - return G10ERR_RESOURCE_LIMIT; - } - if( dirty_count ) { - int n = dirty_count / 5; /* discard some dirty entries */ - if( !n ) - n = 1; - if( !is_locked ) { - if( make_dotlock( lockhandle, -1 ) ) - log_fatal("can't acquire lock - giving up\n"); - else - is_locked = 1; - } - for( unused = NULL, r = cache_list; r; r = r->next ) { - if( r->flags.used && r->flags.dirty ) { - int rc = write_cache_item( r ); - if( rc ) - return rc; - if( !unused ) - unused = r; - r->flags.used = 0; - cache_entries--; - if( !--n ) - break; - } - } - if( !opt.lock_once ) { - if( !release_dotlock( lockhandle ) ) - is_locked = 0; - } - assert( unused ); - r = unused; - r->flags.used = 1; - r->recno = recno; - memcpy( r->data, data, TRUST_RECORD_LEN ); - r->flags.dirty = 1; - cache_is_dirty = 1; - cache_entries++; - return 0; - } - BUG(); -} - - -int -tdbio_is_dirty() -{ - return cache_is_dirty; -} - - -/**************** - * Flush the cache. This cannot be used while in a transaction. - */ -int -tdbio_sync() -{ - CACHE_CTRL r; - int did_lock = 0; - - if( db_fd == -1 ) - open_db(); - if( in_transaction ) - log_bug("tdbio: syncing while in transaction\n"); - - if( !cache_is_dirty ) - return 0; - - if( !is_locked ) { - if( make_dotlock( lockhandle, -1 ) ) - log_fatal("can't acquire lock - giving up\n"); - else - is_locked = 1; - did_lock = 1; - } - for( r = cache_list; r; r = r->next ) { - if( r->flags.used && r->flags.dirty ) { - int rc = write_cache_item( r ); - if( rc ) - return rc; - } - } - cache_is_dirty = 0; - if( did_lock && !opt.lock_once ) { - if( !release_dotlock( lockhandle ) ) - is_locked = 0; - } - - return 0; -} - - - -/**************** - * Simple transactions system: - * Everything between begin_transaction and end/cancel_transaction - * is not immediatly written but at the time of end_transaction. - * - */ -int -tdbio_begin_transaction() -{ - int rc; - - if( in_transaction ) - log_bug("tdbio: nested transactions\n"); - /* flush everything out */ - rc = tdbio_sync(); - if( rc ) - return rc; - in_transaction = 1; - return 0; -} - -int -tdbio_end_transaction() -{ - int rc; - - if( !in_transaction ) - log_bug("tdbio: no active transaction\n"); - if( !is_locked ) { - if( make_dotlock( lockhandle, -1 ) ) - log_fatal("can't acquire lock - giving up\n"); - else - is_locked = 1; - } - block_all_signals(); - in_transaction = 0; - rc = tdbio_sync(); - unblock_all_signals(); - if( !opt.lock_once ) { - if( !release_dotlock( lockhandle ) ) - is_locked = 0; - } - return rc; -} - -int -tdbio_cancel_transaction() -{ - CACHE_CTRL r; - - if( !in_transaction ) - log_bug("tdbio: no active transaction\n"); - - /* remove all dirty marked entries, so that the original ones - * are read back the next time */ - if( cache_is_dirty ) { - for( r = cache_list; r; r = r->next ) { - if( r->flags.used && r->flags.dirty ) { - r->flags.used = 0; - cache_entries--; - } - } - cache_is_dirty = 0; - } - - in_transaction = 0; - return 0; -} - - - -/******************************************************** - **************** cached I/O functions ****************** - ********************************************************/ - -static void -cleanup(void) -{ - if( is_locked ) { - if( !release_dotlock(lockhandle) ) - is_locked = 0; - } -} - -static int -create_version_record (void) -{ - TRUSTREC rec; - int rc; - - memset( &rec, 0, sizeof rec ); - rec.r.ver.version = 3; - rec.r.ver.created = make_timestamp(); - rec.r.ver.marginals = opt.marginals_needed; - rec.r.ver.completes = opt.completes_needed; - rec.r.ver.cert_depth = opt.max_cert_depth; - rec.rectype = RECTYPE_VER; - rec.recnum = 0; - rc = tdbio_write_record( &rec ); - if( !rc ) - tdbio_sync(); - return rc; -} - - - -int -tdbio_set_dbname( const char *new_dbname, int create ) -{ - char *fname; - static int initialized = 0; - - if( !initialized ) { - atexit( cleanup ); - initialized = 1; - } - fname = new_dbname? m_strdup( new_dbname ) - : make_filename(opt.homedir, - "trustdb" EXTSEP_S "gpg", NULL ); - - if( access( fname, R_OK ) ) { - if( errno != ENOENT ) { - log_error( _("%s: can't access: %s\n"), fname, strerror(errno) ); - m_free(fname); - return G10ERR_TRUSTDB; - } - if( create ) { - FILE *fp; - TRUSTREC rec; - int rc; - char *p = strrchr( fname, DIRSEP_C ); - mode_t oldmask; - - assert(p); - *p = 0; - if( access( fname, F_OK ) ) { - try_make_homedir( fname ); - log_fatal( _("%s: directory does not exist!\n"), fname ); - } - *p = DIRSEP_C; - - m_free(db_name); - db_name = fname; -#ifdef __riscos__ - if( !lockhandle ) - lockhandle = create_dotlock( db_name ); - if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); - if( make_dotlock( lockhandle, -1 ) ) - log_fatal( _("%s: can't make lock\n"), db_name ); -#endif /* __riscos__ */ - oldmask=umask(077); - fp =fopen( fname, "wb" ); - umask(oldmask); - if( !fp ) - log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) ); - fclose(fp); - db_fd = open( db_name, O_RDWR | MY_O_BINARY ); - if( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); - -#ifndef __riscos__ - if( !lockhandle ) - lockhandle = create_dotlock( db_name ); - if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); -#endif /* !__riscos__ */ - - rc = create_version_record (); - if( rc ) - log_fatal( _("%s: failed to create version record: %s"), - fname, g10_errstr(rc)); - /* and read again to check that we are okay */ - if( tdbio_read_record( 0, &rec, RECTYPE_VER ) ) - log_fatal( _("%s: invalid trustdb created\n"), db_name ); - - if( !opt.quiet ) - log_info(_("%s: trustdb created\n"), db_name); - - return 0; - } - } - m_free(db_name); - db_name = fname; - return 0; -} - - -const char * -tdbio_get_dbname() -{ - return db_name; -} - - - -static void -open_db() -{ - byte buf[10]; - int n; - TRUSTREC rec; - - assert( db_fd == -1 ); - - if (!lockhandle ) - lockhandle = create_dotlock( db_name ); - if (!lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); -#ifdef __riscos__ - if (make_dotlock( lockhandle, -1 ) ) - log_fatal( _("%s: can't make lock\n"), db_name ); -#endif /* __riscos__ */ - db_fd = open (db_name, O_RDWR | MY_O_BINARY ); - if (db_fd == -1 && errno == EACCES) { - db_fd = open (db_name, O_RDONLY | MY_O_BINARY ); - if (db_fd != -1) - log_info (_("NOTE: trustdb not writable\n")); - } - if ( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); - - /* check whether we need to do a version migration */ - do - n = read (db_fd, buf, 5); - while (n==-1 && errno == EINTR); - if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5)) - { - migrate_from_v2 (); - } - - /* read the version record */ - if (tdbio_read_record (0, &rec, RECTYPE_VER ) ) - log_fatal( _("%s: invalid trustdb\n"), db_name ); -} - - -/**************** - * Make a hashtable: type 0 = trust hash - */ -static void -create_hashtable( TRUSTREC *vr, int type ) -{ - TRUSTREC rec; - off_t offset; - ulong recnum; - int i, n, rc; - - offset = lseek( db_fd, 0, SEEK_END ); - if( offset == -1 ) - log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) ); - recnum = offset / TRUST_RECORD_LEN; - assert(recnum); /* this is will never be the first record */ - - if( !type ) - vr->r.ver.trusthashtbl = recnum; - - /* Now write the records */ - n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD; - for(i=0; i < n; i++, recnum++ ) { - memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_HTBL; - rec.recnum = recnum; - rc = tdbio_write_record( &rec ); - if( rc ) - log_fatal( _("%s: failed to create hashtable: %s\n"), - db_name, g10_errstr(rc)); - } - /* update the version record */ - rc = tdbio_write_record( vr ); - if( !rc ) - rc = tdbio_sync(); - if( rc ) - log_fatal( _("%s: error updating version record: %s\n"), - db_name, g10_errstr(rc)); -} - - -int -tdbio_db_matches_options() -{ - static int yes_no = -1; - - if( yes_no == -1 ) { - TRUSTREC vr; - int rc; - - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); - - if( !vr.r.ver.marginals && !vr.r.ver.completes - && !vr.r.ver.cert_depth ) - { /* special hack for trustdbs created by old versions of GnuPG */ - vr.r.ver.marginals = opt.marginals_needed; - vr.r.ver.completes = opt.completes_needed; - vr.r.ver.cert_depth = opt.max_cert_depth; - rc = tdbio_write_record( &vr ); - if( !rc && !in_transaction ) - rc = tdbio_sync(); - if( rc ) - log_error( _("%s: error writing version record: %s\n"), - db_name, g10_errstr(rc) ); - } - - yes_no = vr.r.ver.marginals == opt.marginals_needed - && vr.r.ver.completes == opt.completes_needed - && vr.r.ver.cert_depth == opt.max_cert_depth; - } - return yes_no; -} - - -/**************** - * Return the nextstamp value. - */ -ulong -tdbio_read_nextcheck () -{ - TRUSTREC vr; - int rc; - - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); - return vr.r.ver.nextcheck; -} - -/* Return true when the stamp was actually changed. */ -int -tdbio_write_nextcheck (ulong stamp) -{ - TRUSTREC vr; - int rc; - - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); - - if (vr.r.ver.nextcheck == stamp) - return 0; - - vr.r.ver.nextcheck = stamp; - rc = tdbio_write_record( &vr ); - if( rc ) - log_fatal( _("%s: error writing version record: %s\n"), - db_name, g10_errstr(rc) ); - return 1; -} - - - -/**************** - * Return the record number of the trusthash tbl or create a new one. - */ -static ulong -get_trusthashrec(void) -{ - static ulong trusthashtbl; /* record number of the trust hashtable */ - - if( !trusthashtbl ) { - TRUSTREC vr; - int rc; - - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); - if( !vr.r.ver.trusthashtbl ) - create_hashtable( &vr, 0 ); - - trusthashtbl = vr.r.ver.trusthashtbl; - } - return trusthashtbl; -} - - - -/**************** - * Update a hashtable. - * table gives the start of the table, key and keylen is the key, - * newrecnum is the record number to insert. - */ -static int -upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) -{ - TRUSTREC lastrec, rec; - ulong hashrec, item; - int msb; - int level=0; - int rc, i; - - hashrec = table; - next_level: - msb = key[level]; - hashrec += msb / ITEMS_PER_HTBL_RECORD; - rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); - if( rc ) { - log_error( db_name, "upd_hashtable: read failed: %s\n", - g10_errstr(rc) ); - return rc; - } - - item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; - if( !item ) { /* insert a new item into the hash table */ - rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum; - rc = tdbio_write_record( &rec ); - if( rc ) { - log_error( db_name, "upd_hashtable: write htbl failed: %s\n", - g10_errstr(rc) ); - return rc; - } - } - else if( item != newrecnum ) { /* must do an update */ - lastrec = rec; - rc = tdbio_read_record( item, &rec, 0 ); - if( rc ) { - log_error( "upd_hashtable: read item failed: %s\n", - g10_errstr(rc) ); - return rc; - } - - if( rec.rectype == RECTYPE_HTBL ) { - hashrec = item; - level++; - if( level >= keylen ) { - log_error( "hashtable has invalid indirections.\n"); - return G10ERR_TRUSTDB; - } - goto next_level; - } - else if( rec.rectype == RECTYPE_HLST ) { /* extend list */ - /* see whether the key is already in this list */ - for(;;) { - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - if( rec.r.hlst.rnum[i] == newrecnum ) { - return 0; /* okay, already in the list */ - } - } - if( rec.r.hlst.next ) { - rc = tdbio_read_record( rec.r.hlst.next, - &rec, RECTYPE_HLST); - if( rc ) { - log_error( "upd_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); - return rc; - } - } - else - break; /* not there */ - } - /* find the next free entry and put it in */ - for(;;) { - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - if( !rec.r.hlst.rnum[i] ) { - rec.r.hlst.rnum[i] = newrecnum; - rc = tdbio_write_record( &rec ); - if( rc ) - log_error( "upd_hashtable: write hlst failed: %s\n", - g10_errstr(rc) ); - return rc; /* done */ - } - } - if( rec.r.hlst.next ) { - rc = tdbio_read_record( rec.r.hlst.next, - &rec, RECTYPE_HLST ); - if( rc ) { - log_error( "upd_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); - return rc; - } - } - else { /* add a new list record */ - rec.r.hlst.next = item = tdbio_new_recnum(); - rc = tdbio_write_record( &rec ); - if( rc ) { - log_error( "upd_hashtable: write hlst failed: %s\n", - g10_errstr(rc) ); - return rc; - } - memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_HLST; - rec.recnum = item; - rec.r.hlst.rnum[0] = newrecnum; - rc = tdbio_write_record( &rec ); - if( rc ) - log_error( "upd_hashtable: write ext hlst failed: %s\n", - g10_errstr(rc) ); - return rc; /* done */ - } - } /* end loop over hlst slots */ - } - else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */ - if( rec.recnum == newrecnum ) { - return 0; - } - item = rec.recnum; /* save number of key record */ - memset( &rec, 0, sizeof rec ); - rec.rectype = RECTYPE_HLST; - rec.recnum = tdbio_new_recnum(); - rec.r.hlst.rnum[0] = item; /* old keyrecord */ - rec.r.hlst.rnum[1] = newrecnum; /* and new one */ - rc = tdbio_write_record( &rec ); - if( rc ) { - log_error( "upd_hashtable: write new hlst failed: %s\n", - g10_errstr(rc) ); - return rc; - } - /* update the hashtable record */ - lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum; - rc = tdbio_write_record( &lastrec ); - if( rc ) - log_error( "upd_hashtable: update htbl failed: %s\n", - g10_errstr(rc) ); - return rc; /* ready */ - } - else { - log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n", - table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); - list_trustdb(NULL); - return G10ERR_TRUSTDB; - } - } - - return 0; -} - - -/**************** - * Drop an entry from a hashtable - * table gives the start of the table, key and keylen is the key, - */ -static int -drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) -{ - TRUSTREC rec; - ulong hashrec, item; - int msb; - int level=0; - int rc, i; - - hashrec = table; - next_level: - msb = key[level]; - hashrec += msb / ITEMS_PER_HTBL_RECORD; - rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); - if( rc ) { - log_error( db_name, "drop_from_hashtable: read failed: %s\n", - g10_errstr(rc) ); - return rc; - } - - item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; - if( !item ) /* not found - forget about it */ - return 0; - - if( item == recnum ) { /* tables points direct to the record */ - rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0; - rc = tdbio_write_record( &rec ); - if( rc ) - log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - g10_errstr(rc) ); - return rc; - } - - rc = tdbio_read_record( item, &rec, 0 ); - if( rc ) { - log_error( "drop_from_hashtable: read item failed: %s\n", - g10_errstr(rc) ); - return rc; - } - - if( rec.rectype == RECTYPE_HTBL ) { - hashrec = item; - level++; - if( level >= keylen ) { - log_error( "hashtable has invalid indirections.\n"); - return G10ERR_TRUSTDB; - } - goto next_level; - } - - if( rec.rectype == RECTYPE_HLST ) { - for(;;) { - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - if( rec.r.hlst.rnum[i] == recnum ) { - rec.r.hlst.rnum[i] = 0; /* drop */ - rc = tdbio_write_record( &rec ); - if( rc ) - log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - g10_errstr(rc) ); - return rc; - } - } - if( rec.r.hlst.next ) { - rc = tdbio_read_record( rec.r.hlst.next, - &rec, RECTYPE_HLST); - if( rc ) { - log_error( "drop_from_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); - return rc; - } - } - else - return 0; /* key not in table */ - } - } - - log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n", - table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); - return G10ERR_TRUSTDB; -} - - - -/**************** - * Lookup a record via the hashtable tablewith key/keylen and return the - * result in rec. cmp() should return if the record is the desired one. - * Returns -1 if not found, 0 if found or another errocode - */ -static int -lookup_hashtable( ulong table, const byte *key, size_t keylen, - int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata, - TRUSTREC *rec ) -{ - int rc; - ulong hashrec, item; - int msb; - int level=0; - - hashrec = table; - next_level: - msb = key[level]; - hashrec += msb / ITEMS_PER_HTBL_RECORD; - rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL ); - if( rc ) { - log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) ); - return rc; - } - - item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; - if( !item ) - return -1; /* not found */ - - rc = tdbio_read_record( item, rec, 0 ); - if( rc ) { - log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) ); - return rc; - } - if( rec->rectype == RECTYPE_HTBL ) { - hashrec = item; - level++; - if( level >= keylen ) { - log_error( db_name, "hashtable has invalid indirections\n"); - return G10ERR_TRUSTDB; - } - goto next_level; - } - else if( rec->rectype == RECTYPE_HLST ) { - for(;;) { - int i; - - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - if( rec->r.hlst.rnum[i] ) { - TRUSTREC tmp; - - rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 ); - if( rc ) { - log_error( "lookup_hashtable: read item failed: %s\n", - g10_errstr(rc) ); - return rc; - } - if( (*cmpfnc)( cmpdata, &tmp ) ) { - *rec = tmp; - return 0; - } - } - } - if( rec->r.hlst.next ) { - rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST ); - if( rc ) { - log_error( "lookup_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); - return rc; - } - } - else - return -1; /* not found */ - } - } - - - if( (*cmpfnc)( cmpdata, rec ) ) - return 0; /* really found */ - - return -1; /* no: not found */ -} - - -/**************** - * Update the trust hashtbl or create the table if it does not exist - */ -static int -update_trusthashtbl( TRUSTREC *tr ) -{ - return upd_hashtable( get_trusthashrec(), - tr->r.trust.fingerprint, 20, tr->recnum ); -} - - - -void -tdbio_dump_record( TRUSTREC *rec, FILE *fp ) -{ - int i; - ulong rnum = rec->recnum; - - fprintf(fp, "rec %5lu, ", rnum ); - - switch( rec->rectype ) { - case 0: fprintf(fp, "blank\n"); - break; - case RECTYPE_VER: fprintf(fp, - "version, td=%lu, f=%lu, m/c/d=%d/%d/%d nc=%lu (%s)\n", - rec->r.ver.trusthashtbl, - rec->r.ver.firstfree, - rec->r.ver.marginals, - rec->r.ver.completes, - rec->r.ver.cert_depth, - rec->r.ver.nextcheck, - strtimestamp(rec->r.ver.nextcheck) - ); - break; - case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next ); - break; - case RECTYPE_HTBL: - fprintf(fp, "htbl,"); - for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) - fprintf(fp, " %lu", rec->r.htbl.item[i] ); - putc('\n', fp); - break; - case RECTYPE_HLST: - fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next ); - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) - fprintf(fp, " %lu", rec->r.hlst.rnum[i] ); - putc('\n', fp); - break; - case RECTYPE_TRUST: - fprintf(fp, "trust "); - for(i=0; i < 20; i++ ) - fprintf(fp, "%02X", rec->r.trust.fingerprint[i] ); - fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust, - rec->r.trust.depth, rec->r.trust.validlist); - break; - case RECTYPE_VALID: - fprintf(fp, "valid "); - for(i=0; i < 20; i++ ) - fprintf(fp, "%02X", rec->r.valid.namehash[i] ); - fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity, - rec->r.valid.next); - break; - default: - fprintf(fp, "unknown type %d\n", rec->rectype ); - break; - } -} - -/**************** - * read the record with number recnum - * returns: -1 on error, 0 on success - */ -int -tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) -{ - byte readbuf[TRUST_RECORD_LEN]; - const byte *buf, *p; - int rc = 0; - int n, i; - - if( db_fd == -1 ) - open_db(); - buf = get_record_from_cache( recnum ); - if( !buf ) { - if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return G10ERR_READ_FILE; - } - n = read( db_fd, readbuf, TRUST_RECORD_LEN); - if( !n ) { - return -1; /* eof */ - } - else if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb: read failed (n=%d): %s\n"), n, - strerror(errno) ); - return G10ERR_READ_FILE; - } - buf = readbuf; - } - rec->recnum = recnum; - rec->dirty = 0; - p = buf; - rec->rectype = *p++; - if( expected && rec->rectype != expected ) { - log_error("%lu: read expected rec type %d, got %d\n", - recnum, expected, rec->rectype ); - return G10ERR_TRUSTDB; - } - p++; /* skip reserved byte */ - switch( rec->rectype ) { - case 0: /* unused (free) record */ - break; - case RECTYPE_VER: /* version record */ - if( memcmp(buf+1, "gpg", 3 ) ) { - log_error( _("%s: not a trustdb file\n"), db_name ); - rc = G10ERR_TRUSTDB; - } - p += 2; /* skip "gpg" */ - rec->r.ver.version = *p++; - rec->r.ver.marginals = *p++; - rec->r.ver.completes = *p++; - rec->r.ver.cert_depth = *p++; - p += 4; /* lock flags */ - rec->r.ver.created = buftoulong(p); p += 4; - rec->r.ver.nextcheck = buftoulong(p); p += 4; - p += 4; - p += 4; - rec->r.ver.firstfree =buftoulong(p); p += 4; - p += 4; - rec->r.ver.trusthashtbl =buftoulong(p); p += 4; - if( recnum ) { - log_error( _("%s: version record with recnum %lu\n"), db_name, - (ulong)recnum ); - rc = G10ERR_TRUSTDB; - } - else if( rec->r.ver.version != 3 ) { - log_error( _("%s: invalid file version %d\n"), db_name, - rec->r.ver.version ); - rc = G10ERR_TRUSTDB; - } - break; - case RECTYPE_FREE: - rec->r.free.next = buftoulong(p); p += 4; - break; - case RECTYPE_HTBL: - for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) { - rec->r.htbl.item[i] = buftoulong(p); p += 4; - } - break; - case RECTYPE_HLST: - rec->r.hlst.next = buftoulong(p); p += 4; - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - rec->r.hlst.rnum[i] = buftoulong(p); p += 4; - } - break; - case RECTYPE_TRUST: - memcpy( rec->r.trust.fingerprint, p, 20); p+=20; - rec->r.trust.ownertrust = *p++; - rec->r.trust.depth = *p++; - p += 2; - rec->r.trust.validlist = buftoulong(p); p += 4; - break; - case RECTYPE_VALID: - memcpy( rec->r.valid.namehash, p, 20); p+=20; - rec->r.valid.validity = *p++; - rec->r.valid.next = buftoulong(p); p += 4; - break; - default: - log_error( "%s: invalid record type %d at recnum %lu\n", - db_name, rec->rectype, (ulong)recnum ); - rc = G10ERR_TRUSTDB; - break; - } - - return rc; -} - -/**************** - * Write the record at RECNUM - */ -int -tdbio_write_record( TRUSTREC *rec ) -{ - byte buf[TRUST_RECORD_LEN], *p; - int rc = 0; - int i; - ulong recnum = rec->recnum; - - if( db_fd == -1 ) - open_db(); - - memset(buf, 0, TRUST_RECORD_LEN); - p = buf; - *p++ = rec->rectype; p++; - switch( rec->rectype ) { - case 0: /* unused record */ - break; - case RECTYPE_VER: /* version record */ - if( recnum ) - BUG(); - memcpy(p-1, "gpg", 3 ); p += 2; - *p++ = rec->r.ver.version; - *p++ = rec->r.ver.marginals; - *p++ = rec->r.ver.completes; - *p++ = rec->r.ver.cert_depth; - p += 4; /* skip lock flags */ - ulongtobuf(p, rec->r.ver.created); p += 4; - ulongtobuf(p, rec->r.ver.nextcheck); p += 4; - p += 4; - p += 4; - ulongtobuf(p, rec->r.ver.firstfree ); p += 4; - p += 4; - ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4; - break; - - case RECTYPE_FREE: - ulongtobuf(p, rec->r.free.next); p += 4; - break; - - - case RECTYPE_HTBL: - for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) { - ulongtobuf( p, rec->r.htbl.item[i]); p += 4; - } - break; - - case RECTYPE_HLST: - ulongtobuf( p, rec->r.hlst.next); p += 4; - for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4; - } - break; - - case RECTYPE_TRUST: - memcpy( p, rec->r.trust.fingerprint, 20); p += 20; - *p++ = rec->r.trust.ownertrust; - *p++ = rec->r.trust.depth; - p += 2; - ulongtobuf( p, rec->r.trust.validlist); p += 4; - break; - - case RECTYPE_VALID: - memcpy( p, rec->r.valid.namehash, 20); p += 20; - *p++ = rec->r.valid.validity; - ulongtobuf( p, rec->r.valid.next); p += 4; - break; - - default: - BUG(); - } - - rc = put_record_into_cache( recnum, buf ); - if( rc ) - ; - else if( rec->rectype == RECTYPE_TRUST ) - rc = update_trusthashtbl( rec ); - - return rc; -} - -int -tdbio_delete_record( ulong recnum ) -{ - TRUSTREC vr, rec; - int rc; - - /* Must read the record fist, so we can drop it from the hash tables */ - rc = tdbio_read_record( recnum, &rec, 0 ); - if( rc ) - ; - else if( rec.rectype == RECTYPE_TRUST ) { - rc = drop_from_hashtable( get_trusthashrec(), - rec.r.trust.fingerprint, 20, rec.recnum ); - } - - if( rc ) - return rc; - - /* now we can chnage it to a free record */ - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); - - rec.recnum = recnum; - rec.rectype = RECTYPE_FREE; - rec.r.free.next = vr.r.ver.firstfree; - vr.r.ver.firstfree = recnum; - rc = tdbio_write_record( &rec ); - if( !rc ) - rc = tdbio_write_record( &vr ); - return rc; -} - -/**************** - * create a new record and return its record number - */ -ulong -tdbio_new_recnum() -{ - off_t offset; - ulong recnum; - TRUSTREC vr, rec; - int rc; - - /* look for unused records */ - rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); - if( rc ) - log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); - if( vr.r.ver.firstfree ) { - recnum = vr.r.ver.firstfree; - rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE ); - if( rc ) { - log_error( _("%s: error reading free record: %s\n"), - db_name, g10_errstr(rc) ); - return rc; - } - /* update dir record */ - vr.r.ver.firstfree = rec.r.free.next; - rc = tdbio_write_record( &vr ); - if( rc ) { - log_error( _("%s: error writing dir record: %s\n"), - db_name, g10_errstr(rc) ); - return rc; - } - /*zero out the new record */ - memset( &rec, 0, sizeof rec ); - rec.rectype = 0; /* unused record */ - rec.recnum = recnum; - rc = tdbio_write_record( &rec ); - if( rc ) - log_fatal(_("%s: failed to zero a record: %s\n"), - db_name, g10_errstr(rc)); - } - else { /* not found, append a new record */ - offset = lseek( db_fd, 0, SEEK_END ); - if( offset == -1 ) - log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) ); - recnum = offset / TRUST_RECORD_LEN; - assert(recnum); /* this is will never be the first record */ - /* we must write a record, so that the next call to this function - * returns another recnum */ - memset( &rec, 0, sizeof rec ); - rec.rectype = 0; /* unused record */ - rec.recnum = recnum; - rc = 0; - if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - log_error(_("trustdb rec %lu: lseek failed: %s\n"), - recnum, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - } - else { - int n = write( db_fd, &rec, TRUST_RECORD_LEN); - if( n != TRUST_RECORD_LEN ) { - log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), - recnum, n, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - } - } - - if( rc ) - log_fatal(_("%s: failed to append a record: %s\n"), - db_name, g10_errstr(rc)); - } - return recnum ; -} - - - -static int -cmp_trec_fpr ( void *fpr, const TRUSTREC *rec ) -{ - return rec->rectype == RECTYPE_TRUST - && !memcmp( rec->r.trust.fingerprint, fpr, 20); -} - - -int -tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec ) -{ - int rc; - - /* locate the trust record using the hash table */ - rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20, - cmp_trec_fpr, (void*)fingerprint, rec ); - return rc; -} - -int -tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec) -{ - byte fingerprint[MAX_FINGERPRINT_LEN]; - size_t fingerlen; - - fingerprint_from_pk( pk, fingerprint, &fingerlen ); - for (; fingerlen < 20; fingerlen++ ) - fingerprint[fingerlen] = 0; - return tdbio_search_trust_byfpr (fingerprint, rec); -} - - - -void -tdbio_invalid(void) -{ - log_error(_( - "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") ); - g10_exit(2); -} - -/* - * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2) - * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs - * only to scan the tdb and insert new the new trust records. The old ones are - * obsolte from now on - */ -static void -migrate_from_v2 () -{ - TRUSTREC rec; - int i, n; - struct { - ulong keyrecno; - byte ot; - byte okay; - byte fpr[20]; - } *ottable; - int ottable_size, ottable_used; - byte oldbuf[40]; - ulong recno; - int rc, count; - - ottable_size = 5; - ottable = m_alloc (ottable_size * sizeof *ottable); - ottable_used = 0; - - /* We have some restrictions here. We can't use the version record - * and we can't use any of the old hashtables because we dropped the - * code. So we first collect all ownertrusts and then use a second - * pass fo find the associated keys. We have to do this all without using - * the regular record read functions. - */ - - /* get all the ownertrusts */ - if (lseek (db_fd, 0, SEEK_SET ) == -1 ) - log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); - for (recno=0;;recno++) - { - do - n = read (db_fd, oldbuf, 40); - while (n==-1 && errno == EINTR); - if (!n) - break; /* eof */ - if (n != 40) - log_fatal ("migrate_vfrom_v2: read error or short read\n"); - - if (*oldbuf != 2) - continue; - - /* v2 dir record */ - if (ottable_used == ottable_size) - { - ottable_size += 1000; - ottable = m_realloc (ottable, ottable_size * sizeof *ottable); - } - ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); - ottable[ottable_used].ot = oldbuf[18]; - ottable[ottable_used].okay = 0; - memset (ottable[ottable_used].fpr,0, 20); - if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot) - ottable_used++; - } - log_info ("found %d ownertrust records\n", ottable_used); - - /* Read again and find the fingerprints */ - if (lseek (db_fd, 0, SEEK_SET ) == -1 ) - log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); - for (recno=0;;recno++) - { - do - n = read (db_fd, oldbuf, 40); - while (n==-1 && errno == EINTR); - if (!n) - break; /* eof */ - if (n != 40) - log_fatal ("migrate_from_v2: read error or short read\n"); - - if (*oldbuf != 3) - continue; - - /* v2 key record */ - for (i=0; i < ottable_used; i++) - { - if (ottable[i].keyrecno == recno) - { - memcpy (ottable[i].fpr, oldbuf+20, 20); - ottable[i].okay = 1; - break; - } - } - } - - /* got everything - create the v3 trustdb */ - if (ftruncate (db_fd, 0)) - log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) ); - if (create_version_record ()) - log_fatal ("failed to recreate version record of `%s'\n", db_name); - - /* access the hash table, so it is store just after the version record, - * this is not needed put a dump is more pretty */ - get_trusthashrec (); - - /* And insert the old ownertrust values */ - count = 0; - for (i=0; i < ottable_used; i++) - { - if (!ottable[i].okay) - continue; - - memset (&rec, 0, sizeof rec); - rec.recnum = tdbio_new_recnum (); - rec.rectype = RECTYPE_TRUST; - memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20); - rec.r.trust.ownertrust = ottable[i].ot; - if (tdbio_write_record (&rec)) - log_fatal ("failed to write trust record of `%s'\n", db_name); - count++; - } - - revalidation_mark (); - rc = tdbio_sync (); - if (rc) - log_fatal ("failed to sync `%s'\n", db_name); - log_info ("migrated %d version 2 ownertrusts\n", count); - m_free (ottable); -} - - - diff --git a/g10/tdbio.h b/g10/tdbio.h deleted file mode 100644 index f2c6bec1b..000000000 --- a/g10/tdbio.h +++ /dev/null @@ -1,111 +0,0 @@ -/* tdbio.h - Trust database I/O functions - * 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 - */ - -#ifndef G10_TDBIO_H -#define G10_TDBIO_H - -#include "host2net.h" - -#define TRUST_RECORD_LEN 40 -#define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5) -#define ITEMS_PER_HTBL_RECORD ((TRUST_RECORD_LEN-2)/4) -#define ITEMS_PER_HLST_RECORD ((TRUST_RECORD_LEN-6)/5) -#define ITEMS_PER_PREF_RECORD (TRUST_RECORD_LEN-10) -#if ITEMS_PER_PREF_RECORD % 2 - #error ITEMS_PER_PREF_RECORD must be even -#endif -#define MAX_LIST_SIGS_DEPTH 20 - - -#define RECTYPE_VER 1 -#define RECTYPE_HTBL 10 -#define RECTYPE_HLST 11 -#define RECTYPE_TRUST 12 -#define RECTYPE_VALID 13 -#define RECTYPE_FREE 254 - - -struct trust_record { - int rectype; - int mark; - int dirty; /* for now only used internal by functions */ - struct trust_record *next; /* help pointer to build lists in memory */ - ulong recnum; - union { - struct { /* version record: */ - byte version; /* should be 3 */ - byte marginals; - byte completes; - byte cert_depth; - ulong created; /* timestamp of trustdb creation */ - ulong nextcheck; /* timestamp of next scheduled check */ - ulong reserved; - ulong reserved2; - ulong firstfree; - ulong reserved3; - ulong trusthashtbl; - } ver; - struct { /* free record */ - ulong next; - } free; - struct { - ulong item[ITEMS_PER_HTBL_RECORD]; - } htbl; - struct { - ulong next; - ulong rnum[ITEMS_PER_HLST_RECORD]; /* of another record */ - } hlst; - struct { - byte fingerprint[20]; - byte ownertrust; - byte depth; - ulong validlist; - } trust; - struct { - byte namehash[20]; - ulong next; - byte validity; - } valid; - } r; -}; -typedef struct trust_record TRUSTREC; - -/*-- tdbio.c --*/ -int tdbio_set_dbname( const char *new_dbname, int create ); -const char *tdbio_get_dbname(void); -void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); -int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); -int tdbio_write_record( TRUSTREC *rec ); -int tdbio_db_matches_options(void); -ulong tdbio_read_nextcheck (void); -int tdbio_write_nextcheck (ulong stamp); -int tdbio_is_dirty(void); -int tdbio_sync(void); -int tdbio_begin_transaction(void); -int tdbio_end_transaction(void); -int tdbio_cancel_transaction(void); -int tdbio_delete_record( ulong recnum ); -ulong tdbio_new_recnum(void); -int tdbio_search_trust_byfpr(const byte *fingerprint, TRUSTREC *rec ); -int tdbio_search_trust_bypk(PKT_public_key *pk, TRUSTREC *rec ); - -void tdbio_invalid(void); - -#endif /*G10_TDBIO_H*/ diff --git a/g10/textfilter.c b/g10/textfilter.c deleted file mode 100644 index ded030d79..000000000 --- a/g10/textfilter.c +++ /dev/null @@ -1,235 +0,0 @@ -/* textfilter.c - * 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 -#include -#include -#include -#include -#include - -#include "errors.h" -#include "iobuf.h" -#include "memory.h" -#include "util.h" -#include "filter.h" -#include "i18n.h" -#include "options.h" - -#ifdef HAVE_DOSISH_SYSTEM - #define LF "\r\n" -#else - #define LF "\n" -#endif - -#define MAX_LINELEN 19995 /* a little bit smaller than in armor.c */ - /* to make sure that a warning is displayed while */ - /* creating a message */ - -static unsigned -len_without_trailing_chars( byte *line, unsigned len, const char *trimchars ) -{ - byte *p, *mark; - unsigned n; - - for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { - if( strchr( trimchars, *p ) ) { - if( !mark ) - mark = p; - } - else - mark = NULL; - } - - return mark? (mark - line) : len; -} - -unsigned -len_without_trailing_ws( byte *line, unsigned len ) -{ - return len_without_trailing_chars( line, len, " \t\r\n" ); -} - - - - -static int -standard( text_filter_context_t *tfx, IOBUF a, - byte *buf, size_t size, size_t *ret_len) -{ - int rc=0; - size_t len = 0; - unsigned maxlen; - - assert( size > 10 ); - size -= 2; /* reserve 2 bytes to append CR,LF */ - while( !rc && len < size ) { - int lf_seen; - - while( len < size && tfx->buffer_pos < tfx->buffer_len ) - buf[len++] = tfx->buffer[tfx->buffer_pos++]; - if( len >= size ) - continue; - - /* read the next line */ - maxlen = MAX_LINELEN; - tfx->buffer_pos = 0; - tfx->buffer_len = iobuf_read_line( a, &tfx->buffer, - &tfx->buffer_size, &maxlen ); - if( !maxlen ) - tfx->truncated++; - if( !tfx->buffer_len ) { - if( !len ) - rc = -1; /* eof */ - break; - } - lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n'; - tfx->buffer_len = trim_trailing_ws( tfx->buffer, tfx->buffer_len ); - if( lf_seen ) { - tfx->buffer[tfx->buffer_len++] = '\r'; - tfx->buffer[tfx->buffer_len++] = '\n'; - } - } - *ret_len = len; - return rc; -} - - - - -/**************** - * The filter is used to make canonical text: Lines are terminated by - * CR, LF, trailing white spaces are removed. - */ -int -text_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) -{ - size_t size = *ret_len; - text_filter_context_t *tfx = opaque; - int rc=0; - - if( control == IOBUFCTRL_UNDERFLOW ) { - rc = standard( tfx, a, buf, size, ret_len ); - } - else if( control == IOBUFCTRL_FREE ) { - if( tfx->truncated ) - log_error(_("can't handle text lines longer than %d characters\n"), - MAX_LINELEN ); - m_free( tfx->buffer ); - tfx->buffer = NULL; - } - else if( control == IOBUFCTRL_DESC ) - *(char**)buf = "text_filter"; - return rc; -} - - -/**************** - * Copy data from INP to OUT and do some escaping if requested. - * md is updated as required by rfc2440 - */ -int -copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, - int escape_dash, int escape_from, int pgp2mode ) -{ - unsigned maxlen; - byte *buffer = NULL; /* malloced buffer */ - unsigned bufsize; /* and size of this buffer */ - unsigned n; - int truncated = 0; - int pending_lf = 0; - - if( !opt.pgp2_workarounds ) - pgp2mode = 0; - - if( !escape_dash ) - escape_from = 0; - - for(;;) { - maxlen = MAX_LINELEN; - n = iobuf_read_line( inp, &buffer, &bufsize, &maxlen ); - if( !maxlen ) - truncated++; - - if( !n ) - break; /* read_line has returned eof */ - - /* update the message digest */ - if( escape_dash ) { - if( pending_lf ) { - md_putc( md, '\r' ); - md_putc( md, '\n' ); - } - md_write( md, buffer, - len_without_trailing_chars( buffer, n, - pgp2mode? " \r\n":" \t\r\n")); - } - else - md_write( md, buffer, n ); - pending_lf = buffer[n-1] == '\n'; - - /* write the output */ - if( ( escape_dash && *buffer == '-') - || ( escape_from && n > 4 && !memcmp(buffer, "From ", 5 ) ) ) { - iobuf_put( out, '-' ); - iobuf_put( out, ' ' ); - } - - #if 0 /*defined(HAVE_DOSISH_SYSTEM)*/ - /* We don't use this anymore because my interpretation of rfc2440 7.1 - * is that there is no conversion needed. If one decides to - * clearsign a unix file on a DOS box he will get a mixed line endings. - * If at some point it turns out, that a conversion is a nice feature - * we can make an option out of it. - */ - /* make sure the lines do end in CR,LF */ - if( n > 1 && ( (buffer[n-2] == '\r' && buffer[n-1] == '\n' ) - || (buffer[n-2] == '\n' && buffer[n-1] == '\r'))) { - iobuf_write( out, buffer, n-2 ); - iobuf_put( out, '\r'); - iobuf_put( out, '\n'); - } - else if( n && buffer[n-1] == '\n' ) { - iobuf_write( out, buffer, n-1 ); - iobuf_put( out, '\r'); - iobuf_put( out, '\n'); - } - else - iobuf_write( out, buffer, n ); - - #else - iobuf_write( out, buffer, n ); - #endif - } - - /* at eof */ - if( !pending_lf ) { /* make sure that the file ends with a LF */ - iobuf_writestr( out, LF ); - if( !escape_dash ) - md_putc( md, '\n' ); - } - - if( truncated ) - log_info(_("input line longer than %d characters\n"), MAX_LINELEN ); - - return 0; /* okay */ -} - diff --git a/g10/trustdb.c b/g10/trustdb.c deleted file mode 100644 index fe2ad34e3..000000000 --- a/g10/trustdb.c +++ /dev/null @@ -1,1642 +0,0 @@ -/* trustdb.c - * 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 -#include -#include -#include -#include - -#include "errors.h" -#include "iobuf.h" -#include "keydb.h" -#include "memory.h" -#include "util.h" -#include "options.h" -#include "packet.h" -#include "main.h" -#include "i18n.h" -#include "tdbio.h" -#include "trustdb.h" - - -/* - * A structure to store key identification as well as some stuff needed - * for validation - */ -struct key_item { - struct key_item *next; - unsigned int ownertrust; - u32 kid[2]; -}; - - -typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */ - -/* - * Structure to keep track of keys, this is used as an array wherre - * the item right after the last one has a keyblock set to NULL. - * Maybe we can drop this thing and replace it by key_item - */ -struct key_array { - KBNODE keyblock; -}; - - -/* control information for the trust DB */ -static struct { - int init; - int level; - char *dbname; -} trustdb_args; - -/* some globals */ -static struct key_item *user_utk_list; /* temp. used to store --trusted-keys */ -static struct key_item *utk_list; /* all ultimately trusted keys */ - -static int pending_check_trustdb; - -static int validate_keys (int interactive); - - -/********************************************** - ************* some helpers ******************* - **********************************************/ - -static struct key_item * -new_key_item (void) -{ - struct key_item *k; - - k = m_alloc_clear (sizeof *k); - return k; -} - -static void -release_key_items (struct key_item *k) -{ - struct key_item *k2; - - for (; k; k = k2) - { - k2 = k->next; - m_free (k); - } -} - -/* - * For fast keylook up we need a hash table. Each byte of a KeyIDs - * should be distributed equally over the 256 possible values (except - * for v3 keyIDs but we consider them as not important here). So we - * can just use 10 bits to index a table of 1024 key items. - * Possible optimization: Don not use key_items but other hash_table when the - * duplicates lists gets too large. - */ -static KeyHashTable -new_key_hash_table (void) -{ - struct key_item **tbl; - - tbl = m_alloc_clear (1024 * sizeof *tbl); - return tbl; -} - -static void -release_key_hash_table (KeyHashTable tbl) -{ - int i; - - if (!tbl) - return; - for (i=0; i < 1024; i++) - release_key_items (tbl[i]); - m_free (tbl); -} - -/* - * Returns: True if the keyID is in the given hash table - */ -static int -test_key_hash_table (KeyHashTable tbl, u32 *kid) -{ - struct key_item *k; - - for (k = tbl[(kid[1] & 0x03ff)]; k; k = k->next) - if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) - return 1; - return 0; -} - -/* - * Add a new key to the hash table. The key is identified by its key ID. - */ -static void -add_key_hash_table (KeyHashTable tbl, u32 *kid) -{ - struct key_item *k, *kk; - - for (k = tbl[(kid[1] & 0x03ff)]; k; k = k->next) - if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) - return; /* already in table */ - - kk = new_key_item (); - kk->kid[0] = kid[0]; - kk->kid[1] = kid[1]; - kk->next = tbl[(kid[1] & 0x03ff)]; - tbl[(kid[1] & 0x03ff)] = kk; -} - -/* - * Release a key_array - */ -static void -release_key_array ( struct key_array *keys ) -{ - struct key_array *k; - - if (keys) { - for (k=keys; k->keyblock; k++) - release_kbnode (k->keyblock); - m_free (keys); - } -} - - -/********************************************* - ********** Initialization ***************** - *********************************************/ - - - -/* - * Used to register extra ultimately trusted keys - this has to be done - * before initializing the validation module. - * FIXME: Should be replaced by a function to add those keys to the trustdb. - */ -void -register_trusted_key( const char *string ) -{ - KEYDB_SEARCH_DESC desc; - struct key_item *k; - - if (classify_user_id (string, &desc) != KEYDB_SEARCH_MODE_LONG_KID ) { - log_error(_("`%s' is not a valid long keyID\n"), string ); - return; - } - - k = new_key_item (); - k->kid[0] = desc.u.kid[0]; - k->kid[1] = desc.u.kid[1]; - k->next = user_utk_list; - user_utk_list = k; -} - -/* - * Helper to add a key to the global list of ultimately trusted keys. - * Retruns: true = inserted, false = already in in list. - */ -static int -add_utk (u32 *kid) -{ - struct key_item *k; - - for (k = utk_list; k; k = k->next) - { - if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) - { - return 0; - } - } - - k = new_key_item (); - k->kid[0] = kid[0]; - k->kid[1] = kid[1]; - k->ownertrust = TRUST_ULTIMATE; - k->next = utk_list; - utk_list = k; - if( opt.verbose > 1 ) - log_info(_("key %08lX: accepted as trusted key\n"), (ulong)kid[1]); - return 1; -} - - -/**************** - * Verify that all our secret keys are usable and put them into the utk_list. - */ -static void -verify_own_keys(void) -{ - TRUSTREC rec; - ulong recnum; - int rc; - struct key_item *k; - - if (utk_list) - return; - - /* scan the trustdb to find all ultimately trusted keys */ - for (recnum=1; !tdbio_read_record (recnum, &rec, 0); recnum++ ) - { - if ( rec.rectype == RECTYPE_TRUST - && (rec.r.trust.ownertrust & TRUST_MASK) == TRUST_ULTIMATE) - { - byte *fpr = rec.r.trust.fingerprint; - int fprlen; - u32 kid[2]; - - /* Problem: We do only use fingerprints in the trustdb but - * we need the keyID here to indetify the key; we can only - * use that ugly hack to distinguish between 16 and 20 - * butes fpr - it does not work always so we better change - * the whole validation code to only work with - * fingerprints */ - fprlen = (!fpr[16] && !fpr[17] && !fpr[18] && !fpr[19])? 16:20; - keyid_from_fingerprint (fpr, fprlen, kid); - if (!add_utk (kid)) - log_info(_("key %08lX occurs more than once in the trustdb\n"), - (ulong)kid[1]); - } - } - - /* the --trusted-key option is again deprecated; however we automagically - * add those keys to the trustdb */ - for (k = user_utk_list; k; k = k->next) - { - if ( add_utk (k->kid) ) - { /* not yet in trustDB as ultimately trusted */ - PKT_public_key pk; - - memset (&pk, 0, sizeof pk); - rc = get_pubkey (&pk, k->kid); - if (rc) { - log_info(_("key %08lX: no public key for trusted key - skipped\n"), - (ulong)k->kid[1] ); - } - else { - update_ownertrust (&pk, - ((get_ownertrust (&pk) & ~TRUST_MASK) - | TRUST_ULTIMATE )); - release_public_key_parts (&pk); - } - log_info (_("key %08lX marked as ultimately trusted\n"), - (ulong)k->kid[1]); - } - } - - - /* release the helper table table */ - release_key_items (user_utk_list); - user_utk_list = NULL; - return; -} - - -/********************************************* - *********** TrustDB stuff ******************* - *********************************************/ - -/* - * Read a record but die if it does not exist - */ -static void -read_record (ulong recno, TRUSTREC *rec, int rectype ) -{ - int rc = tdbio_read_record (recno, rec, rectype); - if (rc) - { - log_error(_("trust record %lu, req type %d: read failed: %s\n"), - recno, rec->rectype, g10_errstr(rc) ); - tdbio_invalid(); - } - if (rectype != rec->rectype) - { - log_error(_("trust record %lu is not of requested type %d\n"), - rec->recnum, rectype); - tdbio_invalid(); - } -} - -/* - * Write a record and die on error - */ -static void -write_record (TRUSTREC *rec) -{ - int rc = tdbio_write_record (rec); - if (rc) - { - log_error(_("trust record %lu, type %d: write failed: %s\n"), - rec->recnum, rec->rectype, g10_errstr(rc) ); - tdbio_invalid(); - } -} - -/* - * sync the TrustDb and die on error - */ -static void -do_sync(void) -{ - int rc = tdbio_sync (); - if(rc) - { - log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) ); - g10_exit(2); - } -} - - -/**************** - * Perform some checks over the trustdb - * level 0: only open the db - * 1: used for initial program startup - */ -int -setup_trustdb( int level, const char *dbname ) -{ - /* just store the args */ - if( trustdb_args.init ) - return 0; - trustdb_args.level = level; - trustdb_args.dbname = dbname? m_strdup(dbname): NULL; - return 0; -} - -void -init_trustdb() -{ - int rc=0; - int level = trustdb_args.level; - const char* dbname = trustdb_args.dbname; - - if( trustdb_args.init ) - return; - - trustdb_args.init = 1; - - if ( !level || level==1) - { - rc = tdbio_set_dbname( dbname, !!level ); - if( !rc ) - { - if( !level ) - return; - - /* verify that our own keys are in the trustDB - * or move them to the trustdb. */ - verify_own_keys(); - - /* should we check whether there is no other ultimately trusted - * key in the database? */ - } - } - else - BUG(); - if( rc ) - log_fatal("can't init trustdb: %s\n", g10_errstr(rc) ); -} - - - - -/*********************************************** - ************* Print helpers **************** - ***********************************************/ - -/**************** - * This function returns a letter for a trustvalue Trust flags - * are ignore. - */ -int -trust_letter (unsigned int value) -{ - switch( (value & TRUST_MASK) ) - { - case TRUST_UNKNOWN: return '-'; - case TRUST_EXPIRED: return 'e'; - case TRUST_UNDEFINED: return 'q'; - case TRUST_NEVER: return 'n'; - case TRUST_MARGINAL: return 'm'; - case TRUST_FULLY: return 'f'; - case TRUST_ULTIMATE: return 'u'; - default: return 0; - } -} - - -/**************** - * Recreate the WoT but do not ask for new ownertrusts. Special - * feature: In batch mode and without a forced yes, this is only done - * when a check is due. This can be used to run the check from a crontab - */ -void -check_trustdb () -{ - init_trustdb(); - if (opt.batch && !opt.answer_yes) - { - ulong scheduled; - - scheduled = tdbio_read_nextcheck (); - if (!scheduled) - { - log_info (_("no need for a trustdb check\n")); - return; - } - - if (scheduled > make_timestamp ()) - { - log_info (_("next trustdb check due at %s\n"), - strtimestamp (scheduled)); - return; - } - } - - validate_keys (0); -} - - -/* - * Recreate the WoT. - */ -void -update_trustdb() -{ - init_trustdb(); - validate_keys (1); -} - -void -revalidation_mark (void) -{ - init_trustdb(); - /* we simply set the time for the next check to 1 (far back in 1970) - * so that a --update-trustdb will be scheduled */ - if (tdbio_write_nextcheck (1)) - do_sync (); - pending_check_trustdb = 1; -} - - -/*********************************************** - *********** Ownertrust et al. **************** - ***********************************************/ - -static int -read_trust_record (PKT_public_key *pk, TRUSTREC *rec) -{ - int rc; - - init_trustdb(); - rc = tdbio_search_trust_bypk (pk, rec); - if (rc == -1) - return -1; /* no record yet */ - if (rc) - { - log_error ("trustdb: searching trust record failed: %s\n", - g10_errstr (rc)); - return rc; - } - - if (rec->rectype != RECTYPE_TRUST) - { - log_error ("trustdb: record %lu is not a trust record\n", - rec->recnum); - return G10ERR_TRUSTDB; - } - - return 0; -} - - -/**************** - * Return the assigned ownertrust value for the given public key. - * The key should be the primary key. - */ -unsigned int -get_ownertrust ( PKT_public_key *pk) -{ - TRUSTREC rec; - int rc; - - rc = read_trust_record (pk, &rec); - if (rc == -1) - return TRUST_UNKNOWN; /* no record yet */ - if (rc) - { - tdbio_invalid (); - return rc; /* actually never reached */ - } - - return rec.r.trust.ownertrust; -} - -/* - * Same as get_ownertrust but return a trust letter instead of an value. - */ -int -get_ownertrust_info (PKT_public_key *pk) -{ - unsigned int otrust; - int c; - - otrust = get_ownertrust (pk); - c = trust_letter( (otrust & TRUST_MASK) ); - if( !c ) - c = '?'; - return c; -} - -/* - * Set the trust value of the given public key to the new value. - * The key should be a primary one. - */ -void -update_ownertrust (PKT_public_key *pk, unsigned int new_trust ) -{ - TRUSTREC rec; - int rc; - - rc = read_trust_record (pk, &rec); - if (!rc) - { - if (DBG_TRUST) - log_debug ("update ownertrust from %u to %u\n", - (unsigned int)rec.r.trust.ownertrust, new_trust ); - if (rec.r.trust.ownertrust != new_trust) - { - rec.r.trust.ownertrust = new_trust; - write_record( &rec ); - revalidation_mark (); - do_sync (); - } - } - else if (rc == -1) - { /* no record yet - create a new one */ - size_t dummy; - - if (DBG_TRUST) - log_debug ("insert ownertrust %u\n", new_trust ); - - memset (&rec, 0, sizeof rec); - rec.recnum = tdbio_new_recnum (); - rec.rectype = RECTYPE_TRUST; - fingerprint_from_pk (pk, rec.r.trust.fingerprint, &dummy); - rec.r.trust.ownertrust = new_trust; - write_record (&rec); - revalidation_mark (); - do_sync (); - rc = 0; - } - else - { - tdbio_invalid (); - } -} - -/* Clear the ownertrust value. Return true if a changed actually happend. */ -int -clear_ownertrust (PKT_public_key *pk) -{ - TRUSTREC rec; - int rc; - - rc = read_trust_record (pk, &rec); - if (!rc) - { - if (DBG_TRUST) - log_debug ("clearing ownertrust (old value %u)\n", - (unsigned int)rec.r.trust.ownertrust); - if (rec.r.trust.ownertrust) - { - rec.r.trust.ownertrust = 0; - write_record( &rec ); - revalidation_mark (); - do_sync (); - return 1; - } - } - else if (rc != -1) - { - tdbio_invalid (); - } - return 0; -} - -/* - * Note: Caller has to do a sync - */ -static void -update_validity (PKT_public_key *pk, const byte *namehash, - int depth, int validity) -{ - TRUSTREC trec, vrec; - int rc; - ulong recno; - - rc = read_trust_record (pk, &trec); - if (rc && rc != -1) - { - tdbio_invalid (); - return; - } - if (rc == -1) /* no record yet - create a new one */ - { - size_t dummy; - - rc = 0; - memset (&trec, 0, sizeof trec); - trec.recnum = tdbio_new_recnum (); - trec.rectype = RECTYPE_TRUST; - fingerprint_from_pk (pk, trec.r.trust.fingerprint, &dummy); - trec.r.trust.ownertrust = 0; - } - - /* locate an existing one */ - recno = trec.r.trust.validlist; - while (recno) - { - read_record (recno, &vrec, RECTYPE_VALID); - if ( !memcmp (vrec.r.valid.namehash, namehash, 20) ) - break; - recno = vrec.r.valid.next; - } - - if (!recno) /* insert a new validity record */ - { - memset (&vrec, 0, sizeof vrec); - vrec.recnum = tdbio_new_recnum (); - vrec.rectype = RECTYPE_VALID; - memcpy (vrec.r.valid.namehash, namehash, 20); - vrec.r.valid.next = trec.r.trust.validlist; - } - vrec.r.valid.validity = validity; - write_record (&vrec); - trec.r.trust.depth = depth; - trec.r.trust.validlist = vrec.recnum; - write_record (&trec); -} - - -/* reset validity for all user IDs. Caller must sync. */ -static int -clear_validity (PKT_public_key *pk) -{ - TRUSTREC trec, vrec; - int rc; - ulong recno; - int any = 0; - - rc = read_trust_record (pk, &trec); - if (rc && rc != -1) - { - tdbio_invalid (); - return 0; - } - if (rc == -1) /* no record yet - no need to clerar it then ;-) */ - return 0; - - /* reset validity for all user IDs */ - recno = trec.r.trust.validlist; - while (recno) - { - read_record (recno, &vrec, RECTYPE_VALID); - if ((vrec.r.valid.validity & TRUST_MASK)) - { - vrec.r.valid.validity &= ~TRUST_MASK; - write_record (&vrec); - any = 1; - } - recno = vrec.r.valid.next; - } - - return any; -} - - - -/*********************************************** - ********* Query trustdb values ************** - ***********************************************/ - -/* - * Return the validity information for PK. If the namehash is not - * NULL, the validity of the corresponsing user ID is returned, - * otherwise, a reasonable value for the entire key is returned. - */ -unsigned int -get_validity (PKT_public_key *pk, const byte *namehash) -{ - static int did_nextcheck; - TRUSTREC trec, vrec; - int rc; - ulong recno; - unsigned int validity; - u32 kid[2]; - PKT_public_key *main_pk; - - init_trustdb (); - if (!did_nextcheck) - { - ulong scheduled; - - did_nextcheck = 1; - scheduled = tdbio_read_nextcheck (); - if (scheduled && scheduled <= make_timestamp ()) - { - if (opt.no_auto_check_trustdb) - { - pending_check_trustdb = 1; - log_info ("please do a --check-trustdb\n"); - } - else - { - log_info (_("checking the trustdb\n")); - validate_keys (0); - } - } - } - - keyid_from_pk (pk, kid); - if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1]) - { /* this is a subkey - get the mainkey */ - main_pk = m_alloc_clear (sizeof *main_pk); - rc = get_pubkey (main_pk, pk->main_keyid); - if (rc) - { - log_error ("error getting main key %08lX of subkey %08lX: %s\n", - (ulong)pk->main_keyid[1], (ulong)kid[1], g10_errstr(rc)); - validity = TRUST_UNKNOWN; - goto leave; - } - } - else - main_pk = pk; - - rc = read_trust_record (main_pk, &trec); - if (rc && rc != -1) - { - tdbio_invalid (); - return 0; - } - if (rc == -1) /* no record found */ - { - validity = TRUST_UNKNOWN; - goto leave; - } - - /* loop over all user IDs */ - recno = trec.r.trust.validlist; - validity = 0; - while (recno) - { - read_record (recno, &vrec, RECTYPE_VALID); - if ( validity < (vrec.r.valid.validity & TRUST_MASK) ) - validity = (vrec.r.valid.validity & TRUST_MASK); - if ( namehash && !memcmp (vrec.r.valid.namehash, namehash, 20) ) - break; - recno = vrec.r.valid.next; - } - - if (recno) /* okay, use the user ID associated one */ - validity = (vrec.r.valid.validity & TRUST_MASK); - - if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) ) - validity |= TRUST_FLAG_DISABLED; - - leave: - /* set some flags direct from the key */ - if (main_pk->is_revoked) - validity |= TRUST_FLAG_REVOKED; - if (main_pk != pk && pk->is_revoked) - validity |= TRUST_FLAG_SUB_REVOKED; - /* Note: expiration is a trust value and not a flag - don't know why - * I initially designed it that way */ - if (main_pk->has_expired || pk->has_expired) - validity = (validity & ~TRUST_MASK) | TRUST_EXPIRED; - - if (pending_check_trustdb) - validity |= TRUST_FLAG_PENDING_CHECK; - - if (main_pk != pk) - free_public_key (main_pk); - return validity; -} - - -int -get_validity_info (PKT_public_key *pk, const byte *namehash) -{ - int trustlevel; - int c; - - trustlevel = get_validity (pk, namehash); - if( trustlevel & TRUST_FLAG_DISABLED ) - return 'd'; - if( trustlevel & TRUST_FLAG_REVOKED ) - return 'r'; - c = trust_letter ( (trustlevel & TRUST_MASK) ); - if( !c ) - c = '?'; - return c; -} - - - - -void -list_trust_path( const char *username ) -{ -} - - - - -/**************** - * Enumerate all keys, which are needed to build all trust paths for - * the given key. This function does not return the key itself or - * the ultimate key (the last point in cerificate chain). Only - * certificate chains which ends up at an ultimately trusted key - * are listed. If ownertrust or validity is not NULL, the corresponding - * value for the returned LID is also returned in these variable(s). - * - * 1) create a void pointer and initialize it to NULL - * 2) pass this void pointer by reference to this function. - * Set lid to the key you want to enumerate and pass it by reference. - * 3) call this function as long as it does not return -1 - * to indicate EOF. LID does contain the next key used to build the web - * 4) Always call this function a last time with LID set to NULL, - * so that it can free its context. - * - * Returns: -1 on EOF or the level of the returned LID - */ -int -enum_cert_paths( void **context, ulong *lid, - unsigned *ownertrust, unsigned *validity ) -{ - return -1; -} - - -/**************** - * Print the current path - */ -void -enum_cert_paths_print( void **context, FILE *fp, - int refresh, ulong selected_lid ) -{ - return; -} - - - -/**************************************** - *********** NEW NEW NEW **************** - ****************************************/ - -static int -ask_ownertrust (u32 *kid) -{ - PKT_public_key *pk; - int rc; - int ot; - - pk = m_alloc_clear (sizeof *pk); - rc = get_pubkey (pk, kid); - if (rc) - { - log_error (_("public key %08lX not found: %s\n"), - (ulong)kid[1], g10_errstr(rc) ); - return TRUST_UNKNOWN; - } - - ot=edit_ownertrust(pk,0); - if(ot>0) - ot = get_ownertrust (pk); - else if(ot==0) - ot = TRUST_UNDEFINED; - else - ot = -1; /* quit */ - free_public_key( pk ); - return ot; -} - - -static void -mark_keyblock_seen (KeyHashTable tbl, KBNODE node) -{ - for ( ;node; node = node->next ) - if (node->pkt->pkttype == PKT_PUBLIC_KEY - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) - { - u32 aki[2]; - - keyid_from_pk (node->pkt->pkt.public_key, aki); - add_key_hash_table (tbl, aki); - } -} - - - -static void -dump_key_array (int depth, struct key_array *keys) -{ - struct key_array *kar; - - for (kar=keys; kar->keyblock; kar++) - { - KBNODE node = kar->keyblock; - u32 kid[2]; - - keyid_from_pk(node->pkt->pkt.public_key, kid); - printf ("%d:%08lX%08lX:K::%c::::\n", - depth, (ulong)kid[0], (ulong)kid[1], '?'); - - for (; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID) - { - int len = node->pkt->pkt.user_id->len; - - if (len > 30) - len = 30; - printf ("%d:%08lX%08lX:U:::%c:::", - depth, (ulong)kid[0], (ulong)kid[1], - (node->flag & 4)? 'f': - (node->flag & 2)? 'm': - (node->flag & 1)? 'q':'-'); - print_string (stdout, node->pkt->pkt.user_id->name, len, ':'); - putchar (':'); - putchar ('\n'); - } - } - } -} - - -static void -store_validation_status (int depth, KBNODE keyblock) -{ - KBNODE node; - byte namehash[20]; - int status; - int any = 0; - - for (node=keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID) - { - PKT_user_id *uid = node->pkt->pkt.user_id; - - if (node->flag & 4) - status = TRUST_FULLY; - else if (node->flag & 2) - status = TRUST_MARGINAL; - else if (node->flag & 1) - status = TRUST_UNDEFINED; - else - status = 0; - - if (status) - { - if( uid->attrib_data ) - rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len); - else - rmd160_hash_buffer (namehash, uid->name, uid->len ); - - update_validity (keyblock->pkt->pkt.public_key, - namehash, depth, status); - any = 1; - } - } - } - - if (any) - do_sync (); -} - -/* - * check whether the signature sig is in the klist k - */ -static struct key_item * -is_in_klist (struct key_item *k, PKT_signature *sig) -{ - for (; k; k = k->next) - { - if (k->kid[0] == sig->keyid[0] && k->kid[1] == sig->keyid[1]) - return k; - } - return NULL; -} - -/* - * Mark the signature of the given UID which are used to certify it. - * To do this, we first revmove all signatures which are not valid and - * from the remain ones we look for the latest one. If this is not a - * certification revocation signature we mark the signature by setting - * node flag bit 8. Note that flag bits 9 and 10 are used for internal - * purposes. - */ -static void -mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, - u32 *main_kid, struct key_item *klist, - u32 curtime, u32 *next_expire) -{ - KBNODE node; - PKT_signature *sig; - - /* first check all signatures */ - for (node=uidnode->next; node; node = node->next) - { - node->flag &= ~(1<<8 | 1<<9 | 1<<10); - if (node->pkt->pkttype == PKT_USER_ID - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) - break; /* ready */ - if (node->pkt->pkttype != PKT_SIGNATURE) - continue; - - sig = node->pkt->pkt.signature; - if (sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1]) - continue; /* ignore self-signatures */ - if (!IS_UID_SIG(sig) && !IS_UID_REV(sig)) - continue; /* we only look at these signature classes */ - if (!is_in_klist (klist, sig)) - continue; /* no need to check it then */ - if (check_key_signature (keyblock, node, NULL)) - continue; /* ignore invalid signatures */ - node->flag |= 1<<9; - } - /* reset the remaining flags */ - for (; node; node = node->next) - node->flag &= ~(1<<8 | 1<<9 | 1 << 10); - - /* kbnode flag usage: bit 9 is here set for signatures to consider, - * bit 10 will be set by the loop to keep track of keyIDs already - * processed, bit 8 will be set for the usable signatures */ - - /* for each cert figure out the latest valid one */ - for (node=uidnode->next; node; node = node->next) - { - KBNODE n, signode; - u32 kid[2]; - u32 sigdate; - - if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) - break; - if ( !(node->flag & (1<<9)) ) - continue; /* not a node to look at */ - if ( (node->flag & (1<<10)) ) - continue; /* signature with a keyID already processed */ - node->flag |= (1<<10); /* mark this node as processed */ - sig = node->pkt->pkt.signature; - signode = node; - sigdate = sig->timestamp; - kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1]; - for (n=uidnode->next; n; n = n->next) - { - if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY) - break; - if ( !(n->flag & (1<<9)) ) - continue; - if ( (n->flag & (1<<10)) ) - continue; /* shortcut already processed signatures */ - sig = n->pkt->pkt.signature; - if (kid[0] != sig->keyid[0] || kid[1] != sig->keyid[1]) - continue; - n->flag |= (1<<10); /* mark this node as processed */ - - /* If signode is nonrevocable and unexpired and n isn't, - then take signode (skip). It doesn't matter which is - older: if signode was older then we don't want to take n - as signode is nonrevocable. If n was older then we're - automatically fine. */ - - if(((IS_UID_SIG(signode->pkt->pkt.signature) && - !signode->pkt->pkt.signature->flags.revocable && - (signode->pkt->pkt.signature->expiredate==0 || - signode->pkt->pkt.signature->expiredate>curtime))) && - (!(IS_UID_SIG(n->pkt->pkt.signature) && - !n->pkt->pkt.signature->flags.revocable && - (n->pkt->pkt.signature->expiredate==0 || - n->pkt->pkt.signature->expiredate>curtime)))) - continue; - - /* If n is nonrevocable and unexpired and signode isn't, - then take n. Again, it doesn't matter which is older: if - n was older then we don't want to take signode as n is - nonrevocable. If signode was older then we're - automatically fine. */ - - if((!(IS_UID_SIG(signode->pkt->pkt.signature) && - !signode->pkt->pkt.signature->flags.revocable && - (signode->pkt->pkt.signature->expiredate==0 || - signode->pkt->pkt.signature->expiredate>curtime))) && - ((IS_UID_SIG(n->pkt->pkt.signature) && - !n->pkt->pkt.signature->flags.revocable && - (n->pkt->pkt.signature->expiredate==0 || - n->pkt->pkt.signature->expiredate>curtime)))) - { - signode = n; - sigdate = sig->timestamp; - continue; - } - - /* At this point, if it's newer, it goes in as the only - remaining possibilities are signode and n are both either - revocable or expired or both nonrevocable and unexpired. - If the timestamps are equal take the later ordered - packet, presuming that the key packets are hopefully in - their original order. */ - - if (sig->timestamp >= sigdate) - { - signode = n; - sigdate = sig->timestamp; - } - } - sig = signode->pkt->pkt.signature; - if (IS_UID_SIG (sig)) - { /* this seems to be a usable one which is not revoked. - * Just need to check whether there is an expiration time, - * We do the expired certification after finding a suitable - * certification, the assumption is that a signator does not - * want that after the expiration of his certificate the - * system falls back to an older certification which has a - * different expiration time */ - const byte *p; - u32 expire; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL ); - expire = p? sig->timestamp + buffer_to_u32(p) : 0; - - if (expire==0 || expire > curtime ) - { - signode->flag |= (1<<8); /* yeah, found a good cert */ - if (expire && expire < *next_expire) - *next_expire = expire; - } - } - } -} - - -/* - * Return true if the key is signed by one of the keys in the given - * key ID list. User IDs with a valid signature are marked by node - * flags as follows: - * flag bit 0: There is at least one signature - * 1: There is marginal confidence that this is a legitimate uid - * 2: There is full confidence that this is a legitimate uid. - * 8: Used for internal purposes. - * 9: Ditto (in mark_usable_uid_certs()) - * 10: Ditto (ditto) - * This function assumes that all kbnode flags are cleared on entry. - */ -static int -validate_one_keyblock (KBNODE kb, struct key_item *klist, - u32 curtime, u32 *next_expire) -{ - struct key_item *kr; - KBNODE node, uidnode=NULL; - PKT_public_key *pk = kb->pkt->pkt.public_key; - u32 main_kid[2]; - int issigned=0, any_signed = 0, fully_count =0, marginal_count = 0; - - keyid_from_pk(pk, main_kid); - for (node=kb; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID) - { - if (uidnode && issigned) - { - if (fully_count >= opt.completes_needed - || marginal_count >= opt.marginals_needed ) - uidnode->flag |= 4; - else if (fully_count || marginal_count) - uidnode->flag |= 2; - uidnode->flag |= 1; - any_signed = 1; - } - uidnode = node; - issigned = 0; - fully_count = marginal_count = 0; - mark_usable_uid_certs (kb, uidnode, main_kid, klist, - curtime, next_expire); - } - else if (node->pkt->pkttype == PKT_SIGNATURE - && (node->flag & (1<<8)) ) - { - PKT_signature *sig = node->pkt->pkt.signature; - - kr = is_in_klist (klist, sig); - if (kr) - { - if (kr->ownertrust == TRUST_ULTIMATE) - fully_count = opt.completes_needed; - else if (kr->ownertrust == TRUST_FULLY) - fully_count++; - else if (kr->ownertrust == TRUST_MARGINAL) - marginal_count++; - issigned = 1; - } - } - } - - if (uidnode && issigned) - { - if (fully_count >= opt.completes_needed - || marginal_count >= opt.marginals_needed ) - uidnode->flag |= 4; - else if (fully_count || marginal_count) - uidnode->flag |= 2; - uidnode->flag |= 1; - any_signed = 1; - } - - return any_signed; -} - - -static int -search_skipfnc (void *opaque, u32 *kid) -{ - return test_key_hash_table ((KeyHashTable)opaque, kid); -} - - -/* - * Scan all keys and return a key_array of all suitable keys from - * kllist. The caller has to pass keydb handle so that we don't use - * to create our own. Returns either a key_array or NULL in case of - * an error. No results found are indicated by an empty array. - * Caller hast to release the returned array. - */ -static struct key_array * -validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited, - struct key_item *klist, u32 curtime, u32 *next_expire) -{ - KBNODE keyblock = NULL; - struct key_array *keys = NULL; - size_t nkeys, maxkeys; - int rc; - KEYDB_SEARCH_DESC desc; - - maxkeys = 1000; - keys = m_alloc ((maxkeys+1) * sizeof *keys); - nkeys = 0; - - rc = keydb_search_reset (hd); - if (rc) - { - log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); - m_free (keys); - return NULL; - } - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - desc.skipfnc = search_skipfnc; - desc.skipfncvalue = visited; - rc = keydb_search (hd, &desc, 1); - if (rc == -1) - { - keys[nkeys].keyblock = NULL; - return keys; - } - if (rc) - { - log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); - m_free (keys); - return NULL; - } - - desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */ - do - { - PKT_public_key *pk; - - rc = keydb_get_keyblock (hd, &keyblock); - if (rc) - { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - m_free (keys); - return NULL; - } - - if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY) - { - log_debug ("ooops: invalid pkttype %d encountered\n", - keyblock->pkt->pkttype); - dump_kbnode (keyblock); - release_kbnode(keyblock); - continue; - } - - /* prepare the keyblock for further processing */ - merge_keys_and_selfsig (keyblock); - clear_kbnode_flags (keyblock); - pk = keyblock->pkt->pkt.public_key; - if (pk->has_expired || pk->is_revoked) - { - /* it does not make sense to look further at those keys */ - mark_keyblock_seen (visited, keyblock); - } - else if (validate_one_keyblock (keyblock, klist, curtime, next_expire)) - { - if (pk->expiredate && pk->expiredate >= curtime - && pk->expiredate < *next_expire) - *next_expire = pk->expiredate; - - if (nkeys == maxkeys) { - maxkeys += 1000; - keys = m_realloc (keys, (maxkeys+1) * sizeof *keys); - } - keys[nkeys++].keyblock = keyblock; - /* this key is signed - don't check it again */ - mark_keyblock_seen (visited, keyblock); - keyblock = NULL; - } - - release_kbnode (keyblock); - keyblock = NULL; - } - while ( !(rc = keydb_search (hd, &desc, 1)) ); - if (rc && rc != -1) - { - log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); - m_free (keys); - return NULL; - } - - keys[nkeys].keyblock = NULL; - return keys; -} - - -static void -reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited) -{ - int rc; - KBNODE keyblock = NULL; - KEYDB_SEARCH_DESC desc; - int count = 0, nreset = 0; - - rc = keydb_search_reset (hd); - if (rc) - { - log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); - return; - } - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - desc.skipfnc = search_skipfnc; - desc.skipfncvalue = visited; - rc = keydb_search (hd, &desc, 1); - if (rc && rc != -1 ) - log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); - else if (!rc) - { - desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */ - do - { - rc = keydb_get_keyblock (hd, &keyblock); - if (rc) - { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - break; - } - count++; - - if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY) /* paranoid assertion*/ - { - nreset += clear_validity (keyblock->pkt->pkt.public_key); - release_kbnode (keyblock); - } - } - while ( !(rc = keydb_search (hd, &desc, 1)) ); - if (rc && rc != -1) - log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); - } - if (opt.verbose) - log_info ("%d unconnected keys (%d trust records cleared)\n", - count, nreset); - do_sync (); -} - - -/* - * Run the key validation procedure. - * - * This works this way: - * Step 1: Find all ultimately trusted keys (UTK). - * mark them all as seen and put them into klist. - * Step 2: loop max_cert_times - * Step 3: if OWNERTRUST of any key in klist is undefined - * ask user to assign ownertrust - * Step 4: Loop over all keys in the keyDB which are not marked seen - * Step 5: if key is revoked or expired - * mark key as seen - * continue loop at Step 4 - * Step 6: For each user ID of that key signed by a key in klist - * Calculate validity by counting trusted signatures. - * Set validity of user ID - * Step 7: If any signed user ID was found - * mark key as seen - * End Loop - * Step 8: Build a new klist from all fully trusted keys from step 6 - * End Loop - * Ready - * - */ -static int -validate_keys (int interactive) -{ - int rc = 0; - int quit=0; - struct key_item *klist = NULL; - struct key_item *k; - struct key_array *keys = NULL; - struct key_array *kar; - KEYDB_HANDLE kdb = NULL; - KBNODE node; - int depth; - int key_count; - int ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate; - KeyHashTable visited; - u32 start_time, next_expire; - - start_time = make_timestamp (); - next_expire = 0xffffffff; /* set next expire to the year 2106 */ - visited = new_key_hash_table (); - /* Fixme: Instead of always building a UTK list, we could just build it - * here when needed */ - if (!utk_list) - { - log_info ("no ultimately trusted keys found\n"); - goto leave; - } - - - /* mark all UTKs as visited and set validity to ultimate */ - for (k=utk_list; k; k = k->next) - { - KBNODE keyblock; - PKT_public_key *pk; - - keyblock = get_pubkeyblock (k->kid); - if (!keyblock) - { - log_error (_("public key of ultimately" - " trusted key %08lX not found\n"), (ulong)k->kid[1]); - continue; - } - mark_keyblock_seen (visited, keyblock); - pk = keyblock->pkt->pkt.public_key; - for (node=keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID) - { - byte namehash[20]; - PKT_user_id *uid = node->pkt->pkt.user_id; - - if( uid->attrib_data ) - rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len); - else - rmd160_hash_buffer (namehash, uid->name, uid->len ); - update_validity (pk, namehash, 0, TRUST_ULTIMATE); - } - } - if ( pk->expiredate && pk->expiredate >= start_time - && pk->expiredate < next_expire) - next_expire = pk->expiredate; - - release_kbnode (keyblock); - do_sync (); - } - - - klist = utk_list; - kdb = keydb_new (0); - - for (depth=0; depth < opt.max_cert_depth; depth++) - { - /* See whether we should assign ownertrust values to the keys in - utk_list. */ - ot_unknown = ot_undefined = ot_never = 0; - ot_marginal = ot_full = ot_ultimate = 0; - for (k=klist; k; k = k->next) - { - if (interactive && k->ownertrust == TRUST_UNKNOWN) - k->ownertrust = ask_ownertrust (k->kid); - if (k->ownertrust == -1) - { - quit=1; - goto leave; - } - else if (k->ownertrust == TRUST_UNKNOWN) - ot_unknown++; - else if (k->ownertrust == TRUST_UNDEFINED) - ot_undefined++; - else if (k->ownertrust == TRUST_NEVER) - ot_never++; - else if (k->ownertrust == TRUST_MARGINAL) - ot_marginal++; - else if (k->ownertrust == TRUST_FULLY) - ot_full++; - else if (k->ownertrust == TRUST_ULTIMATE) - ot_ultimate++; - } - - /* Find all keys which are signed by a key in kdlist */ - keys = validate_key_list (kdb, visited, klist, start_time, &next_expire); - if (!keys) - { - log_error ("validate_key_list failed\n"); - rc = G10ERR_GENERAL; - goto leave; - } - - - for (key_count=0, kar=keys; kar->keyblock; kar++, key_count++) - ; - - /* Store the calculated valididation status somewhere */ - if (opt.verbose > 1) - dump_key_array (depth, keys); - - log_info (_("checking at depth %d signed=%d" - " ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n"), - depth, key_count, ot_unknown, ot_undefined, - ot_never, ot_marginal, ot_full, ot_ultimate ); - - for (kar=keys; kar->keyblock; kar++) - store_validation_status (depth, kar->keyblock); - - /* Build a new kdlist from all fully valid keys in KEYS */ - if (klist != utk_list) - release_key_items (klist); - klist = NULL; - for (kar=keys; kar->keyblock; kar++) - { - for (node=kar->keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID && (node->flag & 4)) - { - k = new_key_item (); - keyid_from_pk (kar->keyblock->pkt->pkt.public_key, k->kid); - k->ownertrust = get_ownertrust (kar->keyblock - ->pkt->pkt.public_key); - k->next = klist; - klist = k; - break; - } - } - } - release_key_array (keys); - keys = NULL; - if (!klist) - break; /* no need to dive in deeper */ - } - - reset_unconnected_keys (kdb, visited); - - leave: - keydb_release (kdb); - release_key_array (keys); - release_key_items (klist); - release_key_hash_table (visited); - if (!rc && !quit) /* mark trustDB as checked */ - { - if (next_expire == 0xffffffff || next_expire < start_time ) - tdbio_write_nextcheck (0); - else - { - tdbio_write_nextcheck (next_expire); - log_info (_("next trustdb check due at %s\n"), - strtimestamp (next_expire)); - } - do_sync (); - pending_check_trustdb = 0; - } - return rc; -} - - diff --git a/g10/trustdb.h b/g10/trustdb.h deleted file mode 100644 index c94a2daa1..000000000 --- a/g10/trustdb.h +++ /dev/null @@ -1,76 +0,0 @@ -/* trustdb.h - Trust database - * 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 - */ - -#ifndef G10_TRUSTDB_H -#define G10_TRUSTDB_H - - -/* Trust values must be sorted in ascending order */ -#define TRUST_MASK 15 -#define TRUST_UNKNOWN 0 /* o: not yet calculated/assigned */ -#define TRUST_EXPIRED 1 /* e: calculation may be invalid */ -#define TRUST_UNDEFINED 2 /* q: not enough information for calculation */ -#define TRUST_NEVER 3 /* n: never trust this pubkey */ -#define TRUST_MARGINAL 4 /* m: marginally trusted */ -#define TRUST_FULLY 5 /* f: fully trusted */ -#define TRUST_ULTIMATE 6 /* u: ultimately trusted */ -/* trust values not covered by the mask */ -#define TRUST_FLAG_REVOKED 32 /* r: revoked */ -#define TRUST_FLAG_SUB_REVOKED 64 /* r: revoked but for subkeys */ -#define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */ -#define TRUST_FLAG_PENDING_CHECK 256 /* a check-trustdb is pending */ - -/*-- trustdb.c --*/ -void register_trusted_key( const char *string ); -void check_trustdb (void); -void update_trustdb (void); -int setup_trustdb( int level, const char *dbname ); -void init_trustdb( void ); -void sync_trustdb( void ); - -int trust_letter( unsigned value ); - -void revalidation_mark (void); - -unsigned int get_validity (PKT_public_key *pk, const byte *namehash); -int get_validity_info (PKT_public_key *pk, const byte *namehash); - -void list_trust_path( const char *username ); - -int enum_cert_paths( void **context, ulong *lid, - unsigned *ownertrust, unsigned *validity ); -void enum_cert_paths_print( void **context, FILE *fp, - int refresh, ulong selected_lid ); - -unsigned int get_ownertrust (PKT_public_key *pk); -int get_ownertrust_info (PKT_public_key *pk); -void update_ownertrust (PKT_public_key *pk, unsigned int new_trust ); -int clear_ownertrust (PKT_public_key *pk); - - -/*-- tdbdump.c --*/ -void list_trustdb(const char *username); -void export_ownertrust(void); -void import_ownertrust(const char *fname); - -/*-- pkclist.c --*/ -int edit_ownertrust (PKT_public_key *pk, int mode ); - -#endif /*G10_TRUSTDB_H*/ diff --git a/g10/verify.c b/g10/verify.c deleted file mode 100644 index 7ab20c140..000000000 --- a/g10/verify.c +++ /dev/null @@ -1,189 +0,0 @@ -/* verify.c - verify signed data - * 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 -#include -#include -#include -#include -#include -#include /* for isatty() */ - -#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 "filter.h" -#include "ttyio.h" -#include "i18n.h" - - - -/**************** - * Assume that the input is a signature and verify it without - * generating any output. With no arguments, the signature packet - * is read from stdin (it may be a detached signature when not - * used in batch mode). If only a sigfile is given, it may be a complete - * signature or a detached signature in which case the signed stuff - * is expected from stdin. With more than 1 argument, the first should - * be a detached signature and the remaining files are the signed stuff. - */ - -int -verify_signatures( int nfiles, char **files ) -{ - IOBUF fp; - armor_filter_context_t afx; - const char *sigfile; - int i, rc; - STRLIST sl; - - memset( &afx, 0, sizeof afx); - /* decide whether we should handle a detached or a normal signature, - * which is needed so that the code later can hash the correct data and - * not have a normal signature act as detached signature and ignoring the - * indended signed material from the 2nd file or stdin. - * 1. gpg - -%%interface: Command line - -%%updated: 1 Jun 2001 - -%%keywords: PGP, security, decryption, encryption, digital signatures - -%%programs: - -%%GNU: yes - -%%web-page: http://www.gnupg.org/ - -%%support: Paid extension/consulting from http://www.g10code.com - -%%doc: English user manual available from: -http://www.gnupg.org/gph/index.html; Spanish user manual available from: -http://www.gnupg.org/gph/index.html; English HOWTO available from -http://www.dewinter.com/gnupg_howto/english/; French HOWTO available -from http://www.gnupg.org/howtos/fr/; German HOWTO available from -http://www.gnupg.org/howtos/de/; Spanish HOWTO available from -http://www.dewinter.com/gnupg_howto/spanish. - -%%developers: Matthew Skala, Michael Roth, Niklas Hernaeus, Remi -Guyomarch, Werner Koch . - -%%contributors: J. Michael Ashley - -%%sponsors: German Federal Ministry of Economics and Technology - -%%source: ftp://ftp.gnupg.org/gcrypt/gnupg - -%%debian: http://www.debian.org/Packages/stable/non-us/gnupg.html - -%%redhat: http://www.megaloman.com/~hany/RPM/gnupg.html - -%%repository: See http://www.gnupg.org/cvs-access.html - -%%related: shred - -%%source-language: C - -%%supported-languages: - -%%use-requirements: - -%%build-prerequisites: - -%%weak-prerequisites: - -%%source-prerequisites: - -%%version: 1.0.6 stable released on 29 May 2001 - -%%announce-list: announce@gnupg.org - -%%announce-news: - -%%help-list: gnupg-users@gnupg.org - -%%help-news: - -%%dev-list: gnupg-devel@gnupg.org - -%%dev-news: - -%%bug-list: bug-gnupg@gnupg.org diff --git a/include/ChangeLog b/include/ChangeLog deleted file mode 100644 index 748778a20..000000000 --- a/include/ChangeLog +++ /dev/null @@ -1,310 +0,0 @@ -2002-10-14 David Shaw - - * keyserver.h: Go to KEYSERVER_PROTO_VERSION 1. - -2002-10-08 David Shaw - - * keyserver.h: Add new error code KEYSERVER_UNREACHABLE. - -2002-10-03 David Shaw - - * util.h: Add new log_warning logger command which can be switched - between log_info and log_error via log_set_strict. - -2002-09-24 David Shaw - - * keyserver.h: Add some new error codes for better GPA support. - -2002-09-10 Werner Koch - - * mpi.h (mpi_is_protected, mpi_set_protect_flag) - (mpi_clear_protect_flag): Removed. - (mpi_get_nbit_info, mpi_set_nbit_info): Removed. - -2002-08-13 David Shaw - - * cipher.h: Add AES aliases for RIJNDAEL algo numbers. - -2002-08-07 David Shaw - - * cipher.h: Add md_algo_present(). - -2002-08-06 Stefan Bellon - - * util.h [__riscos__]: Added riscos_getchar(). - -2002-06-21 Stefan Bellon - - * util.h [__riscos__]: Further moving away of RISC OS specific - stuff from general code. - -2002-06-20 Stefan Bellon - - * util.h [__riscos__]: Added riscos_set_filetype(). - -2002-06-14 David Shaw - - * util.h: Add pop_strlist() from strgutil.c. - -2002-06-07 Stefan Bellon - - * util.h [__riscos__]: RISC OS needs strings.h for strcasecmp() - and strncasecmp(). - -2002-05-22 Werner Koch - - * util.h: Add strncasecmp. Removed stricmp and memicmp. - -2002-05-10 Stefan Bellon - - * mpi.h: New function mpi_debug_alloc_like for M_DEBUG. - - * util.h [__riscos__]: Make use of __func__ that later - Norcroft compiler provides. - - * memory.h: Fixed wrong definition of m_alloc_secure_clear. - -2002-04-23 David Shaw - - * util.h: New function answer_is_yes_no_default() to give a - default answer. - -2002-04-22 Stefan Bellon - - * util.h [__riscos__]: Removed riscos_open, riscos_fopen and - riscos_fstat as those special versions aren't needed anymore. - -2002-02-19 David Shaw - - * keyserver.h: Add KEYSERVER_NOT_SUPPORTED for unsupported actions - (say, a keyserver that has no way to search, or a readonly - keyserver that has no way to add). - -2002-01-02 Stefan Bellon - - * util.h [__riscos__]: Updated prototype list. - - * types.h [__riscos__]: Changed comment wording. - -2001-12-27 David Shaw - - * KEYSERVER_SCHEME_NOT_FOUND should be 127 to match the POSIX - system() (via /bin/sh) way of signaling this. - - * Added G10ERR_KEYSERVER - -2001-12-27 Werner Koch - - * util.h [MINGW32]: Fixed name of include file. - -2001-12-22 Timo Schulz - - * util.h (is_file_compressed): New. - -2001-12-19 Werner Koch - - * util.h [CYGWIN32]: Allow this as an alias for MINGW32. Include - stdarg.h becuase we use the va_list type. By Disastry. - -2001-09-28 Werner Koch - - * cipher.h (PUBKEY_USAGE_CERT): New. - -2001-09-07 Werner Koch - - * util.h: Add strsep(). - -2001-08-30 Werner Koch - - * cipher.h (DEK): Added use_mdc. - -2001-08-24 Werner Koch - - * cipher.h (md_write): Made buf arg const. - -2001-08-20 Werner Koch - - * cipher.h (DEK): Added algo_info_printed; - - * util.h [__riscos__]: Added prototypes and made sure that we - never use __attribute__. - * cipher.h, iobuf.h, memory.h, mpi.h [__riscos__]: extern hack. - * i18n.h [__riscos__]: Use another include file - -2001-05-30 Werner Koch - - * ttyio.h (tty_printf): Add missing parenthesis for non gcc. - * http.h: Removed trailing comma to make old ccs happy. Both are - by Albert Chin. - -2001-05-25 Werner Koch - - * ttyio.h (tty_printf): Add printf attribute. - -2001-04-23 Werner Koch - - * http.h: New flag HTTP_FLAG_NO_SHUTDOWN. - -2001-04-13 Werner Koch - - * iobuf.h: Removed iobuf_fopen. - -2001-03-01 Werner Koch - - * errors.h (G10ERR_UNU_SECKEY,G10ERR_UNU_PUBKEY): New - -2000-11-30 Werner Koch - - * iobuf.h (iobuf_translate_file_handle): Add prototype. - -2000-11-11 Paul Eggert - - * iobuf.h (iobuf_get_filelength): Now returns off_t, not u32. - (struct iobuf_struct, iobuf_set_limit, - iobuf_tell, iobuf_seek): Use off_t, not ulong, for file offsets. - -2000-10-12 Werner Koch - - * mpi.h: Changed the way mpi_limb_t is defined. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch - - * iobuf.c (IOBUF_FILELENGTH_LIMIT): New. - -2000-03-14 14:03:43 Werner Koch (wk@habibti.openit.de) - - * types.h (HAVE_U64_TYPEDEF): Defined depending on configure test. - -Thu Jan 13 19:31:58 CET 2000 Werner Koch - - * types.h (HAVE_U64_TYPEDEF): Add a test for _LONGLONG which fixes - this long living SGI bug. Reported by Alec Habig. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch - - * iobuf.h (IOBUFCTRL_CANCEL): Nww. - -Mon Oct 4 21:23:04 CEST 1999 Werner Koch - - * errors.h (G10ERR_NOT_PROCESSED): New. - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch - - - * i18n.h: Add support for simple-gettext. - -Tue Jun 29 21:44:25 CEST 1999 Werner Koch - - - * util.h (stricmp): Use strcasecmp as replacement. - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch - - - * cipher.h (MD_HANDLE): Assigned a structure name. - -Fri Apr 9 12:26:25 CEST 1999 Werner Koch - - * cipher.h (BLOWFISH160): Removed. - -Tue Apr 6 19:58:12 CEST 1999 Werner Koch - - * cipher.h (DEK): increased max. key length to 32 bytes - - -Sat Feb 20 21:40:49 CET 1999 Werner Koch - - * g10lib.h: Removed file and changed all files that includes this. - -Tue Feb 16 14:10:02 CET 1999 Werner Koch - - * types.h (STRLIST): Add field flags. - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - * cipher.h (CIPHER_ALGO_TWOFISH): Chnaged ID to 10 and renamed - the old experimenatl algorithm to xx_OLD. - -Thu Jan 7 18:00:58 CET 1999 Werner Koch - - * cipher.h (MD_BUFFER_SIZE): Removed. - -Mon Dec 14 21:18:49 CET 1998 Werner Koch - - * types.h: fix for SUNPRO_C - -Tue Dec 8 13:15:16 CET 1998 Werner Koch - - * mpi.h (MPI): Changed the structure name to gcry_mpi and - changed all users. - -Tue Oct 20 11:40:00 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.h (iobuf_get_temp_buffer): New. - -Tue Oct 13 12:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.h (iobuf_get): Now uses .nofast - (iobuf_get2): Removed. - -Mon Sep 14 09:17:22 1998 Werner Koch (wk@(none)) - - * util.h (HAVE_ATEXIT): New. - (HAVE_RAISE): New. - -Mon Jul 6 10:41:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h (PUBKEY_USAGE_): New. - -Mon Jul 6 09:49:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.h (iobuf_set_error): New. - (iobuf_error): New. - -Sat Jun 13 17:31:32 1998 Werner Koch (wk@isil.d.shuttle.de) - - * g10lib.h: New as interface for the g10lib. - -Mon Jun 8 22:14:48 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h (CIPHER_ALGO_CAST5): Changed name from .. CAST - -Thu May 21 13:25:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h: removed ROT 5 and changed one id and add dummy - -Tue May 19 18:09:05 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h (DIGEST_ALGO_TIGER): Chnaged id from 101 to 6. - -Mon May 4 16:37:17 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h (PUBKEY_ALGO_ELGAMAL_E): New, with value of the - old one. - * (is_ELGAMAL, is_RSA): New macros - -Sun Apr 26 14:35:24 1998 Werner Koch (wk@isil.d.shuttle.de) - - * types.h: New type u64 - -Mon Mar 9 12:59:55 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h: Included dsa.h. - -Tue Mar 3 15:11:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * cipher.h (random.h): Add new header and move all relevalt - functions to this header. - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/include/cipher.h b/include/cipher.h deleted file mode 100644 index 5a8982244..000000000 --- a/include/cipher.h +++ /dev/null @@ -1,198 +0,0 @@ -/* cipher.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_CIPHER_H -#define G10_CIPHER_H - -#define DBG_CIPHER g10c_debug_mode - -#include "mpi.h" -#include "../cipher/random.h" - - -#define CIPHER_ALGO_NONE 0 -#define CIPHER_ALGO_IDEA 1 -#define CIPHER_ALGO_3DES 2 -#define CIPHER_ALGO_CAST5 3 -#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ -#define CIPHER_ALGO_SAFER_SK128 5 -#define CIPHER_ALGO_DES_SK 6 -#define CIPHER_ALGO_AES 7 -#define CIPHER_ALGO_AES192 8 -#define CIPHER_ALGO_AES256 9 -#define CIPHER_ALGO_RIJNDAEL CIPHER_ALGO_AES -#define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192 -#define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256 -#define CIPHER_ALGO_TWOFISH 10 /* twofish 256 bit */ -#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */ -#define CIPHER_ALGO_TWOFISH_OLD 102 /* experimental: twofish 128 bit */ -#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ - -#define PUBKEY_ALGO_RSA 1 -#define PUBKEY_ALGO_RSA_E 2 /* RSA encrypt only */ -#define PUBKEY_ALGO_RSA_S 3 /* RSA sign only */ -#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not for v3)*/ -#define PUBKEY_ALGO_DSA 17 -#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ - -#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ -#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ -#define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/ - -#define DIGEST_ALGO_MD5 1 -#define DIGEST_ALGO_SHA1 2 -#define DIGEST_ALGO_RMD160 3 -#define DIGEST_ALGO_TIGER 6 - -#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ - || (a)==PUBKEY_ALGO_RSA_S ) -#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) - -typedef struct { - int algo; - int keylen; - int algo_info_printed; - int use_mdc; - byte key[32]; /* this is the largest used keylen (256 bit) */ -} DEK; - -struct cipher_handle_s; -typedef struct cipher_handle_s *CIPHER_HANDLE; - - -#define CIPHER_MODE_ECB 1 -#define CIPHER_MODE_CFB 2 -#define CIPHER_MODE_PHILS_CFB 3 -#define CIPHER_MODE_AUTO_CFB 4 -#define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */ -#define CIPHER_MODE_CBC 6 - -struct md_digest_list_s; - -struct gcry_md_context { - int secure; - FILE *debug; - int finalized; - struct md_digest_list_s *list; - int bufcount; - int bufsize; - byte buffer[1]; -}; - -typedef struct gcry_md_context *MD_HANDLE; - -#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 g10c_debug_mode; -EXTERN_UNLESS_MAIN_MODULE int g10_opt_verbose; -EXTERN_UNLESS_MAIN_MODULE const char *g10_opt_homedir; - - -/*-- dynload.c --*/ -void register_cipher_extension( const char *mainpgm, const char *fname ); - -/*-- md.c --*/ -int string_to_digest_algo( const char *string ); -const char * digest_algo_to_string( int algo ); -int check_digest_algo( int algo ); -MD_HANDLE md_open( int algo, int secure ); -void md_enable( MD_HANDLE hd, int algo ); -MD_HANDLE md_copy( MD_HANDLE a ); -void md_reset( MD_HANDLE a ); -void md_close(MD_HANDLE a); -void md_write( MD_HANDLE a, const byte *inbuf, size_t inlen); -void md_final(MD_HANDLE a); -byte *md_read( MD_HANDLE a, int algo ); -int md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen ); -int md_get_algo( MD_HANDLE a ); -int md_algo_present( MD_HANDLE a, int algo ); -int md_digest_length( int algo ); -const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); -void md_start_debug( MD_HANDLE a, const char *suffix ); -void md_stop_debug( MD_HANDLE a ); -#define md_is_secure(a) ((a)->secure) -#define md_putc(h,c) \ - do { \ - if( (h)->bufcount == (h)->bufsize ) \ - md_write( (h), NULL, 0 ); \ - (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ - } while(0) - -void rmd160_hash_buffer (char *outbuf, const char *buffer, size_t length); - - -/*-- cipher.c --*/ -int string_to_cipher_algo( const char *string ); -const char * cipher_algo_to_string( int algo ); -void disable_cipher_algo( int algo ); -int check_cipher_algo( int algo ); -unsigned cipher_get_keylen( int algo ); -unsigned cipher_get_blocksize( int algo ); -CIPHER_HANDLE cipher_open( int algo, int mode, int secure ); -void cipher_close( CIPHER_HANDLE c ); -int cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ); -void cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ); -void cipher_encrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); -void cipher_decrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); -void cipher_sync( CIPHER_HANDLE c ); - -/*-- pubkey.c --*/ -#define PUBKEY_MAX_NPKEY 4 -#define PUBKEY_MAX_NSKEY 6 -#define PUBKEY_MAX_NSIG 2 -#define PUBKEY_MAX_NENC 2 - -int string_to_pubkey_algo( const char *string ); -const char * pubkey_algo_to_string( int algo ); -void disable_pubkey_algo( int algo ); -int check_pubkey_algo( int algo ); -int check_pubkey_algo2( int algo, unsigned use ); -int pubkey_get_npkey( int algo ); -int pubkey_get_nskey( int algo ); -int pubkey_get_nsig( int algo ); -int pubkey_get_nenc( int algo ); -unsigned pubkey_nbits( int algo, MPI *pkey ); -int pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); -int pubkey_check_secret_key( int algo, MPI *skey ); -int pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); -int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); -int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); -int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaque ); - -/*-- smallprime.c --*/ -extern ushort small_prime_numbers[]; - -/*-- primegen.c --*/ -void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ); -MPI generate_secret_prime( unsigned nbits ); -MPI generate_public_prime( unsigned nbits ); -MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **factors ); - -/*-- elsewhere --*/ -void register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data ); -void register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data ); - -#endif /*G10_CIPHER_H*/ diff --git a/include/distfiles b/include/distfiles deleted file mode 100644 index fe9c41c7f..000000000 --- a/include/distfiles +++ /dev/null @@ -1,14 +0,0 @@ -cipher.h -errors.h -iobuf.h -memory.h -mpi.h -ttyio.h -types.h -util.h -i18n.h -host2net.h -http.h -keyserver.h - -ChangeLog diff --git a/include/http.h b/include/http.h deleted file mode 100644 index 7e79ed2c1..000000000 --- a/include/http.h +++ /dev/null @@ -1,81 +0,0 @@ -/* http.h - HTTP protocol handler - * Copyright (C) 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_HTTP_H -#define G10_HTTP_H 1 - -#include "iobuf.h" - -struct uri_tuple { - struct uri_tuple *next; - const char *name; /* a pointer into name */ - char *value; /* a pointer to value (a Nul is always appended) */ - size_t valuelen; /* and the real length of the value */ - /* because the value may contain embedded Nuls */ -}; -typedef struct uri_tuple *URI_TUPLE; - -struct parsed_uri { - /* all these pointers point into buffer; most stuff is not escaped */ - char *scheme; /* pointer to the scheme string (lowercase) */ - char *host; /* host (converted to lowercase) */ - ushort port; /* port (always set if the host is set) */ - char *path; /* the path */ - URI_TUPLE params; /* ";xxxxx" */ - URI_TUPLE query; /* "?xxx=yyy" */ - char buffer[1]; /* buffer which holds a (modified) copy of the URI */ -}; -typedef struct parsed_uri *PARSED_URI; - -typedef enum { - HTTP_REQ_GET = 1, - HTTP_REQ_HEAD = 2, - HTTP_REQ_POST = 3 -} HTTP_REQ_TYPE; - -enum { /* put flag values into an enum, so that gdb can display them */ - HTTP_FLAG_TRY_PROXY = 1, - HTTP_FLAG_NO_SHUTDOWN = 2 -}; - -struct http_context { - int initialized; - unsigned int status_code; - int sock; - int in_data; - IOBUF fp_read; - IOBUF fp_write; - int is_http_0_9; - PARSED_URI uri; - HTTP_REQ_TYPE req_type; - byte *buffer; /* line buffer */ - unsigned buffer_size; - unsigned int flags; -}; -typedef struct http_context *HTTP_HD; - -int http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, - unsigned int flags ); -void http_start_data( HTTP_HD hd ); -int http_wait_response( HTTP_HD hd, unsigned int *ret_status ); -void http_close( HTTP_HD hd ); - -int http_open_document( HTTP_HD hd, const char *document, unsigned int flags ); - -#endif /*G10_HTTP_H*/ diff --git a/include/i18n.h b/include/i18n.h deleted file mode 100644 index 0b270687a..000000000 --- a/include/i18n.h +++ /dev/null @@ -1,54 +0,0 @@ -/* i18n.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_I18N_H -#define G10_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 /* suggested by Ernst Molitor */ -#endif - -#ifdef ENABLE_NLS -#ifndef __riscos__ - #include -#else - #include "libgettext.h" -#endif /* __riscos__ */ - #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 /*G10_I18N_H*/ diff --git a/include/iobuf.h b/include/iobuf.h deleted file mode 100644 index f94cf4d28..000000000 --- a/include/iobuf.h +++ /dev/null @@ -1,161 +0,0 @@ -/* iobuf.h - I/O buffer - * 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_IOBUF_H -#define G10_IOBUF_H - -#include "types.h" - - -#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; - -/* 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 chain, byte *buf, size_t *len); - void *filter_ov; /* value for opaque */ - int filter_ov_owner; - char *real_fname; - IOBUF 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 iobuf_alloc(int use, size_t bufsize); -IOBUF iobuf_temp(void); -IOBUF iobuf_temp_with_content( const char *buffer, size_t length ); -IOBUF iobuf_open( const char *fname ); -IOBUF iobuf_fdopen( int fd, const char *mode ); -IOBUF iobuf_sockopen( int fd, const char *mode ); -IOBUF iobuf_create( const char *fname ); -IOBUF iobuf_append( const char *fname ); -IOBUF iobuf_openrw( const char *fname ); -int iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ); -int iobuf_close( IOBUF iobuf ); -int iobuf_cancel( IOBUF iobuf ); - -int iobuf_push_filter( IOBUF a, int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), void *ov ); -int iobuf_push_filter2( IOBUF a, - int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), - void *ov, int rel_ov ); -int iobuf_flush(IOBUF a); -void iobuf_clear_eof(IOBUF a); -#define iobuf_set_error(a) do { (a)->error = 1; } while(0) -#define iobuf_error(a) ((a)->error) - -void iobuf_set_limit( IOBUF a, off_t nlimit ); - -off_t iobuf_tell( IOBUF a ); -int iobuf_seek( IOBUF a, off_t newpos ); - -int iobuf_readbyte(IOBUF a); -int iobuf_read(IOBUF a, byte *buf, unsigned buflen ); -unsigned iobuf_read_line( IOBUF a, byte **addr_of_buffer, - unsigned *length_of_buffer, unsigned *max_length ); -int iobuf_peek(IOBUF a, byte *buf, unsigned buflen ); -int iobuf_writebyte(IOBUF a, unsigned c); -int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); -int iobuf_writestr(IOBUF a, const char *buf ); - -void iobuf_flush_temp( IOBUF temp ); -int iobuf_write_temp( IOBUF a, IOBUF temp ); -size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ); -void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ); - -off_t iobuf_get_filelength( IOBUF a ); -#define IOBUF_FILELENGTH_LIMIT 0xffffffff -const char *iobuf_get_real_fname( IOBUF a ); -const char *iobuf_get_fname( IOBUF a ); - -void iobuf_set_block_mode( IOBUF a, size_t n ); -void iobuf_set_partial_block_mode( IOBUF a, size_t len ); -int iobuf_in_block_mode( IOBUF 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 /*G10_IOBUF_H*/ diff --git a/include/memory.h b/include/memory.h deleted file mode 100644 index 6a364795b..000000000 --- a/include/memory.h +++ /dev/null @@ -1,95 +0,0 @@ -/* memory.h - memory allocation - * 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_MEMORY_H -#define G10_MEMORY_H - -#ifdef M_DEBUG -#ifndef STR - #define STR(v) #v -#endif -#ifndef __riscos__ - #define M_DBGINFO(a) __FUNCTION__ "["__FILE__ ":" STR(a) "]" -#else /* __riscos__ */ - #define M_DBGINFO(a) "["__FILE__ ":" STR(a) "]" -#endif /* __riscos__ */ -#define m_alloc(n) m_debug_alloc((n), M_DBGINFO( __LINE__ ) ) -#define m_alloc_clear(n) m_debug_alloc_clear((n), M_DBGINFO(__LINE__) ) -#define m_alloc_secure(n) m_debug_alloc((n), M_DBGINFO(__LINE__) ) -#define m_alloc_secure_clear(n) m_debug_alloc_secure_clear((n), M_DBGINFO(__LINE__) ) -#define m_realloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) ) -#define m_free(n) m_debug_free((n), M_DBGINFO(__LINE__) ) -#define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) ) -/*#define m_copy(a) m_debug_copy((a), M_DBGINFO(__LINE__) )*/ -#define m_strdup(a) m_debug_strdup((a), M_DBGINFO(__LINE__) ) - -void *m_debug_alloc( size_t n, const char *info ); -void *m_debug_alloc_clear( size_t n, const char *info ); -void *m_debug_alloc_secure( size_t n, const char *info ); -void *m_debug_alloc_secure_clear( size_t n, const char *info ); -void *m_debug_realloc( void *a, size_t n, const char *info ); -void m_debug_free( void *p, const char *info ); -void m_debug_check( const void *a, const char *info ); -/*void *m_debug_copy( const void *a, const char *info );*/ -char *m_debug_strdup( const char *a, const char *info ); - -#else -void *m_alloc( size_t n ); -void *m_alloc_clear( size_t n ); -void *m_alloc_secure( size_t n ); -void *m_alloc_secure_clear( size_t n ); -void *m_realloc( void *a, size_t n ); -void m_free( void *p ); -void m_check( const void *a ); -/*void *m_copy( const void *a );*/ -char *m_strdup( const char * a); -#endif - -size_t m_size( const void *a ); -void m_print_stats(const char *prefix); - -/*-- secmem.c --*/ -void secmem_init( size_t npool ); -void secmem_term( void ); -void *secmem_malloc( size_t size ); -void *secmem_realloc( void *a, size_t newsize ); -void secmem_free( void *a ); -int m_is_secure( const void *p ); -void secmem_dump_stats(void); -void secmem_set_flags( unsigned flags ); -unsigned secmem_get_flags(void); - - - -#define DBG_MEMORY memory_debug_mode -#define DBG_MEMSTAT memory_stat_debug_mode - -#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 memory_debug_mode; -EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; - - -#endif /*G10_MEMORY_H*/ diff --git a/include/mpi.h b/include/mpi.h deleted file mode 100644 index 7bb8271dc..000000000 --- a/include/mpi.h +++ /dev/null @@ -1,197 +0,0 @@ -/* mpi.h - Multi Precision Integers - * Copyright (C) 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#ifndef G10_MPI_H -#define G10_MPI_H - -#include -#include -#include "iobuf.h" -#include "types.h" -#include "memory.h" - -#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT - typedef unsigned int mpi_limb_t; - typedef signed int mpi_limb_signed_t; -#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG - typedef unsigned long int mpi_limb_t; - typedef signed long int mpi_limb_signed_t; -#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG - typedef unsigned long long int mpi_limb_t; - typedef signed long long int mpi_limb_signed_t; -#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT - typedef unsigned short int mpi_limb_t; - typedef signed short int mpi_limb_signed_t; -#else - #error BYTES_PER_MPI_LIMB does not match any C type -#endif -#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) - -#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 - -#define DBG_MPI mpi_debug_mode -EXTERN_UNLESS_MAIN_MODULE int mpi_debug_mode; - - -struct gcry_mpi { - int alloced; /* array size (# of allocated limbs) */ - int nlimbs; /* number of valid limbs */ - int nbits; /* the real number of valid bits (info only) */ - int sign; /* indicates a negative number */ - unsigned flags; /* bit 0: array must be allocated in secure memory space */ - /* bit 1: not used */ - /* bit 2: the limb is a pointer to some m_alloced data */ - mpi_limb_t *d; /* array with the limbs */ -}; - -typedef struct gcry_mpi *MPI; - -#define MPI_NULL NULL - -#define mpi_get_nlimbs(a) ((a)->nlimbs) -#define mpi_is_neg(a) ((a)->sign) - -/*-- mpiutil.c --*/ - -#ifdef M_DEBUG - #define mpi_alloc(n) mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) ) - #define mpi_alloc_secure(n) mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) ) - #define mpi_alloc_like(n) mpi_debug_alloc_like((n), M_DBGINFO( __LINE__ ) ) - #define mpi_free(a) mpi_debug_free((a), M_DBGINFO(__LINE__) ) - #define mpi_resize(a,b) mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) ) - #define mpi_copy(a) mpi_debug_copy((a), M_DBGINFO(__LINE__) ) - MPI mpi_debug_alloc( unsigned nlimbs, const char *info ); - MPI mpi_debug_alloc_secure( unsigned nlimbs, const char *info ); - MPI mpi_debug_alloc_like( MPI a, const char *info ); - void mpi_debug_free( MPI a, const char *info ); - void mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ); - MPI mpi_debug_copy( MPI a, const char *info ); -#else - MPI mpi_alloc( unsigned nlimbs ); - MPI mpi_alloc_secure( unsigned nlimbs ); - MPI mpi_alloc_like( MPI a ); - void mpi_free( MPI a ); - void mpi_resize( MPI a, unsigned nlimbs ); - MPI mpi_copy( MPI a ); -#endif -#define mpi_is_opaque(a) ((a) && ((a)->flags&4)) -MPI mpi_set_opaque( MPI a, void *p, int len ); -void *mpi_get_opaque( MPI a, int *len ); -#define mpi_is_secure(a) ((a) && ((a)->flags&1)) -void mpi_set_secure( MPI a ); -void mpi_clear( MPI a ); -void mpi_set( MPI w, MPI u); -void mpi_set_ui( MPI w, ulong u); -MPI mpi_alloc_set_ui( unsigned long u); -void mpi_m_check( MPI a ); -void mpi_swap( MPI a, MPI b); - -/*-- mpicoder.c --*/ -int mpi_write( IOBUF out, MPI a ); -#ifdef M_DEBUG - #define mpi_read(a,b,c) mpi_debug_read((a),(b),(c), M_DBGINFO( __LINE__ ) ) - MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info); -#else - MPI mpi_read(IOBUF inp, unsigned *nread, int secure); -#endif -MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure); -int mpi_fromstr(MPI val, const char *str); -int mpi_print( FILE *fp, MPI a, int mode ); -void g10_log_mpidump( const char *text, MPI a ); -u32 mpi_get_keyid( MPI a, u32 *keyid ); -byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ); -byte *mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ); -void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ); - -#define log_mpidump g10_log_mpidump - -/*-- mpi-add.c --*/ -void mpi_add_ui(MPI w, MPI u, ulong v ); -void mpi_add(MPI w, MPI u, MPI v); -void mpi_addm(MPI w, MPI u, MPI v, MPI m); -void mpi_sub_ui(MPI w, MPI u, ulong v ); -void mpi_sub( MPI w, MPI u, MPI v); -void mpi_subm( MPI w, MPI u, MPI v, MPI m); - -/*-- mpi-mul.c --*/ -void mpi_mul_ui(MPI w, MPI u, ulong v ); -void mpi_mul_2exp( MPI w, MPI u, ulong cnt); -void mpi_mul( MPI w, MPI u, MPI v); -void mpi_mulm( MPI w, MPI u, MPI v, MPI m); - -/*-- mpi-div.c --*/ -ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ); -void mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ); -void mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ); -void mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ); -void mpi_tdiv_r( MPI rem, MPI num, MPI den); -void mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den); -void mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ); -int mpi_divisible_ui(MPI dividend, ulong divisor ); - -/*-- mpi-gcd.c --*/ -int mpi_gcd( MPI g, MPI a, MPI b ); - -/*-- mpi-pow.c --*/ -void mpi_pow( MPI w, MPI u, MPI v); -void mpi_powm( MPI res, MPI base, MPI exp, MPI mod); - -/*-- mpi-mpow.c --*/ -void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod); - -/*-- mpi-cmp.c --*/ -int mpi_cmp_ui( MPI u, ulong v ); -int mpi_cmp( MPI u, MPI v ); - -/*-- mpi-scan.c --*/ -int mpi_getbyte( MPI a, unsigned idx ); -void mpi_putbyte( MPI a, unsigned idx, int value ); -unsigned mpi_trailing_zeros( MPI a ); - -/*-- mpi-bit.c --*/ -void mpi_normalize( MPI a ); -unsigned mpi_get_nbits( MPI a ); -int mpi_test_bit( MPI a, unsigned n ); -void mpi_set_bit( MPI a, unsigned n ); -void mpi_set_highbit( MPI a, unsigned n ); -void mpi_clear_highbit( MPI a, unsigned n ); -void mpi_clear_bit( MPI a, unsigned n ); -void mpi_rshift( MPI x, MPI a, unsigned n ); - -/*-- mpi-inv.c --*/ -void mpi_invm( MPI x, MPI u, MPI v ); - - -#endif /*G10_MPI_H*/ diff --git a/include/ttyio.h b/include/ttyio.h deleted file mode 100644 index 08ca994c9..000000000 --- a/include/ttyio.h +++ /dev/null @@ -1,39 +0,0 @@ -/* ttyio.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_TTYIO_H -#define G10_TTYIO_H - -int tty_batchmode( int onoff ); -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) - void tty_printf (const char *fmt, ... ) __attribute__ ((format (printf,1,2))); -#else - void tty_printf (const char *fmt, ... ); -#endif -void tty_print_string( byte *p, size_t n ); -void tty_print_utf8_string( byte *p, size_t n ); -void tty_print_utf8_string2( byte *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 /*G10_TTYIO_H*/ diff --git a/include/types.h b/include/types.h deleted file mode 100644 index b41109ee5..000000000 --- a/include/types.h +++ /dev/null @@ -1,131 +0,0 @@ -/* types.h - some common typedefs - * 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_TYPES_H -#define G10_TYPES_H - - -/* The AC_CHECK_SIZEOF() in configure fails for some machines. - * we provide some fallback values here */ -#if !SIZEOF_UNSIGNED_SHORT - #undef SIZEOF_UNSIGNED_SHORT - #define SIZEOF_UNSIGNED_SHORT 2 -#endif -#if !SIZEOF_UNSIGNED_INT - #undef SIZEOF_UNSIGNED_INT - #define SIZEOF_UNSIGNED_INT 4 -#endif -#if !SIZEOF_UNSIGNED_LONG - #undef SIZEOF_UNSIGNED_LONG - #define SIZEOF_UNSIGNED_LONG 4 -#endif - - -#include - - -#ifndef HAVE_BYTE_TYPEDEF - #undef byte /* maybe there is a macro with this name */ - #ifndef __riscos__ - typedef unsigned char byte; - #else - /* Norcroft treats char = unsigned char as legal assignment - but char* = unsigned char* as illegal assignment - and the same applies to the signed variants as well */ - typedef char byte; - #endif - #define HAVE_BYTE_TYPEDEF -#endif - -#ifndef HAVE_USHORT_TYPEDEF - #undef ushort /* maybe there is a macro with this name */ - typedef unsigned short ushort; - #define HAVE_USHORT_TYPEDEF -#endif - -#ifndef HAVE_ULONG_TYPEDEF - #undef ulong /* maybe there is a macro with this name */ - typedef unsigned long ulong; - #define HAVE_ULONG_TYPEDEF -#endif - -#ifndef HAVE_U16_TYPEDEF - #undef u16 /* maybe there is a macro with this name */ - #if SIZEOF_UNSIGNED_INT == 2 - typedef unsigned int u16; - #elif SIZEOF_UNSIGNED_SHORT == 2 - typedef unsigned short u16; - #else - #error no typedef for u16 - #endif - #define HAVE_U16_TYPEDEF -#endif - -#ifndef HAVE_U32_TYPEDEF - #undef u32 /* maybe there is a macro with this name */ - #if SIZEOF_UNSIGNED_INT == 4 - typedef unsigned int u32; - #elif SIZEOF_UNSIGNED_LONG == 4 - typedef unsigned long u32; - #else - #error no typedef for u32 - #endif - #define HAVE_U32_TYPEDEF -#endif - -/**************** - * Warning: Some systems segfault when this u64 typedef and - * the dummy code in cipher/md.c is not available. Examples are - * Solaris and IRIX. - */ -#ifndef HAVE_U64_TYPEDEF - #undef u64 /* maybe there is a macro with this name */ - #if SIZEOF_UNSIGNED_INT == 8 - typedef unsigned int u64; - #define HAVE_U64_TYPEDEF - #elif SIZEOF_UNSIGNED_LONG == 8 - typedef unsigned long u64; - #define HAVE_U64_TYPEDEF - #elif SIZEOF_UNSIGNED_LONG_LONG == 8 - typedef unsigned long long u64; - #define HAVE_U64_TYPEDEF - #endif -#endif - -typedef union { - int a; - short b; - char c[1]; - long d; - #ifdef HAVE_U64_TYPEDEF - u64 e; - #endif - float f; - double g; -} PROPERLY_ALIGNED_TYPE; - -typedef struct string_list { - struct string_list *next; - unsigned int flags; - char d[1]; -} *STRLIST; - - -#endif /*G10_TYPES_H*/ diff --git a/include/util.h b/include/util.h deleted file mode 100644 index 8f7363908..000000000 --- a/include/util.h +++ /dev/null @@ -1,296 +0,0 @@ -/* util.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_UTIL_H -#define G10_UTIL_H - -#if defined (__MINGW32__) || defined (__CYGWIN32__) -# include -#endif - -#include "types.h" -#include "errors.h" -#include "types.h" -#include "mpi.h" - - -typedef struct { - int *argc; /* pointer to argc (value subject to change) */ - char ***argv; /* pointer to argv (value subject to change) */ - unsigned flags; /* Global flags (DO NOT CHANGE) */ - int err; /* print error about last option */ - /* 1 = warning, 2 = abort */ - int r_opt; /* return option */ - int r_type; /* type of return value (0 = no argument found)*/ - union { - int ret_int; - long ret_long; - ulong ret_ulong; - char *ret_str; - } r; /* Return values */ - struct { - int idx; - int inarg; - int stopped; - const char *last; - void *aliases; - const void *cur_alias; - } internal; /* DO NOT CHANGE */ -} ARGPARSE_ARGS; - -typedef struct { - int short_opt; - const char *long_opt; - unsigned flags; - const char *description; /* optional option description */ -} ARGPARSE_OPTS; - -/*-- logger.c --*/ -void log_set_logfile( const char *name, int fd ); -FILE *log_stream(void); -void g10_log_print_prefix(const char *text); -void log_set_name( const char *name ); -const char *log_get_name(void); -void log_set_pid( int pid ); -int log_get_errorcount( int clear ); -void log_inc_errorcount(void); -int log_set_strict(int val); -void g10_log_hexdump( const char *text, const char *buf, size_t len ); - -#if defined (__riscos__) \ - || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) - void g10_log_bug( const char *fmt, ... ) - __attribute__ ((noreturn, format (printf,1,2))); - void g10_log_bug0( const char *, int, const char * ) __attribute__ ((noreturn)); - void g10_log_fatal( const char *fmt, ... ) - __attribute__ ((noreturn, format (printf,1,2))); - void g10_log_error( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); - void g10_log_info( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); - void g10_log_warning( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); - void g10_log_debug( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); - void g10_log_fatal_f( const char *fname, const char *fmt, ... ) - __attribute__ ((noreturn, format (printf,2,3))); - void g10_log_error_f( const char *fname, const char *fmt, ... ) - __attribute__ ((format (printf,2,3))); - void g10_log_info_f( const char *fname, const char *fmt, ... ) - __attribute__ ((format (printf,2,3))); - void g10_log_debug_f( const char *fname, const char *fmt, ... ) - __attribute__ ((format (printf,2,3))); -#ifndef __riscos__ - #define BUG() g10_log_bug0( __FILE__ , __LINE__, __FUNCTION__ ) -#else - #define BUG() g10_log_bug0( __FILE__ , __LINE__, __func__ ) -#endif -#else - void g10_log_bug( const char *fmt, ... ); - void g10_log_bug0( const char *, int ); - void g10_log_fatal( const char *fmt, ... ); - void g10_log_error( const char *fmt, ... ); - void g10_log_info( const char *fmt, ... ); - void g10_log_warning( const char *fmt, ... ); - void g10_log_debug( const char *fmt, ... ); - void g10_log_fatal_f( const char *fname, const char *fmt, ... ); - void g10_log_error_f( const char *fname, const char *fmt, ... ); - void g10_log_info_f( const char *fname, const char *fmt, ... ); - void g10_log_debug_f( const char *fname, const char *fmt, ... ); - #define BUG() g10_log_bug0( __FILE__ , __LINE__ ) -#endif - -#define log_hexdump g10_log_hexdump -#define log_bug g10_log_bug -#define log_bug0 g10_log_bug0 -#define log_fatal g10_log_fatal -#define log_error g10_log_error -#define log_info g10_log_info -#define log_warning g10_log_warning -#define log_debug g10_log_debug -#define log_fatal_f g10_log_fatal_f -#define log_error_f g10_log_error_f -#define log_info_f g10_log_info_f -#define log_debug_f g10_log_debug_f - - -/*-- errors.c --*/ -const char * g10_errstr( int no ); - -/*-- argparse.c --*/ -int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -void usage( int level ); -const char *default_strusage( int level ); - - -/*-- (main program) --*/ -const char *strusage( int level ); - - -/*-- dotlock.c --*/ -struct dotlock_handle; -typedef struct dotlock_handle *DOTLOCK; - -void disable_dotlock(void); -DOTLOCK create_dotlock( const char *file_to_lock ); -int make_dotlock( DOTLOCK h, long timeout ); -int release_dotlock( DOTLOCK h ); -void remove_lockfiles (void); - -/*-- fileutil.c --*/ -char * make_basename(const char *filepath); -char * make_dirname(const char *filepath); -char *make_filename( const char *first_part, ... ); -int compare_filenames( const char *a, const char *b ); -const char *print_fname_stdin( const char *s ); -const char *print_fname_stdout( const char *s ); -int is_file_compressed(const char *s, int *r_status); - - -/*-- miscutil.c --*/ -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 */ -void print_string( FILE *fp, const byte *p, size_t n, int delim ); -void print_utf8_string( FILE *fp, const byte *p, size_t n ); -void print_utf8_string2( FILE *fp, const byte *p, size_t n, int delim); -char *make_printable_string( const byte *p, size_t n, int delim ); -int answer_is_yes_no_default( const char *s, int def_answer ); -int answer_is_yes( const char *s ); -int answer_is_yes_no_quit( const char *s ); - -/*-- strgutil.c --*/ -void free_strlist( STRLIST sl ); -#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) -STRLIST add_to_strlist( STRLIST *list, const char *string ); -STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); -STRLIST append_to_strlist( STRLIST *list, const char *string ); -STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); -STRLIST strlist_prev( STRLIST head, STRLIST node ); -STRLIST strlist_last( STRLIST node ); -char *pop_strlist( STRLIST *list ); -const char *memistr( const char *buf, size_t buflen, const char *sub ); -const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); -char *mem2str( char *, const void *, size_t); -char *trim_spaces( char *string ); -unsigned int trim_trailing_chars( byte *line, unsigned int len, - const char *trimchars); -unsigned int trim_trailing_ws( byte *line, unsigned len ); -unsigned int check_trailing_chars( const byte *line, unsigned int len, - const char *trimchars ); -unsigned int check_trailing_ws( const byte *line, unsigned int len ); -int string_count_chr( const char *string, int c ); -int set_native_charset( const char *newset ); -const char* get_native_charset(void); -char *native_to_utf8( const char *string ); -char *utf8_to_native( const char *string, size_t length, int delim); -int check_utf8_string( const char *string ); - -int ascii_isupper (int c); -int ascii_islower (int c); -int ascii_toupper (int c); -int ascii_tolower (int c); -int ascii_strcasecmp( const char *a, const char *b ); -int ascii_strncasecmp( const char *a, const char *b, size_t n); -int ascii_memcasecmp( const char *a, const char *b, size_t n); - -#ifndef HAVE_STPCPY -char *stpcpy(char *a,const char *b); -#endif -#ifndef HAVE_STRLWR -char *strlwr(char *a); -#endif -#ifndef HAVE_STRSEP -char *strsep (char **stringp, const char *delim); -#endif -#ifndef HAVE_STRCASECMP -int strcasecmp( const char *, const char *b); -#endif -#ifndef HAVE_STRNCASECMP -int strncasecmp (const char *, const char *b, size_t n); -#endif -#ifndef HAVE_STRTOUL - #define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) -#endif -#ifndef HAVE_MEMMOVE - #define memmove(d, s, n) bcopy((s), (d), (n)) -#endif - -#if defined (__MINGW32__) || defined (__CYGWIN32__) -/*-- w32reg.c --*/ -char *read_w32_registry_string( const char *root, - const char *dir, const char *name ); -int write_w32_registry_string(const char *root, const char *dir, - const char *name, const char *value); - -/*-- strgutil.c --*/ -int vasprintf ( char **result, const char *format, va_list args); -#endif - -/**** other missing stuff ****/ -#ifndef HAVE_ATEXIT /* For SunOS */ - #define atexit(a) (on_exit((a),0)) -#endif - -#ifndef HAVE_RAISE - #define raise(a) kill(getpid(), (a)) -#endif - -/******** some macros ************/ -#ifndef STR - #define STR(v) #v -#endif -#define STR2(v) STR(v) -#define DIM(v) (sizeof(v)/sizeof((v)[0])) -#define DIMof(type,member) DIM(((type *)0)->member) - -/******* RISC OS stuff ***********/ -#ifdef __riscos__ -/* needed for strcasecmp() */ -#include -/* needed for filename munging */ -#include -/* needed for image file system feature */ -#include -void riscos_global_defaults(void); -#define RISCOS_GLOBAL_STATICS(a) const char *__dynamic_da_name = (a); -void riscos_set_filetype(const char *filename, const char *mimetype); -pid_t riscos_getpid(void); -int riscos_kill(pid_t pid, int sig); -int riscos_access(const char *path, int amode); -int riscos_getchar(void); -int fdopenfile(const char *filename, const int allow_write); -void close_fds(void); -int renamefile(const char *old, const char *new); -char *gstrans(const char *old); -void not_implemented(const char *feature); -#ifdef DEBUG -void dump_fdlist(void); -void list_openfiles(void); -#endif -#ifndef __RISCOS__C__ - #define getpid riscos_getpid - #define kill(a,b) riscos_kill((a),(b)) - #define access(a,b) riscos_access((a),(b)) -#endif /* !__RISCOS__C__ */ -#endif /* __riscos__ */ - -#endif /*G10_UTIL_H*/ - diff --git a/intl/ChangeLog b/intl/ChangeLog deleted file mode 100644 index 84e2b37ec..000000000 --- a/intl/ChangeLog +++ /dev/null @@ -1,4 +0,0 @@ -2001-09-13 GNU - - * Version 0.10.40 released. - diff --git a/intl/Makefile.in b/intl/Makefile.in deleted file mode 100644 index 19ed4a7e0..000000000 --- a/intl/Makefile.in +++ /dev/null @@ -1,313 +0,0 @@ -# Makefile for directory with message catalog handling in GNU NLS Utilities. -# Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. -# -# This program 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, 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. - -PACKAGE = @PACKAGE@ -VERSION = @VERSION@ - -SHELL = /bin/sh - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -top_builddir = .. -VPATH = @srcdir@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -transform = @program_transform_name@ -libdir = @libdir@ -includedir = @includedir@ -datadir = @datadir@ -localedir = $(datadir)/locale -gettextsrcdir = $(datadir)/gettext/intl -aliaspath = $(localedir) -subdir = intl - -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` - -l = @INTL_LIBTOOL_SUFFIX_PREFIX@ - -AR = ar -CC = @CC@ -LIBTOOL = @LIBTOOL@ -RANLIB = @RANLIB@ -YACC = @INTLBISON@ -y -d -YFLAGS = --name-prefix=__gettext - -DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \ --DLIBDIR=\"$(libdir)\" @DEFS@ -CPPFLAGS = @CPPFLAGS@ -CFLAGS = @CFLAGS@ -LDFLAGS = @LDFLAGS@ - -COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) - -HEADERS = $(COMHDRS) libgnuintl.h libgettext.h loadinfo.h -COMHDRS = gettext.h gettextP.h hash-string.h -SOURCES = $(COMSRCS) intl-compat.c -COMSRCS = bindtextdom.c dcgettext.c dgettext.c gettext.c \ -finddomain.c loadmsgcat.c localealias.c textdomain.c l10nflist.c \ -explodename.c dcigettext.c dcngettext.c dngettext.c ngettext.c plural.y \ -localcharset.c -OBJECTS = @INTLOBJS@ bindtextdom.$lo dcgettext.$lo dgettext.$lo gettext.$lo \ -finddomain.$lo loadmsgcat.$lo localealias.$lo textdomain.$lo l10nflist.$lo \ -explodename.$lo dcigettext.$lo dcngettext.$lo dngettext.$lo ngettext.$lo \ -plural.$lo localcharset.$lo -GETTOBJS = intl-compat.$lo -DISTFILES.common = Makefile.in \ -config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) -DISTFILES.generated = plural.c -DISTFILES.normal = VERSION -DISTFILES.gettext = COPYING.LIB-2 COPYING.LIB-2.1 libintl.glibc -DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c - -# Libtool's library version information for libintl. -# Before making a gettext release, the gettext maintainer must change this -# according to the libtool documentation, section "Library interface versions". -# Maintainers of other packages that include the intl directory must *not* -# change these values. -LTV_CURRENT=1 -LTV_REVISION=1 -LTV_AGE=0 - -.SUFFIXES: -.SUFFIXES: .c .y .o .lo .sin .sed -.c.o: - $(COMPILE) $< -.c.lo: - $(LIBTOOL) --mode=compile $(COMPILE) $< - -.y.c: - $(YACC) $(YFLAGS) --output $@ $< - rm -f $*.h - -.sin.sed: - sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@ - mv t-$@ $@ - -INCLUDES = -I.. -I. -I$(top_srcdir)/intl - -all: all-@USE_INCLUDED_LIBINTL@ -all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed -all-no: all-no-@BUILD_INCLUDED_LIBINTL@ -all-no-yes: libgnuintl.$la -all-no-no: - -libintl.a libgnuintl.a: $(OBJECTS) - rm -f $@ - $(AR) cru $@ $(OBJECTS) - $(RANLIB) $@ - -libintl.la libgnuintl.la: $(OBJECTS) - $(LIBTOOL) --mode=link \ - $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \ - $(OBJECTS) @LIBICONV@ \ - -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \ - -rpath $(libdir) \ - -no-undefined - -libintl.h: libgnuintl.h - cp $(srcdir)/libgnuintl.h libintl.h - -charset.alias: config.charset - $(SHELL) $(srcdir)/config.charset '@host@' > t-$@ - mv t-$@ $@ - -check: all - -# This installation goal is only used in GNU gettext. Packages which -# only use the library should use install instead. - -# We must not install the libintl.h/libintl.a files if we are on a -# system which has the GNU gettext() function in its C library or in a -# separate library. -# If you want to use the one which comes with this version of the -# package, you have to use `configure --with-included-gettext'. -install: install-exec install-data -install-exec: all - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ - $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \ - $(LIBTOOL) --mode=install \ - $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir); \ - temp=$(DESTDIR)$(libdir)/t-charset.alias; \ - dest=$(DESTDIR)$(libdir)/charset.alias; \ - if test -f $(DESTDIR)$(libdir)/charset.alias; then \ - orig=$(DESTDIR)$(libdir)/charset.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - else \ - if test @GLIBC21@ = no; then \ - orig=charset.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - fi; \ - fi; \ - $(mkinstalldirs) $(DESTDIR)$(localedir); \ - test -f $(DESTDIR)$(localedir)/locale.alias \ - && orig=$(DESTDIR)$(localedir)/locale.alias \ - || orig=$(srcdir)/locale.alias; \ - temp=$(DESTDIR)$(localedir)/t-locale.alias; \ - dest=$(DESTDIR)$(localedir)/locale.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - else \ - : ; \ - fi -install-data: all - if test "$(PACKAGE)" = "gettext"; then \ - $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ - $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \ - $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \ - dists="COPYING.LIB-2 COPYING.LIB-2.1 $(DISTFILES.common)"; \ - for file in $$dists; do \ - $(INSTALL_DATA) $(srcdir)/$$file \ - $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \ - dists="$(DISTFILES.generated)"; \ - for file in $$dists; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - $(INSTALL_DATA) $$dir/$$file \ - $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - dists="$(DISTFILES.obsolete)"; \ - for file in $$dists; do \ - rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - else \ - : ; \ - fi - -# Define this as empty until I found a useful application. -installcheck: - -uninstall: - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - rm -f $(DESTDIR)$(includedir)/libintl.h; \ - $(LIBTOOL) --mode=uninstall \ - rm -f $(DESTDIR)$(libdir)/libintl.$la; \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - if test -f $(DESTDIR)$(libdir)/charset.alias; then \ - temp=$(DESTDIR)$(libdir)/t-charset.alias; \ - dest=$(DESTDIR)$(libdir)/charset.alias; \ - sed -f ref-del.sed $$dest > $$temp; \ - if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ - rm -f $$dest; \ - else \ - $(INSTALL_DATA) $$temp $$dest; \ - fi; \ - rm -f $$temp; \ - fi; \ - if test -f $(DESTDIR)$(localedir)/locale.alias; then \ - temp=$(DESTDIR)$(localedir)/t-locale.alias; \ - dest=$(DESTDIR)$(localedir)/locale.alias; \ - sed -f ref-del.sed $$dest > $$temp; \ - if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ - rm -f $$dest; \ - else \ - $(INSTALL_DATA) $$temp $$dest; \ - fi; \ - rm -f $$temp; \ - fi; \ - else \ - : ; \ - fi - if test "$(PACKAGE)" = "gettext"; then \ - for file in VERSION ChangeLog COPYING.LIB-2 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \ - rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - else \ - : ; \ - fi - -info dvi: - -$(OBJECTS): ../config.h libgnuintl.h -bindtextdom.$lo finddomain.$lo loadmsgcat.$lo: gettextP.h gettext.h loadinfo.h -dcgettext.$lo: gettextP.h gettext.h hash-string.h loadinfo.h - -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) - here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) - -id: ID - -ID: $(HEADERS) $(SOURCES) - here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) - - -mostlyclean: - rm -f *.a *.la *.o *.lo core core.* - rm -f libintl.h charset.alias ref-add.sed ref-del.sed - rm -f -r .libs _libs - -clean: mostlyclean - -distclean: clean - rm -f Makefile ID TAGS - if test "$(PACKAGE)" = gettext; then \ - rm -f ChangeLog.inst $(DISTFILES.normal); \ - else \ - : ; \ - fi - -maintainer-clean: distclean - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - - -# GNU gettext needs not contain the file `VERSION' but contains some -# other files which should not be distributed in other packages. -distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) -dist distdir: Makefile - if test "$(PACKAGE)" = gettext; then \ - additional="$(DISTFILES.gettext)"; \ - else \ - additional="$(DISTFILES.normal)"; \ - fi; \ - $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \ - for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - ln $$dir/$$file $(distdir) 2> /dev/null \ - || cp -p $$dir/$$file $(distdir); \ - done - -Makefile: Makefile.in ../config.status - cd .. \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - -# Tell versions [3.59,3.63) of GNU make not to export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/intl/VERSION b/intl/VERSION deleted file mode 100644 index cb8a01a78..000000000 --- a/intl/VERSION +++ /dev/null @@ -1 +0,0 @@ -GNU gettext library from gettext-0.10.40 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c deleted file mode 100644 index c6a9bd164..000000000 --- a/intl/bindtextdom.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Implementation of the bindtextdomain(3) function - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include -#include -#include - -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "gettextP.h" - -#ifdef _LIBC -/* We have to handle multi-threaded applications. */ -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_rwlock_define(CLASS, NAME) -# define __libc_rwlock_wrlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_dirname _nl_default_dirname__ -# define _nl_domain_bindings _nl_domain_bindings__ -#endif - -/* Some compilers, like SunOS4 cc, don't have offsetof in . */ -#ifndef offsetof -# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) -#endif - -/* @@ end of prolog @@ */ - -/* Contains the default location of the message catalogs. */ -extern const char _nl_default_dirname[]; - -/* List with bindings of specific domains. */ -extern struct binding *_nl_domain_bindings; - -/* Lock variable to protect the global data in the gettext implementation. */ -__libc_rwlock_define (extern, _nl_state_lock) - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define BINDTEXTDOMAIN __bindtextdomain -# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset -# ifndef strdup -# define strdup(str) __strdup (str) -# endif -#else -# define BINDTEXTDOMAIN bindtextdomain__ -# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__ -#endif - -/* Prototypes for local functions. */ -static void set_binding_values PARAMS ((const char *domainname, - const char **dirnamep, - const char **codesetp)); - -/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP - to be used for the DOMAINNAME message catalog. - If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not - modified, only the current value is returned. - If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither - modified nor returned. */ -static void -set_binding_values (domainname, dirnamep, codesetp) - const char *domainname; - const char **dirnamep; - const char **codesetp; -{ - struct binding *binding; - int modified; - - /* Some sanity checks. */ - if (domainname == NULL || domainname[0] == '\0') - { - if (dirnamep) - *dirnamep = NULL; - if (codesetp) - *codesetp = NULL; - return; - } - - __libc_rwlock_wrlock (_nl_state_lock); - - modified = 0; - - for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) - { - int compare = strcmp (domainname, binding->domainname); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It is not in the list. */ - binding = NULL; - break; - } - } - - if (binding != NULL) - { - if (dirnamep) - { - const char *dirname = *dirnamep; - - if (dirname == NULL) - /* The current binding has be to returned. */ - *dirnamep = binding->dirname; - else - { - /* The domain is already bound. If the new value and the old - one are equal we simply do nothing. Otherwise replace the - old binding. */ - char *result = binding->dirname; - if (strcmp (dirname, result) != 0) - { - if (strcmp (dirname, _nl_default_dirname) == 0) - result = (char *) _nl_default_dirname; - else - { -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (dirname); -#else - size_t len = strlen (dirname) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result != NULL, 1)) - memcpy (result, dirname, len); -#endif - } - - if (__builtin_expect (result != NULL, 1)) - { - if (binding->dirname != _nl_default_dirname) - free (binding->dirname); - - binding->dirname = result; - modified = 1; - } - } - *dirnamep = result; - } - } - - if (codesetp) - { - const char *codeset = *codesetp; - - if (codeset == NULL) - /* The current binding has be to returned. */ - *codesetp = binding->codeset; - else - { - /* The domain is already bound. If the new value and the old - one are equal we simply do nothing. Otherwise replace the - old binding. */ - char *result = binding->codeset; - if (result == NULL || strcmp (codeset, result) != 0) - { -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (codeset); -#else - size_t len = strlen (codeset) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result != NULL, 1)) - memcpy (result, codeset, len); -#endif - - if (__builtin_expect (result != NULL, 1)) - { - if (binding->codeset != NULL) - free (binding->codeset); - - binding->codeset = result; - binding->codeset_cntr++; - modified = 1; - } - } - *codesetp = result; - } - } - } - else if ((dirnamep == NULL || *dirnamep == NULL) - && (codesetp == NULL || *codesetp == NULL)) - { - /* Simply return the default values. */ - if (dirnamep) - *dirnamep = _nl_default_dirname; - if (codesetp) - *codesetp = NULL; - } - else - { - /* We have to create a new binding. */ - size_t len = strlen (domainname) + 1; - struct binding *new_binding = - (struct binding *) malloc (offsetof (struct binding, domainname) + len); - - if (__builtin_expect (new_binding == NULL, 0)) - goto failed; - - memcpy (new_binding->domainname, domainname, len); - - if (dirnamep) - { - const char *dirname = *dirnamep; - - if (dirname == NULL) - /* The default value. */ - dirname = _nl_default_dirname; - else - { - if (strcmp (dirname, _nl_default_dirname) == 0) - dirname = _nl_default_dirname; - else - { - char *result; -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (dirname); - if (__builtin_expect (result == NULL, 0)) - goto failed_dirname; -#else - size_t len = strlen (dirname) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result == NULL, 0)) - goto failed_dirname; - memcpy (result, dirname, len); -#endif - dirname = result; - } - } - *dirnamep = dirname; - new_binding->dirname = (char *) dirname; - } - else - /* The default value. */ - new_binding->dirname = (char *) _nl_default_dirname; - - new_binding->codeset_cntr = 0; - - if (codesetp) - { - const char *codeset = *codesetp; - - if (codeset != NULL) - { - char *result; - -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (codeset); - if (__builtin_expect (result == NULL, 0)) - goto failed_codeset; -#else - size_t len = strlen (codeset) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result == NULL, 0)) - goto failed_codeset; - memcpy (result, codeset, len); -#endif - codeset = result; - new_binding->codeset_cntr++; - } - *codesetp = codeset; - new_binding->codeset = (char *) codeset; - } - else - new_binding->codeset = NULL; - - /* Now enqueue it. */ - if (_nl_domain_bindings == NULL - || strcmp (domainname, _nl_domain_bindings->domainname) < 0) - { - new_binding->next = _nl_domain_bindings; - _nl_domain_bindings = new_binding; - } - else - { - binding = _nl_domain_bindings; - while (binding->next != NULL - && strcmp (domainname, binding->next->domainname) > 0) - binding = binding->next; - - new_binding->next = binding->next; - binding->next = new_binding; - } - - modified = 1; - - /* Here we deal with memory allocation failures. */ - if (0) - { - failed_codeset: - if (new_binding->dirname != _nl_default_dirname) - free (new_binding->dirname); - failed_dirname: - free (new_binding); - failed: - if (dirnamep) - *dirnamep = NULL; - if (codesetp) - *codesetp = NULL; - } - } - - /* If we modified any binding, we flush the caches. */ - if (modified) - ++_nl_msg_cat_cntr; - - __libc_rwlock_unlock (_nl_state_lock); -} - -/* Specify that the DOMAINNAME message catalog will be found - in DIRNAME rather than in the system locale data base. */ -char * -BINDTEXTDOMAIN (domainname, dirname) - const char *domainname; - const char *dirname; -{ - set_binding_values (domainname, &dirname, NULL); - return (char *) dirname; -} - -/* Specify the character encoding in which the messages from the - DOMAINNAME message catalog will be returned. */ -char * -BIND_TEXTDOMAIN_CODESET (domainname, codeset) - const char *domainname; - const char *codeset; -{ - set_binding_values (domainname, NULL, &codeset); - return (char *) codeset; -} - -#ifdef _LIBC -/* Aliases for function names in GNU C Library. */ -weak_alias (__bindtextdomain, bindtextdomain); -weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset); -#endif diff --git a/intl/config.charset b/intl/config.charset deleted file mode 100755 index f4f2611c5..000000000 --- a/intl/config.charset +++ /dev/null @@ -1,438 +0,0 @@ -#! /bin/sh -# Output a system dependent table of character encoding aliases. -# -# Copyright (C) 2000-2001 Free Software Foundation, Inc. -# -# This program 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, 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. -# -# The table consists of lines of the form -# ALIAS CANONICAL -# -# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". -# ALIAS is compared in a case sensitive way. -# -# CANONICAL is the GNU canonical name for this character encoding. -# It must be an encoding supported by libiconv. Support by GNU libc is -# also desirable. CANONICAL is case insensitive. Usually an upper case -# MIME charset name is preferred. -# The current list of GNU canonical charset names is as follows. -# -# name used by which systems a MIME name? -# ASCII, ANSI_X3.4-1968 glibc solaris freebsd -# ISO-8859-1 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-2 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-3 glibc yes -# ISO-8859-4 osf solaris freebsd yes -# ISO-8859-5 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-6 glibc aix hpux solaris yes -# ISO-8859-7 glibc aix hpux irix osf solaris yes -# ISO-8859-8 glibc aix hpux osf solaris yes -# ISO-8859-9 glibc aix hpux irix osf solaris yes -# ISO-8859-13 glibc -# ISO-8859-15 glibc aix osf solaris freebsd -# KOI8-R glibc solaris freebsd yes -# KOI8-U glibc freebsd yes -# CP437 dos -# CP775 dos -# CP850 aix osf dos -# CP852 dos -# CP855 dos -# CP856 aix -# CP857 dos -# CP861 dos -# CP862 dos -# CP864 dos -# CP865 dos -# CP866 freebsd dos -# CP869 dos -# CP874 win32 dos -# CP922 aix -# CP932 aix win32 dos -# CP943 aix -# CP949 osf win32 dos -# CP950 win32 dos -# CP1046 aix -# CP1124 aix -# CP1129 aix -# CP1250 win32 -# CP1251 glibc win32 -# CP1252 aix win32 -# CP1253 win32 -# CP1254 win32 -# CP1255 win32 -# CP1256 win32 -# CP1257 win32 -# GB2312 glibc aix hpux irix solaris freebsd yes -# EUC-JP glibc aix hpux irix osf solaris freebsd yes -# EUC-KR glibc aix hpux irix osf solaris freebsd yes -# EUC-TW glibc aix hpux irix osf solaris -# BIG5 glibc aix hpux osf solaris freebsd yes -# BIG5-HKSCS glibc -# GBK aix osf win32 dos -# GB18030 glibc -# SHIFT_JIS hpux osf solaris freebsd yes -# JOHAB glibc win32 -# TIS-620 glibc aix hpux osf solaris -# VISCII glibc yes -# HP-ROMAN8 hpux -# HP-ARABIC8 hpux -# HP-GREEK8 hpux -# HP-HEBREW8 hpux -# HP-TURKISH8 hpux -# HP-KANA8 hpux -# DEC-KANJI osf -# DEC-HANYU osf -# UTF-8 glibc aix hpux osf solaris yes -# -# Note: Names which are not marked as being a MIME name should not be used in -# Internet protocols for information interchange (mail, news, etc.). -# -# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications -# must understand both names and treat them as equivalent. -# -# The first argument passed to this file is the canonical host specification, -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM - -host="$1" -os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` -echo "# This file contains a table of character encoding aliases," -echo "# suitable for operating system '${os}'." -echo "# It was automatically generated from config.charset." -# List of references, updated during installation: -echo "# Packages using this file: " -case "$os" in - linux* | *-gnu*) - # With glibc-2.1 or newer, we don't need any canonicalization, - # because glibc has iconv and both glibc and libiconv support all - # GNU canonical names directly. Therefore, the Makefile does not - # need to install the alias file at all. - # The following applies only to glibc-2.0.x and older libcs. - echo "ISO_646.IRV:1983 ASCII" - ;; - aix*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-6 ISO-8859-6" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "IBM-850 CP850" - echo "IBM-856 CP856" - echo "IBM-921 ISO-8859-13" - echo "IBM-922 CP922" - echo "IBM-932 CP932" - echo "IBM-943 CP943" - echo "IBM-1046 CP1046" - echo "IBM-1124 CP1124" - echo "IBM-1129 CP1129" - echo "IBM-1252 CP1252" - echo "IBM-eucCN GB2312" - echo "IBM-eucJP EUC-JP" - echo "IBM-eucKR EUC-KR" - echo "IBM-eucTW EUC-TW" - echo "big5 BIG5" - echo "GBK GBK" - echo "TIS-620 TIS-620" - echo "UTF-8 UTF-8" - ;; - hpux*) - echo "iso88591 ISO-8859-1" - echo "iso88592 ISO-8859-2" - echo "iso88595 ISO-8859-5" - echo "iso88596 ISO-8859-6" - echo "iso88597 ISO-8859-7" - echo "iso88598 ISO-8859-8" - echo "iso88599 ISO-8859-9" - echo "iso885915 ISO-8859-15" - echo "roman8 HP-ROMAN8" - echo "arabic8 HP-ARABIC8" - echo "greek8 HP-GREEK8" - echo "hebrew8 HP-HEBREW8" - echo "turkish8 HP-TURKISH8" - echo "kana8 HP-KANA8" - echo "tis620 TIS-620" - echo "big5 BIG5" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "hp15CN GB2312" - #echo "ccdc ?" # what is this? - echo "SJIS SHIFT_JIS" - echo "utf8 UTF-8" - ;; - irix*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-9 ISO-8859-9" - echo "eucCN GB2312" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - ;; - osf*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "cp850 CP850" - echo "big5 BIG5" - echo "dechanyu DEC-HANYU" - echo "dechanzi GB2312" - echo "deckanji DEC-KANJI" - echo "deckorean EUC-KR" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "GBK GBK" - echo "KSC5601 CP949" - echo "sdeckanji EUC-JP" - echo "SJIS SHIFT_JIS" - echo "TACTIS TIS-620" - echo "UTF-8 UTF-8" - ;; - solaris*) - echo "646 ASCII" - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-6 ISO-8859-6" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "koi8-r KOI8-R" - echo "BIG5 BIG5" - echo "gb2312 GB2312" - echo "cns11643 EUC-TW" - echo "5601 EUC-KR" - echo "eucJP EUC-JP" - echo "PCK SHIFT_JIS" - echo "TIS620.2533 TIS-620" - #echo "sun_eu_greek ?" # what is this? - echo "UTF-8 UTF-8" - ;; - freebsd*) - # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "C ASCII" - echo "US-ASCII ASCII" - for l in la_LN lt_LN; do - echo "$l.ASCII ASCII" - done - for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ - fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ - lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do - echo "$l.ISO_8859-1 ISO-8859-1" - echo "$l.DIS_8859-15 ISO-8859-15" - done - for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do - echo "$l.ISO_8859-2 ISO-8859-2" - done - for l in la_LN lt_LT; do - echo "$l.ISO_8859-4 ISO-8859-4" - done - for l in ru_RU ru_SU; do - echo "$l.KOI8-R KOI8-R" - echo "$l.ISO_8859-5 ISO-8859-5" - echo "$l.CP866 CP866" - done - echo "uk_UA.KOI8-U KOI8-U" - echo "zh_TW.BIG5 BIG5" - echo "zh_TW.Big5 BIG5" - echo "zh_CN.EUC GB2312" - echo "ja_JP.EUC EUC-JP" - echo "ja_JP.SJIS SHIFT_JIS" - echo "ja_JP.Shift_JIS SHIFT_JIS" - echo "ko_KR.EUC EUC-KR" - ;; - beos*) - # BeOS has a single locale, and it has UTF-8 encoding. - echo "* UTF-8" - ;; - msdosdjgpp*) - # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "#" - echo "# The encodings given here may not all be correct." - echo "# If you find that the encoding given for your language and" - echo "# country is not the one your DOS machine actually uses, just" - echo "# correct it in this file, and send a mail to" - echo "# Juan Manuel Guerrero " - echo "# and Bruno Haible ." - echo "#" - echo "C ASCII" - # ISO-8859-1 languages - echo "ca CP850" - echo "ca_ES CP850" - echo "da CP865" # not CP850 ?? - echo "da_DK CP865" # not CP850 ?? - echo "de CP850" - echo "de_AT CP850" - echo "de_CH CP850" - echo "de_DE CP850" - echo "en CP850" - echo "en_AU CP850" # not CP437 ?? - echo "en_CA CP850" - echo "en_GB CP850" - echo "en_NZ CP437" - echo "en_US CP437" - echo "en_ZA CP850" # not CP437 ?? - echo "es CP850" - echo "es_AR CP850" - echo "es_BO CP850" - echo "es_CL CP850" - echo "es_CO CP850" - echo "es_CR CP850" - echo "es_CU CP850" - echo "es_DO CP850" - echo "es_EC CP850" - echo "es_ES CP850" - echo "es_GT CP850" - echo "es_HN CP850" - echo "es_MX CP850" - echo "es_NI CP850" - echo "es_PA CP850" - echo "es_PY CP850" - echo "es_PE CP850" - echo "es_SV CP850" - echo "es_UY CP850" - echo "es_VE CP850" - echo "et CP850" - echo "et_EE CP850" - echo "eu CP850" - echo "eu_ES CP850" - echo "fi CP850" - echo "fi_FI CP850" - echo "fr CP850" - echo "fr_BE CP850" - echo "fr_CA CP850" - echo "fr_CH CP850" - echo "fr_FR CP850" - echo "ga CP850" - echo "ga_IE CP850" - echo "gd CP850" - echo "gd_GB CP850" - echo "gl CP850" - echo "gl_ES CP850" - echo "id CP850" # not CP437 ?? - echo "id_ID CP850" # not CP437 ?? - echo "is CP861" # not CP850 ?? - echo "is_IS CP861" # not CP850 ?? - echo "it CP850" - echo "it_CH CP850" - echo "it_IT CP850" - echo "lt CP775" - echo "lt_LT CP775" - echo "lv CP775" - echo "lv_LV CP775" - echo "nb CP865" # not CP850 ?? - echo "nb_NO CP865" # not CP850 ?? - echo "nl CP850" - echo "nl_BE CP850" - echo "nl_NL CP850" - echo "nn CP865" # not CP850 ?? - echo "nn_NO CP865" # not CP850 ?? - echo "no CP865" # not CP850 ?? - echo "no_NO CP865" # not CP850 ?? - echo "pt CP850" - echo "pt_BR CP850" - echo "pt_PT CP850" - echo "sv CP850" - echo "sv_SE CP850" - # ISO-8859-2 languages - echo "cs CP852" - echo "cs_CZ CP852" - echo "hr CP852" - echo "hr_HR CP852" - echo "hu CP852" - echo "hu_HU CP852" - echo "pl CP852" - echo "pl_PL CP852" - echo "ro CP852" - echo "ro_RO CP852" - echo "sk CP852" - echo "sk_SK CP852" - echo "sl CP852" - echo "sl_SI CP852" - echo "sq CP852" - echo "sq_AL CP852" - echo "sr CP852" # CP852 or CP866 or CP855 ?? - echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? - # ISO-8859-3 languages - echo "mt CP850" - echo "mt_MT CP850" - # ISO-8859-5 languages - echo "be CP866" - echo "be_BE CP866" - echo "bg CP866" # not CP855 ?? - echo "bg_BG CP866" # not CP855 ?? - echo "mk CP866" # not CP855 ?? - echo "mk_MK CP866" # not CP855 ?? - echo "ru KOI8-R" # not CP866 ?? - echo "ru_RU KOI8-R" # not CP866 ?? - # ISO-8859-6 languages - echo "ar CP864" - echo "ar_AE CP864" - echo "ar_DZ CP864" - echo "ar_EG CP864" - echo "ar_IQ CP864" - echo "ar_IR CP864" - echo "ar_JO CP864" - echo "ar_KW CP864" - echo "ar_MA CP864" - echo "ar_OM CP864" - echo "ar_QA CP864" - echo "ar_SA CP864" - echo "ar_SY CP864" - # ISO-8859-7 languages - echo "el CP869" - echo "el_GR CP869" - # ISO-8859-8 languages - echo "he CP862" - echo "he_IL CP862" - # ISO-8859-9 languages - echo "tr CP857" - echo "tr_TR CP857" - # Japanese - echo "ja CP932" - echo "ja_JP CP932" - # Chinese - echo "zh_CN GBK" - echo "zh_TW CP950" # not CP938 ?? - # Korean - echo "kr CP949" # not CP934 ?? - echo "kr_KR CP949" # not CP934 ?? - # Thai - echo "th CP874" - echo "th_TH CP874" - # Other - echo "eo CP850" - echo "eo_EO CP850" - ;; -esac diff --git a/intl/dcgettext.c b/intl/dcgettext.c deleted file mode 100644 index b7c96523d..000000000 --- a/intl/dcgettext.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Implementation of the dcgettext(3) function. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCGETTEXT __dcgettext -# define DCIGETTEXT __dcigettext -#else -# define DCGETTEXT dcgettext__ -# define DCIGETTEXT dcigettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY - locale. */ -char * -DCGETTEXT (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; -{ - return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dcgettext, dcgettext); -#endif diff --git a/intl/dcigettext.c b/intl/dcigettext.c deleted file mode 100644 index 6acde195f..000000000 --- a/intl/dcigettext.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* Implementation of the internal dcigettext function. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include -#ifndef errno -extern int errno; -#endif -#ifndef __set_errno -# define __set_errno(val) errno = (val) -#endif - -#include -#include - -#include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#include - -#if defined HAVE_SYS_PARAM_H || defined _LIBC -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "hash-string.h" - -/* Thread safetyness. */ -#ifdef _LIBC -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_lock_define_initialized(CLASS, NAME) -# define __libc_lock_lock(NAME) -# define __libc_lock_unlock(NAME) -# define __libc_rwlock_define_initialized(CLASS, NAME) -# define __libc_rwlock_rdlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* Alignment of types. */ -#if defined __GNUC__ && __GNUC__ >= 2 -# define alignof(TYPE) __alignof__ (TYPE) -#else -# define alignof(TYPE) \ - ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_default_domain _nl_default_default_domain__ -# define _nl_current_default_domain _nl_current_default_domain__ -# define _nl_default_dirname _nl_default_dirname__ -# define _nl_domain_bindings _nl_domain_bindings__ -#endif - -/* Some compilers, like SunOS4 cc, don't have offsetof in . */ -#ifndef offsetof -# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# define getcwd __getcwd -# ifndef stpcpy -# define stpcpy __stpcpy -# endif -# define tfind __tfind -#else -# if !defined HAVE_GETCWD -char *getwd (); -# define getcwd(buf, max) getwd (buf) -# else -char *getcwd (); -# endif -# ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); -# endif -# ifndef HAVE_MEMPCPY -static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); -# endif -#endif - -/* Amount to increase buffer size by in each try. */ -#define PATH_INCR 32 - -/* The following is from pathmax.h. */ -/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define - PATH_MAX but might cause redefinition warnings when sys/param.h is - later included (as on MORE/BSD 4.3). */ -#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) -# include -#endif - -#ifndef _POSIX_PATH_MAX -# define _POSIX_PATH_MAX 255 -#endif - -#if !defined PATH_MAX && defined _PC_PATH_MAX -# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) -#endif - -/* Don't include sys/param.h if it already has been. */ -#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN -# include -#endif - -#if !defined PATH_MAX && defined MAXPATHLEN -# define PATH_MAX MAXPATHLEN -#endif - -#ifndef PATH_MAX -# define PATH_MAX _POSIX_PATH_MAX -#endif - -/* Pathname support. - ISSLASH(C) tests whether C is a directory separator character. - IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, - it may be concatenated to a directory pathname. - IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. - */ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ - /* Win32, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -# define HAS_DEVICE(P) \ - ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ - && (P)[1] == ':') -# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) -# define IS_PATH_WITH_DIR(P) \ - (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) -#else - /* Unix */ -# define ISSLASH(C) ((C) == '/') -# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) -# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) -#endif - -/* XPG3 defines the result of `setlocale (category, NULL)' as: - ``Directs `setlocale()' to query `category' and return the current - setting of `local'.'' - However it does not specify the exact format. Neither do SUSV2 and - ISO C 99. So we can use this feature only on selected systems (e.g. - those using GNU C Library). */ -#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2) -# define HAVE_LOCALE_NULL -#endif - -/* This is the type used for the search tree where known translations - are stored. */ -struct known_translation_t -{ - /* Domain in which to search. */ - char *domainname; - - /* The category. */ - int category; - - /* State of the catalog counter at the point the string was found. */ - int counter; - - /* Catalog where the string was found. */ - struct loaded_l10nfile *domain; - - /* And finally the translation. */ - const char *translation; - size_t translation_length; - - /* Pointer to the string in question. */ - char msgid[ZERO]; -}; - -/* Root of the search tree with known translations. We can use this - only if the system provides the `tsearch' function family. */ -#if defined HAVE_TSEARCH || defined _LIBC -# include - -static void *root; - -# ifdef _LIBC -# define tsearch __tsearch -# endif - -/* Function to compare two entries in the table of known translations. */ -static int transcmp PARAMS ((const void *p1, const void *p2)); -static int -transcmp (p1, p2) - const void *p1; - const void *p2; -{ - const struct known_translation_t *s1; - const struct known_translation_t *s2; - int result; - - s1 = (const struct known_translation_t *) p1; - s2 = (const struct known_translation_t *) p2; - - result = strcmp (s1->msgid, s2->msgid); - if (result == 0) - { - result = strcmp (s1->domainname, s2->domainname); - if (result == 0) - /* We compare the category last (though this is the cheapest - operation) since it is hopefully always the same (namely - LC_MESSAGES). */ - result = s1->category - s2->category; - } - - return result; -} -#endif - -/* Name of the default domain used for gettext(3) prior any call to - textdomain(3). The default value for this is "messages". */ -const char _nl_default_default_domain[] = "messages"; - -/* Value used as the default domain for gettext(3). */ -const char *_nl_current_default_domain = _nl_default_default_domain; - -/* Contains the default location of the message catalogs. */ -const char _nl_default_dirname[] = LOCALEDIR; - -/* List with bindings of specific domains created by bindtextdomain() - calls. */ -struct binding *_nl_domain_bindings; - -/* Prototypes for local functions. */ -static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, - unsigned long int n, - const char *translation, - size_t translation_len)) - internal_function; -static unsigned long int plural_eval PARAMS ((struct expression *pexp, - unsigned long int n)) - internal_function; -static const char *category_to_name PARAMS ((int category)) internal_function; -static const char *guess_category_value PARAMS ((int category, - const char *categoryname)) - internal_function; - - -/* For those loosing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -/* Nothing has to be done. */ -# define ADD_BLOCK(list, address) /* nothing */ -# define FREE_BLOCKS(list) /* nothing */ -#else -struct block_list -{ - void *address; - struct block_list *next; -}; -# define ADD_BLOCK(list, addr) \ - do { \ - struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ - /* If we cannot get a free block we cannot add the new element to \ - the list. */ \ - if (newp != NULL) { \ - newp->address = (addr); \ - newp->next = (list); \ - (list) = newp; \ - } \ - } while (0) -# define FREE_BLOCKS(list) \ - do { \ - while (list != NULL) { \ - struct block_list *old = list; \ - list = list->next; \ - free (old); \ - } \ - } while (0) -# undef alloca -# define alloca(size) (malloc (size)) -#endif /* have alloca */ - - -#ifdef _LIBC -/* List of blocks allocated for translations. */ -typedef struct transmem_list -{ - struct transmem_list *next; - char data[ZERO]; -} transmem_block_t; -static struct transmem_list *transmem_list; -#else -typedef unsigned char transmem_block_t; -#endif - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCIGETTEXT __dcigettext -#else -# define DCIGETTEXT dcigettext__ -#endif - -/* Lock variable to protect the global data in the gettext implementation. */ -#ifdef _LIBC -__libc_rwlock_define_initialized (, _nl_state_lock) -#endif - -/* Checking whether the binaries runs SUID must be done and glibc provides - easier methods therefore we make a difference here. */ -#ifdef _LIBC -# define ENABLE_SECURE __libc_enable_secure -# define DETERMINE_SECURE -#else -# ifndef HAVE_GETUID -# define getuid() 0 -# endif -# ifndef HAVE_GETGID -# define getgid() 0 -# endif -# ifndef HAVE_GETEUID -# define geteuid() getuid() -# endif -# ifndef HAVE_GETEGID -# define getegid() getgid() -# endif -static int enable_secure; -# define ENABLE_SECURE (enable_secure == 1) -# define DETERMINE_SECURE \ - if (enable_secure == 0) \ - { \ - if (getuid () != geteuid () || getgid () != getegid ()) \ - enable_secure = 1; \ - else \ - enable_secure = -1; \ - } -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current - CATEGORY locale and, if PLURAL is nonzero, search over string - depending on the plural form determined by N. */ -char * -DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - int plural; - unsigned long int n; - int category; -{ -#ifndef HAVE_ALLOCA - struct block_list *block_list = NULL; -#endif - struct loaded_l10nfile *domain; - struct binding *binding; - const char *categoryname; - const char *categoryvalue; - char *dirname, *xdomainname; - char *single_locale; - char *retval; - size_t retlen; - int saved_errno; -#if defined HAVE_TSEARCH || defined _LIBC - struct known_translation_t *search; - struct known_translation_t **foundp = NULL; - size_t msgid_len; -#endif - size_t domainname_len; - - /* If no real MSGID is given return NULL. */ - if (msgid1 == NULL) - return NULL; - - __libc_rwlock_rdlock (_nl_state_lock); - - /* If DOMAINNAME is NULL, we are interested in the default domain. If - CATEGORY is not LC_MESSAGES this might not make much sense but the - definition left this undefined. */ - if (domainname == NULL) - domainname = _nl_current_default_domain; - -#if defined HAVE_TSEARCH || defined _LIBC - msgid_len = strlen (msgid1) + 1; - - /* Try to find the translation among those which we found at - some time. */ - search = (struct known_translation_t *) - alloca (offsetof (struct known_translation_t, msgid) + msgid_len); - memcpy (search->msgid, msgid1, msgid_len); - search->domainname = (char *) domainname; - search->category = category; - - foundp = (struct known_translation_t **) tfind (search, &root, transcmp); - if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) - { - /* Now deal with plural. */ - if (plural) - retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, - (*foundp)->translation_length); - else - retval = (char *) (*foundp)->translation; - - __libc_rwlock_unlock (_nl_state_lock); - return retval; - } -#endif - - /* Preserve the `errno' value. */ - saved_errno = errno; - - /* See whether this is a SUID binary or not. */ - DETERMINE_SECURE; - - /* First find matching binding. */ - for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) - { - int compare = strcmp (domainname, binding->domainname); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It is not in the list. */ - binding = NULL; - break; - } - } - - if (binding == NULL) - dirname = (char *) _nl_default_dirname; - else if (IS_ABSOLUTE_PATH (binding->dirname)) - dirname = binding->dirname; - else - { - /* We have a relative path. Make it absolute now. */ - size_t dirname_len = strlen (binding->dirname) + 1; - size_t path_max; - char *ret; - - path_max = (unsigned int) PATH_MAX; - path_max += 2; /* The getcwd docs say to do this. */ - - for (;;) - { - dirname = (char *) alloca (path_max + dirname_len); - ADD_BLOCK (block_list, dirname); - - __set_errno (0); - ret = getcwd (dirname, path_max); - if (ret != NULL || errno != ERANGE) - break; - - path_max += path_max / 2; - path_max += PATH_INCR; - } - - if (ret == NULL) - { - /* We cannot get the current working directory. Don't signal an - error but simply return the default string. */ - FREE_BLOCKS (block_list); - __libc_rwlock_unlock (_nl_state_lock); - __set_errno (saved_errno); - return (plural == 0 - ? (char *) msgid1 - /* Use the Germanic plural rule. */ - : n == 1 ? (char *) msgid1 : (char *) msgid2); - } - - stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); - } - - /* Now determine the symbolic name of CATEGORY and its value. */ - categoryname = category_to_name (category); - categoryvalue = guess_category_value (category, categoryname); - - domainname_len = strlen (domainname); - xdomainname = (char *) alloca (strlen (categoryname) - + domainname_len + 5); - ADD_BLOCK (block_list, xdomainname); - - stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), - domainname, domainname_len), - ".mo"); - - /* Creating working area. */ - single_locale = (char *) alloca (strlen (categoryvalue) + 1); - ADD_BLOCK (block_list, single_locale); - - - /* Search for the given string. This is a loop because we perhaps - got an ordered list of languages to consider for the translation. */ - while (1) - { - /* Make CATEGORYVALUE point to the next element of the list. */ - while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') - ++categoryvalue; - if (categoryvalue[0] == '\0') - { - /* The whole contents of CATEGORYVALUE has been searched but - no valid entry has been found. We solve this situation - by implicitly appending a "C" entry, i.e. no translation - will take place. */ - single_locale[0] = 'C'; - single_locale[1] = '\0'; - } - else - { - char *cp = single_locale; - while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') - *cp++ = *categoryvalue++; - *cp = '\0'; - - /* When this is a SUID binary we must not allow accessing files - outside the dedicated directories. */ - if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) - /* Ingore this entry. */ - continue; - } - - /* If the current locale value is C (or POSIX) we don't load a - domain. Return the MSGID. */ - if (strcmp (single_locale, "C") == 0 - || strcmp (single_locale, "POSIX") == 0) - { - FREE_BLOCKS (block_list); - __libc_rwlock_unlock (_nl_state_lock); - __set_errno (saved_errno); - return (plural == 0 - ? (char *) msgid1 - /* Use the Germanic plural rule. */ - : n == 1 ? (char *) msgid1 : (char *) msgid2); - } - - - /* Find structure describing the message catalog matching the - DOMAINNAME and CATEGORY. */ - domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); - - if (domain != NULL) - { - retval = _nl_find_msg (domain, binding, msgid1, &retlen); - - if (retval == NULL) - { - int cnt; - - for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) - { - retval = _nl_find_msg (domain->successor[cnt], binding, - msgid1, &retlen); - - if (retval != NULL) - { - domain = domain->successor[cnt]; - break; - } - } - } - - if (retval != NULL) - { - /* Found the translation of MSGID1 in domain DOMAIN: - starting at RETVAL, RETLEN bytes. */ - FREE_BLOCKS (block_list); - __set_errno (saved_errno); -#if defined HAVE_TSEARCH || defined _LIBC - if (foundp == NULL) - { - /* Create a new entry and add it to the search tree. */ - struct known_translation_t *newp; - - newp = (struct known_translation_t *) - malloc (offsetof (struct known_translation_t, msgid) - + msgid_len + domainname_len + 1); - if (newp != NULL) - { - newp->domainname = - mempcpy (newp->msgid, msgid1, msgid_len); - memcpy (newp->domainname, domainname, domainname_len + 1); - newp->category = category; - newp->counter = _nl_msg_cat_cntr; - newp->domain = domain; - newp->translation = retval; - newp->translation_length = retlen; - - /* Insert the entry in the search tree. */ - foundp = (struct known_translation_t **) - tsearch (newp, &root, transcmp); - if (foundp == NULL - || __builtin_expect (*foundp != newp, 0)) - /* The insert failed. */ - free (newp); - } - } - else - { - /* We can update the existing entry. */ - (*foundp)->counter = _nl_msg_cat_cntr; - (*foundp)->domain = domain; - (*foundp)->translation = retval; - (*foundp)->translation_length = retlen; - } -#endif - /* Now deal with plural. */ - if (plural) - retval = plural_lookup (domain, n, retval, retlen); - - __libc_rwlock_unlock (_nl_state_lock); - return retval; - } - } - } - /* NOTREACHED */ -} - - -char * -internal_function -_nl_find_msg (domain_file, domainbinding, msgid, lengthp) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; - const char *msgid; - size_t *lengthp; -{ - struct loaded_domain *domain; - size_t act; - char *result; - size_t resultlen; - - if (domain_file->decided == 0) - _nl_load_domain (domain_file, domainbinding); - - if (domain_file->data == NULL) - return NULL; - - domain = (struct loaded_domain *) domain_file->data; - - /* Locate the MSGID and its translation. */ - if (domain->hash_size > 2 && domain->hash_tab != NULL) - { - /* Use the hashing table. */ - nls_uint32 len = strlen (msgid); - nls_uint32 hash_val = hash_string (msgid); - nls_uint32 idx = hash_val % domain->hash_size; - nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); - - while (1) - { - nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]); - - if (nstr == 0) - /* Hash table entry is empty. */ - return NULL; - - /* Compare msgid with the original string at index nstr-1. - We compare the lengths with >=, not ==, because plural entries - are represented by strings with an embedded NUL. */ - if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len - && (strcmp (msgid, - domain->data + W (domain->must_swap, - domain->orig_tab[nstr - 1].offset)) - == 0)) - { - act = nstr - 1; - goto found; - } - - if (idx >= domain->hash_size - incr) - idx -= domain->hash_size - incr; - else - idx += incr; - } - /* NOTREACHED */ - } - else - { - /* Try the default method: binary search in the sorted array of - messages. */ - size_t top, bottom; - - bottom = 0; - top = domain->nstrings; - while (bottom < top) - { - int cmp_val; - - act = (bottom + top) / 2; - cmp_val = strcmp (msgid, (domain->data - + W (domain->must_swap, - domain->orig_tab[act].offset))); - if (cmp_val < 0) - top = act; - else if (cmp_val > 0) - bottom = act + 1; - else - goto found; - } - /* No translation was found. */ - return NULL; - } - - found: - /* The translation was found at index ACT. If we have to convert the - string to use a different character set, this is the time. */ - result = ((char *) domain->data - + W (domain->must_swap, domain->trans_tab[act].offset)); - resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; - -#if defined _LIBC || HAVE_ICONV - if (domain->codeset_cntr - != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) - { - /* The domain's codeset has changed through bind_textdomain_codeset() - since the message catalog was initialized or last accessed. We - have to reinitialize the converter. */ - _nl_free_domain_conv (domain); - _nl_init_domain_conv (domain_file, domain, domainbinding); - } - - if ( -# ifdef _LIBC - domain->conv != (__gconv_t) -1 -# else -# if HAVE_ICONV - domain->conv != (iconv_t) -1 -# endif -# endif - ) - { - /* We are supposed to do a conversion. First allocate an - appropriate table with the same structure as the table - of translations in the file, where we can put the pointers - to the converted strings in. - There is a slight complication with plural entries. They - are represented by consecutive NUL terminated strings. We - handle this case by converting RESULTLEN bytes, including - NULs. */ - - if (domain->conv_tab == NULL - && ((domain->conv_tab = (char **) calloc (domain->nstrings, - sizeof (char *))) - == NULL)) - /* Mark that we didn't succeed allocating a table. */ - domain->conv_tab = (char **) -1; - - if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) - /* Nothing we can do, no more memory. */ - goto converted; - - if (domain->conv_tab[act] == NULL) - { - /* We haven't used this string so far, so it is not - translated yet. Do this now. */ - /* We use a bit more efficient memory handling. - We allocate always larger blocks which get used over - time. This is faster than many small allocations. */ - __libc_lock_define_initialized (static, lock) -# define INITIAL_BLOCK_SIZE 4080 - static unsigned char *freemem; - static size_t freemem_size; - - const unsigned char *inbuf; - unsigned char *outbuf; - int malloc_count; -# ifndef _LIBC - transmem_block_t *transmem_list = NULL; -# endif - - __libc_lock_lock (lock); - - inbuf = (const unsigned char *) result; - outbuf = freemem + sizeof (size_t); - - malloc_count = 0; - while (1) - { - transmem_block_t *newmem; -# ifdef _LIBC - size_t non_reversible; - int res; - - if (freemem_size < sizeof (size_t)) - goto resize_freemem; - - res = __gconv (domain->conv, - &inbuf, inbuf + resultlen, - &outbuf, - outbuf + freemem_size - sizeof (size_t), - &non_reversible); - - if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) - break; - - if (res != __GCONV_FULL_OUTPUT) - { - __libc_lock_unlock (lock); - goto converted; - } - - inbuf = result; -# else -# if HAVE_ICONV - const char *inptr = (const char *) inbuf; - size_t inleft = resultlen; - char *outptr = (char *) outbuf; - size_t outleft; - - if (freemem_size < sizeof (size_t)) - goto resize_freemem; - - outleft = freemem_size - sizeof (size_t); - if (iconv (domain->conv, - (ICONV_CONST char **) &inptr, &inleft, - &outptr, &outleft) - != (size_t) (-1)) - { - outbuf = (unsigned char *) outptr; - break; - } - if (errno != E2BIG) - { - __libc_lock_unlock (lock); - goto converted; - } -# endif -# endif - - resize_freemem: - /* We must allocate a new buffer or resize the old one. */ - if (malloc_count > 0) - { - ++malloc_count; - freemem_size = malloc_count * INITIAL_BLOCK_SIZE; - newmem = (transmem_block_t *) realloc (transmem_list, - freemem_size); -# ifdef _LIBC - if (newmem != NULL) - transmem_list = transmem_list->next; - else - { - struct transmem_list *old = transmem_list; - - transmem_list = transmem_list->next; - free (old); - } -# endif - } - else - { - malloc_count = 1; - freemem_size = INITIAL_BLOCK_SIZE; - newmem = (transmem_block_t *) malloc (freemem_size); - } - if (__builtin_expect (newmem == NULL, 0)) - { - freemem = NULL; - freemem_size = 0; - __libc_lock_unlock (lock); - goto converted; - } - -# ifdef _LIBC - /* Add the block to the list of blocks we have to free - at some point. */ - newmem->next = transmem_list; - transmem_list = newmem; - - freemem = newmem->data; - freemem_size -= offsetof (struct transmem_list, data); -# else - transmem_list = newmem; - freemem = newmem; -# endif - - outbuf = freemem + sizeof (size_t); - } - - /* We have now in our buffer a converted string. Put this - into the table of conversions. */ - *(size_t *) freemem = outbuf - freemem - sizeof (size_t); - domain->conv_tab[act] = (char *) freemem; - /* Shrink freemem, but keep it aligned. */ - freemem_size -= outbuf - freemem; - freemem = outbuf; - freemem += freemem_size & (alignof (size_t) - 1); - freemem_size = freemem_size & ~ (alignof (size_t) - 1); - - __libc_lock_unlock (lock); - } - - /* Now domain->conv_tab[act] contains the translation of all - the plural variants. */ - result = domain->conv_tab[act] + sizeof (size_t); - resultlen = *(size_t *) domain->conv_tab[act]; - } - - converted: - /* The result string is converted. */ - -#endif /* _LIBC || HAVE_ICONV */ - - *lengthp = resultlen; - return result; -} - - -/* Look up a plural variant. */ -static char * -internal_function -plural_lookup (domain, n, translation, translation_len) - struct loaded_l10nfile *domain; - unsigned long int n; - const char *translation; - size_t translation_len; -{ - struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; - unsigned long int index; - const char *p; - - index = plural_eval (domaindata->plural, n); - if (index >= domaindata->nplurals) - /* This should never happen. It means the plural expression and the - given maximum value do not match. */ - index = 0; - - /* Skip INDEX strings at TRANSLATION. */ - p = translation; - while (index-- > 0) - { -#ifdef _LIBC - p = __rawmemchr (p, '\0'); -#else - p = strchr (p, '\0'); -#endif - /* And skip over the NUL byte. */ - p++; - - if (p >= translation + translation_len) - /* This should never happen. It means the plural expression - evaluated to a value larger than the number of variants - available for MSGID1. */ - return (char *) translation; - } - return (char *) p; -} - - -/* Function to evaluate the plural expression and return an index value. */ -static unsigned long int -internal_function -plural_eval (pexp, n) - struct expression *pexp; - unsigned long int n; -{ - switch (pexp->nargs) - { - case 0: - switch (pexp->operation) - { - case var: - return n; - case num: - return pexp->val.num; - default: - break; - } - /* NOTREACHED */ - break; - case 1: - { - /* pexp->operation must be lnot. */ - unsigned long int arg = plural_eval (pexp->val.args[0], n); - return ! arg; - } - case 2: - { - unsigned long int leftarg = plural_eval (pexp->val.args[0], n); - if (pexp->operation == lor) - return leftarg || plural_eval (pexp->val.args[1], n); - else if (pexp->operation == land) - return leftarg && plural_eval (pexp->val.args[1], n); - else - { - unsigned long int rightarg = plural_eval (pexp->val.args[1], n); - - switch (pexp->operation) - { - case mult: - return leftarg * rightarg; - case divide: - return leftarg / rightarg; - case module: - return leftarg % rightarg; - case plus: - return leftarg + rightarg; - case minus: - return leftarg - rightarg; - case less_than: - return leftarg < rightarg; - case greater_than: - return leftarg > rightarg; - case less_or_equal: - return leftarg <= rightarg; - case greater_or_equal: - return leftarg >= rightarg; - case equal: - return leftarg == rightarg; - case not_equal: - return leftarg != rightarg; - default: - break; - } - } - /* NOTREACHED */ - break; - } - case 3: - { - /* pexp->operation must be qmop. */ - unsigned long int boolarg = plural_eval (pexp->val.args[0], n); - return plural_eval (pexp->val.args[boolarg ? 1 : 2], n); - } - } - /* NOTREACHED */ - return 0; -} - - -/* Return string representation of locale CATEGORY. */ -static const char * -internal_function -category_to_name (category) - int category; -{ - const char *retval; - - switch (category) - { -#ifdef LC_COLLATE - case LC_COLLATE: - retval = "LC_COLLATE"; - break; -#endif -#ifdef LC_CTYPE - case LC_CTYPE: - retval = "LC_CTYPE"; - break; -#endif -#ifdef LC_MONETARY - case LC_MONETARY: - retval = "LC_MONETARY"; - break; -#endif -#ifdef LC_NUMERIC - case LC_NUMERIC: - retval = "LC_NUMERIC"; - break; -#endif -#ifdef LC_TIME - case LC_TIME: - retval = "LC_TIME"; - break; -#endif -#ifdef LC_MESSAGES - case LC_MESSAGES: - retval = "LC_MESSAGES"; - break; -#endif -#ifdef LC_RESPONSE - case LC_RESPONSE: - retval = "LC_RESPONSE"; - break; -#endif -#ifdef LC_ALL - case LC_ALL: - /* This might not make sense but is perhaps better than any other - value. */ - retval = "LC_ALL"; - break; -#endif - default: - /* If you have a better idea for a default value let me know. */ - retval = "LC_XXX"; - } - - return retval; -} - -/* Guess value of current locale from value of the environment variables. */ -static const char * -internal_function -guess_category_value (category, categoryname) - int category; - const char *categoryname; -{ - const char *language; - const char *retval; - - /* The highest priority value is the `LANGUAGE' environment - variable. But we don't use the value if the currently selected - locale is the C locale. This is a GNU extension. */ - language = getenv ("LANGUAGE"); - if (language != NULL && language[0] == '\0') - language = NULL; - - /* We have to proceed with the POSIX methods of looking to `LC_ALL', - `LC_xxx', and `LANG'. On some systems this can be done by the - `setlocale' function itself. */ -#if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL) - retval = setlocale (category, NULL); -#else - /* Setting of LC_ALL overwrites all other. */ - retval = getenv ("LC_ALL"); - if (retval == NULL || retval[0] == '\0') - { - /* Next comes the name of the desired category. */ - retval = getenv (categoryname); - if (retval == NULL || retval[0] == '\0') - { - /* Last possibility is the LANG environment variable. */ - retval = getenv ("LANG"); - if (retval == NULL || retval[0] == '\0') - /* We use C as the default domain. POSIX says this is - implementation defined. */ - return "C"; - } - } -#endif - - return language != NULL && strcmp (retval, "C") != 0 ? language : retval; -} - -/* @@ begin of epilog @@ */ - -/* We don't want libintl.a to depend on any other library. So we - avoid the non-standard function stpcpy. In GNU C Library this - function is available, though. Also allow the symbol HAVE_STPCPY - to be defined. */ -#if !_LIBC && !HAVE_STPCPY -static char * -stpcpy (dest, src) - char *dest; - const char *src; -{ - while ((*dest++ = *src++) != '\0') - /* Do nothing. */ ; - return dest - 1; -} -#endif - -#if !_LIBC && !HAVE_MEMPCPY -static void * -mempcpy (dest, src, n) - void *dest; - const void *src; - size_t n; -{ - return (void *) ((char *) memcpy (dest, src, n) + n); -} -#endif - - -#ifdef _LIBC -/* If we want to free all resources we have to do some work at - program's end. */ -static void __attribute__ ((unused)) -free_mem (void) -{ - void *old; - - while (_nl_domain_bindings != NULL) - { - struct binding *oldp = _nl_domain_bindings; - _nl_domain_bindings = _nl_domain_bindings->next; - if (oldp->dirname != _nl_default_dirname) - /* Yes, this is a pointer comparison. */ - free (oldp->dirname); - free (oldp->codeset); - free (oldp); - } - - if (_nl_current_default_domain != _nl_default_default_domain) - /* Yes, again a pointer comparison. */ - free ((char *) _nl_current_default_domain); - - /* Remove the search tree with the known translations. */ - __tdestroy (root, free); - root = NULL; - - while (transmem_list != NULL) - { - old = transmem_list; - transmem_list = transmem_list->next; - free (old); - } -} - -text_set_element (__libc_subfreeres, free_mem); -#endif diff --git a/intl/dcngettext.c b/intl/dcngettext.c deleted file mode 100644 index c16af2126..000000000 --- a/intl/dcngettext.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Implementation of the dcngettext(3) function. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCNGETTEXT __dcngettext -# define DCIGETTEXT __dcigettext -#else -# define DCNGETTEXT dcngettext__ -# define DCIGETTEXT dcigettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY - locale. */ -char * -DCNGETTEXT (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; -{ - return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dcngettext, dcngettext); -#endif diff --git a/intl/dgettext.c b/intl/dgettext.c deleted file mode 100644 index 3651207a0..000000000 --- a/intl/dgettext.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Implementation of the dgettext(3) function. - Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DGETTEXT __dgettext -# define DCGETTEXT __dcgettext -#else -# define DGETTEXT dgettext__ -# define DCGETTEXT dcgettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog of the current - LC_MESSAGES locale. */ -char * -DGETTEXT (domainname, msgid) - const char *domainname; - const char *msgid; -{ - return DCGETTEXT (domainname, msgid, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dgettext, dgettext); -#endif diff --git a/intl/dngettext.c b/intl/dngettext.c deleted file mode 100644 index f214e95b4..000000000 --- a/intl/dngettext.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Implementation of the dngettext(3) function. - Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DNGETTEXT __dngettext -# define DCNGETTEXT __dcngettext -#else -# define DNGETTEXT dngettext__ -# define DCNGETTEXT dcngettext__ -#endif - -/* Look up MSGID in the DOMAINNAME message catalog of the current - LC_MESSAGES locale and skip message according to the plural form. */ -char * -DNGETTEXT (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dngettext, dngettext); -#endif diff --git a/intl/finddomain.c b/intl/finddomain.c deleted file mode 100644 index 2f103d556..000000000 --- a/intl/finddomain.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Handle list of needed message catalogs - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include -#include -#include -#include - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ -/* List of already loaded domains. */ -static struct loaded_l10nfile *_nl_loaded_domains; - - -/* Return a data structure describing the message catalog described by - the DOMAINNAME and CATEGORY parameters with respect to the currently - established bindings. */ -struct loaded_l10nfile * -internal_function -_nl_find_domain (dirname, locale, domainname, domainbinding) - const char *dirname; - char *locale; - const char *domainname; - struct binding *domainbinding; -{ - struct loaded_l10nfile *retval; - const char *language; - const char *modifier; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *special; - const char *sponsor; - const char *revision; - const char *alias_value; - int mask; - - /* LOCALE can consist of up to four recognized parts for the XPG syntax: - - language[_territory[.codeset]][@modifier] - - and six parts for the CEN syntax: - - language[_territory][+audience][+special][,[sponsor][_revision]] - - Beside the first part all of them are allowed to be missing. If - the full specified locale is not found, the less specific one are - looked for. The various parts will be stripped off according to - the following order: - (1) revision - (2) sponsor - (3) special - (4) codeset - (5) normalized codeset - (6) territory - (7) audience/modifier - */ - - /* If we have already tested for this locale entry there has to - be one data set in the list of loaded domains. */ - retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, - strlen (dirname) + 1, 0, locale, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, domainname, 0); - if (retval != NULL) - { - /* We know something about this locale. */ - int cnt; - - if (retval->decided == 0) - _nl_load_domain (retval, domainbinding); - - if (retval->data != NULL) - return retval; - - for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) - { - if (retval->successor[cnt]->decided == 0) - _nl_load_domain (retval->successor[cnt], domainbinding); - - if (retval->successor[cnt]->data != NULL) - break; - } - return cnt >= 0 ? retval : NULL; - /* NOTREACHED */ - } - - /* See whether the locale value is an alias. If yes its value - *overwrites* the alias name. No test for the original value is - done. */ - alias_value = _nl_expand_alias (locale); - if (alias_value != NULL) - { -#if defined _LIBC || defined HAVE_STRDUP - locale = strdup (alias_value); - if (locale == NULL) - return NULL; -#else - size_t len = strlen (alias_value) + 1; - locale = (char *) malloc (len); - if (locale == NULL) - return NULL; - - memcpy (locale, alias_value, len); -#endif - } - - /* Now we determine the single parts of the locale name. First - look for the language. Termination symbols are `_' and `@' if - we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ - mask = _nl_explode_name (locale, &language, &modifier, &territory, - &codeset, &normalized_codeset, &special, - &sponsor, &revision); - - /* Create all possible locale entries which might be interested in - generalization. */ - retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, - strlen (dirname) + 1, mask, language, territory, - codeset, normalized_codeset, modifier, special, - sponsor, revision, domainname, 1); - if (retval == NULL) - /* This means we are out of core. */ - return NULL; - - if (retval->decided == 0) - _nl_load_domain (retval, domainbinding); - if (retval->data == NULL) - { - int cnt; - for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) - { - if (retval->successor[cnt]->decided == 0) - _nl_load_domain (retval->successor[cnt], domainbinding); - if (retval->successor[cnt]->data != NULL) - break; - } - } - - /* The room for an alias was dynamically allocated. Free it now. */ - if (alias_value != NULL) - free (locale); - - /* The space for normalized_codeset is dynamically allocated. Free it. */ - if (mask & XPG_NORM_CODESET) - free ((void *) normalized_codeset); - - return retval; -} - - -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - struct loaded_l10nfile *runp = _nl_loaded_domains; - - while (runp != NULL) - { - struct loaded_l10nfile *here = runp; - if (runp->data != NULL) - _nl_unload_domain ((struct loaded_domain *) runp->data); - runp = runp->next; - free ((char *) here->filename); - free (here); - } -} - -text_set_element (__libc_subfreeres, free_mem); -#endif diff --git a/intl/gettext.c b/intl/gettext.c deleted file mode 100644 index 22a6c2453..000000000 --- a/intl/gettext.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Implementation of gettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#ifdef _LIBC -# define __need_NULL -# include -#else -# include /* Just for NULL. */ -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define GETTEXT __gettext -# define DCGETTEXT __dcgettext -#else -# define GETTEXT gettext__ -# define DCGETTEXT dcgettext__ -#endif - -/* Look up MSGID in the current default message catalog for the current - LC_MESSAGES locale. If not found, returns MSGID itself (the default - text). */ -char * -GETTEXT (msgid) - const char *msgid; -{ - return DCGETTEXT (NULL, msgid, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__gettext, gettext); -#endif diff --git a/intl/gettext.h b/intl/gettext.h deleted file mode 100644 index 6f5d76055..000000000 --- a/intl/gettext.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Description of GNU message catalog format: general file layout. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _GETTEXT_H -#define _GETTEXT_H 1 - -#if HAVE_LIMITS_H || _LIBC -# include -#endif - -/* @@ end of prolog @@ */ - -/* The magic number of the GNU message catalog format. */ -#define _MAGIC 0x950412de -#define _MAGIC_SWAPPED 0xde120495 - -/* Revision number of the currently used .mo (binary) file format. */ -#define MO_REVISION_NUMBER 0 - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work - when cross-compiling. */ - -#if __STDC__ -# define UINT_MAX_32_BITS 4294967295U -#else -# define UINT_MAX_32_BITS 0xFFFFFFFF -#endif - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -#ifndef UINT_MAX -# define UINT_MAX UINT_MAX_32_BITS -#endif - -#if UINT_MAX == UINT_MAX_32_BITS -typedef unsigned nls_uint32; -#else -# if USHRT_MAX == UINT_MAX_32_BITS -typedef unsigned short nls_uint32; -# else -# if ULONG_MAX == UINT_MAX_32_BITS -typedef unsigned long nls_uint32; -# else - /* The following line is intended to throw an error. Using #error is - not portable enough. */ - "Cannot determine unsigned 32-bit data type." -# endif -# endif -#endif - - -/* Header for binary .mo file format. */ -struct mo_file_header -{ - /* The magic number. */ - nls_uint32 magic; - /* The revision number of the file format. */ - nls_uint32 revision; - /* The number of strings pairs. */ - nls_uint32 nstrings; - /* Offset of table with start offsets of original strings. */ - nls_uint32 orig_tab_offset; - /* Offset of table with start offsets of translation strings. */ - nls_uint32 trans_tab_offset; - /* Size of hashing table. */ - nls_uint32 hash_tab_size; - /* Offset of first hashing entry. */ - nls_uint32 hash_tab_offset; -}; - -struct string_desc -{ - /* Length of addressed string. */ - nls_uint32 length; - /* Offset of string in file. */ - nls_uint32 offset; -}; - -/* @@ begin of epilog @@ */ - -#endif /* gettext.h */ diff --git a/intl/gettextP.h b/intl/gettextP.h deleted file mode 100644 index 43de1cd47..000000000 --- a/intl/gettextP.h +++ /dev/null @@ -1,252 +0,0 @@ -/* Header describing internals of libintl library. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _GETTEXTP_H -#define _GETTEXTP_H - -#include /* Get size_t. */ - -#ifdef _LIBC -# include "../iconv/gconv_int.h" -#else -# if HAVE_ICONV -# include -# endif -#endif - -#include "loadinfo.h" - -#include "gettext.h" /* Get nls_uint32. */ - -/* @@ end of prolog @@ */ - -#ifndef PARAMS -# if __STDC__ -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* Tell the compiler when a conditional or integer expression is - almost always true or almost always false. */ -#ifndef HAVE_BUILTIN_EXPECT -# define __builtin_expect(expr, val) (expr) -#endif - -#ifndef W -# define W(flag, data) ((flag) ? SWAP (data) : (data)) -#endif - - -#ifdef _LIBC -# include -# define SWAP(i) bswap_32 (i) -#else -static inline nls_uint32 -SWAP (i) - nls_uint32 i; -{ - return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); -} -#endif - - -/* This is the representation of the expressions to determine the - plural form. */ -struct expression -{ - int nargs; /* Number of arguments. */ - enum operator - { - /* Without arguments: */ - var, /* The variable "n". */ - num, /* Decimal number. */ - /* Unary operators: */ - lnot, /* Logical NOT. */ - /* Binary operators: */ - mult, /* Multiplication. */ - divide, /* Division. */ - module, /* Module operation. */ - plus, /* Addition. */ - minus, /* Subtraction. */ - less_than, /* Comparison. */ - greater_than, /* Comparison. */ - less_or_equal, /* Comparison. */ - greater_or_equal, /* Comparison. */ - equal, /* Comparision for equality. */ - not_equal, /* Comparision for inequality. */ - land, /* Logical AND. */ - lor, /* Logical OR. */ - /* Ternary operators: */ - qmop /* Question mark operator. */ - } operation; - union - { - unsigned long int num; /* Number value for `num'. */ - struct expression *args[3]; /* Up to three arguments. */ - } val; -}; - -/* This is the data structure to pass information to the parser and get - the result in a thread-safe way. */ -struct parse_args -{ - const char *cp; - struct expression *res; -}; - - -/* The representation of an opened message catalog. */ -struct loaded_domain -{ - const char *data; - int use_mmap; - size_t mmap_size; - int must_swap; - nls_uint32 nstrings; - struct string_desc *orig_tab; - struct string_desc *trans_tab; - nls_uint32 hash_size; - nls_uint32 *hash_tab; - int codeset_cntr; -#ifdef _LIBC - __gconv_t conv; -#else -# if HAVE_ICONV - iconv_t conv; -# endif -#endif - char **conv_tab; - - struct expression *plural; - unsigned long int nplurals; -}; - -/* We want to allocate a string at the end of the struct. But ISO C - doesn't allow zero sized arrays. */ -#ifdef __GNUC__ -# define ZERO 0 -#else -# define ZERO 1 -#endif - -/* A set of settings bound to a message domain. Used to store settings - from bindtextdomain() and bind_textdomain_codeset(). */ -struct binding -{ - struct binding *next; - char *dirname; - int codeset_cntr; /* Incremented each time codeset changes. */ - char *codeset; - char domainname[ZERO]; -}; - -/* A counter which is incremented each time some previous translations - become invalid. - This variable is part of the external ABI of the GNU libintl. */ -extern int _nl_msg_cat_cntr; - -struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, - char *__locale, - const char *__domainname, - struct binding *__domainbinding)) - internal_function; -void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain, - struct binding *__domainbinding)) - internal_function; -void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) - internal_function; -const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file, - struct loaded_domain *__domain, - struct binding *__domainbinding)) - internal_function; -void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain)) - internal_function; - -char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file, - struct binding *domainbinding, - const char *msgid, size_t *lengthp)) - internal_function; - -#ifdef _LIBC -extern char *__gettext PARAMS ((const char *__msgid)); -extern char *__dgettext PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *__dcgettext PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *__dngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int n)); -extern char *__dcngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n, int __category)); -extern char *__dcigettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *__textdomain PARAMS ((const char *__domainname)); -extern char *__bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); -#else -extern char *gettext__ PARAMS ((const char *__msgid)); -extern char *dgettext__ PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *dcgettext__ PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *ngettext__ PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *dngettext__ PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *dcngettext__ PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n, int __category)); -extern char *dcigettext__ PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *textdomain__ PARAMS ((const char *__domainname)); -extern char *bindtextdomain__ PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *bind_textdomain_codeset__ PARAMS ((const char *__domainname, - const char *__codeset)); -#endif - -#ifdef _LIBC -extern void __gettext_free_exp PARAMS ((struct expression *exp)) - internal_function; -extern int __gettextparse PARAMS ((void *arg)); -#else -extern void gettext_free_exp__ PARAMS ((struct expression *exp)) - internal_function; -extern int gettextparse__ PARAMS ((void *arg)); -#endif - -/* @@ begin of epilog @@ */ - -#endif /* gettextP.h */ diff --git a/intl/hash-string.h b/intl/hash-string.h deleted file mode 100644 index ccb7acca6..000000000 --- a/intl/hash-string.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Description of GNU message catalog format: string hashing function. - Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 of prolog @@ */ - -#ifndef PARAMS -# if __STDC__ -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif -#endif - -/* We assume to have `unsigned long int' value with at least 32 bits. */ -#define HASHWORDBITS 32 - - -/* Defines the so called `hashpjw' function by P.J. Weinberger - [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, - 1986, 1987 Bell Telephone Laboratories, Inc.] */ -static unsigned long int hash_string PARAMS ((const char *__str_param)); - -static inline unsigned long int -hash_string (str_param) - const char *str_param; -{ - unsigned long int hval, g; - const char *str = str_param; - - /* Compute the hash value for the given string. */ - hval = 0; - while (*str != '\0') - { - hval <<= 4; - hval += (unsigned long int) *str++; - g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); - if (g != 0) - { - hval ^= g >> (HASHWORDBITS - 8); - hval ^= g; - } - } - return hval; -} diff --git a/intl/intl-compat.c b/intl/intl-compat.c deleted file mode 100644 index 0a06ce947..000000000 --- a/intl/intl-compat.c +++ /dev/null @@ -1,166 +0,0 @@ -/* intl-compat.c - Stub functions to call gettext functions from GNU gettext - Library. - Copyright (C) 1995, 2000, 2001 Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include "libgnuintl.h" -#include "gettextP.h" - -/* @@ end of prolog @@ */ - -/* This file redirects the gettext functions (without prefix or suffix) to - those defined in the included GNU gettext library (with "__" suffix). - It is compiled into libintl when the included GNU gettext library is - configured --with-included-gettext. - - This redirection works also in the case that the system C library or - the system libintl library contain gettext/textdomain/... functions. - If it didn't, we would need to add preprocessor level redirections to - libgnuintl.h of the following form: - -# define gettext gettext__ -# define dgettext dgettext__ -# define dcgettext dcgettext__ -# define ngettext ngettext__ -# define dngettext dngettext__ -# define dcngettext dcngettext__ -# define textdomain textdomain__ -# define bindtextdomain bindtextdomain__ -# define bind_textdomain_codeset bind_textdomain_codeset__ - - How does this redirection work? There are two cases. - A. When libintl.a is linked into an executable, it works because - functions defined in the executable always override functions in - the shared libraries. - B. When libintl.so is used, it works because - 1. those systems defining gettext/textdomain/... in the C library - (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer) are - ELF systems and define these symbols as weak, thus explicitly - letting other shared libraries override it. - 2. those systems defining gettext/textdomain/... in a standalone - libintl.so library (namely, Solaris 2.3 and newer) have this - shared library in /usr/lib, and the linker will search /usr/lib - *after* the directory where the GNU gettext library is installed. - - A third case, namely when libintl.a is linked into a shared library - whose name is not libintl.so, is not supported. In this case, on - Solaris, when -lintl precedes the linker option for the shared library - containing GNU gettext, the system's gettext would indeed override - the GNU gettext. Anyone doing this kind of stuff must be clever enough - to 1. compile libintl.a with -fPIC, 2. remove -lintl from his linker - command line. */ - - -#undef gettext -#undef dgettext -#undef dcgettext -#undef ngettext -#undef dngettext -#undef dcngettext -#undef textdomain -#undef bindtextdomain -#undef bind_textdomain_codeset - - -char * -gettext (msgid) - const char *msgid; -{ - return gettext__ (msgid); -} - - -char * -dgettext (domainname, msgid) - const char *domainname; - const char *msgid; -{ - return dgettext__ (domainname, msgid); -} - - -char * -dcgettext (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; -{ - return dcgettext__ (domainname, msgid, category); -} - - -char * -ngettext (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return ngettext__ (msgid1, msgid2, n); -} - - -char * -dngettext (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return dngettext__ (domainname, msgid1, msgid2, n); -} - - -char * -dcngettext (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; -{ - return dcngettext__ (domainname, msgid1, msgid2, n, category); -} - - -char * -textdomain (domainname) - const char *domainname; -{ - return textdomain__ (domainname); -} - - -char * -bindtextdomain (domainname, dirname) - const char *domainname; - const char *dirname; -{ - return bindtextdomain__ (domainname, dirname); -} - - -char * -bind_textdomain_codeset (domainname, codeset) - const char *domainname; - const char *codeset; -{ - return bind_textdomain_codeset__ (domainname, codeset); -} diff --git a/intl/l10nflist.c b/intl/l10nflist.c deleted file mode 100644 index 533e94be8..000000000 --- a/intl/l10nflist.c +++ /dev/null @@ -1,405 +0,0 @@ -/* Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Contributed by Ulrich Drepper , 1995. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for stpcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#if defined _LIBC || defined HAVE_ARGZ_H -# include -#endif -#include -#include -#include - -#include "loadinfo.h" - -/* On some strange systems still no definition of NULL is found. Sigh! */ -#ifndef NULL -# if defined __STDC__ && __STDC__ -# define NULL ((void *) 0) -# else -# define NULL 0 -# endif -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# ifndef stpcpy -# define stpcpy(dest, src) __stpcpy(dest, src) -# endif -#else -# ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); -# endif -#endif - -/* Define function which are usually not available. */ - -#if !defined _LIBC && !defined HAVE___ARGZ_COUNT -/* Returns the number of strings in ARGZ. */ -static size_t argz_count__ PARAMS ((const char *argz, size_t len)); - -static size_t -argz_count__ (argz, len) - const char *argz; - size_t len; -{ - size_t count = 0; - while (len > 0) - { - size_t part_len = strlen (argz); - argz += part_len + 1; - len -= part_len + 1; - count++; - } - return count; -} -# undef __argz_count -# define __argz_count(argz, len) argz_count__ (argz, len) -#endif /* !_LIBC && !HAVE___ARGZ_COUNT */ - -#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY -/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's - except the last into the character SEP. */ -static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); - -static void -argz_stringify__ (argz, len, sep) - char *argz; - size_t len; - int sep; -{ - while (len > 0) - { - size_t part_len = strlen (argz); - argz += part_len; - len -= part_len + 1; - if (len > 0) - *argz++ = sep; - } -} -# undef __argz_stringify -# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep) -#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ - -#if !defined _LIBC && !defined HAVE___ARGZ_NEXT -static char *argz_next__ PARAMS ((char *argz, size_t argz_len, - const char *entry)); - -static char * -argz_next__ (argz, argz_len, entry) - char *argz; - size_t argz_len; - const char *entry; -{ - if (entry) - { - if (entry < argz + argz_len) - entry = strchr (entry, '\0') + 1; - - return entry >= argz + argz_len ? NULL : (char *) entry; - } - else - if (argz_len > 0) - return argz; - else - return 0; -} -# undef __argz_next -# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry) -#endif /* !_LIBC && !HAVE___ARGZ_NEXT */ - - -/* Return number of bits set in X. */ -static int pop PARAMS ((int x)); - -static inline int -pop (x) - int x; -{ - /* We assume that no more than 16 bits are used. */ - x = ((x & ~0x5555) >> 1) + (x & 0x5555); - x = ((x & ~0x3333) >> 2) + (x & 0x3333); - x = ((x >> 4) + x) & 0x0f0f; - x = ((x >> 8) + x) & 0xff; - - return x; -} - - -struct loaded_l10nfile * -_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, - territory, codeset, normalized_codeset, modifier, special, - sponsor, revision, filename, do_allocate) - struct loaded_l10nfile **l10nfile_list; - const char *dirlist; - size_t dirlist_len; - int mask; - const char *language; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *modifier; - const char *special; - const char *sponsor; - const char *revision; - const char *filename; - int do_allocate; -{ - char *abs_filename; - struct loaded_l10nfile *last = NULL; - struct loaded_l10nfile *retval; - char *cp; - size_t entries; - int cnt; - - /* Allocate room for the full file name. */ - abs_filename = (char *) malloc (dirlist_len - + strlen (language) - + ((mask & TERRITORY) != 0 - ? strlen (territory) + 1 : 0) - + ((mask & XPG_CODESET) != 0 - ? strlen (codeset) + 1 : 0) - + ((mask & XPG_NORM_CODESET) != 0 - ? strlen (normalized_codeset) + 1 : 0) - + (((mask & XPG_MODIFIER) != 0 - || (mask & CEN_AUDIENCE) != 0) - ? strlen (modifier) + 1 : 0) - + ((mask & CEN_SPECIAL) != 0 - ? strlen (special) + 1 : 0) - + (((mask & CEN_SPONSOR) != 0 - || (mask & CEN_REVISION) != 0) - ? (1 + ((mask & CEN_SPONSOR) != 0 - ? strlen (sponsor) + 1 : 0) - + ((mask & CEN_REVISION) != 0 - ? strlen (revision) + 1 : 0)) : 0) - + 1 + strlen (filename) + 1); - - if (abs_filename == NULL) - return NULL; - - retval = NULL; - last = NULL; - - /* Construct file name. */ - memcpy (abs_filename, dirlist, dirlist_len); - __argz_stringify (abs_filename, dirlist_len, PATH_SEPARATOR); - cp = abs_filename + (dirlist_len - 1); - *cp++ = '/'; - cp = stpcpy (cp, language); - - if ((mask & TERRITORY) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, territory); - } - if ((mask & XPG_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, codeset); - } - if ((mask & XPG_NORM_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, normalized_codeset); - } - if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) - { - /* This component can be part of both syntaces but has different - leading characters. For CEN we use `+', else `@'. */ - *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; - cp = stpcpy (cp, modifier); - } - if ((mask & CEN_SPECIAL) != 0) - { - *cp++ = '+'; - cp = stpcpy (cp, special); - } - if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) - { - *cp++ = ','; - if ((mask & CEN_SPONSOR) != 0) - cp = stpcpy (cp, sponsor); - if ((mask & CEN_REVISION) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, revision); - } - } - - *cp++ = '/'; - stpcpy (cp, filename); - - /* Look in list of already loaded domains whether it is already - available. */ - last = NULL; - for (retval = *l10nfile_list; retval != NULL; retval = retval->next) - if (retval->filename != NULL) - { - int compare = strcmp (retval->filename, abs_filename); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It's not in the list. */ - retval = NULL; - break; - } - - last = retval; - } - - if (retval != NULL || do_allocate == 0) - { - free (abs_filename); - return retval; - } - - retval = (struct loaded_l10nfile *) - malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len) - * (1 << pop (mask)) - * sizeof (struct loaded_l10nfile *))); - if (retval == NULL) - return NULL; - - retval->filename = abs_filename; - retval->decided = (__argz_count (dirlist, dirlist_len) != 1 - || ((mask & XPG_CODESET) != 0 - && (mask & XPG_NORM_CODESET) != 0)); - retval->data = NULL; - - if (last == NULL) - { - retval->next = *l10nfile_list; - *l10nfile_list = retval; - } - else - { - retval->next = last->next; - last->next = retval; - } - - entries = 0; - /* If the DIRLIST is a real list the RETVAL entry corresponds not to - a real file. So we have to use the DIRLIST separation mechanism - of the inner loop. */ - cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask; - for (; cnt >= 0; --cnt) - if ((cnt & ~mask) == 0 - && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) - && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) - { - /* Iterate over all elements of the DIRLIST. */ - char *dir = NULL; - - while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) - != NULL) - retval->successor[entries++] - = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt, - language, territory, codeset, - normalized_codeset, modifier, special, - sponsor, revision, filename, 1); - } - retval->successor[entries] = NULL; - - return retval; -} - -/* Normalize codeset name. There is no standard for the codeset - names. Normalization allows the user to use any of the common - names. The return value is dynamically allocated and has to be - freed by the caller. */ -const char * -_nl_normalize_codeset (codeset, name_len) - const char *codeset; - size_t name_len; -{ - int len = 0; - int only_digit = 1; - char *retval; - char *wp; - size_t cnt; - - for (cnt = 0; cnt < name_len; ++cnt) - if (isalnum (codeset[cnt])) - { - ++len; - - if (isalpha (codeset[cnt])) - only_digit = 0; - } - - retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); - - if (retval != NULL) - { - if (only_digit) - wp = stpcpy (retval, "iso"); - else - wp = retval; - - for (cnt = 0; cnt < name_len; ++cnt) - if (isalpha (codeset[cnt])) - *wp++ = tolower (codeset[cnt]); - else if (isdigit (codeset[cnt])) - *wp++ = codeset[cnt]; - - *wp = '\0'; - } - - return (const char *) retval; -} - - -/* @@ begin of epilog @@ */ - -/* We don't want libintl.a to depend on any other library. So we - avoid the non-standard function stpcpy. In GNU C Library this - function is available, though. Also allow the symbol HAVE_STPCPY - to be defined. */ -#if !_LIBC && !HAVE_STPCPY -static char * -stpcpy (dest, src) - char *dest; - const char *src; -{ - while ((*dest++ = *src++) != '\0') - /* Do nothing. */ ; - return dest - 1; -} -#endif diff --git a/intl/libgettext.h b/intl/libgettext.h deleted file mode 100644 index c5be54a80..000000000 --- a/intl/libgettext.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -#else - -# define gettext(Msgid) (Msgid) -# define dgettext(Domainname, Msgid) (Msgid) -# define dcgettext(Domainname, Msgid, Category) (Msgid) -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define textdomain(Domainname) ((char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) ((char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) ((char *) (Codeset)) - -#endif - -/* For automatical extraction of messages sometimes no real - translation is needed. Instead the string itself is the result. */ -#define gettext_noop(Str) (Str) - -#endif /* _LIBGETTEXT_H */ diff --git a/intl/loadinfo.h b/intl/loadinfo.h deleted file mode 100644 index b8612607b..000000000 --- a/intl/loadinfo.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (C) 1996-1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 1996. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LOADINFO_H -#define _LOADINFO_H 1 - -#ifndef PARAMS -# if __STDC__ -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* Tell the compiler when a conditional or integer expression is - almost always true or almost always false. */ -#ifndef HAVE_BUILTIN_EXPECT -# define __builtin_expect(expr, val) (expr) -#endif - -/* Separator in PATH like lists of pathnames. */ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ - /* Win32, OS/2, DOS */ -# define PATH_SEPARATOR ';' -#else - /* Unix */ -# define PATH_SEPARATOR ':' -#endif - -/* Encoding of locale name parts. */ -#define CEN_REVISION 1 -#define CEN_SPONSOR 2 -#define CEN_SPECIAL 4 -#define XPG_NORM_CODESET 8 -#define XPG_CODESET 16 -#define TERRITORY 32 -#define CEN_AUDIENCE 64 -#define XPG_MODIFIER 128 - -#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) -#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) - - -struct loaded_l10nfile -{ - const char *filename; - int decided; - - const void *data; - - struct loaded_l10nfile *next; - struct loaded_l10nfile *successor[1]; -}; - - -/* Normalize codeset name. There is no standard for the codeset - names. Normalization allows the user to use any of the common - names. The return value is dynamically allocated and has to be - freed by the caller. */ -extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, - size_t name_len)); - -extern struct loaded_l10nfile * -_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, - const char *dirlist, size_t dirlist_len, int mask, - const char *language, const char *territory, - const char *codeset, - const char *normalized_codeset, - const char *modifier, const char *special, - const char *sponsor, const char *revision, - const char *filename, int do_allocate)); - - -extern const char *_nl_expand_alias PARAMS ((const char *name)); - -/* normalized_codeset is dynamically allocated and has to be freed by - the caller. */ -extern int _nl_explode_name PARAMS ((char *name, const char **language, - const char **modifier, - const char **territory, - const char **codeset, - const char **normalized_codeset, - const char **special, - const char **sponsor, - const char **revision)); - -extern char *_nl_find_language PARAMS ((const char *name)); - -#endif /* loadinfo.h */ diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c deleted file mode 100644 index f99ebee3a..000000000 --- a/intl/loadmsgcat.c +++ /dev/null @@ -1,567 +0,0 @@ -/* Load needed message catalogs. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include -#include - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#ifdef _LIBC -# include -# include -#endif - -#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ - || (defined _LIBC && defined _POSIX_MAPPED_FILES) -# include -# undef HAVE_MMAP -# define HAVE_MMAP 1 -#else -# undef HAVE_MMAP -#endif - -#include "gettext.h" -#include "gettextP.h" - -#ifdef _LIBC -# include "../locale/localeinfo.h" -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ISO C functions. This is required by the standard - because some ISO C functions will require linking with this object - file and the name space must not be polluted. */ -# define open __open -# define close __close -# define read __read -# define mmap __mmap -# define munmap __munmap -#endif - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define PLURAL_PARSE __gettextparse -#else -# define PLURAL_PARSE gettextparse__ -#endif - -/* For those losing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -# define freea(p) /* nothing */ -#else -# define alloca(n) malloc (n) -# define freea(p) free (p) -#endif - -/* For systems that distinguish between text and binary I/O. - O_BINARY is usually declared in . */ -#if !defined O_BINARY && defined _O_BINARY - /* For MSC-compatible compilers. */ -# define O_BINARY _O_BINARY -# define O_TEXT _O_TEXT -#endif -#ifdef __BEOS__ - /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ -# undef O_BINARY -# undef O_TEXT -#endif -/* On reasonable systems, binary I/O is the default. */ -#ifndef O_BINARY -# define O_BINARY 0 -#endif - -/* We need a sign, whether a new catalog was loaded, which can be associated - with all translations. This is important if the translations are - cached by one of GCC's features. */ -int _nl_msg_cat_cntr; - -#if (defined __GNUC__ && !defined __APPLE_CC__) \ - || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - -/* These structs are the constant expression for the germanic plural - form determination. It represents the expression "n != 1". */ -static const struct expression plvar = -{ - .nargs = 0, - .operation = var, -}; -static const struct expression plone = -{ - .nargs = 0, - .operation = num, - .val = - { - .num = 1 - } -}; -static struct expression germanic_plural = -{ - .nargs = 2, - .operation = not_equal, - .val = - { - .args = - { - [0] = (struct expression *) &plvar, - [1] = (struct expression *) &plone - } - } -}; - -# define INIT_GERMANIC_PLURAL() - -#else - -/* For compilers without support for ISO C 99 struct/union initializers: - Initialization at run-time. */ - -static struct expression plvar; -static struct expression plone; -static struct expression germanic_plural; - -static void -init_germanic_plural () -{ - if (plone.val.num == 0) - { - plvar.nargs = 0; - plvar.operation = var; - - plone.nargs = 0; - plone.operation = num; - plone.val.num = 1; - - germanic_plural.nargs = 2; - germanic_plural.operation = not_equal; - germanic_plural.val.args[0] = &plvar; - germanic_plural.val.args[1] = &plone; - } -} - -# define INIT_GERMANIC_PLURAL() init_germanic_plural () - -#endif - - -/* Initialize the codeset dependent parts of an opened message catalog. - Return the header entry. */ -const char * -internal_function -_nl_init_domain_conv (domain_file, domain, domainbinding) - struct loaded_l10nfile *domain_file; - struct loaded_domain *domain; - struct binding *domainbinding; -{ - /* Find out about the character set the file is encoded with. - This can be found (in textual form) in the entry "". If this - entry does not exist or if this does not contain the `charset=' - information, we will assume the charset matches the one the - current locale and we don't have to perform any conversion. */ - char *nullentry; - size_t nullentrylen; - - /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ - domain->codeset_cntr = - (domainbinding != NULL ? domainbinding->codeset_cntr : 0); -#ifdef _LIBC - domain->conv = (__gconv_t) -1; -#else -# if HAVE_ICONV - domain->conv = (iconv_t) -1; -# endif -#endif - domain->conv_tab = NULL; - - /* Get the header entry. */ - nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); - - if (nullentry != NULL) - { -#if defined _LIBC || HAVE_ICONV - const char *charsetstr; - - charsetstr = strstr (nullentry, "charset="); - if (charsetstr != NULL) - { - size_t len; - char *charset; - const char *outcharset; - - charsetstr += strlen ("charset="); - len = strcspn (charsetstr, " \t\n"); - - charset = (char *) alloca (len + 1); -# if defined _LIBC || HAVE_MEMPCPY - *((char *) mempcpy (charset, charsetstr, len)) = '\0'; -# else - memcpy (charset, charsetstr, len); - charset[len] = '\0'; -# endif - - /* The output charset should normally be determined by the - locale. But sometimes the locale is not used or not correctly - set up, so we provide a possibility for the user to override - this. Moreover, the value specified through - bind_textdomain_codeset overrides both. */ - if (domainbinding != NULL && domainbinding->codeset != NULL) - outcharset = domainbinding->codeset; - else - { - outcharset = getenv ("OUTPUT_CHARSET"); - if (outcharset == NULL || outcharset[0] == '\0') - { -# ifdef _LIBC - outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string; -# else -# if HAVE_ICONV - extern const char *locale_charset (void); - outcharset = locale_charset (); -# endif -# endif - } - } - -# ifdef _LIBC - /* We always want to use transliteration. */ - outcharset = norm_add_slashes (outcharset, "TRANSLIT"); - charset = norm_add_slashes (charset, NULL); - if (__gconv_open (outcharset, charset, &domain->conv, - GCONV_AVOID_NOCONV) - != __GCONV_OK) - domain->conv = (__gconv_t) -1; -# else -# if HAVE_ICONV - /* When using GNU libiconv, we want to use transliteration. */ -# if _LIBICONV_VERSION >= 0x0105 - len = strlen (outcharset); - { - char *tmp = (char *) alloca (len + 10 + 1); - memcpy (tmp, outcharset, len); - memcpy (tmp + len, "//TRANSLIT", 10 + 1); - outcharset = tmp; - } -# endif - domain->conv = iconv_open (outcharset, charset); -# if _LIBICONV_VERSION >= 0x0105 - freea (outcharset); -# endif -# endif -# endif - - freea (charset); - } -#endif /* _LIBC || HAVE_ICONV */ - } - - return nullentry; -} - -/* Frees the codeset dependent parts of an opened message catalog. */ -void -internal_function -_nl_free_domain_conv (domain) - struct loaded_domain *domain; -{ - if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) - free (domain->conv_tab); - -#ifdef _LIBC - if (domain->conv != (__gconv_t) -1) - __gconv_close (domain->conv); -#else -# if HAVE_ICONV - if (domain->conv != (iconv_t) -1) - iconv_close (domain->conv); -# endif -#endif -} - -/* Load the message catalogs specified by FILENAME. If it is no valid - message catalog do nothing. */ -void -internal_function -_nl_load_domain (domain_file, domainbinding) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; -{ - int fd; - size_t size; -#ifdef _LIBC - struct stat64 st; -#else - struct stat st; -#endif - struct mo_file_header *data = (struct mo_file_header *) -1; - int use_mmap = 0; - struct loaded_domain *domain; - const char *nullentry; - - domain_file->decided = 1; - domain_file->data = NULL; - - /* Note that it would be useless to store domainbinding in domain_file - because domainbinding might be == NULL now but != NULL later (after - a call to bind_textdomain_codeset). */ - - /* If the record does not represent a valid locale the FILENAME - might be NULL. This can happen when according to the given - specification the locale file name is different for XPG and CEN - syntax. */ - if (domain_file->filename == NULL) - return; - - /* Try to open the addressed file. */ - fd = open (domain_file->filename, O_RDONLY | O_BINARY); - if (fd == -1) - return; - - /* We must know about the size of the file. */ - if ( -#ifdef _LIBC - __builtin_expect (fstat64 (fd, &st) != 0, 0) -#else - __builtin_expect (fstat (fd, &st) != 0, 0) -#endif - || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0) - || __builtin_expect (size < sizeof (struct mo_file_header), 0)) - { - /* Something went wrong. */ - close (fd); - return; - } - -#ifdef HAVE_MMAP - /* Now we are ready to load the file. If mmap() is available we try - this first. If not available or it failed we try to load it. */ - data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, - MAP_PRIVATE, fd, 0); - - if (__builtin_expect (data != (struct mo_file_header *) -1, 1)) - { - /* mmap() call was successful. */ - close (fd); - use_mmap = 1; - } -#endif - - /* If the data is not yet available (i.e. mmap'ed) we try to load - it manually. */ - if (data == (struct mo_file_header *) -1) - { - size_t to_read; - char *read_ptr; - - data = (struct mo_file_header *) malloc (size); - if (data == NULL) - return; - - to_read = size; - read_ptr = (char *) data; - do - { - long int nb = (long int) read (fd, read_ptr, to_read); - if (nb <= 0) - { -#ifdef EINTR - if (nb == -1 && errno == EINTR) - continue; -#endif - close (fd); - return; - } - read_ptr += nb; - to_read -= nb; - } - while (to_read > 0); - - close (fd); - } - - /* Using the magic number we can test whether it really is a message - catalog file. */ - if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED, - 0)) - { - /* The magic number is wrong: not a message catalog file. */ -#ifdef HAVE_MMAP - if (use_mmap) - munmap ((caddr_t) data, size); - else -#endif - free (data); - return; - } - - domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); - if (domain == NULL) - return; - domain_file->data = domain; - - domain->data = (char *) data; - domain->use_mmap = use_mmap; - domain->mmap_size = size; - domain->must_swap = data->magic != _MAGIC; - - /* Fill in the information about the available tables. */ - switch (W (domain->must_swap, data->revision)) - { - case 0: - domain->nstrings = W (domain->must_swap, data->nstrings); - domain->orig_tab = (struct string_desc *) - ((char *) data + W (domain->must_swap, data->orig_tab_offset)); - domain->trans_tab = (struct string_desc *) - ((char *) data + W (domain->must_swap, data->trans_tab_offset)); - domain->hash_size = W (domain->must_swap, data->hash_tab_size); - domain->hash_tab = (nls_uint32 *) - ((char *) data + W (domain->must_swap, data->hash_tab_offset)); - break; - default: - /* This is an invalid revision. */ -#ifdef HAVE_MMAP - if (use_mmap) - munmap ((caddr_t) data, size); - else -#endif - free (data); - free (domain); - domain_file->data = NULL; - return; - } - - /* Now initialize the character set converter from the character set - the file is encoded with (found in the header entry) to the domain's - specified character set or the locale's character set. */ - nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); - - /* Also look for a plural specification. */ - if (nullentry != NULL) - { - const char *plural; - const char *nplurals; - - plural = strstr (nullentry, "plural="); - nplurals = strstr (nullentry, "nplurals="); - if (plural == NULL || nplurals == NULL) - goto no_plural; - else - { - /* First get the number. */ - char *endp; - unsigned long int n; - struct parse_args args; - - nplurals += 9; - while (*nplurals != '\0' && isspace (*nplurals)) - ++nplurals; -#if defined HAVE_STRTOUL || defined _LIBC - n = strtoul (nplurals, &endp, 10); -#else - for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++) - n = n * 10 + (*endp - '0'); -#endif - domain->nplurals = n; - if (nplurals == endp) - goto no_plural; - - /* Due to the restrictions bison imposes onto the interface of the - scanner function we have to put the input string and the result - passed up from the parser into the same structure which address - is passed down to the parser. */ - plural += 7; - args.cp = plural; - if (PLURAL_PARSE (&args) != 0) - goto no_plural; - domain->plural = args.res; - } - } - else - { - /* By default we are using the Germanic form: singular form only - for `one', the plural form otherwise. Yes, this is also what - English is using since English is a Germanic language. */ - no_plural: - INIT_GERMANIC_PLURAL (); - domain->plural = &germanic_plural; - domain->nplurals = 2; - } -} - - -#ifdef _LIBC -void -internal_function -_nl_unload_domain (domain) - struct loaded_domain *domain; -{ - if (domain->plural != &germanic_plural) - __gettext_free_exp (domain->plural); - - _nl_free_domain_conv (domain); - -# ifdef _POSIX_MAPPED_FILES - if (domain->use_mmap) - munmap ((caddr_t) domain->data, domain->mmap_size); - else -# endif /* _POSIX_MAPPED_FILES */ - free ((void *) domain->data); - - free (domain); -} -#endif diff --git a/intl/localcharset.c b/intl/localcharset.c deleted file mode 100644 index 61f8f3e85..000000000 --- a/intl/localcharset.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Determine a canonical name for the current locale's character encoding. - - Copyright (C) 2000-2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Written by Bruno Haible . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#if HAVE_STDDEF_H -# include -#endif - -#include -#if HAVE_STRING_H -# include -#else -# include -#endif -#if HAVE_STDLIB_H -# include -#endif - -#if defined _WIN32 || defined __WIN32__ -# undef WIN32 /* avoid warning on mingw32 */ -# define WIN32 -#endif - -#ifndef WIN32 -# if HAVE_LANGINFO_CODESET -# include -# else -# if HAVE_SETLOCALE -# include -# endif -# endif -#else /* WIN32 */ -# define WIN32_LEAN_AND_MEAN -# include -#endif - -#ifndef DIRECTORY_SEPARATOR -# define DIRECTORY_SEPARATOR '/' -#endif - -#ifndef ISSLASH -# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) -#endif - -/* The following static variable is declared 'volatile' to avoid a - possible multithread problem in the function get_charset_aliases. If we - are running in a threaded environment, and if two threads initialize - 'charset_aliases' simultaneously, both will produce the same value, - and everything will be ok if the two assignments to 'charset_aliases' - are atomic. But I don't know what will happen if the two assignments mix. */ -#if __STDC__ != 1 -# define volatile /* empty */ -#endif -/* Pointer to the contents of the charset.alias file, if it has already been - read, else NULL. Its format is: - ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ -static const char * volatile charset_aliases; - -/* Return a pointer to the contents of the charset.alias file. */ -static const char * -get_charset_aliases () -{ - const char *cp; - - cp = charset_aliases; - if (cp == NULL) - { -#ifndef WIN32 - FILE *fp; - const char *dir = LIBDIR; - const char *base = "charset.alias"; - char *file_name; - - /* Concatenate dir and base into freshly allocated file_name. */ - { - size_t dir_len = strlen (dir); - size_t base_len = strlen (base); - int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); - file_name = (char *) malloc (dir_len + add_slash + base_len + 1); - if (file_name != NULL) - { - memcpy (file_name, dir, dir_len); - if (add_slash) - file_name[dir_len] = DIRECTORY_SEPARATOR; - memcpy (file_name + dir_len + add_slash, base, base_len + 1); - } - } - - if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) - /* Out of memory or file not found, treat it as empty. */ - cp = ""; - else - { - /* Parse the file's contents. */ - int c; - char buf1[50+1]; - char buf2[50+1]; - char *res_ptr = NULL; - size_t res_size = 0; - size_t l1, l2; - - for (;;) - { - c = getc (fp); - if (c == EOF) - break; - if (c == '\n' || c == ' ' || c == '\t') - continue; - if (c == '#') - { - /* Skip comment, to end of line. */ - do - c = getc (fp); - while (!(c == EOF || c == '\n')); - if (c == EOF) - break; - continue; - } - ungetc (c, fp); - if (fscanf(fp, "%50s %50s", buf1, buf2) < 2) - break; - l1 = strlen (buf1); - l2 = strlen (buf2); - if (res_size == 0) - { - res_size = l1 + 1 + l2 + 1; - res_ptr = malloc (res_size + 1); - } - else - { - res_size += l1 + 1 + l2 + 1; - res_ptr = realloc (res_ptr, res_size + 1); - } - if (res_ptr == NULL) - { - /* Out of memory. */ - res_size = 0; - break; - } - strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); - strcpy (res_ptr + res_size - (l2 + 1), buf2); - } - fclose (fp); - if (res_size == 0) - cp = ""; - else - { - *(res_ptr + res_size) = '\0'; - cp = res_ptr; - } - } - - if (file_name != NULL) - free (file_name); - -#else /* WIN32 */ - - /* To avoid the troubles of installing a separate file in the same - directory as the DLL and of retrieving the DLL's directory at - runtime, simply inline the aliases here. */ - - cp = "CP936" "\0" "GBK" "\0" - "CP1361" "\0" "JOHAB" "\0"; -#endif - - charset_aliases = cp; - } - - return cp; -} - -/* Determine the current locale's character encoding, and canonicalize it - into one of the canonical names listed in config.charset. - The result must not be freed; it is statically allocated. - If the canonical name cannot be determined, the result is a non-canonical - name. */ - -#ifdef STATIC -STATIC -#endif -const char * -locale_charset () -{ - const char *codeset; - const char *aliases; - -#ifndef WIN32 - -# if HAVE_LANGINFO_CODESET - - /* Most systems support nl_langinfo (CODESET) nowadays. */ - codeset = nl_langinfo (CODESET); - -# else - - /* On old systems which lack it, use setlocale or getenv. */ - const char *locale = NULL; - - /* But most old systems don't have a complete set of locales. Some - (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't - use setlocale here; it would return "C" when it doesn't support the - locale name the user has set. */ -# if HAVE_SETLOCALE && 0 - locale = setlocale (LC_CTYPE, NULL); -# endif - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - } - - /* On some old systems, one used to set locale = "iso8859_1". On others, - you set it to "language_COUNTRY.charset". In any case, we resolve it - through the charset.alias file. */ - codeset = locale; - -# endif - -#else /* WIN32 */ - - static char buf[2 + 10 + 1]; - - /* Win32 has a function returning the locale's codepage as a number. */ - sprintf (buf, "CP%u", GetACP ()); - codeset = buf; - -#endif - - if (codeset == NULL) - /* The canonical name cannot be determined. */ - codeset = ""; - - /* Resolve alias. */ - for (aliases = get_charset_aliases (); - *aliases != '\0'; - aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) - if (strcmp (codeset, aliases) == 0 - || (aliases[0] == '*' && aliases[1] == '\0')) - { - codeset = aliases + strlen (aliases) + 1; - break; - } - - return codeset; -} diff --git a/intl/localealias.c b/intl/localealias.c deleted file mode 100644 index 91e7acc9c..000000000 --- a/intl/localealias.c +++ /dev/null @@ -1,404 +0,0 @@ -/* Handle aliases for locale names. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include - -#include -#if !HAVE_STRCHR && !defined _LIBC -# ifndef strchr -# define strchr index -# endif -#endif - -#include "gettextP.h" - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# define strcasecmp __strcasecmp - -# ifndef mempcpy -# define mempcpy __mempcpy -# endif -# define HAVE_MEMPCPY 1 - -/* We need locking here since we can be called from different places. */ -# include - -__libc_lock_define_initialized (static, lock); -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* For those losing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -# define freea(p) /* nothing */ -#else -# define alloca(n) malloc (n) -# define freea(p) free (p) -#endif - -#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED -# undef fgets -# define fgets(buf, len, s) fgets_unlocked (buf, len, s) -#endif -#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED -# undef feof -# define feof(s) feof_unlocked (s) -#endif - - -struct alias_map -{ - const char *alias; - const char *value; -}; - - -static char *string_space; -static size_t string_space_act; -static size_t string_space_max; -static struct alias_map *map; -static size_t nmap; -static size_t maxmap; - - -/* Prototypes for local functions. */ -static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) - internal_function; -static int extend_alias_table PARAMS ((void)); -static int alias_compare PARAMS ((const struct alias_map *map1, - const struct alias_map *map2)); - - -const char * -_nl_expand_alias (name) - const char *name; -{ - static const char *locale_alias_path = LOCALE_ALIAS_PATH; - struct alias_map *retval; - const char *result = NULL; - size_t added; - -#ifdef _LIBC - __libc_lock_lock (lock); -#endif - - do - { - struct alias_map item; - - item.alias = name; - - if (nmap > 0) - retval = (struct alias_map *) bsearch (&item, map, nmap, - sizeof (struct alias_map), - (int (*) PARAMS ((const void *, - const void *)) - ) alias_compare); - else - retval = NULL; - - /* We really found an alias. Return the value. */ - if (retval != NULL) - { - result = retval->value; - break; - } - - /* Perhaps we can find another alias file. */ - added = 0; - while (added == 0 && locale_alias_path[0] != '\0') - { - const char *start; - - while (locale_alias_path[0] == PATH_SEPARATOR) - ++locale_alias_path; - start = locale_alias_path; - - while (locale_alias_path[0] != '\0' - && locale_alias_path[0] != PATH_SEPARATOR) - ++locale_alias_path; - - if (start < locale_alias_path) - added = read_alias_file (start, locale_alias_path - start); - } - } - while (added != 0); - -#ifdef _LIBC - __libc_lock_unlock (lock); -#endif - - return result; -} - - -static size_t -internal_function -read_alias_file (fname, fname_len) - const char *fname; - int fname_len; -{ - FILE *fp; - char *full_fname; - size_t added; - static const char aliasfile[] = "/locale.alias"; - - full_fname = (char *) alloca (fname_len + sizeof aliasfile); -#ifdef HAVE_MEMPCPY - mempcpy (mempcpy (full_fname, fname, fname_len), - aliasfile, sizeof aliasfile); -#else - memcpy (full_fname, fname, fname_len); - memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); -#endif - - fp = fopen (full_fname, "r"); - freea (full_fname); - if (fp == NULL) - return 0; - - added = 0; - while (!feof (fp)) - { - /* It is a reasonable approach to use a fix buffer here because - a) we are only interested in the first two fields - b) these fields must be usable as file names and so must not - be that long - */ - char buf[BUFSIZ]; - char *alias; - char *value; - char *cp; - - if (fgets (buf, sizeof buf, fp) == NULL) - /* EOF reached. */ - break; - - /* Possibly not the whole line fits into the buffer. Ignore - the rest of the line. */ - if (strchr (buf, '\n') == NULL) - { - char altbuf[BUFSIZ]; - do - if (fgets (altbuf, sizeof altbuf, fp) == NULL) - /* Make sure the inner loop will be left. The outer loop - will exit at the `feof' test. */ - break; - while (strchr (altbuf, '\n') == NULL); - } - - cp = buf; - /* Ignore leading white space. */ - while (isspace (cp[0])) - ++cp; - - /* A leading '#' signals a comment line. */ - if (cp[0] != '\0' && cp[0] != '#') - { - alias = cp++; - while (cp[0] != '\0' && !isspace (cp[0])) - ++cp; - /* Terminate alias name. */ - if (cp[0] != '\0') - *cp++ = '\0'; - - /* Now look for the beginning of the value. */ - while (isspace (cp[0])) - ++cp; - - if (cp[0] != '\0') - { - size_t alias_len; - size_t value_len; - - value = cp++; - while (cp[0] != '\0' && !isspace (cp[0])) - ++cp; - /* Terminate value. */ - if (cp[0] == '\n') - { - /* This has to be done to make the following test - for the end of line possible. We are looking for - the terminating '\n' which do not overwrite here. */ - *cp++ = '\0'; - *cp = '\n'; - } - else if (cp[0] != '\0') - *cp++ = '\0'; - - if (nmap >= maxmap) - if (__builtin_expect (extend_alias_table (), 0)) - return added; - - alias_len = strlen (alias) + 1; - value_len = strlen (value) + 1; - - if (string_space_act + alias_len + value_len > string_space_max) - { - /* Increase size of memory pool. */ - size_t new_size = (string_space_max - + (alias_len + value_len > 1024 - ? alias_len + value_len : 1024)); - char *new_pool = (char *) realloc (string_space, new_size); - if (new_pool == NULL) - return added; - - if (__builtin_expect (string_space != new_pool, 0)) - { - size_t i; - - for (i = 0; i < nmap; i++) - { - map[i].alias += new_pool - string_space; - map[i].value += new_pool - string_space; - } - } - - string_space = new_pool; - string_space_max = new_size; - } - - map[nmap].alias = memcpy (&string_space[string_space_act], - alias, alias_len); - string_space_act += alias_len; - - map[nmap].value = memcpy (&string_space[string_space_act], - value, value_len); - string_space_act += value_len; - - ++nmap; - ++added; - } - } - } - - /* Should we test for ferror()? I think we have to silently ignore - errors. --drepper */ - fclose (fp); - - if (added > 0) - qsort (map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, const void *))) alias_compare); - - return added; -} - - -static int -extend_alias_table () -{ - size_t new_size; - struct alias_map *new_map; - - new_size = maxmap == 0 ? 100 : 2 * maxmap; - new_map = (struct alias_map *) realloc (map, (new_size - * sizeof (struct alias_map))); - if (new_map == NULL) - /* Simply don't extend: we don't have any more core. */ - return -1; - - map = new_map; - maxmap = new_size; - return 0; -} - - -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - if (string_space != NULL) - free (string_space); - if (map != NULL) - free (map); -} -text_set_element (__libc_subfreeres, free_mem); -#endif - - -static int -alias_compare (map1, map2) - const struct alias_map *map1; - const struct alias_map *map2; -{ -#if defined _LIBC || defined HAVE_STRCASECMP - return strcasecmp (map1->alias, map2->alias); -#else - const unsigned char *p1 = (const unsigned char *) map1->alias; - const unsigned char *p2 = (const unsigned char *) map2->alias; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - /* I know this seems to be odd but the tolower() function in - some systems libc cannot handle nonalpha characters. */ - c1 = isupper (*p1) ? tolower (*p1) : *p1; - c2 = isupper (*p2) ? tolower (*p2) : *p2; - if (c1 == '\0') - break; - ++p1; - ++p2; - } - while (c1 == c2); - - return c1 - c2; -#endif -} diff --git a/intl/ngettext.c b/intl/ngettext.c deleted file mode 100644 index fb3ec5a91..000000000 --- a/intl/ngettext.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Implementation of ngettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#ifdef _LIBC -# define __need_NULL -# include -#else -# include /* Just for NULL. */ -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -#include - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define NGETTEXT __ngettext -# define DCNGETTEXT __dcngettext -#else -# define NGETTEXT ngettext__ -# define DCNGETTEXT dcngettext__ -#endif - -/* Look up MSGID in the current default message catalog for the current - LC_MESSAGES locale. If not found, returns MSGID itself (the default - text). */ -char * -NGETTEXT (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__ngettext, ngettext); -#endif diff --git a/intl/plural.c b/intl/plural.c deleted file mode 100644 index 640d43cc5..000000000 --- a/intl/plural.c +++ /dev/null @@ -1,1326 +0,0 @@ - -/* A Bison parser, made from plural.y - by GNU Bison version 1.28 */ - -#define YYBISON 1 /* Identify Bison output. */ - -#define yyparse __gettextparse -#define yylex __gettextlex -#define yyerror __gettexterror -#define yylval __gettextlval -#define yychar __gettextchar -#define yydebug __gettextdebug -#define yynerrs __gettextnerrs -#define EQUOP2 257 -#define CMPOP2 258 -#define ADDOP2 259 -#define MULOP2 260 -#define NUMBER 261 - -#line 1 "plural.y" - -/* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 2000. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* The bison generated parser uses alloca. AIX 3 forces us to put this - declaration at the beginning of the file. The declaration in bison's - skeleton file comes too late. This must come before - because may include arbitrary system headers. */ -#if defined _AIX && !defined __GNUC__ - #pragma alloca -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "gettextP.h" - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define FREE_EXPRESSION __gettext_free_exp -#else -# define FREE_EXPRESSION gettext_free_exp__ -# define __gettextparse gettextparse__ -#endif - -#define YYLEX_PARAM &((struct parse_args *) arg)->cp -#define YYPARSE_PARAM arg - -#line 53 "plural.y" -typedef union { - unsigned long int num; - enum operator op; - struct expression *exp; -} YYSTYPE; -#line 59 "plural.y" - -/* Prototypes for local functions. */ -static struct expression *new_exp PARAMS ((int nargs, enum operator op, - struct expression * const *args)); -static inline struct expression *new_exp_0 PARAMS ((enum operator op)); -static inline struct expression *new_exp_1 PARAMS ((enum operator op, - struct expression *right)); -static struct expression *new_exp_2 PARAMS ((enum operator op, - struct expression *left, - struct expression *right)); -static inline struct expression *new_exp_3 PARAMS ((enum operator op, - struct expression *bexp, - struct expression *tbranch, - struct expression *fbranch)); -static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); -static void yyerror PARAMS ((const char *str)); - -/* Allocation of expressions. */ - -static struct expression * -new_exp (nargs, op, args) - int nargs; - enum operator op; - struct expression * const *args; -{ - int i; - struct expression *newp; - - /* If any of the argument could not be malloc'ed, just return NULL. */ - for (i = nargs - 1; i >= 0; i--) - if (args[i] == NULL) - goto fail; - - /* Allocate a new expression. */ - newp = (struct expression *) malloc (sizeof (*newp)); - if (newp != NULL) - { - newp->nargs = nargs; - newp->operation = op; - for (i = nargs - 1; i >= 0; i--) - newp->val.args[i] = args[i]; - return newp; - } - - fail: - for (i = nargs - 1; i >= 0; i--) - FREE_EXPRESSION (args[i]); - - return NULL; -} - -static inline struct expression * -new_exp_0 (op) - enum operator op; -{ - return new_exp (0, op, NULL); -} - -static inline struct expression * -new_exp_1 (op, right) - enum operator op; - struct expression *right; -{ - struct expression *args[1]; - - args[0] = right; - return new_exp (1, op, args); -} - -static struct expression * -new_exp_2 (op, left, right) - enum operator op; - struct expression *left; - struct expression *right; -{ - struct expression *args[2]; - - args[0] = left; - args[1] = right; - return new_exp (2, op, args); -} - -static inline struct expression * -new_exp_3 (op, bexp, tbranch, fbranch) - enum operator op; - struct expression *bexp; - struct expression *tbranch; - struct expression *fbranch; -{ - struct expression *args[3]; - - args[0] = bexp; - args[1] = tbranch; - args[2] = fbranch; - return new_exp (3, op, args); -} - -#include - -#ifndef __cplusplus -#ifndef __STDC__ -#define const -#endif -#endif - - - -#define YYFINAL 27 -#define YYFLAG -32768 -#define YYNTBASE 16 - -#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18) - -static const char yytranslate[] = { 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 10, 2, 2, 2, 2, 5, 2, 14, - 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 12, 2, 2, - 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 6, 7, 8, 9, - 11 -}; - -#if YYDEBUG != 0 -static const short yyprhs[] = { 0, - 0, 2, 8, 12, 16, 20, 24, 28, 32, 35, - 37, 39 -}; - -static const short yyrhs[] = { 17, - 0, 17, 3, 17, 12, 17, 0, 17, 4, 17, - 0, 17, 5, 17, 0, 17, 6, 17, 0, 17, - 7, 17, 0, 17, 8, 17, 0, 17, 9, 17, - 0, 10, 17, 0, 13, 0, 11, 0, 14, 17, - 15, 0 -}; - -#endif - -#if YYDEBUG != 0 -static const short yyrline[] = { 0, - 178, 186, 190, 194, 198, 202, 206, 210, 214, 218, - 222, 227 -}; -#endif - - -#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) - -static const char * const yytname[] = { "$","error","$undefined.","'?'","'|'", -"'&'","EQUOP2","CMPOP2","ADDOP2","MULOP2","'!'","NUMBER","':'","'n'","'('","')'", -"start","exp", NULL -}; -#endif - -static const short yyr1[] = { 0, - 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 17, 17 -}; - -static const short yyr2[] = { 0, - 1, 5, 3, 3, 3, 3, 3, 3, 2, 1, - 1, 3 -}; - -static const short yydefact[] = { 0, - 0, 11, 10, 0, 1, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 12, 0, 3, 4, 5, 6, - 7, 8, 0, 2, 0, 0, 0 -}; - -static const short yydefgoto[] = { 25, - 5 -}; - -static const short yypact[] = { -9, - -9,-32768,-32768, -9, 34,-32768, 11, -9, -9, -9, - -9, -9, -9, -9,-32768, 24, 39, 43, 16, 26, - -3,-32768, -9, 34, 21, 53,-32768 -}; - -static const short yypgoto[] = {-32768, - -1 -}; - - -#define YYLAST 53 - - -static const short yytable[] = { 6, - 1, 2, 7, 3, 4, 14, 16, 17, 18, 19, - 20, 21, 22, 8, 9, 10, 11, 12, 13, 14, - 26, 24, 12, 13, 14, 15, 8, 9, 10, 11, - 12, 13, 14, 13, 14, 23, 8, 9, 10, 11, - 12, 13, 14, 10, 11, 12, 13, 14, 11, 12, - 13, 14, 27 -}; - -static const short yycheck[] = { 1, - 10, 11, 4, 13, 14, 9, 8, 9, 10, 11, - 12, 13, 14, 3, 4, 5, 6, 7, 8, 9, - 0, 23, 7, 8, 9, 15, 3, 4, 5, 6, - 7, 8, 9, 8, 9, 12, 3, 4, 5, 6, - 7, 8, 9, 5, 6, 7, 8, 9, 6, 7, - 8, 9, 0 -}; -#define YYPURE 1 - -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/home/haible/gnu/arch/linuxlibc6/share/bison.simple" -/* This file comes from bison-1.28. */ - -/* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. - - 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, 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. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* This is the parser code that is written into each bison parser - when the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include -#endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ -#endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ - -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca -#else -#define YYSTACK_ALLOC malloc -#endif - -/* Note: there must be only one dollar sign in this file. - It is replaced by the list of actions, each action - as one case of the switch. */ - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 -#define YYEOF 0 -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. - This remains here temporarily to ease the - transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ -#define YYFAIL goto yyerrlab -#define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(token, value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { yychar = (token), yylval = (value); \ - yychar1 = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ - goto yybackup; \ - } \ - else \ - { yyerror ("syntax error: cannot back up"); YYERROR; } \ -while (0) - -#define YYTERROR 1 -#define YYERRCODE 256 - -#ifndef YYPURE -#define YYLEX yylex() -#endif - -#ifdef YYPURE -#ifdef YYLSP_NEEDED -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval, &yylloc) -#endif -#else /* not YYLSP_NEEDED */ -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval) -#endif -#endif /* not YYLSP_NEEDED */ -#endif - -/* If nonreentrant, generate the variables here */ - -#ifndef YYPURE - -int yychar; /* the lookahead symbol */ -YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ - -#ifdef YYLSP_NEEDED -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ -#endif - -int yynerrs; /* number of parse errors so far */ -#endif /* not YYPURE */ - -#if YYDEBUG != 0 -int yydebug; /* nonzero means print parse trace */ -/* Since this is uninitialized, it does not stop multiple parsers - from coexisting. */ -#endif - -/* YYINITDEPTH indicates the initial size of the parser's stacks */ - -#ifndef YYINITDEPTH -#define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH is the maximum size the stacks can grow to - (effective only if the built-in stack extension method is used). */ - -#if YYMAXDEPTH == 0 -#undef YYMAXDEPTH -#endif - -#ifndef YYMAXDEPTH -#define YYMAXDEPTH 10000 -#endif - -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ - -#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) -#else /* not GNU C or C++ */ -#ifndef __cplusplus - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (to, from, count) - char *to; - char *from; - unsigned int count; -{ - register char *f = from; - register char *t = to; - register int i = count; - - while (i-- > 0) - *t++ = *f++; -} - -#else /* __cplusplus */ - -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (char *to, char *from, unsigned int count) -{ - register char *t = to; - register char *f = from; - register int i = count; - - while (i-- > 0) - *t++ = *f++; -} - -#endif -#endif - -#line 217 "/home/haible/gnu/arch/linuxlibc6/share/bison.simple" - -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ - -#ifdef YYPARSE_PARAM -#ifdef __cplusplus -#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* not __cplusplus */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -#endif /* not __cplusplus */ -#else /* not YYPARSE_PARAM */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* not YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -#ifdef YYPARSE_PARAM -int yyparse (void *); -#else -int yyparse (void); -#endif -#endif - -int -yyparse(YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL -{ - register int yystate; - register int yyn; - register short *yyssp; - register YYSTYPE *yyvsp; - int yyerrstatus; /* number of tokens to shift before error messages enabled */ - int yychar1 = 0; /* lookahead token as an internal (translated) token number */ - - short yyssa[YYINITDEPTH]; /* the state stack */ - YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ - - short *yyss = yyssa; /* refer to the stacks thru separate pointers */ - YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ - -#ifdef YYLSP_NEEDED - YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else -#define YYPOPSTACK (yyvsp--, yyssp--) -#endif - - int yystacksize = YYINITDEPTH; - int yyfree_stacks = 0; - -#ifdef YYPURE - int yychar; - YYSTYPE yylval; - int yynerrs; -#ifdef YYLSP_NEEDED - YYLTYPE yylloc; -#endif -#endif - - YYSTYPE yyval; /* the variable used to return */ - /* semantic values from the action */ - /* routines */ - - int yylen; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Starting parse\n"); -#endif - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss - 1; - yyvsp = yyvs; -#ifdef YYLSP_NEEDED - yylsp = yyls; -#endif - -/* Push a new state, which is found in yystate . */ -/* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. */ -yynewstate: - - *++yyssp = yystate; - - if (yyssp >= yyss + yystacksize - 1) - { - /* Give user a chance to reallocate the stack */ - /* Use copies of these so that the &'s don't force the real ones into memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; -#ifdef YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; -#endif - - /* Get the current used size of the three stacks, in elements. */ - int size = yyssp - yyss + 1; - -#ifdef yyoverflow - /* Each stack pointer address is followed by the size of - the data in use in that stack, in bytes. */ -#ifdef YYLSP_NEEDED - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yyls1, size * sizeof (*yylsp), - &yystacksize); -#else - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yystacksize); -#endif - - yyss = yyss1; yyvs = yyvs1; -#ifdef YYLSP_NEEDED - yyls = yyls1; -#endif -#else /* no yyoverflow */ - /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - { - yyerror("parser stack overflow"); - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 2; - } - yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) - yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); -#ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); -#endif -#endif /* no yyoverflow */ - - yyssp = yyss + size - 1; - yyvsp = yyvs + size - 1; -#ifdef YYLSP_NEEDED - yylsp = yyls + size - 1; -#endif - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Stack size increased to %d\n", yystacksize); -#endif - - if (yyssp >= yyss + yystacksize - 1) - YYABORT; - } - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Entering state %d\n", yystate); -#endif - - goto yybackup; - yybackup: - -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ - - /* First try to decide what to do without reference to lookahead token. */ - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - - if (yychar == YYEMPTY) - { -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Reading a token: "); -#endif - yychar = YYLEX; - } - - /* Convert token to internal form (in yychar1) for indexing tables with */ - - if (yychar <= 0) /* This means end of input. */ - { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Now at end of input.\n"); -#endif - } - else - { - yychar1 = YYTRANSLATE(yychar); - -#if YYDEBUG != 0 - if (yydebug) - { - fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise meaning - of a token, for further debugging info. */ -#ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -#endif - fprintf (stderr, ")\n"); - } -#endif - } - - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) - goto yydefault; - - yyn = yytable[yyn]; - - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ - - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrlab; - - if (yyn == YYFINAL) - YYACCEPT; - - /* Shift the lookahead token. */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); -#endif - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - /* count tokens shifted since error; after three, turn off error status. */ - if (yyerrstatus) yyerrstatus--; - - yystate = yyn; - goto yynewstate; - -/* Do the default action for the current state. */ -yydefault: - - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - -/* Do a reduction. yyn is the number of a rule to reduce with. */ -yyreduce: - yylen = yyr2[yyn]; - if (yylen > 0) - yyval = yyvsp[1-yylen]; /* implement default value of the action */ - -#if YYDEBUG != 0 - if (yydebug) - { - int i; - - fprintf (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) - fprintf (stderr, "%s ", yytname[yyrhs[i]]); - fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif - - - switch (yyn) { - -case 1: -#line 179 "plural.y" -{ - if (yyvsp[0].exp == NULL) - YYABORT; - ((struct parse_args *) arg)->res = yyvsp[0].exp; - ; - break;} -case 2: -#line 187 "plural.y" -{ - yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 3: -#line 191 "plural.y" -{ - yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 4: -#line 195 "plural.y" -{ - yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 5: -#line 199 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 6: -#line 203 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 7: -#line 207 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 8: -#line 211 "plural.y" -{ - yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); - ; - break;} -case 9: -#line 215 "plural.y" -{ - yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); - ; - break;} -case 10: -#line 219 "plural.y" -{ - yyval.exp = new_exp_0 (var); - ; - break;} -case 11: -#line 223 "plural.y" -{ - if ((yyval.exp = new_exp_0 (num)) != NULL) - yyval.exp->val.num = yyvsp[0].num; - ; - break;} -case 12: -#line 228 "plural.y" -{ - yyval.exp = yyvsp[-1].exp; - ; - break;} -} - /* the action file gets copied in in place of this dollarsign */ -#line 543 "/home/haible/gnu/arch/linuxlibc6/share/bison.simple" - - yyvsp -= yylen; - yyssp -= yylen; -#ifdef YYLSP_NEEDED - yylsp -= yylen; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - - *++yyvsp = yyval; - -#ifdef YYLSP_NEEDED - yylsp++; - if (yylen == 0) - { - yylsp->first_line = yylloc.first_line; - yylsp->first_column = yylloc.first_column; - yylsp->last_line = (yylsp-1)->last_line; - yylsp->last_column = (yylsp-1)->last_column; - yylsp->text = 0; - } - else - { - yylsp->last_line = (yylsp+yylen-1)->last_line; - yylsp->last_column = (yylsp+yylen-1)->last_column; - } -#endif - - /* Now "shift" the result of the reduction. - Determine what state that goes to, - based on the state we popped back to - and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTBASE]; - - goto yynewstate; - -yyerrlab: /* here on detecting error */ - - if (! yyerrstatus) - /* If not already recovering from an error, report this error. */ - { - ++yynerrs; - -#ifdef YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (yyn > YYFLAG && yyn < YYLAST) - { - int size = 0; - char *msg; - int x, count; - - count = 0; - /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - size += strlen(yytname[x]) + 15, count++; - msg = (char *) malloc(size + 15); - if (msg != 0) - { - strcpy(msg, "parse error"); - - if (count < 5) - { - count = 0; - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - { - strcat(msg, count == 0 ? ", expecting `" : " or `"); - strcat(msg, yytname[x]); - strcat(msg, "'"); - count++; - } - } - yyerror(msg); - free(msg); - } - else - yyerror ("parse error; also virtual memory exceeded"); - } - else -#endif /* YYERROR_VERBOSE */ - yyerror("parse error"); - } - - goto yyerrlab1; -yyerrlab1: /* here on error raised explicitly by an action */ - - if (yyerrstatus == 3) - { - /* if just tried and failed to reuse lookahead token after an error, discard it. */ - - /* return failure if at end of input */ - if (yychar == YYEOF) - YYABORT; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); -#endif - - yychar = YYEMPTY; - } - - /* Else will try to reuse lookahead token - after shifting the error token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ - - goto yyerrhandle; - -yyerrdefault: /* current state does not do anything special for the error token. */ - -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ - if (yyn) goto yydefault; -#endif - -yyerrpop: /* pop the current state because it cannot handle the error token */ - - if (yyssp == yyss) YYABORT; - yyvsp--; - yystate = *--yyssp; -#ifdef YYLSP_NEEDED - yylsp--; -#endif - -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "Error: state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - -yyerrhandle: - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; - - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; - - yyn = yytable[yyn]; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrpop; - - if (yyn == YYFINAL) - YYACCEPT; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting error token, "); -#endif - - *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - yystate = yyn; - goto yynewstate; - - yyacceptlab: - /* YYACCEPT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 0; - - yyabortlab: - /* YYABORT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 1; -} -#line 233 "plural.y" - - -void -internal_function -FREE_EXPRESSION (exp) - struct expression *exp; -{ - if (exp == NULL) - return; - - /* Handle the recursive case. */ - switch (exp->nargs) - { - case 3: - FREE_EXPRESSION (exp->val.args[2]); - /* FALLTHROUGH */ - case 2: - FREE_EXPRESSION (exp->val.args[1]); - /* FALLTHROUGH */ - case 1: - FREE_EXPRESSION (exp->val.args[0]); - /* FALLTHROUGH */ - default: - break; - } - - free (exp); -} - - -static int -yylex (lval, pexp) - YYSTYPE *lval; - const char **pexp; -{ - const char *exp = *pexp; - int result; - - while (1) - { - if (exp[0] == '\0') - { - *pexp = exp; - return YYEOF; - } - - if (exp[0] != ' ' && exp[0] != '\t') - break; - - ++exp; - } - - result = *exp++; - switch (result) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - unsigned long int n = result - '0'; - while (exp[0] >= '0' && exp[0] <= '9') - { - n *= 10; - n += exp[0] - '0'; - ++exp; - } - lval->num = n; - result = NUMBER; - } - break; - - case '=': - if (exp[0] == '=') - { - ++exp; - lval->op = equal; - result = EQUOP2; - } - else - result = YYERRCODE; - break; - - case '!': - if (exp[0] == '=') - { - ++exp; - lval->op = not_equal; - result = EQUOP2; - } - break; - - case '&': - case '|': - if (exp[0] == result) - ++exp; - else - result = YYERRCODE; - break; - - case '<': - if (exp[0] == '=') - { - ++exp; - lval->op = less_or_equal; - } - else - lval->op = less_than; - result = CMPOP2; - break; - - case '>': - if (exp[0] == '=') - { - ++exp; - lval->op = greater_or_equal; - } - else - lval->op = greater_than; - result = CMPOP2; - break; - - case '*': - lval->op = mult; - result = MULOP2; - break; - - case '/': - lval->op = divide; - result = MULOP2; - break; - - case '%': - lval->op = module; - result = MULOP2; - break; - - case '+': - lval->op = plus; - result = ADDOP2; - break; - - case '-': - lval->op = minus; - result = ADDOP2; - break; - - case 'n': - case '?': - case ':': - case '(': - case ')': - /* Nothing, just return the character. */ - break; - - case ';': - case '\n': - case '\0': - /* Be safe and let the user call this function again. */ - --exp; - result = YYEOF; - break; - - default: - result = YYERRCODE; -#if YYDEBUG != 0 - --exp; -#endif - break; - } - - *pexp = exp; - - return result; -} - - -static void -yyerror (str) - const char *str; -{ - /* Do nothing. We don't print error messages here. */ -} diff --git a/intl/plural.y b/intl/plural.y deleted file mode 100644 index be049a6d4..000000000 --- a/intl/plural.y +++ /dev/null @@ -1,413 +0,0 @@ -%{ -/* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 2000. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* The bison generated parser uses alloca. AIX 3 forces us to put this - declaration at the beginning of the file. The declaration in bison's - skeleton file comes too late. This must come before - because may include arbitrary system headers. */ -#if defined _AIX && !defined __GNUC__ - #pragma alloca -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "gettextP.h" - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define FREE_EXPRESSION __gettext_free_exp -#else -# define FREE_EXPRESSION gettext_free_exp__ -# define __gettextparse gettextparse__ -#endif - -#define YYLEX_PARAM &((struct parse_args *) arg)->cp -#define YYPARSE_PARAM arg -%} -%pure_parser -%expect 10 - -%union { - unsigned long int num; - enum operator op; - struct expression *exp; -} - -%{ -/* Prototypes for local functions. */ -static struct expression *new_exp PARAMS ((int nargs, enum operator op, - struct expression * const *args)); -static inline struct expression *new_exp_0 PARAMS ((enum operator op)); -static inline struct expression *new_exp_1 PARAMS ((enum operator op, - struct expression *right)); -static struct expression *new_exp_2 PARAMS ((enum operator op, - struct expression *left, - struct expression *right)); -static inline struct expression *new_exp_3 PARAMS ((enum operator op, - struct expression *bexp, - struct expression *tbranch, - struct expression *fbranch)); -static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); -static void yyerror PARAMS ((const char *str)); - -/* Allocation of expressions. */ - -static struct expression * -new_exp (nargs, op, args) - int nargs; - enum operator op; - struct expression * const *args; -{ - int i; - struct expression *newp; - - /* If any of the argument could not be malloc'ed, just return NULL. */ - for (i = nargs - 1; i >= 0; i--) - if (args[i] == NULL) - goto fail; - - /* Allocate a new expression. */ - newp = (struct expression *) malloc (sizeof (*newp)); - if (newp != NULL) - { - newp->nargs = nargs; - newp->operation = op; - for (i = nargs - 1; i >= 0; i--) - newp->val.args[i] = args[i]; - return newp; - } - - fail: - for (i = nargs - 1; i >= 0; i--) - FREE_EXPRESSION (args[i]); - - return NULL; -} - -static inline struct expression * -new_exp_0 (op) - enum operator op; -{ - return new_exp (0, op, NULL); -} - -static inline struct expression * -new_exp_1 (op, right) - enum operator op; - struct expression *right; -{ - struct expression *args[1]; - - args[0] = right; - return new_exp (1, op, args); -} - -static struct expression * -new_exp_2 (op, left, right) - enum operator op; - struct expression *left; - struct expression *right; -{ - struct expression *args[2]; - - args[0] = left; - args[1] = right; - return new_exp (2, op, args); -} - -static inline struct expression * -new_exp_3 (op, bexp, tbranch, fbranch) - enum operator op; - struct expression *bexp; - struct expression *tbranch; - struct expression *fbranch; -{ - struct expression *args[3]; - - args[0] = bexp; - args[1] = tbranch; - args[2] = fbranch; - return new_exp (3, op, args); -} - -%} - -/* This declares that all operators have the same associativity and the - precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. - There is no unary minus and no bitwise operators. - Operators with the same syntactic behaviour have been merged into a single - token, to save space in the array generated by bison. */ -%right '?' /* ? */ -%left '|' /* || */ -%left '&' /* && */ -%left EQUOP2 /* == != */ -%left CMPOP2 /* < > <= >= */ -%left ADDOP2 /* + - */ -%left MULOP2 /* * / % */ -%right '!' /* ! */ - -%token EQUOP2 CMPOP2 ADDOP2 MULOP2 -%token NUMBER -%type exp - -%% - -start: exp - { - if ($1 == NULL) - YYABORT; - ((struct parse_args *) arg)->res = $1; - } - ; - -exp: exp '?' exp ':' exp - { - $$ = new_exp_3 (qmop, $1, $3, $5); - } - | exp '|' exp - { - $$ = new_exp_2 (lor, $1, $3); - } - | exp '&' exp - { - $$ = new_exp_2 (land, $1, $3); - } - | exp EQUOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | exp CMPOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | exp ADDOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | exp MULOP2 exp - { - $$ = new_exp_2 ($2, $1, $3); - } - | '!' exp - { - $$ = new_exp_1 (lnot, $2); - } - | 'n' - { - $$ = new_exp_0 (var); - } - | NUMBER - { - if (($$ = new_exp_0 (num)) != NULL) - $$->val.num = $1; - } - | '(' exp ')' - { - $$ = $2; - } - ; - -%% - -void -internal_function -FREE_EXPRESSION (exp) - struct expression *exp; -{ - if (exp == NULL) - return; - - /* Handle the recursive case. */ - switch (exp->nargs) - { - case 3: - FREE_EXPRESSION (exp->val.args[2]); - /* FALLTHROUGH */ - case 2: - FREE_EXPRESSION (exp->val.args[1]); - /* FALLTHROUGH */ - case 1: - FREE_EXPRESSION (exp->val.args[0]); - /* FALLTHROUGH */ - default: - break; - } - - free (exp); -} - - -static int -yylex (lval, pexp) - YYSTYPE *lval; - const char **pexp; -{ - const char *exp = *pexp; - int result; - - while (1) - { - if (exp[0] == '\0') - { - *pexp = exp; - return YYEOF; - } - - if (exp[0] != ' ' && exp[0] != '\t') - break; - - ++exp; - } - - result = *exp++; - switch (result) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - unsigned long int n = result - '0'; - while (exp[0] >= '0' && exp[0] <= '9') - { - n *= 10; - n += exp[0] - '0'; - ++exp; - } - lval->num = n; - result = NUMBER; - } - break; - - case '=': - if (exp[0] == '=') - { - ++exp; - lval->op = equal; - result = EQUOP2; - } - else - result = YYERRCODE; - break; - - case '!': - if (exp[0] == '=') - { - ++exp; - lval->op = not_equal; - result = EQUOP2; - } - break; - - case '&': - case '|': - if (exp[0] == result) - ++exp; - else - result = YYERRCODE; - break; - - case '<': - if (exp[0] == '=') - { - ++exp; - lval->op = less_or_equal; - } - else - lval->op = less_than; - result = CMPOP2; - break; - - case '>': - if (exp[0] == '=') - { - ++exp; - lval->op = greater_or_equal; - } - else - lval->op = greater_than; - result = CMPOP2; - break; - - case '*': - lval->op = mult; - result = MULOP2; - break; - - case '/': - lval->op = divide; - result = MULOP2; - break; - - case '%': - lval->op = module; - result = MULOP2; - break; - - case '+': - lval->op = plus; - result = ADDOP2; - break; - - case '-': - lval->op = minus; - result = ADDOP2; - break; - - case 'n': - case '?': - case ':': - case '(': - case ')': - /* Nothing, just return the character. */ - break; - - case ';': - case '\n': - case '\0': - /* Be safe and let the user call this function again. */ - --exp; - result = YYEOF; - break; - - default: - result = YYERRCODE; -#if YYDEBUG != 0 - --exp; -#endif - break; - } - - *pexp = exp; - - return result; -} - - -static void -yyerror (str) - const char *str; -{ - /* Do nothing. We don't print error messages here. */ -} diff --git a/intl/textdomain.c b/intl/textdomain.c deleted file mode 100644 index 2e420ad77..000000000 --- a/intl/textdomain.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Implementation of the textdomain(3) function. - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program 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, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 -#endif - -#include -#include - -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "gettextP.h" - -#ifdef _LIBC -/* We have to handle multi-threaded applications. */ -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_rwlock_define(CLASS, NAME) -# define __libc_rwlock_wrlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_default_domain _nl_default_default_domain__ -# define _nl_current_default_domain _nl_current_default_domain__ -#endif - -/* @@ end of prolog @@ */ - -/* Name of the default text domain. */ -extern const char _nl_default_default_domain[]; - -/* Default text domain in which entries for gettext(3) are to be found. */ -extern const char *_nl_current_default_domain; - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define TEXTDOMAIN __textdomain -# ifndef strdup -# define strdup(str) __strdup (str) -# endif -#else -# define TEXTDOMAIN textdomain__ -#endif - -/* Lock variable to protect the global data in the gettext implementation. */ -__libc_rwlock_define (extern, _nl_state_lock) - -/* Set the current default message catalog to DOMAINNAME. - If DOMAINNAME is null, return the current default. - If DOMAINNAME is "", reset to the default of "messages". */ -char * -TEXTDOMAIN (domainname) - const char *domainname; -{ - char *new_domain; - char *old_domain; - - /* A NULL pointer requests the current setting. */ - if (domainname == NULL) - return (char *) _nl_current_default_domain; - - __libc_rwlock_wrlock (_nl_state_lock); - - old_domain = (char *) _nl_current_default_domain; - - /* If domain name is the null string set to default domain "messages". */ - if (domainname[0] == '\0' - || strcmp (domainname, _nl_default_default_domain) == 0) - { - _nl_current_default_domain = _nl_default_default_domain; - new_domain = (char *) _nl_current_default_domain; - } - else if (strcmp (domainname, old_domain) == 0) - /* This can happen and people will use it to signal that some - environment variable changed. */ - new_domain = old_domain; - else - { - /* If the following malloc fails `_nl_current_default_domain' - will be NULL. This value will be returned and so signals we - are out of core. */ -#if defined _LIBC || defined HAVE_STRDUP - new_domain = strdup (domainname); -#else - size_t len = strlen (domainname) + 1; - new_domain = (char *) malloc (len); - if (new_domain != NULL) - memcpy (new_domain, domainname, len); -#endif - - if (new_domain != NULL) - _nl_current_default_domain = new_domain; - } - - /* We use this possibility to signal a change of the loaded catalogs - since this is most likely the case and there is no other easy we - to do it. Do it only when the call was successful. */ - if (new_domain != NULL) - { - ++_nl_msg_cat_cntr; - - if (old_domain != new_domain && old_domain != _nl_default_default_domain) - free (old_domain); - } - - __libc_rwlock_unlock (_nl_state_lock); - - return new_domain; -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__textdomain, textdomain); -#endif diff --git a/kbx/ChangeLog b/kbx/ChangeLog deleted file mode 100644 index 351ec5d13..000000000 --- a/kbx/ChangeLog +++ /dev/null @@ -1,102 +0,0 @@ -2002-08-10 Werner Koch - - * keybox-search.c (blob_cmp_fpr_part): New. - (has_short_kid, has_long_kid): Implemented. - -2002-07-22 Werner Koch - - * keybox-defs.h: New BLOBTYPTE_EMPTY. - * keybox-dump.c (_keybox_dump_blob): Handle new type. - * keybox-file.c (_keybox_read_blob): Skip over empty blobs. Store - the file offset. - * keybox-blob.c (_keybox_new_blob): Add new arg OFF. - (_keybox_get_blob_fileoffset): New. - * keybox-update.c (keybox_delete): Implemented. - -2002-06-19 Werner Koch - - * keybox-init.c (keybox_set_ephemeral): New. - * keybox-blob.c (create_blob_header): Store epheermal flag. - (_keybox_create_x509_blob): Pass epheermal flag on. - * keybox-update.c (keybox_insert_cert): Ditto. - * keybox-search.c (blob_get_blob_flags): New. - (keybox_search): Ignore ephemeral blobs when not in ephemeral mode. - - * keybox-dump.c (_keybox_dump_blob): Print blob flags as strings. - -2002-02-25 Werner Koch - - * keybox-search.c (blob_cmp_mail): Use case-insensitive compare - because mail addresses are in general case insensitive (well - RFC2822 allows for case sensitive mailbox parts, but this is in - general considired a Bad Thing). Add additional substr parameter - to allow for substring matches within the mail address. Change - all callers to pass this along. - (blob_cmp_name): Likewise but do the case-insensitive search only - in sub string mode. - (keybox_search): Implement MAILSUB and SUBSTR mode. - -2002-01-21 Werner Koch - - * keybox-search.c (keybox_search): Allow KEYDB_SEARCH_MODE_FPR20. - -2002-01-15 Werner Koch - - * keybox-search.c (blob_cmp_fpr): New. - (has_fingerprint): Implemented; - -2001-12-20 Werner Koch - - * keybox-blob.c (_keybox_create_x509_blob): Skip the leading - parenthesis of the serial number's S-exp. - (_keybox_create_x509_blob): And fixed length calculation. - (create_blob_header): Don't add an offset when writing the serial. - -2001-12-18 Werner Koch - - * Makefile.am (AM_CPPFLAGS): Add flags for libksba - - * keybox-blob.c (_keybox_create_x509_blob): Use - gcry_sexp_canon_len to get the length of the serial number. - (_keybox_release_blob): Need to use a new serialbuf to free the memory. - -2001-12-17 Werner Koch - - * keybox-search.c: Changed the way the serial number is - represented. - -2001-12-15 Werner Koch - - * keybox-search.c (blob_cmp_name): There is no terminating 0 stored - for the uid; fixed length compare. - -2001-12-14 Werner Koch - - * keybox-blob.c (x509_email_kludge): New. - (_keybox_create_x509_blob): Insert an extra email address if the - subject's DN has an email part. - * keybox-defs.h: Added the xtoi_2 and digitp macros. - -2001-12-13 Werner Koch - - * keybox-search.c (blob_cmp_name): Kludge to allow searching for - more than one name. - (has_subject_or_alt): New. - (blob_cmp_mail): New. - (has_mail): New. - (keybox_search): Implemented exact search and exact mail search. - - * kbx/keybox-blob.c (_keybox_create_x509_blob): Insert alternate - names. - - - Copyright 2001 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 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. - \ No newline at end of file diff --git a/kbx/Makefile.am b/kbx/Makefile.am deleted file mode 100644 index 4e7170379..000000000 --- a/kbx/Makefile.am +++ /dev/null @@ -1,53 +0,0 @@ -# Keybox Makefile -# 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 - -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - -EXTRA_DIST = mkerrors -AM_CPPFLAGS = $(KSBA_CFLAGS) $(LIBGCRYPT_CLFAGS) -BUILT_SOURCES = keybox-errors.c - -noinst_LIBRARIES = libkeybox.a -bin_PROGRAMS = kbxutil - -common_sources = \ - keybox.h keybox-defs.h keybox-search-desc.h \ - keybox-util.c \ - keybox-errors.c \ - keybox-init.c \ - keybox-blob.c \ - keybox-file.c \ - keybox-search.c \ - keybox-update.c \ - keybox-dump.c - - -libkeybox_a_SOURCES = $(common_sources) - -kbxutil_SOURCES = kbxutil.c $(common_sources) -kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) - -keybox-errors.c : keybox.h mkerrors - $(srcdir)/mkerrors < $(srcdir)/keybox.h > keybox-errors.c - - - diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c deleted file mode 100644 index b733b81c8..000000000 --- a/kbx/kbxutil.c +++ /dev/null @@ -1,338 +0,0 @@ -/* kbxutil.c - The Keybox utility - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include - -#include - -#include "../jnlib/logging.h" -#include "../jnlib/argparse.h" -#include "../jnlib/stringhelp.h" -#include "../common/i18n.h" -#include "keybox-defs.h" - -enum cmd_and_opt_values { - aNull = 0, - oArmor = 'a', - oDryRun = 'n', - oOutput = 'o', - oQuiet = 'q', - oVerbose = 'v', - - aNoSuchCmd = 500, /* force other values not to be a letter */ - aFindByFpr, - aFindByKid, - aFindByUid, - - oDebug, - oDebugAll, - - oNoArmor, - - - aTest -}; - - -static ARGPARSE_OPTS opts[] = { - { 300, NULL, 0, N_("@Commands:\n ") }, - - { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, - { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, - { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, - - { 301, NULL, 0, N_("@\nOptions:\n ") }, - - { oArmor, "armor", 0, N_("create ascii armored output")}, - { oArmor, "armour", 0, "@" }, - { oOutput, "output", 2, N_("use as output file")}, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oDryRun, "dry-run", 0, N_("do not make any changes") }, - - { oDebug, "debug" ,4|16, N_("set debugging flags")}, - { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, - - {0} /* end of list */ -}; - - -void myexit (int rc); - -int keybox_errors_seen = 0; - - -static const char * -my_strusage( int level ) -{ - const char *p; - switch( level ) { - case 11: p = "kbxutil (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = - _("Please report bugs to " PACKAGE_BUGREPORT ".\n"); - break; - case 1: - case 40: p = - _("Usage: kbxutil [options] [files] (-h for help)"); - break; - case 41: p = - _("Syntax: kbxutil [options] [files]\n" - "list, export, import Keybox data\n"); - break; - - - default: p = NULL; - } - return p; -} - - -static void -i18n_init(void) -{ - #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); - #else - #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_TIME, "" ); - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif - bindtextdomain( PACKAGE, LOCALEDIR ); - textdomain( PACKAGE ); - #endif - #endif -} - - -/* static void */ -/* wrong_args( const char *text ) */ -/* { */ -/* log_error("usage: kbxutil %s\n", text); */ -/* myexit ( 1 ); */ -/* } */ - - -#if 0 -static int -hextobyte( const byte *s ) -{ - int c; - - if( *s >= '0' && *s <= '9' ) - c = 16 * (*s - '0'); - else if( *s >= 'A' && *s <= 'F' ) - c = 16 * (10 + *s - 'A'); - else if( *s >= 'a' && *s <= 'f' ) - c = 16 * (10 + *s - 'a'); - else - return -1; - s++; - if( *s >= '0' && *s <= '9' ) - c += *s - '0'; - else if( *s >= 'A' && *s <= 'F' ) - c += 10 + *s - 'A'; - else if( *s >= 'a' && *s <= 'f' ) - c += 10 + *s - 'a'; - else - return -1; - return c; -} -#endif - -#if 0 -static char * -format_fingerprint ( const char *s ) -{ - int i, c; - byte fpr[20]; - - for (i=0; i < 20 && *s; ) { - if ( *s == ' ' || *s == '\t' ) { - s++; - continue; - } - c = hextobyte(s); - if (c == -1) { - return NULL; - } - fpr[i++] = c; - s += 2; - } - return gcry_xstrdup ( fpr ); -} -#endif - -#if 0 -static int -format_keyid ( const char *s, u32 *kid ) -{ - char helpbuf[9]; - switch ( strlen ( s ) ) { - case 8: - kid[0] = 0; - kid[1] = strtoul( s, NULL, 16 ); - return 10; - - case 16: - mem2str( helpbuf, s, 9 ); - kid[0] = strtoul( helpbuf, NULL, 16 ); - kid[1] = strtoul( s+8, NULL, 16 ); - return 11; - } - return 0; /* error */ -} -#endif - - -int -main( int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - enum cmd_and_opt_values cmd = 0; - - set_strusage( my_strusage ); - /*log_set_name("kbxutil"); fixme */ -#if 0 - /* check that the libraries are suitable. Do it here because - * the option parse may need services of the library */ - if ( !gcry_check_version ( "1.1.4" ) ) - { - log_fatal(_("libgcrypt is too old (need %s, have %s)\n"), - "1.1.4", gcry_check_version(NULL) ); - } -#endif - - /*create_dotlock(NULL); register locking cleanup */ - i18n_init(); - - /* We need to use the gcry malloc function because jnlib does use them */ - keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); - - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - while (arg_parse( &pargs, opts) ) - { - switch (pargs.r_opt) - { - case oVerbose: - /*opt.verbose++;*/ - /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/ - break; - case oDebug: - /*opt.debug |= pargs.r.ret_ulong; */ - break; - case oDebugAll: - /*opt.debug = ~0;*/ - break; - - case aFindByFpr: - case aFindByKid: - case aFindByUid: - cmd = pargs.r_opt; - break; - - default: - pargs.err = 2; - break; - } - } - if (log_get_errorcount(0) ) - myexit(2); - - if (!cmd) - { /* default is to list a KBX file */ - if (!argc) - _keybox_dump_file (NULL, stdout); - else - { - for (; argc; argc--, argv++) - _keybox_dump_file (*argv, stdout); - } - } -#if 0 - else if ( cmd == aFindByFpr ) { - char *fpr; - if ( argc != 2 ) - wrong_args ("kbxfile foingerprint"); - fpr = format_fingerprint ( argv[1] ); - if ( !fpr ) - log_error ("invalid formatted fingerprint\n"); - else { - kbxfile_search_by_fpr ( argv[0], fpr ); - gcry_free ( fpr ); - } - } - else if ( cmd == aFindByKid ) { - u32 kid[2]; - int mode; - - if ( argc != 2 ) - wrong_args ("kbxfile short-or-long-keyid"); - mode = format_keyid ( argv[1], kid ); - if ( !mode ) - log_error ("invalid formatted keyID\n"); - else { - kbxfile_search_by_kid ( argv[0], kid, mode ); - } - } - else if ( cmd == aFindByUid ) { - if ( argc != 2 ) - wrong_args ("kbxfile userID"); - kbxfile_search_by_uid ( argv[0], argv[1] ); - } -#endif - else - log_error ("unsupported action\n"); - - myexit(0); - return 8; /*NEVER REACHED*/ -} - - -void -myexit( int rc ) -{ - /* if( opt.debug & DBG_MEMSTAT_VALUE ) {*/ -/* gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */ -/* gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */ - /* }*/ -/* if( opt.debug ) */ -/* gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */ - rc = rc? rc : log_get_errorcount(0)? 2 : - keybox_errors_seen? 1 : 0; - exit(rc ); -} - - diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c deleted file mode 100644 index 48e2b5b87..000000000 --- a/kbx/keybox-blob.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* keybox-blob.c - KBX Blob handling - * Copyright (C) 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 - */ - - -/* The keybox data formats - -The KeyBox uses an augmented OpenPGP/X.509 key format. This makes -random access to a keyblock/Certificate easier and also gives the -opportunity to store additional information (e.g. the fingerprint) -along with the key. All integers are stored in network byte order, -offsets are counted from the beginning of the Blob. - -The first record of a plain KBX file has a special format: - - u32 length of the first record - byte Blob type (1) - byte version number (1) - byte reserved - byte reserved - u32 magic 'KBXf' - byte pgp_marginals used for validity calculation of this file - byte pgp_completes ditto. - byte pgp_cert_depth ditto. - -The OpenPGP and X.509 blob are verry similiar, things which are -X.509 specific are noted like [X.509: xxx] - - u32 length of this blob (including these 4 bytes) - byte Blob type (2) [X509: 3] - byte version number of this blob type (1) - u16 Blob flags - bit 0 = contains secret key material - bit 1 = ephemeral blob (e.g. used while quering external resources) - - u32 offset to the OpenPGP keyblock or X509 DER encoded certificate - u32 and its length - u16 number of keys (at least 1!) [X509: always 1] - u16 size of additional key information - n times: - b20 The keys fingerprint - (fingerprints are always 20 bytes, MD5 left padded with zeroes) - u32 offset to the n-th key's keyID (a keyID is always 8 byte) - or 0 if not known which is the case opnly for X509. - u16 special key flags - bit 0 = - u16 reserved - u16 size of serialnumber(may be zero) - n u16 (see above) bytes of serial number - u16 number of user IDs - u16 size of additional user ID information - n times: - u32 offset to the n-th user ID - u32 length of this user ID. - u16 special user ID flags. - bit 0 = - byte validity - byte reserved - [For X509, the first user ID is the ISsuer, the second the subject - and the others are subjectAltNames] - u16 number of signatures - u16 size of signature information (4) - u32 expiration time of signature with some special values: - 0x00000000 = not checked - 0x00000001 = missing key - 0x00000002 = bad signature - 0x10000000 = valid and expires at some date in 1978. - 0xffffffff = valid and does not expire - u8 assigned ownertrust [X509: no used] - u8 all_validity [X509: no used] - u16 reserved - u32 recheck_after - u32 Newest timestamp in the keyblock (useful for KS syncronsiation?) - u32 Blob created at - u32 size of reserved space (not including this field) - reserved space - - Here we might want to put other data - - Here comes the keyblock - - maybe we put a signature here later. - - b16 MD5 checksum (useful for KS syncronisation), we might also want to use - a mac here. - b4 resevered - -*/ - - -#include -#include -#include -#include -#include -#include -#include - -#ifdef KEYBOX_WITH_OPENPGP -/* include stuff to parse the packets */ -#endif -#ifdef KEYBOX_WITH_X509 -#include -#endif - -#include "keybox-defs.h" - - -/* special values of the signature status */ -#define SF_NONE(a) ( !(a) ) -#define SF_NOKEY(a) ((a) & (1<<0)) -#define SF_BAD(a) ((a) & (1<<1)) -#define SF_VALID(a) ((a) & (1<<29)) - - -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; -}; - - -/* #if MAX_FINGERPRINT_LEN < 20 */ -/* #error fingerprints are 20 bytes */ -/* #endif */ - -struct keyboxblob_key { - char fpr[20]; - u32 off_kid; - ulong off_kid_addr; - u16 flags; -}; -struct keyboxblob_uid { - ulong off_addr; - char *name; /* used only with x509 */ - u32 len; - u16 flags; - byte validity; -}; - -struct keyid_list { - struct keyid_list *next; - int seqno; - byte kid[8]; -}; - -struct fixup_list { - struct fixup_list *next; - u32 off; - u32 val; -}; - - -struct keyboxblob { - byte *blob; - size_t bloblen; - off_t fileoffset; - - /* stuff used only by keybox_create_blob */ - unsigned char *serialbuf; - const unsigned char *serial; - size_t seriallen; - int nkeys; - struct keyboxblob_key *keys; - int nuids; - struct keyboxblob_uid *uids; - int nsigs; - u32 *sigs; - struct fixup_list *fixups; - int fixup_out_of_core; - - struct keyid_list *temp_kids; - struct membuf bufbuf; /* temporary store for the blob */ - struct membuf *buf; -}; - - - -/* A simple implemnation 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. */ - -static void -init_membuf (struct membuf *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 = 1; -} - -static void -put_membuf (struct membuf *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 = 1; - return; - } - mb->buf = p; - } - memcpy (mb->buf + mb->len, buf, len); - mb->len += len; -} - -static void * -get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ - return p; -} - - -static void -put8 (struct membuf *mb, byte a ) -{ - put_membuf (mb, &a, 1); -} - -static void -put16 (struct membuf *mb, u16 a ) -{ - unsigned char tmp[2]; - tmp[0] = a>>8; - tmp[1] = a; - put_membuf (mb, tmp, 2); -} - -static void -put32 (struct membuf *mb, u32 a ) -{ - unsigned char tmp[4]; - tmp[0] = a>>24; - tmp[1] = a>>16; - tmp[2] = a>>8; - tmp[3] = a; - put_membuf (mb, tmp, 4); -} - - -/* Store a value in the fixup list */ -static void -add_fixup (KEYBOXBLOB blob, u32 off, u32 val) -{ - struct fixup_list *fl; - - if (blob->fixup_out_of_core) - return; - - fl = xtrycalloc(1, sizeof *fl); - if (!fl) - blob->fixup_out_of_core = 1; - else - { - fl->off = off; - fl->val = val; - fl->next = blob->fixups; - blob->fixups = fl; - } -} - - -/* - Some wrappers -*/ - -static u32 -make_timestamp (void) -{ - return time(NULL); -} - - - -#ifdef KEYBOX_WITH_OPENPGP -/* - OpenPGP specific stuff -*/ - - -/* - We must store the keyid at some place because we can't calculate the - offset yet. This is only used for v3 keyIDs. Function returns an - index value for later fixup or -1 for out of core. The value must be - a non-zero value */ -static int -pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk) -{ - struct keyid_list *k, *r; - - k = xtrymalloc (sizeof *k); - if (!k) - return -1; - k->kid[0] = pk->keyid[0] >> 24 ; - k->kid[1] = pk->keyid[0] >> 16 ; - k->kid[2] = pk->keyid[0] >> 8 ; - k->kid[3] = pk->keyid[0] ; - k->kid[4] = pk->keyid[0] >> 24 ; - k->kid[5] = pk->keyid[0] >> 16 ; - k->kid[6] = pk->keyid[0] >> 8 ; - k->kid[7] = pk->keyid[0] ; - k->seqno = 0; - k->next = blob->temp_kids; - blob->temp_kids = k; - for (r=k; r; r = r->next) - k->seqno++; - - return k->seqno; -} - -static int -pgp_create_key_part (KEYBOXBLOB blob, KBNODE keyblock) -{ - KBNODE node; - size_t fprlen; - int n; - - for (n=0, node = keyblock; node; node = node->next) - { - if ( node->pkt->pkttype == PKT_PUBLIC_KEY - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - { - PKT_public_key *pk = node->pkt->pkt.public_key; - char tmp[20]; - - fingerprint_from_pk (pk, tmp , &fprlen); - memcpy (blob->keys[n].fpr, tmp, 20); - if ( fprlen != 20 ) /*v3 fpr - shift right and fill with zeroes*/ - { - assert (fprlen == 16); - memmove (blob->keys[n].fpr+4, blob->keys[n].fpr, 16); - memset (blob->keys[n].fpr, 0, 4); - blob->keys[n].off_kid = pgp_temp_store_kid (blob, pk); - } - else - { - blob->keys[n].off_kid = 0; /* will be fixed up later */ - } - blob->keys[n].flags = 0; - n++; - } - else if ( node->pkt->pkttype == PKT_SECRET_KEY - || node->pkt->pkttype == PKT_SECRET_SUBKEY ) - { - never_reached (); /* actually not yet implemented */ - } - } - assert (n == blob->nkeys); - return 0; -} - -static int -pgp_create_uid_part (KEYBOXBLOB blob, KBNODE keyblock) -{ - KBNODE node; - int n; - - for (n=0, node = keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_USER_ID) - { - PKT_user_id *u = node->pkt->pkt.user_id; - - blob->uids[n].len = u->len; - blob->uids[n].flags = 0; - blob->uids[n].validity = 0; - n++; - } - } - assert (n == blob->nuids); - return 0; -} - -static int -pgp_create_sig_part (KEYBOXBLOB blob, KBNODE keyblock) -{ - KBNODE node; - int n; - - for (n=0, node = keyblock; node; node = node->next) - { - if (node->pkt->pkttype == PKT_SIGNATURE) - { - PKT_signature *sig = node->pkt->pkt.signature; - - blob->sigs[n] = 0; /* FIXME: check the signature here */ - n++; - } - } - assert( n == blob->nsigs ); - return 0; -} - -static int -pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) -{ - struct membuf *a = blob->buf; - KBNODE node; - int rc; - int n; - u32 kbstart = a->len; - - add_fixup (blob, kbstart); - - for (n = 0, node = keyblock; node; node = node->next) - { - rc = build_packet ( a, node->pkt ); - if ( rc ) { - gpg_log_error ("build_packet(%d) for keyboxblob failed: %s\n", - node->pkt->pkttype, gpg_errstr(rc) ); - return GPGERR_WRITE_FILE; - } - if ( node->pkt->pkttype == PKT_USER_ID ) - { - PKT_user_id *u = node->pkt->pkt.user_id; - /* build_packet has set the offset of the name into u ; - * now we can do the fixup */ - add_fixup (blob, blob->uids[n].off_addr, u->stored_at); - n++; - } - } - assert (n == blob->nuids); - - add_fixup (blob, a->len - kbstart); - return 0; -} - -#endif /*KEYBOX_WITH_OPENPGP*/ - - -#ifdef KEYBOX_WITH_X509 -/* - X.509 specific stuff - */ - -/* Write the raw certificate out */ -static int -x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert) -{ - struct membuf *a = blob->buf; - const unsigned char *image; - size_t length; - u32 kbstart = a->len; - - /* Store our offset for later fixup */ - add_fixup (blob, 8, kbstart); - - image = ksba_cert_get_image (cert, &length); - if (!image) - return KEYBOX_General_Error; - put_membuf (a, image, length); - - add_fixup (blob, 12, a->len - kbstart); - return 0; -} - -#endif /*KEYBOX_WITH_X509*/ - -/* Write a stored keyID out to the buffer */ -static void -write_stored_kid (KEYBOXBLOB blob, int seqno) -{ - struct keyid_list *r; - - for ( r = blob->temp_kids; r; r = r->next ) - { - if (r->seqno == seqno ) - { - put_membuf (blob->buf, r->kid, 8); - return; - } - } - never_reached (); -} - -/* Release a list of key IDs */ -static void -release_kid_list (struct keyid_list *kl) -{ - struct keyid_list *r, *r2; - - for ( r = kl; r; r = r2 ) - { - r2 = r->next; - xfree (r); - } -} - - - -static int -create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral) -{ - struct membuf *a = blob->buf; - int i; - - put32 ( a, 0 ); /* blob length, needs fixup */ - put8 ( a, blobtype); - put8 ( a, 1 ); /* blob type version */ - put16 ( a, as_ephemeral? 2:0 ); /* blob flags */ - - put32 ( a, 0 ); /* offset to the raw data, needs fixup */ - put32 ( a, 0 ); /* length of the raw data, needs fixup */ - - put16 ( a, blob->nkeys ); - put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */ - for ( i=0; i < blob->nkeys; i++ ) - { - put_membuf (a, blob->keys[i].fpr, 20); - blob->keys[i].off_kid_addr = a->len; - put32 ( a, 0 ); /* offset to keyid, fixed up later */ - put16 ( a, blob->keys[i].flags ); - put16 ( a, 0 ); /* reserved */ - } - - put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/ - if (blob->serial) - put_membuf (a, blob->serial, blob->seriallen); - - put16 ( a, blob->nuids ); - put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */ - for (i=0; i < blob->nuids; i++) - { - blob->uids[i].off_addr = a->len; - put32 ( a, 0 ); /* offset to userid, fixed up later */ - put32 ( a, blob->uids[i].len ); - put16 ( a, blob->uids[i].flags ); - put8 ( a, 0 ); /* validity */ - put8 ( a, 0 ); /* reserved */ - } - - put16 ( a, blob->nsigs ); - put16 ( a, 4 ); /* size of sig info */ - for (i=0; i < blob->nsigs; i++) - { - put32 ( a, blob->sigs[i]); - } - - put8 ( a, 0 ); /* assigned ownertrust */ - put8 ( a, 0 ); /* validity of all user IDs */ - put16 ( a, 0 ); /* reserved */ - put32 ( a, 0 ); /* time of next recheck */ - put32 ( a, 0 ); /* newest timestamp (none) */ - put32 ( a, make_timestamp() ); /* creation time */ - put32 ( a, 0 ); /* size of reserved space */ - /* reserved space (which is currently of size 0) */ - - /* space where we write keyIDs and and other stuff so that the - pointers can actually point to somewhere */ - if (blobtype == BLOBTYPE_PGP) - { - /* We need to store the keyids for all pgp v3 keys because those key - IDs are not part of the fingerprint. While we are doing that, we - fixup all the keyID offsets */ - for (i=0; i < blob->nkeys; i++ ) - { - if (blob->keys[i].off_kid) - { /* this is a v3 one */ - add_fixup (blob, blob->keys[i].off_kid_addr, a->len); - write_stored_kid (blob, blob->keys[i].off_kid); - } - else - { /* the better v4 key IDs - just store an offset 8 bytes back */ - add_fixup (blob, blob->keys[i].off_kid_addr, - blob->keys[i].off_kid_addr - 8); - } - } - } - - if (blobtype == BLOBTYPE_X509) - { - /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to - the utf-8 string represenation of them */ - for (i=0; i < blob->nuids; i++ ) - { - if (blob->uids[i].name) - { /* this is a v3 one */ - add_fixup (blob, blob->uids[i].off_addr, a->len); - put_membuf (blob->buf, blob->uids[i].name, blob->uids[i].len); - } - } - } - - return 0; -} - - - -static int -create_blob_trailer (KEYBOXBLOB blob) -{ - return 0; -} - - -static int -create_blob_finish (KEYBOXBLOB blob) -{ - struct membuf *a = blob->buf; - byte *p; - char *pp; - int i; - size_t n; - - /* write a placeholder for the checksum */ - for (i = 0; i < 16; i++ ) - put32 (a, 0); /* Hmmm: why put32() ?? */ - - /* get the memory area */ - p = get_membuf (a, &n); - if (!p) - return KEYBOX_Out_Of_Core; - assert (n >= 20); - - /* fixup the length */ - add_fixup (blob, 0, n); - - /* do the fixups */ - if (blob->fixup_out_of_core) - return KEYBOX_Out_Of_Core; - - { - struct fixup_list *fl; - for (fl = blob->fixups; fl; fl = fl->next) - { - assert (fl->off+4 <= n); - p[fl->off+0] = fl->val >> 24; - p[fl->off+1] = fl->val >> 16; - p[fl->off+2] = fl->val >> 8; - p[fl->off+3] = fl->val; - } - } - - /* calculate and store the MD5 checksum */ - gcry_md_hash_buffer (GCRY_MD_MD5, p + n - 16, p, n - 16); - - pp = xtrymalloc (n); - if ( !pp ) - return KEYBOX_Out_Of_Core; - memcpy (pp , p, n); - blob->blob = pp; - blob->bloblen = n; - - return 0; -} - - -#ifdef KEYBOX_WITH_OPENPGP - -int -_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral) -{ - int rc = 0; - KBNODE node; - KEYBOXBLOB blob; - - *r_blob = NULL; - blob = xtrycalloc (1, sizeof *blob); - if( !blob ) - return KEYBOX_Out_Of_Core; - - /* fixme: Do some sanity checks on the keyblock */ - - /* count userids and keys so that we can allocate the arrays */ - for (node = keyblock; node; node = node->next) - { - switch (node->pkt->pkttype) - { - case PKT_PUBLIC_KEY: - case PKT_SECRET_KEY: - case PKT_PUBLIC_SUBKEY: - case PKT_SECRET_SUBKEY: blob->nkeys++; break; - case PKT_USER_ID: blob->nuids++; break; - case PKT_SIGNATURE: blob->nsigs++; break; - default: break; - } - } - - blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys ); - blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids ); - blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs ); - if (!blob->keys || !blob->uids || !blob->sigs) - { - rc = KEYBOX_Out_Of_Core; - goto leave; - } - - rc = pgp_create_key_part ( blob, keyblock ); - if (rc) - goto leave; - rc = pgp_create_uid_part ( blob, keyblock ); - if (rc) - goto leave; - rc = pgp_create_sig_part ( blob, keyblock ); - if (rc) - goto leave; - - init_membuf (&blob->bufbuf, 1024); - blob->buf = &blob->bufbuf; - rc = create_blob_header (blob, BLOBTYPE_OPENPGP, as_ephemeral); - if (rc) - goto leave; - rc = pgp_create_blob_keyblock (blob, keyblock); - if (rc) - goto leave; - rc = create_blob_trailer (blob); - if (rc) - goto leave; - rc = create_blob_finish ( blob ); - if (rc) - goto leave; - - - leave: - release_kid_list (blob->temp_kids); - blob->temp_kids = NULL; - if (rc) - { - keybox_release_blob (blob); - *r_blob = NULL; - } - else - { - *r_blob = blob; - } - return rc; -} -#endif /*KEYBOX_WITH_OPENPGP*/ - -#ifdef KEYBOX_WITH_X509 - -/* return an allocated string with the email address extracted from a - DN */ -static char * -x509_email_kludge (const char *name) -{ - const unsigned char *p; - unsigned char *buf; - int n; - - if (strncmp (name, "1.2.840.113549.1.9.1=#", 22)) - return NULL; - /* This looks pretty much like an email address in the subject's DN - we use this to add an additional user ID entry. This way, - openSSL generated keys get a nicer and usable listing */ - name += 22; - for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++) - ; - if (*p != '#' || !n) - return NULL; - buf = xtrymalloc (n+3); - if (!buf) - return NULL; /* oops, out of core */ - *buf = '<'; - for (n=1, p=name; *p != '#'; p +=2, n++) - buf[n] = xtoi_2 (p); - buf[n++] = '>'; - buf[n] = 0; - return buf; -} - - - -/* Note: We should move calculation of the digest into libksba and - remove that parameter */ -int -_keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert, - unsigned char *sha1_digest, int as_ephemeral) -{ - int i, rc = 0; - KEYBOXBLOB blob; - unsigned char *p; - unsigned char **names = NULL; - size_t max_names; - - *r_blob = NULL; - blob = xtrycalloc (1, sizeof *blob); - if( !blob ) - return KEYBOX_Out_Of_Core; - - p = ksba_cert_get_serial (cert); - if (p) - { - size_t n, len; - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - if (n < 2) - { - xfree (p); - return KEYBOX_General_Error; - } - blob->serialbuf = p; - p++; n--; /* skip '(' */ - for (len=0; n && *p && *p != ':' && digitp (p); n--, p++) - len = len*10 + atoi_1 (p); - if (*p != ':') - { - xfree (blob->serialbuf); - blob->serialbuf = NULL; - return KEYBOX_General_Error; - } - p++; - blob->serial = p; - blob->seriallen = len; - } - - blob->nkeys = 1; - - /* create list of names */ - blob->nuids = 0; - max_names = 100; - names = xtrymalloc (max_names * sizeof *names); - if (!names) - { - rc = KEYBOX_Out_Of_Core; - goto leave; - } - p = ksba_cert_get_issuer (cert, 0); - if (!p) - { - rc = KEYBOX_Missing_Value; - goto leave; - } - names[blob->nuids++] = p; - for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) - { - - if (blob->nuids >= max_names) - { - unsigned char **tmp; - - max_names += 100; - tmp = xtryrealloc (names, max_names * sizeof *names); - if (!tmp) - { - rc = KEYBOX_Out_Of_Core; - goto leave; - } - } - names[blob->nuids++] = p; - if (!i && (p=x509_email_kludge (p))) - names[blob->nuids++] = p; /* due to !i we don't need to check bounds*/ - } - - /* space for signature information */ - blob->nsigs = 1; - - blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys ); - blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids ); - blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs ); - if (!blob->keys || !blob->uids || !blob->sigs) - { - rc = KEYBOX_Out_Of_Core; - goto leave; - } - - memcpy (blob->keys[0].fpr, sha1_digest, 20); - blob->keys[0].off_kid = 0; /* We don't have keyids */ - blob->keys[0].flags = 0; - - /* issuer and subject names */ - for (i=0; i < blob->nuids; i++) - { - blob->uids[i].name = names[i]; - blob->uids[i].len = strlen(names[i]); - names[i] = NULL; - blob->uids[i].flags = 0; - blob->uids[i].validity = 0; - } - xfree (names); - names = NULL; - - /* signatures */ - blob->sigs[0] = 0; /* not yet checked */ - - /* Create a temporary buffer for further processing */ - init_membuf (&blob->bufbuf, 1024); - blob->buf = &blob->bufbuf; - /* write out what we already have */ - rc = create_blob_header (blob, BLOBTYPE_X509, as_ephemeral); - if (rc) - goto leave; - rc = x509_create_blob_cert (blob, cert); - if (rc) - goto leave; - rc = create_blob_trailer (blob); - if (rc) - goto leave; - rc = create_blob_finish ( blob ); - if (rc) - goto leave; - - - leave: - release_kid_list (blob->temp_kids); - blob->temp_kids = NULL; - if (blob && names) - { - for (i=0; i < blob->nuids; i++) - xfree (names[i]); - } - xfree (names); - if (rc) - { - _keybox_release_blob (blob); - *r_blob = NULL; - } - else - { - *r_blob = blob; - } - return rc; -} -#endif /*KEYBOX_WITH_X509*/ - - - -int -_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off) -{ - KEYBOXBLOB blob; - - *r_blob = NULL; - blob = xtrycalloc (1, sizeof *blob); - if (!blob) - return KEYBOX_Out_Of_Core; - - blob->blob = image; - blob->bloblen = imagelen; - blob->fileoffset = off; - *r_blob = blob; - return 0; -} - -void -_keybox_release_blob (KEYBOXBLOB blob) -{ - int i; - if (!blob) - return; - /* hmmm: release membuf here?*/ - xfree (blob->keys ); - xfree (blob->serialbuf); - for (i=0; i < blob->nuids; i++) - xfree (blob->uids[i].name); - xfree (blob->uids ); - xfree (blob->sigs ); - xfree (blob->blob ); - xfree (blob ); -} - - - -const char * -_keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n ) -{ - *n = blob->bloblen; - return blob->blob; -} - -off_t -_keybox_get_blob_fileoffset (KEYBOXBLOB blob) -{ - return blob->fileoffset; -} - diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h deleted file mode 100644 index 1c66020f7..000000000 --- a/kbx/keybox-defs.h +++ /dev/null @@ -1,179 +0,0 @@ -/* keybox-defs.h - interal Keybox defintions - * 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 KEYBOX_DEFS_H -#define KEYBOX_DEFS_H 1 - -#include /* off_t */ -#include "keybox.h" - -#ifndef HAVE_BYTE_TYPEDEF -typedef unsigned char byte; /* fixme */ -#endif -#ifndef HAVE_U16_TYPEDEF -typedef unsigned short u16; /* fixme */ -#endif -#ifndef HAVE_U32_TYPEDEF -typedef unsigned int u32; /* fixme */ -#endif - -enum { - BLOBTYPE_EMPTY = 0, - BLOBTYPE_HEADER = 1, - BLOBTYPE_PGP = 2, - BLOBTYPE_X509 = 3 -}; - - -typedef struct keyboxblob *KEYBOXBLOB; - - -typedef struct keybox_name *KB_NAME; -typedef struct keybox_name const * CONST_KB_NAME; -struct keybox_name { - struct keybox_name *next; - int secret; - /*DOTLOCK lockhd;*/ - int is_locked; - int did_full_scan; - char fname[1]; -}; - - - -struct keybox_handle { - CONST_KB_NAME kb; - int secret; /* this is for a secret keybox */ - FILE *fp; - int eof; - int error; - int ephemeral; - struct { - KEYBOXBLOB blob; - off_t offset; - size_t pk_no; - size_t uid_no; - unsigned int n_packets; /*used for delete and update*/ - } found; - struct { - char *name; - char *pattern; - } word_match; -}; - - -/* Don't know whether this is needed: */ -/* static struct { */ -/* const char *homedir; */ -/* int dry_run; */ -/* int quiet; */ -/* int verbose; */ -/* int preserve_permissions; */ -/* } keybox_opt; */ - - -/*-- keybox-blob.c --*/ -#ifdef KEYBOX_WITH_OPENPGP - /* fixme */ -#endif /*KEYBOX_WITH_OPENPGP*/ -#ifdef KEYBOX_WITH_X509 -int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert, - unsigned char *sha1_digest, int as_ephemeral); -#endif /*KEYBOX_WITH_X509*/ - -int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, - off_t off); -void _keybox_release_blob (KEYBOXBLOB blob); -const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); -off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); - -/*-- keybox-file.c --*/ -int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); -int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp); - -/*-- keybox-dump.c --*/ -int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); -int _keybox_dump_file (const char *filename, FILE *outfp); - - -/*-- keybox-util.c --*/ -void *_keybox_malloc (size_t n); -void *_keybox_calloc (size_t n, size_t m); -void *_keybox_realloc (void *p, size_t n); -void _keybox_free (void *p); - -#define xtrymalloc(a) _keybox_malloc ((a)) -#define xtrycalloc(a,b) _keybox_calloc ((a),(b)) -#define xtryrealloc(a,b) _keybox_realloc((a),(b)) -#define xfree(a) _keybox_free ((a)) - - -#define DIM(v) (sizeof(v)/sizeof((v)[0])) -#define DIMof(type,member) DIM(((type *)0)->member) -#ifndef STR - #define STR(v) #v -#endif -#define STR2(v) STR(v) - -/* - a couple of handy macros -*/ - -#define return_if_fail(expr) do { \ - if (!(expr)) { \ - fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ - __FILE__, __LINE__, #expr ); \ - return; \ - } } while (0) -#define return_null_if_fail(expr) do { \ - if (!(expr)) { \ - fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ - __FILE__, __LINE__, #expr ); \ - return NULL; \ - } } while (0) -#define return_val_if_fail(expr,val) do { \ - if (!(expr)) { \ - fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ - __FILE__, __LINE__, #expr ); \ - return (val); \ - } } while (0) -#define never_reached() do { \ - fprintf (stderr, "%s:%d: oops; should never get here\n", \ - __FILE__, __LINE__ ); \ - } while (0) - - -/* some macros to replace ctype ones and avoid locale problems */ -#define digitp(p) (*(p) >= '0' && *(p) <= '9') -#define hexdigitp(a) (digitp (a) \ - || (*(a) >= 'A' && *(a) <= 'F') \ - || (*(a) >= 'a' && *(a) <= 'f')) -/* 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)) - - -#endif /*KEYBOX_DEFS_H*/ - - diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c deleted file mode 100644 index 4fb3a4eb2..000000000 --- a/kbx/keybox-dump.c +++ /dev/null @@ -1,346 +0,0 @@ -/* keybox-dump.c - Debug helpers - * 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 - */ - -#include -#include -#include -#include -#include - -#include "keybox-defs.h" - -static ulong -get32 (const byte *buffer) -{ - ulong a; - a = *buffer << 24; - a |= buffer[1] << 16; - a |= buffer[2] << 8; - a |= buffer[3]; - return a; -} - -static ulong -get16 (const byte *buffer) -{ - ulong a; - a = *buffer << 8; - a |= buffer[1]; - return a; -} - -void -print_string (FILE *fp, const byte *p, size_t n, int delim) -{ - for ( ; n; n--, p++ ) - { - if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim) - { - putc('\\', fp); - if( *p == '\n' ) - putc('n', fp); - else if( *p == '\r' ) - putc('r', fp); - else if( *p == '\f' ) - putc('f', fp); - else if( *p == '\v' ) - putc('v', fp); - else if( *p == '\b' ) - putc('b', fp); - else if( !*p ) - putc('0', fp); - else - fprintf(fp, "x%02x", *p ); - } - else - putc(*p, fp); - } -} - - -static int -dump_header_blob (const byte *buffer, size_t length, FILE *fp) -{ - fprintf (fp, "Version: %d\n", buffer[5]); - if ( memcmp (buffer+8, "KBXf", 4)) - fprintf (fp, "[Error: invalid magic number]\n"); - return 0; -} - - -/* Dump one block to FP */ -int -_keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) -{ - const byte *buffer; - size_t length; - int type; - ulong n, nkeys, keyinfolen; - ulong nuids, uidinfolen; - ulong nsigs, siginfolen; - ulong rawdata_off, rawdata_len; - ulong nserial; - const byte *p; - - buffer = _keybox_get_blob_image (blob, &length); - - if (length < 40) - { - fprintf (fp, "[blob too short]\n"); - return -1; - } - - n = get32( buffer ); - if (n > length) - fprintf (fp, "[blob larger than length - output truncated]\n"); - else - length = n; /* ignore the rest */ - - fprintf (fp, "Length: %lu\n", n ); - type = buffer[4]; - switch (type) - { - case BLOBTYPE_EMPTY: - fprintf (fp, "Type: Empty\n"); - return 0; - - case BLOBTYPE_HEADER: - fprintf (fp, "Type: Header\n"); - return dump_header_blob (buffer, length, fp); - case BLOBTYPE_PGP: - fprintf (fp, "Type: OpenPGP\n"); - break; - case BLOBTYPE_X509: - fprintf (fp, "Type: X.509\n"); - break; - default: - fprintf (fp, "Type: %d\n", type); - fprintf (fp, "[can't dump this blob type]\n"); - return 0; - } - fprintf (fp, "Version: %d\n", buffer[5]); - - n = get16 (buffer + 6); - fprintf( fp, "Blob-Flags: %04lX", n); - if (n) - { - int any = 0; - - fputs (" (", fp); - if ((n & 1)) - { - fputs ("secret", fp); - any++; - } - if ((n & 2)) - { - if (any) - putc (',', fp); - fputs ("ephemeral", fp); - any++; - } - putc (')', fp); - } - putc ('\n', fp); - - rawdata_off = get32 (buffer + 8); - rawdata_len = get32 (buffer + 12); - - fprintf( fp, "Data-Offset: %lu\n", rawdata_off ); - fprintf( fp, "Data-Length: %lu\n", rawdata_len ); - - nkeys = get16 (buffer + 16); - fprintf (fp, "Key-Count: %lu\n", nkeys ); - if (!nkeys) - fprintf (fp, "[Error: no keys]\n"); - if (nkeys > 1 && type == BLOBTYPE_X509) - fprintf (fp, "[Error: only one key allowed for X509]\n"); - - keyinfolen = get16 (buffer + 18 ); - fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen); - /* fixme: check bounds */ - p = buffer + 20; - for (n=0; n < nkeys; n++, p += keyinfolen) - { - int i; - ulong kidoff, kflags; - - fprintf (fp, "Key-Fpr[%lu]: ", n ); - for (i=0; i < 20; i++ ) - fprintf (fp, "%02X", p[i]); - kidoff = get32 (p + 20); - fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff ); - fprintf (fp, "Key-Kid[%lu]: ", n ); - /* fixme: check bounds */ - for (i=0; i < 8; i++ ) - fprintf (fp, "%02X", buffer[kidoff+i] ); - kflags = get16 (p + 24 ); - fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags); - } - - /* serial number */ - fputs ("Serial-No: ", fp); - nserial = get16 (p); - p += 2; - if (!nserial) - fputs ("none", fp); - else - { - for (; nserial; nserial--, p++) - fprintf (fp, "%02X", *p); - } - putc ('\n', fp); - - /* user IDs */ - nuids = get16 (p); - fprintf (fp, "Uid-Count: %lu\n", nuids ); - uidinfolen = get16 (p + 2); - fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen); - /* fixme: check bounds */ - p += 4; - for (n=0; n < nuids; n++, p += uidinfolen) - { - ulong uidoff, uidlen, uflags; - - uidoff = get32( p ); - uidlen = get32( p+4 ); - if (type == BLOBTYPE_X509 && !n) - { - fprintf (fp, "Issuer-Off: %lu\n", uidoff ); - fprintf (fp, "Issuer-Len: %lu\n", uidlen ); - fprintf (fp, "Issuer: \""); - } - else if (type == BLOBTYPE_X509 && n == 1) - { - fprintf (fp, "Subject-Off: %lu\n", uidoff ); - fprintf (fp, "Subject-Len: %lu\n", uidlen ); - fprintf (fp, "Subject: \""); - } - else - { - fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff ); - fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen ); - fprintf (fp, "Uid[%lu]: \"", n ); - } - print_string (fp, buffer+uidoff, uidlen, '\"'); - fputs ("\"\n", fp); - uflags = get16 (p + 8); - if (type == BLOBTYPE_X509 && !n) - { - fprintf (fp, "Issuer-Flags: %04lX\n", uflags ); - fprintf (fp, "Issuer-Validity: %d\n", p[10] ); - } - else if (type == BLOBTYPE_X509 && n == 1) - { - fprintf (fp, "Subject-Flags: %04lX\n", uflags ); - fprintf (fp, "Subject-Validity: %d\n", p[10] ); - } - else - { - fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags ); - fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] ); - } - } - - nsigs = get16 (p); - fprintf (fp, "Sig-Count: %lu\n", nsigs ); - siginfolen = get16 (p + 2); - fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen ); - /* fixme: check bounds */ - p += 4; - for (n=0; n < nsigs; n++, p += siginfolen) - { - ulong sflags; - - sflags = get32 (p); - fprintf (fp, "Sig-Expire[%lu]: ", n ); - if (!sflags) - fputs ("[not checked]", fp); - else if (sflags == 1 ) - fputs ("[missing key]", fp); - else if (sflags == 2 ) - fputs ("[bad signature]", fp); - else if (sflags < 0x10000000) - fprintf (fp, "[bad flag %0lx]", sflags); - else if (sflags == 0xffffffff) - fputs ("0", fp ); - else - fputs ("a time"/*strtimestamp( sflags )*/, fp ); - putc ('\n', fp ); - } - - fprintf (fp, "Ownertrust: %d\n", p[0] ); - fprintf (fp, "All-Validity: %d\n", p[1] ); - p += 4; - n = get32 (p); p += 4; - fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" ); - n = get32 (p ); p += 4; - fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ ); - n = get32 (p ); p += 4; - fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ ); - n = get32 (p ); p += 4; - fprintf (fp, "Reserved-Space: %lu\n", n ); - - /* check that the keyblock is at the correct offset and other bounds */ - /*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/ - return 0; -} - - - -int -_keybox_dump_file (const char *filename, FILE *outfp) -{ - FILE *fp; - KEYBOXBLOB blob; - int rc; - unsigned long count = 0; - - if (!filename) - { - filename = "-"; - fp = stdin; - } - else - fp = fopen (filename, "rb"); - if (!fp) - { - fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno)); - return KEYBOX_File_Error; - } - - while ( !(rc = _keybox_read_blob (&blob, fp)) ) - { - fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); - _keybox_dump_blob (blob, outfp); - _keybox_release_blob (blob); - fprintf (outfp, "END-RECORD\n"); - count++; - } - if (rc == -1) - rc = 0; - if (rc) - fprintf (outfp, "error reading `%s': %s\n", filename, - rc == KEYBOX_Read_Error? keybox_strerror(rc):strerror (errno)); - - if (fp != stdin) - fclose (fp); - return rc; -} diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c deleted file mode 100644 index bbbf78e3c..000000000 --- a/kbx/keybox-file.c +++ /dev/null @@ -1,102 +0,0 @@ -/* keybox-file.c - file oeprations - * 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 - */ - -#include -#include -#include -#include - -#include "keybox-defs.h" - -/* Read a block at the current postion and return it in r_blob. - r_blob may be NULL to simply skip the current block */ -int -_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) -{ - char *image; - size_t imagelen = 0; - int c1, c2, c3, c4, type; - int rc; - off_t off; - - again: - *r_blob = NULL; - off = ftello (fp); - if (off == (off_t)-1) - return KEYBOX_Read_Error; - - if ((c1 = getc (fp)) == EOF - || (c2 = getc (fp)) == EOF - || (c3 = getc (fp)) == EOF - || (c4 = getc (fp)) == EOF - || (type = getc (fp)) == EOF) - { - if ( c1 == EOF && !ferror (fp) ) - return -1; /* eof */ - return KEYBOX_Read_Error; - } - - imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; - if (imagelen > 500000) /* sanity check */ - return KEYBOX_Blob_Too_Large; - - if (imagelen < 5) - return KEYBOX_Blob_Too_Short; - - if (!type) - { - /* special treatment for empty blobs. */ - if (fseek (fp, imagelen-5, SEEK_CUR)) - return KEYBOX_Read_Error; - goto again; - } - - image = xtrymalloc (imagelen); - if (!image) - return KEYBOX_Out_Of_Core; - - image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type; - if (fread (image+5, imagelen-5, 1, fp) != 1) - { - xfree (image); - return KEYBOX_Read_Error; - } - - rc = r_blob? _keybox_new_blob (r_blob, image, imagelen, off) : 0; - if (rc || !r_blob) - xfree (image); - return rc; -} - - -/* Write the block to the current file position */ -int -_keybox_write_blob (KEYBOXBLOB blob, FILE *fp) -{ - const char *image; - size_t length; - - image = _keybox_get_blob_image (blob, &length); - if (fwrite (image, length, 1, fp) != 1) - { - return KEYBOX_Write_Error; - } - return 0; -} diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c deleted file mode 100644 index b1d279999..000000000 --- a/kbx/keybox-init.c +++ /dev/null @@ -1,127 +0,0 @@ -/* keybox-init.c - Initalization of the library - * 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 - */ - -#include -#include -#include -#include -#include -#include - -#include "keybox-defs.h" - -#define compare_filenames strcmp - -static KB_NAME kb_names; - - -/* - Register a filename for plain keybox files. Returns a pointer to be - used to create a handles etc or NULL to indicate that it has already - been registered */ -void * -keybox_register_file (const char *fname, int secret) -{ - KB_NAME kr; - - for (kr=kb_names; kr; kr = kr->next) - { - if ( !compare_filenames (kr->fname, fname) ) - return NULL; /* already registered */ - } - - kr = xtrymalloc (sizeof *kr + strlen (fname)); - if (!kr) - return NULL; - strcpy (kr->fname, fname); - kr->secret = !!secret; - /* kr->lockhd = NULL;*/ - kr->is_locked = 0; - kr->did_full_scan = 0; - /* keep a list of all issued pointers */ - kr->next = kb_names; - kb_names = kr; - - /* create the offset table the first time a function here is used */ -/* if (!kb_offtbl) */ -/* kb_offtbl = new_offset_hash_table (); */ - - return kr; -} - -int -keybox_is_writable (void *token) -{ - KB_NAME r = token; - - return r? !access (r->fname, W_OK) : 0; -} - - - -/* Create a new handle for the resource associated with TOKEN. SECRET - is just a cross-check. - - The returned handle must be released using keybox_release (). */ -KEYBOX_HANDLE -keybox_new (void *token, int secret) -{ - KEYBOX_HANDLE hd; - KB_NAME resource = token; - - assert (resource && !resource->secret == !secret); - hd = xtrycalloc (1, sizeof *hd); - if (hd) - { - hd->kb = resource; - hd->secret = !!secret; - } - return hd; -} - -void -keybox_release (KEYBOX_HANDLE hd) -{ - if (!hd) - return; - _keybox_release_blob (hd->found.blob); - xfree (hd->word_match.name); - xfree (hd->word_match.pattern); - xfree (hd); -} - - -const char * -keybox_get_resource_name (KEYBOX_HANDLE hd) -{ - if (!hd || !hd->kb) - return NULL; - return hd->kb->fname; -} - -int -keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes) -{ - if (!hd) - return KEYBOX_Invalid_Handle; - hd->ephemeral = yes; - return 0; -} - diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c deleted file mode 100644 index 126364f5b..000000000 --- a/kbx/keybox-search.c +++ /dev/null @@ -1,810 +0,0 @@ -/* keybox-search.c - Search operations - * 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 -#include -#include -#include -#include - -#include "../jnlib/stringhelp.h" /* ascii_xxxx() */ -#include "keybox-defs.h" - -#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)) - -struct sn_array_s { - int snlen; - unsigned char *sn; -}; - - - -static ulong -get32 (const byte *buffer) -{ - ulong a; - a = *buffer << 24; - a |= buffer[1] << 16; - a |= buffer[2] << 8; - a |= buffer[3]; - return a; -} - -static ulong -get16 (const byte *buffer) -{ - ulong a; - a = *buffer << 8; - a |= buffer[1]; - return a; -} - - - -static int -blob_get_type (KEYBOXBLOB blob) -{ - const unsigned char *buffer; - size_t length; - - buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) - return -1; /* blob too short */ - - return buffer[4]; -} - -static unsigned int -blob_get_blob_flags (KEYBOXBLOB blob) -{ - const unsigned char *buffer; - size_t length; - - buffer = _keybox_get_blob_image (blob, &length); - if (length < 8) - return 0; /* oops */ - - return get16 (buffer + 6); -} - - -static int -blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) -{ - const unsigned char *buffer; - size_t length; - size_t pos, off; - size_t nkeys, keyinfolen; - size_t nserial; - - buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) - return 0; /* blob too short */ - - /*keys*/ - nkeys = get16 (buffer + 16); - keyinfolen = get16 (buffer + 18 ); - if (keyinfolen < 28) - return 0; /* invalid blob */ - pos = 20 + keyinfolen*nkeys; - if (pos+2 > length) - return 0; /* out of bounds */ - - /*serial*/ - nserial = get16 (buffer+pos); - off = pos + 2; - if (off+nserial > length) - return 0; /* out of bounds */ - - return nserial == snlen && !memcmp (buffer+off, sn, snlen); -} - - -static int -blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr) -{ - const unsigned char *buffer; - size_t length; - size_t pos, off; - size_t nkeys, keyinfolen; - int idx; - - buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) - return 0; /* blob too short */ - - /*keys*/ - nkeys = get16 (buffer + 16); - keyinfolen = get16 (buffer + 18 ); - if (keyinfolen < 28) - return 0; /* invalid blob */ - pos = 20; - if (pos + keyinfolen*nkeys > length) - return 0; /* out of bounds */ - - for (idx=0; idx < nkeys; idx++) - { - off = pos + idx*keyinfolen; - if (!memcmp (buffer + off, fpr, 20)) - return 1; /* found */ - } - return 0; /* not found */ -} - -static int -blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr, - int fproff, int fprlen) -{ - const unsigned char *buffer; - size_t length; - size_t pos, off; - size_t nkeys, keyinfolen; - int idx; - - buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) - return 0; /* blob too short */ - - /*keys*/ - nkeys = get16 (buffer + 16); - keyinfolen = get16 (buffer + 18 ); - if (keyinfolen < 28) - return 0; /* invalid blob */ - pos = 20; - if (pos + keyinfolen*nkeys > length) - return 0; /* out of bounds */ - - for (idx=0; idx < nkeys; idx++) - { - off = pos + idx*keyinfolen; - if (!memcmp (buffer + off + fproff, fpr, fprlen)) - return 1; /* found */ - } - return 0; /* not found */ -} - - -static int -blob_cmp_name (KEYBOXBLOB blob, int idx, - const char *name, size_t namelen, int substr) -{ - const unsigned char *buffer; - size_t length; - size_t pos, off, len; - size_t nkeys, keyinfolen; - size_t nuids, uidinfolen; - size_t nserial; - - buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) - return 0; /* blob too short */ - - /*keys*/ - nkeys = get16 (buffer + 16); - keyinfolen = get16 (buffer + 18 ); - if (keyinfolen < 28) - return 0; /* invalid blob */ - pos = 20 + keyinfolen*nkeys; - if (pos+2 > length) - return 0; /* out of bounds */ - - /*serial*/ - nserial = get16 (buffer+pos); - pos += 2 + nserial; - if (pos+4 > length) - return 0; /* out of bounds */ - - /* user ids*/ - nuids = get16 (buffer + pos); pos += 2; - uidinfolen = get16 (buffer + pos); pos += 2; - if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */) - return 0; /* invalid blob */ - if (pos + uidinfolen*nuids > length) - return 0; /* out of bounds */ - - if (idx < 0) - { /* compare all names starting with that (negated) index */ - idx = -idx; - - for ( ;idx < nuids; idx++) - { - size_t mypos = pos; - - mypos += idx*uidinfolen; - off = get32 (buffer+mypos); - len = get32 (buffer+mypos+4); - if (off+len > length) - return 0; /* error: better stop here out of bounds */ - if (len < 2) - continue; /* empty name or 0 not stored */ - len--; - if (substr) - { - if (ascii_memcasemem (buffer+off, len, name, namelen)) - return 1; /* found */ - } - else - { - if (len == namelen && !memcmp (buffer+off, name, len)) - return 1; /* found */ - } - } - return 0; /* not found */ - } - else - { - if (idx > nuids) - return 0; /* no user ID with that idx */ - pos += idx*uidinfolen; - off = get32 (buffer+pos); - len = get32 (buffer+pos+4); - if (off+len > length) - return 0; /* out of bounds */ - if (len < 1) - return 0; /* empty name */ - - if (substr) - { - return !!ascii_memcasemem (buffer+off, len, name, namelen); - } - else - { - return len == namelen && !memcmp (buffer+off, name, len); - } - } -} - - -/* compare all email addresses of the subject. With SUBSTR given as - True a substring search is done in the mail address */ -static int -blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr) -{ - const unsigned char *buffer; - size_t length; - size_t pos, off, len; - size_t nkeys, keyinfolen; - size_t nuids, uidinfolen; - size_t nserial; - int idx; - - /* fixme: this code is common to blob_cmp_mail */ - buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) - return 0; /* blob too short */ - - /*keys*/ - nkeys = get16 (buffer + 16); - keyinfolen = get16 (buffer + 18 ); - if (keyinfolen < 28) - return 0; /* invalid blob */ - pos = 20 + keyinfolen*nkeys; - if (pos+2 > length) - return 0; /* out of bounds */ - - /*serial*/ - nserial = get16 (buffer+pos); - pos += 2 + nserial; - if (pos+4 > length) - return 0; /* out of bounds */ - - /* user ids*/ - nuids = get16 (buffer + pos); pos += 2; - uidinfolen = get16 (buffer + pos); pos += 2; - if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */) - return 0; /* invalid blob */ - if (pos + uidinfolen*nuids > length) - return 0; /* out of bounds */ - - if (namelen < 1) - return 0; - - for (idx=1 ;idx < nuids; idx++) - { - size_t mypos = pos; - - mypos += idx*uidinfolen; - off = get32 (buffer+mypos); - len = get32 (buffer+mypos+4); - if (off+len > length) - return 0; /* error: better stop here out of bounds */ - if (len < 2 || buffer[off] != '<') - continue; /* empty name or trailing 0 not stored */ - len--; /* one back */ - if ( len < 3 || buffer[off+len] != '>') - continue; /* not a proper email address */ - len--; - if (substr) - { - if (ascii_memcasemem (buffer+off+1, len, name, namelen)) - return 1; /* found */ - } - else - { - if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len)) - return 1; /* found */ - } - } - return 0; /* not found */ -} - - - - -/* - The has_foo functions are used as helpers for search -*/ -static int -has_short_kid (KEYBOXBLOB blob, const unsigned char *kid) -{ - return blob_cmp_fpr_part (blob, kid+4, 16, 4); -} - -static int -has_long_kid (KEYBOXBLOB blob, const unsigned char *kid) -{ - return blob_cmp_fpr_part (blob, kid, 12, 8); -} - -static int -has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr) -{ - return blob_cmp_fpr (blob, fpr); -} - - -static int -has_issuer (KEYBOXBLOB blob, const char *name) -{ - size_t namelen; - - return_val_if_fail (name, 0); - - if (blob_get_type (blob) != BLOBTYPE_X509) - return 0; - - namelen = strlen (name); - return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0); -} - -static int -has_issuer_sn (KEYBOXBLOB blob, const char *name, - const unsigned char *sn, int snlen) -{ - size_t namelen; - - return_val_if_fail (name, 0); - return_val_if_fail (sn, 0); - - if (blob_get_type (blob) != BLOBTYPE_X509) - return 0; - - namelen = strlen (name); - - return (blob_cmp_sn (blob, sn, snlen) - && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0)); -} - -static int -has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) -{ - return_val_if_fail (sn, 0); - - if (blob_get_type (blob) != BLOBTYPE_X509) - return 0; - return blob_cmp_sn (blob, sn, snlen); -} - -static int -has_subject (KEYBOXBLOB blob, const char *name) -{ - size_t namelen; - - return_val_if_fail (name, 0); - - if (blob_get_type (blob) != BLOBTYPE_X509) - return 0; - - namelen = strlen (name); - return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0); -} - -static int -has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr) -{ - size_t namelen; - - return_val_if_fail (name, 0); - - if (blob_get_type (blob) != BLOBTYPE_X509) - return 0; - - namelen = strlen (name); - return blob_cmp_name (blob, -1 /* all subject names*/, name, - namelen, substr); -} - - -static int -has_mail (KEYBOXBLOB blob, const char *name, int substr) -{ - size_t namelen; - - return_val_if_fail (name, 0); - - if (blob_get_type (blob) != BLOBTYPE_X509) - return 0; - - namelen = strlen (name); - if (namelen && name[namelen-1] == '>') - namelen--; - return blob_cmp_mail (blob, name, namelen, substr); -} - - -static void -release_sn_array (struct sn_array_s *array, size_t size) -{ - size_t n; - - for (n=0; n < size; n++) - xfree (array[n].sn); - xfree (array); -} - - -/* - - The search API - -*/ - -int -keybox_search_reset (KEYBOX_HANDLE hd) -{ - if (!hd) - return KEYBOX_Invalid_Value; - - if (hd->found.blob) - { - _keybox_release_blob (hd->found.blob); - hd->found.blob = NULL; - } - - if (hd->fp) - { - fclose (hd->fp); - hd->fp = NULL; - } - hd->error = 0; - hd->eof = 0; - return 0; -} - - -/* Note: When in ephemeral mode the search function does visit all - blobs but in standard mode, blobs flagged as ephemeral are ignored. */ -int -keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) -{ - int rc; - size_t n; - int need_words, any_skip; - KEYBOXBLOB blob = NULL; - struct sn_array_s *sn_array = NULL; - - if (!hd) - return KEYBOX_Invalid_Value; - - /* clear last found result */ - if (hd->found.blob) - { - _keybox_release_blob (hd->found.blob); - hd->found.blob = NULL; - } - - if (hd->error) - return hd->error; /* still in error state */ - if (hd->eof) - return -1; /* still EOF */ - - /* figure out what information we need */ - need_words = any_skip = 0; - for (n=0; n < ndesc; n++) - { - switch (desc[n].mode) - { - case KEYDB_SEARCH_MODE_WORDS: - need_words = 1; - break; - case KEYDB_SEARCH_MODE_FIRST: - /* always restart the search in this mode */ - keybox_search_reset (hd); - break; - default: - break; - } - if (desc[n].skipfnc) - any_skip = 1; - if (desc[n].snlen == -1 && !sn_array) - { - sn_array = xtrycalloc (ndesc, sizeof *sn_array); - if (!sn_array) - return (hd->error = KEYBOX_Out_Of_Core); - } - } - - if (!hd->fp) - { - hd->fp = fopen (hd->kb->fname, "rb"); - if (!hd->fp) - { - xfree (sn_array); - return (hd->error = KEYBOX_File_Open_Error); - } - } - - /* kludge: we need to convert an SN given as hexstring to it's - binary representation - in some cases we are not able to store it - in the search descriptor, because due to its usgae it is not - possible to free allocated memory */ - if (sn_array) - { - const unsigned char *s; - int i, odd; - size_t snlen; - - for (n=0; n < ndesc; n++) - { - if (!desc[n].sn) - ; - else if (desc[n].snlen == -1) - { - unsigned char *sn; - - s = desc[n].sn; - for (i=0; *s && *s != '/'; s++, i++) - ; - odd = (i & 1); - snlen = (i+1)/2; - sn_array[n].sn = xtrymalloc (snlen); - if (!sn_array[n].sn) - { - release_sn_array (sn_array, n); - return (hd->error = KEYBOX_Out_Of_Core); - } - sn_array[n].snlen = snlen; - sn = sn_array[n].sn; - s = desc[n].sn; - if (odd) - { - *sn++ = xtoi_1 (s); - s++; - } - for (; *s && *s != '/'; s += 2) - *sn++ = xtoi_2 (s); - } - else - { - const unsigned char *sn; - - sn = desc[n].sn; - snlen = desc[n].snlen; - sn_array[n].sn = xtrymalloc (snlen); - if (!sn_array[n].sn) - { - release_sn_array (sn_array, n); - return (hd->error = KEYBOX_Out_Of_Core); - } - sn_array[n].snlen = snlen; - memcpy (sn_array[n].sn, sn, snlen); - } - } - } - - - for (;;) - { - unsigned int blobflags; - - _keybox_release_blob (blob); blob = NULL; - rc = _keybox_read_blob (&blob, hd->fp); - if (rc) - break; - - blobflags = blob_get_blob_flags (blob); - if (!hd->ephemeral && (blobflags & 2)) - continue; /* not in ephemeral mode but blob is flagged ephemeral */ - - for (n=0; n < ndesc; n++) - { - switch (desc[n].mode) - { - case KEYDB_SEARCH_MODE_NONE: - never_reached (); - break; - case KEYDB_SEARCH_MODE_EXACT: - if (has_subject_or_alt (blob, desc[n].u.name, 0)) - goto found; - break; - case KEYDB_SEARCH_MODE_MAIL: - if (has_mail (blob, desc[n].u.name, 0)) - goto found; - break; - case KEYDB_SEARCH_MODE_MAILSUB: - if (has_mail (blob, desc[n].u.name, 1)) - goto found; - break; - case KEYDB_SEARCH_MODE_SUBSTR: - if (has_subject_or_alt (blob, desc[n].u.name, 1)) - goto found; - break; - case KEYDB_SEARCH_MODE_MAILEND: - case KEYDB_SEARCH_MODE_WORDS: - never_reached (); /* not yet implemented */ - break; - case KEYDB_SEARCH_MODE_ISSUER: - if (has_issuer (blob, desc[n].u.name)) - goto found; - break; - case KEYDB_SEARCH_MODE_ISSUER_SN: - if (has_issuer_sn (blob, desc[n].u.name, - sn_array? sn_array[n].sn : desc[n].sn, - sn_array? sn_array[n].snlen : desc[n].snlen)) - goto found; - break; - case KEYDB_SEARCH_MODE_SN: - if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn, - sn_array? sn_array[n].snlen : desc[n].snlen)) - goto found; - break; - case KEYDB_SEARCH_MODE_SUBJECT: - if (has_subject (blob, desc[n].u.name)) - goto found; - break; - case KEYDB_SEARCH_MODE_SHORT_KID: - if (has_short_kid (blob, desc[n].u.kid)) - goto found; - break; - case KEYDB_SEARCH_MODE_LONG_KID: - if (has_long_kid (blob, desc[n].u.kid)) - goto found; - break; - case KEYDB_SEARCH_MODE_FPR: - case KEYDB_SEARCH_MODE_FPR20: - if (has_fingerprint (blob, desc[n].u.fpr)) - goto found; - break; - case KEYDB_SEARCH_MODE_FIRST: - goto found; - break; - case KEYDB_SEARCH_MODE_NEXT: - goto found; - break; - default: - rc = KEYBOX_Invalid_Value; - goto found; - } - } - continue; - found: - for (n=any_skip?0:ndesc; n < ndesc; n++) - { -/* if (desc[n].skipfnc */ -/* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */ -/* break; */ - } - if (n == ndesc) - break; /* got it */ - } - - if (!rc) - { - hd->found.blob = blob; - } - else if (rc == -1) - { - _keybox_release_blob (blob); - hd->eof = 1; - } - else - { - _keybox_release_blob (blob); - hd->error = rc; - } - - if (sn_array) - release_sn_array (sn_array, ndesc); - - return rc; -} - - - - -/* - Functions to return a certificate or a keyblock. To be used after - a successful search operation. -*/ -#ifdef KEYBOX_WITH_X509 -/* - Return the last found cert. Caller must free it. - */ -int -keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert) -{ - const unsigned char *buffer; - size_t length; - size_t cert_off, cert_len; - KsbaReader reader = NULL; - KsbaCert cert = NULL; - int rc; - - if (!hd) - return KEYBOX_Invalid_Value; - if (!hd->found.blob) - return KEYBOX_Nothing_Found; - - if (blob_get_type (hd->found.blob) != BLOBTYPE_X509) - return KEYBOX_Wrong_Blob_Type; - - buffer = _keybox_get_blob_image (hd->found.blob, &length); - if (length < 40) - return KEYBOX_Blob_Too_Short; - cert_off = get32 (buffer+8); - cert_len = get32 (buffer+12); - if (cert_off+cert_len > length) - return KEYBOX_Blob_Too_Short; - - reader = ksba_reader_new (); - if (!reader) - return KEYBOX_Out_Of_Core; - rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len); - if (rc) - { - ksba_reader_release (reader); - /* fixme: need to map the error codes */ - return KEYBOX_General_Error; - } - - cert = ksba_cert_new (); - if (!cert) - { - ksba_reader_release (reader); - return KEYBOX_Out_Of_Core; - } - - rc = ksba_cert_read_der (cert, reader); - if (rc) - { - ksba_cert_release (cert); - ksba_reader_release (reader); - /* fixme: need to map the error codes */ - return KEYBOX_General_Error; - } - - *r_cert = cert; - ksba_reader_release (reader); - return 0; -} - -#endif /*KEYBOX_WITH_X509*/ diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c deleted file mode 100644 index 8b189bbed..000000000 --- a/kbx/keybox-update.c +++ /dev/null @@ -1,433 +0,0 @@ -/* keybox-update.c - keybox update 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 - */ - -#include -#include -#include -#include -#include -#include - -#include "keybox-defs.h" - -#define EXTSEP_S "." - - -static int -create_tmp_file (const char *template, - char **r_bakfname, char **r_tmpfname, FILE **r_fp) -{ - char *bakfname, *tmpfname; - - *r_bakfname = NULL; - *r_tmpfname = NULL; - -# ifdef USE_ONLY_8DOT3 - /* Here is another Windoze bug?: - * you cant rename("pubring.kbx.tmp", "pubring.kbx"); - * but rename("pubring.kbx.tmp", "pubring.aaa"); - * works. So we replace .kbx by .bak or .tmp - */ - if (strlen (template) > 4 - && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") ) - { - bakfname = xtrymalloc (strlen (template) + 1); - if (!bakfname) - return KEYBOX_Out_Of_Core; - strcpy (bakfname, template); - strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak"); - - tmpfname = xtrymalloc (strlen (template) + 1); - if (!tmpfname) - { - xfree (bakfname); - return KEYBOX_Out_Of_Core; - } - strcpy (tmpfname,template); - strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp"); - } - else - { /* file does not end with kbx; hmmm */ - bakfname = xtrymalloc ( strlen (template) + 5); - if (!bakfname) - return KEYBOX_Out_Of_Core; - strcpy (stpcpy (bakfname, template), EXTSEP_S "bak"); - - tmpfname = xtrymalloc ( strlen (template) + 5); - if (!tmpfname) - { - xfree (bakfname); - return KEYBOX_Out_Of_Core; - } - strcpy (stpcpy (tmpfname, template), EXTSEP_S "tmp"); - } -# else /* Posix file names */ - bakfname = xtrymalloc (strlen (template) + 2); - if (!bakfname) - return KEYBOX_Out_Of_Core; - strcpy (stpcpy (bakfname,template),"~"); - - tmpfname = xtrymalloc ( strlen (template) + 5); - if (!tmpfname) - { - xfree (bakfname); - return KEYBOX_Out_Of_Core; - } - strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp"); -# endif /* Posix filename */ - - *r_fp = fopen (tmpfname, "wb"); - if (!*r_fp) - { - xfree (tmpfname); - xfree (bakfname); - return KEYBOX_File_Create_Error; - } - - *r_bakfname = bakfname; - *r_tmpfname = tmpfname; - return 0; -} - - -static int -rename_tmp_file (const char *bakfname, const char *tmpfname, - const char *fname, int secret ) -{ - int rc=0; - - /* restrict the permissions for secret keyboxs */ -#ifndef HAVE_DOSISH_SYSTEM -/* if (secret && !opt.preserve_permissions) */ -/* { */ -/* if (chmod (tmpfname, S_IRUSR | S_IWUSR) ) */ -/* { */ -/* log_debug ("chmod of `%s' failed: %s\n", */ -/* tmpfname, strerror(errno) ); */ -/* return KEYBOX_Write_File; */ -/* } */ -/* } */ -#endif - - /* fixme: invalidate close caches (not used with stdio)*/ -/* iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); */ -/* iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); */ -/* iobuf_ioctl (NULL, 2, 0, (char*)fname ); */ - - /* first make a backup file except for secret keyboxs */ - if (!secret) - { -#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - remove (bakfname); -#endif - if (rename (fname, bakfname) ) - { - return KEYBOX_File_Error; - } - } - - /* then rename the file */ -#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - remove (fname); -#endif - if (rename (tmpfname, fname) ) - { - rc = KEYBOX_File_Error; - if (secret) - { -/* log_info ("WARNING: 2 files with confidential" */ -/* " information exists.\n"); */ -/* log_info ("%s is the unchanged one\n", fname ); */ -/* log_info ("%s is the new one\n", tmpfname ); */ -/* log_info ("Please fix this possible security flaw\n"); */ - } - return rc; - } - - return 0; -} - - - -/* Perform insert/delete/update operation. - mode 1 = insert - 2 = delete - 3 = update -*/ -static int -blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, - int secret, off_t start_offset, unsigned int n_packets ) -{ - FILE *fp, *newfp; - int rc=0; - char *bakfname = NULL; - char *tmpfname = NULL; - char buffer[4096]; - int nread, nbytes; - - /* Open the source file. Because we do a rename, we have to check the - permissions of the file */ - if (access (fname, W_OK)) - return KEYBOX_Write_Error; - - fp = fopen (fname, "rb"); - if (mode == 1 && !fp && errno == ENOENT) - { /* insert mode but file does not exist: create a new keybox file */ - newfp = fopen (fname, "wb"); - if (!newfp ) - { - return KEYBOX_File_Create_Error; - } - - rc = _keybox_write_blob (blob, newfp); - if (rc) - { - return rc; - } - if ( fclose (newfp) ) - { - return KEYBOX_File_Create_Error; - } - -/* if (chmod( fname, S_IRUSR | S_IWUSR )) */ -/* { */ -/* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */ -/* return KEYBOX_File_Error; */ -/* } */ - return 0; /* ready */ - } - - if (!fp) - { - rc = KEYBOX_File_Open_Error; - goto leave; - } - - /* create the new file */ - rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); - if (rc) - { - fclose(fp); - goto leave; - } - - /* prepare for insert */ - if (mode == 1) - { - /* copy everything to the new file */ - while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) - { - if (fwrite (buffer, nread, 1, newfp) != 1) - { - rc = KEYBOX_Write_Error; - goto leave; - } - } - if (ferror (fp)) - { - rc = KEYBOX_Read_Error; - goto leave; - } - } - - /* prepare for delete or update */ - if ( mode == 2 || mode == 3 ) - { - off_t current = 0; - - /* copy first part to the new file */ - while ( current < start_offset ) - { - nbytes = DIM(buffer); - if (current + nbytes > start_offset) - nbytes = start_offset - current; - nread = fread (buffer, 1, nbytes, fp); - if (!fread) - break; - current += nread; - - if (fwrite (buffer, nread, 1, newfp) != 1) - { - rc = KEYBOX_Write_Error; - goto leave; - } - } - if (ferror (fp)) - { - rc = KEYBOX_Read_Error; - goto leave; - } - - /* skip this blob */ - rc = _keybox_read_blob (NULL, fp); - if (rc) - return rc; - } - - /* Do an insert or update */ - if ( mode == 1 || mode == 3 ) - { - rc = _keybox_write_blob (blob, newfp); - if (rc) - return rc; - } - - /* copy the rest of the packet for an delete or update */ - if (mode == 2 || mode == 3) - { - while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) - { - if (fwrite (buffer, nread, 1, newfp) != 1) - { - rc = KEYBOX_Write_Error; - goto leave; - } - } - if (ferror (fp)) - { - rc = KEYBOX_Read_Error; - goto leave; - } - } - - /* close both files */ - if (fclose(fp)) - { - rc = KEYBOX_File_Close_Error; - fclose (newfp); - goto leave; - } - if (fclose(newfp)) - { - rc = KEYBOX_File_Close_Error; - goto leave; - } - - rc = rename_tmp_file (bakfname, tmpfname, fname, secret); - - leave: - xfree(bakfname); - xfree(tmpfname); - return rc; -} - - - - -#ifdef KEYBOX_WITH_X509 -int -keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, - unsigned char *sha1_digest) -{ - int rc; - const char *fname; - KEYBOXBLOB blob; - - if (!hd) - return KEYBOX_Invalid_Handle; - if (!hd->kb) - return KEYBOX_Invalid_Handle; - fname = hd->kb->fname; - if (!fname) - return KEYBOX_Invalid_Handle; - - /* close this one otherwise we will mess up the position for a next - search. Fixme: it would be better to adjust the position after - the write opertions. */ - if (hd->fp) - { - fclose (hd->fp); - hd->fp = NULL; - } - - rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral); - if (!rc) - { - rc = blob_filecopy (1, fname, blob, hd->secret, 0, 0 ); - _keybox_release_blob (blob); - /* if (!rc && !hd->secret && kb_offtbl) */ - /* { */ - /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */ - /* } */ - } - return rc; -} - -int -keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert, - unsigned char *sha1_digest) -{ - return -1; -} - - -#endif /*KEYBOX_WITH_X509*/ - - -int -keybox_delete (KEYBOX_HANDLE hd) -{ - off_t off; - const char *fname; - FILE *fp; - int rc; - - if (!hd) - return KEYBOX_Invalid_Value; - if (!hd->found.blob) - return KEYBOX_Nothing_Found; - if (!hd->kb) - return KEYBOX_Invalid_Handle; - fname = hd->kb->fname; - if (!fname) - return KEYBOX_Invalid_Handle; - - off = _keybox_get_blob_fileoffset (hd->found.blob); - if (off == (off_t)-1) - return KEYBOX_General_Error; - off += 4; - - if (hd->fp) - { - fclose (hd->fp); - hd->fp = NULL; - } - - fp = fopen (hd->kb->fname, "r+b"); - if (!fp) - return KEYBOX_File_Open_Error; - - if (fseeko (fp, off, SEEK_SET)) - rc = KEYBOX_Write_Error; - else if (putc (0, fp) == EOF) - rc = KEYBOX_Write_Error; - else - rc = 0; - - if (fclose (fp)) - { - if (!rc) - rc = KEYBOX_File_Close_Error; - } - - return rc; -} - - diff --git a/kbx/keybox.h b/kbx/keybox.h deleted file mode 100644 index a763ec837..000000000 --- a/kbx/keybox.h +++ /dev/null @@ -1,125 +0,0 @@ -/* keybox.h - Keybox 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 KEYBOX_H -#define KEYBOX_H 1 -#ifdef __cplusplus -extern "C" { -#if 0 - } -#endif -#endif - -#include "keybox-search-desc.h" - -#define KEYBOX_WITH_OPENPGP 1 -#define KEYBOX_WITH_X509 1 - - -#ifdef KEYBOX_WITH_OPENPGP -# undef KEYBOX_WITH_OPENPGP -/*#include */ -#endif - -#ifdef KEYBOX_WITH_X509 -# include -#endif - - -typedef enum { - KEYBOX_No_Error = 0, - KEYBOX_General_Error = 1, - KEYBOX_Out_Of_Core = 2, - KEYBOX_Invalid_Value = 3, - KEYBOX_Timeout = 4, - KEYBOX_Read_Error = 5, - KEYBOX_Write_Error = 6, - KEYBOX_File_Error = 7, - KEYBOX_Blob_Too_Short = 8, - KEYBOX_Blob_Too_Large = 9, - KEYBOX_Invalid_Handle = 10, - KEYBOX_File_Create_Error = 11, - KEYBOX_File_Open_Error = 12, - KEYBOX_File_Close_Error = 13, - KEYBOX_Nothing_Found = 14, - KEYBOX_Wrong_Blob_Type = 15, - KEYBOX_Missing_Value = 16, -} KeyboxError; - - - -typedef struct keybox_handle *KEYBOX_HANDLE; - - -/*-- keybox-init.c --*/ -void *keybox_register_file (const char *fname, int secret); -int keybox_is_writable (void *token); - -KEYBOX_HANDLE keybox_new (void *token, int secret); -void keybox_release (KEYBOX_HANDLE hd); -const char *keybox_get_resource_name (KEYBOX_HANDLE hd); -int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes); - - -/*-- keybox-search.c --*/ -#ifdef KEYBOX_WITH_X509 -int keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *ret_cert); -#endif /*KEYBOX_WITH_X509*/ - -int keybox_search_reset (KEYBOX_HANDLE hd); -int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc); - - -/*-- keybox-update.c --*/ -#ifdef KEYBOX_WITH_X509 -int keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, - unsigned char *sha1_digest); -int keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert, - unsigned char *sha1_digest); -#endif /*KEYBOX_WITH_X509*/ - -int keybox_delete (KEYBOX_HANDLE hd); - - -/*-- --*/ - -#if 0 -int keybox_lock (KEYBOX_HANDLE hd, int yes); -int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb); -int keybox_locate_writable (KEYBOX_HANDLE hd); -int keybox_search_reset (KEYBOX_HANDLE hd); -int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); -int keybox_rebuild_cache (void *); -#endif - - -/*-- keybox-util.c --*/ -void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), - void *(*new_realloc_func)(void *p, size_t n), - void (*new_free_func)(void*) ); - -/*-- keybox-errors.c (built) --*/ -const char *keybox_strerror (KeyboxError err); - - -#ifdef __cplusplus -} -#endif -#endif /*KEYBOX_H*/ diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog deleted file mode 100644 index a24a6e7ef..000000000 --- a/keyserver/ChangeLog +++ /dev/null @@ -1,291 +0,0 @@ -2002-10-14 David Shaw - - * gpgkeys_hkp.c (write_quoted): Use %-encoding instead of - \-encoding. - (parse_hkp_index): Use new keyserver key listing format, and add - support for disabled keys via include-disabled. - - * gpgkeys_ldap.c (get_key): Don't print keysize unless it's >0. - (printquoted): Use %-encoding instead of \-encoding. - (search_key): Use new keyserver key listing format. - -2002-10-08 David Shaw - - * gpgkeys_ldap.c (search_key, main): Make sure LDAP values are - freed in case of error. - - * gpgkeys_ldap.c (fail_all): New function to unwind a keylist and - error each item. - (main): Call fail_all from here, as needed. Also add a NO_MEMORY - error in an appropriate place and fix error return code. - (ldap_err_to_gpg_err): Add KEYSERVER_UNREACHABLE. - - * gpgkeys_hkp.c (fail_all): New function to unwind a keylist and - error each item. - (main): Call fail_all from here. Also add a NO_MEMORY error in an - appropriate place. - (get_key): Use new UNREACHABLE error for network errors. - -2002-09-26 Werner Koch - - * gpgkeys_ldap.c (send_key): Removed non-constant initializers. - -2002-09-24 David Shaw - - * gpgkeys_ldap.c (ldap_err_to_gpg_err, ldap_to_gpg_err, send_key, - get_key, search_key, main): Some minor error reporting - enhancements for use with GPA (show reasons for KEY FAILED). - - * gpgkeys_hkp.c (send_key, get_key, search_key, main): Some minor - error reporting enhancements for use with GPA (show reasons for - KEY FAILED). - -2002-09-20 Werner Koch - - * gpgkeys_hkp.c (handle_old_hkp_index): s/input/inp/ to avoid - shadowing warning. - -2002-09-19 David Shaw - - * gpgkeys_hkp.c (get_key, handle_old_hkp_index, search_key): - Properly handle line truncation. - -2002-09-16 David Shaw - - * gpgkeys_mailto.in: Add quasi-RFC-2368 mailto:email@addr?from= - syntax so people can set their own email address to respond to. - - * gpgkeys_hkp.c (get_key): Properly respond with KEY FAILED (to - gpg) and "key not found" (to user) on failure. - -2002-09-13 David Shaw - - * gpgkeys_hkp.c: (search_key, handle_old_hkp_index): Try and - request a machine-readable key index. If the server supports - this, pass it through. If the server does not support it, parse - the "index" page. - -2002-09-12 Stefan Bellon - - * gpgkeys_hkp.c: Tidied up RISC OS initializations. - -2002-09-12 David Shaw - - * gpgkeys_hkp.c (main): Remove warning - this is no longer - experimental code. - -2002-09-09 Werner Koch - - * gpgkeys_hkp.c (send_key, get_key, search_key): Check return - value of malloc. - (dehtmlize): Use ascii_tolower to protect against weird locales. - Cast the argument for isspace for the sake of broken HP/UXes. - (search_key): Check return value of realloc. - -2002-09-09 David Shaw - - * gpgkeys_ldap.c (get_key): Some compilers (RISC OS, HPUX c89) - don't like using variables as array initializers. - - * gpgkeys_hkp.c (send_key): Use CRLF in headers. - -2002-08-28 David Shaw - - * gpgkeys_hkp.c (parse_hkp_index): Use same types on all - platforms. This was probably leftover from earlier code where the - typing mattered. - - * gpgkeys_hkp.c: Overall cleanup from iobuf conversion. Be - consistent in m_alloc and malloc usage. Remove include-disabled - (meaningless on HKP). RISC OS tweak. - -2002-08-27 David Shaw - - * gpgkeys_hkp.c, Makefile.am: Convert over to using iobufs. - - * gpgkeys_hkp.c (http_get, http_post): Use CRLF for line endings. - - * gpgkeys_hkp.c: Include util.h on RISC OS as per Stefan. Include - a replacement for hstrerror() for those platforms (such as RISC - OS) that don't have it. - -2002-08-26 David Shaw - - * Makefile.am: May as well include gpgkeys_hkp.c in the - distribution now. It works well enough without proxies, and isn't - built by default. It would be good to get some test experience - with it. - - * gpgkeys_hkp.c (main): Don't warn about include-subkeys - it - isn't unsupported, it's actually non-meaningful in the context of - HKP (yet). - - * gpgkeys_hkp.c (parse_hkp_index, dehtmlize): Move HTML - functionality into new "dehtmlize" function. Remove HTML before - trying to parse each line from the keyserver. If the keyserver - provides key type information in the listing, use it. (Copy over - from g10/hkp.c). - -2002-08-19 David Shaw - - * gpgkeys_hkp.c (get_key, parse_hkp_index): Bring over latest code - from g10/hkp.c. - - * gpgkeys_ldap.c (get_key): Fix cosmetic URL display problem - (extra ":" at the end). - -2002-08-03 Stefan Bellon - - * gpgkeys_ldap.c: Tidied up RISC OS initializations. - -2002-07-25 David Shaw - - * gpgkeys_hkp.c: "Warning" -> "WARNING" - -2002-07-24 David Shaw - - * Makefile.am: Install keyserver helpers in @GNUPG_LIBEXECDIR@ - -2002-07-15 David Shaw - - * gpgkeys_ldap.c (send_key, get_key, main): Consult the server - version string to determine whether to use pgpKey or pgpKeyV2. - -2002-07-09 David Shaw - - * gpgkeys_mailto.in: Use new OPAQUE tag for non net-path URIs. - Fail more elegantly if there is no email address to send to. Show - the GnuPG version in the message body. - -2002-07-04 David Shaw - - * gpgkeys_ldap.c (get_key), gpgkeys_hkp.c (get_key): Display - keyserver URI as a URI, but only if verbose. - -2002-07-01 David Shaw - - * gpgkeys_hkp.c (parse_hkp_index): Error if the keyserver returns - an unparseable HKP response. - - * gpgkeys_hkp.c (main): Warn on honor-http-proxy, - broken-http-proxy, and include-subkeys (not supported yet). - - * gpgkeys_ldap.c (main), gpgkeys_hkp.c (http_connect, main): Fix - some shadowing warnings. - -2002-06-11 David Shaw - - * Makefile.am: Don't hard-code the LDAP libraries - get them from - LDAPLIBS via configure. Also, gpgkeys_hkp is a program, not a - script. - -2002-06-10 David Shaw - - * gpgkeys_ldap.c (include_subkeys): Default "include-subkeys" to - off, since GnuPG now defaults it to on. - -2002-06-06 David Shaw - - * gpgkeys_hkp.c (parse_hkp_index): Type tweaks. - - * gpgkeys_hkp.c (main): Add experimental code warning. - -2002-06-05 David Shaw - - * Makefile.am, gpgkeys_hkp.c (new): Experimental HKP keyserver - interface. - -2002-05-08 David Shaw - - * gpgkeys_ldap.c: Include if we absolutely must. This - helps when compiling against a very old OpenLDAP. - -2002-04-29 David Shaw - - * gpgkeys_mailto.in: Properly handle key requests in full - fingerprint form. - -2002-03-29 David Shaw - - * gpgkeys_ldap.c (printquoted): Quote backslashes within keyserver - search responses. - -2002-02-25 David Shaw - - * gpgkeys_ldap (get_key): LDAP keyservers do not support v3 - fingerprints, so error out if someone tries. Actually, they don't - support any fingerprints, but at least we can calculate a keyid - from a v4 fingerprint. - -2002-02-23 David Shaw - - * gpgkeys_ldap: Clarify the notion of a partial failure. This is - possible if more than one key is being handled in a batch, and one - fails while the other succeeds. Note that a search that comes up - with no results is not a failure - that is a valid response of "no - answer". - - * gpgkeys_ldap.c (get_key): Allow GnuPG to send us full v4 - fingerprints, long key ids, or short key ids while fetching. - Since the LDAP server doesn't actually handle fingerprints, chop - them down to long key ids for actual use. - - * gpgkeys_ldap.c (main, get_key): When searching for a keyid, - search for subkeys as well as primary keys. This is mostly - significant when automatically fetching the key based on the id in - a header (i.e. "signature made by...."). "no-include-subkeys" - disables. - -2002-02-14 David Shaw - - * gpgkeys_ldap.c: Fix compiler warning. - - * gpgkeys_ldap.c: Be much more robust with mangled input files. - -2001-12-28 David Shaw - - * gpgkeys_mailto.in: Use the new OUTOFBAND indicator so gpg knows - not to try and import anything. Also turn on perl -w for - warnings. - - * gpgkeys_ldap.c (main): If we're using temp files (rather than - stdin/stdout), make sure the file is closed when we're done. - -2001-12-20 David Shaw - - * Properly free the LDAP response when we're done with it. - - * Now that we handle multiple keys, we must remove duplicates as - the LDAP keyserver returns keys with multiple user IDs multiple - times. - - * Properly handle multiple keys with the same key ID (it's really - rare, so fetch "0xDEADBEEF" to test this). - -2001-12-17 David Shaw - - * gpgkeys_ldap.c, gpgkeys_mailto.in: Fix GNU capitalization - issues. Prefix log messages with "gpgkeys" to clarify which - program is generating them. - -2001-12-14 David Shaw - - * gpgkeys_ldap.c (search_key): Use unsigned int rather than uint - for portability. - -2001-12-04 David Shaw - - * Initial version of gpgkeys_ldap (LDAP keyserver helper) and - gpgkeys_mailto (email keyserver helper) - - - Copyright 1998, 1999, 2000, 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. - \ No newline at end of file diff --git a/keyserver/Makefile.am b/keyserver/Makefile.am deleted file mode 100644 index 6ef15d801..000000000 --- a/keyserver/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - -INCLUDES = -I$(top_srcdir)/include -EXTRA_PROGRAMS = gpgkeys_ldap gpgkeys_hkp -EXTRA_SCRIPTS = gpgkeys_mailto -libexecdir = @GNUPG_LIBEXECDIR@ - -# We don't need the libs the regular GPG binaries do -LIBS= - -libexec_PROGRAMS = @GPGKEYS_LDAP@ @GPGKEYS_HKP@ -libexec_SCRIPTS = @GPGKEYS_MAILTO@ -noinst_SCRIPTS = gpgkeys_test - -gpgkeys_ldap_LDADD = @LDAPLIBS@ @NETLIBS@ -gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ diff --git a/keyserver/gpgkeys_hkp.c b/keyserver/gpgkeys_hkp.c deleted file mode 100644 index f5a0ed0ca..000000000 --- a/keyserver/gpgkeys_hkp.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* gpgkeys_hkp.c - talk to an HKP keyserver - * 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 -#include -#include -#include -#include -#include -#include -#define INCLUDED_BY_MAIN_MODULE 1 -#include "util.h" -#include "http.h" -#include "keyserver.h" - -#define GET 0 -#define SEND 1 -#define SEARCH 2 -#define MAX_LINE 80 - -int verbose=0,include_revoked=0,include_disabled=0; -unsigned int http_flags=0; -char host[80]={'\0'},port[10]={'\0'}; -FILE *input=NULL,*output=NULL,*console=NULL; - -struct keylist -{ - char str[MAX_LINE]; - struct keylist *next; -}; - -#ifdef __riscos__ -RISCOS_GLOBAL_STATICS("HKP Keyfetcher Heap") -#endif /* __riscos__ */ - -int -urlencode_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) -{ - size_t size = *ret_len; - int rc=0; - - if( control == IOBUFCTRL_FLUSH ) { - const byte *p; - for(p=buf; size; p++, size-- ) { - if( isalnum(*p) || *p == '-' ) - iobuf_put( a, *p ); - else if( *p == ' ' ) - iobuf_put( a, '+' ); - else { - char numbuf[5]; - sprintf(numbuf, "%%%02X", *p ); - iobuf_writestr(a, numbuf ); - } - } - } - else if( control == IOBUFCTRL_DESC ) - *(char**)buf = "urlencode_filter"; - return rc; -} - -int -send_key(int *eof) -{ - int rc,gotit=0,ret=KEYSERVER_INTERNAL_ERROR; - char keyid[17]; - char *request; - struct http_context hd; - unsigned int status; - IOBUF temp = iobuf_temp(); - char line[MAX_LINE]; - - request=malloc(strlen(host)+100); - if(!request) - { - fprintf(console,"gpgkeys: out of memory\n"); - return KEYSERVER_NO_MEMORY; - } - - iobuf_push_filter(temp,urlencode_filter,NULL); - - /* Read and throw away input until we see the BEGIN */ - - while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) - { - gotit=1; - break; - } - - if(!gotit) - { - /* i.e. eof before the KEY BEGIN was found. This isn't an - error. */ - *eof=1; - ret=KEYSERVER_OK; - goto fail; - } - - gotit=0; - - /* Now slurp up everything until we see the END */ - - while(fgets(line,MAX_LINE,input)) - if(sscanf(line,"KEY %16s END\n",keyid)==1) - { - gotit=1; - break; - } - else - if(iobuf_writestr(temp,line)) - { - fprintf(console,"gpgkeys: internal iobuf error\n"); - goto fail; - } - - if(!gotit) - { - fprintf(console,"gpgkeys: no KEY %s END found\n",keyid); - *eof=1; - ret=KEYSERVER_KEY_INCOMPLETE; - goto fail; - } - - iobuf_flush_temp(temp); - - sprintf(request,"x-hkp://%s%s%s/pks/add", - host,port[0]?":":"",port[0]?port:""); - - if(verbose>2) - fprintf(console,"gpgkeys: HTTP URL is \"%s\"\n",request); - - rc=http_open(&hd,HTTP_REQ_POST,request,http_flags); - if(rc) - { - fprintf(console,"gpgkeys: unable to connect to `%s'\n",host); - goto fail; - } - - sprintf(request,"Content-Length: %u\r\n", - (unsigned)iobuf_get_temp_length(temp)+9); - iobuf_writestr(hd.fp_write,request); - - http_start_data(&hd); - - iobuf_writestr(hd.fp_write,"keytext="); - iobuf_write(hd.fp_write, - iobuf_get_temp_buffer(temp),iobuf_get_temp_length(temp)); - iobuf_put(hd.fp_write,'\n'); - - rc=http_wait_response(&hd,&status); - if(rc) - { - fprintf(console,"gpgkeys: error sending to `%s': %s\n", - host,g10_errstr(rc)); - goto fail; - } - - if((status/100)!=2) - { - fprintf(console,"gpgkeys: remote server returned error %d\n",status); - fprintf(output,"KEY %s FAILED %d\n",keyid,ret); - goto fail; - } - - fprintf(output,"KEY %s SENT\n",keyid); - - ret=KEYSERVER_OK; - - fail: - free(request); - iobuf_close(temp); - http_close(&hd); - - return ret; -} - -int -get_key(char *getkey) -{ - int rc,gotit=0; - char search[29]; - char *request; - struct http_context hd; - - /* Build the search string. HKP only uses the short key IDs. */ - - if(strncmp(getkey,"0x",2)==0) - getkey+=2; - - if(strlen(getkey)==32) - { - fprintf(console, - "gpgkeys: HKP keyservers do not support v3 fingerprints\n"); - fprintf(output,"KEY 0x%s BEGIN\n",getkey); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED); - return KEYSERVER_NOT_SUPPORTED; - } - - if(strlen(getkey)>8) - { - char *offset=&getkey[strlen(getkey)-8]; - - /* fingerprint or long key id. Take the last 8 characters and - treat it like a short key id */ - - sprintf(search,"0x%.8s",offset); - } - else - { - /* short key id */ - - sprintf(search,"0x%.8s",getkey); - } - - fprintf(output,"KEY 0x%s BEGIN\n",getkey); - - if(verbose) - fprintf(console,"gpgkeys: requesting key 0x%s from hkp://%s%s%s\n", - getkey,host,port[0]?":":"",port[0]?port:""); - - request=malloc(strlen(host)+100); - if(!request) - { - fprintf(console,"gpgkeys: out of memory\n"); - return KEYSERVER_NO_MEMORY; - } - - sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=get&search=%s", - host,port[0]?":":"",port[0]?port:"", search); - - if(verbose>2) - fprintf(console,"gpgkeys: HTTP URL is \"%s\"\n",request); - - rc=http_open_document(&hd,request,http_flags); - if(rc!=0) - { - fprintf(console,"gpgkeys: HKP fetch error: %s\n", - rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc)); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey, - rc==G10ERR_NETWORK?KEYSERVER_UNREACHABLE:KEYSERVER_INTERNAL_ERROR); - } - else - { - unsigned int maxlen=1024,buflen; - byte *line=NULL; - - while(iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen)) - { - maxlen=1024; - - if(gotit) - { - fprintf(output,line); - if(strcmp(line,"-----END PGP PUBLIC KEY BLOCK-----\n")==0) - break; - } - else - if(strcmp(line,"-----BEGIN PGP PUBLIC KEY BLOCK-----\n")==0) - { - fprintf(output,line); - gotit=1; - } - } - - if(gotit) - fprintf(output,"KEY 0x%s END\n",getkey); - else - { - fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey); - fprintf(output,"KEY 0x%s FAILED %d\n", - getkey,KEYSERVER_KEY_NOT_FOUND); - } - - m_free(line); - } - - free(request); - - return KEYSERVER_OK; -} - -/* Remove anything and de-urlencode in place. Note - that this requires all brackets to be closed on the same line. It - also means that the result is never larger than the input. */ -void -dehtmlize(char *line) -{ - int parsedindex=0; - char *parsed=line; - - while(*line!='\0') - { - switch(*line) - { - case '<': - while(*line!='>' && *line!='\0') - line++; - - if(*line!='\0') - line++; - break; - - case '&': - if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='l') && - (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') && - (*(line+3)!='\0' && *(line+3)==';')) - { - parsed[parsedindex++]='<'; - line+=4; - break; - } - else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='g') && - (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') && - (*(line+3)!='\0' && *(line+3)==';')) - { - parsed[parsedindex++]='>'; - line+=4; - break; - } - else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='a') && - (*(line+2)!='\0' && ascii_tolower(*(line+2))=='m') && - (*(line+3)!='\0' && ascii_tolower(*(line+3))=='p') && - (*(line+4)!='\0' && *(line+4)==';')) - { - parsed[parsedindex++]='&'; - line+=5; - break; - } - - default: - parsed[parsedindex++]=*line; - line++; - break; - } - } - - parsed[parsedindex]='\0'; - - /* Chop off any trailing whitespace. Note that the HKP servers have - \r\n as line endings, and the NAI HKP servers have just \n. */ - - if(parsedindex>0) - { - parsedindex--; - while(isspace(((unsigned char *)parsed)[parsedindex])) - { - parsed[parsedindex]='\0'; - parsedindex--; - } - } -} - -int -write_quoted(IOBUF a, const char *buf, char delim) -{ - char quoted[5]; - - sprintf(quoted,"%%%02X",delim); - - while(*buf) - { - if(*buf==delim) - { - if(iobuf_writestr(a,quoted)) - return -1; - } - else if(*buf=='%') - { - if(iobuf_writestr(a,"%25")) - return -1; - } - else - { - if(iobuf_writebyte(a,*buf)) - return -1; - } - - buf++; - } - - return 0; -} - -/* pub 2048/3CB3B415 1998/04/03 David M. Shaw <dshaw@jabberwocky.com> */ - -/* Luckily enough, both the HKP server and NAI HKP interface to their - LDAP server are close enough in output so the same function can - parse them both. */ - -int -parse_hkp_index(IOBUF buffer,char *line) -{ - int ret=0; - - /* printf("Open %d, LINE: \"%s\"\n",open,line); */ - - dehtmlize(line); - - /* printf("Now open %d, LINE: \"%s\"\n",open,line); */ - - if(line[0]=='\0') - return 0; - else if(ascii_strncasecmp(line,"pub",3)==0) - { - char *tok,*keyid,*uid=NULL,number[15]; - int bits=0,type=0,disabled=0,revoked=0; - u32 createtime=0; - - line+=3; - - if(*line=='-') - { - disabled=1; - if(!include_disabled) - return 0; - } - - line++; - - tok=strsep(&line,"/"); - if(tok==NULL) - return ret; - - if(tok[strlen(tok)-1]=='R') - type=1; - else if(tok[strlen(tok)-1]=='D') - type=17; - - bits=atoi(tok); - - keyid=strsep(&line," "); - - tok=strsep(&line," "); - if(tok!=NULL) - { - char *temp=tok; - - /* The date parser wants '-' instead of '/', so... */ - while(*temp!='\0') - { - if(*temp=='/') - *temp='-'; - - temp++; - } - - createtime=scan_isodatestr(tok); - } - - if(line!=NULL) - { - while(*line==' ' && *line!='\0') - line++; - - if(*line!='\0') - { - if(strncmp(line,"*** KEY REVOKED ***",19)==0) - { - revoked=1; - if(!include_revoked) - return 0; - } - else - uid=line; - } - } - - if(keyid) - { - iobuf_writestr(buffer,"pub:"); - - write_quoted(buffer,keyid,':'); - - iobuf_writestr(buffer,":"); - - if(type) - { - sprintf(number,"%d",type); - write_quoted(buffer,number,':'); - } - - iobuf_writestr(buffer,":"); - - if(bits) - { - sprintf(number,"%d",bits); - write_quoted(buffer,number,':'); - } - - iobuf_writestr(buffer,":"); - - if(createtime) - { - sprintf(number,"%d",createtime); - write_quoted(buffer,number,':'); - } - - iobuf_writestr(buffer,"::"); - - if(revoked) - write_quoted(buffer,"r",':'); - - if(disabled) - write_quoted(buffer,"d",':'); - - if(uid) - { - iobuf_writestr(buffer,"\nuid:"); - write_quoted(buffer,uid,':'); - } - - iobuf_writestr(buffer,"\n"); - - ret=1; - } - } - else if(ascii_strncasecmp(line," ",3)==0) - { - while(*line==' ' && *line!='\0') - line++; - - if(*line!='\0') - { - iobuf_writestr(buffer,"uid:"); - write_quoted(buffer,line,':'); - iobuf_writestr(buffer,"\n"); - } - } - -#if 0 - else if(open) - { - /* Try and catch some bastardization of HKP. If we don't have - certain unchanging landmarks, we can't reliably parse the - response. This only complains about problems within the key - section itself. Headers and footers should not matter. */ - - fprintf(console,"gpgkeys: this keyserver does not support searching\n"); - ret=-1; - } -#endif - - return ret; -} - -void -handle_old_hkp_index(IOBUF inp) -{ - int ret,rc,count=0; - unsigned int buflen; - byte *line=NULL; - IOBUF buffer=iobuf_temp(); - - do - { - unsigned int maxlen=1024; - - /* This is a judgement call. Is it better to slurp up all the - results before prompting the user? On the one hand, it - probably makes the keyserver happier to not be blocked on - sending for a long time while the user picks a key. On the - other hand, it might be nice for the server to be able to - stop sending before a large search result page is - complete. */ - - rc=iobuf_read_line(inp,&line,&buflen,&maxlen); - - ret=parse_hkp_index(buffer,line); - if(ret==-1) - break; - - if(rc!=0) - count+=ret; - } - while(rc!=0); - - m_free(line); - - if(ret>-1) - fprintf(output,"info:1:%d\n%s",count,iobuf_get_temp_buffer(buffer)); - - iobuf_close(buffer); -} - -int -search_key(char *searchkey) -{ - int max=0,len=0,ret=KEYSERVER_INTERNAL_ERROR,rc; - struct http_context hd; - char *search=NULL,*request=NULL,*skey=searchkey; - - fprintf(output,"SEARCH %s BEGIN\n",searchkey); - - /* Build the search string. It's going to need url-encoding. */ - - while(*skey!='\0') - { - if(max-len<3) - { - max+=100; - search=realloc(search,max+1); /* Note +1 for \0 */ - if (!search) - { - fprintf(console,"gpgkeys: out of memory\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - } - - if(isalnum(*skey) || *skey=='-') - search[len++]=*skey; - else if(*skey==' ') - search[len++]='+'; - else - { - sprintf(&search[len],"%%%02X",*skey); - len+=3; - } - - skey++; - } - - search[len]='\0'; - - fprintf(console,("gpgkeys: searching for \"%s\" from HKP server %s\n"), - searchkey,host); - - request=malloc(strlen(host)+100+strlen(search)); - if(!request) - { - fprintf(console,"gpgkeys: out of memory\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=index&options=mr&search=%s", - host,port[0]?":":"",port[0]?port:"",search); - - if(verbose>2) - fprintf(console,"gpgkeys: HTTP URL is \"%s\"\n",request); - - rc=http_open_document(&hd,request,http_flags); - if(rc) - { - fprintf(console,"gpgkeys: can't search keyserver `%s': %s\n", - host,rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc)); - } - else - { - unsigned int maxlen=1024,buflen; - byte *line=NULL; - - /* Is it a pksd that knows how to handle machine-readable - format? */ - - rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen); - if(line[0]=='<') - handle_old_hkp_index(hd.fp_read); - else - do - { - fprintf(output,"%s",line); - maxlen=1024; - rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen); - } - while(rc!=0); - - m_free(line); - - http_close(&hd); - - fprintf(output,"SEARCH %s END\n",searchkey); - - ret=KEYSERVER_OK; - } - - fail: - - free(request); - free(search); - - if(ret!=KEYSERVER_OK) - fprintf(output,"SEARCH %s FAILED %d\n",searchkey,ret); - - return ret; -} - -void -fail_all(struct keylist *keylist,int action,int err) -{ - if(!keylist) - return; - - if(action==SEARCH) - { - fprintf(output,"SEARCH "); - while(keylist) - { - fprintf(output,"%s ",keylist->str); - keylist=keylist->next; - } - fprintf(output,"FAILED %d\n",err); - } - else - while(keylist) - { - fprintf(output,"KEY %s FAILED %d\n",keylist->str,err); - keylist=keylist->next; - } -} - -int -main(int argc,char *argv[]) -{ - int arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR; - char line[MAX_LINE]; - int failed=0; - struct keylist *keylist=NULL,*keyptr=NULL; - -#ifdef __riscos__ - riscos_global_defaults(); -#endif - - console=stderr; - - while((arg=getopt(argc,argv,"ho:"))!=-1) - switch(arg) - { - default: - case 'h': - fprintf(console,"-h\thelp\n"); - fprintf(console,"-o\toutput to this file\n"); - return KEYSERVER_OK; - - case 'o': - output=fopen(optarg,"w"); - if(output==NULL) - { - fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n", - optarg,strerror(errno)); - return KEYSERVER_INTERNAL_ERROR; - } - - break; - } - - if(argc>optind) - { - input=fopen(argv[optind],"r"); - if(input==NULL) - { - fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n", - argv[optind],strerror(errno)); - return KEYSERVER_INTERNAL_ERROR; - } - } - - if(input==NULL) - input=stdin; - - if(output==NULL) - output=stdout; - - /* Get the command and info block */ - - while(fgets(line,MAX_LINE,input)!=NULL) - { - int version; - char commandstr[7]; - char optionstr[30]; - char hash; - - if(line[0]=='\n') - break; - - if(sscanf(line,"%c",&hash)==1 && hash=='#') - continue; - - if(sscanf(line,"COMMAND %6s\n",commandstr)==1) - { - commandstr[6]='\0'; - - if(strcasecmp(commandstr,"get")==0) - action=GET; - else if(strcasecmp(commandstr,"send")==0) - action=SEND; - else if(strcasecmp(commandstr,"search")==0) - action=SEARCH; - - continue; - } - - if(sscanf(line,"HOST %79s\n",host)==1) - { - host[79]='\0'; - continue; - } - - if(sscanf(line,"PORT %9s\n",port)==1) - { - port[9]='\0'; - continue; - } - - if(sscanf(line,"VERSION %d\n",&version)==1) - { - if(version!=KEYSERVER_PROTO_VERSION) - { - ret=KEYSERVER_VERSION_ERROR; - goto fail; - } - - continue; - } - - if(sscanf(line,"OPTION %29s\n",optionstr)==1) - { - int no=0; - char *start=&optionstr[0]; - - optionstr[29]='\0'; - - if(strncasecmp(optionstr,"no-",3)==0) - { - no=1; - start=&optionstr[3]; - } - - if(strcasecmp(start,"verbose")==0) - { - if(no) - verbose--; - else - verbose++; - } - else if(strcasecmp(start,"include-revoked")==0) - { - if(no) - include_revoked=0; - else - include_revoked=1; - } - else if(strcasecmp(start,"include-disabled")==0) - { - if(no) - include_disabled=0; - else - include_disabled=1; - } - else if(strcasecmp(start,"honor-http-proxy")==0) - { - if(no) - http_flags&=~HTTP_FLAG_TRY_PROXY; - else - http_flags|=HTTP_FLAG_TRY_PROXY; - - } - else if(strcasecmp(start,"broken-http-proxy")==0) - { - if(no) - http_flags&=~HTTP_FLAG_NO_SHUTDOWN; - else - http_flags|=HTTP_FLAG_NO_SHUTDOWN; - } - - continue; - } - } - - /* If it's a GET or a SEARCH, the next thing to come in is the - keyids. If it's a SEND, then there are no keyids. */ - - if(action==SEND) - while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n'); - else if(action==GET || action==SEARCH) - { - for(;;) - { - struct keylist *work; - - if(fgets(line,MAX_LINE,input)==NULL) - break; - else - { - if(line[0]=='\n') - break; - - work=malloc(sizeof(struct keylist)); - if(work==NULL) - { - fprintf(console,"gpgkeys: out of memory while " - "building key list\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - strcpy(work->str,line); - - /* Trim the trailing \n */ - work->str[strlen(line)-1]='\0'; - - work->next=NULL; - - /* Always attach at the end to keep the list in proper - order for searching */ - if(keylist==NULL) - keylist=work; - else - keyptr->next=work; - - keyptr=work; - } - } - } - else - { - fprintf(console,"gpgkeys: no keyserver command specified\n"); - goto fail; - } - - /* Send the response */ - - fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); - fprintf(output,"PROGRAM %s\n\n",VERSION); - - if(verbose>1) - { - fprintf(console,"Host:\t\t%s\n",host); - if(port[0]) - fprintf(console,"Port:\t\t%s\n",port); - fprintf(console,"Command:\t%s\n",action==GET?"GET": - action==SEND?"SEND":"SEARCH"); - } - -#if 0 - if(verbose>1) - { - vals=ldap_get_values(ldap,res,"software"); - if(vals!=NULL) - { - fprintf(console,"Server: \t%s\n",vals[0]); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,res,"version"); - if(vals!=NULL) - { - fprintf(console,"Version:\t%s\n",vals[0]); - ldap_value_free(vals); - } - } -#endif - - switch(action) - { - case GET: - keyptr=keylist; - - while(keyptr!=NULL) - { - if(get_key(keyptr->str)!=KEYSERVER_OK) - failed++; - - keyptr=keyptr->next; - } - break; - - case SEND: - { - int eof=0; - - do - { - if(send_key(&eof)!=KEYSERVER_OK) - failed++; - } - while(!eof); - } - break; - - case SEARCH: - { - char *searchkey=NULL; - int len=0; - - /* To search, we stick a space in between each key to search - for. */ - - keyptr=keylist; - while(keyptr!=NULL) - { - len+=strlen(keyptr->str)+1; - keyptr=keyptr->next; - } - - searchkey=malloc(len+1); - if(searchkey==NULL) - { - ret=KEYSERVER_NO_MEMORY; - fail_all(keylist,action,KEYSERVER_NO_MEMORY); - goto fail; - } - - searchkey[0]='\0'; - - keyptr=keylist; - while(keyptr!=NULL) - { - strcat(searchkey,keyptr->str); - strcat(searchkey," "); - keyptr=keyptr->next; - } - - /* Nail that last space */ - searchkey[strlen(searchkey)-1]='\0'; - - if(search_key(searchkey)!=KEYSERVER_OK) - failed++; - - free(searchkey); - } - - break; - } - - if(!failed) - ret=KEYSERVER_OK; - - fail: - while(keylist!=NULL) - { - struct keylist *current=keylist; - keylist=keylist->next; - free(current); - } - - if(input!=stdin) - fclose(input); - - if(output!=stdout) - fclose(output); - - return ret; -} diff --git a/keyserver/gpgkeys_ldap.c b/keyserver/gpgkeys_ldap.c deleted file mode 100644 index ad8f0cf13..000000000 --- a/keyserver/gpgkeys_ldap.c +++ /dev/null @@ -1,1107 +0,0 @@ -/* gpgkeys_ldap.c - talk to a LDAP keyserver - * 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 -#include -#include -#include -#include -#include -#include -#ifdef NEED_LBER_H -#include -#endif -#include -#include "keyserver.h" - -#ifdef __riscos__ -#include "util.h" -#endif - -#define GET 0 -#define SEND 1 -#define SEARCH 2 -#define MAX_LINE 80 - -int verbose=0,include_disabled=0,include_revoked=0,include_subkeys=0; -char *basekeyspacedn=NULL; -char host[80]={'\0'}; -char portstr[10]={'\0'}; -char *pgpkeystr="pgpKey"; -FILE *input=NULL,*output=NULL,*console=NULL; -LDAP *ldap=NULL; - -struct keylist -{ - char str[MAX_LINE]; - struct keylist *next; -}; - -#ifdef __riscos__ -RISCOS_GLOBAL_STATICS("LDAP Keyfetcher Heap") -#endif /* __riscos__ */ - -int -ldap_err_to_gpg_err(int err) -{ - int ret; - - switch(err) - { - case LDAP_ALREADY_EXISTS: - ret=KEYSERVER_KEY_EXISTS; - break; - - case LDAP_SERVER_DOWN: - ret=KEYSERVER_UNREACHABLE; - break; - - default: - ret=KEYSERVER_GENERAL_ERROR; - break; - } - - return ret; -} - -int -ldap_to_gpg_err(LDAP *ld) -{ -#if defined(HAVE_LDAP_GET_OPTION) - - int err; - - if(ldap_get_option(ld,LDAP_OPT_ERROR_NUMBER,&err)==0) - return ldap_err_to_gpg_err(err); - else - return KEYSERVER_GENERAL_ERROR; - -#elif defined(HAVE_LDAP_LD_ERRNO) - - return ldap_err_to_gpg_err(ld->ld_errno); - -#else - - /* We should never get here since the LDAP library should always - have either ldap_get_option or ld_errno, but just in case... */ - return KEYSERVER_GENERAL_ERROR; - -#endif -} - -int -send_key(int *eof) -{ - int err,gotit=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR; - char *dn=NULL,line[MAX_LINE],*key[2]={NULL,NULL}; - char keyid[17]; - LDAPMod mod, *attrs[2]; - - memset (&mod, 0, sizeof mod); - mod.mod_op = LDAP_MOD_ADD; - mod.mod_type = pgpkeystr; - mod.mod_values = key; - attrs[0] = &mod; - attrs[1] = NULL; - - dn=malloc(strlen("pgpCertid=virtual,")+strlen(basekeyspacedn)+1); - if(dn==NULL) - { - fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - strcpy(dn,"pgpCertid=virtual,"); - strcat(dn,basekeyspacedn); - - key[0]=malloc(1); - if(key[0]==NULL) - { - fprintf(console,"gpgkeys: unable to allocate memory for key\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - key[0][0]='\0'; - - /* Read and throw away stdin until we see the BEGIN */ - - while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) - { - gotit=1; - break; - } - - if(!gotit) - { - /* i.e. eof before the KEY BEGIN was found. This isn't an - error. */ - *eof=1; - ret=KEYSERVER_OK; - goto fail; - } - - gotit=0; - - /* Now slurp up everything until we see the END */ - - while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s END\n",keyid)==1) - { - gotit=1; - break; - } - else - { - keysize+=strlen(line); - key[0]=realloc(key[0],keysize); - if(key[0]==NULL) - { - fprintf(console,"gpgkeys: unable to reallocate for key\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - strcat(key[0],line); - } - - if(!gotit) - { - fprintf(console,"gpgkeys: no KEY %s END found\n",keyid); - *eof=1; - ret=KEYSERVER_KEY_INCOMPLETE; - goto fail; - } - - err=ldap_add_s(ldap,dn,attrs); - if(err!=LDAP_SUCCESS) - { - fprintf(console,"gpgkeys: error adding key %s to keyserver: %s\n", - keyid,ldap_err2string(err)); - ret=ldap_err_to_gpg_err(err); - goto fail; - } - - ret=KEYSERVER_OK; - - fail: - - free(key[0]); - free(dn); - - if(ret!=0) - fprintf(output,"KEY %s FAILED %d\n",keyid,ret); - - /* Not a fatal error */ - if(ret==KEYSERVER_KEY_EXISTS) - ret=KEYSERVER_OK; - - return ret; -} - -/* Note that key-not-found is not a fatal error */ -int -get_key(char *getkey) -{ - char **vals; - LDAPMessage *res,*each; - int ret=KEYSERVER_INTERNAL_ERROR,err,count; - struct keylist *dupelist=NULL; - char search[62]; - char *attrs[]={"replaceme","pgpuserid","pgpkeyid","pgpcertid","pgprevoked", - "pgpdisabled","pgpkeycreatetime","modifytimestamp", - "pgpkeysize","pgpkeytype",NULL}; - attrs[0]=pgpkeystr; /* Some compilers don't like using variables as - array initializers. */ - - /* Build the search string */ - - /* GPG can send us a v4 fingerprint, a v3 or v4 long key id, or a v3 - or v4 short key id */ - - if(strncmp(getkey,"0x",2)==0) - getkey+=2; - - if(strlen(getkey)==32) - { - fprintf(console, - "gpgkeys: LDAP keyservers do not support v3 fingerprints\n"); - fprintf(output,"KEY 0x%s BEGIN\n",getkey); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED); - return KEYSERVER_NOT_SUPPORTED; - } - - if(strlen(getkey)>16) - { - char *offset=&getkey[strlen(getkey)-16]; - - /* fingerprint. Take the last 16 characters and treat it like a - long key id */ - - if(include_subkeys) - sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))", - offset,offset); - else - sprintf(search,"(pgpcertid=%.16s)",offset); - } - else if(strlen(getkey)>8) - { - /* long key id */ - - if(include_subkeys) - sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))", - getkey,getkey); - else - sprintf(search,"(pgpcertid=%.16s)",getkey); - } - else - { - /* short key id */ - - sprintf(search,"(pgpkeyid=%.8s)",getkey); - } - - fprintf(output,"KEY 0x%s BEGIN\n",getkey); - - if(verbose>2) - fprintf(console,"gpgkeys: LDAP fetch for: %s\n",search); - - if(!verbose) - attrs[1]=NULL; - - if(verbose) - fprintf(console,"gpgkeys: requesting key 0x%s from ldap://%s%s%s\n", - getkey,host,portstr[0]?":":"",portstr[0]?portstr:""); - - err=ldap_search_s(ldap,basekeyspacedn, - LDAP_SCOPE_SUBTREE,search,attrs,0,&res); - if(err!=0) - { - int errtag=ldap_err_to_gpg_err(err); - - fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err)); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag); - return errtag; - } - - count=ldap_count_entries(ldap,res); - if(count<1) - { - fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND); - } - else - { - /* There may be more than one unique result for a given keyID, - so we should fetch them all (test this by fetching short key - id 0xDEADBEEF). */ - - each=ldap_first_entry(ldap,res); - while(each!=NULL) - { - struct keylist *keyptr=dupelist; - - /* Use the long keyid to remove duplicates. The LDAP server - returns the same keyid more than once if there are - multiple user IDs on the key. Note that this does NOT - mean that a keyid that exists multiple times on the - keyserver will not be fetched. It means that each KEY, - no matter how many user IDs share it's keyid, will be - fetched only once. If a keyid that belongs to more than - one key is fetched, the server quite properly responds - with all matching keys. -ds */ - - vals=ldap_get_values(ldap,each,"pgpcertid"); - if(vals!=NULL) - { - while(keyptr!=NULL) - { - if(strcasecmp(keyptr->str,vals[0])==0) - break; - - keyptr=keyptr->next; - } - - if(!keyptr) - { - /* it's not a duplicate, so add it */ - - keyptr=malloc(sizeof(struct keylist)); - if(keyptr==NULL) - { - fprintf(console,"gpgkeys: out of memory when deduping " - "key list\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - strncpy(keyptr->str,vals[0],MAX_LINE); - keyptr->str[MAX_LINE-1]='\0'; - - keyptr->next=dupelist; - dupelist=keyptr; - keyptr=NULL; - } - - ldap_value_free(vals); - } - - if(!keyptr) /* it's not a duplicate */ - { - if(verbose) - { - vals=ldap_get_values(ldap,each,"pgpuserid"); - if(vals!=NULL) - { - /* This is wrong, as the user ID is UTF8. A - better way to handle this would be to send it - over to gpg and display it on that side of - the pipe. */ - fprintf(console,"\nUser ID:\t%s\n",vals[0]); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgprevoked"); - if(vals!=NULL) - { - if(atoi(vals[0])==1) - fprintf(console,"\t\t** KEY REVOKED **\n"); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgpdisabled"); - if(vals!=NULL) - { - if(atoi(vals[0])==1) - fprintf(console,"\t\t** KEY DISABLED **\n"); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgpkeyid"); - if(vals!=NULL) - { - fprintf(console,"Short key ID:\t%s\n",vals[0]); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgpcertid"); - if(vals!=NULL) - { - fprintf(console,"Long key ID:\t%s\n",vals[0]); - ldap_value_free(vals); - } - - /* YYYYMMDDHHmmssZ */ - - vals=ldap_get_values(ldap,each,"pgpkeycreatetime"); - if(vals!=NULL) - { - if(strlen(vals[0])==15) - fprintf(console,"Key created:\t%.2s/%.2s/%.4s\n", - &vals[0][4],&vals[0][6],vals[0]); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"modifytimestamp"); - if(vals!=NULL) - { - if(strlen(vals[0])==15) - fprintf(console,"Key modified:\t%.2s/%.2s/%.4s\n", - &vals[0][4],&vals[0][6],vals[0]); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgpkeysize"); - if(vals!=NULL) - { - if(atoi(vals[0])>0) - fprintf(console,"Key size:\t%d\n",atoi(vals[0])); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgpkeytype"); - if(vals!=NULL) - { - fprintf(console,"Key type:\t%s\n",vals[0]); - ldap_value_free(vals); - } - } - - vals=ldap_get_values(ldap,each,pgpkeystr); - if(vals==NULL) - { - int errtag=ldap_to_gpg_err(ldap); - - fprintf(console,"gpgkeys: unable to retrieve key %s " - "from keyserver\n",getkey); - fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag); - } - else - { - fprintf(output,"%sKEY 0x%s END\n",vals[0],getkey); - - ldap_value_free(vals); - } - } - - each=ldap_next_entry(ldap,each); - } - } - - ret=KEYSERVER_OK; - - fail: - ldap_msgfree(res); - - /* free up the dupe checker */ - while(dupelist!=NULL) - { - struct keylist *keyptr=dupelist; - - dupelist=keyptr->next; - free(keyptr); - } - - return ret; -} - -time_t -ldap2epochtime(const char *timestr) -{ - struct tm pgptime; - - memset(&pgptime,0,sizeof(pgptime)); - - /* YYYYMMDDHHmmssZ */ - - sscanf(timestr,"%4d%2d%2d%2d%2d%2d", - &pgptime.tm_year, - &pgptime.tm_mon, - &pgptime.tm_mday, - &pgptime.tm_hour, - &pgptime.tm_min, - &pgptime.tm_sec); - - pgptime.tm_year-=1900; - pgptime.tm_isdst=-1; - pgptime.tm_mon--; - - return mktime(&pgptime); -} - -void -printquoted(FILE *stream,char *string,char delim) -{ - while(*string) - { - if(*string==delim || *string=='%') - fprintf(stream,"%%%02x",*string); - else - fputc(*string,stream); - - string++; - } -} - -/* Returns 0 on success and -1 on error. Note that key-not-found is - not an error! */ -int -search_key(char *searchkey) -{ - char **vals; - LDAPMessage *res,*each; - int err,count; - /* The maxium size of the search, including the optional stuff and - the trailing \0 */ - char search[2+12+MAX_LINE+2+15+14+1+1]; - char *attrs[]={"pgpcertid","pgpuserid","pgprevoked","pgpdisabled", - "pgpkeycreatetime","pgpkeyexpiretime","modifytimestamp", - "pgpkeysize","pgpkeytype",NULL}; - - fprintf(output,"SEARCH %s BEGIN\n",searchkey); - - /* Build the search string */ - - sprintf(search,"%s(pgpuserid=*%s*)%s%s%s", - (!(include_disabled&&include_revoked))?"(&":"", - searchkey, - include_disabled?"":"(pgpdisabled=0)", - include_revoked?"":"(pgprevoked=0)", - !(include_disabled&&include_revoked)?")":""); - - if(verbose>2) - fprintf(console,"gpgkeys: LDAP search for: %s\n",search); - - fprintf(console,("gpgkeys: searching for \"%s\" from LDAP server %s\n"), - searchkey,host); - - err=ldap_search_s(ldap,basekeyspacedn, - LDAP_SCOPE_SUBTREE,search,attrs,0,&res); - if(err!=0) - { - int errtag=ldap_err_to_gpg_err(err); - - fprintf(output,"SEARCH %s FAILED %d\n",searchkey,errtag); - fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err)); - return errtag; - } - - count=ldap_count_entries(ldap,res); - - if(count<1) - fprintf(output,"info:1:0\n"); - else - { - fprintf(output,"info:1:%d\n",count); - - each=ldap_first_entry(ldap,res); - while(each!=NULL) - { - fprintf(output,"pub:"); - - vals=ldap_get_values(ldap,each,"pgpcertid"); - if(vals!=NULL) - { - fprintf(output,"%s",vals[0]); - ldap_value_free(vals); - } - - fputc(':',output); - - vals=ldap_get_values(ldap,each,"pgpkeytype"); - if(vals!=NULL) - { - /* The LDAP server doesn't exactly handle this well. */ - if(strcasecmp(vals[0],"RSA")==0) - fprintf(output,"1"); - else if(strcasecmp(vals[0],"DSS/DH")==0) - fprintf(output,"17"); - ldap_value_free(vals); - } - - fputc(':',output); - - vals=ldap_get_values(ldap,each,"pgpkeysize"); - if(vals!=NULL) - { - /* Not sure why, but some keys are listed with a key size of - 0. Treat that like an unknown. */ - if(atoi(vals[0])>0) - fprintf(output,"%d",atoi(vals[0])); - ldap_value_free(vals); - } - - fputc(':',output); - - /* YYYYMMDDHHmmssZ */ - - vals=ldap_get_values(ldap,each,"pgpkeycreatetime"); - if(vals!=NULL && strlen(vals[0])==15) - { - fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0])); - ldap_value_free(vals); - } - - fputc(':',output); - - vals=ldap_get_values(ldap,each,"pgpkeyexpiretime"); - if(vals!=NULL && strlen(vals[0])==15) - { - fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0])); - ldap_value_free(vals); - } - - fputc(':',output); - - vals=ldap_get_values(ldap,each,"pgprevoked"); - if(vals!=NULL) - { - if(atoi(vals[0])==1) - fprintf(output,"r"); - ldap_value_free(vals); - } - - vals=ldap_get_values(ldap,each,"pgpdisabled"); - if(vals!=NULL) - { - if(atoi(vals[0])==1) - fprintf(output,"d"); - ldap_value_free(vals); - } - - fputc(':',output); - - vals=ldap_get_values(ldap,each,"modifytimestamp"); - if(vals!=NULL && strlen(vals[0])==15) - { - fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0])); - ldap_value_free(vals); - } - - fprintf(output,"\nuid:"); - - vals=ldap_get_values(ldap,each,"pgpuserid"); - if(vals!=NULL) - { - /* Need to escape any colons */ - printquoted(output,vals[0],':'); - ldap_value_free(vals); - } - - fprintf(output,"\n"); - - each=ldap_next_entry(ldap,each); - } - } - - ldap_msgfree(res); - - fprintf(output,"SEARCH %s END\n",searchkey); - - return KEYSERVER_OK; -} - -void -fail_all(struct keylist *keylist,int action,int err) -{ - if(!keylist) - return; - - if(action==SEARCH) - { - fprintf(output,"SEARCH "); - while(keylist) - { - fprintf(output,"%s ",keylist->str); - keylist=keylist->next; - } - fprintf(output,"FAILED %d\n",err); - } - else - while(keylist) - { - fprintf(output,"KEY %s FAILED %d\n",keylist->str,err); - keylist=keylist->next; - } -} - -int -main(int argc,char *argv[]) -{ - int port=0,arg,err,action=-1,ret=KEYSERVER_INTERNAL_ERROR; - char line[MAX_LINE],**vals; - int version,failed=0; - char *attrs[]={"basekeyspacedn","version","software",NULL}; - LDAPMessage *res; - struct keylist *keylist=NULL,*keyptr=NULL; - -#ifdef __riscos__ - riscos_global_defaults(); -#endif - - console=stderr; - - while((arg=getopt(argc,argv,"ho:"))!=-1) - switch(arg) - { - default: - case 'h': - fprintf(console,"-h\thelp\n"); - fprintf(console,"-o\toutput to this file\n"); - return KEYSERVER_OK; - - case 'o': - output=fopen(optarg,"w"); - if(output==NULL) - { - fprintf(console,"gpgkeys: Cannot open output file \"%s\": %s\n", - optarg,strerror(errno)); - return KEYSERVER_INTERNAL_ERROR; - } - - break; - } - - if(argc>optind) - { - input=fopen(argv[optind],"r"); - if(input==NULL) - { - fprintf(console,"gpgkeys: Cannot open input file \"%s\": %s\n", - argv[optind],strerror(errno)); - return KEYSERVER_INTERNAL_ERROR; - } - } - - if(input==NULL) - input=stdin; - - if(output==NULL) - output=stdout; - - /* Get the command and info block */ - - while(fgets(line,MAX_LINE,input)!=NULL) - { - char commandstr[7]; - char optionstr[30]; - char hash; - - if(line[0]=='\n') - break; - - if(sscanf(line,"%c",&hash)==1 && hash=='#') - continue; - - if(sscanf(line,"COMMAND %6s\n",commandstr)==1) - { - commandstr[6]='\0'; - - if(strcasecmp(commandstr,"get")==0) - action=GET; - else if(strcasecmp(commandstr,"send")==0) - action=SEND; - else if(strcasecmp(commandstr,"search")==0) - action=SEARCH; - - continue; - } - - if(sscanf(line,"HOST %79s\n",host)==1) - { - host[79]='\0'; - continue; - } - - if(sscanf(line,"PORT %9s\n",portstr)==1) - { - portstr[9]='\0'; - port=atoi(portstr); - continue; - } - - if(sscanf(line,"VERSION %d\n",&version)==1) - { - if(version!=KEYSERVER_PROTO_VERSION) - { - ret=KEYSERVER_VERSION_ERROR; - goto fail; - } - - continue; - } - - if(sscanf(line,"OPTION %29s\n",optionstr)==1) - { - int no=0; - char *start=&optionstr[0]; - - optionstr[29]='\0'; - - if(strncasecmp(optionstr,"no-",3)==0) - { - no=1; - start=&optionstr[3]; - } - - if(strcasecmp(start,"verbose")==0) - { - if(no) - verbose--; - else - verbose++; - } - else if(strcasecmp(start,"include-disabled")==0) - { - if(no) - include_disabled=0; - else - include_disabled=1; - } - else if(strcasecmp(start,"include-revoked")==0) - { - if(no) - include_revoked=0; - else - include_revoked=1; - } - else if(strcasecmp(start,"include-subkeys")==0) - { - if(no) - include_subkeys=0; - else - include_subkeys=1; - } - - continue; - } - } - - /* If it's a GET or a SEARCH, the next thing to come in is the - keyids. If it's a SEND, then there are no keyids. */ - - if(action==SEND) - while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n'); - else if(action==GET || action==SEARCH) - { - for(;;) - { - struct keylist *work; - - if(fgets(line,MAX_LINE,input)==NULL) - break; - else - { - if(line[0]=='\n') - break; - - work=malloc(sizeof(struct keylist)); - if(work==NULL) - { - fprintf(console,"gpgkeys: out of memory while " - "building key list\n"); - ret=KEYSERVER_NO_MEMORY; - goto fail; - } - - strcpy(work->str,line); - - /* Trim the trailing \n */ - work->str[strlen(line)-1]='\0'; - - work->next=NULL; - - /* Always attach at the end to keep the list in proper - order for searching */ - if(keylist==NULL) - keylist=work; - else - keyptr->next=work; - - keyptr=work; - } - } - } - else - { - fprintf(console,"gpgkeys: no keyserver command specified\n"); - goto fail; - } - - /* Send the response */ - - fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); - fprintf(output,"PROGRAM %s\n\n",VERSION); - - if(verbose>1) - { - fprintf(console,"Host:\t\t%s\n",host); - if(port) - fprintf(console,"Port:\t\t%d\n",port); - fprintf(console,"Command:\t%s\n",action==GET?"GET": - action==SEND?"SEND":"SEARCH"); - } - - /* Note that this tries all A records on a given host (or at least, - OpenLDAP does). */ - ldap=ldap_init(host,port); - if(ldap==NULL) - { - fprintf(console,"gpgkeys: internal LDAP init error: %s\n", - strerror(errno)); - fail_all(keylist,action,KEYSERVER_INTERNAL_ERROR); - goto fail; - } - - err=ldap_simple_bind_s(ldap,NULL,NULL); - if(err!=0) - { - fprintf(console,"gpgkeys: internal LDAP bind error: %s\n", - ldap_err2string(err)); - fail_all(keylist,action,ldap_err_to_gpg_err(err)); - goto fail; - } - - /* Get the magic info record */ - - err=ldap_search_s(ldap,"cn=PGPServerInfo",LDAP_SCOPE_BASE, - "(objectclass=*)",attrs,0,&res); - if(err!=0) - { - fprintf(console,"gpgkeys: error retrieving LDAP server info: %s\n", - ldap_err2string(err)); - fail_all(keylist,action,ldap_err_to_gpg_err(err)); - goto fail; - } - - if(ldap_count_entries(ldap,res)!=1) - { - fprintf(console,"gpgkeys: more than one serverinfo record\n"); - fail_all(keylist,action,KEYSERVER_INTERNAL_ERROR); - goto fail; - } - - if(verbose>1) - { - vals=ldap_get_values(ldap,res,"software"); - if(vals!=NULL) - { - fprintf(console,"Server: \t%s\n",vals[0]); - ldap_value_free(vals); - } - } - - vals=ldap_get_values(ldap,res,"version"); - if(vals!=NULL) - { - if(verbose>1) - fprintf(console,"Version:\t%s\n",vals[0]); - - /* If the version is high enough, use the new pgpKeyV2 - attribute. This design if iffy at best, but it matches how - PGP does it. I figure the NAI folks assumed that there would - never be a LDAP keyserver vendor with a different numbering - scheme. */ - if(atoi(vals[0])>1) - pgpkeystr="pgpKeyV2"; - - ldap_value_free(vals); - } - - /* This is always "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not - be in the future. */ - - vals=ldap_get_values(ldap,res,"basekeyspacedn"); - if(vals!=NULL) - { - basekeyspacedn=strdup(vals[0]); - ldap_value_free(vals); - if(basekeyspacedn==NULL) - { - fprintf(console,"gpgkeys: can't allocate string space " - "for LDAP base\n"); - fail_all(keylist,action,KEYSERVER_NO_MEMORY); - goto fail; - } - } - - ldap_msgfree(res); - - switch(action) - { - case GET: - keyptr=keylist; - - while(keyptr!=NULL) - { - if(get_key(keyptr->str)!=KEYSERVER_OK) - failed++; - - keyptr=keyptr->next; - } - break; - - case SEND: - { - int eof=0; - - do - { - if(send_key(&eof)!=KEYSERVER_OK) - failed++; - } - while(!eof); - } - break; - - case SEARCH: - { - char *searchkey=NULL; - int len=0; - - /* To search, we stick a * in between each key to search for. - This means that if the user enters words, they'll get - "enters*words". If the user "enters words", they'll get - "enters words" */ - - keyptr=keylist; - while(keyptr!=NULL) - { - len+=strlen(keyptr->str)+1; - keyptr=keyptr->next; - } - - searchkey=malloc(len+1); - if(searchkey==NULL) - { - ret=KEYSERVER_NO_MEMORY; - fail_all(keylist,action,KEYSERVER_NO_MEMORY); - goto fail; - } - - searchkey[0]='\0'; - - keyptr=keylist; - while(keyptr!=NULL) - { - strcat(searchkey,keyptr->str); - strcat(searchkey,"*"); - keyptr=keyptr->next; - } - - /* Nail that last "*" */ - searchkey[strlen(searchkey)-1]='\0'; - - if(search_key(searchkey)!=KEYSERVER_OK) - failed++; - - free(searchkey); - } - - break; - } - - if(!failed) - ret=KEYSERVER_OK; - - fail: - - while(keylist!=NULL) - { - struct keylist *current=keylist; - keylist=keylist->next; - free(current); - } - - if(input!=stdin) - fclose(input); - - if(output!=stdout) - fclose(output); - - if(ldap!=NULL) - ldap_unbind_s(ldap); - - free(basekeyspacedn); - - return ret; -} diff --git a/keyserver/gpgkeys_mailto.in b/keyserver/gpgkeys_mailto.in deleted file mode 100755 index 9086de419..000000000 --- a/keyserver/gpgkeys_mailto.in +++ /dev/null @@ -1,202 +0,0 @@ -#!@PERL@ -w - -# gpgkeys_mailto - talk to a email keyserver -# 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 - -use Getopt::Std; -$sendmail="@SENDMAIL@ -t"; - -### - -getopts('o:'); - -if(defined($opt_o)) -{ - open(STDOUT,">$opt_o") || die "Can't open output file $opt_o\n"; -} - -if(@ARGV) -{ - open(STDIN,$ARGV[0]) || die "Can't open input file $ARGV[0]\n"; -} - -($login,$name)=(getpwuid($<))[0,6]; - -$from="$name <$login>"; - -while() -{ - last if($_ eq "\n"); - - if(/^COMMAND (\w+)/) - { - $command=$1; - } - - if(/^OPAQUE (\S+)/) - { - $address=$1; - } - - if(/^PROGRAM (\S+)/) - { - $program=$1; - } - - if(/^OPTION (\w+)/) - { - if($1=~/^verbose$/i) - { - $verbose++; - } - elsif($1=~/^no-verbose$/i) - { - $verbose--; - } - } -} - -$program="(unknown)" if(!defined($program)); - -if(!defined($address)) -{ - print STDERR "gpgkeys: no address provided\n"; - exit(1); -} - -# decode $address - -($address,$args)=split(/\?/,$address); - -if(defined($args)) -{ - @pairs = split(/&/, $args); - foreach $pair (@pairs) - { - ($hdr, $val) = split(/=/, $pair); - $hdr =~ tr/+/ /; - $hdr =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; - $val =~ tr/+/ /; - $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; -# we only handle "from" right now - if($hdr=~/^from$/i) - { - $from=$val; - last; - } - } -} - -while() -{ - last if($_ eq "\n"); - - chomp; - - push(@keys,$_); -} - -# Send response - -print "VERSION 0\n"; -print "OPTION OUTOFBAND\n\n"; - -# Email keyservers get and search the same way - -if($command=~/get/i || $command=~/search/i) -{ - if($command=~/search/i) - { - print "COUNT 0\n"; - } - - foreach $key (@keys) - { - open(MAIL,"|$sendmail") || die "ERROR: Can't open $sendmail\n"; - print MAIL "From: $from\n"; - print MAIL "To: $address\n"; - if($command=~/get/i) - { - # mail keyservers don't like long-form keyids - - if(substr($key,0,2) eq "0x") - { - $key=substr($key,2); - } - - if(length($key)>8) - { - $key=substr($key,-8); - } - - print MAIL "Subject: GET 0x$key\n\n"; - } - else - { - print MAIL "Subject: GET $key\n\n"; - } - print MAIL "GnuPG $program email keyserver request\n"; - close(MAIL); - - # Tell GnuPG not to expect a key - print "KEY $key OUTOFBAND\n"; - - if($verbose) - { - print STDERR "gpgkeys: key $key requested from $address\n"; - } - } -} - -if($command=~/send/i) -{ - while(!eof(STDIN)) - { - open(MAIL,"|$sendmail") || die "ERROR: Can't open $sendmail\n"; - print MAIL "From: $name <$login>\n"; - print MAIL "To: $address\n"; - print MAIL "Subject: ADD\n\n"; - - while() - { - if(/^KEY (\w+) BEGIN$/) - { - $key=$1; - last; - } - } - - while() - { - if(/^KEY \w+ END$/) - { - last; - } - - print MAIL; - } - - close(MAIL); - - if($verbose) - { - print STDERR "gpgkeys: key $key sent to $address\n"; - } - } -} diff --git a/keyserver/gpgkeys_test.in b/keyserver/gpgkeys_test.in deleted file mode 100755 index 09c14bfd4..000000000 --- a/keyserver/gpgkeys_test.in +++ /dev/null @@ -1,79 +0,0 @@ -#!@PERL@ - -# gpgkeys_test - keyserver code tester -# 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 - -use Getopt::Std; - -$|=1; - -print STDERR "gpgkeys_test starting\n"; - -getopts('o:'); - -if(defined($opt_o)) -{ - print STDERR "Using output file $opt_o\n"; - open(STDOUT,">$opt_o") || die "Can't open output file $opt_o\n"; -} - -if(@ARGV) -{ - print STDERR "Using input file $ARGV[0]\n"; - open(STDIN,$ARGV[0]) || die "Can't open input file $ARGV[0]\n"; -} - -# Get the command block - -print STDERR "Command block:\n"; - -while() -{ - last if($_ eq "\n"); - print STDERR "--command-> $_"; - - if(/^COMMAND (\w+)/) - { - $command=$1; - } -} - -# Get the keylist block - -print STDERR "Keylist block:\n"; - -while() -{ - last if($_ eq "\n"); - print STDERR "--keylist-> $_"; -} - -# If it's a SEND, then get the key material - -if($command eq "SEND") -{ - print STDERR "Key material to send:\n"; - - while() - { - print STDERR "$_"; - } -} - -printf STDERR "gpgkeys_test finished\n"; diff --git a/mpi/ChangeLog b/mpi/ChangeLog deleted file mode 100644 index f1e2e459e..000000000 --- a/mpi/ChangeLog +++ /dev/null @@ -1,390 +0,0 @@ -2002-10-17 Werner Koch - - * config.links (powerpc-apple-darwin6.1): Disable assembler - due to non-working modules/as. Suggested by Gordon Worley. - -2002-10-02 David Shaw - - * longlong.h: Some whitespace changes in HPPA to fix assembler - problems on HP-UX. From David Ellement. - -2002-09-20 Werner Koch - - * mpicoder.c (do_get_buffer): Avoid zero length allocation. - Checked that all callers behave properly when NBYTES returns 0 as - the length of the allocated buffer. - -2002-09-10 Werner Koch - - * mpi-bit.c (mpi_normalize): Replaced the check for protected by - is_opaque. - (mpi_get_nbits): Removed the special case for protected MPIs. - * mpicoder.c (do_get_buffer): Likewise. - (mpi_print): Removed the nbit_info printing. - -2002-09-03 Werner Koch - - * mpicoder.c (mpi_set_buffer): Cast all left operands of a shift - to a larger type so that 16 bit CPUs don't suffer from an - overflow. Suggested by TOGAWA Satoshi. - -2002-08-24 David Shaw - - * longlong.h: Remove space between \ and newline. gcc is - complaining. - -2002-08-13 Werner Koch - - * mpicoder.c (do_get_buffer): Don't remove leading zeros if the - MPI is marked as protected. - -2002-08-02 Timo Schulz - - * mpicoder.c: Add a '\n' to all log_bug functions. - -2002-08-01 Werner Koch - - * config.links: Added case for sparc64-netbsd. Suggested by - ww@styx.org. - -2002-07-25 David Shaw - - * config.links: Add special rule for OpenBSD on x86 to use special - i386-openbsd files. OpenBSD (at least until version 3.1) has an - older assembler that won't work with the files in i386. - -2002-07-24 Stefan Bellon - - * longlong.h [__riscos__]: Removed #pragma which is not needed - anymore since the K&R multiline strings are gone. - -2002-07-24 Werner Koch - - * longlong.h: Replaced all K&R multiline strings by ISO ones for - the sake of modern compilers. Suggested by Marco Parrone. - -2002-05-10 Stefan Bellon - - * mpiutil.c (mpi_alloc_like/mpi_debug_alloc_like): Added code - for M_DEBUG. - -2002-04-18 Werner Koch - - * i386/syntax.h (ALIGN): Removed parens from definition - * i386/mpih-add1.S, i386/mpih-sub1.S, i386/mpih-rshift.S, - i386/mpih-lshift.S: Minor syntax changes suggested by Mark Pettit - after comparing the files with those for GMP 4. - -2001-11-08 Werner Koch - - * config.links (mpi_sflags): Add extra rule for sparc64-sun-solaris2. - -2001-08-20 Werner Koch - - * longlong.h [__riscos__]: Need a special pragma here. - -2001-08-09 Werner Koch - - * config.links: Added configuraton for powerpc-openbsd. By Peter - Valchev - -2001-07-09 Werner Koch - - * config.links: Changed the way the list of files to be - symlinked is returned. - -2001-05-27 Werner Koch - - * hppa/, hppa1.1/, pa7100/ : Use .label command instead of labels - because there syntax changed. By Matthew Wilcox. - -2001-05-06 Werner Koch - - * longlong.h: Fixes for ARM by Phil Blundell. - -2001-04-17 Werner Koch - - Updated copyright notices. - -2001-03-24 Werner Koch - - * mpi-mul.c (mpi_mul): Make sure that secret temporary results are - not stored in w. Suggested by Florian Weimer. - -2001-03-18 Werner Koch - - * config.links: Use i386 code for i386. According to tests by - Kevin Ryde the i586 code runs slow on i386 CPUs. Ditto for i786. - -2000-10-24 Werner Koch - - * mips3/: Changed a few comments to C-style. By Jeff Long. - -2000-10-13 Werner Koch - - * mpi.h: Removed the inclusion of mpi-asm-defs.h because this - makes some trouble when doing a VPATH build. configure now - takes care of it. - -2000-10-12 Werner Koch - - * generic/mpi-asm-defs.h: New. - * mips3/mpi-asm-defs.h: New. - * config.links: Create a link to one of the above files. - -Wed Jul 19 11:26:43 CEST 2000 Werner Koch - - * config.links: Support for powerpc--netbsd by Gabriel Rosenkoetter. - -Wed Mar 22 13:50:24 CET 2000 Werner Koch - - * config.links: Add support for FreeBSD 5 and made the case stmt - looking nicer. From Jun Kuriyama. - -Fri Mar 17 17:50:25 CET 2000 Werner Koch - - * config.links (sparc64-unknown-linux-gnu): use udic module. - From Adam Mitchell. - -2000-03-14 12:03:56 Werner Koch (wk@habibti.openit.de) - - * Makefile.am: Do not use .s and .S files but a temp names, so that - OSes with caseinsensitive filenames do work. From Frank Donahoe. - -Tue Mar 7 18:45:31 CET 2000 Werner Koch - - * mpih-mul.c (mpihelp_mul_karatsuba_case): It seems that the - untested part works fine. Removed the debugging message. - - * longlong.h (umul_ppmm): Fixes for ARM-4. By Sean MacLennan. - - * config.links: Add support for NetBSD. - -Thu Jan 13 19:31:58 CET 2000 Werner Koch - - * mpi-internal.h (karatsuba_ctx): New. - * mpih-mul.c (mpihelp_release_karatsuba_ctx): New. - (mpihelp_mul_karatsuba_case): New. - (mpihelp_mul): Splitted to make use of the new functions. - * mpi-pow.c (mpi_powm): Make use of the new splitted function - to avoid multiple allocation of temporary memory during the - karatsuba operations. - - * mpi_mpow.c: Removed the unused Barrett code. - -Sun Dec 19 15:22:26 CET 1999 Werner Koch - - * power/ : Converted more comments to C comments because some AS - complain about ' in comments. - -Thu Dec 16 10:07:58 CET 1999 Werner Koch - - * Makefile.am: c/SFLAGS/ASFLAGS/. This has only been used by the - powerpc and actually never passed the -Wa,foo to the cc. - -Thu Dec 9 10:31:05 CET 1999 Werner Koch - - * power/: Add all files from GMP for this CPU. - - * config.links: Support for BSDI 4.x. By Wayne Chapeskie. - (sparc8): Made the search path the same as sparc9 - - * mpih-div.c (mpihelp_divrem): The MPN_COPY_DECR copied one - elemnat too many. This is gmp2.0.2p9.txt patch. - -Sat Oct 9 20:34:41 CEST 1999 Werner Koch - - * Makefile.am: Removed libtool. - -Mon Aug 30 20:38:33 CEST 1999 Werner Koch - - * config.links: Add case label for DJGPP - -Wed Jul 14 19:42:08 CEST 1999 Werner Koch - - - * Makefile.am: Use .s files as temporaries, disabled other .S rules. - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch - - - * mpicoder.c (g10_log_mpidump): New. - - * Makefile.am: Support for libtool. - -Fri Jul 2 11:45:54 CEST 1999 Werner Koch - - - * mpi-bit.c (mpi_lshift_limbs,mpi_rshift_limbs): New. - * mpi-mpow.c (barrett_mulm): New but diabled. - -Tue Jun 1 16:01:46 CEST 1999 Werner Koch - - * config.links (i[56]86*-*-freebsdelf*): New. - -Sun May 23 14:20:22 CEST 1999 Werner Koch - - * config.links (sysdep.h): Not any more conditionally created. - -Tue May 4 15:47:53 CEST 1999 Werner Koch - - * mpiutil.c (mpi_alloc_like): New. - -Mon Apr 26 17:48:15 CEST 1999 Werner Koch - - * mpih-add.c, mpih-sub.c: Removed - * mpi-inline.c: New. - * mpi-inline.h: Make it usable by mpi-inline.c. - -Sun Apr 18 10:11:28 CEST 1999 Werner Koch - - * mpih-mul.c (mpihelp_mul_n): Fixed use of memory region. - (mpihelp_mul): Ditto. - -Wed Apr 7 20:51:39 CEST 1999 Werner Koch - - * Makefile.am: Explicit rules to invoke cpp on *.S - -Mon Mar 8 20:47:17 CET 1999 Werner Koch - - * config.links: Take advantage of the with_symbol_underscore macro. - Add support for freebsd 4. - -Wed Feb 24 11:07:27 CET 1999 Werner Koch - - * mips3/mpih-sub1.S: Removed left over junk in last line. (Should I - blame me or my editor?). - -Sat Feb 13 12:04:43 CET 1999 Werner Koch - - * Makefile.am: Removed the +=. Add MPI_OPT_FLAGS. - -Sat Jan 9 16:02:23 CET 1999 Werner Koch - - * mpi-cmp.c (mpi_cmp_ui): Normalized the arg. - -Thu Jan 7 18:00:58 CET 1999 Werner Koch - - * mpi-bit.c (mpi_normalize): New. - (mpi_get_nbits): Normalize the MPI. - * mpi-bit.c (mpi_cmp): Normalize the MPI before the compare. - - -Tue Dec 8 13:15:16 CET 1998 Werner Koch - - * config.links: Moved the case for powerpc*linux - * powerpcp32/*.S: Removed some underscores. - -Thu Nov 26 07:27:52 1998 Werner Koch - - * config.links: Support for ppc with ELF - * powerpc32/syntax.h: New. - * powerpc32/*.S: Applied ELF patches (glibc patches) - -Tue Nov 10 19:31:37 1998 Werner Koch (wk@isil.d.shuttle.de) - - * power*/ : Started with stuff for PPC - * config.links: Some stuff for PPC. - * generic/udiv-w-sdiv.c: New but disabled. - -Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links (freebsd): Fixes for FreeBSD 3.0 - -Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links (freebsd): ELF patches from Jun Kuriyama. - -Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpi-mpow.c (mpi_mulpowm): Fixed mem leak (m_free/mpi_free). - -Thu Sep 17 18:08:50 1998 Werner Koch (wk@(none)) - - * hppa1.1/udiv-qrnnd.S: Fix from Steffen Zahn for HPUX 10.20 - -Thu Aug 6 16:39:28 1998 Werner Koch,mobil,,, (wk@tobold) - - * mpi-bit.c (mpi_set_bytes): Removed. - -Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none)) - - * mpicoder.c (mpi_read_from_buffer): New. - - * mpiutil.c (mpi_set_opaque): New. - (mpi_get_opaque): New. - (mpi_copy): Changed to support opauqe flag - (mpi_free): Ditto. - -Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpiutil.c (mpi_clear): Reset flags. - (mpi_set): Ditto. - (mpi_alloc_secure): Set flag to 1 and not ored the 1 in, tsss.. - -Fri Jun 26 11:19:06 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpiutil.c (mpi_alloc): set nbits to 0. - (mpi_alloc_secure): Ditto. - (mpi_clear): Ditto. - -Thu Jun 25 11:50:01 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mips3/*.S: New - -Mon May 18 13:47:06 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links: split mpih-shift into mpih-[lr]shift and - changed all implementations. - * mpi/alpha: add some new assembler stuff. - -Wed May 13 11:04:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links: Add support for MIPS - -Thu Apr 9 11:31:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpicoder.c (mpi_get_secure_buffer): New. - -Wed Apr 8 09:44:33 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links: Applied small fix from Ulf Mller. - -Mon Apr 6 12:38:52 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpicoder.c (mpi_get_buffer): Removed returned leading zeroes - and changed all callers. - -Tue Mar 10 13:40:34 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpi-bit.c (mpi_clear_highbit): New. - -Mon Mar 2 19:29:00 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am (DISTCLEANFILES): New - -Thu Feb 26 06:48:54 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links (X86_BROKEN_ALIGN): Added for some systems. - -Mon Feb 23 12:21:40 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mpi/m68k/mpih-shift.S (Lspecial): Changed duplicate symbol. - -Mon Feb 16 13:00:27 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.links : Add detection of m68k cpus - - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/mpi/Makefile.am b/mpi/Makefile.am deleted file mode 100644 index 56cf47a52..000000000 --- a/mpi/Makefile.am +++ /dev/null @@ -1,79 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - - -INCLUDES = -I.. -I$(top_srcdir)/include -CFLAGS = @CFLAGS@ @MPI_OPT_FLAGS@ -ASFLAGS = @MPI_SFLAGS@ - -EXTRA_DIST = config.links -DISTCLEANFILES = mpi-asm-defs.h \ - mpih-add1.S mpih-mul1.S mpih-mul2.S mpih-mul3.S \ - mpih-lshift.S mpih-rshift.S mpih-sub1.S asm-syntax.h sysdep.h -# Note: we only use .S files so we should delete all left over .s -CLEANFILES = _*.s - -noinst_LIBRARIES = libmpi.a - -# libmpi_a_LDFLAGS = -libmpi_a_SOURCES = longlong.h \ - mpi-add.c \ - mpi-bit.c \ - mpi-cmp.c \ - mpi-div.c \ - mpi-gcd.c \ - mpi-internal.h \ - mpi-inline.h \ - mpi-inline.c \ - mpi-inv.c \ - mpi-mul.c \ - mpi-pow.c \ - mpi-mpow.c \ - mpi-scan.c \ - mpicoder.c \ - mpih-cmp.c \ - mpih-div.c \ - mpih-mul.c \ - mpiutil.c \ - g10m.c - -# Note this objects are actually links, the sourcefiles are -# distributed by special code in dist-hook -common_asm_objects = mpih-mul1.o \ - mpih-mul2.o \ - mpih-mul3.o \ - mpih-add1.o \ - mpih-sub1.o \ - mpih-lshift.o \ - mpih-rshift.o - -libmpi_a_DEPENDENCIES = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ -libmpi_a_LIBADD = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ - -# cancel the default rules used by libtool which do not really -# work and add one to cpp .S files -.S.o: - $(CPP) $(INCLUDES) $(DEFS) $< | grep -v '^#' > _$*.s - $(COMPILE) -c _$*.s - mv -f _$*.o $*.o - -.S.lo: - - diff --git a/mpi/alpha/README b/mpi/alpha/README deleted file mode 100644 index 55c0a2917..000000000 --- a/mpi/alpha/README +++ /dev/null @@ -1,53 +0,0 @@ -This directory contains mpn functions optimized for DEC Alpha processors. - -RELEVANT OPTIMIZATION ISSUES - -EV4 - -1. This chip has very limited store bandwidth. The on-chip L1 cache is -write-through, and a cache line is transfered from the store buffer to the -off-chip L2 in as much 15 cycles on most systems. This delay hurts -mpn_add_n, mpn_sub_n, mpn_lshift, and mpn_rshift. - -2. Pairing is possible between memory instructions and integer arithmetic -instructions. - -3. mulq and umulh is documented to have a latency of 23 cycles, but 2 of -these cycles are pipelined. Thus, multiply instructions can be issued at a -rate of one each 21nd cycle. - -EV5 - -1. The memory bandwidth of this chip seems excellent, both for loads and -stores. Even when the working set is larger than the on-chip L1 and L2 -caches, the perfromance remain almost unaffected. - -2. mulq has a measured latency of 13 cycles and an issue rate of 1 each 8th -cycle. umulh has a measured latency of 15 cycles and an issue rate of 1 -each 10th cycle. But the exact timing is somewhat confusing. - -3. mpn_add_n. With 4-fold unrolling, we need 37 instructions, whereof 12 - are memory operations. This will take at least - ceil(37/2) [dual issue] + 1 [taken branch] = 20 cycles - We have 12 memory cycles, plus 4 after-store conflict cycles, or 16 data - cache cycles, which should be completely hidden in the 20 issue cycles. - The computation is inherently serial, with these dependencies: - addq - / \ - addq cmpult - | | - cmpult | - \ / - or - I.e., there is a 4 cycle path for each limb, making 16 cycles the absolute - minimum. We could replace the `or' with a cmoveq/cmovne, which would save - a cycle on EV5, but that might waste a cycle on EV4. Also, cmov takes 2 - cycles. - addq - / \ - addq cmpult - | \ - cmpult -> cmovne - -STATUS - diff --git a/mpi/alpha/distfiles b/mpi/alpha/distfiles deleted file mode 100644 index f2ab9fc3c..000000000 --- a/mpi/alpha/distfiles +++ /dev/null @@ -1,11 +0,0 @@ -README -mpih-add1.S -mpih-sub1.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S -mpih-lshift.S -mpih-rshift.S - -udiv-qrnnd.S - diff --git a/mpi/alpha/mpih-add1.S b/mpi/alpha/mpih-add1.S deleted file mode 100644 index a2ee8eb17..000000000 --- a/mpi/alpha/mpih-add1.S +++ /dev/null @@ -1,124 +0,0 @@ -/* alpha add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * Copyright (C) 1995, 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 - */ - - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, ($16) - * mpi_ptr_t s1_ptr, ($17) - * mpi_ptr_t s2_ptr, ($18) - * mpi_size_t size) ($19) - */ - - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_add_n - .ent mpihelp_add_n -mpihelp_add_n: - .frame $30,0,$26,0 - - ldq $3,0($17) - ldq $4,0($18) - - subq $19,1,$19 - and $19,4-1,$2 # number of limbs in first loop - bis $31,$31,$0 - beq $2,.L0 # if multiple of 4 limbs, skip first loop - - subq $19,$2,$19 - -.Loop0: subq $2,1,$2 - ldq $5,8($17) - addq $4,$0,$4 - ldq $6,8($18) - cmpult $4,$0,$1 - addq $3,$4,$4 - cmpult $4,$3,$0 - stq $4,0($16) - or $0,$1,$0 - - addq $17,8,$17 - addq $18,8,$18 - bis $5,$5,$3 - bis $6,$6,$4 - addq $16,8,$16 - bne $2,.Loop0 - -.L0: beq $19,.Lend - - .align 3 -.Loop: subq $19,4,$19 - - ldq $5,8($17) - addq $4,$0,$4 - ldq $6,8($18) - cmpult $4,$0,$1 - addq $3,$4,$4 - cmpult $4,$3,$0 - stq $4,0($16) - or $0,$1,$0 - - ldq $3,16($17) - addq $6,$0,$6 - ldq $4,16($18) - cmpult $6,$0,$1 - addq $5,$6,$6 - cmpult $6,$5,$0 - stq $6,8($16) - or $0,$1,$0 - - ldq $5,24($17) - addq $4,$0,$4 - ldq $6,24($18) - cmpult $4,$0,$1 - addq $3,$4,$4 - cmpult $4,$3,$0 - stq $4,16($16) - or $0,$1,$0 - - ldq $3,32($17) - addq $6,$0,$6 - ldq $4,32($18) - cmpult $6,$0,$1 - addq $5,$6,$6 - cmpult $6,$5,$0 - stq $6,24($16) - or $0,$1,$0 - - addq $17,32,$17 - addq $18,32,$18 - addq $16,32,$16 - bne $19,.Loop - -.Lend: addq $4,$0,$4 - cmpult $4,$0,$1 - addq $3,$4,$4 - cmpult $4,$3,$0 - stq $4,0($16) - or $0,$1,$0 - ret $31,($26),1 - - .end mpihelp_add_n - diff --git a/mpi/alpha/mpih-lshift.S b/mpi/alpha/mpih-lshift.S deleted file mode 100644 index 4ce4879af..000000000 --- a/mpi/alpha/mpih-lshift.S +++ /dev/null @@ -1,123 +0,0 @@ -/* alpha - left shift - * - * Copyright (C) 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (r16) - * mpi_ptr_t up, (r17) - * mpi_size_t usize, (r18) - * unsigned cnt) (r19) - * - * This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling, - * it would take 4 cycles/limb. It should be possible to get down to 3 - * cycles/limb since both ldq and stq can be paired with the other used - * instructions. But there are many restrictions in the 21064 pipeline that - * makes it hard, if not impossible, to get down to 3 cycles/limb: - * - * 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay. - * 2. Only aligned instruction pairs can be paired. - * 3. The store buffer or silo might not be able to deal with the bandwidth. - */ - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_lshift - .ent mpihelp_lshift -mpihelp_lshift: - .frame $30,0,$26,0 - - s8addq $18,$17,$17 # make r17 point at end of s1 - ldq $4,-8($17) # load first limb - subq $17,8,$17 - subq $31,$19,$7 - s8addq $18,$16,$16 # make r16 point at end of RES - subq $18,1,$18 - and $18,4-1,$20 # number of limbs in first loop - srl $4,$7,$0 # compute function result - - beq $20,.L0 - subq $18,$20,$18 - - .align 3 -.Loop0: - ldq $3,-8($17) - subq $16,8,$16 - subq $17,8,$17 - subq $20,1,$20 - sll $4,$19,$5 - srl $3,$7,$6 - bis $3,$3,$4 - bis $5,$6,$8 - stq $8,0($16) - bne $20,.Loop0 - -.L0: beq $18,.Lend - - .align 3 -.Loop: ldq $3,-8($17) - subq $16,32,$16 - subq $18,4,$18 - sll $4,$19,$5 - srl $3,$7,$6 - - ldq $4,-16($17) - sll $3,$19,$1 - bis $5,$6,$8 - stq $8,24($16) - srl $4,$7,$2 - - ldq $3,-24($17) - sll $4,$19,$5 - bis $1,$2,$8 - stq $8,16($16) - srl $3,$7,$6 - - ldq $4,-32($17) - sll $3,$19,$1 - bis $5,$6,$8 - stq $8,8($16) - srl $4,$7,$2 - - subq $17,32,$17 - bis $1,$2,$8 - stq $8,0($16) - - bgt $18,.Loop - -.Lend: sll $4,$19,$8 - stq $8,-8($16) - ret $31,($26),1 - .end mpihelp_lshift - - diff --git a/mpi/alpha/mpih-mul1.S b/mpi/alpha/mpih-mul1.S deleted file mode 100644 index e62ccbdb7..000000000 --- a/mpi/alpha/mpih-mul1.S +++ /dev/null @@ -1,90 +0,0 @@ -/* Alpha 21064 mpih-mul1.S -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1994, 1995, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (r16) - * mpi_ptr_t s1_ptr, (r17) - * mpi_size_t s1_size, (r18) - * mpi_limb_t s2_limb) (r19) - * - * This code runs at 42 cycles/limb on the EV4 and 18 cycles/limb on the EV5. - * - * To improve performance for long multiplications, we would use - * 'fetch' for S1 and 'fetch_m' for RES. It's not obvious how to use - * these instructions without slowing down the general code: 1. We can - * only have two prefetches in operation at any time in the Alpha - * architecture. 2. There will seldom be any special alignment - * between RES_PTR and S1_PTR. Maybe we can simply divide the current - * loop into an inner and outer loop, having the inner loop handle - * exactly one prefetch block? - */ - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_mul_1 - .ent mpihelp_mul_1 2 -mpihelp_mul_1: - .frame $30,0,$26 - - ldq $2,0($17) # $2 = s1_limb - subq $18,1,$18 # size-- - mulq $2,$19,$3 # $3 = prod_low - bic $31,$31,$4 # clear cy_limb - umulh $2,$19,$0 # $0 = prod_high - beq $18,Lend1 # jump if size was == 1 - ldq $2,8($17) # $2 = s1_limb - subq $18,1,$18 # size-- - stq $3,0($16) - beq $18,Lend2 # jump if size was == 2 - - .align 3 -Loop: mulq $2,$19,$3 # $3 = prod_low - addq $4,$0,$0 # cy_limb = cy_limb + 'cy' - subq $18,1,$18 # size-- - umulh $2,$19,$4 # $4 = cy_limb - ldq $2,16($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - addq $3,$0,$3 # $3 = cy_limb + prod_low - stq $3,8($16) - cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) - addq $16,8,$16 # res_ptr++ - bne $18,Loop - -Lend2: mulq $2,$19,$3 # $3 = prod_low - addq $4,$0,$0 # cy_limb = cy_limb + 'cy' - umulh $2,$19,$4 # $4 = cy_limb - addq $3,$0,$3 # $3 = cy_limb + prod_low - cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) - stq $3,8($16) - addq $4,$0,$0 # cy_limb = prod_high + cy - ret $31,($26),1 -Lend1: stq $3,0($16) - ret $31,($26),1 - - .end mpihelp_mul_1 - - diff --git a/mpi/alpha/mpih-mul2.S b/mpi/alpha/mpih-mul2.S deleted file mode 100644 index 595af99d3..000000000 --- a/mpi/alpha/mpih-mul2.S +++ /dev/null @@ -1,97 +0,0 @@ -/* Alpha 21064 addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 1995, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r16) - * mpi_ptr_t s1_ptr, (r17) - * mpi_size_t s1_size, (r18) - * mpi_limb_t s2_limb) (r19) - * - * This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5. - */ - - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_addmul_1 - .ent mpihelp_addmul_1 2 -mpihelp_addmul_1: - .frame $30,0,$26 - - ldq $2,0($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - subq $18,1,$18 # size-- - mulq $2,$19,$3 # $3 = prod_low - ldq $5,0($16) # $5 = *res_ptr - umulh $2,$19,$0 # $0 = prod_high - beq $18,.Lend1 # jump if size was == 1 - ldq $2,0($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - subq $18,1,$18 # size-- - addq $5,$3,$3 - cmpult $3,$5,$4 - stq $3,0($16) - addq $16,8,$16 # res_ptr++ - beq $18,.Lend2 # jump if size was == 2 - - .align 3 -.Loop: mulq $2,$19,$3 # $3 = prod_low - ldq $5,0($16) # $5 = *res_ptr - addq $4,$0,$0 # cy_limb = cy_limb + 'cy' - subq $18,1,$18 # size-- - umulh $2,$19,$4 # $4 = cy_limb - ldq $2,0($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - addq $3,$0,$3 # $3 = cy_limb + prod_low - cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) - addq $5,$3,$3 - cmpult $3,$5,$5 - stq $3,0($16) - addq $16,8,$16 # res_ptr++ - addq $5,$0,$0 # combine carries - bne $18,.Loop - -.Lend2: mulq $2,$19,$3 # $3 = prod_low - ldq $5,0($16) # $5 = *res_ptr - addq $4,$0,$0 # cy_limb = cy_limb + 'cy' - umulh $2,$19,$4 # $4 = cy_limb - addq $3,$0,$3 # $3 = cy_limb + prod_low - cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) - addq $5,$3,$3 - cmpult $3,$5,$5 - stq $3,0($16) - addq $5,$0,$0 # combine carries - addq $4,$0,$0 # cy_limb = prod_high + cy - ret $31,($26),1 -.Lend1: addq $5,$3,$3 - cmpult $3,$5,$5 - stq $3,0($16) - addq $0,$5,$0 - ret $31,($26),1 - - .end mpihelp_addmul_1 - diff --git a/mpi/alpha/mpih-mul3.S b/mpi/alpha/mpih-mul3.S deleted file mode 100644 index fa3df92a5..000000000 --- a/mpi/alpha/mpih-mul3.S +++ /dev/null @@ -1,95 +0,0 @@ -/* Alpha 21064 submul_1 -- Multiply a limb vector with a limb and - * subtract the result from a second limb vector. - * Copyright (C) 1992, 1994, 1995, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (r16 ) - * mpi_ptr_t s1_ptr, (r17 ) - * mpi_size_t s1_size, (r18 ) - * mpi_limb_t s2_limb) (r19 ) - * - * This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5. - */ - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_submul_1 - .ent mpihelp_submul_1 2 -mpihelp_submul_1: - .frame $30,0,$26 - - ldq $2,0($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - subq $18,1,$18 # size-- - mulq $2,$19,$3 # $3 = prod_low - ldq $5,0($16) # $5 = *res_ptr - umulh $2,$19,$0 # $0 = prod_high - beq $18,.Lend1 # jump if size was == 1 - ldq $2,0($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - subq $18,1,$18 # size-- - subq $5,$3,$3 - cmpult $5,$3,$4 - stq $3,0($16) - addq $16,8,$16 # res_ptr++ - beq $18,.Lend2 # jump if size was == 2 - - .align 3 -.Loop: mulq $2,$19,$3 # $3 = prod_low - ldq $5,0($16) # $5 = *res_ptr - addq $4,$0,$0 # cy_limb = cy_limb + 'cy' - subq $18,1,$18 # size-- - umulh $2,$19,$4 # $4 = cy_limb - ldq $2,0($17) # $2 = s1_limb - addq $17,8,$17 # s1_ptr++ - addq $3,$0,$3 # $3 = cy_limb + prod_low - cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) - subq $5,$3,$3 - cmpult $5,$3,$5 - stq $3,0($16) - addq $16,8,$16 # res_ptr++ - addq $5,$0,$0 # combine carries - bne $18,.Loop - -.Lend2: mulq $2,$19,$3 # $3 = prod_low - ldq $5,0($16) # $5 = *res_ptr - addq $4,$0,$0 # cy_limb = cy_limb + 'cy' - umulh $2,$19,$4 # $4 = cy_limb - addq $3,$0,$3 # $3 = cy_limb + prod_low - cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) - subq $5,$3,$3 - cmpult $5,$3,$5 - stq $3,0($16) - addq $5,$0,$0 # combine carries - addq $4,$0,$0 # cy_limb = prod_high + cy - ret $31,($26),1 -.Lend1: subq $5,$3,$3 - cmpult $5,$3,$5 - stq $3,0($16) - addq $0,$5,$0 - ret $31,($26),1 - - .end mpihelp_submul_1 - diff --git a/mpi/alpha/mpih-rshift.S b/mpi/alpha/mpih-rshift.S deleted file mode 100644 index e15542de5..000000000 --- a/mpi/alpha/mpih-rshift.S +++ /dev/null @@ -1,120 +0,0 @@ -/* alpha rshift - * Copyright (C) 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (r16) - * mpi_ptr_t up, (r17) - * mpi_size_t usize, (r18) - * unsigned cnt) (r19) - * - * This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling, - * it would take 4 cycles/limb. It should be possible to get down to 3 - * cycles/limb since both ldq and stq can be paired with the other used - * instructions. But there are many restrictions in the 21064 pipeline that - * makes it hard, if not impossible, to get down to 3 cycles/limb: - * - * 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay. - * 2. Only aligned instruction pairs can be paired. - * 3. The store buffer or silo might not be able to deal with the bandwidth. - */ - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_rshift - .ent mpihelp_rshift -mpihelp_rshift: - .frame $30,0,$26,0 - - ldq $4,0($17) # load first limb - addq $17,8,$17 - subq $31,$19,$7 - subq $18,1,$18 - and $18,4-1,$20 # number of limbs in first loop - sll $4,$7,$0 # compute function result - - beq $20,.R0 - subq $18,$20,$18 - - .align 3 -.Roop0: - ldq $3,0($17) - addq $16,8,$16 - addq $17,8,$17 - subq $20,1,$20 - srl $4,$19,$5 - sll $3,$7,$6 - bis $3,$3,$4 - bis $5,$6,$8 - stq $8,-8($16) - bne $20,.Roop0 - -.R0: beq $18,.Rend - - .align 3 -.Roop: ldq $3,0($17) - addq $16,32,$16 - subq $18,4,$18 - srl $4,$19,$5 - sll $3,$7,$6 - - ldq $4,8($17) - srl $3,$19,$1 - bis $5,$6,$8 - stq $8,-32($16) - sll $4,$7,$2 - - ldq $3,16($17) - srl $4,$19,$5 - bis $1,$2,$8 - stq $8,-24($16) - sll $3,$7,$6 - - ldq $4,24($17) - srl $3,$19,$1 - bis $5,$6,$8 - stq $8,-16($16) - sll $4,$7,$2 - - addq $17,32,$17 - bis $1,$2,$8 - stq $8,-8($16) - - bgt $18,.Roop - -.Rend: srl $4,$19,$8 - stq $8,0($16) - ret $31,($26),1 - .end mpihelp_rshift - diff --git a/mpi/alpha/mpih-sub1.S b/mpi/alpha/mpih-sub1.S deleted file mode 100644 index a32b470e2..000000000 --- a/mpi/alpha/mpih-sub1.S +++ /dev/null @@ -1,124 +0,0 @@ -/* Alpha sub_n -- Subtract two limb vectors of the same length > 0 and - * store difference in a third limb vector. - * Copyright (C) 1995, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (r16) - * mpi_ptr_t s1_ptr, (r17) - * mpi_ptr_t s2_ptr, (r18) - * mpi_size_t size) (r19) - */ - - .set noreorder - .set noat -.text - .align 3 - .globl mpihelp_sub_n - .ent mpihelp_sub_n -mpihelp_sub_n: - .frame $30,0,$26,0 - - ldq $3,0($17) - ldq $4,0($18) - - subq $19,1,$19 - and $19,4-1,$2 # number of limbs in first loop - bis $31,$31,$0 - beq $2,.L0 # if multiple of 4 limbs, skip first loop - - subq $19,$2,$19 - -.Loop0: subq $2,1,$2 - ldq $5,8($17) - addq $4,$0,$4 - ldq $6,8($18) - cmpult $4,$0,$1 - subq $3,$4,$4 - cmpult $3,$4,$0 - stq $4,0($16) - or $0,$1,$0 - - addq $17,8,$17 - addq $18,8,$18 - bis $5,$5,$3 - bis $6,$6,$4 - addq $16,8,$16 - bne $2,.Loop0 - -.L0: beq $19,.Lend - - .align 3 -.Loop: subq $19,4,$19 - - ldq $5,8($17) - addq $4,$0,$4 - ldq $6,8($18) - cmpult $4,$0,$1 - subq $3,$4,$4 - cmpult $3,$4,$0 - stq $4,0($16) - or $0,$1,$0 - - ldq $3,16($17) - addq $6,$0,$6 - ldq $4,16($18) - cmpult $6,$0,$1 - subq $5,$6,$6 - cmpult $5,$6,$0 - stq $6,8($16) - or $0,$1,$0 - - ldq $5,24($17) - addq $4,$0,$4 - ldq $6,24($18) - cmpult $4,$0,$1 - subq $3,$4,$4 - cmpult $3,$4,$0 - stq $4,16($16) - or $0,$1,$0 - - ldq $3,32($17) - addq $6,$0,$6 - ldq $4,32($18) - cmpult $6,$0,$1 - subq $5,$6,$6 - cmpult $5,$6,$0 - stq $6,24($16) - or $0,$1,$0 - - addq $17,32,$17 - addq $18,32,$18 - addq $16,32,$16 - bne $19,.Loop - -.Lend: addq $4,$0,$4 - cmpult $4,$0,$1 - subq $3,$4,$4 - cmpult $3,$4,$0 - stq $4,0($16) - or $0,$1,$0 - ret $31,($26),1 - - .end mpihelp_sub_n - - diff --git a/mpi/alpha/udiv-qrnnd.S b/mpi/alpha/udiv-qrnnd.S deleted file mode 100644 index 0079c3cae..000000000 --- a/mpi/alpha/udiv-qrnnd.S +++ /dev/null @@ -1,161 +0,0 @@ -/* Alpha 21064 __udiv_qrnnd - * - * Copyright (C) 1992, 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - - .set noreorder - .set noat -.text - .align 3 - .globl __udiv_qrnnd - .ent __udiv_qrnnd -__udiv_qrnnd: - .frame $30,0,$26,0 - .prologue 0 -#define cnt $2 -#define tmp $3 -#define rem_ptr $16 -#define n1 $17 -#define n0 $18 -#define d $19 -#define qb $20 - - ldiq cnt,16 - blt d,.Largedivisor - -.Loop1: cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule d,n1,qb - subq n1,d,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule d,n1,qb - subq n1,d,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule d,n1,qb - subq n1,d,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule d,n1,qb - subq n1,d,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - subq cnt,1,cnt - bgt cnt,.Loop1 - stq n1,0(rem_ptr) - bis $31,n0,$0 - ret $31,($26),1 - -.Largedivisor: - and n0,1,$4 - - srl n0,1,n0 - sll n1,63,tmp - or tmp,n0,n0 - srl n1,1,n1 - - and d,1,$6 - srl d,1,$5 - addq $5,$6,$5 - -.Loop2: cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule $5,n1,qb - subq n1,$5,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule $5,n1,qb - subq n1,$5,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule $5,n1,qb - subq n1,$5,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - cmplt n0,0,tmp - addq n1,n1,n1 - bis n1,tmp,n1 - addq n0,n0,n0 - cmpule $5,n1,qb - subq n1,$5,tmp - cmovne qb,tmp,n1 - bis n0,qb,n0 - subq cnt,1,cnt - bgt cnt,.Loop2 - - addq n1,n1,n1 - addq $4,n1,n1 - bne $6,.LOdd - stq n1,0(rem_ptr) - bis $31,n0,$0 - ret $31,($26),1 - -.LOdd: - /* q' in n0. r' in n1 */ - addq n1,n0,n1 - cmpult n1,n0,tmp # tmp := carry from addq - beq tmp,.LLp6 - addq n0,1,n0 - subq n1,d,n1 -.LLp6: cmpult n1,d,tmp - bne tmp,.LLp7 - addq n0,1,n0 - subq n1,d,n1 -.LLp7: - stq n1,0(rem_ptr) - bis $31,n0,$0 - ret $31,($26),1 - - .end __udiv_qrnnd diff --git a/mpi/config.links b/mpi/config.links deleted file mode 100644 index 7350a76b0..000000000 --- a/mpi/config.links +++ /dev/null @@ -1,328 +0,0 @@ -# config.links - helper for ../configure -# 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 - -# sourced by ../configure to get the list of files to link -# this should set $mpi_ln_list. -# Note: this is called from the above directory. - - -mpi_extra_modules= -mpi_sflags= - -test -d ./mpi || mkdir ./mpi - -echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h - -if test "$try_asm_modules" = "yes" ; then -case "${target}" in - powerpc-apple-darwin6.1) - echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h - path="" - ;; - - i[3467]86*-*-freebsd*-elf | \ - i[3467]86*-*-freebsd[3-9]* | \ - i[3467]86*-*-freebsdelf* | \ - i[3467]86*-*-netbsd* ) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i386" - ;; - i586*-*-freebsd*-elf | \ - i586*-*-freebsd[3-9]* | \ - i586*-*-freebsdelf* | \ - i586*-*-netbsd* | \ - pentium-*-netbsd* | \ - pentiumpro-*-netbsd*) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i586 i386" - ;; - i[34]86*-*-bsdi4*) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i386" - ;; -# Use old assembler syntax for OpenBSD as their assembler is really old. - i[34567]86*-*-openbsd*) - echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h - echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386-openbsd/syntax.h >>./mpi/asm-syntax.h - path="i386-openbsd" - ;; - i[3467]86*-*-linuxaout* | \ - i[3467]86*-*-linuxoldld* | \ - i[3467]86*-*-*bsd*) - echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h - echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i386" - ;; - i586*-*-linuxaout* | \ - i586*-*-linuxoldld* | \ - i586*-*-*bsd*) - echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h - echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i586 i386" - ;; - i[3467]86*-msdosdjgpp*) - echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i386" - ;; - i586*-msdosdjgpp*) - echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i586 i386" - ;; - i[3467]86*-*-*) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i386" - ;; - i586*-*-* | \ - pentium-*-* | \ - pentiumpro-*-*) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h - path="i586 i386" - ;; - alpha*-*-*) - echo '/* configured for alpha */' >>./mpi/asm-syntax.h - path="alpha" - mpi_extra_modules="udiv-qrnnd" - ;; - hppa7000*-*-*) - echo '/* configured for HPPA (pa7000) */' >>./mpi/asm-syntax.h - path="hppa1.1 hppa" - mpi_extra_modules="udiv-qrnnd" - ;; - hppa1.0*-*-*) - echo '/* configured for HPPA 1.0 */' >>./mpi/asm-syntax.h - path="hppa" - mpi_extra_modules="udiv-qrnnd" - ;; - hppa*-*-*) # assume pa7100 - echo '/* configured for HPPA (pa7100) */' >>./mpi/asm-syntax.h - path="pa7100 hppa1.1 hppa" - mpi_extra_modules="udiv-qrnnd" - ;; - sparc64-*-linux-gnu) - # An extra rule because we have an report for this one only. - # Should be compared against the next GMP version - echo '/* configured for sparc64-*-linux-gnu */' >>./mpi/asm-syntax.h - path="sparc32v8 sparc32" - mpi_extra_modules="udiv" - ;; - sparc64-sun-solaris2*) - # Got a report that udiv is missing, so we try this one - echo '/* configured for sparc64-sun-solaris2 */' >>./mpi/asm-syntax.h - path="sparc32v8 sparc32" - mpi_extra_modules="udiv" - ;; - sparc64-*-netbsd) - # There are no sparc64 assembler modules that work, so - # just use generic C functions - echo '/* configured for sparc64-*netbsd */' >>./mpi/asm-syntax.h - path="" - ;; - sparc9*-*-* | \ - sparc64*-*-* | \ - ultrasparc*-*-* ) - echo '/* configured for sparc9 or higher */' >>./mpi/asm-syntax.h - path="sparc32v8 sparc32" - ;; - sparc8*-*-* | \ - microsparc*-*-*) - echo '/* configured for sparc8 */' >>./mpi/asm-syntax.h - path="sparc32v8 sparc32" - ;; - supersparc*-*-*) - echo '/* configured for supersparc */' >>./mpi/asm-syntax.h - path="supersparc sparc32v8 sparc32" - mpi_extra_modules="udiv" - ;; - sparc*-*-*) - echo '/* configured for sparc */' >>./mpi/asm-syntax.h - path="sparc32" - mpi_extra_modules="udiv" - ;; - mips[34]*-*-* | \ - mips*-*-irix6*) - echo '/* configured for MIPS3 */' >>./mpi/asm-syntax.h - path="mips3" - ;; - mips*-*-*) - echo '/* configured for MIPS2 */' >>./mpi/asm-syntax.h - path="mips2" - ;; - - # Motorola 68k configurations. Let m68k mean 68020-68040. - # mc68000 or mc68060 configurations need to be specified explicitly - m680[234]0*-*-linuxaout* | \ - m68k*-*-linuxaout*) - echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - path="m68k/mc68020 m68k" - ;; - m68060*-*-linuxaout*) - echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - path="m68k" - ;; - m680[234]0*-*-linux* | \ - m68k*-*-linux*) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - ;; - m68060*-*-linux*) - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - path="m68k" - ;; - m68k-atari-mint) - echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - path="m68k/mc68020 m68k" - ;; - m68000*-*-* | \ - m68060*-*-*) - echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - path="m68k/mc68000" - ;; - m680[234]0*-*-* | \ - m68k*-*-*) - echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h - path="m68k/mc68020 m68k" - ;; - - powerpc*-*-linux*) - echo '/* configured for powerpc/ELF */' >>./mpi/asm-syntax.h - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h - path="powerpc32" - ;; - - powerpc*-*-netbsd* | powerpc*-*-openbsd*) - echo '/* configured {Open,Net}BSD on powerpc */' >>./mpi/asm-syntax.h - echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h - cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h - mpi_sflags="-Wa,-mppc" - path="powerpc32" - ;; - - rs6000-*-aix[456789]* | \ - rs6000-*-aix3.2.[456789]) - mpi_sflags="-Wa,-mpwr" - path="power" - mpi_extra_modules="udiv-w-sdiv" - ;; - rs6000-*-* | \ - power-*-* | \ - power2-*-*) - mpi_sflags="-Wa,-mppc" - path="power" - mpi_extra_modules="udiv-w-sdiv" - ;; - powerpc-ibm-aix4.2.* ) - # I am not sure about this one but a machine identified by - # powerpc-ibm-aix4.2.1.0 cannot use the powerpc32 code. - mpi_sflags="-Wa,-mpwr" - path="power" - mpi_extra_modules="udiv-w-sdiv" - ;; - ppc601-*-*) - mpi_sflags="-Wa,-mppc" - path="power powerpc32" - ;; - ppc60[234]*-*-* | \ - powerpc*-*-*) - mpi_sflags="-Wa,-mppc" - path="powerpc32" - ;; - ppc620-*-* | \ - powerpc64*-*-*) - mpi_sflags="-Wa,-mppc" - path="powerpc64" - ;; - - *) - echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h - path="" - ;; -esac -else - echo '/* Assembler modules disabled on request */' >>./mpi/asm-syntax.h - path="" -fi - - -# Make sysdep.h -echo '/* created by config.links - do not edit */' >./mpi/sysdep.h -if test x$ac_cv_sys_symbol_underscore = xyes; then - cat <>./mpi/sysdep.h -#if __STDC__ -#define C_SYMBOL_NAME(name) _##name -#else -#define C_SYMBOL_NAME(name) _/**/name -#endif -EOF -else - cat <>./mpi/sysdep.h -#define C_SYMBOL_NAME(name) name -EOF -fi - - -# fixme: grep these modules from Makefile.in -mpi_ln_modules="${mpi_extra_modules} mpih-add1 mpih-mul1 mpih-mul2 mpih-mul3 \ - mpih-lshift mpih-rshift mpih-sub1" - -mpi_ln_objects= -mpi_ln_list= - -# try to get file to link from the assembler subdirectory and -# if this fails get it from the generic subdirectory. -path="$path generic" -for fn in $mpi_ln_modules ; do - mpi_ln_objects="$mpi_ln_objects $fn.o" - for dir in $path ; do - rm -f $srcdir/mpi/$fn.[Sc] - if test -f $srcdir/mpi/$dir/$fn.S ; then - mpi_ln_list="$mpi_ln_list mpi/$fn.S:mpi/$dir/$fn.S" - break; - elif test -f $srcdir/mpi/$dir/$fn.c ; then - mpi_ln_list="$mpi_ln_list mpi/$fn.c:mpi/$dir/$fn.c" - break; - fi - done -done - -# Same thing for the file which defines the limb size -path="$path generic" -for dir in $path ; do - rm -f $srcdir/mpi/mpi-asm-defs.h - if test -f $srcdir/mpi/$dir/mpi-asm-defs.h ; then - mpi_ln_list="$mpi_ln_list mpi/mpi-asm-defs.h:mpi/$dir/mpi-asm-defs.h" - break; - fi -done diff --git a/mpi/g10m.c b/mpi/g10m.c deleted file mode 100644 index ea6696dc7..000000000 --- a/mpi/g10m.c +++ /dev/null @@ -1,95 +0,0 @@ -/* g10m.c - Wrapper for MPI - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include -#include -#include -#include "mpi.h" -#include "util.h" - -/* FIXME: The modules should use functions from libgcrypt */ - -const char *g10m_revision_string(int dummy) { return "$Revision$"; } - -MPI -g10m_new( unsigned nbits ) -{ - return mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); -} - -MPI -g10m_new_secure( unsigned nbits ) -{ - return mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); -} - -void -g10m_release( MPI a ) -{ - mpi_free(a); -} - -void -g10m_resize( MPI a, unsigned nbits ) -{ - mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); -} - -MPI g10m_copy( MPI a ) { return mpi_copy( a ); } -void g10m_swap( MPI a, MPI b) { mpi_swap( a, b ); } -void g10m_set( MPI w, MPI u) { mpi_set( w, u ); } -void g10m_set_ui( MPI w, ulong u ) { mpi_set_ui( w, u ); } - -int g10m_cmp( MPI u, MPI v ) { return mpi_cmp( u, v ); } -int g10m_cmp_ui( MPI u, ulong v ) { return mpi_cmp_ui( u, v ); } - -void g10m_add(MPI w, MPI u, MPI v) { mpi_add( w, u, v ); } -void g10m_add_ui(MPI w, MPI u, ulong v ) { mpi_add_ui( w, u, v ); } -void g10m_sub( MPI w, MPI u, MPI v) { mpi_sub( w, u, v ); } -void g10m_sub_ui(MPI w, MPI u, ulong v ) { mpi_sub_ui( w, u, v ); } - -void g10m_mul( MPI w, MPI u, MPI v) { mpi_mul( w, u, v ); } -void g10m_mulm( MPI w, MPI u, MPI v, MPI m) { mpi_mulm( w, u, v, m ); } -void g10m_mul_2exp( MPI w, MPI u, ulong cnt) { mpi_mul_2exp( w, u, cnt ); } -void g10m_mul_ui(MPI w, MPI u, ulong v ) { mpi_mul_ui( w, u, v ); } - -void g10m_fdiv_q( MPI q, MPI d, MPI r ) { mpi_fdiv_q( q, d, r ); } - -void g10m_powm( MPI r, MPI b, MPI e, MPI m) { mpi_powm( r, b, e, m ); } - -int g10m_gcd( MPI g, MPI a, MPI b ) { return mpi_gcd( g, a, b ); } -int g10m_invm( MPI x, MPI u, MPI v ) { mpi_invm( x, u, v ); return 0; } - -unsigned g10m_get_nbits( MPI a ) { return mpi_get_nbits( a ); } - -unsigned -g10m_get_size( MPI a ) -{ - return mpi_get_nlimbs( a ) * BITS_PER_MPI_LIMB; -} - - -void -g10m_set_buffer( MPI a, const char *buffer, unsigned nbytes, int sign ) -{ - mpi_set_buffer( a, buffer, nbytes, sign ); -} - - diff --git a/mpi/generic/distfiles b/mpi/generic/distfiles deleted file mode 100644 index 649e829b7..000000000 --- a/mpi/generic/distfiles +++ /dev/null @@ -1,10 +0,0 @@ -mpih-add1.c -mpih-mul1.c -mpih-mul2.c -mpih-mul3.c -mpih-lshift.c -mpih-rshift.c -mpih-sub1.c -udiv-w-sdiv.c -mpi-asm-defs.h - diff --git a/mpi/generic/mpi-asm-defs.h b/mpi/generic/mpi-asm-defs.h deleted file mode 100644 index 13424e280..000000000 --- a/mpi/generic/mpi-asm-defs.h +++ /dev/null @@ -1,10 +0,0 @@ -/* This file defines some basic constants for the MPI machinery. We - * need to define the types on a per-CPU basis, so it is done with - * this file here. */ -#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) - - - - - - diff --git a/mpi/generic/mpih-add1.c b/mpi/generic/mpih-add1.c deleted file mode 100644 index d9c3cbb66..000000000 --- a/mpi/generic/mpih-add1.c +++ /dev/null @@ -1,65 +0,0 @@ -/* mpihelp-add_1.c - MPI helper functions - * Copyright (C) 1994, 1996, 1997, 1998, - * 2000 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - -mpi_limb_t -mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_ptr_t s2_ptr, mpi_size_t size) -{ - mpi_limb_t x, y, cy; - mpi_size_t j; - - /* The loop counter and index J goes from -SIZE to -1. This way - the loop becomes faster. */ - j = -size; - - /* Offset the base pointers to compensate for the negative indices. */ - s1_ptr -= j; - s2_ptr -= j; - res_ptr -= j; - - cy = 0; - do { - y = s2_ptr[j]; - x = s1_ptr[j]; - y += cy; /* add previous carry to one addend */ - cy = y < cy; /* get out carry from that addition */ - y += x; /* add other addend */ - cy += y < x; /* get out carry from that add, combine */ - res_ptr[j] = y; - } while( ++j ); - - return cy; -} - diff --git a/mpi/generic/mpih-lshift.c b/mpi/generic/mpih-lshift.c deleted file mode 100644 index fba8c052e..000000000 --- a/mpi/generic/mpih-lshift.c +++ /dev/null @@ -1,69 +0,0 @@ -/* mpihelp-lshift.c - MPI helper functions - * Copyright (C) 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" - -/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left - * and store the USIZE least significant digits of the result at WP. - * Return the bits shifted out from the most significant digit. - * - * Argument constraints: - * 1. 0 < CNT < BITS_PER_MP_LIMB - * 2. If the result is to be written over the input, WP must be >= UP. - */ - -mpi_limb_t -mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, - unsigned int cnt) -{ - mpi_limb_t high_limb, low_limb; - unsigned sh_1, sh_2; - mpi_size_t i; - mpi_limb_t retval; - - sh_1 = cnt; - wp += 1; - sh_2 = BITS_PER_MPI_LIMB - sh_1; - i = usize - 1; - low_limb = up[i]; - retval = low_limb >> sh_2; - high_limb = low_limb; - while( --i >= 0 ) { - low_limb = up[i]; - wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); - high_limb = low_limb; - } - wp[i] = high_limb << sh_1; - - return retval; -} - - diff --git a/mpi/generic/mpih-mul1.c b/mpi/generic/mpih-mul1.c deleted file mode 100644 index 83a81add0..000000000 --- a/mpi/generic/mpih-mul1.c +++ /dev/null @@ -1,61 +0,0 @@ -/* mpihelp-mul_1.c - MPI helper functions - * Copyright (C) 1994, 1996, 1997, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - -mpi_limb_t -mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, - mpi_limb_t s2_limb) -{ - mpi_limb_t cy_limb; - mpi_size_t j; - mpi_limb_t prod_high, prod_low; - - /* The loop counter and index J goes from -S1_SIZE to -1. This way - * the loop becomes faster. */ - j = -s1_size; - - /* Offset the base pointers to compensate for the negative indices. */ - s1_ptr -= j; - res_ptr -= j; - - cy_limb = 0; - do { - umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); - prod_low += cy_limb; - cy_limb = (prod_low < cy_limb?1:0) + prod_high; - res_ptr[j] = prod_low; - } while( ++j ); - - return cy_limb; -} - diff --git a/mpi/generic/mpih-mul2.c b/mpi/generic/mpih-mul2.c deleted file mode 100644 index ff8f998f2..000000000 --- a/mpi/generic/mpih-mul2.c +++ /dev/null @@ -1,66 +0,0 @@ -/* mpihelp-mul_2.c - MPI helper functions - * Copyright (C) 1994, 1996, 1997, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - - -mpi_limb_t -mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb) -{ - mpi_limb_t cy_limb; - mpi_size_t j; - mpi_limb_t prod_high, prod_low; - mpi_limb_t x; - - /* The loop counter and index J goes from -SIZE to -1. This way - * the loop becomes faster. */ - j = -s1_size; - res_ptr -= j; - s1_ptr -= j; - - cy_limb = 0; - do { - umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); - - prod_low += cy_limb; - cy_limb = (prod_low < cy_limb?1:0) + prod_high; - - x = res_ptr[j]; - prod_low = x + prod_low; - cy_limb += prod_low < x?1:0; - res_ptr[j] = prod_low; - } while ( ++j ); - return cy_limb; -} - - diff --git a/mpi/generic/mpih-mul3.c b/mpi/generic/mpih-mul3.c deleted file mode 100644 index 80eedcc4c..000000000 --- a/mpi/generic/mpih-mul3.c +++ /dev/null @@ -1,67 +0,0 @@ -/* mpihelp-mul_3.c - MPI helper functions - * Copyright (C) 1994, 1996, 1997, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - - -mpi_limb_t -mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb) -{ - mpi_limb_t cy_limb; - mpi_size_t j; - mpi_limb_t prod_high, prod_low; - mpi_limb_t x; - - /* The loop counter and index J goes from -SIZE to -1. This way - * the loop becomes faster. */ - j = -s1_size; - res_ptr -= j; - s1_ptr -= j; - - cy_limb = 0; - do { - umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); - - prod_low += cy_limb; - cy_limb = (prod_low < cy_limb?1:0) + prod_high; - - x = res_ptr[j]; - prod_low = x - prod_low; - cy_limb += prod_low > x?1:0; - res_ptr[j] = prod_low; - } while( ++j ); - - return cy_limb; -} - - diff --git a/mpi/generic/mpih-rshift.c b/mpi/generic/mpih-rshift.c deleted file mode 100644 index be73adfb8..000000000 --- a/mpi/generic/mpih-rshift.c +++ /dev/null @@ -1,68 +0,0 @@ -/* mpih-rshift.c - MPI helper functions - * Copyright (C) 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" - - -/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right - * and store the USIZE least significant limbs of the result at WP. - * The bits shifted out to the right are returned. - * - * Argument constraints: - * 1. 0 < CNT < BITS_PER_MP_LIMB - * 2. If the result is to be written over the input, WP must be <= UP. - */ - -mpi_limb_t -mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) -{ - mpi_limb_t high_limb, low_limb; - unsigned sh_1, sh_2; - mpi_size_t i; - mpi_limb_t retval; - - sh_1 = cnt; - wp -= 1; - sh_2 = BITS_PER_MPI_LIMB - sh_1; - high_limb = up[0]; - retval = high_limb << sh_2; - low_limb = high_limb; - for( i=1; i < usize; i++) { - high_limb = up[i]; - wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); - low_limb = high_limb; - } - wp[i] = low_limb >> sh_1; - - return retval; -} - diff --git a/mpi/generic/mpih-sub1.c b/mpi/generic/mpih-sub1.c deleted file mode 100644 index c618fee49..000000000 --- a/mpi/generic/mpih-sub1.c +++ /dev/null @@ -1,65 +0,0 @@ -/* mpihelp-add_2.c - MPI helper functions - * Copyright (C) 1994, 1996, 1997, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - -mpi_limb_t -mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_ptr_t s2_ptr, mpi_size_t size) -{ - mpi_limb_t x, y, cy; - mpi_size_t j; - - /* The loop counter and index J goes from -SIZE to -1. This way - the loop becomes faster. */ - j = -size; - - /* Offset the base pointers to compensate for the negative indices. */ - s1_ptr -= j; - s2_ptr -= j; - res_ptr -= j; - - cy = 0; - do { - y = s2_ptr[j]; - x = s1_ptr[j]; - y += cy; /* add previous carry to subtrahend */ - cy = y < cy; /* get out carry from that addition */ - y = x - y; /* main subtract */ - cy += y > x; /* get out carry from the subtract, combine */ - res_ptr[j] = y; - } while( ++j ); - - return cy; -} - - diff --git a/mpi/generic/udiv-w-sdiv.c b/mpi/generic/udiv-w-sdiv.c deleted file mode 100644 index dd0285037..000000000 --- a/mpi/generic/udiv-w-sdiv.c +++ /dev/null @@ -1,133 +0,0 @@ -/* mpihelp_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed - * division. - * Copyright (C) 1992, 1994, 1996, 1998 Free Software Foundation, Inc. - * Contributed by Peter L. Montgomery. - * - * 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 -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - - -#if 0 /* not yet ported to MPI */ - -mpi_limb_t -mpihelp_udiv_w_sdiv( mpi_limp_t *rp, - mpi_limp_t *a1, - mpi_limp_t *a0, - mpi_limp_t *d ) -{ - mp_limb_t q, r; - mp_limb_t c0, c1, b1; - - if ((mpi_limb_signed_t) d >= 0) - { - if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1))) - { - /* dividend, divisor, and quotient are nonnegative */ - sdiv_qrnnd (q, r, a1, a0, d); - } - else - { - /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ - sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1)); - /* Divide (c1*2^32 + c0) by d */ - sdiv_qrnnd (q, r, c1, c0, d); - /* Add 2^31 to quotient */ - q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); - } - } - else - { - b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ - c1 = a1 >> 1; /* A/2 */ - c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1); - - if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ - { - sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ - - r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ - if ((d & 1) != 0) - { - if (r >= q) - r = r - q; - else if (q - r <= d) - { - r = r - q + d; - q--; - } - else - { - r = r - q + 2*d; - q -= 2; - } - } - } - else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ - { - c1 = (b1 - 1) - c1; - c0 = ~c0; /* logical NOT */ - - sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ - - q = ~q; /* (A/2)/b1 */ - r = (b1 - 1) - r; - - r = 2*r + (a0 & 1); /* A/(2*b1) */ - - if ((d & 1) != 0) - { - if (r >= q) - r = r - q; - else if (q - r <= d) - { - r = r - q + d; - q--; - } - else - { - r = r - q + 2*d; - q -= 2; - } - } - } - else /* Implies c1 = b1 */ - { /* Hence a1 = d - 1 = 2*b1 - 1 */ - if (a0 >= -d) - { - q = -1; - r = a0 + d; - } - else - { - q = -2; - r = a0 + 2*d; - } - } - } - - *rp = r; - return q; -} - -#endif - diff --git a/mpi/hppa/README b/mpi/hppa/README deleted file mode 100644 index 5a2d5fd97..000000000 --- a/mpi/hppa/README +++ /dev/null @@ -1,84 +0,0 @@ -This directory contains mpn functions for various HP PA-RISC chips. Code -that runs faster on the PA7100 and later implementations, is in the pa7100 -directory. - -RELEVANT OPTIMIZATION ISSUES - - Load and Store timing - -On the PA7000 no memory instructions can issue the two cycles after a store. -For the PA7100, this is reduced to one cycle. - -The PA7100 has a lookup-free cache, so it helps to schedule loads and the -dependent instruction really far from each other. - -STATUS - -1. mpn_mul_1 could be improved to 6.5 cycles/limb on the PA7100, using the - instructions bwlow (but some sw pipelining is needed to avoid the - xmpyu-fstds delay): - - fldds s1_ptr - - xmpyu - fstds N(%r30) - xmpyu - fstds N(%r30) - - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - - addc - stws res_ptr - addc - stws res_ptr - - addib Loop - -2. mpn_addmul_1 could be improved from the current 10 to 7.5 cycles/limb - (asymptotically) on the PA7100, using the instructions below. With proper - sw pipelining and the unrolling level below, the speed becomes 8 - cycles/limb. - - fldds s1_ptr - fldds s1_ptr - - xmpyu - fstds N(%r30) - xmpyu - fstds N(%r30) - xmpyu - fstds N(%r30) - xmpyu - fstds N(%r30) - - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - ldws N(%r30) - addc - addc - addc - addc - addc %r0,%r0,cy-limb - - ldws res_ptr - ldws res_ptr - ldws res_ptr - ldws res_ptr - add - stws res_ptr - addc - stws res_ptr - addc - stws res_ptr - addc - stws res_ptr - - addib diff --git a/mpi/hppa/distfiles b/mpi/hppa/distfiles deleted file mode 100644 index 7f24205d3..000000000 --- a/mpi/hppa/distfiles +++ /dev/null @@ -1,7 +0,0 @@ -README -udiv-qrnnd.S -mpih-add1.S -mpih-sub1.S -mpih-lshift.S -mpih-rshift.S - diff --git a/mpi/hppa/mpih-add1.S b/mpi/hppa/mpih-add1.S deleted file mode 100644 index 7a2a2c2cb..000000000 --- a/mpi/hppa/mpih-add1.S +++ /dev/null @@ -1,72 +0,0 @@ -/* hppa add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1998, - * 2001 Fee 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, (gr26) - * mpi_ptr_t s1_ptr, (gr25) - * mpi_ptr_t s2_ptr, (gr24) - * mpi_size_t size) (gr23) - * - * One might want to unroll this as for other processors, but it turns - * out that the data cache contention after a store makes such - * unrolling useless. We can't come under 5 cycles/limb anyway. - */ - - .code - .export mpihelp_add_n - .label mpihelp_add_n - .proc - .callinfo frame=0,no_calls - .entry - - ldws,ma 4(0,%r25),%r20 - ldws,ma 4(0,%r24),%r19 - - addib,= -1,%r23,L$end ; check for (SIZE == 1) - add %r20,%r19,%r28 ; add first limbs ignoring cy - - .label L$loop - ldws,ma 4(0,%r25),%r20 - ldws,ma 4(0,%r24),%r19 - stws,ma %r28,4(0,%r26) - addib,<> -1,%r23,L$loop - addc %r20,%r19,%r28 - - .label L$end - stws %r28,0(0,%r26) - bv 0(%r2) - addc %r0,%r0,%r28 - - .exit - .procend diff --git a/mpi/hppa/mpih-lshift.S b/mpi/hppa/mpih-lshift.S deleted file mode 100644 index 6a8b2c4ce..000000000 --- a/mpi/hppa/mpih-lshift.S +++ /dev/null @@ -1,77 +0,0 @@ -/* hppa lshift - * - * Copyright (C) 1992, 1994, 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 - */ - - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (gr26) - * mpi_ptr_t up, (gr25) - * mpi_size_t usize, (gr24) - * unsigned cnt) (gr23) - */ - - .code - .export mpihelp_lshift - .label mpihelp_lshift - .proc - .callinfo frame=64,no_calls - .entry - - sh2add %r24,%r25,%r25 - sh2add %r24,%r26,%r26 - ldws,mb -4(0,%r25),%r22 - subi 32,%r23,%r1 - mtsar %r1 - addib,= -1,%r24,L$0004 - vshd %r0,%r22,%r28 ; compute carry out limb - ldws,mb -4(0,%r25),%r29 - addib,= -1,%r24,L$0002 - vshd %r22,%r29,%r20 - - .label L$loop - ldws,mb -4(0,%r25),%r22 - stws,mb %r20,-4(0,%r26) - addib,= -1,%r24,L$0003 - vshd %r29,%r22,%r20 - ldws,mb -4(0,%r25),%r29 - stws,mb %r20,-4(0,%r26) - addib,<> -1,%r24,L$loop - vshd %r22,%r29,%r20 - - .label L$0002 - stws,mb %r20,-4(0,%r26) - vshd %r29,%r0,%r20 - bv 0(%r2) - stw %r20,-4(0,%r26) - .label L$0003 - stws,mb %r20,-4(0,%r26) - .label L$0004 - vshd %r22,%r0,%r20 - bv 0(%r2) - stw %r20,-4(0,%r26) - - .exit - .procend - - - diff --git a/mpi/hppa/mpih-rshift.S b/mpi/hppa/mpih-rshift.S deleted file mode 100644 index b1e6a6795..000000000 --- a/mpi/hppa/mpih-rshift.S +++ /dev/null @@ -1,73 +0,0 @@ -/* hppa rshift - * - * Copyright (C) 1992, 1994, 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 - */ - - - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (gr26) - * mpi_ptr_t up, (gr25) - * mpi_size_t usize, (gr24) - * unsigned cnt) (gr23) - */ - - .code - .export mpihelp_rshift - .label mpihelp_rshift - .proc - .callinfo frame=64,no_calls - .entry - - ldws,ma 4(0,%r25),%r22 - mtsar %r23 - addib,= -1,%r24,L$r004 - vshd %r22,%r0,%r28 ; compute carry out limb - ldws,ma 4(0,%r25),%r29 - addib,= -1,%r24,L$r002 - vshd %r29,%r22,%r20 - - .label L$roop - ldws,ma 4(0,%r25),%r22 - stws,ma %r20,4(0,%r26) - addib,= -1,%r24,L$r003 - vshd %r22,%r29,%r20 - ldws,ma 4(0,%r25),%r29 - stws,ma %r20,4(0,%r26) - addib,<> -1,%r24,L$roop - vshd %r29,%r22,%r20 - - .label L$r002 - stws,ma %r20,4(0,%r26) - vshd %r0,%r29,%r20 - bv 0(%r2) - stw %r20,0(0,%r26) - .label L$r003 - stws,ma %r20,4(0,%r26) - .label L$r004 - vshd %r0,%r22,%r20 - bv 0(%r2) - stw %r20,0(0,%r26) - - .exit - .procend - diff --git a/mpi/hppa/mpih-sub1.S b/mpi/hppa/mpih-sub1.S deleted file mode 100644 index 870009e95..000000000 --- a/mpi/hppa/mpih-sub1.S +++ /dev/null @@ -1,80 +0,0 @@ -/* hppa sub_n -- Sub two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (gr26) - * mpi_ptr_t s1_ptr, (gr25) - * mpi_ptr_t s2_ptr, (gr24) - * mpi_size_t size) (gr23) - * - * One might want to unroll this as for other processors, but it turns - * out that the data cache contention after a store makes such - * unrolling useless. We can't come under 5 cycles/limb anyway. - */ - - - .code - .export mpihelp_sub_n - .label mpihelp_sub_n - .proc - .callinfo frame=0,no_calls - .entry - - ldws,ma 4(0,%r25),%r20 - ldws,ma 4(0,%r24),%r19 - - addib,= -1,%r23,L$end ; check for (SIZE == 1) - sub %r20,%r19,%r28 ; subtract first limbs ignoring cy - - .label L$loop - ldws,ma 4(0,%r25),%r20 - ldws,ma 4(0,%r24),%r19 - stws,ma %r28,4(0,%r26) - addib,<> -1,%r23,L$loop - subb %r20,%r19,%r28 - - .label L$end - stws %r28,0(0,%r26) - addc %r0,%r0,%r28 - bv 0(%r2) - subi 1,%r28,%r28 - - .exit - .procend - - - diff --git a/mpi/hppa/udiv-qrnnd.S b/mpi/hppa/udiv-qrnnd.S deleted file mode 100644 index c8a52412b..000000000 --- a/mpi/hppa/udiv-qrnnd.S +++ /dev/null @@ -1,298 +0,0 @@ -/* HP-PA __udiv_qrnnd division support, used from longlong.h. - * This version runs fast on pre-PA7000 CPUs. - * - * Copyright (C) 1993, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -/* INPUT PARAMETERS - * rem_ptr gr26 - * n1 gr25 - * n0 gr24 - * d gr23 - * - * The code size is a bit excessive. We could merge the last two ds;addc - * sequences by simply moving the "bb,< Odd" instruction down. The only - * trouble is the FFFFFFFF code that would need some hacking. - */ - - .code - .export __udiv_qrnnd - .label __udiv_qrnnd - .proc - .callinfo frame=0,no_calls - .entry - - comb,< %r23,0,L$largedivisor - sub %r0,%r23,%r1 ; clear cy as side-effect - ds %r0,%r1,%r0 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r24 - ds %r25,%r23,%r25 - addc %r24,%r24,%r28 - ds %r25,%r23,%r25 - comclr,>= %r25,%r0,%r0 - addl %r25,%r23,%r25 - stws %r25,0(0,%r26) - bv 0(%r2) - addc %r28,%r28,%r28 - - .label L$largedivisor - extru %r24,31,1,%r19 ; r19 = n0 & 1 - bb,< %r23,31,L$odd - extru %r23,30,31,%r22 ; r22 = d >> 1 - shd %r25,%r24,1,%r24 ; r24 = new n0 - extru %r25,30,31,%r25 ; r25 = new n1 - sub %r0,%r22,%r21 - ds %r0,%r21,%r0 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - comclr,>= %r25,%r0,%r0 - addl %r25,%r22,%r25 - sh1addl %r25,%r19,%r25 - stws %r25,0(0,%r26) - bv 0(%r2) - addc %r24,%r24,%r28 - - .label L$odd - addib,sv,n 1,%r22,L$FF.. ; r22 = (d / 2 + 1) - shd %r25,%r24,1,%r24 ; r24 = new n0 - extru %r25,30,31,%r25 ; r25 = new n1 - sub %r0,%r22,%r21 - ds %r0,%r21,%r0 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r24 - ds %r25,%r22,%r25 - addc %r24,%r24,%r28 - comclr,>= %r25,%r0,%r0 - addl %r25,%r22,%r25 - sh1addl %r25,%r19,%r25 -; We have computed (n1,,n0) / (d + 1), q' = r28, r' = r25 - add,nuv %r28,%r25,%r25 - addl %r25,%r1,%r25 - addc %r0,%r28,%r28 - sub,<< %r25,%r23,%r0 - addl %r25,%r1,%r25 - stws %r25,0(0,%r26) - bv 0(%r2) - addc %r0,%r28,%r28 - -; This is just a special case of the code above. -; We come here when d == 0xFFFFFFFF - .label L$FF.. - add,uv %r25,%r24,%r24 - sub,<< %r24,%r23,%r0 - ldo 1(%r24),%r24 - stws %r24,0(0,%r26) - bv 0(%r2) - addc %r0,%r25,%r28 - - .exit - .procend diff --git a/mpi/hppa1.1/distfiles b/mpi/hppa1.1/distfiles deleted file mode 100644 index d68227ac7..000000000 --- a/mpi/hppa1.1/distfiles +++ /dev/null @@ -1,5 +0,0 @@ -udiv-qrnnd.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S - diff --git a/mpi/hppa1.1/mpih-mul1.S b/mpi/hppa1.1/mpih-mul1.S deleted file mode 100644 index ac9baced4..000000000 --- a/mpi/hppa1.1/mpih-mul1.S +++ /dev/null @@ -1,115 +0,0 @@ -/* hppa1.1 mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1993, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (r26) - * mpi_ptr_t s1_ptr, (r25) - * mpi_size_t s1_size, (r24) - * mpi_limb_t s2_limb) (r23) - * - * - * - * This runs at 9 cycles/limb on a PA7000. With the used instructions, it can - * not become faster due to data cache contention after a store. On the - * PA7100 it runs at 7 cycles/limb, and that can not be improved either, since - * only the xmpyu does not need the integer pipeline, so the only dual-issue - * we will get are addc+xmpyu. Unrolling would not help either CPU. - * - * We could use fldds to read two limbs at a time from the S1 array, and that - * could bring down the times to 8.5 and 6.5 cycles/limb for the PA7000 and - * PA7100, respectively. We don't do that since it does not seem worth the - * (alignment) troubles... - * - * At least the PA7100 is rumored to be able to deal with cache-misses - * without stalling instruction issue. If this is true, and the cache is - * actually also lockup-free, we should use a deeper software pipeline, and - * load from S1 very early! (The loads and stores to -12(sp) will surely be - * in the cache.) - */ - - .code - .export mpihelp_mul_1 - .label mpihelp_mul_1 - .proc - .callinfo frame=64,no_calls - .entry - - ldo 64(%r30),%r30 - fldws,ma 4(%r25),%fr5 - stw %r23,-16(%r30) ; move s2_limb ... - addib,= -1,%r24,L$just_one_limb - fldws -16(%r30),%fr4 ; ... into fr4 - add %r0,%r0,%r0 ; clear carry - xmpyu %fr4,%fr5,%fr6 - fldws,ma 4(%r25),%fr7 - fstds %fr6,-16(%r30) - xmpyu %fr4,%fr7,%fr8 - ldw -12(%r30),%r19 ; least significant limb in product - ldw -16(%r30),%r28 - - fstds %fr8,-16(%r30) - addib,= -1,%r24,L$end - ldw -12(%r30),%r1 - -; Main loop - .label L$loop - fldws,ma 4(%r25),%fr5 - stws,ma %r19,4(%r26) - addc %r28,%r1,%r19 - xmpyu %fr4,%fr5,%fr6 - ldw -16(%r30),%r28 - fstds %fr6,-16(%r30) - addib,<> -1,%r24,L$loop - ldw -12(%r30),%r1 - - .label L$end - stws,ma %r19,4(%r26) - addc %r28,%r1,%r19 - ldw -16(%r30),%r28 - stws,ma %r19,4(%r26) - addc %r0,%r28,%r28 - bv 0(%r2) - ldo -64(%r30),%r30 - - .label L$just_one_limb - xmpyu %fr4,%fr5,%fr6 - fstds %fr6,-16(%r30) - ldw -16(%r30),%r28 - ldo -64(%r30),%r30 - bv 0(%r2) - fstws %fr6R,0(%r26) - - .exit - .procend - - diff --git a/mpi/hppa1.1/mpih-mul2.S b/mpi/hppa1.1/mpih-mul2.S deleted file mode 100644 index c73397e3e..000000000 --- a/mpi/hppa1.1/mpih-mul2.S +++ /dev/null @@ -1,117 +0,0 @@ -/* hppa1.1 addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1993, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r26) - * mpi_ptr_t s1_ptr, (r25) - * mpi_size_t s1_size, (r24) - * mpi_limb_t s2_limb) (r23) - * - * This runs at 11 cycles/limb on a PA7000. With the used instructions, it - * can not become faster due to data cache contention after a store. On the - * PA7100 it runs at 10 cycles/limb, and that can not be improved either, - * since only the xmpyu does not need the integer pipeline, so the only - * dual-issue we will get are addc+xmpyu. Unrolling could gain a cycle/limb - * on the PA7100. - * - * There are some ideas described in mul1.S that applies to this code too. - */ - - .code - .export mpihelp_addmul_1 - .label mpihelp_addmul_1 - .proc - .callinfo frame=64,no_calls - .entry - - ldo 64(%r30),%r30 - fldws,ma 4(%r25),%fr5 - stw %r23,-16(%r30) ; move s2_limb ... - addib,= -1,%r24,L$just_one_limb - fldws -16(%r30),%fr4 ; ... into fr4 - add %r0,%r0,%r0 ; clear carry - xmpyu %fr4,%fr5,%fr6 - fldws,ma 4(%r25),%fr7 - fstds %fr6,-16(%r30) - xmpyu %fr4,%fr7,%fr8 - ldw -12(%r30),%r19 ; least significant limb in product - ldw -16(%r30),%r28 - - fstds %fr8,-16(%r30) - addib,= -1,%r24,L$end - ldw -12(%r30),%r1 - -; Main loop - .label L$loop - ldws 0(%r26),%r29 - fldws,ma 4(%r25),%fr5 - add %r29,%r19,%r19 - stws,ma %r19,4(%r26) - addc %r28,%r1,%r19 - xmpyu %fr4,%fr5,%fr6 - ldw -16(%r30),%r28 - fstds %fr6,-16(%r30) - addc %r0,%r28,%r28 - addib,<> -1,%r24,L$loop - ldw -12(%r30),%r1 - - .label L$end - ldw 0(%r26),%r29 - add %r29,%r19,%r19 - stws,ma %r19,4(%r26) - addc %r28,%r1,%r19 - ldw -16(%r30),%r28 - ldws 0(%r26),%r29 - addc %r0,%r28,%r28 - add %r29,%r19,%r19 - stws,ma %r19,4(%r26) - addc %r0,%r28,%r28 - bv 0(%r2) - ldo -64(%r30),%r30 - - .label L$just_one_limb - xmpyu %fr4,%fr5,%fr6 - ldw 0(%r26),%r29 - fstds %fr6,-16(%r30) - ldw -12(%r30),%r1 - ldw -16(%r30),%r28 - add %r29,%r1,%r19 - stw %r19,0(%r26) - addc %r0,%r28,%r28 - bv 0(%r2) - ldo -64(%r30),%r30 - - .exit - .procend - - diff --git a/mpi/hppa1.1/mpih-mul3.S b/mpi/hppa1.1/mpih-mul3.S deleted file mode 100644 index f9ccb1b57..000000000 --- a/mpi/hppa1.1/mpih-mul3.S +++ /dev/null @@ -1,127 +0,0 @@ -/* hppa1.1 submul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1993, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (r26) - * mpi_ptr_t s1_ptr, (r25) - * mpi_size_t s1_size, (r24) - * mpi_limb_t s2_limb) (r23) - * - * - * This runs at 12 cycles/limb on a PA7000. With the used instructions, it - * can not become faster due to data cache contention after a store. On the - * PA7100 it runs at 11 cycles/limb, and that can not be improved either, - * since only the xmpyu does not need the integer pipeline, so the only - * dual-issue we will get are addc+xmpyu. Unrolling could gain a cycle/limb - * on the PA7100. - * - * There are some ideas described in mul1.S that applies to this code too. - * - * It seems possible to make this run as fast as addmul_1, if we use - * sub,>>= %r29,%r19,%r22 - * addi 1,%r28,%r28 - * but that requires reworking the hairy software pipeline... - */ - - - .code - .export mpihelp_submul_1 - .label mpihelp_submul_1 - .proc - .callinfo frame=64,no_calls - .entry - - ldo 64(%r30),%r30 - fldws,ma 4(%r25),%fr5 - stw %r23,-16(%r30) ; move s2_limb ... - addib,= -1,%r24,L$just_one_limb - fldws -16(%r30),%fr4 ; ... into fr4 - add %r0,%r0,%r0 ; clear carry - xmpyu %fr4,%fr5,%fr6 - fldws,ma 4(%r25),%fr7 - fstds %fr6,-16(%r30) - xmpyu %fr4,%fr7,%fr8 - ldw -12(%r30),%r19 ; least significant limb in product - ldw -16(%r30),%r28 - - fstds %fr8,-16(%r30) - addib,= -1,%r24,L$end - ldw -12(%r30),%r1 - -; Main loop - .label L$loop - ldws 0(%r26),%r29 - fldws,ma 4(%r25),%fr5 - sub %r29,%r19,%r22 - add %r22,%r19,%r0 - stws,ma %r22,4(%r26) - addc %r28,%r1,%r19 - xmpyu %fr4,%fr5,%fr6 - ldw -16(%r30),%r28 - fstds %fr6,-16(%r30) - addc %r0,%r28,%r28 - addib,<> -1,%r24,L$loop - ldw -12(%r30),%r1 - - .label L$end - ldw 0(%r26),%r29 - sub %r29,%r19,%r22 - add %r22,%r19,%r0 - stws,ma %r22,4(%r26) - addc %r28,%r1,%r19 - ldw -16(%r30),%r28 - ldws 0(%r26),%r29 - addc %r0,%r28,%r28 - sub %r29,%r19,%r22 - add %r22,%r19,%r0 - stws,ma %r22,4(%r26) - addc %r0,%r28,%r28 - bv 0(%r2) - ldo -64(%r30),%r30 - - .label L$just_one_limb - xmpyu %fr4,%fr5,%fr6 - ldw 0(%r26),%r29 - fstds %fr6,-16(%r30) - ldw -12(%r30),%r1 - ldw -16(%r30),%r28 - sub %r29,%r1,%r22 - add %r22,%r1,%r0 - stw %r22,0(%r26) - addc %r0,%r28,%r28 - bv 0(%r2) - ldo -64(%r30),%r30 - - .exit - .procend - diff --git a/mpi/hppa1.1/udiv-qrnnd.S b/mpi/hppa1.1/udiv-qrnnd.S deleted file mode 100644 index a1643d707..000000000 --- a/mpi/hppa1.1/udiv-qrnnd.S +++ /dev/null @@ -1,90 +0,0 @@ -/* HP-PA __udiv_qrnnd division support, used from longlong.h. - * This version runs fast on PA 7000 and later. - * - * Copyright (C) 1993, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -/* INPUT PARAMETERS - * rem_ptr gr26 - * n1 gr25 - * n0 gr24 - * d gr23 - */ - - .code - .label L$0000 - .word 0x43f00000 - .word 0x0 - .export __udiv_qrnnd - .label __udiv_qrnnd - .proc - .callinfo frame=64,no_calls - .entry - ldo 64(%r30),%r30 - - stws %r25,-16(0,%r30) ; n_hi - stws %r24,-12(0,%r30) ; n_lo - ldil L'L$0000,%r19 ; ' - ldo R'L$0000(%r19),%r19 ; ' - fldds -16(0,%r30),%fr5 - stws %r23,-12(0,%r30) - comib,<= 0,%r25,L$1 - fcnvxf,dbl,dbl %fr5,%fr5 - fldds 0(0,%r19),%fr4 - fadd,dbl %fr4,%fr5,%fr5 - .label L$1 - fcpy,sgl %fr0,%fr6L - fldws -12(0,%r30),%fr6R - fcnvxf,dbl,dbl %fr6,%fr4 - - fdiv,dbl %fr5,%fr4,%fr5 - - fcnvfx,dbl,dbl %fr5,%fr4 - fstws %fr4R,-16(%r30) - xmpyu %fr4R,%fr6R,%fr6 - ldws -16(%r30),%r28 - fstds %fr6,-16(0,%r30) - ldws -12(0,%r30),%r21 - ldws -16(0,%r30),%r20 - sub %r24,%r21,%r22 - subb %r25,%r20,%r19 - comib,= 0,%r19,L$2 - ldo -64(%r30),%r30 - - add %r22,%r23,%r22 - ldo -1(%r28),%r28 - .label L$2 - bv 0(%r2) - stws %r22,0(0,%r26) - - .exit - .procend - - diff --git a/mpi/i386-openbsd/README b/mpi/i386-openbsd/README deleted file mode 100644 index 0b13a7405..000000000 --- a/mpi/i386-openbsd/README +++ /dev/null @@ -1,3 +0,0 @@ -These are special i386 files for use on OpenBSD, which (at least until -version 3.1) has an older assembler that won't work with the files in -i386. diff --git a/mpi/i386-openbsd/distfiles b/mpi/i386-openbsd/distfiles deleted file mode 100644 index 88d2a30c7..000000000 --- a/mpi/i386-openbsd/distfiles +++ /dev/null @@ -1,9 +0,0 @@ -mpih-add1.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S -mpih-lshift.S -mpih-rshift.S -mpih-sub1.S -syntax.h - diff --git a/mpi/i386-openbsd/mpih-add1.S b/mpi/i386-openbsd/mpih-add1.S deleted file mode 100644 index 3b3b23c8c..000000000 --- a/mpi/i386-openbsd/mpih-add1.S +++ /dev/null @@ -1,118 +0,0 @@ -/* i80386 add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 12) - * mpi_size_t size) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_add_n) -C_SYMBOL_NAME(mpihelp_add_n:) - pushl %edi - pushl %esi - - movl 12(%esp),%edi /* res_ptr */ - movl 16(%esp),%esi /* s1_ptr */ - movl 20(%esp),%edx /* s2_ptr */ - movl 24(%esp),%ecx /* size */ - - movl %ecx,%eax - shrl $3,%ecx /* compute count for unrolled loop */ - negl %eax - andl $7,%eax /* get index where to start loop */ - jz Loop /* necessary special case for 0 */ - incl %ecx /* adjust loop count */ - shll $2,%eax /* adjustment for pointers... */ - subl %eax,%edi /* ... since they are offset ... */ - subl %eax,%esi /* ... by a constant when we ... */ - subl %eax,%edx /* ... enter the loop */ - shrl $2,%eax /* restore previous value */ -#ifdef PIC -/* Calculate start address in loop for PIC. Due to limitations in some - assemblers, Loop-L0-3 cannot be put into the leal */ - call L0 -L0: leal (%eax,%eax,8),%eax - addl (%esp),%eax - addl $(Loop-L0-3),%eax - addl $4,%esp -#else -/* Calculate start address in loop for non-PIC. */ - leal (Loop - 3)(%eax,%eax,8),%eax -#endif - jmp *%eax /* jump into loop */ - ALIGN (3) -Loop: movl (%esi),%eax - adcl (%edx),%eax - movl %eax,(%edi) - movl 4(%esi),%eax - adcl 4(%edx),%eax - movl %eax,4(%edi) - movl 8(%esi),%eax - adcl 8(%edx),%eax - movl %eax,8(%edi) - movl 12(%esi),%eax - adcl 12(%edx),%eax - movl %eax,12(%edi) - movl 16(%esi),%eax - adcl 16(%edx),%eax - movl %eax,16(%edi) - movl 20(%esi),%eax - adcl 20(%edx),%eax - movl %eax,20(%edi) - movl 24(%esi),%eax - adcl 24(%edx),%eax - movl %eax,24(%edi) - movl 28(%esi),%eax - adcl 28(%edx),%eax - movl %eax,28(%edi) - leal 32(%edi),%edi - leal 32(%esi),%esi - leal 32(%edx),%edx - decl %ecx - jnz Loop - - sbbl %eax,%eax - negl %eax - - popl %esi - popl %edi - ret - diff --git a/mpi/i386-openbsd/mpih-lshift.S b/mpi/i386-openbsd/mpih-lshift.S deleted file mode 100644 index 5e6387a4f..000000000 --- a/mpi/i386-openbsd/mpih-lshift.S +++ /dev/null @@ -1,96 +0,0 @@ -/* i80386 lshift - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_lshift) -C_SYMBOL_NAME(mpihelp_lshift:) - pushl %edi - pushl %esi - pushl %ebx - - movl 16(%esp),%edi /* res_ptr */ - movl 20(%esp),%esi /* s_ptr */ - movl 24(%esp),%edx /* size */ - movl 28(%esp),%ecx /* cnt */ - - subl $4,%esi /* adjust s_ptr */ - - movl (%esi,%edx,4),%ebx /* read most significant limb */ - xorl %eax,%eax - shldl %cl,%ebx,%eax /* compute carry limb */ - decl %edx - jz Lend - pushl %eax /* push carry limb onto stack */ - testb $1,%edx - jnz L1 /* enter loop in the middle */ - movl %ebx,%eax - - ALIGN (3) -Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */ - shldl %cl,%ebx,%eax /* compute result limb */ - movl %eax,(%edi,%edx,4) /* store it */ - decl %edx -L1: movl (%esi,%edx,4),%eax - shldl %cl,%eax,%ebx - movl %ebx,(%edi,%edx,4) - decl %edx - jnz Loop - - shll %cl,%eax /* compute least significant limb */ - movl %eax,(%edi) /* store it */ - - popl %eax /* pop carry limb */ - - popl %ebx - popl %esi - popl %edi - ret - -Lend: shll %cl,%ebx /* compute least significant limb */ - movl %ebx,(%edi) /* store it */ - - popl %ebx - popl %esi - popl %edi - ret - diff --git a/mpi/i386-openbsd/mpih-mul1.S b/mpi/i386-openbsd/mpih-mul1.S deleted file mode 100644 index cf87046f5..000000000 --- a/mpi/i386-openbsd/mpih-mul1.S +++ /dev/null @@ -1,86 +0,0 @@ -/* i80386 mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_mul_1) -C_SYMBOL_NAME(mpihelp_mul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) -Loop: - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - INSN1(mul,l ,R(s2_limb)) - INSN2(add,l ,R(eax),R(ebx)) - INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax)) - INSN2(adc,l ,R(edx),$0) - INSN2(mov,l ,R(ebx),R(edx)) - - INSN1(inc,l ,R(size)) - INSN1(jnz, ,Loop) - INSN2(mov,l ,R(eax),R(ebx)) - - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i386-openbsd/mpih-mul2.S b/mpi/i386-openbsd/mpih-mul2.S deleted file mode 100644 index f134af70e..000000000 --- a/mpi/i386-openbsd/mpih-mul2.S +++ /dev/null @@ -1,88 +0,0 @@ -/* i80386 addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) -C_SYMBOL_NAME(mpihelp_addmul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) -Loop: - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - INSN1(mul,l ,R(s2_limb)) - INSN2(add,l ,R(eax),R(ebx)) - INSN2(adc,l ,R(edx),$0) - INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax)) - INSN2(adc,l ,R(edx),$0) - INSN2(mov,l ,R(ebx),R(edx)) - - INSN1(inc,l ,R(size)) - INSN1(jnz, ,Loop) - INSN2(mov,l ,R(eax),R(ebx)) - - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i386-openbsd/mpih-mul3.S b/mpi/i386-openbsd/mpih-mul3.S deleted file mode 100644 index 2907ed039..000000000 --- a/mpi/i386-openbsd/mpih-mul3.S +++ /dev/null @@ -1,88 +0,0 @@ -/* i80386 submul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_submul_1) -C_SYMBOL_NAME(mpihelp_submul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) -Loop: - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - INSN1(mul,l ,R(s2_limb)) - INSN2(add,l ,R(eax),R(ebx)) - INSN2(adc,l ,R(edx),$0) - INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax)) - INSN2(adc,l ,R(edx),$0) - INSN2(mov,l ,R(ebx),R(edx)) - - INSN1(inc,l ,R(size)) - INSN1(jnz, ,Loop) - INSN2(mov,l ,R(eax),R(ebx)) - - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i386-openbsd/mpih-rshift.S b/mpi/i386-openbsd/mpih-rshift.S deleted file mode 100644 index 9718204c7..000000000 --- a/mpi/i386-openbsd/mpih-rshift.S +++ /dev/null @@ -1,99 +0,0 @@ -/* i80386 rshift - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_rshift) -C_SYMBOL_NAME(mpihelp_rshift:) - pushl %edi - pushl %esi - pushl %ebx - - movl 16(%esp),%edi /* wp */ - movl 20(%esp),%esi /* up */ - movl 24(%esp),%edx /* usize */ - movl 28(%esp),%ecx /* cnt */ - - leal -4(%edi,%edx,4),%edi - leal (%esi,%edx,4),%esi - negl %edx - - movl (%esi,%edx,4),%ebx /* read least significant limb */ - xorl %eax,%eax - shrdl %cl,%ebx,%eax /* compute carry limb */ - incl %edx - jz Lend2 - pushl %eax /* push carry limb onto stack */ - testb $1,%edx - jnz L2 /* enter loop in the middle */ - movl %ebx,%eax - - ALIGN (3) -Loop2: movl (%esi,%edx,4),%ebx /* load next higher limb */ - shrdl %cl,%ebx,%eax /* compute result limb */ - movl %eax,(%edi,%edx,4) /* store it */ - incl %edx -L2: movl (%esi,%edx,4),%eax - shrdl %cl,%eax,%ebx - movl %ebx,(%edi,%edx,4) - incl %edx - jnz Loop2 - - shrl %cl,%eax /* compute most significant limb */ - movl %eax,(%edi) /* store it */ - - popl %eax /* pop carry limb */ - - popl %ebx - popl %esi - popl %edi - ret - -Lend2: shrl %cl,%ebx /* compute most significant limb */ - movl %ebx,(%edi) /* store it */ - - popl %ebx - popl %esi - popl %edi - ret - diff --git a/mpi/i386-openbsd/mpih-sub1.S b/mpi/i386-openbsd/mpih-sub1.S deleted file mode 100644 index 169c53950..000000000 --- a/mpi/i386-openbsd/mpih-sub1.S +++ /dev/null @@ -1,119 +0,0 @@ -/* i80386 sub_n -- Sub two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 12) - * mpi_size_t size) (sp + 16) - */ - - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_sub_n) -C_SYMBOL_NAME(mpihelp_sub_n:) - pushl %edi - pushl %esi - - movl 12(%esp),%edi /* res_ptr */ - movl 16(%esp),%esi /* s1_ptr */ - movl 20(%esp),%edx /* s2_ptr */ - movl 24(%esp),%ecx /* size */ - - movl %ecx,%eax - shrl $3,%ecx /* compute count for unrolled loop */ - negl %eax - andl $7,%eax /* get index where to start loop */ - jz Loop /* necessary special case for 0 */ - incl %ecx /* adjust loop count */ - shll $2,%eax /* adjustment for pointers... */ - subl %eax,%edi /* ... since they are offset ... */ - subl %eax,%esi /* ... by a constant when we ... */ - subl %eax,%edx /* ... enter the loop */ - shrl $2,%eax /* restore previous value */ -#ifdef PIC -/* Calculate start address in loop for PIC. Due to limitations in some - assemblers, Loop-L0-3 cannot be put into the leal */ - call L0 -L0: leal (%eax,%eax,8),%eax - addl (%esp),%eax - addl $(Loop-L0-3),%eax - addl $4,%esp -#else -/* Calculate start address in loop for non-PIC. */ - leal (Loop - 3)(%eax,%eax,8),%eax -#endif - jmp *%eax /* jump into loop */ - ALIGN (3) -Loop: movl (%esi),%eax - sbbl (%edx),%eax - movl %eax,(%edi) - movl 4(%esi),%eax - sbbl 4(%edx),%eax - movl %eax,4(%edi) - movl 8(%esi),%eax - sbbl 8(%edx),%eax - movl %eax,8(%edi) - movl 12(%esi),%eax - sbbl 12(%edx),%eax - movl %eax,12(%edi) - movl 16(%esi),%eax - sbbl 16(%edx),%eax - movl %eax,16(%edi) - movl 20(%esi),%eax - sbbl 20(%edx),%eax - movl %eax,20(%edi) - movl 24(%esi),%eax - sbbl 24(%edx),%eax - movl %eax,24(%edi) - movl 28(%esi),%eax - sbbl 28(%edx),%eax - movl %eax,28(%edi) - leal 32(%edi),%edi - leal 32(%esi),%esi - leal 32(%edx),%edx - decl %ecx - jnz Loop - - sbbl %eax,%eax - negl %eax - - popl %esi - popl %edi - ret - diff --git a/mpi/i386-openbsd/syntax.h b/mpi/i386-openbsd/syntax.h deleted file mode 100644 index 5a2c7b232..000000000 --- a/mpi/i386-openbsd/syntax.h +++ /dev/null @@ -1,68 +0,0 @@ -/* syntax.h -- Definitions for x86 syntax variations. - * - * Copyright (C) 1992, 1994, 1995, 1998, - * 2001 Free Software Foundation, Inc. - * - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#undef ALIGN - -#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX) -#define R(r) %r -#define MEM(base)(base) -#define MEM_DISP(base,displacement)displacement(R(base)) -#define MEM_INDEX(base,index,size)(R(base),R(index),size) -#ifdef __STDC__ -#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst -#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst -#else -#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst -#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst -#endif -#define TEXT .text -#if defined (BSD_SYNTAX) -#define ALIGN(log) .align log -#endif -#if defined (ELF_SYNTAX) -#define ALIGN(log) .align 1<<(log) -#endif -#define GLOBL .globl -#endif - -#ifdef INTEL_SYNTAX -#define R(r) r -#define MEM(base)[base] -#define MEM_DISP(base,displacement)[base+(displacement)] -#define MEM_INDEX(base,index,size)[base+index*size] -#define INSN1(mnemonic,size_suffix,dst)mnemonic dst -#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src -#define TEXT .text -#define ALIGN(log) .align log -#define GLOBL .globl -#endif - -#ifdef X86_BROKEN_ALIGN -#undef ALIGN -#define ALIGN(log) .align log,0x90 -#endif diff --git a/mpi/i386/distfiles b/mpi/i386/distfiles deleted file mode 100644 index 88d2a30c7..000000000 --- a/mpi/i386/distfiles +++ /dev/null @@ -1,9 +0,0 @@ -mpih-add1.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S -mpih-lshift.S -mpih-rshift.S -mpih-sub1.S -syntax.h - diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S deleted file mode 100644 index da7e7f8b3..000000000 --- a/mpi/i386/mpih-add1.S +++ /dev/null @@ -1,118 +0,0 @@ -/* i80386 add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1998, - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 12) - * mpi_size_t size) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_add_n) -C_SYMBOL_NAME(mpihelp_add_n:) - pushl %edi - pushl %esi - - movl 12(%esp),%edi /* res_ptr */ - movl 16(%esp),%esi /* s1_ptr */ - movl 20(%esp),%edx /* s2_ptr */ - movl 24(%esp),%ecx /* size */ - - movl %ecx,%eax - shrl $3,%ecx /* compute count for unrolled loop */ - negl %eax - andl $7,%eax /* get index where to start loop */ - jz Loop /* necessary special case for 0 */ - incl %ecx /* adjust loop count */ - shll $2,%eax /* adjustment for pointers... */ - subl %eax,%edi /* ... since they are offset ... */ - subl %eax,%esi /* ... by a constant when we ... */ - subl %eax,%edx /* ... enter the loop */ - shrl $2,%eax /* restore previous value */ -#ifdef PIC -/* Calculate start address in loop for PIC. Due to limitations in some - assemblers, Loop-L0-3 cannot be put into the leal */ - call L0 -L0: leal (%eax,%eax,8),%eax - addl (%esp),%eax - addl $(Loop-L0-3),%eax - addl $4,%esp -#else -/* Calculate start address in loop for non-PIC. */ - leal Loop-3(%eax,%eax,8),%eax -#endif - jmp *%eax /* jump into loop */ - ALIGN (3) -Loop: movl (%esi),%eax - adcl (%edx),%eax - movl %eax,(%edi) - movl 4(%esi),%eax - adcl 4(%edx),%eax - movl %eax,4(%edi) - movl 8(%esi),%eax - adcl 8(%edx),%eax - movl %eax,8(%edi) - movl 12(%esi),%eax - adcl 12(%edx),%eax - movl %eax,12(%edi) - movl 16(%esi),%eax - adcl 16(%edx),%eax - movl %eax,16(%edi) - movl 20(%esi),%eax - adcl 20(%edx),%eax - movl %eax,20(%edi) - movl 24(%esi),%eax - adcl 24(%edx),%eax - movl %eax,24(%edi) - movl 28(%esi),%eax - adcl 28(%edx),%eax - movl %eax,28(%edi) - leal 32(%edi),%edi - leal 32(%esi),%esi - leal 32(%edx),%edx - decl %ecx - jnz Loop - - sbbl %eax,%eax - negl %eax - - popl %esi - popl %edi - ret - diff --git a/mpi/i386/mpih-lshift.S b/mpi/i386/mpih-lshift.S deleted file mode 100644 index a7dad2c96..000000000 --- a/mpi/i386/mpih-lshift.S +++ /dev/null @@ -1,96 +0,0 @@ -/* i80386 lshift - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_lshift) -C_SYMBOL_NAME(mpihelp_lshift:) - pushl %edi - pushl %esi - pushl %ebx - - movl 16(%esp),%edi /* res_ptr */ - movl 20(%esp),%esi /* s_ptr */ - movl 24(%esp),%edx /* size */ - movl 28(%esp),%ecx /* cnt */ - - subl $4,%esi /* adjust s_ptr */ - - movl (%esi,%edx,4),%ebx /* read most significant limb */ - xorl %eax,%eax - shldl %ebx,%eax /* compute carry limb */ - decl %edx - jz Lend - pushl %eax /* push carry limb onto stack */ - testb $1,%dl - jnz L1 /* enter loop in the middle */ - movl %ebx,%eax - - ALIGN (3) -Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */ - shldl %ebx,%eax /* compute result limb */ - movl %eax,(%edi,%edx,4) /* store it */ - decl %edx -L1: movl (%esi,%edx,4),%eax - shldl %eax,%ebx - movl %ebx,(%edi,%edx,4) - decl %edx - jnz Loop - - shll %cl,%eax /* compute least significant limb */ - movl %eax,(%edi) /* store it */ - - popl %eax /* pop carry limb */ - - popl %ebx - popl %esi - popl %edi - ret - -Lend: shll %cl,%ebx /* compute least significant limb */ - movl %ebx,(%edi) /* store it */ - - popl %ebx - popl %esi - popl %edi - ret - diff --git a/mpi/i386/mpih-mul1.S b/mpi/i386/mpih-mul1.S deleted file mode 100644 index cf87046f5..000000000 --- a/mpi/i386/mpih-mul1.S +++ /dev/null @@ -1,86 +0,0 @@ -/* i80386 mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_mul_1) -C_SYMBOL_NAME(mpihelp_mul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) -Loop: - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - INSN1(mul,l ,R(s2_limb)) - INSN2(add,l ,R(eax),R(ebx)) - INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax)) - INSN2(adc,l ,R(edx),$0) - INSN2(mov,l ,R(ebx),R(edx)) - - INSN1(inc,l ,R(size)) - INSN1(jnz, ,Loop) - INSN2(mov,l ,R(eax),R(ebx)) - - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i386/mpih-mul2.S b/mpi/i386/mpih-mul2.S deleted file mode 100644 index f134af70e..000000000 --- a/mpi/i386/mpih-mul2.S +++ /dev/null @@ -1,88 +0,0 @@ -/* i80386 addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) -C_SYMBOL_NAME(mpihelp_addmul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) -Loop: - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - INSN1(mul,l ,R(s2_limb)) - INSN2(add,l ,R(eax),R(ebx)) - INSN2(adc,l ,R(edx),$0) - INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax)) - INSN2(adc,l ,R(edx),$0) - INSN2(mov,l ,R(ebx),R(edx)) - - INSN1(inc,l ,R(size)) - INSN1(jnz, ,Loop) - INSN2(mov,l ,R(eax),R(ebx)) - - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i386/mpih-mul3.S b/mpi/i386/mpih-mul3.S deleted file mode 100644 index 2907ed039..000000000 --- a/mpi/i386/mpih-mul3.S +++ /dev/null @@ -1,88 +0,0 @@ -/* i80386 submul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_submul_1) -C_SYMBOL_NAME(mpihelp_submul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) -Loop: - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - INSN1(mul,l ,R(s2_limb)) - INSN2(add,l ,R(eax),R(ebx)) - INSN2(adc,l ,R(edx),$0) - INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax)) - INSN2(adc,l ,R(edx),$0) - INSN2(mov,l ,R(ebx),R(edx)) - - INSN1(inc,l ,R(size)) - INSN1(jnz, ,Loop) - INSN2(mov,l ,R(eax),R(ebx)) - - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i386/mpih-rshift.S b/mpi/i386/mpih-rshift.S deleted file mode 100644 index 4886a98ca..000000000 --- a/mpi/i386/mpih-rshift.S +++ /dev/null @@ -1,99 +0,0 @@ -/* i80386 rshift - * - * Copyright (C) 1992, 1994, 1998, - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_rshift) -C_SYMBOL_NAME(mpihelp_rshift:) - pushl %edi - pushl %esi - pushl %ebx - - movl 16(%esp),%edi /* wp */ - movl 20(%esp),%esi /* up */ - movl 24(%esp),%edx /* usize */ - movl 28(%esp),%ecx /* cnt */ - - leal -4(%edi,%edx,4),%edi - leal (%esi,%edx,4),%esi - negl %edx - - movl (%esi,%edx,4),%ebx /* read least significant limb */ - xorl %eax,%eax - shrdl %ebx,%eax /* compute carry limb */ - incl %edx - jz Lend2 - pushl %eax /* push carry limb onto stack */ - testb $1,%dl - jnz L2 /* enter loop in the middle */ - movl %ebx,%eax - - ALIGN (3) -Loop2: movl (%esi,%edx,4),%ebx /* load next higher limb */ - shrdl %ebx,%eax /* compute result limb */ - movl %eax,(%edi,%edx,4) /* store it */ - incl %edx -L2: movl (%esi,%edx,4),%eax - shrdl %eax,%ebx - movl %ebx,(%edi,%edx,4) - incl %edx - jnz Loop2 - - shrl %cl,%eax /* compute most significant limb */ - movl %eax,(%edi) /* store it */ - - popl %eax /* pop carry limb */ - - popl %ebx - popl %esi - popl %edi - ret - -Lend2: shrl %cl,%ebx /* compute most significant limb */ - movl %ebx,(%edi) /* store it */ - - popl %ebx - popl %esi - popl %edi - ret - diff --git a/mpi/i386/mpih-sub1.S b/mpi/i386/mpih-sub1.S deleted file mode 100644 index 2339334fe..000000000 --- a/mpi/i386/mpih-sub1.S +++ /dev/null @@ -1,119 +0,0 @@ -/* i80386 sub_n -- Sub two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1998, - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 12) - * mpi_size_t size) (sp + 16) - */ - - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_sub_n) -C_SYMBOL_NAME(mpihelp_sub_n:) - pushl %edi - pushl %esi - - movl 12(%esp),%edi /* res_ptr */ - movl 16(%esp),%esi /* s1_ptr */ - movl 20(%esp),%edx /* s2_ptr */ - movl 24(%esp),%ecx /* size */ - - movl %ecx,%eax - shrl $3,%ecx /* compute count for unrolled loop */ - negl %eax - andl $7,%eax /* get index where to start loop */ - jz Loop /* necessary special case for 0 */ - incl %ecx /* adjust loop count */ - shll $2,%eax /* adjustment for pointers... */ - subl %eax,%edi /* ... since they are offset ... */ - subl %eax,%esi /* ... by a constant when we ... */ - subl %eax,%edx /* ... enter the loop */ - shrl $2,%eax /* restore previous value */ -#ifdef PIC -/* Calculate start address in loop for PIC. Due to limitations in some - assemblers, Loop-L0-3 cannot be put into the leal */ - call L0 -L0: leal (%eax,%eax,8),%eax - addl (%esp),%eax - addl $(Loop-L0-3),%eax - addl $4,%esp -#else -/* Calculate start address in loop for non-PIC. */ - leal Loop-3(%eax,%eax,8),%eax -#endif - jmp *%eax /* jump into loop */ - ALIGN (3) -Loop: movl (%esi),%eax - sbbl (%edx),%eax - movl %eax,(%edi) - movl 4(%esi),%eax - sbbl 4(%edx),%eax - movl %eax,4(%edi) - movl 8(%esi),%eax - sbbl 8(%edx),%eax - movl %eax,8(%edi) - movl 12(%esi),%eax - sbbl 12(%edx),%eax - movl %eax,12(%edi) - movl 16(%esi),%eax - sbbl 16(%edx),%eax - movl %eax,16(%edi) - movl 20(%esi),%eax - sbbl 20(%edx),%eax - movl %eax,20(%edi) - movl 24(%esi),%eax - sbbl 24(%edx),%eax - movl %eax,24(%edi) - movl 28(%esi),%eax - sbbl 28(%edx),%eax - movl %eax,28(%edi) - leal 32(%edi),%edi - leal 32(%esi),%esi - leal 32(%edx),%edx - decl %ecx - jnz Loop - - sbbl %eax,%eax - negl %eax - - popl %esi - popl %edi - ret - diff --git a/mpi/i386/syntax.h b/mpi/i386/syntax.h deleted file mode 100644 index 035c01960..000000000 --- a/mpi/i386/syntax.h +++ /dev/null @@ -1,68 +0,0 @@ -/* syntax.h -- Definitions for x86 syntax variations. - * - * Copyright (C) 1992, 1994, 1995, 1998, - * 2001 Free Software Foundation, Inc. - * - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#undef ALIGN - -#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX) -#define R(r) %r -#define MEM(base)(base) -#define MEM_DISP(base,displacement)displacement(R(base)) -#define MEM_INDEX(base,index,size)(R(base),R(index),size) -#ifdef __STDC__ -#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst -#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst -#else -#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst -#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst -#endif -#define TEXT .text -#if defined (BSD_SYNTAX) -#define ALIGN(log) .align log -#endif -#if defined (ELF_SYNTAX) -#define ALIGN(log) .align 1< 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1996, 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 - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 12) - * mpi_size_t size) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_add_n) -C_SYMBOL_NAME(mpihelp_add_n:) - pushl %edi - pushl %esi - pushl %ebx - pushl %ebp - - movl 20(%esp),%edi /* res_ptr */ - movl 24(%esp),%esi /* s1_ptr */ - movl 28(%esp),%ebp /* s2_ptr */ - movl 32(%esp),%ecx /* size */ - - movl (%ebp),%ebx - - decl %ecx - movl %ecx,%edx - shrl $3,%ecx - andl $7,%edx - testl %ecx,%ecx /* zero carry flag */ - jz Lend - pushl %edx - - ALIGN (3) -Loop: movl 28(%edi),%eax /* fetch destination cache line */ - leal 32(%edi),%edi - -L1: movl (%esi),%eax - movl 4(%esi),%edx - adcl %ebx,%eax - movl 4(%ebp),%ebx - adcl %ebx,%edx - movl 8(%ebp),%ebx - movl %eax,-32(%edi) - movl %edx,-28(%edi) - -L2: movl 8(%esi),%eax - movl 12(%esi),%edx - adcl %ebx,%eax - movl 12(%ebp),%ebx - adcl %ebx,%edx - movl 16(%ebp),%ebx - movl %eax,-24(%edi) - movl %edx,-20(%edi) - -L3: movl 16(%esi),%eax - movl 20(%esi),%edx - adcl %ebx,%eax - movl 20(%ebp),%ebx - adcl %ebx,%edx - movl 24(%ebp),%ebx - movl %eax,-16(%edi) - movl %edx,-12(%edi) - -L4: movl 24(%esi),%eax - movl 28(%esi),%edx - adcl %ebx,%eax - movl 28(%ebp),%ebx - adcl %ebx,%edx - movl 32(%ebp),%ebx - movl %eax,-8(%edi) - movl %edx,-4(%edi) - - leal 32(%esi),%esi - leal 32(%ebp),%ebp - decl %ecx - jnz Loop - - popl %edx -Lend: - decl %edx /* test %edx w/o clobbering carry */ - js Lend2 - incl %edx -Loop2: - leal 4(%edi),%edi - movl (%esi),%eax - adcl %ebx,%eax - movl 4(%ebp),%ebx - movl %eax,-4(%edi) - leal 4(%esi),%esi - leal 4(%ebp),%ebp - decl %edx - jnz Loop2 -Lend2: - movl (%esi),%eax - adcl %ebx,%eax - movl %eax,(%edi) - - sbbl %eax,%eax - negl %eax - - popl %ebp - popl %ebx - popl %esi - popl %edi - ret - - diff --git a/mpi/i586/mpih-lshift.S b/mpi/i586/mpih-lshift.S deleted file mode 100644 index ed040912d..000000000 --- a/mpi/i586/mpih-lshift.S +++ /dev/null @@ -1,231 +0,0 @@ -/* i80586 lshift - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_lshift) -C_SYMBOL_NAME(mpihelp_lshift:) - - pushl %edi - pushl %esi - pushl %ebx - pushl %ebp - - movl 20(%esp),%edi /* res_ptr */ - movl 24(%esp),%esi /* s_ptr */ - movl 28(%esp),%ebp /* size */ - movl 32(%esp),%ecx /* cnt */ - -/* We can use faster code for shift-by-1 under certain conditions. */ - cmp $1,%ecx - jne Lnormal - leal 4(%esi),%eax - cmpl %edi,%eax - jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */ - leal (%esi,%ebp,4),%eax - cmpl %eax,%edi - jnc Lspecial /* jump if res_ptr >= s_ptr + size */ - -Lnormal: - leal -4(%edi,%ebp,4),%edi - leal -4(%esi,%ebp,4),%esi - - movl (%esi),%edx - subl $4,%esi - xorl %eax,%eax - shldl %cl,%edx,%eax /* compute carry limb */ - pushl %eax /* push carry limb onto stack */ - - decl %ebp - pushl %ebp - shrl $3,%ebp - jz Lend - - movl (%edi),%eax /* fetch destination cache line */ - - ALIGN (2) -Loop: movl -28(%edi),%eax /* fetch destination cache line */ - movl %edx,%ebx - - movl (%esi),%eax - movl -4(%esi),%edx - shldl %cl,%eax,%ebx - shldl %cl,%edx,%eax - movl %ebx,(%edi) - movl %eax,-4(%edi) - - movl -8(%esi),%ebx - movl -12(%esi),%eax - shldl %cl,%ebx,%edx - shldl %cl,%eax,%ebx - movl %edx,-8(%edi) - movl %ebx,-12(%edi) - - movl -16(%esi),%edx - movl -20(%esi),%ebx - shldl %cl,%edx,%eax - shldl %cl,%ebx,%edx - movl %eax,-16(%edi) - movl %edx,-20(%edi) - - movl -24(%esi),%eax - movl -28(%esi),%edx - shldl %cl,%eax,%ebx - shldl %cl,%edx,%eax - movl %ebx,-24(%edi) - movl %eax,-28(%edi) - - subl $32,%esi - subl $32,%edi - decl %ebp - jnz Loop - -Lend: popl %ebp - andl $7,%ebp - jz Lend2 -Loop2: movl (%esi),%eax - shldl %cl,%eax,%edx - movl %edx,(%edi) - movl %eax,%edx - subl $4,%esi - subl $4,%edi - decl %ebp - jnz Loop2 - -Lend2: shll %cl,%edx /* compute least significant limb */ - movl %edx,(%edi) /* store it */ - - popl %eax /* pop carry limb */ - - popl %ebp - popl %ebx - popl %esi - popl %edi - ret - -/* We loop from least significant end of the arrays, which is only - permissable if the source and destination don't overlap, since the - function is documented to work for overlapping source and destination. -*/ - -Lspecial: - movl (%esi),%edx - addl $4,%esi - - decl %ebp - pushl %ebp - shrl $3,%ebp - - addl %edx,%edx - incl %ebp - decl %ebp - jz LLend - - movl (%edi),%eax /* fetch destination cache line */ - - ALIGN (2) -LLoop: movl 28(%edi),%eax /* fetch destination cache line */ - movl %edx,%ebx - - movl (%esi),%eax - movl 4(%esi),%edx - adcl %eax,%eax - movl %ebx,(%edi) - adcl %edx,%edx - movl %eax,4(%edi) - - movl 8(%esi),%ebx - movl 12(%esi),%eax - adcl %ebx,%ebx - movl %edx,8(%edi) - adcl %eax,%eax - movl %ebx,12(%edi) - - movl 16(%esi),%edx - movl 20(%esi),%ebx - adcl %edx,%edx - movl %eax,16(%edi) - adcl %ebx,%ebx - movl %edx,20(%edi) - - movl 24(%esi),%eax - movl 28(%esi),%edx - adcl %eax,%eax - movl %ebx,24(%edi) - adcl %edx,%edx - movl %eax,28(%edi) - - leal 32(%esi),%esi /* use leal not to clobber carry */ - leal 32(%edi),%edi - decl %ebp - jnz LLoop - -LLend: popl %ebp - sbbl %eax,%eax /* save carry in %eax */ - andl $7,%ebp - jz LLend2 - addl %eax,%eax /* restore carry from eax */ -LLoop2: movl %edx,%ebx - movl (%esi),%edx - adcl %edx,%edx - movl %ebx,(%edi) - - leal 4(%esi),%esi /* use leal not to clobber carry */ - leal 4(%edi),%edi - decl %ebp - jnz LLoop2 - - jmp LL1 -LLend2: addl %eax,%eax /* restore carry from eax */ -LL1: movl %edx,(%edi) /* store last limb */ - - sbbl %eax,%eax - negl %eax - - popl %ebp - popl %ebx - popl %esi - popl %edi - ret - - diff --git a/mpi/i586/mpih-mul1.S b/mpi/i586/mpih-mul1.S deleted file mode 100644 index 42bcde6bd..000000000 --- a/mpi/i586/mpih-mul1.S +++ /dev/null @@ -1,91 +0,0 @@ -/* i80586 mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_mul_1) -C_SYMBOL_NAME(mpihelp_mul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) - -Loop: INSN2(adc,l ,R(ebx),$0) - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - - INSN1(mul,l ,R(s2_limb)) - - INSN2(add,l ,R(ebx),R(eax)) - - INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) - INSN1(inc,l ,R(size)) - - INSN2(mov,l ,R(ebx),R(edx)) - INSN1(jnz, ,Loop) - - INSN2(adc,l ,R(ebx),$0) - INSN2(mov,l ,R(eax),R(ebx)) - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i586/mpih-mul2.S b/mpi/i586/mpih-mul2.S deleted file mode 100644 index 54c5df96b..000000000 --- a/mpi/i586/mpih-mul2.S +++ /dev/null @@ -1,95 +0,0 @@ -/* i80586 addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) -C_SYMBOL_NAME(mpihelp_addmul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) - -Loop: INSN2(adc,l ,R(ebx),$0) - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - - INSN1(mul,l ,R(s2_limb)) - - INSN2(add,l ,R(eax),R(ebx)) - INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) - - INSN2(adc,l ,R(edx),$0) - INSN2(add,l ,R(ebx),R(eax)) - - INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) - INSN1(inc,l ,R(size)) - - INSN2(mov,l ,R(ebx),R(edx)) - INSN1(jnz, ,Loop) - - INSN2(adc,l ,R(ebx),$0) - INSN2(mov,l ,R(eax),R(ebx)) - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i586/mpih-mul3.S b/mpi/i586/mpih-mul3.S deleted file mode 100644 index 0d61ff267..000000000 --- a/mpi/i586/mpih-mul3.S +++ /dev/null @@ -1,95 +0,0 @@ -/* i80586 submul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - -#define res_ptr edi -#define s1_ptr esi -#define size ecx -#define s2_limb ebp - - TEXT - ALIGN (3) - GLOBL C_SYMBOL_NAME(mpihelp_submul_1) -C_SYMBOL_NAME(mpihelp_submul_1:) - - INSN1(push,l ,R(edi)) - INSN1(push,l ,R(esi)) - INSN1(push,l ,R(ebx)) - INSN1(push,l ,R(ebp)) - - INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) - INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) - INSN2(mov,l ,R(size),MEM_DISP(esp,28)) - INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) - - INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) - INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) - INSN1(neg,l ,R(size)) - INSN2(xor,l ,R(ebx),R(ebx)) - ALIGN (3) - -Loop: INSN2(adc,l ,R(ebx),$0) - INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) - - INSN1(mul,l ,R(s2_limb)) - - INSN2(add,l ,R(eax),R(ebx)) - INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) - - INSN2(adc,l ,R(edx),$0) - INSN2(sub,l ,R(ebx),R(eax)) - - INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) - INSN1(inc,l ,R(size)) - - INSN2(mov,l ,R(ebx),R(edx)) - INSN1(jnz, ,Loop) - - INSN2(adc,l ,R(ebx),$0) - INSN2(mov,l ,R(eax),R(ebx)) - INSN1(pop,l ,R(ebp)) - INSN1(pop,l ,R(ebx)) - INSN1(pop,l ,R(esi)) - INSN1(pop,l ,R(edi)) - ret - diff --git a/mpi/i586/mpih-rshift.S b/mpi/i586/mpih-rshift.S deleted file mode 100644 index 2e3316216..000000000 --- a/mpi/i586/mpih-rshift.S +++ /dev/null @@ -1,230 +0,0 @@ -/* i80586 rshift - * - * Copyright (C) 1992, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_rshift) -C_SYMBOL_NAME(mpihelp_rshift:) - pushl %edi - pushl %esi - pushl %ebx - pushl %ebp - - movl 20(%esp),%edi /* res_ptr */ - movl 24(%esp),%esi /* s_ptr */ - movl 28(%esp),%ebp /* size */ - movl 32(%esp),%ecx /* cnt */ - -/* We can use faster code for shift-by-1 under certain conditions. */ - cmp $1,%ecx - jne Rnormal - leal 4(%edi),%eax - cmpl %esi,%eax - jnc Rspecial /* jump if res_ptr + 1 >= s_ptr */ - leal (%edi,%ebp,4),%eax - cmpl %eax,%esi - jnc Rspecial /* jump if s_ptr >= res_ptr + size */ - -Rnormal: - movl (%esi),%edx - addl $4,%esi - xorl %eax,%eax - shrdl %cl,%edx,%eax /* compute carry limb */ - pushl %eax /* push carry limb onto stack */ - - decl %ebp - pushl %ebp - shrl $3,%ebp - jz Rend - - movl (%edi),%eax /* fetch destination cache line */ - - ALIGN (2) -Roop: movl 28(%edi),%eax /* fetch destination cache line */ - movl %edx,%ebx - - movl (%esi),%eax - movl 4(%esi),%edx - shrdl %cl,%eax,%ebx - shrdl %cl,%edx,%eax - movl %ebx,(%edi) - movl %eax,4(%edi) - - movl 8(%esi),%ebx - movl 12(%esi),%eax - shrdl %cl,%ebx,%edx - shrdl %cl,%eax,%ebx - movl %edx,8(%edi) - movl %ebx,12(%edi) - - movl 16(%esi),%edx - movl 20(%esi),%ebx - shrdl %cl,%edx,%eax - shrdl %cl,%ebx,%edx - movl %eax,16(%edi) - movl %edx,20(%edi) - - movl 24(%esi),%eax - movl 28(%esi),%edx - shrdl %cl,%eax,%ebx - shrdl %cl,%edx,%eax - movl %ebx,24(%edi) - movl %eax,28(%edi) - - addl $32,%esi - addl $32,%edi - decl %ebp - jnz Roop - -Rend: popl %ebp - andl $7,%ebp - jz Rend2 -Roop2: movl (%esi),%eax - shrdl %cl,%eax,%edx /* compute result limb */ - movl %edx,(%edi) - movl %eax,%edx - addl $4,%esi - addl $4,%edi - decl %ebp - jnz Roop2 - -Rend2: shrl %cl,%edx /* compute most significant limb */ - movl %edx,(%edi) /* store it */ - - popl %eax /* pop carry limb */ - - popl %ebp - popl %ebx - popl %esi - popl %edi - ret - -/* We loop from least significant end of the arrays, which is only - permissable if the source and destination don't overlap, since the - function is documented to work for overlapping source and destination. -*/ - -Rspecial: - leal -4(%edi,%ebp,4),%edi - leal -4(%esi,%ebp,4),%esi - - movl (%esi),%edx - subl $4,%esi - - decl %ebp - pushl %ebp - shrl $3,%ebp - - shrl $1,%edx - incl %ebp - decl %ebp - jz RLend - - movl (%edi),%eax /* fetch destination cache line */ - - ALIGN (2) -RLoop: movl -28(%edi),%eax /* fetch destination cache line */ - movl %edx,%ebx - - movl (%esi),%eax - movl -4(%esi),%edx - rcrl $1,%eax - movl %ebx,(%edi) - rcrl $1,%edx - movl %eax,-4(%edi) - - movl -8(%esi),%ebx - movl -12(%esi),%eax - rcrl $1,%ebx - movl %edx,-8(%edi) - rcrl $1,%eax - movl %ebx,-12(%edi) - - movl -16(%esi),%edx - movl -20(%esi),%ebx - rcrl $1,%edx - movl %eax,-16(%edi) - rcrl $1,%ebx - movl %edx,-20(%edi) - - movl -24(%esi),%eax - movl -28(%esi),%edx - rcrl $1,%eax - movl %ebx,-24(%edi) - rcrl $1,%edx - movl %eax,-28(%edi) - - leal -32(%esi),%esi /* use leal not to clobber carry */ - leal -32(%edi),%edi - decl %ebp - jnz RLoop - -RLend: popl %ebp - sbbl %eax,%eax /* save carry in %eax */ - andl $7,%ebp - jz RLend2 - addl %eax,%eax /* restore carry from eax */ -RLoop2: movl %edx,%ebx - movl (%esi),%edx - rcrl $1,%edx - movl %ebx,(%edi) - - leal -4(%esi),%esi /* use leal not to clobber carry */ - leal -4(%edi),%edi - decl %ebp - jnz RLoop2 - - jmp RL1 -RLend2: addl %eax,%eax /* restore carry from eax */ -RL1: movl %edx,(%edi) /* store last limb */ - - movl $0,%eax - rcrl $1,%eax - - popl %ebp - popl %ebx - popl %esi - popl %edi - ret - diff --git a/mpi/i586/mpih-sub1.S b/mpi/i586/mpih-sub1.S deleted file mode 100644 index a54be0e91..000000000 --- a/mpi/i586/mpih-sub1.S +++ /dev/null @@ -1,144 +0,0 @@ -/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 12) - * mpi_size_t size) (sp + 16) - */ - - -.text - ALIGN (3) - .globl C_SYMBOL_NAME(mpihelp_sub_n) -C_SYMBOL_NAME(mpihelp_sub_n:) - - pushl %edi - pushl %esi - pushl %ebx - pushl %ebp - - movl 20(%esp),%edi /* res_ptr */ - movl 24(%esp),%esi /* s1_ptr */ - movl 28(%esp),%ebp /* s2_ptr */ - movl 32(%esp),%ecx /* size */ - - movl (%ebp),%ebx - - decl %ecx - movl %ecx,%edx - shrl $3,%ecx - andl $7,%edx - testl %ecx,%ecx /* zero carry flag */ - jz Lend - pushl %edx - - ALIGN (3) -Loop: movl 28(%edi),%eax /* fetch destination cache line */ - leal 32(%edi),%edi - -L1: movl (%esi),%eax - movl 4(%esi),%edx - sbbl %ebx,%eax - movl 4(%ebp),%ebx - sbbl %ebx,%edx - movl 8(%ebp),%ebx - movl %eax,-32(%edi) - movl %edx,-28(%edi) - -L2: movl 8(%esi),%eax - movl 12(%esi),%edx - sbbl %ebx,%eax - movl 12(%ebp),%ebx - sbbl %ebx,%edx - movl 16(%ebp),%ebx - movl %eax,-24(%edi) - movl %edx,-20(%edi) - -L3: movl 16(%esi),%eax - movl 20(%esi),%edx - sbbl %ebx,%eax - movl 20(%ebp),%ebx - sbbl %ebx,%edx - movl 24(%ebp),%ebx - movl %eax,-16(%edi) - movl %edx,-12(%edi) - -L4: movl 24(%esi),%eax - movl 28(%esi),%edx - sbbl %ebx,%eax - movl 28(%ebp),%ebx - sbbl %ebx,%edx - movl 32(%ebp),%ebx - movl %eax,-8(%edi) - movl %edx,-4(%edi) - - leal 32(%esi),%esi - leal 32(%ebp),%ebp - decl %ecx - jnz Loop - - popl %edx -Lend: - decl %edx /* test %edx w/o clobbering carry */ - js Lend2 - incl %edx -Loop2: - leal 4(%edi),%edi - movl (%esi),%eax - sbbl %ebx,%eax - movl 4(%ebp),%ebx - movl %eax,-4(%edi) - leal 4(%esi),%esi - leal 4(%ebp),%ebp - decl %edx - jnz Loop2 -Lend2: - movl (%esi),%eax - sbbl %ebx,%eax - movl %eax,(%edi) - - sbbl %eax,%eax - negl %eax - - popl %ebp - popl %ebx - popl %esi - popl %edi - ret - diff --git a/mpi/longlong.h b/mpi/longlong.h deleted file mode 100644 index 2976a0e22..000000000 --- a/mpi/longlong.h +++ /dev/null @@ -1,1499 +0,0 @@ -/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. - Note: I added some stuff for use with gnupg - -Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998, - 2000, 2001, 2002 Free Software Foundation, Inc. - -This file 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. - -This file 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 this file; see the file COPYING.LIB. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -MA 02111-1307, USA. */ - -/* You have to define the following before including this file: - - UWtype -- An unsigned type, default type for operations (typically a "word") - UHWtype -- An unsigned type, at least half the size of UWtype. - UDWtype -- An unsigned type, at least twice as large a UWtype - W_TYPE_SIZE -- size in bits of UWtype - - SItype, USItype -- Signed and unsigned 32 bit types. - DItype, UDItype -- Signed and unsigned 64 bit types. - - On a 32 bit machine UWtype should typically be USItype; - on a 64 bit machine, UWtype should typically be UDItype. -*/ - -#define __BITS4 (W_TYPE_SIZE / 4) -#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) -#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) -#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) - -/* This is used to make sure no undesirable sharing between different libraries - that use this file takes place. */ -#ifndef __MPN -#define __MPN(x) __##x -#endif - -/* Define auxiliary asm macros. - - 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two - UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype - word product in HIGH_PROD and LOW_PROD. - - 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a - UDWtype product. This is just a variant of umul_ppmm. - - 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, - denominator) divides a UDWtype, composed by the UWtype integers - HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient - in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less - than DENOMINATOR for correct operation. If, in addition, the most - significant bit of DENOMINATOR must be 1, then the pre-processor symbol - UDIV_NEEDS_NORMALIZATION is defined to 1. - - 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, - denominator). Like udiv_qrnnd but the numbers are signed. The quotient - is rounded towards 0. - - 5) count_leading_zeros(count, x) counts the number of zero-bits from the - msb to the first non-zero bit in the UWtype X. This is the number of - steps X needs to be shifted left to set the msb. Undefined for X == 0, - unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. - - 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts - from the least significant end. - - 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, - high_addend_2, low_addend_2) adds two UWtype integers, composed by - HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 - respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow - (i.e. carry out) is not stored anywhere, and is lost. - - 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, - high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, - composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and - LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE - and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, - and is lost. - - If any of these macros are left undefined for a particular CPU, - C macros are used. */ - -/* The CPUs come in alphabetical order below. - - Please add support for more CPUs here, or improve the current support - for the CPUs below! */ - -#if defined (__GNUC__) && !defined (NO_ASM) - -/* We sometimes need to clobber "cc" with gcc2, but that would not be - understood by gcc1. Use cpp to avoid major code duplication. */ -#if __GNUC__ < 2 -#define __CLOBBER_CC -#define __AND_CLOBBER_CC -#else /* __GNUC__ >= 2 */ -#define __CLOBBER_CC : "cc" -#define __AND_CLOBBER_CC , "cc" -#endif /* __GNUC__ < 2 */ - - -/*************************************** - ************** A29K ***************** - ***************************************/ -#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add %1,%4,%5\n" \ - "addc %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "rI" ((USItype)(bh)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub %1,%4,%5\n" \ - "subc %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "rI" ((USItype)(bh)), \ - "r" ((USItype)(al)), \ - "rI" ((USItype)(bl))) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("multiplu %0,%1,%2" \ - : "=r" ((USItype)(xl)) \ - : "r" (__m0), \ - "r" (__m1)); \ - __asm__ ("multmu %0,%1,%2" \ - : "=r" ((USItype)(xh)) \ - : "r" (__m0), \ - "r" (__m1)); \ - } while (0) -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("dividu %0,%3,%4" \ - : "=r" ((USItype)(q)), \ - "=q" ((USItype)(r)) \ - : "1" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "r" ((USItype)(d))) -#define count_leading_zeros(count, x) \ - __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ - : "r" ((USItype)(x))) -#define COUNT_LEADING_ZEROS_0 32 -#endif /* __a29k__ */ - - -#if defined (__alpha) && W_TYPE_SIZE == 64 -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - UDItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("umulh %r1,%2,%0" \ - : "=r" ((UDItype) ph) \ - : "%rJ" (__m0), \ - "rI" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#define UMUL_TIME 46 -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { UDItype __r; \ - (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ - (r) = __r; \ - } while (0) -extern UDItype __udiv_qrnnd (); -#define UDIV_TIME 220 -#endif /* LONGLONG_STANDALONE */ -#endif /* __alpha */ - -/*************************************** - ************** ARM ****************** - ***************************************/ -#if defined (__arm__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("adds %1, %4, %5\n" \ - "adc %0, %2, %3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "rI" ((USItype)(bh)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subs %1, %4, %5\n" \ - "sbc %0, %2, %3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "rI" ((USItype)(bh)), \ - "r" ((USItype)(al)), \ - "rI" ((USItype)(bl))) -#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__ -#define umul_ppmm(xh, xl, a, b) \ - __asm__ ("%@ Inlined umul_ppmm\n" \ - "mov %|r0, %2, lsr #16 @ AAAA\n" \ - "mov %|r2, %3, lsr #16 @ BBBB\n" \ - "bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \ - "bic %0, %3, %|r2, lsl #16 @ bbbb\n" \ - "mul %1, %|r1, %|r2 @ aaaa * BBBB\n" \ - "mul %|r2, %|r0, %|r2 @ AAAA * BBBB\n" \ - "mul %|r1, %0, %|r1 @ aaaa * bbbb\n" \ - "mul %0, %|r0, %0 @ AAAA * bbbb\n" \ - "adds %|r0, %1, %0 @ central sum\n" \ - "addcs %|r2, %|r2, #65536\n" \ - "adds %1, %|r1, %|r0, lsl #16\n" \ - "adc %0, %|r2, %|r0, lsr #16" \ - : "=&r" ((USItype)(xh)), \ - "=r" ((USItype)(xl)) \ - : "r" ((USItype)(a)), \ - "r" ((USItype)(b)) \ - : "r0", "r1", "r2") -#else -#define umul_ppmm(xh, xl, a, b) \ - __asm__ ("%@ Inlined umul_ppmm\n" \ - "umull %r1, %r0, %r2, %r3" \ - : "=&r" ((USItype)(xh)), \ - "=r" ((USItype)(xl)) \ - : "r" ((USItype)(a)), \ - "r" ((USItype)(b)) \ - : "r0", "r1") -#endif -#define UMUL_TIME 20 -#define UDIV_TIME 100 -#endif /* __arm__ */ - -/*************************************** - ************** CLIPPER ************** - ***************************************/ -#if defined (__clipper__) && W_TYPE_SIZE == 32 -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __xx; \ - __asm__ ("mulwux %2,%0" \ - : "=r" (__xx.__ll) \ - : "%0" ((USItype)(u)), \ - "r" ((USItype)(v))); \ - (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) -#define smul_ppmm(w1, w0, u, v) \ - ({union {DItype __ll; \ - struct {SItype __l, __h;} __i; \ - } __xx; \ - __asm__ ("mulwx %2,%0" \ - : "=r" (__xx.__ll) \ - : "%0" ((SItype)(u)), \ - "r" ((SItype)(v))); \ - (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) -#define __umulsidi3(u, v) \ - ({UDItype __w; \ - __asm__ ("mulwux %2,%0" \ - : "=r" (__w) \ - : "%0" ((USItype)(u)), \ - "r" ((USItype)(v))); \ - __w; }) -#endif /* __clipper__ */ - - -/*************************************** - ************** GMICRO *************** - ***************************************/ -#if defined (__gmicro__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add.w %5,%1\n" \ - "addx %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ - : "%0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub.w %5,%1\n" \ - "subx %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ - : "0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define umul_ppmm(ph, pl, m0, m1) \ - __asm__ ("mulx %3,%0,%1" \ - : "=g" ((USItype)(ph)), \ - "=r" ((USItype)(pl)) \ - : "%0" ((USItype)(m0)), \ - "g" ((USItype)(m1))) -#define udiv_qrnnd(q, r, nh, nl, d) \ - __asm__ ("divx %4,%0,%1" \ - : "=g" ((USItype)(q)), \ - "=r" ((USItype)(r)) \ - : "1" ((USItype)(nh)), \ - "0" ((USItype)(nl)), \ - "g" ((USItype)(d))) -#define count_leading_zeros(count, x) \ - __asm__ ("bsch/1 %1,%0" \ - : "=g" (count) \ - : "g" ((USItype)(x)), \ - "0" ((USItype)0)) -#endif - - -/*************************************** - ************** HPPA ***************** - ***************************************/ -#if defined (__hppa) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ (" add %4,%5,%1\n" \ - " addc %2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%rM" ((USItype)(ah)), \ - "rM" ((USItype)(bh)), \ - "%rM" ((USItype)(al)), \ - "rM" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ (" sub %4,%5,%1\n" \ - " subb %2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "rM" ((USItype)(ah)), \ - "rM" ((USItype)(bh)), \ - "rM" ((USItype)(al)), \ - "rM" ((USItype)(bl))) -#if defined (_PA_RISC1_1) -#define umul_ppmm(wh, wl, u, v) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __xx; \ - __asm__ (" xmpyu %1,%2,%0" \ - : "=*f" (__xx.__ll) \ - : "*f" ((USItype)(u)), \ - "*f" ((USItype)(v))); \ - (wh) = __xx.__i.__h; \ - (wl) = __xx.__i.__l; \ - } while (0) -#define UMUL_TIME 8 -#define UDIV_TIME 60 -#else -#define UMUL_TIME 40 -#define UDIV_TIME 80 -#endif -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { USItype __r; \ - (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ - (r) = __r; \ - } while (0) -extern USItype __udiv_qrnnd (); -#endif /* LONGLONG_STANDALONE */ -#define count_leading_zeros(count, x) \ - do { \ - USItype __tmp; \ - __asm__ ( \ - " ldi 1,%0 \n" \ - " extru,= %1,15,16,%%r0 ; Bits 31..16 zero? \n" \ - " extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ - " ldo 16(%0),%0 ; Yes. Perform add. \n" \ - " extru,= %1,23,8,%%r0 ; Bits 15..8 zero? \n" \ - " extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ - " ldo 8(%0),%0 ; Yes. Perform add. \n" \ - " extru,= %1,27,4,%%r0 ; Bits 7..4 zero? \n" \ - " extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ - " ldo 4(%0),%0 ; Yes. Perform add. \n" \ - " extru,= %1,29,2,%%r0 ; Bits 3..2 zero? \n" \ - " extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ - " ldo 2(%0),%0 ; Yes. Perform add. \n" \ - " extru %1,30,1,%1 ; Extract bit 1. \n" \ - " sub %0,%1,%0 ; Subtract it. " \ - : "=r" (count), "=r" (__tmp) : "1" (x)); \ - } while (0) -#endif /* hppa */ - - -/*************************************** - ************** I370 ***************** - ***************************************/ -#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __xx; \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mr %0,%3" \ - : "=r" (__xx.__i.__h), \ - "=r" (__xx.__i.__l) \ - : "%1" (__m0), \ - "r" (__m1)); \ - (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ - (xh) += ((((SItype) __m0 >> 31) & __m1) \ - + (((SItype) __m1 >> 31) & __m0)); \ - } while (0) -#define smul_ppmm(xh, xl, m0, m1) \ - do { \ - union {DItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __xx; \ - __asm__ ("mr %0,%3" \ - : "=r" (__xx.__i.__h), \ - "=r" (__xx.__i.__l) \ - : "%1" (m0), \ - "r" (m1)); \ - (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ - } while (0) -#define sdiv_qrnnd(q, r, n1, n0, d) \ - do { \ - union {DItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __xx; \ - __xx.__i.__h = n1; __xx.__i.__l = n0; \ - __asm__ ("dr %0,%2" \ - : "=r" (__xx.__ll) \ - : "0" (__xx.__ll), "r" (d)); \ - (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ - } while (0) -#endif - - -/*************************************** - ************** I386 ***************** - ***************************************/ -#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addl %5,%1\n" \ - "adcl %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subl %5,%1\n" \ - "sbbl %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mull %3" \ - : "=a" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "%0" ((USItype)(u)), \ - "rm" ((USItype)(v))) -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divl %4" \ - : "=a" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "rm" ((USItype)(d))) -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - __asm__ ("bsrl %1,%0" \ - : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ - (count) = __cbtmp ^ 31; \ - } while (0) -#define count_trailing_zeros(count, x) \ - __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) -#ifndef UMUL_TIME -#define UMUL_TIME 40 -#endif -#ifndef UDIV_TIME -#define UDIV_TIME 40 -#endif -#endif /* 80x86 */ - - -/*************************************** - ************** I860 ***************** - ***************************************/ -#if defined (__i860__) && W_TYPE_SIZE == 32 -#define rshift_rhlc(r,h,l,c) \ - __asm__ ("shr %3,r0,r0\n" \ - "shrd %1,%2,%0" \ - "=r" (r) : "r" (h), "r" (l), "rn" (c)) -#endif /* i860 */ - -/*************************************** - ************** I960 ***************** - ***************************************/ -#if defined (__i960__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("cmpo 1,0\n" \ - "addc %5,%4,%1\n" \ - "addc %3,%2,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%dI" ((USItype)(ah)), \ - "dI" ((USItype)(bh)), \ - "%dI" ((USItype)(al)), \ - "dI" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("cmpo 0,0\n" \ - "subc %5,%4,%1\n" \ - "subc %3,%2,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "dI" ((USItype)(ah)), \ - "dI" ((USItype)(bh)), \ - "dI" ((USItype)(al)), \ - "dI" ((USItype)(bl))) -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __xx; \ - __asm__ ("emul %2,%1,%0" \ - : "=d" (__xx.__ll) \ - : "%dI" ((USItype)(u)), \ - "dI" ((USItype)(v))); \ - (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) -#define __umulsidi3(u, v) \ - ({UDItype __w; \ - __asm__ ("emul %2,%1,%0" \ - : "=d" (__w) \ - : "%dI" ((USItype)(u)), \ - "dI" ((USItype)(v))); \ - __w; }) -#define udiv_qrnnd(q, r, nh, nl, d) \ - do { \ - union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __nn; \ - __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ - __asm__ ("ediv %d,%n,%0" \ - : "=d" (__rq.__ll) \ - : "dI" (__nn.__ll), \ - "dI" ((USItype)(d))); \ - (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ - } while (0) -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - __asm__ ("scanbit %1,%0" \ - : "=r" (__cbtmp) \ - : "r" ((USItype)(x))); \ - (count) = __cbtmp ^ 31; \ - } while (0) -#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ -#if defined (__i960mx) /* what is the proper symbol to test??? */ -#define rshift_rhlc(r,h,l,c) \ - do { \ - union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __nn; \ - __nn.__i.__h = (h); __nn.__i.__l = (l); \ - __asm__ ("shre %2,%1,%0" \ - : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ - } -#endif /* i960mx */ -#endif /* i960 */ - - -/*************************************** - ************** 68000 **************** - ***************************************/ -#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add%.l %5,%1\n" \ - "addx%.l %3,%0" \ - : "=d" ((USItype)(sh)), \ - "=&d" ((USItype)(sl)) \ - : "%0" ((USItype)(ah)), \ - "d" ((USItype)(bh)), \ - "%1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub%.l %5,%1\n" \ - "subx%.l %3,%0" \ - : "=d" ((USItype)(sh)), \ - "=&d" ((USItype)(sl)) \ - : "0" ((USItype)(ah)), \ - "d" ((USItype)(bh)), \ - "1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("mulu%.l %3,%1:%0" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "%0" ((USItype)(u)), \ - "dmi" ((USItype)(v))) -#define UMUL_TIME 45 -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divu%.l %4,%1:%0" \ - : "=d" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "dmi" ((USItype)(d))) -#define UDIV_TIME 90 -#define sdiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divs%.l %4,%1:%0" \ - : "=d" ((USItype)(q)), \ - "=d" ((USItype)(r)) \ - : "0" ((USItype)(n0)), \ - "1" ((USItype)(n1)), \ - "dmi" ((USItype)(d))) -#define count_leading_zeros(count, x) \ - __asm__ ("bfffo %1{%b2:%b2},%0" \ - : "=d" ((USItype)(count)) \ - : "od" ((USItype)(x)), "n" (0)) -#define COUNT_LEADING_ZEROS_0 32 -#else /* not mc68020 */ -#define umul_ppmm(xh, xl, a, b) \ - do { USItype __umul_tmp1, __umul_tmp2; \ - __asm__ ("| Inlined umul_ppmm \n" \ - " move%.l %5,%3 \n" \ - " move%.l %2,%0 \n" \ - " move%.w %3,%1 \n" \ - " swap %3 \n" \ - " swap %0 \n" \ - " mulu %2,%1 \n" \ - " mulu %3,%0 \n" \ - " mulu %2,%3 \n" \ - " swap %2 \n" \ - " mulu %5,%2 \n" \ - " add%.l %3,%2 \n" \ - " jcc 1f \n" \ - " add%.l %#0x10000,%0 \n" \ - "1: move%.l %2,%3 \n" \ - " clr%.w %2 \n" \ - " swap %2 \n" \ - " swap %3 \n" \ - " clr%.w %3 \n" \ - " add%.l %3,%1 \n" \ - " addx%.l %2,%0 \n" \ - " | End inlined umul_ppmm" \ - : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ - "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ - : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ - } while (0) -#define UMUL_TIME 100 -#define UDIV_TIME 400 -#endif /* not mc68020 */ -#endif /* mc68000 */ - - -/*************************************** - ************** 88000 **************** - ***************************************/ -#if defined (__m88000__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addu.co %1,%r4,%r5\n" \ - "addu.ci %0,%r2,%r3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%rJ" ((USItype)(ah)), \ - "rJ" ((USItype)(bh)), \ - "%rJ" ((USItype)(al)), \ - "rJ" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subu.co %1,%r4,%r5\n" \ - "subu.ci %0,%r2,%r3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "rJ" ((USItype)(ah)), \ - "rJ" ((USItype)(bh)), \ - "rJ" ((USItype)(al)), \ - "rJ" ((USItype)(bl))) -#define count_leading_zeros(count, x) \ - do { \ - USItype __cbtmp; \ - __asm__ ("ff1 %0,%1" \ - : "=r" (__cbtmp) \ - : "r" ((USItype)(x))); \ - (count) = __cbtmp ^ 31; \ - } while (0) -#define COUNT_LEADING_ZEROS_0 63 /* sic */ -#if defined (__m88110__) -#define umul_ppmm(wh, wl, u, v) \ - do { \ - union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x; \ - __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ - (wh) = __x.__i.__h; \ - (wl) = __x.__i.__l; \ - } while (0) -#define udiv_qrnnd(q, r, n1, n0, d) \ - ({union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __x, __q; \ - __x.__i.__h = (n1); __x.__i.__l = (n0); \ - __asm__ ("divu.d %0,%1,%2" \ - : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ - (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) -#define UMUL_TIME 5 -#define UDIV_TIME 25 -#else -#define UMUL_TIME 17 -#define UDIV_TIME 150 -#endif /* __m88110__ */ -#endif /* __m88000__ */ - -/*************************************** - ************** MIPS ***************** - ***************************************/ -#if defined (__mips__) && W_TYPE_SIZE == 32 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("multu %2,%3" \ - : "=l" ((USItype)(w0)), \ - "=h" ((USItype)(w1)) \ - : "d" ((USItype)(u)), \ - "d" ((USItype)(v))) -#else -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("multu %2,%3 \n" \ - "mflo %0 \n" \ - "mfhi %1" \ - : "=d" ((USItype)(w0)), \ - "=d" ((USItype)(w1)) \ - : "d" ((USItype)(u)), \ - "d" ((USItype)(v))) -#endif -#define UMUL_TIME 10 -#define UDIV_TIME 100 -#endif /* __mips__ */ - -/*************************************** - ************** MIPS/64 ************** - ***************************************/ -#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmultu %2,%3" \ - : "=l" ((UDItype)(w0)), \ - "=h" ((UDItype)(w1)) \ - : "d" ((UDItype)(u)), \ - "d" ((UDItype)(v))) -#else -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("dmultu %2,%3 \n" \ - "mflo %0 \n" \ - "mfhi %1" \ - : "=d" ((UDItype)(w0)), \ - "=d" ((UDItype)(w1)) \ - : "d" ((UDItype)(u)), \ - "d" ((UDItype)(v))) -#endif -#define UMUL_TIME 20 -#define UDIV_TIME 140 -#endif /* __mips__ */ - - -/*************************************** - ************** 32000 **************** - ***************************************/ -#if defined (__ns32000__) && W_TYPE_SIZE == 32 -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __xx; \ - __asm__ ("meid %2,%0" \ - : "=g" (__xx.__ll) \ - : "%0" ((USItype)(u)), \ - "g" ((USItype)(v))); \ - (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) -#define __umulsidi3(u, v) \ - ({UDItype __w; \ - __asm__ ("meid %2,%0" \ - : "=g" (__w) \ - : "%0" ((USItype)(u)), \ - "g" ((USItype)(v))); \ - __w; }) -#define udiv_qrnnd(q, r, n1, n0, d) \ - ({union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __xx; \ - __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ - __asm__ ("deid %2,%0" \ - : "=g" (__xx.__ll) \ - : "0" (__xx.__ll), \ - "g" ((USItype)(d))); \ - (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) -#define count_trailing_zeros(count,x) \ - do { - __asm__ ("ffsd %2,%0" \ - : "=r" ((USItype) (count)) \ - : "0" ((USItype) 0), \ - "r" ((USItype) (x))); \ - } while (0) -#endif /* __ns32000__ */ - - -/*************************************** - ************** PPC ****************** - ***************************************/ -#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))); \ - else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ - __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))); \ - else \ - __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%r" ((USItype)(ah)), \ - "r" ((USItype)(bh)), \ - "%r" ((USItype)(al)), \ - "rI" ((USItype)(bl))); \ - } while (0) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - if (__builtin_constant_p (ah) && (ah) == 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(bh)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(bh)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - else if (__builtin_constant_p (bh) && (bh) == 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ - __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - else \ - __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "r" ((USItype)(ah)), \ - "r" ((USItype)(bh)), \ - "rI" ((USItype)(al)), \ - "r" ((USItype)(bl))); \ - } while (0) -#define count_leading_zeros(count, x) \ - __asm__ ("{cntlz|cntlzw} %0,%1" \ - : "=r" ((USItype)(count)) \ - : "r" ((USItype)(x))) -#define COUNT_LEADING_ZEROS_0 32 -#if defined (_ARCH_PPC) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhwu %0,%1,%2" \ - : "=r" ((USItype) ph) \ - : "%r" (__m0), \ - "r" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#define UMUL_TIME 15 -#define smul_ppmm(ph, pl, m0, m1) \ - do { \ - SItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mulhw %0,%1,%2" \ - : "=r" ((SItype) ph) \ - : "%r" (__m0), \ - "r" (__m1)); \ - (pl) = __m0 * __m1; \ - } while (0) -#define SMUL_TIME 14 -#define UDIV_TIME 120 -#else -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("mul %0,%2,%3" \ - : "=r" ((USItype)(xh)), \ - "=q" ((USItype)(xl)) \ - : "r" (__m0), \ - "r" (__m1)); \ - (xh) += ((((SItype) __m0 >> 31) & __m1) \ - + (((SItype) __m1 >> 31) & __m0)); \ - } while (0) -#define UMUL_TIME 8 -#define smul_ppmm(xh, xl, m0, m1) \ - __asm__ ("mul %0,%2,%3" \ - : "=r" ((SItype)(xh)), \ - "=q" ((SItype)(xl)) \ - : "r" (m0), \ - "r" (m1)) -#define SMUL_TIME 4 -#define sdiv_qrnnd(q, r, nh, nl, d) \ - __asm__ ("div %0,%2,%4" \ - : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \ - : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d))) -#define UDIV_TIME 100 -#endif -#endif /* Power architecture variants. */ - - -/*************************************** - ************** PYR ****************** - ***************************************/ -#if defined (__pyr__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addw %5,%1 \n" \ - "addwc %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subw %5,%1 \n" \ - "subwb %3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ -#define umul_ppmm(w1, w0, u, v) \ - ({union {UDItype __ll; \ - struct {USItype __h, __l;} __i; \ - } __xx; \ - __asm__ ("movw %1,%R0 \n" \ - "uemul %2,%0" \ - : "=&r" (__xx.__ll) \ - : "g" ((USItype) (u)), \ - "g" ((USItype)(v))); \ - (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) -#endif /* __pyr__ */ - - -/*************************************** - ************** RT/ROMP ************** - ***************************************/ -#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("a %1,%5 \n" \ - "ae %0,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%0" ((USItype)(ah)), \ - "r" ((USItype)(bh)), \ - "%1" ((USItype)(al)), \ - "r" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("s %1,%5\n" \ - "se %0,%3" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "0" ((USItype)(ah)), \ - "r" ((USItype)(bh)), \ - "1" ((USItype)(al)), \ - "r" ((USItype)(bl))) -#define umul_ppmm(ph, pl, m0, m1) \ - do { \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ( \ - "s r2,r2 \n" \ - "mts r10,%2 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "m r2,%3 \n" \ - "cas %0,r2,r0 \n" \ - "mfs r10,%1" \ - : "=r" ((USItype)(ph)), \ - "=r" ((USItype)(pl)) \ - : "%r" (__m0), \ - "r" (__m1) \ - : "r2"); \ - (ph) += ((((SItype) __m0 >> 31) & __m1) \ - + (((SItype) __m1 >> 31) & __m0)); \ - } while (0) -#define UMUL_TIME 20 -#define UDIV_TIME 200 -#define count_leading_zeros(count, x) \ - do { \ - if ((x) >= 0x10000) \ - __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ - : "r" ((USItype)(x) >> 16)); \ - else \ - { \ - __asm__ ("clz %0,%1" \ - : "=r" ((USItype)(count)) \ - : "r" ((USItype)(x))); \ - (count) += 16; \ - } \ - } while (0) -#endif /* RT/ROMP */ - - -/*************************************** - ************** SH2 ****************** - ***************************************/ -#if defined (__sh2__) && W_TYPE_SIZE == 32 -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ( \ - "dmulu.l %2,%3\n" \ - "sts macl,%1\n" \ - "sts mach,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ - : "r" ((USItype)(u)), \ - "r" ((USItype)(v)) \ - : "macl", "mach") -#define UMUL_TIME 5 -#endif - -/*************************************** - ************** SPARC **************** - ***************************************/ -#if defined (__sparc__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %r4,%5,%1\n" \ - "addx %r2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "%rJ" ((USItype)(ah)), \ - "rI" ((USItype)(bh)), \ - "%rJ" ((USItype)(al)), \ - "rI" ((USItype)(bl)) \ - __CLOBBER_CC) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subcc %r4,%5,%1\n" \ - "subx %r2,%3,%0" \ - : "=r" ((USItype)(sh)), \ - "=&r" ((USItype)(sl)) \ - : "rJ" ((USItype)(ah)), \ - "rI" ((USItype)(bh)), \ - "rJ" ((USItype)(al)), \ - "rI" ((USItype)(bl)) \ - __CLOBBER_CC) -#if defined (__sparc_v8__) -/* Don't match immediate range because, 1) it is not often useful, - 2) the 'I' flag thinks of the range as a 13 bit signed interval, - while we want to match a 13 bit interval, sign extended to 32 bits, - but INTERPRETED AS UNSIGNED. */ -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("umul %2,%3,%1;rd %%y,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ - : "r" ((USItype)(u)), \ - "r" ((USItype)(v))) -#define UMUL_TIME 5 -#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */ -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { \ - USItype __q; \ - __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ - : "=r" ((USItype)(__q)) \ - : "r" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "r" ((USItype)(d))); \ - (r) = (n0) - __q * (d); \ - (q) = __q; \ - } while (0) -#define UDIV_TIME 25 -#endif /* SUPERSPARC */ -#else /* ! __sparc_v8__ */ -#if defined (__sparclite__) -/* This has hardware multiply but not divide. It also has two additional - instructions scan (ffs from high bit) and divscc. */ -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("umul %2,%3,%1;rd %%y,%0" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ - : "r" ((USItype)(u)), \ - "r" ((USItype)(v))) -#define UMUL_TIME 5 -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("! Inlined udiv_qrnnd \n" \ - " wr %%g0,%2,%%y ! Not a delayed write for sparclite \n" \ - " tst %%g0 \n" \ - " divscc %3,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%%g1 \n" \ - " divscc %%g1,%4,%0 \n" \ - " rd %%y,%1 \n" \ - " bl,a 1f \n" \ - " add %1,%4,%1 \n" \ - "1: ! End of inline udiv_qrnnd" \ - : "=r" ((USItype)(q)), \ - "=r" ((USItype)(r)) \ - : "r" ((USItype)(n1)), \ - "r" ((USItype)(n0)), \ - "rI" ((USItype)(d)) \ - : "%g1" __AND_CLOBBER_CC) -#define UDIV_TIME 37 -#define count_leading_zeros(count, x) \ - __asm__ ("scan %1,0,%0" \ - : "=r" ((USItype)(x)) \ - : "r" ((USItype)(count))) -/* Early sparclites return 63 for an argument of 0, but they warn that future - implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 - undefined. */ -#endif /* __sparclite__ */ -#endif /* __sparc_v8__ */ -/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ -#ifndef umul_ppmm -#define umul_ppmm(w1, w0, u, v) \ - __asm__ ("! Inlined umul_ppmm \n" \ - " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr \n" \ - " sra %3,31,%%g2 ! Don't move this insn \n" \ - " and %2,%%g2,%%g2 ! Don't move this insn \n" \ - " andcc %%g0,0,%%g1 ! Don't move this insn \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,%3,%%g1 \n" \ - " mulscc %%g1,0,%%g1 \n" \ - " add %%g1,%%g2,%0 \n" \ - " rd %%y,%1" \ - : "=r" ((USItype)(w1)), \ - "=r" ((USItype)(w0)) \ - : "%rI" ((USItype)(u)), \ - "r" ((USItype)(v)) \ - : "%g1", "%g2" __AND_CLOBBER_CC) -#define UMUL_TIME 39 /* 39 instructions */ -#endif -#ifndef udiv_qrnnd -#ifndef LONGLONG_STANDALONE -#define udiv_qrnnd(q, r, n1, n0, d) \ - do { USItype __r; \ - (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ - (r) = __r; \ - } while (0) -extern USItype __udiv_qrnnd (); -#define UDIV_TIME 140 -#endif /* LONGLONG_STANDALONE */ -#endif /* udiv_qrnnd */ -#endif /* __sparc__ */ - - -/*************************************** - ************** VAX ****************** - ***************************************/ -#if defined (__vax__) && W_TYPE_SIZE == 32 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addl2 %5,%1\n" \ - "adwc %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ - : "%0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "%1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subl2 %5,%1\n" \ - "sbwc %3,%0" \ - : "=g" ((USItype)(sh)), \ - "=&g" ((USItype)(sl)) \ - : "0" ((USItype)(ah)), \ - "g" ((USItype)(bh)), \ - "1" ((USItype)(al)), \ - "g" ((USItype)(bl))) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {UDItype __ll; \ - struct {USItype __l, __h;} __i; \ - } __xx; \ - USItype __m0 = (m0), __m1 = (m1); \ - __asm__ ("emul %1,%2,$0,%0" \ - : "=g" (__xx.__ll) \ - : "g" (__m0), \ - "g" (__m1)); \ - (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ - (xh) += ((((SItype) __m0 >> 31) & __m1) \ - + (((SItype) __m1 >> 31) & __m0)); \ - } while (0) -#define sdiv_qrnnd(q, r, n1, n0, d) \ - do { \ - union {DItype __ll; \ - struct {SItype __l, __h;} __i; \ - } __xx; \ - __xx.__i.__h = n1; __xx.__i.__l = n0; \ - __asm__ ("ediv %3,%2,%0,%1" \ - : "=g" (q), "=g" (r) \ - : "g" (__xx.__ll), "g" (d)); \ - } while (0) -#endif /* __vax__ */ - - -/*************************************** - ************** Z8000 **************** - ***************************************/ -#if defined (__z8000__) && W_TYPE_SIZE == 16 -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ - : "=r" ((unsigned int)(sh)), \ - "=&r" ((unsigned int)(sl)) \ - : "%0" ((unsigned int)(ah)), \ - "r" ((unsigned int)(bh)), \ - "%1" ((unsigned int)(al)), \ - "rQR" ((unsigned int)(bl))) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ - : "=r" ((unsigned int)(sh)), \ - "=&r" ((unsigned int)(sl)) \ - : "0" ((unsigned int)(ah)), \ - "r" ((unsigned int)(bh)), \ - "1" ((unsigned int)(al)), \ - "rQR" ((unsigned int)(bl))) -#define umul_ppmm(xh, xl, m0, m1) \ - do { \ - union {long int __ll; \ - struct {unsigned int __h, __l;} __i; \ - } __xx; \ - unsigned int __m0 = (m0), __m1 = (m1); \ - __asm__ ("mult %S0,%H3" \ - : "=r" (__xx.__i.__h), \ - "=r" (__xx.__i.__l) \ - : "%1" (__m0), \ - "rQR" (__m1)); \ - (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ - (xh) += ((((signed int) __m0 >> 15) & __m1) \ - + (((signed int) __m1 >> 15) & __m0)); \ - } while (0) -#endif /* __z8000__ */ - -#endif /* __GNUC__ */ - - -/*************************************** - *********** Generic Versions ******** - ***************************************/ -#if !defined (umul_ppmm) && defined (__umulsidi3) -#define umul_ppmm(ph, pl, m0, m1) \ - { \ - UDWtype __ll = __umulsidi3 (m0, m1); \ - ph = (UWtype) (__ll >> W_TYPE_SIZE); \ - pl = (UWtype) __ll; \ - } -#endif - -#if !defined (__umulsidi3) -#define __umulsidi3(u, v) \ - ({UWtype __hi, __lo; \ - umul_ppmm (__hi, __lo, u, v); \ - ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) -#endif - -/* If this machine has no inline assembler, use C macros. */ - -#if !defined (add_ssaaaa) -#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - UWtype __x; \ - __x = (al) + (bl); \ - (sh) = (ah) + (bh) + (__x < (al)); \ - (sl) = __x; \ - } while (0) -#endif - -#if !defined (sub_ddmmss) -#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - UWtype __x; \ - __x = (al) - (bl); \ - (sh) = (ah) - (bh) - (__x > (al)); \ - (sl) = __x; \ - } while (0) -#endif - -#if !defined (umul_ppmm) -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __x0, __x1, __x2, __x3; \ - UHWtype __ul, __vl, __uh, __vh; \ - UWtype __u = (u), __v = (v); \ - \ - __ul = __ll_lowpart (__u); \ - __uh = __ll_highpart (__u); \ - __vl = __ll_lowpart (__v); \ - __vh = __ll_highpart (__v); \ - \ - __x0 = (UWtype) __ul * __vl; \ - __x1 = (UWtype) __ul * __vh; \ - __x2 = (UWtype) __uh * __vl; \ - __x3 = (UWtype) __uh * __vh; \ - \ - __x1 += __ll_highpart (__x0);/* this can't give carry */ \ - __x1 += __x2; /* but this indeed can */ \ - if (__x1 < __x2) /* did we get it? */ \ - __x3 += __ll_B; /* yes, add it in the proper pos. */ \ - \ - (w1) = __x3 + __ll_highpart (__x1); \ - (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ - } while (0) -#endif - -#if !defined (umul_ppmm) -#define smul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __w1; \ - UWtype __m0 = (u), __m1 = (v); \ - umul_ppmm (__w1, w0, __m0, __m1); \ - (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ - - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ - } while (0) -#endif - -/* Define this unconditionally, so it can be used for debugging. */ -#define __udiv_qrnnd_c(q, r, n1, n0, d) \ - do { \ - UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ - __d1 = __ll_highpart (d); \ - __d0 = __ll_lowpart (d); \ - \ - __r1 = (n1) % __d1; \ - __q1 = (n1) / __d1; \ - __m = (UWtype) __q1 * __d0; \ - __r1 = __r1 * __ll_B | __ll_highpart (n0); \ - if (__r1 < __m) \ - { \ - __q1--, __r1 += (d); \ - if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ - if (__r1 < __m) \ - __q1--, __r1 += (d); \ - } \ - __r1 -= __m; \ - \ - __r0 = __r1 % __d1; \ - __q0 = __r1 / __d1; \ - __m = (UWtype) __q0 * __d0; \ - __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ - if (__r0 < __m) \ - { \ - __q0--, __r0 += (d); \ - if (__r0 >= (d)) \ - if (__r0 < __m) \ - __q0--, __r0 += (d); \ - } \ - __r0 -= __m; \ - \ - (q) = (UWtype) __q1 * __ll_B | __q0; \ - (r) = __r0; \ - } while (0) - -/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through - __udiv_w_sdiv (defined in libgcc or elsewhere). */ -#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) -#define udiv_qrnnd(q, r, nh, nl, d) \ - do { \ - UWtype __r; \ - (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ - (r) = __r; \ - } while (0) -#endif - -/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ -#if !defined (udiv_qrnnd) -#define UDIV_NEEDS_NORMALIZATION 1 -#define udiv_qrnnd __udiv_qrnnd_c -#endif - -#if !defined (count_leading_zeros) -extern -#ifdef __STDC__ -const -#endif -unsigned char __clz_tab[]; -#define MPI_INTERNAL_NEED_CLZ_TAB 1 -#define count_leading_zeros(count, x) \ - do { \ - UWtype __xr = (x); \ - UWtype __a; \ - \ - if (W_TYPE_SIZE <= 32) \ - { \ - __a = __xr < ((UWtype) 1 << 2*__BITS4) \ - ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ - : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ - } \ - else \ - { \ - for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ - if (((__xr >> __a) & 0xff) != 0) \ - break; \ - } \ - \ - (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ - } while (0) -/* This version gives a well-defined value for zero. */ -#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE -#endif - -#if !defined (count_trailing_zeros) -/* Define count_trailing_zeros using count_leading_zeros. The latter might be - defined in asm, but if it is not, the C version above is good enough. */ -#define count_trailing_zeros(count, x) \ - do { \ - UWtype __ctz_x = (x); \ - UWtype __ctz_c; \ - count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ - (count) = W_TYPE_SIZE - 1 - __ctz_c; \ - } while (0) -#endif - -#ifndef UDIV_NEEDS_NORMALIZATION -#define UDIV_NEEDS_NORMALIZATION 0 -#endif diff --git a/mpi/m68k/distfiles b/mpi/m68k/distfiles deleted file mode 100644 index 4c0967b84..000000000 --- a/mpi/m68k/distfiles +++ /dev/null @@ -1,8 +0,0 @@ -syntax.h -mpih-lshift.S -mpih-rshift.S -mpih-add1.S -mpih-sub1.S - - - diff --git a/mpi/m68k/mc68020/distfiles b/mpi/m68k/mc68020/distfiles deleted file mode 100644 index fc7df9fa3..000000000 --- a/mpi/m68k/mc68020/distfiles +++ /dev/null @@ -1,3 +0,0 @@ -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S diff --git a/mpi/m68k/mc68020/mpih-mul1.S b/mpi/m68k/mc68020/mpih-mul1.S deleted file mode 100644 index 4872b9ba7..000000000 --- a/mpi/m68k/mc68020/mpih-mul1.S +++ /dev/null @@ -1,106 +0,0 @@ -/* mc68020 __mpn_mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_mul_1) - -C_SYMBOL_NAME(mpihelp_mul_1:) -PROLOG(mpihelp_mul_1) - -#define res_ptr a0 -#define s1_ptr a1 -#define s1_size d2 -#define s2_limb d4 - -/* Save used registers on the stack. */ - moveml R(d2)-R(d4),MEM_PREDEC(sp) -#if 0 - movel R(d2),MEM_PREDEC(sp) - movel R(d3),MEM_PREDEC(sp) - movel R(d4),MEM_PREDEC(sp) -#endif - -/* Copy the arguments to registers. Better use movem? */ - movel MEM_DISP(sp,16),R(res_ptr) - movel MEM_DISP(sp,20),R(s1_ptr) - movel MEM_DISP(sp,24),R(s1_size) - movel MEM_DISP(sp,28),R(s2_limb) - - eorw #1,R(s1_size) - clrl R(d1) - lsrl #1,R(s1_size) - bcc L(L1) - subql #1,R(s1_size) - subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ - -L(Loop:) - movel MEM_POSTINC(s1_ptr),R(d3) - mulul R(s2_limb),R(d1):R(d3) - addxl R(d0),R(d3) - movel R(d3),MEM_POSTINC(res_ptr) -L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) - mulul R(s2_limb),R(d0):R(d3) - addxl R(d1),R(d3) - movel R(d3),MEM_POSTINC(res_ptr) - - dbf R(s1_size),L(Loop) - clrl R(d3) - addxl R(d3),R(d0) - subl #0x10000,R(s1_size) - bcc L(Loop) - -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d4) -#if 0 - movel MEM_POSTINC(sp),R(d4) - movel MEM_POSTINC(sp),R(d3) - movel MEM_POSTINC(sp),R(d2) -#endif - rts -EPILOG(mpihelp_mul_1) - - diff --git a/mpi/m68k/mc68020/mpih-mul2.S b/mpi/m68k/mc68020/mpih-mul2.S deleted file mode 100644 index 7c492ffb2..000000000 --- a/mpi/m68k/mc68020/mpih-mul2.S +++ /dev/null @@ -1,96 +0,0 @@ -/* mc68020 __mpn_addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) - -C_SYMBOL_NAME(mpihelp_addmul_1:) -PROLOG(mpihelp_addmul_1) - -#define res_ptr a0 -#define s1_ptr a1 -#define s1_size d2 -#define s2_limb d4 - -/* Save used registers on the stack. */ - moveml R(d2)-R(d5),MEM_PREDEC(sp) - -/* Copy the arguments to registers. Better use movem? */ - movel MEM_DISP(sp,20),R(res_ptr) - movel MEM_DISP(sp,24),R(s1_ptr) - movel MEM_DISP(sp,28),R(s1_size) - movel MEM_DISP(sp,32),R(s2_limb) - - eorw #1,R(s1_size) - clrl R(d1) - clrl R(d5) - lsrl #1,R(s1_size) - bcc L(L1) - subql #1,R(s1_size) - subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ - -L(Loop:) - movel MEM_POSTINC(s1_ptr),R(d3) - mulul R(s2_limb),R(d1):R(d3) - addxl R(d0),R(d3) - addxl R(d5),R(d1) - addl R(d3),MEM_POSTINC(res_ptr) -L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) - mulul R(s2_limb),R(d0):R(d3) - addxl R(d1),R(d3) - addxl R(d5),R(d0) - addl R(d3),MEM_POSTINC(res_ptr) - - dbf R(s1_size),L(Loop) - addxl R(d5),R(d0) - subl #0x10000,R(s1_size) - bcc L(Loop) - -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d5) - - rts -EPILOG(mpihelp_addmul_1) - diff --git a/mpi/m68k/mc68020/mpih-mul3.S b/mpi/m68k/mc68020/mpih-mul3.S deleted file mode 100644 index 1e4ac45d6..000000000 --- a/mpi/m68k/mc68020/mpih-mul3.S +++ /dev/null @@ -1,99 +0,0 @@ -/* mc68020 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract - * the result from a second limb vector. - * - * Copyright (C) 1992, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - - -#include "sysdep.h" -#include "asm-syntax.h" - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_size_t s1_size, (sp + 12) - * mpi_limb_t s2_limb) (sp + 16) - */ - - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_submul_1) - -C_SYMBOL_NAME(mpihelp_submul_1:) -PROLOG(mpihelp_submul_1) - -#define res_ptr a0 -#define s1_ptr a1 -#define s1_size d2 -#define s2_limb d4 - -/* Save used registers on the stack. */ - moveml R(d2)-R(d5),MEM_PREDEC(sp) - -/* Copy the arguments to registers. Better use movem? */ - movel MEM_DISP(sp,20),R(res_ptr) - movel MEM_DISP(sp,24),R(s1_ptr) - movel MEM_DISP(sp,28),R(s1_size) - movel MEM_DISP(sp,32),R(s2_limb) - - eorw #1,R(s1_size) - clrl R(d1) - clrl R(d5) - lsrl #1,R(s1_size) - bcc L(L1) - subql #1,R(s1_size) - subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ - -L(Loop:) - movel MEM_POSTINC(s1_ptr),R(d3) - mulul R(s2_limb),R(d1):R(d3) - addxl R(d0),R(d3) - addxl R(d5),R(d1) - subl R(d3),MEM_POSTINC(res_ptr) -L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) - mulul R(s2_limb),R(d0):R(d3) - addxl R(d1),R(d3) - addxl R(d5),R(d0) - subl R(d3),MEM_POSTINC(res_ptr) - - dbf R(s1_size),L(Loop) - addxl R(d5),R(d0) - subl #0x10000,R(s1_size) - bcc L(Loop) - -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d5) - - rts -EPILOG(mpihelp_submul_1) - - diff --git a/mpi/m68k/mpih-add1.S b/mpi/m68k/mpih-add1.S deleted file mode 100644 index 1e9cc6406..000000000 --- a/mpi/m68k/mpih-add1.S +++ /dev/null @@ -1,94 +0,0 @@ -/* mc68020 __mpn_add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1992, 1994,1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 16) - * mpi_size_t size) (sp + 12) - */ - - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_add_n) - -C_SYMBOL_NAME(mpihelp_add_n:) -PROLOG(mpihelp_add_n) - /* Save used registers on the stack. */ - movel R(d2),MEM_PREDEC(sp) - movel R(a2),MEM_PREDEC(sp) - - /* Copy the arguments to registers. Better use movem? */ - movel MEM_DISP(sp,12),R(a2) - movel MEM_DISP(sp,16),R(a0) - movel MEM_DISP(sp,20),R(a1) - movel MEM_DISP(sp,24),R(d2) - - eorw #1,R(d2) - lsrl #1,R(d2) - bcc L(L1) - subql #1,R(d2) /* clears cy as side effect */ - -L(Loop:) - movel MEM_POSTINC(a0),R(d0) - movel MEM_POSTINC(a1),R(d1) - addxl R(d1),R(d0) - movel R(d0),MEM_POSTINC(a2) -L(L1:) movel MEM_POSTINC(a0),R(d0) - movel MEM_POSTINC(a1),R(d1) - addxl R(d1),R(d0) - movel R(d0),MEM_POSTINC(a2) - - dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */ - subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */ - subl #0x10000,R(d2) - bcs L(L2) - addl R(d0),R(d0) /* restore cy */ - bra L(Loop) - -L(L2:) - negl R(d0) - - /* Restore used registers from stack frame. */ - movel MEM_POSTINC(sp),R(a2) - movel MEM_POSTINC(sp),R(d2) - - rts -EPILOG(mpihelp_add_n) - - diff --git a/mpi/m68k/mpih-lshift.S b/mpi/m68k/mpih-lshift.S deleted file mode 100644 index cc9dfba69..000000000 --- a/mpi/m68k/mpih-lshift.S +++ /dev/null @@ -1,166 +0,0 @@ -/* mc68020 lshift -- Shift left a low-level natural-number integer. - * - * Copyright (C) 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -#define res_ptr a1 -#define s_ptr a0 -#define s_size d6 -#define cnt d4 - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_lshift) - -C_SYMBOL_NAME(mpihelp_lshift:) -PROLOG(mpihelp_lshift) - - /* Save used registers on the stack. */ - moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) - - /* Copy the arguments to registers. */ - movel MEM_DISP(sp,28),R(res_ptr) - movel MEM_DISP(sp,32),R(s_ptr) - movel MEM_DISP(sp,36),R(s_size) - movel MEM_DISP(sp,40),R(cnt) - - moveql #1,R(d5) - cmpl R(d5),R(cnt) - bne L(Lnormal) - cmpl R(s_ptr),R(res_ptr) - bls L(Lspecial) /* jump if s_ptr >= res_ptr */ -#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) - lea MEM_INDX1(s_ptr,s_size,l,4),R(a2) -#else /* not mc68020 */ - movel R(s_size),R(d0) - asll #2,R(d0) - lea MEM_INDX(s_ptr,d0,l),R(a2) -#endif - cmpl R(res_ptr),R(a2) - bls L(Lspecial) /* jump if res_ptr >= s_ptr + s_size */ - -L(Lnormal:) - moveql #32,R(d5) - subl R(cnt),R(d5) - -#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) - lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) - lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) -#else /* not mc68000 */ - movel R(s_size),R(d0) - asll #2,R(d0) - addl R(s_size),R(s_ptr) - addl R(s_size),R(res_ptr) -#endif - movel MEM_PREDEC(s_ptr),R(d2) - movel R(d2),R(d0) - lsrl R(d5),R(d0) /* compute carry limb */ - - lsll R(cnt),R(d2) - movel R(d2),R(d1) - subql #1,R(s_size) - beq L(Lend) - lsrl #1,R(s_size) - bcs L(L1) - subql #1,R(s_size) - -L(Loop:) - movel MEM_PREDEC(s_ptr),R(d2) - movel R(d2),R(d3) - lsrl R(d5),R(d3) - orl R(d3),R(d1) - movel R(d1),MEM_PREDEC(res_ptr) - lsll R(cnt),R(d2) -L(L1:) - movel MEM_PREDEC(s_ptr),R(d1) - movel R(d1),R(d3) - lsrl R(d5),R(d3) - orl R(d3),R(d2) - movel R(d2),MEM_PREDEC(res_ptr) - lsll R(cnt),R(d1) - - dbf R(s_size),L(Loop) - subl #0x10000,R(s_size) - bcc L(Loop) - -L(Lend:) - movel R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */ - -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) - rts - -/* We loop from least significant end of the arrays, which is only - permissable if the source and destination don't overlap, since the - function is documented to work for overlapping source and destination. */ - -L(Lspecial:) - clrl R(d0) /* initialize carry */ - eorw #1,R(s_size) - lsrl #1,R(s_size) - bcc L(LL1) - subql #1,R(s_size) - -L(LLoop:) - movel MEM_POSTINC(s_ptr),R(d2) - addxl R(d2),R(d2) - movel R(d2),MEM_POSTINC(res_ptr) -L(LL1:) - movel MEM_POSTINC(s_ptr),R(d2) - addxl R(d2),R(d2) - movel R(d2),MEM_POSTINC(res_ptr) - - dbf R(s_size),L(LLoop) - addxl R(d0),R(d0) /* save cy in lsb */ - subl #0x10000,R(s_size) - bcs L(LLend) - lsrl #1,R(d0) /* restore cy */ - bra L(LLoop) - -L(LLend:) -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) - rts -EPILOG(mpihelp_lshift) - - - - - diff --git a/mpi/m68k/mpih-rshift.S b/mpi/m68k/mpih-rshift.S deleted file mode 100644 index cc86166a7..000000000 --- a/mpi/m68k/mpih-rshift.S +++ /dev/null @@ -1,164 +0,0 @@ -/* mc68020 rshift -- Shift right a low-level natural-number integer. - * - * Copyright (C) 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) - * mpi_ptr_t up, (sp + 8) - * mpi_size_t usize, (sp + 12) - * unsigned cnt) (sp + 16) - */ - -#define res_ptr a1 -#define s_ptr a0 -#define s_size d6 -#define cnt d4 - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_rshift) - -C_SYMBOL_NAME(mpihelp_rshift:) -PROLOG(mpihelp_rshift) - /* Save used registers on the stack. */ - moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) - - /* Copy the arguments to registers. */ - movel MEM_DISP(sp,28),R(res_ptr) - movel MEM_DISP(sp,32),R(s_ptr) - movel MEM_DISP(sp,36),R(s_size) - movel MEM_DISP(sp,40),R(cnt) - - moveql #1,R(d5) - cmpl R(d5),R(cnt) - bne L(Rnormal) - cmpl R(res_ptr),R(s_ptr) - bls L(Rspecial) /* jump if res_ptr >= s_ptr */ -#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) - lea MEM_INDX1(res_ptr,s_size,l,4),R(a2) -#else /* not mc68020 */ - movel R(s_size),R(d0) - asll #2,R(d0) - lea MEM_INDX(res_ptr,d0,l),R(a2) -#endif - cmpl R(s_ptr),R(a2) - bls L(Rspecial) /* jump if s_ptr >= res_ptr + s_size */ - -L(Rnormal:) - moveql #32,R(d5) - subl R(cnt),R(d5) - movel MEM_POSTINC(s_ptr),R(d2) - movel R(d2),R(d0) - lsll R(d5),R(d0) /* compute carry limb */ - - lsrl R(cnt),R(d2) - movel R(d2),R(d1) - subql #1,R(s_size) - beq L(Rend) - lsrl #1,R(s_size) - bcs L(R1) - subql #1,R(s_size) - -L(Roop:) - movel MEM_POSTINC(s_ptr),R(d2) - movel R(d2),R(d3) - lsll R(d5),R(d3) - orl R(d3),R(d1) - movel R(d1),MEM_POSTINC(res_ptr) - lsrl R(cnt),R(d2) -L(R1:) - movel MEM_POSTINC(s_ptr),R(d1) - movel R(d1),R(d3) - lsll R(d5),R(d3) - orl R(d3),R(d2) - movel R(d2),MEM_POSTINC(res_ptr) - lsrl R(cnt),R(d1) - - dbf R(s_size),L(Roop) - subl #0x10000,R(s_size) - bcc L(Roop) - -L(Rend:) - movel R(d1),MEM(res_ptr) /* store most significant limb */ - -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) - rts - -/* We loop from most significant end of the arrays, which is only - permissable if the source and destination don't overlap, since the - function is documented to work for overlapping source and destination. */ - -L(Rspecial:) -#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) - lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) - lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) -#else /* not mc68000 */ - movel R(s_size),R(d0) - asll #2,R(d0) - addl R(s_size),R(s_ptr) - addl R(s_size),R(res_ptr) -#endif - - clrl R(d0) /* initialize carry */ - eorw #1,R(s_size) - lsrl #1,R(s_size) - bcc L(LR1) - subql #1,R(s_size) - -L(LRoop:) - movel MEM_PREDEC(s_ptr),R(d2) - roxrl #1,R(d2) - movel R(d2),MEM_PREDEC(res_ptr) -L(LR1:) - movel MEM_PREDEC(s_ptr),R(d2) - roxrl #1,R(d2) - movel R(d2),MEM_PREDEC(res_ptr) - - dbf R(s_size),L(LRoop) - roxrl #1,R(d0) /* save cy in msb */ - subl #0x10000,R(s_size) - bcs L(LRend) - addl R(d0),R(d0) /* restore cy */ - bra L(LRoop) - -L(LRend:) -/* Restore used registers from stack frame. */ - moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) - rts -EPILOG(mpihelp_rshift) - - - - diff --git a/mpi/m68k/mpih-sub1.S b/mpi/m68k/mpih-sub1.S deleted file mode 100644 index 1847fbd65..000000000 --- a/mpi/m68k/mpih-sub1.S +++ /dev/null @@ -1,93 +0,0 @@ -/* mc68020 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and - * store difference in a third limb vector. - * - * Copyright (C) 1992, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) - * mpi_ptr_t s1_ptr, (sp + 8) - * mpi_ptr_t s2_ptr, (sp + 16) - * mpi_size_t size) (sp + 12) - */ - - - TEXT - ALIGN - GLOBL C_SYMBOL_NAME(mpihelp_sub_n) - -C_SYMBOL_NAME(mpihelp_sub_n:) -PROLOG(mpihelp_sub_n) -/* Save used registers on the stack. */ - movel R(d2),MEM_PREDEC(sp) - movel R(a2),MEM_PREDEC(sp) - -/* Copy the arguments to registers. Better use movem? */ - movel MEM_DISP(sp,12),R(a2) - movel MEM_DISP(sp,16),R(a0) - movel MEM_DISP(sp,20),R(a1) - movel MEM_DISP(sp,24),R(d2) - - eorw #1,R(d2) - lsrl #1,R(d2) - bcc L(L1) - subql #1,R(d2) /* clears cy as side effect */ - -L(Loop:) - movel MEM_POSTINC(a0),R(d0) - movel MEM_POSTINC(a1),R(d1) - subxl R(d1),R(d0) - movel R(d0),MEM_POSTINC(a2) -L(L1:) movel MEM_POSTINC(a0),R(d0) - movel MEM_POSTINC(a1),R(d1) - subxl R(d1),R(d0) - movel R(d0),MEM_POSTINC(a2) - - dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */ - subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */ - subl #0x10000,R(d2) - bcs L(L2) - addl R(d0),R(d0) /* restore cy */ - bra L(Loop) - -L(L2:) - negl R(d0) - -/* Restore used registers from stack frame. */ - movel MEM_POSTINC(sp),R(a2) - movel MEM_POSTINC(sp),R(d2) - - rts -EPILOG(mpihelp_sub_n) - - diff --git a/mpi/m68k/syntax.h b/mpi/m68k/syntax.h deleted file mode 100644 index 316518fef..000000000 --- a/mpi/m68k/syntax.h +++ /dev/null @@ -1,187 +0,0 @@ -/* asm.h -- Definitions for 68k syntax variations. - * - * Copyright (C) 1992, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -#undef ALIGN - -#ifdef MIT_SYNTAX -#define PROLOG(name) -#define EPILOG(name) -#define R(r)r -#define MEM(base)base@ -#define MEM_DISP(base,displacement)base@(displacement) -#define MEM_INDX(base,idx,size_suffix)base@(idx:size_suffix) -#define MEM_INDX1(base,idx,size_suffix,scale)base@(idx:size_suffix:scale) -#define MEM_PREDEC(memory_base)memory_base@- -#define MEM_POSTINC(memory_base)memory_base@+ -#define L(label) label -#define TEXT .text -#define ALIGN .even -#define GLOBL .globl -#define moveql moveq -/* Use variable sized opcodes. */ -#define bcc jcc -#define bcs jcs -#define bls jls -#define beq jeq -#define bne jne -#define bra jra -#endif - -#ifdef SONY_SYNTAX -#define PROLOG(name) -#define EPILOG(name) -#define R(r)r -#define MEM(base)(base) -#define MEM_DISP(base,displacement)(displacement,base) -#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix) -#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale) -#define MEM_PREDEC(memory_base)-(memory_base) -#define MEM_POSTINC(memory_base)(memory_base)+ -#define L(label) label -#define TEXT .text -#define ALIGN .even -#define GLOBL .globl -#endif - -#ifdef MOTOROLA_SYNTAX -#define PROLOG(name) -#define EPILOG(name) -#define R(r)r -#define MEM(base)(base) -#define MEM_DISP(base,displacement)(displacement,base) -#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix) -#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale) -#define MEM_PREDEC(memory_base)-(memory_base) -#define MEM_POSTINC(memory_base)(memory_base)+ -#define L(label) label -#define TEXT -#define ALIGN -#define GLOBL XDEF -#define lea LEA -#define movel MOVE.L -#define moveml MOVEM.L -#define moveql MOVEQ.L -#define cmpl CMP.L -#define orl OR.L -#define clrl CLR.L -#define eorw EOR.W -#define lsrl LSR.L -#define lsll LSL.L -#define roxrl ROXR.L -#define roxll ROXL.L -#define addl ADD.L -#define addxl ADDX.L -#define addql ADDQ.L -#define subl SUB.L -#define subxl SUBX.L -#define subql SUBQ.L -#define negl NEG.L -#define mulul MULU.L -#define bcc BCC -#define bcs BCS -#define bls BLS -#define beq BEQ -#define bne BNE -#define bra BRA -#define dbf DBF -#define rts RTS -#define d0 D0 -#define d1 D1 -#define d2 D2 -#define d3 D3 -#define d4 D4 -#define d5 D5 -#define d6 D6 -#define d7 D7 -#define a0 A0 -#define a1 A1 -#define a2 A2 -#define a3 A3 -#define a4 A4 -#define a5 A5 -#define a6 A6 -#define a7 A7 -#define sp SP -#endif - -#ifdef ELF_SYNTAX -#define PROLOG(name) .type name,@function -#define EPILOG(name) .size name,.-name -#define MEM(base)(R(base)) -#define MEM_DISP(base,displacement)(displacement,R(base)) -#define MEM_PREDEC(memory_base)-(R(memory_base)) -#define MEM_POSTINC(memory_base)(R(memory_base))+ -#ifdef __STDC__ -#define R_(r)%##r -#define R(r)R_(r) -#define MEM_INDX_(base,idx,size_suffix)(R(base),R(idx##.##size_suffix)) -#define MEM_INDX(base,idx,size_suffix)MEM_INDX_(base,idx,size_suffix) -#define MEM_INDX1_(base,idx,size_suffix,scale)(R(base),R(idx##.##size_suffix*scale)) -#define MEM_INDX1(base,idx,size_suffix,scale)MEM_INDX1_(base,idx,size_suffix,scale) -#define L(label) .##label -#else -#define R(r)%/**/r -#define MEM_INDX(base,idx,size_suffix)(R(base),R(idx).size_suffix) -#define MEM_INDX1(base,idx,size_suffix,scale)(R(base),R(idx).size_suffix*scale) -#define L(label) ./**/label -#endif -#define TEXT .text -#define ALIGN .align 2 -#define GLOBL .globl -#define bcc jbcc -#define bcs jbcs -#define bls jbls -#define beq jbeq -#define bne jbne -#define bra jbra -#endif - -#if defined (SONY_SYNTAX) || defined (ELF_SYNTAX) -#define movel move.l -#define moveml movem.l -#define moveql moveq.l -#define cmpl cmp.l -#define orl or.l -#define clrl clr.l -#define eorw eor.w -#define lsrl lsr.l -#define lsll lsl.l -#define roxrl roxr.l -#define roxll roxl.l -#define addl add.l -#define addxl addx.l -#define addql addq.l -#define subl sub.l -#define subxl subx.l -#define subql subq.l -#define negl neg.l -#define mulul mulu.l -#endif diff --git a/mpi/mips3/README b/mpi/mips3/README deleted file mode 100644 index e94b2c746..000000000 --- a/mpi/mips3/README +++ /dev/null @@ -1,23 +0,0 @@ -This directory contains mpn functions optimized for MIPS3. Example of -processors that implement MIPS3 are R4000, R4400, R4600, R4700, and R8000. - -RELEVANT OPTIMIZATION ISSUES - -1. On the R4000 and R4400, branches, both the plain and the "likely" ones, - take 3 cycles to execute. (The fastest possible loop will take 4 cycles, - because of the delay insn.) - - On the R4600, branches takes a single cycle - - On the R8000, branches often take no noticable cycles, as they are - executed in a separate function unit.. - -2. The R4000 and R4400 have a load latency of 4 cycles. - -3. On the R4000 and R4400, multiplies take a data-dependent number of - cycles, contrary to the SGI documentation. There seem to be 3 or 4 - possible latencies. - -STATUS - -Good... diff --git a/mpi/mips3/distfiles b/mpi/mips3/distfiles deleted file mode 100644 index 85260fc8e..000000000 --- a/mpi/mips3/distfiles +++ /dev/null @@ -1,10 +0,0 @@ -README -mpih-add1.S -mpih-sub1.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S -mpih-lshift.S -mpih-rshift.S -mpi-asm-defs.h - diff --git a/mpi/mips3/mpi-asm-defs.h b/mpi/mips3/mpi-asm-defs.h deleted file mode 100644 index 2d9a9c1f2..000000000 --- a/mpi/mips3/mpi-asm-defs.h +++ /dev/null @@ -1,10 +0,0 @@ -/* This file defines some basic constants for the MPI machinery. We - * need to define the types on a per-CPU basis, so it is done with - * this file here. */ -#define BYTES_PER_MPI_LIMB 8 - - - - - - diff --git a/mpi/mips3/mpih-add1.S b/mpi/mips3/mpih-add1.S deleted file mode 100644 index a998420d7..000000000 --- a/mpi/mips3/mpih-add1.S +++ /dev/null @@ -1,124 +0,0 @@ -/* mips3 add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1995, 1998, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, ($4) - * mpi_ptr_t s1_ptr, ($5) - * mpi_ptr_t s2_ptr, ($6) - * mpi_size_t size) ($7) - */ - - .text - .align 2 - .globl mpihelp_add_n - .ent mpihelp_add_n -mpihelp_add_n: - .set noreorder - .set nomacro - - ld $10,0($5) - ld $11,0($6) - - daddiu $7,$7,-1 - and $9,$7,4-1 # number of limbs in first loop - beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop - move $2,$0 - - dsubu $7,$7,$9 - -.Loop0: daddiu $9,$9,-1 - ld $12,8($5) - daddu $11,$11,$2 - ld $13,8($6) - sltu $8,$11,$2 - daddu $11,$10,$11 - sltu $2,$11,$10 - sd $11,0($4) - or $2,$2,$8 - - daddiu $5,$5,8 - daddiu $6,$6,8 - move $10,$12 - move $11,$13 - bne $9,$0,.Loop0 - daddiu $4,$4,8 - -.L0: beq $7,$0,.Lend - nop - -.Loop: daddiu $7,$7,-4 - - ld $12,8($5) - daddu $11,$11,$2 - ld $13,8($6) - sltu $8,$11,$2 - daddu $11,$10,$11 - sltu $2,$11,$10 - sd $11,0($4) - or $2,$2,$8 - - ld $10,16($5) - daddu $13,$13,$2 - ld $11,16($6) - sltu $8,$13,$2 - daddu $13,$12,$13 - sltu $2,$13,$12 - sd $13,8($4) - or $2,$2,$8 - - ld $12,24($5) - daddu $11,$11,$2 - ld $13,24($6) - sltu $8,$11,$2 - daddu $11,$10,$11 - sltu $2,$11,$10 - sd $11,16($4) - or $2,$2,$8 - - ld $10,32($5) - daddu $13,$13,$2 - ld $11,32($6) - sltu $8,$13,$2 - daddu $13,$12,$13 - sltu $2,$13,$12 - sd $13,24($4) - or $2,$2,$8 - - daddiu $5,$5,32 - daddiu $6,$6,32 - - bne $7,$0,.Loop - daddiu $4,$4,32 - -.Lend: daddu $11,$11,$2 - sltu $8,$11,$2 - daddu $11,$10,$11 - sltu $2,$11,$10 - sd $11,0($4) - j $31 - or $2,$2,$8 - - .end mpihelp_add_n - diff --git a/mpi/mips3/mpih-lshift.S b/mpi/mips3/mpih-lshift.S deleted file mode 100644 index 112383f90..000000000 --- a/mpi/mips3/mpih-lshift.S +++ /dev/null @@ -1,97 +0,0 @@ -/* mips3 lshift - * - * Copyright (C) 1995, 1998, 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 - */ - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, ($4) - * mpi_ptr_t up, ($5) - * mpi_size_t usize, ($6) - * unsigned cnt) ($7) - */ - - .text - .align 2 - .globl mpihelp_lshift - .ent mpihelp_lshift -mpihelp_lshift: - .set noreorder - .set nomacro - - dsll $2,$6,3 - daddu $5,$5,$2 # make r5 point at end of src - ld $10,-8($5) # load first limb - dsubu $13,$0,$7 - daddu $4,$4,$2 # make r4 point at end of res - daddiu $6,$6,-1 - and $9,$6,4-1 # number of limbs in first loop - beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop - dsrl $2,$10,$13 # compute function result - - dsubu $6,$6,$9 - -.Loop0: ld $3,-16($5) - daddiu $4,$4,-8 - daddiu $5,$5,-8 - daddiu $9,$9,-1 - dsll $11,$10,$7 - dsrl $12,$3,$13 - move $10,$3 - or $8,$11,$12 - bne $9,$0,.Loop0 - sd $8,0($4) - -.L0: beq $6,$0,.Lend - nop - -.Loop: ld $3,-16($5) - daddiu $4,$4,-32 - daddiu $6,$6,-4 - dsll $11,$10,$7 - dsrl $12,$3,$13 - - ld $10,-24($5) - dsll $14,$3,$7 - or $8,$11,$12 - sd $8,24($4) - dsrl $9,$10,$13 - - ld $3,-32($5) - dsll $11,$10,$7 - or $8,$14,$9 - sd $8,16($4) - dsrl $12,$3,$13 - - ld $10,-40($5) - dsll $14,$3,$7 - or $8,$11,$12 - sd $8,8($4) - dsrl $9,$10,$13 - - daddiu $5,$5,-32 - or $8,$14,$9 - bgtz $6,.Loop - sd $8,0($4) - -.Lend: dsll $8,$10,$7 - j $31 - sd $8,-8($4) - .end mpihelp_lshift diff --git a/mpi/mips3/mpih-mul1.S b/mpi/mips3/mpih-mul1.S deleted file mode 100644 index 70409e8db..000000000 --- a/mpi/mips3/mpih-mul1.S +++ /dev/null @@ -1,89 +0,0 @@ -/* mips3 mpih-mul1.S -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1998, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (r4) - * mpi_ptr_t s1_ptr, (r5) - * mpi_size_t s1_size, (r6) - * mpi_limb_t s2_limb) (r7) - */ - - .text - .align 4 - .globl mpihelp_mul_1 - .ent mpihelp_mul_1 -mpihelp_mul_1: - .set noreorder - .set nomacro - -/* # warm up phase 0 */ - ld $8,0($5) - -/* # warm up phase 1 */ - daddiu $5,$5,8 - dmultu $8,$7 - - daddiu $6,$6,-1 - beq $6,$0,$LC0 - move $2,$0 # zero cy2 - - daddiu $6,$6,-1 - beq $6,$0,$LC1 - ld $8,0($5) # load new s1 limb as early as possible - -Loop: mflo $10 - mfhi $9 - daddiu $5,$5,8 - daddu $10,$10,$2 # add old carry limb to low product limb - dmultu $8,$7 - ld $8,0($5) # load new s1 limb as early as possible - daddiu $6,$6,-1 # decrement loop counter - sltu $2,$10,$2 # carry from previous addition -> $2 - sd $10,0($4) - daddiu $4,$4,8 - bne $6,$0,Loop - daddu $2,$9,$2 # add high product limb and carry from addition - -/* # cool down phase 1 */ -$LC1: mflo $10 - mfhi $9 - daddu $10,$10,$2 - sltu $2,$10,$2 - dmultu $8,$7 - sd $10,0($4) - daddiu $4,$4,8 - daddu $2,$9,$2 # add high product limb and carry from addition - -/* # cool down phase 0 */ -$LC0: mflo $10 - mfhi $9 - daddu $10,$10,$2 - sltu $2,$10,$2 - sd $10,0($4) - j $31 - daddu $2,$9,$2 # add high product limb and carry from addition - - .end mpihelp_mul_1 - diff --git a/mpi/mips3/mpih-mul2.S b/mpi/mips3/mpih-mul2.S deleted file mode 100644 index 1bddd0530..000000000 --- a/mpi/mips3/mpih-mul2.S +++ /dev/null @@ -1,101 +0,0 @@ -/* MIPS3 addmul_1 -- Multiply a limb vector with a single limb and - * add the product to a second limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1998, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r4) - * mpi_ptr_t s1_ptr, (r5) - * mpi_size_t s1_size, (r6) - * mpi_limb_t s2_limb) (r7) - */ - - .text - .align 4 - .globl mpihelp_addmul_1 - .ent mpihelp_addmul_1 -mpihelp_addmul_1: - .set noreorder - .set nomacro - -/* # warm up phase 0 */ - ld $8,0($5) - -/* # warm up phase 1 */ - daddiu $5,$5,8 - dmultu $8,$7 - - daddiu $6,$6,-1 - beq $6,$0,$LC0 - move $2,$0 # zero cy2 - - daddiu $6,$6,-1 - beq $6,$0,$LC1 - ld $8,0($5) # load new s1 limb as early as possible - -Loop: ld $10,0($4) - mflo $3 - mfhi $9 - daddiu $5,$5,8 - daddu $3,$3,$2 # add old carry limb to low product limb - dmultu $8,$7 - ld $8,0($5) # load new s1 limb as early as possible - daddiu $6,$6,-1 # decrement loop counter - sltu $2,$3,$2 # carry from previous addition -> $2 - daddu $3,$10,$3 - sltu $10,$3,$10 - daddu $2,$2,$10 - sd $3,0($4) - daddiu $4,$4,8 - bne $6,$0,Loop - daddu $2,$9,$2 # add high product limb and carry from addition - -/* # cool down phase 1 */ -$LC1: ld $10,0($4) - mflo $3 - mfhi $9 - daddu $3,$3,$2 - sltu $2,$3,$2 - dmultu $8,$7 - daddu $3,$10,$3 - sltu $10,$3,$10 - daddu $2,$2,$10 - sd $3,0($4) - daddiu $4,$4,8 - daddu $2,$9,$2 # add high product limb and carry from addition - -/* # cool down phase 0 */ -$LC0: ld $10,0($4) - mflo $3 - mfhi $9 - daddu $3,$3,$2 - sltu $2,$3,$2 - daddu $3,$10,$3 - sltu $10,$3,$10 - daddu $2,$2,$10 - sd $3,0($4) - j $31 - daddu $2,$9,$2 # add high product limb and carry from addition - - .end mpihelp_addmul_1 - diff --git a/mpi/mips3/mpih-mul3.S b/mpi/mips3/mpih-mul3.S deleted file mode 100644 index 82fe47d53..000000000 --- a/mpi/mips3/mpih-mul3.S +++ /dev/null @@ -1,101 +0,0 @@ -/* MIPS3 submul_1 -- Multiply a limb vector with a single limb and - * subtract the product from a second limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1998, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (r4) - * mpi_ptr_t s1_ptr, (r5) - * mpi_size_t s1_size, (r6) - * mpi_limb_t s2_limb) (r7) - */ - - .text - .align 4 - .globl mpihelp_submul_1 - .ent mpihelp_submul_1 -mpihelp_submul_1: - .set noreorder - .set nomacro - -/* # warm up phase 0 */ - ld $8,0($5) - -/* # warm up phase 1 */ - daddiu $5,$5,8 - dmultu $8,$7 - - daddiu $6,$6,-1 - beq $6,$0,$LC0 - move $2,$0 # zero cy2 - - daddiu $6,$6,-1 - beq $6,$0,$LC1 - ld $8,0($5) # load new s1 limb as early as possible - -Loop: ld $10,0($4) - mflo $3 - mfhi $9 - daddiu $5,$5,8 - daddu $3,$3,$2 # add old carry limb to low product limb - dmultu $8,$7 - ld $8,0($5) # load new s1 limb as early as possible - daddiu $6,$6,-1 # decrement loop counter - sltu $2,$3,$2 # carry from previous addition -> $2 - dsubu $3,$10,$3 - sgtu $10,$3,$10 - daddu $2,$2,$10 - sd $3,0($4) - daddiu $4,$4,8 - bne $6,$0,Loop - daddu $2,$9,$2 # add high product limb and carry from addition - -/* # cool down phase 1 */ -$LC1: ld $10,0($4) - mflo $3 - mfhi $9 - daddu $3,$3,$2 - sltu $2,$3,$2 - dmultu $8,$7 - dsubu $3,$10,$3 - sgtu $10,$3,$10 - daddu $2,$2,$10 - sd $3,0($4) - daddiu $4,$4,8 - daddu $2,$9,$2 # add high product limb and carry from addition - -/* # cool down phase 0 */ -$LC0: ld $10,0($4) - mflo $3 - mfhi $9 - daddu $3,$3,$2 - sltu $2,$3,$2 - dsubu $3,$10,$3 - sgtu $10,$3,$10 - daddu $2,$2,$10 - sd $3,0($4) - j $31 - daddu $2,$9,$2 # add high product limb and carry from addition - - .end mpihelp_submul_1 - diff --git a/mpi/mips3/mpih-rshift.S b/mpi/mips3/mpih-rshift.S deleted file mode 100644 index 74a6cc96d..000000000 --- a/mpi/mips3/mpih-rshift.S +++ /dev/null @@ -1,95 +0,0 @@ -/* mips3 rshift - * - * Copyright (C) 1995, 1998, 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 - */ - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, ($4) - * mpi_ptr_t up, ($5) - * mpi_size_t usize, ($6) - * unsigned cnt) ($7) - */ - - .text - .align 2 - .globl mpihelp_rshift - .ent mpihelp_rshift -mpihelp_rshift: - .set noreorder - .set nomacro - - ld $10,0($5) # load first limb - dsubu $13,$0,$7 - daddiu $6,$6,-1 - and $9,$6,4-1 # number of limbs in first loop - beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop - dsll $2,$10,$13 # compute function result - - dsubu $6,$6,$9 - -.Loop0: ld $3,8($5) - daddiu $4,$4,8 - daddiu $5,$5,8 - daddiu $9,$9,-1 - dsrl $11,$10,$7 - dsll $12,$3,$13 - move $10,$3 - or $8,$11,$12 - bne $9,$0,.Loop0 - sd $8,-8($4) - -.L0: beq $6,$0,.Lend - nop - -.Loop: ld $3,8($5) - daddiu $4,$4,32 - daddiu $6,$6,-4 - dsrl $11,$10,$7 - dsll $12,$3,$13 - - ld $10,16($5) - dsrl $14,$3,$7 - or $8,$11,$12 - sd $8,-32($4) - dsll $9,$10,$13 - - ld $3,24($5) - dsrl $11,$10,$7 - or $8,$14,$9 - sd $8,-24($4) - dsll $12,$3,$13 - - ld $10,32($5) - dsrl $14,$3,$7 - or $8,$11,$12 - sd $8,-16($4) - dsll $9,$10,$13 - - daddiu $5,$5,32 - or $8,$14,$9 - bgtz $6,.Loop - sd $8,-8($4) - -.Lend: dsrl $8,$10,$7 - j $31 - sd $8,0($4) - .end mpihelp_rshift - diff --git a/mpi/mips3/mpih-sub1.S b/mpi/mips3/mpih-sub1.S deleted file mode 100644 index 72f506ea2..000000000 --- a/mpi/mips3/mpih-sub1.S +++ /dev/null @@ -1,125 +0,0 @@ -/* mips3 sub_n -- Subtract two limb vectors of the same length > 0 and - * store difference in a third limb vector. - * - * Copyright (C) 1995, 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 - */ - - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (r4) - * mpi_ptr_t s1_ptr, (r5) - * mpi_ptr_t s2_ptr, (r6) - * mpi_size_t size) (r7) - */ - - - .text - .align 2 - .globl mpihelp_sub_n - .ent mpihelp_sub_n -mpihelp_sub_n: - .set noreorder - .set nomacro - - ld $10,0($5) - ld $11,0($6) - - daddiu $7,$7,-1 - and $9,$7,4-1 # number of limbs in first loop - beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop - move $2,$0 - - dsubu $7,$7,$9 - -.Loop0: daddiu $9,$9,-1 - ld $12,8($5) - daddu $11,$11,$2 - ld $13,8($6) - sltu $8,$11,$2 - dsubu $11,$10,$11 - sltu $2,$10,$11 - sd $11,0($4) - or $2,$2,$8 - - daddiu $5,$5,8 - daddiu $6,$6,8 - move $10,$12 - move $11,$13 - bne $9,$0,.Loop0 - daddiu $4,$4,8 - -.L0: beq $7,$0,.Lend - nop - -.Loop: daddiu $7,$7,-4 - - ld $12,8($5) - daddu $11,$11,$2 - ld $13,8($6) - sltu $8,$11,$2 - dsubu $11,$10,$11 - sltu $2,$10,$11 - sd $11,0($4) - or $2,$2,$8 - - ld $10,16($5) - daddu $13,$13,$2 - ld $11,16($6) - sltu $8,$13,$2 - dsubu $13,$12,$13 - sltu $2,$12,$13 - sd $13,8($4) - or $2,$2,$8 - - ld $12,24($5) - daddu $11,$11,$2 - ld $13,24($6) - sltu $8,$11,$2 - dsubu $11,$10,$11 - sltu $2,$10,$11 - sd $11,16($4) - or $2,$2,$8 - - ld $10,32($5) - daddu $13,$13,$2 - ld $11,32($6) - sltu $8,$13,$2 - dsubu $13,$12,$13 - sltu $2,$12,$13 - sd $13,24($4) - or $2,$2,$8 - - daddiu $5,$5,32 - daddiu $6,$6,32 - - bne $7,$0,.Loop - daddiu $4,$4,32 - -.Lend: daddu $11,$11,$2 - sltu $8,$11,$2 - dsubu $11,$10,$11 - sltu $2,$10,$11 - sd $11,0($4) - j $31 - or $2,$2,$8 - - .end mpihelp_sub_n - diff --git a/mpi/mpi-add.c b/mpi/mpi-add.c deleted file mode 100644 index bbd1ac70e..000000000 --- a/mpi/mpi-add.c +++ /dev/null @@ -1,247 +0,0 @@ -/* mpi-add.c - MPI functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * Copyright (C) 1994, 1996 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include - -#include "mpi-internal.h" - - -/**************** - * Add the unsigned integer V to the mpi-integer U and store the - * result in W. U and V may be the same. - */ -void -mpi_add_ui(MPI w, MPI u, unsigned long v ) -{ - mpi_ptr_t wp, up; - mpi_size_t usize, wsize; - int usign, wsign; - - usize = u->nlimbs; - usign = u->sign; - wsign = 0; - - /* If not space for W (and possible carry), increase space. */ - wsize = usize + 1; - if( w->alloced < wsize ) - mpi_resize(w, wsize); - - /* These must be after realloc (U may be the same as W). */ - up = u->d; - wp = w->d; - - if( !usize ) { /* simple */ - wp[0] = v; - wsize = v? 1:0; - } - else if( !usign ) { /* mpi is not negative */ - mpi_limb_t cy; - cy = mpihelp_add_1(wp, up, usize, v); - wp[usize] = cy; - wsize = usize + cy; - } - else { /* The signs are different. Need exact comparison to determine - * which operand to subtract from which. */ - if( usize == 1 && up[0] < v ) { - wp[0] = v - up[0]; - wsize = 1; - } - else { - mpihelp_sub_1(wp, up, usize, v); - /* Size can decrease with at most one limb. */ - wsize = usize - (wp[usize-1]==0); - wsign = 1; - } - } - - w->nlimbs = wsize; - w->sign = wsign; -} - - -void -mpi_add(MPI w, MPI u, MPI v) -{ - mpi_ptr_t wp, up, vp; - mpi_size_t usize, vsize, wsize; - int usign, vsign, wsign; - - if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ - usize = v->nlimbs; - usign = v->sign; - vsize = u->nlimbs; - vsign = u->sign; - wsize = usize + 1; - RESIZE_IF_NEEDED(w, wsize); - /* These must be after realloc (u or v may be the same as w). */ - up = v->d; - vp = u->d; - } - else { - usize = u->nlimbs; - usign = u->sign; - vsize = v->nlimbs; - vsign = v->sign; - wsize = usize + 1; - RESIZE_IF_NEEDED(w, wsize); - /* These must be after realloc (u or v may be the same as w). */ - up = u->d; - vp = v->d; - } - wp = w->d; - wsign = 0; - - if( !vsize ) { /* simple */ - MPN_COPY(wp, up, usize ); - wsize = usize; - wsign = usign; - } - else if( usign != vsign ) { /* different sign */ - /* This test is right since USIZE >= VSIZE */ - if( usize != vsize ) { - mpihelp_sub(wp, up, usize, vp, vsize); - wsize = usize; - MPN_NORMALIZE(wp, wsize); - wsign = usign; - } - else if( mpihelp_cmp(up, vp, usize) < 0 ) { - mpihelp_sub_n(wp, vp, up, usize); - wsize = usize; - MPN_NORMALIZE(wp, wsize); - if( !usign ) - wsign = 1; - } - else { - mpihelp_sub_n(wp, up, vp, usize); - wsize = usize; - MPN_NORMALIZE(wp, wsize); - if( usign ) - wsign = 1; - } - } - else { /* U and V have same sign. Add them. */ - mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize); - wp[usize] = cy; - wsize = usize + cy; - if( usign ) - wsign = 1; - } - - w->nlimbs = wsize; - w->sign = wsign; -} - - -/**************** - * Subtract the unsigned integer V from the mpi-integer U and store the - * result in W. - */ -void -mpi_sub_ui(MPI w, MPI u, unsigned long v ) -{ - mpi_ptr_t wp, up; - mpi_size_t usize, wsize; - int usign, wsign; - - usize = u->nlimbs; - usign = u->sign; - wsign = 0; - - /* If not space for W (and possible carry), increase space. */ - wsize = usize + 1; - if( w->alloced < wsize ) - mpi_resize(w, wsize); - - /* These must be after realloc (U may be the same as W). */ - up = u->d; - wp = w->d; - - if( !usize ) { /* simple */ - wp[0] = v; - wsize = v? 1:0; - wsign = 1; - } - else if( usign ) { /* mpi and v are negative */ - mpi_limb_t cy; - cy = mpihelp_add_1(wp, up, usize, v); - wp[usize] = cy; - wsize = usize + cy; - } - else { /* The signs are different. Need exact comparison to determine - * which operand to subtract from which. */ - if( usize == 1 && up[0] < v ) { - wp[0] = v - up[0]; - wsize = 1; - wsign = 1; - } - else { - mpihelp_sub_1(wp, up, usize, v); - /* Size can decrease with at most one limb. */ - wsize = usize - (wp[usize-1]==0); - } - } - - w->nlimbs = wsize; - w->sign = wsign; -} - -void -mpi_sub(MPI w, MPI u, MPI v) -{ - if( w == v ) { - MPI vv = mpi_copy(v); - vv->sign = !vv->sign; - mpi_add( w, u, vv ); - mpi_free(vv); - } - else { - /* fixme: this is not thread-save (we temp. modify v) */ - v->sign = !v->sign; - mpi_add( w, u, v ); - v->sign = !v->sign; - } -} - - -void -mpi_addm( MPI w, MPI u, MPI v, MPI m) -{ - mpi_add(w, u, v); - mpi_fdiv_r( w, w, m ); -} - -void -mpi_subm( MPI w, MPI u, MPI v, MPI m) -{ - mpi_sub(w, u, v); - mpi_fdiv_r( w, w, m ); -} - diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c deleted file mode 100644 index 440e35212..000000000 --- a/mpi/mpi-bit.c +++ /dev/null @@ -1,255 +0,0 @@ -/* mpi-bit.c - MPI bit level fucntions - * Copyright (C) 1998, 1999 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 -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - - -#ifdef MPI_INTERNAL_NEED_CLZ_TAB -#ifdef __STDC__ -const -#endif -unsigned char -__clz_tab[] = -{ - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -}; -#endif - - -#define A_LIMB_1 ((mpi_limb_t)1) - - -/**************** - * Sometimes we have MSL (most significant limbs) which are 0; - * this is for some reasons not good, so this function removes them. - */ -void -mpi_normalize( MPI a ) -{ - if( mpi_is_opaque (a) ) - return; - - for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ) - ; -} - - - -/**************** - * Return the number of bits in A. - */ -unsigned -mpi_get_nbits( MPI a ) -{ - unsigned n; - - mpi_normalize( a ); - if( a->nlimbs ) { - mpi_limb_t alimb = a->d[a->nlimbs-1]; - if( alimb ) - count_leading_zeros( n, alimb ); - else - n = BITS_PER_MPI_LIMB; - n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB; - } - else - n = 0; - return n; -} - - -/**************** - * Test whether bit N is set. - */ -int -mpi_test_bit( MPI a, unsigned n ) -{ - unsigned limbno, bitno; - mpi_limb_t limb; - - limbno = n / BITS_PER_MPI_LIMB; - bitno = n % BITS_PER_MPI_LIMB; - - if( limbno >= a->nlimbs ) - return 0; /* too far left: this is a 0 */ - limb = a->d[limbno]; - return (limb & (A_LIMB_1 << bitno))? 1: 0; -} - - -/**************** - * Set bit N of A. - */ -void -mpi_set_bit( MPI a, unsigned n ) -{ - unsigned limbno, bitno; - - limbno = n / BITS_PER_MPI_LIMB; - bitno = n % BITS_PER_MPI_LIMB; - - if( limbno >= a->nlimbs ) { /* resize */ - if( a->alloced >= limbno ) - mpi_resize(a, limbno+1 ); - a->nlimbs = limbno+1; - } - a->d[limbno] |= (A_LIMB_1<= a->nlimbs ) { /* resize */ - if( a->alloced >= limbno ) - mpi_resize(a, limbno+1 ); - a->nlimbs = limbno+1; - } - a->d[limbno] |= (A_LIMB_1<d[limbno] &= ~(A_LIMB_1 << bitno); - a->nlimbs = limbno+1; -} - -/**************** - * clear bit N of A and all bits above - */ -void -mpi_clear_highbit( MPI a, unsigned n ) -{ - unsigned limbno, bitno; - - limbno = n / BITS_PER_MPI_LIMB; - bitno = n % BITS_PER_MPI_LIMB; - - if( limbno >= a->nlimbs ) - return; /* not allocated, so need to clear bits :-) */ - - for( ; bitno < BITS_PER_MPI_LIMB; bitno++ ) - a->d[limbno] &= ~(A_LIMB_1 << bitno); - a->nlimbs = limbno+1; -} - -/**************** - * Clear bit N of A. - */ -void -mpi_clear_bit( MPI a, unsigned n ) -{ - unsigned limbno, bitno; - - limbno = n / BITS_PER_MPI_LIMB; - bitno = n % BITS_PER_MPI_LIMB; - - if( limbno >= a->nlimbs ) - return; /* don't need to clear this bit, it's to far to left */ - a->d[limbno] &= ~(A_LIMB_1 << bitno); -} - - -/**************** - * Shift A by N bits to the right - * FIXME: should use alloc_limb if X and A are same. - */ -void -mpi_rshift( MPI x, MPI a, unsigned n ) -{ - mpi_ptr_t xp; - mpi_size_t xsize; - - xsize = a->nlimbs; - x->sign = a->sign; - RESIZE_IF_NEEDED(x, xsize); - xp = x->d; - - if( xsize ) { - mpihelp_rshift( xp, a->d, xsize, n); - MPN_NORMALIZE( xp, xsize); - } - x->nlimbs = xsize; -} - - -/**************** - * Shift A by COUNT limbs to the left - * This is used only within the MPI library - */ -void -mpi_lshift_limbs( MPI a, unsigned int count ) -{ - mpi_ptr_t ap = a->d; - int n = a->nlimbs; - int i; - - if( !count || !n ) - return; - - RESIZE_IF_NEEDED( a, n+count ); - - for( i = n-1; i >= 0; i-- ) - ap[i+count] = ap[i]; - for(i=0; i < count; i++ ) - ap[i] = 0; - a->nlimbs += count; -} - - -/**************** - * Shift A by COUNT limbs to the right - * This is used only within the MPI library - */ -void -mpi_rshift_limbs( MPI a, unsigned int count ) -{ - mpi_ptr_t ap = a->d; - mpi_size_t n = a->nlimbs; - unsigned int i; - - if( count >= n ) { - a->nlimbs = 0; - return; - } - - for( i = 0; i < n - count; i++ ) - ap[i] = ap[i+count]; - ap[i] = 0; - a->nlimbs -= count; -} - - diff --git a/mpi/mpi-cmp.c b/mpi/mpi-cmp.c deleted file mode 100644 index 612198885..000000000 --- a/mpi/mpi-cmp.c +++ /dev/null @@ -1,74 +0,0 @@ -/* mpi-cmp.c - MPI functions - * Copyright (C) 1998, 1999 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 -#include -#include -#include "mpi-internal.h" - -int -mpi_cmp_ui( MPI u, unsigned long v ) -{ - mpi_limb_t limb = v; - - mpi_normalize( u ); - if( !u->nlimbs && !limb ) - return 0; - if( u->sign ) - return -1; - if( u->nlimbs > 1 ) - return 1; - - if( u->d[0] == limb ) - return 0; - else if( u->d[0] > limb ) - return 1; - else - return -1; -} - -int -mpi_cmp( MPI u, MPI v ) -{ - mpi_size_t usize, vsize; - int cmp; - - mpi_normalize( u ); - mpi_normalize( v ); - usize = u->nlimbs; - vsize = v->nlimbs; - if( !u->sign && v->sign ) - return 1; - if( u->sign && !v->sign ) - return -1; - if( usize != vsize && !u->sign && !v->sign ) - return usize - vsize; - if( usize != vsize && u->sign && v->sign ) - return vsize + usize; - if( !usize ) - return 0; - if( !(cmp=mpihelp_cmp( u->d, v->d, usize )) ) - return 0; - if( (cmp < 0?1:0) == (u->sign?1:0)) - return 1; - return -1; -} - - diff --git a/mpi/mpi-div.c b/mpi/mpi-div.c deleted file mode 100644 index a86df2daf..000000000 --- a/mpi/mpi-div.c +++ /dev/null @@ -1,322 +0,0 @@ -/* mpi-div.c - MPI functions - * Copyright (C) 1994, 1996 Free Software Foundation, Inc. - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - - - -void -mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ) -{ - int divisor_sign = divisor->sign; - MPI temp_divisor = NULL; - - /* We need the original value of the divisor after the remainder has been - * preliminary calculated. We have to copy it to temporary space if it's - * the same variable as REM. */ - if( rem == divisor ) { - temp_divisor = mpi_copy( divisor ); - divisor = temp_divisor; - } - - mpi_tdiv_r( rem, dividend, divisor ); - - if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) - mpi_add( rem, rem, divisor); - - if( temp_divisor ) - mpi_free(temp_divisor); -} - - - -/**************** - * Division rounding the quotient towards -infinity. - * The remainder gets the same sign as the denominator. - * rem is optional - */ - -ulong -mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ) -{ - mpi_limb_t rlimb; - - rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); - if( rlimb && dividend->sign ) - rlimb = divisor - rlimb; - - if( rem ) { - rem->d[0] = rlimb; - rem->nlimbs = rlimb? 1:0; - } - return rlimb; -} - - -void -mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ) -{ - MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) ); - mpi_fdiv_qr( quot, tmp, dividend, divisor); - mpi_free(tmp); -} - -void -mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) -{ - int divisor_sign = divisor->sign; - MPI temp_divisor = NULL; - - if( quot == divisor || rem == divisor ) { - temp_divisor = mpi_copy( divisor ); - divisor = temp_divisor; - } - - mpi_tdiv_qr( quot, rem, dividend, divisor ); - - if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { - mpi_sub_ui( quot, quot, 1 ); - mpi_add( rem, rem, divisor); - } - - if( temp_divisor ) - mpi_free(temp_divisor); -} - - -/* If den == quot, den needs temporary storage. - * If den == rem, den needs temporary storage. - * If num == quot, num needs temporary storage. - * If den has temporary storage, it can be normalized while being copied, - * i.e no extra storage should be allocated. - */ - -void -mpi_tdiv_r( MPI rem, MPI num, MPI den) -{ - mpi_tdiv_qr(NULL, rem, num, den ); -} - -void -mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den) -{ - mpi_ptr_t np, dp; - mpi_ptr_t qp, rp; - mpi_size_t nsize = num->nlimbs; - mpi_size_t dsize = den->nlimbs; - mpi_size_t qsize, rsize; - mpi_size_t sign_remainder = num->sign; - mpi_size_t sign_quotient = num->sign ^ den->sign; - unsigned normalization_steps; - mpi_limb_t q_limb; - mpi_ptr_t marker[5]; - int markidx=0; - - /* Ensure space is enough for quotient and remainder. - * We need space for an extra limb in the remainder, because it's - * up-shifted (normalized) below. */ - rsize = nsize + 1; - mpi_resize( rem, rsize); - - qsize = rsize - dsize; /* qsize cannot be bigger than this. */ - if( qsize <= 0 ) { - if( num != rem ) { - rem->nlimbs = num->nlimbs; - rem->sign = num->sign; - MPN_COPY(rem->d, num->d, nsize); - } - if( quot ) { - /* This needs to follow the assignment to rem, in case the - * numerator and quotient are the same. */ - quot->nlimbs = 0; - quot->sign = 0; - } - return; - } - - if( quot ) - mpi_resize( quot, qsize); - - /* Read pointers here, when reallocation is finished. */ - np = num->d; - dp = den->d; - rp = rem->d; - - /* Optimize division by a single-limb divisor. */ - if( dsize == 1 ) { - mpi_limb_t rlimb; - if( quot ) { - qp = quot->d; - rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] ); - qsize -= qp[qsize - 1] == 0; - quot->nlimbs = qsize; - quot->sign = sign_quotient; - } - else - rlimb = mpihelp_mod_1( np, nsize, dp[0] ); - rp[0] = rlimb; - rsize = rlimb != 0?1:0; - rem->nlimbs = rsize; - rem->sign = sign_remainder; - return; - } - - - if( quot ) { - qp = quot->d; - /* Make sure QP and NP point to different objects. Otherwise the - * numerator would be gradually overwritten by the quotient limbs. */ - if(qp == np) { /* Copy NP object to temporary space. */ - np = marker[markidx++] = mpi_alloc_limb_space(nsize, - mpi_is_secure(quot)); - MPN_COPY(np, qp, nsize); - } - } - else /* Put quotient at top of remainder. */ - qp = rp + dsize; - - count_leading_zeros( normalization_steps, dp[dsize - 1] ); - - /* Normalize the denominator, i.e. make its most significant bit set by - * shifting it NORMALIZATION_STEPS bits to the left. Also shift the - * numerator the same number of steps (to keep the quotient the same!). - */ - if( normalization_steps ) { - mpi_ptr_t tp; - mpi_limb_t nlimb; - - /* Shift up the denominator setting the most significant bit of - * the most significant word. Use temporary storage not to clobber - * the original contents of the denominator. */ - tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den)); - mpihelp_lshift( tp, dp, dsize, normalization_steps ); - dp = tp; - - /* Shift up the numerator, possibly introducing a new most - * significant word. Move the shifted numerator in the remainder - * meanwhile. */ - nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps); - if( nlimb ) { - rp[nsize] = nlimb; - rsize = nsize + 1; - } - else - rsize = nsize; - } - else { - /* The denominator is already normalized, as required. Copy it to - * temporary space if it overlaps with the quotient or remainder. */ - if( dp == rp || (quot && (dp == qp))) { - mpi_ptr_t tp; - - tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den)); - MPN_COPY( tp, dp, dsize ); - dp = tp; - } - - /* Move the numerator to the remainder. */ - if( rp != np ) - MPN_COPY(rp, np, nsize); - - rsize = nsize; - } - - q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize ); - - if( quot ) { - qsize = rsize - dsize; - if(q_limb) { - qp[qsize] = q_limb; - qsize += 1; - } - - quot->nlimbs = qsize; - quot->sign = sign_quotient; - } - - rsize = dsize; - MPN_NORMALIZE (rp, rsize); - - if( normalization_steps && rsize ) { - mpihelp_rshift(rp, rp, rsize, normalization_steps); - rsize -= rp[rsize - 1] == 0?1:0; - } - - rem->nlimbs = rsize; - rem->sign = sign_remainder; - while( markidx ) - mpi_free_limb_space(marker[--markidx]); -} - -void -mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ) -{ - mpi_size_t usize, wsize; - mpi_size_t limb_cnt; - - usize = u->nlimbs; - limb_cnt = count / BITS_PER_MPI_LIMB; - wsize = usize - limb_cnt; - if( limb_cnt >= usize ) - w->nlimbs = 0; - else { - mpi_ptr_t wp; - mpi_ptr_t up; - - RESIZE_IF_NEEDED( w, wsize ); - wp = w->d; - up = u->d; - - count %= BITS_PER_MPI_LIMB; - if( count ) { - mpihelp_rshift( wp, up + limb_cnt, wsize, count ); - wsize -= !wp[wsize - 1]; - } - else { - MPN_COPY_INCR( wp, up + limb_cnt, wsize); - } - - w->nlimbs = wsize; - } -} - -/**************** - * Check whether dividend is divisible by divisor - * (note: divisor must fit into a limb) - */ -int -mpi_divisible_ui(MPI dividend, ulong divisor ) -{ - return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); -} - diff --git a/mpi/mpi-gcd.c b/mpi/mpi-gcd.c deleted file mode 100644 index efd703b32..000000000 --- a/mpi/mpi-gcd.c +++ /dev/null @@ -1,54 +0,0 @@ -/* mpi-gcd.c - MPI 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 -#include -#include -#include "mpi-internal.h" - -/**************** - * Find the greatest common divisor G of A and B. - * Return: true if this 1, false in all other cases - */ -int -mpi_gcd( MPI g, MPI xa, MPI xb ) -{ - MPI a, b; - - a = mpi_copy(xa); - b = mpi_copy(xb); - - /* TAOCP Vol II, 4.5.2, Algorithm A */ - a->sign = 0; - b->sign = 0; - while( mpi_cmp_ui( b, 0 ) ) { - mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ - mpi_set(a,b); - mpi_set(b,g); - } - mpi_set(g, a); - - mpi_free(a); - mpi_free(b); - return !mpi_cmp_ui( g, 1); -} - - - diff --git a/mpi/mpi-inline.c b/mpi/mpi-inline.c deleted file mode 100644 index 787d897dd..000000000 --- a/mpi/mpi-inline.c +++ /dev/null @@ -1,36 +0,0 @@ -/* mpi-inline.c - * Copyright (C) 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 -#include -#include - -/* put the inline functions as real functions into the lib */ -#define G10_MPI_INLINE_DECL - -#include "mpi-internal.h" - -/* always include the header becuase it is only - * included by mpi-internal if __GCC__ is defined but we - * need it here in all cases and the above definition of - * of the macro allows us to do so - */ -#include "mpi-inline.h" - diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h deleted file mode 100644 index 02481b67c..000000000 --- a/mpi/mpi-inline.h +++ /dev/null @@ -1,128 +0,0 @@ -/* mpi-inline.h - Internal to the Multi Precision Integers - * Copyright (C) 1994, 1996, 1998, 1999 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#ifndef G10_MPI_INLINE_H -#define G10_MPI_INLINE_H - -#ifndef G10_MPI_INLINE_DECL - #define G10_MPI_INLINE_DECL extern __inline__ -#endif - -G10_MPI_INLINE_DECL mpi_limb_t -mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb) -{ - mpi_limb_t x; - - x = *s1_ptr++; - s2_limb += x; - *res_ptr++ = s2_limb; - if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ - while( --s1_size ) { - x = *s1_ptr++ + 1; /* add carry */ - *res_ptr++ = x; /* and store */ - if( x ) /* not 0 (no overflow): we can stop */ - goto leave; - } - return 1; /* return carry (size of s1 to small) */ - } - - leave: - if( res_ptr != s1_ptr ) { /* not the same variable */ - mpi_size_t i; /* copy the rest */ - for( i=0; i < s1_size-1; i++ ) - res_ptr[i] = s1_ptr[i]; - } - return 0; /* no carry */ -} - - - -G10_MPI_INLINE_DECL mpi_limb_t -mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, - mpi_ptr_t s2_ptr, mpi_size_t s2_size) -{ - mpi_limb_t cy = 0; - - if( s2_size ) - cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); - - if( s1_size - s2_size ) - cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size, - s1_size - s2_size, cy); - return cy; -} - - -G10_MPI_INLINE_DECL mpi_limb_t -mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb ) -{ - mpi_limb_t x; - - x = *s1_ptr++; - s2_limb = x - s2_limb; - *res_ptr++ = s2_limb; - if( s2_limb > x ) { - while( --s1_size ) { - x = *s1_ptr++; - *res_ptr++ = x - 1; - if( x ) - goto leave; - } - return 1; - } - - leave: - if( res_ptr != s1_ptr ) { - mpi_size_t i; - for( i=0; i < s1_size-1; i++ ) - res_ptr[i] = s1_ptr[i]; - } - return 0; -} - - - -G10_MPI_INLINE_DECL mpi_limb_t -mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, - mpi_ptr_t s2_ptr, mpi_size_t s2_size) -{ - mpi_limb_t cy = 0; - - if( s2_size ) - cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); - - if( s1_size - s2_size ) - cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size, - s1_size - s2_size, cy); - return cy; -} - - -#endif /*G10_MPI_INLINE_H*/ diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h deleted file mode 100644 index 60d9e09ee..000000000 --- a/mpi/mpi-internal.h +++ /dev/null @@ -1,259 +0,0 @@ -/* mpi-internal.h - Internal to the Multi Precision Integers - * Copyright (C) 1994, 1996 Free Software Foundation, Inc. - * Copyright (C) 1998, 2000 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#ifndef G10_MPI_INTERNAL_H -#define G10_MPI_INTERNAL_H - -#include "mpi.h" - -/* If KARATSUBA_THRESHOLD is not already defined, define it to a - * value which is good on most machines. */ - -/* tested 4, 16, 32 and 64, where 16 gave the best performance when - * checking a 768 and a 1024 bit ElGamal signature. - * (wk 22.12.97) */ -#ifndef KARATSUBA_THRESHOLD - #define KARATSUBA_THRESHOLD 16 -#endif - -/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ -#if KARATSUBA_THRESHOLD < 2 - #undef KARATSUBA_THRESHOLD - #define KARATSUBA_THRESHOLD 2 -#endif - - -typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */ -typedef int mpi_size_t; /* (must be a signed type) */ - -#define ABS(x) (x >= 0 ? x : -x) -#define MIN(l,o) ((l) < (o) ? (l) : (o)) -#define MAX(h,i) ((h) > (i) ? (h) : (i)) -#define RESIZE_IF_NEEDED(a,b) \ - do { \ - if( (a)->alloced < (b) ) \ - mpi_resize((a), (b)); \ - } while(0) - -/* Copy N limbs from S to D. */ -#define MPN_COPY( d, s, n) \ - do { \ - mpi_size_t _i; \ - for( _i = 0; _i < (n); _i++ ) \ - (d)[_i] = (s)[_i]; \ - } while(0) - -#define MPN_COPY_INCR( d, s, n) \ - do { \ - mpi_size_t _i; \ - for( _i = 0; _i < (n); _i++ ) \ - (d)[_i] = (d)[_i]; \ - } while (0) - -#define MPN_COPY_DECR( d, s, n ) \ - do { \ - mpi_size_t _i; \ - for( _i = (n)-1; _i >= 0; _i--) \ - (d)[_i] = (s)[_i]; \ - } while(0) - -/* Zero N limbs at D */ -#define MPN_ZERO(d, n) \ - do { \ - int _i; \ - for( _i = 0; _i < (n); _i++ ) \ - (d)[_i] = 0; \ - } while (0) - -#define MPN_NORMALIZE(d, n) \ - do { \ - while( (n) > 0 ) { \ - if( (d)[(n)-1] ) \ - break; \ - (n)--; \ - } \ - } while(0) - -#define MPN_NORMALIZE_NOT_ZERO(d, n) \ - do { \ - for(;;) { \ - if( (d)[(n)-1] ) \ - break; \ - (n)--; \ - } \ - } while(0) - -#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ - do { \ - if( (size) < KARATSUBA_THRESHOLD ) \ - mul_n_basecase (prodp, up, vp, size); \ - else \ - mul_n (prodp, up, vp, size, tspace); \ - } while (0); - - -/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest - * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). - * If this would yield overflow, DI should be the largest possible number - * (i.e., only ones). For correct operation, the most significant bit of D - * has to be set. Put the quotient in Q and the remainder in R. - */ -#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ - do { \ - mpi_limb_t _q, _ql, _r; \ - mpi_limb_t _xh, _xl; \ - umul_ppmm (_q, _ql, (nh), (di)); \ - _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ - umul_ppmm (_xh, _xl, _q, (d)); \ - sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ - if( _xh ) { \ - sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ - _q++; \ - if( _xh) { \ - sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ - _q++; \ - } \ - } \ - if( _r >= (d) ) { \ - _r -= (d); \ - _q++; \ - } \ - (r) = _r; \ - (q) = _q; \ - } while (0) - - -/*-- mpiutil.c --*/ -#ifdef M_DEBUG - #define mpi_alloc_limb_space(n,f) mpi_debug_alloc_limb_space((n),(f), M_DBGINFO( __LINE__ ) ) - #define mpi_free_limb_space(n) mpi_debug_free_limb_space((n), M_DBGINFO( __LINE__ ) ) - mpi_ptr_t mpi_debug_alloc_limb_space( unsigned nlimbs, int sec, const char *info ); - void mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ); -#else - mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs, int sec ); - void mpi_free_limb_space( mpi_ptr_t a ); -#endif -void mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ); - -/*-- mpi-bit.c --*/ -void mpi_rshift_limbs( MPI a, unsigned int count ); -void mpi_lshift_limbs( MPI a, unsigned int count ); - - -/*-- mpihelp-add.c --*/ -mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb ); -mpi_limb_t mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_ptr_t s2_ptr, mpi_size_t size); -mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, - mpi_ptr_t s2_ptr, mpi_size_t s2_size); - -/*-- mpihelp-sub.c --*/ -mpi_limb_t mpihelp_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb ); -mpi_limb_t mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_ptr_t s2_ptr, mpi_size_t size); -mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, - mpi_ptr_t s2_ptr, mpi_size_t s2_size); - -/*-- mpihelp-cmp.c --*/ -int mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); - -/*-- mpihelp-mul.c --*/ - -struct karatsuba_ctx { - struct karatsuba_ctx *next; - mpi_ptr_t tspace; - mpi_size_t tspace_size; - mpi_ptr_t tp; - mpi_size_t tp_size; -}; - -void mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ); - -mpi_limb_t mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb); -mpi_limb_t mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb); -void mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, - mpi_size_t size); -mpi_limb_t mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, - mpi_ptr_t vp, mpi_size_t vsize); -void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ); -void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, - mpi_ptr_t tspace); - -void mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, - mpi_ptr_t up, mpi_size_t usize, - mpi_ptr_t vp, mpi_size_t vsize, - struct karatsuba_ctx *ctx ); - - -/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/ -mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, - mpi_size_t s1_size, mpi_limb_t s2_limb); - -/*-- mpihelp-div.c --*/ -mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, - mpi_limb_t divisor_limb); -mpi_limb_t mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, - mpi_ptr_t np, mpi_size_t nsize, - mpi_ptr_t dp, mpi_size_t dsize); -mpi_limb_t mpihelp_divmod_1( mpi_ptr_t quot_ptr, - mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, - mpi_limb_t divisor_limb); - -/*-- mpihelp-shift.c --*/ -mpi_limb_t mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, - unsigned cnt); -mpi_limb_t mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, - unsigned cnt); - - -/* Define stuff for longlong.h. */ -#define W_TYPE_SIZE BITS_PER_MPI_LIMB - typedef mpi_limb_t UWtype; - typedef unsigned int UHWtype; -#if defined (__GNUC__) - typedef unsigned int UQItype __attribute__ ((mode (QI))); - typedef int SItype __attribute__ ((mode (SI))); - typedef unsigned int USItype __attribute__ ((mode (SI))); - typedef int DItype __attribute__ ((mode (DI))); - typedef unsigned int UDItype __attribute__ ((mode (DI))); -#else - typedef unsigned char UQItype; - typedef long SItype; - typedef unsigned long USItype; -#endif - -#ifdef __GNUC__ - #include "mpi-inline.h" -#endif - -#endif /*G10_MPI_INTERNAL_H*/ diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c deleted file mode 100644 index ad41cf2a5..000000000 --- a/mpi/mpi-inv.c +++ /dev/null @@ -1,270 +0,0 @@ -/* mpi-inv.c - MPI 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 -#include -#include -#include "mpi-internal.h" - - -/**************** - * Calculate the multiplicative inverse X of A mod N - * That is: Find the solution x for - * 1 = (a*x) mod n - */ -void -mpi_invm( MPI x, MPI a, MPI n ) -{ - #if 0 - MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3; - MPI ta, tb, tc; - - u = mpi_copy(a); - v = mpi_copy(n); - u1 = mpi_alloc_set_ui(1); - u2 = mpi_alloc_set_ui(0); - u3 = mpi_copy(u); - v1 = mpi_alloc_set_ui(0); - v2 = mpi_alloc_set_ui(1); - v3 = mpi_copy(v); - q = mpi_alloc( mpi_get_nlimbs(u)+1 ); - t1 = mpi_alloc( mpi_get_nlimbs(u)+1 ); - t2 = mpi_alloc( mpi_get_nlimbs(u)+1 ); - t3 = mpi_alloc( mpi_get_nlimbs(u)+1 ); - while( mpi_cmp_ui( v3, 0 ) ) { - mpi_fdiv_q( q, u3, v3 ); - mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q); - mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3); - mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3); - mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3); - } - /* log_debug("result:\n"); - log_mpidump("q =", q ); - log_mpidump("u1=", u1); - log_mpidump("u2=", u2); - log_mpidump("u3=", u3); - log_mpidump("v1=", v1); - log_mpidump("v2=", v2); */ - mpi_set(x, u1); - - mpi_free(u1); - mpi_free(u2); - mpi_free(u3); - mpi_free(v1); - mpi_free(v2); - mpi_free(v3); - mpi_free(q); - mpi_free(t1); - mpi_free(t2); - mpi_free(t3); - mpi_free(u); - mpi_free(v); - #elif 0 - /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) - * modified according to Michael Penk's solution for Exercice 35 */ - - /* FIXME: we can simplify this in most cases (see Knuth) */ - MPI u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3; - unsigned k; - int sign; - - u = mpi_copy(a); - v = mpi_copy(n); - for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { - mpi_rshift(u, u, 1); - mpi_rshift(v, v, 1); - } - - - u1 = mpi_alloc_set_ui(1); - u2 = mpi_alloc_set_ui(0); - u3 = mpi_copy(u); - v1 = mpi_copy(v); /* !-- used as const 1 */ - v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u ); - v3 = mpi_copy(v); - if( mpi_test_bit(u, 0) ) { /* u is odd */ - t1 = mpi_alloc_set_ui(0); - t2 = mpi_alloc_set_ui(1); t2->sign = 1; - t3 = mpi_copy(v); t3->sign = !t3->sign; - goto Y4; - } - else { - t1 = mpi_alloc_set_ui(1); - t2 = mpi_alloc_set_ui(0); - t3 = mpi_copy(u); - } - do { - do { - if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ - mpi_add(t1, t1, v); - mpi_sub(t2, t2, u); - } - mpi_rshift(t1, t1, 1); - mpi_rshift(t2, t2, 1); - mpi_rshift(t3, t3, 1); - Y4: - ; - } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ - - if( !t3->sign ) { - mpi_set(u1, t1); - mpi_set(u2, t2); - mpi_set(u3, t3); - } - else { - mpi_sub(v1, v, t1); - sign = u->sign; u->sign = !u->sign; - mpi_sub(v2, u, t2); - u->sign = sign; - sign = t3->sign; t3->sign = !t3->sign; - mpi_set(v3, t3); - t3->sign = sign; - } - mpi_sub(t1, u1, v1); - mpi_sub(t2, u2, v2); - mpi_sub(t3, u3, v3); - if( t1->sign ) { - mpi_add(t1, t1, v); - mpi_sub(t2, t2, u); - } - } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ - /* mpi_lshift( u3, k ); */ - mpi_set(x, u1); - - mpi_free(u1); - mpi_free(u2); - mpi_free(u3); - mpi_free(v1); - mpi_free(v2); - mpi_free(v3); - mpi_free(t1); - mpi_free(t2); - mpi_free(t3); - #else - /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) - * modified according to Michael Penk's solution for Exercice 35 - * with further enhancement */ - MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; - unsigned k; - int sign; - int odd ; - - u = mpi_copy(a); - v = mpi_copy(n); - - for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { - mpi_rshift(u, u, 1); - mpi_rshift(v, v, 1); - } - odd = mpi_test_bit(v,0); - - u1 = mpi_alloc_set_ui(1); - if( !odd ) - u2 = mpi_alloc_set_ui(0); - u3 = mpi_copy(u); - v1 = mpi_copy(v); - if( !odd ) { - v2 = mpi_alloc( mpi_get_nlimbs(u) ); - mpi_sub( v2, u1, u ); /* U is used as const 1 */ - } - v3 = mpi_copy(v); - if( mpi_test_bit(u, 0) ) { /* u is odd */ - t1 = mpi_alloc_set_ui(0); - if( !odd ) { - t2 = mpi_alloc_set_ui(1); t2->sign = 1; - } - t3 = mpi_copy(v); t3->sign = !t3->sign; - goto Y4; - } - else { - t1 = mpi_alloc_set_ui(1); - if( !odd ) - t2 = mpi_alloc_set_ui(0); - t3 = mpi_copy(u); - } - do { - do { - if( !odd ) { - if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ - mpi_add(t1, t1, v); - mpi_sub(t2, t2, u); - } - mpi_rshift(t1, t1, 1); - mpi_rshift(t2, t2, 1); - mpi_rshift(t3, t3, 1); - } - else { - if( mpi_test_bit(t1, 0) ) - mpi_add(t1, t1, v); - mpi_rshift(t1, t1, 1); - mpi_rshift(t3, t3, 1); - } - Y4: - ; - } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ - - if( !t3->sign ) { - mpi_set(u1, t1); - if( !odd ) - mpi_set(u2, t2); - mpi_set(u3, t3); - } - else { - mpi_sub(v1, v, t1); - sign = u->sign; u->sign = !u->sign; - if( !odd ) - mpi_sub(v2, u, t2); - u->sign = sign; - sign = t3->sign; t3->sign = !t3->sign; - mpi_set(v3, t3); - t3->sign = sign; - } - mpi_sub(t1, u1, v1); - if( !odd ) - mpi_sub(t2, u2, v2); - mpi_sub(t3, u3, v3); - if( t1->sign ) { - mpi_add(t1, t1, v); - if( !odd ) - mpi_sub(t2, t2, u); - } - } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ - /* mpi_lshift( u3, k ); */ - mpi_set(x, u1); - - mpi_free(u1); - mpi_free(v1); - mpi_free(t1); - if( !odd ) { - mpi_free(u2); - mpi_free(v2); - mpi_free(t2); - } - mpi_free(u3); - mpi_free(v3); - mpi_free(t3); - - mpi_free(u); - mpi_free(v); - #endif -} - - - diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c deleted file mode 100644 index 7c46fc65c..000000000 --- a/mpi/mpi-mpow.c +++ /dev/null @@ -1,101 +0,0 @@ -/* mpi-mpow.c - MPI functions - * Copyright (C) 1998, 1999, 2000 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 -#include -#include -#include "mpi-internal.h" -#include "longlong.h" -#include - -static int -build_index( MPI *exparray, int k, int i, int t ) -{ - int j, bitno; - int index = 0; - - bitno = t-i; - for(j=k-1; j >= 0; j-- ) { - index <<= 1; - if( mpi_test_bit( exparray[j], bitno ) ) - index |= 1; - } - return index; -} - -/**************** - * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M - */ -void -mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) -{ - int k; /* number of elements */ - int t; /* bit size of largest exponent */ - int i, j, idx; - MPI *G; /* table with precomputed values of size 2^k */ - MPI tmp; - - for(k=0; basearray[k]; k++ ) - ; - assert(k); - for(t=0, i=0; (tmp=exparray[i]); i++ ) { - j = mpi_get_nbits(tmp); - if( j > t ) - t = j; - } - assert(i==k); - assert(t); - assert( k < 10 ); - - G = m_alloc_clear( (1<= 0 && idx < (1< -#include -#include -#include "mpi-internal.h" - - -void -mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult ) -{ - mpi_size_t size, prod_size; - mpi_ptr_t prod_ptr; - mpi_limb_t cy; - int sign; - - size = mult->nlimbs; - sign = mult->sign; - - if( !size || !small_mult ) { - prod->nlimbs = 0; - prod->sign = 0; - return; - } - - prod_size = size + 1; - if( prod->alloced < prod_size ) - mpi_resize( prod, prod_size ); - prod_ptr = prod->d; - - cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult ); - if( cy ) - prod_ptr[size++] = cy; - prod->nlimbs = size; - prod->sign = sign; -} - - -void -mpi_mul_2exp( MPI w, MPI u, unsigned long cnt) -{ - mpi_size_t usize, wsize, limb_cnt; - mpi_ptr_t wp; - mpi_limb_t wlimb; - int usign, wsign; - - usize = u->nlimbs; - usign = u->sign; - - if( !usize ) { - w->nlimbs = 0; - w->sign = 0; - return; - } - - limb_cnt = cnt / BITS_PER_MPI_LIMB; - wsize = usize + limb_cnt + 1; - if( w->alloced < wsize ) - mpi_resize(w, wsize ); - wp = w->d; - wsize = usize + limb_cnt; - wsign = usign; - - cnt %= BITS_PER_MPI_LIMB; - if( cnt ) { - wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt ); - if( wlimb ) { - wp[wsize] = wlimb; - wsize++; - } - } - else { - MPN_COPY_DECR( wp + limb_cnt, u->d, usize ); - } - - /* Zero all whole limbs at low end. Do it here and not before calling - * mpn_lshift, not to lose for U == W. */ - MPN_ZERO( wp, limb_cnt ); - - w->nlimbs = wsize; - w->sign = wsign; -} - - - -void -mpi_mul( MPI w, MPI u, MPI v) -{ - mpi_size_t usize, vsize, wsize; - mpi_ptr_t up, vp, wp; - mpi_limb_t cy; - int usign, vsign, usecure, vsecure, sign_product; - int assign_wp=0; - mpi_ptr_t tmp_limb=NULL; - - - if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ - usize = v->nlimbs; - usign = v->sign; - usecure = mpi_is_secure(v); - up = v->d; - vsize = u->nlimbs; - vsign = u->sign; - vsecure = mpi_is_secure(u); - vp = u->d; - } - else { - usize = u->nlimbs; - usign = u->sign; - usecure = mpi_is_secure(u); - up = u->d; - vsize = v->nlimbs; - vsign = v->sign; - vsecure = mpi_is_secure(v); - vp = v->d; - } - sign_product = usign ^ vsign; - wp = w->d; - - /* Ensure W has space enough to store the result. */ - wsize = usize + vsize; - if ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) { - /* w is not allocated in secure space but u or v is. To make sure - * that no temporray results are stored in w, we temporary use - * a newly allocated limb space for w */ - wp = mpi_alloc_limb_space( wsize, 1 ); - assign_wp = 2; /* mark it as 2 so that we can later copy it back to - * mormal memory */ - } - else if( w->alloced < wsize ) { - if( wp == up || wp == vp ) { - wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) ); - assign_wp = 1; - } - else { - mpi_resize(w, wsize ); - wp = w->d; - } - } - else { /* Make U and V not overlap with W. */ - if( wp == up ) { - /* W and U are identical. Allocate temporary space for U. */ - up = tmp_limb = mpi_alloc_limb_space( usize, usecure ); - /* Is V identical too? Keep it identical with U. */ - if( wp == vp ) - vp = up; - /* Copy to the temporary space. */ - MPN_COPY( up, wp, usize ); - } - else if( wp == vp ) { - /* W and V are identical. Allocate temporary space for V. */ - vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure ); - /* Copy to the temporary space. */ - MPN_COPY( vp, wp, vsize ); - } - } - - if( !vsize ) - wsize = 0; - else { - cy = mpihelp_mul( wp, up, usize, vp, vsize ); - wsize -= cy? 0:1; - } - - if( assign_wp ) { - if (assign_wp == 2) { - /* copy the temp wp from secure memory back to normal memory */ - mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); - MPN_COPY (tmp_wp, wp, wsize); - mpi_free_limb_space (wp); - wp = tmp_wp; - } - mpi_assign_limb_space( w, wp, wsize ); - } - w->nlimbs = wsize; - w->sign = sign_product; - if( tmp_limb ) - mpi_free_limb_space( tmp_limb ); -} - - -void -mpi_mulm( MPI w, MPI u, MPI v, MPI m) -{ - mpi_mul(w, u, v); - mpi_fdiv_r( w, w, m ); -} - diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c deleted file mode 100644 index d65258b0f..000000000 --- a/mpi/mpi-pow.c +++ /dev/null @@ -1,294 +0,0 @@ -/* mpi-pow.c - MPI functions - * Copyright (C) 1994, 1996, 1998, 2000 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" -#include - - -/**************** - * RES = BASE ^ EXP mod MOD - */ -void -mpi_powm( MPI res, MPI base, MPI exp, MPI mod) -{ - mpi_ptr_t rp, ep, mp, bp; - mpi_size_t esize, msize, bsize, rsize; - int esign, msign, bsign, rsign; - int esec, msec, bsec, rsec; - mpi_size_t size; - int mod_shift_cnt; - int negative_result; - mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL; - mpi_ptr_t xp_marker=NULL; - int assign_rp=0; - mpi_ptr_t tspace = NULL; - mpi_size_t tsize=0; /* to avoid compiler warning */ - /* fixme: we should check that the warning is void*/ - - esize = exp->nlimbs; - msize = mod->nlimbs; - size = 2 * msize; - esign = exp->sign; - msign = mod->sign; - - esec = mpi_is_secure(exp); - msec = mpi_is_secure(mod); - bsec = mpi_is_secure(base); - rsec = mpi_is_secure(res); - - rp = res->d; - ep = exp->d; - - if( !msize ) - msize = 1 / msize; /* provoke a signal */ - - if( !esize ) { - /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 - * depending on if MOD equals 1. */ - rp[0] = 1; - res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; - res->sign = 0; - goto leave; - } - - /* Normalize MOD (i.e. make its most significant bit set) as required by - * mpn_divrem. This will make the intermediate values in the calculation - * slightly larger, but the correct result is obtained after a final - * reduction using the original MOD value. */ - mp = mp_marker = mpi_alloc_limb_space(msize, msec); - count_leading_zeros( mod_shift_cnt, mod->d[msize-1] ); - if( mod_shift_cnt ) - mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt ); - else - MPN_COPY( mp, mod->d, msize ); - - bsize = base->nlimbs; - bsign = base->sign; - if( bsize > msize ) { /* The base is larger than the module. Reduce it. */ - /* Allocate (BSIZE + 1) with space for remainder and quotient. - * (The quotient is (bsize - msize + 1) limbs.) */ - bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); - MPN_COPY( bp, base->d, bsize ); - /* We don't care about the quotient, store it above the remainder, - * at BP + MSIZE. */ - mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize ); - bsize = msize; - /* Canonicalize the base, since we are going to multiply with it - * quite a few times. */ - MPN_NORMALIZE( bp, bsize ); - } - else - bp = base->d; - - if( !bsize ) { - res->nlimbs = 0; - res->sign = 0; - goto leave; - } - - if( res->alloced < size ) { - /* We have to allocate more space for RES. If any of the input - * parameters are identical to RES, defer deallocation of the old - * space. */ - if( rp == ep || rp == mp || rp == bp ) { - rp = mpi_alloc_limb_space( size, rsec ); - assign_rp = 1; - } - else { - mpi_resize( res, size ); - rp = res->d; - } - } - else { /* Make BASE, EXP and MOD not overlap with RES. */ - if( rp == bp ) { - /* RES and BASE are identical. Allocate temp. space for BASE. */ - assert( !bp_marker ); - bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); - MPN_COPY(bp, rp, bsize); - } - if( rp == ep ) { - /* RES and EXP are identical. Allocate temp. space for EXP. */ - ep = ep_marker = mpi_alloc_limb_space( esize, esec ); - MPN_COPY(ep, rp, esize); - } - if( rp == mp ) { - /* RES and MOD are identical. Allocate temporary space for MOD.*/ - assert( !mp_marker ); - mp = mp_marker = mpi_alloc_limb_space( msize, msec ); - MPN_COPY(mp, rp, msize); - } - } - - MPN_COPY( rp, bp, bsize ); - rsize = bsize; - rsign = bsign; - - { - mpi_size_t i; - mpi_ptr_t xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); - int c; - mpi_limb_t e; - mpi_limb_t carry_limb; - struct karatsuba_ctx karactx; - - memset( &karactx, 0, sizeof karactx ); - negative_result = (ep[0] & 1) && base->sign; - - i = esize - 1; - e = ep[i]; - count_leading_zeros (c, e); - e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ - c = BITS_PER_MPI_LIMB - 1 - c; - - /* Main loop. - * - * Make the result be pointed to alternately by XP and RP. This - * helps us avoid block copying, which would otherwise be necessary - * with the overlap restrictions of mpihelp_divmod. With 50% probability - * the result after this loop will be in the area originally pointed - * by RP (==RES->d), and with 50% probability in the area originally - * pointed to by XP. - */ - - for(;;) { - while( c ) { - mpi_ptr_t tp; - mpi_size_t xsize; - - /*mpihelp_mul_n(xp, rp, rp, rsize);*/ - if( rsize < KARATSUBA_THRESHOLD ) - mpih_sqr_n_basecase( xp, rp, rsize ); - else { - if( !tspace ) { - tsize = 2 * rsize; - tspace = mpi_alloc_limb_space( tsize, 0 ); - } - else if( tsize < (2*rsize) ) { - mpi_free_limb_space( tspace ); - tsize = 2 * rsize; - tspace = mpi_alloc_limb_space( tsize, 0 ); - } - mpih_sqr_n( xp, rp, rsize, tspace ); - } - - xsize = 2 * rsize; - if( xsize > msize ) { - mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); - xsize = msize; - } - - tp = rp; rp = xp; xp = tp; - rsize = xsize; - - if( (mpi_limb_signed_t)e < 0 ) { - /*mpihelp_mul( xp, rp, rsize, bp, bsize );*/ - if( bsize < KARATSUBA_THRESHOLD ) { - mpihelp_mul( xp, rp, rsize, bp, bsize ); - } - else { - mpihelp_mul_karatsuba_case( - xp, rp, rsize, bp, bsize, &karactx ); - } - - xsize = rsize + bsize; - if( xsize > msize ) { - mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); - xsize = msize; - } - - tp = rp; rp = xp; xp = tp; - rsize = xsize; - } - e <<= 1; - c--; - } - - i--; - if( i < 0 ) - break; - e = ep[i]; - c = BITS_PER_MPI_LIMB; - } - - /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT - * steps. Adjust the result by reducing it with the original MOD. - * - * Also make sure the result is put in RES->d (where it already - * might be, see above). - */ - if( mod_shift_cnt ) { - carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt); - rp = res->d; - if( carry_limb ) { - rp[rsize] = carry_limb; - rsize++; - } - } - else { - MPN_COPY( res->d, rp, rsize); - rp = res->d; - } - - if( rsize >= msize ) { - mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize); - rsize = msize; - } - - /* Remove any leading zero words from the result. */ - if( mod_shift_cnt ) - mpihelp_rshift( rp, rp, rsize, mod_shift_cnt); - MPN_NORMALIZE (rp, rsize); - - mpihelp_release_karatsuba_ctx( &karactx ); - } - - if( negative_result && rsize ) { - if( mod_shift_cnt ) - mpihelp_rshift( mp, mp, msize, mod_shift_cnt); - mpihelp_sub( rp, mp, msize, rp, rsize); - rsize = msize; - rsign = msign; - MPN_NORMALIZE(rp, rsize); - } - res->nlimbs = rsize; - res->sign = rsign; - - leave: - if( assign_rp ) mpi_assign_limb_space( res, rp, size ); - if( mp_marker ) mpi_free_limb_space( mp_marker ); - if( bp_marker ) mpi_free_limb_space( bp_marker ); - if( ep_marker ) mpi_free_limb_space( ep_marker ); - if( xp_marker ) mpi_free_limb_space( xp_marker ); - if( tspace ) mpi_free_limb_space( tspace ); -} - diff --git a/mpi/mpi-scan.c b/mpi/mpi-scan.c deleted file mode 100644 index abebe2208..000000000 --- a/mpi/mpi-scan.c +++ /dev/null @@ -1,132 +0,0 @@ -/* mpi-scan.c - MPI 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 -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - -/**************** - * Scan through an mpi and return byte for byte. a -1 is returned to indicate - * the end of the mpi. Scanning is done from the lsb to the msb, returned - * values are in the range of 0 .. 255. - * - * FIXME: This code is VERY ugly! - */ -int -mpi_getbyte( MPI a, unsigned idx ) -{ - int i, j; - unsigned n; - mpi_ptr_t ap; - mpi_limb_t limb; - - ap = a->d; - for(n=0,i=0; i < a->nlimbs; i++ ) { - limb = ap[i]; - for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) - if( n == idx ) - return (limb >> j*8) & 0xff; - } - return -1; -} - - -/**************** - * Put a value at position IDX into A. idx counts from lsb to msb - */ -void -mpi_putbyte( MPI a, unsigned idx, int xc ) -{ - int i, j; - unsigned n; - mpi_ptr_t ap; - mpi_limb_t limb, c; - - c = xc & 0xff; - ap = a->d; - for(n=0,i=0; i < a->alloced; i++ ) { - limb = ap[i]; - for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) - if( n == idx ) { - #if BYTES_PER_MPI_LIMB == 4 - if( j == 0 ) - limb = (limb & 0xffffff00) | c; - else if( j == 1 ) - limb = (limb & 0xffff00ff) | (c<<8); - else if( j == 2 ) - limb = (limb & 0xff00ffff) | (c<<16); - else - limb = (limb & 0x00ffffff) | (c<<24); - #elif BYTES_PER_MPI_LIMB == 8 - if( j == 0 ) - limb = (limb & 0xffffffffffffff00) | c; - else if( j == 1 ) - limb = (limb & 0xffffffffffff00ff) | (c<<8); - else if( j == 2 ) - limb = (limb & 0xffffffffff00ffff) | (c<<16); - else if( j == 3 ) - limb = (limb & 0xffffffff00ffffff) | (c<<24); - else if( j == 4 ) - limb = (limb & 0xffffff00ffffffff) | (c<<32); - else if( j == 5 ) - limb = (limb & 0xffff00ffffffffff) | (c<<40); - else if( j == 6 ) - limb = (limb & 0xff00ffffffffffff) | (c<<48); - else - limb = (limb & 0x00ffffffffffffff) | (c<<56); - #else - #error please enhance this function, its ugly - i know. - #endif - if( a->nlimbs <= i ) - a->nlimbs = i+1; - ap[i] = limb; - return; - } - } - abort(); /* index out of range */ -} - - -/**************** - * Count the number of zerobits at the low end of A - */ -unsigned -mpi_trailing_zeros( MPI a ) -{ - unsigned n, count = 0; - - for(n=0; n < a->nlimbs; n++ ) { - if( a->d[n] ) { - unsigned nn; - mpi_limb_t alimb = a->d[n]; - - count_trailing_zeros( nn, alimb ); - count += nn; - break; - } - count += BITS_PER_MPI_LIMB; - } - return count; - -} - - diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c deleted file mode 100644 index 8cb1538c0..000000000 --- a/mpi/mpicoder.c +++ /dev/null @@ -1,447 +0,0 @@ -/* mpicoder.c - Coder for the external representation of MPIs - * Copyright (C) 1998, 1999 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 -#include -#include -#include -#include - -#include "mpi.h" -#include "mpi-internal.h" -#include "iobuf.h" -#include "memory.h" -#include "util.h" - -#ifdef M_DEBUG - #undef mpi_read -#endif - -#define MAX_EXTERN_MPI_BITS 16384 - -/**************** - * write an mpi to out. - */ -int -mpi_write( IOBUF out, MPI a ) -{ - int rc; - unsigned nbits = mpi_get_nbits(a); - byte *p, *buf; - unsigned n; - - if( nbits > MAX_EXTERN_MPI_BITS ) - log_bug("mpi_encode: mpi too large (%u bits)\n", nbits); - - iobuf_put(out, (nbits >>8) ); - iobuf_put(out, (nbits) ); - - p = buf = mpi_get_buffer( a, &n, NULL ); - rc = iobuf_write( out, p, n ); - m_free(buf); - return rc; -} - - -/**************** - * Read an external representation of an mpi and return the MPI - * The external format is a 16 bit unsigned value stored in network byte order, - * giving the number of bits for the following integer. The integer is stored - * with MSB first (left padded with zeroes to align on a byte boundary). - */ -MPI -#ifdef M_DEBUG -mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info) -#else -mpi_read(IOBUF inp, unsigned *ret_nread, int secure) -#endif -{ - int c, i, j; - unsigned nbits, nbytes, nlimbs, nread=0; - mpi_limb_t a; - MPI val = MPI_NULL; - - if( (c = iobuf_get(inp)) == -1 ) - goto leave; - nbits = c << 8; - if( (c = iobuf_get(inp)) == -1 ) - goto leave; - nbits |= c; - if( nbits > MAX_EXTERN_MPI_BITS ) { - log_error("mpi too large (%u bits)\n", nbits); - goto leave; - } - nread = 2; - - nbytes = (nbits+7) / 8; - nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; - #ifdef M_DEBUG - val = secure? mpi_debug_alloc_secure( nlimbs, info ) - : mpi_debug_alloc( nlimbs, info ); - #else - val = secure? mpi_alloc_secure( nlimbs ) - : mpi_alloc( nlimbs ); - #endif - i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; - i %= BYTES_PER_MPI_LIMB; - val->nbits = nbits; - j= val->nlimbs = nlimbs; - val->sign = 0; - for( ; j > 0; j-- ) { - a = 0; - for(; i < BYTES_PER_MPI_LIMB; i++ ) { - a <<= 8; - a |= iobuf_get(inp) & 0xff; nread++; - } - i = 0; - val->d[j-1] = a; - } - - leave: - if( nread > *ret_nread ) - log_bug("mpi crosses packet border\n"); - else - *ret_nread = nread; - return val; -} - - -MPI -mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure) -{ - int i, j; - unsigned nbits, nbytes, nlimbs, nread=0; - mpi_limb_t a; - MPI val = MPI_NULL; - - if( *ret_nread < 2 ) - goto leave; - nbits = buffer[0] << 8 | buffer[1]; - if( nbits > MAX_EXTERN_MPI_BITS ) { - log_error("mpi too large (%u bits)\n", nbits); - goto leave; - } - buffer += 2; - nread = 2; - - nbytes = (nbits+7) / 8; - nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; - val = secure? mpi_alloc_secure( nlimbs ) - : mpi_alloc( nlimbs ); - i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; - i %= BYTES_PER_MPI_LIMB; - val->nbits = nbits; - j= val->nlimbs = nlimbs; - val->sign = 0; - for( ; j > 0; j-- ) { - a = 0; - for(; i < BYTES_PER_MPI_LIMB; i++ ) { - if( ++nread > *ret_nread ) - log_bug("mpi larger than buffer\n"); - a <<= 8; - a |= *buffer++; - } - i = 0; - val->d[j-1] = a; - } - - leave: - *ret_nread = nread; - return val; -} - - -/**************** - * Make an mpi from a character string. - */ -int -mpi_fromstr(MPI val, const char *str) -{ - int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2; - unsigned nbits, nbytes, nlimbs; - mpi_limb_t a; - - if( *str == '-' ) { - sign = 1; - str++; - } - if( *str == '0' && str[1] == 'x' ) - hexmode = 1; - else - return 1; /* other bases are not yet supported */ - str += 2; - - nbits = strlen(str)*4; - if( nbits % 8 ) - prepend_zero = 1; - nbytes = (nbits+7) / 8; - nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; - if( val->alloced < nlimbs ) - mpi_resize(val, nlimbs ); - i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; - i %= BYTES_PER_MPI_LIMB; - j= val->nlimbs = nlimbs; - val->sign = sign; - for( ; j > 0; j-- ) { - a = 0; - for(; i < BYTES_PER_MPI_LIMB; i++ ) { - if( prepend_zero ) { - c1 = '0'; - prepend_zero = 0; - } - else - c1 = *str++; - assert(c1); - c2 = *str++; - assert(c2); - if( c1 >= '0' && c1 <= '9' ) - c = c1 - '0'; - else if( c1 >= 'a' && c1 <= 'f' ) - c = c1 - 'a' + 10; - else if( c1 >= 'A' && c1 <= 'F' ) - c = c1 - 'A' + 10; - else { - mpi_clear(val); - return 1; - } - c <<= 4; - if( c2 >= '0' && c2 <= '9' ) - c |= c2 - '0'; - else if( c2 >= 'a' && c2 <= 'f' ) - c |= c2 - 'a' + 10; - else if( c2 >= 'A' && c2 <= 'F' ) - c |= c2 - 'A' + 10; - else { - mpi_clear(val); - return 1; - } - a <<= 8; - a |= c; - } - i = 0; - val->d[j-1] = a; - } - - return 0; -} - - -/**************** - * print an MPI to the given stream and return the number of characters - * printed. - */ -int -mpi_print( FILE *fp, MPI a, int mode ) -{ - int i, n=0; - - if( a == MPI_NULL ) - return fprintf(fp, "[MPI_NULL]"); - if( !mode ) { - unsigned int n1; - - n1 = mpi_get_nbits(a); - n += fprintf(fp, "[%u bits]", n1); - } - else { - if( a->sign ) - putc('-', fp); -#if BYTES_PER_MPI_LIMB == 2 -#define X "4" -#elif BYTES_PER_MPI_LIMB == 4 -#define X "8" -#elif BYTES_PER_MPI_LIMB == 8 -#define X "16" -#else -#error please define the format here -#endif - for(i=a->nlimbs; i > 0 ; i-- ) { - n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); -#undef X - } - if( !a->nlimbs ) - putc('0', fp ); - } - return n; -} - - -void -g10_log_mpidump( const char *text, MPI a ) -{ - FILE *fp = log_stream(); - - g10_log_print_prefix(text); - mpi_print(fp, a, 1 ); - fputc('\n', fp); -} - -/**************** - * Special function to get the low 8 bytes from an mpi. - * This can be used as a keyid; KEYID is an 2 element array. - * Return the low 4 bytes. - */ -u32 -mpi_get_keyid( MPI a, u32 *keyid ) -{ -#if BYTES_PER_MPI_LIMB == 4 - if( keyid ) { - keyid[0] = a->nlimbs >= 2? a->d[1] : 0; - keyid[1] = a->nlimbs >= 1? a->d[0] : 0; - } - return a->nlimbs >= 1? a->d[0] : 0; -#elif BYTES_PER_MPI_LIMB == 8 - if( keyid ) { - keyid[0] = a->nlimbs? (u32)(a->d[0] >> 32) : 0; - keyid[1] = a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0; - } - return a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0; -#else - #error Make this function work with other LIMB sizes -#endif -} - - -/**************** - * Return an m_alloced buffer with the MPI (msb first). - * NBYTES receives the length of this buffer. Caller must free the - * return string (This function does return a 0 byte buffer with NBYTES - * set to zero if the value of A is zero. If sign is not NULL, it will - * be set to the sign of the A. - */ -static byte * -do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure ) -{ - byte *p, *buffer; - mpi_limb_t alimb; - int i; - unsigned int n; - - if( sign ) - *sign = a->sign; - *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB; - if (!n) - n++; /* avoid zero length allocation */ - p = buffer = force_secure || mpi_is_secure(a) ? m_alloc_secure(n) - : m_alloc(n); - - for(i=a->nlimbs-1; i >= 0; i-- ) { - alimb = a->d[i]; -#if BYTES_PER_MPI_LIMB == 4 - *p++ = alimb >> 24; - *p++ = alimb >> 16; - *p++ = alimb >> 8; - *p++ = alimb ; -#elif BYTES_PER_MPI_LIMB == 8 - *p++ = alimb >> 56; - *p++ = alimb >> 48; - *p++ = alimb >> 40; - *p++ = alimb >> 32; - *p++ = alimb >> 24; - *p++ = alimb >> 16; - *p++ = alimb >> 8; - *p++ = alimb ; -#else -#error please implement for this limb size. -#endif - } - - /* this is sub-optimal but we need to do the shift operation - * because the caller has to free the returned buffer */ - for(p=buffer; !*p && *nbytes; p++, --*nbytes ) - ; - if( p != buffer ) - memmove(buffer,p, *nbytes); - - return buffer; -} - - -byte * -mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ) -{ - return do_get_buffer( a, nbytes, sign, 0 ); -} - -byte * -mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ) -{ - return do_get_buffer( a, nbytes, sign, 1 ); -} - -/**************** - * Use BUFFER to update MPI. - */ -void -mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ) -{ - const byte *p; - mpi_limb_t alimb; - int nlimbs; - int i; - - nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; - RESIZE_IF_NEEDED(a, nlimbs); - a->sign = sign; - - for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) { - #if BYTES_PER_MPI_LIMB == 4 - alimb = (mpi_limb_t)*p-- ; - alimb |= (mpi_limb_t)*p-- << 8 ; - alimb |= (mpi_limb_t)*p-- << 16 ; - alimb |= (mpi_limb_t)*p-- << 24 ; - #elif BYTES_PER_MPI_LIMB == 8 - alimb = (mpi_limb_t)*p-- ; - alimb |= (mpi_limb_t)*p-- << 8 ; - alimb |= (mpi_limb_t)*p-- << 16 ; - alimb |= (mpi_limb_t)*p-- << 24 ; - alimb |= (mpi_limb_t)*p-- << 32 ; - alimb |= (mpi_limb_t)*p-- << 40 ; - alimb |= (mpi_limb_t)*p-- << 48 ; - alimb |= (mpi_limb_t)*p-- << 56 ; - #else - #error please implement for this limb size. - #endif - a->d[i++] = alimb; - } - if( p >= buffer ) { - #if BYTES_PER_MPI_LIMB == 4 - alimb = *p-- ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ; - #elif BYTES_PER_MPI_LIMB == 8 - alimb = (mpi_limb_t)*p-- ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ; - if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ; - #else - #error please implement for this limb size. - #endif - a->d[i++] = alimb; - } - a->nlimbs = i; - assert( i == nlimbs ); -} - diff --git a/mpi/mpih-cmp.c b/mpi/mpih-cmp.c deleted file mode 100644 index 03d41557c..000000000 --- a/mpi/mpih-cmp.c +++ /dev/null @@ -1,62 +0,0 @@ -/* mpihelp-sub.c - MPI helper functions - * Copyright (C) 1994, 1996 Free Software Foundation, Inc. - * 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include - -#include "mpi-internal.h" - -/**************** - * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. - * There are no restrictions on the relative sizes of - * the two arguments. - * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. - */ -int -mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) -{ - mpi_size_t i; - mpi_limb_t op1_word, op2_word; - - for( i = size - 1; i >= 0 ; i--) { - op1_word = op1_ptr[i]; - op2_word = op2_ptr[i]; - if( op1_word != op2_word ) - goto diff; - } - return 0; - - diff: - /* This can *not* be simplified to - * op2_word - op2_word - * since that expression might give signed overflow. */ - return (op1_word > op2_word) ? 1 : -1; -} - diff --git a/mpi/mpih-div.c b/mpi/mpih-div.c deleted file mode 100644 index 6eb0e1a34..000000000 --- a/mpi/mpih-div.c +++ /dev/null @@ -1,537 +0,0 @@ -/* mpihelp-div.c - MPI helper functions - * Copyright (C) 1994, 1996 Free Software Foundation, Inc. - * Copyright (C) 1998, 1999 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - -#ifndef UMUL_TIME - #define UMUL_TIME 1 -#endif -#ifndef UDIV_TIME - #define UDIV_TIME UMUL_TIME -#endif - -/* FIXME: We should be using invert_limb (or invert_normalized_limb) - * here (not udiv_qrnnd). - */ - -mpi_limb_t -mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, - mpi_limb_t divisor_limb) -{ - mpi_size_t i; - mpi_limb_t n1, n0, r; - int dummy; - - /* Botch: Should this be handled at all? Rely on callers? */ - if( !dividend_size ) - return 0; - - /* If multiplication is much faster than division, and the - * dividend is large, pre-invert the divisor, and use - * only multiplications in the inner loop. - * - * This test should be read: - * Does it ever help to use udiv_qrnnd_preinv? - * && Does what we save compensate for the inversion overhead? - */ - if( UDIV_TIME > (2 * UMUL_TIME + 6) - && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { - int normalization_steps; - - count_leading_zeros( normalization_steps, divisor_limb ); - if( normalization_steps ) { - mpi_limb_t divisor_limb_inverted; - - divisor_limb <<= normalization_steps; - - /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The - * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the - * most significant bit (with weight 2**N) implicit. - * - * Special case for DIVISOR_LIMB == 100...000. - */ - if( !(divisor_limb << 1) ) - divisor_limb_inverted = ~(mpi_limb_t)0; - else - udiv_qrnnd(divisor_limb_inverted, dummy, - -divisor_limb, 0, divisor_limb); - - n1 = dividend_ptr[dividend_size - 1]; - r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); - - /* Possible optimization: - * if (r == 0 - * && divisor_limb > ((n1 << normalization_steps) - * | (dividend_ptr[dividend_size - 2] >> ...))) - * ...one division less... - */ - for( i = dividend_size - 2; i >= 0; i--) { - n0 = dividend_ptr[i]; - UDIV_QRNND_PREINV(dummy, r, r, - ((n1 << normalization_steps) - | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), - divisor_limb, divisor_limb_inverted); - n1 = n0; - } - UDIV_QRNND_PREINV(dummy, r, r, - n1 << normalization_steps, - divisor_limb, divisor_limb_inverted); - return r >> normalization_steps; - } - else { - mpi_limb_t divisor_limb_inverted; - - /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The - * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the - * most significant bit (with weight 2**N) implicit. - * - * Special case for DIVISOR_LIMB == 100...000. - */ - if( !(divisor_limb << 1) ) - divisor_limb_inverted = ~(mpi_limb_t)0; - else - udiv_qrnnd(divisor_limb_inverted, dummy, - -divisor_limb, 0, divisor_limb); - - i = dividend_size - 1; - r = dividend_ptr[i]; - - if( r >= divisor_limb ) - r = 0; - else - i--; - - for( ; i >= 0; i--) { - n0 = dividend_ptr[i]; - UDIV_QRNND_PREINV(dummy, r, r, - n0, divisor_limb, divisor_limb_inverted); - } - return r; - } - } - else { - if( UDIV_NEEDS_NORMALIZATION ) { - int normalization_steps; - - count_leading_zeros(normalization_steps, divisor_limb); - if( normalization_steps ) { - divisor_limb <<= normalization_steps; - - n1 = dividend_ptr[dividend_size - 1]; - r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); - - /* Possible optimization: - * if (r == 0 - * && divisor_limb > ((n1 << normalization_steps) - * | (dividend_ptr[dividend_size - 2] >> ...))) - * ...one division less... - */ - for(i = dividend_size - 2; i >= 0; i--) { - n0 = dividend_ptr[i]; - udiv_qrnnd (dummy, r, r, - ((n1 << normalization_steps) - | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), - divisor_limb); - n1 = n0; - } - udiv_qrnnd (dummy, r, r, - n1 << normalization_steps, - divisor_limb); - return r >> normalization_steps; - } - } - /* No normalization needed, either because udiv_qrnnd doesn't require - * it, or because DIVISOR_LIMB is already normalized. */ - i = dividend_size - 1; - r = dividend_ptr[i]; - - if(r >= divisor_limb) - r = 0; - else - i--; - - for(; i >= 0; i--) { - n0 = dividend_ptr[i]; - udiv_qrnnd (dummy, r, r, n0, divisor_limb); - } - return r; - } -} - -/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write - * the NSIZE-DSIZE least significant quotient limbs at QP - * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is - * non-zero, generate that many fraction bits and append them after the - * other quotient limbs. - * Return the most significant limb of the quotient, this is always 0 or 1. - * - * Preconditions: - * 0. NSIZE >= DSIZE. - * 1. The most significant bit of the divisor must be set. - * 2. QP must either not overlap with the input operands at all, or - * QP + DSIZE >= NP must hold true. (This means that it's - * possible to put the quotient in the high part of NUM, right after the - * remainder in NUM. - * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. - */ - -mpi_limb_t -mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, - mpi_ptr_t np, mpi_size_t nsize, - mpi_ptr_t dp, mpi_size_t dsize) -{ - mpi_limb_t most_significant_q_limb = 0; - - switch(dsize) { - case 0: - /* We are asked to divide by zero, so go ahead and do it! (To make - the compiler not remove this statement, return the value.) */ - return 1 / dsize; - - case 1: - { - mpi_size_t i; - mpi_limb_t n1; - mpi_limb_t d; - - d = dp[0]; - n1 = np[nsize - 1]; - - if( n1 >= d ) { - n1 -= d; - most_significant_q_limb = 1; - } - - qp += qextra_limbs; - for( i = nsize - 2; i >= 0; i--) - udiv_qrnnd( qp[i], n1, n1, np[i], d ); - qp -= qextra_limbs; - - for( i = qextra_limbs - 1; i >= 0; i-- ) - udiv_qrnnd (qp[i], n1, n1, 0, d); - - np[0] = n1; - } - break; - - case 2: - { - mpi_size_t i; - mpi_limb_t n1, n0, n2; - mpi_limb_t d1, d0; - - np += nsize - 2; - d1 = dp[1]; - d0 = dp[0]; - n1 = np[1]; - n0 = np[0]; - - if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { - sub_ddmmss (n1, n0, n1, n0, d1, d0); - most_significant_q_limb = 1; - } - - for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { - mpi_limb_t q; - mpi_limb_t r; - - if( i >= qextra_limbs ) - np--; - else - np[0] = 0; - - if( n1 == d1 ) { - /* Q should be either 111..111 or 111..110. Need special - * treatment of this rare case as normal division would - * give overflow. */ - q = ~(mpi_limb_t)0; - - r = n0 + d1; - if( r < d1 ) { /* Carry in the addition? */ - add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); - qp[i] = q; - continue; - } - n1 = d0 - (d0 != 0?1:0); - n0 = -d0; - } - else { - udiv_qrnnd (q, r, n1, n0, d1); - umul_ppmm (n1, n0, d0, q); - } - - n2 = np[0]; - q_test: - if( n1 > r || (n1 == r && n0 > n2) ) { - /* The estimated Q was too large. */ - q--; - sub_ddmmss (n1, n0, n1, n0, 0, d0); - r += d1; - if( r >= d1 ) /* If not carry, test Q again. */ - goto q_test; - } - - qp[i] = q; - sub_ddmmss (n1, n0, r, n2, n1, n0); - } - np[1] = n1; - np[0] = n0; - } - break; - - default: - { - mpi_size_t i; - mpi_limb_t dX, d1, n0; - - np += nsize - dsize; - dX = dp[dsize - 1]; - d1 = dp[dsize - 2]; - n0 = np[dsize - 1]; - - if( n0 >= dX ) { - if(n0 > dX || mpihelp_cmp(np, dp, dsize - 1) >= 0 ) { - mpihelp_sub_n(np, np, dp, dsize); - n0 = np[dsize - 1]; - most_significant_q_limb = 1; - } - } - - for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { - mpi_limb_t q; - mpi_limb_t n1, n2; - mpi_limb_t cy_limb; - - if( i >= qextra_limbs ) { - np--; - n2 = np[dsize]; - } - else { - n2 = np[dsize - 1]; - MPN_COPY_DECR (np + 1, np, dsize - 1); - np[0] = 0; - } - - if( n0 == dX ) { - /* This might over-estimate q, but it's probably not worth - * the extra code here to find out. */ - q = ~(mpi_limb_t)0; - } - else { - mpi_limb_t r; - - udiv_qrnnd(q, r, n0, np[dsize - 1], dX); - umul_ppmm(n1, n0, d1, q); - - while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { - q--; - r += dX; - if( r < dX ) /* I.e. "carry in previous addition?" */ - break; - n1 -= n0 < d1; - n0 -= d1; - } - } - - /* Possible optimization: We already have (q * n0) and (1 * n1) - * after the calculation of q. Taking advantage of that, we - * could make this loop make two iterations less. */ - cy_limb = mpihelp_submul_1(np, dp, dsize, q); - - if( n2 != cy_limb ) { - mpihelp_add_n(np, np, dp, dsize); - q--; - } - - qp[i] = q; - n0 = np[dsize - 1]; - } - } - } - - return most_significant_q_limb; -} - - -/**************** - * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. - * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. - * Return the single-limb remainder. - * There are no constraints on the value of the divisor. - * - * QUOT_PTR and DIVIDEND_PTR might point to the same limb. - */ - -mpi_limb_t -mpihelp_divmod_1( mpi_ptr_t quot_ptr, - mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, - mpi_limb_t divisor_limb) -{ - mpi_size_t i; - mpi_limb_t n1, n0, r; - int dummy; - - if( !dividend_size ) - return 0; - - /* If multiplication is much faster than division, and the - * dividend is large, pre-invert the divisor, and use - * only multiplications in the inner loop. - * - * This test should be read: - * Does it ever help to use udiv_qrnnd_preinv? - * && Does what we save compensate for the inversion overhead? - */ - if( UDIV_TIME > (2 * UMUL_TIME + 6) - && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { - int normalization_steps; - - count_leading_zeros( normalization_steps, divisor_limb ); - if( normalization_steps ) { - mpi_limb_t divisor_limb_inverted; - - divisor_limb <<= normalization_steps; - - /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The - * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the - * most significant bit (with weight 2**N) implicit. - */ - /* Special case for DIVISOR_LIMB == 100...000. */ - if( !(divisor_limb << 1) ) - divisor_limb_inverted = ~(mpi_limb_t)0; - else - udiv_qrnnd(divisor_limb_inverted, dummy, - -divisor_limb, 0, divisor_limb); - - n1 = dividend_ptr[dividend_size - 1]; - r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); - - /* Possible optimization: - * if (r == 0 - * && divisor_limb > ((n1 << normalization_steps) - * | (dividend_ptr[dividend_size - 2] >> ...))) - * ...one division less... - */ - for( i = dividend_size - 2; i >= 0; i--) { - n0 = dividend_ptr[i]; - UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, - ((n1 << normalization_steps) - | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), - divisor_limb, divisor_limb_inverted); - n1 = n0; - } - UDIV_QRNND_PREINV( quot_ptr[0], r, r, - n1 << normalization_steps, - divisor_limb, divisor_limb_inverted); - return r >> normalization_steps; - } - else { - mpi_limb_t divisor_limb_inverted; - - /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The - * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the - * most significant bit (with weight 2**N) implicit. - */ - /* Special case for DIVISOR_LIMB == 100...000. */ - if( !(divisor_limb << 1) ) - divisor_limb_inverted = ~(mpi_limb_t) 0; - else - udiv_qrnnd(divisor_limb_inverted, dummy, - -divisor_limb, 0, divisor_limb); - - i = dividend_size - 1; - r = dividend_ptr[i]; - - if( r >= divisor_limb ) - r = 0; - else - quot_ptr[i--] = 0; - - for( ; i >= 0; i-- ) { - n0 = dividend_ptr[i]; - UDIV_QRNND_PREINV( quot_ptr[i], r, r, - n0, divisor_limb, divisor_limb_inverted); - } - return r; - } - } - else { - if(UDIV_NEEDS_NORMALIZATION) { - int normalization_steps; - - count_leading_zeros (normalization_steps, divisor_limb); - if( normalization_steps ) { - divisor_limb <<= normalization_steps; - - n1 = dividend_ptr[dividend_size - 1]; - r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); - - /* Possible optimization: - * if (r == 0 - * && divisor_limb > ((n1 << normalization_steps) - * | (dividend_ptr[dividend_size - 2] >> ...))) - * ...one division less... - */ - for( i = dividend_size - 2; i >= 0; i--) { - n0 = dividend_ptr[i]; - udiv_qrnnd (quot_ptr[i + 1], r, r, - ((n1 << normalization_steps) - | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), - divisor_limb); - n1 = n0; - } - udiv_qrnnd (quot_ptr[0], r, r, - n1 << normalization_steps, - divisor_limb); - return r >> normalization_steps; - } - } - /* No normalization needed, either because udiv_qrnnd doesn't require - * it, or because DIVISOR_LIMB is already normalized. */ - i = dividend_size - 1; - r = dividend_ptr[i]; - - if(r >= divisor_limb) - r = 0; - else - quot_ptr[i--] = 0; - - for(; i >= 0; i--) { - n0 = dividend_ptr[i]; - udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); - } - return r; - } -} - - diff --git a/mpi/mpih-mul.c b/mpi/mpih-mul.c deleted file mode 100644 index db6c1aeb8..000000000 --- a/mpi/mpih-mul.c +++ /dev/null @@ -1,528 +0,0 @@ -/* mpihelp-mul.c - MPI helper functions - * Copyright (C) 1994, 1996, 1998, 1999, - * 2000 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - -#include -#include -#include -#include -#include "mpi-internal.h" -#include "longlong.h" - - - -#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ - do { \ - if( (size) < KARATSUBA_THRESHOLD ) \ - mul_n_basecase (prodp, up, vp, size); \ - else \ - mul_n (prodp, up, vp, size, tspace); \ - } while (0); - -#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ - do { \ - if ((size) < KARATSUBA_THRESHOLD) \ - mpih_sqr_n_basecase (prodp, up, size); \ - else \ - mpih_sqr_n (prodp, up, size, tspace); \ - } while (0); - - - - -/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), - * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are - * always stored. Return the most significant limb. - * - * Argument constraints: - * 1. PRODP != UP and PRODP != VP, i.e. the destination - * must be distinct from the multiplier and the multiplicand. - * - * - * Handle simple cases with traditional multiplication. - * - * This is the most critical code of multiplication. All multiplies rely - * on this, both small and huge. Small ones arrive here immediately. Huge - * ones arrive here as this is the base case for Karatsuba's recursive - * algorithm below. - */ - -static mpi_limb_t -mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, - mpi_ptr_t vp, mpi_size_t size) -{ - mpi_size_t i; - mpi_limb_t cy; - mpi_limb_t v_limb; - - /* Multiply by the first limb in V separately, as the result can be - * stored (not added) to PROD. We also avoid a loop for zeroing. */ - v_limb = vp[0]; - if( v_limb <= 1 ) { - if( v_limb == 1 ) - MPN_COPY( prodp, up, size ); - else - MPN_ZERO( prodp, size ); - cy = 0; - } - else - cy = mpihelp_mul_1( prodp, up, size, v_limb ); - - prodp[size] = cy; - prodp++; - - /* For each iteration in the outer loop, multiply one limb from - * U with one limb from V, and add it to PROD. */ - for( i = 1; i < size; i++ ) { - v_limb = vp[i]; - if( v_limb <= 1 ) { - cy = 0; - if( v_limb == 1 ) - cy = mpihelp_add_n(prodp, prodp, up, size); - } - else - cy = mpihelp_addmul_1(prodp, up, size, v_limb); - - prodp[size] = cy; - prodp++; - } - - return cy; -} - - -static void -mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, - mpi_size_t size, mpi_ptr_t tspace ) -{ - if( size & 1 ) { - /* The size is odd, and the code below doesn't handle that. - * Multiply the least significant (size - 1) limbs with a recursive - * call, and handle the most significant limb of S1 and S2 - * separately. - * A slightly faster way to do this would be to make the Karatsuba - * code below behave as if the size were even, and let it check for - * odd size in the end. I.e., in essence move this code to the end. - * Doing so would save us a recursive call, and potentially make the - * stack grow a lot less. - */ - mpi_size_t esize = size - 1; /* even size */ - mpi_limb_t cy_limb; - - MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace ); - cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] ); - prodp[esize + esize] = cy_limb; - cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] ); - prodp[esize + size] = cy_limb; - } - else { - /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. - * - * Split U in two pieces, U1 and U0, such that - * U = U0 + U1*(B**n), - * and V in V1 and V0, such that - * V = V0 + V1*(B**n). - * - * UV is then computed recursively using the identity - * - * 2n n n n - * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V - * 1 1 1 0 0 1 0 0 - * - * Where B = 2**BITS_PER_MP_LIMB. - */ - mpi_size_t hsize = size >> 1; - mpi_limb_t cy; - int negflg; - - /* Product H. ________________ ________________ - * |_____U1 x V1____||____U0 x V0_____| - * Put result in upper part of PROD and pass low part of TSPACE - * as new TSPACE. - */ - MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace); - - /* Product M. ________________ - * |_(U1-U0)(V0-V1)_| - */ - if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) { - mpihelp_sub_n(prodp, up + hsize, up, hsize); - negflg = 0; - } - else { - mpihelp_sub_n(prodp, up, up + hsize, hsize); - negflg = 1; - } - if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) { - mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize); - negflg ^= 1; - } - else { - mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize); - /* No change of NEGFLG. */ - } - /* Read temporary operands from low part of PROD. - * Put result in low part of TSPACE using upper part of TSPACE - * as new TSPACE. - */ - MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size); - - /* Add/copy product H. */ - MPN_COPY (prodp + hsize, prodp + size, hsize); - cy = mpihelp_add_n( prodp + size, prodp + size, - prodp + size + hsize, hsize); - - /* Add product M (if NEGFLG M is a negative number) */ - if(negflg) - cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size); - else - cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); - - /* Product L. ________________ ________________ - * |________________||____U0 x V0_____| - * Read temporary operands from low part of PROD. - * Put result in low part of TSPACE using upper part of TSPACE - * as new TSPACE. - */ - MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); - - /* Add/copy Product L (twice) */ - - cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); - if( cy ) - mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy); - - MPN_COPY(prodp, tspace, hsize); - cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize); - if( cy ) - mpihelp_add_1(prodp + size, prodp + size, size, 1); - } -} - - -void -mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ) -{ - mpi_size_t i; - mpi_limb_t cy_limb; - mpi_limb_t v_limb; - - /* Multiply by the first limb in V separately, as the result can be - * stored (not added) to PROD. We also avoid a loop for zeroing. */ - v_limb = up[0]; - if( v_limb <= 1 ) { - if( v_limb == 1 ) - MPN_COPY( prodp, up, size ); - else - MPN_ZERO(prodp, size); - cy_limb = 0; - } - else - cy_limb = mpihelp_mul_1( prodp, up, size, v_limb ); - - prodp[size] = cy_limb; - prodp++; - - /* For each iteration in the outer loop, multiply one limb from - * U with one limb from V, and add it to PROD. */ - for( i=1; i < size; i++) { - v_limb = up[i]; - if( v_limb <= 1 ) { - cy_limb = 0; - if( v_limb == 1 ) - cy_limb = mpihelp_add_n(prodp, prodp, up, size); - } - else - cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb); - - prodp[size] = cy_limb; - prodp++; - } -} - - -void -mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) -{ - if( size & 1 ) { - /* The size is odd, and the code below doesn't handle that. - * Multiply the least significant (size - 1) limbs with a recursive - * call, and handle the most significant limb of S1 and S2 - * separately. - * A slightly faster way to do this would be to make the Karatsuba - * code below behave as if the size were even, and let it check for - * odd size in the end. I.e., in essence move this code to the end. - * Doing so would save us a recursive call, and potentially make the - * stack grow a lot less. - */ - mpi_size_t esize = size - 1; /* even size */ - mpi_limb_t cy_limb; - - MPN_SQR_N_RECURSE( prodp, up, esize, tspace ); - cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] ); - prodp[esize + esize] = cy_limb; - cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] ); - - prodp[esize + size] = cy_limb; - } - else { - mpi_size_t hsize = size >> 1; - mpi_limb_t cy; - - /* Product H. ________________ ________________ - * |_____U1 x U1____||____U0 x U0_____| - * Put result in upper part of PROD and pass low part of TSPACE - * as new TSPACE. - */ - MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); - - /* Product M. ________________ - * |_(U1-U0)(U0-U1)_| - */ - if( mpihelp_cmp( up + hsize, up, hsize) >= 0 ) - mpihelp_sub_n( prodp, up + hsize, up, hsize); - else - mpihelp_sub_n (prodp, up, up + hsize, hsize); - - /* Read temporary operands from low part of PROD. - * Put result in low part of TSPACE using upper part of TSPACE - * as new TSPACE. */ - MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); - - /* Add/copy product H */ - MPN_COPY(prodp + hsize, prodp + size, hsize); - cy = mpihelp_add_n(prodp + size, prodp + size, - prodp + size + hsize, hsize); - - /* Add product M (if NEGFLG M is a negative number). */ - cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size); - - /* Product L. ________________ ________________ - * |________________||____U0 x U0_____| - * Read temporary operands from low part of PROD. - * Put result in low part of TSPACE using upper part of TSPACE - * as new TSPACE. */ - MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); - - /* Add/copy Product L (twice). */ - cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size); - if( cy ) - mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, - hsize, cy); - - MPN_COPY(prodp, tspace, hsize); - cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); - if( cy ) - mpihelp_add_1 (prodp + size, prodp + size, size, 1); - } -} - - -/* This should be made into an inline function in gmp.h. */ -void -mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) -{ - int secure; - - if( up == vp ) { - if( size < KARATSUBA_THRESHOLD ) - mpih_sqr_n_basecase( prodp, up, size ); - else { - mpi_ptr_t tspace; - secure = m_is_secure( up ); - tspace = mpi_alloc_limb_space( 2 * size, secure ); - mpih_sqr_n( prodp, up, size, tspace ); - mpi_free_limb_space( tspace ); - } - } - else { - if( size < KARATSUBA_THRESHOLD ) - mul_n_basecase( prodp, up, vp, size ); - else { - mpi_ptr_t tspace; - secure = m_is_secure( up ) || m_is_secure( vp ); - tspace = mpi_alloc_limb_space( 2 * size, secure ); - mul_n (prodp, up, vp, size, tspace); - mpi_free_limb_space( tspace ); - } - } -} - - - -void -mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, - mpi_ptr_t up, mpi_size_t usize, - mpi_ptr_t vp, mpi_size_t vsize, - struct karatsuba_ctx *ctx ) -{ - mpi_limb_t cy; - - if( !ctx->tspace || ctx->tspace_size < vsize ) { - if( ctx->tspace ) - mpi_free_limb_space( ctx->tspace ); - ctx->tspace = mpi_alloc_limb_space( 2 * vsize, - m_is_secure( up ) || m_is_secure( vp ) ); - ctx->tspace_size = vsize; - } - - MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); - - prodp += vsize; - up += vsize; - usize -= vsize; - if( usize >= vsize ) { - if( !ctx->tp || ctx->tp_size < vsize ) { - if( ctx->tp ) - mpi_free_limb_space( ctx->tp ); - ctx->tp = mpi_alloc_limb_space( 2 * vsize, m_is_secure( up ) - || m_is_secure( vp ) ); - ctx->tp_size = vsize; - } - - do { - MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); - cy = mpihelp_add_n( prodp, prodp, ctx->tp, vsize ); - mpihelp_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); - prodp += vsize; - up += vsize; - usize -= vsize; - } while( usize >= vsize ); - } - - if( usize ) { - if( usize < KARATSUBA_THRESHOLD ) { - mpihelp_mul( ctx->tspace, vp, vsize, up, usize ); - } - else { - if( !ctx->next ) { - ctx->next = m_alloc_clear( sizeof *ctx ); - } - mpihelp_mul_karatsuba_case( ctx->tspace, - vp, vsize, - up, usize, - ctx->next ); - } - - cy = mpihelp_add_n( prodp, prodp, ctx->tspace, vsize); - mpihelp_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); - } -} - - -void -mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ) -{ - struct karatsuba_ctx *ctx2; - - if( ctx->tp ) - mpi_free_limb_space( ctx->tp ); - if( ctx->tspace ) - mpi_free_limb_space( ctx->tspace ); - for( ctx=ctx->next; ctx; ctx = ctx2 ) { - ctx2 = ctx->next; - if( ctx->tp ) - mpi_free_limb_space( ctx->tp ); - if( ctx->tspace ) - mpi_free_limb_space( ctx->tspace ); - m_free( ctx ); - } -} - -/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) - * and v (pointed to by VP, with VSIZE limbs), and store the result at - * PRODP. USIZE + VSIZE limbs are always stored, but if the input - * operands are normalized. Return the most significant limb of the - * result. - * - * NOTE: The space pointed to by PRODP is overwritten before finished - * with U and V, so overlap is an error. - * - * Argument constraints: - * 1. USIZE >= VSIZE. - * 2. PRODP != UP and PRODP != VP, i.e. the destination - * must be distinct from the multiplier and the multiplicand. - */ - -mpi_limb_t -mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, - mpi_ptr_t vp, mpi_size_t vsize) -{ - mpi_ptr_t prod_endp = prodp + usize + vsize - 1; - mpi_limb_t cy; - struct karatsuba_ctx ctx; - - if( vsize < KARATSUBA_THRESHOLD ) { - mpi_size_t i; - mpi_limb_t v_limb; - - if( !vsize ) - return 0; - - /* Multiply by the first limb in V separately, as the result can be - * stored (not added) to PROD. We also avoid a loop for zeroing. */ - v_limb = vp[0]; - if( v_limb <= 1 ) { - if( v_limb == 1 ) - MPN_COPY( prodp, up, usize ); - else - MPN_ZERO( prodp, usize ); - cy = 0; - } - else - cy = mpihelp_mul_1( prodp, up, usize, v_limb ); - - prodp[usize] = cy; - prodp++; - - /* For each iteration in the outer loop, multiply one limb from - * U with one limb from V, and add it to PROD. */ - for( i = 1; i < vsize; i++ ) { - v_limb = vp[i]; - if( v_limb <= 1 ) { - cy = 0; - if( v_limb == 1 ) - cy = mpihelp_add_n(prodp, prodp, up, usize); - } - else - cy = mpihelp_addmul_1(prodp, up, usize, v_limb); - - prodp[usize] = cy; - prodp++; - } - - return cy; - } - - memset( &ctx, 0, sizeof ctx ); - mpihelp_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ); - mpihelp_release_karatsuba_ctx( &ctx ); - return *prod_endp; -} - - diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c deleted file mode 100644 index 04e280caa..000000000 --- a/mpi/mpiutil.c +++ /dev/null @@ -1,471 +0,0 @@ -/* mpiutil.ac - Utility functions for MPI - * Copyright (C) 1998, 1999 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 -#include -#include -#include -#include - -#include "mpi.h" -#include "mpi-internal.h" -#include "memory.h" -#include "util.h" - - -#ifdef M_DEBUG - #undef mpi_alloc - #undef mpi_alloc_secure - #undef mpi_free -#endif - -/**************** - * Note: It was a bad idea to use the number of limbs to allocate - * because on a alpha the limbs are large but we normally need - * integers of n bits - So we should chnage this to bits (or bytes). - * - * But mpi_alloc is used in a lot of places :-) - */ -MPI -#ifdef M_DEBUG -mpi_debug_alloc( unsigned nlimbs, const char *info ) -#else -mpi_alloc( unsigned nlimbs ) -#endif -{ - MPI a; - - if( DBG_MEMORY ) - log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); - #ifdef M_DEBUG - a = m_debug_alloc( sizeof *a, info ); - a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL; - #else - a = m_alloc( sizeof *a ); - a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; - #endif - a->alloced = nlimbs; - a->nlimbs = 0; - a->sign = 0; - a->flags = 0; - a->nbits = 0; - return a; -} - -void -mpi_m_check( MPI a ) -{ - m_check(a); - m_check(a->d); -} - -MPI -#ifdef M_DEBUG -mpi_debug_alloc_secure( unsigned nlimbs, const char *info ) -#else -mpi_alloc_secure( unsigned nlimbs ) -#endif -{ - MPI a; - - if( DBG_MEMORY ) - log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); - #ifdef M_DEBUG - a = m_debug_alloc( sizeof *a, info ); - a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL; - #else - a = m_alloc( sizeof *a ); - a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; - #endif - a->alloced = nlimbs; - a->flags = 1; - a->nlimbs = 0; - a->sign = 0; - a->nbits = 0; - return a; -} - - -#if 0 -static void *unused_limbs_5; -static void *unused_limbs_32; -static void *unused_limbs_64; -#endif - -mpi_ptr_t -#ifdef M_DEBUG -mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info ) -#else -mpi_alloc_limb_space( unsigned nlimbs, int secure ) -#endif -{ - size_t len = nlimbs * sizeof(mpi_limb_t); - mpi_ptr_t p; - - if( DBG_MEMORY ) - log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 ); - #if 0 - if( !secure ) { - if( nlimbs == 5 && unused_limbs_5 ) { /* DSA 160 bits */ - p = unused_limbs_5; - unused_limbs_5 = *p; - return p; - } - else if( nlimbs == 32 && unused_limbs_32 ) { /* DSA 1024 bits */ - p = unused_limbs_32; - unused_limbs_32 = *p; - return p; - } - else if( nlimbs == 64 && unused_limbs_64 ) { /* DSA 2*1024 bits */ - p = unused_limbs_64; - unused_limbs_64 = *p; - return p; - } - } - #endif - - #ifdef M_DEBUG - p = secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info ); - #else - p = secure? m_alloc_secure( len ):m_alloc( len ); - #endif - - return p; -} - -void -#ifdef M_DEBUG -mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ) -#else -mpi_free_limb_space( mpi_ptr_t a ) -#endif -{ - if( !a ) - return; - if( DBG_MEMORY ) - log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 ); - - #if 0 - if( !m_is_secure(a) ) { - size_t nlimbs = m_size(a) / 4 ; - void *p = a; - - if( nlimbs == 5 ) { /* DSA 160 bits */ - *a = unused_limbs_5; - unused_limbs_5 = a; - return; - } - else if( nlimbs == 32 ) { /* DSA 1024 bits */ - *a = unused_limbs_32; - unused_limbs_32 = a; - return; - } - else if( nlimbs == 64 ) { /* DSA 2*1024 bits */ - *a = unused_limbs_64; - unused_limbs_64 = a; - return; - } - } - #endif - - - m_free(a); -} - - -void -mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ) -{ - mpi_free_limb_space(a->d); - a->d = ap; - a->alloced = nlimbs; -} - - - -/**************** - * Resize the array of A to NLIMBS. the additional space is cleared - * (set to 0) [done by m_realloc()] - */ -void -#ifdef M_DEBUG -mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ) -#else -mpi_resize( MPI a, unsigned nlimbs ) -#endif -{ - if( nlimbs <= a->alloced ) - return; /* no need to do it */ - /* Note: a->secure is not used - instead the realloc functions - * take care of it. Maybe we should drop a->secure completely - * and rely on a mpi_is_secure function, which would be - * a wrapper around m_is_secure - */ - #ifdef M_DEBUG - if( a->d ) - a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info ); - else - a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info ); - #else - if( a->d ) - a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) ); - else - a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) ); - #endif - a->alloced = nlimbs; -} - -void -mpi_clear( MPI a ) -{ - a->nlimbs = 0; - a->nbits = 0; - a->flags = 0; -} - - -void -#ifdef M_DEBUG -mpi_debug_free( MPI a, const char *info ) -#else -mpi_free( MPI a ) -#endif -{ - if( !a ) - return; - if( DBG_MEMORY ) - log_debug("mpi_free\n" ); - if( a->flags & 4 ) - m_free( a->d ); - else { - #ifdef M_DEBUG - mpi_debug_free_limb_space(a->d, info); - #else - mpi_free_limb_space(a->d); - #endif - } - if( a->flags & ~7 ) - log_bug("invalid flag value in mpi\n"); - m_free(a); -} - - -void -mpi_set_secure( MPI a ) -{ - mpi_ptr_t ap, bp; - - if( (a->flags & 1) ) - return; - a->flags |= 1; - ap = a->d; - if( !a->nlimbs ) { - assert(!ap); - return; - } - #ifdef M_DEBUG - bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" ); - #else - bp = mpi_alloc_limb_space( a->nlimbs, 1 ); - #endif - MPN_COPY( bp, ap, a->nlimbs ); - a->d = bp; - #ifdef M_DEBUG - mpi_debug_free_limb_space(ap, "set_secure"); - #else - mpi_free_limb_space(ap); - #endif -} - - -MPI -mpi_set_opaque( MPI a, void *p, int len ) -{ - if( !a ) { - #ifdef M_DEBUG - a = mpi_debug_alloc(0,"alloc_opaque"); - #else - a = mpi_alloc(0); - #endif - } - - if( a->flags & 4 ) - m_free( a->d ); - else { - #ifdef M_DEBUG - mpi_debug_free_limb_space(a->d, "alloc_opaque"); - #else - mpi_free_limb_space(a->d); - #endif - } - - a->d = p; - a->alloced = 0; - a->nlimbs = 0; - a->nbits = len; - a->flags = 4; - return a; -} - - -void * -mpi_get_opaque( MPI a, int *len ) -{ - if( !(a->flags & 4) ) - log_bug("mpi_get_opaque on normal mpi\n"); - if( len ) - *len = a->nbits; - return a->d; -} - - -/**************** - * Note: This copy function should not interpret the MPI - * but copy it transparently. - */ -MPI -#ifdef M_DEBUG -mpi_debug_copy( MPI a, const char *info ) -#else -mpi_copy( MPI a ) -#endif -{ - int i; - MPI b; - - if( a && (a->flags & 4) ) { - void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) - : m_alloc( a->nbits ); - memcpy( p, a->d, a->nbits ); - b = mpi_set_opaque( NULL, p, a->nbits ); - } - else if( a ) { - #ifdef M_DEBUG - b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) - : mpi_debug_alloc( a->nlimbs, info ); - #else - b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) - : mpi_alloc( a->nlimbs ); - #endif - b->nlimbs = a->nlimbs; - b->sign = a->sign; - b->flags = a->flags; - b->nbits = a->nbits; - for(i=0; i < b->nlimbs; i++ ) - b->d[i] = a->d[i]; - } - else - b = NULL; - return b; -} - - -/**************** - * This function allocates an MPI which is optimized to hold - * a value as large as the one given in the arhgument and allocates it - * with the same flags as A. - */ -MPI -#ifdef M_DEBUG -mpi_debug_alloc_like( MPI a, const char *info ) -#else -mpi_alloc_like( MPI a ) -#endif -{ - MPI b; - - if( a && (a->flags & 4) ) { - void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) - : m_alloc( a->nbits ); - memcpy( p, a->d, a->nbits ); - b = mpi_set_opaque( NULL, p, a->nbits ); - } - else if( a ) { - #ifdef M_DEBUG - b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) - : mpi_debug_alloc( a->nlimbs, info ); - #else - b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) - : mpi_alloc( a->nlimbs ); - #endif - b->nlimbs = 0; - b->sign = 0; - b->flags = a->flags; - b->nbits = 0; - } - else - b = NULL; - return b; -} - - -void -mpi_set( MPI w, MPI u) -{ - mpi_ptr_t wp, up; - mpi_size_t usize = u->nlimbs; - int usign = u->sign; - - RESIZE_IF_NEEDED(w, usize); - wp = w->d; - up = u->d; - MPN_COPY( wp, up, usize ); - w->nlimbs = usize; - w->nbits = u->nbits; - w->flags = u->flags; - w->sign = usign; -} - - -void -mpi_set_ui( MPI w, unsigned long u) -{ - RESIZE_IF_NEEDED(w, 1); - w->d[0] = u; - w->nlimbs = u? 1:0; - w->sign = 0; - w->nbits = 0; - w->flags = 0; -} - - -MPI -mpi_alloc_set_ui( unsigned long u) -{ - #ifdef M_DEBUG - MPI w = mpi_debug_alloc(1,"alloc_set_ui"); - #else - MPI w = mpi_alloc(1); - #endif - w->d[0] = u; - w->nlimbs = u? 1:0; - w->sign = 0; - return w; -} - - -void -mpi_swap( MPI a, MPI b) -{ - struct gcry_mpi tmp; - - tmp = *a; *a = *b; *b = tmp; -} - diff --git a/mpi/pa7100/distfiles b/mpi/pa7100/distfiles deleted file mode 100644 index fece94310..000000000 --- a/mpi/pa7100/distfiles +++ /dev/null @@ -1,3 +0,0 @@ -mpih-lshift.S -mpih-rshift.S - diff --git a/mpi/pa7100/mpih-lshift.S b/mpi/pa7100/mpih-lshift.S deleted file mode 100644 index 76368fe78..000000000 --- a/mpi/pa7100/mpih-lshift.S +++ /dev/null @@ -1,96 +0,0 @@ -/* hppa lshift - * optimized for the PA7100, where it runs at 3.25 cycles/limb - * - * Copyright (C) 1992, 1994, 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 - */ - - - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (gr26) - * mpi_ptr_t up, (gr25) - * mpi_size_t usize, (gr24) - * unsigned cnt) (gr23) - */ - - .code - .export mpihelp_lshift - .label mpihelp_lshift - .proc - .callinfo frame=64,no_calls - .entry - - sh2add %r24,%r25,%r25 - sh2add %r24,%r26,%r26 - ldws,mb -4(0,%r25),%r22 - subi 32,%r23,%r1 - mtsar %r1 - addib,= -1,%r24,L$0004 - vshd %r0,%r22,%r28 ; compute carry out limb - ldws,mb -4(0,%r25),%r29 - addib,<= -5,%r24,L$rest - vshd %r22,%r29,%r20 - - .label L$loop - ldws,mb -4(0,%r25),%r22 - stws,mb %r20,-4(0,%r26) - vshd %r29,%r22,%r20 - ldws,mb -4(0,%r25),%r29 - stws,mb %r20,-4(0,%r26) - vshd %r22,%r29,%r20 - ldws,mb -4(0,%r25),%r22 - stws,mb %r20,-4(0,%r26) - vshd %r29,%r22,%r20 - ldws,mb -4(0,%r25),%r29 - stws,mb %r20,-4(0,%r26) - addib,> -4,%r24,L$loop - vshd %r22,%r29,%r20 - - .label L$rest - addib,= 4,%r24,L$end1 - nop - .label L$eloop - ldws,mb -4(0,%r25),%r22 - stws,mb %r20,-4(0,%r26) - addib,<= -1,%r24,L$end2 - vshd %r29,%r22,%r20 - ldws,mb -4(0,%r25),%r29 - stws,mb %r20,-4(0,%r26) - addib,> -1,%r24,L$eloop - vshd %r22,%r29,%r20 - - .label L$end1 - stws,mb %r20,-4(0,%r26) - vshd %r29,%r0,%r20 - bv 0(%r2) - stw %r20,-4(0,%r26) - .label L$end2 - stws,mb %r20,-4(0,%r26) - .label L$0004 - vshd %r22,%r0,%r20 - bv 0(%r2) - stw %r20,-4(0,%r26) - - .exit - .procend - - - diff --git a/mpi/pa7100/mpih-rshift.S b/mpi/pa7100/mpih-rshift.S deleted file mode 100644 index 3bada7ce9..000000000 --- a/mpi/pa7100/mpih-rshift.S +++ /dev/null @@ -1,92 +0,0 @@ -/* hppa rshift - * optimized for the PA7100, where it runs at 3.25 cycles/limb - * - * Copyright (C) 1992, 1994, 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 - */ - - - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (gr26) - * mpi_ptr_t up, (gr25) - * mpi_size_t usize, (gr24) - * unsigned cnt) (gr23) - */ - - .code - .export mpihelp_rshift - .label mpihelp_rshift - .proc - .callinfo frame=64,no_calls - .entry - - ldws,ma 4(0,%r25),%r22 - mtsar %r23 - addib,= -1,%r24,L$r004 - vshd %r22,%r0,%r28 ; compute carry out limb - ldws,ma 4(0,%r25),%r29 - addib,<= -5,%r24,L$rrest - vshd %r29,%r22,%r20 - - .label L$roop - ldws,ma 4(0,%r25),%r22 - stws,ma %r20,4(0,%r26) - vshd %r22,%r29,%r20 - ldws,ma 4(0,%r25),%r29 - stws,ma %r20,4(0,%r26) - vshd %r29,%r22,%r20 - ldws,ma 4(0,%r25),%r22 - stws,ma %r20,4(0,%r26) - vshd %r22,%r29,%r20 - ldws,ma 4(0,%r25),%r29 - stws,ma %r20,4(0,%r26) - addib,> -4,%r24,L$roop - vshd %r29,%r22,%r20 - - .label L$rrest - addib,= 4,%r24,L$rend1 - nop - .label L$eroop - ldws,ma 4(0,%r25),%r22 - stws,ma %r20,4(0,%r26) - addib,<= -1,%r24,L$rend2 - vshd %r22,%r29,%r20 - ldws,ma 4(0,%r25),%r29 - stws,ma %r20,4(0,%r26) - addib,> -1,%r24,L$eroop - vshd %r29,%r22,%r20 - - .label L$rend1 - stws,ma %r20,4(0,%r26) - vshd %r0,%r29,%r20 - bv 0(%r2) - stw %r20,0(0,%r26) - .label L$rend2 - stws,ma %r20,4(0,%r26) - .label L$r004 - vshd %r0,%r22,%r20 - bv 0(%r2) - stw %r20,0(0,%r26) - - .exit - .procend - - diff --git a/mpi/power/distfiles b/mpi/power/distfiles deleted file mode 100644 index e664c8db6..000000000 --- a/mpi/power/distfiles +++ /dev/null @@ -1,7 +0,0 @@ -mpih-add1.S -mpih-lshift.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S -mpih-rshift.S -mpih-sub1.S diff --git a/mpi/power/mpih-add1.S b/mpi/power/mpih-add1.S deleted file mode 100644 index 7313ac618..000000000 --- a/mpi/power/mpih-add1.S +++ /dev/null @@ -1,86 +0,0 @@ -/* IBM POWER add_n -- Add two limb vectors of equal, non-zero length. - * - * Copyright (C) 1992, 1994, 1996, 1999 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 "sysdep.h" -#include "asm-syntax.h" - -/* -# INPUT PARAMETERS -# res_ptr r3 -# s1_ptr r4 -# s2_ptr r5 -# size r6 - */ - - .toc - .extern mpihelp_add_n[DS] - .extern .mpihelp_add_n -.csect [PR] - .align 2 - .globl mpihelp_add_n - .globl .mpihelp_add_n - .csect mpihelp_add_n[DS] -mpihelp_add_n: - .long .mpihelp_add_n, TOC[tc0], 0 - .csect [PR] -.mpihelp_add_n: - andil. 10,6,1 # odd or even number of limbs? - l 8,0(4) # load least significant s1 limb - l 0,0(5) # load least significant s2 limb - cal 3,-4(3) # offset res_ptr, it's updated before it's used - sri 10,6,1 # count for unrolled loop - a 7,0,8 # add least significant limbs, set cy - mtctr 10 # copy count into CTR - beq 0,Leven # branch if even # of limbs (# of limbs >= 2) - -# We have an odd # of limbs. Add the first limbs separately. - cmpi 1,10,0 # is count for unrolled loop zero? - bne 1,L1 # branch if not - st 7,4(3) - aze 3,10 # use the fact that r10 is zero... - br # return - -# We added least significant limbs. Now reload the next limbs to enter loop. -L1: lu 8,4(4) # load s1 limb and update s1_ptr - lu 0,4(5) # load s2 limb and update s2_ptr - stu 7,4(3) - ae 7,0,8 # add limbs, set cy -Leven: lu 9,4(4) # load s1 limb and update s1_ptr - lu 10,4(5) # load s2 limb and update s2_ptr - bdz Lend # If done, skip loop - -Loop: lu 8,4(4) # load s1 limb and update s1_ptr - lu 0,4(5) # load s2 limb and update s2_ptr - ae 11,9,10 # add previous limbs with cy, set cy - stu 7,4(3) # - lu 9,4(4) # load s1 limb and update s1_ptr - lu 10,4(5) # load s2 limb and update s2_ptr - ae 7,0,8 # add previous limbs with cy, set cy - stu 11,4(3) # - bdn Loop # decrement CTR and loop back - -Lend: ae 11,9,10 # add limbs with cy, set cy - st 7,4(3) # - st 11,8(3) # - lil 3,0 # load cy into ... - aze 3,3 # ... return value register - br - diff --git a/mpi/power/mpih-lshift.S b/mpi/power/mpih-lshift.S deleted file mode 100644 index 20cf45353..000000000 --- a/mpi/power/mpih-lshift.S +++ /dev/null @@ -1,64 +0,0 @@ -/* IBM POWER lshift - * - * Copyright (C) 1992, 1994, 1999 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 "sysdep.h" -#include "asm-syntax.h" - -/* -# INPUT PARAMETERS -# res_ptr r3 -# s_ptr r4 -# size r5 -# cnt r6 - */ - - .toc - .extern mpihelp_lshift[DS] - .extern .mpihelp_lshift -.csect [PR] - .align 2 - .globl mpihelp_lshift - .globl .mpihelp_lshift - .csect mpihelp_lshift[DS] -mpihelp_lshift: - .long .mpihelp_lshift, TOC[tc0], 0 - .csect [PR] -.mpihelp_lshift: - sli 0,5,2 - cax 9,3,0 - cax 4,4,0 - sfi 8,6,32 - mtctr 5 # put limb count in CTR loop register - lu 0,-4(4) # read most significant limb - sre 3,0,8 # compute carry out limb, and init MQ register - bdz Lend2 # if just one limb, skip loop - lu 0,-4(4) # read 2:nd most significant limb - sreq 7,0,8 # compute most significant limb of result - bdz Lend # if just two limb, skip loop -Loop: lu 0,-4(4) # load next lower limb - stu 7,-4(9) # store previous result during read latency - sreq 7,0,8 # compute result limb - bdn Loop # loop back until CTR is zero -Lend: stu 7,-4(9) # store 2:nd least significant limb -Lend2: sle 7,0,6 # compute least significant limb - st 7,-4(9) # store it - br - diff --git a/mpi/power/mpih-mul1.S b/mpi/power/mpih-mul1.S deleted file mode 100644 index 03fff4f98..000000000 --- a/mpi/power/mpih-mul1.S +++ /dev/null @@ -1,115 +0,0 @@ -/* IBM POWER mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1994, 1999 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 "sysdep.h" -#include "asm-syntax.h" - -/* -# INPUT PARAMETERS -# res_ptr r3 -# s1_ptr r4 -# size r5 -# s2_limb r6 - -# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To -# obtain that operation, we have to use the 32x32->64 signed multiplication -# instruction, and add the appropriate compensation to the high limb of the -# result. We add the multiplicand if the multiplier has its most significant -# bit set, and we add the multiplier if the multiplicand has its most -# significant bit set. We need to preserve the carry flag between each -# iteration, so we have to compute the compensation carefully (the natural, -# srai+and doesn't work). Since the POWER architecture has a branch unit -# we can branch in zero cycles, so that's how we perform the additions. - */ - - .toc - .csect .mpihelp_mul_1[PR] - .align 2 - .globl mpihelp_mul_1 - .globl .mpihelp_mul_1 - .csect mpihelp_mul_1[DS] -mpihelp_mul_1: - .long .mpihelp_mul_1[PR], TOC[tc0], 0 - .csect .mpihelp_mul_1[PR] -.mpihelp_mul_1: - - cal 3,-4(3) - l 0,0(4) - cmpi 0,6,0 - mtctr 5 - mul 9,0,6 - srai 7,0,31 - and 7,7,6 - mfmq 8 - ai 0,0,0 # reset carry - cax 9,9,7 - blt Lneg -Lpos: bdz Lend -Lploop: lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 10,0,6 - mfmq 0 - ae 8,0,9 - bge Lp0 - cax 10,10,6 # adjust high limb for negative limb from s1 -Lp0: bdz Lend0 - lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 9,0,6 - mfmq 0 - ae 8,0,10 - bge Lp1 - cax 9,9,6 # adjust high limb for negative limb from s1 -Lp1: bdn Lploop - b Lend - -Lneg: cax 9,9,0 - bdz Lend -Lnloop: lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 10,0,6 - cax 10,10,0 # adjust high limb for negative s2_limb - mfmq 0 - ae 8,0,9 - bge Ln0 - cax 10,10,6 # adjust high limb for negative limb from s1 -Ln0: bdz Lend0 - lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 9,0,6 - cax 9,9,0 # adjust high limb for negative s2_limb - mfmq 0 - ae 8,0,10 - bge Ln1 - cax 9,9,6 # adjust high limb for negative limb from s1 -Ln1: bdn Lnloop - b Lend - -Lend0: cal 9,0(10) -Lend: st 8,4(3) - aze 3,9 - br - diff --git a/mpi/power/mpih-mul2.S b/mpi/power/mpih-mul2.S deleted file mode 100644 index 3d7fc153c..000000000 --- a/mpi/power/mpih-mul2.S +++ /dev/null @@ -1,130 +0,0 @@ -/* IBM POWER addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1992, 1994, 1999 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 "sysdep.h" -#include "asm-syntax.h" - - - -/* -# INPUT PARAMETERS -# res_ptr r3 -# s1_ptr r4 -# size r5 -# s2_limb r6 - -# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To -# obtain that operation, we have to use the 32x32->64 signed multiplication -# instruction, and add the appropriate compensation to the high limb of the -# result. We add the multiplicand if the multiplier has its most significant -# bit set, and we add the multiplier if the multiplicand has its most -# significant bit set. We need to preserve the carry flag between each -# iteration, so we have to compute the compensation carefully (the natural, -# srai+and doesn't work). Since the POWER architecture has a branch unit -# we can branch in zero cycles, so that's how we perform the additions. - */ - - .toc - .csect .mpihelp_addmul_1[PR] - .align 2 - .globl mpihelp_addmul_1 - .globl .mpihelp_addmul_1 - .csect mpihelp_addmul_1[DS] -mpihelp_addmul_1: - .long .mpihelp_addmul_1[PR], TOC[tc0], 0 - .csect .mpihelp_addmul_1[PR] -.mpihelp_addmul_1: - - cal 3,-4(3) - l 0,0(4) - cmpi 0,6,0 - mtctr 5 - mul 9,0,6 - srai 7,0,31 - and 7,7,6 - mfmq 8 - cax 9,9,7 - l 7,4(3) - a 8,8,7 # add res_limb - blt Lneg -Lpos: bdz Lend - -Lploop: lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 10,0,6 - mfmq 0 - ae 8,0,9 # low limb + old_cy_limb + old cy - l 7,4(3) - aze 10,10 # propagate cy to new cy_limb - a 8,8,7 # add res_limb - bge Lp0 - cax 10,10,6 # adjust high limb for negative limb from s1 -Lp0: bdz Lend0 - lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 9,0,6 - mfmq 0 - ae 8,0,10 - l 7,4(3) - aze 9,9 - a 8,8,7 - bge Lp1 - cax 9,9,6 # adjust high limb for negative limb from s1 -Lp1: bdn Lploop - - b Lend - -Lneg: cax 9,9,0 - bdz Lend -Lnloop: lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 10,0,6 - mfmq 7 - ae 8,7,9 - l 7,4(3) - ae 10,10,0 # propagate cy to new cy_limb - a 8,8,7 # add res_limb - bge Ln0 - cax 10,10,6 # adjust high limb for negative limb from s1 -Ln0: bdz Lend0 - lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 9,0,6 - mfmq 7 - ae 8,7,10 - l 7,4(3) - ae 9,9,0 # propagate cy to new cy_limb - a 8,8,7 # add res_limb - bge Ln1 - cax 9,9,6 # adjust high limb for negative limb from s1 -Ln1: bdn Lnloop - b Lend - -Lend0: cal 9,0(10) -Lend: st 8,4(3) - aze 3,9 - br - diff --git a/mpi/power/mpih-mul3.S b/mpi/power/mpih-mul3.S deleted file mode 100644 index f94018ca9..000000000 --- a/mpi/power/mpih-mul3.S +++ /dev/null @@ -1,135 +0,0 @@ -/* IBM POWER submul_1 -- Multiply a limb vector with a limb and subtract - * the result from a second limb vector. - * - * Copyright (C) 1992, 1994, 1999 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 "sysdep.h" -#include "asm-syntax.h" - - -/* - -# INPUT PARAMETERS -# res_ptr r3 -# s1_ptr r4 -# size r5 -# s2_limb r6 - -# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To -# obtain that operation, we have to use the 32x32->64 signed multiplication -# instruction, and add the appropriate compensation to the high limb of the -# result. We add the multiplicand if the multiplier has its most significant -# bit set, and we add the multiplier if the multiplicand has its most -# significant bit set. We need to preserve the carry flag between each -# iteration, so we have to compute the compensation carefully (the natural, -# srai+and doesn't work). Since the POWER architecture has a branch unit -# we can branch in zero cycles, so that's how we perform the additions. - */ - - .toc - .csect .mpihelp_submul_1[PR] - .align 2 - .globl mpihelp_submul_1 - .globl .mpihelp_submul_1 - .csect mpihelp_submul_1[DS] -mpihelp_submul_1: - .long .mpihelp_submul_1[PR], TOC[tc0], 0 - .csect .mpihelp_submul_1[PR] -.mpihelp_submul_1: - - cal 3,-4(3) - l 0,0(4) - cmpi 0,6,0 - mtctr 5 - mul 9,0,6 - srai 7,0,31 - and 7,7,6 - mfmq 11 - cax 9,9,7 - l 7,4(3) - sf 8,11,7 # add res_limb - a 11,8,11 # invert cy (r11 is junk) - blt Lneg -Lpos: bdz Lend - -Lploop: lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 10,0,6 - mfmq 0 - ae 11,0,9 # low limb + old_cy_limb + old cy - l 7,4(3) - aze 10,10 # propagate cy to new cy_limb - sf 8,11,7 # add res_limb - a 11,8,11 # invert cy (r11 is junk) - bge Lp0 - cax 10,10,6 # adjust high limb for negative limb from s1 -Lp0: bdz Lend0 - lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 9,0,6 - mfmq 0 - ae 11,0,10 - l 7,4(3) - aze 9,9 - sf 8,11,7 - a 11,8,11 # invert cy (r11 is junk) - bge Lp1 - cax 9,9,6 # adjust high limb for negative limb from s1 -Lp1: bdn Lploop - - b Lend - -Lneg: cax 9,9,0 - bdz Lend -Lnloop: lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 10,0,6 - mfmq 7 - ae 11,7,9 - l 7,4(3) - ae 10,10,0 # propagate cy to new cy_limb - sf 8,11,7 # add res_limb - a 11,8,11 # invert cy (r11 is junk) - bge Ln0 - cax 10,10,6 # adjust high limb for negative limb from s1 -Ln0: bdz Lend0 - lu 0,4(4) - stu 8,4(3) - cmpi 0,0,0 - mul 9,0,6 - mfmq 7 - ae 11,7,10 - l 7,4(3) - ae 9,9,0 # propagate cy to new cy_limb - sf 8,11,7 # add res_limb - a 11,8,11 # invert cy (r11 is junk) - bge Ln1 - cax 9,9,6 # adjust high limb for negative limb from s1 -Ln1: bdn Lnloop - b Lend - -Lend0: cal 9,0(10) -Lend: st 8,4(3) - aze 3,9 - br - diff --git a/mpi/power/mpih-rshift.S b/mpi/power/mpih-rshift.S deleted file mode 100644 index 04fb5942d..000000000 --- a/mpi/power/mpih-rshift.S +++ /dev/null @@ -1,64 +0,0 @@ -/* IBM POWER rshift - * - * Copyright (C) 1992, 1994, 1999 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 "sysdep.h" -#include "asm-syntax.h" - - -/* -# INPUT PARAMETERS -# res_ptr r3 -# s_ptr r4 -# size r5 -# cnt r6 -*/ - - .toc - .extern mpihelp_rshift[DS] - .extern .mpihelp_rshift -.csect [PR] - .align 2 - .globl mpihelp_rshift - .globl .mpihelp_rshift - .csect mpihelp_rshift[DS] -mpihelp_rshift: - .long .mpihelp_rshift, TOC[tc0], 0 - .csect [PR] -.mpihelp_rshift: - sfi 8,6,32 - mtctr 5 # put limb count in CTR loop register - l 0,0(4) # read least significant limb - ai 9,3,-4 # adjust res_ptr since it's offset in the stu:s - sle 3,0,8 # compute carry limb, and init MQ register - bdz Lend2 # if just one limb, skip loop - lu 0,4(4) # read 2:nd least significant limb - sleq 7,0,8 # compute least significant limb of result - bdz Lend # if just two limb, skip loop -Loop: lu 0,4(4) # load next higher limb - stu 7,4(9) # store previous result during read latency - sleq 7,0,8 # compute result limb - bdn Loop # loop back until CTR is zero -Lend: stu 7,4(9) # store 2:nd most significant limb -Lend2: sre 7,0,6 # compute most significant limb - st 7,4(9) # store it - br - - diff --git a/mpi/power/mpih-sub1.S b/mpi/power/mpih-sub1.S deleted file mode 100644 index 375a5be88..000000000 --- a/mpi/power/mpih-sub1.S +++ /dev/null @@ -1,88 +0,0 @@ -/* IBM POWER sub_n -- Subtract two limb vectors of equal, non-zero length. - * - * Copyright (C) 1992, 1994, 1995, 1996, 1999 - * 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 "sysdep.h" -#include "asm-syntax.h" - -/* -# INPUT PARAMETERS -# res_ptr r3 -# s1_ptr r4 -# s2_ptr r5 -# size r6 - */ - - .toc - .extern mpihelp_sub_n[DS] - .extern .mpihelp_sub_n -.csect [PR] - .align 2 - .globl mpihelp_sub_n - .globl .mpihelp_sub_n - .csect mpihelp_sub_n[DS] -mpihelp_sub_n: - .long .mpihelp_sub_n, TOC[tc0], 0 - .csect [PR] -.mpihelp_sub_n: - andil. 10,6,1 # odd or even number of limbs? - l 8,0(4) # load least significant s1 limb - l 0,0(5) # load least significant s2 limb - cal 3,-4(3) # offset res_ptr, it's updated before it's used - sri 10,6,1 # count for unrolled loop - sf 7,0,8 # subtract least significant limbs, set cy - mtctr 10 # copy count into CTR - beq 0,Leven # branch if even # of limbs (# of limbs >= 2) - -# We have an odd # of limbs. Add the first limbs separately. - cmpi 1,10,0 # is count for unrolled loop zero? - bne 1,L1 # branch if not - st 7,4(3) - sfe 3,0,0 # load !cy into ... - sfi 3,3,0 # ... return value register - br # return - -# We added least significant limbs. Now reload the next limbs to enter loop. -L1: lu 8,4(4) # load s1 limb and update s1_ptr - lu 0,4(5) # load s2 limb and update s2_ptr - stu 7,4(3) - sfe 7,0,8 # subtract limbs, set cy -Leven: lu 9,4(4) # load s1 limb and update s1_ptr - lu 10,4(5) # load s2 limb and update s2_ptr - bdz Lend # If done, skip loop - -Loop: lu 8,4(4) # load s1 limb and update s1_ptr - lu 0,4(5) # load s2 limb and update s2_ptr - sfe 11,10,9 # subtract previous limbs with cy, set cy - stu 7,4(3) # - lu 9,4(4) # load s1 limb and update s1_ptr - lu 10,4(5) # load s2 limb and update s2_ptr - sfe 7,0,8 # subtract previous limbs with cy, set cy - stu 11,4(3) # - bdn Loop # decrement CTR and loop back - -Lend: sfe 11,10,9 # subtract limbs with cy, set cy - st 7,4(3) # - st 11,8(3) # - sfe 3,0,0 # load !cy into ... - sfi 3,3,0 # ... return value register - br - diff --git a/mpi/powerpc32/distfiles b/mpi/powerpc32/distfiles deleted file mode 100644 index af10d795b..000000000 --- a/mpi/powerpc32/distfiles +++ /dev/null @@ -1,9 +0,0 @@ -mpih-add1.S -mpih-sub1.S -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S -mpih-lshift.S -mpih-rshift.S -syntax.h - diff --git a/mpi/powerpc32/mpih-add1.S b/mpi/powerpc32/mpih-add1.S deleted file mode 100644 index 81c4e20f7..000000000 --- a/mpi/powerpc32/mpih-add1.S +++ /dev/null @@ -1,136 +0,0 @@ -/* PowerPC-32 add_n -- Add two limb vectors of equal, non-zero length. - * - * Copyright (C) 1992, 1994, 1995, 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, (r3) - * mpi_ptr_t s1_ptr, (r4) - * mpi_ptr_t s2_ptr, (r5) - * mpi_size_t size) (r6) - */ - - .toc - .extern mpihelp_add_n[DS] - .extern .mpihelp_add_n -.csect [PR] - .align 2 - .globl mpihelp_add_n - .globl .mpihelp_add_n - .csect mpihelp_add_n[DS] -mpihelp_add_n: - .long .mpihelp_add_n, TOC[tc0], 0 - .csect [PR] -.mpihelp_add_n: - mtctr 6 # copy size into CTR - lwz 8,0(4) # load least significant s1 limb - lwz 0,0(5) # load least significant s2 limb - addi 3,3,-4 # offset res_ptr, it is updated before used - addc 7,0,8 # add least significant limbs, set cy - bdz Lend # If done, skip loop -Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr - lwzu 0,4(5) # load s2 limb and update s2_ptr - stwu 7,4(3) # store previous limb in load latency slot - adde 7,0,8 # add new limbs with cy, set cy - bdnz Loop # decrement CTR and loop back -Lend: stw 7,4(3) # store ultimate result limb - li 3,0 # load cy into ... - addze 3,3 # ... return value register - blr - -#else -/* Add two limb vectors of equal, non-zero length for PowerPC. - Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -/* mp_limb_t mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, - mp_size_t size) - Calculate s1+s2 and put result in res_ptr; return carry, 0 or 1. */ - -/* Note on optimisation: This code is optimal for the 601. Almost every other - possible 2-unrolled inner loop will not be. Also, watch out for the - alignment... */ - -EALIGN(mpihelp_add_n,3,0) -/* Set up for loop below. */ - mtcrf 0x01,%r6 - srwi. %r7,%r6,1 - li %r10,0 - mtctr %r7 - bt 31,2f - -/* Clear the carry. */ - addic %r0,%r0,0 -/* Adjust pointers for loop. */ - addi %r3,%r3,-4 - addi %r4,%r4,-4 - addi %r5,%r5,-4 - b 0f - -2: lwz %r7,0(%r5) - lwz %r6,0(%r4) - addc %r6,%r6,%r7 - stw %r6,0(%r3) - beq 1f - -/* The loop. */ - -/* Align start of loop to an odd word boundary to guarantee that the - last two words can be fetched in one access (for 601). */ -0: lwz %r9,4(%r4) - lwz %r8,4(%r5) - lwzu %r6,8(%r4) - lwzu %r7,8(%r5) - adde %r8,%r9,%r8 - stw %r8,4(%r3) - adde %r6,%r6,%r7 - stwu %r6,8(%r3) - bdnz 0b -/* Return the carry. */ -1: addze %r3,%r10 - blr -END(mpihelp_add_n) -#endif - diff --git a/mpi/powerpc32/mpih-lshift.S b/mpi/powerpc32/mpih-lshift.S deleted file mode 100644 index 20ca7f922..000000000 --- a/mpi/powerpc32/mpih-lshift.S +++ /dev/null @@ -1,198 +0,0 @@ -/* PowerPC-32 lshift - * - * Copyright (C) 1995, 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_lshift( mpi_ptr_t wp, (r3) - * mpi_ptr_t up, (r4) - * mpi_size_t usize, (r5) - * unsigned cnt) (r6) - */ - - .toc -.csect .text[PR] - .align 2 - .globl mpihelp_lshift - .globl .mpihelp_lshift - .csect mpihelp_lshift[DS] -mpihelp_lshift: - .long .mpihelp_lshift, TOC[tc0], 0 - .csect .text[PR] -.mpihelp_lshift: - mtctr 5 # copy size into CTR - slwi 0,5,2 - add 7,3,0 # make r7 point at end of res - add 4,4,0 # make r4 point at end of s1 - subfic 8,6,32 - lwzu 11,-4(4) # load first s1 limb - srw 3,11,8 # compute function return value - bdz Lend1 - -Loop: lwzu 10,-4(4) - slw 9,11,6 - srw 12,10,8 - or 9,9,12 - stwu 9,-4(7) - bdz Lend2 - lwzu 11,-4(4) - slw 9,10,6 - srw 12,11,8 - or 9,9,12 - stwu 9,-4(7) - bdnz Loop - -Lend1: slw 0,11,6 - stw 0,-4(7) - blr - -Lend2: slw 0,10,6 - stw 0,-4(7) - blr - -#else -/* Shift a limb left, low level routine. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* mp_limb_t mpn_lshift (mp_ptr wp, mp_srcptr up, mp_size_t usize, - unsigned int cnt) */ - -EALIGN(mpihelp_lshift,3,0) - mtctr %r5 # copy size into CTR - cmplwi %cr0,%r5,16 # is size < 16 - slwi %r0,%r5,2 - add %r7,%r3,%r0 # make r7 point at end of res - add %r4,%r4,%r0 # make r4 point at end of s1 - lwzu %r11,-4(%r4) # load first s1 limb - subfic %r8,%r6,32 - srw %r3,%r11,%r8 # compute function return value - bge %cr0,L(big) # branch if size >= 16 - - bdz L(end1) - -0: lwzu %r10,-4(%r4) - slw %r9,%r11,%r6 - srw %r12,%r10,%r8 - or %r9,%r9,%r12 - stwu %r9,-4(%r7) - bdz L(end2) - lwzu %r11,-4(%r4) - slw %r9,%r10,%r6 - srw %r12,%r11,%r8 - or %r9,%r9,%r12 - stwu %r9,-4(%r7) - bdnz 0b - -L(end1):slw %r0,%r11,%r6 - stw %r0,-4(%r7) - blr - - -/* Guaranteed not to succeed. */ -L(boom): tweq %r0,%r0 - -/* We imitate a case statement, by using (yuk!) fixed-length code chunks, - of size 4*12 bytes. We have to do this (or something) to make this PIC. */ -L(big): mflr %r9 - bltl- %cr0,L(boom) # Never taken, only used to set LR. - slwi %r10,%r6,4 - mflr %r12 - add %r10,%r12,%r10 - slwi %r8,%r6,5 - add %r10,%r8,%r10 - mtctr %r10 - addi %r5,%r5,-1 - mtlr %r9 - bctr - -L(end2):slw %r0,%r10,%r6 - stw %r0,-4(%r7) - blr - -#define DO_LSHIFT(n) \ - mtctr %r5; \ -0: lwzu %r10,-4(%r4); \ - slwi %r9,%r11,n; \ - inslwi %r9,%r10,n,32-n; \ - stwu %r9,-4(%r7); \ - bdz- L(end2); \ - lwzu %r11,-4(%r4); \ - slwi %r9,%r10,n; \ - inslwi %r9,%r11,n,32-n; \ - stwu %r9,-4(%r7); \ - bdnz 0b; \ - b L(end1) - - DO_LSHIFT(1) - DO_LSHIFT(2) - DO_LSHIFT(3) - DO_LSHIFT(4) - DO_LSHIFT(5) - DO_LSHIFT(6) - DO_LSHIFT(7) - DO_LSHIFT(8) - DO_LSHIFT(9) - DO_LSHIFT(10) - DO_LSHIFT(11) - DO_LSHIFT(12) - DO_LSHIFT(13) - DO_LSHIFT(14) - DO_LSHIFT(15) - DO_LSHIFT(16) - DO_LSHIFT(17) - DO_LSHIFT(18) - DO_LSHIFT(19) - DO_LSHIFT(20) - DO_LSHIFT(21) - DO_LSHIFT(22) - DO_LSHIFT(23) - DO_LSHIFT(24) - DO_LSHIFT(25) - DO_LSHIFT(26) - DO_LSHIFT(27) - DO_LSHIFT(28) - DO_LSHIFT(29) - DO_LSHIFT(30) - DO_LSHIFT(31) - -END(mpihelp_lshift) -#endif diff --git a/mpi/powerpc32/mpih-mul1.S b/mpi/powerpc32/mpih-mul1.S deleted file mode 100644 index b3cb62f3e..000000000 --- a/mpi/powerpc32/mpih-mul1.S +++ /dev/null @@ -1,120 +0,0 @@ -/* PowerPC-32 mul_1 -- Multiply a limb vector with a limb and store - * the result in a second limb vector. - * - * Copyright (C) 1992, 1993, 1994, 1995, - * 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_mul_1( mpi_ptr_t res_ptr, (r3) - * mpi_ptr_t s1_ptr, (r4) - * mpi_size_t s1_size, (r5) - * mpi_limb_t s2_limb) (r6) - * - * This is a fairly straightforward implementation. The timing of the PC601 - * is hard to understand, so I will wait to optimize this until I have some - * hardware to play with. - * - * The code trivially generalizes to 64 bit limbs for the PC620. - */ - - .toc - .csect .mpihelp_mul_1[PR] - .align 2 - .globl mpihelp_mul_1 - .globl .mpihelp_mul_1 - .csect mpihelp_mul_1[DS] -mpihelp_mul_1: - .long .mpihelp_mul_1[PR], TOC[tc0], 0 - .csect .mpihelp_mul_1[PR] -.mpihelp_mul_1: - mtctr 5 - - lwz 0,0(4) - mullw 7,0,6 - mulhwu 10,0,6 - addi 3,3,-4 # adjust res_ptr - addic 5,5,0 # clear cy with dummy insn - bdz Lend - -Loop: lwzu 0,4(4) - stwu 7,4(3) - mullw 8,0,6 - adde 7,8,10 - mulhwu 10,0,6 - bdnz Loop - -Lend: stw 7,4(3) - addze 3,10 - blr - -#else -/* Multiply a limb vector by a limb, for PowerPC. - Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - - -/* mp_limb_t mpn_mul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, - mp_size_t s1_size, mp_limb_t s2_limb) - Calculate s1*s2 and put result in res_ptr; return carry. */ - -ENTRY(mpihelp_mul_1) - mtctr %r5 - - lwz %r0,0(%r4) - mullw %r7,%r0,%r6 - mulhwu %r10,%r0,%r6 - addi %r3,%r3,-4 # adjust res_ptr - addic %r5,%r5,0 # clear cy with dummy insn - bdz 1f - -0: lwzu %r0,4(%r4) - stwu %r7,4(%r3) - mullw %r8,%r0,%r6 - adde %r7,%r8,%r10 - mulhwu %r10,%r0,%r6 - bdnz 0b - -1: stw %r7,4(%r3) - addze %r3,%r10 - blr -END(mpihelp_mul_1) -#endif diff --git a/mpi/powerpc32/mpih-mul2.S b/mpi/powerpc32/mpih-mul2.S deleted file mode 100644 index d3b39bc01..000000000 --- a/mpi/powerpc32/mpih-mul2.S +++ /dev/null @@ -1,127 +0,0 @@ -/* PowerPC-32 addmul_1 -- Multiply a limb vector with a limb and add - * the result to a second limb vector. - * - * Copyright (C) 1995, 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r3) - * mpi_ptr_t s1_ptr, (r4) - * mpi_size_t s1_size, (r5) - * mpi_limb_t s2_limb) (r6) - * - * This is a fairly straightforward implementation. The timing of the PC601 - * is hard to understand, so I will wait to optimize this until I have some - * hardware to play with. - * - * The code trivially generalizes to 64 bit limbs for the PC620. - */ - - - .toc - .csect .mpihelp_addmul_1[PR] - .align 2 - .globl mpihelp_addmul_1 - .globl .mpihelp_addmul_1 - .csect mpihelp_addmul_1[DS] -mpihelp_addmul_1: - .long .mpihelp_addmul_1[PR], TOC[tc0], 0 - .csect .mpihelp_addmul_1[PR] -.mpihelp_addmul_1: - mtctr 5 - - lwz 0,0(4) - mullw 7,0,6 - mulhwu 10,0,6 - lwz 9,0(3) - addc 8,7,9 - addi 3,3,-4 - bdz Lend - -Loop: lwzu 0,4(4) - stwu 8,4(3) - mullw 8,0,6 - adde 7,8,10 - mulhwu 10,0,6 - lwz 9,4(3) - addze 10,10 - addc 8,7,9 - bdnz Loop - -Lend: stw 8,4(3) - addze 3,10 - blr - -#else -/* Multiply a limb vector by a single limb, for PowerPC. - Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - - -/* mp_limb_t mpn_addmul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, - mp_size_t s1_size, mp_limb_t s2_limb) - Calculate res+s1*s2 and put result back in res; return carry. */ -ENTRY(mpihelp_addmul_1) - mtctr %r5 - - lwz %r0,0(%r4) - mullw %r7,%r0,%r6 - mulhwu %r10,%r0,%r6 - lwz %r9,0(%r3) - addc %r8,%r7,%r9 - addi %r3,%r3,-4 /* adjust res_ptr */ - bdz 1f - -0: lwzu %r0,4(%r4) - stwu %r8,4(%r3) - mullw %r8,%r0,%r6 - adde %r7,%r8,%r10 - mulhwu %r10,%r0,%r6 - lwz %r9,4(%r3) - addze %r10,%r10 - addc %r8,%r7,%r9 - bdnz 0b - -1: stw %r8,4(%r3) - addze %r3,%r10 - blr -END(mpihelp_addmul_1) -#endif diff --git a/mpi/powerpc32/mpih-mul3.S b/mpi/powerpc32/mpih-mul3.S deleted file mode 100644 index d84f853ba..000000000 --- a/mpi/powerpc32/mpih-mul3.S +++ /dev/null @@ -1,130 +0,0 @@ -/* PowerPC-32 submul_1 -- Multiply a limb vector with a limb and subtract - * the result from a second limb vector. - * - * Copyright (C) 1995, 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_submul_1( mpi_ptr_t res_ptr, (r3) - * mpi_ptr_t s1_ptr, (r4) - * mpi_size_t s1_size, (r5) - * mpi_limb_t s2_limb) (r6) - * - * This is a fairly straightforward implementation. The timing of the PC601 - * is hard to understand, so I will wait to optimize this until I have some - * hardware to play with. - * - * The code trivially generalizes to 64 bit limbs for the PC620. - */ - - .toc - .csect .mpihelp_submul_1[PR] - .align 2 - .globl mpihelp_submul_1 - .globl .mpihelp_submul_1 - .csect mpihelp_submul_1[DS] -mpihelp_submul_1: - .long .mpihelp_submul_1[PR], TOC[tc0], 0 - .csect .mpihelp_submul_1[PR] -.mpihelp_submul_1: - mtctr 5 - - lwz 0,0(4) - mullw 7,0,6 - mulhwu 10,0,6 - lwz 9,0(3) - subfc 8,7,9 - addc 7,7,8 # invert cy (r7 is junk) - addi 3,3,-4 - bdz Lend - -Loop: lwzu 0,4(4) - stwu 8,4(3) - mullw 8,0,6 - adde 7,8,10 - mulhwu 10,0,6 - lwz 9,4(3) - addze 10,10 - subfc 8,7,9 - addc 7,7,8 # invert cy (r7 is junk) - bdnz Loop - -Lend: stw 8,4(3) - addze 3,10 - blr - -#else -/* Multiply a limb vector by a single limb, for PowerPC. - Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* mp_limb_t mpn_submul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, - mp_size_t s1_size, mp_limb_t s2_limb) - Calculate res-s1*s2 and put result back in res; return carry. */ - -ENTRY(mpihelp_submul_1) - mtctr %r5 - - lwz %r0,0(%r4) - mullw %r7,%r0,%r6 - mulhwu %r10,%r0,%r6 - lwz %r9,0(%r3) - subf %r8,%r7,%r9 - addc %r7,%r7,%r8 # invert cy (r7 is junk) - addi %r3,%r3,-4 # adjust res_ptr - bdz 1f - -0: lwzu %r0,4(%r4) - stwu %r8,4(%r3) - mullw %r8,%r0,%r6 - adde %r7,%r8,%r10 - mulhwu %r10,%r0,%r6 - lwz %r9,4(%r3) - addze %r10,%r10 - subf %r8,%r7,%r9 - addc %r7,%r7,%r8 # invert cy (r7 is junk) - bdnz 0b - -1: stw %r8,4(%r3) - addze %r3,%r10 - blr -END(mpihelp_submul_1) -#endif diff --git a/mpi/powerpc32/mpih-rshift.S b/mpi/powerpc32/mpih-rshift.S deleted file mode 100644 index e9704db93..000000000 --- a/mpi/powerpc32/mpih-rshift.S +++ /dev/null @@ -1,131 +0,0 @@ -/* PowerPC-32 rshift - * - * Copyright (C) 1995, 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_rshift( mpi_ptr_t wp, (r3) - * mpi_ptr_t up, (r4) - * mpi_size_t usize, (r5) - * unsigned cnt) (r6) - */ - - .toc -.csect .text[PR] - .align 2 - .globl mpihelp_rshift - .globl .mpihelp_rshift - .csect mpihelp_rshift[DS] -mpihelp_rshift: - .long .mpihelp_rshift, TOC[tc0], 0 - .csect .text[PR] -.mpihelp_rshift: - mtctr 5 # copy size into CTR - addi 7,3,-4 # move adjusted res_ptr to free return reg - subfic 8,6,32 - lwz 11,0(4) # load first s1 limb - slw 3,11,8 # compute function return value - bdz Lend1 - -Loop: lwzu 10,4(4) - srw 9,11,6 - slw 12,10,8 - or 9,9,12 - stwu 9,4(7) - bdz Lend2 - lwzu 11,4(4) - srw 9,10,6 - slw 12,11,8 - or 9,9,12 - stwu 9,4(7) - bdnz Loop - -Lend1: srw 0,11,6 - stw 0,4(7) - blr - -Lend2: srw 0,10,6 - stw 0,4(7) - blr - -#else -/* Shift a limb right, low level routine. - Copyright (C) 1995, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - - -/* INPUT PARAMETERS - res_ptr r3 - s1_ptr r4 - size r5 - cnt r6 */ - -ENTRY(mpihelp_rshift) - mtctr 5 # copy size into CTR - addi 7,3,-4 # move adjusted res_ptr to free return reg - subfic 8,6,32 - lwz 11,0(4) # load first s1 limb - slw 3,11,8 # compute function return value - bdz 1f - -0: lwzu 10,4(4) - srw 9,11,6 - slw 12,10,8 - or 9,9,12 - stwu 9,4(7) - bdz 2f - lwzu 11,4(4) - srw 9,10,6 - slw 12,11,8 - or 9,9,12 - stwu 9,4(7) - bdnz 0b - -1: srw 0,11,6 - stw 0,4(7) - blr - -2: srw 0,10,6 - stw 0,4(7) - blr -END(mpihelp_rshift) -#endif diff --git a/mpi/powerpc32/mpih-sub1.S b/mpi/powerpc32/mpih-sub1.S deleted file mode 100644 index 8c67d988f..000000000 --- a/mpi/powerpc32/mpih-sub1.S +++ /dev/null @@ -1,132 +0,0 @@ -/* PowerPC-32 sub_n -- Subtract two limb vectors of the same length > 0 - * and store difference in a third limb vector. - * - * Copyright (C) 1992, 1994, 1995, 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "sysdep.h" -#include "asm-syntax.h" - - -#ifndef USE_PPC_PATCHES - -/******************* - * mpi_limb_t - * mpihelp_sub_n( mpi_ptr_t res_ptr, (r3) - * mpi_ptr_t s1_ptr, (r4) - * mpi_ptr_t s2_ptr, (r5) - * mpi_size_t size) (r6) - */ - - .toc - .extern mpihelp_sub_n[DS] - .extern .mpihelp_sub_n -.csect [PR] - .align 2 - .globl mpihelp_sub_n - .globl .mpihelp_sub_n - .csect mpihelp_sub_n[DS] -mpihelp_sub_n: - .long .mpihelp_sub_n, TOC[tc0], 0 - .csect [PR] -.mpihelp_sub_n: - mtctr 6 # copy size into CTR - lwz 8,0(4) # load least significant s1 limb - lwz 0,0(5) # load least significant s2 limb - addi 3,3,-4 # offset res_ptr, it is updated before used - subfc 7,0,8 # add least significant limbs, set cy - bdz Lend # If done, skip loop -Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr - lwzu 0,4(5) # load s2 limb and update s2_ptr - stwu 7,4(3) # store previous limb in load latency slot - subfe 7,0,8 # add new limbs with cy, set cy - bdnz Loop # decrement CTR and loop back -Lend: stw 7,4(3) # store ultimate result limb - subfe 3,0,0 # load !cy into ... - subfic 3,3,0 # ... return value register - blr - -#else -/* Subtract two limb vectors of equal, non-zero length for PowerPC. - Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* mp_limb_t mpn_sub_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, - mp_size_t size) - Calculate s1-s2 and put result in res_ptr; return borrow, 0 or 1. */ - -/* Note on optimisation: This code is optimal for the 601. Almost every other - possible 2-unrolled inner loop will not be. Also, watch out for the - alignment... */ - -EALIGN(mpihelp_sub_n,3,1) -/* Set up for loop below. */ - mtcrf 0x01,%r6 - srwi. %r7,%r6,1 - mtctr %r7 - bt 31,2f - -/* Set the carry (clear the borrow). */ - subfc %r0,%r0,%r0 -/* Adjust pointers for loop. */ - addi %r3,%r3,-4 - addi %r4,%r4,-4 - addi %r5,%r5,-4 - b 0f - -2: lwz %r7,0(%r5) - lwz %r6,0(%r4) - subfc %r6,%r7,%r6 - stw %r6,0(%r3) - beq 1f - -/* Align start of loop to an odd word boundary to guarantee that the - last two words can be fetched in one access (for 601). This turns - out to be important. */ -0: - lwz %r9,4(%r4) - lwz %r8,4(%r5) - lwzu %r6,8(%r4) - lwzu %r7,8(%r5) - subfe %r8,%r8,%r9 - stw %r8,4(%r3) - subfe %r6,%r7,%r6 - stwu %r6,8(%r3) - bdnz 0b -/* Return the borrow. */ -1: subfe %r3,%r3,%r3 - neg %r3,%r3 - blr -END(mpihelp_sub_n) -#endif diff --git a/mpi/powerpc32/syntax.h b/mpi/powerpc32/syntax.h deleted file mode 100644 index 19f797273..000000000 --- a/mpi/powerpc32/syntax.h +++ /dev/null @@ -1,75 +0,0 @@ -/* gmp2-2.0.2-ppc/mpn/powerpc-linux/syntax.h Tue Oct 6 19:27:01 1998 */ -/* From glibc's sysdeps/unix/sysv/linux/powerpc/sysdep.h */ - -/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library 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. - - The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - - -#define USE_PPC_PATCHES 1 - -/* This seems to always be the case on PPC. */ -#define ALIGNARG(log2) log2 -/* For ELF we need the `.type' directive to make shared libs work right. */ -#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; -#define ASM_SIZE_DIRECTIVE(name) .size name,.-name -#define ASM_GLOBAL_DIRECTIVE .globl - -#ifdef __STDC__ -# define C_LABEL(name) C_SYMBOL_NAME(name)##: -#else -# define C_LABEL(name) C_SYMBOL_NAME(name)/**/: -#endif - -#ifdef __STDC__ -# define L(body) .L##body -#else -# define L(body) .L/**/body -#endif - -/* No profiling of gmp's assembly for now... */ -#define CALL_MCOUNT /* no profiling */ - -#define ENTRY(name) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(2); \ - C_LABEL(name) \ - CALL_MCOUNT - -#define EALIGN_W_0 /* No words to insert. */ -#define EALIGN_W_1 nop -#define EALIGN_W_2 nop;nop -#define EALIGN_W_3 nop;nop;nop -#define EALIGN_W_4 EALIGN_W_3;nop -#define EALIGN_W_5 EALIGN_W_4;nop -#define EALIGN_W_6 EALIGN_W_5;nop -#define EALIGN_W_7 EALIGN_W_6;nop - -/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes - past a 2^align boundary. */ -#define EALIGN(name, alignt, words) \ - ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ - ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ - .align ALIGNARG(alignt); \ - EALIGN_W_##words; \ - C_LABEL(name) - -#undef END -#define END(name) \ - ASM_SIZE_DIRECTIVE(name) - diff --git a/mpi/powerpc64/distfiles b/mpi/powerpc64/distfiles deleted file mode 100644 index e69de29bb..000000000 diff --git a/mpi/sparc32/distfiles b/mpi/sparc32/distfiles deleted file mode 100644 index 95ff42882..000000000 --- a/mpi/sparc32/distfiles +++ /dev/null @@ -1,6 +0,0 @@ - -mpih-lshift.S -mpih-rshift.S -mpih-add1.S -udiv.S - diff --git a/mpi/sparc32/mpih-add1.S b/mpi/sparc32/mpih-add1.S deleted file mode 100644 index b8faadb5f..000000000 --- a/mpi/sparc32/mpih-add1.S +++ /dev/null @@ -1,239 +0,0 @@ -/* SPARC _add_n -- Add two limb vectors of the same length > 0 and store - * sum in a third limb vector. - * - * Copyright (C) 1995, 1996, 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 - */ - - - -/******************* - * mpi_limb_t - * mpihelp_add_n( mpi_ptr_t res_ptr, - * mpi_ptr_t s1_ptr, - * mpi_ptr_t s2_ptr, - * mpi_size_t size) - */ - -! INPUT PARAMETERS -#define res_ptr %o0 -#define s1_ptr %o1 -#define s2_ptr %o2 -#define size %o3 - -#include "sysdep.h" - - .text - .align 4 - .global C_SYMBOL_NAME(mpihelp_add_n) -C_SYMBOL_NAME(mpihelp_add_n): - xor s2_ptr,res_ptr,%g1 - andcc %g1,4,%g0 - bne L1 ! branch if alignment differs - nop -! ** V1a ** -L0: andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0 - be L_v1 ! if no, branch - nop -/* Add least significant limb separately to align res_ptr and s2_ptr */ - ld [s1_ptr],%g4 - add s1_ptr,4,s1_ptr - ld [s2_ptr],%g2 - add s2_ptr,4,s2_ptr - add size,-1,size - addcc %g4,%g2,%o4 - st %o4,[res_ptr] - add res_ptr,4,res_ptr -L_v1: addx %g0,%g0,%o4 ! save cy in register - cmp size,2 ! if size < 2 ... - bl Lend2 ! ... branch to tail code - subcc %g0,%o4,%g0 ! restore cy - - ld [s1_ptr+0],%g4 - addcc size,-10,size - ld [s1_ptr+4],%g1 - ldd [s2_ptr+0],%g2 - blt Lfin1 - subcc %g0,%o4,%g0 ! restore cy -/* Add blocks of 8 limbs until less than 8 limbs remain */ -Loop1: addxcc %g4,%g2,%o4 - ld [s1_ptr+8],%g4 - addxcc %g1,%g3,%o5 - ld [s1_ptr+12],%g1 - ldd [s2_ptr+8],%g2 - std %o4,[res_ptr+0] - addxcc %g4,%g2,%o4 - ld [s1_ptr+16],%g4 - addxcc %g1,%g3,%o5 - ld [s1_ptr+20],%g1 - ldd [s2_ptr+16],%g2 - std %o4,[res_ptr+8] - addxcc %g4,%g2,%o4 - ld [s1_ptr+24],%g4 - addxcc %g1,%g3,%o5 - ld [s1_ptr+28],%g1 - ldd [s2_ptr+24],%g2 - std %o4,[res_ptr+16] - addxcc %g4,%g2,%o4 - ld [s1_ptr+32],%g4 - addxcc %g1,%g3,%o5 - ld [s1_ptr+36],%g1 - ldd [s2_ptr+32],%g2 - std %o4,[res_ptr+24] - addx %g0,%g0,%o4 ! save cy in register - addcc size,-8,size - add s1_ptr,32,s1_ptr - add s2_ptr,32,s2_ptr - add res_ptr,32,res_ptr - bge Loop1 - subcc %g0,%o4,%g0 ! restore cy - -Lfin1: addcc size,8-2,size - blt Lend1 - subcc %g0,%o4,%g0 ! restore cy -/* Add blocks of 2 limbs until less than 2 limbs remain */ -Loope1: addxcc %g4,%g2,%o4 - ld [s1_ptr+8],%g4 - addxcc %g1,%g3,%o5 - ld [s1_ptr+12],%g1 - ldd [s2_ptr+8],%g2 - std %o4,[res_ptr+0] - addx %g0,%g0,%o4 ! save cy in register - addcc size,-2,size - add s1_ptr,8,s1_ptr - add s2_ptr,8,s2_ptr - add res_ptr,8,res_ptr - bge Loope1 - subcc %g0,%o4,%g0 ! restore cy -Lend1: addxcc %g4,%g2,%o4 - addxcc %g1,%g3,%o5 - std %o4,[res_ptr+0] - addx %g0,%g0,%o4 ! save cy in register - - andcc size,1,%g0 - be Lret1 - subcc %g0,%o4,%g0 ! restore cy -/* Add last limb */ - ld [s1_ptr+8],%g4 - ld [s2_ptr+8],%g2 - addxcc %g4,%g2,%o4 - st %o4,[res_ptr+8] - -Lret1: retl - addx %g0,%g0,%o0 ! return carry-out from most sign. limb - -L1: xor s1_ptr,res_ptr,%g1 - andcc %g1,4,%g0 - bne L2 - nop -! ** V1b ** - mov s2_ptr,%g1 - mov s1_ptr,s2_ptr - b L0 - mov %g1,s1_ptr - -! ** V2 ** -/* If we come here, the alignment of s1_ptr and res_ptr as well as the - alignment of s2_ptr and res_ptr differ. Since there are only two ways - things can be aligned (that we care about) we now know that the alignment - of s1_ptr and s2_ptr are the same. */ - -L2: cmp size,1 - be Ljone - nop - andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0 - be L_v2 ! if no, branch - nop -/* Add least significant limb separately to align s1_ptr and s2_ptr */ - ld [s1_ptr],%g4 - add s1_ptr,4,s1_ptr - ld [s2_ptr],%g2 - add s2_ptr,4,s2_ptr - add size,-1,size - addcc %g4,%g2,%o4 - st %o4,[res_ptr] - add res_ptr,4,res_ptr - -L_v2: addx %g0,%g0,%o4 ! save cy in register - addcc size,-8,size - blt Lfin2 - subcc %g0,%o4,%g0 ! restore cy -/* Add blocks of 8 limbs until less than 8 limbs remain */ -Loop2: ldd [s1_ptr+0],%g2 - ldd [s2_ptr+0],%o4 - addxcc %g2,%o4,%g2 - st %g2,[res_ptr+0] - addxcc %g3,%o5,%g3 - st %g3,[res_ptr+4] - ldd [s1_ptr+8],%g2 - ldd [s2_ptr+8],%o4 - addxcc %g2,%o4,%g2 - st %g2,[res_ptr+8] - addxcc %g3,%o5,%g3 - st %g3,[res_ptr+12] - ldd [s1_ptr+16],%g2 - ldd [s2_ptr+16],%o4 - addxcc %g2,%o4,%g2 - st %g2,[res_ptr+16] - addxcc %g3,%o5,%g3 - st %g3,[res_ptr+20] - ldd [s1_ptr+24],%g2 - ldd [s2_ptr+24],%o4 - addxcc %g2,%o4,%g2 - st %g2,[res_ptr+24] - addxcc %g3,%o5,%g3 - st %g3,[res_ptr+28] - addx %g0,%g0,%o4 ! save cy in register - addcc size,-8,size - add s1_ptr,32,s1_ptr - add s2_ptr,32,s2_ptr - add res_ptr,32,res_ptr - bge Loop2 - subcc %g0,%o4,%g0 ! restore cy - -Lfin2: addcc size,8-2,size - blt Lend2 - subcc %g0,%o4,%g0 ! restore cy -Loope2: ldd [s1_ptr+0],%g2 - ldd [s2_ptr+0],%o4 - addxcc %g2,%o4,%g2 - st %g2,[res_ptr+0] - addxcc %g3,%o5,%g3 - st %g3,[res_ptr+4] - addx %g0,%g0,%o4 ! save cy in register - addcc size,-2,size - add s1_ptr,8,s1_ptr - add s2_ptr,8,s2_ptr - add res_ptr,8,res_ptr - bge Loope2 - subcc %g0,%o4,%g0 ! restore cy -Lend2: andcc size,1,%g0 - be Lret2 - subcc %g0,%o4,%g0 ! restore cy -/* Add last limb */ -Ljone: ld [s1_ptr],%g4 - ld [s2_ptr],%g2 - addxcc %g4,%g2,%o4 - st %o4,[res_ptr] - -Lret2: retl - addx %g0,%g0,%o0 ! return carry-out from most sign. limb - - - diff --git a/mpi/sparc32/mpih-lshift.S b/mpi/sparc32/mpih-lshift.S deleted file mode 100644 index b217d5e62..000000000 --- a/mpi/sparc32/mpih-lshift.S +++ /dev/null @@ -1,97 +0,0 @@ -/* sparc lshift - * - * Copyright (C) 1995, 1996, 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 - */ - - -! INPUT PARAMETERS -! res_ptr %o0 -! src_ptr %o1 -! size %o2 -! cnt %o3 - -#include "sysdep.h" - - .text - .align 4 - .global C_SYMBOL_NAME(mpihelp_lshift) -C_SYMBOL_NAME(mpihelp_lshift): - sll %o2,2,%g1 - add %o1,%g1,%o1 ! make %o1 point at end of src - ld [%o1-4],%g2 ! load first limb - sub %g0,%o3,%o5 ! negate shift count - add %o0,%g1,%o0 ! make %o0 point at end of res - add %o2,-1,%o2 - andcc %o2,4-1,%g4 ! number of limbs in first loop - srl %g2,%o5,%g1 ! compute function result - be L0 ! if multiple of 4 limbs, skip first loop - st %g1,[%sp+80] - - sub %o2,%g4,%o2 ! adjust count for main loop - -Loop0: ld [%o1-8],%g3 - add %o0,-4,%o0 - add %o1,-4,%o1 - addcc %g4,-1,%g4 - sll %g2,%o3,%o4 - srl %g3,%o5,%g1 - mov %g3,%g2 - or %o4,%g1,%o4 - bne Loop0 - st %o4,[%o0+0] - -L0: tst %o2 - be Lend - nop - -Loop: ld [%o1-8],%g3 - add %o0,-16,%o0 - addcc %o2,-4,%o2 - sll %g2,%o3,%o4 - srl %g3,%o5,%g1 - - ld [%o1-12],%g2 - sll %g3,%o3,%g4 - or %o4,%g1,%o4 - st %o4,[%o0+12] - srl %g2,%o5,%g1 - - ld [%o1-16],%g3 - sll %g2,%o3,%o4 - or %g4,%g1,%g4 - st %g4,[%o0+8] - srl %g3,%o5,%g1 - - ld [%o1-20],%g2 - sll %g3,%o3,%g4 - or %o4,%g1,%o4 - st %o4,[%o0+4] - srl %g2,%o5,%g1 - - add %o1,-16,%o1 - or %g4,%g1,%g4 - bne Loop - st %g4,[%o0+0] - -Lend: sll %g2,%o3,%g2 - st %g2,[%o0-4] - retl - ld [%sp+80],%o0 - diff --git a/mpi/sparc32/mpih-rshift.S b/mpi/sparc32/mpih-rshift.S deleted file mode 100644 index 62902cbe3..000000000 --- a/mpi/sparc32/mpih-rshift.S +++ /dev/null @@ -1,93 +0,0 @@ -/* sparc rshift - * - * Copyright (C) 1995, 1996, 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 - */ - -! INPUT PARAMETERS -! res_ptr %o0 -! src_ptr %o1 -! size %o2 -! cnt %o3 - -#include "sysdep.h" - - .text - .align 4 - .global C_SYMBOL_NAME(mpihelp_rshift) -C_SYMBOL_NAME(mpihelp_rshift): - ld [%o1],%g2 ! load first limb - sub %g0,%o3,%o5 ! negate shift count - add %o2,-1,%o2 - andcc %o2,4-1,%g4 ! number of limbs in first loop - sll %g2,%o5,%g1 ! compute function result - be L0 ! if multiple of 4 limbs, skip first loop - st %g1,[%sp+80] - - sub %o2,%g4,%o2 ! adjust count for main loop - -Loop0: ld [%o1+4],%g3 - add %o0,4,%o0 - add %o1,4,%o1 - addcc %g4,-1,%g4 - srl %g2,%o3,%o4 - sll %g3,%o5,%g1 - mov %g3,%g2 - or %o4,%g1,%o4 - bne Loop0 - st %o4,[%o0-4] - -L0: tst %o2 - be Lend - nop - -Loop: ld [%o1+4],%g3 - add %o0,16,%o0 - addcc %o2,-4,%o2 - srl %g2,%o3,%o4 - sll %g3,%o5,%g1 - - ld [%o1+8],%g2 - srl %g3,%o3,%g4 - or %o4,%g1,%o4 - st %o4,[%o0-16] - sll %g2,%o5,%g1 - - ld [%o1+12],%g3 - srl %g2,%o3,%o4 - or %g4,%g1,%g4 - st %g4,[%o0-12] - sll %g3,%o5,%g1 - - ld [%o1+16],%g2 - srl %g3,%o3,%g4 - or %o4,%g1,%o4 - st %o4,[%o0-8] - sll %g2,%o5,%g1 - - add %o1,16,%o1 - or %g4,%g1,%g4 - bne Loop - st %g4,[%o0-4] - -Lend: srl %g2,%o3,%g2 - st %g2,[%o0-0] - retl - ld [%sp+80],%o0 - diff --git a/mpi/sparc32/udiv.S b/mpi/sparc32/udiv.S deleted file mode 100644 index 752d07193..000000000 --- a/mpi/sparc32/udiv.S +++ /dev/null @@ -1,197 +0,0 @@ -/* SPARC v7 __udiv_qrnnd division support, used from longlong.h. - * This is for v7 CPUs without a floating-point unit. - * - * Copyright (C) 1993, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -! INPUT PARAMETERS -! rem_ptr o0 -! n1 o1 -! n0 o2 -! d o3 - -#include "sysdep.h" - - .text - .align 4 - .global C_SYMBOL_NAME(__udiv_qrnnd) -C_SYMBOL_NAME(__udiv_qrnnd): - tst %o3 - bneg Largedivisor - mov 8,%g1 - - b Lp1 - addxcc %o2,%o2,%o2 - -Lplop: bcc Ln1 - addxcc %o2,%o2,%o2 -Lp1: addx %o1,%o1,%o1 - subcc %o1,%o3,%o4 - bcc Ln2 - addxcc %o2,%o2,%o2 -Lp2: addx %o1,%o1,%o1 - subcc %o1,%o3,%o4 - bcc Ln3 - addxcc %o2,%o2,%o2 -Lp3: addx %o1,%o1,%o1 - subcc %o1,%o3,%o4 - bcc Ln4 - addxcc %o2,%o2,%o2 -Lp4: addx %o1,%o1,%o1 - addcc %g1,-1,%g1 - bne Lplop - subcc %o1,%o3,%o4 - bcc Ln5 - addxcc %o2,%o2,%o2 -Lp5: st %o1,[%o0] - retl - xnor %g0,%o2,%o0 - -Lnlop: bcc Lp1 - addxcc %o2,%o2,%o2 -Ln1: addx %o4,%o4,%o4 - subcc %o4,%o3,%o1 - bcc Lp2 - addxcc %o2,%o2,%o2 -Ln2: addx %o4,%o4,%o4 - subcc %o4,%o3,%o1 - bcc Lp3 - addxcc %o2,%o2,%o2 -Ln3: addx %o4,%o4,%o4 - subcc %o4,%o3,%o1 - bcc Lp4 - addxcc %o2,%o2,%o2 -Ln4: addx %o4,%o4,%o4 - addcc %g1,-1,%g1 - bne Lnlop - subcc %o4,%o3,%o1 - bcc Lp5 - addxcc %o2,%o2,%o2 -Ln5: st %o4,[%o0] - retl - xnor %g0,%o2,%o0 - -Largedivisor: - and %o2,1,%o5 ! %o5 = n0 & 1 - - srl %o2,1,%o2 - sll %o1,31,%g2 - or %g2,%o2,%o2 ! %o2 = lo(n1n0 >> 1) - srl %o1,1,%o1 ! %o1 = hi(n1n0 >> 1) - - and %o3,1,%g2 - srl %o3,1,%g3 ! %g3 = floor(d / 2) - add %g3,%g2,%g3 ! %g3 = ceil(d / 2) - - b LLp1 - addxcc %o2,%o2,%o2 - -LLplop: bcc LLn1 - addxcc %o2,%o2,%o2 -LLp1: addx %o1,%o1,%o1 - subcc %o1,%g3,%o4 - bcc LLn2 - addxcc %o2,%o2,%o2 -LLp2: addx %o1,%o1,%o1 - subcc %o1,%g3,%o4 - bcc LLn3 - addxcc %o2,%o2,%o2 -LLp3: addx %o1,%o1,%o1 - subcc %o1,%g3,%o4 - bcc LLn4 - addxcc %o2,%o2,%o2 -LLp4: addx %o1,%o1,%o1 - addcc %g1,-1,%g1 - bne LLplop - subcc %o1,%g3,%o4 - bcc LLn5 - addxcc %o2,%o2,%o2 -LLp5: add %o1,%o1,%o1 ! << 1 - tst %g2 - bne Oddp - add %o5,%o1,%o1 - st %o1,[%o0] - retl - xnor %g0,%o2,%o0 - -LLnlop: bcc LLp1 - addxcc %o2,%o2,%o2 -LLn1: addx %o4,%o4,%o4 - subcc %o4,%g3,%o1 - bcc LLp2 - addxcc %o2,%o2,%o2 -LLn2: addx %o4,%o4,%o4 - subcc %o4,%g3,%o1 - bcc LLp3 - addxcc %o2,%o2,%o2 -LLn3: addx %o4,%o4,%o4 - subcc %o4,%g3,%o1 - bcc LLp4 - addxcc %o2,%o2,%o2 -LLn4: addx %o4,%o4,%o4 - addcc %g1,-1,%g1 - bne LLnlop - subcc %o4,%g3,%o1 - bcc LLp5 - addxcc %o2,%o2,%o2 -LLn5: add %o4,%o4,%o4 ! << 1 - tst %g2 - bne Oddn - add %o5,%o4,%o4 - st %o4,[%o0] - retl - xnor %g0,%o2,%o0 - -Oddp: xnor %g0,%o2,%o2 - ! q' in %o2. r' in %o1 - addcc %o1,%o2,%o1 - bcc LLp6 - addx %o2,0,%o2 - sub %o1,%o3,%o1 -LLp6: subcc %o1,%o3,%g0 - bcs LLp7 - subx %o2,-1,%o2 - sub %o1,%o3,%o1 -LLp7: st %o1,[%o0] - retl - mov %o2,%o0 - -Oddn: xnor %g0,%o2,%o2 - ! q' in %o2. r' in %o4 - addcc %o4,%o2,%o4 - bcc LLn6 - addx %o2,0,%o2 - sub %o4,%o3,%o4 -LLn6: subcc %o4,%o3,%g0 - bcs LLn7 - subx %o2,-1,%o2 - sub %o4,%o3,%o4 -LLn7: st %o4,[%o0] - retl - mov %o2,%o0 diff --git a/mpi/sparc32v8/distfiles b/mpi/sparc32v8/distfiles deleted file mode 100644 index 5789f35b3..000000000 --- a/mpi/sparc32v8/distfiles +++ /dev/null @@ -1,5 +0,0 @@ - -mpih-mul1.S -mpih-mul2.S -mpih-mul3.S - diff --git a/mpi/sparc32v8/mpih-mul1.S b/mpi/sparc32v8/mpih-mul1.S deleted file mode 100644 index 551450060..000000000 --- a/mpi/sparc32v8/mpih-mul1.S +++ /dev/null @@ -1,111 +0,0 @@ -/* SPARC v8 __mpn_mul_1 -- Multiply a limb vector with a single limb and - * store the product in a second limb vector. - * - * Copyright (C) 1992, 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -! INPUT PARAMETERS -! res_ptr o0 -! s1_ptr o1 -! size o2 -! s2_limb o3 - -#include "sysdep.h" - -.text - .align 8 - .global C_SYMBOL_NAME(mpihelp_mul_1) -C_SYMBOL_NAME(mpihelp_mul_1): - sll %o2,4,%g1 - and %g1,(4-1)<<4,%g1 -#if PIC - mov %o7,%g4 ! Save return address register - call 1f - add %o7,LL-1f,%g3 -1: mov %g4,%o7 ! Restore return address register -#else - sethi %hi(LL),%g3 - or %g3,%lo(LL),%g3 -#endif - jmp %g3+%g1 - ld [%o1+0],%o4 ! 1 -LL: -LL00: add %o0,-4,%o0 - add %o1,-4,%o1 - b Loop00 /* 4, 8, 12, ... */ - orcc %g0,%g0,%g2 -LL01: b Loop01 /* 1, 5, 9, ... */ - orcc %g0,%g0,%g2 - nop - nop -LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ - add %o1,4,%o1 - b Loop10 - orcc %g0,%g0,%g2 - nop -LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ - add %o1,-8,%o1 - b Loop11 - orcc %g0,%g0,%g2 - -Loop: addcc %g3,%g2,%g3 ! 1 - ld [%o1+4],%o4 ! 2 - st %g3,[%o0+0] ! 1 - rd %y,%g2 ! 1 -Loop00: umul %o4,%o3,%g3 ! 2 - addxcc %g3,%g2,%g3 ! 2 - ld [%o1+8],%o4 ! 3 - st %g3,[%o0+4] ! 2 - rd %y,%g2 ! 2 -Loop11: umul %o4,%o3,%g3 ! 3 - addxcc %g3,%g2,%g3 ! 3 - ld [%o1+12],%o4 ! 4 - add %o1,16,%o1 - st %g3,[%o0+8] ! 3 - rd %y,%g2 ! 3 -Loop10: umul %o4,%o3,%g3 ! 4 - addxcc %g3,%g2,%g3 ! 4 - ld [%o1+0],%o4 ! 1 - st %g3,[%o0+12] ! 4 - add %o0,16,%o0 - rd %y,%g2 ! 4 - addx %g0,%g2,%g2 -Loop01: addcc %o2,-4,%o2 - bg Loop - umul %o4,%o3,%g3 ! 1 - - addcc %g3,%g2,%g3 ! 4 - st %g3,[%o0+0] ! 4 - rd %y,%g2 ! 4 - - retl - addx %g0,%g2,%o0 - - diff --git a/mpi/sparc32v8/mpih-mul2.S b/mpi/sparc32v8/mpih-mul2.S deleted file mode 100644 index 55f37814b..000000000 --- a/mpi/sparc32v8/mpih-mul2.S +++ /dev/null @@ -1,134 +0,0 @@ -/* SPARC v8 __mpn_addmul_1 -- Multiply a limb vector with a limb and - * add the result to a second limb vector. - * - * Copyright (C) 1992, 1993, 1994, 1995, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -! INPUT PARAMETERS -! res_ptr o0 -! s1_ptr o1 -! size o2 -! s2_limb o3 - -#include "sysdep.h" - -.text - .align 4 - .global C_SYMBOL_NAME(mpihelp_addmul_1) -C_SYMBOL_NAME(mpihelp_addmul_1): - orcc %g0,%g0,%g2 - ld [%o1+0],%o4 ! 1 - - sll %o2,4,%g1 - and %g1,(4-1)<<4,%g1 -#if PIC - mov %o7,%g4 ! Save return address register - call 1f - add %o7,LL-1f,%g3 -1: mov %g4,%o7 ! Restore return address register -#else - sethi %hi(LL),%g3 - or %g3,%lo(LL),%g3 -#endif - jmp %g3+%g1 - nop -LL: -LL00: add %o0,-4,%o0 - b Loop00 /* 4, 8, 12, ... */ - add %o1,-4,%o1 - nop -LL01: b Loop01 /* 1, 5, 9, ... */ - nop - nop - nop -LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ - b Loop10 - add %o1,4,%o1 - nop -LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ - b Loop11 - add %o1,-8,%o1 - nop - -1: addcc %g3,%g2,%g3 ! 1 - ld [%o1+4],%o4 ! 2 - rd %y,%g2 ! 1 - addx %g0,%g2,%g2 - ld [%o0+0],%g1 ! 2 - addcc %g1,%g3,%g3 - st %g3,[%o0+0] ! 1 -Loop00: umul %o4,%o3,%g3 ! 2 - ld [%o0+4],%g1 ! 2 - addxcc %g3,%g2,%g3 ! 2 - ld [%o1+8],%o4 ! 3 - rd %y,%g2 ! 2 - addx %g0,%g2,%g2 - nop - addcc %g1,%g3,%g3 - st %g3,[%o0+4] ! 2 -Loop11: umul %o4,%o3,%g3 ! 3 - addxcc %g3,%g2,%g3 ! 3 - ld [%o1+12],%o4 ! 4 - rd %y,%g2 ! 3 - add %o1,16,%o1 - addx %g0,%g2,%g2 - ld [%o0+8],%g1 ! 2 - addcc %g1,%g3,%g3 - st %g3,[%o0+8] ! 3 -Loop10: umul %o4,%o3,%g3 ! 4 - addxcc %g3,%g2,%g3 ! 4 - ld [%o1+0],%o4 ! 1 - rd %y,%g2 ! 4 - addx %g0,%g2,%g2 - ld [%o0+12],%g1 ! 2 - addcc %g1,%g3,%g3 - st %g3,[%o0+12] ! 4 - add %o0,16,%o0 - addx %g0,%g2,%g2 -Loop01: addcc %o2,-4,%o2 - bg 1b - umul %o4,%o3,%g3 ! 1 - - addcc %g3,%g2,%g3 ! 4 - rd %y,%g2 ! 4 - addx %g0,%g2,%g2 - ld [%o0+0],%g1 ! 2 - addcc %g1,%g3,%g3 - st %g3,[%o0+0] ! 4 - addx %g0,%g2,%o0 - - retl - nop - - -! umul, ld, addxcc, rd, st - -! umul, ld, addxcc, rd, ld, addcc, st, addx - diff --git a/mpi/sparc32v8/mpih-mul3.S b/mpi/sparc32v8/mpih-mul3.S deleted file mode 100644 index cfd0a1576..000000000 --- a/mpi/sparc32v8/mpih-mul3.S +++ /dev/null @@ -1,69 +0,0 @@ -/* SPARC v8 __mpn_submul_1 -- Multiply a limb vector with a limb and - * subtract the result from a second limb vector. - * - * Copyright (C) 1992, 1993, 1994, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - -! INPUT PARAMETERS -! res_ptr o0 -! s1_ptr o1 -! size o2 -! s2_limb o3 - -#include "sysdep.h" - -.text - .align 4 - .global C_SYMBOL_NAME(mpihelp_submul_1) -C_SYMBOL_NAME(mpihelp_submul_1): - sub %g0,%o2,%o2 ! negate ... - sll %o2,2,%o2 ! ... and scale size - sub %o1,%o2,%o1 ! o1 is offset s1_ptr - sub %o0,%o2,%g1 ! g1 is offset res_ptr - - mov 0,%o0 ! clear cy_limb - -Loop: ld [%o1+%o2],%o4 - ld [%g1+%o2],%g2 - umul %o4,%o3,%o5 - rd %y,%g3 - addcc %o5,%o0,%o5 - addx %g3,0,%o0 - subcc %g2,%o5,%g2 - addx %o0,0,%o0 - st %g2,[%g1+%o2] - - addcc %o2,4,%o2 - bne Loop - nop - - retl - nop - - diff --git a/mpi/supersparc/distfiles b/mpi/supersparc/distfiles deleted file mode 100644 index 5506c419b..000000000 --- a/mpi/supersparc/distfiles +++ /dev/null @@ -1,3 +0,0 @@ - -udiv.S - diff --git a/mpi/supersparc/udiv.S b/mpi/supersparc/udiv.S deleted file mode 100644 index 31b7387c7..000000000 --- a/mpi/supersparc/udiv.S +++ /dev/null @@ -1,120 +0,0 @@ -/* SuperSPARC __udiv_qrnnd division support, used from longlong.h. - * This is for SuperSPARC only, to compensate for its - * semi-functional udiv instruction. - * - * Copyright (C) 1993, 1994, 1996, 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 - * - * Note: This code is heavily based on the GNU MP Library. - * Actually it's the same code with only minor changes in the - * way the data is stored; this is to support the abstraction - * of an optional secure memory allocation which may be used - * to avoid revealing of sensitive data due to paging etc. - * The GNU MP Library itself is published under the LGPL; - * however I decided to publish this code under the plain GPL. - */ - - - -! INPUT PARAMETERS -! rem_ptr i0 -! n1 i1 -! n0 i2 -! d i3 - -#include "sysdep.h" -#undef ret /* Kludge for glibc */ - - .text - .align 8 -LC0: .double 0r4294967296 -LC1: .double 0r2147483648 - - .align 4 - .global C_SYMBOL_NAME(__udiv_qrnnd) -C_SYMBOL_NAME(__udiv_qrnnd): - !#PROLOGUE# 0 - save %sp,-104,%sp - !#PROLOGUE# 1 - st %i1,[%fp-8] - ld [%fp-8],%f10 - sethi %hi(LC0),%o7 - fitod %f10,%f4 - ldd [%o7+%lo(LC0)],%f8 - cmp %i1,0 - bge L248 - mov %i0,%i5 - faddd %f4,%f8,%f4 -L248: - st %i2,[%fp-8] - ld [%fp-8],%f10 - fmuld %f4,%f8,%f6 - cmp %i2,0 - bge L249 - fitod %f10,%f2 - faddd %f2,%f8,%f2 -L249: - st %i3,[%fp-8] - faddd %f6,%f2,%f2 - ld [%fp-8],%f10 - cmp %i3,0 - bge L250 - fitod %f10,%f4 - faddd %f4,%f8,%f4 -L250: - fdivd %f2,%f4,%f2 - sethi %hi(LC1),%o7 - ldd [%o7+%lo(LC1)],%f4 - fcmped %f2,%f4 - nop - fbge,a L251 - fsubd %f2,%f4,%f2 - fdtoi %f2,%f2 - st %f2,[%fp-8] - b L252 - ld [%fp-8],%i4 -L251: - fdtoi %f2,%f2 - st %f2,[%fp-8] - ld [%fp-8],%i4 - sethi %hi(-2147483648),%g2 - xor %i4,%g2,%i4 -L252: - umul %i3,%i4,%g3 - rd %y,%i0 - subcc %i2,%g3,%o7 - subxcc %i1,%i0,%g0 - be L253 - cmp %o7,%i3 - - add %i4,-1,%i0 - add %o7,%i3,%o7 - st %o7,[%i5] - ret - restore -L253: - blu L246 - mov %i4,%i0 - add %i4,1,%i0 - sub %o7,%i3,%o7 -L246: - st %o7,[%i5] - ret - restore - diff --git a/po/Makefile.in.in b/po/Makefile.in.in deleted file mode 100644 index 28726a21f..000000000 --- a/po/Makefile.in.in +++ /dev/null @@ -1,196 +0,0 @@ -# Makefile for program source directory in GNU NLS utilities package. -# Copyright (C) 1995-1997, 2000, 2001 by Ulrich Drepper -# -# This file file be copied and used freely without restrictions. It can -# be used in projects which are not available under the GNU General Public License -# but which still want to provide support for the GNU gettext functionality. -# Please note that the actual code is *not* freely available. - -PACKAGE = @PACKAGE@ -VERSION = @VERSION@ - -# These two variables depend on the location of this directory. -subdir = po -top_builddir = .. - -SHELL = /bin/sh -@SET_MAKE@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -datadir = @datadir@ -localedir = $(datadir)/locale -gettextsrcdir = $(datadir)/gettext/po - -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` - -CC = @CC@ -GMSGFMT = @GMSGFMT@ -MSGFMT = @MSGFMT@ -XGETTEXT = @XGETTEXT@ -MSGMERGE = msgmerge - -DEFS = @DEFS@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ - -INCLUDES = -I.. -I$(top_srcdir)/intl - -COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) - -POFILES = @POFILES@ -GMOFILES = @GMOFILES@ -DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \ -$(POFILES) $(GMOFILES) - -POTFILES = \ - -CATALOGS = @CATALOGS@ - -.SUFFIXES: -.SUFFIXES: .c .o .po .pox .gmo .mo - -.c.o: - $(COMPILE) $< - -.po.pox: - $(MAKE) $(PACKAGE).pot - $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox - -.po.mo: - $(MSGFMT) -o $@ $< - -.po.gmo: - file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ - && rm -f $$file && $(GMSGFMT) --statistics -o $$file $< - - -all: all-@USE_NLS@ - -all-yes: $(CATALOGS) -all-no: - -# Note: Target 'all' must not depend on target '$(srcdir)/$(PACKAGE).pot', -# otherwise packages like GCC can not be built if only parts of the source -# have been downloaded. - -$(srcdir)/$(PACKAGE).pot: $(POTFILES) $(srcdir)/POTFILES.in - $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \ - --add-comments --keyword=_ --keyword=N_ \ - --files-from=$(srcdir)/POTFILES.in \ - && test ! -f $(PACKAGE).po \ - || ( rm -f $(srcdir)/$(PACKAGE).pot \ - && mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot ) - - -install: install-exec install-data -install-exec: -install-data: install-data-@USE_NLS@ - if test "$(PACKAGE)" = "gettext"; then \ - $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ - $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ - $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ - else \ - : ; \ - fi -install-data-no: all -install-data-yes: all - $(mkinstalldirs) $(DESTDIR)$(datadir) - @catalogs='$(CATALOGS)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - lang=`echo $$cat | sed 's/\.gmo$$//'`; \ - dir=$(localedir)/$$lang/LC_MESSAGES; \ - $(mkinstalldirs) $(DESTDIR)$$dir; \ - if test -r $$cat; then \ - $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \ - echo "installing $$cat as $(DESTDIR)$$dir/$(PACKAGE).mo"; \ - else \ - $(INSTALL_DATA) $(srcdir)/$$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \ - echo "installing $(srcdir)/$$cat as" \ - "$(DESTDIR)$$dir/$(PACKAGE).mo"; \ - fi; \ - done - -# Define this as empty until I found a useful application. -installcheck: - -uninstall: - catalogs='$(CATALOGS)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - lang=`echo $$cat | sed 's/\.gmo$$//'`; \ - rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \ - done - if test "$(PACKAGE)" = "gettext"; then \ - rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ - else \ - : ; \ - fi - -check: all - -dvi info tags TAGS ID: - -mostlyclean: - rm -f core core.* *.pox $(PACKAGE).po *.new.po - rm -fr *.o - -clean: mostlyclean - -distclean: clean - rm -f Makefile Makefile.in POTFILES *.mo - -maintainer-clean: distclean - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - rm -f $(GMOFILES) - -distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) -dist distdir: - $(MAKE) update-po - @$(MAKE) dist2 -# This is a separate target because 'update-po' must be executed before. -dist2: $(DISTFILES) - dists="$(DISTFILES)"; \ - for file in $$dists; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - cp -p $$dir/$$file $(distdir); \ - done - -update-po: Makefile - $(MAKE) $(PACKAGE).pot - if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \ - cd $(srcdir); \ - catalogs='$(GMOFILES)'; \ - for cat in $$catalogs; do \ - cat=`basename $$cat`; \ - lang=`echo $$cat | sed 's/\.gmo$$//'`; \ - echo "$$lang:"; \ - if $(MSGMERGE) $$lang.po $(PACKAGE).pot -o $$lang.new.po; then \ - mv -f $$lang.new.po $$lang.po; \ - else \ - echo "msgmerge for $$cat failed!"; \ - rm -f $$lang.new.po; \ - fi; \ - done - $(MAKE) update-gmo - -update-gmo: Makefile $(GMOFILES) - @: - -Makefile: Makefile.in.in $(top_builddir)/config.status POTFILES.in - cd $(top_builddir) \ - && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ - $(SHELL) ./config.status - -# Tell versions [3.59,3.63) of GNU make not to export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/po/ca.po b/po/ca.po deleted file mode 100644 index e4545965e..000000000 --- a/po/ca.po +++ /dev/null @@ -1,4944 +0,0 @@ -# Missatges de gnupg en catal -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. -# Carles Sadurn Anguita , 2001. -# Jordi Mallach , 2001, 2002. -# -# Coses: -# ID d'usuari s mascul? -# Canviar ID -> ID d'usuari -# Xifratge vs. Xifrat -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.6\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-06-03 20:37+0200\n" -"Last-Translator: Jordi Mallach \n" -"Language-Team: Catalan \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Alerta: esteu usant memria insegura!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "l'operaci no s possible sense memria segura inicialitzada\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(potser heu utilitzat el programa erroni per a aquesta tasca)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "s" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "sS" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "no" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "eixir" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "error general" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "tipus de paquet desconegut" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "versi desconeguda" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algoritme de clau pblica desconegut" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algoritme de digest desconegut" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "clau pblica errnia" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "clau secreta errnia" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "signatura errnia" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "suma de control errnia" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "contrasenya errnia" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "no s'ha trobat la clau pblica" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algoritme de xifrat desconegut" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "no s'ha pogut obrir l'anell" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "paquet invlid" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armadura invlida" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "no s'ha trobat l'id de l'usuari" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "la clau secreta no est disponible" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "s'ha utilitzat una clau secreta incorrecta" - -#: util/errors.c:72 -msgid "not supported" -msgstr "no suportat" - -#: util/errors.c:73 -msgid "bad key" -msgstr "clau incorrecta" - -#: util/errors.c:74 -msgid "file read error" -msgstr "error de lectura" - -#: util/errors.c:75 -msgid "file write error" -msgstr "error d'escriptura" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritme de compressi desconegut" - -#: util/errors.c:77 -msgid "file open error" -msgstr "error en l'obertura del fitxer" - -#: util/errors.c:78 -msgid "file create error" -msgstr "error en la creaci del fitxer" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "contrasenya invlida" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritme de clau pblica no implementat" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritme de xifrat no implementat" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "classe de signatura desconeguda" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "error de la base de dades de confiana" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI erroni" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "lmit de recursos" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "l'anell no s vlid" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "certificat incorrecte" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "id d'usuari mal formada" - -#: util/errors.c:89 -msgid "file close error" -msgstr "error en el tancament del fitxer" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "error en el reanomenament del fitxer" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "error a l'eliminar fitxer" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "dades inesperades" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "conflicte de data" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritme de clau pblica inusable" - -#: util/errors.c:95 -msgid "file exists" -msgstr "el fitxer existeix" - -#: util/errors.c:96 -msgid "weak key" -msgstr "clau feble" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argument invlid" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI errnia" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI no suportada" - -#: util/errors.c:100 -msgid "network error" -msgstr "error de la xarxa" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "no xifrat" - -#: util/errors.c:103 -msgid "not processed" -msgstr "no processat" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "clau pblica inusable" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "clau secreta inusable" - -#: util/errors.c:107 -#, fuzzy -msgid "keyserver error" -msgstr "error general" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... a s un bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "heu trobat un bug... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "no s'ha pogut obrir %s: %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "no es pot fer stat de %s: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "%s no s un fitxer regular: s'ignorar\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "nota: el fitxer random_seed s buit\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "alerta: el tamany del fitxer random_seed no s vlid - no s'usar\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "no s'ha pogut llegir %s: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "nota: el fitxer random_seed no s'ha actualitzat\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "no s'ha pogut crear %s: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "no s'ha pogut escriure %s: %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "no s'ha pogut tancar `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "ALERTA: esteu usant un generador de nombres aleatoris insegur!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"El generador de nombres aleatoris s noms un peda\n" -"per a que funcioni - de cap manera s un GNA fort!\n" -"\n" -"NO UTILITZEU CAP DADA GENERADA PER AQUEST PROGRAMA!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"No hi ha prou bytes aleatoris. Per favor, feu alguna altra cosa perqu el\n" -"sistema tinga oportunitat de recollir ms entropia. (Fan falta %d bytes " -"ms)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Ordres:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[fitxer]|crea una signatura" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[fitxer]|crea una signatura en text clar" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "crea una firma separada" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "xifra dades" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "xifra noms amb xifratge simtric" - -#: g10/g10.c:315 -msgid "store only" -msgstr "noms emmagatzema" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "desxifra dades (predeterminat)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verifica una signatura" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "llista claus" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "llista claus i signatures" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "comprova les signatures de les claus" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "llista claus i empremtes dactilars" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "llista claus secretes" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "genera un nou parell de claus" - -#: g10/g10.c:327 -#, fuzzy -msgid "remove keys from the public keyring" -msgstr "elimina una clau de l'anell pblic" - -#: g10/g10.c:329 -#, fuzzy -msgid "remove keys from the secret keyring" -msgstr "elimina clau de l'anell secret" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "firma una clau" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "signa localment una clau" - -#: g10/g10.c:332 -#, fuzzy -msgid "sign a key non-revocably" -msgstr "signa localment una clau" - -#: g10/g10.c:333 -#, fuzzy -msgid "sign a key locally and non-revocably" -msgstr "signa localment una clau" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "signa o edita una clau" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "genera un certificat de revocament" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exporta claus" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exporta claus a un servidor de claus" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importa claus d'un servidor de claus" - -#: g10/g10.c:341 -#, fuzzy -msgid "search for keys on a key server" -msgstr "exporta claus a un servidor de claus" - -#: g10/g10.c:343 -#, fuzzy -msgid "update all keys from a keyserver" -msgstr "importa claus d'un servidor de claus" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importa/fon claus" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "llista noms la seqncia de paquets" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exporta els valors de confiana" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importa els valors de confiana" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "actualitza la base de dades de confiana" - -#: g10/g10.c:357 -#, fuzzy -msgid "unattended trust database update" -msgstr "actualitza la base de dades de confiana" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "arregla una base de dades de confiana corrompuda" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "lleva l'armadura a un fitxer o a stdin" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "crea l'armadura a un fitxer o a stdin" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [fitxers]imprimeix digests de missatges" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opcions:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "crea eixida amb armadura ascii" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOM|xifra per a NOM" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOM|usa NOM com a destinatari predeterminat" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "usa la clau predeterminada com a destinatari predeterminat" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "usa aquest id per a signar o desxifrar" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|nivell de compressi N (0 no comprimeix)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "usa mode de text cannic" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "fitxer d'eixida" - -# Cal comprovar el context. jm -#: g10/g10.c:393 -msgid "verbose" -msgstr "detall" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "una mica ms silencis" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "no usa el terminal en absolut" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "fora signatures v3" - -#: g10/g10.c:397 -#, fuzzy -msgid "do not force v3 signatures" -msgstr "fora signatures v3" - -#: g10/g10.c:398 -#, fuzzy -msgid "force v4 key signatures" -msgstr "fora signatures v3" - -#: g10/g10.c:399 -#, fuzzy -msgid "do not force v4 key signatures" -msgstr "fora signatures v3" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "sempre utilitza un MDC per a xifrar" - -#: g10/g10.c:402 -#, fuzzy -msgid "never use a MDC for encryption" -msgstr "sempre utilitza un MDC per a xifrar" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "no fa cap canvi" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "utilitza el gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "mode batch: no pregunta mai" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "suposa s en la majoria de les preguntes" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "suposa no en la majoria de les preguntes" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "afegeix aquest anell a la llista" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "afegeix aquest anell secret a la llista" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOM|usa NOM com a clau secreta predeterminada" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|usa aquest servidor per a buscar claus" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NOM|el joc de carcters ser NOM" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "llig opcions del fitxer" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|escriu informaci d'estat en aquest FD" - -#: g10/g10.c:427 -#, fuzzy -msgid "|[file]|write status info to file" -msgstr "|FD|escriu informaci d'estat en aquest FD" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|IDCLAU|confia definitivament en aquesta clau" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FITXER|carrega el mdul d'extensi especificat" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emula el mode descrit en RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"estableix totes les opcions de paquets, xifrat i digest al comportament " -"d'OpenPGP" - -#: g10/g10.c:443 -#, fuzzy -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"estableix totes les opcions de paquets, xifrat i digest al comportament " -"d'OpenPGP" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|usa el mode de contrasenya especificat" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NOM|usa l'algoritme de digest de missatges NOM per a les contrasenyes" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NOM|usa l'algoritme de xifratge NOM per a les contrasenyes" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOM|usa l'algoritme de xifratge NOM" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOM|usa l'algoritme de digest de missatges NOM" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|usa l'algoritme de compressi N" - -# elimina o descarta? jm -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "descarta el camp keyid dels paquets xifrats" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(En la pgina del man hi ha una llista completa d'ordres i d'opcions)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Exemples:\n" -"\n" -" -se -r Pep [fitxer] signa i xifra per a l'usuari Pep\n" -" --clearsign [fitxer] crea una signatura en text clar\n" -" --detach-sign [fitxer] crea una signatura separada\n" -" --list-keys [noms] mostra claus\n" -" --fingerprint [noms] mostra empremtes dactilars\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Per favor informeu sobre els errors a .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "s: gpg [opcions] [fitxers] (-h per a veure l'ajuda)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintaxi: gpg [opcions] [fitxers]\n" -"signa, comprova, xifra o desxifra\n" -"l'operaci predeterminada depn de les dades introdudes\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritmes admesos:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "s: gpg [opcions] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "ordres en conflicte\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTA: no existeix el fitxer d'opcions predeterminat %s\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTA: no existeix el fitxer d'opcions predeterminat %s\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "fitxer d'opcions %s: %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "llegint opcions de %s\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s no s un joc de carcters vlid\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: versi de fitxer %d invlid\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armadura invlida" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: versi de fitxer %d invlid\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "l'anell no s vlid" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "ALERTA: el programa podria crear un fitxer core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTA: %s no s per a s normal!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s no s perms amb %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s no t sentit amb %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "l'algoritme de xifratge triat no s vlid\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "el algorime de digest seleccionat no s vlid\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "el algorime de digest seleccionat no s vlid\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "l'algoritme de compressi ha d'estar en l'interval %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed ha de ser major que 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed ha de ser major que 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth ha d'estar entre el rang 1 a 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTA: el mode S2K simple (0) no s gens recomanable\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "mode S2K invlid; ha de ser 0, 1 o 3\n" - -#: g10/g10.c:1862 -#, fuzzy -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "mode S2K invlid; ha de ser 0, 1 o 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "llista les preferncies" - -#: g10/g10.c:1876 -msgid "invalid personal cipher preferences\n" -msgstr "" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "llista les preferncies" - -#: g10/g10.c:1884 -msgid "invalid personal compress preferences\n" -msgstr "" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "no s'ha pogut inicialitzar la base de dades de confiana: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [nom_del_fitxer]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [nom_del_fitxer]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [nom_del_fitxer]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [nom_del_fitxer]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [nom_del_fitxer]" - -#: g10/g10.c:2056 -#, fuzzy -msgid "--sign --symmetric [filename]" -msgstr "--symmetric [nom_del_fitxer]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [nom_del_fitxer]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [nom_del_fitxer]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key user-id" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key user-id" - -#: g10/g10.c:2110 -#, fuzzy -msgid "--nrsign-key user-id" -msgstr "--sign-key user-id" - -#: g10/g10.c:2118 -#, fuzzy -msgid "--nrlsign-key user-id" -msgstr "--lsign-key user-id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key user-id [ordres]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "no s'ha pogut obrir %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [user-id] [anell]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "no s'ha pogut llevar l'armadura: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "no s'ha pogut crear l'armadura: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "" -"algoritme de hash invlid %s\n" -"\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nom_del_fitxer]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Endavant, escriviu el missatge...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "no s'ha pogut obrir %s\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"el nom de la notaci noms pot tenir lletres, dgits, punts o subratllats i " -"acabar amb el signe =\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "un valor de notaci no pot utilitzar cap carcter de control\n" - -#: g10/g10.c:2737 -#, fuzzy -msgid "the given certification policy URL is invalid\n" -msgstr "la URL de poltica donada no s vlida\n" - -#: g10/g10.c:2739 -#, fuzzy -msgid "the given signature policy URL is invalid\n" -msgstr "la URL de poltica donada no s vlida\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armadura: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "capalera d'armadura no vlida: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "capalera d'armadura: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "capalera de signatura clara invlida\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "signatures en text pla anidades\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "lnia escapada amb gui no vlida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armadura inesperada:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "carcter radix64 %02x invlid oms\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "fi de fitxer prematur (no CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "fi de fitxer prematur (en CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC mal format\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "error de CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "f de fitxer prematur (al final)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "error en la ltima lnia\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "no s'han trobat dades OpenPGP vlides.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armadura invlida: lnia ms llarga que %d carcters\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"carcter quoted printable en l'armadura - probablement s'ha utilitzat un " -"MTA amb errors\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "No s'ha especificat cap ra" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "La clau ha estat substituda" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "La clau ha estat compromesa" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "La clau ja no s'usa" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "La ID d'usuari ja no s vlid" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Ra de la revocaci: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Comentari: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "" - -#: g10/pkclist.c:258 -#, fuzzy, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"No hi ha cap valor de confiana assignat a %lu:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -#, fuzzy -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Fins a quin punt confieu en aquest usuari per a verificar\n" -"les claus d'altres usuaris (mirant passaports,\n" -"comprovant empremtes de diferents fonts...)?\n" -"\n" -" 1 = No ho s\n" -" 2 = No hi confie\n" -" 3 = Hi confie poc\n" -" 4 = Hi confie completament\n" -" s = mostra ms informaci\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr "" - -#: g10/pkclist.c:274 -#, fuzzy, c-format -msgid " %d = I do NOT trust\n" -msgstr "%08lX: La clau no s de confiana\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr "" - -#: g10/pkclist.c:276 -#, fuzzy, c-format -msgid " %d = I trust fully\n" -msgstr "%s no s un fitxer de base de dades de confiana\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr "" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr "" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = torna al men principal\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr "" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = ix\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "La vostra decisi? " - -#: g10/pkclist.c:316 -#, fuzzy -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Realment voleu eliminar aquesta clau? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificats que duen a una clau de confiana absoluta:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "clau %08lX: aquesta clau ha estat revocada!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Voleu usar de tota manera aquesta clau?" - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "clau %08lX: aquesta subclau ha estat revocada!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: la clau ha caducat\n" - -#: g10/pkclist.c:448 -#, fuzzy, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -" No hi ha res que indique que la signatura pertany al seu propietari.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: La clau no s de confiana\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: No hi ha garanties que aquesta clau pertanga realment al seu\n" -"propietari per s'accepta de tota manera\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Aquesta clau pertany probablement al seu propietari\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Aquesta clau s nostra\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"No s segur que la clau pertanga al seu propietari.\n" -"Si realment sabeu qu feu, podeu respondre\n" -"que s a la segent pregunta\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "ALERTA: s una clau no fiable!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "ALERTA: Aquesta clau ha estat revocada pel propietari!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " A podria significar que la signatura s falsificada.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "ALERTA: Aquesta subclau ha estat revocada pel propietari!\n" - -#: g10/pkclist.c:580 -#, fuzzy -msgid "Note: This key has been disabled.\n" -msgstr "Aquesta clau ha estat desactivada" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Nota: La clau ha caducat!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "ALERTA: Aquesta clau no ve certificada per una firma de confiana!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" No hi ha res que indique que la signatura pertany al seu propietari.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "ALERTA: La clau no s de confiana!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Probablement la signatura s falsa.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "ALERTA: Aquesta clau no ve certificada per signatures prou fiables!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr "No s segur que la signatura pertanga al seu propietari.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: ignorat: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: ignorat: clau pblica ja present\n" - -#: g10/pkclist.c:811 -#, fuzzy -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "No heu especificat usuari. (Podeu usar -r)\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Usuari inexistent.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "ignorat: la clau pblica ja s'ha especificat com a destinatari\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "La clau pblica est desactivada.\n" - -#: g10/pkclist.c:870 -#, fuzzy -msgid "skipped: public key already set\n" -msgstr "%s: ignorat: clau pblica ja present\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "destinatari predeterminat desconegut %s\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: ignorat: la clau pblica est desactivada\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "no hi ha adreces vlides\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "" - -#: g10/keygen.c:189 -#, fuzzy, c-format -msgid "preference %c%lu duplicated\n" -msgstr "%s ignorat: duplicat\n" - -#: g10/keygen.c:194 -#, fuzzy, c-format -msgid "too many `%c' preferences\n" -msgstr "llista les preferncies" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "Carcter invlid en el camp *nom*\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "escriptura de l'autosignatura\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "escriptura de l'autosignatura\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "escriptura de la signatura de comprovaci de la clau\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "grandria de la clau invlida; s'hi usaran %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "grandria de la clau arrodonida fins a %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Trieu quin tipus de clau voleu:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA i ElGamal (predeterminat)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (noms signar)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (noms xifrar)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (signar i xifrar)\n" - -#: g10/keygen.c:949 -#, fuzzy, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) DSA (noms signar)\n" - -#: g10/keygen.c:951 -#, fuzzy, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) ElGamal (noms xifrar)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (signar i xifrar)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Trieu: " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "L'us d'aquest algoritme est desaconsellat - crear igualment? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Selecci invlida.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Preparat per a generar un nou parell de claus %s.\n" -" grandria mnima: 768 bits\n" -" grandria predeterminada: 1024 bits\n" -" grandria mxima aconsellada: 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Quina grandria voleu? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA noms permet clau entre 512 i 1024 bits\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "calu massa petita; 1024 bits s el mnim perms per a claus RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "clau massa petita; 768 bits s el mnim perms.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "clau massa llarga; %d s el mxim perms.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"No es recomanen claus ms llargues de 2048 bits perqu\n" -"els clculs sn VERITABLEMENT llargs!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Segur que voleu aquesta grandria? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"D'acord, per sapigueu que la radiaci del monitor i del teclat tamb son " -"molt vulnerables als atacs!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "La grandria sollicitada s %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "arrodonida fins a %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Especifiqueu el temps de validesa de la clau.\n" -" 0 = no caduca\n" -" = caduca als n dies\n" -" w = caduca a les n setmanes\n" -" m = caduca als n mesos\n" -" y = caduca als n anys\n" - -#: g10/keygen.c:1126 -#, fuzzy -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Especifiqueu el temps de validesa de la clau.\n" -" 0 = no caduca\n" -" = caduca als n dies\n" -" w = caduca a les n setmanes\n" -" m = caduca als n mesos\n" -" y = caduca als n anys\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Indiqueu la validesa de la clau (0) " - -#: g10/keygen.c:1150 -#, fuzzy -msgid "Signature is valid for? (0) " -msgstr "Indiqueu la validesa de la clau (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valor invlid\n" - -#: g10/keygen.c:1160 -#, fuzzy, c-format -msgid "%s does not expire at all\n" -msgstr "La clau no caduca\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, fuzzy, c-format -msgid "%s expires at %s\n" -msgstr "La clau caduca el %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"El vostre sistema no pot representar dates posteriors a l'any 2038.\n" -"Tanmateix, les manejar b fins l'any 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "s correcte? (s/n)" - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Necessiteu un ID d'usuari per a identificar la vostra clau; el programa\n" -"construeix la id de l'usuari amb el Nom, Comentari i Adrea electrnica\n" -"d'aquesta forma:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nom i cognoms" - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Carcter invlid en el camp *nom*\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "El nom no pot comenar amb un dgit\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "El nom ha de tenir, si ms no, 5 carcters\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Adrea electrnica: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "No s una adrea vlida\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Comentari: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Carcter invlid en el camp *comentari*\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Esteu usant el joc de carcters `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Heu triat l'usuari:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "No inclogueu l'adrea ni en el camp *nom* ni en el camp *comentari*\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoQq" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Canvia (N)om, (C)omentari, (E)mail o (Q) ix " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Canvia (N)om, (C)omentari, (E)mail o (O) d'acord / (Q) ix" - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Corregiu l'error primer\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Cal una contrasenya per a protegir la clau privada.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -#, fuzzy -msgid "passphrase not correctly repeated; try again" -msgstr "la contrasenya no s'ha repetit correctament; torneu a intentar-ho\n" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"No voleu contrasenya: s una mala idea!\n" -"B. Si voleu canviar-la ms endavant,\n" -"useu aquest programa amb l'opci \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Cal generar molts bits aleatoriament. s bona idea fer alguna altra cosa\n" -"(teclejar, moure el ratol, usar els discos) durant la generaci de\n" -"nombres primers; a dna oportunitat al generador de nombres aleatoris\n" -"d'aconseguir prou entropia.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "La parella de claus DSA ha de tenir 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Generaci de claus cancellada.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "escriptura de la clau pblica a `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "escriptura de la clau privada a `%s'\n" - -#: g10/keygen.c:2205 -#, fuzzy, c-format -msgid "no writable public keyring found: %s\n" -msgstr "clau %08lX: no s'ha trobat la clau pblica: %s\n" - -#: g10/keygen.c:2211 -#, fuzzy, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "clau %08lX: no s'ha trobat la clau privada: %s\n" - -#: g10/keygen.c:2225 -#, fuzzy, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "error mentre s'escrivia l'anell %s: %s\n" - -#: g10/keygen.c:2232 -#, fuzzy, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "error mentre s'escrivia l'anell %s: %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "claus pblica i privada creades i signades.\n" - -#: g10/keygen.c:2253 -#, fuzzy -msgid "key marked as ultimately trusted.\n" -msgstr "Certificats que duen a una clau de confiana absoluta:\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Noteu que aquesta clau no serveix per a xifrar. Potser vulgueu usar l'ordre\n" -"\"--edit-key\" per a generar una clau secundria per a tal propsit.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "La generaci de claus ha fallat: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"la clau s'ha creat %lu segons en el futur (salt en el temps o problemes\n" -"amb el rellotge)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"la clau s'ha creat %lu segons en el futur (salt en el temps o problemes\n" -"amb el rellotge)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "NOTA: crear subclaus per a claus v3 no s conformant amb OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Crear realment? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: no s'ha pogut obrir: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "error en la creaci de la contrasenya: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, fuzzy, c-format -msgid "`%s' already compressed\n" -msgstr "%lu claus processades\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: ALERTA: fitxer buit\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "llegint des de %s\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: no s'ha trobat l'algoritme de xifratge %d en les preferncies\n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s xifrat per a: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, fuzzy, c-format -msgid "key `%s' not found: %s\n" -msgstr "no s'ha trobat l'usuari %s: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, fuzzy, c-format -msgid "error reading keyblock: %s\n" -msgstr "error en la lectura de %s: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "clau %08lX: no s una clau rfc2440 - ignorada\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "clau %08lX: no protegida - ignorada\n" - -#: g10/export.c:246 -#, fuzzy, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "clau %08lX: clau nova: s'ignorar\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "ALERTA: no s'hi ha exportat res\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "massa entrades en la memria cau de claus pbliques - desactivada\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[No s'ha trobat l'usuari]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "s'usar la clau secundria %08lX en lloc de la primria %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "clau %08lX: clau secreta sense clau pblica: ignorada\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "bloc de tipus %d ignorat\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "fins ara s'han processat %lu claus\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "error en la lectura de %s: %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Nombre total processat: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " claus noves ignorades: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sense ID: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importades: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " no modificades: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " IDs d'usuaris nous: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " subclaus noves: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " signatures noves: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " noves revocacions: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr "claus privades llegides: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "claus privades importades: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "claus privades no canviades: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importades: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "clau %08lX: sense ID\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "clau %08lX: no hi ha una subclau per a l'enlla de la clau\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "clau %08lX: s'ha acceptat la ID d'usuari no auto-signada '" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "clau %08lX: l'ID no s vlid\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "a pot ser causat per l'absncia d'autofirma\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "clau %08lX: no s'ha trobat la clau pblica: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "clau %08lX: clau nova: s'ignorar\n" - -#: g10/import.c:646 -#, fuzzy, c-format -msgid "no writable keyring found: %s\n" -msgstr "error mentre s'escrivia l'anell %s: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "escriptura a %s\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "error mentre s'escrivia l'anell %s: %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "clau %08lX: clau pblica importada\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "clau %08lX: no correspon a la nostra cpia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "clau %08lX: no s'ha trobat el bloc de claus original: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "clau %08lX: no s'ha pogut llegir el bloc de claus original: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "clau %08lX: 1 ID d'usuari nou\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "clau %08lX: %d ID nous\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "clau %08lX: 1 signatura nova\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "clau %08lX: %d signatures noves\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "clau %08lX: 1 subclau nova\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "clau %08lX: %d subclaus noves\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "clau %08lX: no modificada\n" - -#: g10/import.c:844 -#, fuzzy, c-format -msgid "no default secret keyring: %s\n" -msgstr "no hi ha anell pblic predeterminat\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "clau %08lX: clau privada importada\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "clau %08lX: ja es troba en l'anell privat\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "clau %08lX: no s'ha trobat la clau privada: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"clau %08lX: falta la clau pblica: no es pot aplicar el certificat\n" -"de revocaci\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "clau %08lX: certificat de revocaci invlid: %s: rebutjat\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "clau %08lX: certificat de revocaci importat\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "clau %08lX: no hi ha ID per a la signatura\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "clau %08lX: algoritme de clau pblica no suportat\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "clau %08lX: autofirma no vlida\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "clau %08lX: no hi ha una subclau per a l'enlla de la clau\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "clau %08lX: algoritme de clau pblica no suportat\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "clau %08lX: enlla de subclau invlid\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "clau %08lX: enlla de subclau invlid\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "clau %08lX: no hi ha una subclau per a l'enlla de la clau\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "clau %08lX.%lu: Subclau de revocaci vlida\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "clau %08lX: enlla de subclau invlid\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "clau %08lX: ID ignorat '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "clau %08lX: subclau ignorada\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "clau %08lX: signatura inexportable (classe %02x) - ignorada\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "clau %08lX: certificat de revocaci en el lloc equivocat - ignorat\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "clau %08lX: certificat de revocaci no vlid: %s - ignorat\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "clau %08lX: certificat de revocaci en el lloc equivocat - ignorat\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "clau %08lX: detectat ID duplicat - fusionat\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "clau %08lX: s'hi ha afegit el certificat de revocaci\n" - -#: g10/import.c:1491 -#, fuzzy, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "clau %08lX: %d signatures noves\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revocaci]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[autosignatura]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 signatura errnia\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d signatures errnies\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 signatura no comprovada per falta de clau\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d signatures no comprovades per falta de clau\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 signatura no comprovada a causa d'un error\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d signatures no comprovades a causa d'errors\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "Ha estat detectat 1 ID sense autosignatura vlida\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "Han estat detectats %d IDs sense autosignatura vlida\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Segur que voleu aquesta grandria? " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "ALERTA: %s s un fitxer buit\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "Ja est signat amb la clau %08lX\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "Ja est signat amb la clau %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "No hi ha res que signat amb la clau %08lX\n" - -#: g10/keyedit.c:478 -#, fuzzy -msgid "This key has expired!" -msgstr "Nota: La clau ha caducat!\n" - -#: g10/keyedit.c:498 -#, fuzzy, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Aquesta clau no est protegida.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "" - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr "" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr "" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr "" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr "" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Esteu segurs que voleu signar aquesta clau\n" -"amb la vostra clau: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "a pot ser causat per l'absncia d'autofirma\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"La signatura es marcar com a inexportable.\n" -"\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"La signatura es marcar com a inexportable.\n" -"\n" - -#: g10/keyedit.c:620 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"La signatura es marcar com a inexportable.\n" -"\n" - -#: g10/keyedit.c:624 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"La signatura es marcar com a inexportable.\n" -"\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Signar realment? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "Ha fallat el procs de signatura: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Aquesta clau no est protegida.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Les parts secretes de la clau primria no estan disponibles.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "La clau est protegida.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "No es pot editar aquesta clau: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Introduu la nova contrasenya per a la clau secreta.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"No voleu contrasenya: a s probablement una *mala* idea!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "N'esteu segur de voler fer a? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "posant la signatura al lloc correcte\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "eixit del men" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "desa" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "desa i ix" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "ajuda" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "mostrar aquesta pantalla" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "mostra empremta" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "llista" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "llista claus i ID" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "triar ID N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "clau" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "tria clau secundria N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "comprovar" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "llista signatures" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "signa la clau" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "signar la clau localment" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "nrsign" -msgstr "sign" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "sign the key non-revocably" -msgstr "signar la clau localment" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "nrlsign" -msgstr "lsign" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "sign the key locally and non-revocably" -msgstr "signar la clau localment" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "depura" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "afegir ID d'usuari" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "" - -#: g10/keyedit.c:920 -#, fuzzy -msgid "add a photo ID" -msgstr "afegir ID d'usuari" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "esborrar ID d'usuari" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "afegir una clau secundria" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "esborrar una clau secundria" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "revocada" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "afegir una clau secundria" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "esborrar signatures" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "canviar la data de caducitat" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "canvia entre el llistat de claus secretes i pbliques" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -#, fuzzy -msgid "list preferences (expert)" -msgstr "llista les preferncies" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "list preferences (verbose)" -msgstr "llista les preferncies" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "setpref" -msgstr "pref" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "set preference list" -msgstr "llista les preferncies" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updpref" -msgstr "pref" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updated preferences" -msgstr "llista les preferncies" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "canvia la contrasenya" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "canvia la confiana" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revoca signatures" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revoca una clau secundria" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "desactivar clau" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "activa una clau" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "no es pot fet aix en mode batch\n" - -#: g10/keyedit.c:1000 -#, fuzzy, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "error en la lectura de %s: %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "La clau secreta est disponible.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Ordre>" - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Cal la clau secreta per a fer a.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Useu l'ordre toggle abans.\n" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "La clau est protegida.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Signar tots els IDs? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Pista: Trieu els IDs que voleu signar\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Heu de seleccionar al menys un ID.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "No podeu esborrar l'ltim ID!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Eliminar tots els IDs seleccionats? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Eliminar aquest ID? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Heu de seleccionar, si ms no, una clau.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Realment voleu esborrar les claus seleccionades? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Realment voleu eliminar aquesta clau? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Realment voleu revocar les claus seleccionades? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Realment voleu revocar aquesta clau? " - -#: g10/keyedit.c:1354 -#, fuzzy -msgid "Really update the preferences for the selected user IDs? " -msgstr "Eliminar tots els IDs seleccionats? " - -#: g10/keyedit.c:1356 -#, fuzzy -msgid "Really update the preferences? " -msgstr "Crear els certificats de revocaci? (y/N)" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Desar els canvis? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Eixir sense desar? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "ha fallat l'actualitzaci: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "ha fallat l'actualitzaci de la clau secreta: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "La clau no ha canviat, per tant no cal actualitzaci.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "L'ordre no s vlida (proveu help)\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "ALERTA: Aquesta clau ha estat revocada pel propietari!\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX creada: %s expira: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " confiana: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Aquesta clau ha estat desactivada" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! la subclau ha estat revocada: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- s'ha trobat una revocaci falsa\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problemes en la comprovaci de la revocaci: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Segur que voleu aquesta grandria? " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Esborrar aquesta signatura correcta? (y/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Esborrar aquesta signatura invlida? (y/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Esborrar aquesta signatura desconeguda? (y/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Esborrar aquesta auto-signatura? (y/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d signatura esborrada.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d signatures esborrades.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "No s'hi ha eliminat res.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Introduu la grandria de la clau" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Per favor, elimineu les seleccions de les claus secretes.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Per favor, seleccioneu com a molt una clau secundria.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Canviant la data de caducitat per a una clau secundria.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Canviant la data de caducitat per a una clau primria.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "No podeu canviar la data de caducitat de les claus v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "No hi ha cap signatura corresponent en l'anell secret\n" - -#: g10/keyedit.c:2546 -#, fuzzy -msgid "Please select exactly one user ID.\n" -msgstr "Heu de seleccionar al menys un ID.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "No hi ha cap ID amb l'ndex %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "No hi ha cap clau secundria amb l'ndex %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "ID d'usuari: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"signat amb la vostra clau %08lX el %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"signat amb la vostra clau %08lX el %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "%s signatura de: %s\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Realment voleu revocar aquesta clau? " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Crear un certificat de revocaci per a aquesta signatura? (y/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Heu signat els segents ID d'usuari:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " signat per %08lX el %s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revocat per %08lX el %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Esteu a punt de revocar aquestes signatures:\n" - -#: g10/keyedit.c:3013 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " signat per %08lX el %s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Crear els certificats de revocaci? (y/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "ho hi ha clau secreta\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "escriptura de l'autosignatura\n" - -#: g10/keylist.c:93 -#, fuzzy -msgid "Signature policy: " -msgstr "%s signatura de: %s\n" - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "ALERTA: s'hi ha trobat dades de notaci invlides\n" - -#: g10/keylist.c:127 -msgid "Critical signature notation: " -msgstr "" - -#: g10/keylist.c:129 -#, fuzzy -msgid "Signature notation: " -msgstr "Notaci: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr "[caduca: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "llista claus i empremtes dactilars" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Empremta digital:" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr "llista claus i empremtes dactilars" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Empremta digital:" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -#, fuzzy -msgid " Key fingerprint =" -msgstr " Empremta digital:" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "" -"algoritme de hash invlid %s\n" -"\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "dades xifrades amb %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "xifrat amb l'algoritme %d (desconegut)\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "la clau pblica s %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "dades xifrades amb clau pblica: bona clau de xifratge (DEK)\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "xifrat amb una clau %2$s de %1$u bits, ID %3$08lX, creada en %4$s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "xifrat amb una clau %s, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "ha fallat el desxifratge amb la clau pblica: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, fuzzy, c-format -msgid "assuming %s encrypted data\n" -msgstr "dades xifrades amb %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "desxifratge correcte\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "ALERTA: el missatge xifrat ha estat manipulat!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "ha fallat el desxifratge: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTA: el remitent ha sollicitat \"alt secret\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nom del fitxer original='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "revocaci autnoma: useu \"gpg --import\" per a aplicar-la\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notaci: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Poltica: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verificaci de signatura eliminada\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "no es poden manejar aquestes signatures mltiples\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Signatura creada %.*s usant una clau %s ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "Signatura INCORRECTA de \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -#, fuzzy -msgid "Expired signature from \"" -msgstr "Signatura correcta de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Signatura correcta de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "No s'ha pogut comprovar la signatura: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "no s una signatura separada\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "signatura autnoma de classe 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "signatura de l'estil antic (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "paquet arrel invlid detectat en proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "no s'han pogut desactivar els *core dump*: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "No haureu d'usar algoritmes experimentals!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"aquest algoritme de xifrat est desaconsellat; useu-ne un de ms estndard!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "%s: no s'ha pogut obrir: %s\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "ALERTA: %s s un fitxer buit\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "no s'ha pogut manejar l'algoritme de clau pblica %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "el subpaquet de tipus %d t el bit crtic activat\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent no est disponible en aquesta sessi\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "variable d'entorn GPG_AGENT_INFO mal formada\n" - -#: g10/passphrase.c:511 -#, fuzzy, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "l'algoritme de protecci %d no est suportat\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "no s'ha pogut connectar amb %s: %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -#, fuzzy -msgid "problem with the agent - disabling agent use\n" -msgstr "hi ha un problema amb l'agent: l'agent ha tornat 0x%lx\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (ID de la clau principal %08lX)" - -# Com es canvia l'ordre dels arguments? jm -# Ah, bingo! jm -# Uh, ara torna a donar error. -# La idea s ficar: -# "Necessiteu la contrasenya per desbloquejar la clau secreta de l'usuari:\n" -# "%1$.*s\n" -# "clau %3$s de %2$u bits, ID %4$08lX, creada en %5$s%6$s\n" -# jm -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Necessiteu la contrasenya per desbloquejar la clau secreta de l'usuari:\n" -"%.*s\n" -"clau de %u bits, %s, ID %08lX, creada en %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Introduu contrasenya\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Repetiu contrasenya\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "contrasenya massa llarga\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "resposta invlida del agent\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "cancellat per l'usuari\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "hi ha un problema amb l'agent: l'agent ha tornat 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Necessiteu la contrasenya per desbloquejar la clau secreta de\n" -"l'usuari: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "clau %2$s de %1$u bits, ID %3$08lX, creada en %4$s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "no es pot demanar la contrasenya en mode batch\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Introduu contrasenya: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Repetiu contrasenya: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "les dades no s'han desat; useu l'opci \"--output\" per desar-les\n" - -#: g10/plaintext.c:108 -#, fuzzy, c-format -msgid "error creating `%s': %s\n" -msgstr "error en la lectura de %s: %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Signatura separada.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Introduu el nom del fitxer de dades: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "llegint stdin...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "no hi ha dades signades\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "no s'han pogut obrir les dades signades `%s'\n" - -#: g10/pubkey-enc.c:101 -#, fuzzy, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinatari annim; es provar la clau secreta %08lX...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "d'acord, som el destinatari annim.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "la codificaci antiga del DEK no est suportada\n" - -#: g10/pubkey-enc.c:178 -#, fuzzy, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "l'algoritme de xifratge %d s desconegut o est desactivat\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "NOTA: no s'ha trobat l'algoritme de xifratge %d en les preferncies\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTA: la clau secreta %08lX caduca el %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "clau %08lX: aquesta clau ha estat revocada!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "sollicitud de la clau %08lX de %s...\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "no s'ha pogut obtenir del servidor la clau: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "error mentre s'enviava a `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "l'enviament a `%s' ha tingut xit (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "l'enviament a `%s' ha fallat: status=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "" - -#: g10/hkp.c:565 -#, fuzzy, c-format -msgid "can't search keyserver: %s\n" -msgstr "no s'ha pogut obtenir del servidor la clau: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "parts de la clau secreta no estan disponbles\n" - -#: g10/seckey-cert.c:59 -#, fuzzy, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "l'algoritme de protecci %d no est suportat\n" - -#: g10/seckey-cert.c:224 -#, fuzzy -msgid "Invalid passphrase; please try again" -msgstr "La contrasenya no s vlida; torneu a intentar-ho...\n" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "ALERTA: la clau s feble; per favor, canvieu la contrasenya.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"esta s una clau ElGamal generada per PGP que NO s segura per a " -"signatures!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "la clau pblica s %lu segons posterior a la signatura\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "la clau pblica s %lu segons posterior a la signatura\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"la clau s'ha creat %lu segons en el futur (salt en el temps o problemes\n" -"amb el rellotge)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"la clau s'ha creat %lu segons en el futur (salt en el temps o problemes\n" -"amb el rellotge)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTA: la clau de signatura %08lX va caducar el %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"es supossa una signatura incorrcta a causa d'un bit crtic desconegut\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "No s'ha pogut comprovar la signatura creada: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s signatura de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "ALERTA: %s s un fitxer buit\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "no s'ha pogut creat %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: no s'ha trobat l'algoritme de xifratge %d en les preferncies\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "signatura:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:1029 -#, fuzzy, c-format -msgid "%s encryption will be used\n" -msgstr "ha fallat el desxifratge: %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "no es poden manejar lnies ms llargues de %d carcters\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "la lnia d'entrada s superior a %d carcters\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "reg de la base de dades de confiana %lu: ha fallat lseek: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "" -"reg de la base de dades de confiana %lu: ha fallat la escriptura (n=%d): %" -"s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transacci de la base de dades de confiana massa gran\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: no s'ha pogut accedir: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: el directori no existeix!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: no s'ha pogut crear el bloqueig\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, fuzzy, c-format -msgid "%s: can't make lock\n" -msgstr "%s: no s'ha pogut crear el bloqueig\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: no s'ha pogut crear: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: no s'ha pogut crear un registre de versi: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: s'ha creat una base de dades de confiana invlida\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: s'ha creat la base de dades de confiana\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: base de dades de confiana invlida\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: no s'ha pogut crear la taula hash: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: error al actualitzar el registre de la versi: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: error al llegir el registre de la versi: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: error al escriure el registre de la versi: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "base de dades de confiana: ha fallat lseek: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "base de dades de confiana: ha fallat la lectura (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s no s un fitxer de base de dades de confiana\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: registre de versi amb nmero de registre %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: versi de fitxer %d invlid\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: error al llegir el registre lliure: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: error al escriure el registre de directoris: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: no s'ha pogut posar a zero un registre: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: no s'ha pogut afegir un registre: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"la base de dades de confiana est corrompuda; per favor, executeu gpg --" -"fix-trustdb.\n" - -#: g10/trustdb.c:200 -#, fuzzy, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "%s no s un ID de clau llarg vlid\n" - -#: g10/trustdb.c:235 -#, fuzzy, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "clau %08lX: acceptada com a clau fiable.\n" - -#: g10/trustdb.c:274 -#, fuzzy, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "clau %08lX: no es pot introduir en la base de dades de confiana\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"clau %08lX: no hi ha una clau pblica per a la clau fiable - ignorada\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "registre de confiana %lu, tipus %d: no s'ha pogut llegir: %s\n" - -#: g10/trustdb.c:338 -#, fuzzy, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "registre de confiana %lu: no s'ha pogut eliminar: %s\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "registre de confiana %lu, tipus %d: no s'ha pogut escriure: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "base de dades de confiana: no s'ha pogut sincronitzar: %s\n" - -#: g10/trustdb.c:468 -#, fuzzy -msgid "no need for a trustdb check\n" -msgstr "%s no s un fitxer de base de dades de confiana\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, fuzzy, c-format -msgid "next trustdb check due at %s\n" -msgstr "reg de la base de dades de confiana %lu: ha fallat lseek: %s\n" - -#: g10/trustdb.c:779 -#, fuzzy -msgid "checking the trustdb\n" -msgstr "canvia la confiana" - -#: g10/trustdb.c:933 -#, fuzzy, c-format -msgid "public key %08lX not found: %s\n" -msgstr "no s'ha trobat la clau pblica" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"no s'ha pogut verificar la signatura.\n" -"Recordeu que el fitxer de signatura (.sig o .asc)\n" -"ha de ser el primer que figure en la lnia d'ordres.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "lnia d'entrada %u massa llarga o hi falta LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"la clau no est marcada com a insegura - no es pot utilitzar amb el GNA " -"fals!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "%s ignorat: duplicat\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "%s ignorat: %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "ignorat: clau secreta ja present\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"Ignorada %s: s una clau ElGamal generada per PGP que no s segura per a " -"signatures!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "El fitxer %s existeix. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Sobreescriure? (s/N) " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: sufix desconegut\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Introduu el nou nom del fitxer" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "escrivint en stdout\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "es supossa que les dades s'han signat amb %s\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: s'ha creat el nou fitxer d'opcions\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: no s'ha pogut crear el directori: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: directori creat\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"ATENCI: el missatge s'ha xifrat amb una clau feble durant el xifratge\n" -"simtric.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problema al manejar un paquet xifrat\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "s'hi ha creat una clau feble - reintent\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"no s'ha pogut evitar una clau feble per a xifratge simtric;\n" -"hi ha hagut %d intents!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "no es pot fer aix en el mode per lots sense --yes\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Esborrar aquesta clau de l'anell? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "s una clau secreta! Voleu esborrar-la? " - -# fuzzy... jm -# (esborra aquest comentari i tal) -#: g10/delkey.c:168 -#, fuzzy, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "no s'ha pogut enumerar els blocs de claus: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, fuzzy, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "hi ha una clau secreta per a aquesta clau pblica!\n" - -#: g10/delkey.c:208 -#, fuzzy -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "utilitzeu l'opci --delete-secret-key per a eliminar-la primer.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"L'assignaci d'un valor ac s cosa vostra; aquest valor mai s'exportar\n" -"a cap tercer. Ho necessitem per a implementar la xarxa de confiana; no te\n" -"res a veure amb la xarxa de certificats (creada implcitament)." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Si voleu utilitzar aquesta clau revocada de totes maneres, dieu s." - -# fuzzy, "clau no confiable"? jm -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Si voleu utilitzar aquesta clau no confiable de totes maneres, dieu s." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Introduu l'ID d'usuari de la persona a qui voleu enviar el missatge." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Seleccioneu l'algoritme a utilitzar.\n" -"\n" -"DSA (tamb conegut com DSS) s el algoritme de signatura digital que noms\n" -"pot ser utilitzat per a signatures. Aquest s el algoritme suggerit perque\n" -"la comprovaci de signatures DSA s molt ms rpida que les de ElGamal.\n" -"\n" -"ElGamal s un algoritme que es pot utilitzar per a signatures i xifrat.\n" -"OpenPGP distingueix entre 2 variants d'aquest algoritme: una de noms " -"xifrat\n" -"i una de signatura+xifrat; en veritat s el mateix, per alguns parmentres\n" -"han de seleccionar-se d'una manera especial per a crear claus ms segures\n" -"per a signatures: aquest programa fa a, per altres implementacions\n" -"d'OpenPGP no estan obligades a entendre la variant signatura+xifrat.\n" -"\n" -"La primera clau (primria) ha de ser sempre una clau que siga capa de " -"signar;\n" -"aquesta s la ra per la que la clau de noms encriptaci ElGamal no est\n" -"disponible en aquest men." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Encara que aquestes claus estan definides en RFC2440, no es recomanen\n" -"Perqu no tots els programes hi poden treballar i perqu les\n" -"signatures que generen sn molt llargues i lentes de verificar." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Introduu la grandria de la clau" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Contesteu s o no" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Introduu el valor requerit tal i com es mostra en l'indicatiu.\n" -"s possible introduir una data USO (AAAA-MM-DD) per no rebreu\n" -"una bona resposta d'error - en canvi, el sistema tractar d'interpretar\n" -"el valor donat com un interval." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Introduu el nom del propietari de la clau" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "introduu una adrea de correu (opcional per molt recomanable)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Introduu un comentari opcional" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N canvia el nom.\n" -"C canvia el comentari.\n" -"E canvia l'adrea de correu electrnic.\n" -"O continua la generaci de les claus.\n" -"Q ix." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Contesteu s (o noms s) si s correcte generar la subclau." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Contesteu s si voleu signar TOTS els ID d'usuari" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Contesteu s si realment voleu eliminar aquest ID d'usuari.\n" -"Tots els certificats tamb es perdran!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Contesteu s si s correcte eliminar la subclau" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Aquesta s una signatura vlida en la clau; normalment no voldreu\n" -"eliminar aquesta signatura perque pot ser important per a establir\n" -"una connexi de confiana a la clau o a un altra clau certificada\n" -"per aquesta clau." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Aquesta signatura no es pot comprovar perque no teniu la clau\n" -"corresponent. Haurieu de pospossar la seua eliminaci fins que\n" -"sapigueu quina clau es va utilitzar ja que aquesta clau de signatura\n" -"podria establir una connexi de confiana a travs d'una altra clau ja\n" -"certificada." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"La signatura no s vlida. T sentit que l'elimineu de l'anell\n" -"de claus." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Aquesta s una signatura que enllaa el ID de l'usuari a la clau.\n" -"Normalment no s una bona idea eliminar una signatura com aquesta.\n" -"Actualment, GnuPG podria no poder utilitzar aquesta clau de nou, aix\n" -"que feu a noms si la auto-signatura no s vlida per alguna ra i\n" -"hi ha una segona disponible." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:244 -#, fuzzy -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "" -"Introduu la contrasenya; aquesta ha de ser una frase secreta \n" -" Blurb, blurb..." - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Per favor, repetiu l'ltima contrasenya per confirmar-la." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Doneu el nom del fitxer al que s'aplica la signatura" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Contesteu s si s correcte sobreescriure el fitxer" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Introduu un nom de fitxer. Si premeu RETURN s'hi usar el fitxer\n" -"predeterminat (apareix entre claudtors)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Haurieu d'especificar una ra per a la certificaci. Depenent en el\n" -"context teniu l'habilitat de triar d'aquesta llista:\n" -" La clau ha estat compromesa\n" -" Utilitzeu a si teniu alguna ra per a creure que persones no\n" -" autoritzades han tingut accs a la vostra clau secreta.\n" -" La clau ha estat reemplaada\n" -" Utilitzeu a si heu reemplaat aquesta clau amb una ms nova.\n" -" La clau ja no est en s\n" -" Utilitzeu a si heu retirat aquesta clau.\n" -" L'ID de l'usuari ja no s vlid\n" -" Utilitzeu a per a constatar que l'ID de l'usuari no s'hauria\n" -" d'utilitzar ms; a s'utilitza normalment per a marcar una adrea\n" -" de correu com invlida.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Si voleu podeu introduir un text que descriga per qu expediu aquest\n" -"certificat de revocaci. Per favor, sigueu concisos.\n" -"Una lnia buida indica el final del text.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "No hi ha ajuda disponible" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "No hi ha ajuda disponible per a `%s'" - -#: g10/keydb.c:178 -#, fuzzy, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "error mentre s'escrivia l'anell %s: %s\n" - -#: g10/keydb.c:185 -#, fuzzy, c-format -msgid "keyring `%s' created\n" -msgstr "%s: anell creat\n" - -#: g10/keydb.c:575 -#, fuzzy, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "%s: no s'ha pogut crear la taula hash: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "ALERTA: hi ha 2 fitxers amb informaci confidencial.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s s el que no ha canviat\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s s el nou\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Per favor, solucioneu aquest possible problema de seguretat\n" - -#: g10/keyring.c:1346 -#, fuzzy, c-format -msgid "checking keyring `%s'\n" -msgstr "no s'ha pogut tancar l'anell %s: %s\n" - -#: g10/keyring.c:1377 -#, fuzzy, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "fins ara s'han processat %lu claus\n" - -#: g10/keyring.c:1388 -#, fuzzy, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "llista claus i signatures" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: anell creat\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "heu d'executar GnuPG de nou perqu puga llegir el nou fitxer d'opcions\n" - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "massa bits aleatoris sollicitats; el lmit s %d\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NOMS]|comprova la base de dades de confiana" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOM=VALOR|usa aquesta notaci de dades" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key user-id" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key user-id" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key user-id" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "el primer carcter de la notaci ha de ser una lletra o un subratllat\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "els punts han d'estar envoltat per altres carcters\n" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Si voleu ms informaci vegeu http://www.gnupg.org" - -#~ msgid "Fingerprint:" -#~ msgstr "Empremta digital:" - -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "No s'ha trobat un cam de confiana vlid a la clau. Vegem si podem\n" -#~ "assignar valors de confiana no assignats.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "No s'ha trobat un cam que condueixe a una de les nostres claus.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "No s'han trobat certificats amb confiana no definida.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "No s'ha canviat cap valor de confiana.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "" -#~ "%08lX: no hi ha informaci per a calcular una probabilitat de confiana\n" - -#~ msgid "Enter the user ID: " -#~ msgstr "Introduu el nom d'usuari: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "ignorat: la clau pblica ja s'ha especificat amb --encrypt-to\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: error en la comprovaci de la clau: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "Segur que voleu crear una clau de signatura i xifratge? " - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Realment necessiteu una clau tan llarga? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: no s'ha trobat l'usuari: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "problema en la lectura del certificat: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "" -#~ "massa entrades en la memria cau de claus desconegudes - desactivada\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "clau secreta %08lX no importada (utilitzeu %s per a permitir-ho)\n" - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "clau %08lX: la nostra cpia no t auto-signatura\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: no s'ha trobat l'usuari\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "ha fallat l'actualitzaci de la base de dades de confiana: %s\n" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "no es coneix cap servidor de claus (useu l'opci \"--keyserver\")\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: no s un ID vlid\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "es suposa MDC erroni a causa d'un bit crtic desconegut\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "error al llegir el registre de directori per al LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: s'esperava registre de directori, s'ha obtingut %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "no hi ha una clau primria per al LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "error al llegir clau primria per al LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: ha fallat search_record: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "clau %08lX: la consulta del registre ha fallat\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "clau %08lX: ja es troba en la taula de claus de confiana\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "NOTE: la clau secreta %08lX no est protegida.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "clau %08lX: les claus pblica i secreta no coincideixen\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "no s'ha pogut enumerar les claus secretes: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "clau %08lX.%lu: Enlla de subclau correcta\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "clau %08lX.%lu: Enlla de subclau invlid: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "clau %08lX.%lu: Revocaci de clau vlida\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "clau %08lX.%lu: Revocaci de clau invlida: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Auto-signatura correcta" - -#~ msgid "Invalid self-signature" -#~ msgstr "Auto-signatura invlida" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Revocaci d'ID d'usuari vlida ignorada degut a una auto-signatura ms " -#~ "recent" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Revocaci d'ID d'usuari vlida" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Revocaci d'ID d'usuari invlida" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Certificat de revocaci vlid" - -#~ msgid "Good certificate" -#~ msgstr "Certificat correcte" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Certificat de revocaci invlid" - -#~ msgid "Invalid certificate" -#~ msgstr "Certificat invlid" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "el registre de signatura %lu[%d] apunta a un registre incorrecte.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "certificat duplicat: esborrat" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir ha fallat: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: la inserci ha fallat: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: la inserci ha fallat: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: inserit\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "error al llegir el registre de directori: %s\n" - -#~ msgid "\t%lu keys with errors\n" -#~ msgstr "\t%lu claus amb errors\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu claus inserides\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: registre de directori sense clau - ignorat\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\\t%lu degut a noves claus pbliques\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu claus ignorades\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu clau actualitzades\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Ooops, no hi ha claus\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Ooops, no hi ha IDs\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: ha fallat la cerca en el registre de directori: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "" -#~ "clau %08lX: ha fallat la inserci en la base de dades de confiana: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "clau %08lX.%lu: inserida en la base de dades de confiana\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "clau %08lX.%lu: creada en el futur (salt en el temps o problema de\n" -#~ "rellotge)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "clau %08lX.%lu: caducada el %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "clau %08lX.%lu: ha fallat la verificaci de confiana: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "problema al cercar %s en la base de dades de confiana: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "" -#~ "l'usuari %s no est en la base de dades de confiana - inserint-lo\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "no s'ha pogut posar %s en la base de dades de confiana - %s\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "AVS: encara no es poden manejar registres de prefncies llargs\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: no s'ha creat l'anell: %s\n" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "No es poden usar claus RSA en aquesta versi\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "No hi ha clau per a l'usuari\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "No hi ha usuari per a la clau\n" - -#~ msgid "invalid" -#~ msgstr "invlida" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "no hi ha clau secreta disponible per al desxifratge\n" diff --git a/po/cs.po b/po/cs.po deleted file mode 100644 index d77d6f385..000000000 --- a/po/cs.po +++ /dev/null @@ -1,4716 +0,0 @@ -# GnuPG Czech translation -# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Magda Prochzkov , Roman Pavlik 2001, 2002. -msgid "" -msgstr "" -"Project-Id-Version: gnupg-1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-04-20 10:20+0200\n" -"Last-Translator: Roman Pavlik \n" -"Language-Team: Czech \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-2\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "VAROVN: Pouvan pam nen bezpen!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "Vce informac naleznete na adrese http://www.gnupg.cz/faq.html\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "provst operaci nen mon bez inicializovan bezpen pamti\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(pravdpodobn jste pro tento kol pouili nesprvn program)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ano" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "aAyY" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "ne" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "ukonit" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "uUqQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "obecn chyba" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "neznm typ paketu" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "neznm verze" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "neznm algoritmus veejnho kle" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "neznm hashovac algoritmus" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "patn veejn kl" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "patn tajn kl" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "patn podpis" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "chyba kontrolnho soutu" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "patn heslo" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "veejn kl nenalezen" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "neznm ifrovac algoritmus" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "nemohu otevt soubor kl" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "neplatn paket" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "neplatn zpsob reprezentace v ASCII" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "neexistuje uivatel s tmto id" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "tajn kl nen dostupn" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "je pouit patn tajn kl" - -#: util/errors.c:72 -msgid "not supported" -msgstr "nepodporovno" - -#: util/errors.c:73 -msgid "bad key" -msgstr "patn kl" - -#: util/errors.c:74 -msgid "file read error" -msgstr "chyba pi ten souboru" - -#: util/errors.c:75 -msgid "file write error" -msgstr "chyba pi zpisu souboru" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "neznm kompresn algoritmus" - -#: util/errors.c:77 -msgid "file open error" -msgstr "chyba pi otvrn souboru" - -#: util/errors.c:78 -msgid "file create error" -msgstr "chyba pi vytven souboru" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "nesprvn heslo" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmus veejnho kle nen implementovn" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "ifrovac algoritmus nen implementovn" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "neznm tda podpisu" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "chyba v databzi dvry" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "patn MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "omezen zdroj" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "neplatn soubor kl" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "patn certifikt" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "patn formt id uivatele" - -#: util/errors.c:89 -msgid "file close error" -msgstr "chyba pi zavrn souboru" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "chyba pi pejmenovn souboru" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "chyba pi mazn souboru" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "neoekvan data" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "konflikt asovho raztka" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "nepouiteln algoritmus s veejnm klem" - -#: util/errors.c:95 -msgid "file exists" -msgstr "soubor existuje" - -#: util/errors.c:96 -msgid "weak key" -msgstr "slab kl" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "neplatn argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "patn URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "toto URI nen podporovno" - -#: util/errors.c:100 -msgid "network error" -msgstr "chyba st" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "nezaifrovno" - -#: util/errors.c:103 -msgid "not processed" -msgstr "nezpracovno" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "nepouiteln veejn kl" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "nepouiteln tajn kl" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "chyba serveru kl" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... toto je chyba v programu (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "nalezena chyba v programu ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "nemohu otevt `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "nemohu pout pkaz stat na `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' nen normln soubor - ignoruji\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "poznmka: soubor random_seed je przdn\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "varovn: neplatn velikost random_seed - soubor nepouit\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "nemohu st `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "poznmka: soubor random_seed nen aktualizovn\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "nemohu vytvoit `%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "nemohu zapisovat do `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "nemohu zavt `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "VAROVN: pouit genertor nhodnch sel nen bezpen!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Genertor nhodnch sel je pouze atrapa, aby program mohl bet,\n" -"v dnm ppad nen kryptograficky bezpen!\n" -"\n" -"NEPOUVEJTE JAKKOLIV DATA VYTVOEN TMTO PROGRAMEM!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Nedostatek nhodnch bajt. Prosm, pracujte s operanm systmem, abyste\n" -"mu umonili zskat vce entropie (je poteba %d bajt).\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Pkazy:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[soubor]|vytvoit podpis" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[soubor]|vytvoit podpis v itelnm dokumentu" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "vytvoit podpis oddlen od dokumentu" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "ifrovat data" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[soubor]|ifrovat soubor" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "ifrovn pouze se symetrickou ifrou" - -#: g10/g10.c:315 -msgid "store only" -msgstr "pouze uloen" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "deifrovat data (implicitn)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[soubor]|deifrovat soubor" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verifikovat podpis" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "vypsat seznam kl" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "vypsat seznam kl a podpis" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "zkontrolovat podpisy kl" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "vypsat seznam kl a fingerprint" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "vypsat seznam tajnch kl" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "vytvoit nov pr kl" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "odstranit kl ze souboru veejnch kl" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "odstranit kl ze souboru tajnch kl" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "podepsat kl" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "podepsat kl lokln" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "podepsat kl bez monosti revokace podpisu" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "" -"podepsat kl lokln a bez monosti\n" -" revokace podpisu" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "podepsat nebo modifikovat kl" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "vytvoit revokan certifikt" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exportovat kle" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exportovat kle na server kl" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importovat kle ze serveru kl" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "vyhledat kle na serveru kl" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "aktualizovat vechny kle ze serveru kl" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importovat/slouit kle" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "vypsat pouze poad paket" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "" -"exportovat hodnoty dvryhodnosti\n" -" vlastnka kle" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "" -"importovat hodnoty dvryhodnosti\n" -" vlastnka kle" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "aktualizovat databzi dvry" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "neinteraktivn aktualizace databze dvry" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "opravit naruenou databzi dvry" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Dekdovat ASCII soubor nebo std. vstup" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Zakdovat soubor nebo std. vstup do ASCII" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [soubory]|vypi hash" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Monosti:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "vytvo vstup zakdovan pomoc ASCII" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|JMNO|ifrovat pro JMNO" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|JMNO|pout JMNO jako implicitnho adresta" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "" -"pout implicitn kl jako implicitnho\n" -" adresta" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "" -"pout tento id uivatele pro podepsn\n" -" nebo deifrovn" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "" -"|N|nastavit rov komprimace N (0 - dn\n" -" komprimace)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "pout kanonick textov md" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "pout jako vstupn soubor" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "s dodatenmi informacemi" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "bt o trochu vc tich" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "vbec nepouvat terminl" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "vynutit podpisy verze 3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "nevynucovat podpisy verze 3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "vynutit podpisy verze 4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "nevynucovat podpisy verze 4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "pro ifrovn vdy pout MDC" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "pro ifrovn nikdy nepout MDC" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "neprovdt dn zmny" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "pouijte gpg-agenta" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "dvkov reim: nikdy se na nic neptat" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "automaticky odpovdt ANO na vtinu otzek" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "automaticky odpovdt NE na vtinu otzek" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "" -"pidat tento soubor kl do seznamu\n" -" pouvanch soubor kl" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "pidat tento soubor tajnch kl do seznamu" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "uka ve kterm souboru kl je vypsan kl" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|JMNO|pouij JMNO jako implicitn tajn kl" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "" -"|POTA|pouij tento server kl pro vyhledvn\n" -" kl" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|JMNO|nastav znakovou sadu terminlu na JMNO" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "st nastaven ze souboru" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|zapsat informace o stavu do tohoto FD" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[SOUBOR]|zapi informaci o stavu do SOUBORu" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KL|pln dvovat tomuto kli" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|SOUBOR|nahrt roziujc modul SOUBOR" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emulovat md popsan v RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"nastav vechny vlastnosti paket, ifer\n" -" a hash jako v OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"nastav vechny vlastnosti paket, ifer\n" -" a hash jako v PGP 2.x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|pout md hesla N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|ALG|pout hashovac algoritmus ALG pro hesla" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|ALG|pout ifrovac algoritmus ALG pro hesla" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|ALG|pout ifrovac algoritmus ALG" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|ALG|pout hashovac algoritmus ALG" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|pout kompresn algoritmus N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "" -"zahodit identifiktor kle z ifrovanch\n" -" paket" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Zobrazit fotografick ID" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Nezobrazovat fotografick ID" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" -"Nastavit pkazov dek k prohlen\n" -" fotografickho ID" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Pouijte manulov strnky pro kompletn seznam vech pkaz a monost)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -" -se -r Bob [soubor] podepsat a zaifrovat pro uivatele Bob\n" -" --clearsign [soubor] vytvoit podpis itelnho dokumentu\n" -" --detach-sign [soubor] vytvoit podpis oddlen od dokumentu\n" -" --list-keys [jmna] vypsat kle\n" -" --fingerprint [jmna] vypsat fingerprinty \n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "" -"Chyby oznamte, prosm, na adresu .\n" -"Pipomnky k pekladu .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Pouit: gpg [monosti] [soubory] (-h pro pomoc)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Syntaxe: gpg [monosti] [soubory]\n" -"podepsat, ovit, ifrovat nebo deifrovat\n" -"implicitn operace zvis na vstupnch datech\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Podporovan algoritmy:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uit: gpg [monosti]" - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "konfliktn pkazy\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "VAROVN: vlastnictv pro %s nastaveno nebezpen \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "VAROVN: pstupov prva pro %s nejsou nastavena bezpen \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "VAROVN: vlastnictv pro %s nastaveno nebezpen \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "VAROVN: pstupov prva pro %s nejsou nastavena bezpen \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "POZNMKA: neexistuje implicitn soubor s monostmi `%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "POZNMKA: neexistuje implicitn soubor s monostmi `%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "soubor s monostmi `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "tu monosti z `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s nen platn znakov sada\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "nelze pout URI serveru kl - chyba analzy URI\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "VAROVN: pouvn paralteru %s se nedoporuuje.\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "neplatn zpsob reprezentace v ASCII" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "VAROVN: pouvn paralteru %s se nedoporuuje.\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "neplatn soubor kl" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "nelze nastavit exec-path na %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "VAROVN: program me vytvoit soubor core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "VAROVN: %s pepe %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "POZNMKA: %s nen pro normln pouit!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "Nen dovoleno pouvat %s s %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s nedv s %s smysl!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -"v mdu --pgp2 mete vytvet pouze oddlen podpisy nebo podpisy iteln " -"jako text\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "v mdu --pgp2 nelze souasn ifrovat a podepisovat\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "v mdu --pgp2 muste pout soubor (ne rouru).\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "ifrovn zprv v mdu --pgp2 vyaduje algoritmus IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "tato zprva nen pro PGP 2.x pouiteln\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "vybran ifrovac algoritmus je neplatn\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "vybran hashovac algoritmus je neplatn\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "vybran hashovac algoritmus je neplatn\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "kompresn algoritmus mus bt v rozmez %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "poloka completes-needed mus bt vt ne 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "poloka marginals-needed mus bt vt ne 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "poloka max-cert-depth mus bt v rozmez od 1 do 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "POZNMKA: jednoduch md S2K (0) je drazn nedoporuovn\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "neplatn md S2K; mus bt 0, 1 nebo 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "neplatn implicitn rove kontroly; mus bt 0, 1, 2 nebo 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "neplatn pedvolby \n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "neplatn pedvolby \n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "neplatn pedvolby \n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "neplatn pedvolby \n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "nemohu inicializovat databzi dvry: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [jmno souboru]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [jmno souboru]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [jmno souboru]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [jmno souboru]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [jmno souboru]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [jmno souboru]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [jmno souboru]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [jmno souboru]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key id uivatele" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key id uivatele" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key id uivatele" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key id uivatele" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key id uivatele [pkazy]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "nelze otevt %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [id uivatele] [soubor s kli (keyring)]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "dekdovn z ASCII formtu selhalo: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "kdovn do ASCII formtu selhalo: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "neplatn hashovac algoritmus `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[jmno souboru]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Zante pst svou zprvu ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "nelze otevt `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"jmno me obsahovat pouze psmena, slice, teky nebo podtrtka a konit " -"s '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "hodnota neme obsahovat dn kontroln znaky\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "zadan URL pro certifikan politiku je neplatn\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "zadan URL pro podepisovac politiku je neplatn\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "ASCII kdovn: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "neplatn hlavika ASCII kdovn: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "ASCII hlavika: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "neplatn hlavika podpisu v itelnm formtu\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "vnoen podpisy v itelnm formtu\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "nesprvn oznaen dku mnusy: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "neoekvan kdovn ASCII:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "neplatn znak formtu radix64 %02x byl peskoen\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "pedasn konec souboru (dn CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "pedasn konec souboru (dn CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "patn formt CRC\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Chyba CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "pedasn konec souboru (v patice)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "chyba v patice\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "nenalezena dn platn data ve formtu OpenPGP.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "neplatn kdovn ASCII: dek je del ne %d znak\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"neplatn znak (quoted-printable) v ASCII kdovn - pravdpodobn byl pouit " -"patn MTA\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Dvod nebyl specifikovn" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Kl je nahrazen" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Kl byl zkompromitovn" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Kl se ji nepouv" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Identifiktor uivatele ji neplat" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Dvod pro revokaci: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Revokan poznmka: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMuUqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"K nen piazena dn hodnota dvry:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Prosm rozhodnte, nakolik dvete tomuto uivateli, e sprvn\n" -"verifikuje kle jinch uivatel (prohldnutm cestovnch pas,\n" -"kontrolou fingerprint z rznch zdroj...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Nevm\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = Nedvuji\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Dvuji sten\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Dvuji pln\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Dvuji absolutn\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = prosm o vce informac\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = zpt do hlavnho menu\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = peskoit tento kl\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " u = ukonit\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Vae rozhodnut? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Opravdu chcete nastavit pro tento kl absolutn dvru? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certifikty vedouc k finlnmu dvryhodnmu kli:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "kl %08lX: kl byl revokovn\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Pout pesto tento kl? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "kl %08lX: podkl byl revokovn!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: skonila platnost kle\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Nic nenaznauje tomu, e tento podpis pat vlastnkovi kle.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: NEdvujeme tomuto kli!\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Nen jist, zda tento podpis pat vlastnkovi, pesto je akceptovn\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Tento kl pravdpodobn nle jeho majiteli\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Tento kl nle nm (mme odpovdajc tajn kl)\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"NEN jist, zda tento kl pat osob, kter se vydv za jeho\n" -"vlastnka. Pokud *skuten* vte, co dlte, mete na otzku\n" -"odpovdt ano\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "VAROVN: Je pouit nedvryhodn kl!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "VAROVN: Tento kl byl revokovn svm vlastnkem!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " To me znamenat, e podpis je padlan.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "VAROVN: Tento podkl byl revokovn svm vlastnkem!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Poznmka: Tento kl byl oznaen jako neplatn (disabled).\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Poznmka: Skonila platnost tohoto kle!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "VAROVN: Tento kl nen certifikovn dvryhodnm podpisem!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Nic nenaznauje tomu, e tento podpis pat vlastnkovi kle.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "VAROVN: NEdvujeme tomuto kli!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Tento podpis je pravdpodobn PADLAN.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"VAROVN: Tento kl nen certifikovn dostaten dvryhodnmi podpisy!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Nen jist, zda tento podpis pat vlastnkovi.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: peskoeno: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: peskoeno: veejn kl je ji obsaen v databzi\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Nespecifikoval jste identifiktor uivatele (user ID). Mete pout \"-r\"\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Napite identifiktor uivatele (user ID). Ukonete przdnm dkem: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Takov identifiktor uivatele neexistuje.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "peskoeno: veejn kl je u nastaven podle implicitnho adresta\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Veejn kl je neplatn (disabled).\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "peskoeno: veejn kl je ji nastaven\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "neznm implicitn adrest `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: peskoeno: veejn kl je neplatn (disabled)\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "dn platn adresy\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "pedvolba %c%lu nen platn\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "duplicita pedvolby %c%lu\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "pli mnoho `%c' pedvoleb\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "neplatn znak v etzci s pedvolbami\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "zapisuji podpis kle sebou samm\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "zapisuji podpis kle sebou samm\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "zapisuji \"key-binding\" podpis\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "neplatn dlka kle; pouiji %u bit\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "dlka kle zaokrouhlena na %u bit\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Prosm, vyberte druh kle, kter chcete:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA a ElGamal (implicitn)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (pouze pro podpis)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (pouze pro ifrovn)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (pro ifrovn a podpis)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (pouze pro podpis)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (pouze pro ifrovn)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (pro ifrovn a podpis)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "V vbr? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" -"Pouit tohoto algoritmu se ji nedoporuuje - chcete ho pesto vytvoit? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Neplatn vbr.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Chystm se vytvoit nov pr kl %s.\n" -" minimln velikost kle je 768 bit\n" -" implicitn velikost kle je 1024 bit\n" -" nejvy navrhovan velikost kle je 2048 bit\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Jakou velikost kle si pejete? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "Kl DSA mus mt velikost od 512 do 1024 bit.\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "" -"velikost kle je pli mal; minimln dovolen velikost pro RSA je 1024 " -"bit.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "" -"velikost kle je pli mal; minimln dovolen velikost je 768 bit.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "velikost kle je pli velk; maximln dovolen hodnota je %d.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Velikosti kle vt jak 2048 bit se nedoporuuj, protoe\n" -"vpoty pak trvaj VELMI dlouho!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Opravdu chcete vytvoit kl tto dlky? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Dobe, ale nezapomete, e informace mohou bt vyzrazeny z potae tak " -"elektromagnetickm vyzaovnm monitoru nebo klvesnice!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Poadovan dlka kle je %u bit.\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "zaokrouhleno na %u bit\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Prosm urete, jak dlouho by kl ml platit.\n" -" 0 = doba platnosti kle nen omezena\n" -" = doba platnosti kle skon za n dn\n" -" w = doba platnosti kle skon za n tdn\n" -" m = doba platnosti kle skon za n msc\n" -" y = doba platnosti kle skon za n let\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Prosm urete, jak dlouho by ml podpis platit.\n" -" 0 = doba platnosti podpisu nen omezena\n" -" = doba platnosti podpisu skon za n dn\n" -" w = doba platnosti podpisu skon za n tdn\n" -" m = doba platnosti podpisu skon za n msc\n" -" y = doba platnosti podpisu skon za n let\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Kl je platn pro? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Podpis je platn pro? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "neplatn hodnota\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "platnost %s neskon\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "platnost %s skon %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"V systm neum zobrazit data po roce 2038.\n" -"V kadm ppad budou data korektn zpracovvna do roku 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Je to sprvn (a/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Aby bylo mon rozpoznat V kl, muste znt identifiktor uivatele;\n" -"program jej slo z Vaeho jmna a pjmen, komente a e-mailu\n" -"v tomto tvaru:\n" -" \"Magda Prochazkova (student) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Jmno a pjmen: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Neplatn znak ve jmn\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Jmno neme zanat slic\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Jmno mus bt dlouh alespo 5 znak\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "E-mailov adresa: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Neplatn e-mailov adresa\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Koment: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Neplatn znak v komenti\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Pouvte znakovou sadu `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Zvolil(a) jste tento identifiktor uivatele:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Do pole jmno nebo koment nepite, prosm, e-mailovou adresu.\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "jJkKeEPpUu" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Zmnit (J)mno, (K)oment, (E)-mail nebo (U)konit? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "" -"Zmnit (J)mno, (K)oment, (E)-mail, (P)okraovat dl nebo (U)konit " -"program? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Nejdv, prosm, opravte chybu\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Pro ochranu Vaeho tajnho kle muste zadat heslo.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "heslo nen zopakovno sprvn; zkuste to znovu" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Nechcete heslo - to *nen* dobr npad!\n" -"Dobe, budu pokraovat bez hesla. Kdykoliv mete heslo zmnit pouitm\n" -"tohoto programu s parametrem \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Musme vytvoit mnoho nhodnch bajt. Bhem vytven mete\n" -"provdt njakou jinou prci na potai (pst na klvesnici, pohybovat " -"my,\n" -"pouvat disky); dky tomu m genertor lep anci zskat dostatek " -"entropie.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "Pr kl DSA bude dlouh 1024 bit.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Vytven kle bylo zrueno.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "zapisuji veejn kl do `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "zapisuji tajn kl do `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "nenalezen zapisovateln soubor veejnch kl (pubring): %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "nenalezen zapisovateln soubor tajnch kl (secring): %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "chyba pi zpisu do souboru veejnch kl `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "chyba pi zpisu do souboru tajnch kl `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "veejn a tajn kl byly vytvoeny a podepsny.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "kl oznaen jako absolutn dvryhodn.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Tento kl neme bt pouit pro ifrovn. K vytvoen\n" -"sekundrnho kle pro tento el mete pout pkaz \"--edit-key\".\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Vytvoen kle se nepodailo: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"kl byl vytvoen %lu sekund v budoucnosti (dolo ke zmn asu nebo\n" -"je problm se systmovm asem)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"kl byl vytvoen %lu sekund v budoucnosti (dolo ke zmn asu nebo\n" -"je problm se systmovm asem)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "POZNMKA: vytvoen podkle pro kle v3 nen v souladu s OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Opravdu vytvoit? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output pro tento pkaz nen platn\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: nemohu otevt: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "chyba pi vytven hesla: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' je ji zakomprimovn\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: VAROVN: soubor je przdn\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"v mdu --pgp2 mete ifrovat pouze RSA klem o dlce 2048 bit a mn\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "tu z `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "algoritmus IDEA nelze pout pro vechny kle, pro kter ifrujete.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "POZNMKA: v pedvolbch nenalezen ifrovac algoritmus %d\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Tento pkaz nen v md %s dovolen.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s zaifrovan pro: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "kl `%s' nenalezen: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "chyba pi ten bloku kle: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "kl %08lX: nen ve formtu RFC 2440 - peskoeno\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "kl %08lX: nen chrnn - peskoeno\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "kl %08lX: PGP 2.x kl - peskoeno\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "VAROVN: nebylo nic vyexportovno\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "pli mnoho poloek v bufferu veejch kl - vypnuto\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[User ID not found]" - -# c-format -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Neplatn kl %08lX zmnn na platn pomoc --always-non-selfsigned-uid\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "pouvm sekundrn kl %08lX msto primrnho kle %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "kl %08lX: tajn kl bez kle veejnho - peskoeno\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "blok typu %d byl peskoen\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu kle byly doposud zpracovny\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "chyba pi ten `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Celkov poet zpracovanch kl: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " peskoeny nov kle: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " bez identifiktor (user ID): %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importovno: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " beze zmn: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nov id uivatel (user ID): %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nov podkle: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nov podpisy: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " nov revokace kl: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " peten tajn kle: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " importovan tajn kle: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "tajn kle nezmnny: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importovno: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "kl %08lX: chyb identifiktor uivatele\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "kl %08lX: neexistuje podkl pro vzn kl\n" - -# c-format -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "kl %08lX: pijat id uivatele '%s',kter nen podepsn jm samm\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "kl %08lX: chyb platn identifiktor uivatele\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "me to bt zpsobeno chybjcm podpisem kle jm samm\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "kl %08lX: veejn kl nenalezen: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "kl %08lX: nov kl - peskoen\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "nenalezen zapisovateln soubor kl (keyring): %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "zapisuji do '%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "chyba pi zpisu souboru kl (keyring) `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "kl %08lX: veejn kl importovn\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "kl %08lX: neodpovd na kopii\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "kl %08lX: nemohu najt originln blok kle: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "kl %08lX: nemohu st originln blok kle: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "kl %08lX: 1 nov identifiktor uivatele\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "kl %08lX: %d novch identifiktor uivatele\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "kl %08lX: 1 nov podpis\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "kl %08lX: %d novch podpis\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "kl %08lX: 1 nov podkl\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "kl %08lX: %d novch podkl\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "kl %08lX: beze zmn\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "nen nastaven implicitn soubor tajnch kl %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "kl %08lX: tajn kl importovn\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "kl %08lX: je ji v souboru tajnch kl\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "kl %08lX: nenalezen tajn kl: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"kl %08lX: chyb veejn kl - nemohu aplikovat revokan certifikt\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "kl %08lX: neplatn revokan certifikt: %s - zamtnuto\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "kl %08lX: revokan certifikt importovn\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "kl %08lX: neexistuje id uivatele pro podpis\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"kl %08lX: nepodporovan algoritmus veejnho kle u uivatelskho id \"%s" -"\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "" -"kl %08lX: neplatn podpis kle jm samm u uivatelskho id \"%s\"\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "kl %08lX: neexistuje podkl pro vzn kl\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "kl %08lX: nepodporovan algoritmus veejnho kle\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "kl %08lX: neplatn vazba podkle\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "kl %08lX: neplatn vazba podkle\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "kl %08lX: neexistuje podkl pro vzn kl\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "kl %08lX: neplatn vazba podkle\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "kl %08lX: neplatn vazba podkle\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "kl %08lX: identifiktor uivatele peskoen '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "kl %08lX: podkl peskoen\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "kl %08lX: podpis nen exportovateln (tda %02x) - peskoeno\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "kl %08lX: revokan certifikt na patnm mst - peskoeno \n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "kl %08lX: neplatn revokan certifikt: %s - peskoen\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "kl %08lX: revokan certifikt na patnm mst - peskoeno \n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "kl %08lX: objeven duplikovan identifiktor uivatele - slouen\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"VAROVN: kl %08lX me bt revokovn: zkoum zskat revokan kl %" -"08lX\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"VAROVN: kl %08lX me bt revokovn: revokan kl %08lX nenalezen.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "kl %08lX: pidn revokan certifikt\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "kl %08lX: podpis kle jm samm (direct key signature)\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revokace]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[podpis kle jm samm]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 patn podpis\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d patnch podpis\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 podpis neoven, protoe chyb kl\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d podpis neovench, protoe chyb kl\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 podpis neoven, protoe vznikla chyba\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d podpis neovench, protoe vznikly chyby\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "objeven 1 identifiktor uivatele bez platnho podpisu jm samm\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "objeveno %d identifiktor uivatele bez platnho podpisu jm samm\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Uivatelsk ID \"%s\" je revokovno." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Jste si jist(), e stle chcete podpsat tento kl? (a/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Nelze podepsat.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "VAROVN: soubor `%s' je przdn\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Va souasn podpis na \"%s\"\n" -"je pouze lokln.\n" -"\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Pejete si jej zmnit na pln exportovateln podpise? (a/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Va souasn podpis na \"%s\"\n" -"je pouze lokln.\n" -"\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Pejete si jej zmnit na pln exportovateln podpise? (a/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" je ji lokln podepsn klem %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" je ji podepsn klem %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nic k podepsn klem %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Platnost kle vyprela!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Platnost kle vypr %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Chcete, aby platnost Vaeho podpisu vyprela ve stejnou dobu? (A/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"Nemete udlat OpenPGP podpis kle typu PGP 2.x, kdy jste v --pgp2 mdu.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "To by zpsobilo nepouitelnost kle v PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"S jakou jistotou jste provili, e kl, kter chcete podepsat\n" -"pat ve uveden osob.\n" -"Pokud neznte odpov, zadejte \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Neodpovm.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Nijak jsem to nekontroloval(a).%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) sen jsem to ovil(a).%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Velmi peliv jsem to ovil(a).%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Jste si jist(), e chcete podepsat tento kl\n" -"svm klem: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "me to bt zpsobeno chybjcm podpisem kle jm samm\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"Podpis bude oznaen jako neexportovateln.\n" -"\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"Podpis bude oznaen jako neodvolateln (non-revocable).\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"Podpis bude oznaen jako neexportovateln.\n" -"\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"Podpis bude oznaen jako neodvolateln (non-revocable).\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Nijak jsem tento kl neovil.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"sten jsem ovil tento kl.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Velmi peliv jsem ovil tento kl.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Skuten podepsat? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "podepsn selhalo: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Tento kl nen chrnn.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Tajn sti primrnho kle nejsou dostupn.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Kl je chrnn.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Nen mon editovat tento kl: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Vlote nov heslo (passphrase) pro tento tajn kl.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Nechcete heslo - to *nen* dobr npad!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Opravdu to chcete udlat? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "pesunuji podpis kle na sprvn msto\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "ukonit toto menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "u" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "uloit" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "uloit a ukonit" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "ukzat tuto pomoc" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "vypsat fingerprint" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "vypsat seznam kl a id uivatel" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "vyberte identifiktor uivatele N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "vyberte sekundrn kl N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "vypsat seznam podpis" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "podepsat kl" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "podepsat kl lokln" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "podepsat kl bez monosti odvolat podpis (non-revocably)" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "podepsat kl lokln a bez monosti odvolat podpis (non-revocably)" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "pidat identifiktor uivatele" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "pidat fotografick ID" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "smazat identifiktor uivatele" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "pidat sekundrn kl" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "smazat sekundrn kl" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "pidat sekundrn kl" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "smazat podpisy" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "zmnit dobu platnosti" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "oznait uivatelsk ID jako primrn" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "pepnout mezi vypsnm seznamu tajnch a veejnch kl" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "vypsat seznam pedvoleb (pro experty)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "vypsat seznam pedvoleb (podrobn)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "nastavit seznam pedvoleb" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "aktualizovat pedvolby" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "zmnit heslo" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "zmnit dvryhodnost vlastnka kle" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revokovat podpisy" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revokovat sekundrn kl" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "nastavit kl jako neplatn (disable)" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "nastavit kl jako platn (enable)" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "ukzat fotografick ID" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "nelze provst v dvkovm mdu\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "chyba pi ten bloku tajnho kle `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Tajn kl je dostupn.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Pkaz> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Pro proveden tto operace je poteba tajn kl.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Prosm, nejdve pouijte pkaz \"toggle\" (pepnout).\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "Kl revokovn." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Opravdu podepsat vechny id uivatele? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Npovda: Vyberte id uivatele k podepsn\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Tento pkaz nen v md %s dovolen.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Muste vybrat alespo jeden id uivatele.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Nemete smazat posledn id uivatele!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Opravdu odstranit vechny vybran id uivatele? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Opravdu odstranit tento id uivatele? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Muste vybrat alespo jeden kl.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Opravdu chcete smazat vybran kle? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Opravdu chcete smazat tento kl? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Opravdu chcete revokovat vybran kle? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Opravdu chcete revokovat tento kl? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "Opravdu aktualizovat pedvoleby pro vybran id uivatele? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Opravdu aktualizovat pedvolby? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Uloit zmny? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Ukonit bez uloen? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "aktualizace selhala: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "aktualizace tajnho kle selhala: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Kl nebyl zmnn, take nen poteba jej aktualizovat.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Neplatn pkaz (zkuste \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Tento kl me bt revokovn %s klem %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "(citliv informace)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX vytvoen: %s platnost skon: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr "dvra: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Tento kl byl oznaen za neplatn (disabled)" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! podkl byl revokovn: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- nalezena padlan revokace\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problm oven revokace: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Prosm nezapomete, e zobrazovan daje o platnosti kl nemus\n" -"bt sprvn, dokud znova nespustte program.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"VAROVN: Toto je PGP2 kl. Pidn fotografickho ID me v nkterch\n" -" verzch PGP vst k odmtnut tohoto kle.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Jste si jist, e jej chcete stle pidat? (a/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Nemli by jste pidvat fotografick ID k PGP2 kli.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Smazat tento dobr podpis? (a/N/u)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Smazat tento neplatn podpis? (a/N/u)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Smazat tento neznm podpis? (a/N/u)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Opravdu smazat tento podpis podepsan sebou samm? (a/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Smazn %d podpis.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Smazno %d podpis.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Nic nebylo smaznno.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Vlote dlku kle" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Prosm, odstrate vbr z tajnch kl.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Prosm, vyberte nejve jeden sekundrn kl.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Mnm dobu platnosti sekundrnho kle.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Mnm dobu platnosti primrnho kle.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Nemete zmnit dobu platnosti kle verze 3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "V souboru tajnch kl chyb odpovdajc podpis\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Prosm, vyberte prv jeden id uivatele .\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "" -"kl %08lX: neplatn podpis kle jm samm u uivatelskho id \"%s\"\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Neexistuje identifiktor uivatele s indexem %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Neexistuje sekundrn kl s indexem %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "id uivatele: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"podepsno Vam klem %08lX v %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"lokln podepsno Vam klem %08lX v %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Platnost podpisu vypr %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Jste si jist, e jej chcete stle revokovat? (a/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Vytvoit pro tento podpis revokan certifikt? (a/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Podepsal(a) jste nsledujc identifiktory uivatele:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " podepsno %08lX v %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revokovno %08lX v %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Chystte se revokovat tyto podpisy:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " podepsno %08lX v %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (nexeportovateln)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Opravdu vytvoit revokan certifikty? (a/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "neexistuje tajn kl\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Zobrazuji %s fotografick ID o velikosti %ld pro kl 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Podepisovac politika: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Podepisovac politika: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "VAROVN: nalezen neplatn formt zpisu datumu\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Podepisovac notace: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Podepisovac notace: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "nen v pmo itelnm formtu" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "soubor kl (keyring)" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [platnost skon: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "vypsat seznam kl a fingerprint" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingerprint kle =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Fingerprint kle =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingerprint kle =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Fingerprint kle =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "neplatn hashovac algoritmus `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s zaifrovan data\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "zaifrovno neznmm algoritmem %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "veejn kl je %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "data zaifrovna veejnm klem: sprvn DEK\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "zaifrovna %u-bitovm %s klem, ID %08lX, vytvoenm %s\n" - -# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( -# [kw] -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "zaifrovno %s klem, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "deifrovn veenm klem selhalo: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "pedpokldm %s ifrovanch dat\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" -"algoritmus IDEA nen dostupn; optimisticky se jej pokusme nahradit " -"algoritmem %s\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "deifrovn o.k.\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "VAROVN: se zaifrovanou zprvou bylo manipulovno!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "deifrovn selhalo: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "POZNMKA: odeslatel poadoval (\"for-your-eyes-only\")\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "pvodn jmno souboru='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "" -"samostatn revokan certifikt - pouijte \"gpg --import\", chcete-li jej " -"ut\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notace: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Politika: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verifikace podpisu potlaena\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "neumm pracovat s tmito nsobnmi podpisy\n" - -# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "" -"Podpis vytvoen %.*s pomoc %s kle s identifiktorem uivatele %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "PATN podpis od \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Podpis s vyprenou platnost od \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Dobr podpis od \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[nejist] " - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Nemohu ovit podpis: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "toto nen podpis oddlen od dokumentu\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "samostatn podpis tdy 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "podpis starho typu (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "nalezen neplatn koenov paket v proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "nemohu vypnout vytven core soubor: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Experimentln algoritmy by se nemly pouvat!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"tento ifrovac algoritmus se nedoporuuje; prosm, pouijte njak " -"standardnj!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "IDEA modul pro GnuPG nenalezen\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"vce informac naleznete v dokumentu http://www.gnupg.cz/why-not-idea.html\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "VAROVN: pouvn paralteru %s se nedoporuuje.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "VAROVN: pouvn paralteru %s se nedoporuuje.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "pujte msto nj \"--keyserver-options %s\" \n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "nemohu pracovat s algoritmem veejnho kle %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "podpaket typu %d m nastaven kritick bit\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent nen v tomto sezen dostupn\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "nemohu nastavit PID clienta pro gpg-agenta\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "nelze zskat server read file descriptor pro agenta r\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "nezle zskat server write file descriptor pro agenta\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "patn formt promnn prosted GPG_AGENT_INFO\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "gpg-agent protokol verze %d nen podporovn\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "nemohu se pipojit k `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problm v komunikaci s gpg-agentem\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problm s agentem - pouvn agenta vypnuto\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (hlavn ID kle %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Potebujete heslo, abyste odemknul(a) tajn kl pro uivatele:\n" -"\"%.*s\"\n" -"Kl o dlce %u bit, typ %s, ID %08lX, vytvoen %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Vloit heslo\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Opakovat heslo\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "heslo je pli dlouh\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "neplatn reakce od agenta\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "zrueno uivatelem\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problm s agentem: agent vrac 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Muste znt heslo, abyste odemknul(a) tajn kl pro\n" -"uivatele: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "dlka %u bit, typ %s, kl %08lX, vytvoen %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "v dvkovm reimu se nemohu ptt na heslo\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Vlote heslo: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Opakujte heslo: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"data nebyla uloena; k jejich uloen pouijte parametr pkazu \"--output" -"\"\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "chyba pi vytven `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Podpis oddlen od dokumentu.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Prosm, vlote nzev datovho souboru: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "tu standardn vstup ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "chyb podepsan data\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "nemohu otevt podepsan data '%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "anonymn adrest; zkoum tajn kl %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "o.k., my jsme anonymn adrest.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "star kdovn DEK nen podporovno\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "ifrovac algoritmus %d%s je neznm nebo je zneplatnn\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "POZNMKA: v pedvolbch nenalezen ifrovac algoritmus %d\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "POZNMKA: platnost tajnho kle %08lX skonila %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "kl %08lX: kl byl revokovn\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "poaduji kl %08lX z HKP serveru kl %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "nemohu dostat kl ze serveru kl: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "chyba pi posln na `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "spn odesln na `%s' (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "chyba odesln na `%s': (status=%u)\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "vyhledvm \"%s\" na HKP serveru %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "nemohu prohledvat server kl: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "tajn sti kle nejsou dostupn\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "ochrann algoritmus %d%s nen podporovn\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Neplatn heslo; prosm, zkuste to znovu" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "VAROVN: Objeven slab kl - zmte, prosm, znovu heslo.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"generuji _nevhodn_ 16-ti bitov kontroln souet pro ochranu soukromho " -"kle\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"toto je kl algoritmu ElGamal vygenerovan v PGP - podpisy jm vytvoen " -"NEJSOU bezpen!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "veejn kl je o %lu sekund novj ne podpis\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "veejn kl je o %lu sekund novj ne podpis\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"kl byl vytvoen %lu sekund v budoucnosti (dolo ke zmn asu nebo\n" -"je problm se systmovm asem)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"kl byl vytvoen %lu sekund v budoucnosti (dolo ke zmn asu nebo\n" -"je problm se systmovm asem)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "POZNMKA: podpisovmu kli %08lX skonila platnost %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "pedpokldm patn podpis, protoe je nastaven neznm kritick bit\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"VAROVN: nemohu %%-expandovat URL politiky (pli dlouh). Pouity " -"neexpandovan.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"VAROVN: nemohu %%-expandovat URL politiky (pli dlouh). Pouity " -"neexpandovan.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "kontrola vytvoenho podpisu se nepodaila: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s podpis od: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "VAROVN: soubor `%s' je przdn\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "v mdu --pgp2 mete pouze podepisovat s kli formtu PGP-2.x\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "%s: nemohu vytvoit: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "POZNMKA: v pedvolbch nenalezen ifrovac algoritmus %d\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "podepisuji:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"v mdu --pgp2 mete vytvet jen iteln podpisy s kli formtu PGP-2.x\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "bude pouito ifrovn %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "nemohu pracovat s dky delmi ne %d znak\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "vstupn dek je del ne %d znak\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "zznam v databzi dvry %lu: lseek() se nepodail: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "zznam v databzi dvry %lu: zpis se nepodail (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transakce s databz dvry je pli dlouh\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: nemohu pistoupit k: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: adres neexistuje!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: nemohu vytvoit zmek\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: nemohu zamknout\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: nemohu vytvoit: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: nepodailo se vytvoit zznam verze: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: vytvoena neplatn databze dvry\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: databze dvry vytvoena\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: neplatn databze dvry\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: nepodailo se vytvoit hashovac tabulku: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: chyba pi aktualizaci zznamu verze: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: chyba pi ten zznamu verze: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: chyba pi zpisu zznamu verze: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "databze dvry: procedura lseek() selhala: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "databze dvry: procedura read() (n=%d) selhala: %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: nen soubor databze dvry\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: zznam verze s slem %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: neplatn verze souboru %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: chyba pri ten volnho zznamu: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: chyba pi zpisu adresovho zznamu: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: vynulovn zznamu selhalo: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: pidn zznamu selhalo: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "databze dvry je pokozena; prosm spuste \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' nen platn dlouh keyID\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "kl %08lX: akceptovn jako dvryhodn kl\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "kl %08lX se v databzi dvry vyskytuje vce ne jednou\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"kl %08lX: nenalezen veejn kl k dvryhodnmu kli - peskoeno\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "zznam dvry %lu, typ po. %d: ten selhalo: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "zznam dvry %lu nen poadovanho typu %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "zznam dvry %lu, typ %d: zpis selhal: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "databze dvry: synchronizace selhala %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "nen nutn kontrolovat databzi dvry\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "dal kontrolova databze dvry v %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "kontroluji databzi dvry\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "veejn kl %08lX nebyl nalezen: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "veejn kl k absolutn dvryhodnmu kli %08lX nebyl nalezen\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "kontrola v hloubce %d podepsno=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"podpis nebylo mon ovit.\n" -"Prosm, nezapomete, e soubor s podpisem (.sig nebo .asc)\n" -"by ml bt prvnm souborem zadanm na pkazov dce.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "vstupn dek %u je pli dlouh nebo na konci chyb znak LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"kl nen oznaen jako nedostaten bezpen - nemohu jej pout s padlanm " -"RNG!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "peskoen `%s': duplikovn\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "peskoen `%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "peskoeno: tajn kl je u v databzi\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"peskoen `%s': toto je vygenerovan PGP kl podle algoritmu ElGamal,\n" -"podpisy vytvoen tmto klem nejsou bezpen!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Soubor `%s' existuje. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Pepsat (a/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: neznm ppona\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Vlote nov nzev souboru" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "zapisuji do standardnho vstupu\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "pedpokldm podepsan data v `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: vytvoen nov soubor s pedvolbami\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: nemohu vytvoit adres: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: adres vytvoen\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "VAROVN: zprva byla zaifrovna slabm klem v symetrick ife.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problm se zaifrovanm paketem\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "vytvoen slab kl - zkoum znovu\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"nemohu se vyvarovat slabho kle pro symetrickou ifru; operaci jsem zkusil " -"%d krt!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA poaduje pouit 160-ti bitovho hashovacho algoritmu\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "bez parametru \"--yes\" to nemohu v dvkovm mdu provst\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Smazat tento kl ze souboru kl? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Toto je tajn kl! - opravdu smazat? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "smazn bloku kle se nezdailo: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "informace o dvryhodnosti vlastnka kle vymazny\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "existuje tajn kl pro tento veejn kl \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "" -"abyste ho smazal(a), pouijte nejprve parametr \"--delete-secret-key\".\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Je na Vs, abyste zde piadil(a) hodnotu; tato hodnota nebude nikdy\n" -"exportovna tet stran. Potebujeme ji k implementaci \"pavuiny\n" -"dvry\"; nem to nic spolenho s (implicitn vytvoenou) \"pavuinou\n" -"certifikt\"." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Aby bylo mon vybudovat pavuinu dvry, mus GnuPG vdt, kterm klm\n" -"dvujete absolutn - obvykle to jsou ty kle, pro n mte pstup\n" -"k tajnm klm. Odpovzte \"ano\", abyste nastavili tyto kle\n" -"jako absolutn dvryhodn\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Pokud pesto chcete pout tento revokovan kl, odpovzte \"ano\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Pokud pesto chcete pout tento nedvryhodn kl, odpovzte \"ano\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Vlote identifiktor adresta, ktermu chcete poslat zprvu." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Vyberte algoritmus.\n" -"\n" -"DSA (nazvan tak DSS) je algoritmus digitlnho podpisu, kter me bt\n" -"pouit pouze pro podpisy. Je to doporuovan algoritmus, protoe oven\n" -"DSA podpis je mnohem rychlej ne v algoritmu ElGamal.\n" -"\n" -"Algoritmus ElGamal me bt pouvn jak pro podpisy tak pro ifrovn.\n" -"Standard OpenPGP rozliuje mezi dvma reimy tohoto algoritmu:\n" -"pouze ifrovn a ifrovn+podpis; v podstat je to stejn, ale nkolik\n" -"parametr mus bt vybrno specilnm zpsobem pro vytvoen bezpenho " -"kle\n" -"pro podpisy: tento program to um, ale nen vyadovno, aby i jin\n" -"implementace OpenPGP pracovaly v reimu podpis+ifrovn.\n" -"\n" -"Prvn (primrn) kl mus bt vdy kl, kter je schopn podepisovat;\n" -"to je dvod, pro v tomto menu nen k dispozi kl algoritmu ElGamal\n" -"urn pouze pro ifrovn." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Akoli jsou tyto kle definovny v RFC2440, nejsou doporuovny,\n" -"protoe nejsou podporovny vemi programy a podpisy jimi vytvoen\n" -"jsou znan velk a pro oven velmi pomal." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Vlote dlku kle" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Odpovzte \"ano\" nebo \"ne\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Vlote poadovanou hodnotu tak, jak je uvedeno v pkazovm dku.\n" -"Je mon vloit datum ve formtu ISO (RRRR-MM-DD), ale nedostanete\n" -"sprvnou chybovou hlku - msto toho systm zkus interpretovat\n" -"zadanou hodnotu jako interval." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Vlote jmno dritele kle" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "prosm, vlote e-mailovou adresu (nepovinn, ale velmi doporuovan)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Prosm, vlote nepovinn koment" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N pro zmnu nzvu.\n" -"C pro zmnu komente.\n" -"E pro zmnu e-mailov adresy.\n" -"O pro pokraovn generovn kle.\n" -"Q pro ukonen generovn kle." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Jestlie chcete generovat podkl, odpovzte \"ano\" (nebo jen \"a\")." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Ne podepete id uivatele, mli byste nejprve ovit, zda kl\n" -"pat osob, jej jmno je uvedeno v identifiktoru uivatele.\n" -"Je velmi uiten, kdy ostatn vd, jak dsledn jste provedl(a)\n" -"takov oven.\n" -"\n" -"\"0\" znamen, e neuvdte, jak dsledn jste pravost kle ovil(a) \n" -"\n" -"\"1\" znamen, e vte tomu, e kl pat osob, kter je uvedena,\n" -" v uivatelskm ID, ale nemohl jste nebo jste neprovil tuto " -"skutenost.\n" -" To je uiten pro \"osobn\" verifikaci, kdy podepisujete kle, " -"kter\n" -" pouvaj pseudonym uivatele.\n" -"\n" -"\"2\" znamen, e jste sten ovil pravost kle. Nap. jste ovil\n" -" fingerprint kle a zkontroloval identifiktor uivatele\n" -" uveden na kli s fotografickm id.\n" -"\n" -"\"3\" Znamen, e jste provedl velmi peliv oven pravosti kle.\n" -" To me napklad znamenat, e jste ovil fingerprint kle \n" -" jeho vlastnka osobn a dle jste pomoc obtn padlatelnho \n" -" dokumentu s fotografi (napklad pasu) ovil, e jmno majitele\n" -" kle se shoduje se jmnem uvedenm v uivatelskm ID a dle jste \n" -" ovil (vmnou elektronickch dopis), e elektronick adresa uveden \n" -" v ID uivatele pat majiteli kle.\n" -"\n" -"Prosm nezapomete, e pklady uveden pro rove 2 a 3 jsou *pouze*\n" -"pklady.\n" -"Je jen na Vaem rozhodnut co \"sten\" a \"peliv\" oven znamen\n" -"kdy budete podepisovat kle jinm uivatelm.\n" -"\n" -"Pokud nevte, jak je sprvn odpov, odpovzte \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "" -"Pokud chcete podepsat VECHNY identifiktory uivatel, odpovzte \"ano\"" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Pokud opravdu chcete smazat tento identifiktor uivatele, odpovzte \"ano" -"\".\n" -"Vechny certifikty budou tak ztraceny!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Odpovzte \"ano\", pokud chcete smazat podkl" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Toto je platn podpis kle; normln nechcete tento podpis smazat,\n" -"protoe me bt dleit pi vytven dvry kle nebo jinho kle\n" -"ceritifikovanho tmto klem." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Tento podpis neme bt oven, protoe nemte odpovdajc veejn kl.\n" -"Jeho smazn byste ml(a) odloit do doby, ne budete znt, kter kl\n" -"byl pouit, protoe tento podpisovac kl me vytvoit dvru\n" -"prostednictvm jinho ji certifikovanho kle." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "Podpis je neplatn. Je rozumn ho odstranit z Vaeho souboru kl." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Toto je podpis, kter ve identifiktor uivatele ke kli. Obvykle\n" -"nen dobr takov podpis odstranit. GnuPG neme tento kl nadle\n" -"pouvat. Udlejte to jenom v ppad, kdy je tento podpis kle\n" -"jm samm z njakho dvodu neplatn a kdy je k dipozici kl jin." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Zmnit pedvolby pro vechny uivatelsk ID (nebo pouze pro oznaen)\n" -"na aktuln seznam pedvoleb. asov raztka vech dotench podpis\n" -"kl jimi samotnmi budou posunuty o jednu vteinu dopedu.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Prosm, vlote heslo; toto je tajn vta \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Prosm, zopakujte posledn heslo, abyste si byl(a) jist(), co jste napsal" -"(a)." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Zadejte nzev souboru, ke ktermu se podpis vztahuje" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Pokud si pejete pepsn souboru, odpovzte \"ano\"" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Prosm, vlote nov nzev souboru. Pokud pouze stisknete RETURN, bude\n" -"pouit implicitn soubor (kter je ukzn v zvorkch)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Ml(a) byste specifikovat dvod certifikace. V zvislosti na kontextu\n" -"mte monost si vybrat ze seznamu:\n" -" \"Kl byl kompromitovn\"\n" -" Toto pouijte, pokud si myslte, e k Vaemu tajnmu kli zskaly\n" -" pstup neoprvnn osoby.\n" -" \"Kl je nahrazen\"\n" -" Toto pouijte, pokud jste tento kl nahradil(a) novjm klem.\n" -" \"Kl se ji nepouv\"\n" -" Toto pouijte, pokud tento kl ji nepouvte.\n" -" \"Identifiktor uivatele u nen platn\"\n" -" Toto pouijte, pokud by se identifiktor uivatele u neml pouvat;\n" -" normln se pouv k oznaen neplatn e-mailov adresy.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Pokud chcete, mete vloit text popisujc pvod vzniku tohoto revokanho\n" -"ceritifiktu. Prosm, strun. \n" -"Text kon przdnm dkem.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Pomoc nen k dispozici" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Pomoc nen dostupn pro '%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "chyba pi vytven souboru kl (keyring)`%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "soubor kl (keyring) `%s' vytvoen\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "selhalo obnoven vyrovnvac pamti kl: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "VAROVN: Existuj dva soubory s tajnmi informacemi.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s je beze zmny\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s je nov\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Prosm, opravte tento mon bezpenostn problm\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "kontroluji soubor kl (keyring) `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu kl ji zkontrolovno (%lu podpis)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu kl zkontrolovn (%lu podpis)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: soubor kl (keyring) vytvoen\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "muste znovu spustit GnuPG pro optovn naten souboru pedvoleb\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "zmna uivatelskch oprvnn `%s' selhala: %s\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Miniatura (fingerprint):" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingerprint:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|JMNO=HODNOTA|pout tento zpis dat" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "prvn znak jmna mus bt psmeno nebo podtrtko\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "teky ve jmn mus bt obklopeny jinmi znaky\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "VAROVN: Tento kl ji obsahuje fotografick ID.\n" -#~ " Pidn dal fotografie me zmst nkter verze PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Mli byste mt jen jeden fotografick ID na kli.\n" diff --git a/po/da.po b/po/da.po deleted file mode 100644 index 5f0cd4e59..000000000 --- a/po/da.po +++ /dev/null @@ -1,4565 +0,0 @@ -# Dansk oversttelse af: / Danish translation of: GnuPG -# Copyright (C) 2000 Free Software Foundation, Inc. -# Birger Langkjer , 2000. -# Kenneth Christiansen -- kenneth@ripen.dk, 2000. -# -- puh'ha denne er lang...n men det gr da fremad ;-) -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.0h\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2000-03-07 22:51+01:00\n" -"Last-Translator: Birger Langkjer \n" -"Language-Team: Danish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Advarsel: benytter ubeskyttet hukommelse!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "operation er ikke mulig uden beskyttet hukommelse indlst\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(du kan have brugt et forkert program til denne opgave)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ja" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "jJ" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "n" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "afslut" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "aA" - -#: util/errors.c:54 -msgid "general error" -msgstr "generel fejl" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "ukendt pakketype" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "ukendt version" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "ukendt offentlig nglealgoritme" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "ukendt sammenfatningsalgoritme" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "drlig offentlig ngle" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "drlig hemmelig ngle" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "drlig signatur" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "tjeksumsfejl" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "drlig kodestning" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "offentlig ngle ikke fundet" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "ukendt cifferalgoritme " - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "kan ikke bne ngleringen" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "ugyldig pakke" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "ugyldig rustning" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "ikke-eksisterende bruger id" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "hemmelig ngle ikke tilgngelig" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "forkert hemmelig ngle brugt" - -#: util/errors.c:72 -msgid "not supported" -msgstr "ikke understttet" - -#: util/errors.c:73 -msgid "bad key" -msgstr "drlig ngle" - -#: util/errors.c:74 -msgid "file read error" -msgstr "fillsningsfejl" - -#: util/errors.c:75 -msgid "file write error" -msgstr "filskrivningsfejl" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "ukendt kompressionsalgoritme" - -#: util/errors.c:77 -msgid "file open error" -msgstr "filbningsfejl" - -#: util/errors.c:78 -msgid "file create error" -msgstr "filoprettelsesfejl" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "ugyldig kodestning" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "uimplementeret offentlig nglealgoritme" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "uimplementeret cifferalgoritme" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "ukendt signaturklasse" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "tillidsdatabasefejl" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "drlig mpi" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "resursegrnse" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "ugyldig nglering" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "ugyldigt certifikat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "drlig bruger-id" - -#: util/errors.c:89 -msgid "file close error" -msgstr "fillukningsfejl" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "filomdbningsfejl" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "filsletningsfejl" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "uforventet data" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "tidsstempelkonflikt" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "uanvendelig offentlig nglealgoritme" - -#: util/errors.c:95 -msgid "file exists" -msgstr "fil eksisterer" - -#: util/errors.c:96 -msgid "weak key" -msgstr "svag ngle" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "ugyldigt argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "ugyldig URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "ikke-understttet URI" - -#: util/errors.c:100 -msgid "network error" -msgstr "netvrksfejl" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "ikke krypteret" - -#: util/errors.c:103 -msgid "not processed" -msgstr "ikke bearbejdet" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -#, fuzzy -msgid "unusable public key" -msgstr "drlig offentlig ngle" - -#: util/errors.c:106 -#, fuzzy -msgid "unusable secret key" -msgstr "drlig hemmelig ngle" - -#: util/errors.c:107 -#, fuzzy -msgid "keyserver error" -msgstr "generel fejl" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... dette er en fejl (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "du fandt en fejl ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "kan ikke bne '%s': %s\n" - -#: cipher/random.c:385 -#, fuzzy, c-format -msgid "can't stat `%s': %s\n" -msgstr "kan ikke bne '%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "" - -#: cipher/random.c:401 -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" - -#: cipher/random.c:409 -#, fuzzy, c-format -msgid "can't read `%s': %s\n" -msgstr "kan ikke bne '%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "" - -#: cipher/random.c:467 -#, fuzzy, c-format -msgid "can't create `%s': %s\n" -msgstr "kan ikke oprette %s: %s\n" - -#: cipher/random.c:474 -#, fuzzy, c-format -msgid "can't write `%s': %s\n" -msgstr "kan ikke bne '%s': %s\n" - -#: cipher/random.c:477 -#, fuzzy, c-format -msgid "can't close `%s': %s\n" -msgstr "kan ikke bne '%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "ADVARSEL: bruger usikker tilfldig-nummer-generator!!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Den tilfldige nummer generator er kun en \"kludge\" for at\n" -"lade den kre - det er ikke en strk RNG!\n" -"\n" -"BENYT IKKE DATA GENERERET AF DETTE PROGRAM!!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Ikke nok tilfldige byte tilgngelig. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Krver %d byte mere)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Kommandoer:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[filer]|opret en signatur" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[filer]|opret rentekst signatur" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "opret en separat signatur" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "kryptr data" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "kryptr kun med symmetriske cifre" - -#: g10/g10.c:315 -msgid "store only" -msgstr "gem kun" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "afkryptr data (standard)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "godkend en signatur" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "vis ngler" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "vis ngler og signaturer" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "tjek nglesignaturer" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "vis ngle og fingeraftryk" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "vis hemmelige ngler" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "generr et nyt nglepar" - -#: g10/g10.c:327 -#, fuzzy -msgid "remove keys from the public keyring" -msgstr "fjern ngle fra den offentlige nglering" - -#: g10/g10.c:329 -#, fuzzy -msgid "remove keys from the secret keyring" -msgstr "fjern ngle fra den hemmelige nglering" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "signr en ngle" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "signr en ngle lokalt" - -#: g10/g10.c:332 -#, fuzzy -msgid "sign a key non-revocably" -msgstr "signr en ngle lokalt" - -#: g10/g10.c:333 -#, fuzzy -msgid "sign a key locally and non-revocably" -msgstr "signr en ngle lokalt" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "signr eller redigr en ngle" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "Generr en annullrbar certifikat" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "eksportr ngler" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "eksportr ngler til en ngletjener" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importr ngler fra en ngleserver" - -#: g10/g10.c:341 -#, fuzzy -msgid "search for keys on a key server" -msgstr "eksportr ngler til en ngletjener" - -#: g10/g10.c:343 -#, fuzzy -msgid "update all keys from a keyserver" -msgstr "importr ngler fra en ngleserver" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importr/fusionr ngler" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "vis kun pakkesekvensen" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "eksportr ejertillidsvrdierne" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importr ejertillidsvrdierne" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "opdatr tillidsdatabasen" - -#: g10/g10.c:357 -#, fuzzy -msgid "unattended trust database update" -msgstr "opdatr tillidsdatabasen" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "reparr en delagt tillidsdatabase" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "De-beskydt en fil el. stdin" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Beskydt en fil el. stdin" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [filer]|print meddelelsesresum" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Indstillinger:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "opret ascii beskyttet uddata" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NAME|kryptr for NAME" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NAME|brug NAME som standard modtager" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "brug standard nglen som standard modtager" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "brug denne bruger-id til at signere eller dekryptere" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|st kompresningsniveau N (0 = slet fra)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "brug kanonisk tekstmodus" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "brug som uddatafil" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "meddelsom" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "vr mere stille" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "brug overhovedet ikke terminalen" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "tving v3 signaturer" - -#: g10/g10.c:397 -#, fuzzy -msgid "do not force v3 signatures" -msgstr "tving v3 signaturer" - -#: g10/g10.c:398 -#, fuzzy -msgid "force v4 key signatures" -msgstr "tving v3 signaturer" - -#: g10/g10.c:399 -#, fuzzy -msgid "do not force v4 key signatures" -msgstr "tving v3 signaturer" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "brug altid en MDC for kryptering" - -#: g10/g10.c:402 -#, fuzzy -msgid "never use a MDC for encryption" -msgstr "brug altid en MDC for kryptering" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "lav ingen ndringer" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "krselsmodus: sprg aldrig" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "forvent ja til de fleste sprgsml" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "forvent nej til de fleste sprgsml" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "tilfj denne nglering til ngleringslisten" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "tilfj denne hemmeligenglering til listen" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NAME|brug NAME som standard hemmeligngle" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|brug denne ngletjener til at sl ngler op" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAME|st terminal karakterst til NAME" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "ls indstillinger fra fil" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|skriv statusinfo til denne FD" - -#: g10/g10.c:427 -#, fuzzy -msgid "|[file]|write status info to file" -msgstr "|FD|skriv statusinfo til denne FD" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FILE|indls udvidelsesmodul FILE" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emulr modusen beskrevet i RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "st alle pakker, cifre og resum flag til OpenPGP standard" - -#: g10/g10.c:443 -#, fuzzy -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "st alle pakker, cifre og resum flag til OpenPGP standard" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|brug pasfrasemodus N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NAME|brug meddelelses resumalgoritme NAME for pasfrase" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NAME|brug cifrealgoritme NAME for pasfrase" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAME|brug cifferalgoritme NAME" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAME|brug meddelelsesresum algoritme NAME" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|brug kompresalgoritme N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Eksempler:\n" -"\n" -" -se -r Mikael [fil] signr og kryptr for bruger Mikael\n" -" --clearsign [fil] lav en ren tekstsignatur\n" -" --detach-sign [fil] lav en separat signatur\n" -" --list-keys [navne] vis ngler\n" -" --fingerprint [navne] vis fingeraftryk\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Rapportr venligst fejl til .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Brug: gpg [flag] [filer] (-h for hjlp)" - -# Skal alt dette oversttes eller er det flagene? -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Syntaks: gpg [flag] [filer]\n" -"sign, check, encrypt eller decrypt\n" -"standard operation afhnger af inddata\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Understttede algoritmer:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "brug: gpg [flag] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "konfliktende kommandoer\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTITS: ingen standard alternativfil '%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTITS: ingen standard alternativfil '%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "alternativfil`%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "lser indstillinger fra `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s er ikke et gyldigt tegnst\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "ADVARSEL: '%s' er en tom fil\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "ugyldig rustning" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "ADVARSEL: '%s' er en tom fil\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "ugyldig nglering" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTITS: %s er ikke til normal brug!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s ikke tilladt med %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s er meningsls sammen med %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "valgte cifferalgoritme er ugyldig\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "valgte resumalgoritme er ugyldig\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "valgte resumalgoritme er ugyldig\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTE: simpel S2K modus (0) frardes p det skarpeste\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "ugyldig S2K modus; skal vre 0, 1 el. 3\n" - -#: g10/g10.c:1862 -#, fuzzy -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "ugyldig S2K modus; skal vre 0, 1 el. 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "vis prferencer" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "vis prferencer" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "vis prferencer" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "vis prferencer" - -# er det klogt at overstte TrustDB? -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "kunne ikke initialisere TillidsDB: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [filnavn (som gemmes)]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [filnavn]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [filnavn (som krypteres)]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [filnavn (som signeres)]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [filnavn]" - -#: g10/g10.c:2056 -#, fuzzy -msgid "--sign --symmetric [filename]" -msgstr "--symmetric [filnavn]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [filnavn]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [filnavn (som dekrypteres)]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key bruger-id" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key bruger-id" - -#: g10/g10.c:2110 -#, fuzzy -msgid "--nrsign-key user-id" -msgstr "--sign-key bruger-id" - -#: g10/g10.c:2118 -#, fuzzy -msgid "--nrlsign-key user-id" -msgstr "--sign-key bruger-id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key bruger-id [kommandoer]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "kan ikke bne %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [bruger-id] [nglering]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "fjernelse af beskyttelse fejlede: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "pkldning af beskyttelse fejlede: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "ugyldig hash-algoritme `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[filnavn]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "G til sagen og skriv meddelelsen ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "kan ikke bne `%s'\n" - -#: g10/g10.c:2691 -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "en notationsvrdi m ikke bruge nogen kontroltegn\n" - -#: g10/g10.c:2737 -#, fuzzy -msgid "the given certification policy URL is invalid\n" -msgstr "den givne politik-URL er ugyldig\n" - -#: g10/g10.c:2739 -#, fuzzy -msgid "the given signature policy URL is invalid\n" -msgstr "den givne politik-URL er ugyldig\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "panser: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "ugyldigt panserhoved: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "panserhoved: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "" - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "uforventet beskyttelse:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "ugyldigt radix64 tegn %02x udeladt\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "for tidlig eof (ingen CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "for tidlig eof (i CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "drlig CRC\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "CRC fejl; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "for tidlig eof (i trailer)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "fejl i trailerlinie\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "ingen gyldig OpenPGP data fundet.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "ugyldigt panser: linie lngere end %d tegn\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "quoted printable-tegn i panser - mske pga. en fejlbehftet MTA\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "" - -#: g10/pkclist.c:63 -#, fuzzy -msgid "Key is superseded" -msgstr "Nglen er beskyttet.\n" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "rev- forkert ngletilbagekald\n" - -#: g10/pkclist.c:90 -msgid "revocation comment: " -msgstr "" - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "" - -#: g10/pkclist.c:258 -#, fuzzy, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Ingen tillidsvrdi tildelt til %lu:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr "" - -#: g10/pkclist.c:274 -#, fuzzy, c-format -msgid " %d = I do NOT trust\n" -msgstr "%08lX: Vi stoler IKKE p denne ngle\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr "" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr "" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr "" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr "" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = tilbage til hovedmenu\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr "" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = afslut\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Dit valg? " - -#: g10/pkclist.c:316 -#, fuzzy -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Vil du virkelig gerne gre dette?" - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "ngle %08lX: ngle er blevet annulleret!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Brug denne ngle alligevel? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "ngle %08lX: underngle er blevet annulleret!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: ngle er udlbet\n" - -#: g10/pkclist.c:448 -#, fuzzy, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr " Intet tyder p at denne signatur tilhrer ejeren.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Vi stoler IKKE p denne ngle\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Denne ngle tilhrer sikkert ejeren\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Denne ngle tilhrer os\n" - -#: g10/pkclist.c:513 -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "ADVARSEL: Bruger ngle uden tillid!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "ADVARSEL: Denne ngle er blevet annulleret af dets ejer!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Dette kan betyde at signaturen er forfalsket.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "ADVARSEL: Denne underngle er blevet tilbagekaldt af dens ejer!\n" - -#: g10/pkclist.c:580 -#, fuzzy -msgid "Note: This key has been disabled.\n" -msgstr "Bemrk: Denne ngle er forldet!\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Bemrk: Denne ngle er forldet!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " Intet tyder p at denne signatur tilhrer ejeren.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "ADVARSEL: Vi tror IKKE p denne ngle!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Signaturen er formentlig FORFALSKET.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Det er ikke sikkert at signaturen tilhrer ejeren.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: udelod: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: udelod: offentlig ngle er allerede tilstede\n" - -#: g10/pkclist.c:811 -#, fuzzy -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Du angav ikke en bruger-id. (du kan bruge \"-r\")\n" -"\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Ingen sdan bruger-id.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "udeladt: offentlig ngle er allerede valgt som standard modtager\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Offentlig ngle er slet fra.\n" - -#: g10/pkclist.c:870 -#, fuzzy -msgid "skipped: public key already set\n" -msgstr "%s: udelod: offentlig ngle er allerede tilstede\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "ukendt standard modtager '%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: udelod: offentligngle er slet fra\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "ingen gyldige adresser\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "" - -#: g10/keygen.c:194 -#, fuzzy, c-format -msgid "too many `%c' preferences\n" -msgstr "vis prferencer" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "Ugyldige bogstaver i navn\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "skriver selvsignatur\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "skriver selvsignatur\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, fuzzy, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "nsket nglestrrelse er %u bit\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, fuzzy, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "rundet op til %u bit\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Vlg venligst hvilken slags ngle du vil have:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA og ElGamal (standard)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (signr kun)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (kryptr kun)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (signr og kryptr)\n" - -#: g10/keygen.c:949 -#, fuzzy, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) DSA (signr kun)\n" - -#: g10/keygen.c:951 -#, fuzzy, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) ElGamal (kryptr kun)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (signr og kryptr)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Dit valg? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Ugyldigt valg.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Hvilken nglestrrelse nsker du? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA tillader kun nglestrrelser fra 512 til 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Er du sikker p at de vil benytte denne nglestrrelse? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "nsket nglestrrelse er %u bit\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "rundet op til %u bit\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Ngle er gyldig for? (0) " - -#: g10/keygen.c:1150 -#, fuzzy -msgid "Signature is valid for? (0) " -msgstr "Ngle er gyldig for? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "ugyldig vrdi\n" - -#: g10/keygen.c:1160 -#, fuzzy, c-format -msgid "%s does not expire at all\n" -msgstr "Nglen udlber aldrig\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, fuzzy, c-format -msgid "%s expires at %s\n" -msgstr "Ngle udlber d. %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" - -# virker j automatisk istedetfor y? -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Er dette korrekt (j/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Rigtige navn: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Ugyldige bogstaver i navn\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Navn m ikke starte med et tal\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Navn skal vre mindst 5 bogstaver langt\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Epostadresse: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Ikke en gyldig epostadresse\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Kommentar: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Ugyldigt tegn i kommentar\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Du bruger '%s' tegnsttet.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Du valgte denne BRUGER-ID:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoQq" - -#: g10/keygen.c:1326 -#, fuzzy -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "ndr (N)avn, (K)ommentar, (E)post eller (O)kay/(Q)vit? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "ndr (N)avn, (K)ommentar, (E)post eller (O)kay/(Q)vit? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Du skal bruge en kodestning til at beskytte din hemmelige ngle.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -#, fuzzy -msgid "passphrase not correctly repeated; try again" -msgstr "kodestningen blev ikke ordentlig gentaget; prv igen.\n" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSA nglepar vil have 1024 bit.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Ngleoprettelse annulleret.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, fuzzy, c-format -msgid "writing public key to `%s'\n" -msgstr "skriver offentligt certifikat til '%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, fuzzy, c-format -msgid "writing secret key to `%s'\n" -msgstr "skriver hemmeligt certifikat til '%s'\n" - -#: g10/keygen.c:2205 -#, fuzzy, c-format -msgid "no writable public keyring found: %s\n" -msgstr "ngle %08lX: offentlig ngle ikke fundet: %s\n" - -#: g10/keygen.c:2211 -#, fuzzy, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "skriver hemmeligt certifikat til '%s'\n" - -#: g10/keygen.c:2225 -#, fuzzy, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "fejl ved skrivning af nglering `%s': %s\n" - -#: g10/keygen.c:2232 -#, fuzzy, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "fejl ved skrivning af nglering `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "offentlig og hemmelig ngle oprettet og signeret.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Vil du virkelig oprette?" - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: kan ikke bne: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "fejl ved oprettelse af kodestning: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: ADVARSEL: tom fil\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lser fra '%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s krypteret for: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, fuzzy, c-format -msgid "key `%s' not found: %s\n" -msgstr "%s: bruger ikke fundet: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, fuzzy, c-format -msgid "error reading keyblock: %s\n" -msgstr "fejl ved lsning af '%s': %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/export.c:238 -#, fuzzy, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/export.c:246 -#, fuzzy, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "ADVARSEL: intet blev eksporteret\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -#, fuzzy -msgid "[User id not found]" -msgstr "[bruger ikke fundet]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "bruger sekundr ngle %08lX istedetfor primr ngle %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "sprang over blok af typen %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu ngler behandlet indtil nu\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "fejl ved lsning af '%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Totalt antal behandlede: %lu\n" - -#: g10/import.c:286 -#, fuzzy, c-format -msgid " skipped new keys: %lu\n" -msgstr " nye underngler: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr "" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importerede: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " undrede: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nye bruger-id'er: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nye underngler: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nye signaturer: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " nye ngletilbagekald: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " hemmelige ngler lst: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "hemmelige ngler import: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "hemmelige ngler undre: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importerede: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "ngle %08lX: ingen bruger-id\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "ngle %08lX: underngle er blevet annulleret!\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "ngle %08lX: ingen gyldige bruger-id'er\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "ngle %08lX: ingen gyldige bruger-id'er\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "ngle %08lX: offentlig ngle ikke fundet: %s\n" - -#: g10/import.c:636 -#, fuzzy, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/import.c:646 -#, fuzzy, c-format -msgid "no writable keyring found: %s\n" -msgstr "fejl ved skrivning af nglering `%s': %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "skriver til `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "fejl ved skrivning af nglering `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "ngle %08lX: stemmer ikke med vores kopi\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "ngle %08lX: kan ikke lokalisere original ngleblok: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "ngle %08lX: kan ikke lse original ngleblok: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "ngle %08lX: ingen bruger-id\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "ngle %08lX: ingen bruger-id\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "ngle %08lX: ingen bruger-id\n" - -#: g10/import.c:844 -#, fuzzy, c-format -msgid "no default secret keyring: %s\n" -msgstr "ingen standard offentlig nglering\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "Generr en annullrbar certifikat" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "ngle %08lX: offentlig ngle ikke fundet: %s\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "ngle %08lX: ingen gyldige bruger-id'er\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "ngle %08lX: underngle er blevet annulleret!\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "ngle %08lX: ingen gyldige bruger-id'er\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/import.c:1491 -#, fuzzy, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[selv-signatur]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 drlig signature\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d drlige signaturer\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Nglen er beskyttet.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Er du sikker p at de vil benytte denne nglestrrelse? " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "ADVARSEL: '%s' er en tom fil\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "" - -#: g10/keyedit.c:478 -#, fuzzy -msgid "This key has expired!" -msgstr "Bemrk: Denne ngle er forldet!\n" - -#: g10/keyedit.c:498 -#, fuzzy, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Denne ngle er ikke beskyttet.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "" - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr "" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr "" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr "" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr "" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "skriver selvsignatur\n" - -#: g10/keyedit.c:608 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" - -#: g10/keyedit.c:613 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Vil du gerne signere? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "signering fejlede: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Denne ngle er ikke beskyttet.\n" - -#: g10/keyedit.c:748 -#, fuzzy -msgid "Secret parts of primary key are not available.\n" -msgstr "hemmelig ngle ikke tilgngelig" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Nglen er beskyttet.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Kan ikke redigere denne ngle: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Vil du virkelig gerne gre dette?" - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "afslut denne menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "a" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "gem" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "gem og afslut" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "hjlp" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "vis denne hjlp" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "vis fingeraftryk" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "vis" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "vis ngler og bruger-id'er" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "ngle" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "vlg sekundr ngle N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "tjek" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "vis signaturer" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "signr" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "signr nglen" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsignr" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "signr nglen lokalt" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "nrsign" -msgstr "signr" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "sign the key non-revocably" -msgstr "signr nglen lokalt" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "nrlsign" -msgstr "signr" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "sign the key locally and non-revocably" -msgstr "signr nglen lokalt" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "aflus" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "tilfj-bid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "tilfj bruger-id" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "" - -#: g10/keyedit.c:920 -#, fuzzy -msgid "add a photo ID" -msgstr "tilfj bruger-id" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "sletbid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "slet bruger id" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "tilfj ngle" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "tilfj sekundr ngle" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "sletngle" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "slet sekundr ngle" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "tilfj ngle" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "tilfj sekundr ngle" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "sletsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "slet signaturer" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "udlb" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "ndr udlbsdatoen" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "skift" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "skift imellem hemmelig og offentlig ngle visning" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "s" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "prf" - -#: g10/keyedit.c:933 -#, fuzzy -msgid "list preferences (expert)" -msgstr "vis prferencer" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "showpref" -msgstr "visprf" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "list preferences (verbose)" -msgstr "vis prferencer" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "setpref" -msgstr "prf" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "set preference list" -msgstr "vis prferencer" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updpref" -msgstr "prf" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updated preferences" -msgstr "vis prferencer" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "kodeord" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "ndr kodestningen" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "betro" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "slfra" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "sl ngle fra" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "sltil" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "sl ngle til" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "" - -#: g10/keyedit.c:1000 -#, fuzzy, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "fejl ved lsning af '%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "" - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "Nglen er beskyttet.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "" - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "" - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "" - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "" - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "" - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "" - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "" - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Gem ndringer? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Afslut uden at gemme? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "ADVARSEL: Denne ngle er blevet annulleret af dets ejer!\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr "" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "" - -#: g10/keyedit.c:1802 -#, fuzzy, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! underngle er blevet annulleret! %s\n" - -#: g10/keyedit.c:1805 -#, fuzzy -msgid "rev- faked revocation found\n" -msgstr "rev- forkert ngletilbagekald\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Er du sikker p at de vil benytte denne nglestrrelse? " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Slettede %d signatur.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Indtast nglens strrelse" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "" - -#: g10/keyedit.c:2546 -#, fuzzy -msgid "Please select exactly one user ID.\n" -msgstr "Vlg venligst hvilken slags ngle du vil have:\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "ngle %08lX: ingen gyldige bruger-id'er\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Ingen bruger-id med indeks %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Ingen sekundr ngle med indeks %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "bruger-id: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "Denne ngle er ikke beskyttet.\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Er du sikker p at de vil benytte denne nglestrrelse? " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Generr en annullrbar certifikat" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr "" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr "" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr "" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Generr en annullrbar certifikat" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "%s signatur fra: %s\n" - -#: g10/keylist.c:93 -#, fuzzy -msgid "Signature policy: " -msgstr "%s signatur fra: %s\n" - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "" - -#: g10/keylist.c:127 -msgid "Critical signature notation: " -msgstr "" - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "" - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, fuzzy, c-format -msgid " [expires: %s]" -msgstr "Ngle udlber d. %s\n" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "vis ngle og fingeraftryk" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingeraftryk:" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Fingeraftryk:" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingeraftryk:" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -#, fuzzy -msgid " Key fingerprint =" -msgstr " Fingeraftryk:" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "ugyldig hash-algoritme `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, fuzzy, c-format -msgid "assuming %s encrypted data\n" -msgstr "kryptr data" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "" - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Politik: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -#, fuzzy -msgid "can't handle these multiple signatures\n" -msgstr "opret en separat signatur" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "DRLIG signatur fra \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -#, fuzzy -msgid "Expired signature from \"" -msgstr "God signatur fra \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "God signatur fra \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Kan ikke tjekke signatur: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -#, fuzzy -msgid "not a detached signature\n" -msgstr "opret en separat signatur" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "gammeldags (PGP 2.x) signatur\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "kan ikke sl core-dump fra: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "ADVARSEL: '%s' er en tom fil\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "ADVARSEL: '%s' er en tom fil\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "" - -#: g10/passphrase.c:511 -#, fuzzy, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "valgte cifferalgoritme %d er ugyldig\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, fuzzy, c-format -msgid "can't connect to `%s': %s\n" -msgstr "kan ikke bne '%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (hovedngle-ID %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" - -#: g10/passphrase.c:662 -#, fuzzy -msgid "Enter passphrase\n" -msgstr "Indtast kodestning: " - -#: g10/passphrase.c:664 -#, fuzzy -msgid "Repeat passphrase\n" -msgstr "Gentag kodestning: " - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Indtast kodestning: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Gentag kodestning: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" - -#: g10/plaintext.c:108 -#, fuzzy, c-format -msgid "error creating `%s': %s\n" -msgstr "fejl ved lsning af '%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "" - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lser stdin ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "" - -#: g10/pubkey-enc.c:178 -#, fuzzy, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "valgte cifferalgoritme %d er ugyldig\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "ngle %08lX: ngle er blevet annulleret!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "importr ngler fra en ngleserver: %s\n" - -#: g10/hkp.c:96 -#, fuzzy, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "importr ngler fra en ngleserver: %s\n" - -#: g10/hkp.c:175 -#, fuzzy, c-format -msgid "error sending to `%s': %s\n" -msgstr "fejl ved lsning af '%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "" - -#: g10/hkp.c:565 -#, fuzzy, c-format -msgid "can't search keyserver: %s\n" -msgstr "importr ngler fra en ngleserver: %s\n" - -#: g10/seckey-cert.c:53 -#, fuzzy -msgid "secret key parts are not available\n" -msgstr "hemmelig ngle ikke tilgngelig" - -#: g10/seckey-cert.c:59 -#, fuzzy, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "valgte cifferalgoritme %d er ugyldig\n" - -#: g10/seckey-cert.c:224 -#, fuzzy -msgid "Invalid passphrase; please try again" -msgstr "ugyldig kodestning" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "ngle %08lX: offentlig ngle importeret\n" - -#: g10/sig-check.c:234 -#, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" - -#: g10/sig-check.c:236 -#, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "" - -#: g10/sig-check.c:348 -#, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:303 -#, fuzzy, c-format -msgid "checking created signature failed: %s\n" -msgstr "Kan ikke tjekke signatur: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s signatur fra: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "ADVARSEL: '%s' er en tom fil\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "kan ikke oprette %s: %s\n" - -#: g10/sign.c:690 -#, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "signerer:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, fuzzy, c-format -msgid "%s: can't make lock\n" -msgstr "%s: kan ikke bne: %s\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" - -#: g10/trustdb.c:200 -#, fuzzy, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "%s er ikke et gyldigt tegnst\n" - -#: g10/trustdb.c:235 -#, fuzzy, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "" - -#: g10/trustdb.c:290 -#, fuzzy, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "ngle %08lX: ikke en rfc2440 ngle - udeladt\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "" - -#: g10/trustdb.c:779 -#, fuzzy -msgid "checking the trustdb\n" -msgstr "|[NAMES]|tjek tillidsdatabasen" - -#: g10/trustdb.c:933 -#, fuzzy, c-format -msgid "public key %08lX not found: %s\n" -msgstr "offentlig ngle ikke fundet" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "" - -#: g10/skclist.c:168 -#, fuzzy -msgid "skipped: secret key already present\n" -msgstr "udelod: hemmelig ngle er allerede tilstede\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Fil `%s' eksisterer. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Overskriv (j/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: ukendt suffiks\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Indtast nyt filnavn" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "skriver til stdout\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "" - -#: g10/openfile.c:326 -#, c-format -msgid "new configuration file `%s' created\n" -msgstr "" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: kan ikke oprette mappe: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: mappe oprettet\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Slet denne ngle fra ngleringen? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "" - -#: g10/delkey.c:168 -#, fuzzy, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "fjernelse af beskyttelse fejlede: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "" - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Indtast nglens strrelse" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Svar \"ja\" eller \"nej\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "" - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Svar \"ja\" hvis det er ok at overskrive filen" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Indtast et nyt filnavn. Hvis du bare trykker RETUR vil det\n" -"forvalgte navn (som er vist i klammer) blive brugt." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Ingen hjlp tilgngelig" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Ingen hjlp tilgngelig for `%s'" - -#: g10/keydb.c:178 -#, fuzzy, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "fejl ved skrivning af nglering `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "" - -#: g10/keydb.c:575 -#, fuzzy, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "ingen standard offentlig nglering\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "" - -#: g10/keyring.c:1346 -#, fuzzy, c-format -msgid "checking keyring `%s'\n" -msgstr "fejl ved skrivning af nglering `%s': %s\n" - -#: g10/keyring.c:1377 -#, fuzzy, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu ngler behandlet indtil nu\n" - -#: g10/keyring.c:1388 -#, fuzzy, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "vis ngler og signaturer" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "" - -#~ msgid "Fingerprint:" -#~ msgstr "Fingeraftryk:" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingeraftryk:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAME=VALUE|brug denne notationsdata" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "frste bogstav af en notationsnavn skal vre et bogstave eller en " -#~ "understregning\n" - -#, fuzzy -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Er du sikker p at de vil benytte denne nglestrrelse? " - -#, fuzzy -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr "Er du sikker p at de vil benytte denne nglestrrelse? " - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Vil du gerne signere? " - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key bruger-id" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key bruger-id" - -#, fuzzy -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key bruger-id" - -#~ msgid "Enter the user ID: " -#~ msgstr "Indtast bruger-id: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "udeladt: offentlig ngle er allerede valgt med --encrypt-to\n" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "WARNING: This is a PGP2-style key\n" -#~ msgstr "ADVARSEL: '%s' er en tom fil\n" - -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#, fuzzy -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s er ikke et gyldigt tegnst\n" - -#, fuzzy -#~ msgid "%lu key(s) to refresh\n" -#~ msgstr "%lu ngler behandlet indtil nu\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "Ingen tillidsvrdier er ndret.\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "%08lX: ignen info til at udregne en tillidssandsynlighed\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: fejl ved undersgelse af ngle: %s\n" - -#~ msgid "Good certificate" -#~ msgstr "Godt certifikat" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "Vil du gerne oprette en underskrivnings- og krypteringsngle? " - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "certifikatlseproblem: %s\n" - -#~ msgid "can't lock keyring `%s': %s\n" -#~ msgstr "kan ikke lse nglering `%s': %s\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: bruger ikke fundet\n" - -#, fuzzy -#~ msgid "invalid" -#~ msgstr "ugyldig rustning" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "RSA ngle kan ikke bruges i denne version\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Ingen ngle for bruger-ID\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Ingen bruger-ID for ngle\n" - -#~ msgid "set debugging flags" -#~ msgstr "st aflusningsflag" - -#~ msgid "enable full debugging" -#~ msgstr "sl fuld fejltjekning til" - -#~ msgid "do not write comment packets" -#~ msgstr "skriv ikke kommentarpakker" - -#~ msgid "(default is 1)" -#~ msgstr "(standard er 1)" - -#~ msgid "(default is 3)" -#~ msgstr "(standard er 3)" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal i en v3 pakke\n" diff --git a/po/de.glo b/po/de.glo deleted file mode 100644 index 7e32f93ab..000000000 --- a/po/de.glo +++ /dev/null @@ -1,238 +0,0 @@ -# Glossary for GnuPG german translation -# Zusammenstellung der Liste: -# Copyright (C) 1998 Free Software Foundation, Inc. -# Walter Koch , 1998. -# -# This is just a textfile for your information. -# It will _not_ be read or processed automatically by any program -# -# 1. Die Begriffe ohne ein "<" oder ">" vor dem deutschen Wort -# stammen aus der Wortliste von Walter Koch (Programmbersetzung). -# 2. Die nderungsvorschlge dazu mit einem "*" vor dem deutschen Wort -# stammen von Peter Gerwinski. -# 3. Die Begriffe mit einem "<" vor dem deutschen Wort sind so in der -# Bearbeitung von Herrn Goretzki verwendet worden -# 4. Die Begriffe mit einem ">" vor dem deutschen Wort sind -# alternative bersetzungsmglichkeiten, die von H.Martin angegeben -# wurden. -# 5. (*) Uneinheitlich verwendet -# 6. - Gefllt mir (Walter Koch) nicht so toll -# 7. Die erste genannte bersetzung ist die in de.po verwendete -# 8. # - Wurde in frherere de.po-Version verwendet - - -agent Agent -aka alias -algorithm Verfahren -anonymous ungenannter -argument > Argument -armor ASCII-Hlle -assigned zugewiesen -associate with a person zufllig, >gelegentlich >unregelmig -certificate Zertifikat -, (Urkunde) -character set Zeichensatz -check (verb) prfen, geprft -checking [sth.] [sth-]-berprfung -checksum Prfsumme -cipher algorithm Verschlsselungsverfahren -clearsign -clearsig header Klartextsignatur-Einleitung -created erzeugt -command Befehl -comment Bemerkung -compress algorithm Komprimierverfahren,*Komprimierungsverfahren ? -compressed komprimiert -compromised nicht mehr sicher -core dump core-dump-Datei -, (Speicherauszug?) -core function behandeln, lschen -depend on >sich verlassen auf,>angewiesen sein auf,>abhngen von -deprecated mibilligte -detached [sign] abgetrennte [Unterschrift] -determined attacker >zielbewusster,>entschlossener Angreifer -digest algorithm Hashmethode -direct [key sig] -"direct key" -disabled abgeschaltet -duplicated (adj.) doppelt -encrypted verschlsselte -enviorement variable Umgebungsvariable -eventually >schlielich, endlich Nicht: eventuell -expand -expiration date ist angemessen, manchmal: Gltigkeitsdauer, >Geltungsdauer -listed -locally (nur) fr diesen Rechner, #(nur) auf diesem Rechner -lookup - Suche -machine hufig: Computer, Rechner -main key Hauptschlssel -maintenance utility -Wartungs-Hilfsprogramm -making signatures >Unterschreiben Universalschlssel -, Generalschlssel -match Treffer -MDC Manipulation detection code (Siegel ?) -merge (to) >zusammenfhren, >vermischen ?? -message Botschaft -mode Modus, Methode * -move schieben, *verschieben -multiple signature Mehrfachunterschriften -NAI -network error Netzwerkfehler -non-revocably nicht-widerrufbar, unwiderruflich?? -note Hinweis -okay in Ordnung -Ooops Huch -OpenPGP -option Option -original ursprnglicher -overrides -ersetzt -ownertrust \"Owner trust\" *Vertrauenswrdigkeit des Besitzers -packet Paket -packet type Pakettyp -parse -zerlegen -passphrase Mantra -permission [file] Zugriffsrechte -Photo-ID Foto-ID -policy Richtlinie -policy URL Richtlinien-URL -preference items ???? -preferences Einstellungen *(die gesamten) Einstellungen -preferred bevorzugt -primary keys Hauptschlssel -problem [to do sth.] -Schwierigkeit -prompt (to) auch: >abfragen, >anfordern, >verlangen -protected -protection algorithm Schutzverfahren -pubkey algorithm Public-Key-Verfahren -public key ffentlicher Schssel -public key algorithm Public-Key-Verfahren -quit *(Programm) verlassen, beenden -radix64 radix64 -random Zufall -random bytes Zufallswerte -reason Grund (fr revocation) -[xyz] rebuild [xyz]-Neuaufbau, neu erzeugt -regular file normale Datei -response Antwort (Reaktion?) -retry ???? (Wiederholung?, Wiederaufnahme?) -returns gibt zurck / antwortet -reveal auch: anderen zeigen -revocation Widerruf <*>Rckruf -revocation certificate *Sicherheitsbedfnis(se), >Sicherheitsbedarf -self-signature Eigenbeglaubigung -sender Absender -sensitive - empfindlich -set [sth.] einstellen, festlegen -session Sitzung -show [an]zeigen, zeigen -sign user id User-ID beglaubigen * -signed unterschriebene -signature (files) Unterschrift * -signature (keys) Beglaubigung * -simple S2K mode ???? -skipped bergangen, bersprungen, ignoriert -so far bislang -specify >spezifizieren, Vertrauensniveaus?? *Vertrauensma? >Vertrauenswerte? -trying Versuch -type [message] [Botschaft] eintippen -ulimately [trust] uneingeschrnkt [vertrauen] -ultimate trust uneingeschrnktes Vertrauen -unable -unattended unbeaufsichtigt -unavailble -untrusted - nichtvertrauenswrdig, *nicht vertrauenswrdig -unusable unbrauchbar -update ndern, nderung >Aktualisieren, >Aktualisierung *auf den -URL (die) URL -[the] use [of] -User - User, *Benutzer-Schnittstelle -username Username, *besser authentisieren ?? So im -Wrterbuch der neuen Rechtschreibung) -validation -- >Authentisierung -verbose ausfhrlich -verify < berprfen -warning Warnung -weak key unsicherer Schlssel -writeable schreibbarer -wisely >klug, vernnftig(erweise), >gescheit; mglichst sinnvoll - diff --git a/po/de.po b/po/de.po deleted file mode 100644 index bde0643df..000000000 --- a/po/de.po +++ /dev/null @@ -1,5158 +0,0 @@ -# GnuPG german translation -# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Walter Koch , 1998, 1999, 2000, 2001 -msgid "" -msgstr "" -"Project-Id-Version: gnupg-1.0.7\n" -"POT-Creation-Date: 2002-10-18 11:37+0200\n" -"PO-Revision-Date: 2002-09-11 15:40+0200\n" -"Last-Translator: Walter Koch \n" -"Language-Team: German \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:90 -msgid "WARNING: using insecure memory!\n" -msgstr "WARNUNG: Sensible Daten knnten auf Platte ausgelagert werden.\n" - -#: util/secmem.c:91 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "siehe http://www.gnupg.org/de/faq.html fr weitere Informationen\n" - -# " Um dies zu vermeiden, kann das Programm suid(root) installiert werden.\n" -# " Bitte wenden Sie sich hierzu an den Systemadministrator.\n" -#: util/secmem.c:328 -msgid "operation is not possible without initialized secure memory\n" -msgstr "Vorgang ist ohne sicheren Hauptspeicher nicht mglich\n" - -#: util/secmem.c:329 -msgid "(you may have used the wrong program for this task)\n" -msgstr "" -"(mglicherweise haben Sie das falsche Programm fr diese Aufgabe benutzt)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ja" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "jJyY" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "nein" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "quit" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "Allgemeiner Fehler" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "Unbekannter Pakettyp" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "Unbekannte Version" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "Unbekanntes Public-Key-Verfahren" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "Unbekanntes Hashverfahren" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "Falscher ffentlicher Schssel" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "Falscher geheimer Schlssel" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "Falsche Unterschrift" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "Prfsummen-Fehler" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "Falsches Mantra" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "ffentlicher Schlssel nicht gefunden" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "Unbekanntes Verschlsselungsverfahren" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "Der Schlsselbund kann nicht geffnet werden" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "Ungltiges Paket" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "Ungltige ASCII-Hlle" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "Keine solche User-ID" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "Geheimer Schlssel ist nicht vorhanden" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "Falscher geheimer Schlssel benutzt" - -#: util/errors.c:72 -msgid "not supported" -msgstr "Wird nicht untersttzt" - -#: util/errors.c:73 -msgid "bad key" -msgstr "Falscher Schlssel" - -#: util/errors.c:74 -msgid "file read error" -msgstr "Dateilesefehler" - -#: util/errors.c:75 -msgid "file write error" -msgstr "Dateischreibfehler" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "Unbekanntes Komprimierverfahren" - -#: util/errors.c:77 -msgid "file open error" -msgstr "Fehler beim ffnen der Datei" - -#: util/errors.c:78 -msgid "file create error" -msgstr "Fehler beim Erzeugen der Datei" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "Ungltiges Mantra" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "nicht implementiertes ffentliches Schlsselverfahren" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "Verschlsselungsverfahren ist nicht implementiert" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "Unbekannte Unterschriftenklasse" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "Fehler in der Trust-DB" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "Falsche MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "festdefinierte Ressourcenobergrenze erreicht" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "Ungltiger Schlsselbund" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "Falsches Zertifikat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "Ungnstig aufgebaute User-ID" - -#: util/errors.c:89 -msgid "file close error" -msgstr "Fehler beim Schlieen der Datei" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "Fehler beim Umbenennen einer Datei" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "Fehler beim Lschen einer Datei" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "Unerwartete Daten" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "Zeitangaben differieren" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "Unbenutzbares ffentliches Schlsselverfahren" - -#: util/errors.c:95 -msgid "file exists" -msgstr "Datei existiert bereits" - -#: util/errors.c:96 -msgid "weak key" -msgstr "Unsicherer Schlssel" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "Ungltiges Argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "fehlerhafter URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "Nicht untersttzter URI" - -#: util/errors.c:100 -msgid "network error" -msgstr "Netzwerkfehler" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "nicht verschlsselt" - -#: util/errors.c:103 -msgid "not processed" -msgstr "nicht bearbeitet" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "unbrauchbarer ffentlicher Schssel" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "unbrauchbarer geheimer Schlssel" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "Schlsselserverfehler" - -#: util/logger.c:183 -msgid "ERROR: " -msgstr "" - -#: util/logger.c:186 -msgid "WARNING: " -msgstr "" - -#: util/logger.c:279 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... dies ist ein Bug (Programmfehler) (%s:%d:%s)\n" - -#: util/logger.c:285 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "Sie haben eine Bug (Programmfehler) gefunden ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "Kein Modul zum sammeln von Entropie vorhanden\n" - -#: cipher/random.c:381 g10/import.c:200 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "'%s' kann nicht geffnet werden: %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "Status von '%s' ist nicht feststellbar: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "'%s' ist keine normale Datei - sie bleibt unbeachtet\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "Hinweis: 'random_seed'-Datei ist leer\n" - -#: cipher/random.c:401 -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -"WARNUNG: Falsche Gre der 'random_seed'-Datei - sie wird nicht verwendet\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "'%s' ist unlesbar: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "Hinweis: 'random_seed'-Datei bleibt unverndert\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "'%s' kann nicht erzeugt werden: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "kann '%s' nicht schreiben: %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "kann '%s' nicht schliessen: %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "WARNUNG: Der Zufallsgenerator erzeugt keine echten Zufallszahlen!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Der Zufallsgenerator (RNG) ist lediglich ein \"kludge\", damit das\n" -"Programms berhaupt luft - es ist KEINESFALLS ein starker RNG!\n" -"\n" -"BENUTZEN SIE DIE DURCH DIESES PROGRAMM ERZEUGTEN DATEN NICHT!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Es sind nicht gengend Zufallswerte vorhanden. Bitte fhren Sie andere\n" -"Arbeiten durch, damit das Betriebssystem weitere Entropie sammeln kann!\n" -"(Es werden noch %d Byte bentigt.)\n" - -#: g10/g10.c:310 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Befehle:\n" -" " - -#: g10/g10.c:312 -msgid "|[file]|make a signature" -msgstr "|[Datei]|Eine Unterschrift erzeugen" - -#: g10/g10.c:313 -msgid "|[file]|make a clear text signature" -msgstr "|[Datei]|Eine Klartextunterschrift erzeugen" - -#: g10/g10.c:314 -msgid "make a detached signature" -msgstr "Eine abgetrennte Unterschrift erzeugen" - -#: g10/g10.c:315 -msgid "encrypt data" -msgstr "Daten verschlsseln" - -#: g10/g10.c:316 -msgid "|[files]|encrypt files" -msgstr "|[Dateien]|Dateien verschlsseln" - -#: g10/g10.c:317 -msgid "encryption only with symmetric cipher" -msgstr "Daten symmetrisch verschlsseln" - -#: g10/g10.c:318 -msgid "store only" -msgstr "Nur speichern" - -#: g10/g10.c:319 -msgid "decrypt data (default)" -msgstr "Daten entschlsseln (Voreinstellung)" - -#: g10/g10.c:320 -msgid "|[files]|decrypt files" -msgstr "|[Dateien]|Dateien entschlsseln" - -#: g10/g10.c:321 -msgid "verify a signature" -msgstr "Signatur prfen" - -#: g10/g10.c:323 -msgid "list keys" -msgstr "Liste der Schlssel" - -#: g10/g10.c:325 -msgid "list keys and signatures" -msgstr "Liste der Schlssel und ihrer Signaturen" - -#: g10/g10.c:326 -msgid "check key signatures" -msgstr "Signaturen der Schlssel prfen" - -#: g10/g10.c:327 -msgid "list keys and fingerprints" -msgstr "Liste der Schlssel und ihrer \"Fingerabdrcke\"" - -#: g10/g10.c:328 -msgid "list secret keys" -msgstr "Liste der geheimen Schlssel" - -#: g10/g10.c:329 -msgid "generate a new key pair" -msgstr "Ein neues Schlsselpaar erzeugen" - -#: g10/g10.c:330 -msgid "remove keys from the public keyring" -msgstr "Schlssel aus dem ff. Schlsselbund entfernen" - -#: g10/g10.c:332 -msgid "remove keys from the secret keyring" -msgstr "Schlssel aus dem geh. Schlsselbund entfernen" - -#: g10/g10.c:333 -msgid "sign a key" -msgstr "Schlssel signieren" - -#: g10/g10.c:334 -msgid "sign a key locally" -msgstr "Schlssel nur fr diesen Rechner signieren" - -#: g10/g10.c:335 -msgid "sign a key non-revocably" -msgstr "Schlssel nicht widerrufbar signieren" - -#: g10/g10.c:336 -msgid "sign a key locally and non-revocably" -msgstr "Schlssel nur fr diesen Rechner und nicht-widerrufbar signieren" - -#: g10/g10.c:337 -msgid "sign or edit a key" -msgstr "Unterschreiben oder bearbeiten eines Schl." - -#: g10/g10.c:338 -msgid "generate a revocation certificate" -msgstr "Ein Schlsselwiderruf-Zertifikat erzeugen" - -#: g10/g10.c:340 -msgid "export keys" -msgstr "Schlssel exportieren" - -#: g10/g10.c:341 -msgid "export keys to a key server" -msgstr "Schlssel zu einem Schl.server exportieren" - -#: g10/g10.c:342 -msgid "import keys from a key server" -msgstr "Schlssel von einem Schl.server importieren" - -#: g10/g10.c:344 -msgid "search for keys on a key server" -msgstr "Schlssel auf einem Schl.server suchen" - -#: g10/g10.c:346 -msgid "update all keys from a keyserver" -msgstr "alle Schlssel per Schl.server aktualisieren" - -#: g10/g10.c:350 -msgid "import/merge keys" -msgstr "Schlssel importieren/kombinieren" - -#: g10/g10.c:352 -msgid "list only the sequence of packets" -msgstr "Lediglich Struktur der Datenpakete anzeigen" - -#: g10/g10.c:354 -msgid "export the ownertrust values" -msgstr "Exportieren der \"Owner trust\"-Werte" - -#: g10/g10.c:356 -msgid "import ownertrust values" -msgstr "Importieren der \"Owner trust\"-Werte" - -#: g10/g10.c:358 -msgid "update the trust database" -msgstr "ndern der \"Trust\"-Datenbank" - -#: g10/g10.c:360 -msgid "unattended trust database update" -msgstr "unbeaufsichtigtes ndern der \"Trust\"-Datenbank" - -#: g10/g10.c:361 -msgid "fix a corrupted trust database" -msgstr "Reparieren einer beschdigten \"Trust\"-Datenb." - -#: g10/g10.c:362 -msgid "De-Armor a file or stdin" -msgstr "Datei oder stdin von der ASCII-Hlle befreien" - -#: g10/g10.c:364 -msgid "En-Armor a file or stdin" -msgstr "Datei oder stdin in eine ASCII-Hlle einpacken" - -#: g10/g10.c:366 -msgid "|algo [files]|print message digests" -msgstr "|algo [Dateien]|Message-Digests fr die Dateien ausgeben" - -#: g10/g10.c:370 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Optionen:\n" -" " - -#: g10/g10.c:372 -msgid "create ascii armored output" -msgstr "Ausgabe mit ASCII-Hlle versehen" - -#: g10/g10.c:374 -msgid "|NAME|encrypt for NAME" -msgstr "|NAME|Verschlsseln fr NAME" - -#: g10/g10.c:377 -msgid "|NAME|use NAME as default recipient" -msgstr "|NAME|NAME als voreingestellten Empfnger benutzen" - -#: g10/g10.c:379 -msgid "use the default key as default recipient" -msgstr "" -"Den Standardschlssel als voreingestellten\n" -"Empfnger benutzen" - -#: g10/g10.c:385 -msgid "use this user-id to sign or decrypt" -msgstr "Mit dieser User-ID signieren" - -#: g10/g10.c:386 -msgid "|N|set compress level N (0 disables)" -msgstr "Kompressionsstufe auf N setzen (0=keine)" - -#: g10/g10.c:388 -msgid "use canonical text mode" -msgstr "Textmodus benutzen" - -#: g10/g10.c:395 -msgid "use as output file" -msgstr "Als Ausgabedatei benutzen" - -#: g10/g10.c:396 -msgid "verbose" -msgstr "Detaillierte Informationen" - -#: g10/g10.c:397 -msgid "be somewhat more quiet" -msgstr "Etwas weniger Infos" - -#: g10/g10.c:398 -msgid "don't use the terminal at all" -msgstr "das Terminal gar nicht benutzen" - -#: g10/g10.c:399 -msgid "force v3 signatures" -msgstr "v3 Signaturen erzwingen" - -#: g10/g10.c:400 -msgid "do not force v3 signatures" -msgstr "v3 Signaturen nicht erzwingen" - -#: g10/g10.c:401 -msgid "force v4 key signatures" -msgstr "v4 Signaturen erzwingen" - -#: g10/g10.c:402 -msgid "do not force v4 key signatures" -msgstr "v4 Signaturen nicht erzwingen" - -#: g10/g10.c:403 -msgid "always use a MDC for encryption" -msgstr "Beim Verschlsseln ein Siegel (MDC) verwenden" - -#: g10/g10.c:405 -msgid "never use a MDC for encryption" -msgstr "Beim Verschlsseln niemals ein Siegel (MDC) verwenden" - -#: g10/g10.c:407 -msgid "do not make any changes" -msgstr "Keine wirklichen nderungen durchfhren" - -#: g10/g10.c:408 -msgid "prompt before overwriting" -msgstr "vor berschreiben nachfragen" - -#: g10/g10.c:409 -msgid "use the gpg-agent" -msgstr "den GPG-Agent verwenden" - -#: g10/g10.c:412 -msgid "batch mode: never ask" -msgstr "Stapelmodus: Keine Abfragen" - -#: g10/g10.c:413 -msgid "assume yes on most questions" -msgstr "\"Ja\" als Standardantwort annehmen" - -#: g10/g10.c:414 -msgid "assume no on most questions" -msgstr "\"Nein\" als Standardantwort annehmen" - -#: g10/g10.c:415 -msgid "add this keyring to the list of keyrings" -msgstr "Als ffentlichen Schlsselbund mitbenutzen" - -#: g10/g10.c:416 -msgid "add this secret keyring to the list" -msgstr "Als geheimen Schlsselbund mitbenutzen" - -#: g10/g10.c:417 -msgid "show which keyring a listed key is on" -msgstr "Anzeigen des Schlsselbundes, in dem ein Schlssel drin ist" - -#: g10/g10.c:418 -msgid "|NAME|use NAME as default secret key" -msgstr "|NAME|NAME als voreingestellten Schlssel benutzen" - -#: g10/g10.c:419 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|Schlssel bei diesem Server nachschlagen" - -#: g10/g10.c:423 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAME|Terminalzeichensatz NAME benutzen" - -#: g10/g10.c:424 -msgid "read options from file" -msgstr "Optionen aus der Datei lesen" - -#: g10/g10.c:428 -msgid "|FD|write status info to this FD" -msgstr "|FD|Statusinfo auf FD (Dateihandle) ausgeben" - -#: g10/g10.c:430 -msgid "|[file]|write status info to file" -msgstr "|[Datei]|Statusinfo in Datei schreiben" - -#: g10/g10.c:442 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID|diesem Schlssel uneingeschrnkt vertrauen" - -#: g10/g10.c:443 -msgid "|FILE|load extension module FILE" -msgstr "|DATEI|Erweiterungsmodul DATEI laden" - -#: g10/g10.c:444 -msgid "emulate the mode described in RFC1991" -msgstr "Den in RFC1991 beschriebenen Modus nachahmen" - -#: g10/g10.c:445 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"alle Paket-, Verschlsselungs- und\n" -"Hashoptionen auf OpenPGP-Verhalten einstellen" - -#: g10/g10.c:446 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"alle Paket-, Verschlsselungs- und\n" -"Hashoptionen auf PGP 2.X-Verhalten einstellen" - -#: g10/g10.c:452 -msgid "|N|use passphrase mode N" -msgstr "|N|Verwenden des Mantra-Modus N" - -#: g10/g10.c:454 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NAME|Hashverfahren NAME fr Mantras benutzen" - -#: g10/g10.c:456 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NAME|Verschl.verfahren NAME fr Mantras benutzen" - -#: g10/g10.c:458 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAME|Verschl.verfahren NAME benutzen" - -#: g10/g10.c:459 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAME|Hashverfahren NAME benutzen" - -#: g10/g10.c:461 -msgid "|N|use compress algorithm N" -msgstr "|N|Komprimierverfahren N benutzen" - -#: g10/g10.c:462 -msgid "throw keyid field of encrypted packets" -msgstr "Empfnger-ID verschlsselter Pakete entfernen" - -#: g10/g10.c:463 -msgid "Show Photo IDs" -msgstr "Foto-IDs anzeigen" - -#: g10/g10.c:464 -msgid "Don't show Photo IDs" -msgstr "Foto-IDs nicht anzeigen" - -#: g10/g10.c:465 -msgid "Set command line to view Photo IDs" -msgstr "Kommandozeilentext fr den Foto-Betrachter setzen" - -#: g10/g10.c:471 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Auf der \"man\"-Seite ist eine vollstndige Liste aller Kommandos und " -"Optionen)\n" - -#: g10/g10.c:474 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Beispiele:\n" -"\n" -" -se -r Bob [Datei] Signieren und verschlsseln fr Benutzer Bob\n" -" --clearsign [Datei] Eine Klartextsignatur erzeugen\n" -" --detach-sign [Datei] Eine abgetrennte Signatur erzeugen\n" -" --list-keys [Namen] Schlssel anzeigen\n" -" --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\n" - -#: g10/g10.c:628 -msgid "Please report bugs to .\n" -msgstr "" -"Berichte ber Programmfehler bitte in englisch an .\n" -"Sinn- oder Schreibfehler in den deutschen Texten bitte an .\n" - -#: g10/g10.c:632 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Aufruf: gpg [Optionen] [Dateien] (-h fr Hilfe)" - -#: g10/g10.c:635 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Aufruf: gpg [Optionen] [Dateien]\n" -"Signieren, prfen, verschlsseln, entschlsseln.\n" -"Die voreingestellte Operation ist abhngig von den Eingabedaten.\n" - -#: g10/g10.c:646 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Untersttzte Verfahren:\n" - -#: g10/g10.c:750 -msgid "usage: gpg [options] " -msgstr "Aufruf: gpg [Optionen] " - -#: g10/g10.c:818 -msgid "conflicting commands\n" -msgstr "Widersprchliche Befehle\n" - -#: g10/g10.c:836 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "Kein '='-Zeichen in der Gruppendefinition \"%s\"\n" - -#: g10/g10.c:996 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on homedir \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:999 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on configuration file \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1002 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on extension \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1008 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on homedir \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" - -#: g10/g10.c:1011 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on configuration file \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" - -#: g10/g10.c:1014 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on extension \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" - -#: g10/g10.c:1020 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on homedir \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1023 -#, fuzzy, c-format -msgid "" -"WARNING: unsafe enclosing directory ownership on configuration file \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1026 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on extension \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1032 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on homedir \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" - -#: g10/g10.c:1035 -#, fuzzy, c-format -msgid "" -"WARNING: unsafe enclosing directory permissions on configuration file \"%s" -"\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" - -#: g10/g10.c:1038 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on extension \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" - -#: g10/g10.c:1223 -#, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "Hinweis: Alte voreingestellte Optionendatei '%s' wurde ignoriert\n" - -#: g10/g10.c:1259 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "Hinweis: Keine voreingestellte Optionendatei '%s' vorhanden\n" - -#: g10/g10.c:1263 -#, c-format -msgid "option file `%s': %s\n" -msgstr "Optionendatei '%s': %s\n" - -#: g10/g10.c:1270 -#, c-format -msgid "reading options from `%s'\n" -msgstr "Optionen werden aus '%s' gelesen\n" - -#: g10/g10.c:1445 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" -"Verschlsselungserweiterung \"%s\" wurde wegen falscher Rechte nicht " -"geladen\n" - -#: g10/g10.c:1578 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s ist kein gltiger Zeichensatz.\n" - -#: g10/g10.c:1596 -msgid "could not parse keyserver URI\n" -msgstr "Schlsselserver-URI konnte nicht zerlegt werden\n" - -#: g10/g10.c:1605 -#, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s:%d: ungltige Import Option.\n" - -#: g10/g10.c:1608 -msgid "invalid import options\n" -msgstr "Ungltige Import Option\n" - -#: g10/g10.c:1615 -#, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s:%d: ungltige Export Option.\n" - -#: g10/g10.c:1618 -msgid "invalid export options\n" -msgstr "Ungltige export Option\n" - -#: g10/g10.c:1624 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "Der Ausfhrungspfad konnte nicht auf %s gesetzt werden.\n" - -#: g10/g10.c:1745 -msgid "WARNING: program may create a core file!\n" -msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" - -#: g10/g10.c:1749 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "WARNUNG: %s ersetzt %s\n" - -#: g10/g10.c:1756 g10/g10.c:1767 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "Hinweis: %s ist nicht fr den blichen Gebrauch gedacht!\n" - -#: g10/g10.c:1758 g10/g10.c:1777 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s kann nicht zusammen mit %s verwendet werden!\n" - -#: g10/g10.c:1761 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s zusammen mit %s ist nicht sinnvoll!\n" - -#: g10/g10.c:1787 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus knnen Sie nur abgetrennte oder Klartextunterschriften " -"machen\n" - -#: g10/g10.c:1793 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus knnen Sie nicht gleichzeitig unterschreiben und " -"verschlsseln\n" - -#: g10/g10.c:1799 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" -"Im --pgp2-Modus mssen Sie Dateien benutzen und knnen keine Pipes " -"verwenden.\n" - -#: g10/g10.c:1812 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" -"Verschlssen einer Botschaft bentigt im --pgp2-Modus die IDEA-" -"Verschlsselung\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1837 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "Diese Botschaft knnte fr %s unbrauchbar sein\n" - -#: g10/g10.c:1885 g10/g10.c:1903 -msgid "selected cipher algorithm is invalid\n" -msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" - -#: g10/g10.c:1891 g10/g10.c:1909 -msgid "selected digest algorithm is invalid\n" -msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" - -#: g10/g10.c:1897 -msgid "selected certification digest algorithm is invalid\n" -msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" - -#: g10/g10.c:1912 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "Das Komprimierverfahren mu im Bereich %d bis %d liegen\n" - -#: g10/g10.c:1914 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed mssen grer als 0 sein\n" - -#: g10/g10.c:1916 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed mssen grer als 1 sein\n" - -#: g10/g10.c:1918 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth mu im Bereich 1 bis 255 liegen\n" - -#: g10/g10.c:1921 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "Hinweis: Vom \"simple S2K\"-Modus (0) ist strikt abzuraten\n" - -#: g10/g10.c:1925 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "ungltiger \"simple S2K\"-Modus; Wert mu 0, 1 oder 3 sein\n" - -#: g10/g10.c:1929 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "ungltiger \"default-check-level\"; Wert mu 0, 1, 2 oder 3 sein\n" - -#: g10/g10.c:1935 -msgid "invalid default preferences\n" -msgstr "ungltige Standard Voreinstellungen\n" - -#: g10/g10.c:1943 -msgid "invalid personal cipher preferences\n" -msgstr "ungltige private Verschlsselungsvoreinstellungen\n" - -#: g10/g10.c:1947 -msgid "invalid personal digest preferences\n" -msgstr "ungltige private Hashvoreinstellungen\n" - -#: g10/g10.c:1951 -msgid "invalid personal compress preferences\n" -msgstr "ungltige private Komprimierungsvoreinstellungen\n" - -#: g10/g10.c:2044 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "Die Trust-DB kann nicht initialisiert werden: %s\n" - -#: g10/g10.c:2054 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" -"WARNUNG: Empfnger (-r) angegeben ohne Verwendung von Public-Key-Verfahren\n" - -#: g10/g10.c:2064 -msgid "--store [filename]" -msgstr "--store [Dateiname]" - -#: g10/g10.c:2071 -msgid "--symmetric [filename]" -msgstr "--symmetric [Dateiname]" - -#: g10/g10.c:2079 -msgid "--encrypt [filename]" -msgstr "--encrypt [Dateiname]" - -#: g10/g10.c:2096 -msgid "--sign [filename]" -msgstr "--sign [Dateiname]" - -#: g10/g10.c:2109 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [Dateiname]" - -#: g10/g10.c:2123 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [Dateiname]" - -#: g10/g10.c:2132 -msgid "--clearsign [filename]" -msgstr "--clearsign [Dateiname]" - -#: g10/g10.c:2150 -msgid "--decrypt [filename]" -msgstr "--decrypt [Dateiname]" - -#: g10/g10.c:2161 -msgid "--sign-key user-id" -msgstr "--sign-key User-ID" - -#: g10/g10.c:2169 -msgid "--lsign-key user-id" -msgstr "--lsign-key User-ID" - -#: g10/g10.c:2177 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key User-ID" - -#: g10/g10.c:2185 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key User-ID" - -#: g10/g10.c:2193 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key User-ID [Befehle]" - -#: g10/encode.c:416 g10/g10.c:2249 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "'%s' kann nicht geffnet werden: %s\n" - -#: g10/g10.c:2264 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [User-ID] [Schlsselbund]" - -#: g10/g10.c:2356 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "Entfernen der ASCII-Hlle ist fehlgeschlagen: %s\n" - -#: g10/g10.c:2364 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "Anbringen der ASCII-Hlle ist fehlgeschlagen: %s\n" - -#: g10/g10.c:2451 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "Ungltiges Hashverfahren '%s'\n" - -#: g10/g10.c:2537 -msgid "[filename]" -msgstr "[Dateiname]" - -#: g10/g10.c:2541 -msgid "Go ahead and type your message ...\n" -msgstr "Auf geht's - Botschaft eintippen ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2544 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "'%s' kann nicht geffnet werden\n" - -#: g10/g10.c:2758 -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"Ein \"notation\"-Name darf nur Buchstaben, Zahlen, Punkte oder Unterstriche " -"enthalten und mu mit einem '=' enden\n" - -#: g10/g10.c:2767 -msgid "a notation value must not use any control characters\n" -msgstr "Ein \"notation\"-Wert darf keine Kontrollzeichen verwenden\n" - -#: g10/g10.c:2804 -msgid "the given certification policy URL is invalid\n" -msgstr "Die angegebene Zertifikat-Richtlinien-URL ist ungltig\n" - -#: g10/g10.c:2806 -msgid "the given signature policy URL is invalid\n" -msgstr "Die angegebene Unterschriften-Richtlinien-URL ist ungltig\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "ASCII-Hlle: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "Ungltige ASCII-Hlle" - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "ASCII-Hlle: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "Ungltige Klartextsignatur-Einleitung\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "verschachtelte Klartextunterschriften\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "Ungltige mit Bindestrich \"escapte\" Zeile: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "Unerwartete ASCII-Hlle:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "Ungltiges \"radix64\" Zeichen %02x ignoriert\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "vorzeitiges Dateiende (keine Prfsumme)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "vorzeitiges Dateiende (innerhalb der Prfsumme)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "Falsch aufgebaute Prfsumme\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Prfsummenfehler; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "vorzeitiges Dateiende (im Nachsatz)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "Fehler in der Nachsatzzeile\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "Keine gltigen OpenPGP-Daten gefunden.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "ungltige ASCII-Hlle: Zeile ist lnger als %d Zeichen\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"\"quoted printable\" Zeichen in der ASCII-Hlle gefunden - mglicherweise\n" -" war ein fehlerhafter E-Mail-Transporter(\"MTA\") die Ursache\n" - -#: g10/pkclist.c:62 -msgid "No reason specified" -msgstr "Kein Grund angegeben" - -#: g10/pkclist.c:64 -msgid "Key is superseded" -msgstr "Schlssel ist berholt" - -#: g10/pkclist.c:66 -msgid "Key has been compromised" -msgstr "Hinweis: Dieser Schlssel ist nicht mehr sicher" - -#: g10/pkclist.c:68 -msgid "Key is no longer used" -msgstr "Schlssel wird nicht mehr benutzt" - -#: g10/pkclist.c:70 -msgid "User ID is no longer valid" -msgstr "User-ID ist nicht mehr gltig" - -#: g10/pkclist.c:74 -msgid "reason for revocation: " -msgstr "Grund fr Widerruf: " - -#: g10/pkclist.c:91 -msgid "revocation comment: " -msgstr "Widerruf-Bemerkung: " - -#. a string with valid answers -#: g10/pkclist.c:253 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:261 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Es ist kein \"trust value\" zugewiesen fr:\n" -"%4u%c/%08lX %s \"" - -#: g10/mainproc.c:1428 g10/pkclist.c:289 -msgid " aka \"" -msgstr " alias \"" - -#: g10/pkclist.c:299 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Bitte entscheiden Sie, in wieweit Sie diesem User zutrauen,\n" -"Schlssel anderer User korrekt zu prfen (durch Vergleich\n" -"mit Lichtbildausweisen, Vergleich der Fingerabdrcke aus\n" -"unterschiedlichen Quellen ...)?\n" -"\n" - -#: g10/pkclist.c:302 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Wei nicht so recht\n" - -#: g10/pkclist.c:303 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = Nein, ihm traue ich NICHT\n" - -#: g10/pkclist.c:304 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Ich vertraue ihm einigermaen\n" - -#: g10/pkclist.c:305 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Ich vertraue ihm vollstndig\n" - -#: g10/pkclist.c:307 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Ich vertraue ihm absolut\n" - -#. not yet implemented -#: g10/pkclist.c:310 -msgid " i = please show me more information\n" -msgstr " i = Bitte weitere Information anzeigen\n" - -#: g10/pkclist.c:313 -msgid " m = back to the main menu\n" -msgstr " m = Zurck zum Men\n" - -#: g10/pkclist.c:316 -msgid " s = skip this key\n" -msgstr " s = diesen Schlssel berSpringen\n" - -#: g10/pkclist.c:317 -msgid " q = quit\n" -msgstr " q = verlassen\n" - -#: g10/pkclist.c:324 -msgid "Your decision? " -msgstr "Ihre Auswahl? " - -#: g10/pkclist.c:345 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Mchten Sie diesem Schlssel wirklich uneingeschrnkt vertrauen? " - -#: g10/pkclist.c:359 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Zertifikate fhren zu einem letztlich vertrauenswrdigen Schlssel:\n" - -#: g10/pkclist.c:434 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "Schlssel %08lX: Schlssel wurde widerrufen\n" - -#: g10/pkclist.c:441 g10/pkclist.c:453 g10/pkclist.c:547 -msgid "Use this key anyway? " -msgstr "Diesen Schlssel trotzdem benutzen? " - -#: g10/pkclist.c:446 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "Schlssel %08lX: Unterschlssel wurde widerrufen\n" - -#: g10/pkclist.c:467 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: Schlssel ist verfallen!\n" - -#: g10/pkclist.c:477 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Es gibt keinen Hinweis, da die Signatur wirklich dem vorgeblichen " -"Besitzer gehrt.\n" - -#: g10/pkclist.c:483 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Wir haben KEIN Vertrauen zu diesem Schlssel!\n" - -#: g10/pkclist.c:489 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Es ist nicht sicher, da dieser Schlssel wirklich dem vorgeblichen\n" -"Besitzer gehrt, aber er wird trotzdem akzeptiert\n" - -#: g10/pkclist.c:495 -msgid "This key probably belongs to the owner\n" -msgstr "" -"Dieser Schlssel gehrt hchstwahrscheinlich dem angegebenen Besitzer\n" - -#: g10/pkclist.c:500 -msgid "This key belongs to us\n" -msgstr "" -"Dieser Schlssel gehrt uns (da wir nmlich den geheimen Schlssel dazu " -"haben)\n" - -#: g10/pkclist.c:542 -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Es ist NICHT sicher, da der Schlssel dem vorgeblichen Besitzer gehrt.\n" -"Wenn Sie *wirklich* wissen, was Sie tun, knnen Sie die nchste\n" -"Frage mit ja beantworten\n" - -#: g10/pkclist.c:556 g10/pkclist.c:578 -msgid "WARNING: Using untrusted key!\n" -msgstr "WARNUNG: Ein Schlssel ohne gesichertes Vertrauen wird benutzt!\n" - -#: g10/pkclist.c:597 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "WARNUNG: Dieser Schlssel wurde von seinem Besitzer widerrufen!\n" - -#: g10/pkclist.c:598 -msgid " This could mean that the signature is forgery.\n" -msgstr " Das knnte bedeuten, da die Signatur geflscht ist.\n" - -#: g10/pkclist.c:604 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "WARNUNG: Dieser Unterschlssel wurde von seinem Besitzer widerrufen!\n" - -#: g10/pkclist.c:609 -msgid "Note: This key has been disabled.\n" -msgstr "Hinweis: Dieser Schlssel wurde abgeschaltet.\n" - -#: g10/pkclist.c:614 -msgid "Note: This key has expired!\n" -msgstr "Hinweis: Dieser Schlssel ist verfallen!\n" - -#: g10/pkclist.c:625 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "WARNUNG: Dieser Schlssel trgt keine vertrauenswrdige Signatur!\n" - -#: g10/pkclist.c:627 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Es gibt keinen Hinweis, da die Signatur wirklich dem vorgeblichen " -"Besitzer gehrt.\n" - -#: g10/pkclist.c:635 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "WARNUNG: Wir haben KEIN Vertrauen zu diesem Schlssel!\n" - -#: g10/pkclist.c:636 -msgid " The signature is probably a FORGERY.\n" -msgstr " Die Signatur ist wahrscheinlich eine FLSCHUNG.\n" - -#: g10/pkclist.c:644 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"WARNUNG: Dieser Schlssel ist nicht durch hinreichend vertrauenswrdige " -"Signaturen zertifiziert!\n" - -#: g10/pkclist.c:646 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr "" -" Es ist nicht sicher, da die Signatur wirklich dem vorgeblichen " -"Besitzer gehrt.\n" - -#: g10/pkclist.c:799 g10/pkclist.c:823 g10/pkclist.c:975 g10/pkclist.c:1035 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: bersprungen: %s\n" - -#: g10/pkclist.c:809 g10/pkclist.c:1007 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: bersprungen: ffentlicher Schlssel bereits vorhanden\n" - -#: g10/pkclist.c:840 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Sie haben keine User-ID angegeben (Sie knnen die Option \"-r\" verwenden).\n" - -#: g10/pkclist.c:853 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Geben Sie die User-ID ein. Beenden mit einer leeren Zeile: " - -#: g10/pkclist.c:869 -msgid "No such user ID.\n" -msgstr "Keine solche User-ID vorhanden.\n" - -#: g10/pkclist.c:874 g10/pkclist.c:950 -msgid "skipped: public key already set as default recipient\n" -msgstr "" -"bersprungen: ffentlicher Schlssel bereits als Standardempfnger gesetzt\n" - -#: g10/pkclist.c:892 -msgid "Public key is disabled.\n" -msgstr "ffentlicher Schlssel ist abgeschaltet.\n" - -#: g10/pkclist.c:899 -msgid "skipped: public key already set\n" -msgstr "bersprungen: ffentlicher Schlssel bereits gesetzt\n" - -#: g10/pkclist.c:942 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "Unbekannter voreingestellter Empfnger '%s'\n" - -#: g10/pkclist.c:987 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: bersprungen: ffentlicher Schlssel ist abgeschaltet\n" - -#: g10/pkclist.c:1042 -msgid "no valid addressees\n" -msgstr "Keine gltigen Adressaten\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "Voreinstellung %c%lu ist nicht gltig\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "Voreinstellung %c%lu ist doppelt\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "zu viele `%c' Voreinstellungen\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "Ungltiges Zeichen in den Voreinstellungen\n" - -#: g10/keygen.c:524 -msgid "writing direct signature\n" -msgstr "Die \"Direct Key Signature\" wird geschrieben\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "Die Eigenbeglaubigung wird geschrieben\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "Schreiben der \"key-binding\" Signatur\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "Ungltig Schlssellnge; %u Bit werden verwendet\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "Schlssellnge auf %u Bit aufgerundet\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Bitte whlen Sie, welche Art von Schlssel Sie mchten:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA und ElGamal (voreingestellt)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (nur signieren/beglaubigen)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (nur verschlsseln)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (signieren/beglaubigen und verschlsseln)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (nur signieren/beglaubigen)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (nur verschlsseln)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (signieren/beglaubigen und verschlsseln)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Ihre Auswahl? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" -"Von der Benutzung dieses Verfahrens ist abzuraten - Trotzdem erzeugen? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Ungltige Auswahl.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Es wird ein neues %s Schlsselpaar erzeugt.\n" -" kleinste Schlssellnge ist 768 Bit\n" -" standard Schlssellnge ist 1024 Bit\n" -" grte sinnvolle Schlssellnge ist 2048 Bit\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Welche Schlssellnge wnschen Sie? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA erlaubt nur Schlssellngen von 512 bis 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "zu kurz; 1024 ist die kleinste fr RSA mgliche Schlssellnge.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "zu kurz; 768 ist die kleinste mgliche Schlssellnge.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "Schsselgre zu hoch; %d ist der Maximalwert.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Schlssellngen grer als 2048 werden nicht empfohlen, da die\n" -"Berechnungen dann WIRKLICH lange brauchen!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Sind Sie sicher, da Sie diese Schlssellnge wnschen? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Gut, aber bitte denken Sie auch daran, da Monitor und Tastatur Daten " -"abstrahlen und diese leicht mitgelesen werden knnen.\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Die verlangte Schlssellnge betrgt %u Bit\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "aufgerundet auf %u Bit\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Bitte whlen Sie, wie lange der Schlssel gltig bleiben soll.\n" -" 0 = Schlssel verfllt nie\n" -" = Schlssel verfllt nach n Tagen\n" -" w = Schlssel verfllt nach n Wochen\n" -" m = Schlssel verfllt nach n Monaten\n" -" y = Schlssel verfllt nach n Jahren\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Bitte whlen Sie, wie lange die Beglaubigung gltig bleiben soll.\n" -" 0 = Schlssel verfllt nie\n" -" = Schlssel verfllt nach n Tagen\n" -" w = Schlssel verfllt nach n Wochen\n" -" m = Schlssel verfllt nach n Monaten\n" -" y = Schlssel verfllt nach n Jahren\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Wie lange bleibt der Schlssel gltig? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Wie lange bleibt die Beglaubigung gltig? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "Ungltiger Wert.\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s verfllt nie.\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s verfllt am %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Ihr Rechner kann Daten jenseits des Jahres 2038 nicht anzeigen.\n" -"Trotzdem werden Daten bis 2106 korrekt verarbeitet.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Ist dies richtig? (j/n) " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Sie bentigen eine User-ID, um Ihren Schlssel eindeutig zu machen; das\n" -"Programm baut diese User-ID aus Ihrem echten Namen, einem Kommentar und\n" -"Ihrer E-Mail-Adresse in dieser Form auf:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Ihr Name (\"Vorname Nachname\"): " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Ungltiges Zeichen im Namen\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Der Name darf nicht mit einer Ziffer beginnen.\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Der Name mu min. 5 Zeichen lang sein.\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "E-Mail-Adresse: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Diese E-Mail-Adresse ist ungltig\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Kommentar: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Ungltiges Zeichen im Kommentar.\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Sie benutzen den Zeichensatz `%s'\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Sie haben diese User-ID gewhlt:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Bitte keine E-Mailadressen als Namen oder Kommentar verwenden\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnKkEeFfBb" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "ndern: (N)ame, (K)ommentar, (E)-Mail oder (B)eenden? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "ndern: (N)ame, (K)ommentar, (E)-Mail oder (F)ertig/(B)eenden? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Bitte beseitigen Sie zuerst den Fehler\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Sie bentigen ein Mantra, um den geheimen Schlssel zu schtzen.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "Mantra wurde nicht richtig wiederholt; noch einmal versuchen" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Sie mchten kein Mantra - Dies ist *nicht* zu empfehlen!\n" -"Es ist trotzdem mglich. Sie knnen Ihr Mantra jederzeit\n" -"ndern, indem sie dieses Programm mit dem Befehl \"--edit-key\"\n" -"aufrufen.\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Wir mssen eine ganze Menge Zufallswerte erzeugen. Sie knnen dies\n" -"untersttzen, indem Sie z.B. in einem anderen Fenster/Konsole irgendetwas\n" -"tippen, die Maus verwenden oder irgendwelche anderen Programme benutzen.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "Das DSA-Schlsselpaar wird 1024 Bit haben.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Schlsselerzeugung abgebrochen.\n" - -#: g10/keygen.c:2146 g10/keygen.c:2234 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "schreiben des ffentlichen Schlssels nach '%s'\n" - -#: g10/keygen.c:2147 g10/keygen.c:2236 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "schreiben des geheimen Schlssels nach '%s'\n" - -#: g10/keygen.c:2223 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "kein schreibbarer ffentlicher Schlsselbund gefunden: %s\n" - -#: g10/keygen.c:2229 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "kein schreibbarer geheimer Schlsselbund gefunden: %s\n" - -#: g10/keygen.c:2243 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "Fehler beim Schreiben des ff. Schlsselbundes `%s': %s\n" - -#: g10/keygen.c:2250 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "Fehler beim Schreiben des geheimen Schlsselbundes `%s': %s\n" - -#: g10/keygen.c:2270 -msgid "public and secret key created and signed.\n" -msgstr "ffentlichen und geheimen Schlssel erzeugt und signiert.\n" - -#: g10/keygen.c:2271 -msgid "key marked as ultimately trusted.\n" -msgstr "Schlssel ist als uneingeschrnkt vertrauenswrdig gekennzeichnet.\n" - -#: g10/keygen.c:2282 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Bitte beachten Sie, da dieser Schlssel nicht zum Verschlsseln benutzt\n" -"werden kann. Sie knnen aber mit dem Befehl \"--edit-key\" einen\n" -"Zweitschlssel fr diesem Zweck erzeugen.\n" - -#: g10/keygen.c:2294 g10/keygen.c:2404 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Schlsselerzeugung fehlgeschlagen: %s\n" - -#: g10/keygen.c:2340 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"Der Schlssel wurde %lu Sekunde in der Zukunft erzeugt (Zeitreise oder Uhren " -"stimmen nicht berein)\n" - -#: g10/keygen.c:2342 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"Der Schlssel wurde %lu Sekunden in der Zukunft erzeugt (Zeitreise oder " -"Uhren stimmen nicht berein)\n" - -#: g10/keygen.c:2351 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "HINWEIS: Unterschlssel fr v3-Schlssen sind nicht OpenPGP-konform\n" - -#: g10/keygen.c:2380 -msgid "Really create? " -msgstr "Wirklich erzeugen? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output funktioniert nicht bei diesem Kommando\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: kann nicht geffnet werden: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "Fehler beim Erzeugen des Mantras: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" -"Aufgrund des S2K-Modus kann ein symmetrisches ESK Packet nicht benutzt " -"werden\n" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' ist bereits komprimiert\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: WARNUNG: Leere Datei\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus kann nur fr RSA-Schlssel mit maximal 2048 Bit " -"verschlsselt werden\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "Lesen von '%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"Die IDEA-Verschlsselung kann nicht mit allen Zielschlsseln verwendet " -"werden.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" -"Erzwungene Verwendung des symmetrischen Verschlsselungsverfahren %s (%d) " -"verletzt die Empfngervoreinstellungen\n" - -#: g10/encode.c:558 g10/sign.c:758 -#, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"Erzwungenes Kompressionsverfahren %s (%d) verletzt die " -"Empfngervoreinstellungen.\n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Die Benutzung von %s ist im %s-Modus nicht erlaubt.\n" - -#: g10/encode.c:735 -#, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s verschlsselt fr: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2317 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "Schlssel `%s' nicht gefunden: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "Fehler beim Lesen des Schlsselblocks: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "Schlssel %08lX: dies ist kein RFC2440-Schssel - bersprungen\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "Schlssel %08lX: ungeschtzt - bersprungen\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "Schlssel %08lX: PGP 2.x-artiger Schlssel - bersprungen\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "WARNUNG: Nichts exportiert\n" - -#: g10/getkey.c:150 -msgid "too many entries in pk cache - disabled\n" -msgstr "zu viele Eintrge im pk-Cache - abgeschaltet\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:186 g10/getkey.c:2455 -msgid "[User id not found]" -msgstr "[User-ID nicht gefunden]" - -#: g10/getkey.c:1494 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Ungltiger Schlssel %08lX, gltig gemacht per --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2171 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "" -"der Zweitschlssel %08lX wird anstelle des Hauptschlssels %08lX verwendet\n" - -#: g10/getkey.c:2218 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "" -"Schlssel %08lX: geheimer Schlssel, aber ohne ffentlichen Schlssel - " -"bersprungen\n" - -#: g10/import.c:270 -#, c-format -msgid "skipping block of type %d\n" -msgstr "berspringe den Block vom Typ %d\n" - -#: g10/import.c:279 -#, fuzzy, c-format -msgid "%lu keys processed so far\n" -msgstr "%lu Schlssel bislang bearbeitet\n" - -#: g10/import.c:284 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "Fehler beim Lesen von `%s': %s\n" - -#: g10/import.c:296 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Anzahl insgesamt bearbeiteter Schlssel: %lu\n" - -#: g10/import.c:298 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " ignorierte neue Schlssel: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " ohne User-ID: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " imported: %lu" -msgstr " importiert: %lu" - -#: g10/import.c:309 -#, c-format -msgid " unchanged: %lu\n" -msgstr " unverndert: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " neue User-IDs: %lu\n" - -#: g10/import.c:313 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " neue Unterschlssel: %lu\n" - -#: g10/import.c:315 -#, c-format -msgid " new signatures: %lu\n" -msgstr " neue Signaturen: %lu\n" - -#: g10/import.c:317 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " neue Schlsselwiderrufe: %lu\n" - -#: g10/import.c:319 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " gelesene geheime Schlssel: %lu\n" - -#: g10/import.c:321 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " geheime Schlssel importiert: %lu\n" - -#: g10/import.c:323 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " unvernderte geh.Schl.: %lu\n" - -#: g10/import.c:325 -#, c-format -msgid " not imported: %lu\n" -msgstr " nicht importiert: %lu\n" - -#: g10/import.c:593 g10/import.c:849 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "Schlssel %08lX: Keine User-ID\n" - -#: g10/import.c:609 -#, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "Schlssel %08lX: HKP Unterschlsseldefekt repariert\n" - -#: g10/import.c:624 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "Schlssel %08lX: Nicht eigenbeglaubigte User-ID `%s' bernommen\n" - -#: g10/import.c:631 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "Schlssel %08lX: Keine gltigen User-IDs\n" - -#: g10/import.c:633 -msgid "this may be caused by a missing self-signature\n" -msgstr "dies knnte durch fehlende Eigenbeglaubigung verursacht worden sein\n" - -#: g10/import.c:643 g10/import.c:929 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "Schlssel %08lX: ffentlicher Schlssel nicht gefunden: %s\n" - -#: g10/import.c:648 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "Schlssel %08lX: neuer Schlssel - bersprungen\n" - -#: g10/import.c:657 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "kein schreibbarer Schlsselbund gefunden: %s\n" - -#: g10/import.c:662 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "Schreiben nach '%s'\n" - -#: g10/import.c:665 g10/import.c:750 g10/import.c:876 g10/import.c:989 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "Fehler beim Schreiben des Schlsselbundes `%s': %s\n" - -#: g10/import.c:682 -#, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "Schlssel %08lX: ffentlicher Schlssel \"%s\" importiert\n" - -#: g10/import.c:704 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "Schlssel %08lX: Stimmt nicht mit unserer Kopie berein\n" - -#: g10/import.c:721 g10/import.c:946 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "" -"Schlssel %08lX: der lokale originale Schlsselblocks wurde nicht gefunden: %" -"s\n" - -#: g10/import.c:728 g10/import.c:952 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "" -"Schlssel %08lX: Lesefehler im lokalen originalen Schlsselblocks: %s\n" - -#: g10/import.c:759 -#, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "Schlssel %08lX: \"%s\" 1 neue User-ID\n" - -#: g10/import.c:762 -#, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "Schlssel %08lX: \"%s\" %d neue User-IDs\n" - -#: g10/import.c:765 -#, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "Schlssel %08lX: \"%s\" 1 neue Signatur\n" - -#: g10/import.c:768 -#, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "Schlssel %08lX: \"%s\" %d neue Signaturen\n" - -#: g10/import.c:771 -#, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "Schlssel %08lX: \"%s\" 1 neuer Unterschlssel\n" - -#: g10/import.c:774 -#, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "Schlssel %08lX: \"%s\" %d neue Unterschlssel\n" - -#: g10/import.c:793 -#, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "Schlssel %08lX: \"%s\" Nicht gendert\n" - -#: g10/import.c:855 -#, fuzzy, c-format -msgid "key %08lX: secret key with invalid cipher %d - skipped\n" -msgstr "" -"Schlssel %08lX: geheimer Schlssel, aber ohne ffentlichen Schlssel - " -"bersprungen\n" - -#: g10/import.c:870 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "Kein voreingestellter geheimer Schlsselbund: %s\n" - -#: g10/import.c:881 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "Schlssel %08lX: Geheimer Schlssel importiert\n" - -#. we can't merge secret keys -#: g10/import.c:887 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "Schlssel %08lX: Ist bereits im geheimen Schlsselbund\n" - -#: g10/import.c:894 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "Schlssel %08lX: geheimer Schlssel nicht gefunden: %s\n" - -#: g10/import.c:923 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"Schlssel %08lX: Kein ffentlicher Schlssel - der Schlsselwiderruf kann " -"nicht angebracht werden\n" - -#: g10/import.c:963 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "Schlssel %08lX: Ungltiges Widerrufzertifikat: %s - zurckgewiesen\n" - -#: g10/import.c:995 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "Schlssel %08lX: \"%s\" Widerrufzertifikat importiert\n" - -#: g10/import.c:1043 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "Schlssel %08lX: Keine User-ID fr Signatur\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"Schlssel %08lX: Nicht untersttztes Public-Key-Verfahren fr User-ID \"%s" -"\"\n" - -#: g10/import.c:1058 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "Schlssel %08lX: Ungltige Eigenbeglaubigung fr User-ID \"%s\"\n" - -#: g10/import.c:1073 -#, fuzzy, c-format -msgid "key %08lX: no subkey for subkey binding signature\n" -msgstr "Schlssel %08lX: Kein Unterschlssel fr die Schlsselanbindung\n" - -#: g10/import.c:1081 g10/import.c:1122 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "Schlssel %08lX: Nicht untersttztes Public-Key-Verfahren\n" - -#: g10/import.c:1082 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "Schlssel %08lX: Ungltige Unterschlssel-Anbindung\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1094 -#, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "Schlssel %08lX: Ungltige Unterschlssel-Anbindung entfernt\n" - -#: g10/import.c:1114 g10/sig-check.c:550 -#, fuzzy, c-format -msgid "key %08lX: no subkey for subkey revocation signature\n" -msgstr "Schlssel %08lX: Kein Unterschlssel fr den Schlsselwiderruf\n" - -#: g10/import.c:1123 -#, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "Schlssel %08lX: Ungltiger Unterschlsselwiderruf\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1134 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation signatures\n" -msgstr "Schlssel %08lX: Mehrfacher Unterschlssel-Widerruf entfernt\n" - -#: g10/import.c:1171 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "Schlssel %08lX: User-ID bergangen '" - -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "Schlssel %08lX: Unterschlssel ignoriert\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "" -"Schlssel %08lX: Nicht exportfhige Unterschrift (Klasse %02x) - bergangen\n" - -#: g10/import.c:1229 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "Schlssel %08lX: Widerrufzertifikat an falschem Platz - bergangen\n" - -#: g10/import.c:1246 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "Schlssel %08lX: Ungltiges Widerrufzertifikat: %s - bergangen\n" - -#: g10/import.c:1258 -#, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "Schlssel %08lX: Widerrufzertifikat an falschem Platz - bergangen\n" - -#: g10/import.c:1356 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "Schlssel %08lX: Doppelte User-ID entdeckt - zusammengefhrt\n" - -#: g10/import.c:1415 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"WARNUNG: Schlssel %08lX ist u.U. widerrufen: hole Widerrufschlssel %08lX\n" - -#: g10/import.c:1429 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"WARNUNG: Schlssel %08lX ist u.U. widerrufen: Widerrufschlssel %08lX ist " -"nicht vorhanden\n" - -#: g10/import.c:1486 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "Schlssel %08lX: \"%s\" Widerrufzertifikat hinzugefgt\n" - -#: g10/import.c:1517 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "Schlssel %08lX: \"direct-key\"-Signaturen hinzugefgt\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[Widerruf]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[Eigenbeglaubigung]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 falsche Beglaubigung\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d falsche Beglaubigungen\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 Beglaubigung wegen fehlendem Schlssel nicht geprft\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d Beglaubigungen wegen fehlenden Schlsseln nicht geprft\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 Beglaubigung aufgrund von Fehler nicht geprft\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d Beglaubigungen aufgrund von Fehlern nicht geprft\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "Eine User-ID ohne gltige Eigenbeglaubigung entdeckt\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d User-IDs ohne gltige Eigenbeglaubigung entdeckt\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "User-ID \"%s\" ist widerrufen." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Wollen Sie ihn immmer noch beglaubigen? (j/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Beglaubigen ist nicht mglich.\n" - -#: g10/keyedit.c:380 -#, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "WARNUNG: User-ID \"%s\" ist nicht eigenbeglaubigt.\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Die Eigenbeglaubigung von \"%s\"\n" -"ist eine PGP 2.x artige Signatur.\n" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Soll sie zu einer OpenPGP Eigenbeglaubigung gendert werden? (j/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Die derzeitige Beglaubigung von \"%s\"\n" -"ist nur fr diesen Rechner gltig.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" -"Soll sie zu einer voll exportierbaren Beglaubigung erhoben werden? (j/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" wurde bereits durch Schlssel %08lX lokal beglaubigt\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" wurde bereits durch Schlssel %08lX beglaubigt\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nichts zu beglaubigen fr Schlssel %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Dieser Schlssel ist verfallen!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Dieser Schlssel wird %s verfallen.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Soll Ihre Beglaubigung zur selben Zeit verfallen? (J/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"Im --pgp2-Modus kann nur mit PGP-2.x-artigen Schlsseln unterschrieben " -"werden\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Dies wrde den Schlssel fr PGP 2.x unbrauchbar machen\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Wie genau haben Sie berprft, ob der Schlssel, den Sie jetzt beglaubigen\n" -"wollen, wirklich der o.g. Person gehrt?\n" -"Wenn Sie darauf keine Antwort wissen, geben Sie \"0\" ein.\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Ich antworte nicht.%s\n" - -#: g10/keyedit.c:565 g10/keyedit.c:567 g10/keyedit.c:569 g10/keyedit.c:571 -#, fuzzy -msgid " (default)" -msgstr "Daten entschlsseln (Voreinstellung)" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Ich habe es berhaupt nicht berprft.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Ich habe es flchtig berprft.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Ich habe es sehr sorgfltig berprft.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Sind Sie wirklich sicher, da Sie vorstehenden Schlssel mit Ihrem\n" -"Schlssel beglaubigen wollen: \"" - -#: g10/keyedit.c:604 -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "" -"\n" -"Dies wird eine Eigenbeglaubigung sein.\n" - -#: g10/keyedit.c:608 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"WARNUNG: Die Unterschrift wird nicht als nicht-exportierbar markiert " -"werden.\n" - -#: g10/keyedit.c:613 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"Die Unterschrift wird nicht als nicht-widerrufbar markiert werden.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"Die Unterschrift wird als nicht exportfhig markiert werden.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"Die Unterschrift wird als nicht exportfhig markiert werden.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Ich habe diesen Schlssel berhaupt nicht berprft.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Ich habe diesen Schlssel flchtig berprft.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Ich habe diesen Schlssel sehr sorgfltig berprft.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Wirklich unterschreiben? " - -#: g10/keyedit.c:688 g10/keyedit.c:3128 g10/keyedit.c:3190 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "Beglaubigung fehlgeschlagen: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Dieser Schlssel ist nicht geschtzt.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Geheime Teile des Haupschlssels sind nicht vorhanden\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Schlssel ist geschtzt.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Dieser Schlssel kann nicht editiert werden: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Geben Sie das neue Mantra fr diesen geheimen Schlssel ein.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Sie wollen kein Mantra - dies ist bestimmt *keine* gute Idee!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Mchten Sie dies wirklich tun? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "schiebe eine Beglaubigung an die richtige Stelle\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "Men verlassen" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "speichern und Men verlassen" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "Diese Hilfe zeigen" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "\"Fingerabdruck\" anzeigen" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "Liste der Schlssel" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "Schlssel und User-IDs auflisten" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "User-ID N auswhlen" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "Zweitschlssel N auswhlen" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "Liste der Signaturen" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "Den Schlssel signieren" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "Den Schlssel nur fr diesen Rechner beglaubigen" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "Den Schlssel nicht-widerrufbar beglaubigen" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "Den Schlssel nicht-widerrufbar und nur fr diesen Rechner signieren" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "Eine User-ID hinzufgen" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "Eine Foto-ID hinzufgen" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "User-ID entfernen" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "Einen Zweitschlssel hinzufgen" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "Einen Zweitschlssel entfernen" - -#: g10/keyedit.c:926 -msgid "addrevoker" -msgstr "addrevoker" - -#: g10/keyedit.c:926 -msgid "add a revocation key" -msgstr "Einen Widerrufschlssel hinzufgen" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "Signatur entfernen" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "ndern des Verfallsdatums" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "User-ID als Haupt-User-ID kennzeichnen" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "Umschalten zwischen Anzeige geheimer und ffentlicher Schlssel" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "Liste der Voreinstellungen (fr Experten)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "Liste der Voreinstellungen (ausfhrlich)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "Liste der Voreinstellungen einstellen" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "genderte Voreinstellungen" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "Das Mantra ndern" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "Den \"Owner trust\" ndern" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "Signaturen widerrufen" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "Einen Zweitschlssel widerrufen" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "Schlssel abschalten" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "Schlssel anschalten" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "Foto-ID anzeigen" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "Dies kann im Batchmodus nicht durchgefhrt werden.\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "Fehler beim Lesen des geheimen Schlsselblocks `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Geheimer Schlssel ist vorhanden.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Befehl> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Hierzu wird der geheime Schlssel bentigt.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Bitte verwenden sie zunchst den Befehl \"toggle\"\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "Schlssel wurde widerrufen." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Wirklich alle User-IDs beglaubigen? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Tip: Whlen Sie die User-IDs, die beglaubigt werden sollen\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Dieses Kommando ist im %s-Modus nicht erlaubt.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Zumindestens eine User-ID mu ausgewhlt werden.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Die letzte User-ID kann nicht gelscht werden!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Mchten Sie alle ausgewhlten User-IDs wirklich entfernen? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Diese User-ID wirklich entfernen? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Zumindestens ein Schlssel mu ausgewhlt werden.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Mchten Sie die ausgewhlten Schlssel wirklich entfernen? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Mchten Sie diesen Schlssel wirklich entfernen? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Mchten Sie die ausgewhlten Schlssel wirklich widerrufen? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Mchten Sie diesen Schlssel wirklich wiederrufen? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Mchten Sie die Voreinstellungen der ausgewhlten User-IDs wirklich ndern? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Die Voreinstellungen wirklich ndern? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "nderungen speichern? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Beenden ohne zu speichern? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "nderung fehlgeschlagen: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "nderung des Geheimnisses fehlgeschlagen: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Schlssel ist nicht gendert worden, also ist kein Speichern ntig.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Ungltiger Befehl (versuchen Sie's mal mit \"help\")\n" - -#: g10/keyedit.c:1750 -#, c-format -msgid "This key may be revoked by %s key " -msgstr "Dieser Schlssel knnte widerrufen worden sein von %s Schlssel " - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "(empfindlich)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX erstellt: %s verfllt: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " Vertrauen: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Hinweis: Dieser Schlssel ist abgeschaltet" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! Unterschlssel wurde widerrufen: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- geflschter Schlsselwiderruf entdeckt\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? Schwierigkeiten bei der Widerruf-berprfung: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "PGP 2.x-artige Schlssel haben keine Voreinstellungen.\n" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Bitte beachten Sie, da ohne einen Programmneustart die angezeigte\n" -"Schlsselgltigkeit nicht notwendigerweise korrekt ist.\n" - -#: g10/keyedit.c:2002 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"WARNUNG: Dies ist ein PGP2-artiger Schlssel. Hinzufgen einer Foto-ID " -"knnte\n" -" bei einigen PGP-Versionen zur Zurckweisung des Schlssels fhren.\n" - -#: g10/keyedit.c:2007 g10/keyedit.c:2280 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Wollen Sie ihn immmer noch hinzufgen? (j/N) " - -#: g10/keyedit.c:2013 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Sie knnen einem PGP2-artigen Schlsel keine Foto-ID hinzufgen.\n" - -#: g10/keyedit.c:2148 -msgid "Delete this good signature? (y/N/q)" -msgstr "Diese korrekte Beglaubigung entfernen? (j/N/q)" - -#: g10/keyedit.c:2158 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Diese ungltige Beglaubigung entfernen= (j/N/q)" - -#: g10/keyedit.c:2162 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Diese unbekannte Beglaubigung entfernen? (j/N/q)" - -#: g10/keyedit.c:2168 -msgid "Really delete this self-signature? (y/N)" -msgstr "Eigenbeglaubigung wirklich entfernen? (j/N)" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d Beglaubigungen entfernt.\n" - -#: g10/keyedit.c:2183 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d Beglaubigungen entfernt.\n" - -#: g10/keyedit.c:2186 -msgid "Nothing deleted.\n" -msgstr "Nichts entfernt.\n" - -#: g10/keyedit.c:2275 -#, fuzzy -msgid "" -"WARNING: This is a PGP 2.x-style key. Adding a designated revoker may " -"cause\n" -" some versions of PGP to reject this key.\n" -msgstr "" -"WARNUNG: Dies ist ein PGP2-artiger Schlssel. Hinzufgen einer Foto-ID " -"knnte\n" -" bei einigen PGP-Versionen zur Zurckweisung des Schlssels fhren.\n" - -#: g10/keyedit.c:2286 -#, fuzzy -msgid "You may not add a designated revoker to a PGP 2.x-style key.\n" -msgstr "Sie knnen einem PGP2-artigen Schlsel keine Foto-ID hinzufgen.\n" - -#: g10/keyedit.c:2309 -msgid "Enter the user ID of the designated revoker: " -msgstr "Geben sie die User-ID des designierten Widerrufers ein: " - -#: g10/keyedit.c:2324 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" -"Ein PGP 2.x-artiger Schlssel kann nicht als designierter Widerrufer " -"eingetragen werden\n" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2339 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" -"Ein Schlssel kann nicht als sein eigener designierter Widerrufer agieren\n" - -#: g10/keyedit.c:2361 -#, fuzzy -msgid "this key has already been designated as a revoker\n" -msgstr "" -"Ein Schlssel kann nicht als sein eigener designierter Widerrufer agieren\n" - -#: g10/keyedit.c:2457 -msgid "Please remove selections from the secret keys.\n" -msgstr "Bitte entfernen Sie die Auswahl von den geheimen Schlsseln.\n" - -#: g10/keyedit.c:2463 -msgid "Please select at most one secondary key.\n" -msgstr "Bitte whlen Sie hchstens einen Zweitschlssel aus.\n" - -#: g10/keyedit.c:2467 -msgid "Changing expiration time for a secondary key.\n" -msgstr "ndern des Verfallsdatums des Zweitschlssels.\n" - -#: g10/keyedit.c:2469 -msgid "Changing expiration time for the primary key.\n" -msgstr "ndern des Verfallsdatums des Hauptschlssels.\n" - -#: g10/keyedit.c:2511 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Sie knnen das Verfallsdatum eines v3-Schlssels nicht ndern\n" - -#: g10/keyedit.c:2527 -msgid "No corresponding signature in secret ring\n" -msgstr "Keine entsprechende Signatur im geheimen Schlsselbund\n" - -#: g10/keyedit.c:2610 -msgid "Please select exactly one user ID.\n" -msgstr "Bitte genau eine User-ID auswhlen.\n" - -#: g10/keyedit.c:2647 g10/keyedit.c:2754 -#, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "berspringen der v3 Eigenbeglaubigung von User-ID \"%s\"\n" - -#: g10/keyedit.c:2814 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Keine User-ID mit Index %d\n" - -#: g10/keyedit.c:2860 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Kein Zweitschlssel mit Index %d\n" - -#: g10/keyedit.c:2974 -msgid "user ID: \"" -msgstr "User-ID: \"" - -#: g10/keyedit.c:2979 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"unterschrieben mit Ihrem Schlssel %08lX um %s\n" - -#: g10/keyedit.c:2982 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"lokal unterschrieben mit Ihrem Schlssel %08lX um %s\n" - -#: g10/keyedit.c:2987 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Diese Unterschrift ist seit %s verfallen.\n" - -#: g10/keyedit.c:2991 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Wollen Sie ihn immmer noch widerrufen? (j/N) " - -#: g10/keyedit.c:2995 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Ein Widerrufszertifikat fr diese Unterschrift erzeugen (j/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:3020 -msgid "You have signed these user IDs:\n" -msgstr "Sie haben folgende User-IDs beglaubigt:\n" - -#: g10/keyedit.c:3039 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " beglaubigt durch %08lX um %s%s%s\n" - -#: g10/keyedit.c:3047 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " widerrufen durch %08lX um %s\n" - -#: g10/keyedit.c:3067 -msgid "You are about to revoke these signatures:\n" -msgstr "Es werden nun folgende Beglaubigungen entfernt:\n" - -#: g10/keyedit.c:3077 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " beglaubigt durch %08lX am %s%s\n" - -#: g10/keyedit.c:3079 -msgid " (non-exportable)" -msgstr " (nicht-exportierbar)" - -#: g10/keyedit.c:3086 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Wirklich ein Unterschrift-Widerrufszertifikat erzeugen? (j/N) " - -#: g10/keyedit.c:3116 -msgid "no secret key\n" -msgstr "Kein geheimer Schlssel\n" - -#: g10/keyedit.c:3271 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Anzeigen einer %s Photo ID (%ld Byte) fr Schlssel %08lX (User-ID %d)\n" - -#: g10/keylist.c:91 -msgid "Critical signature policy: " -msgstr "Krititische Beglaubigungsrichtlinie: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Beglaubigungsrichtlinie: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:769 g10/mainproc.c:778 -msgid "WARNING: invalid notation data found\n" -msgstr "WARNUNG: Ungltige \"Notation\"-Daten gefunden\n" - -#: g10/keylist.c:127 -msgid "Critical signature notation: " -msgstr "Krititische Beglaubigungs-\"Notation\": " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Beglaubigungs-\"Notation\": " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "nicht als Klartext darstellbar" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Schlsselbund" - -#. of subkey -#: g10/keylist.c:494 g10/mainproc.c:905 -#, c-format -msgid " [expires: %s]" -msgstr " [verfllt: %s]" - -#: g10/keylist.c:1019 -msgid "Primary key fingerprint:" -msgstr "Haupt-Fingerabdruck =" - -#: g10/keylist.c:1021 -msgid " Subkey fingerprint:" -msgstr "Unter-Fingerabdruck =" - -#: g10/keylist.c:1028 -msgid " Primary key fingerprint:" -msgstr " Haupt-Fingerabdruck =" - -#: g10/keylist.c:1030 -msgid " Subkey fingerprint:" -msgstr " Unter-Fingerabdruck =" - -#. use tty -#: g10/keylist.c:1034 g10/keylist.c:1038 -msgid " Key fingerprint =" -msgstr " Schl.-Fingerabdruck =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "Seltsame Lnge des verschlsselten Session-Keys (%d)\n" - -#: g10/mainproc.c:259 -#, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "Ungltiger Veschlsselungsalgorithmus entdeckt (%d)\n" - -#: g10/encr-data.c:66 g10/mainproc.c:288 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s verschlsselte Daten\n" - -#: g10/encr-data.c:68 g10/mainproc.c:290 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "Mit unbekanntem Verfahren verschlsselt %d\n" - -#: g10/mainproc.c:318 -#, c-format -msgid "public key is %08lX\n" -msgstr "ffentlicher Schlssel ist %08lX\n" - -#: g10/mainproc.c:364 -msgid "public key encrypted data: good DEK\n" -msgstr "Mit ffentlichem Schssel verschlsselte Daten: Korrekte DEK\n" - -#: g10/mainproc.c:416 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "verschlsselt mit %u-Bit %s Schlssel, ID %08lX, erzeugt %s\n" - -# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( -# [kw] -#: g10/mainproc.c:426 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "verschlsselt mit %s Schlssel, ID %08lX\n" - -#: g10/mainproc.c:440 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "Entschlsselung mit ffentlichem Schlssel fehlgeschlagen: %s\n" - -#: g10/mainproc.c:467 g10/mainproc.c:486 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "vermutlich %s-verschlsselte Daten\n" - -#: g10/mainproc.c:474 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "IDEA-Verschlsselung nicht verfgbar; versucht wird stattdessen %s\n" - -#: g10/mainproc.c:504 -msgid "decryption okay\n" -msgstr "Entschlsselung erfolgreich\n" - -#: g10/mainproc.c:511 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "Warnung: Verschlsselte Botschaft ist manipuliert worden!\n" - -#: g10/mainproc.c:517 -#, c-format -msgid "decryption failed: %s\n" -msgstr "Entschlsselung fehlgeschlagen: %s\n" - -#: g10/mainproc.c:536 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "" -"Hinweis: Der Absender verlangte Vertraulichkeit(\"for-your-eyes-only\")\n" - -#: g10/mainproc.c:538 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "Ursprnglicher Dateiname='%.*s'\n" - -#: g10/mainproc.c:713 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "" -"Einzelner Widerruf - verwenden Sie \"gpg --import\" um ihn anzuwenden\n" - -#: g10/mainproc.c:781 -msgid "Notation: " -msgstr "\"Notation\": " - -#: g10/mainproc.c:793 -msgid "Policy: " -msgstr "Richtlinie: " - -#: g10/mainproc.c:1248 -msgid "signature verification suppressed\n" -msgstr "Unterschriften-berprfung unterdrckt\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1290 g10/mainproc.c:1300 -msgid "can't handle these multiple signatures\n" -msgstr "diese Mehrfachunterschriften knnen nicht behandelt werden\n" - -# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( -#: g10/mainproc.c:1311 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Unterschrift vom %.*s, %s Schlssel ID %08lX\n" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "BAD signature from \"" -msgstr "FALSCHE Unterschrift von \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Expired signature from \"" -msgstr "Verfallene Unterschrift von \"" - -#: g10/mainproc.c:1362 g10/mainproc.c:1395 -msgid "Good signature from \"" -msgstr "Korrekte Unterschrift von \"" - -#: g10/mainproc.c:1397 -msgid "[uncertain]" -msgstr "[ungewi] " - -#: g10/mainproc.c:1489 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Unterschrift kann nicht geprft werden: %s\n" - -#: g10/mainproc.c:1558 g10/mainproc.c:1574 g10/mainproc.c:1636 -msgid "not a detached signature\n" -msgstr "keine abgetrennte Unterschrift\n" - -#: g10/mainproc.c:1585 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "Einzelne Unterschrift der Klasse 0x%02x\n" - -#: g10/mainproc.c:1642 -msgid "old style (PGP 2.x) signature\n" -msgstr "Unterschrift nach alter (PGP 2.x) Art\n" - -#: g10/mainproc.c:1649 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "ungltiges root-Paket in proc_tree() entdeckt\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "core-dump-Dateierzeugung kann nicht abgeschaltet werden: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Experimentiermethoden sollten nicht benutzt werden!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "Es ist davon abzuraten, diese Verschlsselungsmethode zu benutzen!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "das IDEA-Verschlsselungs-Plugin ist nicht vorhanden\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "Fr weitere Info siehe http://www.gnupg.org/why-not-idea.html\n" - -#: g10/misc.c:509 -#, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "%s:%d: mibilligte Option \"%s\".\n" - -#: g10/misc.c:513 -#, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "WARNUNG: \"%s\" ist eine mibilligte Option.\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "Bitte benutzen Sie stattdessen \"%s%s\".\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "dieses Public-Key Verfahren %d kann nicht benutzt werden\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "Im Unterpaket des Typs %d ist das \"critical bit\" gesetzt\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "GPG-Agent ist in dieser Sitzung nicht vorhanden\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "Client-PID fr den Agent kann nicht gesetzt werden\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "Server-Lese-Handle fr den Agent nicht verfgbar\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "Server-Schreib-Handle fr den Agent nicht verfgbar\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "fehlerhaft aufgebaute GPG_AGENT_INFO - Umgebungsvariable\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "GPG-Agent-Protokoll-Version %d wird nicht untersttzt\n" - -#: g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "Verbindung zu '%s' kann nicht aufgebaut werden: %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "Kommunikationsproblem mit GPG-Agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:812 g10/passphrase.c:920 -msgid "problem with the agent - disabling agent use\n" -msgstr "" -"Schwierigkeiten mit dem Agenten - Agent-Ansteuerung wird abgeschaltet\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1018 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (Hauptschlssel-ID %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Sie bentigen ein Mantra, um den geheimen Schlssel zu entsperren.\n" -"Benutzer: \"\"%.*s\"\n" -"%u-bit %s Schlssel, ID %08lX, erzeugt %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Geben Sie das Mantra ein\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Geben Sie das Mantra nochmal ein\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "Mantra ist zu lang\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "Falsche Antwort des Agenten\n" - -#: g10/passphrase.c:727 g10/passphrase.c:809 -msgid "cancelled by user\n" -msgstr "Abbruch durch Benutzer\n" - -#: g10/passphrase.c:729 g10/passphrase.c:891 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "Schwierigkeiten mit dem Agenten: Agent antwortet 0x%lx\n" - -#: g10/passphrase.c:1004 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Sie bentigen ein Mantra, um den geheimen Schlssel zu entsperren.\n" -"Benutzer: \"" - -#: g10/passphrase.c:1013 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-Bit %s Schlssel, ID %08lX, erzeugt %s" - -#: g10/passphrase.c:1064 -msgid "can't query password in batchmode\n" -msgstr "Mantra kann im Batchmodus nicht abgefragt werden\n" - -#: g10/passphrase.c:1068 -msgid "Enter passphrase: " -msgstr "Geben Sie das Mantra ein: " - -#: g10/passphrase.c:1072 -msgid "Repeat passphrase: " -msgstr "Geben Sie das Mantra nochmal ein: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"Daten wurden nicht gespeichert; verwenden Sie dafr die Option \"--output\"\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "Fehler beim Erstellen von `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Abgetrennte Beglaubigungen.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Bitte geben Sie den Namen der Datendatei ein: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lese stdin ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "keine unterschriebene Daten\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "kann signierte Datei '%s' nicht ffnen.\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "Ungenannter Empfnger; Versuch mit geheimen Schlssel %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "Alles klar, wir sind der ungenannte Empfnger.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "alte Kodierung des DEK wird nicht untersttzt\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "Verschsselungsverfahren %d%s ist unbekannt oder abgeschaltet\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "Hinweis: Verfahren %d ist kein bevorzugtes Verschlsselungsverfahren\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "Hinweis: geheimer Schlssel %08lX verfllt am %s\n" - -#: g10/pubkey-enc.c:249 -msgid "NOTE: key has been revoked" -msgstr "Hinweis: Schlssel wurde widerrufen" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "Teile des geheimen Schlssels sind nicht vorhanden\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "Schutzverfahren %d%s wird nicht untersttzt\n" - -#: g10/seckey-cert.c:225 -msgid "Invalid passphrase; please try again" -msgstr "Ungltiges Mantra; versuchen Sie es bitte noch einmal" - -#: g10/seckey-cert.c:226 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:283 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"WARNUNG: Unsicherer Schlssel entdeckt -\n" -" bitte Mantra nochmals wechseln.\n" - -#: g10/seckey-cert.c:321 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"Die mibilligte 16-bit Prfsumme wird zum Schutz des geheimen Schlssels " -"benutzt\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "WARNUNG: Widersprechende Hashverfahren in der signierten Nachricht\n" - -#: g10/sig-check.c:213 -#, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"Schlssel %08lX: Dieser durch PGP erzeugte ElGamal-Schlssel ist fr " -"Signaturen NICHT sicher genug!\n" - -#: g10/sig-check.c:222 -#, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "" -"ffentlicher Schlssel %08lX ist um %lu Sekunde jnger als die Unterschrift\n" - -#: g10/sig-check.c:223 -#, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "" -"ffentlicher Schlssel %08lX ist um %lu Sekunden jnger als die " -"Unterschrift\n" - -#: g10/sig-check.c:232 -#, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"Der Schlssel %08lX wurde %lu Sekunde in der Zukunft erzeugt (Zeitreise oder " -"Uhren stimmen nicht berein)\n" - -#: g10/sig-check.c:234 -#, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"Der Schlssel %08lX wurde %lu Sekunden in der Zukunft erzeugt (Zeitreise " -"oder Uhren stimmen nicht berein)\n" - -#: g10/sig-check.c:247 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "Hinweis: Signaturschlssel %08lX ist am %s verfallen.\n" - -#: g10/sig-check.c:346 -#, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"Vermutlich eine FALSCHE Unterschrift von Schlssel %08lX, wegen unbekanntem " -"\"critical bit\"\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"WARNUNG: \"Notation\" kann nicht %%-erweitert werden (zu gro). Verwende " -"\"unerweiterte\".\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"WARNUNG: Richtlinien-URL kann nicht %%-erweitert werden (zu gro0). Verwende " -"\"unerweiterte\".\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "Prfung der erstellten Unterschrift ist fehlgeschlagen: %s\n" - -#: g10/sign.c:312 -#, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s Unterschrift von: \"%s\"\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "WARNUNG: '%s' ist eine leere Datei.\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus kann nur mit PGP-2.x-artigen Schlsseln eine abgetrennte " -"Unterschrift erzeugt werden\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "%s kann nicht erzeugt werden: %s\n" - -#: g10/sign.c:690 -#, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"Erzwingen des Hashverfahrens %s (%d) verletzt die Empfngervoreinstellungen\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "unterschreibe:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus knnen Sie Klartextunterschriften nur mit PGP-2.x-artigen " -"Schlssel machen\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%s Verschlsselung wird verwendet\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "Textzeilen lnger als %d Zeichen knnen nicht benutzt werden\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "Eingabezeile ist lnger als %d Zeichen\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb Satz %lu: lseek fehlgeschlagen: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb Satz %lu: write fehlgeschlagen (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "trustdb Transaktion zu gro\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: kann nicht zugegriffen werden: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: Verzeichnis existiert nicht!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: Sperre kann nicht erzeugt werden\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: Sperre kann nicht erzeugt werden\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: kann nicht erzeugt werden: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: Fehler beim Erzeugen des Versionsatzes: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: ungltige trust-db erzeugt\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: trust-db erzeugt\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "Notiz: Die \"trustdb\" ist nicht schreibbar\n" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: ungltige 'Trust'-Datenbank\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: hashtable kann nicht erzeugt werden: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: Fehler beim ndern des Versionsatzes: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: Fehler beim Lesen des Versionsatzes: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: Fehler beim Schreiben des Versionsatzes: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "trustdb: lseek fehlgeschlagen: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "trustdb: read failed (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: keine trustdb Datei\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: version record with recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: invalid file version %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: Fehler beim Lesen eines freien Satzes: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: Fehler beim Schreiben eines Verzeichnis-Satzes: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: konnte einen Satz nicht Nullen: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: konnte Satz nicht anhngen: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"Die \"Trust\"-Datenbank ist beschdigt; verwenden Sie \"gpg --fix-trustdb" -"\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "'%s' ist keine gltige lange Schlssel-ID\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "Schlssel %08lX: Akzeptiert als vertrauenswrdiger Schlssel\n" - -#: g10/trustdb.c:273 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "Schlssel %08lX tritt mehr als einmal in der \"trustdb\" auf\n" - -#: g10/trustdb.c:289 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"Schlssel %08lX: kein ffentlicher Schlssel fr den vertrauenswrdigen " -"Schlssel - bersprungen\n" - -#: g10/trustdb.c:298 -#, fuzzy, c-format -msgid "key %08lX marked as ultimately trusted\n" -msgstr "Schlssel ist als uneingeschrnkt vertrauenswrdig gekennzeichnet.\n" - -#: g10/trustdb.c:324 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "trust record %lu, req type %d: read failed: %s\n" - -#: g10/trustdb.c:330 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "Vertrauenssatz %lu ist nicht von der angeforderten Art %d\n" - -#: g10/trustdb.c:345 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "trust record %lu, type %d: write failed: %s\n" - -#: g10/trustdb.c:360 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "\"Trust-DB\": sync fehlgeschlagen: %s\n" - -#: g10/trustdb.c:460 -msgid "no need for a trustdb check\n" -msgstr "\"Trust-DB\"-berprfung nicht ntig\n" - -#: g10/trustdb.c:466 g10/trustdb.c:1633 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "nchste \"Trust-DB\"-Pflichtberprfung am %s\n" - -#: g10/trustdb.c:771 -msgid "checking the trustdb\n" -msgstr "\"Trust-DB\" wird berprft\n" - -#: g10/trustdb.c:925 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "ffentlicher Schlssel %08lX nicht gefunden: %s\n" - -#: g10/trustdb.c:1507 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" -"ff.Schlssel des uneingeschrnkt vertrautem Schlssel %08lX nicht gefunden\n" - -#: g10/trustdb.c:1585 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"berprfen, Tiefe %d, unterschrieben =%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"Die Unterschrift konnte nicht berprft werden.\n" -"Denken Sie daran, da die Datei mit der Unterschrift (.sig oder .asc)\n" -"als erster in der Kommandozeile stehen sollte.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "Eingabezeile %u ist zu lang oder es fehlt ein LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"Schlssel ist nicht als unsicher gekennzeichnet - er ist nur mit einem\n" -"echten Zufallsgenerator verwendbar\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "bersprungen '%s': doppelt\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "bersprungen '%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "bersprungen: geheimer Schlssel bereits vorhanden\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"'%s bersprungen: Dies ist ein durch PGP erzeugter ElGamal-Schlssel. Das " -"ist fr Signaturen NICHT sicher genug!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Datei '%s' existiert bereits. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "berschreiben (j/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: unbekannte Dateinamenerweiterung\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Neuen Dateinamen eingeben" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "Schreiben auf die Standardausgabe\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "die unterzeichneten Daten sind wohl in '%s'\n" - -#: g10/openfile.c:326 -#, c-format -msgid "new configuration file `%s' created\n" -msgstr "Neue Konfigurationsdatei `%s' erstellt\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: Verzeichnis kann nicht erzeugt werden: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: Verzeichnis erzeugt\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"Warnung: Botschaft wurde mit einem unsicheren Schlssel verschlsselt.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "Problem beim Bearbeiten des verschlsselten Pakets\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "Unsicherer Schlssel erzeugt - neuer Versuch\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"Trotz %d-fachen Versuch konnte die Erzeugung eines unsicheren Schlssels fr " -"sym.Verschlsselung nicht vermieden werden!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA bentigt einen 160-bit Hash Algorithmus\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "(es sei denn, Sie geben den Schlssel mittels Fingerprint an)\n" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "Dies kann im Batchmodus ohne \"--yes\" nicht durchgefhrt werden.\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Diesen Schlssel aus dem Schlsselbund lschen? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Dies ist ein privater Schlssel! - Wirklich lschen? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "lschen des Schlsselblocks fehlgeschlagen: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "Der \"Ownertrust\" wurde gelscht\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "" -"Es gibt einen privaten Schlssel zu diesem ffentlichen Schlssel \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "" -"Verwenden Sie zunchst das Kommando \"--delete-secret-key\", um ihn zu " -"entfernen.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Sie mssen selbst entscheiden, welchen Wert Sie hier eintragen; dieser Wert\n" -"wird niemals an eine dritte Seite weitergegeben. Wir brauchen diesen Wert,\n" -"um das \"Netz des Vertrauens\" aufzubauen. Dieses hat nichts mit dem\n" -"(implizit erzeugten) \"Netz der Zertifikate\" zu tun." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Um das Web-of-Trust aufzubauen mu GnuPG wissen, welchen Schlsseln\n" -"uneingeschrnkt vertraut wird. Das sind blicherweise die Schlssel\n" -"auf deren geheimen Schlssel Sie Zugruff haben.\n" -"Antworten Sie mit \"yes\" um diesen Schlssel uneingeschrnkt zu vertrauen\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" -"Wenn Sie diesen widerrufenen Schlssel trotzdem benutzen wollen,\n" -"so antworten Sie mit \"ja\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Wenn Sie diesen nicht vertrauenswrdigen Schlssel trotzdem benutzen " -"wollen,\n" -"so antworten Sie mit \"ja\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Geben Sie die User-ID dessen ein, dem Sie die Botschaft senden wollen." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Whlen Sie die zu verwendende Methode aus.\n" -"\n" -"DSA (alias DSS) bedeutet \"digital signature algorithm\" (Digitales\n" -" Unterschrift-Verfahren). Es kann nur zum Unterschreiben und Beglaubigen\n" -" benutzt werden. Dies ist das empfohlene Verfahren, da dessen berprfung\n" -" wesentlich schneller abluft, als die von \"ElGamal\".\n" -"\n" -"ElGamal ist ein Verfahren fr Unterschrift, Beglaubigung und " -"Verschlsselung\n" -" OpenPGP unterscheidet zwischen zwei Arten von ElGamal: eines nur zum\n" -" Unterschreiben/Beglaubigen und eines zustzlich zum Verschlsseln.\n" -" Eigentlich sind diese Arten identisch; allerdings mssen einige Parameter\n" -" auf eine besondere Art gewhlt werden, um einen sicheren Schlssel fr\n" -" Unterschriften zu erzeugen. Dieses Programm macht dies zwar so, aber " -"andere\n" -" Programme sind laut der OpenPGP-Spezifikation nicht verpflichtet, die\n" -" zweite Art (die mit zustzlichem Verschlsseln) zu verstehen.\n" -"\n" -"Der Hauptschlssel (\"primary Key\") mu auf jeden Fall zum Unterschreiben " -"fhig\n" -"sein. Deshalb kann ein nur-Verschlssel-ElGamal-Schlssel dafr nicht\n" -"verwendet werden." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Obwohl diese Schlssel in RFC 2440 definiert sind, ist ihre Verwendung " -"nicht\n" -"empfohlen. Sie werden nmlich nicht von allen Programmen untersttzt.\n" -"Auerdem sind damit ezeugte Unterschriften recht gro und ihre berprfung\n" -"ist langsam." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" -"Normalerweise ist es nicht gut, denselben Schlssel zum unterschreiben\n" -"und verschlsseln zu nutzen. Dieses Verfahren sollte in speziellen\n" -"Anwendungsgebiten benutzt werden. Bitte lassen Sie sich zuerst von \n" -"einem Sicherheistexperten beraten." - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Whlen Sie die gewnschte Schlssellnge" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Geben Sie \"ja\" oder \"nein\" ein" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Geben Sie den bentigten Wert so an, wie er im Prompt erscheint.\n" -"Es ist zwar mglich ein \"ISO\"-Datum (JJJJ-MM-DD) einzugeben, aber man\n" -"erhlt dann ggfs. keine brauchbaren Fehlermeldungen - stattdessen versucht\n" -"der Rechner den Wert als Intervall (von-bis) zu deuten." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Geben Sie den Namen des Schlsselinhabers ein" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "" -"Geben Sie eine E-Mail-Adresse ein. Dies ist zwar nicht unbedingt notwendig,\n" -"aber sehr empfehlenswert." - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Geben Sie - bei Bedarf - einen Kommentar ein" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N um den Namen zu ndern.\n" -"K um den Kommentar zu ndern.\n" -"E um die E-Mail-Adresse zu ndern.\n" -"F um mit der Schlsselerzeugung fortzusetzen.\n" -"B um die Schlsselerzeugung abbrechen." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "" -"Geben Sie \"ja\" (oder nur \"j\") ein, um den Unterschlssel zu erzeugen." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Wenn Sie die User-ID eines Schlssels beglaubigen wollen, sollten Sie " -"zunchst\n" -"sicherstellen, da der Schlssel demjenigen gehrt, der in der User-ID " -"genannt\n" -"ist. Fr Dritte ist es hilfreich zu wissen, wie gut diese Zuordnung " -"berprft\n" -"wurde.\n" -"\n" -"\"0\" zeigt, da Sie keine bestimmte Aussage ber die Sorgfalt der \n" -" Schlsselzuordnung machen.\n" -"\n" -"\"1\" Sie glauben, da der Schlssel der benannten Person gehrt,\n" -" aber Sie konnten oder nahmen die berpfung berhaupt nicht vor.\n" -" Dies ist hilfreich fr eine \"persona\"-berprfung, wobei man den\n" -" Schlssel eines Pseudonym-Trgers beglaubigt\n" -"\n" -"\"2\" Sie nahmen eine flchtige berprfung vor. Das heisst Sie haben z.B.\n" -" den Schlsselfingerabdruck kontrolliert und die User-ID des Schlssels\n" -" anhand des Fotos geprft.\n" -"\n" -"\"3\" Sie haben eine ausfhrlich Kontrolle des Schlssels vorgenommen.\n" -" Das kann z.B. die Kontrolle des Schlsselfingerabdrucks mit dem\n" -" Schlsselinhaber persnlich vorgenommen haben; da Sie die User-ID des\n" -" Schlssel anhand einer schwer zu flschenden Urkunde mit Foto (wie z.B.\n" -" einem Pa) abgeglichen haben und schliesslich per E-Mail-Verkehr die\n" -" E-Mail-Adresse als zum Schlsselbesitzer gehrig erkannt haben.\n" -"\n" -"Beachten Sie, da diese Beispiele fr die Antworten 2 und 3 *nur* Beispiele " -"sind.\n" -"Schluendlich ist es Ihre Sache, was Sie unter \"flchtig\" oder " -"\"ausfhrlich\"\n" -"verstehen, wenn Sie Schlssel Dritter beglaubigen.\n" -"\n" -"Wenn Sie nicht wissen, wie Sie antworten sollen, whlen Sie \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Geben Sie \"ja\" (oder nur \"j\") ein, um alle User-IDs zu beglaubigen" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Geben Sie \"ja\" (oder nur \"j\") ein, um diese User-ID zu LSCHEN.\n" -"Alle Zertifikate werden dann auch weg sein!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "" -"Geben Sie \"ja\" (oder nur \"j\") ein, um diesen Unterschlssel zu lschen" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Dies ist eine gltige Beglaubigung fr den Schlssel. Es ist normalerweise\n" -"unntig sie zu lschen. Sie ist mglicherweise sogar notwendig, um einen\n" -"Trust-Weg zu diesem oder einem durch diesen Schlssel beglaubigten " -"Schlssel\n" -"herzustellen." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Diese Beglaubigung kann nicht geprft werden, da Sie den passenden " -"Schlssel\n" -"nicht besitzen. Sie sollten die Lschung der Beglaubigung verschieben, bis\n" -"sie wissen, welcher Schlssel verwendet wurde. Denn vielleicht wrde genau\n" -"diese Beglaubigung den \"Trust\"-Weg kompletieren." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"Diese Beglaubigung ist ungltig. Es ist sinnvoll sie aus Ihrem\n" -"Schlsselbund zu entfernen." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Diese Beglaubigung bindet die User-ID an den Schlssel. Normalerweise ist\n" -"es nicht gut, solche Beglaubigungen zu entfernen. Um ehrlich zu sein:\n" -"Es knnte dann sein, da GnuPG diesen Schlssel gar nicht mehr benutzen " -"kann.\n" -"Sie sollten diese Eigenbeglaubigung also nur dann entfernen, wenn sie aus\n" -"irgendeinem Grund nicht gltig ist und eine zweite Beglaubigung verfgbar " -"ist." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"ndern der Voreinstellung aller User-IDs (oder nur der ausgewhlten)\n" -"auf die aktuelle Liste der Voreinstellung. Die Zeitangaben aller " -"betroffenen\n" -"Eigenbeglaubigungen werden um eine Sekunde vorgestellt.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Bitte geben Sie das Mantra ein. Dies ist ein geheimer Satz \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Um sicher zu gehen, da Sie sich bei der Eingabe des Mantras nicht\n" -"vertippt haben, geben Sie diese bitte nochmal ein. Nur wenn beide Eingaben\n" -"bereinstimmen, wird das Mantra akzeptiert." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "" -"Geben Sie den Namen der Datei an, zu dem die abgetrennte Unterschrift gehrt" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Geben Sie \"ja\" ein, wenn Sie die Datei berschreiben mchten" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Geben Sie bitte einen neuen Dateinamen ein. Falls Sie nur die\n" -"Eingabetaste bettigen, wird der (in Klammern angezeigte) Standarddateiname\n" -"verwendet." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Sie sollten einen Grund fr die Zertifizierung angeben. Je nach\n" -"Zusammenhang knnen Sie aus dieser Liste auswhlen:\n" -" \"Schlssel wurde kompromitiert\"\n" -" Falls Sie Grund zu der Annahme haben, da nicht berechtigte Personen\n" -" Zugriff zu Ihrem geheimen Schlssel hatten\n" -" \"Schlssel ist berholt\"\n" -" Falls Sie diesen Schlssel durch einem neuen ersetzt haben.\n" -" \"Schlssel wird nicht mehr benutzt\"\n" -" Falls Sie diesen Schlssel zurckgezogen haben.\n" -" \"User-ID ist nicht mehr gltig\"\n" -" Um bekanntzugeben, da die User-ID nicht mehr benutzt werden soll.\n" -" So weist man normalerweise auf eine ungltige E-Mailadresse hin.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Wenn Sie mchten, knnen Sie hier einen Text eingeben, der darlegt, warum\n" -"Sie diesen Widerruf herausgeben. Der Text sollte mglichst knapp sein.\n" -"Eine Leerzeile beendet die Eingabe.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Keine Hilfe vorhanden." - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Keine Hilfe fr '%s' vorhanden." - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "Fehler beim Erzeugen des Schlsselbundes `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "Schlsselbund `%s' erstellt\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "Schlsselbund-Cache konnte nicht neu erzeugt werden: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "Warnung: Zwei Dateien mit vertraulichem Inhalt vorhanden.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s ist der Unvernderte\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s ist der Neue\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Bitte diesen potentiellen Sicherheitsmangel beseitigen\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "Prfen des Schlsselbundes `%s'\n" - -#: g10/keyring.c:1377 -#, fuzzy, c-format -msgid "%lu keys checked so far (%lu signatures)\n" -msgstr "%lu Schlssel geprft (%lu Beglaubigungen)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu Schlssel geprft (%lu Beglaubigungen)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: Schlsselbund erstellt\n" - -#~ msgid "requesting key %08lX from %s\n" -#~ msgstr "Schlssel %08lX wird von %s angefordert\n" - -#~ msgid "can't get key from keyserver: %s\n" -#~ msgstr "Schlssel ist beim Schlsselserver nicht erhltlich: %s\n" - -#~ msgid "error sending to `%s': %s\n" -#~ msgstr "Fehler beim Senden an `%s': %s\n" - -#~ msgid "success sending to `%s' (status=%u)\n" -#~ msgstr "Senden an `%s' erfolgreich (status=%u)\n" - -#~ msgid "failed sending to `%s': status=%u\n" -#~ msgstr "Senden an `%s' erfolglos (status=%u)\n" - -#~ msgid "this keyserver is not fully HKP compatible\n" -#~ msgstr "Dieser Schlsselserver ist nicht vollstndig HKP kompatibel\n" - -#~ msgid "searching for \"%s\" from HKP server %s\n" -#~ msgstr "suche nach \"%s\" auf HKP-Server %s\n" - -#~ msgid "can't search keyserver: %s\n" -#~ msgstr "kann Schlsselserver nicht durchsuchen: %s\n" - -#~ msgid "%lu keys so far checked (%lu signatures)\n" -#~ msgstr "%lu Schlssel bislang geprft (%lu Beglaubigungen)\n" - -#~ msgid "no values for group \"%s\"\n" -#~ msgstr "Keine Werte fr Gruppe \"%s\"\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "Sie mssen GnuPG noch einmal starten, damit es die neue " -#~ "Konfigurationsdatei liest\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "ndern der Zugriffsrechte fr `%s' ist fehlgeschlagen: %s\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Fingerabdruck:" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingerabdruck:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAME=WERT|diese \"notation\"-Daten verwenden" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "Das erste Zeichen eines \"notation\"-Namens mu ein Buchstabe oder\n" -#~ "ein Unterstrich sein\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "Punkte in einem \"notation\"-Namen mssen von anderen Zeichen umgeben " -#~ "sein\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "WARNUNG: Dieser Schlssel besitzt bereits eine Foto-ID.\n" -#~ " Ein hinzugefgte Foto-ID knnte einige Versionen von PGP " -#~ "verwirren.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Sie knnen nur eine Foto-ID fr diesen Schlssel haben.\n" - -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Sind Sie sicher, da Sie dies wiklich unterschreiben mchten?\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " Sind Sie sicher, da Sie dies immer noch unterschreiben wollen?\n" - -#~ msgid "Really sign? (y/N) " -#~ msgstr "Wirklich unterschreiben? (j/N) " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "Schlssel %08lX: Unsere Kopie hat keine Eigenbeglaubigung\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Brauchen Sie wirklich einen derartig langen Schlssel? " - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " beglaubigt durch %08lX um %s\n" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key User-ID" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key User-ID" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key User-ID" - -#~ msgid "Enter the user ID: " -#~ msgstr "Geben Sie die User-ID ein: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "" -#~ "bersprungen: ffentlicher Schlssel bereits mittels --encrypt-to " -#~ "gesetzt\n" - -#~ msgid "" -#~ "\n" -#~ "WARNING: This is a PGP2-style key\n" -#~ msgstr "WARNUNG: '%s' ist eine leere Datei.\n" - -# valid user replies (not including 1..4) -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "Kein Schlsselserver bekannt (Option --keyserver verwenden)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: Dies ist keine gltige Schlssel-ID\n" - -#~ msgid "duplicate (short) key ID %08lX\n" -#~ msgstr "ffentlicher Schlssel ist %08lX\n" - -#~ msgid "%lu key(s) to refresh\n" -#~ msgstr "\t%lu Schlssel mit Fehlern\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NAMEN]|berprfen der \"Trust\"-Datenbank" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Fr diesen Schlssel konnte kein gltiger \"Trust Path\" gefunden " -#~ "werden.\n" -#~ "Mal sehen, ob wir sonst irgendwie ein paar fehlende \"Owner trust\" " -#~ "Werte \n" -#~ "ermitteln knnen.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "Kein Pfad fhrt zu einem unserer Schlsseln.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Keine Zertifikate mit undefiniertem Vertrauen gefunden.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Keine \"trust\" Werte gendert.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "" -#~ "%08lX: Keine Infos zur Berechnung der Vertrauenswahrscheinlichkeit " -#~ "vorgefunden\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: Fehler beim Prfen des Schlssels: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "zu viele Eintrge im unk-Lager - abgeschaltet\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "" -#~ "Geheimer Schlssel %08lX nicht importiert (%s verwenden, um das zu " -#~ "ermglichen)\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "nderung der \"Trust-DB\" fehlgeschlagen: %s\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "" -#~ "Vermutlich ist das Siegel (MDC) BESCHDIGT (wegen unbekanntem \"critical " -#~ "bit\")\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "Fehler beim Lesen des Dir-Satzes fr LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: Dir-Satz erwartet, aber es kam Typ %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "Kein Hauptschlssel fr LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "Fehler beim Lesen den Hauptschlssels der LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record fehlgeschlagen: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "Schlssel %08lX: Satzabfrage fehlgeschlagen\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "Schlssel %08lX: Ist bereits in geheimer Schlsseltabelle\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "HINWEIS: Geheimer Schlssel %08lX ist NICHT geschtzt.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "" -#~ "Schlssel %08lX: geheimer und ffentlicher Schlssel passen nicht " -#~ "zusammen.\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "enum_secret_keys fehlgeschlagen: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "Schlssel %08lX.%lu: Korrekte Unterschlssel-Anbindung\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "Schlssel %08lX.%lu: Ungltige Unterschlssel-Anbindung: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "Schlssel %08lX.%lu: Gltiger Schlsselwiderruf\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "Schlssel %08lX.%lu: Ungltiger Schlsselwiderruf: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Korrekte Eigenbeglaubigung" - -#~ msgid "Invalid self-signature" -#~ msgstr "Ungltige Eigenbeglaubigung" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Gltiger User-ID-Widerruf ignoriert, da eine neuere Eigenbeglaubigung " -#~ "vorliegt" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Gltiger User-ID-Widerruf" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Ungltiger User-ID-Widerruf" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Gltiger Zerifikat-Widerruf" - -#~ msgid "Good certificate" -#~ msgstr "Korrektes Zertifikat" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Ungltiger Zertifikatswiderruf" - -#~ msgid "Invalid certificate" -#~ msgstr "Ungltiges Zertifikat" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "Signatursatz %lu[%d] zeigt auf falschen Satz.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "Doppelte Zertifikate - entfernt" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir fehlgeschlagen: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: Einfgen fehlgeschlagen: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: Einfgen fehlgeschlagen: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: eingefgt\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "Fehler beim Lesen des Verz.Satzes: %s\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu Schlssel eingefgt\n" - -#~ msgid "enumerate keyblocks failed: %s\n" -#~ msgstr "enumerate Schlsselblock fehlgeschlagen: %s\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: Dir-Satz ohne Schlssel - bergangen\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu wegen neuer Schlssel\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu Schlssel bersprungen\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu Schlssel gendert\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Huch, keine Schlssel\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Huch, keine User-IDs\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: Suche nach Dir-Satz fehlgeschlagen: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "Schlssel %08lX: 'trust record' einfgen fehlgeschlagen: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "Schlssel %08lX.%lu: in \"trustdb\" eingefgt\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "Schlssel %08lX.%lu: wurde in der Zukunft erzeugt (Zeitreise oder Uhren " -#~ "stimmen nicht berein)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "Schlssel %08lX.%lu: verfallen am %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "Schlssel %08lX.%lu: Vertrauensprfung fehlgeschlagen: %s\n" - -#~ msgid "user '%s' not found: %s\n" -#~ msgstr "Benutzer '%s' nicht gefunden: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "Problem, '%s' in der Trust-DB zu finden: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "User '%s' ist nicht in der 'Trust'-Datenbank - wird eingefgt\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "konnte '%s' nicht in die 'Trust'-Datenbank hineintun: %s\n" - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "Zu viele Zufallswerte angefordert: Die Grenze liegt bei %d\n" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Weitere Infos: siehe http://www.gnupg.org" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "" -#~ "Mchten Sie wirklich einen Unterschriften-/Verschlsselungschlssel " -#~ "erzeugen? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: Benutzer nicht gefunden: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "Zertifikat Leseproblem: %s\n" - -#~ msgid "can't lock keyring `%s': %s\n" -#~ msgstr "kann Schlsselbund `%s' nicht sperren: %s\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: Benutzer nicht gefunden\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "WARNUNG: Lange 'Pref'-Records knnen noch nicht benutzt werden\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: Schlsselbund kann nicht erzeugt werden: %s\n" - -#~ msgid "invalid" -#~ msgstr "ungltig" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "RSA-Schlssel knnen in dieser Version nicht verwendet werden\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Kein Schlssel fr User-ID\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Keine User-ID fr Schlssel\n" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "kein geheimer Schlssel zur Entschlsselung vorhanden\n" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal in einem v3-Paket\n" - -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "" -#~ "Die Schlsselerzeugung kann nur im interaktiven Modus benutzt werden.\n" diff --git a/po/el.po b/po/el.po deleted file mode 100644 index 047506317..000000000 --- a/po/el.po +++ /dev/null @@ -1,4673 +0,0 @@ -# Greek Translation of GnuPG. -# Copyright (C) 2002 Free Software Foundation, Inc. -# Dokianakis Theofanis , 2002. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg-1.1.92\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-09-12 03:24+0200\n" -"Last-Translator: Dokianakis Theofanis \n" -"Language-Team: Greek \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-7\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -msgid "WARNING: using insecure memory!\n" -msgstr ": !\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr " http://www.gnupg.org/faq.html \n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr " \n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "( )\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "yY" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr " " - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr " " - -#: util/errors.c:56 -msgid "unknown version" -msgstr " " - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr " " - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr " " - -#: util/errors.c:59 -msgid "bad public key" -msgstr " " - -#: util/errors.c:60 -msgid "bad secret key" -msgstr " " - -#: util/errors.c:61 -msgid "bad signature" -msgstr " " - -#: util/errors.c:62 -msgid "checksum error" -msgstr " checksum" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr " " - -#: util/errors.c:64 -msgid "public key not found" -msgstr " " - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr " " - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr " " - -#: util/errors.c:67 -msgid "invalid packet" -msgstr " " - -#: util/errors.c:68 -msgid "invalid armor" -msgstr " " - -#: util/errors.c:69 -msgid "no such user id" -msgstr " (user id)" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr " " - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr " " - -#: util/errors.c:72 -msgid "not supported" -msgstr " " - -#: util/errors.c:73 -msgid "bad key" -msgstr " " - -#: util/errors.c:74 -msgid "file read error" -msgstr " " - -#: util/errors.c:75 -msgid "file write error" -msgstr " " - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr " " - -#: util/errors.c:77 -msgid "file open error" -msgstr " " - -#: util/errors.c:78 -msgid "file create error" -msgstr " " - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr " " - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr " " - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr " " - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr " " - -#: util/errors.c:83 -msgid "trust database error" -msgstr " " - -#: util/errors.c:84 -msgid "bad MPI" -msgstr " MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr " " - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr " " - -#: util/errors.c:87 -msgid "bad certificate" -msgstr " " - -#: util/errors.c:88 -msgid "malformed user id" -msgstr " (user id)" - -#: util/errors.c:89 -msgid "file close error" -msgstr " " - -#: util/errors.c:90 -msgid "file rename error" -msgstr " " - -#: util/errors.c:91 -msgid "file delete error" -msgstr " " - -#: util/errors.c:92 -msgid "unexpected data" -msgstr " " - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr " (timestamp)" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr " " - -#: util/errors.c:95 -msgid "file exists" -msgstr " " - -#: util/errors.c:96 -msgid "weak key" -msgstr " " - -#: util/errors.c:97 -msgid "invalid argument" -msgstr " " - -#: util/errors.c:98 -msgid "bad URI" -msgstr " URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr " URI" - -#: util/errors.c:100 -msgid "network error" -msgstr " " - -#: util/errors.c:102 -msgid "not encrypted" -msgstr " " - -#: util/errors.c:103 -msgid "not processed" -msgstr " " - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr " " - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr " " - -#: util/errors.c:107 -msgid "keyserver error" -msgstr " " - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr " bug ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr " \n" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr " `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr " `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' - \n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr ": random_seed \n" - -#: cipher/random.c:401 -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -": random_seed - \n" -"\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr " `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr ": random_seed\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr " `%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr " `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr " `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr ": !!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -" \n" -"\n" -" !!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -" bytes. \n" -" \n" -" ! ( %d bytes)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[]| " - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[]| " - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr " " - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr " " - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[]| " - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr " " - -#: g10/g10.c:315 -msgid "store only" -msgstr " " - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr " ()" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[]| " - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr " " - -#: g10/g10.c:320 -msgid "list keys" -msgstr " " - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr " " - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr " " - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr " (fingerprints)" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr " " - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr " " - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr " " - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr " " - -#: g10/g10.c:330 -msgid "sign a key" -msgstr " " - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr " " - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr " -" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr " -" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr " " - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr " " - -#: g10/g10.c:337 -msgid "export keys" -msgstr " " - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr " " - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr " " - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr " " - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr " " - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "/ " - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr " " - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr " " - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr " " - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr " " - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr " " - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr " " - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "- stdin" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "- stdin" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "| []| " - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -":\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr " ascii " - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|| " - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|| " - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr " " - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr " (user id) " - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N| N (0 )" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr " " - -#: g10/g10.c:392 -msgid "use as output file" -msgstr " " - -#: g10/g10.c:393 -msgid "verbose" -msgstr "" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr " " - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr " " - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr " v3 " - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr " v3 " - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr " v4 " - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr " v4 " - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr " MDC " - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr " MDC " - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr " " - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr " " - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr " gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr " batch: " - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr " " - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr " " - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr " " - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr " " - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr " " - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|| " - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|| " - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|| " - -#: g10/g10.c:421 -msgid "read options from file" -msgstr " " - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD| FD" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[]| " - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID| " - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|| " - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr " RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -" , OPENPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -" ,, PGP 2.x " - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N| N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "" -"|ONOMA| " - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|| " - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|| " - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|| " - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N| N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr " keyid " - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr " Photo ID" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr " Photo ID" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr " Photo ID" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"( man )\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -":\n" -"\n" -" -se -r Bob [] Bob\n" -" --clearsign [] \n" -" --detach-sign [] \n" -" --list-keys [] \n" -" --fingerprint [] (fingerprints)\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr " \n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr ": gpg [] [] (-h )" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -": gpg [] []\n" -", , \n" -" \n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -" :\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr ": gpg [] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr " \n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr " = \"%s\"\n" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr ": %s \"%s\"\n" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr ": %s \"%s\"\n" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "" -": %s \"%s\"\n" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr ": %s \"%s\"\n" - -#: g10/g10.c:1168 -#, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr ": `%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr ": `%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr " `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" -" \"%s\" \n" -" \n" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr " %s \n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr " URI \n" - -#: g10/g10.c:1550 -#, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s:%d: \n" - -#: g10/g10.c:1553 -msgid "invalid import options\n" -msgstr " \n" - -#: g10/g10.c:1560 -#, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s:%d: \n" - -#: g10/g10.c:1563 -msgid "invalid export options\n" -msgstr " \n" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr " exec-path %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr ": core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr ": %s %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr ": %s !\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr " %s %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr " %s %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -" --pgp2 \n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" -" --pgp2 " -"\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr " ( pipes) --pgp2.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" -" --pgp2 . IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr " %s\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr " \n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr " \n" - -#: g10/g10.c:1830 -msgid "selected certification digest algorithm is invalid\n" -msgstr "" -" \n" -" \n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr " %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth 1 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr ": S2K (0) \n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr " S2K; 0, 1 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr " default-check-level 0, 1, 2, 3\n" - -#: g10/g10.c:1868 -msgid "invalid default preferences\n" -msgstr " \n" - -#: g10/g10.c:1876 -msgid "invalid personal cipher preferences\n" -msgstr " \n" - -#: g10/g10.c:1880 -msgid "invalid personal digest preferences\n" -msgstr " \n" - -#: g10/g10.c:1884 -msgid "invalid personal compress preferences\n" -msgstr " \n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr " TrustDB: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" -": (-r) \n" -" \n" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [ ]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [ ]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [ ]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [ ]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [ ]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [ ]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [ ]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [ ]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key user-id" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key user-id" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key user-id" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key user-id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key user-id []" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr " %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [user-id] []" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr " : %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr " : %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr " hash `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[ ]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr " ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr " `%s'\n" - -#: g10/g10.c:2691 -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -" " -" '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr " control\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr " URL \n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr " URL \n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr ": %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr " : " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr " : " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr " clearsig\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr " \n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr " dash escaped : " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr " :" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr " radix64 %02x \n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr " ( CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr " ( CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr " CRC\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr " CRC: %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr " ( railer)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr " trailer\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr " OpenPGP .\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr " : %d \n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -", , - " -" MTA\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr " " - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr " " - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr " " - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr " " - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr " User ID " - -#: g10/pkclist.c:73 -msgid "reason for revocation: " -msgstr " :" - -#: g10/pkclist.c:90 -msgid "revocation comment: " -msgstr " :" - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -" :\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -" \n" -", ( \n" -" passports fingerprints ...);\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = \n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = \n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = \n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = \n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = \n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = \n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = \n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = \n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = \n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr " ; " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr " ; " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr " :\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr " %08lX: !\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr " ; " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr " %08lX: !\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: \n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: .\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: \n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: \n" -" \n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr " \n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr " \n" - -#: g10/pkclist.c:513 -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -" \n" -" user ID. ** , \n" -" \n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr ": !\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr ": !\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " .\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "" -": !\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr ": .\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr ": !\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "" -": " -"!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " .\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr ": !\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " .\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -": \n" -" !\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " .\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: : %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: : \n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr " user ID. ( \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -" user ID. : " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr " user ID.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "" -": \n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr " .\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr ": \n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr " `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: : .\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr " \n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr " %c%lu \n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr " %c%lu \n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr " `%c' \n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr " \"\" \n" - -#: g10/keygen.c:524 -msgid "writing direct signature\n" -msgstr " \n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr " -\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr " \"\" \n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr " , %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr " %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr " :\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA ElGamal ()\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA ( )\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal ( )\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal ( )\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA ( )\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA ( )\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA ( )\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr " ; " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" -" - ; " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr " .\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -" %s keypair.\n" -" 768 bits\n" -" 1024 bits\n" -" 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr " ; (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr " DSA 512 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "" -" , 1024 RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "" -" , 768 " -".\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "" -" , %d " -".\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -" 2048 \n" -" !\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr " ; " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -", ' \n" -" !\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr " %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr " %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -" .\n" -" 0 = \n" -" = n \n" -" w = n \n" -" m = n \n" -" y = n \n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -" .\n" -" 0 = \n" -" = n \n" -" w = n \n" -" m = n \n" -" y = n \n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr " ; (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr " ; (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr " \n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr " %s \n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr " %s %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -" 2038.\n" -", 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr " (y/n); " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -" User-ID . " -"\n" -" user-id , Email :\n" -" \"Nikolaoy Nikos (toy Ioanni) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr " : " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr " \n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr " \n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr " 5 \n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr " Email: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr " Email\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr ": " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr " \n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr " `%s' .\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -" USER-ID:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr " email \n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoQq" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr " (N), (C), (E)mail (Q); " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr " (N), (C), (E)mail (O)/(Q); " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr ", \n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -" .\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr " . " - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -" - ** !\n" -" . \n" -" , \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -" bytes. \n" -" (, , \n" -" ) . \n" -" .\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr " DSA 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr " .\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr " `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr " `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr " : %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr " : %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr " .\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr " .\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -" " -".\n" -" \"--edit-key\" \n" -" .\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr " : %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -" %lu ( \n" -" )\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -" %lu ( \n" -" )\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "" -": v3 \n" -" OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr " ; " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output \n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: : %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr " : %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr " ESK S2K\n" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' \n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: : \n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -" RSA 2048 bit --" -"pgp2\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr " `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -" IDEA " -".\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" -" %s (%d) \n" -" \n" - -#: g10/encode.c:558 g10/sign.c:758 -#, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "" -" %s (%d) \n" -" \n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr " %s %s.\n" - -#: g10/encode.c:735 -#, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s : \"%s\"\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr " '%s' : %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr " : %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr " %08lX: rfc2440 - \n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr " %08lX: - \n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr " %08lX: PGP 2.x - \n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr ": \n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr " pk cache - \n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[User id ]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -" %08lX --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr " %08lX %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr " %08lX: - \n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr " %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu \n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " user ID: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " : %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " user ID: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:313 -#, c-format -msgid " not imported: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr " %08lX: user ID\n" - -#: g10/import.c:597 -#, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr " %08lX: HKP\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr " %08lX: - user ID '%s'\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr " %08lX: user ID\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr " \n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr " %08lX: : %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr " %08lX: - \n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr " : %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr " `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/import.c:663 -#, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr " %08lX: \"%s\" \n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr " %08lX: \n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr " %08lX: : %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr " %08lX: : %s\n" - -#: g10/import.c:740 -#, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr " %08lX: \"%s\" 1 user ID\n" - -#: g10/import.c:743 -#, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr " %08lX: \"%s\" %d user ID\n" - -#: g10/import.c:746 -#, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr " %08lX: \"%s\" 1 \n" - -#: g10/import.c:749 -#, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr " %08lX: \"%s\" %d \n" - -#: g10/import.c:752 -#, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr " %08lX: \"%s\" 1 \n" - -#: g10/import.c:755 -#, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr " %08lX: \"%s\" %d \n" - -#: g10/import.c:774 -#, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr " %08lX: \"%s\" \n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr " : %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr " %08lX: \n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr " %08lX: \n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr " %08lX: : %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -" %08lX: - " -"\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr " %08lX: : %s - \n" - -#: g10/import.c:969 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr " %08lX: \"%s\" \n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr " %08lX: user ID \n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -" %08lX: user id \"%" -"s\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr " %08lX: - user id \"%s\"\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr " %08lX: \n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr " %08lX: \n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr " %08lX: \n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr " %08lX: \n" - -#: g10/import.c:1088 -#, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr " %08lX: \n" - -#: g10/import.c:1097 -#, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr " %08lX: \n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr " %08lX: \n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr " %08lX: user ID '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr " %08lX: \n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr " %08lX: ( %02x) - \n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "" -" %08lX: - \n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr " %08lX: : %s - \n" - -#: g10/import.c:1232 -#, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "" -" %08lX: - \n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr " %08lX: user ID - \n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -": %08lX : %" -"08lX\n" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -": %08lX : %08lX\n" -" .\n" - -#: g10/import.c:1460 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr " %08lX: \"%s\" \n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr " %08lX: \n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[-]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 \n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d \n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 \n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d \n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 \n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d \n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 user ID -\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d user ID -\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr " user ID \"%s\" ." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr " ; (y/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " .\n" - -#: g10/keyedit.c:380 -#, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr ": user ID \"%s\" -.\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -" - \"%s\"\n" -" PGP 2.x.\n" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr " OpenPGP -; (y/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -" \"%s\"\n" -" .\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr " ; (y/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr " %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr " !" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr " %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr " ; (Y/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -" OpenPGP PGP 2.x " -" --pgp2.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr " PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -" \n" -" ; " -"\"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) .%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) .%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) .%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) .%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -" \n" -" : \"" - -#: g10/keyedit.c:604 -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "" -"\n" -" -.\n" - -#: g10/keyedit.c:608 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -": -.\n" - -#: g10/keyedit.c:613 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -": -.\n" -"\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -" -.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -" -.\n" -"\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -" .\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -" .\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -" .\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr " ; " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr " : %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr " .\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr " .\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr " .\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr " :%s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -" .\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr " - ** !\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr " ; " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr " \n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr " " - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr " " - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr " " - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr " fingerprint" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr " user ID" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr " user ID N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr " N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr " " - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr " " - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr " " - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr " -" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr " -" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr " user ID" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr " photo ID" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr " user ID" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr " " - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr " " - -#: g10/keyedit.c:926 -msgid "addrevoker" -msgstr "addrevoker" - -#: g10/keyedit.c:926 -msgid "add a revocation key" -msgstr " " - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr " " - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr " " - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr " user ID " - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr " " - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr " ()" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr " ()" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr " " - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr " " - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr " " - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr " " - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr " " - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr " " - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr " " - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr " " - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr " photo ID" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr " (batchmode)\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr " .\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr " .\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr " \"toggle\" .\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr " ." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr " user ID; " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr ": user ID \n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr " %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr " user ID.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr " user ID!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr " user ID; " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr " user ID; " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr " .\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr " ; " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr " ; " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr " ; " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr " ; " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -" user ID; " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr " ;" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr " ; " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr " ; " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr " : %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr " : %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr " .\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr " ( \"help\")\n" - -#: g10/keyedit.c:1750 -#, c-format -msgid "This key may be revoked by %s key " -msgstr " %s " - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " ()" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX : %s : %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " : %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr " " - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! : %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- \n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? : %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr " user ID PGP 2.x.\n" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -" \n" -" .\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -": PGP2. photo ID\n" -" PGP .\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr " ; (y/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr " photo ID PGP2.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr " ; (y/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr " ; (y/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr " ; (y/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr " -; (y/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr " %d .\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr " %d .\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr " .\n" - -#: g10/keyedit.c:2281 -msgid "Enter the user ID of the designated revoker: " -msgstr " user ID : " - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" -" PGP 2.x, \n" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" -" \n" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr " .\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr " .\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr " .\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr " .\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr " v3 \n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr " \n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr " user ID.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr " v3 - user id \"%s\"\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr " user ID %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr " %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "user ID: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -" %08lX %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -" %08lX %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr " %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr " ; " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr " ; (y/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr " user ID:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " %08lX %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " %08lX %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr " :\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " %08lX %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (-)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr " ; (y/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr " \n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr " %s photo ID %ld 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -msgid "Critical signature policy: " -msgstr " : " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr " : " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr ": \n" - -#: g10/keylist.c:127 -msgid "Critical signature notation: " -msgstr " : " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr " : " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr " " - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [: %s]" - -#: g10/keylist.c:1001 -msgid "Primary key fingerprint:" -msgstr " :" - -#: g10/keylist.c:1003 -msgid " Subkey fingerprint:" -msgstr " :" - -#: g10/keylist.c:1010 -msgid " Primary key fingerprint:" -msgstr " :" - -#: g10/keylist.c:1012 -msgid " Subkey fingerprint:" -msgstr " :" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr " (%d)\n" - -#: g10/mainproc.c:258 -#, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr " hash `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s \n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr " %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr " %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr " : DEK\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr " %u-bit %s , ID %08lX, %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr " %s key, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr " : %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr " %s \n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" -" IDEA , \n" -"%s \n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr " OK\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr ": !\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr " : %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr ": \"----\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr " ='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr " - \"gpg --import\" \n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr ": " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr ": " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr " \n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr " \n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr " %.*s %s ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr " \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr " \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr " \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr " : %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr " \n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr " 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr " (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr " (root) proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr " core dump: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr " !\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -" . " -" !\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr " IDEA \n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -" http://www.gnupg.org/why-not-idea.html " -"\n" - -#: g10/misc.c:509 -#, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "%s:%d: \"%s\"\n" - -#: g10/misc.c:513 -#, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr ": \"%s\" \n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr " \"%s%s\" \n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr " %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr " %d bit\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr " gpg-agent \n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr " pid agent\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr " FD agent\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr " FD agent\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr " GPG_AGENT_INFO\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr " %d gpg-agent\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr " gpg-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr " agent - agent\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " ( , ID %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -" " -":\n" -"\"%.*s\"\n" -"%u-bit %s , ID %08lX, %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr " \n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr " \n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr " \n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr " agent\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr " \n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr " agent: agent 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -" \n" -" : \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bit %s , ID %08lX, %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr " \n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr " : " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr " : " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr " . \"--output\"\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr " .\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr " : " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr " stdin ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr " \n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr " `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr " %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr ", .\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr " DEK \n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr " %d%s \n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr ": %d \n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr ": %08lX %s\n" - -#: g10/pubkey-enc.c:249 -msgid "NOTE: key has been revoked" -msgstr ": " - -#: g10/hkp.c:71 -#, c-format -msgid "requesting key %08lX from %s\n" -msgstr " %08lX %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr " : %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr " `%s' (=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr " `%s': =%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr " HKP \n" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr " \"%s\" HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr " : %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr " \n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr " %d%s\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr " , " - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr ": - \n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -" 16-bit checksum \n" -" \n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr ": \n" - -#: g10/sig-check.c:215 -#, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -" , PGP, ElGamal " -"!\n" - -#: g10/sig-check.c:224 -#, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "" -" %08lX %lu \n" - -#: g10/sig-check.c:225 -#, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "" -" %08lX %lu \n" - -#: g10/sig-check.c:234 -#, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -" %08lX %lu ( \n" -" )\n" - -#: g10/sig-check.c:236 -#, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -" %08lX %lu ( \n" -" )\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr ": %08lX %s\n" - -#: g10/sig-check.c:348 -#, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr " %08lX bit\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -": %%- ( ).\n" -" .\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -": %%- url ( ).\n" -" .\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr " : %s\n" - -#: g10/sign.c:312 -#, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s : \"%s\"\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr ": `%s' \n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -" - PGP 2.x \n" -"--pgp2 \n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr " %s: %s\n" - -#: g10/sign.c:690 -#, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "" -" %s (%d) \n" -" \n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr ":" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -" PGP 2.x --pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%s \n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr " %d \n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr " %d \n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb rec %lu: lseek: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb rec %lu: write (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr " trustdb\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: !\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: (lock)\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: (lock)\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: : %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: trustdb\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: trustdb\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr ": trustdb \n" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: trustdb\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: hashtable: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "trustdb: lseek: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "trustdb: read (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: trustdb \n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: free : %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: dir : %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: : %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr " trustdb - \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' keyID\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr " %08lX: \n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr " %08lX trustdb\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -" %08lX: - " -"\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr " trust %lu, req %d: read : %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr " trust %lu %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr " trust %lu, %d: write : %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "trustdb: sync : %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr " trustdb\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr " trustdb %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr " trustdb\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr " %08lX : %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" -" %08lX\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr " %d =%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -" .\n" -" (.sig or .asc)\n" -" .\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr " %u LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -" - " -" RNG!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr " `%s': \n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr ": \n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -" `%s': PGP ElGamal " -" !\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr " `%s' . " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr " (y/N); " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: \n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr " " - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr " stdout\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr " `%s'\n" - -#: g10/openfile.c:326 -#, c-format -msgid "new configuration file `%s' created\n" -msgstr " `%s'\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: : %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: \n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -": \n" -" .\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr " \n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr " - \n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -" , " -" %d !\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr " DSA 160 bit hash\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "( )\n" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr " \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr " ; " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr " ! - ; " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr " block : %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr " -\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr " \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "" -" \"--delete-secret-key\" .\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -" . \n" -" . -" -",\n" -" ( ) -." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -" -, GnuPG " -"\n" -" - \n" -" . \"yes\" () " -"\n" -" \n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" -" , \"yes\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -" , \"yes" -"\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "" -" user ID ." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -" .\n" -"\n" -"DSA ( DSS) \n" -" . \n" -" DSA \n" -" ElGamal.\n" -"\n" -"ElGamal -\n" -". OpenPGP \"\" :\n" -" - --, \n" -" , \n" -" .\n" -" , OpenPGP \n" -" ().\n" -"\n" -" () \n" -". -\n" -" ElGamal ." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -" RFC2440 \n" -" \n" -" ." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" -", \n" -" . \n" -" . ." - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr " " - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr " \"yes\"() \"no\"()" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -" .\n" -" ISO (YYYY-MM-DD) \n" -" - \n" -" ." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr " " - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr " email ()" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr " " - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N .\n" -"C .\n" -"E email.\n" -"O .\n" -"Q ." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "" -" \"yes\" ( \"y\") " -"." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -" user ID , \n" -" user ID. " -" , .\n" -"\n" -"\"0\" " -".\n" -"\"1\" " -"\n" -" , . \n" -" \"\" .\n" -"\n" -"\"2\" . " -"\n" -" \n" -" user ID photo ID.\n" -"\n" -"\"3\" . , " -"\n" -" \n" -" \"\" photo ID " -"\n" -" ." -".\n" -" , , .\n" -"\n" -" \"\" 2 3 \n" -"** . \n" -" \"\" \"\" " -".\n" -"\n" -" , \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr " \"yes\" user ID" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -" \"yes\" \n" -" user ID. !" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr " \"yes\" " - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -" . \n" -" \n" -" \n" -" ." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -" \n" -". , \n" -" \n" -" ." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -" . \n" -" ." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -" user ID . \n" -" . \n" -" GnuPG \n" -" . - \n" -" ." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -" user ID ( )\n" -" . \n" -"- 1 .\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr " ߷ \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr " , ." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr " " - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr " \"yes\" " - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -" . RETURN\n" -" ' ( ) ." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -" . \n" -", :\n" -" \" \"\n" -" \n" -" .\n" -" \" \"\n" -" .\n" -" \" \"\n" -" .\n" -" \" user ID \"\n" -" user ID \n" -" . email.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -" , \n" -" .\n" -" . \n" -" .\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr " " - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr " `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr " `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr " `%s' \n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr " cache : %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr ": 2 .\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s \n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s \n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr " \"\" \n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr " `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu (%lu )\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu (%lu )\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: \n" diff --git a/po/eo.po b/po/eo.po deleted file mode 100644 index 6f797ec2e..000000000 --- a/po/eo.po +++ /dev/null @@ -1,4938 +0,0 @@ -# Mesaoj por la programo GnuPG -# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. -# Edmund GRIMLEY EVANS , 2000-2002. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.6d\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-04-14 14:33+0100\n" -"Last-Translator: Edmund GRIMLEY EVANS \n" -"Language-Team: Esperanto \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-3\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Averto: uzas malsekuran memoron!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "bonvolu vidi http://www.gnupg.org/faq.html por pliaj informoj\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "operacio ne eblas sen sekura memoro kun komenca valoro\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(eble vi uzis la malustan programon por i tiu tasko)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "jes" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "jJ" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "ne" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "fini" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "fF" - -#: util/errors.c:54 -msgid "general error" -msgstr "enerala eraro" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "nekonata paketo-speco" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "nekonata versio" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "nekonata publiklosila metodo" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "nekonata kompendi-metodo" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "malbona publika losilo" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "malbona sekreta losilo" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "malbona subskribo" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "eraro en kontrolsumo" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "malbona pasfrazo" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "publika losilo ne trovita" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "nekonata ifrad-metodo" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "ne povas malfermi la losilaron" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "nevalida paketo" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "nevalida kiraso" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "uzantidentigilo ne ekzistas" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "sekreta losilo ne havebla" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "malusta sekreta losilo uzata" - -#: util/errors.c:72 -msgid "not supported" -msgstr "ne realigita" - -#: util/errors.c:73 -msgid "bad key" -msgstr "malbona losilo" - -#: util/errors.c:74 -msgid "file read error" -msgstr "legeraro e dosiero" - -#: util/errors.c:75 -msgid "file write error" -msgstr "skriberaro e dosiero" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "nekonata densig-metodo" - -#: util/errors.c:77 -msgid "file open error" -msgstr "eraro e malfermo de dosiero" - -#: util/errors.c:78 -msgid "file create error" -msgstr "eraro e kreo de dosiero" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "nevalida pasfrazo" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "nerealigita publiklosila metodo" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "nerealigita ifrad-metodo" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "nekonata klaso de subskribo" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "eraro en fido-datenaro" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "malbona MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "trafis rimedolimon" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "nevalida losilaro" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "malbona atestilo" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "misformita uzantidentigilo" - -#: util/errors.c:89 -msgid "file close error" -msgstr "eraro e fermo de dosiero" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "eraro e renomado de dosiero" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "eraro e forvio de dosiero" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "neatendita dateno" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "malkongruo de tempostampoj" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "neuzebla publiklosila metodo" - -#: util/errors.c:95 -msgid "file exists" -msgstr "dosiero ekzistas" - -#: util/errors.c:96 -msgid "weak key" -msgstr "malforta losilo" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "nevalida argumento" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "malbona URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "nerealigita URI" - -#: util/errors.c:100 -msgid "network error" -msgstr "reteraro" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "ne ifrita" - -#: util/errors.c:103 -msgid "not processed" -msgstr "ne traktita" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "neuzebla publika losilo" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "neuzebla sekreta losilo" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "losilservila eraro" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... i tio estas cimo (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "vi trovis cimon ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "ne povas malfermi '%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "ne povas stat-i '%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "'%s' ne estas normala dosiero - ignorita\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "noto: dosiero random_seed estas malplena\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "averto: nevalida grando de la dosiero random_seen - ne uzita\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "ne povas legi '%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "noto: dosiero random_seed ne aktualigita\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "ne povas krei '%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "ne povas skribi '%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "ne povas fermi '%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "AVERTO: uzas malsekuran stokastilon!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"La kvazastokastilo estas nur simpla protezo, por ke la\n" -"programo entute ruliu; i neniel estas forta stokastilo!\n" -"\n" -"NE UZU DATENOJN KREITAJN DE I TIU PROGRAMO!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Nesufie da stokastaj datenoj. Bonvolu fari ion por ebligi al la\n" -"mastruma sistemo kolekti pli da entropio! (Mankas %d bitokoj)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Komandoj:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[dosiero]|fari subskribon" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[dosiero]|fari klartekstan subskribon" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "fari apartan subskribon" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "ifri datenojn" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[dosieroj]|ifri dosierojn" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "ifri nur kun simetria ifro" - -#: g10/g10.c:315 -msgid "store only" -msgstr "nur skribi" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "malifri datenojn (implicita elekto)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[dosieroj]|malifri dosierojn" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "kontroli subskribon" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "listigi losilojn" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "listigi losilojn kaj subskribojn" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "kontroli losilsubskribojn" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "listigi losilojn kaj fingropurojn" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "listigi sekretajn losilojn" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "krei novan losilparon" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "forigi losilojn de la publika losilaro" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "forigi losilojn de la sekreta losilaro" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "subskribi losilon" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "subskribi losilon loke" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "subskribi losilon nerevokeble" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "subskribi losilon loke kaj nerevokeble" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "subskribi a redakti losilon" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "krei revokatestilon" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "eksporti losilojn" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "eksporti losilojn al losilservilo" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importi losilojn de losilservilo" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "seri losilojn e losilservilo" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "aktualigi iujn losilojn de losilservilo" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importi/kunfandi losilojn" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "listigi nur la sinsekvon de paketoj" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "eksporti la posedantofido-valorojn" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importi posedantofido-valorojn" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "aktualigi la fido-datenaron" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "senintervena aktualigo de fido-datenaro" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "ripari fuitan fido-datenaron" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "elkirasigi dosieron a la normalan enigon" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "enkirasigi dosieron a la normalan enigon" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|metodo [dosieroj]|presi mesao-kompendiojn" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opcioj:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "krei eligon en askia kiraso" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOMO|ifri por NOMO" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOMO|uzi NOMOn kiel implicitan ricevonton" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "uzi la implicitan losilon kiel implicitan ricevonton" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "uzi i tiun uzantidentigilon por subskribi a malifri" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|difini densig-nivelon N (0=nenia)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "uzi tekstan reimon" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "uzi dosieron por eligo" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "detala eligo" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "iom malpli da informoj" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "tute ne uzi la terminalon" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "devigi v3-subskribojn" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "ne devigi v3-subskribojn" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "devigi v4-subskribojn" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "ne devigi v4-losilsubskribojn" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "iam uzi sigelon (MDC) por ifrado" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "neniam uzi MDC por ifrado" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "fari neniajn anojn" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "uzi gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "neinteraga reimo: neniam demandi" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "supozi \"jes\" e la plej multaj demandoj" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "supozi \"ne\" e la plej multaj demandoj" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "aldoni i tiun losilaron al la listo de losilaroj" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "aldoni i tiun sekretan losilaron al la listo" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "montri, en kiu losilaro estas listigita losilo" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOMO|uzi NOMOn kiel la implicitan sekretan losilon" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|SERVILO|uzi i tiun losilservilon por seri losilojn" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NOMO|difini NOMOn kiel la signaron de la terminalo" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "legi la opciojn el dosiero" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|skribi statusinformojn al FD (dosierpriskribilo)" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[dosiero]|skribi statusinformojn al dosiero" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID|fidi i tiun losilon absolute" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|DOSIERO|legi aldonan bibliotekon DOSIERO" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "imiti la reimon priskribitan en RFC 1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "alti iujn paket-, ifrad- kaj kompendi-opciojn al OpenPGP-konduto" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "alti iujn paket-, ifrad- kaj kompendi-opciojn al PGP-2.x-konduto" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|uzi pasfraz-reimon N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NOMO|uzi kompendi-metodon NOMO por pasfrazoj" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NOMO|uzi ifrad-metodon NOMO por pasfrazoj" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOMO|uzi ifrad-metodon NOMO" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOMO|uzi kompendi-metodon NOMO" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|uzi densig-metodon N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "forigi la losilidentigilon de ifritaj paketoj" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Montri Foto-Identigilojn" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Ne montri Foto-Identigilojn" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Agordi komandlinion por montri Foto-Identigilojn" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Vidu la manpaon por kompleta listo de iuj komandoj kaj opcioj)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Ekzemploj:\n" -"\n" -" -se -r Bob [dosiero] subskribi kaj ifri por uzanto Bob\n" -" --clearsign [dosiero] fari klartekstan subskribon\n" -" --detach-sign [dosiero] fari apartan subskribon\n" -" --list-keys [nomoj] montri losilojn\n" -" --fingerprint [nomoj] montri fingropurojn\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Bonvolu raporti cimojn al .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Uzado: gpg [opcioj] [dosieroj] (-h por helpo)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintakso: gpg [opcioj] [dosieroj]\n" -"subskribi, kontroli, ifri a malifri\n" -"implicita operacio dependas de la enigataj datenoj\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Realigitaj metodoj:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uzado: gpg [opcioj] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "malkongruaj komandoj\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Averto: malsekura posedeco sur %s \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Averto: malsekuraj permesoj sur %s \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Averto: malsekura posedeco sur %s \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Averto: malsekuraj permesoj sur %s \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTO: mankas implicita opcio-dosiero '%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTO: mankas implicita opcio-dosiero '%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "opcio-dosiero '%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "legas opciojn el '%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s ne estas valida signaro\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "ne povis analizi URI de losilservilo\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "AVERTO: '%s' estas malplena dosiero\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "nevalida kiraso" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "AVERTO: '%s' estas malplena dosiero\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "nevalida losilaro" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "AVERTO: programo povas krei core-dosieron!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "AVERTO: %s nuligas %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTO: %s ne estas por normala uzado!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s ne eblas kun %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s ne havas sencon kun %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "eblas fari nur apartajn kaj klartekstajn subskribojn kun --pgp2\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "ne eblas samtempe subskribi kaj ifri kun --pgp2\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "necesas uzi dosierojn (kaj ne tubon) kun --pgp2\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "ifri mesaon kun --pgp2 postulas la ifron IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "i tiu mesao povas ne esti uzebla de PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "elektita ifrad-metodo ne validas\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "elektita kompendi-metodo ne validas\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "elektita kompendi-metodo ne validas\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "la densig-metodo devas esti inter %d kaj %d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed devas esti pli granda ol 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed devas esti pli granda ol 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth devas esti inter 1 kaj 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTO: simpla S2K-reimo (0) estas forte malrekomendata\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "nevalida S2K-reimo; devas esti 0, 1 a 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "nevalida default-check-level; devas esti 0, 1, 2 a 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "nevalidaj preferoj\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "nevalidaj preferoj\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "nevalidaj preferoj\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "nevalidaj preferoj\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "malsukcesis doni komencajn valorojn al fido-datenaro: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [dosiero]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [dosiero]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [dosiero]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [dosiero]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [dosiero]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [dosiero]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [dosiero]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [dosiero]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key uzantidentigilo" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key uzantidentigilo" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key uzantidentigilo" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key uzantidentigilo" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key uzantidentigilo [komandoj]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "ne povas malfermi %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [uzantidentigilo] [losilaro]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "elkirasigo malsukcesis: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "enkirasigo malsukcesis: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "nevalida kompendi-metodo '%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[dosiero]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Ektajpu vian mesaon ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "ne povas malfermi '%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"notacia nomo devas enhavi nur literojn, ciferojn, punktojn a substrekojn " -"kaj fini per '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "notacia valoro ne povas enhavi stirsignojn\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "la donita gvidlinia URL por atestado ne validas\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "la donita gvidlinia URL por subskriboj ne validas\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "kiraso: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "nevalida kirasoapo: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "kirasoapo: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "nevalida apo de klarteksta subskribo\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "ingitaj klartekstaj subskriboj\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "nevalida strek-eskapita linio: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "neatendita kiraso:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "nevalida signo %02x en bazo 64 ignorita\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "tro frua dosierfino (nenia CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "tro frua dosierfino (en CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "misformita CRC\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "CRC-eraro; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "tro frua dosierfino (en vosto)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "eraro en vostolinio\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "validaj OpenPGP-datenoj ne trovitaj.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "nevalida kiraso: linio pli longa ol %d signojn\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"quoted-printable-signo en kiraso - verajne cima pototransendilo estis " -"uzata\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Nenia kialo specifita" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "losilo estas anstataigita." - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "losilo estas kompromitita" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "losilo estas ne plu uzata" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Uzantidentigilo ne plu validas" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Kialo por revoko: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Komento pri revoko: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMfFsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Nenia fidovaloro atribuita al:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Bonvolu decidi, kiagrade vi fidas al i tiu uzanto uste\n" -"kontroli la losilojn de aliaj uzantoj (rigardante pasportojn,\n" -"kontrolante fingrospurojn el diversaj fontoj ...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Ne scias\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = Ni NE fidas i tiun losilon\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Mi fidas iomete\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Mi plene fidas\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Mi fidas absolute\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = bonvolu montri pli da informoj\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = reen al la efmenuo\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = supersalti i tiun losilon\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " f = fini\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Via decido? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "u vi vere volas ani i tiun losilon al absoluta fido? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Atestiloj, kiuj kondukas al absolute fidata losilo:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "losilo %08lX: losilo estas revokita!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "u tamen uzi i tiun losilon? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "losilo %08lX: sublosilo estas revokita!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: losilo eksvalidiis\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Estas nenia indiko, ke i tiu losilo vere apartenas al la posedanto\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Ni NE fidas i tiun losilon\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Ne estas certe, ke i tiu losilo vere apartenas al la posedanto,\n" -"sed i tamen estas akceptita\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "i tiu losilo verajne apartenas al la posedanto\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "i tiu losilo apartenas al ni\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"NE estas certe, ke la losilo apartenas al sia posedanto.\n" -"Se vi *vere* scias, kion vi faras, vi povas respondi al\n" -"la sekva demando per \"jes\"\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "AVERTO: Uzas nefidatan losilon!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "AVERTO: i tiu losilo estas revokita de sia posedanto!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Tio povas signifi, ke la subskribo estas falsa.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "AVERTO: i tiu sublosilo estas revokita de sia posedanto!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Noto: i tiu losilo estas malaltita.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Noto: i tiu losilo eksvalidiis!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "AVERTO: i tiu losilo ne estas atestita kun fidata subskribo!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Estas nenia indiko, ke la subskribo apartenas al la posedanto.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "AVERTO: Ni NE fidas i tiun losilon!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " La subskribo verajne estas FALSA.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"AVERTO: i tiu losilo ne estas atestita kun sufie fidataj subskriboj!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Ne estas certe, ke la subskribo apartenas al la posedanto.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: ignorita: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: ignorita: publika losilo jam eestas\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Vi ne specifis uzantidentigilon. (Vi povas uzi \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Donu la uzantidentigilon. Finu per malplena linio: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Uzantidentigilo ne ekzistas.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "ignorita: publika losilo jam difinita kiel implicita ricevonto\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Publika losilo estas malaltita.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "ignorita: publika losilo jam agordita\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "nekonata implicita ricevonto '%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: ignorita: publika losilo estas malaltita\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "mankas validaj adresitoj\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "prefero %c%lu ne estas valida\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "prefero %c%lu ripetita\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "tro da '%c'-preferoj\n" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "nevalida signo en signoeno\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "skribas mem-subskribon\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "skribas mem-subskribon\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "skribas losilbindan subskribon\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "losilgrando nevalida; uzas %u bitojn\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "losilgrando rondigita is %u bitoj\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Bonvolu elekti, kian losilon vi deziras:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA kaj ElGamal (implicita elekto)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (nur subskribi)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (nur ifri)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (subskribi kaj ifri)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (nur subskribi)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (nur ifri)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (subskribi kaj ifri)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Via elekto? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Uzado de i tiu algoritmo estas malrekomendata - u tamen krei? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Nevalida elekto.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Kreos novan %s-losilparon.\n" -" minimuma losilgrando estas 768 bitoj\n" -" implicita losilgrando estas 1024 bitoj\n" -" plej granda rekomendata losilgrando estas 2048 bitoj\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Kiun losilgrandon vi deziras? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA permesas losilgrandon nur inter 512 kaj 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "losilgrando tro malgranda; 1024 estas plej eta valoro por RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "losilgrando tro malgranda; 768 estas plej eta permesata valoro.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "losilgrando tro granda; %d estas plej granda permesata valoro.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"losilgrandoj pli grandaj ol 2048 ne estas rekomendataj,\n" -"ar la komputado daras TRE longe!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "u vi estas certa, ke vi deziras i tiun losilgrandon? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Bone, sed pripensu, ke la elradiado de viaj ekrano kaj klavaro estas tre " -"facile kaptebla!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Petita losilgrando estas %u bitoj\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "rondigita is %u bitoj\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Bonvolu specifi, kiom longe la losilo validu.\n" -" 0 = losilo neniam eksvalidios\n" -" = losilo eksvalidios post n tagoj\n" -" w = losilo eksvalidios post n semajnoj\n" -" m = losilo eksvalidios post n monatoj\n" -" y = losilo eksvalidios post n jaroj\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Bonvolu specifi, kiom longe la losilo validu.\n" -" 0 = losilo neniam eksvalidios\n" -" = losilo eksvalidios post n tagoj\n" -" w = losilo eksvalidios post n semajnoj\n" -" m = losilo eksvalidios post n monatoj\n" -" y = losilo eksvalidios post n jaroj\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "losilo validu ...? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "losilo validu por ...? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "nevalida valoro\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s neniam eksvalidios\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s eksvalidios je %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Via sistemo ne povas montri datojn post 2038.\n" -"Tamen, i estos uste traktata is 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "u tio estas usta (j/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Vi bezonas uzantidentigilon por identigi vian losilon; la programo\n" -"konstruas la uzantidentigilon el Vera Nomo, Komento kaj Retadreso, jene:\n" -" \"Heinrich Heine (la poeto) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Vera nomo: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Nevalida signo en nomo\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Nomo ne povas komencii per cifero\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Nomo devas havi almena 5 signojn\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Retadreso: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Nevalida retadreso\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Komento: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Nevalida signo en komento\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Vi uzas la signaron '%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Vi elektis i tiun uzantidentigilon:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Bonvolu ne meti la retadreson en la veran nomon a la komenton\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnKkAaBbFf" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "anu (N)omon, (K)omenton, (A)adreson, a (F)ini? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "anu (N)omon, (K)omenton, (A)adreson, a (B)one/(F)ini? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Bonvolu korekti la eraron unue\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Vi bezonas pasfrazon por protekti vian sekretan losilon.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "la pasfrazo ne estis uste ripetita; provu denove" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Vi ne deziras pasfrazon; tio verajne estas *malbona* ideo!\n" -"Mi tamen faros tiel. Vi povos iam ajn ani vian pasfrazon,\n" -"uzante i tiun programon kun la opcio \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Ne devas krei multe da stokastaj datenoj. Estas konsilinde fari ion\n" -"alian (tajpi e la klavaro, movi la muson, uzi la diskojn) dum la\n" -"kreado de la primoj; tio donas al la stokastilo pli bonan ancon\n" -"akiri sufie da entropio.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSA-losilparo havos 1024 bitojn.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Kreado de losiloj nuligita.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "skribas publikan losilon al '%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "skribas sekretan losilon al '%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "neniu skribebla publika losilaro trovita: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "neniu skribebla sekreta losilaro trovita: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "eraro dum skribado de publika losilaro '%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "eraro dum skribado de sekreta losilaro '%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "publika kaj sekreta losiloj kreitaj kaj subskribitaj.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "losilo markita kiel absolute fidata.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Notu, ke i tiu losilo ne estas uzebla por ifrado. Vi eble volos\n" -"uzi la komandon \"--edit-key\" por krei flankan losilon por tiu celo.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Kreado de losiloj malsukcesis: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"losilo estis kreita %lu sekundon en la estonteco (tempotordo a " -"horloeraro)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"losilo estis kreita %lu sekundojn en la estonteco (tempotordo a " -"horloeraro)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "NOTO: krei sublosilojn por v3-losiloj ne estas OpenPGP-kongrue\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "u vere krei? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output ne funkcias por i tiu komando\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: ne povas malfermi: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "eraro dum kreado de pasfrazo: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "'%s' jam densigita\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: AVERTO: malplena dosiero\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "eblas ifri nur per RSA-losiloj de maksimume 2048 bitoj kun --pgp2\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "legas el '%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "ne povas uzi la ifron IDEA por iuj losiloj, al kiuj vi ifras.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTO: ifrad-metodo %d ne trovita en preferoj\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Tiu komando ne eblas en la reimo %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s-ifrita por: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "losilo '%s' ne trovita: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "eraro dum legado de losilbloko: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "losilo %08lX: ne estas RFC-2440-losilo - ignorita\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "losilo %08lX: ne protektita - ignorita\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "losilo %08lX: PGP-2.x-stila losilo - ignorita\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "AVERTO: nenio estis eksportita\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "tro da registroj en pk-staplo - malaltas\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Uzantidentigilo ne trovita]" - -#: g10/getkey.c:1438 -#, fuzzy, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "Nevalida losilo %08lX validigita per --always-trust\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "uzas flankan losilon %08lX anstata la efa losilo %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "losilo %08lX: sekreta losilo sen publika losilo - ignorita\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "ignoras blokon de speco %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu losiloj jam traktitaj\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "eraro dum legado de '%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr " Nombro traktita entute: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " ignoritaj novaj losiloj: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sen uzantidentigilo: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importitaj: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " neanitaj: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " novaj uzantidentigiloj: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " novaj sublosiloj: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " novaj subskriboj: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " novaj losilrevokoj: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " sekretaj losiloj legitaj: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "sekretaj losiloj importitaj: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "sekretaj losiloj neanitaj: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importitaj: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "losilo %08lX: mankas uzantidentigilo\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "losilo %08lX: mankas sublosilo por losilbindado\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "losilo %08lX: akceptis ne-mem-subskribitan uzantidentigilon '" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "losilo %08lX: mankas valida uzantidentigilo\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "tio povas esti kazata de mankanta mem-subskribo\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "losilo %08lX: publika losilo ne trovita: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "losilo %08lX: nova losilo - ignorita\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "neniu skribebla losilaro trovita: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "skribas al '%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "eraro dum skribado de losilaro '%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "losilo %08lX: publika losilo importita\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "losilo %08lX: diferencas de nia kopio\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "losilo %08lX: ne povas trovi originalan losilblokon: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "losilo %08lX: ne povas legi originalan losilblokon: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "losilo %08lX: 1 nova uzantidentigilo\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "losilo %08lX: %d novaj uzantidentigiloj\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "losilo %08lX: 1 nova subskribo\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "losilo %08lX: %d novaj subskriboj\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "losilo %08lX: 1 nova sublosilo\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "losilo %08lX: %d novaj sublosiloj\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "losilo %08lX: ne anita\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "mankas implicita sekreta losilaro: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "losilo %08lX: sekreta losilo importita\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "losilo %08lX: jam en sekreta losilaro\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "losilo %08lX: sekreta losilo ne trovita: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"losilo %08lX: publika losilo mankas - ne povas apliki revokatestilon\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "losilo %08lX: nevalida revokatestilo: %s - malakceptita\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "losilo %08lX: revokatestilo importita\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "losilo %08lX: mankas uzantidentigilo por subskribo\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "losilo %08lX: nerealigita publiklosila metodo\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "losilo %08lX: nevalida mem-subskribo\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "losilo %08lX: mankas sublosilo por losilbindado\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "losilo %08lX: nerealigita publiklosila metodo\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "losilo %08lX: nevalida sublosila bindado\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "losilo %08lX: nevalida sublosila bindado\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "losilo %08lX: mankas sublosilo por losilbindado\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "losilo %08lX.%lu: Valida sublosilrevoko\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "losilo %08lX: nevalida sublosila bindado\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "losilo %08lX: ignoris uzantidentigilon '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "losilo %08lX: ignoris sublosilon\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "losilo %08lX: neeksportebla subskribo (klaso %02x) - ignorita\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "losilo %08lX: revokatestilo en malusta loko - ignorita\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "losilo %08lX: nevalida revokatestilo: %s - ignorita\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "losilo %08lX: revokatestilo en malusta loko - ignorita\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "losilo %08lX: trovis ripetitan uzantidentigilon - kunfandita\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "losilo %08lX: revokatestilo aldonita\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "losilo %08lX: rekta losilsubskribo aldonita\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revoko]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[mem-subskribo]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 malbona subskribo\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d malbonaj subskriboj\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 subskribo ne kontrolita pro manko de losilo\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d subskriboj ne kontrolitaj pro manko de losiloj\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 subskribo ne kontrolita pro eraro\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d subskriboj ne kontrolitaj pro eraroj\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 uzantidentigilo sen valida mem-subskribo estis trovita\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d uzantidentigiloj sen valida mem-subskribo estis trovitaj\n" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Uzantidentigilo \"%s\" estas revokita.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "u vi estas certa, ke vi ankora volas subskribi in?\n" - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "AVERTO: '%s' estas malplena dosiero\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Via aktuala subskribo sur \"%s\"\n" -"estas loka subskribo.\n" -"\n" -"u vi volas igi in plena eksportebla subskribo?\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" -"Via aktuala subskribo sur \"%s\"\n" -"estas loka subskribo.\n" -"\n" -"u vi volas igi in plena eksportebla subskribo?\n" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, fuzzy, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Via aktuala subskribo sur \"%s\"\n" -"estas loka subskribo.\n" -"\n" -"u vi volas igi in plena eksportebla subskribo?\n" - -#: g10/keyedit.c:426 -#, fuzzy -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" -"Via aktuala subskribo sur \"%s\"\n" -"estas loka subskribo.\n" -"\n" -"u vi volas igi in plena eksportebla subskribo?\n" - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" jam estis %ssubskribita per losilo %08lX\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" jam estis %ssubskribita per losilo %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nenio por subskribi per losilo %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "i tiu losilo eksvalidiis!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "i tiu losilo eksvalidios je %s.\n" - -#: g10/keyedit.c:502 -#, fuzzy -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "u vi volas, ke via subskribo eksvalidiu je la sama tempo? (j/n) " - -#: g10/keyedit.c:535 -#, fuzzy -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "eblas subskribi nur per PGP-2.x-stilaj losiloj kun --pgp2\n" - -#: g10/keyedit.c:537 -#, fuzzy -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "i tiu mesao povas ne esti uzebla de PGP 2.x\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Kiom zorge vi kontrolis, ke la losilo, kiun vi subskribos, vere apartenas\n" -"al la supre nomita persono? Se vi ne scias la respondon, donu \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Mi ne respondas.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Mi tute ne kontrolis.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Mi malzorge kontrolis.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Mi tre zorge kontrolis.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"u vi estas tute certa, ke vi volas subskribi i tiun losilon\n" -"per via losilo: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "tio povas esti kazata de mankanta mem-subskribo\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"La subskribo estos markita kiel neeksportebla.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"La subskribo estos markita kiel nerevokebla.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"La subskribo estos markita kiel neeksportebla.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"La subskribo estos markita kiel nerevokebla.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Mi tute ne kontrolis i tiun losilon.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Mi malzorge kontrolis i tiun losilon.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Mi tre zorge kontrolis i tiun losilon.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "u vere subskribi? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "subskribado malsukcesis: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "i tiu losilo ne estas protektita.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Sekretaj partoj de efa losilo ne estas disponataj.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "losilo estas protektita.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Ne povas redakti i tiun losilon: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Donu la novan pasfrazon por i tiu sekreta losilo.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Vi ne deziras pasfrazon - tio verajne estas *malbona* ideo!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "u vi vere volas fari tion? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "movas losilsubskribon al la usta loko\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "forlasi i tiun menuon" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "f" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "skribi" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "skribi kaj fini" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "helpo" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "montri i tiun helpon" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fsp" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "montri fingrospuron" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "listo" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "listigi losilojn kaj uzantidentigilojn" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "elekti uzantidentigilon N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "losilo" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "elekti flankan losilon N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "kontroli" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "listigi subskribojn" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "k" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "subskribi" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "subskribi la losilon" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsub" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "subskribi la losilon loke" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsub" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "subskribi la losilon nerevokeble" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsub" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "subskribi la losilon loke kaj nerevokeble" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "spuri" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "aluid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "aldoni uzantidentigilon" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "alfoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "aldoni foto-identigilon" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "foruid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "forvii uzantidentigilon" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "forfoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "al" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "aldoni flankan losilon" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "for" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "forvii flankan losilon" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "revokita" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "aldoni flankan losilon" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "forsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "forvii subskribojn" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "eksval" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "ani la daton de eksvalidio" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "efa" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "marku uzantidentigilon kiel efan" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "alia" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "de sekreta a publika listo iri al la alia" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "a" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "listigi preferojn (spertula)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "monpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "listigi preferojn (detale)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "agpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "agordi liston de preferoj" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "aktpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "aktualigitaj preferoj" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "pasf" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "ani la pasfrazon" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "fido" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "ani la posedantofidon" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revoki subskribojn" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "rev" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revoki flankan losilon" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "el" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "malalti losilon" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "en" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "alti losilon" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "monfoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "montri foto-identigilon" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "ne povas fari tion en neinteraga reimo\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "eraro dum legado de sekreta losilbloko '%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Sekreta losilo estas havebla.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Komando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Bezonas la sekretan losilon por fari tion.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Bonvolu uzi la komandon \"toggle\" unue.\n" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "losilo estas revokita.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "u vere subskribi iujn uzantidentigilojn? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Sugesto: Elekti la uzantidentigilojn por subskribi\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Tiu komando ne eblas en la reimo %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Vi devas elekti almena unu uzantidentigilon.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Vi ne povas forvii la lastan uzantidentigilon!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "u vere forigi iujn elektitajn uzantidentigilojn? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "u vere forigi i tiun uzantidentigilon? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Vi devas elekti almena unu losilon.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "u vi vere volas forvii la elektitajn losilojn? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "u vi vere volas forvii i tiun losilon? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "u vi vere volas revoki la elektitajn losilojn? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "u vi vere volas revoki i tiun losilon? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "u vere aktualigi la preferojn por la elektitaj uzantidentigiloj? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "u vere aktualigi la preferojn? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "u skribi anojn? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "u fini sen skribi anojn? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "aktualigo malsukcesis: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "aktualigo de sekreto malsukcesis: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "losilo ne anita, do aktualigo ne necesas.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Nevalida komando (provu per \"helpo\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "i tiu losilo estas revokebla per %s losilo %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (sentema)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX kreita: %s eksvalidios: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " fido: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "i tiu losilo estas malaltita" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! sublosilo estas revokita: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- falsita revoko trovita\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problemo en kontrolo de revoko: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"AVERTO: i tiu estas PGP2-stila losilo. Aldono de foto-identigilo eble\n" -" kazos, ke iuj versioj de PGP malakceptos la losilon.\n" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "u vi estas certa, ke vi ankora volas aldoni in? (j/n) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Ne eblas aldoni foto-identigilon al PGP2-stila losilo.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "u forvii i tiun bonan subskribon? (j/N/f)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "u forvii i tiun nevalidan subskribon? (j/N/f)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "u forvii i tiun nekonatan subskribon? (j/N/f)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "u vere forvii i tiun mem-subskribon? (j/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Forviis %d subskribon.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Forviis %d subskribojn.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Nenio estis forviita.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Donu la losilgrandon" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Bonvolu malelekti la sekretajn losilojn.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Bonvolu elekti maksimume unu flankan losilon.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "anas la daton de eksvalidio de flanka losilo.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "anas la daton de eksvalidio de la efa losilo.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Vi ne povas ani la daton de eksvalidio de v3-losilo\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Mankas responda subskribo en sekreta losilaro\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Bonvolu elekti precize unu uzantidentigilon.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "losilo %08lX: nevalida mem-subskribo\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Mankas uzantidentigilo kun indekso %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Mankas flanka losilo kun indekso %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "uzantidentigilo: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"subskribita per via losilo %08lX je %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"subskribita per via losilo %08lX je %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "i tiu losilo eksvalidios je %s.\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "u vi estas certa, ke vi ankora volas aldoni in? (j/n) " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "u krei revokatestilon por i tiu subskribo? (j/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Vi subskribis la sekvajn uzantidentigilojn:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " subskribita per %08lX je %s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revokita de %08lX je %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Vi revokos la sekvajn subskribojn:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " subskribita per %08lX je %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "u vere krei la revokatestilojn? (j/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "mankas sekreta losilo\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Subskribo-gvidlinioj: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Subskribo-gvidlinioj: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "AVERTO: nevalida notacia dateno trovita\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Subskribo-notacio: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Subskribo-notacio: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "ne homlegebla" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "losilaro" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [eksvalidios: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "listigi losilojn kaj fingropurojn" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " losilo-fingrospuro =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " losilo-fingrospuro =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " losilo-fingrospuro =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " losilo-fingrospuro =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "nevalida kompendi-metodo '%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s-ifritaj datenoj\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "ifrita per nekonata metodo %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "publika losilo estas %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "publiklosile ifritaj datenoj: bona DEK\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "ifrita per %u-bita %s-losilo, %08lX, kreita je %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "ifrita per %s-losilo, %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "publiklosila malifrado malsukcesis: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "supozas %s ifritajn datenojn\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "ifro IDEA ne disponata, optimisme provas uzi %s anstatae\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "malifrado sukcesis\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "AVERTO: ifrita mesao estis manipulita!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "malifrado malsukcesis: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTO: sendinto petis konfidencon (\"for-your-eyes-only\")\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "originala dosiernomo='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "memstara revoko - uzu \"gpg --import\" por apliki in\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notacio: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Gvidlinio: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "kontrolo de subskribo estas malaltita\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "ne povas trakti i tiujn pluroblajn subskribojn\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Subskribo farita je %.*s per %s, losilo %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "MALBONA subskribo de \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Eksvalidiinta subskribo de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Bona subskribo de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[malcerta]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alinome \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Ne povas kontroli subskribon: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "ne aparta subskribo\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "memstara subskribo de klaso 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "malnovstila subskribo (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "nevalida radikpaketo trovita en proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "ne povas malalti kreadon de core-dosieroj: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Eksperimentaj metodoj ne estu uzataj!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "i tiu ifrad-metodo estas malrekomendata; bonvolu uzi pli normalan!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "la aldonao por la ifro IDEA en eestas\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"bonvolu vidi http://www.gnupg.org/why-not-idea.html por pliaj informoj\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "AVERTO: '%s' estas malplena dosiero\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "AVERTO: '%s' estas malplena dosiero\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "ne povas trakti publiklosilan metodon %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "subpaketo de speco %d havas altitan \"critical bit\"\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent ne estas disponata en i tiu sesio\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "ne povas agordi kliento-PID por la agento\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "ne povas akiri lego-FD de servilo por la agento\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "ne povas akiri skribo-FD de servilo por la agento\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "malbona valoro de la media variablo GPG_AGENT_INFO\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "protokolversio %d de gpg-agent ne estas uzebla\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "ne povas konektii al '%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "komunikproblemo kun gpg-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problemo kun agento - malaltas uzadon de agento\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (eflosilo %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Vi bezonas pasfrazon por mallosi la sekretan losilon por la uzanto:\n" -"\"%.*s\"\n" -"%u-bita %s losilo, ID %08lX, kreita je %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Donu pasfrazon\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Ripetu pasfrazon\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "pasfrazo estas tro longa\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "nevalida respondo de agento\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "nuligita de uzanto\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problemo kun agento: agento redonas 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Vi bezonas pasfrazon por mallosi la sekretan losilon\n" -"por la uzanto: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bita %s-losilo, %08lX, kreita je %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "ne povas kontroli pasvorton en neinteraga reimo\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Donu pasfrazon: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Ripetu pasfrazon: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "datenoj ne savitaj; uzu la opcion \"--output\" por savi ilin\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "eraro dum kreado de '%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Aparta subskribo.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Bonvolu doni la nomon de la dosiero: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "legas la normalan enigon ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "mankas subskribitaj datenoj\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "ne povas malfermi subskribitan dosieron '%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "nenomita ricevonto; provas per sekreta losilo %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "bone; ni estas la nenomita ricevonto.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "malnova kodado de DEK ne estas realigita\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "ifrad-metodo %d%s estas nekonata a malaltita\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "NOTO: ifrad-metodo %d ne trovita en preferoj\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTO: sekreta losilo %08lX eksvalidiis je %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "losilo %08lX: losilo estas revokita!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "petas la losilon %08lX de HKP-losilservilo %s ...\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "ne povas akiri losilon de losilservilo: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "eraro dum sendo al '%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "sukceso dum sendo al '%s' (statuso=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "malsukceso dum sendo al '%s': statuso=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "seras pri \"%s\" e HKP-servilo %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "ne povas seri e losilservilo: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "sekretaj losilpartoj ne estas disponataj\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "protekto-metodo %d%s ne estas realigita\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Nevalida pasfrazo; bonvolu provi denove" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"AVERTO: Malforta losilo trovita - bonvolu ani la pasfrazon denove.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"i tio estas PGP-kreita ElGamal-losilo, kiu NE estas sekura por " -"subskribado!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "la publika losilo estas %lu sekundon pli nova ol la subskribo\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "la publika losilo estas %lu sekundojn pli nova ol la subskribo\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"losilo estis kreita %lu sekundon en la estonteco (tempotordo a " -"horloeraro)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"losilo estis kreita %lu sekundojn en la estonteco (tempotordo a " -"horloeraro)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTO: subskribo-losilo %08lX eksvalidiis je %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "supozas malbonan subskribon pro nekonata \"critical bit\"\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"AVERTO: ne povas %%-kompletigi gvidlinian URL (tro granda); uzas sen " -"kompletigo.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"AVERTO: ne povas %%-kompletigi gvidlinian URL (tro granda); uzas sen " -"kompletigo.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "kontrolo de kreita subskribo malsukcesis: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s-subskribo de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "AVERTO: '%s' estas malplena dosiero\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "eblas subskribi nur per PGP-2.x-stilaj losiloj kun --pgp2\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "ne povas krei %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTO: ifrad-metodo %d ne trovita en preferoj\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "subskribas:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"eblas klartekste subskribi nur per PGP-2.x-stilaj losiloj kun --pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%s ifrado estos aplikata\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "ne povas trakti tekstliniojn pli longajn ol %d signojn\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "enigata linio pli longa ol %d signojn\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "fido-datenaro loko %lu: lseek malsukcesis: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "fido-datenaro loko %lu: skribo malsukcesis (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "fido-datenaro-transakcio tro granda\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: ne povas aliri: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: dosierujo ne ekzistas!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: ne povas krei loson\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: ne povas krei loson\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: ne povas krei: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: malsukcesis krei versiregistron: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: nevalida fido-datenaro kreita\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: fido-datenaro kreita\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: nevalida fido-datenaro\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: malsukcesis krei haktabelon: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: eraro dum aktualigo de versiregistro: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: eraro dum legado de versiregistro: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: eraro dum skribado de versiregistro: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "fido-datenaro: lseek malsukcesis: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "fido-datenaro: lego malsukcesis (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: ne estas fido-datenaro\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: versiregistro kun registronumero %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: nevalida dosiero-versio %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: eraro dum legado de libera registro: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: eraro dum skribo de dosieruja registro: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: malsukcesis nuligi registron: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: malsukcesis aldoni registron: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "la fido-datenaro estas fuita; bonvolu ruli \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "'%s' ne estas valida longa losilidentigilo\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "losilo %08lX: akceptita kiel fidata losilo\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "losilo %08lX aperas pli ol unufoje en la fido-datenaro\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "losilo %08lX: mankas publika losilo por fidata losilo - ignorita\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "fido-datenaro loko %lu, petospeco %d: lego malsukcesis: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "fido-registro %lu ne havas petitan specon %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "fido-datenaro %lu, speco %d: skribo malsukcesis: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "fido-datenaro: sync malsukcesis: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "kontrolo de fido-datenaro ne estas bezonata\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "sekva kontrolo de fido-datenaro je %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "kontrolas la fido-datenaron\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "publika losilo %08lX ne trovita: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "publika losilo de absolute fidata losilo %08lX ne trovita\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"kontrolas e profundo %d subskribita=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"ne eblis kontroli la subskribon.\n" -"Bonvolu memori, ke la subskribodosiero (.sig a .asc)\n" -"devas esti la unua dosiero donita en la komandlinio.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "enigata linio %u tro longa, a mankas linifino\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"losilo ne estas markita kiel malsekura - ne povas uzi in kun falsa " -"stokastilo!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "ignoris '%s': ripetita\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "ignoris '%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "ignorita: sekreta losilo jam eestas\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"ignoris '%s': i tio estas PGP-kreita ElGamal-losilo, kiu ne estas sekura " -"por subskribado!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Dosiero '%s' ekzistas. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "u surskribi (j/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: nekonata sufikso\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Donu novan dosiernomon" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "skribas al la normala eligo\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "supozas subskribitajn datenojn en '%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: nova opcio-dosiero kreita\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: ne povas krei dosierujon: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: dosierujo kreita\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"AVERTO: mesao estis ifrita per malforta losilo en la simetria ifro.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problemo e traktado de ifrita paketo\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "malforta losilo kreita - provas denove\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"ne povas eviti malfortajn losilojn por simetria ifro; provis %d fojojn!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "ne povas fari tion en neinteraga reimo sen \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "u forvii i tiun losilon de la losilaro? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Tio estas sekreta losilo! u vere forvii in? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "forvio de losilbloko malsukcesis: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "estas sekreta losilo por la publika losilo \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "uzu la opcion \"--delete-secret-key\" por forvii in unue.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Vi devas mem doni valoron i tie; la valoro neniam estos eksportita\n" -"al alia persono. Ni bezonas in por realigi la fido-reton; i neniel\n" -"rilatas al la (implicite kreita) atestilo-reto." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Por konstrui la fido-reton, GnuPG devas scii, kiuj losiloj estas\n" -"absolute fidataj; normale tiuj estas la losiloj, por kiuj vi havas\n" -"aliron al la sekreta losilo. Respondu \"jes\" por igi i tiun losilon\n" -"absolute fidata\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" -"Se vi tamen volas uzi i tiun revokitan losilon, respondu per \"jes\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Se vi tamen volas uzi i tiun nefidatan losilon, respondu per \"jes\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "" -"Donu la uzantidentigilon de la adresito, al kiu vi volas sendi la mesaon." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Elektu la uzotan metodon.\n" -"\n" -"DSA (alinome DSS) estas la subskrib-metodo uzebla nur por subskribado.\n" -"i tio estas la rekomendata metodo, ar kontrolado e DSA-subskriboj\n" -"estas multe pli rapida ol e ElGamal.\n" -"\n" -"ElGamal estas metodo uzebla kaj por subskribado kaj por ifrado.\n" -"OpenPGP distingas inter du specoj de i tiu metodo: nurifra, kaj\n" -"subskriba-kaj-ifra; efektive temas pri la sama, sed iuj parametroj\n" -"devas esti elektitaj en speciala maniero por krei sekuran losilon\n" -"por subskribado: i tiu programo faras tion, sed aliaj OpenPGP-\n" -"programoj ne devas kompreni la subskriban-kaj-ifran specon.\n" -"\n" -"La unua (efa) losilo devas esti losilo uzebla por subskribado;\n" -"tial la nurifra ElGamal-losilo ne estas proponata en i tiu menuo." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Kvankam i tiuj losiloj estas difinitaj en RFC 2440, ili ne estas\n" -"rekomendataj, ar ili ne estas komprenataj de iuj programoj, kaj\n" -"subskriboj kreitaj per ili etas iom grandaj kaj malrapide kontroleblaj." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Donu la losilgrandon" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Respondu per \"jes\" a \"ne\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Donu la bezonatan valoron, kiel montrite en la invito.\n" -"Eblas doni ISO-forman daton (JJJJ-MM-TT), sed vi ne ricevos\n" -"bonan eraromesaon; anstatae la sistemo provas interpreti\n" -"la donitan valoron kiel gamon." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Donu la nomon de la losilposedanto" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "bonvolu doni retadreson (ne devige, sed tre rekomendate)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Bonvolu doni nedevigan komenton" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N por ani la nomon.\n" -"K por ani la komenton.\n" -"A por ani la retadreson.\n" -"B por darigi kun la losilkreado.\n" -"F por interrompi la losilkreadon kaj fini." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Respondu per \"jes\" (a nur \"j\"), se la sublosilo estu kreita." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Kiam vi subskribas uzantidentigilon sur losilo, vi devas unue kontroli,\n" -"ke la losilo apartenas al la persono nomita en la identigilo. Estas\n" -"utile por aliaj homoj scii, kiom zorge vi kontrolis tion.\n" -"\n" -"\"0\" signifas, ke vi faras nenian specifan aserton pri tio, kiel zorge vi\n" -" kontrolis la losilon.\n" -"\n" -"\"1\" signifas, ke vi kredas, ke la losilo apartenas al la homo, kiu\n" -" pretendas posedi in, sed vi ne povis kontroli, a simple ne\n" -" kontrolis la losilon. Tio estas utila, kiam oni subskribas la\n" -" losilon de psedonoma uzanto.\n" -"\n" -"\"2\" signifas, ke vi malzorge kontrolis la losilon. Ekzemple, povas esti,\n" -" ke vi kontrolis la fingropuron de la losilo kaj komparis la\n" -" uzantidentigilon sur la losilo kun foto-identigilo.\n" -"\n" -"\"3\" signifas, ke vi zorge kontrolis la losilon. Ekzemple, povas esti,\n" -" ke vi kontrolis la fingropuron persone e la posedanto de la\n" -" losilo, kaj vi kontrolis, per malfacile falsebla dokumento kun\n" -" foto-identigilo (ekzemple pasporto), ke la nomo de losilposedanto\n" -" kongruas kun la nomo en la uzantidentigilo sur la losilo, kaj fine\n" -" vi kontrolis (per interano de retmesaoj), ke la retadreso sur\n" -" la losilo apartenas al la posedanto de la losilo.\n" -"\n" -"Notu, ke la ekzemploj donitaj supre por la niveloj 2 kaj 3 estas nur\n" -"ekzemploj. Vi devas fine mem decidi, kion precize signifas \"malzorga\"\n" -"kaj \"zorga\", kiam vi subskribas aliajn losilojn.\n" -"\n" -"Se vi ne scias la ustan respondon, respondu per \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Respondu per \"jes\", se vi volas subskribi iujn uzantidentigilojn" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Respondu per \"jes\", se vi vere volas forvii la uzantidentigilon.\n" -"Tiam anka iuj atestiloj perdios!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Respondu per \"jes\", se la sublosilo estu forviita" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"i tio estas valida losilsubskribo; normale vi ne volas forvii\n" -"i tiun subskribon, ar eble i estos grava por establi fido-ligon\n" -"al la losilo a al alia losilo atestita per i tiu losilo." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"La subskribo ne estas kontrolebla, ar vi ne havas la respondan\n" -"losilon. Vi devus prokrasti ian forvion, is vi scios, kiu\n" -"losilo estis uzita, ar la subskribanta losilo eble establos\n" -"fido-ligon tra alia jam atestita losilo." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"La subskribo ne estas valida. Estas prudente forigi in de\n" -"via losilaro." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"i tio estas subskribo, kiu ligas la uzantidentigilon al la losilo.\n" -"Normale ne estas konsilinde forigi tian subskribon. Efektive, GnuPG\n" -"eble ne povus uzi la losilon poste. Do, faru i tion, nur se la\n" -"mem-subskribo estas ial nevalida, kaj dua mem-subskribo estas\n" -"havebla." - -#: g10/helptext.c:237 -#, fuzzy -msgid "" -"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" -msgstr "" -"ani la preferojn de iuj uzantidentigiloj (a nur la elektitaj)\n" -"al la aktuala listo de preferoj. La dato de iuj trafitaj\n" -"mem-subskriboj estos antaenigitaj je unu sekundo.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Bonvolu doni la pasfrazon; tio estas sekreta frazo \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Bonvolu ripeti la pasfrazon, por kontroli, ke vi bone scias, kion vi tajpis." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Donu la nomon de la dosiero, al kiu la subskribo aplikias" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Respondu per \"jes\", se la dosiero estu surskribita" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Bonvolu doni novan dosiernomon. Se vi premas nur ENEN, la implicita\n" -"dosiero (montrita en parentezo) estos uzata." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Vi devus doni kialon por i tiu atestilo. Depende de la kunteksto, vi\n" -"povas elekti el i tiu listo:\n" -" \"losilo estas kompromitita\"\n" -" Uzu i tion, se vi pensas, ke nerajtigita homo havis aliron al\n" -" via sekreta losilo.\n" -" \"losilo estas anstataigita\"\n" -" Uzu i tion, se vi anstataigis la losilon per pli nova.\n" -" \"losilo estas ne plu uzata\"\n" -" Uzu i tion, se vi retiris i tiun losilon.\n" -" \"Uzantidentigilo ne plu validas\"\n" -" Uzu i tion por aserti, ke la uzantidentigilo ne plu estu uzata;\n" -" normale oni uzas i tion por marki retadreson kiel nevalidan.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Se vi volas, vi povas doni tekston por priskribi, kial vi faras\n" -"i tiun revokatestilon. Bonvolu fari i tiun tekston konciza.\n" -"Malplena linio finas la tekston.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Nenia helpo disponata" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Nenia helpo disponata por '%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "eraro dum kreado de losilaro '%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "losilaro '%s' kreita\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "malsukcesis rekonstrui losilaran staplon: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "AVERTO: ekzistas 2 dosieroj kun sekretaj informoj.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s estas la neanita\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s estas la nova\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Bonvolu ripari i tiun eblan sekurecproblemon\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "kontrolas losilaron '%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu losiloj jam kontrolitaj (%lu subskriboj)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu losiloj kontrolitaj (%lu subskriboj)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: losilaro kreita\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "vi devas restartigi GnuPG, por ke i povu legi la novan opcio-dosieron\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "ano de permesoj de '%s' malsukcesis: %s\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Fingrospuro:" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingrospuro:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOMO=VALORO|uzi i tiun notacian datenon" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "la unua signo de notacia nomo devas esti litero a substreko\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "punktoj en notacia nomo devas esti inter aliaj signoj\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "AVERTO: i tiu losilo jam havas foto-identigilon.\n" -#~ " Aldono de alia foto-identigilo eble konfuzos iujn versiojn de " -#~ "PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Eblas havi nur unu foto-identigilon sur losilo.\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "u vi vere bezonas tiom grandan losilgrandon? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "losilo %08lX: nia kopio ne havas mem-subskribon\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " u vi estas certa, ke vi ankora volas subskribi in?\n" - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " subskribita per %08lX je %s\n" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key uzantidentigilo" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key uzantidentigilo" - -#~ msgid "Enter the user ID: " -#~ msgstr "Donu la uzantidentigilon: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "ignorita: publika losilo jam difinita per --encrypt-to\n" - -#~ msgid "sSmMqQ" -#~ msgstr "iImMfF" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "neniu losilservilo konata (uzu la opcion --keyserver)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: ne valida losilidentigilo\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NOMOJ]|kontroli la fido-datenaron" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Ne povis trovi validan fidovojon al la losilo. Ni vidu, u eblas\n" -#~ "atribui iujn mankantajn posedantofido-valorojn.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "Nenia vojo trovita, kiu kondukas al unu el niaj losiloj.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Neniom da atestiloj trovitaj kun nedifinita fidovaloro.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Neniuj fidovaloroj anitaj.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "%08lX: mankas informoj por kalkuli fidovaloron\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: eraro dum kontrolo de losilo: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "tro da registroj en unk-staplo - malaltas\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "aktualigo de fido-datenaro malsukcesis: %s\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "supozas malbonan sigelon (MDC) pro nekonata \"critical bit\"\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "eraro dum legado de dosieruja registro por LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: atendis dosierujan registron, trovis specon %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "mankas efa losilo por LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "eraro dum legado de efa losilo por LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record malsukcesis: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "losilo %08lX: peto-registro malsukcesis\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "losilo %08lX: jam en tabelo de fidataj losiloj\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "NOTO: sekreta losilo %08lX NE estas protektita.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "losilo %08lX: sekreta kaj publika losiloj ne kongruas\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "listigo de sekretaj losiloj malsukcesis: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "losilo %08lX.%lu: Bona sublosila bindado\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "losilo %08lX.%lu: Nevalida sublosila bindado: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "losilo %08lX.%lu: Valida losilrevoko\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "losilo %08lX.%lu: Nevalida losilrevoko: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Bona mem-subskribo" - -#~ msgid "Invalid self-signature" -#~ msgstr "Nevalida mem-subskribo" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "Valida uzantidentigil-revoko ignorita pro pli nova mem-subskribo" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Valida uzantidentigil-revoko" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Nevalida uzantidentigil-revoko" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Valida atestilrevoko" - -#~ msgid "Good certificate" -#~ msgstr "Bona atestilo" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Nevalida atestilrevoko" - -#~ msgid "Invalid certificate" -#~ msgstr "Nevalida atestilo" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "subskribo-registro %lu[%d] montras al malusta registro.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "ripetita atestilo - forviita" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir malsukcesis: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: enovo malsukcesis: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: enovo malsukcesis: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: enovita\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "eraro dum legado de dosieruja registro: %s\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu losiloj enovitaj\n" - -#~ msgid "enumerate keyblocks failed: %s\n" -#~ msgstr "listigo de losilblokoj malsukcesis: %s\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: dosieruja registro sen losilo - ignorita\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu pro novaj publikaj losiloj\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu losiloj ignoritaj\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu losiloj aktualigitaj\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Hu, mankas losiloj\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Hu, mankas uzantidentigiloj\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: sero pri dosieruja registro malsukcesis: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "losilo %08lX: enovo de fidoregistro malsukcesis: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "losilo %08lX.%lu: enovis en fido-datenaron\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "losilo %08lX.%lu: kreita en la estonteco (tempotordo a horloeraro)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "losilo %08lX.%lu: eksvalidiis je %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "losilo %08lX.%lu: fido-kontrolo malsukcesis: %s\n" - -#~ msgid "user '%s' not found: %s\n" -#~ msgstr "uzanto '%s' ne trovita: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "problemo dum trovo de '%s' en fido-datenaro: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "uzanto '%s' ne estas en fido-datenaro - enovas\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "malsukcesis meti '%s' en fido-datenaron: %s\n" - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "tro da stokastaj bitoj petitaj; la limo estas %d\n" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Por informoj vidu http://www.gnupg.org" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "u vi vere volas krei subskriban kaj ifran losilon? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: uzanto ne trovita: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "problemo e legado de atestilo: %s\n" - -#~ msgid "can't lock keyring `%s': %s\n" -#~ msgstr "ne povas losi la losilaron '%s': %s\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: uzanto ne trovita\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "AVERTO: ne povas trakti longajn preferoregistrojn\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: ne povas krei losilaron: %s\n" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "RSA-losilo ne estas uzebla kun i tiu versio\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Mankas losilo por uzantidentigilo\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Mankas uzantidentigilo por losilo\n" - -#~ msgid "invalid" -#~ msgstr "nevalida" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "mankas sekreta losilo por malifrado\n" diff --git a/po/es.po b/po/es.po deleted file mode 100644 index 3494296fe..000000000 --- a/po/es.po +++ /dev/null @@ -1,5228 +0,0 @@ -# Mensajes en espaol para GnuPG. -# Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. -# Urko Lusa , 1998, 1999. -# I've tried to mantain the terminology used by Armando Ramos -# in his PGP 2.3.6i translation. -# I also got inspiration from it.po by Marco d'Itri -# Jaime Surez , 2001, 2002. -# -msgid "" -msgstr "" -"Project-Id-Version: GNU gnupg 1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-05-01 00:33+0200\n" -"Last-Translator: Jaime Surez \n" -"Language-Team: Spanish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "ATENCIN: se est usando memoria insegura!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "por favor, vea http://www.gnupg.org/faq.html para ms informacin\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "operacin imposible sin memoria segura inicializada\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(es posible que haya usado el programa incorrecto para esta tarea)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "s" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "sS" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "no" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "salir" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "sS" - -#: util/errors.c:54 -msgid "general error" -msgstr "Error general" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "Formato desconocido" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "Versin desconocida" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "Algoritmo de clave pblica desconocido" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "Algoritmo desconocido de resumen de mensaje" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "Clave pblica incorrecta" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "Clave secreta incorrecta" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "Firma incorrecta" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "Error en la suma de comprobacin" - -# Por qu no frase de paso? -# Porque todo el mundo sabe lo que es una contrasea -# y una "frase de paso" no. Soy consciente de que se -# traduce igual password y passphrase pero el contexto -# permite saber de lo que se est hablando. -# No s, no s. -# Por qu los ingleses entonces s que saben lo que es un "passphrase"? -# Es que son ms listos? :-) -# -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "Contrasea incorrecta" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "Clave pblica no encontrada" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "Algoritmo de cifrado desconocido" - -# y llavero? -# Hombre... las claves son parecidas a las llaves pero no lo mismo -# toda la literatura en castellano usa "anillos de claves" si un -# programa nos habla del llavero no puedo abrir el llavero? nos -# miraremos en el bolsillo bastante desconcertados. No creo que se -# trate de establecer una nomenclatura propia. -# A lo mejor toda esa literatura est producida por gente que no saba -# cmo se dice llavero en ingls... -# Si los ingleses dicen llavero en su idioma por qu no vamos a poder -# nosotros decir lo mismo en el nuestro? -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "No se puede abrir el anillo de claves" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "paquete invlido" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armadura invlida" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "no existe el ID de usuario" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "clave secreta no disponible" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "clave secreta incorrecta" - -#: util/errors.c:72 -msgid "not supported" -msgstr "no disponible" - -#: util/errors.c:73 -msgid "bad key" -msgstr "clave incorrecta" - -#: util/errors.c:74 -msgid "file read error" -msgstr "error de lectura" - -#: util/errors.c:75 -msgid "file write error" -msgstr "error de escritura" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritmo de compresin desconocido" - -#: util/errors.c:77 -msgid "file open error" -msgstr "error al abrir fichero" - -#: util/errors.c:78 -msgid "file create error" -msgstr "error al crear fichero" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "contrasea incorrecta" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmo de clave pblica no implementado" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritmo de cifrado no implementado" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "clase de firma desconocida" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "error en la base de datos de confianza" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI incorrecto" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "lmite de recurso" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "anillo invlido" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "certificado incorrecto" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "ID de usuario mal formado" - -#: util/errors.c:89 -msgid "file close error" -msgstr "error al cerrar fichero" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "error al renombrar fichero" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "error al borrar fichero" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "datos inesperados" - -# o tal vez "en el sello..." -# Creo que es mejor "con el sello de fecha", no es un conflicto -# del sello en si mismo sino en relacin con el mensaje. -# Ok. -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "conflicto con el sello de fecha" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritmo de clave pblica no utilizable" - -#: util/errors.c:95 -msgid "file exists" -msgstr "el fichero existe" - -#: util/errors.c:96 -msgid "weak key" -msgstr "clave dbil" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argumento invlido" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI incorrecto" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI no disponible" - -#: util/errors.c:100 -msgid "network error" -msgstr "error de red" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "no cifrado" - -#: util/errors.c:103 -msgid "not processed" -msgstr "no procesado" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "clave pblica inutilizable" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "clave secreta inutilizable" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "error del servidor de claves" - -# bicho :-) -# Error simplemente? -# Uf, preferira bug, si leo "error" voy a pensar en otra cosa distinta... -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... esto es un bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "ha encontrado un error... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "no se puede abrir `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "no se puede obtener informacin de `%s': %s\n" - -# ignore no es ignorar, es no tener en cuenta, ignorar es not to know. -# Sugerencia: descartar. -# Sugerencia a la sugerencia: qu tal omitido? (pasar en silencio una -# cosa; excluirla de lo que se habla o escribe) dice el diccionario. -# Bien. Tambin se puede poner "descartado". -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s` no es un fichero regular - omitido\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "nota: el fichero de semillas aleatorias est vaco\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -"atencin: tamao incorrecto del fichero de semillas aleatorias - no se usa\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "no se puede leer `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "nota: el fichero de semillas aleatorias no se ha actualizado\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "no se puede crear %s: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "no se puede escribir `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "no se puede cerrar `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "ATENCIN: usando un generador de nmeros aleatorios inseguro!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"El generador de nmeros aleatorios es slo un apao\n" -"para poder compilar. No es en absoluto un generador seguro!\n" -"\n" -"NO USE DATOS GENERADOS POR ESTE PROGRAMA!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"No hay suficientes bytes aleatorios disponibles. Por favor, haga algn\n" -"otro trabajo para que el sistema pueda recolectar ms entropa\n" -"(se necesitan %d bytes ms).\n" - -# rdenes, please... -# S, este no he podido ser yo :-) Por cierto, por qu la O no se -# puede acentuar? demasiado alta? -# Quin dice que no se puede? :-) -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@rdenes:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[file]|crea una firma" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[file]|crea una firma en texto claro" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "crea una firma separada" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "cifra datos" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[ficheros]|cifra ficheros" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "cifra slo con un cifrado simtrico" - -#: g10/g10.c:315 -msgid "store only" -msgstr "slo almacenar" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "descifra datos (predefinido)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[ficheros]|descifra ficheros" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verifica una firma" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "lista claves" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "lista claves y firmas" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "comprueba las firmas de las claves" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "lista claves y huellas dactilares" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "lista claves secretas" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "genera un nuevo par de claves" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "elimina claves del anillo pblico" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "elimina claves del anillo privado" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "firma la clave" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "firma la clave localmente" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "firma la clave no revocablemente" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "firma la clave localmente y no revocablemente" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "firma o modifica una clave" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "genera un certificado de revocacin" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exporta claves" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exporta claves a un servidor de claves" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importa claves desde un servidor de claves" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "busca claves en un servidor de claves" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "actualiza claves desde un servidor de claves" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importa/fusiona claves" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "lista slo la secuencia de paquetes" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exporta los valores de confianza" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importa los valores de confianza" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "actualiza la base de datos de confianza" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "actualiza la base de datos de confianza" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "arregla una base de datos de confianza daada" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "quita la armadura de un fichero o de la entrada estndar" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "crea la armadura a un fichero o a la entrada estndar" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [ficheros]|imprime resmenes de mensaje" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opciones:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "crea una salida ascii con armadura" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOMBRE|cifra para NOMBRE" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOMBRE|usa NOMBRE como destinatario por defecto" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "usa la clave por defecto como destinatario" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "usa este usuario para firmar o descifrar" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|nivel de compresin N (0 no comprime)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "usa modo de texto cannico" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "usa como fichero de salida" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "prolijo" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "algo ms discreto" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "no usa la terminal en absoluto" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "fuerza firmas v3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "no fuerza firmas v3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "fuerza firmas v4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "no fuerza firmas v4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "siempre usa un MDC para cifrar" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "nunca usa un MDC para cifrar" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "no hace ningn cambio" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -# usa -# Vale. -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "usa el agente gpg" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "proceso por lotes: nunca preguntar" - -# assume -> suponer, no asumir -# No estoy seguro. El diccionario Collins en la acepcin b) de asumir -# dice "b) (suponer) to assume, suppose..." -# Adems una de las acepciones de asumir es "aceptar algo" y suponer -# viene a ser asumir una idea como propia. Suponer "s" en casi todas las -# preguntas no me acaba de gustar. -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "asume \"s\" en casi todas las preguntas" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "asume \"no\" en casi todas las preguntas" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "aade este anillo a la lista de anillos" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "aade este anillo secreto a la lista" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "muestra en qu anillos est una clave" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOMBRE|usa NOMBRE como clave secreta por defecto" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|SERVIDOR|usa este servidor de claves" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NOMBRE|usa el juego de caracteres NOMBRE" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "lee opciones del fichero" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|DF|escribe informacin de estado en este descriptor de fichero" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[fichero]|escribe informacin de estado en el fichero" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|ID-CLAVE|confa plenamente en esta clave" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FICHERO|carga mdulo de extensiones FICHERO" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emula el modo descrito en la RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "todas las opciones de paquete, cifrado y resumen tipo OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "todas las opciones de paquete, cifrado y resumen tipo PGP 2.x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|usa modo de contrasea N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "" -"|NOMBRE|usa algoritmo de resumen de mensaje NOMBRE para las contraseas" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NOMBRE|usa el algoritmo de cifrado NOMBRE para las contraseas" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOMBRE|usa el algoritmo de cifrado NOMBRE" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOMBRE|usa algoritmo de resumen de mensaje NOMBRE" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|usa el algoritmo de compresin N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "elimina campo keyid de los paquetes cifrados" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Muestra IDs fotogrficos" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "No muestra IDs fotogrficos" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Ajusta linea de comandos para ver IDs fotogrficos" - -# ordenes -> rdenes -# pgina man -> pgina de manual -# Vale. del manual mejor? -# Hmm, no s, en man-db se usa "de". La verdad es que no lo he pensado. -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Vase en la pgina del manual la lista completo de rdenes y opciones)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Ejemplos:\n" -"\n" -" -se -r Bob [fichero] firma y cifra para el usuario Bob\n" -" --clearsign [fichero] hace una firma manteniendo el texto sin cifrar\n" -" --detach-sign [fichero] hace una firma separada\n" -" --list-keys [nombres] muestra las claves\n" -" --fingerprint [nombres] muestra las huellas dactilares\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Por favor, informe de posibles \"bugs\" a .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Uso: gpg [opciones] [ficheros] (-h para ayuda)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintaxis: gpg [opciones] [ficheros]\n" -"firma, comprueba, cifra o descifra\n" -"la operacin por defecto depende del tipo de datos de entrada.\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritmos disponibles:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uso: gpg [opciones] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "rdenes incompatibles\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Aviso: propiedad insegura de %s \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Aviso: permisos inseguros de %s \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Aviso: propiedad insegura de %s \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Aviso: permisos inseguros de %s \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTA: no existe el fichero de opciones predefinido `%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTA: no existe el fichero de opciones predefinido `%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "fichero de opciones `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "leyendo opciones desde `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s no es un juego de caracteres vlido\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "no se puede interpretar la URI del servidor de claves\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: versin del fichero %d invlida\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armadura invlida" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: versin del fichero %d invlida\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "anillo invlido" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "imposible establecer camino de ejecutables %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "ATENCIN: el programa podra volcar un fichero core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "AVISO: %s sustituye a %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTA: %s no es para uso normal!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s no permitido con %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s no tiene sentido con %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "slo puede hacer firmas separadas o en claro en modo --pgp2\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "no puede firmar y cifrar a la vez en modo --pgp2\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "debe usar ficheros (no tuberas) si trabaja con --pgp2 activo.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "cifrar un mensaje en modo --pgp2 requiere el algoritmo IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "este mensaje podra no ser utilizable por PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "el algoritmo de cifrado seleccionado es invlido\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "el algoritmo de resumen seleccionado no invlido\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "el algoritmo de resumen seleccionado no invlido\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "el algoritmo de compresin debe estar en el rango %d-%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed debe ser mayor que 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed debe ser mayor que 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth debe estar en el rango 1-255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTA: el modo S2K simple (0) no es nada recomendable\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "modo S2K incorrecto; debe ser 0, 1 o 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "nivel de comprobacin por defecto invlido; debe ser 0, 1, 2, 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "preferencias invlidas\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "preferencias invlidas\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "preferencias invlidas\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "preferencias invlidas\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "inicializacin de la base de datos de confianza fallida: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [nombre_fichero]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [nombre_fichero]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [nombre_fichero]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [nombre_fichero]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [nombre_fichero]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [nombre_fichero]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [nombre_fichero]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [nombre_fichero]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key id-usuario" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key id-usuario" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key id-usuario" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key id-usuario" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key id-usuario [rdenes]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "no se puede abrir `%s': %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [id-usuario] [anillo]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "eliminacin de armadura fallida: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "creacin de armadura fallida: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algoritmo de distribucin invlido `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nombre_fichero]" - -# Falta un espacio. -# En espaol no se deja espacio antes de los puntos suspensivos -# (Real Academia dixit) :) -# Tomo nota :-). Este comentario djalo siempre. -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Adelante, teclee su mensaje...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "no se puede abrir `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"un nombre de notacin debe tener slo letras, dgitos, puntos o subrayados, " -"y acabar con un '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "un valor de notacin no debe usar ningn caracter de control\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "URL de poltica de certificado invlida\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "URL de poltica invlida\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armadura: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "cabecera de armadura invlida: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "cabecera de armadura: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "cabecera de firma clara invlida\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "firmas en texto claro anidadas\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "Lnea con guiones invlida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armadura inesperada" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "caracteres invlidos radix64 %02x omitidos\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "Fin de fichero prematuro (falta suma de comprobacin)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "Fin de suma de comprobacin prematuro\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "Suma de comprobacin mal creada\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Error en suma de comprobacin: %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "fin de fichero prematuro (en el cierre)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "error en la lnea de cierre\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "no se han encontrados datos OpenPGP vlidos\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armadura incorrecta: lnea ms larga de %d caracteres\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"caracter \"quoted printable\" en la armadura - probablemente se us\n" -"un MTA defectuoso\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "No se dio ninguna razn" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "La clave ha sido reemplazada." - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "La clave ha sido comprometida" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "La clave ya no est en uso" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "El identificador de usuario ya no es vlido" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Razn para la revocacin: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Comentario a la revocacin: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"No hay confianza definida para:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Por favor, decida su nivel de confianza para que este usuario\n" -"verifique las claves de otros usuarios (mirando pasaportes,\n" -"comprobando huellas dactilares en diferentes fuentes...)\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = No lo s\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr "%d = No confo\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Confo poco\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Confo totalmente\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = confo por completo\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = por favor mustreme ms informacin\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = volver al men principal\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = saltar esta clave\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = salir\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Su decisin: " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "De verdad quiere asignar total confianza a esta clave? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificados que llevan a una clave de confianza absoluta:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "clave %08lX: esta clave ha sido revocada!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Usar esta clave de todas formas? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "clave %08lX: esta subclave ha sido revocada!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: clave caducada\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: No hay indicios de que la firma pertenezca realmente al propietario.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Esta clave NO es de confianza!\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: No hay seguridad que esta clave pertenezca realmente a su \n" -"proprietario pero se acepta igualmente\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Esta clave probablemente pertenece a su proprietario\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Esta clave nos pertenece\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"No es seguro que la clave pertenezca a su propietario.\n" -"Si *realmente* sabe lo que est haciendo, puede contestar\n" -"\"s\" a la siguiente pregunta.\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "ATENCIN: Usando una clave no fiable!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "ATENCIN: Esta clave ha sido revocada por su propietario!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Esto puede significar que la firma est falsificada.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "ATENCIN: Esta clave ha sido revocada por su propietario!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Nota: Esta clave est deshabilitada.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Nota: Esta clave ha caducado!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "" -"ATENCIN: Esta clave no est certificada por una firma de confianza!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " No hay indicios de que la firma pertenezca al propietario.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "ATENCIN: Esta clave NO es de confianza!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " La firma es probablemente una FALSIFICACIN.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"ATENCIN: Esta clave no est certificada con firmas de " -"suficienteconfianza!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " No es seguro que la firma pertenezca al propietario.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: omitido: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: omitida: clave pblica ya presente\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "No ha especificado un ID de usuario (puede usar \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Introduzca ID de usuario. Acabe con una lnea vaca: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "ID de usuario inexistente.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "omitida: clave pblica ya designada como destinataria por defecto\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Clave pblica deshabilitada.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "omitida: clave pblica ya establecida\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "desconocido el destinatario predefinido `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: omitida: clave pblica deshabilitada\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "no hay direcciones vlidas\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "la preferencia %c%lu no es vlida\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "preferencia %c%lu duplicada\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "demasiadas `%c' preferencias\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "caracter invlido en cadena de preferencias\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "escribiendo autofirma\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "escribiendo autofirma\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "escribiendo la firma de comprobacin de clave\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "tamao de clave incorrecto; se usarn %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "tamao de clave redondeado a %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Por favor seleccione tipo de clave deseado:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA y ElGamal (por defecto)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (slo firmar)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (slo cifrar)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (firmar y cifrar)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (slo firmar)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (slo cifrar)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (firmar y cifrar)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Su eleccin: " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "El uso de este algoritmo est desaconsejado - crear de todas formas?" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Eleccin invlida.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Listo para generar un nuevo par de claves %s.\n" -" el tamao mnimo es 768 bits\n" -" el tamao por defecto es 1024 bits\n" -" el tamao mximo recomendado es 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "De qu tamao quiere la clave (1024)? " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA slo permite tamaos desde 512 a 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "tamao de clave insuficiente; 1024 es el mnimo permitido para RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "tamao insuficiente; 768 es el valor mnimo permitido\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "tamao excesivo; %d es el mximo valor permitido.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"No se recomiendan claves de ms de 2048 bits porque\n" -"el tiempo de clculo es REALMENTE largo!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Seguro que quiere una clave de este tamao? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"De acuerdo, pero tenga en cuenta que las radiaciones de su monitor y\n" -"teclado tambin son vulnerables a un ataque!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "El tamao requerido es de %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "redondeados a %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Por favor, especifique el perodo de validez de la clave.\n" -" 0 = la clave nunca caduca\n" -" = la clave caduca en n das\n" -" w = la clave caduca en n semanas\n" -" m = la clave caduca en n meses\n" -" y = la clave caduca en n aos\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Por favor, especifique el perodo de validez de la clave.\n" -" 0 = la clave nunca caduca\n" -" = la clave caduca en n das\n" -" w = la clave caduca en n semanas\n" -" m = la clave caduca en n meses\n" -" y = la clave caduca en n aos\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Validez de la clave (0)? " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Clave vlida durante (0)? " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valor invlido\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s nunca caduca\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s caduca el %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Su sistema no puede mostrar fechas ms all del 2038.\n" -"Sin embargo funcionar correctamente hasta el 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Es correcto (s/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Necesita un identificador de usuario para identificar su clave. El programa\n" -"construye el identificador a partir del Nombre Real, Comentario y Direccin\n" -"de Correo Electrnico de esta forma:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nombre y apellidos: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Caracter invlido en el nombre\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "El nombre no puede empezar con un nmero\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "El nombre debe tener al menos 5 caracteres\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Direccin de correo electrnico: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Direccin invlida\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Comentario: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Caracter invlido en el comentario\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Est usando el juego de caracteres `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Ha seleccionado este ID de usuario:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" -"Por favor no ponga la direccin de correo-e en el nombre real o en el " -"comentario\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcDdVvSs" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Cambia (N)ombre, (C)omentario, (D)ireccin o (S)alir? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Cambia (N)ombre, (C)omentario, (D)ireccin o (V)ale/(S)alir? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Por favor corrija primero el error.\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Necesita una contrasea para proteger su clave secreta.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "contrasea repetida incorrectamente; intntelo de nuevo" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"No ha especificado contrasea. Esto es probablemente una *mala* idea.\n" -"Si ms tarde quiere aadir una, puede hacerlo usando este programa con\n" -"la opcin \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Es necesario generar muchos bytes aleatorios. Es una buena idea realizar\n" -"alguna otra tarea (trabajar en otra ventana/consola, mover el ratn, usar\n" -"la red y los discos) durante la generacin de nmeros primos. Esto da al\n" -"generador de nmeros aleatorios mayor oportunidad de recoger suficiente\n" -"entropa.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "El par de claves DSA tendr 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Creacin de claves cancelada.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "escribiendo clave pblica en `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "escribiendo clave privada en `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "anillo pblico de claves no escribible encontrado: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "anillo privado de claves no escribible encontrado: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "error escribiendo anillo pblico `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "error escribiendo anillo privado `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "claves pblica y secreta creadas y firmadas.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "clave marcada como de confianza absoluta.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Tenga en cuenta que esta clave no puede ser usada para cifrado. Puede usar\n" -"la orden \"--edit-key\" para crear una clave secundaria con este propsito.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Creacin de la clave fallida: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"clave pblica creada %lu segundos en el futuro (salto en el tiempo o\n" -"problemas con el reloj)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"clave pblica creada %lu segundos en el futuro (salto en el tiempo o\n" -"problemas con el reloj)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "NOTA: crear subclaves para claves V3 no sigue el estndar OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Crear de verdad? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output no funciona con esta orden\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: no se puede abrir: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "error creando contrasea: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' ya est comprimido\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: ATENCIN: fichero vaco\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "solo puede cifrar a claves RSA de 2048 bits o menos en modo --pgp2\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "leyendo desde `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"no se puede usar el algoritmo IDEA para todas las claves a las que cifra.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: algoritmo de cifrado %d no encontrado en las preferencias\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Esta orden no se permite en modo %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s cifrado para: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "clave '%s' no encontrada: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "error leyendo bloque de claves: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "clave %08lX: no es conforme a rfc2440 - omitida\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "clave %08lX: no protegida - omitida\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "clave %08lX: clave estilo PGP 2.x - omitida\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "ATENCIN: no se ha exportado nada\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "demasiados registros en la cache pk - anulada\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Identificador de usuario no encontrado]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "Clave %08lX invlida hecha mediante --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "usando clave secundaria %08lX en vez de clave primaria %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "clave %08lX: clave secreta sin clave pblica - omitida\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "omitiendo bloque de tipo %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "hasta ahora se han procesado %lu claves\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "error leyendo `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Cantidad total procesada: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " omitidas nuevas claves: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sin identificador: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importadas: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " sin cambios: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nuevos identificativos: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nuevas subclaves: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nuevas firmas: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " nuevas revocaciones de claves: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " claves secretas ledas: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " claves secretas importadas: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "claves secretas sin cambios: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importadas: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "clave %08lX: sin identificador de usuario\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "clave %08lX: no hay subclave que unir\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "clave %08lX: aceptado ID de usuario sin autofirma '%s'\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "clave %08lX: sin identificadores de usuario vlidos\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "esto puede ser debido a la ausencia de autofirma\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "clave %08lX: clave pblica no encontrada: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "clave %08lX: clave nueva - omitida\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "anillo de claves no escribible encontrado: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "escribiendo en `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "error escribiendo anillo `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "clave %08lX: clave pblica importada\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "clave %08lX: no coincide con nuestra copia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "clave %08lX: no puede localizarse el bloque de claves original: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "clave %08lX: no puede leerse el bloque de claves original: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "clave %08lX: 1 nuevo identificador de usuario\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "clave %08lX: %d nuevos identificadores de usuario\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "clave %08lX: 1 nueva firma\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "clave %08lX: %d nuevas firmas\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "clave %08lX: 1 nueva subclave\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "clave %08lX: %d nuevas subclaves\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "clave %08lX: sin cambios\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "no hay anillo secreto de claves por defecto: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "clave %08lX: clave secreta importada\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "clave %08lX: ya estaba en el anillo secreto\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "clave %08lX: clave secreta no encontrada: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"clave %08lX: falta la clave pblica - imposible emplear el\n" -"certificado de revocacin\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "clave %08lX: certificado de revocacin invlido: %s - rechazado\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "clave %08lX: certificado de revocacin importado\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "clave %08lX: no hay identificador de usuario para la firma\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"clave %08lX: algoritmo de clave pblica no disponible para el id \"%s\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "clave %08lX: autofirma invlida para el id \"%s\"\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "clave %08lX: no hay subclave que unir\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "clave %08lX: algoritmo de clave pblica no disponible\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "clave %08lX: unin de subclave invlida\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "clave %08lX: unin de subclave invlida\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "clave %08lX: no hay subclave que unir\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "clave %08lX.%lu: revocacin de subclave vlida\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "clave %08lX: unin de subclave invlida\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "clave %08lX: omitido ID de usuario '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "clave %08lX: subclave omitida\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "clave %08lX: firma no exportable (clase %02x) - omitida\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "clave %08lX: certificado de revocacin en lugar equivocado - omitido\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "clave %08lX: certificado de revocacin no valido: %s - omitido\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "clave %08lX: certificado de revocacin en lugar equivocado - omitido\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "clave %08lX: detectado usuario duplicado - fusionada\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"Aviso: la clave %08lX puede estar revocada: recuperando clave de revocacin %" -"08lX\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"Aviso: la clave %08lX puede estar revocada: clave e revocacin %08lXno est " -"presente.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "clave %08lX: certificado de revocacin aadido\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "clave %08lX: firma directa de clave aadida\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revocacin]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[autofirma]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 firma incorrecta\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d firmas incorrectas\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 firma no comprobada por falta de clave\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d firmas no comprobadas por falta de clave\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 firma no comprobada por causa de un error\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d firmas no comprobadas por causa de un error\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "Detectado 1 identificador de usuario sin autofirma vlida\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "Detectados %d identificadores de usuario sin autofirma vlida\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "ID de usuario \"%s\" revocado." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Seguro que todava quiere firmarlo? (s/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Imposible firmar.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "ATENCIN `%s' es un fichero vaco\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Su firma actual en \"%s\"\n" -"es una firma local.\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Quiere convertirla en una clave totalmente exportable? (s/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Su firma actual en \"%s\"\n" -"es una firma local.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Quiere convertirla en una clave totalmente exportable? (s/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" ya estaba firmada localmente por la clave %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" ya estaba firmada por la clave %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nada que firmar con la clave %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Esta clave ha caducado!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Esta clave expirar el %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Quiere que su firma caduque al mismo tiempo? (S/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"No puede hacer una firma OpenPGP de una clave PGP 2.x estando en modo --" -"pgp2.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Esto inutilizara la clave en PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Cmo de cuidadosamente ha verificado que la clave que est a punto de\n" -"firmar pertenece realmente a la persona arriba nombrada? Si no sabe que\n" -"contestar, introduzca \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) No contesto.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) No lo he comprobado en absoluto.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) He hecho una comprobacin informal.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Lo he comprobado meticulosamente.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Est realmente seguro de querer firmar esta clave\n" -"con su clave: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "esto puede ser debido a la ausencia de autofirma\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"La firma se marcar como no exportable.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"La firma se marcar como no revocable.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"La firma se marcar como no exportable.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"La firma se marcar como no revocable.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"No he comprobado esta clave en absoluto.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"He comprobado esta clave informalmente.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"He comprobado esta clave meticulosamente.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Firmar de verdad? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "firma fallida: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Esta clave no est protegida.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Las partes secretas de la clave primaria no estn disponibles.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "La clave est protegida.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "No puede editarse esta clave: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Introduzca la nueva contrasea para esta clave secreta.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"No ha especificado contrasea. Esto es probablemente una *mala* idea.\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Realmente quiere hacer esto? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "moviendo la firma de la clave al lugar correcto\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "sale de este men" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "s" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "graba" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "graba y sale" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "ayuda" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "muestra esta ayuda" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "hdac" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "muestra huella dactilar" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "lista" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "lista clave e identificadores de usuario" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "idu" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "selecciona identificador de usuario N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "clave" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "selecciona clave secundaria N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "comprueba" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "lista firmas" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "firma" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "firma la clave" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "firmal" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "firma la clave localmente" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "firmanr" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "firma la clave irrevocablemente" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "firmanrl" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "firma la clave local e irrevocablemente" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "depura" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "aaidu" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "aade un identificador de usuario" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "aadirfoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "aade un ID fotogrfico" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "borridu" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "borra un identificador de usuario" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "borfoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "aacla" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "aade una clave secundaria" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "borrcla" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "borra una clave secundaria" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "aacla" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "aade una clave secundaria" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "borrfir" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "borra firmas" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expira" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "cambia fecha de caducidad" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primaria" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "marca ID de usuario como primario" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "cambia" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "cambia entre lista de claves secretas y pblicas" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "muestra preferencias (experto)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "verpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "muestra preferencias (prolijo)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "estpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "establece preferencias" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "actpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "preferencias actualizadas" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "contr" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "cambia la contrasea" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "conf" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "cambia valores de confianza" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revfir" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revoca firmas" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revcla" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revoca una clave secundaria" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "descla" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "deshabilita una clave" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "habcla" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "habilita una clave" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "verfoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "mostrar ID fotogrfico" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "imposible hacer esto en modo de proceso por lotes\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "error leyendo bloque de clave secreta `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Clave secreta disponible.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Orden> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Se necesita la clave secreta para hacer esto.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Por favor use la orden \"cambia\" primero.\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "La clave est revocada." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Firmar realmente todos los identificadores de usuario? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Sugerencia: seleccione los identificadores de usuario para firmar\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Esta orden no se permite en modo %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Debe seleccionar por lo menos un identificador de usuario.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "No puede borrar el ltimo identificador de usuario!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Borrar realmente todos los identificadores seleccionados? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Borrar realmente este identificador de usuario? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Debe seleccionar por lo menos una clave.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "De verdad quiere borrar las claves seleccionadas? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "De verdad quiere borrar esta clave? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "De verdad quiere revocar las claves seleccionadas? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "De verdad quiere revocar esta clave? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Actualizar realmente las preferencias para todos los ID seleccionados? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Actualizar realmente las preferencias? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Grabar cambios? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Salir sin grabar? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "actualizacin fallida: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "actualizacin de la clave secreta fallida: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Clave sin cambios, no se necesita actualizacin.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Orden invlida (pruebe \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Esta clave puede ser revocada por %s clave %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (confidencial)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX creada: %s expira: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " confianza: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Esta clave est deshabilitada" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! esta subclave ha sido revocada! %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- se encontr una revocacin falsificada\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problema comprobando la revocacin: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Por favor, advierta que la validez de clave mostrada no es necesariamente\n" -"correcta a menos de que reinicie el programa.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"AVISO: esta es una clave de tipo PGP2. Aadir un ID fotogrfico puede\n" -"hacer que algunas versiones de PGP rechacen esta clave.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Est seguro de querer aadirla? (s/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "No puede aadir un ID fotogrfico a una clave tipo PGP2.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Borrar esta firma correcta? (s/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Borrar esta firma invlida? (s/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Borrar esta firma desconocida? (s/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Borrar realmente esta autofirma? (s/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d firmas borradas.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d firmas borradas\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "No se borr nada\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Introduzca la longitud de la clave" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Por favor, quite la seleccin de las claves secretas.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Por favor, seleccione como mximo una clave secundaria.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Cambiando caducidad de clave secundaria.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Cambiando caducidad de clave primaria.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "No puede cambiar la fecha de caducidad de una clave v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "No existe la firma correspondiente en el anillo secreto\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Por favor seleccione exactamente un identificador de usuario.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "clave %08lX: autofirma invlida para el id \"%s\"\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "No hay ningn identificador de usuario con el ndice %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "No hay ninguna clave secundaria con el ndice %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "ID de usuario: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"firmada con su clave %08lX el %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"firmada localmente con su clave %08lX el %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Esta firma caduc el %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "De verdad quiere revocarla? (s/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Crear un certificado de revocacin para esta clave? (s/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Ha firmado los siguientes IDs de usuario:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " firmada por %08lX el %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revocada por %08lX el %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Va a revocar las siguientes firmas:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " firmada por %08lX el %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (no exportable)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Crear los certificados de revocacin realmente? (s/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "no hay clave secreta\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Mostrando ID fotogrfico %s de tamao %ld para la clave 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Poltica de firmas: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Poltica de firmas: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "ATENCIN: encontrados datos de notacin invlidos\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notacin de firma: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Notacin de firma: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "ilegible" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Anillo de claves" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [caduca: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "lista claves y huellas dactilares" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Huella de clave =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Huella de clave =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Huella de clave =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Huella de clave =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algoritmo de distribucin invlido `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "datos cifrados %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "cifrado con algoritmo desconocido %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "la clave pblica es %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "datos cifrados de la clave pblica: DEK correcta\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "cifrado con clave %2$s de %1$u bits, ID %3$08lX, creada el %4$s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "cifrado con clave %s, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "descifrado de la clave pblica fallido: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "suponiendo %s datos cifrados\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" -"cifrado IDEA indisponible, optimistamente intentando usar %s en su lugar\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "descifrado correcto\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "ATENCIN: el mensaje cifrado ha sido manipulado!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "descifrado fallido: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTA: el remitente solicit \"slo-para-tus-ojos\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nombre fichero original='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "revocacin independiente - use \"gpg --import\" para aplicarla\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notacin: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Poltica: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "suprimida la verificacin de la firma\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "no se puede trabajar con firmas mltiples\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Firma creada el %.*s usando clave %s ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "Firma INCORRECTA de \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Firma caducada de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Firma correcta de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[incierto]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Imposible comprobar la firma: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "no es una firma separada\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "firma independiente de clase 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "firma al viejo estilo (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "paquete raz invlido detectado en proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "no se pueden desactivar los volcados de core: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "No se deberan usar algoritmos experimentales!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"ese algoritmo de cifrado est desacreditado;por favor use uno ms " -"estndar!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "el plugin para el cifrado IDEA no est presente\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"por favor vea http://www.gnupg.org/why-not-idea.html para ms informacin\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "ATENCIN: %s es una opcin desaconsejada.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "ATENCIN: %s es una opcin desaconsejada.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "por favor use \"--keyserver-options %s\" en su lugar\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "no puedo manejar el algoritmo de clave pblica %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "el subpaquete de tipo %d tiene el bit crtico activado\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "el agente gpg no esta disponible en esta sesin\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "no puedo establecer pid para el agente\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "no puedo conseguir el FD de lectura para el agente\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "no puedo conseguir el FD de escritura para el agente\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "variable de entorno GPG_AGENT_INFO malformada\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "el programa no permite usar el protocolo agente gpg versin %d\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "no se puede conectar con `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problema de comunicacin con el agente gpg\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problema con el agente - inhabilitando el uso del agente\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr "(ID clave primaria %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Necesita una contrasea para desbloquear la clave secreta\n" -"del usuario: \"%.*s\"\n" -"%u bits, clave %s, ID %08lX, creada el %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Introduzca contrasea\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Repita contrasea\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "contrasea demasiado larga\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "respuesta del agente invlida\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "cancelado por el usuario\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problema con el agente: el agente devuelve 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Necesita una contrasea para desbloquear la clave secreta\n" -"del usuario: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "clave %2$s de %1$u bits, ID %3$08lX, creada el %4$s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "imposible pedir contrasea en modo de proceso por lotes\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Introduzca contrasea: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Repita contrasea: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "datos no grabados; use la opcin \"--output\" para grabarlos\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "error creando `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Firma separada.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Introduzca el nombre del fichero de datos: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "leyendo stdin...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "no hay datos firmados\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "imposible abrir datos firmados `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinatario annimo; probando clave secreta %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "de acuerdo, somos el destinatario annimo.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "la antigua codificacin de la DEK no puede usarse\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "algoritmo de cifrado %d%s desconocido o desactivado\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "NOTA: algoritmo de cifrado %d no encontrado en las preferencias\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTA: clave secreta %08lX caducada el %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "clave %08lX: esta clave ha sido revocada!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "solicitando clave %08lX del servidor de claves HKP %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "no puede obtenerse la clave en el servidor: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "error enviando a `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "envi correcto a `%s` (estado=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "fall el envio a `%s': status=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "buscando \"%s\" en el servidor HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "no puede buscarse en el servidor: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "las partes de la clave privada no estn disponibles\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "el algoritmo de proteccin %d%s no puede ser utilizado\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Contrasea incorrecta; intntelo de nuevo." - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ... \n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "ATENCIN: detectada clave dbil - por favor cambie la contrasea.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"generando la suma de comprobacin de 16 bits (desaconsejada) para \n" -"proteger la clave secreta.\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"esto es una clave ElGamal generada por PGP que NO es segura para las " -"firmas!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "la clave pblica es %lu segundos ms nueva que la firma\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "la clave pblica es %lu segundos ms nueva que la firma\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"clave pblica creada %lu segundos en el futuro (salto en el tiempo o\n" -"problemas con el reloj)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"clave pblica creada %lu segundos en el futuro (salto en el tiempo o\n" -"problemas con el reloj)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTA: clave de la firma %08lX caducada el %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "asumiendo firma incorrecta debido a un bit crtico desconocido\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"AVISO: no puedo expandir el %% de la url de poltica . Se usa sin expandir.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"AVISO: no puedo expandir el %% de la url de poltica . Se usa sin expandir.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "la comprobacin de la firma creada fall: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "firma %s de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "ATENCIN `%s' es un fichero vaco\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "slo puede firmar con claves tipo PGP 2.x estando en modo --pgp2\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "no se puede crear %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: algoritmo de cifrado %d no encontrado en las preferencias\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "firmando:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "slo puede firmar en claro con claves PGP 2.x estando en modo --pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "se usar un cifrado %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "no se pueden manejar lneas de texto de ms de %d caracteres\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "lnea de longitud superior a %d caracteres\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "registro base de datos de confianza %lu: lseek fallido: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "" -"resgistro base de datos de confianza %lu: escritura fallida (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transaccin en la base de datos de confianza demasiado grande\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: no se puede abrir: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: el directorio no existe!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: no se puede crear bloqueo\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: no se puede crear bloqueo\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: no se puede crear: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: fallo en la creacin del registro de versin: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: se ha creado base de datos de confianza invlida\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: se ha creado base de datos de confianza\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: base de datos de confianza invlida\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: fallo en la creacin de la tabla hash: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: error actualizando el registro de versin: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: error leyendo registro de versin: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: error escribiendo registro de versin: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "base de datos de confianza: fallo lseek: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "base de datos de confianza: error lectura (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: no es una base de datos de confianza\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: registro de versin con nmero de registro %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: versin del fichero %d invlida\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: error leyendo registro libre: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: error escribiendo registro de directorio: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: fallo en poner a cero un registro: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: fallo al aadir un registro: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"La base de datos de confianza est daada. Por favor, ejecute\n" -"\"gpg --fix-trust-db\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "'%s' no es un identificador largo de clave vlido\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "clave %08lX: aceptada como clave de confianza\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "clave %08lX aparece ms de una vez en la base de datos de confianza\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "clave %08lX: clave fiable sin clave pblica - omitida\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "registro de confianza %lu, peticin tipo %d: fallo lectura: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "registro de confianza %lu no es del tipo requerido %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "registro de confianza %lu, tipo %d: fallo escritura: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "base de datos de confianza: fallo sincronizacin: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "no es necesaria una comprobacin de la base de datos de confianza\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "siguiente comprobacin de base de datos de confianza el: %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "comprobando base de datos de confianza\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "clave pblica %08lX no encontrada: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "clave pblica de la clave totalmente fiable %08lX no encontrada\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"comprobando en profundidad %d firmado=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"la firma no se pudo verificar.\n" -"Por favor recuerde que el fichero de firma (.sig o .asc)\n" -"debera ser el primero que se da en la lnea de rdenes.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "la lnea %u es demasiado larga o no tiene avance de lnea (LF)\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "clave no marcada como insegura - no puede usarse con el pseudo RNG\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "`%s' omitido: duplicado\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "`%s' omitido: %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "omitido: clave secreta ya presente\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"`%s' omitida: esta es una clave ElGamal generada por PGP que NO es segura " -"para las firmas\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "El fichero `%s' ya existe. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Sobreescribir (s/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: sufijo desconocido\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Introduzca nuevo nombre de fichero" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "escribiendo en stdout\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "asumiendo que hay datos firmados en `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: se ha creado un nuevo fichero de opciones\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: no se puede crear el directorio: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: directorio creado\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"ATENCIN: mensaje cifrado con una clave dbil en el cifrado simtrico.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problema trabajando con un paquete cifrado\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "creada clave dbil - reintentando\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"imposible evitar clave dbil para cifrado simtrico despus de %d " -"intentos!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA necesita un algoritmo de hash de 160 bits.\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "imposible hacer esto en modo de proceso por lotes sin \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Eliminar esta clave del anillo? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Esta es una clave secreta! Eliminar realmente? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "borrado de bloque de anillo de claves fallido: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "borrada informacin de propietarios\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "hay una clave secreta para esta clave pblica! \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "use antes la opcin \"--delete-secret-key\" para borrarla.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Est en su mano asignar un valor aqu. Dicho valor nunca ser exportado a\n" -"terceros. Es necesario para implementar la red de confianza, no tiene nada\n" -"que ver con la red de certificados (implcitamente creada)." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Para construir la Red-de-Confianza, GnuPG necesita saber qu claves\n" -"tienen confianza total - normalmente son las claves para las que usted\n" -"puede acceder a la clave secreta. Conteste \"yes\" para hacer que esta\n" -"clave se considere como de total confianza\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Si quiere usar esta clave revocada de todos modos, conteste \"s\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "Si quiere usar esta clave no fiable de todos modos, conteste \"s\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Introduzca el ID de usuario al que quiere enviar el mensaje." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Seleccione el algoritmo que usar.\n" -"\n" -"DSA (tambin conocido como DSS) es un algoritmo de firma digital que slo\n" -"puede usarse para firmas. Es el algoritmo sugerido porque la verificacin\n" -"de firmas DSA es mucho ms rpida que la de firmas ElGamal.\n" -"\n" -"ElGamal es un algoritmo que puede ser usado para firma y cifrado. OpenPGP\n" -"distingue entre dos tipos de estos algoritmos: slo para cifrado y para\n" -"firma y cifrado. En realidad es lo mismo, pero se deben seleccionar ciertos\n" -"parmetros de una forma particular para crear una clave segura para firmas.\n" -"Este programa lo hace as, pero otras implementaciones de OpenPGP no tienen\n" -"por qu entender el tipo de firma y cifrado.\n" -"\n" -"La clave primaria debe ser una clave capaz de firmar, es por ello que la\n" -"opcin de clave ElGamal slo para cifrado no est disponible en este men." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Aunque estas claves estn definidas en RFC2440, no se aconseja su uso,\n" -"ya que no todos los programas pueden utilizarlas y las firmas creadas\n" -"con ellas son bastante grandes y lentas de verificar." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Introduzca la longitud de la clave" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Responda \"s\" o \"no\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Introduzca el valor requerido conforme se muestra.\n" -"Es posible introducir una fecha ISO (AAAA-MM-DD), pero no se obtendr una\n" -"buena respuesta a los errores; el sistema intentar interpretar el valor\n" -"introducido como un intervalo." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Introduzca el nombre del dueo de la clave" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "" -"Introduzca una direccin de correo electrnico (opcional pero muy\n" -"recomendable)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Introduzca un comentario opcional" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N para cambiar el nombre.\n" -"C para cambiar el comentario.\n" -"E para cambiar la direccin.\n" -"O para continuar con la generacin de clave.\n" -"S para interrumpir la generacin de clave." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Responda \"s\" (o slo \"s\") para generar la subclave." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Cuando firme un ID de usuario en una clave, debera verificar que la clave\n" -"pertenece a la persona que se nombra en el ID de usuario. Es til para\n" -"otros saber cmo de cuidadosamente lo ha verificado.\n" -"\n" -"\"0\" significa que no hace ninguna declaracin concreta sobre como ha\n" -" comprobado la validez de la clave.\n" -"\n" -"\"1\" significa que cree que la clave pertenece a la persona que declara\n" -" poseerla pero no pudo o no verific la clave en absoluto. Esto es " -"til\n" -" para una verificacin en persona cuando firmas la clave de un usuario\n" -" pseudoannimo.\n" -"\n" -"\"2\" significa que hizo una comprobacin informal de la clave. Por ejemplo\n" -" podra querer decir que comprob la huella dactilar de la clave y\n" -" comprob el ID de usuario en la clave con un ID fotogrfico.\n" -"\n" -"\"3\" significa que hizo una comprobacin exhaustiva de la clave. Por\n" -" ejemplo verificando la huella dactilar de la clave con el propietario\n" -" de la clave, y que comprob, mediante un documento difcil de " -"falsificar\n" -" con ID fotogrfico (como un pasaporte) que el nombre del poseedor de " -"la\n" -" clave coincide con el ID de usuario en la clave y finalmente que " -"verific\n" -" (intercambiando email) que la direccin de email de la clave " -"pertenece\n" -" al poseedor de la clave.\n" -"\n" -"Observe que los ejemplos dados en los niveles 2 y 3 son *solo* ejemplos.\n" -"En definitiva, usted decide lo que significa \"informal\" y \"exhaustivo\"\n" -"para usted cuando firma las claves de otros.\n" -"\n" -"Si no sabe qu contestar, conteste \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Responda \"s\" si quiere firmar TODOS los IDs de usuario" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Responda \"s\" si realmente quiere borrar este ID de usuario.\n" -"Tambin se perdern todos los certificados!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Responda \"s\" si quiere borrar esta subclave" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Esta es una firma vlida de esta clave. Normalmente no ser deseable\n" -"borrar esta firma ya que puede ser importante para establecer una conexin\n" -"de confianza con la clave o con otra clave certificada por sta." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Esta firma no puede ser comprobada porque no tiene Vd. la clave\n" -"correspondiente. Debera posponer su borrado hasta conocer qu clave\n" -"se us, ya que dicha clave podra establecer una conexin de confianza\n" -"a travs de otra clave certificada." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "Esta firma no es vlida. Tiene sentido borrarla de su anillo." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Esta es una firma que une el ID de usuario a la clave. No suele ser una\n" -"buena idea borrar dichas firmas. De hecho, GnuPG podra no ser capaz de\n" -"volver a usar esta clave. As que brrela tan slo si esta autofirma no\n" -"es vlida por alguna razn y hay otra disponible." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Cambiar las preferencias de todos los IDs de usuario (o slo los \n" -"seleccionados) a la lista actual de preferencias. El sello de tiempo\n" -"de todas las autofirmas afectadas se avanzar en un segundo.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Por favor introduzca la contrasea: una frase secreta \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Repita la ltima contrasea para asegurarse de lo que tecle." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Introduzca el nombre del fichero al que corresponde la firma" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Responda \"s\" para sobreescribir el fichero" - -# Sugerencia: ENTER -> INTRO. -# Aceptada. -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Introduzca un nuevo nombre de fichero. Si pulsa INTRO se usar el fichero\n" -"por omisin (mostrado entre corchetes)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Debera especificar un motivo para la certificacin. Dependiendo del\n" -"contexto puede elegir una opcin de esta lista:\n" -" \"La clave ha sido comprometida\"\n" -" Use esto si tiene razones para pensar que personas no autorizadas\n" -" tuvieron acceso a su clave secreta.\n" -" \"La clave ha sido sustituida\"\n" -" Use esto si ha reemplazado la clave por otra ms nueva.\n" -" \"La clave ya no est en uso\"\n" -" Use esto si ha dejado de usar esta clave.\n" -" \"La identificacin de usuario ya no es vlida\"\n" -" Use esto para sealar que la identificacin de usuario no debera\n" -" seguir siendo usada; esto se utiliza normalmente para marcar una\n" -" direccin de correo-e como invlida.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Si lo desea puede introducir un texto explicando por qu emite\n" -"este certificado de revocacin. Por favor, que el texto sea breve.\n" -"Una lnea vaca pone fin al texto.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Ayuda no disponible" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "No hay ayuda disponible para `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "error escribiendo anillo `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "anillo `%s' creado\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "fallo reconstruyendo cach del anillo de claves: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "ATENCIN: existen 2 ficheros con informacin confidencial.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s es el que no se ha modificado\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s es el nuevo\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Por favor arregle este posible fallo de seguridad\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "comprobando anillo `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "hasta ahora procesadas %lu claves (%lu firmas)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu claves comprobadas (%lu firmas)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: anillo creado\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "reinicie GnuPG otra vez para que lea el nuevo fichero de opciones\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "al cambiar permisos de `%s' ocurri el fallo: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOMBRE=VALOR|usa estos datos de notacin" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "El primer carcter de una notacin debe ser una letra o un subrayado\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "los puntos en una notacin deben estar rodeados por otros caracteres\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "AVISO: Esta clave ya tiene identificador fotogrfico.\n" -#~ " Aadir otro ID puede confundir a algunas versiones de PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Solo puede tener un ID fotogrfico en una clave.\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Huella dactilar:" - -#~ msgid " Fingerprint:" -#~ msgstr " Huella dactilar:" - -#, fuzzy -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Seguro que quiere una clave de este tamao? " - -#, fuzzy -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr "Seguro que quiere una clave de este tamao? " - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Firmar de verdad? " - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "se solicitan demasiados bits aleatorios; el lmite es %d\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NOMBRES]|comprueba la base de datos de confianza" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key id-usuario" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key id-usuario" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key id-usuario" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Informacin en http://www.gnupg.org" - -#~ msgid "sSmMqQ" -#~ msgstr "iImMqQ" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "No puede encontrarse una ruta de confianza vlida para esta clave. " -#~ "Veamos\n" -#~ "si es posible asignar algunos valores de confianza perdidos.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "No se ha encontrado ninguna ruta con una de nuestras claves.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "No se ha encontrado ningn certificado sin valor de confianza.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "No se cambi ningn valor de confianza.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "" -#~ "%08lX: no hay informacin para calcular la probabilidad de confianza\n" - -#~ msgid "Enter the user ID: " -#~ msgstr "Introduzca el ID de usuario: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "omitida: clave pblica ya designada con --encrypt-to\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: error comprobando la clave: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "De verdad quiere crear una clave de firma y cifrado? " - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "De verdad necesita una clave tan grande? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: usuario no encontrado: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "problema en la lectura del certificado: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "demasiados registros en la cache unk - anulada\n" - -#~ msgid "no default public keyring\n" -#~ msgstr "no hay anillo pblico por defecto\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "clave secreta %08lX no importada (use %s para permitirlo)\n" - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "clave %08lX: nuestra copia no tiene autofirma\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: usuario no encontrado\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "actualizacin de base de datos de confianza fallida: %s\n" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "no hay servidores de claves conocidos (use opcin --keyserver)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "'%s' no es un identificador de clave vlido\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "asumiendo MDC incorrecto debido a un bit crtico desconocido\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "error leyendo registro de directorio del LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: esperaba registro directorio, encontrado tipo %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "no hay clave primaria para el LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "error leyendo clave primaria para el LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record fallida: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "clave %08lX: peticin de registro fallida\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "clave %08lX: ya est en la tabla de confianza\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "NOTA: la clave secreta %08lX NO est protegida.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "clave %08lX: las claves pblica y secreta no se corresponden\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "enumeracin de claves secretas fallida: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "clave %08lX.%lu: unin de subclave vlida\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "clave %08lX.%lu: unin de subclave invlida: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "clave %08lX.%lu: revocacin de clave vlida\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "clave %08lX.%lu: revocacin de clave invlida: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Autofirma vlida" - -#~ msgid "Invalid self-signature" -#~ msgstr "Autofirma invlida" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Revocacin vlida de ID de usuario omitida, existe autofirma ms reciente" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Revocacin de ID de usuario vlida" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Revocacin de ID de usuario invlida." - -#~ msgid "Valid certificate revocation" -#~ msgstr "Revocacin de certificado vlida" - -#~ msgid "Good certificate" -#~ msgstr "Certificado correcto" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Certificado de revocacin incorrecto" - -#~ msgid "Invalid certificate" -#~ msgstr "Certificado incorrecto" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "registro de firma %lu[%d] apunta al registro equivocado.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "certificado duplicado - eliminado" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir fallida: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: insercin fallida: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: insercin fallida: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: insertada\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "error leyendo registro de directorio: %s\n" - -#~ msgid "\t%lu keys with errors\n" -#~ msgstr "\t%lu claves con errores\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu claves insertadas\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: registro de directiorio sin clave - omitido\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu debido a las nuevas claves pblicas\n" - -# msgstr "clave %08lX: %d nuevas subclaves\n" -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu claves omitidas\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu claves actualizadas\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Oh oh, no hay claves\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Oh oh, no hay ningn ID de usuario\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: bsqueda registro directorio fallida: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "clave %08lX: insercin del registro de confianza fallida: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "clave %08lX.%lu: incluida en la base de datos de confianza\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "clave %08lX.%lu: creada en el futuro (salto en el tiempo o\n" -#~ "problemas con el reloj)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "clave %08lX.%lu: caducada el %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "clave %08lX.%lu: comprobacin de confianza fallida: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "problema buscando '%s' en la tabla de confianza: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "usuario '%s' no est en la tabla de confianza - insertando\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "fallo al poner '%s' en la tabla de confianza: %s\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "" -#~ "ATENCON: todava no puedo tratar registros de preferencias largos\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: no se puede crear el anillo: %s\n" - -#, fuzzy -#~ msgid "invalid" -#~ msgstr "Armadura no vlida" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "No puede usarse clave RSA en esta versin\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "No hay clave para tal usuario\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "No hay clave secreta para tal usuario\n" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "clave secreta para descifrado no disponible\n" - -#~ msgid "" -#~ "RSA keys are deprecated; please consider creating a new key and use this " -#~ "key in the future\n" -#~ msgstr "" -#~ "Las claves RSA estn en desuso, considere la creacin de una nueva clave " -#~ "para futuros usos\n" - -#~ msgid "set debugging flags" -#~ msgstr "establece los parmetros de depuracin" - -#~ msgid "enable full debugging" -#~ msgstr "habilita depuracin completa" - -#~ msgid "do not write comment packets" -#~ msgstr "no escribe paquetes de comentario" - -#~ msgid "(default is 1)" -#~ msgstr "(por defecto es 1)" - -#~ msgid "(default is 3)" -#~ msgstr "(por defecto es 3)" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal en un paquete v3\n" - -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "La creacin de claves slo es posible en modo interactivo\n" - -#, fuzzy -#~ msgid "tdbio_search_sdir failed: %s\n" -#~ msgstr "tdbio_search_dir fallida: %s\n" - -#~ msgid "print all message digests" -#~ msgstr "imprime todos los resmenes de mensaje" - -#~ msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n" -#~ msgstr "" -#~ "NOTA: el registro de firma %lu[%d] est en la lista\n" -#~ "de bsqueda de %lu pero est marcado como comprobado\n" - -#~ msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n" -#~ msgstr "" -#~ "NOTA: el registro de firma %lu[%d] est en la lista\n" -#~ "de bsqueda de %lu pero no est marcado\n" - -#~ msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n" -#~ msgstr "" -#~ "El registro de firma %lu[%d] en la lista de bsqueda de %lu\n" -#~ "no apunta a un registro de directorio\n" - -#~ msgid "lid %lu: no primary key\n" -#~ msgstr "lid %lu: ninguna clave primaria\n" - -#~ msgid "lid %lu: user id not found in keyblock\n" -#~ msgstr "" -#~ "lid %lu: no se ha encontrado identificativo de usuario\n" -#~ "en el bloque de clave\n" - -#~ msgid "lid %lu: user id without signature\n" -#~ msgstr "lid %lu: identificativo de usuario sin firma\n" - -#~ msgid "lid %lu: self-signature in hintlist\n" -#~ msgstr "lid %lu: autofirma en lista de bsqueda\n" - -#~ msgid "very strange: no public key\n" -#~ msgstr "muy raro: no hay clave pblica\n" - -#~ msgid "hintlist %lu[%d] of %lu does not point to a dir record\n" -#~ msgstr "" -#~ "la lista de bsqueda %lu[%d] de %lu no apunta a\n" -#~ "un registro de directorio\n" - -#~ msgid "lid %lu does not have a key\n" -#~ msgstr "lid %lu no dispone de clave\n" - -#~ msgid "lid %lu: can't get keyblock: %s\n" -#~ msgstr "lid %lu: no puedo obtener el bloque de clave: %s\n" - -#~ msgid "Too many preference items" -#~ msgstr "Demasiados tems de preferencias" - -#~ msgid "public key not anymore available" -#~ msgstr "clave pblica no disponible" - -#~ msgid "insert_trust_record: keyblock not found: %s\n" -#~ msgstr "insert_trust_record: bloque de clave no encontrado: %s\n" - -#~ msgid "lid %lu: update failed: %s\n" -#~ msgstr "lid %lu: actualizacin fallida: %s\n" - -#~ msgid "lid %lu: updated\n" -#~ msgstr "lid %lu: actualizado\n" - -#~ msgid "lid %lu: okay\n" -#~ msgstr "lid %lu: bien\n" - -#~ msgid "%s: keyblock read problem: %s\n" -#~ msgstr "%s: problema lectura del bloque de clave: %s\n" - -#~ msgid "%s: update failed: %s\n" -#~ msgstr "%s: actualizacin fallida: %s\n" - -#~ msgid "%s: updated\n" -#~ msgstr "%s: actualizada\n" - -#~ msgid "%s: okay\n" -#~ msgstr "%s: bien\n" - -#~ msgid "lid %lu: keyblock not found: %s\n" -#~ msgstr "lid %lu: bloque de clave no encontrado: %s\n" - -#~ msgid "can't lock keyring `%': %s\n" -#~ msgstr "no puede bloquearse el anillo pblico `%s': %s\n" - -#~ msgid "error writing keyring `%': %s\n" -#~ msgstr "error escribiendo anillo `%s': %s\n" - -#~ msgid "can't open file: %s\n" -#~ msgstr "no puede abrirse el fichero: %s\n" - -#~ msgid "read error: %s\n" -#~ msgstr "error de lectura: %s\n" - -#~ msgid "writing keyblock\n" -#~ msgstr "escribiendo bloque de claves\n" - -#~ msgid "can't write keyblock: %s\n" -#~ msgstr "no puede escribirse el bloque de claves: %s\n" - -#, fuzzy -#~ msgid "encrypted message is valid\n" -#~ msgstr "el algoritmo de resumen seleccionado no es vlido\n" - -#, fuzzy -#~ msgid "Can't check MDC: %s\n" -#~ msgstr "Imposible comprobar la firma: %s\n" - -#~ msgid "Usage: gpgm [options] [files] (-h for help)" -#~ msgstr "Uso: gpgm [opciones] [ficheros] (-h para ayuda)" - -#~ msgid "" -#~ "Syntax: gpgm [options] [files]\n" -#~ "GnuPG maintenance utility\n" -#~ msgstr "" -#~ "Sintaxis: gpgm [opciones] [ficheros]\n" -#~ "Utilidad de mantenimiento de GnuPG\n" - -#~ msgid "usage: gpgm [options] " -#~ msgstr "uso: gpgm [opciones] " - -#~ msgid "chained sigrec %lu has a wrong owner\n" -#~ msgstr "registro de firma encadenado %lu tiene el propietario equivocado\n" - -#~ msgid "lid %lu: read dir record failed: %s\n" -#~ msgstr "lid %lu: lectura registro de directorio fallida: %s\n" - -#~ msgid "lid %lu: read key record failed: %s\n" -#~ msgstr "lid %lu: lectura registro de clave fallida: %s\n" - -#~ msgid "lid %lu: read uid record failed: %s\n" -#~ msgstr "lid %lu: lectura registro identificativo fallida: %s\n" - -#~ msgid "lid %lu: read pref record failed: %s\n" -#~ msgstr "lid %lu: lectura registro preferencias fallida: %s\n" - -#~ msgid "user '%s' read problem: %s\n" -#~ msgstr "problema de lectura usuario '%s': %s\n" - -#~ msgid "user '%s' list problem: %s\n" -#~ msgstr "problema lista usuario '%s': %s\n" - -#~ msgid "user '%s' not in trustdb\n" -#~ msgstr "usuario '%s' no est en la tabla de confianza\n" - -#~ msgid "" -#~ "# List of assigned trustvalues, created %s\n" -#~ "# (Use \"gpgm --import-ownertrust\" to restore them)\n" -#~ msgstr "" -#~ "# Lista de valores de confianza, creada el %s\n" -#~ "# (Puede usar \"gpgm --import-ownertrust\" para restablecerlos)\n" - -#~ msgid "directory record w/o primary key\n" -#~ msgstr "registro de directorio sin clave primaria\n" - -#~ msgid "error: missing colon\n" -#~ msgstr "error: falta ':'\n" - -#~ msgid "error: invalid fingerprint\n" -#~ msgstr "error: huella dactilar no vlida\n" - -#~ msgid "error: no ownertrust value\n" -#~ msgstr "error: no hay valor de confianza del propietario\n" - -#~ msgid "key not in trustdb, searching ring.\n" -#~ msgstr "la clave no est en tabla de confianza, buscando en el anillo.\n" - -#~ msgid "key not in ring: %s\n" -#~ msgstr "la clave no est en el anillo: %s\n" - -#~ msgid "Oops: key is now in trustdb???\n" -#~ msgstr "Oh oh: la clave ahora est en la tabla de confianza???\n" - -#~ msgid "Hmmm, public key lost?" -#~ msgstr "Oh oh, se ha perdido la clave pblica?" - -#~ msgid "did not use primary key for insert_trust_record()\n" -#~ msgstr "no se us clave primaria para insert_trust_record()\n" - -#~ msgid "second" -#~ msgstr "segundo" - -#~ msgid "seconds" -#~ msgstr "segundos" diff --git a/po/et.po b/po/et.po deleted file mode 100644 index 0cbbbaf4a..000000000 --- a/po/et.po +++ /dev/null @@ -1,4646 +0,0 @@ -# Estonian translations for gnupg. -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. -# Toomas Soome , 2002. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-05-10 08:47+0300\n" -"Last-Translator: Toomas Soome \n" -"Language-Team: Estonian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-15\n" -"Content-Transfer-Encoding: 8-bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Hoiatus: kasutan ebaturvalist mlu!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "Lisainfot leiate lehelt http://www.gnupg.org/faq.html\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "initsialiseerimata turvalise mluta ei ole operatsioon vimalik\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(te kasutasite vahest selle t jaoks valet programmi)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "jah" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "jJ" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "ei" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "eE" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "vlju" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "vV" - -#: util/errors.c:54 -msgid "general error" -msgstr "ldine viga" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "tundmatu paketi tp" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "tundmatu versioon" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "tundmatu avaliku vtme algoritm" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "tundmatu lhendi algoritm" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "halb avalik vti" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "halb salajane vti" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "halb allkiri" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "kontrollsumma viga" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "halb parool" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "ei leia avalikku vtit" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "tundmatu ifri algoritm" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "vtmehoidlat ei nnestu avada" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "vigane pakett" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "vigane pakend" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "sellist kasutaja id pole" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "salajane vti ei ole kttesaadav" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "kasutati valet salajast vtit" - -#: util/errors.c:72 -msgid "not supported" -msgstr "ei ole toetatud" - -#: util/errors.c:73 -msgid "bad key" -msgstr "halb vti" - -#: util/errors.c:74 -msgid "file read error" -msgstr "viga faili lugemisel" - -#: util/errors.c:75 -msgid "file write error" -msgstr "viga faili kirjutamisel" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "tundmatu pakkimisalgoritm" - -#: util/errors.c:77 -msgid "file open error" -msgstr "viga faili avamisel" - -#: util/errors.c:78 -msgid "file create error" -msgstr "viga faili loomisel" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "vigane parool" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "realiseerimata avaliku vtme algoritm" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "realiseerimata ifri algoritm" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "tundmatu allkirja klass" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "usalduse andmebaasi viga" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "halb MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "ressursi limiit" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "vigane vtmehoidla" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "halb sertifikaat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "vigane kasutaja id" - -#: util/errors.c:89 -msgid "file close error" -msgstr "viga faili sulgemisel" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "viga faili mber nimetamisel" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "viga faili kustutamisel" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "ootamatud andmed" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "ajatemplite konflikt" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "mittekasutatav avaliku vtme algoritm" - -#: util/errors.c:95 -msgid "file exists" -msgstr "fail on olemas" - -#: util/errors.c:96 -msgid "weak key" -msgstr "nrk vti" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "vigane argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "halb URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "mittetoetatud URI" - -#: util/errors.c:100 -msgid "network error" -msgstr "vrgu viga" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "krptimata" - -#: util/errors.c:103 -msgid "not processed" -msgstr "ei tdeldud" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "mittekasutatav avalik vti" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "mittekasutatav salajane vti" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "vtmeserveri viga" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... see on viga (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "te leidsite vea ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "`%s' ei nnestu avada: %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "ei nnestu lugeda `%s' atribuute: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' ei ole tavaline fail - ignoreerin\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "mrkus: random_seed fail on thi\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "hoiatus: vigane random_seed faili suurus - ei kasuta\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "`%s' ei nnestu lugeda: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "mrkus: random_seed faili ei uuendatud\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "`%s' ei nnestu luua: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "`%s' ei nnestu kirjutada: %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "`%s' ei nnestu sulgeda: %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "HOIATUS: kasutan ebaturvalist juhuarvude generaatorit!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Juhuarvude generaator on ainult thi kest, et programmid\n" -"kiks - see EI OLE tugev juhuarvude generaator!\n" -"\n" -"RGE KASUTAGE SELLE PROGRAMMI POOLT GENEREERITUD ANDMEID!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Juhuslikke baite ei ole piisavalt. Palun tehke arvutiga muid tid,\n" -"et anda masinal vimalust koguda enam entroopiat! (Vajatakse %d baiti)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Ksud:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[fail]|loo allkiri" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[fail]|loo avateksti allkiri" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "loo eraldiseisev allkiri" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "krpteeri andmed" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[failid]|krpteeri failid" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "krpteerimine kasutades ainult smmeetrilist ifrit" - -#: g10/g10.c:315 -msgid "store only" -msgstr "ainult salvesta" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "dekrpteeri andmed (vaikimisi)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[failid]|dekrpteeri failid" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "kontrolli allkirja" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "nita vtmeid" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "nita vtmeid ja allkirju" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "kontrolli vtmete allkirju" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "nita vtmeid ja srmejlgi" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "nita salajasi vtmeid" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "genereeri uus vtmepaar" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "eemalda vtmed avalike vtmete hoidlast" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "eemalda vtmed salajaste vtmete hoidlast" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "allkirjasta vti" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "allkirjasta vti lokaalselt" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "allkirjasta vti mitte-thistatavana" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "allkirjasta vti lokaalselt ja mitte-thistatavana" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "allkirjasta vi toimeta vtit" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "genereeri thistamise sertifikaat" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "ekspordi vtmed" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "ekspordi vtmed vtmeserverisse" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "impordi vtmed vtmeserverist" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "otsi vtmeid vtmeserverist" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "uuenda vtmeid vtmeserverist" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "impordi/mesti vtmed" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "nita ainult pakettide jrjendeid" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "ekspordi usalduse vrtused" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "impordi usalduse vrtused" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "uuenda usalduse andmebaasi" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "hooldusvaba usalduse andmebaasi uuendamine" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "paranda vigane usalduse andmebaas" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Pakenda fail vi standardsisend lahti" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Pakenda fail vi standardsisend" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [failid]|trki teatelhendid" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Vtmed:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "loo ascii pakendis vljund" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NIMI|krpti NIMEle" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NIMI|kasuta NIME vaikimisi saajana" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "kasuta vaikimisi saajana vaikimisi vtit" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "kasuta seda kasutaja IDd" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|mra pakkimise tase N (0 blokeerib)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "kasuta kanoonilist tekstimoodi" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "kasuta vljundfailina" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "ole jutukas" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "ole mnevrra vaiksem" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "ra kasuta terminali" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "kasuta v3 allkirju" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "ra kasuta v3 allkirju" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "kasuta v4 vtme allkirju" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "ra kasuta v3 vtme allkirju" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "krptimisel kasuta alati MDC" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "krptimisel ra kasuta kunagi MDC" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "ra tee mingeid muutusi" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "kasuta gpg-agenti" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "pakettmood: ra ksi kunagi" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "eelda enamus ksimustele jah vastust" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "eelda enamus ksimustele ei vastust" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "lisa see vtmehoidla vtmehoidlate nimekirja" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "lisa see salajaste vtmete hoidla nimekirja" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "nita millisesse vtmehoidlasse nidatud vti kuulub" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NIMI|kasuta NIME vaikimisi salajase vtmena" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|kasuta seda vtmeserverit" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NIMI|terminali kooditabel on NIMI" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "loe vtmed failist" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FP|kirjuta olekuinfo sellesse failipidemesse" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[fail]|kirjuta olekuinfo faili" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|VTMEID|usalda seda vtit tielikult" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FAIL|lae laiendusmoodul FAIL" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emuleeri dokumendis RFC1991 kirjeldatud moodi" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "kasuta kikides tegevustes OpenPGP vtmeid" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "kasuta kikide pakettide, iffrite ja lhendi seadeid PGP 2.x moodis" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|kasuta parooli moodi N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NIMI|kasuta paroolidega lhendialgoritmi NIMI" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NIMI|kasuta paroolidega ifri algoritmi NIMI" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NIMI|kasuta ifri algoritmi NIMI" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NIMI|kasuta teatelhendi algoritmi NIMI" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|kasuta pakkimisalgoritmi N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "ra lisa krptimisel vtme id" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Esita foto IDd" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Ei esita foto IDd" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Sea ksurida foto ID vaatamiseks" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Kikide kskude ja vtmete tieliku kirjelduse leiate manualist)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Nited:\n" -"\n" -" -se -r Bob [fail] allkirjasta ja krpti kasutajale Bob\n" -" --clearsign [fail] loo avateksti allkiri\n" -" --detach-sign [fail] loo eraldiseisev allkiri\n" -" --list-keys [nimed] nita vtmeid\n" -" --fingerprint [nimed] nita srmejlgi\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Palun saatke veateated aadressil .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Kasuta: gpg [vtmed] [failid] (-h nitab abiinfot)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sntaks: gpg [vtmed] [failid]\n" -"allkirjasta, kontrolli, krpti ja dekrpti\n" -"vaikimisi operatsioon sltub sisendandmetest\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Toetatud algoritmid:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "kasuta: gpg [vtmed] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "vastuolulised ksud\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Hoiatus: ebaturvaline omanik %s \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Hoiatus: ebaturvalised igused %s \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Hoiatus: ebaturvaline omanik %s \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Hoiatus: ebaturvalised igused %s \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "MRKUS: vaikimisi vtmete fail `%s' puudub\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "MRKUS: vaikimisi vtmete fail `%s' puudub\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "vtmete fail `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "loen vtmeid failist `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s ei ole lubatud kooditabel\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "ei saa parsida vtmeserveri URI\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: vigane faili versioon %d\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "vigane pakend" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: vigane faili versioon %d\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "vigane vtmehoidla" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "exec-path vrtuseks ei nnestu seada %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "HOIATUS: programm vib salvestada oma mlupildi!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "HOIATUS: %s mrab le %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "MRKUS: %s ei ole tavapraseks kasutamiseks!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s ja %s ei ole koos lubatud!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s ja %s ei oma koos mtet!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -"--pgp2 moodis saate luua ainult eraldiseisvaid vi avateksti allkirju\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "--pgp2 moodis ei saa korraga allkirjastada ja krpteerida\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "--pgp2 moodis peate kasutama faile (ja mitte toru).\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "teate krpteerimine --pgp2 moodis nuab IDEA iffrit\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "see teade ei pruugi olla PGP 2.x programmidega kasutatav\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "valitud ifri algoritm ei ole lubatud\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "valitud lhendi algoritm ei ole lubatud\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "valitud lhendi algoritm ei ole lubatud\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "pakkimise algoritm peab olema vahemikust %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed peab olema suurem, kui 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed peab olema suurem, kui 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth peab olema vahemikus 1 kuni 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "MRKUS: lihtne S2K mood (0) ei soovitata kasutada\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "vigane S2K mood; peab olema 0, 1 vi 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "vigane vaikimisi kontrolli mood; peab olema 0, 1, 2 vi 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "vigased eelistused\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "vigased eelistused\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "vigased eelistused\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "vigased eelistused\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "TrustDB initsialiseerimine ebannestus: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [failinimi]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [failinimi]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [failinimi]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [failinimi]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [failinimi]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [failinimi]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [failinimi]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [failinimi]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key kasutaja-id" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key kasutaja-id" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key kasutaja-id" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key kasutaja-id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key kasutaja-id [ksud]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "%s ei nnestu avada: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [kasutaja-id] [vtmehoidla]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "lahtipakendamine ebannestus: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "pakendamine ebannestus: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "vigane teatelhendi algoritm `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[failinimi]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Kirjutage nd oma teade ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "`%s' ei nnestu avada\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"noteerimise nimes vivad olla ainult thed, numbrid, punktid ja alakriipsud\n" -"ning lpus peab olema '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "noteerimise vrtus ei vi sisaldada kontroll smboleid\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "antud sertifikaadi poliisi URL on vigane\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "antud allkirja poliisi URL on vigane\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "pakend: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "vigane pakendi pis: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "pakendi pis: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "vigane avateksti allkirja pis\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "avateksti allkirjad ksteise sees\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "vigane kriipsudega mrgitud rida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "ootamatu pakend:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "vigane radix64 smbol %02x vahele jetud\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "enneaegne faililpp (puudub CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "enneaegne faililpp (poolik CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "vigane CRC\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "CRC viga; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "enneaegne faililpp (lpetaval real)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "viga lpetaval real\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "ei leia OpenPGP andmeid.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "vigane pakend: rida on pikem, kui %d smbolit\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"kvooditud smbol pakendis - tenoliselt on kasutatud vigast MTA programmi\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Phjus puudub" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Vti on asendatud" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Vti on kompromiteeritud" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Vti ei ole enam kasutusel" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Kasutaja ID ei ole enam kehtiv" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Thistamise phjus: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Thistamise kommentaar: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iItTvVjJ" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Usalduse vrtus puudub:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Palun otsustage, kuivrd te usaldate seda kasutajat\n" -"teiste kasutajate vtmete kontrollimisel (kontrollige\n" -"passe, kontrollige erinevatest allikatest npujlgi...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Ei tea\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = EI usalda\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Usaldan vhesel mral\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Usaldan tiesti\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Usaldan absoluutselt\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = esita palun tiendavat infot\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " t = tagasi phimensse\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " j = jta see vti vahele\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " v = vlju\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Teie otsus? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Kas te testi soovite seda vtit absoluutselt usaldada? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Sertifikaadid tiesti usaldatava vtmeni:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "vti %08lX: vti on thistatud!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Kasutan seda vtit ikka? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "vti %08lX: alamvti on thistatud!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: vti on aegunud\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "%08lX: Ei ole midagi, mis nitaks, et see vti kuulub omanikule\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Me EI usalda seda vtit\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Ei ole kindel, et see vti testi kuulub omanikule,\n" -"aktsepteerime seda siiski\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "See vti kuulub tenoliselt omanikule\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "See vti kuulub meile\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"EI ole kindel, et see vti kuulub tema omanikule.\n" -"Kui te *testi* teate, mida te teete, vite jrgnevale\n" -"ksimusele vastata jaatavalt\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "HOIATUS: Kasutan mitteusaldatavat vtit!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "HOIATUS: See vti on omaniku poolt thistatud!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " See vib thendada, et allkiri on vltsing.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "HOIATUS: See alamvti on omaniku poolt thistatud!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Mrkus: See vti on blokeeritud.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Mrkus: See vti on aegunud!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "HOIATUS: Seda vtit ei ole sertifitseeritud usaldatava allkirjaga!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " Ei ole midagi, mis nitaks, et allkiri kuulub omanikule.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "HOIATUS: Me EI usalda seda vtit!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Allkiri on tenoliselt VLTSING.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"HOIATUS: Seda vtit ei ole sertifitseeritud piisavalt usaldatava " -"allkirjaga!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Ei ole kindel, et allkiri kuulub omanikule.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: jtsin vahele: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: jtsin vahele: avalik vti on juba olemas\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Te ei mranud kasutaja IDd. (vite kasutada vtit \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Sisestage kasutaja ID. Lpetage thja reaga: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Tundmatu kasutaja ID.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "jtsin vahele: avalik vti on juba vaikimisi saaja\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Avalik vti on blokeeritud.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "jtsin vahele: avalik vti on juba olemas\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "tundmatu vaikimisi saaja `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: jtsin vahele: avalik vti on blokeeritud\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "kehtivaid aadresse pole\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "eelistus %c%lu ei ole lubatud\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "eelistus %c%lu on duplikaat\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "liiga palju `%c' eelistusi\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "lubamatu smbol eelistuste snes\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "kirjutan iseenda allkirja\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "kirjutan iseenda allkirja\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "kirjutan vtit siduva allkirja\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "vigane vtme suurus; kasutan %u bitti\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "vtme suurus mardatud les %u bitini\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Palun valige, millist vtmetpi te soovite:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA ja ElGamal (vaikimisi)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (ainult allkirjastamiseks)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (ainult krptimiseks)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (allkirjastamiseks ja krptimiseks)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (ainult allkirjastamiseks)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (ainult krpteerimiseks)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (allkirjastamiseks ja krptimiseks)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Teie valik? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Selle algoritmi kasutamine ei ole soovitatav - loon ikkagi? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Vigane valik.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Enne uue %s vtmepaari genereerimist.\n" -" minimaalne vtmepikkus on 768 bitti\n" -" vaikimisi vtmepikkus on 1024 bitti\n" -" suurim soovitatav vtmepikkus on 2048 bitti\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Millist vtmepikkust te soovite? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA lubab vtmepikkuseid ainult vahemikus 512 kuni 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "vtmepikkus on liiga vike; RSA korral on vikseim vrtus 1024.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "vtmepikkus on liiga vike; vikseim lubatud vrtus on 768.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "vtmepikkus on liiga suur; suurim lubatud vrtus on %d.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Suuremad vtmepikkused kui 2048 ei ole soovitatavad, kuna\n" -"arvutused vtavad VGA palju aega!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Olete kindel, et soovite sellist vtmepikkust? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Olgu, kuid pidage meeles, et ka teie monitor ja klaviatuur on samuti\n" -"vimalikud rndeobjektid!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Soovitud vtmepikkus on %u bitti\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "mardatud les %u bitini\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Palun mrake, kui kaua on vti kehtiv.\n" -" 0 = vti ei aegu\n" -" = vti aegub n pevaga\n" -" w = vti aegub n ndalaga\n" -" m = vti aegub n kuuga\n" -" y = vti aegub n aastaga\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Palun mrake, kui kaua allkiri kehtib.\n" -" 0 = allkiri ei aegu\n" -" = allkiri aegub n pevaga\n" -" w = allkiri aegub n ndalaga\n" -" m = allkiri aegub n kuuga\n" -" y = allkiri aegub n aastaga\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Vti on kehtiv kuni? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Allkiri on kehtiv kuni? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "vigane vrtus\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s ei aegu kunagi\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s aegub %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Teie ssteem ei saa esitada kuupevi peale aastat 2038.\n" -"Siiski ksitletakse neid korrektselt aastani 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "On see ige (j/e)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Vtme identifitseerimiseks on vaja mrata kasutaja; tarkvara konstrueerib\n" -"kasutaja id kasutades prisnime, kommentaari ja e-posti aadressi kujul:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Prisnimi: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Lubamatu smbol nimes\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Nimi ei vi alata numbriga\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Nimes peab olema vhemalt 5 smbolit\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "E-posti aadress: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Selline e-posti aadress ei ole lubatud\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Kommentaar: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Lubamatu smbol kommentaaris\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Te kasutate kooditabelit `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Te valisite selle KASUTAJA-ID:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "rge palun kirjutage e-posti aadressi prisnimesse ega kommentaari\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnKkEeOoVv" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Muuda (N)ime, (K)ommentaari, (E)posti vi (V)lju? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Muuda (N)ime, (K)ommentaari, (E)posti vi (O)k/(V)lju? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Palun parandage kigepealt viga\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Te vajate oma salajase vtme kaitsmiseks parooli.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "parooli ei korratud ieti; proovige uuesti" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Te ei soovi parooli - see on tenoliselt *halb* idee!\n" -"Ma siiski tidan teie soovi. Te saate oma parooli alati muuta,\n" -"kasutades seda programmi vtmega \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Me peame genereerima palju juhuslikke baite. Praegu oleks hea teostada\n" -"arvutil mingeid teisi tegevusi (kirjutada klaviatuuril, liigutada hiirt,\n" -"kasutada kettaid jne), see annaks juhuarvude generaatorile vimaluse\n" -"koguda paremat entroopiat.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSA vtmepaari pikkuseks saab 1024 bitti.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Vtme genereerimine katkestati.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "kirjutan avaliku vtme faili `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "kirjutan salajase vtme faili `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "kirjutatavat avalike vtmete hoidlat pole: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "kirjutatavat salajaste vtmete hoidlat pole: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "viga avaliku vtme vtmehoidlasse `%s' kirjutamisel: %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "viga salajase vtme vtmehoidlasse `%s' kirjutamisel: %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "avalik ja salajane vti on loodud ja allkirjastatud.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "vti on mrgitud abslouutselt usaldatuks.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Pidage silmas, et seda vtit ei saa kasutada krptimiseks. \n" -"Krptimiseks tuleb genereerida teine vti, seda saate teha\n" -"kasutades vtit \"--edit-key\".\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Vtme genereerimine ebannestus: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "vti loodi %lu sekund tulevikus (ajahpe vi kella probleem)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "vti loodi %lu sekundit tulevikus (ajahpe vi kella probleem)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "MRKUS: v3 vtmetele alamvtmete loomine ei ole OpenPGP hilduv\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Loon testi? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "vti --output ei tta selle ksuga\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: ei nnestu avada: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "viga parooli loomisel: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' on juba pakitud\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: HOIATUS: thi fail\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"RSA vtmeid pikkusega kuni 2048 bitti saab krpteerida ainult --pgp2 moodis\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "loen failist `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "kikide krpteeritavate vtmetega ei saa IDEA iffrit kasutada.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "MRKUS: ifri algoritm %d puudub eelistustes\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "See ksklus ei ole %s moodis lubatud.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s krptitud kasutajale: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "vtit '%s' ei leitud: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "viga vtmebloki lugemisel: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "vti %08lX: ei ole rfc2440 vti - jtsin vahele\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "vti %08lX: ei ole kaitstud - jtsin vahele\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "vti %08lX: PGP 2.x stiilis vti - jtsin vahele\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "HOIATUS: midagi ei eksporditud\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "avalike vtmete puhvris on liiga palju vtmeid - blokeerin\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Kasutaja id puudub]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Vigane vti %08lX muudeti kehtivaks vtme --allow-non-selfsigned-uid " -"kasutamisega\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "kasutan sekundaarset vtit %08lX primaarse vtme %08lX asemel\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "vti %08lX: salajane vti avaliku vtmeta - jtsin vahele\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "jtan bloki tbiga %d vahele\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu vtit on seni tdeldud\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "viga `%s' lugemisel: %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Tdeldud kokku: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " vahele jetud uusi vtmeid: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " puudub kasutaja ID: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " imporditud: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " muutmata: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " uusi kasutajaid: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " uusi alamvtmeid: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " uusi allkirju: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " uusi thistamisi: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " loetud salajasi vtmeid: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " salajasi vtmeid imporditud: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " muutmata salajasi vtmeid: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " imporditud: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "vti %08lX: kasutaja ID puudub\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "vti %08lX: vtmeseosel puudub alamvti\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "" -"vti %08lX: aktsepteerisin iseenda poolt allakirjutamata kasutaja ID '%s'\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "vti %08lX: puudub kehtiv kasutaja ID\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "see vib olla phjustatud puuduvast iseenda allkirjast\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "vti %08lX: avalikku vtit ei leitud: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "vti %08lX: uus vti - jtsin vahele\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "ei leia kirjutatavat vtmehoidlat: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "kirjutan faili `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "viga vtmehoidlasse `%s' kirjutamisel: %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "vti %08lX: avalik vti on imporditud\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "vti %08lX: ei sobi meie koopiaga\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "vti %08lX: ei leia algset vtmeblokki: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "vti %08lX: ei nnestu lugeda algset vtmeblokki: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "vti %08lX: 1 uus kasutaja ID\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "vti %08lX: %d uut kasutaja IDd\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "vti %08lX: 1 uus allkiri\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "vti %08lX: %d uut allkirja\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "vti %08lX: 1 uus alamvti\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "vti %08lX: %d uut alamvtit\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "vti %08lX: ei muudetud\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "puudub salajaste vtmete vaikimisi vtmehoidla: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "vti %08lX: salajane vti on imporditud\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "vti %08lX: on juba salajaste vtmete hoidlas\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "vti %08lX: salajast vtit ei leitud: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"vti %08lX: avalik vti puudub - thistamise sertifikaati ei saa rakendada\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "vti %08lX: vigane thistamise sertifikaat: %s - lkkasin tagasi\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "vti %08lX: thistamise sertifikaat imporditud\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "vti %08lX: allkirjal puudub kasutaja ID\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "vti %08lX: mittetoetatud avaliku vtme algoritm kasutajaga \"%s\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "vti %08lX: kasutajal \"%s\" on vigane iseenda allkiri\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "vti %08lX: vtmeseosel puudub alamvti\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "vti %08lX: mittetoetatud avaliku vtme algoritm\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "vti %08lX: vigane alamvtme seos\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "vti %08lX: vigane alamvtme seos\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "vti %08lX: vtmeseosel puudub alamvti\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "vti %08lX: vigane alamvtme seos\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "vti %08lX: vigane alamvtme seos\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "vti %08lX: jtsin vahele kasutaja ID '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "vti %08lX: jtsin alamvtme vahele\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "vti %08lX: mitte eksporditav allkiri (klass %02x) - jtan vahele\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "vti %08lX: thistamise sertifikaat on vales kohas - jtan vahele\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "vti %08lX: vigane thistamise sertifikaat: %s - jtan vahele\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "vti %08lX: thistamise sertifikaat on vales kohas - jtan vahele\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "vti %08lX: tuvastasin dubleeritud kasutaja ID - mestisin\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"Hoiatus: vti %08lX vib olla thistatud: laen thistamise vtit %08lX\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"Hoiatus: vti %08lX vib olla thistatud: thistamise vtit %08lX pole.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "vti %08lX: thistamise sertifikaat lisatud\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "vti %08lX: lisatud vahetu vtme allkiri\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[thistamine]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[iseenda allkiri]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 halb allkiri\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d halba allkirja\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 allkiri ji testimata, kuna vti puudub\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d allkirja ji testimata, kuna vtmed puuduvad\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 allkiri ji vea tttu kontrollimata\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d allkirja ji vigade tttu kontrollimata\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "tuvastasin he kehtiva iseenda allkirjata kasutaja ID\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "tuvastasin %d kehtiva iseenda allkirjata kasutaja IDd\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Kasutaja ID \"%s\" on thistatud." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Olete kindel, et soovite seda ikka allkirjastada? (j/e) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Ei saa allkirjastada.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "HOIATUS: `%s' on thi fail\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Teie praegune allkiri \"%s\"\n" -"on lokaalne allkiri.\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" -"Kas te soovite seda edutada tielikuks eksporditavaks allkirjaks? (j/E) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Teie praegune allkiri \"%s\"\n" -"on lokaalne allkiri.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" -"Kas te soovite seda edutada tielikuks eksporditavaks allkirjaks? (j/E) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" on juba lokaalselt allkirjastatud vtmega %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" on juba allkirjastatud vtmega %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Vtmega %08lX pole midagi allkirjastada\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "See vti on aegunud!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "See vti aegub %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Soovite, et teie allkiri aeguks samal ajal? (J/e) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "--pgp2 moodis ei saa PGP 2.x vtmele OpenPGP allkirja anda.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "See muudab vtme PGP 2.x programmidega mitte-kasutatavaks.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Kui hoolikalt te olete kontrollinud et vti, mida te asute allkirjastama,\n" -"kuulub ka tegelikult lal mainitud isikule? Kui te ei tea, mida vastata,\n" -"sisestage \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Ma ei vasta.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Ma ei ole ldse kontrollinud.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Ma olen teinud pealiskaudset kontrolli.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Ma olen kontrollinud vga hoolikalt.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Olete testi kindel, et soovite seda vtit oma\n" -"vtmega allkirjastada: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "see vib olla phjustatud puuduvast iseenda allkirjast\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"Allkiri mrgitakse mitte-eksporditavaks.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"Allkiri mrgitakse kehtetuks mitte-tunnistatavaks.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"Allkiri mrgitakse mitte-eksporditavaks.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"Allkiri mrgitakse kehtetuks mitte-tunnistatavaks.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Ma ei ole seda vtit ldse kontrollinud.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Ma olen seda vtit kontrollinud ainult pealiskaudselt.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Ma olen kontrollinud seda vtit vga hoolikalt.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Allkirjastan testi? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "allkirjastamine ebannestus: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "See vti ei ole kaitstud.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Primaarse vtme salajased komponendid ei ole kttesaadavad.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Vti on kaitstud.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Seda vtit ei nnestu toimetada: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Sisestage sellele salajasele vtmele uus parool.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Te ei soovi parooli - see on tenoliselt *halb* idee!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Kas te testi soovite seda teha? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "tstan vtme allkirja igesse kohta\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "vlju sellest menst" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "v" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "salvesta ja vlju" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "nita seda abiinfot" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "nita srmejlge" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "nita vtit ja kasutaja IDd" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "vali kasutaja ID N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "vali sekundaarne vti N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "nita allkirju" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "allkirjasta vti" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "allkirjasta vti lokaalselt" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "allkirjasta vti kehtetuks mitte-tunnistatavana" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "allkirjasta vti lokaalselt ja kehtetuks mitte-tunnistatavana" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "lisa kasutaja ID" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "lisa foto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "lisa foto ID" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "kustuta kasutaja ID" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "lisa sekundaarne vti" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "kustuta sekundaarne vti" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "lisa sekundaarne vti" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "kustuta allkirjad" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "muuda aegumise kuupeva" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primaarne" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "mrgi kasutaja ID primaarseks" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "llita" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "llita salajaste vi avalike vtmete loendi vahel" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "nita eelistusi (ekspert)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "nita eelistusi (detailsena)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "sea eelistuste nimekiri" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "uuendatud eelistused" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "muuda parooli" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "muuda omaniku usaldust" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "thista allkirjad" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "thista sekundaarne vti" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "blokeeri vti" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "luba vti" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "nita foto ID" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "seda ei saa teha pakettmoodis\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "viga salajase vtmebloki `%s' lugemisel: %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Salajane vti on kasutatav.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Ksklus> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Selle tegamiseks on vaja salajast vtit.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Palun kasutage kigepealt ksku \"toggle\".\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "Vti on thistatud." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Kas allkirjastan testi kik kasutaja IDd? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Vihje: Valige allkirjastamiseks kasutaja\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "See ksklus ei ole %s moodis lubatud.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Te peate valima vhemalt he kasutaja ID.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Viimast kasutaja ID ei saa kustutada!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Kas kustutan testi kik kasutaja IDd? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Kas eemaldan testi selle kasutaja ID? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Te peata valima vhemalt he vtme.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Kas te testi soovite valitud vtmeid kustutada? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Kas te testi soovite seda vtit kustutada? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Kas te testi soovite valitud vtmeid thistada? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Kas te testi soovite seda vtit thistada? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "Kas uuendan testi kik kasutaja ID-de seaded? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Kas testi uuendan seaded? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Salvestan muutused? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Vljun salvestamata? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "uuendamine ebannestus: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "salajase vtme uuendamine ebannestus: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Vtit ei muudetud, seega pole uuendamist vaja.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Vigane ksklus (proovige \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Selle vtme vib olla thistanud %s vti %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (tundlik)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX loodud: %s aegub: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " usaldus: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "See vti on blokeeritud" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! alamvti on thistatud: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- leitud vltsitud thistamine\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? probleem thistamise kontrollimisel: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Tuleb thele panna, et kuni te pole programmi uuesti kivitanud,ei pruugi " -"nidatud vtme kehtivus olla tingimata korrektne.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"HOIATUS: See on PGP2-stiilis vti. Foto ID lisamine vib sundida mningaid\n" -" PGP versioone seda vtit tagasi lkkama.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Olete kindel, et soovite seda ikka lisada? (j/E) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Foto IDd ei saa PGP2 vtmele lisada.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Kustutan selle korrektse allkirja? (j/E/v)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Kustutan selle vigase allkirja? (j/E/v)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Kustutan selle tundmatu allkirja? (j/E/v)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Kas testi kustutan selle iseenda allkirja? (j/E)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Kustutatud %d allkiri.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Kustutatud %d allkirja.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Midagi ei kustutatud.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Sisestage vtmepikkus" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Palun eemaldage salajastelt vtmetelt valikud.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "palun valige limalt ks sekundaarne vti.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Muudan sekundaarse vtme aegumise aega.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Muudan primaarse vtme aegumise aega.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "v3 vtme aegumise aega ei saa muuta.\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Vastavat allkirja salajaste vtmete hoidlas pole\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Palun valige tpselt ks kasutaja ID.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "vti %08lX: kasutajal \"%s\" on vigane iseenda allkiri\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Kasutaja ID numbriga %d puudub\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Sekundaarne vti numbriga %d puudub\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "kasutaja ID: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"allkirjastatud teie vtmega %08lX %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"lokaalselt allkirjastatud teie vtmega %08lX %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "See allkiri aegub %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Olete kindel, et soovite seda ikka thistada? (j/E) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Loon sellele allkirjale thistamise sertifikaadi? (j/E) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Te olete allkirjastanud jrgnevad kasutaja IDd:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " allkirjastanud %08lX %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " thistanud %08lX %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Te asute thistama jrgmisi allkirju:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " allkirjastanud %08lX %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (mitte-eksporditav)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Kas testi loon thistamise sertifikaadid? (j/E) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "salajast vtit pole\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "Nitan %s foto IDd suurusega %ld, vti 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Allkirja poliitika: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Allkirja poliitika: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "HOIATUS: leidsin vigased noteerimise andmed\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Allkirja noteerimine: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Allkirja noteerimine: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "pole inimese poolt loetav" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Vtmehoidla" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [aegub: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "nita vtmeid ja srmejlgi" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Vtme srmejlg =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Vtme srmejlg =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Vtme srmejlg =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Vtme srmejlg =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "vigane teatelhendi algoritm `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s krpteeritud andmed\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "krpteeritud tundmatu algoritmiga %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "avalik vti on %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "avaliku vtmega krpteeritud andmed: hea DEK\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "krpteeritud %u-bitise %s vtmega, ID %08lX, loodud %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "krpteeritud %s vtmega, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "avaliku vtmega lahtikrpteerimine ebannestus: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "eeldan %s krpteeritud andmeid\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "IDEA iffer pole saadaval, loodan kasutada selle asemel %s\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "lahtikrpteerimine nnestus\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "HOIATUS: krpteeritud teadet on muudetud!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "lahtikrpteerimine ebannestus: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "MRKUS: saatja nudis \"ainult-teie-silmadele\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "algne failinimi on='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "eraldiseisev thistus - realiseerimiseks kasutage \"gpg --import\"\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Noteering: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Poliis: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "allkirja kontroll jeti ra\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "neid allkirju ei nnestu tdelda\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Allkirja li %.*s kasutades %s vtit ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "HALB allkiri kasutajalt \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Aegunud allkiri kasutajalt \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Korrektne allkiri kasutajalt \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[ebakindel]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " ka \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Allkirja ei saa kontrollida: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "ei ole eraldiseisev allkiri\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "eraldiseisev allkiri klassiga 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "vana stiili (PGP 2.x) allkiri\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "proc_tree() tuvastas vigase juurmise paketi\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "ei nnestu blokeerida mlupildi salvestamist: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Eksperimentaalseid algoritme ei peaks kasutama!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"see ifri algoritm ei ole soovitatav; kasutage palun mnd standardsemat!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "IDEA ifri lisandprogrammi pole\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "lisainfot leiate lehelt http://www.gnupg.org/why-not-idea.html\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "HOIATUS: vtit %s ei soovitata kasutada.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "HOIATUS: vtit %s ei soovitata kasutada.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "palun kasutage selle asemel \"--keyserver-options %s\"\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "ei oska ksitleda avaliku vtme algoritmi %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "alampaketil tbiga %d on kriitiline bitt seatud\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent ei ole sesses sessioonis kasutatav\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "agendile ei nnestu seada kliendi pid\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "agendiga suhtlemiseks ei nnestu saada lugemise FD\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "agendiga suhtlemiseks ei nnestu saada kirjutamise FD\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "vigane GPG_AGENT_INFO keskkonnamuutuja\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "gpg-agendi protokolli versioon %d ei ole toetatud\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "ei nnestu luua hendust serveriga `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "probleem gpg-agent programmiga suhtlemisel\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "probleem agendiga - blokeerin agendi kasutamise\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (peamise vtme ID %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Te vajate kasutaja salajase vtme lahtilukustamiseks parooli:\n" -"\"%.*s\"\n" -"%u-bitti %s vti, ID %08lX, loodud %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Sisestage parool\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Korrake parooli\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "liiga pikk parool\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "vigane vastus agendilt\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "katkestatud kasutaja poolt\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "probleem agendiga: agent tagastas 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Te vajate kasutaja salajase vtme lahtilukustamiseks\n" -"parooli: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bitine %s vti, ID %08lX, loodud %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "pakettmoodis ei saa parooli ksida\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Sisestage parool: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Korrake parooli: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "andmeid ei salvestatud; salvestamiseks kasutage vtit \"--output\"\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "viga `%s' loomisel: %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Eraldiseisev allkiri.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Palun sisestage andmefaili nimi: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "loen standardsisendit ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "allkirjastatud andmeid pole\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "allkirjastatud andmete avamine ebannestus `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "anonmne saaja; proovin salajast vtit %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "ok, me oleme anonmne teate saaja.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "vana DEK kodeerimine ei ole toetatud\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "ifri algoritm %d%s on tundmatu vi blokeeritud\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "MRKUS: ifri algoritm %d puudub eelistustes\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "MRKUS: salajane vti %08lX aegus %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "vti %08lX: vti on thistatud!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "ksin vtit %08lX HKP vtmeserverist %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "vtmeserverist ei saa vtit: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "viga teate saatmisel serverile `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "teate saatmine serverile `%s' nnestus (olek=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "teate saatmine serverile `%s' ebannestus: olek=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "otsin \"%s\" HKP serverist %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "vtmeserverist ei saa otsida: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "salajase vtme komponendid ei ole kttesaadavad\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "kaitse algoritm %d%s ei ole toetatud\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Vigane parool; palun proovige uuesti" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "HOIATUS: Tuvastasin nrga vtme - palun muutke uuesti parooli.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"loon salajase vtme kaitseks mittesoovitavat 16 bitist kontrollsummat\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"see on PGP genereeritud ElGamal vti ja EI OLE allkirjastamiseks turvaline!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "avalik vti on %lu sekund uuem, kui allkiri\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "avalik vti on %lu sekundit uuem, kui allkiri\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "vti loodi %lu sekund tulevikus (ajahpe vi kella probleem)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "vti loodi %lu sekundit tulevikus (ajahpe vi kella probleem)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "MRKUS: allkirja vti %08lX aegus %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "eeldan tundmatu kriitilise biti tttu vigast allkirja\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"HOIATUS: poliisi urli %%-asendus ebannestus (liiga suur). Kasutan " -"kompaktset.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"HOIATUS: poliisi urli %%-asendus ebannestus (liiga suur). Kasutan " -"kompaktset.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "Loodud allkirja ei nnestu kontrollida: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s allkiri kasutajalt: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "HOIATUS: `%s' on thi fail\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "PGP 2.x stiilis vtmetega saab allkirjastada ainult --pgp2 moodis\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "%s ei nnestu luua: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "MRKUS: ifri algoritm %d puudub eelistustes\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "allkirjastan:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"PGP 2.x stiilis vtmetega saab avateksti allkirjastada ainult --pgp2 moodis\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "kasutatakse %s krpteerimist\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "ei suuda ksitleda tekstiridu mis on pikemad, kui %d smbolit\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "sisendrida on pikem, kui %d smbolit\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb kirje %lu: lseek ebannestus: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb rec %lu: write failed (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "trustdb transaktsioon on liiga suur\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: ei nnestu kasutada: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: kataloogi ei ole!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: ei nnestu luua lukku\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: ei nnestu seada lukku\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: ei nnestu luua: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: versioonikirje loomine ei nnestu: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: loodi vigane usalduse andmebaas\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: trustdb on loodud\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: vigane trustdb\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: paisktabeli loomine ebannestus: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: viga versioonikirje uuendamisel: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: viga versioonikirje lugemisel: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: viga versioonikirje kirjutamisel: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "trustdb: lseek ebannestus: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "trustdb: lugemine ebannestus (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: ei ole trustdb fail\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: versioonikirje kirje numbriga %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: vigane faili versioon %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: viga vaba kirje lugemisel: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: viga kataloogikirje kirjutamisel: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: kirje nullimine ebannestus: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: kirje lisamine ebannestus: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "trustdb on vigane; palun kivitage \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' ei ole kehtiv pikk vtmeID\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "vti %08lX: aktsepteerin usaldusvrse vtmena\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "vti %08lX esineb trustdb failis enam kui korra\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "vti %08lX: usaldataval vtmel pole avalikku vtit - jtsin vahele\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "usalduse kirje %lu, pringu tp %d: lugemine ebannestus: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "usalduse kirje %lu ei oma soovitud tpi %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "usalduse kirje %lu, tp %d: kirjutamine ebannestus: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "trustdb: sync ebannestus: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "trustdb kontrolliks puudub vajadus\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "trustdb jrgmine kontroll %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "kontrollin trustdb faili\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "ei leia avalikku vtit %08lX: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "puudub absoluutselt usaldatava vtme %08lX avalik vti\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"kontrollin sgavusel %d allkirjastatud=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"allkirja ei nnestu kontrollida.\n" -"Palun pidage meeles, et allkirja fail (.sig vi .asc)\n" -"peab olema ksureal esimene fail.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "sisendrida %u on liiga pikk vi seavahetus puudub\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"vti ei ole mrgitud ebaturvaliseks - sellega ei saa vlts RNGd kasutada!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "`%s' jtsin vahele: duplikaat\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "`%s' jtsin vahele: %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "jtsin vahele: avalik vti on juba olemas\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"jtsin `%s' vahele: see on PGP genereeritud ElGamal vti,\n" -"mis ei ole allkirjades kasutamiseks turvaline!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Fail `%s' on olemas. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Kirjutan le (j/E)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: tundmatu suffiks\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Sisestage uus failinimi" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "kirjutan standardvljundisse\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "eeldan allkirjastatud andmeid failis `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: uus omaduste fail on loodud\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: kataloogi ei nnestu luua: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: kataloog on loodud\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "HOIATUS: teade on krptitud smmeetrilise ifri nrga vtmega.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "probleem krptitud paketi ksitlemisel\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "loodi nrk vti - proovin uuesti\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"smmeetrilises ifris ei nnestu vltida nrga vtme kasutamist; proovisin %" -"d korda!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA nuab 160 bitist rsialgoritmi kasutamist\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "pakettmoodis ei nnestu seda vtmeta teha \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Kustutan selle vtme vtmehoidlast? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "See on salajane vti! - kas kustutan testi? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "vtmebloki kustutamine ebannestus: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "omaniku usalduse info puhastatud\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "avaliku vtme \"%s\" jaoks on salajane vti!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "selle kustutamiseks kasutage vtit \"--delete-secret-keys\".\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Teie lesanne on sisestada nd vrtus; seda vrtust ei avalikustata\n" -"kolmandatele pooltele. Seda vrtust on vaja et realiseerida usaldusvrk." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Usalduse vrgu loomiseks peab GnuPG teadma, millised vtmed on\n" -"absoluutselt usaldatavad. Need on tavaliselt vtmed, mille puhul\n" -"on teil juurdeps ka nende salajastele vtmetele. Kui soovite\n" -"mrata seda vtit absoluutselt usaldatavaks, vastake \"jah\"\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Kui te ikkagi soovite kasutada seda kehtetut vtit, vastake \"jah\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Kui te ikkagi soovite kasutada seda mitteusaldatavat vtit, vastake \"jah\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Sisestage kasutaja ID aadressile, kellele te soovite teadet saata." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Valige kasutatav algoritm.\n" -"\n" -"DSA (ka DSS) on digitaalallkirja algoritm, mida saab kasutada ainult\n" -"allkirjades. See on soovitatav algoritm, kuna DSA allkirjade kontroll\n" -"on oluliselt kiirem ElGamal allkirjade kontrollimisest.\n" -"\n" -"ElGamal on algoritm, mida saab kasutada nii allkirjastamisel, kui ka\n" -"krptimisel. OpenPGP eristab selle algoritmi kahte varianti: ainult\n" -"krptivat ja krptivat ning allkirjastavat. Algoritm on sama, aga\n" -"turvaliseks allkirjastamiseks on vaja valida sobivad parameetrid. See\n" -"programm toetab mlemat varianti, aga teised OpenPGP realisatsioonid\n" -"ei pruugi krptivat ning allkirjastavat vimalust tunda.\n" -"\n" -"Esimene (primaarne) vti peab alati olema selline, mida saab kasutada\n" -"allkirjastamisel; see on ka phjus, miks selles mens ei lubata valida\n" -"ainult krptivat ElGamal vtit." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Kuigi need vtmed on kirjeldatud dokumendis RFC2440, ei ole nende\n" -"kasutamine soovitatav, kuna mitte kik programmid ei toeta neid\n" -"ja nendega loodud allkirjad on suured ning kontrollimine aeglane." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Sisestage vtmepikkus" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Vastake \"jah\" vi \"ei\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Sisestage nutav vrtus, nagu viibal nidati.\n" -"Vimalik on ka sisestada ISO kuupev (AAAA-KK-PP), aga te ei\n" -"saa korrektset veateadet, kuna ssteem ritab antud vrtust\n" -"tlgendada vahemikuna." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Sisestage vtmehoidja nimi" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "palun e-posti aadress, aadress ei ole kohustuslik, aga vga soovitav" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Te vite nd sisestada kommentaari" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N et muuta nime.\n" -"K et muuta kommentaari.\n" -"E et muuta e-posti aadressi.\n" -"O et jtkata vtme loomist.\n" -"V et lpetada vtme loomine." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Vastake \"jah\" (vi \"j\"), kui vib alustada alamvtme loomisega." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Kui te allkirjastate vtme kasutaja ID, kontrollige kigepealt, kas vti\n" -"ikka kuulub antud ID-ga nidatud isikule. Teistel inimestel on hea teada,\n" -"kui hoolikalt te seda kontrolli olete teostanud.\n" -"\n" -"\"0\" thendab, et te ei vida oma kontrollimise kohta midagi.\n" -"\n" -"\"1\" thendab, et te usute, et vtit omab isik, kes seda vidab omavat, " -"kuid\n" -" te ei saanud vi ei soovinud seda videt tiendavalt kontrollida. See\n" -" on kasulik \"persooni\" kontrolliks, kui te allkirjastate isiku pseudo-\n" -" nmi vtit.\n" -"\n" -"\"2\" thendab, et te teostasite vtme pealiskaudset kontrolli. See vib\n" -" niteks thendada, et te kontrollisite vtme srmejlge ja " -"kontrollisite\n" -" vtme kasutaja ID foto ID vastu.\n" -"\n" -"\"3\" thendab, et te teostasite vtme phjalikku kontrolli. See vib " -"niteks\n" -" thendada, et vrdlesite vtme srmejlge vrme omanikuga otse suheldes\n" -" ja et te kontrollisite raskesti vltsitavast allikast (nt. pass) et\n" -" vtme omaniku nimi vastab vtmel nidatud kasutaja IDle ja te kontrol-\n" -" lisite, et vtmel nidatud e-posti aadress kuulub vtme omanikule.\n" -"\n" -"pange thele, et nited tasemete 2 ja 3 juures on *ainult* nited. Sltub\n" -"ainult teist, milline on \"pealiskaudse\" ja \"phjaliku\" kontrolli " -"thendus,\n" -"kui te allkirjastate teisi vtmeid.\n" -"\n" -"Kui te ei tea iget vastust, vastake \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Kui te soovite allkirjastada KIK kasutaja IDd, vastake \"jah\"" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Kui te testi soovite seda kasutaja IDd kustutada, vastake \"jah\".\n" -"Sertifikaadid kustutatakse samuti!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Kui selle alamvtme vib kustutada, vastake \"jah\"" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"See on vtme kehtiv allkiri; tavaliselt seda ei soovita kustutada,\n" -"kuna see allkiri vib olla vajalik, et kirjeldada antud vtme vi\n" -"antud vtmega sertifitseeritud teise vtme usaldatavust." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Seda allkirja ei saa kontrollida, kuna puudub allkirjale vastav vti.\n" -"Te peaksite peatama kustutamise, kuni on teada, millist vtit see\n" -"kasutab, sest see vti vib moodustada usaldussuhte lbi mne juba\n" -"sertifitseeritud vtme." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "Allkiri ei ole kehtiv. Oleks mistlik see vtmehoidlast kustutada." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"See allkiri seob kasutaja ID vtmega. Sellist allkirja ei ole\n" -"ldiselt soovitatav eemaldada. Peale selle kustutamist ei pruugi\n" -"GnuPG enam olla vimeline seda vtit leidma. Kustutada viks\n" -"vaid siis, kui see allkiri ei ole miskiprast kehtiv ja on\n" -"olemas ka teine allkiri, mis kasutajat vtmega seob." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Muuda kikide kasutaja ID-de seaded (vi ainult valitud)\n" -"vastavaks hetkel mratud seadetele. Kikide asjasse puutuvate\n" -"ise loodud allkirjade ajatempleid suurendatakse he sekundi vrra.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Palun sisestage parool; see on salajane tekst \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Palun korrake parooli, siis saate oma kirjutatus kindel olla." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Sisestage palun failinimi, mida allkirjastada" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Vastake \"jah\", kui faili vib le kirjutada" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Palun sisestage uus failinimi. Kui te vajutate lihtsalt reavahetust,\n" -"kasutatakse vaikimisi faili (nimi on nurksulgudes)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Te peate mrama sertifitseerimise phjuse. Sltuvalt kontekstist on\n" -"teil vimalus valida ks jrgnevaist:\n" -" \"Vti on kompromiteeritud\"\n" -" Kasutage seda, kui teil on phjust uskuda, et autoriseerimata\n" -" isikud on saanud juurdepsu teie salajasele vtmele.\n" -" \"Vti on asendatud\"\n" -" Kasutage seda, kui te olete selle vtme asendanud uuemaga.\n" -" \"Vti ei ole enam kasutusel\"\n" -" Kasutage seda, kui te ei kasuta enam seda vtit.\n" -" \"Kasutaja ID ei ole enam kehtiv\"\n" -" Kasutage seda mrkimaks, et konkreetset kasutaja ID ei peaks enam\n" -" kasutama; seda kasutatakse tavaliselt mrkimaks vigast e-posti " -"aadressi.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Kui te soovite, vite nd sisestada phjenduse, miks te\n" -"soovite seda thistamise sertifikaati esitada. Palun kirjutage\n" -"lhidalt. Thi rida lpetab teksti.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Abiinfo puudub" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "`%s' kohta abiinfo puudub" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "viga vtmehoidla `%s' loomisel: %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "vtmehoidla `%s' on loodud\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "vtmehoidla vahemlu uuesti loomine ebannestus: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "HOIATUS: on olemas 2 faili konfidentsiaalse infoga.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s ei ole muudetud\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s on uus\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Palun parandage see vimalik turvaprobleem\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "kontrollin vtmehoidlat `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "seni on kontrollitud %lu vtit (%lu allkirja)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "kontrollitud %lu vtit (%lu allkirja)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: vtmehoidla on loodud\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "te peate GnuPG uuesti kivitama, siis vetakse uued vtmed arvesse\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "`%s' iguste muutmine ebannestus: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NIMI=VRTUS|kasuta neid noteerimise andmeid" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "esimene smbol noteerimise nimes peab olema tht vi alakriips\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "punktid noteerimise nimes peavad olema mbritsetud teiste smbolitega\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "HOIATUS: Sellel vtmel on juba foto ID.\n" -#~ " Jrgmise foto ID lisamine vib tekitada segadusi mne PGP\n" -#~ " versiooni kasutamisel.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Vtmel vib olla ainult ks foto ID.\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Srmejlg:" - -#~ msgid " Fingerprint:" -#~ msgstr " Srmejlg:" diff --git a/po/fr.po b/po/fr.po deleted file mode 100644 index 709c670e9..000000000 --- a/po/fr.po +++ /dev/null @@ -1,4750 +0,0 @@ -# GnuPG French translation -# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Gal Quri , 1998. -# -# Thanks to Rmi Guyomarch and -# for pointing me out some errors. -# -# $Id$ -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-06-24 02:06+02:00\n" -"Last-Translator: Gal Quri \n" -"Language-Team: French \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" -"Content-Transfer-Encoding: 8-bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Avertissement: l'utilisation de la mmoire n'est pas sre !\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "voir http://www.gnupg.org/fr/faq.html pour plus d'informations\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "" -"l'opration n'est pas possible tant que la mmoire sre n'est pas\n" -"initialise\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(vous avez peut-tre utilis un programme non adapt cette fin)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "oui" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "oO" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "non" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "quitter" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "erreur gnrale" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "type de paquet inconnu" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "version inconnue" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algorithme cl publique inconnu" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algorithme de hachage inconnu" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "mauvaise cl publique" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "mauvaise cl secrte" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "mauvaise signature" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "somme de contrle errone" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "mauvais mot de passe" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "cl publique non trouve" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algorithme de chiffrement inconnu" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "impossible d'ouvrir le porte-cls" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "paquet invalide" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armure invalide" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "pas d'utilisateur de ce nom" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "la cl secrte n'est pas disponible" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "mauvaise cl secrte utilise" - -#: util/errors.c:72 -msgid "not supported" -msgstr "non support" - -#: util/errors.c:73 -msgid "bad key" -msgstr "mauvaise cl" - -#: util/errors.c:74 -msgid "file read error" -msgstr "erreur de lecture" - -#: util/errors.c:75 -msgid "file write error" -msgstr "erreur d'criture" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algorithme de compression inconnu" - -#: util/errors.c:77 -msgid "file open error" -msgstr "erreur d'ouverture de fichier" - -#: util/errors.c:78 -msgid "file create error" -msgstr "erreur de cration de fichier" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "mot de passe invalide" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algorithme cl publique non implant" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algorithme de chiffrement non implant" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "classe de signature inconnue" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "erreur dans la base de confiance" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "mauvais entier en prcision multiple (MPI)" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "limite de ressources atteinte" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "porte-cls invalide" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "mauvais certificat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "nom d'utilisateur malform" - -#: util/errors.c:89 -msgid "file close error" -msgstr "erreur de fermeture de fichier" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "erreur pendant le changement de nom du fichier" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "erreur pendant la suppression du fichier" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "donnes inattendues" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "conflit de dates" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algorithme de cls publiques inutilisable" - -#: util/errors.c:95 -msgid "file exists" -msgstr "le fichier existe" - -#: util/errors.c:96 -msgid "weak key" -msgstr "cl faible" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argument invalide" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "mauvaise adresse (URI)" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI non supporte" - -#: util/errors.c:100 -msgid "network error" -msgstr "erreur de rseau" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "non chiffr" - -#: util/errors.c:103 -msgid "not processed" -msgstr "non trait" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "cl publique inutilisable" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "cl secrte inutilisable" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "erreur du serveur de cls" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... c'est un bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "vous avez trouv un bug... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "impossible d'ouvrir `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "impossible d'accder `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' n'est pas un fichier rgulier - ignor\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "note: le fichier `random_seed' est vide\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -"avertissement: la taille du fichier `random_seed' est invalide.\n" -"Celui-ci ne sera pas utilis.\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "impossible de lire `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "note: le fichier `random_seed' n'a pas t mis jour\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "impossible de crer `%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "impossible d'crire `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "impossible de fermer `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "" -"ATTENTION: utilisation d'un gnrateur de nombres alatoires peu sr !!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Le gnrateur de nombres alatoires n'est qu'un artifice visant excuter\n" -"GnuPG - ce n'est en aucune manire un gnrateur (RNG) fort!\n" -"\n" -"N'UTILISEZ PAS LES DONNES GNRES PAR CE PROGRAMME !!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Il n'y a pas assez d'octets alatoires disponibles. Faites autre chose\n" -"pour que l'OS puisse amasser plus d'entropie ! (il faut %d octets de plus)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Commandes:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[fichier]|faire une signature" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[fichier]|faire une signature en texte clair" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "faire une signature dtache" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "chiffrer les donnes" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "[fichier]|chiffrer les fichiers" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "chiffrement symtrique seulement" - -#: g10/g10.c:315 -msgid "store only" -msgstr "pas d'action" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "dchiffrer les donnes (dfaut)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[fichiers]|dchiffrer les fichiers" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "vrifier une signature" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "lister les cls" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "lister les cls et les signatures" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "vrifier les signatures des cls" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "lister les cls et les empreintes" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "lister les cls secrtes" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "gnrer une nouvelle paire de cls" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "enlever les cls du porte-cls public" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "enlever les cls du porte-cls secret" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "signer une cl" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "signer une cl localement" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "signer une cl irrvocablement" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "signer une cl localement et irrvocablement" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "signer ou diter une cl" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "gnrer un certificat de rvocation" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exporter les cls" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exporter les cls vers un serveur de cls" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importer les cls d'un serveur de cls" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "chercher les cls avec un serveur de cls" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "mettre jour les cls depuis un serveur" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importer/fusionner les cls" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "ne lister que les paquets" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exporter les indices de confiance" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importer les indices de confiance" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "mettre la base de confiance jour" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "mise jour inattendue de la base de confiance" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "rparer une base de confiance corrompue" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Enlever l'armure d'un fichier ou de stdin" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Mettre une armure un fichier ou stdin" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|alg. [fich.]|indiquer les fonctions de hachage" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Options:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "crer une sortie ascii avec armure" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOM|chiffrer pour NOM" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOM|utiliser NOM comme rcipient par dfaut" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "utiliser la cl par df. comme rcipient" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "utiliser ce nom pour signer ou dchiffrer" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|niveau de compression N (0 dsactive)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "utiliser le mode texte canonique" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "utiliser comme fichier de sortie" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "bavard" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "devenir beaucoup plus silencieux" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "ne pas utiliser du tout le terminal" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "forcer les signatures en v3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "ne pas forcer les signatures en v3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "forcer les signatures en v4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "ne pas forcer les signatures en v4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "toujours utiliser un sceau pour le chiffrement" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "" -"ne jamais utiliser de sceau pour le\n" -"chiffrement" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "ne rien changer" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "utiliser gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "mode automatique: ne jamais rien demander" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "rpondre oui la plupart des questions" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "rpondre non la plupart des questions" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "ajouter ce porte-cls la liste" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "ajouter ce porte-cls secret la liste" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "indiquer o est une cl liste" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOM|utiliser NOM comme cl secrte par dfaut" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HTE|utiliser ce serveur pour chercher des cls" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NOM|le terminal utilise la table de caractres NOM" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "lire les options du fichier" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|crire l'tat sur ce descripteur" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[fichier]|crire les informations d'tat vers ce fichier" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|IDCL|donner une confiance ultime cette cl" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FICH|charger le module d'extension FICH" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "imiter le mode dcrit dans la RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "utiliser le comportement dfini par OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"utiliser le comportement de PGP 2.x\n" -"pour toutes les options de paquets,\n" -"de hachage et de chiffrement" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|coder les mots de passe suivant le mode N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NOM|utiliser le hachage NOM pour les mots de passe" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NOM|utiliser le chiffre NOM pour les mots de passe" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOM|utiliser l'algorithme de chiffrement NOM" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOM|utiliser la fonction de hachage NOM" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|utiliser l'algorithme de compression N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "supprimer l'ident. des paquets chiffrs" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Montrer les photos d'identit" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Ne pas montrer les photos d'identit" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" -"Choisir la ligne de commande servant \n" -"afficher les photos d'identit" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Voir la page de manuel pour une liste complte des commandes et options)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Exemples:\n" -"\n" -" -se -r Alice [fichier] signer et chiffrer pour l'utilisateur Alice\n" -" --clearsign [fichier] faire une signature en texte clair\n" -" --detach-sign [fichier] faire une signature dtache\n" -" --list-keys [utilisateur] montrer les cls\n" -" --fingerprint [utilisateur] montrer les empreintes\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "" -"Signaler toutes anomalies (en anglais)\n" -"et tout problme de traduction .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Utilisation: gpg [options] [fichiers] (-h pour l'aide)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Syntaxe: gpg [options] [fichiers]\n" -"signer, vrifier, chiffrer ou dchiffrer\n" -"l'opration par dfaut dpend des donnes entres\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algorithmes supports:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "utilisation: gpg [options] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "commandes en conflit\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Attention: propritaire de %s \"%s\" peu sr\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Attention: permissions de %s \"%s\" peu sres\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Attention: propritaire de %s \"%s\" peu sr\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Attention: permissions de %s \"%s\" peu sres\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTE: pas de fichier d'options par dfaut `%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTE: pas de fichier d'options par dfaut `%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "fichier d'options `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "lire les options de `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s n'est pas une table de caractres valide\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "impossible d'interprter l'URI du serveur de cls\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: version %d du fichier invalide\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armure invalide" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: version %d du fichier invalide\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "porte-cls invalide" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "impossible de mettre le chemin d'excution %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "ATTENTION: Le programme peut crer un fichier core !\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "ATTENTION: %s remplace %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTE: %s n'est pas pour une utilisation normale !\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s n'est pas permis avec %s !\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s n'a aucun sens avec %s !\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -"il n'est possible de faire une signature dtache ou en texte clair\n" -"qu'en mode --pgp2\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "vous ne pouvez pas signer et chiffrer en mme temps en mode --pgp2\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" -"vous devez utiliser des fichiers (et pas un tube) lorsque --pgp2\n" -"est activ.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" -"chiffrer un message en mode --pgp2 ncessite l'algorithme de chiffrage IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "ce message ne sera pas forcment utilisable par PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "l'algorithme de chiffrement slectionn est invalide\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "la fonction de hachage slectionne est invalide\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "la fonction de hachage slectionne est invalide\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "l'algorithme de compression doit faire partie de l'intervalle %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed doit tre suprieur 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed doit tre suprieur 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth doit tre compris entre 1 et 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTE: le mode S2K simple (0) est fortement dconseill\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "mode S2K invalide; ce doit tre 0, 1 ou 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "default-check-level invalide; ce doit tre 0, 1, 2 ou 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "prfrences invalides\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "prfrences invalides\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "prfrences invalides\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "prfrences invalides\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "impossible d'initialiser la base de confiance: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [nom du fichier]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [nom du fichier]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [nom du fichier]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [nom du fichier]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [nom du fichier]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [nom du fichier]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [nom du fichier]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [nom du fichier]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key utilisateur" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key utilisateur" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key utilisateur" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key utilisateur" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key utilisateur [commandes]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "impossible d'ouvrir %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [utilisateur] [porte-cls]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "la suppression d'une armure a chou: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "la construction d'une armure a chou: %s \n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algorithme de hachage `%s' invalide\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nom du fichier]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Vous pouvez taper votre message...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "impossible d'ouvrir `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"le nom d'une notation ne doit comporter que des lettres, des chiffres,\n" -"des points ou des traits de soulignement et doit se terminer par un signe " -"gal\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "une valeur de notation ne doit utiliser aucun caractre de contrle\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "l'URL de politique de certification donne est invalide\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "l'URL de politique de signature donne est invalide\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armure: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "en-tte d'armure invalide: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "en-tte d'armure: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "en-tte de signature claire invalide\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "signatures en texte clair imbriques\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "ligne chappe par `-' invalide: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armure inattendue:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "caractre %02x invalide en base 64 ignor\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "fin de fichier prmature (pas de CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "fin de fichier prmature (dans le CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC dform\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Erreur de CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "fin de fichier prmature (dans la remorque)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "erreur dans la ligne de remorque\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "aucune donne OpenPGP valide n'a t trouve.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armure invalide: ligne plus longue que %d caractres\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"caractre cit-imprimable (quoted-printable) dans l'armure provenant\n" -"certainement d'un agent de transfert de messages bogu\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Aucune raison spcifie" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "La cl a t remplace" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "La cl a t compromise" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "La cl n'est plus utilise" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Le nom d'utilisateur n'est plus valide" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Cause de rvocation: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Commentaire de rvocation: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Pas de confiance dfinie pour :\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -" quel point avez-vous confiance en cet utilisateur pour la vrification\n" -"des cls des autres utilisateurs (vous pouvez vrifier son passeport,\n" -"vrifier les empreintes de diverses sources...) ?\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = ne sait pas\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = je ne fais PAS confiance\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = je crois marginalement\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = je fais entirement confiance\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = je donne une confiance ultime\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = donnez-moi plus d'informations\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = retour au menu principal\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = sauter cette cl\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = quitter\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Votre dcision ? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Voulez-vous vraiment donner une confiance ultime cette cl ?" - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificats conduisant vers une cl confiance ultime:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "cl %08lX: la cl a t rvoque !\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Utiliser cette cl quand mme ? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "cl %08lX: la sous-cl a t rvoque !\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: la cl a expir\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "%08lX: Rien ne dit que la cl appartient vraiment au propritaire.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Nous ne faisons PAS confiance cette cl\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Il n'est pas sr que cette cl appartient vraiment son\n" -"propritaire mais elle est quand mme accepte\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Cette cl appartient probablement son propritaire\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Cette cl nous appartient\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Il n'est pas certain que la cl appartient sos propritaire.\n" -"Si vous savez *vraiment* ce que vous faites, vous pouvez rpondre\n" -"oui la prochaine question\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "ATTENTION: Utilisation d'une cl sans confiance !\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "ATTENTION: Cette cl t rvoque par son propritaire !\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Cela pourrait signifier que la signature est fausse.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "ATTENTION: Cette sous-cl t rvoque par son propritaire !\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Note: cette cl a t dsactive.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Note: Cette cl a expir !\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "" -"ATTENTION: Cette cl n'est pas certifie avec une signature de confiance !\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Rien ne dit que la signature appartient son propritaire.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "ATTENTION: Nous ne faisons PAS confiance cette cl !\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " La signature est certainement FAUSSE.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"ATTENTION: Les signatures de cette cl n'ont pas une confiance suffisante !\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr "" -" Il n'est pas sr que la signature appartient son " -"propritaire.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: ignor: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: ignor: cl publique dj prsente\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Vous n'avez pas spcifi de nom d'utilisateur. (vous pouvez\n" -"utiliser -r)\n" -"\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Entrez le nom d'utilisateur, en terminant par une ligne vide: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Pas d'utilisateur de ce nom.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "ignor: la cl publique est dj le rcipient par dfaut\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "La cl publique est dsactive.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "ignor: cl publique dj active\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "rcipient par dfaut `%s' inconnu\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: ignor: la cl publique est dsactive\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "pas de destinataire valide\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "la prfrence %c%lu n'est pas valide\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "prfrence %c%lu duplique\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "trop de prfrences `%c'\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "Caractre invalide dans la chane de prfrences\n" - -# g10/keygen.c:123 ??? -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "criture de l'auto-signature\n" - -# g10/keygen.c:123 ??? -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "criture de l'auto-signature\n" - -# g10/keygen.c:161 ??? -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "criture de la signature de liaison\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "Taille invalide; utilisation de %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "taille arrondie %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Slectionnez le type de cl dsir:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA et ElGamal (par dfaut)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (signature seule)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (chiffrement seul)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (signature et chiffrement)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (signature seule)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (chiffrement seul)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (signature et chiffrement)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Votre choix ? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" -"L'utilisation de cet algorithme est dconseill - faut-il quand-mme\n" -"crer la cl ?" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Choix invalide.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Prparation la gnration d'une nouvelle paire de cls %s.\n" -" la taille minimale est 768 bits\n" -" la taille par dfaut est 1024 bits\n" -" la taille maximale conseille est 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Quelle taille de cl dsirez-vous ? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA permet seulement des tailles comprises entre 512 et 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "taille trop petite; 1024 est la plus petite valeur permise pour RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "taille trop petite; 768 est la plus petite valeur permise.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "taille trop importante; %d est la plus grande valeur permise.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Les tailles suprieures 2048 ne sont pas conseilles car\n" -"les calculs prennent VRAIMENT beaucoup de temps !\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Etes-vous sr de vouloir cette taille ? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"D'accord, mais n'oubliez pas que les radiations de votre cran et de votre\n" -"clavier sont aussi trs vulnrables aux attaques !\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "La taille demande est %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "arrondie %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Spcifiez combien de temps cette cl devrait tre valide.\n" -" 0 = la cl n'expire pas\n" -" = la cl expire dans n jours\n" -" w = la cl expire dans n semaines\n" -" m = la cl expire dans n mois\n" -" y = la cl expire dans n annes\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Spcifiez combien de temps la signature devrait tre valide.\n" -" 0 = la signature n'expire pas\n" -" = la signature expire dans n jours\n" -" w = la signature expire dans n semaines\n" -" m = la signature expire dans n mois\n" -" y = la signature expire dans n annes\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "La cl est valide pour ? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "La signature est valide pour ? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valeur invalide\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s n'expire pas du tout\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s expire le %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Votre systme ne sait pas afficher les dates au-del de 2038.\n" -"Cependant la gestion des dates sera correcte jusqu' 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Est-ce correct (o/n) ? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Vous avez besoin d'un nom d'utilisateur pour identifier votre cl; le\n" -"programme le construit partir du nom rel, d'un commentaire et d'une\n" -"adresse e-mail de cette manire:\n" -" Heinrich Heine (Der Dichter) \n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nom rel: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Caractre invalide dans le nom\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Le nom ne doit pas commencer par un chiffre\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Le nom doit faire au moins 5 caractres de long\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Adresse e-mail: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Ce n'est pas une adresse e-mail valide\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Commentaire: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Caractre invalide dans le commentaire\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Vous utilisez le jeu de caractres '%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Vous avez slectionn ce nom d'utilisateur:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" -"Ne mettez pas d'adresse e-mail dans le nom rel ou dans le commentaire\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoQq" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Changer le (N)om, le (C)ommentaire, l'(E)-mail ou (Q)uitter ? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Changer le (N)om, le (C)ommentaire, l'(E)-mail ou (O)K/(Q)uitter ? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Corrigez l'erreur d'abord\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Vous avez besoin d'un mot de passe pour protger votre cl secrte.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "le mot de passe n'a pas t correctement rpt ; recommencez." - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Vous ne voulez pas de mot de passe - c'est srement une *mauvaise* ide !\n" -"Je l'accepte quand-mme. Vous pouvez changer votre mot de passe quand vous\n" -"le dsirez, en utilisant ce programme avec l'option --edit-key .\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Un grand nombre d'octets alatoires doit tre gnr. Vous devriez faire\n" -"autre-chose (taper au clavier, dplacer la souris, utiliser les disques)\n" -"pendant la gnration de nombres premiers; cela donne au gnrateur de\n" -"nombres alatoires une meilleure chance d'avoir assez d'entropie.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "La paire de cls DSA fera 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "La gnration de cl a t annule.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "criture de la cl publique vers `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "criture de la cl secrte vers `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "" -"aucun portes-cls public n'a t trouv avec des droits d'criture : %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "" -"aucun portes-cls secret n'a t trouv avec des droits d'criture : %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "erreur durant l'criture du porte-cls public `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "erreur durant l'criture du porte-cls secret `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "les cls publique et secrte ont t cres et signes.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "cl marque comme ayant une confiance ultime.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Notez que cette cl ne peut tre utilise pour chiffrer. Vous pouvez\n" -"utiliser la commande --edit-key pour gnrer une cl secondaire \n" -"cette fin.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "La gnration de cl a chou: %s\n" - -# on s'amuse comme on peut... -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"la cl a t cre %lu seconde dans le futur (rupture spatio-temporelle ou\n" -"problme d'horloge)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"la cl a t cre %lu secondes dans le futur (rupture spatio-temporelle ou\n" -"problme d'horloge\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "" -"NOTE: crer des sous-cls pour des cls v3 n'est pas conforme OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Crer vraiment ? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output n'est pas compatible avec cette commande\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: impossible d'ouvrir: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "erreur pendant la cration du mot de passe: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' dj compress\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: ATTENTION: fichier vide\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"le chiffrement RSA ne se fait qu'avec des cls de moins de 2048 bits\n" -"en mode --pgp2\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lecture de `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"impossible d'utiliser le chiffre IDEA pour toutes les cls vers\n" -"lesquelles vous chiffrez.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"NOTE: l'algorithme de chiffrement %d n'a pas t trouv dans les " -"prfrences\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Cette commande n'est pas admise en mode %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s chiffr pour: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "cl '%s' introuvable: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "erreur pendant la lecture du bloc de cl : %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "cl %08lX: ce n'est pas une cl rfc2440 - ignore\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "cl %08lX: non protge - ignore\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "cl %08lX: cl de style PGP 2.x - ignore\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "ATTENTION: rien n'a t export\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "trop d'entres dans le cache pk - dsactiv\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Nom utilisateur introuvable]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"La cl invalide %08lX a t rendue valide par --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "" -"utilisation de la cl secondaire %08lX la place de la cl\n" -"principale %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "cl %08lX: cl secrte sans cl publique - non prise en compte\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "un bloc de type %d a t ignor\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu cls traites jusqu'ici\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "erreur pendant la lecture de `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr " Quantit totale traite: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " nouvelles cls ignores: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sans nom d'utilisateur: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importe: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " inchange: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nouveaux noms d'utilisateurs: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nouvelles sous-cls: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nouvelles signatures: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " nouvelles rvocations de cls: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " cls secrtes lues: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " cls secrtes importes: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " cls secrtes inchanges: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importe: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "cl %08lX: pas de nom d'utilisateur\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "cl %08lX: pas de sous-cl pour relier la cl\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "cl %08lX: nom d'utilisateur non auto-sign accept '%s':\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "cl %08lX: pas de nom d'utilisateur valide\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "cela peut provenir d'une auto-signature manquante\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "cl %08lX: cl publique pas trouve: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "cl %08lX: nouvelle cl - ignore\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "aucun porte-cl n'a t trouv avec des droits d'criture : %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "criture de `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "erreur durant l'criture du porte-cls `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "cl %08lX: cl publique importe\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "cl %08lX: ne ressemble pas notre copie\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "cl %08lX: impossible de trouver le bloc de cls original: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "cl %08lX: impossible de lire le bloc de cls original: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "cl %08lX: un nouvel utilisateur\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "cl %08lX: %d nouveaux utilisateurs\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "cl %08lX: une nouvelle signature\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "cl %08lX: %d nouvelles signatures\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "cl %08lX: une nouvelle sous-cl\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "cl %08lX: %d nouvelles sous-cls\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "cl %08lX: n'a pas chang\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "pas de porte-cls par dfaut: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "cl %08lX: cl secrte importe\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "cl %08lX: dj dans le porte-cls secret\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "cl %08lX: cl secrte pas trouve: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"cl %08lX: pas de cl publique - le certificat de rvocation ne peut\n" -"tre appliqu\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "cl %08lX: certificat de rvocation invalide: %s - rejet\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "cl %08lX: certificat de rvocation import\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "cl %08lX: pas d'utilisateur pour la signature\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"cl %08lX: algorithme de cl publique non support sur le nom\n" -"d'utilisateur \"%s\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "cl %08lX: auto-signature sur le nom d'utilisateur \"%s\" invalide\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "cl %08lX: pas de sous-cl pour relier la cl\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "cl %08lX: algorithme de cl publique non support\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "cl %08lX: liaison avec la sous-cl invalide\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "cl %08lX: liaison avec la sous-cl invalide\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "cl %08lX: pas de sous-cl pour relier la cl\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "cl %08lX: liaison avec la sous-cl invalide\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "cl %08lX: liaison avec la sous-cl invalide\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "cl %08lX: utilisateur non pris en compte: '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "cl %08lX: sous-cl non prise en compte\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "cl %08lX: signature non exportable (classe %02x) - ignore\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "cl %08lX: certificat de rvocation au mauvais endroit - ignore\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "cl %08lX: certificat de rvocation invalide: %s - ignore\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "cl %08lX: certificat de rvocation au mauvais endroit - ignore\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "cl %08lX: nom d'utilisateur en double fusionn\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"Attention: la cl %08lX est peut-tre rvoque: recherche de la cl de\n" -"rvocation %08lX\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"Attention: la cl %08lX est peut-tre rvoque: la cl de rvocation\n" -"%08lX est absente.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "cl %08lX: certificat de rvocation ajout\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "cl %08lX: ajout de la signature de cl directe\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[rvocation]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[auto-signature]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "une mauvaise signature\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d mauvaises signatures\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "une signature non vrifie cause d'une cl manquante\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d signatures non vrifies cause de cls manquantes\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "une signature non vrifie cause d'une erreur\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d signatures non vrifies cause d'erreurs\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "un nom d'utilisateur sans auto-signature valide dtect\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d nom d'utilisateurs sans auto-signature valide dtect\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Le nom d'utilisateur \"%s\" est rvoqu." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Etes-vous sur de toujours vouloir le signer ? (o/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Impossible de signer.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "AVERTISSEMENT: `%s' est un fichier vide\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Votre signature actuelle sur \"%s\"\n" -"est locale.\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Voulez vous la rendre compltement exportable ? (o/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Votre signature actuelle sur \"%s\"\n" -"est locale.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Voulez vous la rendre compltement exportable ? (o/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" a dj t sign localement par la cl %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" a dj t sign localement par la cl %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Rien signer avec la cl %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Cette cl a expir !" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Cette cl va expirer le %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Voulez-vous que votre signature expire en mme temps ? (O/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"il n'est pas possible de gnrer une signature OpenPGP sur une cl de style\n" -"PGP 2.x en mode --pgp2.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Cela rendra la cl inutilisable par PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Avec quel soin avez-vous vrifi que la cl que vous allez signer\n" -"appartient rellement la personne sus-nomme ? Si vous ne savez\n" -"quoi rpondre, entrez \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Je ne rpondrai pas.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Je n'ai pas vrifi du tout.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) J'ai un peu vrifi.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) J'ai vrifi trs soigneusement.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Etes-vous vraiment sr(e) que vous voulez signer cette cl\n" -"avec la vtre: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "cela peut provenir d'une auto-signature manquante\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"La signature sera marque comme non-exportable.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"La signature sera marque comme non-rvocable.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"La signature sera marque comme non-exportable.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"La signature sera marque comme non-rvocable.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Je n'ai pas du tout vrifi cette cl.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"J'ai un peu vrifi cette cl.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"J'ai vrifi cette cl avec grand soin.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Signer rellement ? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "la signature a chou: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Cette cl n'est pas protge.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Les parties secrtes de la cl principale ne sont pas disponibles.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "La cl est protge.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Impossible d'diter cette cl: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "Entrez le nouveau mot de passe pour cette cl secrte.\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Vous ne voulez pas de mot de passe - cela est certainement une\n" -"*mauvaise* ide\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Voulez-vous vraiment faire cela ? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "replacer la signature d'une cl l'endroit correct\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "quitter ce menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "enregistrer" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "enregistrer et quitter" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "afficher cette aide" - -# g10/keyedit.c:556 ??? -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "afficher l'empreinte" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "lister" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "lister la cl et les noms d'utilisateurs" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "slectionner le nom d'utilisateur N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "cl" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "slectionner la cl secondaire N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "vrifier" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "lister les signatures" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "signer" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "signer la cl" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsigner" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "signer la cl localement" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsigner" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "signer la cl de faon non-rvocable" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsigner" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "signer la cl de faon locale et non-rvocable" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "dboguer" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "aj.ut" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "ajouter un utilisateur" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "aj.photo" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "ajouter une photo d'identit" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "suppr.ut" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "enlever un utilisateur" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "suppr.photo" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "aj.cl" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "ajouter une cl secondaire" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "suppr.cl" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "enlever une cl secondaire" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "aj.cl" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "ajouter une cl secondaire" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "suppr.sign" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "supprimer les signatures" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "changer la date d'expiration" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "principale" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "marquer le nom d'utilisateur comme principal" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "changer" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "passer de la liste des cls secrtes aux cls prives et inversement" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "prf" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "lister les prfrences (expert)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "montr.prf" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "lister les prfrences (bavard)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "mettre.prf" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "donner la liste de prfrences" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "prf.mj" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "prfrences mises jour" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "mot.pas" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "changer le mot de passe" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "confi." - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "changer la confiance" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "rvoquer les signatures" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revcl" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "rvoquer une cl secondaire" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "dsactiver" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "dsactiver une cl" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "activer" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "activer une cl" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "montr.photo" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "montrer la photo d'identit" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "impossible de faire cela en mode automatique\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "erreur pendant la lecture du bloc de cl secrte `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "La cl secrte est disponible.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Commande> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Il faut la cl secrte pour faire cela.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Utilisez la commande toggle d'abord.\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "La cl est rvoque." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Signer vraiment tous les utilisateurs ? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Aide: Slectionner les utilisateurs signer\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Cette commande n'est pas admise en mode %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Vous devez slectionner au moins un utilisateur.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Vous ne pouvez pas supprimer le dernier utilisateur !\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Enlever rellement tous les utilisateurs slectionns ? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Enlever rellement cet utilisateur ? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Vous devez slectionner au moins une cl.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Voulez-vous vraiment supprimer les cls slectionnes ? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Voulez-vous vraiment supprimer cette cl ? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Voulez-vous vraiment rvoquer les cls slectionnes ? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Voulez-vous vraiment rvoquer cette cl ? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "Enlever rellement les prfrences des utilisateurs slectionns ? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Faut-il vraiment mettre jour les prfrences ? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Enregistrer les changements? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Quitter sans enregistrer? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "la mise jour a chou: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "la mise jour de la cl secrte a chou: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "La cl n'a pas chang donc la mise jour est inutile.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Commande invalide (essayez help)\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Cette cl peut tre rvoque par la cl %s %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (sensible)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX cre: %s expire: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " confiance: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Cette cl a t dsactive" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! la sous-cl a t rvoque: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- une rvocation truque a t trouve\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problme de vrification de la rvocation: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Notez que la validit affiche pour la cl n'est pas ncessairement\n" -"correcte moins de redmarrer le programme.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"ATTENTION: C'est une cl du style PGP2. Ajouter une photo\n" -"d'identit peut empcher certaines versions de PGP d'accepter\n" -"cette cl\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Etes-vous sur de vouloir l'ajouter ? (y/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" -"Vous ne pouvez pas ajouter de photo d'identit une cl du style PGP2.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Supprimer cette bonne signature ? (o/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Supprimer cette signature invalide ? (o/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Supprimer cette signature inconnue ? (o/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Faut-il vraiment supprimer cette auto-signature ? (o/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d signature supprime.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d signatures supprimes\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Rien n'a t supprim.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Entrez la taille de la cl" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Enlevez les slections des cls secrtes.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Vous devez slectionner au plus une cl secondaire.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Changer la date d'expiration d'une cl secondaire.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Changer la date d'expiration de la cl principale.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Vous ne pouvez pas changer la date d'expiration d'une cl v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Pas de signature correspondante dans le porte-cls secret\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Vous devez slectionner exactement un utilisateur.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "cl %08lX: auto-signature sur le nom d'utilisateur \"%s\" invalide\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Pas d'utilisateur avec l'index %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Pas de cl secondaire avec l'index %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "nom d'utilisateur: " - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\n" -"sign avec votre cl %08lX %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"sign localement avec votre cl %08lX %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Cette signature a expir le %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Etes-vous sur de vouloir toujours le rvoquer ? (y/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Gnrer un certificat de rvocation pour cette signature ? (o/N) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Vous avez sign ces noms d'utilisateurs:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " sign par %08lX %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " rvoqu par %08lX %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Vous tes sur le point de rvoquer ces signatures:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " sign par %08lX %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (non-exportable)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Crer rellement les certificats de rvocation ? (o/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "pas de cl secrte\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Affichage %s photo d'identit de taille %ld pour la cl 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Politique de signature: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Politique de signature: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "ATTENTION: des donnes de notation invalides ont t dtectes\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notation de signature: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Notation de signature: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "illisible par un humain" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Porte-cls" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [expire: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "lister les cls et les empreintes" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Empreinte de la cl =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Empreinte de la cl =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Empreinte de la cl =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Empreinte de la cl =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algorithme de hachage `%s' invalide\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "donnes chiffres avec %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "chiffr avec l'algorithme inconnu %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "la cl publique est %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "donnes chiffres par cl publique: bonne cl de chiffrement (DEK)\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "chiffr avec une cl de %u bits %s, ID %08lX, cre le %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "chiffr avec une cl %s, %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "le dchiffrement par cl publique a chou: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "on suppose des donnes chiffres avec %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" -"L'algorithme IDEA n'est pas disponible, avec un peu de chance %s marchera\n" -"peut-tre\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "le dchiffrement a russi\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "ATTENTION: le message chiffr a t manipul !\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "le dchiffrement a chou: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTE: l'expditeur a demand pour vos yeux seulement\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nom de fichier original: '%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "rvocation autonome - utilisez gpg --import pour l'appliquer\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notation: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Politique: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "vrification de signature supprime\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "le traitement de ces signatures multiples est impossible\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Signature faite %.*s avec une cl %s ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "MAUVAISE signature de \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Signature expire de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Bonne signature de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[incertain]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Impossible de vrifier la signature: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "la signature n'est pas dtache\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "signature autonome de classe 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "signature d'un ancien style (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "paquet racine invalide dtect dans proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "impossible d'empcher la gnration de fichiers core: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Les algorithmes exprimentaux ne devraient pas tre utiliss !\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"Cet algorithme de chiffrement est dconseill; utilisez-en un\n" -"plus standard !\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "le module de chiffrement IDEA n'est pas prsent\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"voir http://www.gnupg.org/fr/why-not-idea.html pour plus d'informations\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "AVERTISSEMENT: `%s' est une option dconseille.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "AVERTISSEMENT: `%s' est une option dconseille.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "utilisez \"--keyserver-options %s\" la place\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "impossible de grer l'algorithme cl publique %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "un sous-paquet de type %d possde un bit critique\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent n'est pas disponible dans cette session\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "impossible d'obtenir le pid du client pour l'agent\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "" -"impossible d'obtenir le descripteur de lecture du serveur\n" -"pour l'agent\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "" -"impossible d'obtenir le descripteur d'criture du serveur pour l'agent\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "la variable d'environnement GPG_AGENT_INFO est mal dfinie\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "le protocole gpg-agent version %d n'est pas support\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "impossible de se connecter `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problme de communication avec ssh-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problme avec l'agent - arrt d'utilisation de l'agent\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (ID cl principale %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Vous avez besoin d'un mot de passe pour dverrouiller la cl secrte pour\n" -"l'utilisateur:\n" -"\"%.*s\"\n" -"cl %u bits %s, ID %08lX, cre %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Entrez le mot de passe\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Rptez le mot de passe\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "mot de passe trop long\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "rponse de l'agent invalide\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "annul par l'utilisateur\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problme avec l'agent : l'agent renvoie 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Vous avez besoin d'un mot de passe pour dverrouiller la cl secrte pour\n" -"l'utilisateur: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "cl de %u bits %s, ID %08lX, cre le %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "impossible de demander un mot de passe en mode automatique\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Entrez le mot de passe: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Rptez le mot de passe: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"les donnes ne sont pas enregistres; utilisez l'option --output pour\n" -"les enregistrer\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "erreur pendant la cration de `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Signature dtache.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Entrez le nom du fichier de donnes: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lecture de l'entre standard...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "pas de donnes signes\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "impossible d'ouvir les donnes signes `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinataire anonyme; essai de la cl secrte %08lX...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "d'accord, nous sommes le rcipient anonyme.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "l'ancien codage de la cl de chiffrement (DEK) n'est pas support\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "l'algorithme de chiffrement %d%s est inconnu ou dsactiv\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "" -"NOTE: l'algorithme de chiffrement %d n'a pas t trouv dans les " -"prfrences\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTE: la cl secrte %08lX a expir le %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "cl %08lX: la cl a t rvoque !\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "requte de la cl %08lX du serveur de cls HKP %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "impossible d'obtenir les cls du serveur: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "erreur pendant l'envoi de `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "l'envoi `%s' s'est droul avec succs (rsultat=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "l'envoi `%s' a chou: le rsultat est %u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "recherche de \"%s\" du serveur HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "impossible de chercher une cl dans le serveur : %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "les parties secrtes ne sont pas disponibles\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "l'algorithme de protection %d%s n'est pas support\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Mot de passe invalide ; ressayez" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "ATTENTION: Cl faible dtecte - changez encore le mot de passe.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"gnration de la somme de contrle de 16 bits (dprcie) pour protger\n" -"la cl secrte\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"Ceci est une cl ElGamal gnre par PGP qui n'est PAS sre pour les\n" -"signatures !\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "la cl publique est plus rcente de %lu seconde que la signature\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "la cl publique est plus rcente de %lu secondes que la signature\n" - -# on s'amuse comme on peut... -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"la cl a t cre %lu seconde dans le futur (rupture spatio-temporelle ou\n" -"problme d'horloge)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"la cl a t cre %lu secondes dans le futur (rupture spatio-temporelle ou\n" -"problme d'horloge\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTE: la cl de signature %08lX a expir le %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"la signature est suppose tre fausse car un bit critique est\n" -"inconnu\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"AVERTISSEMENT: impossible de faire une expansion base de %% de l'url\n" -"de politique (trop grande). Utilisation de la version non expanse.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"AVERTISSEMENT: impossible de faire une expansion base de %% de l'url\n" -"de politique (trop grande). Utilisation de la version non expanse.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "Impossible de vrifier la signature cre: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "Signature %s de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "AVERTISSEMENT: `%s' est un fichier vide\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"il n'est possible de signer avec des cls de style PGP 2.x uniquement\n" -"en mode --pgp2\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "impossible de crer %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"NOTE: l'algorithme de chiffrement %d n'a pas t trouv dans les " -"prfrences\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "signature:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"il n'est possible de faire une signature en texte clair avec des cls\n" -"de style PGP 2.x qu'en mode --pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "le chiffrement %s sera utilis\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "impossible de traiter les lignes plus longues que %d caractres\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "la ligne d'entre est plus longue que %d caractres\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "enregistrement de base de confiance %lu: lseek a chou: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "" -"enregistrement de la base de confiance %lu: l'criture a chou (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transaction de base de confiance trop volumineuse\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: impossible d'accder: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: le rpertoire n'existe pas !\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: impossible de crer le verrouillage\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: impossible de crer le verrou\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: impossible de crer: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: impossible de crer un enregistrement de version: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: base de confiance invalide cre\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: base de confiance cre\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: base de confiance invalide\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: la cration de la table de hachage a chou: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: erreur pendant la mise jour de l'enregistrement de version: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: erreur pendant la lecture de l'enregistrement de version: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: erreur pendant l'criture de l'enregistrement de version: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "base de confiance: lseek() a chou: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "base de confiance: la lecture a chou (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: ce n'est pas un fichier de base de confiance\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: enregistrement de version avec un numro %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: version %d du fichier invalide\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: erreur pendant la lecture de l'enregistrement libre: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "" -"%s: erreur pendant l'criture de l'enregistrement de\n" -"rpertoire: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: n'a pu mettre un enregistrement zro: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: impossible d'ajouter un enregistrement: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "la base de confiance est corrompue; excutez gpg --fix-trustdb.\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' n'est pas une identification de cl longue valide\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "cl %08lX: accepte comme cl de confiance.\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "la cl %08lX apparat plusieurs fois dans la base de confiance\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "cl %08lX: pas de cl publique pour la cl de confiance - ignore\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "" -"enregistrement de confiance %lu, type de requte %d: la lecture a chou: %" -"s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "l'enregistrement de confiance %lu: n'est pas du type demand %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "enregistrement de confiance %lu, type %d: l'criture a chou: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "base de confiance: la synchronisation a chou: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "vrification de la base de confiance inutile\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "la prochaine vrification de la base de confiance aura lieu le %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "vrifier la base de confiance\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "cl publique %08lX non trouve : %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "la cl publique de la cl de confiace ultime %08lX est introuvable\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"vrification la profondeur %d sign=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"impossible de vrifier la signature.\n" -"Rappelez-vous bien que le fichier de signature (.sig ou .asc)\n" -"doit tre le premier fichier indiqu sur la ligne de commande.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "" -"la ligne d'entre %u est trop longue ou il manque un caractre de saut\n" -"de ligne\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"la cl n'est pas marque comme non-sre; on ne peut pas l'utiliser avec le\n" -"pseudo-gnrateur de nombres alatiores !\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "`%s' a t ignor: dupliqu\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "`%s' a t ignor: %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "ignor: cl secrte dj prsente\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"`%s' a t ignore: c'est une cl ElGamal gnre par PGP qui n'est pas\n" -"sre pour les signatures !\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Le fichier `%s' existe. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Rcrire (o/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: suffixe inconnu\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Entrez le nouveau nom de fichier" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "criture vers la sortie standard\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "les donnes signes sont supposes tre dans `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: nouveau fichier d'options cr\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: impossible de crer le rpertoire: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: rpertoire cr\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"ATTENTION: Le message a t chiffr avec une cl faible pendant le\n" -"chiffrement symtrique.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problme de gestion des paquets chiffrs\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "cl faible gnre - nouvel essai\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"impossible d'viter une cl faible pour le chiffrement symtrique:\n" -"%d essais ont eu lieu !\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA ncessite l'utilisation d'un algorithme de hachage de 160 bits\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "impossible de faire cela en mode automatique sans --yes\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Enlever cette cl du porte-cls ? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "C'est une cl secrte - faut-il vraiment l'effacer ? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "la suppression du bloc de cls a chou : %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "les informations de confiance au propritaires ont t effaces\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "il y a une cl secrte pour la cl publique \"%s\" !\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "utiliser l'option --delete-secret-keys pour l'effacer d'abord.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"C'est vous d'assigner une valeur ici; cette valeur ne sera jamais\n" -"envoye une tierce personne. Nous en avons besoin pour crer le rseau\n" -"de confiance (web-of-trust); cela n'a rien voir avec le rseau des\n" -"certificats (cr implicitement)" - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Pour mettre en place le Rseau de confiance (Web of Trust), GnuPG a\n" -"besoin de savoir en quelles cls votre confiance est ultime - ce sont\n" -"en gnral les cls dont vous avez accs la cl secrte. Rpondez\n" -"\"oui\" pour indiquer que votre confiance en cette cl est ultime\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Si vous voulez utiliser cette cl rvoque quand-mme, rpondez oui." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "Si vous voulez utiliser cette cl peu sre quand-mme, rpondez oui." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "" -"Entrez le nom d'utilisateur de la personne qui vous voulez envoyer\n" -"le message." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Slectionnez l'algorithme utiliser.\n" -"DSA (alias DSS) est l'algorithme de signatures lectroniques qui ne peut\n" -"tre utilis que pour les signatures. C'est l'algorithme recommand car\n" -"la vrification des signatures DSA est beaucoup plus rapide que celle des\n" -"signatures ElGamal.\n" -"\n" -"ElGamal est un algorithme pouvant la fois tre utilis pour les\n" -"signatures et le chiffrement. OpenPGP en distingue deux sortes:\n" -"l'une destine uniquement au chiffrement et l'autre pouvant aussi bien\n" -"servir aux signatures ; elles sont en fait identiques mais certains\n" -"paramtres doivent tre spcialement choisis pour que la cl gnre des\n" -"signatures sres: ce programme est capable de le faire mais les autres\n" -"implantations de OpenPGP ne sont pas obliges d'accepter cette forme de\n" -"cl.\n" -"\n" -"La premire cl (cl principale) doit toujours tre capable de signer ;\n" -"c'est pourquoi la cl ElGamal de chiffrement seul est alors dsactive." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Bien que ces cls soient dfinies dans la RFC2440 elles ne sont pas\n" -"conseilles car tous les programmes ne les supportent pas et les\n" -"signatures cres avec elles sont plutt longues et trs lentes vrifier." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Entrez la taille de la cl" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Rpondez oui ou non" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Entrez la valeur demande comme indiqu dans la ligne de commande.\n" -"On peut entrer une date ISO (AAAA-MM-JJ) mais le rsultat d'erreur sera\n" -"mauvais - le systme essaierait d'interprter la valeur donne comme un\n" -"intervalle." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Entrez le nom du propritaire de la cl" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "entrez une adresse e-mail optionnelle mais hautement recommande" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Entrez un commentaire optionnel" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N pour changer le nom.\n" -"C pour changer le commentaire.\n" -"E pour changer l'adresse e-mail.\n" -"O pour continuer gnrer la cl.\n" -"Q pour arrter de gnrer de cl." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Rpondez oui (ou simplement o) pour gnrer la sous-cl" - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Quand vous signez un nom d'utilisateur d'une cl, vous devriez d'abord\n" -"vrifier que la cl appartient la personne nomme. Il est utile que\n" -"les autres personnes sachent avec quel soin vous l'avez vrifi.\n" -"\n" -"\"0\" signifie que vous n'avez pas d'opinon.\n" -"\n" -"\"1\" signifie que vous croyez que la cl appartient la personne qui\n" -"dit la possder mais vous n'avez pas pu vrifier du tout la cl.\n" -"C'est utile lorsque vous signez la cl d'un pseudonyme.\n" -"\n" -"\"2\" signifie que vous avez un peu vrifi la cl. Par exemple, cela\n" -"pourrait tre un vrification de l'empreinte et du nom de\n" -"l'utilisateur avec la photo.\n" -"\n" -"\"3\" signifie que vous avez compltement vrifi la cl. Par exemple,\n" -"cela pourrait tre une vrification de l'empreinte, du nom de\n" -"l'utilisateur avec un document difficile contrefaire (comme un\n" -"passeport) et de son adresse e-mail (vrifi par un change de\n" -"courrier lectronique).\n" -"\n" -"Notez bien que les exemples donns ci-dessus pour les niveaux 2 et\n" -"3 ne sont *que* des exemples.\n" -"C'est vous de dcider quelle valeur mettre quand vous signez\n" -"les cls des autres personnes.\n" -"\n" -"Si vous ne savez pas quelle rponse est la bonne, rpondez \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Rpondez oui si vous voulez signer TOUS les noms d'utilisateurs" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Rpondez oui si vous voulez vraiment supprimer ce nom\n" -"d'utilisateur. Tous les certificats seront alors perdus en mme temps !" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Rpondez oui s'il faut vraiment supprimer la sous-cl" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"C'est une signature valide dans la cl; vous n'avez pas normalement\n" -"intrt supprimer cette signature car elle peut tre importante pour\n" -"tablir une connection de confiance vers la cl ou une autre cl certifie\n" -"par celle-l." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Cette signature ne peut pas tre vrifie parce que vous n'avez pas la\n" -"cl correspondante. Vous devriez remettre sa supression jusqu' ce que\n" -"vous soyez sr de quelle cl a t utilise car cette cl de signature\n" -"peut tablir une connection de confiance vers une autre cl dj certifie." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"Cette signature n'est pas valide. Vous devriez la supprimer de votre\n" -"porte-cls." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Cette signature relie le nom d'utilisateur la cl. Habituellement\n" -"enlever une telle signature n'est pas une bonne ide. En fait GnuPG peut\n" -"ne plus tre capable d'utiliser cette cl. Donc faites ceci uniquement si\n" -"cette auto-signature est invalide pour une certaine raison et si une autre\n" -"est disponible." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Changer les prfrences de tous les noms d'utilisateurs (ou juste\n" -"ceux qui sont slectionns) vers la liste actuelle. La date de toutes\n" -"les auto-signatures affectes seront avances d'une seconde.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Entrez le mot de passe ; c'est une phrase secrte \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Rptez le dernier mot de passe pour tre sr de ce que vous avez tap." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Donnez le nom du fichier auquel la signature se rapporte" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Rpondez oui s'il faut vraiment rcrire le fichier" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Entrez le nouveau nom de fichier. Si vous tapez simplement ENTRE le\n" -"fichier par dfaut (indiqu entre crochets) sera utilis." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Vous devriez donner une raison pour la certification. Selon le contexte\n" -"vous pouvez choisir dans cette liste:\n" -" La cl a t compromise\n" -" Utilisez cette option si vous avez une raison de croire que des\n" -" personnes ont pu accder votre cl secrte sans autorisation.\n" -" La cl a t remplace\n" -" Utilisez cette option si vous avez remplac la cl par une nouvelle.\n" -" La cl n'est plus utilise\n" -" Utilisez cette option si cette cl n'a plus d'utilit.\n" -" Le nom d'utilisateur n'est plus valide\n" -" Utilisez cette option si le nom d'utilisateur ne doit plus tre\n" -" utilis. Cela sert gnralement indiquer qu'une adresse e-mail\n" -" est invalide.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Si vous le dsirez, vous pouvez entrer un texte qui explique pourquoi vous\n" -"avez mis ce certificat de rvocation. Essayez de garder ce texte concis.\n" -"Une ligne vide dlimite la fin du texte.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Pas d'aide disponible" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Pas d'aide disponible pour `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "erreur durant la cration du porte-cls `%s' : %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "le porte-cls `%s` a t cr\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "la reconstruction du cache de porte-cls a chou : %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "" -"ATTENTION: 2 fichiers avec des informations confidentielles existent.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s est le fichier original\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s est le nouveau\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Rparez ce problme de scurit possible\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "vrification du porte-cls `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu cls traites jusqu'ici (%lu signatures)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu cls vrifies (%lu signatures)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: porte-cls cr\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "vous devez redmarrer GnuPG pour qu'il puisse lire le nouveau\n" -#~ "fichier options\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "le changement de permission de `%s' a chou: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOM=VALEUR|utiliser ces donnes de notation" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "le premier caractre du nom d'une notation doit tre un lettre ou un " -#~ "trait\n" -#~ "de soulignement\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "les points dans le nom d'une notation doivent tre entours d'autes " -#~ "caractres\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "ATTENTION: Cette cl possde dj une photo d'identit.\n" -#~ " Ajouter une autre photo d'identit peut poser des\n" -#~ " problmes avec certaines versions de PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Vous ne pouvez avoir qu'une seule photo d'identit par cl.\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Empreinte:" - -#~ msgid " Fingerprint:" -#~ msgstr " Empreinte :" diff --git a/po/gl.po b/po/gl.po deleted file mode 100644 index 119573bf4..000000000 --- a/po/gl.po +++ /dev/null @@ -1,5002 +0,0 @@ -# Galician translation of GNUpg -# Copyright (C) 2001 Free Software Foundation, Inc. -# Jacobo Tarrio , 2001. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-05-14 13:21+0200\n" -"Last-Translator: Jacobo Tarrio \n" -"Language-Team: Galician \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Aviso: sase unha zona insegura de memoria!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "mire en http://www.gnupg.org/faq.html para obter mis informacin\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "a operacin non posible sen memoria inicializada como segura\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(pode que usara o programa equivocado para esta tarefa)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "si" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "sS" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "non" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "abandonar" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "aA" - -#: util/errors.c:54 -msgid "general error" -msgstr "erro xeral" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "tipo de paquete descoecido" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "versin descoecida" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algoritmo de chave pblica descoecido" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algoritmo de resumo descoecido" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "chave pblica errnea" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "chave secreta errnea" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "sinatura errnea" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "error de checksum" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "contrasinal errneo" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "non se atopou a chave pblica" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algoritmo de cifrado descoecido" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "non foi posible abri-lo chaveiro" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "paquete non vlido" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armadura non vlida" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "non hai tal id de usuario" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "a chave secreta non est dispoible" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "empregouse unha chave secreta errnea" - -#: util/errors.c:72 -msgid "not supported" -msgstr "non est soportado" - -#: util/errors.c:73 -msgid "bad key" -msgstr "chave incorrecta" - -#: util/errors.c:74 -msgid "file read error" -msgstr "erro de lectura de ficheiro" - -#: util/errors.c:75 -msgid "file write error" -msgstr "erro de escritura de ficheiro" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritmo de compresin descoecido" - -#: util/errors.c:77 -msgid "file open error" -msgstr "erro de apertura de ficheiro" - -#: util/errors.c:78 -msgid "file create error" -msgstr "erro de creacin de ficheiro" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "contrasinal incorrecto" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmo de chave pblica non implementado" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritmo de cifrado non implementado" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "clase de sinatura descoecida" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "erro da base de datos de confianza" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI errneo" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "lmite de recursos" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "chaveiro incorrecto" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "certificado errneo" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "id de usuario mal formado" - -#: util/errors.c:89 -msgid "file close error" -msgstr "erro de peche de ficheiro" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "erro de cambio de nome de ficheiro" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "erro de borrado de ficheiro" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "datos inesperados" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "conflicto de selo de data" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritmo de chave pblica imposible de usar" - -#: util/errors.c:95 -msgid "file exists" -msgstr "o ficheiro xa existe" - -#: util/errors.c:96 -msgid "weak key" -msgstr "chave feble" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argumento non vlido" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI incorrecto" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI non soportado" - -#: util/errors.c:100 -msgid "network error" -msgstr "erro de rede" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "non cifrado" - -#: util/errors.c:103 -msgid "not processed" -msgstr "non procesado" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "chave pblica non utilizable" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "chave secreta non utilizable" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "erro do servidor de chaves" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... isto un erro (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "atopou un erro ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "non se puido abrir `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "non se puido facer stat sobre `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' non un ficheiro normal - ignrase\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "nota: o ficheiro random_seed est baleiro\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "aviso: tamao de random_seed non vlido - non se emprega\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "non se pode ler de `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "nota: o ficheiro random_seed non se actualiza\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "non se pode crear `%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "non se pode escribir en `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "non se pode pechar `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "AVISO: emprgase un xerador de nmeros aleatorios inseguro!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"O xerador de nmeros aleatorios s un truco para poder\n" -"executalo - non de ningn xeito un xerador de nmeros\n" -"aleatorios seguro!\n" -"\n" -"NON USE NINGUN DATO XERADO POR ESTE PROGRAMA!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Non hai suficientes bytes aleatorios dispoibles. Por favor, faga outro\n" -"traballo para lle dar ao sistema operativo unha oportunidade de acumular\n" -"mis entropa (Precsanse %d bytes mis)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Comandos:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[ficheiro]|facer unha sinatura" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[ficheiro]|facer unha sinatura en texto claro" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "facer unha sinatura separada" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "cifrar datos" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[ficheiros]|cifrar ficheiros" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "cifrar s con cifrado simtrico" - -#: g10/g10.c:315 -msgid "store only" -msgstr "s armacenar" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "descifrar datos (por defecto)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[ficheiros]|descifrar ficheiros" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verificar unha sinatura" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "ve-la lista de chaves" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "ve-la lista de chaves e sinaturas" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "verifica-las sinaturas das chaves" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "ve-la lista de chaves e pegadas dactilares" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "ve-la lista de chaves secretas" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "xerar un novo par de chaves" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "borrar chaves do chaveiro pblico" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "borrar chaves do chaveiro secreto" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "asinar unha chave" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "asinar unha chave localmente" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "asinar unha chave de xeito non revocable" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "asinar unha chave localmente e de xeito non revocable" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "asinar ou editar unha chave" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "xerar un certificado de revocacin" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exportar chaves" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exportar chaves a un servidor de chaves" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importar chaves dun servidor de chaves" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "buscar chaves nun servidor de chaves" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "actualizar tdalas chaves dun servidor de chaves" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importar/mesturar chaves" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "listar s a secuencia de paquetes" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exporta-los valores de confianza no propietario" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importa-los valores de confianza no propietario" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "actualiza-la base de datos de confianza" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "actualizacin inatendida da base de datos de confianza" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "amaar unha base de datos de confianza corrompida" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Quita-la armadura a un ficheiro ou entrada estndar" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Pr armadura a un ficheiro ou entrada estndar" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [ficheiros]|visualizar resumos de mensaxes" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opcins:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "crear sada con armadura en ascii" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOME|cifrar para NOME" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOME|empregar NOME como valor por defecto do destinatario" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "usa-la chave por defecto coma o destinatario por defecto" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "empregar este id de usuario para asinar ou descifrar" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|axusta-lo nivel de compresin a N (0 desactiva)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "usar modo de texto cannico" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "usar coma ficheiro de sada" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "lareto" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "ser un pouquio mis calado" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "non usa-la terminal en absoluto" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "forzar sinaturas v3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "non forzar sinaturas v3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "forzar sinaturas de chave v4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "non forzar sinaturas de chave v4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "sempre usar un MDC para cifrar" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "nunca usar un MDC para cifrar" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "non facer ningn cambio" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "emprega-lo gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "modo por lotes: non preguntar nunca" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "asumir `si' na maiora das preguntas" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "asumir `non' na maiora das preguntas" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "engadir este chaveiro lista de chaveiros" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "engadir este chaveiro secreto lista" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "amosar en que chaveiro est unha chave listada" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOME|empregar NOME coma chave secreta por defecto" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|empregar este servidor de chaves para buscar chaves" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAME|axusta-lo xogo de caracteres do terminal a NOME" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "le-las opcins dun ficheiro" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|DF|escribi-la informacin de estado a este DF" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[ficheiro]|escribi-la informacin de estado no ficheiro" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|IDCHAVE|confiar absolutamente nesta chave" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FICHEIRO|carga-lo mdulo de extensin FICHEIRO" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emula-lo modo descrito no RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"axustar tdalas opcins de paquetes, cifrado e resumo ao comportamento " -"OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"axustar tdalas opcins de paquetes, cifrado e resumo ao comportamento PGP 2." -"x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|emprega-lo modo de contrasinal N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NOME|emprega-lo algoritmo para resumos NOME para os contrasinais" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NOME|emprega-lo algoritmo de cifrado NOME para os contrasinais" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOME|emprega-lo algoritmo de cifrado NOME" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOME|emprega-lo algoritmo de resumos de mensaxes NOME" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|emprega-lo algoritmo de compresin N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "descarta-lo campo de id de chave dos paquetes cifrados" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Amosar Identificacins Fotogrficas" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Non amosar Identificacins Fotogrficas" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Estabrece-la lia de comando para ve-las Identificacins Fotogrficas" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Vexa a pxina man para un listado completo de comandos e opcins)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Exemplos:\n" -"\n" -" -se -r Bob [ficheiro] asinar e cifrar para o usuario Bob\n" -" --clearsgn [ficheiro] facer unha sinatura en texto claro\n" -" --detach-sign [ficheiro] facer unha sinatura separada\n" -" --list-keys [nomes] amosa-las chaves\n" -" --fingerprint [nomes] amosa-las pegadas dactilares\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "" -"Por favor, informe dos erros no programa a ,\n" -"e dos erros na traduccin a .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Uso: gpg [opcins] [ficheiros] (-h para ve-la axuda)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintaxe: gpg [opcins] [ficheiros]\n" -"asinar, verificar, cifrar ou descifrar\n" -"a operacin por defecto depende dos datos de entrada\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritmos soportados:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uso: gpg [opcins] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "comandos conflictivos\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Aviso: propiedade insegura en %s \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Aviso: permisos inseguros en %s \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Aviso: propiedade insegura en %s \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Aviso: permisos inseguros en %s \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTA: non existe o ficheiro de opcins por defecto `%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTA: non existe o ficheiro de opcins por defecto `%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "ficheiro de opcins `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "lendo as opcins de `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s non un xogo de caracteres vlido\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "non se puido analisa-lo URI do servidor de chaves\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: versin do ficheiro incorrecta %d\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armadura non vlida" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: versin do ficheiro incorrecta %d\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "chaveiro incorrecto" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "non se puido estabrecer exec-path a %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "AVISO: o programa pode crear un ficheiro 'core'!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "AVISO: %s fai que se ignore %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTA: %s non para uso normal!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s non se admite con %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s non ten sentido empregndoo con %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "s pode crear sinaturas separadas ou en claro no modo --pgp2\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "non pode asinar e cifrar ao mesmo tempo no modo --pgp2\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" -"debe empregar ficheiros (e non canalizacins) ao traballar con --pgp2 " -"activado.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "para cifrar unha mensaxe en modo --pgp2 precsase da cifra IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "esta mensaxe pode non ser utilizable por PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "o algoritmo de cifrado seleccionado non vlido\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "o algoritmo de resumo seleccionado non vlido\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "o algoritmo de resumo seleccionado non vlido\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "o algoritmo de compresin debe estar entre %d e %d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed debe ser superior a 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed debe ser superior a 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth debe valer entre 1 e 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTA: desaconsllase encarecidamente o modo S2K simple (0)\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "modo S2K non vlido; debe ser 0, 1 ou 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "nivel de comprobacin por defecto non vlido; debe ser 0, 1, 2 ou 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "preferencias non vlidas\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "preferencias non vlidas\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "preferencias non vlidas\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "preferencias non vlidas\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "non se puido inicializa-la base de datos de confianzas: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [ficheiro]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [ficheiro]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [ficheiro]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [ficheiro]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [ficheiro]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [ficheiro]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [ficheiro]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [ficheiro]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key id-de-usuario" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key id-de-usuario" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key id-de-usuario" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key id-de-usuario" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key id-de-usuario [comandos]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "non se puido abrir %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [id-de-usuario] [chaveiro]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "non se puido quita-la armadura: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "non se puido poe-la armadura: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algoritmo de hash non vlido `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[ficheiro]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Escriba a sa mensaxe ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "non se puido abrir `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"un nome de notacin s debe ter letras, dxitos, puntos ou guins baixos e " -"rematar con '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "un valor de notacin non pode empregar ningn carcter de control\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "o URL de normativa de certificacin dado non vlido\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "o URL de normativa de sinaturas dado non vlido\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armadura: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "cabeceira de armadura non vlida: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "cabeceira de armadura: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "cabeceira de sinatura en claro non vlida\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "sinaturas en texto claro aniadas\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "lia escapada cunha barra non vlida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armadura inesperada:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "carcter radix64 non vlido %02x omitido\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "fin de ficheiro prematura (non hai CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "fin de ficheiro prematura (no CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC mal formado\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Erro de CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "fin de ficheiro prematura (nas lias adicionais)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "error nunha lia adicional\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "non se atoparon datos OpenPGP vlidos.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armadura incorrecta: lia mis longa ca %d caracteres\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"carcter quoted-printable na armadura - seguramente empregouse un MTA con " -"erros\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Non se especificou un motivo" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "A chave obsoleta" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Esta chave quedou descoberta" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Xa non se emprega esta chave" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "O ID de usuario xa non vlido" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Motivo para a revocacin: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Comentario de revocacin: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMsSoO" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Non se asignou un valor de confianza a:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Por favor, decida canto confa en que este usuario verifique\n" -"correctamente as chaves de outros usuarios (mirando nos pasaportes,\n" -"comprobando pegadas dactilares de varias fontes...).\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Non sei\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = NON confo\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Confo marxinalmente\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Confo totalmente\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Confo absolutamente\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = amosar mis informacin\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = voltar ao men principal\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " o = omitir esta chave\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " s = sar\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "A sa decisin? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Est seguro de querer dar confianza absoluta a esta chave? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificados que conducen a unha chave de confianza absoluta:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "chave %08lX: esta chave est revocada!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Empregar esta chave de tdolos xeitos?" - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "chave %08lX: unha subchave est revocada!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: a chave caducou\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Non hai indicacins de que a sinatura pertenza ao seu propietario.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Esta chave NON de confianza\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Non seguro que esta chave pertenza de verdade ao seu propietario\n" -"pero acptase de tdolos xeitos\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Esta chave probablemente pertenza ao propietario\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Esta chave pertncenos a ns\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"NON seguro que a chave pertenza ao seu propietario.\n" -"Se *de verdade* sabe o que est a facer, pode respostar \n" -"seguinte pregunta cun \"si\"\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "AVISO: Emprgase unha chave que non de confianza!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "AVISO: Esta chave est revocada polo propietario!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Isto pode significar que a sinatura est falsificada.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "AVISO: Esta subchave est revocada polo propietario!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Nota: Esta chave est desactivada.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Nota: Esta chave xa caducou!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "AVISO: Esta chave non est certificada cunha sinatura de confianza!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Non hai indicacins de que a sinatura pertenza ao seu propietario.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "AVISO: Esta chave NON de confianza!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Probablemente, a sinatura estea FALSIFICADA.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"AVISO: Esta chave non est certificada con sinaturas de suficiente " -"confianza!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Non seguro que a sinatura pertenza ao seu propietario.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: omitido: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: omitido: a chave pblica xa est presente\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Non especificou un ID de usuario. (pode empregar \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Introduza o ID de usuario. Remate cunha lia en branco: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Non hai tal ID de usuario.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "" -"omitido: a chave pblica xa est estabrecida coma destinatario por defecto\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "A chave pblica est desactivada.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "omitido: chave pblica xa estabrecida\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "destinatario por defecto `%s' descoecido\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: omitido: a chave pblica est desactivada\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "non hai enderezos vlidos\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "a preferencia %c%lu non vlida\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "preferencia %c%lu duplicada\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "demasiadas preferencias `%c'\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "caracter non vlido na cadea de preferencias\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "escribindo a propia sinatura\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "escribindo a propia sinatura\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "escribindo unha sinatura que liga a chave\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "tamao de chave non vlido; empregando %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "tamao de chave redondeado a %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Por favor, seleccione o tipo de chave que quere:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA e ElGamal (por defecto)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (s asinar)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (s cifrar)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (asinar e cifrar)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (s asinar)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (s cifrar)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (asinar e cifrar)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "A sa seleccin? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Este algoritmo est obsoleto - crear de tdolos xeitos? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Seleccin non vlida.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Hase crear unh novo par de chaves %s.\n" -" tamao de chave mnimo: 768 bits\n" -" tamao de chave por defecto: 1024 bits\n" -" tamao de chave mximo recomendado: 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Qu tamao de chave quere? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA s admite tamaos entre 512 e 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "chave pequena de mis; 1024 o menor valor admitido para RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "chave pequena de mis; 768 o menor valor admitido\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "chave grande de mis; %d o maior tamao admitido.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"As chaves maiores de 2048 bits non se aconsellan porque\n" -"os clculos levan MOITO tempo!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Est seguro de que quere este tamao de chave? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"De acordo, pero tea en conta que a radiacin do monitor e o teclado tamn " -"son vulnerables a ataques!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "O tamao de chave requerido son %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "redondeado a %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Por favor, indique canto tempo debera ser vlida a chave.\n" -" 0 = a chave non caduca\n" -" = a chave caduca en n das\n" -" w = a chave caduca en n semanas\n" -" m = a chave caduca en n meses\n" -" y = a chave caduca en n anos\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Por favor, indique canto tempo debera ser vlida a sinatura.\n" -" 0 = a sinatura non caduca\n" -" = a sinatura caduca en n das\n" -" w = a sinatura caduca en n semanas\n" -" m = a sinatura caduca en n meses\n" -" y = a sinatura caduca en n anos\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Por canto tempo vlida a chave? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Por canto tempo vlida a sinatura? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valor non vlido\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s non caduca nunca\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s caduca o %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"O seu sistema non pode amosar datas mis al do 2038.\n" -"Anda as, hase tratar correctamente ata o 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Isto correcto? (s/n) " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Precisa un ID de usuario para identifica-la sa chave; o software constre " -"o\n" -"id de usuario co Nome, un Comentario e un Enderezo de E-mail deste xeito:\n" -" \"Heinrich Heime (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nome: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Caracter non vlido no nome\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "O nome non pode comezar cun dxito\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "O nome debe ter alomenos 5 caracteres\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Enderezo de E-mail: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Non un enderezo de e-mail vlido\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Comentario: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Carcter non vlido no comentario\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Est a usa-lo xogo de caracteres `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Escolleu este ID de usuario:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" -"Por favor, non poa o enderezo de correo no nome real ou no comentario\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeAaSs" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Cambia-lo (N)ome, (C)omentario, (E)-mail ou (S)ar? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Cambiar (N)ome, (C)omentario, (E)-mail ou (A)ceptar/(S)ar? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Por favor, corrixa antes o erro\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Necesita un contrasinal para protexe-la sa chave secreta.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "o contrasinal non se repetiu correctamente; tnteo de novo" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Non quere empregar un contrasinal - unha idea *moi* mala!\n" -"Hase facer as de tdolos xeitos; pode cambia-lo contrasinal en calquera\n" -"momento, empregando este programa coa opcin \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Cmpre xerar unha morea de bytes aleatorios. E unha boa idea facer outras\n" -"cousas (premer teclas no teclado, move-lo rato, usa-los discos duros)\n" -"mentres se xeran os nmeros primos; isto proporcinalle ao xerador de\n" -"nmeros aleatorios unha opoertunidade de acumular entropa de abondo.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "O par de chaves DSA ha ter 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Cancelouse a xeracin de chaves.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "gravando a chave pblica en `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "gravando a chave secreta en `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "non se atopou un chaveiro pblico no que se poida escribir: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "non se atopou un chaveiro privado no que se poida escribir: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "erro escribindo no chaveiro pblico `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "erro escribindo no chaveiro secreto `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "creronse e asinronse as chaves pblica e secreta.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "chave marcada coma de confianza absoluta.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Tea en conta que non se pode empregar esta chave para cifrar. Pode que\n" -"queira emprega-lo comando \"--edit-key\" para xerar unha chave secundaria\n" -"con esa finalidade.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "A xeracin da chave fallou: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"creouse a chave %lu segundo no futuro (salto no tempo ou problemas co " -"reloxo)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"creouse a chave %lu segundos no futuro (salto no tempo ou problemas co " -"reloxo)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "NOTA: a creacin de subchaves para chaves v3 non cumpre OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Crear realmente? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output non traballa con este comando\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: non se pode abrir: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "erro ao crea-lo contrasinal: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' xa est comprimido\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: AVISO: ficheiro baleiro\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "s pode cifrar a chaves RSA de 2048 bits ou menos en modo --pgp2\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lendo de `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"non se puido emprega-la cifra IDEA para tdalas chaves s que est a " -"cifrar.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: o algoritmo de cifrado %d non foi atopado nas preferencias\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Non se admite este comando no modo %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s cifrado para: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "non se atopou a chave `%s': %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "erro ao le-lo bloque de chaves: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "chave %08lX: non unha chave rfc2440 - omitida\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "chave %08lX: non est protexida - omitida\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "chave %08lX: chave estilo PGP 2.x - omitida\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "AVISO: non se exportou nada\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "demasiadas entradas na cach de chaves pblicas - desactivada\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Non se atopou o id de usuario]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Chave %08lX non vlida convertida en vlida por --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "emprgase a chave secundaria %08lX no canto da primaria %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "chave %08lX: chave secreta sen chave pblica - ignorada\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "pasando por alto un bloque de tipo %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu chaves procesadas hasta polo momento\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "erro lendo `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Nmero total procesado: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr "novas chaves omitidas: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sin IDs de usuario: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importadas: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " sin cambios: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " novos IDs de usuario: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " novas sub-chaves: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " novas sinaturas: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " novas revocacins de chaves: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr "chaves secretas lidas: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "chaves secretas importadas: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "chaves secretas sin cambios: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importadas: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "chave %08lX: non hai ID de usuario\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "chave %08lX: non hai sub-chave para o enlace da chave\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "chave %08lX: aceptouse o ID de usuario '%s' sen auto-sinatura\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "chave %08lX: non hai IDs de usuario vlidos\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "isto pode ser causado por unha auto-sinatura que falta\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "chave %08lX: chave pblica non atopada: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "chave %08lX: nova chave - omitida\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "non se atopou un chaveiro no que se poida escribir: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "escribindo a `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "erro escribindo no chaveiro `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "chave %08lX: chave pblica importada\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "chave %08lX: non coincide coa nosa copia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "" -"chave %08lX: non foi posible localiza-lo bloque de chaves original:\n" -"%s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "" -"chave %08lX: non foi posible le-lo bloque de chaves original:\n" -"%s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "chave %08lX: 1 novo ID de usuario\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "chave %08lX: %d novos IDs de usuario\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "chave %08lX: 1 nova sinatura\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "chave %08lX: %d novas sinaturas\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "chave %08lX: 1 nova sub-chave\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "chave %08lX: %d novas sub-chaves\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "chave %08lX: sin cambios\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "non hai un chaveiro privado por defecto: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "chave %08lX: chave secreta importada\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "chave %08lX: xa estaba no chaveiro secreto\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "chave %08lX: chave secreta non atopada: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"chave %08lX: non hai chave pblica - non se pode aplica-lo\n" -"certificado de revocacin\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "" -"chave %08lX: certificado de revocacin incorrecto:\n" -"%s - rechazado\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "chave %08lX: certificado de revocacin importado\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "chave %08lX: non hai ID de usuario para a sinatura\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"chave %08lX: algoritmo de chave pblica non soportado no ID de usuario \"%s" -"\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "" -"chave %08lX: auto-sinatura non vlida no identificadr de usuario \"%s\"\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "chave %08lX: non hai sub-chave para o enlace da chave\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "chave %08lX: algoritmo de chave pblica non soportado\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "chave %08lX: enlace de sub-chave incorrecto\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "chave %08lX: enlace de sub-chave incorrecto\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "chave %08lX: non hai sub-chave para o enlace da chave\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "chave %08lX.%lu: Revocacin de subchave vlida\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "chave %08lX: enlace de sub-chave incorrecto\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "chave %08lX: pasado por alto o ID de usuario '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "chave %08lX: pasada por alto a sub-chave\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "chave %08lX: sinatura non exportable (clase %02x) - pasada por alto\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "" -"chave %08lX: certificado de revocacin no lugar errneo - pasada\n" -"por alto\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "" -"chave %08lX: certificado de revocacin incorrecto:\n" -"%s - pasado por alto\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "" -"chave %08lX: certificado de revocacin no lugar errneo - pasada\n" -"por alto\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "chave %08lX: ID de usuario duplicado detectado - mezclado\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"Aviso: a chave %08lX pode estar revocada: obtendo a chave de revocacin %" -"08lX\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"Aviso: a chave %08lX pode estar revocada: chave de revocacin %08lX " -"ausente.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "chave %08lX: certificado de revocacin engadido\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "chave %08lX: engadiuse unha sinatura de chave directa\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revocacin]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[auto-sinatura]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 sinatura errnea\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d sinaturas errneas\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 sinatura non verificada debido a unha chave que falta\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d sinaturas non verificadas debido a chaves que faltan\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 sinatura non verificada debido a un erro\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d sinaturas non verificadas debido a erros\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "detectado 1 ID de usuario sin auto-sinatura vlida\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "detectados %d IDs de usuario sin auto-sinatura vlida\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "O ID de usuario \"%s\" est revocado." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Est seguro de que quere asinalo? (s/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Non se puido asinar.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "AVISO: `%s' un ficheiro baleiro\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"A sa sinatura actual en \"%s\"\n" -" unha sinatura local.\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Quere promovela a sinatura totalmente exportable? (s/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"A sa sinatura actual en \"%s\"\n" -" unha sinatura local.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Quere promovela a sinatura totalmente exportable? (s/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" xa estaba asinado localmente coa chave %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" xa estaba asinado coa chave %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nada que asinar coa chave %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Esta chave caducou!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Esta chave ha caducar o %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Quere que a sa sinatura caduque ao mesmo tempo? (S/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"Non pode facer unha sinatura OpenPGP nunha chave PGP 2.x no modo --pgp2.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Isto podera face-la chave non utilizable en PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Con canto tino comprobou que a chave que vai asinar realmente pertence \n" -"persoa de enriba? Se non sabe que respostar, introduza \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Non hei respostar.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Non o comprobei en absoluto.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Fixen algunhas comprobacins.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Fixen comprobacins moi exhaustivas.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Esta seguro de que quere asinar esta chave\n" -"coa sa chave: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "isto pode ser causado por unha auto-sinatura que falta\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"A sinatura hase marcar coma non exportable.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"A sinatura hase marcar coma non revocable.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"A sinatura hase marcar coma non exportable.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"A sinatura hase marcar coma non revocable.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Non se comprobou esta chave en absoluto.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Comprobouse esta chave de xeito informal.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Comprobouse esta chave con moito tino.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Asinar de verdade? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "fallou a sinatura: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Esta chave non est protexida.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "as partes secretas da chave primaria non estn dispoibles.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "A chave est protexida.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Non se pode editar esta chave: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Introduza o novo contrasinal para esta chave secreta.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Non desexa un contrainal - o que unha *mala* idea!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Seguro que quere facer esto? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "movendo a sinatura dunha chave seu sitio\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "sar deste men" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "s" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "gardar" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "gardar e sar" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "axuda" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "amosar esta axuda" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "amosar fingerprint" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "listar" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "listar chave e IDs de usuario" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "selecciona-lo ID de usuario N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "chave" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "selecciona-la chave secundaria N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "verificar" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "listar sinaturas" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "v" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "asina-la chave" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "f" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "asina-la chave localmente" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "asina-la chave de xeito non revocable" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "asina-la chave localmente e de xeito non revocable" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "depurar" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "engadir un ID de usuario" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "engadir unha identificacin fotogrfica" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "borrar un ID de usuario" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "engadir unha chave secundaria" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "borrar unha chave secundaria" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "engadir unha chave secundaria" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "borrar sinaturas" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "cambia-la fecha de expiracin" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "marcar un ID de usuario coma primario" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "cambiar entre o listado de chaves pblicas e secretas" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "c" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "lista-las preferencias (expertos)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "lista-las preferencias (moitos datos)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "estabrece-la lista de preferencias" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "preferencias actualizadas" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "cambia-lo contrasinal" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "cambia-la confianza sobre o dono" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revocar sinaturas" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revocar unha chave secundaria" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "deshabilitar unha chave" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "habilitar unha chave" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "amosa-la identificacin fotogrfica" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "non se pode facer iso no modo por lotes\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "erro ao le-lo bloque de chave secreta `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "A chave secreta est disponible.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Comando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Cmpre a chave secreta para facer isto.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Por favor, empregue o comando \"toggle\" antes.\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "A chave est revocada." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Seguro de que quere asinar tdolos IDs de usuario? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Pista: seleccione os IDs de usuario que desexa asinar\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Non se admite este comando no modo %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Debe seleccionar alomenos un ID de usuario.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Non pode borra-lo ltimo ID de usuario!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Seguro de que quere borrar tdolos IDs de usuario seleccionados? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Seguro de que quere borrar este ID de usuario? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Debe seleccionar alomenos unha chave.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Seguro de que quere borra-las chaves seleccionadas? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Seguro de que quere borrar esta chave? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Realmente quere revoca-las chaves seleccionadas? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Realmente quere revocar esta chave? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Seguro que quere actualiza-las preferencias dos IDs de usuario " -"seleccionados? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Realmente desexa actualiza-las preferencias? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Garda-los cambios? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Sar sin gardar? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "a actualizacin fallou: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "o segredo da actualizacin fallou: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "A chave non cambiou, polo que non fai falla actualizar.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Comando incorrecto (tente \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Esta chave pode estar revocada por %s chave %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (sensible)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX creada: %s caduca: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " confianza: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Esta chave est desactivada" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! revocouse a subchave: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- atopouse unha revocacin falsa\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problema ao comproba-la revocacin: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Tea en conta que a validez da chave amosada non necesariamente\n" -"correcta ata que reinicie o programa.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"AVISO: Esta unha chave de estilo PGP2. Se engade unha identificacin\n" -" fotogrfica algunhas versins de PGP han rexeitar esta chave.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Est seguro de que quere engadila? (s/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" -"Non pode engadir unha identificacin fotogrfica a unha chave de estilo " -"PGP2.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Borrar esta sinatura correcta? (y/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Borrar esta sinatura incorrecta? (y/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Borrar esta sinatura descoecida? (y/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Realmente quere borrar esta auto-sinatura? (y/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Borrada %d sinatura.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Borradas %d sinaturas.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Non se borrou nada.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Introduza o tamao da chave" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Por favor, quite as seleccins das chaves secretas.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Por favor, seleccione como mximo unha chave secundaria.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Cambiando a data de expiracin para a chave secundaria.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Cambiando a data de expiracin da chave primaria.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Non pode cambia-la data de expiracin dunha chave v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Non hai unha sinatura correspondiente no chaveiro secreto\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Escolla exactamente un ID de usuario.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "" -"chave %08lX: auto-sinatura non vlida no identificadr de usuario \"%s\"\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Non hai ID de usuario con ndice %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Non hai chave secundaria con ndice %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "ID de usuario: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"asinado coa sa chave %08lX no %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"asinado localmente coa sa chave %08lX no %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Esta sinatura caducou o %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Est seguro de que quere revocala? (s/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Crear un certificado de revocacin para esta sinatura? (s/N) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Firmou estes IDs de usuario: \n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " asinada por %08lX no %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revocada por %08lX no %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Est a punto de revocar estas sinaturas:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " asinada por %08lX no %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (non exportable)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Realmente desexa crea-los certificados de revocacin? (s/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "non hai chave secreta\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Amosando a id. fotogrfica %s de tamao %ld da chave 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Normativa de sinaturas: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Normativa de sinaturas: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "AVISO: atopronse datos de notacin non vlidos\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notacin de sinaturas: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Notacin de sinaturas: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "non lexible por humanos" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Chaveiro" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [caduca: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "ve-la lista de chaves e pegadas dactilares" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Pegada dactilar =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Pegada dactilar =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Pegada dactilar =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Pegada dactilar =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algoritmo de hash non vlido `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "datos cifrados con %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "cifrado cun algoritmo descoecido %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "a chave pblica %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "datos cifrados coa chave pblica: DEK correcto\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "cifrado cunha chave de %u bits, %s, ID %08lX, creado o %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "cifrado cunha chave %s, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "fallou o descifrado de chave pblica: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "supoendo datos cifrados con %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "A cifra IDEA non est dispoible, tntase empregar %s no seu canto\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "descifrado correcto\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "AVISO: a mensaxe cifrada foi manipulada!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "o descifrado fallou: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTA: o remitente pediu \"confidencial\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nome do ficheiro orixinal='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "revocacin independente - empregue \"gpg --import\" para aplicar\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notacin: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Normativa: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verificacin de sinatura suprimida\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "non se poden manexar estas sinaturas mltiples\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Asinada o %.*s usando %s coa chave de ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "Sinatura INCORRECTA de\"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Sinatura caducada de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Sinatura correcta de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[incerto]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Non foi posible verifica-la sinatura: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "non unha sinatura separada\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "sinatura independiente de clase 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "Sinatura vello estilo (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "paquete raz incorrecto detectado en proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "non posible deshabilita-los volcados de 'core': %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Os algoritmos experimentais non deberan ser usados!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"este algoritmo de cifrado est obsoleto; por favor, empregue un mis " -"estndar!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "o plugin de cifra IDEA non est presente\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"mire en http://www.gnupg.org/why-not-idea.html para obter mis informacin\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "AVISO: %s unha opcin a extinguir.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "AVISO: %s unha opcin a extinguir.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "empregue \"--keyserver-options %s\" no seu canto\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "non posible manexa-lo algoritmo de chave pblica %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "un subpaquete de tipo %d ten o bit crtico posto\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent non est dispoible nesta sesin\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "non se pode estabrece-lo pid do cliente para o axente\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "non se pode obte-lo FD de lectura do servidor para o axente\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "non se pode obte-lo FD de escritura do servidor para o axente\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "variable de ambiente GPG_AGENT_INFO mal formada\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "a versin %d do protocolo de gpg-agent non est soportada\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "non se puido conectar a `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problema de comunicacin con gpg-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problema co axente - desactivando o emprego do axente\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (ID principal da chave %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Precisa un contrasinal para desbloquea-la chave secreta do usuario:\n" -"\"%.*s\"\n" -"Chave de %u bits, %s, ID %08lX, creada o %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Introduza o contrasinal\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Repita o contrasinal\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "contrasinal demasiado longo\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "resposta do axente non vlida\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "cancelado polo usuario\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problema co axente: o axente voltou coa resposta 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Necesita un contrasinal para desbloquea-la chave secreta para\n" -"o usuario \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bits, chave %s, ID %08lX, creada %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "non se pode consulta-lo contrasinal en modo de proceso por lotes\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Introduza o contrasinal: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Repita o contrasinal: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "os datos non foron gardados; use a opcin \"--output\" para gardalos\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "erro ao crear `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Sinatura non adxunta.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Por favor, introduza o nome do ficheiro de datos: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lendo de stdin ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "non hai datos asinados\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "non foi posible abri-los datos asinados `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinatario annimo; tentando a chave secreta %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "vale, ns somo-lo destinatario annimo.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "a codificacin vella do DEK non est soportada\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "o algoritmo de cifrado %d%s descoecido ou est desactivado\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "NOTA: o algoritmo de cifrado %d non foi atopado nas preferencias\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTA: a chave secreta %08lX caducou o %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "chave %08lX: esta chave est revocada!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "solicitando a chave %08lX do servidor de chaves HKP %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "non se pode obte-la chave do servidor de chaves: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "erro ao enviar a `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "xito ao enviar a `%s' (estado=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "fallo ao enviar a `%s': estado=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "buscando \"%s\" no servidor HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "non se pode buscar no servidor de chaves: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "hai partes da chave secreta non dispoibles\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "o algoritmo de proteccin %d%s non est soportado\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Contrasinal non vlido; por favor, tnteo de novo" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"AVISO: Detectouse unha chave feble - por favor, cambie o contrasinal outra " -"vez.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"xerando o checksum de 16-bits a extinguir para a proteccin da chave " -"secreta\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"esta unha chave ElGamal xerada por PGP que non segura para sinaturas!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "a chave pblica %lu segundo mis nova c sinatura\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "a chave pblica %lu segundos mis nova c sinatura\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"creouse a chave %lu segundo no futuro (salto no tempo ou problemas co " -"reloxo)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"creouse a chave %lu segundos no futuro (salto no tempo ou problemas co " -"reloxo)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTA: a chave de sinatura %08lX caducou o %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"asumindo unha sinatura incorrecta debido a un bit crtico descoecido\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "AVISO: non se pode expandir-%% o url de normativa (grande de mis).\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "AVISO: non se pode expandir-%% o url de normativa (grande de mis).\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "fallou a comprobacin da sinatura creada: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "Sinatura %s de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "AVISO: `%s' un ficheiro baleiro\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "s pode asinar con chaves estilo PGP 2.x no modo --pgp2\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "non foi posible crear %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: o algoritmo de cifrado %d non foi atopado nas preferencias\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "asinando:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "s pode asinar en claro con chaves estilo PGP 2.x no modo --pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "hase empregar cifrado %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "non posible manexar lias de texto maiores que %d caracteres\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "a lia de entrada contn mis de %d caracteres\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "rexistro da base de datos de confianza %lu: lseek fallou: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "" -"rexistro da base de datos de confianza %lu: fallou a escritura (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transaccin da base de datos de confianza demasiado grande\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: non posible acceder: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: o directorio non existe!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: non se pode crea-lo bloqueo\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: non se pode bloquear\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: non se pode crear: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: non se puido crea-lo rexistro de versin: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: creouse unha base de datos de confianza incorrecta\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: creouse a base de datos de confianza\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: base de datos de confianza non vlida\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: fallo ao crear unha tboa hash: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: erro ao actualiza-lo rexistro de versin: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: erro ao le-lo rexistro de versin: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: erro ao escribi-lo rexistro de versin: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "base de datos de confianza: lseek fallou: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "base de datos de confianza: fallou a lectura (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: non un ficheiro de base de datos de confianza\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: rexistro de versin con nmero de rexistro %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: versin do ficheiro incorrecta %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: erro ao ler un rexistro libre: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: erro ao escribi-lo rexistro de directorios: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: non se puido pr a cero un rexistro: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: non se puido engadir un rexistro: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"a base de datos de confianza est corrompida; execute \"gpg --fix-trustdb" -"\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' non un ID longo de chave vlido\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "chave %08lX: aceptada como chave de confianza\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "a chave %08lX aparece mis dunha vez na base de datos de confianza\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"chave %08lX: non hai unha chave pblica para a chave de confianza - omitida\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "rexistro de confianza %lu, tipo da peticin %d: fallou a lectura: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "o rexistro de confianza %lu non do tipo %d solicitado\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "rexistro de confianza %lu, tipo %d: fallou a escritura: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "base de datos de confianza: fallou a sincronizacin: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "non se precisa comproba-la base de datos de confianza\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "hase comproba-la base de datos de confianza o %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "comprobando a base de datos de confianza\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "non se atopou a chave pblica %08lX: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "non se atopou a chave pblica da clave de confianza absoluta %08lX\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"comprobando con profundidade %d asinadas=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%" -"d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"non se puido verifica-la sinatura.\n" -"Por favor, lembre que o ficheiro de sinatura (.sig ou .asc) debera\n" -"se-lo primeiro ficheiro que se indique na lia de comandos.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "" -"a lia de entrada %u longa de mis ou fltalle a marca de fin de lia\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"a chave non est marcada coma insegura - non se pode empregar co xerador de " -"nmeros aleatorios falso\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "omtese `%s': duplicada\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "omtese `%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "omtese: a chave secreta xa est presente\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"ignorouse `%s': esta unha chave ElGamal xerada por PGP que non segura " -"para sinaturas!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "O ficheiro `%s' xa existe. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Sobrescribir? (s/N) " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: sufixo descoecido\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Introduza o novo nome de ficheiro" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "escribindo na sada estndar\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "suponse que hai datos asinados en `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: creouse un novo ficheiro de opcins\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: non foi posible crear un directorio: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: directorio creado\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "AVISO: cifrouse a mensaxe cunha chave feble no cifrado simtrico.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problema ao manexa-lo paquete cifrado\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "creouse unha chave feble - volvendo a tentalo\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"non se pode evitar unha chave feble para o cifrado simtrico; tentouse %d " -"veces\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA require o emprego dun algoritmo hash de 160 bits\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "" -"iso non se pode facer no modo de procesamento por lotes sen \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Borrar esta chave do chaveiro? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Esta unha chave secreta! - est seguro de que quere borrala? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "fallou o borrado do bloque de chaves: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "borrouse a informacin de confianza\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "hai unha chave secreta para a chave pblica \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "empregue a opcin \"--delete-secret-keys\" para borrala primeiro.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"A asignacin dun valor aqu cousa sa; este valor nunca se ha exportar\n" -"a ningn terceiro. Precsase para implementa-la rede de confianza; non ten\n" -"nada que ver coa rede de certificados." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Para constru-la Rede-de-Confianza, GnuPG precisa saber que chaves teen\n" -"confianza absoluta - esas adoitan se-las chaves das que ten acceso chave\n" -"secreta. Responda \"si\" para lle dar confianza total a esta chave\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Se desexa empregar esta chave revocada, conteste \"si\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "Se desexa empregar esta clave na que non se confa, conteste \"si\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Introduza o ID de usuario da persoa que lle quere manda-la mensaxe." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Seleccione o algoritmo a usar.\n" -"\n" -"DSA (tamn chamado DSS) un algoritmo de sinatura dixital, que s se pode\n" -"empregar para asinar. o algoritmo aconsellado porque moito mis rpido\n" -"verificar unha sinatura DSA que unha sinatura ElGamal.\n" -"\n" -"ElGamal un algoritmo que se pode empregar para asinar e cifrar. OpenPGP\n" -"distingue entre das variantes do algoritmo: un que s cifra e outro que\n" -"asina e cifra; realmente o mesmo, pero hai que escoller algns parmetros\n" -"dun xeito especial para crear unha clave que sexa segura para asinar: este\n" -"programa faino, pero outras implementacins de OpenPGP non teen por que\n" -"entende-la variante de asinado+cifrado.\n" -"\n" -"A primeira clave (a primaria) debe ser sempre unha clave capaz de asinar;\n" -"este o motivo polo que a clave ElGamal que s cifra non est dispoible\n" -"neste men." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Anda que estas chaves estn definidas no RFC2440, non se aconsellan\n" -"porque non estn soportadas por tdolos programas, e as sinaturas\n" -"creadas con elas son moi grandes e lentas de comprobar." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Introduza o tamao da chave" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Conteste \"si\" ou \"non\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Introduza o valor requerido tal como se amosa no indicativo.\n" -" posible introducir unha data ISO (AAA-MM-DD) pero non ha obter unha\n" -"boa resposta de erro - no canto diso, o sistema ha tratar de interpreta-lo\n" -"valor proporcionado coma se fora un intervalo." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Introduza o nome do propietario da chave" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "por favor, introduza un enderezo de e-mail (opcional pero recomendado)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Por favor, introduza un comentario (opcional)" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N para cambia-lo nome.\n" -"C para cambia-lo comentario.\n" -"E para cambia-lo enderezo de e-mail.\n" -"O para continuar coa xeracin da chave.\n" -"S para sar da xeracin da chave." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Conteste \"si\" (ou s \"s\") se correcto xerar esta subchave." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Cando asina un ID de usuario dunha chave, debera comprobar antes\n" -"que a chave pertence persoa que aparece no identificador. til para os\n" -"demais saber con canto tino comprobou isto.\n" -"\n" -"\"0\" significa que non di nada do coidado co que comprobou a chave.\n" -"\n" -"\"1\" significa que cre que a chave pertence persoa que o afirma, pero " -"non\n" -" puido ou non quixo verifica-la chave. til para verificacins de\n" -" \"personaxes\", nas que asina a chave dun usuario pseudnimo.\n" -"\n" -"\"2\" significa que fixo unha comprobacin informal da chave. Por exemplo,\n" -" pode significar que comprobou a pegada dixital da chave e comprobou\n" -" a identidade do usuario na chave contra unha identificacin " -"fotogrfica.\n" -"\n" -"\"3\" significa que fixo unha comprobacin extensiva da chave. Por exemplo,\n" -" pode significar que comprobou a pegada dixital da chave co propietario\n" -" da chave en persoa, e que comprobou, cun documento difcil de " -"falsificar\n" -" cunha identificacin fotogrfica (coma o carnet de identidade ou\n" -" pasaporte) que o nome do propietario da chave coincide co do " -"identificador\n" -" de usuario da chave, e que comprobou (por intercambio de correo\n" -" electrnico) que o enderezo de e-mail da chave pertence ao propietario\n" -" da chave.\n" -"\n" -"Tea en conta que os exemplos de enriba para os niveis 2 e 3 son *s*\n" -"exemplos. final, depende de vostede decidir que significan \"informal\" e\n" -"\"extensivo\" ao asinar outras chaves.\n" -"\n" -"Se non sabe cal a resposta correcta, resposte \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Conteste \"si\" se quere asinar TDOLOS IDs de usuario" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Conteste \"si\" se realmente desexa borrar este ID de usuario.\n" -"Tamn se han perder tdolos certificados!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Conteste \"si\" se correcto borrar esta subchave" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Esta unha sinatura vlida na chave; normalmente non ha borrar esta\n" -"sinatura porque pode ser importante para estabrecer unha conexin de\n" -"confianza na chave ou noutra chave certificada por esta chave." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Non se pode verificar esta sinatura porque non pose a chave\n" -"correspondente. Debera retrasa-lo borrado ata que saiba que chave\n" -"se empregou porque esta chave de sinatura podera estabrecer unha\n" -"conexin de confianza mediante outra chave xa certificada." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "A sinatura non correcta. Ten sentido borrala do chaveiro." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Esta unha sinatura que liga o ID de usuario chave. Normalmente\n" -"non unha boa idea borrar unha sinatura como esta. De feito,\n" -"GnuPG pode non ser capaz de usar mis esta chave. As que faga isto\n" -"s se esta auto-sinatura non correcta por algun motivo e hai\n" -"unha segunda sa disposicin." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Cambia-las preferencias de tdolos IDs de usuario (ou s dos seleccionados)\n" -" lista actual de preferencias. A marca de tempo de tdalas auto-sinaturas\n" -"afectadas ha avanzar un segundo.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Por favor, introduza o contrasinal; esta unha frase secreta \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Por favor, repita o ltimo contrasinal, para estar seguro do que tecleou." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Introduza o nome do ficheiro ao que corresponde a sinatura" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Conteste \"si\" se correcto sobrescribi-lo ficheiro" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Por favor, introduza un novo nome de ficheiro. Se s preme ENTER, hase\n" -"emprega-lo ficheiro por defecto (que se amosa entre corchetes)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Debera especificar un motivo para o certificado. Dependendo do contexto\n" -"pode escoller desta lista:\n" -" \"Descobreuse a chave\"\n" -" Emprgueo se ten motivos para crer que algunha persoa non autorizada\n" -" obtivo acceso sa chave secreta.\n" -" \"A chave obsoleta\"\n" -" Emprgueo se cambiou esta chave cunha mis recente.\n" -" \"Xa non se emprega a chave\"\n" -" Emprgueo se retirou esta chave.\n" -" \"O ID de usuario xa non vlido\"\n" -" Emprgueo para indicar que o ID de usuario xa non se debera empregar;\n" -" adoita empregarse para marcar un enderezo de correo non vlido.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Se quere, pode introducir un texto que describa por que emite este\n" -"certificado de revocacin. Por favor, mantea este texto breve.\n" -"Unha lia en branco remata o texto.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Non hai axuda dispoible" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Non hai axuda dispoible para `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "erro ao crea-lo chaveiro `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "chaveiro `%s' creado\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "fallo ao reconstru-la cach de chaveiros: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "AVISO: existen dous ficheiros con informacin confidencial.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s o que non cambiou\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s o novo\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Por favor, amae este posible fallo de seguridade\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "comprobando o chaveiro `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu chaves comprobadas ata o momento (%lu sinaturas)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu chaves comprobadas (%lu sinaturas)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: chaveiro creado\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "ten que iniciar GnuPG outra vez para que lea o novo ficheiro de opcins\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "o cambio de permisos de `%s' fallou: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOME=VALOR|usar estes datos de notacin" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "o primeiro carcter dun nome de notacin debe ser unha letra ou guin " -#~ "baixo\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "os puntos dun nome de notacin deben estar rodeados por outros " -#~ "caracteres\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "AVISO: Esta chave xa ten unha identificacin fotogrfica.\n" -#~ " Se engade outra pode confundir a algunhas versins de PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "S pode ter unha identificacin fotogrfica nunha chave.\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Pegada dactilar:" - -#~ msgid " Fingerprint:" -#~ msgstr " Pegada dactilar:" - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "pedronse demasiados bits aleatorios; o lmite %d\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NOMES]|verifica-la base de datos de confianza" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key id-de-usuario" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key id de usuario" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-key-and-public-key id-de-usuario" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Para obter mis informacin vexa http://www.gnupg.org" - -#~ msgid "sSmMqQ" -#~ msgstr "iImMsS" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Non se puido atopar unha ruta de confianza vlida ata a chave. Hase ver " -#~ "se\n" -#~ "se pode asignar algn valor de confianza non asignado.\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "Non se atopou unha ruta que conduza a unha das nosas chaves.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Non se atoparon certificados con confianza non definida.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Non se cambiou ningn valor de confianza.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "" -#~ "%08lX: non hai informacin para calcular unha probabilidade de confianza\n" - -#~ msgid "Enter the user ID: " -#~ msgstr "Introduza o ID de usuario: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "omitida: a chave pblica xa est estabrecida con --encrypt-to\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: erro ao verifica-la chave: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "Seguro que quere crear unha chave para asinar e cifrar? " - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Est seguro de precisar un tamao de chave tan grande? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: non se atopou o usuario: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "problema de lectura do certificado: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "demasiadas entradas na cach de chaves descoecidas - desactivada\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "" -#~ "non se importou a chave secreta %08lX (empregue %s para permitilo)\n" - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "chave %08lX: a nosa copia non ten auto-sinatura\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: usuario non atopado\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "" -#~ "a actualizacin da base de datos de confianza fallou:\n" -#~ "%s\n" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "" -#~ "non hai un servidor de chaves coecido (empregue a opcin --keyserver)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: non un ID de chave vlido\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "asumindo un MDC incorrecto debido a un bit crtico\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "erro ao le-lo rexistro de directorio para o LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "" -#~ "lid %lu: esperbase un rexistro de directorio, obtvose un tipo %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "non hai unha chave primaria para o LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "erro ao le-la chave primaria para o LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record fallou: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "chave %08lX: a consulta do rexistro fallou\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "chave %08lX: xa est na tabla de chaves de confianza\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "NOTA: a chave secreta %08lX NON est protexida.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "chave %08lX: as chaves secreta e pblica non coinciden\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "erro ao enumera-las chaves secretas: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "chave %08lX.%lu: Ligadura de subchave correcta\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "chave %08lX.%lu: Ligadura de subchave non vlida: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "chave %08lX.%lu: Revocacin de chave vlida\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "chave %08lX.%lu: Revocacin de chave non vlida: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Auto-sinatura correcta" - -#~ msgid "Invalid self-signature" -#~ msgstr "Auto-sinatura non vlida" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Omtese unha revocacin de ID de usuario vlida debido a unha auto-" -#~ "sinatura mis recente" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Revocacin de ID de usuario vlida" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Revocacin de ID de usuario non vlida" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Revocacin de certificado vlida" - -#~ msgid "Good certificate" -#~ msgstr "Certificado correcto" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Revocacin de certificado non vlida" - -#~ msgid "Invalid certificate" -#~ msgstr "Certificado non vlido" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "o rexistro de sinatura %lu[%d] apunta a un rexistro incorrecto.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "certificado duplicado - borrado" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir fallou: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: a insercin fallou: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: a insercin fallou: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: inserido\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "erro lendo o rexistro de directorio: %s\n" - -#~ msgid "\t%lu keys with errors\n" -#~ msgstr "\t%lu chaves con erros\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu chaves inseridas\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: rexistro de directorio sen chave - ignorado\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu debidos a novas chaves pblicas\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu chaves omitidas\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu chaves actualizadas\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Ooops, non hai chaves\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Ooops, non hai IDs de usuario\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "" -#~ "check_trust:\n" -#~ "a bsqueda de rexistro de directorio fallou: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "" -#~ "chave %08lX:\n" -#~ "a insercin na base de datos de confianza fallou: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "chave %08lX.%lu: inserida na base de datos de confianza\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "chave %08lX.%lu: creada no futuro (salto no tempo ou problema de reloxo)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "chave %08lX.%lu: caducou o %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "chave %08lX.%lu: a verificacin de confianza fallou: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "problema ao buscar '%s' na base de datos de confianza: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "o usuario '%s' non est na base de datos de confianza - inserindo\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "erro ao pr '%s' na base de datos de confianza: %s\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "" -#~ "AVISO: anda non se poden manexar rexistros de preferencias longos\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: non se pode crea-lo chaveiro: %s\n" - -#~ msgid "set debugging flags" -#~ msgstr "axusta-los valores de depuracin" - -#~ msgid "enable full debugging" -#~ msgstr "habilitar depuracin total" - -#~ msgid "do not write comment packets" -#~ msgstr "non escribir paquetes de comentario" - -#~ msgid "(default is 1)" -#~ msgstr "(por defecto 1)" - -#~ msgid "(default is 3)" -#~ msgstr "(por defecto 3)" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal nun paquete v3\n" - -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "A xeracin de chaves somentes pode ser usada no modo interactivo\n" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "A chave RSA non pode user usada nesta version\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Non hay unha chave para o ID de usuario\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Non hai un ID de usuario para a chave\n" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "non hai chave secreta disponible para desencriptar\n" - -#~ msgid "" -#~ "RSA keys are deprecated; please consider creating a new key and use this " -#~ "key in the future\n" -#~ msgstr "" -#~ "As chaves RSA estn obsoletas; por favor, considere a opcin de crear " -#~ "unha\n" -#~ "chave nova e usa-la no futuro.\n" diff --git a/po/id.po b/po/id.po deleted file mode 100644 index 407348c29..000000000 --- a/po/id.po +++ /dev/null @@ -1,4707 +0,0 @@ -# gnupg 1.0.7 (Indonesian) -# Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Tedi Heriyanto , 1999, 2000, 2001, 2002. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-07-24 21:11GMT+0700\n" -"Last-Translator: Tedi Heriyanto \n" -"Language-Team: Indonesian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 0.9.5\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Peringatan: menggunakan memori yang tidak aman!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" -"silakan lihat http://www.gnupg.org/faq.html untuk informasi lebih lanjut\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "operasi tidak mungkin tanpa menginisialisasi memori yang aman\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(anda mungkin menggunakan program yang salah untuk tugas ini)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ya" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "yY" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "tidak" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "tT" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "keluar" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "kK" - -#: util/errors.c:54 -msgid "general error" -msgstr "Kesalahan umum" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "tipe paket tidak dikenal" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "versi tidak dikenal" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algoritma pubkey tidak dikenal" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algoritma digest tidak dikenal" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "kunci publik yang buruk" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "kunci rahasia yang buruk" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "signature yang buruk" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "kesalahan checksum" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "passphrase yang buruk" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "kunci publik tidak ditemukan" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algoritma cipher tidak dikenal" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "tidak dapat membuka keyring" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "paket tidak valid" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armor tidak valid" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "tidak ada user id tsb" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "kunci rahasia tidak tersedia" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "digunakan kunci rahasia yang salah" - -#: util/errors.c:72 -msgid "not supported" -msgstr "tidak didukung" - -#: util/errors.c:73 -msgid "bad key" -msgstr "kunci yang buruk" - -#: util/errors.c:74 -msgid "file read error" -msgstr "kesalahan baca file" - -#: util/errors.c:75 -msgid "file write error" -msgstr "kesalahan tulis file" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritma kompresi tidak dikenal" - -#: util/errors.c:77 -msgid "file open error" -msgstr "kesalahan buka file" - -#: util/errors.c:78 -msgid "file create error" -msgstr "kesalahan buat file" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "passphrase tidak valid" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritma pubkey belum diimplementasikan" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritma cipher belum diimplementasikan" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "kelas signature tidak dikenal" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "kesalahan database trust" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI yang buruk" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "batasan sumber daya" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "keyring tidak valid" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "sertifikat yang buruk" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "user id yang tidak benar" - -#: util/errors.c:89 -msgid "file close error" -msgstr "kesalahan tutup file" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "kesalahan ganti nama file" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "kesalahan hapus file" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "data tidak terduga" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "konflik timestamp" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritma pubkey tidak dapat digunakan" - -#: util/errors.c:95 -msgid "file exists" -msgstr "file ada" - -#: util/errors.c:96 -msgid "weak key" -msgstr "kunci lemah" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argumen tidak valid" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI yang buruk" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI tidak didukung" - -#: util/errors.c:100 -msgid "network error" -msgstr "kesalahan jaringan" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "tidak dienkripsi" - -#: util/errors.c:103 -msgid "not processed" -msgstr "tidak diproses" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "kunci publik tidak dapat dipakai" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "kunci rahasia tidak dapat dipakai" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "kesalahan keyserver" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... kesalahan (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "anda menemukan kesalahan ...(%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "tidak dapat membuka `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "tidak dapat melakukan statistik `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "'%s' bukan file reguler - diabaikan\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "catatan: file random_seed kosong\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "peringatan: ukuran file random_seed tidak valid - tidak dipakai\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "tidak dapat membaca `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "catatan: file random_seed tidak diupdate\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "tidak dapat membuat %s: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "tidak dapat menulis `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "tidak dapat menutup `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "PERINGATAN: menggunakan random number generator yang tidak aman!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Random number generator yang digunakan tidak aman,\n" -"ia bukanlah RNG yang kuat!\n" -"\n" -"JANGAN MENGGUNAKAN DATA YANG DIHASILKAN PROGRAM INI!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Tidak tersedia cukup byte random. Silakan melakukan aktivitas lain agar\n" -"memungkinkan SO mengumpulkan lebih banyak entropi! (Perlu %d byte lagi)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Perintah:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[file]|buat signature" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[file]|buat signature teks" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "buat detached signature" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "enkripsi data" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[files]|enkripsi file" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "enkripsi hanya dengan symmetric cipher" - -#: g10/g10.c:315 -msgid "store only" -msgstr "hanya disimpan" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "dekripsi data (default)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[files]|dekripsi file" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verifikasi signature" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "tampilkan kunci" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "tampilkan kunci dan signature" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "periksa signature kunci" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "tampilkan kunci dan fingerprint" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "tampilkan kunci rahasia" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "buat sepasang kunci baru" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "hapus kunci dari keyring publik" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "hapus kunci dari keyring pribadi" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "tandai kunci" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "tandai kunci secara lokal" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "tandai kunci tidak dapat di-revoke" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "tandai kunci secara lokal dan tidak dapat di-revoke" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "tandai atau edit kunci" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "buat sertifikat revokasi" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "ekspor kunci" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "ekspor kunci ke key server" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "impor kunci dari key server" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "cari kunci di key server" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "update semua kunci dari keyserver" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "impor/gabung kunci" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "tampilkan hanya urutan paket" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "ekspor nilai ownertrust" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "impor nilai ownertrust" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "perbarui database trust" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "perbarui database trust secara otomatis" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "perbaiki database trust yang terkorupsi" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "De-Armor file atau stdin" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "En-Armor file atau stdin" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [file]|cetak digest pesan" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Pilihan:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "ciptakan output ascii" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NAMA|enkripsi untuk NAMA" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NAMA|gunakan NAMA sebagai penerima baku" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "gunakan kunci baku sebagai penerima baku" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "gunakan id-user ini untuk menandai/dekripsi" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|set tingkat kompresi N (0 tidak ada)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "gunakan mode teks kanonikal" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "gunakan sebagai file output" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "detil" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "lebih diam" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "jangan menggunakan terminal" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "paksa signature v3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "jangan paksa signature v3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "paksa signature kunci v4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "jangan paksa signature kunci v4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "selalu gunakan MDC untuk enkripsi" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "jangan gunakan MDC untuk enkripsi" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "jangan buat perubahan" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "gunakan gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "mode batch: tanpa tanya" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "asumsikan ya untuk seluruh pertanyaan" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "asumsikan tidak untuk seluruh pertanyaan" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "tambah keyring ini ke daftar keyring" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "tambah keyring rahasia ini ke daftar" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "tampilkan keyring tempat kunci yang dipilih berada" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NAMA|gunakan NAMA sebagai kunci rahasia baku" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|gunakan keyserver ini utk lihat kunci" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAMA|set charset terminal ke NAMA" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "baca pilihan dari file" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|tulis info status ke FD ini" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[file]|tulis status info ke file" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID|sangat percayai kunci ini" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FILE|muat modul ekstensi FILE" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emulasikan mode seperti dalam RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "set pilihan semua paket, cipher, digest ke perilaku OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "set pilihan semua paket, cipher, digest ke perilaku PGP 2.x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|gunakan passphrase mode N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NAMA|gunakan algoritma digest NAMA utk passphrase" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NAMA|gunakan algoritma cipher NAMA untuk passphrase" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAMA|gunakan algoritma cipher NAMA" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAMA|gunakan algoritma digest pesan NAMA" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|gunakan algoritma kompresi N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "buang field keyid paket terenkripsi" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Tampilkan Photo IDs" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Jangan tampilkan Photo IDs" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Set perintah baris untuk melihat Photo IDs" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Lihat man page untuk daftar lengkap semua perintah dan option)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Contoh:\n" -"\n" -" -se -r Bob [file] tandai dan enkripsi untuk user Bob\n" -" --clearsign [file] buat signature berbentuk teks\n" -" --detach-sign [file] buat signature detached\n" -" --list-keys [nama] tampilkan kunci\n" -" --fingerprint [nama] tampilkan fingerprint\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Silakan laporkan kesalahan ke .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Pemakaian: gpg [pilihan] [file] (-h untuk bantuan)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintaks: gpg [pilihan] [file]\n" -"tandai, cek, enkripsi atau dekripsi\n" -"operasi baku tergantung pada data input\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritma yang didukung:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "pemakaian: gpg [pilihan] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "perintah saling konflik\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Peringatan: kepemilikan tidak aman pada %s \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Peringatan: permisi tidak aman pada %s \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Peringatan: kepemilikan tidak aman pada %s \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Peringatan: permisi tidak aman pada %s \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "CATATAN: tidak ada file pilihan baku `%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "CATATAN: tidak ada file pilihan baku `%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "file pilihan `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "membaca pilihan dari `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s bukanlah set karakter yang valid\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "tidak dapat memparsing URI keyserver\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: versi file %d tidak valid\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armor tidak valid" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: versi file %d tidak valid\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "keyring tidak valid" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "PERINGATAN: program mungkin membuat file core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "PERINGATAN: %s menimpa %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "CATATAN: %s tidak untuk pemakaian normal!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s tidak dibolehkan dengan %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s tidak masuk akal dengan %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -"anda hanya dapat membuat signature detached atau clear saat dalam mode --" -"pgp2\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" -"anda tidak dapat menandai dan mengenkripsi pada saat bersamaan dalam mode --" -"pgp2\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" -"anda harus menggunakan file (dan bukan pipe) saat bekerja dengan opsi --" -"pgpg2\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "mengenkripsi pesan dalam mode --pgp2 membutuhkan cipher IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "pesan ini mungkin tidak dapat digunakan oleh PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "algoritma cipher yang dipilih tidak valid\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "algoritma digest yang dipilih tidak valid\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "algoritma digest yang dipilih tidak valid\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "algoritma kompresi harus di antara %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed harus lebih dari 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed harus lebih dari 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth harus di antara 1 hingga 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "CATATAN: mode S2K sederhana (0) tidak dianjurkan\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "mode S2K yang tidak valid; harus 0, 1 atau 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "default-check-level tidak valid; harus 0, 1, 2, atau 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "preferensi tidak valid\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "preferensi tidak valid\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "preferensi tidak valid\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "preferensi tidak valid\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "gagal inisialisasi TrustDB: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [namafile]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [namafile]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [namafile]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [namafile]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [namafile]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [namafile]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [namafile]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [namafile]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key id-user" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key id-user" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key user-id" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key user-id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key id-user [perintah]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "tidak dapat membuka %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [id-user] [keyring]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "gagal dearmoring: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "gagal enarmoring: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algoritma hash tidak valid `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[namafile]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Teruskan dan ketikkan pesan anda ....\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "tidak dapat membuka `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"nama notasi hanya terdiri dari huruf, digit, titik atau garis bawah dan " -"diakhiri dengan sebuah '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "nilai notasi tidak boleh menggunakan karakter kendali\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "URL sertifikasi kebijakan yang diberikan tidak valid\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "URL signature kebijakan yang diberikan tidak valid\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armor: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "header armor tidak valid: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "header armor: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "header clearsig tidak valid\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "signature teks bersarang\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "dash escaped line tidak valid: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armor tidak terduga:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "karakter radix64 tidak valid %02x dilewati\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "eof prematur (tanpa CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "eof prematur (dalam CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC tidak tepat\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "kesalahan CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "eof prematur (dalam Trailer)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "kesalahan dalam garis trailer\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "tidak ditemukan data OpenPGP yang valid.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armor tidak valid: baris melebihi %d karakter\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"karakter yang dapat dicetak dalam armor - mungkin telah digunakan MTA yang " -"mengandung bug\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Tidak ada alasan diberikan" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Kunci dilampaui" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Kunci ini telah dikompromikan" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Kunci tidak lagi digunakan" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "ID User tidak lagi valid" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Alasan pembatalan:" - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Komentar pembatalan:" - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Tidak ada nilai trust untuk:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Silakan putuskan seberapa jauh anda percaya user ini untuk\n" -"secara tepat memverifikasi kunci user lain (dengan melihat pada passpor,\n" -"memeriksa fingerprint dari berbagai sumber...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Tidak tahu\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d: Saya TIDAK percaya\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Saya cukup percaya\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Saya sangat percaya\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Saya sangat percaya sekali\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = beri saya informasi lebih banyak lagi\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = kembali ke menu utama\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = lewati kunci ini\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = berhenti\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Keputusan anda? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Anda ingin menset kunci ini menjadi sangat percaya sekali?" - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Sertifikat mengarahkan ke kunci terpercaya:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "kunci %08lX: kunci telah dibatalkan!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Tetap gunakan kunci ini? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "kunci %08lX: subkey telah dibatalkan!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: kunci telah berakhir\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Tidak ada indikasi bahwa kunci ini benar-benar milik pemiliknya\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Kita TIDAK percaya kunci ini\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Tidak pasti kunci ini milik pemiliknya\n" -"tapi tetap diterima\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Kunci ini mungkin milik pemiliknya\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Kunci ini milik kita\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Tidak pasti bahwa kunci milik pemiliknya.\n" -"Jika anda sangat tahu apa yang sedang anda lakukan, anda boleh menjawab\n" -"pertanyaan berikut dengan ya\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "PERINGATAN: Menggunakan kunci tidak dipercaya!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "PERINGATAN: Kunci ini telah dibatalkan oleh pemiliknya!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Hal ini dapat berarti bahwa signature adalah palsu.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "PERINGATAN: Subkey ini telah dibatalkan oleh pemiliknya!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Catatan: Kunci ini telah ditiadakan\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Catatan: Kunci ini telah berakhir!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "" -"PERINGATAN: Kunci ini tidak disertifikasi dengan sig yang terpercaya!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " Tidak ada indikasi signature milik pemilik.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "PERINGATAN: Kita tidak percaya kunci ini!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Signature mungkin palsu.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"PERINGATAN: Kunci tdk disertifikasi dg signature terpercaya yg cukup!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Tidak pasti signature milik pemilik.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: dilewati: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: dilewati: kunci publik telah ada\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Anda tidak menspesifikasikan ID user. (anda dapat gunakan \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Masukkan user ID. Akhiri dengan baris kosong: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Tidak ada ID user tersebut.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "dilewati: kunci publik telah diset sebagai penerima baku\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Kunci publik dimatikan.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "dilewati: kunci publik telah diset\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "penerima baku tidak dikenal `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: dilewati: kunci publik dimatikan\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "tidak ada alamat yang valid\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "preferensi %c%lu tidak valid\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "preferensi %c%lu ganda \n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "terlalu banyak preferensi `%c'\n" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "Karakter tidak valid dalam string\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "menulis self signature\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "menulis self signature\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "menulis key binding signature\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "keysize tidak valid; menggunakan %u bit\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "keysize dibulatkan hingga %u bit\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Silakan pilih kunci yang anda inginkan:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA dan ElGamal (baku)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (hanya menandai)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (hanya enkripsi)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (tandai dan enkripsi)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (hanya menandai)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (hanya enkripsi)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (tandai dan enkripsi)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Pilihan anda? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Penggunaan algoritma ini didepresiasi - tetap ciptakan?" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Pilihan tidak valid.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Akan dibuat satu pasang kunci baru %s.\n" -" keysize minimum adalah 768 bit\n" -" keysize default adalah 1024 bit\n" -" keysize tertinggi dianjurkan 2048 bit\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Keysize yang anda inginkan? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA hanya membolehkan keysize dari 512 hingga 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "" -"keysize terlalu kecil; 1024 adalah nilai terendah yang diijinkan untuk RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "keysize terlalu kecil; 768 adalah nilai terendah yang diijinkan.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "keysize terlalu besar; %d adalah nilai tertinggi yang diijinkan.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Keysize lebih besar dari 2048 tidak dianjurkan karena\n" -"komputasi akan sangat lama!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Apakah anda yakin memerlukan keysize ini? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Oke, tetapi ingat bahwa radiasi monitor dan keyboard anda juga sangat mudah " -"diserang!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Keysize yang diminta adalah %u bit\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "dibulatkan hingga %u bit\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Silakan spesifikasikan lama kunci tetap valid.\n" -" 0 = kunci tidak pernah berakhir\n" -" = kunci berakhir dalam n hari\n" -" w = kunci berakhir dalam n minggu\n" -" m = kunci berakhir dalam n bulan\n" -" y = kunci berakhir dalam n tahun\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Silakan spesifikasikan lama signature tetap valid.\n" -" 0 = signature tidak pernah berakhir\n" -" = signature berakhir dalam n hari\n" -" w = signature berakhir dalam n minggu\n" -" m = signature berakhir dalam n bulan\n" -" y = signature berakhir dalam n tahun\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Kunci valid untuk? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Signature valid untuk? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "nilai yang tidak valid\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s tidak pernah berakhir\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s berakhir pada %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Sistem anda tidak dapat menampilkan tanggal melebihi 2038.\n" -"Namun, ia dapat menanganinya secara benar hingga 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Benar (y/t)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Anda perlu sebuah User-ID untuk mengidentifikasi kunci anda; software " -"membuat \n" -"user-id dari Nama sebenarnya, Komentar dan Alamat email dalam bentuk:\n" -" \"Heinrich Heine (Der Dichter) \"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nama sebenarnya: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Karakter tidak valid dalam nama\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Nama tidak boleh dimulai dengan digit\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Nama harus berukuran minimum 5 karakter\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Alamat email: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Bukan alamat email yang valid\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Komentar: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Karakter tidak valid dalam komentar\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Anda menggunakan set karakter `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Anda memilih USER-ID ini:\n" -" \"%s\"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Jangan menaruh alamat email ke dalam nama sebenarnya atau komentar\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnKkEeOoQq" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Ganti (N)ama, (K)omentar, (E)mail atau (Q)uit? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Ganti (N)ama, (K)omentar, (E)mail atau (O)ke/(Q)uit? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Silakan perbaiki kesalahan ini dulu\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Anda perlu sebuah passphrase untuk melindungi kunci rahasia anda.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "passphrase tidak diulang dengan benar; coba lagi" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Anda tidak ingin sebuah passphrase - ini mungkin ide yang *buruk*!\n" -"Namun saya akan tetap lakukan. Anda dapat merubah passphrase anda setiap " -"saat,\n" -"menggunakan program ini dengan pilihan \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Kita perlu membuat banyak byte random. Adalah ide yang baik untuk melakukan\n" -"aksi lain (mengetik pada keyboard, menggerakkan mouse, memakai disk)\n" -"selama pembuatan prima; ini akan memberi random number generator kesempatan\n" -"yang baik untuk memperoleh entropi.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "Keypair DSA akan memiliki 1024 bit.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Pembuatan kunci dibatalkan.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "menulis kunci publik ke `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "menulis kunci rahasia ke `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "tidak ditemukan keyring publik yang dapat ditulisi: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "tidak ditemukan keyring rahasia yang dapat ditulisi: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "kesalahan menulis keyring publik `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "kesalahan menulis keyring rahasia `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "kunci publik dan rahasia dibuat dan ditandai.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "kunci ditandai sebagai sangat dipercaya.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Perhatikan bahwa kunci ini tidak dapat digunakan untuk enkripsi. Anda \n" -"mungkin ingin menggunakan perintah \"--edit-key\" untuk membuat kunci kedua " -"untuk tujuan ini.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Pembuatan kunci gagal: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"kunci telah diciptakan dalam %lu detik mendatang (masalah waktu atau jam)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"kunci telah diciptakan dalam %lu detik mendatang (masalah waktu atau jam)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "CATATAN: membuat subkey bagi kunci-kunci v3 tidak OpenPGP compliant\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Ingin diciptakan? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output tidak berfungsi untuk perintah ini\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: tidak dapat membuka: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "kesalahan penciptaan passphrase: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' sudah dikompresi\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: PERINGATAN: file kosong\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"anda hanya dapat mengenkripsi ke kunci RSA 2048 bit atau kurang dalam mode --" -"pgp2\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "Membaca dari `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"tidak dapat menggunakan cipher IDEA untuk semua kunci yang anda enkripsi.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "CATATAN: algoritma cipher %d tidak ditemukan dalam preferensi\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Perintah ini tidak dibolehkan saat dalam mode %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s dienkripsi untuk: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "kunci '%s' tidak ditemukan: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "gagal membaca keyblock: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "kunci %08lX: bukan kunci rfc2440 - dilewati\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "kunci %08lX: tidak diproteksi - dilewati\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "kunci %08lX: kunci gaya PGP 2.x - dilewati\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "PERINGATAN: tidak ada yang diekspor\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "terlalu banyak masukan dalam pk cache - ditiadakan\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[User id tidak ditemukan]" - -#: g10/getkey.c:1438 -#, fuzzy, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "kunci tidak valid %08lX dibuat valid oleh --always-trust\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "menggunakan kunci sekunder %08lX bukannya kunci primer %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "kunci %08lX: kunci rahasia tanpa kunci publik - dilewati\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "melewati blok tipe %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu kunci telah diproses\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "kesalahan membaca `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Jumlah yang telah diproses: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " lewati kunci baru: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " tanpa ID user: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " diimpor: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " tidak berubah: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " ID user baru: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " subkey baru: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " signature baru: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " pembatalan kunci baru: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " kunci rahasia dibaca: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " kunci rahasia diimpor: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " kunci rahasia tidak berubah: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " diimpor: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "kunci %08lX: tidak ada ID user\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "kunci %08lX: tidak ada subkey untuk key binding\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "kunci %08lX: menerima ID user yang tidak self-signed " - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "kunci %08lX: tidak ada ID user yang valid\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "mungkin disebabkan oleh self-signature yang tidak ada\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "kunci %08lX: kunci publik tidak ditemukan: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "kunci %08lX: kunci baru - dilewati\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "tidak ditemukan keyring yang dapat ditulisi: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "menulis ke `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "kesalahan menulis keyring `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "kunci %08lX: kunci publik diimpor\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "kunci %08lX: tidak cocok dengan duplikat kami\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "kunci %08lX: tidak dapat menemukan keyblock orisinal: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "kunci %08lX: tidak dapat membaca keyblok orisinal: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "kunci %08lX: 1 user ID baru\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "kunci %08lX: %d user ID baru\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "kunci %08lX: 1 signature baru\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "kunci %08lX: %d signature baru\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "kunci %08lX: 1 subkey baru\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "kunci %08lX: %d subkey baru\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "kunci %08lX: tidak berubah\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "tidak ada keyring rahasia baku: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "kunci %08lX: kunci rahasia diimpor\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "kunci %08lX: sudah ada di keyring rahasia\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "kunci %08lX: kunci rahasia tidak ditemukan: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"kunci %08lX: tdk ada kunci publik-tdk dpt mengaplikasikan sertifikat " -"pembatalan\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "kunci %08lX: sertifikat pembatalan tidak valid: %s - ditolak\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "kunci %08lX: sertifikat pembatalan diimpor\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "kunci %08lX: tidak ada ID user untuk signature\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "kunci %08lX: algoritma publik key tidak didukung\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "kunci %08lX: self-signature tidak valid\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "kunci %08lX: tidak ada subkey untuk key binding\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "kunci %08lX: algoritma publik key tidak didukung\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "kunci %08lX: subkey binding tidak valid\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "kunci %08lX: subkey binding tidak valid\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "kunci %08lX: tidak ada subkey untuk key binding\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "kunci %08lX: subkey binding tidak valid\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "kunci %08lX: subkey binding tidak valid\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "kunci %08lX: melewati ID user " - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "kunci %08lX: melewati subkey\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "kunci %08lX: signature tidak dapat diekpor (kelas %02x) - dilewati\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "kunci %08lX: sertifikat pembatalan di tempat yang salah - dilewati\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "kunci %08lX: sertifikat pembatalan tidak valid: %s - dilewati\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "kunci %08lX: sertifikat pembatalan di tempat yang salah - dilewati\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "kunci %08lX: terdeteksi ID user duplikat - digabungkan\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "kunci %08lX: penambahan sertifikat pembatalan\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "kunci %08lX: signature kunci langsung ditambahkan\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[pembatalan]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[self-signature]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 signature yang buruk\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d signature yang buruk\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 signature tidak diperiksa karena tidak ada kunci\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d signature tidak diperiksa karena tidak ada kunci\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 signature tidak diperiksa karena kesalahan\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d signature tidak diperiksa karena ada kesalahan\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "terdeteksi 1 ID user tanpa self-signature yang valid\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "terdeteksi ID %d user tanpa self-signature yang valid\n" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "ID User \"%s\" dibatalkan.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Apakah anda yakin masih ingin menandainya?\n" - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "PERINGATAN: `%s' adalah file kosong\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Signature anda saat ini pada \"%s\"\n" -"adalah signature.lokal \n" -"\n" -"Apakah anda ingin menjadikannya signature yang full exportable?\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" -"Signature anda saat ini pada \"%s\"\n" -"adalah signature.lokal \n" -"\n" -"Apakah anda ingin menjadikannya signature yang full exportable?\n" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, fuzzy, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Signature anda saat ini pada \"%s\"\n" -"adalah signature.lokal \n" -"\n" -"Apakah anda ingin menjadikannya signature yang full exportable?\n" - -#: g10/keyedit.c:426 -#, fuzzy -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" -"Signature anda saat ini pada \"%s\"\n" -"adalah signature.lokal \n" -"\n" -"Apakah anda ingin menjadikannya signature yang full exportable?\n" - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" Sudah ditandai %s dengan kunci %08lX\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" Sudah ditandai %s dengan kunci %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Tidak ada yang ditandai dengan kunci %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Kunci ini telah berakhir!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Kunci ini akan kadaluarsa pada %s \n" - -#: g10/keyedit.c:502 -#, fuzzy -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Anda ingin signature anda kadaluarsa pada waktu yang sama? (y/n) " - -#: g10/keyedit.c:535 -#, fuzzy -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"anda hanya dapat menandai kunci bergaya PGP 2.x saat dalam mode --pgp2\n" - -#: g10/keyedit.c:537 -#, fuzzy -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "pesan ini mungkin tidak dapat digunakan oleh PGP 2.x\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Sudah seberapa teliti anda memverifikasi kunci yang akan anda gunakan untuk " -"menandai benar benar milik\n" -"orang tersebut? Jika anda tidak tahu jawabannya. masukkan \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Saya tidak akan menjawab.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Saya belum memeriksanya.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Saya telah melakukan pemeriksaan biasa.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Saya telah melakukan pemeriksaan hati-hati.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Apakah anda yakin untuk menandai kunci ini \n" -"dengan kunci anda: " - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "mungkin disebabkan oleh self-signature yang tidak ada\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"Signature akan ditandai sebagai tidak dapat diekspor.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"Signature akan ditandai sebagai tidak dapat dibatalkan.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"Signature akan ditandai sebagai tidak dapat diekspor.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"Signature akan ditandai sebagai tidak dapat dibatalkan.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Saya belum memeriksa kunci ini sama sekali.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Saya telah memeriksa kunci ini.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Saya telah memeriksa kunci ini dengan sangat hati-hati.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Ditandai? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "gagal menandai: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Kunci ini tidak diproteksi.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Bagian rahasia kunci primer tidak tersedia.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Kunci diproteksi.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Tidak dapat mengedit kunci ini: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Masukkan passphrase baru untuk kunci rahasia ini.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Anda tidak ingin passphrase - bukan ide yang baik!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Apakah anda ingin melakukan hal ini? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "memindahkan signature kunci ke tempat yang tepat\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "berhenti dari menu ini" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "simpan" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "simpan dan berhenti" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "bantuan" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "tampilkan bantuan" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "tampilkan fingerprint" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "tampilkan" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "tampilkan kunci dan ID user" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "pilih ID user N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "kunci" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "pilih kunci sekunder N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "periksa" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "tampilkan signature" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "tandai" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "tandai kunci" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "tandai kunci secara lokal" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "tandai kunci sebagai tidak dapat dibatalkan" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "tandai kunci secara lokal dan tidak dapat dibatalkan" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "tambah sebuah ID user" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "tambah sebuah photo ID" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "hapus ID user" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "tambah kunci sekunder" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "hapus kunci sekunder" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "tambah kunci sekunder" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "hapus signature" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "ubah tanggal kadaluarsa" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primer" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "tandai ID user sebagai primer" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "ubah tampilan kunci rahasia dan publik" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "tampilkan preferensi (ahli)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "tampilkan preferensi (verbose)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "set daftar preferensi" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "perbarui preferensi" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "ubah passphrase" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "ubah ownertrust" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "batalkan signature" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "batalkan kunci sekunder" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "tiadakan kunci" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "aktifkan kunci" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "tampilkan photo ID" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "tidak dapat melakukan hal itu dalam mode batch\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "kesalahan membaca keyblock rahasia `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Kunci rahasia tersedia.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Perintah> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Perlu kunci rahasia untuk melakukan hal ini.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Silakan gunakan dulu perintah \"toogle\".\n" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "Kunci dibatalkan.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Tandai ID seluruh user? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Petunjuk: Pilih ID user untuk ditandai\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Perintah ini tidak dibolehkan saat dalam mode %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Anda harus memilih minimum satu ID user.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Anda tidak dapat menghapus ID user terakhir!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Hapus seluruh ID user terpilih? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Hapus ID user ini? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Anda harus memilih minimum satu kunci.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Anda ingin menghapus kunci terpilih ini? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Anda ingin menghapus kunci ini? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Anda ingin membatalkan kunci terpilih ini? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Anda ingin membatalkan kunci ini? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "Perbarui preferensi untuk user ID terpilih?" - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Update preferensi?" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Simpan perubahan? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Berhenti tanpa menyimpan? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "gagal memperbarui: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "gagal perbarui rahasia: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Kunci tidak berubah sehingga tidak perlu pembaharuan.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Perintah tidak valid (coba \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Kunci ini mungkin dibatalkan oleh %s kunci %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (sensitive)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX diciptakan: %s berakhir: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " trust: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Kunci ini telah ditiadakan" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! subkey telah dibatalkan: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev - ditemukan pembatalan palsu\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? masalah memeriksa pembatalan: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"PERINGATAN: Ini adalah kunci bergaya PGP2. Menambahkan sebuah photo ID " -"dapat menyebabkan beberapa versi\n" -" PGP menolak kunci ini.\n" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Anda tetap ingin menambahkannya? (y/n) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Anda tidak boleh menambahkan sebuah photo ID ke kunci bergaya PGP2 \n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Hapus signature baik ini? (y/T/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Hapus signature tidak valid ini? (y/T/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Hapus signature tidak dikenal ini? (y/T/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Yakin ingin menghapus self-signature ini? (y/T)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Menghapus %d signature.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Menghapus %d signature.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Tidak ada yang dihapus.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Masukkan ukuran kunci" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Silakan hapus pilihan dari kunci rahasia.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Silakan pilih maksimum satu kunci sekunder.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Merubah batas waktu untuk kunci sekunder.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Merubah batas waktu untuk kunci primer.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Anda tidak dapat merubah batas waktu kunci v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Tidak ada signature koresponden di ring rahasia\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Anda harus memilih minimum satu ID user.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "kunci %08lX: self-signature tidak valid\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Tidak ada ID user dengan index %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Tidak ada kunci sekunder dengan index %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "ID user: " - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"ditandai dengan kunci anda %08lX pada %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"ditandai dengan kunci anda %08lX pada %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "Kunci ini akan kadaluarsa pada %s \n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Anda tetap ingin menambahkannya? (y/n) " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Membuat sertifikat pembatalan untuk signature ini? (y/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Anda telah menandai ID user ini:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " ditandai oleh %08lX pada %s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " dibatalkan oleh %08lX pada %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Anda akan membatalkan signature ini:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " ditandai oleh %08lX pada %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Ingin membuat sertifikat pembatalan? (y/T)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "tidak ada kunci rahasia\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Kebijakan signature: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Kebijakan signature: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "PERINGATAN: ditemukan notasi data tidak valid\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notasi signature: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Notasi signature: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "tidak dapat dibaca manusia" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Keyring" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [berakhir: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "tampilkan kunci dan fingerprint" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingerprint kunci =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Fingerprint kunci =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingerprint kunci =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Fingerprint kunci =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algoritma hash tidak valid `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s data terenkripsi\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "dienkripsi dengan algoritma tidak dikenal %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "kunci publik adalah %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "data terenkripsi dengan kunci publik: DEK baik\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "dienkripsi dengan %u-bit kunci %s, ID %08lX, tercipta %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "dienkripsi dengan kunci %s, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "gagal dekripsi kunci publik: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "asumsikan %s data terenkripsi\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "Cipher IDEA tidak tersedia, secara optimis berusaha menggunakan %s\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "dekripsi lancar\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "PERINGATAN: pesan terenkripsi telah dimanipulasi!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "dekripsi gagal: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "CATATAN: pengirim meminta \"for-your-eyes-only\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "original file name='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "pembatalan mandiri - gunakan \"gpg --import\" untuk mengaplikasikan\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notasi: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Kebijakan: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verifikasi signature tidak diabaikan\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "tidak dapat menangani banyak signature ini\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Signature dibuat %.*s menggunakan kunci %s ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "signature BURUK dari \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Signature kadaluarsa dari \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Signature baik dari \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[uncertain]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Tidak dapat memeriksa signature: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "bukan detached signature\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "kelas signature mandiri 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "signature model lama (PGP 2.X)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "terdeteksi root paket tidak valid dalam proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "tidak dapat meniadakan core dump: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Algoritma eksperimental sebaiknya tidak dipakai!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"algoritma cipher ini didepresiasi; silakan gunakan yang lebih standar!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "plugin cipher IDEA tidak tersedia\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"silakan lihat http://www.gnupg.org/why-not-idea.html untuk informasi lebih " -"lanjut\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "PERINGATAN: `%s' adalah file kosong\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "PERINGATAN: `%s' adalah file kosong\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "tidak dapat menangani algoritma kunci publik %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "subpaket tipe %d memiliki bit kritis terset\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent tidak tersedia untuk sesi ini\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "tidak dapat menset pid client untuk agen\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "tidak dapat membuat server membaca FD untuk agen\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "tidak dapat membuat server menulis FD untuk agen\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "variabel lingkungan GPG_AGENT_INFO salah bentuk\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "protokol gpg-agent versi %d tidak didukung\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "tidak dapat terkoneksi ke `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "masalah komunikasi dengan gpg-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "masalah dengan agen - tiadakan penggunaan agen\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (ID kunci utama %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Anda perlu passphrase untuk membuka kunci rahasia untuk user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, tercipta %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Masukkan passphrase\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Ulangi passphrase\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "passphrase terlalu panjang\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "respon tidak valid dari agen\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "dibatalkan oleh user\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "masalah dengan agen: agen mengembalikan 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Anda perlu passphrase untuk membuka kunci rahasia untuk\n" -"pemakai: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bit kunci %s, ID %08lX, tercipta %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "tidak dapat meminta password dalam mode batch\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Masukkan passphrase: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Ulangi passphrase: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "data tidak disimpan; gunakan pilihan \"--output\" untuk menyimpannya\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "kesalahan penciptaan : `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Menghapus signature.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Silakan masukkan nama file data: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "membaca stdin ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "tidak ada data tertandai\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "tidak dapat membuka data tertandai `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "penerima anonim; mencoba kunci rahasia %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "baik, kita adalah penerima anonim.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "encoding lama DEK tidak didukung\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "algoritma cipher %d%s tidak dikenal atau ditiadakan\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "CATATAN: algoritma cipher %d tidak ditemukan dalam preferensi\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "CATATAN: kunci pribadi %08lX berakhir pada %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "kunci %08lX: kunci telah dibatalkan!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "meminta kunci %08lX dari keyserver HKP %s ...\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "tidak dapat memperoleh kunci keyserver: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "kesalahan mengirim ke `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "success sending to `%s' (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "failed sending to `%s': status=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "mencari \"%s\" dari server HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "tidak dapat mencari keyserver: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "bagian kunci rahasia tidak tersedia\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "algoritma proteksi %d%s tidak didukung\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Passphrase tidak valid; silakan coba lagi" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "PERINGATAN: terdeteksi kunci lemah - silakan ubah passphrase lagi.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"ini adalah kunci ElGamal ciptaan PGP yang tidak aman untuk signature!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "kunci publik adalah %lu detik lebih baru daripada signature\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "kunci publik adalah %lu detik lebih baru daripada signature\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"kunci telah diciptakan dalam %lu detik mendatang (masalah waktu atau jam)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"kunci telah diciptakan dalam %lu detik mendatang (masalah waktu atau jam)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "CATATAN: kunci signature %08lX berakhir %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "mengasumsikan signature buruk karena ada bit kritik tidak dikenal\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"PERINGATAN: tidak dapat melakukan %%-expand policy url (terlalu besar). " -"Menggunakan yang tidak expand.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"PERINGATAN: tidak dapat melakukan %%-expand policy url (terlalu besar). " -"Menggunakan yang tidak expand.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "Gagal memeriksa signature yang dibuat: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s signature dari: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "PERINGATAN: `%s' adalah file kosong\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"anda hanya dapat menandai kunci bergaya PGP 2.x saat dalam mode --pgp2\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "tidak dapat membuat %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "CATATAN: algoritma cipher %d tidak ditemukan dalam preferensi\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "menandai:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"anda hanya dapat clearsign dengan kunci bergaya PGP 2.x saat dalam mode --" -"pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%s enkripsi akan digunakan\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "tidak dapat menangani baris teks lebih dari %d karakter\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "baris input lebih dari %d karakter\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb rec %lu: lseek gagal: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb rec %lu: write failed (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transaksi trustdb terlalu besar\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: tidak dapat mengakses: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: direktori tidak ada!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: tidak dapat membuat lock\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: tidak dapat membuat lock\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: tidak dapat membuat: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: gagal membuat catatan versi: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: tercipta trustdb tidak valid\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: tercipta trustdb\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: trustdb tidak valid\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: gagal membuat hashtable: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: kesalahan memperbaharui catatan versi: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: kesalahan membaca catatan versi: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: kesalahan menulis catatan versi: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "trustdb: lseek gagal: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "trustdb: read failed (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: bukan file trustdb\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: catatan versi dengan recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: versi file %d tidak valid\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: kesalahan membaca record bebas: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: kesalahan menulis dir record: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: gagal mengosongkan record: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: gagal menambahkan record: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "trustdb terkorupsi; silakan jalankan \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "'%s' bukanlah keyID panjang yang valid\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "kunci %08lX: diterima sebagai kunci terpercaya.\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "kunci %08lX muncul lebih dari satu kali dalam trustdb\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "kunci %08lX: tidak ada kunci publik untuk trusted key- dilewati\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "trust record %lu, req tipe %d: gagal baca: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "trust record %lu tidak dalam jenis yang diminta %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "trust record %lu, tipe %d: gagal menulis: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "trustdb: gagal sync: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "tidak perlu memeriksa trustdb\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "pemeriksaan trustdb berikutnya pada %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "memeriksa trustdb\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "kunci publik %08lX tidak ditemukan: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "kunci publik yang sangat terpercaya %08lX tidak ditemukan\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"signature tidak dapat diverifikasi.\n" -"Tolong ingat bahwa file signature (.sig atau .asc)\n" -"haruslah file pertama yang diberikan pada perintah baris.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "baris input %u terlalu panjang atau hilang LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"kunci tidak dianggap sebagai tidak aman - tidak dapat digunakan dengan RNG " -"palsu!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "lewati `%s': terduplikasi\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "melewati `%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "dilewati: kunci pribadi telah ada\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"melewati `%s': ini adalah kunci ElGamal yang dihasilkan PGP yang tidak aman " -"untuk signature!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "File `%s' ada. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Ditimpa (y/T)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: suffix tidak dikenal\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Masukkan nama file baru" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "menulis ke stdout\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "mengasumsikan data bertanda dalam `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: file pilihan baru tercipta\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: tidak dapat membuat direktori: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: direktori tercipta\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"PERINGATAN: pesan dienkripsi dengan kunci lemah dalam cipher simetrik.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "masalah menangani paket terenkripsi\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "kunci lemah tercipta - mengulang\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"tidak dapat menghindari kunci lemah untuk cipher simetrik; mencoba %d kali!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "tidak dapat dilakukan dalam mode batch tanpa \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Menghapus kunci ini dari keyring? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Ini adalah kunci rahasia! - Yakin dihapus? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "gagal menghapus keyblok: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "terdapat kunci rahasia untuk kunci publik \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "gunakan pilihan \"--delete-secret-key\" untuk menghapusnya.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Terserah anda untuk memberi nilai baru di sini; nilai ini tidak akan " -"diekspor\n" -"ke pihak ketiga. Kami perlu untuk mengimplementasikan web-of-trust; tidak " -"ada\n" -"kaitan dengan (membuat secara implisit) web-of-certificates." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Untuk membuat Web-of-Trust, GnuPG perlu tahu kunci mana yang\n" -"sangat dipercaya - mereka biasanya adalah kunci yang anda punya\n" -"akses ke kunci rahasia. Jawab \"yes\" untuk menset kunci ini ke\n" -"sangat dipercaya\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Jika anda ingin menggunakan kunci yang dibatalkan, jawab \"ya\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "Jika anda ingin menggunakan kunci tidak terpercaya ini, jawab \"ya\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Masukkan ID user penerima pesan." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Pilih algoritma untuk digunakan.\n" -"\n" -"DSA (DSS) adalah algoritma signature digital yang hanya dapat digunakan \n" -"untuk signature. Ia merupakan algoritma yang disarankan karena verifikasi\n" -"signature DSA jauh lebih cepat daripada ElGamal.\n" -"\n" -"ElGamal adalah suatu algoritma yang dapat digunakan untuk signature dan \n" -"enkripsi. OpenPGP membedakannya ke dalam dua bentuk yaitu: hanya enkripsi\n" -"dan enkripsi+sign; sebenarnya sama, tetapi beberapa parameter harus dipilih\n" -"secara khusus untuk membuat kunci yang aman untuk signature; program ini\n" -"melakukannya tetapi implementasi OpenPGP lain tidak harus memahami bentuk\n" -"signature+enkripsi.\n" -"\n" -"Kunci pertama (primer) harus selalu merupakan kunci yang mampu men-sign;\n" -"hal ini merupakan alasan mengapa kunci ElGamal hanya-enkripsi tidak ada\n" -"di menu ini." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Meskipun kunci ini didefinisikan dalam RFC2440 mereka tidak disarankan\n" -"karena belum didukung oleh seluruh program dan signature yang dibuat\n" -"oleh mereka cukup besar dan sangat lambat untuk diverifikasi." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Masukkan ukuran kunci" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Jawab \"ya\" atau \"tidak\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Masukkan nilai yang diperlukan seperti pada prompt.\n" -"Dapat digunakan format (YYYY-MM-DD) untuk mengisi tanggal ISO tetapi anda\n" -"tidak akan mendapat respon kesalahan yang baik - sebaiknya sistem akan\n" -"berusaha menginterprestasi nilai yang diberikan sebagai sebuah interval." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Masukkan nama pemegang kunci" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "silakan masukkan alamat email (pilihan namun sangat dianjurkan)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Silakan masukkan komentar tambahan" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N untuk merubah nama.\n" -"K untuk merubah komentar.\n" -"E untuk merubah alamat email.\n" -"O untuk melanjutkan dengan pembuatan kunci.\n" -"K untuk menghentikan pembuatan kunci." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Jawab \"ya\" (atau \"y\") jika telah siap membuat subkey." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Ketika anda menandai user ID pada kunci, anda perlu memverifikasi bahwa " -"kunci\n" -"milik orang yang disebut dalam user ID. Ini penting bagi orang lain untuk " -"tahu\n" -"seberapa cermat anda memverifikasi ini.\n" -"\n" -"\"0\" berarti anda tidak melakukan klaim tentang betapa cermat anda " -"memverifikasi kunci.\n" -"\n" -"\"1\" berarti anda percaya bahwa kunci dimiliki oleh orang yang mengklaim " -"memilikinya\n" -" namun anda tidak dapat, atau tidak memverifikasi kunci sama sekali. Hal " -"ini bergunabagi\n" -" verifikasi \"persona\", yaitu anda menandai kunci user pseudonymous\n" -"\n" -"\"2\" berarti anda melakukan verifikasi kasual atas kunci. Sebagai contoh, " -"halini dapat\n" -" berarti bahwa anda memverifikasi fingerprint kunci dan memeriksa user ID " -"pada kunci\n" -" dengan photo ID.\n" -"\n" -"\"3\" berarti anda melakukan verifikasi ekstensif atas kunci. Sebagai " -"contoh, hal ini\n" -" dapat berarti anda memverifikasi fingerprint kunci dengan pemilik kunci\n" -" secara personal, dan anda memeriksa, dengan menggunakan dokumen yang " -"sulit dipalsukan yang memiliki\n" -" photo ID (seperti paspor) bahwa nama pemilik kunci cocok dengan\n" -" nama user ID kunci, dan bahwa anda telah memverifikasi (dengan " -"pertukaran\n" -" email) bahwa alamat email pada kunci milik pemilik kunci.\n" -"\n" -"Contoh-contoh pada level 2 dan 3 hanyalah contoh.\n" -"Pada akhirnya, terserah anda untuk memutuskan apa arti \"kasual\" dan " -"\"ekstensif\"\n" -"bagi anda ketika menandai kunci lain.\n" -"\n" -"Jika anda tidak tahu jawaban yang tepat, jawab \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Jawab \"ya\" jika anda ingin menandai seluruh ID user" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Jawab \"ya\" jika anda benar-benar ingin menghapus ID user ini.\n" -"Seluruh sertifikat juga akan hilang!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Jawab \"ya\" jika ingin menghapus subkey" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Ini adalah signature valid untuk kunci; anda normalnya tdk ingin menghapus\n" -"signature ini karena mungkin penting membangun koneksi trust ke kunci atau\n" -"ke kunci tersertifikasi lain dengan kunci ini." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Signature ini tidak dapat diperiksa karena anda tidak memiliki kunci\n" -"korespondennya. Anda perlu menunda penghapusannya hingga anda tahu\n" -"kunci yang digunakan karena kunci penanda ini mungkin membangun suatu\n" -"koneksi trust melalui kunci yang telah tersertifikasi lain." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"Signature tidak valid. Adalah hal yang masuk akal untuk menghapusnya dari\n" -"keyring anda" - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Ini adalah signature yang menghubungkan ID pemakai ke kunci. Biasanya\n" -"bukan ide yang baik untuk menghapus signature semacam itu. Umumnya\n" -"GnuPG tidak akan dapat menggunakan kunci ini lagi. Sehingga lakukan hal\n" -"ini bila self-signature untuk beberapa alasan tidak valid dan\n" -"tersedia yang kedua." - -#: g10/helptext.c:237 -#, fuzzy -msgid "" -"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" -msgstr "" -"Rubah preferensi seluruh user ID (atau hanya yang terpilih)\n" -"ke daftar preferensi saat ini. Timestamp seluruh self-signature\n" -"yang terpengaruh akan bertambah satu detik.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Silakan masukkan passphrase; ini kalimat rahasia\n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Silakan ulangi passphrase terakhir, sehingga anda yakin yang anda ketikkan." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Beri nama file tempat berlakunya signature" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Jawab \"ya\" jika tidak apa-apa menimpa file" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Silakan masukan nama file baru. Jika anda hanya menekan RETURN nama\n" -"file baku (yang diapit tanda kurung) akan dipakai." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Anda harus menspesifikasikan alasan pembatalan. Semua ini tergantung\n" -"konteks, anda dapat memilih dari daftar berikut:\n" -" \"Key has been compromised\"\n" -" Gunakan ini jika anda punya alasan untuk percaya bahwa orang yang " -"tidak berhak\n" -" memiliki akses ke kunci pribadi anda.\n" -" \"Key is superseded\"\n" -" Gunakan ini bila anda mengganti kunci anda dengan yang baru.\n" -" \"Key is no longer used\"\n" -" Gunakan ini bila anda telah mempensiunkan kunci ini.\n" -" \"User ID is no longer valid\"\n" -" Gunakan ini untuk menyatakan user ID tidak boleh digunakan lagi;\n" -" normalnya digunakan untuk menandai bahwa alamat email tidak valid " -"lagi.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Jika anda suka, anda dapat memasukkan teks menjelaskan mengapa anda\n" -"mengeluarkan sertifikat pembatalan ini. Buatlah ringkas.\n" -"Baris kosong mengakhiri teks.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Tidak tersedia bantuan" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Tidak tersedia bantuan untuk `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "kesalahan menulis keyring `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "%s: keyring tercipta\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "gagal membuat kembali cache keyring: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "PERINGATAN: terdapat 2 file dengan informasi penting.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s adalah yang tidak berubah\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s adalah yang baru\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Silakan perbaiki kemungkinan lubang keamanan ini\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "memeriksa keyring `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu kunci telah diperiksa (%lu signature)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu kunci telah diperiksa (%lu signature)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: keyring tercipta\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "anda harus memulai GnuPG lagi, sehingga ia dapat membaca file option " -#~ "baru\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "merubah permisi `%s' gagal: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAME=VALUE|gunakan notasi data ini" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "karakter pertama nama notasi harus huruf atau garis bawah\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "titik dalam nama notasi harus diapit oleh karakter lain\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "PERINGATAN: Kunci ini telah memiliki sebuah photo ID.\n" -#~ " Menambahkan photo ID lain dapat membingungkan beberapa versi " -#~ "PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Anda hanya boleh memiliki satu photo ID untuk satu kunci. \n" - -#~ msgid "Fingerprint:" -#~ msgstr "Fingerprint:" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingerprint:" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Apakah anda perlu keysize sebesar itu? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "kunci %08lX: salinan kita tidak memiliki self-signature\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " Apakah anda yakin masih ingin menandainya?\n" - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " ditandai oleh %08lX pada %s\n" diff --git a/po/it.po b/po/it.po deleted file mode 100644 index e21091c6f..000000000 --- a/po/it.po +++ /dev/null @@ -1,4704 +0,0 @@ -# GnuPG italian translation -# Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. -# Marco d'Itri , 1998, 1999, 2001, 2002. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg-1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-05-09 21:57+0200\n" -"Last-Translator: Marco d'Itri \n" -"Language-Team: Italian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Attenzione: si sta usando memoria insicura!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "visitare http://www.gnupg.org/faq.html per ulteriori informazioni\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "l'operazione non possibile senza memoria sicura inizializzata\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(potresti avere usato il programma sbagliato per questa funzione)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "s" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "sS" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "no" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "quit" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "errore generale" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "pacchetto di tipo sconosciuto" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "versione sconosciuta" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algoritmo della chiave pubblica sconosciuto" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algoritmo del digest sconosciuto" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "chiave pubblica errata" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "chiave segreta errata" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "firma errata" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "codice di controllo errato" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "passphrase errata" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "chiave pubblica non trovata" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algoritmo di cifratura sconosciuto" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "impossibile aprire il portachiavi" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "pacchetto non valido" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armatura non valida" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "l'user id non esiste" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "la chiave segreta non disponibile" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr " stata usata la chiave segreta sbagliata" - -#: util/errors.c:72 -msgid "not supported" -msgstr "non gestito" - -#: util/errors.c:73 -msgid "bad key" -msgstr "chiave sbagliata" - -#: util/errors.c:74 -msgid "file read error" -msgstr "errore durante la lettura del file" - -#: util/errors.c:75 -msgid "file write error" -msgstr "errore durante la scrittura del file" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritmo di compressione sconosciuto" - -#: util/errors.c:77 -msgid "file open error" -msgstr "errore durante l'apertura del file" - -#: util/errors.c:78 -msgid "file create error" -msgstr "errore durante la creazione del file" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "passphrase non valida" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmo della chiave pubblica non implementato" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritmo di cifratura non implementato" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "classe della firma sconosciuta" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "errore nel database della fiducia" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI danneggiato" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "limite della risorsa" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "portachiavi non valido" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "certificato danneggiato" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "user id malformato" - -#: util/errors.c:89 -msgid "file close error" -msgstr "errore durante la chiusura del file" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "errore durante la rinominazione del file" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "errore durante la cancellazione del file" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "dati inattesi" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "date in conflitto" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritmo della chiave pubblica non utilizzabile" - -#: util/errors.c:95 -msgid "file exists" -msgstr "il file esiste" - -#: util/errors.c:96 -msgid "weak key" -msgstr "chiave debole" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argomento non valido" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI non valida" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI non gestito" - -#: util/errors.c:100 -msgid "network error" -msgstr "errore di rete" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "non cifrato" - -# ??? (Md) -#: util/errors.c:103 -msgid "not processed" -msgstr "non esaminato" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "chiave pubblica inutilizzabile" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "chiave segreta inutilizzabile" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "errore del keyserver" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... questo un bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "Hai trovato un bug... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "impossibile aprire `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "impossibile eseguire stat su `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' non un file regolare - ignorato\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "nota: il file random_seed vuoto\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -"attenzione: le dimensioni del file random_seed non sono valide - non usato\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "impossibile leggere `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "nota: il file random_seed non stato aggiornato\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "impossibile creare `%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "impossibile scrivere su `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "impossibile chiudere `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "" -"ATTENZIONE: si sta usando un generatore di numeri casuali non sicuro!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Il generatore di numeri casuali solo un ripiego per fare\n" -"compilare il programma - non assolutamente un RNG forte!\n" -"\n" -"NON USARE ALCUN DATO GENERATO DA QUESTO PROGRAMMA!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Non ci sono abbastanza byte casuali disponibili. Per favore fai qualche\n" -"altra cosa per dare all'OS la possibilit di raccogliere altra entropia!\n" -"(Servono altri %d byte)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Comandi:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[file]|fai una firma" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[file]|fai una firma mantenendo il testo in chiaro" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "fai una firma separata" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "cifra dati" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[file]|cifra i file" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "cifra solo con un cifrario simmetrico" - -#: g10/g10.c:315 -msgid "store only" -msgstr "immagazzina soltanto" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "decifra dati (predefinito)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[file]|decifra i file" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verifica una firma" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "elenca le chiavi" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "elenca le chiavi e le firme" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "controlla le firme delle chiavi" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "elenca le chiavi e le impronte digitali" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "elenca le chiavi segrete" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "genera una nuova coppia di chiavi" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "rimuove le chiavi dal portachiavi pubblico" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "rimuove le chiavi dal portachiavi privato" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "firma una chiave" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "firma una chiave localmente" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "firma una chiave irrevocabilmente" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "firma una chiave localmente e irrevocabilmente" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "firma o modifica una chiave" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "genera un certificato di revoca" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "esporta delle chiavi" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "esporta le chiavi a un key server" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importa le chiavi da un key server" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "cerca delle chiavi su un key server" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "aggiorna tutte le chiavi da un key server" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importa/aggiungi delle chiavi" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "elenca solo la sequenza dei pacchetti" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "esporta i valori di fiducia" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importa i valori di fiducia" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "aggiorna il database della fiducia" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "aggiornamento non presidiato del database della fiducia" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "ripara un database della fiducia rovinato" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "rimuovi l'armatura a un file o a stdin" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "crea l'armatura a un file o a stdin" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [files]|stampa tutti i message digests" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opzioni:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "crea un output ascii con armatura" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOME|cifra per NOME" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOME|usa NOME come destinatario predefinito" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "usa la chiave predefinita come destinatario predefinito" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "usa questo user-id per firmare o decifrare" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|imposta il livello di compressione (0 disab.)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "usa il modo testo canonico" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "usa come file di output" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "prolisso" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "meno prolisso" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "non usa per niente il terminale" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "forza l'uso di firme v3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "non forza l'uso di firme v3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "forza l'uso di firme v4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "non forza l'uso di firme v4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "usa sempre un MDC per cifrare" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "non usa mai un MDC per cifrare" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "non fa cambiamenti" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "usa gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "modo batch: non fa domande" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "assumi \"s\" per quasi tutte le domande" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "assumi \"no\" per quasi tutte le domande" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "aggiungi questo portachiavi alla lista" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "aggiungi questo portachiavi segreto alla lista" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "mostra in quali portachiavi sono contenute le chiavi elencate" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOME|usa NOME come chiave segreta predefinita" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|cerca le chiavi in questo keyserver" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NOME|imposta NOME come set di caratteri del terminale" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "leggi le opzioni dal file" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|scrivi le informazioni di stato sul FD" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[file]|scrivi le informazioni di stato nel file" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID|assegna fiducia definitiva a questa chiave" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FILE|carica il modulo di estensione FILE" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emula il modo descritto in RFC 1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"imposta tutte le opzioni di pacchetto,\n" -"cifrario e digest per OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "imposta tutte le opzioni di pacchetto, cifrario e digest per PGP 2.x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|usa il modo N per la passphrase" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NOME|usa l'algoritmo di message digest NOME per le passphrase" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NOME|usa l'alg. di cifratura NOME per le passphrase" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOME|usa l'algoritmo di cifratura NOME" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOME|usa l'algoritmo di message digest NOME" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|usa l'algoritmo di compressione N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "elimina il campo keyid dei pacchetti cifrati" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Mostra le fotografie" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Non mostra le fotografie" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Imposta la riga di comando per vedere le fotografie" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Vedi la man page per una lista completa di tutti i comandi e opzioni)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Esempi:\n" -"\n" -" -se -r Bob [file] firma e cifra per l'utente Bob\n" -" --clearsign [file] fai una firma mantenendo il testo in chiaro\n" -" --detach-sign [file] fai una firma separata\n" -" --list-keys [nomi] mostra le chiavi\n" -" --fingerprint [nomi] mostra le impronte digitali\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Per favore segnala i bug a .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Uso: gpg [opzioni] [files] (-h per l'aiuto)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintassi: gpg [opzioni] [files]\n" -"firma, controlla, cifra o decifra\n" -"l'operazione predefinita dipende dai dati di input\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritmi gestiti:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uso: gpg [opzioni] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "comandi in conflitto\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Attenzione: proprietario \"%s\" di %s insicuro\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Attenzione: permessi \"%s\" di %s insicuri\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Attenzione: proprietario \"%s\" di %s insicuro\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Attenzione: permessi \"%s\" di %s insicuri\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTA: manca il file `%s' con le opzioni predefinite\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTA: manca il file `%s' con le opzioni predefinite\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "file con le opzioni `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "lettura delle opzioni da `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s non un set di caratteri valido\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "impossibile fare il parsing dell'URI del keyserver\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: versione %d del file non valida\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armatura non valida" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: versione %d del file non valida\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "portachiavi non valido" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "impossibile impostare exec-path a %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "ATTENZIONE: il programma potrebbe creare un file core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "ATTENZIONE: %s ha la precedenza su %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTA: %s normalmente non deve essere usato!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "Non permesso usare %s con %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "Non ha senso usare %s con %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "nella modalit --pgp2 puoi fare solo firme in chiaro o separate\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "nella modalit --pgp2 non puoi firmare e cifrare contemporaneamente\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" -"devi usare dei file (e non una pipe) quando lavori con --pgp2 attivo.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" -"nella modalit --pgp2 richiesto il cifrario IDEA per cifrare un messaggio\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "questo messaggio pu non essere utilizzabile da PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "l'algoritmo di cifratura selezionato non valido\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "l'algoritmo di digest selezionato non valido\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "l'algoritmo di digest selezionato non valido\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "l'algoritmo di compressione deve essere tra %d e %d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed deve essere maggiore di 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed deve essere maggiore di 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth deve essere tra 1 e 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTA: l'uso del modo S2K semplice (0) fortemente scoraggiato\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "modo S2K non valido; deve essere 0, 1 o 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "default-check-level non valido; deve essere 0, 1 o 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "preferenze non valide\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "preferenze non valide\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "preferenze non valide\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "preferenze non valide\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "inizializzazione del trustdb fallita: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [nomefile]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [nomefile]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [nomefile]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [nomefile]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [nomefile]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [nomefile]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [nomefile]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [nomefile]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key user-id" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key user-id" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key user-id" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key user-id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key user-id [comandi]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "impossibile aprire `%s': %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [user-id] [portachiavi]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "rimozione dell'armatura fallita: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "creazione dell'armatura fallita: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algoritmo di hash non valido `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nomefile]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Vai avanti e scrivi il messaggio...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "impossibile aprire `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"il nome di una nota deve essere formato solo da lettere, numeri, punti o\n" -"underscore e deve finire con `='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "il valore di una nota non deve usare caratteri di controllo\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "l'URL della politica di certificazione indicato non valido\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "l'URL della politica di firma indicato non valido\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armatura: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "header dell'armatura non valido: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "header dell'armatura: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "header della firma in chiaro non valido\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "firme in chiaro annidate\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "riga protetta con il trattino non valida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armatura inaspettata:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "Carattere radix64 non valido %02x saltato\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "eof prematura (nessun CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "eof prematura (nel CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC malformato\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "errore nel CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "eof prematura (nella coda)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "errore nella riga della coda\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "Non sono stati trovati dati OpenPGP validi.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armatura non valida: linea pi lunga di %d caratteri\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"carattere quoted printable nell'armatura - probabilmente stato usato\n" -"un MTA buggato\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Nessuna ragione specificata" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Questa chiave stata sostituita" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Questa chiave stata compromessa" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "La chiave non pi usata" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "L'user ID non pi valido" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Ragione della revoca: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Commento alla revoca: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Nessun valore di fiducia assegnato a:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Per favore decidi quanto hai fiducia che questo utente firmi correttamente\n" -"le chiavi di altri utenti (guardando il loro passaporto, controllando le\n" -"impronte digitali da diverse fonti...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = Non lo so\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = NON mi fido\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Mi fido marginalmente\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Mi fido completamente\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Mi fido definitivamente\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = mostrami ulteriori informazioni\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = torna al men principale\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = salta questa chiave\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = abbandona\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Cosa hai deciso? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Vuoi davvero assegnare fiducia definitiva a questa chiave? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificati che portano a chiavi definitivamente affidabili:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "chiave %08lX: la chiave stata revocata!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Uso lo stesso questa chiave? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "chiave %08lX: la subchiave stata revocata!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: la chiave scaduta\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Non ci sono indicazioni che la chiave appartenga al proprietario\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: NON ci fidiamo di questa chiave!\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Non sicuro che questa chiave appartenga veramente al proprietario\n" -"ma accettata comunque\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Questa chiave probabilmente appartiene al proprietario\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Questa chiave ci appartiene\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"NON sicuro che la chiave appartenga al suo proprietario.\n" -"Se *veramente* sai cosa stai facendo, puoi rispondere s alla\n" -"prossima domanda.\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "ATTENZIONE: uso di una chiave non fidata!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "ATTENZIONE: questa chiave stata revocata dal suo proprietario!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Questo pu significare che la firma stata falsificata.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "ATTENZIONE: questa subchiave stata revocata dal proprietario!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Nota: questa chiave stata disabilitata.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Nota: questa chiave scaduta!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "ATTENZIONE: questa chiave non certificata con una firma fidata!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Non ci sono indicazioni che la firma appartenga al proprietario.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "ATTENZIONE: NON ci fidiamo di questa chiave!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " La firma probabilmente un FALSO.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"ATTENZIONE: questa chiave non certificata con firme abbastanza fidate!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Non sicuro che la firma appartenga al proprietario.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: saltata: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: saltato: chiave pubblica gi presente\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Non hai specificato un user ID. (puoi usare \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Inserisci l'user ID. Termina con una riga vuota: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "User ID inesistente.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "saltato: chiave pubblica gi impostata come destinatario predefinito\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "La chiave pubblica disabilitata.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "saltato: chiave pubblica gi impostata\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "destinatario predefinito `%s' sconosciuto\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: saltato: chiave pubblica disabilitata\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "nessun indirizzo valido\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "la preferenza %c%lu non valida\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "la preferenza %c%lu doppia\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "ci sono troppe preferenze `%c'\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "carattere non valido nella stringa delle preferenze\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "scrittura della autofirma\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "scrittura della autofirma\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "scrittura della firma di collegamento alla chiave\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "dimensione della chiave non valida; uso %u bit\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "dimensioni della chiave arrotondate a %u bit\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Per favore scegli che tipo di chiave vuoi:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA e ElGamal (default)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (firma solo)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (cifra solo)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (firma e cifra)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (firma solo)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (cifra solo)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (firma e cifra)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Cosa scegli? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "L'uso di questo algoritmo deprecato - la creo comunque? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Scelta non valida.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Sto per generare una nuova coppia di chiavi %s.\n" -" la dimensione minima 768 bit\n" -" la dimensione predefinita 1024 bit\n" -" la dimensione massima consigliata 2048 bit\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Di che dimensioni vuoi la chiave? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA permette solo chiavi di dimensioni tra 512 e 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "la chiave troppo corta; 1024 il minimo valore permesso per RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "la chiave troppo corta; 768 il minimo valore permesso.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "la chiave troppo lunga; %d il massimo valore permesso.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Chiavi pi lunghe di 2048 non sono consigliate perch i calcoli sono\n" -"VERAMENTE lunghi!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Sei sicuro di volere una chiave di queste dimensioni? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Va bene, ma ricordati che anche le radiazioni emesse dal tuo monitor e dalla " -"tua tastiera sono molto vulnerabili ad attacchi!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "La dimensione richiesta della chiave %u bit\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "arrotondate a %u bit\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Per favore specifica per quanto tempo la chiave sar valida.\n" -" 0 = la chiave non scadr\n" -" = la chiave scadr dopo n giorni\n" -" w = la chiave scadr dopo n settimane\n" -" m = la chiave scadr dopo n mesi\n" -" y = la chiave scadr dopo n anni\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Per favore specifica per quanto tempo la firma sar valida.\n" -" 0 = la chiave non scadr\n" -" = la chiave scadr dopo n giorni\n" -" w = la chiave scadr dopo n settimane\n" -" m = la chiave scadr dopo n mesi\n" -" y = la chiave scadr dopo n anni\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Chiave valida per? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Firma valida per? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valore non valido\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s non ha scadenza\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s scadr il %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Il tuo sistema non pu mostrare date oltre il 2038.\n" -"Comunque, sar gestita correttamente fino al 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr " giusto (s/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Ti serve un User ID per identificare la tua chiave; il software costruisce " -"l'user id a partire da Nome e Cognome, Commento e Indirizzo di Email " -"indicati in questa forma:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nome e Cognome: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Carattere non valido nel nome\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Il nome non pu iniziare con una cifra\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Il nome deve essere lungo almeno 5 caratteri\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Indirizzo di Email: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "L'indirizzo di email non valido\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Commento: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Carattere non valido nel commento\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Stai usando il set di caratteri `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Hai selezionato questo User Id:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Per favore non mettere l'indirizzo di email nel nome o nel commento\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoQq" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Modifica (N)ome, (C)ommento, (E)mail oppure (Q)uit? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Modifica (N)ome, (C)ommento, (E)mail oppure (O)kay/(Q)uit? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Per favore correggi prima l'errore\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Ti serve una passphrase per proteggere la tua chiave segreta.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "passphrase non ripetuta correttamente; prova ancora" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Non hai specificato una passphrase - questa probabilmente una *cattiva*\n" -"idea! Lo far io comunque. Puoi cambiarla in ogni momento, usando questo\n" -"programma con l'opzione \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Dobbiamo generare un mucchio di byte casuali. una buona idea eseguire\n" -"qualche altra azione (scrivere sulla tastiera, muovere il mouse, usare i\n" -"dischi) durante la generazione dei numeri primi; questo da al generatore di\n" -"numeri casuali migliori possibilit di raccogliere abbastanza entropia.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "La coppia DSA avr 1024 bit.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Generazione della chiave annullata.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "scrittura della chiave pubblica in `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "scrittura della chiave segreta in `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "non stato trovato un portachiavi pubblico scrivibile: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "non stato trovato un portachiavi segreto scrivibile: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "errore scrivendo il portachiavi pubblico `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "errore scrivendo il portachiavi segreto `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "chiavi pubbliche e segrete create e firmate.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "chiavi marcate definitivamente affidabili.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Nota che questa chiave non pu essere usata per cifrare. Forse vorrai usare\n" -"il comando \"--edit-key\" per generare una chiave secondaria per questo " -"scopo.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Generazione della chiave fallita: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"la chiave stata creata %lu secondo nel futuro (salto nel tempo o problema\n" -"con l'orologio)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"la chiave stata creata %lu secondi nel futuro (salto nel tempo o problema\n" -"con l'orologio)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "NB: la creazione di sottochiavi per chiavi v3 non rispetta OpenPGP.\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Crea davvero? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output non funziona con questo comando\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: impossibile aprire: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "errore nella creazione della passhprase: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' gi compresso\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: ATTENZIONE: file vuoto\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"in modalit --pgp2 puoi cifrare solo per chiavi RSA non pi lunghe di 2048 " -"bit\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lettura da `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"impossibile usare il cifrario IDEA con tutti i tipi di chiavi per cui\n" -"stai cifrando.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"NOTA: l'algoritmo di cifratura %d non stato trovato tra le preferenze\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Questo comando non permesso in modalit %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s cifrato per: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "chiave `%s' non trovata: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "errore leggendo il keyblock: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "chiave %08lX: chiave non rfc2440 - saltata\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "chiave %08lX: non protetta - saltata\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "chiave %08lX: chiave in stile PGP 2.x - saltata\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "ATTENZIONE: non stato esportato nulla\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "troppe voci nella pk cache - disabilitata\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[User ID non trovato]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "Chiave %08lX non valida resa valida da --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "uso la chiave secondaria %08lX invece della chiave primaria %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "chiave %08lX: chiave segreta senza chiave pubblica - saltata\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "salto un blocco di tipo %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "Per ora sono state esaminate %lu chiavi\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "errore leggendo `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Numero totale esaminato: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " nuove chiavi saltate: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " senza user ID: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importate: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " non modificate: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nuovi user ID: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nuove subchiavi: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nuove firme: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr "nuove revoche di chiavi: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " chiavi segrete lette: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "chiavi segrete importate: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "chiavi segrete non cambiate: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importate: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "chiave %08lX: nessun user ID\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "chiave %08lX: non ci sono subchiavi per il legame con la chiave\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "chiave %08lX: accettato l'user ID non autofirmato '%s'\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "chiave %08lX: nessun user ID valido\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "questo pu essere causato da una autofirma mancante\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "chiave %08lX: chiave pubblica non trovata: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "chiave %08lX: nuova chiave - saltata\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "non stato trovato un portachiavi scrivibile: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "scrittura in `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "errore scrivendo il portachiavi `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "chiave %08lX: chiave pubblica importata\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "chiave %08lX: non corrisponde alla nostra copia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "chiave %08lX: impossibile individuare il keyblock originale: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "chiave %08lX: impossibile leggere il keyblock originale: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "chiave %08lX: 1 nuovo user ID\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "chiave %08lX: %d nuovi user ID\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "chiave %08lX: una nuova firma\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "chiave %08lX: %d nuove firme\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "chiave %08lX: una nuova subchiave\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "chiave %08lX: %d nuove subchiavi\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "chiave %08lX: non cambiata\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "nessun portachiavi segreto predefinito: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "chiave %08lX: chiave segreta importata\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "chiave %08lX: gi nel portachiavi segreto\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "chiave %08lX: chiave segreta non trovata: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"chiave %08lX: manca la chiave pubblica - impossibile applicare il\n" -"certificato di revoca\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "chiave %08lX: certificato di revoca non valido: %s - rifiutato\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "chiave %08lX: certificato di revoca importato\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "chiave %08lX: nessun user ID per la firma\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"chiave %08lX: algoritmo a chiave pubblica non gestito sull'user ID \"%s\"\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "chiave %08lX: autofirma non valida sull'user ID \"%s\"\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "chiave %08lX: non ci sono subchiavi per il legame con la chiave\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "chiave %08lX: algoritmo a chiave pubblica non gestito\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "chiave %08lX: legame con la subchiave non valido:\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "chiave %08lX: legame con la subchiave non valido:\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "chiave %08lX: non ci sono subchiavi per il legame con la chiave\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "chiave %08lX: legame con la subchiave non valido:\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "chiave %08lX: legame con la subchiave non valido:\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "chiave %08lX: saltato l'user ID '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "chiave %08lX: saltata la subchiave\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "chiave %08lX: firma non esportabile (classe %02x) - saltata\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "chiave %08lX: certificato di revoca nel posto sbagliato - saltato\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "chiave %08lX: certificato di revoca non valido: %s - saltato\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "chiave %08lX: certificato di revoca nel posto sbagliato - saltato\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "chiave %08lX: trovato un user ID duplicato - unito\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"Attenzione: la chiave %08lX pu essere stata revocata: scarico la chiave\n" -"di revoca %08lX.\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"Attenzione: la chiave %08lX pu essere stata revocata: la chiave di revoca\n" -"%08lX non presente.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "chiave %08lX: certificato di revoca aggiunto\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "chiave %08lX: aggiunta una firma alla chiave diretta\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revoca]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[autofirma]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "una firma non corretta\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d firme non corrette\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "una firma non controllata per mancanza della chiave\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d firme non controllate per mancanza delle chiavi\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "una firma non controllata a causa di un errore\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d firme non controllate a causa di errori\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "Trovato un user ID senza autofirma valida\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "Trovati %d user ID senza autofirme valide\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "L'user ID \"%s\" stato revocato." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Sei ancora sicuro di volerla firmare? (s/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Impossibile firmarla.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "ATTENZIONE: `%s' un file vuoto\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"La tua firma attuale su \"%s\"\n" -" una firma locale.\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Vuoi trasformarla in una firma completa esportabile? (s/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"La tua firma attuale su \"%s\"\n" -" una firma locale.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Vuoi trasformarla in una firma completa esportabile? (s/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" era gi stato firmato localmente dalla chiave %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" era gi stato firmato dalla chiave %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Niente da firmare con la chiave %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Questa chiave scaduta!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Questa chiave scadr il %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Vuoi che la tua firma scada nello stesso momento? (S/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"In modalit -pgp2 non possibile fare firme OpenPGP su chiavi in stile PGP " -"2.x.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Questo renderebbe la chiave non utilizzabile da PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Con quanta attenzione hai verificato che la chiave che stai per firmare\n" -"appartiene veramente alla persona indicata sopra?\n" -"Se non sai cosa rispondere digita \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Preferisco non rispondere.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Non l'ho controllata per niente.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) L'ho controllata superficialmente.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) L'ho controllata molto attentamente.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Sei davvero sicuro di volere firmare questa chiave\n" -"con la tua chiave: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "questo pu essere causato da una autofirma mancante\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"La firma sar marcata come non esportabile.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"La firma sar marcata come irrevocabile.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"La firma sar marcata come non esportabile.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"La firma sar marcata come irrevocabile.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Non ho controllato per niente questa chiave.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Ho controllato questa chiave superficialmente.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Ho controllato questa chiave molto attentamente.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Firmo davvero? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "firma fallita: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Questa chiave non protetta.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Parti della chiave segreta non sono disponibili.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "La chiave protetta.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Impossibile modificare questa chiave: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Inserisci la nuova passphrase per questa chiave segreta.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Non vuoi una passphrase - questa probabilmente una *cattiva* idea!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Vuoi veramente farlo?" - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "spostamento della firma di una chiave nel posto corretto\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "abbandona questo men" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "salva ed esci" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "mostra questo aiuto" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "mostra le impronte digitali" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "elenca le chiavi e gli user ID" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "scegli l'user ID N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "scegli la chiave secondaria N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "elenca le firme" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "firma la chiave" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "firma la chiave localmente" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "firma la chiave irrevocabilmente" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "firma la chiave localmente e irrevocabilmente" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "aggiungi un user ID" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "aggiungi un ID fotografico" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "cancella un user ID" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "aggiungi una chiave secondaria" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "cancella una chiave secondaria" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "aggiungi una chiave secondaria" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsign" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "cancella le firme" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "cambia la data di scadenza" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "imposta l'user ID come primario" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "cambia tra visualizzare la chiave segreta e la chiave pubblica" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "elenca le preferenze (per esperti)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "elenca le preferenze (prolisso)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "imposta la lista di preferenze" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "preferenze aggiornate" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "cambia la passphrase" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "cambia il valore di fiducia" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revoca firme" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revoca una chiave secondaria" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "disabilita una chiave" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "abilita" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "abilita una chiave" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "mostra l'ID fotografico" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "impossibile fare questo in modo batch\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "errore leggendo il keyblock segreto `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr " disponibile una chiave segreta.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Comando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Per fare questo serve la chiave segreta.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Per favore usa prima il comando \"toggle\".\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "La chiave stata revocata." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Firmo davvero tutti gli user ID? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Suggerimento: seleziona gli user ID da firmare\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Questo comando non permesso in modalit %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Devi selezionare almeno un user ID.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Non puoi cancellare l'ultimo user ID!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Tolgo davvero tutti gli user ID selezionati? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Tolgo davvero questo user ID? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Devi selezionare almeno una chiave.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Vuoi davvero cancellare le chiavi selezionate? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Vuoi davvero cancellare questa chiave? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Vuoi davvero revocare le chiavi selezionate? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Vuoi davvero revocare questa chiave? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "Aggiorno davvero le preferenze per gli user ID selezionati? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Aggiorno davvero le preferenze? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Salvo i cambiamenti? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Esco senza salvare? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "aggiornamento fallito: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "aggiornamento della chiave segreta fallito: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "La chiave non cambiata quindi non sono necessari aggiornamenti.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Comando non valido (prova \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Questa chiave pu essere revocata dalla chiave %s %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (sensibile)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX creata: %s scade: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " fiducia: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Questa chiave stata disabilitata" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! la subchiave stata revocata: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- trovata una revoca falsificata\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problema controllando la revoca: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Nota che la validit della firma indicata non sar necessariamente corretta\n" -"finch non eseguirai di nuovo il programma.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"ATTENZIONE: Questa una chiave in stile PGP2. Aggiungere un ID fotografico\n" -" pu causare il rifiuto della chiave da parte di alcune versioni\n" -" di PGP.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Sei ancora sicuro di volerlo aggiungere? (s/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" -"Non possibile aggiungere un ID fotografico a una chiave in stile PGP2.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Cancellare questa firma corretta? (s/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Cancellare questa firma non valida? (s/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Cancellare questa firma sconosciuta? (s/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Cancellare davvero questa autofirma? (s/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Cancellata %d firma.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Cancellate %d firme.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Non stato cancellato nulla.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Inserisci le dimensioni della chiave" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Togli le selezioni dalle chiavi segrete.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Seleziona al massimo una chiave secondaria.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Cambio la data di scadenza per una chiave secondaria.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Cambio la data di scadenza per la chiave primaria.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Non possibile cambiare la data di scadenza di una chiave v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Manca la firma corrispondente nel portachiavi segreto\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Devi selezionare esattamente un user ID.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "chiave %08lX: autofirma non valida sull'user ID \"%s\"\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Nessun user ID con l'indice %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Nessuna chiave secondaria con l'indice %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "user ID: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"firmata con la tua chiave %08lX il %s\n" -"\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"firmata localmente con la tua chiave %08lX il %s\n" -"\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Questa chiave scaduta il %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Sei ancora sicuro di volerlo aggiungere? (s/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Creare un certificato di revoca per questa firma? (s/N) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Non puoi cancellare l'ultimo user ID!\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " firmata da %08lX il %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revocata da %08lX il %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Stai per revocare queste firme:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " firmata da %08lX il %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (non esportabile)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Creare davvero i certificati di revoca? (s/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "manca la chiave segreta\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Mostro %s ID fotografici di dimensioni %ld per la chaive 0x%08lX (uid %d)\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Politica di firma: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Politica di firma: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "ATTENZIONE: trovati dati di una nota non validi\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Annotazione della firma: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Annotazione della firma: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "non leggibile" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Portachiavi" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr "[scadenza: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "elenca le chiavi e le impronte digitali" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Impronta digitale =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Impronta digitale =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Impronta digitale =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Impronta digitale =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algoritmo di hash non valido `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "dati cifrati con %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "cifrato con l'algoritmo sconosciuto %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "la chiave pubblica %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "dati cifrati con la chiave pubblica: DEK corretto\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "cifrato con la chiave %2$s di %1$u bit, ID %3$08lX, creata il %4$s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "Cifrato con la chiave %s con ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "decifratura della chiave pubblica fallita: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "suppongo che i dati siano cifrati con %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "Cifrario IDEA non disponibile, ottimisticamente cerco di usare %s\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "decifratura corretta\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "ATTENZIONE: il messaggio cifrato stato manipolato!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "decifratura fallita: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTA: il mittente ha richiesto \"solo-per-i-tuoi-occhi\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nome del file originale='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "revoca solitaria - usa \"gpg --import\" per applicarla\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Nota: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Policy: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verifica della firma soppressa\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "impossibile gestire queste firme multiple\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Firma fatta %.*s usando la chiave %s con ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "Firma NON corretta da \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Firma scaduta da \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Firma valida da \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[incerta]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Impossibile controllare la firma: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "non una firma separata\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "firma solitaria di classe 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "firma vecchio stile (PGP 2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "individuato un pacchetto radice non valido in proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "impossibile disabilitare i core dump: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Gli algoritmi sperimentali non dovrebbero essere usati!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "questo algoritmo di cifratura deprecato; usane uno pi standard!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "il plugin per il cifrario IDEA non presente\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"per ulteriori informazioni si veda http://www.gnupg.org/it/why-not-idea." -"html\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "ATTENZIONE: %s una opzione deprecata.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "ATTENZIONE: %s una opzione deprecata.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "usa al suo posto \"--keyserver-options %s\"\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "impossibile gestire l'algoritmo a chiave pubblica %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "il sottopacchetto di tipo %d ha un bit critico impostato\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent non disponibile in questa sessione\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "impossibile impostare il pid del client dell'agent\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "impossibile ottenere il FD di lettura dell'agent\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "impossibile ottenere il FD di scrittura dell'agent\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "variabile di ambiente GPG_AGENT_INFO malformata\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "la versione %d del protocollo di gpg-agent non gestita\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "impossibile connettersi a `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problema di comunicazione con gpg-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problema con l'agent - uso dell'agent disattivato\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (key ID principale %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Ti serve una passphrase per sbloccare la chiave segreta dell'utente:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Inserisci la passphrase\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Ripeti la passphrase\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "passphrase troppo lunga\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "risposta non valida dall'agent\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "interrotto dall'utente\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problema con l'agent: ha restituito 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Ti serve una passphrase per sbloccare la chiave segreta\n" -"dell'utente: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "chiave %2$s di %1$u bit, ID %3$08lX, creata il %4$s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "impossibile chiedere la password in modo batch\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Inserisci la passphrase: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Ripeti la passphrase: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"i dati non sono stati salvati; usa l'opzione \"--output\" per salvarli\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "errore creando `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Firma separata.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Inserisci il nome del file di dati: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "viene letto stdin...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "non ci sono dati firmati\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "impossibile aprire i dati firmati `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinatario anonimo; provo la chiave segreta %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "bene, siamo il destinatario anonimo.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "la vecchia codifica del DEK non gestita\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "l'algoritmo di cifratura %d%s sconosciuto o disattivato\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "" -"NOTA: l'algoritmo di cifratura %d non stato trovato tra le preferenze\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTA: chiave %08lX scaduta il %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "chiave %08lX: la chiave stata revocata!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "richiedo la chiave %08lX dal keyserver HKP %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "impossibile scaricare la chiave dal keyserver: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "errore leggendo `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "inviata con successo a `%s' (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "invio a `%s' fallito: status=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "cerco \"%s\" sul server HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "impossibile cercare sul keyserver: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "parti della chiave segreta non sono disponibili\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "l'algoritmo di protezione %d%s non gestito\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Passphrase non valida; riprova" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"ATTENZIONE: Individuata una chiave debole - per favore cambia ancora la\n" -"passphrase.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"genero il checksum a 16 bit deprecato per la protezione della chiave " -"segreta\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"questa una chiave ElGamal generata da PGP e NON sicura per le firme!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "la chiave pubblica %lu secondo pi recente della firma\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "la chiave pubblica %lu secondi pi recente della firma\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"la chiave stata creata %lu secondo nel futuro (salto nel tempo o problema\n" -"con l'orologio)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"la chiave stata creata %lu secondi nel futuro (salto nel tempo o problema\n" -"con l'orologio)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTA: chiave per firmare %08lX scaduta il %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"si suppone una firma non valida a causa di un bit critico sconosciuto\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"ATTENZIONE: Impossibile espandere i %% nell'URL (troppo lunga). Usata " -"inespansa.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"ATTENZIONE: Impossibile espandere i %% nell'URL (troppo lunga). Usata " -"inespansa.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "controllo della firma creata fallito: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "Firma %s da: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "ATTENZIONE: `%s' un file vuoto\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "In modalit -pgp2 puoi firmare solo con chiavi in stile PGP 2.x\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "impossibile creare %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"NOTA: l'algoritmo di cifratura %d non stato trovato tra le preferenze\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "firma:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"In modalit -pgp2 puoi firmare in chiaro solo con chiavi in stile PGP 2.x\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "sar usato il cifrario %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "impossibile gestire linee di testo pi lunghe di %d caratteri\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "linea di input pi lunga di %d caratteri\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb rec %lu: lseek fallita: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb rec %lu: scrittura fallita (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transazione del trustdb troppo grande\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: impossibile acedere a: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: la directory non esiste!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: impossibile creare il lock\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: impossibile creare il lock\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: impossibile creare: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: creazione del record della versione fallita: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: stato creato un trustdb non valido\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: creato il trustdb\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: trustdb non valido\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: creazione della tabella hash fallita: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: errore durante l'aggiornamento del record di versione: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: errore durante la lettura del record di versione: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: errore durante la scrittura del record di versione: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "trustdb: lseek fallita: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "trustdb: read fallita (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: non un file di trustdb\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: record di versione con recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: versione %d del file non valida\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: errore durante la lettura del record libero: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: errore durante la scrittura del dir record: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: azzeramento di un record fallito: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: accodatura a un record fallita: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "Il trustdb danneggiato; eseguire \"gpg --fix-trust-db\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' non un key ID lungo valido\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "chiave %08lX: accettata come chiave affidabile\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "chiave %08lX: appare nel trustdb pi di una volta\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"chiave %08lX: manca la chiave pubblica della chiave fidata - ignorata\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "trust record %lu, tipo %d: read fallita: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "il trust record %lu non del tipo richiesto %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "trust record %lu, req type %d: write fallita: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "trustdb: sync fallita: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "non necessario un controllo del trustdb\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "il prossimoi controllo del trustdb sar fatto il %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "controllo il trustdb\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "chiave pubblica %08lX non trovata: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "chiave pubblica definitivamente affidabile %08lX non trovata\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "controllo al livello %d firmato=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"non stato possibile verificare la firma.\n" -"Ricorda che il file con la firma (.sig or .asc) deve\n" -"essere il primo file indicato sulla riga di comando.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "linea di input %u troppo lunga o LF mancante\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"la chiave non indicata come insicura - impossibile usarla con il RNG " -"finto!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "saltata `%s': doppia\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "saltata `%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "saltata: chiave pubblica gi presente\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"saltata %s: questa una chiave ElGamal generata da PGP che NON sicura per " -"le firme!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Il file `%s' esiste. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Sovrascrivo (s/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: suffisso sconosciuto\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Inserire il nuovo nome del file" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "scrivo su stdout\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "suppongo che i dati firmati siano in `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: creato un nuovo file delle opzioni\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: impossibile creare la directory: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: directory creata\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"ATTENZIONE: il messaggio era stato cifrato usando una chiave debole\n" -"per il cifrario simmetrico\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problema nella gestione del pacchetto cifrato\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "creata una chiave debole - riprovo\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"Impossibile evitare una chiave debole per il cifrario simmetrico;\n" -"ho provato %d volte!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA richiede l'uso di un algoritmo di hashing con almeno 160 bit\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "impossibile fare questo in modo batch senza \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Vuoi cancellare questa chiave dal portachiavi? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr " una chiave segreta! - Vuoi cancellarla davvero? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "cancellazione del keyblock fallita: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "informazioni di fiducia del possessore cancellate\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "c' una chiave segreta per la chiave pubblica \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "usa prima l'opzione \"--delete-secret-keys\" per cancellarla.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"E compito tuo assegnare un valore; questo valore non sar mai esportato a\n" -"terzi. Ci serve per implementare il web-of-trust; non ha nulla a che fare\n" -"con il web-of-certificates (creato implicitamente)." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Per costruire il Web-Of-Trust, GnuPG ha bisogno di sapere quali chiavi sono\n" -"definitivamente affidabili - di solito quelle per cui hai accesso alla " -"chiave\n" -"segreta.\n" -"Rispondi \"s\" per impostare questa chiave come definitivamente affidabile\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Se vuoi usare comunque questa chiave revocata, rispondi \"si\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "Se vuoi usare comunque questa chiave non fidata, rispondi \"si\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Inserisci l'user ID del destinatario a cui vuoi mandare il messaggio." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Seleziona l'algoritmo da usare.\n" -"\n" -"DSA (alias DSS) un algoritmo usabile solo per firmare. E l'algoritmo\n" -"suggerito perch verificare firme DSA molto pi veloce di quelle ElGamal.\n" -"\n" -"ElGamal un algoritmo usabile per firmare e cifrare.\n" -"OpenPGP distingue tra due versioni di questo algoritmo: una solo per " -"firmare\n" -"e una per firmare e cifrare. In realt sempre lo stesso, ma per creare\n" -"firme sicure per la cifratura occorre scegliere in un modo particolare " -"alcuni\n" -"parametri: questo programma lo fa ma non richiesto che altre " -"implementazioni\n" -"di OpenPGP capiscano la versione per firmare e cifrare.\n" -"\n" -"La prima chiave (primaria) deve sempre essere una chiave in grado di " -"firmare;\n" -"questo il motivo per cui le chiavi ElGamal solo per cifrare non sono\n" -"disponibili in questo men." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Anche se queste chiavi sono definite da RFC2400 non sono suggerite perch " -"non\n" -"sono gestite da tutti i programmi e le firme create sono grandi e lunghe da\n" -"verificare." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Inserisci le dimensioni della chiave" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Rispondi \"si\" o \"no\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Inserisci il valore richiesto come indicato dal prompt.\n" -" possibile inserire una data in formato ISO (YYYY-MM-DD) ma non avrai un\n" -"messaggio di errore corretto: il sistema cerca di interpretare il valore\n" -"dato come un intervallo." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Inserisci il nome del proprietario della chiave" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "Inserisci un indirizzo di email opzionale (ma fortemente suggerito)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Inserisci un commento opzionale" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N per cambiare il nome.\n" -"C per cambiare il commento.\n" -"E per cambiare l'indirizzo di email.\n" -"O per continuare con la generazione della chiave.\n" -"Q per abbandonare il processo di generazione della chiave." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Rispondi \"si\" (o \"y\") se va bene generare la subchiave." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Quando firmi l'user ID di una chiave dovresti prima verificare che questa\n" -"appartiene alla persona indicata nell'user ID. utile agli altri sapere\n" -"con quanta attenzione lo hai verificato.\n" -"\n" -"\"0\" significa che non fai particolari affermazioni sull'attenzione con " -"cui\n" -" hai ferificato la chiave.\n" -"\n" -"\"1\" significa che credi che la chiave sia posseduta dalla persona che dice " -"di\n" -" possederla, ma non hai o non hai potuto verificare per niente la " -"chiave.\n" -"\n" -"\"2\" significa che hai fatto una verifica superficiale della chiave. Per " -"esempio\n" -" potrebbe significare che hai verificato l'impronta digitale e " -"confrontato\n" -" l'user ID della chiave con un documento di identit con fotografia.\n" -"\n" -"\"3\" significa che hai fatto una verifica approfondita della chiave. Per " -"esempio\n" -" potrebbe significare che hai verificato di persona l'impronta digitale " -"con\n" -" il possessore della chiave e hai controllato, per esempio per mezzo di\n" -" un documento di identit con fotografia difficile da falsificare (come\n" -" un passaporto), che il nome del proprietario della chiave corrisponde a\n" -" quello nell'user ID della chiave, e per finire che hai verificato\n" -" (scambiando dei messaggi) che l'indirizzo di email sulla chiave " -"appartiene\n" -" al proprietario.\n" -"\n" -"Nota che gli esempi indicati per i livelli 2 e 3 sono *solo* esempi. Alla " -"fine\n" -"sta a te decidere cosa significano \"superficiale\" e \"approfondita\" " -"quando\n" -"firmi chiavi di altri.\n" -"\n" -"Se non sai cosa rispondere, rispondi \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Rispondi \"si\" se vuoi firmare TUTTI gli user ID" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Rispondi \"si\" se vuoi davvero cancellare questo user ID.\n" -"Tutti i certificati saranno persi!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Rispondi \"si\" se va bene cancellare la subchiave" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Questa una firma valida per la chiave. Normalmente non vorresti " -"cancellare\n" -"questa firma perch pu essere importante per stabilire una connessione di\n" -"fiducia alla chiave o a un'altra chiave certificata da questa chiave." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Questa firma non pu essere verificata perch non hai la chiave " -"corrispondente.\n" -"Dovresti rimandare la sua cancellazione finch non saprai quale chiave " -"stata\n" -"usata perch questa chiave potrebbe stabilire una connessione di fiducia\n" -"attraverso una chiave gi certificata." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "La firma non valida. Ha senso rimuoverla dal tuo portachiavi." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Questa una firma che collega l'user id alla chiave. Solitamente non una\n" -"buona idea rimuovere questo tipo di firma. In realt GnuPG potrebbe non " -"essere\n" -"pi in grado di usare questa chiave. Quindi fallo solo se questa autofirma " -"non\n" -" valida per qualche ragione e ne disponibile un'altra." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Cambia le preferenze di tutti gli user ID (o solo di quelli selezionati) " -"con\n" -"la lista di preferenze corrente. L'orario di tutte le autofirme coinvolte\n" -"sar aumentato di un secondo.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Inserisci la passphrase, cio una frase segreta \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Ripeti l'ultima passphrase per essere sicuro di cosa hai scritto." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Inserisci il nome del file a cui si riferisce la firma." - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Rispondi \"si\" se va bene sovrascrivere il file." - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Inserisci il nuovo nome del file. Se premi INVIO sar usato il nome\n" -"predefinito (quello indicato tra parentesi)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Dovresti specificare un motivo per questa certificazione. A seconda del\n" -"contesto hai la possibilit di scegliere tra questa lista:\n" -" \"Key has been compromised\"\n" -" Usa questo se hai un motivo per credere che una persona non " -"autorizzata\n" -" abbia avuto accesso alla tua chiave segreta.\n" -" \"Key is superseded\"\n" -" Usa questo se hai sostituito questa chiave con una pi recente.\n" -" \"Key is no longer used\"\n" -" Usa questo se hai mandato in pensione questa chiave.\n" -" \"User ID is no longer valid\"\n" -" Usa questo per affermare che l'user ID non dovrebbe pi essere usato;\n" -" solitamente usato per indicare un indirizzo di email non valido.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Se vuoi, puoi digitare un testo che descrive perch hai emesso\n" -"questo certificato di revoca. Per favore sii conciso.\n" -"Una riga vuota termina il testo.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Non disponibile un aiuto" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Non disponibile un aiuto per `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "errore creando il portachiavi `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "portachiavi `%s' creato\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "rebuild della cache del portachiavi fallito: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "ATTENZIONE: esistono due file con informazioni confidenziali.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s quello non modificato\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s quello nuovo\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Per favore risolvete questo possibile problema di sicurezza\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "controllo il portachiavi `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "Per ora sono state controllate %lu chiavi (%lu firme)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "Sono state controllate %lu chiavi (%lu firme)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: portachiavi creato\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ " necessario eseguire di nuovo GnuPG in modo che possa leggere il nuovo\n" -#~ "file delle opzioni\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "cabiamento dei permessi di `%s' fallito: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOME=VALORE|usa questi dati per una nota" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "il primo carattere del nome di una nota deve essere una lettera o un\n" -#~ "underscore\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "nel nome di una nota i punti devono avere altri caratteri intorno\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "ATTENZIONE: Questa chiave ha gi un ID fotografico.\n" -#~ " Aggiungerne un altro pu confondere alcune versioni di PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr " possibile avere un solo ID fotografico su ogni chiave.\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Impronta digitale:" - -#~ msgid " Fingerprint:" -#~ msgstr " Impronta digitale:" diff --git a/po/ja.po b/po/ja.po deleted file mode 100644 index 8af08559c..000000000 --- a/po/ja.po +++ /dev/null @@ -1,4671 +0,0 @@ -# Japanese messages for GnuPG -# Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. -# IIDA Yosiaki , 1999, 2000, 2002. -# Yoshihiro Kajiki , 1999. -# This file is distributed under the same license as the GnuPG package. -# Special thanks to "Takashi P.KATOH". -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.7\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-05-10 07:28-0400\n" -"Last-Translator: IIDA Yosiaki \n" -"Language-Team: Japanese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=EUC-JP\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "ٹ: Ф꡼ѤƤޤ!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "ܺ٤http://www.gnupg.org/faq.html\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "Ѥߤΰʥ꡼ʤˤϼ¹ԤǤޤ\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(ŪˤϸäץѤΤǤ礦)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "yes" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "yY" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "no" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "quit" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "Ūʥ顼" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "̤ΤΥѥåȡפǤ" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "̤ΤΥСǤ" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "̤Τθ르ꥺǤ" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "̤Τ󥢥르ꥺǤ" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "Ǥ" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "̩Ǥ" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "̾Ǥ" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "åࡦ顼" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "ѥե졼Ǥ" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "Ĥޤ" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "̤ΤΰŹ楢르ꥺǤ" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "ؤޤ" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "̵ʥѥåȤǤ" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "̵Ǥ" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "Υ桼IDϤޤ" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "̩ޤ" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "ä̩ѤƤޤ" - -#: util/errors.c:72 -msgid "not supported" -msgstr "ݡȤƤޤ" - -#: util/errors.c:73 -msgid "bad key" -msgstr "Ǥ" - -#: util/errors.c:74 -msgid "file read error" -msgstr "եɽФ顼" - -#: util/errors.c:75 -msgid "file write error" -msgstr "եνߥ顼" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "̤Τΰ̥르ꥺǤ" - -#: util/errors.c:77 -msgid "file open error" -msgstr "ե뤬ޤ" - -#: util/errors.c:78 -msgid "file create error" -msgstr "եκ顼" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "ѥե졼̵Ǥ" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "̤θ르ꥺǤ" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "̤ΰŹ楢르ꥺǤ" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "̤Τν̾饹Ǥ" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "ѥǡ١Υ顼Ǥ" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPIǤ" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "꥽³Ǥ" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "ؤ̵Ǥ" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "Ǥ" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "桼IDν񼰤ޤ" - -#: util/errors.c:89 -msgid "file close error" -msgstr "ե뤬Ĥޤ" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "ե̾ѹ顼" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "եκ顼" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "ͽ̥ǡǤ" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "դͤƤޤ" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "ѤǤʤ르ꥺǤ" - -#: util/errors.c:95 -msgid "file exists" -msgstr "ե뤬¸ߤƤޤ" - -#: util/errors.c:96 -msgid "weak key" -msgstr "夤Ǥ" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "̵ʻǤ" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URIǤ" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URIϥݡȤƤޤ" - -#: util/errors.c:100 -msgid "network error" -msgstr "ͥåȥ顼" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "Ź沽Ƥޤ" - -#: util/errors.c:103 -msgid "not processed" -msgstr "̤" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "ѤǤʤǤ" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "ѤǤʤ̩Ǥ" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "СΥ顼" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... ХǤ (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "Х򸫤Ĥ褦Ǥ ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "`%s'ޤ: %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "`%s'Ĵ٤뤳ȤǤޤ: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' ̤ΥեǤϤޤ - ̵\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr ": random_seed ե϶Ǥ\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "ٹ: ̵ʥ random_seed ե - Ȥޤ\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "`%s'ɤޤ: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr ": random_seed եι򤷤ޤ\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "`%s'Ǥޤ: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "`%s'˽񤱤ޤ: %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "`%s'Ĥޤ: %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "ٹ: ФҤȤƤޤ!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"ܤƤҤϡŹѤȤƤϤޤĤǡ\n" -"Ǥޤ!\n" -"\n" -"ΥץǡڻѤƤϤޤ!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"ʬĹޤOSä𻨤\n" -"Ǥ褦Ƥ! (%dХȤޤ)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@ޥ:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[ե]|̾" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[ե]|ꥢ̾" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "ʬΥ̾" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "ǡŹ沽" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[ե뷲]|ե뷲Ź沽" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "Ź沽ˤоΰŹˡΤߤ" - -#: g10/g10.c:315 -msgid "store only" -msgstr "¸Τ" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "ǡ ()" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[ե뷲]|ե뷲" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "̾򸡾" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "ΰ" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "Ƚ̾ΰ" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "ν̾򸡾" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "Ȼΰ" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "̩ΰ" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "Ф" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "ؤ鸰" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "̩ؤ鸰" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "˽̾" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "Ū˽̾" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "˴Ǥʤ褦˽̾" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "˴Ǥʤ褦Ū˽̾" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "ؤν̾Խ" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "˴" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "񤭽Ф" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "С˸񤭽Ф" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "С鸰ɤ߹" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "Сθ򸡺" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "С鸰" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "ɹ/ʻ" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "ѥåΤߤΰ" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "ͭԤѤͤ񤭽Ф" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "ͭԤѤͤɤ߹" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "ѥǡ١򹹿" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "ƤƤʤѥǡ١򹹿" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "줿ѥǡ١" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "" -"եޤɸϤ\n" -"" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "եޤɸϤ" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|르ꥺ [ե]|å" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"ץ:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "ASCII" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|̾|̾Ѥ˰Ź沽" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "" -"|̾|μԤȤ\n" -"̾פ" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "μԤ˴θ" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "" -"̾ˤΥ桼id\n" -"" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "" -"|N|̥٥N\n" -"(0󰵽)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "ƥȡ⡼ɤ" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "ϥեȤƻ" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "Ĺ" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "Ť" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "üԻ" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "Ūv3̾" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "v3̾ʤ" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "Ūv4̾" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "v4̾ʤ" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "Ź沽ˤϾMDC" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "Ź沽ˤФMDCѤʤ" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "̵ѹ" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "gpgȤ" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "Хå⡼: ǧά" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "" -"Ƥμyes\n" -"Ȥߤʤ" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "" -"Ƥμno\n" -"Ȥߤʤ" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "ؤΰˤθؤɲ" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "ˤ̩ؤɲ" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "θ븰ؤɽ" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "" -"|̾|̩Ȥ\n" -"̾פ" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|ۥ|θˤθС" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "" -"|CHARSET̾|ücharsetCHARSET̾\n" -"" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "" -"ե뤫饪ץ\n" -"ɤ߹" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "" -"|ե뵭һ|Υե뵭һҤ˾֤\n" -"񤭽Ф" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "" -"|ե|ơե\n" -"񤭽Ф" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|ID|θŪ˿Ѥ" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "" -"|ե|ĥ⥸塼Υե\n" -"ɤ߹" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "" -"RFC1991˵Ҥ줿⡼ɤ\n" -"" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"ѥåȤȰŹȽ̾Υץ\n" -"OpenPGPο" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"ѥåȤȰŹΥץ\n" -"PGP 2.xο" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|ѥե졼⡼N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "" -"|̾|ѥե졼ˡ̾פΥ\n" -"󥢥르ꥺ" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "" -"|̾|ѥե졼ˡ̾פΰŹ\n" -"르ꥺ" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "" -"|̾|̾פΰŹ楢르ꥺ\n" -"" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "" -"|̾|̾פΥå\n" -"르ꥺ" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "" -"|̾|̾פΰ̥르ꥺ\n" -"" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "" -"ŹѥåȤθIDե\n" -"" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "եIDɽ" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "եIDɽʤ" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" -"եID륳ޥɹ\n" -"" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(ޥɤȥץΰϡ\n" -"ޥ˥奢롦ڡ)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -":\n" -"\n" -" -se -r Bob [ե] 桼Bobؤν̾ȰŹ沽\n" -" --clearsign [ե] ꥢ̾\n" -" --detach-sign [ե] ʬΥ̾\n" -" --list-keys [̾] ɽ\n" -" --fingerprint [̾] ɽ\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Х򸫤Ĥ ޤǤ𤯤\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Ȥ: gpg [ץ] [ե] (إפ -h)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -": gpg [ץ] [ե]\n" -"̾ڡŹ沽\n" -"ưϡϥǡ˰¸\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"ݡȤƤ륢르ꥺ:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "Ȥ: gpg [ץ] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "ޥɤξ\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "ٹ: %s \"%s\" ΰǤʤͭ\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "ٹ: %s \"%s\" ΰǤʤ\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "ٹ: %s \"%s\" ΰǤʤͭ\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "ٹ: %s \"%s\" ΰǤʤ\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr ": Υץ󡦥ե`%s'ޤ\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr ": Υץ󡦥ե`%s'ޤ\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "ץ󡦥ե`%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "`%s'饪ץɤ߹ߤޤ\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%sʸǤϤޤ\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "СURIǽ\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s: ̵ʥե롦С%d\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "̵Ǥ" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s: ̵ʥե롦С%d\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "ؤ̵Ǥ" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "exec-path%sǽ\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "ٹ: ץΥե뤬Ǥ뤳Ȥޤ!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "ٹ: %s%sͥ\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr ": %sѤޤ!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s%sȤȤѤ뤳ȤϤǤޤ!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s%sȤȤѤƤ̵̣Ǥ!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "--pgp2⡼ɤǤʬΥ̾ꥢ̾Ǥޤ\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "--pgp2⡼ɤǤϽ̾ȰŹƱˤǤޤ\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "--pgp2ꤷ顢(ѥפǤʤ) եꤻͤФʤޤ\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "--pgp2⡼ɤΥåŹ沽ǤIDEAŹ椬׵ᤵޤ \n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "ΥåPGP 2.xǤϻѤǤʤ⤷ޤ\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "򤵤줿Ź楢르ꥺ̵Ǥ\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "򤵤줿󥢥르ꥺ̵Ǥ\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "򤵤줿󥢥르ꥺ̵Ǥ\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "̥르ꥺ%d..%dϰϤǤʤФʤޤ\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-neededͤɬפǤ\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed1礭ͤɬפǤ\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth1255ϰϤǤʤФʤޤ\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr ": ñS2K⡼(0)λѤˤ϶ȿФޤ\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "̵S2K⡼ɡ013ǤʤФʤޤ\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "̵default-check-level0123ǤʤФʤޤ\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "̵ͥ\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "̵ͥ\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "̵ͥ\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "̵ͥ\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "ѥǡ١ν˼Ԥޤ: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [ե̾]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [ե̾]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [ե̾]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [ե̾]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [ե̾]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [ե̾]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [ե̾]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [ե̾]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key 桼id" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key 桼id" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key 桼id" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key 桼id" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key 桼id [ޥ]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "%sޤ: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [桼id] []" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "˼Ԥޤ: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "˼Ԥޤ: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "̵ʥϥå塦르ꥺ`%s'Ǥ\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[ե̾]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Ϥޤå򥿥פƤ ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "`%s'ޤ\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"̾ˤʸɥåȡΤߤѤ\n" -"'='ǽʤФʤޤ\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "̾ͤʸѤƤϤޤ\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "줿ݥꥷURL̵Ǥ\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "줿̾ݥꥷURL̵Ǥ\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr ": %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "̵إå: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "إå: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "̵ʥꥢ̾إå\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "ҤΥꥢ̾\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "̵ʥåǥפ줿: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "ͽ:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "̵64ʸ%02xȤФޤ\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "ե᤹ޤ (CRCޤ)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "ե᤹ޤ (CRCˤޤ)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRCν񼰤ޤ\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "CRC顼%06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "ե᤹ޤ (ˤޤ)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "ιԤ˥顼ޤ\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "ͭOpenPGPǡĤޤ\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "̵: ԤĹ%dʸĶƤޤ\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -" quoted printable ʸޤ餯ХΤ\n" -"MTAѤΤǤ礦\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "ͳϻꤵƤޤ" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Ȥ꤫äƤޤ" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "ѥޤ" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Ϥ⤦ȤƤޤ" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "桼ID⤦ͭǤޤ" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "˴ͳ: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Ŭ: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"٤ꤵƤޤ:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"¾Υ桼θڤ뤿ˡΥ桼ο٤\n" -"(ѥݡȤ򸫤Ƥäꡢ¾Ⱦȹ礷...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = ̤\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = Ѥ ʤ\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = ٿѤ\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = ˿Ѥ\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Ū˿Ѥ\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = ܤ򸫤\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = ᡼󡦥˥塼\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = θϤȤФ\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = λ\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "ʤη? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "ˤθŪ˿Ѥޤ? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Ū˿Ѥؤξ:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "%08lX: ˴ѤߤǤ!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Ǥ⤳θȤޤ? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "%08lX: ˴ѤߤǤ!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: ϴڤǤ\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "%08lX: θܿͤΤΤɤθڼʤޤ\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: θϿѤǤ \n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: θϼºݤܿͤΤΤǤ\n" -"ޤ\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "θϤ֤ܿͤΤΤǤ\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "θϲ桹ΤΤǤ\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"θܿͤΤΤɤοǤ \n" -"ԤȤ *μ¤* 򤷤Ƥʤˤϡ\n" -"μˤnoƤ\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "ٹ: ѤǤʤѤƤޤ!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "ٹ: θܿͤˤä˴Ƥޤ!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " ̾ʪʤȤ⤢롢ȤȤǤ\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "ٹ: ܿͤˤä˴Ƥޤ!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr ": θϻѶػߤꤵƤޤ\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr ": θϴڤǤ!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "ٹ: θϿѤǤ̾ǾƤޤ!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " ν̾ܿͤΤΤɤθڼʤޤ\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "ٹ: θϿѤǤ !\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " ν̾Ϥ餯 ʪ Ǥ\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "ٹ: θϽʬ˿ѤǤ̾ǾƤޤ!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " ν̾ܿͤΤΤɤοǤޤ\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: å: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: å: ϴˤޤ\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "桼IDꤷƤޤ (-rפѤޤ礦) \n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"桼IDϡԤǽλ: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Υ桼IDϤޤ\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "å: ϴμԤȤѤߤǤ\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "ϻѶػߤǤ\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "å: ѤߤǤ\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "μ`%s'Ĥޤ\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: å: ϻѶػߤǤ\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "ͭʥɥ쥹ޤ\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "%c%luͭǤϤޤ\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "%c%luνʣ\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "¿`%c'\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "ʸ̵ʸޤ\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "ʽ̾񤭹ߤޤ\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "ʽ̾񤭹ߤޤ\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "̾б븰񤭹ߤޤ\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "̵ʸ%uӥåȤˤޤ\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "%uӥåȤ˴ݤޤ\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "ʸμ򤷤Ƥ:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSAElGamal ()\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (̾Τ)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (Ź沽Τ)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (̾ȰŹ沽)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (̾Τ)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (Ź沽Τ)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (̾ȰŹ沽)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "ɤˤޤ? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Υ르ꥺȿФƤޤ - Ǥޤ? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "̵Ǥ\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"%sФޤ\n" -" ǾθĹ 768 ӥå\n" -" θĹ 1024 ӥå\n" -" ο侩Ĺ 2048 ӥå\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "ɤθĹˤޤ? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSAθĹ5121024ޤǤǤ\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "ĹޤRSAϺǾǤ1024Ǥ\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "ĹޤǾǤ768Ǥ\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "Ĺ礭ޤ%dǤ\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"2048礭ʸĹϡ׻֤ ĹʤΤ\n" -"侩ޤ!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "θĹˤǤ? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"狼ޤʤΥ˥䥭ܡϤϡ\n" -"ˤȼǤ뤳Ȥ򿴤αƤƤ!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "׵ᤵ줿Ĺ%uӥå\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "%uӥåȤ˴ݤޤ\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"δ¤Ƥ\n" -" 0 = ̵\n" -" = ͭ n \n" -" w = ͭ n \n" -" m = ͭ n \n" -" y = ͭ n ǯ\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"̾δ¤Ƥ\n" -" 0 = ̵\n" -" = ͭ n \n" -" w = ͭ n \n" -" m = ͭ n \n" -" y = ͭ n ǯ\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "֤ͭ? (0)" - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "֤̾ͭ? (0)" - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "̵\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s̵¤Ǥ\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s%sˤƴڤˤʤޤ\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"ΥƥǤϡ2038ǯʹߤդɽǤޤ󤬡\n" -"2106ǯޤǤʤǤޤ\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "ǤǤ (y/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"ʤθƱꤹ뤿˥桼IDɬפǤ\n" -"ΥեȤ̾ȡŻҥ᡼롦ɥ쥹\n" -"ν񼰤ǥ桼IDޤ:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "̾: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "̵̾ʸޤ\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "̾ǻϤƤϤޤ\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "̾5ʸʾǤʤФʤޤ\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Żҥ᡼롦ɥ쥹: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "ͭŻҥ᡼롦ɥ쥹ǤϤޤ\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr ": " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Ȥ̵ʸޤ\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "ʤʸ`%s'ȤäƤޤ\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Υ桼IDꤷޤ:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Żҥ᡼Υɥ쥹̾䥳Ȥʤ褦\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoQq" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "̾(N)(C)Żҥ᡼(E)ѹޤϽλ(Q)? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "̾(N)(C)Żҥ᡼(E)ѹޤOK(O)λ(Q)? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "ޤ顼Ƥ\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"̩ݸ뤿˥ѥե졼ޤ\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "ѥե졼ȷ֤Ƥޤ󡣺ϤƤ" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"ѥե졼ɬפʤ褦Ǥ餯ϤʹͤǤ\n" -"ޤ! ³Ԥޤѥե졼ϡΥץ\n" -"Ρ--edit-keyץץǤĤǤѹǤޤ\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"ĹޤܡɤǤĤȤޥư\n" -"Ȥǥ˥Ȥ¾ΤȤ򤹤ȡҤ\n" -"𻨤礭ʤ䤹ʤΤǡᤷޤ\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSAФ1024ӥåȤˤʤޤ\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "ߤޤ\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "`%s'ظ񤭹ߤޤ\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "`%s'̩񤭹ߤޤ\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "߲ǽʸؤĤޤ: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "߲ǽ̩ؤĤޤ: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "`%s'νߥ顼: %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "̩`%s'νߥ顼: %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "̩ꡢ̾ޤ\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "Ū˿ѤȤƵϿޤ\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"θϰŹ沽ˤϻѤǤʤȤդƤŹ沽Ԥˤϡ\n" -"--edit-keyץޥɤѤƤ\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "˼Ԥޤ: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "%lṳˤǤޤ (ιԤפΤ뤤Ǥ礦)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "%lṳˤǤޤ (ιԤפΤ뤤Ǥ礦)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr ": v3κϡOpenPGPŬ礷ޤ\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "˺ޤ? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "Υޥɤ--outputϵǽޤ\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: ޤ: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "ѥե졼κ顼: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s'ϴ˰̺ѤߤǤ\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: ٹ: ΥեǤ\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "--pgp2⡼ɤǤ2048ӥåȰʲRSAǰŹ沽Ǥޤ\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "`%s'ɤ߹ߤޤ\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "Ź沽褦ȤƤ븰IDEAŹȤޤ\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr ": Ź楢르ꥺ%dͥäƤޤ\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "%s⡼ɤǤΥޥɤѤ뤳ȤϤǤޤ\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%sŹ沽 : %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "`%s'Ĥޤ: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "֥åɹߥ顼: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr " %08lX: rfc2440θǤϤޤ - å\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr " %08lX: ݸƤޤ - å\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr " %08lX: PGP 2.xθǤ - å\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "ٹ: 񤭽ФƤޤ\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "pkåΥȥ꡼¿ޤ - Ѷػ\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[桼idĤޤ]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "--allow-non-selfsigned-uidͭˤ줿̵ʸ%08lXǤ\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "%08lX縰%08lXѤޤ\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "%08lX: Τʤ̩Ǥå\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "%dΥ֥å򥹥åפޤ\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%luޤǽ\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "`%s'ɹߥ顼: %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr " ι: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " åפ: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " 桼IDʤ: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " ɹ: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " ѹʤ: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " 桼ID: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " : %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " ̾: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " ˴: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " ̩ɽФ: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " ̩ɹ: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " ̵ѹ̩: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " ɹ: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "%08lX: 桼IDޤ\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "%08lX: бޤ\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "%08lX: ̤ʽ̾Υ桼ID '%s'\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "%08lX: ѤǤ桼IDޤ\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "ʽ̾ΤʤǤ礦\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "%08lX: Ĥޤ: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr " %08lX: Ǥ - å\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "߲ǽʸؤĤޤ: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "`%s'ؤνФ\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "`%s'νߥ顼: %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "%08lX: ɤ߹ߤޤ\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "%08lX: ʣȹ礤ޤ\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "%08lX: θ֥å˰֤ŤǤޤ: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "%08lX: θ֥åɤ߹ޤ: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "%08lX: 桼ID1\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "%08lX: 桼ID%d\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "%08lX: ̾1\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "%08lX: ̾%d\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "%08lX: 1\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "%08lX: %d\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "%08lX: ѹʤ\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "̩ؤޤ: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "%08lX: ̩ɤ߹ߤޤ\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "%08lX: ̩ؤˤޤ\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "%08lX: ̩Ĥޤ: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "%08lX: ޤ - ˴ŬѤǤޤ\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "%08lX: ̵˴: %s - \n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "%08lX: ˴ɤ߹ߤޤ\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "%08lX: ̾б桼IDޤ\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"%08lX: 桼id \"%s\" ΥݡȤƤʤ르ꥺǤ\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "%08lX: 桼id \"%s\" μʽ̵̾Ǥ\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "%08lX: бޤ\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "%08lX: ݡȤƤʤ르ꥺǤ\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "%08lX: ̵бǤ\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "%08lX: ̵бǤ\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "%08lX: бޤ\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "%08lX: ̵бǤ\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "%08lX: ̵бǤ\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "%08lX: åפ桼ID '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "%08lX: åפ\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "%08lX: ФԲĤʽ̾ (饹%02x) - å\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "%08lX: ˴񤬸äꤵƤޤ - å\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "%08lX: ̵˴: %s - å\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "%08lX: ˴񤬸äꤵƤޤ - å\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "%08lX: ʣ桼IDθ - ʻ\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "ٹ: %08lX˴줿褦Ǥ: ˴%08lXΰФ\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "ٹ: %08lX˴줿褦Ǥ: ˴%08lXԺߡ\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "%08lX: ˴ɲ\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "%08lX: ľܸ̾ɲ\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[˴]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[ʽ̾]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "̵ʽ̾1\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "̵ʽ̾%d\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "ʤ1Ĥν̾򸡾ڤޤ\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "ʤ%dĤν̾򸡾ڤޤ\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "顼Τ1Ĥν̾򸡾ڤޤ\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "顼Τ%dĤν̾򸡾ڤޤ\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "ͭʼʽ̾Τʤ桼ID1ĸ\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "ͭʼʽ̾Τʤ桼ID%dĸ\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "桼ID \"%s\" ˴Ƥޤ" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Ǥ⤳θ˽̾Ǥ? (y/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " ̾ǽ\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "ٹ: `%s'϶ΥեǤ\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"\"%s\" ˤ뺣Τʤν̾\n" -"̾Ǥ\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Фǽʽ̾˳ʾ夲Ǥ? (y/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"\"%s\" ˤ뺣Τʤν̾\n" -"̾Ǥ\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Фǽʽ̾˳ʾ夲Ǥ? (y/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" ϸ%08lXǤ⤦̾Ƥޤ\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" ϸ%08lXǤ⤦̾Ƥޤ\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "%08lXǽ̾ΤϤޤ\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "θϴڤǤ!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "θ%sǴ¤ڤޤ\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Ʊ˽̾ڤˤǤ? (Y/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "--pgp2⡼ɤǤPGP 2.xOpenPGP̾Ǥʤ⤷ޤ\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "θPGP 2.xǻѤǤʤʤޤ\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"̾褦ȤƤ븰ºݤ˾嵭̾οͤΤΤɤɤ\n" -"դƸڤޤ? 狼ʤ\"0\"ϤƤ\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) ޤ%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) ǧƤޤ%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) ǧޤ%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) ʤդƳǧޤ%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "ˤθˤʤθǽ̾Ƥ褤Ǥ: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "ʽ̾ΤʤǤ礦\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"̾ϽФԲĤꤵޤ\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"̾˴ԲĤꤵޤ\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"̾ϽФԲĤꤵޤ\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"̾˴ԲĤꤵޤ\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"θǧƤޤ\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"θϰǧޤ\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"θϡʤդƳǧޤ\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "˽̾ޤ? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "̾˼Ԥޤ: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "θݸƤޤ\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "縰̩ʬޤ\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "ݸƤޤ\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "θԽǤޤ: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"̩οѥե졼ϤƤ\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"ѥե졼ɬפʤ褦Ǥ\n" -"餯ϤʹͤǤϤޤ!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "˼¹Ԥޤ? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "ν̾˰ưޤ\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "Υ˥塼λ" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "¸ƽλ" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "Υإפ򸫤" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "򸫤" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "ȥ桼IDΰ" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "桼ID N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "̾ΰ" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "ؽ̾" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "Ū˽̾" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "˴Ǥʤ褦ؽ̾" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "˴Ǥʤ褦Ū˽̾" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "桼IDɲ" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "եIDɲ" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "桼IDκ" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "ɲ" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "κ" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "ɲ" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "̾κ" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "ͭ¤ѹ" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "桼IDˤ" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "̩ȸΰؤ" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "ΰ (ѡ)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "ΰ (Ĺ)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "ΰ" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "ΰ򹹿" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "ѥե졼ѹ" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "ͭԿѤѹ" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "̾˴" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "˴" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "λѤػߤ" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "λѤĤ" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "եIDɽ" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "ϥХå⡼ɤǤϤǤޤ\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "̩֥å`%s'ɹߥ顼: %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "̩ѤǤޤ\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "ޥ> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "μ¹Ԥˤ̩ޤ\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "ޤtoggleץޥɤȤäƤ\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "˴Ƥޤ" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "桼ID˽̾ޤ? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr ": ޤ̾桼ID򤷤ޤ\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "%s⡼ɤǤΥޥɤѤ뤳ȤϤǤޤ\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "桼ID򾯤ʤȤҤȤ򤷤Ƥ\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "ǸΥ桼IDϺǤޤ!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "򤷤桼ID˺ޤ? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Υ桼ID˺ޤ? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "򾯤ʤȤҤȤ򤷤Ƥ\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "򤷤˺ޤ? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "θ˺ޤ? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "򤷤˴ޤ? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "θ˴ޤ? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "򤷤桼ID˹ޤ? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "˹ޤ? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "ѹ¸ޤ? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "¸˽λޤ? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "˼Ԥޤ: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "̩ι˼Ԥޤ: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "̵ѹʤΤǹϤޤ\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "̵ʥޥ (helpפ򻲾)\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "θ%s%s%sˤä˴줿褦Ǥ\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (ǥꥱ)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX : %s : %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " trust: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "θϻѶػߤꤵƤޤ" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! ˴ѤߤǤ: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- Ǥä˴ȯ\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? ˴ǧ㳲: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"ץƵưޤǡɽ줿ͭʤ⤷ʤ\n" -"ȤȤǰƬ֤Ƥ\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"ٹ: PGP2θǤեIDɲäǡǤPGPϡ\n" -" θݤ뤫⤷ޤ\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "ǤɲäǤ? (y/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "PGP2θˤϥեIDɲäǤʤ⤷ޤ\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "̾ޤ? (y/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "̵ʽ̾ޤ? (y/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "̤Τν̾ޤ? (y/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "μʽ̾˺ޤ? (y/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%dĤν̾ޤ\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%dĤν̾ޤ\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Ƥޤ\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "ĹϤƤ" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "̩ȤƤ\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "⡹1Ĥ򤷤Ƥ\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "ͭ¤ѹޤ\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "縰ͭ¤ѹޤ\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "v3ͭ¤ѹǤޤ\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "̩ؤб̾ޤ\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "桼ID򤭤äҤȤ򤷤Ƥ\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "%08lX: 桼id \"%s\" μʽ̵̾Ǥ\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "%d֤Υ桼IDϤޤ\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "%d֤Ϥޤ\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "桼ID: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"ʤθ%08lX%s˽̾Ƥޤ\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"ʤθ%08lX%sŪ˽̾Ƥޤ\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "ν̾%sǴڤǤ\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Ǥ˴Ǥ? (y/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "ν̾ˤ˴ޤ? (y/N) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Υ桼ID˽̾ޤ:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " %08lX%s%s%s˽̾Ƥޤ\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " %08lX%s˴Ƥޤ\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "ν̾˴褦ȤƤޤ:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " %08lX%s%s˽̾Ƥޤ\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (ФԲ)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "˴˺ޤ? (y/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "̩ޤ\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "%s򥵥%ldθ0x%08lX (uid %d) ΥեIDȤɽ\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "̾ݥꥷ: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "̾ݥꥷ: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "ٹ: ̵ǡޤ\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "̾: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "̾: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "ͤˤɤޤ" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [ͭ: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "Ȼΰ" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "̵ʥϥå塦르ꥺ`%s'Ǥ\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%sŹ沽줿ǡ\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "̤ΤΥ르ꥺˤŹ %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "%08lXǤ\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "ǰŹ沽줿ǡ: DEKǤ\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "%u-ӥå%s, ID %08lXǰŹ沽%sˤǤޤ\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "%s, ID %08lXǰŹ沽ޤ\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "˼Ԥޤ: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "%sŹ沽줿ǡ\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "IDEAŹǽʤΤǡŷŪǤ%sѤ褦ȤƤޤ\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "ٹ: Ź沽줿åϲ⤵Ƥޤ!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "˼Ԥޤ: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr ": Ԥϡˤפ褦˵Ƥޤ\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "Υե̾='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "Ω˴gpg --importפȤäŬѤƤ\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr ": " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "ݥꥷ: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "̾θڤά\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "¿Ž̾ϼ갷ޤ\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "%.*s %sID %08lXˤ̾\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr " ̾: \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "ڤν̾: \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "̾: \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[Գ]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " ̾ \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "̾򸡾ڤǤޤ: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "ʬΥ̾Ǥޤ\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "饹0x%02xΩ̾\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "Ť (PGP 2.x) ν̾\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "proc_tree() ̵ʥѥåȤ򸡽Фޤ\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "פ̵ˤǤޤ: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "¸Υ르ꥺϻѤ٤ǤϤޤ!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"ΰŹ楢르ꥺȿФƤޤ\n" -"äɸŪʥ르ꥺѤƤ!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "IDEAŹΥץ饰󤬤ޤ\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "ܺ٤ϡhttp://www.gnupg.org/why-not-idea.html\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "ٹ: %sȿФƤ륪ץǤ\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "ٹ: %sȿФƤ륪ץǤ\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "\"--keyserver-options %s\"˻ȤäƤ\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "Υ르ꥺ%dϻѤǤޤ\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "%dβ̥ѥåȤ˥ƥ롦ӥåȤȯ\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "ΥågpgȤ̵Ǥ\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "ȤΥ饤pidǤޤ\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "ѤΥСɽФFDǤޤ\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "ѤΥСFDǤޤ\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "GPG_AGENT_INFOĶѿν񼰤ޤ\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "gpg-agentץȥ롦С%dϥݡȤƤޤ\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "`%s'³Ǥޤ: %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "gpg-agentȤ̿㳲\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "Ȥ˾㳲: Ѷػ\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (縰ID %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Υ桼̩Υåˤϥѥե졼ޤ:\n" -"\"%.*s\"\n" -"%uӥå%s, ID %08lXդ%s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "ѥե졼\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "ѥե졼\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "ѥե졼Ĺ᤮ޤ\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "Ȥ̵ʱ\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "桼ˤä\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "Ȥ˾㳲: Ȥ0x%lxֵ\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Υ桼̩Υåˤ\n" -"ѥե졼ޤ: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%uӥå%s, ID %08lXդ%s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "Хå⡼ɤǤϥѥɤ礻Ǥޤ\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "ѥե졼: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "ѥե졼: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"ǡ¸Ƥޤ\n" -"¸ˤϡ--outputץץѤƤ\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "`%s'κ顼: %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "ʬΥ̾\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "ǡե̾: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "ɸϤɹ ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "̾줿ǡޤ\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "̾줿ǡ`%s'ޤ\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "ƿ̾μѤǤ̩%08lXѤޤ ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "λƿ̾μѤǤ\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "DEKˤ켰ΰŹϥݡȤƤޤ\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "ݸ르ꥺ%d%s̤ΤԲĤǤ\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr ": Ź楢르ꥺ%dͥäƤޤ\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr ": ̩%08lX%sǴڤǤ\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "%08lX: ˴ѤߤǤ!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "%08lXHKPС%s׵\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "С鸰ɤ߹ޤ: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "`%s'ؤ顼: %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "`%s'ؤ (=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "`%s'ؤ˼Ԥޤ: =%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "\"%s\"HKPС%s鸡\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "С򸡺Ǥޤ: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "̩ʬޤ\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "ݸ르ꥺ%d%sϥݡȤƤޤ\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "̵ʥѥե졼ǤϤƤ" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "ٹ: 夤򸡽Фޤѥե졼ѹƤ\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "ȿФ줿16ӥåȤΥå̩ݸ\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"PGPElGamalǤ\n" -"̾ѤˤϡθϰǤ ʤ Ǥ!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "Ͻ̾%luø˺Ƥޤ\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "Ͻ̾%luø˺Ƥޤ\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "%lṳˤǤޤ (ιԤפΤ뤤Ǥ礦)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "%lṳˤǤޤ (ιԤפΤ뤤Ǥ礦)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr ": ̾%08lXϴڤǤ%s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "̤ΤΥƥ롦ӥåȤäΤǡ̾Ȥߤʤޤ\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "ٹ: ݥꥷurl%%ĥǽ (礭)̤ĥѡ\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "ٹ: ݥꥷurl%%ĥǽ (礭)̤ĥѡ\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "줿̾θڤ˼: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s̾̾: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "ٹ: `%s'϶ΥեǤ\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "--pgp2⡼ɤǤPGP 2.xθǽ̾ǤǤ\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "%sǤޤ: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr ": Ź楢르ꥺ%dͥäƤޤ\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "̾:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "--pgp2⡼ɤǤPGP 2.xθǥꥢ̾Ǥޤ\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%sŹ沽Ѥޤ\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "%dʸʾĹΥƥȹԤϻѤǤޤ\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "ϹԤĹ%dʸĶƤޤ\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "ѥǡ١ 쥳%lu: ˼Ԥޤ: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "ѥǡ١ 쥳%lu: ߤ˼ (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "ѥǡ١Υȥ󥶥礭ޤ\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: Ǥޤ: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: 񤬤ޤ!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: åǤޤ\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: åǤޤ\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: Ǥޤ: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: С󡦥쥳ɤκ˼Ԥޤ: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: ̵ʿѥǡ١\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: ѥǡ١Ǥޤ\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: ̵ʿѥǡ١\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: ϥåɽκ˼Ԥޤ: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: С󡦥쥳ɤι顼: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: С󡦥쥳ɤɽФ顼: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: С󡦥쥳ɤνߥ顼: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "ѥǡ١: ˼Ԥޤ: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "ѥǡ١: ɽФ˼ (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: ѥǡ١եǤϤޤ\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: 쥳ֹ%lu֤ΥС󡦥쥳\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: ̵ʥե롦С%d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: 쥳ɤɽФ顼: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: ǥ쥯ȥ꡼쥳ɤνߥ顼: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: 쥳ɤν˼Ԥޤ: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: 쥳ɤɲä˼Ԥޤ: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"ѥǡ١Ƥޤgpg --fix-trustdbפ¹ԤƤ\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' 緿IDǤޤ\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "%08lX: Ѥ븰ȤƼޤ\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "%08lXѥǡ١ʣޤ\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr " %08lX: Ѥ븰θޤ - å\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "ѥ쥳%lu, ꥯȡ%d: ɽФ˼Ԥޤ: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "ѥ쥳%lu׵ᤵ줿%dǤϤޤ\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "ѥ쥳%lu, %d: ߤ˼Ԥޤ: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "ѥǡ١: Ʊ˼Ԥޤ: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "ѥǡ١θڤפǤ\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "ѥǡ١μθڤ%sǤ\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "ѥǡ١θ\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "%08lXĤޤ: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "Ū˿Ѥ븰%08lXθĤޤ\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "%dǸڡ̾Ѥ=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"̾򸡾ڤǤޤǤ̾ե\n" -"(.sig.asc)ޥɹԤκǽǤʤ\n" -"ʤʤȤǰƬˤƤ\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "Ϥ%uܤĹ뤫LFʤ褦Ǥ\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"ФƤ⤤ե饰ˤꤵƤޤ\n" -"ʪҤȤϤä˻Ȥޤ!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "`%s'򥹥å: ʣ\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "`%s'򥹥å: %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "å: ̩ϴˤޤ\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"`%s'򥹥å: PGPElGamalǤ\n" -"̾ѤˤϡǤϤޤ!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "ե`%s'ϴ¸ߤޤ" - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "񤭤ޤ (y/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: ̤Τγĥ\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "ե̾ϤƤ" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "ɸϤ˽񤭽Фޤ\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "̾줿ǡ`%s'ˤꤷޤ\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: ץ󡦥ե뤬Ǥޤ\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: 񤬤Ǥޤ: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: 񤬤Ǥޤ\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "ٹ: åоΰŹˡμ夤ǰŹ沽Ƥޤ\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "ŹѥåȤμ갷Ǿ㳲\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "夤Ǥޤ - Ƽ¹\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "оΰŹˡμ夤򤹤뤳ȤǤޤ%dߤޤ!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSAǤ160ӥåȤΥϥå塦르ꥺλѤɬפǤ\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "--yesפΤʤХå⡼ɤǤϤǤޤ\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "θؤޤ? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "̩Ǥ! ˺ޤ? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "֥åκ˼Ԥޤ: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "ͭԿѾ򥯥ꥢޤ\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "θˤ̩ \"%s\" ޤ!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "ޤ--delete-secret-keysץץǤƤ\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"ͤϡʤǤͤϡ軰Ԥ˷褷\n" -"󶡤ޤ󡣤ϡweb-of-trust μɬפǡ\n" -"(ŪˤǤ) web-of-certificates Ȥ̵طǤ" - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Web-of-Trustۤ뤿GnuPGϡɤθŪ˿Ѥ\n" -"ΤΤɬפޤϤդĤ̩˥Ǥ\n" -"븰ΤȤǤθŪ˿Ѥ뤳Ȥˤʤ顢\n" -"\"yes\"Ȥ\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "˴줿ȤʤСnoפƤ" - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "οѤǤʤȤʤСnoפƤ" - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "åꥢɥ쥹Υ桼IDϤƤ" - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Ѥ륢르ꥺ򤷤Ƥ\n" -"\n" -"DSA (̾DSS) ϡ̾ˤΤѤ뤳ȤǤŻҽ̾르\n" -"ǤDSA̾ElGamalˡ®˸ڤǤΤǡ\n" -"侩륢르ꥺǤ\n" -"\n" -"ElGamalϡ̾ȰŹ沽Ѥ뤳ȤǤ륢르ꥺǤ\n" -"OpenPGPǤϡΥ르ꥺΡְŹ沽Τߡפȡֽ̾+Ź沽\n" -"2Ĥˡ̤ƤޤºݤˤƱǤ̾\n" -"ΰʸˤϰѿ̤ˡ򤷤ʤФʤ\n" -"ޤ󡣤ΥץǤϤ줬ǽǤ¾OpenPGPμ\n" -"ϡֽ̾+Ź沽פˡᤷʤ⤷ޤ\n" -"\n" -"ǽθ(縰)ϡ̾˻ѤǤ븰ǤʤФʤޤ󡣤줬\n" -"Υ˥塼ˡְŹ沽ΤߡפElGamalΤʤͳǤ" - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"θRFC2440Ƥޤ侩ޤ\n" -"ʤʤ顢򥵥ݡȤƤʤץबꡢ\n" -"̾Ĺơڤˤ֤뤿Ǥ" - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "ĹϤƤ" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "yesפnoפƤ" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"ץץȤ˼񼰤ͤϤƤ\n" -"ISOդν (YYYY-MM-DD) ǤϤǤޤ顼\n" -"ɽʤǤ礦ꡢƥ֤ͤѴ\n" -"褦˻ߤޤ" - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "ۥ̾ϤƤ" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "ץǤŻҥ᡼Υɥ쥹Ϥ뤳Ȥ򶯤侩ޤ" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "ץΥȤϤƤ" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N ̾ѹ\n" -"C Ȥѹ\n" -"E Żҥ᡼Υɥ쥹ѹ\n" -"O ³ԡ\n" -"Q ߡ" - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "硢yes(ޤϡñˡy) Ƥ" - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Υ桼ID˽̾ȤϡΥ桼ID̾οͤ\n" -"ͭƤ롢ȤȤǧ٤Ǥʤɤ\n" -"տǧΤ¾οͤΤ餻ȡǤ\n" -"\n" -"\"0\" ϡʤɤտǧΤä˼ĥ\n" -" Ȥ̣Ǥ\n" -"\n" -"\"1\" ϡνͭԤȼĥƤͤθͭƤ롢\n" -" ʤϿƤϤΤΡǧƤʤäޤ\n" -" ϤǤʤäȤ̣Ǥϡڥ͡Ȥ\n" -" 桼θ˽̾Ρ֥ڥ륽ʡ׳ǧǤ\n" -"\n" -"\"2\" ϡʤγǧ򤷤Ȥ̣ǤȤ\n" -" λ򸡾ڤեIDˤƸΥ桼IDǧ\n" -" 礬Ǥ\n" -"\n" -"\"3\" ϡʤϰϤˤ錄기򸡾ڤȤ̣Ǥ\n" -" ȤСνͭܿͤȸλ򸡾ڤ(ѥݡ\n" -" Τ褦) ¤ΤĤեIDĤμʤǡν\n" -" ͭԤ̾Υ桼ID̾Ȱפ뤳Ȥǧ\n" -" ơ(Żҥ᡼θ򴹤ʤɤ) Żҥ᡼롦ɥ쥹\n" -" νͭԤ°Ƥ뤳Ȥ򸡾ڤ礬Ǥ\n" -"\n" -"嵭23ϡ*ñʤ*ˤʤȤȤǰƬ֤\n" -"Ƥ¾θ˽̾ݡְפֹϰϡפ\n" -"̣뤫ǽŪ˷ΤϡʤǤ\n" -"\n" -"Τ狼ʤϡ0פƤ" - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Ƥ 桼ID˽̾СyesפƤ" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Υ桼ID˺СyesפƤ\n" -"Ʊ˺ޤ!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "硢yesפƤ" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"ϸˤͭʽ̾Ǥ̤ν̾٤\n" -"ϤʤǤ礦ʤʤ顢ν̾ϡؤοѤؤκ䡢\n" -"θˤˤȤäƽפǤ" - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"ν̾Ȱפ븰ͭƤʤΤǡν̾ϸڤǤޤ\n" -"θѤޤǤϡʤϤν̾κα٤Ǥ\n" -"ʤʤ顢ν̾θϡ¾ξ줿ǿѤؤ뤫\n" -"ʤǤ" - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"ν̾ͭǤϤޤ󡣤ΤȤϡʤθؤ٤\n" -"Ȥ̣Ǥ" - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"ϡΥ桼IDб̾Ǥ̾ν̾Τ\n" -"ͤǤϤޤ󡣼ºݤˤϡGnuPGϤϤ䤳θȤʤΤ\n" -"ޤ󡣤äơμʽ̾餫ͳˤ̵Ǥäơ\n" -"ؤȤʤ븰ˤΤߡ¹ԤƤ" - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -" (ޤ򤷤) 桼ID򡢸ߤѹ\n" -"ޤط뼫ʽ̾Υॹפϡ1äߤޤ\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "ѥե졼ϤƤ̩ʸϤΤȤǤ \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Ϥѥե졼γǧΤᡢϤƤ" - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "̾Ԥե̾ꤷƤ" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "񤭤Ƥ褱СyesפƤ" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"ե̾ϤƤñ˥꥿󡦥򲡤ȡ\n" -"(̤ǰϤ) Υե̾Ѥޤ" - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"ͳꤹɬפޤطˤޤ\n" -"ʲ֤ȤǤޤ\n" -" ָѥޤ\n" -" ǧڤƤʤ̩ͤؤΥȿ\n" -" ­ͳΤȤˡȤޤ\n" -" ָȤ꤫äƤޤ\n" -" θʬǿȤȤ꤫Ȥ˻Ȥޤ\n" -" ָϤ⤦ȤƤޤ\n" -" θȤΤ᤿Ȥ˻Ȥޤ\n" -" ֥桼ID⤦ͭǤޤ\n" -" ⤦Υ桼IDϻȤ٤ǤʤȤȤ˻Ȥ\n" -" ޤ̡Żҥ᡼Υɥ쥹̵ˤʤä\n" -" ˻Ȥޤ\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"⤷Сʤ˴ȯԤΤ\n" -"ȤϤ뤳ȤǤޤƥȤϴʷˤƤ\n" -"Ԥǽˤʤޤ\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "إפϤޤ" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "`%s'ΥإפϤޤ" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "`%s'κ顼: %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr " `%s' Ǥޤ\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "إåκƹۤ˼Ԥޤ: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "ٹ: Ѿä2ĤΥե뤬¸ߤޤ\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%sѹΤʤǤ\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%sϿǤ\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "ΰη٤Ƥ\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "`%s'򸡾ڤƤޤ\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "ޤǤ%luĤθޤǸ (%luĤν̾)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%luĤθޤǸ (%luĤν̾)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: ؤǤޤ\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "ץ󡦥եɤľ褦GnuPGƵưƤ\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "`%s' ؤεĤѹ˼: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|̾=|ǡ" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "̾Ƭʸ(_)ǤʤФʤޤ\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "̾ΥɥåȤ¾ʸǰϤޤʤФʤޤ\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "ٹ: θˤϤ⤦եIDޤ\n" -#~ " 㤦եIDɲäȡǤPGPϺ𤹤뤫⤷ޤ\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "1ܤθˤϥեIDҤȤդǤ\n" - -#~ msgid "Fingerprint:" -#~ msgstr ":" - -#~ msgid " Fingerprint:" -#~ msgstr " :" diff --git a/po/nl.po b/po/nl.po deleted file mode 100644 index 383952501..000000000 --- a/po/nl.po +++ /dev/null @@ -1,5017 +0,0 @@ -# Dutch messages for gnupg -# Copyright (C) 2000 Free Software Foundation, Inc. -# Ivo Timmermans , 2000. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.0h\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2000-02-20 21:30+01:00\n" -"Last-Translator: Ivo Timmermans \n" -"Language-Team: Dutch \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Let op: er wordt onveilig geheugen gebruikt!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "bewerking is niet mogelijk zonder initialisatie van veilig geheugen\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(misschien heb je hiervoor het verkeerde programma gebruikt)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ja" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "yYjJ" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "nee" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "einde" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQeE" - -#: util/errors.c:54 -msgid "general error" -msgstr "algemene fout" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "onbekend pakket type" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "onbekende versie" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "onbekend publieke sleutel algoritme" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "onbekend verteeralgoritme" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "foutieve publieke sleutel" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "foutieve geheime sleutel" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "foutieve ondertekening" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "verkeerd controlegetal" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "verkeerde sleuteltekst" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "publieke sleutel niet gevonden" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "onbekend versleutelalgoritme" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "kan de sleutelbos niet openen" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "ongeldig pakket" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "ongeldige versleuteling" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "niet-bestaand gebruikersnummer" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "geheime sleutel niet beschikbaar" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "verkeerde geheime sleutel gebruikt" - -#: util/errors.c:72 -msgid "not supported" -msgstr "niet ondersteund" - -#: util/errors.c:73 -msgid "bad key" -msgstr "foutieve sleutel" - -#: util/errors.c:74 -msgid "file read error" -msgstr "leesfout op bestand" - -#: util/errors.c:75 -msgid "file write error" -msgstr "schrijffout op bestand" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "onbekend compressiealgoritme" - -#: util/errors.c:77 -msgid "file open error" -msgstr "fout bij openen bestand" - -#: util/errors.c:78 -msgid "file create error" -msgstr "fout bij aanmaken bestand" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "ongeldige sleuteltekst" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "publieke sleutel algoritme niet gemplementeerd" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "encryptie-algoritme niet gemplementeerd" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "onbekende klasse van ondertekeningen" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "fout in de vertrouwensrelatiedatabase" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "foutieve MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "hulpbronlimiet" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "ongeldige sleutelbos" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "foutief certificaat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "ongeldige gebruikersidentificatie" - -#: util/errors.c:89 -msgid "file close error" -msgstr "fout bij het sluiten van het bestand" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "fout bij het hernoemen van het bestand" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "fout bij het verwijderen van het bestand" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "onverwachte gegevens" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "tijden komen niet overeen" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "onbruikbaar publieke sleutel-algoritme" - -#: util/errors.c:95 -msgid "file exists" -msgstr "bestand bestaat al" - -#: util/errors.c:96 -msgid "weak key" -msgstr "onveilige sleutel" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "ongeldig argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "foutieve URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI wordt niet ondersteund" - -#: util/errors.c:100 -msgid "network error" -msgstr "netwerkfout" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "niet versleuteld" - -#: util/errors.c:103 -msgid "not processed" -msgstr "niet behandeld" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "foutieve publieke sleutel" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "foutieve geheime sleutel" - -#: util/errors.c:107 -#, fuzzy -msgid "keyserver error" -msgstr "algemene fout" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... dit is een programmeerfout (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "u heeft een fout in het programma gevonden ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "kan `%s' niet openen: %s\n" - -#: cipher/random.c:385 -#, fuzzy, c-format -msgid "can't stat `%s': %s\n" -msgstr "kan `%s' niet openen: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "LET OP: ongeldige aantekeningen gevonden\n" - -#: cipher/random.c:409 -#, fuzzy, c-format -msgid "can't read `%s': %s\n" -msgstr "kan `%s' niet openen: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "" - -#: cipher/random.c:467 -#, fuzzy, c-format -msgid "can't create `%s': %s\n" -msgstr "kan %s niet aanmaken: %s\n" - -#: cipher/random.c:474 -#, fuzzy, c-format -msgid "can't write `%s': %s\n" -msgstr "kan `%s' niet openen: %s\n" - -#: cipher/random.c:477 -#, fuzzy, c-format -msgid "can't close `%s': %s\n" -msgstr "kan `%s' niet openen: %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "LET OP: de willekeurige getallengenerator is niet veilig!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"De willekeurige getallengenerator is slechts een slordige oplossing om\n" -"het te laten werken - het is in geen geval een echte WGG!\n" -"\n" -"Gebruik geen enkele gegevens die door dit programma gegenereerd zijn!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Niet genoeg willekeurige gegevens beschikbaar. Ga wat ander werk doen\n" -"om het besturingssysteem de kans te geven om meer entropie te\n" -"verzamelen! (Nog %d bytes nodig)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Opdrachten:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[bestand]|maak een ondertekening" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[bestand]|maak een niet versleutelde ondertekening" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "maak een losstaande ondertekening" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "versleutel gegevens" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "versleutel slechts met een symmetrische versleutelmethode" - -#: g10/g10.c:315 -msgid "store only" -msgstr "alleen bewaren" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "gegevens decoderen (standaard)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "ondertekening controleren" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "lijst van sleutels genereren" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "sleutels en ondertekeningen opnoemen" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "sleutelverificaties controleren" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "sleutels en vingerafdrukken opnoemen" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "geheime sleutels opnoemen" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "nieuw sleutelpaar genereren" - -#: g10/g10.c:327 -#, fuzzy -msgid "remove keys from the public keyring" -msgstr "sleutel weghalen uit de publieke sleutelbos" - -#: g10/g10.c:329 -#, fuzzy -msgid "remove keys from the secret keyring" -msgstr "sleutel weghalen uit de geheime sleutelbos" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "onderteken een sleutel" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "onderteken een sleutel lokaal" - -#: g10/g10.c:332 -#, fuzzy -msgid "sign a key non-revocably" -msgstr "onderteken een sleutel lokaal" - -#: g10/g10.c:333 -#, fuzzy -msgid "sign a key locally and non-revocably" -msgstr "onderteken een sleutel lokaal" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "onderteken of bewerk een sleutel" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "genereer een terugtrekkings-certificaat" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exporteer sleutels" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exporteer sleutels naar een sleutelserver" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importeer sleutels van een sleutelserver" - -#: g10/g10.c:341 -#, fuzzy -msgid "search for keys on a key server" -msgstr "exporteer sleutels naar een sleutelserver" - -#: g10/g10.c:343 -#, fuzzy -msgid "update all keys from a keyserver" -msgstr "importeer sleutels van een sleutelserver" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "sleutels importeren/samenvoegen" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "noem alleen de volgorde van pakketten" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exporteer het vertrouwen in de eigenaars" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importeer het vertrouwen in de eigenaars" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "werk de vertrouwensdatabase bij" - -#: g10/g10.c:357 -#, fuzzy -msgid "unattended trust database update" -msgstr "werk de vertrouwensdatabase bij" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "repareer een beschadigde vertrouwensdatabase" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Verwijder de beveiliging op bestand of standaard invoer" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Voeg beveiliging toe aan bestad of standaard invoer" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [bestanden]|geef controlegetal van berichten weer" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opties:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "genereer beveiliging in ASCII" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NAAM|versleutel voor NAAM" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NAAM|gebruik NAAM als standaard ontvanger" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "gebruik de standaard sleutel als standaard ontvanger" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "" -"gebruik deze gebruikersidentificatie om te ondertekenen of te decoderen" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|stel compressieniveau in op N (uitzetten met 0)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "gebruik de verkorte tekstmodus" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "gebruik als uitvoerbestand" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "geef meer informatie" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "wees iets stiller" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "gebruik de terminal helemaal niet" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "forcees v3 ondertekening" - -#: g10/g10.c:397 -#, fuzzy -msgid "do not force v3 signatures" -msgstr "forcees v3 ondertekening" - -#: g10/g10.c:398 -#, fuzzy -msgid "force v4 key signatures" -msgstr "forcees v3 ondertekening" - -#: g10/g10.c:399 -#, fuzzy -msgid "do not force v4 key signatures" -msgstr "forcees v3 ondertekening" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "gebruik altijd een MDC voor versleuteling" - -#: g10/g10.c:402 -#, fuzzy -msgid "never use a MDC for encryption" -msgstr "gebruik altijd een MDC voor versleuteling" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "maak geen enkele verandering" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "doorlopende modus: vraag nooit" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "veronderstel ja als antwoord op de meeste vragen" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "veronderstel nee als antwoord op de meeste vragen" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "voeg deze sleutelbos toe aan de lijst van sleutelbossen" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "voeg deze geheime sleutelbos toe aan de lijst" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NAAM|gebruik NAAM als standaard geheime sleutel" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|SERVER|gebruik deze sleutelserver om sleutels op te zoeken" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAAM|zet tekenverzameling van terminal op NAAM" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "lees opties uit bestand" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|BB|schrijf status naar deze bestandsbeschrijver" - -#: g10/g10.c:427 -#, fuzzy -msgid "|[file]|write status info to file" -msgstr "|BB|schrijf status naar deze bestandsbeschrijver" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|BESTAND|laad extensiemodule BESTAND" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "doe als RFC1991 voorschrijft" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "zet alle pakket-, versleutel- en controle-opties naar OpenPGP gedrag" - -#: g10/g10.c:443 -#, fuzzy -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "zet alle pakket-, versleutel- en controle-opties naar OpenPGP gedrag" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|gebruik sleuteltekst modus N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NAAM|gebruik berichtsamenvattingsalgoritme NAAM voor sleutelteksten" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NAAM|gebruik versleutelalgoritme NAAM voor sleutelteksten" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAAM|gebruik versleutelalgoritme NAAM" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAAM|gebruik berichtsamenvattingsalgoritme NAAM" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|gebruik compressiealgoritme N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "plaats geen sleutelidentificatieveld in versleutelde pakketten" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Voorbeelden:\n" -"\n" -" -se -r Bob [bestand] teken en versleutel voor Bob\n" -" --clearsign [bestand] genereer een leesbare ondertekening\n" -" --detach-sign [bestand] genereer een losstaande ondertekening\n" -" --list-keys [namen] toon sleutels\n" -" --fingerprints [namen] toon vingerafdrukken\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "" -"Meld fouten in het programma a.u.b. aan ;\n" -"fouten in de vertaling aan .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Gebruik: gpg [opties] [bestanden] (-h voor hulp)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Syntaxis: gpg [opties] [bestanden]\n" -"onderteken, controleer, versleutel of decodeer de ingevoerde gegevens\n" -"standaardactie hangt af van de gegevens\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Ondersteunde algoritmes:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "gebruik: gpg [opties] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "tegenstrijdige commando's\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "LET OP: geen bestand `%s' met standaardopties\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "LET OP: geen bestand `%s' met standaardopties\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "optiebestand `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "opties inlezen van `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s is een onbekende tekenverzameling\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "LET OP: `%s' is een leeg bestand\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "ongeldige versleuteling" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "LET OP: `%s' is een leeg bestand\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "ongeldige sleutelbos" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "LET OP: programma zou een geheugendump kunnen maken!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "LET OP: %s is niet voor gewoon gebruik!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s is niet toegestaan met deze %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s heeft geen betekenis met %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "geselecteerd versleutelalgoritme is ongeldig\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "geselecteerd controle-algoritme is ongeldig\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "geselecteerd controle-algoritme is ongeldig\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "compressie-algoritme moet in het bereik %d..%d liggen\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed(?) moet groter zijn dan 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed(?) moet groter zijn dan 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth moet tussen de 1 en de 255 (inclusief) liggen\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "LET OP: simpele S2K mode (0) wordt met klem afgeraden\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "ongeldige S2K modus; moet 0, 1 of 3 zijn\n" - -#: g10/g10.c:1862 -#, fuzzy -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "ongeldige S2K modus; moet 0, 1 of 3 zijn\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "toon voorkeuren" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "toon voorkeuren" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "toon voorkeuren" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "toon voorkeuren" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "fout bij het initialiseren van de vertrouwensdatabase: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [bestandsnaam]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [bestandsnaam]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [bestandsnaam]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [bestandsnaam]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [bestandsnaam]" - -#: g10/g10.c:2056 -#, fuzzy -msgid "--sign --symmetric [filename]" -msgstr "--symmetric [bestandsnaam]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [bestandsnaam]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [bestandsnaam]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key gebruikersidentificatie" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key gebruikers-identificatie" - -#: g10/g10.c:2110 -#, fuzzy -msgid "--nrsign-key user-id" -msgstr "--sign-key gebruikersidentificatie" - -#: g10/g10.c:2118 -#, fuzzy -msgid "--nrlsign-key user-id" -msgstr "--sign-key gebruikersidentificatie" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key gebruikersidentificatie [opdrachten]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "kan %s niet openen: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [gebruikersidentificatie] [sleutelbos]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "opheffen van beveiliging mislukt: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "beveiligen mislukt: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "ongeldig frommelalgoritme `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[bestandsnaam]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Gaat uw gang, type het bericht ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "kan `%s' niet openen\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"een notitienaam mag alleen letters, cijfers, punten of underscores bevatten " -"en eindig met een =\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "een notitienaam mag geen controletekens bevatten\n" - -#: g10/g10.c:2737 -#, fuzzy -msgid "the given certification policy URL is invalid\n" -msgstr "de gegeven beleids-URL is ongeldig\n" - -#: g10/g10.c:2739 -#, fuzzy -msgid "the given signature policy URL is invalid\n" -msgstr "de gegeven beleids-URL is ongeldig\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "beveiliging: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "ongeldige beveiliginsinformatie: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "beveiligingsinformatie" - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "ongeldige informatie over leesbare ondertekening\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "geneste leesbare ondertekeningen\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "ongeldige regel met streepjes: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "onverwachte beveiliging:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "ongeldig wortel64 teken %02x overgeslagen\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "voortijdig einde (geen controlesom)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "voortijdig einde (in controlesom)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "verkeerde controlesom\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "fout in controlesom; %06lx - %06lx\n" - -# fixme -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "voortijdig einde (in trailer)\n" - -# fixme -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "fout in de trailer regel\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "geen geldige OpenPGP gegevens gevonden.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "ongeldige beveiliging: regel langer dan %d tekens\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"aangehaald gewoon teken in beveiliging - waaschijnlijk is er een foutief " -"mailbezorgprogramma gebruikt\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "" - -#: g10/pkclist.c:63 -#, fuzzy -msgid "Key is superseded" -msgstr "Sleutel is beveiligd.\n" - -#: g10/pkclist.c:65 -#, fuzzy -msgid "Key has been compromised" -msgstr "Deze sleutel is niet beschikbaar" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "rev- vervalste sleutelterugtrekking gevonden\n" - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "[terugtrekking]" - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "" - -#: g10/pkclist.c:258 -#, fuzzy, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Geen vertrouwenswaarde toegekend aan %lu:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -#, fuzzy -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Geef aan hoezeer je deze gebruiker vertrouwt om de sleutels van andere\n" -"gebruikers correct te verifieren (door naar paspoorten of\n" -"vingerafdrukken van andere bronnen te kijken...) ?\n" -"\n" -" 1 = Geen idee\n" -" 2 = Ik vertrouw hem niet\n" -" 3 = Ik vertrouw hem maar ten dele\n" -" 4 = Ik vertrouw hem volledig\n" -" s = Geef wat meer informatie\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr "" - -#: g10/pkclist.c:274 -#, fuzzy, c-format -msgid " %d = I do NOT trust\n" -msgstr "%08lx: We vertrouwen deze sleutel NIET\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr "" - -#: g10/pkclist.c:276 -#, fuzzy, c-format -msgid " %d = I trust fully\n" -msgstr "%s: is geen vertrouwensdatabasebestand\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr "" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr "" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = terug naar hoofdmenu\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr "" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = beindigen\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Uw keuze? " - -#: g10/pkclist.c:316 -#, fuzzy -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Wilt u deze sleutel echt verwijderen? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificaten die leiden tot een volledig betrouwbare sleutel:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "sleutel %08lx: sleutel is teruggeroepen!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Deze sleutel toch gebruiken? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "sleutel %08lx: subsleutel is teruggeroepen!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lx: sleutel is verlopen\n" - -#: g10/pkclist.c:448 -#, fuzzy, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -" Er is geen indicatie dat deze ondertekening van de eigenaar is.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lx: We vertrouwen deze sleutel NIET\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lx: Het is niet helemaal zeker dat deze sleutel echt aan de\n" -"eigenaar toebehoort, maar ik accepteer hem toch\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Deze sleutel behoort waarschijnlijk toe aan de eigenaar\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Deze sleutel is van ons\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Het is NIET zeker dat deze sleutel van de eigenaar is. Als je\n" -"*echt* weet waar je mee bezig bent, mag je de volgende vraag\n" -"beantwoorden met ja\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "LET OP: Ik gebruik een onbetrouwbare sleutel!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "LET OP: Deze sleutel is ingetrokken door de eigenaar!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr "" -" Dit zou kunnen betekenen dat de ondertekening een vervalsing is.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "LET OP: Deze subsleutel is ingetrokken door de eigenaar!\n" - -#: g10/pkclist.c:580 -#, fuzzy -msgid "Note: This key has been disabled.\n" -msgstr "Deze sleutel is niet beschikbaar" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Let op: Deze sleutel is verlopen!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "" -"LET OP: Deze sleutel is niet getekend met een betrouwbare ondertekening!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Er is geen indicatie dat deze ondertekening van de eigenaar is.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "LET OP: We vertrouwen NIET op deze sleutel!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " De sleutel is waarschijnlijk VERVALST.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"LET OP: Deze sleutel is niet getekend met genoeg betrouwbare " -"ondertekeningen!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr "" -" Het is niet zeker dat deze ondertekening toebehoort aan de " -"eigenaar.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: overgeslagen: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: overgeslagen: openbare sleutel is al aanwezig\n" - -#: g10/pkclist.c:811 -#, fuzzy -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Je gaf geen gebruikersidentificatie op. (je kunt \"-r\" gebruiken)\n" -"\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Gebruiker bestaat niet.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "" -"overgeslagen: openbare sleutel is al ingesteld als de standaard ontvanger\n" - -# fixme -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Openbare sleutel is niet toegankelijk.\n" - -#: g10/pkclist.c:870 -#, fuzzy -msgid "skipped: public key already set\n" -msgstr "%s: overgeslagen: openbare sleutel is al aanwezig\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "onbekende standaard ontvanger `%s'\n" - -# fixme -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: overgeslagen: openbare sleutel is niet toegankelijk\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "geen geldige adressen\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "" - -#: g10/keygen.c:189 -#, fuzzy, c-format -msgid "preference %c%lu duplicated\n" -msgstr "`%s' overgeslagen: dubbel\n" - -#: g10/keygen.c:194 -#, fuzzy, c-format -msgid "too many `%c' preferences\n" -msgstr "toon voorkeuren" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "Ongeldig teken in naam\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "zelfondertekening wegschrijven\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "zelfondertekening wegschrijven\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "schrijven van sleutelbindingsondertekening\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, fuzzy, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "Gevraagde sleutellengte is %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, fuzzy, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "afgerond naar %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Selecteer aub wat voor sleutel u wilt:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA en ElGamal (standaard)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (alleen ondertekenen)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (alleen versleutelen)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (ondertekenen en versleutelen)\n" - -#: g10/keygen.c:949 -#, fuzzy, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) DSA (alleen ondertekenen)\n" - -#: g10/keygen.c:951 -#, fuzzy, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) ElGamal (alleen versleutelen)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (ondertekenen en versleutelen)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Uw keuze? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Ongeldige keuze.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Ik ga zo een nieuw %s sleutelpaar aanmaken.\n" -" mimimale sleutellengte is 768 bits\n" -" standaard sleutellengte is 1024 bits\n" -" hoogste aan te raden sleutellengte is 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Hoe lang wil je de sleutel maken? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA staat alleen sleutellengtes toe van 512 tot 1024\n" - -#: g10/keygen.c:1027 -#, fuzzy -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "sleutel te kort; 768 is de kleinste toegestane waarde.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "sleutel te kort; 768 is de kleinste toegestane waarde.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "sleutel te lang; %d is de maximumlengte.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Sleutels langer dan 2048 worden afgeraden omdat berekeningen dan ERG\n" -"lang duren!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Weet je zeker dat je deze sleutellengte wilt gebruiken? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Okee, maar houd er rekening mee dat straling van monitor en toetsenbord ook " -"erg vatbaar zijn voor aanvallen!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Gevraagde sleutellengte is %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "afgerond naar %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Geef aub aan hoe lang de sleutel geldig mag blijven.\n" -" 0 = sleutel verloopt nooit\n" -" = sleutel verloopt over n dagen\n" -" w = sleutel verloopt over n weken\n" -" m = sleutel verloopt over n maanden\n" -" y = sleutel verloopt over n jaar\n" - -#: g10/keygen.c:1126 -#, fuzzy -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Geef aub aan hoe lang de sleutel geldig mag blijven.\n" -" 0 = sleutel verloopt nooit\n" -" = sleutel verloopt over n dagen\n" -" w = sleutel verloopt over n weken\n" -" m = sleutel verloopt over n maanden\n" -" y = sleutel verloopt over n jaar\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Sleutel is geldig gedurende? (0) " - -#: g10/keygen.c:1150 -#, fuzzy -msgid "Signature is valid for? (0) " -msgstr "Sleutel is geldig gedurende? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "ongeldige waarde\n" - -#: g10/keygen.c:1160 -#, fuzzy, c-format -msgid "%s does not expire at all\n" -msgstr "Sleutel verloopt nooit\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, fuzzy, c-format -msgid "%s expires at %s\n" -msgstr "Sleutel verloopt op %s\n" - -# fixme -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Uw systeem kan geen data weergeven van na 2038.\n" -"Desondanks wordt het goed behandeld tot 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Klopt dit (j/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"U heeft een gebruikersidentificatie nodig voor de sleutel; het\n" -"programma bouwt deze op uit Echte naam, Kommentaar en Email Adres in\n" -"dit formaat:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Echte naam: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Ongeldig teken in naam\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Naam mag niet beginnen met een cijfer\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Naam moet ten minste 5 tekens lang zijn\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Email Adres: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Ongeldig email adres\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Kommentaar: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Ongeldig teken in kommentaar\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Je gebruik tekenverzameling `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Je hebt deze gebruikersidentificatie gekozen:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnKkEeOoEe" - -#: g10/keygen.c:1326 -#, fuzzy -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Verander (N)aam, (K)ommentaar, (E)mail of (O)kee/ei(N)de? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Verander (N)aam, (K)ommentaar, (E)mail of (O)kee/ei(N)de? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Je hebt een sleuteltekst nodig om je geheime sleutel te bewaken.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -#, fuzzy -msgid "passphrase not correctly repeated; try again" -msgstr "sleuteltekst is niet goed herhaald; probeer het opnieuw.\n" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"U heeft gekozen voor geen sleuteltekst - dit is waaschijnlijk een\n" -"*slecht* idee! Ik zal het toch doen. U kunt uw sleuteltekst altijd\n" -"nog aanpassen, gebruik dit programma met de optie \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"We hebben een heleboel willekeurige data nodig. Het is wellicht een\n" -"goed idee om wat anders te doen (het toetsenbord en de muis gebruiken,\n" -"of de schijven aanspreken) tijdens de generatie van de priemgetallen;\n" -"dit geeft de generator een grotere kans om genoeg entropie te\n" -"verzamelen.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSA sleutelpaar zal 1024 bits lang zijn.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Sleutelgeneratie afgebroken.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, fuzzy, c-format -msgid "writing public key to `%s'\n" -msgstr "Openbaar certificaat wordt geschreven naar `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, fuzzy, c-format -msgid "writing secret key to `%s'\n" -msgstr "Geheim certificaat wordt weggeschreven naar `%s'\n" - -#: g10/keygen.c:2205 -#, fuzzy, c-format -msgid "no writable public keyring found: %s\n" -msgstr "sleutel %08lX: openbare sleutel niet gevonden: %s\n" - -#: g10/keygen.c:2211 -#, fuzzy, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "sleutel %08lX: geheime sleutel niet gevonden: %s\n" - -#: g10/keygen.c:2225 -#, fuzzy, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "fout bij schrijven van de sleutelbos `%s': %s\n" - -#: g10/keygen.c:2232 -#, fuzzy, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "fout bij schrijven van de sleutelbos `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "openbare en geheime sleutels zijn gemaakt en getekend.\n" - -#: g10/keygen.c:2253 -#, fuzzy -msgid "key marked as ultimately trusted.\n" -msgstr "Certificaten die leiden tot een volledig betrouwbare sleutel:\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Let er op dat deze sleutel niet gebruikt kan worden voor versleutelen.\n" -"U wilt misschien het commando \"--edit-key\" gebruiken om een tweede\n" -"sleutel te maken hiervoor.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Sleutelgeneratie is mislukt: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"Sleutel is %lu seconden in de toekomst gemaakt (tijdsverschuiving of\n" -"klokprobleem)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"sleutel is %lu seconden in de toekomst gemaakt (tijdsverschuiving of\n" -"klokprobleem)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Echt maken? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: kon niet openen: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "fout tijdens aanmake sleuteltekst: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, fuzzy, c-format -msgid "`%s' already compressed\n" -msgstr "%lu sleutels verwerkt\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: LET OP: leeg bestand\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lezen uit `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "LET OP: versleutelalgoritme %d niet gevonden in de voorkeuren\n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s versleuteld voor: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, fuzzy, c-format -msgid "key `%s' not found: %s\n" -msgstr "gebruiker `%s' niet gevonden: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, fuzzy, c-format -msgid "error reading keyblock: %s\n" -msgstr "fout bij lezen `%s': %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "sleutel %08lx: geen sleutel volgens rfc2240 - overgeslagen\n" - -#: g10/export.c:238 -#, fuzzy, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "sleutel %08lx: geen sleutel volgens rfc2240 - overgeslagen\n" - -#: g10/export.c:246 -#, fuzzy, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "sleutel %08lx: geen sleutel volgens rfc2240 - overgeslagen\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "LET OP: er is niets gexporteerd\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "te veel ingangen in de pk cache - uitgezet\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -#, fuzzy -msgid "[User id not found]" -msgstr "[gebruiker niet gevonden]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "gebruik secundaire sleutel %08lx in plaats van de primaire %08lx\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "" -"sleutel %08lX: geheime sleutel zonder openbare sleutel - overgeslagen\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "blok van type %d wordt overgeslagen\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu sleutels zijn tot nu toe behandeld\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "fout bij lezen `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Totaal aantal behandeld: %lu\n" - -#: g10/import.c:286 -#, fuzzy, c-format -msgid " skipped new keys: %lu\n" -msgstr "nieuwe subsleutels: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " zonder identificatie: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr "gemporteerd: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr "onveranderd: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr "nieuwe gebruikers: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr "nieuwe subsleutels: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr "nieuwe ondertekeningen: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr "nieuwe sleutelterugtrekkingen: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr "geheime sleutels gelezen: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "geheime sleutels gemporteerd: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "onveranderde geheime sleutels: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr "gemporteerd: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "sleutel %08lX: geen gebruikersidentificatie\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "sleutel %08lX: geen subsleutel voor sleutelbinding\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "" -"sleutel %08lX: niet zelfondertekende gebruikersidentificatie geaccepteerd '" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "sleutel %08lX: geen geldige gebruikersidentificaties\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "" -"dit zou veroorzaakt kunnen worden door een ontbrekende zelf-ondertkening\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "sleutel %08lX: openbare sleutel niet gevonden: %s\n" - -#: g10/import.c:636 -#, fuzzy, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "sleutel %08lx: geen sleutel volgens rfc2240 - overgeslagen\n" - -#: g10/import.c:646 -#, fuzzy, c-format -msgid "no writable keyring found: %s\n" -msgstr "fout bij schrijven van de sleutelbos `%s': %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "schrijven naar `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "fout bij schrijven van de sleutelbos `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "sleutel %08lX: openbare sleutel gemporteerd\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "sleutel %08lX: komt niet overeen met onze kopie\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "sleutel %08lX: kan originele sleutelblok niet vinden: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "sleutel %08lX: kan origineel sleutelblok niet lezen: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "sleutel %08lX: 1 nieuwe gebruiker\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "sleutel %08lX: %d nieuwe gebruikers\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "sleutel %08lX: 1 nieuwe ondertekening\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "sleutel %08lX: %d nieuwe ondertekeningen\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "sleutel %08lX: 1 nieuwe subsleutel\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "sleutel %08lX: %d nieuwe subsleutels\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "sleutel %08lX: niet veranderd\n" - -#: g10/import.c:844 -#, fuzzy, c-format -msgid "no default secret keyring: %s\n" -msgstr "geen standaard openbare sleutelbos\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "sleutel %08lX: geheime sleutel gemporteerd\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "sleutel %08lX: reeds aanwezig in de geheime sleutelbos\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "sleutel %08lX: geheime sleutel niet gevonden: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"sleutel %08lX: geen openbare sleutel - kan terugtrekkingscertificaat niet " -"toepassen\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "sleutel %08lX: ongeldig terugtrekkingscertificaat: %s - afgewezen\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "sleutel %08lX: terugtrekkingscertificaat gemporteerd\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "sleutel %08lX: geen gebruikersidentificatie voor ondertekening\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "sleutel %08lX: openbaar sleutel algoritme niet ondersteund\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "sleutel %08lX: ongeldige eigen ondertekening\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "sleutel %08lX: geen subsleutel voor sleutelbinding\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "sleutel %08lX: openbaar sleutel algoritme niet ondersteund\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "sleutel %08lX: ongeldige subsleutelbinding\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "sleutel %08lX: ongeldige subsleutelbinding\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "sleutel %08lX: geen subsleutel voor sleutelbinding\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "sleutel %08lX.%lu: Geldige subsleutelterugtrekking\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "sleutel %08lX: ongeldige subsleutelbinding\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "sleutel %08lX: gebruikersidentificatie overgeslagen '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "sleutel %08lX: subsleutel overgeslagen\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "" -"sleutel %08lX: niet exporteerbare ondertekening (klasse %02x) - " -"overgeslagen\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "" -"sleutel %08lX: terugtrekkingscertificaat op de verkeerde plek - " -"overgeslagen\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "sleutel %08lX: ongeldig terugtrekkingscertificaat: %s - overgeslagen\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "" -"sleutel %08lX: terugtrekkingscertificaat op de verkeerde plek - " -"overgeslagen\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "" -"sleutel %08lX: dubbele gebruikersidentificatie gevonden - samengevoegd\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "sleutel %08lX: terugtrekkingscertificaat toegevoegd\n" - -#: g10/import.c:1491 -#, fuzzy, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "sleutel %08lX: %d nieuwe ondertekeningen\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[terugtrekking]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[zelfondertekening]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 ongeldige ondertekening\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d ongeldige ondertekeningen\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 ondertekening niet gecontroleerd wegens een ontbrekende sleutel\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d ondertekeningen niet gecontroleerd wegens ontbrekende sleutels\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 ondertekening niet gecontroleerd wegens een fout\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d ondertekeningen niet gecontroleerd wegens fouten\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 gebruikersidentificatie gevonden zonder geldige zelfondertekening\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "" -"%d gebruikersidentificaties gevonden zonder geldige zelfondertekening\n" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Sleutel is beveiligd.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Weet je zeker dat je deze sleutellengte wilt gebruiken? " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "LET OP: `%s' is een leeg bestand\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "Reeds ondertekend met sleutel %08lx\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "Reeds ondertekend met sleutel %08lx\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Niets te tekenen met sleutel %08lX\n" - -#: g10/keyedit.c:478 -#, fuzzy -msgid "This key has expired!" -msgstr "Let op: Deze sleutel is verlopen!\n" - -#: g10/keyedit.c:498 -#, fuzzy, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Deze sleutel is niet beveiligd.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "" - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr "" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr "" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr "" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr "" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Bent u er echt zeker van dat u deze sleutel wilt tekenen\n" -"met uw sleutel: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "" -"dit zou veroorzaakt kunnen worden door een ontbrekende zelf-ondertkening\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"Deze ondertekening zal gemarkeerd worden als niet exporteerbaar.\n" -"\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"Deze ondertekening zal gemarkeerd worden als niet exporteerbaar.\n" -"\n" - -#: g10/keyedit.c:620 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"Deze ondertekening zal gemarkeerd worden als niet exporteerbaar.\n" -"\n" - -#: g10/keyedit.c:624 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"Deze ondertekening zal gemarkeerd worden als niet exporteerbaar.\n" -"\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Echt tekenen? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "ondertekening mislukt: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Deze sleutel is niet beveiligd.\n" - -#: g10/keyedit.c:748 -#, fuzzy -msgid "Secret parts of primary key are not available.\n" -msgstr "geheime sleutel niet beschikbaar" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Sleutel is beveiligd.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Kan deze sleutel niet bewerken: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Geef de sleuteltekst voor deze geheime sleutel.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"U wilt geen sleuteltekst - dit is waaschijnlijk een *slecht* idee!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Wilt u dit echt? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "sleutelondertekening naar de juiste plaats schuiven\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "beindig dit menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "bewaar" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "opslaan en beindigen" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "hulp" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "geef deze hulp" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "toon vingerafdruk" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "lijst" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "lijst van sleutel- en gebruikersidentificaties" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "gebruikersidentificatie" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "selecteer gebruikersidentificatie N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "sleutel" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "selecteer subsleutel N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "controleer" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "toon ondertekeningen" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "onderteken" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "onderteken de sleutel" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lteken" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "teken de sleutel lokaal" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "nrsign" -msgstr "onderteken" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "sign the key non-revocably" -msgstr "teken de sleutel lokaal" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "nrlsign" -msgstr "onderteken" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "sign the key locally and non-revocably" -msgstr "teken de sleutel lokaal" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "voeg een gebruikersidentificatie toe" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "" - -#: g10/keyedit.c:920 -#, fuzzy -msgid "add a photo ID" -msgstr "voeg een gebruikersidentificatie toe" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "verwijder gebruikersidentificatie" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "voeg een secundaire sleutel toe" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "verwijder een secundaire sleutel" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "revkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "voeg een secundaire sleutel toe" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "verwijder ondertekeningen" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "verander de vervaldatum" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "wissel" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "wissel tussen geheime en openbare sleutels" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -#, fuzzy -msgid "list preferences (expert)" -msgstr "toon voorkeuren" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "list preferences (verbose)" -msgstr "toon voorkeuren" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "setpref" -msgstr "pref" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "set preference list" -msgstr "toon voorkeuren" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updpref" -msgstr "pref" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updated preferences" -msgstr "toon voorkeuren" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "verander de sleuteltekst" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "verander het vertrouwen in de eigenaar" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "roep ondertekeningen terug" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "trek secundaire sleutel in" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "sta het gebruik van een sleutel niet toe" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "sta gebruik van een sleutel toe" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "kan dat niet doen in lopende band-modus\n" - -#: g10/keyedit.c:1000 -#, fuzzy, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "fout bij lezen `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Geheime sleutel is beschikbaar.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Commando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Ik heb de geheime sleutel nodig om dat te doen.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "Sleutel is beveiligd.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Echt alle gebruikers tekenen? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Hint: Selecteer de gebruikersidentificaties om te tekenen\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "U moet op zijn minst een gebruikersidentificatie opgeven.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "U kunt de laatste gebruiker niet verwijderen!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Al deze gebruikers echt verwijderen? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Deze gebruiker echt verwijderen? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "U moet op zijn minst een sleutel selecteren.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Wilt u echt alle geselecteerde sleutels verwijderen? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Wilt u deze sleutel echt verwijderen? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Wilt u echt alle geselecteerde sleutels intrekken? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Wilt u deze sleutel echt intrekken? " - -#: g10/keyedit.c:1354 -#, fuzzy -msgid "Really update the preferences for the selected user IDs? " -msgstr "Al deze gebruikers echt verwijderen? " - -#: g10/keyedit.c:1356 -#, fuzzy -msgid "Really update the preferences? " -msgstr "Echt deze terugtrekkingscertificaten aanmaken? (j/N)" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Veranderingen bewaren? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Beindigen zonder te bewaren? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "bijwerken ging niet: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "bijwerken van de geheime sleutel mislukte: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "sleutel is niet veranderd en hoeft dus niet bijgewerkt te worden.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Foutief commando (probeer \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "LET OP: Deze sleutel is ingetrokken door de eigenaar!\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr "" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Deze sleutel is niet beschikbaar" - -#: g10/keyedit.c:1802 -#, fuzzy, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! subsleutel is teruggeroepen: %s\n" - -#: g10/keyedit.c:1805 -#, fuzzy -msgid "rev- faked revocation found\n" -msgstr "rev- vervalste sleutelterugtrekking gevonden\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Weet je zeker dat je deze sleutellengte wilt gebruiken? " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Verwijder deze goede ondertekening? (j/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Verwijder deze ongeldige ondertekening? (j/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Verwijder deze onbekende ondertekening? (j/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Deze zelfondertekening echt verwijderen? (j/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d ondertekening verwijderd.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d ondertekeningen verwijderd.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Niets verwijderd.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Geef de sleutelgrootte" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Haal a.u.b. de selecties weg voor de geheime sleutels.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Selecteer a.u.b. maximaal n secundaire sleutel.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Vervaldatum voor secundaire sleutel instellen.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Vervaldatum voor primaire sleutel instellen.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "U kunt de vervaldatum van een v3 sleutel niet wijzigen\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Geen overeenkomende ondertekening in de geheime sleutelbos\n" - -#: g10/keyedit.c:2546 -#, fuzzy -msgid "Please select exactly one user ID.\n" -msgstr "U moet op zijn minst een gebruikersidentificatie opgeven.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "sleutel %08lX: ongeldige eigen ondertekening\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Geen gebruikersidentificatie met index %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Geen secundaire sleutel met index %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "gebruikersidentificatie: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"tekende met uw sleutel %08lX op %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"tekende met uw sleutel %08lX op %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "Deze sleutel is niet beveiligd.\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Weet je zeker dat je deze sleutellengte wilt gebruiken? " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Terugtrekkingscertificaat maken voor deze ondertekening? (j/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "U heeft deze gebruikers ondertekend:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " getekend door %08lX op %s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " ingetrokken door %08lX op %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "U staat op het punt om deze ondertekeningen in te trekken:\n" - -#: g10/keyedit.c:3013 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " getekend door %08lX op %s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Echt deze terugtrekkingscertificaten aanmaken? (j/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "geen geheime sleutel\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "%s ondertekening van: %s\n" - -#: g10/keylist.c:93 -#, fuzzy -msgid "Signature policy: " -msgstr "%s ondertekening van: %s\n" - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "LET OP: ongeldige aantekeningen gevonden\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Aantekening: " - -#: g10/keylist.c:129 -#, fuzzy -msgid "Signature notation: " -msgstr "Aantekening: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, fuzzy, c-format -msgid " [expires: %s]" -msgstr "Sleutel verloopt op %s\n" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "sleutels en vingerafdrukken opnoemen" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Vingerafdruk:" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Vingerafdruk:" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Vingerafdruk:" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -#, fuzzy -msgid " Key fingerprint =" -msgstr " Vingerafdruk:" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "ongeldig frommelalgoritme `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s versleutelde gegevens\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "versleuteld met onbekend algoritme %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "openbare sleutel is %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "gegevens versleuteld met een openbare sleutel: goede DEK\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "versleuteld met %u-bit %s sleutel, nummer %08lX, gemaakt op %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "versleuteld met %s sleutel, nummer %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "openbare sleutel-ontsleuteling ging niet: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, fuzzy, c-format -msgid "assuming %s encrypted data\n" -msgstr "%s versleutelde gegevens\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "ontsleutelen ging goed\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "LET OP: het versleutelde bericht is veranderd!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "ontsleuteling mislukte: %s\n" - -# Dit kan wel Engels blijven.. toch? -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "LET OP: afzender vroeg om \"for-your-eyes-only\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "originele bestandsnaam='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "alleenstaande intrekking - gebruik \"gpg --import\" om uit te voeren\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Aantekening: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Beleid: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "controle van de ondertekening overgeslagen\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -#, fuzzy -msgid "can't handle these multiple signatures\n" -msgstr "maak een losstaande ondertekening" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Ondertekening gemaakt op %.*s met %s sleutel nummer %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "FOUTE ondertekening van \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -#, fuzzy -msgid "Expired signature from \"" -msgstr "Correcte ondertekening van \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Correcte ondertekening van \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Kan ondertekening niet controleren: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -#, fuzzy -msgid "not a detached signature\n" -msgstr "maak een losstaande ondertekening" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "losstaande ondertekening van type 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "oude stijl (PGP 2.x) ondertekening\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "ongeldig hoofdpakket gevonden in proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "kan geheugendumps niet uitzetten: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Experimentele algoritmes dienen niet gebruikt te worden!\n" - -#: g10/misc.c:192 -#, fuzzy -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "dit versleutelalgoritme is verouderd; gebruik een meer algemene!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "LET OP: `%s' is een leeg bestand\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "LET OP: `%s' is een leeg bestand\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "kan openbare sleutel-algoritme %d niet behandelen\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "subpakket type %d heeft kritische bit gezet\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "" - -#: g10/passphrase.c:511 -#, fuzzy, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "beschermingsalgoritme %d wordt niet ondersteund\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "kan geen verbinding maken met `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (hoofdsleutelnummer %08lX)" - -#: g10/passphrase.c:641 -#, fuzzy, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"\n" -"U heeft een sleuteltekst nodig om de beveiliging voor de geheime\n" -"sleutel op te heffen voor gebruiker \"%.*s\"\n" -"%u-bit %s sleutel, ID %08lX, gemaakt op %s%s\n" - -#: g10/passphrase.c:662 -#, fuzzy -msgid "Enter passphrase\n" -msgstr "Geef de sleuteltekst: " - -#: g10/passphrase.c:664 -#, fuzzy -msgid "Repeat passphrase\n" -msgstr "Herhaal de sleuteltekst: " - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"U heeft een sleuteltekst nodig om de beveiliging voor de geheime\n" -"sleutel voor gebruiker op te heffen: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bit %s sleutel, nummer %08lX, gemaakt op %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "kan niet om wachtwoord vragen in lopende band-modus\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Geef de sleuteltekst: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Herhaal de sleuteltekst: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"gegevens niet bewaard; gebruik de optie \"--output\" om het op te slaan in\n" - -#: g10/plaintext.c:108 -#, fuzzy, c-format -msgid "error creating `%s': %s\n" -msgstr "fout bij lezen `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Losstaande ondertekening.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Geef de naam van het gegevensbestand: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lezen uit standaard invoer ...\n" - -#: g10/plaintext.c:396 -#, fuzzy -msgid "no signed data\n" -msgstr "geen ondertekende gegevens\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "kan ondertekende gegevens `%s' niet openen\n" - -#: g10/pubkey-enc.c:101 -#, fuzzy, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "anonieme ontvanger; ik probeer geheime sleutel %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "okee, wij zijn de anonieme ontvanger.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "oude codering van de DEK wordt niet ondersteund.\n" - -#: g10/pubkey-enc.c:178 -#, fuzzy, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "beschermingsalgoritme %d wordt niet ondersteund\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "LET OP: versleutelalgoritme %d niet gevonden in de voorkeuren\n" - -#: g10/pubkey-enc.c:243 -#, fuzzy, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "LET OP: geheime sleutel %08lX is vervallen op %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "sleutel %08lx: sleutel is teruggeroepen!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "opvragen van sleutel %08lX van %s ...\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "kan de sleutel niet opvragen van de server: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "fout bij versturen naar `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "versturen naar `%s' gelukt (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "fout bij versturen naar `%s': status=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "" - -#: g10/hkp.c:565 -#, fuzzy, c-format -msgid "can't search keyserver: %s\n" -msgstr "kan de sleutel niet opvragen van de server: %s\n" - -#: g10/seckey-cert.c:53 -#, fuzzy -msgid "secret key parts are not available\n" -msgstr "geheime sleutel niet beschikbaar" - -#: g10/seckey-cert.c:59 -#, fuzzy, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "beschermingsalgoritme %d wordt niet ondersteund\n" - -#: g10/seckey-cert.c:224 -#, fuzzy -msgid "Invalid passphrase; please try again" -msgstr "Foutieve sleuteltekst; probeer a.u.b. opnieuw ...\n" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"LET OP: Kwetsbare sleutel gevonden - verander a.u.b. de sleuteltekst " -"opnieuw.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"dit is een ElGamal sleutel van PGP, die NIET veilig is voor " -"ondertekeningen!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "openbare sleutel is %lu seconde nieuwer dan de ondertekening\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "openbare sleutel is %lu seconden nieuwer dan de ondertekening\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"Sleutel is %lu seconden in de toekomst gemaakt (tijdsverschuiving of\n" -"klokprobleem)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"sleutel is %lu seconden in de toekomst gemaakt (tijdsverschuiving of\n" -"klokprobleem)\n" - -#: g10/sig-check.c:249 -#, fuzzy, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "LET OP: sleutel voor ondertekening %08lX is vervallen op %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "foutieve ondertekening aangenomen wegens een onbekende kritische bit\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:303 -#, fuzzy, c-format -msgid "checking created signature failed: %s\n" -msgstr "Kan ondertekening niet controleren: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s ondertekening van: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "LET OP: `%s' is een leeg bestand\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "kan %s niet aanmaken: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "LET OP: versleutelalgoritme %d niet gevonden in de voorkeuren\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "ondertekenen:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:1029 -#, fuzzy, c-format -msgid "%s encryption will be used\n" -msgstr "ontsleuteling mislukte: %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "kan tekstregels langer dan %d tekens niet aan\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "invoerregel langer dan %d tekens\n" - -# Untranslated. -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb rec %lu: lseed failed: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb rec %lu: write failed (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transactie naar vertrouwensdatabase te groot\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: kan er niet bij: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: map bestaat niet!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: kan hem niet vergrendelen\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, fuzzy, c-format -msgid "%s: can't make lock\n" -msgstr "%s: kan hem niet vergrendelen\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: kan hem niet aanmaken: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: aanmaken van versieveld lukte niet: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: foutieve vertrouwensdatabase aangemaakt\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: vertrouwensdatabase aangemaakt\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: ongeldige vertrouwensdatabase\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: kon frommeltabel niet aanmaken: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: fout bij het bijwerken van versieveld: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: fout bij het lezen van het versieveld: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: fout bij het schrijven van het versieveld: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "vertrouwensdatabase: lseek mislukte: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "vertrouwensdatabase: lezen mislukte (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: is geen vertrouwensdatabasebestand\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: versieveld met recnr %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: ongeldige bestandsversie %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: fout bij het lezen van een beschikbaar veld: %s\n" - -# dir? -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: fout bij het schrijven van indexveld: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: veld met nullen vullen lukte niet: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: kon geen veld toevoegen: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"de vertrouwensdatabase is beschadigd; draai a.u.b. \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, fuzzy, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "%s: ongeldig sleutelnummer\n" - -#: g10/trustdb.c:235 -#, fuzzy, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "sleutel %08lX: geaccepteerd als een betrouwbare sleutel.\n" - -#: g10/trustdb.c:274 -#, fuzzy, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "sleutel %08lX: kan niet toevoegen aan de vertrouwensdatabase\n" - -#: g10/trustdb.c:290 -#, fuzzy, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "sleutel %08lx: geen sleutel volgens rfc2240 - overgeslagen\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "vertrouwensveld %lu, req type %d: lezen mislukte: %s\n" - -#: g10/trustdb.c:338 -#, fuzzy, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "vertrouwensveld %lu: verwijderen mislukte: %s\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "vertrouwensveld %lu, type %d: schrijven mislukte: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "vertrouwensdatabase: synchronisatie mislukte: %s\n" - -#: g10/trustdb.c:468 -#, fuzzy -msgid "no need for a trustdb check\n" -msgstr "%s: is geen vertrouwensdatabasebestand\n" - -# Untranslated. -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, fuzzy, c-format -msgid "next trustdb check due at %s\n" -msgstr "trustdb rec %lu: lseed failed: %s\n" - -#: g10/trustdb.c:779 -#, fuzzy -msgid "checking the trustdb\n" -msgstr "verander het vertrouwen in de eigenaar" - -#: g10/trustdb.c:933 -#, fuzzy, c-format -msgid "public key %08lX not found: %s\n" -msgstr "publieke sleutel niet gevonden" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"deze ondertekening kon niet worden gecontroleerd.\n" -"Onthoud dat het bestand met de ondertekening (.sig of .asc) het eerste\n" -"bestand van de commandoregel moet zijn.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "invoerregel %u is te lang, of ontbrekende LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"sleutel is niet als onveilig gemarkeerd - kan hem niet gebruiken met nep-" -"RNG!\n" - -#: g10/skclist.c:157 -#, fuzzy, c-format -msgid "skipped `%s': duplicated\n" -msgstr "`%s' overgeslagen: dubbel\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "`%s' overgeslagen: %s\n" - -#: g10/skclist.c:168 -#, fuzzy -msgid "skipped: secret key already present\n" -msgstr "overgeslagen: geheime sleutel is al aanwezig\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"`%s' overgeslagen: dit is een ElGamal sleutel gemaakt door PGP, dit is\n" -"niet veilig genoeg voor ondertekeningen!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Bestand `%s' bestaat al. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Overschrijven (j/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: onbekend achtervoegsel\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Geef een nieuwe bestandsnaam" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "naar standaard uitvoer schrijven\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "ik neem aan dat de getekende gegevens zich in `%s' bevinden\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: nieuw optiebestand aangemaakt\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: kan map niet aamaken: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: map aangemaakt\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"LET OP: dit bericht werd versleuteld met een zwakke sleutel in het\n" -"symmetrische versleutelalgoritme.\n" - -#: g10/encr-data.c:98 -#, fuzzy -msgid "problem handling encrypted packet\n" -msgstr "plaats geen sleutelidentificatieveld in versleutelde pakketten" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "zwakke sleutel gemaakt - ik probeer het opnieuw\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"kon het aanmaken van een zwakke sleutel voor het symmetrische\n" -"algoritme niet voorkomen; ik heb het %d keer geprobeerd!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "kan dat niet doen in lopende band-mode zonder \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Deze sleutel van de sleutelbos verwijderen? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Dit is een geheime sleutel! - echt verwijderen? " - -#: g10/delkey.c:168 -#, fuzzy, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "nummeren van de sleutelblokken mislukte: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, fuzzy, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "er is een geheime sleutel voor deze openbare sleutel!\n" - -#: g10/delkey.c:208 -#, fuzzy -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "" -"gebruik eerst de optie \"--delete-secret-key\" om hem te verwijderen.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Het is aan u om hier een waarde te geven; deze waarde zal nooit\n" -"weggegeven worden aan derden. We hebben het nodig om het\n" -"netwerk-van-vertrouwen op te bouwen; het heeft niets te maken met het\n" -"netwerk-van-certificaten (dat automatisch gemaakt wordt)." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Als u dit desondanks toch wilt intrekken, antwoord dan \"ja\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Als u deze onbetrouwbare sleutel toch wilt gebruiken, antwoord dan \"ja\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Geef de identificatie van de ontvangende gebruiker." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Selecteer het te gebruiken algoritme.\n" -"\n" -"DSA (ook wel DSS) is het `Digital Signature Algoritm' dat alleen\n" -"gebruikt kan worden voor ondertekeningen. Dit heeft de voorkeur omdat\n" -"controle van DSA ondertekeningen veel sneller gaan dan van ElGamal.\n" -"\n" -"ElGamal is een algoritme dat gebruikt kan worden voor ondertekening en\n" -"versleuteling. OpenPGP maakt een onderscheid tussen de twee varianten\n" -"van dit algoritme: alleen versleutelen en versleutelen+tekenen; het is\n" -"in werkelijkheid het zelfde, maar sommige parameters moeten speciaal\n" -"gezet worden voor de aanmaak van een veilige sleutel voor\n" -"ondertekeningen: dit programma doet dit, maar andere OpenPGP\n" -"implementaties zijn niet verplicht om de versleutelen+tekenen-variant\n" -"te ondersteunen.\n" -"\n" -"De eerste (primaire) sleutel moet altijd een sleutel zijn waarmee\n" -"ondertekend kan worden; om deze reden is de ElGamal sleutel voor\n" -"alleen versleutelen niet aanwezig in dit menu." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Hoewel deze sleutels gedefinieerd zijn in RFC2440, worden ze niet\n" -"aangeraden om dat ze niet ondersteund worden door alle programma's, en\n" -"ondertekeningen die ermee gemaakt zijn, zijn behoorlijk groot en traag\n" -"te verifiren." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Geef de sleutelgrootte" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Antwoord met \"ja\" of \"nee\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Geef de verwachtte waarde zoals aangegeven in de prompt.\n" -"Het is mogelijk om een ISO datum (JJJJ-MM-DD) op te geven, maar u zult\n" -"dan geen goede foutafhandeling krijgen, inplaats daarvan zal het\n" -"systeem deze waarde proberen te interpreteren als een interval." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Geef de naam van de eigenaar van de sleutel" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "geef a.u.b. een optioneel maar aan te raden e-mail adres." - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Geef eventueel een kanttekening" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N om de naam te veranderen.\n" -"C om het kommentaar te veranderen.\n" -"E om het e-mail adres te veranderen.\n" -"O om door te gaan met de sleutelgeneratie.\n" -"Q om te stoppen met de sleutelgeneratie." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Antwoord met \"ja\" (of alleen \"j\") om een subsleutel aan te maken." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Antwoord met \"ja\" als u ALLE gebruikersidentificaties wilt tekenen" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Antwoord \"ja\" indien u deze gebruiker echt wilt verwijderen.\n" -"Alle certificaten gaan dan ook verloren!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Antwoord met \"ja\" als het goed is om de subsleutel te verwijderen" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Dit is een geldige ondertekening van de sleutel; u hoeft deze normaal\n" -"gesproken niet te verwijderen, omdat het misschien een vertrouwens-\n" -"relatie met deze of een andere sleutel verstoort, die getekend is met\n" -"deze sleutel." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Deze ondertekening kan niet gecontroleerd worden omdat u de\n" -"bijbehorende sleutel niet heeft. U kunt het verwijderen beter\n" -"uitstellen totdat u weet welke sleutel gebruikt was, omdat het\n" -"ondertekenen met deze sleutel misschien een vertrouwensband kan\n" -"scheppen met een andere, al getekende, sleutel." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"De ondertekening is ongeldig. Het is zinnig om deze uit de sleutelbos\n" -"te verwijderen." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Dit is een ondertekening die de gebruikersidentificatie met de sleutel\n" -"verbindt. Het is meestal geen goed idee om zo'n ondertekening te\n" -"verwijderen. Wellicht is GnuPG zelfs niet meer in staat om de sleutel\n" -"hierna te gebruiken. Dus doe dit alleen als de zelfondertekening om de\n" -"een of andere reden niet geldig is, en een tweede beschikbaar is." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:244 -#, fuzzy -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "" -"Geef a.u.b. een sleuteltekst; dit is een geheime zin\n" -" blabla, blablabla, ..." - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Herhaal a.u.b. de voorgaande sleuteltekst, zodat u zeker weet wat u ingetypt " -"heeft." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Geef de naam van het bestand waaraan de ondertekening toebehoort" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Antwoord \"ja\" als het goed is om het bestand te overschrijven" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Geef a.u.b. een nieuwe bestansnaam. Als u op RETURN drukt, wordt de\n" -"standaard bestandsnaam (tussen blokhaken weergegeven) gebruikt." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Geen hulp beschikbaar" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Geen hulp beschikbaar voor `%s'" - -#: g10/keydb.c:178 -#, fuzzy, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "fout bij schrijven van de sleutelbos `%s': %s\n" - -#: g10/keydb.c:185 -#, fuzzy, c-format -msgid "keyring `%s' created\n" -msgstr "%s: sleutelbos aangemaakt\n" - -#: g10/keydb.c:575 -#, fuzzy, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "%s: kon frommeltabel niet aanmaken: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "LET OP: er zijn 2 bestanden met vertrouwelijke informatie.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s is de onveranderde\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s is de nieuwe\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Dicht dit mogelijke beveiligingsgat\n" - -#: g10/keyring.c:1346 -#, fuzzy, c-format -msgid "checking keyring `%s'\n" -msgstr "fout bij schrijven van de sleutelbos `%s': %s\n" - -#: g10/keyring.c:1377 -#, fuzzy, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu sleutels zijn tot nu toe behandeld\n" - -#: g10/keyring.c:1388 -#, fuzzy, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "sleutels en ondertekeningen opnoemen" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: sleutelbos aangemaakt\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "u moet GnuPG opnieuw starten, zodat het het nieuwe optiebestand kan " -#~ "inlezen\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Vingerafdruk:" - -#~ msgid " Fingerprint:" -#~ msgstr " Vingerafdruk:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAAM=WAARDE|gebruik deze notitiegegevens" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "het eerste teken van een notitienaam moet een letter of laag liggend " -#~ "steepje zijn\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "punten in notitienamen moeten omgeven zijn door andere tekens\n" - -#, fuzzy -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Weet je zeker dat je deze sleutellengte wilt gebruiken? " - -#, fuzzy -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr "Weet je zeker dat je deze sleutellengte wilt gebruiken? " - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Echt tekenen? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "sleutel %08lX: onze versie heeft geen zelfondertekening\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Heb je echt een sleutel nodig die zo lang is? " - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " getekend door %08lX op %s\n" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key gebruikersidentificatie" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key gebruikersidentificatie" - -#, fuzzy -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key gebruikersidentificatie" - -#~ msgid "Enter the user ID: " -#~ msgstr "Geef de gebruikersidentificatie: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "overgeslagen: openbare sleutel is al ingesteld met --encrypt-to\n" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "WARNING: This is a PGP2-style key\n" -#~ msgstr "LET OP: `%s' is een leeg bestand\n" - -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "geen sleutelserver bekend (gebruik de optie --keyserver)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: ongeldig sleutelnummer\n" - -#, fuzzy -#~ msgid "duplicate (short) key ID %08lX\n" -#~ msgstr "openbare sleutel is %08lX\n" - -#, fuzzy -#~ msgid "%lu key(s) to refresh\n" -#~ msgstr " %lu sleutels met fouten\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NAMEN]|controleer de vertrouwensdatabase" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Kon geen pad vinden dat leidt tot vertrouwen van de sleutel. Laten we\n" -#~ "eens proberen of we wat missende waarden kunnen invullen.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "Geen pad gevonden dat leidt naar een van onze sleutels.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Geen certificaten gevonden zonder betrouwbaarheidswaarden.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Betrouwbaarheidswaarden zijn niet veranderd.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "%08lx: geen informatie om een betrouwbaarheidskans te berekenen\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: fout tijdens controleren van de sleutel: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "te veel ingangen in de unk cache - uitgezet\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "bijwerken van de vertrouwensdatabase ging niet goed: %s\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "foutieve MDC aangenomen wegens een onbekende kritische bit\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "fout tijdens lezen van indexveld voor LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: verwachtte indexveld, kreeg type %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "geen pimaire sleutel voor LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "fout tijdens het lezen van primaire sleutel voor LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record mislukte: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "sleutel %08lX: opvragen van veld mislukte\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "sleutel %08lX: reeds aanwezig in de betrouwbare sleutel-tabel\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "LET OP: geheime sleutel %08lX is NIET beveiligd.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "sleutel %08lX: geheime en openbare sleutel horen niet bij elkaar\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "nummeren van de geheime sleutels mislukte: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "sleutel %08lX.%lu: Goede subsleutelbinding\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "sleutel %08lX.%lu: Foutieve subsleutelbinding: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "sleutel %08lX.%lu: Geldige sleutelterugtrekking\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "sleutel %08lX.%lu: Ongeldige sleutelterugtrekking: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Correcte zelfondertekening" - -#~ msgid "Invalid self-signature" -#~ msgstr "Ongeldige zelfondertekening" - -# User ID onvertaald -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Geldig terugtrekkingscertificaat overgeslagen wegens een nieuwere " -#~ "zelfondertekening" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Geldig terugtrekkingscertificaat voor gebruiker" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Ongeldig terugtrekkingscertificaat voor gebruiker" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Geldige terugtrekking van certificaat" - -#~ msgid "Good certificate" -#~ msgstr "Correct certificaat" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Ongeldige terugtrekking van certificaat" - -#~ msgid "Invalid certificate" -#~ msgstr "Ongeldig certificaat" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "ondert. veld %lu[%d] wijst naar een verkeerd veld.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "dubbel certificaat - verwijderd" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir mislukte: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: invoegen mislukte: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: invoegen mislukte: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: ingevoegd\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "fout bij het lezen van indexveld: %s\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr " %lu sleutels ingevoegd\n" - -#~ msgid "enumerate keyblocks failed: %s\n" -#~ msgstr "nummeren van de sleutelblokken mislukte: %s\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: indexveld zonder sleutel - overgeslagen\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr " %lu vanwege nieuwe openbare sleutels\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr " %lu sleutels overgeslagen\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr " %lu sleutels bijgewerkt\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Ooeeps, geen sleutels\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Ooeeps, geen gebruikersidentificaties\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: zoeken naar indexveld mislukte: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "sleutel %08lX: invoegen van vertrouwensveld mislukte: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "sleutel %08lX.%lu: ingevoegd in de vertrouwensdatabase\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "sleutel %08lX.%lu: aangemaakt in de toekomst (tijdsverschuiving of " -#~ "klokprobleem)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "sleutel %08lX.%lu: vervallen op %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "sleutel %08lX.%lu: betrouwbaarheidscontrole mislukt: %s\n" - -#~ msgid "user '%s' not found: %s\n" -#~ msgstr "gebruiker `%s' niet gevonden: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "kon `%s' niet opzoeken in de vertrouwensdatabase: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "" -#~ "gebruiker '%s' komt niet voor in de vertrouwensdatabase - invoegen\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "kon '%s' niet invoegen in de vertrouwensdatabase: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "" -#~ "Wilt u echt een sleutel maken om mee te ondertekenen en versleutelen? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: gebruiker niet gevonden: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "leesprobleem voor certificaat: %s\n" - -#~ msgid "can't lock keyring `%s': %s\n" -#~ msgstr "kan sleutelbos `%s' niet vergrendelen: %s\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: gebruiker niet gevonden\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "LET OP: kan nog geen lange voorkeursblokken verwerken\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: kan sleutelbos niet aanmaken: %s\n" - -#, fuzzy -#~ msgid "invalid" -#~ msgstr "ongeldige versleuteling" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "RSA sleutel kan niet gebruikt worden in deze versie\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Geen sleutel voor gebruikersidentificatie\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Geen gebruikersidentificatie voor sleutel\n" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "geheime sleutel voor ontsleuteling is niet beschikbaar\n" - -#~ msgid "" -#~ "RSA keys are deprecated; please consider creating a new key and use this " -#~ "key in the future\n" -#~ msgstr "" -#~ "RSA sleutels zijn verouderd; overweeg a.u.b. het aanmaken van een\n" -#~ "nieuwe sleutel om in de toekomst te gebruiken\n" - -#~ msgid "set debugging flags" -#~ msgstr "zet afluistervlaggen" - -#~ msgid "enable full debugging" -#~ msgstr "sta volledige aflustering toe" - -#~ msgid "do not write comment packets" -#~ msgstr "schrijf geen commentaarpakketten" - -#~ msgid "(default is 1)" -#~ msgstr "(standaard is 1)" - -#~ msgid "(default is 3)" -#~ msgstr "(standaard is 3)" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal in een v3 pakket\n" - -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "Sleutelgeneratie kan alleen gebruikt worden in interactieve modus\n" diff --git a/po/pl.po b/po/pl.po deleted file mode 100644 index 5557177d3..000000000 --- a/po/pl.po +++ /dev/null @@ -1,5358 +0,0 @@ -# Gnu Privacy Guard. -# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Janusz A. Urbanowicz , 1999, 2000, 2001, 2002. -# -# To be included in GnuPG 1.0.7 -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg-1.0.6\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-04-28 02:44+02:00\n" -"Last-Translator: Janusz A. Urbanowicz \n" -"Language-Team: Polish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-2\n" -"Content-Transfer-Encoding: 8bit\n" -"Xgettext-Options: --default-domain=gnupg --directory=.. --add-comments --" -"keyword=_ --keyword=N_ --files-from=./POTFILES.in\n" -"Files: util/secmem.c util/argparse.c cipher/random.c cipher/rand-dummy.c " -"cipher/rand-unix.c cipher/rand-w32.c g10/g10.c g10/pkclist.c g10/keygen.c " -"g10/decrypt.c g10/encode.c g10/import.c g10/keyedit.c g10/keylist.c g10/" -"mainproc.c g10/passphrase.c g10/plaintext.c g10/pref.c g10/seckey-cert.c g10/" -"sig-check.c g10/sign.c g10/trustdb.c g10/verify.c g10/status.c g10/pubkey-" -"enc.c\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Ostrzeenie: uywana pami nie jest pamici bezpieczn!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "objanienie mona przeczyta tutaj: http://www.gnupg.org/faq.html\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "operacja niemoliwa do wykonania bez dostpnej pamici bezpiecznej\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(prawdopodobnie uywany program jest niewaciwy dlatego zadania)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "tak" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "tT" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "nie" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "wyjcie" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "wW" - -#: util/errors.c:54 -msgid "general error" -msgstr "bd oglny" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "nieznany rodzaj pakietu" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "nieznana wersja" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "nieznany algorytm klucza publicznego" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "nieznany algorytm skrtu" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "niepoprawny klucz publiczny" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "niepoprawny klucz tajny" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "niepoprawny podpis" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "bd sumy kontrolnej" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "niepoprawne dugie haso." - -#: util/errors.c:64 -msgid "public key not found" -msgstr "brak klucza publicznego." - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "nieznany algorytm szyfrujcy" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "otwarcie zbioru kluczy jest niemoliwe" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "niepoprawny pakiet" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "bd w opakowaniu ASCII." - -#: util/errors.c:69 -msgid "no such user id" -msgstr "brak takiego identyfikatora uytkownika." - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "brak klucza tajnego." - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "zosta uyty niewaciwy klucz tajny" - -#: util/errors.c:72 -msgid "not supported" -msgstr "nie jest obsugiwany" - -#: util/errors.c:73 -msgid "bad key" -msgstr "niepoprawny klucz." - -#: util/errors.c:74 -msgid "file read error" -msgstr "bd przy odczycie pliku." - -#: util/errors.c:75 -msgid "file write error" -msgstr "bd przy zapisie pliku." - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "nieznany algorytm kompresji" - -#: util/errors.c:77 -msgid "file open error" -msgstr "bd przy otwieraniu pliku." - -#: util/errors.c:78 -msgid "file create error" -msgstr "bd przy tworzeniu pliku" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "niepoprawne dugie haso" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algorytm szyfrowania z kluczem publicznym nie jest zaimplementowany" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algorytm szyfrujcy nie jest zaimplementowany" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "nieznana klasa podpisu" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "bd w bazie zaufania." - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "bd MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "ograniczenie zasobw" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "bd w zbiorze kluczy" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "niepoprawny certyfikat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "bd formatu identyfikatora uytkownika" - -#: util/errors.c:89 -msgid "file close error" -msgstr "bd przy zamykaniu pliku" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "bd przy zmianie nazwy pliku" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "bd przy usuwaniu pliku" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "nieoczekiowane dane" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "konflikt znacznikw czasu" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "nieuyteczny algorytm z kluczem publicznym" - -#: util/errors.c:95 -msgid "file exists" -msgstr "plik ju istnieje" - -#: util/errors.c:96 -msgid "weak key" -msgstr "klucz saby" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "bdny argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "niepoprawny URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI nie jest obsugiwany" - -#: util/errors.c:100 -msgid "network error" -msgstr "bd sieci" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "nie zaszyfrowany" - -#: util/errors.c:103 -msgid "not processed" -msgstr "nie zosta przetworzony" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "bezuyteczny klucz publiczny" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "bezuyteczny klucz tajny" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "bd serwera kluczy" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... to jest bd w programie (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "znalaze(a) bd w programie ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "nie mona otworzy %s: %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "nie mona sprawdzi %s: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "'%s' nie jest zwykym plikiem - zostaje pominity\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "uwaga: plik random_seed jest pusty\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -"ostrzeenie: plik random_seed ma niewaciwy rozmiar - nie zostanie uyty\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "nie mona odczyta %s: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "uwaga: plik random_seed nie jest uaktualniony\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "nie mona stworzy %s: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "nie mona zapisa %s: %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "nie mona zamkn %s: %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "" -"OSTRZEENIE: uywany generator liczb losowych\n" -"nie jest kryptograficznie bezpieczny!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Uywany generator liczb losowych jest atrap wprowadzon dla umoliwienia\n" -"normalnej kompilacji - nie jest kryptograficznie bezpieczny!\n" -"\n" -"JAKIEKOLWIEK DANE GENEROWANE PRZEZ TEN PROGRAM NIE NADAJ SI DO \n" -"NORMALNEGO UYTKU I NIE ZAPEWNIAJ BEZPIECZESTWA!!\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Brakuje moliwoci wygenerowania odpowiedniej liczby losowych bajtw.\n" -"Prosz kontynuowa inne dziaania aby system mg zebra odpowiedni\n" -"ilo entropii do ich wygenerowania (brakuje %d bajtw).\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Polecenia:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[plik]|zoenie podpisu" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[plik]|zoenie podpisu na czytelnym dokumencie" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "zoenie podpisu oddzielonego od dokumentu" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "szyfrowanie danych" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[pliki]|szyfrowanie plikw" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "szyfrowanie tylko szyfrem symetrycznym" - -#: g10/g10.c:315 -msgid "store only" -msgstr "tylko zapis danych w formacie OpenPGP" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "odszyfrowywanie danych (domylnie)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[pliki]|odszyfrowywanie plikw" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "sprawdzenie podpisu" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "lista kluczy" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "lista kluczy i podpisw" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "sprawdzenie podpisw kluczy" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "lista kluczy i ich odciskw" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "lista kluczy tajnych" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "generacja nowej pary kluczy" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "usunicie klucza ze zbioru kluczy publicznych" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "usunicie klucza ze zbioru kluczy tajnych" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "zoenie podpisu na kluczu" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "zoenie prywatnego podpisu na kluczu" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "" -"zoenie na kluczu podpisu nie podlegajcego \n" -"uniewanieniu" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "" -"zoenie na kluczu podpisu prywatnego,\n" -"nie podlegajcego uniewanieniu" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "podpisanie lub modyfikacja klucza" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "tworzenie certyfikatu uniewanienia klucza" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "eksport kluczy do pliku" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "eksport kluczy do serwera kluczy" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "import kluczy z serwera kluczy" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "szukanie kluczy na serwerze" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "odwieenie kluczy z serwera" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "import/doczenie kluczy" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "wypisane sekwencji pakietw" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "eksport wartoci zaufania" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "wczytanie wartoi zaufania" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "uaktualnienie bazy zaufania" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "automatyczne uaktualnienie bazy zaufania" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "naprawa uszkodzonej bazy zaufania" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "zdjcie opakowania ASCII pliku lub potoku" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "opakowanie ASCII pliku lub potoku" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [pliki]|skrty wiadomoci" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opcje:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "plik wynikowy w opakowaniu ASCII" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NAZWA|szyfrowanie dla odbiorcy NAZWA" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NAZWA|uycie NAZWA jako domylnego adresata" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "domylny klucz jest domylnym adresatem" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "identyfikator do podpisania lub odszyfrowania" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|poziom kompresji N (0 - brak)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "kanoniczny format tekstowy" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "plik wyjciowy" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "z informacjami dodatkowymi" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "mniej komunikatww" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "bez odwoa do terminala" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "wymuszenie trzeciej wersji formatu podpisw" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "bez wymuszania trzeciej wersji formatu podpisw" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "wymuszenie czwartej wersji formatu podpisw" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "bez wymuszania czwartej wersji formatu podpisw" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "do szyfrowania bdzie uywany MDC" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "do szyfrowania nie zostanie uyty MDC" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "pozostawienie bez zmian" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "wykorzystanie gpg-agenta" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "tryb wsadowy: adnych pyta" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "automatyczna odpowied tak na wikszo pyta" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "automatyczna odpowied nie na wikszo pyta" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "doda zbir kluczy do listy uywanych" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "doda zbir kluczy tajnych do listy" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "okazanie, w ktrym zbiorze kluczy znajduje si dany klucz" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NAZWA|uycie NAZWA jako domylnego klucza tajnego" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|serwer kluczy w ktrym bd poszukiwane" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAZWA|zestaw znakw terminala NAZWA" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "wczytanie opcji z pliku" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|zapisa opis stanu do FD" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[plik]|zapisa opis stanu do pliku" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KLUCZ|klucz cakowicie zaufany" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|PLIK|adowanie moduu rozszerzenia z PLIK" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emulacja trybu opisanego w RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "tryb zgodnoci formatu pakietw, szyfrw i skrtw z OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "tryb zgodnoci formatw, szyfrw i skrtw z PGP 2.x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|N-ty tryb obliczania hasa" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|ALG|algorytm skrtu dla hasa ALG" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|ALG|algorytmu szyfrujcy ALG dla hasa" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAZWA|algorytm szyfrujcy NAZWA" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAZWA|algorytm obliczania skrtw wiadomoci NAZWA" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|algorytm kompresji N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "usunicie numerw kluczy adresatw z zaszyfrowanych pakietw" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "okazanie identyfikatora - zdjcia uytkownika" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "bez pokazywania zdj" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "polecenie wywoania przegldarki do zdj" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Pen list polece i opcji mona znale w podrczniku systemowym.)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Przykady:\n" -"\n" -" -se -r Bob [plik] podpisa i zaszyfrowa kluczem Boba\n" -" --clearsign [plik] podpisa z pozostawieniem czytelnoci dokumentu\n" -" --detach-sign [plik] podpisa z umieszczeniem podpisu w osobnym " -"pliku\n" -" --list-keys [nazwy] pokazuje klucze\n" -" --fingerprint [nazwy] pokazuje odciski kluczy\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Bdy prosimy zgasza na adres .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Wywoanie: gpg [opcje] [pliki] (-h podaje pomoc)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Skadnia: gpg [opcje] [pliki]\n" -"podpisywanie, sprawdzanie podpisw, szyfrowanie, deszyfrowanie\n" -"domylnie wykonywana operacja zaley od danych wejciowych\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Obsugiwane algorytmy:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "wywoanie: gpg [opcje]" - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "sprzeczne polecenia\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Ostrzeenie: niebezpieczne prawa wasnoci do %s \"%s\".\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Ostrzeenie: niebezpieczne prawa dostpu do %s \"%s\".\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Ostrzeenie: niebezpieczne prawa wasnoci do %s \"%s\".\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Ostrzeenie: niebezpieczne prawa dostpu do %s \"%s\".\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "UWAGA: brak domylnego pliku opcji '%s'\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "UWAGA: brak domylnego pliku opcji '%s'\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "plik opcji '%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "odczyt opcji z '%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s nie jest poprawn nazw zestawu znakw\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "niezrozumay URI serwera kluczy\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "OSTRZEENIE: '%s' jest przestarza opcj.\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "bd w opakowaniu ASCII." - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "OSTRZEENIE: '%s' jest przestarza opcj.\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "bd w zbiorze kluczy" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "nie mona ustawi cieki programw wykonywalnych na %s\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "OSTRZEENIE: program moe stworzy plik zrzutu pamici!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "OSTRZEENIE: %s powoduje obejcie %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "UWAGA: %s nie jest do normalnego uytku!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "Nie wolno uywa %s z %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s nie ma sensu z %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" -"w trybie --pgp2 mona skada tylko podpisy oddzielne lub doczone do " -"tekstu\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "w trybie --pgp2 nie mona jednoczenie szyfrowa i podpisywa\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "w trybie --pgp2 trzeba uywa plikw a nie potokw.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "szyfrowanie wiadomoci w trybie --pgp2 wymaga moduu szyfru IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "tej wiadomoci moe nie da si odczyta za pomoc PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "wybrany algorytm szyfrujcy jest niepoprawny\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "wybrany algorytm geenracji skrtw wiadomoci jest niepoprawny\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "wybrany algorytm geenracji skrtw wiadomoci jest niepoprawny\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "ustawienie algortytmu kompresji musi pochodzi z zakresu %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "warto completes-needed musi by wiksza od 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "warto marginals-needed musi by wiksza od 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "warto max-cert-depth musi mieci si w zakresie od 1 do 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "UWAGA: prosty tryb S2K (0) jest stanowczo odradzany\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "niepoprawny tryb S2K; musi mie warto 0, 1 lub 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "" -"niewaciwy domylny poziom sprawdzania; musi mie warto 0, 1 lub 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "niewaciwe ustawienia\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "niewaciwe ustawienia\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "niewaciwe ustawienia\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "niewaciwe ustawienia\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "inicjowanie Bazy Zaufania nie powiodo si: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [plik]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [plik]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [plik]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [plik]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [plik]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [plik]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [plik]\"" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [plik]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key nazwa uytkownika" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key nazwa uytkownika" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key nazwa uytkownika" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrsign-key nazwa uytkownika" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key nazwa uytkownika [polecenia]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "nie mona otworzy %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [identyfikator] [zbir kluczy]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "zdjcie opakowania ASCII nie powiodo si: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "opakowywanie ASCII nie powiodo si: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "niewaciwy algorytm skrtu ,%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nazwa pliku]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Wpisz tutaj swoj wiadomo ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "nie mona otworzy ,%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"nazwa adnotacji moe zawiera tylko litery, cyfry, kropki,\n" -"podkrelenia, i musi koczy si ,='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "warto adnotacji nie moe zawiera znakw sterujcych\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "podany URL regulaminu certyfikacji jest niepoprawny\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "podany URL regulaminu podpisw jest niepoprawny\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "opakowanie: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "niepoprawny nagwek opakowania: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "nagwek opakowania: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "niewaciwy nagwek czytelnego podpisanego dokumentu\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "zagniedone podpisy na czytelnym dokumencie\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "niepoprawne oznaczenie linii minusami: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "nieoczekiwane opakowanie:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "niewaciwy znak formatu radix64 %02x zosta pominity\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "przewczesny koniec pliku (brak CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "przedwczesny koniec pliku (w CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "bd formatu CRC\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Bd sumy CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "przedwczesny koniec pliku (w linii koczcej)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "bd w linii koczcej\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "nie odnaleziono poprawnych danych w formacie OpenPGP.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "bd opakowania: linia dusza ni %d znakw\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"znak kodowania quoted-printable w opakowaniu ASCII - prawdopodobnie\n" -"przekamanie wprowadzone przez program transportowy poczty\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Nie podano przyczyny" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Klucz zosta zastpiony" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Klucz zosta skompromitowany" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Klucz nie jest ju uywany" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Identyfikator uytkownika przesta by poprawny" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Powd uniewanienia: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Komentarz do uniewanienia: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMwWpP" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Brak wartoci zaufania dla:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Zastanw si jak bardzo ufasz temu uytkownikowi w kwestii sprawdzania\n" -"tosamoci innych wacicieli kluczy (czy sprawdzi on odciski klucza \n" -"pobrane z rnych rde, dokumenty potwierdzajce tosamo, itd.)?\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = nie wiem\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = NIE ufam mu\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = mam ograniczone zaufanie\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = mam pene zaufanie\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = ufam absolutnie\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = potrzebuj wicej informacji\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = powrt do gwnego menu\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " p = pominicie klucza\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " w = wyjcie\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Twoja decyzja? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Czy na pewno chcesz przypisa absolutne zaufanie temu kluczowi? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certyfikaty prowadzce do ostatecznie zaufanego klucza:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "klucz %08lX: klucz zosta uniewaniony!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Uy tego klucza pomimo to? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "klucz %08lX: podklucz zosta uniewaniony!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: data wanoci klucza upyna\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "%08lX: Nie ma pewnoci co do tosamoci waciciela klucza.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: NIE UFAMY temu kluczowi\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Nie ma pewne, do do kogo naley ten klucz, ale jest akceptowalny.\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Ten klucz prawdopodobnie naley do tej osoby.\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Ten klucz naley do nas\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"NIE MA pewnoci, do kogo naley ten klucz. Jeli nie masz co do\n" -"tego adnych wtpliwoci i *naprawd* wiesz co robisz moesz\n" -"odpowiedzie \"tak\" na nastpne pytanie.\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "OSTRZEENIE: uywany jest klucz nie obdarzony zaufaniem!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "OSTRZEENIE: Ten klucz zosta uniewaniony przez waciciela!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " To moe oznacza e podpis jest faszerstwem.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "OSTRZEENIE: Ten podklucz zosta uniewaniony przez waciciela!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Uwaga: Ten klucz zosta wyczony z uytku\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Uwaga: Data wanoci tego klucza upyna!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "OSTRZEENIE: Ten klucz nie jest powiadczony zaufanym podpisem!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Nie ma pewnoci co do tosamoci osoby ktra zoya podpis.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "OSTRZEENIE: NIE UFAMY temu kluczowi!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Ten podpis prawdopodobnie jest FASZERSTWEM.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"OSTRZEENIE: Tego klucza nie powiadczaj wystarczajc zaufane podpisy!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr "" -" Nie ma pewnoci co do tosamoci osoby ktra zoya ten " -"podpis.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: pominity: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: pominity: zosta ju wybrany\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Nie zosta podany identyfikatora uytkownika (np za pomoc ,,-r'')\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Identyfikator uytkownika (pusta linia oznacza koniec): " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Brak takiego identyfikatora uytkownika.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "pominity: klucz publiczny ju jest domylnym adresatem\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Klucz publiczny wyczony z uzycia.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "pominity: zosta ju wybrany\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "nieznany domylny adresat '%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: pominity: klucz publiczny wyczony z uycia\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "brak poprawnych adresatw\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "ustawienie %c%lu jest niepoprawne\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "ustawienie %c%lu powtarza si\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "zbyt wiele `%c' ustawie\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "niewaciwy znak w tekcie ustawie\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "zapis podpisu klucza nim samym\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "zapis podpisu klucza nim samym\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "zapis podpisu wicego klucz\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "niewaciwa dugo klucza; wykorzystano %u bitw\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "rozmair klucza zaokrglony do %u bitw\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Prosz wybra rodzaj klucza:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) Para kluczy dla algorytmw DSA i ElGamala (domylne)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (tylko do podpisywania)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) Klucz dla algorytmu ElGamala (tylko do szyfrowania)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) Klucz dla algorytmu ElGamala (do szyfrowania i podpisywania)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (tylko do podpisywania)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (tylko do szyfrowania)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) Klucz dla algorytmu RSA (do szyfrowania i podpisywania)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Twj wybr? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Uywanie tego algorytmu jest odradzane - tworzy mimo to? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Niewaciwy wybr.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Nastpi generacja nowej pary kluczy dla algorytmu(w) %s.\n" -" minimalny rozmiar klucza wynosi 768 bitw\n" -" domylny rozmiar klucza wynosi 1024 bity\n" -" najwikszy sugerowany rozmiar klucza wynosi 2048 bitw\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Jakiej dugoci klucz wygenerowa? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "Klucz dla DSA musi mie dugo pomidzy 512 i 1024 bitow.\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "" -"Dugo klucza zbyt maa; minimalna dopuszczalna dla RSA wynosi 1024 bity.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "Dugo klucza zbyt maa; minimalna dopuszczona wynosi 768 bitw.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "zbyt duy rozmiar klucza, ograniczenie wynosi %d.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Klucze dusze ni 2048 bitw s odradzane, poniewa obliczenia\n" -"trwaj wtedy BARDZO dugo!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Na pewno wygenerowa klucz takiej dugoci? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Naley take pamita o tym, e informacje mog by te wykradzione z\n" -"komputera przez podsuch emisji elektromagnetycznej klawiatury i monitora!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "dana dugo klucza to %u bity.\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "zaokrglono do %u bitw\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Okres wanoi klucza.\n" -" 0 = klucz nie ma okrelonego terminu wanoci\n" -" = termin wanoci klucza upywa za n dni\n" -" w = termin wanoci klucza upywa za n tygodni\n" -" m = termin wanoci klucza upywa za n miesicy\n" -" y = termin wanoci klucza upywa za n lat\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Okres wanoi podpisu.\n" -" 0 = klucz nie ma okrelonego terminu wanoci\n" -" = termin wanoci podpisu upywa za n dni\n" -" w = termin wanoci podpisu upywa za n tygodni\n" -" m = termin wanoci podpisu upywa za n miesicy\n" -" y = termin wanoci podpisu upywa za n lat\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Okres wanoci klucza ? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "Okres wanoci podpisu? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "niepoprawna warto\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s nie ma daty wanoci (nie traci wanoci z upywem czasu).\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s traci wano: %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Twj system nie potrafi pokaza daty po roku 2038.\n" -"Niemniej daty do roku 2106 bd poprawnie obsugiwane.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Dane poprawne (t/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Musisz okreli identyfikator uytkownika aby mona byo rozpozna twj\n" -"klucz; program zoy go z twojego imienia i nazwiska, komentarza i adresu\n" -"poczty elektronicznej. Bdzie on mia tak posta:\n" -" \"Tadeusz eleski (Boy) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Imi i nazwisko: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Niewaciwy znak w imieniu lub nazwisku\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Imi lub nazwisko nie moe zaczyna si od cyfry\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Imi i nazwisko musz mie conajmniej 5 znakw dugoci.\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Adres poczty elektronicznej: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "To nie jest poprawny adres poczty elektronicznej\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Komentarz: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Niewaciwy znak w komentarzu\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Uywasz zestawu znakw %s.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Twj identyfikator uytkownika bdzie wyglda tak:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" -"Nie nalezy umieszcza adresu poczty elektronicznej w polu nazwiska czy\n" -"komentarza.\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "IiKkEeDdWw" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "" -"Zmieni (I)mi/nazwisko, (K)omentarz, adres (E)mail, \n" -"czy (W)yj? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "" -"Zmieni (I)mi/nazwisko, (K)omentarz, adres (E)mail, \n" -"przej (D)alej czy (W)yj z programu ? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Najpierw trzeba poprawi ten bd\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Musisz poda dugie, skomplikowane haso aby ochroni swj klucz tajny.\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "haso nie zostao poprawnie powtrzone; jeszcze jedna prba" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Nie chcesz poda hasa - to *zy* pomys!\n" -"W kadej chwili moesz ustawi haso uywajc tego programu i opcji\n" -"\"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Musimy wygenerowa duo losowych bajtw. Dobrym pomysem podczas " -"generowania\n" -"liczb pierszych jest wykonanywanie w tym czasie innych dziaa (pisanie na\n" -"klawiaturze, poruszanie myszk, odwoanie si do dyskw); dziki temu\n" -"generator liczb losowych ma moliwo zebrania odpowiedniej iloci " -"entropii.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "Para kluczy dla DSA bdzie miaa 1024 bity dugoci.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Procedura generacji klucza zostaa anulowana.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "zapisuj klucz publiczny w '%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "zapisuj klucz tajny w '%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "brak zapisywalnego zbioru kluczy publicznych: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "brak zapisywalnego zbioru kluczy tajnych: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "bd podczas zapisu zbioru kluczy publicznych `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "bd podczas zapisu zbioru kluczy tajnych `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "klucz publiczny i prywatny (tajny) zostay utworzone i podpisane.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "klucz zosta oznaczony jako obdarzony absolutnym zaufaniem.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Ten klucz nie moe by wykorzystany do szyfrowania. Komend \"--edit-key\"\n" -"mona doda do niego podklucz uywany do szyfrowania.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Generacja klucza nie powioda si: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"klucz zosta stworzony %lu sekund w przyszoci (zaburzenia\n" -"czasoprzestrzeni, lub le ustawiony zegar systemowy)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"klucz zosta stworzony %lu sekund w przyszoci (zaburzenia\n" -"czasoprzestrzeni, lub le ustawiony zegar systemowy)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "" -"UWAGA: tworzenie podkluczy dla kluczy wersji 3 jest niezgodne z OpenPGP.\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Na pewno utworzy? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "opcja --output nie dziaa z tym poleceniem\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: nie mona otworzy: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "bd podczas tworzenia hasa: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' ju jest spakowany\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: OSTRZEENIE: plik jest pusty\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"w trybie --pgp2 mona szyfrowa dla kluczy RSA krtszych od 2048 bitw\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "odczyt z '%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"nie mona uy szyfru IDEA z wszystkimi kluczami dla ktrych szyfrujesz.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "UWAGA: brak algorytmu szyfrujcego %d w ustawieniach\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "To polecenie nie jest dostpne w trybie %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s zaszyfrowany dla: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "klucz `%s' nie zosta odaleziony: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "bd odczytu bloku kluczy: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "klucz %08lX: nie jest w formacie RFC 2440 - pominity\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "klucz %08lX: nie jest chroniony - pominity\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "klucz %08lX: klucz PGP 2.x - pominity\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "OSTRZEENIE: nic nie zostao wyeksportowane!\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "zbyt wiele wpisw w buforze kluczy publicznych - wyczony\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[brak identyfikatora uytkownika]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Niepoprawny klucz %08lX uznany za poprawny przez --allow non-selfsigned-" -"uid.\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "uywany jest podklucz %08lX zamiast klucza gwnego %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "klucz %08lX: klucz tajny bez klucza jawnego - pominity\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "blok typu %d zostaje pominity\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu kluczy przetworzonych do tej chwili\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "bd odczytu '%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Ogem przetworzonych kluczy: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " pominitych nowych kluczy: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " bez identyfikatora: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " doczono do zbioru: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " bez zmian: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nowych identyfikatorw: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nowych podkluczy: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nowych podpisw: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " nowych uniewanie kluczy: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " tajnych kluczy wczytanych: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " tajnych kluczy dodanych: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " tajnych kluczy bez zmian: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " doczono do zbioru: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "klucz %08lX: brak identyfikatora uytkownika\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "klucz %08lX: brak podklucza do dowizania\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "klucz %08lX: przyjto identyfikator nie podpisany nim samym '%s'\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "klucz %08lX: brak poprawnych identyfikatorw uytkownika\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "to moe by spowodowane brakiem podpisu waciciela klucza\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "klucz %08lX: brak klucza publicznego: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "klucz %08lX: nowy klucz - pominity\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "brak zapisywalnego zbioru kluczy: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "zapis do '%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "bd zapisu zbioru kluczy '%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "klucz %08lX: klucz publiczny wczytano do zbioru\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "klucz %08lX: nie zgadza si z lokalnie posiadan kopi\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "klucz %08lX: brak oryginalnego bloku klucza; %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "klucz %08lX: nie mona odczyta oryginalnego bloku klucza; %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "klucz %08lX: 1 nowy identyfikator uytkownika\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "klucz %08lX: %d nowych identyfikatorw uytkownika\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "klucz %08lX: 1 nowy podpis\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "klucz %08lX: %d nowych podpisw\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "klucz %08lX: 1 nowy podklucz\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "klucz %08lX: %d nowych podkluczy\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "klucz %08lX: bez zmian\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "brak domylego zbioru kluczy tajnych: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "Klucz %08lX: klucz tajny wczytany do zbioru\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "Klucz %08lX: ten klucz ju znajduje si w zbiorze\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "klucz %08lX: brak klucza tajnego: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"klucz %08lX: brak klucza publicznego - wczytany certyfikat \n" -"uniwanienia nie moe by zastosowany\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "klucz %08lX: niepoprawny certyfikat uniewanienia: %s - odrzucony\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "klucz %08lX: wczytany certyfikat uniewanienia\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "klucz %08lX: brak identyfikatora uytkownika do podpisu\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "klucz %08lX: algorytm klucza publicznego \"%s\" nie jest obsugiwany\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "klucz %08lX: niepoprawny podpis na identyfikatorze \"%s\"\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "klucz %08lX: brak podklucza do dowizania\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "" -"klucz %08lX: nie obsugiwany algorytm szyfrowania z kluczem publicznym\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "klucz %08lX: niepoprawne dowizanie podklucza\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "klucz %08lX: niepoprawne dowizanie podklucza\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "klucz %08lX: brak podklucza do dowizania\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "klucz %08lX.%lu: Poprawne uniewanienie podklucza\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "klucz %08lX: niepoprawne dowizanie podklucza\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "klucz %08lX: pominito identyfikator uytkownika '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "klucz %08lX: podklucz pominity\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "klucz %08lX: podpis nieeksportowalny (klasa %02x) - pominity\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "" -"klucz %08lX: certyfikat uniewanienia umieszczony w niewaciwym \n" -"miejscu - zosta pominity\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "klucz %08lX: niepoprawny certyfikat uniewanienia: %s - pominity\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "" -"klucz %08lX: certyfikat uniewanienia umieszczony w niewaciwym \n" -"miejscu - zosta pominity\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "key %08lX: powtrzony identyfikator uytkownika - doczony\n" - -#: g10/import.c:1389 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"Ostrzeenie: klucz %08lX mg zosta uniewazniony:\n" -" zapytanie o uniewaniajcy klucz %08lX w serwerze kluczy\n" - -#: g10/import.c:1403 -#, fuzzy, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"Ostrzeenie: klucz %08lX mg zosta uniewaniony:\n" -" brak uniewaniajcego klucza %08lX.\n" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "klucz %08lX: dodany certyfikat uniewanienia\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "klucz %08lX: dodano bezporedni podpis\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[uniewanienie]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[podpis klucza nim samym]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 niepoprawny podpis\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d niepoprawnych podpisw\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 podpis nie zosta sprawdzony z powodu braku klucza\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d podpisw nie zostao sprawdzonych z powodu braku kluczy\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 podpis nie zosta sprawdzony z powodu bdu\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d podpisw nie sprawdzonych z powodu bdw\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "wykryto 1 identyfikator uytkownika bez podpisu waciciela klucza\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "" -"wykryto %d identyfikatorw uytkownika bez podpisw waciciela klucza\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Identyfikator uytkownika \"%s\" zosta uniewaniony." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Czy na pewno chcesz podpisa? (t/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " Nie da si zoy podpisu.\n" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "OSTRZEENIE: plik '%s' jest pusty\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Twj podpis na \"%s\"\n" -"jest podpisem prywatnym (lokalnym).\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" -"Czy chcesz zamieni go na peny, publiczny, eksportowalny podpis? (t/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Twj podpis na \"%s\"\n" -"jest podpisem prywatnym (lokalnym).\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" -"Czy chcesz zamieni go na peny, publiczny, eksportowalny podpis? (t/N) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" jest ju lokalnie podpisany kluczem %08lX\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" jest ju podpisany kluczem %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nie ma nic do podpisania kluczem %08lX.\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Data wanoci tego klucza upyna!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Wano tego klucza wygasa %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "" -"Czy chcesz eby wano Twojego podpisu wygasaa w tej samej chwili? (T/n) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "W trybie --pgp2 nie mona podpisywa w formacie OpenPGP.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "To uczyni ten klucz nieuzytecznym dla PGP 2.x.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Jak dokadnie zostaa przez Ciebie sprawdzona tosamo tej osoby?\n" -"Jeli nie wiesz co odpowiedzie, podaj \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Nie odpowiem na to pytanie. %s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) W ogle nie.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Pobienie.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Bardzo dokadnie.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Czy jeste naprawd pewien e chcesz podpisa ten klucz \n" -"swoim kluczem: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "to moe by spowodowane brakiem podpisu waciciela klucza\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"Podpis zostanie oznaczony jako nieeksportowalny (prywatny).\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"Podpis zostanie oznaczony jako nie podlegajcy uniewanieniu.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"Podpis zostanie oznaczony jako nieeksportowalny (prywatny).\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"Podpis zostanie oznaczony jako nie podlegajcy uniewanieniu.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Tosamo uytkownika nie zostaa w ogle sprawdzona.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Tosamo uytkownika zostaa sprawdzona pobienie.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Tosamo uytkownika zostaa dokadnie sprawdzona.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Czy na pewno podpisa? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "zoenie podpisu nie powiodo si: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Ten klucz nie jest chroniony.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Cz tajna gwnego klucza jest niedostpna.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Klucz jest chroniony.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Tego klucza nie mona edytowa: %s.\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Wprowad nowe dugie haso dla tego klucza tajnego.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Nie chcesz hasa - to *zy* pomys!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Czy na pewno chcesz to zrobi? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "przenosz podpis klucza na waciwe miejsce\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "wyjcie z tego menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "w" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "zapis" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "zapis zmian i wyjcie" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "pomoc" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "ten tekst pomocy" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "odc" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "okazanie odcisku klucza" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "lista" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "lista kluczy i identyfikatorw uytkownikw" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "id" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "wybr identyfikatora uytkownika N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "klucz" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "wybr podklucza N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "lista" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "lista podpisw" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "l" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "podpis" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "zoenie podpisu na kluczu" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "p" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lpodpis" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "zoenie lokalnego podpisu na kluczu" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nupodpis" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "zoenie na kluczu podpisu nie podlegajcego uniewanieniu" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nulpodpis" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "zoenie na kluczu lokalnego podpisu nie podlegajcego uniewanieniu" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "ledzenia" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "dodid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "dodanie nowego identyfikatora uytkownika do klucza" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "dodfoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "dodanie zdjcia uytkownika do klucza" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "usid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "usunicie identyfikatora uytkownika z klucza" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "usfoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "dodkl" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "dodanie podklucza" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "uskl" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "usunicie podklucza" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "uniewaniony" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "dodanie podklucza" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "uspod" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "usunicie podpisw" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "data" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "zmiana daty wanoci klucza" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "gwny" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "oznaczenie identyfikatora uytkownika jako gwnego" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "prze" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "przeczenie pomidzy list kluczy publicznych i tajnych" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "p" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "opcje" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "ustawienia (zaawansowane)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "opcje" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "rozbudowana lista ustawie" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "ustaw" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "ustawienie opcji klucza" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "aktopc" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "aktualizacja ustawie klucza" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "haso" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "zmiana hasa klucza" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "zaufanie" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "zmiana zaufania waciciela" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "unpod" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "uniewanienie podpisu" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "unpkl" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "uniewanienie podklucza" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "wykl" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "wyczy klucz z uycia" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "wkl" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "wczy klucz do uycia" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "foto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "okazanie identyfikatora - zdjcia" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "nie dziaa w trybie wsadowym\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "bd odczytu bloku klucza tajnego '%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Dostpny jest klucz tajny.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Polecenie> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Do wykonania tej operacji potrzebny jest klucz tajny.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Najpierw trzeba uy polecenia \"prze\".\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "Klucz uniewaniony." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Podpisa wszystkie identyfikatory uytkownika na tym kluczu? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Podpowied: wybierz identyfikatory uytkownika do podpisania.\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "To polecenie nie jest dostpne w trybie %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Musisz wybra co najmniej jeden identyfikator uytkownika.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Nie moesz usun ostatniego identyfikatora uytkownika!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Czy na pewno usun wszystkie wybrane identyfikatory uytkownika? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Czy na pewno usun ten identyfikator uytkownika? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Musisz wybra co najmniej jeden klucz.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Czy na pewno chcesz usun wybrane klucze? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Czy na pewno chcesz usun ten klucz? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Czy na pewno chcesz uniewani wybrane klucze? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Czy na pewno chcesz uniewani ten klucz? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Czy na pewno zaktualizowa ustawienia klucza dla wybranych identyfikatorw? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Czy na pewno usaktualni ustawienia? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Zapisa zmiany? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Wyj bez zapisania zmian? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "naniesienie poprawek nie powiodo si: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "naniesienie poprawek na kluczu tajnym nie powiodo si: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "" -"Klucz nie zosta zmieniony wic naniesienie poprawek nie jest konieczne.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Niepoprawna komenda (sprbuj \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Klucz moe zosta uniewaniony przez klucz %s %s%s.\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (poufne)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX utworzony: %s, wany do: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " zaufanie: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Ten klucz zosta wyczony z uytku" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "podklucz zosta uniewaniony: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "faszywy certyfikat uniewanienia\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "problem przy sprawdzaniu uniewanienia: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -#, fuzzy -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Pokazana warto wiarygodnoci klucza moe by niepoprawna dopki program " -"nie\n" -"zostanie uruchomiony ponownie.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"OSTRZEENIE: To jest klucz PGP wersji 2. Dodanie zdjcia spowoduje, e " -"niektre \n" -" wersje przestan go rozumie.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Czy dalej chcesz je doda? (t/N) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Do klucza dla wersji 2 PGP nie mona doda zdjcia.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Usun ten poprawny podpis? (t/N/w) " - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Usun ten niepoprawny podpis? (t/N/w) " - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Usun ten nieznany podpis? (t/N/w) " - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Na pewno usun ten podpis klucza nim samym? (t/N) " - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d podpis usunity.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d podpisw usunitych.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Nic nie zostao usunite.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Wprowad rozmiar klucza" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Prosz usun znacznik wyboru z kluczy tajnych.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Prosz wybra tylko jeden podklucz.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Zmiana daty wanoci podklucza.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Zmiana daty wanoci gwnego klucza.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Nie mona zmieni daty wanoci klucza w wersji 3.\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Brak odpowiadajcego podpisu w zbiorze kluczy tajnych\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Prosz wybra dokadnie jeden identyfikator uytkownika.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "klucz %08lX: niepoprawny podpis na identyfikatorze \"%s\"\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Brak identyfikatora uytkownika o numerze %d.\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Brak podklucza o numerze %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "Identyfikator uytkownika: " - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"podpisano Twoim kluczem %08lX w %s\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"lokalnie podpisano Twoim kluczem %08lX w %s\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Wano tego klucza wygasa %s.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Czy dalej chcesz go uniewani? (t/N) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Stworzy certyfikat uniewanienia tego podpisu? (t/N) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Te identyfikatory uytkownikw s podpisane przez Ciebie:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr "podpisany przez %08lX w %s%s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr "uniewaniony przez %08lX w %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Czy na pewno chcesz uniewani te podpisy:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr "podpisany przez %08lX w %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (podpis nieeksportowalny) " - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Na pewno utworzy certyfikaty uniewanienia ? (t/N) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "brak klucza tajnego\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "Zdjcie w formacie %s, rozmiar %ld bajtw, klucz 0x%08lX (id %d).\n" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Regulamin podpisu: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Regulamin podpisu: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "OSTRZEENIE: niepoprawne dane w adnotacji\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Adnotacje podpisu: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Adnotacje podpisu: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "nieczytelne dla czowieka" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Zbir kluczy" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr " [wygasa :%s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "lista kluczy i ich odciskw" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Odcisk klucza =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Odcisk klucza =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Odcisk klucza =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Odcisk klucza =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "niewaciwy algorytm skrtu ,%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "dane zaszyfrowano za pomoc %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "dane zaszyfrowano nieznanym algorytmem numer %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "klucz publiczny %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "dane zaszyfrowane kluczem publicznym: poprawny klucz sesyjny\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "Zaszyfrowano %u-bitowym kluczem %s, numer %08lX, stworzonym %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "Zaszyfrowano kluczem %s, o numerze %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "bd odszyfrowywania kluczem publicznym: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "przyjmujc e dane zostay zaszyfrowane za pomoc %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "szyfr IDEA nie jest dostpny, %s zostanie wykorzystany zamiast niego\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "odszyfrowanie poprawne\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "OSTRZEENIE: zaszyfrowana wiadomo bya manipulowana!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "bd odszyfrowywania: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "UWAGA: nadawca zaznaczy e wiadomo nie powinna by zapisywana\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "pierwotna nazwa pliku='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "" -"osobny certyfikat uniewanienia - uyj ,,gpg --import'' aby go przyj\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Adnotacja: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Regulamin: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "wymuszono pominicie sprawdzenia podpisu\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "nie mona obsuzy tych wielokrotnych podpisw\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Podpisano w %.*s kluczem %s o numerze %08lX.\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "NIEPOPRAWNY podpis zoony przez \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Przeterminowany podpis zoony przez \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Poprawny podpis zoony przez \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[niepewne]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " alias \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Nie mona sprawdzi podpisu: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "nie jest oddzielonym podpisem.\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "oddzielony podpis klasy 0x%02x.\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "podpis starego typu (PGP 2.x).\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "wykryto niepoprawny pakiet pierwotny w proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "nie mona wyczy zrzutw pamici: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Nie naley uywa algorytmw dowiadczalnych!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"uywanie tego szyfru jest odradzane; naley uywa standardowych szyfrw!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "modu szyfru IDEA nie jest dostpny\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "wicej informacji jest tutaj: http://www.gnupg.org/why-not-idea.html\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "OSTRZEENIE: '%s' jest przestarza opcj.\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "OSTRZEENIE: '%s' jest przestarza opcj.\n" - -#: g10/misc.c:515 -#, fuzzy, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "naley uy opcji \"--keyserver-options %s\"\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "nie mona obsuy tego algorytmu klucza publicznego: %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "podpakiet typu %d ma ustawiony krytyczny bit\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent nie jest dostpny w tej sesji\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "nie mona ustawi numeru procesu klienckiego agenta\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "serwer nie chce czyta deskryptora dla agenta\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "serwer nie chce pisa deskryptora dla agenta\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "zy format zmiennej GPG_AGENT_INFO\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "wersja %d protokou agenta nie jest obsugiwana\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "nie mona si poczy z ,,%s'': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problem z porozumiewaniem si z gpg-agentem\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problem z agentem - zostaje wyczony\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (podklucz %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Musisz poda haso aby odbezpieczy klucz tajny uytkownika:\n" -"\"%.*s\".\n" -"Klucz o dugoci %u bitw, typ %s, numer %08lX, stworzony %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Haso\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Powtrzone haso\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "haso zbyt dugie\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "bdna odpowied agenta\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "anulowano przez uytkownika\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problem agenta: zwrci 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Musisz poda haso aby odbezpieczy klucz tajny uytkownika:\n" -"\"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "dugo %u bitw, typ %s, numer %08lX, stworzony %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "pytanie o haso nie dziaa w trybie wsadowym\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Podaj haso: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Powtrz haso: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"dane nie zostay zapisane; aby to zrobi, naley uy opcji \"--output\"\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "bd tworzenia `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Podpis oddzielony od danych.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Nazwa pliku danych: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "czytam strumie standardowego wejcia\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "brak podpisanych danych\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "nie mona otworzy podpisanego pliku '%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "adresat anonimowy; sprawdzanie %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "OK, to my jestemy adresatem anonimowym.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "stary, nie obsugiwany algorytm szyfrowania klucza sesyjnego\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "algorytm szyfrujcy %d%s jest nieznany, bd te zosta wyczony\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "UWAGA: brak algorytmu szyfrujcego %d w ustawieniach\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "UWAGA: wano klucza tajnego %08lX wygasa %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "klucz %08lX: klucz zosta uniewaniony!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "zapytanie o klucz %08lX w serwerze HKP %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "nie mona pobra klucza z serwera: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "bd przy wysyaniu do '%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "wysyanie do '%s' powiodo si (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "wysyanie do '%s' nie powiodo si (status=%u)\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "zapytanie o \"%s\" w serwerze HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "nie mona przeszuka serwera: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "tajne czci klucza s niedostpne\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "algorytm ochrony %d%s nie jest obsugiwany\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Niepoprawne haso; prosz sprbowa ponownie" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"OSTRZEENIE: Wykryto klucz saby algorytmu - naley ponownie zmieni haso.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"tworzenie przestarzaej 16-bitowej sumy kontrolnej dla ochrony klucza\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"Klucz algorytmu ElGamala wygenerowany przez PGP - podpisy nim skadane\n" -"nie zapewniaj bezpieczestwa!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "klucz publiczny jest o %lu sekund modszy od podpisu\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "klucz publiczny jest o %lu sekund modszy od podpisu\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"klucz zosta stworzony %lu sekund w przyszoci (zaburzenia\n" -"czasoprzestrzeni, lub le ustawiony zegar systemowy)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"klucz zosta stworzony %lu sekund w przyszoci (zaburzenia\n" -"czasoprzestrzeni, lub le ustawiony zegar systemowy)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "UWAGA: klucz podpisujcy %08lX przekroczy dat wanoci %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"przyjto niewano podpisu z powodu ustawienia nieznanego bitu krytycznego\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"OSTRZEENIE: nie mona rozkodowa urla regulaminu, pozostanie zakodowany.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"OSTRZEENIE: nie mona rozkodowa urla regulaminu, pozostanie zakodowany.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "sprawdzenie zoonego podpisu nie powiodo si: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s podpis zoony przez: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "OSTRZEENIE: plik '%s' jest pusty\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "w trybie --pgp2 mona podpisywa tylko za pomoc kluczy z wersji 2.x\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "nie mona utworzy %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "UWAGA: brak algorytmu szyfrujcego %d w ustawieniach\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "podpis:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "w trybie --pgp2 mona podpisywa tylko za pomoc kluczy z wersji 2.x\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "zostanie uyty szyfr %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "nie mona obsuy linii tekstu duszej ni %d znakw\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "linia dusza ni %d znakw\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "baza zaufania, wpis %lu: lseek() nie powioda si: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "baza zaufania, wpis %lu: zapis nie powid si (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "zbyt due zlecenie dla bazy zaufania\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: dostp niemoliwy: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: katalog nie istnieje!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: nie mona utworzy blokady\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: nie mona utworzy blokady\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: nie mona utworzy: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: stworzenie zapisu o wersji nie powiodo si: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: stworzony niepoprawny plik bazy zaufania\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: baza zaufania utworzona\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: niepoprawny plik bazy zaufania\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: tworzenie tablicy skrtw nie powiodo si: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: bd przy uaktualnianiu numeru wersji: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: bd odczytu numeru wersji: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: bd zapisu numeru wersji: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "baza zaufania: procedura lseek() zawioda: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "baza zaufania: procedura read() (n=%d) zawioda: %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: to nie jest plik bazy zaufania\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: wpis wersji z numerem %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: niewaciwa wersja pliku %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: bd odczytu pustego wpisu: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: bd zapisu wpisu katalogowego: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: zerowanie rekordu nie powiodo si: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: dopisanie rekordu nie powiodo si: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"Baza zaufania jest uszkodzona; prosz uruchomi \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' nie jest poprawnym dugim numerem klucza\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "klucz %08lX: zaakceptowany jako klucz zaufany\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "klucz %08lX jest wpisany wicej ni raz w bazie zaufania\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"klucz %08lX: brak klucza publicznego dla zaufanego klucza - pominity\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "wpis zaufania %lu, typ zapytania %d: odczyt nie powid si: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "wpis zaufania %lu jest typu innego ni poszukiwany %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "wpis zaufania %lu, typ zapytania %d: zapis nie powid si: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "baza zaufania: synchronizacja nie powioda si %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "sprawdzanie bazy jest niepotrzebne\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "nastpne sprawdzanie bazy odbdzie si %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "sprawdzanie bazy zaufania\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "klucz publiczny %08lX nie odnaleziony: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "klucz publiczny absolutnie zaufanego klucza %08lX nie odnaleziony\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"sprawdzanie na gbokoci %d podpisw =%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%" -"d)\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"nie mona sprawdzi podpisu.\n" -"Naley pamita o podawaniu pliku podpisu (.sig lub .asc) jako pierwszego\n" -"argumentu linii polece.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "linia wejcia %u zbyt duga lub brak znaku LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"klucz nie jest oznaczony jako niepewny - nie mona go uy z atrap \n" -"generatora liczb losowych!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "pominity '%s': duplikat\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "pominity '%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "pominity: klucz tajny ju znajduje si w bazie\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"pominity '%s': wygenerowany przez PGP klucz dla algorytmu ElGamala,\n" -"podpisy skadane tym kluczem nie zapewniaj bezpieczestwa!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Plik '%s' ju istnieje. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Nadpisa (t/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: nieznana kocwka\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Nazwa pliku" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "zapisywanie na wyjcie standardowe\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "przyjto obecno podpisanych danych w '%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: stworzono nowy plik ustawie\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: nie mona utworzy katalogu: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: katalog utworzony\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"OSTRZEENIE: wiadomo bya szyfrowana sabym kluczem szyfru symetrycznego.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problem podczas obrbki pakietu szyfrowego\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "wygenerowano saby klucz - operacja zostaje powtrzona\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"brak moliwoci generacji dobrego klucza dla szyfru symetrycznego;\n" -"operacja bya powtarzana %d razy!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" -"Algorytm DSA wymaga uycia algorytmu skrtu dajcego 160-bitowy wynik.\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "bez opcji \"--yes\" nie dziaa w trybie wsadowym\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Usun ten klucz ze zbioru? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "To jest klucz tajny! - czy na pewno go usun? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "usunicie bloku klucza nie powiodo si: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "informacja o zaufaniu dla waciciela klucza zostaa wymazana\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "dla klucza publicznegi ,,%s'' jest klucz tajny!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "aby go usun nalezy najpierw uy opcji \"--delete-secret-key\".\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Te wartosci uytkownik przydziela wg swojego uznania; nie bd nigdy\n" -"eksportowane poza ten system. Potrzebne s one do zbudowania sieci\n" -"zaufania, i nie ma to nic wsplnego z tworzon automatycznie sieci\n" -"certyfikatw." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Aby zbudowa Sie Zaufania, GnuPG potrzebuje zna klucze do ktrych\n" -"masz absolutne zaufanie. Zwykle s to klucze do ktrych masz klucze\n" -"tajne. Odpowiedz \"tak\", jeli chcesz okreli ten klucz jako klucz\n" -"do ktrego masz absolutne zaufanie.\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" -"Jeli mimo wszystko chcesz uy tego uniewanionego klucza, odpowiedz \"tak" -"\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Jeli mimo wszystko chcesz uy tego klucza, klucza, co do ktrego nie ma\n" -"adnej pewnoci do kogo naley, odpowiedz \"tak\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Podaj adresatw tej wiadomoci." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Wybr algorytmu.\n" -"\n" -"DSA (zwany te DSS) to algorytm podpisu cyfrowego i tylko do skadania\n" -"podpisw moe by uywany. Jest to preferowany algorytm poniewa\n" -"skadane nim podpisy sprawdza si duo szybciej ni te skadane\n" -"algorytmem ElGamala.\n" -"\n" -"Algorytm ElGamala moe by uywany zarwno do podpisw jak i do\n" -"szyfrowania. Standard OpenPGP rozrnia dwa typy tego algorytmu -\n" -"tylko do szyfrowania, oraz do szyfrowania i podpisywania. Faktycznie\n" -"algorytm pozostaje bez zmian ale pewne parametry musz by odpowiednio\n" -"dobrane aby stworzy klucz ktrym mona skada bezpieczne\n" -"podpisy. Ten program obsuguje oba typy ale inne implementacje nnie\n" -"musz rozumie kluczy do podpisw i szyfrowania\n" -"\n" -"Gwny klucz musi by kluczem podpisujcym, jest to powodem dla\n" -"ktrego w tym menu nie ma monoci wyboru klucza ElGamala do\n" -"szyfrowania." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Ten typ klucza jest zdefiniowany w RFC2440, jednake jest on odradzany\n" -"gdy nie jest obsugiwany przez wszystkie programy, a podpisy nim\n" -"skadane s due i ich sprawdzanie trwa dugo." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Wprowad rozmiar klucza" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Odpowied \"tak\" lub \"nie\"." - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Wprowad dan warto (jak w znaku zachty). \n" -"Mona tu poda dat w formacie ISO (RRRR-MM-DD) ale nie da to\n" -"waciwej obsugi bdw - system prbuje interpretowa podan warto\n" -"jako okres." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Nazwa waciciela klucza." - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "prosz wprowadzi opcjonalny ale wysoce doradzany adres e-mail" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Prosz wprowadzi opcjonalny komentarz" - -# OSTRZEENIE: nic nie zostao wyeksportowane! -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N aby zmieni nazw (nazwisko).\n" -"C aby zmieni komentarz.<\n" -"E aby zmieni adres e-mail.\n" -"O aby kontynuowa tworzenie klucza.\n" -"Q aby zrezygnowa z tworzenia klucza." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Jeli ma zosta wygenerowany podklucz, naley odpowiedzie \"tak\"." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Przy podpisywaniu identyfikatora uytkownika na kluczu naley sprawdzi, \n" -"czy tosamo uytkownika odpowiada temu, co jest wpisane w " -"identyfikatorze.\n" -"Innym uytkownikom przyda si informacja, jak dogbnie zostao to przez\n" -"Ciebie sprawdzone.\n" -"\n" -"\"0\" oznacza, e nie podajesz adnych informacji na temat tego jak " -"dogbnie\n" -" sprawdzia/e tosamo uytkownika.\n" -"\n" -"\"1\" oznacza, e masz przekonanie, e tosamo uytkownka odpowiada\n" -" identyfikatorowi klucza, ale nie byo moliwoci sprawdzenia tego.\n" -" Taka sytuacja wystpuje te kiedy podpisujesz identyfikator bdcy\n" -" pseudonimem.\n" -"\n" -"\"2\" oznacza, e tosamo uytkownika zosta przez Ciebie potwierdzona\n" -" pobienie - sprawdzilicie odcisk klucza, sprawdzia/e tosamo\n" -" na okazanym dokumencie ze zdjciem.\n" -"\n" -"\"3\" to dogbna weryfikacja tosamoci. Na przykad sprawdzenie odcisku \n" -" klucza, sprawdzenie tosamoci z okazanego oficjalnego dokumentu ze\n" -" zdjciem (np paszportu) i weryfikacja poprawnoci adresu poczty\n" -" elektronicznej przez wymian poczty z tym adresem.\n" -"\n" -"Zauwa, e podane powyej przykady dla poziomw \"2\" i \"3\" to *tylko*\n" -"przykady. Do Ciebie naley decyzja co oznacza \"pobieny\" i \"dogbny\" " -"w\n" -"kontekcie powiadczania i podpisywania kluczy.\n" -"\n" -"Jeli nie wiesz co odpowiedzie, podaj \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Odpowiedz \"tak\", aby podpisa WSZYSTKIE identyfikatory uytkownika." - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Aby skasowa ten identyfikator uytkownika (co wie si ze utrat\n" -"wszystkich jego powiadcze!) naley odpowiedzie \"tak\"." - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Aby skasowa podklucz naley odpowiedzie \"tak\"." - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"To jest poprawny podpis na tym kluczu; normalnie nie naley go usuwa\n" -"poniewa moe by wany dla zestawienia poaczenia zaufania do klucza\n" -"ktrym go zoono lub do innego klucza nim powiadczonego." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Ten podpis nie moe zosta potwierdzony poniewa nie ma\n" -"odpowiadajcego mu klucza publicznego. Naley odoy usunicie tego\n" -"podpisu do czasu, kiedy okae si ktry klucz zosta uyty, poniewa\n" -"w momencie uzyskania tego klucza moe pojawi si cieka zaufania\n" -"pomidzy tym a innym, ju powiadczonym kluczem." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "Ten podpis jest niepoprawny. Mona usuni go z bazy kluczy." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"To jest podpis wicy identyfikator uytkownika z kluczem. Nie naley\n" -"go usuwa - GnuPG moe nie mc posugiwa si dalej kluczem bez\n" -"takiego podpisu. Bezpiecznie mona go usun tylko jeli ten podpis\n" -"klucza nim samym z jakich przyczyn nie jest poprawny, i klucz jest\n" -"drugi raz podpisany w ten sam sposb." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Przestawienie wszystkich (lub tylko wybranych) identyfikatorw na aktualne\n" -"ustawienia. Data na odpowiednich podpisach zostane przesunita do przodu o\n" -"jedn sekund. \n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Podaj dugie, skomplikowane haso, np cae zdanie.\n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Prosz powrtrzy haso, aby upewni si e nie byo pomyki." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Podaj nazw pliku ktrego dotyczy ten podpis" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Jeli mona nadpisa ten plik, naley odpowiedzie ,,tak''" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Nazwa pliku. Nacinicie ENTER potwierdzi nazw domyln (w nawiasach)." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Nalezy poda powd uniewanienia klucza. W zalenoci od kontekstu mona\n" -"go wybra z listy:\n" -" \"Klucz zosta skompromitowany\"\n" -" Masz powody uwaa e twj klucz tajny dosta si w niepowoane rce.\n" -" \"Klucz zosta zastpiony\"\n" -" Klucz zosta zastpiony nowym.\n" -" \"Klucz nie jest ju uywany\"\n" -" Klucz zosta wycofany z uycia.\n" -" \"Identyfikator uytkownika przesta by poprawny\"\n" -" Identyfikator uytkownika (najczciej adres e-mail przesta by \n" -" poprawny.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Jeli chcesz, moesz poda opis powodu wystawienia certyfikatu\n" -"uniewanienia. Opis powinien byc zwizy. \n" -"Pusta linia koczy wprowadzanie tekstu.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Pomoc niedostpna" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Brak pomocy o '%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "bd tworzenia zbioru kluczy `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "zbir kluczy `%s' utworzony\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "nie powioda si odbudowa bufora bazy: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "OSTRZEENIE: Istniej dwa pliki z poufnymi informacjami.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s pozosta bez zmian\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s zosta utworzony\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Prosz usun to naruszenie zasad bezpieczestwa\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "sprawdzanie zbioru kluczy `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu kluczy do tej chwili (%lu podpisw)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu kluczy (%lu podpisw)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: zbir kluczy utworzony\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "aby uy nowego pliku ustawie, naley od nowa uruchomi GnuPG\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "zmiana uprawnie do `%s' nie powioda si: %s\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Odcisk klucza:" - -#~ msgid " Fingerprint:" -#~ msgstr " Odcisk:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAZWA=TRE|adnotacje" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "adnotacja musi zaczyna si od podkrelenia lub litery\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "kropki w adnotacji musz znajdowa si pomidzy innymi znakami\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "OSTRZEENIE: Do tego klucza dodano ju zdjcie uytkownika.\n" -#~ " Dodanie drugiego spowoduje, e niektre wersje PGP " -#~ "przestan\n" -#~ " rozumie ten klucz.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Do klucza mona doczy tylko jedno zdjcie.\n" - -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Czy na pewno chcesz to podpisa?\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " Czy na pewno chcesz go podpisa?\n" - -#~ msgid "Really sign? (y/N) " -#~ msgstr "Czy na pewno podpisa? (t/N) " - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Czy naprawd potrzebujesz takiego dugiego klucza? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "klucz %08lX: dostpna kopia nie jest podpisana ni sam\n" - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr "podpisany przez %08lX w %s\n" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key nazwa uytkownika" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key nazwa uytkownika" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key key nazwa uytkownika" - -#~ msgid "Enter the user ID: " -#~ msgstr "Podaj identyfikator uytkownika (user ID): " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "pominity: klucz publiczny ju wybrany w --encrypt-to\n" - -#~ msgid "" -#~ "\n" -#~ "WARNING: This is a PGP2-style key\n" -#~ msgstr "" -#~ "\n" -#~ "OSTRZEENIE: Klucz z PGP wersji 2.\n" - -#~ msgid "sSmMqQ" -#~ msgstr "iIpPwW" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "brak znanyk serwerw kluczy (uyj opcji --keyserver)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: nie jest poprawnym identyfikatorem klucza\n" - -#~ msgid "duplicate (short) key ID %08lX\n" -#~ msgstr "skrcony numer klucza si powtarza %08lX\n" - -#~ msgid "%lu key(s) to refresh\n" -#~ msgstr "%lu klucz(y) do odwieenia\n" - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "danie zbyt wielu losowych bitw; ograniczenie wynosi %d\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NAZWY]|sprawdzenie bazy zaufania" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Dalsze informacje znajduj si na http://www.gnupg.org/" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Niemoliwe jest znalezienie poprawnej scieki zaufania do tego klucza.\n" -#~ "Sprawdmy czy mona przypisa brakujce wartoci zaufania.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "Brak cieki prowadzcej do ktrego z naszych kluczy.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Brak certyfikatw o niezdefiniowanym poziomie zaufania.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Parametry zaufania nie zostay zmienione.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "%08lX: brak informacji aby obliczy prawdopodobiestwo zaufania\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: bd podczas sprawdzania klucza: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "Czy na pewno chcesz stworzy klucz do szyfrowania i podpisywania? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: nie znaleziono uytkownika %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "bd przy odczycie certyfikatu: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "zbyt wiele wpisw w buforze nieznanych kluczy - wyczony\n" - -#~ msgid "no default public keyring\n" -#~ msgstr "brak domylnego zbioru kluczy publicznych\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "klucz tajny %08lX nie zosta wczytany (aby to zrobi uyj %s)\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: nie znaleziono uytkownika\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "naniesienie poprawek bazy zaufania nie powiodo si: %s\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "" -#~ "przyjto niepoprawno MDC z powonu ustawienia nieznanego bitu " -#~ "krytycznego\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "bd odczytu wpisu katalogowego dla LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: oczekiwany wpis katalogowy, napotkano typ %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "brak klucza gwnego dla LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "bd odczytu gwnego klucza dla LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: funkcja search_record zawioda: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "klucz %08lX: wyszukanie zapisu nie powiodo si\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "klucz %08lX: ju znajduje si w tablicy kluczy zaufanych\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "UWAGA: klucz tajny %08lX NIE jest chroniony.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "klucz %08lX: klucz tajny nie pasuje do klucza jawnego\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "wyliczenie kluczy tajnych nie powiodo si %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "klucz %08lX.%lu Dobre dowizanie podklucza\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "klucz %08lX.%lu: Niepoprawne dowizanie podklucza %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "klucz %08lX.%lu: Poprawne uniewanienie klucza\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "klucz %08lX.%lu: Niewaciwe uniewanienie klucza: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Poprawny podpis klucza nim samym" - -#~ msgid "Invalid self-signature" -#~ msgstr "Niepoprawny podpis klucza nim samym" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Poprawne uniewanienie identyfikatora uytkownika pominite z powodu\n" -#~ "nowszego podpisu tym samym kluczem" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Poprawne uniewanienie identyfikatora uytkownika" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Niepoprawne uniewanienie identyfikatora uytkownika" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Poprawne uniewanienie certyfikatu" - -#~ msgid "Good certificate" -#~ msgstr "Poprawny certyfikat" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Niepoprawne uniewanienie certyfikatu" - -#~ msgid "Invalid certificate" -#~ msgstr "Niepoprawny certyfikat" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "zapis o podpisach %lu[%d] wskazuje na zy wpis.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "podwjny certyfikat - usunity" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "Procedura tdbio_search_dir nie powioda si: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: wpisanie nie powiodo si: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: wpisanie nie powiodo si: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: wpisany\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "bd podczas odczytu wpisu katalogowego: %s\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu kluczy wpisanych\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: wpis katalogowy bez bloku klucza - pominity\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr " %lu z powodu nowych podkluczy\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu kluczy pominitych\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu kluczy uaktualnionych\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Oops, brak kluczy\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Oops, brak identyfikatorw uytkownikw\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: poszukiwanie wpisu katalogowego nie powiodo si: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "klucz %08lX: wprowadzenie wpisu zaufania nie powiodo si: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "Klucz %08lX.%lu: wprowadzony do bazy zaufania\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "Klucz %08lX.%lu: stworzony w przyszoci (zaburzenia czasoprzestrzeni,\n" -#~ "lub le ustawiony zegar systemowy)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "klucz %08lX.%lu: okres wanoci upyn %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "klucz %08lX.%lu: bd przy sprawdzaniu zaufania: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "problem podczas szukania '%s' w bazie zaufania: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "brak uytkownika '%s' w bazie zaufania - dodano\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "umieszczenie '%s' w Bazie Zaufania nie powiodo si: %s\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "OSTRZEENIE: dugie wpisy ustawie jeszcze nie s obsugiwane.\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: stworzenie zbioru kluczy jest niemoliwe: %s\n" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "W tej wersji nie mona uywa kluczy RSA\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Brak klucza z takim identyfikatorem uytkownika.\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Brak identyfikatora uytkownika dla klucza.\n" - -#~ msgid "invalid" -#~ msgstr "niepoprawny" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "odszyfrowujcy klucz tajny do jest niedostpny\n" - -#~ msgid "set debugging flags" -#~ msgstr "ustawienie opcji ledzenia wykonania programu" - -#~ msgid "enable full debugging" -#~ msgstr "umoliwienie penego ledzenia programu" - -#~ msgid "do not write comment packets" -#~ msgstr "nie zapisywa pakietw z komentarzem" - -#~ msgid "(default is 1)" -#~ msgstr "(domylnie 1)" - -#~ msgid "(default is 3)" -#~ msgstr "(domylnie 3)" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr "" -#~ " (%d) Klucz dla algorytmu ElGamala w pakiecie w trzeciej wersji " -#~ "formatu\n" - -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "Generacj klucza mona wykonywa tylko w trybie interaktywnym\n" - -#~ msgid "" -#~ "RSA keys are deprecated; please consider creating a new key and use this " -#~ "key in the future\n" -#~ msgstr "" -#~ "Odradza si stosowanie kluczy RSA; prosz rozway przejcie na inne " -#~ "algorytmy\n" -#~ "po wygenerowaniu odpowiednich kluczy.\n" - -#~ msgid "print all message digests" -#~ msgstr "wszystkie skrty wiadomoci" - -#~ msgid "can't lock keyring `%': %s\n" -#~ msgstr "nie mona zablokowa zbioru kluczy publicznych: %s\n" - -#~ msgid "error writing keyring `%': %s\n" -#~ msgstr "bd zapisu zbioru kluczy '%': %s\n" - -#~ msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n" -#~ msgstr "" -#~ "UWAGA: wpis podpisu %lu[%d] znajduje si w licie domylnej %lu,\n" -#~ "ale jest zaznaczony jako sprawdzony.\n" - -#~ msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n" -#~ msgstr "" -#~ "UWAGA: wpis podpisu %lu[%d] znajduje si w licie domylnej %lu,\n" -#~ "ale nie jest zaznaczony.\n" - -#~ msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n" -#~ msgstr "" -#~ "wpis oi podpisie %lu[%d] w licie domylnej %lu nie wskazuje \n" -#~ "na wpis katalogowy\n" - -#~ msgid "lid %lu: no primary key\n" -#~ msgstr "lid %lu: brak klucza gwnego\n" - -#~ msgid "lid %lu: user id not found in keyblock\n" -#~ msgstr "" -#~ "lid %lu: identyfikator uytkownika nie zosta odnaleziony w bloku klucza\n" - -#~ msgid "lid %lu: user id without signature\n" -#~ msgstr "lid %lu: niepodpisany identyfikator uytkownika\n" - -#~ msgid "lid %lu: self-signature in hintlist\n" -#~ msgstr "lid %lu: podpis klucza nim samym w licie domylnej\n" - -#~ msgid "very strange: no public key\n" -#~ msgstr "bardzo dziwne: brak klucza publicznego\n" - -#~ msgid "hintlist %lu[%d] of %lu does not point to a dir record\n" -#~ msgstr "lista domylna %lu[%d] z %lu nie wskazuje na wpis katalogowy\n" - -#~ msgid "lid %lu does not have a key\n" -#~ msgstr "lid %lu nie ma klucza\n" - -#~ msgid "lid %lu: can't get keyblock: %s\n" -#~ msgstr "lid %lu: pobranie bloku klucza niemoliwe: %s\n" - -#~ msgid "Too many preference items" -#~ msgstr "Zbyt wiele pozycji w ustawieniach" - -#~ msgid "public key not anymore available" -#~ msgstr "klucz publiczny jest ju niedostpny" - -#~ msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n" -#~ msgstr "" -#~ "identyfikator %08lX.%lu/%02X%02X: ma zdublowany katalog %lu,\n" -#~ "ale nie jest jeszcze zaznaczony.\n" - -#~ msgid "insert_trust_record: keyblock not found: %s\n" -#~ msgstr "insert_trust_record: brak bloku klucza: %s\n" - -#~ msgid "lid %lu: update failed: %s\n" -#~ msgstr "lid %lu: naniesienie poprawek nie powiodo si: %s\n" - -#~ msgid "lid %lu: updated\n" -#~ msgstr "lid %lu: uaktualniony\n" - -#~ msgid "lid %lu: okay\n" -#~ msgstr "lid %lu: OK\n" - -#~ msgid "%s: update failed: %s\n" -#~ msgstr "%s: zapis zmian nie powiod si: %s\n" - -#~ msgid "%s: updated\n" -#~ msgstr "%s: uaktualniony\n" - -#~ msgid "%s: okay\n" -#~ msgstr "%s: OK\n" - -#~ msgid "lid %lu: keyblock not found: %s\n" -#~ msgstr "lid %lu: blok klucza nie zosta odnaleziony: %s\n" - -#~ msgid "edit_ownertrust.value" -#~ msgstr "" -#~ "Przypisanie tych wartoci naley do Ciebie, nie bd one udostpnione\n" -#~ "nikomu innemu. S one uywane do stworzenia sieci zaufania i nie ma\n" -#~ "to nic wsplnego z tworzon sieci certyfikatw." - -#~ msgid "revoked_key.override" -#~ msgstr "" -#~ "Jeli mimo wszystko chcesz uy tego uniewanionego klucza, odpowiedz " -#~ "\"tak\"." - -#~ msgid "untrusted_key.override" -#~ msgstr "" -#~ "Jeli mimo wszystko chcesz uy tego klucza, klucza do ktrego nie masz\n" -#~ "zaufania, odpowiedz \"tak\"." - -#~ msgid "pklist.user_id.enter" -#~ msgstr "Podaj identyfikator uytkownika adresata tych informacji." - -#~ msgid "keygen.algo" -#~ msgstr "" -#~ "Wybr algorytmu:\n" -#~ "DSA (znany te jako DSS) to Algorytm Podpisu Cyfrowego - uywa go mona " -#~ "tylko\n" -#~ "do tworzenia cyfrowych podpisw. Jego wybr jest sugerowany poniewa\n" -#~ "sprawdzanie podpisw zoonych algorytmem DSA jest duo szybsze ni tych\n" -#~ "zoonych algorytmem ElGamala.\n" -#~ "Algorytm ElGamala to algorytm klucza publicznego ktry nadaje mona " -#~ "stosowa\n" -#~ "zarwno do szyfrowania jak i do tworzenia podpisw cyfrowych\n" -#~ "W standardzie OpenPGP algorytm ElGamala wystpuje w dwch wersjach:\n" -#~ "obsugujcej podpisywanie, oraz obsugujcej podpisywanie i szyfrowanie; " -#~ "z\n" -#~ "technicznego punktu widzenia algorytm dziaa tak samo, ale pewne " -#~ "wspczynniki\n" -#~ "musz by dobrane tak aby klucz nadawa si do skadania bezpiecznych\n" -#~ "podpisw. Ten program obsuguje obie wersje, ale inne implementacje " -#~ "OpenPGP\n" -#~ "nie musz rozumie obsugiwa klucza przeznaczonego jednoczenie do\n" -#~ "podpisywania i szyfrowania.\n" -#~ "Gwny klucz musi by zawsze kluczem sucym umoliwiajcym " -#~ "podpisywanie,\n" -#~ "dlatego te ten program nie obsuguje osobnych kluczy ElGamala sucych " -#~ "tylko\n" -#~ "do szyfrowania." - -#~ msgid "keygen.algo.elg_se" -#~ msgstr "" -#~ "Mimo e ten rodzaj kluczy jest zdefiniowany w RFC 2440, wybr takiego " -#~ "klucza\n" -#~ "nie jest sugerowany. Nie wszystkie programy taki klucz s w stanie " -#~ "obsuy,\n" -#~ "a podpisy zoone za jego pomoc s due i ich sprawdzenie zajmuje duo " -#~ "czasu." - -#~ msgid "keygen.size" -#~ msgstr "Rozmiar klucza" - -#~ msgid "keygen.size.huge.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "keygen.size.large.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "keygen.valid" -#~ msgstr "Podaj dan warto" - -#~ msgid "keygen.valid.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "keygen.name" -#~ msgstr "Podaj nazw (imi, nazwisko) waciciela klucza" - -#~ msgid "keygen.email" -#~ msgstr "Adres e-mail (opcjonalny ale warto go wpisa)" - -#~ msgid "keygen.comment" -#~ msgstr "Komentarz (opcjonalny)" - -#~ msgid "keygen.userid.cmd" -#~ msgstr "" -#~ "I - zmiana imienia lub nazwiska.\n" -#~ "K - zmiana komentarza.\n" -#~ "E - zmiana adresu email.\n" -#~ "D - przejcie do waciwej generacji klucza.\n" -#~ "W - wyjcie z procedury generacji i z programu." - -#~ msgid "keygen.sub.okay" -#~ msgstr "" -#~ "Odpowiedz \"tak\" (lub po prostu \"t\") jeli zgadzasz si na stworzenie " -#~ "podklucza." - -#~ msgid "sign_uid.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "change_passwd.empty.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "keyedit.cmd" -#~ msgstr "Podaj \"help\" aby zobaczy list polece." - -#~ msgid "keyedit.save.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "keyedit.cancel.okay" -#~ msgstr "Odpowiedz \"tak\" lub \"nie\"" - -#~ msgid "keyedit.sign_all.okay" -#~ msgstr "" -#~ "Odpowiedz \"tak\" jeli chcesz podpisa wszystkie identyfikatory klucza" - -#~ msgid "keyedit.remove.uid.okay" -#~ msgstr "" -#~ "Odpowiedz \"tak\" jeli na pewno chcesz skasowa ten identyfikator " -#~ "klucza.\n" -#~ "Utracisz wszystkie podpisy innych uytkownikw zoone na tym " -#~ "identyfikatorze!" - -#~ msgid "keyedit.remove.subkey.okay" -#~ msgstr "Odpowiedz \"tak\" jeli na pewno chcesz skasowa ten podklucz" - -#~ msgid "passphrase.enter" -#~ msgstr "" -#~ "Prosz wprowadzi wyraenie przejciowe (tajne zdanie)\n" -#~ " Bla, bla, bla ..." - -#~ msgid "passphrase.repeat" -#~ msgstr "" -#~ "Prosz powtrzy podane wyraenie przejciowe dla wyeliminowania pomyek." - -#~ msgid "detached_signature.filename" -#~ msgstr "Nazwa pliku ktrego dotyczy ten podpis" - -#~ msgid "openfile.overwrite.okay" -#~ msgstr "Odpowiedz \"tak\" jeli na pewno chcesz nadpisa ten plik" - -#~ msgid "can't open file: %s\n" -#~ msgstr "nie mona otworzy pliku: %s\n" - -#~ msgid "read error: %s\n" -#~ msgstr "bd odczytu: %s\n" - -#~ msgid "writing keyblock\n" -#~ msgstr "zapisuj blok klucza\n" - -#~ msgid "can't write keyblock: %s\n" -#~ msgstr "nie mog zapisa bloku klucza: %s\n" - -#~ msgid "encrypted message is valid\n" -#~ msgstr "zaszyfrowana wiadomo jest poprawna\n" - -#~ msgid "Can't check MDC: %s\n" -#~ msgstr "Sprawdzenie MDC niemoliwe: %s\n" - -#~ msgid "Usage: gpgm [options] [files] (-h for help)" -#~ msgstr "Wywoanie: gpgm [opcje] [pliki] (-h podaje pomoc)" - -#~ msgid "" -#~ "Syntax: gpgm [options] [files]\n" -#~ "GnuPG maintenance utility\n" -#~ msgstr "" -#~ "Skadnia: gpgm [opcje] [pliki]\n" -#~ "GnuPG program obsugujcy\n" - -#~ msgid "usage: gpgm [options] " -#~ msgstr "sposb uycia: gpgm [opcje]" - -#~ msgid "chained sigrec %lu has a wrong owner\n" -#~ msgstr "powizany rekord podpisu %lu ma niewaciwego waciciela\n" - -#~ msgid "lid %lu: read dir record failed: %s\n" -#~ msgstr "lid %lu: odczyt wpisu katalogowego nie powid si: %s\n" - -#~ msgid "lid %lu: read key record failed: %s\n" -#~ msgstr "lid %lu: odczyt wpisu klucza nie powid si: %s\n" - -#~ msgid "lid %lu: read uid record failed: %s\n" -#~ msgstr "lid %lu: odczyt wpisu z identyfikatorem nie powid si; %s\n" - -#~ msgid "lid %lu: read pref record failed: %s\n" -#~ msgstr "lid %lu: odczyt wpisu ustawie nie powid si: %s\n" - -#~ msgid "user '%s' read problem: %s\n" -#~ msgstr "uytkownik '%s' bd przy odczycie: %s\n" - -#~ msgid "user '%s' list problem: %s\n" -#~ msgstr "uytkownik '%s' bd listy: %s\n" - -#~ msgid "user '%s' not in trustdb\n" -#~ msgstr "brak uytkownika '%s' w bazie zaufania\n" - -#~ msgid "" -#~ "# List of assigned trustvalues, created %s\n" -#~ "# (Use \"gpgm --import-ownertrust\" to restore them)\n" -#~ msgstr "" -#~ "# Lista przypisanych wartoci zaufania, stworzona %s\n" -#~ "# (uyj \"gpgm --import-ownertrust\" aby j przywrci)\n" - -#~ msgid "directory record w/o primary key\n" -#~ msgstr "wpis katalogowy bez klucza gwnego\n" - -#~ msgid "error: missing colon\n" -#~ msgstr "bd: brak dwukropka\n" - -#~ msgid "error: invalid fingerprint\n" -#~ msgstr "bd: niewaciwy odcisk klucza\n" - -#~ msgid "error: no ownertrust value\n" -#~ msgstr "bd: brak wartoi zaufania waciciela\n" - -#~ msgid "key not in trustdb, searching ring.\n" -#~ msgstr "brak klucza w bazie zaufania, przeszukiwany jest zbir kluczy\n" - -#~ msgid "key not in ring: %s\n" -#~ msgstr "klucza nie ma w zbiorze: %s\n" - -#~ msgid "Oops: key is now in trustdb???\n" -#~ msgstr "Oops: klucz ju jest w bazie zaufania???\n" - -#~ msgid "Hmmm, public key lost?" -#~ msgstr "Hmmm, klucz publiczny utracony?" - -#~ msgid "did not use primary key for insert_trust_record()\n" -#~ msgstr "gowny klucz nie zosta uyty w procedurze insert_trust_record()\n" - -#~ msgid "second" -#~ msgstr "sekunda" - -#~ msgid "seconds" -#~ msgstr "sekund" - -#~ msgid "invalid clear text header: " -#~ msgstr "niepoprawny nagwek tekstu jawnego:" - -#~ msgid "This key belongs to us (we have the secret key)\n" -#~ msgstr "Ten klucz naley do nas (mamy odpowiadajcy mu klucz tajny).\n" - -# %d niepoprawnych podpisw -#~ msgid "You will see a list of signators etc. here\n" -#~ msgstr "Tu ukae si lista podpisw itd.\n" diff --git a/po/pt.po b/po/pt.po deleted file mode 100644 index ab2cab474..000000000 --- a/po/pt.po +++ /dev/null @@ -1,4720 +0,0 @@ -# pt messages for gnupg -# Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Pedro Morais -# -# Based on pt_PT work done by: -# Thiago Jung Bauermann -# Rafael Caetano dos Santos -msgid "" -msgstr "" -"Project-Id-Version: gnupg\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-03-05 16:05+0000\n" -"Last-Translator: Pedro Morais \n" -"Language-Team: pt \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Aviso: a utilizar memria insegura!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "por favor veja http://www.gnupg.org/faq.html para mais informaes\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "a operao no possvel sem memria segura inicializada\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(voc pode ter usado o programa errado para esta tarefa)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "sim" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "sS" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "no" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "sair" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "erro geral" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "formato de pacote desconhecido" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "verso desconhecida" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algoritmo de chave pblica desconhecido" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algoritmo de \"digest\" desconhecido" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "chave pblica incorrecta" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "chave secreta incorrecta" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "assinatura incorrecta" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "erro de \"checksum\"" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "frase secreta incorrecta" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "chave pblica no encontrada" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algoritmo de criptografia desconhecido" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "no possvel abrir o porta-chaves" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "pacote invlido" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armadura invlida" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "identificador de utilizador inexistente" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "chave secreta no disponvel" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "chave secreta incorrecta" - -#: util/errors.c:72 -msgid "not supported" -msgstr "no suportado" - -#: util/errors.c:73 -msgid "bad key" -msgstr "chave incorrecta" - -#: util/errors.c:74 -msgid "file read error" -msgstr "erro de leitura" - -#: util/errors.c:75 -msgid "file write error" -msgstr "erro de escrita" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritmo de compresso desconhecido" - -#: util/errors.c:77 -msgid "file open error" -msgstr "erro na abertura do ficheiro" - -#: util/errors.c:78 -msgid "file create error" -msgstr "erro na criao do ficheiro" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "frase-secreta invlida" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmo de chave pblica no implementado" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritmo de criptografia no implementado" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "classe de assinatura desconhecida" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "erro na base de dados de confiana" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI incorreto" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "limite de recursos" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "porta-chaves invlido" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "certificado incorrecto" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "identificador de utilizador malformado" - -#: util/errors.c:89 -msgid "file close error" -msgstr "erro ao fechar ficheiro" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "erro na renomeao do ficheiro" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "erro na remoo do ficheiro" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "dados inesperados" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "conflito de \"timestamp\"" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritmo de chave pblica inutilizvel" - -#: util/errors.c:95 -msgid "file exists" -msgstr "o ficheiro j existe" - -#: util/errors.c:96 -msgid "weak key" -msgstr "chave fraca" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argumento invlido" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI incorrecto" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI no suportado" - -#: util/errors.c:100 -msgid "network error" -msgstr "erro na rede" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "no cifrado" - -#: util/errors.c:103 -msgid "not processed" -msgstr "no processado" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "chave pblica no utilizvel" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "chave secreta no utilizvel" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "erro do servidor de chaves" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... isto um bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "voc encontrou um bug ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "impossvel 'stat' a `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' no um ficheiro normal - ignorado\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "nota: random_seed est vazia\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "" -"aviso: o ficheiro random_seed tem um tamanho invlido - no utilizado\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "impossvel ler `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "nota: ficheiro random_seed no actualizado\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "impossvel criar `%s': %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "impossvel escrever `%s': %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "impossvel fechar `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "AVISO: a utilizar gerador de nmeros aleatrios inseguro!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"O gerador de nmeros aleatrios apenas um \"remendo\"\n" -"para poder funcionar - no de modo algum um bom gerador!\n" -"\n" -"NO USE NENHUM DADO GERADO POR ESTE PROGRAMA!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"No h bytes aleatrios suficientes. Por favor, faa outro trabalho para\n" -"que o sistema possa recolher mais entropia! (So necessrios mais %d bytes)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Comandos:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[ficheiro]|fazer uma assinatura" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[ficheiro]|fazer uma assinatura em texto puro" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "fazer uma assinatura separada" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "cifrar dados" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[ficheiros]|cifrar ficheiros" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "cifrar apenas com cifra simtrica" - -#: g10/g10.c:315 -msgid "store only" -msgstr "apenas armazenar" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "decifrar dados (aco por omisso)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[ficheiros]|decifrar ficheiros" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verificar uma assinatura" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "listar as chaves" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "listar as chaves e as assinaturas" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "verificar as assinaturas das chaves" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "listar as chaves e as impresses digitais" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "listar as chaves secretas" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "gerar um novo par de chaves" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "remover chaves do porta-chaves pblico" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "remover chaves do porta-chaves secreto" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "assinar uma chave" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "assinar uma chave localmente" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "assinar uma chave de forma no revocvel" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "assinar uma chave localmente e de forma no revocvel" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "assinar ou editar uma chave" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "gerar um certificado de revogao" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exportar chaves" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exportar chaves para um servidor de chaves" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importar chaves de um servidor de chaves" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "procurar chaves num servidor de chaves" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "actualizar todas as chaves a partir de um servidor de chaves" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importar/fundir chaves" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "listar apenas as sequncias de pacotes" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exportar os valores de confiana" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importar os valores de confiana" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "actualizar a base de dados de confiana" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "actualizar automaticamente a base de dados de confiana" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "consertar uma base de dados de confiana" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "retirar armadura de um ficheiro ou do \"stdin\"" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "criar armadura para um ficheiro ou \"stdin\"" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [ficheiros]|imprimir \"digests\" de mensagens" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opes:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "criar sada com armadura ascii" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOME|cifrar para NOME" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOME|usar NOME como destinatrio por omisso" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "usar a chave por omisso como destinatrio por omisso" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "" -"usar este identificador de utilizador para\n" -"assinar ou decifrar" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "" -"|N|estabelecer nvel de compresso N\n" -"(0 desactiva)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "usar modo de texto cannico" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "usar como ficheiro de sada" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "detalhado" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "ser mais silencioso" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "nunca usar o terminal" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "forar assinaturas v3" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "no forar assinaturas v3" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "forar assinaturas v4" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "no forar assinaturas v4" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "sempre usar um MDC para cifrar" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "nunca usar um MDC para cifrar" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "no fazer alteraes" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "utilizar o gpg-agent" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "modo no-interactivo: nunca perguntar" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "assumir sim para a maioria das perguntas" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "assumir no para a maioria das perguntas" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "" -"adicionar este porta-chaves\n" -" lista de porta-chaves" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "adicionar este porta-chaves secreto lista" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "mostrar em que porta-chave a chave est" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOME|usar NOME como chave secreta por omisso" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|ENDEREO|usar este servidor para buscar chaves" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "" -"|NOME|definir mapa de caracteres do terminal como\n" -"NOME" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "ler opes do ficheiro" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "" -"|DF|escrever informaes de estado para o\n" -"descritor de ficheiro DF" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[ficheiro]|escrever ifnroames de estado para o ficheiro" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID|confiar totalmente nesta chave" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FICHEIRO|carregar mdulo de extenso FICHEIRO" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emular o modo descrito no RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"configurar todas as opes de pacote, cifragem e \"digest\"\n" -"para comportamento OpenPGP" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"configurar todas as opes de pacote, cifragem e \"digest\"\n" -"para comportamento PGP 2.x" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|usar mode de frase secreta N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "" -"|NOME|usar algoritmo de \"digest\" de mensagens NOME\n" -"para frases secretas" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "" -"|NOME|usar algoritmo de criptografia NOME para\n" -"frases secretas" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOME|usar algoritmo de criptografia NOME" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOME|usar algoritmo de \"digest\" de mensagens NOME" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|usar algoritmo de compresso N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "eliminar campo keyid dos pacotes cifrados" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Mostrar IDs Fotogrficos" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "No mostrar IDs Fotogrficos" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Configurar linha de comandos para ver fotografias" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Veja a pgina man para uma lista completa de comandos e opes)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Exemplos:\n" -"\n" -" -se -r Bob [ficheiro] assinar e cifrar para o utilizador Bob\n" -" --clearsign [ficheiro] criar uma assinatura em texto puro\n" -" --detach-sign [ficheiro] criar uma assinatura separada\n" -" --list-keys [nomes] mostrar chaves\n" -" --fingerprint [nomes] mostrar impresses digitais\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Por favor comunique bugs para .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Uso: gpg [opes] [ficheiros] (-h para ajuda)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintaxe: gpg [opes] [ficheiros]\n" -"assina, verifica, cifra ou decifra\n" -"a operao por omisso depende dos dados de entrada\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritmos suportados:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uso: gpg [opes] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "comandos em conflito\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "Aviso: dono pouco seguro em %s \"%s\"\n" - -#: g10/g10.c:986 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "Aviso: permisses pouco seguras em %s \"%s\"\n" - -#: g10/g10.c:989 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "Aviso: dono pouco seguro em %s \"%s\"\n" - -#: g10/g10.c:993 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "Aviso: permisses pouco seguras em %s \"%s\"\n" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTA: ficheiro de opes por omisso `%s' inexistente\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTA: ficheiro de opes por omisso `%s' inexistente\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "ficheiro de opes `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "a ler opes de `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s no um conjunto de caracteres vlido\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "no consegui processar a URI do servidor de chaves\n" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "AVISO: `%s' um ficheiro vazio\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armadura invlida" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "AVISO: `%s' um ficheiro vazio\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "porta-chaves invlido" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "AVISO: O programa pode criar um ficheiro core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "AVISO: %s sobrepe %s\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTA: %s no para uso normal!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s no permitido com %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s no faz sentido com %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "s pode fazer assinaturas separadas ou em texto puro no modo --pgp2\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "no pode assinar e cifrar ao mesmo tempo no modo --pgp2\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" -"deve utilizar ficheiros (e no um 'pipe') quando trabalho no modo --pgp2.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "cifrar uma mensagem no modo --pgp2 necessita da cifra IDEA\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, fuzzy, c-format -msgid "this message may not be usable by %s\n" -msgstr "esta mensagem poder no ser utilizvel pelo PGP 2.x\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "o algoritmo de cifragem selecionado no vlido\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "o algoritmo de \"digest\" selecionado no vlido\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "o algoritmo de \"digest\" selecionado no vlido\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "o algoritmo de compresso deve estar na faixa %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed deve ser maior que 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed deve ser maior que 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth deve estar na entre 1 e 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTA: o modo S2K simples (0) no recomendvel\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "modo S2K invlido: deve ser 0, 1 ou 3\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "nvel de verificao por omisso invlido: deve ser 0, 1, 2 ou 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "preferncias invlidas\n" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "preferncias invlidas\n" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "preferncias invlidas\n" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "preferncias invlidas\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "falha ao inicializar a base de dados de confiana: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [nome_do_ficheiro]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [nome_do_ficheiro]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [nome_do_ficheiro]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [nome_do_ficheiro]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [nome_do_ficheiro]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [nome_do_ficheiro]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [nome_do_ficheiro]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [nome_do_ficheiro]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key id-utilizador" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key id-utilizador" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key id-utilizador" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key id-utilizador" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key id-utilizador [comandos]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "impossvel abrir %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [id-utilizador] [porta-chaves]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "retirada de armadura falhou: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "criao de armadura falhou: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algoritmo de disperso invlido `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nome_do_ficheiro]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Digite a sua mensagem ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "impossvel abrir `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"um nome de notao deve ter apenas letras, dgitos, pontos ou sublinhados e " -"terminar com '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "um valor de notao no deve usar caracteres de controle\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "a URL de poltica de certificao dada invlida\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "a URL de poltica de assinatura dada invlida\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armadura: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "cabealho de armadura invlido: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "cabealho de armadura: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "cabealho de assinatura em texto puro invlido\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "assinaturas em texto puro aninhadas\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "linha com hfen invlida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armadura inesperada:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "caracter radix64 invlido %02x ignorado\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "fim de ficheiro prematuro (sem CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "fim de ficheiro prematuro (no CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC malformado\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "erro de CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "fim de ficheiro prematuro (no \"Trailer\")\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "erro na ltima linha\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "nenhum dado OpenPGP vlido encontrado.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armadura invlida: linha maior que %d caracteres\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"caracter \"quoted printable\" na armadura - provavelmente um MTA com bugs " -"foi usado\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Nenhum motivo especificado" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "A chave foi substituda" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "A chave foi comprometida" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "A chave j no utilizada" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "O identificador do utilizador j no vlido" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Motivo da revocao: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "Comentrio da revocao: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Nenhum valor de confiana designado para:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Por favor decida quanto confia neste utilizador para\n" -"verificar correctamente as chaves de outros utilizadores\n" -"(vendo passaportes, verificando impresses digitais...)?\n" -"\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = No sei\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = Eu NO confio\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Confio moderadamente\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Confio plenamente\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Confio de forma total\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " i = mostrar mais informaes\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = voltar ao menu principal\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " s = saltar esta chave\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = sair\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Deciso? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Tem a certeza que quer confiar totalmente nesta chave?" - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificados que levam a uma chave confiada plenamente:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "chave %08lX: a chave foi revogada!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Usar esta chave de qualquer modo? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "chave %08lX: a subchave foi revogada!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: a chave expirou\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lx: No h indicao de que a assinatura pertence realmente ao dono.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Ns NO confiamos nesta chave\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: No se tem certeza de que esta chave realmente pertence ao dono,\n" -"mas aceite de qualquer modo\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Esta chave provavelmente pertence ao dono\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Esta chave pertence-nos\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"No se tem certeza de que esta chave pertence ao seu dono.\n" -"Se voc *realmente* sabe o que est a fazer, pode responder\n" -"sim prxima pergunta\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "AVISO: A utilizar uma chave que no de confiana!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "AVISO: Esta chave foi revogada pelo seu dono!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Isto pode significar que a assinatura falsificada.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "AVISO: Esta subchave foi revogada pelo seu dono!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Nota: Esta chave foi desactivada.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Nota: Esta chave expirou!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "AVISO: Esta chave no est certificada com uma assinatura confivel!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " No h indicao de que a assinatura pertence ao dono.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "AVISO: Ns NO confiamos nesta chave!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " A assinatura provavelmente uma FALSIFICAO.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"AVISO: Esta chave no est certificada com assinaturas suficientemente\n" -" confiveis!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " No se tem certeza de que a assinatura pertence ao dono.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: ignorado: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: ignorado: a chave pblica j est presente\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "No especificou um identificador de utilizador. (pode usar \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Insira o identificador do utilizador. Termine com uma linha vazia: " - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Identificador de utilizador inexistente.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "ignorado: chave pblica j colocada como destinatrio por omisso\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "A chave pblica est desativada.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "ignorado: a chave pblica j est presente\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "destinatrio por omisso desconhecido `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: ignorado: a chave pblica est desactivada\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "nenhum endereo vlido\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "preferncia %c%lu no vlida\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "preferncia %c%lu duplicada\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "demasiadas preferncias `%c'\n" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "caracter invlido na cadeia de caractres\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "escrevendo auto-assinatura\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "escrevendo auto-assinatura\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "escrevendo assinatura ligada a uma chave\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "tamanho de chave invlido; a utilizar %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "tamanho da chave arredondado para %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Por favor selecione o tipo de chave desejado:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA e ElGamal (por omisso)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (apenas assinatura)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (apenas cifragem)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (assinatura e cifragem)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (apenas assinatura)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (apenas cifragem)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (assinatura e cifragem)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Opo? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "A utilizao destes algoritmos est desactualizada - criar na mesma?" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Opo invlida.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Prestes a gerar um novo par de chaves %s.\n" -" tamanho mnimo 768 bits\n" -" tamanho por omisso 1024 bits\n" -" tamanho mximo sugerido 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Qual o tamanho de chave desejado? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA permite apenas tamanhos de 512 a 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "tamanho muito pequeno; 1024 o valor mnimo permitido para RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "tamanho muito pequeno; 768 o valor mnimo permitido.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "tamanho muito grande; %d o valor mximo permitido.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Tamanhos de chave maiores que 2048 no so recomendados\n" -"porque o tempo de computao REALMENTE longo!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Tudo bem, mas no se esquea que a radiao do seu monitor e teclado tambm " -" extremamente vulnervel a ataques!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "O tamanho de chave pedido %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "arredondado para %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Por favor especifique por quanto tempo a chave deve ser vlida.\n" -" 0 = chave no expira\n" -" = chave expira em n dias\n" -" w = chave expira em n semanas\n" -" m = chave expira em n meses\n" -" y = chave expira em n anos\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Por favor especifique por quanto tempo a assinatura deve ser vlida.\n" -" 0 = assinatura no expira\n" -" = assinatura expira em n dias\n" -" w = assinatura expira em n semanas\n" -" m = assinatura expira em n meses\n" -" y = assinatura expira em n anos\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "A chave valida por? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "A assinatura valida por? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valor invlido\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "A %s no expira nunca\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s expira em %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"O seu sistema no consegue mostrar datas para alm de 2038.\n" -"No entanto, estas vo ser tratadas correctamente at 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Est correto (s/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Voc precisa de um identificador de utilizador para identificar sua chave; " -"o\n" -"programa constri o identificador a partir do Nome Completo, Comentrio e\n" -"Endereo Eletrnico desta forma:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nome completo: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Caracter invlido no nome\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "O nome no pode comear com um dgito\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "O nome deve ter pelo menos 5 caracteres\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Endereo de correio eletrnico: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Endereo eletrnico invlido\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Comentrio: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Caracter invlido no comentrio\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Voc est usando o conjunto de caracteres `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Voc selecionou este identificador de utilizador:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" -"Por favor no coloque o endereo de email no nome verdadeiro ou no " -"comentrio\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoSs" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Mudar (N)ome, (C)omentrio, (E)mail ou (S)air? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Mudar (N)ome, (C)omentrio, (E)ndereo ou (O)k/(S)air? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Por favor corrija primeiro o erro\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Voc precisa de uma frase secreta para proteger a sua chave.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "a frase secreta no foi repetida corretamente; tente outra vez" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Voc no quer uma frase secreta - provavelmente isto uma *m* idia!\n" -"Vou continuar assim mesmo. Voc pode mudar sua frase secreta a\n" -"qualquer hora, usando este programa com a opo \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Precisamos gerar muitos bytes aleatrios. uma boa ideia realizar outra\n" -"actividade (escrever no teclado, mover o rato, usar os discos) durante a\n" -"gerao dos nmeros primos; isso d ao gerador de nmeros aleatrios\n" -"uma hiptese maior de ganhar entropia suficiente.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "O par de chaves DSA ter 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Gerao de chave cancelada.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "a escrever chave pblica para `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "a escrever chave privada para `%s'\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "nenhum porta-chaves pblico com permisses de escrita encontrado: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "nenhum porta-chaves secreto com permisses de escrita encontrado: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "erro ao escrever no porta-chaves pblico `%s': %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "erro ao escrever no porta-chaves secreto `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "chaves pblica e privada criadas e assinadas.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "chave marcada como de confiana absoluta\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Note que esta chave no pode ser usada para cifragem. Voc pode usar\n" -"o comando \"--edit-key\" para gerar uma chave secundria para esse fim.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "A gerao de chaves falhou: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"a chave foi criada %lu segundo no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"a chave foi criada %lu segundos no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "NOTA: a criao de sub-chave para chaves v3 no respeito o OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Realmente criar? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output no funciona para este comando\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: impossvel abrir: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "erro na criao da frase secreta: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "%s' j comprimido\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: AVISO: ficheiro vazio\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "no modo --pgp2 s pode cifrar com chaves RSA de 2048 bits ou menos\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lendo de `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"impossvel utilizar a cifra IDEA para todas as chaves para que est a " -"cifrar.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: algoritmo de cifragem %d no encontrado nas preferncias\n" - -#: g10/encode.c:703 -#, fuzzy, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Este comando no permitido no modo %s.\n" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s cifrado para: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "chave `%s' no encontrada: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "erro na leitura do bloco de chave: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "chave %08lX: no uma chave rfc2440 - ignorada\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "chave %08lX: no est protegida - ignorada\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "chave %08lX: tipo PGP 2.x - ignorada\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "AVISO: nada exportado\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "entradas demais no cache pk - desactivado\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Utilizador no encontrado]" - -#: g10/getkey.c:1438 -#, fuzzy, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "Chave invlida %08lX tornada vlida por --always-trust\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "usando chave secundria %08lX ao invs de chave primria %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "chave %08lX: chave secreta sem chave pblica - ignorada\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "ignorando bloco do tipo %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu chaves processadas at agora\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "erro na leitura de `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Nmero total processado: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " ignorei novas chaves: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sem IDs de utilizadores: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importados: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " no modificados: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " novos IDs de utilizadores: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " novas subchaves: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " novas assinaturas: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " novas revogaes de chaves: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " chaves secretas lidas: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " chaves secretas importadas: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " chaves secretas no modificadas: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importados: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "chave %08lX: sem ID de utilizador\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "chave %08lX: sem subchave para ligao de chaves\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "chave %08lX: aceite ID de utilizador sem auto-assinatura '" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "chave %08lX: sem IDs de utilizadores vlidos\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "isto pode ser causado por falta de auto-assinatura\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "chave %08lX: chave pblica no encontrada: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "chave %08lX: chave nova - ignorada\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "no foi encontrada nenhum porta-chaves onde escrever: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "a escrever para `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "erro na escrita do porta-chaves `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "chave %08lX: chave pblica importada\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "chave %08lX: no corresponde nossa cpia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "chave %08lX: impossvel localizar bloco de chaves original: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "chave %08lX: impossvel ler bloco de chaves original: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "chave %8lX: 1 novo ID de utilizador\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "chave %08lX: %d novos IDs de utilizadores\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "chave %08lX: 1 nova assinatura\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "chave %08lX: %d novas assinaturas\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "chave %08lX: 1 nova subchave\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "chave %08lX: %d novas subchaves\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "chave %08lX: no modificada\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "sem porta-chaves pblico por omisso: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "chave %08lX: chave secreta importada\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "chave %08lX: j est no porta-chaves secreto\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "chave %08lX: chave secreta no encontrada: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"chave %08lX: sem chave pblica - impossvel aplicar certificado\n" -"de revogao\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "chave %08lX: certificado de revogao invlido: %s - rejeitado\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "chave %08lX: certificado de revogao importado\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "chave %08lX: nenhum ID de utilizador para assinatura\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "chave %08lX: algoritmo de chave pblica no suportado\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "chave %08lX: auto-assinatura invlida\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "chave %08lX: sem subchave para ligao de chaves\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "chave %08lX: algoritmo de chave pblica no suportado\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "chave %08lX: sem subchave para ligao de chaves\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "chave %08lX: ignorado ID de utilizador '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "chave %08lX: subchave ignorada\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "chave %08lX: assinatura no exportvel (classe %02x) - ignorada\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "chave %08lX: certificado de revogao no local errado - ignorado\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "chave %08lX: certificado de revogao invlido: %s - ignorado\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "chave %08lX: certificado de revogao no local errado - ignorado\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "chave %08lX: detectado ID de utilizador duplicado - fundido\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "chave %08lX: certificado de revogao adicionado\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "chave %08lX: assinatura directa de chave adicionada\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revogao]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[auto-assinatura]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 assinatura incorrecta\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d assinaturas incorrectas\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 assinatura no verificada por falta de chave\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d assinaturas no verificadas por falta de chaves\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 assinatura no verificada devido a um erro\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d assinaturas no verificadas devido a erros\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 ID de utilizador sem auto-assinatura vlida detectado\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d IDs de utilizadores sem auto-assinaturas vlidas detectados\n" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Identificador do utilizador \"%s\" est revocado.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Voc tem certeza de que quer adicion-la de qualquer forma? (y/N) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "AVISO: `%s' um ficheiro vazio\n" - -#: g10/keyedit.c:399 -#, fuzzy, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"A sua assinatura actual em \"%s\"\n" -" uma assinatura local.\n" - -#: g10/keyedit.c:408 -#, fuzzy -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Quer promov-la a uma assinatura exportvel? " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"A sua assinatura actual em \"%s\"\n" -" uma assinatura local.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Quer promov-la a uma assinatura exportvel? " - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" j foi %sassinado pela chave %08lX\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" j foi %sassinado pela chave %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nada para assinar com a chave %08lX\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Esta chave expirou!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Esta chave vai expirar em %s.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Quer que a sua assinatura expire na mesma altura? (S/n) " - -#: g10/keyedit.c:535 -#, fuzzy -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "s pode assinar com chaves do tipo PGP 2.x no modo --pgp2\n" - -#: g10/keyedit.c:537 -#, fuzzy -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "esta mensagem poder no ser utilizvel pelo PGP 2.x\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Com que cuidado que verificou que chave que est prestes a assinar " -"pertence\n" -" pessoa correcta? Se no sabe o que responder, escolha \"0\".\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) No vou responder.%s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) No verifiquei.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Verifiquei por alto.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Verifiquei com bastante cuidado.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Voc tem certeza de que quer assinar esta chave com\n" -"a sua chave: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "isto pode ser causado por falta de auto-assinatura\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"A assinatura ser marcada como no-exportvel.\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"A assinatura ser marcada como no-revocvel.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"A assinatura ser marcada como no-exportvel.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"A assinatura ser marcada como no-revocvel.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"No verifiquei esta chave.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Verifiquei por alto esta chave.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Verifiquei esta chave com muito cuidado.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Realmente assinar? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "assinatura falhou: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Esta chave no protegida.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Componentes secretas da chave primria no disponveis.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "A chave protegida.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Impossvel editar esta chave: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Digite a nova frase para esta chave secreta.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Voc no quer uma frase secreta - provavelmente isto uma *m* idia!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Voc quer realmente fazer isso? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "a mover a assinatura da chave para o local correcto\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "sair deste menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "gravar e sair" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "mostra esta ajuda" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "mostra impresso digital" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "lista chave e identificadores de utilizadores" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "seleciona ID de utilizador N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "seleciona chave secundria N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "lista assinaturas" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "assina a chave" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "assina a chave localmente" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "assina a chave de forma no-revogvel" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "assinar a chave localmente e de forma no revogvel" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "adiciona um novo ID de utilizador" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "adiciona um identificador fotogrfico" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "remove ID de utilizador" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "adiciona nova chave secundria" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "remove uma chave secundria" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "adiciona nova chave secundria" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "remove assinaturas" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "muda a data de validade" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "seleccionar o identificador do utilizador como primrio" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "alterna entre listagem de chave secreta e pblica" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "lista preferncias (perito)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "lista preferncias (detalhadamente)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "configurar lista de preferncias" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "preferncias actualizadas" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "muda a frase secreta" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "muda os valores de confiana" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revoga assinaturas" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revoga uma chave secundria" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "desactiva uma chave" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "activa uma chave" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "mostrar identificador fotogrfico" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "impossvel fazer isso em modo no-interativo\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "erro na leitura do bloco de chave secreto `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Chave secreta disponvel.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Comando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "A chave secreta necessria para fazer isto.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Por favor utilize o comando \"toggle\" primeiro.\n" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "A chave est revogada.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Realmente assinar todos os IDs de utilizador? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Sugesto: Selecione os IDs de utilizador para assinar\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Este comando no permitido no modo %s.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Voc precisa selecionar pelo menos um ID de utilizador.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Voc no pode remover o ltimo ID de utilizador!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Realmente remover todos os IDs de utilizador seleccionados? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Realmente remover este ID de utilizador? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Voc deve selecionar pelo menos uma chave.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Voc quer realmente remover as chaves selecionadas? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Voc quer realmente remover esta chave? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Voc quer realmente revogar as chaves selecionadas? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Voc quer realmente revogar esta chave? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Realmente actualizar as preferncias para os utilizadores seleccionados?" - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Realmente actualizar as preferncias?" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Gravar alteraes? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Sair sem gravar? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "actualizao falhou: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "actualizao da chave secreta falhou: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Chave no alterada, nenhuma actualizao necessria.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Comando invlido (tente \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "Esta chave pode ser revogada pela chave %s %s%s\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (sensvel)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX criada: %s expira: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " confiana: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Esta chave foi desactivada" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! subchave foi revogada: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- revogao falsa encontrada\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problema ao verificar revogao: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"AVISO: Esta chave do tipo PGP2. Se adicionar um identificador fotogrfico\n" -" algumas verso do PGP podem rejeit-la.\n" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Voc tem certeza de que quer adicion-la de qualquer forma? (y/n) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" -"No pode adicionar um identificador fotogrfico a uma chave tipo PGP2.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Apagar esta assinatura vlida? (s/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Apagar esta assinatura invlida? (s/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Apagar esta assinatura desconhecida? (s/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Realmente remover esta auto-assinatura? (s/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d assinatura removida.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d assinaturas removidas.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Nada removido.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Insira o tamanho da chave" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Por favor remova as seleces das chaves secretas.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Por favor seleccione no mximo uma chave secundria.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "A modificar a data de validade para uma chave secundria.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Modificar a data de validade para uma chave primria.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Voc no pode modificar a data de validade de uma chave v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Nenhuma assinatura correspondente no porta-chaves secreto\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Seleccione exactamente um identificador de utilizador.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "chave %08lX: auto-assinatura invlida\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Nenhum ID de utilizador com ndice %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Nenhuma chave secundria com ndice %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "ID de utilizador: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"assinado com sua chave %08lX em %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"assinado com sua chave %08lX em %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "Esta chave vai expirar em %s.\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Voc tem certeza de que quer adicion-la de qualquer forma? (y/n) " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Gerar um certificado de revogao para esta assinatura? (s/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Assinou estes identificadores de utilizadores:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " assinado por %08lX em %s%s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revogado por %08lX em %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Est prestes a revogar estas assinaturas:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " assinado por %08lX em %s%s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Realmente gerar os certificados de revogao? (s/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "nenhuma chave secreta\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "Politica de assinatura: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "Politica de assinatura: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "AVISO: dados de notao invlidos encontrados\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notao da assinatura: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "Notao da assinatura: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "no legvel por humanos" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Porta-chaves" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr "[expira: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "listar as chaves e as impresses digitais" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Impresso da chave =" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Impresso da chave =" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Impresso da chave =" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Impresso da chave =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algoritmo de disperso invlido `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "dados cifrados com %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "cifrado com algoritmo desconhecido %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "a chave pblica %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "dados cifrados com chave pblica: DEK vlido\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "cifrado com chave %u-bit %s, ID %08lX, criada em %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "cifrado com chave %s, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "decifragem de chave pblica falhou: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "a assumir dados cifrados %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "Cifra IDEO no disponvel, a tentar utilizar %s em substituio\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "decifragem correcta\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "CUIDADO: a mensagem cifrada foi manipulada!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "decifragem falhou: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTA: o remetente solicitou \"apenas-para-seus-olhos\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nome do ficheiro original='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "revocao solitria - utilize \"gpg --import\" para aplicar\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notao: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Poltica: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verificao de assinatura suprimida\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "no consigo tratar estas assinaturas mltiplas\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Assinatura feita em %.*s usando %s, ID da chave %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "Assinatura INCORRECTA de \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Assinatura expirada de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Assinatura correcta de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[incerto]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " ou \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Impossvel verificar assinatura: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "no uma assinatura separada\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "assinatura de classe 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "formato de assinatura antigo (PGP2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "pacote raiz invlido detectado em proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "impossvel desactivar core dumps: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Algoritmos experimentais no devem ser usados!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"este algoritmo de criptografia est desctualizado; por favor use um " -"algoritmo mais standard!x\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "o 'plugin' com a cifra IDEA no est presente\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "veja http://www.gnupg.org/why-not-idea.html para mais informaes\n" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "AVISO: `%s' um ficheiro vazio\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "AVISO: `%s' um ficheiro vazio\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "impossvel manipular algoritmo de chave pblica %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "subpacote do tipo %d tem bit crtico ligado\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "o gpg-agent no est disponvel nesta sesso\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "no consegui colocar o pid do cliente no agente\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "no consigo obter FD de leitura no servidor para o agente\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "no consigo obter FD de escrita no servidor para o agente\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "varivel de ambiente GPG_AGENT_INFO invlida\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "a verso %d do protocolo gpg-agent no suportada\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "impossvel ligar a `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "problemas na comunicao com o gpg-agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "problema com o agente - a desactivar a utilizao deste\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (ID principal da chave %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Precisa de uma frase secreta para desbloquear a chave secreta do " -"utilizador:\n" -"\n" -"\"%.*s\"\n" -"chave %u bits %s, ID %08lx, criada %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Insira a frase secreta\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Repita a frase secreta\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "frase secreta demasiado longa\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "resposta do agente invlida\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "cancelado pelo utilizador\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problema com o agente: o agente returnou 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Voc precisa de uma frase secreta para desbloquear a chave secreta do\n" -"utilizador: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "chave de %u-bit/%s, ID %08lX, criada em %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "impossvel pedir senha em modo no-interactivo\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Digite a frase secreta: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Repita a frase secreta: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "dados no gravados; use a opo \"--output\" para grav-los\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "erro ao criar `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Assinatura separada.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Por favor digite o nome do ficheiro de dados: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lendo do \"stdin\" ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "no h dados assinados\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "impossvel abrir dados assinados `%s'\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinatrio annimo; a tentar chave secreta %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "certo, ns somos o destinatrio annimo.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "codificao antiga do DEK no suportada\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "algoritmo de cifra %d%s desconhecido ou foi desactivado\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "NOTA: algoritmo de cifragem %d no encontrado nas preferncias\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTA: chave secreta %08lX expirou em %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "chave %08lX: a chave foi revogada!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "a pedir chave %08lX do servidor de chaves HKP %s\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "no consigo obter chave do servidor: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "erro ao enviar para `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "sucesso ao enviar para `%s' (estado=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "erro ao enviar para `%s': estado=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "a procurar por \"%s\" no servidor HKP %s\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "no consigo procurar no servidor de chaves: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "partes da chave secreta no disponveis\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "algoritmo de proteco %d%s no suportado\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Frase secreta invlida; por favor tente novamente" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"AVISO: Chave fraca detectada - por favor mude a frase secreta novamente.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"esta uma chave ElGamal gerada pelo PGP que NO segura para assinaturas!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "a chave pblica %lu segundo mais nova que a assinatura\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "a chave pblica %lu segundos mais nova que a assinatura\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"a chave foi criada %lu segundo no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"a chave foi criada %lu segundos no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTA: chave de assinatura %08lx expirou %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "assumindo assinatura incorrecta devido a um bit crtico desconhecido\n" - -#: g10/sign.c:103 -#, fuzzy, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"AVISO: impossvel expandir-%% a url de poltica (demasiado grande).\n" -"A utilizar no expandida.\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"AVISO: impossvel expandir-%% a url de poltica (demasiado grande).\n" -"A utilizar no expandida.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "verificao da assinatura criada falhou: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "assinatura %s de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "AVISO: `%s' um ficheiro vazio\n" - -#: g10/sign.c:644 -#, fuzzy -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "s pode assinar com chaves do tipo PGP 2.x no modo --pgp2\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "impossvel criar %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: algoritmo de cifragem %d no encontrado nas preferncias\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "a assinar:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "s pode assinar vista com chaves do tipo PGP 2.x no modo --pgp2\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "ser utilizada a cifragem %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "impossvel manipular linhas de texto maiores que %d caracteres\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "linha de entrada maior que %d caracteres\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "base de dados de confiana rec %lu: lseek falhou: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "base de dados de confiana rec %lu: escrita falhou (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transao de base de dados de confiana muito grande\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: impossvel aceder: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: diretoria inexistente!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: impossvel criar tranca\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: impossvel criar tranca\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: impossvel criar: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: falha ao criar registo de verso: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: base de dados de confiana invlida criada\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: base de dados de confiana criada\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: base de dados de confiana invlida\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: falha ao criar tabela de disperso: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: erro a actualizar registo de verso: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: erro ao ler registo de verso: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: erro ao escrever registo de verso: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "base de dados de confiana: lseek falhou: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "base de dados de confiana: leitura falhou (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: no um base de dados de confiana\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: registo de verso com recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: verso de ficheiro invlida %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: erro ao ler registo livre: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: erro ao escrever registo de diretrio: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: falha ao zerar um registo: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: falha ao anexar um registo: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"A base de dados de confiana est danificada; por favor execute\n" -"\"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' no um identificador longo de chave vlido\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "chave %08lX: aceite como chave de confiana\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "chave %08lX ocrreu mais do que uma vez na base de dados de confiana\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"chave %08lX: nenhuma chave pblica para chave de confiana - ignorada\n" -"\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "registo de confiana %lu, tipo req %d: falha na leitura: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "registo de confiana %lu no do tipo pedido %d\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "registo de confiana %lu, tipo %d: escrita falhou: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "base de dados de confiana: sincronizao falhou: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "no necessria uma verificao da base de dados de confiana\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "proxima verificao da base de dados de confiana a %s\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "a verificar a base de dados de confiana\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "chave pblica %08lX no encontrada: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" -"chave pblica da chave absolutamente de confiana %08lX no encontrada\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"a verificar profundidade %d assinado=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"a assinatura no pode ser verificada.\n" -"No se esquea que o ficheiro com a assinatura (.sig ou .asc)\n" -"deve ser o primeiro a ser dado na linha de comando.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "linha de entrada %u demasiado longa ou falta o LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"a chave no est marcada insegura - impossvel us-la com o RNG falso!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "ignorado `%s': duplicada\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "ignorado `%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "ignorado: a chave secreta j est presente\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"ignorado `%s': esta uma chave ElGamal gerada pelo PGP que no segura " -"para assinaturas!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Arquivo `%s' j existe. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Escrever por cima (s/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: sufixo desconhecido\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Digite novo nome de ficheiro" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "a escrever em \"stdout\"\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "a assumir dados assinados em `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: novo ficheiro de opes criado\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: impossvel criar directoria: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: directoria criada\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"AVISO: A mensagem foi cifrada com uma chave fraca na cifragem simtrica.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problema ao tratar pacote cifrado\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "chave fraca criada - tentando novamente\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"impossvel evitar chave fraca para criptografia simtrica;\n" -"tentei %d vezes!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "impossvel fazer isso em modo no-interactivo sem utilizar \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Remover esta chave do porta-chaves?" - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Esta chave secreta! - apagar de qualquer modo? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "remoo do bloco de chave falhou: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "h uma chave secreta para a chave pblica \"%s\"!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "utilize a opo \"--delete-secret-keys\" para a apagar primeiro.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Voc decide que valor usar aqui; este valor nunca ser exportado para\n" -"terceiros. Precisamos dele implementar a rede de confiana, que no tem\n" -"nada a ver com a rede de certificados (implicitamente criada)." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Para construir a Teia-de-Confiana ('Web-of-Trust'), o GnuPG precisa de\n" -"saber quais so as chaves em que deposita confiana absoluta - normalmente\n" -"estas so as chaves a que tem acesso chave privada. Responda \"sim\" " -"para\n" -"que esta chave seja de confiana absoluta.\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Se voc quiser usar esta chave revogada assim mesmo, responda \"sim\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Se voc quiser usar esta chave, no de confiana, assim mesmo, responda \"sim" -"\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "" -"Digite o ID de utilizador do destinatrio para quem quer enviar a\n" -"mensagem." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Seleccione o algoritmo a ser usado.\n" -"\n" -"DSA (ou DSS) o algoritmo de assinatura digital que pode ser usado apenas\n" -"para assinaturas. Este o algoritmo recomendado porque a verificao de\n" -"assinaturas DSA muito mais rpida que a verificao de ElGamal.\n" -"\n" -"ElGamal um algoritmo que pode ser usado para assinatura e cifragem.\n" -"O OpenPGP distingue dois tipos deste algoritmo: um apenas para cifragem\n" -"e outro para assinatura+cifragem; na verdade so iguais, mas alguns\n" -"parmetros precisam ser escolhidos de modo especial para criar uma chave\n" -"segura para assinatura: este programa faz isso, mas algumas outras\n" -"implementaes do OpenPGP no vo necessariamente entender o tipo\n" -"assinatura+cifragem.\n" -"\n" -"A chave primria precisa sempre ser uma chave capaz de fazer assinaturas;\n" -"este o motivo pelo qual a chave ElGamal apenas para cifragem no est\n" -"disponvel neste menu." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Apesar de estas chaves estarem definidas no RFC2440, elas no so " -"recomendadas\n" -"porque no so suportadas por todos os programas e assinaturas criadas com\n" -"elas so grandes e sua verificao lenta." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Insira o tamanho da chave" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Responda \"sim\" ou \"no\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Digite o valor necessrio conforme pedido.\n" -" possvel digitar uma data ISO (AAAA-MM-DD) mas voc no ter uma boa\n" -"reaco a erros - o sistema tentar interpretar o valor dado como um " -"intervalo." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Digite o nome do possuidor da chave" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "por favor digite um endereo de email (opcional mas recomendado)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Por favor digite um comentrio (opcional)" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N para mudar o nome.\n" -"C para mudar o comentrio.\n" -"E para mudar o endereo de email\n" -"O para continuar a gerao da chave.\n" -"S para interromper a gerao da chave." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Responda \"sim\" (ou apenas \"s\") se quiser gerar a subchave." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Quando assina uma chave de identificao de um utilizador, deve primeiro\n" -"verificar que a chave pertence realmente pessoa em questo. til para\n" -"terceiros saberem com que cuidado que efectuou esta verificao.\n" -"\n" -"\"0\" significa que no deseja declarar a forma com verificou a chave\n" -"\n" -"\"1\" significa que acredita que a chave pertence pessoa em questo, mas\n" -" no conseguiu ou no tentou verificar. Este grau til para quando\n" -" assina a chave de uma utilizador pseudo-annimo.\n" -"\n" -"\"2\" significa que efectuou uma verificao normal da chave. Por exemplo,\n" -" isto pode significar que verificou a impresso digital da chave e\n" -" verificou o identificador de utilizador da chave contra uma " -"identificao\n" -" fotogrfica.\n" -"\n" -"\"3\" significa que efectuou uma verificao exaustiva da chave. Por " -"exemplo,\n" -" isto pode significar que efectuou a verificao pessoalmente, e que \n" -" utilizou um documento, com fotografia, difcil de falsificar \n" -" (como por exemplo um passaporte) que o nome do dono da chave o\n" -" mesmo do que o identificador da chave, e que, finalmente, verificou\n" -" (atravs de troca de e-mail) que o endereo de email da chave pertence\n" -" ao done da chave.\n" -"\n" -"Ateno: os exemplos dados para os nveis 2 e 3 so *apenas* exemplos.\n" -"Compete-lhe a si decidir o que considera, ao assinar chaves, uma " -"verificao\n" -"\"normal\" e uma verificao \"exaustiva\".\n" -"\n" -"Se no sabe qual a resposta correcta, responda \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Responda \"sim\" se quiser assinar TODOS os IDs de utilizador" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Responda \"sim\" se quiser realmente remover este ID de utilizador.\n" -"Todos os certificados tambm sero perdidos!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Responda \"sim\" se quiser remover a subchave" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Esta uma assinatura vlida na chave; normalmente no desejvel\n" -"remover esta assinatura porque ela pode ser importante para estabelecer\n" -"uma conexo de confiana chave ou a outra chave certificada por esta." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Esta assinatura no pode ser verificada porque voc no tem a chave\n" -"correspondente. Voc deve adiar sua remoo at saber que chave foi usada\n" -"porque a chave desta assinatura pode estabelecer uma conexo de confiana\n" -"atravs de outra chave j certificada." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "A assinatura no vlida. Faz sentido remov-la do seu porta-chaves." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Esta uma assinatura que liga o ID de utilizador chave. Geralmente\n" -"no uma boa idia remover tal assinatura. possvel que o GnuPG\n" -"no consiga mais usar esta chave. Faa isto apenas se por alguma\n" -"razo esta auto-assinatura no for vlida e h uma segunda disponvel." - -#: g10/helptext.c:237 -#, fuzzy -msgid "" -"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" -msgstr "" -"Muda as preferncias de todos os identificadores de utilizadores\n" -"(ou apenas dos seleccionados) para a lista actual de preferncias.\n" -"O 'timestamp' de todas as auto-assinaturas afectuadas ser avanado\n" -"em um segundo.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Por favor digite a frase secreta \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Por favor repita a frase secreta, para ter certeza do que digitou." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "D o nome para o ficheiro ao qual a assinatura se aplica" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Responda \"sim\" se quiser escrever por cima do ficheiro" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Por favor digite um novo nome de ficheiro. Se voc apenas carregar em " -"RETURN\n" -"o ficheiro por omisso (que mostrado entre parnteses) ser utilizado." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Deve especificar uma razo para a emisso do certificado. Dependendo no\n" -"contexto, pode escolher as seguintes opes desta lista:\n" -" \"A chave foi comprometida\"\n" -" Utilize esta opo se tem razes para acreditar que indivduos no\n" -" autorizados obtiveram acesso sua chave secreta.\n" -" \"A chave foi substituida\"\n" -" Utilize esta opo se substituiu esta chave com uma mais recente.\n" -" \"A chave j no utilizada\"\n" -" Utilize esta opo se j no utiliza a chave.\n" -" \"O identificador do utilizador j no vlido\"\n" -" Utilize esta opo para comunicar que o identificador do utilizador\n" -" no deve ser mais utilizado; normalmente utilizada para indicar\n" -" que um endereo de email invlido.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Se desejar, pode inserir uma texto descrevendo a razo pela qual criou\n" -"este certificado de revogao. Por favor mantenha este texto conciso.\n" -"Uma linha vazia termina o texto.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Nenhuma ajuda disponvel" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Nenhuma ajuda disponvel para `%s'" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "erro ao criar porta-chaves `%s': %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "porta-chaves `%s' criado\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "falha ao criar 'cache' do porta-chaves: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "AVISO: existem 2 ficheiros com informaes confidenciais.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s o no modificado\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s o novo\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Por favor conserte esta possvel falha de segurana\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "a verificar o porta chaves `%s'\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu chaves verificadas at agora (%lu assinaturas)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu chave verificadas (%lu assinaturas)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: porta-chaves criado\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "vai ter de reiniciar o GnuPG, para poder ler as novas opes\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "a mudana de permisses de `%s' falhou: %s\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Impresso digital:" - -#~ msgid " Fingerprint:" -#~ msgstr " Impresso digital:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOME=VALOR|usar estes dados de notao" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "o primeiro caracter de um nome de notao deve ser uma letra ou um " -#~ "sublinhado\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "pontos num nome de notao devem estar cercados por outros caracteres\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "AVISO: Esta chave j tem um identificador fotogrfico.\n" -#~ " Se adicionar outro pode confundir algumas verso do PGP.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "S pode ter um identificador fotogrfico por chave.\n" - -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Voc tem certeza de que quer assin-la?\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " Voc tem a certeza que quer mesmo assim assin-la?\n" - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Realmente assinar? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "chave %08lX: a nossa cpia no tem auto-assinatura\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Voc precisa realmente de uma chave to grande? " - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " assinado por %08lX em %s\n" diff --git a/po/pt_BR.po b/po/pt_BR.po deleted file mode 100644 index a97f9018a..000000000 --- a/po/pt_BR.po +++ /dev/null @@ -1,5222 +0,0 @@ -# Portuguese (Brazilian) messages for gnupg -# Copyright (C) 1999, 2002 Free Software Foundation, Inc. -# Thiago Jung Bauermann , 1999. -# Revised by Rafael Caetano dos Santos . -# I tried to make this one close to es_ES by Urko Lusa -# -# Rafael Caetano dos Santos used to be -# the last translator but he can't continue his work. -# -msgid "" -msgstr "" -"Project-Id-Version: GNU gnupg 1.0\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 1998-11-20 23:46:36-0200\n" -"Last-Translator:\n" -"Language-Team: ?\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Aviso: usando memria insegura!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "a operao no possvel sem memria segura inicializada\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(voc pode ter usado o programa errado para esta tarefa)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "sim" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "sS" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "no" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -# INICIO MENU -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "sair" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" - -#: util/errors.c:54 -msgid "general error" -msgstr "erro geral" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "formato de pacote desconhecido" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "verso desconhecida" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "algoritmo de chave pblica desconhecido" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "algoritmo de \"digest\" desconhecido" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "chave pblica incorreta" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "chave secreta incorreta" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "assinatura incorreta" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "erro de \"checksum\"" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "frase secreta incorreta" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "chave pblica no encontrada" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "algoritmo de criptografia desconhecido" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "no possvel abrir o chaveiro" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "pacote invlido" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "armadura invlida" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "identificador de usurio inexistente" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "chave secreta no disponvel" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "chave secreta incorreta" - -# suportado ??? -#: util/errors.c:72 -msgid "not supported" -msgstr "no suportado" - -#: util/errors.c:73 -msgid "bad key" -msgstr "chave incorreta" - -#: util/errors.c:74 -msgid "file read error" -msgstr "erro de leitura" - -#: util/errors.c:75 -msgid "file write error" -msgstr "erro de escrita" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "algoritmo de compresso desconhecido" - -#: util/errors.c:77 -msgid "file open error" -msgstr "erro na abertura de arquivo" - -#: util/errors.c:78 -msgid "file create error" -msgstr "erro na criao de arquivo" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "frase secreta invlida" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmo de chave pblica no implementado" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "algoritmo de criptografia no implementado" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "classe de assinatura desconhecida" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "erro no banco de dados de confiabilidade" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI incorreto" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "limite de recurso" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "chaveiro invlido" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "certificado incorreto" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "identificador de usurio malformado" - -#: util/errors.c:89 -msgid "file close error" -msgstr "erro no fechamento de arquivo" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "erro na renomeao de arquivo" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "erro na remoo de arquivo" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "dados inesperados" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "conflito de \"timestamp\"" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "algoritmo de chave pblica inutilizvel" - -#: util/errors.c:95 -msgid "file exists" -msgstr "o arquivo j existe" - -#: util/errors.c:96 -msgid "weak key" -msgstr "chave fraca" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "argumento invlido" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI incorreto" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "URI no suportado" - -#: util/errors.c:100 -msgid "network error" -msgstr "erro na rede" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "no criptografado" - -#: util/errors.c:103 -msgid "not processed" -msgstr "no processado(s)" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -#, fuzzy -msgid "unusable public key" -msgstr "chave pblica incorreta" - -#: util/errors.c:106 -#, fuzzy -msgid "unusable secret key" -msgstr "chave secreta incorreta" - -#: util/errors.c:107 -#, fuzzy -msgid "keyserver error" -msgstr "erro geral" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... isto um bug (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "voc encontrou um bug ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: cipher/random.c:385 -#, fuzzy, c-format -msgid "can't stat `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "AVISO: dados de notao invlidos encontrados\n" - -#: cipher/random.c:409 -#, fuzzy, c-format -msgid "can't read `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "" - -#: cipher/random.c:467 -#, fuzzy, c-format -msgid "can't create `%s': %s\n" -msgstr "impossvel criar %s: %s\n" - -#: cipher/random.c:474 -#, fuzzy, c-format -msgid "can't write `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: cipher/random.c:477 -#, fuzzy, c-format -msgid "can't close `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "AVISO: usando gerador de nmeros aleatrios inseguro!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"O gerador de nmeros aleatrios apenas um \"remendo\"\n" -"para poder funcionar - no de modo algum um bom gerador!\n" -"\n" -"NO USE NENHUM DADO GERADO POR ESTE PROGRAMA!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"No h bytes aleatrios suficientes. Por favor, faa algum outro trabalho\n" -"para que o sistema possa coletar mais entropia!\n" -"(So necessrios mais %d bytes)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Comandos:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[arquivo]|fazer uma assinatura" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[arquivo]|fazer uma assinatura em texto puro" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "fazer uma assinatura separada" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "criptografar dados" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "" -"criptografar apenas com criptografia\n" -"simtrica" - -#: g10/g10.c:315 -msgid "store only" -msgstr "apenas armazenar" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "descriptografar dados (padro)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verificar uma assinatura" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "listar as chaves" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "listar as chaves e as assinaturas" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "verificar as assinaturas das chaves" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "listar as chaves e as impresses digitais" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "listar as chaves secretas" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "gerar um novo par de chaves" - -#: g10/g10.c:327 -#, fuzzy -msgid "remove keys from the public keyring" -msgstr "remover a chave do chaveiro pblico" - -#: g10/g10.c:329 -#, fuzzy -msgid "remove keys from the secret keyring" -msgstr "remover a chave do chaveiro secreto" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "assinar uma chave" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "assinar uma chave localmente" - -#: g10/g10.c:332 -#, fuzzy -msgid "sign a key non-revocably" -msgstr "assinar uma chave localmente" - -#: g10/g10.c:333 -#, fuzzy -msgid "sign a key locally and non-revocably" -msgstr "assinar uma chave localmente" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "assinar ou editar uma chave" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "gerar um certificado de revogao" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exportar chaves" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exportar chaves para um servidor" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importar chaves de um servidor" - -#: g10/g10.c:341 -#, fuzzy -msgid "search for keys on a key server" -msgstr "exportar chaves para um servidor" - -#: g10/g10.c:343 -#, fuzzy -msgid "update all keys from a keyserver" -msgstr "importar chaves de um servidor" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importar/fundir chaves" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "listar apenas as seqncias de pacotes" - -# ownertrust ??? -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exportar os valores de confiana" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importar os valores de confiana" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "atualizar o banco de dados de confiabilidade" - -#: g10/g10.c:357 -#, fuzzy -msgid "unattended trust database update" -msgstr "atualizar o banco de dados de confiabilidade" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "" -"consertar um banco de dados de confiabilidade\n" -"danificado" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "retirar a armadura de um arquivo ou de \"stdin\"" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "criar armadura para um arquivo ou \"stdin\"" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [arquivos]|imprimir \"digests\" de mensagens" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Opes:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "criar sada com armadura ascii" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NOME|criptografar para NOME" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NOME|usar NOME como destinatrio padro" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "usar a chave padro como destinatrio padro" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "" -"usar este identificador de usurio para\n" -"assinar ou descriptografar" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "" -"|N|estabelecer nvel de compresso N\n" -"(0 desabilita)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "usar modo de texto cannico" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "usar como arquivo de sada" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "detalhado" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "ser mais silencioso" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "nunca usar o terminal" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "forar assinaturas v3" - -#: g10/g10.c:397 -#, fuzzy -msgid "do not force v3 signatures" -msgstr "forar assinaturas v3" - -#: g10/g10.c:398 -#, fuzzy -msgid "force v4 key signatures" -msgstr "forar assinaturas v3" - -#: g10/g10.c:399 -#, fuzzy -msgid "do not force v4 key signatures" -msgstr "forar assinaturas v3" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "sempre usar um MDC para criptografar" - -#: g10/g10.c:402 -#, fuzzy -msgid "never use a MDC for encryption" -msgstr "sempre usar um MDC para criptografar" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "no fazer alteraes" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "modo no-interativo: nunca perguntar" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "assumir sim para a maioria das perguntas" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "assumir no para a maioria das perguntas" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "adicionar este chaveiro lista de chaveiros" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "adicionar este chaveiro secreto lista" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NOME|usar NOME como chave secreta padro" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|ENDEREO|usar este servidor para buscar chaves" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "" -"|NOME|definir mapa de caracteres do terminal como\n" -"NOME" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "ler opes do arquivo" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "" -"|DA|escrever informaes de estado para o\n" -"descritor de arquivo DA" - -#: g10/g10.c:427 -#, fuzzy -msgid "|[file]|write status info to file" -msgstr "" -"|DA|escrever informaes de estado para o\n" -"descritor de arquivo DA" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|ARQUIVO|carregar mdulo de extenso ARQUIVO" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "emular o modo descrito no RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"configurar todas as opes de pacote,\n" -"criptografia e \"digest\" para comportamento\n" -"OpenPGP" - -#: g10/g10.c:443 -#, fuzzy -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "" -"configurar todas as opes de pacote,\n" -"criptografia e \"digest\" para comportamento\n" -"OpenPGP" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|usar frase secreta modo N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "" -"|NOME|usar algoritmo de \"digest\" de mensagens NOME\n" -"para frases secretas" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "" -"|NOME|usar algoritmo de criptografia NOME para\n" -"frases secretas" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NOME|usar algoritmo de criptografia NOME" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NOME|usar algoritmo de \"digest\" de mensagens NOME" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|usar algoritmo de compresso N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "" -"eliminar o campo keyid dos pacotes\n" -"criptografados" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Exemplos:\n" -"\n" -" -se -r Bob [arquivo] assinar e criptografar para usurio Bob\n" -" --clearsign [arquivo] criar uma assinatura em texto puro\n" -" --detach-sign [arquivo] criar uma assinatura separada\n" -" --list-keys [nomes] mostrar chaves\n" -" --fingerprint [nomes] mostrar impresses digitais\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Por favor comunique bugs para .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Uso: gpg [opes] [arquivos] (-h para ajuda)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Sintaxe: gpg [opes] [arquivos]\n" -"assina, verifica, criptografa ou descriptografa\n" -"a operao padro depende dos dados de entrada\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Algoritmos suportados:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "uso: gpg [opes] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "comandos conflitantes\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "NOTA: arquivo de opes padro `%s' inexistente\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "NOTA: arquivo de opes padro `%s' inexistente\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "arquivo de opes `%s': %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "lendo opes de `%s'\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s no um conjunto de caracteres vlido\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "AVISO: `%s' um arquivo vazio\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "armadura invlida" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "AVISO: `%s' um arquivo vazio\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "chaveiro invlido" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "AVISO: O programa pode criar um arquivo core!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "NOTA: %s no para uso normal!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s no permitido com %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s no faz sentido com %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "o algoritmo de criptografia selecionado no vlido\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "o algoritmo de \"digest\" selecionado no vlido\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "o algoritmo de \"digest\" selecionado no vlido\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "o algoritmo de compresso deve estar na faixa %d..%d\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed deve ser maior que 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed deve ser maior que 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth deve estar na entre 1 e 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "NOTA: o modo S2K simples (0) no recomendvel\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "modo S2K invlido: deve ser 0, 1 ou 3\n" - -#: g10/g10.c:1862 -#, fuzzy -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "modo S2K invlido: deve ser 0, 1 ou 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "lista preferncias" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "lista preferncias" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "lista preferncias" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "lista preferncias" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "falha ao inicializar o banco de dados de confiabilidade: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [nome_do_arquivo]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [nome_do_arquivo]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [nome_do_arquivo]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [nome_do_arquivo]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [nome_do_arquivo]" - -#: g10/g10.c:2056 -#, fuzzy -msgid "--sign --symmetric [filename]" -msgstr "--symmetric [nome_do_arquivo]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [nome_do_arquivo]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [nome_do_arquivo]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key id-usurio" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key id-usurio" - -#: g10/g10.c:2110 -#, fuzzy -msgid "--nrsign-key user-id" -msgstr "--sign-key id-usurio" - -#: g10/g10.c:2118 -#, fuzzy -msgid "--nrlsign-key user-id" -msgstr "--sign-key id-usurio" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key id-usurio [comandos]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "impossvel abrir %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [id-usurio] [chaveiro]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "retirada de armadura falhou: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "criao de armadura falhou: %s\n" - -# "hash" poderia ser "espalhamento", mas no fica claro -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "algoritmo de hash invlido `%s'\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[nome_do_arquivo]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "V em frente e digite sua mensagem ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "impossvel abrir `%s'\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"um nome de notao deve ter apenas letras, dgitos, pontos ou sublinhados e " -"terminar com '='\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "um valor de notao no deve usar caracteres de controle\n" - -#: g10/g10.c:2737 -#, fuzzy -msgid "the given certification policy URL is invalid\n" -msgstr "a URL de poltica dada invlida\n" - -#: g10/g10.c:2739 -#, fuzzy -msgid "the given signature policy URL is invalid\n" -msgstr "a URL de poltica dada invlida\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "armadura: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "cabealho de armadura invlido: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "cabealho de armadura: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "cabealho de assinatura em texto puro invlido\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "assinaturas em texto puro aninhadas\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "linha com hfen invlida: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "armadura inesperada:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "caractere radix64 invlido %02x ignorado\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "fim de arquivo prematuro (sem CRC)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "fim de arquivo prematuro (no CRC)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC malformado\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "erro de CRC; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "fim de arquivo prematuro (no \"Trailer\")\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "erro na linha \"trailer\"\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "nenhum dado OpenPGP vlido encontrado.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "armadura invlida: linha maior que %d caracteres\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"caractere \"quoted printable\" na armadura - provavelmente um MTA com bugs " -"foi usado\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "" - -#: g10/pkclist.c:63 -#, fuzzy -msgid "Key is superseded" -msgstr "A chave protegida.\n" - -#: g10/pkclist.c:65 -#, fuzzy -msgid "Key has been compromised" -msgstr "Esta chave foi desativada" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "rev- revogaes de chaves incorreta\n" - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "[revogao]" - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "" - -#: g10/pkclist.c:258 -#, fuzzy, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Nenhum valor de confiana designado para %lu:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -#, fuzzy -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Por favor decida quanto voc confia neste usurio para\n" -"verificar corretamente as chaves de outros usurios\n" -"(olhando em passaportes, checando impresses digitais\n" -"de outras fontes...)?\n" -"\n" -" 1 = No sei\n" -" 2 = Eu NO confio\n" -" 3 = Eu confio moderadamente\n" -" 4 = Eu confio completamente\n" -" s = Mostrar mais informaes\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr "" - -#: g10/pkclist.c:274 -#, fuzzy, c-format -msgid " %d = I do NOT trust\n" -msgstr "%08lX: Ns NO confiamos nesta chave\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr "" - -#: g10/pkclist.c:276 -#, fuzzy, c-format -msgid " %d = I trust fully\n" -msgstr "%s: no um banco de dados de confiabilidade\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr "" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr "" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = voltar ao menu principal\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr "" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = sair\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Sua deciso? " - -#: g10/pkclist.c:316 -#, fuzzy -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Voc realmente quer remover esta chave? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certificados que levam a uma chave confiada plenamente:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "chave %08lX: a chave foi revogada!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Usa esta chave de qualquer modo? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "chave %08lX: a subchave foi revogada!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: a chave expirou\n" - -#: g10/pkclist.c:448 -#, fuzzy, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr " No h indicao de que a assinatura pertence ao dono.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Ns NO confiamos nesta chave\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: No se tem certeza de que esta chave realmente pertence ao dono,\n" -"mas aceita de qualquer modo\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Esta chave provavelmente pertence ao dono\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Esta chave pertence a ns\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"No se tem certeza de que esta chave pertence a seu dono.\n" -"Se voc *realmente* sabe o que est fazendo, pode responder\n" -"sim prxima pergunta\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "AVISO: Usando chave no confivel!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "AVISO: Esta chave foi revogada pelo seu dono!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Isto pode significar que a assinatura falsificada.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "AVISO: Esta subchave foi revogada pelo seu dono!\n" - -#: g10/pkclist.c:580 -#, fuzzy -msgid "Note: This key has been disabled.\n" -msgstr "Esta chave foi desativada" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Nota: Esta chave expirou!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "AVISO: Esta chave no est certificada com uma assinatura confivel!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr " No h indicao de que a assinatura pertence ao dono.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "AVISO: Ns NO confiamos nesta chave!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " A assinatura provavelmente uma FALSIFICAO.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"AVISO: Esta chave no est certificada com assinaturas suficientemente\n" -" confiveis!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " No se tem certeza de que a assinatura pertence ao dono.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: ignorado: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: ignorado: a chave pblica j est presente\n" - -#: g10/pkclist.c:811 -#, fuzzy -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Voc no especificou um identificador de usurio. (pode-se usar \"-r\")\n" -"\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Identificador de usurio inexistente.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "ignorado: chave pblica j marcada como destinatrio padro\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "A chave pblica est desativada.\n" - -#: g10/pkclist.c:870 -#, fuzzy -msgid "skipped: public key already set\n" -msgstr "%s: ignorado: a chave pblica j est presente\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "destinatrio padro desconhecido `%s'\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: ignorado: a chave pblica est desativada\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "nenhum endereo vlido\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "" - -#: g10/keygen.c:189 -#, fuzzy, c-format -msgid "preference %c%lu duplicated\n" -msgstr "ignorado `%s': duplicado\n" - -# muitas ou demais ??? -#: g10/keygen.c:194 -#, fuzzy, c-format -msgid "too many `%c' preferences\n" -msgstr "Preferncias demais" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "Caractere invlido no nome\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "escrevendo auto-assinatura\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "escrevendo auto-assinatura\n" - -# key binding ??? -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "escrevendo assinatura ligada a uma chave\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, fuzzy, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "O tamanho de chave pedido %u bits\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, fuzzy, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "arredondado para %u bits\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Por favor selecione o tipo de chave desejado:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA e ElGamal (padro)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (apenas assinatura)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (apenas criptografia)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (assinatura e criptografia)\n" - -#: g10/keygen.c:949 -#, fuzzy, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) DSA (apenas assinatura)\n" - -#: g10/keygen.c:951 -#, fuzzy, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) ElGamal (apenas criptografia)\n" - -#: g10/keygen.c:953 -#, fuzzy, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) ElGamal (assinatura e criptografia)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Sua opo? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Opo invlida.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Prestes a gerar novo par de chaves %s.\n" -" tamanho mnimo 768 bits\n" -" tamanho padro 1024 bits\n" -" tamanho mximo sugerido 2048 bits\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Que tamanho de chave voc quer? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA permite apenas tamanhos de 512 a 1024\n" - -#: g10/keygen.c:1027 -#, fuzzy -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "tamanho muito pequeno; 768 o valor mnimo permitido.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "tamanho muito pequeno; 768 o valor mnimo permitido.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "tamanho muito grande; %d o valor mximo permitido.\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Tamanhos de chave maiores que 2048 no so recomendados\n" -"porque o tempo de computao REALMENTE longo!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Tudo bem, mas tenha em mente que a radiao de seu monitor e teclado tambm " -" vulnervel a ataques!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "O tamanho de chave pedido %u bits\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "arredondado para %u bits\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Por favor especifique por quanto tempo a chave deve ser vlida.\n" -" 0 = chave no expira\n" -" = chave expira em n dias\n" -" w = chave expira em n semanas\n" -" m = chave expira em n meses\n" -" y = chave expira em n anos\n" - -#: g10/keygen.c:1126 -#, fuzzy -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Por favor especifique por quanto tempo a chave deve ser vlida.\n" -" 0 = chave no expira\n" -" = chave expira em n dias\n" -" w = chave expira em n semanas\n" -" m = chave expira em n meses\n" -" y = chave expira em n anos\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "A chave valida por? (0) " - -#: g10/keygen.c:1150 -#, fuzzy -msgid "Signature is valid for? (0) " -msgstr "A chave valida por? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "valor invlido\n" - -#: g10/keygen.c:1160 -#, fuzzy, c-format -msgid "%s does not expire at all\n" -msgstr "A chave no expira nunca\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, fuzzy, c-format -msgid "%s expires at %s\n" -msgstr "A chave expira em %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Seu sistema no consegue mostrar datas alm de 2038.\n" -"Apesar disso, elas sero corretamente manipuladas at 2106.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Est correto (s/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Voc precisa de um identificador de usurio para identificar sua chave; o\n" -"programa constri o identificador a partir do Nome Completo, Comentrio e\n" -"Endereo Eletrnico desta forma:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Nome completo: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Caractere invlido no nome\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "O nome no pode comear com um dgito\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "O nome deve ter pelo menos 5 caracteres\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Endereo de correio eletrnico: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Endereo eletrnico invlido\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Comentrio: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Caractere invlido no comentrio\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Voc est usando o conjunto de caracteres `%s'.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Voc selecionou este identificador de usurio:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnCcEeOoSs" - -#: g10/keygen.c:1326 -#, fuzzy -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "Muda (N)ome, (C)omentrio, (E)ndereo ou (O)k/(S)air? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "Muda (N)ome, (C)omentrio, (E)ndereo ou (O)k/(S)air? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Voc precisa de uma frase secreta para proteger sua chave.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -#, fuzzy -msgid "passphrase not correctly repeated; try again" -msgstr "A frase secreta no foi repetida corretamente; tente outra vez.\n" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Voc no quer uma frase secreta - provavelmente isto uma *m* idia!\n" -"Vou continuar assim mesmo. Voc pode mudar sua frase secreta a\n" -"qualquer hora, usando este programa com a opo \"--edit-key\".\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Precisamos gerar muitos bytes aleatrios. uma boa idia realizar outra\n" -"atividade (digitar no teclado, mover o mouse, usar os discos) durante a\n" -"gerao dos nmeros primos; isso d ao gerador de nmeros aleatrios\n" -"uma chance melhor de conseguir entropia suficiente.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "O par de chaves DSA ter 1024 bits.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Gerao de chave cancelada.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, fuzzy, c-format -msgid "writing public key to `%s'\n" -msgstr "escrevendo certificado pblico para `%s'\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, fuzzy, c-format -msgid "writing secret key to `%s'\n" -msgstr "escrevendo certificado privado para `%s'\n" - -#: g10/keygen.c:2205 -#, fuzzy, c-format -msgid "no writable public keyring found: %s\n" -msgstr "chave %08lX: chave pblica no encontrada: %s\n" - -#: g10/keygen.c:2211 -#, fuzzy, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "impossvel bloquear chaveiro secreto: %s\n" - -#: g10/keygen.c:2225 -#, fuzzy, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "erro na escrita do chaveiro `%s': %s\n" - -#: g10/keygen.c:2232 -#, fuzzy, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "erro na escrita do chaveiro `%s': %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "chaves pblica e privada criadas e assinadas.\n" - -#: g10/keygen.c:2253 -#, fuzzy -msgid "key marked as ultimately trusted.\n" -msgstr "Certificados que levam a uma chave confiada plenamente:\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Note que esta chave no pode ser usada para criptografia. Voc pode usar\n" -"o comando \"--edit-key\" para gerar uma chave secundria para esse fim.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "A gerao de chaves falhou: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"a chave foi criada %lu segundo no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"a chave foi criada %lu segundos no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Realmente criar? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: impossvel abrir: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "erro na criao da frase secreta: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, fuzzy, c-format -msgid "`%s' already compressed\n" -msgstr "%lu chaves processadas\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: AVISO: arquivo vazio\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lendo de `%s'\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: algoritmo de criptografia %d no encontrado nas preferncias\n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s criptografado para: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, fuzzy, c-format -msgid "key `%s' not found: %s\n" -msgstr "usurio `%s' no encontrado: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, fuzzy, c-format -msgid "error reading keyblock: %s\n" -msgstr "erro na leitura de `%s': %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "chave %08lX: no uma chave rfc2440 - ignorada\n" - -#: g10/export.c:238 -#, fuzzy, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "chave %08lX: no uma chave rfc2440 - ignorada\n" - -#: g10/export.c:246 -#, fuzzy, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "chave %08lX: no uma chave rfc2440 - ignorada\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "AVISO: nada exportado\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "entradas demais no cache pk - desativado\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -#, fuzzy -msgid "[User id not found]" -msgstr "[usurio no encontrado]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "usando chave secundria %08lX ao invs de chave primria %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "chave %08lX: chave secreta sem chave pblica - ignorada\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "ignorando bloco do tipo %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "%lu chaves processadas at agora\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "erro na leitura de `%s': %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Nmero total processado: %lu\n" - -#: g10/import.c:286 -#, fuzzy, c-format -msgid " skipped new keys: %lu\n" -msgstr " novas subchaves: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " sem IDs de usurios: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importados: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " no modificados: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " novos IDs de usurios: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " novas subchaves: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " novas assinaturas: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " novas revogaes de chaves: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " chaves secretas lidas: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " chaves secretas importadas: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " chaves secretas no modificadas: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importados: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "chave %08lX: sem ID de usurio\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "chave %08lX: sem subchave para ligao de chaves\n" - -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "chave %08lX: aceito ID de usurio sem auto-assinatura '" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "chave %08lX: sem IDs de usurios vlidos\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "isto pode ser causado por falta de auto-assinatura\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "chave %08lX: chave pblica no encontrada: %s\n" - -#: g10/import.c:636 -#, fuzzy, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "chave %08lX: no uma chave rfc2440 - ignorada\n" - -#: g10/import.c:646 -#, fuzzy, c-format -msgid "no writable keyring found: %s\n" -msgstr "impossvel escrever chaveiro: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "escrevendo para `%s'\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "erro na escrita do chaveiro `%s': %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "chave %08lX: chave pblica importada\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "chave %08lX: no corresponde nossa cpia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "chave %08lX: impossvel localizar bloco de chaves original: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "chave %08lX: impossvel ler bloco de chaves original: %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "chave %8lX: 1 novo ID de usurio\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "chave %08lX: %d novos IDs de usurios\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "chave %08lX: 1 nova assinatura\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "chave %08lX: %d novas assinaturas\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "chave %08lX: 1 nova subchave\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "chave %08lX: %d novas subchaves\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "chave %08lX: no modificada\n" - -#: g10/import.c:844 -#, fuzzy, c-format -msgid "no default secret keyring: %s\n" -msgstr "impossvel bloquear chaveiro secreto: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "chave %08lX: chave secreta importada\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "chave %08lX: j est no chaveiro secreto\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "chave %08lX: chave secreta no encontrada: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"chave %08lX: sem chave pblica - impossvel aplicar certificado\n" -"de revogao\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "chave %08lX: certificado de revogao invlido: %s - rejeitado\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "chave %08lX: certificado de revogao importado\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "chave %08lX: nenhum ID de usurio para assinatura\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "chave %08lX: algoritmo de chave pblica no suportado\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "chave %08lX: auto-assinatura invlida\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "chave %08lX: sem subchave para ligao de chaves\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "chave %08lX: algoritmo de chave pblica no suportado\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "chave %08lX: sem subchave para ligao de chaves\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "chave %08lX.%lu: Revogao de subchave vlida\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "chave %08lX: ligao de subchave invlida\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "chave %08lX: ignorado ID de usurio '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "chave %08lX: subchave ignorada\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "chave %08lX: assinatura no exportvel (classe %02x) - ignorada\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "chave %08lX: certificado de revogao no local errado - ignorada\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "chave %08lX: certificado de revogao invlido: %s - ignorada\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "chave %08lX: certificado de revogao no local errado - ignorada\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "chave %08lX: detectado ID de usurio duplicado - unido\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "chave %08lX: certificado de revogao adicionado\n" - -#: g10/import.c:1491 -#, fuzzy, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "chave %08lX: %d novas assinaturas\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[revogao]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[auto-assinatura]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 assinatura incorreta\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d assinaturas incorretas\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 assinatura no verificada por falta de chave\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d assinaturas no verificadas por falta de chaves\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 assinatura no verificada devido a um erro\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d assinaturas no verificadas devido a erros\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 ID de usurio sem auto-assinatura vlida detectado\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d IDs de usurios sem auto-assinaturas vlidas detectados\n" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "A chave protegida.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "AVISO: `%s' um arquivo vazio\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "J assinado pela chave %08lX\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "J assinado pela chave %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nada para assinar com a chave %08lX\n" - -#: g10/keyedit.c:478 -#, fuzzy -msgid "This key has expired!" -msgstr "Nota: Esta chave expirou!\n" - -#: g10/keyedit.c:498 -#, fuzzy, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Esta chave no protegida.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "" - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr "" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr "" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr "" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr "" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Voc tem certeza de que quer assinar esta chave com\n" -"sua chave: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "isto pode ser causado por falta de auto-assinatura\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"A assinatura ser marcada como no-exportvel.\n" -"\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"A assinatura ser marcada como no-exportvel.\n" -"\n" - -#: g10/keyedit.c:620 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"A assinatura ser marcada como no-exportvel.\n" -"\n" - -#: g10/keyedit.c:624 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"A assinatura ser marcada como no-exportvel.\n" -"\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Realmente assinar? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "assinatura falhou: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Esta chave no protegida.\n" - -#: g10/keyedit.c:748 -#, fuzzy -msgid "Secret parts of primary key are not available.\n" -msgstr "chave secreta no disponvel" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "A chave protegida.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Impossvel editar esta chave: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Digite a nova frase para esta chave secreta.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Voc no quer uma frase secreta - provavelmente isto uma *m* idia!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Voc realmente quer fazer isso? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "movendo a assinatura da chave para o local correto\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "sair deste menu" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "gravar e sair" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "mostra esta ajuda" - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "mostra impresso digital" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "lista chave e identificadores de usurios" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "seleciona ID de usurio N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "seleciona chave secundria N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "lista assinaturas" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "assina a chave" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "assina a chave localmente" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "nrsign" -msgstr "sign" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "sign the key non-revocably" -msgstr "assina a chave localmente" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "nrlsign" -msgstr "sign" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "sign the key locally and non-revocably" -msgstr "assina a chave localmente" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "adiciona um novo ID de usurio" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "" - -#: g10/keyedit.c:920 -#, fuzzy -msgid "add a photo ID" -msgstr "adiciona um novo ID de usurio" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "remove ID de usurio" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "adiciona nova chave secundria" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "remove uma chave secundria" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "revkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "adiciona nova chave secundria" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "remove assinaturas" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "muda a data de validade" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "alterna entre listagem de chave secreta e pblica" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -#, fuzzy -msgid "list preferences (expert)" -msgstr "lista preferncias" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "list preferences (verbose)" -msgstr "lista preferncias" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "setpref" -msgstr "pref" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "set preference list" -msgstr "lista preferncias" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updpref" -msgstr "pref" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updated preferences" -msgstr "lista preferncias" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "muda a frase secreta" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "muda os valores de confiana" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "revoga assinaturas" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "revoga uma chave secundria" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "desativa uma chave" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "ativa uma chave" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "impossvel fazer isso em modo no-interativo\n" - -#: g10/keyedit.c:1000 -#, fuzzy, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "erro na leitura de `%s': %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Chave secreta disponvel.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Comando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "A chave secreta necessria para fazer isto.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "A chave protegida.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Realmente assinar todos os IDs de usurio? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Sugesto: Selecione os IDs de usurio para assinar\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Voc precisa selecionar pelo menos um ID de usurio.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Voc no pode remover o ltimo ID de usurio!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Realmente remover todos os IDs de usurio selecionados? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Realmente remover este ID de usurio? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Voc deve selecionar pelo menos uma chave.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Voc realmente quer remover as chaves selecionadas? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Voc realmente quer remover esta chave? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Voc realmente quer revogar as chaves selecionadas? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Voc realmente quer revogar esta chave? " - -#: g10/keyedit.c:1354 -#, fuzzy -msgid "Really update the preferences for the selected user IDs? " -msgstr "Realmente remover todos os IDs de usurio selecionados? " - -#: g10/keyedit.c:1356 -#, fuzzy -msgid "Really update the preferences? " -msgstr "Realmente gerar os certificados de revogao? (s/N)" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Salvar alteraes? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Sair sem salvar? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "atualizao falhou: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "atualizao da chave secreta falhou: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Chave no alterada, nenhuma atualizao necessria.\n" - -# help ou ajuda ??? -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Comando invlido (tente \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "AVISO: Esta chave foi revogada pelo seu dono!\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr "" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Esta chave foi desativada" - -#: g10/keyedit.c:1802 -#, fuzzy, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! a subchave foi revogada: %s\n" - -#: g10/keyedit.c:1805 -#, fuzzy -msgid "rev- faked revocation found\n" -msgstr "rev- revogaes de chaves incorreta\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Deletar esta assinatura vlida? (s/N/q)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Deletar esta assinatura invlida? (s/N/q)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Deletar esta assinatura desconhecida? (s/N/q)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Realmente remover esta auto-assinatura? (s/N)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d assinatura removida.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d assinaturas removidas.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Nada removido.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Digite o tamanho da chave" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Por favor remova as selees das chaves secretas.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Por favor selecione no mximo uma chave secundria.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Modificando a data de validade para uma chave secundria.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Modificando a data de validade para uma chave primria.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Voc no pode modificar a data de validade de uma chave v3\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Nenhuma assinatura correspondente no chaveiro secreto\n" - -#: g10/keyedit.c:2546 -#, fuzzy -msgid "Please select exactly one user ID.\n" -msgstr "Voc precisa selecionar pelo menos um ID de usurio.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "chave %08lX: auto-assinatura invlida\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Nenhum ID de usurio com ndice %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Nenhuma chave secundria com ndice %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "ID de usurio: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"assinado com sua chave %08lX em %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"assinado com sua chave %08lX em %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "Esta chave no protegida.\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Gerar um certificado de revogao para esta assinatura? (s/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Voc assinou estes IDs de usurio:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " assinado por %08lX em %s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " revogado por %08lX em %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Voc est prestes a revogar estas assinaturas:\n" - -#: g10/keyedit.c:3013 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " assinado por %08lX em %s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Realmente gerar os certificados de revogao? (s/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "nenhuma chave secreta\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "assinatura %s de: %s\n" - -#: g10/keylist.c:93 -#, fuzzy -msgid "Signature policy: " -msgstr "assinatura %s de: %s\n" - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "AVISO: dados de notao invlidos encontrados\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notao: " - -#: g10/keylist.c:129 -#, fuzzy -msgid "Signature notation: " -msgstr "Notao: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, fuzzy, c-format -msgid " [expires: %s]" -msgstr "A chave expira em %s\n" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "listar as chaves e as impresses digitais" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Impresso digital:" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Impresso digital:" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Impresso digital:" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -#, fuzzy -msgid " Key fingerprint =" -msgstr " Impresso digital:" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -# "hash" poderia ser "espalhamento", mas no fica claro -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "algoritmo de hash invlido `%s'\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "dados criptografados com %s\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "criptografado com algoritmo desconhecido %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "a chave pblica %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "dados criptografados com chave pblica: DEK vlido\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "criptografado com chave %u-bit %s, ID %08lX, criada em %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "criptografado com chave %s, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "descriptografia de chave pblica falhou: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, fuzzy, c-format -msgid "assuming %s encrypted data\n" -msgstr "dados criptografados com %s\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "descriptografia correta\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "CUIDADO: a mensagem criptografada foi manipulada!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "descriptografia falhou: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "NOTA: o remetente solicitou \"apenas-para-seus-olhos\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "nome de arquivo original='%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "revogao isolada - use \"gpg --import\" para aplic-la\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notao: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Poltica: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "verificao de assinatura suprimida\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -#, fuzzy -msgid "can't handle these multiple signatures\n" -msgstr "fazer uma assinatura separada" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Assinatura feita em %.*s usando %s, ID da chave %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "Assinatura INCORRETA de \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -#, fuzzy -msgid "Expired signature from \"" -msgstr "Assinatura correta de \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Assinatura correta de \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " ou \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Impossvel verificar assinatura: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -#, fuzzy -msgid "not a detached signature\n" -msgstr "fazer uma assinatura separada" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "assinatura isolada da classe 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "formato de assinatura antigo (PGP2.x)\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "pacote raiz invlido detectado em proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "impossvel desativar core dumps: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Algoritmos experimentais no devem ser usados!\n" - -#: g10/misc.c:192 -#, fuzzy -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"este algoritmo de criptografia depreciado; por favor use algum\n" -"algoritmo padro!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "AVISO: `%s' um arquivo vazio\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "AVISO: `%s' um arquivo vazio\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "impossvel manipular algoritmo de chave pblica %d\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "subpacote do tipo %d tem bit crtico ligado\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "" - -#: g10/passphrase.c:511 -#, fuzzy, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "algoritmo de proteo %d no suportado\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, fuzzy, c-format -msgid "can't connect to `%s': %s\n" -msgstr "impossvel abrir `%s': %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (ID principal da chave %08lX)" - -#: g10/passphrase.c:641 -#, fuzzy, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"\n" -"Voc precisa de uma frase secreta para desbloquear a chave secreta do\n" -"usurio: \"%.*s\"\n" -"%u-bit %s chave, ID %08lX, criada %s%s\n" - -#: g10/passphrase.c:662 -#, fuzzy -msgid "Enter passphrase\n" -msgstr "Digite a frase secreta: " - -#: g10/passphrase.c:664 -#, fuzzy -msgid "Repeat passphrase\n" -msgstr "Repita a frase secreta: " - -#: g10/passphrase.c:705 -#, fuzzy -msgid "passphrase too long\n" -msgstr "linha muito longa\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Voc precisa de uma frase secreta para desbloquear a chave secreta do\n" -"usurio: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "chave de %u-bit/%s, ID %08lX, criada em %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "impossvel pedir senha em modo no-interativo\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Digite a frase secreta: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Repita a frase secreta: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "dados no salvos; use a opo \"--output\" para salv-los\n" - -#: g10/plaintext.c:108 -#, fuzzy, c-format -msgid "error creating `%s': %s\n" -msgstr "erro na leitura de `%s': %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Assinatura separada.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Por favor digite o nome do arquivo de dados: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lendo de \"stdin\" ...\n" - -#: g10/plaintext.c:396 -#, fuzzy -msgid "no signed data\n" -msgstr "no dados assinados\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "impossvel abrir dados assinados `%s'\n" - -#: g10/pubkey-enc.c:101 -#, fuzzy, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "destinatrio annimo; tentando chave secreta %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "certo, ns somos o destinatrio annimo.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "codificao antiga do DEK no suportada\n" - -#: g10/pubkey-enc.c:178 -#, fuzzy, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "algoritmo de proteo %d no suportado\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "NOTA: algoritmo de criptografia %d no encontrado nas preferncias\n" - -#: g10/pubkey-enc.c:243 -#, fuzzy, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "NOTA: chave secreta %08lX expirou %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "chave %08lX: a chave foi revogada!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "impossvel escrever para o chaveiro: %s\n" - -#: g10/hkp.c:96 -#, fuzzy, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "impossvel escrever para o chaveiro: %s\n" - -#: g10/hkp.c:175 -#, fuzzy, c-format -msgid "error sending to `%s': %s\n" -msgstr "erro na leitura de `%s': %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "" - -#: g10/hkp.c:565 -#, fuzzy, c-format -msgid "can't search keyserver: %s\n" -msgstr "impossvel escrever para o chaveiro: %s\n" - -#: g10/seckey-cert.c:53 -#, fuzzy -msgid "secret key parts are not available\n" -msgstr "chave secreta no disponvel" - -#: g10/seckey-cert.c:59 -#, fuzzy, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "algoritmo de proteo %d no suportado\n" - -#: g10/seckey-cert.c:224 -#, fuzzy -msgid "Invalid passphrase; please try again" -msgstr "Frase secreta invlida; por favor tente novamente ...\n" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"AVISO: Chave fraca detectada - por favor mude a frase secreta novamente.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"esta uma chave ElGamal gerada pelo PGP que NO segura para assinaturas!\n" - -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "a chave pblica %lu segundo mais nova que a assinatura\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "a chave pblica %lu segundos mais nova que a assinatura\n" - -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"a chave foi criada %lu segundo no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"a chave foi criada %lu segundos no futuro\n" -"(viagem no tempo ou problema no relgio)\n" - -#: g10/sig-check.c:249 -#, fuzzy, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "NOTA: chave de assinatura %08lX expirou %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "assumindo assinatura incorreta devido a um bit crtico desconhecido\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:303 -#, fuzzy, c-format -msgid "checking created signature failed: %s\n" -msgstr "leitura de registro de assinatura falhou: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "assinatura %s de: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "AVISO: `%s' um arquivo vazio\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "impossvel criar %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "NOTA: algoritmo de criptografia %d no encontrado nas preferncias\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "assinando:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:1029 -#, fuzzy, c-format -msgid "%s encryption will be used\n" -msgstr "descriptografia falhou: %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "impossvel manipular linhas de texto maiores que %d caracteres\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "linha de entrada maior que %d caracteres\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "banco de dados de confiabilidade rec %lu: lseek falhou: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "banco de dados de confiabilidade rec %lu: escrita falhou (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "transao de banco de dados de confiabilidade muito grande\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: impossvel acessar: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: diretrio inexistente!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: impossvel criar trava\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, fuzzy, c-format -msgid "%s: can't make lock\n" -msgstr "%s: impossvel criar trava\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: impossvel criar: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: falha ao criar registro de verso: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: banco de dados de confiabilidade invlido criado\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: banco de dados de confiabilidade criado\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: banco de dados de confiabilidade invlido\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: falha ao criar tabela de \"hash\": %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: erro atualizando registro de verso: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: erro lendo registro de verso: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: erro escrevendo registro de verso: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "banco de dados de confiabilidade: lseek falhou: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "banco de dados de confiabilidade: leitura falhou (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: no um banco de dados de confiabilidade\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: registro de verso com recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: verso de arquivo invlida %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: erro lendo registro livre: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: erro escrevendo registro de diretrio: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: falha ao zerar um registro: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: falha ao anexar um registro: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"O banco de dados de confiabilidade est danificado; por favor rode\n" -"\"gpg --fix-trust-db\".\n" - -#: g10/trustdb.c:200 -#, fuzzy, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "%s no um mapa de caracteres vlido\n" - -#: g10/trustdb.c:235 -#, fuzzy, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "chave %08lX: aceita como chave confivel.\n" - -#: g10/trustdb.c:274 -#, fuzzy, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "" -"chave %08lX: impossvel coloc-la no banco de dados de confiabilidade\n" - -#: g10/trustdb.c:290 -#, fuzzy, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "chave %08lX: chave secreta sem chave pblica - ignorada\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "registro de confiana %lu, tipo req %d: falha na leitura: %s\n" - -#: g10/trustdb.c:338 -#, fuzzy, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "registro de confiana %lu: remoo falhou: %s\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "registro de confiana %lu, tipo %d: escrita falhou: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "banco de dados de confiabilidade: sincronizao falhou: %s\n" - -#: g10/trustdb.c:468 -#, fuzzy -msgid "no need for a trustdb check\n" -msgstr "%s: no um banco de dados de confiabilidade\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, fuzzy, c-format -msgid "next trustdb check due at %s\n" -msgstr "insero de registro de confiana falhou: %s\n" - -#: g10/trustdb.c:779 -#, fuzzy -msgid "checking the trustdb\n" -msgstr "muda os valores de confiana" - -#: g10/trustdb.c:933 -#, fuzzy, c-format -msgid "public key %08lX not found: %s\n" -msgstr "chave pblica no encontrada" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"a assinatura no pde ser verificada.\n" -"Por favor lembre-se de que o arquivo com a assinatura (.sig ou .asc)\n" -"deve ser o primeiro arquivo dado na linha de comando.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "linha %u muito longa ou sem LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"a chave no est marcada como insegura - impossvel us-la com o pseudo " -"RNG!\n" - -#: g10/skclist.c:157 -#, fuzzy, c-format -msgid "skipped `%s': duplicated\n" -msgstr "ignorado `%s': duplicado\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "ignorado `%s': %s\n" - -#: g10/skclist.c:168 -#, fuzzy -msgid "skipped: secret key already present\n" -msgstr "ignorado: a chave secreta j est presente\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"ignorado `%s': esta uma chave ElGamal gerada pelo PGP que no segura " -"para assinaturas!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Arquivo `%s' j existe. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Sobrescrever (s/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: sufixo desconhecido\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Digite novo nome de arquivo" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "escrevendo em \"stdout\"\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "assumindo dados assinados em `%s'\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: novo arquivo de opes criado\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: impossvel criar diretrio: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: diretrio criado\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"AVISO: A mensagem foi criptografada com uma chave fraca na criptografia\n" -"simtrica.\n" - -#: g10/encr-data.c:98 -#, fuzzy -msgid "problem handling encrypted packet\n" -msgstr "eliminar o campo keyid dos pacotes criptografados\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "chave fraca criada - tentando novamente\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"impossvel evitar chave fraca para criptografia simtrica;\n" -"%d tentativas!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "impossvel fazer isso em modo no-interativo sem \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Deletar esta chave do chaveiro? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Esta uma chave secreta! - realmente deletar? " - -#: g10/delkey.c:168 -#, fuzzy, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "enumerao de blocos de chaves falhou: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, fuzzy, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "h uma chave secreta para esta chave pblica!\n" - -#: g10/delkey.c:208 -#, fuzzy -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "use a opo \"--delete-secret-key\" para delet-la antes.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Voc decide que valor usar aqui; este valor nunca ser exportado para\n" -"terceiros. Precisamos dele implementar a rede de confiana, que no tem\n" -"nada a ver com a rede de certificados (implicitamente criada)." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Se voc quiser usar esta chave revogada assim mesmo, responda \"sim\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Se voc quiser usar esta chave no confivel assim mesmo, responda \"sim\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "" -"Digite o ID de usurio do destinatrio para o qual voc quer enviar a\n" -"mensagem." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Selecione o algoritmo a ser usado.\n" -"\n" -"DSA (ou DSS) o algoritmo de assinatura digital que pode ser usado apenas\n" -"para assinaturas. Este o algoritmo recomendado porque a verificao de\n" -"assinaturas DSA muito mais rpida que a verificao de ElGamal.\n" -"\n" -"ElGamal um algoritmo que pode ser usado para assinatura e criptografia.\n" -"O OpenPGP distingue dois tipos deste algoritmo: um apenas para criptografia\n" -"e outro para assinatura+criptografia; na verdade so iguais, mas alguns\n" -"parmetros precisam ser escolhidos de modo especial para criar uma chave\n" -"segura para asssinatura: este programa faz isso, mas algumas outras\n" -"implementaes do OpenPGP no vo necessariamente entender o tipo\n" -"assinatura+criptografia.\n" -"\n" -"A chave primria precisa sempre ser uma chave capaz de fazer assinaturas;\n" -"este o motivo pelo qual a chave ElGamal apenas para criptografia no est\n" -"disponvel neste menu." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Apesar de estas chaves estarem definidas no RFC2440, elas no so " -"recomendadas\n" -"porque no so suportadas por todos os programas e assinaturas criadas com\n" -"elas so grandes e sua verificao lenta." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Digite o tamanho da chave" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Responda \"sim\" ou \"no\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Digite o valor necessrio conforme pedido.\n" -" possvel digitar uma data ISO (AAAA-MM-DD) mas voc no ter uma boa\n" -"reao a erros - o sistema tentar interpretar o valor dado como um " -"intervalo." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Digite o nome do possuidor da chave" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "por favor digite um endereo de email (opcional mas recomendado)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Por favor digite um comentrio (opcional)" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N para mudar o nome.\n" -"C para mudar o comentrio.\n" -"E para mudar o endereo de correio eletrnico.\n" -"O para continuar a gerao da chave.\n" -"S para interromper a gerao da chave." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Responda \"sim\" (ou apenas \"s\") se quiser gerar a subchave." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Responda \"sim\" se quiser assinar TODOS os IDs de usurio" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Responda \"sim\" se quiser realmente remover este ID de usurio.\n" -"Todos os certificados tambm sero perdidos!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Responda \"sim\" se quiser remover a subchave" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Esta uma assinatura vlida na chave; normalmente no desejvel\n" -"remover esta assinatura porque ela pode ser importante para estabelecer\n" -"uma conexo de confiana chave ou a outra chave certificada por esta." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Esta assinatura no pode ser verificada porque voc no tem a chave\n" -"correspondente. Voc deve adiar sua remoo at saber que chave foi usada\n" -"porque a chave desta assinatura pode estabelecer uma conexo de confiana\n" -"atravs de outra chave j certificada." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "A assinatura no vlida. Faz sentido remov-la de seu chaveiro." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Esta uma assinatura que liga o ID de usurio chave. Geralmente\n" -"no uma boa idia remover tal assinatura. possvel que o GnuPG\n" -"no consiga mais usar esta chave. Faa isto apenas se por alguma\n" -"razo esta auto-assinatura no for vlida e h uma segunda disponvel." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:244 -#, fuzzy -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Por favor digite a frase secreta" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Por favor repita a ltima frase secreta, para ter certeza do que voc " -"digitou." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "D o nome para o arquivo ao qual a assinatura se aplica" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Responda \"sim\" se quiser sobrescrever o arquivo" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Por favor digite um novo nome de arquivo. Se voc apenas apertar RETURN o\n" -"arquivo padro (que mostrado em colchetes) ser usado." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Nenhuma ajuda disponvel" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Nenhuma ajuda disponvel para `%s'" - -#: g10/keydb.c:178 -#, fuzzy, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "erro na escrita do chaveiro `%s': %s\n" - -#: g10/keydb.c:185 -#, fuzzy, c-format -msgid "keyring `%s' created\n" -msgstr "%s: chaveiro criado\n" - -#: g10/keydb.c:575 -#, fuzzy, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "%s: falha ao criar tabela de \"hash\": %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "AVISO: existem 2 arquivos com informaes confidenciais.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s o no modificado\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s o novo\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Por favor conserte este possvel furo de segurana\n" - -#: g10/keyring.c:1346 -#, fuzzy, c-format -msgid "checking keyring `%s'\n" -msgstr "erro na escrita do chaveiro `%s': %s\n" - -#: g10/keyring.c:1377 -#, fuzzy, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "%lu chaves processadas at agora\n" - -#: g10/keyring.c:1388 -#, fuzzy, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "listar as chaves e as assinaturas" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: chaveiro criado\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "voc deve reiniciar o GnuPG, para que ele possa ler o novo arquivo\n" -#~ "de opes\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Impresso digital:" - -#~ msgid " Fingerprint:" -#~ msgstr " Impresso digital:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NOME=VALOR|usar estes dados de notao" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "o primeiro caractere de um nome de notao deve ser uma letra ou um " -#~ "sublinhado\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "pontos em um nome de notao devem estar cercados por outros caracteres\n" - -#, fuzzy -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#, fuzzy -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr "Voc tem certeza de que quer este tamanho de chave? " - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Realmente assinar? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "chave %08lX: nossa cpia no tem auto-assinatura\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Voc realmente precisa de uma chave to grande? " - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " assinado por %08lX em %s\n" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key id-usurio" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key id-usurio" - -#, fuzzy -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key id-usurio" - -#~ msgid "Enter the user ID: " -#~ msgstr "Digite o identificador de usurio: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "ignorado: chave pblica j marcada com --encrypt-to\n" - -#, fuzzy -#~ msgid "" -#~ "\n" -#~ "WARNING: This is a PGP2-style key\n" -#~ msgstr "AVISO: `%s' um arquivo vazio\n" - -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#, fuzzy -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s no um mapa de caracteres vlido\n" - -#, fuzzy -#~ msgid "duplicate (short) key ID %08lX\n" -#~ msgstr "a chave pblica %08lX\n" - -#, fuzzy -#~ msgid "%lu key(s) to refresh\n" -#~ msgstr "\t%lu chaves com erros\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NOMES]|verificar o banco de dados de confiabilidade" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "No foi possvel encontrar uma rota de confiana vlida para a chave.\n" -#~ "Vamos ver se possvel designar alguns valores de confiana ausentes.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "Nenhuma rota encontrada que leve a uma de nossas chaves.\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Nenhum certificado com confiana indefinida encontrado.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Nenhum valor de confiana modificado.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "%08lX: sem informao para calcular probabilidade de confiana\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: erro na verificao da chave: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "entradas demais no cache unk - desativado\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "atualizao do banco de dados de confiabilidade falhou: %s\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "assumindo MDC incorreto devido a um bit crtico desconhecido\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "erro lendo registro de diretrio para LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: registro de diretrio esperado, tipo %d recebido\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "nenhuma chave primria para LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "erro lendo chave primria para LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record falhou: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "chave %08lX: pedido de registro falhou\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "chave %08lX: j est na tabela de chaves confiveis\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "NOTA: a chave secreta %08lX NO est protegida.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "chave %08lX: chaves secreta e pblica no so correspondentes\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "enumerao de chaves secretas falhou: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "chave %08lX.%lu: Ligao de subchave vlida\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "chave %08lX.%lu: Ligao de subchave invlida: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "chave %08lX.%lu: Revogao de chave vlida\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "chave %08lX.%lu: Revogao de chave invlida: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Auto-assinatura vlida" - -#~ msgid "Invalid self-signature" -#~ msgstr "Auto-assinatura invlida" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Revogao vlida de ID de usurio ignorada devido a nova auto-assinatura" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Revogao de ID de usurio vlida" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Revogao de ID de usurio invlida" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Certificado de revogao vlido" - -#~ msgid "Good certificate" -#~ msgstr "Certificado correto" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Certificado de revogao invlido" - -#~ msgid "Invalid certificate" -#~ msgstr "Certificado invlido" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "registro de assinatura %lu[%d] aponta para registro errado.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "certificado duplicado - removido" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir falhou: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: insero falhou: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: insero falhou: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: inserido\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "erro lendo registro de diretrio: %s\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu chaves inseridas\n" - -#~ msgid "enumerate keyblocks failed: %s\n" -#~ msgstr "enumerao de blocos de chaves falhou: %s\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: registro de diretrio sem chave - ignorado\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu devido a novas chaves pblicas\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu chaves ignoradas\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu chaves atualizadas\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Ooops, nenhuma chave\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Ooops, nenhum ID de usurio\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: busca de registro de diretrio falhou: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "chave %08lX: insero de registro de confiana falhou: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "chave %08lX.%lu: inserida no banco de dados de confiabilidade\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "chave %08lX.%lu: criada no futuro (viagem no tempo ou problema no " -#~ "relogio)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "chave %08lX.%lu: expirou em %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "chave %08lX.%lu: verificao de confiana falhou: %s\n" - -#~ msgid "user '%s' not found: %s\n" -#~ msgstr "usurio `%s' no encontrado: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "" -#~ "problemas na procura de `%s' no banco de dados de confiabilidade: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "" -#~ "usurio `%s' no encontrado no banco de dados de confiabilidade - " -#~ "inserindo\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "falha ao colocar `%s' no banco de dados de confiabilidade: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "" -#~ "Voc realmente quer criar uma chave para assinatura e criptografia? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: usurio no encontrado: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "erro de leitura do certificado: %s\n" - -#~ msgid "no default public keyring\n" -#~ msgstr "sem chaveiro pblico padro\n" - -#~ msgid "can't lock keyring `%s': %s\n" -#~ msgstr "impossvel bloquear chaveiro `%s': %s\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: usurio no encontrado\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "" -#~ "AVISO: ainda impossvel manipular registros de preferncias longos\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: impossvel criar chaveiro: %s\n" - -#, fuzzy -#~ msgid "invalid" -#~ msgstr "armadura invlida" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "chave RSA no pode ser usada nesta verso\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Nenhuma chave para identificador de usurio\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Nenhum identificador de usurio para chave\n" - -#~ msgid "no secret key for decryption available\n" -#~ msgstr "nenhuma chave secreta para descriptografia disponvel\n" - -#~ msgid "" -#~ "RSA keys are deprecated; please consider creating a new key and use this " -#~ "key in the future\n" -#~ msgstr "" -#~ "Chaves RSA no so recomendveis; por favor considere criar uma nova " -#~ "chave e us-la no futuro\n" - -#~ msgid "set debugging flags" -#~ msgstr "definir parmetros de depurao" - -#~ msgid "enable full debugging" -#~ msgstr "habilitar depurao completa" - -#~ msgid "do not write comment packets" -#~ msgstr "no escrever pacotes de comentrio" - -#~ msgid "(default is 1)" -#~ msgstr "(o padro 1)" - -#~ msgid "(default is 3)" -#~ msgstr "(o padro 3)" - -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal em um pacote v3\n" - -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "A gerao de chaves s pode ser feita em modo interativo\n" - -#, fuzzy -#~ msgid "tdbio_search_sdir failed: %s\n" -#~ msgstr "tdbio_search_dir falhou: %s\n" - -#~ msgid "print all message digests" -#~ msgstr "imprime todos os \"digests\" de mensagens" - -#~ msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n" -#~ msgstr "" -#~ "NOTA: assinatura rec %lu[%d] est na lista de sugestes de %lu mas est\n" -#~ " marcada como verificada\n" - -#~ msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n" -#~ msgstr "" -#~ "NOTA: assinatura rec %lu[%d] est na lista de sugestes de %lu mas no " -#~ "est\n" -#~ " marcada\n" - -#~ msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n" -#~ msgstr "" -#~ "assinatura rec %lu[%d] na lista de sugestes de %lu no aponta para\n" -#~ "um registro de diretrio\n" - -#~ msgid "lid %lu: no primary key\n" -#~ msgstr "lid %lu: nenhuma chave primria\n" - -#~ msgid "lid %lu: user id not found in keyblock\n" -#~ msgstr "lid %lu: id de usurio no encontrado no bloco de chaves\n" - -#~ msgid "lid %lu: user id without signature\n" -#~ msgstr "lid %lu: id de usurio sem assinatura\n" - -#~ msgid "lid %lu: self-signature in hintlist\n" -#~ msgstr "lid %lu: auto-assinatura na lista de sugestes\n" - -#~ msgid "very strange: no public key\n" -#~ msgstr "muito estranho: nenhuma chave pblica\n" - -#~ msgid "hintlist %lu[%d] of %lu does not point to a dir record\n" -#~ msgstr "" -#~ "lista de sugestes %lu[%d] de %lu no aponta para registro de diretrio\n" - -#~ msgid "lid %lu does not have a key\n" -#~ msgstr "lid %lu no tem chave\n" - -#~ msgid "lid %lu: can't get keyblock: %s\n" -#~ msgstr "lid %lu: impossvel pegar bloco de chaves: %s\n" - -#~ msgid "Too many preference items" -#~ msgstr "Muitos itens de preferncia" - -#~ msgid "public key not anymore available" -#~ msgstr "a chave pblica no est mais disponvel" - -# trauzir sombra ??? -#~ msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n" -#~ msgstr "" -#~ "uid %08lX.%lu/%02X%02X: tem diretrio \"shadow\" %lu mas ainda no est\n" -#~ "marcado\n" - -#~ msgid "insert_trust_record: keyblock not found: %s\n" -#~ msgstr "insert_trust_record: bloco de chaves no encontrado: %s\n" - -#~ msgid "lid %lu: update failed: %s\n" -#~ msgstr "lid %lu: atualizao falhou %s\n" - -#~ msgid "lid %lu: updated\n" -#~ msgstr "lid %lu: atualizado\n" - -#~ msgid "lid %lu: okay\n" -#~ msgstr "lid %lu: correto\n" - -#~ msgid "%s: keyblock read problem: %s\n" -#~ msgstr "%s: erro de leitura de bloco de chaves: %s\n" - -#~ msgid "%s: update failed: %s\n" -#~ msgstr "%s: atualizao falhou: %s\n" - -#~ msgid "%s: updated\n" -#~ msgstr "%s: atualizado\n" - -#~ msgid "%s: okay\n" -#~ msgstr "%s: correto\n" - -#~ msgid "lid %lu: keyblock not found: %s\n" -#~ msgstr "lid %lu: bloco de chaves no encontrado: %s\n" - -#~ msgid "can't lock keyring `%': %s\n" -#~ msgstr "impossvel bloquear chaveiro `%': %s\n" - -#~ msgid "error writing keyring `%': %s\n" -#~ msgstr "erro na escrita do chaveiro `%': %s\n" - -#~ msgid "can't open file: %s\n" -#~ msgstr "impossvel abrir arquivo: %s\n" - -#~ msgid "read error: %s\n" -#~ msgstr "erro de leitura: %s\n" - -#~ msgid "writing keyblock\n" -#~ msgstr "escrevendo bloco de chaves\n" - -#~ msgid "can't write keyblock: %s\n" -#~ msgstr "impossvel escrever bloco de chaves: %s\n" - -#, fuzzy -#~ msgid "encrypted message is valid\n" -#~ msgstr "algoritmo de \"digest\" selecionado no vlido\n" - -#, fuzzy -#~ msgid "Can't check MDC: %s\n" -#~ msgstr "Impossvel verificar assinatura: %s\n" - -#~ msgid "Usage: gpgm [options] [files] (-h for help)" -#~ msgstr "Uso: gpgm [opes] [arquivos] (-h para ajuda)" - -#~ msgid "" -#~ "Syntax: gpgm [options] [files]\n" -#~ "GnuPG maintenance utility\n" -#~ msgstr "" -#~ "Sintaxe: gpgm [opes] [arquivos]\n" -#~ "Utilitrio de manuteno do GnuPG\n" - -#~ msgid "usage: gpgm [options] " -#~ msgstr "Uso: gpgm [opes] " - -#, fuzzy -#~ msgid "chained sigrec %lu has a wrong owner\n" -#~ msgstr "sigrec em cadeia %lu possui dono errado\n" - -#, fuzzy -#~ msgid "lid %lu: read dir record failed: %s\n" -#~ msgstr "lid %lu: leitura de registro de diretrio falhou: %s\n" - -#~ msgid "lid %lu: read key record failed: %s\n" -#~ msgstr "lid %lu: leitura de registro de chave falhou: %s\n" - -#~ msgid "lid %lu: read uid record failed: %s\n" -#~ msgstr "lid %lu: leitura de registro de uid falhou: %s\n" - -#, fuzzy -#~ msgid "lid %lu: read pref record failed: %s\n" -#~ msgstr "lid %lu: leitura de registro de preferncias falhou: %s\n" - -#, fuzzy -#~ msgid "user '%s' read problem: %s\n" -#~ msgstr "erro de leitura do usurio `%s': %s\n" - -#, fuzzy -#~ msgid "user '%s' list problem: %s\n" -#~ msgstr "erro de listagem do usurio `%s': %s\n" - -#, fuzzy -#~ msgid "user '%s' not in trustdb\n" -#~ msgstr "usurio `%s' no est no banco de dados de confiabilidade\n" - -#~ msgid "" -#~ "# List of assigned trustvalues, created %s\n" -#~ "# (Use \"gpgm --import-ownertrust\" to restore them)\n" -#~ msgstr "" -#~ "# Lista de valores de confiana designados, criada em %s\n" -#~ "# (Use \"gpgm --import-ownertrust\" para restaur-los)\n" - -#~ msgid "directory record w/o primary key\n" -#~ msgstr "registro de diretrio sem chave primria\n" - -#~ msgid "error: missing colon\n" -#~ msgstr "erro: falta dois pontos\n" - -#~ msgid "error: invalid fingerprint\n" -#~ msgstr "erro: impresso digital invlida\n" - -#~ msgid "error: no ownertrust value\n" -#~ msgstr "erro: nenhum valor de confiana\n" - -#~ msgid "key not in trustdb, searching ring.\n" -#~ msgstr "" -#~ "chave no encontrada no banco de dados de confiabilidade, procurando no " -#~ "chaveiro\n" - -#~ msgid "key not in ring: %s\n" -#~ msgstr "chave no encontrada no chaveiro: %s\n" - -#~ msgid "Oops: key is now in trustdb???\n" -#~ msgstr "Oops: agora a chave est no banco de dados de confiabilidade???\n" - -#~ msgid "Hmmm, public key lost?" -#~ msgstr "Hmmm, chave pblica perdida?" - -#~ msgid "did not use primary key for insert_trust_record()\n" -#~ msgstr "voc usou a chave primria para insert_trust_record()\n" - -#~ msgid "invalid clear text header: " -#~ msgstr "cabealho de texto puro invlido: " - -#~ msgid "LID %lu: changing trust from %u to %u\n" -#~ msgstr "LID %lu: mudando confiana de %u para %u\n" - -#~ msgid "LID %lu: setting trust to %u\n" -#~ msgstr "LID %lu: estabelecendo confiana para %u\n" diff --git a/po/sv.po b/po/sv.po deleted file mode 100644 index a3eb755ee..000000000 --- a/po/sv.po +++ /dev/null @@ -1,4987 +0,0 @@ -# Swedish messages for gnupg -# Copyright (C) 1999 Free Software Foundation, Inc. -# Daniel Resare , 1999. -# -# Thanks to Andr Dahlqvist for -# many improvements -# -# Also many thanks to my wife Olivia for -# patience, help and suggestions -# -# $Id$ -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.0.6\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2001-08-23 10:32+02:00\n" -"Last-Translator: Daniel Resare \n" -"Language-Team: Swedish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" -"Content-Transfer-Encoding: 8bit\n" - -#: util/secmem.c:88 -#, fuzzy -msgid "WARNING: using insecure memory!\n" -msgstr "Varning: anvnder oskert minne!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "operationen r ej mjlig utan tillgng till skert minne\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(du kan ha anvnt fel program fr denna uppgift)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ja" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "jJ" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "nej" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "avsluta" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "aA" - -#: util/errors.c:54 -msgid "general error" -msgstr "allmnt fel" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "oknd pakettyp" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "oknd version" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "oknd algoritm fr publik nyckel" - -# jag r inte njd med versttningen digest -> kontrollsumma, -# om du har ett bttre frslag kontakta mig grna p -# daniel@resare.com. Andra frslag jag sgat r digest (oversatt), -# fingeravtryck, indatakarakteristik, sammandrag och sammanfattning -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "oknd algoritm fr berkning av kontrollsumma" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "felaktig publik nyckel" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "felaktig hemlig nyckel" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "felaktig signatur" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "fel vid berkning av kontrollsumma" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "felaktig lsenordsfras" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "hittade inte publik nyckel" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "oknd chifferalgoritm" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "kan inte ppna nyckelringen" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "felaktigt paket" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "felaktigt skal" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "oknd anvndaridentitet" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "den hemliga nyckeln r inte tillgnglig" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "fel hemlig nyckel har anvnts" - -#: util/errors.c:72 -msgid "not supported" -msgstr "ej stdd" - -#: util/errors.c:73 -msgid "bad key" -msgstr "felaktig nyckel" - -#: util/errors.c:74 -msgid "file read error" -msgstr "fel vid lsning av fil" - -#: util/errors.c:75 -msgid "file write error" -msgstr "fel vid skrivning av fil" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "oknd komprimeringsalgoritm" - -#: util/errors.c:77 -msgid "file open error" -msgstr "fel vid ppnande av fil" - -#: util/errors.c:78 -msgid "file create error" -msgstr "fel vid skapande av fil" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "felaktig lsenordsfras" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "algoritmen fr publik nyckel r ej implementerad" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "chifferalgorimten r ej implementerad" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "oknd signaturklass" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "fel i tillitsdatabasen" - -# MPI str fr Multiple Precision Integer (tror jag) -#: util/errors.c:84 -msgid "bad MPI" -msgstr "felaktig MPI" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "resursbegrnsning" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "felaktig nyckelring" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "felaktigt certifikat" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "felformaterad anvndaridentitet" - -#: util/errors.c:89 -msgid "file close error" -msgstr "fel vid stngning av fil" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "fel vid namnbyte av fil" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "fel vid borttagande av fil" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "ovntad data" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "konflikt mellan tidsstmplar" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "oanvndbar algoritm fr publika nycklar" - -#: util/errors.c:95 -msgid "file exists" -msgstr "filen finns" - -#: util/errors.c:96 -msgid "weak key" -msgstr "svag nyckel" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "felaktigt argument" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "felaktig URI" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "ej stdd URI" - -#: util/errors.c:100 -msgid "network error" -msgstr "ntverksfel" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "ej krypterad" - -#: util/errors.c:103 -msgid "not processed" -msgstr "inte behandlade" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "oanvndbar publik nyckel" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "oanvndbar hemlig nyckel" - -#: util/errors.c:107 -#, fuzzy -msgid "keyserver error" -msgstr "allmnt fel" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... detta r ett fel i programmet (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "du har hittat ett fel i programmet ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "kan inte ppna \"%s\": %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "kan inte ta status p \"%s\": %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "\"%s\" r inte n vanlig fil - ignorerad\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "notera: filen random_seed r tom\n" - -#: cipher/random.c:401 -#, fuzzy -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "varning: random_seed har en felaktig storlek och anvnds drfr inte\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "kan inte lsa \"%s\": %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "notera: random_seed uppdaterades inte\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "kan inte skapa \"%s\": %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "kan inte skriva till \"%s\": %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "kan inte stnga \"%s\": %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "VARNING: anvnder en osker slumptalsgenerator!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Slumptalsgeneratorn r bara ett lappverk fr att\n" -"f den att fungera - den r inte p ngot stt en\n" -"stark slumptalsgenerator!\n" -"\n" -"ANVND INGEN DATA GENERERAD AV DETTA PROGRAM!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Otillrcklig mngd slumpdata tillgngliga. Jobba med andra saker\n" -"en stund fr att ge operativsystemet en chans att samla mer entropi!\n" -"(Behver %d fler byte)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Kommandon:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[fil]|skapa en signatur" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[fil]|skapa en klartext-signatur" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "skapa en signatur i en separat fil" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "kryptera data" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "endast kryptering med symmetriskt chiffer" - -#: g10/g10.c:315 -msgid "store only" -msgstr "endast lagring" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "dekryptera data (normallge)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "verifiera en signatur" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "rkna upp nycklar" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "rkna upp nycklar och signaturer" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "verifiera nyckelsignaturer" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "rkna upp nycklar och fingeravtryck" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "rkna upp hemliga nycklar" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "generera ett nytt nyckelpar" - -#: g10/g10.c:327 -#, fuzzy -msgid "remove keys from the public keyring" -msgstr "ta bort en nyckel frn den publika nyckelringen" - -#: g10/g10.c:329 -#, fuzzy -msgid "remove keys from the secret keyring" -msgstr "ta bort en nyckel frn den hemliga nyckelringen" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "signera en nyckel" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "signera en nyckel lokalt" - -#: g10/g10.c:332 -#, fuzzy -msgid "sign a key non-revocably" -msgstr "signera en nyckel lokalt" - -#: g10/g10.c:333 -#, fuzzy -msgid "sign a key locally and non-revocably" -msgstr "signera en nyckel lokalt" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "signera eller redigera en nyckel" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "generera ett terkallelesecertifikat" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "exportera nycklar" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "exportera nycklar till en nyckelserver" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "importera nycklar frn en nyckelserver" - -#: g10/g10.c:341 -#, fuzzy -msgid "search for keys on a key server" -msgstr "exportera nycklar till en nyckelserver" - -#: g10/g10.c:343 -#, fuzzy -msgid "update all keys from a keyserver" -msgstr "importera nycklar frn en nyckelserver" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "importera/sl ihop nycklar" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "skriv endast ut paketsekvensen" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "exportera de vrden som representerar gartillit" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "importera vrden som representerar gartillit" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "uppdatera tillitsdatabasen" - -#: g10/g10.c:357 -#, fuzzy -msgid "unattended trust database update" -msgstr "uppdatera tillitsdatabasen" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "reparera en korrupt tillitsdatabas" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Skala av en fil eller standard in" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Skapa ett skal fr en fil eller standard in" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [filer]|skriv ut kontrollsummor" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Flaggor:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "skapa utdata med ett ascii-skal" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|NAMN|kryptera fr NAMN" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|NAMN|anvnd NAMN som standardvrdet fr mottagare" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "anvnd standardnyckeln som standardmottagare" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "anvnd denna anvndaridentitet fr att signera eller dekryptera" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|stt kompressionsnivn till N (0 fr att sl av kompression)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "anvnd \"ursprunglig text\"-lget" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "anvnd som fil fr utdata" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "utfrlig" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "var ngot tystare" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "anvnd inte terminalen alls" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "anvnd v3-signaturer" - -#: g10/g10.c:397 -#, fuzzy -msgid "do not force v3 signatures" -msgstr "anvnd v3-signaturer" - -#: g10/g10.c:398 -#, fuzzy -msgid "force v4 key signatures" -msgstr "anvnd v3-signaturer" - -#: g10/g10.c:399 -#, fuzzy -msgid "do not force v4 key signatures" -msgstr "anvnd v3-signaturer" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "anvnd alltid en MDC fr kryptering" - -#: g10/g10.c:402 -#, fuzzy -msgid "never use a MDC for encryption" -msgstr "anvnd alltid en MDC fr kryptering" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "gr inga ndringar" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "" - -# syftar p ett anvndargrnsnitt i ett separat program, till exempel gpa -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "anvnd gpg-agenten" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "batch-lge: frga aldrig" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "anta att svaret r ja p de flesta frgor" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "anta att svaret r nej p de flesta frgor" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "lgg till denna nyckelring till listan av nyckelringar" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "lgg till denna hemliga nyckelring till listan" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|NAMN|anvnd NAMN som frvald hemlig nyckel" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|VRD|anvnd denna nyckelserver fr att sl upp nycklar" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|NAMN|stt teckentabellen fr terminalen till NAMN" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "ls flaggor frn fil" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|skriv statusinformation till denna FD" - -#: g10/g10.c:427 -#, fuzzy -msgid "|[file]|write status info to file" -msgstr "|FD|skriv statusinformation till denna FD" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|NYCKELID|lita ovillkorligen p denna nyckel" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|FIL|ladda tillggsmodul FIL" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "imitera lget som beskrivs i RFC1991" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "stll om alla flaggor s att gpg fljer OpenPGP-standarden" - -#: g10/g10.c:443 -#, fuzzy -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "stll om alla flaggor s att gpg fljer OpenPGP-standarden" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|anvnd lsenordslget N" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NAMN|anvnd kontrollsummealgoritmen NAMN fr lsenordsfraser" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NAMN|anvnd chifferalgoritmen NAMN fr lsenordsfraser" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAMN|anvnd chifferalgoritmen NAMN" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAMN|anvnd kontrollsummealgoritmen NAMN" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|anvnd komprimeringsalgoritmen N" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "slng bort nyckelidentitetsfltet frn krypterade paket" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Se manualsidan fr en komplett lista p alla kommandon och flaggor)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"Exempel:\n" -"\n" -"-se -r Bo [fil] signera och kryptera fr anvndaren Bo\n" -"--clearsign [fil] skapa en klartextsignatur\n" -"--detach-sign [fil] skapa en signatur i en separat fil\n" -"--list-keys [namn] visa nycklar\n" -"--fingerprint [namn] visa fingeravtryck\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "" -"Rapportera grna fel till .\n" -"Rapportera grna fel eller synpunkter p versttningen till .\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Anvndning: gpg [flaggor] [filer] (-h fr hjlp)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Syntax: gpg [flaggor] [filer]\n" -"signera, kontrollera, kryptera eller dekryptera\n" -"vilken operation som utfrs beror p programmets indata\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Stdda algoritmer:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "anvndning: gpg [flaggor] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "motstridiga kommandon\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "" - -#: g10/g10.c:1168 -#, fuzzy, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "OBSERVERA: instllningsfilen \"%s\" saknas\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "OBSERVERA: instllningsfilen \"%s\" saknas\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "instllningsfil \"%s\": %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "lser flaggor frn \"%s\"\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s r ingen giltig teckentabell\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "" - -#: g10/g10.c:1550 -#, fuzzy, c-format -msgid "%s:%d: invalid import options\n" -msgstr "VARNING: \"%s\" r en tom fil\n" - -#: g10/g10.c:1553 -#, fuzzy -msgid "invalid import options\n" -msgstr "felaktigt skal" - -#: g10/g10.c:1560 -#, fuzzy, c-format -msgid "%s:%d: invalid export options\n" -msgstr "VARNING: \"%s\" r en tom fil\n" - -#: g10/g10.c:1563 -#, fuzzy -msgid "invalid export options\n" -msgstr "felaktig nyckelring" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "VARNING: programmet kan komma att skapa en minnesutskrift!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "OBSERVERA: %s r inte fr normal anvndning!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s r inte tillten tillsammans med %s!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "det r ingen pong att anvnda %s tillsammans med %s!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "den valda chifferalgoritmen r ogiltig\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "den valda kontrollsummealgoritmen r ogiltig\n" - -#: g10/g10.c:1830 -#, fuzzy -msgid "selected certification digest algorithm is invalid\n" -msgstr "den valda kontrollsummealgoritmen r ogiltig\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "kompressionsalgoritmen mste vara i intervallet %d..%d\n" - -# jag bedmer att detta och de fljande r interna felmeddelanden -# som det r i princip omjligt att verstta p p ett bra stt. -# Sannolikheten fr att anvndaren drabbas av felmeddelandet -# r nd litet. Eventuellt borde meddelandena inte alls -# versttas fr att gra eventuell felskning lttare -# fr internationella felskare -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "variabeln \"completes-needed\" mste ha ett vrde som r strre n 0\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "variabeln \"marginals-needed\" mste vara strre n 1\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "variabeln \"max-cert-depth\" mste ha ett vrde mellan 1 och 255\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "OBSERVERA: enkelt S2K-lge (0) rekommenderas inte\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "ogiltigt S2K-lge; mste vara 0, 1 eller 3\n" - -#: g10/g10.c:1862 -#, fuzzy -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "ogiltigt S2K-lge; mste vara 0, 1 eller 3\n" - -#: g10/g10.c:1868 -#, fuzzy -msgid "invalid default preferences\n" -msgstr "skriv ut instllningar" - -#: g10/g10.c:1876 -#, fuzzy -msgid "invalid personal cipher preferences\n" -msgstr "skriv ut instllningar" - -#: g10/g10.c:1880 -#, fuzzy -msgid "invalid personal digest preferences\n" -msgstr "skriv ut instllningar" - -#: g10/g10.c:1884 -#, fuzzy -msgid "invalid personal compress preferences\n" -msgstr "skriv ut instllningar" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "misslyckades med att initialisera tillitsdatabasen: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [filnamn]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [filnamn]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [filnamn]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [filnamn]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [filnamn]" - -#: g10/g10.c:2056 -#, fuzzy -msgid "--sign --symmetric [filename]" -msgstr "--symmetric [filnamn]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [filnamn]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [filnamn]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key anvndaridentitet" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key anvndaridentitet" - -#: g10/g10.c:2110 -#, fuzzy -msgid "--nrsign-key user-id" -msgstr "--sign-key anvndaridentitet" - -#: g10/g10.c:2118 -#, fuzzy -msgid "--nrlsign-key user-id" -msgstr "--lsign-key anvndaridentitet" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key anvndaridentitet [kommandon]" - -# Filnamn bde med och utan fnuttar finns. lite ologiskt. Vill ngon -# fixa en patch? -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "kan inte ppna %s: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [anvndaridentitet] [nyckelring]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "misslyckades med att ta bort skalet: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "misslyckades med att skapa skal: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "felaktig hash-algoritm \"%s\"\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[filnamn]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "Skriv ditt meddelande hr ...\n" - -# se frra kommentaren -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "kan inte ppna \"%s\"\n" - -#: g10/g10.c:2691 -#, fuzzy -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"ett notationsnamn kan bara innehlla bokstver, siffror, punkter eller\n" -"understrykningstecken och sluta med ett likhetstecken\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "ett notationsvrde fr inte inehlla ngra kontrolltecken\n" - -#: g10/g10.c:2737 -#, fuzzy -msgid "the given certification policy URL is invalid\n" -msgstr "angiven URL r ogiltig\n" - -#: g10/g10.c:2739 -#, fuzzy -msgid "the given signature policy URL is invalid\n" -msgstr "angiven URL r ogiltig\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "skal: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "felaktig rubrikrad i skalet: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "rad i skalet: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "felaktig rubrikrad i klartextsignatur\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "flera klartextsignaturer gr in i varandra\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "felaktig bindestreck-kodad rad: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "ovntat skal:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "ogiltigt radix64-tecken %02x hoppades ver\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "fr tidigt filslut (ingen CRC-summa)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "fr tidigt filslut (i CRC-summan)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "felformaterad CRC-summa\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "CRC-fel; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "fr tidigt filslut (i den avslutande raden)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "fel i avslutande rad\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "hittade ingen giltig OpenPGP-data.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "felaktigt skal: raden r lngre n %d tecken\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"tecken kodade enligt \"quoted printable\"-standarden funna i skalet - detta\n" -"beror sannolikt p att en felaktig epostserver eller epostklient har " -"anvnts\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Ingen anledning har angivits" - -# tveksam versttning. funderar p "ersatt av ngot bttre" men det -# knns inte heller bra -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Nyckeln r ersatt" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Nyckeln har tappat sin skerhet" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Nyckeln anvnds inte lngre" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Anvndaridentiteten r inte lngre giltig" - -#: g10/pkclist.c:73 -#, fuzzy -msgid "reason for revocation: " -msgstr "Anledning till terkallelsen: " - -#: g10/pkclist.c:90 -#, fuzzy -msgid "revocation comment: " -msgstr "terkallelsekommentar: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "" - -#: g10/pkclist.c:258 -#, fuzzy, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"%lu har inte tilldelats ngot tillitsvrde:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -#, fuzzy -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Var god bestm hur mycket du litar p denna anvndare\n" -"nr det gller att korrekt verifiera andra anvndares nycklar\n" -"(genom att underska pass, underska fingeravtryck frn olika\n" -"kllor...)?\n" -"\n" -" 1 = Vet ej\n" -" 2 = Jag litar INTE p denna anvndare\n" -" 3 = Jag litar marginellt p denna anvndare\n" -" 4 = Jag litar fullstndigt p denna anvndare\n" -" s = visa mig mer information\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr "" - -#: g10/pkclist.c:274 -#, fuzzy, c-format -msgid " %d = I do NOT trust\n" -msgstr "%08lX: Vi litar INTE p denna nyckel\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr "" - -#: g10/pkclist.c:276 -#, fuzzy, c-format -msgid " %d = I trust fully\n" -msgstr "%s: ej en tillitsdatabasfil\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr "" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr "" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = g tillbaka till huvudmenyn\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr "" - -# q skall bytas ut mot a sfort det kollas upp s att q ocks funkar. -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " q = avsluta\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Vad vljer du? " - -#: g10/pkclist.c:316 -#, fuzzy -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Vill du verkligen ta bort denna nyckel? " - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Certifikat som leder till en plitlig nyckel:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "nyckeln %08lX: nyckeln har terkallats!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Vill du anvnda nyckeln trots det? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "nyckeln %08lX: en undernyckel har terkallats!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: nyckeln har blivit fr gammal\n" - -#: g10/pkclist.c:448 -#, fuzzy, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -" Det finns inget som indikerar att signaturen tillhr garen.\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Vi litar INTE p denna nyckel\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Det r inte skert att denna nyckel verkligen tillhr garen\n" -"men den accepteras trots detta\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Denna nyckel tillhr sannolikt garen\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Denna nyckel tillhr oss\n" - -#: g10/pkclist.c:513 -#, fuzzy -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Det r INTE skert att nyckeln tillhr sin gare. Om du\n" -"*verkligen* vet vad du gr, kan du svara ja p nsta frga\n" -"\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "VARNING: Anvnder en nyckel som inte r betrodd!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "VARNING: Denna nyckel har terkallats av sin gare!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Detta kan betyda att signaturen r en frfalskning.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "VARNING: Denna undernyckel har terkallats av sin gare!\n" - -#: g10/pkclist.c:580 -#, fuzzy -msgid "Note: This key has been disabled.\n" -msgstr "Denna nyckel har deaktiverats" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Notera: Denna nyckel har gtt ut!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "VARNING: Denna nyckel r inte certifierad med en plitlig signatur!\n" - -#: g10/pkclist.c:598 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Det finns inget som indikerar att signaturen tillhr garen.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "VARNING: Vi litar INTE p denna nyckel!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Signaturen r sannolikt en FRFALSKNING.\n" - -#: g10/pkclist.c:615 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"VARNING: Denna nyckel r inte certifierad med signaturer med ett\n" -"tillrckligt hgt tillitsvrde!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Det r inte skert att signaturen tillhr garen.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: %s verhoppad\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: hoppade ver: publik nyckel finns redan\n" - -#: g10/pkclist.c:811 -#, fuzzy -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Du specificerade ingen anvndaridentitet. (du kan anvnda \"-r\")\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Hittade inte anvndaridentiteten.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "" -"hoppade ver: den publika nyckeln r redan satt som frvald mottagare\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Den publika nyckeln r deaktiverad\n" - -#: g10/pkclist.c:870 -#, fuzzy -msgid "skipped: public key already set\n" -msgstr "%s: hoppade ver: publik nyckel finns redan\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "den frvalda mottagaren \"%s\" r oknd\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: hoppade ver: den publika nyckeln r deaktiverad\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "inga giltiga adresser\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "" - -#: g10/keygen.c:189 -#, fuzzy, c-format -msgid "preference %c%lu duplicated\n" -msgstr "hoppade ver \"%s\": kopia\n" - -#: g10/keygen.c:194 -#, fuzzy, c-format -msgid "too many `%c' preferences\n" -msgstr "skriv ut instllningar" - -#: g10/keygen.c:264 -#, fuzzy -msgid "invalid character in preference string\n" -msgstr "Ogiltigt tecken i namnet\n" - -#: g10/keygen.c:524 -#, fuzzy -msgid "writing direct signature\n" -msgstr "skriver sjlvsignatur\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "skriver sjlvsignatur\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "skriver signatur knuten till nyckeln\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "ogiltig nyckelstorlek; anvnder %u bitar\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "nyckelstorleken avrundad uppt till %u bitar\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Vlj vilken typ av nyckel du vill ha:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA och ElGamal (standardvalet)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (endast signering)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (endast kryptering)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (signering och kryptering)\n" - -#: g10/keygen.c:949 -#, fuzzy, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) DSA (endast signering)\n" - -#: g10/keygen.c:951 -#, fuzzy, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) ElGamal (endast kryptering)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (signering och kryptering)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Vad vljer du? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Anvndanadet av denna algoritm r frlegat - skapa nd? " - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Felaktigt val.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Kommer att generera ett nytt %s nyckelpar.\n" -" den minimala nyckelstorleken r 768 bitar\n" -" den frvalda nyckelstorleken r 1024 bitar\n" -" den strsta freslagna nyckelstorleken r 2048 bitar\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "Vilken nyckelstorlek vill du ha? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA tillter bara nyckelstorlekar frn 512 till 1024\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "" -"nyckelstorleken r fr liten; 1024 r det minsta tilltna vrdet fr RSA.\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "nyckelstorleken r fr liten; 768 r det minsta tilltna vrdet.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "nyckelstorleken r fr stor; %d r det strsta tilltna vrdet\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Nyckelstorlekar strre n 2048 r inte att rekommendera\n" -"eftersom berkningar tar MYCKET lng tid!\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "r du sker p att du vill ha denna nyckelstorlek? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Ok, men kom ihg att din bildskrm och ditt tangentbord ocks snder\n" -"avsljande strlning som kan avlyssnas!\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Den efterfrgade nyckelstorleken r %u bitar\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "avrundade uppt till %u bitar\n" - -# borde kolla upp mjligheterna i kllkoden att anvnda v m istllet fr wmy -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Specificera hur lnge nyckeln skall vara giltig.\n" -" 0 = nyckeln blir aldrig ogiltig\n" -" = nyckeln blir ogiltig efter n dagar\n" -" w = nyckeln blir ogiltig efter n veckor\n" -" m = nyckeln blir ogiltig efter n mnader\n" -" y = nyckeln blir ogiltig efter n r\n" - -# borde kolla upp mjligheterna i kllkoden att anvnda v m istllet fr wmy -#: g10/keygen.c:1126 -#, fuzzy -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Specificera hur lnge nyckeln skall vara giltig.\n" -" 0 = nyckeln blir aldrig ogiltig\n" -" = nyckeln blir ogiltig efter n dagar\n" -" w = nyckeln blir ogiltig efter n veckor\n" -" m = nyckeln blir ogiltig efter n mnader\n" -" y = nyckeln blir ogiltig efter n r\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Fr hur lng tid r nyckeln giltig? (0) " - -#: g10/keygen.c:1150 -#, fuzzy -msgid "Signature is valid for? (0) " -msgstr "Fr hur lng tid r nyckeln giltig? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "ogiltigt vrde\n" - -#: g10/keygen.c:1160 -#, fuzzy, c-format -msgid "%s does not expire at all\n" -msgstr "Nyckeln gr aldrig ut\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, fuzzy, c-format -msgid "%s expires at %s\n" -msgstr "Nyckeln gr ut vid fljande tidpunkt: %s\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Ditt system kan inte visa datum senare n r 2038.\n" -"Datum fram till r 2106 kommer dock att hanteras korrekt.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Stmmer detta (j/n)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Du behver en anvndaridentitet fr att identifiera din nyckel; mjukvaran\n" -"konstruerar en anvndaridentitet frn namn, kommentar och epostadress\n" -"enligt fljande form: \n" -" \"Gustav Vasa (Brutal kung) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Namn: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Ogiltigt tecken i namnet\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Namnet fr inte brja med en siffra\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Namnet mste vara tminstone 5 tecken lngt\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "Epostadress: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "Epostadressen r ogiltig\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "Kommentar: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "Ogiltigt tecken i kommentaren\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Du anvnder teckenuppsttningen \"%s\"\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Du valde fljande anvndaridentitet:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Ange inte epostadressen som namn eller kommentar\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "NnKkEeOoAa" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "ndra (N)amn, (K)ommentar, (E)post eller (A)vsluta? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "ndra (N)amn, (K)ommentar, (E)post eller (O)k/(A)vsluta? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Rtta frst felet\n" - -# fel kapitalisering i originalet? -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Du behver en lsenordsfras fr att skydda din hemliga nyckel\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -#, fuzzy -msgid "passphrase not correctly repeated; try again" -msgstr "lsenordsfrasen upprepades ej korrekt; frsk igen.\n" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Du vill inte ha ngon lsenordsfras - det r sannolikt en *dlig* id!\n" -"Jag kommer att gra det nd. Du kan ndra din lsenordsfras nrsomhelst\n" -"om du anvnder detta program med flaggan \"--edit-key\".\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Vi behver generera ett stor mngd slumpmssig data. Det r en bra id\n" -"att gra ngot annat (skriva p tangentbordet, rra musen, anvnda\n" -"hrddisken) under primtalsgenereringen; detta ger slumptalsgeneratorn\n" -"en strre chans att samla ihop en tillrcklig mngd entropi.\n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSA-nyckelparet kommer att ha 1024 bitar.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Skapandet av nycklar avbrts.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "skriver publik nyckel till \"%s\"\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "skriver hemlig nyckel till \"%s\"\n" - -#: g10/keygen.c:2205 -#, fuzzy, c-format -msgid "no writable public keyring found: %s\n" -msgstr "nyckel %08lX: hittade ingen publik nyckel: %s\n" - -#: g10/keygen.c:2211 -#, fuzzy, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "nyckel %08lX: hittade inte den hemliga nyckeln: %s\n" - -#: g10/keygen.c:2225 -#, fuzzy, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "fel vid skrivning av nyckelringen \"%s\": %s\n" - -#: g10/keygen.c:2232 -#, fuzzy, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "fel vid skrivning av nyckelringen \"%s\": %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "publik och hemlig nyckel skapad och signerad.\n" - -#: g10/keygen.c:2253 -#, fuzzy -msgid "key marked as ultimately trusted.\n" -msgstr "Certifikat som leder till en plitlig nyckel:\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Notera att denna nyckel inte kan anvndas fr kryptering. Du kommer kanske\n" -"att vilja anvnda kommandot \"--edit-key\" fr att generera en sekundr\n" -"nyckel fr detta syfte.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Nyckelgenereringen misslyckades: %s\n" - -# c-format behvs inte i singularis -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"nyckeln r skapad %lu sekund in i framtiden (problemet r\n" -"relaterat till tidsresande eller en felstlld klocka)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"nyckeln r skapad %lu sekunder in i framtiden (problemet r\n" -"relaterat till tidsresande eller en felstlld klocka)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "OSERVERA: att skapa undernycklar till v3-nycklar bryter mot OpenPGP\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Vill du verkligen skapa? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: kan inte ppna: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "fel vid skapandet av lsenordsfras: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" - -#: g10/encode.c:229 g10/encode.c:486 -#, fuzzy, c-format -msgid "`%s' already compressed\n" -msgstr "%lu nycklar behandlade\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: VARNING: tom fil\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "lser frn \"%s\"\n" - -#: g10/encode.c:456 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" - -#: g10/encode.c:558 g10/sign.c:758 -#, fuzzy, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "OBSERVERA: chifferalgoritmen %d finns inte i instllningarna\n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "" - -#: g10/encode.c:735 -#, fuzzy, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s krypterad fr: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, fuzzy, c-format -msgid "key `%s' not found: %s\n" -msgstr "anvndaren \"%s\" hittades inte: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, fuzzy, c-format -msgid "error reading keyblock: %s\n" -msgstr "fel vid lsning av \"%s\": %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "nyckeln %08lX fljer inte standarden RFC2440 - verhoppad\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "nyckeln %08lX r inte skyddad - verhoppad\n" - -#: g10/export.c:246 -#, fuzzy, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "nyckeln %08lX: ny nyckel - verhoppad\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "VARNING: exporterade ingenting\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "fr mnga poster i pk-cachen - inaktiverad\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Hittade inte anvndaridentiteten]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "anvnder sekundra nyckeln %08lX istllet fr primrnyckeln %08lX\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "nyckel %08lX: hemlig nyckel utan publik nyckel - hoppade ver\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "hoppar ver block av typen %d\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "har behandlat %lu nycklar hittills\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "fel vid lsning av \"%s\": %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr " Totalt antal behandlade enheter: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " verhoppade nya nycklar: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " utan anvndaridentiteter: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " importerade: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " ofrndrade: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " nya anvndaridentiteter: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " nya undernycklar: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " nya signaturer: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " nya terkallelser av nycklar: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " antal lsta hemliga nycklar: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr "antal importerade hemliga nycklar: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr "antal ofrndrade hemliga nycklar: %lu\n" - -#: g10/import.c:313 -#, fuzzy, c-format -msgid " not imported: %lu\n" -msgstr " importerade: %lu" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "nyckel %08lX: ingen anvndaridentitet\n" - -#: g10/import.c:597 -#, fuzzy, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "nyckel %08lX: ingen undernyckel fr nyckelbindning\n" - -# vad innebr fnutten i slutet? -#: g10/import.c:612 -#, fuzzy, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "nyckel %08lX: accepterade icke sjlvsignerad anvndaridentitet '" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "nyckel %08lX: inga giltiga anvndaridentiteter\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "detta kan bero p att det saknas en sjlvsignatur\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "nyckel %08lX: hittade ingen publik nyckel: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "nyckeln %08lX: ny nyckel - verhoppad\n" - -#: g10/import.c:646 -#, fuzzy, c-format -msgid "no writable keyring found: %s\n" -msgstr "fel vid skrivning av nyckelringen \"%s\": %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "skriver till \"%s\"\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "fel vid skrivning av nyckelringen \"%s\": %s\n" - -#: g10/import.c:663 -#, fuzzy, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "nyckel %08lX: importerade publik nyckel\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "nyckel %08lX: matchar inte vr lokala kopia\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "nyckel %08lX: kan inte hitta det ursprungliga nyckelblocket: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "nyckel %08lX: kan inte lsa det ursprungliga nyckelblocket %s\n" - -#: g10/import.c:740 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "nyckel %08lX: 1 ny anvndaridentitet\n" - -#: g10/import.c:743 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "nyckel %08lX: %d nya anvndaridentiteter\n" - -#: g10/import.c:746 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "nyckel %08lX: 1 ny signatur\n" - -#: g10/import.c:749 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "nyckel %08lX: %d nya signaturer\n" - -#: g10/import.c:752 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "nyckel %08lX: 1 ny undernyckel\n" - -#: g10/import.c:755 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "nyckel %08lX: %d nya undernycklar\n" - -#: g10/import.c:774 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "nyckel %08lX: inte frndrad\n" - -#: g10/import.c:844 -#, fuzzy, c-format -msgid "no default secret keyring: %s\n" -msgstr "ingen frvald publik nyckel\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "nyckel %08lX: den hemliga nyckeln r importerad\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "nyckel %08lX: finns redan i den hemliga nyckelringen\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "nyckel %08lX: hittade inte den hemliga nyckeln: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"nyckel %08lX: ingen publik nyckel - kan inte tillmpa " -"terkallelsecertifikatet\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "nyckel %08lX: ogiltigt terkallelsecertifikat: %s - avvisat\n" - -#: g10/import.c:969 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "nyckel %08lX: terkallelsecertifikat importerat\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "nyckel %08lX: ingen anvndaridentitet fr signaturen\n" - -#: g10/import.c:1030 -#, fuzzy, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "nyckel %08lX: algoritmen fr publik nyckel ej stdd\n" - -#: g10/import.c:1032 -#, fuzzy, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "nyckel %08lX: ogiltig sjlvsignatur\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "nyckel %08lX: ingen undernyckel fr nyckelbindning\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "nyckel %08lX: algoritmen fr publik nyckel ej stdd\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "nyckel %08lX: ogiltig undernyckelbindning\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "nyckel %08lX: ogiltig undernyckelbindning\n" - -#: g10/import.c:1088 -#, fuzzy, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "nyckel %08lX: ingen undernyckel fr nyckelbindning\n" - -#: g10/import.c:1097 -#, fuzzy, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "nyckel %08lX.%lu: Giltig terkallelse av undernyckel\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "nyckel %08lX: ogiltig undernyckelbindning\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "nyckel %08lX: hoppade ver anvndaridentitet '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "nyckel %08lX: hoppade ver undernyckel\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "nyckel %08lX: icke exporterbar signatur (klass %02x) - hoppade ver\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "nyckel %08lX: terkallelsecertifikat p fel plats - hoppade ver\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "nyckel %08lX: felaktigt terkallelsecertifikat: %s - hoppade ver\n" - -#: g10/import.c:1232 -#, fuzzy, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "nyckel %08lX: terkallelsecertifikat p fel plats - hoppade ver\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "nyckel %08lX: anvndaridentitet hittades tv gnger - slog ihop\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" - -#: g10/import.c:1460 -#, fuzzy, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "nyckel %08lX: lade till terkallelsecertifikat\n" - -#: g10/import.c:1491 -#, fuzzy, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "nyckel %08lX: %d nya signaturer\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[terkallelse]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[sjlvsignatur]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 felaktig signatur\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d felaktiga signaturer\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 signatur verifierades inte eftersom nyckeln saknades\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d signaturer verifierades inte eftersom nycklar saknades\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 signatur verifierades inte eftersom ett fel uppstod\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d signaturer verifierades inte eftersom fel uppstod\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 anvndaridentitet utan giltig sjlvsignatur hittades\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d anvndaridentiteter utan giltig sjlvsignatur hittades\n" - -#: g10/keyedit.c:360 -#, fuzzy, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Nyckeln r skyddad.\n" - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -#, fuzzy -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "r du sker p att du vill ha denna nyckelstorlek? " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr "" - -#: g10/keyedit.c:380 -#, fuzzy, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "VARNING: \"%s\" r en tom fil\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "" - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" - -#: g10/keyedit.c:446 -#, fuzzy, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "Redan signerad av nyckeln %08lX\n" - -#: g10/keyedit.c:450 -#, fuzzy, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "Redan signerad av nyckeln %08lX\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Det finns inget att signera med nyckeln %08lX\n" - -#: g10/keyedit.c:478 -#, fuzzy -msgid "This key has expired!" -msgstr "Notera: Denna nyckel har gtt ut!\n" - -#: g10/keyedit.c:498 -#, fuzzy, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Denna nyckel r inte skyddad.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "" - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr "" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr "" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr "" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr "" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"r du verkligen sker p att du vill signera denna nyckel\n" -"med din nyckel: \"" - -#: g10/keyedit.c:604 -#, fuzzy -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "detta kan bero p att det saknas en sjlvsignatur\n" - -#: g10/keyedit.c:608 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"Signaturen kommer att markeras som icke exporterbar.\n" -"\n" - -#: g10/keyedit.c:613 -#, fuzzy -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"Signaturen kommer att markeras som icke exporterbar.\n" -"\n" - -#: g10/keyedit.c:620 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"Signaturen kommer att markeras som icke exporterbar.\n" -"\n" - -#: g10/keyedit.c:624 -#, fuzzy -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"Signaturen kommer att markeras som icke exporterbar.\n" -"\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Vill du verkligen signera? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "signeringen misslyckades: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Denna nyckel r inte skyddad.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "De hemliga delarna av den primra nyckeln r inte tillgngliga.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Nyckeln r skyddad.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Kan inte redigera denna nyckel: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Skriv in den nya lsenordsfrasen fr denna hemliga nyckel.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Du vill inte ha ngon lsenordsfras - detta r sannolikt en dlig id!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Vill du verkligen gra detta? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "flyttar en nyckelsignatur till den rtta platsen\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "avsluta denna meny" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "spara och avsluta" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "visa denna hjlp" - -# skall dessa versttas? -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "visa fingeravtryck" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "list" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "rkna upp nycklar och anvndaridentiteter" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "vlj anvndaridentitet N" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "vlj sekundr nyckel N" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "rkna upp signaturer" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "signera nyckeln" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "signera nyckeln lokalt" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "nrsign" -msgstr "sign" - -#: g10/keyedit.c:916 -#, fuzzy -msgid "sign the key non-revocably" -msgstr "signera nyckeln lokalt" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "nrlsign" -msgstr "lsign" - -#: g10/keyedit.c:917 -#, fuzzy -msgid "sign the key locally and non-revocably" -msgstr "signera nyckeln lokalt" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "lgg till en anvndaridentitet" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "" - -#: g10/keyedit.c:920 -#, fuzzy -msgid "add a photo ID" -msgstr "lgg till en anvndaridentitet" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "ta bort en anvndaridentitet" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "lgg till en sekundr nyckel" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "ta bort en sekundr nyckel" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "addrevoker" -msgstr "addkey" - -#: g10/keyedit.c:926 -#, fuzzy -msgid "add a revocation key" -msgstr "lgg till en sekundr nyckel" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "ta bort signaturer" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "ndra utgngsdatum" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "hoppa mellan utskrift av hemliga och publika nycklar" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:933 -#, fuzzy -msgid "list preferences (expert)" -msgstr "skriv ut instllningar" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:934 -#, fuzzy -msgid "list preferences (verbose)" -msgstr "skriv ut instllningar" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "setpref" -msgstr "pref" - -#: g10/keyedit.c:935 -#, fuzzy -msgid "set preference list" -msgstr "skriv ut instllningar" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updpref" -msgstr "pref" - -#: g10/keyedit.c:936 -#, fuzzy -msgid "updated preferences" -msgstr "skriv ut instllningar" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "ndra lsenordsfrasen" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "trust" - -# originalet borde ha ett value -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "ndra gartillitsvrdet" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "terkalla signaturer" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "terkalla en sekundr nyckel" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "deaktivera en nyckel" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "aktivera en nyckel" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "kan ej gra detta i batch-lge\n" - -#: g10/keyedit.c:1000 -#, fuzzy, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "fel vid lsning av \"%s\": %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Den hemliga nyckeln finns tillgnglig.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Kommando> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Den hemliga nyckeln behvs fr att gra detta.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Anvnd kommandot \"toggle\" frst.\n" - -#: g10/keyedit.c:1134 -#, fuzzy -msgid "Key is revoked." -msgstr "Nyckeln r skyddad.\n" - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Vill du verkligen signera alla anvndaridentiteter? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Tips: Vlj det anvndarid du vill signera\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "Du mste vlja tminstone en anvndaridentitet.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Du kan inte ta bort den sista anvndaridentiteten!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Vill du verkligen ta bort alla valda anvndaridentiteter? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Vill du verkligen ta bort denna anvndaridentitet? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "Du mste vlja tminstone en nyckel.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Vill du verkligen ta bort valda nycklar? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Vill du verkligen ta bort denna nyckel? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Vill du verkligen terkalla de valda nycklarna? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Vill du verkligen terkalla denna nyckel? " - -#: g10/keyedit.c:1354 -#, fuzzy -msgid "Really update the preferences for the selected user IDs? " -msgstr "Vill du verkligen ta bort alla valda anvndaridentiteter? " - -#: g10/keyedit.c:1356 -#, fuzzy -msgid "Really update the preferences? " -msgstr "Vill du verkligen skapa terkallelsecertifikaten? (j/N)" - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Spara ndringarna? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Avsluta utan att spara? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "uppdateringen misslyckades: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "misslyckades med att uppdatera hemligheten: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Nyckeln r ofrndrad s det behvs ingen uppdatering.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Ogiltigt kommando (frsk med \"help\")\n" - -#: g10/keyedit.c:1750 -#, fuzzy, c-format -msgid "This key may be revoked by %s key " -msgstr "VARNING: Denna nyckel har terkallats av sin gare!\n" - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr "" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX skapad: %s gr ut: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " tillit: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Denna nyckel har deaktiverats" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! en undernyckel har terkallats: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "rev- hittade felaktig terkallelse\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? problem vid kontroll av terkallandet: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" - -#: g10/keyedit.c:2006 -#, fuzzy -msgid "Are you sure you still want to add it? (y/N) " -msgstr "r du sker p att du vill ha denna nyckelstorlek? " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Vill du radera denna korrekta signatur? (j/N/a)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Vill du radera denna ogiltiga signatur? (j/N/a)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Vill du radera denna oknda signatur? (j/N/a)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Vill du radera denna sjlvsignatur? (j/N)" - -# skulle lika grna kunna heta 1 signatur va? -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "Raderade %d signatur.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "Raderade %d signaturer.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Ingenting raderat.\n" - -#: g10/keyedit.c:2281 -#, fuzzy -msgid "Enter the user ID of the designated revoker: " -msgstr "Ange storleken p nyckeln" - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Tag bort markeringar frn de hemliga nycklarna.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Vlj som mest en sekundr nyckel.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "ndrar giltighetstid fr en sekundr nyckel.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "ndrar giltighetstid fr den primra nyckeln.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Du kan inte ndra giltighetsdatum fr en v3-nyckel\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Det finns ingen motsvarande signatur i den hemliga nyckelringen\n" - -#: g10/keyedit.c:2546 -#, fuzzy -msgid "Please select exactly one user ID.\n" -msgstr "Du mste vlja tminstone en anvndaridentitet.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, fuzzy, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "nyckel %08lX: ogiltig sjlvsignatur\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Ingen anvndaridentitet med index %d\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Ingen sekundr nyckel med index %d\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "anvndaridentitet: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"signerad med din nyckel %08lX %s\n" - -#: g10/keyedit.c:2918 -#, fuzzy, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"signerad med din nyckel %08lX %s\n" - -#: g10/keyedit.c:2923 -#, fuzzy, c-format -msgid "This signature expired on %s.\n" -msgstr "%s-signatur frn: %s\n" - -#: g10/keyedit.c:2927 -#, fuzzy -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Vill du verkligen terkalla denna nyckel? " - -#: g10/keyedit.c:2931 -#, fuzzy -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Vill du skapa ett terkallelsecertifikat fr denna signatur? (j/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Du har signerat fljande anvndaridentiteter:\n" - -#: g10/keyedit.c:2975 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " signerad av %08lX %s\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " terkallad av %08lX %s\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Du str i begrepp att terkalla dessa signaturer:\n" - -#: g10/keyedit.c:3013 -#, fuzzy, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " signerad av %08lX %s\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr "" - -#: g10/keyedit.c:3022 -#, fuzzy -msgid "Really create the revocation certificates? (y/N) " -msgstr "Vill du verkligen skapa terkallelsecertifikaten? (j/N)" - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "ingen hemlig nyckel\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" - -#: g10/keylist.c:91 -#, fuzzy -msgid "Critical signature policy: " -msgstr "%s-signatur frn: %s\n" - -#: g10/keylist.c:93 -#, fuzzy -msgid "Signature policy: " -msgstr "%s-signatur frn: %s\n" - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "VARNING: ogiltig notationsdata hittades\n" - -#: g10/keylist.c:127 -#, fuzzy -msgid "Critical signature notation: " -msgstr "Notation: " - -#: g10/keylist.c:129 -#, fuzzy -msgid "Signature notation: " -msgstr "Notation: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr "[gr ut: %s]" - -#: g10/keylist.c:1001 -#, fuzzy -msgid "Primary key fingerprint:" -msgstr "rkna upp nycklar och fingeravtryck" - -#: g10/keylist.c:1003 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingeravtryck:" - -#: g10/keylist.c:1010 -#, fuzzy -msgid " Primary key fingerprint:" -msgstr " Fingeravtryck:" - -#: g10/keylist.c:1012 -#, fuzzy -msgid " Subkey fingerprint:" -msgstr " Fingeravtryck:" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -#, fuzzy -msgid " Key fingerprint =" -msgstr " Fingeravtryck:" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "" - -#: g10/mainproc.c:258 -#, fuzzy, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "felaktig hash-algoritm \"%s\"\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s krypterad data\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "krypterad med en oknd algoritm %d\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "den publika nyckeln r %08lX\n" - -# DEK betyder Data Encryption Key, Meddelandet r frvirrande -# men efter att ha kikat i koden har jag kommit fram till att -# meddelandet bara visas om verbose-flaggan r satt, och d -# markerar meddelandet att get_session_key lyckades hitta -# rtt publik nyckel att kryptera datat med. Jag tycker -# inte att svenska versttningen r mycket obskyrare n engelska -# originalet iallafall. -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "data krypterad med publik nyckel: korrekt krypteringsnyckel\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "krypterad med %u-bitars %s-nyckel, ID %08lX, skapad %s\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "krypterad med %s-nyckel, ID %08lX\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "dekryptering med publik nyckel misslyckades: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, fuzzy, c-format -msgid "assuming %s encrypted data\n" -msgstr "%s krypterad data\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "dekrypteringen lyckades\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "VARNING: det krypterade meddelandet har ndrats!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "dekrypteringen misslyckades: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "OBSERVERA: avsndaren efterfrgade \"endast-fr-dina-gon\"\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "ursprungligt filnamn=\"%.*s\"\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "" -"fristende terkallelsecertifikat - anvnd \"gpg --import\" fr\n" -"att applicera\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Notation: " - -# finns det ngon bra svensk versttning av policy? -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Policy: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "signaturen verifierades inte\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "kan inte hantera dessa multipla signaturer\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Signerades %.*s med hjlp av %s-nyckeln med ID %08lX\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "FELAKTIG signatur frn \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -#, fuzzy -msgid "Expired signature from \"" -msgstr "Korrekt signatur frn \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Korrekt signatur frn \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " ven knd som \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Kan inte verifiera signaturen: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "ingen frikopplad signatur\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "fristende signatur av klassen 0x%02x\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "signatur av den gamla (PGP 2.x) typen\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "felaktigt rotpaket hittades i proc_tree()\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "kan inte deaktivera minnesutskrifter: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Experimentella algoritmer br inte anvndas!\n" - -# XXX -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "" -"denna chifferalgoritm r frlegad, anvnd istllet en mer normal algoritm!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" - -#: g10/misc.c:509 -#, fuzzy, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "VARNING: \"%s\" r en tom fil\n" - -#: g10/misc.c:513 -#, fuzzy, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "VARNING: \"%s\" r en tom fil\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "kan inte hantera algoritm %d fr publik nyckelhantering\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "underpaket av typen %d har den bit satt som markerar den som kritisk\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "kunde inte f tillgng till ngon gpg-agent i denna session\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "miljvariabeln GPG_AGENT_INFO r felformaterad\n" - -#: g10/passphrase.c:511 -#, fuzzy, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "skyddsalgoritmen %d stds inte\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "kan inte ansluta till \"%s\": %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -#, fuzzy -msgid "problem with the agent - disabling agent use\n" -msgstr "problem med agenten: agenten returnerar 0x%lx\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (huvudnyckelns identitet %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Du behver en lsenordsfras fr att lsa upp den hemliga nyckeln fr\n" -"anvndaren: \"%.*s\"\n" -"%u-bitars %s-nyckel, ID %08lX, skapad %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Ange lsenordsfras\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Repetera lsenordsfrasen\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "lsenordsfrasen r fr lng\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "felaktigt svar frn agenten\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "avbruten av anvndaren\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "problem med agenten: agenten returnerar 0x%lx\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Du behver en lsenordsfras fr att lsa upp den hemliga nyckeln fr\n" -"anvndaren: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-bits %s-nyckel, ID %08lX, skapad %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "kan inte frga efter lsenord i batch-lge\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Ange lsenordsfras: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Repetera lsenordsfrasen: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "data sparades inte, anvnd flaggan \"--output\" fr att spara den\n" - -#: g10/plaintext.c:108 -#, fuzzy, c-format -msgid "error creating `%s': %s\n" -msgstr "fel vid lsning av \"%s\": %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Lskopplad signatur.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Ange namnet p datafilen: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "lser frn standard in ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "ingen signerad data\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "kan inte ppna signerad data \"%s\"\n" - -#: g10/pubkey-enc.c:101 -#, fuzzy, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "anonym mottagare, frsker anvnda den hemliga nyckeln %08lX ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "ok, vi r den hemliga mottagaren.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "gammal kodning av krypteringsnyckeln stds inte\n" - -#: g10/pubkey-enc.c:178 -#, fuzzy, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "chifferalgoritmen %d r oknd eller avslagen\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "OBSERVERA: chifferalgoritmen %d finns inte i instllningarna\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "OBSERVERA: den hemliga nyckeln %08lX gick ut %s\n" - -#: g10/pubkey-enc.c:249 -#, fuzzy -msgid "NOTE: key has been revoked" -msgstr "nyckeln %08lX: nyckeln har terkallats!\n" - -#: g10/hkp.c:71 -#, fuzzy, c-format -msgid "requesting key %08lX from %s\n" -msgstr "frga efter nyckeln %08lX frn %s ...\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "kan inte hmta nyckeln frn en nyckelserver: %s\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "fel vid sndning till \"%s\": %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "lyckades snda till \"%s\" (status=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "misslyckades snda till \"%s\": status=%u\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "" - -#: g10/hkp.c:565 -#, fuzzy, c-format -msgid "can't search keyserver: %s\n" -msgstr "kan inte hmta nyckeln frn en nyckelserver: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "de hemliga nyckeldelarna r inte tillgnliga\n" - -#: g10/seckey-cert.c:59 -#, fuzzy, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "skyddsalgoritmen %d stds inte\n" - -#: g10/seckey-cert.c:224 -#, fuzzy -msgid "Invalid passphrase; please try again" -msgstr "Ogiltig lsenordsfras, frsk igen ...\n" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "" - -# r det nyckeln som r svag, konstigt -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "VARNING: Upptckte en svag nyckel - byt lsenordsfras igen.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "" - -#: g10/sig-check.c:215 -#, fuzzy, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"detta r en PGP-genererad ElGamal-nyckel som INTE r sker fr signaturer!\n" - -# behvs verkligen c-format hr? -#: g10/sig-check.c:224 -#, fuzzy, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "den publika nyckeln r %lu sekund nyare n signaturen\n" - -#: g10/sig-check.c:225 -#, fuzzy, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "den publika nyckeln r %lu sekunder nyare n signaturen\n" - -# c-format behvs inte i singularis -#: g10/sig-check.c:234 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"nyckeln r skapad %lu sekund in i framtiden (problemet r\n" -"relaterat till tidsresande eller en felstlld klocka)\n" - -#: g10/sig-check.c:236 -#, fuzzy, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"nyckeln r skapad %lu sekunder in i framtiden (problemet r\n" -"relaterat till tidsresande eller en felstlld klocka)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "OBSERVERA: signaturnyckeln %08lX, gick ut vid %s\n" - -#: g10/sig-check.c:348 -#, fuzzy, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"antar att signaturen r felaktig eftersom en oknd kritisk bit r satt\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "frsk att verifiera signaturen misslyckades: %s\n" - -#: g10/sign.c:312 -#, fuzzy, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s-signatur frn: %s\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "VARNING: \"%s\" r en tom fil\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "kan inte skapa %s: %s\n" - -#: g10/sign.c:690 -#, fuzzy, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "OBSERVERA: chifferalgoritmen %d finns inte i instllningarna\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "signerar:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" - -#: g10/sign.c:1029 -#, fuzzy, c-format -msgid "%s encryption will be used\n" -msgstr "dekrypteringen misslyckades: %s\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "kan inte hantera text med rader lngre n %d tecken\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "indataraden r lngre n %d tecken\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "tillitsdatabasposten %lu: lseek misslyckades: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "tillitsdatabasposten %lu: skrivning misslyckades (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "tillitsdatabastransaktion fr stor\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: ingen tkomst: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: katalogen finns inte!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: kan inte skapa ls\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, fuzzy, c-format -msgid "%s: can't make lock\n" -msgstr "%s: kan inte skapa ls\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: kan inte skapa: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: misslyckades med att skapa versionspost: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: felaktig tillitsdatabas skapad\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: tillitsdatabas skapad\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: felaktig tillitsdatabas\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: misslyckades med att skapa hash-tabell: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: fel vid uppdatering av versionspost: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: fel vid lsning av versionspost: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: fel vid skrivning av versionspost: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "tillitsdatabas: lseek misslyckades: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "tillitsdatabas: lsning misslyckades (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: ej en tillitsdatabasfil\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: versionspost med postnummer %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: ogiltig filversion %d\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: fel vid lsning av ledig post: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: fel vid lsning av katalogpost: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: misslyckades med att nollstlla en post: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: misslyckades med att lgga till en post: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "tillitsdatabasen r trasig, kr \"gpg --fix-trustdb\".\n" - -#: g10/trustdb.c:200 -#, fuzzy, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "\"%s\" r en ogiltig lng nyckelidentitet\n" - -#: g10/trustdb.c:235 -#, fuzzy, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "nyckel %08lX: accepterad som en plitlig nyckel\n" - -#: g10/trustdb.c:274 -#, fuzzy, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "nyckel %08lX: kan inte lgga till i tillitsdatabasen\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "nyckel %08lX: hittade ingen motsvarande publik nyckel - verhoppad\n" - -# req r nog felstavat i originalet d det syftar p record och inte -# request -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "tillitspost %lu, posttyp %d: kunde inte lsa: %s\n" - -#: g10/trustdb.c:338 -#, fuzzy, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "tillitspost %lu: kunde inte radera: %s\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "tillitspost: %lu, typ %d: kunde inte skriva: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "tillitsdatabas: synkronisering misslyckades: %s\n" - -#: g10/trustdb.c:468 -#, fuzzy -msgid "no need for a trustdb check\n" -msgstr "%s: ej en tillitsdatabasfil\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, fuzzy, c-format -msgid "next trustdb check due at %s\n" -msgstr "tillitsdatabasposten %lu: lseek misslyckades: %s\n" - -# originalet borde ha ett value -#: g10/trustdb.c:779 -#, fuzzy -msgid "checking the trustdb\n" -msgstr "ndra gartillitsvrdet" - -#: g10/trustdb.c:933 -#, fuzzy, c-format -msgid "public key %08lX not found: %s\n" -msgstr "hittade inte publik nyckel" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"signaturen kunde inte verifieras.\n" -"Kom ihg att signaturfilen (.sig eller .asc)\n" -"ska vara den frst angivna filen p kommandoraden\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "raden %u r fr lng, eller saknar nyradstecken\n" - -# om ngon kan tala om fr mig vad detta betyder skulle jag bli jtteglad! -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"nyckeln r inte markerad osker - gr inte att anvnda med fejkad RNG!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "hoppade ver \"%s\": kopia\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "hoppade ver \"%s\": %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "hoppade ver: hemlig nyckel finns redan\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"hoppade ver \"%s\": detta r en nyckel av ElGamal-typ genererad av PGP\n" -"som inte r sker fr signaturer!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Filen \"%s\" finns. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "Skriv ver (j/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: oknt suffix\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Ange nytt filnamn" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "skriver till standard ut\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "antar att signera data finns i filen \"%s\"\n" - -#: g10/openfile.c:326 -#, fuzzy, c-format -msgid "new configuration file `%s' created\n" -msgstr "%s: ny instllningsfil skapad\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: kan inte skapa katalog: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: katalog skapad\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"VARNING: meddelandet krypterades med en svag nyckel i det symmetriska\n" -"chiffret.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "problem vid hanteringen av krypterat paket\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "skapade en svag nyckel - frsker igen\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"kan inte undvika en svag nyckel fr symmetriskt chiffer; frskte\n" -"%d gnger!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "kan inte gra s i batch-lge utan flaggan \"--yes\"\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Vill du ta bort denna nyckel frn nyckelringen? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Detta r en hemlig nyckel! - vill du verkligen ta bort den? " - -#: g10/delkey.c:168 -#, fuzzy, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "numrering av nyckelblock misslyckades: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "" - -#: g10/delkey.c:206 -#, fuzzy, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "det finns en hemlig nyckel tillhrande denna publika nyckel!\n" - -#: g10/delkey.c:208 -#, fuzzy -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "anvnd flaggan \"--delete-secret-key\" fr att ta bort den frst.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Det r upp till dig att ange ett vrde hr. Detta vrde kommer aldrig att\n" -"exporteras till ngon tredje part. Vi behver det fr att implementera\n" -"\"ntet av tillit\". Det har inget att gra med det (implicit skapade)\n" -"ntet av certifikat." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "Om du vill anvnda denna terkallade nyckel nd, svara \"ja\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "Om du vill anvnda denna otillfrlitliga nyckel nd, svara \"ja\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Ange anvndaridentiteten till vilken du vill skicka meddelandet." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Vlj vilken algoritm du vill anvnda.\n" -"\n" -"DSA (ven knd som DSS) r den algoritm fr digitala signaturer som bara\n" -"kan anvndas fr just signaturer. Detta r den rekommenderade algoritmen\n" -"eftersom verifiering av DSA-signaturer r mycket snabbare n\n" -"ElGamal-signaturer.\n" -"\n" -"ElGamal r en algoritm som kan anvndas fr signaturer och kryptering.\n" -"OpenPGP-standarden skiljer p tv varianter av denna algoritm: en som bara\n" -"kan anvndas fr kryptering och en som bde kan signera och kryptera.\n" -"Egentligen r det samma algoritm, men vissa parametrar mste vljas p\n" -"ett speciellt stt fr att skapa en sker nyckel fr signaturer: detta " -"program\n" -"gr detta men andra OpenPGP-implementationer behver inte frst\n" -"signatur+kryptering varianten.\n" -"\n" -"Den frsta (primra) nyckeln mste alltid vara en nyckel som kan anvndas\n" -"fr att skapa signaturer. Detta r anledningen till att den ElGamal-variant\n" -"som bara krypterar inte r tillgnglig i denna meny" - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Trots att dessa nycklar r definierade i RFC2440 r det inte rekommenderat\n" -"att anvnda dem eftersom de inte stds i alla program och signaturer\n" -"skapade med dem r stora och mycket lngsamma att verifiera." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Ange storleken p nyckeln" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Svara \"ja\" eller \"nej\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Ange vrdet som krvs som det visas vid prompten.\n" -"Det r mjligt att ange ett ISO-datum (-MM-DD) men du kommer\n" -"inte att f ngot vettigt felmeddelande - istllet kommer systemet\n" -"att frska tolka det angivna vrdet som ett intervall." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Ange namnet p nyckelns gare" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "ange en epostadress. Detta r valfritt men rekommenderas varmt" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Ange en valfri kommentar" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N fr att ndra namnet.\n" -"C fr att ndra kommentaren.\n" -"E fr att ndra epostadressen.\n" -"O fr att fortstta med nyckelgenerering.\n" -"Q fr att avsluta nyckelgenereringen." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Svara \"ja\" (eller bara \"j\") om du vill generera denna undernyckel." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" - -# felstavat original -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Svara \"ja\" om du vill signera ALLA anvndaridentiteter" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Svara \"ja\" om du verkligen vill ta bort denna anvndaridentitet.\n" -"Alla certifikat kommer att g frlorade!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Svara \"ja\" om du vill ta bort denna undernyckel" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Detta r en giltig signatur p nyckeln. Normalt sett vill du inte\n" -"ta bort denna signatur eftersom den kan vara viktig fr att skapa\n" -"en tillitskoppling till nyckeln eller en annan nyckel som r\n" -"certifierad av denna nyckel." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Denna signatur kan inte verifieras eftersom du inte har den\n" -"motsvarande nyckeln. Du br vnta med att ta bort den tills du\n" -"vet vilken nyckel som anvndes eftersom den nyckeln kanske upprttar\n" -"en tillitskoppling genom en annan redan certifierad nyckel." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"Denna signatur r inte giltig. Det r rimligt att ta bort den frn\n" -"din nyckelring." - -# borde inge GnuPG bytas ut mot gpg eller nnu bttre %s? -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Detta r en signatur som knyter anvndaridentiteten till denna nyckel.\n" -"Det r oftast inte en bra id att ta bort en sdan signatur. Till\n" -"och med kan det bli s att GnuPG kanske inte kan anvnda denna nyckel\n" -"mer. S gr bara detta om denna sjlvsignatur av ngon anledning r\n" -"ogiltig och det finns en andra signatur som tillgnglig." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" - -# ej klar, eller? -#: g10/helptext.c:244 -#, fuzzy -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "" -"Ange en lsenordsfras. Detta r en hemlig mening\n" -"[hjlptexten ej frdigstlld]" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Reptera lsenordsfrasen, s du r sker p vad du skrev in." - -# # felstavat/ologiskt original -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "Ange namnet p den fil signaturen gller" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Svara \"ja\" om det du vill skriva ver filen" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Ange ett nytt filnamn. Om du bara trycker RETUR kommer standarfilnamnet\n" -"(som anges i hakparenteser) att anvndas." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Du borde ange en anledning till certifikationen. Beroende p sammanhanget\n" -"har du mjligheten att vlja frn fljande lista:\n" -" \"Nyckeln har tappat sin skerhet\"\n" -" Anvnd denna om du har anledning att tro att icke auktoriserade " -"personer\n" -" har ftt tillgng till din hemliga nyckel.\n" -" \"Nyckeln har ersatts\"\n" -" Anvnd denna om du har ersatt denna nyckel med en nyare.\n" -" \"Nyckeln anvnds inte lngre\"\n" -" Anvnd denna om du har pensionerat denna nyckel.\n" -" \"Anvndaridentiteten r inte lngre giltig\"\n" -" Anvnd denna fr att visa att denna anvndaridentitet inte lngre\n" -" skall anvndas. Detta anvnds normalt fr att visa att en epostadress\n" -" r ogiltig.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Om du vill kan du ange en text som beskriver varfr du utfrdar\n" -"detta terkallelsecertifikat. Frsk att hlla texten kort och koncis.\n" -"En tom rad avslutar texten.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Det finns ingen hjlp tillgnglig" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Det finns ingen hjlp tillgnglig fr \"%s\"" - -#: g10/keydb.c:178 -#, fuzzy, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "fel vid skrivning av nyckelringen \"%s\": %s\n" - -#: g10/keydb.c:185 -#, fuzzy, c-format -msgid "keyring `%s' created\n" -msgstr "%s: nyckelring skapad\n" - -#: g10/keydb.c:575 -#, fuzzy, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "%s: misslyckades med att skapa hash-tabell: %s\n" - -# mrkligt felmeddelande, kolla upp -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "VARNING: det finns 2 filer med konfidentiell information.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s r den ofrndrade\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s r den nya\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Ls detta potentiella skerhetsproblem\n" - -#: g10/keyring.c:1346 -#, fuzzy, c-format -msgid "checking keyring `%s'\n" -msgstr "kan inte lsa nyckelringen \"%s\": %s\n" - -#: g10/keyring.c:1377 -#, fuzzy, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "har behandlat %lu nycklar hittills\n" - -#: g10/keyring.c:1388 -#, fuzzy, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "rkna upp nycklar och signaturer" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: nyckelring skapad\n" - -# GnuPG borde vl ersttas med %s? -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "du mste starta om GnuPG, s att den nya instllningsfilen kan lsas\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Fingeravtryck:" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingeravtryck:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAMN=VRDE|anvnd detta stt fr att beskriva data" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "det frsta tecknet i ett notationsnamn mste vara en bokstav eller\n" -#~ "ett understrykningstecken (_)\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "punkter i ett notationsnamn mste vara omgivna av andra tecken\n" - -#, fuzzy -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "r du sker p att du vill ha denna nyckelstorlek? " - -#, fuzzy -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr "r du sker p att du vill ha denna nyckelstorlek? " - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Vill du verkligen signera? " - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "fr mnga slumpmssiga bitar efterfrgades; maximalt antal r %d\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NAMN]|kontrollera tillitsdatabasen" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key anvndaridentitet" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key anvndaridentitet" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key anvndaridentitet" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Fr information se http://www.gnupg.org/" - -# vrdena str fr s = show me more info, m = back to menu, q = quit -# hur skall sdant internationaliseras p ett bra stt? -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Kunde inte hitta ngon giltig tillitsvg till nyckeln. Lt oss se om vi " -#~ "kan\n" -#~ "tilldela ngra av de gartillitsvrden som saknas\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "En av de funna nycklarna saknar tillitsvg.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Hittade inga certifikat med odefinierat tillitvrde\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Inga tillitsvrden ndrade.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "" -#~ "%08lX: det finns ingen information fr att berkna ett tillitvrde\n" - -#~ msgid "Enter the user ID: " -#~ msgstr "Ange anvndaridentiteten: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "hoppade ver: publik nyckel r redan angiven med --encrypt-to\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: fel vid kontroll av nyckeln: %s\n" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "Vill du verkligen skapa en nyckel fr signering och kryptering? " - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Behver du verkligen en s stor nyckelstorlek? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: hittade inte anvndaren: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "fel vid lsning av certifikat: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "fr mnga poster i unk-cachen - inaktiverad\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "" -#~ "den hemliga nyckeln %08lX importerades inte (anvnd %s fr att tillta)\n" - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "nyckel %08lX: vr kopia har ingen sjlvsignatur\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: hittade inte anvndaren\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "uppdateringen av tillitsdatabasen misslyckades: %s\n" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "knner inte till ngon nyckelserver (anvnd flaggan --keyserver)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: ogiltig nyckelidentitet\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "antar att MDC r felaktig eftersom en oknd kritisk bit r satt\n" - -# LID betyder local id och r serienumret i den lokala databasen -# fr en given nyckel -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "fel vid lsning av katalogpost fr lokalt id %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lokalt id %lu: vntade en katalogpost, fick en post av typen %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "ingen primr nyckel fr lokalt id %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "fel vid lsning av primr nyckel fr lokalt id %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record misslyckades: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "nyckel %08lX: uppslagning av post misslyckades\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "nyckel %08lX: finns redan i tabellen ver plitliga nycklar\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "OBSERVERA: den hemliga nyckeln %08lX r INTE skyddad.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "nyckel %08lX: hemlig och publik nyckel stmmer inte verens\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "numrering av hemliga nycklar misslyckades: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "nyckel: %08lX.%lu: Korrekt bindning till undernyckel\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "nyckel %08lX.%lu: Felaktig bindning till undernyckel: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "nyckel %08lX.%lu: Giltig terkallelse av nyckel\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "nyckel %08lX.%lu: Felaktig terkallelse av nyckel: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Korrekt sjlvsignatur" - -#~ msgid "Invalid self-signature" -#~ msgstr "Felaktig sjlvsignatur" - -# detta verkar mycket mrkligt. Ngon borde kanske f en frklaring frn -# gnupg-utvecklarna? -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Hoppade ver en giltig terkallelse av anvndaridentiteten p\n" -#~ "grund av en nyare sjlvsignatur" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Giltig terkallelse av anvndaridentitet" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Ogiltig terkallelse av anvndaridentitet" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Giltig terkallelse av certifikat" - -#~ msgid "Good certificate" -#~ msgstr "Korrekt certifikat" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Ogiltig terkallelse av certifikat " - -#~ msgid "Invalid certificate" -#~ msgstr "Ogiltigt certifikat" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "signaturpost %lu[%d] pekar mot fel post.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "dubblett av certifikat - borttaget" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir misslyckades: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lokalt id ?: tillgg misslyckades: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lokalt id %lu: tillgg misslyckades: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lokalt id %lu: lades till\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "fel vid lsning av katalogpost: %s\n" - -#~ msgid "\t%lu keys with errors\n" -#~ msgstr "\t%lu nycklar med fel\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu nycklar tillagda\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lokalt id %lu: katalogpost utan nyckel - hoppade ver\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu p grund av nya publika nycklar\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu nycklar hoppades ver\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu nycklar uppdaterades\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Ooops, inga nycklar\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Ooops, inga anvndaridentiteter\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: skning av katalogpost misslyckades: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "nyckel %08lX: tillgg av tillitspost misslyckades: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "nyckel %08lX.%lu: lades till i tillitsdatabasen\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "nyckel %08lX.%lu: skapad i framtiden (problemet r relaterat till\n" -#~ "tidsresande eller en felstlld klocka)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "nyckel %08lX.%lu: gick ut %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "nyckel %08lX.%lu: tillitskontroll misslyckades: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "problem att hitta \"%s\" i tillitsdatabasen: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "anvndaren \"%s\" finns inte tillitsdatabasen - lgger till\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "misslyckades med att placera \"%s\" i tillitsdatabasen: %s\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "VARNING: kan nnu inte hantera lnga instllningsposter\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: kan inte skapa nyckelring: %s\n" diff --git a/po/tr.po b/po/tr.po deleted file mode 100644 index 2650f9a32..000000000 --- a/po/tr.po +++ /dev/null @@ -1,4658 +0,0 @@ -# Turkish translations for GnuPG messages. -# Copyright (C) 2002 Free Software Foundation, Inc. -# Nilgn Belma Bugner , 2001, 2002. -# -msgid "" -msgstr "" -"Project-Id-Version: gnupg 1.2.0\n" -"POT-Creation-Date: 2002-09-11 15:11+0200\n" -"PO-Revision-Date: 2002-09-11 22:09+0300\n" -"Last-Translator: Nilgn Belma Bugner \n" -"Language-Team: Turkish \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ISO-8859-9\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: KBabel 0.9.6\n" - -#: util/secmem.c:88 -msgid "WARNING: using insecure memory!\n" -msgstr "UYARI: kullanlan bellek gvenli deil!\n" - -#: util/secmem.c:89 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "" -"Daha geni bilgi edinmek iin http://www.gnupg.org/faq.html adresine " -"baknz\n" - -#: util/secmem.c:326 -msgid "operation is not possible without initialized secure memory\n" -msgstr "gvenli bellek hazrlanmadan ilem yapmak mmkn deil\n" - -#: util/secmem.c:327 -msgid "(you may have used the wrong program for this task)\n" -msgstr "(bu grev iin yanl program kullanm olabilirsiniz)\n" - -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "evet" - -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "eE" - -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "hayr" - -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "hH" - -#: g10/keyedit.c:901 util/miscutil.c:333 -msgid "quit" -msgstr "k" - -#: util/miscutil.c:336 -msgid "qQ" -msgstr "" - -#: util/errors.c:54 -msgid "general error" -msgstr "genel hata" - -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "bilinmeyen paket tipi" - -#: util/errors.c:56 -msgid "unknown version" -msgstr "bilinmeyen srm" - -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "bilinmeyen genel anahtar algoritmas" - -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "bilinmeyen zmleme algoritmas" - -#: util/errors.c:59 -msgid "bad public key" -msgstr "genel anahtar hatal" - -#: util/errors.c:60 -msgid "bad secret key" -msgstr "gizli anahtar hatal" - -#: util/errors.c:61 -msgid "bad signature" -msgstr "imza hatal" - -#: util/errors.c:62 -msgid "checksum error" -msgstr "\"checksum\" hatas" - -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "anahtar parolas hatal" - -#: util/errors.c:64 -msgid "public key not found" -msgstr "genel anahtar bulunamad" - -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "bilinmeyen ifre algoritmas" - -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "anahtar zinciri alamad" - -#: util/errors.c:67 -msgid "invalid packet" -msgstr "geersiz paket" - -#: util/errors.c:68 -msgid "invalid armor" -msgstr "geersiz zrh" - -#: util/errors.c:69 -msgid "no such user id" -msgstr "byle bir kullanc kimlii yok" - -#: util/errors.c:70 -msgid "secret key not available" -msgstr "gizli anahtar kullansz" - -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "yanl gizli anahtar kullanlm" - -#: util/errors.c:72 -msgid "not supported" -msgstr "desteklenmiyor" - -#: util/errors.c:73 -msgid "bad key" -msgstr "anahtar hatal" - -#: util/errors.c:74 -msgid "file read error" -msgstr "dosya okuma hatas" - -#: util/errors.c:75 -msgid "file write error" -msgstr "dosya yazma hatas" - -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "bilinmeyen sktrma algoritmas" - -#: util/errors.c:77 -msgid "file open error" -msgstr "dosya ama hatas" - -#: util/errors.c:78 -msgid "file create error" -msgstr "dosya oluturma hatas" - -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "anahtar parolas geersiz" - -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "tamamlanmam genel anahtar algoritmas" - -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "tamamlanmam ifre algoritmas" - -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "bilinmeyen imza snf" - -#: util/errors.c:83 -msgid "trust database error" -msgstr "gvence veritaban hatas" - -#: util/errors.c:84 -msgid "bad MPI" -msgstr "MPI hatal" - -#: util/errors.c:85 -msgid "resource limit" -msgstr "i kaynak snr" - -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "anahtar zinciri geersiz" - -#: util/errors.c:87 -msgid "bad certificate" -msgstr "sertifika hatal" - -#: util/errors.c:88 -msgid "malformed user id" -msgstr "kullanc kimlii bozuk" - -#: util/errors.c:89 -msgid "file close error" -msgstr "dosya kapama hatas" - -#: util/errors.c:90 -msgid "file rename error" -msgstr "dosya isim deitirme hatas" - -#: util/errors.c:91 -msgid "file delete error" -msgstr "dosya silme hatas" - -#: util/errors.c:92 -msgid "unexpected data" -msgstr "beklenmeyen veri" - -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "zaman damgas elikili" - -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "genel anahtar algoritmas kullansz" - -#: util/errors.c:95 -msgid "file exists" -msgstr "dosya mevcut" - -#: util/errors.c:96 -msgid "weak key" -msgstr "anahtar zayf" - -#: util/errors.c:97 -msgid "invalid argument" -msgstr "geersiz argman" - -#: util/errors.c:98 -msgid "bad URI" -msgstr "URI hatal" - -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "desteklenmeyen URI" - -#: util/errors.c:100 -msgid "network error" -msgstr "a hatas" - -#: util/errors.c:102 -msgid "not encrypted" -msgstr "ifrelenemedi" - -#: util/errors.c:103 -msgid "not processed" -msgstr "ilenemedi" - -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "genel anahtar kullanmd" - -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "gizli anahtar kullanmd" - -#: util/errors.c:107 -msgid "keyserver error" -msgstr "anahtar sunucusu hatas" - -#: util/logger.c:249 -#, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... bu bir yazlm hatas (%s:%d:%s)\n" - -#: util/logger.c:255 -#, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "bir yazlm hatas buldunuz ... (%s:%d)\n" - -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "rasgele bayt elde etme modl bulunamad\n" - -#: cipher/random.c:381 g10/import.c:195 g10/keygen.c:1809 -#, c-format -msgid "can't open `%s': %s\n" -msgstr "`%s' alamyor: %s\n" - -#: cipher/random.c:385 -#, c-format -msgid "can't stat `%s': %s\n" -msgstr "`%s' durumlanamyor: %s\n" - -#: cipher/random.c:390 -#, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "`%s' dzenli bir dosya deil - grlmedi\n" - -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "not: \"random_seed\" dosyas bo\n" - -#: cipher/random.c:401 -msgid "WARNING: invalid size of random_seed file - not used\n" -msgstr "UYARI: random_seed dosyasnn boyu hatal - kullanlmad\n" - -#: cipher/random.c:409 -#, c-format -msgid "can't read `%s': %s\n" -msgstr "\"%s\" okunamyor: %s\n" - -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "bilgi: \"random_seed\" dosyas gncel deil\n" - -#: cipher/random.c:467 -#, c-format -msgid "can't create `%s': %s\n" -msgstr "\"%s\" oluturulamyor: %s\n" - -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "\"%s\" yazlamyor: %s\n" - -#: cipher/random.c:477 -#, c-format -msgid "can't close `%s': %s\n" -msgstr "\"%s\" kapatlamyor: %s\n" - -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "UYARI: kullanlan rasgele say reteci gvenli deil!!\n" - -#: cipher/random.c:724 -msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" -msgstr "" -"Rasgele say reteci kendi halinde alan\n" -"bir kukla - gvenilir bir RS deil!\n" -"\n" -"BU PROGRAMLA RETLM HBR VERY KULLANMAYIN!!\n" -"\n" - -#: cipher/rndlinux.c:134 -#, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Rasgele retilen baytlar yetersiz. Ltfen baz ilemler yaparak\n" -"daha fazla rasgele bayt toplayabilmesi iin iletim sistemine\n" -"yardmc olun! (%d bayt daha gerekiyor)\n" - -#: g10/g10.c:307 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Komutlar:\n" -" " - -#: g10/g10.c:309 -msgid "|[file]|make a signature" -msgstr "|[dosya]|bir imza yapar" - -#: g10/g10.c:310 -msgid "|[file]|make a clear text signature" -msgstr "|[dosya]|aka okunabilen bir imza yapar" - -#: g10/g10.c:311 -msgid "make a detached signature" -msgstr "bamsz bir imza yapar" - -#: g10/g10.c:312 -msgid "encrypt data" -msgstr "veriyi ifreler" - -#: g10/g10.c:313 -msgid "|[files]|encrypt files" -msgstr "|[dosyalar]|dosyalar ifrelenir" - -#: g10/g10.c:314 -msgid "encryption only with symmetric cipher" -msgstr "sadece simetrik ifre ile ifreler" - -#: g10/g10.c:315 -msgid "store only" -msgstr "sadece saklar" - -#: g10/g10.c:316 -msgid "decrypt data (default)" -msgstr "veri ifresini aar (ntanml)" - -#: g10/g10.c:317 -msgid "|[files]|decrypt files" -msgstr "|[dosyalar]|dosyalarn ifresi alr" - -#: g10/g10.c:318 -msgid "verify a signature" -msgstr "bir imzay dorular" - -#: g10/g10.c:320 -msgid "list keys" -msgstr "anahtarlar listeler" - -#: g10/g10.c:322 -msgid "list keys and signatures" -msgstr "anahtarlar ve imzalar listeler" - -#: g10/g10.c:323 -msgid "check key signatures" -msgstr "anahtar imzalarn kontrol eder" - -#: g10/g10.c:324 -msgid "list keys and fingerprints" -msgstr "anahtarlar ve parmak izlerini listeler" - -#: g10/g10.c:325 -msgid "list secret keys" -msgstr "gizli anahtarlar listeler" - -#: g10/g10.c:326 -msgid "generate a new key pair" -msgstr "yeni bir anahtar ifti retir" - -#: g10/g10.c:327 -msgid "remove keys from the public keyring" -msgstr "anahtarlar genel anahtar zincirinden siler" - -#: g10/g10.c:329 -msgid "remove keys from the secret keyring" -msgstr "anahtarlar gizli anahtar zincirinden siler" - -#: g10/g10.c:330 -msgid "sign a key" -msgstr "bir anahtar imzalar" - -#: g10/g10.c:331 -msgid "sign a key locally" -msgstr "bir anahtar yerel olarak imzalar" - -#: g10/g10.c:332 -msgid "sign a key non-revocably" -msgstr "bir anahtar iptal edilemez olarak imzalar" - -#: g10/g10.c:333 -msgid "sign a key locally and non-revocably" -msgstr "bir anahtar yerel ve iptal edilemez olarak imzalar" - -#: g10/g10.c:334 -msgid "sign or edit a key" -msgstr "bir anahtar dzenler ve imzalar" - -#: g10/g10.c:335 -msgid "generate a revocation certificate" -msgstr "bir yrrlkten kaldrma sertifikas retir" - -#: g10/g10.c:337 -msgid "export keys" -msgstr "anahtarlar gnderir" - -#: g10/g10.c:338 -msgid "export keys to a key server" -msgstr "anahtarlar bir anahtar sunucusuna gnderir" - -#: g10/g10.c:339 -msgid "import keys from a key server" -msgstr "anahtarlar bir anahtar sunucusundan indirir" - -#: g10/g10.c:341 -msgid "search for keys on a key server" -msgstr "bir anahtar sunucusunda anahtarlar arar" - -#: g10/g10.c:343 -msgid "update all keys from a keyserver" -msgstr "anahtarlar bir anahtar sunucusundan gnceller" - -#: g10/g10.c:347 -msgid "import/merge keys" -msgstr "anahtarlar indirir/kattrr" - -#: g10/g10.c:349 -msgid "list only the sequence of packets" -msgstr "sadece paketlerin silsilesini listeler" - -#: g10/g10.c:351 -msgid "export the ownertrust values" -msgstr "sahibiningvencesi deerlerini gnderir" - -#: g10/g10.c:353 -msgid "import ownertrust values" -msgstr "sahibiningvencesi deerlerini indirir" - -#: g10/g10.c:355 -msgid "update the trust database" -msgstr "gvence veritabann gnceller" - -#: g10/g10.c:357 -msgid "unattended trust database update" -msgstr "bakmsz gvence veritabannn gncellemesi" - -#: g10/g10.c:358 -msgid "fix a corrupted trust database" -msgstr "bozulan gvence veritabann onarr" - -#: g10/g10.c:359 -msgid "De-Armor a file or stdin" -msgstr "Bir dosya veya standart girdinin zrhn kaldrr" - -#: g10/g10.c:361 -msgid "En-Armor a file or stdin" -msgstr "Bir dosya veya standart girdiyi zrhlar" - -#: g10/g10.c:363 -msgid "|algo [files]|print message digests" -msgstr "|algo [dosyalar]|ileti zmlemelerini gsterir" - -#: g10/g10.c:367 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Seenekler:\n" -" " - -#: g10/g10.c:369 -msgid "create ascii armored output" -msgstr "ascii zrhl kt oluturur" - -#: g10/g10.c:371 -msgid "|NAME|encrypt for NAME" -msgstr "|SM|SM iin ifreleme yapar" - -#: g10/g10.c:374 -msgid "|NAME|use NAME as default recipient" -msgstr "|SM|ntanml alc olarak SM kullanlr" - -#: g10/g10.c:376 -msgid "use the default key as default recipient" -msgstr "ntanml alc olarak ntanml anahtar kullanlr" - -#: g10/g10.c:382 -msgid "use this user-id to sign or decrypt" -msgstr "imzalamak ya da ifre zmek iin bu kullanc kimlii kullanlr" - -#: g10/g10.c:383 -msgid "|N|set compress level N (0 disables)" -msgstr "|N|sktrma seviyesi N olarak ayarlanr (0 ise sktrma yaplmaz)" - -#: g10/g10.c:385 -msgid "use canonical text mode" -msgstr "kurall metin kipini kullanr" - -#: g10/g10.c:392 -msgid "use as output file" -msgstr "kt dosyas olarak kullanlr" - -#: g10/g10.c:393 -msgid "verbose" -msgstr "ok detayl" - -#: g10/g10.c:394 -msgid "be somewhat more quiet" -msgstr "daha az detayl" - -#: g10/g10.c:395 -msgid "don't use the terminal at all" -msgstr "terminali hi kullanma" - -#: g10/g10.c:396 -msgid "force v3 signatures" -msgstr "v3 imzalarna zorlar" - -#: g10/g10.c:397 -msgid "do not force v3 signatures" -msgstr "v3 imzalara zorlamaz" - -#: g10/g10.c:398 -msgid "force v4 key signatures" -msgstr "v4 imzalara zorlar" - -#: g10/g10.c:399 -msgid "do not force v4 key signatures" -msgstr "v4 imzalara zorlamaz" - -#: g10/g10.c:400 -msgid "always use a MDC for encryption" -msgstr "ifreleme iin daima bir MDC kullanlr" - -#: g10/g10.c:402 -msgid "never use a MDC for encryption" -msgstr "ifreleme iin asla bir MDC kullanlmaz" - -#: g10/g10.c:404 -msgid "do not make any changes" -msgstr "hibir deiiklik yapmaz" - -#: g10/g10.c:405 -msgid "prompt before overwriting" -msgstr "zerine yazmadan nce sorar" - -#: g10/g10.c:406 -msgid "use the gpg-agent" -msgstr "gpg-agent kullan" - -#: g10/g10.c:409 -msgid "batch mode: never ask" -msgstr "nceden belirlenmi ilemler kipi: hi sormaz" - -#: g10/g10.c:410 -msgid "assume yes on most questions" -msgstr "sorularn ounda cevap evet farzedilir" - -#: g10/g10.c:411 -msgid "assume no on most questions" -msgstr "sorularn ounda cevap hayr farzedilir" - -#: g10/g10.c:412 -msgid "add this keyring to the list of keyrings" -msgstr "bu anahtar zincirini anahtar zincirleri listesine ekler" - -#: g10/g10.c:413 -msgid "add this secret keyring to the list" -msgstr "bu gizli anahtar zincirini listeye ekler" - -#: g10/g10.c:414 -msgid "show which keyring a listed key is on" -msgstr "listedeki bir anahtarn hangi anahtar zincirinde olduunu gsterir" - -#: g10/g10.c:415 -msgid "|NAME|use NAME as default secret key" -msgstr "|SM|ntanml gizli anahtar olarak SM kullanlr" - -#: g10/g10.c:416 -msgid "|HOST|use this keyserver to lookup keys" -msgstr "|MAKNA|anahtarlar aramak iin bu anahtar sunucusu kullanlr" - -#: g10/g10.c:420 -msgid "|NAME|set terminal charset to NAME" -msgstr "|SM|terminal karakter setini SM olarak ayarlar" - -#: g10/g10.c:421 -msgid "read options from file" -msgstr "seenekleri dosyadan okur" - -#: g10/g10.c:425 -msgid "|FD|write status info to this FD" -msgstr "|FD|durum bilgisini bu FD'ye yazar" - -#: g10/g10.c:427 -msgid "|[file]|write status info to file" -msgstr "|[DOSYA]|durum bilgisini DOSYAya yazar" - -#: g10/g10.c:439 -msgid "|KEYID|ultimately trust this key" -msgstr "|ANHKML|bu anahtar son derece gvenli" - -#: g10/g10.c:440 -msgid "|FILE|load extension module FILE" -msgstr "|DOSYA|geniletme modl olarak DOSYA yklenir" - -#: g10/g10.c:441 -msgid "emulate the mode described in RFC1991" -msgstr "RFC1991 de aklanan kipi uygular" - -#: g10/g10.c:442 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "tm paket, ifre ve zmleme seeneklerini OpenPGP tarznda ayarlar" - -#: g10/g10.c:443 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" -msgstr "tm paket, ifre ve zmleme seeneklerini PGP 2.x'e gre ayarlar" - -#: g10/g10.c:449 -msgid "|N|use passphrase mode N" -msgstr "|N|anahtar parolas kipi olarak N kullanlr" - -#: g10/g10.c:451 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "" -"|SM|anahtar parolalar iin ileti zmleme algoritmas olarak SM " -"kullanlr" - -#: g10/g10.c:453 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|SM|anahtar parolalar iin ifre algoritmas olarak SM kullanlr" - -#: g10/g10.c:455 -msgid "|NAME|use cipher algorithm NAME" -msgstr "|SM|ifre algoritmas olarak SM kullanlr" - -#: g10/g10.c:456 -msgid "|NAME|use message digest algorithm NAME" -msgstr "|SM|zmleme algoritmas olarak SM kullanlr" - -#: g10/g10.c:458 -msgid "|N|use compress algorithm N" -msgstr "|N|sktrma algoritmas olarak N kullanlr" - -#: g10/g10.c:459 -msgid "throw keyid field of encrypted packets" -msgstr "ifreli paketlerin anahtar-kimlik alanlarn atar" - -#: g10/g10.c:460 -msgid "Show Photo IDs" -msgstr "Foto kimliklerini gsterir" - -#: g10/g10.c:461 -msgid "Don't show Photo IDs" -msgstr "Foto kimliklerini gstermez" - -#: g10/g10.c:462 -msgid "Set command line to view Photo IDs" -msgstr "Komut satrn foto kimliklerini gstermeye ayarlar" - -#: g10/g10.c:468 -msgid "" -"@\n" -"(See the man page for a complete listing of all commands and options)\n" -msgstr "" -"@\n" -"(Tm komut ve seeneklerin komple listesi iin man sayfalarna bakn)\n" - -#: g10/g10.c:471 -msgid "" -"@\n" -"Examples:\n" -"\n" -" -se -r Bob [file] sign and encrypt for user Bob\n" -" --clearsign [file] make a clear text signature\n" -" --detach-sign [file] make a detached signature\n" -" --list-keys [names] show keys\n" -" --fingerprint [names] show fingerprints\n" -msgstr "" -"@\n" -"rnekler:\n" -"\n" -" -se -r Ali [dosya] kullanc Ali iin imzalar ve ifreler\n" -" --clearsign [dosya] aka okunabilir bir imza yapar\n" -" --detach-sign [dosya] bamsz bir imza yapar\n" -" --list-keys [isimler] anahtarlar listeler\n" -" --fingerprint [isimler] parmak izlerini gsterir\n" - -#: g10/g10.c:623 -msgid "Please report bugs to .\n" -msgstr "Yazlm hatalarn ltfen adresine bildirin.\n" - -#: g10/g10.c:627 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Kullanm: gpg [seenekler] [dosyalar] (yardm iin -h)" - -#: g10/g10.c:630 -msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" -"default operation depends on the input data\n" -msgstr "" -"Yazl: gpg [seenekler] [dosyalar]\n" -"imzalama, kontrol, ifreleme veya zme\n" -"ntanml ilem girilen veriye bamldr\n" - -#: g10/g10.c:641 -msgid "" -"\n" -"Supported algorithms:\n" -msgstr "" -"\n" -"Desteklenen algoritmalar:\n" - -#: g10/g10.c:745 -msgid "usage: gpg [options] " -msgstr "kullanm: gpg [seenekler] " - -#: g10/g10.c:802 -msgid "conflicting commands\n" -msgstr "elien komutlar\n" - -#: g10/g10.c:820 -#, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "grup tanm \"%s\" iinde = iareti yok\n" - -#: g10/g10.c:983 -#, c-format -msgid "WARNING: unsafe ownership on %s \"%s\"\n" -msgstr "UYARI: %s \"%s\" de gvensiz sahiplik\n" - -#: g10/g10.c:986 -#, c-format -msgid "WARNING: unsafe permissions on %s \"%s\"\n" -msgstr "UYARI: %s \"%s\" de gvensiz izinler\n" - -#: g10/g10.c:989 -#, c-format -msgid "WARNING: unsafe enclosing directory ownership on %s \"%s\"\n" -msgstr "UYARI: %s \"%s\" de gvensiz ilitirilen dizin sahiplii\n" - -#: g10/g10.c:993 -#, c-format -msgid "WARNING: unsafe enclosing directory permissions on %s \"%s\"\n" -msgstr "UYARI: %s \"%s\" de gvensiz ilitirilen dizin izinleri\n" - -#: g10/g10.c:1168 -#, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "BLG: eski ntanml seenekler dosyas `%s' yoksayld\n" - -#: g10/g10.c:1204 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "BLG: `%s' ntanml seenek dosyas yok\n" - -#: g10/g10.c:1208 -#, c-format -msgid "option file `%s': %s\n" -msgstr "seenek dosyas \"%s\": %s\n" - -#: g10/g10.c:1215 -#, c-format -msgid "reading options from `%s'\n" -msgstr "\"%s\"den seenekler okunuyor\n" - -#: g10/g10.c:1390 -#, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "ifre uzants \"%s\" gvensiz izinlerden dolay yklenmedi\n" - -#: g10/g10.c:1523 -#, c-format -msgid "%s is not a valid character set\n" -msgstr "%s geerli bir karakter seti deil\n" - -#: g10/g10.c:1541 -msgid "could not parse keyserver URI\n" -msgstr "anahtar sunucusunun adresi zmlenemedi\n" - -#: g10/g10.c:1550 -#, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s:%d: geersiz iselletirme seenekleri\n" - -#: g10/g10.c:1553 -msgid "invalid import options\n" -msgstr "iselletirme seenekleri geersiz\n" - -#: g10/g10.c:1560 -#, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s:%d geersiz dsallatrma seenekleri\n" - -#: g10/g10.c:1563 -msgid "invalid export options\n" -msgstr "dsallatrma seenekleri geersiz\n" - -#: g10/g10.c:1569 -#, c-format -msgid "unable to set exec-path to %s\n" -msgstr "altrlabilirlerin patikas %s yaplamyor\n" - -#: g10/g10.c:1688 -msgid "WARNING: program may create a core file!\n" -msgstr "UYARI: program bir \"core\" dosyas oluturabilir!\n" - -#: g10/g10.c:1692 -#, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "UYARI: %s %s'i ayor\n" - -#: g10/g10.c:1699 g10/g10.c:1710 -#, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "BLG: %s normal kullanm iin deil!\n" - -#: g10/g10.c:1701 g10/g10.c:1721 -#, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s ile %s birlikte kullanlmaz!\n" - -#: g10/g10.c:1704 -#, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s, %s ile etkisiz olur!\n" - -#: g10/g10.c:1731 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" -msgstr "--pgp2 kipinde sadece ayrk veya sade imzalar yapabilirsiniz\n" - -#: g10/g10.c:1737 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" -msgstr "--pgp2 kipinde ayn anda hem imzalama hem de ifreleme yapamazsnz\n" - -#: g10/g10.c:1743 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" -msgstr "--pgp2 ile alrken veri yolu yerine dosyalar kullanmalsnz.\n" - -#: g10/g10.c:1756 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" -msgstr "--pgp2 kipinde ileti ifrelemesi IDEA ifresi gerektirir\n" - -#: g10/encode.c:408 g10/encode.c:458 g10/encode.c:707 g10/g10.c:1770 -#: g10/sign.c:646 g10/sign.c:878 -#, c-format -msgid "this message may not be usable by %s\n" -msgstr "bu ileti %s tarafndan kullanlamayabilir\n" - -#: g10/g10.c:1818 g10/g10.c:1836 -msgid "selected cipher algorithm is invalid\n" -msgstr "seilen ifre algoritmas geersiz\n" - -#: g10/g10.c:1824 g10/g10.c:1842 -msgid "selected digest algorithm is invalid\n" -msgstr "seilen zmleme algoritmas geersiz\n" - -#: g10/g10.c:1830 -msgid "selected certification digest algorithm is invalid\n" -msgstr "seilen sertifikalama zmleme algoritmas geersiz\n" - -#: g10/g10.c:1845 -#, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "sktrma algoritmas %d..%d aralnda olmal\n" - -#: g10/g10.c:1847 -msgid "completes-needed must be greater than 0\n" -msgstr "\"completes-needed\" 0 dan byk olmal\n" - -#: g10/g10.c:1849 -msgid "marginals-needed must be greater than 1\n" -msgstr "\"marginals-needed\" 1 den byk olmal\n" - -#: g10/g10.c:1851 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "\"max-cert-depth\" 1 ile 255 arasnda olmal\n" - -#: g10/g10.c:1854 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "BLG: basit S2K kipi (0) kesinlikle tavsiye edilmez\n" - -#: g10/g10.c:1858 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "S2K kipi geersiz; 0, 1 veya 3 olmal\n" - -#: g10/g10.c:1862 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "ntanml denetim seviyesi geersiz; 0, 1, 2, ya da 3 olabilir\n" - -#: g10/g10.c:1868 -msgid "invalid default preferences\n" -msgstr "ntanml tercihler geersiz\n" - -#: g10/g10.c:1876 -msgid "invalid personal cipher preferences\n" -msgstr "kiisel ifre tercihleri geersiz\n" - -#: g10/g10.c:1880 -msgid "invalid personal digest preferences\n" -msgstr "kiisel zmleme tercihleri geersiz\n" - -#: g10/g10.c:1884 -msgid "invalid personal compress preferences\n" -msgstr "kiisel sktrma tercihleri geersiz\n" - -#: g10/g10.c:1977 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "\"TrustDB\" gvence veritaban balang aamasnda baarsz: %s\n" - -#: g10/g10.c:1987 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "UYARI: alclar (-r) genel anahtar ifrelemesi kullanlmadan belirtilmi\n" - -#: g10/g10.c:1997 -msgid "--store [filename]" -msgstr "--store [dosyaismi]" - -#: g10/g10.c:2004 -msgid "--symmetric [filename]" -msgstr "--symmetric [dosyaismi]" - -#: g10/g10.c:2012 -msgid "--encrypt [filename]" -msgstr "--encrypt [dosyaismi]" - -#: g10/g10.c:2029 -msgid "--sign [filename]" -msgstr "--sign [dosyaismi]" - -#: g10/g10.c:2042 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [dosyaismi]" - -#: g10/g10.c:2056 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [DOSYA]" - -#: g10/g10.c:2065 -msgid "--clearsign [filename]" -msgstr "--clearsign [dosyaismi]" - -#: g10/g10.c:2083 -msgid "--decrypt [filename]" -msgstr "--decrypt [dosyaismi]" - -#: g10/g10.c:2094 -msgid "--sign-key user-id" -msgstr "--sign-key kullanc-kimlii" - -#: g10/g10.c:2102 -msgid "--lsign-key user-id" -msgstr "--lsign-key kullanc-kimlii" - -#: g10/g10.c:2110 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key KULL-KML" - -#: g10/g10.c:2118 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key KULL-KML" - -#: g10/g10.c:2126 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key kullanc-kimlii [komutlar]" - -#: g10/encode.c:416 g10/g10.c:2182 g10/sign.c:789 -#, c-format -msgid "can't open %s: %s\n" -msgstr "%s alamad: %s\n" - -#: g10/g10.c:2197 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [kullanc-kimlii] [anahtar-zinciri]" - -#: g10/g10.c:2289 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "zrhn kaldrlmas baarsz: %s\n" - -#: g10/g10.c:2297 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "zrhlama baarsz: %s\n" - -#: g10/g10.c:2384 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "`%s' hash algoritmas geersiz\n" - -#: g10/g10.c:2470 -msgid "[filename]" -msgstr "[dosyaismi]" - -#: g10/g10.c:2474 -msgid "Go ahead and type your message ...\n" -msgstr "letinizi yazn ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2477 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "`%s' alamad\n" - -#: g10/g10.c:2691 -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"bir niteleme ismi sadece yazlabilir karakterler ve boluklar ierebilir ve " -"bir '=' ile biter.\n" - -#: g10/g10.c:2700 -msgid "a notation value must not use any control characters\n" -msgstr "bir niteleme deerinde kontrol karakterleri kullanlamaz\n" - -#: g10/g10.c:2737 -msgid "the given certification policy URL is invalid\n" -msgstr "belirtilen sertifika gvence adresi geersiz\n" - -#: g10/g10.c:2739 -msgid "the given signature policy URL is invalid\n" -msgstr "belirtilen imza gvence adresi geersiz\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "zrh: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "zrh bal geersiz: " - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "zrh bal: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "aka okunabilen imza bal geersiz\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "aka okunabilen imzalar dahil edildi\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "araizgisi escape'l satr geersiz: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "beklenmeyen zrh: " - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "geersiz radix64 karakteri %02x atland\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "dosya sonu belirsiz (CRC yok)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "dosya sonu belirsiz (CRC iinde)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "CRC bozulmu\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "CRC hatas; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "dosya sonu belirsiz (kuyruk iinde)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "kuyruk satrnda hata\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "geerli OpenPGP verisi yok\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "geersiz zrh: satr %d karakterden uzun\n" - -#: g10/armor.c:1066 -msgid "quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"zrh iinde uluslararas karakterler - byk olaslkla hatal bir e-posta " -"sunucusu kullanlm\n" - -#: g10/pkclist.c:61 -msgid "No reason specified" -msgstr "Belirtilmi bir neden yok" - -#: g10/pkclist.c:63 -msgid "Key is superseded" -msgstr "Anahtarn yerine bakas konulmu ve iptal edilmitir" - -#: g10/pkclist.c:65 -msgid "Key has been compromised" -msgstr "Anahtar tehlikede" - -#: g10/pkclist.c:67 -msgid "Key is no longer used" -msgstr "Anahtar artk kullanlmayacak" - -#: g10/pkclist.c:69 -msgid "User ID is no longer valid" -msgstr "Kullanc kimlii artk geersiz" - -#: g10/pkclist.c:73 -msgid "reason for revocation: " -msgstr "yrrlkten kaldrma sebebi: " - -#: g10/pkclist.c:90 -msgid "revocation comment: " -msgstr "yrrlkten kaldrma aklamas: " - -#. a string with valid answers -#: g10/pkclist.c:252 -msgid "iImMqQsS" -msgstr "bBmMaAkK" - -#: g10/pkclist.c:258 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Gven derecesi belirtilmemi:\n" -"%4u%c/%08lX %s \"" - -#: g10/pkclist.c:270 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Dier kullanclar anahtarlarn dorulayacak\n" -"bu kullancnn gven derecesine ltfen karar verin.\n" -"(pasportuna m bakarsnz yoksa farkl kaynaklardan\n" -"parmakizlerini mi kontrol edersiniz...)? kararnz verin\n" - -#: g10/pkclist.c:273 -#, c-format -msgid " %d = Don't know\n" -msgstr " %d = bilmiyorum\n" - -#: g10/pkclist.c:274 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = gvence vermem\n" - -#: g10/pkclist.c:275 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = yle byle gveniyorum\n" - -#: g10/pkclist.c:276 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Tamamen gveniyorum\n" - -#: g10/pkclist.c:278 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Son derece gveniyorum\n" - -#. not yet implemented -#: g10/pkclist.c:281 -msgid " i = please show me more information\n" -msgstr " b = Daha fazla bilgi gerekli\n" - -#: g10/pkclist.c:284 -msgid " m = back to the main menu\n" -msgstr " m = ana menye dn\n" - -#: g10/pkclist.c:287 -msgid " s = skip this key\n" -msgstr " a = bu anahtar atla\n" - -#: g10/pkclist.c:288 -msgid " q = quit\n" -msgstr " k = k\n" - -#: g10/pkclist.c:295 -msgid "Your decision? " -msgstr "Kararnz? " - -#: g10/pkclist.c:316 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Bu anahtara gerekten en yksek gven derecesini vermek istiyor musunuz?" - -#: g10/pkclist.c:330 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Son derece gvenli bir anahtarla sonulanan sertifikalar:\n" - -#: g10/pkclist.c:405 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "anahtar %08lX: anahtar yrrlkten kaldrlmt!\n" - -#: g10/pkclist.c:412 g10/pkclist.c:424 g10/pkclist.c:518 -msgid "Use this key anyway? " -msgstr "Bu anahtar yine de kullanlsn m? " - -#: g10/pkclist.c:417 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "anahtar %08lX: yardmc anahtar yrrlkten kaldrlmt!\n" - -#: g10/pkclist.c:438 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: anahtarn kullanm sresi dolmu\n" - -#: g10/pkclist.c:448 -#, c-format -msgid "%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "%08lX: Bu anahtarn gerekten sahibine ait olduuna dair bir belirti yok\n" - -#: g10/pkclist.c:454 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Bu anahtara gven-mi-yoruz\n" - -#: g10/pkclist.c:460 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Bu anahtarn gerekten sahibine ait olup olmadndan emin\n" -"olunamad fakat yine de kabul edildi.\n" - -#: g10/pkclist.c:466 -msgid "This key probably belongs to the owner\n" -msgstr "Bu anahtarn sahibine ait olduu umuluyor\n" - -#: g10/pkclist.c:471 -msgid "This key belongs to us\n" -msgstr "Bu anahtar bizim\n" - -#: g10/pkclist.c:513 -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Bu anahtarn kullanc kimliinde ismi belirtilen ahsa ait\n" -"olduu kesin DEL. *Gerekten* ne yaptnz biliyorsanz,\n" -"sonraki soruya da evet cevab verebilirsiniz.\n" - -#: g10/pkclist.c:527 g10/pkclist.c:549 -msgid "WARNING: Using untrusted key!\n" -msgstr "UYARI: Gven derecesiz anahtar kullanlyor!\n" - -#: g10/pkclist.c:568 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "UYARI: Bu anahtar sahibi tarafndan yrrlkten kaldrlmt!\n" - -#: g10/pkclist.c:569 -msgid " This could mean that the signature is forgery.\n" -msgstr " Bu imza sahte anlamna gelebilir.\n" - -#: g10/pkclist.c:575 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "UYARI: Bu yardmc anahtar sahibi tarafndan yrrlkten kaldrlmt!\n" - -#: g10/pkclist.c:580 -msgid "Note: This key has been disabled.\n" -msgstr "Bilgi: Bu anahtar iptal edildi.\n" - -#: g10/pkclist.c:585 -msgid "Note: This key has expired!\n" -msgstr "Bilgi: Bu anahtarn kullanm sresi dolmutu!\n" - -#: g10/pkclist.c:596 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "UYARI: Bu anahtar gven dereceli bir imza ile sertifikalanmam!\n" - -#: g10/pkclist.c:598 -msgid " There is no indication that the signature belongs to the owner.\n" -msgstr " Bu imzann sahibine ait olduuna dair bir belirti yok.\n" - -#: g10/pkclist.c:606 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "UYARI: Bu anahtara gven-mi-yoruz!\n" - -#: g10/pkclist.c:607 -msgid " The signature is probably a FORGERY.\n" -msgstr " Bu imza SAHTE olabilir.\n" - -#: g10/pkclist.c:615 -msgid "WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"UYARI: Bu anahtar yeterli gven derecesine sahip imzalarla " -"sertifikalanmam!\n" - -#: g10/pkclist.c:617 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr " Bu imzann sahibine ait olduu kesin deil.\n" - -#: g10/pkclist.c:770 g10/pkclist.c:794 g10/pkclist.c:946 g10/pkclist.c:1006 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: atland: %s\n" - -#: g10/pkclist.c:780 g10/pkclist.c:978 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: atland: genel anahtar zaten var\n" - -#: g10/pkclist.c:811 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "Bir kullanc kimlii belirtmediniz. (\"-r\" kullanabilirsiniz)\n" - -#: g10/pkclist.c:824 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Kullanc kimliini girin. Bo bir satr ilemi sonlandrr:" - -#: g10/pkclist.c:840 -msgid "No such user ID.\n" -msgstr "Byle bir kullanc kimlii yok.\n" - -#: g10/pkclist.c:845 g10/pkclist.c:921 -msgid "skipped: public key already set as default recipient\n" -msgstr "atland: genel anahtar zaten ntanml alc olarak ayarlanm\n" - -#: g10/pkclist.c:863 -msgid "Public key is disabled.\n" -msgstr "Genel anahtar iptal edildi.\n" - -#: g10/pkclist.c:870 -msgid "skipped: public key already set\n" -msgstr "atland: genel anahtar zaten belirtilmi\n" - -#: g10/pkclist.c:913 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "ntanml alc `%s' bilinmiyor\n" - -#: g10/pkclist.c:958 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: atland: genel anahtar iptal edildi\n" - -#: g10/pkclist.c:1013 -msgid "no valid addressees\n" -msgstr "geerli adresler yok\n" - -#: g10/keygen.c:182 -#, c-format -msgid "preference %c%lu is not valid\n" -msgstr "%c%lu tercihi geersiz\n" - -#: g10/keygen.c:189 -#, c-format -msgid "preference %c%lu duplicated\n" -msgstr "%c%lu tercihi yinelendi\n" - -#: g10/keygen.c:194 -#, c-format -msgid "too many `%c' preferences\n" -msgstr "`%c' tercih ok fazla\n" - -#: g10/keygen.c:264 -msgid "invalid character in preference string\n" -msgstr "tercih dizgesindeki karakter geersiz\n" - -#: g10/keygen.c:524 -msgid "writing direct signature\n" -msgstr "dorudan imza yazlyor\n" - -#: g10/keygen.c:563 -msgid "writing self signature\n" -msgstr "z-imza yazlyor\n" - -#: g10/keygen.c:607 -msgid "writing key binding signature\n" -msgstr "anahtar garantileyen imzay yazyor\n" - -#: g10/keygen.c:661 g10/keygen.c:745 g10/keygen.c:836 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "anahtar uzunluu geersiz; %u bit kullanlyor\n" - -#: g10/keygen.c:666 g10/keygen.c:750 g10/keygen.c:841 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "anahtar uzunluu %u bite yuvarland\n" - -#: g10/keygen.c:941 -msgid "Please select what kind of key you want:\n" -msgstr "Ltfen istediiniz anahtar seiniz:\n" - -#: g10/keygen.c:943 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA ve ElGamal (ntanml)\n" - -#: g10/keygen.c:944 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (yalnz imzalamak iin)\n" - -#: g10/keygen.c:946 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (yalnz ifrelemek iin)\n" - -#: g10/keygen.c:948 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (imzalamak ve ifrelemek iin)\n" - -#: g10/keygen.c:949 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (sadece imzalamak iin)\n" - -#: g10/keygen.c:951 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (sadece ifrelemek iin)\n" - -#: g10/keygen.c:953 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (imzalamak ve ifrelemek iin)\n" - -#: g10/keyedit.c:576 g10/keygen.c:956 -msgid "Your selection? " -msgstr "Seiminiz? " - -#: g10/keygen.c:966 g10/keygen.c:984 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "Bu algoritmann kullanm uygun deil - Yine de oluturulsun mu?" - -#: g10/keyedit.c:589 g10/keygen.c:998 -msgid "Invalid selection.\n" -msgstr "Seim geersiz.\n" - -#: g10/keygen.c:1011 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Yeni bir %s anahtar ifti retmek zeresiniz.\n" -" en kk anahtar uzunluu: 768 bit\n" -" ntanml anahtar uzunluu: 1024 bit\n" -" nerilebilecek en byk anahtar uzunluu: 2048 bit\n" - -#: g10/keygen.c:1020 -msgid "What keysize do you want? (1024) " -msgstr "stediiniz anahtar uzunluu nedir? (1024) " - -#: g10/keygen.c:1025 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA anahtarnn uzunluu 512 ile 1024 bit arasnda olabilir\n" - -#: g10/keygen.c:1027 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "anahtar uzunluu ok kk; RSA anahtar iin en kk uzunluk: 1024 bit\n" - -#: g10/keygen.c:1030 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "anahtar uzunluu ok kk; en kk anahtar uzunluu 768 bit'tir.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1041 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "anahtar uzunluu ok byk; izin verilen en byk deer: %d bit\n" - -#: g10/keygen.c:1046 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Hesaplama EPEYCE UZUN zaman alacandan anahtar uzunluklarnda\n" -"2048 bitten fazlas tavsiye edilmez.\n" - -#: g10/keygen.c:1049 -msgid "Are you sure that you want this keysize? " -msgstr "Bu anahtar uzunluunu istediinizden emin misiniz? " - -#: g10/keygen.c:1050 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Tamam, ama saldrlara ok duyarl olan monitr ve klavye nmlarndan " -"kendinizi uzak tutun! (ne demekse...)\n" - -#: g10/keygen.c:1059 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "stenen anahtar uzunluu: %u bit\n" - -#: g10/keygen.c:1062 g10/keygen.c:1066 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "%u bite yuvarland\n" - -#: g10/keygen.c:1117 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" = key expires in n days\n" -" w = key expires in n weeks\n" -" m = key expires in n months\n" -" y = key expires in n years\n" -msgstr "" -"Ltfen anahtarn ne kadar sreyle geerli olacan belirtin.\n" -" 0 = anahtar sresiz geerli\n" -" = anahtar n gn geerli\n" -" w = anahtar n hafta geerli\n" -" m = anahtar n ay geerli\n" -" y = anahtar n yl geerli\n" - -#: g10/keygen.c:1126 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" = signature expires in n days\n" -" w = signature expires in n weeks\n" -" m = signature expires in n months\n" -" y = signature expires in n years\n" -msgstr "" -"Ltfen imzannn ne kadar sreyle geerli olacan belirtin.\n" -" 0 = imza sresiz geerli\n" -" = imza n gn geerli\n" -" w = imza n hafta geerli\n" -" m = imza n ay geerli\n" -" y = imza n yl geerli\n" - -#: g10/keygen.c:1148 -msgid "Key is valid for? (0) " -msgstr "Anahtar ne kadar geerli olacak? (0) " - -#: g10/keygen.c:1150 -msgid "Signature is valid for? (0) " -msgstr "mza ne kadar geerli olacak? (0) " - -#: g10/keygen.c:1155 -msgid "invalid value\n" -msgstr "deer hatal\n" - -#: g10/keygen.c:1160 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s hep geerli olacak\n" - -#. print the date when the key expires -#: g10/keygen.c:1167 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s %s sonra geersiz olacak\n" - -#: g10/keygen.c:1173 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Sisteminiz 2038 ylndan sonraki tarihleri gsteremiyor.\n" -"Ama emin olun ki 2106 ylna kadar elde edilebilecek.\n" - -#: g10/keygen.c:1178 -msgid "Is this correct (y/n)? " -msgstr "Bu doru mu? (e/h)? " - -#: g10/keygen.c:1221 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) \"\n" -"\n" -msgstr "" -"\n" -"Anahtarnzn size ait olduunu belirten bir Kullanc-Kimlii olmal;\n" -"Kullanc-Kimlii, Gerek sminiz, Bir nbilgi ve e-Posta Adresiniz\n" -"alanlarnn bir birleiminden oluur. rnein:\n" -"\t\"Fatih Sultan Mehmed (Padisah) \"\n" -"\n" - -#: g10/keygen.c:1233 -msgid "Real name: " -msgstr "Adnz ve Soyadnz: " - -#: g10/keygen.c:1241 -msgid "Invalid character in name\n" -msgstr "Ad ve soyadnzda geersiz karakter var\n" - -#: g10/keygen.c:1243 -msgid "Name may not start with a digit\n" -msgstr "Ad ve soyadnz bir rakamla balamamal\n" - -#: g10/keygen.c:1245 -msgid "Name must be at least 5 characters long\n" -msgstr "Ad ve soyadnz en az 5 harfli olmal\n" - -#: g10/keygen.c:1253 -msgid "Email address: " -msgstr "E-posta adresiniz: " - -#: g10/keygen.c:1264 -msgid "Not a valid email address\n" -msgstr "geerli bir E-posta adresi deil\n" - -#: g10/keygen.c:1272 -msgid "Comment: " -msgstr "nbilgi: " - -#: g10/keygen.c:1278 -msgid "Invalid character in comment\n" -msgstr "nbilgi alannda geersiz karakter var\n" - -#: g10/keygen.c:1301 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "`%s' karakter kmesini kullanyorsunuz.\n" - -#: g10/keygen.c:1307 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Setiiniz KULLANICI-KML:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1311 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Ltfen E-posta adresinizi Ad ve Soyad veya Aklama alan iine koymayn\n" - -#: g10/keygen.c:1316 -msgid "NnCcEeOoQq" -msgstr "AaYyEeTtKk" - -#: g10/keygen.c:1326 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "(A)d ve Soyad, (Y)orum, (E)posta alanlarn deitir ya da (k)? " - -#: g10/keygen.c:1327 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "(A)d ve Soyad, (Y)orum, (E)posta alanlarn deitir ya da (T)amam/(k)? " - -#: g10/keygen.c:1346 -msgid "Please correct the error first\n" -msgstr "Ltfen nce hatay dzeltin\n" - -#: g10/keygen.c:1385 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Gizli anahtarnz korumak iin bir Anahtar Parolanz olmal.\n" -"\n" - -#: g10/keyedit.c:787 g10/keygen.c:1393 -msgid "passphrase not correctly repeated; try again" -msgstr "" -"ikinci kez yazdnz anahtar parolas ilkiyle ayn deil; ilem " -"tekrarlanacak" - -#: g10/keygen.c:1394 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1400 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Bir anahtar parolas istemediniz - bu *kt* bir fikir!\n" -"Nasl isterseniz. Anahtar parolanz bu program \"--edit-key\"\n" -"seenei ile kullanarak her zaman deitirebilirsiniz.\n" -"\n" - -#: g10/keygen.c:1421 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Bir miktar rasgele bayt retilmesi gerekiyor. lk retim srasnda biraz\n" -"hareket (klavyeyi kullanmak, fareyi hareket ettirmek, disklerden " -"yararlanmak)\n" -"iyi olacaktr; bu yeterli rasgele bayt kazanmak iin rasgele say\n" -"retecine yardmc olur. \n" - -#: g10/keygen.c:1985 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "DSA anahtar ifti 1024 bit olacak.\n" - -#: g10/keygen.c:2039 -msgid "Key generation canceled.\n" -msgstr "Anahtar retimi durduruldu.\n" - -#: g10/keygen.c:2128 g10/keygen.c:2216 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "genel anahtar `%s'e yazyor\n" - -#: g10/keygen.c:2129 g10/keygen.c:2218 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "gizli anahtar `%s'e yazyor\n" - -#: g10/keygen.c:2205 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "yazlabilir bir genel anahtar zinciri yok: %s\n" - -#: g10/keygen.c:2211 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "yazlabilir bir gizli anahtar zinciri yok: %s\n" - -#: g10/keygen.c:2225 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "`%s' genel anahtar zincirine yazlrken hata olutu: %s\n" - -#: g10/keygen.c:2232 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "`%s' gixli anahtar zincirine yazlrken hata olutu: %s\n" - -#: g10/keygen.c:2252 -msgid "public and secret key created and signed.\n" -msgstr "genel ve gizli anahtar retildi ve imzaland.\n" - -#: g10/keygen.c:2253 -msgid "key marked as ultimately trusted.\n" -msgstr "anahtar son derece gvenli olarak imlendi.\n" - -#: g10/keygen.c:2264 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Bu anahtar ifreleme iin kullanlamaz. ifreleme iin ikinci bir anahtar\n" -"\"--edit-key\" seeneini kullanarak retebilirsiniz.\n" - -#: g10/keygen.c:2276 g10/keygen.c:2384 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Anahtar retimi baarszla urad: %s\n" - -#: g10/keygen.c:2320 g10/sign.c:257 -#, c-format -msgid "key has been created %lu second in future (time warp or clock problem)\n" -msgstr "anahtar %lu saniye sonra retilmi (zaman sapmas veya saat problemi)\n" - -#: g10/keygen.c:2322 g10/sign.c:259 -#, c-format -msgid "key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"anahtar bundan %lu saniye sonra retilmi (zaman sapmas veya saat " -"problemi)\n" - -#: g10/keygen.c:2331 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "BLG: v3 anahtarlar iin yardmc anahtar retimi OpenPGP uyumlu deildir\n" - -#: g10/keygen.c:2360 -msgid "Really create? " -msgstr "Gerekten oluturulsun mu? " - -#: g10/decrypt.c:92 g10/encode.c:762 -msgid "--output doesn't work for this command\n" -msgstr "--output seenei bu komutla almaz\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: alamyor: %s\n" - -#: g10/encode.c:205 g10/sign.c:1035 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "anahtar parolas oluturulurken hata: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "S2K kipi sayesinde bir simetrik ESK paketi kullanlamyor\n" - -#: g10/encode.c:229 g10/encode.c:486 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' zaten sktrlm\n" - -#: g10/encode.c:295 g10/encode.c:520 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: UYARI: dosya bo\n" - -#: g10/encode.c:406 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"--pgp2 kipinde sadece 2048 bitlik RSA anahtarlar ile ifreleme " -"yapabilirsiniz\n" - -#: g10/encode.c:422 -#, c-format -msgid "reading from `%s'\n" -msgstr "`%s'den okunuyor\n" - -#: g10/encode.c:456 -msgid "unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "tm anahtarlar ifrelemek iin IDEA ifresi kullanlamaz.\n" - -#: g10/encode.c:467 g10/encode.c:644 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "alcnn tercihleriyle elien %s (%d) simetrik ifre kullanm zorlanyor\n" - -#: g10/encode.c:558 g10/sign.c:758 -#, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "alcnn tercihleriyle elien %s (%d) sktrma algoritmas kullanm zorlanyor\n" - -#: g10/encode.c:703 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "%2$s kipindeyken %1$s kullanlamaz.\n" - -#: g10/encode.c:735 -#, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s \"%s\" iin ifrelendi\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2289 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "anahtar `%s' yok: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "anahtar blou okunurken hata: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "%08lX anahtar: bir RFC2440 anahtar deil - atland\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "%08lX anahtar: korunmam - atland\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "%08lX anahtar: PGP 2.x tarz bir anahtar - atland\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "UYARI: hibir ey dar aktarlmad\n" - -#: g10/getkey.c:151 -msgid "too many entries in pk cache - disabled\n" -msgstr "pk belleinde ok fazla girdi - iptal edildi\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:187 g10/getkey.c:2393 -msgid "[User id not found]" -msgstr "[Kullanc kimlii bulunamad]" - -#: g10/getkey.c:1438 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Geersiz %08lX anahtar --allow-non-selfsigned-uid kullanlarak geerli " -"oldu\n" - -#: g10/getkey.c:2109 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "yardmc anahtar %08lX, asl anahtar %08lX yerine kullanlyor\n" - -#: g10/getkey.c:2156 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "%08lX anahtar: genel anahtarsz gizli anahtar - atland\n" - -#: g10/import.c:258 -#, c-format -msgid "skipping block of type %d\n" -msgstr "%d. tr blok atland\n" - -#: g10/import.c:267 -#, c-format -msgid "%lu keys so far processed\n" -msgstr "u ana kadar herey yolunda giderek %lu anahtar ilenmi\n" - -#: g10/import.c:272 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "\"%s\" okunurken hata: %s\n" - -#: g10/import.c:284 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "lenmi toplam miktar: %lu\n" - -#: g10/import.c:286 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " yeni anahtarlar atland: %lu\n" - -#: g10/import.c:289 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " kullanc kimliksiz: %lu\n" - -#: g10/import.c:291 -#, c-format -msgid " imported: %lu" -msgstr " indirildi: %lu" - -#: g10/import.c:297 -#, c-format -msgid " unchanged: %lu\n" -msgstr " deimedi: %lu\n" - -#: g10/import.c:299 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " yeni kullanc kimlii: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " yeni yardmc anahtarlar: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " new signatures: %lu\n" -msgstr " yeni imzalar: %lu\n" - -#: g10/import.c:305 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " yeni anahtar iptalleri: %lu\n" - -#: g10/import.c:307 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " gizli anahtarlar okundu: %lu\n" - -#: g10/import.c:309 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " gizli anahtarlar indirildi: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " gizli anahtarlar deimedi: %lu\n" - -#: g10/import.c:313 -#, c-format -msgid " not imported: %lu\n" -msgstr " alnamad: %lu\n" - -#: g10/import.c:581 g10/import.c:830 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "anahtar %08lX: kullanc kimlii yok\n" - -#: g10/import.c:597 -#, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "anahtar %08lX: HKP yardmc anahtar bozulmas giderildi\n" - -#: g10/import.c:612 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "anahtar %08lX: z-imzal olmayan kullanc kimlii '%s' kabul edildi\n" - -#: g10/import.c:619 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "anahtar %08lX: kullanc kimlii geersiz\n" - -#: g10/import.c:621 -msgid "this may be caused by a missing self-signature\n" -msgstr "bu kayp bir z-imza yznden meydana gelebilir\n" - -#: g10/import.c:631 g10/import.c:903 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "anahtar %08lX: genel anahtar bulunamad: %s\n" - -#: g10/import.c:636 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "anahtar %08lX: yeni anahtar - atland\n" - -#: g10/import.c:646 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "yazlabilir bir anahtar zinciri yok: %s\n" - -#: g10/import.c:651 g10/openfile.c:244 g10/sign.c:670 g10/sign.c:897 -#, c-format -msgid "writing to `%s'\n" -msgstr "\"%s\"e yazyor\n" - -#: g10/import.c:654 g10/import.c:731 g10/import.c:850 g10/import.c:963 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "\"%s\" anahtar zincirine yazarken hata olutu: %s\n" - -#: g10/import.c:663 -#, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "anahtar %08lX: genel anahtar \"%s\" alnd\n" - -#: g10/import.c:685 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "anahtar %08lX: bizim kopyamzla elemiyor\n" - -#: g10/import.c:702 g10/import.c:920 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "anahtar %08lX: zgn anahtar bloku bulunamad: %s\n" - -#: g10/import.c:709 g10/import.c:926 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "anahtar %08lX: zgn anahtar bloku okunamad: %s\n" - -#: g10/import.c:740 -#, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "anahtar %08lX: \"%s\" 1 yeni kullanc kimlii\n" - -#: g10/import.c:743 -#, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "anahtar %08lX: \"%s\" %d yeni kullanc kimlii\n" - -#: g10/import.c:746 -#, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "anahtar %08lX: \"%s\" 1 yeni imza\n" - -#: g10/import.c:749 -#, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "anahtar %08lX: \"%s\" %d yeni imza\n" - -#: g10/import.c:752 -#, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "anahtar %08lX: %s 1 yeni yardmc anahtar\n" - -#: g10/import.c:755 -#, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "anahtar %08lX: \"%s\" %d yeni yardmc anahtar\n" - -#: g10/import.c:774 -#, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "anahtar %08lX: \"%s\" deimedi\n" - -#: g10/import.c:844 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "ntanml gizli anahtar zinciri yok: %s\n" - -#: g10/import.c:855 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "anahtar %08lX: gizli anahtar indirildi\n" - -#. we can't merge secret keys -#: g10/import.c:861 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "anahtar %08lX: zaten gizli anahtar zincirinde\n" - -#: g10/import.c:868 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "anahtar %08lX: gizli anahtar bulunamad: %s\n" - -#: g10/import.c:897 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"anahtar %08lX: genel anahtar deil - yrrlkten kaldrma sertifikas " -"uygulanamaz\n" - -#: g10/import.c:937 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "anahtar %08lX: yrrlkten kaldrma sertifikas geersiz: %s - reddedildi\n" - -#: g10/import.c:969 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "anahtar %08lX: \"%s\" yrrlkten kaldrma sertifikas alnd\n" - -#: g10/import.c:1017 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "anahtar %08lX: imza iin kullanc kimlii yok\n" - -#: g10/import.c:1030 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"anahtar %08lX: genel anahtar algoritmas, kullanc kimlii \"%s\" iin " -"desteklenmiyor\n" - -#: g10/import.c:1032 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "anahtar %08lX: kullanc kimlii \"%s\" iin z-imza geersiz\n" - -#: g10/import.c:1047 -#, c-format -msgid "key %08lX: no subkey for key binding\n" -msgstr "anahtar %08lX: anahtar garantilemek iin yardmc anahtar yok\n" - -#: g10/import.c:1055 g10/import.c:1096 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "anahtar %08lX: genel anahtar algoritmas desteklenmiyor\n" - -#: g10/import.c:1056 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "anahtar %08lX: yardmc anahtar garantileme geersiz\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1068 -#, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "anahtar %08lX: ok sayda yardmc anahtar balants silindi\n" - -#: g10/import.c:1088 -#, c-format -msgid "key %08lX: no subkey for key revocation\n" -msgstr "anahtar %08lX: anahtar yrrlkten kaldrmak iin yardmc anahtar yok\n" - -#: g10/import.c:1097 -#, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "anahtar %08lX: yardmc anahtar yrrlkten kaldrmas geersiz\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1108 -#, c-format -msgid "key %08lX: removed multiple subkey revocation\n" -msgstr "anahtar %08lX: ok sayda yardmc anahtar yrrlkten kaldrmas silindi\n" - -#: g10/import.c:1145 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "anahtar %08lX: kullanc kimlii atland: '" - -#: g10/import.c:1168 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "anahtar %08lX: yardmc anahtar atland\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1194 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "anahtar %08lX: imza gnderilebilir deil (%02x snf) - atland\n" - -#: g10/import.c:1203 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "anahtar %08lX: yrrlkten kaldrma sertifikas yanl yerde - atland\n" - -#: g10/import.c:1220 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "anahtar %08lX: yrrlkten kaldrma sertifikas geersiz: %s - atland\n" - -#: g10/import.c:1232 -#, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "anahtar %08lX: yardmc anahtar imzas yanl yerde - atland\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "anahtar %08lX: ift kullanc kimlii saptand - kattrld\n" - -#: g10/import.c:1389 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"UYARI: anahtar %08lX yrrlkten kaldrlm olmal: yrrlkten kaldrma " -"anahtar %08lX alnyor\n" - -#: g10/import.c:1403 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"UYARI: anahtar %08lX yrrlkten kaldrlm olabilir: yrrlkten kaldrma " -"anahtar %08lX mevcut deil.\n" - -#: g10/import.c:1460 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "anahtar %08lX: \"%s\" yrrlkten kaldrma sertifikas eklendi\n" - -#: g10/import.c:1491 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "anahtar %08lX: dorudan anahtar imzas eklendi\n" - -#: g10/keyedit.c:147 -msgid "[revocation]" -msgstr "[yrrlkten kaldrma]" - -#: g10/keyedit.c:148 -msgid "[self-signature]" -msgstr "[z-imza]" - -#: g10/keyedit.c:219 g10/keylist.c:148 -msgid "1 bad signature\n" -msgstr "1 kt imza\n" - -#: g10/keyedit.c:221 g10/keylist.c:150 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d kt imza\n" - -#: g10/keyedit.c:223 g10/keylist.c:152 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 imza kayp bir anahtar yznden kontrol edilmedi\n" - -#: g10/keyedit.c:225 g10/keylist.c:154 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d imza kayp bir anahtar yznden kontrol edilmedi\n" - -#: g10/keyedit.c:227 g10/keylist.c:156 -msgid "1 signature not checked due to an error\n" -msgstr "1 imza bir hata yznden kontrol edilmedi\n" - -#: g10/keyedit.c:229 g10/keylist.c:158 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d imza hatalardan dolay kontrol edilmedi\n" - -#: g10/keyedit.c:231 -msgid "1 user ID without valid self-signature detected\n" -msgstr "1 z-imzas geersiz kullanc kimlii saptand\n" - -#: g10/keyedit.c:233 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d z-imzas geersiz kullanc kimlii saptand\n" - -#: g10/keyedit.c:360 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "Kullanc kimlii \"%s\" yrrlkten kaldrld." - -#: g10/keyedit.c:367 g10/keyedit.c:484 g10/keyedit.c:542 g10/keyedit.c:1140 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Onu yine de imzalamak istiyor musunuz? (e/H) " - -#: g10/keyedit.c:375 g10/keyedit.c:490 g10/keyedit.c:1146 -msgid " Unable to sign.\n" -msgstr " mzalanamyor.\n" - -#: g10/keyedit.c:380 -#, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "UYARI: kullanc kimlii \"%s\" z-imzal deil.\n" - -#: g10/keyedit.c:399 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"\"%s\" zerindeki z-imza\n" -"bir PGP 2.x tarz imza.\n" - -#: g10/keyedit.c:408 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Bir OpenPGP z-imzas haline getirilmesini istiyor musunuz? (e/H) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:422 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"\"%s\" zerindeki imzanz\n" -"dahili bir imza.\n" - -#: g10/keyedit.c:426 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "Bu imzann darda da geerli hale getirilmesini istiyor musunuz? (e/H) " - -#: g10/keyedit.c:446 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" zaten %08lX anahtaryla yerel olarak imzalanm\n" - -#: g10/keyedit.c:450 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" zaten %08lX anahtaryla imzalanm\n" - -#: g10/keyedit.c:463 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "%08lX anahtar ile imzalanacak hibir ey yok\n" - -#: g10/keyedit.c:478 -msgid "This key has expired!" -msgstr "Bu anahtarn kullanm sresi dolmu!" - -#: g10/keyedit.c:498 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Bu anahtarn geerlilii %s de bitiyor.\n" - -#: g10/keyedit.c:502 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "mzanzn da bu kadar sre geerli olmasn ister misiniz? (E/h) " - -#: g10/keyedit.c:535 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"--pgp2 kipinde bir PGP 2.x anahtarlara bir OpenPGP imzas " -"uygulanamayabilir.\n" - -#: g10/keyedit.c:537 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Bu, anahtar PGP 2.x iin kullansz yapacak.\n" - -#: g10/keyedit.c:560 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Bu anahtarn ismi yukarda yazl kiiye ait olduunu ne kadar dikkatli\n" -"doruladnz? Bu sorunun cevabn bilmiyorsanz \"0\" yazn.\n" - -#: g10/keyedit.c:564 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Cevab bilmiyorum. %s\n" - -#: g10/keyedit.c:566 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Tamamen kontrol edildi.%s\n" - -#: g10/keyedit.c:568 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) likisel denetim yaptm.%s\n" - -#: g10/keyedit.c:570 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) ok dikkatli bir denetim yaptm.%s\n" - -#: g10/keyedit.c:595 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Bu anahtar kendi anahtarnzla imzalamak istediinize gerekten\n" -"emin misiniz?: \"" - -#: g10/keyedit.c:604 -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "" -"\n" -"Bu bir z-imza olacak.\n" - -#: g10/keyedit.c:608 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"UYARI: imza dar gnderilemez olarak imlenmeyecek.\n" - -#: g10/keyedit.c:613 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"UYARI: imza yrrlkten kaldrlamaz olarak imlenmeyecek.\n" - -#: g10/keyedit.c:620 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"mza dar gnderilemez olarak imlenecek.\n" - -#: g10/keyedit.c:624 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"mza yrrlkten kaldrlamaz olarak imlenecek.\n" - -#: g10/keyedit.c:629 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Her eyiyle bu anahtar kontol edemedim.\n" - -#: g10/keyedit.c:633 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Bu anahtar karlatrmal kontrol ettim.\n" - -#: g10/keyedit.c:637 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Bu anahtar ok dikkatli kontrol ettim.\n" - -#: g10/keyedit.c:646 -msgid "Really sign? " -msgstr "Gerekten imzalayacak msnz? " - -#: g10/keyedit.c:688 g10/keyedit.c:3064 g10/keyedit.c:3126 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "imzalama baarsz: %s\n" - -#: g10/keyedit.c:744 -msgid "This key is not protected.\n" -msgstr "Bu anahtar korunmam.\n" - -#: g10/keyedit.c:748 -msgid "Secret parts of primary key are not available.\n" -msgstr "Asl anahtarn gizli paralar kullanlamaz.\n" - -#: g10/keyedit.c:752 -msgid "Key is protected.\n" -msgstr "Anahtar korunmu.\n" - -#: g10/keyedit.c:772 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Bu anahtar zerinde dzenleme yaplamaz: %s\n" - -#: g10/keyedit.c:778 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Bu gizli anahtar iin yeni anahtar parolasn giriniz.\n" -"\n" - -#: g10/keyedit.c:792 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Bir anahtar parolas vermediniz - bu ok *kt* bir fikir!\n" -"\n" - -#: g10/keyedit.c:795 -msgid "Do you really want to do this? " -msgstr "Gerekten bunu yapmak istiyor musunuz? " - -#: g10/keyedit.c:859 -msgid "moving a key signature to the correct place\n" -msgstr "bir anahtar imzas doru yere tanyor\n" - -#: g10/keyedit.c:901 -msgid "quit this menu" -msgstr "bu menden k" - -#: g10/keyedit.c:902 -msgid "q" -msgstr "k" - -#: g10/keyedit.c:903 -msgid "save" -msgstr "kaydet" - -#: g10/keyedit.c:903 -msgid "save and quit" -msgstr "kaydet ve k" - -#: g10/keyedit.c:904 -msgid "help" -msgstr "yardm" - -#: g10/keyedit.c:904 -msgid "show this help" -msgstr "bunu gsterir " - -#: g10/keyedit.c:906 -msgid "fpr" -msgstr "piz" - -#: g10/keyedit.c:906 -msgid "show fingerprint" -msgstr "parmak izini gster" - -#: g10/keyedit.c:907 -msgid "list" -msgstr "listele" - -#: g10/keyedit.c:907 -msgid "list key and user IDs" -msgstr "anahtar ve kullanc kimliini gster" - -#: g10/keyedit.c:908 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:909 -msgid "uid" -msgstr "kullkim" - -#: g10/keyedit.c:909 -msgid "select user ID N" -msgstr "N kullanc kimliini seer" - -#: g10/keyedit.c:910 -msgid "key" -msgstr "anahtar" - -#: g10/keyedit.c:910 -msgid "select secondary key N" -msgstr "N yardmc anahtarn seer" - -#: g10/keyedit.c:911 -msgid "check" -msgstr "kontrol" - -#: g10/keyedit.c:911 -msgid "list signatures" -msgstr "imzalar listele" - -#: g10/keyedit.c:912 -msgid "c" -msgstr "k" - -#: g10/keyedit.c:913 -msgid "sign" -msgstr "imzala" - -#: g10/keyedit.c:913 -msgid "sign the key" -msgstr "anahtar imzalar" - -#: g10/keyedit.c:914 -msgid "s" -msgstr "i" - -#: g10/keyedit.c:915 -msgid "lsign" -msgstr "yimza" - -#: g10/keyedit.c:915 -msgid "sign the key locally" -msgstr "anahtar yerel olarak imzala" - -#: g10/keyedit.c:916 -msgid "nrsign" -msgstr "ykszimza" - -#: g10/keyedit.c:916 -msgid "sign the key non-revocably" -msgstr "yrrlkten kaldrlamayan imza" - -#: g10/keyedit.c:917 -msgid "nrlsign" -msgstr "iykszimza" - -#: g10/keyedit.c:917 -msgid "sign the key locally and non-revocably" -msgstr "yrrlkten kaldrlamayan yerel imza" - -#: g10/keyedit.c:918 -msgid "debug" -msgstr "hata ayklama" - -#: g10/keyedit.c:919 -msgid "adduid" -msgstr "kullkimEkle" - -#: g10/keyedit.c:919 -msgid "add a user ID" -msgstr "bir kullanc kimlii ekler" - -#: g10/keyedit.c:920 -msgid "addphoto" -msgstr "fotoekle" - -#: g10/keyedit.c:920 -msgid "add a photo ID" -msgstr "bir foto kimlii ekler" - -#: g10/keyedit.c:921 -msgid "deluid" -msgstr "kullkimSil" - -#: g10/keyedit.c:921 -msgid "delete user ID" -msgstr "kullanc kimliini siler" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:923 -msgid "delphoto" -msgstr "fotosil" - -#: g10/keyedit.c:924 -msgid "addkey" -msgstr "anhEkle" - -#: g10/keyedit.c:924 -msgid "add a secondary key" -msgstr "bir yardmc anahtar ekler" - -#: g10/keyedit.c:925 -msgid "delkey" -msgstr "anhSil" - -#: g10/keyedit.c:925 -msgid "delete a secondary key" -msgstr "bir yardmc anahtar siler" - -#: g10/keyedit.c:926 -msgid "addrevoker" -msgstr "iptalEkle" - -#: g10/keyedit.c:926 -msgid "add a revocation key" -msgstr "bir yrrlkten kaldrma anahtar ekler" - -#: g10/keyedit.c:927 -msgid "delsig" -msgstr "imzaSil" - -#: g10/keyedit.c:927 -msgid "delete signatures" -msgstr "imzalar siler" - -#: g10/keyedit.c:928 -msgid "expire" -msgstr "sontarih" - -#: g10/keyedit.c:928 -msgid "change the expire date" -msgstr "son kullanm tarihini deitirir" - -#: g10/keyedit.c:929 -msgid "primary" -msgstr "asl" - -#: g10/keyedit.c:929 -msgid "flag user ID as primary" -msgstr "kullanc kimliini asl olarak imler" - -#: g10/keyedit.c:930 -msgid "toggle" -msgstr "semece" - -#: g10/keyedit.c:930 -msgid "toggle between secret and public key listing" -msgstr "genel ve gizli anahtar listeleri arasnda yer deitirir" - -#: g10/keyedit.c:932 -msgid "t" -msgstr "b" - -#: g10/keyedit.c:933 -msgid "pref" -msgstr "nayar" - -#: g10/keyedit.c:933 -msgid "list preferences (expert)" -msgstr "tercihleri listeler (uzman)" - -#: g10/keyedit.c:934 -msgid "showpref" -msgstr "tercihgst" - -#: g10/keyedit.c:934 -msgid "list preferences (verbose)" -msgstr "tercihleri listeler (ayrntl)" - -#: g10/keyedit.c:935 -msgid "setpref" -msgstr "tercihyap" - -#: g10/keyedit.c:935 -msgid "set preference list" -msgstr "tercih listesi oluturmak iin" - -#: g10/keyedit.c:936 -msgid "updpref" -msgstr "tercgncel" - -#: g10/keyedit.c:936 -msgid "updated preferences" -msgstr "gncelenmi tercihler" - -#: g10/keyedit.c:937 -msgid "passwd" -msgstr "aparola" - -#: g10/keyedit.c:937 -msgid "change the passphrase" -msgstr "anahtar parolasn deitirir" - -#: g10/keyedit.c:938 -msgid "trust" -msgstr "gvence" - -#: g10/keyedit.c:938 -msgid "change the ownertrust" -msgstr "sahibiningvencesini deitirir" - -#: g10/keyedit.c:939 -msgid "revsig" -msgstr "imzayrkal" - -#: g10/keyedit.c:939 -msgid "revoke signatures" -msgstr "imzalar yrrlkten kaldrr" - -#: g10/keyedit.c:940 -msgid "revkey" -msgstr "yrkalanh" - -#: g10/keyedit.c:940 -msgid "revoke a secondary key" -msgstr "bir yardmc anahtar yrrlkten kaldrr" - -#: g10/keyedit.c:941 -msgid "disable" -msgstr "iptal" - -#: g10/keyedit.c:941 -msgid "disable a key" -msgstr "bir anahtar iptal eder" - -#: g10/keyedit.c:942 -msgid "enable" -msgstr "kullan" - -#: g10/keyedit.c:942 -msgid "enable a key" -msgstr "bir anahtar kullanma sokar" - -#: g10/keyedit.c:943 -msgid "showphoto" -msgstr "fotogst" - -#: g10/keyedit.c:943 -msgid "show photo ID" -msgstr "foto kimliini gsterir" - -#: g10/delkey.c:119 g10/keyedit.c:963 -msgid "can't do that in batchmode\n" -msgstr "bu nceden belirlenmi ilemler kipinde (in batchmode) yaplamaz\n" - -#: g10/keyedit.c:1000 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "gizli anahtar blou `%s' okunurken hata olutu: %s\n" - -#: g10/keyedit.c:1018 -msgid "Secret key is available.\n" -msgstr "Gizli anahtar mevcut.\n" - -#: g10/keyedit.c:1049 -msgid "Command> " -msgstr "Komut> " - -#: g10/keyedit.c:1081 -msgid "Need the secret key to do this.\n" -msgstr "Bunu yapmak iin gizli anahtar gerekli.\n" - -#: g10/keyedit.c:1085 -msgid "Please use the command \"toggle\" first.\n" -msgstr "ltfen nce \"semece\" komutunu kullann.\n" - -#: g10/keyedit.c:1134 -msgid "Key is revoked." -msgstr "Anahtar yrrlkten kaldrld." - -#: g10/keyedit.c:1153 -msgid "Really sign all user IDs? " -msgstr "Tm kullanc kimlikleri gerekten imzalanacak m? " - -#: g10/keyedit.c:1154 -msgid "Hint: Select the user IDs to sign\n" -msgstr "pucu: mzalamak iin bir kullanc kimlii seiniz\n" - -#: g10/keyedit.c:1179 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "%s kipindeyken bu komut kullanlamaz.\n" - -#: g10/keyedit.c:1199 g10/keyedit.c:1220 -msgid "You must select at least one user ID.\n" -msgstr "En az bir kullanc kimlii semelisiniz.\n" - -#: g10/keyedit.c:1201 -msgid "You can't delete the last user ID!\n" -msgstr "Son kullanc kimliini silemezsiniz!\n" - -#: g10/keyedit.c:1204 -msgid "Really remove all selected user IDs? " -msgstr "Seilen tm kullanc kimlikleri gerekten silinecek mi? " - -#: g10/keyedit.c:1205 -msgid "Really remove this user ID? " -msgstr "Bu kullanc kimlii gerekten silinecek mi? " - -#: g10/keyedit.c:1243 g10/keyedit.c:1280 -msgid "You must select at least one key.\n" -msgstr "En az bir anahtar semelisiniz.\n" - -#: g10/keyedit.c:1247 -msgid "Do you really want to delete the selected keys? " -msgstr "Seilen anahtarlar gerekten silmek istiyor musunuz? " - -#: g10/keyedit.c:1248 -msgid "Do you really want to delete this key? " -msgstr "Bu anahtar gerekten silmek istiyor musunuz? " - -#: g10/keyedit.c:1284 -msgid "Do you really want to revoke the selected keys? " -msgstr "Seilen anahtarlar gerekten yrrlkten kaldrmak istiyor musunuz? " - -#: g10/keyedit.c:1285 -msgid "Do you really want to revoke this key? " -msgstr "Bu anahtar gerekten yrrlkten kaldrmak istiyor musunuz? " - -#: g10/keyedit.c:1354 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Seilen kullanc kimlik iin tercihleri gerekten gncellemek istiyor " -"musunuz? " - -#: g10/keyedit.c:1356 -msgid "Really update the preferences? " -msgstr "Tercihleri gerekten gncellemek istiyor musunuz? " - -#: g10/keyedit.c:1394 -msgid "Save changes? " -msgstr "Deiiklikler kaydedilecek mi? " - -#: g10/keyedit.c:1397 -msgid "Quit without saving? " -msgstr "Kaydetmeden klsn m? " - -#: g10/keyedit.c:1408 -#, c-format -msgid "update failed: %s\n" -msgstr "gncelleme baarsz: %s\n" - -#: g10/keyedit.c:1415 -#, c-format -msgid "update secret failed: %s\n" -msgstr "gizliyi gncelleme baarsz: %s\n" - -#: g10/keyedit.c:1422 -msgid "Key not changed so no update needed.\n" -msgstr "Gncelleme gerei olmadndan anahtar deimedi.\n" - -#: g10/keyedit.c:1434 -msgid "Invalid command (try \"help\")\n" -msgstr "Komut geersiz (\"yardm\" komutunu deneyin)\n" - -#: g10/keyedit.c:1750 -#, c-format -msgid "This key may be revoked by %s key " -msgstr "Bu anahtar %s tarafndan bu anahtarla yrrlkten kaldrlm olabilir: " - -#: g10/keyedit.c:1754 -msgid " (sensitive)" -msgstr " (duyarl)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1760 g10/keyedit.c:1786 g10/keyedit.c:1871 g10/keyedit.c:1886 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX retildi: %s son kullanma tarihi: %s" - -#: g10/keyedit.c:1769 -#, c-format -msgid " trust: %c/%c" -msgstr " gven derecesi: %c/%c" - -#: g10/keyedit.c:1773 -msgid "This key has been disabled" -msgstr "Bu anahtar iptal edilmiti" - -#: g10/keyedit.c:1802 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "yrkal! yardmc anahtar yrrllkten kaldrld: %s\n" - -#: g10/keyedit.c:1805 -msgid "rev- faked revocation found\n" -msgstr "yrkal- sahte yrrlkten kaldrma sertifikas bulundu\n" - -#: g10/keyedit.c:1807 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "yrkal? Yrrlkten kaldrma denetlenirken problem: %s\n" - -#: g10/keyedit.c:1837 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "Bir PGP 2.x tarz kullanc kimliine uygun tercih yok.\n" - -#: g10/keyedit.c:1845 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Gsterilen anahtarn, uygulamay yeniden balatncaya kadar, gerekli\n" -"dorulukta olmayacan ltfen gznne alnz.\n" - -#: g10/keyedit.c:2001 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"UYARI: Bu PGP-2 tarz bir anahtar. Bir foto kimlii eklenmesi bu anahtarn\n" -" baz PGP srmleri tarafndan reddedilmesi ile sonulanabilir.\n" - -#: g10/keyedit.c:2006 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Onu yine de eklemek istiyor musunuz? (e/H) " - -#: g10/keyedit.c:2012 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "PGP2 tarz bir anahtara bir foto kimlii ekleyemeyebilirsiniz.\n" - -#: g10/keyedit.c:2147 -msgid "Delete this good signature? (y/N/q)" -msgstr "Bu doru imza silinsin mi? (e/H/k)" - -#: g10/keyedit.c:2157 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Bu geersiz imza silinsin mi? (e/H/k)" - -#: g10/keyedit.c:2161 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Bu bilinmeyen imza silinsin mi? (e/H/k)" - -#: g10/keyedit.c:2167 -msgid "Really delete this self-signature? (y/N)" -msgstr "Bu z-imza gerekten silinecek mi? (e/H)" - -#: g10/keyedit.c:2181 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d imza silindi.\n" - -#: g10/keyedit.c:2182 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d imza silindi.\n" - -#: g10/keyedit.c:2185 -msgid "Nothing deleted.\n" -msgstr "Hibir ey silinmedi.\n" - -#: g10/keyedit.c:2281 -msgid "Enter the user ID of the designated revoker: " -msgstr "Tasarlanan yrrlkten kaldrma anahtarnn kullanc kimliini giriniz: " - -#: g10/keyedit.c:2296 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" -"bir PGP 2.x tarz anahtar bir tasarlanm yrrlkten kaldrma anahtar olarak " -"atanamaz\n" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2306 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "bir anahtar kendisini yrrlkten kaldracak anahtar olarak kullanamazsnz\n" - -#: g10/keyedit.c:2393 -msgid "Please remove selections from the secret keys.\n" -msgstr "Ltfen gizli anahtarlardan seilenleri silin.\n" - -#: g10/keyedit.c:2399 -msgid "Please select at most one secondary key.\n" -msgstr "Ltfen en fazla bir yardmc anahtar sein.\n" - -#: g10/keyedit.c:2403 -msgid "Changing expiration time for a secondary key.\n" -msgstr "Bir yardmc anahtar iin son kullanma tarihi deitiriliyor.\n" - -#: g10/keyedit.c:2405 -msgid "Changing expiration time for the primary key.\n" -msgstr "Asl anahtar iin son kullanma tarihi deitiriliyor.\n" - -#: g10/keyedit.c:2447 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Bir v3 anahtarnn son kullanma tarihini deitiremezsiniz\n" - -#: g10/keyedit.c:2463 -msgid "No corresponding signature in secret ring\n" -msgstr "Gizli anahtar demetinde uygun/benzer imza yok\n" - -#: g10/keyedit.c:2546 -msgid "Please select exactly one user ID.\n" -msgstr "Ltfen sadece ve sadece bir kullanc kimlik seiniz.\n" - -#: g10/keyedit.c:2583 g10/keyedit.c:2690 -#, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "kullanc kimlii \"%s\" iin v3 z-imzas atlanyor\n" - -#: g10/keyedit.c:2750 -#, c-format -msgid "No user ID with index %d\n" -msgstr "%d endeksine sahip kullanc kimlii yok\n" - -#: g10/keyedit.c:2796 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "%d endeksine sahip yardmc anahtar yok\n" - -#: g10/keyedit.c:2910 -msgid "user ID: \"" -msgstr "Kullanc kimlii: \"" - -#: g10/keyedit.c:2915 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -" %08lX anahtarnzla %s de imzaland\n" - -#: g10/keyedit.c:2918 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"%08lX anahtarnzla %s de yerel olarak imzal\n" - -#: g10/keyedit.c:2923 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Bu anahtarn geerlilii %s de bitti.\n" - -#: g10/keyedit.c:2927 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Onu yine de yrrlkten kaldrmak istiyor musunuz? (e/H) " - -#: g10/keyedit.c:2931 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Bu imza iin bir yrrlkten kaldrma sertifikas oluturulsun mu? (e/H) " - -#. FIXME: detect duplicates here -#: g10/keyedit.c:2956 -msgid "You have signed these user IDs:\n" -msgstr "Bu kullanc kimliklerini imzalamsnz:\n" - -#: g10/keyedit.c:2975 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " %08lX ile %s%s%s de imzalanm\n" - -#: g10/keyedit.c:2983 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " %08lX tarafndan %s de yrrlkten kaldrlm\n" - -#: g10/keyedit.c:3003 -msgid "You are about to revoke these signatures:\n" -msgstr "Bu imzalar yrrlkten kaldrmak zeresiniz:\n" - -#: g10/keyedit.c:3013 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " %08lX ile %s%s de imzalanm\n" - -#: g10/keyedit.c:3015 -msgid " (non-exportable)" -msgstr " (darda geersiz)" - -#: g10/keyedit.c:3022 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Bu yrrlkten kaldrma sertifikalarn gerekten oluturacak msnz? (e/H) " - -#: g10/keyedit.c:3052 -msgid "no secret key\n" -msgstr "gizli anahtar yok\n" - -#: g10/keyedit.c:3207 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Anahtar 0x%3$08lX (kull-kiml %4$d) iin %2$ld uzunluktaki %1$s foto kimlii " -"gsteriliyor\n" - -#: g10/keylist.c:91 -msgid "Critical signature policy: " -msgstr "Kritik imza guvencesi: " - -#: g10/keylist.c:93 -msgid "Signature policy: " -msgstr "imza guvencesi: " - -#: g10/keylist.c:118 g10/keylist.c:141 g10/mainproc.c:768 g10/mainproc.c:777 -msgid "WARNING: invalid notation data found\n" -msgstr "UYARI: geersiz niteleme verisi bulundu\n" - -#: g10/keylist.c:127 -msgid "Critical signature notation: " -msgstr "Kritik imza niteleyici: " - -#: g10/keylist.c:129 -msgid "Signature notation: " -msgstr "imza niteleyici: " - -#: g10/keylist.c:136 -msgid "not human readable" -msgstr "insan okuyabilir deil" - -#: g10/keylist.c:225 -msgid "Keyring" -msgstr "Anahtar Zinciri" - -#. of subkey -#: g10/keylist.c:478 g10/mainproc.c:904 -#, c-format -msgid " [expires: %s]" -msgstr "[son kullanma tarihi: %s]" - -#: g10/keylist.c:1001 -msgid "Primary key fingerprint:" -msgstr "Birincil anahtar parmak izi:" - -#: g10/keylist.c:1003 -msgid " Subkey fingerprint:" -msgstr "Yardmc anahtar parmak izi:" - -#: g10/keylist.c:1010 -msgid " Primary key fingerprint:" -msgstr "Birincil anahtar parmak izi:" - -#: g10/keylist.c:1012 -msgid " Subkey fingerprint:" -msgstr "Yardmc anahtar parmak izi:" - -#. use tty -#: g10/keylist.c:1016 g10/keylist.c:1020 -msgid " Key fingerprint =" -msgstr " Anahtar parmak izi =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "bir ifreli oturum anahtar (%d) iin tuhaf uzunluk\n" - -#: g10/mainproc.c:258 -#, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "geersiz symkey algoritmas saptand (%d)\n" - -#: g10/encr-data.c:66 g10/mainproc.c:287 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s ifreli veri\n" - -#: g10/encr-data.c:68 g10/mainproc.c:289 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "bilinmeyen algoritma %d ile ifrelenmi\n" - -#: g10/mainproc.c:317 -#, c-format -msgid "public key is %08lX\n" -msgstr "genel anahtar: %08lX\n" - -#: g10/mainproc.c:363 -msgid "public key encrypted data: good DEK\n" -msgstr "genel anahtarla ifreli veri: doru DEK\n" - -#: g10/mainproc.c:415 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "" -"%u bitlik %s anahtar ve kullanc kimlii\n" -"%08lX ile ifrelendi, %s oluturuldu\n" - -#: g10/mainproc.c:425 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "%s anahtar ve %08lX kullanc kimlii ile ifrelendi\n" - -#: g10/mainproc.c:439 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "genel anahtar ifre zm baarsz: %s\n" - -#: g10/mainproc.c:466 g10/mainproc.c:485 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "%s ifreli veri varsaylyor\n" - -#: g10/mainproc.c:473 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "IDEA ifre kullansz, iyimserlikle yerine %s kullanlmaya allyor\n" - -#: g10/mainproc.c:503 -msgid "decryption okay\n" -msgstr "ifre zme tamam\n" - -#: g10/mainproc.c:510 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "UYARI: ifreli ileti tahrip edilmi!\n" - -#: g10/mainproc.c:516 -#, c-format -msgid "decryption failed: %s\n" -msgstr "ifre zme baarsz: %s\n" - -#: g10/mainproc.c:535 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "BLG: gnderen \"yalnz-gzleriniz-iin\" ricasnda bulundu\n" - -#: g10/mainproc.c:537 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "zgn dosya ad = '%.*s'\n" - -#: g10/mainproc.c:712 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "tek bana yrrlkten kaldrma - uygulamak iin \"gpg --import\" kullann\n" - -#: g10/mainproc.c:780 -msgid "Notation: " -msgstr "Niteleme: " - -#: g10/mainproc.c:792 -msgid "Policy: " -msgstr "Gvence: " - -#: g10/mainproc.c:1247 -msgid "signature verification suppressed\n" -msgstr "imza dorulama engellendi\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1289 g10/mainproc.c:1299 -msgid "can't handle these multiple signatures\n" -msgstr "bu oklu imzalar elde edilemiyor\n" - -#: g10/mainproc.c:1310 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "%.*s imzas, %s anahtar ve %08lX kullanc kimlii ile yapld\n" - -#: g10/mainproc.c:1359 g10/mainproc.c:1392 -msgid "BAD signature from \"" -msgstr "KT imza: \"" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "Expired signature from \"" -msgstr "Kullanm tarihi gemi imza: \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Good signature from \"" -msgstr "Doru imza: \"" - -#: g10/mainproc.c:1396 -msgid "[uncertain]" -msgstr "[pheli]" - -#: g10/mainproc.c:1427 -msgid " aka \"" -msgstr " den \"" - -#: g10/mainproc.c:1488 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "mza kontrol edilemedi: %s\n" - -#: g10/mainproc.c:1557 g10/mainproc.c:1573 g10/mainproc.c:1635 -msgid "not a detached signature\n" -msgstr "bir bamsz imza deil\n" - -#: g10/mainproc.c:1584 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "0x%02x snf tek bana imza\n" - -#: g10/mainproc.c:1641 -msgid "old style (PGP 2.x) signature\n" -msgstr "eski stil (PGP 2.x) imza\n" - -#: g10/mainproc.c:1648 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "proc_tree() iinde geersiz kk paket saptand\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "\"core\" oluumu iptal edilemedi: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Deneysel algoritmalar kullanlmamal!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "bu ifre algoritmas standart d; ltfen daha standart birini kullann!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "IDEA ifre eklentisi yok\n" - -#: g10/misc.c:301 -msgid "please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "" -"Daha fazla bilgi iin ltfen http://www.gnupg.org/why-not-idea.html " -"adresine\n" -"baknz.\n" - -#: g10/misc.c:509 -#, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "%s:%d: \"%s\" seenei kullanmdan kaldrlmak zere.\n" - -#: g10/misc.c:513 -#, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "UYARI: %s seenei kullanmdan kaldrlmak zere.\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "ltfen yerine \"%s%s\" kullannz\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "%d genel anahtar algoritmas kullanlamad\n" - -#: g10/parse-packet.c:1065 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "%d tipi alt paket kritik bit kmesine sahip\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "gpg-agent bu oturumda kullanlamaz\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "istemci pid'i belirlenemiyor\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "sunucu okuma dosya tantcs alnamad\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "sunucu yazma dosya tantcs alnamad\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "GPG_AGENT_INFO evre deikeni hatal\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "gpg-agent protokol srm %d desteklenmiyor\n" - -#: g10/hkp.c:151 g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "\"%s\" sunucusuna balanlamad: %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "gpg-agent ile haberleme problemi\n" - -#: g10/passphrase.c:561 g10/passphrase.c:811 g10/passphrase.c:919 -msgid "problem with the agent - disabling agent use\n" -msgstr "vekil ile problem - vekil kullanm iptal ediliyor\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1017 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (asl anahtar kimlii %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"\"%.*s\"\n" -"kullancsnn gizli anahtarn aacak bir anahtar parolasna ihtiya var.\n" -"%u bitlik %s anahtar, kimlik %08lX, oluturulan %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Anahtar parolasn giriniz\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Parolay tekrar yaznz\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "Parola ok uzun\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "yant geersiz\n" - -#: g10/passphrase.c:727 g10/passphrase.c:808 -msgid "cancelled by user\n" -msgstr "kullanc tarafndan durduruldu\n" - -#: g10/passphrase.c:729 g10/passphrase.c:890 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "vekil ile sorun var: vekil 0x%lx ile sonuland\n" - -#: g10/passphrase.c:1003 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Gizli anahtarn kilidini amak iin bir anahtar parolasna ihtiyacnz var.\n" -"Anahtarn sahibi: \"" - -#: g10/passphrase.c:1012 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u bitlik %s anahtar, kimlik: %08lX, oluturuldu %s" - -#: g10/passphrase.c:1063 -msgid "can't query password in batchmode\n" -msgstr "nceden tanmlanm ilemler kipinde (batchmode) parola sorgulanamaz\n" - -#: g10/passphrase.c:1067 -msgid "Enter passphrase: " -msgstr "Anahtar parolasn girin: " - -#: g10/passphrase.c:1071 -msgid "Repeat passphrase: " -msgstr "Tekrar: " - -#: g10/plaintext.c:67 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "veri kaydedilmedi; kaydetmek iin \"--output\" seeneini kullann\n" - -#: g10/plaintext.c:108 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "`%s' oluturulurken hata: %s\n" - -#: g10/plaintext.c:337 -msgid "Detached signature.\n" -msgstr "Bamsz imza.\n" - -#: g10/plaintext.c:341 -msgid "Please enter name of data file: " -msgstr "Ltfen veri dosyasnn ismini girin: " - -#: g10/plaintext.c:362 -msgid "reading stdin ...\n" -msgstr "standart girdiden okuyor ...\n" - -#: g10/plaintext.c:396 -msgid "no signed data\n" -msgstr "imzal veri yok\n" - -#: g10/plaintext.c:404 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "imzal veri '%s' alamad\n" - -#: g10/pubkey-enc.c:101 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "anonim alc: %08lX gizli anahtar deneniyor ...\n" - -#: g10/pubkey-enc.c:107 -msgid "okay, we are the anonymous recipient.\n" -msgstr "tamam, biz anonim alcyz.\n" - -#: g10/pubkey-enc.c:159 -msgid "old encoding of the DEK is not supported\n" -msgstr "DEK'in eski kodlamas desteklenmiyor\n" - -#: g10/pubkey-enc.c:178 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "ifre algoritmas %d%s bilinmiyor ya da iptal edilmi\n" - -#: g10/pubkey-enc.c:221 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "BLG: %d ifre algoritmas tercihlerde bulunamad\n" - -#: g10/pubkey-enc.c:243 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "BLG: %08lX gizli anahtarnn %s tarihinde kullanm sresi doldu\n" - -#: g10/pubkey-enc.c:249 -msgid "NOTE: key has been revoked" -msgstr "BLG: anahtar yrrlkten kaldrlmt" - -#: g10/hkp.c:71 -#, c-format -msgid "requesting key %08lX from %s\n" -msgstr "%08lX anahtar %s adresinden isteniyor\n" - -#: g10/hkp.c:96 -#, c-format -msgid "can't get key from keyserver: %s\n" -msgstr "anahtar sunucusunun %s adresinden anahtar alnamad\n" - -#: g10/hkp.c:175 -#, c-format -msgid "error sending to `%s': %s\n" -msgstr "\"%s\" adresine gnderme hatas: %s\n" - -#: g10/hkp.c:190 -#, c-format -msgid "success sending to `%s' (status=%u)\n" -msgstr "\"%s\" adresine gnderme ilemi baarl (durum=%u)\n" - -#: g10/hkp.c:193 -#, c-format -msgid "failed sending to `%s': status=%u\n" -msgstr "\"%s\" adresine gnderme ilemi baarsz (durum=%u)\n" - -#: g10/hkp.c:363 -msgid "this keyserver is not fully HKP compatible\n" -msgstr "bu anahtar sunucusu tamamen HKP uyumlu deil\n" - -#: g10/hkp.c:515 -#, c-format -msgid "searching for \"%s\" from HKP server %s\n" -msgstr "HKP sunucusunun %2$s adresinde \"%1$s\" aranyor\n" - -#: g10/hkp.c:565 -#, c-format -msgid "can't search keyserver: %s\n" -msgstr "anahtar sunucusu aranamyor: %s\n" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "gizli anahtar paralar kullanm d\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "koruma algoritmas %d%s desteklenmiyor\n" - -#: g10/seckey-cert.c:224 -msgid "Invalid passphrase; please try again" -msgstr "Anahtar parolas geersiz; ltfen tekrar deneyin" - -#: g10/seckey-cert.c:225 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:282 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"UYARI: Zayf anahtar saptand - ltfen anahtar parolasn tekrar " -"deitirin.\n" - -#: g10/seckey-cert.c:320 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"gizli anahtarn gvenlii iin eski tarz 16 bitlik salama toplam " -"retiliyor\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "UYARI: iletideki imza zmlemesi elikili\n" - -#: g10/sig-check.c:215 -#, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "key %08lX: bu, imzalar iin gvenli olmayan PGP retimi bir ElGamal anahtar!\n" - -#: g10/sig-check.c:224 -#, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "genel anahtar %08lX imzadan %lu saniye daha yeni\n" - -#: g10/sig-check.c:225 -#, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "genel anahtar %08lX imzadan %lu saniye daha yeni.\n" - -#: g10/sig-check.c:234 -#, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "anahtar %08lX %lu saniye sonra retilmi (zaman sapmas veya saat problemi)\n" - -#: g10/sig-check.c:236 -#, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"anahtar %08lX bundan %lu saniye sonra retilmi (zaman sapmas veya saat " -"problemi)\n" - -#: g10/sig-check.c:249 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "BLG: %08lX imza anahtarnn kullanm sresi %s tarihinde dolmu\n" - -#: g10/sig-check.c:348 -#, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"Hatal imzann bilinmeyen bir kritik bitten dolay %08lX anahtarndan " -"kaynakland sanlyor\n" - -#: g10/sign.c:103 - -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"UYARI: %%-geniletmesi imkansz (ok byk).\n" -"Uzatlmadan kullanlyor.\n" - -#: g10/sign.c:151 -#, c-format -msgid "WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"UYARI: gvence adresinin uzatlmas imkansz (ok byk).\n" -"Uzatlmadan kullanlyor.\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "oluturulan imzann denetimi baarsz: %s\n" - -#: g10/sign.c:312 -#, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s imza: \"%s\"den\n" - -#: g10/sign.c:461 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "UYARI: \"%s\" dosyas bo\n" - -#: g10/sign.c:644 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "--pgp2 kipinde sadece PGP 2.x tarz anahtarlarla ayrma imzalamas yapabilirsiniz\n" - -#: g10/sign.c:665 g10/sign.c:892 -#, c-format -msgid "can't create %s: %s\n" -msgstr "%s oluturulamyor: %s\n" - -#: g10/sign.c:690 -#, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "alcnn tercihleriyle elien %s (%d) zmleme algoritmas kullanm zorlanyor\n" - -#: g10/sign.c:784 -msgid "signing:" -msgstr "imzalanyor:" - -#: g10/sign.c:876 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "--pgp2 kipinde sadece PGP 2.x tarz anahtarlarla temiz imzalama yapabilirsiniz\n" - -#: g10/sign.c:1029 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%s ifrelemesi kullanlmayacak\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "%d karakterden daha uzun metin satrlar okunamyor\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "girdi satr %d karakterden daha uzun\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1387 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "gvence veritaban %lu kayd: eriim baarsz: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1394 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "gvence veritaban %lu kayd: yazma baarsz (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "gvence veritaban ilemi ok uzun\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: eriilemedi: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: dizin yok!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: kilit oluturulamad\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: kilitleme yaplamad\n" - -#: g10/keyring.c:1448 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: oluturulamad: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: srm kayd oluturmada baarsz: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: geersiz gvence veritaban oluturuldu\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: gvence veritaban oluturuldu\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "BLG: gvence veritabanna yazlamyor\n" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: gvence veritaban geersiz\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: nitelemeli tablo oluturulamad: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: srm kaydnn gncellenmesinde hata: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1320 g10/tdbio.c:1347 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: srm kaydnn okunmasnda hata: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: srm kaydnn yazlmasnda hata: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "gvence veritaban: eriim baarsz: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "gvence veritaban: okuma baarsz (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: bir gvence veritaban dosyas deil\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: %lu kayt numaras ile srm kayd\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: dosya srm %d geersiz\n" - -#: g10/tdbio.c:1353 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: serbest kayd okuma hatas: %s\n" - -#: g10/tdbio.c:1361 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: dizin kaydn yazma hatas: %s\n" - -#: g10/tdbio.c:1371 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: kayt sfrlama baarsz: %s\n" - -#: g10/tdbio.c:1401 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: kayt ekleme baarsz: %s\n" - -#: g10/tdbio.c:1446 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "gvence veritaban bozulmu; ltfen \"gpg --fix-trustdb\" altrn.\n" - -#: g10/trustdb.c:200 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "`%s' geerli bir anahtar kimlii deil\n" - -#: g10/trustdb.c:235 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "%08lX anahtar: gvenli anahtar olarak kabul edildi\n" - -#: g10/trustdb.c:274 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "%08lX anahtar gvence veritabannda birden fazla kaytta bulundu\n" - -#: g10/trustdb.c:290 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "%08lX anahtar: gvenli anahtar iin genel anahtar yok - atland\n" - -#: g10/trustdb.c:332 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "gvence veritaban kayd %lu, istek tipi %d: okuma baarsz: %s\n" - -#: g10/trustdb.c:338 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "gvence veritabannn %lu. kayd %d istek trnde deil\n" - -#: g10/trustdb.c:353 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "gvence veritabannn %lu. kayd, %d trnde: yazma baarsz: %s\n" - -#: g10/trustdb.c:368 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "gvence veritaban: ezamanlama baarsz: %s\n" - -#: g10/trustdb.c:468 -msgid "no need for a trustdb check\n" -msgstr "bir gvence veritaban denetimi gereksiz\n" - -#: g10/trustdb.c:474 g10/trustdb.c:1641 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "sonraki gvence veritaban denetimi %s de\n" - -#: g10/trustdb.c:779 -msgid "checking the trustdb\n" -msgstr "gvence veritaban denetleniyor\n" - -#: g10/trustdb.c:933 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "%08lX genel anahtar yok: %s\n" - -#: g10/trustdb.c:1515 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "son derece gvenli %08lX genel anahtar yok\n" - -#: g10/trustdb.c:1593 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"denetim %d derinlikte yaplyor: signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%" -"d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"imza dorulanamad.\n" -"mza dosyasnn (.sig veya .asc) komut satrnda verilecek\n" -"ilk dosya olmas gerektiini ltfen hatrlayn.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "girdi satr %u ya ok uzun ya da sonunda satrsonu karakteri yok\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "anahtar gvenli olarak imlenmemi - onu sahte RS ile kullanmayn!\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "`%s' atland: tekrarlanm\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "\"%s\" atland: %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "atland: gizli anahtar zaten var\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"`%s' atland:\n" -"Bu, imzalar iin gvenli olmayan PGP retimi bir ElGamal anahtar!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "\"%s\" dosyas var. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "zerine yazlsn m? (e/H)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: bilinmeyen sonek\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Yeni dosya ismini giriniz" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "standart ktya yazyor\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "\"%s\" iindeki veri imzal kabul ediliyor\n" - -#: g10/openfile.c:326 -#, c-format -msgid "new configuration file `%s' created\n" -msgstr "yeni yaplandrma dosyas `%s' oluturuldu\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: dizin oluturulamyor: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: dizin oluturuldu\n" - -#: g10/encr-data.c:91 -msgid "WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "UYARI: ileti simetrik ifre iindeki zayf bir anahtarla ifrelendi.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "ifreli paketin elde edilmesinde sorun var\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "zayf anahtar oluturuldu - yeniden deneniyor\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"simetrik ifre iin zayf anahtarn nlenmesi mmkn olamad: %d kere " -"denendi!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA, 160 bitlik bir hash algoritmas kullanlmasn gerektiriyor\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "(anahtar parmak izi ile belirtmedike)\n" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "nceden belirlenmi ilemler kipinde \"--yes\" olmakszn yaplamaz\n" - -#: g10/delkey.c:150 -msgid "Delete this key from the keyring? " -msgstr "Bu anahtar, anahtar zincirinden silinsin mi? " - -#: g10/delkey.c:158 -msgid "This is a secret key! - really delete? " -msgstr "Bu bir gizli anahtar! - gerekten silinecek mi? " - -#: g10/delkey.c:168 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "anahtar blou silinemedi: %s\n" - -#: g10/delkey.c:178 -msgid "ownertrust information cleared\n" -msgstr "sahibinin gvencesi bilgisi temizlendi\n" - -#: g10/delkey.c:206 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "genel anahtar \"%s\" iin bir gizli anahtar var!\n" - -#: g10/delkey.c:208 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "onu nce \"--delete-secret-keys\" ile silmelisiniz.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Bir deeri buraya iaretlemek size kalm; bu deer herhangi bir 3. ahsa\n" -"gnderilmeyecek. Bir gvence a salamak iin bizim buna ihtiyacmz var;\n" -"bunun (aka belirtilmeden oluturulmu) sertifikalar ayla\n" -"hibir alakas yok." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Web-of-Trust oluturulabilmesi iin GnuPG'ye hangi anahtarlarn son derece\n" -"gvenli (bunlar gizli anahtarlarna eriiminiz olan anahtarlardr) " -"olduunun\n" -"bildirilmesi gerekir. \"evet\" yant bu anahtarn son derece gvenli\n" -"olduunun belirtilmesi iin yeterlidir.\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" -"Bu yrrlkten kaldrlm anahtar yine de kullanmak istiyorsanz\n" -"cevap olarak \"evet\" yazn." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Bu gvencesiz anahtar yine de kullanmak istiyorsanz cevap olarak\n" -" \"evet\" yazn." - -#: g10/helptext.c:68 -msgid "Enter the user ID of the addressee to whom you want to send the message." -msgstr "Bu iletiyi gndereceiniz adresin kullanc kimliini giriniz." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Kullanlacak algoritmay seiniz.\n" -"\n" -"DSA (DSS olarak da bilinir) sadece imzalar iin kullanlan bir saysal\n" -"imza algoritmasdr. Bu algoritma ElGamal algoritmasndan ok daha hzl\n" -"doruland iin nerilmektedir.\n" -"\n" -"ElGamal imzalar ve ifreleme iin kullanlan bir algoritmadr.\n" -"OpenPGP bu algoritmann bu iki kullanmn birbirinden ayrr:\n" -"sadece ifreleme ve imza+ifreleme; esas olarak ayn gibi grnmekle " -"beraber\n" -"imzalar iin kullanlacak anahtar oluturacak baz zel parametrelerin\n" -"seilmesini gerektirir: bu program bunu yapar ama dier OpenPGP\n" -"gereklemelerinin imza+ifreleme olayn anlamas gerekmiyorsa kullanmak\n" -"anlaml olur.\n" -"\n" -"lk (asl) anahtar imzalama yeteneine sahip bir anahtar olmaldr;\n" -"bu durum, sadece ifreleme yapabilen ElGamal anahtarlarnn neden mende\n" -"bulunmadn aklar." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Bu anahtarlar tm programlar tarafndan desteklenmedii iin ve\n" -"onlarla oluturulan imzalar gereinden byk ve dorulanmas ok yava\n" -"olduundan RFC2440 standardnda tanml olmalarna ramen tavsiye\n" -"edilmezler." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" -"Genelde imzalama ve ifreleme iin ayn anahtar kullanmak iyi bir fikir\n" -"deildir. Bu algoritma sadece belli alanlarda kullanlabilir.\n" -"Ltfen gvenlik uzmannza dann." - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Anahtar uzunluunu giriniz" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Cevap \"evet\" ya da \"hayr\"" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"stenen deeri girin. ISO tarihi (YYYY-AA-GG) girmeniz mmkndr fakat\n" -"iyi bir hata cevab alamazsnz -- onun yerine sistem verilen deeri\n" -"bir zaman aral olarak zmlemeyi dener." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Anahtar tutucunun ismini giriniz" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "ltfen bir E-posta adresi girin (istee bal ancak kuvvetle tavsiye edilir)" - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Ltfen nbilgi girin (istee bal)" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"S iSim deitirmek iin.\n" -"B nBilgiyi deitirmek iin.\n" -"P e-Posta adresini deitirmek iin.\n" -"D anahtar retimine Devam etmek iin.\n" -"K anahtar retiminden Kmak iin." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "Yardmc anahtar retmek istiyorsanz \"evet\" ya da \"e\" girin." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Bir anahtar bir kullanc kimlikle imzalamadan nce kullanc kimliin\n" -"iindeki ismin, anahtarn sahibine ait olup olmadn kontrol etmelisiniz.\n" -"\n" -"\"0\" bu kontrolu yapmadnz ve yapmay da bilmediiniz anlamndadr.\n" -"\"1\" anahtar size sahibi tarafndan gnderildi ama siz bu anahtar baka\n" -" kaynaklardan dorulamadnz anlamndadr. Bu kiisel dorulama iin\n" -" yeterlidir. En aznda yar anonim bir anahtar imzalamas yapm\n" -" olursunuz.\n" -"\"2\" ayrntl bir inceleme yapld anlamndadr. rnein parmakizi ve\n" -" bir anahtarn foto kimliiyle kullanc kimliini karlatrmak\n" -" gibi denetimleri yapmsnzdr.\n" -"\"3\" inceden inceye bir dorulama anlatr. rnein, ahstaki anahtarn\n" -" sahibi ile anahtar parmak izini karlatrmsnzdr ve anahtardaki\n" -" kullanc kimlikte belirtilen isme ait bir basl kimlik belgesindeki\n" -" bir fotorafla ahs karlatrmsnzdr ve son olarak anahtar\n" -" sahibinin e-posta adresini kendisinin kullanmakta olduunu da\n" -" denetlemisinizdir.\n" -"Burada 2 ve 3 iin verilen rnekler *sadece* rnektir.\n" -"Eninde sonunda bir anahtar imzalarken \"ayrntl\" ve \"inceden inceye\" " -"kontroller arasndaki ayrma siz karar vereceksiniz.\n" -"Bu karar verebilecek durumda deilseniz \"0\" cevabn verin." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Kullanc kimliklerinin TMn imzalamak istiyorsanz \"evet\" girin" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Bu kullanc kimliini gerekten silmek istiyorsanz \"evet\" girin.\n" -"Bylece btn sertifikalar kaybedeceksiniz!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "Bu yardmc anahtar silme izni vermek istiyorsanz \"evet\" girin" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Bu, anahtar zerinde geerli bir imzadr; anahtara ya da bu anahtarla\n" -"sertifikalanm bir dier anahtara bir gvence balants salamakta\n" -"nemli olabileceinden normalde bu imzay silmek istemezsiniz." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Bu imza, anahtarna sahip olmadnzdan, kontrol edilemez. Bu imzann\n" -"silinmesini hangi anahtarn kullanldn bilene kadar\n" -"ertelemelisiniz nk bu imzalama anahtar baka bir sertifikal\n" -"anahtar vastas ile bir gvence balants salayabilir." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "mza geersiz. Onu anahtar zincirinizden kaldrmak uygun olacak." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Bu imza kullanc kimliini anahtara balar. z-imzay silmek hi iyi\n" -"bir fikir deil. GnuPG bu anahtar bir daha hi kullanamayabilir.\n" -"Bunu sadece, eer bu z-imza baz durumlarda geerli deilse ya da\n" -"kullanlabilir bir ikincisi var ise yapn." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"Tm kullanc kimlik tercihlerini (ya da seilen birini) mevcut tercihler\n" -"listesine evirir. Tm etkilenen z-imzalarn zaman damgalar bir sonraki\n" -"tarafndan ne alnacaktr.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Ltfen bir anahtar parolas giriniz; yazdklarnz grnmeyecek\n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "Ltfen son parolay tekrarlayarak ne yazdnzdan emin olun." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "mzann uygulanaca dosyann ismini verin" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Dosyann zerine yazlacaksa ltfen \"evet\" yazn" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Ltfen yeni dosya ismini girin. Dosya ismini yazmadan RETURN tularsanz\n" -"parantez iinde gsterilen ntanml dosya kullanlacak." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Sertifikalama iin bir sebep belirtmelisiniz. eriine bal olarak\n" -"bu listeden seebilirsiniz:\n" -" \"Anahtar tehlikede\"\n" -"\tYetkisiz kiilerin gizli anahtarnza eriebildiine inanyorsanz\n" -"\tbunu sein.\n" -" \"Anahtar geici\"\n" -"\tMevcut anahtar daha yeni bir anahtar ile deitirmiseniz bunu sein.\n" -" \"Anahtar artk kullanlmayacak\"\n" -"\tAnahtar emekliye ayracaksanz bunu sein.\n" -" \"Kullanc kimlii artk geersiz\"\n" -"\tKullanc kimlii artk kullanlamayacak durumdaysa bunu\n" -"\tsein; genelde Eposta adresi geersiz olduunda kullanlr.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"sterseniz, neden bu yrrlkten kaldrma sertifikasn\n" -"verdiinizi aklayan bir metin girebilirsiniz.\n" -"Ltfen bu metin ksa olsun. Bir bo satr metni bitirir.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "yardm mevcut deil" - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "\"%s\" iin yardm mevcut deil" - -#: g10/keydb.c:178 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "`%s' anahtar zinciri oluturulurken hata: %s\n" - -#: g10/keydb.c:185 -#, c-format -msgid "keyring `%s' created\n" -msgstr "`%s' anahtar zinciri oluturuldu\n" - -#: g10/keydb.c:575 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "anahtar zinciri bellei yeniden oluturulurken hata: %s\n" - -#: g10/keyring.c:1226 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "UYARI: gizli bilgi ieren 2 dosya mevcut.\n" - -#: g10/keyring.c:1228 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s deimeyenlerden\n" - -#: g10/keyring.c:1229 -#, c-format -msgid "%s is the new one\n" -msgstr "%s yenilerden\n" - -#: g10/keyring.c:1230 -msgid "Please fix this possible security flaw\n" -msgstr "Ltfen bu gvenlik atlan giderin\n" - -#: g10/keyring.c:1346 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "`%s' anahtar zinciri denetleniyor\n" - -#: g10/keyring.c:1377 -#, c-format -msgid "%lu keys so far checked (%lu signatures)\n" -msgstr "imdiye dek %lu anahtar denetlendi (%lu imza)\n" - -#: g10/keyring.c:1388 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu anahtar denetlendi (%lu imza)\n" - -#: g10/keyring.c:1453 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: anahtar zinciri oluturuldu\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "Yeni seenekler dosyasnn okunabilmesi iin GnuPG yeniden " -#~ "balatlmaldr\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "`%s' izinleri deitirilemedi: %s\n" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|SM=DEER|veri bu nitelemeyle kullanlr" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "bir niteleme isminin ilk karakteri bir harf ya da altizgi olmal\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "bir niteleme isminde noktalar dier karakterler tarafndan kuatlm " -#~ "olmaldr\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "UYARI: Bu anahtarn zaten bir foto kimlii var.\n" -#~ " Baka bir foto kimlii eklemek PGP'in baz srmleriyle uyumsuz " -#~ "olabilir.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Bir anahtarn sadece bir foto kimlii olabilir.\n" - -#~ msgid "Fingerprint:" -#~ msgstr " Parmak izi:" - -#~ msgid " Fingerprint:" -#~ msgstr " Parmak izi:" - -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Onu yine de imzalamak istiyor musunuz?\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " Onu yine de imzalamak istiyor musunuz?\n" - -#, fuzzy -#~ msgid "Really sign? (y/N) " -#~ msgstr "Gerekten imzalayacak msnz? " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "anahtar %08lX: bizim kopyann z-imzas yok\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Bu kadar byk anahtar uzunluuna gerekten ihtiyacnz var m?" - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " %08lX tarafndan %s de imzalanm\n" - diff --git a/scd/ChangeLog b/scd/ChangeLog deleted file mode 100644 index a55c51d53..000000000 --- a/scd/ChangeLog +++ /dev/null @@ -1,91 +0,0 @@ -2002-08-21 Werner Koch - - * scdaemon.c (main): New option --daemon so that the program is - not accidently started in the background. - -2002-08-16 Werner Koch - - * scdaemon.c: Include i18n.h. - - * card-common.h (struct p15_private_s): Forward declaration. Add - it to card_ctx_s. - * card.c (card_close): Make sure private data is released. - (card_enum_certs): New. - * card-p15.c (p15_release_private_data): New. - (init_private_data): New to work around an OpenSC weirdness. - (p15_enum_keypairs): Do an OpenSC get_objects only once. - (p15_enum_certs): New. - (card_p15_bind): Bind new function. - * command.c (cmd_learn): Return information about the certificates. - -2002-08-09 Werner Koch - - * card.c (card_get_serial_and_stamp): Use the tokeinfo serial - number as a fallback. Add a special prefix for serial numbers. - -2002-07-30 Werner Koch - - Changes to cope with OpenSC 0.7.0: - - * card.c: Removed the check for the packed opensc version. - Changed include file names of opensc. - (map_sc_err): Adjusted error codes for new opensc version. - * card-p15.c: Changed include filename of opensc. - * card-dinsig.c: Ditto. - - * card-p15.c (p15_decipher): Add flags argument to OpenSC call. - -2002-07-24 Werner Koch - - * card.c (find_simple_tlv, find_iccsn): New. - (card_get_serial_and_stamp): Improved serial number parser. - -2002-06-27 Werner Koch - - * scdaemon.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. - -2002-06-15 Werner Koch - - * card-dinsig.c: Documented some stuff from the DIN norm. - -2002-04-15 Werner Koch - - * command.c (cmd_pksign, cmd_pkdecrypt): Use a copy of the key ID. - -2002-04-12 Werner Koch - - * scdaemon.c: New option --debug-sc N. - * card.c (card_open): set it here. - - * card-p15.c (p15_prepare_key): Factored out common code from ... - (p15_sign, p15_decipher): here and made the decryption work the - regular way. - -2002-04-10 Werner Koch - - * card.c (card_open): Return immediately when no reader is available. - -2002-03-27 Werner Koch - - * card.c (card_open, card_close): Adjusted for changes in OpenSC. - -2002-03-10 Werner Koch - - * card-p15.c, card-dinsig.c, card-common.h: New. - * card.c: Factored most code out to the new modules, so that we - can better support different types of card applications. - -2002-01-26 Werner Koch - - * scdaemon.c scdaemon.h, command.c: New. Based on the code from - the gpg-agent. - - 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. diff --git a/scd/Makefile.am b/scd/Makefile.am deleted file mode 100644 index 8812d1b9a..000000000 --- a/scd/Makefile.am +++ /dev/null @@ -1,42 +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 - -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - -bin_PROGRAMS = scdaemon - -AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ - $(KSBA_CFLAGS) -LDFLAGS = @LDFLAGS@ - -scdaemon_SOURCES = \ - scdaemon.c scdaemon.h \ - command.c card.c \ - card-common.h \ - card-p15.c card-dinsig.c - -scdaemon_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \ - ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) - - - - diff --git a/scd/card-common.h b/scd/card-common.h deleted file mode 100644 index 50014cead..000000000 --- a/scd/card-common.h +++ /dev/null @@ -1,73 +0,0 @@ -/* card-common.h - Common declarations for all card types - * 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 - */ - -#ifndef CARD_COMMON_H -#define CARD_COMMON_H - -/* Declaration of private data structure used by card-p15.c */ -struct p15private_s; - - -struct card_ctx_s { - int reader; /* used reader */ - struct sc_context *ctx; - struct sc_card *scard; - struct sc_pkcs15_card *p15card; /* only if there is a pkcs15 application */ - struct p15private_s *p15priv; /* private data used by card-p15.c */ - - struct { - int initialized; /* the card has been initialied and the function - pointers may be used. However for - unsupported operations the particular - function pointer is set to NULL */ - - int (*enum_keypairs) (CARD card, int idx, - unsigned char *keygrip, char **keyid); - int (*enum_certs) (CARD card, int idx, char **certid, int *certtype); - int (*read_cert) (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert); - int (*sign) (CARD card, - const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ); - int (*decipher) (CARD card, const char *keyidstr, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen); - } fnc; - -}; - -/*-- card.c --*/ -int map_sc_err (int rc); -int card_help_get_keygrip (KsbaCert cert, unsigned char *array); - -/*-- card-15.c --*/ -void p15_release_private_data (CARD card); - -/* constructors */ -void card_p15_bind (CARD card); -void card_dinsig_bind (CARD card); - - -#endif /*CARD_COMMON_H*/ diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c deleted file mode 100644 index 161d5dbfc..000000000 --- a/scd/card-dinsig.c +++ /dev/null @@ -1,256 +0,0 @@ -/* card-dinsig.c - German signature law (DINSIG) functions - * 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 - */ - -/* The German signature law and its bylaw (SigG and SigV) is currently - used with an interface specification described in DIN V 66291-1. - The AID to be used is: 'D27600006601'. - - The file IDs for certificates utilize the generic format: - Cxyz - C being the hex digit 'C' (12). - x being the service indicator: - '0' := SigG conform digital signature. - '1' := entity authentication. - '2' := key encipherment. - '3' := data encipherment. - '4' := key agreement. - other values are reserved for future use. - y being the security environment number using '0' for cards - not supporting a SE number. - z being the certificate type: - '0' := C.CH (base certificate of ard holder) or C.ICC. - '1' .. '7' := C.CH (business or professional certificate - of card holder. - '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA). - 'E' := C.RCA (self certified certificate of the Root-CA). - 'F' := reserved. - - The file IDs used by default are: - '1F00' EF.SSD (security service descriptor). [o,o] - '2F02' EF.GDO (global data objects) [m,m] - 'A000' EF.PROT (signature log). Cyclic file with 20 records of 53 byte. - Read and update after user authentication. [o,o] - 'B000' EF.PK.RCA.DS (public keys of Root-CA). Size is 512b or size - of keys. [m (unless a 'C00E' is present),m] - 'B001' EF.PK.CA.DS (public keys of CAs). Size is 512b or size - of keys. [o,o] - 'C00n' EF.C.CH.DS (digital signature certificate of card holder) - with n := 0 .. 7. Size is 2k or size of cert. Read and - update allowed after user authentication. [m,m] - 'C00m' EF.C.CA.DS (digital signature certificate of CA) - with m := 8 .. E. Size is 1k or size of cert. Read always - allowed, update after uder authentication. [o,o] - 'C100' EF.C.ICC.AUT (AUT certificate of ICC) [o,m] - 'C108' EF.C.CA.AUT (AUT certificate of CA) [o,m] - 'D000' EF.DM (display message) [-,m] - - The letters in brackets indicate optional or mandatory files: The - first for card terminals under full control and the second for - "business" card terminals. - - FIXME: Needs a lot more explanation. - -*/ - - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "scdaemon.h" -#include "card-common.h" - -static int dinsig_read_cert (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert); - - - -/* See card.c for interface description. Frankly we don't do any real - enumeration but just check whether the well know files are - available. */ -static int -dinsig_enum_keypairs (CARD card, int idx, - unsigned char *keygrip, char **keyid) -{ - int rc; - unsigned char *buf; - size_t buflen; - KsbaError krc; - KsbaCert cert; - - /* fixme: We should locate the application via the EF(DIR) and not - assume a Netkey card */ - if (!idx) - rc = dinsig_read_cert (card, "DINSIG-DF01.C000", &buf, &buflen); - else if (idx == 1) - rc = dinsig_read_cert (card, "DINSIG-DF01.C200", &buf, &buflen); - else - rc = -1; - if (rc) - return rc; - - cert = ksba_cert_new (); - if (!cert) - { - xfree (buf); - return GNUPG_Out_Of_Core; - } - - krc = ksba_cert_init_from_mem (cert, buf, buflen); - xfree (buf); - if (krc) - { - log_error ("failed to parse the certificate at idx %d: %s\n", - idx, ksba_strerror (krc)); - ksba_cert_release (cert); - return GNUPG_Card_Error; - } - if (card_help_get_keygrip (cert, keygrip)) - { - log_error ("failed to calculate the keygrip at index %d\n", idx); - ksba_cert_release (cert); - return GNUPG_Card_Error; - } - ksba_cert_release (cert); - - /* return the iD */ - if (keyid) - { - *keyid = xtrymalloc (17); - if (!*keyid) - return GNUPG_Out_Of_Core; - if (!idx) - strcpy (*keyid, "DINSIG-DF01.C000"); - else - strcpy (*keyid, "DINSIG-DF01.C200"); - } - - return 0; -} - - - -/* See card.c for interface description */ -static int -dinsig_read_cert (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert) -{ - int rc; - struct sc_path path; - struct sc_file *file; - unsigned char *buf; - int buflen; - - if (!strcmp (certidstr, "DINSIG-DF01.C000")) - sc_format_path ("3F00DF01C000", &path); - else if (!strcmp (certidstr, "DINSIG-DF01.C200")) - sc_format_path ("3F00DF01C200", &path); - else - return GNUPG_Invalid_Id; - - rc = sc_select_file (card->scard, &path, &file); - if (rc) - { - log_error ("sc_select_file failed: %s\n", sc_strerror (rc)); - return map_sc_err (rc); - } - if (file->type != SC_FILE_TYPE_WORKING_EF - || file->ef_structure != SC_FILE_EF_TRANSPARENT) - { - log_error ("wrong type or structure of certificate EF\n"); - sc_file_free (file); - return GNUPG_Card_Error; - } - if (file->size < 20) /* check against a somewhat arbitrary length */ - { - log_error ("certificate EF too short\n"); - sc_file_free (file); - return GNUPG_Card_Error; - } - buf = xtrymalloc (file->size); - if (!buf) - { - sc_file_free (file); - return GNUPG_Out_Of_Core; - } - - rc = sc_read_binary (card->scard, 0, buf, file->size, 0); - if (rc >= 0 && rc != file->size) - { - log_error ("short read on certificate EF\n"); - sc_file_free (file); - xfree (buf); - return GNUPG_Card_Error; - } - sc_file_free (file); - if (rc < 0) - { - log_error ("error reading certificate EF: %s\n", sc_strerror (rc)); - xfree (buf); - return map_sc_err (rc); - } - buflen = rc; - - /* The object is not a plain certificate but wrapped into id-at - userCertificate - fixme: we should check the specs and decided - whether libksba should support it */ - if (buflen > 9 && buf[0] == 0x30 && buf[4] == 6 && buf[5] == 3 - && buf[6] == 0x55 && buf[7] == 4 && buf[8] == 0x24) - { - /* We have to strip the padding. Although this is a good idea - anyway, we have to do it due to a KSBA problem; KSBA does not - work correct when the buffer is larger than the ASN.1 - structure and the certificates here are padded with FF. So - as a workaround we look at the outer structure to get the - size of the entire thing and adjust the buflen. We can only - do this when there is a 2 byte length field */ - size_t seqlen; - if (buf[1] == 0x82) - { - seqlen = ((buf[2] << 8) | buf[3]) + 4; - if (seqlen < buflen) - buflen = seqlen; - } - memmove (buf, buf+9, buflen-9); - buflen -= 9; - } - - *cert = buf; - *ncert = buflen; - return 0; -} - - - - -/* Bind our operations to the card */ -void -card_dinsig_bind (CARD card) -{ - card->fnc.enum_keypairs = dinsig_enum_keypairs; - card->fnc.read_cert = dinsig_read_cert; - -} diff --git a/scd/card-p15.c b/scd/card-p15.c deleted file mode 100644 index 25502a610..000000000 --- a/scd/card-p15.c +++ /dev/null @@ -1,498 +0,0 @@ -/* card-p15.c - PKCS-15 based card access - * 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 - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "scdaemon.h" -#include "card-common.h" - - -struct p15private_s { - int n_prkey_rsa_objs; - struct sc_pkcs15_object *prkey_rsa_objs[32]; - int n_cert_objs; - struct sc_pkcs15_object *cert_objs[32]; -}; - - -/* Allocate private data. */ -static int -init_private_data (CARD card) -{ - struct p15private_s *priv; - int rc; - - if (card->p15priv) - return 0; /* already done. */ - - priv = xtrycalloc (1, sizeof *priv); - if (!priv) - return GNUPG_Out_Of_Core; - - /* OpenSC (0.7.0) is a bit strange in that the get_objects functions - tries to be a bit too clever and implicitly does an enumeration - which eventually leads to the fact that every call to this - fucntion returns one more macthing object. The old code in - p15_enum_keypairs assume that it would alwyas return the same - numer of objects and used this to figure out what the last object - enumerated is. We now do an enum_objects just once and keep it - in the private data. */ - rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, - priv->prkey_rsa_objs, - DIM (priv->prkey_rsa_objs)); - if (rc < 0) - { - log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); - xfree (priv); - return GNUPG_Card_Error; - } - priv->n_prkey_rsa_objs = rc; - - /* Read all certificate objects. */ - rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509, - priv->cert_objs, - DIM (priv->cert_objs)); - if (rc < 0) - { - log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); - xfree (priv); - return GNUPG_Card_Error; - } - priv->n_cert_objs = rc; - - card->p15priv = priv; - return 0; -} - - -/* Release private data used in this module. */ -void -p15_release_private_data (CARD card) -{ - if (!card->p15priv) - return; - xfree (card->p15priv); - card->p15priv = NULL; -} - - - -/* See card.c for interface description */ -static int -p15_enum_keypairs (CARD card, int idx, - unsigned char *keygrip, char **keyid) -{ - int rc; - KsbaError krc; - struct p15private_s *priv; - struct sc_pkcs15_object *tmpobj; - int nobjs; - struct sc_pkcs15_prkey_info *pinfo; - struct sc_pkcs15_cert_info *certinfo; - struct sc_pkcs15_cert *certder; - KsbaCert cert; - - rc = init_private_data (card); - if (rc) - return rc; - priv = card->p15priv; - nobjs = priv->n_prkey_rsa_objs; - rc = 0; - if (idx >= nobjs) - return -1; - pinfo = priv->prkey_rsa_objs[idx]->data; - - /* now we need to read the certificate so that we can calculate the - keygrip */ - rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj); - if (rc) - { - log_info ("certificate for private key %d not found: %s\n", - idx, sc_strerror (rc)); - /* note, that we return the ID anyway */ - rc = GNUPG_Missing_Certificate; - goto return_keyid; - } - certinfo = tmpobj->data; - rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder); - if (rc) - { - log_info ("failed to read certificate for private key %d: %s\n", - idx, sc_strerror (rc)); - return GNUPG_Card_Error; - } - - cert = ksba_cert_new (); - if (!cert) - { - sc_pkcs15_free_certificate (certder); - return GNUPG_Out_Of_Core; - } - krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len); - sc_pkcs15_free_certificate (certder); - if (krc) - { - log_error ("failed to parse the certificate for private key %d: %s\n", - idx, ksba_strerror (krc)); - ksba_cert_release (cert); - return GNUPG_Card_Error; - } - if (card_help_get_keygrip (cert, keygrip)) - { - log_error ("failed to calculate the keygrip of private key %d\n", idx); - ksba_cert_release (cert); - return GNUPG_Card_Error; - } - ksba_cert_release (cert); - - rc = 0; - return_keyid: - if (keyid) - { - char *p; - int i; - - *keyid = p = xtrymalloc (9+pinfo->id.len*2+1); - if (!*keyid) - return GNUPG_Out_Of_Core; - p = stpcpy (p, "P15-5015."); - for (i=0; i < pinfo->id.len; i++, p += 2) - sprintf (p, "%02X", pinfo->id.value[i]); - *p = 0; - } - - return rc; -} - -/* See card.c for interface description */ -static int -p15_enum_certs (CARD card, int idx, char **certid, int *type) -{ - int rc; - struct p15private_s *priv; - struct sc_pkcs15_object *obj; - struct sc_pkcs15_cert_info *cinfo; - int nobjs; - - rc = init_private_data (card); - if (rc) - return rc; - priv = card->p15priv; - nobjs = priv->n_cert_objs; - rc = 0; - if (idx >= nobjs) - return -1; - obj = priv->cert_objs[idx]; - cinfo = obj->data; - - if (certid) - { - char *p; - int i; - - *certid = p = xtrymalloc (9+cinfo->id.len*2+1); - if (!*certid) - return GNUPG_Out_Of_Core; - p = stpcpy (p, "P15-5015."); - for (i=0; i < cinfo->id.len; i++, p += 2) - sprintf (p, "%02X", cinfo->id.value[i]); - *p = 0; - } - if (type) - { - if (!obj->df) - *type = 0; /* unknown */ - else if (obj->df->type == SC_PKCS15_CDF) - *type = 100; - else if (obj->df->type == SC_PKCS15_CDF_TRUSTED) - *type = 101; - else if (obj->df->type == SC_PKCS15_CDF_USEFUL) - *type = 102; - else - *type = 0; /* error -> unknown */ - } - - return rc; -} - - - -static int -idstr_to_id (const char *idstr, struct sc_pkcs15_id *id) -{ - const char *s; - int n; - - /* For now we only support the standard DF */ - if (strncmp (idstr, "P15-5015.", 9) ) - return GNUPG_Invalid_Id; - for (s=idstr+9, n=0; hexdigitp (s); s++, n++) - ; - if (*s || (n&1)) - return GNUPG_Invalid_Id; /* invalid or odd number of digits */ - n /= 2; - if (!n || n > SC_PKCS15_MAX_ID_SIZE) - return GNUPG_Invalid_Id; /* empty or too large */ - for (s=idstr+9, n=0; *s; s += 2, n++) - id->value[n] = xtoi_2 (s); - id->len = n; - return 0; -} - - -/* See card.c for interface description */ -static int -p15_read_cert (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert) -{ - struct sc_pkcs15_object *tmpobj; - struct sc_pkcs15_id certid; - struct sc_pkcs15_cert_info *certinfo; - struct sc_pkcs15_cert *certder; - int rc; - - if (!card || !certidstr || !cert || !ncert) - return GNUPG_Invalid_Value; - if (!card->p15card) - return GNUPG_No_PKCS15_App; - - rc = idstr_to_id (certidstr, &certid); - if (rc) - return rc; - - rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj); - if (rc) - { - log_info ("certificate '%s' not found: %s\n", - certidstr, sc_strerror (rc)); - return -1; - } - certinfo = tmpobj->data; - rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder); - if (rc) - { - log_info ("failed to read certificate '%s': %s\n", - certidstr, sc_strerror (rc)); - return GNUPG_Card_Error; - } - - *cert = xtrymalloc (certder->data_len); - if (!*cert) - { - sc_pkcs15_free_certificate (certder); - return GNUPG_Out_Of_Core; - } - memcpy (*cert, certder->data, certder->data_len); - *ncert = certder->data_len; - sc_pkcs15_free_certificate (certder); - return 0; -} - - - - - -static int -p15_prepare_key (CARD card, const char *keyidstr, - int (pincb)(void*, const char *, char **), - void *pincb_arg, struct sc_pkcs15_object **r_keyobj) -{ - struct sc_pkcs15_id keyid; - struct sc_pkcs15_pin_info *pin; - struct sc_pkcs15_object *keyobj, *pinobj; - char *pinvalue; - int rc; - - rc = idstr_to_id (keyidstr, &keyid); - if (rc) - return rc; - - rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj); - if (rc < 0) - { - log_error ("private key not found: %s\n", sc_strerror(rc)); - return GNUPG_No_Secret_Key; - } - - rc = sc_pkcs15_find_pin_by_auth_id (card->p15card, - &keyobj->auth_id, &pinobj); - if (rc) - { - log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc)); - return GNUPG_Bad_PIN_Method; - } - pin = pinobj->data; - - /* Fixme: pack this into a verification loop */ - /* Fixme: we might want to pass pin->min_length and - pin->stored_length */ - rc = pincb (pincb_arg, pinobj->label, &pinvalue); - if (rc) - { - log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc)); - return rc; - } - - rc = sc_pkcs15_verify_pin (card->p15card, pin, - pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_info ("PIN verification failed: %s\n", sc_strerror (rc)); - return GNUPG_Bad_PIN; - } - - /* fixme: check wheter we need to release KEYOBJ in case of an error */ - *r_keyobj = keyobj; - return 0; -} - - -/* See card.c for interface description */ -static int -p15_sign (CARD card, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ) -{ - unsigned int cryptflags; - struct sc_pkcs15_object *keyobj; - int rc; - unsigned char *outbuf = NULL; - size_t outbuflen; - - if (hashalgo != GCRY_MD_SHA1) - return GNUPG_Unsupported_Algorithm; - - rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj); - if (rc) - return rc; - - cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1; - - outbuflen = 1024; - outbuf = xtrymalloc (outbuflen); - if (!outbuf) - return GNUPG_Out_Of_Core; - - rc = sc_pkcs15_compute_signature (card->p15card, keyobj, - cryptflags, - indata, indatalen, - outbuf, outbuflen ); - if (rc < 0) - { - log_error ("failed to create signature: %s\n", sc_strerror (rc)); - rc = GNUPG_Card_Error; - } - else - { - *outdatalen = rc; - *outdata = outbuf; - outbuf = NULL; - rc = 0; - } - - xfree (outbuf); - return rc; -} - - -/* See card.c for description */ -static int -p15_decipher (CARD card, const char *keyidstr, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ) -{ - struct sc_pkcs15_object *keyobj; - int rc; - unsigned char *outbuf = NULL; - size_t outbuflen; - - rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj); - if (rc) - return rc; - - if (card && card->scard && card->scard->driver - && !strcasecmp (card->scard->driver->short_name, "tcos")) - { - /* very ugly hack to force the use of a local key. We need this - until we have fixed the initialization code for TCOS cards */ - struct sc_pkcs15_prkey_info *prkey = keyobj->data; - if ( !(prkey->key_reference & 0x80)) - { - prkey->key_reference |= 0x80; - log_debug ("using TCOS hack to force the use of local keys\n"); - } - if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6') - { - prkey->key_reference |= 1; - log_debug ("warning: using even more TCOS hacks\n"); - } - } - - outbuflen = indatalen < 256? 256 : indatalen; - outbuf = xtrymalloc (outbuflen); - if (!outbuf) - return GNUPG_Out_Of_Core; - - rc = sc_pkcs15_decipher (card->p15card, keyobj, - 0, - indata, indatalen, - outbuf, outbuflen); - if (rc < 0) - { - log_error ("failed to decipher the data: %s\n", sc_strerror (rc)); - rc = GNUPG_Card_Error; - } - else - { - *outdatalen = rc; - *outdata = outbuf; - outbuf = NULL; - rc = 0; - } - - xfree (outbuf); - return rc; -} - - - -/* Bind our operations to the card */ -void -card_p15_bind (CARD card) -{ - card->fnc.enum_keypairs = p15_enum_keypairs; - card->fnc.enum_certs = p15_enum_certs; - card->fnc.read_cert = p15_read_cert; - card->fnc.sign = p15_sign; - card->fnc.decipher = p15_decipher; -} diff --git a/scd/card.c b/scd/card.c deleted file mode 100644 index 9e0f060e5..000000000 --- a/scd/card.c +++ /dev/null @@ -1,540 +0,0 @@ -/* card.c - SCdaemon card functions - * 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 - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "scdaemon.h" -#include "card-common.h" - -/* Map the SC error codes to the GNUPG ones */ -int -map_sc_err (int rc) -{ - switch (rc) - { - case 0: rc = 0; break; - case SC_ERROR_NOT_SUPPORTED: rc = GNUPG_Not_Supported; break; - case SC_ERROR_PKCS15_APP_NOT_FOUND: rc = GNUPG_No_PKCS15_App; break; - case SC_ERROR_OUT_OF_MEMORY: rc = GNUPG_Out_Of_Core; break; - case SC_ERROR_CARD_NOT_PRESENT: rc = GNUPG_Card_Not_Present; break; - case SC_ERROR_CARD_REMOVED: rc = GNUPG_Card_Removed; break; - case SC_ERROR_INVALID_CARD: rc = GNUPG_Invalid_Card; break; - default: rc = GNUPG_Card_Error; break; - } - return rc; -} - -/* Get the keygrip from CERT, return 0 on success */ -int -card_help_get_keygrip (KsbaCert cert, unsigned char *array) -{ - GCRY_SEXP s_pkey; - int rc; - KsbaSexp p; - size_t n; - - p = ksba_cert_get_public_key (cert); - if (!p) - return -1; /* oops */ - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - if (!n) - return -1; /* libksba did not return a proper S-expression */ - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); - xfree (p); - if (rc) - return -1; /* can't parse that S-expression */ - array = gcry_pk_get_keygrip (s_pkey, array); - gcry_sexp_release (s_pkey); - if (!array) - return -1; /* failed to calculate the keygrip */ - return 0; -} - - - - - - - -/* Create a new context for the card and figures out some basic - information of the card. Detects whgether a PKCS_15 application is - stored. - - Common errors: GNUPG_Card_Not_Present */ -int -card_open (CARD *rcard) -{ - CARD card; - int rc; - - card = xtrycalloc (1, sizeof *card); - if (!card) - return GNUPG_Out_Of_Core; - card->reader = 0; - - rc = sc_establish_context (&card->ctx, "scdaemon"); - if (rc) - { - log_error ("failed to establish SC context: %s\n", sc_strerror (rc)); - rc = map_sc_err (rc); - goto leave; - } - if (card->reader >= card->ctx->reader_count) - { - log_error ("no card reader available\n"); - rc = GNUPG_Card_Error; - goto leave; - } - card->ctx->error_file = log_get_stream (); - card->ctx->debug = opt.debug_sc; - card->ctx->debug_file = log_get_stream (); - - if (sc_detect_card_presence (card->ctx->reader[card->reader], 0) != 1) - { - rc = GNUPG_Card_Not_Present; - goto leave; - } - - rc = sc_connect_card (card->ctx->reader[card->reader], 0, &card->scard); - if (rc) - { - log_error ("failed to connect card in reader %d: %s\n", - card->reader, sc_strerror (rc)); - rc = map_sc_err (rc); - goto leave; - } - if (opt.verbose) - log_info ("connected to card in reader %d using driver `%s'\n", - card->reader, card->scard->driver->name); - - rc = sc_lock (card->scard); - if (rc) - { - log_error ("can't lock card in reader %d: %s\n", - card->reader, sc_strerror (rc)); - rc = map_sc_err (rc); - goto leave; - } - - - leave: - if (rc) - card_close (card); - else - *rcard = card; - return rc; -} - - -/* Close a card and release all resources */ -void -card_close (CARD card) -{ - if (card) - { - if (card->p15card) - { - sc_pkcs15_unbind (card->p15card); - card->p15card = NULL; - } - if (card->p15priv) - p15_release_private_data (card); - if (card->scard) - { - sc_unlock (card->scard); - sc_disconnect_card (card->scard, 0); - card->scard = NULL; - } - if (card->ctx) - { - sc_release_context (card->ctx); - card->ctx = NULL; - } - xfree (card); - } -} - -/* Locate a simple TLV encoded data object in BUFFER of LENGTH and - return a pointer to value as well as its length in NBYTES. Return - NULL if it was not found. Note, that the function does not check - whether the value fits into the provided buffer. */ -static const char * -find_simple_tlv (const unsigned char *buffer, size_t length, - int tag, size_t *nbytes) -{ - const char *s = buffer; - size_t n = length; - size_t len; - - for (;;) - { - buffer = s; - if (n < 2) - return NULL; /* buffer too short for tag and length. */ - len = s[1]; - s += 2; n -= 2; - if (len == 255) - { - if (n < 2) - return NULL; /* we expected 2 more bytes with the length. */ - len = (s[0] << 8) | s[1]; - s += 2; n -= 2; - } - if (*buffer == tag) - { - *nbytes = len; - return s; - } - if (len > n) - return NULL; /* buffer too short to skip to the next tag. */ - s += len; n -= len; - } -} - -/* Find the ICC Serial Number within the provided BUFFER of LENGTH - (which should contain the GDO file) and return it as a hex encoded - string and allocated string in SERIAL. Return an error code when - the ICCSN was not found. */ -static int -find_iccsn (const unsigned char *buffer, size_t length, char **serial) -{ - size_t n; - const unsigned char *s; - char *p; - - s = find_simple_tlv (buffer, length, 0x5A, &n); - if (!s) - return GNUPG_Card_Error; - length -= s - buffer; - if (n > length) - { - /* Oops, it does not fit into the buffer. This is an invalid - encoding (or the buffer is too short. However, I have some - test cards with such an invalid encoding and therefore I use - this ugly workaround to return something I can further - experiment with. */ - if (n == 0x0D && length+1 == n) - { - log_debug ("enabling BMI testcard workaround\n"); - n--; - } - else - return GNUPG_Card_Error; /* Bad encoding; does not fit into buffer. */ - } - if (!n) - return GNUPG_Card_Error; /* Well, that is too short. */ - - *serial = p = xtrymalloc (2*n+1); - if (!*serial) - return GNUPG_Out_Of_Core; - for (; n; n--, p += 2, s++) - sprintf (p, "%02X", *s); - *p = 0; - return 0; -} - - -/* Retrieve the serial number and the time of the last update of the - card. The serial number is returned as a malloced string (hex - encoded) in SERIAL and the time of update is returned in STAMP. - If no update time is available the returned value is 0. The serial - is mandatory for a PKCS_15 application and an error will be - returned if this value is not availbale. For non-PKCS-15 cards a - serial number is constructed by other means. Caller must free - SERIAL unless the function returns an error. */ -int -card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp) -{ - int rc; - struct sc_path path; - struct sc_file *file; - unsigned char buf[256]; - int buflen; - - if (!card || !serial || !stamp) - return GNUPG_Invalid_Value; - - *serial = NULL; - *stamp = 0; /* not available */ - - if (!card->fnc.initialized) - { - card->fnc.initialized = 1; - /* The first use of this card tries to figure out the type of the card - and sets up the function pointers. */ - rc = sc_pkcs15_bind (card->scard, &card->p15card); - if (rc) - { - if (rc != SC_ERROR_PKCS15_APP_NOT_FOUND) - log_error ("binding of existing PKCS-15 failed in reader %d: %s\n", - card->reader, sc_strerror (rc)); - card->p15card = NULL; - rc = 0; - } - if (card->p15card) - card_p15_bind (card); - else - card_dinsig_bind (card); - card->fnc.initialized = 1; - } - - - /* We should lookup the iso 7812-1 and 8583-3 - argh ISO - practice is suppressing innovation - IETF rules! So we - always get the serialnumber from the 2F02 GDO file. */ - /* FIXME: in case we can't parse the 2F02 EF and we have a P15 card, - we should get the serial number from the respective P15 file */ - sc_format_path ("3F002F02", &path); - rc = sc_select_file (card->scard, &path, &file); - if (rc) - { - log_error ("sc_select_file failed: %s\n", sc_strerror (rc)); - return GNUPG_Card_Error; - } - if (file->type != SC_FILE_TYPE_WORKING_EF - || file->ef_structure != SC_FILE_EF_TRANSPARENT) - { - log_error ("wrong type or structure of GDO file\n"); - sc_file_free (file); - return GNUPG_Card_Error; - } - - if (!file->size || file->size >= DIM(buf) ) - { /* FIXME: Use a real parser */ - log_error ("unsupported size of GDO file (%d)\n", file->size); - sc_file_free (file); - return GNUPG_Card_Error; - } - buflen = file->size; - - rc = sc_read_binary (card->scard, 0, buf, buflen, 0); - sc_file_free (file); - if (rc < 0) - { - log_error ("error reading GDO file: %s\n", sc_strerror (rc)); - return GNUPG_Card_Error; - } - if (rc != buflen) - { - log_error ("short read on GDO file\n"); - return GNUPG_Card_Error; - } - - rc = find_iccsn (buf, buflen, serial); - if (rc == GNUPG_Card_Error) - log_error ("invalid structure of GDO file\n"); - if (!rc && card->p15card && !strcmp (*serial, "D27600000000000000000000")) - { /* This is a German card with a silly serial number. Try to get - the serial number from the EF(TokenInfo). We indicate such a - serial number by the using the prefix: "FF0100". */ - const char *efser = card->p15card->serial_number; - char *p; - - if (!efser) - efser = ""; - - xfree (*serial); - *serial = NULL; - p = xtrymalloc (strlen (efser) + 7); - if (!p) - rc = GNUPG_Out_Of_Core; - else - { - strcpy (p, "FF0100"); - strcpy (p+6, efser); - *serial = p; - } - } - else if (!rc && **serial == 'F' && (*serial)[1] == 'F') - { /* The serial number starts with our special prefix. This - requires that we put our default prefix "FF0000" in front. */ - char *p = xtrymalloc (strlen (*serial) + 7); - if (!p) - { - xfree (*serial); - *serial = NULL; - rc = GNUPG_Out_Of_Core; - } - else - { - strcpy (p, "FF0000"); - strcpy (p+6, *serial); - xfree (*serial); - *serial = p; - } - } - return rc; -} - - -/* Enumerate all keypairs on the card and return the Keygrip as well - as the internal identification of the key. KEYGRIP must be a - caller provided buffer with a size of 20 bytes which will receive - the KEYGRIP of the keypair. If KEYID is not NULL, it returns the - ID field of the key in allocated memory; this is a string without - spaces. The function returns -1 when all keys have been - enumerated. Note that the error GNUPG_Missing_Certificate may be - returned if there is just the private key but no public key (ie.e a - certificate) available. Applications might want to continue - enumerating after this error.*/ -int -card_enum_keypairs (CARD card, int idx, - unsigned char *keygrip, - char **keyid) -{ - int rc; - - if (keyid) - *keyid = NULL; - - if (!card || !keygrip) - return GNUPG_Invalid_Value; - if (idx < 0) - return GNUPG_Invalid_Index; - if (!card->fnc.initialized) - return GNUPG_Card_Not_Initialized; - if (!card->fnc.enum_keypairs) - return GNUPG_Unsupported_Operation; - rc = card->fnc.enum_keypairs (card, idx, keygrip, keyid); - if (opt.verbose) - log_info ("card operation enum_keypairs result: %s\n", - gnupg_strerror (rc)); - return rc; -} - - -/* Enumerate all trusted certificates available on the card, return - their ID in CERT and the type in CERTTYPE. Types of certificates - are: - 0 := Unknown - 100 := Regular X.509 cert - 101 := Trusted X.509 cert - 102 := Useful X.509 cert - */ -int -card_enum_certs (CARD card, int idx, char **certid, int *certtype) -{ - int rc; - - if (certid) - *certid = NULL; - - if (!card) - return GNUPG_Invalid_Value; - if (idx < 0) - return GNUPG_Invalid_Index; - if (!card->fnc.initialized) - return GNUPG_Card_Not_Initialized; - if (!card->fnc.enum_certs) - return GNUPG_Unsupported_Operation; - rc = card->fnc.enum_certs (card, idx, certid, certtype); - if (opt.verbose) - log_info ("card operation enum_certs result: %s\n", - gnupg_strerror (rc)); - return rc; -} - - - -/* Read the certificate identified by CERTIDSTR which is the - hexadecimal encoded ID of the certificate, prefixed with the string - "3F005015.". The certificate is return in DER encoded form in CERT - and NCERT. */ -int -card_read_cert (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert) -{ - int rc; - - if (!card || !certidstr || !cert || !ncert) - return GNUPG_Invalid_Value; - if (!card->fnc.initialized) - return GNUPG_Card_Not_Initialized; - if (!card->fnc.read_cert) - return GNUPG_Unsupported_Operation; - rc = card->fnc.read_cert (card, certidstr, cert, ncert); - if (opt.verbose) - log_info ("card operation read_cert result: %s\n", gnupg_strerror (rc)); - return rc; -} - - -/* Create the signature and return the allocated result in OUTDATA. - If a PIN is required the PINCB will be used to ask for the PIN; it - should return the PIN in an allocated buffer and put it into PIN. */ -int -card_sign (CARD card, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ) -{ - int rc; - - if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) - return GNUPG_Invalid_Value; - if (!card->fnc.initialized) - return GNUPG_Card_Not_Initialized; - if (!card->fnc.sign) - return GNUPG_Unsupported_Operation; - rc = card->fnc.sign (card, keyidstr, hashalgo, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); - if (opt.verbose) - log_info ("card operation sign result: %s\n", gnupg_strerror (rc)); - return rc; -} - - -/* Create the signature and return the allocated result in OUTDATA. - If a PIN is required the PINCB will be used to ask for the PIN; it - should return the PIN in an allocated buffer and put it into PIN. */ -int -card_decipher (CARD card, const char *keyidstr, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ) -{ - int rc; - - if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) - return GNUPG_Invalid_Value; - if (!card->fnc.initialized) - return GNUPG_Card_Not_Initialized; - if (!card->fnc.decipher) - return GNUPG_Unsupported_Operation; - rc = card->fnc.decipher (card, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); - if (opt.verbose) - log_info ("card operation decipher result: %s\n", gnupg_strerror (rc)); - return rc; -} diff --git a/scd/command.c b/scd/command.c deleted file mode 100644 index aa410a6ee..000000000 --- a/scd/command.c +++ /dev/null @@ -1,651 +0,0 @@ -/* command.c - SCdaemon command handler - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "scdaemon.h" -#include "../assuan/assuan.h" - -/* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */ -#define MAXLEN_PIN 100 - -#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) - -/* Data used to associate an Assuan context with local server data */ -struct server_local_s { - ASSUAN_CONTEXT assuan_ctx; -}; - - -/* Check whether the option NAME appears in LINE */ -static int -has_option (const char *line, const char *name) -{ - const char *s; - int n = strlen (name); - - s = strstr (line, name); - return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); -} - - - - -/* Note, that this reset_notify is also used for cleanup purposes. */ -static void -reset_notify (ASSUAN_CONTEXT ctx) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - if (ctrl->card_ctx) - { - card_close (ctrl->card_ctx); - ctrl->card_ctx = NULL; - xfree (ctrl->in_data.value); - ctrl->in_data.value = NULL; - } -} - - -static int -option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) -{ - return 0; -} - - -/* If the card has not yet been opened, do it. Note that this - function returns an Assuan error, so don't map the error a second - time */ -static AssuanError -open_card (CTRL ctrl) -{ - if (!ctrl->card_ctx) - { - int rc = card_open (&ctrl->card_ctx); - if (rc) - return map_to_assuan_status (rc); - } - return 0; -} - - -/* SERIALNO - - Return the serial number of the card using a status reponse. This - functon should be used to check for the presence of a card. - - This function is special in that it can be used to reset the card. - Most other functions 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 doneon the same card unless he call this function. - */ -static int -cmd_serialno (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc = 0; - char *serial_and_stamp; - char *serial; - time_t stamp; - - if ((rc = open_card (ctrl))) - return rc; - - rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); - if (rc) - return map_to_assuan_status (rc); - rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); - xfree (serial); - if (rc < 0) - return ASSUAN_Out_Of_Core; - rc = 0; - assuan_write_status (ctx, "SERIALNO", serial_and_stamp); - free (serial_and_stamp); - return 0; -} - - - - -/* LEARN [--force] - - Learn all useful information of the currently inserted card. When - used without the force options, the command might do an INQUIRE - like this: - - INQUIRE KNOWNCARDP - - The client should just send an "END" if the processing should go on - or a "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: - - S KEYPAIRINFO - - If there is no certificate yet stored on the card a single "X" is - returned as the keygrip. In addition to the keypair info, information - about all certificates stored on the card is also returned: - - S CERTINFO - - Where CERTINFO is a number indicating the type of certificate: - 0 := Unknown - 100 := Regular X.509 cert - 101 := Trusted X.509 cert - 102 := Useful X.509 cert - - -*/ -static int -cmd_learn (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc = 0; - int idx; - - if ((rc = open_card (ctrl))) - return rc; - - /* Unless the force option is used we try a shortcut by identifying - the card using a serial number and inquiring the client with - that. The client may choose to cancel the operation if he already - knows about this card */ - { - char *serial_and_stamp; - char *serial; - time_t stamp; - - rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); - if (rc) - return map_to_assuan_status (rc); - rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); - xfree (serial); - if (rc < 0) - return ASSUAN_Out_Of_Core; - rc = 0; - assuan_write_status (ctx, "SERIALNO", serial_and_stamp); - - if (!has_option (line, "--force")) - { - char *command; - - rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); - if (rc < 0) - { - free (serial_and_stamp); - return ASSUAN_Out_Of_Core; - } - rc = 0; - rc = assuan_inquire (ctx, command, NULL, NULL, 0); - free (command); /* (must use standard free here) */ - if (rc) - { - if (rc != ASSUAN_Canceled) - log_error ("inquire KNOWNCARDP failed: %s\n", - assuan_strerror (rc)); - free (serial_and_stamp); - return rc; - } - /* not canceled, so we have to proceeed */ - } - free (serial_and_stamp); - } - - /* Return information about the certificates. */ - for (idx=0; !rc; idx++) - { - char *certid; - int certtype; - - rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype); - if (!rc) - { - char *buf; - - buf = xtrymalloc (40 + 1 + strlen (certid) + 1); - if (!buf) - rc = GNUPG_Out_Of_Core; - else - { - sprintf (buf, "%d %s", certtype, certid); - assuan_write_status (ctx, "CERTINFO", buf); - xfree (buf); - } - } - xfree (certid); - } - if (rc == -1) - rc = 0; - - - /* Return information about the keys. */ - for (idx=0; !rc; idx++) - { - unsigned char keygrip[20]; - char *keyid; - int no_cert = 0; - - rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid); - if (rc == GNUPG_Missing_Certificate && keyid) - { - /* this does happen with an incomplete personalized - card; i.e. during the time we have stored the key on the - card but not stored the certificate; probably becuase it - has not yet been received back from the CA. Note that we - must release KEYID in this case. */ - rc = 0; - no_cert = 1; - } - if (!rc) - { - char *buf, *p; - - buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1); - if (!buf) - rc = GNUPG_Out_Of_Core; - else - { - int i; - - if (no_cert) - *p++ = 'X'; - else - { - for (i=0; i < 20; i++, p += 2) - sprintf (p, "%02X", keygrip[i]); - } - *p++ = ' '; - strcpy (p, keyid); - assuan_write_status (ctx, "KEYPAIRINFO", buf); - xfree (buf); - } - } - xfree (keyid); - } - if (rc == -1) - rc = 0; - - - return map_to_assuan_status (rc); -} - - - -/* READCERT - - */ -static int -cmd_readcert (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - unsigned char *cert; - size_t ncert; - - if ((rc = open_card (ctrl))) - return rc; - - rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); - if (rc) - { - log_error ("card_read_cert failed: %s\n", gnupg_strerror (rc)); - } - if (!rc) - { - rc = assuan_send_data (ctx, cert, ncert); - xfree (cert); - if (rc) - return rc; - } - - return map_to_assuan_status (rc); -} - - -/* READKEY - - Return the public key for the given cert or key ID as an standard - S-Expression. */ -static int -cmd_readkey (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - unsigned char *cert = NULL; - size_t ncert, n; - KsbaCert kc = NULL; - KsbaSexp p; - - if ((rc = open_card (ctrl))) - return rc; - - rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); - if (rc) - { - log_error ("card_read_cert failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - kc = ksba_cert_new (); - if (!kc) - { - xfree (cert); - rc = GNUPG_Out_Of_Core; - goto leave; - } - rc = ksba_cert_init_from_mem (kc, cert, ncert); - if (rc) - { - log_error ("failed to parse the certificate: %s\n", ksba_strerror (rc)); - rc = map_ksba_err (rc); - goto leave; - } - - p = ksba_cert_get_public_key (kc); - if (!p) - { - rc = GNUPG_No_Public_Key; - goto leave; - } - - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - rc = assuan_send_data (ctx, p, n); - rc = map_assuan_err (rc); - xfree (p); - - - leave: - ksba_cert_release (kc); - xfree (cert); - return map_to_assuan_status (rc); -} - - - - -/* SETDATA - - The client should use this command to tell us the data he want to - sign. */ -static int -cmd_setdata (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int n; - char *p; - unsigned char *buf; - - /* parse the hexstring */ - for (p=line,n=0; hexdigitp (p); p++, n++) - ; - if (*p) - return set_error (Parameter_Error, "invalid hexstring"); - if ((n&1)) - return set_error (Parameter_Error, "odd number of digits"); - n /= 2; - buf = xtrymalloc (n); - if (!buf) - return ASSUAN_Out_Of_Core; - - ctrl->in_data.value = buf; - ctrl->in_data.valuelen = n; - for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++) - buf[n] = xtoi_2 (p); - return 0; -} - - - -static int -pin_cb (void *opaque, const char *info, char **retstr) -{ - ASSUAN_CONTEXT ctx = opaque; - char *command; - int rc; - char *value; - size_t valuelen; - - *retstr = NULL; - log_debug ("asking for PIN '%s'\n", info); - - rc = asprintf (&command, "NEEDPIN %s", info); - if (rc < 0) - return GNUPG_Out_Of_Core; - - /* FIXME: Write an inquire function which returns the result in - secure memory */ - rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); - free (command); - if (rc) - return map_assuan_err (rc); - - if (!valuelen || value[valuelen-1]) - { - /* We require that the returned value is an UTF-8 string */ - xfree (value); - return GNUPG_Invalid_Response; - } - *retstr = value; - return 0; -} - - -/* PKSIGN - - */ -static int -cmd_pksign (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - void *outdata; - size_t outdatalen; - char *keyidstr; - - if ((rc = open_card (ctrl))) - return rc; - - /* We have to use a copy of the key ID because the function may use - the pin_cb which in turn uses the assuan line buffer and thus - overwriting the original line with the keyid */ - keyidstr = strdup (line); - if (!keyidstr) - return ASSUAN_Out_Of_Core; - rc = card_sign (ctrl->card_ctx, - keyidstr, GCRY_MD_SHA1, - pin_cb, ctx, - ctrl->in_data.value, ctrl->in_data.valuelen, - &outdata, &outdatalen); - free (keyidstr); - if (rc) - { - log_error ("card_sign failed: %s\n", gnupg_strerror (rc)); - } - else - { - rc = assuan_send_data (ctx, outdata, outdatalen); - xfree (outdata); - if (rc) - return rc; /* that is already an assuan error code */ - } - - return map_to_assuan_status (rc); -} - -/* PKDECRYPT - - */ -static int -cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - void *outdata; - size_t outdatalen; - char *keyidstr; - - if ((rc = open_card (ctrl))) - return rc; - - keyidstr = strdup (line); - if (!keyidstr) - return ASSUAN_Out_Of_Core; - rc = card_decipher (ctrl->card_ctx, - keyidstr, - pin_cb, ctx, - ctrl->in_data.value, ctrl->in_data.valuelen, - &outdata, &outdatalen); - free (keyidstr); - if (rc) - { - log_error ("card_create_signature failed: %s\n", gnupg_strerror (rc)); - } - else - { - rc = assuan_send_data (ctx, outdata, outdatalen); - xfree (outdata); - if (rc) - return rc; /* that is already an assuan error code */ - } - - return map_to_assuan_status (rc); -} - - - - -/* Tell the assuan library about our commands */ -static int -register_commands (ASSUAN_CONTEXT ctx) -{ - static struct { - const char *name; - int cmd_id; - int (*handler)(ASSUAN_CONTEXT, char *line); - } table[] = { - { "SERIALNO", 0, cmd_serialno }, - { "LEARN", 0, cmd_learn }, - { "READCERT", 0, cmd_readcert }, - { "READKEY", 0, cmd_readkey }, - { "SETDATA", 0, cmd_setdata }, - { "PKSIGN", 0, cmd_pksign }, - { "PKDECRYPT", 0,cmd_pkdecrypt }, - { "", ASSUAN_CMD_INPUT, NULL }, - { "", ASSUAN_CMD_OUTPUT, NULL }, - { NULL } - }; - int i, j, rc; - - for (i=j=0; table[i].name; i++) - { - rc = assuan_register_command (ctx, - table[i].cmd_id? table[i].cmd_id - : (ASSUAN_CMD_USER + j++), - table[i].name, table[i].handler); - if (rc) - return rc; - } - assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready"); - - assuan_register_reset_notify (ctx, reset_notify); - assuan_register_option_handler (ctx, option_handler); - return 0; -} - - -/* Startup the server. If LISTEN_FD is given as -1, this is simple - piper server, otherwise it is a regular server */ -void -scd_command_handler (int listen_fd) -{ - int rc; - ASSUAN_CONTEXT ctx; - struct server_control_s ctrl; - - memset (&ctrl, 0, sizeof ctrl); - scd_init_default_ctrl (&ctrl); - - if (listen_fd == -1) - { - int filedes[2]; - - filedes[0] = 0; - filedes[1] = 1; - rc = assuan_init_pipe_server (&ctx, filedes); - } - else - { - rc = assuan_init_socket_server (&ctx, listen_fd); - } - if (rc) - { - log_error ("failed to initialize the server: %s\n", - assuan_strerror(rc)); - scd_exit (2); - } - rc = register_commands (ctx); - if (rc) - { - log_error ("failed to register commands with Assuan: %s\n", - assuan_strerror(rc)); - scd_exit (2); - } - assuan_set_pointer (ctx, &ctrl); - ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); - ctrl.server_local->assuan_ctx = ctx; - - if (DBG_ASSUAN) - assuan_set_log_stream (ctx, log_get_stream ()); - - for (;;) - { - rc = assuan_accept (ctx); - if (rc == -1) - { - break; - } - else if (rc) - { - log_info ("Assuan accept problem: %s\n", assuan_strerror (rc)); - break; - } - - rc = assuan_process (ctx); - if (rc) - { - log_info ("Assuan processing failed: %s\n", assuan_strerror (rc)); - continue; - } - } - reset_notify (ctx); /* used for cleanup */ - - assuan_deinit_server (ctx); -} diff --git a/scd/scdaemon.c b/scd/scdaemon.c deleted file mode 100644 index b63b59c5b..000000000 --- a/scd/scdaemon.c +++ /dev/null @@ -1,633 +0,0 @@ -/* scdaemon.c - The GnuPG Smartcard Daemon - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define JNLIB_NEED_LOG_LOGV -#include "scdaemon.h" -#include "../assuan/assuan.h" /* malloc hooks */ - -#include "i18n.h" -#include "sysutils.h" - - - -enum cmd_and_opt_values -{ aNull = 0, - oCsh = 'c', - oQuiet = 'q', - oSh = 's', - oVerbose = 'v', - - oNoVerbose = 500, - oOptions, - oDebug, - oDebugAll, - oDebugWait, - oDebugSC, - oNoGreeting, - oNoOptions, - oHomedir, - oNoDetach, - oNoGrab, - oLogFile, - oServer, - oDaemon, - oBatch, - -aTest }; - - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, N_("@Options:\n ") }, - - { oServer, "server", 0, N_("run in server mode (foreground)") }, - { oDaemon, "daemon", 0, N_("run in daemon mode (background)") }, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oSh, "sh", 0, N_("sh-style command output") }, - { oCsh, "csh", 0, N_("csh-style command output") }, - { oOptions, "options" , 2, N_("read options from file")}, - { oDebug, "debug" ,4|16, N_("set debugging flags")}, - { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, - { oDebugWait,"debug-wait",1, "@"}, - { oDebugSC, "debug-sc", 1, N_("|N|set OpenSC debug level to N")}, - { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, - { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - - - {0} -}; - - -static volatile int caught_fatal_sig = 0; - -/* It is possible that we are currently running under setuid permissions */ -static int maybe_setuid = 1; - -/* Name of the communication socket */ -static char socket_name[128]; - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "scdaemon (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: scdaemon [options] (-h for help)"); - break; - case 41: p = _("Syntax: scdaemon [options] [command [args]]\n" - "Smartcard daemon for GnuPG\n"); - break; - - default: p = NULL; - } - return p; -} - - - -static void -i18n_init (void) -{ -#ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); -#else -#ifdef ENABLE_NLS - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -#endif -#endif -} - - - -/* Used by gcry for logging */ -static void -my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) -{ - /* translate the log levels */ - switch (level) - { - case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; - case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; - case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; - case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; - case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; - case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; - case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; - default: level = JNLIB_LOG_ERROR; break; - } - log_logv (level, fmt, arg_ptr); -} - - -static void -cleanup (void) -{ - if (*socket_name) - { - char *p; - - remove (socket_name); - p = strrchr (socket_name, '/'); - if (p) - { - *p = 0; - rmdir (socket_name); - *p = '/'; - } - *socket_name = 0; - } -} - - -static RETSIGTYPE -cleanup_sh (int sig) -{ - if (caught_fatal_sig) - raise (sig); - caught_fatal_sig = 1; - - /* gcry_control( GCRYCTL_TERM_SECMEM );*/ - cleanup (); - -#ifndef HAVE_DOSISH_SYSTEM - { /* reset action to default action and raise signal again */ - struct sigaction nact; - nact.sa_handler = SIG_DFL; - sigemptyset( &nact.sa_mask ); - nact.sa_flags = 0; - sigaction( sig, &nact, NULL); - } -#endif - raise( sig ); -} - -int -main (int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - int orig_argc; - int may_coredump; - char **orig_argv; - FILE *configfp = NULL; - char *configname = NULL; - const char *shell; - unsigned configlineno; - int parse_debug = 0; - int default_config =1; - int greeting = 0; - int nogreeting = 0; - int pipe_server = 0; - int is_daemon = 0; - int nodetach = 0; - int csh_style = 0; - char *logfile = NULL; - int debug_wait = 0; - - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - /* Please note that we may running SUID(ROOT), so be very CAREFUL - when adding any stuff between here and the call to INIT_SECMEM() - somewhere after the option parsing */ - log_set_prefix ("scdaemon", 1|4); - i18n_init (); - - /* check that the libraries are suitable. Do it here because - the option parsing may need services of the library */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - - ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - gcry_set_log_handler (my_gcry_logger, NULL); - gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); - - may_coredump = disable_core_dumps (); - - shell = getenv ("SHELL"); - if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) - csh_style = 1; - - /* FIXME: Using this homedir option does only make sense when not - running as a system service. We might want to check for this by - looking at the uid or ebtter use an explict option for this */ - opt.homedir = getenv("GNUPGHOME"); - if (!opt.homedir || !*opt.homedir) - opt.homedir = GNUPG_DEFAULT_HOMEDIR; - - /* check whether we have a config file on the commandline */ - orig_argc = argc; - orig_argv = argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ - while (arg_parse( &pargs, opts)) - { - if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) - parse_debug++; - else if (pargs.r_opt == oOptions) - { /* yes there is one, so we do not try the default one, but - read the option file when it is encountered at the - commandline */ - default_config = 0; - } - else if (pargs.r_opt == oNoOptions) - default_config = 0; /* --no-options */ - else if (pargs.r_opt == oHomedir) - opt.homedir = pargs.r.ret_str; - } - - /* initialize the secure memory. */ - gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); - maybe_setuid = 0; - - /* - Now we are working under our real uid - */ - - - if (default_config) - configname = make_filename (opt.homedir, "scdaemon.conf", NULL ); - - argc = orig_argc; - argv = orig_argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - next_pass: - if (configname) - { - configlineno = 0; - configfp = fopen (configname, "r"); - if (!configfp) - { - if (default_config) - { - if( parse_debug ) - log_info (_("NOTE: no default option file `%s'\n"), - configname ); - } - else - { - log_error (_("option file `%s': %s\n"), - configname, strerror(errno) ); - exit(2); - } - xfree (configname); - configname = NULL; - } - if (parse_debug && configname ) - log_info (_("reading options from `%s'\n"), configname ); - default_config = 0; - } - - while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) - { - switch (pargs.r_opt) - { - case oQuiet: opt.quiet = 1; break; - case oVerbose: opt.verbose++; break; - case oBatch: opt.batch=1; break; - - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - case oDebugWait: debug_wait = pargs.r.ret_int; break; - case oDebugSC: opt.debug_sc = pargs.r.ret_int; break; - - case oOptions: - /* config files may not be nested (silently ignore them) */ - if (!configfp) - { - xfree(configname); - configname = xstrdup(pargs.r.ret_str); - goto next_pass; - } - break; - case oNoGreeting: nogreeting = 1; break; - case oNoVerbose: opt.verbose = 0; break; - case oNoOptions: break; /* no-options */ - case oHomedir: opt.homedir = pargs.r.ret_str; break; - case oNoDetach: nodetach = 1; break; - case oLogFile: logfile = pargs.r.ret_str; break; - case oCsh: csh_style = 1; break; - case oSh: csh_style = 0; break; - case oServer: pipe_server = 1; break; - case oDaemon: is_daemon = 1; break; - - default : pargs.err = configfp? 1:2; break; - } - } - if (configfp) - { - fclose( configfp ); - configfp = NULL; - xfree(configname); - configname = NULL; - goto next_pass; - } - xfree (configname); - configname = NULL; - if (log_get_errorcount(0)) - exit(2); - if (nogreeting ) - greeting = 0; - - if (greeting) - { - fprintf (stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - fprintf (stderr, "%s\n", strusage(15) ); - } -#ifdef IS_DEVELOPMENT_VERSION - log_info ("NOTE: this is a development version!\n"); -#endif - - - if (atexit (cleanup)) - { - log_error ("atexit failed\n"); - cleanup (); - exit (1); - } - - if (debug_wait && pipe_server) - { - log_debug ("waiting for debugger - my pid is %u .....\n", - (unsigned int)getpid()); - sleep (debug_wait); - log_debug ("... okay\n"); - } - - /* now start with logging to a file if this is desired */ - if (logfile) - { - log_set_file (logfile); - log_set_prefix (NULL, 1|2|4); - } - - - if (pipe_server) - { /* this is the simple pipe based server */ - scd_command_handler (-1); - } - else if (!is_daemon) - { - log_info (_("please use the option `--daemon'" - " to run the program in the background\n")); - } - else - { /* regular server mode */ - int fd; - pid_t pid; - int i; - int len; - struct sockaddr_un serv_addr; - char *p; - - /* fixme: if there is already a running gpg-agent we should - share the same directory - and vice versa */ - *socket_name = 0; - snprintf (socket_name, DIM(socket_name)-1, - "/tmp/gpg-XXXXXX/S.scdaemon"); - socket_name[DIM(socket_name)-1] = 0; - p = strrchr (socket_name, '/'); - if (!p) - BUG (); - *p = 0;; - if (!mkdtemp(socket_name)) - { - log_error ("can't create directory `%s': %s\n", - socket_name, strerror(errno) ); - exit (1); - } - *p = '/'; - - if (strchr (socket_name, ':') ) - { - log_error ("colons are not allowed in the socket name\n"); - exit (1); - } - if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) - { - log_error ("name of socket to long\n"); - exit (1); - } - - - fd = socket (AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror(errno) ); - exit (1); - } - - memset (&serv_addr, 0, sizeof serv_addr); - serv_addr.sun_family = AF_UNIX; - strcpy (serv_addr.sun_path, socket_name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen(serv_addr.sun_path) + 1); - - if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1) - { - log_error ("error binding socket to `%s': %s\n", - serv_addr.sun_path, strerror (errno) ); - close (fd); - exit (1); - } - - if (listen (fd, 5 ) == -1) - { - log_error ("listen() failed: %s\n", strerror (errno)); - close (fd); - exit (1); - } - - if (opt.verbose) - log_info ("listening on socket `%s'\n", socket_name ); - - - fflush (NULL); - pid = fork (); - if (pid == (pid_t)-1) - { - log_fatal ("fork failed: %s\n", strerror (errno) ); - exit (1); - } - else if (pid) - { /* we are the parent */ - char *infostr; - - close (fd); - - /* create the info string: :: */ - if (asprintf (&infostr, "SCDAEMON_INFO=%s:%lu:1", - socket_name, (ulong)pid ) < 0) - { - log_error ("out of core\n"); - kill (pid, SIGTERM); - exit (1); - } - *socket_name = 0; /* don't let cleanup() remove the socket - - the child should do this from now on */ - if (argc) - { /* run the program given on the commandline */ - if (putenv (infostr)) - { - log_error ("failed to set environment: %s\n", - strerror (errno) ); - kill (pid, SIGTERM ); - exit (1); - } - execvp (argv[0], argv); - log_error ("failed to run the command: %s\n", strerror (errno)); - kill (pid, SIGTERM); - exit (1); - } - else - { - /* print the environment string, so that the caller can use - shell's eval to set it */ - if (csh_style) - { - *strchr (infostr, '=') = ' '; - printf ( "setenv %s\n", infostr); - } - else - { - printf ( "%s; export SCDAEMON_INFO;\n", infostr); - } - free (infostr); - exit (0); - } - /* NOTREACHED */ - } /* end parent */ - - /* this is the child */ - - /* detach from tty and put process into a new session */ - if (!nodetach ) - { /* close stdin, stdout and stderr unless it is the log stream */ - for (i=0; i <= 2; i++) - { - if ( log_get_fd () != i) - close (i); - } - if (setsid() == -1) - { - log_error ("setsid() failed: %s\n", strerror(errno) ); - cleanup (); - exit (1); - } - } - - /* setup signals */ - { - struct sigaction oact, nact; - - nact.sa_handler = cleanup_sh; - sigemptyset (&nact.sa_mask); - nact.sa_flags = 0; - - sigaction (SIGHUP, NULL, &oact); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGHUP, &nact, NULL); - sigaction( SIGTERM, NULL, &oact ); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGTERM, &nact, NULL); - nact.sa_handler = SIG_IGN; - sigaction (SIGPIPE, &nact, NULL); - sigaction (SIGINT, &nact, NULL); - } - - if (chdir("/")) - { - log_error ("chdir to / failed: %s\n", strerror (errno)); - exit (1); - } - - scd_command_handler (fd); - - close (fd); - } - - return 0; -} - -void -scd_exit (int rc) -{ - #if 0 -#warning no update_random_seed_file - update_random_seed_file(); - #endif -#if 0 - /* at this time a bit annoying */ - if (opt.debug & DBG_MEMSTAT_VALUE) - { - gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); - gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); - } - if (opt.debug) - gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); -#endif - gcry_control (GCRYCTL_TERM_SECMEM ); - rc = rc? rc : log_get_errorcount(0)? 2 : 0; - exit (rc); -} - - -void -scd_init_default_ctrl (CTRL ctrl) -{ - -} - diff --git a/scd/scdaemon.h b/scd/scdaemon.h deleted file mode 100644 index 9fbf891bb..000000000 --- a/scd/scdaemon.h +++ /dev/null @@ -1,104 +0,0 @@ -/* scdaemon.h - Global definitions for the SCdaemon - * 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 - */ - -#ifndef SCDAEMON_H -#define SCDAEMON_H - -#include -#include -#include "../common/util.h" -#include "../common/errors.h" - -#define MAX_DIGEST_LEN 24 - -/* A large struct name "opt" to keep global flags */ -struct { - unsigned int debug; /* debug flags (DBG_foo_VALUE) */ - int debug_sc; /* OpenSC debug level */ - int verbose; /* verbosity level */ - int quiet; /* be as quiet as possible */ - int dry_run; /* don't change any persistent data */ - int batch; /* batch mode */ - const char *homedir; /* configuration directory name */ -} opt; - - -#define DBG_COMMAND_VALUE 1 /* debug commands i/o */ -#define DBG_MPI_VALUE 2 /* debug mpi details */ -#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ -#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ -#define DBG_CACHE_VALUE 64 /* debug the caching */ -#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ -#define DBG_HASHING_VALUE 512 /* debug hashing operations */ -#define DBG_ASSUAN_VALUE 1024 - -#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE) -#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) -#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) -#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) -#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) -#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) - -struct server_local_s; -struct card_ctx_s; - -struct server_control_s { - struct server_local_s *server_local; - struct card_ctx_s *card_ctx; - struct { - unsigned char *value; - int valuelen; - } in_data; /* helper to store the value we are going to sign */ - -}; -typedef struct server_control_s *CTRL; -typedef struct card_ctx_s *CARD; - -/*-- scdaemon.c --*/ -void scd_exit (int rc); -void scd_init_default_ctrl (CTRL ctrl); - -/*-- command.c --*/ -void scd_command_handler (int); - -/*-- card.c --*/ -int card_open (CARD *rcard); -void card_close (CARD card); -int card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp); -int card_enum_keypairs (CARD card, int idx, - unsigned char *keygrip, - char **keyid); -int card_enum_certs (CARD card, int idx, char **certid, int *certtype); -int card_read_cert (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert); -int card_sign (CARD card, - const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ); -int card_decipher (CARD card, const char *keyidstr, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen); - - -#endif /*SCDAEMON_H*/ diff --git a/scripts/ChangeLog b/scripts/ChangeLog deleted file mode 100644 index 1a6ec032b..000000000 --- a/scripts/ChangeLog +++ /dev/null @@ -1,285 +0,0 @@ -2002-10-17 Werner Koch - - * autogen.sh: Allow env variables to override the auto* tool - names. Suggested by Simon Josefsson. - -2002-09-11 Werner Koch - - * distfiles: Include mk-w32-dist. - - * mk-w32-dist: Convert the character sets on a per language base. - -2002-09-02 Werner Koch - - * mk-w32-dist: Include more man pages and gpg split. Changed name - of ZIP file to better indicate that this is a command line version. - -2002-08-23 Werner Koch - - * autogen.sh : Don't run gettextize. - -2002-08-06 Stefan Bellon - - * conf-riscos/include/config.h: Changed #define FOO to - #define FOO 1. - * conf-riscos/include/g10defs.h: Likewise. - -2002-08-03 Stefan Bellon - - * conf-riscos/include/g10defs.h: Added GNUPG_LIBEXECDIR. - * conf-riscos/include/config.h: Changes due to dynload removal and - minor changes to avoid some warnings. - * conf-riscos/Makefile: Changes due to dynload removal. - * conf-riscos/cipher/*: Not needed anymore due to dynload removal. - -2002-07-25 David Shaw - - * gnupgbug: "Warning" -> "WARNING" - -2002-07-01 Werner Koch - - * mk-gpg-texi: New. - -2002-06-30 Werner Koch - - * mk-w32-dist (bindir): Fixes vor VPATH builds in a subdir, - include gpgv. - -2002-06-21 Stefan Bellon - - * conf-riscos/Makefile: Changes due to moving around RISC OS - specific stuff in the code. - -2002-06-07 Stefan Bellon - - * conf-riscos/include/config.h [__riscos__]: Fixed macro bug. - -2002-05-10 Stefan Bellon - - * conf-riscos/include/config.h [__riscos__]: Changes for later - Norcroft compilers. - - * conf-riscos/Makefile [__riscos__]: Updated. - -2002-04-22 Stefan Bellon - - * conf-riscos/include/config.h [__riscos__]: Development - versions automatically define DEBUG from now on. - - * conf-riscos/Makefile [__riscos__]: Updated for LDAP keyserver - code. - -2002-04-19 David Shaw - - * gnupg.spec.in: Removed pubring.asc and OPTIONS. Added - samplekeys.asc. - -2002-03-31 David Shaw - - * gnupg.spec.in: Added the gpgkeys_xxx keyserver helpers. Added a - * to catch variations on the basic gpg man page (gpg, gpgv). Mark - options.skel as a config file. Do not include the FAQ/faq.html - twice (in /doc/ and /share/). - -2002-01-02 Stefan Bellon - - * build-riscos [__riscos__]: Set filetype of Makefile correctly. - - * conf-riscos/include/g10defs.h [__riscos__]: Added GNU GPL - header and exec code defines. - - * conf-riscos/include/config.h [__riscos__]: Moved parts to - include/util.h where they really belong to. - - * conf-riscos/Makefile [__riscos__]: Updated for new keyserver, - exec and photo id code. - -2001-12-22 Werner Koch - - * autogen.sh: Fixed last change. - -2001-12-21 Werner Koch - - * distfiles: Removed those files which which automake installs by - default. - - * autogen.sh: Replaced $() by backticks for system without a posix - shell. Removed gawk specific quoting. By David Champion. - -2001-10-22 Werner Koch - - * autogen.sh (aclocal_vers): Require automalke 1.5. - -2001-08-21 Stefan Bellon - - * build-riscos [__riscos__]: New. - * conf-riscos [__riscos__]: Ditto. - -2001-08-13 Werner Koch - - * autogen.sh: Test on gettext 0.10.38. By Michael Engels. - -2001-08-07 Werner Koch - - * autogen.sh: Adjusted --build-w32 for autoconf 2.52 - -2001-07-09 Werner Koch - - * autogen.sh (autoconf_vers): Require autoconf 2.50 - -2001-05-06 Werner Koch - - * config.guess, config.sub: Add updates from subversions.gnu.org. - -2001-04-19 Werner Koch - - * autogen.sh: Add VPATH build support for option --build-w32. - -2001-03-12 Werner Koch - - * config.guess, config.sub: Replaced with the current GNU CVS ones. - -2001-01-18 Werner Koch - - * autogen.sh: New options --build-w32 - * build-w32: Does now call autogen.sh - -2000-11-24 Werner Koch - - * build-w32: New script to build the W32 version. - * distfiles: And put it into the distribution - -Thu Sep 14 17:45:11 CEST 2000 Werner Koch - - * gnupg.spec.in: Updated. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch - - * config.guess, config.sub: Replaced with the latest version from the - CVS archive. Hope that does not break too much. - -Fri May 12 14:01:20 CEST 2000 Werner Koch - - * gnupg.spec.in: New version from Fabio with some updated descriptions. - -Mon May 1 15:38:04 CEST 2000 Werner Koch - - * gnupg.spec.in: New version from Fabio. - -Fri Mar 17 16:26:05 CET 2000 Werner Koch - - * config.gues, config.sub: Support for s390-ibm-linux-gnu. Thanks - to Holger Smolinski. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch - - * config.guess: Add support for QNX. By Sam Roberts. - * config.sub: Ditto. - -Thu Sep 23 09:49:25 1999 Werner Koch (wk@gnupg.org) - - * commit: Remove leading and trailing empty lines when copying - Changes to Changelog - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch - - * gnupg.spec: Add Portuguese description - -Thu Sep 2 16:40:55 CEST 1999 Werner Koch - - * mkdiff: changed format of diff file name and made script more - general. - -Wed Aug 4 10:34:18 CEST 1999 Werner Koch - - * config.guess: Updated from gnu/common and applied my emx patch again. - * config.sub: Updated from gnu/common. - -Wed Jul 14 19:42:08 CEST 1999 Werner Koch - - * ltmain.sh, ltconfig.sh : Updated to libtool 1.3.3 - -Mon Jul 12 14:55:34 CEST 1999 Werner Koch - - * autogen.sh: Run libtoolize - -Sat May 22 22:47:26 CEST 1999 Werner Koch - - * autogen.sh: Fixed the error message for a missing libtool. - -Sat May 8 19:28:08 CEST 1999 Werner Koch - - * mkinstalldirs, install-sh: New from GNU repository - * config.sub, config.guess: Merged with rep version. - -Sun Mar 14 19:34:36 CET 1999 Werner Koch - - * autogen.sh: Add a check for libtool because some autoconf macros - are needed. - -Mon Feb 22 20:04:00 CET 1999 Werner Koch - - * autogen.sh: Enhanced the version testing code (Philippe Laliberte) - - * mkwebpage: Edits the buglist. - -Sat Feb 13 12:04:43 CET 1999 Werner Koch - - * autogen.sh: Now uses gettextize - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - * config.sub, config.guess: Support i386-emx-os2 - -Sun Jan 17 11:04:33 CET 1999 Werner Koch - - * autogen.sh: Now checks for installed gettext - -Sat Jan 16 09:27:30 CET 1999 Werner Koch - - * config.guess (m68k-atari-mint): New. - * config.sub: Add support for atarist-MiNT - -Wed Jan 13 12:49:36 CET 1999 Werner Koch - - * gnupg.spec.in: New - * gnupg.spec: Removed - -Wed Dec 23 13:18:14 CET 1998 Werner Koch - - * gnupg.spec: Updated version by Fabio Coatti - -Thu Dec 17 18:31:15 CET 1998 Werner Koch - - * gnupg.spec: New version by Reuben Sumner and did some more - changes. - -Fri Nov 27 12:39:29 CET 1998 Werner Koch - - - * commit: New - - -Fri Nov 20 12:01:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mkdiff: signs the patch file - -Sat Oct 17 16:10:16 1998 Werner Koch (wk@isil.d.shuttle.de) - - * autogen.sh: New. - -Wed Oct 14 09:55:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.guess (FreeBSD): Changes from Jun Kuriyama to support ELF - * config.sub: (freebsd): Add to maybe_os - - - Copyright 1998, 1999, 2000, 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. diff --git a/scripts/autogen.sh b/scripts/autogen.sh deleted file mode 100755 index 07ce852ef..000000000 --- a/scripts/autogen.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/sh -# Run this to generate all the initial makefiles, etc. -# -# Copyright (C) 1998, 1999, 2000, 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 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. - -PGM=GnuPG -lib_config_files="" -autoconf_vers=2.52 -automake_vers=1.6 -aclocal_vers=1.6 - -ACLOCAL=${ACLOCAL:-aclocal} -AUTOCONF=${AUTOCONF:-autoconf} -AUTOMAKE=${AUTOMAKE:-automake} -AUTOHEADER=${AUTOHEADER:-autoheader} -DIE=no -if test "$1" = "--build-w32"; then - tmp=`dirname $0` - tsdir=`cd "$tmp"; cd ..; pwd` - shift - host=i386--mingw32 - if [ ! -f $tsdir/scripts/config.guess ]; then - echo "$tsdir/scripts/config.guess not found" >&2 - exit 1 - fi - build=`$tsdir/scripts/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 "$tsdir/config.log" ]; then - if ! head $tsdir/config.log | grep i386--mingw32 >/dev/null; then - echo "Pease run a 'make distclean' first" >&2 - exit 1 - fi - fi - - crossbindir=`mingw32 --install-dir`/bin - 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 - - $tsdir/configure --build=${build} --host=${host} \ - ${disable_foo_tests} $* - exit $? -fi - - - -if ($AUTOCONF --version) < /dev/null > /dev/null 2>&1 ; then - if ($AUTOCONF --version | awk 'NR==1 { if( $3 >= '$autoconf_vers') \ - exit 1; exit 0; }'); - then - echo "**Error**: "\`autoconf\'" is too old." - echo ' (version ' $autoconf_vers ' or newer is required)' - DIE="yes" - fi -else - echo - echo "**Error**: You must have "\`autoconf\'" installed to compile $PGM." - echo ' (version ' $autoconf_vers ' or newer is required)' - DIE="yes" -fi - -if ($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 ; then - if ($AUTOMAKE --version | awk 'NR==1 { if( $4 >= '$automake_vers') \ - exit 1; exit 0; }'); - then - echo "**Error**: "\`automake\'" is too old." - echo ' (version ' $automake_vers ' or newer is required)' - DIE="yes" - fi - if ($ACLOCAL --version) < /dev/null > /dev/null 2>&1; then - if ($ACLOCAL --version | awk 'NR==1 { if( $4 >= '$aclocal_vers' ) \ - exit 1; exit 0; }' ); - then - echo "**Error**: "\`aclocal\'" is too old." - echo ' (version ' $aclocal_vers ' or newer is required)' - DIE="yes" - fi - else - echo - echo "**Error**: Missing "\`aclocal\'". The version of "\`automake\' - echo " installed doesn't appear recent enough." - DIE="yes" - fi -else - echo - echo "**Error**: You must have "\`automake\'" installed to compile $PGM." - echo ' (version ' $automake_vers ' or newer is required)' - DIE="yes" -fi - - -if (gettext --version /dev/null | awk 'NR==1 { split($4,A,"."); \ - X=10000*A[1]+100*A[2]+A[3]; echo X; if( X >= 1038 ) exit 1; exit 0}') - then - echo "**Error**: You must have "\`gettext\'" installed to compile $PGM." - echo ' (version 0.10.38 or newer is required; get' - echo ' ftp://alpha.gnu.org/gnu/gettext/gettext-0.10.38.tar.gz' - echo ' or install the latest Debian package)' - DIE="yes" -fi - - -if test "$DIE" = "yes"; then - exit 1 -fi - -echo "Running aclocal..." -$ACLOCAL -echo "Running autoheader..." -$AUTOHEADER -echo "Running automake --gnu ..." -$AUTOMAKE --gnu; -echo "Running autoconf..." -$AUTOCONF - -echo "You can now run \"./configure --enable-maintainer-mode\" and then \"make\"." - diff --git a/scripts/build-riscos b/scripts/build-riscos deleted file mode 100644 index c255a7827..000000000 --- a/scripts/build-riscos +++ /dev/null @@ -1,11 +0,0 @@ -| This is an RISC OS Obey file (filetype &feb) that copies handcrafted files -| for the RISC OS version into the correct places. -| It won't run on anything other than RISC OS -- I think ;-) - -copy .conf-riscos.cipher.c.construct .^.cipher.c.construct ~cf~v -copy .conf-riscos.cipher.c.constructv .^.cipher.c.constructv ~cf~v -copy .conf-riscos.include.h.config .^.include.h.config ~cf~v -copy .conf-riscos.include.h.g10defs .^.include.h.g10defs ~cf~v -copy .conf-riscos.Makefile .^.Makefile ~cf~v -settype .^.Makefile &fe1 -echo Done. diff --git a/scripts/build-w32 b/scripts/build-w32 deleted file mode 100755 index 9995a4865..000000000 --- a/scripts/build-w32 +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -exec scripts/autogen.sh --build-w32 - - - diff --git a/scripts/commit b/scripts/commit deleted file mode 100755 index 6bfa0a615..000000000 --- a/scripts/commit +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -# need a Posix shell, so we simply use bash - -set -e - -uid=`id -u` -date=`date` -name=$(awk -F: "\$3==$uid { print \$5 }" /etc/passwd ) -addr="<`id -un`@`hostname -d`>" - -for i in `find . -name Changes -print`; do - dir=`dirname $i` - if [ -s $dir/Changes ]; then - awk ' - state == 0 && /^[ \t]*$/ { next } - state == 0 { state = 1 } - /^[ \t]*$/ { empty++; next } - { while ( empty > 0 ) { print ""; empty--; }; print } - ' < $dir/Changes > $dir/Changes.tmp - if [ -s $dir/Changes.tmp ]; then - lines=`wc -l <$dir/Changes.tmp` - echo "$date $name $addr" >$dir/ChangeLog.new - echo >>$dir/ChangeLog.new - cat $dir/Changes.tmp >>$dir/ChangeLog.new - echo >>$dir/ChangeLog.new - [ -f $dir/ChangeLog ] && cat $dir/ChangeLog >>$dir/ChangeLog.new - echo -n > $dir/Changes - [ -f $dir/ChangeLog ] && rm $dir/ChangeLog - mv $dir/ChangeLog.new $dir/ChangeLog - echo "$lines new lines in $dir/ChangeLog" - fi - rm $dir/Changes.tmp || true - fi -done - -# Execute canned cvs remove commands -for i in `find . -name cvs-remove -print`; do - dir=`dirname $i` - if [ -s $dir/cvs-remove ]; then - here=`pwd` - cd $dir - if cvs remove -f `cat cvs-remove`; then - rm cvs-remove - fi - cd $here - fi -done - -# Execute canned cvs add commands -for i in `find . -name cvs-add -print`; do - dir=`dirname $i` - if [ -s $dir/cvs-add ]; then - here=`pwd` - cd $dir - if cvs add `cat cvs-add`; then - rm cvs-add - fi - cd $here - fi -done - -cvs -z3 commit -m "See ChangeLog: $date $name" $* - diff --git a/scripts/conf-riscos/Makefile b/scripts/conf-riscos/Makefile deleted file mode 100644 index eeb6206c6..000000000 --- a/scripts/conf-riscos/Makefile +++ /dev/null @@ -1,466 +0,0 @@ -# Makefile for the RISC OS version of GnuPG -CC=cc -LINK=link -AS=objasm -MAKE=amu -DEPEND=-depend !Depend -LIBLDAP=^.^.openldap-2/0/18 -CC_FLAGS=-Wpc -apcs 3/26bit/fpe2 -throwback -Otime -IUnix:,include,mpi,intl,zlib,$(LIBLDAP).include -JUnix: -D__riscos__ -DHAVE_CONFIG_H -DNO_ASM -UIS_MODULE -DVERSION="\"$(GnuPG$Version)\"" $(GnuPG$DevDefine) -AS_FLAGS=-apcs 3/26bit -throwback -predefine "ARMv4 SETA 0" -LD_FLAGS=Unix:o.unixlib -CIPHER_OBJS=cipher.o.blowfish \ - cipher.o.cast5 \ - cipher.o.cipher \ - cipher.o.des \ - cipher.o.dsa \ - cipher.o.dynload \ - cipher.o.elgamal \ - cipher.o.g10c \ - cipher.o.md \ - cipher.o.md5 \ - cipher.o.primegen \ - cipher.o.pubkey \ - cipher.o.random \ - cipher.o.rijndael \ - cipher.o.rmd160 \ - cipher.o.rndriscos \ - cipher.o.rsa \ - cipher.o.sha1 \ - cipher.o.smallprime \ - cipher.o.tiger32 \ - cipher.o.twofish -GETTEXT_OBJS=intl.o.bindtextdom \ - intl.o.dcgettext \ - intl.o.dgettext \ - intl.o.explodename \ - intl.o.finddomain \ - intl.o.gettext \ - intl.o.intl-compat \ - intl.o.l10nflist \ - intl.o.loadmsgcat \ - intl.o.localealias \ - intl.o.textdomain -MPI_OBJS=mpi.o.mpi-add \ - mpi.o.mpi-bit \ - mpi.o.mpi-cmp \ - mpi.o.mpi-div \ - mpi.o.mpi-gcd \ - mpi.o.mpi-inline \ - mpi.o.mpi-inv \ - mpi.o.mpi-mul \ - mpi.o.mpi-pow \ - mpi.o.mpi-mpow \ - mpi.o.mpi-scan \ - mpi.o.mpicoder \ - mpi.o.mpih-div \ - mpi.o.mpih-mul \ - mpi.o.mpiutil \ - mpi.o.g10m \ - mpi.arm.o.mpih -UTIL_OBJS=util.o.argparse \ - util.o.dotlock \ - util.o.errors \ - util.o.fileutil \ - util.o.g10u \ - util.o.http \ - util.o.iobuf \ - util.o.logger \ - util.o.memory \ - util.o.miscutil \ - util.o.secmem \ - util.o.strgutil \ - util.o.ttyio \ - util.o.riscos -ZLIB_OBJS=zlib.o.adler32 \ - zlib.o.compress \ - zlib.o.crc32 \ - zlib.o.deflate \ - zlib.o.infblock \ - zlib.o.infcodes \ - zlib.o.inffast \ - zlib.o.inflate \ - zlib.o.inftrees \ - zlib.o.infutil \ - zlib.o.trees \ - zlib.o.uncompr \ - zlib.o.zutil -G10_OBJS=g10.o.armor \ - g10.o.build-packet \ - g10.o.cipher \ - g10.o.comment \ - g10.o.compress \ - g10.o.dearmor \ - g10.o.decrypt \ - g10.o.delkey \ - g10.o.encode \ - g10.o.encr-data \ - g10.o.exec \ - g10.o.export \ - g10.o.free-packet \ - g10.o.g10 \ - g10.o.getkey \ - g10.o.helptext \ - g10.o.hkp \ - g10.o.import \ - g10.o.kbnode \ - g10.o.keydb \ - g10.o.keyedit \ - g10.o.keygen \ - g10.o.keyid \ - g10.o.keylist \ - g10.o.keyring \ - g10.o.keyserver \ - g10.o.mainproc \ - g10.o.mdfilter \ - g10.o.misc \ - g10.o.mkdtemp \ - g10.o.openfile \ - g10.o.parse-packet \ - g10.o.passphrase \ - g10.o.photoid \ - g10.o.pipemode \ - g10.o.pkclist \ - g10.o.plaintext \ - g10.o.pubkey-enc \ - g10.o.revoke \ - g10.o.seckey-cert \ - g10.o.seskey \ - g10.o.sig-check \ - g10.o.sign \ - g10.o.signal \ - g10.o.skclist \ - g10.o.status \ - g10.o.tdbdump \ - g10.o.tdbio \ - g10.o.textfilter \ - g10.o.trustdb \ - g10.o.verify -GPGV_OBJS=g10.o.armor \ - g10.o.build-packet \ - g10.o.compress \ - g10.o.free-packet \ - g10.o.getkey \ - g10.o.gpgv \ - g10.o.keydb \ - g10.o.keylist \ - g10.o.kbnode \ - g10.o.keyid \ - g10.o.keyring \ - g10.o.mainproc \ - g10.o.mdfilter \ - g10.o.misc \ - g10.o.openfile \ - g10.o.parse-packet \ - g10.o.plaintext \ - g10.o.seskey \ - g10.o.sig-check \ - g10.o.signal \ - g10.o.status \ - g10.o.textfilter \ - g10.o.verify \ - util.o.argparse \ - util.o.errors \ - util.o.fileutil \ - util.o.g10u \ - util.o.iobuf \ - util.o.logger \ - util.o.memory \ - util.o.miscutil \ - util.o.secmem \ - util.o.strgutil \ - util.o.riscos \ - cipher.o.dsa \ - cipher.o.dynload \ - cipher.o.elgamal \ - cipher.o.g10c \ - cipher.o.md \ - cipher.o.md5 \ - cipher.o.pubkey \ - cipher.o.rmd160 \ - cipher.o.rsa \ - cipher.o.sha1 \ - cipher.o.tiger32 \ - mpi.mpi \ - zlib.zlib -GPGKEYS_OBJS=util.o.riscos \ - util.o.strgutil \ - util.o.memory \ - util.o.logger \ - util.o.secmem \ - intl.gettext - -## Rule Patterns ## - -.SUFFIXES: .c .o .s - -.c.o: - $(CC) $(CC_FLAGS) $(DEPEND) -c -o $@ $< - -.s.o: - $(AS) $(AS_FLAGS) $(DEPEND) $< $@ - -# Static dependencies: - -all: - @echo Use one of the following as target: - @echo | dev to build the development version - @echo | dist to build the distribution with all archives - @echo All other targets are internal and shouldn't be used! - -cipher.cipher: $(CIPHER_OBJS) - $(LINK) -aof $(CIPHER_OBJS) -o cipher.cipher - -intl.gettext: $(GETTEXT_OBJS) - $(LINK) -aof $(GETTEXT_OBJS) -o intl.gettext - -mpi.mpi: $(MPI_OBJS) - $(LINK) -aof $(MPI_OBJS) -o mpi.mpi - -tools.gpgsplit: tools.o.gpgsplit util.util intl.gettext zlib.zlib - $(LINK) $(LD_FLAGS) tools.o.gpgsplit util.util intl.gettext zlib.zlib -o tools.gpgsplit - -squeeze tools.gpgsplit - -copy tools.gpgsplit ADFS::A5.$.tmp.!GnuPG.gpgsplit ~CF~V - -keyserver.gpgkeys_ldap: keyserver.o.gpgkeys_ldap $(GPGKEYS_OBJS) $(LIBLDAP).libraries.libldap.libldap - $(LINK) $(LD_FLAGS) keyserver.o.gpgkeys_ldap $(GPGKEYS_OBJS) $(LIBLDAP).libraries.libldap.libldap -o keyserver.gpgkeys_ldap - -squeeze keyserver.gpgkeys_ldap - -copy keyserver.gpgkeys_ldap ADFS::A5.$.tmp.!GnuPG.gpgkeys_ldap ~CF~V - -riscos.jpegview.jpegview: - -dir riscos.jpegview - -$(MAKE) - -back - -util.util: $(UTIL_OBJS) - $(LINK) -aof $(UTIL_OBJS) -o util.util - -zlib.zlib: $(ZLIB_OBJS) - $(LINK) -aof zlib.o.* -o zlib.zlib - -g10.gpg: $(G10_OBJS) cipher.o.idea cipher.cipher intl.gettext mpi.mpi util.util zlib.zlib BUILD - $(LINK) $(G10_OBJS) $(LD_FLAGS) cipher.o.idea cipher.cipher intl.gettext mpi.mpi util.util zlib.zlib -o g10.gpg - -copy g10.gpg ADFS::A5.$.tmp.!GnuPG.gpg ~CFR~V - -g10.gpgv: $(GPGV_OBJS) intl.gettext BUILD - $(LINK) $(GPGV_OBJS) intl.gettext $(LD_FLAGS) -o g10.gpgv - -copy g10.gpgv ADFS::A5.$.tmp.!GnuPG.gpgv ~CFR~V - -g10.gpgpart: $(G10_OBJS) cipher.cipher intl.gettext mpi.mpi util.util zlib.zlib BUILD - drlink034 -aof $(G10_OBJS) $(LD_FLAGS) cipher.cipher intl.gettext mpi.mpi util.util zlib.zlib -o g10.gpgpart - -select-idea-src: - -copy distrib.idea-addon.cipher.c.idea cipher.c.idea ~CF~NR~V - $(CC) $(CC_FLAGS) $(DEPEND) -c -o cipher.o.idea cipher.c.idea - -select-gpl-src: - -copy distrib.non-idea.cipher.c.idea cipher.c.idea ~CF~NR~V - $(CC) $(CC_FLAGS) $(DEPEND) -c -o cipher.o.idea cipher.c.idea - -distrib.gnupgsrc/zip: select-gpl-src - -zip -9@ distrib.gnupgsrc/zip < distrib.resources.distfiles - -distrib.gnupg/zip: distrib.gpl-bin.!GnuPG.JPEGview distrib.gpl-bin.!GnuPG.gpgsplit distrib.gpl-bin.!GnuPG.gpg distrib.gpl-bin.!GnuPG.gpgv select-gpl-src - -copy distrib.resources.History distrib.gpl-bin.History ~CFR~V - -copy distrib.resources.Upgrading distrib.gpl-bin.Upgrading ~CFR~V - -copy distrib.resources.ReadMe_bin distrib.gpl-bin.!ReadMe1st ~CFR~V - -copy distrib.resources.!GnuPG distrib.gpl-bin.!GnuPG ~CFR~V - -copy distrib.resources.!GnuPGUser distrib.gpl-bin.!GnuPGUser ~CFR~V - -copy distrib.resources.!System distrib.gpl-bin.!System ~CFR~V - -copy distrib.resources.orig_docs distrib.gpl-bin.orig_docs ~CFR~V - -dir distrib.gpl-bin - -zip -r9 ^.gnupg/zip * - -back - -distrib.gnupgdev/zip: distrib.private.!GnuPG.JPEGview distrib.private.!GnuPG.gpgsplit distrib.private.!GnuPG.gpgkeys_ldap distrib.private.!GnuPG.gpg distrib.private.!GnuPG.gpgv select-idea-src - -ifthere distrib.private.!GnuPG.locale then wipe distrib.private.!GnuPG.locale ~CFR~V - -copy distrib.intl.!GnuPG.locale distrib.private.!GnuPG.locale ~CFR~V - -copy distrib.resources.History distrib.private.History ~CFR~V - -copy distrib.resources.Upgrading distrib.private.Upgrading ~CFR~V - -copy distrib.resources.ReadMe_bin distrib.private.!ReadMe1st ~CFR~V - -copy distrib.resources.!GnuPG distrib.private.!GnuPG ~CFR~V - -copy distrib.resources.!GnuPGUser distrib.private.!GnuPGUser ~CFR~V - -copy distrib.resources.!System distrib.private.!System ~CFR~V - -copy distrib.resources.orig_docs distrib.private.orig_docs ~CFR~V - -dir distrib.private - -zip -r9 ^.gnupgdev/zip * - -back - -distrib.gnupgidea/zip: cipher.o.idea select-idea-src - -copy distrib.resources.ReadMe_idea distrib.idea-addon.!ReadMe ~CFR~V - -copy cipher.o.idea distrib.idea-addon.cipher.o.idea ~CFR~V - -dir distrib.idea-addon - -zip -r9 ^.gnupgidea/zip * - -back - -distrib.gnupgpart/zip: g10.gpgpart select-idea-src - -copy distrib.resources.ReadMe_part distrib.part.!ReadMe1st ~CFR~V - -copy g10.gpgpart distrib.part.g10.gpgpart ~CFR~V - -dir distrib.part - -zip -r9 ^.gnupgpart/zip * - -back - -distrib.gnupgldap/zip: keyserver.gpgkeys_ldap - -copy distrib.resources.ReadMe_ldap distrib.ldap.!ReadMe ~CFR~V - -copy keyserver.gpgkeys_ldap distrib.ldap.!GnuPG.gpgkeys_ldap ~CFR~V - -dir distrib.ldap - -zip -r9 ^.gnupgldap/zip * - -back - -distrib.gnupgintl/zip: - -dir distrib.intl - -zip -r9 ^.gnupgintl/zip * - -back - -distrib.gpl-bin.!GnuPG.gpg: g10.gpg - -copy g10.gpg distrib.gpl-bin.!GnuPG.gpg ~CFR~V - -squeeze distrib.gpl-bin.!GnuPG.gpg - -distrib.gpl-bin.!GnuPG.gpgv: g10.gpgv - -copy g10.gpgv distrib.gpl-bin.!GnuPG.gpgv ~CFR~V - -squeeze distrib.gpl-bin.!GnuPG.gpgv - -distrib.gpl-bin.!GnuPG.gpgsplit: tools.gpgsplit - -copy tools.gpgsplit distrib.gpl-bin.!GnuPG.gpgsplit ~CFR~V - -squeeze distrib.gpl-bin.!GnuPG.gpgsplit - -distrib.gpl-bin.!GnuPG.JPEGview: riscos.jpegview.jpegview - -copy riscos.jpegview.jpegview distrib.gpl-bin.!GnuPG.JPEGview ~CFR~V - -distrib.private.!GnuPG.gpg: g10.gpg - -copy g10.gpg distrib.private.!GnuPG.gpg ~CFR~V - -squeeze distrib.private.!GnuPG.gpg - -distrib.private.!GnuPG.gpgv: g10.gpgv - -copy g10.gpgv distrib.private.!GnuPG.gpgv ~CFR~V - -squeeze distrib.private.!GnuPG.gpgv - -distrib.private.!GnuPG.gpgsplit: tools.gpgsplit - -copy tools.gpgsplit distrib.private.!GnuPG.gpgsplit ~CFR~V - -squeeze distrib.private.!GnuPG.gpgsplit - -distrib.private.!GnuPG.gpgkeys_ldap: keyserver.gpgkeys_ldap - -copy keyserver.gpgkeys_ldap distrib.private.!GnuPG.gpgkeys_ldap ~CFR~V - -squeeze distrib.private.!GnuPG.gpgkeys_ldap - -distrib.private.!GnuPG.JPEGview: riscos.jpegview.jpegview - -copy riscos.jpegview.jpegview distrib.private.!GnuPG.JPEGview ~CFR~V - -clean-cipher: - -ifthere cipher.o.* then wipe cipher.o.* ~CFR~V - -ifthere cipher.cipher then wipe cipher.cipher ~CFR~V - -clean-intl: - -ifthere intl.o.* then wipe intl.o.* ~CFR~V - -ifthere intl.gettext then wipe intl.gettext ~CFR~V - -clean-mpi: - -ifthere mpi.o.* then wipe mpi.o.* ~CFR~V - -ifthere mpi.arm.o.* then wipe mpi.arm.o.* ~CFR~V - -ifthere mpi.mpi then wipe mpi.mpi ~CFR~V - -clean-util: - -ifthere util.o.* then wipe util.o.* ~CFR~V - -ifthere util.util then wipe util.util ~CFR~V - -clean-zlib: - -ifthere zlib.o.* then wipe zlib.o.* ~CFR~V - -ifthere zlib.zlib then wipe zlib.zlib ~CFR~V - -clean-dist: - -ifthere distrib.*/zip then wipe distrib.*/zip ~CFR~V - -clean-g10: - -ifthere g10.gpg then wipe g10.gpg ~CFR~V - -ifthere g10.gpgv then wipe g10.gpgv ~CFR~V - -ifthere g10.gpgpart then wipe g10.gpgpart ~CFR~V - -ifthere g10.o.* then wipe g10.o.* ~CFR~V - -clean-keyserver: - -ifthere keyserver.gpgkeys_ldap then wipe keyserver.gpgkeys_ldap ~CFR~V - -ifthere keyserver.o.* then wipe keyserver.o.* ~CFR~V - -clean-tools: - -ifthere tools.gpgsplit then wipe tools.gpgsplit ~CFR~V - -ifthere tools.o.* then wipe tools.o.* ~CFR~V - -clean-riscos: - -ifthere riscos.jpegview.jpegview then wipe riscos.jpegview.jpegview ~CFR~V - -clean-version: - -ifthere g10.o.armor then wipe g10.o.armor ~CFR~V - -ifthere g10.o.encode then wipe g10.o.encode ~CFR~V - -ifthere g10.o.g10 then wipe g10.o.g10 ~CFR~V - -ifthere g10.o.gpgv then wipe g10.o.gpgv ~CFR~V - -ifthere g10.o.keygen then wipe g10.o.keygen ~CFR~V - -ifthere g10.o.sign then wipe g10.o.sign ~CFR~V - -ifthere g10.gpg then wipe g10.gpg ~CFR~V - -ifthere g10.gpgv then wipe g10.gpgv ~CFR~V - -ifthere g10.gpgpart then wipe g10.gpgpart ~CFR~V - -clean: clean-dist clean-cipher clean-intl clean-mpi clean-util clean-zlib clean-g10 clean-keyserver clean-tools clean-riscos - -g10.o.armor: BUILD - $(CC) $(CC_FLAGS) $(DEPEND) -c -o g10.o.armor g10.c.armor - -g10.o.encode: BUILD - $(CC) $(CC_FLAGS) $(DEPEND) -c -o g10.o.encode g10.c.encode - -g10.o.g10: BUILD - $(CC) $(CC_FLAGS) $(DEPEND) -c -o g10.o.g10 g10.c.g10 - -g10.o.gpgv: BUILD - $(CC) $(CC_FLAGS) $(DEPEND) -c -o g10.o.gpgv g10.c.gpgv - -g10.o.keygen: BUILD - $(CC) $(CC_FLAGS) $(DEPEND) -c -o g10.o.keygen g10.c.keygen - -g10.o.sign: BUILD - $(CC) $(CC_FLAGS) $(DEPEND) -c -o g10.o.sign g10.c.sign - -dev: clean-version - $(MAKE) fast-dev - -fast-dev: BUILD - setver configure/ac AC_INIT(gnupg, , dev - wipe distrib.private.!GnuPG.gpg* ~CFR~V - -$(MAKE) keyserver.gpgkeys_ldap - $(MAKE) tools.gpgsplit - $(MAKE) distrib.gnupgdev/zip - ifthere .private.gnupgdev/zip then wipe .private.gnupgdev/zip ~CFR~V - rename distrib.gnupgdev/zip .private.gnupgdev/zip - -dist: BUILD clean-version tools.gpgsplit - setver configure/ac AC_INIT(gnupg, , dist - wipe distrib.gpl-bin.!GnuPG.gpg* ~CFR~V - $(MAKE) distrib.gnupg/zip - $(MAKE) distrib.gnupgidea/zip - $(MAKE) distrib.gnupgpart/zip - wipe distrib.private.!GnuPG.gpg* ~CFR~V - $(MAKE) distrib.gnupgdev/zip - $(MAKE) distrib.gnupgsrc/zip - $(MAKE) distrib.gnupgintl/zip - $(MAKE) distrib.gnupgldap/zip - $(MAKE) select-idea-src - ifthere .archives.gnupg/zip then wipe .archives.gnupg/zip ~CFR~V - ifthere .private.gnupgdev/zip then wipe .private.gnupgdev/zip ~CFR~V - ifthere .archives.gnupgidea/zip then wipe .archives.gnupgidea/zip ~CFR~V - ifthere .archives.gnupgpart/zip then wipe .archives.gnupgpart/zip ~CFR~V - ifthere .archives.gnupgsrc/zip then wipe .archives.gnupgsrc/zip ~CFR~V - ifthere .archives.gnupgintl/zip then wipe .archives.gnupgintl/zip ~CFR~V - ifthere .archives.gnupgldap/zip then wipe .archives.gnupgldap/zip ~CFR~V - ifthere .gnupg_history/txt then wipe .gnupg_history/txt ~CFR~V - ifthere .gnupg_news/txt then wipe .gnupg_news/txt ~CFR~V - rename distrib.gnupgdev/zip .private.gnupgdev/zip - rename distrib.gnupg/zip .archives.gnupg/zip - rename distrib.gnupgidea/zip .archives.gnupgidea/zip - rename distrib.gnupgpart/zip .archives.gnupgpart/zip - rename distrib.gnupgsrc/zip .archives.gnupgsrc/zip - rename distrib.gnupgintl/zip .archives.gnupgintl/zip - rename distrib.gnupgldap/zip .archives.gnupgldap/zip - copy distrib.resources.History .gnupg_history/txt ~CFR~V - copy distrib.resources.orig_docs.NEWS .gnupg_news/txt ~CFR~V - unset GnuPG$DevDefine - unset GnuPG$Version - updatesigs .archives --secring adfs::ap.$.secring/gpg - -# Dynamic dependencies: diff --git a/scripts/conf-riscos/include/config.h b/scripts/conf-riscos/include/config.h deleted file mode 100644 index b95bef608..000000000 --- a/scripts/conf-riscos/include/config.h +++ /dev/null @@ -1,390 +0,0 @@ -/* config.h - hand edited by Stefan Bellon to suit RISC OS needs - * 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 G10_CONFIG_H -#define G10_CONFIG_H - -/* need this, because some autoconf tests rely on this (e.g. stpcpy) - * and it should be used for new programs - */ -#define _GNU_SOURCE 1 - - -/* Define if using alloca.c. */ -#undef C_ALLOCA - -/* Define to empty if the keyword does not work. */ -/* #undef const */ - -/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. - This function is required for alloca.c support on those systems. */ -#undef CRAY_STACKSEG_END - -/* Define if you have alloca, as a function or macro. */ -/* #undef HAVE_ALLOCA */ -#define HAVE_ALLOCA 1 - -/* Define if you have and it should be used (not on Ultrix). */ -/* #undef HAVE_ALLOCA_H */ -#define HAVE_ALLOCA_H 1 - -/* #undef _LIBC */ - -/* Define if you don't have vprintf but do have _doprnt. */ -#undef HAVE_DOPRNT - -/* Define if you have the vprintf function. */ -#define HAVE_VPRINTF 1 - -/* Define to `long' if doesn't define. */ -#undef off_t - -/* Define if you need to in order for stat and other things to work. */ -#undef _POSIX_SOURCE - -/* Define as the return type of signal handlers (int or void). */ -#define RETSIGTYPE void - -/* Define to `unsigned' if doesn't define. */ -#define size_t unsigned int - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at run-time. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown - */ -#undef STACK_DIRECTION - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if `sys_siglist' is declared by . */ -#define SYS_SIGLIST_DECLARED 1 - -#undef M_DEBUG -#undef M_GUARD -#define PRINTABLE_OS_NAME "RISC OS" - -/* Define if your locale.h file contains LC_MESSAGES. */ -#define HAVE_LC_MESSAGES 1 - -/* Define to 1 if NLS is requested. */ -#define ENABLE_NLS 1 - -/* Define as 1 if you have catgets and don't want to use GNU gettext. */ -#undef HAVE_CATGETS - -/* Define as 1 if you have gettext and don't want to use GNU gettext. */ -#undef HAVE_GETTEXT - -#undef BIG_ENDIAN_HOST -#define LITTLE_ENDIAN_HOST 1 - -#undef HAVE_BYTE_TYPEDEF -#undef HAVE_USHORT_TYPEDEF -#undef HAVE_ULONG_TYPEDEF -#undef HAVE_U16_TYPEDEF -#undef HAVE_U32_TYPEDEF - -#undef HAVE_BROKEN_MLOCK - -/* defined if we have a /dev/random and /dev/urandom */ -#undef HAVE_DEV_RANDOM -/* and the real names of the random devices */ -#undef NAME_OF_DEV_RANDOM -#undef NAME_OF_DEV_URANDOM -/* Linux has an ioctl */ -#undef HAVE_DEV_RANDOM_IOCTL - -/* see cipher/rndegd.c */ -#undef EGD_SOCKET_NAME - -#undef USE_DYNAMIC_LINKING -#undef HAVE_DL_DLOPEN -#undef HAVE_DL_SHL_LOAD -#undef HAVE_DLD_DLD_LINK - -#undef USE_SHM_COPROCESSING - -#undef IPC_HAVE_SHM_LOCK -#undef IPC_RMID_DEFERRED_RELEASE - -/* set this to limit filenames to the 8.3 format */ -#undef USE_ONLY_8DOT3 -/* defined if we must run on a stupid file system */ -#undef HAVE_DRIVE_LETTERS -/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) - * with special properties like no file modes */ -#undef HAVE_DOSISH_SYSTEM -/* because the Unix gettext has to much overhead on MingW32 systems - * and these systems lack Posix functions, we use a simplified version - * of gettext */ -#undef USE_SIMPLE_GETTEXT -/* At some point in the system we need to know that we use the Windows - * random module. */ -#undef USE_STATIC_RNDW32 - -#undef USE_CAPABILITIES - -/* Some systems have mkdir that takes a single argument. */ -#undef MKDIR_TAKES_ONE_ARG - -/* The number of bytes in a unsigned int. */ -#define SIZEOF_UNSIGNED_INT 4 - -/* The number of bytes in a unsigned long. */ -#define SIZEOF_UNSIGNED_LONG 4 - -/* The number of bytes in a unsigned long long. */ -#define SIZEOF_UNSIGNED_LONG_LONG 0 - -/* The number of bytes in a unsigned short. */ -#define SIZEOF_UNSIGNED_SHORT 2 - -/* Define if you have the __argz_count function. */ -#undef HAVE___ARGZ_COUNT - -/* Define if you have the __argz_next function. */ -#undef HAVE___ARGZ_NEXT - -/* Define if you have the __argz_stringify function. */ -#undef HAVE___ARGZ_STRINGIFY - -/* Define if you have the atexit function. */ -#define HAVE_ATEXIT 1 - -/* Define if you have the clock_gettime function. */ -#undef HAVE_CLOCK_GETTIME - -/* Define if you have the dcgettext function. */ -#undef HAVE_DCGETTEXT - -/* Define if you have the dlopen function. */ -#undef HAVE_DLOPEN - -/* Define if you have the fopen64 function. */ -#undef HAVE_FOPEN64 - -/* Define if you have the fstat64 function. */ -#undef HAVE_FSTAT64 - -/* Define if you have the getcwd function. */ -#define HAVE_GETCWD 1 - -/* Define if you have the gethrtime function. */ -#undef HAVE_GETHRTIME - -/* Define if you have the getpagesize function. */ -#define HAVE_GETPAGESIZE 1 - -/* Define if you have the getrusage function. */ -#define HAVE_GETRUSAGE 1 - -/* Define if you have the gettimeofday function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define if you have the memicmp function. */ -#undef HAVE_MEMICMP - -/* Define if you have the memmove function. */ -#define HAVE_MEMMOVE 1 - -/* Define if you have the mlock function. */ -#undef HAVE_MLOCK - -/* Define if you have the mmap function. */ -#undef HAVE_MMAP - -/* Define if you have the munmap function. */ -#undef HAVE_MUNMAP - -/* Define if you have the nl_langinfo function. */ -#undef HAVE_NL_LANGINFO - -/* Define if you have the putenv function. */ -#define HAVE_PUTENV 1 - -/* Define if you have the raise function. */ -#define HAVE_RAISE 1 - -/* Define if you have the rand function. */ -#define HAVE_RAND 1 - -/* Define if you have the setenv function. */ -#define HAVE_SETENV 1 - -/* Define if you have the setlocale function. */ -#define HAVE_SETLOCALE 1 - -/* Define if you have the setrlimit function. */ -#define HAVE_SETRLIMIT 1 - -/* Define if you have the sigaction function. */ -#define HAVE_SIGACTION 1 - -/* Define if you have the sigprocmask function. */ -#define HAVE_SIGPROCMASK 1 - -/* Define if you have the stpcpy function. */ -#define HAVE_STPCPY 1 - -/* Define if you have the strcasecmp function. */ -#define HAVE_STRCASECMP 1 - -/* Define if you have the strchr function. */ -#define HAVE_STRCHR 1 - -/* Define if you have the strdup function. */ -#define HAVE_STRDUP 1 - -/* Define if you have the strerror function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the strftime function. */ -#define HAVE_STRFTIME 1 - -/* Define if you have the stricmp function. */ -#define HAVE_STRICMP 1 - -/* Define if you have the strlwr function. */ -#undef HAVE_STRLWR - -/* Define if you have the strtoul function. */ -#define HAVE_STRTOUL 1 - -/* Define if you have the tcgetattr function. */ -#undef HAVE_TCGETATTR - -/* Define if you have the wait4 function. */ -#define HAVE_WAIT4 1 - -/* Define if you have the waitpid function. */ -#define HAVE_WAITPID 1 - -/* Define if you have the header file. */ -#undef HAVE_ARGZ_H - -/* Define if you have the header file. */ -#undef HAVE_DIRECT_H - -/* Define if you have the header file. */ -#undef HAVE_GDBM_H - -/* Define if you have the header file. */ -#undef HAVE_LANGINFO_H - -/* Define if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define if you have the header file. */ -#undef HAVE_LINUX_RANDOM_H - -/* Define if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define if you have the header file. */ -#undef HAVE_NL_TYPES_H - -/* Define if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define if you have the header file. */ -#undef HAVE_SYS_CAPABILITY_H - -/* Define if you have the header file. */ -#undef HAVE_SYS_IPC_H - -/* Define if you have the header file. */ -#define HAVE_SYS_MMAN_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define if you have the header file. */ -#undef HAVE_SYS_SHM_H - -/* Define if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define if you have the header file. */ -#undef HAVE_TERMIO_H - -/* Define if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define if you have the header file. */ -#define HAVE_ZLIB_H 1 - -/* Define if you have the dl library (-ldl). */ -#undef HAVE_LIBDL - -/* Define if you have the dld library (-ldld). */ -#undef HAVE_LIBDLD - -/* Define if you have the gdbm library (-lgdbm). */ -#undef HAVE_LIBGDBM - -/* Define if you have the i library (-li). */ -#undef HAVE_LIBI - -/* Define if you have the nsl library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Define if you have the rt library (-lrt). */ -#undef HAVE_LIBRT - -/* Name of package */ -#define PACKAGE "GnuPG" - - -/* define if compiled symbols have a leading underscore */ -#define WITH_SYMBOL_UNDERSCORE 1 - -#ifdef IS_DEVELOPMENT_VERSION - #define DEBUG 1 -/* #define M_DEBUG */ - #define M_GUARD 1 -#endif - -#define USE_RNDRISCOS 1 - -/* RISC OS specifica */ -#if (__CC_NORCROFT == 1) /* Norcroft */ -# undef __GNUC__ -# define __GNUC_MINOR__ 0 -# define __GLIBC__ 0 -# define __attribute__(x) -# if (__CC_NORCROFT_VERSION < 544) /* old version of Norcroft */ -# define inline __inline -# define STR(a) #a -# define __func__ "[" __FILE__ ":" STR(__LINE__) "]" -# endif -#else /* gcc */ -#endif - -/* #define USE_EXTERNAL_HKP */ - -#include "g10defs.h" - -#endif /*G10_CONFIG_H*/ diff --git a/scripts/conf-riscos/include/g10defs.h b/scripts/conf-riscos/include/g10defs.h deleted file mode 100644 index 6b47a6b38..000000000 --- a/scripts/conf-riscos/include/g10defs.h +++ /dev/null @@ -1,42 +0,0 @@ -/* g10defs.h - hand edited by Stefan Bellon to suit RISC OS needs - * 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 - */ - -/* Path variables and filing system constants for RISC OS */ -#define G10_LOCALEDIR ".locale" -#define GNUPG_LIBDIR "" -#define GNUPG_LIBEXECDIR "" -#define GNUPG_DATADIR "" -#define GNUPG_HOMEDIR "" -#define LOCALE_ALIAS_PATH ".locale" -#define GNULOCALEDIR ".locale" -#define DIRSEP_C '.' -#define EXTSEP_C '/' -#define DIRSEP_S "." -#define EXTSEP_S "/" - -/* This file defines some basic constants for the MPI machinery. We - * need to define the types on a per-CPU basis, so it is done with - * this file here. */ -#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) - -/* External process spawning mechanism */ -#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) -#define EXEC_TEMPFILE_ONLY 1 -#endif diff --git a/scripts/config.guess b/scripts/config.guess deleted file mode 100755 index dff9e481b..000000000 --- a/scripts/config.guess +++ /dev/null @@ -1,1317 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2001-09-04' - -# This file 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. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner . -# Please send patches to . -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - - -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - rm -f $dummy.c $dummy.o $dummy.rel ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - sparc*:NetBSD:*) - echo `uname -p`-unknown-netbsd${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; - esac - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in - big) echo mips-unknown-linux-gnu && exit 0 ;; - little) echo mipsel-unknown-linux-gnu && exit 0 ;; - esac - ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_targets=`cd /; ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-pc-linux-gnu\n", argv[1]); -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-pc-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-pc-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit 0 ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i*86:*:5:[78]*) - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then - UNAME_MACHINE=pc - fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/scripts/config.sub b/scripts/config.sub deleted file mode 100755 index 393f13d37..000000000 --- a/scripts/config.sub +++ /dev/null @@ -1,1411 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2001-09-07' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dsp16xx \ - | fr30 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el | mips64vr4300 \ - | mips64vr4300el | mips64vr5000 | mips64vr5000el \ - | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ - | mipsisa32 \ - | mn10200 | mn10300 \ - | ns16k | ns32k \ - | openrisc \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | s390 | s390x \ - | sh | sh[34] | sh[34]eb | shbe | shle \ - | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \ - | stormy16 | strongarm \ - | tahoe | thumb | tic80 | tron \ - | v850 \ - | we32k \ - | x86 | xscale \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alphapca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armv*-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c54x-* \ - | clipper-* | cray2-* | cydra-* \ - | d10v-* | d30v-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | m32r-* \ - | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ - | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ - | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | s390-* | s390x-* \ - | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \ - | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ - | v850-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | ymp) - basic_machine=ymp-cray - os=-unicos - ;; - cray2) - basic_machine=cray2-cray - os=-unicos - ;; - [cjt]90) - basic_machine=${basic_machine}-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon) - basic_machine=i686-pc - ;; - pentiumii | pentium2) - basic_machine=i686-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sparclite-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=t3e-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; - xmp) - basic_machine=xmp-cray - os=-unicos - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4 | sh3eb | sh4eb) - basic_machine=sh-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto*) - os=-nto-qnx - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -vxsim* | -vxworks*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/scripts/distfiles b/scripts/distfiles deleted file mode 100644 index 0e3d55801..000000000 --- a/scripts/distfiles +++ /dev/null @@ -1,6 +0,0 @@ -mkdiff -build-w32 -gnupg.spec.in -autogen.sh -mk-gpg-texi -mk-w32-dist \ No newline at end of file diff --git a/scripts/gnupg.spec.in b/scripts/gnupg.spec.in deleted file mode 100644 index 357f540a3..000000000 --- a/scripts/gnupg.spec.in +++ /dev/null @@ -1,177 +0,0 @@ -# -# gnupg -- gnu privacy guard -# This is a template. The dist target uses it to create the real file. -# -%define version @pkg_version@ -%define name gnupg -Summary: GNU Utility for data encryption and digital signatures -Summary(it): Utility GNU per la sicurezza nelle comunicazioni e nell'archiviazione dei dati. -Summary(cs): GNU nstroj pro ifrovanou komunikaci a bezpen ukldn dat -Summary(fr): Utilitaire GNU de chiffrement et d'authentification des communications et des donnes -Summary(pl): Narzedzie GNU do szyfrowania i podpisywania danych -Vendor: GNU Privacy Guard Project -Name: %{name} -Version: %{version} -Release: 1 -Copyright: GPL -Group: Applications/Cryptography -Group(cs): Aplikace/ifrovn -Group(fr): Applications/Cryptographie -Group(it): Applicazioni/Crittografia -Source: ftp://ftp.gnupg.org/pub/gcrypt/%{name}-%{version}.tar.gz -URL: http://www.gnupg.org -Provides: gpg openpgp -BuildRoot: /tmp/rpmbuild_%{name} - -%changelog -* Fri Apr 19 2002 David Shaw -- Removed OPTIONS and pubring.asc - no longer used -- Added doc/samplekeys.asc -* Sun Mar 31 2002 David Shaw -- Added the gpgkeys_xxx keyserver helpers. -- Added a * to catch variations on the basic gpg man page (gpg, gpgv). -- Mark options.skel as a config file. -- Do not include the FAQ/faq.html twice (in /doc/ and /share/). - -* Wed Sep 06 2000 Fabio Coatti -- Added Polish description and summary (Kindly provided by - Lukasz Stelmach ) - -* Thu Jul 13 2000 Fabio Coatti -- Added a * to catch all formats for man pages (plain, gz, bz2...) - -* Mon May 01 2000 Fabio Coatti -- Some corrections in French description, thanks to Gal Quri - ; Some corrections to Italian descriptions. - -* Tue Apr 25 2000 Fabio Coatti -- Removed the no longer needed patch for man page by Keith Owens - -* Wed Mar 1 2000 Petr Kritof -- Czech descriptions added; some fixes and updates. - -* Sat Jan 15 2000 Keith Owens -- Add missing man page as separate patch instead of updating the tar file. - -* Mon Dec 27 1999 Fabio Coatti -- Upgraded for 1.0.1 (added missing gpg.1 man page) - -* Sat May 29 1999 Fabio Coatti -- Some corrections in French description, thanks to Gal Quri - -* Mon May 17 1999 Fabio Coatti -- Added French description, provided by - Christophe Labouisse - -* Thu May 06 1999 Fabio Coatti -- Upgraded for 0.9.6 (removed gpgm) - -* Tue Jan 12 1999 Fabio Coatti -- LINGUAS variable is now unset in configure to ensure that all languages will be built. (Thanks to Luca Olivetti ) - -* Sat Jan 02 1999 Fabio Coatti -- Added pl language file. -- Included g10/pubring.asc in documentation files. - -* Sat Dec 19 1998 Fabio Coatti -- Modified the spec file provided by Caskey L. Dickson -- Now it can be built also by non-root. Installation has to be done as - root, gpg is suid. -- Added some changes by Ross Golder -- Updates for version 0.4.5 of GnuPG (.mo files) - -%description -GnuPG (GNU Privacy Guard) is a GNU utility for encrypting data and -creating digital signatures. GnuPG has advanced key management -capabilities and is compliant with the proposed OpenPGP Internet -standard described in RFC2440. Since GnuPG doesn't use any patented -algorithm, it is not compatible with any version of PGP2 (PGP2.x uses -only IDEA, patented worldwide, and RSA, which is patented in the US -until 9/20/00). - -%description -l it -GnuPG (GNU Privacy Guard) una utility GNU per la cifratura di dati e -la creazione di firme digitali. Possiede una gestione avanzata delle -chiavi ed conforme allo standard Internet OpenPGP, descritto nella -RFC 2440. Non utilizzando algoritmi brevettati, non compatibile con -PGP2 (PGP2.x usa solo IDEA, coperto da brevetto mondiale, ed RSA, -brevettato negli USA con scadenza 20/09/2000). Questi algoritmi sono -utilizzabili da GnuPG tramite moduli esterni. - -%description -l fr -GnuPG est un utilitaire GNU destin chiffrer des donnes et crer -des signatures lectroniques. Il a des capacits avances de gestion de -cls et il est conforme la norme propose OpenPGP dcrite dans la -RFC2440. Comme GnuPG n'utilise pas d'algorithme brevet, il n'est -compatible avec aucune version de PGP2 (PGP2.x ne sait utiliser que -l'IDEA brevet dans le monde entier et RSA, brevet aux tats-Unis -jusqu'au 20 septembre 2000). - -%description -l cs -GnuPG je GNU nstroj pro bezpenou komunikaci a ukldn dat. Me bt -pouit na ifrovn dat a vytven digitlnch podpis. Obsahuje -funkce pro pokroilou sprvu kl a vyhovuje navrhovanmu OpenPGP -Internet standardu podle RFC2440. Byl vytvoen jako kompletn -nhrada za PGP. Protoe neobsahuje ifrovac algoritmy IDEA nebo RSA, -me bt pouvn bez omezen. -Protoe GnuPG nepouv dn patentovan algoritmus, neme bt pln -kompatibiln s PGP verze 2. PGP 2.x pouv algoritmy IDEA (patentovno -celosvtov) a RSA (patentovno ve Spojench sttech do 20. z -2000). Tyto algoritmy lze zavst do GnuPG pomoc externch modul. - -%description -l pl -GnuPG (GNU Privacy Guard) jest nazedziem do szfrowania danych i tworzenia -cyfrowych podpisw. GnuPG posiada zaawansowane mozliwosci obslugi kluczy -i jest zgodne z OpenPGP, proponowanym standardem internetowym opisanym -w RFC2440. Poniewaz GnuPG nie uzywa zadnych opatentowanych algorytmw -nie jest wiec zgodne z jaka kolwiek wersja PGP2 (PGP2.x kozysta jedynie -z algorytmw: IDEA, opatentowanego na calym swiecie, oraz RSA, ktrego -patent na terenie Stanw Zjednoczonych wygasa 20 wrzesnia 2000). - -%prep -rm -rf $RPM_BUILD_ROOT -rm -rf $RPM_BUILD_DIR/%{name}-%{version} - -%setup - -%build -if test -n "$LINGUAS"; then - unset LINGUAS -fi -CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --enable-shared -make - -%install -make install-strip prefix=$RPM_BUILD_ROOT/usr - -%files - -%doc %attr (-,root,root) INSTALL -%doc %attr (-,root,root) AUTHORS -%doc %attr (-,root,root) COPYING -%doc %attr (-,root,root) ChangeLog -%doc %attr (-,root,root) NEWS -%doc %attr (-,root,root) README -%doc %attr (-,root,root) THANKS -%doc %attr (-,root,root) TODO -%doc %attr (-,root,root) PROJECTS -%doc %attr (-,root,root) doc/DETAILS -%doc %attr (-,root,root) doc/FAQ -%doc %attr (-,root,root) doc/faq.html -%doc %attr (-,root,root) doc/HACKING -%doc %attr (-,root,root) doc/OpenPGP -%doc %attr (-,root,root) doc/samplekeys.asc - -%attr (-,root,root) /usr/man/man1/gpg*.1* -%attr (4755,root,root) /usr/bin/gpg -%attr (-,root,root) /usr/bin/gpgkeys_* - -%attr (-,root,root) /usr/share/locale/*/*/%{name}.mo - -%attr (-,root,root) /usr/lib/%{name} - -%config %attr (-,root,root) /usr/share/%{name}/options.skel - -%clean -rm -rf $RPM_BUILD_ROOT -rm -rf $RPM_BUILD_DIR/%{name}-%{version} diff --git a/scripts/gnupgbug b/scripts/gnupgbug deleted file mode 100644 index 52efc2ab4..000000000 --- a/scripts/gnupgbug +++ /dev/null @@ -1,185 +0,0 @@ -#!/bin/sh - -# -# File a bug against the GNU Privacy Guard. -# - -# -# Copyright (c) 2000 Thomas Roessler -# -# -# 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., 675 Mass Ave, Cambridge, MA 02139, USA. -# - -SUBMIT="submit@bugs.guug.de" -DEBIAN_SUBMIT="submit@bugs.debian.org" - - -include_file () -{ - echo - echo "--- Begin $1" - sed -e 's/^-/- -/' $1 | egrep -v '^[ ]*(#|$)' - echo "--- End $1" - echo -} - -case `echo -n` in -"") n=-n; c= ;; - *) n=; c='\c' ;; -esac - - -exec > /dev/tty -exec < /dev/tty - -SCRATCH=${TMPDIR-/tmp}/`basename $0`.`hostname`.$$ - -mkdir ${SCRATCH} || \ -{ - echo "`basename $0`: Can't create temporary directory." >& 2 ; - exit 1 ; -} - -trap "rm -r -f ${SCRATCH} ; trap '' 0 ; exit" 0 1 2 - -TEMPLATE=${SCRATCH}/template.txt - -echo "Please enter a one-line description of the problem you experience:" -echo $n "> $c" -read SUBJECT - -echo $n "Do you want to include your personal GnuPG configuration files? [Y|n]$c" -read personal -case "$personal" in -[nN]*) personal=no ;; - *) personal=yes ;; -esac - -if test -f /etc/debian_version ; then - DEBIAN=yes - echo $n "Checking whether GnuPG has been installed as a package... $c" - GNUPGVERSION="`dpkg -l gnupg | grep ^i | awk '{print $3}'`" 2> /dev/null - if test "$GNUPGVERSION" ; then - DPKG=yes - else - DPKG=no - fi - echo "$DPKG" - if test "$DPKG" = "no" ; then - echo $n "File this bug with Debian? [Y|n]$c" - read $DPKG - case "$DPKG" in - [nN]) DPKG=no ;; - *) DPKG=yes ;; - esac - fi -else - DEBIAN=no - DPKG=no -fi - -test "$MUTTVERSION" || MUTTVERSION="`mutt -v | head -1 | awk '{print $2}' | tr -d i`" -test "$DPKG" = "yes" && SUBMIT="$SUBMIT, $DEBIAN_SUBMIT" - - -exec > ${TEMPLATE} - -echo "Subject: mutt-$MUTTVERSION: $SUBJECT" -echo "To: $SUBMIT" -echo "Cc: $LOGNAME" -echo -echo "Package: mutt" -echo "Version: $MUTTVERSION" -echo -echo "-- Please type your report below this line" -echo -echo -echo - -if test "$DEBIAN" = "yes" ; then - echo "Obtaining Debian-specific information..." > /dev/tty - bug -p -s dummy mutt | \ - sed -n -e "/^-- System Information/,/^---/p" | \ - grep -v '^---' -fi - -echo -echo "-- Mutt Version Information" -echo -mutt -v - -if test "$personal" = "yes" ; then - CANDIDATES=".muttrc-${MUTTVERSION} .muttrc .mutt/muttrc-${MUTTVERSION} .mutt/muttrc" - MATCHED="none" - for f in $CANDIDATES; do - if test -f "${HOME}/$f" ; then - MATCHED="${HOME}/$f" - break - fi - done - - if test "$MATCHED" = "none" ; then - echo "WARNING: Can't find your personal .muttrc." >&2 - else - include_file $MATCHED - fi -fi - -if test "$global" = "yes" ; then - CANDIDATES="Muttrc-${MUTTVERSION} Muttrc" - DIRECTORIES="/etc /usr/local/share/mutt" - MATCHED="none" - for d in $DIRECTORIES ; do - for f in $CANDIDATES; do - if test -f $d/$f ; then - MATCHED="$d/$f" - break - fi - done - test "$MATCHED" = "none" || break - done - - if test "$MATCHED" = "none" ; then - echo "WARNING: Can't find global Muttrc." >&2 - else - include_file $MATCHED - fi -fi - -exec > /dev/tty - -cp $TEMPLATE $SCRATCH/mutt-bug.txt - -input="e" -while : ; do - if test "$input" = "e" ; then - ${VISUAL-vi} $SCRATCH/mutt-bug.txt - if cmp $SCRATCH/mutt-bug.txt ${TEMPLATE} > /dev/null ; then - echo "WARNING: Bug report was not modified!" - fi - fi - - echo $n "Submit, Edit, Print, Quit? [S|e|p|q]$c" - read _input - input="`echo $_input | tr EPSQ epsq`" - case $input in - e*) ;; - p*) ${PAGER-more} $SCRATCH/mutt-bug.txt ;; - s*|"") /usr/sbin/sendmail -t < $SCRATCH/mutt-bug.txt ; exit ;; - q*) exit - esac -done - diff --git a/scripts/log_accum b/scripts/log_accum deleted file mode 100755 index 0629abb48..000000000 --- a/scripts/log_accum +++ /dev/null @@ -1,595 +0,0 @@ -#! /usr/bin/perl -# -*-Perl-*- -# -# Perl filter to handle the log messages from the checkin of files in -# a directory. This script will group the lists of files by log -# message, and mail a single consolidated log message at the end of -# the commit. -# -# This file assumes a pre-commit checking program that leaves the -# names of the first and last commit directories in a temporary file. -# -# Contributed by David Hampton -# -# hacked greatly by Greg A. Woods -# -# Modified by werner.koch@guug.de to add support for -# automagically extraction of ChangeLog entries 1998-12-29 - -# Usage: log_accum.pl [-d] [-s] [-M module] [[-m mailto] ...] [[-R replyto] ...] [-f logfile] -# -d - turn on debugging -# -m mailto - send mail to "mailto" (multiple) -# -R replyto - set the "Reply-To:" to "replyto" (multiple) -# -M modulename - set module name to "modulename" -# -f logfile - write commit messages to logfile too -# -s - *don't* run "cvs status -v" for each file -# -w - show working directory with log message - -# -# Configurable options -# - -# set this to something that takes a whole message on stdin -$MAILER = "/usr/lib/sendmail -t"; - -# -# End user configurable options. -# - -# Constants (don't change these!) -# -$STATE_NONE = 0; -$STATE_CHANGED = 1; -$STATE_ADDED = 2; -$STATE_REMOVED = 3; -$STATE_LOG = 4; - -$LAST_FILE = "/tmp/#cvs.lastdir"; - -$CHANGED_FILE = "/tmp/#cvs.files.changed"; -$ADDED_FILE = "/tmp/#cvs.files.added"; -$REMOVED_FILE = "/tmp/#cvs.files.removed"; -$LOG_FILE = "/tmp/#cvs.files.log"; - -$FILE_PREFIX = "#cvs.files"; - -# -# Subroutines -# - -sub cleanup_tmpfiles { - local($wd, @files); - - $wd = `pwd`; - chdir("/tmp") || die("Can't chdir('/tmp')\n"); - opendir(DIR, "."); - push(@files, grep(/^$FILE_PREFIX\..*\.$id$/, readdir(DIR))); - closedir(DIR); - foreach (@files) { - unlink $_; - } - unlink $LAST_FILE . "." . $id; - - chdir($wd); -} - -sub write_logfile { - local($filename, @lines) = @_; - - open(FILE, ">$filename") || die("Cannot open log file $filename.\n"); - print FILE join("\n", @lines), "\n"; - close(FILE); -} - -sub append_to_logfile { - local($filename, @lines) = @_; - - open(FILE, ">$filename") || die("Cannot open log file $filename.\n"); - print FILE join("\n", @lines), "\n"; - close(FILE); -} - -sub format_names { - local($dir, @files) = @_; - local(@lines); - - $format = "\t%-" . sprintf("%d", length($dir)) . "s%s "; - - $lines[0] = sprintf($format, $dir, ":"); - - if ($debug) { - print STDERR "format_names(): dir = ", $dir, "; files = ", join(":", @files), ".\n"; - } - foreach $file (@files) { - if (length($lines[$#lines]) + length($file) > 65) { - $lines[++$#lines] = sprintf($format, " ", " "); - } - $lines[$#lines] .= $file . " "; - } - - @lines; -} - -sub format_lists { - local(@lines) = @_; - local(@text, @files, $lastdir); - - if ($debug) { - print STDERR "format_lists(): ", join(":", @lines), "\n"; - } - @text = (); - @files = (); - $lastdir = shift @lines; # first thing is always a directory - if ($lastdir !~ /.*\/$/) { - die("Damn, $lastdir doesn't look like a directory!\n"); - } - foreach $line (@lines) { - if ($line =~ /.*\/$/) { - push(@text, &format_names($lastdir, @files)); - $lastdir = $line; - @files = (); - } else { - push(@files, $line); - } - } - push(@text, &format_names($lastdir, @files)); - - @text; -} - -sub append_names_to_file { - local($filename, $dir, @files) = @_; - - if (@files) { - open(FILE, ">>$filename") || die("Cannot open file $filename.\n"); - print FILE $dir, "\n"; - print FILE join("\n", @files), "\n"; - close(FILE); - } -} - -sub read_line { - local($line); - local($filename) = @_; - - open(FILE, "<$filename") || die("Cannot open file $filename.\n"); - $line = ; - close(FILE); - chop($line); - $line; -} - -sub read_logfile { - local(@text); - local($filename, $leader) = @_; - - open(FILE, "<$filename"); - while () { - chop; - push(@text, $leader.$_); - } - close(FILE); - @text; -} - -sub build_header { - local($header); - local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - $header = sprintf("CVSROOT:\t%s\nModule name:\t%s\nRepository:\t%s\nChanges by:\t%s@%s\t%02d/%02d/%02d %02d:%02d:%02d", - $cvsroot, - $modulename, - $dir, - $login, $hostdomain, - $year%100, $mon+1, $mday, - $hour, $min, $sec); -} - -sub mail_notification { - local(@text) = @_; - - # if only we had strftime()... stuff stolen from perl's ctime.pl: - local($[) = 0; - - @DoW = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); - @MoY = ('Jan','Feb','Mar','Apr','May','Jun', - 'Jul','Aug','Sep','Oct','Nov','Dec'); - - # Determine what time zone is in effect. - # Use GMT if TZ is defined as null, local time if TZ undefined. - # There's no portable way to find the system default timezone. - # - $TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : ''; - - # Hack to deal with 'PST8PDT' format of TZ - # Note that this can't deal with all the esoteric forms, but it - # does recognize the most common: [:]STDoff[DST[off][,rule]] - # - if ($TZ =~ /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) { - $TZ = $isdst ? $4 : $1; - $tzoff = sprintf("%05d", -($2) * 100); - } - - # perl-4.036 doesn't have the $zone or $gmtoff... - ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst, $zone, $gmtoff) = - ($TZ eq 'GMT') ? gmtime(time) : localtime(time); - - $year += ($year < 70) ? 2000 : 1900; - - if ($gmtoff != 0) { - $tzoff = sprintf("%05d", ($gmtoff / 60) * 100); - } - if ($zone ne '') { - $TZ = $zone; - } - - # ok, let's try.... - $rfc822date = sprintf("%s, %2d %s %4d %2d:%02d:%02d %s (%s)", - $DoW[$wday], $mday, $MoY[$mon], $year, - $hour, $min, $sec, $tzoff, $TZ); - - open(MAIL, "| $MAILER"); - print MAIL "Date: " . $rfc822date . "\n"; - print MAIL "Subject: CVS Update: " . $modulename . "\n"; - print MAIL "To: " . $mailto . "\n"; - print MAIL "Reply-To: " . $replyto . "\n"; - print MAIL "\n"; - print MAIL join("\n", @text), "\n"; - close(MAIL); -} - -sub write_commitlog { - local($logfile, @text) = @_; - - open(FILE, ">>$logfile"); - print FILE join("\n", @text), "\n"; - close(FILE); -} - -# -# Main Body -# - -# Initialize basic variables -# -$debug = 0; -$id = getpgrp(); # note, you *must* use a shell which does setpgrp() -$state = $STATE_NONE; -$login = getlogin || (getpwuid($<))[0] || "nobody"; -chop($hostname = `hostname`); -chop($domainname = `domainname`); -if ($domainname !~ '^\..*') { - $domainname = '.' . $domainname; -} -$hostdomain = $hostname . $domainname; -$cvsroot = $ENV{'CVSROOT'}; -$do_status = 1; # moderately useful -$show_wd = 0; # useless in client/server -$modulename = ""; - -# parse command line arguments (file list is seen as one arg) -# -while (@ARGV) { - $arg = shift @ARGV; - - if ($arg eq '-d') { - $debug = 1; - print STDERR "Debug turned on...\n"; - } elsif ($arg eq '-m') { - if ($mailto eq '') { - $mailto = shift @ARGV; - } else { - $mailto = $mailto . ", " . shift @ARGV; - } - } elsif ($arg eq '-R') { - if ($replyto eq '') { - $replyto = shift @ARGV; - } else { - $replyto = $replyto . ", " . shift @ARGV; - } - } elsif ($arg eq '-M') { - $modulename = shift @ARGV; - } elsif ($arg eq '-s') { - $do_status = 0; - } elsif ($arg eq '-w') { - $show_wd = 1; - } elsif ($arg eq '-f') { - ($commitlog) && die("Too many '-f' args\n"); - $commitlog = shift @ARGV; - } else { - ($donefiles) && die("Too many arguments! Check usage.\n"); - $donefiles = 1; - @files = split(/ /, $arg); - } -} -($mailto) || die("No mail recipient specified (use -m)\n"); -if ($replyto eq '') { - $replyto = $login; -} - -# for now, the first "file" is the repository directory being committed, -# relative to the $CVSROOT location -# -@path = split('/', $files[0]); - -# XXX There are some ugly assumptions in here about module names and -# XXX directories relative to the $CVSROOT location -- really should -# XXX read $CVSROOT/CVSROOT/modules, but that's not so easy to do, since -# XXX we have to parse it backwards. -# XXX -# XXX Fortunately it's relatively easy for the user to specify the -# XXX module name as appropriate with a '-M' via the directory -# XXX matching in loginfo. -# -if ($modulename eq "") { - $modulename = $path[0]; # I.e. the module name == top-level dir -} -if ($#path == 0) { - $dir = "."; -} else { - $dir = join('/', @path); -} -$dir = $dir . "/"; - -if ($debug) { - print STDERR "module - ", $modulename, "\n"; - print STDERR "dir - ", $dir, "\n"; - print STDERR "path - ", join(":", @path), "\n"; - print STDERR "files - ", join(":", @files), "\n"; - print STDERR "id - ", $id, "\n"; -} - -# Check for a new directory first. This appears with files set as follows: -# -# files[0] - "path/name/newdir" -# files[1] - "-" -# files[2] - "New" -# files[3] - "directory" -# -if ($files[2] =~ /New/ && $files[3] =~ /directory/) { - local(@text); - - @text = (); - push(@text, &build_header()); - push(@text, ""); - push(@text, $files[0]); - push(@text, ""); - - while () { - chop; # Drop the newline - push(@text, $_); - } - - &mail_notification($mailto, @text); - - exit 0; -} - -# Check for an import command. This appears with files set as follows: -# -# files[0] - "path/name" -# files[1] - "-" -# files[2] - "Imported" -# files[3] - "sources" -# -if ($files[2] =~ /Imported/ && $files[3] =~ /sources/) { - local(@text); - - @text = (); - push(@text, &build_header()); - push(@text, ""); - push(@text, $files[0]); - push(@text, ""); - - while () { - chop; # Drop the newline - push(@text, $_); - } - - &mail_notification(@text); - - exit 0; -} - -# Iterate over the body of the message collecting information. -# -while () { - chop; # Drop the newline - - if (/^In directory/) { - if ($show_wd) { # useless in client/server mode - push(@log_lines, $_); - push(@log_lines, ""); - } - next; - } - - if (/^Modified Files/) { $state = $STATE_CHANGED; next; } - if (/^Added Files/) { $state = $STATE_ADDED; next; } - if (/^Removed Files/) { $state = $STATE_REMOVED; next; } - if (/^Log Message/) { $state = $STATE_LOG; next; } - - s/^[ \t\n]+//; # delete leading whitespace - s/[ \t\n]+$//; # delete trailing whitespace - - if ($state == $STATE_CHANGED) { push(@changed_files, split); } - if ($state == $STATE_ADDED) { push(@added_files, split); } - if ($state == $STATE_REMOVED) { push(@removed_files, split); } - if ($state == $STATE_LOG) { - if( /^See[ ]ChangeLog:[ ](.*)/ ) { - $changelog = $1; - $okay = false; - open(RCS, "-|") || exec 'cvs', '-Qn', 'update', '-p', 'ChangeLog'; - while () { - if( /^$changelog .*/ ) { - $okay = true; - push(@log_lines, $_); - } - elsif( $okay ) { - last if( /^[A-Z]+.*/ ); - push(@log_lines, $_); - } - } - while () { ; } - close(RCS); - } - else { - push(@log_lines, $_); - } - } -} - -# Strip leading and trailing blank lines from the log message. Also -# compress multiple blank lines in the body of the message down to a -# single blank line. -# -while ($#log_lines > -1) { - last if ($log_lines[0] ne ""); - shift(@log_lines); -} -while ($#log_lines > -1) { - last if ($log_lines[$#log_lines] ne ""); - pop(@log_lines); -} -for ($i = $#log_lines; $i > 0; $i--) { - if (($log_lines[$i - 1] eq "") && ($log_lines[$i] eq "")) { - splice(@log_lines, $i, 1); - } -} - -if ($debug) { - print STDERR "Searching for log file index..."; -} -# Find an index to a log file that matches this log message -# -for ($i = 0; ; $i++) { - local(@text); - - last if (! -e "$LOG_FILE.$i.$id"); # the next available one - @text = &read_logfile("$LOG_FILE.$i.$id", ""); - last if ($#text == -1); # nothing in this file, use it - last if (join(" ", @log_lines) eq join(" ", @text)); # it's the same log message as another -} -if ($debug) { - print STDERR " found log file at $i.$id, now writing tmp files.\n"; -} - -# Spit out the information gathered in this pass. -# -&append_names_to_file("$CHANGED_FILE.$i.$id", $dir, @changed_files); -&append_names_to_file("$ADDED_FILE.$i.$id", $dir, @added_files); -&append_names_to_file("$REMOVED_FILE.$i.$id", $dir, @removed_files); -&write_logfile("$LOG_FILE.$i.$id", @log_lines); - -# Check whether this is the last directory. If not, quit. -# -if ($debug) { - print STDERR "Checking current dir against last dir.\n"; -} -$_ = &read_line("$LAST_FILE.$id"); - -if ($_ ne $cvsroot . "/" . $files[0]) { - if ($debug) { - print STDERR sprintf("Current directory %s is not last directory %s.\n", $cvsroot . "/" .$files[0], $_); - } - exit 0; -} -if ($debug) { - print STDERR sprintf("Current directory %s is last directory %s -- all commits done.\n", $files[0], $_); -} - -# -# End Of Commits! -# - -# This is it. The commits are all finished. Lump everything together -# into a single message, fire a copy off to the mailing list, and drop -# it on the end of the Changes file. -# - -# -# Produce the final compilation of the log messages -# -@text = (); -@status_txt = (); -push(@text, &build_header()); -push(@text, ""); - -for ($i = 0; ; $i++) { - last if (! -e "$LOG_FILE.$i.$id"); # we're done them all! - @lines = &read_logfile("$CHANGED_FILE.$i.$id", ""); - if ($#lines >= 0) { - push(@text, "Modified files:"); - push(@text, &format_lists(@lines)); - } - @lines = &read_logfile("$ADDED_FILE.$i.$id", ""); - if ($#lines >= 0) { - push(@text, "Added files:"); - push(@text, &format_lists(@lines)); - } - @lines = &read_logfile("$REMOVED_FILE.$i.$id", ""); - if ($#lines >= 0) { - push(@text, "Removed files:"); - push(@text, &format_lists(@lines)); - } - if ($#text >= 0) { - push(@text, ""); - } - @lines = &read_logfile("$LOG_FILE.$i.$id", "\t"); - if ($#lines >= 0) { - push(@text, "Log message:"); - push(@text, @lines); - push(@text, ""); - } - if ($do_status) { - local(@changed_files); - - @changed_files = (); - push(@changed_files, &read_logfile("$CHANGED_FILE.$i.$id", "")); - push(@changed_files, &read_logfile("$ADDED_FILE.$i.$id", "")); - push(@changed_files, &read_logfile("$REMOVED_FILE.$i.$id", "")); - - if ($debug) { - print STDERR "main: pre-sort changed_files = ", join(":", @changed_files), ".\n"; - } - sort(@changed_files); - if ($debug) { - print STDERR "main: post-sort changed_files = ", join(":", @changed_files), ".\n"; - } - - foreach $dofile (@changed_files) { - if ($dofile =~ /\/$/) { - next; # ignore the silly "dir" entries - } - if ($debug) { - print STDERR "main(): doing 'cvs -nQq status -v $dofile'\n"; - } - open(STATUS, "-|") || exec 'cvs', '-nQq', 'status', '-v', $dofile; - while () { - chop; - push(@status_txt, $_); - } - } - } -} - -# Write to the commitlog file -# -if ($commitlog) { - &write_commitlog($commitlog, @text); -} - -if ($#status_txt >= 0) { - push(@text, @status_txt); -} - -# Mailout the notification. -# -&mail_notification(@text); - -# cleanup -# -if (! $debug) { - &cleanup_tmpfiles(); -} - -exit 0; diff --git a/scripts/mail-to-translators b/scripts/mail-to-translators deleted file mode 100755 index 10210a73f..000000000 --- a/scripts/mail-to-translators +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# mail a compressed version of the current translation to the Last-Translator -# - -# remove the colon to armor this script. -SENDMAIL=": /usr/sbin/sendmail" - -for file in *.po; do - addr=$(awk '/Last-Translator:/ { printf "%s", $0; exit 0}' $file | sed 's/.*\(<.*>\).*/\1/') - ll=$(basename $file .po) - - if ! msgfmt -vc $file 2>&1| egrep -q 'fuzzy|untranslated|error'; then - echo "$file: okay" >&2 - continue; - fi - - if ! echo "$addr" | grep -q @ ; then - echo "$file: no translator known" >&2 - continue; - fi - - echo "$file: sending to $addr" - ( cat <&1 | head) - -If you are not able to continue the translation work, I suggest to -pass this message on to another translator and drop me a short note. - -Thanks, - - Werner - - ---=-=-= -Content-Type: application/octet-stream -Content-Disposition: attachment; filename=gnupg-${file}.gz -Content-Transfer-Encoding: base64 - -EOF - -gzip <$file | mimencode - -echo "" -echo "--=-=-=--" -echo "" - ) | $SENDMAIL -oi "$addr" - -done diff --git a/scripts/mk-gpg-texi b/scripts/mk-gpg-texi deleted file mode 100755 index 45a811742..000000000 --- a/scripts/mk-gpg-texi +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# Helper to create the texinfo versions from gpg.sgml -# -# Copyright (C) 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 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. - -set -e - -for file in gpg gpgv; do - sgml2xml -x lower ${file}.sgml >${file}.xml - docbook2texi ${file}.xml | sed 's,--,---,' | ( - case "$file" in - *gpgv) - sed '/@setfilename/a \ -@dircategory GnuPG\ -@direntry\ -* gpgv: (gpgv). GnuPG signature verification tool.\ -@end direntry -' - ;; - - gpg) - sed '/@setfilename/a \ -@dircategory GnuPG\ -@direntry\ -* gpg: (gpg). GnuPG encryption and signing tool.\ -@end direntry -' - ;; - - *) - cat - ;; - esac - ) >${file}.texi -done - - - diff --git a/scripts/mk-w32-dist b/scripts/mk-w32-dist deleted file mode 100755 index 378278a99..000000000 --- a/scripts/mk-w32-dist +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2000, 2001 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 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. - - -set -e - -cd dist-w32 - -bindir=.. - -if [ -f ../README ]; then - srcdir=.. -elif [ -f ../../README ]; then - srcdir=../.. - bindir=.. -elif [ -f ../../gnupg-stable/README ]; then - srcdir=../../gnupg-stable -elif [ -f ../../../gnupg-stable/README ]; then - srcdir=../../../gnupg-stable -else - echo "cannot figure out the source dir" >&2 - exit 1 -fi - -version=$(sed -n 's/^#[ ]*define[ ][ ]*VERSION[ ][ ]*\"\([0-9.]*\)\"/\1/p' $bindir/config.h) -echo "building version $version" - -rm * || true - -cp ${bindir}/g10/gpg.exe gpg.exe -mingw32 strip gpg.exe -cp ${bindir}/g10/gpgv.exe gpgv.exe -mingw32 strip gpgv.exe -cp ${bindir}/tools/gpgsplit.exe gpgsplit.exe -mingw32 strip gpgsplit.exe - -for i in FAQ; do - cp ${bindir}/doc/$i . - todos $i -done -man -Tlatin1 -l ${srcdir}/doc/gpg.1 | sed `printf "s/\b.//g"` >gpg.man -todos gpg.man -man -Tlatin1 -l ${srcdir}/doc/gpgv.1 | sed `printf "s/\b.//g"` >gpgv.man -todos gpgv.man -man -Tlatin1 -l ${srcdir}/doc/gnupg.7 | sed `printf "s/\b.//g"` >gnupg.man -todos gnupg.man -for i in README COPYING; do - cp ${srcdir}/$i . - todos $i -done -for i in README.W32 gnupg-w32.reg; do - cp ${srcdir}/doc/$i . - todos $i -done - - -for i in ${srcdir}/po/*.po; do - lang=$(basename $i .po) - fromset=`sed -n '/^"Content-Type:/ s/.*charset=\([a-zA-Z0-9_-]*\).*/\1/p' $i` - case $lang in - cs|pl) toset="CP1250" ;; - tr) toset="CP1254" ;; # DOS: CP857 - el) toset="CP1253" ;; # same as latin-7? - el|eo|et|ja) toset="" ;; - *) toset="CP850" ;; - esac - if [ -n "$toset" ]; then - echo "$lang: converting from $fromset to $toset" >&2 - iconv --silent --from-code=$fromset --to-code=$toset < $i | \ - sed "/^\"Content-Type:/ s/charset=[a-zA-Z0-9_-]*/charset=$toset/" | \ - msgfmt --output-file=$lang.mo - - else - echo "$lang: keeping $fromset" >&2 - msgfmt --output-file=$lang.mo $i - fi -done -zip -9 "gnupg-w32cli-${version}.zip" * - - - - diff --git a/scripts/mkdiff b/scripts/mkdiff deleted file mode 100755 index f17979383..000000000 --- a/scripts/mkdiff +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/sh -# Copyright (C) 1998, 1999, 2000, 2001 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 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. - -# Please note that this script is now maintained outside of GNUPG. -# To get the most up to date version use -# cvs -d :pserver:anoncvs@cvs.gnupg.org:/cvs/wk checkout misc-scripts/mkdiff - -if [ $# != 1 ] ; then - echo "usage: mkdiff package-name" >&2 - exit 1 -fi - -pack="$1" - -set -e - -curr_ver=$(ls $pack-*.tar.gz 2>/dev/null | sed "s/^$pack-\(.*\)\.tar\.gz/\1/"\ - | sort -r -t '.' -n +0 -1 +1 -2 +2 | head -1 ) -if [ ! -f $pack-$curr_ver.tar.gz ]; then - echo "mkdiff: no current version of package $pack found" >&2 - exit 1 -fi -prev_ver=$(ls $pack-*.tar.gz 2>/dev/null | sed "s/^$pack-\(.*\)\.tar\.gz/\1/"\ - | sort -r -t '.' -n +0 -1 +1 -2 +2 | head -2 | tail -1 ) -if [ "$prev_ver" = "$curr_ver" ]; then - echo "mkdiff: no previous version of package $pack found" >&2 - exit 1 -fi - -echo "Current is: $pack-$curr_ver" -echo "Previous is: $pack-$prev_ver" - - -echo "Removing old directories" -[ -d "$pack-$curr_ver" ] && rm -rf "$pack-$curr_ver" -[ -d "$pack-$prev_ver" ] && rm -rf "$pack-$prev_ver" - -echo "Unpacking previous and current tar" -tar xzf "$pack-$curr_ver.tar.gz" -rm -f $pack-${curr_ver}/po/*.gmo -tar xzf "$pack-$prev_ver.tar.gz" -rm -f $pack-${prev_ver}/po/*.gmo - - -echo "Diffing" -tmp_name="$pack-$prev_ver-$curr_ver.diff.tmp" -diff_name="$pack-$prev_ver-$curr_ver.diff" - -diff -urN "$pack-$prev_ver/" "$pack-$curr_ver/" > $tmp_name || true - -echo "Making patch file" - -cat < $diff_name - -This is a patch file to create version $curr_ver from $prev_ver. - -Please check the signature of this patch file: - - zcat somepath/$pack-$prev_ver-$curr_ver.diff.gz | gpg --verify - -Change to directory $pack-$prev_ver (or however you renamed it) -and give this command: - - zcat somepath/$pack-$prev_ver-$curr_ver.diff.gz | patch -p1 - -It is a good idea to rename your current directory to $pack-$curr_ver now. - - - -Prereq: $prev_ver - -EOF - -sed -ne '/^diff.*VERSION/,/^+[0-9][0-9]*/ p' $tmp_name >> $diff_name -echo >> $diff_name -sed -e '/^diff.*VERSION/,/^+[0-9][0-9]*/ d' $tmp_name >> $diff_name - -rm $tmp_name - -echo "Signing and compressing patch file" -gpg --clearsign --not-dash-escaped -u 57548DCD \ - < $diff_name | gzip --best > $diff_name.gz -rm $diff_name - -echo "Checking patch file" -cd $pack-$prev_ver -zcat ../$diff_name.gz | patch -s -p1 -rm $(find . -name "*.orig") 2>/dev/null || true -cd .. - -if ! diff -urN "$pack-$prev_ver/" "$pack-$curr_ver/" >/dev/null ; then - echo "compare failed" - exit 1 -fi - -if ! zcat $diff_name.gz | gpg --batch --verify ; then - exit 1 -fi - - -echo "cleaning up" - -rm -rf "$pack-$curr_ver" -rm -rf "$pack-$prev_ver" - -echo "Patch file $diff_name.gz is good." - diff --git a/scripts/mkinstalldirs b/scripts/mkinstalldirs deleted file mode 100755 index 994d71ce7..000000000 --- a/scripts/mkinstalldirs +++ /dev/null @@ -1,101 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id$ - -errstatus=0 -dirmode="" - -usage="\ -Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." - -# process command line arguments -while test $# -gt 0 ; do - case "${1}" in - -h | --help | --h* ) # -h for help - echo "${usage}" 1>&2; exit 0 ;; - -m ) # -m PERM arg - shift - test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } - dirmode="${1}" - shift ;; - -- ) shift; break ;; # stop option processing - -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option - * ) break ;; # first non-opt arg - esac -done - -for file -do - if test -d "$file"; then - shift - else - break - fi -done - -case $# in -0) exit 0 ;; -esac - -case $dirmode in -'') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi ;; -*) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi ;; -esac - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" - - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? - - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# Local Variables: -# mode: shell-script -# sh-indentation: 3 -# End: -# mkinstalldirs ends here diff --git a/scripts/mksnapshot b/scripts/mksnapshot deleted file mode 100755 index cca19d98d..000000000 --- a/scripts/mksnapshot +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh -# Make a snapshot of the CVS head revision - -exec >>/home/koch/mksnapshot.log 2>&1 - -echo "Started at `date`." -set -e - -ftp_dir=$1 - -cd $HOME/pub -PATH="$HOME/bin:$PATH" - -fix_version () { - version=$(cat $1/VERSION) - echo "$version-snap$(date +%Y-%m-%d)" >$1/VERSION - cat <$1/SNAPSHOT - WARNING! - -This is a snapshot of the current CVS head branch! - -It may not compile or not work. Please don't report -bugs about this snapshot release it is just for your -convenience and to reduce the load of out CVS server. - -Thanks, - - Werner -EOF -} - -build_dist () { - set +e - nice scripts/autogen.sh && nice ./configure && nice make dist - if ! awk ' -/^diff gnupg-snapshot\/VERSION/ { getline; getline; getline; getline; next } -/^Common subdirectories:/ { next } -/~$/ { next } -{ exit 1 } -' ; then - # Okay, we have some changes and it is not only the version number - rm $ftp_dir/gnupg-*snap*-*-*.tar.gz - mv gnupg-*.tar.gz $ftp_dir/ - fi - make distclean - set -e -} - - - -do_export () { - pgm=$1 - mod=$2 - - rm -rf $pgm.new || true - rm -rf $pgm.old || true - cvs -Q export -r HEAD -d $pgm.new $mod - fix_version $pgm.new - if [ -n "$ftp_dir" ]; then - here=$(pwd) - cd $pgm.new - build_dist - cd $here - fi - [ -d $pgm ] && mv $pgm $pgm.old - if ! mv $pgm.new $pgm ; then - echo "rename failed - restoring" >&2 - mv $pgm.old $pgm - exit 1 - fi - rm -rf $pgm.old || true -} - - -do_export gnupg-snapshot gnupg - -echo "Ended at `date`." -exit 0 - diff --git a/scripts/mkwebpage b/scripts/mkwebpage deleted file mode 100755 index b39feb176..000000000 --- a/scripts/mkwebpage +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/sh -# Make a snapshot of the CVS head revision for the gnupg webpages - - -set -e - -cd $HOME/pub - -extract_date () { - # This strange construct is to speed up things. Grouping a "s" and a "q" - # does not work. Anyway we should use awk instead. - # Have to quote the I from $Id so that CVS does not expand it - sed '/^.*\$[I]d:.*\$.*$/q' $1 | - sed -n 's!^.*\$[I]d: [^ ]\+ [^ ]\+ \([0-9]*\)/\([0-9]*\)/\([0-9]*\) [^ ]\+ \([^ ]\+\).*$!\1-\2-\3 \4!p' -} - -# We have to edit most files -sed_it () { - src=$1 - dst=$2 - - for srcdir in `find $src -type d -print` ; do - dstdir=`echo "$srcdir" | sed "s/^$src/$dst/g"` - mkdir $dstdir || true - for sf in `find $srcdir -type f -maxdepth 1 -print`; do - updated=`extract_date $sf` - df="$dstdir/`basename $sf`" - case "$df" in - *.html) - sed "/@FOOTER@/ { - r $src/footer.html.inc - d - } - /^$/ { - r $src/body-tag.html.inc - d - } - /@UPDATED@/c\\ -Updated: $updated \\ -
- /@INSERT_BUGLIST_HERE@/ { - r $src/BUGS - d - } - /@HOSTEDBY@/ { - r $src/hostedby.html.inc - d - } - " $sf > $df - ;; - *.html.inc | *~ | *.tmp | */BUGS ) - : - ;; - *) - cat $sf > $df - ;; - esac - done - done -} - - -do_export () { - pgm=$1 - mod=$2 - - rm -rf $pgm.tmp 2>/dev/null || true - rm -rf $pgm.new || true - rm -rf $pgm.old || true - cvs -Q export -r HEAD -d $pgm.tmp $mod - cat <$pgm.tmp/NEWS -[ This is a snapshot of the NEWS file from the CVS head revision. - You will find the NEWS for the latest revision below the line - "Noteworthy changes in version 0.x.y". - (wk $(date +%Y-%m-%d)) ] - - -EOF - cvs -Q checkout -p gnupg/NEWS >>$pgm.tmp/NEWS - cvs -Q checkout -p gnupg/BUGS | sed '1,/^~~~~~~~~~~~/ d' > $pgm.tmp/BUGS - echo "(List generated from CVS: " $(date +%Y-%m-%d) ")" >> $pgm.tmp/BUGS - sed_it $pgm.tmp $pgm.new - rm -rf $pgm.tmp || true - ln -sf gnupg.html $pgm.new/index.html - - rm -rf $pgm.old || true - [ -d $pgm ] && mv $pgm $pgm.old - if ! mv $pgm.new $pgm ; then - echo "rename failed - restoring" >&2 - mv $pgm.old $pgm - exit 1 - fi - rm -rf $pgm.old || true -} - - -do_export gnupg-www gnupg-www - -#cd gnupg-www -#tar czf /home/ftp/pub/gcrypt/.old/webpages.tmp * -#mv /home/ftp/pub/gcrypt/old/webpages.tmp /home/ftp/pub/gcrypt/old/webpages.tar.gz - - -exit 0 - diff --git a/sm/ChangeLog b/sm/ChangeLog deleted file mode 100644 index 8e11e0ddf..000000000 --- a/sm/ChangeLog +++ /dev/null @@ -1,741 +0,0 @@ -2002-09-19 Werner Koch - - * certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging. - - * certchain.c (find_up): Print info when the cert was not found - by the autorithyKeyIdentifier. - -2002-09-03 Werner Koch - - * gpgsm.c (main): Disable the internal libgcrypt locking. - -2002-08-21 Werner Koch - - * import.c (print_imported_summary): Cleaned up. Print new - not_imported value. - (check_and_store): Update non_imported counter. - (print_import_problem): New. - (check_and_store): Print error status message. - * server.c (get_status_string): Added STATUS_IMPORT_PROBLEM. - -2002-08-20 Werner Koch - - * gpgsm.c (main): Use the log file only in server mode. - - * import.c (print_imported_summary): New. - (check_and_store): Update the counters, take new argument. - (import_one): Factored out core of gpgsm_import. - (gpgsm_import): Print counters. - (gpgsm_import_files): New. - * gpgsm.c (main): Use the new function for import. - -2002-08-19 Werner Koch - - * decrypt.c (gpgsm_decrypt): Return a better error status token. - * verify.c (gpgsm_verify): Don't error on messages with no signing - time or no message digest. This is only the case for messages - without any signed attributes. - -2002-08-16 Werner Koch - - * certpath.c: Renamed to .. - * certchain.c: this. Renamed all all other usages of "path" in the - context of certificates to "chain". - - * call-agent.c (learn_cb): Special treatment when the issuer - certificate is missing. - -2002-08-10 Werner Koch - - * Makefile.am (INCLUDES): Add definition for localedir. - - * keylist.c (list_cert_colon): Print the short fingerprint in the - key ID field. - * fingerprint.c (gpgsm_get_short_fingerprint): New. - * verify.c (gpgsm_verify): Print more verbose info for a good - signature. - -2002-08-09 Werner Koch - - * decrypt.c (prepare_decryption): Hack to detected already - unpkcsedone keys. - - * gpgsm.c (emergency_cleanup): New. - (main): Initialize the signal handler. - - * sign.c (gpgsm_sign): Reset the hash context for subsequent - signers and release it at the end. - -2002-08-05 Werner Koch - - * server.c (cmd_signer): New command "SIGNER" - (register_commands): Register it. - (cmd_sign): Pass the signer list to gpgsm_sign. - * certlist.c (gpgsm_add_to_certlist): Add SECRET argument, check - for secret key if set and changed all callers. - * sign.c (gpgsm_sign): New argument SIGNERLIST and implemt - multiple signers. - * gpgsm.c (main): Support more than one -u. - - * server.c (cmd_recipient): Return reason code 1 for No_Public_Key - which is actually what gets returned from add_to_certlist. - -2002-07-26 Werner Koch - - * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup. - (gpgsm_check_cms_signature): Ditto. - -2002-07-22 Werner Koch - - * keydb.c (keydb_add_resource): Register a lock file. - (lock_all, unlock_all): Implemented. - - * delete.c: New. - * gpgsm.c: Made --delete-key work. - * server.c (cmd_delkeys): New. - (register_commands): New command DELKEYS. - - * decrypt.c (gpgsm_decrypt): Print a convenience note when RC2 is - used and a STATUS_ERROR with the algorithm oid. - -2002-07-03 Werner Koch - - * server.c (gpgsm_status2): Insert a blank between all optional - arguments when using assuan. - * server.c (cmd_recipient): No more need for extra blank in constants. - * import.c (print_imported_status): Ditto. - * gpgsm.c (main): Ditto. - -2002-07-02 Werner Koch - - * verify.c (gpgsm_verify): Extend the STATUS_BADSIG line with - the fingerprint. - - * certpath.c (check_cert_policy): Don't use log_error to print a - warning. - - * keydb.c (keydb_store_cert): Add optional ar EXISTED and changed - all callers. - * call-agent.c (learn_cb): Print info message only for real imports. - - * import.c (gpgsm_import): Moved duplicated code to ... - (check_and_store): new function. Added magic to import the entire - chain. Print status only for real imports and moved printing code - to .. - (print_imported_status): New. - - * call-dirmngr.c (gpgsm_dirmngr_isvalid): print status of dirmngr - call in very verbose mode. - - * gpgsm.c (main): Use the same error codes for STATUS_INV_RECP as - with the server mode. - -2002-06-29 Werner Koch - - * gpgsm.c: New option --auto-issuer-key-retrieve. - * certpath.c (find_up): Try to retrieve an issuer key from an - external source and from the ephemeral key DB. - (find_up_store_certs_cb): New. - - * keydb.c (keydb_set_ephemeral): Does now return the old - state. Call the backend only when required. - - * call-dirmngr.c (start_dirmngr): Use GNUPG_DEFAULT_DIRMNGR. - (lookup_status_cb): Issue status only when CTRL is not NULL. - (gpgsm_dirmngr_lookup): Document that CTRL is optional. - - * call-agent.c (start_agent): Use GNUPG_DEFAULT_AGENT. - -2002-06-28 Werner Koch - - * server.c (cmd_recipient): Add more reason codes. - -2002-06-27 Werner Koch - - * certpath.c (gpgsm_basic_cert_check): Use - --debug-no-path-validation to also bypass this basic check. - - * gpgsm.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. - - * call-agent.c (start_agent): Create and pass the list of FD to - keep in the child to assuan. - * call-dirmngr.c (start_dirmngr): Ditto. - -2002-06-26 Werner Koch - - * import.c (gpgsm_import): Print an STATUS_IMPORTED. - - * gpgsm.c: --debug-no-path-validation does not take an argument. - -2002-06-25 Werner Koch - - * certdump.c (print_dn_part): Always print a leading slash, - removed NEED_DELIM arg and changed caller. - - * export.c (gpgsm_export): Print LFs to FP and not stdout. - (print_short_info): Ditto. Make use of gpgsm_print_name. - - * server.c (cmd_export): Use output-fd instead of data lines; this - was actually the specified way. - -2002-06-24 Werner Koch - - * gpgsm.c: Removed duped help entry for --list-keys. - - * gpgsm.c, gpgsm.h: New option --debug-no-path-validation. - - * certpath.c (gpgsm_validate_path): Use it here instead of the - debug flag hack. - - * certpath.c (check_cert_policy): Return No_Policy_Match if the - policy file could not be opened. - -2002-06-20 Werner Koch - - * certlist.c (gpgsm_add_to_certlist): Fixed locating of a - certificate with the required key usage. - - * gpgsm.c (main): Fixed a segv when using --outfile without an - argument. - - * keylist.c (print_capabilities): Also check for non-repudiation - and data encipherment. - * certlist.c (cert_usage_p): Test for signing and encryption was - swapped. Add a case for certification usage, handle - non-repudiation and data encipherment. - (gpgsm_cert_use_cert_p): New. - (gpgsm_add_to_certlist): Added a CTRL argument and changed all - callers to pass it. - * certpath.c (gpgsm_validate_path): Use it here to print a status - message. Added a CTRL argument and changed all callers to pass it. - * decrypt.c (gpgsm_decrypt): Print a status message for wrong key - usage. - * verify.c (gpgsm_verify): Ditto. - * keydb.c (classify_user_id): Allow a colon delimited fingerprint. - -2002-06-19 Werner Koch - - * call-agent.c (learn_cb): Use log_info instead of log_error on - successful import. - - * keydb.c (keydb_set_ephemeral): New. - (keydb_store_cert): New are ephemeral, changed all callers. - * keylist.c (list_external_cb): Store cert as ephemeral. - * export.c (gpgsm_export): Kludge to export epehmeral certificates. - - * gpgsm.c (main): New command --list-external-keys. - -2002-06-17 Werner Koch - - * certreqgen.c (read_parameters): Improved error handling. - (gpgsm_genkey): Print error message. - -2002-06-13 Werner Koch - - * gpgsm.c (main): New option --log-file. - -2002-06-12 Werner Koch - - * call-dirmngr.c (lookup_status_cb): New. - (gpgsm_dirmngr_lookup): Use the status CB. Add new arg CTRL and - changed caller to pass it. - - * gpgsm.c (open_fwrite): New. - (main): Allow --output for --verify. - - * sign.c (hash_and_copy_data): New. - (gpgsm_sign): Implemented normal (non-detached) signatures. - * gpgsm.c (main): Ditto. - - * certpath.c (gpgsm_validate_path): Special error handling for - no policy match. - -2002-06-10 Werner Koch - - * server.c (get_status_string): Add STATUS_ERROR. - - * certpath.c (gpgsm_validate_path): Tweaked the error checking to - return error codes in a more sensitive way. - * verify.c (gpgsm_verify): Send status TRUST_NEVER also for a bad - CA certificate and when the certificate has been revoked. Issue - TRUST_FULLY even when the cert has expired. Append an error token - to these status lines. Issue the new generic error status when a - cert was not found and when leaving the function. - -2002-06-04 Werner Koch - - * gpgsm.c (main): New command --list-sigs - * keylist.c (list_cert_std): New. Use it whenever colon mode is - not used. - (list_cert_chain): New. - -2002-05-31 Werner Koch - - * gpgsm.c (main): Don't print the "go ahead" message for an - invalid command. - -2002-05-23 Werner Koch - - * import.c (gpgsm_import): Add error messages. - -2002-05-21 Werner Koch - - * keylist.c (list_internal_keys): Renamed from gpgsm_list_keys. - (list_external_keys): New. - (gpgsm_list_keys): Dispatcher for above. - * call-dirmngr.c (lookup_cb,pattern_from_strlist) - (gpgsm_dirmngr_lookup): New. - * server.c (option_handler): Handle new option --list-mode. - (do_listkeys): Handle options and actually use the mode argument. - (get_status_string): New code TRUNCATED. - - * import.c (gpgsm_import): Try to identify the type of input and - handle certs-only messages. - -2002-05-14 Werner Koch - - * gpgsm.c: New option --faked-system-time - * sign.c (gpgsm_sign): And use it here. - * certpath.c (gpgsm_validate_path): Ditto. - -2002-05-03 Werner Koch - - * certpath.c (gpgsm_validate_path): Added EXPTIME arg and changed - all callers. - * verify.c (gpgsm_verify): Tweaked usage of log_debug and - log_error. Return EXPSIG status and add expiretime to VALIDSIG. - -2002-04-26 Werner Koch - - * gpgsm.h (DBG_AGENT,DBG_AGENT_VALUE): Replaced by DBG_ASSUAN_*. - Changed all users. - - * call-agent.c (start_agent): Be more silent without -v. - * call-dirmngr.c (start_dirmngr): Ditto. - -2002-04-25 Werner Koch - - * call-agent.c (start_agent): Make copies of old locales and check - for setlocale. - -2002-04-25 Marcus Brinkmann - - * call-agent.c (start_agent): Fix error handling logic so the - locale is always correctly reset. - -2002-04-25 Marcus Brinkmann - - * server.c (option_handler): Accept display, ttyname, ttytype, - lc_ctype and lc_messages options. - * gpgsm.c (main): Allocate memory for these options. - * gpgsm.h (struct opt): Make corresponding members non-const. - -2002-04-24 Marcus Brinkmann - - * gpgsm.h (struct opt): New members display, ttyname, ttytype, - lc_ctype, lc_messages. - * gpgsm.c (enum cmd_and_opt_values): New members oDisplay, - oTTYname, oTTYtype, oLCctype, oLCmessages. - (opts): New entries for these options. - (main): Handle these new options. - * call-agent.c (start_agent): Set the various display and tty - parameter after resetting. - -2002-04-18 Werner Koch - - * certreqgen.c (gpgsm_genkey): Write status output on success. - -2002-04-15 Werner Koch - - * gpgsm.c (main): Check ksba version. - - * certpath.c (find_up): New to use the authorithKeyIdentifier. - Use it in all other functions to locate the signing cert.. - -2002-04-11 Werner Koch - - * certlist.c (cert_usable_p): New. - (gpgsm_cert_use_sign_p,gpgsm_cert_use_encrypt_p): New. - (gpgsm_cert_use_verify_p,gpgsm_cert_use_decrypt_p): New. - (gpgsm_add_to_certlist): Check the key usage. - * sign.c (gpgsm_sign): Ditto. - * verify.c (gpgsm_verify): Print a message wehn an unsuitable - certificate was used. - * decrypt.c (gpgsm_decrypt): Ditto - * keylist.c (print_capabilities): Determine values from the cert. - -2002-03-28 Werner Koch - - * keylist.c (list_cert_colon): Fixed listing of crt record; the - issuer is not at the right place. Print a chainingID. - * certpath.c (gpgsm_walk_cert_chain): Be a bit more silent on - common errors. - -2002-03-21 Werner Koch - - * export.c: New. - * gpgsm.c: Add command --export. - * server.c (cmd_export): New. - -2002-03-13 Werner Koch - - * decrypt.c (gpgsm_decrypt): Allow multiple recipients. - -2002-03-12 Werner Koch - - * certpath.c (check_cert_policy): Print the policy list. - - * verify.c (gpgsm_verify): Detect certs-only message. - -2002-03-11 Werner Koch - - * import.c (gpgsm_import): Print a notice about imported certificates - when in verbose mode. - - * gpgsm.c (main): Print INV_RECP status. - * server.c (cmd_recipient): Ditto. - - * server.c (gpgsm_status2): New. Allows for a list of strings. - (gpgsm_status): Divert to gpgsm_status2. - - * encrypt.c (gpgsm_encrypt): Don't use a default key when no - recipients are given. Print a NO_RECP status. - -2002-03-06 Werner Koch - - * server.c (cmd_listkeys, cmd_listsecretkeys): Divert to - (do_listkeys): new. Add pattern parsing. - - * keylist.c (gpgsm_list_keys): Handle selection pattern. - - * gpgsm.c: New command --learn-card - * call-agent.c (learn_cb,gpgsm_agent_learn): New. - - * gpgsm.c (main): Print error messages for non-implemented commands. - - * base64.c (base64_reader_cb): Use case insensitive compare of the - Content-Type string to detect plain base-64. - -2002-03-05 Werner Koch - - * gpgsm.c, gpgsm.h: Add local_user. - * sign.c (gpgsm_get_default_cert): New. - (get_default_signer): Use the new function if local_user is not - set otherwise used that value. - * encrypt.c (get_default_recipient): Removed. - (gpgsm_encrypt): Use gpgsm_get_default_cert. - - * verify.c (gpgsm_verify): Better error text for a bad signature - found by comparing the hashs. - -2002-02-27 Werner Koch - - * call-dirmngr.c, call-agent.c: Add 2 more arguments to all uses - of assuan_transact. - -2002-02-25 Werner Koch - - * server.c (option_handler): Allow to use -2 for "send all certs - except the root cert". - * sign.c (add_certificate_list): Implement it here. - * certpath.c (gpgsm_is_root_cert): New. - -2002-02-19 Werner Koch - - * certpath.c (check_cert_policy): New. - (gpgsm_validate_path): And call it from here. - * gpgsm.c (main): New options --policy-file, - --disable-policy-checks and --enable-policy-checks. - * gpgsm.h (opt): Added policy_file, no_policy_checks. - -2002-02-18 Werner Koch - - * certpath.c (gpgsm_validate_path): Ask the agent to add the - certificate into the trusted list. - * call-agent.c (gpgsm_agent_marktrusted): New. - -2002-02-07 Werner Koch - - * certlist.c (gpgsm_add_to_certlist): Check that the specified - name identifies a certificate unambiguously. - (gpgsm_find_cert): Ditto. - - * server.c (cmd_listkeys): Check that the data stream is available. - (cmd_listsecretkeys): Ditto. - (has_option): New. - (cmd_sign): Fix ambiguousity in option recognition. - - * gpgsm.c (main): Enable --logger-fd. - - * encrypt.c (gpgsm_encrypt): Increased buffer size for better - performance. - - * call-agent.c (gpgsm_agent_pksign): Check the S-Exp received from - the agent. - - * keylist.c (list_cert_colon): Filter out control characters. - -2002-02-06 Werner Koch - - * decrypt.c (gpgsm_decrypt): Bail out after an decryption error. - - * server.c (reset_notify): Close input and output FDs. - (cmd_encrypt,cmd_decrypt,cmd_verify,cmd_sign.cmd_import) - (cmd_genkey): Close the FDs and release the recipient list even in - the error case. - -2002-02-01 Marcus Brinkmann - - * sign.c (gpgsm_sign): Do not release certificate twice. - -2002-01-29 Werner Koch - - * call-agent.c (gpgsm_agent_havekey): New. - * keylist.c (list_cert_colon): New arg HAVE_SECRET, print "crs" - when we know that the secret key is available. - (gpgsm_list_keys): New arg MODE, check whether a secret key is - available. Changed all callers. - * gpgsm.c (main): New command --list-secret-keys. - * server.c (cmd_listsecretkeys): New. - (cmd_listkeys): Return secret keys with "crs" record. - -2002-01-28 Werner Koch - - * certreqgen.c (create_request): Store the email address in the req. - -2002-01-25 Werner Koch - - * gpgsm.c (main): Disable core dumps. - - * sign.c (add_certificate_list): New. - (gpgsm_sign): Add the certificates to the CMS object. - * certpath.c (gpgsm_walk_cert_chain): New. - * gpgsm.h (server_control_s): Add included_certs. - * gpgsm.c: Add option --include-certs. - (gpgsm_init_default_ctrl): New. - (main): Call it. - * server.c (gpgsm_server): Ditto. - (option_handler): Support --include-certs. - -2002-01-23 Werner Koch - - * certpath.c (gpgsm_validate_path): Print the DN of a missing issuer. - * certdump.c (gpgsm_dump_string): New. - (print_dn): Replaced by above. - -2002-01-22 Werner Koch - - * certpath.c (unknown_criticals): New. - (allowed_ca): New. - (gpgsm_validate_path): Check validity, CA attribute, path length - and unknown critical extensions. - -2002-01-21 Werner Koch - - * gpgsm.c: Add option --enable-crl-checks. - - * call-agent.c (start_agent): Implemented socket based access. - * call-dirmngr.c (start_dirmngr): Ditto. - -2002-01-20 Werner Koch - - * server.c (option_handler): New. - (gpgsm_server): Register it with assuan. - -2002-01-19 Werner Koch - - * server.c (gpgsm_server): Use assuan_deinit_server and setup - assuan logging if enabled. - * call-agent.c (inq_ciphertext_cb): Don't show the session key in - an Assuan log file. - - * gpgsm.c (my_strusage): Take bugreport address from configure.ac - -2002-01-15 Werner Koch - - * import.c (gpgsm_import): Just do a basic cert check before - storing it. - * certpath.c (gpgsm_basic_cert_check): New. - - * keydb.c (keydb_store_cert): New. - * import.c (store_cert): Removed and change all caller to use - the new function. - * verify.c (store_cert): Ditto. - - * certlist.c (gpgsm_add_to_certlist): Validate the path - - * certpath.c (gpgsm_validate_path): Check the trust list. - * call-agent.c (gpgsm_agent_istrusted): New. - -2002-01-14 Werner Koch - - * call-dirmngr.c (inq_certificate): Changed for new interface semantic. - * certlist.c (gpgsm_find_cert): New. - -2002-01-13 Werner Koch - - * fingerprint.c (gpgsm_get_certid): Print the serial and not the - hash after the dot. - -2002-01-11 Werner Koch - - * call-dirmngr.c: New. - * certpath.c (gpgsm_validate_path): Check the CRL here. - * fingerprint.c (gpgsm_get_certid): New. - * gpgsm.c: New options --dirmngr-program and --disable-crl-checks. - -2002-01-10 Werner Koch - - * base64.c (gpgsm_create_writer): Allow to set the object name - -2002-01-08 Werner Koch - - * keydb.c (spacep): Removed because it is now in util.c - - * server.c (cmd_genkey): New. - * certreqgen.c: New. The parameter handling code has been taken - from gnupg/g10/keygen.c version 1.0.6. - * call-agent.c (gpgsm_agent_genkey): New. - -2002-01-02 Werner Koch - - * server.c (rc_to_assuan_status): Removed and changed all callers - to use map_to_assuan_status. - -2001-12-20 Werner Koch - - * verify.c (gpgsm_verify): Implemented non-detached signature - verification. Add OUT_FP arg, initialize a writer and changed all - callers. - * server.c (cmd_verify): Pass an out_fp if one has been set. - - * base64.c (base64_reader_cb): Try to detect an S/MIME body part. - - * certdump.c (print_sexp): Renamed to gpgsm_dump_serial, made - global. - (print_time): Renamed to gpgsm_dump_time, made global. - (gpgsm_dump_serial): Take a real S-Expression as argument and - print the first item. - * keylist.c (list_cert_colon): Ditto. - * keydb.c (keydb_search_issuer_sn): Ditto. - * decrypt.c (print_integer_sexp): Removed and made callers - use gpgsm_dump_serial. - * verify.c (print_time): Removed, made callers use gpgsm_dump_time. - -2001-12-19 Marcus Brinkmann - - * call-agent.c (start_agent): Add new argument to assuan_pipe_connect. - -2001-12-18 Werner Koch - - * verify.c (print_integer_sexp): Renamed from print_integer and - print the serial number according to the S-Exp rules. - * decrypt.c (print_integer_sexp): Ditto. - -2001-12-17 Werner Koch - - * keylist.c (list_cert_colon): Changed for new return value of - get_serial. - * keydb.c (keydb_search_issuer_sn): Ditto. - * certcheck.c (gpgsm_check_cert_sig): Likewise for other S-Exp - returingin functions. - * fingerprint.c (gpgsm_get_keygrip): Ditto. - * encrypt.c (encrypt_dek): Ditto - * certcheck.c (gpgsm_check_cms_signature): Ditto - * decrypt.c (prepare_decryption): Ditto. - * call-agent.c (gpgsm_agent_pkdecrypt): Removed arg ciphertextlen, - use KsbaSexp type and calculate the length. - - * certdump.c (print_sexp): Remaned from print_integer, changed caller. - - * Makefile.am: Use the LIBGCRYPT and LIBKSBA variables. - - * fingerprint.c (gpgsm_get_keygrip): Use the new - gcry_pk_get_keygrip to calculate the grip - note the algorithm and - therefore the grip values changed. - -2001-12-15 Werner Koch - - * certcheck.c (gpgsm_check_cms_signature): Removed the faked-key - kludge. - (gpgsm_create_cms_signature): Removed the commented fake key - code. This makes the function pretty simple. - - * gpgsm.c (main): Renamed the default key database to "keyring.kbx". - - * decrypt.c (gpgsm_decrypt): Write STATUS_DECRYPTION_*. - * sign.c (gpgsm_sign): Write a STATUS_SIG_CREATED. - -2001-12-14 Werner Koch - - * keylist.c (list_cert_colon): Kludge to show an email address - encoded in the subject's DN. - - * verify.c (gpgsm_verify): Add hash debug helpers - * sign.c (gpgsm_sign): Ditto. - - * base64.c (base64_reader_cb): Reset the linelen when we need to - skip the line and adjusted test; I somehow forgot about DeMorgan. - - * server.c (cmd_encrypt,cmd_decrypt,cmd_sign,cmd_verify) - (cmd_import): Close the FDs on success. - (close_message_fd): New. - (input_notify): Setting autodetect_encoding to 0 after initializing - it to 0 is pretty pointless. Easy to fix. - - * gpgsm.c (main): New option --debug-wait n, so that it is - possible to attach gdb when used in server mode. - - * sign.c (get_default_signer): Use keydb_classify_name here. - -2001-12-14 Marcus Brinkmann - - * call-agent.c (LINELENGTH): Removed. - (gpgsm_agent_pksign): Use ASSUAN_LINELENGTH, not LINELENGTH. - (gpgsm_agent_pkdecrypt): Likewise. - -2001-12-13 Werner Koch - - * keylist.c (list_cert_colon): Print alternative names of subject - and a few other values. - -2001-12-12 Werner Koch - - * gpgsm.c (main): New options --assume-{armor,base64,binary}. - * base64.c (base64_reader_cb): Fixed non-autodetection mode. - -2001-12-04 Werner Koch - - * call-agent.c (read_from_agent): Check for inquire responses. - (request_reply): Handle them using a new callback arg, changed all - callers. - (gpgsm_agent_pkdecrypt): New. - -2001-11-27 Werner Koch - - * base64.c: New. Changed all other functions to use this instead - of direct creation of ksba_reader/writer. - * gpgsm.c (main): Set ctrl.auto_encoding unless --no-armor is used. - -2001-11-26 Werner Koch - - * gpgsm.c: New option --agent-program - * call-agent.c (start_agent): Allow to override the default path - to the agent. - - * keydb.c (keydb_add_resource): Create keybox - - * keylist.c (gpgsm_list_keys): Fixed non-server keylisting. - - * server.c (rc_to_assuan_status): New. Use it for all commands. - - - 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. diff --git a/sm/Makefile.am b/sm/Makefile.am deleted file mode 100644 index 5c137fbb8..000000000 --- a/sm/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - -bin_PROGRAMS = gpgsm - -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \ - $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) -LDFLAGS = @LDFLAGS@ - -gpgsm_SOURCES = \ - gpgsm.c gpgsm.h \ - misc.c \ - keydb.c keydb.h \ - server.c \ - call-agent.c \ - call-dirmngr.c \ - fingerprint.c \ - base64.c \ - certlist.c \ - certdump.c \ - certcheck.c \ - certchain.c \ - keylist.c \ - verify.c \ - sign.c \ - encrypt.c \ - decrypt.c \ - import.c \ - export.c \ - delete.c \ - certreqgen.c - - -gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a ../kbx/libkeybox.a \ - ../common/libcommon.a $(LIBGCRYPT_LIBS) $(KSBA_LIBS) - - diff --git a/sm/base64.c b/sm/base64.c deleted file mode 100644 index f70615e97..000000000 --- a/sm/base64.c +++ /dev/null @@ -1,624 +0,0 @@ -/* base64.c - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "gpgsm.h" -#include "i18n.h" - -#ifdef HAVE_DOSISH_SYSTEM - #define LF "\r\n" -#else - #define LF "\n" -#endif - -/* data used by the reader callbacks */ -struct reader_cb_parm_s { - FILE *fp; - unsigned char line[1024]; - int linelen; - int readpos; - int have_lf; - unsigned long line_counter; - - int autodetect; /* try to detect the input encoding */ - int assume_pem; /* assume input encoding is PEM */ - int assume_base64; /* assume input is base64 encoded */ - - int identified; - int is_pem; - int is_base64; - int stop_seen; - int might_be_smime; - - struct { - int idx; - unsigned char val; - int stop_seen; - } base64; -}; - -/* data used by the writer callbacks */ -struct writer_cb_parm_s { - FILE *fp; - const char *pem_name; - - int wrote_begin; - int did_finish; - - struct { - int idx; - int quad_count; - unsigned char radbuf[4]; - } base64; - -}; - - -/* context for this module's functions */ -struct base64_context_s { - union { - struct reader_cb_parm_s rparm; - struct writer_cb_parm_s wparm; - } u; -}; - - -/* The base-64 character list */ -static unsigned char bintoasc[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; -/* The reverse base-64 list */ -static unsigned char asctobin[256] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, - 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff -}; - - -static int -has_only_base64 (const unsigned char *line, int linelen) -{ - if (linelen < 20) - return 0; - for (; linelen; line++, linelen--) - { - if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n')) - break; - if ( !strchr (bintoasc, *line) ) - return 0; - } - return 1; /* yes */ -} - -static int -is_empty_line (const unsigned char *line, int linelen) -{ - if (linelen >= 2 && *line == '\r' && line[1] == '\n') - return 1; - if (linelen >= 1 && *line == '\n') - return 1; - return 0; -} - - -static int -base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) -{ - struct reader_cb_parm_s *parm = cb_value; - size_t n; - int c, c2; - - *nread = 0; - if (!buffer) - return -1; /* not supported */ - - next: - if (!parm->linelen) - { - /* read an entire line or up to the size of the buffer */ - parm->line_counter++; - parm->have_lf = 0; - for (n=0; n < DIM(parm->line);) - { - c = getc (parm->fp); - if (c == EOF) - { - if (ferror (parm->fp)) - return -1; - break; - } - parm->line[n++] = c; - if (c == '\n') - { - parm->have_lf = 1; - /* Fixme: we need to skip overlong lines while detecting - the dashed lines */ - break; - } - } - parm->linelen = n; - if (!n) - return -1; /* eof */ - parm->readpos = 0; - } - - if (!parm->identified) - { - if (!parm->autodetect) - { - if (parm->assume_pem) - { - /* wait for the header line */ - parm->linelen = parm->readpos = 0; - if (!parm->have_lf || strncmp (parm->line, "-----BEGIN ", 11) - || !strncmp (parm->line+11, "PGP ", 4)) - goto next; - parm->is_pem = 1; - } - else if (parm->assume_base64) - parm->is_base64 = 1; - } - else if (parm->line_counter == 1 && !parm->have_lf) - { - /* first line too long - assume DER encoding */ - parm->is_pem = 0; - } - else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30) - { - /* the very first byte does pretty much look like a SEQUENCE tag*/ - parm->is_pem = 0; - } - else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11) - && strncmp (parm->line+11, "PGP ", 4) ) - { - /* Fixme: we must only compare if the line really starts at - the beginning */ - parm->is_pem = 1; - parm->linelen = parm->readpos = 0; - } - else if ( parm->have_lf && parm->line_counter == 1 - && parm->linelen >= 13 - && !ascii_memcasecmp (parm->line, "Content-Type:", 13)) - { /* might be a S/MIME body */ - parm->might_be_smime = 1; - parm->linelen = parm->readpos = 0; - goto next; - } - else if (parm->might_be_smime == 1 - && is_empty_line (parm->line, parm->linelen)) - { - parm->might_be_smime = 2; - parm->linelen = parm->readpos = 0; - goto next; - } - else if (parm->might_be_smime == 2) - { - parm->might_be_smime = 0; - if ( !has_only_base64 (parm->line, parm->linelen)) - { - parm->linelen = parm->readpos = 0; - goto next; - } - parm->is_pem = 1; - } - else - { - parm->linelen = parm->readpos = 0; - goto next; - } - parm->identified = 1; - parm->base64.stop_seen = 0; - parm->base64.idx = 0; - } - - - n = 0; - if (parm->is_pem || parm->is_base64) - { - if (parm->is_pem && parm->have_lf - && !strncmp (parm->line, "-----END ", 9)) - { - parm->identified = 0; - parm->linelen = parm->readpos = 0; - /* let us return 0 */ - } - else if (parm->stop_seen) - { /* skip the rest of the line */ - parm->linelen = parm->readpos = 0; - } - else - { - int idx = parm->base64.idx; - unsigned char val = parm->base64.val; - - while (n < count && parm->readpos < parm->linelen ) - { - c = parm->line[parm->readpos++]; - if (c == '\n' || c == ' ' || c == '\r' || c == '\t') - continue; - if (c == '=') - { /* pad character: stop */ - if (idx == 1) - buffer[n++] = val; - parm->stop_seen = 1; - break; - } - if( (c = asctobin[(c2=c)]) == 255 ) - { - log_error (_("invalid radix64 character %02x skipped\n"), - c2); - continue; - } - switch (idx) - { - case 0: - val = c << 2; - break; - case 1: - val |= (c>>4)&3; - buffer[n++] = val; - val = (c<<4)&0xf0; - break; - case 2: - val |= (c>>2)&15; - buffer[n++] = val; - val = (c<<6)&0xc0; - break; - case 3: - val |= c&0x3f; - buffer[n++] = val; - break; - } - idx = (idx+1) % 4; - } - if (parm->readpos == parm->linelen) - parm->linelen = parm->readpos = 0; - - parm->base64.idx = idx; - parm->base64.val = val; - } - } - else - { /* DER encoded */ - while (n < count && parm->readpos < parm->linelen) - buffer[n++] = parm->line[parm->readpos++]; - if (parm->readpos == parm->linelen) - parm->linelen = parm->readpos = 0; - } - - *nread = n; - return 0; -} - - - -static int -simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) -{ - struct reader_cb_parm_s *parm = cb_value; - size_t n; - int c = 0; - - *nread = 0; - if (!buffer) - return -1; /* not supported */ - - for (n=0; n < count; n++) - { - c = getc (parm->fp); - if (c == EOF) - { - if ( ferror (parm->fp) ) - return -1; - if (n) - break; /* return what we have before an EOF */ - return -1; - } - *(byte *)buffer++ = c; - } - - *nread = n; - return 0; -} - - - - -static int -base64_writer_cb (void *cb_value, const void *buffer, size_t count) -{ - struct writer_cb_parm_s *parm = cb_value; - unsigned char radbuf[4]; - int i, c, idx, quad_count; - const unsigned char *p; - FILE *fp = parm->fp; - - if (!count) - return 0; - - if (!parm->wrote_begin) - { - if (parm->pem_name) - { - fputs ("-----BEGIN ", fp); - fputs (parm->pem_name, fp); - fputs ("-----\n", fp); - } - parm->wrote_begin = 1; - parm->base64.idx = 0; - parm->base64.quad_count = 0; - } - - idx = parm->base64.idx; - quad_count = parm->base64.quad_count; - for (i=0; i < idx; i++) - radbuf[i] = parm->base64.radbuf[i]; - - for (p=buffer; count; p++, count--) - { - radbuf[idx++] = *p; - if (idx > 2) - { - idx = 0; - c = bintoasc[(*radbuf >> 2) & 077]; - putc (c, fp); - c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; - putc (c, fp); - c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; - putc (c, fp); - c = bintoasc[radbuf[2]&077]; - putc (c, fp); - if (++quad_count >= (64/4)) - { - fputs (LF, fp); - quad_count = 0; - } - } - } - for (i=0; i < idx; i++) - parm->base64.radbuf[i] = radbuf[i]; - parm->base64.idx = idx; - parm->base64.quad_count = quad_count; - - return ferror (fp) ? KSBA_Write_Error:0; -} - -static int -base64_finish_write (struct writer_cb_parm_s *parm) -{ - unsigned char radbuf[4]; - int i, c, idx, quad_count; - FILE *fp = parm->fp; - - if (!parm->wrote_begin) - return 0; /* nothing written */ - - /* flush the base64 encoding */ - idx = parm->base64.idx; - quad_count = parm->base64.quad_count; - for (i=0; i < idx; i++) - radbuf[i] = parm->base64.radbuf[i]; - - if (idx) - { - c = bintoasc[(*radbuf>>2)&077]; - putc (c, fp); - if (idx == 1) - { - c = bintoasc[((*radbuf << 4) & 060) & 077]; - putc (c, fp); - putc ('=', fp); - putc ('=', fp); - } - else - { - c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; - putc (c, fp); - c = bintoasc[((radbuf[1] << 2) & 074) & 077]; - putc (c, fp); - putc ('=', fp); - - } - if (++quad_count >= (64/4)) - { - fputs (LF, fp); - quad_count = 0; - } - } - - if (quad_count) - fputs (LF, fp); - - if (parm->pem_name) - { - fputs ("-----END ", fp); - fputs (parm->pem_name, fp); - fputs ("-----\n", fp); - } - return ferror (fp)? GNUPG_Write_Error : 0; -} - - - - -/* Create a reader for the given file descriptor. Depending on the - control information an input decoding is automagically choosen. - The function returns a Base64Context object which must be passed to - the gpgme_destroy_reader function. The created KsbaReader object - is also returned, but the caller must not call the - ksba_reader_release function on. */ -int -gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaReader *r_reader) -{ - int rc; - KsbaReader r; - - *r_reader = NULL; - *ctx = xtrycalloc (1, sizeof **ctx); - if (!*ctx) - return seterr (Out_Of_Core); - - r = ksba_reader_new (); - if (!r) - { - xfree (*ctx); *ctx = NULL; - return seterr (Out_Of_Core); - } - - (*ctx)->u.rparm.fp = fp; - if (ctrl->is_pem) - { - (*ctx)->u.rparm.assume_pem = 1; - (*ctx)->u.rparm.assume_base64 = 1; - rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); - } - else if (ctrl->is_base64) - { - (*ctx)->u.rparm.assume_base64 = 1; - rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); - } - else if (ctrl->autodetect_encoding) - { - (*ctx)->u.rparm.autodetect = 1; - rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); - } - else - rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm); - - if (rc) - { - ksba_reader_release (r); - xfree (*ctx); *ctx = NULL; - return map_ksba_err (rc); - } - - *r_reader = r; - return 0; -} - - -void -gpgsm_destroy_reader (Base64Context ctx) -{ - xfree (ctx); -} - - - -/* Create a writer for the given stream. Depending on the control - information an output encoding is automagically choosen. The - function returns a Base64Context object which must be passed to the - gpgme_destroy_writer function. The created KsbaWriter object is - also returned, but the caller must not call the ksba_reader_release - function on. */ -int -gpgsm_create_writer (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaWriter *r_writer) -{ - int rc; - KsbaWriter w; - - *r_writer = NULL; - *ctx = xtrycalloc (1, sizeof **ctx); - if (!*ctx) - return seterr (Out_Of_Core); - - w = ksba_writer_new (); - if (!w) - { - xfree (*ctx); *ctx = NULL; - return seterr (Out_Of_Core); - } - - if (ctrl->create_pem || ctrl->create_base64) - { - (*ctx)->u.wparm.fp = fp; - if (ctrl->create_pem) - (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name - : "CMS OBJECT"; - rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm); - } - else - rc = ksba_writer_set_file (w, fp); - - if (rc) - { - ksba_writer_release (w); - xfree (*ctx); *ctx = NULL; - return map_ksba_err (rc); - } - - *r_writer = w; - return 0; -} - - -int -gpgsm_finish_writer (Base64Context ctx) -{ - struct writer_cb_parm_s *parm; - - if (!ctx) - return GNUPG_Invalid_Value; - parm = &ctx->u.wparm; - if (parm->did_finish) - return 0; /* already done */ - parm->did_finish = 1; - if (!parm->fp) - return 0; /* callback was not used */ - return base64_finish_write (parm); -} - -void -gpgsm_destroy_writer (Base64Context ctx) -{ - xfree (ctx); -} diff --git a/sm/call-agent.c b/sm/call-agent.c deleted file mode 100644 index 6cb2fb505..000000000 --- a/sm/call-agent.c +++ /dev/null @@ -1,751 +0,0 @@ -/* call-agent.c - divert operations to the agent - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_LOCALE_H -#include -#endif - -#include "gpgsm.h" -#include "../assuan/assuan.h" -#include "i18n.h" -#include "keydb.h" /* fixme: Move this to import.c */ - -static ASSUAN_CONTEXT agent_ctx = NULL; -static int force_pipe_server = 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; -}; - -struct learn_parm_s { - int error; - ASSUAN_CONTEXT ctx; - struct membuf *data; -}; - -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; -}; - - - -/* A simple implemnation 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. */ - -static void -init_membuf (struct membuf *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 = 1; -} - -static void -put_membuf (struct membuf *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 = 1; - return; - } - mb->buf = p; - } - memcpy (mb->buf + mb->len, buf, len); - mb->len += len; -} - -static void * -get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ - return p; -} - - - -/* 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 (which is suitable given that - the agent is not MT */ - - infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO"); - if (!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)) - { - log_error ("error flushing pending output: %s\n", strerror (errno)); - return seterr (Write_Error); - } - - 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 seterr (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 GNUPG_Out_Of_Core; - rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, - NULL); - free (optstr); - if (rc) - return map_assuan_err (rc); - } - if (!opt.ttyname && ttyname (1)) - dft_ttyname = ttyname (1); - if (opt.ttyname || dft_ttyname) - { - char *optstr; - if (asprintf (&optstr, "OPTION ttyname=%s", - opt.ttyname ? opt.ttyname : dft_ttyname) < 0) - return GNUPG_Out_Of_Core; - 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 GNUPG_Out_Of_Core; - 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 GNUPG_Out_Of_Core; - } - 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 = GNUPG_Out_Of_Core; - 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 GNUPG_Out_Of_Core; - } - 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 = GNUPG_Out_Of_Core; - 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; -} - - -static AssuanError -membuf_data_cb (void *opaque, const void *buffer, size_t length) -{ - struct membuf *data = opaque; - - if (buffer) - put_membuf (data, buffer, length); - return 0; -} - - - - -/* Call the agent to do a sign operation using the key identified by - the hex string KEYGRIP. */ -int -gpgsm_agent_pksign (const char *keygrip, - unsigned char *digest, size_t digestlen, int digestalgo, - char **r_buf, size_t *r_buflen ) -{ - int rc, i; - char *p, line[ASSUAN_LINELENGTH]; - struct membuf data; - size_t len; - - *r_buf = NULL; - rc = start_agent (); - if (rc) - return rc; - - if (digestlen*2 + 50 > DIM(line)) - return seterr (General_Error); - - rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return map_assuan_err (rc); - - snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip); - line[DIM(line)-1] = 0; - rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return map_assuan_err (rc); - - sprintf (line, "SETHASH %d ", digestalgo); - p = line + strlen (line); - for (i=0; i < digestlen ; i++, p += 2 ) - sprintf (p, "%02X", digest[i]); - rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return map_assuan_err (rc); - - init_membuf (&data, 1024); - rc = assuan_transact (agent_ctx, "PKSIGN", - 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 (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL)) - { - xfree (*r_buf); *r_buf = NULL; - return GNUPG_Invalid_Value; - } - - return *r_buf? 0 : GNUPG_Out_Of_Core; -} - - - - -/* Handle a CIPHERTEXT inquiry. Note, we only send the data, - assuan_transact talkes care of flushing and writing the end */ -static AssuanError -inq_ciphertext_cb (void *opaque, const char *keyword) -{ - struct cipher_parm_s *parm = opaque; - AssuanError rc; - - assuan_begin_confidential (parm->ctx); - rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen); - assuan_end_confidential (parm->ctx); - return rc; -} - - -/* Call the agent to do a decrypt operation using the key identified by - the hex string KEYGRIP. */ -int -gpgsm_agent_pkdecrypt (const char *keygrip, - KsbaConstSexp ciphertext, - char **r_buf, size_t *r_buflen ) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - struct membuf data; - struct cipher_parm_s cipher_parm; - size_t n, len; - char *buf, *endp; - size_t ciphertextlen; - - if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen) - return GNUPG_Invalid_Value; - *r_buf = NULL; - - ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL); - if (!ciphertextlen) - return GNUPG_Invalid_Value; - - 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); - - assert ( DIM(line) >= 50 ); - snprintf (line, DIM(line)-1, "SETKEY %s", keygrip); - line[DIM(line)-1] = 0; - rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - return map_assuan_err (rc); - - init_membuf (&data, 1024); - cipher_parm.ctx = agent_ctx; - cipher_parm.ciphertext = ciphertext; - cipher_parm.ciphertextlen = ciphertextlen; - rc = assuan_transact (agent_ctx, "PKDECRYPT", - membuf_data_cb, &data, - inq_ciphertext_cb, &cipher_parm, NULL, NULL); - if (rc) - { - xfree (get_membuf (&data, &len)); - return map_assuan_err (rc); - } - - put_membuf (&data, "", 1); /* make sure it is 0 terminated */ - buf = get_membuf (&data, &len); - if (!buf) - return seterr (Out_Of_Core); - /* FIXME: We would better a return a full S-exp and not just a part */ - assert (len); - len--; /* remove the terminating 0 */ - n = strtoul (buf, &endp, 10); - if (!n || *endp != ':') - return seterr (Invalid_Sexp); - endp++; - if (endp-buf+n > len) - return seterr (Invalid_Sexp); /* oops len does not match internal len*/ - memmove (buf, endp, n); - *r_buflen = n; - *r_buf = buf; - return 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 newkey */ -int -gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey) -{ - int rc; - struct genkey_parm_s gk_parm; - struct membuf 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 GNUPG_Invalid_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 GNUPG_Out_Of_Core; - if (!gcry_sexp_canon_len (buf, len, NULL, NULL)) - { - xfree (buf); - return GNUPG_Invalid_Sexp; - } - *r_pubkey = buf; - return 0; -} - - -/* Ask the agent whether the certificate is in the list of trusted - keys */ -int -gpgsm_agent_istrusted (KsbaCert cert) -{ - int rc; - char *fpr; - char line[ASSUAN_LINELENGTH]; - - rc = start_agent (); - if (rc) - return rc; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - if (!fpr) - { - log_error ("error getting the fingerprint\n"); - return seterr (General_Error); - } - - snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr); - line[DIM(line)-1] = 0; - xfree (fpr); - - rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - return map_assuan_err (rc); -} - -/* Ask the agent to mark CERT as a trusted Root-CA one */ -int -gpgsm_agent_marktrusted (KsbaCert cert) -{ - int rc; - char *fpr, *dn; - char line[ASSUAN_LINELENGTH]; - - rc = start_agent (); - if (rc) - return rc; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - if (!fpr) - { - log_error ("error getting the fingerprint\n"); - return seterr (General_Error); - } - - dn = ksba_cert_get_issuer (cert, 0); - if (!dn) - { - xfree (fpr); - return seterr (General_Error); - } - snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn); - line[DIM(line)-1] = 0; - ksba_free (dn); - xfree (fpr); - - rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - return map_assuan_err (rc); -} - - - -/* Ask the agent whether the a corresponding secret key is available - for the given keygrip */ -int -gpgsm_agent_havekey (const char *hexkeygrip) -{ - int rc; - char line[ASSUAN_LINELENGTH]; - - rc = start_agent (); - if (rc) - return rc; - - if (!hexkeygrip || strlen (hexkeygrip) != 40) - return GNUPG_Invalid_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); -} - - -static AssuanError -learn_cb (void *opaque, const void *buffer, size_t length) -{ - struct learn_parm_s *parm = opaque; - size_t len; - char *buf; - KsbaCert cert; - int rc; - - if (parm->error) - return 0; - - if (buffer) - { - put_membuf (parm->data, buffer, length); - return 0; - } - /* END encountered - process what we have */ - buf = get_membuf (parm->data, &len); - if (!buf) - { - parm->error = GNUPG_Out_Of_Core; - return 0; - } - - - /* FIXME: this should go into import.c */ - cert = ksba_cert_new (); - if (!cert) - { - parm->error = GNUPG_Out_Of_Core; - return 0; - } - rc = ksba_cert_init_from_mem (cert, buf, len); - if (rc) - { - log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); - ksba_cert_release (cert); - parm->error = map_ksba_err (rc); - return 0; - } - - rc = gpgsm_basic_cert_check (cert); - if (rc == GNUPG_Missing_Certificate) - { /* For later use we store it in the ephemeral database. */ - log_info ("issuer certificate missing - storing as ephemeral\n"); - keydb_store_cert (cert, 1, NULL); - } - else if (rc) - log_error ("invalid certificate: %s\n", gnupg_strerror (rc)); - else - { - int existed; - - if (!keydb_store_cert (cert, 0, &existed)) - { - if (opt.verbose > 1 && existed) - log_info ("certificate already in DB\n"); - else if (opt.verbose && !existed) - log_info ("certificate imported\n"); - } - } - - ksba_cert_release (cert); - init_membuf (parm->data, 4096); - return 0; -} - -/* Call the agent to learn about a smartcard */ -int -gpgsm_agent_learn () -{ - int rc; - struct learn_parm_s learn_parm; - struct membuf data; - size_t len; - - rc = start_agent (); - if (rc) - return rc; - - init_membuf (&data, 4096); - learn_parm.error = 0; - learn_parm.ctx = agent_ctx; - learn_parm.data = &data; - rc = assuan_transact (agent_ctx, "LEARN --send", - learn_cb, &learn_parm, - NULL, NULL, NULL, NULL); - xfree (get_membuf (&data, &len)); - if (rc) - return map_assuan_err (rc); - return learn_parm.error; -} - diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c deleted file mode 100644 index a1d94e25b..000000000 --- a/sm/call-dirmngr.c +++ /dev/null @@ -1,495 +0,0 @@ -/* call-dirmngr.c - communication with the dromngr - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "gpgsm.h" -#include "../assuan/assuan.h" -#include "i18n.h" - -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; -}; - - - -static ASSUAN_CONTEXT dirmngr_ctx = NULL; -static int force_pipe_server = 0; - -struct inq_certificate_parm_s { - ASSUAN_CONTEXT ctx; - KsbaCert cert; -}; - -struct lookup_parm_s { - CTRL ctrl; - ASSUAN_CONTEXT ctx; - void (*cb)(void *, KsbaCert); - void *cb_value; - struct membuf data; - int error; -}; - - - - -/* 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. */ - -static void -init_membuf (struct membuf *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 = 1; -} - -static void -put_membuf (struct membuf *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 = 1; - return; - } - mb->buf = p; - } - memcpy (mb->buf + mb->len, buf, len); - mb->len += len; -} - -static void * -get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ - return p; -} - - - - - -/* 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_dirmngr (void) -{ - int rc; - char *infostr, *p; - ASSUAN_CONTEXT ctx; - - if (dirmngr_ctx) - return 0; /* fixme: We need a context for each thread or serialize - the access to the dirmngr */ - - infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); - if (!infostr) - { - const char *pgmname; - const char *argv[3]; - int no_close_list[3]; - int i; - - if (opt.verbose) - log_info (_("no running dirmngr - starting one\n")); - - if (fflush (NULL)) - { - log_error ("error flushing pending output: %s\n", strerror (errno)); - return seterr (Write_Error); - } - - if (!opt.dirmngr_program || !*opt.dirmngr_program) - opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR; - if ( !(pgmname = strrchr (opt.dirmngr_program, '/'))) - pgmname = opt.dirmngr_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.dirmngr_program, (char**)argv, - no_close_list); - } - else - { - int prot; - int pid; - - infostr = xstrdup (infostr); - if ( !(p = strchr (infostr, ':')) || p == infostr) - { - log_error (_("malformed DIRMNGR_INFO environment variable\n")); - xfree (infostr); - force_pipe_server = 1; - return start_dirmngr (); - } - *p++ = 0; - pid = atoi (p); - while (*p && *p != ':') - p++; - prot = *p? atoi (p+1) : 0; - if (prot != 1) - { - log_error (_("dirmngr protocol version %d is not supported\n"), - prot); - xfree (infostr); - force_pipe_server = 1; - return start_dirmngr (); - } - - rc = assuan_socket_connect (&ctx, infostr, pid); - xfree (infostr); - if (rc == ASSUAN_Connect_Failed) - { - log_error (_("can't connect to the dirmngr - trying fall back\n")); - force_pipe_server = 1; - return start_dirmngr (); - } - } - - if (rc) - { - log_error ("can't connect to the dirmngr: %s\n", assuan_strerror (rc)); - return seterr (No_Dirmngr); - } - dirmngr_ctx = ctx; - - if (DBG_ASSUAN) - log_debug ("connection to dirmngr established\n"); - return 0; -} - - - -/* Handle a SENDCERT inquiry. */ -static AssuanError -inq_certificate (void *opaque, const char *line) -{ - struct inq_certificate_parm_s *parm = opaque; - AssuanError rc; - const unsigned char *der; - size_t derlen; - - if (!(!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))) - { - log_error ("unsupported inquiry `%s'\n", line); - return ASSUAN_Inquire_Unknown; - } - line += 8; - - if (!*line) - { /* send the current certificate */ - der = ksba_cert_get_image (parm->cert, &derlen); - if (!der) - rc = ASSUAN_Inquire_Error; - else - rc = assuan_send_data (parm->ctx, der, derlen); - } - else - { /* send the given certificate */ - int err; - KsbaCert cert; - - err = gpgsm_find_cert (line, &cert); - if (err) - { - log_error ("certificate not found: %s\n", gnupg_strerror (err)); - rc = ASSUAN_Inquire_Error; - } - else - { - der = ksba_cert_get_image (cert, &derlen); - if (!der) - rc = ASSUAN_Inquire_Error; - else - rc = assuan_send_data (parm->ctx, der, derlen); - ksba_cert_release (cert); - } - } - - return rc; -} - - - -/* Call the directory manager to check whether the certificate is valid - Returns 0 for valid or usually one of the errors: - - GNUPG_Certificate_Revoked - GNUPG_No_CRL_Known - GNUPG_CRL_Too_Old - */ -int -gpgsm_dirmngr_isvalid (KsbaCert cert) -{ - int rc; - char *certid; - char line[ASSUAN_LINELENGTH]; - struct inq_certificate_parm_s parm; - - rc = start_dirmngr (); - if (rc) - return rc; - - certid = gpgsm_get_certid (cert); - if (!certid) - { - log_error ("error getting the certificate ID\n"); - return seterr (General_Error); - } - - if (opt.verbose > 1) - { - char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1); - log_info ("asking dirmngr about %s\n", fpr); - xfree (fpr); - } - - parm.ctx = dirmngr_ctx; - parm.cert = cert; - - snprintf (line, DIM(line)-1, "ISVALID %s", certid); - line[DIM(line)-1] = 0; - xfree (certid); - - rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, - inq_certificate, &parm, NULL, NULL); - if (opt.verbose > 1) - log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); - return map_assuan_err (rc); -} - - - -/* Lookup helpers*/ -static AssuanError -lookup_cb (void *opaque, const void *buffer, size_t length) -{ - struct lookup_parm_s *parm = opaque; - size_t len; - char *buf; - KsbaCert cert; - int rc; - - if (parm->error) - return 0; - - if (buffer) - { - put_membuf (&parm->data, buffer, length); - return 0; - } - /* END encountered - process what we have */ - buf = get_membuf (&parm->data, &len); - if (!buf) - { - parm->error = GNUPG_Out_Of_Core; - return 0; - } - - cert = ksba_cert_new (); - if (!cert) - { - parm->error = GNUPG_Out_Of_Core; - return 0; - } - rc = ksba_cert_init_from_mem (cert, buf, len); - if (rc) - { - log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); - } - else - { - parm->cb (parm->cb_value, cert); - } - - ksba_cert_release (cert); - init_membuf (&parm->data, 4096); - return 0; -} - -/* Return a properly escaped pattern from NAMES. The only error - return is NULL to indicate a malloc failure. */ -static char * -pattern_from_strlist (STRLIST names) -{ - STRLIST sl; - int n; - const char *s; - char *pattern, *p; - - for (n=0, sl=names; sl; sl = sl->next) - { - for (s=sl->d; *s; s++, n++) - { - if (*s == '%' || *s == ' ' || *s == '+') - n += 2; - } - n++; - } - - p = pattern = xtrymalloc (n+1); - if (!pattern) - return NULL; - - for (n=0, sl=names; sl; sl = sl->next) - { - for (s=sl->d; *s; s++) - { - switch (*s) - { - case '%': - *p++ = '%'; - *p++ = '2'; - *p++ = '5'; - break; - case ' ': - *p++ = '%'; - *p++ = '2'; - *p++ = '0'; - break; - case '+': - *p++ = '%'; - *p++ = '2'; - *p++ = 'B'; - break; - default: - *p++ = *s; - break; - } - } - *p++ = ' '; - } - if (p == pattern) - *pattern = 0; /* is empty */ - else - p[-1] = '\0'; /* remove trailing blank */ - - return pattern; -} - -static AssuanError -lookup_status_cb (void *opaque, const char *line) -{ - struct lookup_parm_s *parm = opaque; - - if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) - { - if (parm->ctrl) - { - for (line +=9; *line == ' '; line++) - ; - gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line); - } - } - return 0; -} - - -/* Run the Directroy Managers lookup command using the apptern - compiled from the strings given in NAMES. The caller must provide - the callback CB which will be passed cert by cert. Note that CTRL - is optional. */ -int -gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, - void (*cb)(void*, KsbaCert), void *cb_value) -{ - int rc; - char *pattern; - char line[ASSUAN_LINELENGTH]; - struct lookup_parm_s parm; - size_t len; - - rc = start_dirmngr (); - if (rc) - return rc; - - pattern = pattern_from_strlist (names); - if (!pattern) - return GNUPG_Out_Of_Core; - snprintf (line, DIM(line)-1, "LOOKUP %s", pattern); - line[DIM(line)-1] = 0; - xfree (pattern); - - parm.ctrl = ctrl; - parm.ctx = dirmngr_ctx; - parm.cb = cb; - parm.cb_value = cb_value; - parm.error = 0; - init_membuf (&parm.data, 4096); - - rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm, - NULL, NULL, lookup_status_cb, &parm); - xfree (get_membuf (&parm.data, &len)); - if (rc) - return map_assuan_err (rc); - return parm.error; -} - - diff --git a/sm/certchain.c b/sm/certchain.c deleted file mode 100644 index b01398f18..000000000 --- a/sm/certchain.c +++ /dev/null @@ -1,786 +0,0 @@ -/* certchain.c - certificate chain validation - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -static int -unknown_criticals (KsbaCert cert) -{ - static const char *known[] = { - "2.5.29.15", /* keyUsage */ - "2.5.29.19", /* basic Constraints */ - "2.5.29.32", /* certificatePolicies */ - NULL - }; - int rc = 0, i, idx, crit; - const char *oid; - KsbaError err; - - for (idx=0; !(err=ksba_cert_get_extension (cert, idx, - &oid, &crit, NULL, NULL));idx++) - { - if (!crit) - continue; - for (i=0; known[i] && strcmp (known[i],oid); i++) - ; - if (!known[i]) - { - log_error (_("critical certificate extension %s is not supported\n"), - oid); - rc = GNUPG_Unsupported_Certificate; - } - } - if (err && err != -1) - rc = map_ksba_err (err); - - return rc; -} - -static int -allowed_ca (KsbaCert cert, int *chainlen) -{ - KsbaError err; - int flag; - - err = ksba_cert_is_ca (cert, &flag, chainlen); - if (err) - return map_ksba_err (err); - if (!flag) - { - log_error (_("issuer certificate is not marked as a CA\n")); - return GNUPG_Bad_CA_Certificate; - } - return 0; -} - - -static int -check_cert_policy (KsbaCert cert) -{ - KsbaError err; - char *policies; - FILE *fp; - int any_critical; - - err = ksba_cert_get_cert_policies (cert, &policies); - if (err == KSBA_No_Data) - return 0; /* no policy given */ - if (err) - return map_ksba_err (err); - - /* STRING is a line delimited list of certifiate policies as stored - in the certificate. The line itself is colon delimited where the - first field is the OID of the policy and the second field either - N or C for normal or critical extension */ - - if (opt.verbose > 1) - log_info ("certificate's policy list: %s\n", policies); - - /* The check is very minimal but won't give false positives */ - any_critical = !!strstr (policies, ":C"); - - if (!opt.policy_file) - { - xfree (policies); - if (any_critical) - { - log_error ("critical marked policy without configured policies\n"); - return GNUPG_No_Policy_Match; - } - return 0; - } - - fp = fopen (opt.policy_file, "r"); - if (!fp) - { - log_error ("failed to open `%s': %s\n", - opt.policy_file, strerror (errno)); - xfree (policies); - return GNUPG_No_Policy_Match; - } - - for (;;) - { - int c; - char *p, line[256]; - char *haystack, *allowed; - - /* read line */ - do - { - if (!fgets (line, DIM(line)-1, fp) ) - { - xfree (policies); - if (feof (fp)) - { - fclose (fp); - /* with no critical policies this is only a warning */ - if (!any_critical) - { - log_info (_("note: certificate policy not allowed\n")); - return 0; - } - log_error (_("certificate policy not allowed\n")); - return GNUPG_No_Policy_Match; - } - fclose (fp); - return GNUPG_Read_Error; - } - - if (!*line || line[strlen(line)-1] != '\n') - { - /* eat until end of line */ - while ( (c=getc (fp)) != EOF && c != '\n') - ; - fclose (fp); - xfree (policies); - return *line? GNUPG_Line_Too_Long: GNUPG_Incomplete_Line; - } - - /* Allow for empty lines and spaces */ - for (p=line; spacep (p); p++) - ; - } - while (!*p || *p == '\n' || *p == '#'); - - /* parse line */ - for (allowed=line; spacep (allowed); allowed++) - ; - p = strpbrk (allowed, " :\n"); - if (!*p || p == allowed) - { - fclose (fp); - xfree (policies); - return GNUPG_Configuration_Error; - } - *p = 0; /* strip the rest of the line */ - /* See whether we find ALLOWED (which is an OID) in POLICIES */ - for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1) - { - if ( !(p == policies || p[-1] == '\n') ) - continue; /* does not match the begin of a line */ - if (p[strlen (allowed)] != ':') - continue; /* the length does not match */ - /* Yep - it does match so return okay */ - fclose (fp); - xfree (policies); - return 0; - } - } -} - - -static void -find_up_store_certs_cb (void *cb_value, KsbaCert cert) -{ - if (keydb_store_cert (cert, 1, NULL)) - log_error ("error storing issuer certificate as ephemeral\n"); - ++*(int*)cb_value; -} - - -static int -find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer) -{ - KsbaName authid; - KsbaSexp authidno; - int rc = -1; - - if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno)) - { - const char *s = ksba_name_enum (authid, 0); - if (s && *authidno) - { - rc = keydb_search_issuer_sn (kh, s, authidno); - if (rc) - keydb_search_reset (kh); - if (rc == -1) - { /* And try the ephemeral DB. */ - int old = keydb_set_ephemeral (kh, 1); - if (!old) - { - rc = keydb_search_issuer_sn (kh, s, authidno); - if (rc) - keydb_search_reset (kh); - } - keydb_set_ephemeral (kh, old); - } - } - /* print a note so that the user does not feel too helpless when - an issuer certificate was found and gpgsm prints BAD - signature becuase it is not the correct one. */ - if (rc == -1) - { - log_info ("issuer certificate (#"); - gpgsm_dump_serial (authidno); - log_printf ("/"); - gpgsm_dump_string (s); - log_printf (") not found\n"); - } - else if (rc) - log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc); - ksba_name_release (authid); - xfree (authidno); - /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */ - } - - if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */ - rc = keydb_search_subject (kh, issuer); - if (rc == -1) - { - /* Not found, lets see whether we have one in the ephemeral key DB. */ - int old = keydb_set_ephemeral (kh, 1); - if (!old) - { - keydb_search_reset (kh); - rc = keydb_search_subject (kh, issuer); - } - keydb_set_ephemeral (kh, old); - } - - if (rc == -1 && opt.auto_issuer_key_retrieve) - { - STRLIST names = NULL; - int count = 0; - char *pattern; - const char *s; - - if (opt.verbose) - log_info (_("looking up issuer at external location\n")); - /* dirmngr is confused about unknown attributes so has a quick - and ugly hack we locate the CN and use this and the - following. Fixme: we should have far better parsing in the - dirmngr. */ - s = strstr (issuer, "CN="); - if (!s || s == issuer || s[-1] != ',') - s = issuer; - - pattern = xtrymalloc (strlen (s)+2); - if (!pattern) - return GNUPG_Out_Of_Core; - strcpy (stpcpy (pattern, "/"), s); - add_to_strlist (&names, pattern); - xfree (pattern); - rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count); - free_strlist (names); - if (opt.verbose) - log_info (_("number of issuers matching: %d\n"), count); - if (rc) - { - log_error ("external key lookup failed: %s\n", gnupg_strerror (rc)); - rc = -1; - } - else if (!count) - rc = -1; - else - { - int old; - /* The issuers are currently stored in the ephemeral key - DB, so we temporary switch to ephemeral mode. */ - old = keydb_set_ephemeral (kh, 1); - keydb_search_reset (kh); - rc = keydb_search_subject (kh, issuer); - keydb_set_ephemeral (kh, old); - } - } - return rc; -} - - -/* Return the next certificate up in the chain starting at START. - Returns -1 when there are no more certificates. */ -int -gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next) -{ - int rc = 0; - char *issuer = NULL; - char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); - - *r_next = NULL; - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - issuer = ksba_cert_get_issuer (start, 0); - subject = ksba_cert_get_subject (start, 0); - if (!issuer) - { - log_error ("no issuer found in certificate\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - if (!subject) - { - log_error ("no subject found in certificate\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - if (!strcmp (issuer, subject)) - { - rc = -1; /* we are at the root */ - goto leave; - } - - rc = find_up (kh, start, issuer); - if (rc) - { - /* it is quite common not to have a certificate, so better don't - print an error here */ - if (rc != -1 && opt.verbose > 1) - log_error ("failed to find issuer's certificate: rc=%d\n", rc); - rc = GNUPG_Missing_Certificate; - goto leave; - } - - rc = keydb_get_cert (kh, r_next); - if (rc) - { - log_error ("failed to get cert: rc=%d\n", rc); - rc = GNUPG_General_Error; - } - - leave: - xfree (issuer); - xfree (subject); - keydb_release (kh); - return rc; -} - - -/* Check whether the CERT is a root certificate. Returns True if this - is the case. */ -int -gpgsm_is_root_cert (KsbaCert cert) -{ - char *issuer; - char *subject; - int yes; - - issuer = ksba_cert_get_issuer (cert, 0); - subject = ksba_cert_get_subject (cert, 0); - yes = (issuer && subject && !strcmp (issuer, subject)); - xfree (issuer); - xfree (subject); - return yes; -} - - -/* Validate a chain and optionally return the nearest expiration time - in R_EXPTIME */ -int -gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) -{ - int rc = 0, depth = 0, maxdepth; - char *issuer = NULL; - char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); - KsbaCert subject_cert = NULL, issuer_cert = NULL; - time_t current_time = gnupg_get_time (); - time_t exptime = 0; - int any_expired = 0; - int any_revoked = 0; - int any_no_crl = 0; - int any_crl_too_old = 0; - int any_no_policy_match = 0; - - if (r_exptime) - *r_exptime = 0; - - if (opt.no_chain_validation) - { - log_info ("WARNING: bypassing certificate chain validation\n"); - return 0; - } - - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - if (DBG_X509) - gpgsm_dump_cert ("subject", cert); - - subject_cert = cert; - maxdepth = 50; - - for (;;) - { - xfree (issuer); - xfree (subject); - issuer = ksba_cert_get_issuer (subject_cert, 0); - subject = ksba_cert_get_subject (subject_cert, 0); - - if (!issuer) - { - log_error ("no issuer found in certificate\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - { - time_t not_before, not_after; - - not_before = ksba_cert_get_validity (subject_cert, 0); - not_after = ksba_cert_get_validity (subject_cert, 1); - if (not_before == (time_t)(-1) || not_after == (time_t)(-1)) - { - log_error ("certificate with invalid validity\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - if (not_after) - { - if (!exptime) - exptime = not_after; - else if (not_after < exptime) - exptime = not_after; - } - - if (not_before && current_time < not_before) - { - log_error ("certificate too young; valid from "); - gpgsm_dump_time (not_before); - log_printf ("\n"); - rc = GNUPG_Certificate_Too_Young; - goto leave; - } - if (not_after && current_time > not_after) - { - log_error ("certificate has expired at "); - gpgsm_dump_time (not_after); - log_printf ("\n"); - any_expired = 1; - } - } - - rc = unknown_criticals (subject_cert); - if (rc) - goto leave; - - if (!opt.no_policy_check) - { - rc = check_cert_policy (subject_cert); - if (rc == GNUPG_No_Policy_Match) - { - any_no_policy_match = 1; - rc = 1; - } - else if (rc) - goto leave; - } - - if (!opt.no_crl_check) - { - rc = gpgsm_dirmngr_isvalid (subject_cert); - if (rc) - { - switch (rc) - { - case GNUPG_Certificate_Revoked: - log_error (_("the certificate has been revoked\n")); - any_revoked = 1; - break; - case GNUPG_No_CRL_Known: - log_error (_("no CRL found for certificate\n")); - any_no_crl = 1; - break; - case GNUPG_CRL_Too_Old: - log_error (_("the available CRL is too old\n")); - log_info (_("please make sure that the " - "\"dirmngr\" is properly installed\n")); - any_crl_too_old = 1; - break; - default: - log_error (_("checking the CRL failed: %s\n"), - gnupg_strerror (rc)); - goto leave; - } - rc = 0; - } - } - - if (subject && !strcmp (issuer, subject)) - { - if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) - { - log_error ("selfsigned certificate has a BAD signatures\n"); - rc = depth? GNUPG_Bad_Certificate_Chain : GNUPG_Bad_Certificate; - goto leave; - } - rc = allowed_ca (subject_cert, NULL); - if (rc) - goto leave; - - rc = gpgsm_agent_istrusted (subject_cert); - if (!rc) - ; - else if (rc == GNUPG_Not_Trusted) - { - int rc2; - - char *fpr = gpgsm_get_fingerprint_string (subject_cert, - GCRY_MD_SHA1); - log_info (_("root certificate is not marked trusted\n")); - log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); - xfree (fpr); - rc2 = gpgsm_agent_marktrusted (subject_cert); - if (!rc2) - { - log_info (_("root certificate has now" - " been marked as trusted\n")); - rc = 0; - } - else - { - gpgsm_dump_cert ("issuer", subject_cert); - log_info ("after checking the fingerprint, you may want " - "to enter it manually into " - "\"~/.gnupg-test/trustlist.txt\"\n"); - } - } - else - { - log_error (_("checking the trust list failed: %s\n"), - gnupg_strerror (rc)); - } - - break; /* okay, a self-signed certicate is an end-point */ - } - - depth++; - if (depth > maxdepth) - { - log_error (_("certificate chain too long\n")); - rc = GNUPG_Bad_Certificate_Chain; - goto leave; - } - - /* find the next cert up the tree */ - keydb_search_reset (kh); - rc = find_up (kh, subject_cert, issuer); - if (rc) - { - if (rc == -1) - { - log_info ("issuer certificate (#/"); - gpgsm_dump_string (issuer); - log_printf (") not found\n"); - } - else - log_error ("failed to find issuer's certificate: rc=%d\n", rc); - rc = GNUPG_Missing_Certificate; - goto leave; - } - - ksba_cert_release (issuer_cert); issuer_cert = NULL; - rc = keydb_get_cert (kh, &issuer_cert); - if (rc) - { - log_error ("failed to get cert: rc=%d\n", rc); - rc = GNUPG_General_Error; - goto leave; - } - - if (DBG_X509) - { - log_debug ("got issuer's certificate:\n"); - gpgsm_dump_cert ("issuer", issuer_cert); - } - - if (gpgsm_check_cert_sig (issuer_cert, subject_cert) ) - { - log_error ("certificate has a BAD signatures\n"); - rc = GNUPG_Bad_Certificate_Chain; - goto leave; - } - - { - int chainlen; - rc = allowed_ca (issuer_cert, &chainlen); - if (rc) - goto leave; - if (chainlen >= 0 && (depth - 1) > chainlen) - { - log_error (_("certificate chain longer than allowed by CA (%d)\n"), - chainlen); - rc = GNUPG_Bad_Certificate_Chain; - goto leave; - } - } - - rc = gpgsm_cert_use_cert_p (issuer_cert); - if (rc) - { - gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", - gnupg_error_token (rc), NULL); - rc = 0; - } - - if (opt.verbose) - log_info ("certificate is good\n"); - - keydb_search_reset (kh); - subject_cert = issuer_cert; - issuer_cert = NULL; - } - - if (opt.no_policy_check) - log_info ("policies not checked due to --disable-policy-checks option\n"); - if (opt.no_crl_check) - log_info ("CRLs not checked due to --disable-crl-checks option\n"); - - if (!rc) - { /* If we encountered an error somewhere during the checks, set - the error code to the most critical one */ - if (any_revoked) - rc = GNUPG_Certificate_Revoked; - else if (any_no_crl) - rc = GNUPG_No_CRL_Known; - else if (any_crl_too_old) - rc = GNUPG_CRL_Too_Old; - else if (any_no_policy_match) - rc = GNUPG_No_Policy_Match; - else if (any_expired) - rc = GNUPG_Certificate_Expired; - } - - leave: - if (r_exptime) - *r_exptime = exptime; - xfree (issuer); - keydb_release (kh); - ksba_cert_release (issuer_cert); - if (subject_cert != cert) - ksba_cert_release (subject_cert); - return rc; -} - - -/* Check that the given certificate is valid but DO NOT check any - constraints. We assume that the issuers certificate is already in - the DB and that this one is valid; which it should be because it - has been checked using this function. */ -int -gpgsm_basic_cert_check (KsbaCert cert) -{ - int rc = 0; - char *issuer = NULL; - char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); - KsbaCert issuer_cert = NULL; - - if (opt.no_chain_validation) - { - log_info ("WARNING: bypassing basic certificate checks\n"); - return 0; - } - - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - issuer = ksba_cert_get_issuer (cert, 0); - subject = ksba_cert_get_subject (cert, 0); - if (!issuer) - { - log_error ("no issuer found in certificate\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - - if (subject && !strcmp (issuer, subject)) - { - if (gpgsm_check_cert_sig (cert, cert) ) - { - log_error ("selfsigned certificate has a BAD signatures\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - } - else - { - /* find the next cert up the tree */ - keydb_search_reset (kh); - rc = find_up (kh, cert, issuer); - if (rc) - { - if (rc == -1) - { - log_info ("issuer certificate (#/"); - gpgsm_dump_string (issuer); - log_printf (") not found\n"); - } - else - log_error ("failed to find issuer's certificate: rc=%d\n", rc); - rc = GNUPG_Missing_Certificate; - goto leave; - } - - ksba_cert_release (issuer_cert); issuer_cert = NULL; - rc = keydb_get_cert (kh, &issuer_cert); - if (rc) - { - log_error ("failed to get cert: rc=%d\n", rc); - rc = GNUPG_General_Error; - goto leave; - } - - if (gpgsm_check_cert_sig (issuer_cert, cert) ) - { - log_error ("certificate has a BAD signatures\n"); - rc = GNUPG_Bad_Certificate; - goto leave; - } - if (opt.verbose) - log_info ("certificate is good\n"); - } - - leave: - xfree (issuer); - keydb_release (kh); - ksba_cert_release (issuer_cert); - return rc; -} - diff --git a/sm/certcheck.c b/sm/certcheck.c deleted file mode 100644 index 37d2b00df..000000000 --- a/sm/certcheck.c +++ /dev/null @@ -1,301 +0,0 @@ -/* certcheck.c - check one certificate - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -static int -do_encode_md (GCRY_MD_HD md, int algo, unsigned int nbits, - GCRY_MPI *r_val) -{ - int nframe = (nbits+7) / 8; - byte *frame; - int i, n; - byte asn[100]; - size_t asnlen; - size_t len; - - asnlen = DIM(asn); - if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) - { - log_error ("No object identifier for algo %d\n", algo); - return GNUPG_Internal_Error; - } - - len = gcry_md_get_algo_dlen (algo); - - if ( len + asnlen + 4 > nframe ) - { - log_error ("can't encode a %d bit MD into a %d bits frame\n", - (int)(len*8), (int)nbits); - return GNUPG_Internal_Error; - } - - /* We encode the MD in this way: - * - * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = xtrymalloc (nframe); - if (!frame) - return GNUPG_Out_Of_Core; - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - len - asnlen -3 ; - assert ( i > 1 ); - memset ( frame+n, 0xff, i ); n += i; - frame[n++] = 0; - memcpy ( frame+n, asn, asnlen ); n += asnlen; - memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; - assert ( n == nframe ); - if (DBG_X509) - { - int j; - log_debug ("encoded hash:"); - for (j=0; j < nframe; j++) - log_printf (" %02X", frame[j]); - log_printf ("\n"); - } - - gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe); - xfree (frame); - return 0; -} - - -/* - Check the signature on CERT using the ISSUER-CERT. This function - does only test the cryptographic signature and nothing else. It is - assumed that the ISSUER_CERT is valid. */ -int -gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert) -{ - const char *algoid; - GCRY_MD_HD md; - int rc, algo; - GCRY_MPI frame; - KsbaSexp p; - size_t n; - GCRY_SEXP s_sig, s_hash, s_pkey; - - algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert))); - if (!algo) - { - log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); - return GNUPG_General_Error; - } - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - return GNUPG_General_Error; - } - if (DBG_HASHING) - gcry_md_start_debug (md, "hash.cert"); - - rc = ksba_cert_hash (cert, 1, HASH_FNC, md); - if (rc) - { - log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); - gcry_md_close (md); - return map_ksba_err (rc); - } - gcry_md_final (md); - - p = ksba_cert_get_sig_val (cert); - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - if (!n) - { - log_error ("libksba did not return a proper S-Exp\n"); - gcry_md_close (md); - ksba_free (p); - return GNUPG_Bug; - } - if (DBG_X509) - { - int j; - log_debug ("signature value:"); - for (j=0; j < n; j++) - log_printf (" %02X", p[j]); - log_printf ("\n"); - } - - rc = gcry_sexp_sscan ( &s_sig, NULL, p, n); - ksba_free (p); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - gcry_md_close (md); - return map_gcry_err (rc); - } - - p = ksba_cert_get_public_key (issuer_cert); - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - if (!n) - { - log_error ("libksba did not return a proper S-Exp\n"); - gcry_md_close (md); - ksba_free (p); - gcry_sexp_release (s_sig); - return GNUPG_Bug; - } - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); - ksba_free (p); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - gcry_md_close (md); - gcry_sexp_release (s_sig); - return map_gcry_err (rc); - } - - rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); - if (rc) - { - gcry_md_close (md); - gcry_sexp_release (s_sig); - gcry_sexp_release (s_pkey); - return rc; - } - - /* put hash into the S-Exp s_hash */ - if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) - BUG (); - gcry_mpi_release (frame); - - - rc = gcry_pk_verify (s_sig, s_hash, s_pkey); - if (DBG_CRYPTO) - log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc)); - gcry_md_close (md); - gcry_sexp_release (s_sig); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_pkey); - return map_gcry_err (rc); -} - - - -int -gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, - GCRY_MD_HD md, int algo) -{ - int rc; - KsbaSexp p; - GCRY_MPI frame; - GCRY_SEXP s_sig, s_hash, s_pkey; - size_t n; - - n = gcry_sexp_canon_len (sigval, 0, NULL, NULL); - if (!n) - { - log_error ("libksba did not return a proper S-Exp\n"); - return GNUPG_Bug; - } - rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return map_gcry_err (rc); - } - - p = ksba_cert_get_public_key (cert); - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - if (!n) - { - log_error ("libksba did not return a proper S-Exp\n"); - ksba_free (p); - gcry_sexp_release (s_sig); - return GNUPG_Bug; - } - if (DBG_X509) - log_printhex ("public key: ", p, n); - - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); - ksba_free (p); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - gcry_sexp_release (s_sig); - return map_gcry_err (rc); - } - - - rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); - if (rc) - { - gcry_sexp_release (s_sig); - gcry_sexp_release (s_pkey); - return rc; - } - /* put hash into the S-Exp s_hash */ - if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) - BUG (); - gcry_mpi_release (frame); - - - rc = gcry_pk_verify (s_sig, s_hash, s_pkey); - if (DBG_CRYPTO) - log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc)); - gcry_sexp_release (s_sig); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_sig); - return map_gcry_err (rc); -} - - - -int -gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo, - char **r_sigval) -{ - int rc; - char *grip; - size_t siglen; - - grip = gpgsm_get_keygrip_hexstring (cert); - if (!grip) - return seterr (Bad_Certificate); - - rc = gpgsm_agent_pksign (grip, gcry_md_read(md, mdalgo), - gcry_md_get_algo_dlen (mdalgo), mdalgo, - r_sigval, &siglen); - xfree (grip); - return rc; -} - - - diff --git a/sm/certdump.c b/sm/certdump.c deleted file mode 100644 index 9afb1154d..000000000 --- a/sm/certdump.c +++ /dev/null @@ -1,457 +0,0 @@ -/* certdump.c - Dump a certificate for debugging - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct dn_array_s { - char *key; - char *value; -}; - - -/* print the first element of an S-Expression */ -void -gpgsm_print_serial (FILE *fp, KsbaConstSexp p) -{ - unsigned long n; - KsbaConstSexp endp; - - if (!p) - fputs (_("none"), fp); - else if (*p != '(') - fputs ("[Internal error - not an S-expression]", fp); - else - { - p++; - n = strtoul (p, (char**)&endp, 10); - p = endp; - if (*p!=':') - fputs ("[Internal Error - invalid S-expression]", fp); - else - { - for (p++; n; n--, p++) - fprintf (fp, "%02X", *p); - } - } -} - - -void -gpgsm_dump_serial (KsbaConstSexp p) -{ - unsigned long n; - KsbaConstSexp endp; - - if (!p) - log_printf ("none"); - else if (*p != '(') - log_printf ("ERROR - not an S-expression"); - else - { - p++; - n = strtoul (p, (char**)&endp, 10); - p = endp; - if (*p!=':') - log_printf ("ERROR - invalid S-expression"); - else - { - for (p++; n; n--, p++) - log_printf ("%02X", *p); - } - } -} - -void -gpgsm_print_time (FILE *fp, time_t t) -{ - if (!t) - fputs (_("none"), fp); - else if ( t == (time_t)(-1) ) - fputs ("[Error - Invalid time]", fp); - else - { - struct tm *tp; - - tp = gmtime (&t); - fprintf (fp, "%04d-%02d-%02d %02d:%02d:%02d Z", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } -} - -void -gpgsm_dump_time (time_t t) -{ - - if (!t) - log_printf (_("[none]")); - else if ( t == (time_t)(-1) ) - log_printf (_("[error]")); - else - { - struct tm *tp; - - tp = gmtime (&t); - log_printf ("%04d-%02d-%02d %02d:%02d:%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } -} - - - - -void -gpgsm_dump_string (const char *string) -{ - - if (!string) - log_printf ("[error]"); - else - { - const unsigned char *s; - - for (s=string; *s; s++) - { - if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0)) - break; - } - if (!*s && *string != '[') - log_printf ("%s", string); - else - { - log_printf ( "[ "); - log_printhex (NULL, string, strlen (string)); - log_printf ( " ]"); - } - } -} - - -void -gpgsm_dump_cert (const char *text, KsbaCert cert) -{ - KsbaSexp sexp; - unsigned char *p; - char *dn; - time_t t; - - log_debug ("BEGIN Certificate `%s':\n", text? text:""); - if (cert) - { - sexp = ksba_cert_get_serial (cert); - log_debug (" serial: "); - gpgsm_dump_serial (sexp); - ksba_free (sexp); - log_printf ("\n"); - - t = ksba_cert_get_validity (cert, 0); - log_debug (" notBefore: "); - gpgsm_dump_time (t); - log_printf ("\n"); - t = ksba_cert_get_validity (cert, 1); - log_debug (" notAfter: "); - gpgsm_dump_time (t); - log_printf ("\n"); - - dn = ksba_cert_get_issuer (cert, 0); - log_debug (" issuer: "); - gpgsm_dump_string (dn); - ksba_free (dn); - log_printf ("\n"); - - dn = ksba_cert_get_subject (cert, 0); - log_debug (" subject: "); - gpgsm_dump_string (dn); - ksba_free (dn); - log_printf ("\n"); - - log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert)); - - p = gpgsm_get_fingerprint_string (cert, 0); - log_debug (" SHA1 Fingerprint: %s\n", p); - xfree (p); - } - log_debug ("END Certificate\n"); -} - - - -/* helper for the rfc2253 string parser */ -static const unsigned char * -parse_dn_part (struct dn_array_s *array, const unsigned char *string) -{ - const unsigned char *s, *s1; - size_t n; - unsigned char *p; - - /* parse attributeType */ - for (s = string+1; *s && *s != '='; s++) - ; - if (!*s) - return NULL; /* error */ - n = s - string; - if (!n) - return NULL; /* empty key */ - array->key = p = xtrymalloc (n+1); - if (!array->key) - return NULL; - memcpy (p, string, n); - p[n] = 0; - trim_trailing_spaces (p); - if ( !strcmp (p, "1.2.840.113549.1.9.1") ) - strcpy (p, "EMail"); - string = s + 1; - - if (*string == '#') - { /* hexstring */ - string++; - for (s=string; hexdigitp (s); s++) - s++; - n = s - string; - if (!n || (n & 1)) - return NULL; /* empty or odd number of digits */ - n /= 2; - array->value = p = xtrymalloc (n+1); - if (!p) - return NULL; - for (s1=string; n; s1 += 2, n--) - *p++ = xtoi_2 (s1); - *p = 0; - } - else - { /* regular v3 quoted string */ - for (n=0, s=string; *s; s++) - { - if (*s == '\\') - { /* pair */ - s++; - if (*s == ',' || *s == '=' || *s == '+' - || *s == '<' || *s == '>' || *s == '#' || *s == ';' - || *s == '\\' || *s == '\"' || *s == ' ') - n++; - else if (hexdigitp (s) && hexdigitp (s+1)) - { - s++; - n++; - } - else - return NULL; /* invalid escape sequence */ - } - else if (*s == '\"') - return NULL; /* invalid encoding */ - else if (*s == ',' || *s == '=' || *s == '+' - || *s == '<' || *s == '>' || *s == '#' || *s == ';' ) - break; - else - n++; - } - - array->value = p = xtrymalloc (n+1); - if (!p) - return NULL; - for (s=string; n; s++, n--) - { - if (*s == '\\') - { - s++; - if (hexdigitp (s)) - { - *p++ = xtoi_2 (s); - s++; - } - else - *p++ = *s; - } - else - *p++ = *s; - } - *p = 0; - } - return s; -} - - -/* Parse a DN and return an array-ized one. This is not a validating - parser and it does not support any old-stylish syntax; KSBA is - expected to return only rfc2253 compatible strings. */ -static struct dn_array_s * -parse_dn (const unsigned char *string) -{ - struct dn_array_s *array; - size_t arrayidx, arraysize; - int i; - - arraysize = 7; /* C,ST,L,O,OU,CN,email */ - arrayidx = 0; - array = xtrymalloc ((arraysize+1) * sizeof *array); - if (!array) - return NULL; - while (*string) - { - while (*string == ' ') - string++; - if (!*string) - break; /* ready */ - if (arrayidx >= arraysize) - { - struct dn_array_s *a2; - - arraysize += 5; - a2 = xtryrealloc (array, (arraysize+1) * sizeof *array); - if (!a2) - goto failure; - array = a2; - } - array[arrayidx].key = NULL; - array[arrayidx].value = NULL; - string = parse_dn_part (array+arrayidx, string); - arrayidx++; - if (!string) - goto failure; - while (*string == ' ') - string++; - if (*string && *string != ',' && *string != ';' && *string != '+') - goto failure; /* invalid delimiter */ - if (*string) - string++; - } - array[arrayidx].key = NULL; - array[arrayidx].value = NULL; - return array; - - failure: - for (i=0; i < arrayidx; i++) - { - xfree (array[i].key); - xfree (array[i].value); - } - xfree (array); - return NULL; -} - - -static void -print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) -{ - int any = 0; - - for (; dn->key; dn++) - { - if (!strcmp (dn->key, key) && dn->value && *dn->value) - { - putc ('/', fp); - if (any) - fputs (" + ", fp); - else - fprintf (fp, "%s=", key); - print_sanitized_utf8_string (fp, dn->value, '/'); - any = 1; - } - } -} - -/* Print all parts of a DN in a "standard" sequence. We first print - all the known parts, followed by the uncommon ones */ -static void -print_dn_parts (FILE *fp, struct dn_array_s *dn) -{ - const char *stdpart[] = { - "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL - }; - int i; - - for (i=0; stdpart[i]; i++) - print_dn_part (fp, dn, stdpart[i]); - - /* now print the rest without any specific ordering */ - for (; dn->key; dn++) - { - for (i=0; stdpart[i]; i++) - { - if (!strcmp (dn->key, stdpart[i])) - break; - } - if (!stdpart[i]) - print_dn_part (fp, dn, dn->key); - } -} - - - -void -gpgsm_print_name (FILE *fp, const char *name) -{ - const unsigned char *s; - int i; - - s = name; - if (!s) - { - fputs (_("[Error - No name]"), fp); - } - else if (*s == '<') - { - const unsigned char *s2 = strchr (s+1, '>'); - if (s2) - print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0); - } - else if (*s == '(') - fputs (_("[Error - unknown encoding]"), fp); - else if (!((*s >= '0' && *s < '9') - || (*s >= 'A' && *s <= 'Z') - || (*s >= 'a' && *s <= 'z'))) - fputs (_("[Error - invalid encoding]"), fp); - else - { - struct dn_array_s *dn = parse_dn (s); - if (!dn) - fputs (_("[Error - invalid DN]"), fp); - else - { - print_dn_parts (fp, dn); - for (i=0; dn[i].key; i++) - { - xfree (dn[i].key); - xfree (dn[i].value); - } - xfree (dn); - } - } -} - - - diff --git a/sm/certlist.c b/sm/certlist.c deleted file mode 100644 index f31e6ee2b..000000000 --- a/sm/certlist.c +++ /dev/null @@ -1,313 +0,0 @@ -/* certlist.c - build list of certificates - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -/* Return 0 if the cert is usable for encryption. A MODE of 0 checks - for signing a MODE of 1 checks for encryption, a MODE of 2 checks - for verification and a MODE of 3 for decryption (just for - debugging) */ -static int -cert_usage_p (KsbaCert cert, int mode) -{ - KsbaError err; - unsigned int use; - - err = ksba_cert_get_key_usage (cert, &use); - if (err == KSBA_No_Data) - { - if (opt.verbose && mode < 2) - log_info (mode? - _("no key usage specified - accepted for encryption\n"): - _("no key usage specified - accepted for signing\n")); - return 0; - } - if (err) - { - log_error (_("error getting key usage information: %s\n"), - ksba_strerror (err)); - return map_ksba_err (err); - } - - if (mode == 4) - { - if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN))) - return 0; - log_info ( _("certificate should have not been used certification\n")); - return GNUPG_Wrong_Key_Usage; - } - - if ((use & ((mode&1)? - (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT): - (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) - ) - return 0; - log_info (mode==3? _("certificate should have not been used for encryption\n"): - mode==2? _("certificate should have not been used for signing\n"): - mode==1? _("certificate is not usable for encryption\n"): - _("certificate is not usable for signing\n")); - return GNUPG_Wrong_Key_Usage; -} - - -/* Return 0 if the cert is usable for signing */ -int -gpgsm_cert_use_sign_p (KsbaCert cert) -{ - return cert_usage_p (cert, 0); -} - - -/* Return 0 if the cert is usable for encryption */ -int -gpgsm_cert_use_encrypt_p (KsbaCert cert) -{ - return cert_usage_p (cert, 1); -} - -int -gpgsm_cert_use_verify_p (KsbaCert cert) -{ - return cert_usage_p (cert, 2); -} - -int -gpgsm_cert_use_decrypt_p (KsbaCert cert) -{ - return cert_usage_p (cert, 3); -} - -int -gpgsm_cert_use_cert_p (KsbaCert cert) -{ - return cert_usage_p (cert, 4); -} - - -static int -same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert) -{ - char *subject2 = ksba_cert_get_subject (cert, 0); - char *issuer2 = ksba_cert_get_subject (cert, 0); - int tmp; - - tmp = (subject && subject2 - && !strcmp (subject, subject2) - && issuer && issuer2 - && !strcmp (issuer, issuer2)); - xfree (subject2); - xfree (issuer2); - return tmp; -} - - - -/* Add a certificate to a list of certificate and make sure that it is - a valid certificate. With SECRET set to true a secret key must be - avaibale for the certificate. */ -int -gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, - CERTLIST *listaddr) -{ - int rc; - KEYDB_SEARCH_DESC desc; - KEYDB_HANDLE kh = NULL; - KsbaCert cert = NULL; - - rc = keydb_classify_name (name, &desc); - if (!rc) - { - kh = keydb_new (0); - if (!kh) - rc = GNUPG_Out_Of_Core; - else - { - int wrong_usage = 0; - char *subject = NULL; - char *issuer = NULL; - - get_next: - rc = keydb_search (kh, &desc, 1); - if (!rc) - rc = keydb_get_cert (kh, &cert); - if (!rc) - { - rc = secret? gpgsm_cert_use_sign_p (cert) - : gpgsm_cert_use_encrypt_p (cert); - if (rc == GNUPG_Wrong_Key_Usage) - { - /* There might be another certificate with the - correct usage, so we try again */ - if (!wrong_usage) - { /* save the first match */ - wrong_usage = rc; - subject = ksba_cert_get_subject (cert, 0); - issuer = ksba_cert_get_subject (cert, 0); - ksba_cert_release (cert); - cert = NULL; - goto get_next; - } - else if (same_subject_issuer (subject, issuer, cert)) - { - wrong_usage = rc; - ksba_cert_release (cert); - cert = NULL; - goto get_next; - } - else - wrong_usage = rc; - - } - } - /* we want the error code from the first match in this case */ - if (rc && wrong_usage) - rc = wrong_usage; - - if (!rc) - { - next_ambigious: - rc = keydb_search (kh, &desc, 1); - if (rc == -1) - rc = 0; - else if (!rc) - { - KsbaCert cert2 = NULL; - - /* We have to ignore ambigious names as long as - there only fault is a bad key usage */ - if (!keydb_get_cert (kh, &cert2)) - { - int tmp = (same_subject_issuer (subject, issuer, cert2) - && ((secret? gpgsm_cert_use_sign_p (cert2): - gpgsm_cert_use_encrypt_p (cert2)) - == GNUPG_Wrong_Key_Usage)); - ksba_cert_release (cert2); - if (tmp) - goto next_ambigious; - } - rc = GNUPG_Ambiguous_Name; - } - } - xfree (subject); - xfree (issuer); - - if (!rc && secret) - { - char *p; - - rc = GNUPG_No_Secret_Key; - p = gpgsm_get_keygrip_hexstring (cert); - if (p) - { - if (!gpgsm_agent_havekey (p)) - rc = 0; - xfree (p); - } - } - if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL); - if (!rc) - { - CERTLIST cl = xtrycalloc (1, sizeof *cl); - if (!cl) - rc = GNUPG_Out_Of_Core; - else - { - cl->cert = cert; cert = NULL; - cl->next = *listaddr; - *listaddr = cl; - } - } - } - } - - keydb_release (kh); - ksba_cert_release (cert); - return rc == -1? GNUPG_No_Public_Key: rc; -} - -void -gpgsm_release_certlist (CERTLIST list) -{ - while (list) - { - CERTLIST cl = list->next; - ksba_cert_release (list->cert); - xfree (list); - list = cl; - } -} - - -/* Like gpgsm_add_to_certlist, but look only for one certificate. No - chain validation is done */ -int -gpgsm_find_cert (const char *name, KsbaCert *r_cert) -{ - int rc; - KEYDB_SEARCH_DESC desc; - KEYDB_HANDLE kh = NULL; - - *r_cert = NULL; - rc = keydb_classify_name (name, &desc); - if (!rc) - { - kh = keydb_new (0); - if (!kh) - rc = GNUPG_Out_Of_Core; - else - { - rc = keydb_search (kh, &desc, 1); - if (!rc) - rc = keydb_get_cert (kh, r_cert); - if (!rc) - { - rc = keydb_search (kh, &desc, 1); - if (rc == -1) - rc = 0; - else - { - if (!rc) - rc = GNUPG_Ambiguous_Name; - ksba_cert_release (*r_cert); - *r_cert = NULL; - } - } - } - } - - keydb_release (kh); - return rc == -1? GNUPG_No_Public_Key: rc; -} - diff --git a/sm/certreqgen.c b/sm/certreqgen.c deleted file mode 100644 index 600a278bc..000000000 --- a/sm/certreqgen.c +++ /dev/null @@ -1,699 +0,0 @@ -/* certreqgen.c - Generate a key and a certification request - * 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 - */ - -/* -The format of the native parameter file is follows: - o Text only, line length is limited to about 1000 chars. - o You must use UTF-8 encoding to specify non-ascii characters. - o Empty lines are ignored. - o Leading and trailing spaces are ignored. - o A hash sign as the first non white space character is a comment line. - o Control statements are indicated by a leading percent sign, the - arguments are separated by white space from the keyword. - o Parameters are specified by a keyword, followed by a colon. Arguments - are separated by white space. - o The first parameter must be "Key-Type", control statements - may be placed anywhere. - o Key generation takes place when either the end of the parameter file - is reached, the next "Key-Type" parameter is encountered or at the - controlstatement "%commit" - o Control statements: - %echo - Print . - %dry-run - Suppress actual key generation (useful for syntax checking). - %commit - Perform the key generation. Note that an implicit commit is done - at the next "Key-Type" parameter. - %certfile - Do not write the certificate to the keyDB but to . - This must be given before the first - commit to take place, duplicate specification of the same filename - is ignored, the last filename before a commit is used. - The filename is used until a new filename is used (at commit points) - and all keys are written to that file. If a new filename is given, - this file is created (and overwrites an existing one). - Both control statements must be given. - o The order of the parameters does not matter except for "Key-Type" - which must be the first parameter. The parameters are only for the - generated keyblock and parameters from previous key generations are not - used. Some syntactically checks may be performed. - The currently defined parameters are: - Key-Type: - Starts a new parameter block by giving the type of the - primary key. The algorithm must be capable of signing. - This is a required parameter. For now the only supported - algorithm is "rsa". - Key-Length: - Length of the key in bits. Default is 1024. - Key-Usage: - Space or comma delimited list of key usage, allowed values are - "encrypt" and "sign". This is used to generate the KeyUsage extension. - Please make sure that the algorithm is capable of this usage. Default - is to allow encrypt and sign. - Name-DN: subject name - This is the DN name of the subject in rfc2253 format. - Name-Email: - The ist the email address - -Here is an example: -$ cat >foo < -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -enum para_name { - pKEYTYPE, - pKEYLENGTH, - pKEYUSAGE, - pNAMEDN, - pNAMEEMAIL -}; - -struct para_data_s { - struct para_data_s *next; - int lnr; - enum para_name key; - union { - unsigned int usage; - char value[1]; - } u; -}; - -struct reqgen_ctrl_s { - int lnr; - int dryrun; - KsbaWriter writer; -}; - - -static int proc_parameters (struct para_data_s *para, - struct reqgen_ctrl_s *outctrl); -static int create_request (struct para_data_s *para, - KsbaConstSexp public, - struct reqgen_ctrl_s *outctrl); - - - -static void -release_parameter_list (struct para_data_s *r) -{ - struct para_data_s *r2; - - for (; r ; r = r2) - { - r2 = r->next; - xfree(r); - } -} - -static struct para_data_s * -get_parameter (struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r; - - for (r = para; r && r->key != key; r = r->next) - ; - return r; -} - -static const char * -get_parameter_value (struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r = get_parameter (para, key); - return (r && *r->u.value)? r->u.value : NULL; -} - -static int -get_parameter_algo (struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r = get_parameter (para, key); - if (!r) - return -1; - if (digitp (r->u.value)) - return atoi( r->u.value ); - return gcry_pk_map_name (r->u.value); -} - -/* parse the usage parameter. Returns 0 on success. Note that we - only care about sign and encrypt and don't (yet) allow all the - other X.509 usage to be specified; instead we will use a fixed - mapping to the X.509 usage flags */ -static int -parse_parameter_usage (struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r = get_parameter (para, key); - char *p, *pn; - unsigned int use; - - if (!r) - return 0; /* none (this is an optional parameter)*/ - - use = 0; - pn = r->u.value; - while ( (p = strsep (&pn, " \t,")) ) - { - if (!*p) - ; - else if ( !ascii_strcasecmp (p, "sign") ) - use |= GCRY_PK_USAGE_SIGN; - else if ( !ascii_strcasecmp (p, "encrypt") ) - use |= GCRY_PK_USAGE_ENCR; - else - { - log_error ("line %d: invalid usage list\n", r->lnr); - return -1; /* error */ - } - } - r->u.usage = use; - return 0; -} - - -static unsigned int -get_parameter_uint (struct para_data_s *para, enum para_name key) -{ - struct para_data_s *r = get_parameter (para, key); - - if (!r) - return 0; - - return (unsigned int)strtoul (r->u.value, NULL, 10); -} - - - -/* Read the certificate generation parameters from FP and generate - (all) certificate requests. */ -static int -read_parameters (FILE *fp, KsbaWriter writer) -{ - static struct { - const char *name; - enum para_name key; - } keywords[] = { - { "Key-Type", pKEYTYPE}, - { "Key-Length", pKEYLENGTH }, - { "Key-Usage", pKEYUSAGE }, - { "Name-DN", pNAMEDN }, - { "Name-Email", pNAMEEMAIL }, - { NULL, 0 } - }; - char line[1024], *p; - const char *err = NULL; - struct para_data_s *para, *r; - int i, rc = 0, any = 0; - struct reqgen_ctrl_s outctrl; - - memset (&outctrl, 0, sizeof (outctrl)); - outctrl.writer = writer; - - err = NULL; - para = NULL; - while (fgets (line, DIM(line)-1, fp) ) - { - char *keyword, *value; - - outctrl.lnr++; - if (*line && line[strlen(line)-1] != '\n') - { - err = "line too long"; - break; - } - for (p=line; spacep (p); p++) - ; - if (!*p || *p == '#') - continue; - - keyword = p; - if (*keyword == '%') - { - for (; !spacep (p); p++) - ; - if (*p) - *p++ = 0; - for (; spacep (p); p++) - ; - value = p; - trim_trailing_spaces (value); - - if (!ascii_strcasecmp (keyword, "%echo")) - log_info ("%s\n", value); - else if (!ascii_strcasecmp (keyword, "%dry-run")) - outctrl.dryrun = 1; - else if (!ascii_strcasecmp( keyword, "%commit")) - { - rc = proc_parameters (para, &outctrl); - if (rc) - goto leave; - any = 1; - release_parameter_list (para); - para = NULL; - } - else - log_info ("skipping control `%s' (%s)\n", keyword, value); - - continue; - } - - - if (!(p = strchr (p, ':')) || p == keyword) - { - err = "missing colon"; - break; - } - if (*p) - *p++ = 0; - for (; spacep (p); p++) - ; - if (!*p) - { - err = "missing argument"; - break; - } - value = p; - trim_trailing_spaces (value); - - for (i=0; (keywords[i].name - && ascii_strcasecmp (keywords[i].name, keyword)); i++) - ; - if (!keywords[i].name) - { - err = "unknown keyword"; - break; - } - if (keywords[i].key != pKEYTYPE && !para) - { - err = "parameter block does not start with \"Key-Type\""; - break; - } - - if (keywords[i].key == pKEYTYPE && para) - { - rc = proc_parameters (para, &outctrl); - if (rc) - goto leave; - any = 1; - release_parameter_list (para); - para = NULL; - } - else - { - for (r = para; r && r->key != keywords[i].key; r = r->next) - ; - if (r) - { - err = "duplicate keyword"; - break; - } - } - - r = xtrycalloc (1, sizeof *r + strlen( value )); - if (!r) - { - err = "out of core"; - break; - } - r->lnr = outctrl.lnr; - r->key = keywords[i].key; - strcpy (r->u.value, value); - r->next = para; - para = r; - } - - if (err) - { - log_error ("line %d: %s\n", outctrl.lnr, err); - rc = GNUPG_General_Error; - } - else if (ferror(fp)) - { - log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) ); - rc = GNUPG_General_Error; - } - else if (para) - { - rc = proc_parameters (para, &outctrl); - if (rc) - goto leave; - any = 1; - } - - if (!rc && !any) - rc = GNUPG_No_Data; - - leave: - release_parameter_list (para); - return rc; -} - -/* check whether there are invalid characters in the email address S */ -static int -has_invalid_email_chars (const char *s) -{ - int at_seen=0; - static char valid_chars[] = "01234567890_-." - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - for (; *s; s++) - { - if (*s & 0x80) - return 1; - if (*s == '@') - at_seen++; - else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+')) - return 1; - else if (at_seen && !strchr (valid_chars, *s)) - return 1; - } - return at_seen != 1; -} - - -/* Check that all required parameters are given and perform the action */ -static int -proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) -{ - struct para_data_s *r; - const char *s; - int i; - unsigned int nbits; - char numbuf[20]; - unsigned char keyparms[100]; - int rc; - KsbaSexp public; - - /* check that we have all required parameters */ - assert (get_parameter (para, pKEYTYPE)); - - /* We can only use RSA for now. There is a with pkcs-10 on how to - use ElGamal becuase it is expected that a PK algorithm can always - be used for signing. */ - i = get_parameter_algo (para, pKEYTYPE); - if (i < 1 || i != GCRY_PK_RSA ) - { - r = get_parameter (para, pKEYTYPE); - log_error ("line %d: invalid algorithm\n", r->lnr); - return GNUPG_Invalid_Parameter; - } - - /* check the keylength */ - if (!get_parameter (para, pKEYLENGTH)) - nbits = 1024; - else - nbits = get_parameter_uint (para, pKEYLENGTH); - if (nbits < 512 || nbits > 4096) - { - r = get_parameter (para, pKEYTYPE); - log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n", - r->lnr, nbits); - return GNUPG_Invalid_Parameter; - } - - /* check the usage */ - if (parse_parameter_usage (para, pKEYUSAGE)) - return GNUPG_Invalid_Parameter; - - /* check that there is a subject name and that this DN fits our - requirements */ - if (!(s=get_parameter_value (para, pNAMEDN))) - { - r = get_parameter (para, pKEYTYPE); - log_error ("line %d: no subject name given\n", r->lnr); - return GNUPG_Invalid_Parameter; - } - /* fixme check s */ - - /* check that the optional email address is okay */ - if ((s=get_parameter_value (para, pNAMEEMAIL))) - { - if (has_invalid_email_chars (s) - || *s == '@' - || s[strlen(s)-1] == '@' - || s[strlen(s)-1] == '.' - || strstr(s, "..")) - { - r = get_parameter (para, pKEYTYPE); - log_error ("line %d: not a valid email address\n", r->lnr); - return GNUPG_Invalid_Parameter; - } - } - - sprintf (numbuf, "%u", nbits); - snprintf (keyparms, DIM (keyparms)-1, - "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf); - rc = gpgsm_agent_genkey (keyparms, &public); - if (rc) - { - r = get_parameter (para, pKEYTYPE); - log_error ("line %d: key generation failed: %s\n", - r->lnr, gnupg_strerror (rc)); - return rc; - } - - rc = create_request (para, public, outctrl); - xfree (public); - - return rc; -} - - -/* Parameters are checked, the key pair has been created. Now - generate the request and write it out */ -static int -create_request (struct para_data_s *para, KsbaConstSexp public, - struct reqgen_ctrl_s *outctrl) -{ - KsbaCertreq cr; - KsbaError err; - GCRY_MD_HD md; - KsbaStopReason stopreason; - int rc = 0; - const char *s; - - cr = ksba_certreq_new (); - if (!cr) - return seterr (Out_Of_Core); - - md = gcry_md_open (GCRY_MD_SHA1, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - rc = map_gcry_err (gcry_errno ()); - goto leave; - } - if (DBG_HASHING) - gcry_md_start_debug (md, "cr.cri"); - - ksba_certreq_set_hash_function (cr, HASH_FNC, md); - ksba_certreq_set_writer (cr, outctrl->writer); - - err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN)); - if (err) - { - log_error ("error setting the subject's name: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - s = get_parameter_value (para, pNAMEEMAIL); - if (s) - { - char *buf = xtrymalloc (strlen (s) + 3); - - if (!buf) - { - rc = GNUPG_Out_Of_Core; - goto leave; - } - *buf = '<'; - strcpy (buf+1, s); - strcat (buf+1, ">"); - err = ksba_certreq_add_subject (cr, buf); - xfree (buf); - if (err) - { - log_error ("error setting the subject's alternate name: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - - err = ksba_certreq_set_public_key (cr, public); - if (err) - { - log_error ("error setting the public key: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - do - { - err = ksba_certreq_build (cr, &stopreason); - if (err) - { - log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - if (stopreason == KSBA_SR_NEED_SIG) - { - GCRY_SEXP s_pkey; - size_t n; - unsigned char grip[20], hexgrip[41]; - char *sigval; - size_t siglen; - - n = gcry_sexp_canon_len (public, 0, NULL, NULL); - if (!n) - { - log_error ("libksba did not return a proper S-Exp\n"); - err = GNUPG_Bug; - goto leave; - } - rc = gcry_sexp_sscan (&s_pkey, NULL, public, n); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - rc = map_gcry_err (rc); - goto leave; - } - if ( !gcry_pk_get_keygrip (s_pkey, grip) ) - { - rc = seterr (General_Error); - log_error ("can't figure out the keygrip\n"); - gcry_sexp_release (s_pkey); - goto leave; - } - gcry_sexp_release (s_pkey); - for (n=0; n < 20; n++) - sprintf (hexgrip+n*2, "%02X", grip[n]); - - rc = gpgsm_agent_pksign (hexgrip, - gcry_md_read(md, GCRY_MD_SHA1), - gcry_md_get_algo_dlen (GCRY_MD_SHA1), - GCRY_MD_SHA1, - &sigval, &siglen); - if (rc) - { - log_error ("signing failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - err = ksba_certreq_set_sig_val (cr, sigval); - xfree (sigval); - if (err) - { - log_error ("failed to store the sig_val: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - } - while (stopreason != KSBA_SR_READY); - - - leave: - gcry_md_close (md); - ksba_certreq_release (cr); - return rc; -} - - - -/* Create a new key by reading the parameters from in_fd. Multiple - keys may be created */ -int -gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp) -{ - int rc; - FILE *in_fp; - Base64Context b64writer = NULL; - KsbaWriter writer; - - in_fp = fdopen (dup (in_fd), "rb"); - if (!in_fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - return seterr (IO_Error); - } - - ctrl->pem_name = "NEW CERTIFICATE REQUEST"; - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - - rc = read_parameters (in_fp, writer); - if (rc) - { - log_error ("error creating certificate request: %s\n", - gnupg_strerror (rc)); - goto leave; - } - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - gpgsm_status (ctrl, STATUS_KEY_CREATED, "P"); - log_info ("certificate request created\n"); - - leave: - gpgsm_destroy_writer (b64writer); - fclose (in_fp); - return rc; -} - diff --git a/sm/decrypt.c b/sm/decrypt.c deleted file mode 100644 index 012254e22..000000000 --- a/sm/decrypt.c +++ /dev/null @@ -1,502 +0,0 @@ -/* decrypt.c - Decrypt a message - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct decrypt_filter_parm_s { - int algo; - int mode; - int blklen; - GCRY_CIPHER_HD hd; - char iv[16]; - size_t ivlen; - int any_data; /* dod we push anything through the filter at all? */ - unsigned char lastblock[16]; /* to strip the padding we have to - keep this one */ - char helpblock[16]; /* needed because there is no block buffering in - libgcrypt (yet) */ - int helpblocklen; -}; - - - -/* decrypt the session key and fill in the parm structure. The - algo and the IV is expected to be already in PARM. */ -static int -prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val, - struct decrypt_filter_parm_s *parm) -{ - char *seskey = NULL; - size_t n, seskeylen; - int rc; - - rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val, - &seskey, &seskeylen); - if (rc) - { - log_error ("error decrypting session key: %s\n", gnupg_strerror (rc)); - goto leave; - } - - if (DBG_CRYPTO) - log_printhex ("pkcs1 encoded session key:", seskey, seskeylen); - - n=0; - if (seskeylen == 24) - { - /* Smells like a 3-des key. This might happen because a SC has - already done the unpacking. fixme! */ - } - else - { - if (n + 7 > seskeylen ) - { - rc = seterr (Invalid_Session_Key); - goto leave; - } - - /* FIXME: Actually the leading zero is required but due to the way - we encode the output in libgcrypt as an MPI we are not able to - encode that leading zero. However, when using a Smartcard we are - doing it the rightway and therefore we have to skip the zero. This - should be fixed in gpg-agent of course. */ - if (!seskey[n]) - n++; - - if (seskey[n] != 2 ) /* wrong block type version */ - { - rc = seterr (Invalid_Session_Key); - goto leave; - } - - for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */ - ; - n++; /* and the zero byte */ - if (n >= seskeylen ) - { - rc = seterr (Invalid_Session_Key); - goto leave; - } - } - - if (DBG_CRYPTO) - log_printhex ("session key:", seskey+n, seskeylen-n); - - parm->hd = gcry_cipher_open (parm->algo, parm->mode, 0); - if (!parm->hd) - { - rc = gcry_errno (); - log_error ("error creating decryptor: %s\n", gcry_strerror (rc)); - rc = map_gcry_err (rc); - goto leave; - } - - rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n); - if (rc == GCRYERR_WEAK_KEY) - { - log_info (_("WARNING: message was encrypted with " - "a weak key in the symmetric cipher.\n")); - rc = 0; - } - if (rc) - { - log_error("key setup failed: %s\n", gcry_strerror(rc) ); - rc = map_gcry_err (rc); - goto leave; - } - - gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen); - - leave: - xfree (seskey); - return rc; -} - - -/* This function is called by the KSBA writer just before the actual - write is done. The function must take INLEN bytes from INBUF, - decrypt it and store it inoutbuf which has a maximum size of - maxoutlen. The valid bytes in outbuf should be return in outlen. - Due to different buffer sizes or different length of input and - output, it may happen that fewer bytes are process or fewer bytes - are written. */ -static KsbaError -decrypt_filter (void *arg, - const void *inbuf, size_t inlen, size_t *inused, - void *outbuf, size_t maxoutlen, size_t *outlen) -{ - struct decrypt_filter_parm_s *parm = arg; - int blklen = parm->blklen; - size_t orig_inlen = inlen; - - /* fixme: Should we issue an error when we have not seen one full block? */ - if (!inlen) - return KSBA_Bug; - - if (maxoutlen < 2*parm->blklen) - return KSBA_Bug; - /* make some space becuase we will later need an extra block at the end */ - maxoutlen -= blklen; - - if (parm->helpblocklen) - { - int i, j; - - for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++) - parm->helpblock[i] = ((const char*)inbuf)[j]; - inlen -= j; - if (blklen > maxoutlen) - return KSBA_Bug; - if (i < blklen) - { - parm->helpblocklen = i; - *outlen = 0; - } - else - { - parm->helpblocklen = 0; - if (parm->any_data) - { - memcpy (outbuf, parm->lastblock, blklen); - *outlen =blklen; - } - else - *outlen = 0; - gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen, - parm->helpblock, blklen); - parm->any_data = 1; - } - *inused = orig_inlen - inlen; - return 0; - } - - - if (inlen > maxoutlen) - inlen = maxoutlen; - if (inlen % blklen) - { /* store the remainder away */ - parm->helpblocklen = inlen%blklen; - inlen = inlen/blklen*blklen; - memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen); - } - - *inused = inlen + parm->helpblocklen; - if (inlen) - { - assert (inlen >= blklen); - if (parm->any_data) - { - gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen, - inbuf, inlen); - memcpy (outbuf, parm->lastblock, blklen); - memcpy (parm->lastblock,(char*)outbuf+inlen, blklen); - *outlen = inlen; - } - else - { - gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen); - memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen); - *outlen = inlen - blklen; - parm->any_data = 1; - } - } - else - *outlen = 0; - return 0; -} - - - -/* Perform a decrypt operation. */ -int -gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) -{ - int rc; - KsbaError err; - Base64Context b64reader = NULL; - Base64Context b64writer = NULL; - KsbaReader reader; - KsbaWriter writer; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KEYDB_HANDLE kh; - int recp; - FILE *in_fp = NULL; - struct decrypt_filter_parm_s dfparm; - - memset (&dfparm, 0, sizeof dfparm); - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - - in_fp = fdopen ( dup (in_fd), "rb"); - if (!in_fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gnupg_strerror (rc)); - goto leave; - } - - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* parser loop */ - do - { - err = ksba_cms_parse (cms, &stopreason); - if (err) - { - log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - if (stopreason == KSBA_SR_BEGIN_DATA - || stopreason == KSBA_SR_DETACHED_DATA) - { - int algo, mode; - const char *algoid; - int any_key = 0; - - algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/); - algo = gcry_cipher_map_name (algoid); - mode = gcry_cipher_mode_from_oid (algoid); - if (!algo || !mode) - { - rc = GNUPG_Unsupported_Algorithm; - log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?"); - if (algoid && !strcmp (algoid, "1.2.840.113549.3.2")) - log_info (_("(this is the RC2 algorithm)\n")); - else if (!algoid) - log_info (_("(this does not seem to be an encrypted" - " message)\n")); - gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm", - gnupg_error_token (rc), algoid?algoid:"?", NULL); - goto leave; - } - dfparm.algo = algo; - dfparm.mode = mode; - dfparm.blklen = gcry_cipher_get_algo_blklen (algo); - if (dfparm.blklen > sizeof (dfparm.helpblock)) - return GNUPG_Bug; - - rc = ksba_cms_get_content_enc_iv (cms, - dfparm.iv, - sizeof (dfparm.iv), - &dfparm.ivlen); - if (rc) - { - log_error ("error getting IV: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - for (recp=0; !any_key; recp++) - { - char *issuer; - KsbaSexp serial; - KsbaSexp enc_val; - char *hexkeygrip = NULL; - - err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); - if (err == -1 && recp) - break; /* no more recipients */ - if (err) - log_error ("recp %d - error getting info: %s\n", - recp, ksba_strerror (err)); - else - { - KsbaCert cert = NULL; - - log_debug ("recp %d - issuer: `%s'\n", - recp, issuer? issuer:"[NONE]"); - log_debug ("recp %d - serial: ", recp); - gpgsm_dump_serial (serial); - log_printf ("\n"); - - keydb_search_reset (kh); - rc = keydb_search_issuer_sn (kh, issuer, serial); - if (rc) - { - log_error ("failed to find the certificate: %s\n", - gnupg_strerror(rc)); - goto oops; - } - - rc = keydb_get_cert (kh, &cert); - if (rc) - { - log_error ("failed to get cert: %s\n", gnupg_strerror (rc)); - goto oops; - } - /* Just in case there is a problem with the own - certificate we print this message - should never - happen of course */ - rc = gpgsm_cert_use_decrypt_p (cert); - if (rc) - { - gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage", - gnupg_error_token (rc), NULL); - rc = 0; - } - - hexkeygrip = gpgsm_get_keygrip_hexstring (cert); - - oops: - xfree (issuer); - xfree (serial); - ksba_cert_release (cert); - } - - if (!hexkeygrip) - ; - else if (!(enc_val = ksba_cms_get_enc_val (cms, recp))) - log_error ("recp %d - error getting encrypted session key\n", - recp); - else - { - rc = prepare_decryption (hexkeygrip, enc_val, &dfparm); - xfree (enc_val); - if (rc) - { - log_debug ("decrypting session key failed: %s\n", - gnupg_strerror (rc)); - } - else - { /* setup the bulk decrypter */ - any_key = 1; - ksba_writer_set_filter (writer, - decrypt_filter, - &dfparm); - } - } - } - if (!any_key) - { - rc = GNUPG_No_Secret_Key; - goto leave; - } - } - else if (stopreason == KSBA_SR_END_DATA) - { - ksba_writer_set_filter (writer, NULL, NULL); - if (dfparm.any_data) - { /* write the last block with padding removed */ - int i, npadding = dfparm.lastblock[dfparm.blklen-1]; - if (!npadding || npadding > dfparm.blklen) - { - log_error ("invalid padding with value %d\n", npadding); - rc = seterr (Invalid_Data); - goto leave; - } - rc = ksba_writer_write (writer, - dfparm.lastblock, - dfparm.blklen - npadding); - if (rc) - { - rc = map_ksba_err (rc); - goto leave; - } - for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++) - { - if (dfparm.lastblock[i] != npadding) - { - log_error ("inconsistent padding\n"); - rc = seterr (Invalid_Data); - goto leave; - } - } - } - } - - } - while (stopreason != KSBA_SR_READY); - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL); - - - leave: - if (rc) - gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); - ksba_cms_release (cms); - gpgsm_destroy_reader (b64reader); - gpgsm_destroy_writer (b64writer); - keydb_release (kh); - if (in_fp) - fclose (in_fp); - if (dfparm.hd) - gcry_cipher_close (dfparm.hd); - return rc; -} - - diff --git a/sm/delete.c b/sm/delete.c deleted file mode 100644 index cd1491a86..000000000 --- a/sm/delete.c +++ /dev/null @@ -1,165 +0,0 @@ -/* delete.c - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -/* Delete a certificate or an secret key from a key database. */ -static int -delete_one (CTRL ctrl, const char *username) -{ - int rc = 0; - KEYDB_SEARCH_DESC desc; - KEYDB_HANDLE kh = NULL; - KsbaCert cert = NULL; - int duplicates = 0; - - rc = keydb_classify_name (username, &desc); - if (rc) - { - log_error (_("certificate `%s' not found: %s\n"), - username, gnupg_strerror (rc)); - gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "1", NULL); - goto leave; - } - - kh = keydb_new (0); - if (!kh) - { - log_error ("keydb_new failed\n"); - goto leave; - } - - - rc = keydb_search (kh, &desc, 1); - if (!rc) - rc = keydb_get_cert (kh, &cert); - if (!rc) - { - char fpr[20]; - - gpgsm_get_fingerprint (cert, 0, fpr, NULL); - - next_ambigious: - rc = keydb_search (kh, &desc, 1); - if (rc == -1) - rc = 0; - else if (!rc) - { - KsbaCert cert2 = NULL; - char fpr2[20]; - - /* We ignore all duplicated certificates which might have - been inserted due to program bugs. */ - if (!keydb_get_cert (kh, &cert2)) - { - gpgsm_get_fingerprint (cert2, 0, fpr2, NULL); - ksba_cert_release (cert2); - if (!memcmp (fpr, fpr2, 20)) - { - duplicates++; - goto next_ambigious; - } - } - rc = GNUPG_Ambiguous_Name; - } - } - if (rc) - { - if (rc == -1) - rc = GNUPG_No_Public_Key; - log_error (_("certificate `%s' not found: %s\n"), - username, gnupg_strerror (rc)); - gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "3", NULL); - goto leave; - } - - /* we need to search again to get back to the right position. */ - do - { - keydb_search_reset (kh); - rc = keydb_search (kh, &desc, 1); - if (rc) - { - log_error ("problem re-searching certificate: %s\n", - gnupg_strerror (rc)); - goto leave; - } - - rc = keydb_delete (kh); - if (rc) - goto leave; - if (opt.verbose) - { - if (duplicates) - log_info (_("duplicated certificate `%s' deleted\n"), username); - else - log_info (_("certificate `%s' deleted\n"), username); - } - } - while (duplicates--); - - leave: - keydb_release (kh); - ksba_cert_release (cert); - return rc; -} - - - -/* Delete the certificates specified by NAMES. */ -int -gpgsm_delete (CTRL ctrl, STRLIST names) -{ - int rc; - - if (!names) - { - log_error ("nothing to delete\n"); - return GNUPG_No_Data; - } - - for (; names; names=names->next ) - { - rc = delete_one (ctrl, names->d); - if (rc) - { - log_error (_("deleting certificate \"%s\" failed: %s\n"), - names->d, gnupg_strerror (rc) ); - return rc; - } - } - - return 0; -} diff --git a/sm/encrypt.c b/sm/encrypt.c deleted file mode 100644 index 40e12582f..000000000 --- a/sm/encrypt.c +++ /dev/null @@ -1,549 +0,0 @@ -/* encrypt.c - Encrypt a message - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -struct dek_s { - const char *algoid; - int algo; - GCRY_CIPHER_HD chd; - char key[32]; - int keylen; - char iv[32]; - int ivlen; -}; -typedef struct dek_s *DEK; - -struct encrypt_cb_parm_s { - FILE *fp; - DEK dek; - int eof_seen; - int ready; - int readerror; - int bufsize; - unsigned char *buffer; - int buflen; -}; - - - - - -/* initialize the data encryptionkey (session key) */ -static int -init_dek (DEK dek) -{ - int rc=0, mode, i; - - dek->algo = gcry_cipher_map_name (dek->algoid); - mode = gcry_cipher_mode_from_oid (dek->algoid); - if (!dek->algo || !mode) - { - log_error ("unsupported algorithm `%s'\n", dek->algoid); - return GNUPG_Unsupported_Algorithm; - } - - dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); - if (!dek->keylen || dek->keylen > sizeof (dek->key)) - return GNUPG_Bug; - - dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo); - if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) - return GNUPG_Bug; - - if (dek->keylen < 100/8) - { /* make sure we don't use weak keys */ - log_error ("key length of `%s' too small\n", dek->algoid); - return GNUPG_Unsupported_Algorithm; - } - - dek->chd = gcry_cipher_open (dek->algo, mode, GCRY_CIPHER_SECURE); - if (!dek->chd) - { - log_error ("failed to create cipher context: %s\n", gcry_strerror (-1)); - return GNUPG_General_Error; - } - - for (i=0; i < 8; i++) - { - gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); - rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen); - if (rc != GCRYERR_WEAK_KEY) - break; - log_info(_("weak key created - retrying\n") ); - } - if (rc) - { - log_error ("failed to set the key: %s\n", gcry_strerror (rc)); - gcry_cipher_close (dek->chd); - dek->chd = NULL; - return map_gcry_err (rc); - } - - gcry_randomize (dek->iv, dek->ivlen, GCRY_STRONG_RANDOM); - rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); - if (rc) - { - log_error ("failed to set the IV: %s\n", gcry_strerror (rc)); - gcry_cipher_close (dek->chd); - dek->chd = NULL; - return map_gcry_err (rc); - } - - return 0; -} - - -/* Encode the session key. NBITS is the number of bits which should be - used for packing the session key. returns: An mpi with the session - key (caller must free) */ -static GCRY_MPI -encode_session_key (DEK dek, unsigned int nbits) -{ - int nframe = (nbits+7) / 8; - byte *p; - byte *frame; - int i,n; - MPI a; - - if (dek->keylen + 7 > nframe || !nframe) - log_bug ("can't encode a %d bit key in a %d bits frame\n", - dek->keylen*8, nbits ); - - /* We encode the session key in this way: - * - * 0 2 RND(n bytes) 0 KEY(k bytes) - * - * (But how can we store the leading 0 - the external representaion - * of MPIs doesn't allow leading zeroes =:-) - * - * RND are non-zero random bytes. - * KEY is the encryption key (session key) - */ - - frame = gcry_xmalloc_secure (nframe); - n = 0; - frame[n++] = 0; - frame[n++] = 2; - i = nframe - 3 - dek->keylen; - assert (i > 0); - p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); - /* replace zero bytes by new values */ - for (;;) - { - int j, k; - byte *pp; - - /* count the zero bytes */ - for(j=k=0; j < i; j++ ) - { - if( !p[j] ) - k++; - } - if( !k ) - break; /* okay: no zero bytes */ - - k += k/128; /* better get some more */ - pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); - for (j=0; j < i && k; j++) - { - if( !p[j] ) - p[j] = pp[--k]; - } - xfree (pp); - } - memcpy (frame+n, p, i); - xfree (p); - - n += i; - frame[n++] = 0; - memcpy (frame+n, dek->key, dek->keylen); - n += dek->keylen; - assert (n == nframe); - if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, &nframe) ) - BUG (); - gcry_free(frame); - - return a; -} - - - -/* encrypt the DEK under the key contained in CERT and return it as a - canonical S-Exp in encval */ -static int -encrypt_dek (const DEK dek, KsbaCert cert, char **encval) -{ - GCRY_SEXP s_ciph, s_data, s_pkey; - int rc; - KsbaSexp buf; - size_t len; - - *encval = NULL; - - /* get the key from the cert */ - buf = ksba_cert_get_public_key (cert); - if (!buf) - { - log_error ("no public key for recipient\n"); - return GNUPG_No_Public_Key; - } - len = gcry_sexp_canon_len (buf, 0, NULL, NULL); - if (!len) - { - log_error ("libksba did not return a proper S-Exp\n"); - return GNUPG_Bug; - } - rc = gcry_sexp_sscan (&s_pkey, NULL, buf, len); - xfree (buf); buf = NULL; - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return map_gcry_err (rc); - } - - /* put the encoded cleartext into a simple list */ - { - /* fixme: actually the pkcs-1 encoding should go into libgcrypt */ - GCRY_MPI data = encode_session_key (dek, gcry_pk_get_nbits (s_pkey)); - if (!data) - { - gcry_mpi_release (data); - return GNUPG_General_Error; - } - if (gcry_sexp_build (&s_data, NULL, "%m", data)) - BUG (); - gcry_mpi_release (data); - } - - /* pass it to libgcrypt */ - rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); - gcry_sexp_release (s_data); - gcry_sexp_release (s_pkey); - - /* reformat it */ - len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xtrymalloc (len); - if (!buf) - { - gcry_sexp_release (s_ciph); - return GNUPG_Out_Of_Core; - } - len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - - *encval = buf; - return 0; -} - - - -/* do the actual encryption */ -static int -encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread) -{ - struct encrypt_cb_parm_s *parm = cb_value; - int blklen = parm->dek->ivlen; - unsigned char *p; - size_t n; - - *nread = 0; - if (!buffer) - return -1; /* not supported */ - - if (parm->ready) - return -1; - - if (count < blklen) - BUG (); - - if (!parm->eof_seen) - { /* fillup the buffer */ - p = parm->buffer; - for (n=parm->buflen; n < parm->bufsize; n++) - { - int c = getc (parm->fp); - if (c == EOF) - { - if (ferror (parm->fp)) - { - parm->readerror = errno; - return -1; - } - parm->eof_seen = 1; - break; - } - p[n] = c; - } - parm->buflen = n; - } - - n = parm->buflen < count? parm->buflen : count; - n = n/blklen * blklen; - if (n) - { /* encrypt the stuff */ - gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n); - *nread = n; - /* Who cares about cycles, take the easy way and shift the buffer */ - parm->buflen -= n; - memmove (parm->buffer, parm->buffer+n, parm->buflen); - } - else if (parm->eof_seen) - { /* no complete block but eof: add padding */ - /* fixme: we should try to do this also in the above code path */ - int i, npad = blklen - (parm->buflen % blklen); - p = parm->buffer; - for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++) - p[n] = npad; - gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n); - *nread = n; - parm->ready = 1; - } - - return 0; -} - - - - -/* Perform an encrypt operation. - - Encrypt the data received on DATA-FD and write it to OUT_FP. The - recipients are take from the certificate given in recplist; if this - is NULL it will be encrypted for a default recipient */ -int -gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) -{ - int rc = 0; - Base64Context b64writer = NULL; - KsbaError err; - KsbaWriter writer; - KsbaReader reader = NULL; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KEYDB_HANDLE kh = NULL; - struct encrypt_cb_parm_s encparm; - DEK dek = NULL; - int recpno; - FILE *data_fp = NULL; - CERTLIST cl; - - memset (&encparm, 0, sizeof encparm); - - if (!recplist) - { - log_error(_("no valid recipients given\n")); - gpgsm_status (ctrl, STATUS_NO_RECP, "0"); - rc = GNUPG_No_Public_Key; - goto leave; - } - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - data_fp = fdopen ( dup (data_fd), "rb"); - if (!data_fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - reader = ksba_reader_new (); - if (!reader) - rc = KSBA_Out_Of_Core; - if (!rc) - rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm); - if (rc) - { - rc = map_ksba_err (rc); - goto leave; - } - encparm.fp = data_fp; - - ctrl->pem_name = "ENCRYPTED MESSAGE"; - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* We are going to create enveloped data with uninterpreted data as - inner content */ - err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA); - if (!err) - err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA); - if (err) - { - log_debug ("ksba_cms_set_content_type failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* create a session key */ - dek = xtrycalloc (1, sizeof *dek); /* hmmm: should we put it into secmem?*/ - if (!dek) - rc = GNUPG_Out_Of_Core; - else - { - dek->algoid = opt.def_cipher_algoid; - rc = init_dek (dek); - } - if (rc) - { - log_error ("failed to create the session key: %s\n", - gnupg_strerror (rc)); - goto leave; - } - - err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen); - if (err) - { - log_error ("ksba_cms_set_content_enc_algo failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - encparm.dek = dek; - /* Use a ~8k (AES) or ~4k (3DES) buffer */ - encparm.bufsize = 500 * dek->ivlen; - encparm.buffer = xtrymalloc (encparm.bufsize); - if (!encparm.buffer) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - /* gather certificates of recipients, encrypt the session key for - each and store them in the CMS object */ - for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next) - { - char *encval; - - rc = encrypt_dek (dek, cl->cert, &encval); - if (rc) - { - log_error ("encryption failed for recipient no. %d: %s\n", - recpno, gnupg_strerror (rc)); - goto leave; - } - - err = ksba_cms_add_recipient (cms, cl->cert); - if (err) - { - log_error ("ksba_cms_add_recipient failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - xfree (encval); - goto leave; - } - - err = ksba_cms_set_enc_val (cms, recpno, encval); - xfree (encval); - if (err) - { - log_error ("ksba_cms_set_enc_val failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - /* main control loop for encryption */ - recpno = 0; - do - { - err = ksba_cms_build (cms, &stopreason); - if (err) - { - log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - while (stopreason != KSBA_SR_READY); - - if (encparm.readerror) - { - log_error ("error reading input: %s\n", strerror (encparm.readerror)); - rc = seterr (Read_Error); - goto leave; - } - - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - log_info ("encrypted data created\n"); - - leave: - ksba_cms_release (cms); - gpgsm_destroy_writer (b64writer); - ksba_reader_release (reader); - keydb_release (kh); - xfree (dek); - if (data_fp) - fclose (data_fp); - xfree (encparm.buffer); - return rc; -} diff --git a/sm/export.c b/sm/export.c deleted file mode 100644 index 042850752..000000000 --- a/sm/export.c +++ /dev/null @@ -1,248 +0,0 @@ -/* export.c - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" - -static void print_short_info (KsbaCert cert, FILE *fp); - - - -/* Export all certificates or just those given in NAMES. */ -void -gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) -{ - KEYDB_HANDLE hd; - KEYDB_SEARCH_DESC *desc = NULL; - int ndesc; - Base64Context b64writer = NULL; - KsbaWriter writer; - STRLIST sl; - KsbaCert cert = NULL; - int rc=0; - int count = 0; - int i; - - hd = keydb_new (0); - if (!hd) - { - log_error ("keydb_new failed\n"); - goto leave; - } - - if (!names) - ndesc = 1; - else - { - for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) - ; - } - - desc = xtrycalloc (ndesc, sizeof *desc); - if (!ndesc) - { - log_error ("%s\n", gnupg_strerror (GNUPG_Out_Of_Core)); - goto leave; - } - - if (!names) - desc[0].mode = KEYDB_SEARCH_MODE_FIRST; - else - { - for (ndesc=0, sl=names; sl; sl = sl->next) - { - rc = keydb_classify_name (sl->d, desc+ndesc); - if (rc) - { - log_error ("key `%s' not found: %s\n", - sl->d, gnupg_strerror (rc)); - rc = 0; - } - else - ndesc++; - } - } - - /* If all specifications are done by fingerprint, we switch to - ephemeral mode so that _all_ currently available and matching - certificates are exported. - - fixme: we should in this case keep a list of certificates to - avoid accidential export of duplicate certificates. */ - if (names && ndesc) - { - for (i=0; (i < ndesc - && (desc[i].mode == KEYDB_SEARCH_MODE_FPR - || desc[i].mode == KEYDB_SEARCH_MODE_FPR20 - || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++) - ; - if (i == ndesc) - keydb_set_ephemeral (hd, 1); - } - - while (!(rc = keydb_search (hd, desc, ndesc))) - { - const unsigned char *image; - size_t imagelen; - - if (!names) - desc[0].mode = KEYDB_SEARCH_MODE_NEXT; - - rc = keydb_get_cert (hd, &cert); - if (rc) - { - log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - image = ksba_cert_get_image (cert, &imagelen); - if (!image) - { - log_error ("ksba_cert_get_image failed\n"); - goto leave; - } - - if (ctrl->create_pem) - { - if (count) - putc ('\n', fp); - print_short_info (cert, fp); - putc ('\n', fp); - } - count++; - - if (!b64writer) - { - ctrl->pem_name = "CERTIFICATE"; - rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - } - - rc = ksba_writer_write (writer, image, imagelen); - if (rc) - { - log_error ("write error: %s\n", ksba_strerror (rc)); - goto leave; - } - - if (ctrl->create_pem) - { - /* We want one certificate per PEM block */ - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - gpgsm_destroy_writer (b64writer); - b64writer = NULL; - } - - ksba_cert_release (cert); - cert = NULL; - } - if (rc && rc != -1) - log_error ("keydb_search failed: %s\n", gnupg_strerror (rc)); - else if (b64writer) - { - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - } - - leave: - gpgsm_destroy_writer (b64writer); - ksba_cert_release (cert); - xfree (desc); - keydb_release (hd); -} - - -/* Print some info about the certifciate CERT to FP */ -static void -print_short_info (KsbaCert cert, FILE *fp) -{ - char *p; - KsbaSexp sexp; - int idx; - - for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++) - { - fputs (!idx? "Issuer ...: " - : "\n aka ...: ", fp); - gpgsm_print_name (fp, p); - xfree (p); - } - putc ('\n', fp); - - fputs ("Serial ...: ", fp); - sexp = ksba_cert_get_serial (cert); - if (sexp) - { - int len; - const unsigned char *s = sexp; - - if (*s == '(') - { - s++; - for (len=0; *s && *s != ':' && digitp (s); s++) - len = len*10 + atoi_1 (s); - if (*s == ':') - for (s++; len; len--, s++) - fprintf (fp, "%02X", *s); - } - xfree (sexp); - } - putc ('\n', fp); - - for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++) - { - fputs (!idx? "Subject ..: " - : "\n aka ..: ", fp); - gpgsm_print_name (fp, p); - xfree (p); - } - putc ('\n', fp); -} - - - - - - diff --git a/sm/fingerprint.c b/sm/fingerprint.c deleted file mode 100644 index 6a84966db..000000000 --- a/sm/fingerprint.c +++ /dev/null @@ -1,271 +0,0 @@ -/* fingerprint.c - Get the fingerprint - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" - -/* Return the fingerprint of the certificate (we can't put this into - libksba because we need libgcrypt support). The caller must - provide an array of sufficient length or NULL so that the function - allocates the array. If r_len is not NULL, the length of the - digest is returned; well, this can also be done by using - gcry_md_get_algo_dlen(). If algo is 0, a SHA-1 will be used. - - If there is a problem , the function does never return NULL but a - digest of all 0xff. - */ -char * -gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len) -{ - GCRY_MD_HD md; - int rc, len; - - if (!algo) - algo = GCRY_MD_SHA1; - - len = gcry_md_get_algo_dlen (algo); - assert (len); - if (!array) - array = xmalloc (len); - - if (r_len) - *r_len = len; - - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - memset (array, 0xff, len); /* better return an invalid fpr than NULL */ - return array; - } - - rc = ksba_cert_hash (cert, 0, HASH_FNC, md); - if (rc) - { - log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); - gcry_md_close (md); - memset (array, 0xff, len); /* better return an invalid fpr than NULL */ - return array; - } - gcry_md_final (md); - memcpy (array, gcry_md_read(md, algo), len ); - return array; -} - - -/* Return an allocated buffer with the formatted fingerprint */ -char * -gpgsm_get_fingerprint_string (KsbaCert cert, int algo) -{ - unsigned char digest[MAX_DIGEST_LEN]; - char *buf; - int len, i; - - if (!algo) - algo = GCRY_MD_SHA1; - - len = gcry_md_get_algo_dlen (algo); - assert (len <= MAX_DIGEST_LEN ); - gpgsm_get_fingerprint (cert, algo, digest, NULL); - buf = xmalloc (len*3+1); - *buf = 0; - for (i=0; i < len; i++ ) - sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]); - return buf; -} - -/* Return an allocated buffer with the formatted fingerprint as one - large hexnumber */ -char * -gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo) -{ - unsigned char digest[MAX_DIGEST_LEN]; - char *buf; - int len, i; - - if (!algo) - algo = GCRY_MD_SHA1; - - len = gcry_md_get_algo_dlen (algo); - assert (len <= MAX_DIGEST_LEN ); - gpgsm_get_fingerprint (cert, algo, digest, NULL); - buf = xmalloc (len*3+1); - *buf = 0; - for (i=0; i < len; i++ ) - sprintf (buf+strlen(buf), "%02X", digest[i]); - return buf; -} - -/* Return a certificate ID. These are the last 4 bytes of the SHA-1 - fingerprint. */ -unsigned long -gpgsm_get_short_fingerprint (KsbaCert cert) -{ - unsigned char digest[20]; - - gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); - return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]); -} - - -/* Return the so called KEYGRIP which is the SHA-1 hash of the public - key parameters expressed as an canoncial encoded S-Exp. array must - be 20 bytes long. returns the array or a newly allocated one if the - passed one was NULL */ -char * -gpgsm_get_keygrip (KsbaCert cert, char *array) -{ - GCRY_SEXP s_pkey; - int rc; - KsbaSexp p; - size_t n; - - p = ksba_cert_get_public_key (cert); - if (!p) - return NULL; /* oops */ - - if (DBG_X509) - log_debug ("get_keygrip for public key: %s\n", p); - n = gcry_sexp_canon_len (p, 0, NULL, NULL); - if (!n) - { - log_error ("libksba did not return a proper S-Exp\n"); - return NULL; - } - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); - xfree (p); - if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return NULL; - } - array = gcry_pk_get_keygrip (s_pkey, array); - gcry_sexp_release (s_pkey); - if (!array) - { - rc = seterr (General_Error); - log_error ("can't calculate keygrip\n"); - return NULL; - } - if (DBG_X509) - log_printhex ("keygrip=", array, 20); - - return array; -} - -/* Return an allocated buffer with the keygrip of CERT in from of an - hexstring. NULL is returned in case of error */ -char * -gpgsm_get_keygrip_hexstring (KsbaCert cert) -{ - unsigned char grip[20]; - char *buf, *p; - int i; - - gpgsm_get_keygrip (cert, grip); - buf = p = xmalloc (20*2+1); - for (i=0; i < 20; i++, p += 2 ) - sprintf (p, "%02X", grip[i]); - return buf; -} - - - -/* For certain purposes we need a certificate id which has an upper - limit of the size. We use the hash of the issuer name and the - serial number for this. In most cases the serial number is not - that large and the resulting string can be passed on an assuan - command line. Everything is hexencoded with the serialnumber - delimted from the has by a dot. - - The caller must free the string. -*/ -char * -gpgsm_get_certid (KsbaCert cert) -{ - KsbaSexp serial; - unsigned char *p; - char *endp; - unsigned char hash[20]; - unsigned long n; - char *certid; - int i; - - p = ksba_cert_get_issuer (cert, 0); - if (!p) - return NULL; /* Ooops: No issuer */ - gcry_md_hash_buffer (GCRY_MD_SHA1, hash, p, strlen (p)); - xfree (p); - - serial = ksba_cert_get_serial (cert); - if (!serial) - return NULL; /* oops: no serial number */ - p = serial; - if (*p != '(') - { - log_error ("Ooops: invalid serial number\n"); - xfree (serial); - return NULL; - } - p++; - n = strtoul (p, &endp, 10); - p = endp; - if (*p != ':') - { - log_error ("Ooops: invalid serial number (no colon)\n"); - xfree (serial); - return NULL; - } - p++; - - certid = xtrymalloc ( 40 + 1 + n*2 + 1); - if (!certid) - { - xfree (serial); - return NULL; /* out of core */ - } - - for (i=0, endp = certid; i < 20; i++, endp += 2 ) - sprintf (endp, "%02X", hash[i]); - *endp++ = '.'; - for (i=0; i < n; i++, endp += 2) - sprintf (endp, "%02X", p[i]); - *endp = 0; - - xfree (serial); - return certid; -} - - - - - - diff --git a/sm/gpgsm.c b/sm/gpgsm.c deleted file mode 100644 index bfcdeb741..000000000 --- a/sm/gpgsm.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* gpgsm.c - GnuPG for S/MIME - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include "gpgsm.h" -#include "../assuan/assuan.h" /* malloc hooks */ -#include "../kbx/keybox.h" /* malloc hooks */ -#include "i18n.h" -#include "keydb.h" -#include "sysutils.h" - -enum cmd_and_opt_values { - aNull = 0, - oArmor = 'a', - aDetachedSign = 'b', - aSym = 'c', - aDecrypt = 'd', - aEncr = 'e', - oInteractive = 'i', - oKOption = 'k', - oDryRun = 'n', - oOutput = 'o', - oQuiet = 'q', - oRecipient = 'r', - aSign = 's', - oTextmodeShort= 't', - oUser = 'u', - oVerbose = 'v', - oCompress = 'z', - oNotation = 'N', - oBatch = 500, - aClearsign, - aStore, - aKeygen, - aSignEncr, - aSignKey, - aLSignKey, - aListPackets, - aEditKey, - aDeleteKey, - aImport, - aVerify, - aVerifyFiles, - aListKeys, - aListExternalKeys, - aListSigs, - aListSecretKeys, - aSendKeys, - aRecvKeys, - aExport, - aCheckKeys, /* nyi */ - aServer, - aLearnCard, - - oOptions, - oDebug, - oDebugAll, - oDebugWait, - oDebugNoChainValidation, - oLogFile, - - oEnableSpecialFilenames, - - oAgentProgram, - oDisplay, - oTTYname, - oTTYtype, - oLCctype, - oLCmessages, - - oDirmngrProgram, - oFakedSystemTime, - - - oAssumeArmor, - oAssumeBase64, - oAssumeBinary, - - oBase64, - oNoArmor, - - oDisableCRLChecks, - oEnableCRLChecks, - - oIncludeCerts, - oPolicyFile, - oDisablePolicyChecks, - oEnablePolicyChecks, - oAutoIssuerKeyRetrieve, - - - oTextmode, - oFingerprint, - oWithFingerprint, - oAnswerYes, - oAnswerNo, - oKeyring, - oSecretKeyring, - oDefaultKey, - oDefRecipient, - oDefRecipientSelf, - oNoDefRecipient, - oStatusFD, - oNoComment, - oNoVersion, - oEmitVersion, - oCompletesNeeded, - oMarginalsNeeded, - oMaxCertDepth, - oLoadExtension, - oRFC1991, - oOpenPGP, - oCipherAlgo, - oDigestAlgo, - oCompressAlgo, - oPasswdFD, - oCommandFD, - oNoVerbose, - oTrustDBName, - oNoSecmemWarn, - oNoDefKeyring, - oNoGreeting, - oNoTTY, - oNoOptions, - oNoBatch, - oHomedir, - oWithColons, - oWithKeyData, - oSkipVerify, - oCompressKeys, - oCompressSigs, - oAlwaysTrust, - oRunAsShmCP, - oSetFilename, - oSetPolicyURL, - oUseEmbeddedFilename, - oComment, - oDefaultComment, - oThrowKeyid, - oForceV3Sigs, - oForceMDC, - oS2KMode, - oS2KDigest, - oS2KCipher, - oCharset, - oNotDashEscaped, - oEscapeFrom, - oLockOnce, - oLockMultiple, - oLockNever, - oKeyServer, - oEncryptTo, - oNoEncryptTo, - oLoggerFD, - oUtf8Strings, - oNoUtf8Strings, - oDisableCipherAlgo, - oDisablePubkeyAlgo, - oAllowNonSelfsignedUID, - oAllowFreeformUID, - oNoLiteral, - oSetFilesize, - oHonorHttpProxy, - oFastListMode, - oListOnly, - oIgnoreTimeConflict, - oNoRandomSeedFile, - oNoAutoKeyRetrieve, - oUseAgent, - oMergeOnly, - oTryAllSecrets, - oTrustedKey, - oEmuMDEncodeBug, - aDummy - }; - - -static ARGPARSE_OPTS opts[] = { - - { 300, NULL, 0, N_("@Commands:\n ") }, - - { aSign, "sign", 256, N_("|[file]|make a signature")}, - { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, - { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, - { aEncr, "encrypt", 256, N_("encrypt data")}, - { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, - { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, - { aVerify, "verify" , 256, N_("verify a signature")}, - { aVerifyFiles, "verify-files" , 256, "@" }, - { aListKeys, "list-keys", 256, N_("list keys")}, - { aListExternalKeys, "list-external-keys", 256, N_("list external keys")}, - { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, - { aListSigs, "list-sigs", 256, N_("list certificate chain")}, - { aListSigs, "check-sigs",256, "@"}, - { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, - { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, - { aKeygen, "gen-key", 256, N_("generate a new key pair")}, - { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")}, - { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, - { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, - { aImport, "import", 256 , N_("import certificates")}, - { aExport, "export", 256 , N_("export certificates")}, - { aLearnCard, "learn-card", 256 ,N_("register a smartcard")}, - { aServer, "server", 256, N_("run in server mode")}, - { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - - { 301, NULL, 0, N_("@\nOptions:\n ") }, - - { oArmor, "armor", 0, N_("create ascii armored output")}, - { oArmor, "armour", 0, "@" }, - { oBase64, "base64", 0, N_("create base-64 encoded output")}, - - { oAssumeArmor, "assume-armor", 0, N_("assume input is in PEM format")}, - { oAssumeBase64, "assume-base64", 0, - N_("assume input is in base-64 format")}, - { oAssumeBinary, "assume-binary", 0, - N_("assume input is in binary format")}, - - { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, - - - { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, - { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, - - { oIncludeCerts, "include-certs", 1, - N_("|N|number of certificates to include") }, - - { oPolicyFile, "policy-file", 2, - N_("|FILE|take policy information from FILE") }, - - { oDisablePolicyChecks, "disable-policy-checks", 0, - N_("do not check certificate policies")}, - { oEnablePolicyChecks, "enable-policy-checks", 0, "@"}, - - { oAutoIssuerKeyRetrieve, "auto-issuer-key-retrieve", 0, - N_("fetch missing issuer certificates")}, - -#if 0 - { oDefRecipient, "default-recipient" ,2, - N_("|NAME|use NAME as default recipient")}, - { oDefRecipientSelf, "default-recipient-self" ,0, - N_("use the default key as default recipient")}, - { oNoDefRecipient, "no-default-recipient", 0, "@" }, - { oEncryptTo, "encrypt-to", 2, "@" }, - { oNoEncryptTo, "no-encrypt-to", 0, "@" }, - -#endif - { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, - -#if 0 - { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, - { oTextmodeShort, NULL, 0, "@"}, - { oTextmode, "textmode", 0, N_("use canonical text mode")}, -#endif - - { oOutput, "output", 2, N_("use as output file")}, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, -#if 0 - { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, - { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, -#endif - { oDryRun, "dry-run", 0, N_("do not make any changes") }, - /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */ - /*{ oUseAgent, "use-agent",0, N_("use the gpg-agent")},*/ - { oBatch, "batch", 0, N_("batch mode: never ask")}, - { oAnswerYes, "yes", 0, N_("assume yes on most questions")}, - { oAnswerNo, "no", 0, N_("assume no on most questions")}, - - { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, - { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, - { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, - { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, - { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, - { oOptions, "options" , 2, N_("read options from file")}, - - { oDebug, "debug" ,4|16, "@"}, - { oDebugAll, "debug-all" ,0, "@"}, - { oDebugWait, "debug-wait" ,1, "@"}, - { oDebugNoChainValidation, "debug-no-chain-validation" ,0, "@"}, - { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, - { aDummy, "no-comment", 0, "@"}, - { aDummy, "completes-needed", 1, "@"}, - { aDummy, "marginals-needed", 1, "@"}, - { oMaxCertDepth, "max-cert-depth", 1, "@" }, - { aDummy, "trusted-key", 2, "@"}, - { oLoadExtension, "load-extension" ,2, - N_("|FILE|load extension module FILE")}, - { aDummy, "rfc1991", 0, "@"}, - { aDummy, "openpgp", 0, "@"}, - { aDummy, "s2k-mode", 1, "@"}, - { aDummy, "s2k-digest-algo",2, "@"}, - { aDummy, "s2k-cipher-algo",2, "@"}, - { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, - { oDigestAlgo, "digest-algo", 2 , - N_("|NAME|use message digest algorithm NAME")}, -#if 0 - { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")}, -#endif - { aDummy, "throw-keyid", 0, "@"}, - { aDummy, "notation-data", 2, "@"}, - - { 302, NULL, 0, N_( - "@\n(See the man page for a complete listing of all commands and options)\n" - )}, - - { 303, NULL, 0, N_("@\nExamples:\n\n" - " -se -r Bob [file] sign and encrypt for user Bob\n" - " --clearsign [file] make a clear text signature\n" - " --detach-sign [file] make a detached signature\n" - " --list-keys [names] show keys\n" - " --fingerprint [names] show fingerprints\n" ) }, - - /* hidden options */ - { oNoVerbose, "no-verbose", 0, "@"}, - - { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" }, - - - { oTrustDBName, "trustdb-name", 2, "@" }, - { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, - { oNoArmor, "no-armor", 0, "@"}, - { oNoArmor, "no-armour", 0, "@"}, - { oNoDefKeyring, "no-default-keyring", 0, "@" }, - { oNoGreeting, "no-greeting", 0, "@" }, - { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */ - { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ - { oAgentProgram, "agent-program", 2 , "@" }, - { oDisplay, "display", 2, "@" }, - { oTTYname, "ttyname", 2, "@" }, - { oTTYtype, "ttytype", 2, "@" }, - { oLCctype, "lc-ctype", 2, "@" }, - { oLCmessages, "lc-messages", 2, "@" }, - { oDirmngrProgram, "dirmngr-program", 2 , "@" }, - { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */ - - - { oNoBatch, "no-batch", 0, "@" }, - { oWithColons, "with-colons", 0, "@"}, - { oWithKeyData,"with-key-data", 0, "@"}, - { aListKeys, "list-key", 0, "@" }, /* alias */ - { aListSigs, "list-sig", 0, "@" }, /* alias */ - { aListSigs, "check-sig",0, "@" }, /* alias */ - { oSkipVerify, "skip-verify",0, "@" }, - { oCompressKeys, "compress-keys",0, "@"}, - { oCompressSigs, "compress-sigs",0, "@"}, - { oAlwaysTrust, "always-trust", 0, "@"}, - { oNoVersion, "no-version", 0, "@"}, - { oLockOnce, "lock-once", 0, "@" }, - { oLockMultiple, "lock-multiple", 0, "@" }, - { oLockNever, "lock-never", 0, "@" }, - { oLoggerFD, "logger-fd",1, "@" }, - { oWithFingerprint, "with-fingerprint", 0, "@" }, - { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, - { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, - { oHonorHttpProxy,"honor-http-proxy", 0, "@" }, - { oListOnly, "list-only", 0, "@"}, - { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, - { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, -{0} }; - - - -int gpgsm_errors_seen = 0; - -/* It is possible that we are currentlu running under setuid permissions */ -static int maybe_setuid = 1; - -/* Option --enable-special-filenames */ -static int allow_special_filenames; - - -static char *build_list (const char *text, - const char *(*mapf)(int), int (*chkf)(int)); -static void set_cmd (enum cmd_and_opt_values *ret_cmd, - enum cmd_and_opt_values new_cmd ); - -static void emergency_cleanup (void); -static int check_special_filename (const char *fname); -static int open_read (const char *filename); -static FILE *open_fwrite (const char *filename); - - -static int -our_pk_test_algo (int algo) -{ - return 1; -} - -static int -our_cipher_test_algo (int algo) -{ - return 1; -} - -static int -our_md_test_algo (int algo) -{ - return 1; -} - -static const char * -my_strusage( int level ) -{ - static char *digests, *pubkeys, *ciphers; - const char *p; - - switch (level) - { - case 11: p = "gpgsm (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: gpgsm [options] [files] (-h for help)"); - break; - case 41: - p = _("Syntax: gpgsm [options] [files]\n" - "sign, check, encrypt or decrypt using the S/MIME protocol\n" - "default operation depends on the input data\n"); - break; - - case 31: p = "\nHome: "; break; - case 32: p = opt.homedir; break; - case 33: p = _("\nSupported algorithms:\n"); break; - case 34: - if (!ciphers) - ciphers = build_list ("Cipher: ", gcry_cipher_algo_name, - our_cipher_test_algo ); - p = ciphers; - break; - case 35: - if (!pubkeys) - pubkeys = build_list ("Pubkey: ", gcry_pk_algo_name, - our_pk_test_algo ); - p = pubkeys; - break; - case 36: - if (!digests) - digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo ); - p = digests; - break; - - default: p = NULL; break; - } - return p; -} - - -static char * -build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int)) -{ - int i; - size_t n=strlen(text)+2; - char *list, *p; - - if (maybe_setuid) { - gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */ - } - - for (i=1; i < 110; i++ ) - if (!chkf(i)) - n += strlen(mapf(i)) + 2; - list = xmalloc (21 + n); - *list = 0; - for (p=NULL, i=1; i < 110; i++) - { - if (!chkf(i)) - { - if( !p ) - p = stpcpy (list, text ); - else - p = stpcpy (p, ", "); - p = stpcpy (p, mapf(i) ); - } - } - if (p) - p = stpcpy(p, "\n" ); - return list; -} - - -static void -i18n_init(void) -{ -#ifdef USE_SIMPLE_GETTEXT - set_gettext_file (PACKAGE); -#else -# ifdef ENABLE_NLS -# ifdef HAVE_LC_MESSAGES - setlocale (LC_TIME, ""); - setlocale (LC_MESSAGES, ""); -# else - setlocale (LC_ALL, "" ); -# endif - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); -# endif -#endif -} - - -static void -wrong_args (const char *text) -{ - fputs (_("usage: gpgsm [options] "), stderr); - fputs (text, stderr); - putc ('\n', stderr); - gpgsm_exit (2); -} - - -static void -set_debug(void) -{ - if (opt.debug & DBG_MPI_VALUE) - gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); - if (opt.debug & DBG_CRYPTO_VALUE ) - gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); -} - - -static void -set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd) -{ - enum cmd_and_opt_values cmd = *ret_cmd; - - if (!cmd || cmd == new_cmd) - cmd = new_cmd; - else if ( cmd == aSign && new_cmd == aEncr ) - cmd = aSignEncr; - else if ( cmd == aEncr && new_cmd == aSign ) - cmd = aSignEncr; - else if ( (cmd == aSign && new_cmd == aClearsign) - || (cmd == aClearsign && new_cmd == aSign) ) - cmd = aClearsign; - else - { - log_error(_("conflicting commands\n")); - gpgsm_exit(2); - } - - *ret_cmd = cmd; -} - - -int -main ( int argc, char **argv) -{ - ARGPARSE_ARGS pargs; - int orig_argc; - char **orig_argv; - const char *fname; - /* char *username;*/ - int may_coredump; - STRLIST sl, remusr= NULL, locusr=NULL; - STRLIST nrings=NULL; - int detached_sig = 0; - FILE *configfp = NULL; - char *configname = NULL; - unsigned configlineno; - int parse_debug = 0; - int default_config =1; - int default_keyring = 1; - char *logfile = NULL; - int greeting = 0; - int nogreeting = 0; - int debug_wait = 0; - int use_random_seed = 1; - int with_fpr = 0; - char *def_digest_string = NULL; - enum cmd_and_opt_values cmd = 0; - struct server_control_s ctrl; - CERTLIST recplist = NULL; - CERTLIST signerlist = NULL; - - /* trap_unaligned ();*/ - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - /* We don't need any locking in libgcrypt unless we use any kind of - threading. */ - gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING); - - /* Please note that we may running SUID(ROOT), so be very CAREFUL - when adding any stuff between here and the call to secmem_init() - somewhere after the option parsing */ - log_set_prefix ("gpgsm", 1); - /* check that the libraries are suitable. Do it here because the - option parse may need services of the library */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - if (!ksba_check_version (NEED_KSBA_VERSION) ) - { - log_fatal( _("libksba is too old (need %s, have %s)\n"), - NEED_KSBA_VERSION, ksba_check_version (NULL) ); - } - - gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); - - may_coredump = disable_core_dumps (); - - gnupg_init_signals (0, emergency_cleanup); - - create_dotlock (NULL); /* register locking cleanup */ - i18n_init(); - - opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/ -#ifdef __MINGW32__ - 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; - - /* first check whether we have a config file on the commandline */ - orig_argc = argc; - orig_argv = argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ - while (arg_parse( &pargs, opts)) - { - if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) - parse_debug++; - else if (pargs.r_opt == oOptions) - { /* yes there is one, so we do not try the default one but - read the config file when it is encountered at the - commandline */ - default_config = 0; - } - else if (pargs.r_opt == oNoOptions) - default_config = 0; /* --no-options */ - else if (pargs.r_opt == oHomedir) - opt.homedir = pargs.r.ret_str; - } - - - /* initialize the secure memory. */ - gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); - maybe_setuid = 0; - - /* - Now we are now working under our real uid - */ - - ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); - assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - - /* Setup a default control structure for command line mode */ - memset (&ctrl, 0, sizeof ctrl); - gpgsm_init_default_ctrl (&ctrl); - ctrl.no_server = 1; - ctrl.status_fd = -1; /* not status output */ - ctrl.autodetect_encoding = 1; - - /* set the default option file */ - if (default_config ) - configname = make_filename (opt.homedir, "gpgsm.conf", NULL); - /* cet the default policy file */ - opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL); - - argc = orig_argc; - argv = orig_argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags = 1; /* do not remove the args */ - - next_pass: - if (configname) { - configlineno = 0; - configfp = fopen (configname, "r"); - if (!configfp) - { - if (default_config) - { - if (parse_debug) - log_info (_("NOTE: no default option file `%s'\n"), configname); - } - else - { - log_error (_("option file `%s': %s\n"), configname, strerror(errno)); - gpgsm_exit(2); - } - xfree(configname); - configname = NULL; - } - if (parse_debug && configname) - log_info (_("reading options from `%s'\n"), configname); - default_config = 0; - } - - while (optfile_parse (configfp, configname, &configlineno, &pargs, opts)) - { - switch (pargs.r_opt) - { - case aServer: - opt.batch = 1; - set_cmd (&cmd, aServer); - break; - - case aCheckKeys: set_cmd (&cmd, aCheckKeys); break; - case aImport: set_cmd (&cmd, aImport); break; - case aSendKeys: set_cmd (&cmd, aSendKeys); break; - case aRecvKeys: set_cmd (&cmd, aRecvKeys); break; - case aExport: set_cmd (&cmd, aExport); break; - case aListKeys: set_cmd (&cmd, aListKeys); break; - case aListExternalKeys: set_cmd (&cmd, aListExternalKeys); break; - case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break; - case aListSigs: set_cmd (&cmd, aListSigs); break; - - case aLearnCard: set_cmd (&cmd, aLearnCard); break; - - case aDeleteKey: - set_cmd (&cmd, aDeleteKey); - /*greeting=1;*/ - break; - - case aDetachedSign: - detached_sig = 1; - set_cmd (&cmd, aSign ); - break; - - case aSym: set_cmd (&cmd, aSym); break; - case aDecrypt: set_cmd (&cmd, aDecrypt); break; - case aEncr: set_cmd (&cmd, aEncr); break; - case aSign: set_cmd (&cmd, aSign ); break; - case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break; - case aClearsign: set_cmd (&cmd, aClearsign); break; - case aVerify: set_cmd (&cmd, aVerify); break; - - - /* output encoding selection */ - case oArmor: - ctrl.create_pem = 1; - break; - case oBase64: - ctrl.create_pem = 0; - ctrl.create_base64 = 1; - break; - case oNoArmor: - ctrl.create_pem = 0; - ctrl.create_base64 = 0; - break; - - /* Input encoding selection */ - case oAssumeArmor: - ctrl.autodetect_encoding = 0; - ctrl.is_pem = 1; - ctrl.is_base64 = 0; - break; - case oAssumeBase64: - ctrl.autodetect_encoding = 0; - ctrl.is_pem = 0; - ctrl.is_base64 = 1; - break; - case oAssumeBinary: - ctrl.autodetect_encoding = 0; - ctrl.is_pem = 0; - ctrl.is_base64 = 0; - break; - - case oDisableCRLChecks: - opt.no_crl_check = 1; - break; - case oEnableCRLChecks: - opt.no_crl_check = 0; - break; - - case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break; - - case oPolicyFile: - xfree (opt.policy_file); - if (*pargs.r.ret_str) - opt.policy_file = xstrdup (pargs.r.ret_str); - else - opt.policy_file = NULL; - break; - - case oDisablePolicyChecks: - opt.no_policy_check = 1; - break; - case oEnablePolicyChecks: - opt.no_policy_check = 0; - break; - - case oAutoIssuerKeyRetrieve: - opt.auto_issuer_key_retrieve = 1; - break; - - case oOutput: opt.outfile = pargs.r.ret_str; break; - - - case oQuiet: opt.quiet = 1; break; - case oNoTTY: /* fixme:tty_no_terminal(1);*/ break; - case oDryRun: opt.dry_run = 1; break; - - case oVerbose: - opt.verbose++; - gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); - break; - case oNoVerbose: - opt.verbose = 0; - gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); - break; - - case oLogFile: logfile = pargs.r.ret_str; break; - - case oBatch: - opt.batch = 1; - greeting = 0; - break; - case oNoBatch: opt.batch = 0; break; - - case oAnswerYes: opt.answer_yes = 1; break; - case oAnswerNo: opt.answer_no = 1; break; - - case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break; - - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - case oDebugWait: debug_wait = pargs.r.ret_int; break; - case oDebugNoChainValidation: opt.no_chain_validation = 1; break; - - case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; - case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; - case oWithFingerprint: - with_fpr=1; /*fall thru*/ - case oFingerprint: - opt.fingerprint++; - break; - - case oOptions: - /* config files may not be nested (silently ignore them) */ - if (!configfp) - { - xfree(configname); - configname = xstrdup (pargs.r.ret_str); - goto next_pass; - } - break; - case oNoOptions: break; /* no-options */ - case oHomedir: opt.homedir = pargs.r.ret_str; break; - case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; - case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break; - case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break; - case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break; - case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break; - case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break; - case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; - - case oFakedSystemTime: - gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0); - break; - - case oNoDefKeyring: default_keyring = 0; break; - case oNoGreeting: nogreeting = 1; break; - - case oDefaultKey: - /* fixme:opt.def_secret_key = pargs.r.ret_str;*/ - break; - case oDefRecipient: - if (*pargs.r.ret_str) - opt.def_recipient = xstrdup (pargs.r.ret_str); - break; - case oDefRecipientSelf: - xfree (opt.def_recipient); - opt.def_recipient = NULL; - opt.def_recipient_self = 1; - break; - case oNoDefRecipient: - xfree (opt.def_recipient); - opt.def_recipient = NULL; - opt.def_recipient_self = 0; - break; - - case oWithKeyData: opt.with_key_data=1; /* fall thru */ - case oWithColons: ctrl.with_colons = 1; break; - - case oSkipVerify: opt.skip_verify=1; break; - - case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break; - case oEncryptTo: /* store the recipient in the second list */ - sl = add_to_strlist (&remusr, pargs.r.ret_str); - sl->flags = 1; - break; - - case oRecipient: /* store the recipient */ - add_to_strlist ( &remusr, pargs.r.ret_str); - break; - - case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break; - case oTextmode: /*fixme:opt.textmode=1;*/ break; - - case oUser: /* store the local users, the first one is the default */ - if (!opt.local_user) - opt.local_user = pargs.r.ret_str; - add_to_strlist (&locusr, pargs.r.ret_str); - break; - - case oNoSecmemWarn: - gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); - break; - - case oCipherAlgo: - opt.def_cipher_algoid = pargs.r.ret_str; - break; - - case oDisableCipherAlgo: - { - int algo = gcry_cipher_map_name (pargs.r.ret_str); - gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); - } - break; - case oDisablePubkeyAlgo: - { - int algo = gcry_pk_map_name (pargs.r.ret_str); - gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo ); - } - break; - - case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; - case oNoRandomSeedFile: use_random_seed = 0; break; - - case oEnableSpecialFilenames: allow_special_filenames =1; break; - - - case aDummy: - break; - default: - pargs.err = configfp? 1:2; - break; - } - } - - if (configfp) - { - fclose (configfp); - configfp = NULL; - xfree (configname); - configname = NULL; - goto next_pass; - } - - xfree (configname); - configname = NULL; - - if (log_get_errorcount(0)) - gpgsm_exit(2); - - if (nogreeting) - greeting = 0; - - if (greeting) - { - fprintf(stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - fprintf(stderr, "%s\n", strusage(15) ); - } -# ifdef IS_DEVELOPMENT_VERSION - if (!opt.batch) - { - log_info ("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); - log_info ("It is only intended for test purposes and should NOT be\n"); - log_info ("used in a production environment or with production keys!\n"); - } -# endif - - if (may_coredump && !opt.quiet) - log_info (_("WARNING: program may create a core file!\n")); - - if (logfile && cmd == aServer) - { - log_set_file (logfile); - log_set_prefix (NULL, 1|2|4); - } - - if (gnupg_faked_time_p ()) - { - log_info (_("WARNING: running with faked system time: ")); - gpgsm_dump_time (gnupg_get_time ()); - log_printf ("\n"); - } - -/*FIXME if (opt.batch) */ -/* tty_batchmode (1); */ - - gcry_control (GCRYCTL_RESUME_SECMEM_WARN); - - set_debug (); - - /* FIXME: should set filenames of libgcrypt explicitly - * gpg_opt_homedir = opt.homedir; */ - - /* must do this after dropping setuid, because the mapping functions - may try to load an module and we may have disabled an algorithm */ - if ( !gcry_cipher_map_name (opt.def_cipher_algoid) - || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid)) - log_error (_("selected cipher algorithm is invalid\n")); - - if (def_digest_string) - { - opt.def_digest_algo = gcry_md_map_name (def_digest_string); - xfree (def_digest_string); - def_digest_string = NULL; - if (our_md_test_algo(opt.def_digest_algo) ) - log_error (_("selected digest algorithm is invalid\n")); - } - - if (log_get_errorcount(0)) - gpgsm_exit(2); - - /* set the random seed file */ - if (use_random_seed) { - char *p = make_filename (opt.homedir, "random_seed", NULL); -#if 0 -#warning set_random_seed_file not yet available in Libgcrypt - set_random_seed_file(p); -#endif - xfree(p); - } - - - if (!cmd && opt.fingerprint && !with_fpr) - set_cmd (&cmd, aListKeys); - - if (!nrings && default_keyring) /* add default keybox */ - keydb_add_resource ("pubring.kbx", 0, 0); - for (sl = nrings; sl; sl = sl->next) - keydb_add_resource (sl->d, 0, 0); - FREE_STRLIST(nrings); - - - for (sl = locusr; sl; sl = sl->next) - { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist); - if (rc) - { - log_error (_("can't sign using `%s': %s\n"), - sl->d, gnupg_strerror (rc)); - gpgsm_status2 (&ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - rc == GNUPG_No_Secret_Key? "9": - "0", - sl->d, NULL); - } - } - for (sl = remusr; sl; sl = sl->next) - { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist); - if (rc) - { - log_error (_("can't encrypt to `%s': %s\n"), - sl->d, gnupg_strerror (rc)); - gpgsm_status2 (&ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - "0", - sl->d, NULL); - } - } - if (log_get_errorcount(0)) - gpgsm_exit(1); /* must stop for invalid recipients */ - - - - fname = argc? *argv : NULL; - - switch (cmd) - { - case aServer: - if (debug_wait) - { - log_debug ("waiting for debugger - my pid is %u .....\n", - (unsigned int)getpid()); - sleep (debug_wait); - log_debug ("... okay\n"); - } - gpgsm_server (); - break; - - case aEncr: /* encrypt the given file */ - if (!argc) - gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */ - else if (argc == 1) - gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */ - else - wrong_args (_("--encrypt [datafile]")); - break; - - case aSign: /* sign the given file */ - /* FIXME: We don't handle --output yet. We should also allow - to concatenate multiple files for signing because that is - what gpg does.*/ - if (!argc) - gpgsm_sign (&ctrl, signerlist, - 0, detached_sig, stdout); /* create from stdin */ - else if (argc == 1) - gpgsm_sign (&ctrl, signerlist, - open_read (*argv), detached_sig, stdout); /* from file */ - else - wrong_args (_("--sign [datafile]")); - break; - - case aSignEncr: /* sign and encrypt the given file */ - log_error ("this command has not yet been implemented\n"); - break; - - case aClearsign: /* make a clearsig */ - log_error ("this command has not yet been implemented\n"); - break; - - case aVerify: - { - FILE *fp = NULL; - - if (argc == 2 && opt.outfile) - log_info ("option --output ignored for a detached signature\n"); - else if (opt.outfile) - fp = open_fwrite (opt.outfile); - - if (!argc) - gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */ - else if (argc == 1) - gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */ - else if (argc == 2) /* detached signature (sig, detached) */ - gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL); - else - wrong_args (_("--verify [signature [detached_data]]")); - - if (fp && fp != stdout) - fclose (fp); - } - break; - - case aVerifyFiles: - log_error ("this command has not yet been implemented\n"); - break; - - case aDecrypt: - if (!argc) - gpgsm_decrypt (&ctrl, 0, stdout); /* from stdin */ - else if (argc == 1) - gpgsm_decrypt (&ctrl, open_read (*argv), stdout); /* from file */ - else - wrong_args (_("--decrypt [filename]")); - break; - - case aDeleteKey: - for (sl=NULL; argc; argc--, argv++) - add_to_strlist (&sl, *argv); - gpgsm_delete (&ctrl, sl); - free_strlist(sl); - break; - - case aListSigs: - ctrl.with_chain = 1; - case aListKeys: - for (sl=NULL; argc; argc--, argv++) - add_to_strlist (&sl, *argv); - gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<6))); - free_strlist(sl); - break; - - case aListExternalKeys: - for (sl=NULL; argc; argc--, argv++) - add_to_strlist (&sl, *argv); - gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<7))); - free_strlist(sl); - break; - - case aListSecretKeys: - for (sl=NULL; argc; argc--, argv++) - add_to_strlist (&sl, *argv); - gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6))); - free_strlist(sl); - break; - - case aKeygen: /* generate a key */ - log_error ("this function is not yet available from the commandline\n"); - break; - - case aImport: - gpgsm_import_files (&ctrl, argc, argv, open_read); - break; - - case aExport: - for (sl=NULL; argc; argc--, argv++) - add_to_strlist (&sl, *argv); - gpgsm_export (&ctrl, sl, stdout); - free_strlist(sl); - break; - - - case aSendKeys: - case aRecvKeys: - log_error ("this command has not yet been implemented\n"); - break; - - - case aLearnCard: - if (argc) - wrong_args ("--learn-card"); - else - { - int rc = gpgsm_agent_learn (); - if (rc) - log_error ("error learning card: %s\n", gnupg_strerror (rc)); - } - break; - - - default: - log_error ("invalid command (there is no implicit command)\n"); - break; - } - - /* cleanup */ - gpgsm_release_certlist (recplist); - gpgsm_release_certlist (signerlist); - FREE_STRLIST(remusr); - FREE_STRLIST(locusr); - gpgsm_exit(0); - return 8; /*NEVER REACHED*/ -} - -/* Note: This function is used by signal handlers!. */ -static void -emergency_cleanup (void) -{ - gcry_control (GCRYCTL_TERM_SECMEM ); -} - - -void -gpgsm_exit (int rc) -{ - #if 0 -#warning no update_random_seed_file - update_random_seed_file(); - #endif -#if 0 - /* at this time a bit annoying */ - if (opt.debug & DBG_MEMSTAT_VALUE) - { - gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); - gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); - } - if (opt.debug) - gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); -#endif - emergency_cleanup (); - rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0; - exit (rc); -} - - -void -gpgsm_init_default_ctrl (struct server_control_s *ctrl) -{ - ctrl->include_certs = 1; /* only include the signer's cert */ -} - - - -/* Check whether the filename has the form "-&nnnn", where n is a - non-zero number. Returns this number or -1 if it is not the case. */ -static int -check_special_filename (const char *fname) -{ - if (allow_special_filenames - && fname && *fname == '-' && fname[1] == '&' ) { - int i; - - fname += 2; - for (i=0; isdigit (fname[i]); i++ ) - ; - if ( !fname[i] ) - return atoi (fname); - } - return -1; -} - - - -/* Open the FILENAME for read and return the filedescriptor. Stop - with an error message in case of problems. "-" denotes stdin and - if special filenames are allowed the given fd is opened instead. */ -static int -open_read (const char *filename) -{ - int fd; - - if (filename[0] == '-' && !filename[1]) - return 0; /* stdin */ - fd = check_special_filename (filename); - if (fd != -1) - return fd; - fd = open (filename, O_RDONLY); - if (fd == -1) - { - log_error (_("can't open `%s': %s\n"), filename, strerror (errno)); - gpgsm_exit (2); - } - return fd; -} - -/* Open FILENAME for fwrite and return the stream. Stop with an error - message in case of problems. "-" denotes stdout and if special - filenames are allowed the given fd is opened instead. Caller must - close the returned stream unless it is stdout. */ -static FILE * -open_fwrite (const char *filename) -{ - int fd; - FILE *fp; - - if (filename[0] == '-' && !filename[1]) - return stdout; - - fd = check_special_filename (filename); - if (fd != -1) - { - fp = fdopen (dup (fd), "wb"); - if (!fp) - { - log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); - gpgsm_exit (2); - } - return fp; - } - fp = fopen (filename, "wb"); - if (!fp) - { - log_error (_("can't open `%s': %s\n"), filename, strerror (errno)); - gpgsm_exit (2); - } - return fp; -} diff --git a/sm/gpgsm.h b/sm/gpgsm.h deleted file mode 100644 index 50590206e..000000000 --- a/sm/gpgsm.h +++ /dev/null @@ -1,261 +0,0 @@ -/* gpgsm.h - Global definitions for GpgSM - * 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 GPGSM_H -#define GPGSM_H - -#include -#include "../common/util.h" -#include "../common/errors.h" - -#define MAX_DIGEST_LEN 24 - -/* A large struct name "opt" to keep global flags */ -struct { - unsigned int debug; /* debug flags (DBG_foo_VALUE) */ - int verbose; /* verbosity level */ - int quiet; /* be as quiet as possible */ - int batch; /* run in batch mode, i.e w/o any user interaction */ - int answer_yes; /* assume yes on most questions */ - int answer_no; /* assume no on most questions */ - int dry_run; /* don't change any persistent data */ - - const char *homedir; /* configuration directory name */ - const char *agent_program; - char *display; - char *ttyname; - char *ttytype; - char *lc_ctype; - char *lc_messages; - - const char *dirmngr_program; - char *outfile; /* name of output file */ - - int with_key_data;/* include raw key in the column delimted output */ - - int fingerprint; /* list fingerprints in all key listings */ - - int armor; /* force base64 armoring (see also ctrl.with_base64) */ - int no_armor; /* don't try to figure out whether data is base64 armored*/ - - const char *def_cipher_algoid; /* cipher algorithm to use if - nothing else is specified */ - - int def_digest_algo; /* Ditto for hash algorithm */ - int def_compress_algo; /* Ditto for compress algorithm */ - - char *def_recipient; /* userID of the default recipient */ - int def_recipient_self; /* The default recipient is the default key */ - - char *local_user; /* NULL or argument to -u */ - - int always_trust; /* Trust the given keys even if there is no - valid certification chain */ - int skip_verify; /* do not check signatures on data */ - - int lock_once; /* Keep lock once they are set */ - - int ignore_time_conflict; /* Ignore certain time conflicts */ - - int no_crl_check; /* Don't do a CRL check */ - - char *policy_file; /* full pathname of policy file */ - int no_policy_check; /* ignore certificate policies */ - int no_chain_validation; /* Bypass all cert chain validity tests */ - - int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ -} opt; - - -#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */ -#define DBG_MPI_VALUE 2 /* debug mpi details */ -#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ -#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ -#define DBG_CACHE_VALUE 64 /* debug the caching */ -#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ -#define DBG_HASHING_VALUE 512 /* debug hashing operations */ -#define DBG_ASSUAN_VALUE 1024 /* debug assuan communication */ - -#define DBG_X509 (opt.debug & DBG_X509_VALUE) -#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) -#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) -#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) -#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) -#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) - -struct server_local_s; - -/* Note that the default values for this are set by - gpgsm_init_default_ctrl() */ -struct server_control_s { - int no_server; /* we are not running under server control */ - int status_fd; /* only for non-server mode */ - struct server_local_s *server_local; - int with_colons; /* use column delimited output format */ - int with_chain; /* include the certifying certs in a listing */ - - int autodetect_encoding; /* try to detect the input encoding */ - int is_pem; /* Is in PEM format */ - int is_base64; /* is in plain base-64 format */ - - int create_base64; /* Create base64 encoded output */ - int create_pem; /* create PEM output */ - const char *pem_name; /* PEM name to use */ - - int include_certs; /* -1 to send all certificates in the chain - along with a signature or the number of - certificates up the chain (0 = none, 1 = only - signer) */ -}; -typedef struct server_control_s *CTRL; - -/* data structure used in base64.c */ -typedef struct base64_context_s *Base64Context; - - -struct certlist_s { - struct certlist_s *next; - KsbaCert cert; -}; -typedef struct certlist_s *CERTLIST; - -/*-- gpgsm.c --*/ -void gpgsm_exit (int rc); -void gpgsm_init_default_ctrl (struct server_control_s *ctrl); - -/*-- server.c --*/ -void gpgsm_server (void); -void gpgsm_status (CTRL ctrl, int no, const char *text); -void gpgsm_status2 (CTRL ctrl, int no, ...); - -/*-- fingerprint --*/ -char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len); -char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo); -char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo); -unsigned long gpgsm_get_short_fingerprint (KsbaCert cert); -char *gpgsm_get_keygrip (KsbaCert cert, char *array); -char *gpgsm_get_keygrip_hexstring (KsbaCert cert); -char *gpgsm_get_certid (KsbaCert cert); - - -/*-- base64.c --*/ -int gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaReader *r_reader); -void gpgsm_destroy_reader (Base64Context ctx); -int gpgsm_create_writer (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaWriter *r_writer); -int gpgsm_finish_writer (Base64Context ctx); -void gpgsm_destroy_writer (Base64Context ctx); - - -/*-- certdump.c --*/ -void gpgsm_print_serial (FILE *fp, KsbaConstSexp p); -void gpgsm_print_time (FILE *fp, time_t t); -void gpgsm_print_name (FILE *fp, const char *string); - -void gpgsm_dump_cert (const char *text, KsbaCert cert); -void gpgsm_dump_serial (KsbaConstSexp p); -void gpgsm_dump_time (time_t t); -void gpgsm_dump_string (const char *string); - - - -/*-- certcheck.c --*/ -int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert); -int gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, - GCRY_MD_HD md, int hash_algo); -/* fixme: move create functions to another file */ -int gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo, - char **r_sigval); - - -/*-- certchain.c --*/ -int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next); -int gpgsm_is_root_cert (KsbaCert cert); -int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime); -int gpgsm_basic_cert_check (KsbaCert cert); - -/*-- certlist.c --*/ -int gpgsm_cert_use_sign_p (KsbaCert cert); -int gpgsm_cert_use_encrypt_p (KsbaCert cert); -int gpgsm_cert_use_verify_p (KsbaCert cert); -int gpgsm_cert_use_decrypt_p (KsbaCert cert); -int gpgsm_cert_use_cert_p (KsbaCert cert); -int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, - CERTLIST *listaddr); -void gpgsm_release_certlist (CERTLIST list); -int gpgsm_find_cert (const char *name, KsbaCert *r_cert); - -/*-- keylist.c --*/ -void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode); - -/*-- import.c --*/ -int gpgsm_import (CTRL ctrl, int in_fd); -int gpgsm_import_files (CTRL ctrl, int nfiles, char **files, - int (*of)(const char *fname)); - -/*-- export.c --*/ -void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp); - -/*-- delete.c --*/ -int gpgsm_delete (CTRL ctrl, STRLIST names); - -/*-- verify.c --*/ -int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp); - -/*-- sign.c --*/ -int gpgsm_get_default_cert (KsbaCert *r_cert); -int gpgsm_sign (CTRL ctrl, CERTLIST signerlist, - int data_fd, int detached, FILE *out_fp); - -/*-- encrypt.c --*/ -int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp); - -/*-- decrypt.c --*/ -int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp); - -/*-- certreqgen.c --*/ -int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp); - -/*-- call-agent.c --*/ -int gpgsm_agent_pksign (const char *keygrip, - unsigned char *digest, - size_t digestlen, - int digestalgo, - char **r_buf, size_t *r_buflen); -int gpgsm_agent_pkdecrypt (const char *keygrip, - KsbaConstSexp ciphertext, - char **r_buf, size_t *r_buflen); -int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey); -int gpgsm_agent_istrusted (KsbaCert cert); -int gpgsm_agent_havekey (const char *hexkeygrip); -int gpgsm_agent_marktrusted (KsbaCert cert); -int gpgsm_agent_learn (void); - -/*-- call-dirmngr.c --*/ -int gpgsm_dirmngr_isvalid (KsbaCert cert); -int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, - void (*cb)(void*, KsbaCert), void *cb_value); - - - - - -#endif /*GPGSM_H*/ diff --git a/sm/import.c b/sm/import.c deleted file mode 100644 index 2fc6b1a79..000000000 --- a/sm/import.c +++ /dev/null @@ -1,349 +0,0 @@ -/* import.c - Import certificates - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct stats_s { - unsigned long count; - unsigned long imported; - unsigned long unchanged; - unsigned long not_imported; -}; - - - -static void -print_imported_status (CTRL ctrl, KsbaCert cert) -{ - char *fpr; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL); - xfree (fpr); -} - - -/* Print an IMPORT_PROBLEM status. REASON is one of: - 0 := "No specific reason given". - 1 := "Invalid Certificate". - 2 := "Issuer Certificate missing". - 3 := "Certificate Chain too long". - 4 := "Error storing certificate". -*/ -static void -print_import_problem (CTRL ctrl, KsbaCert cert, int reason) -{ - char *fpr = NULL; - char buf[25]; - int i; - - sprintf (buf, "%d", reason); - if (cert) - { - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - /* detetect an error (all high) value */ - for (i=0; fpr[i] == 'F'; i++) - ; - if (!fpr[i]) - { - xfree (fpr); - fpr = NULL; - } - } - gpgsm_status2 (ctrl, STATUS_IMPORT_PROBLEM, buf, fpr, NULL); - xfree (fpr); -} - - -void -print_imported_summary (CTRL ctrl, struct stats_s *stats) -{ - char buf[14*25]; - - if (!opt.quiet) - { - log_info (_("total number processed: %lu\n"), stats->count); - if (stats->imported) - { - log_info (_(" imported: %lu"), stats->imported ); - log_printf ("\n"); - } - if (stats->unchanged) - log_info (_(" unchanged: %lu\n"), stats->unchanged); - if (stats->not_imported) - log_info (_(" not imported: %lu\n"), stats->not_imported); - } - - sprintf (buf, "%lu 0 %lu 0 %lu 0 0 0 0 0 0 0 0 %lu", - stats->count, - stats->imported, - stats->unchanged, - stats->not_imported - ); - gpgsm_status (ctrl, STATUS_IMPORT_RES, buf); -} - - - -static void -check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth) -{ - int rc; - - stats->count++; - if ( depth >= 50 ) - { - log_error (_("certificate chain too long\n")); - stats->not_imported++; - print_import_problem (ctrl, cert, 3); - return; - } - - rc = gpgsm_basic_cert_check (cert); - if (!rc) - { - int existed; - - if (!keydb_store_cert (cert, 0, &existed)) - { - KsbaCert next = NULL; - - if (!existed) - { - print_imported_status (ctrl, cert); - stats->imported++; - } - else - stats->unchanged++; - - if (opt.verbose > 1 && existed) - { - if (depth) - log_info ("issuer certificate already in DB\n"); - else - log_info ("certificate already in DB\n"); - } - else if (opt.verbose && !existed) - { - if (depth) - log_info ("issuer certificate imported\n"); - else - log_info ("certificate imported\n"); - } - /* Now lets walk up the chain and import all certificates up - the chain.*/ - else if (!gpgsm_walk_cert_chain (cert, &next)) - { - check_and_store (ctrl, stats, next, depth+1); - ksba_cert_release (next); - } - } - else - { - log_error (_("error storing certificate\n")); - stats->not_imported++; - print_import_problem (ctrl, cert, 4); - } - } - else - { - log_error (_("basic certificate checks failed - not imported\n")); - stats->not_imported++; - print_import_problem (ctrl, cert, - rc == GNUPG_Missing_Certificate? 2 : - rc == GNUPG_Bad_Certificate? 1 : 0); - } -} - - - - -static int -import_one (CTRL ctrl, struct stats_s *stats, int in_fd) -{ - int rc; - Base64Context b64reader = NULL; - KsbaReader reader; - KsbaCert cert = NULL; - KsbaCMS cms = NULL; - FILE *fp = NULL; - KsbaContentType ct; - - fp = fdopen ( dup (in_fd), "rb"); - if (!fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gnupg_strerror (rc)); - goto leave; - } - - ct = ksba_cms_identify (reader); - if (ct == KSBA_CT_SIGNED_DATA) - { /* This is probably a signed-only message - import the certs */ - KsbaStopReason stopreason; - int i; - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - rc = ksba_cms_set_reader_writer (cms, reader, NULL); - if (rc) - { - log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (rc)); - rc = map_ksba_err (rc); - goto leave; - } - - - do - { - rc = ksba_cms_parse (cms, &stopreason); - if (rc) - { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (rc)); - rc = map_ksba_err (rc); - goto leave; - } - - if (stopreason == KSBA_SR_BEGIN_DATA) - log_info ("not a certs-only message\n"); - } - while (stopreason != KSBA_SR_READY); - - for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) - { - check_and_store (ctrl, stats, cert, 0); - ksba_cert_release (cert); - cert = NULL; - } - if (!i) - log_error ("no certificate found\n"); - } - else if (ct == KSBA_CT_NONE) - { /* Failed to identify this message - assume a certificate */ - - cert = ksba_cert_new (); - if (!cert) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - rc = ksba_cert_read_der (cert, reader); - if (rc) - { - rc = map_ksba_err (rc); - goto leave; - } - - check_and_store (ctrl, stats, cert, 0); - } - else - { - log_error ("can't extract certificates from input\n"); - rc = GNUPG_No_Data; - } - - leave: - ksba_cms_release (cms); - ksba_cert_release (cert); - gpgsm_destroy_reader (b64reader); - if (fp) - fclose (fp); - return rc; -} - - -int -gpgsm_import (CTRL ctrl, int in_fd) -{ - int rc; - struct stats_s stats; - - memset (&stats, 0, sizeof stats); - rc = import_one (ctrl, &stats, in_fd); - print_imported_summary (ctrl, &stats); - /* If we never printed an error message do it now so that a command - line invocation will return with an error (log_error keeps a - global errorcount) */ - if (rc && !log_get_errorcount (0)) - log_error (_("error importing certificate: %s\n"), gnupg_strerror (rc)); - return rc; -} - - -int -gpgsm_import_files (CTRL ctrl, int nfiles, char **files, - int (*of)(const char *fname)) -{ - int rc = 0; - struct stats_s stats; - - memset (&stats, 0, sizeof stats); - - if (!nfiles) - rc = import_one (ctrl, &stats, 0); - else - { - for (; nfiles && !rc ; nfiles--, files++) - { - int fd = of (*files); - rc = import_one (ctrl, &stats, fd); - close (fd); - if (rc == -1) - rc = 0; - } - } - print_imported_summary (ctrl, &stats); - /* If we never printed an error message do it now so that a command - line invocation will return with an error (log_error keeps a - global errorcount) */ - if (rc && !log_get_errorcount (0)) - log_error (_("error importing certificate: %s\n"), gnupg_strerror (rc)); - return rc; -} - - diff --git a/sm/keydb.c b/sm/keydb.c deleted file mode 100644 index 5b5722d3e..000000000 --- a/sm/keydb.c +++ /dev/null @@ -1,1282 +0,0 @@ -/* keydb.c - key database dispatcher - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gpgsm.h" -#include "../kbx/keybox.h" -#include "keydb.h" -#include "i18n.h" - -#define DIRSEP_C '/' - -static int active_handles; - -typedef enum { - KEYDB_RESOURCE_TYPE_NONE = 0, - KEYDB_RESOURCE_TYPE_KEYBOX -} KeydbResourceType; -#define MAX_KEYDB_RESOURCES 20 - -struct resource_item { - KeydbResourceType type; - union { - KEYBOX_HANDLE kr; - } u; - void *token; - int secret; - DOTLOCK lockhandle; -}; - -static struct resource_item all_resources[MAX_KEYDB_RESOURCES]; -static int used_resources; - -struct keydb_handle { - int locked; - int found; - int current; - int is_ephemeral; - 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 keybox file). - * The first keybox which is added by this function is - * created if it does not exist. - * Note: this function may be called before secure memory is - * available. - */ -int -keydb_add_resource (const char *url, int force, int secret) -{ - static int any_secret, any_public; - const char *resname = url; - char *filename = NULL; - int rc = 0; - FILE *fp; - KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; - const char *created_fname = NULL; - - /* Do we have an URL? - gnupg-kbx:filename := this is a plain keybox - filename := See what is is, but create as plain keybox. - */ - if (strlen (resname) > 10) - { - if (!strncmp (resname, "gnupg-kbx:", 10) ) - { - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - resname += 10; - } -#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) - else if (strchr (resname, ':')) - { - log_error ("invalid key resource URL `%s'\n", url ); - rc = GNUPG_General_Error; - 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 *fp2 = fopen( filename, "rb" ); - - if (fp2) { - u32 magic; - - /* FIXME: check for the keybox magic */ - if (fread( &magic, 4, 1, fp2) == 1 ) - { - if (magic == 0x13579ace || magic == 0xce9a5713) - ; /* GDBM magic - no more support */ - else - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - } - else /* maybe empty: assume ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - fclose (fp2); - } - else /* no file yet: create ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - } - - switch (rt) - { - case KEYDB_RESOURCE_TYPE_NONE: - log_error ("unknown type of key resource `%s'\n", url ); - rc = GNUPG_General_Error; - goto leave; - - case KEYDB_RESOURCE_TYPE_KEYBOX: - fp = fopen (filename, "rb"); - if (!fp && !force) - { - rc = GNUPG_File_Open_Error; - goto leave; - } - - if (!fp) - { /* no file */ -#if 0 /* no autocreate of the homedirectory yet */ - { - char *last_slash_in_filename; - - 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 in this case the process will be - terminated, so that on the next invocation can - read the options file in on startup */ - try_make_homedir (filename); - rc = GNUPG_File_Open_Error; - *last_slash_in_filename = DIRSEP_C; - goto leave; - } - *last_slash_in_filename = DIRSEP_C; - } -#endif - fp = fopen (filename, "w"); - if (!fp) - { - log_error (_("error creating keybox `%s': %s\n"), - filename, strerror(errno)); - rc = GNUPG_File_Create_Error; - goto leave; - } - - if (!opt.quiet) - log_info (_("keybox `%s' created\n"), filename); - created_fname = filename; - } - fclose (fp); - fp = NULL; - /* now register the file */ - { - - void *token = keybox_register_file (filename, secret); - if (!token) - ; /* already registered - ignore it */ - else if (used_resources >= MAX_KEYDB_RESOURCES) - rc = GNUPG_Resource_Limit; - else - { - 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; - - all_resources[used_resources].lockhandle - = create_dotlock (filename); - if (!all_resources[used_resources].lockhandle) - log_fatal ( _("can't create lock for `%s'\n"), filename); - - used_resources++; - } - } - break; - default: - log_error ("resource type of `%s' not supported\n", url); - rc = GNUPG_Not_Supported; - goto leave; - } - - /* fixme: check directory permissions and print a warning */ - - leave: - if (rc) - log_error ("keyblock resource `%s': %s\n", filename, gnupg_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_KEYBOX: - 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].lockhandle = all_resources[i].lockhandle; - hd->active[j].u.kr = keybox_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_KEYBOX: - keybox_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_KEYBOX: - s = keybox_get_resource_name (hd->active[idx].u.kr); - break; - } - - return s? s: ""; -} - -/* Switch the handle into ephemeral mode and return the orginal value. */ -int -keydb_set_ephemeral (KEYDB_HANDLE hd, int yes) -{ - int i; - - if (!hd) - return 0; - - yes = !!yes; - if (hd->is_ephemeral != yes) - { - for (i=0; i < hd->used; i++) - { - switch (hd->active[i].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_set_ephemeral (hd->active[i].u.kr, yes); - break; - } - } - } - - i = hd->is_ephemeral; - hd->is_ephemeral = yes; - return i; -} - - - -static int -lock_all (KEYDB_HANDLE hd) -{ - int i, rc = 0; - - /* Fixme: This locking scheme may lead to deadlock if the resources - are not added in the same sequence by all processes. We are - cuurently only allowing one resource so it is not a problem. */ - for (i=0; i < hd->used; i++) - { - switch (hd->active[i].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - if (hd->active[i].lockhandle) - rc = make_dotlock (hd->active[i].lockhandle, -1); - break; - } - if (rc) - 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_KEYBOX: - if (hd->active[i].lockhandle) - release_dotlock (hd->active[i].lockhandle); - 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_KEYBOX: - if (hd->active[i].lockhandle) - release_dotlock (hd->active[i].lockhandle); - break; - } - } - hd->locked = 0; -} - - -#if 0 -/* - * Return the last found keybox. 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 G10ERR_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 = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_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 G10ERR_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 = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_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 G10ERR_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 G10ERR_GENERAL; - - rc = lock_all (hd); - if (rc) - return rc; - - switch (hd->active[idx].type) { - case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb); - break; - } - - unlock_all (hd); - return rc; -} - -#endif /*disabled code*/ - - - -/* - Return the last found keybox. 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_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) -{ - int rc = 0; - - if (!hd) - return GNUPG_Invalid_Value; - - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ - - switch (hd->active[hd->found].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - rc = GNUPG_General_Error; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert); - break; - } - - return rc; -} - -/* - * Insert a new Certificate into one of the resources. - */ -int -keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) -{ - int rc = -1; - int idx; - char digest[20]; - - if (!hd) - return GNUPG_Invalid_Value; - - 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 GNUPG_General_Error; - - rc = lock_all (hd); - if (rc) - return rc; - - gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ - - switch (hd->active[idx].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - rc = GNUPG_General_Error; - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest); - break; - } - - unlock_all (hd); - return rc; -} - - - -/* update the current keyblock with KB */ -int -keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert) -{ - int rc = 0; - char digest[20]; - - if (!hd) - return GNUPG_Invalid_Value; - - 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; - - gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ - - switch (hd->active[hd->found].type) - { - case KEYDB_RESOURCE_TYPE_NONE: - rc = GNUPG_General_Error; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest); - break; - } - - unlock_all (hd); - return rc; -} - - -/* - * The current keyblock or cert will be deleted. - */ -int -keydb_delete (KEYDB_HANDLE hd) -{ - int rc = -1; - - if (!hd) - return GNUPG_Invalid_Value; - - 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 = GNUPG_General_Error; - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_delete (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 GNUPG_Invalid_Value; - - 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_KEYBOX: - if (keybox_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; - - 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_KEYBOX: -/* rc = keybox_rebuild_cache (all_resources[i].token); */ -/* if (rc) */ -/* log_error (_("failed to rebuild keybox cache: %s\n"), */ -/* g10_errstr (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 GNUPG_Invalid_Value; - - 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_KEYBOX: - rc = keybox_search_reset (hd->active[i].u.kr); - break; - } - } - return rc; /* fixme: we need to map error codes or share them with - all modules*/ -} - -/* - * 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_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) -{ - int rc = -1; - - if (!hd) - return GNUPG_Invalid_Value; - - 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_KEYBOX: - rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); - 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, 20); - return keydb_search (hd, &desc, 1); -} - -int -keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer) -{ - KEYDB_SEARCH_DESC desc; - int rc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_ISSUER; - desc.u.name = issuer; - rc = keydb_search (hd, &desc, 1); - return rc; -} - -int -keydb_search_issuer_sn (KEYDB_HANDLE hd, - const char *issuer, KsbaConstSexp serial) -{ - KEYDB_SEARCH_DESC desc; - int rc; - const unsigned char *s; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN; - s = serial; - if (*s !='(') - return GNUPG_Invalid_Value; - s++; - for (desc.snlen = 0; digitp (s); s++) - desc.snlen = 10*desc.snlen + atoi_1 (s); - if (*s !=':') - return GNUPG_Invalid_Value; - desc.sn = s+1; - desc.u.name = issuer; - rc = keydb_search (hd, &desc, 1); - return rc; -} - -int -keydb_search_subject (KEYDB_HANDLE hd, const char *name) -{ - KEYDB_SEARCH_DESC desc; - int rc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_SUBJECT; - desc.u.name = name; - rc = keydb_search (hd, &desc, 1); - return rc; -} - - -static int -hextobyte (const unsigned char *s) -{ - int c; - - if( *s >= '0' && *s <= '9' ) - c = 16 * (*s - '0'); - else if ( *s >= 'A' && *s <= 'F' ) - c = 16 * (10 + *s - 'A'); - else if ( *s >= 'a' && *s <= 'f' ) - c = 16 * (10 + *s - 'a'); - else - return -1; - s++; - if ( *s >= '0' && *s <= '9' ) - c += *s - '0'; - else if ( *s >= 'A' && *s <= 'F' ) - c += 10 + *s - 'A'; - else if ( *s >= 'a' && *s <= 'f' ) - c += 10 + *s - 'a'; - else - return -1; - return c; -} - - -static int -classify_user_id (const char *name, - KEYDB_SEARCH_DESC *desc, - int *force_exact ) -{ - const char *s; - int hexprefix = 0; - int hexlength; - int mode = 0; - - /* clear the structure so that the mode field is set to zero unless - * we set it to the correct value right at the end of this function */ - memset (desc, 0, sizeof *desc); - *force_exact = 0; - /* skip leading spaces. Fixme: what about trailing white space? */ - for(s = name; *s && spacep (s); s++ ) - ; - - switch (*s) - { - case 0: /* empty string is an error */ - return 0; - - case '.': /* an email address, compare from end */ - mode = KEYDB_SEARCH_MODE_MAILEND; - s++; - desc->u.name = s; - break; - - case '<': /* an email address */ - mode = KEYDB_SEARCH_MODE_MAIL; - s++; - desc->u.name = s; - break; - - case '@': /* part of an email address */ - mode = KEYDB_SEARCH_MODE_MAILSUB; - s++; - desc->u.name = s; - break; - - case '=': /* exact compare */ - mode = KEYDB_SEARCH_MODE_EXACT; - s++; - desc->u.name = s; - break; - - case '*': /* case insensitive substring search */ - mode = KEYDB_SEARCH_MODE_SUBSTR; - s++; - desc->u.name = s; - break; - - case '+': /* compare individual words */ - mode = KEYDB_SEARCH_MODE_WORDS; - s++; - desc->u.name = s; - break; - - case '/': /* subject's DN */ - s++; - if (!*s || spacep (s)) - return 0; /* no DN or prefixed with a space */ - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_SUBJECT; - break; - - case '#': - { - const char *si; - - s++; - if ( *s == '/') - { /* "#/" indicates an issuer's DN */ - s++; - if (!*s || spacep (s)) - return 0; /* no DN or prefixed with a space */ - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_ISSUER; - } - else - { /* serialnumber + optional issuer ID */ - for (si=s; *si && *si != '/'; si++) - { - if (!strchr("01234567890abcdefABCDEF", *si)) - return 0; /* invalid digit in serial number*/ - } - desc->sn = s; - desc->snlen = -1; - if (!*si) - mode = KEYDB_SEARCH_MODE_SN; - else - { - s = si+1; - if (!*s || spacep (s)) - return 0; /* no DN or prefixed with a space */ - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_ISSUER_SN; - } - } - } - break; - - case ':': /*Unified fingerprint */ - { - const char *se, *si; - int i; - - se = strchr (++s,':'); - if (!se) - return 0; - for (i=0,si=s; si < se; si++, i++ ) - { - if (!strchr("01234567890abcdefABCDEF", *si)) - return 0; /* invalid digit */ - } - if (i != 32 && i != 40) - return 0; /* invalid length of fpr*/ - for (i=0,si=s; si < se; i++, si +=2) - desc->u.fpr[i] = hextobyte(si); - for (; i < 20; i++) - desc->u.fpr[i]= 0; - s = se + 1; - mode = KEYDB_SEARCH_MODE_FPR; - } - break; - - default: - if (s[0] == '0' && s[1] == 'x') - { - hexprefix = 1; - s += 2; - } - - hexlength = strspn(s, "0123456789abcdefABCDEF"); - if (hexlength >= 8 && s[hexlength] =='!') - { - *force_exact = 1; - hexlength++; /* just for the following check */ - } - - /* check if a hexadecimal number is terminated by EOS or blank */ - if (hexlength && s[hexlength] && !spacep (s+hexlength)) - { - if (hexprefix) /* a "0x" prefix without correct */ - return 0; /* termination is an error */ - /* The first chars looked like a hex number, but really is - not */ - hexlength = 0; - } - - if (*force_exact) - hexlength--; /* remove the bang */ - - if (hexlength == 8 - || (!hexprefix && hexlength == 9 && *s == '0')) - { /* short keyid */ - unsigned long kid; - if (hexlength == 9) - s++; - kid = strtoul( s, NULL, 16 ); - desc->u.kid[4] = kid >> 24; - desc->u.kid[5] = kid >> 16; - desc->u.kid[6] = kid >> 8; - desc->u.kid[7] = kid; - mode = KEYDB_SEARCH_MODE_SHORT_KID; - } - else if (hexlength == 16 - || (!hexprefix && hexlength == 17 && *s == '0')) - { /* complete keyid */ - unsigned long kid0, kid1; - char buf[9]; - if (hexlength == 17) - s++; - mem2str(buf, s, 9 ); - kid0 = strtoul (buf, NULL, 16); - kid1 = strtoul (s+8, NULL, 16); - desc->u.kid[0] = kid0 >> 24; - desc->u.kid[1] = kid0 >> 16; - desc->u.kid[2] = kid0 >> 8; - desc->u.kid[3] = kid0; - desc->u.kid[4] = kid1 >> 24; - desc->u.kid[5] = kid1 >> 16; - desc->u.kid[6] = kid1 >> 8; - desc->u.kid[7] = kid1; - mode = KEYDB_SEARCH_MODE_LONG_KID; - } - else if (hexlength == 32 - || (!hexprefix && hexlength == 33 && *s == '0')) - { /* md5 fingerprint */ - int i; - if (hexlength == 33) - s++; - memset(desc->u.fpr+16, 0, 4); - for (i=0; i < 16; i++, s+=2) - { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR16; - } - else if (hexlength == 40 - || (!hexprefix && hexlength == 41 && *s == '0')) - { /* sha1/rmd160 fingerprint */ - int i; - if (hexlength == 41) - s++; - for (i=0; i < 20; i++, s+=2) - { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR20; - } - else if (!hexprefix) - { - /* The fingerprint in an X.509 listing is often delimited by - colons, so we try to single this case out. */ - mode = 0; - hexlength = strspn (s, ":0123456789abcdefABCDEF"); - if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength))) - { - int i; - - for (i=0; i < 20; i++, s += 3) - { - int c = hextobyte(s); - if (c == -1 || (i < 19 && s[2] != ':')) - break; - desc->u.fpr[i] = c; - } - if (i == 20) - mode = KEYDB_SEARCH_MODE_FPR20; - } - if (!mode) /* default is substring search */ - { - *force_exact = 0; - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_SUBSTR; - } - } - else - { /* hex number with a prefix but a wrong length */ - return 0; - } - } - - desc->mode = mode; - return mode; -} - - -int -keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc) -{ - int dummy; - KEYDB_SEARCH_DESC dummy_desc; - - if (!desc) - desc = &dummy_desc; - - if (!classify_user_id (name, desc, &dummy)) - return GNUPG_Invalid_Name; - return 0; -} - - -/* Store the certificate in the key DB but make sure that it does not - already exists. We do this simply by comparing the fingerprint. - If EXISTED is not NULL it will be set to true if the certificate - was already in the DB. */ -int -keydb_store_cert (KsbaCert cert, int ephemeral, int *existed) -{ - KEYDB_HANDLE kh; - int rc; - unsigned char fpr[20]; - - if (existed) - *existed = 0; - - if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL)) - { - log_error (_("failed to get the fingerprint\n")); - return GNUPG_General_Error; - } - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocate keyDB handle\n")); - return GNUPG_Out_Of_Core; - } - - if (ephemeral) - keydb_set_ephemeral (kh, 1); - - rc = keydb_search_fpr (kh, fpr); - if (rc != -1) - { - keydb_release (kh); - if (!rc) - { - if (existed) - *existed = 1; - return 0; /* okay */ - } - log_error (_("problem looking for existing certificate: %s\n"), - gnupg_strerror (rc)); - return rc; - } - - rc = keydb_locate_writable (kh, 0); - if (rc) - { - log_error (_("error finding writable keyDB: %s\n"), gnupg_strerror (rc)); - keydb_release (kh); - return rc; - } - - rc = keydb_insert_cert (kh, cert); - if (rc) - { - log_error (_("error storing certificate: %s\n"), gnupg_strerror (rc)); - keydb_release (kh); - return rc; - } - keydb_release (kh); - return 0; -} - - - diff --git a/sm/keylist.c b/sm/keylist.c deleted file mode 100644 index 96a8469ba..000000000 --- a/sm/keylist.c +++ /dev/null @@ -1,616 +0,0 @@ -/* keylist.c - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -struct list_external_parm_s { - FILE *fp; - int print_header; - int with_colons; - int with_chain; -}; - - - -static void -print_key_data (KsbaCert cert, FILE *fp) -{ -#if 0 - int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; - int i; - - for(i=0; i < n; i++ ) - { - fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) ); - mpi_print(stdout, pk->pkey[i], 1 ); - putchar(':'); - putchar('\n'); - } -#endif -} - -static void -print_capabilities (KsbaCert cert, FILE *fp) -{ - KsbaError err; - unsigned int use; - - err = ksba_cert_get_key_usage (cert, &use); - if (err == KSBA_No_Data) - { - putc ('e', fp); - putc ('s', fp); - putc ('c', fp); - putc ('E', fp); - putc ('S', fp); - putc ('C', fp); - return; - } - if (err) - { - log_error (_("error getting key usage information: %s\n"), - ksba_strerror (err)); - return; - } - - if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT))) - putc ('e', fp); - if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) - putc ('s', fp); - if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN)) - putc ('c', fp); - if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT))) - putc ('E', fp); - if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) - putc ('S', fp); - if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN)) - putc ('C', fp); -} - - -static void -print_time (time_t t, FILE *fp) -{ - if (!t) - ; - else if ( t == (time_t)(-1) ) - putc ('?', fp); - else - fprintf (fp, "%lu", (unsigned long)t); -} - - -/* return an allocated string with the email address extracted from a - DN */ -static char * -email_kludge (const char *name) -{ - const unsigned char *p; - unsigned char *buf; - int n; - - if (strncmp (name, "1.2.840.113549.1.9.1=#", 22)) - return NULL; - /* This looks pretty much like an email address in the subject's DN - we use this to add an additional user ID entry. This way, - openSSL generated keys get a nicer and usable listing */ - name += 22; - for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++) - ; - if (*p != '#' || !n) - return NULL; - buf = xtrymalloc (n+3); - if (!buf) - return NULL; /* oops, out of core */ - *buf = '<'; - for (n=1, p=name; *p != '#'; p +=2, n++) - buf[n] = xtoi_2 (p); - buf[n++] = '>'; - buf[n] = 0; - return buf; -} - - - - -/* List one certificate in colon mode */ -static void -list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) -{ - int idx, trustletter = 0; - char *p; - KsbaSexp sexp; - char *fpr; - - fputs (have_secret? "crs:":"crt:", fp); - trustletter = 0; -#if 0 - if (is_not_valid (cert)) - putc ('i', fp); - else if ( is_revoked (cert) ) - putc ('r', fp); - else if ( has_expired (cert)) - putcr ('e', fp); - else -#endif - { - trustletter = '?'; /*get_validity_info ( pk, NULL );*/ - putc (trustletter, fp); - } - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - fprintf (fp, ":%u:%d:%s:", - /*keylen_of_cert (cert)*/1024, - /* pubkey_algo_of_cert (cert)*/1, - fpr+24); - - /* we assume --fixed-list-mode for gpgsm */ - print_time ( ksba_cert_get_validity (cert, 0), fp); - putc (':', fp); - print_time ( ksba_cert_get_validity (cert, 1), fp); - putc (':', fp); - /* field 8, serial number: */ - if ((sexp = ksba_cert_get_serial (cert))) - { - int len; - const unsigned char *s = sexp; - - if (*s == '(') - { - s++; - for (len=0; *s && *s != ':' && digitp (s); s++) - len = len*10 + atoi_1 (s); - if (*s == ':') - for (s++; len; len--, s++) - fprintf (fp,"%02X", *s); - } - xfree (sexp); - } - putc (':', fp); - /* field 9, ownertrust - not used here */ - putc (':', fp); - /* field 10, old user ID - we use it here for the issuer DN */ - if ((p = ksba_cert_get_issuer (cert,0))) - { - print_sanitized_string (fp, p, ':'); - xfree (p); - } - putc (':', fp); - /* field 11, signature class - not used */ - putc (':', fp); - /* field 12, capabilities: */ - print_capabilities (cert, fp); - putc (':', fp); - putc ('\n', fp); - - /* FPR record */ - fprintf (fp, "fpr:::::::::%s:::", fpr); - xfree (fpr); fpr = NULL; - /* print chaining ID (field 13)*/ - { - KsbaCert next; - - if (!gpgsm_walk_cert_chain (cert, &next)) - { - p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); - fputs (p, fp); - xfree (p); - ksba_cert_release (next); - } - } - putc (':', fp); - putc ('\n', fp); - - - if (opt.with_key_data) - { - if ( (p = gpgsm_get_keygrip_hexstring (cert))) - { - fprintf (fp, "grp:::::::::%s:\n", p); - xfree (p); - } - print_key_data (cert, fp); - } - - for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++) - { - fprintf (fp, "uid:%c::::::::", trustletter); - print_sanitized_string (fp, p, ':'); - putc (':', fp); - putc (':', fp); - putc ('\n', fp); - if (!idx) - { - /* It would be better to get the faked email address from - the keydb. But as long as we don't have a way to pass - the meta data back, we just check it the same way as the - code used to create the keybox meta data does */ - char *pp = email_kludge (p); - if (pp) - { - fprintf (fp, "uid:%c::::::::", trustletter); - print_sanitized_string (fp, pp, ':'); - putc (':', fp); - putc (':', fp); - putc ('\n', fp); - xfree (pp); - } - } - xfree (p); - } -} - - -/* List one certificate in standard mode */ -static void -list_cert_std (KsbaCert cert, FILE *fp, int have_secret) -{ - KsbaError kerr; - KsbaSexp sexp; - char *dn; - time_t t; - int idx; - int is_ca, chainlen; - unsigned int kusage; - char *string, *p; - - sexp = ksba_cert_get_serial (cert); - fputs ("Serial number: ", fp); - gpgsm_print_serial (fp, sexp); - ksba_free (sexp); - putc ('\n', fp); - - dn = ksba_cert_get_issuer (cert, 0); - fputs (" Issuer: ", fp); - gpgsm_print_name (fp, dn); - ksba_free (dn); - putc ('\n', fp); - for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++) - { - fputs (" aka: ", fp); - gpgsm_print_name (fp, dn); - ksba_free (dn); - putc ('\n', fp); - } - - dn = ksba_cert_get_subject (cert, 0); - fputs (" Subject: ", fp); - gpgsm_print_name (fp, dn); - ksba_free (dn); - putc ('\n', fp); - for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++) - { - fputs (" aka: ", fp); - gpgsm_print_name (fp, dn); - ksba_free (dn); - putc ('\n', fp); - } - - t = ksba_cert_get_validity (cert, 0); - fputs (" validity: ", fp); - gpgsm_print_time (fp, t); - fputs (" through ", fp); - t = ksba_cert_get_validity (cert, 1); - gpgsm_print_time (fp, t); - putc ('\n', fp); - - kerr = ksba_cert_get_key_usage (cert, &kusage); - if (kerr != KSBA_No_Data) - { - fputs (" key usage:", fp); - if (kerr) - fprintf (fp, " [error: %s]", ksba_strerror (kerr)); - else - { - if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE)) - fputs (" digitalSignature", fp); - if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION)) - fputs (" nonRepudiation", fp); - if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) - fputs (" keyEncipherment", fp); - if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT)) - fputs (" dataEncipherment", fp); - if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT)) - fputs (" keyAgreement", fp); - if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN)) - fputs (" certSign", fp); - if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN)) - fputs (" crlSign", fp); - if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY)) - fputs (" encipherOnly", fp); - if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY)) - fputs (" decipherOnly", fp); - } - putc ('\n', fp); - } - - kerr = ksba_cert_get_cert_policies (cert, &string); - if (kerr != KSBA_No_Data) - { - fputs (" policies: ", fp); - if (kerr) - fprintf (fp, "[error: %s]", ksba_strerror (kerr)); - else - { - for (p=string; *p; p++) - { - if (*p == '\n') - *p = ','; - } - print_sanitized_string (fp, string, 0); - xfree (string); - } - putc ('\n', fp); - } - - kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen); - if (kerr || is_ca) - { - fputs (" chain length: ", fp); - if (kerr) - fprintf (fp, "[error: %s]", ksba_strerror (kerr)); - else if (chainlen == -1) - fputs ("unlimited", fp); - else - fprintf (fp, "%d", chainlen); - putc ('\n', fp); - } - - - dn = gpgsm_get_fingerprint_string (cert, 0); - fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); - xfree (dn); -} - -/* Same as standard mode mode list all certifying certts too */ -static void -list_cert_chain (KsbaCert cert, FILE *fp) -{ - KsbaCert next = NULL; - - list_cert_std (cert, fp, 0); - ksba_cert_ref (cert); - while (!gpgsm_walk_cert_chain (cert, &next)) - { - ksba_cert_release (cert); - fputs ("Certified by\n", fp); - list_cert_std (next, fp, 0); - cert = next; - } - ksba_cert_release (cert); - putc ('\n', fp); -} - - - -/* List all internal keys or just the key given as NAMES. - */ -static void -list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) -{ - KEYDB_HANDLE hd; - KEYDB_SEARCH_DESC *desc = NULL; - STRLIST sl; - int ndesc; - KsbaCert cert = NULL; - int rc=0; - const char *lastresname, *resname; - int have_secret; - - hd = keydb_new (0); - if (!hd) - { - log_error ("keydb_new failed\n"); - goto leave; - } - - if (!names) - ndesc = 1; - else - { - for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) - ; - } - - desc = xtrycalloc (ndesc, sizeof *desc); - if (!ndesc) - { - log_error ("out of core\n"); - goto leave; - } - - if (!names) - desc[0].mode = KEYDB_SEARCH_MODE_FIRST; - else - { - for (ndesc=0, sl=names; sl; sl = sl->next) - { - rc = keydb_classify_name (sl->d, desc+ndesc); - if (rc) - { - log_error ("key `%s' not found: %s\n", - sl->d, gnupg_strerror (rc)); - rc = 0; - } - else - ndesc++; - } - - } - - /* 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 */ - - lastresname = NULL; - while (!(rc = keydb_search (hd, desc, ndesc))) - { - if (!names) - desc[0].mode = KEYDB_SEARCH_MODE_NEXT; - - rc = keydb_get_cert (hd, &cert); - if (rc) - { - log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - resname = keydb_get_resource_name (hd); - - if (lastresname != resname ) - { - int i; - - if (ctrl->no_server) - { - fprintf (fp, "%s\n", resname ); - for (i=strlen(resname); i; i-- ) - putchar('-'); - putc ('\n', fp); - lastresname = resname; - } - } - - have_secret = 0; - if (mode) - { - char *p = gpgsm_get_keygrip_hexstring (cert); - if (p) - { - if (!gpgsm_agent_havekey (p)) - have_secret = 1; - xfree (p); - } - } - - if (!mode - || ((mode & 1) && !have_secret) - || ((mode & 2) && have_secret) ) - { - if (ctrl->with_colons) - list_cert_colon (cert, fp, have_secret); - else if (ctrl->with_chain) - list_cert_chain (cert, fp); - else - { - list_cert_std (cert, fp, have_secret); - putc ('\n', fp); - } - } - ksba_cert_release (cert); - cert = NULL; - } - if (rc && rc != -1) - log_error ("keydb_search failed: %s\n", gnupg_strerror (rc)); - - leave: - ksba_cert_release (cert); - xfree (desc); - keydb_release (hd); -} - - - -static void -list_external_cb (void *cb_value, KsbaCert cert) -{ - struct list_external_parm_s *parm = cb_value; - - if (keydb_store_cert (cert, 1, NULL)) - log_error ("error storing certificate as ephemeral\n"); - - if (parm->print_header) - { - const char *resname = "[external keys]"; - int i; - - fprintf (parm->fp, "%s\n", resname ); - for (i=strlen(resname); i; i-- ) - putchar('-'); - putc ('\n', parm->fp); - parm->print_header = 0; - } - - if (parm->with_colons) - list_cert_colon (cert, parm->fp, 0); - else if (parm->with_chain) - list_cert_chain (cert, parm->fp); - else - { - list_cert_std (cert, parm->fp, 0); - putc ('\n', parm->fp); - } -} - - -/* List external keys similar to internal one. Note: mode does not - make sense here because it would be unwise to list external secret - keys */ -static void -list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) -{ - int rc; - struct list_external_parm_s parm; - - parm.fp = fp; - parm.print_header = ctrl->no_server; - parm.with_colons = ctrl->with_colons; - parm.with_chain = ctrl->with_chain; - - rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm); - if (rc) - log_error ("listing external keys failed: %s\n", gnupg_strerror (rc)); -} - -/* List all keys or just the key given as NAMES. - MODE controls the operation mode: - Bit 0-2: - 0 = list all public keys but don't flag secret ones - 1 = list only public keys - 2 = list only secret keys - 3 = list secret and public keys - Bit 6: list internal keys - Bit 7: list external keys - */ -void -gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) -{ - if ((mode & (1<<6))) - list_internal_keys (ctrl, names, fp, (mode & 3)); - if ((mode & (1<<7))) - list_external_keys (ctrl, names, fp); -} diff --git a/sm/server.c b/sm/server.c deleted file mode 100644 index e8200feda..000000000 --- a/sm/server.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* server.c - Server mode and main entry point - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "gpgsm.h" -#include "../assuan/assuan.h" - -#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) - - -/* The filepointer for status message used in non-server mode */ -static FILE *statusfp; - -/* Data used to assuciate an Assuan context with local server data */ -struct server_local_s { - ASSUAN_CONTEXT assuan_ctx; - int message_fd; - int list_internal; - int list_external; - CERTLIST recplist; - CERTLIST signerlist; -}; - - - -/* note, that it is sufficient to allocate the target string D as - long as the source string S, i.e.: strlen(s)+1; */ -static void -strcpy_escaped_plus (char *d, const unsigned char *s) -{ - while (*s) - { - if (*s == '%' && s[1] && s[2]) - { - s++; - *d++ = xtoi_2 ( s); - s += 2; - } - else if (*s == '+') - *d++ = ' ', s++; - else - *d++ = *s++; - } - *d = 0; -} - - - - -/* Check whether the option NAME appears in LINE */ -static int -has_option (const char *line, const char *name) -{ - const char *s; - int n = strlen (name); - - s = strstr (line, name); - return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); -} - - -static void -close_message_fd (CTRL ctrl) -{ - if (ctrl->server_local->message_fd != -1) - { - close (ctrl->server_local->message_fd); - ctrl->server_local->message_fd = -1; - } -} - - -static int -option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - if (!strcmp (key, "include-certs")) - { - int i = *value? atoi (value) : -1; - if (ctrl->include_certs < -2) - return ASSUAN_Parameter_Error; - ctrl->include_certs = i; - } - else if (!strcmp (key, "display")) - { - if (opt.display) - free (opt.display); - opt.display = strdup (value); - if (!opt.display) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "ttyname")) - { - if (opt.ttyname) - free (opt.ttyname); - opt.ttyname = strdup (value); - if (!opt.ttyname) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "ttytype")) - { - if (opt.ttytype) - free (opt.ttytype); - opt.ttytype = strdup (value); - if (!opt.ttytype) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "lc-ctype")) - { - if (opt.lc_ctype) - free (opt.lc_ctype); - opt.lc_ctype = strdup (value); - if (!opt.lc_ctype) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "lc-messages")) - { - if (opt.lc_messages) - free (opt.lc_messages); - opt.lc_messages = strdup (value); - if (!opt.lc_messages) - return ASSUAN_Out_Of_Core; - } - else if (!strcmp (key, "list-mode")) - { - int i = *value? atoi (value) : 0; - if (!i || i == 1) /* default and mode 1 */ - { - ctrl->server_local->list_internal = 1; - ctrl->server_local->list_external = 0; - } - else if (i == 2) - { - ctrl->server_local->list_internal = 0; - ctrl->server_local->list_external = 1; - } - else if (i == 3) - { - ctrl->server_local->list_internal = 1; - ctrl->server_local->list_external = 1; - } - else - return ASSUAN_Parameter_Error; - } - else - return ASSUAN_Invalid_Option; - - return 0; -} - - - - -static void -reset_notify (ASSUAN_CONTEXT ctx) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - gpgsm_release_certlist (ctrl->server_local->recplist); - gpgsm_release_certlist (ctrl->server_local->signerlist); - ctrl->server_local->recplist = NULL; - ctrl->server_local->signerlist = NULL; - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); -} - - -static void -input_notify (ASSUAN_CONTEXT ctx, const char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - ctrl->autodetect_encoding = 0; - ctrl->is_pem = 0; - ctrl->is_base64 = 0; - if (strstr (line, "--armor")) - ctrl->is_pem = 1; - else if (strstr (line, "--base64")) - ctrl->is_base64 = 1; - else if (strstr (line, "--binary")) - ; - else - ctrl->autodetect_encoding = 1; -} - -static void -output_notify (ASSUAN_CONTEXT ctx, const char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - - ctrl->create_pem = 0; - ctrl->create_base64 = 0; - if (strstr (line, "--armor")) - ctrl->create_pem = 1; - else if (strstr (line, "--base64")) - ctrl->create_base64 = 1; /* just the raw output */ -} - - - -/* RECIPIENT - - Set the recipient for the encryption. should be the - internal representation of the key; the server may accept any other - way of specification [we will support this]. 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 RECIPIENT commands are - cumulative until a RESET or an successful ENCRYPT command. */ -static int -cmd_recipient (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - - rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist); - if (rc) - gpgsm_status2 (ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - "0", - line, NULL); - - return map_to_assuan_status (rc); -} - -/* SIGNER - - Set the signer's keys for the signature creation. should - be the internal representation of the key; the server may accept any - other way of specification [we will support this]. If this is a - valid and usable signing key the server does respond with OK, - otherwise it returns an ERR with the reason why the key can't be - used, the signing will then not be done for this key. If the policy - is not to sign at all if not all signer keys are valid, the client - has to take care of this. All SIGNER commands are cumulative until - a RESET but they are *not* reset by an SIGN command becuase it can - be expected that set of signers are used for more than one sign - operation. - - Note that this command returns an INV_RECP status which is a bit - strange, but they are very similar. */ -static int -cmd_signer (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - - rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist); - if (rc) - gpgsm_status2 (ctrl, STATUS_INV_RECP, - rc == -1? "1": - rc == GNUPG_No_Public_Key? "1": - rc == GNUPG_Ambiguous_Name? "2": - rc == GNUPG_Wrong_Key_Usage? "3": - rc == GNUPG_Certificate_Revoked? "4": - rc == GNUPG_Certificate_Expired? "5": - rc == GNUPG_No_CRL_Known? "6": - rc == GNUPG_CRL_Too_Old? "7": - rc == GNUPG_No_Policy_Match? "8": - rc == GNUPG_No_Secret_Key? "9": - "0", - line, NULL); - - return map_to_assuan_status (rc); -} - - -/* ENCRYPT - - Do the actual encryption process. Takes the plaintext from the INPUT - command, writes to the ciphertext to the file descriptor set with - the OUTPUT command, take the recipients form 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. */ -static int -cmd_encrypt (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int inp_fd, out_fd; - FILE *out_fp; - int rc; - - inp_fd = assuan_get_input_fd (ctx); - if (inp_fd == -1) - return set_error (No_Input, NULL); - out_fd = assuan_get_output_fd (ctx); - if (out_fd == -1) - return set_error (No_Output, NULL); - - out_fp = fdopen ( dup(out_fd), "w"); - if (!out_fp) - return set_error (General_Error, "fdopen() failed"); - rc = gpgsm_encrypt (assuan_get_pointer (ctx), - ctrl->server_local->recplist, - inp_fd, out_fp); - fclose (out_fp); - - gpgsm_release_certlist (ctrl->server_local->recplist); - ctrl->server_local->recplist = NULL; - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - return map_to_assuan_status (rc); -} - -/* DECRYPT - - This performs the decrypt operation after doing some check on the - internal state. (e.g. that only 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 - does take care of this by requesting this from the user. */ -static int -cmd_decrypt (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int inp_fd, out_fd; - FILE *out_fp; - int rc; - - inp_fd = assuan_get_input_fd (ctx); - if (inp_fd == -1) - return set_error (No_Input, NULL); - out_fd = assuan_get_output_fd (ctx); - if (out_fd == -1) - return set_error (No_Output, NULL); - - out_fp = fdopen ( dup(out_fd), "w"); - if (!out_fp) - return set_error (General_Error, "fdopen() failed"); - rc = gpgsm_decrypt (ctrl, inp_fd, out_fp); - fclose (out_fp); - - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - - return map_to_assuan_status (rc); -} - - -/* VERIFY - - This 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. - */ -static int -cmd_verify (ASSUAN_CONTEXT ctx, char *line) -{ - int rc; - CTRL ctrl = assuan_get_pointer (ctx); - int fd = assuan_get_input_fd (ctx); - int out_fd = assuan_get_output_fd (ctx); - FILE *out_fp = NULL; - - if (fd == -1) - return set_error (No_Input, NULL); - - if (out_fd != -1) - { - out_fp = fdopen ( dup(out_fd), "w"); - if (!out_fp) - return set_error (General_Error, "fdopen() failed"); - } - - rc = gpgsm_verify (assuan_get_pointer (ctx), fd, - ctrl->server_local->message_fd, out_fp); - if (out_fp) - fclose (out_fp); - - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - - return map_to_assuan_status (rc); -} - - -/* SIGN [--detached] - - Sign the data set with the INPUT command and write it to the sink - set by OUTPUT. With "--detached" specified, a detached signature is - created (surprise). */ -static int -cmd_sign (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int inp_fd, out_fd; - FILE *out_fp; - int detached; - int rc; - - inp_fd = assuan_get_input_fd (ctx); - if (inp_fd == -1) - return set_error (No_Input, NULL); - out_fd = assuan_get_output_fd (ctx); - if (out_fd == -1) - return set_error (No_Output, NULL); - - detached = has_option (line, "--detached"); - - out_fp = fdopen ( dup(out_fd), "w"); - if (!out_fp) - return set_error (General_Error, "fdopen() failed"); - - rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist, - inp_fd, detached, out_fp); - fclose (out_fp); - - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - - return map_to_assuan_status (rc); -} - - -/* IMPORT - - Import the certificates read form the input-fd, return status - message for each imported one. The import checks the validity of - the certificate but not of the entire chain. It is possible to - import expired certificates. */ -static int -cmd_import (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int rc; - int fd = assuan_get_input_fd (ctx); - - if (fd == -1) - return set_error (No_Input, NULL); - - rc = gpgsm_import (assuan_get_pointer (ctx), fd); - - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - - return map_to_assuan_status (rc); -} - - -static int -cmd_export (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int fd = assuan_get_output_fd (ctx); - FILE *out_fp; - char *p; - STRLIST list, sl; - - if (fd == -1) - return set_error (No_Output, NULL); - - /* break the line down into an STRLIST */ - list = NULL; - for (p=line; *p; line = p) - { - while (*p && *p != ' ') - p++; - if (*p) - *p++ = 0; - if (*line) - { - sl = xtrymalloc (sizeof *sl + strlen (line)); - if (!sl) - { - free_strlist (list); - return ASSUAN_Out_Of_Core; - } - sl->flags = 0; - strcpy_escaped_plus (sl->d, line); - sl->next = list; - list = sl; - } - } - - out_fp = fdopen ( dup(fd), "w"); - if (!out_fp) - { - free_strlist (list); - return set_error (General_Error, "fdopen() failed"); - } - - gpgsm_export (ctrl, list, out_fp); - fclose (out_fp); - free_strlist (list); - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - return 0; -} - - -static int -cmd_delkeys (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - char *p; - STRLIST list, sl; - int rc; - - /* break the line down into an STRLIST */ - list = NULL; - for (p=line; *p; line = p) - { - while (*p && *p != ' ') - p++; - if (*p) - *p++ = 0; - if (*line) - { - sl = xtrymalloc (sizeof *sl + strlen (line)); - if (!sl) - { - free_strlist (list); - return ASSUAN_Out_Of_Core; - } - sl->flags = 0; - strcpy_escaped_plus (sl->d, line); - sl->next = list; - list = sl; - } - } - - rc = gpgsm_delete (ctrl, list); - free_strlist (list); - - /* close and reset the fd */ - close_message_fd (ctrl); - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - - return map_to_assuan_status (rc); -} - - - -/* MESSAGE FD= - - Set the file descriptor to read a message which is used with - detached signatures */ -static int -cmd_message (ASSUAN_CONTEXT ctx, char *line) -{ - char *endp; - int fd; - CTRL ctrl = assuan_get_pointer (ctx); - - if (strncmp (line, "FD=", 3)) - return set_error (Syntax_Error, "FD= expected"); - line += 3; - if (!digitp (line)) - return set_error (Syntax_Error, "number required"); - fd = strtoul (line, &endp, 10); - if (*endp) - return set_error (Syntax_Error, "garbage found"); - if (fd == -1) - return set_error (No_Input, NULL); - - ctrl->server_local->message_fd = fd; - return 0; -} - - -static int -do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode) -{ - CTRL ctrl = assuan_get_pointer (ctx); - FILE *fp = assuan_get_data_fp (ctx); - char *p; - STRLIST list, sl; - unsigned int listmode; - - if (!fp) - return set_error (General_Error, "no data stream"); - - /* break the line down into an STRLIST */ - list = NULL; - for (p=line; *p; line = p) - { - while (*p && *p != ' ') - p++; - if (*p) - *p++ = 0; - if (*line) - { - sl = xtrymalloc (sizeof *sl + strlen (line)); - if (!sl) - { - free_strlist (list); - return ASSUAN_Out_Of_Core; - } - sl->flags = 0; - strcpy_escaped_plus (sl->d, line); - sl->next = list; - list = sl; - } - } - - ctrl->with_colons = 1; - listmode = mode; - if (ctrl->server_local->list_internal) - listmode |= (1<<6); - if (ctrl->server_local->list_external) - listmode |= (1<<7); - gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode); - free_strlist (list); - return 0; -} - -static int -cmd_listkeys (ASSUAN_CONTEXT ctx, char *line) -{ - return do_listkeys (ctx, line, 3); -} - -static int -cmd_listsecretkeys (ASSUAN_CONTEXT ctx, char *line) -{ - return do_listkeys (ctx, line, 2); -} - - -/* GENKEY - - Read the parameters in native format from the input fd and write a - certificate request to the output. - */ -static int -cmd_genkey (ASSUAN_CONTEXT ctx, char *line) -{ - CTRL ctrl = assuan_get_pointer (ctx); - int inp_fd, out_fd; - FILE *out_fp; - int rc; - - inp_fd = assuan_get_input_fd (ctx); - if (inp_fd == -1) - return set_error (No_Input, NULL); - out_fd = assuan_get_output_fd (ctx); - if (out_fd == -1) - return set_error (No_Output, NULL); - - out_fp = fdopen ( dup(out_fd), "w"); - if (!out_fp) - return set_error (General_Error, "fdopen() failed"); - rc = gpgsm_genkey (ctrl, inp_fd, out_fp); - fclose (out_fp); - - /* close and reset the fds */ - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - - return map_to_assuan_status (rc); -} - - - - - -/* Tell the assuan library about our commands */ -static int -register_commands (ASSUAN_CONTEXT ctx) -{ - static struct { - const char *name; - int cmd_id; - int (*handler)(ASSUAN_CONTEXT, char *line); - } table[] = { - { "RECIPIENT", 0, cmd_recipient }, - { "SIGNER", 0, cmd_signer }, - { "ENCRYPT", 0, cmd_encrypt }, - { "DECRYPT", 0, cmd_decrypt }, - { "VERIFY", 0, cmd_verify }, - { "SIGN", 0, cmd_sign }, - { "IMPORT", 0, cmd_import }, - { "EXPORT", 0, cmd_export }, - { "", ASSUAN_CMD_INPUT, NULL }, - { "", ASSUAN_CMD_OUTPUT, NULL }, - { "MESSAGE", 0, cmd_message }, - { "LISTKEYS", 0, cmd_listkeys }, - { "LISTSECRETKEYS", 0, cmd_listsecretkeys }, - { "GENKEY", 0, cmd_genkey }, - { "DELKEYS", 0, cmd_delkeys }, - { NULL } - }; - int i, j, rc; - - for (i=j=0; table[i].name; i++) - { - rc = assuan_register_command (ctx, - table[i].cmd_id? table[i].cmd_id - : (ASSUAN_CMD_USER + j++), - table[i].name, table[i].handler); - if (rc) - return rc; - } - return 0; -} - -/* Startup the server */ -void -gpgsm_server (void) -{ - int rc; - int filedes[2]; - ASSUAN_CONTEXT ctx; - struct server_control_s ctrl; - - memset (&ctrl, 0, sizeof ctrl); - gpgsm_init_default_ctrl (&ctrl); - - /* For now we use a simple pipe based server so that we can work - from scripts. We will later add options to run as a daemon and - wait for requests on a Unix domain socket */ - filedes[0] = 0; - filedes[1] = 1; - rc = assuan_init_pipe_server (&ctx, filedes); - if (rc) - { - log_error ("failed to initialize the server: %s\n", - assuan_strerror(rc)); - gpgsm_exit (2); - } - rc = register_commands (ctx); - if (rc) - { - log_error ("failed to the register commands with Assuan: %s\n", - assuan_strerror(rc)); - gpgsm_exit (2); - } - assuan_set_hello_line (ctx, "GNU Privacy Guard's S/M server ready"); - - assuan_register_reset_notify (ctx, reset_notify); - assuan_register_input_notify (ctx, input_notify); - assuan_register_output_notify (ctx, output_notify); - assuan_register_option_handler (ctx, option_handler); - - assuan_set_pointer (ctx, &ctrl); - ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); - ctrl.server_local->assuan_ctx = ctx; - ctrl.server_local->message_fd = -1; - ctrl.server_local->list_internal = 1; - ctrl.server_local->list_external = 0; - - if (DBG_ASSUAN) - assuan_set_log_stream (ctx, log_get_stream ()); - - for (;;) - { - rc = assuan_accept (ctx); - if (rc == -1) - { - break; - } - else if (rc) - { - log_info ("Assuan accept problem: %s\n", assuan_strerror (rc)); - break; - } - - rc = assuan_process (ctx); - if (rc) - { - log_info ("Assuan processing failed: %s\n", assuan_strerror (rc)); - continue; - } - } - - gpgsm_release_certlist (ctrl.server_local->recplist); - ctrl.server_local->recplist = NULL; - gpgsm_release_certlist (ctrl.server_local->signerlist); - ctrl.server_local->signerlist = NULL; - - assuan_deinit_server (ctx); -} - - -static const char * -get_status_string ( int no ) -{ - const char *s; - - switch (no) - { - case STATUS_ENTER : s = "ENTER"; break; - case STATUS_LEAVE : s = "LEAVE"; break; - case STATUS_ABORT : s = "ABORT"; break; - case STATUS_GOODSIG: s = "GOODSIG"; break; - case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break; - case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; - case STATUS_BADSIG : s = "BADSIG"; break; - case STATUS_ERRSIG : s = "ERRSIG"; break; - case STATUS_BADARMOR : s = "BADARMOR"; break; - case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; - case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; - case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; - case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; - case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; - case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; - case STATUS_GET_BOOL : s = "GET_BOOL"; break; - case STATUS_GET_LINE : s = "GET_LINE"; break; - case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break; - case STATUS_GOT_IT : s = "GOT_IT"; break; - case STATUS_SHM_INFO : s = "SHM_INFO"; break; - case STATUS_SHM_GET : s = "SHM_GET"; break; - case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; - case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; - case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; - case STATUS_VALIDSIG : s = "VALIDSIG"; break; - case STATUS_SIG_ID : s = "SIG_ID"; break; - case STATUS_ENC_TO : s = "ENC_TO"; break; - case STATUS_NODATA : s = "NODATA"; break; - case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; - case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; - case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; - case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; - case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; - case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; - case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; - case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; - case STATUS_GOODMDC : s = "GOODMDC"; break; - case STATUS_BADMDC : s = "BADMDC"; break; - case STATUS_ERRMDC : s = "ERRMDC"; break; - case STATUS_IMPORTED : s = "IMPORTED"; break; - case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; - case STATUS_FILE_START : s = "FILE_START"; break; - case STATUS_FILE_DONE : s = "FILE_DONE"; break; - case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; - case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break; - case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break; - case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break; - case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break; - case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break; - case STATUS_PROGRESS : s = "PROGRESS"; break; - case STATUS_SIG_CREATED : s = "SIG_CREATED"; break; - case STATUS_SESSION_KEY : s = "SESSION_KEY"; break; - case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break; - case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break; - case STATUS_POLICY_URL : s = "POLICY_URL" ; break; - case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break; - case STATUS_END_STREAM : s = "END_STREAM"; break; - case STATUS_KEY_CREATED : s = "KEY_CREATED"; break; - case STATUS_UNEXPECTED : s = "UNEXPECTED"; break; - case STATUS_INV_RECP : s = "INV_RECP"; break; - case STATUS_NO_RECP : s = "NO_RECP"; break; - case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break; - case STATUS_EXPSIG : s = "EXPSIG"; break; - case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; - case STATUS_TRUNCATED : s = "TRUNCATED"; break; - case STATUS_ERROR : s = "ERROR"; break; - case STATUS_IMPORT_PROBLEM : s = "IMPORT_PROBLEM"; break; - default: s = "?"; break; - } - return s; -} - - -void -gpgsm_status2 (CTRL ctrl, int no, ...) -{ - va_list arg_ptr; - const char *text; - - va_start (arg_ptr, no); - - if (ctrl->no_server) - { - if (ctrl->status_fd == -1) - return; /* no status wanted */ - if (!statusfp) - { - if (ctrl->status_fd == 1) - statusfp = stdout; - else if (ctrl->status_fd == 2) - statusfp = stderr; - else - statusfp = fdopen (ctrl->status_fd, "w"); - - if (!statusfp) - { - log_fatal ("can't open fd %d for status output: %s\n", - ctrl->status_fd, strerror(errno)); - } - } - - fputs ("[GNUPG:] ", statusfp); - fputs (get_status_string (no), statusfp); - - while ( (text = va_arg (arg_ptr, const char*) )) - { - putc ( ' ', statusfp ); - for (; *text; text++) - { - if (*text == '\n') - fputs ( "\\n", statusfp ); - else if (*text == '\r') - fputs ( "\\r", statusfp ); - else - putc ( *(const byte *)text, statusfp ); - } - } - putc ('\n', statusfp); - fflush (statusfp); - } - else - { - ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx; - char buf[950], *p; - size_t n; - - p = buf; - n = 0; - while ( (text = va_arg (arg_ptr, const char *)) ) - { - if (n) - { - *p++ = ' '; - n++; - } - for ( ; *text && n < DIM (buf)-2; n++) - *p++ = *text++; - } - *p = 0; - assuan_write_status (ctx, get_status_string (no), buf); - } - - va_end (arg_ptr); -} - -void -gpgsm_status (CTRL ctrl, int no, const char *text) -{ - gpgsm_status2 (ctrl, no, text, NULL); -} - - - -#if 0 -/* - * Write a status line with a buffer using %XX escapes. If WRAP is > - * 0 wrap the line after this length. If STRING is not NULL it will - * be prepended to the buffer, no escaping is done for string. - * A wrap of -1 forces spaces not to be encoded as %20. - */ -void -write_status_text_and_buffer ( int no, const char *string, - const char *buffer, size_t len, int wrap ) -{ - const char *s, *text; - int esc, first; - int lower_limit = ' '; - size_t n, count, dowrap; - - if( !statusfp ) - return; /* not enabled */ - - if (wrap == -1) { - lower_limit--; - wrap = 0; - } - - text = get_status_string (no); - count = dowrap = first = 1; - do { - if (dowrap) { - fprintf (statusfp, "[GNUPG:] %s ", text ); - count = dowrap = 0; - if (first && string) { - fputs (string, statusfp); - count += strlen (string); - } - first = 0; - } - for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) { - if ( *s == '%' || *(const byte*)s <= lower_limit - || *(const byte*)s == 127 ) - esc = 1; - if ( wrap && ++count > wrap ) { - dowrap=1; - break; - } - } - if (esc) { - s--; n++; - } - if (s != buffer) - fwrite (buffer, s-buffer, 1, statusfp ); - if ( esc ) { - fprintf (statusfp, "%%%02X", *(const byte*)s ); - s++; n--; - } - buffer = s; - len = n; - if ( dowrap && len ) - putc ( '\n', statusfp ); - } while ( len ); - - putc ('\n',statusfp); - fflush (statusfp); -} -#endif diff --git a/sm/sign.c b/sm/sign.c deleted file mode 100644 index 061dfeebc..000000000 --- a/sm/sign.c +++ /dev/null @@ -1,622 +0,0 @@ -/* sign.c - Sign a message - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - - -static void -hash_data (int fd, GCRY_MD_HD md) -{ - FILE *fp; - char buffer[4096]; - int nread; - - fp = fdopen ( dup (fd), "rb"); - if (!fp) - { - log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); - return; - } - - do - { - nread = fread (buffer, 1, DIM(buffer), fp); - gcry_md_write (md, buffer, nread); - } - while (nread); - if (ferror (fp)) - log_error ("read error on fd %d: %s\n", fd, strerror (errno)); - fclose (fp); -} - -static int -hash_and_copy_data (int fd, GCRY_MD_HD md, KsbaWriter writer) -{ - KsbaError err; - FILE *fp; - char buffer[4096]; - int nread; - int rc = 0; - int any = 0; - - fp = fdopen ( dup (fd), "rb"); - if (!fp) - { - log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); - return GNUPG_File_Open_Error; - } - - do - { - nread = fread (buffer, 1, DIM(buffer), fp); - if (nread) - { - any = 1; - gcry_md_write (md, buffer, nread); - err = ksba_writer_write_octet_string (writer, buffer, nread, 0); - if (err) - { - log_error ("write failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - } - } - } - while (nread && !rc); - if (ferror (fp)) - { - log_error ("read error on fd %d: %s\n", fd, strerror (errno)); - rc = GNUPG_Read_Error; - } - fclose (fp); - if (!any) - { - /* We can't allow to sign an empty message becuase it does not - make mnuch sense and more seriously, ksba-cms_build has - already written the tag for data and now expects an octet - string but an octet string of zeize 0 is illegal. */ - log_error ("cannot sign an empty message\n"); - rc = GNUPG_No_Data; - } - if (!rc) - { - err = ksba_writer_write_octet_string (writer, NULL, 0, 1); - if (err) - { - log_error ("write failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - } - } - - return rc; -} - - -/* Get the default certificate which is defined as the first one our - keyDB retruns and has a secret key available */ -int -gpgsm_get_default_cert (KsbaCert *r_cert) -{ - KEYDB_HANDLE hd; - KsbaCert cert = NULL; - int rc; - char *p; - - hd = keydb_new (0); - if (!hd) - return GNUPG_General_Error; - rc = keydb_search_first (hd); - if (rc) - { - keydb_release (hd); - return rc; - } - - do - { - rc = keydb_get_cert (hd, &cert); - if (rc) - { - log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc)); - keydb_release (hd); - return rc; - } - - p = gpgsm_get_keygrip_hexstring (cert); - if (p) - { - if (!gpgsm_agent_havekey (p)) - { - xfree (p); - keydb_release (hd); - *r_cert = cert; - return 0; /* got it */ - } - xfree (p); - } - - ksba_cert_release (cert); - cert = NULL; - } - while (!(rc = keydb_search_next (hd))); - if (rc && rc != -1) - log_error ("keydb_search_next failed: %s\n", gnupg_strerror (rc)); - - ksba_cert_release (cert); - keydb_release (hd); - return rc; -} - - -static KsbaCert -get_default_signer (void) -{ - KEYDB_SEARCH_DESC desc; - KsbaCert cert = NULL; - KEYDB_HANDLE kh = NULL; - int rc; - - if (!opt.local_user) - { - rc = gpgsm_get_default_cert (&cert); - if (rc) - { - if (rc != -1) - log_debug ("failed to find default certificate: %s\n", - gnupg_strerror (rc)); - return NULL; - } - return cert; - } - - rc = keydb_classify_name (opt.local_user, &desc); - if (rc) - { - log_error ("failed to find default signer: %s\n", gnupg_strerror (rc)); - return NULL; - } - - kh = keydb_new (0); - if (!kh) - return NULL; - - rc = keydb_search (kh, &desc, 1); - if (rc) - { - log_debug ("failed to find default certificate: rc=%d\n", rc); - } - else - { - rc = keydb_get_cert (kh, &cert); - if (rc) - { - log_debug ("failed to get cert: rc=%d\n", rc); - } - } - - keydb_release (kh); - return cert; -} - -/* Depending on the options in CTRL add the certificate CERT as well as - other certificate up in the chain to the Root-CA to the CMS - object. */ -static int -add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert) -{ - KsbaError err; - int rc = 0; - KsbaCert next = NULL; - int n; - int not_root = 0; - - ksba_cert_ref (cert); - - n = ctrl->include_certs; - if (n == -2) - { - not_root = 1; - n = -1; - } - if (n < 0 || n > 50) - n = 50; /* We better apply an upper bound */ - - if (n) - { - if (not_root && gpgsm_is_root_cert (cert)) - err = 0; - else - err = ksba_cms_add_cert (cms, cert); - if (err) - goto ksba_failure; - } - while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) ) - { - if (not_root && gpgsm_is_root_cert (next)) - err = 0; - else - err = ksba_cms_add_cert (cms, next); - ksba_cert_release (cert); - cert = next; next = NULL; - if (err) - goto ksba_failure; - } - ksba_cert_release (cert); - - return rc == -1? 0: rc; - - ksba_failure: - ksba_cert_release (cert); - log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err)); - return map_ksba_err (err); -} - - - - -/* Perform a sign operation. - - Sign the data received on DATA-FD in embedded mode or in detached - mode when DETACHED is true. Write the signature to OUT_FP. The - keys used to sign are taken from SIGNERLIST or the default one will - be used if the value of this argument is NULL. */ -int -gpgsm_sign (CTRL ctrl, CERTLIST signerlist, - int data_fd, int detached, FILE *out_fp) -{ - int i, rc; - KsbaError err; - Base64Context b64writer = NULL; - KsbaWriter writer; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KEYDB_HANDLE kh = NULL; - GCRY_MD_HD data_md = NULL; - int signer; - const char *algoid; - int algo; - time_t signed_at; - CERTLIST cl; - int release_signerlist = 0; - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - ctrl->pem_name = "SIGNED MESSAGE"; - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, NULL, writer); - if (err) - { - log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* We are going to create signed data with data as encap. content */ - err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA); - if (!err) - err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA); - if (err) - { - log_debug ("ksba_cms_set_content_type failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - /* If no list of signers is given, use a default one. */ - if (!signerlist) - { - KsbaCert cert = get_default_signer (); - if (!cert) - { - log_error ("no default signer found\n"); - rc = seterr (General_Error); - goto leave; - } - signerlist = xtrycalloc (1, sizeof *signerlist); - if (!signerlist) - { - rc = GNUPG_Out_Of_Core; - ksba_cert_release (cert); - goto leave; - } - signerlist->cert = cert; - release_signerlist = 1; - } - - - /* Gather certificates of signers and store them in the CMS object. */ - for (cl=signerlist; cl; cl = cl->next) - { - rc = gpgsm_cert_use_sign_p (cl->cert); - if (rc) - goto leave; - - err = ksba_cms_add_signer (cms, cl->cert); - if (err) - { - log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - rc = add_certificate_list (ctrl, cms, cl->cert); - if (rc) - { - log_error ("failed to store list of certificates: %s\n", - gnupg_strerror(rc)); - goto leave; - } - /* Set the hash algorithm we are going to use */ - err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/); - if (err) - { - log_debug ("ksba_cms_add_digest_algo failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - /* Prepare hashing (actually we are figuring out what we have set above)*/ - data_md = gcry_md_open (0, 0); - if (!data_md) - { - rc = map_gcry_err (gcry_errno()); - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - goto leave; - } - if (DBG_HASHING) - gcry_md_start_debug (data_md, "sign.data"); - - for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) - { - algo = gcry_md_map_name (algoid); - if (!algo) - { - log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); - rc = GNUPG_Bug; - goto leave; - } - gcry_md_enable (data_md, algo); - } - - if (detached) - { /* we hash the data right now so that we can store the message - digest. ksba_cms_build() takes this as an flag that detached - data is expected. */ - unsigned char *digest; - size_t digest_len; - /* Fixme do this for all signers and get the algo to use from - the signer's certificate - does not make mich sense, bu we - should do this consistent as we have already done it above */ - algo = GCRY_MD_SHA1; - hash_data (data_fd, data_md); - digest = gcry_md_read (data_md, algo); - digest_len = gcry_md_get_algo_dlen (algo); - if ( !digest || !digest_len) - { - log_error ("problem getting the hash of the data\n"); - rc = GNUPG_Bug; - goto leave; - } - for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) - { - err = ksba_cms_set_message_digest (cms, signer, digest, digest_len); - if (err) - { - log_error ("ksba_cms_set_message_digest failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - } - - signed_at = gnupg_get_time (); - for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) - { - err = ksba_cms_set_signing_time (cms, signer, signed_at); - if (err) - { - log_error ("ksba_cms_set_signing_time failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - - do - { - err = ksba_cms_build (cms, &stopreason); - if (err) - { - log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - if (stopreason == KSBA_SR_BEGIN_DATA) - { /* hash the data and store the message digest */ - unsigned char *digest; - size_t digest_len; - - assert (!detached); - /* Fixme: get the algo to use from the signer's certificate - - does not make much sense, but we should do this - consistent as we have already done it above. Code is - mostly duplicated above. */ - - algo = GCRY_MD_SHA1; - rc = hash_and_copy_data (data_fd, data_md, writer); - if (rc) - goto leave; - digest = gcry_md_read (data_md, algo); - digest_len = gcry_md_get_algo_dlen (algo); - if ( !digest || !digest_len) - { - log_error ("problem getting the hash of the data\n"); - rc = GNUPG_Bug; - goto leave; - } - for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) - { - err = ksba_cms_set_message_digest (cms, signer, - digest, digest_len); - if (err) - { - log_error ("ksba_cms_set_message_digest failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - } - } - else if (stopreason == KSBA_SR_NEED_SIG) - { /* calculate the signature for all signers */ - GCRY_MD_HD md; - - algo = GCRY_MD_SHA1; - md = gcry_md_open (algo, 0); - if (DBG_HASHING) - gcry_md_start_debug (md, "sign.attr"); - - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - goto leave; - } - ksba_cms_set_hash_function (cms, HASH_FNC, md); - for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) - { - char *sigval = NULL; - char *buf, *fpr; - - if (signer) - gcry_md_reset (md); - rc = ksba_cms_hash_signed_attrs (cms, signer); - if (rc) - { - log_debug ("hashing signed attrs failed: %s\n", - ksba_strerror (rc)); - gcry_md_close (md); - goto leave; - } - - rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval); - if (rc) - { - gcry_md_close (md); - goto leave; - } - - err = ksba_cms_set_sig_val (cms, signer, sigval); - xfree (sigval); - if (err) - { - log_error ("failed to store the signature: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - gcry_md_close (md); - goto leave; - } - - /* write a status message */ - fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1); - if (!fpr) - { - rc = seterr (Out_Of_Core); - gcry_md_close (md); - goto leave; - } - rc = asprintf (&buf, "%c %d %d 00 %lu %s", - detached? 'D':'S', - GCRY_PK_RSA, /* FIXME: get pk algo from cert */ - algo, - (ulong)signed_at, - fpr); - xfree (fpr); - if (rc < 0) - { - rc = seterr (Out_Of_Core); - gcry_md_close (md); - goto leave; - } - rc = 0; - gpgsm_status (ctrl, STATUS_SIG_CREATED, buf); - free (buf); /* yes, we must use the regular free() here */ - } - gcry_md_close (md); - - } - } - while (stopreason != KSBA_SR_READY); - - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - - log_info ("signature created\n"); - - - leave: - if (release_signerlist) - gpgsm_release_certlist (signerlist); - ksba_cms_release (cms); - gpgsm_destroy_writer (b64writer); - keydb_release (kh); - gcry_md_close (data_md); - return rc; -} diff --git a/sm/verify.c b/sm/verify.c deleted file mode 100644 index df7c8bfe8..000000000 --- a/sm/verify.c +++ /dev/null @@ -1,510 +0,0 @@ -/* verify.c - Verify a messages signature - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "gpgsm.h" -#include "keydb.h" -#include "i18n.h" - -/* fixme: Move this to jnlib */ -static char * -strtimestamp (time_t atime) -{ - char *buffer = xmalloc (15); - - if (atime < 0) - strcpy (buffer, "????" "-??" "-??"); - else if (!atime) - strcpy (buffer, "none"); - else - { - struct tm *tp; - - tp = gmtime( &atime ); - sprintf (buffer, "%04d-%02d-%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday); - } - return buffer; -} - - - -/* Hash the data for a detached signature */ -static void -hash_data (int fd, GCRY_MD_HD md) -{ - FILE *fp; - char buffer[4096]; - int nread; - - fp = fdopen ( dup (fd), "rb"); - if (!fp) - { - log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); - return; - } - - do - { - nread = fread (buffer, 1, DIM(buffer), fp); - gcry_md_write (md, buffer, nread); - } - while (nread); - if (ferror (fp)) - log_error ("read error on fd %d: %s\n", fd, strerror (errno)); - fclose (fp); -} - - - - -/* Perform a verify operation. To verify detached signatures, data_fd - must be different than -1. With OUT_FP given and a non-detached - signature, the signed material is written to that stream. */ -int -gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) -{ - int i, rc; - Base64Context b64reader = NULL; - Base64Context b64writer = NULL; - KsbaError err; - KsbaReader reader; - KsbaWriter writer = NULL; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KsbaCert cert; - KEYDB_HANDLE kh; - GCRY_MD_HD data_md = NULL; - int signer; - const char *algoid; - int algo; - int is_detached; - FILE *fp = NULL; - char *p; - - kh = keydb_new (0); - if (!kh) - { - log_error (_("failed to allocated keyDB handle\n")); - rc = GNUPG_General_Error; - goto leave; - } - - - fp = fdopen ( dup (in_fd), "rb"); - if (!fp) - { - log_error ("fdopen() failed: %s\n", strerror (errno)); - rc = seterr (IO_Error); - goto leave; - } - - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); - if (rc) - { - log_error ("can't create reader: %s\n", gnupg_strerror (rc)); - goto leave; - } - - if (out_fp) - { - rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); - if (rc) - { - log_error ("can't create writer: %s\n", gnupg_strerror (rc)); - goto leave; - } - } - - cms = ksba_cms_new (); - if (!cms) - { - rc = seterr (Out_Of_Core); - goto leave; - } - - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) - { - log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - data_md = gcry_md_open (0, 0); - if (!data_md) - { - rc = map_gcry_err (gcry_errno()); - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - goto leave; - } - if (DBG_HASHING) - gcry_md_start_debug (data_md, "vrfy.data"); - - is_detached = 0; - do - { - err = ksba_cms_parse (cms, &stopreason); - if (err) - { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); - goto leave; - } - - if (stopreason == KSBA_SR_NEED_HASH) - { - is_detached = 1; - if (opt.verbose) - log_info ("detached signature\n"); - } - - if (stopreason == KSBA_SR_NEED_HASH - || stopreason == KSBA_SR_BEGIN_DATA) - { /* We are now able to enable the hash algorithms */ - for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) - { - algo = gcry_md_map_name (algoid); - if (!algo) - log_error ("unknown hash algorithm `%s'\n", - algoid? algoid:"?"); - else - gcry_md_enable (data_md, algo); - } - if (is_detached) - { - if (data_fd == -1) - log_info ("detached signature w/o data " - "- assuming certs-only\n"); - else - hash_data (data_fd, data_md); - } - else - { - ksba_cms_set_hash_function (cms, HASH_FNC, data_md); - } - } - else if (stopreason == KSBA_SR_END_DATA) - { /* The data bas been hashed */ - - } - } - while (stopreason != KSBA_SR_READY); - - if (b64writer) - { - rc = gpgsm_finish_writer (b64writer); - if (rc) - { - log_error ("write failed: %s\n", gnupg_strerror (rc)); - goto leave; - } - } - - if (data_fd != -1 && !is_detached) - { - log_error ("data given for a non-detached signature\n"); - rc = GNUPG_Conflict; - goto leave; - } - - for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) - { - /* Fixme: it might be better to check the validity of the - certificate first before entering it into the DB. This way - we would avoid cluttering the DB with invalid - certificates. */ - keydb_store_cert (cert, 0, NULL); - ksba_cert_release (cert); - } - - cert = NULL; - err = 0; - for (signer=0; ; signer++) - { - char *issuer = NULL; - KsbaSexp sigval = NULL; - time_t sigtime, keyexptime; - KsbaSexp serial; - char *msgdigest = NULL; - size_t msgdigestlen; - - err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); - if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached) - { - log_info ("certs-only message accepted\n"); - err = 0; - break; - } - if (err) - { - if (signer && err == -1) - err = 0; - break; - } - if (DBG_X509) - { - log_debug ("signer %d - issuer: `%s'\n", - signer, issuer? issuer:"[NONE]"); - log_debug ("signer %d - serial: ", signer); - gpgsm_dump_serial (serial); - log_printf ("\n"); - } - - err = ksba_cms_get_signing_time (cms, signer, &sigtime); - if (err == KSBA_No_Data) - sigtime = 0; - else if (err) - { - log_error ("error getting signing time: %s\n", ksba_strerror (err)); - sigtime = (time_t)-1; - } - - err = ksba_cms_get_message_digest (cms, signer, - &msgdigest, &msgdigestlen); - if (!err) - { - algoid = ksba_cms_get_digest_algo (cms, signer); - algo = gcry_md_map_name (algoid); - if (DBG_X509) - log_debug ("signer %d - digest algo: %d\n", signer, algo); - if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) ) - { - log_error ("digest algo %d has not been enabled\n", algo); - goto next_signer; - } - } - else if (err == KSBA_No_Data) - { - assert (!msgdigest); - err = 0; - algoid = NULL; - algo = 0; - } - else /* real error */ - break; - - sigval = ksba_cms_get_sig_val (cms, signer); - if (!sigval) - { - log_error ("no signature value available\n"); - goto next_signer; - } - if (DBG_X509) - log_debug ("signer %d - signature available", signer); - - /* Find the certificate of the signer */ - keydb_search_reset (kh); - rc = keydb_search_issuer_sn (kh, issuer, serial); - if (rc) - { - if (rc == -1) - { - log_error ("certificate not found\n"); - rc = GNUPG_No_Public_Key; - } - else - log_error ("failed to find the certificate: %s\n", - gnupg_strerror(rc)); - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey", - gnupg_error_token (rc), NULL); - /* fixme: we might want to append the issuer and serial - using our standard notation */ - goto next_signer; - } - - rc = keydb_get_cert (kh, &cert); - if (rc) - { - log_error ("failed to get cert: %s\n", gnupg_strerror (rc)); - goto next_signer; - } - - log_info (_("Signature made ")); - if (sigtime) - gpgsm_dump_time (sigtime); - else - log_printf (_("[date not given]")); - log_printf (_(" using certificate ID %08lX\n"), - gpgsm_get_short_fingerprint (cert)); - - - if (msgdigest) - { /* Signed attributes are available. */ - GCRY_MD_HD md; - unsigned char *s; - - /* check that the message digest in the signed attributes - matches the one we calculated on the data */ - s = gcry_md_read (data_md, algo); - if ( !s || !msgdigestlen - || gcry_md_get_algo_dlen (algo) != msgdigestlen - || !s || memcmp (s, msgdigest, msgdigestlen) ) - { - char *fpr; - - log_error ("invalid signature: message digest attribute " - "does not match calculated one\n"); - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status (ctrl, STATUS_BADSIG, fpr); - xfree (fpr); - goto next_signer; - } - - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - goto next_signer; - } - if (DBG_HASHING) - gcry_md_start_debug (md, "vrfy.attr"); - - ksba_cms_set_hash_function (cms, HASH_FNC, md); - rc = ksba_cms_hash_signed_attrs (cms, signer); - if (rc) - { - log_error ("hashing signed attrs failed: %s\n", - ksba_strerror (rc)); - gcry_md_close (md); - goto next_signer; - } - rc = gpgsm_check_cms_signature (cert, sigval, md, algo); - gcry_md_close (md); - } - else - { - rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo); - } - - if (rc) - { - char *fpr; - - log_error ("invalid signature: %s\n", gnupg_strerror (rc)); - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status (ctrl, STATUS_BADSIG, fpr); - xfree (fpr); - goto next_signer; - } - rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/ - if (rc) - { - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.keyusage", - gnupg_error_token (rc), NULL); - rc = 0; - } - - if (DBG_X509) - log_debug ("signature okay - checking certs\n"); - rc = gpgsm_validate_chain (ctrl, cert, &keyexptime); - if (rc == GNUPG_Certificate_Expired) - { - gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); - rc = 0; - } - else - gpgsm_status (ctrl, STATUS_GOODSIG, NULL); - - { - char *buf, *fpr, *tstr; - - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - tstr = strtimestamp (sigtime); - buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120); - sprintf (buf, "%s %s %lu %lu", fpr, tstr, - (unsigned long)sigtime, (unsigned long)keyexptime ); - xfree (tstr); - xfree (fpr); - gpgsm_status (ctrl, STATUS_VALIDSIG, buf); - xfree (buf); - } - - if (rc) /* of validate_chain */ - { - log_error ("invalid certification chain: %s\n", gnupg_strerror (rc)); - if (rc == GNUPG_Bad_Certificate_Chain - || rc == GNUPG_Bad_Certificate - || rc == GNUPG_Bad_CA_Certificate - || rc == GNUPG_Certificate_Revoked) - gpgsm_status (ctrl, STATUS_TRUST_NEVER, gnupg_error_token (rc)); - else - gpgsm_status (ctrl, STATUS_TRUST_UNDEFINED, gnupg_error_token (rc)); - goto next_signer; - } - - for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) - { - log_info (!i? _("Good signature from") - : _(" aka")); - log_printf (" \""); - gpgsm_print_name (log_get_stream (), p); - log_printf ("\"\n"); - ksba_free (p); - } - - gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL); - - - next_signer: - rc = 0; - xfree (issuer); - xfree (serial); - xfree (sigval); - xfree (msgdigest); - ksba_cert_release (cert); - cert = NULL; - } - rc = 0; - if (err) - { - log_error ("ksba error: %s\n", ksba_strerror (err)); - rc = map_ksba_err (rc); - } - - - - leave: - ksba_cms_release (cms); - gpgsm_destroy_reader (b64reader); - gpgsm_destroy_writer (b64writer); - keydb_release (kh); - gcry_md_close (data_md); - if (fp) - fclose (fp); - - if (rc) - gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave", - gnupg_error_token (rc), NULL); - return rc; -} - diff --git a/stamp-h.in b/stamp-h.in deleted file mode 100644 index 9788f7023..000000000 --- a/stamp-h.in +++ /dev/null @@ -1 +0,0 @@ -timestamp diff --git a/tests/ChangeLog b/tests/ChangeLog deleted file mode 100644 index d9ff7eb8f..000000000 --- a/tests/ChangeLog +++ /dev/null @@ -1,52 +0,0 @@ -2002-09-04 Neal H. Walfield - - * Makefile.am (inittests.stamp): Do not set LD_LIBRARY_PATH, but - rather prepend it. Be more robust and prefer printf over echo -n. - -2002-09-04 Marcus Brinkmann - - * asschk.c (start_server): Close the parent's file descriptors in - the child. - (read_assuan): Variable NREAD removed. Cut off the received line - currectly if more than one line was read. - -2002-09-03 Neal H. Walfield - - * Makefile.am (inittests.stamp): Construct an LD_LIBRARY_PATH from - LDFLAGS. - -2002-08-09 Werner Koch - - * asschk.c (cmd_getenv): New. - (expand_line): Allow / as variable name delimiter. - * sm-sign+verify, sm-verify: Use $srcdir so that a VPATH build works. - - * Makefile.am: Fixes for make dist. - * samplekets/Makefile.am: New. - -2002-08-08 Werner Koch - - * asschk.c: Added some new features. - * runtest, inittests: New. - * text-1.txt, text-2.txt, text-3.txt: New. - * text-1.osig.pem, text-1.dsig.pem, text-1.osig-bad.pem: New. - * text-2.osig.pem, text-2.osig-bad.pem: New. - * samplekeys : New directory - * sm-verify, sm-sign+verify: The first test scripts. - -2002-08-06 Werner Koch - - * Makefile.am, asschk.c: 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. - - diff --git a/tests/Makefile.am b/tests/Makefile.am deleted file mode 100644 index b2fa56704..000000000 --- a/tests/Makefile.am +++ /dev/null @@ -1,78 +0,0 @@ -# Makefile.am -tests makefile for libxtime -# 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 - -GPGSM = ../sm/gpgsm - -# We can't unset a variable here so we unset GPG_AGENT_INFO in runtest -TESTS_ENVIRONMENT = GNUPGHOME=`pwd` LC_ALL=C GPGSM=$(GPGSM) $(srcdir)/runtest - -testscripts = sm-sign+verify sm-verify - -EXTRA_DIST = runtest inittests $(testscripts) \ - text-1.txt text-2.txt text-3.txt \ - text-1.osig.pem text-1.dsig.pem text-1.osig-bad.pem \ - text-2.osig.pem text-2.osig-bad.pem \ - samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key \ - samplekeys/cert_g10code_pete1.pem \ - samplekeys/cert_g10code_test1.pem \ - samplekeys/cert_g10code_theo1.pem - -TESTS = $(testscripts) - -CLEANFILES = inittests.stamp x y y z out err - *.lock .\#lk* - -DISTCLEANFILES = pubring.kbx~ random_seed - -noinst_PROGRAMS = asschk - -asschk_SOURCES = asschk.c - - -all-local: inittests.stamp - -clean-local: - srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean - -inittests.stamp: inittests - LD_LIBRARY_PATH=$$(seen=0; \ - for i in $(LDFLAGS); \ - do \ - if echo "$$i" | egrep '^-L' >/dev/null 2>&1; \ - then \ - if test $$seen = 0; \ - then \ - seen=1; \ - else \ - printf ":"; \ - fi; \ - printf "%s" "$${i}" | sed 's/^-L//'; \ - fi; \ - done; \ - if test $$seen != 0 \ - && test x$${LD_LIBRARY_PATH} != x; \ - then \ - printf ":"; \ - fi; \ - printf "%s" "$${LD_LIBRARY_PATH}") \ - srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests - echo timestamp >./inittests.stamp - diff --git a/tests/asschk.c b/tests/asschk.c deleted file mode 100644 index 1a11ead33..000000000 --- a/tests/asschk.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* asschk.c - Assuan Server Checker - * 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 is a simple stand-alone Assuan server test program. We don't - want to use the assuan library because we don't want to hide errors - in that library. - - The script language is line based. Empty lines or lines containing - only white spaces are ignored, line with a hash sign as first non - white space character are treated as comments. - - A simple macro mechanism is implemnted. Macros are expanded before - a line is processed but after comment processing. Macros are only - expanded once and non existing macros expand to the empty string. - A macro is dereferenced by prefixing its name with a dollar sign; - the end of the name is currently indicated by a white space, a - dollar sign or a slash. To use a dollor sign verbatim, double it. - - A macro is assigned by prefixing a statement with the macro name - and an equal sign. The value is assigned verbatim if it does not - resemble a command, otherwise the return value of the command will - get assigned. The command "let" may be used to assign values - unambigiously and it should be used if the value starts with a - letter. - - Conditions are not yes implemented except for a simple evaluation - which yields false for an empty string or the string "0". The - result may be negated by prefixing with a '!'. - - The general syntax of a command is: - - [ =] [] - - If NAME is not specifed but the statement returns a value it is - assigned to the name "?" so that it can be referenced using "$?". - The following commands are implemented: - - let - Return VALUE. - - echo - Print VALUE. - - openfile - Open file FILENAME for read access and retrun the file descriptor. - - createfile - Create file FILENAME, open for write access and retrun the file - descriptor. - - pipeserver - Connect to the Assuan server PROGRAM. - - send - Send LINE to the server. - - expect-ok - Expect an OK response from the server. Status and data out put - is ignored. - - expect-err - Expect an ERR response from the server. Status and data out put - is ignored. - - count-status - Initialize the assigned variable to 0 and assign it as an counter for - status code CODE. This command must be called with an assignment. - - quit - Terminate the process. - - quit-if - Terminate the process if CONDITION evaluates to true. - - fail-if - Terminate the process with an exit code of 1 if CONDITION - evaluates to true. - - cmpfiles - Returns true when the content of the files FIRST and SECOND match. - - getenv - Return the value of the environment variable NAME. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) -# define ATTR_PRINTF(f,a) __attribute__ ((format (printf,f,a))) -#else -# define ATTR_PRINTF(f,a) -#endif - -#define spacep(p) (*(p) == ' ' || *(p) == '\t') - -#define MAX_LINELEN 2048 - -typedef enum { - LINE_OK = 0, - LINE_ERR, - LINE_STAT, - LINE_DATA, - LINE_END, -} LINETYPE; - -typedef enum { - VARTYPE_SIMPLE = 0, - VARTYPE_FD, - VARTYPE_COUNTER -} VARTYPE; - - -struct variable_s { - struct variable_s *next; - VARTYPE type; - unsigned int count; - char *value; - char name[1]; -}; -typedef struct variable_s *VARIABLE; - - -static void die (const char *format, ...) ATTR_PRINTF(1,2); - - -/* Name of this program to be printed in error messages. */ -static const char *invocation_name; - -/* Talk a bit about what is going on. */ -static int opt_verbose; - -/* Option to ignore the echo command. */ -static int opt_no_echo; - -/* File descriptors used to communicate with the current server. */ -static int server_send_fd = -1; -static int server_recv_fd = -1; - -/* The Assuan protocol limits the line length to 1024, so we can - safely use a (larger) buffer. The buffer is filled using the - read_assuan(). */ -static char recv_line[MAX_LINELEN]; -/* Tell the status of the current line. */ -static LINETYPE recv_type; - -/* This is our variable storage. */ -static VARIABLE variable_list; - - -static void -die (const char *format, ...) -{ - va_list arg_ptr; - - fflush (stdout); - fprintf (stderr, "%s: ", invocation_name); - - va_start (arg_ptr, format); - vfprintf (stderr, format, arg_ptr); - va_end (arg_ptr); - putc ('\n', stderr); - - exit (1); -} - -static void -err (const char *format, ...) -{ - va_list arg_ptr; - - fflush (stdout); - fprintf (stderr, "%s: ", invocation_name); - - va_start (arg_ptr, format); - vfprintf (stderr, format, arg_ptr); - va_end (arg_ptr); - putc ('\n', stderr); -} - -static void * -xmalloc (size_t n) -{ - void *p = malloc (n); - if (!p) - die ("out of core"); - return p; -} - -static void * -xcalloc (size_t n, size_t m) -{ - void *p = calloc (n, m); - if (!p) - die ("out of core"); - return p; -} - -static char * -xstrdup (const char *s) -{ - char *p = xmalloc (strlen (s)+1); - strcpy (p, s); - return p; -} - - -/* Write LENGTH bytes from BUFFER to FD. */ -static int -writen (int fd, const char *buffer, size_t length) -{ - while (length) - { - int nwritten = write (fd, buffer, length); - - if (nwritten < 0) - { - if (errno == EINTR) - continue; - return -1; /* write error */ - } - length -= nwritten; - buffer += nwritten; - } - return 0; /* okay */ -} - - - - -/* Assuan specific stuff. */ - -/* Read a line from FD, store it in the global recv_line, analyze the - type and store that in recv_type. The function terminates on a - communication error. Returns a pointer into the inputline to the - first byte of the arguments. The parsing is very strict to match - excalty what we want to send. */ -static char * -read_assuan (int fd) -{ - static char pending[MAX_LINELEN]; - static size_t pending_len; - size_t nleft = sizeof recv_line; - char *buf = recv_line; - char *p; - - while (nleft > 0) - { - int n; - - if (pending_len) - { - if (pending_len >= nleft) - die ("received line too large"); - memcpy (buf, pending, pending_len); - n = pending_len; - pending_len = 0; - } - else - n = read (fd, buf, nleft); - if (n < 0) - { - if (errno == EINTR) - continue; - die ("reading fd %d failed: %s", fd, strerror (errno)); - } - else if (!n) - die ("received incomplete line on fd %d", fd); - p = buf; - nleft -= n; - buf += n; - - for (; n && *p != '\n'; n--, p++) - ; - if (n) - { - if (n>1) - { - n--; - memcpy (pending, p + 1, n); - pending_len = n; - } - *p = '\0'; - break; - } - } - if (!nleft) - die ("received line too large"); - - p = recv_line; - if (p[0] == 'O' && p[1] == 'K' && (p[2] == ' ' || !p[2])) - { - recv_type = LINE_OK; - p += 3; - } - else if (p[0] == 'E' && p[1] == 'R' && p[2] == 'R' - && (p[3] == ' ' || !p[3])) - { - recv_type = LINE_ERR; - p += 4; - } - else if (p[0] == 'S' && (p[1] == ' ' || !p[1])) - { - recv_type = LINE_STAT; - p += 2; - } - else if (p[0] == 'D' && p[1] == ' ') - { - recv_type = LINE_DATA; - p += 2; - } - else if (p[0] == 'E' && p[1] == 'N' && p[2] == 'D' && !p[3]) - { - recv_type = LINE_END; - p += 3; - } - else - die ("invalid line type (%.5s)", p); - - return p; -} - -/* Write LINE to the server using FD. It is expected that the line - contains the terminating linefeed as last character. */ -static void -write_assuan (int fd, const char *line) -{ - char buffer[1026]; - size_t n = strlen (line); - - if (n > 1024) - die ("line too long for Assuan protocol"); - strcpy (buffer, line); - if (!n || buffer[n-1] != '\n') - buffer[n++] = '\n'; - - if (writen (fd, buffer, n)) - die ("sending line to %d failed: %s", fd, strerror (errno)); -} - - -/* Start the server with path PGMNAME and connect its stdout and - strerr to a newly created pipes; the file descriptors are then - store in the gloabl variables SERVER_SEND_FD and - SERVER_RECV_FD. The initial handcheck is performed.*/ -static void -start_server (const char *pgmname) -{ - int rp[2]; - int wp[2]; - pid_t pid; - - if (pipe (rp) < 0) - die ("pipe creation failed: %s", strerror (errno)); - if (pipe (wp) < 0) - die ("pipe creation failed: %s", strerror (errno)); - - fflush (stdout); - fflush (stderr); - pid = fork (); - if (pid < 0) - die ("fork failed"); - - if (!pid) - { - const char *arg0; - - arg0 = strrchr (pgmname, '/'); - if (arg0) - arg0++; - else - arg0 = pgmname; - - if (wp[0] != STDIN_FILENO) - { - if (dup2 (wp[0], STDIN_FILENO) == -1) - die ("dup2 failed in child: %s", strerror (errno)); - close (wp[0]); - } - if (rp[1] != STDOUT_FILENO) - { - if (dup2 (rp[1], STDOUT_FILENO) == -1) - die ("dup2 failed in child: %s", strerror (errno)); - close (rp[1]); - } - if (!opt_verbose) - { - int fd = open ("/dev/null", O_WRONLY); - if (fd == -1) - die ("can't open `/dev/null': %s", strerror (errno)); - if (dup2 (fd, STDERR_FILENO) == -1) - die ("dup2 failed in child: %s", strerror (errno)); - close (fd); - } - - close (wp[1]); - close (rp[0]); - execl (pgmname, arg0, "--server", NULL); - die ("exec failed for `%s': %s", pgmname, strerror (errno)); - } - close (wp[0]); - close (rp[1]); - server_send_fd = wp[1]; - server_recv_fd = rp[0]; - - read_assuan (server_recv_fd); - if (recv_type != LINE_OK) - die ("no greating message"); -} - - - - - -/* Script intepreter. */ - -static void -unset_var (const char *name) -{ - VARIABLE var; - - for (var=variable_list; var && strcmp (var->name, name); var = var->next) - ; - if (!var) - return; -/* fprintf (stderr, "unsetting `%s'\n", name); */ - - if (var->type == VARTYPE_FD && var->value) - { - int fd; - - fd = atoi (var->value); - if (fd != -1 && fd != 0 && fd != 1 && fd != 2) - close (fd); - } - - free (var->value); - var->value = NULL; - var->type = 0; - var->count = 0; -} - - -static void -set_type_var (const char *name, const char *value, VARTYPE type) -{ - VARIABLE var; - - if (!name) - name = "?"; - for (var=variable_list; var && strcmp (var->name, name); var = var->next) - ; - if (!var) - { - var = xcalloc (1, sizeof *var + strlen (name)); - strcpy (var->name, name); - var->next = variable_list; - variable_list = var; - } - else - free (var->value); - - if (var->type == VARTYPE_FD && var->value) - { - int fd; - - fd = atoi (var->value); - if (fd != -1 && fd != 0 && fd != 1 && fd != 2) - close (fd); - } - - var->type = type; - var->count = 0; - if (var->type == VARTYPE_COUNTER) - { - /* We need some extra sapce as scratch area for get_var. */ - var->value = xmalloc (strlen (value) + 1 + 20); - strcpy (var->value, value); - } - else - var->value = xstrdup (value); -} - -static void -set_var (const char *name, const char *value) -{ - set_type_var (name, value, 0); -} - - -static const char * -get_var (const char *name) -{ - VARIABLE var; - - for (var=variable_list; var && strcmp (var->name, name); var = var->next) - ; - if (!var) - return NULL; - if (var->type == VARTYPE_COUNTER && var->value) - { /* Use the scratch space allocated by set_var. */ - char *p = var->value + strlen(var->value)+1; - sprintf (p, "%u", var->count); - return p; - } - else - return var->value; -} - - -/* Incremente all counter type variables with NAME in their VALUE. */ -static void -inc_counter (const char *name) -{ - VARIABLE var; - - if (!*name) - return; - for (var=variable_list; var; var = var->next) - { - if (var->type == VARTYPE_COUNTER - && var->value && !strcmp (var->value, name)) - var->count++; - } -} - - -/* Expand variables in LINE and return a new allocated buffer if - required. The function might modify LINE if the expanded version - fits into it. */ -static char * -expand_line (char *buffer) -{ - char *line = buffer; - char *p, *pend; - const char *value; - size_t valuelen, n; - char *result = NULL; - - while (*line) - { - p = strchr (line, '$'); - if (!p) - return result; /* nothing more to expand */ - - if (p[1] == '$') /* quoted */ - { - memmove (p, p+1, strlen (p+1)+1); - line = p + 1; - continue; - } - for (pend=p+1; *pend && !spacep (pend) - && *pend != '$' && *pend != '/'; pend++) - ; - if (*pend) - { - int save = *pend; - *pend = 0; - value = get_var (p+1); - *pend = save; - } - else - value = get_var (p+1); - if (!value) - value = ""; - valuelen = strlen (value); - if (valuelen <= pend - p) - { - memcpy (p, value, valuelen); - p += valuelen; - n = pend - p; - if (n) - memmove (p, p+n, strlen (p+n)+1); - line = p; - } - else - { - char *src = result? result : buffer; - char *dst; - - dst = xmalloc (strlen (src) + valuelen + 1); - n = p - src; - memcpy (dst, src, n); - memcpy (dst + n, value, valuelen); - n += valuelen; - strcpy (dst + n, pend); - line = dst + n; - free (result); - result = dst; - } - } - return result; -} - - -/* Evaluate COND and return the result. */ -static int -eval_boolean (const char *cond) -{ - int true = 1; - - for ( ; *cond == '!'; cond++) - true = !true; - if (!*cond || (*cond == '0' && !cond[1])) - return !true; - return true; -} - - - - - -static void -cmd_let (const char *assign_to, char *arg) -{ - set_var (assign_to, arg); -} - - -static void -cmd_echo (const char *assign_to, char *arg) -{ - if (!opt_no_echo) - printf ("%s\n", arg); -} - -static void -cmd_send (const char *assign_to, char *arg) -{ - if (opt_verbose) - fprintf (stderr, "sending `%s'\n", arg); - write_assuan (server_send_fd, arg); -} - -static void -handle_status_line (char *arg) -{ - char *p; - - for (p=arg; *p && !spacep (p); p++) - ; - if (*p) - { - int save = *p; - *p = 0; - inc_counter (arg); - *p = save; - } - else - inc_counter (arg); -} - -static void -cmd_expect_ok (const char *assign_to, char *arg) -{ - if (opt_verbose) - fprintf (stderr, "expecting OK\n"); - do - { - char *p = read_assuan (server_recv_fd); - if (opt_verbose > 1) - fprintf (stderr, "got line `%s'\n", recv_line); - if (recv_type == LINE_STAT) - handle_status_line (p); - } - while (recv_type != LINE_OK && recv_type != LINE_ERR); - if (recv_type != LINE_OK) - die ("expected OK but got `%s'", recv_line); -} - -static void -cmd_expect_err (const char *assign_to, char *arg) -{ - if (opt_verbose) - fprintf (stderr, "expecting ERR\n"); - do - { - char *p = read_assuan (server_recv_fd); - if (opt_verbose > 1) - fprintf (stderr, "got line `%s'\n", recv_line); - if (recv_type == LINE_STAT) - handle_status_line (p); - } - while (recv_type != LINE_OK && recv_type != LINE_ERR); - if (recv_type != LINE_ERR) - die ("expected ERR but got `%s'", recv_line); -} - -static void -cmd_count_status (const char *assign_to, char *arg) -{ - char *p; - - if (!*assign_to || !*arg) - die ("syntax error: count-status requires an argument and a variable"); - - for (p=arg; *p && !spacep (p); p++) - ; - if (*p) - { - for (*p++ = 0; spacep (p); p++) - ; - if (*p) - die ("cmpfiles: syntax error"); - } - set_type_var (assign_to, arg, VARTYPE_COUNTER); -} - -static void -cmd_openfile (const char *assign_to, char *arg) -{ - int fd; - char numbuf[20]; - - do - fd = open (arg, O_RDONLY); - while (fd == -1 && errno == EINTR); - if (fd == -1) - die ("error opening `%s': %s", arg, strerror (errno)); - - sprintf (numbuf, "%d", fd); - set_type_var (assign_to, numbuf, VARTYPE_FD); -} - -static void -cmd_createfile (const char *assign_to, char *arg) -{ - int fd; - char numbuf[20]; - - do - fd = open (arg, O_WRONLY|O_CREAT|O_TRUNC, 0666); - while (fd == -1 && errno == EINTR); - if (fd == -1) - die ("error creating `%s': %s", arg, strerror (errno)); - - sprintf (numbuf, "%d", fd); - set_type_var (assign_to, numbuf, VARTYPE_FD); -} - - -static void -cmd_pipeserver (const char *assign_to, char *arg) -{ - if (!*arg) - die ("syntax error: servername missing"); - - start_server (arg); -} - - -static void -cmd_quit_if(const char *assign_to, char *arg) -{ - if (eval_boolean (arg)) - exit (0); -} - -static void -cmd_fail_if(const char *assign_to, char *arg) -{ - if (eval_boolean (arg)) - exit (1); -} - - -static void -cmd_cmpfiles (const char *assign_to, char *arg) -{ - char *p = arg; - char *second; - FILE *fp1, *fp2; - char buffer1[2048]; /* note: both must be of equal size. */ - char buffer2[2048]; - size_t nread1, nread2; - int rc = 0; - - set_var (assign_to, "0"); - for (p=arg; *p && !spacep (p); p++) - ; - if (!*p) - die ("cmpfiles: syntax error"); - for (*p++ = 0; spacep (p); p++) - ; - second = p; - for (; *p && !spacep (p); p++) - ; - if (*p) - { - for (*p++ = 0; spacep (p); p++) - ; - if (*p) - die ("cmpfiles: syntax error"); - } - - fp1 = fopen (arg, "rb"); - if (!fp1) - { - err ("can't open `%s': %s", arg, strerror (errno)); - return; - } - fp2 = fopen (second, "rb"); - if (!fp2) - { - err ("can't open `%s': %s", second, strerror (errno)); - fclose (fp1); - return; - } - while ( (nread1 = fread (buffer1, 1, sizeof buffer1, fp1))) - { - if (ferror (fp1)) - break; - nread2 = fread (buffer2, 1, sizeof buffer2, fp2); - if (ferror (fp2)) - break; - if (nread1 != nread2 || memcmp (buffer1, buffer2, nread1)) - { - rc = 1; - break; - } - } - if (feof (fp1) && feof (fp2) && !rc) - { - if (opt_verbose) - err ("files match"); - set_var (assign_to, "1"); - } - else if (!rc) - err ("cmpfiles: read error: %s", strerror (errno)); - else - err ("cmpfiles: mismatch"); - fclose (fp1); - fclose (fp2); -} - -static void -cmd_getenv (const char *assign_to, char *arg) -{ - const char *s; - s = *arg? getenv (arg):""; - set_var (assign_to, s? s:""); -} - - - - -/* Process the current script line LINE. */ -static int -interpreter (char *line) -{ - static struct { - const char *name; - void (*fnc)(const char*, char*); - } cmdtbl[] = { - { "let" , cmd_let }, - { "echo" , cmd_echo }, - { "send" , cmd_send }, - { "expect-ok" , cmd_expect_ok }, - { "expect-err", cmd_expect_err }, - { "count-status", cmd_count_status }, - { "openfile" , cmd_openfile }, - { "createfile", cmd_createfile }, - { "pipeserver", cmd_pipeserver }, - { "quit" , NULL }, - { "quit-if" , cmd_quit_if }, - { "fail-if" , cmd_fail_if }, - { "cmpfiles" , cmd_cmpfiles }, - { "getenv" , cmd_getenv }, - { NULL } - }; - char *p, *save_p; - int i, save_c; - char *stmt = NULL; - char *assign_to = NULL; - char *must_free = NULL; - - for ( ;spacep (line); line++) - ; - if (!*line || *line == '#') - return 0; /* empty or comment */ - p = expand_line (line); - if (p) - { - must_free = p; - line = p; - for ( ;spacep (line); line++) - ; - if (!*line || *line == '#') - { - free (must_free); - return 0; /* empty or comment */ - } - } - for (p=line; *p && !spacep (p) && *p != '='; p++) - ; - if (*p == '=') - { - *p = 0; - assign_to = line; - } - else if (*p) - { - for (*p++ = 0; spacep (p); p++) - ; - if (*p == '=') - assign_to = line; - } - if (!*line) - die ("syntax error"); - stmt = line; - save_c = 0; - save_p = NULL; - if (assign_to) - { /* this is an assignment */ - for (p++; spacep (p); p++) - ; - if (!*p) - { - unset_var (assign_to); - free (must_free); - return 0; - } - stmt = p; - for (; *p && !spacep (p); p++) - ; - if (*p) - { - save_p = p; - save_c = *p; - for (*p++ = 0; spacep (p); p++) - ; - } - } - for (i=0; cmdtbl[i].name && strcmp (stmt, cmdtbl[i].name); i++) - ; - if (!cmdtbl[i].name) - { - if (!assign_to) - die ("invalid statement `%s'\n", stmt); - if (save_p) - *save_p = save_c; - set_var (assign_to, stmt); - free (must_free); - return 0; - } - - if (cmdtbl[i].fnc) - cmdtbl[i].fnc (assign_to, p); - free (must_free); - return cmdtbl[i].fnc? 0:1; -} - - - -int -main (int argc, char **argv) -{ - char buffer[2048]; - char *p, *pend; - - if (!argc) - invocation_name = "asschk"; - else - { - invocation_name = *argv++; - argc--; - p = strrchr (invocation_name, '/'); - if (p) - invocation_name = p+1; - } - - - set_var ("?","1"); /* defaults to true */ - - for (; argc; argc--, argv++) - { - p = *argv; - if (*p != '-') - break; - if (!strcmp (p, "--verbose")) - opt_verbose++; - else if (!strcmp (p, "--no-echo")) - opt_no_echo++; - else if (*p == '-' && p[1] == 'D') - { - p += 2; - pend = strchr (p, '='); - if (pend) - { - int tmp = *pend; - *pend = 0; - set_var (p, pend+1); - *pend = tmp; - } - else - set_var (p, "1"); - } - else if (*p == '-' && p[1] == '-' && !p[2]) - { - argc--; argv++; - break; - } - else - break; - } - if (argc) - die ("usage: asschk [--verbose] {-D[=]}"); - - - while (fgets (buffer, sizeof buffer, stdin)) - { - p = strchr (buffer,'\n'); - if (!p) - die ("incomplete script line"); - *p = 0; - if (interpreter (buffer)) - break; - fflush (stdout); - } - return 0; -} - diff --git a/tests/inittests b/tests/inittests deleted file mode 100755 index b1860f5fd..000000000 --- a/tests/inittests +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh -# Copyright (C) 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. - -set -e - -sample_certs=' -cert_g10code_test1.pem -cert_g10code_pete1.pem -cert_g10code_theo1.pem -' - -private_keys=' -32100C27173EF6E9C4E9A25D3D69F86D37A4F939 -' - -clean_files=' -gpgsm.conf gpg-agent.conf trustlist.txt pubring.kbx -msg msg.sig msg.unsig -' - - -[ -z "$srcdir" ] && srcdir=. -[ -z "$GPGSM" ] && GPGSM=../sm/gpgsm - -if [ -d $srcdir/samplekeys ] \ - && grep TESTS_ENVIRONMENT Makefile >/dev/null 2>&1; then - : -else - # During make distclean the Makefile has already been removed, - # so we need this extra test. - if ! grep gnupg-test-directory testdir.stamp >/dev/null 2>&1; then - echo "inittests: please cd to the tests directory first" >&2 - exit 1 - fi -fi - -if [ "$1" = "--clean" ]; then - if [ -d private-keys-v1.d ]; then - rm private-keys-v1.d/* 2>/dev/null || true - rmdir private-keys-v1.d - fi - rm ${clean_files} testdir.stamp 2>/dev/null || true - exit 0 -fi - -if [ "$GNUPGHOME" != "`pwd`" ]; then - echo "inittests: please set GNUPGHOME to the test directory" >&2 - exit 1 -fi - -if [ -n "$GPG_AGENT_INFO" ]; then - echo "inittests: please unset GPG_AGENT_INFO" >&2 - exit 1 -fi - -# A stamp file used with --clean -echo gnupg-test-directory > testdir.stamp - - -# Create the private key directy if it does not exists and copy -# the sample keys. -[ -d private-keys-v1.d ] || mkdir private-keys-v1.d -for i in ${private_keys}; do - cat ${srcdir}/samplekeys/$i.key >private-keys-v1.d/$i.key -done - -# Create the configuration scripts -cat > gpgsm.conf < gpg-agent.conf < trustlist.txt < - - * Makefile.am: Link bftest with EGDLIBS (i.e. NETLIBS) as EGD uses - sockets. - -2002-05-07 Stefan Bellon - - * gpgsplit.c (create_filename): Use EXTSEP_S instead of ".". - -2002-04-23 David Shaw - - * Makefile.am: Do not list libraries in -lxxx format in a - dependency line. - -2002-01-02 Stefan Bellon - - * gpgsplit.c [__riscos__]: Added RISC OS specific file name - code. - - * gpgsplit.c (write_part): Introduced two explicit casts. - -2001-12-21 David Shaw - - * gpgsplit.c (pkttype_to_string): PKT_PHOTO_ID -> PKT_ATTRIBUTE - -2001-10-23 Werner Koch - - * Makefile.am (gpgsplit_LDADD): Add ZLIBS. - -2001-09-18 Werner Koch - - * gpgsplit.c: New option --uncompress. - (write_part): Handle old style uncompressing. - -2001-06-20 Werner Koch - - * gpgsplit.c: New. - * Makefile.am (bin_PROGRAMS): Install gpgsplit. - -2001-03-27 Werner Koch - - * mail-signed-keys: Add option --dry-run. - -2001-03-21 Werner Koch - - * shmtest.c: Add sys/types.h - -Fri Sep 15 18:40:36 CEST 2000 Werner Koch - - * ring-a-party: An array start at offset 1 no 0. Many thanks to Mike - for finding this bug. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch - - * ring-a-party: Flush the last key. - -Wed Jul 5 13:28:45 CEST 2000 Werner Koch - - * mail-signed-keys: New. - -Tue May 23 09:19:00 CEST 2000 Werner Koch - - * ring-a-party: New. - -Thu Jul 8 16:21:27 CEST 1999 Werner Koch - - * lspgpot: New - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch - - * Makefile.am: Support for libtool. - -Tue Jun 8 13:36:25 CEST 1999 Werner Koch - - * mpicalc.c (main): hex digits may now be lowercase - (do_mulm): new. - -Thu Dec 10 20:15:36 CET 1998 Werner Koch - - * mpicalc.c (main): Moved initialization out of definition. - -Mon May 18 15:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mk-tdata.c: New. - -Tue Apr 7 19:50:41 1998 Werner Koch (wk@isil.d.shuttle.de) - - * bftest.c: Now supports all availabe ciphers. - - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/tools/Makefile.am b/tools/Makefile.am deleted file mode 100644 index 2d5e681eb..000000000 --- a/tools/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - -EXTRA_DIST = lspgpot ring-a-party mail-signed-keys -INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl -needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a - -bin_PROGRAMS = gpgsplit -noinst_PROGRAMS = mpicalc bftest clean-sat mk-tdata shmtest - -mpicalc_SOURCES = mpicalc.c - -bftest_SOURCES = bftest.c - -clean_sat_SOURCES = clean-sat.c -mk_tdata_SOURCES = mk-tdata.c -shmtest_SOURCES = shmtest.c - -gpgsplit_SOURCES = gpgsplit.c - - -mpicalc_LDADD = $(needed_libs) @INTLLIBS@ -bftest_LDADD = $(needed_libs) @EGDLIBS@ @INTLLIBS@ - -shmtest_LDADD = $(needed_libs) @INTLLIBS@ -gpgsplit_LDADD = @ZLIBS@ $(needed_libs) @INTLLIBS@ - -mpicalc bftest shmtest gpgsplit: $(needed_libs) diff --git a/tools/bftest.c b/tools/bftest.c deleted file mode 100644 index b15f4a1da..000000000 --- a/tools/bftest.c +++ /dev/null @@ -1,112 +0,0 @@ -/* bftest.c - Blowfish test program - * 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 -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM - #include - #include -#endif - -#include "util.h" -#include "cipher.h" -#include "i18n.h" - -static void -my_usage(void) -{ - fprintf(stderr, "usage: bftest [-e][-d] algo key\n"); - exit(1); -} - -const char * -strusage( int level ) -{ - return default_strusage(level); -} - -static void -i18n_init(void) -{ - #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif - bindtextdomain( PACKAGE, G10_LOCALEDIR ); - textdomain( PACKAGE ); - #endif -} - -int -main(int argc, char **argv) -{ - int encode=0; - CIPHER_HANDLE hd; - char buf[4096]; - int n, size=4096; - int algo; - - #ifdef HAVE_DOSISH_SYSTEM - setmode( fileno(stdin), O_BINARY ); - setmode( fileno(stdout), O_BINARY ); - #endif - - i18n_init(); - if( argc > 1 && !strcmp(argv[1], "-e") ) { - encode++; - argc--; argv++; - } - else if( argc > 1 && !strcmp(argv[1], "-E") ) { - encode++; - argc--; argv++; - size = 10; - } - else if( argc > 1 && !strcmp(argv[1], "-d") ) { - argc--; argv++; - } - else if( argc > 1 && !strcmp(argv[1], "-D") ) { - argc--; argv++; - size = 10; - } - if( argc != 3 ) - my_usage(); - argc--; argv++; - algo = string_to_cipher_algo( *argv ); - argc--; argv++; - - hd = cipher_open( algo, CIPHER_MODE_CFB, 0 ); - cipher_setkey( hd, *argv, strlen(*argv) ); - cipher_setiv( hd, NULL, 0 ); - while( (n = fread( buf, 1, size, stdin )) > 0 ) { - if( encode ) - cipher_encrypt( hd, buf, buf, n ); - else - cipher_decrypt( hd, buf, buf, n ); - if( fwrite( buf, 1, n, stdout) != n ) - log_fatal("write error\n"); - } - cipher_close(hd); - return 0; -} - diff --git a/tools/clean-sat.c b/tools/clean-sat.c deleted file mode 100644 index 8b6bfd77a..000000000 --- a/tools/clean-sat.c +++ /dev/null @@ -1,34 +0,0 @@ -/* clean-sat.c - * Copyright (C) 1998, 1999, 2000, 2001 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 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. - */ - -#include - -int -main(int argc, char **argv) -{ - int c; - - if( argc > 1 ) { - fprintf(stderr, "no arguments, please\n"); - return 1; - } - - while( (c=getchar()) == '\n' ) - ; - while( c != EOF ) { - putchar(c); - c = getchar(); - } - - return 0; -} - diff --git a/tools/crlf.c b/tools/crlf.c deleted file mode 100644 index e6ac8c70f..000000000 --- a/tools/crlf.c +++ /dev/null @@ -1,53 +0,0 @@ -/* crlf.c - * Copyright (C) 1999, 2000, 2001 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 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. - */ - -#include - -int -main(int argc, char **argv) -{ - int c, lc; - int off=0; - - if( argc > 1 ) { - fprintf(stderr, "no arguments, please\n"); - return 1; - } - - lc = -1; - while( (c=getchar()) != EOF ) { - #if 0 - if( c == '\r' && lc == ' ' ) - fprintf(stderr,"SP,CR at %d\n", off ); - if( c == '\n' && lc == ' ' ) - fprintf(stderr,"SP,LF at %d\n", off ); - #endif - if( c == '\n' && lc == '\r' ) - putchar(c); - else if( c == '\n' ) { - putchar('\r'); - putchar(c); - } - else if( c != '\n' && lc == '\r' ) { - putchar('\n'); - putchar(c); - } - else - putchar(c); - - lc = c; - off++; - } - - return 0; -} - diff --git a/tools/gpgsplit.c b/tools/gpgsplit.c deleted file mode 100644 index 8d89b1b9d..000000000 --- a/tools/gpgsplit.c +++ /dev/null @@ -1,553 +0,0 @@ -/* gpgsplit.c - An OpenPGP packet splitting tool - * 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 - */ - -/* - * TODO: Add an option to uncompress packets. This should come quite handy. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM - #include /* for setmode() */ -#endif -#include -#ifdef __riscos__ -#include -#endif /* __riscos__ */ - -#define INCLUDED_BY_MAIN_MODULE 1 -#include "../g10/packet.h" -#include "util.h" - -static int opt_verbose; -static const char *opt_prefix = ""; -static int opt_uncompress; - -static void g10_exit( int rc ); -static void split_packets (const char *fname); - - -enum cmd_and_opt_values { aNull = 0, - oVerbose = 'v', - oPrefix = 'p', - oUncompress = 500, -aTest }; - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, "@Options:\n " }, - - { oVerbose, "verbose", 0, "verbose" }, - { oPrefix, "prefix", 2, "|STRING|Prepend filenames with STRING" }, - { oUncompress, "uncompress", 0, "uncompress a packet"}, -{0} }; - - -const char * -strusage( int level ) -{ - const char *p; - switch( level ) { - case 11: p = "gpgsplit (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = - "Please report bugs to .\n"; - break; - case 1: - case 40: p = - "Usage: gpgsplit [options] [files] (-h for help)"; - break; - case 41: p = - "Syntax: gpgsplit [options] [files]\n" - "Split an OpenPGP message into packets\n"; - break; - - default: p = default_strusage(level); - } - return p; -} - - - -int -main( int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - - #ifdef __riscos__ - /* set global RISC OS specific properties */ - __riscosify_control = __RISCOSIFY_NO_PROCESS; - #endif /* __riscos__ */ - #ifdef HAVE_DOSISH_SYSTEM - setmode( fileno(stdin), O_BINARY ); - setmode( fileno(stdout), O_BINARY ); - #endif - log_set_name("gpgsplit"); - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - while( optfile_parse( NULL, NULL, NULL, &pargs, opts) ) { - switch( pargs.r_opt ) { - case oVerbose: opt_verbose = 1; break; - case oPrefix: opt_prefix = pargs.r.ret_str; break; - case oUncompress: opt_uncompress = 1; break; - default : pargs.err = 2; break; - } - } - - if( log_get_errorcount(0) ) - g10_exit(2); - - if (!argc) - split_packets (NULL); - else { - for ( ;argc; argc--, argv++) - split_packets (*argv); - } - - g10_exit (0); - return 0; -} - - -static void -g10_exit( int rc ) -{ - rc = rc? rc : log_get_errorcount(0)? 2 : 0; - exit(rc ); -} - -static const char * -pkttype_to_string (int pkttype) -{ - const char *s; - switch (pkttype) { - case PKT_PUBKEY_ENC : s = "pk_enc"; break; - case PKT_SIGNATURE : s = "sig"; break; - case PKT_SYMKEY_ENC : s = "sym_enc"; break; - case PKT_ONEPASS_SIG : s = "onepass_sig"; break; - case PKT_SECRET_KEY : s = "secret_key"; break; - case PKT_PUBLIC_KEY : s = "public_key"; break; - case PKT_SECRET_SUBKEY : s = "secret_subkey"; break; - case PKT_COMPRESSED : - s = opt_uncompress? "uncompressed":"compressed"; - break; - case PKT_ENCRYPTED : s = "encrypted"; break; - case PKT_MARKER : s = "marker"; break; - case PKT_PLAINTEXT : s = "plaintext"; break; - case PKT_RING_TRUST : s = "ring_trust"; break; - case PKT_USER_ID : s = "user_id"; break; - case PKT_PUBLIC_SUBKEY : s = "public_subkey"; break; - case PKT_OLD_COMMENT : s = "old_comment"; break; - case PKT_ATTRIBUTE : s = "attribute"; break; - case PKT_ENCRYPTED_MDC : s = "encrypted_mdc"; break; - case PKT_MDC : s = "mdc"; break; - case PKT_COMMENT : s = "comment"; break; - case PKT_GPG_CONTROL : s = "gpg_control"; break; - default: s = "unknown"; break; - } - return s; -} - - -/* - * Create a new filename and a return a pointer to a statically - * allocated buffer - */ -static char * -create_filename (int pkttype) -{ - static unsigned int partno = 0; - static char *name; - - if (!name) - name = m_alloc (strlen (opt_prefix) + 100 ); - - assert (pkttype < 1000 && pkttype >= 0 ); - partno++; - sprintf (name, "%s%06u-%03d" EXTSEP_S "%.40s", - opt_prefix, partno, pkttype, pkttype_to_string (pkttype)); - return name; -} - -static int -read_u16 (FILE *fp, size_t *rn) -{ - int c; - - if ( (c = getc (fp)) == EOF ) - return -1; - *rn = c << 8; - if ( (c = getc (fp)) == EOF ) - return -1; - *rn |= c; - return 0; -} - -static int -read_u32 (FILE *fp, unsigned long *rn) -{ - size_t tmp; - - if (read_u16 (fp, &tmp)) - return -1; - *rn = tmp << 16; - if (read_u16 (fp, &tmp)) - return -1; - *rn |= tmp; - return 0; -} - - -/* hdr must pint to a buffer large enough to hold all header bytes */ -static int -write_part ( const char *fname, FILE *fpin, unsigned long pktlen, - int pkttype, int partial, unsigned char *hdr, size_t hdrlen) -{ - FILE *fpout; - int c, first; - unsigned char *p; - const char *outname = create_filename (pkttype); - - /* fixme: should we check that this file does not yet exist? */ - if (opt_verbose) - log_info ("writing `%s'\n", outname); - fpout = fopen (outname, "wb"); - if (!fpout) { - log_error ("error creating `%s': %s\n", outname, strerror(errno)); - /* stop right now, otherwise we would mess up the sequence of - * the part numbers */ - g10_exit (1); - } - - if (!opt_uncompress) { - for (p=hdr; hdrlen; p++, hdrlen--) { - if ( putc (*p, fpout) == EOF ) - goto write_error; - } - } - - first = 1; - while (partial) { - size_t partlen; - - if (partial == 1) { /* openpgp */ - if( first ) { - c = pktlen; - assert( c >= 224 && c < 255 ); - first = 0; - } - else if( (c = getc (fpin)) == EOF ) { - goto read_error; - } - else - hdr[hdrlen++] = c; - - if( c < 192 ) { - pktlen = c; - partial = 0; /* (last segment may follow) */ - } - else if( c < 224 ) { - pktlen = (c - 192) * 256; - if( (c = getc (fpin)) == EOF ) - goto read_error; - hdr[hdrlen++] = c; - pktlen += c + 192; - partial = 0; - } - else if( c == 255 ) { - if (read_u32 (fpin, &pktlen)) - goto read_error; - hdr[hdrlen++] = pktlen >> 24; - hdr[hdrlen++] = pktlen >> 16; - hdr[hdrlen++] = pktlen >> 8; - hdr[hdrlen++] = pktlen; - partial = 0; - } - else { /* next partial body length */ - for (p=hdr; hdrlen; p++, hdrlen--) { - if ( putc (*p, fpout) == EOF ) - goto write_error; - } - partlen = 1 << (c & 0x1f); - for (; partlen; partlen--) { - if ((c = getc (fpin)) == EOF) - goto read_error; - if ( putc (c, fpout) == EOF ) - goto write_error; - } - } - } - else if (partial == 2) { /* old gnupg */ - assert (!pktlen); - if ( read_u16 (fpin, &partlen) ) - goto read_error; - hdr[hdrlen++] = partlen >> 8; - hdr[hdrlen++] = partlen; - for (p=hdr; hdrlen; p++, hdrlen--) { - if ( putc (*p, fpout) == EOF ) - goto write_error; - } - if (!partlen) - partial = 0; /* end of packet */ - for (; partlen; partlen--) { - c = getc (fpin); - if (c == EOF) - goto read_error; - if ( putc (c, fpout) == EOF ) - goto write_error; - } - } - else { /* compressed: read to end */ - pktlen = 0; - partial = 0; - hdrlen = 0; - if (opt_uncompress) { - z_stream zs; - byte *inbuf, *outbuf; - unsigned int inbufsize, outbufsize; - int algo, zinit_done, zrc, nread, count; - size_t n; - - if ((c = getc (fpin)) == EOF) - goto read_error; - algo = c; - - memset (&zs, 0, sizeof zs); - inbufsize = 2048; - inbuf = m_alloc (inbufsize); - outbufsize = 8192; - outbuf = m_alloc (outbufsize); - zs.avail_in = 0; - zinit_done = 0; - - do { - if (zs.avail_in < inbufsize) { - n = zs.avail_in; - if (!n) - zs.next_in = (Bytef *) inbuf; - count = inbufsize - n; - for (nread=0; - nread < count && (c=getc (fpin)) != EOF; - nread++) { - inbuf[n+nread] = c; - } - n += nread; - if (nread < count && algo == 1) { - inbuf[n] = 0xFF; /* chew dummy byte */ - n++; - } - zs.avail_in = n; - } - zs.next_out = (Bytef *) outbuf; - zs.avail_out = outbufsize; - - if (!zinit_done) { - zrc = algo == 1? inflateInit2 ( &zs, -13) - : inflateInit ( &zs ); - if (zrc != Z_OK) { - log_fatal ("zlib problem: %s\n", zs.msg? zs.msg : - zrc == Z_MEM_ERROR ? "out of core" : - zrc == Z_VERSION_ERROR ? - "invalid lib version" : - "unknown error" ); - } - zinit_done = 1; - } - else { -#ifdef Z_SYNC_FLUSH - zrc = inflate (&zs, Z_SYNC_FLUSH); -#else - zrc = inflate (&zs, Z_PARTIAL_FLUSH); -#endif - if (zrc == Z_STREAM_END) - ; /* 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 ); - } - for (n=0; n < outbufsize - zs.avail_out; n++) { - if (putc (outbuf[n], fpout) == EOF ) - goto write_error; - } - } - } while (zrc != Z_STREAM_END && zrc != Z_BUF_ERROR); - inflateEnd (&zs); - } - else { - while ( (c=getc (fpin)) != EOF ) { - if ( putc (c, fpout) == EOF ) - goto write_error; - } - } - if (!feof (fpin)) - goto read_error; - } - - } - - for (p=hdr; hdrlen; p++, hdrlen--) { - if ( putc (*p, fpout) == EOF ) - goto write_error; - } - /* standard packet or last segment of partial length encoded packet */ - for (; pktlen; pktlen--) { - c = getc (fpin); - if (c == EOF) - goto read_error; - if ( putc (c, fpout) == EOF ) - goto write_error; - } - - - if ( fclose (fpout) ) - log_error ("error closing `%s': %s\n", outname, strerror (errno)); - return 0; - - write_error: - log_error ("error writing `%s': %s\n", outname, strerror (errno)); - fclose (fpout); - return 2; - - read_error: { - int save = errno; - fclose (fpout); - errno = save; - } - return -1; -} - - - -static int -do_split (const char *fname, FILE *fp) -{ - int c, ctb, pkttype; - unsigned long pktlen = 0; - int partial = 0; - unsigned char header[20]; - int header_idx = 0; - - ctb = getc (fp); - if (ctb == EOF) - return 3; /* ready */ - header[header_idx++] = ctb; - - if( !(ctb & 0x80) ) { - log_error("invalid CTB %02x\n", ctb ); - return 1; - } - if ( (ctb & 0x40) ) { /* new CTB */ - pkttype = (ctb & 0x3f); - if( (c = getc (fp)) == EOF ) - return -1; - header[header_idx++] = c; - - if( c < 192 ) - pktlen = c; - else if( c < 224 ) { - pktlen = (c - 192) * 256; - if( (c = getc (fp)) == EOF ) - return -1; - header[header_idx++] = c; - pktlen += c + 192; - } - else if( c == 255 ) { - if (read_u32 (fp, &pktlen)) - return -1; - header[header_idx++] = pktlen >> 24; - header[header_idx++] = pktlen >> 16; - header[header_idx++] = pktlen >> 8; - header[header_idx++] = pktlen; - } - else { /* partial body length */ - pktlen = c; - partial = 1; - } - } - else { - int lenbytes; - - pkttype = (ctb>>2)&0xf; - lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); - if( !lenbytes ) { - pktlen = 0; /* don't know the value */ - if( pkttype == PKT_COMPRESSED ) - partial = 3; - else - partial = 2; /* the old GnuPG partial length encoding */ - } - else { - for( ; lenbytes; lenbytes-- ) { - pktlen <<= 8; - if( (c = getc (fp)) == EOF ) - return -1; - header[header_idx++] = c; - - pktlen |= c; - } - } - } - - return write_part (fname, fp, pktlen, pkttype, partial, - header, header_idx); -} - - -static void -split_packets (const char *fname) -{ - FILE *fp; - int rc; - - if (!fname || !strcmp (fname, "-")) { - fp = stdin; - fname = "-"; - } - else if ( !(fp = fopen (fname,"rb")) ) { - log_error ("can't open `%s': %s\n", fname, strerror (errno)); - return; - } - - while ( !(rc = do_split (fname, fp)) ) - ; - if ( rc > 0 ) - ; /* error already handled */ - else if ( ferror (fp) ) - log_error ("error reading `%s': %s\n", fname, strerror (errno)); - else - log_error ("premature EOF while reading `%s'\n", fname ); - - if ( fp != stdin ) - fclose (fp); -} - diff --git a/tools/lspgpot b/tools/lspgpot deleted file mode 100755 index 8dc9c3047..000000000 --- a/tools/lspgpot +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# lspgpot - script to extract the ownertrust values -# from PGP keyrings and list them in GnuPG ownertrust format. -# -# 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. - -../g10/gpg --dry-run --with-fingerprint --with-colons $* | awk ' -BEGIN { FS=":" - printf "# Ownertrust listing generated by lspgpot\n" - printf "# This can be imported using the command:\n" - printf "# ggp --import-ownertrust\n\n" } -$1 == "fpr" { fpr = $10 } -$1 == "rtv" && $2 == 1 && $3 == 2 { printf "%s:3:\n", fpr; next } -$1 == "rtv" && $2 == 1 && $3 == 5 { printf "%s:4:\n", fpr; next } -$1 == "rtv" && $2 == 1 && $3 == 6 { printf "%s:5:\n", fpr; next } -' - diff --git a/tools/mail-signed-keys b/tools/mail-signed-keys deleted file mode 100755 index 80fbb3481..000000000 --- a/tools/mail-signed-keys +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/sh -# Copyright (C) 2000, 2001 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 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. - -# FIXME: Add --dry-run, use only valid email addreses, extract only given keys - -dryrun=0 -if [ "$1" = "--dry-run" ]; then - dryrun=1 - shift -fi - -if [ -z "$1" -o -z "$2" -o -z "$3" ]; then - echo "usage: mail-signed-keys keyring signedby signame" >&2 - exit 1 -fi - -signame="$3" - -if [ ! -f $1 ]; then - echo "mail-signed-keys: '$1': no such file" >&2 - exit 1 -fi - -[ -f '.#tdb.tmp' ] && rm '.#tdb.tmp' -ro="--homedir . --no-options --trustdb-name=./.#tdb.tmp --dry-run --lock-never --no-default-keyring --keyring $1" - -signedby=`gpg $ro --list-keys --with-colons $2 \ - 2>/dev/null | awk -F: '$1=="pub" {print $5; exit 0}'` - -if [ -z "$signedby" ]; then - echo "mail-signed-keys: '$2': no such signator" >&2 - exit 1 -fi - -if [ "$dryrun" = "0" ]; then - echo "About to send the the keys signed by $signedby" >&2 - echo -n "to their owners. Do you really want to do this? (y/N)" >&2 - read - [ "$REPLY" != "y" -a "$REPLY" != "Y" ] && exit 0 -fi - -gpg $ro --check-sigs --with-colons 2>/dev/null \ - | awk -F: -v signedby="$signedby" -v gpgopt="$ro" \ - -v dryrun="$dryrun" -v signame="$signame" ' -BEGIN { sendmail="/usr/lib/sendmail -oi -t " } -$1 == "pub" { nextkid=$5; nextuid=$10 - if( uidcount > 0 ) { myflush() } - kid=nextkid; uid=nextuid; next - } -$1 == "uid" { uid=$10 ; next } -$1 == "sig" && $2 == "!" && $5 == signedby { uids[uidcount++] = uid; next } -END { if( uidcount > 0 ) { myflush() } } - -function myflush() -{ - if ( kid == signedby ) { uidcount=0; return } - print "sending key " substr(kid,9) " to" | "cat >&2" - for(i=0; i < 1; i++ ) { - print " " uids[i] | "cat >&2" - if( dryrun == 0 ) { - if( i == 0 ) { - printf "To: %s", uids[i] | sendmail - } - else { - printf ",\n %s", uids[i] | sendmail - } - } - } - if(dryrun == 0) { - printf "\n" | sendmail - print "Subject: I signed your key " substr(kid,9) | sendmail - print "" | sendmail - print "Hi," | sendmail - print "" | sendmail - print "Here you get back the signed key." | sendmail - print "Please send it yourself to a keyserver." | sendmail - print "" | sendmail - print "Peace," | sendmail - print " " signame | sendmail - print "" | sendmail - cmd = "gpg " gpgopt " --export -a " kid " 2>/dev/null" - while( (cmd | getline) > 0 ) { - print | sendmail - } - print "" | sendmail - close(cmd) - close( sendmail ) - } - uidcount=0 -} -' - - - - - - - - - - - - - - - diff --git a/tools/mk-tdata.c b/tools/mk-tdata.c deleted file mode 100644 index dcfa859f1..000000000 --- a/tools/mk-tdata.c +++ /dev/null @@ -1,43 +0,0 @@ -/* mk-tdata.c - Create some simple random testdata - * Copyright (C) 1998, 1999, 2000, 2001 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 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. - */ - -#include -#include -#include -#include - - -#ifndef RAND_MAX /* for SunOS */ - #define RAND_MAX 32767 -#endif - -int -main(int argc, char **argv) -{ - int i, c; - int limit =0; - - limit = argc > 1 ? atoi(argv[1]) : 0; - - srand(getpid()); - - for(i=0; !limit || i < limit; i++ ) { - #ifdef HAVE_RAND - c = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); - #else - c = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); - #endif - putchar(c); - } - return 0; -} - diff --git a/tools/mpicalc.c b/tools/mpicalc.c deleted file mode 100644 index 2817c9932..000000000 --- a/tools/mpicalc.c +++ /dev/null @@ -1,390 +0,0 @@ -/* mpitest.c - test the mpi functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This is an RPN calculator; values must be given in hex. - * Operation is like dc(1) except that the input/output radix is - * always 16 and you can use a '-' to prefix a negative number. - * Addition operators: ++ and --. All operators must be delimited by a blank - * - * - * 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 -#include -#include -#include - -#include "util.h" -#include "mpi.h" -#include "i18n.h" - -#define STACKSIZE 100 -static MPI stack[STACKSIZE]; -static int stackidx; - - -const char * -strusage( int level ) -{ - const char *p; - switch( level ) { - case 10: - case 0: p = "mpicalc - v" VERSION "; " - "Copyright 1997 Werner Koch (dd9jn)" ; break; - case 13: p = "mpicalc"; break; - case 14: p = VERSION; break; - case 1: - case 11: p = "Usage: mpicalc (-h for help)"; - break; - case 2: - case 12: p = - "\nSyntax: mpicalc [options] [files]\n" - "MPI RPN calculator\n"; - break; - default: p = default_strusage(level); - } - return p; -} - - -static void -i18n_init(void) -{ - #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif - bindtextdomain( PACKAGE, G10_LOCALEDIR ); - textdomain( PACKAGE ); - #endif -} - - -static void -do_add(void) -{ - if( stackidx < 2 ) { - fputs("stack underflow\n",stderr); - return; - } - mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; -} - -static void -do_sub(void) -{ - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; -} - -static void -do_inc(void) -{ - if( stackidx < 1 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 ); -} - -static void -do_dec(void) -{ - if( stackidx < 1 ) { - fputs("stack underflow\n", stderr); - return; - } - /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */ -} - -static void -do_mul(void) -{ - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; -} - -static void -do_mulm(void) -{ - if( stackidx < 3 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_mulm( stack[stackidx-3], stack[stackidx-3], - stack[stackidx-2], stack[stackidx-1] ); - stackidx -= 2; -} - -static void -do_div(void) -{ - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; -} - -static void -do_rem(void) -{ - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] ); - stackidx--; -} - -static void -do_powm(void) -{ - MPI a; - if( stackidx < 3 ) { - fputs("stack underflow\n", stderr); - return; - } - a= mpi_alloc(10); - mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] ); - mpi_free(stack[stackidx-3]); - stack[stackidx-3] = a; - stackidx -= 2; -} - -static void -do_inv(void) -{ - MPI a = mpi_alloc(40); - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_invm( a, stack[stackidx-2], stack[stackidx-1] ); - mpi_set(stack[stackidx-2],a); - mpi_free(a); - stackidx--; -} - -static void -do_gcd(void) -{ - MPI a = mpi_alloc(40); - if( stackidx < 2 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] ); - mpi_set(stack[stackidx-2],a); - mpi_free(a); - stackidx--; -} - -static void -do_rshift(void) -{ - if( stackidx < 1 ) { - fputs("stack underflow\n", stderr); - return; - } - mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 ); -} - - -int -main(int argc, char **argv) -{ - static ARGPARSE_OPTS opts[] = { - {0} }; - ARGPARSE_ARGS pargs; - int i, c; - int state = 0; - char strbuf[1000]; - int stridx=0; - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags = 0; - - i18n_init(); - while( arg_parse( &pargs, opts) ) { - switch( pargs.r_opt ) { - default : pargs.err = 2; break; - } - } - if( argc ) - usage(1); - - - for(i=0; i < STACKSIZE; i++ ) - stack[i] = NULL; - stackidx =0; - - while( (c=getc(stdin)) != EOF ) { - if( !state ) { /* waiting */ - if( isdigit(c) ) { - state = 1; - ungetc(c, stdin); - strbuf[0] = '0'; - strbuf[1] = 'x'; - stridx=2; - } - else if( isspace(c) ) - ; - else { - switch(c) { - case '+': - if( (c=getc(stdin)) == '+' ) - do_inc(); - else { - ungetc(c, stdin); - do_add(); - } - break; - case '-': - if( (c=getc(stdin)) == '-' ) - do_dec(); - else if( isdigit(c) || (c >='A' && c <= 'F') ) { - state = 1; - ungetc(c, stdin); - strbuf[0] = '-'; - strbuf[1] = '0'; - strbuf[2] = 'x'; - stridx=3; - } - else { - ungetc(c, stdin); - do_sub(); - } - break; - case '*': - do_mul(); - break; - case 'm': - do_mulm(); - break; - case '/': - do_div(); - break; - case '%': - do_rem(); - break; - case '^': - do_powm(); - break; - case 'I': - do_inv(); - break; - case 'G': - do_gcd(); - break; - case '>': - do_rshift(); - break; - case 'i': /* dummy */ - if( !stackidx ) - fputs("stack underflow\n", stderr); - else { - mpi_free(stack[stackidx-1]); - stackidx--; - } - break; - case 'd': /* duplicate the tos */ - if( !stackidx ) - fputs("stack underflow\n", stderr); - else if( stackidx < STACKSIZE ) { - mpi_free(stack[stackidx]); - stack[stackidx] = mpi_copy( stack[stackidx-1] ); - stackidx++; - } - else - fputs("stack overflow\n", stderr); - break; - case 'c': - for(i=0; i < stackidx; i++ ) - mpi_free(stack[i]), stack[i] = NULL; - stackidx = 0; - break; - case 'p': /* print the tos */ - if( !stackidx ) - puts("stack is empty"); - else { - mpi_print(stdout, stack[stackidx-1], 1 ); - putchar('\n'); - } - break; - case 'f': /* print the stack */ - for( i = stackidx-1 ; i >= 0; i-- ) { - printf("[%2d]: ", i ); - mpi_print(stdout, stack[i], 1 ); - putchar('\n'); - } - break; - default: - fputs("invalid operator\n", stderr); - } - } - } - else if( state == 1 ) { /* in a number */ - if( !isxdigit(c) ) { /* store the number */ - state = 0; - ungetc(c, stdin); - if( stridx < 1000 ) - strbuf[stridx] = 0; - - if( stackidx < STACKSIZE ) { - if( !stack[stackidx] ) - stack[stackidx] = mpi_alloc(10); - if( mpi_fromstr(stack[stackidx], strbuf) ) - fputs("invalid number\n", stderr); - else - stackidx++; - } - else - fputs("stack overflow\n", stderr); - } - else { /* store digit */ - if( stridx < 999 ) - strbuf[stridx++] = c; - else if( stridx == 999 ) { - strbuf[stridx] = 0; - fputs("string too large - truncated\n", stderr); - stridx++; - } - } - } - - } - for(i=0; i < stackidx; i++ ) - mpi_free(stack[i]); - return 0; -} - - diff --git a/tools/ring-a-party b/tools/ring-a-party deleted file mode 100755 index 1993e2732..000000000 --- a/tools/ring-a-party +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/sh -# ring-a-party - print a keyring suitable for a key signing party -# Copyright (C) 2000, 2001 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 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. - -if [ $# -lt 1 ]; then - echo "usage: ring-a-party keyring [headerline]" >&2 - exit 1 -fi - -keyring="$1" -hdrline="$1" -if [ $# -gt 1 ]; then - hdrline="$2" -fi - -if [ ! -f $keyring ]; then - echo "ring-a-party: '$keyring': no such file" >&2 - exit 1 -fi - -echo "ring-a-party: output will be written to 'a.pub'" >&2 - - -gpg --dry-run --with-fingerprint --with-colons $keyring \ - | gawk -v "KEYRING=$hdrline" ' -BEGIN { FS=":" - algos[1] = "RSA"; - algos[16] = "ElGamal"; - algos[17] = "DSA"; - any = 0; - lines = -1; - page = 0; - now = strftime("%b %d %H:%M %Y"); - } -END { - if (any) myflush(); -} -$1 == "pub" { - if( any ) myflush(); - uidcount = 0; - signencrypt = 0; - uids[uidcount++] = $10; - nbits = $3; - keyid = substr($5,9); - created = $6; - expires = $7; - algostr = mapalgo($4); - if( $4 == 20 || $4 == 1 ) signencrypt = 1; - any = 1; - } -$1 == "fpr" { fpr = $10 } -$1 == "uid" { uids[uidcount++] = $10 } -$1 == "sub" { if( $4 != 17 && $4 != 3 ) signencrypt=1 } - -function myflush() -{ - # fixme: take lines to print here into account - if( lines > 45 || lines == -1 ) { - if( lines != -1 ) printf "\f"; - page++; - printf "%s %-50.50s Page %d\n\n", now, KEYRING, page ; - printf " Type Bits KeyID Created Expires Algorithm Use\n\n"; - lines = 1; - } - printf "[ ] pub %04d 0x%s %10s %10s %-10s %15s\n", - nbits, keyid, created, expires == ""? "----------":expires, algostr, - signencrypt == 1? "Sign & Encrypt":"Sign only"; - length(fpr) == 40 ? printfpr20( fpr ) : printfpr16( fpr ); - lnes += 2; - for( i=0; i < uidcount; i++ ) { - printf "( ) uid %s\n", uids[i]; - lines++; - } - printf "\n\n"; - lines += 2; -} - -function mapalgo( no ) -{ - if( no in algos ) - return algos[no]; - return sprintf( "algoID=%ds", no ); -} - - -function printfpr16( s ) -{ - printf " f16 Fingerprint16 ="; - for(i=0; i < 16; i++ ) { - if( i == 8 ) printf " "; - printf " %s", substr( s, i*2+1, 2 ); - } - printf "\n" -} - -function printfpr20( s ) -{ - printf " f20 Fingerprint20 ="; - for(i=0; i < 10; i++ ) { - if( i == 5 ) printf " "; - printf " %s", substr( s, i*4+1, 4 ); - } - printf "\n" -} - -' | tee a.pub | gpg --print-mds - - - - diff --git a/tools/shmtest.c b/tools/shmtest.c deleted file mode 100644 index fceade1e1..000000000 --- a/tools/shmtest.c +++ /dev/null @@ -1,206 +0,0 @@ -/* shmtest.c - * Copyright (C) 1998, 1999, 2000, 2001 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 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. - */ - - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_IPC_H - #include - #include -#endif -#ifdef HAVE_SYS_SHM_H - #include -#endif -#include "util.h" -#include "ttyio.h" -#include "i18n.h" - -#ifdef HAVE_DOSISH_SYSTEM -int main( int argc, char **argv ) -{ - fprintf(stderr, "Sorry, not yet available for DOSish systems\n"); - exit(1); -} -#else - -static int serverpid = -1; - -static void -my_usage(void) -{ - fprintf(stderr, "usage: shmtest gpg-command-line\n"); - exit(1); -} - -const char * -strusage( int level ) -{ - return default_strusage(level); -} - -static void -i18n_init(void) -{ - #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif - bindtextdomain( PACKAGE, G10_LOCALEDIR ); - textdomain( PACKAGE ); - #endif -} - - -static void -do_get_string( int mode, const char *keyword, byte *area, size_t areasize ) -{ - size_t n, len; - char *p=NULL; - int yes=0; - - n = area[0] << 8 | area[1]; - /* fixme: do some sanity checks here */ - if( mode == 1 ) - p = tty_get( keyword ); - else if( mode == 3 ) - p = tty_get_hidden( keyword ); - else - yes = tty_get_answer_is_yes( keyword ); - if( p ) { - len = strlen(p); - memcpy( area+n+2, p, len ); - area[n] = len >> 8; - area[n+1] = len; - m_free(p); - } - else { /* bool */ - area[n] = 0; - area[n+1] = 1; - area[n+2] = yes; - } - area[3] = 1; /* we should better use a semaphore */ - kill( serverpid, SIGUSR1 ); -} - - - -int -main(int argc, char **argv) -{ - void *area = NULL; - size_t areasize = 4096; - int shm_id = -1; - FILE *fp; - char buf[200]; - char *p, *p2; - size_t n; - int i; - - log_set_name("shmtest"); - i18n_init(); - #ifndef USE_SHM_COPROCESSING - log_info("SHM_COPRPOCESSING is not available\n"); - #else - if( argc < 1 ) - my_usage(); - - for(n=0,i=1; i < argc; i++ ) - n += strlen(argv[i]) + 1; - p = m_alloc( 100 + n ); - strcpy( p, "../g10/gpg --status-fd 1 --run-as-shm-coprocess 0"); - for(i=1; i < argc; i++ ) { - strcat(p, " " ); - strcat(p, argv[i] ); - } - - fp = popen( p, "r" ); - m_free( p ); - if( !fp ) - log_error("popen failed: %s\n", strerror(errno)); - - while ( fgets (buf, sizeof (buf) - 1, fp ) != NULL ) { - size_t len = strlen(buf); - if( len >= 9 && !memcmp( buf, "[GNUPG:] ", 9 ) ) { - int word=0; - int is_info = 0, is_get = 0; - - for( p = strtok(buf+9, " \n"); p ; p = strtok(NULL, " \n")) { - word++; - if( word==1 && !strcmp(p,"SHM_INFO") ) { - if( !area ) - is_info=1; - else - log_error("duplicate SHM_INFO ignored\n" ); - } - else if( is_info && (p2 = strchr(p, '=' )) ) { - int val; - *p2++ = 0; - val = atoi(p2); /* should be atou() for some values */ - if( !strcmp(p, "pv" ) ) { - if( atoi(p2) != 1 ) - log_fatal("invalid protocol version %d\n", val ); - is_info = 2; - } - else if( !strcmp(p, "pid" ) ) - serverpid = val; - else if( !strcmp(p, "shmid" ) ) - shm_id = val; - } - else if( word == 1 && !strcmp(p,"SHM_GET") ) - is_get = 1; - else if( word == 1 && !strcmp(p,"SHM_GET_BOOL") ) - is_get = 2; - else if( word == 1 && !strcmp(p,"SHM_GET_HIDDEN") ) - is_get = 3; - else if( word == 2 && is_get ) { - do_get_string( is_get, p, area, areasize ); - break; - } - else if( word == 1 ) - log_info("Status: %s\n", p); - } - if( is_info ) { - if( is_info < 2 ) - log_fatal("SHM info without protocol version\n"); - if( serverpid == -1 ) - log_fatal("SHM info without server's pid\n"); - if( shm_id == -1 ) - log_fatal("SHM info without id\n"); - log_info("Shared memory info: server=%d shm_id=%d\n", - serverpid, shm_id); - area = shmat( shm_id, 0, 0 ); - if( area == (void*)-1 ) - log_fatal("attach to shared memory failed: %s\n", - strerror(errno)); - } - } - else - fputs (buf, stdout); - } - - - if( pclose(fp) ) - log_error("pclose failed\n"); - - return 0; - #endif -} - - -#endif diff --git a/tools/signmany b/tools/signmany deleted file mode 100644 index 9b453d436..000000000 --- a/tools/signmany +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -if [ ! -f ./$1 ]; then - echo "usage: signmany keyring" >&2 - exit 1 -fi - - -ro="--trustdb-name=./tdb.tmp --no-default-keyring --secret-keyring /floppy/secring.gpg --keyring ./$1" - -kis=`gpg $ro --fast-list-mode --list-keys --with-colons \ - | awk -F: '$1=="pub" { print $5 }'` - -for k in $kis; do - echo "Keyid: $k" - answer=A - while [ "$answer" = "A" ]; do - gpg $ro --lock-never --sign-key $k - answer="" - while [ "$answer" = "" ]; do - read -p 'Okay, Again or Quit? (O/A/Q) ' - case "$REPLY" in - o|O) answer=O ;; - a|A) answer=A ;; - q|Q) answer=Q ;; - *) ;; - esac - done - done - [ "$answer" = "Q" ] && break -done - - diff --git a/util/ChangeLog b/util/ChangeLog deleted file mode 100644 index e9caf465a..000000000 --- a/util/ChangeLog +++ /dev/null @@ -1,1021 +0,0 @@ -2002-10-17 David Shaw - - * http.c (connect_server): Try all A records for names with - multiple addresses until one answers for both MINGW32 and not - MINGW32. - -2002-10-10 David Shaw - - * http.c (connect_server): Properly handle a single A record that - fails connect(). - -2002-10-03 David Shaw - - * logger.c (g10_log_warning, log_set_strict): Add new log_warning - logger command which can be switched between log_info and - log_error via log_set_strict. - -2002-09-24 David Shaw - - * http.c (connect_server): Try all A records for names with - multiple addresses until one answers (not MINGW32). - -2002-09-16 Werner Koch - - * w32reg.c (read_w32_registry_string): Fallback to HLM. - -2002-09-12 Stefan Bellon - - * fileutil.c (make_filename): Removed variable for RISC OS to - avoid compiler warning. - - * secmem.c: Removed static variable for RISC OS to avoid - compiler warning. - -2002-09-11 Werner Koch - - * simple-gettext.c: Disable charset mappings. We do it now when - installing the files. - -2002-09-09 Werner Koch - - * w32reg.c (read_w32_registry_string): Handle REG_EXPAND_SZ. - Suggested by Ryan Malayter. - - * strgutil.c (ascii_strcasecmp): Replaced by code from gnulib. - (ascii_strncasecmp): New. - -2002-09-02 Werner Koch - - * simple-gettext.c (set_gettext_file): Make sure that we only use - backslashes. - - * strgutil.c (set_native_charset): Allow NULL as argument to use - nl_langinfo for selection. Mapped latin-15 to latin-1. - -2002-08-30 Werner Koch - - * iobuf.c (block_filter): Removed the assert, so that one can pass - the first character of a message and use the block filter for - non partial length encoded packets. - -2002-08-06 Stefan Bellon - - * ttyio.c [__riscos__]: Moved low-level RISC OS stuff to riscos.c. - * riscos.c: Use new SWI calling mechanism of UnixLib. - -2002-08-03 Stefan Bellon - - * secmem.c (init_pool, secmem_term): Changed #if to #ifdef in - order to avoid warning with RISC OS' Norcroft C. - -2002-07-25 David Shaw - - * secmem.c: "Warning" -> "WARNING" - -2002-07-05 Werner Koch - - * argparse.c (initialize): We better exit after a read error so - that we don't run into an endless loop when reading a directory. - Noted by Andrew Suffield. - -2002-07-01 David Shaw - - * argparse.c (optfile_parse): Fix variable typo - 'p2' should be - 'p' :) - -2002-06-29 Werner Koch - - * argparse.c (optfile_parse): Renamed an auto I to P2 to avoid - shadowing warning. - -2002-06-21 Stefan Bellon - - * riscos.c (riscos_global_defaults): New. - -2002-06-20 Stefan Bellon - - * riscos.c (riscos_set_filetype_by_number, riscos_set_filetype): - New. Set RISC OS filetype according to MIME type. - -2002-06-14 David Shaw - - * strgutil.c (pop_strlist): New function to pop the head off of a - strlist. - -2002-06-05 Timo Schulz - - * fileutil.c (is_file_compressed): Corrected the magic values - for bzip2 and gzip. Noted by David. - -2002-05-22 Werner Koch - - * fileutil.c (compare_filenames): Replaced stricmp by strcasecmp. - * miscutil.c (answer_is_yes_no_quit,answer_is_yes_no_default): Ditto. - - * strgutil.c (strncasecmp): New. - (memicmp): Removed. - -2002-05-10 Stefan Bellon - - * memory.c (add_entry) [M_DEBUG]: Added some missing EXTRA_ALIGN. - (free_entry) [M_DEBUG]: Free secure memory via secmem_free. - (alloc_secure): Malloc at least 1 byte. - (realloc) [M_GUARD]: Added missing FNAMEARG to function call. - - * logger.c (g10_log_bug0) [__riscos__]: Make use of first - g10_log_bug0 function for later Norcroft compiler. - - * riscos.c: Added stdlib.h include. - -2002-05-04 Werner Koch - - * http.c (write_server) [__MINGW32__]: Replaced WriteFile by send - because sockets don't work with WriteFile under NT anymore. - -2002-05-03 David Shaw - - * argparse.c (optfile_parse): Remove quotes only if they totally - enclose the string, and do not occur within the string. This - makes specifying a program under Win32 easier when you need quotes - around part of a string, but not around the whole string. - -2002-05-02 Werner Koch - - * memory.c (alloc): Malloc at least 1 byte. Noted by Winona Brown. - -2002-04-23 David Shaw - - * miscutil.c: New function answer_is_yes_no_default() to give a - default answer. - -2002-04-22 Stefan Bellon - - * riscos.c (riscos_open, riscos_fopen, riscos_fstat, set_filetype): - Removed as they're not needed anymore. - - * iobuf.c (direct_open) [__riscos__]: Don't allow opening of - directories. - -2002-04-08 Werner Koch - - Fixed filename of last entry. - -2002-03-29 David Shaw - - * miscutil.c (print_string, utf8_to_native): If a delimiter is - used, then quote the backslash character as well. Problem noted - by Rainer Perske. - -2002-03-15 Werner Koch - - * argparse.c (optfile_parse): Fixed missing argument handling. - -2002-02-28 Timo Schulz - - * http.c (write_server): Convert integer to a HANDLE for W32. - -2002-01-27 David Shaw - - * iobuf.c (iobuf_fdopen, iobuf_sockopen): Do not cache fdopened - fds on close. - -2002-01-08 Werner Koch - - * secmem.c (print_warn): Print a pointer to the FAQ. - -2002-01-05 Werner Koch - - * argparse.c (default_strusage): Set default copyright date to 2002. - -2002-01-02 Stefan Bellon - - * iobuf.c [__riscos__]: Updated include file name. - - * fileutil.c [__riscos__]: Ditto. - - * ttyio.d [__riscos__]: Ditto. - - * riscos.c [__riscos__]: Ditto. Added debugging code and - unified error messages. - -2001-12-27 David Shaw - - * errors.c (g10_errstr): Added G10ERR_KEYSERVER - -2001-12-27 Werner Koch - - * simple-gettext.c [MINGW32]: Fixed last changed. - -2001-12-22 Stefan Bellon - - * memory.c (realloc): Fixed realloc not working when M_GUARD is - defined and first parameter is NULL. - -2001-12-22 Timo Schulz - - * fileutil.c (is_file_compressed): New. - -2001-12-19 Werner Koch - - * simple-gettext.c, w32reg.c [CYGWIN32]: Allow to use this file - -2001-10-11 Werner Koch - - * http.c (do_parse_uri): Changed initialization of the port number - so that it does also work with x-hkp. By David Shaw. - -2001-09-19 Werner Koch - - * w32reg.c (get_root_key): New. - (read_w32_registry_string): Use it here. - (write_w32_registry_string): New. Contributed by Timo. - - * iobuf.c (iobuf_ioctl): New command to disable fd - caching. Implemented no_cache flag where needed. - (iobuf_sockopen): Always set no_cache flag. - - * strgutil.c (utf8_to_native): Add a delim arg and changed all - callers. Make sure that quoting is done when translation is - disabled. - * miscutil.c (print_utf8_string2): New. - -2001-09-17 Werner Koch - - * miscutil.c (print_string): Use explicit ranges and not iscntrl(). - (make_printable_string): Ditto. - -2001-09-07 Werner Koch - - * strgutil.c (strsep): New, taken from glibc 2.2.1. - -2001-09-03 Werner Koch - - * miscutil.c (strtimestamp,asctimestamp): Avoid trigraphs. - -2001-08-21 Stefan Bellon - - * riscos.c [__riscos__] (close_fds): Fixed possible endless loop. - -2001-08-20 Werner Koch - - Applied patches from Stefan Bellon to support - RISC OS. Nearly all of these patches are identified by the - __riscos__ macro. - * secmem.c [__riscos__]: Disabled secure memory stuff. - * dotlock.c, ttyio.c [__riscos__]: Adapted for RISC OS - * fileutil.c, iobuf.c: Adapted for RISC OS; mainly replaced - hardcoded path separators with EXTSEP_S like macros. - * http.c (send_request): Use macros for the env-var name. - * logger.c [__riscos__]: Do an fflush at the end of each log - function. - * memory.c [__riscos__]: Minor patches - * riscos.c (set_filetype): New. - - * secmem.c (lock_pool): Under HPUX mlock is broken but we might - have plock, so we use this to lock the entire process. By Albert - Chin. - -2001-07-03 Werner Koch - - * strgutil.c (utf8_to_native): Fixed printing of invalid utf-8 - characters. Thomas Roessler reported that the escaping didn't work - correct. - -2001-06-12 Werner Koch - - * strgutil.c (ascii_memistr,ascii_isupper,ascii_islower, - ascii_toupper,ascii_tolower, ascii_strcasecmp, ascii_memcasecmp): New. - (set_native_charset): Use ascii_strcasecmp() - * fileutil.c (compare_filenames): Ditto - * miscutil.c (answer_is_yes): Ditto. - (answer_is_yes_no_quit): Ditto. - -2001-06-06 Werner Koch - - * strgutil.c (vasprintf) [__MINGW32__]: New. Taken from libiberty. - * ttyio.c (tty_printf) [__MINGW32__]: Replaced the sprintf with - the new vasprintf. - -2001-06-05 Werner Koch - - * dotlock.c (make_dotlock): Typo fixes. - -2001-05-25 Werner Koch - - * ttyio.c (do_get): Fixed a serious format string bug. Thanks to - fish stiqz. - -2001-05-23 Werner Koch - - * secmem.c (EPERM): Try to work around a Slackware problem. - -2001-05-05 Werner Koch - - * http.c (http_start_data): Flush before writing. - (http_wait_response): No need to flush here. - -2001-04-27 Werner Koch - - * memory.c (out_of_core): Print an explanation on reasons why - secret memory can get exhausted. - -2001-04-23 Werner Koch - - * http.c (http_wait_response): Implement new flag to inhibit the - TCP shutdown. - -2001-04-20 Werner Koch - - * http.c (http_start_data): Use write_server and not the iobuf - stuff. I wonder why we are at all using write_server - shouldn't - it be handled by iobuf? - - * strgutil.c (set_native_charset): Allow utf-8 by introducing the - new no_translation variable. - (native_to_utf8): Handle no_translation. - (utf8_to_native): Ditto. - -2001-04-19 Werner Koch - - * miscutil.c (asctimestamp): Handle negative times. We must do - this because Windoze segvs on negative times passed to gmtime(). - (strtimestamp): Ditto. - -2001-04-14 Werner Koch - - * strgutil.c (utf8_to_native): Fixed a segv. Thanks to Keith Clayton. - -2001-04-13 Werner Koch - - * iobuf.c (iobuf_fopen): Removed because it is not used and - furthermore mode is ignored for an fname of "-". Suggested by - Florian Weimer. - -2001-04-02 Werner Koch - - * iobuf.c (translate_file_handle): New. Use this function - everywhere in this file. - (iobuf_translate_file_handle): Always use the osfhandle stuff here - because callers don't know the implementation details of iobuf and - they expect that the handles are translated. - -2001-03-29 Werner Koch - - * miscutil.c (answer_is_yes): An empty string does now return no. - (answer_is_yes_no_quit): Likewise. - - * iobuf.c (iobuf_close): Burn the buffers. - -2001-03-26 Werner Koch - - * ttyio.c: Define TERMDEVICE depending on OS. - - * http.c (http_start_data): send a CRLF and not just a LF. - Pointed out by Steven Murdoch. - -2001-03-13 Werner Koch - - * iobuf.c (iobuf_sockopen): New. - (sock_filter) [__MINGW32__]: New. - (iobuf_ioctl): New. - (file_filter): Implemented keep_open mode. - * http.c (http_open, http_wait_response): Replaced iobuf_fdopen by - iobuf_sockopen and use an iobuf_ioctl to avoid the dup(). - (deinit_sockets, init_sockets) [__MINGW32__]: New. - (connect_server, write_server): Add code to work with W32 sockets. - -2001-03-12 Werner Koch - - * strgutil.c (check_trailing_chars,check_trailing_ws): New. - -2001-03-08 Werner Koch - - * argparse.c (default_strusage): Changed year of printed copyright - to 2001. - - * iobuf.c (fd_cache_invalidate, fd_cache_close, fd_cache_open): New. - (direct_open): Invalidate the fd_cache for read access. - (file_filter): Cache the close here. - (iobuf_open): Use new my_fopen_ro macro to try the cache first. - -2001-03-07 Werner Koch - - * iobuf.c: Made the old stdio file handling cpp conditional - controlled by FILE_FILTER_USES_STDIO and added a new - open/read/close based one. We don't need the stdio buffering - becuase we are doing our own buffering anyway. And it is a - prerequesite to allow the use of ReadFile et al for W32 which in - turn is needed to make the http stuff work there. The new W32 - stuff has also been implemented. Minor changes to all open functions. - (direct_open): New. - (file_filter): Core of the new read/write handling. - (iobuf_get_filelength): Use W32 API function here. But it is - currently limited to 2GB files. - (iobuf_seek): Ditto. - -2001-03-01 Werner Koch - - * errors.c (g10_errstr): New codes UNU_SECKEY and UNU_PUBKEY. - -2000-12-28 Werner Koch - - * dotlock.c: Made all_lockfiles volatile. - (remove_lockfiles): Made public. - -2000-11-30 Werner Koch - - * iobuf.c (iobuf_translate_file_handle): New. - (iobuf_open, iobuf_create): Use it for special filenames - -2000-11-11 Paul Eggert - - * iobuf.c (iobuf_get_filelength): Now returns off_t, not u32. - Remove kludges to worry about large files; the callers check - for files that are too large, and they should already be doing - the right thing in an implementation-independent way. - (fopen, fstat): Remove macros. - - * iobuf.c (iobuf_set_limit, iobuf_tell, iobuf_seek): - Use off_t, not ulong, for file offsets. - (): Include if needed. - (LONG_MAX, LONG_MIN): Define a substitute if needed. - (fseeko): Define a substitute if needed. - - * iobuf.c (iobuf_seek): Do not use %lu to report file - -2000-11-09 Werner Koch - - * iobuf.c (iobuf_enable_special_filenames): New. - (check_special_filename): New. - (iobuf_open): check for special filenames. - (iobuf_create): Ditto. - -2000-10-23 Werner Koch - - * secmem.c (lock_pool): Don't print warning for Windows. - -2000-10-16 Werner Koch - - * secmem.c (lock_pool): Fixed error checking for Linux. - By James Troup. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch - - * miscutil.c (answer_is_yes_no_quit): Swapped order of yes/no test - so that no is returned for an empty input. By David Champion. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch - - * iobuf.c: Use fopen64 insead of fopen when available. - (iobuf_get_filelength): Use fstat64 when available but return - 2^32-1 if the file is larger than this value. - -Wed Sep 6 14:59:09 CEST 2000 Werner Koch - - * secmem.c (secmem_realloc): check for failed secmem_malloc. By - Matt Kraai. - - * strgutil.c (utf8_to_native): Fixed null ptr problem. By - Giampaolo Tomassoni. - -Thu Jul 27 10:02:38 CEST 2000 Werner Koch - - * iobuf.c: Use setmode() at several places to set stdin and stdout - to binary mode for MSDOS based systems - - * iobuf.c (underflow): Initialize dummy_len to keep memory checker happy. - -Fri Jun 9 10:09:52 CEST 2000 Werner Koch - - * ttyio.c: Simulate termios with termios. By Dave Dykstra. - -Thu Jun 8 20:22:00 CEST 2000 Werner Koch - - * secmem.c (lock_pool,secmem_init): Additional check for dropped privs. - -Tue May 30 16:37:55 CEST 2000 Werner Koch - - * iobuf.c (iobuf_cancel): Fix for MSDOS. - -Fri Apr 14 19:37:08 CEST 2000 Werner Koch - - * dotlock.c (disable_dotlock): New. Implmented this in the module. - -2000-03-09 14:04:22 Werner Koch (wk@habibti.openit.de) - - * argparse.c (default_strusage): Changed year of default copyright. - -Tue Mar 7 18:45:31 CET 2000 Werner Koch - - * secmem.c (lock_pool): No more warning for QNX. By Sam Roberts. - -2000-03-02 15:51:04 Werner Koch (wk@habibti.gnupg.de) - - * ttyio.c (tty_print_utf8_string): Oops. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch - - * ttyio.c (tty_print_utf8_string2): New to allow a max output size. - -Wed Feb 23 10:07:57 CET 2000 Werner Koch - - * miscutil.c (asctimestamp): Fix for possible buffer overflow by - large system returned date format string. - -Fri Dec 31 14:08:15 CET 1999 Werner Koch - - * logger.c (log_inc_errorcount): New. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch - - * iobuf.c (iobuf_cancel): Broadcast the new Cancel mesaage to all - filters. - -Mon Nov 22 11:14:53 CET 1999 Werner Koch - - * strgutil.c (strcasecmp): New. - - * secmem.c (pool_is_mmapped): Made volatile. - -Sat Oct 9 20:34:41 CEST 1999 Werner Koch - - * Makefile.am: Removed libtool. - -Fri Oct 8 20:32:01 CEST 1999 Werner Koch - - * w32reg.c: New. - * simple-gettext.c: Use the Registry to locate the mo file. - - * http.c (send_request): Add support for proxys; suggested by - Walter Hofmann. - (http_open_document): Pass flags to http_open. - -Fri Sep 17 12:56:42 CEST 1999 Werner Koch - - - * secmem.c (lock_pool): Check for ENOSYS return my mlock() on - old SCOs. - - * ttyio.c (do_get): Replaced #if __MINGW32__ by #ifdef becuase - gcc 2.95.1 assigns a floating point value (0.2) to this macro, - which in turn can't be used in an expression. - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch - - - * simple-gettext.c: New. - -Wed Sep 1 15:30:44 CEST 1999 Werner Koch - - - * argparse.c (arg_parse): Add standard options to the dump-options - output. - -Tue Aug 31 17:20:44 CEST 1999 Werner Koch - - - * strgutil (utf8_to_native): Implemented. - (check_utf8_string): Removed. - - * miscutil.c (make_printable_string): Fixed possible buffer overflow. - (print_utf8_string): New. - - * ttyio.c (tty_print_utf8_string): New. - -Mon Aug 30 20:38:33 CEST 1999 Werner Koch - - - * secmem.c (pool_okay): declared volatile. - - * miscutil.c (answer_is_yes): Always check for plain "yes". - (answer_is_yes_no_quit): Likewise. - - * dotlock.c (create_dotlock): Fixed segv during cleanup. - -Mon Jul 12 14:55:34 CEST 1999 Werner Koch - - - * argparse.c (initialize): Init ret_xxx. - (optfile_parse): Remove quotes from arguments. - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch - - - * memory.c (membug): Use if either M_DEBUG or M_GUARD is used. - - * miscutil.c (scan_isodatestr): New. - - * logger.c (g10_log_mpidump): Moved to ../mpi/mpicoder.c - (g10_log_print_prefix): Renamed from print_prefix and made global. - - * Makefile.am: Support for libtool. - -Thu Jul 1 12:47:31 CEST 1999 Werner Koch - - - * miscutil.c (make_printable_string): New. - - * strgutil.c (add_to_strlist2,append_to_strlist2): New. - -Tue Jun 29 21:44:25 CEST 1999 Werner Koch - - - * secmem.c (USE_CAPABILITIES): Capabilities support (Remi). - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch - - - * dotlock.c (create_dotlock): s/uts/utsbuf/ cause there an Amdahl - system with the name UTS (Dave Dykstra). - - * secmem.c (DEFAULT_POOLSIZE): Doubled the size. - -Fri Jun 18 00:18:02 CEST 1999 Michael Roth - - * iobuf.c: file_filter() Detection of EOF on terminals - improved/fixed (see Bug #21). - -Mon Jun 14 21:18:54 CEST 1999 Michael Roth - - * ttyio.c: tty_no_terminal() new. - -Sat Jun 5 15:30:33 CEST 1999 Werner Koch - - * strgutil.c (set_native_charset): Support Latin-2 - -Tue Jun 1 16:01:46 CEST 1999 Werner Koch - - * iobuf.c (iobuf_get_real_fname): Made global and now keep a - copy of the name in the iobuf struct. - -Mon May 31 19:41:10 CEST 1999 Werner Koch - - * iobuf.c (file_filter,block_filter): Speed patches (Rmi). - -Thu May 27 09:40:55 CEST 1999 Werner Koch - - * miscutil.c (answer_is_yes_no_quit): New. - -Sun May 23 14:20:22 CEST 1999 Werner Koch - - * dotlock.c: Tweaked to make it compile under mingw32 - * http.c: Disabled for mingw32. - -Sat May 22 22:47:26 CEST 1999 Werner Koch - - * logger.c (log_set_logfile): New. - -Thu May 20 14:04:08 CEST 1999 Werner Koch - - * memory.c (membug): Nanu, there was a const instead of a static. - - * strgutil.c (trim_trailing_chars): New. - -Mon May 17 21:54:43 CEST 1999 Werner Koch - - * logger.c (g10_log_hexdump): Made 2nd arg a const. - -Wed Apr 28 13:03:03 CEST 1999 Werner Koch - - * miscutil.c (asctimestamp): Use nl_langinfo (Gal Quri). - -Sun Apr 18 10:11:28 CEST 1999 Werner Koch - - * argparse.c (store_alias): Disabled becuase it is not used. - - * ttyio.c (tty_batchmode): New - -Sat Mar 20 11:44:21 CET 1999 Werner Koch - - * http.c: Swapped to includes. - -Tue Mar 2 16:44:57 CET 1999 Werner Koch - - * strgutil.c (get_native_charset): New. - -Fri Feb 26 17:55:41 CET 1999 Werner Koch - - * secmem.c (memblock_struct): Force align (Rmi Guyomarch) - -Wed Feb 24 11:07:27 CET 1999 Werner Koch - - * iobuf.c (block_filter): Fixed the oscillating partial packet chunks. - -Fri Feb 19 15:49:15 CET 1999 Werner Koch - - * iobuf.c (iobuf_push_filter2): New to allow transer of context - ownership to the iobuf. Released the context where needed. - -Tue Feb 16 14:10:02 CET 1999 Werner Koch - - * strgutil.c (add_to_strglist): Clear the new flags field - (append_to_strglist): Ditto. - - * dotlock.c (read_lockfile): terminate pidstr (Michael). - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - * dotlock.c (remove_lockfiles): Add cleanup function. - (make_dotlock): Add deadlock check. - - * secmem.c (secmem_malloc): Changed error message. - -Wed Jan 20 21:40:21 CET 1999 Werner Koch - - * http.c (http_wait_response): Moved the shutdown behind the dup - -Wed Jan 20 18:59:49 CET 1999 Werner Koch - - * http.c (send_request): Removed double LF - -Tue Jan 19 19:34:58 CET 1999 Werner Koch - - * * iobuf.c (iobuf_push_filter): Allow filters for temp streams - - (iobuf_write_temp): Ditto. - (iobuf_flush_temp): New. - (iobuf_unget_and_close_temp): Removed. - - * http.c (close_http_document): Renamed to http_close(). - (open_http_document): Renamed to http_open_document(). - (http_open): New. - (http_start_data): New. - (http_wait_response): New. - - -Sun Jan 17 11:04:33 CET 1999 Werner Koch - - * strgutil.c (trim_trailing_ws): New. - -Sat Jan 16 12:03:27 CET 1999 Werner Koch - - * http.c (connect_server): Fixed stupid bug. - -Sat Jan 16 09:27:30 CET 1999 Werner Koch - - * http.c: New - - -Wed Jan 13 14:10:15 CET 1999 Werner Koch - - * iobuf.c (iobuf_fdopen): New. - -Sat Jan 9 16:02:23 CET 1999 Werner Koch - - * secmem.c (lock_pool): add another check that setuid() worked. - (secmem_init): Ditto. - -Thu Jan 7 18:00:58 CET 1999 Werner Koch - - * iobuf.c (iobuf_clear_eof): Removed. - (underflow): Changed the eof handling. - (iobuf_pop_filter): Made static and renamed to pop_filter. - - * iobuf.c (iobuf_read_line): New. - -Sun Jan 3 15:28:44 CET 1999 Werner Koch - - * dotlock.c (make_dotlock): print another informal message. - - (make_dotlock): Removed the cpp checks. - - -Tue Dec 29 14:41:47 CET 1998 Werner Koch - - * secmem.c: Moved unistd.h out of the #ifdef - - * dotlock.c (make_dotlock): Sun has no SYS_NMLN - - * iobuf.c (iobuf_unget_and_close_temp): Reset .start - -Sat Dec 12 18:40:32 CET 1998 Werner Koch - - * argparse.c (arg_pars): fixed opts[i] with negative index. - -Fri Nov 27 21:37:41 CET 1998 Werner Koch - - * dotlock.c: Implemented - -Wed Nov 25 11:30:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_pop_filter): Fixed sigsegv after error. - -Thu Nov 19 07:09:55 1998 Werner Koch - - * miscutil.c (strtimevalue): New. - -Tue Nov 10 10:01:53 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (set_native_charset): New. - (native_to_utf8): Now handles koi8-r. - -Tue Nov 3 16:17:56 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (native_to_utf8): New. - (utf8_to_native): New, but only as a stub. - - * argparse.c (optfile_parse): Trimmed spaces from args. - - -Wed Oct 28 08:01:49 1998 me,,, (wk@tobold) - - * argparse.c (find_long_option): New. - (arg_parse): option=value is now allowed. Add a new internal - option "--dump-options". - -Thu Oct 22 16:25:49 1998 Michael Roth (mroth@nessie.de) - - * fileutil.c (make_basename): New. - (make_dirname): New. - -Wed Oct 21 12:20:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * util.c (iobuf_flush): autoincreasing of a temp. iobuf - (iobuf_temp_with_content): New. - -Tue Oct 13 12:40:13 1998 Werner Koch (wk@isil.d.shuttle.de) - - * util.c (.nofast): set this variable - -Wed Oct 7 19:27:50 1998 Werner Koch (wk@isil.d.shuttle.de) - - * memory.c (m_print_stats): New. - -Tue Oct 6 09:53:56 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (memicmp): Add HAVE_MEMICMP. - -Mon Sep 21 19:45:01 1998 Werner Koch (wk@(none)) - - * secmem.c: New flags to allow suspend/resume of warnings. - -Fri Sep 18 16:25:47 1998 Werner Koch (wk@(none)) - - * secmem.c (lock_pool): Kludge for broken mlock on HPUX 10.20 - -Tue Sep 15 17:52:21 1998 Werner Koch (wk@(none)) - - * miscutil.c (asctimestamp): New. - -Mon Sep 14 09:38:18 1998 Werner Koch (wk@(none)) - - * secmem.c (init_pool): Now mmaps /dev/zero if we do not have MAP_ANON. - -Wed Sep 9 13:52:28 1998 Werner Koch (wk@(none)) - - * ttyio.c (do_get): Ctrl-D is now a valid but special character - -Mon Sep 7 13:52:41 1998 Werner Koch (wk@(none)) - - * iobuf.c (get_real_fname): New and changed file_filter datastructures - and their initialization. - -Tue Aug 11 15:12:35 1998 Werner Koch (wk@(none)) - - * miscutil.c (answer_is_yes): i18ned - -Sat Aug 8 18:35:00 1998 Werner Koch (wk@(none)) - - * ttyio.c (cleanup): New. - -Mon Aug 3 17:06:00 1998 Werner Koch (wk@(none)) - - * secmem.c (MAP_ANON): Add a macro test - -Wed Jul 29 14:53:34 1998 Werner Koch (wk@(none)) - - * ttyio.c (tty_get_answer_is_yes): New. - -Tue Jul 21 10:35:48 1998 Werner Koch (wk@(none)) - - * argparse.c: New option flag to distinguish options and commands. - -Sat Jul 18 19:49:30 1998 Werner Koch (wk@(none)) - - * argparse.c (arg_parse): Added -? as alias for -h - -Thu Jul 9 14:47:20 1998 Werner Koch (wk@isil.d.shuttle.de) - - * secmem.c (secmem_init): Drops setuid if called with 0. - -Tue Jul 7 11:49:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * logger.c (log_set_filename): New. - -Mon Jul 6 09:03:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (append_to_strlist): New. - -Thu Jul 2 15:55:44 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (block_filter): Add writing of OP partial length headers. - -Fri Jun 26 10:38:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ttyio.c (do_get): all iso8859-1 characters are now allowed. - -Thu Jun 25 15:57:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * secmem.c (lock_pool): Removed left over test code. - -Wed Jun 10 07:39:41 1998 Werner Koch,mobil,,, (wk@tobold) - - * fileutil.c (compare_filenames): New. - - * argparse.c (arg_parse): New flag bit 6 to ignore --version - -Thu May 14 16:45:13 1998 Werner Koch (wk@isil.d.shuttle.de) - - * argparse.c (show_help): Add some formatting stuff - -Fri May 8 17:06:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * errors.c (strerror): New if !HAVE_STRERROR - -Mon May 4 19:48:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_read): Code is now faster. - * (iobuf_write): ditto. - -Mon Apr 27 11:01:32 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (memicmp): New. - -Thu Mar 19 11:29:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (memistr): Add const to return and first arg. - -Sat Mar 7 11:54:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * miscutil.c (print_string): New arg delim; changed all callers. - -Thu Mar 5 12:19:30 1998 Werner Koch (wk@isil.d.shuttle.de) - - * errors.c: New strings. - -Thu Mar 5 12:06:31 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_open): A name of "-" now opens stdin. - * fileutil.c (print_fname_stdout, print_fname_stdin): New. - -Fri Feb 27 10:20:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * memory.c (m_is_secure): Removed. - * secmem.c (m_is_secure): Moved to here. - - * secmem.c (secmem_realloc): New. - * memory.c (M_GUARD,EXTRA_ALIGN): New (all functions). - -Thu Feb 26 14:36:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * secmem.c (lock_pool): No error if EAGAIN is returned instead - of EPERM. - -Fri Feb 20 17:43:05 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ttyio.c [MINGW32]: Add support for mingw32. - -Tue Feb 17 19:43:44 1998 Werner Koch (wk@isil.d.shuttle.de) - - * memory.c (dump_table_at_exit): New. - -Mon Feb 16 10:07:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * argparse.c (show_version, show_help, default_strusage): Changed - according to GNU standards. - -Mon Feb 16 08:58:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_peek): New - -Fri Feb 13 19:34:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_seek): Set counters to new offset. - -Fri Feb 13 17:13:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * logger.c (log_set_name, log_get_name): New. - (print_prefix, pgm_name): New, changed all function to make use it. - (log_mpidump): Removed the "DBG" prefix. - (log_hexdump): Ditto. - - * logger.c (printstr): Removed. - -Fri Feb 13 15:14:13 1998 Werner Koch (wk@isil.d.shuttle.de) - - * argparse.c (show_help): New '\v' kludge. - - - - Copyright 1998, 1999, 2000, 2001 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. - - diff --git a/util/Makefile.am b/util/Makefile.am deleted file mode 100644 index a8d40da2d..000000000 --- a/util/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -# 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 - -## Process this file with automake to produce Makefile.in - -INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl - -noinst_LIBRARIES = libutil.a - - -#libutil_a_LDFLAGS = -libutil_a_SOURCES = g10u.c logger.c fileutil.c miscutil.c strgutil.c \ - ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c \ - dotlock.c http.c simple-gettext.c w32reg.c - - -http-test: http.c - gcc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) -g -Wall -DTEST \ - -o http-test http.c libutil.a ../mpi/libmpi.a @INTLLIBS@ - - - diff --git a/util/argparse.c b/util/argparse.c deleted file mode 100644 index 2ca0ff8ff..000000000 --- a/util/argparse.c +++ /dev/null @@ -1,1000 +0,0 @@ -/* [argparse.c wk 17.06.97] Argument Parser for option handling - * 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 - * - * - * Note: This is an independent version of the one in WkLib - */ - -#include -#include -#include -#include -#include - -#include "util.h" -#include "i18n.h" - - -/********************************* - * @Summary arg_parse - * #include - * - * typedef struct { - * char *argc; pointer to argc (value subject to change) - * char ***argv; pointer to argv (value subject to change) - * unsigned flags; Global flags (DO NOT CHANGE) - * int err; print error about last option - * 1 = warning, 2 = abort - * int r_opt; return option - * int r_type; type of return value (0 = no argument found) - * union { - * int ret_int; - * long ret_long - * ulong ret_ulong; - * char *ret_str; - * } r; Return values - * struct { - * int idx; - * const char *last; - * void *aliases; - * } internal; DO NOT CHANGE - * } ARGPARSE_ARGS; - * - * typedef struct { - * int short_opt; - * const char *long_opt; - * unsigned flags; - * } ARGPARSE_OPTS; - * - * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts ); - * - * @Description - * This is my replacement for getopt(). See the example for a typical usage. - * Global flags are: - * Bit 0 : Do not remove options form argv - * Bit 1 : Do not stop at last option but return other args - * with r_opt set to -1. - * Bit 2 : Assume options and real args are mixed. - * Bit 3 : Do not use -- to stop option processing. - * Bit 4 : Do not skip the first arg. - * Bit 5 : allow usage of long option with only one dash - * Bit 6 : ignore --version and --help - * all other bits must be set to zero, this value is modified by the - * function, so assume this is write only. - * Local flags (for each option): - * Bit 2-0 : 0 = does not take an argument - * 1 = takes int argument - * 2 = takes string argument - * 3 = takes long argument - * 4 = takes ulong argument - * Bit 3 : argument is optional (r_type will the be set to 0) - * Bit 4 : allow 0x etc. prefixed values. - * Bit 7 : this is a command and not an option - * You stop the option processing by setting opts to NULL, the function will - * then return 0. - * @Return Value - * Returns the args.r_opt or 0 if ready - * r_opt may be -2/-7 to indicate an unknown option/command. - * @See Also - * ArgExpand - * @Notes - * You do not need to process the options 'h', '--help' or '--version' - * because this function includes standard help processing; but if you - * specify '-h', '--help' or '--version' you have to do it yourself. - * The option '--' stops argument processing; if bit 1 is set the function - * continues to return normal arguments. - * To process float args or unsigned args you must use a string args and do - * the conversion yourself. - * @Example - * - * ARGPARSE_OPTS opts[] = { - * { 'v', "verbose", 0 }, - * { 'd', "debug", 0 }, - * { 'o', "output", 2 }, - * { 'c', "cross-ref", 2|8 }, - * { 'm', "my-option", 1|8 }, - * { 500, "have-no-short-option-for-this-long-option", 0 }, - * {0} }; - * ARGPARSE_ARGS pargs = { &argc, &argv, 0 } - * - * while( ArgParse( &pargs, &opts) ) { - * switch( pargs.r_opt ) { - * case 'v': opt.verbose++; break; - * case 'd': opt.debug++; break; - * case 'o': opt.outfile = pargs.r.ret_str; break; - * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - * case 500: opt.a_long_one++; break - * default : pargs.err = 1; break; -- force warning output -- - * } - * } - * if( argc > 1 ) - * log_fatal( "Too many args"); - * - */ - -typedef struct alias_def_s *ALIAS_DEF; -struct alias_def_s { - ALIAS_DEF next; - char *name; /* malloced buffer with name, \0, value */ - const char *value; /* ptr into name */ -}; - -static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s); -static void show_help(ARGPARSE_OPTS *opts, unsigned flags); -static void show_version(void); - -static void -initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) -{ - if( !(arg->flags & (1<<15)) ) { /* initialize this instance */ - arg->internal.idx = 0; - arg->internal.last = NULL; - arg->internal.inarg = 0; - arg->internal.stopped = 0; - arg->internal.aliases = NULL; - arg->internal.cur_alias = NULL; - arg->err = 0; - arg->flags |= 1<<15; /* mark initialized */ - if( *arg->argc < 0 ) - log_bug("Invalid argument for ArgParse\n"); - } - - - if( arg->err ) { /* last option was erroneous */ - const char *s; - - if( filename ) { - if( arg->r_opt == -6 ) - s = "%s:%u: argument not expected\n"; - else if( arg->r_opt == -5 ) - s = "%s:%u: read error\n"; - else if( arg->r_opt == -4 ) - s = "%s:%u: keyword too long\n"; - else if( arg->r_opt == -3 ) - s = "%s:%u: missing argument\n"; - else if( arg->r_opt == -7 ) - s = "%s:%u: invalid command\n"; - else if( arg->r_opt == -10 ) - s = "%s:%u: invalid alias definition\n"; - else - s = "%s:%u: invalid option\n"; - log_error(s, filename, *lineno ); - } - else { - if( arg->r_opt == -3 ) - s = "Missing argument for option \"%.50s\"\n"; - else if( arg->r_opt == -6 ) - s = "Option \"%.50s\" does not expect an argument\n"; - else if( arg->r_opt == -7 ) - s = "Invalid command \"%.50s\"\n"; - else if( arg->r_opt == -8 ) - s = "Option \"%.50s\" is ambiguous\n"; - else if( arg->r_opt == -9 ) - s = "Command \"%.50s\" is ambiguous\n"; - else - s = "Invalid option \"%.50s\"\n"; - log_error(s, arg->internal.last? arg->internal.last:"[??]" ); - } - if( arg->err != 1 || arg->r_opt == -5 ) - exit(2); - arg->err = 0; - } - - /* clearout the return value union */ - arg->r.ret_str = NULL; - arg->r.ret_long= 0; -} - - -static void -store_alias( ARGPARSE_ARGS *arg, char *name, char *value ) -{ - /* TODO: replace this dummy function with a rea one - * and fix the probelms IRIX has with (ALIAS_DEV)arg.. - * used as lvalue - */ -#if 0 - ALIAS_DEF a = m_alloc( sizeof *a ); - a->name = name; - a->value = value; - a->next = (ALIAS_DEF)arg->internal.aliases; - (ALIAS_DEF)arg->internal.aliases = a; -#endif -} - -/**************** - * Get options from a file. - * Lines starting with '#' are comment lines. - * Syntax is simply a keyword and the argument. - * Valid keywords are all keywords from the long_opt list without - * the leading dashes. The special keywords "help", "warranty" and "version" - * are not valid here. - * The special keyword "alias" may be used to store alias definitions, - * which are later expanded like long options. - * Caller must free returned strings. - * If called with FP set to NULL command line args are parse instead. - * - * Q: Should we allow the syntax - * keyword = value - * and accept for boolean options a value of 1/0, yes/no or true/false? - * Note: Abbreviation of options is here not allowed. - */ -int -optfile_parse( FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int state, i, c; - int idx=0; - char keyword[100]; - char *buffer = NULL; - size_t buflen = 0; - int inverse=0; - int in_alias=0; - - if( !fp ) /* same as arg_parse() in this case */ - return arg_parse( arg, opts ); - - initialize( arg, filename, lineno ); - - /* find the next keyword */ - state = i = 0; - for(;;) { - c=getc(fp); - if( c == '\n' || c== EOF ) { - if( c != EOF ) - ++*lineno; - if( state == -1 ) - break; - else if( state == 2 ) { - keyword[i] = 0; - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) - break; - idx = i; - arg->r_opt = opts[idx].short_opt; - if( inverse ) /* this does not have an effect, hmmm */ - arg->r_opt = -arg->r_opt; - if( !opts[idx].short_opt ) /* unknown command/option */ - arg->r_opt = (opts[idx].flags & 256)? -7:-2; - else if( !(opts[idx].flags & 7) ) /* does not take an arg */ - arg->r_type = 0; /* okay */ - else if( (opts[idx].flags & 8) ) /* argument is optional */ - arg->r_type = 0; /* okay */ - else /* required argument */ - arg->r_opt = -3; /* error */ - break; - } - else if( state == 3 ) { /* no argument found */ - if( in_alias ) - arg->r_opt = -3; /* error */ - else if( !(opts[idx].flags & 7) ) /* does not take an arg */ - arg->r_type = 0; /* okay */ - else if( (opts[idx].flags & 8) ) /* no optional argument */ - arg->r_type = 0; /* okay */ - else /* no required argument */ - arg->r_opt = -3; /* error */ - break; - } - else if( state == 4 ) { /* have an argument */ - if( in_alias ) { - if( !buffer ) - arg->r_opt = -6; - else { - char *p; - - buffer[i] = 0; - p = strpbrk( buffer, " \t" ); - if( p ) { - *p++ = 0; - trim_spaces( p ); - } - if( !p || !*p ) { - m_free( buffer ); - arg->r_opt = -10; - } - else { - store_alias( arg, buffer, p ); - } - } - } - else if( !(opts[idx].flags & 7) ) /* does not take an arg */ - arg->r_opt = -6; /* error */ - else { - char *p; - if( !buffer ) { - keyword[i] = 0; - buffer = m_strdup(keyword); - } - else - buffer[i] = 0; - - trim_spaces( buffer ); - p = buffer; - /* remove quotes if they totally enclose the - string, and do not occur within the string */ - if( *p == '"' && p[strlen(p)-1]=='"') { - char *p2=p; - - while(*(++p2)) - if(*p2=='"') - break; - - if(*p2=='"' && *(p2+1)=='\0') { - p[strlen(p)-1] = 0; - p++; - } - } - if( !set_opt_arg(arg, opts[idx].flags, p) ) - m_free(buffer); - } - break; - } - else if( c == EOF ) { - if( ferror(fp) ) - arg->r_opt = -5; /* read error */ - else - arg->r_opt = 0; /* eof */ - break; - } - state = 0; - i = 0; - } - else if( state == -1 ) - ; /* skip */ - else if( !state && isspace(c) ) - ; /* skip leading white space */ - else if( !state && c == '#' ) - state = 1; /* start of a comment */ - else if( state == 1 ) - ; /* skip comments */ - else if( state == 2 && isspace(c) ) { - keyword[i] = 0; - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) - break; - idx = i; - arg->r_opt = opts[idx].short_opt; - if( !opts[idx].short_opt ) { - if( !strcmp( keyword, "alias" ) ) { - in_alias = 1; - state = 3; - } - else { - arg->r_opt = (opts[idx].flags & 256)? -7:-2; - state = -1; /* skip rest of line and leave */ - } - } - else - state = 3; - } - else if( state == 3 ) { /* skip leading spaces of the argument */ - if( !isspace(c) ) { - i = 0; - keyword[i++] = c; - state = 4; - } - } - else if( state == 4 ) { /* collect the argument */ - if( buffer ) { - if( i < buflen-1 ) - buffer[i++] = c; - else { - buflen += 50; - buffer = m_realloc(buffer, buflen); - buffer[i++] = c; - } - } - else if( i < DIM(keyword)-1 ) - keyword[i++] = c; - else { - buflen = DIM(keyword)+50; - buffer = m_alloc(buflen); - memcpy(buffer, keyword, i); - buffer[i++] = c; - } - } - else if( i >= DIM(keyword)-1 ) { - arg->r_opt = -4; /* keyword to long */ - state = -1; /* skip rest of line and leave */ - } - else { - keyword[i++] = c; - state = 2; - } - } - - return arg->r_opt; -} - - - -static int -find_long_option( ARGPARSE_ARGS *arg, - ARGPARSE_OPTS *opts, const char *keyword ) -{ - int i; - size_t n; - - /* Would be better if we can do a binary search, but it is not - possible to reorder our option table because we would mess - up our help strings - What we can do is: Build a nice option - lookup table wehn this function is first invoked */ - if( !*keyword ) - return -1; - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) - return i; - #if 0 - { - ALIAS_DEF a; - /* see whether it is an alias */ - for( a = args->internal.aliases; a; a = a->next ) { - if( !strcmp( a->name, keyword) ) { - /* todo: must parse the alias here */ - args->internal.cur_alias = a; - return -3; /* alias available */ - } - } - } - #endif - /* not found, see whether it is an abbreviation */ - /* aliases may not be abbreviated */ - n = strlen( keyword ); - for(i=0; opts[i].short_opt; i++ ) { - if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { - int j; - for(j=i+1; opts[j].short_opt; j++ ) { - if( opts[j].long_opt - && !strncmp( opts[j].long_opt, keyword, n ) ) - return -2; /* abbreviation is ambiguous */ - } - return i; - } - } - return -1; -} - -int -arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int idx; - int argc; - char **argv; - char *s, *s2; - int i; - - initialize( arg, NULL, NULL ); - argc = *arg->argc; - argv = *arg->argv; - idx = arg->internal.idx; - - if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */ - argc--; argv++; idx++; - } - - next_one: - if( !argc ) { /* no more args */ - arg->r_opt = 0; - goto leave; /* ready */ - } - - s = *argv; - arg->internal.last = s; - - if( arg->internal.stopped && (arg->flags & (1<<1)) ) { - arg->r_opt = -1; /* not an option but a argument */ - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* set to next one */ - } - else if( arg->internal.stopped ) { /* ready */ - arg->r_opt = 0; - goto leave; - } - else if( *s == '-' && s[1] == '-' ) { /* long option */ - char *argpos; - - arg->internal.inarg = 0; - if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */ - arg->internal.stopped = 1; - argc--; argv++; idx++; - goto next_one; - } - - argpos = strchr( s+2, '=' ); - if( argpos ) - *argpos = 0; - i = find_long_option( arg, opts, s+2 ); - if( argpos ) - *argpos = '='; - - if( i < 0 && !strcmp( "help", s+2) ) { - if( !(arg->flags & (1<<6)) ) { - show_help(opts, arg->flags); - } - } - else if( i < 0 && !strcmp( "version", s+2) ) { - if( !(arg->flags & (1<<6)) ) { - show_version(); - exit(0); - } - } - else if( i < 0 && !strcmp( "warranty", s+2) ) { - puts( strusage(16) ); - exit(0); - } - else if( i < 0 && !strcmp( "dump-options", s+2) ) { - for(i=0; opts[i].short_opt; i++ ) { - if( opts[i].long_opt ) - printf( "--%s\n", opts[i].long_opt ); - } - fputs("--dump-options\n--help\n--version\n--warranty\n", stdout ); - exit(0); - } - - if( i == -2 ) /* ambiguous option */ - arg->r_opt = -8; - else if( i == -1 ) { - arg->r_opt = -2; - arg->r.ret_str = s+2; - } - else - arg->r_opt = opts[i].short_opt; - if( i < 0 ) - ; - else if( (opts[i].flags & 7) ) { - if( argpos ) { - s2 = argpos+1; - if( !*s2 ) - s2 = NULL; - } - else - s2 = argv[1]; - if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/ - arg->r_type = 0; /* because it is optional */ - } - else if( !s2 ) { - arg->r_opt = -3; /* missing argument */ - } - else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) { - /* the argument is optional and the next seems to be - * an option. We do not check this possible option - * but assume no argument */ - arg->r_type = 0; - } - else { - set_opt_arg(arg, opts[i].flags, s2); - if( !argpos ) { - argc--; argv++; idx++; /* skip one */ - } - } - } - else { /* does not take an argument */ - if( argpos ) - arg->r_type = -6; /* argument not expected */ - else - arg->r_type = 0; - } - argc--; argv++; idx++; /* set to next one */ - } - else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */ - int dash_kludge = 0; - i = 0; - if( !arg->internal.inarg ) { - arg->internal.inarg++; - if( arg->flags & (1<<5) ) { - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) { - dash_kludge=1; - break; - } - } - } - s += arg->internal.inarg; - - if( !dash_kludge ) { - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].short_opt == *s ) - break; - } - - if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) { - if( !(arg->flags & (1<<6)) ) { - show_help(opts, arg->flags); - } - } - - arg->r_opt = opts[i].short_opt; - if( !opts[i].short_opt ) { - arg->r_opt = (opts[i].flags & 256)? -7:-2; - arg->internal.inarg++; /* point to the next arg */ - arg->r.ret_str = s; - } - else if( (opts[i].flags & 7) ) { - if( s[1] && !dash_kludge ) { - s2 = s+1; - set_opt_arg(arg, opts[i].flags, s2); - } - else { - s2 = argv[1]; - if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/ - arg->r_type = 0; /* because it is optional */ - } - else if( !s2 ) { - arg->r_opt = -3; /* missing argument */ - } - else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) { - /* the argument is optional and the next seems to be - * an option. We do not check this possible option - * but assume no argument */ - arg->r_type = 0; - } - else { - set_opt_arg(arg, opts[i].flags, s2); - argc--; argv++; idx++; /* skip one */ - } - } - s = "x"; /* so that !s[1] yields false */ - } - else { /* does not take an argument */ - arg->r_type = 0; - arg->internal.inarg++; /* point to the next arg */ - } - if( !s[1] || dash_kludge ) { /* no more concatenated short options */ - arg->internal.inarg = 0; - argc--; argv++; idx++; - } - } - else if( arg->flags & (1<<2) ) { - arg->r_opt = -1; /* not an option but a argument */ - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* set to next one */ - } - else { - arg->internal.stopped = 1; /* stop option processing */ - goto next_one; - } - - leave: - *arg->argc = argc; - *arg->argv = argv; - arg->internal.idx = idx; - return arg->r_opt; -} - - - -static int -set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s) -{ - int base = (flags & 16)? 0 : 10; - - switch( arg->r_type = (flags & 7) ) { - case 1: /* takes int argument */ - arg->r.ret_int = (int)strtol(s,NULL,base); - return 0; - case 3: /* takes long argument */ - arg->r.ret_long= strtol(s,NULL,base); - return 0; - case 4: /* takes ulong argument */ - arg->r.ret_ulong= strtoul(s,NULL,base); - return 0; - case 2: /* takes string argument */ - default: - arg->r.ret_str = s; - return 1; - } -} - - -static size_t -long_opt_strlen( ARGPARSE_OPTS *o ) -{ - size_t n = strlen(o->long_opt); - - if( o->description && *o->description == '|' ) { - const char *s; - - s=o->description+1; - if( *s != '=' ) - n++; - for(; *s && *s != '|'; s++ ) - n++; - } - return n; -} - -/**************** - * Print formatted help. The description string has some special - * meanings: - * - A description string which is "@" suppresses help output for - * this option - * - a description,ine which starts with a '@' and is followed by - * any other characters is printed as is; this may be used for examples - * ans such. - * - A description which starts with a '|' outputs the string between this - * bar and the next one as arguments of the long option. - */ -static void -show_help( ARGPARSE_OPTS *opts, unsigned flags ) -{ - const char *s; - - show_version(); - putchar('\n'); - s = strusage(41); - puts(s); - if( opts[0].description ) { /* auto format the option description */ - int i,j, indent; - /* get max. length of long options */ - for(i=indent=0; opts[i].short_opt; i++ ) { - if( opts[i].long_opt ) - if( !opts[i].description || *opts[i].description != '@' ) - if( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) - indent = j; - } - /* example: " -v, --verbose Viele Sachen ausgeben" */ - indent += 10; - if( *opts[0].description != '@' ) - puts("Options:"); - for(i=0; opts[i].short_opt; i++ ) { - s = _( opts[i].description ); - if( s && *s== '@' && !s[1] ) /* hide this line */ - continue; - if( s && *s == '@' ) { /* unindented comment only line */ - for(s++; *s; s++ ) { - if( *s == '\n' ) { - if( s[1] ) - putchar('\n'); - } - else - putchar(*s); - } - putchar('\n'); - continue; - } - - j = 3; - if( opts[i].short_opt < 256 ) { - printf(" -%c", opts[i].short_opt ); - if( !opts[i].long_opt ) { - if(s && *s == '|' ) { - putchar(' '); j++; - for(s++ ; *s && *s != '|'; s++, j++ ) - putchar(*s); - if( *s ) - s++; - } - } - } - else - fputs(" ", stdout); - if( opts[i].long_opt ) { - j += printf("%c --%s", opts[i].short_opt < 256?',':' ', - opts[i].long_opt ); - if(s && *s == '|' ) { - if( *++s != '=' ) { - putchar(' '); - j++; - } - for( ; *s && *s != '|'; s++, j++ ) - putchar(*s); - if( *s ) - s++; - } - fputs(" ", stdout); - j += 3; - } - for(;j < indent; j++ ) - putchar(' '); - if( s ) { - if( *s && j > indent ) { - putchar('\n'); - for(j=0;j < indent; j++ ) - putchar(' '); - } - for(; *s; s++ ) { - if( *s == '\n' ) { - if( s[1] ) { - putchar('\n'); - for(j=0;j < indent; j++ ) - putchar(' '); - } - } - else - putchar(*s); - } - } - putchar('\n'); - } - if( flags & 32 ) - puts("\n(A single dash may be used instead of the double ones)"); - } - if( (s=strusage(19)) ) { /* bug reports to ... */ - putchar('\n'); - fputs(s, stdout); - } - fflush(stdout); - exit(0); -} - -static void -show_version() -{ - const char *s; - int i; - /* version line */ - fputs(strusage(11), stdout); - if( (s=strusage(12)) ) - printf(" (%s)", s ); - printf(" %s\n", strusage(13) ); - /* additional version lines */ - for(i=20; i < 30; i++ ) - if( (s=strusage(i)) ) - printf("%s\n", s ); - /* copyright string */ - if( (s=strusage(14)) ) - printf("%s\n", s ); - /* copying conditions */ - if( (s=strusage(15)) ) - fputs(s, stdout); - /* thanks */ - if( (s=strusage(18)) ) - fputs(s, stdout); - /* additional program info */ - for(i=30; i < 40; i++ ) - if( (s=strusage(i)) ) - fputs( (const byte*)s, stdout); - fflush(stdout); -} - - -void -usage( int level ) -{ - if( !level ) { - fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13), - strusage(14) ); - fflush(stderr); - } - else if( level == 1 ) { - fputs(strusage(40),stderr); - exit(2); - } - else if( level == 2 ) { - puts(strusage(41)); - exit(0); - } -} - -/* Level - * 0: Copyright String auf stderr ausgeben - * 1: Kurzusage auf stderr ausgeben und beenden - * 2: Langusage auf stdout ausgeben und beenden - * 11: name of program - * 12: optional name of package which includes this program. - * 13: version string - * 14: copyright string - * 15: Short copying conditions (with LFs) - * 16: Long copying conditions (with LFs) - * 17: Optional printable OS name - * 18: Optional thanks list (with LFs) - * 19: Bug report info - *20..29: Additional lib version strings. - *30..39: Additional program info (with LFs) - * 40: short usage note (with LF) - * 41: long usage note (with LF) - */ -const char * -default_strusage( int level ) -{ - const char *p = NULL; - switch( level ) { - case 11: p = "foo"; break; - case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2002 Free Software Foundation, Inc."; break; - case 15: p = -"This program comes with ABSOLUTELY NO WARRANTY.\n" -"This is free software, and you are welcome to redistribute it\n" -"under certain conditions. See the file COPYING for details.\n"; break; - case 16: p = -"This is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License as published by\n" -"the Free Software Foundation; either version 2 of the License, or\n" -"(at your option) any later version.\n\n" -"It is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n\n" -"You should have received a copy of the GNU General Public License\n" -"along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"; - break; - case 40: /* short and long usage */ - case 41: p = ""; break; - } - - return p; -} - - - -#ifdef TEST -static struct { - int verbose; - int debug; - char *outfile; - char *crf; - int myopt; - int echo; - int a_long_one; -}opt; - -int -main(int argc, char **argv) -{ - ARGPARSE_OPTS opts[] = { - { 'v', "verbose", 0 , "Laut sein"}, - { 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"}, - { 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"}, - { 'o', "output", 2 }, - { 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" }, - { 'm', "my-option", 1|8 }, - { 500, "a-long-option", 0 }, - {0} }; - ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 }; - int i; - - while( ArgParse( &pargs, opts) ) { - switch( pargs.r_opt ) { - case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break; - case 'v': opt.verbose++; break; - case 'e': opt.echo++; break; - case 'd': opt.debug++; break; - case 'o': opt.outfile = pargs.r.ret_str; break; - case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - case 500: opt.a_long_one++; break; - default : pargs.err = 1; break; /* force warning output */ - } - } - for(i=0; i < argc; i++ ) - printf("%3d -> (%s)\n", i, argv[i] ); - puts("Options:"); - if( opt.verbose ) - printf(" verbose=%d\n", opt.verbose ); - if( opt.debug ) - printf(" debug=%d\n", opt.debug ); - if( opt.outfile ) - printf(" outfile=`%s'\n", opt.outfile ); - if( opt.crf ) - printf(" crffile=`%s'\n", opt.crf ); - if( opt.myopt ) - printf(" myopt=%d\n", opt.myopt ); - if( opt.a_long_one ) - printf(" a-long-one=%d\n", opt.a_long_one ); - if( opt.echo ) - printf(" echo=%d\n", opt.echo ); - return 0; -} -#endif - -/**** bottom of file ****/ diff --git a/util/dotlock.c b/util/dotlock.c deleted file mode 100644 index fac825450..000000000 --- a/util/dotlock.c +++ /dev/null @@ -1,420 +0,0 @@ -/* dotlock.c - dotfile locking - * 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 -#include -#include -#include -#include -#include -#include -#if !defined (HAVE_DOSISH_SYSTEM) -#include -#endif -#include -#include -#include -#include -#include -#include "types.h" -#include "util.h" -#include "memory.h" - -struct dotlock_handle { - struct dotlock_handle *next; - char *tname; /* name of lockfile template */ - char *lockname; /* name of the real lockfile */ - int locked; /* lock status */ - int disable; /* locking */ -}; - - -static volatile DOTLOCK all_lockfiles; -static int never_lock; - -static int read_lockfile( const char *name ); - -void -disable_dotlock(void) -{ - never_lock = 1; -} - -/**************** - * Create a lockfile with the given name and return an object of - * type DOTLOCK which may be used later to actually do the lock. - * A cleanup routine gets installed to cleanup left over locks - * or other files used together with the lockmechanism. - * Althoug the function is called dotlock, this does not necessarily - * mean that real lockfiles are used - the function may decide to - * use fcntl locking. Calling the function with NULL only install - * the atexit handler and maybe used to assure that the cleanup - * is called after all other atexit handlers. - * - * Notes: This function creates a lock file in the same directory - * as file_to_lock with the name "file_to_lock.lock" - * A temporary file ".#lk..pid[.threadid] is used. - * This function does nothing for Windoze. - */ -DOTLOCK -create_dotlock( const char *file_to_lock ) -{ - static int initialized; - DOTLOCK h; - int fd = -1; - char pidstr[16]; - #if !defined (HAVE_DOSISH_SYSTEM) - struct utsname utsbuf; - #endif - const char *nodename; - const char *dirpart; - int dirpartlen; - - if( !initialized ) { - atexit( remove_lockfiles ); - initialized = 1; - } - if( !file_to_lock ) - return NULL; - - h = m_alloc_clear( sizeof *h ); - if( never_lock ) { - h->disable = 1; - #ifdef _REENTRANT - /* fixme: aquire mutex on all_lockfiles */ - #endif - h->next = all_lockfiles; - all_lockfiles = h; - return h; - } - - -#if !defined (HAVE_DOSISH_SYSTEM) - sprintf( pidstr, "%10d\n", (int)getpid() ); - /* fixme: add the hostname to the second line (FQDN or IP addr?) */ - - /* create a temporary file */ - if( uname( &utsbuf ) ) - nodename = "unknown"; - else - nodename = utsbuf.nodename; - -#ifdef __riscos__ - { - char *iter = (char *) nodename; - for (; iter[0]; iter++) - if (iter[0] == '.') - iter[0] = '/'; - } -#endif /* __riscos__ */ - - if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) { - dirpart = EXTSEP_S; - dirpartlen = 1; - } - else { - dirpartlen = dirpart - file_to_lock; - dirpart = file_to_lock; - } - - #ifdef _REENTRANT - /* fixme: aquire mutex on all_lockfiles */ - #endif - h->next = all_lockfiles; - all_lockfiles = h; - - h->tname = m_alloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); -#ifndef __riscos__ - sprintf( h->tname, "%.*s/.#lk%p.%s.%d", - dirpartlen, dirpart, h, nodename, (int)getpid() ); -#else /* __riscos__ */ - sprintf( h->tname, "%.*s.lk%p/%s/%d", - dirpartlen, dirpart, h, nodename, (int)getpid() ); -#endif /* __riscos__ */ - - do { - errno = 0; - fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL, - S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); - } while( fd == -1 && errno == EINTR ); - if( fd == -1 ) { - all_lockfiles = h->next; - log_error( "failed to create temporary file `%s': %s\n", - h->tname, strerror(errno)); - m_free(h->tname); - m_free(h); - return NULL; - } - if( write(fd, pidstr, 11 ) != 11 ) { - all_lockfiles = h->next; - #ifdef _REENTRANT - /* release mutex */ - #endif - log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); - close(fd); - unlink(h->tname); - m_free(h->tname); - m_free(h); - return NULL; - } - if( close(fd) ) { - all_lockfiles = h->next; - #ifdef _REENTRANT - /* release mutex */ - #endif - log_error( "error closing `%s': %s\n", h->tname, strerror(errno)); - unlink(h->tname); - m_free(h->tname); - m_free(h); - return NULL; - } - - #ifdef _REENTRANT - /* release mutex */ - #endif -#endif - h->lockname = m_alloc( strlen(file_to_lock) + 6 ); - strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); - return h; -} - -static int -maybe_deadlock( DOTLOCK h ) -{ - DOTLOCK r; - - for( r=all_lockfiles; r; r = r->next ) { - if( r != h && r->locked ) - return 1; - } - return 0; -} - -/**************** - * Do a lock on H. A TIMEOUT of 0 returns immediately, - * -1 waits forever (hopefully not), other - * values are timeouts in milliseconds. - * Returns: 0 on success - */ -int -make_dotlock( DOTLOCK h, long timeout ) -{ -#if defined (HAVE_DOSISH_SYSTEM) - return 0; -#else - int pid; - const char *maybe_dead=""; - int backoff=0; - - if( h->disable ) { - return 0; - } - - if( h->locked ) { -#ifndef __riscos__ - log_debug("oops, `%s' is already locked\n", h->lockname ); -#endif /* !__riscos__ */ - return 0; - } - - for(;;) { -#ifndef __riscos__ - if( !link(h->tname, h->lockname) ) { - /* fixme: better use stat to check the link count */ - h->locked = 1; - return 0; /* okay */ - } - if( errno != EEXIST ) { - log_error( "lock not made: link() failed: %s\n", strerror(errno) ); - return -1; - } -#else /* __riscos__ */ - if( !renamefile(h->tname, h->lockname) ) { - h->locked = 1; - return 0; /* okay */ - } - if( errno != EEXIST ) { - log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); - return -1; - } -#endif /* __riscos__ */ - if( (pid = read_lockfile(h->lockname)) == -1 ) { - if( errno != ENOENT ) { - log_info("cannot read lockfile\n"); - return -1; - } - log_info( "lockfile disappeared\n"); - continue; - } - else if( pid == getpid() ) { - log_info( "Oops: lock already held by us\n"); - h->locked = 1; - return 0; /* okay */ - } - else if( kill(pid, 0) && errno == ESRCH ) { -#ifndef __riscos__ - maybe_dead = " - probably dead"; - #if 0 /* we should not do this without checking the permissions */ - /* and the hostname */ - log_info( "removing stale lockfile (created by %d)", pid ); - #endif -#else /* __riscos__ */ - /* we are *pretty* sure that the other task is dead and therefore - we remove the other lock file */ - maybe_dead = " - probably dead - removing lock"; - unlink(h->lockname); -#endif /* __riscos__ */ - } - if( timeout == -1 ) { - struct timeval tv; - log_info( "waiting for lock (held by %d%s) %s...\n", - pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); - - - /* can't use sleep, cause signals may be blocked */ - tv.tv_sec = 1 + backoff; - tv.tv_usec = 0; - select(0, NULL, NULL, NULL, &tv); - if( backoff < 10 ) - backoff++ ; - } - else - return -1; - } - /*not reached */ -#endif -} - - -/**************** - * release a lock - * Returns: 0 := success - */ -int -release_dotlock( DOTLOCK h ) -{ -#if defined (HAVE_DOSISH_SYSTEM) - return 0; -#else - int pid; - - if( h->disable ) { - return 0; - } - - if( !h->locked ) { - log_debug("oops, `%s' is not locked\n", h->lockname ); - return 0; - } - - pid = read_lockfile( h->lockname ); - if( pid == -1 ) { - log_error( "release_dotlock: lockfile error\n"); - return -1; - } - if( pid != getpid() ) { - log_error( "release_dotlock: not our lock (pid=%d)\n", pid); - return -1; - } -#ifndef __riscos__ - if( unlink( h->lockname ) ) { - log_error( "release_dotlock: error removing lockfile `%s'", - h->lockname); - return -1; - } -#else /* __riscos__ */ - if( renamefile(h->lockname, h->tname) ) { - log_error( "release_dotlock: error renaming lockfile `%s' to `%s'", - h->lockname, h->tname); - return -1; - } -#endif /* __riscos__ */ - /* fixme: check that the link count is now 1 */ - h->locked = 0; - return 0; -#endif -} - - -/**************** - * Read the lock file and return the pid, returns -1 on error. - */ -static int -read_lockfile( const char *name ) -{ - #if defined (HAVE_DOSISH_SYSTEM) - return 0; - #else - int fd, pid; - char pidstr[16]; - - if( (fd = open(name, O_RDONLY)) == -1 ) { - int e = errno; - log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) ); - errno = e; - return -1; - } - if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */ - log_debug("error reading lockfile `%s'", name ); - close(fd); - errno = 0; - return -1; - } - pidstr[10] = 0; /* terminate pid string */ - close(fd); - pid = atoi(pidstr); -#ifndef __riscos__ - if( !pid || pid == -1 ) { -#else /* __riscos__ */ - if( (!pid && riscos_getpid()) || pid == -1 ) { -#endif /* __riscos__ */ - log_error("invalid pid %d in lockfile `%s'", pid, name ); - errno = 0; - return -1; - } - return pid; - #endif -} - - -void -remove_lockfiles() -{ - #if !defined (HAVE_DOSISH_SYSTEM) - DOTLOCK h, h2; - - h = all_lockfiles; - all_lockfiles = NULL; - - while( h ) { - h2 = h->next; - if( !h->disable ) { - if( h->locked ) - unlink( h->lockname ); - unlink(h->tname); - m_free(h->tname); - m_free(h->lockname); - } - m_free(h); - h = h2; - } - #endif -} - diff --git a/util/errors.c b/util/errors.c deleted file mode 100644 index 25d5a088a..000000000 --- a/util/errors.c +++ /dev/null @@ -1,113 +0,0 @@ -/* errors.c - error strings - * 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 -#include -#include -#include - -#include "errors.h" -#include "i18n.h" - -#ifndef HAVE_STRERROR -char * -strerror( int n ) -{ - extern char *sys_errlist[]; - extern int sys_nerr; - static char buf[15]; - - if( n >= 0 && n < sys_nerr ) - return sys_errlist[n]; - strcpy( buf, "Unknown error" ); - return buf; -} -#endif /* !HAVE_STRERROR */ - -const char * -g10_errstr( int err ) -{ - static char buf[50]; - const char *p; - - #define X(n,s) case G10ERR_##n : p = s; break; - switch( err ) { - case -1: p = "eof"; break; - case 0: p = "okay"; break; - X(GENERAL, N_("general error")) - X(UNKNOWN_PACKET, N_("unknown packet type")) - X(UNKNOWN_VERSION,N_("unknown version")) - X(PUBKEY_ALGO ,N_("unknown pubkey algorithm")) - X(DIGEST_ALGO ,N_("unknown digest algorithm")) - X(BAD_PUBKEY ,N_("bad public key")) - X(BAD_SECKEY ,N_("bad secret key")) - X(BAD_SIGN ,N_("bad signature")) - X(CHECKSUM , N_("checksum error")) - X(BAD_PASS , N_("bad passphrase")) - X(NO_PUBKEY ,N_("public key not found")) - X(CIPHER_ALGO ,N_("unknown cipher algorithm")) - X(KEYRING_OPEN ,N_("can't open the keyring")) - X(INVALID_PACKET ,N_("invalid packet")) - X(INVALID_ARMOR ,N_("invalid armor")) - X(NO_USER_ID ,N_("no such user id")) - X(NO_SECKEY ,N_("secret key not available")) - X(WRONG_SECKEY ,N_("wrong secret key used")) - X(UNSUPPORTED ,N_("not supported")) - X(BAD_KEY ,N_("bad key")) - X(READ_FILE ,N_("file read error")) - X(WRITE_FILE ,N_("file write error")) - X(COMPR_ALGO ,N_("unknown compress algorithm")) - X(OPEN_FILE ,N_("file open error")) - X(CREATE_FILE ,N_("file create error")) - X(PASSPHRASE ,N_("invalid passphrase")) - X(NI_PUBKEY ,N_("unimplemented pubkey algorithm")) - X(NI_CIPHER ,N_("unimplemented cipher algorithm")) - X(SIG_CLASS ,N_("unknown signature class")) - X(TRUSTDB ,N_("trust database error")) - X(BAD_MPI ,N_("bad MPI")) - X(RESOURCE_LIMIT ,N_("resource limit")) - X(INV_KEYRING ,N_("invalid keyring")) - X(BAD_CERT ,N_("bad certificate")) - X(INV_USER_ID ,N_("malformed user id")) - X(CLOSE_FILE ,N_("file close error")) - X(RENAME_FILE ,N_("file rename error")) - X(DELETE_FILE ,N_("file delete error")) - X(UNEXPECTED ,N_("unexpected data")) - X(TIME_CONFLICT ,N_("timestamp conflict")) - X(WR_PUBKEY_ALGO ,N_("unusable pubkey algorithm")) - X(FILE_EXISTS ,N_("file exists")) - X(WEAK_KEY ,N_("weak key")) - X(INV_ARG ,N_("invalid argument")) - X(BAD_URI ,N_("bad URI")) - X(INVALID_URI ,N_("unsupported URI")) - X(NETWORK ,N_("network error")) - X(SELFTEST_FAILED,"selftest failed") - X(NOT_ENCRYPTED ,N_("not encrypted")) - X(NOT_PROCESSED ,N_("not processed")) - /* the key cannot be used for a specific usage */ - X(UNU_PUBKEY ,N_("unusable public key")) - X(UNU_SECKEY ,N_("unusable secret key")) - X(KEYSERVER ,N_("keyserver error")) - default: p = buf; sprintf(buf, "g10err=%d", err); break; - } - #undef X - return _(p); -} - diff --git a/util/fileutil.c b/util/fileutil.c deleted file mode 100644 index c2a2a9df2..000000000 --- a/util/fileutil.c +++ /dev/null @@ -1,242 +0,0 @@ -/* fileutil.c - file utilities - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef __riscos__ -#include -#include -#endif /* __riscos__ */ -#include "util.h" -#include "memory.h" -#include "ttyio.h" - - -/*************** - * Extract from a given path the filename component. - * - */ -char * -make_basename(const char *filepath) -{ - char *p; - - if ( !(p=strrchr(filepath, DIRSEP_C)) ) - #ifdef HAVE_DRIVE_LETTERS - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) - #endif - { - return m_strdup(filepath); - } - - return m_strdup(p+1); -} - - - -/*************** - * Extract from a given filename the path prepended to it. - * If their isn't a path prepended to the filename, a dot - * is returned ('.'). - * - */ -char * -make_dirname(const char *filepath) -{ - char *dirname; - int dirname_length; - char *p; - - if ( !(p=strrchr(filepath, DIRSEP_C)) ) - #ifdef HAVE_DRIVE_LETTERS - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) - #endif - { - return m_strdup(EXTSEP_S); - } - - dirname_length = p-filepath; - dirname = m_alloc(dirname_length+1); - strncpy(dirname, filepath, dirname_length); - dirname[dirname_length] = 0; - - return dirname; -} - - - -/**************** - * Construct a filename from the NULL terminated list of parts. - * Tilde expansion is done here. - */ -char * -make_filename( const char *first_part, ... ) -{ - va_list arg_ptr ; - size_t n; - const char *s; -#ifndef __riscos__ - char *name, *home, *p; -#else - char *name, *p; -#endif - - va_start( arg_ptr, first_part ) ; - n = strlen(first_part)+1; - while( (s=va_arg(arg_ptr, const char *)) ) - n += strlen(s) + 1; - va_end(arg_ptr); - -#ifndef __riscos__ - home = NULL; - if( *first_part == '~' && first_part[1] == DIRSEP_C - && (home = getenv("HOME")) && *home ) - n += strlen(home); - name = m_alloc(n); - p = home ? stpcpy(stpcpy(name,home), first_part+1) - : stpcpy(name, first_part); -#else /* __riscos__ */ - name = m_alloc(n); - p = stpcpy(name, first_part); -#endif /* __riscos__ */ - va_start( arg_ptr, first_part ) ; - while( (s=va_arg(arg_ptr, const char *)) ) - p = stpcpy(stpcpy(p, DIRSEP_S), s); - va_end(arg_ptr); - -#ifndef __riscos__ - return name; -#else /* __riscos__ */ - p = gstrans(name); - m_free(name); - return p; -#endif /* __riscos__ */ -} - - -int -compare_filenames( const char *a, const char *b ) -{ - /* ? check whether this is an absolute filename and - * resolve symlinks? - */ -#ifndef __riscos__ - #ifdef HAVE_DRIVE_LETTERS - return ascii_strcasecmp(a,b); - #else - return strcmp(a,b); - #endif -#else /* __riscos__ */ - int c = 0; - char *abuf, *bbuf; - - abuf = gstrans(a); - bbuf = gstrans(b); - - c = strcasecmp (abuf, bbuf); - - m_free(abuf); - m_free(bbuf); - - return c; -#endif /* __riscos__ */ -} - - -/**************** - * A simple function to decide whether the filename is stdout - * or a real filename. - */ -const char * -print_fname_stdout( const char *s ) -{ - if( !s || (*s == '-' && !s[1]) ) - return "[stdout]"; - return s; -} - - -const char * -print_fname_stdin( const char *s ) -{ - if( !s || (*s == '-' && !s[1]) ) - return "[stdin]"; - return s; -} - -/**************** - * Check if the file is compressed. - **/ -int -is_file_compressed( const char *s, int *ret_rc ) -{ - IOBUF 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 == '-' || !ret_rc ) - return 0; /* We can't check stdin or no file was given */ - - a = iobuf_open( s ); - if ( a == NULL ) { - *ret_rc = G10ERR_OPEN_FILE; - return 0; - } - - if ( iobuf_get_filelength( a ) < 4 ) { - *ret_rc = 0; - goto leave; - } - - if ( iobuf_read( a, buf, 4 ) == -1 ) { - *ret_rc = G10ERR_READ_FILE; - 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; -} - - diff --git a/util/g10u.c b/util/g10u.c deleted file mode 100644 index 2ce3a4e36..000000000 --- a/util/g10u.c +++ /dev/null @@ -1,40 +0,0 @@ -/* g10u.c - Wrapper for utility functions - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include -#include -#include -#include "mpi.h" -#include "util.h" - - -/* FIXME: The modules should use functions from libgcrypt */ - -const char *g10u_revision_string(int dummy) { return "$Revision$"; } - - -void *g10_malloc( size_t n ) { return m_alloc( n ); } -void *g10_calloc( size_t n ) { return m_alloc_clear( n ); } -void *g10_malloc_secure( size_t n ) { return m_alloc_secure( n ); } -void *g10_calloc_secure( size_t n ) { return m_alloc_secure_clear( n ); } -void *g10_realloc( void *a, size_t n ) { return m_realloc( a, n ); } -void g10_free( void *p ) { m_free( p ); } -char *g10_strdup( const char * a) { return m_strdup( a ); } - diff --git a/util/http.c b/util/http.c deleted file mode 100644 index fa3d512e9..000000000 --- a/util/http.c +++ /dev/null @@ -1,903 +0,0 @@ -/* http.c - HTTP protocol handler - * Copyright (C) 1999, 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 -#include -#include -#include -#include -#include -#include - -#ifdef __MINGW32__ - #include -#else - #include - #include - #include - #include - #include - #include - #include - #include -#endif - -#include "util.h" -#include "iobuf.h" -#include "i18n.h" - -#include "http.h" - -#ifdef __riscos__ - #define HTTP_PROXY_ENV "GnuPG$HttpProxy" - #define HTTP_PROXY_ENV_PRINTABLE "" -#else - #define HTTP_PROXY_ENV "http_proxy" - #define HTTP_PROXY_ENV_PRINTABLE "$http_proxy" -#endif - -#ifdef __MINGW32__ -#define sock_close(a) closesocket(a) -#else -#define sock_close(a) close(a) -#endif - -#define MAX_LINELEN 20000 /* max. length of a HTTP line */ -#define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - "01234567890@" \ - "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~" - -#ifndef EAGAIN - #define EAGAIN EWOULDBLOCK -#endif - -static int parse_uri( PARSED_URI *ret_uri, const char *uri ); -static void release_parsed_uri( PARSED_URI uri ); -static int do_parse_uri( PARSED_URI uri, int only_local_part ); -static int remove_escapes( byte *string ); -static int insert_escapes( byte *buffer, const byte *string, - const byte *special ); -static URI_TUPLE parse_tuple( byte *string ); -static int send_request( HTTP_HD hd ); -static byte *build_rel_path( PARSED_URI uri ); -static int parse_response( HTTP_HD hd ); - -static int connect_server( const char *server, ushort port ); -static int write_server( int sock, const char *data, size_t length ); - -#ifdef __MINGW32__ -static void -deinit_sockets (void) -{ - WSACleanup(); -} - -static void -init_sockets (void) -{ - static int initialized; - static WSADATA wsdata; - - if (initialized) - return; - - if( WSAStartup( 0x0101, &wsdata ) ) { - log_error ("error initializing socket library: ec=%d\n", - (int)WSAGetLastError () ); - return; - } - if( wsdata.wVersion < 0x0001 ) { - log_error ("socket library version is %x.%x - but 1.1 needed\n", - LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion)); - WSACleanup(); - return; - } - atexit ( deinit_sockets ); - initialized = 1; -} -#endif /*__MINGW32__*/ - - -int -http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, - unsigned int flags ) -{ - int rc; - - if( !(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST) ) - return G10ERR_INV_ARG; - - /* initialize the handle */ - memset( hd, 0, sizeof *hd ); - hd->sock = -1; - hd->initialized = 1; - hd->req_type = reqtype; - hd->flags = flags; - - rc = parse_uri( &hd->uri, url ); - if( !rc ) { - rc = send_request( hd ); - if( !rc ) { - hd->fp_write = iobuf_sockopen( hd->sock , "w" ); - if( hd->fp_write ) - return 0; - rc = G10ERR_GENERAL; - } - } - - if( !hd->fp_read && !hd->fp_write && hd->sock != -1 ) - sock_close( hd->sock ); - iobuf_close( hd->fp_read ); - iobuf_close( hd->fp_write); - release_parsed_uri( hd->uri ); - hd->initialized = 0; - - return rc; -} - - -void -http_start_data( HTTP_HD hd ) -{ - iobuf_flush ( hd->fp_write ); - if( !hd->in_data ) { - write_server (hd->sock, "\r\n", 2); - hd->in_data = 1; - } -} - - -int -http_wait_response( HTTP_HD hd, unsigned int *ret_status ) -{ - int rc; - - http_start_data( hd ); /* make sure that we are in the data */ - - #if 0 - hd->sock = dup( hd->sock ); - if( hd->sock == -1 ) - return G10ERR_GENERAL; - #endif - iobuf_ioctl (hd->fp_write, 1, 1, NULL); /* keep the socket open */ - iobuf_close (hd->fp_write); - hd->fp_write = NULL; - if ( !(hd->flags & HTTP_FLAG_NO_SHUTDOWN) ) - shutdown( hd->sock, 1 ); - hd->in_data = 0; - - hd->fp_read = iobuf_sockopen( hd->sock , "r" ); - if( !hd->fp_read ) - return G10ERR_GENERAL; - - rc = parse_response( hd ); - if( !rc && ret_status ) - *ret_status = hd->status_code; - - return rc; -} - - -int -http_open_document( HTTP_HD hd, const char *document, unsigned int flags ) -{ - int rc; - - rc = http_open( hd, HTTP_REQ_GET, document, flags ); - if( rc ) - return rc; - - rc = http_wait_response( hd, NULL ); - if( rc ) - http_close( hd ); - - return rc; -} - - - - -void -http_close( HTTP_HD hd ) -{ - if( !hd || !hd->initialized ) - return; - if( !hd->fp_read && !hd->fp_write && hd->sock != -1 ) - sock_close( hd->sock ); - iobuf_close( hd->fp_read ); - iobuf_close( hd->fp_write ); - release_parsed_uri( hd->uri ); - m_free( hd->buffer ); - hd->initialized = 0; -} - - - -/**************** - * Parse an URI and put the result into the newly allocated ret_uri. - * The caller must always use release_parsed_uri to releases the - * resources (even on an error). - */ -static int -parse_uri( PARSED_URI *ret_uri, const char *uri ) -{ - *ret_uri = m_alloc_clear( sizeof(**ret_uri) + strlen(uri) ); - strcpy( (*ret_uri)->buffer, uri ); - return do_parse_uri( *ret_uri, 0 ); -} - -static void -release_parsed_uri( PARSED_URI uri ) -{ - if( uri ) - { - URI_TUPLE r, r2; - - for( r = uri->query; r; r = r2 ) { - r2 = r->next; - m_free( r ); - } - m_free( uri ); - } -} - -static int -do_parse_uri( PARSED_URI uri, int only_local_part ) -{ - URI_TUPLE *tail; - char *p, *p2, *p3; - int n; - - p = uri->buffer; - n = strlen( uri->buffer ); - /* initialize all fields to an empty string or an empty list */ - uri->scheme = uri->host = uri->path = p + n; - uri->port = 0; - uri->params = uri->query = NULL; - - /* a quick validity check */ - if( strspn( p, VALID_URI_CHARS) != n ) - return G10ERR_BAD_URI; /* invalid characters found */ - - if( !only_local_part ) { - /* find the scheme */ - if( !(p2 = strchr( p, ':' ) ) || p2 == p ) - return G10ERR_BAD_URI; /* No scheme */ - *p2++ = 0; - strlwr( p ); - uri->scheme = p; - uri->port = 80; - if( !strcmp( uri->scheme, "http" ) ) - ; - else if( !strcmp( uri->scheme, "x-hkp" ) ) /* same as HTTP */ - uri->port = 11371; - else - return G10ERR_INVALID_URI; /* Unsupported scheme */ - - p = p2; - - /* find the hostname */ - if( *p != '/' ) - return G10ERR_INVALID_URI; /* does not start with a slash */ - - p++; - if( *p == '/' ) { /* there seems to be a hostname */ - p++; - if( (p2 = strchr(p, '/')) ) - *p2++ = 0; - strlwr( p ); - uri->host = p; - if( (p3=strchr( p, ':' )) ) { - *p3++ = 0; - uri->port = atoi( p3 ); - } - - uri->host = p; - if( (n = remove_escapes( uri->host )) < 0 ) - return G10ERR_BAD_URI; - if( n != strlen( p ) ) - return G10ERR_BAD_URI; /* hostname with a Nul in it */ - p = p2 ? p2 : NULL; - } - } /* end global URI part */ - - /* parse the pathname part */ - if( !p || !*p ) /* we don't have a path */ - return 0; /* and this is okay */ - - /* todo: here we have to check params */ - - /* do we have a query part */ - if( (p2 = strchr( p, '?' )) ) - *p2++ = 0; - - uri->path = p; - if( (n = remove_escapes( p )) < 0 ) - return G10ERR_BAD_URI; - if( n != strlen( p ) ) - return G10ERR_BAD_URI; /* path with a Nul in it */ - p = p2 ? p2 : NULL; - - if( !p || !*p ) /* we don't have a query string */ - return 0; /* okay */ - - /* now parse the query string */ - tail = &uri->query; - for(;;) { - URI_TUPLE elem; - - if( (p2 = strchr( p, '&' )) ) - *p2++ = 0; - if( !(elem = parse_tuple( p )) ) - return G10ERR_BAD_URI; - *tail = elem; - tail = &elem->next; - - if( !p2 ) - break; /* ready */ - p = p2; - } - - return 0; -} - - - -/**************** - * Remove all %xx escapes; this is done inplace. - * Returns: new length of the string. - */ -static int -remove_escapes( byte *string ) -{ - int n = 0; - byte *p, *s; - - for(p=s=string; *s ; s++ ) { - if( *s == '%' ) { - if( s[1] && s[2] && isxdigit(s[1]) && isxdigit(s[2]) ) { - s++; - *p = *s >= '0' && *s <= '9' ? *s - '0' : - *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10 ; - *p <<= 4; - s++; - *p |= *s >= '0' && *s <= '9' ? *s - '0' : - *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10 ; - p++; - n++; - } - else { - *p++ = *s++; - if( *s ) - *p++ = *s++; - if( *s ) - *p++ = *s++; - if( *s ) - *p = 0; - return -1; /* bad URI */ - } - } - else - { - *p++ = *s; - n++; - } - } - *p = 0; /* always keep a string terminator */ - return n; -} - - -static int -insert_escapes( byte *buffer, const byte *string, const byte *special ) -{ - int n = 0; - - for( ; *string; string++ ) { - if( strchr( VALID_URI_CHARS, *string ) - && !strchr( special, *string ) ) { - if( buffer ) - *buffer++ = *string; - n++; - } - else { - if( buffer ) { - sprintf( buffer, "%02X", *string ); - buffer += 3; - } - n += 3; - } - } - return n; -} - - - - - -static URI_TUPLE -parse_tuple( byte *string ) -{ - byte *p = string; - byte *p2; - int n; - URI_TUPLE tuple; - - if( (p2 = strchr( p, '=' )) ) - *p2++ = 0; - if( (n = remove_escapes( p )) < 0 ) - return NULL; /* bad URI */ - if( n != strlen( p ) ) - return NULL; /* name with a Nul in it */ - tuple = m_alloc_clear( sizeof *tuple ); - tuple->name = p; - if( !p2 ) { - /* we have only the name, so we assume an empty value string */ - tuple->value = p + strlen(p); - tuple->valuelen = 0; - } - else { /* name and value */ - if( (n = remove_escapes( p2 )) < 0 ) { - m_free( tuple ); - return NULL; /* bad URI */ - } - tuple->value = p2; - tuple->valuelen = n; - } - return tuple; -} - - -/**************** - * Send a HTTP request to the server - * Returns 0 if the request was successful - */ -static int -send_request( HTTP_HD hd ) -{ - const byte *server; - byte *request, *p; - ushort port; - int rc; - const char *http_proxy = NULL; - - server = *hd->uri->host? hd->uri->host : "localhost"; - port = hd->uri->port? hd->uri->port : 80; - - if( (hd->flags & HTTP_FLAG_TRY_PROXY) - && (http_proxy = getenv( HTTP_PROXY_ENV )) ) { - PARSED_URI uri; - - rc = parse_uri( &uri, http_proxy ); - if (rc) { - log_error("invalid " HTTP_PROXY_ENV_PRINTABLE ": %s\n", - g10_errstr(rc)); - release_parsed_uri( uri ); - return G10ERR_NETWORK; - } - hd->sock = connect_server( *uri->host? uri->host : "localhost", - uri->port? uri->port : 80 ); - release_parsed_uri( uri ); - } - else - hd->sock = connect_server( server, port ); - - if( hd->sock == -1 ) - return G10ERR_NETWORK; - - p = build_rel_path( hd->uri ); - request = m_alloc( strlen(server) + strlen(p) + 50 ); - if( http_proxy ) { - sprintf( request, "%s http://%s:%hu%s%s HTTP/1.0\r\n", - hd->req_type == HTTP_REQ_GET ? "GET" : - hd->req_type == HTTP_REQ_HEAD? "HEAD": - hd->req_type == HTTP_REQ_POST? "POST": "OOPS", - server, port, *p == '/'? "":"/", p ); - } - else { - sprintf( request, "%s %s%s HTTP/1.0\r\n", - hd->req_type == HTTP_REQ_GET ? "GET" : - hd->req_type == HTTP_REQ_HEAD? "HEAD": - hd->req_type == HTTP_REQ_POST? "POST": "OOPS", - *p == '/'? "":"/", p ); - } - m_free(p); - - rc = write_server( hd->sock, request, strlen(request) ); - m_free( request ); - - return rc; -} - - - - -/**************** - * Build the relative path from the parsed URI. - * Minimal implementation. - */ -static byte* -build_rel_path( PARSED_URI uri ) -{ - URI_TUPLE r; - byte *rel_path, *p; - int n; - - /* count the needed space */ - n = insert_escapes( NULL, uri->path, "%;?&" ); - /* todo: build params */ - for( r=uri->query; r; r = r->next ) { - n++; /* '?'/'&' */ - n += insert_escapes( NULL, r->name, "%;?&=" ); - n++; /* '='*/ - n += insert_escapes( NULL, r->value, "%;?&=" ); - } - n++; - - /* now allocate and copy */ - p = rel_path = m_alloc( n ); - n = insert_escapes( p, uri->path, "%;?&" ); - p += n; - /* todo: add params */ - for( r=uri->query; r; r = r->next ) { - *p++ = r == uri->query? '?':'&'; - n = insert_escapes( p, r->name, "%;?&=" ); - p += n; - *p++ = '='; - /* todo: use valuelen */ - n = insert_escapes( p, r->value, "%;?&=" ); - p += n; - } - *p = 0; - return rel_path; -} - - - -/*********************** - * Parse the response from a server. - * Returns: errorcode and sets some fileds in the handle - */ -static int -parse_response( HTTP_HD hd ) -{ - byte *line, *p, *p2; - unsigned maxlen, len; - - /* Wait for the status line */ - do { - maxlen = MAX_LINELEN; - len = iobuf_read_line( hd->fp_read, &hd->buffer, - &hd->buffer_size, &maxlen ); - line = hd->buffer; - if( !maxlen ) - return -1; /* line has been truncated */ - if( !len ) - return -1; /* eof */ - } while( !*line ); - - if( (p = strchr( line, '/')) ) - *p++ = 0; - if( !p || strcmp( line, "HTTP" ) ) - return 0; /* assume http 0.9 */ - - if( (p2 = strpbrk( p, " \t" ) ) ) { - *p2++ = 0; - p2 += strspn( p2, " \t" ); - } - if( !p2 ) - return 0; /* assume http 0.9 */ - p = p2; - /* todo: add HTTP version number check here */ - if( (p2 = strpbrk( p, " \t" ) ) ) - *p2++ = 0; - if( !isdigit(p[0]) || !isdigit(p[1]) || !isdigit(p[2]) || p[3] ) { - /* malformed HTTP statuscode - assume HTTP 0.9 */ - hd->is_http_0_9 = 1; - hd->status_code = 200; - return 0; - } - hd->status_code = atoi( p ); - - /* skip all the header lines and wait for the empty line */ - do { - maxlen = MAX_LINELEN; - len = iobuf_read_line( hd->fp_read, &hd->buffer, - &hd->buffer_size, &maxlen ); - line = hd->buffer; - /* we ignore truncated lines */ - if( !len ) - return -1; /* eof */ - /* time lineendings */ - if( (*line == '\r' && line[1] == '\n') || *line == '\n' ) - *line = 0; - } while( len && *line ); - - return 0; -} - -#if 0 -static int -start_server() -{ - struct sockaddr_in mya; - struct sockaddr_in peer; - int fd, client; - fd_set rfds; - int addrlen; - int i; - - if( (fd=socket(AF_INET,SOCK_STREAM, 0)) == -1 ) { - log_error("socket() failed: %s\n", strerror(errno)); - return -1; - } - i = 1; - if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (byte*)&i, sizeof(i) ) ) - log_info("setsockopt(SO_REUSEADDR) failed: %s\n", strerror(errno) ); - - mya.sin_family=AF_INET; - memset(&mya.sin_addr, 0, sizeof(mya.sin_addr)); - mya.sin_port=htons(11371); - - if( bind( fd, (struct sockaddr *)&mya, sizeof(mya)) ) { - log_error("bind to port 11371 failed: %s\n", strerror(errno) ); - sock_close( fd ); - return -1; - } - - if( listen( fd, 5 ) ) { - log_error("listen failed: %s\n", strerror(errno) ); - sock_close( fd ); - return -1; - } - - for(;;) { - FD_ZERO(&rfds); - FD_SET( fd, &rfds ); - - if( select( fd+1, &rfds, NULL, NULL, NULL) <= 0 ) - continue; /* ignore any errors */ - - if( !FD_ISSET( fd, &rfds ) ) - continue; - - addrlen = sizeof peer; - client = accept( fd, (struct sockaddr *)&peer, &addrlen); - if( client == -1 ) - continue; /* oops */ - - log_info("connect from %s\n", inet_ntoa( peer.sin_addr ) ); - - fflush(stdout); - fflush(stderr); - if( !fork() ) { - int c; - FILE *fp; - - fp = fdopen( client , "r" ); - while( (c=getc(fp)) != EOF ) - putchar(c); - fclose(fp); - exit(0); - } - sock_close( client ); - } - - - return 0; -} -#endif - - - -static int -connect_server( const char *server, ushort port ) -{ - int sock,i=0; - struct sockaddr_in addr; - struct hostent *host=NULL; - unsigned long l; - - memset(&addr,0,sizeof(addr)); - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - -#ifdef __MINGW32__ - init_sockets (); - - if((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET) - { - log_error("error creating socket: ec=%d\n",(int)WSAGetLastError()); - return -1; - } -#else - if((sock=socket(AF_INET,SOCK_STREAM,0))==-1) - { - log_error("error creating socket\n"); - return -1; - } -#endif - -#ifdef __MINGW32__ - /* Win32 gethostbyname doesn't handle IP addresses internally, so we - try inet_addr first on that platform only. */ - if((l=inet_addr(server))==SOCKET_ERROR) -#endif - if((host=gethostbyname(server))==NULL) - { -#ifdef __MINGW32__ - log_error("%s: host not found: ec=%d\n",server,(int)WSAGetLastError()); -#else - log_error("%s: host not found\n",server); -#endif - sock_close(sock); - return -1; - } - - if(host) - { - if(host->h_addrtype != AF_INET) - { - log_error ("%s: unknown address family\n", server); - sock_close(sock); - return -1; - } - - if(host->h_length != 4 ) - { - log_error ("%s: illegal address length\n", server); - sock_close(sock); - return -1; - } - - /* Try all A records until one responds. */ - while(host->h_addr_list[i]) - { - memcpy(&addr.sin_addr,host->h_addr_list[i],host->h_length); - - if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0) - break; - - i++; - } - - if(host->h_addr_list[i]==0) - { - sock_close(sock); - return -1; - } - } - else - { - memcpy(&addr.sin_addr,&l,sizeof(l)); - - if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))!=0) - { - sock_close(sock); - return -1; - } - } - - return sock; -} - - -static int -write_server( int sock, const char *data, size_t length ) -{ - int nleft; - - nleft = length; - while( nleft > 0 ) { - #ifdef __MINGW32__ - int nwritten; - - nwritten = send (sock, data, nleft, 0); - if ( nwritten == SOCKET_ERROR ) { - log_info ("write failed: ec=%d\n", (int)WSAGetLastError ()); - return G10ERR_NETWORK; - } - #else - int nwritten = write( sock, data, nleft ); - if( nwritten == -1 ) { - if( errno == EINTR ) - continue; - if( errno == EAGAIN ) { - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 50000; - select(0, NULL, NULL, NULL, &tv); - continue; - } - log_info("write failed: %s\n", strerror(errno)); - return G10ERR_NETWORK; - } - #endif - nleft -=nwritten; - data += nwritten; - } - - return 0; -} - -/**** Test code ****/ -#ifdef TEST - -int -main(int argc, char **argv) -{ - int rc; - PARSED_URI uri; - URI_TUPLE r; - struct http_context hd; - int c; - - log_set_name("http-test"); - if( argc == 1 ) { - start_server(); - return 0; - } - - if( argc != 2 ) { - fprintf(stderr,"usage: http-test uri\n"); - return 1; - } - argc--; argv++; - - rc = parse_uri( &uri, *argv ); - if( rc ) { - log_error("`%s': %s\n", *argv, g10_errstr(rc)); - release_parsed_uri( uri ); - return 1; - } - - printf("Scheme: %s\n", uri->scheme ); - printf("Host : %s\n", uri->host ); - printf("Port : %u\n", uri->port ); - printf("Path : %s\n", uri->path ); - for( r=uri->params; r; r = r->next ) { - printf("Params: %s=%s", r->name, r->value ); - if( strlen( r->value ) != r->valuelen ) - printf(" [real length=%d]", (int)r->valuelen ); - putchar('\n'); - } - for( r=uri->query; r; r = r->next ) { - printf("Query : %s=%s", r->name, r->value ); - if( strlen( r->value ) != r->valuelen ) - printf(" [real length=%d]", (int)r->valuelen ); - putchar('\n'); - } - release_parsed_uri( uri ); uri = NULL; - - rc = http_open_document( &hd, *argv, 0 ); - if( rc ) { - log_error("can't get `%s': %s\n", *argv, g10_errstr(rc)); - return 1; - } - log_info("open_http_document succeeded; status=%u\n", hd.status_code ); - while( (c=iobuf_get( hd.fp_read)) != -1 ) - putchar(c); - http_close( &hd ); - return 0; -} -#endif /*TEST*/ diff --git a/util/iobuf.c b/util/iobuf.c deleted file mode 100644 index a3e9ad3e6..000000000 --- a/util/iobuf.c +++ /dev/null @@ -1,2189 +0,0 @@ -/* iobuf.c - file handling - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_DOSISH_SYSTEM - #include -#endif -#ifdef __riscos__ -#include -#include -#endif /* __riscos__ */ - -#include "memory.h" -#include "util.h" -#include "iobuf.h" - -#undef FILE_FILTER_USES_STDIO - -#ifdef HAVE_DOSISH_SYSTEM - #define USE_SETMODE 1 -#endif - -#ifdef FILE_FILTER_USES_STDIO - #define my_fileno(a) fileno ((a)) - #define my_fopen_ro(a,b) fopen ((a),(b)) - #define my_fopen(a,b) fopen ((a),(b)) - typedef FILE *FILEP_OR_FD; - #define INVALID_FP NULL - #define FILEP_OR_FD_FOR_STDIN (stdin) - #define FILEP_OR_FD_FOR_STDOUT (stdout) - typedef struct { - FILE *fp; /* open file handle */ - int keep_open; - int no_cache; - int print_only_name; /* flags indicating that fname is not a real file*/ - char fname[1]; /* name of the file */ - } file_filter_ctx_t ; -#else - #define my_fileno(a) (a) - #define my_fopen_ro(a,b) fd_cache_open ((a),(b)) - #define my_fopen(a,b) direct_open ((a),(b)) - #ifdef HAVE_DOSISH_SYSTEM - typedef HANDLE FILEP_OR_FD; - #define INVALID_FP ((HANDLE)-1) - #define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE)) - #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE)) - #undef USE_SETMODE - #else - typedef int FILEP_OR_FD; - #define INVALID_FP (-1) - #define FILEP_OR_FD_FOR_STDIN (0) - #define FILEP_OR_FD_FOR_STDOUT (1) - #endif - typedef struct { - FILEP_OR_FD fp; /* open file handle */ - int keep_open; - int no_cache; - int eof_seen; - int print_only_name; /* flags indicating that fname is not a real file*/ - char fname[1]; /* name of the file */ - } file_filter_ctx_t ; - - struct close_cache_s { - struct close_cache_s *next; - FILEP_OR_FD fp; - char fname[1]; - }; - typedef struct close_cache_s *CLOSE_CACHE; - static CLOSE_CACHE close_cache; -#endif - -#ifdef __MINGW32__ -typedef struct { - int sock; - int keep_open; - int no_cache; - int eof_seen; - int print_only_name; /* flags indicating that fname is not a real file*/ - char fname[1]; /* name of the file */ -} sock_filter_ctx_t ; -#endif /*__MINGW32__*/ - -/* The first partial length header block must be of size 512 - * to make it easier (and efficienter) we use a min. block size of 512 - * for all chunks (but the last one) */ -#define OP_MIN_PARTIAL_CHUNK 512 -#define OP_MIN_PARTIAL_CHUNK_2POW 9 - -typedef struct { - int use; - size_t size; - size_t count; - int partial; /* 1 = partial header, 2 in last partial packet */ - char *buffer; /* used for partial header */ - size_t buflen; /* used size of buffer */ - int first_c; /* of partial header (which is > 0)*/ - int eof; -} block_filter_ctx_t; - -static int special_names_enabled; - -static int underflow(IOBUF a); -static int translate_file_handle ( int fd, int for_write ); - -#ifndef FILE_FILTER_USES_STDIO - -/* - * Invalidate (i.e. close) a cached iobuf - */ -static void -fd_cache_invalidate (const char *fname) -{ - CLOSE_CACHE cc; - - assert (fname); - if( DBG_IOBUF ) - log_debug ("fd_cache_invalidate (%s)\n", fname); - - for (cc=close_cache; cc; cc = cc->next ) { - if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { - if( DBG_IOBUF ) - log_debug (" did (%s)\n", cc->fname); - #ifdef HAVE_DOSISH_SYSTEM - CloseHandle (cc->fp); - #else - close(cc->fp); - #endif - cc->fp = INVALID_FP; - } - } -} - - - -static FILEP_OR_FD -direct_open (const char *fname, const char *mode) -{ -#ifdef HAVE_DOSISH_SYSTEM - unsigned long da, cd, sm; - HANDLE hfile; - - /* Note, that we do not handle all mode combinations */ - - /* According to the ReactOS source it seems that open() of the - * standard MSW32 crt does open the file in share mode which is - * something new for MS applications ;-) - */ - if ( strchr (mode, '+') ) { - fd_cache_invalidate (fname); - da = GENERIC_READ|GENERIC_WRITE; - cd = OPEN_EXISTING; - sm = FILE_SHARE_READ | FILE_SHARE_WRITE; - } - else if ( strchr (mode, 'w') ) { - fd_cache_invalidate (fname); - da = GENERIC_WRITE; - cd = CREATE_ALWAYS; - sm = FILE_SHARE_WRITE; - } - else { - da = GENERIC_READ; - cd = OPEN_EXISTING; - sm = FILE_SHARE_READ; - } - - hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL); - return hfile; -#else - int oflag; - int cflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; - - /* Note, that we do not handle all mode combinations */ - if ( strchr (mode, '+') ) { - fd_cache_invalidate (fname); - oflag = O_RDWR; - } - else if ( strchr (mode, 'w') ) { - fd_cache_invalidate (fname); - oflag = O_WRONLY | O_CREAT | O_TRUNC; - } - else { - oflag = O_RDONLY; - } -#ifndef __riscos__ - return open (fname, oflag, cflag ); -#else - { - struct stat buf; - int rc = stat( fname, &buf ); - - /* Don't allow iobufs on directories */ - if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) ) - return __set_errno( EISDIR ); - else - return open( fname, oflag, cflag ); - } -#endif -#endif -} - - -/* - * Instead of closing an FD we keep it open and cache it for later reuse - * Note that this caching strategy only works if the process does not chdir. - */ -static void -fd_cache_close (const char *fname, FILEP_OR_FD fp) -{ - CLOSE_CACHE cc; - - assert (fp); - if ( !fname || !*fname ) { -#ifdef HAVE_DOSISH_SYSTEM - CloseHandle (fp); -#else - close(fp); -#endif - if( DBG_IOBUF ) - log_debug ("fd_cache_close (%p) real\n", (void*)fp); - return; - } - /* try to reuse a slot */ - for (cc=close_cache; cc; cc = cc->next ) { - if ( cc->fp == INVALID_FP && !strcmp (cc->fname, fname) ) { - cc->fp = fp; - if( DBG_IOBUF ) - log_debug ("fd_cache_close (%s) used existing slot\n", fname); - return; - } - } - /* add a new one */ - if( DBG_IOBUF ) - log_debug ("fd_cache_close (%s) new slot created\n", fname); - cc = m_alloc_clear (sizeof *cc + strlen (fname)); - strcpy (cc->fname, fname); - cc->fp = fp; - cc->next = close_cache; - close_cache = cc; -} - -/* - * Do an direct_open on FNAME but first try to reuse one from the fd_cache - */ -static FILEP_OR_FD -fd_cache_open (const char *fname, const char *mode) -{ - CLOSE_CACHE cc; - - assert (fname); - for (cc=close_cache; cc; cc = cc->next ) { - if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) { - FILEP_OR_FD fp = cc->fp; - cc->fp = INVALID_FP; - if( DBG_IOBUF ) - log_debug ("fd_cache_open (%s) using cached fp\n", fname); - #ifdef HAVE_DOSISH_SYSTEM - if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) { - log_error ("rewind file failed on handle %p: ec=%d\n", - fp, (int)GetLastError () ); - fp = INVALID_FP; - } - #else - if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) { - log_error("can't rewind fd %d: %s\n", fp, strerror(errno) ); - fp = INVALID_FP; - } - #endif - return fp; - } - } - if( DBG_IOBUF ) - log_debug ("fd_cache_open (%s) not cached\n", fname); - return direct_open (fname, mode); -} - - -#endif /*FILE_FILTER_USES_STDIO*/ - - -/**************** - * Read data from a file into buf which has an allocated length of *LEN. - * return the number of read bytes in *LEN. OPAQUE is the FILE * of - * the stream. A is not used. - * control may be: - * IOBUFCTRL_INIT: called just before the function is linked into the - * list of function. This can be used to prepare internal - * data structures of the function. - * IOBUFCTRL_FREE: called just before the function is removed from the - * list of functions and can be used to release internal - * data structures or close a file etc. - * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer - * with new stuff. *RET_LEN is the available size of the - * buffer, and should be set to the number of bytes - * which were put into the buffer. The function - * returns 0 to indicate success, -1 on EOF and - * G10ERR_xxxxx for other errors. - * - * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff. - * *RET_LAN is the number of bytes in BUF. - * - * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The - * filter may take appropriate action on this message. - */ -static int -file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) -{ - file_filter_ctx_t *a = opaque; - FILEP_OR_FD f = a->fp; - size_t size = *ret_len; - size_t nbytes = 0; - int rc = 0; - -#ifdef FILE_FILTER_USES_STDIO - if( control == IOBUFCTRL_UNDERFLOW ) { - assert( size ); /* need a buffer */ - if ( feof(f)) { /* On terminals you could easiely read as many EOFs as you call */ - rc = -1; /* fread() or fgetc() repeatly. Every call will block until you press */ - *ret_len = 0; /* CTRL-D. So we catch this case before we call fread() again. */ - } - else { - clearerr( f ); - nbytes = fread( buf, 1, size, f ); - if( feof(f) && !nbytes ) { - rc = -1; /* okay: we can return EOF now. */ - } - else if( ferror(f) && errno != EPIPE ) { - log_error("%s: read error: %s\n", - a->fname, strerror(errno)); - rc = G10ERR_READ_FILE; - } - *ret_len = nbytes; - } - } - else if( control == IOBUFCTRL_FLUSH ) { - if( size ) { - clearerr( f ); - nbytes = fwrite( buf, 1, size, f ); - if( ferror(f) ) { - log_error("%s: write error: %s\n", a->fname, strerror(errno)); - rc = G10ERR_WRITE_FILE; - } - } - *ret_len = nbytes; - } - else if( control == IOBUFCTRL_INIT ) { - a->keep_open = a->no_cache = 0; - } - else if( control == IOBUFCTRL_DESC ) { - *(char**)buf = "file_filter"; - } - else if( control == IOBUFCTRL_FREE ) { - if( f != stdin && f != stdout ) { - if( DBG_IOBUF ) - log_debug("%s: close fd %d\n", a->fname, fileno(f) ); - if (!a->keep_open) - fclose(f); - } - f = NULL; - m_free(a); /* we can free our context now */ - } -#else /* !stdio implementation */ - - if( control == IOBUFCTRL_UNDERFLOW ) { - assert( size ); /* need a buffer */ - if ( a->eof_seen) { - rc = -1; - *ret_len = 0; - } - else { - #ifdef HAVE_DOSISH_SYSTEM - unsigned long nread; - - nbytes = 0; - if ( !ReadFile ( f, buf, size, &nread, NULL ) ) { - int ec = (int)GetLastError (); - if ( ec != ERROR_BROKEN_PIPE ) { - log_error("%s: read error: ec=%d\n", a->fname, ec); - rc = G10ERR_READ_FILE; - } - } - else if ( !nread ) { - a->eof_seen = 1; - rc = -1; - } - else { - nbytes = nread; - } - - #else - - int n; - - nbytes = 0; - do { - n = read ( f, buf, size ); - } while (n == -1 && errno == EINTR ); - if ( n == -1 ) { /* error */ - if (errno != EPIPE) { - log_error("%s: read error: %s\n", - a->fname, strerror(errno)); - rc = G10ERR_READ_FILE; - } - } - else if ( !n ) { /* eof */ - a->eof_seen = 1; - rc = -1; - } - else { - nbytes = n; - } - #endif - *ret_len = nbytes; - } - } - else if( control == IOBUFCTRL_FLUSH ) { - if( size ) { - #ifdef HAVE_DOSISH_SYSTEM - byte *p = buf; - unsigned long n; - - nbytes = size; - do { - if ( size && !WriteFile ( f, p, nbytes, &n, NULL) ) { - int ec = (int)GetLastError (); - log_error("%s: write error: ec=%d\n", a->fname, ec); - rc = G10ERR_WRITE_FILE; - break; - } - p += n; - nbytes -= n; - } while ( nbytes ); - nbytes = p - buf; - #else - byte *p = buf; - int n; - - nbytes = size; - do { - do { - n = write ( f, p, nbytes ); - } while ( n == -1 && errno == EINTR ); - if ( n > 0 ) { - p += n; - nbytes -= n; - } - } while ( n != -1 && nbytes ); - if( n == -1 ) { - log_error("%s: write error: %s\n", a->fname, strerror(errno)); - rc = G10ERR_WRITE_FILE; - } - nbytes = p - buf; - #endif - } - *ret_len = nbytes; - } - else if ( control == IOBUFCTRL_INIT ) { - a->eof_seen = 0; - a->keep_open = 0; - a->no_cache = 0; - } - else if ( control == IOBUFCTRL_DESC ) { - *(char**)buf = "file_filter(fd)"; - } - else if ( control == IOBUFCTRL_FREE ) { - #ifdef HAVE_DOSISH_SYSTEM - if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) { - if( DBG_IOBUF ) - log_debug("%s: close handle %p\n", a->fname, f ); - if (!a->keep_open) - fd_cache_close (a->no_cache?NULL:a->fname, f); - } - #else - if ( (int)f != 0 && (int)f != 1 ) { - if( DBG_IOBUF ) - log_debug("%s: close fd %d\n", a->fname, f ); - if (!a->keep_open) - fd_cache_close (a->no_cache?NULL:a->fname, f); - } - f = INVALID_FP; - #endif - m_free (a); /* we can free our context now */ - } -#endif /* !stdio implementation */ - return rc; -} - -#ifdef __MINGW32__ -/* Becuase sockets are an special object under Lose32 we have to - * use a special filter */ -static int -sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) -{ - sock_filter_ctx_t *a = opaque; - size_t size = *ret_len; - size_t nbytes = 0; - int rc = 0; - - if( control == IOBUFCTRL_UNDERFLOW ) { - assert( size ); /* need a buffer */ - if ( a->eof_seen) { - rc = -1; - *ret_len = 0; - } - else { - int nread; - - nread = recv ( a->sock, buf, size, 0 ); - if ( nread == SOCKET_ERROR ) { - int ec = (int)WSAGetLastError (); - log_error("socket read error: ec=%d\n", ec); - rc = G10ERR_READ_FILE; - } - else if ( !nread ) { - a->eof_seen = 1; - rc = -1; - } - else { - nbytes = nread; - } - *ret_len = nbytes; - } - } - else if( control == IOBUFCTRL_FLUSH ) { - if( size ) { - byte *p = buf; - int n; - - nbytes = size; - do { - n = send (a->sock, p, nbytes, 0); - if ( n == SOCKET_ERROR ) { - int ec = (int)WSAGetLastError (); - log_error("socket write error: ec=%d\n", ec); - rc = G10ERR_WRITE_FILE; - break; - } - p += n; - nbytes -= n; - } while ( nbytes ); - nbytes = p - buf; - } - *ret_len = nbytes; - } - else if ( control == IOBUFCTRL_INIT ) { - a->eof_seen = 0; - a->keep_open = 0; - a->no_cache = 0; - } - else if ( control == IOBUFCTRL_DESC ) { - *(char**)buf = "sock_filter"; - } - else if ( control == IOBUFCTRL_FREE ) { - if (!a->keep_open) - closesocket (a->sock); - m_free (a); /* we can free our context now */ - } - return rc; -} -#endif /*__MINGW32__*/ - -/**************** - * This is used to implement the block write mode. - * Block reading is done on a byte by byte basis in readbyte(), - * without a filter - */ -static int -block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len) -{ - block_filter_ctx_t *a = opaque; - size_t size = *ret_len; - int c, needed, rc = 0; - char *p; - - if( control == IOBUFCTRL_UNDERFLOW ) { - size_t n=0; - - p = buf; - assert( size ); /* need a buffer */ - if( a->eof ) /* don't read any further */ - rc = -1; - while( !rc && size ) { - if( !a->size ) { /* get the length bytes */ - if( a->partial == 2 ) { - a->eof = 1; - if( !n ) - rc = -1; - break; - } - else if( a->partial ) { - /* These OpenPGP introduced huffman like encoded length - * bytes are really a mess :-( */ - if( a->first_c ) { - c = a->first_c; - a->first_c = 0; - } - else if( (c = iobuf_get(chain)) == -1 ) { - log_error("block_filter: 1st length byte missing\n"); - rc = G10ERR_READ_FILE; - break; - } - if( c < 192 ) { - a->size = c; - a->partial = 2; - if( !a->size ) { - a->eof = 1; - if( !n ) - rc = -1; - break; - } - } - else if( c < 224 ) { - a->size = (c - 192) * 256; - if( (c = iobuf_get(chain)) == -1 ) { - log_error("block_filter: 2nd length byte missing\n"); - rc = G10ERR_READ_FILE; - break; - } - a->size += c + 192; - a->partial = 2; - if( !a->size ) { - a->eof = 1; - if( !n ) - rc = -1; - break; - } - } - else if( c == 255 ) { - a->size = iobuf_get(chain) << 24; - a->size |= iobuf_get(chain) << 16; - a->size |= iobuf_get(chain) << 8; - if( (c = iobuf_get(chain)) == -1 ) { - log_error("block_filter: invalid 4 byte length\n"); - rc = G10ERR_READ_FILE; - break; - } - a->size |= c; - } - else { /* next partial body length */ - a->size = 1 << (c & 0x1f); - } - /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/ - } - else { /* the gnupg partial length scheme - much better :-) */ - c = iobuf_get(chain); - a->size = c << 8; - c = iobuf_get(chain); - a->size |= c; - if( c == -1 ) { - log_error("block_filter: error reading length info\n"); - rc = G10ERR_READ_FILE; - } - if( !a->size ) { - a->eof = 1; - if( !n ) - rc = -1; - break; - } - } - } - - while( !rc && size && a->size ) { - needed = size < a->size ? size : a->size; - c = iobuf_read( chain, p, needed ); - if( c < needed ) { - if( c == -1 ) c = 0; - log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n", - a, (ulong)size+c, (ulong)a->size+c); - rc = G10ERR_READ_FILE; - } - else { - size -= c; - a->size -= c; - p += c; - n += c; - } - } - } - *ret_len = n; - } - else if( control == IOBUFCTRL_FLUSH ) { - if( a->partial ) { /* the complicated openpgp scheme */ - size_t blen, n, nbytes = size + a->buflen; - - assert( a->buflen <= OP_MIN_PARTIAL_CHUNK ); - if( nbytes < OP_MIN_PARTIAL_CHUNK ) { - /* not enough to write a partial block out; so we store it*/ - if( !a->buffer ) - a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK ); - memcpy( a->buffer + a->buflen, buf, size ); - a->buflen += size; - } - else { /* okay, we can write out something */ - /* do this in a loop to use the most efficient block lengths */ - p = buf; - do { - /* find the best matching block length - this is limited - * by the size of the internal buffering */ - for( blen=OP_MIN_PARTIAL_CHUNK*2, - c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes; - blen *=2, c++ ) - ; - blen /= 2; c--; - /* write the partial length header */ - assert( c <= 0x1f ); /*;-)*/ - c |= 0xe0; - iobuf_put( chain, c ); - if( (n=a->buflen) ) { /* write stuff from the buffer */ - assert( n == OP_MIN_PARTIAL_CHUNK); - if( iobuf_write(chain, a->buffer, n ) ) - rc = G10ERR_WRITE_FILE; - a->buflen = 0; - nbytes -= n; - } - if( (n = nbytes) > blen ) - n = blen; - if( n && iobuf_write(chain, p, n ) ) - rc = G10ERR_WRITE_FILE; - p += n; - nbytes -= n; - } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK ); - /* store the rest in the buffer */ - if( !rc && nbytes ) { - assert( !a->buflen ); - assert( nbytes < OP_MIN_PARTIAL_CHUNK ); - if( !a->buffer ) - a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK ); - memcpy( a->buffer, p, nbytes ); - a->buflen = nbytes; - } - } - } - else { /* the gnupg scheme (which is not openpgp compliant) */ - size_t avail, n; - - for(p=buf; !rc && size; ) { - n = size; - avail = a->size - a->count; - if( !avail ) { - if( n > a->size ) { - iobuf_put( chain, (a->size >> 8) & 0xff ); - iobuf_put( chain, a->size & 0xff ); - avail = a->size; - a->count = 0; - } - else { - iobuf_put( chain, (n >> 8) & 0xff ); - iobuf_put( chain, n & 0xff ); - avail = n; - a->count = a->size - n; - } - } - if( n > avail ) - n = avail; - if( iobuf_write(chain, p, n ) ) - rc = G10ERR_WRITE_FILE; - a->count += n; - p += n; - size -= n; - } - } - } - else if( control == IOBUFCTRL_INIT ) { - if( DBG_IOBUF ) - log_debug("init block_filter %p\n", a ); - if( a->partial ) - a->count = 0; - else if( a->use == 1 ) - a->count = a->size = 0; - else - a->count = a->size; /* force first length bytes */ - a->eof = 0; - a->buffer = NULL; - a->buflen = 0; - } - else if( control == IOBUFCTRL_DESC ) { - *(char**)buf = "block_filter"; - } - else if( control == IOBUFCTRL_FREE ) { - if( a->use == 2 ) { /* write the end markers */ - if( a->partial ) { - u32 len; - /* write out the remaining bytes without a partial header - * the length of this header may be 0 - but if it is - * the first block we are not allowed to use a partial header - * and frankly we can't do so, because this length must be - * a power of 2. This is _really_ complicated because we - * have to check the possible length of a packet prior - * to it's creation: a chain of filters becomes complicated - * and we need a lot of code to handle compressed packets etc. - * :-((((((( - */ - /* construct header */ - len = a->buflen; - /*log_debug("partial: remaining length=%u\n", len );*/ - if( len < 192 ) - rc = iobuf_put(chain, len ); - else if( len < 8384 ) { - if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) ) - rc = iobuf_put( chain, ((len-192) % 256)); - } - else { /* use a 4 byte header */ - if( !(rc=iobuf_put( chain, 0xff )) ) - if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) ) - if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) ) - if( !(rc=iobuf_put( chain, (len >> 8)&0xff ))) - rc=iobuf_put( chain, len & 0xff ); - } - if( !rc && len ) - rc = iobuf_write(chain, a->buffer, len ); - if( rc ) { - log_error("block_filter: write error: %s\n",strerror(errno)); - rc = G10ERR_WRITE_FILE; - } - m_free( a->buffer ); a->buffer = NULL; a->buflen = 0; - } - else { - iobuf_writebyte(chain, 0); - iobuf_writebyte(chain, 0); - } - } - else if( a->size ) { - log_error("block_filter: pending bytes!\n"); - } - if( DBG_IOBUF ) - log_debug("free block_filter %p\n", a ); - m_free(a); /* we can free our context now */ - } - - return rc; -} - - -static void -print_chain( IOBUF a ) -{ - if( !DBG_IOBUF ) - return; - for(; a; a = a->chain ) { - size_t dummy_len = 0; - const char *desc = "[none]"; - - if( a->filter ) - a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL, - (byte*)&desc, &dummy_len ); - - log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n", - a->no, a->subno, desc, a->filter_eof, - (int)a->d.start, (int)a->d.len ); - } -} - -int -iobuf_print_chain( IOBUF a ) -{ - print_chain(a); - return 0; -} - -/**************** - * Allocate a new io buffer, with no function assigned. - * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer - * BUFSIZE is a suggested buffer size. - */ -IOBUF -iobuf_alloc(int use, size_t bufsize) -{ - IOBUF a; - static int number=0; - - a = m_alloc_clear(sizeof *a); - a->use = use; - a->d.buf = m_alloc( bufsize ); - a->d.size = bufsize; - a->no = ++number; - a->subno = 0; - a->opaque = NULL; - a->real_fname = NULL; - return a; -} - -int -iobuf_close ( IOBUF a ) -{ - IOBUF a2; - size_t dummy_len=0; - int rc=0; - - if( a && a->directfp ) { - fclose( a->directfp ); - m_free( a->real_fname ); - if( DBG_IOBUF ) - log_debug("iobuf_close -> %p\n", a->directfp ); - return 0; - } - - for( ; a && !rc ; a = a2 ) { - a2 = a->chain; - if( a->use == 2 && (rc=iobuf_flush(a)) ) - log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc)); - - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc ); - if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, - a->chain, NULL, &dummy_len)) ) - log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) ); - m_free(a->real_fname); - if (a->d.buf) { - memset (a->d.buf, 0, a->d.size); /* erase the buffer */ - m_free(a->d.buf); - } - m_free(a); - } - return rc; -} - -int -iobuf_cancel( IOBUF a ) -{ - const char *s; - IOBUF a2; - int rc; - #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - char *remove_name = NULL; - #endif - - if( a && a->use == 2 ) { - s = iobuf_get_real_fname(a); - if( s && *s ) { - #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - remove_name = m_strdup ( s ); - #else - remove(s); - #endif - } - } - - /* send a cancel message to all filters */ - for( a2 = a; a2 ; a2 = a2->chain ) { - size_t dummy; - if( a2->filter ) - a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, - NULL, &dummy ); - } - - rc = iobuf_close(a); - #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - if ( remove_name ) { - /* Argg, MSDOS does not allow to remove open files. So - * we have to do it here */ - remove ( remove_name ); - m_free ( remove_name ); - } - #endif - return rc; -} - - -/**************** - * create a temporary iobuf, which can be used to collect stuff - * in an iobuf and later be written by iobuf_write_temp() to another - * iobuf. - */ -IOBUF -iobuf_temp() -{ - IOBUF a; - - a = iobuf_alloc(3, 8192 ); - - return a; -} - -IOBUF -iobuf_temp_with_content( const char *buffer, size_t length ) -{ - IOBUF a; - - a = iobuf_alloc(3, length ); - memcpy( a->d.buf, buffer, length ); - a->d.len = length; - - return a; -} - -void -iobuf_enable_special_filenames ( int yes ) -{ - special_names_enabled = yes; -} - -/* - * see whether the filename has the for "-&nnnn", where n is a - * non-zero number. - * Returns this number or -1 if it is not the case. - */ -static int -check_special_filename ( const char *fname ) -{ - if ( special_names_enabled - && fname && *fname == '-' && fname[1] == '&' ) { - int i; - - fname += 2; - for (i=0; isdigit (fname[i]); i++ ) - ; - if ( !fname[i] ) - return atoi (fname); - } - return -1; -} - -/**************** - * Create a head iobuf for reading from a file - * returns: NULL if an error occures and sets errno - */ -IOBUF -iobuf_open( const char *fname ) -{ - IOBUF a; - FILEP_OR_FD fp; - file_filter_ctx_t *fcx; - size_t len; - int print_only = 0; - int fd; - - if( !fname || (*fname=='-' && !fname[1]) ) { - fp = FILEP_OR_FD_FOR_STDIN; - #ifdef USE_SETMODE - setmode ( my_fileno(fp) , O_BINARY ); - #endif - fname = "[stdin]"; - print_only = 1; - } - else if ( (fd = check_special_filename ( fname )) != -1 ) - return iobuf_fdopen ( translate_file_handle (fd,0), "rb" ); - else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP ) - return NULL; - a = iobuf_alloc(1, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - fcx->print_only_name = print_only; - strcpy(fcx->fname, fname ); - if( !print_only ) - a->real_fname = m_strdup( fname ); - a->filter = file_filter; - a->filter_ov = fcx; - file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); - file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: open `%s' fd=%d\n", - a->no, a->subno, fname, (int)my_fileno(fcx->fp) ); - - return a; -} - -/**************** - * Create a head iobuf for reading from a file - * returns: NULL if an error occures and sets errno - */ -IOBUF -iobuf_fdopen( int fd, const char *mode ) -{ - IOBUF a; - FILEP_OR_FD fp; - file_filter_ctx_t *fcx; - size_t len; - -#ifdef FILE_FILTER_USES_STDIO - if( !(fp = fdopen(fd, mode)) ) - return NULL; -#else - fp = (FILEP_OR_FD)fd; -#endif - a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 ); - fcx = m_alloc( sizeof *fcx + 20 ); - fcx->fp = fp; - fcx->print_only_name = 1; - sprintf(fcx->fname, "[fd %d]", fd ); - a->filter = file_filter; - a->filter_ov = fcx; - file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); - file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname ); - iobuf_ioctl (a,3,1,NULL); /* disable fd caching */ - return a; -} - - -IOBUF -iobuf_sockopen ( int fd, const char *mode ) -{ - IOBUF a; -#ifdef __MINGW32__ - sock_filter_ctx_t *scx; - size_t len; - - a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 ); - scx = m_alloc( sizeof *scx + 25 ); - scx->sock = fd; - scx->print_only_name = 1; - sprintf(scx->fname, "[sock %d]", fd ); - a->filter = sock_filter; - a->filter_ov = scx; - sock_filter( scx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); - sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len ); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname); - iobuf_ioctl (a,3,1,NULL); /* disable fd caching */ -#else - a = iobuf_fdopen (fd, mode); -#endif - return a; -} - -/**************** - * create an iobuf for writing to a file; the file will be created. - */ -IOBUF -iobuf_create( const char *fname ) -{ - IOBUF a; - FILEP_OR_FD fp; - file_filter_ctx_t *fcx; - size_t len; - int print_only = 0; - int fd; - - if( !fname || (*fname=='-' && !fname[1]) ) { - fp = FILEP_OR_FD_FOR_STDOUT; - #ifdef USE_SETMODE - setmode ( my_fileno(fp) , O_BINARY ); - #endif - fname = "[stdout]"; - print_only = 1; - } - else if ( (fd = check_special_filename ( fname )) != -1 ) - return iobuf_fdopen ( translate_file_handle (fd, 1), "wb" ); - else if( (fp = my_fopen(fname, "wb")) == INVALID_FP ) - return NULL; - a = iobuf_alloc(2, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - fcx->print_only_name = print_only; - strcpy(fcx->fname, fname ); - if( !print_only ) - a->real_fname = m_strdup( fname ); - a->filter = file_filter; - a->filter_ov = fcx; - file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); - file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc ); - - return a; -} - -/**************** - * append to an iobuf; if the file does not exist, create it. - * cannot be used for stdout. - * Note: This is not used. - */ -#if 0 /* not used */ -IOBUF -iobuf_append( const char *fname ) -{ - IOBUF a; - FILE *fp; - file_filter_ctx_t *fcx; - size_t len; - - if( !fname ) - return NULL; - else if( !(fp = my_fopen(fname, "ab")) ) - return NULL; - a = iobuf_alloc(2, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - strcpy(fcx->fname, fname ); - a->real_fname = m_strdup( fname ); - a->filter = file_filter; - a->filter_ov = fcx; - file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); - file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc ); - - return a; -} -#endif - -IOBUF -iobuf_openrw( const char *fname ) -{ - IOBUF a; - FILEP_OR_FD fp; - file_filter_ctx_t *fcx; - size_t len; - - if( !fname ) - return NULL; - else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP ) - return NULL; - a = iobuf_alloc(2, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - strcpy(fcx->fname, fname ); - a->real_fname = m_strdup( fname ); - a->filter = file_filter; - a->filter_ov = fcx; - file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len ); - file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len ); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc ); - - return a; -} - - -int -iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ) -{ - if ( cmd == 1 ) { /* keep system filepointer/descriptor open */ - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n", - a? a->no:-1, a?a->subno:-1, a?a->desc:"?", intval ); - for( ; a; a = a->chain ) - if( !a->chain && a->filter == file_filter ) { - file_filter_ctx_t *b = a->filter_ov; - b->keep_open = intval; - return 0; - } - #ifdef __MINGW32__ - else if( !a->chain && a->filter == sock_filter ) { - sock_filter_ctx_t *b = a->filter_ov; - b->keep_open = intval; - return 0; - } - #endif - } - else if ( cmd == 2 ) { /* invalidate cache */ - if( DBG_IOBUF ) - log_debug("iobuf-*.*: ioctl `%s' invalidate\n", - ptrval? (char*)ptrval:"?"); - if ( !a && !intval && ptrval ) { - #ifndef FILE_FILTER_USES_STDIO - fd_cache_invalidate (ptrval); - #endif - return 0; - } - } - else if ( cmd == 3 ) { /* disallow/allow caching */ - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n", - a? a->no:-1, a?a->subno:-1, a?a->desc:"?", intval ); - for( ; a; a = a->chain ) - if( !a->chain && a->filter == file_filter ) { - file_filter_ctx_t *b = a->filter_ov; - b->no_cache = intval; - return 0; - } - #ifdef __MINGW32__ - else if( !a->chain && a->filter == sock_filter ) { - sock_filter_ctx_t *b = a->filter_ov; - b->no_cache = intval; - return 0; - } - #endif - } - - return -1; -} - - -/**************** - * Register an i/o filter. - */ -int -iobuf_push_filter( IOBUF a, - int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), void *ov ) -{ - return iobuf_push_filter2( a, f, ov, 0 ); -} - -int -iobuf_push_filter2( IOBUF a, - int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), - void *ov, int rel_ov ) -{ - IOBUF b; - size_t dummy_len=0; - int rc=0; - - if( a->directfp ) - BUG(); - - if( a->use == 2 && (rc=iobuf_flush(a)) ) - return rc; - /* make a copy of the current stream, so that - * A is the new stream and B the original one. - * The contents of the buffers are transferred to the - * new stream. - */ - b = m_alloc(sizeof *b); - memcpy(b, a, sizeof *b ); - /* fixme: it is stupid to keep a copy of the name at every level - * but we need the name somewhere because the name known by file_filter - * may have been released when we need the name of the file */ - b->real_fname = a->real_fname? m_strdup(a->real_fname):NULL; - /* remove the filter stuff from the new stream */ - a->filter = NULL; - a->filter_ov = NULL; - a->filter_ov_owner = 0; - a->filter_eof = 0; - if( a->use == 3 ) - a->use = 2; /* make a write stream from a temp stream */ - - if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */ - b->d.buf = m_alloc( a->d.size ); - b->d.len = 0; - b->d.start = 0; - } - else { /* allocate a fresh buffer for the new stream */ - a->d.buf = m_alloc( a->d.size ); - a->d.len = 0; - a->d.start = 0; - } - /* disable nlimit for the new stream */ - a->ntotal = b->ntotal + b->nbytes; - a->nlimit = a->nbytes = 0; - a->nofast &= ~1; - /* make a link from the new stream to the original stream */ - a->chain = b; - a->opaque = b->opaque; - - /* setup the function on the new stream */ - a->filter = f; - a->filter_ov = ov; - a->filter_ov_owner = rel_ov; - - a->subno = b->subno + 1; - f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len ); - - if( DBG_IOBUF ) { - log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc ); - print_chain( a ); - } - - /* now we can initialize the new function if we have one */ - if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain, - NULL, &dummy_len)) ) - log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) ); - return rc; -} - -/**************** - * Remove an i/o filter. - */ -int -pop_filter( IOBUF a, int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), void *ov ) -{ - IOBUF b; - size_t dummy_len=0; - int rc=0; - - if( a->directfp ) - BUG(); - - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc ); - if( !a->filter ) { /* this is simple */ - b = a->chain; - assert(b); - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a,b, sizeof *a); - m_free(b); - return 0; - } - for(b=a ; b; b = b->chain ) - if( b->filter == f && (!ov || b->filter_ov == ov) ) - break; - if( !b ) - log_bug("pop_filter(): filter function not found\n"); - - /* flush this stream if it is an output stream */ - if( a->use == 2 && (rc=iobuf_flush(b)) ) { - log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc)); - return rc; - } - /* and tell the filter to free it self */ - if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain, - NULL, &dummy_len)) ) { - log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) ); - return rc; - } - if( b->filter_ov && b->filter_ov_owner ) { - m_free( b->filter_ov ); - b->filter_ov = NULL; - } - - - /* and see how to remove it */ - if( a == b && !b->chain ) - log_bug("can't remove the last filter from the chain\n"); - else if( a == b ) { /* remove the first iobuf from the chain */ - /* everything from b is copied to a. This is save because - * a flush has been done on the to be removed entry - */ - b = a->chain; - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a,b, sizeof *a); - m_free(b); - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno ); - } - else if( !b->chain ) { /* remove the last iobuf from the chain */ - log_bug("Ohh jeee, trying to remove a head filter\n"); - } - else { /* remove an intermediate iobuf from the chain */ - log_bug("Ohh jeee, trying to remove an intermediate filter\n"); - } - - return rc; -} - - -/**************** - * read underflow: read more bytes into the buffer and return - * the first byte or -1 on EOF. - */ -static int -underflow(IOBUF a) -{ - size_t len; - int rc; - - assert( a->d.start == a->d.len ); - if( a->use == 3 ) - return -1; /* EOF because a temp buffer can't do an underflow */ - - if( a->filter_eof ) { - if( a->chain ) { - IOBUF b = a->chain; - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: pop `%s' in underflow\n", - a->no, a->subno, a->desc ); - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a, b, sizeof *a); - m_free(b); - print_chain(a); - } - else - a->filter_eof = 0; /* for the top level filter */ - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n", - a->no, a->subno ); - return -1; /* return one(!) EOF */ - } - if( a->error ) { - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: error\n", a->no, a->subno ); - return -1; - } - - if( a->directfp ) { - FILE *fp = a->directfp; - - len = fread( a->d.buf, 1, a->d.size, fp); - if( len < a->d.size ) { - if( ferror(fp) ) - a->error = 1; - } - a->d.len = len; - a->d.start = 0; - return len? a->d.buf[a->d.start++] : -1; - } - - - if( a->filter ) { - len = a->d.size; - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: underflow: req=%lu\n", - a->no, a->subno, (ulong)len ); - rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, - a->d.buf, &len ); - if( DBG_IOBUF ) { - log_debug("iobuf-%d.%d: underflow: got=%lu rc=%d\n", - a->no, a->subno, (ulong)len, rc ); -/* if( a->no == 1 ) */ -/* log_hexdump (" data:", a->d.buf, len); */ - } - if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */ - size_t dummy_len=0; - - /* and tell the filter to free itself */ - if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain, - NULL, &dummy_len)) ) - log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) ); - if( a->filter_ov && a->filter_ov_owner ) { - m_free( a->filter_ov ); - a->filter_ov = NULL; - } - a->filter = NULL; - a->desc = NULL; - a->filter_ov = NULL; - a->filter_eof = 1; - if( !len && a->chain ) { - IOBUF b = a->chain; - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: pop `%s' in underflow (!len)\n", - a->no, a->subno, a->desc ); - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a,b, sizeof *a); - m_free(b); - print_chain(a); - } - } - else if( rc ) - a->error = 1; - - if( !len ) { - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno ); - return -1; - } - a->d.len = len; - a->d.start = 0; - return a->d.buf[a->d.start++]; - } - else { - if( DBG_IOBUF ) - log_debug("iobuf-%d.%d: underflow: eof (no filter)\n", - a->no, a->subno ); - return -1; /* no filter; return EOF */ - } -} - - -int -iobuf_flush(IOBUF a) -{ - size_t len; - int rc; - - if( a->directfp ) - return 0; - - if( a->use == 3 ) { /* increase the temp buffer */ - char *newbuf; - size_t newsize = a->d.size + 8192; - - log_debug("increasing temp iobuf from %lu to %lu\n", - (ulong)a->d.size, (ulong)newsize ); - newbuf = m_alloc( newsize ); - memcpy( newbuf, a->d.buf, a->d.len ); - m_free(a->d.buf); - a->d.buf = newbuf; - a->d.size = newsize; - return 0; - } - else if( a->use != 2 ) - log_bug("flush on non-output iobuf\n"); - else if( !a->filter ) - log_bug("iobuf_flush: no filter\n"); - len = a->d.len; - rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len ); - if( !rc && len != a->d.len ) { - log_info("iobuf_flush did not write all!\n"); - rc = G10ERR_WRITE_FILE; - } - else if( rc ) - a->error = 1; - a->d.len = 0; - - return rc; -} - - -/**************** - * Read a byte from the iobuf; returns -1 on EOF - */ -int -iobuf_readbyte(IOBUF a) -{ - int c; - - /* nlimit does not work together with unget */ - /* nbytes is also not valid! */ - if( a->unget.buf ) { - if( a->unget.start < a->unget.len ) - return a->unget.buf[a->unget.start++]; - m_free(a->unget.buf); - a->unget.buf = NULL; - a->nofast &= ~2; - } - - if( a->nlimit && a->nbytes >= a->nlimit ) - return -1; /* forced EOF */ - - if( a->d.start < a->d.len ) { - c = a->d.buf[a->d.start++]; - } - else if( (c=underflow(a)) == -1 ) - return -1; /* EOF */ - - a->nbytes++; - return c; -} - - -int -iobuf_read(IOBUF a, byte *buf, unsigned buflen ) -{ - int c, n; - - if( a->unget.buf || a->nlimit ) { - /* handle special cases */ - for(n=0 ; n < buflen; n++ ) { - if( (c = iobuf_readbyte(a)) == -1 ) { - if( !n ) - return -1; /* eof */ - break; - } - else - if( buf ) *buf = c; - if( buf ) buf++; - } - return n; - } - - n = 0; - do { - if( n < buflen && a->d.start < a->d.len ) { - unsigned size = a->d.len - a->d.start; - if( size > buflen - n ) - size = buflen - n; - if( buf ) - memcpy( buf, a->d.buf + a->d.start, size ); - n += size; - a->d.start += size; - if( buf ) - buf += size; - } - if( n < buflen ) { - if( (c=underflow(a)) == -1 ) { - a->nbytes += n; - return n? n : -1/*EOF*/; - } - if( buf ) - *buf++ = c; - n++; - } - } while( n < buflen ); - a->nbytes += n; - return n; -} - - -/**************** - * Have a look at the iobuf. - * NOTE: This only works in special cases. - */ -int -iobuf_peek(IOBUF a, byte *buf, unsigned buflen ) -{ - int n=0; - - if( a->filter_eof ) - return -1; - - if( !(a->d.start < a->d.len) ) { - if( underflow(a) == -1 ) - return -1; - /* and unget this character */ - assert(a->d.start == 1); - a->d.start = 0; - } - - for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ ) - *buf = a->d.buf[n]; - return n; -} - - - - -int -iobuf_writebyte(IOBUF a, unsigned c) -{ - - if( a->directfp ) - BUG(); - - if( a->d.len == a->d.size ) - if( iobuf_flush(a) ) - return -1; - - assert( a->d.len < a->d.size ); - a->d.buf[a->d.len++] = c; - return 0; -} - - -int -iobuf_write(IOBUF a, byte *buf, unsigned buflen ) -{ - - if( a->directfp ) - BUG(); - - do { - if( buflen && a->d.len < a->d.size ) { - unsigned size = a->d.size - a->d.len; - if( size > buflen ) size = buflen; - memcpy( a->d.buf + a->d.len, buf, size ); - buflen -= size; - buf += size; - a->d.len += size; - } - if( buflen ) { - if( iobuf_flush(a) ) - return -1; - } - } while( buflen ); - return 0; -} - - -int -iobuf_writestr(IOBUF a, const char *buf ) -{ - for( ; *buf; buf++ ) - if( iobuf_writebyte(a, *buf) ) - return -1; - return 0; -} - - - -/**************** - * copy the contents of TEMP to A. - */ -int -iobuf_write_temp( IOBUF a, IOBUF temp ) -{ - while( temp->chain ) - pop_filter( temp, temp->filter, NULL ); - return iobuf_write(a, temp->d.buf, temp->d.len ); -} - -/**************** - * copy the contents of the temp io stream to BUFFER. - */ -size_t -iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ) -{ - size_t n = a->d.len; - - if( n > buflen ) - n = buflen; - memcpy( buffer, a->d.buf, n ); - return n; -} - - -/**************** - * Call this function to terminate processing of the temp stream - * without closing it. This removes all filters from the stream - * makes sure that iobuf_get_temp_{buffer,length}() returns correct - * values. - */ -void -iobuf_flush_temp( IOBUF temp ) -{ - while( temp->chain ) - pop_filter( temp, temp->filter, NULL ); -} - - -/**************** - * Set a limit on how many bytes may be read from the input stream A. - * Setting the limit to 0 disables this feature. - */ -void -iobuf_set_limit( IOBUF a, off_t nlimit ) -{ - if( nlimit ) - a->nofast |= 1; - else - a->nofast &= ~1; - a->nlimit = nlimit; - a->ntotal += a->nbytes; - a->nbytes = 0; -} - - - -/**************** - * Return the length of an open file - */ -off_t -iobuf_get_filelength( IOBUF a ) -{ - struct stat st; - - if( a->directfp ) { - FILE *fp = a->directfp; - - if( !fstat(fileno(fp), &st) ) - return st.st_size; - log_error("fstat() failed: %s\n", strerror(errno) ); - return 0; - } - - /* Hmmm: file_filter may have already been removed */ - for( ; a; a = a->chain ) - if( !a->chain && a->filter == file_filter ) { - file_filter_ctx_t *b = a->filter_ov; - FILEP_OR_FD fp = b->fp; - - #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO) - ulong size; - - if ( (size=GetFileSize (fp, NULL)) != 0xffffffff ) - return size; - log_error ("GetFileSize for handle %p failed: ec=%d\n", - fp, (int)GetLastError () ); - #else - if( !fstat(my_fileno(fp), &st) ) - return st.st_size; - log_error("fstat() failed: %s\n", strerror(errno) ); - #endif - break; - } - - return 0; -} - -/**************** - * Tell the file position, where the next read will take place - */ -off_t -iobuf_tell( IOBUF a ) -{ - return a->ntotal + a->nbytes; -} - - -#if !defined(HAVE_FSEEKO) && !defined(fseeko) - -#ifdef HAVE_LIMITS_H -# include -#endif -#ifndef LONG_MAX -# define LONG_MAX ((long) ((unsigned long) -1 >> 1)) -#endif -#ifndef LONG_MIN -# define LONG_MIN (-1 - LONG_MAX) -#endif - -/**************** - * A substitute for fseeko, for hosts that don't have it. - */ -static int -fseeko( FILE *stream, off_t newpos, int whence ) -{ - while( newpos != (long) newpos ) { - long pos = newpos < 0 ? LONG_MIN : LONG_MAX; - if( fseek( stream, pos, whence ) != 0 ) - return -1; - newpos -= pos; - whence = SEEK_CUR; - } - return fseek( stream, (long)newpos, whence ); -} -#endif - -/**************** - * This is a very limited implementation. It simply discards all internal - * buffering and removes all filters but the first one. - */ -int -iobuf_seek( IOBUF a, off_t newpos ) -{ - file_filter_ctx_t *b = NULL; - - if( a->directfp ) { - FILE *fp = a->directfp; - if( fseeko( fp, newpos, SEEK_SET ) ) { - log_error("can't seek: %s\n", strerror(errno) ); - return -1; - } - clearerr(fp); - } - else { - for( ; a; a = a->chain ) { - if( !a->chain && a->filter == file_filter ) { - b = a->filter_ov; - break; - } - } - if( !a ) - return -1; -#ifdef FILE_FILTER_USES_STDIO - if( fseeko( b->fp, newpos, SEEK_SET ) ) { - log_error("can't fseek: %s\n", strerror(errno) ); - return -1; - } -#else - #ifdef HAVE_DOSISH_SYSTEM - if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) { - log_error ("SetFilePointer failed on handle %p: ec=%d\n", - b->fp, (int)GetLastError () ); - return -1; - } - #else - if ( lseek (b->fp, newpos, SEEK_SET) == (off_t)-1 ) { - log_error("can't lseek: %s\n", strerror(errno) ); - return -1; - } - #endif -#endif - } - a->d.len = 0; /* discard buffer */ - a->d.start = 0; - a->nbytes = 0; - a->nlimit = 0; - a->nofast &= ~1; - a->ntotal = newpos; - a->error = 0; - /* remove filters, but the last */ - if( a->chain ) - log_debug("pop_filter called in iobuf_seek - please report\n"); - while( a->chain ) - pop_filter( a, a->filter, NULL ); - - return 0; -} - - - - - - -/**************** - * Retrieve the real filename - */ -const char * -iobuf_get_real_fname( IOBUF a ) -{ - if( a->real_fname ) - return a->real_fname; - - /* the old solution */ - for( ; a; a = a->chain ) - if( !a->chain && a->filter == file_filter ) { - file_filter_ctx_t *b = a->filter_ov; - return b->print_only_name? NULL : b->fname; - } - - return NULL; -} - - -/**************** - * Retrieve the filename - */ -const char * -iobuf_get_fname( IOBUF a ) -{ - for( ; a; a = a->chain ) - if( !a->chain && a->filter == file_filter ) { - file_filter_ctx_t *b = a->filter_ov; - return b->fname; - } - - return NULL; -} - -/**************** - * Start the block write mode, see rfc1991.new for details. - * A value of 0 for N stops this mode (flushes and writes - * the end marker) - */ -void -iobuf_set_block_mode( IOBUF a, size_t n ) -{ - block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx ); - - assert( a->use == 1 || a->use == 2 ); - ctx->use = a->use; - if( !n ) { - if( a->use == 1 ) - log_debug("pop_filter called in set_block_mode - please report\n"); - pop_filter(a, block_filter, NULL ); - } - else { - ctx->size = n; /* only needed for use 2 */ - iobuf_push_filter(a, block_filter, ctx ); - } -} - -/**************** - * enable partial block mode as described in the OpenPGP draft. - * LEN is the first length byte on read, but ignored on writes. - */ -void -iobuf_set_partial_block_mode( IOBUF a, size_t len ) -{ - block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx ); - - assert( a->use == 1 || a->use == 2 ); - ctx->use = a->use; - if( !len ) { - if( a->use == 1 ) - log_debug("pop_filter called in set_partial_block_mode" - " - please report\n"); - pop_filter(a, block_filter, NULL ); - } - else { - ctx->partial = 1; - ctx->size = 0; - ctx->first_c = len; - iobuf_push_filter(a, block_filter, ctx ); - } -} - - -/**************** - * Checks whether the stream is in block mode - * Note: This does not work if other filters are pushed on the stream. - */ -int -iobuf_in_block_mode( IOBUF a ) -{ - if( a && a->filter == block_filter ) - return 1; /* yes */ - return 0; /* no */ -} - - -/**************** - * Same as fgets() but if the buffer is too short a larger one will - * be allocated up to some limit *max_length. - * A line is considered a byte stream ending in a LF. - * Returns the length of the line. EOF is indicated by a line of - * length zero. The last LF may be missing due to an EOF. - * is max_length is zero on return, the line has been truncated. - * - * Note: The buffer is allocated with enough space to append a CR,LF,EOL - */ -unsigned -iobuf_read_line( IOBUF a, byte **addr_of_buffer, - unsigned *length_of_buffer, unsigned *max_length ) -{ - int c; - char *buffer = *addr_of_buffer; - unsigned length = *length_of_buffer; - unsigned nbytes = 0; - unsigned maxlen = *max_length; - char *p; - - if( !buffer ) { /* must allocate a new buffer */ - length = 256; - buffer = m_alloc( length ); - *addr_of_buffer = buffer; - *length_of_buffer = length; - } - - length -= 3; /* reserve 3 bytes (cr,lf,eol) */ - p = buffer; - while( (c=iobuf_get(a)) != -1 ) { - if( nbytes == length ) { /* increase the buffer */ - if( length > maxlen ) { /* this is out limit */ - /* skip the rest of the line */ - while( c != '\n' && (c=iobuf_get(a)) != -1 ) - ; - *p++ = '\n'; /* always append a LF (we have reserved space) */ - nbytes++; - *max_length = 0; /* indicate truncation */ - break; - } - length += 3; /* correct for the reserved byte */ - length += length < 1024? 256 : 1024; - buffer = m_realloc( buffer, length ); - *addr_of_buffer = buffer; - *length_of_buffer = length; - length -= 3; /* and reserve again */ - p = buffer + nbytes; - } - *p++ = c; - nbytes++; - if( c == '\n' ) - break; - } - *p = 0; /* make sure the line is a string */ - - return nbytes; -} - -/* This is the non iobuf specific function */ -int -iobuf_translate_file_handle ( int fd, int for_write ) -{ - #ifdef __MINGW32__ - { - int x; - - if ( fd <= 2 ) - return fd; /* do not do this for error, stdin, stdout, stderr */ - - x = _open_osfhandle ( fd, for_write? 1:0 ); - if (x==-1 ) - log_error ("failed to translate osfhandle %p\n", (void*)fd ); - else { - /*log_info ("_open_osfhandle %p yields %d%s\n", - (void*)fd, x, for_write? " for writing":"" );*/ - fd = x; - } - } - #endif - return fd; -} - -static int -translate_file_handle ( int fd, int for_write ) -{ - #ifdef __MINGW32__ - #ifdef FILE_FILTER_USES_STDIO - fd = iobuf_translate_file_handle (fd, for_write); - #else - { - int x; - - if ( fd == 0 ) - x = (int)GetStdHandle (STD_INPUT_HANDLE); - else if (fd == 1) - x = (int)GetStdHandle (STD_OUTPUT_HANDLE); - else if (fd == 2) - x = (int)GetStdHandle (STD_ERROR_HANDLE); - else - x = fd; - - if (x == -1) - log_debug ("GetStdHandle(%d) failed: ec=%d\n", - fd, (int)GetLastError () ); - - fd = x; - } - #endif - #endif - return fd; -} - - diff --git a/util/logger.c b/util/logger.c deleted file mode 100644 index 6990473b2..000000000 --- a/util/logger.c +++ /dev/null @@ -1,334 +0,0 @@ -/* logger.c - log functions - * Copyright (C) 1998, 1999 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 -#include -#include -#include -#include -#include - -#include "util.h" -#include "i18n.h" - -static char pidstring[15]; -static char *pgm_name; -static int errorcount; -static int strict; -static FILE *logfp; - -/**************** - * Set the logfile to use (not yet implemneted) or, if logfile is NULL, - * the Fd where logoutputs should go. - */ -void -log_set_logfile( const char *name, int fd ) -{ - if( name ) - BUG(); - - if( logfp && logfp != stderr && logfp != stdout ) - fclose( logfp ); - if( fd == 1 ) - logfp = stdout; - else if( fd == 2 ) - logfp = stderr; - else - logfp = fdopen( fd, "a" ); - if( !logfp ) { - logfp = stderr; - log_fatal("can't open fd %d for logging: %s\n", fd, strerror(errno)); - } -} - -FILE * -log_stream() -{ - if( !logfp ) - logfp = stderr; - return logfp; -} - - -void -log_set_name( const char *name ) -{ - m_free(pgm_name); - if( name ) - pgm_name = m_strdup(name); - else - pgm_name = NULL; -} - -const char * -log_get_name(void) -{ - return pgm_name? pgm_name : ""; -} - - -void -log_set_pid( int pid ) -{ - if( pid ) - sprintf(pidstring,"[%u]", (unsigned)pid ); - else - *pidstring = 0; -} - -int -log_get_errorcount( int clear) -{ - int n = errorcount; - if( clear ) - errorcount = 0; - return n; -} - -void -log_inc_errorcount() -{ - errorcount++; -} - -int -log_set_strict(int val) -{ - int old=strict; - strict=val; - return old; -} - -void -g10_log_print_prefix(const char *text) -{ - if( !logfp ) - logfp = stderr; - if( pgm_name ) - fprintf(logfp, "%s%s: %s", pgm_name, pidstring, text ); - else - fprintf(logfp, "?%s: %s", pidstring, text ); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -static void -print_prefix_f(const char *text, const char *fname) -{ - if( !logfp ) - logfp = stderr; - if( pgm_name ) - fprintf(logfp, "%s%s:%s: %s", pgm_name, pidstring, fname, text ); - else - fprintf(logfp, "?%s:%s: %s", pidstring, fname, text ); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -void -g10_log_info( const char *fmt, ... ) -{ - va_list arg_ptr ; - - g10_log_print_prefix(""); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -void -g10_log_info_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("", fname); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -void -g10_log_warning( const char *fmt, ... ) -{ - va_list arg_ptr ; - - if(strict) - { - errorcount++; - g10_log_print_prefix(_("ERROR: ")); - } - else - g10_log_print_prefix(_("WARNING: ")); - - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - - -void -g10_log_error( const char *fmt, ... ) -{ - va_list arg_ptr ; - - g10_log_print_prefix(""); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); - errorcount++; -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -void -g10_log_error_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("", fname); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); - errorcount++; -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -void -g10_log_fatal( const char *fmt, ... ) -{ - va_list arg_ptr ; - - g10_log_print_prefix("fatal: "); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); - secmem_dump_stats(); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ - exit(2); -} - -void -g10_log_fatal_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("fatal: ", fname); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); - secmem_dump_stats(); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ - exit(2); -} - -void -g10_log_bug( const char *fmt, ... ) -{ - va_list arg_ptr ; - - putc('\n', stderr ); - g10_log_print_prefix("Ohhhh jeeee: "); - va_start( arg_ptr, fmt ) ; - vfprintf(stderr,fmt,arg_ptr) ; - va_end(arg_ptr); - fflush(stderr); - secmem_dump_stats(); - abort(); -} - -#if defined (__riscos__) \ - || ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) -void -g10_log_bug0( const char *file, int line, const char *func ) -{ - log_bug(_("... this is a bug (%s:%d:%s)\n"), file, line, func ); -} -#else -void -g10_log_bug0( const char *file, int line ) -{ - log_bug(_("you found a bug ... (%s:%d)\n"), file, line); -} -#endif - -void -g10_log_debug( const char *fmt, ... ) -{ - va_list arg_ptr ; - - g10_log_print_prefix("DBG: "); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - -void -g10_log_debug_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("DBG: ", fname); - va_start( arg_ptr, fmt ) ; - vfprintf(logfp,fmt,arg_ptr) ; - va_end(arg_ptr); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - - - -void -g10_log_hexdump( const char *text, const char *buf, size_t len ) -{ - int i; - - g10_log_print_prefix(text); - for(i=0; i < len; i++ ) - fprintf(logfp, " %02X", ((const byte*)buf)[i] ); - fputc('\n', logfp); -#ifdef __riscos__ - fflush( logfp ); -#endif /* __riscos__ */ -} - - - diff --git a/util/memory.c b/util/memory.c deleted file mode 100644 index 9fab9ea3b..000000000 --- a/util/memory.c +++ /dev/null @@ -1,634 +0,0 @@ -/* memory.c - memory allocation - * Copyright (C) 1998, 1999, 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 - * - * - * We use our own memory allocation functions instead of plain malloc(), - * so that we can provide some special enhancements: - * a) functions to provide memory from a secure memory. - * b) by looking at the requested allocation size we - * can reuse memory very quickly (e.g. MPI storage) - * (really needed?) - * c) memory usage reporting if compiled with M_DEBUG - * d) memory checking if compiled with M_GUARD - */ - -#include -#include -#include -#include -#include - -#include "types.h" -#include "memory.h" -#include "util.h" - - -#define MAGIC_NOR_BYTE 0x55 -#define MAGIC_SEC_BYTE 0xcc -#define MAGIC_END_BYTE 0xaa - -/* This is a very crude alignment check which does not work on all CPUs - * IIRC, I once introduced it for testing on an Alpha. We should better - * replace this guard stuff with one provided by a modern malloc library - */ -#if SIZEOF_UNSIGNED_LONG == 8 - #define EXTRA_ALIGN 4 -#else - #define EXTRA_ALIGN 0 -#endif - -#if defined(M_DEBUG) || defined(M_GUARD) - static void membug( const char *fmt, ... ); -#endif - -#ifdef M_DEBUG - - #ifndef M_GUARD - #define M_GUARD 1 - #endif - #undef m_alloc - #undef m_alloc_clear - #undef m_alloc_secure - #undef m_alloc_secure_clear - #undef m_realloc - #undef m_free - #undef m_check - #undef m_strdup - #define FNAME(a) m_debug_ ##a - #define FNAMEPRT , const char *info - #define FNAMEARG , info - #ifndef __riscos__ - #define store_len(p,n,m) do { add_entry(p,n,m, \ - info, __FUNCTION__); } while(0) - #else - #define store_len(p,n,m) do { add_entry(p,n,m, \ - info, __func__ ); } while(0) - #endif -#else - #define FNAME(a) m_ ##a - #define FNAMEPRT - #define FNAMEARG - #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \ - ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \ - ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \ - ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \ - : MAGIC_NOR_BYTE; \ - } while(0) -#endif - - -#ifdef M_GUARD -static long used_memory; -#endif - -#ifdef M_DEBUG /* stuff used for memory debuging */ - -struct info_entry { - struct info_entry *next; - unsigned count; /* call count */ - const char *info; /* the reference to the info string */ -}; - -struct memtbl_entry { - const void *user_p; /* for reference: the pointer given to the user */ - size_t user_n; /* length requested by the user */ - struct memtbl_entry *next; /* to build a list of unused entries */ - const struct info_entry *info; /* points into the table with */ - /* the info strings */ - unsigned inuse:1; /* this entry is in use */ - unsigned count:31; -}; - - -#define INFO_BUCKETS 53 -#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS ) -static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */ - -static struct memtbl_entry *memtbl; /* the table with the memory info */ -static unsigned memtbl_size; /* number of allocated entries */ -static unsigned memtbl_len; /* number of used entries */ -static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */ - -static void dump_table_at_exit(void); -static void dump_table(void); -static void check_allmem( const char *info ); - -/**************** - * Put the new P into the debug table and return a pointer to the table entry. - * mode is true for security. BY is the name of the function which called us. - */ -static void -add_entry( byte *p, unsigned n, int mode, const char *info, const char *by ) -{ - unsigned index; - struct memtbl_entry *e; - struct info_entry *ie; - - if( memtbl_len < memtbl_size ) - index = memtbl_len++; - else { - struct memtbl_entry *e; - /* look for a used entry in the table. We take the first one, - * so that freed entries remain as long as possible in the table - * (free appends a new one) - */ - if( (e = memtbl_unused) ) { - index = e - memtbl; - memtbl_unused = e->next; - e->next = NULL; - } - else { /* no free entries in the table: extend the table */ - if( !memtbl_size ) { /* first time */ - memtbl_size = 100; - if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) ) - membug("memory debug table malloc failed\n"); - index = 0; - memtbl_len = 1; - atexit( dump_table_at_exit ); - } - else { /* realloc */ - unsigned n = memtbl_size / 4; /* enlarge by 25% */ - if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl))) - membug("memory debug table realloc failed\n"); - memset(memtbl+memtbl_size, 0, n*sizeof *memtbl ); - memtbl_size += n; - index = memtbl_len++; - } - } - } - e = memtbl+index; - if( e->inuse ) - membug("Ooops: entry %u is flagged as in use\n", index); - e->user_p = p + EXTRA_ALIGN + 4; - e->user_n = n; - e->count++; - if( e->next ) - membug("Ooops: entry is in free entry list\n"); - /* do we already have this info string */ - for( ie = info_strings[info_hash(info)]; ie; ie = ie->next ) - if( ie->info == info ) - break; - if( !ie ) { /* no: make a new entry */ - if( !(ie = malloc( sizeof *ie )) ) - membug("can't allocate info entry\n"); - ie->next = info_strings[info_hash(info)]; - info_strings[info_hash(info)] = ie; - ie->info = info; - ie->count = 0; - } - ie->count++; - e->info = ie; - e->inuse = 1; - - /* put the index at the start of the memory */ - p[EXTRA_ALIGN+0] = index; - p[EXTRA_ALIGN+1] = index >> 8 ; - p[EXTRA_ALIGN+2] = index >> 16 ; - p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ; - if( DBG_MEMORY ) - log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by ); -} - - - -/**************** - * Check that the memory block is correct. The magic byte has already been - * checked. Checks which are done here: - * - see whether the index points into our memory table - * - see whether P is the same as the one stored in the table - * - see whether we have already freed this block. - */ -struct memtbl_entry * -check_mem( const byte *p, const char *info ) -{ - unsigned n; - struct memtbl_entry *e; - - n = p[EXTRA_ALIGN+0]; - n |= p[EXTRA_ALIGN+1] << 8; - n |= p[EXTRA_ALIGN+2] << 16; - - if( n >= memtbl_len ) - membug("memory at %p corrupted: index=%u table_len=%u (%s)\n", - p+EXTRA_ALIGN+4, n, memtbl_len, info ); - e = memtbl+n; - - if( e->user_p != p+EXTRA_ALIGN+4 ) - membug("memory at %p corrupted: reference mismatch (%s)\n", - p+EXTRA_ALIGN+4, info ); - if( !e->inuse ) - membug("memory at %p corrupted: marked as free (%s)\n", - p+EXTRA_ALIGN+4, info ); - - if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE - || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) ) - membug("memory at %p corrupted: underflow=%02x (%s)\n", - p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info ); - if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE ) - membug("memory at %p corrupted: overflow=%02x (%s)\n", - p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info ); - return e; -} - - -/**************** - * free the entry and the memory (replaces free) - */ -static void -free_entry( byte *p, const char *info ) -{ - struct memtbl_entry *e, *e2; - - check_allmem("add_entry"); - - e = check_mem(p, info); - if( DBG_MEMORY ) - log_debug( "%s frees %u bytes alloced by %s\n", - info, e->user_n, e->info->info ); - if( !e->inuse ) { - if( e->user_p == p + EXTRA_ALIGN+ 4 ) - membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 ); - else - membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 ); - } - - e->inuse = 0; - e->next = NULL; - if( !memtbl_unused ) - memtbl_unused = e; - else { - for(e2=memtbl_unused; e2->next; e2 = e2->next ) - ; - e2->next = e; - } - if( m_is_secure(p+EXTRA_ALIGN+4) ) - secmem_free(p); - else { - memset(p,'f', e->user_n+5); - free(p); - } -} - -static void -dump_entry(struct memtbl_entry *e ) -{ - unsigned n = e - memtbl; - - fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n", - n, e->inuse?'a':'u', e->count, e->user_p, e->user_n, - e->info->info, e->info->count ); - - -} - - -static void -dump_table_at_exit( void) -{ - if( DBG_MEMSTAT ) - dump_table(); -} - -static void -dump_table( void) -{ - unsigned n; - struct memtbl_entry *e; - ulong sum = 0, chunks =0; - - for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { - if(e->inuse) { - dump_entry(e); - sum += e->user_n; - chunks++; - } - } - fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n", - sum, chunks ); -} - - -static void -check_allmem( const char *info ) -{ - unsigned n; - struct memtbl_entry *e; - - for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { - if( e->inuse ) { - #ifndef __riscos__ - check_mem(e->user_p-4-EXTRA_ALIGN, info); - #else - check_mem((const byte *) e->user_p-4-EXTRA_ALIGN, info); - #endif - } - } -} - -#endif /* M_DEBUG */ - -#if defined(M_DEBUG) || defined(M_GUARD) -static void -membug( const char *fmt, ... ) -{ - va_list arg_ptr ; - - fprintf(stderr, "\nMemory Error: " ) ; - va_start( arg_ptr, fmt ) ; - vfprintf(stderr,fmt,arg_ptr) ; - va_end(arg_ptr); - fflush(stderr); - #ifdef M_DEBUG - if( DBG_MEMSTAT ) - dump_table(); - #endif - abort(); -} -#endif - -void -m_print_stats( const char *prefix ) -{ - #ifdef M_DEBUG - unsigned n; - struct memtbl_entry *e; - ulong sum = 0, chunks =0; - - for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) { - if(e->inuse) { - sum += e->user_n; - chunks++; - } - } - - log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n", - prefix? prefix:"", prefix? ": ":"", sum, chunks ); - #elif defined(M_GUARD) - log_debug( "%s%smemstat: %8ld bytes\n", - prefix? prefix:"", prefix? ": ":"", used_memory ); - #endif -} - -void -m_dump_table( const char *prefix ) -{ - #ifdef M_DEBUG - fprintf(stderr,"Memory-Table-Dump: %s\n", prefix); - dump_table(); - #endif - m_print_stats( prefix ); -} - - -static void -out_of_core(size_t n, int secure) -{ - log_error ("out of %s memory while allocating %u bytes\n", - secure? "secure":"" ,(unsigned)n ); - if (secure) { - /*secmem_dump_stats ();*/ - log_info ("(this may be caused by too many secret keys used " - "simultaneously or due to excessive large key sizes)\n"); - } - exit (2); -} - -/**************** - * Allocate memory of size n. - * This function gives up if we do not have enough memory - */ -void * -FNAME(alloc)( size_t n FNAMEPRT ) -{ - char *p; - - #ifdef M_GUARD - if(!n) - out_of_core(n,0); /* should never happen */ - if( !(p = malloc( n + EXTRA_ALIGN+5 )) ) - out_of_core(n,0); - store_len(p,n,0); - used_memory += n; - p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; - return p+EXTRA_ALIGN+4; - #else - /* mallocing zero bytes is undefined by ISO-C, so we better make - sure that it won't happen */ - if (!n) - n = 1; - if( !(p = malloc( n )) ) - out_of_core(n,0); - return p; - #endif -} - -/**************** - * Allocate memory of size n from the secure memory pool. - * This function gives up if we do not have enough memory - */ -void * -FNAME(alloc_secure)( size_t n FNAMEPRT ) -{ - char *p; - - #ifdef M_GUARD - if(!n) - out_of_core(n,1); /* should never happen */ - if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) ) - out_of_core(n,1); - store_len(p,n,1); - p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE; - return p+EXTRA_ALIGN+4; - #else - /* mallocing zero bytes is undefined by ISO-C, so we better make - sure that it won't happen */ - if (!n) - n = 1; - if( !(p = secmem_malloc( n )) ) - out_of_core(n,1); - return p; - #endif -} - -void * -FNAME(alloc_clear)( size_t n FNAMEPRT ) -{ - void *p; - p = FNAME(alloc)( n FNAMEARG ); - memset(p, 0, n ); - return p; -} - -void * -FNAME(alloc_secure_clear)( size_t n FNAMEPRT) -{ - void *p; - p = FNAME(alloc_secure)( n FNAMEARG ); - memset(p, 0, n ); - return p; -} - - -/**************** - * realloc and clear the old space - */ -void * -FNAME(realloc)( void *a, size_t n FNAMEPRT ) -{ - void *b; - - #ifdef M_GUARD - if( a ) { - unsigned char *p = a; - size_t len = m_size(a); - - if( len >= n ) /* we don't shrink for now */ - return a; - if( p[-1] == MAGIC_SEC_BYTE ) - b = FNAME(alloc_secure_clear)(n FNAMEARG); - else - b = FNAME(alloc_clear)(n FNAMEARG); - FNAME(check)(NULL FNAMEARG); - memcpy(b, a, len ); - FNAME(free)(p FNAMEARG); - } - else - b = FNAME(alloc)(n FNAMEARG); - #else - if( m_is_secure(a) ) { - if( !(b = secmem_realloc( a, n )) ) - out_of_core(n,1); - } - else { - if( !(b = realloc( a, n )) ) - out_of_core(n,0); - } - #endif - - return b; -} - - - -/**************** - * Free a pointer - */ -void -FNAME(free)( void *a FNAMEPRT ) -{ - byte *p = a; - - if( !p ) - return; - #ifdef M_DEBUG - free_entry(p-EXTRA_ALIGN-4, info); - #elif defined M_GUARD - m_check(p); - if( m_is_secure(a) ) - secmem_free(p-EXTRA_ALIGN-4); - else { - used_memory -= m_size(a); - free(p-EXTRA_ALIGN-4); - } - #else - if( m_is_secure(a) ) - secmem_free(p); - else - free(p); - #endif -} - - -void -FNAME(check)( const void *a FNAMEPRT ) -{ - #ifdef M_GUARD - const byte *p = a; - - #ifdef M_DEBUG - if( p ) - check_mem(p-EXTRA_ALIGN-4, info); - else - check_allmem(info); - #else - if( !p ) - return; - if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) ) - membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] ); - else if( p[m_size(p)] != MAGIC_END_BYTE ) - membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] ); - #endif - #endif -} - - -size_t -m_size( const void *a ) -{ - #ifndef M_GUARD - log_debug("dummy m_size called\n"); - return 0; - #else - const byte *p = a; - size_t n; - - #ifdef M_DEBUG - n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n; - #else - n = ((byte*)p)[-4]; - n |= ((byte*)p)[-3] << 8; - n |= ((byte*)p)[-2] << 16; - #endif - return n; - #endif -} - - -#if 0 /* not used */ -/**************** - * Make a copy of the memory block at a - */ -void * -FNAME(copy)( const void *a FNAMEPRT ) -{ - void *b; - size_t n; - - if( !a ) - return NULL; - - n = m_size(a); Aiiiih woher nehmen - if( m_is_secure(a) ) - b = FNAME(alloc_secure)(n FNAMEARG); - else - b = FNAME(alloc)(n FNAMEARG); - memcpy(b, a, n ); - return b; -} -#endif - -char * -FNAME(strdup)( const char *a FNAMEPRT ) -{ - size_t n = strlen(a); - char *p = FNAME(alloc)(n+1 FNAMEARG); - strcpy(p, a); - return p; -} - diff --git a/util/miscutil.c b/util/miscutil.c deleted file mode 100644 index e1735cd59..000000000 --- a/util/miscutil.c +++ /dev/null @@ -1,361 +0,0 @@ -/* miscutil.c - miscellaneous utilities - * 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 -#include -#include -#include -#include -#include -#ifdef HAVE_LANGINFO_H - #include -#endif -#include "types.h" -#include "util.h" -#include "i18n.h" - -/**************** - * I know that the OpenPGP protocol has a Y2106 problem ;-) - */ -u32 -make_timestamp() -{ - return time(NULL); -} - -/**************** - * 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( !isdigit(string[i]) ) - return 0; - if( !isdigit(string[5]) || !isdigit(string[6]) ) - return 0; - if( !isdigit(string[8]) || !isdigit(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"); - 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; -} - -/**************** - * Print a string to FP, but filter all control characters out. - */ -void -print_string( FILE *fp, const byte *p, size_t n, int delim ) -{ - for( ; n; n--, p++ ) - if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim || - (delim && *p=='\\')) { - putc('\\', fp); - if( *p == '\n' ) - putc('n', fp); - else if( *p == '\r' ) - putc('r', fp); - else if( *p == '\f' ) - putc('f', fp); - else if( *p == '\v' ) - putc('v', fp); - else if( *p == '\b' ) - putc('b', fp); - else if( !*p ) - putc('0', fp); - else - fprintf(fp, "x%02x", *p ); - } - else - putc(*p, fp); -} - -/**************** - * Print an UTF8 string to FP and filter all control characters out. - */ -void -print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim ) -{ - size_t i; - char *buf; - - /* 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, delim ); - /*(utf8 conversion already does the control character quoting)*/ - fputs( buf, fp ); - m_free( buf ); - } - else - print_string( fp, p, n, delim ); -} - -void -print_utf8_string( FILE *fp, const byte *p, size_t n ) -{ - print_utf8_string2 (fp, p, n, 0); -} - -/**************** - * This function returns a string which is suitable for printing - * Caller must release it with m_free() - */ -char * -make_printable_string( const byte *p, size_t n, int delim ) -{ - size_t save_n, buflen; - const byte *save_p; - char *buffer, *d; - - /* first count length */ - for(save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) { - if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim || - (delim && *p=='\\')) { - if( *p=='\n' || *p=='\r' || *p=='\f' - || *p=='\v' || *p=='\b' || !*p ) - buflen += 2; - else - buflen += 4; - } - else - buflen++; - } - p = save_p; - n = save_n; - /* and now make the string */ - d = buffer = m_alloc( buflen ); - for( ; n; n--, p++ ) { - if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim || - (delim && *p=='\\')) { - *d++ = '\\'; - if( *p == '\n' ) - *d++ = 'n'; - else if( *p == '\r' ) - *d++ = 'r'; - else if( *p == '\f' ) - *d++ = 'f'; - else if( *p == '\v' ) - *d++ = 'v'; - else if( *p == '\b' ) - *d++ = 'b'; - else if( !*p ) - *d++ = '0'; - else { - sprintf(d, "x%02x", *p ); - d += 2; - } - } - else - *d++ = *p; - } - *d = 0; - return buffer; -} - -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; -} diff --git a/util/riscos.c b/util/riscos.c deleted file mode 100644 index c64da3751..000000000 --- a/util/riscos.c +++ /dev/null @@ -1,299 +0,0 @@ -/* riscos.c - RISC OS stuff - * Copyright (C) 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG for RISC OS. - * - * 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 __RISCOS__C__ -#define __RISCOS__C__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "util.h" -#include "memory.h" - -#define __UNIXLIB_INTERNALS -#include -#undef __UNIXLIB_INTERNALS - -/* RISC OS specific defines that are not yet in UnixLib */ - -#define MimeMap_Translate 0x50B00 -#define MMM_TYPE_RISCOS 0 -#define MMM_TYPE_RISCOS_STRING 1 -#define MMM_TYPE_MIME 2 -#define MMM_TYPE_DOT_EXTN 3 - -/* RISC OS file open descriptor control list */ - -struct fds_item { - int fd; - struct fds_item *next; -}; -static struct fds_item *fds_list = NULL; -static int initialized = 0; - - -/* local RISC OS functions */ - -static int -is_read_only(const char *filename) -{ - int type, attr; - - if (_swix(OS_File, _INR(0,1) | _OUT(0) | _OUT(5), - 17, filename, &type, &attr)) - log_fatal("Can't get file attributes for %s!\n", filename); - - if (type == 0) - log_fatal("Can't find file %s!\n", filename); - - if (_swix(OS_File, _INR(0,1) | _IN(5), 4, filename, attr)) - return 1; - - return 0; -} - -static void -riscos_set_filetype_by_number(const char *filename, int type) -{ - if (_swix(OS_File, _INR(0,2), 18, filename, type)) - log_fatal("Can't set filetype for file %s!\n" - "Is the file on a read-only file system?\n", filename); -} - -/* exported RISC OS functions */ - -void -riscos_global_defaults(void) -{ - __riscosify_control = __RISCOSIFY_NO_PROCESS; - __feature_imagefs_is_file = 1; -} - -void -riscos_set_filetype(const char *filename, const char *mimetype) -{ - int result; - - if (_swix(MimeMap_Translate, _INR(0,2) | _OUT(3), - MMM_TYPE_MIME, mimetype, MMM_TYPE_RISCOS, &result)) - log_fatal("Can't translate MIME type %s!\n", mimetype); - - riscos_set_filetype_by_number(filename, result); -} - -pid_t -riscos_getpid(void) -{ - int state; - - if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 3, &state)) - log_fatal("Wimp_ReadSysInfo failed: Can't get WimpState (R0=3)!\n"); - - if (state) - if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 5, &state)) - log_fatal("Wimp_ReadSysInfo failed: Can't get task handle (R0=5)!\n"); - - return (pid_t) state; -} - -int -riscos_kill(pid_t pid, int sig) -{ - int buf[4], iter = 0; - - if (sig) - kill(pid, sig); - - do { - if (_swix(TaskManager_EnumerateTasks, _INR(0,2) | _OUT(0), - iter, buf, 16, &iter)) - log_fatal("TaskManager_EnumerateTasks failed!\n"); - if (buf[0] == pid) - return 0; - } while (iter >= 0); - - return __set_errno(ESRCH); -} - -int -riscos_access(const char *path, int amode) -{ - /* Do additional check, i.e. whether path is on write-protected floppy */ - if ((amode & W_OK) && is_read_only(path)) - return 1; - return access(path, amode); -} - -int -riscos_getchar(void) -{ - int c, flags; - - if (_swix(OS_ReadC, _OUT(0) | _OUT(_FLAGS), &c, &flags)) - log_fatal("OS_ReadC failed: Couldn't read from keyboard!\n"); - if (flags & _C) - log_fatal("OS_ReadC failed: Return Code = %i!\n", c); - - return c; -} - -#ifdef DEBUG -void -dump_fdlist(void) -{ - struct fds_item *iter = fds_list; - printf("List of open file descriptors:\n"); - while (iter) { - printf(" %i\n", iter->fd); - iter = iter->next; - } -} -#endif /* DEBUG */ - -int -fdopenfile(const char *filename, const int allow_write) -{ - struct fds_item *h; - int fd; - if (allow_write) - fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); - else - fd = open(filename, O_RDONLY); - if (fd == -1) - log_error("Can't open file %s: %i, %s!\n", filename, errno, strerror(errno)); - - if (!initialized) { - atexit (close_fds); - initialized = 1; - } - - h = fds_list; - fds_list = (struct fds_item *) m_alloc(sizeof(struct fds_item)); - fds_list->fd = fd; - fds_list->next = h; - - return fd; -} - -void -close_fds(void) -{ - FILE *fp; - struct fds_item *h = fds_list; - while( fds_list ) { - h = fds_list->next; - fp = fdopen (fds_list->fd, "a"); - if (fp) - fflush(fp); - close(fds_list->fd); - m_free(fds_list); - fds_list = h; - } -} - -int -renamefile(const char *old, const char *new) -{ - _kernel_oserror *e; - - if (e = _swix(OS_FSControl, _INR(0,2), 25, old, new)) { - if (e->errnum == 214) - return __set_errno(ENOENT); - if (e->errnum == 176) - return __set_errno(EEXIST); - printf("Error during renaming: %i, %s!\n", e->errnum, e->errmess); - return __set_errno(EOPSYS); - } - return 0; -} - -char * -gstrans(const char *old) -{ - int size = 256, last; - char *buf, *tmp; - - buf = (char *) m_alloc(size); - if (!buf) - log_fatal("Can't claim memory for OS_GSTrans buffer!\n"); - while (_C & _swi(OS_GSTrans, _INR(0,2) | _OUT(2) | _RETURN(_FLAGS), - old, buf, size, &last)) { - size += 256; - tmp = (char *) m_realloc(buf, size); - if (!tmp) - log_fatal("Can't claim memory for OS_GSTrans buffer!\n"); - buf = tmp; - } - - buf[last] = '\0'; - tmp = (char *) m_realloc(buf, last + 1); - if (!tmp) - log_fatal("Can't realloc memory after OS_GSTrans!\n"); - - return tmp; -} - -#ifdef DEBUG -void -list_openfiles(void) -{ - char *name; - int i, len; - - for (i = 255; i >= 0; --i) { - if (_swix(OS_Args, _INR(0,2) | _IN(5) | _OUT(5), 7, i, 0, 0, &len)) - continue; - - name = (char *) m_alloc(1-len); - if (!name) - log_fatal("Can't claim memory for OS_Args buffer!\n"); - - if (_swix(OS_Args, _INR(0,2) | _IN(5), 7, i, name, 1-len)) { - m_free(name); - log_fatal("Error when calling OS_Args(7)!\n"); - } - - if (_swix(OS_Args, _INR(0,1) | _OUT(0), 254, i, &len)) { - m_free(name); - log_fatal("Error when calling OS_Args(254)!\n"); - } - - printf("%3i: %s (%c%c)\n", i, name, - (len & 0x40) ? 'R' : 0, - (len & 0x80) ? 'W' : 0); - m_free(name); - } -} -#endif - -void -not_implemented(const char *feature) -{ - log_info("%s is not implemented in the RISC OS version!\n", feature); -} - -#endif /* !__RISCOS__C__ */ diff --git a/util/secmem.c b/util/secmem.c deleted file mode 100644 index d077fed17..000000000 --- a/util/secmem.c +++ /dev/null @@ -1,470 +0,0 @@ -/* secmem.c - memory allocation from a secure heap - * Copyright (C) 1998, 1999, 2000 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 -#include -#include -#include -#include -#include -#include -#if defined(HAVE_MLOCK) || defined(HAVE_MMAP) - #include - #include - #include - #ifdef USE_CAPABILITIES - #include - #endif - #ifdef HAVE_PLOCK - #include - #endif -#endif - -#include "types.h" -#include "memory.h" -#include "util.h" -#include "i18n.h" - -#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) - #define MAP_ANONYMOUS MAP_ANON -#endif -/* It seems that Slackware 7.1 does not know about EPERM */ -#if !defined(EPERM) && defined(ENOMEM) - #define EPERM ENOMEM -#endif - - -#define DEFAULT_POOLSIZE 16384 - -typedef struct memblock_struct MEMBLOCK; -struct memblock_struct { - unsigned size; - union { - MEMBLOCK *next; - PROPERLY_ALIGNED_TYPE aligned; - } u; -}; - - - -static void *pool; -static volatile int pool_okay; /* may be checked in an atexit function */ -#ifdef HAVE_MMAP -static volatile int pool_is_mmapped; -#endif -static size_t poolsize; /* allocated length */ -static size_t poollen; /* used length */ -static MEMBLOCK *unused_blocks; -static unsigned max_alloced; -static unsigned cur_alloced; -static unsigned max_blocks; -static unsigned cur_blocks; -static int disable_secmem; -static int show_warning; -static int no_warning; -static int suspend_warning; - - -static void -print_warn(void) -{ - if (!no_warning) - { - log_info(_("WARNING: using insecure memory!\n")); - log_info(_("please see http://www.gnupg.org/faq.html " - "for more information\n")); - } -} - - -static void -lock_pool( void *p, size_t n ) -{ - #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK) - int err; - - cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); - err = mlock( p, n ); - if( err && errno ) - err = errno; - cap_set_proc( cap_from_text("cap_ipc_lock+p") ); - - if( err ) { - if( errno != EPERM - #ifdef EAGAIN /* OpenBSD returns this */ - && errno != EAGAIN - #endif - #ifdef ENOSYS /* Some SCOs return this (function not implemented) */ - && errno != ENOSYS - #endif - #ifdef ENOMEM /* Linux can return this */ - && errno != ENOMEM - #endif - ) - log_error("can't lock memory: %s\n", strerror(err)); - show_warning = 1; - } - - #elif defined(HAVE_MLOCK) - uid_t uid; - int err; - - uid = getuid(); - - #ifdef HAVE_BROKEN_MLOCK - /* ick. but at least we get secured memory. about to lock - entire data segment. */ - #ifdef HAVE_PLOCK - err = plock( DATLOCK ); - if( err && errno ) - err = errno; -#else /*!HAVE_PLOCK*/ - if( uid ) { - errno = EPERM; - err = errno; - } - else { - err = mlock( p, n ); - if( err && errno ) - err = errno; - } - #endif /*!HAVE_PLOCK*/ - #else - err = mlock( p, n ); - if( err && errno ) - err = errno; - #endif - - if( uid && !geteuid() ) { - /* check that we really dropped the privs. - * Note: setuid(0) should always fail */ - if( setuid( uid ) || getuid() != geteuid() || !setuid(0) ) - log_fatal("failed to reset uid: %s\n", strerror(errno)); - } - - if( err ) { - if( errno != EPERM - #ifdef EAGAIN /* OpenBSD returns this */ - && errno != EAGAIN - #endif - #ifdef ENOSYS /* Some SCOs return this (function not implemented) */ - && errno != ENOSYS - #endif - #ifdef ENOMEM /* Linux can return this */ - && errno != ENOMEM - #endif - ) - log_error("can't lock memory: %s\n", strerror(err)); - show_warning = 1; - } - - #elif defined ( __QNX__ ) - /* QNX does not page at all, so the whole secure memory stuff does - * not make much sense. However it is still of use because it - * wipes out the memory on a free(). - * Therefore it is sufficient to suppress the warning - */ - #elif defined (HAVE_DOSISH_SYSTEM) - /* It does not make sense to print such a warning, given the fact that - * this whole Windows !@#$% and their user base are inherently insecure - */ - #elif defined (__riscos__) - /* no virtual memory on RISC OS, so no pages are swapped to disc, - * besides we don't have mmap, so we don't use it! ;-) - * But don't complain, as explained above. - */ - #else - log_info("Please note that you don't have secure memory on this system\n"); - #endif -} - - -static void -init_pool( size_t n) -{ - size_t pgsize; - - poolsize = n; - - if( disable_secmem ) - log_bug("secure memory is disabled"); - - #ifdef HAVE_GETPAGESIZE - pgsize = getpagesize(); - #else - pgsize = 4096; - #endif - - #ifdef HAVE_MMAP - poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1); - #ifdef MAP_ANONYMOUS - pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - #else /* map /dev/zero instead */ - { int fd; - - fd = open("/dev/zero", O_RDWR); - if( fd == -1 ) { - log_error("can't open /dev/zero: %s\n", strerror(errno) ); - pool = (void*)-1; - } - else { - pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, - MAP_PRIVATE, fd, 0); - } - } - #endif - if( pool == (void*)-1 ) - log_info("can't mmap pool of %u bytes: %s - using malloc\n", - (unsigned)poolsize, strerror(errno)); - else { - pool_is_mmapped = 1; - pool_okay = 1; - } - - #endif - if( !pool_okay ) { - pool = malloc( poolsize ); - if( !pool ) - log_fatal("can't allocate memory pool of %u bytes\n", - (unsigned)poolsize); - else - pool_okay = 1; - } - lock_pool( pool, poolsize ); - poollen = 0; -} - - -/* concatenate unused blocks */ -static void -compress_pool(void) -{ - /* fixme: we really should do this */ -} - -void -secmem_set_flags( unsigned flags ) -{ - int was_susp = suspend_warning; - - no_warning = flags & 1; - suspend_warning = flags & 2; - - /* and now issue the warning if it is not longer suspended */ - if( was_susp && !suspend_warning && show_warning ) { - show_warning = 0; - print_warn(); - } -} - -unsigned -secmem_get_flags(void) -{ - unsigned flags; - - flags = no_warning ? 1:0; - flags |= suspend_warning ? 2:0; - return flags; -} - -void -secmem_init( size_t n ) -{ - if( !n ) { -#ifndef __riscos__ - #ifdef USE_CAPABILITIES - /* drop all capabilities */ - cap_set_proc( cap_from_text("all-eip") ); - - #elif !defined(HAVE_DOSISH_SYSTEM) - uid_t uid; - - disable_secmem=1; - uid = getuid(); - if( uid != geteuid() ) { - if( setuid( uid ) || getuid() != geteuid() || !setuid(0) ) - log_fatal("failed to drop setuid\n" ); - } - #endif -#endif /* !__riscos__ */ - } - else { - if( n < DEFAULT_POOLSIZE ) - n = DEFAULT_POOLSIZE; - if( !pool_okay ) - init_pool(n); - else - log_error("Oops, secure memory pool already initialized\n"); - } -} - - -void * -secmem_malloc( size_t size ) -{ - MEMBLOCK *mb, *mb2; - int compressed=0; - - if( !pool_okay ) { - log_info( - _("operation is not possible without initialized secure memory\n")); - log_info(_("(you may have used the wrong program for this task)\n")); - exit(2); - } - if( show_warning && !suspend_warning ) { - show_warning = 0; - print_warn(); - } - - /* blocks are always a multiple of 32 */ - size += sizeof(MEMBLOCK); - size = ((size + 31) / 32) * 32; - - retry: - /* try to get it from the used blocks */ - for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next ) - if( mb->size >= size ) { - if( mb2 ) - mb2->u.next = mb->u.next; - else - unused_blocks = mb->u.next; - goto leave; - } - /* allocate a new block */ - if( (poollen + size <= poolsize) ) { - mb = (void*)((char*)pool + poollen); - poollen += size; - mb->size = size; - } - else if( !compressed ) { - compressed=1; - compress_pool(); - goto retry; - } - else - return NULL; - - leave: - cur_alloced += mb->size; - cur_blocks++; - if( cur_alloced > max_alloced ) - max_alloced = cur_alloced; - if( cur_blocks > max_blocks ) - max_blocks = cur_blocks; - - return &mb->u.aligned.c; -} - - -void * -secmem_realloc( void *p, size_t newsize ) -{ - MEMBLOCK *mb; - size_t size; - void *a; - - mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c)); - size = mb->size; - if( newsize < size ) - return p; /* it is easier not to shrink the memory */ - a = secmem_malloc( newsize ); - if ( a ) { - memcpy(a, p, size); - memset((char*)a+size, 0, newsize-size); - secmem_free(p); - } - return a; -} - - -void -secmem_free( void *a ) -{ - MEMBLOCK *mb; - size_t size; - - if( !a ) - return; - - mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c)); - size = mb->size; - /* This does not make much sense: probably this memory is held in the - * cache. We do it anyway: */ - memset(mb, 0xff, size ); - memset(mb, 0xaa, size ); - memset(mb, 0x55, size ); - memset(mb, 0x00, size ); - mb->size = size; - mb->u.next = unused_blocks; - unused_blocks = mb; - cur_blocks--; - cur_alloced -= size; -} - -int -m_is_secure( const void *p ) -{ - return p >= pool && p < (void*)((char*)pool+poolsize); -} - - - -/**************** - * Warning: This code might be called by an interrupt handler - * and frankly, there should really be such a handler, - * to make sure that the memory is wiped out. - * We hope that the OS wipes out mlocked memory after - * receiving a SIGKILL - it really should do so, otherwise - * there is no chance to get the secure memory cleaned. - */ -void -secmem_term() -{ - if( !pool_okay ) - return; - - memset( pool, 0xff, poolsize); - memset( pool, 0xaa, poolsize); - memset( pool, 0x55, poolsize); - memset( pool, 0x00, poolsize); - #ifdef HAVE_MMAP - if( pool_is_mmapped ) - munmap( pool, poolsize ); - #endif - pool = NULL; - pool_okay = 0; - poolsize=0; - poollen=0; - unused_blocks=NULL; -} - - -void -secmem_dump_stats() -{ - if( disable_secmem ) - return; - fprintf(stderr, - "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n", - cur_alloced, max_alloced, cur_blocks, max_blocks, - (ulong)poollen, (ulong)poolsize ); -} - diff --git a/util/simple-gettext.c b/util/simple-gettext.c deleted file mode 100644 index b5ee446cb..000000000 --- a/util/simple-gettext.c +++ /dev/null @@ -1,497 +0,0 @@ -/* simple-gettext.c - a simplified version of gettext. - * Copyright (C) 1995, 1996, 1997, 1999 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 simplified version of gettext written by Ulrich Drepper. - * It is used for the Win32 version of GnuPG beucase all the overhead - * of gettext is not needed and we have to do some special Win32 stuff. - * I decided that this is far easier than to tweak gettext for the special - * cases (I tried it but it is a lot of code). wk 15.09.99 - */ - -#include -#ifdef USE_SIMPLE_GETTEXT -#if !defined (__MINGW32__) && !defined (__CYGWIN32__) -#error This file can only be used with MingW32 or Cygwin32 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include "types.h" -#include "util.h" - - -/* The magic number of the GNU message catalog format. */ -#define MAGIC 0x950412de -#define MAGIC_SWAPPED 0xde120495 - -/* Revision number of the currently used .mo (binary) file format. */ -#define MO_REVISION_NUMBER 0 - - -/* Header for binary .mo file format. */ -struct mo_file_header -{ - /* The magic number. */ - u32 magic; - /* The revision number of the file format. */ - u32 revision; - /* The number of strings pairs. */ - u32 nstrings; - /* Offset of table with start offsets of original strings. */ - u32 orig_tab_offset; - /* Offset of table with start offsets of translation strings. */ - u32 trans_tab_offset; - /* Size of hashing table. */ - u32 hash_tab_size; - /* Offset of first hashing entry. */ - u32 hash_tab_offset; -}; - -struct string_desc -{ - /* Length of addressed string. */ - u32 length; - /* Offset of string in file. */ - u32 offset; -}; - - - -struct loaded_domain -{ - char *data; - int must_swap; - u32 nstrings; -/* char *mapped; */ - struct string_desc *orig_tab; - struct string_desc *trans_tab; - u32 hash_size; - u32 *hash_tab; -}; - - -static struct loaded_domain *the_domain; - -static __inline__ u32 -do_swap_u32( u32 i ) -{ - return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); -} - -#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) ) - - -/* We assume to have `unsigned long int' value with at least 32 bits. */ -#define HASHWORDBITS 32 - -/* The so called `hashpjw' function by P.J. Weinberger - [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, - 1986, 1987 Bell Telephone Laboratories, Inc.] */ - -static __inline__ ulong -hash_string( const char *str_param ) -{ - unsigned long int hval, g; - const char *str = str_param; - - hval = 0; - while (*str != '\0') - { - hval <<= 4; - hval += (unsigned long int) *str++; - g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); - if (g != 0) - { - hval ^= g >> (HASHWORDBITS - 8); - hval ^= g; - } - } - return hval; -} - - -static struct loaded_domain * -load_domain( const char *filename ) -{ - FILE *fp; - size_t size; - struct stat st; - struct mo_file_header *data = NULL; - struct loaded_domain *domain = NULL; - size_t to_read; - char *read_ptr; - - fp = fopen( filename, "rb" ); - if( !fp ) - return NULL; /* can't open the file */ - /* we must know about the size of the file */ - if( fstat( fileno(fp ), &st ) - || (size = (size_t)st.st_size) != st.st_size - || size < sizeof (struct mo_file_header) ) { - fclose( fp ); - return NULL; - } - - data = malloc( size ); - if( !data ) { - fclose( fp ); - return NULL; /* out of memory */ - } - - to_read = size; - read_ptr = (char *) data; - do { - long int nb = fread( read_ptr, 1, to_read, fp ); - if( nb < to_read ) { - fclose (fp); - free(data); - return NULL; /* read error */ - } - read_ptr += nb; - to_read -= nb; - } while( to_read > 0 ); - fclose (fp); - - /* Using the magic number we can test whether it really is a message - * catalog file. */ - if( data->magic != MAGIC && data->magic != MAGIC_SWAPPED ) { - /* The magic number is wrong: not a message catalog file. */ - free( data ); - return NULL; - } - - domain = calloc( 1, sizeof *domain ); - if( !domain ) { - free( data ); - return NULL; - } - domain->data = (char *) data; - domain->must_swap = data->magic != MAGIC; - - /* Fill in the information about the available tables. */ - switch( SWAPIT(domain->must_swap, data->revision) ) { - case 0: - domain->nstrings = SWAPIT(domain->must_swap, data->nstrings); - domain->orig_tab = (struct string_desc *) - ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset)); - domain->trans_tab = (struct string_desc *) - ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset)); - domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size); - domain->hash_tab = (u32 *) - ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset)); - break; - - default: /* This is an invalid revision. */ - free( data ); - free( domain ); - return NULL; - } - - /* allocate an array to keep track of code page mappings */ -/* domain->mapped = calloc( 1, domain->nstrings ); */ -/* if( !domain->mapped ) { */ -/* free( data ); */ -/* free( domain ); */ -/* return NULL; */ -/* } */ - - return domain; -} - - -/**************** - * Set the file used for translations. Pass a NULL to disable - * translation. A new filename may be set at anytime. - * WARNING: After changing the filename you shoudl not access any data - * retrieved by gettext(). - */ -int -set_gettext_file( const char *filename ) -{ - struct loaded_domain *domain = NULL; - - if( filename && *filename ) { - if( filename[0] == '/' - #ifdef HAVE_DRIVE_LETTERS - || ( isalpha(filename[0]) - && filename[1] == ':' - && (filename[2] == '/' || filename[2] == '\\') ) - #endif - ) { - /* absolute path - use it as is */ - domain = load_domain( filename ); - } - else { /* relative path - append ".mo" and get dir from the environment */ - char *buf = NULL; - char *dir; - char *p; - - dir = read_w32_registry_string( NULL, - "Control Panel\\Mingw32\\NLS", - "MODir" ); - if( dir && (buf=malloc(strlen(dir)+strlen(filename)+1+3+1)) ) { - strcpy(stpcpy(stpcpy(stpcpy( buf, dir),"\\"), filename),".mo"); - /* Better make sure that we don't mix forward and - backward slashes. It seems that some Windoze - versions don't accept this. */ - for (p=buf; *p; p++) - { - if (*p == '/') - *p = '\\'; - } - domain = load_domain( buf ); - free(buf); - } - free(dir); - } - if( !domain ) - return -1; - } - - if( the_domain ) { - free( the_domain->data ); -/* free( the_domain->mapped ); */ - free( the_domain ); - the_domain = NULL; - } - the_domain = domain; - return NULL; -} - - -static const char* -get_string( struct loaded_domain *domain, u32 idx ) -{ - char *p = domain->data + SWAPIT(domain->must_swap, - domain->trans_tab[idx].offset); -#if 0 /* Mapping is not used any more. Instead we convert the files when - Creating the binary distribution. */ - if( !domain->mapped[idx] ) { - byte *pp; - - domain->mapped[idx] = 1; - /* we assume Latin1 -> CP 850 for now */ - for( pp=p; *pp; pp++ ) { - if( (*pp & 0x80) ) { - switch( *pp ) { - /* ISO-8859-1 to IBM-CP-850 */ - case 0xa0: *pp = '\xff' ; break; /* nobreakspace */ - case 0xa1: *pp = '\xad' ; break; /* exclamdown */ - case 0xa2: *pp = '\xbd' ; break; /* cent */ - case 0xa3: *pp = '\x9c' ; break; /* sterling */ - case 0xa4: *pp = '\xcf' ; break; /* currency */ - case 0xa5: *pp = '\xbe' ; break; /* yen */ - case 0xa6: *pp = '\xdd' ; break; /* brokenbar */ - case 0xa7: *pp = '\xf5' ; break; /* section */ - case 0xa8: *pp = '\xf9' ; break; /* diaeresis */ - case 0xa9: *pp = '\xb8' ; break; /* copyright */ - case 0xaa: *pp = '\xa6' ; break; /* ordfeminine */ - case 0xab: *pp = '\xae' ; break; /* guillemotleft */ - case 0xac: *pp = '\xaa' ; break; /* notsign */ - case 0xad: *pp = '\xf0' ; break; /* hyphen */ - case 0xae: *pp = '\xa9' ; break; /* registered */ - case 0xaf: *pp = '\xee' ; break; /* macron */ - case 0xb0: *pp = '\xf8' ; break; /* degree */ - case 0xb1: *pp = '\xf1' ; break; /* plusminus */ - case 0xb2: *pp = '\xfd' ; break; /* twosuperior */ - case 0xb3: *pp = '\xfc' ; break; /* threesuperior */ - case 0xb4: *pp = '\xef' ; break; /* acute */ - case 0xb5: *pp = '\xe6' ; break; /* mu */ - case 0xb6: *pp = '\xf4' ; break; /* paragraph */ - case 0xb7: *pp = '\xfa' ; break; /* periodcentered */ - case 0xb8: *pp = '\xf7' ; break; /* cedilla */ - case 0xb9: *pp = '\xfb' ; break; /* onesuperior */ - case 0xba: *pp = '\xa7' ; break; /* masculine */ - case 0xbb: *pp = '\xaf' ; break; /* guillemotright */ - case 0xbc: *pp = '\xac' ; break; /* onequarter */ - case 0xbd: *pp = '\xab' ; break; /* onehalf */ - case 0xbe: *pp = '\xf3' ; break; /* threequarters */ - case 0xbf: *pp = '\xa8' ; break; /* questiondown */ - case 0xc0: *pp = '\xb7' ; break; /* Agrave */ - case 0xc1: *pp = '\xb5' ; break; /* Aacute */ - case 0xc2: *pp = '\xb6' ; break; /* Acircumflex */ - case 0xc3: *pp = '\xc7' ; break; /* Atilde */ - case 0xc4: *pp = '\x8e' ; break; /* Adiaeresis */ - case 0xc5: *pp = '\x8f' ; break; /* Aring */ - case 0xc6: *pp = '\x92' ; break; /* AE */ - case 0xc7: *pp = '\x80' ; break; /* Ccedilla */ - case 0xc8: *pp = '\xd4' ; break; /* Egrave */ - case 0xc9: *pp = '\x90' ; break; /* Eacute */ - case 0xca: *pp = '\xd2' ; break; /* Ecircumflex */ - case 0xcb: *pp = '\xd3' ; break; /* Ediaeresis */ - case 0xcc: *pp = '\xde' ; break; /* Igrave */ - case 0xcd: *pp = '\xd6' ; break; /* Iacute */ - case 0xce: *pp = '\xd7' ; break; /* Icircumflex */ - case 0xcf: *pp = '\xd8' ; break; /* Idiaeresis */ - case 0xd0: *pp = '\xd1' ; break; /* Eth */ - case 0xd1: *pp = '\xa5' ; break; /* Ntilde */ - case 0xd2: *pp = '\xe3' ; break; /* Ograve */ - case 0xd3: *pp = '\xe0' ; break; /* Oacute */ - case 0xd4: *pp = '\xe2' ; break; /* Ocircumflex */ - case 0xd5: *pp = '\xe5' ; break; /* Otilde */ - case 0xd6: *pp = '\x99' ; break; /* Odiaeresis */ - case 0xd7: *pp = '\x9e' ; break; /* multiply */ - case 0xd8: *pp = '\x9d' ; break; /* Ooblique */ - case 0xd9: *pp = '\xeb' ; break; /* Ugrave */ - case 0xda: *pp = '\xe9' ; break; /* Uacute */ - case 0xdb: *pp = '\xea' ; break; /* Ucircumflex */ - case 0xdc: *pp = '\x9a' ; break; /* Udiaeresis */ - case 0xdd: *pp = '\xed' ; break; /* Yacute */ - case 0xde: *pp = '\xe8' ; break; /* Thorn */ - case 0xdf: *pp = '\xe1' ; break; /* ssharp */ - case 0xe0: *pp = '\x85' ; break; /* agrave */ - case 0xe1: *pp = '\xa0' ; break; /* aacute */ - case 0xe2: *pp = '\x83' ; break; /* acircumflex */ - case 0xe3: *pp = '\xc6' ; break; /* atilde */ - case 0xe4: *pp = '\x84' ; break; /* adiaeresis */ - case 0xe5: *pp = '\x86' ; break; /* aring */ - case 0xe6: *pp = '\x91' ; break; /* ae */ - case 0xe7: *pp = '\x87' ; break; /* ccedilla */ - case 0xe8: *pp = '\x8a' ; break; /* egrave */ - case 0xe9: *pp = '\x82' ; break; /* eacute */ - case 0xea: *pp = '\x88' ; break; /* ecircumflex */ - case 0xeb: *pp = '\x89' ; break; /* ediaeresis */ - case 0xec: *pp = '\x8d' ; break; /* igrave */ - case 0xed: *pp = '\xa1' ; break; /* iacute */ - case 0xee: *pp = '\x8c' ; break; /* icircumflex */ - case 0xef: *pp = '\x8b' ; break; /* idiaeresis */ - case 0xf0: *pp = '\xd0' ; break; /* eth */ - case 0xf1: *pp = '\xa4' ; break; /* ntilde */ - case 0xf2: *pp = '\x95' ; break; /* ograve */ - case 0xf3: *pp = '\xa2' ; break; /* oacute */ - case 0xf4: *pp = '\x93' ; break; /* ocircumflex */ - case 0xf5: *pp = '\xe4' ; break; /* otilde */ - case 0xf6: *pp = '\x94' ; break; /* odiaeresis */ - case 0xf7: *pp = '\xf6' ; break; /* division */ - case 0xf8: *pp = '\x9b' ; break; /* oslash */ - case 0xf9: *pp = '\x97' ; break; /* ugrave */ - case 0xfa: *pp = '\xa3' ; break; /* uacute */ - case 0xfb: *pp = '\x96' ; break; /* ucircumflex */ - case 0xfc: *pp = '\x81' ; break; /* udiaeresis */ - case 0xfd: *pp = '\xec' ; break; /* yacute */ - case 0xfe: *pp = '\xe7' ; break; /* thorn */ - case 0xff: *pp = '\x98' ; break; /* ydiaeresis */ - default : break; - } - } - } - - } -#endif /* unused code */ - return (const char*)p; -} - - - -const char * -gettext( const char *msgid ) -{ - struct loaded_domain *domain; - size_t act = 0; - size_t top, bottom; - - if( !(domain = the_domain) ) - goto not_found; - - /* Locate the MSGID and its translation. */ - if( domain->hash_size > 2 && domain->hash_tab ) { - /* Use the hashing table. */ - u32 len = strlen (msgid); - u32 hash_val = hash_string (msgid); - u32 idx = hash_val % domain->hash_size; - u32 incr = 1 + (hash_val % (domain->hash_size - 2)); - u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]); - - if ( !nstr ) /* Hash table entry is empty. */ - goto not_found; - - if( SWAPIT(domain->must_swap, - domain->orig_tab[nstr - 1].length) == len - && !strcmp( msgid, - domain->data + SWAPIT(domain->must_swap, - domain->orig_tab[nstr - 1].offset)) ) - return get_string( domain, nstr - 1 ); - - for(;;) { - if (idx >= domain->hash_size - incr) - idx -= domain->hash_size - incr; - else - idx += incr; - - nstr = SWAPIT(domain->must_swap, domain->hash_tab[idx]); - if( !nstr ) - goto not_found; /* Hash table entry is empty. */ - - if ( SWAPIT(domain->must_swap, - domain->orig_tab[nstr - 1].length) == len - && !strcmp (msgid, - domain->data + SWAPIT(domain->must_swap, - domain->orig_tab[nstr - 1].offset))) - return get_string( domain, nstr-1 ); - } - /* NOTREACHED */ - } - - /* Now we try the default method: binary search in the sorted - array of messages. */ - bottom = 0; - top = domain->nstrings; - while( bottom < top ) { - int cmp_val; - - act = (bottom + top) / 2; - cmp_val = strcmp(msgid, domain->data - + SWAPIT(domain->must_swap, - domain->orig_tab[act].offset)); - if (cmp_val < 0) - top = act; - else if (cmp_val > 0) - bottom = act + 1; - else - return get_string( domain, act ); - } - - not_found: - return msgid; -} - -#if 0 - unsigned int cp1, cp2; - - cp1 = GetConsoleCP(); - cp2 = GetConsoleOutputCP(); - - log_info("InputCP=%u OutputCP=%u\n", cp1, cp2 ); - - if( !SetConsoleOutputCP( 1252 ) ) - log_info("SetConsoleOutputCP failed: %d\n", (int)GetLastError() ); - - cp1 = GetConsoleCP(); - cp2 = GetConsoleOutputCP(); - log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 ); -#endif - -#endif /* USE_SIMPLE_GETTEXT */ diff --git a/util/strgutil.c b/util/strgutil.c deleted file mode 100644 index e793fc1ce..000000000 --- a/util/strgutil.c +++ /dev/null @@ -1,955 +0,0 @@ -/* strgutil.c - string utilities - * Copyright (C) 1994, 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 -#include -#include -#include -#ifdef HAVE_LANGINFO_CODESET -#include -#endif - -#include "types.h" -#include "util.h" -#include "memory.h" - - -static ushort koi8_unicode[128] = { - 0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524, - 0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590, - 0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248, - 0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7, - 0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556, - 0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e, - 0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565, - 0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9, - 0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433, - 0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e, - 0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432, - 0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a, - 0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413, - 0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e, - 0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412, - 0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a -}; - -static ushort latin2_unicode[128] = { - 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, - 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, - 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, - 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, - 0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7, - 0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B, - 0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7, - 0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C, - 0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7, - 0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E, - 0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7, - 0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF, - 0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7, - 0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F, - 0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7, - 0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9 -}; - - -static const char *active_charset_name = "iso-8859-1"; -static ushort *active_charset = NULL; -static int no_translation = 0; - -void -free_strlist( STRLIST sl ) -{ - STRLIST sl2; - - for(; sl; sl = sl2 ) { - sl2 = sl->next; - m_free(sl); - } -} - - -STRLIST -add_to_strlist( STRLIST *list, const char *string ) -{ - STRLIST sl; - - sl = m_alloc( sizeof *sl + strlen(string)); - sl->flags = 0; - strcpy(sl->d, string); - sl->next = *list; - *list = sl; - return sl; -} - -/**************** - * ame as add_to_strlist() but if is_utf8 is *not* set a conversion - * to UTF8 is done - */ -STRLIST -add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) -{ - STRLIST sl; - - if( is_utf8 ) - sl = add_to_strlist( list, string ); - else { - char *p = native_to_utf8( string ); - sl = add_to_strlist( list, p ); - m_free( p ); - } - return sl; -} - -STRLIST -append_to_strlist( STRLIST *list, const char *string ) -{ - STRLIST r, sl; - - sl = m_alloc( sizeof *sl + strlen(string)); - sl->flags = 0; - strcpy(sl->d, string); - sl->next = NULL; - if( !*list ) - *list = sl; - else { - for( r = *list; r->next; r = r->next ) - ; - r->next = sl; - } - return sl; -} - -STRLIST -append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) -{ - STRLIST sl; - - if( is_utf8 ) - sl = append_to_strlist( list, string ); - else { - char *p = native_to_utf8( string ); - sl = append_to_strlist( list, p ); - m_free( p ); - } - return sl; -} - - -STRLIST -strlist_prev( STRLIST head, STRLIST node ) -{ - STRLIST n; - - for(n=NULL; head && head != node; head = head->next ) - n = head; - return n; -} - -STRLIST -strlist_last( STRLIST node ) -{ - if( node ) - for( ; node->next ; node = node->next ) - ; - return node; -} - -char * -pop_strlist( STRLIST *list ) -{ - char *str=NULL; - STRLIST sl=*list; - - if(sl) - { - str=m_alloc(strlen(sl->d)+1); - strcpy(str,sl->d); - - *list=sl->next; - m_free(sl); - } - - return str; -} - -/**************** - * look for the substring SUB in buffer and return a pointer to that - * substring in BUF or NULL if not found. - * Comparison is case-insensitive. - */ -const char * -memistr( const char *buf, size_t buflen, const char *sub ) -{ - const byte *t, *s ; - size_t n; - - for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) - if( toupper(*t) == toupper(*s) ) { - for( buf=t++, buflen = n--, s++; - n && toupper(*t) == toupper(*s); t++, s++, n-- ) - ; - if( !*s ) - return buf; - t = buf; n = buflen; s = sub ; - } - - return NULL ; -} - -const char * -ascii_memistr( const char *buf, size_t buflen, const char *sub ) -{ - const byte *t, *s ; - size_t n; - - for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) - if( ascii_toupper(*t) == ascii_toupper(*s) ) { - for( buf=t++, buflen = n--, s++; - n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- ) - ; - if( !*s ) - return buf; - t = buf; n = buflen; s = sub ; - } - - return NULL ; -} - -/**************** - * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein - * '\0' angehngt. Ist n = 0, so geschieht nichts, ist Destination - * gleich NULL, so wird via m_alloc Speicher besorgt, ist dann nicht - * gengend Speicher vorhanden, so bricht die funktion ab. - */ -char * -mem2str( char *dest , const void *src , size_t n ) -{ - char *d; - const char *s; - - if( n ) { - if( !dest ) - dest = m_alloc( n ) ; - d = dest; - s = src ; - for(n--; n && *s; n-- ) - *d++ = *s++; - *d = '\0' ; - } - - return dest ; -} - - -/**************** - * remove leading and trailing white spaces - */ -char * -trim_spaces( char *str ) -{ - char *string, *p, *mark; - - string = str; - /* find first non space character */ - for( p=string; *p && isspace( *(byte*)p ) ; p++ ) - ; - /* move characters */ - for( (mark = NULL); (*string = *p); string++, p++ ) - if( isspace( *(byte*)p ) ) { - if( !mark ) - mark = string ; - } - else - mark = NULL ; - if( mark ) - *mark = '\0' ; /* remove trailing spaces */ - - return str ; -} - - - -unsigned int -trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) -{ - byte *p, *mark; - unsigned n; - - for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { - if( strchr(trimchars, *p ) ) { - if( !mark ) - mark = p; - } - else - mark = NULL; - } - - if( mark ) { - *mark = 0; - return mark - line; - } - return len; -} - -/**************** - * remove trailing white spaces and return the length of the buffer - */ -unsigned -trim_trailing_ws( byte *line, unsigned len ) -{ - return trim_trailing_chars( line, len, " \t\r\n" ); -} - -unsigned int -check_trailing_chars( const byte *line, unsigned int len, - const char *trimchars ) -{ - const byte *p, *mark; - unsigned int n; - - for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { - if( strchr(trimchars, *p ) ) { - if( !mark ) - mark = p; - } - else - mark = NULL; - } - - if( mark ) { - return mark - line; - } - return len; -} - -/**************** - * remove trailing white spaces and return the length of the buffer - */ -unsigned int -check_trailing_ws( const byte *line, unsigned int len ) -{ - return check_trailing_chars( line, len, " \t\r\n" ); -} - - - -int -string_count_chr( const char *string, int c ) -{ - int count; - for(count=0; *string; string++ ) - if( *string == c ) - count++; - return count; -} - - -int -set_native_charset( const char *newset ) -{ - if (!newset) -#ifdef HAVE_LANGINFO_CODESET - newset = nl_langinfo (CODESET); -#else - newset = "8859-1"; -#endif - - if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) { - newset += 3; - if (*newset == '-' || *newset == '_') - newset++; - } - - if( !*newset - || !ascii_strcasecmp (newset, "8859-1" ) - || !ascii_strcasecmp (newset, "8859-15" ) ) { - active_charset_name = "iso-8859-1"; - no_translation = 0; - active_charset = NULL; - } - else if( !ascii_strcasecmp( newset, "8859-2" ) ) { - active_charset_name = "iso-8859-2"; - no_translation = 0; - active_charset = latin2_unicode; - } - else if( !ascii_strcasecmp( newset, "koi8-r" ) ) { - active_charset_name = "koi8-r"; - no_translation = 0; - active_charset = koi8_unicode; - } - else if( !ascii_strcasecmp (newset, "utf8" ) - || !ascii_strcasecmp(newset, "utf-8") ) { - active_charset_name = "utf-8"; - no_translation = 1; - active_charset = NULL; - } - else - return G10ERR_GENERAL; - return 0; -} - -const char* -get_native_charset() -{ - return active_charset_name; -} - -/**************** - * Convert string, which is in native encoding to UTF8 and return the - * new allocated UTF8 string. - */ -char * -native_to_utf8( const char *string ) -{ - const byte *s; - char *buffer; - byte *p; - size_t length=0; - - if (no_translation) { - buffer = m_strdup (string); - } - else if( active_charset ) { - for(s=string; *s; s++ ) { - length++; - if( *s & 0x80 ) - length += 2; /* we may need 3 bytes */ - } - buffer = m_alloc( length + 1 ); - for(p=buffer, s=string; *s; s++ ) { - if( *s & 0x80 ) { - ushort val = active_charset[ *s & 0x7f ]; - if( val < 0x0800 ) { - *p++ = 0xc0 | ( (val >> 6) & 0x1f ); - *p++ = 0x80 | ( val & 0x3f ); - } - else { - *p++ = 0xe0 | ( (val >> 12) & 0x0f ); - *p++ = 0x80 | ( (val >> 6) & 0x3f ); - *p++ = 0x80 | ( val & 0x3f ); - } - } - else - *p++ = *s; - } - *p = 0; - } - else { - for(s=string; *s; s++ ) { - length++; - if( *s & 0x80 ) - length++; - } - buffer = m_alloc( length + 1 ); - for(p=buffer, s=string; *s; s++ ) { - if( *s & 0x80 ) { - *p++ = 0xc0 | ((*s >> 6) & 3); - *p++ = 0x80 | ( *s & 0x3f ); - } - else - *p++ = *s; - } - *p = 0; - } - return buffer; -} - - -/**************** - * Convert string, which is in UTF8 to native encoding. illegal - * encodings by some "\xnn" and quote all control characters. A - * character with value DELIM will always be quoted, it must be a - * vanilla ASCII character. - */ -char * -utf8_to_native( const char *string, size_t length, int delim ) -{ - int nleft; - int i; - byte encbuf[8]; - int encidx; - const byte *s; - size_t n; - byte *buffer = NULL, *p = NULL; - unsigned long val = 0; - size_t slen; - int resync = 0; - - /* 1. pass (p==NULL): count the extended utf-8 characters */ - /* 2. pass (p!=NULL): create string */ - for( ;; ) { - for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) { - if( resync ) { - if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) { - /* still invalid */ - if( p ) { - sprintf(p, "\\x%02x", *s ); - p += 4; - } - n += 4; - continue; - } - resync = 0; - } - if( !nleft ) { - if( !(*s & 0x80) ) { /* plain ascii */ - if( *s < 0x20 || *s == 0x7f || *s == delim || - (delim && *s=='\\')) { - n++; - if( p ) - *p++ = '\\'; - switch( *s ) { - case '\n': n++; if( p ) *p++ = 'n'; break; - case '\r': n++; if( p ) *p++ = 'r'; break; - case '\f': n++; if( p ) *p++ = 'f'; break; - case '\v': n++; if( p ) *p++ = 'v'; break; - case '\b': n++; if( p ) *p++ = 'b'; break; - case 0 : n++; if( p ) *p++ = '0'; break; - default: - n += 3; - if ( p ) { - sprintf( p, "x%02x", *s ); - p += 3; - } - break; - } - } - else { - if( p ) *p++ = *s; - n++; - } - } - else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */ - val = *s & 0x1f; - nleft = 1; - encidx = 0; - encbuf[encidx++] = *s; - } - else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */ - val = *s & 0x0f; - nleft = 2; - encidx = 0; - encbuf[encidx++] = *s; - } - else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */ - val = *s & 0x07; - nleft = 3; - encidx = 0; - encbuf[encidx++] = *s; - } - else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */ - val = *s & 0x03; - nleft = 4; - encidx = 0; - encbuf[encidx++] = *s; - } - else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */ - val = *s & 0x01; - nleft = 5; - encidx = 0; - encbuf[encidx++] = *s; - } - else { /* invalid encoding: print as \xnn */ - if( p ) { - sprintf(p, "\\x%02x", *s ); - p += 4; - } - n += 4; - resync = 1; - } - } - else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */ - if( p ) { - for(i=0; i < encidx; i++ ) { - sprintf(p, "\\x%02x", encbuf[i] ); - p += 4; - } - sprintf(p, "\\x%02x", *s ); - p += 4; - } - n += 4 + 4*encidx; - nleft = 0; - encidx = 0; - resync = 1; - } - else { - encbuf[encidx++] = *s; - val <<= 6; - val |= *s & 0x3f; - if( !--nleft ) { /* ready */ - if (no_translation) { - if( p ) { - for(i=0; i < encidx; i++ ) - *p++ = encbuf[i]; - } - n += encidx; - encidx = 0; - } - else if( active_charset ) { /* table lookup */ - for(i=0; i < 128; i++ ) { - if( active_charset[i] == val ) - break; - } - if( i < 128 ) { /* we can print this one */ - if( p ) *p++ = i+128; - n++; - } - else { /* we do not have a translation: print utf8 */ - if( p ) { - for(i=0; i < encidx; i++ ) { - sprintf(p, "\\x%02x", encbuf[i] ); - p += 4; - } - } - n += encidx*4; - encidx = 0; - } - } - else { /* native set */ - if( val >= 0x80 && val < 256 ) { - n++; /* we can simply print this character */ - if( p ) *p++ = val; - } - else { /* we do not have a translation: print utf8 */ - if( p ) { - for(i=0; i < encidx; i++ ) { - sprintf(p, "\\x%02x", encbuf[i] ); - p += 4; - } - } - n += encidx*4; - encidx = 0; - } - } - } - - } - } - if( !buffer ) { /* allocate the buffer after the first pass */ - buffer = p = m_alloc( n + 1 ); - } - else { - *p = 0; /* make a string */ - return buffer; - } - } -} - -/**************************************************** - ******** locale insensitive ctype functions ******** - ****************************************************/ -/* FIXME: replace them by a table lookup and macros */ -int -ascii_isupper (int c) -{ - return c >= 'A' && c <= 'Z'; -} - -int -ascii_islower (int c) -{ - return c >= 'a' && c <= 'z'; -} - -int -ascii_toupper (int c) -{ - if (c >= 'a' && c <= 'z') - c &= ~0x20; - return c; -} - -int -ascii_tolower (int c) -{ - if (c >= 'A' && c <= 'Z') - c |= 0x20; - return c; -} - - -int -ascii_strcasecmp (const char *a, const char *b) -{ - const unsigned char *p1 = (const unsigned char *)a; - const unsigned char *p2 = (const unsigned char *)b; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - c1 = ascii_tolower (*p1); - c2 = ascii_tolower (*p2); - - if (c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - return c1 - c2; -} - -int -ascii_strncasecmp (const char *a, const char *b, size_t n) -{ - const unsigned char *p1 = (const unsigned char *)a; - const unsigned char *p2 = (const unsigned char *)b; - unsigned char c1, c2; - - if (p1 == p2 || !n ) - return 0; - - do - { - c1 = ascii_tolower (*p1); - c2 = ascii_tolower (*p2); - - if ( !--n || c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - return c1 - c2; -} - - -int -ascii_memcasecmp( const char *a, const char *b, size_t n ) -{ - if (a == b) - return 0; - for ( ; n; n--, a++, b++ ) { - if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) ) - return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); - } - return 0; -} - - - -/********************************************* - ********** missing string functions ********* - *********************************************/ - -#ifndef HAVE_STPCPY -char * -stpcpy(char *a,const char *b) -{ - while( *b ) - *a++ = *b++; - *a = 0; - - return (char*)a; -} -#endif - - -#ifndef HAVE_STRSEP -/* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */ -char * -strsep (char **stringp, const char *delim) -{ - char *begin, *end; - - begin = *stringp; - if (begin == NULL) - return NULL; - - /* A frequent case is when the delimiter string contains only one - character. Here we don't need to call the expensive `strpbrk' - function and instead work using `strchr'. */ - if (delim[0] == '\0' || delim[1] == '\0') - { - char ch = delim[0]; - - if (ch == '\0') - end = NULL; - else - { - if (*begin == ch) - end = begin; - else if (*begin == '\0') - end = NULL; - else - end = strchr (begin + 1, ch); - } - } - else - /* Find the end of the token. */ - end = strpbrk (begin, delim); - - if (end) - { - /* Terminate the token and set *STRINGP past NUL character. */ - *end++ = '\0'; - *stringp = end; - } - else - /* No more delimiters; this is the last token. */ - *stringp = NULL; - - return begin; -} -#endif /*HAVE_STRSEP*/ - - -#ifndef HAVE_STRLWR -char * -strlwr(char *s) -{ - char *p; - for(p=s; *p; p++ ) - *p = tolower(*p); - return s; -} -#endif - -#ifndef HAVE_STRCASECMP -int -strcasecmp( const char *a, const char *b ) -{ - for( ; *a && *b; a++, b++ ) { - if( *a != *b && toupper(*a) != toupper(*b) ) - break; - } - return *(const byte*)a - *(const byte*)b; -} -#endif - -#ifndef HAVE_STRNCASECMP -int -strncasecmp( const char *a, const char *b, size_t n ) -{ - for( ; n && *a && *b; a++, b++, n--) { - if( *a != *b && toupper(*a) != toupper(*b) ) - break; - } - if (!n) - return 0; - return *(const byte*)a - *(const byte*)b; -} -#endif - - -#ifdef __MINGW32__ -/* - * Like vsprintf but provides a pointer to malloc'd storage, which - * must be freed by the caller (m_free). Taken from libiberty as - * found in gcc-2.95.2 and a little bit modernized. - * FIXME: Write a new CRT for W32. - */ -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; - - /* this is not really portable but works under Windows */ - memcpy ( &ap, &args, sizeof (va_list)); - - while (*p != '\0') - { - if (*p++ == '%') - { - while (strchr ("-+ #0", *p)) - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - { - char *endp; - total_width += strtoul (p, &endp, 10); - p = endp; - } - if (*p == '.') - { - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - { - char *endp; - total_width += strtoul (p, &endp, 10); - p = endp; - } - } - 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; - - case 's': - total_width += strlen (va_arg (ap, char *)); - break; - case 'p': - case 'n': - (void) va_arg (ap, char *); - break; - } - } - } - *result = m_alloc (total_width); - if (*result != NULL) - return vsprintf (*result, format, args); - else - return 0; -} - -#endif /*__MINGW32__*/ - diff --git a/util/ttyio.c b/util/ttyio.c deleted file mode 100644 index 40fe7eb52..000000000 --- a/util/ttyio.c +++ /dev/null @@ -1,481 +0,0 @@ -/* ttyio.c - tty i/O 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 -#include -#include -#include -#include -#include -#ifdef HAVE_TCGETATTR - #include -#else - #ifdef HAVE_TERMIO_H - /* simulate termios with termio */ - #include - #define termios termio - #define tcsetattr ioctl - #define TCSAFLUSH TCSETAF - #define tcgetattr(A,B) ioctl(A,TCGETA,B) - #define HAVE_TCGETATTR - #endif -#endif -#ifdef __MINGW32__ /* use the odd Win32 functions */ - #include - #ifdef HAVE_TCGETATTR - #error mingw32 and termios - #endif -#endif -#include -#include -#include "util.h" -#include "memory.h" -#include "ttyio.h" - -#define CONTROL_D ('D' - 'A' + 1) -#ifdef __VMS - #define TERMDEVICE "/dev/tty" -#else - #define TERMDEVICE "/dev/tty" -#endif - -#ifdef __MINGW32__ /* 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 - - -#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(__MINGW32__) - { - 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(TERMDEVICE, "r+"); - if( !ttyfp ) { - log_error("cannot open /dev/tty: %s\n", 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 __MINGW32__ - { - 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; - m_free (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( byte *p, size_t n ) -{ - if (no_terminal) - return; - - if( !initialized ) - init_ttyfp(); - - #ifdef __MINGW32__ - /* 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( 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( strlen( buf ) > max_n ) { - buf[max_n] = 0; - } - /*(utf8 conversion already does the control character quoting)*/ - tty_printf("%s", buf ); - m_free( buf ); - } - else { - if( n > max_n ) { - n = max_n; - } - tty_print_string( p, n ); - } -} - -void -tty_print_utf8_string( byte *p, size_t n ) -{ - tty_print_utf8_string2( p, n, n ); -} - - -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 = m_alloc(n=50); - i = 0; - - #ifdef __MINGW32__ /* 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 = m_realloc( 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 = m_realloc(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 = m_realloc( 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 __MINGW32__ - 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); - m_free(p); - return yes; -} - diff --git a/util/w32reg.c b/util/w32reg.c deleted file mode 100644 index 5391c8027..000000000 --- a/util/w32reg.c +++ /dev/null @@ -1,171 +0,0 @@ -/* w32reg.c - MS-Windows Registry access - * Copyright (C) 1999, 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 -#if defined (__MINGW32__) || defined (__CYGWIN32__) - /* This module is only used in this environment */ - -#include -#include -#include -#include -#include -#include "util.h" -#include "memory.h" - -static HKEY -get_root_key(const char *root) -{ - HKEY root_key; - - if( !root ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) - root_key = HKEY_CLASSES_ROOT; - else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) - root_key = HKEY_CURRENT_USER; - else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) - root_key = HKEY_LOCAL_MACHINE; - else if( !strcmp( root, "HKEY_USERS" ) ) - root_key = HKEY_USERS; - else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) - root_key = HKEY_PERFORMANCE_DATA; - else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) - root_key = HKEY_CURRENT_CONFIG; - else - return NULL; - - return root_key; -} - - -/**************** - * Return a string from the Win32 Registry or NULL in case of - * error. Caller must release the return value. A NULL for root - * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. - * NOTE: The value is allocated with a plain malloc() - use free() and not - * the usual m_free()!!! - */ -char * -read_w32_registry_string( const char *root, const char *dir, const char *name ) -{ - HKEY root_key, key_handle; - DWORD n1, nbytes, type; - char *result = NULL; - - if ( !(root_key = get_root_key(root) ) ) - return NULL; - - if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) - { - if (root) - return NULL; /* no need for a RegClose, so return direct */ - /* It seems to be common practise to fall back to HLM. */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) - return NULL; /* still no need for a RegClose, so return direct */ - } - - nbytes = 1; - if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) - goto leave; - result = malloc( (n1=nbytes+1) ); - if( !result ) - goto leave; - if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) { - free(result); result = NULL; - goto leave; - } - result[nbytes] = 0; /* make sure it is really a string */ - if (type == REG_EXPAND_SZ && strchr (result, '%')) { - char *tmp; - - n1 += 1000; - tmp = malloc (n1+1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) { - free (tmp); - tmp = malloc (n1 + 1); - if (!tmp) - goto leave; - nbytes = ExpandEnvironmentStrings (result, tmp, n1); - if (nbytes && nbytes > n1) { - free (tmp); /* oops - truncated, better don't expand at all */ - goto leave; - } - tmp[nbytes] = 0; - free (result); - result = tmp; - } - else if (nbytes) { /* okay, reduce the length */ - tmp[nbytes] = 0; - free (result); - result = malloc (strlen (tmp)+1); - if (!result) - result = tmp; - else { - strcpy (result, tmp); - free (tmp); - } - } - else { /* error - don't expand */ - free (tmp); - } - } - - leave: - RegCloseKey( key_handle ); - return result; -} - - -int -write_w32_registry_string(const char *root, const char *dir, - const char *name, const char *value) -{ - HKEY root_key, reg_key; - - if ( !(root_key = get_root_key(root) ) ) - return -1; - - if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, ®_key ) - != ERROR_SUCCESS ) - return -1; - - if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, - strlen( value ) ) != ERROR_SUCCESS ) { - if ( RegCreateKey( root_key, name, ®_key ) != ERROR_SUCCESS ) { - RegCloseKey(reg_key); - return -1; - } - if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, - strlen( value ) ) != ERROR_SUCCESS ) { - RegCloseKey(reg_key); - return -1; - } - } - - RegCloseKey( reg_key ); - - return 0; -} - -#endif /* __MINGW32__ || __CYGWIN32__ */ diff --git a/zlib/ChangeLog b/zlib/ChangeLog deleted file mode 100644 index 5f06bcc7b..000000000 --- a/zlib/ChangeLog +++ /dev/null @@ -1,505 +0,0 @@ -2002-03-12 Werner Koch - - Merged changes from zlib 1.1.4. - -Sat Feb 13 12:04:43 CET 1999 Werner Koch - - * Makefile.am: Removed -Wall - -Wed Jan 20 21:40:21 CET 1999 Werner Koch - - * Makefile.am: Corrected the list of sources - -Wed Jan 13 14:10:15 CET 1999 Werner Koch - - Merged version 1.1.3 with the previousy used 1.0.4 - -Thu Feb 12 12:20:45 1998 Werner Koch (wk@frodo) - - Removed a couple of files, as this is only used if zlib is - missing on a system. Added automake stuff - - - ChangeLog file for zlib - - -Changes in 1.1.4 (11 March 2002) -- ZFREE was repeated on same allocation on some error conditions. - This creates a security problem described in - http://www.zlib.org/advisory-2002-03-11.txt -- Returned incorrect error (Z_MEM_ERROR) on some invalid data -- Avoid accesses before window for invalid distances with inflate window - less than 32K. -- force windowBits > 8 to avoid a bug in the encoder for a window size - of 256 bytes. (A complete fix will be available in 1.1.5). - -Changes in 1.1.3 (9 July 1998) -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -- Support gzdopen on Mac with Metrowerks (Jason Linhart) -- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) -- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) -- avoid some warnings with Borland C (Tom Tanner) -- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) -- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) -- allow several arguments to configure (Tim Mooney, Frodo Looijaard) -- use libdir and includedir in Makefile.in (Tim Mooney) -- support shared libraries on OSF1 V4 (Tim Mooney) -- remove so_locations in "make clean" (Tim Mooney) -- fix maketree.c compilation error (Glenn, Mark) -- Python interface to zlib now in Python 1.5 (Jeremy Hylton) -- new Makefile.riscos (Rich Walker) -- initialize static descriptors in trees.c for embedded targets (Nick Smith) -- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) -- add the OS/2 files in Makefile.in too (Andrew Zabolotny) -- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) -- fix maketree.c to allow clean compilation of inffixed.h (Mark) -- fix parameter check in deflateCopy (Gunther Nikl) -- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) -- Many portability patches by Christian Spieler: - . zutil.c, zutil.h: added "const" for zmem* - . Make_vms.com: fixed some typos - . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists - . msdos/Makefile.msc: remove "default rtl link library" info from obj files - . msdos/Makefile.*: use model-dependent name for the built zlib library - . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: - new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) -- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) -- replace __far with _far for better portability (Christian Spieler, Tom Lane) -- fix test for errno.h in configure (Tim Newsham) - -Changes in 1.1.2 (19 March 98) -- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) - See http://www.winimage.com/zLibDll/unzip.html -- preinitialize the inflate tables for fixed codes, to make the code - completely thread safe (Mark) -- some simplifications and slight speed-up to the inflate code (Mark) -- fix gzeof on non-compressed files (Allan Schrum) -- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) -- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) -- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) -- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) -- do not wrap extern "C" around system includes (Tom Lane) -- mention zlib binding for TCL in README (Andreas Kupries) -- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) -- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) -- allow "configure --prefix $HOME" (Tim Mooney) -- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) -- move Makefile.sas to amiga/Makefile.sas - -Changes in 1.1.1 (27 Feb 98) -- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) -- remove block truncation heuristic which had very marginal effect for zlib - (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the - compression ratio on some files. This also allows inlining _tr_tally for - matches in deflate_slow. -- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - -Changes in 1.1.0 (24 Feb 98) -- do not return STREAM_END prematurely in inflate (John Bowler) -- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) -- compile with -DFASTEST to get compression code optimized for speed only -- in minigzip, try mmap'ing the input file first (Miguel Albrecht) -- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain - on Sun but significant on HP) - -- add a pointer to experimental unzip library in README (Gilles Vollant) -- initialize variable gcc in configure (Chris Herborth) - -Changes in 1.0.9 (17 Feb 1998) -- added gzputs and gzgets functions -- do not clear eof flag in gzseek (Mark Diekhans) -- fix gzseek for files in transparent mode (Mark Diekhans) -- do not assume that vsprintf returns the number of bytes written (Jens Krinke) -- replace EXPORT with ZEXPORT to avoid conflict with other programs -- added compress2 in zconf.h, zlib.def, zlib.dnt -- new asm code from Gilles Vollant in contrib/asm386 -- simplify the inflate code (Mark): - . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() - . ZALLOC the length list in inflate_trees_fixed() instead of using stack - . ZALLOC the value area for huft_build() instead of using stack - . Simplify Z_FINISH check in inflate() - -- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 -- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) -- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - the declaration of FAR (Gilles VOllant) -- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) -- read_buf buf parameter of type Bytef* instead of charf* -- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) -- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) -- fix check for presence of directories in "make install" (Ian Willis) - -Changes in 1.0.8 (27 Jan 1998) -- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) -- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) -- added compress2() to allow setting the compression level -- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) -- use constant arrays for the static trees in trees.c instead of computing - them at run time (thanks to Ken Raeburn for this suggestion). To create - trees.h, compile with GEN_TREES_H and run "make test". -- check return code of example in "make test" and display result -- pass minigzip command line options to file_compress -- simplifying code of inflateSync to avoid gcc 2.8 bug - -- support CC="gcc -Wall" in configure -s (QingLong) -- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) -- fix test for shared library support to avoid compiler warnings -- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) -- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) -- do not use fdopen for Metrowerks on Mac (Brad Pettit)) -- add checks for gzputc and gzputc in example.c -- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) -- use const for the CRC table (Ken Raeburn) -- fixed "make uninstall" for shared libraries -- use Tracev instead of Trace in infblock.c -- in example.c use correct compressed length for test_sync -- suppress +vnocompatwarnings in configure for HPUX (not always supported) - -Changes in 1.0.7 (20 Jan 1998) -- fix gzseek which was broken in write mode -- return error for gzseek to negative absolute position -- fix configure for Linux (Chun-Chung Chen) -- increase stack space for MSC (Tim Wegner) -- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) -- define EXPORTVA for gzprintf (Gilles Vollant) -- added man page zlib.3 (Rick Rodgers) -- for contrib/untgz, fix makedir() and improve Makefile - -- check gzseek in write mode in example.c -- allocate extra buffer for seeks only if gzseek is actually called -- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) -- add inflateSyncPoint in zconf.h -- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def - -Changes in 1.0.6 (19 Jan 1998) -- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occuring only with compression level 0 (thanks to - Andy Buckler for finding this one). -- In minigzip, pass transparently also the first byte for .Z files. -- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() -- check Z_FINISH in inflate (thanks to Marc Schluper) -- Implement deflateCopy (thanks to Adam Costello) -- make static libraries by default in configure, add --shared option. -- move MSDOS or Windows specific files to directory msdos -- suppress the notion of partial flush to simplify the interface - (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) -- suppress history buffer provided by application to simplify the interface - (this feature was not implemented anyway in 1.0.4) -- next_in and avail_in must be initialized before calling inflateInit or - inflateInit2 -- add EXPORT in all exported functions (for Windows DLL) -- added Makefile.nt (thanks to Stephen Williams) -- added the unsupported "contrib" directory: - contrib/asm386/ by Gilles Vollant - 386 asm code replacing longest_match(). - contrib/iostream/ by Kevin Ruland - A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Lvset - Another C++ I/O streams interface - contrib/untgz/ by "Pedro A. Aranda Guti\irrez" - A very simple tar.gz file extractor using zlib - contrib/visual-basic.txt by Carlos Rios - How to use compress(), uncompress() and the gz* functions from VB. -- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - level) in minigzip (thanks to Tom Lane) - -- use const for rommable constants in deflate -- added test for gzseek and gztell in example.c -- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) -- add undocumented function zError to convert error code to string - (for Tim Smithers) -- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. -- Use default memcpy for Symantec MSDOS compiler. -- Add EXPORT keyword for check_func (needed for Windows DLL) -- add current directory to LD_LIBRARY_PATH for "make test" -- create also a link for libz.so.1 -- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) -- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) -- added -soname for Linux in configure (Chun-Chung Chen, -- assign numbers to the exported functions in zlib.def (for Windows DLL) -- add advice in zlib.h for best usage of deflateSetDictionary -- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) -- allow compilation with ANSI keywords only enabled for TurboC in large model -- avoid "versionString"[0] (Borland bug) -- add NEED_DUMMY_RETURN for Borland -- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). -- allow compilation with CC -- defined STDC for OS/2 (David Charlap) -- limit external names to 8 chars for MVS (Thomas Lund) -- in minigzip.c, use static buffers only for 16-bit systems -- fix suffix check for "minigzip -d foo.gz" -- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) -- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) -- added makelcc.bat for lcc-win32 (Tom St Denis) -- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) -- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. -- check for unistd.h in configure (for off_t) -- remove useless check parameter in inflate_blocks_free -- avoid useless assignment of s->check to itself in inflate_blocks_new -- do not flush twice in gzclose (thanks to Ken Raeburn) -- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h -- use NO_ERRNO_H instead of enumeration of operating systems with errno.h -- work around buggy fclose on pipes for HP/UX -- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) -- fix configure if CC is already equal to gcc - -Changes in 1.0.5 (3 Jan 98) -- Fix inflate to terminate gracefully when fed corrupted or invalid data -- Use const for rommable constants in inflate -- Eliminate memory leaks on error conditions in inflate -- Removed some vestigial code in inflate -- Update web address in README - -Changes in 1.0.4 (24 Jul 96) -- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - bit, so the decompressor could decompress all the correct data but went - on to attempt decompressing extra garbage data. This affected minigzip too. -- zlibVersion and gzerror return const char* (needed for DLL) -- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) -- use z_error only for DEBUG (avoid problem with DLLs) - -Changes in 1.0.3 (2 Jul 96) -- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS - small and medium models; this makes the library incompatible with previous - versions for these models. (No effect in large model or on other systems.) -- return OK instead of BUF_ERROR if previous deflate call returned with - avail_out as zero but there is nothing to do -- added memcmp for non STDC compilers -- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) -- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) -- better check for 16-bit mode MSC (avoids problem with Symantec) - -Changes in 1.0.2 (23 May 96) -- added Windows DLL support -- added a function zlibVersion (for the DLL support) -- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) -- Bytef is define's instead of typedef'd only for Borland C -- avoid reading uninitialized memory in example.c -- mention in README that the zlib format is now RFC1950 -- updated Makefile.dj2 -- added algorithm.doc - -Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] -- fix array overlay in deflate.c which sometimes caused bad compressed data -- fix inflate bug with empty stored block -- fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generated bad compressed data. -- Bytef is define'd instead of typedef'ed (work around Borland bug) -- added an INDEX file -- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) -- speed up adler32 for modern machines without auto-increment -- added -ansi for IRIX in configure -- static_init_done in trees.c is an int -- define unlink as delete for VMS -- fix configure for QNX -- add configure branch for SCO and HPUX -- avoid many warnings (unused variables, dead assignments, etc...) -- no fdopen for BeOS -- fix the Watcom fix for 32 bit mode (define FAR as empty) -- removed redefinition of Byte for MKWERKS -- work around an MWKERKS bug (incorrect merge of all .h files) - -Changes in 0.99 (27 Jan 96) -- allow preset dictionary shared between compressor and decompressor -- allow compression level 0 (no compression) -- add deflateParams in zlib.h: allow dynamic change of compression level - and compression strategy. -- test large buffers and deflateParams in example.c -- add optional "configure" to build zlib as a shared library -- suppress Makefile.qnx, use configure instead -- fixed deflate for 64-bit systems (detected on Cray) -- fixed inflate_blocks for 64-bit systems (detected on Alpha) -- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) -- always return Z_BUF_ERROR when deflate() has nothing to do -- deflateInit and inflateInit are now macros to allow version checking -- prefix all global functions and types with z_ with -DZ_PREFIX -- make falloc completely reentrant (inftrees.c) -- fixed very unlikely race condition in ct_static_init -- free in reverse order of allocation to help memory manager -- use zlib-1.0/* instead of zlib/* inside the tar.gz -- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith - -Wconversion -Wstrict-prototypes -Wmissing-prototypes" -- allow gzread on concatenated .gz files -- deflateEnd now returns Z_DATA_ERROR if it was premature -- deflate is finally (?) fully deterministic (no matches beyond end of input) -- Document Z_SYNC_FLUSH -- add uninstall in Makefile -- Check for __cpluplus in zlib.h -- Better test in ct_align for partial flush -- avoid harmless warnings for Borland C++ -- initialize hash_head in deflate.c -- avoid warning on fdopen (gzio.c) for HP cc -Aa -- include stdlib.h for STDC compilers -- include errno.h for Cray -- ignore error if ranlib doesn't exist -- call ranlib twice for NeXTSTEP -- use exec_prefix instead of prefix for libz.a -- renamed ct_* as _tr_* to avoid conflict with applications -- clear z->msg in inflateInit2 before any error return -- initialize opaque in example.c, gzio.c, deflate.c and inflate.c -- fixed typo in zconf.h (_GNUC__ => __GNUC__) -- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) -- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) -- in fcalloc, normalize pointer if size > 65520 bytes -- don't use special fcalloc for 32 bit Borland C++ -- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... -- use Z_BINARY instead of BINARY -- document that gzclose after gzdopen will close the file -- allow "a" as mode in gzopen. -- fix error checking in gzread -- allow skipping .gz extra-field on pipes -- added reference to Perl interface in README -- put the crc table in FAR data (I dislike more and more the medium model :) -- added get_crc_table -- added a dimension to all arrays (Borland C can't count). -- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast -- guard against multiple inclusion of *.h (for precompiled header on Mac) -- Watcom C pretends to be Microsoft C small model even in 32 bit mode. -- don't use unsized arrays to avoid silly warnings by Visual C++: - warning C4746: 'inflate_mask' : unsized array treated as '__far' - (what's wrong with far data in far model?). -- define enum out of inflate_blocks_state to allow compilation with C++ - -Changes in 0.95 (16 Aug 95) -- fix MSDOS small and medium model (now easier to adapt to any compiler) -- inlined send_bits -- fix the final (:-) bug for deflate with flush (output was correct but - not completely flushed in rare occasions). -- default window size is same for compression and decompression - (it's now sufficient to set MAX_WBITS in zconf.h). -- voidp -> voidpf and voidnp -> voidp (for consistency with other - typedefs and because voidnp was not near in large model). - -Changes in 0.94 (13 Aug 95) -- support MSDOS medium model -- fix deflate with flush (could sometimes generate bad output) -- fix deflateReset (zlib header was incorrectly suppressed) -- added support for VMS -- allow a compression level in gzopen() -- gzflush now calls fflush -- For deflate with flush, flush even if no more input is provided. -- rename libgz.a as libz.a -- avoid complex expression in infcodes.c triggering Turbo C bug -- work around a problem with gcc on Alpha (in INSERT_STRING) -- don't use inline functions (problem with some gcc versions) -- allow renaming of Byte, uInt, etc... with #define. -- avoid warning about (unused) pointer before start of array in deflate.c -- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c -- avoid reserved word 'new' in trees.c - -Changes in 0.93 (25 June 95) -- temporarily disable inline functions -- make deflate deterministic -- give enough lookahead for PARTIAL_FLUSH -- Set binary mode for stdin/stdout in minigzip.c for OS/2 -- don't even use signed char in inflate (not portable enough) -- fix inflate memory leak for segmented architectures - -Changes in 0.92 (3 May 95) -- don't assume that char is signed (problem on SGI) -- Clear bit buffer when starting a stored block -- no memcpy on Pyramid -- suppressed inftest.c -- optimized fill_window, put longest_match inline for gcc -- optimized inflate on stored blocks. -- untabify all sources to simplify patches - -Changes in 0.91 (2 May 95) -- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h -- Document the memory requirements in zconf.h -- added "make install" -- fix sync search logic in inflateSync -- deflate(Z_FULL_FLUSH) now works even if output buffer too short -- after inflateSync, don't scare people with just "lo world" -- added support for DJGPP - -Changes in 0.9 (1 May 95) -- don't assume that zalloc clears the allocated memory (the TurboC bug - was Mark's bug after all :) -- let again gzread copy uncompressed data unchanged (was working in 0.71) -- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented -- added a test of inflateSync in example.c -- moved MAX_WBITS to zconf.h because users might want to change that. -- document explicitly that zalloc(64K) on MSDOS must return a normalized - pointer (zero offset) -- added Makefiles for Microsoft C, Turbo C, Borland C++ -- faster crc32() - -Changes in 0.8 (29 April 95) -- added fast inflate (inffast.c) -- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - is incompatible with previous versions of zlib which returned Z_OK. -- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - (actually that was not a compiler bug, see 0.81 above) -- gzread no longer reads one extra byte in certain cases -- In gzio destroy(), don't reference a freed structure -- avoid many warnings for MSDOS -- avoid the ERROR symbol which is used by MS Windows - -Changes in 0.71 (14 April 95) -- Fixed more MSDOS compilation problems :( There is still a bug with - TurboC large model. - -Changes in 0.7 (14 April 95) -- Added full inflate support. -- Simplified the crc32() interface. The pre- and post-conditioning - (one's complement) is now done inside crc32(). WARNING: this is - incompatible with previous versions; see zlib.h for the new usage. - -Changes in 0.61 (12 April 95) -- workaround for a bug in TurboC. example and minigzip now work on MSDOS. - -Changes in 0.6 (11 April 95) -- added minigzip.c -- added gzdopen to reopen a file descriptor as gzFile -- added transparent reading of non-gziped files in gzread. -- fixed bug in gzread (don't read crc as data) -- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). -- don't allocate big arrays in the stack (for MSDOS) -- fix some MSDOS compilation problems - -Changes in 0.5: -- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - not yet Z_FULL_FLUSH. -- support decompression but only in a single step (forced Z_FINISH) -- added opaque object for zalloc and zfree. -- added deflateReset and inflateReset -- added a variable zlib_version for consistency checking. -- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - Added Z_FILTERED and Z_HUFFMAN_ONLY constants. - -Changes in 0.4: -- avoid "zip" everywhere, use zlib instead of ziplib. -- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - if compression method == 8. -- added adler32 and crc32 -- renamed deflateOptions as deflateInit2, call one or the other but not both -- added the method parameter for deflateInit2. -- added inflateInit2 -- simplied considerably deflateInit and inflateInit by not supporting - user-provided history buffer. This is supported only in deflateInit2 - and inflateInit2. - -Changes in 0.3: -- prefix all macro names with Z_ -- use Z_FINISH instead of deflateEnd to finish compression. -- added Z_HUFFMAN_ONLY -- added gzerror() - - diff --git a/zlib/Makefile.am b/zlib/Makefile.am deleted file mode 100644 index 2c1e9cda4..000000000 --- a/zlib/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -# Process this file with automake to produce Makefile.in -# Copyright (C) 1995-1996 Jean-loup Gailly. -# For conditions of distribution and use, see copyright notice in zlib.h -# This is used if a systems lacks support of zlib - -EXTRA_DIST = README algorithm.doc ChangeLog - -# I found no other easy way to use this only if zlib is neede -# doing this with SUBDIR = @xxx@ in the top Makefile.am does not -# work because automake doesn't scan this Makefile.am here. -if ENABLE_LOCAL_ZLIB -noinst_LIBRARIES = libzlib.a -endif - - -libzlib_a_SOURCES = adler32.c compress.c crc32.c \ - uncompr.c deflate.c trees.c zutil.c \ - inflate.c infblock.c inftrees.c \ - infcodes.c infutil.c inffast.c \ - deflate.h infblock.h infcodes.h inffast.h \ - inffixed.h inftrees.h infutil.h trees.h \ - zconf.h zlib.h zutil.h - - -CLEANFILES = foo.gz - - - diff --git a/zlib/README b/zlib/README deleted file mode 100644 index 8ff458799..000000000 --- a/zlib/README +++ /dev/null @@ -1,148 +0,0 @@ -zlib 1.1.3 is a general purpose data compression library. All the code -is thread safe. The data format used by the zlib library -is described by RFCs (Request for Comments) 1950 to 1952 in the files -ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate -format) and rfc1952.txt (gzip format). These documents are also available in -other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact jloup@gzip.org). A usage -example of the library is given in the file example.c which also tests that -the library is working correctly. Another example is given in the file -minigzip.c. The compression library itself is composed of all source files -except example.c and minigzip.c. - -To compile all files and run the test program, follow the instructions -given at the top of Makefile. In short "make test; make install" -should work for most machines. For Unix: "configure; make test; make install" -For MSDOS, use one of the special makefiles such as Makefile.msc. -For VMS, use Make_vms.com or descrip.mms. - -Questions about zlib should be sent to , or to -Gilles Vollant for the Windows DLL version. -The zlib home page is http://www.cdrom.com/pub/infozip/zlib/ -The official zlib ftp site is ftp://ftp.cdrom.com/pub/infozip/zlib/ -Before reporting a problem, please check those sites to verify that -you have the latest version of zlib; otherwise get the latest version and -check whether the problem still exists or not. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available in -http://web2.airmail.net/markn/articles/zlibtool/zlibtool.htm - -The changes made in version 1.1.3 are documented in the file ChangeLog. -The main changes since 1.1.2 are: - -- fix "an inflate input buffer bug that shows up on rare but persistent - occasions" (Mark) -- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) -- fix gzseek(..., SEEK_SET) in write mode -- fix crc check after a gzeek (Frank Faubert) -- fix miniunzip when the last entry in a zip file is itself a zip file - (J Lillge) -- add contrib/asm586 and contrib/asm686 (Brian Raiter) - See http://www.muppetlabs.com/~breadbox/software/assembly.html -- add support for Delphi 3 in contrib/delphi (Bob Dellaca) -- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) -- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) -- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) -- added a FAQ file - -plus many changes for portability. - -Unsupported third party contributions are provided in directory "contrib". - -A Java implementation of zlib is available in the Java Development Kit 1.1 -http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html -See the zlib home page http://www.cdrom.com/pub/infozip/zlib/ for details. - -A Perl interface to zlib written by Paul Marquess -is in the CPAN (Comprehensive Perl Archive Network) sites, such as: -ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib* - -A Python interface to zlib written by A.M. Kuchling -is available in Python 1.5 and later versions, see -http://www.python.org/doc/lib/module-zlib.html - -A zlib binding for TCL written by Andreas Kupries -is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html - -An experimental package to read and write files in .zip format, -written on top of zlib by Gilles Vollant , is -available at http://www.winimage.com/zLibDll/unzip.html -and also in the contrib/minizip directory of zlib. - - -Notes for some targets: - -- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc - and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL - The zlib DLL support was initially done by Alessandro Iacopetti and is - now maintained by Gilles Vollant . Check the zlib DLL - home page at http://www.winimage.com/zLibDll - - From Visual Basic, you can call the DLL functions which do not take - a structure as argument: compress, uncompress and all gz* functions. - See contrib/visual-basic.txt for more information, or get - http://www.tcfb.com/dowseware/cmp-z-it.zip - -- For 64-bit Irix, deflate.c must be compiled without any optimization. - With -O, one libpng test fails. The test works in 32 bit mode (with - the -n32 compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 - it works when compiled with cc. - -- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 - is necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works - with other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. - -- For Turbo C the small model is supported only with reduced performance to - avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 - -- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html - Per Harald Myrvang - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate - and zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; - they are too numerous to cite here. - -Copyright notice: - - (C) 1995-1998 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* -receiving lengthy legal documents to sign. The sources are provided -for free but without warranty of any kind. The library has been -entirely written by Jean-loup Gailly and Mark Adler; it does not -include third-party code. - -If you redistribute modified sources, we would appreciate that you include -in the file ChangeLog history information documenting your changes. diff --git a/zlib/adler32.c b/zlib/adler32.c deleted file mode 100644 index fae88b655..000000000 --- a/zlib/adler32.c +++ /dev/null @@ -1,48 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zlib.h" - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - buf += 16; - k -= 16; - } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} diff --git a/zlib/algorithm.doc b/zlib/algorithm.doc deleted file mode 100644 index 01902aff6..000000000 --- a/zlib/algorithm.doc +++ /dev/null @@ -1,105 +0,0 @@ -1. Compression algorithm (deflate) - -The deflation algorithm used by zlib (also zip and gzip) is a variation of -LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in -the input data. The second occurrence of a string is replaced by a -pointer to the previous string, in the form of a pair (distance, -length). Distances are limited to 32K bytes, and lengths are limited -to 258 bytes. When a string does not occur anywhere in the previous -32K bytes, it is emitted as a sequence of literal bytes. (In this -description, `string' must be taken as an arbitrary sequence of bytes, -and is not restricted to printable characters.) - -Literals or match lengths are compressed with one Huffman tree, and -match distances are compressed with another tree. The trees are stored -in a compact form at the start of each block. The blocks can have any -size (except that the compressed data for one block must fit in -available memory). A block is terminated when deflate() determines that -it would be useful to start another block with fresh trees. (This is -somewhat similar to the behavior of LZW-based _compress_.) - -Duplicated strings are found using a hash table. All input strings of -length 3 are inserted in the hash table. A hash index is computed for -the next 3 bytes. If the hash chain for this index is not empty, all -strings in the chain are compared with the current input string, and -the longest match is selected. - -The hash chains are searched starting with the most recent strings, to -favor small distances and thus take advantage of the Huffman encoding. -The hash chains are singly linked. There are no deletions from the -hash chains, the algorithm simply discards matches that are too old. - -To avoid a worst-case situation, very long hash chains are arbitrarily -truncated at a certain length, determined by a runtime option (level -parameter of deflateInit). So deflate() does not always find the longest -possible match but generally finds a match which is long enough. - -deflate() also defers the selection of matches with a lazy evaluation -mechanism. After a match of length N has been found, deflate() searches for a -longer match at the next input byte. If a longer match is found, the -previous match is truncated to a length of one (thus producing a single -literal byte) and the longer match is emitted afterwards. Otherwise, -the original match is kept, and the next match search is attempted only -N steps later. - -The lazy match evaluation is also subject to a runtime parameter. If -the current match is long enough, deflate() reduces the search for a longer -match, thus speeding up the whole process. If compression ratio is more -important than speed, deflate() attempts a complete second search even if -the first match is already long enough. - -The lazy match evaluation is not performed for the fastest compression -modes (level parameter 1 to 3). For these fast modes, new strings -are inserted in the hash table only when no match was found, or -when the match is not too long. This degrades the compression ratio -but saves time since there are both fewer insertions and fewer searches. - - -2. Decompression algorithm (inflate) - -The real question is, given a Huffman tree, how to decode fast. The most -important realization is that shorter codes are much more common than -longer codes, so pay attention to decoding the short codes fast, and let -the long codes take longer to decode. - -inflate() sets up a first level table that covers some number of bits of -input less than the length of longest code. It gets that many bits from the -stream, and looks it up in the table. The table will tell if the next -code is that many bits or less and how many, and if it is, it will tell -the value, else it will point to the next level table for which inflate() -grabs more bits and tries to decode a longer code. - -How many bits to make the first lookup is a tradeoff between the time it -takes to decode and the time it takes to build the table. If building the -table took no time (and if you had infinite memory), then there would only -be a first level table to cover all the way to the longest code. However, -building the table ends up taking a lot longer for more bits since short -codes are replicated many times in such a table. What inflate() does is -simply to make the number of bits in the first table a variable, and set it -for the maximum speed. - -inflate() sends new trees relatively often, so it is possibly set for a -smaller first level table than an application that has only one tree for -all the data. For inflate, which has 286 possible codes for the -literal/length tree, the size of the first table is nine bits. Also the -distance trees have 30 possible values, and the size of the first table is -six bits. Note that for each of those cases, the table ended up one bit -longer than the ``average'' code length, i.e. the code length of an -approximately flat code which would be a little more than eight bits for -286 symbols and a little less than five bits for 30 symbols. It would be -interesting to see if optimizing the first level table for other -applications gave values within a bit or two of the flat code size. - - -Jean-loup Gailly Mark Adler -gzip@prep.ai.mit.edu madler@alumni.caltech.edu - - -References: - -[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data -Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, -pp. 337-343. - -``DEFLATE Compressed Data Format Specification'' available in -ftp://ds.internic.net/rfc/rfc1951.txt diff --git a/zlib/compress.c b/zlib/compress.c deleted file mode 100644 index 814bd9d60..000000000 --- a/zlib/compress.c +++ /dev/null @@ -1,68 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zlib.h" - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =========================================================================== - */ -int ZEXPORT compress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} diff --git a/zlib/crc32.c b/zlib/crc32.c deleted file mode 100644 index 60deca2dd..000000000 --- a/zlib/crc32.c +++ /dev/null @@ -1,162 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zlib.h" - -#define local static - -#ifdef DYNAMIC_CRC_TABLE - -local int crc_table_empty = 1; -local uLongf crc_table[256]; -local void make_crc_table OF((void)); - -/* - Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all - the information needed to generate CRC's on data a byte at a time for all - combinations of CRC register values and incoming bytes. -*/ -local void make_crc_table() -{ - uLong c; - int n, k; - uLong poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* make exclusive-or pattern from polynomial (0xedb88320L) */ - poly = 0L; - for (n = 0; n < sizeof(p)/sizeof(Byte); n++) - poly |= 1L << (31 - p[n]); - - for (n = 0; n < 256; n++) - { - c = (uLong)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[n] = c; - } - crc_table_empty = 0; -} -#else -/* ======================================================================== - * Table of CRC-32's of all single-byte values (made by make_crc_table) - */ -local const uLongf crc_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; -#endif - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const uLongf * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) make_crc_table(); -#endif - return (const uLongf *)crc_table; -} - -/* ========================================================================= */ -#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); - -/* ========================================================================= */ -uLong ZEXPORT crc32(crc, buf, len) - uLong crc; - const Bytef *buf; - uInt len; -{ - if (buf == Z_NULL) return 0L; -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif - crc = crc ^ 0xffffffffL; - while (len >= 8) - { - DO8(buf); - len -= 8; - } - if (len) do { - DO1(buf); - } while (--len); - return crc ^ 0xffffffffL; -} diff --git a/zlib/deflate.c b/zlib/deflate.c deleted file mode 100644 index 16ebdade3..000000000 --- a/zlib/deflate.c +++ /dev/null @@ -1,1350 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in ftp://ds.internic.net/rfc/rfc1951.txt - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id$ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -local block_state deflate_slow OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int noheader = 0; - static const char* my_version = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == Z_NULL) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == Z_NULL) strm->zfree = zcfree; - - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#ifdef FASTEST - level = 1; -#endif - - if (windowBits < 0) { /* undocumented feature: suppress zlib header */ - noheader = 1; - windowBits = -windowBits; - } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->noheader = noheader; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->status != INIT_STATE) return Z_STREAM_ERROR; - - s = strm->state; - strm->adler = adler32(strm->adler, dictionary, dictLength); - - if (length < MIN_MATCH) return Z_OK; - if (length > MAX_DIST(s)) { - length = MAX_DIST(s); -#ifndef USE_DICT_HEAD - dictionary += dictLength - length; /* use the tail of the dictionary */ -#endif - } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); - } - if (hash_head) hash_head = 0; /* to make compiler happy */ - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (strm) - z_streamp strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->noheader < 0) { - s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ - } - s->status = s->noheader ? BUSY_STATE : INIT_STATE; - strm->adler = 1; - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - lm_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - - if (level == Z_DEFAULT_COMPRESSION) { - level = 6; - } - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if (func != configuration_table[level].func && strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_PARTIAL_FLUSH); - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - unsigned len = strm->state->pending; - - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, strm->state->pending_out, len); - strm->next_out += len; - strm->state->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_FINISH || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the zlib header */ - if (s->status == INIT_STATE) { - - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags = (s->level-1) >> 1; - - if (level_flags > 3) level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = 1L; - } - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUFF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->noheader) return Z_STREAM_END; - - /* Write the zlib trailer (adler32) */ - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - s->noheader = -1; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (strm) - z_streamp strm; -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - *dest = *source; - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - *ds = *ss; - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (!strm->state->noheader) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -} - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -#ifndef FASTEST -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} - -#else /* FASTEST */ -/* --------------------------------------------------------------------------- - * Optimized version for level == 1 only - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return len <= s->lookahead ? len : s->lookahead; -} -#endif /* FASTEST */ -#endif /* ASMV */ - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if strstart == 0 - * and lookahead == 1 (input done one byte at time) - */ - more--; - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - } else if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, eof) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (eof)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, eof) { \ - FLUSH_BLOCK_ONLY(s, eof); \ - if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in hash table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY) { - s->match_length = longest_match (s, hash_head); - } - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED || - (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} diff --git a/zlib/deflate.h b/zlib/deflate.h deleted file mode 100644 index b99a48a52..000000000 --- a/zlib/deflate.h +++ /dev/null @@ -1,318 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2002 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef _DEFLATE_H -#define _DEFLATE_H - -#include "zutil.h" - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define INIT_STATE 42 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - int pending; /* nb of bytes in the pending buffer */ - int noheader; /* suppress zlib header and adler32 */ - Byte data_type; /* UNKNOWN, BINARY or ASCII */ - Byte method; /* STORED (for zip only) or DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ - -#ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - - /* in trees.c */ -void _tr_init OF((deflate_state *s)); -int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_align OF((deflate_state *s)); -void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch _length_code[]; - extern uch _dist_code[]; -#else - extern const uch _length_code[]; - extern const uch _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif diff --git a/zlib/example.c b/zlib/example.c deleted file mode 100644 index e7e367333..000000000 --- a/zlib/example.c +++ /dev/null @@ -1,556 +0,0 @@ -/* example.c -- usage example of the zlib compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include -#include "zlib.h" - -#ifdef STDC -# include -# include -#else - extern void exit OF((int)); -#endif - -#if defined(VMS) || defined(RISCOS) -# define TESTFILE "foo-gz" -#else -# define TESTFILE "foo.gz" -#endif - -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - -const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ - -const char dictionary[] = "hello"; -uLong dictId; /* Adler32 value of the dictionary */ - -void test_compress OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_gzio OF((const char *out, const char *in, - Byte *uncompr, int uncomprLen)); -void test_deflate OF((Byte *compr, uLong comprLen)); -void test_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_deflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_large_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_flush OF((Byte *compr, uLong *comprLen)); -void test_sync OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -void test_dict_deflate OF((Byte *compr, uLong comprLen)); -void test_dict_inflate OF((Byte *compr, uLong comprLen, - Byte *uncompr, uLong uncomprLen)); -int main OF((int argc, char *argv[])); - -/* =========================================================================== - * Test compress() and uncompress() - */ -void test_compress(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - uLong len = strlen(hello)+1; - - err = compress(compr, &comprLen, (const Bytef*)hello, len); - CHECK_ERR(err, "compress"); - - strcpy((char*)uncompr, "garbage"); - - err = uncompress(uncompr, &uncomprLen, compr, comprLen); - CHECK_ERR(err, "uncompress"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { - printf("uncompress(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test read/write of .gz files - */ -void test_gzio(out, in, uncompr, uncomprLen) - const char *out; /* compressed output file */ - const char *in; /* compressed input file */ - Byte *uncompr; - int uncomprLen; -{ - int err; - int len = strlen(hello)+1; - gzFile file; - z_off_t pos; - - file = gzopen(out, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } - gzputc(file, 'h'); - if (gzputs(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); - exit(1); - } - if (gzprintf(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); - exit(1); - } - gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ - gzclose(file); - - file = gzopen(in, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - } - strcpy((char*)uncompr, "garbage"); - - uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen); - if (uncomprLen != len) { - fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { - printf("gzread(): %s\n", (char *)uncompr); - } - - pos = gzseek(file, -8L, SEEK_CUR); - if (pos != 6 || gztell(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)gztell(file)); - exit(1); - } - - if (gzgetc(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - - gzgets(file, (char*)uncompr, uncomprLen); - uncomprLen = strlen((char*)uncompr); - if (uncomprLen != 6) { /* "hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello+7)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { - printf("gzgets() after gzseek: %s\n", (char *)uncompr); - } - - gzclose(file); -} - -/* =========================================================================== - * Test deflate() with small buffers - */ -void test_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - int len = strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - - while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) { - c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - } - /* Finish the stream, still forcing small buffers: */ - for (;;) { - c_stream.avail_out = 1; - err = deflate(&c_stream, Z_FINISH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); - } - - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with small buffers - */ -void test_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 0; - d_stream.next_out = uncompr; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { - d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { - printf("inflate(): %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Test deflate() with large buffers and dynamic change of compression level - */ -void test_large_deflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_SPEED); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - /* At this point, uncompr is still mostly zeroes, so it should compress - * very well: - */ - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } - - /* Feed in already compressed data and switch to no compression: */ - deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); - c_stream.next_in = compr; - c_stream.avail_in = (uInt)comprLen/2; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - /* Switch back to compressing mode: */ - deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); - c_stream.next_in = uncompr; - c_stream.avail_in = (uInt)uncomprLen; - err = deflate(&c_stream, Z_NO_FLUSH); - CHECK_ERR(err, "deflate"); - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with large buffers - */ -void test_large_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - for (;;) { - d_stream.next_out = uncompr; /* discard the output */ - d_stream.avail_out = (uInt)uncomprLen; - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - CHECK_ERR(err, "large inflate"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (d_stream.total_out != 2*uncomprLen + comprLen/2) { - fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); - exit(1); - } else { - printf("large_inflate(): OK\n"); - } -} - -/* =========================================================================== - * Test deflate() with full flush - */ -void test_flush(compr, comprLen) - Byte *compr; - uLong *comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - int len = strlen(hello)+1; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - c_stream.next_in = (Bytef*)hello; - c_stream.next_out = compr; - c_stream.avail_in = 3; - c_stream.avail_out = (uInt)*comprLen; - err = deflate(&c_stream, Z_FULL_FLUSH); - CHECK_ERR(err, "deflate"); - - compr[3]++; /* force an error in first compressed block */ - c_stream.avail_in = len - 3; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - CHECK_ERR(err, "deflate"); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); - - *comprLen = c_stream.total_out; -} - -/* =========================================================================== - * Test inflateSync() - */ -void test_sync(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = 2; /* just read the zlib header */ - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - inflate(&d_stream, Z_NO_FLUSH); - CHECK_ERR(err, "inflate"); - - d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ - err = inflateSync(&d_stream); /* but skip the damaged part */ - CHECK_ERR(err, "inflateSync"); - - err = inflate(&d_stream, Z_FINISH); - if (err != Z_DATA_ERROR) { - fprintf(stderr, "inflate should report DATA_ERROR\n"); - /* Because of incorrect adler32 */ - exit(1); - } - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - printf("after inflateSync(): hel%s\n", (char *)uncompr); -} - -/* =========================================================================== - * Test deflate() with preset dictionary - */ -void test_dict_deflate(compr, comprLen) - Byte *compr; - uLong comprLen; -{ - z_stream c_stream; /* compression stream */ - int err; - - c_stream.zalloc = (alloc_func)0; - c_stream.zfree = (free_func)0; - c_stream.opaque = (voidpf)0; - - err = deflateInit(&c_stream, Z_BEST_COMPRESSION); - CHECK_ERR(err, "deflateInit"); - - err = deflateSetDictionary(&c_stream, - (const Bytef*)dictionary, sizeof(dictionary)); - CHECK_ERR(err, "deflateSetDictionary"); - - dictId = c_stream.adler; - c_stream.next_out = compr; - c_stream.avail_out = (uInt)comprLen; - - c_stream.next_in = (Bytef*)hello; - c_stream.avail_in = (uInt)strlen(hello)+1; - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } - err = deflateEnd(&c_stream); - CHECK_ERR(err, "deflateEnd"); -} - -/* =========================================================================== - * Test inflate() with a preset dictionary - */ -void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) - Byte *compr, *uncompr; - uLong comprLen, uncomprLen; -{ - int err; - z_stream d_stream; /* decompression stream */ - - strcpy((char*)uncompr, "garbage"); - - d_stream.zalloc = (alloc_func)0; - d_stream.zfree = (free_func)0; - d_stream.opaque = (voidpf)0; - - d_stream.next_in = compr; - d_stream.avail_in = (uInt)comprLen; - - err = inflateInit(&d_stream); - CHECK_ERR(err, "inflateInit"); - - d_stream.next_out = uncompr; - d_stream.avail_out = (uInt)uncomprLen; - - for (;;) { - err = inflate(&d_stream, Z_NO_FLUSH); - if (err == Z_STREAM_END) break; - if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } - err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, - sizeof(dictionary)); - } - CHECK_ERR(err, "inflate with dict"); - } - - err = inflateEnd(&d_stream); - CHECK_ERR(err, "inflateEnd"); - - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { - printf("inflate with dictionary: %s\n", (char *)uncompr); - } -} - -/* =========================================================================== - * Usage: example [output.gz [input.gz]] - */ - -int main(argc, argv) - int argc; - char *argv[]; -{ - Byte *compr, *uncompr; - uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - uLong uncomprLen = comprLen; - static const char* myVersion = ZLIB_VERSION; - - if (zlibVersion()[0] != myVersion[0]) { - fprintf(stderr, "incompatible zlib version\n"); - exit(1); - - } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { - fprintf(stderr, "warning: different zlib version\n"); - } - - compr = (Byte*)calloc((uInt)comprLen, 1); - uncompr = (Byte*)calloc((uInt)uncomprLen, 1); - /* compr and uncompr are cleared to avoid reading uninitialized - * data and to ensure that uncompr compresses well. - */ - if (compr == Z_NULL || uncompr == Z_NULL) { - printf("out of memory\n"); - exit(1); - } - test_compress(compr, comprLen, uncompr, uncomprLen); - - test_gzio((argc > 1 ? argv[1] : TESTFILE), - (argc > 2 ? argv[2] : TESTFILE), - uncompr, (int)uncomprLen); - - test_deflate(compr, comprLen); - test_inflate(compr, comprLen, uncompr, uncomprLen); - - test_large_deflate(compr, comprLen, uncompr, uncomprLen); - test_large_inflate(compr, comprLen, uncompr, uncomprLen); - - test_flush(compr, &comprLen); - test_sync(compr, comprLen, uncompr, uncomprLen); - comprLen = uncomprLen; - - test_dict_deflate(compr, comprLen); - test_dict_inflate(compr, comprLen, uncompr, uncomprLen); - - exit(0); - return 0; /* to avoid warning */ -} diff --git a/zlib/infblock.c b/zlib/infblock.c deleted file mode 100644 index dd7a6d40a..000000000 --- a/zlib/infblock.c +++ /dev/null @@ -1,403 +0,0 @@ -/* infblock.c -- interpret and process block types to last block - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* Table for deflate from PKZIP's appnote.txt. */ -local const uInt border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* - Notes beyond the 1.93a appnote.txt: - - 1. Distance pointers never point before the beginning of the output - stream. - 2. Distance pointers can point back across blocks, up to 32k away. - 3. There is an implied maximum of 7 bits for the bit length table and - 15 bits for the actual data. - 4. If only one code exists, then it is encoded using one bit. (Zero - would be more efficient, but perhaps a little confusing.) If two - codes exist, they are coded using one bit each (0 and 1). - 5. There is no way of sending zero distance codes--a dummy must be - sent if there are none. (History: a pre 2.0 version of PKZIP would - store blocks with no distance codes, but this was discovered to be - too harsh a criterion.) Valid only for 1.93a. 2.04c does allow - zero distance codes, which is sent as one code of zero bits in - length. - 6. There are up to 286 literal/length codes. Code 256 represents the - end-of-block. Note however that the static length tree defines - 288 codes just to fill out the Huffman codes. Codes 286 and 287 - cannot be used though, since there is no length base or extra bits - defined for them. Similarily, there are up to 30 distance codes. - However, static trees define 32 codes (all 5 bits) to fill out the - Huffman codes, but the last two had better not show up in the data. - 7. Unzip can check dynamic Huffman blocks for complete code sets. - The exception is that a single code would not be complete (see #4). - 8. The five bits following the block type is really the number of - literal codes sent minus 257. - 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits - (1+6+6). Therefore, to output three times the length, you output - three codes (1+1+1), whereas to output four times the same length, - you only need two codes (1+3). Hmm. - 10. In the tree reconstruction algorithm, Code = Code + Increment - only if BitLength(i) is not zero. (Pretty obvious.) - 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) - 12. Note: length code 284 can represent 227-258, but length code 285 - really is 258. The last length deserves its own, short code - since it gets used a lot in very redundant files. The length - 258 is special since 258 - 3 (the min match length) is 255. - 13. The literal/length and distance code bit lengths are read as a - single stream of lengths. It is possible (and advantageous) for - a repeat code (16, 17, or 18) to go across the boundary between - the two sets of lengths. - */ - - -void inflate_blocks_reset(s, z, c) -inflate_blocks_statef *s; -z_streamp z; -uLongf *c; -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == BTREE || s->mode == DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); - Tracev((stderr, "inflate: blocks reset\n")); -} - - -inflate_blocks_statef *inflate_blocks_new(z, c, w) -z_streamp z; -check_func c; -uInt w; -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = TYPE; - Tracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -int inflate_blocks(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt t; /* temporary storage */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input based on current state */ - while (1) switch (s->mode) - { - case TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: /* stored */ - Tracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; /* go to byte boundary */ - DUMPBITS(t) - s->mode = LENS; /* get length of stored block */ - break; - case 1: /* fixed */ - Tracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = CODES; - break; - case 2: /* dynamic */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = TABLE; - break; - case 3: /* illegal */ - DUMPBITS(3) - s->mode = BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; /* dump bits */ - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); - break; - case STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - zmemcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? DRY : TYPE; - break; - case TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; -#ifndef PKZIP_BUG_WORKAROUND - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } -#endif - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = BTREE; - case BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = DTREE; - case DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else /* c == 16..18 */ - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; /* must be <= 9 for lookahead assumptions */ - bd = 6; /* must be <= 9 for lookahead assumptions */ - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = BAD; - } - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - ZFREE(z, s->sub.trees.blens); - s->mode = CODES; - case CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = TYPE; - break; - } - s->mode = DRY; - case DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = DONE; - case DONE: - r = Z_STREAM_END; - LEAVE - case BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int inflate_blocks_free(s, z) -inflate_blocks_statef *s; -z_streamp z; -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - -void inflate_set_dictionary(s, d, n) -inflate_blocks_statef *s; -const Bytef *d; -uInt n; -{ - zmemcpy(s->window, d, n); - s->read = s->write = s->window + n; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. - * IN assertion: s != Z_NULL - */ -int inflate_blocks_sync_point(s) -inflate_blocks_statef *s; -{ - return s->mode == LENS; -} diff --git a/zlib/infblock.h b/zlib/infblock.h deleted file mode 100644 index 173b2267a..000000000 --- a/zlib/infblock.h +++ /dev/null @@ -1,39 +0,0 @@ -/* infblock.h -- header to use infblock.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_blocks_state; -typedef struct inflate_blocks_state FAR inflate_blocks_statef; - -extern inflate_blocks_statef * inflate_blocks_new OF(( - z_streamp z, - check_func c, /* check function */ - uInt w)); /* window size */ - -extern int inflate_blocks OF(( - inflate_blocks_statef *, - z_streamp , - int)); /* initial return code */ - -extern void inflate_blocks_reset OF(( - inflate_blocks_statef *, - z_streamp , - uLongf *)); /* check value on output */ - -extern int inflate_blocks_free OF(( - inflate_blocks_statef *, - z_streamp)); - -extern void inflate_set_dictionary OF(( - inflate_blocks_statef *s, - const Bytef *d, /* dictionary */ - uInt n)); /* dictionary length */ - -extern int inflate_blocks_sync_point OF(( - inflate_blocks_statef *s)); diff --git a/zlib/infcodes.c b/zlib/infcodes.c deleted file mode 100644 index 9abe5412b..000000000 --- a/zlib/infcodes.c +++ /dev/null @@ -1,251 +0,0 @@ -/* infcodes.c -- process literals and length/distance pairs - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#include "inffast.h" - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - START, /* x: set up for LEN */ - LEN, /* i: get length/literal/eob next */ - LENEXT, /* i: getting length extra (have base) */ - DIST, /* i: get distance next */ - DISTEXT, /* i: getting distance extra */ - COPY, /* o: copying bytes in window, waiting for space */ - LIT, /* o: got literal, waiting for output space */ - WASH, /* o: got eob, possibly still output waiting */ - END, /* x: got eob and all data flushed */ - BADCODE} /* x: got error */ -inflate_codes_mode; - -/* inflate codes private state */ -struct inflate_codes_state { - - /* mode */ - inflate_codes_mode mode; /* current inflate_codes mode */ - - /* mode dependent information */ - uInt len; - union { - struct { - inflate_huft *tree; /* pointer into tree */ - uInt need; /* bits needed */ - } code; /* if LEN or DIST, where in tree */ - uInt lit; /* if LIT, literal */ - struct { - uInt get; /* bits to get for extra */ - uInt dist; /* distance back to copy from */ - } copy; /* if EXT or COPY, where and how much */ - } sub; /* submode */ - - /* mode independent information */ - Byte lbits; /* ltree bits decoded per branch */ - Byte dbits; /* dtree bits decoder per branch */ - inflate_huft *ltree; /* literal/length/eob tree */ - inflate_huft *dtree; /* distance tree */ - -}; - - -inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) -uInt bl, bd; -inflate_huft *tl; -inflate_huft *td; /* need separate declaration for Borland C++ */ -z_streamp z; -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -int inflate_codes(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt j; /* temporary storage */ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - Bytef *f; /* pointer to copy strings from */ - inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ - - /* copy input/output information to locals (UPDATE macro restores) */ - LOAD - - /* process input and output based on current state */ - while (1) switch (c->mode) - { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ - case START: /* x: set up for LEN */ -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif /* !SLOW */ - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: /* i: get length/literal/eob next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) /* literal */ - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) /* length */ - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) /* end of block */ - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: /* i: getting length extra (have base) */ - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: /* i: get distance next */ - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) /* distance */ - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) /* next table */ - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; /* invalid code */ - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: /* i: getting distance extra */ - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: /* o: copying bytes in window, waiting for space */ - f = q - c->sub.copy.dist; - while (f < s->window) /* modulo window size-"while" instead */ - f += s->end - s->window; /* of "if" handles invalid distances */ - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: /* o: got literal, waiting for output space */ - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: /* o: got eob, possibly more output */ - if (k > 7) /* return unused byte, if any */ - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; /* can always return one */ - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: /* x: got error */ - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -void inflate_codes_free(c, z) -inflate_codes_statef *c; -z_streamp z; -{ - ZFREE(z, c); - Tracev((stderr, "inflate: codes free\n")); -} diff --git a/zlib/infcodes.h b/zlib/infcodes.h deleted file mode 100644 index 46821a02b..000000000 --- a/zlib/infcodes.h +++ /dev/null @@ -1,27 +0,0 @@ -/* infcodes.h -- header to use infcodes.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -struct inflate_codes_state; -typedef struct inflate_codes_state FAR inflate_codes_statef; - -extern inflate_codes_statef *inflate_codes_new OF(( - uInt, uInt, - inflate_huft *, inflate_huft *, - z_streamp )); - -extern int inflate_codes OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -extern void inflate_codes_free OF(( - inflate_codes_statef *, - z_streamp )); - diff --git a/zlib/inffast.c b/zlib/inffast.c deleted file mode 100644 index aa7f1d4d2..000000000 --- a/zlib/inffast.c +++ /dev/null @@ -1,183 +0,0 @@ -/* inffast.c -- process literals and length/distance pairs fast - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "infblock.h" -#include "infcodes.h" -#include "infutil.h" -#include "inffast.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - -/* macros for bit input with no checking and for returning unused bytes */ -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} - -/* Called with number of bytes left to write in window at least 258 - (the maximum string length) and number of input bytes available - at least ten. The ten bytes are six bytes for the longest length/ - distance pair plus four bytes for overloading the bit buffer. */ - -int inflate_fast(bl, bd, tl, td, s, z) -uInt bl, bd; -inflate_huft *tl; -inflate_huft *td; /* need separate declaration for Borland C++ */ -inflate_blocks_statef *s; -z_streamp z; -{ - inflate_huft *t; /* temporary pointer */ - uInt e; /* extra bits or operation */ - uLong b; /* bit buffer */ - uInt k; /* bits in bit buffer */ - Bytef *p; /* input data pointer */ - uInt n; /* bytes available there */ - Bytef *q; /* output window write pointer */ - uInt m; /* bytes to end of window or read pointer */ - uInt ml; /* mask for literal/length tree */ - uInt md; /* mask for distance tree */ - uInt c; /* bytes to copy */ - uInt d; /* distance back to copy from */ - Bytef *r; /* copy source pointer */ - - /* load input, output, bit values */ - LOAD - - /* initialize masks */ - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - /* do until not enough input or output space for fast loop */ - do { /* assume called with m >= 258 && n >= 10 */ - /* get literal/length code */ - GRABBITS(20) /* max bits for literal/length code */ - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits for length */ - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * length %u\n", c)); - - /* decode distance base of block to copy */ - GRABBITS(15); /* max bits for distance code */ - e = (t = td + ((uInt)b & md))->exop; - do { - DUMPBITS(t->bits) - if (e & 16) - { - /* get extra bits to add to distance base */ - e &= 15; - GRABBITS(e) /* get extra bits (up to 13) */ - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * distance %u\n", d)); - - /* do the copy */ - m -= c; - r = q - d; - if (r < s->window) /* wrap if needed */ - { - do { - r += s->end - s->window; /* force pointer in window */ - } while (r < s->window); /* covers invalid distances */ - e = s->end - r; - if (c > e) - { - c -= e; /* wrapped copy */ - do { - *q++ = *r++; - } while (--e); - r = s->window; - do { - *q++ = *r++; - } while (--c); - } - else /* normal copy */ - { - *q++ = *r++; c--; - *q++ = *r++; c--; - do { - *q++ = *r++; - } while (--c); - } - } - else /* normal copy */ - { - *q++ = *r++; c--; - *q++ = *r++; c--; - do { - *q++ = *r++; - } while (--c); - } - break; - } - else if ((e & 64) == 0) - { - t += t->base; - e = (t += ((uInt)b & inflate_mask[e]))->exop; - } - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - break; - } - if ((e & 64) == 0) - { - t += t->base; - if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - } while (1); - } while (m >= 258 && n >= 10); - - /* not enough input or output--restore pointers and return */ - UNGRAB - UPDATE - return Z_OK; -} diff --git a/zlib/inffast.h b/zlib/inffast.h deleted file mode 100644 index a31a4bbb0..000000000 --- a/zlib/inffast.h +++ /dev/null @@ -1,17 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -extern int inflate_fast OF(( - uInt, - uInt, - inflate_huft *, - inflate_huft *, - inflate_blocks_statef *, - z_streamp )); diff --git a/zlib/inffixed.h b/zlib/inffixed.h deleted file mode 100644 index 77f7e7631..000000000 --- a/zlib/inffixed.h +++ /dev/null @@ -1,151 +0,0 @@ -/* inffixed.h -- table for decoding fixed codes - * Generated automatically by the maketree.c program - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -local uInt fixed_bl = 9; -local uInt fixed_bd = 5; -local inflate_huft fixed_tl[] = { - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; -local inflate_huft fixed_td[] = { - {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, - {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, - {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, - {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, - {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, - {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, - {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, - {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; diff --git a/zlib/inflate.c b/zlib/inflate.c deleted file mode 100644 index dfb2e867d..000000000 --- a/zlib/inflate.c +++ /dev/null @@ -1,366 +0,0 @@ -/* inflate.c -- zlib interface to inflate modules - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" - -struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ - -typedef enum { - METHOD, /* waiting for method byte */ - FLAG, /* waiting for flag byte */ - DICT4, /* four dictionary check bytes to go */ - DICT3, /* three dictionary check bytes to go */ - DICT2, /* two dictionary check bytes to go */ - DICT1, /* one dictionary check byte to go */ - DICT0, /* waiting for inflateSetDictionary */ - BLOCKS, /* decompressing blocks */ - CHECK4, /* four check bytes to go */ - CHECK3, /* three check bytes to go */ - CHECK2, /* two check bytes to go */ - CHECK1, /* one check byte to go */ - DONE, /* finished check, done */ - BAD} /* got an error--stay here */ -inflate_mode; - -/* inflate private state */ -struct internal_state { - - /* mode */ - inflate_mode mode; /* current inflate mode */ - - /* mode dependent information */ - union { - uInt method; /* if FLAGS, method byte */ - struct { - uLong was; /* computed check value */ - uLong need; /* stream check value */ - } check; /* if CHECK, check values to compare */ - uInt marker; /* if BAD, inflateSync's marker bytes count */ - } sub; /* submode */ - - /* mode independent information */ - int nowrap; /* flag for no wrapper */ - uInt wbits; /* log2(window size) (8..15, defaults to 15) */ - inflate_blocks_statef - *blocks; /* current inflate_blocks state */ - -}; - - -int ZEXPORT inflateReset(z) -z_streamp z; -{ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? BLOCKS : METHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - - -int ZEXPORT inflateEnd(z) -z_streamp z; -{ - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - - -int ZEXPORT inflateInit2_(z, w, version, stream_size) -z_streamp z; -int w; -const char *version; -int stream_size; -{ - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != sizeof(z_stream)) - return Z_VERSION_ERROR; - - /* initialize state */ - if (z == Z_NULL) - return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; - if ((z->state = (struct internal_state FAR *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - /* handle undocumented nowrap option (no zlib header or check) */ - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - /* set window size */ - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - /* create inflate_blocks state */ - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Tracev((stderr, "inflate: allocated\n")); - - /* reset state */ - inflateReset(z); - return Z_OK; -} - - -int ZEXPORT inflateInit_(z, version, stream_size) -z_streamp z; -const char *version; -int stream_size; -{ - return inflateInit2_(z, DEF_WBITS, version, stream_size); -} - - -#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} -#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int ZEXPORT inflate(z, f) -z_streamp z; -int f; -{ - int r; - uInt b; - - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - while (1) switch (z->state->mode) - { - case METHOD: - NEEDBYTE - if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - z->state->mode = FLAG; - case FLAG: - NEEDBYTE - b = NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = BLOCKS; - break; - } - z->state->mode = DICT4; - case DICT4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = DICT3; - case DICT3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = DICT2; - case DICT2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = DICT1; - case DICT1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = DICT0; - return Z_NEED_DICT; - case DICT0: - z->state->mode = BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; /* can try inflateSync */ - return Z_STREAM_ERROR; - case BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { - z->state->mode = BAD; - z->state->sub.marker = 0; /* can try inflateSync */ - break; - } - if (r == Z_OK) - r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = DONE; - break; - } - z->state->mode = CHECK4; - case CHECK4: - NEEDBYTE - z->state->sub.check.need = (uLong)NEXTBYTE << 24; - z->state->mode = CHECK3; - case CHECK3: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 16; - z->state->mode = CHECK2; - case CHECK2: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE << 8; - z->state->mode = CHECK1; - case CHECK1: - NEEDBYTE - z->state->sub.check.need += (uLong)NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; /* can't try inflateSync */ - break; - } - Tracev((stderr, "inflate: zlib check ok\n")); - z->state->mode = DONE; - case DONE: - return Z_STREAM_END; - case BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } -#ifdef NEED_DUMMY_RETURN - return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ -#endif -} - - -int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) -z_streamp z; -const Bytef *dictionary; -uInt dictLength; -{ - uInt length = dictLength; - - if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) - return Z_STREAM_ERROR; - - if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; - z->adler = 1L; - - if (length >= ((uInt)1<state->wbits)) - { - length = (1<state->wbits)-1; - dictionary += dictLength - length; - } - inflate_set_dictionary(z->state->blocks, dictionary, length); - z->state->mode = BLOCKS; - return Z_OK; -} - - -int ZEXPORT inflateSync(z) -z_streamp z; -{ - uInt n; /* number of bytes to look at */ - Bytef *p; /* pointer to bytes */ - uInt m; /* number of marker bytes found in a row */ - uLong r, w; /* temporaries to save total_in and total_out */ - - /* set up */ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->mode != BAD) - { - z->state->mode = BAD; - z->state->sub.marker = 0; - } - if ((n = z->avail_in) == 0) - return Z_BUF_ERROR; - p = z->next_in; - m = z->state->sub.marker; - - /* search */ - while (n && m < 4) - { - static const Byte mark[4] = {0, 0, 0xff, 0xff}; - if (*p == mark[m]) - m++; - else if (*p) - m = 0; - else - m = 4 - m; - p++, n--; - } - - /* restore */ - z->total_in += p - z->next_in; - z->next_in = p; - z->avail_in = n; - z->state->sub.marker = m; - - /* return no joy or set up to restart on a new block */ - if (m != 4) - return Z_DATA_ERROR; - r = z->total_in; w = z->total_out; - inflateReset(z); - z->total_in = r; z->total_out = w; - z->state->mode = BLOCKS; - return Z_OK; -} - - -/* Returns true if inflate is currently at the end of a block generated - * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH - * but removes the length bytes of the resulting empty stored block. When - * decompressing, PPP checks that at the end of input packet, inflate is - * waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(z) -z_streamp z; -{ - if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) - return Z_STREAM_ERROR; - return inflate_blocks_sync_point(z->state->blocks); -} diff --git a/zlib/inftrees.c b/zlib/inftrees.c deleted file mode 100644 index 4c32ca30d..000000000 --- a/zlib/inftrees.c +++ /dev/null @@ -1,454 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#if !defined(BUILDFIXED) && !defined(STDC) -# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ -#endif - -const char inflate_copyright[] = - " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ -struct internal_state {int dummy;}; /* for buggy compilers */ - -/* simplify the use of the inflate_huft type with some defines */ -#define exop word.what.Exop -#define bits word.what.Bits - - -local int huft_build OF(( - uIntf *, /* code lengths in bits */ - uInt, /* number of codes */ - uInt, /* number of "simple" codes */ - const uIntf *, /* list of base values for non-simple codes */ - const uIntf *, /* list of extra bits for non-simple codes */ - inflate_huft * FAR*,/* result: starting table */ - uIntf *, /* maximum lookup bits (returns actual) */ - inflate_huft *, /* space for trees */ - uInt *, /* hufts used in space */ - uIntf * )); /* space for values */ - -/* Tables for deflate from PKZIP's appnote.txt. */ -local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* see note #13 above about 258 */ -local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ -local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -local const uInt cpdext[30] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -/* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose - size is determined by the longest code. However, the time it takes - to build this table can also be a factor if the data being decoded - is not very long. The most common codes are necessarily the - shortest codes, so those codes dominate the decoding time, and hence - the speed. The idea is you can have a shorter table that decodes the - shorter, more probable codes, and then point to subsidiary tables for - the longer codes. The time it costs to decode the longer codes is - then traded against the time it takes to make longer tables. - - This results of this trade are in the variables lbits and dbits - below. lbits is the number of bits the first level table for literal/ - length codes can decode in one step, and dbits is the same thing for - the distance codes. Subsequent tables are also less than or equal to - those sizes. These values may be adjusted either when all of the - codes are shorter than that, in which case the longest code length in - bits is used, or when the shortest code is *longer* than the requested - table size, in which case the length of the shortest code in bits is - used. - - There are two different values for the two tables, since they code a - different number of possibilities each. The literal/length table - codes 286 possible values, or in a flat code, a little over eight - bits. The distance table codes 30 possible values, or a little less - than five bits, flat. The optimum values for speed end up being - about one bit more than those, so lbits is 8+1 and dbits is 5+1. - The optimum values may differ though from machine to machine, and - possibly even between compilers. Your mileage may vary. - */ - - -/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ -#define BMAX 15 /* maximum bit length of any code */ - -local int huft_build(b, n, s, d, e, t, m, hp, hn, v) -uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ -uInt n; /* number of codes (assumed <= 288) */ -uInt s; /* number of simple-valued codes (0..s-1) */ -const uIntf *d; /* list of base values for non-simple codes */ -const uIntf *e; /* list of extra bits for non-simple codes */ -inflate_huft * FAR *t; /* result: starting table */ -uIntf *m; /* maximum lookup bits, returns actual */ -inflate_huft *hp; /* space for trees */ -uInt *hn; /* hufts used in space */ -uIntf *v; /* working area: values in order of bit length */ -/* Given a list of code lengths and a maximum table size, make a set of - tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - if the given code set is incomplete (the tables are still built in this - case), or Z_DATA_ERROR if the input is invalid. */ -{ - - uInt a; /* counter for codes of length k */ - uInt c[BMAX+1]; /* bit length count table */ - uInt f; /* i repeats in table every f entries */ - int g; /* maximum code length */ - int h; /* table level */ - register uInt i; /* counter, current code */ - register uInt j; /* counter */ - register int k; /* number of bits in current code */ - int l; /* bits per table (returned in m) */ - uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ - register uIntf *p; /* pointer into c[], b[], or v[] */ - inflate_huft *q; /* points to current table */ - struct inflate_huft_s r; /* table entry for structure assignment */ - inflate_huft *u[BMAX]; /* table stack */ - register int w; /* bits before this table == (l * h) */ - uInt x[BMAX+1]; /* bit offsets, then code stack */ - uIntf *xp; /* pointer into x */ - int y; /* number of dummy codes added */ - uInt z; /* number of entries in current table */ - - - /* Generate counts for each bit length */ - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4 /* clear c[]--assume BMAX+1 is 16 */ - p = b; i = n; - do { - c[*p++]++; /* assume all entries <= BMAX */ - } while (--i); - if (c[0] == n) /* null input--all zero length codes */ - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - /* Find minimum and maximum length, bound *m by those */ - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; /* minimum code length */ - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; /* maximum code length */ - if ((uInt)l > i) - l = i; - *m = l; - - - /* Adjust last length count to fill out codes, if needed */ - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - /* Generate starting offsets into the value table for each length */ - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { /* note that i == g from above */ - *xp++ = (j += *p++); - } - - - /* Make a table of values in order of bit lengths */ - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; /* set n to length of v */ - - - /* Generate the Huffman codes and for each, make the table entries */ - x[0] = i = 0; /* first Huffman code is zero */ - p = v; /* grab values in bit order */ - h = -1; /* no tables yet--level -1 */ - w = -l; /* bits decoded == (l * h) */ - u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ - q = (inflate_huft *)Z_NULL; /* ditto */ - z = 0; /* ditto */ - - /* go through the bit lengths (k already is bits in shortest code) */ - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - /* here i is the Huffman code of length k bits for value *p */ - /* make tables up to required level */ - while (k > w + l) - { - h++; - w += l; /* previous table always l bits */ - - /* compute minimum size table less than or equal to l bits */ - z = g - w; - z = z > (uInt)l ? l : z; /* table size upper limit */ - if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ - { /* too few codes for k-w bit table */ - f -= a + 1; /* deduct codes from patterns left */ - xp = c + k; - if (j < z) - while (++j < z) /* try smaller tables up to z bits */ - { - if ((f <<= 1) <= *++xp) - break; /* enough codes to use up j bits */ - f -= *xp; /* else deduct codes from patterns */ - } - } - z = 1 << j; /* table entries for j-bit table */ - - /* allocate new table */ - if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ - return Z_DATA_ERROR; /* overflow of MANY */ - u[h] = q = hp + *hn; - *hn += z; - - /* connect to last table, if there is one */ - if (h) - { - x[h] = i; /* save pattern for backing up */ - r.bits = (Byte)l; /* bits to dump before this table */ - r.exop = (Byte)j; /* bits in this table */ - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ - u[h-1][j] = r; /* connect to last table */ - } - else - *t = q; /* first table is returned result */ - } - - /* set up table entry in r */ - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; /* out of values--invalid code */ - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ - r.base = *p++; /* simple code is just the value */ - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ - r.base = d[*p++ - s]; - } - - /* fill code-like entries with r */ - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - /* backwards increment the k-bit code i */ - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - /* backup over finished tables */ - mask = (1 << w) - 1; /* needed on HP, cc -O bug */ - while ((i & mask) != x[h]) - { - h--; /* don't need to update q */ - w -= l; - mask = (1 << w) - 1; - } - } - } - - - /* Return Z_BUF_ERROR if we were given an incomplete table */ - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -int inflate_trees_bits(c, bb, tb, hp, z) -uIntf *c; /* 19 code lengths */ -uIntf *bb; /* bits tree desired/actual depth */ -inflate_huft * FAR *tb; /* bits tree result */ -inflate_huft *hp; /* space for trees */ -z_streamp z; /* for messages */ -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -} - - -int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) -uInt nl; /* number of literal/length codes */ -uInt nd; /* number of distance codes */ -uIntf *c; /* that many (total) code lengths */ -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -inflate_huft *hp; /* space for trees */ -z_streamp z; /* for messages */ -{ - int r; - uInt hn = 0; /* hufts used in space */ - uIntf *v; /* work area for huft_build */ - - /* allocate work area */ - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - - /* build literal/length tree */ - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - /* build distance tree */ - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { -#ifdef PKZIP_BUG_WORKAROUND - r = Z_OK; - } -#else - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -#endif - } - - /* done */ - ZFREE(z, v); - return Z_OK; -} - - -/* build fixed tables only once--keep them here */ -#ifdef BUILDFIXED -local int fixed_built = 0; -#define FIXEDH 544 /* number of hufts used by fixed tables */ -local inflate_huft fixed_mem[FIXEDH]; -local uInt fixed_bl; -local uInt fixed_bd; -local inflate_huft *fixed_tl; -local inflate_huft *fixed_td; -#else -#include "inffixed.h" -#endif - - -int inflate_trees_fixed(bl, bd, tl, td, z) -uIntf *bl; /* literal desired/actual bit depth */ -uIntf *bd; /* distance desired/actual bit depth */ -inflate_huft * FAR *tl; /* literal/length tree result */ -inflate_huft * FAR *td; /* distance tree result */ -z_streamp z; /* for memory allocation */ -{ -#ifdef BUILDFIXED - /* build fixed tables if not already */ - if (!fixed_built) - { - int k; /* temporary variable */ - uInt f = 0; /* number of hufts used in fixed_mem */ - uIntf *c; /* length list for huft_build */ - uIntf *v; /* work area for huft_build */ - - /* allocate memory */ - if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - { - ZFREE(z, c); - return Z_MEM_ERROR; - } - - /* literal table */ - for (k = 0; k < 144; k++) - c[k] = 8; - for (; k < 256; k++) - c[k] = 9; - for (; k < 280; k++) - c[k] = 7; - for (; k < 288; k++) - c[k] = 8; - fixed_bl = 9; - huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, - fixed_mem, &f, v); - - /* distance table */ - for (k = 0; k < 30; k++) - c[k] = 5; - fixed_bd = 5; - huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, - fixed_mem, &f, v); - - /* done */ - ZFREE(z, v); - ZFREE(z, c); - fixed_built = 1; - } -#endif - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} diff --git a/zlib/inftrees.h b/zlib/inftrees.h deleted file mode 100644 index 04b73b729..000000000 --- a/zlib/inftrees.h +++ /dev/null @@ -1,58 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Huffman code lookup table entry--this entry is four bytes for machines - that have 16-bit pointers (e.g. PC's in the small or medium model). */ - -typedef struct inflate_huft_s FAR inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; /* number of extra bits or operation */ - Byte Bits; /* number of bits in this code or subcode */ - } what; - uInt pad; /* pad structure to a power of 2 (4 bytes for */ - } word; /* 16-bit, 8 bytes for 32-bit int's) */ - uInt base; /* literal, length base, distance base, - or table offset */ -}; - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 huft structures (850 for length/literals - and 154 for distances, the latter actually the result of an - exhaustive search). The actual maximum is not known, but the - value below is more than safe. */ -#define MANY 1440 - -extern int inflate_trees_bits OF(( - uIntf *, /* 19 code lengths */ - uIntf *, /* bits tree desired/actual depth */ - inflate_huft * FAR *, /* bits tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -extern int inflate_trees_dynamic OF(( - uInt, /* number of literal/length codes */ - uInt, /* number of distance codes */ - uIntf *, /* that many (total) code lengths */ - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - inflate_huft *, /* space for trees */ - z_streamp)); /* for messages */ - -extern int inflate_trees_fixed OF(( - uIntf *, /* literal desired/actual bit depth */ - uIntf *, /* distance desired/actual bit depth */ - inflate_huft * FAR *, /* literal/length tree result */ - inflate_huft * FAR *, /* distance tree result */ - z_streamp)); /* for memory allocation */ diff --git a/zlib/infutil.c b/zlib/infutil.c deleted file mode 100644 index 9a076221f..000000000 --- a/zlib/infutil.c +++ /dev/null @@ -1,87 +0,0 @@ -/* inflate_util.c -- data and routines common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "infblock.h" -#include "inftrees.h" -#include "infcodes.h" -#include "infutil.h" - -struct inflate_codes_state {int dummy;}; /* for buggy compilers */ - -/* And'ing with mask[n] masks the lower n bits */ -uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - - -/* copy as much as possible from the sliding window to the output area */ -int inflate_flush(s, z, r) -inflate_blocks_statef *s; -z_streamp z; -int r; -{ - uInt n; - Bytef *p; - Bytef *q; - - /* local copies of source and destination pointers */ - p = z->next_out; - q = s->read; - - /* compute number of bytes to copy as far as end of window */ - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy as far as end of window */ - zmemcpy(p, q, n); - p += n; - q += n; - - /* see if more to copy at beginning of window */ - if (q == s->end) - { - /* wrap pointers */ - q = s->window; - if (s->write == s->end) - s->write = s->window; - - /* compute bytes to copy */ - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - /* update counters */ - z->avail_out -= n; - z->total_out += n; - - /* update check information */ - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - /* copy */ - zmemcpy(p, q, n); - p += n; - q += n; - } - - /* update pointers */ - z->next_out = p; - s->read = q; - - /* done */ - return r; -} diff --git a/zlib/infutil.h b/zlib/infutil.h deleted file mode 100644 index 4401df82f..000000000 --- a/zlib/infutil.h +++ /dev/null @@ -1,98 +0,0 @@ -/* infutil.h -- types and macros common to blocks and codes - * Copyright (C) 1995-2002 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -#ifndef _INFUTIL_H -#define _INFUTIL_H - -typedef enum { - TYPE, /* get type bits (3, including end bit) */ - LENS, /* get lengths for stored */ - STORED, /* processing stored block */ - TABLE, /* get table lengths */ - BTREE, /* get bit lengths tree for a dynamic block */ - DTREE, /* get length, distance trees for a dynamic block */ - CODES, /* processing fixed or dynamic block */ - DRY, /* output remaining window bytes */ - DONE, /* finished last block, done */ - BAD} /* got a data error--stuck here */ -inflate_block_mode; - -/* inflate blocks semi-private state */ -struct inflate_blocks_state { - - /* mode */ - inflate_block_mode mode; /* current inflate_block mode */ - - /* mode dependent information */ - union { - uInt left; /* if STORED, bytes left to copy */ - struct { - uInt table; /* table lengths (14 bits) */ - uInt index; /* index into blens (or border) */ - uIntf *blens; /* bit lengths of codes */ - uInt bb; /* bit length tree depth */ - inflate_huft *tb; /* bit length decoding tree */ - } trees; /* if DTREE, decoding info for trees */ - struct { - inflate_codes_statef - *codes; - } decode; /* if CODES, current state */ - } sub; /* submode */ - uInt last; /* true if this block is the last block */ - - /* mode independent information */ - uInt bitk; /* bits in bit buffer */ - uLong bitb; /* bit buffer */ - inflate_huft *hufts; /* single malloc for tree space */ - Bytef *window; /* sliding window */ - Bytef *end; /* one byte after sliding window */ - Bytef *read; /* window read pointer */ - Bytef *write; /* window write pointer */ - check_func checkfn; /* check function */ - uLong check; /* check on output */ - -}; - - -/* defines for inflate input/output */ -/* update pointers and return */ -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -/* get bytes and bits */ -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -/* output bytes */ -#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -/* load local pointers */ -#define LOAD {LOADIN LOADOUT} - -/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ -extern uInt inflate_mask[17]; - -/* copy as much as possible from the sliding window to the output area */ -extern int inflate_flush OF(( - inflate_blocks_statef *, - z_streamp , - int)); - -struct internal_state {int dummy;}; /* for buggy compilers */ - -#endif diff --git a/zlib/trees.c b/zlib/trees.c deleted file mode 100644 index 0a9840567..000000000 --- a/zlib/trees.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2002 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id$ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef DEBUG -# include -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); -local void set_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (val << s->bi_valid);\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG */ - - -#define MAX(a,b) (a >= b ? a : b) -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if (tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void _tr_stored_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. - */ -void _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void _tr_flush_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is ascii or binary */ - if (s->data_type == Z_UNKNOWN) set_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute first the block length in bytes*/ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, eof); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (eof) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*eof)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; -} - -/* =========================================================================== - * Set the data type to ASCII or BINARY, using a crude approximation: - * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - * IN assertion: the fields freq of dyn_ltree are set and the total of all - * frequencies does not exceed 64K (to fit in an int on 16 bit machines). - */ -local void set_data_type(s) - deflate_state *s; -{ - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; - while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; - while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; - s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/zlib/trees.h b/zlib/trees.h deleted file mode 100644 index 72facf900..000000000 --- a/zlib/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/zlib/uncompr.c b/zlib/uncompr.c deleted file mode 100644 index a287714f5..000000000 --- a/zlib/uncompr.c +++ /dev/null @@ -1,58 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ -int ZEXPORT uncompress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} diff --git a/zlib/zconf.h b/zlib/zconf.h deleted file mode 100644 index eb0ae2e1a..000000000 --- a/zlib/zconf.h +++ /dev/null @@ -1,279 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef _ZCONF_H -#define _ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateReset z_inflateReset -# define compress z_compress -# define compress2 z_compress2 -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table - -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -# define WIN32 -#endif -#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) -# ifndef __32BIT__ -# define __32BIT__ -# endif -#endif -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#if defined(MSDOS) && !defined(__32BIT__) -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) -# define STDC -#endif -#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) -# ifndef STDC -# define STDC -# endif -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Old Borland C incorrectly complains about missing returns: */ -#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) -# define NEED_DUMMY_RETURN -#endif - - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -#endif -#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) -# ifndef __32BIT__ -# define SMALL_MEDIUM -# define FAR _far -# endif -#endif - -/* Compile with -DZLIB_DLL for Windows DLL support */ -#if defined(ZLIB_DLL) -# if defined(_WINDOWS) || defined(WINDOWS) -# ifdef FAR -# undef FAR -# endif -# include -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR _cdecl _export -# endif -# endif -# if defined (__BORLANDC__) -# if (__BORLANDC__ >= 0x0500) && defined (WIN32) -# include -# define ZEXPORT __declspec(dllexport) WINAPI -# define ZEXPORTRVA __declspec(dllexport) WINAPIV -# else -# if defined (_Windows) && defined (__DLL__) -# define ZEXPORT _export -# define ZEXPORTVA _export -# endif -# endif -# endif -#endif - -#if defined (__BEOS__) -# if defined (ZLIB_DLL) -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -#endif - -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif -#ifndef ZEXTERN -# define ZEXTERN extern -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(MACOS) && !defined(TARGET_OS_MAC) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#ifdef HAVE_UNISTD_H -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# define z_off_t off_t -#endif -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif -#ifndef z_off_t -# define z_off_t long -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(inflate_blocks,"INBL") -# pragma map(inflate_blocks_new,"INBLNE") -# pragma map(inflate_blocks_free,"INBLFR") -# pragma map(inflate_blocks_reset,"INBLRE") -# pragma map(inflate_codes_free,"INCOFR") -# pragma map(inflate_codes,"INCO") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_flush,"INFLU") -# pragma map(inflate_mask,"INMA") -# pragma map(inflate_set_dictionary,"INSEDI2") -# pragma map(inflate_copyright,"INCOPY") -# pragma map(inflate_trees_bits,"INTRBI") -# pragma map(inflate_trees_dynamic,"INTRDY") -# pragma map(inflate_trees_fixed,"INTRFI") -# pragma map(inflate_trees_free,"INTRFR") -#endif - -#endif /* _ZCONF_H */ diff --git a/zlib/zlib.h b/zlib/zlib.h deleted file mode 100644 index 52cb529f6..000000000 --- a/zlib/zlib.h +++ /dev/null @@ -1,893 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.1.4, March 11th, 2002 - - Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef _ZLIB_H -#define _ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.1.4" - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: ascii or binary */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -/* Allowed flush values; see deflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 -/* Possible values of the data_type field */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - 0.1% larger than avail_in plus 12 bytes. If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may some - introduce some output latency (reading input without producing any output) - except when forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much - output as possible to the output buffer. The flushing behavior of inflate is - not specified for values of the flush parameter other than Z_SYNC_FLUSH - and Z_FINISH, but the current implementation actually flushes as much output - as possible anyway. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster routine - may be used for the single inflate() call. - - If a preset dictionary is needed at this point (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the - dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise - it sets strm->adler to the adler32 checksum of all output produced - so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or - an error code as described below. At the end of the stream, inflate() - checks that its computed adler32 checksum is equal to that saved by the - compressor and returns Z_STREAM_END only if the checksum is correct. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect - adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent - (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if no progress is possible or if there was not - enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR - case, the application may then call inflateSync to look for a good - compression block. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match). Filtered data consists mostly of small values with a - somewhat random distribution. In this case, the compression algorithm is - tuned to compress them better. The effect of Z_FILTERED is to force more - Huffman coding and less string matching; it is somewhat intermediate - between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects - the compression ratio but not the correctness of the compressed output even - if it is not set appropriately. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. - - Upon return of this function, strm->adler is set to the Adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The Adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. If a compressed stream with a larger window size is given as - input, inflate() will return with the error code Z_DATA_ERROR instead of - trying to allocate a larger window. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the Adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect Adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ - - -typedef voidp gzFile; - -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h". (See the description - of deflateInit2 for more information about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - const voidp buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); - -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) - - -#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int err)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); - -#ifdef __cplusplus -} -#endif - -#endif /* _ZLIB_H */ diff --git a/zlib/zutil.c b/zlib/zutil.c deleted file mode 100644 index dfc38ec14..000000000 --- a/zlib/zutil.c +++ /dev/null @@ -1,225 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -struct internal_state {int dummy;}; /* for buggy compilers */ - -#ifndef STDC -extern void exit OF((int)); -#endif - -const char *z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -#ifdef DEBUG - -# ifndef verbose -# define verbose 0 -# endif -int z_verbose = verbose; - -void z_error (m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(err) - int err; -{ - return ERR_MSG(err); -} - - -#ifndef HAVE_MEMCPY - -void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - -#ifdef __TURBOC__ -#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) -/* Small and medium model in Turbo C are for now limited to near allocation - * with reduced MAX_WBITS and MAX_MEM_LEVEL - */ -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} -#endif -#endif /* __TURBOC__ */ - - -#if defined(M_I86) && !defined(__32BIT__) -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* MSC */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - if (opaque) items += size - size; /* make compiler happy */ - return (voidpf)calloc(items, size); -} - -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ diff --git a/zlib/zutil.h b/zlib/zutil.h deleted file mode 100644 index 718ebc15b..000000000 --- a/zlib/zutil.h +++ /dev/null @@ -1,220 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2002 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id$ */ - -#ifndef _Z_UTIL_H -#define _Z_UTIL_H - -#include "zlib.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#ifdef MSDOS -# define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include -# endif -# else /* MSC or DJGPP */ -# include -# endif -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -#endif - -#ifdef WIN32 /* Window 95 & Windows NT */ -# define OS_CODE 0x0b -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0F -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# define fdopen(fd,type) _fdopen(fd,type) -#endif - - - /* Common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#ifdef HAVE_STRERROR - extern char *strerror OF((int)); -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -#if defined(pyr) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include - extern int z_verbose; - extern void z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, - uInt len)); -voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -void zcfree OF((voidpf opaque, voidpf ptr)); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -#endif /* _Z_UTIL_H */ -- cgit v1.2.3 From 9214e1b282100980789bd6eb9c9940ed02689c2d Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 19 Oct 2002 07:55:27 +0000 Subject: Merged Top directory of NewPG with GnuPG. --- AUTHORS | 117 ------ ChangeLog | 1096 +++++------------------------------------------- Makefile.am | 51 +-- NEWS | 1312 +++------------------------------------------------------- README | 802 ++++++++++++----------------------- THANKS | 231 +---------- TODO | 127 ++---- acinclude.m4 | 829 ++++++++++++------------------------- autogen.sh | 162 +++++++- configure.ac | 1096 +++++++++++------------------------------------- 10 files changed, 1149 insertions(+), 4674 deletions(-) diff --git a/AUTHORS b/AUTHORS index 4b367357a..e69de29bb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,117 +0,0 @@ -Program: GnuPG -Maintainer: Werner Koch -Bug reports: -Security related bug reports: - - -Authors -======= - -Birger Langkjer Translations [da] - -Daniel Resare Translations [sv] - -David Shaw Assignment - (all in keyserver/, - a lot of changes in g10/ see the ChangeLog, - bug fixes here and there) - -Dokianakis Theofanis Translations [el] - -Edmund GRIMLEY EVANS Translations [eo] - -Gal Quri Translations [fr] - (fixed a lot of typos) - -Gregory Steuck Translations [ru] - -Ivo Timmermans Translations [nl] - -Jacobo Tarri'o Barreiro Translations [gl] - -Janusz Aleksander Urbanowicz Translations [po] - -Magda Procha'zkova' Translations [cs] - -Michael Roth Assignment - (wrote cipher/des.c., changes and bug fixes all over the place) - -Marco d'Itri Translations [it] - -Matthew Skala Disclaimer - (wrote cipher/twofish.c) - -Niklas Hernaeus Disclaimer - (weak key patches) - -Nilgun Belma Buguner Translations [tr] - -Nils Ellmenreich Assignment - (configure.in, cipher/rndlinux.c, FAQ) - -Paul Eggert - (configuration macros for LFS) - -Pedro Morais Translations [pt_PT] - -Rmi Guyomarch Assignment - (g10/compress.c, g10/encr-data.c, - g10/free-packet.c, g10/mdfilter.c, g10/plaintext.c, util/iobuf.c) - -Stefan Bellon Assignment - (All patches to support RISC OS) - -Timo Schulz Assignment - (util/w32reg.c, g10/passphrase.c, g10/hkp.c) - -Tedi Heriyanto Translations [id] - -Thiago Jung Bauermann Translations [pt_BR] -Rafael Caetano dos Santos Translations [pt_BR] - -Toomas Soome Translations [et] - -Urko Lusa Translations [es_ES] - -Walter Koch Translations [de] - -Werner Koch Assignment - (started the whole thing) - -Yosiaki IIDA Translations [ja] - - - -Other legal information -======================= - -This program uses the zlib compression library written by -Jean-loup Gailly and Mark Adler. - -Most of the stuff in mpi has been taken from the GMP library by -Torbjorn Granlund . - -The Rijndael implementation (cipher/rijndael.c) is based on the -public domain reference code provided for the AES selection process. -The Rijndael algorithm is due to Joan Daemen and Vincent Rijmen. - -The files cipher/rndunix.c and cipher/rndw32.c are based on rndunix.c -and rndwin32.c from cryptlib. -Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. - -The files in debian/ are by James Troup who is the Debian maintainer -for GnuPG. - -The RPM specs file scripts/gnupg.spec has been contributed by -several people. - - Copyright 1998, 1999, 2000, 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. - diff --git a/ChangeLog b/ChangeLog index 8e547477d..7595565e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,1083 +1,199 @@ -2002-10-18 Werner Koch +2002-10-19 Werner Koch - Released 1.3.0. - - * configure.ac: Changed version number comments. - (ALL_LINGUAS): Removed all except for de. During development it - might not be a good idea to keep all of them - they get outdated - too soon and diff files will be far too large. - -2002-10-17 David Shaw - - * README: Multiple A record rotation works with MINGW32 now, and - clarify how it works with LDAP. - -2002-10-16 David Shaw - - * README: Some typo fixes from Florian Weimer, and bump version - number. - -2002-10-15 David Shaw - - * NEWS: Some 1.3 notes. - -2002-10-12 Werner Koch - - * configure.ac (NAME_OF_DEV_URANDOM): Use /dev/urandom for - NetBSD. Reported by Christian Biere. - -2002-10-07 David Shaw - - * configure.ac: OpenLDAP 2.0.27 changed the dependencies again. - Add a "LDAPLIBS" variable so users can try and suggest the right - dependencies for their platform. - -2002-10-02 David Shaw - - * configure.ac: Add an --enable-old-tiger, to revert back to the - old OID. - -2002-09-27 David Shaw - - * configure.ac: Remove --enable-tiger, as TIGER is now always - enabled. - -2002-09-25 David Shaw - - * configure.ac: Add NETLIBS to EGDLIBS when using EGD as EGD uses - sockets. - -2002-09-24 David Shaw - - * THANKS: Remove duplicate. - - * NEWS: Bring in cosmetic changes from stable branch. - - * configure.ac: Figure out whether the LDAP library supports - ldap_get_option, ld_errno, or neither. - -2002-09-19 David Shaw - - * configure.ac: Try linking LDAP as just -lldap as it seems very - recent OpenLDAPs (>=2.0.23) support that. - -2002-09-14 David Shaw - - * configure.ac: Try linking LDAP without -lresolv first, just in - case the platform has libresolv, but doesn't actually need it to - use LDAP. - -2002-09-12 David Shaw - - * NEWS: Note that the old IDEA plugin won't work with post-1.1.90 - gpg. - -2002-09-12 David Shaw - - * configure.ac: Remove --enable-external-hkp as this is always on - now. Add --disable-hkp to match the other - --disable-{keyservertype} options. - - * NEWS, configure.ac: Move to devel version 1.3. - -2002-09-11 Werner Koch - - Released 1.1.92. - - * configure.ac (random_modules): The default random module for - system lacking a /dev/random is now auto selected at runtime. - -2002-09-09 David Shaw - - * NEWS: typo. - - * configure.ac: Add a link test for LDAP without -lresolv for - HPUX. Remove "hstrerror" test as it is no longer needed. - -2002-09-02 Werner Koch - - * README: Removed the note about a development version so that we - later don't forget this. Minor other changes. - -2002-08-29 Werner Koch - - * configure.ac (random_modules): Reworked the code to select the - random module. Define USE_ALL_RANDOM_MODULES for value all. - -2002-08-27 David Shaw - - * configure.ac: Check type of mode_t. - - * NEWS: Clarify that --libexecdir is a configure option. - - * configure.ac: Check for hstrerror. - -2002-08-19 David Shaw - - * NEWS: Document new ways to enable MDC, and change in automatic - compression disabling. - - * configure.ac: No such thing as the "none" random gather any - longer. + NewPG (Aegypten project) to GnuPG merge. -2002-08-08 David Shaw +2002-09-20 Werner Koch - * configure.ac: Add an --enable-tiger. + Released 0.9.2. - * NEWS: Clarify new permission checks. +2002-09-05 Neal H. Walfield -2002-08-07 David Shaw + * configure.ac: Check for makeinfo. - * configure.ac: If the static IDEA cipher is present, disable - dynamic loading. Also fix backwards grammar of keyserver - exec-path CHECKING message. +2002-09-03 Neal H. Walfield -2002-08-05 Werner Koch + * autogen.sh (have_version): New function. Generalize and + simplify logic for finding and determining the versions of GNU + programs. Use it. - * configure.ac: Bumbed version number. +2002-08-23 Werner Koch -2002-08-04 Werner Koch + Released 0.9.1. - Released 1.1.91. + * acinclude.m4 (AM_PATH_LIBGCRYPT): Updated from Libgcrypt. + (AM_PATH_OPENSC): Strip non-digits from the micro version. - * configure.ac (ALL_LINGUAS): Added Catalan. +2002-08-21 Werner Koch -2002-08-02 Werner Koch + Released 0.9.0. - * configure.ac: Removed all extension stuff but keep the tests for - dlopen. We don't need to figure out the flags required. All - stuff is now statically loaded. + * configure.ac: Changed the default homedir to .gnupg. + * README-alpha: Removed. -2002-07-30 David Shaw +2002-08-19 Werner Koch - * README, configure.ac: --with-exec-path is now clarified into - --disable-keyserver-path + * acinclude.m4: Removed -lpcsclite from KSBA_LIBS; copy+paste bug. - * NEWS: changes since 1.1.90. +2002-08-13 Werner Koch -2002-07-24 David Shaw + * acinclude.m4 (AM_PATH_OPENSC, AM_PATH_KSBA): New. + * configure.ac: Use them. - * configure.ac: Include a GNUPG_LIBEXECDIR in g10defs.h, as well - as a SUBST for Makefiles. +2002-08-10 Werner Koch -2002-07-22 Timo Schulz - - * configure.ac: Replace the 'c:/' variables with 'c:\' due - to the fact we already use '\' in the remaining code. + Released 0.3.10. -2002-07-08 David Shaw - - * configure.ac: Add --with-mailprog to override the use of - sendmail with another MTA. We can use anything that follows the - "$MAILPROG -t" convention. - -2002-07-04 David Shaw - - * configure.ac: --enable-exec-path should be a 'with'. Fix 'no' - cases of --with-exec-path and --with-photo-viewer. - - * README: Document --disable-exec, --disable-photo-viewers, - --disable-keyserver-helpers, --enable-exec-path, and - --with-photo-viewer. - - * configure.ac: Add --with-photo-viewer to lock the viewer at - compile time and --disable-keyserver-helpers and - --disable-photo-viewers to allow disabling one without disabling - the other. + * configure.ac (NEED_LIBKSBA_VERSION): Require 0.4.4. Add support + for gettext. -2002-07-03 David Shaw +2002-07-22 Werner Koch - * configure.ac: Allow setting USE_EXEC_PATH to lock the exec-path - to a fixed value. + * configure.ac: Check for ftello and provide a replacement. 2002-07-01 Werner Koch - * configure.ac: Set version number to 1.1.91. - - Released 1.1.90. + Released 0.3.9. - * INSTALL: Replaced by generic install file. - * README: Marked as development version and moved most stuff of - the old INSTALL file to here. - -2002-06-30 Werner Koch - - * configure.ac: Link W32 version against libwsock32. + * README: Short note on how to export in pkcs-12 format. 2002-06-29 Werner Koch - * configure.ac (development_version): New. - (HAVE_DEV_RANDOM_IOCTL): Removed test for it; it was never used. + * configure.ac: Define --with options to set the default location + of the agent, scdaemon, pinentry and dirmngr. - * BUGS, AUTHORS: Add a note on how to send security related bug - reports. +2002-06-27 Werner Koch -2002-06-20 David Shaw + * README: Short blurb on how to import a PKCS-12 file. - * NEWS: changes since 1.0.7. + * configure.ac (AH_BOTTOM): New to define some constants. - * configure.ac: Set new version number (1.1.90), and fix Solaris - compiler flags for shared objects. +2002-06-25 Werner Koch -2002-06-11 David Shaw - - * configure.ac: Move -lsocket and -lnsl checks before LDAP link - tests so they work properly on Solaris. Noted by David Champion. - Also, check for the Mozilla LDAP library if the OpenLDAP library - check fails. Put -lsocket and -lnsl in NETLIBS rather than LIBS - so not all programs are forced to link to them. + Released 0.3.8. -2002-06-05 David Shaw - - * configure.ac: Add a switch for the experimental external HKP - keyserver interface. - -2002-05-22 Werner Koch + * configure.ac (NEED_LIBGCRYPT_VERSION): Set to 1.1.8. - * configure.ac: Check for strcasecmp and strncasecmp. Removed - stricmp and memicmp checks. +2002-06-12 Werner Koch -2002-05-08 David Shaw + * configure.ac (NEED_LIBKSBA_VERSION): We need 0.4.3 now. - * configure.ac: If LDAP comes up unusable, try #including - before giving up. Old versions of OpenLDAP require that. +2002-06-04 Werner Koch -2002-05-03 David Shaw + Released 0.3.7. - * configure.ac: In g10defs.h, use \ for the directory separator - when HAVE_DOSISH_SYSTEM is on. +2002-05-21 Werner Koch - * configure.ac: Add --disable-exec flag to disable all remote - program execution. --disable-exec implies --disable-ldap and - --disable-mailto. Also look in /usr/lib for sendmail. If - sendmail is not found, do not default - just fail. + * configure.ac: We now require libgcrypt 1.1.7 and libksba 0.4.2. -2002-04-30 David Shaw +2002-05-14 Werner Koch - * configure.ac: Try and link to a sample LDAP program to check if - the LDAP we're about to use is really sane. The most common - problem (using a very old OpenLDAP), could be fixed with an extra - #include, but this would not be very portable to other LDAP - libraries. + * doc/: New + * configure.ac, Makefile.am: Added doc/ -2002-04-29 Werner Koch +2002-05-03 Werner Koch - Released 1.0.7. - - * README: Fixed some minor things. + Released 0.3.6. 2002-04-25 Werner Koch - * configure.ac: Check for locale.h and setlocale - -2002-04-24 David Shaw - - * Update NEWS with recent changes. - -2002-04-19 Werner Koch - - Released 1.0.6e snapshot. - -2002-04-12 Werner Koch - - * configure.ac: Add a warning note to the definition of the - EXTSEP macros. - -2002-04-09 Werner Koch - - * configure.ac (ALL_LINGUAS): Added Czech, Galician and Greek - translations. s/es_ES/es/. - -2002-03-06 Werner Koch - - * configure.ac (ALL_LINGUAS): s/pt_PT/pt/ - -2002-03-04 David Shaw - - * Add a AC_DEFINE(_GNU_SOURCE). Since this is always defined in - config.h, the various autoconf tests should be tested with it - enabled. This also works around a compiler warning caused by a - minor header bug in glibc 2.1 that causes fseeko to be defined - when building gpg, but not when tested for in configure. + * configure.ac: Check for setlocale. -2002-03-03 Werner Koch +2002-04-24 Marcus Brinkmann - Release 1.0.6d snapshot. + * configure.ac: Check for locale.h. -2002-01-04 David Shaw +2002-04-15 Werner Koch - * NEWS: about symmetric messages and fixed file sizes. - -2001-12-22 Werner Koch - - Released 1.0.6c snapshot. + Released 0.3.5. - * configure.ac (AH_BOTTOM): Moved EXEC_TEMPFILE_ONLY to here. - - * acconfig.h: Removed, it should no longer be used. - -2001-12-21 David Shaw - - * Add an acconfig.h to define EXEC_TEMPFILE_ONLY on platforms that - can't do fork/exec. - -2001-12-21 Werner Koch - - * Makefile.am (dist-hook): We should also look in include for - distfiles. - (EXTRA_DIST): Remove VERSION because it is generated by dist-hook. - -2001-12-20 David Shaw - - * configure.ac: replacement function for mkdtemp() - -2001-12-19 David Shaw - - * configure.ac: Check for stat() - -2001-12-19 Werner Koch - - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Support Cygwin target - * configure.ac [CYGWIN32]: Don't build tiger. By Disastry. - -2001-12-18 Werner Koch - - * Makefile.am (SUBDIRS): Add keyserver. - (dist-hook): Only look in mpi and scripts for distfiles; this way - we don't include those of a stale "make dist" directory. - -2001-10-23 Werner Koch - - Released 1.0.6b snapshot. - -2001-10-22 Werner Koch - - * configure.ac: Fixed for automake 1.5 - -2001-10-17 Werner Koch - - * README: Removed note on local_ID. - -2001-09-28 Werner Koch - - * configure.ac: From now on add a string "-cvs" to the version to - indicate that this is a pre-release of the given version number. - -2001-09-26 Werner Koch - - * configure.ac [MINGW32]: Switched from wsock.dll to ws2_32.dll. - -2001-09-09 Werner Koch - - * configure.ac: autoconf changed the name of the maintainer mode - flag, so that not all warnings where enabled. Fixed that. - Reported by Dirk Meyer. - -2001-09-07 Werner Koch - - * configure.ac: Test for strsep(). - -2001-09-03 Werner Koch - - * configure.ac: Removed GDBM tests. - -2001-08-23 Werner Koch - - * configure.in (AC_FUNC_FSEEKO): Add. - (AC_CHECK_FUNCS): Remove fseeko. By Paul Eggert . - -2001-08-22 Werner Koch - - * configure.ac (gethrtime): Enhanced the test by running a test - program. - * INSTALL: Removed the note about Solaris problems because the - above test should catch this. - -2001-08-20 Werner Koch - - * acinclude.m4: Add check for plock if mlock is broken. - * configure.ac: Use regular tests for -lsocket and -lnsl, - more thorough test for gethrtime, allow specifying the path to - the zlib library if it is not in the default compiler/linker - search path, use ${datadir}. All these test enhancements are by - Albert Chin. - - * configure.ac: Set some compiler flags for dec-osf and hpux. By - Tim Mooney. - - * configure.ac: Create g10defs.h with EXTSEP_S et al. - -2001-08-03 Werner Koch - - * configure.ac (VERSION,PACKAGE): Fixed quoting. - -2001-07-26 Werner Koch - - * configure.ac: Finally got it running with the new autoconf. Had - to define PACKAGE and VERSION and to add -I.. to each Makefile.am. - -2001-07-09 Werner Koch - - Migrated to autoconf 2.50. - * acinclude.m4: Removed the temporary LFS macros and GNUPG_LINK_FILES. - * acconfig.h: Removed - * configure.in: Replaced by... - * configure.ac: and modified for use with autoconf 2.50, use a - literal string for the version number. Replaced GNUPG_LINK_FILES - with AC_CONFIG_LINKS and moved some informational messages to the end. - * VERSION: Removed. - * Makefile.am (DISTCLEANFILES): gettext is better now; no more - need to remove the libintl.h symlink. - (dist-hook): Create VERSION file. - -2001-06-08 Werner Koch - - * configure.in (DYNLINK_MOD_CFLAGS): Use -shared with dec-osf. - Reported by Chris Adams. Merged some cases. - -2001-05-29 Werner Koch - - Released version 1.0.6. - -2001-05-28 Werner Koch - - * configure.in (BUILD_INCLUDED_LIBINTL): Set to no for W32. - -2001-04-29 Werner Koch - - Released version 1.0.5. - -2001-04-28 Werner Koch - - Updated all copyright notices. - -2001-04-27 Werner Koch - - * README: Removed a few outdated paragraphs. - -2001-04-17 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_DOCBOOK_TO_TEXI): New. - (GNUPG_CHECK_TYPEDEF): Define _GNU_SOURCE because we will use it - anyway. - - * configure.in: Use it here. - - * configure.in (ALL_LINGUAS): Add Estonian translation by Toomas Soome. - (use_m_debug): Removed --enable-m-debug because it does not work - anymore. - -2001-04-06 Werner Koch - - * configure.in (ALL_LINGUAS): Add Turkish translation. Thanks - to Nilgun Belma Buguner. - -2001-03-18 Werner Koch - - * configure.in: Hardwire the use of -lsocket for some - systems. Thanks to Reinhard Wobst. - -2001-03-13 Werner Koch - - * configure.in: Add copyright notice and -lwsock32. - -2001-03-12 Werner Koch - - * INSTALL: Add a note to VPATH builds. - -2001-03-08 Werner Koch - - * debian/: Applied update from James. - - Added copyright and license notices to some more files. - -2001-01-18 Werner Koch - - * configure.in: Removed tool definitions for MingW32 - -2000-11-17 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_FAQPROG): Do not prinnt the warning. - -2000-11-11 Paul Eggert - - Actually Paul's patches are dated 2000-20-17; I applied them today - and merged some ChangeLog entries (wk@gnupg.org). + * NEWS: Started to describe release notes. - * configure.in (AC_SYS_LARGEFILE): Add. - (try_large_file): Remove. All uses removed. - (AC_CHECK_FUNCS): Remove fopen64 and fstat64. - - * acinclude.m4 (AC_SYS_LARGEFILE_TEST_INCLUDES, - AC_SYS_LARGEFILE_MACRO_VALUE, AC_SYS_LARGEFILE): New macros, - taken from GNU tar. - - * configure.in (AC_CHECK_FUNCS): Add fseeko. - -2000-10-17 Werner Koch - - * configure.in: Disabled fopen64 checks for Solaris and HPUX. - -2000-10-13 Werner Koch - - * configure.in: Append mpi/mpi-asm-defs.h to g10defs.h - -2000-10-09 Werner Koch - - * acinclude.m4: Changed wording of the faqprog.pl warning. - -Wed Oct 4 15:50:18 CEST 2000 Werner Koch - - * configure.in: Set DYNLINK_MOD_CFLAGS for Irix. It seems that Irix - needs the -shared flag. In 1.1 we are going to use libtool, so this - module stuff will get redesigned anyway. Suggested by Jeff Long. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_FAQPROG): New. - * configure.in: Test for this. - - * configure.in (DYNLINK_MOD_CFLAGS): Fix by David Champion. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch - - * configure.in: Check for fstat64 and fopen64 - -Wed Sep 6 14:59:09 CEST 2000 Werner Koch - - * configure.in (GNUPG_HOMEDIR): New. - -Fri Aug 25 16:05:38 CEST 2000 Werner Koch - - * configure.in: Changes to allow for Solaris random device. - By Nils Ellmenreich. - (--with-egd-socket): New. - -Wed Aug 23 19:52:51 CEST 2000 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_MLOCK): Removed that silly mkdir(). - -Wed Jul 19 11:26:43 CEST 2000 Werner Koch - - * configure.in (mingw32): Changes to allow for mingw32msvc - -Fri Jul 14 10:17:30 CEST 2000 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_MLOCK): Fixed syntax error in C code. - -Wed Jul 12 13:32:06 CEST 2000 Werner Koch - - Version 1.0.2 - -Fri Jun 9 10:09:52 CEST 2000 Werner Koch - - * configure.in: Add check for termio.h, wait unctiosn and sigaction. - -Wed Jun 7 19:19:09 CEST 2000 Werner Koch - - * acinclude.m4 (MKDIR_TAKES_ONE_ARG): Check some headers. By Gal Quri. - * configure.in (AM_INIT_AUTOMAKE): Use this now. By Gal. - -Mon Jun 5 12:37:43 CEST 2000 Werner Koch - - * acnclude.m4 (GNUPG_CHECK_EXPORTDYNAMIC): Replacement for - GNUPG_CHECK_RDYNAMIC which should handle gcc with non GNU ld nicer. - Contributed by Dave Dykstra. - * configure.in (GNYPG_CHECK_RDYNAMIC): Replaced by the new check. + * configure.ac (NEED_LIBKSBA_VERSION, NEED_LIBGCRYPT_VERSION): Defined - * configure.in (AC_CHECK_AWK): Moved before the first use of AWK. Suggested - by Dave Dykstra. +2002-04-01 Werner Koch -Tue May 30 16:37:55 CEST 2000 Werner Koch + Released 0.3.4. - Version 1.0.1-ePit-1 +2002-03-18 Werner Koch -Sun May 28 13:55:17 CEST 2000 Werner Koch + Released 0.3.3. - * acinclude.m4 (GNUPG_SYS_NM_PARSE): Added BSDI support. - (GNUPG_CHECK_RDYNAMIC): Ditto. +2002-03-08 Werner Koch -Wed Apr 19 10:57:26 CEST 2000 Werner Koch + * README: Add some explanation on how to specify a user ID. - * acconfig.h (HAVE_MLOCK): Added - -Wed Mar 22 13:50:24 CET 2000 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_MLOCK): Changed the way to test for - librt. Test suggested by Jeff Long. - -Fri Mar 17 17:50:25 CET 2000 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_MLOCK): Do librt check only when - we can't link a test program. This way GNU systems don't need - to link against linrt. - (GNUPG_CHECK_IPC): Fixed use of TRY_COMPILE macro. From Tim Mooney. - -2000-03-14 12:07:54 Werner Koch (wk@habibti.openit.de) - - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add support for - DJGPP. - (GNUPG_CHECK_MLOCK): Check whether mlock sits in librt. - * configure.in: Add a test for unisgned long long. - -Tue Mar 7 18:45:31 CET 2000 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Add NetBSD. By Thomas Klausner. - * configure.in (DYNLINK_MOD_CFLAGS): Set different for NetBSD. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch - - * configure.in: Add check for clock_gettime - -Wed Feb 23 10:07:57 CET 2000 Werner Koch - - * configure.in (ALL_LINGUAS): Add nl. - -Wed Feb 16 16:25:09 CET 2000 Werner Koch - - * configure.in (ALL_LINGUAS): Add Esperanto. - -Wed Feb 16 14:09:00 CET 2000 Werner Koch - - * configure.in (ALL_LINGUAS): Add sv and ja. - - * AUTHORS: Converted to a more compact format. - - * INSTALL: Wrote a note about a Solaris problem. - -Thu Feb 10 17:39:44 CET 2000 Werner Koch - - * configure.in: Use /usr/local for CFLAGS and LDFLAGS when - target is freebsd. By Rmi. - -Thu Jan 13 19:31:58 CET 2000 Werner Koch - - * configure.in: Do not set development version when the version has - a dash in it. Suggested by Dave Dykstra. - -Thu Dec 16 10:07:58 CET 1999 Werner Koch - - * VERSION: Set to 1.0.1. - - * configure.in: Removed substitution for doc/gph/Makefile. - Do all the gcc warning only in maintainer mode. - -Thu Dec 9 10:31:05 CET 1999 Werner Koch - - * INSTALL: Add a hint for AIX. By Jos Backus. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch - - * configure.in (dlopen): Use CHECK_FUNC for a test of dlopen in libc. - Suggested by Alexandre Oliva. - (-Wall): Moved the settting of gcc warning options near to the end - so that tests don't get confused. Suggested by Paul D. Smith. - -Mon Nov 22 11:14:53 CET 1999 Werner Koch - - * BUGS: Replaced content with a link to the online list. - -Fri Nov 12 20:33:19 CET 1999 Werner Koch - - * README: Fixed a type and add a note about the gnupg-i18n ML. - -Thu Oct 28 16:08:20 CEST 1999 Werner Koch - - * acinclude.m4, configure.in (GNUPG_CHECK_GNUMAKE): New. - -Sat Oct 9 20:34:41 CEST 1999 Werner Koch - - * configure.in: Tweaked handling of random modules and removed - dummy support for libgcrypt. - * Makefile.am: Removed libgcrypt support. - * cgrypt/ : Removed. - - * Makefile.am: Removed libtool. - -Fri Oct 8 20:32:01 CEST 1999 Werner Koch - - * configure.in: Fixed quoting in test for development version. - - * THANKS: Add entries for Michael, Brenno and J Horacio who did - very nice Howto documents - I apoligize for forgetting to mention them - earlier. - -Tue Sep 28 20:54:37 CEST 1999 Werner Koch - - * textfilter.c (copy_clearsig_text) [__MINGW32__): Use CR,LF. - -Fri Sep 17 12:56:42 CEST 1999 Werner Koch - - * configure.in: Add "-lcap" when capabilities are requested. - Add the conditional CROSS_COMPILING. - * Makefile.am: Don't use checks when CROSS_COMPILING. - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch - - * configure.in (ALL_LINGUAS): Add pt_PT. - - * configure.in: Some tweaks for cross compiling under MingW32 - * acconfig.h (USE_STATIC_RNDW32): New. - -Tue Sep 7 17:08:10 CEST 1999 Werner Koch - - * VERSION: Set to 1.0.0. - -Mon Sep 6 19:59:08 CEST 1999 Werner Koch - - * configure.in: Create makefile in doc/gph - - * acinclude.m4 (GNUPG_FUNC_MKDIR_TAKES_ONE_ARG): New - * configure.in: use the above. - -Thu Sep 2 16:40:55 CEST 1999 Werner Koch - - * VERSION: Set to 0.9.11. - -Tue Aug 31 17:20:44 CEST 1999 Werner Koch - - * configure.in: Minor changes to the OS/2 and Mingw32 system labels. - Add a printable name for Hurd. - -Mon Aug 30 20:38:33 CEST 1999 Werner Koch - - * configure.in: Some support for DJGPP (Mark Elbrecht) - -Wed Aug 4 10:34:46 CEST 1999 Werner Koch - - * VERSION: Set to 0.9.10. - -Mon Jul 26 09:34:46 CEST 1999 Werner Koch - - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): remove init of ac_cv_... - - * Makefile.am (DISCLEANFILES): New - -Fri Jul 23 13:53:03 CEST 1999 Werner Koch - - * VERSION: Set to 0.9.9. - - * configure.in: Print a notice when rndunix is used. - -Thu Jul 15 10:15:35 CEST 1999 Werner Koch - - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Fixed last modification. - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch - - * Makefile.am: Support for libtool. - * configure.in: Ditto. - -Tue Jun 29 21:44:25 CEST 1999 Werner Koch - - * configure.in (use_local_zlib): The lost dollar is back. - - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add EMX case. - * configure.in: Another variant of the MX vendor string - - * configure.in (--with-capabilities): Some test code (Remi). - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Support for HPUX and IRIX. - * configure.in (HAVE_DL_SHL_LOAD): New for HPUX (Dave Dykstra). - - * VERSION: Now 0.9.8 - -Wed Jun 16 20:16:21 CEST 1999 Werner Koch - - * configure.in: Add test for docbook-to-man - -Tue Jun 15 12:21:08 CEST 1999 Werner Koch - - * acinclude.m4 (GNUPG_SYS_NM_PARSE): Support for {net,free}bsd, - -Thu Jun 10 14:18:23 CEST 1999 Werner Koch - - * configure.in (ZLIB,GDBM): Check both, header and lib. - -Sat Jun 5 15:30:33 CEST 1999 Werner Koch - - * pkclist.c (key_present_in_pk_list): New (Michael). - -Tue May 25 19:50:32 CEST 1999 Werner Koch - - * configure.in (IS_DEVELOPMENT_VERSION): Fixed detection. - -Sun May 23 14:20:22 CEST 1999 Werner Koch - - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): assume yes when - cross-compiling. - -Mon May 17 21:54:43 CEST 1999 Werner Koch - - * configure.in (socket): Fix for Unisys by Katsuhiro Kondou. - -Sat May 8 19:28:08 CEST 1999 Werner Koch - - * NEWS: Add a marker line which I forgot to do for 0.9.6. - -Thu May 6 14:18:17 CEST 1999 Werner Koch - - * README: Minor updates - - * VERSION: Now 0.9.6 - -Thu Apr 8 09:35:53 CEST 1999 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Fix for - amiga-openbsd (Peter Reich) - (GNUPG_PROG_NM): Ditto - -Wed Apr 7 20:51:39 CEST 1999 Werner Koch - - * Makefile.am (g10defs.h): Removed. - * configure.in (AC_OUTPUT_COMMANDS): Create g10defs.h - -Sat Mar 20 12:55:33 CET 1999 Werner Koch - - * VERSION: Now 0.9.5 - -Sun Mar 14 19:34:36 CET 1999 Werner Koch - - * acinclude.m4 (AM_SYS_SYMBOL_UNDERSCORE): Removed because it is - now in the latest libtool. - -Thu Mar 11 16:39:46 CET 1999 Werner Koch - - * configure.in: Removed the need for libtool - -Mon Mar 8 20:47:17 CET 1999 Werner Koch - - * configure.in (DLSYM_NEEDS_UNDERSCORE): Replaced. - * acinclude.in (AM_SYS_SYMBOL_UNDERSCORE): New. - - * VERSION: Now 0.9.4 - -Sun Feb 28 19:11:00 CET 1999 Werner Koch - - * configure.in (dld): Test disabled. - -Fri Feb 26 17:55:41 CET 1999 Werner Koch - - * encode.c (encode_simple): temporary fix. - -Wed Feb 24 11:07:27 CET 1999 Werner Koch - - * configure.in: New option --enable-static-rnd. - -Mon Feb 22 20:04:00 CET 1999 Werner Koch - - * BUGS: Now we assign bug numbers. - * OBUGS: New to keep rack o fixed bugs (CVS only) - -Fri Feb 19 18:01:54 CET 1999 Werner Koch - - * VERSION: Released 0.9.3 - -Fri Feb 19 15:49:15 CET 1999 Werner Koch - - * acinclude.m4: Removed gettext macros. - -Tue Feb 16 14:10:02 CET 1999 Werner Koch - - * configure.in (socket): Check for -lsocket and -lnsl. - (osf4): Disable all warnings for DEC's cc. - (-Wall): Add more warning options for gcc - -Sat Feb 13 12:04:43 CET 1999 Werner Koch - - * configure.in: Changed detection of compiler flags. - * intl/ : Removed directory - -Wed Feb 10 17:15:39 CET 1999 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Fix for freebsd 2.2 - - * configure.in: a lot of changes to allow selection of modules. - Add support for OS/2. - - * acinclude.m4: add some more caching - - * README: Spelling and grammar corrections (John A. Martin) - * INSTALL: Ditto. - -Wed Jan 20 21:40:21 CET 1999 Werner Koch - - * configure.in: --enable-m-guard is now default - -Wed Jan 13 12:49:36 CET 1999 Werner Koch - - * INSTALL: Applied new information how to build rpms by Fabio Coatti - * Makefile.in (gnupg.spec): Changed the names. - -Tue Jan 12 11:17:18 CET 1999 Werner Koch - - * config.links (m68k-atari-mint): New - -Tue Jan 12 09:17:19 CET 1999 Gal Quri - - * all: Fixed typos all over the place - -Sat Jan 9 16:02:23 CET 1999 Werner Koch - - * configure.in: Add a way to statically link rndunix - -Sun Jan 3 15:28:44 CET 1999 Werner Koch - - * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): New. - * configure.in (DYNLOAD_CFLAGS): Use result from CHECK_RDYNAMIC - -Wed Dec 23 13:18:14 CET 1998 Werner Koch - - * README: Replaced the command overview with a short intro. - -Sat Dec 12 18:40:32 CET 1998 Werner Koch - - * configure.in: Add check for dlopen in libc (Greg Troxel) - and a new define - * acconfig.h (DLSYM_NEEDS_UNDERSCORE): New. - -Thu Dec 10 20:15:36 CET 1998 Werner Koch - - * acinclude.m (GNUPG_CHECK_PIC): New - * configure.in, acinclude.m4: Renamed all WK_ to GNUPG_ - -Tue Dec 8 15:09:29 CET 1998 Werner Koch - - * VERSION: Set to 0.4.5 - -Wed Nov 25 12:38:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * configure.in (USE_RNDLINUX): New. - -Fri Nov 20 19:34:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * VERSION: Released 0.4.4 - - * configure.in (try_asm_modules): For option --disable-asm - -Tue Nov 10 19:32:40 1998 Werner Koch (wk@isil.d.shuttle.de) - - * configure.in (MPI_SFLAGS): New. - -Tue Nov 10 13:44:53 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ABOUT-NLS: New - * configure.in (AC_REVISION): New. - -Sun Nov 8 18:20:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * VERSION: Set to 0.4.3 - -Sun Oct 25 19:49:37 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am (g10defs.h): New macro GNUPG_DATADIR. - -Wed Oct 21 17:24:24 1998 Werner Koch (wk@isil.d.shuttle.de) - - * configure.in: Removed gettext kludge - * acinclude.m4: Add patched AM_WITH_NKS macro - -Tue Oct 20 19:03:36 1998 Werner Koch (wk@isil.d.shuttle.de) - - * configure.in: Kludge to make AM_GNU_GETTEXT work, - changed some macors to more modern versions. Also - changeg the all makefiles to remove duplicate ../intl. - * acinclude.m4: Removed the gettext stuff, as this - already comes with automake now. - -Wed Oct 14 12:11:34 1998 Werner Koch (wk@isil.d.shuttle.de) - - * configure.in (NAME_OF_DEV_RANDOM): New. - (DYNLINK_MOD_CFLAGS): New. - -Thu Oct 8 10:55:15 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.am (g10defs.h): creates include file - * acconfig.h: now includes g10defs.h - * configure.in: Removed G10_LOCALEDIR and GNUPG_LIB - -Thu Sep 17 18:49:40 1998 Werner Koch (wk@(none)) - - * Makefile.am (dist-hook): Now creates RPM file. - * scripts/gnupg.spec: New template file for RPMs - -Thu Jul 30 19:17:07 1998 Werner Koch (wk@(none)) - - * acinclude.h (WK_CHECK_IPC): New - * configure.in : Add checks for SysV IPC - -Thu Jun 25 11:18:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * configure.in (--disable-dynload): New. - -Wed Jun 10 07:48:59 1998 Werner Koch,mobil,,, (wk@tobold) - - * configure.in (GNUPG_LIBDIR): New. +2002-03-06 Werner Koch -Mon May 25 19:10:59 1998 Werner Koch (wk@isil.d.shuttle.de) + Released 0.3.2. - * rand-unix.c (fast_random_poll): fixed syntax bug. +2002-03-04 Werner Koch -Mon May 11 10:21:31 1998 Werner Koch (wk@isil.d.shuttle.de) + Released 0.3.1. - * configure.in (PRINTABLE_OS_NAME): Linux is now GNU/Linux + * README: Explained some options and files. -Tue Apr 14 19:08:05 1998 Werner Koch (wk@isil.d.shuttle.de) +2002-02-14 Werner Koch - * [all files]: Applied Matthew Skala's typo and grammar fixes. + * configure.ac: Fixed status messages related to presence of Pth. -Wed Mar 4 10:32:40 1998 Werner Koch (wk@isil.d.shuttle.de) +2002-02-13 Werner Koch - * configure.in (getrusage,gettimeofday): New tests. + * acinclude.m4 (GNUPG_SYS_SO_PEERCRED): New. + * configure.ac: use it. -Fri Feb 27 13:14:17 1998 Werner Koch (wk@isil.d.shuttle.de) +2002-02-12 Werner Koch - * configure.in (--disable-m-guard): New. + * configure.ac: Check for PTH. Provide replacement fucntions for + apsrintf and fopencookie. -Thu Feb 26 17:09:27 1998 Werner Koch (wk@isil.d.shuttle.de) + * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): New. - * configure.in, acinclude.m4, intl/, po/: New macros taken - from GNOME, switched to automake 1.2f +2002-02-07 Werner Koch -Thu Feb 26 09:05:46 1998 Werner Koch (wk@isil.d.shuttle.de) + Released 0.3.0. - * configure.in (doc/Makefile): New + * configure.ac: Require libgcrypt 1.1.6. -Thu Feb 26 07:40:47 1998 Werner Koch (wk@isil.d.shuttle.de) +2002-02-01 Marcus Brinkmann - * configure.in: Changed gettext stuff + * configure.ac (KSBA_CONFIG): Remove superfluous x in front of + variable. -Wed Feb 25 11:44:10 1998 Werner Koch (wk@isil.d.shuttle.de) +2002-01-26 Werner Koch - * checks/*test : restructured the directory. + * 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. -Tue Feb 24 15:59:12 1998 Werner Koch (wk@isil.d.shuttle.de) + * scd/ : New. Added to Makefile and configure. + * configure.ac: Check for libopensc + * Makefile.am: Build scd only when libopensc is available - * configure.in: Changed the name of the package to GNUPG and - chnaged several other names too. +2002-01-23 Werner Koch -Wed Feb 18 17:36:45 1998 Werner Koch (wk@isil.d.shuttle.de) + * configure.ac (mkdtemp): See whether we have to provide a + replacement. - * Makefile.am (checks): New. +2001-12-18 Werner Koch -Sat Feb 14 15:37:55 1998 Werner Koch (wk@isil.d.shuttle.de) + Released 0.0.0. - * configure.in (mpi_config_done): Removed asm links caching. +2001-12-17 Werner Koch -Sat Feb 14 14:02:20 1998 Werner Koch (wk@isil.d.shuttle.de) + * acinclude.m4: Add AM_PATH_LIBGCRYPT macro. + * configure.ac: and use it here. Figure out the location of libksba - * configure.in (PRINTABLE_OS_NAME): New. - * acconfig.h: Likewise. +2001-12-15 Werner Koch -Fri Feb 13 19:43:41 1998 Werner Koch (wk@isil.d.shuttle.de) + * configure.ac (missing_dir): Bail out if asprintf and fopencookie + are not available. - * configure.in : Fixed zlib stuff - * Makefile.am: Likewise +2001-12-04 Werner Koch + * configure.ac (HAVE_JNLIB_LOGGING): always define it. - Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + 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 @@ -1086,5 +202,5 @@ Fri Feb 13 19:43:41 1998 Werner Koch (wk@isil.d.shuttle.de) 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. - + diff --git a/Makefile.am b/Makefile.am index 427d7b639..ccfc98fb2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,8 @@ -# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -# +# 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 @@ -18,37 +19,29 @@ ## Process this file with automake to produce Makefile.in -if CROSS_COMPILING -checks = +EXTRA_DIST = autogen.sh + +if BUILD_GPGSM +sm = sm else -checks = checks +sm = +endif +if BUILD_AGENT +agent = agent +else +agent = +endif +if BUILD_SCDAEMON +scd = scd +else +scd = endif -SUBDIRS = intl zlib util mpi cipher tools g10 keyserver po doc ${checks} -EXTRA_DIST = PROJECTS BUGS config.h.in -DISTCLEANFILES = g10defs.h - -# Add all the files listed in "distfiles" files to the distribution, -# apply version numbers to some files and create a VERSION file which -# we need for the Prereq: patch file trick. -dist-hook: - @set -e; \ - for file in `cd $(top_srcdir); \ - find scripts mpi 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 - @set -e; \ - sed -e 's/@pkg_version@/$(VERSION)/g' \ - $(top_srcdir)/scripts/gnupg.spec.in \ - > $(distdir)/scripts/gnupg.spec - echo "$(VERSION)" > $(distdir)/VERSION - +SUBDIRS = intl jnlib assuan common kbx ${sm} ${agent} ${scd} po doc tests +dist-hook: + @set -e; echo "$(VERSION)" > $(distdir)/VERSION diff --git a/NEWS b/NEWS index 6bea3d211..a2dc8126e 100644 --- a/NEWS +++ b/NEWS @@ -1,1305 +1,95 @@ -Noteworthy changes in version 1.3.1 (unreleased) +Noteworthy changes in version 0.9.3 (unreleased) ------------------------------------------------ -Noteworthy changes in version 1.3.0 (2002-10-18) +Noteworthy changes in version 0.9.2 (2002-09-20) ------------------------------------------------ - * The last piece of internal keyserver support has been removed, - and now all keyserver access is done via the keyserver plugins. - There is also a newer keyserver protocol used between GnuPG and - the plugins, so plugins from earlier versions of GnuPG may not - work properly. + * The default directory structure is created if it does no exists. - * The HKP keyserver plugin supports the new machine-readable key - listing format for those keyservers that provide it. + * A few more diagnostics and a minor bug fixes. - * When using a HKP keyserver with multiple DNS records (such as - wwwkeys.pgp.net which has the addresses of multiple servers - around the world), try all records until one succeeds. Note - that it depends on the LDAP library used whether the LDAP - keyserver plugin does this as well. - * The library dependencies for OpenLDAP seem to change fairly - frequently, and GnuPG's configure script cannot guess all the - combinations. Use ./configure LDAPLIBS="-L libdir -l libs" to - override the script and use the libraries selected. - - * Secret keys generated with --export-secret-subkeys are now - indicated in key listings with a '#' after the "sec", and in - --with-colons listings by showing no capabilities (no lowercase - characters). - - * --trusted-key has been un-obsoleted, as it is useful for adding - ultimately trusted keys from the config file. It is identical - to using --edit and "trust" to change a key to ultimately - trusted. - -Noteworthy changes in version 1.1.92 (2002-09-11) -------------------------------------------------- - - * [IMPORTANT] The default configuration file is now - ~/.gnupg/gpg.conf. If an old ~/.gnupg/options is found it will - still be used. This change is required to have a more - consistent naming scheme with forthcoming tools. - - * The use of MDCs have increased. A MDC will be used if the - recipients directly request it, if the recipients have AES, - AES192, AES256, or TWOFISH in their cipher preferences, or if - the chosen cipher has a blocksize not equal to 64 bits - (currently this is also AES, AES192, AES256, and TWOFISH). - - * GnuPG will no longer automatically disable compression when - processing an already-compressed file unless a MDC is being - used. This is to give the message a certain amount of - resistance to the chosen-ciphertext attack while communicating - with other programs (most commonly PGP earlier than version 7.x) - that do not support MDCs. - - * The option --interactive now has the desired effect when - importing keys. - - * The file permission and ownership checks on files have been - clarified. Specifically, the homedir (usually ~/.gnupg) is - checked to protect everything within it. If the user specifies - keyrings outside this homedir, they are presumed to be shared - keyrings and therefore *not* checked. Configuration files - specified with the --options option and the IDEA cipher - extension specified with --load-extension are checked, along - with their enclosing directories. - - * The configure option --with-static-rnd=auto allows to build gpg - with all available entropy gathering modules included. At - runtime the best usable one will be selected from the list - linux, egd, unix. This is also the default for systems lacking - a /dev/random device. - - * The default character set is now taken from the current locale; - it can still be overridden by the --charset option. Using the - option -vvv shows the used character set. - - * [REMOVED] --emulate-checksum-bug and --emulate-3des-s2k-bug have - been removed. - - -Noteworthy changes in version 1.1.91 (2002-08-04) -------------------------------------------------- - - * All modules are now linked statically; the --load-extension - option is in general not useful anymore. The only exception is - to specify the deprecated idea cipher. - - * The IDEA plugin has changed. Previous versions of the IDEA - plugin will no longer work with GnuPG. However, the current - version of the plugin will work with earlier GnuPG versions. - - * When using --batch with one of the --delete-key commands, the - key must be specified by fingerprint. See the man page for - details. - - * There are now various ways to restrict the ability GnuPG has to - exec external programs (for the keyserver helpers or photo ID - viewers). Read the README file for the complete list. +Noteworthy changes in version 0.9.1 (2002-08-23) +------------------------------------------------ - * New export option to leave off attribute packets (photo IDs) - during export. This is useful when exporting to HKP keyservers - which do not understand attribute packets. + * Minor fixes. - * New import option to repair during import the HKP keyserver - mangling multiple subkeys bug. Note that this cannot completely - repair the damaged key as some crucial data is removed by the - keyserver, but it does at least give you back one subkey. This - is on by default for keyserver --recv-keys, and off by default - for regular --import. - * The keyserver helper programs now live in - /usr/[local/]libexec/gnupg by default. If you are upgrading - from 1.0.7, you might want to delete your old copies in - /usr/[local/]bin. If you use an OS that does not use libexec - for whatever reason, use configure --libexecdir=/usr/local/lib - to place the keyserver helpers there. +Noteworthy changes in version 0.9.0 (2002-08-21) +------------------------------------------------ - * The LDAP keyserver handler now works properly with very old - (version 1) LDAP keyservers. + * The default homedir has changed from ~/.gnupg-test to ~/.gnupg. + * To run gpg-agent or scdaemon in the background, the option --daemon + must be used. -Noteworthy changes in version 1.1.90 (2002-07-01) +Noteworthy changes in version 0.3.10 (2002-08-10) ------------------------------------------------- - * New commands: --personal-cipher-preferences, - --personal-digest-preferences, and - --personal-compress-preferences allow the user to specify which - algorithms are to be preferred. Note that this does not permit - using an algorithm that is not present in the recipient's - preferences (which would violate the OpenPGP standard). This - just allows sorting the preferences differently. - - * New "group" command to refer to several keys with one name. - - * A warning is issued if the user forces the use of an algorithm - that is not listed in the recipient's preferences. - - * Full revocation key (aka "designated revoker") support. - - * The preferred hash algorithms on a key are consulted when - encrypting a signed message to that key. Note that this is - disabled by default by a SHA1 preference in - --personal-digest-preferences. + * A key may be specified by a short fingerprint; either the last 4 or + 8 bytes of the SHA-1 fingerprint. - * --cert-digest-algo allows the user to specify the hash algorithm - to use when signing a key rather than the default SHA1 (or MD5 - for PGP2 keys). Do not use this feature unless you fully - understand the implications of this. + * Very basic regression tests implemented. - * --pgp7 mode automatically sets all necessary options to ensure - that the resulting message will be usable by a user of PGP 7.x. + * Signing using more than one key works on the commandline and in + server mode. - * New --attribute-fd command for frontends and scripts to get the - contents of attribute packets (i.e. photos) + * --import does now try to import all certificates up the chain; this + usually works only when the new option --auto-issuer-key-retrieve + is also used. - * In expert mode, the user can now re-sign a v3 key with a v4 - self-signature. This does not change the v3 key into a v4 key, - but it does allow the user to use preferences, primary ID flags, - etc. + * New command --delete-key. Note that in contrast to gpg this is not + interactive. - * Significantly improved photo ID support on non-unixlike - platforms. - - * The version number has jumped ahead to 1.1.90 to skip over the - old version 1.1 and to get ready for the upcoming 1.2. - - * ElGamal sign and encrypt is not anymore allowed in the key - generation dialog unless in expert mode. RSA sign and encrypt - has been added with the same restrictions. - - * [W32] Keyserver access does work with Windows NT. - - -Noteworthy changes in version 1.0.7 (2002-04-29) +Noteworthy changes in version 0.3.9 (2002-07-01) ------------------------------------------------ - * Secret keys are now stored and exported in a new format which - uses SHA-1 for integrity checks. This format renders the - Rosa/Klima attack useless. Other OpenPGP implementations might - not yet support this, so the option --simple-sk-checksum creates - the old vulnerable format. - - * The default cipher algorithm for encryption is now CAST5, - default hash algorithm is SHA-1. This will give us better - interoperability with other OpenPGP implementations. - - * Symmetric encrypted messages now use a fixed file size if - possible. This is a tradeoff: it breaks PGP 5, but fixes PGP 2, - 6, and 7. Note this was only an issue with RFC-1991 style - symmetric messages. - - * Photographic user ID support. This uses an external program to - view the images. - - * Enhanced keyserver support via keyserver "plugins". GnuPG comes - with plugins for the NAI LDAP keyserver as well as the HKP email - keyserver. It retains internal support for the HKP HTTP - keyserver. - - * Nonrevocable signatures are now supported. If a user signs a - key nonrevocably, this signature cannot be taken back so be - careful! - - * Multiple signature classes are usable when signing a key to - specify how carefully the key information (fingerprint, photo - ID, etc) was checked. - - * --pgp2 mode automatically sets all necessary options to ensure - that the resulting message will be usable by a user of PGP 2.x. - - * --pgp6 mode automatically sets all necessary options to ensure - that the resulting message will be usable by a user of PGP 6.x. - - * Signatures may now be given an expiration date. When signing a - key with an expiration date, the user is prompted whether they - want their signature to expire at the same time. - - * Revocation keys (designated revokers) are now supported if - present. There is currently no way to designate new keys as - designated revokers. - - * Permissions on the .gnupg directory and its files are checked - for safety. - - * --expert mode enables certain silly things such as signing a - revoked user id, expired key, or revoked key. - - * Some fixes to build cleanly under Cygwin32. - - * New tool gpgsplit to split OpenPGP data formats into packets. - - * New option --preserve-permissions. - - * Subkeys created in the future are not used for encryption or - signing unless the new option --ignore-valid-from is used. - - * Revoked user-IDs are not listed unless signatures are listed too - or we are in verbose mode. - - * There is no default comment string with ascii armors anymore - except for revocation certificates and --enarmor mode. - - * The command "primary" in the edit menu can be used to change the - primary UID, "setpref" and "updpref" can be used to change the - preferences. - - * Fixed the preference handling; since 1.0.5 they were erroneously - matched against against the latest user ID and not the given one. + * The protect-tool does now make use of the gpg-agent to query a + passphrase. - * RSA key generation. + * The default path of the daemons are now set to a more common value + and there are configure options to change them. - * Merged Stefan's patches for RISC OS in. See comments in - scripts/build-riscos. - - * It is now possible to sign and conventional encrypt a message (-cs). - - * The MDC feature flag is supported and can be set by using - the "updpref" edit command. - - * The status messages GOODSIG and BADSIG are now returning the primary - UID, encoded using %XX escaping (but with spaces left as spaces, - so that it should not break too much) - - * Support for GDBM based keyrings has been removed. - - * The entire keyring management has been revamped. - - * The way signature stati are store has changed so that v3 - signatures can be supported. To increase the speed of many - operations for existing keyrings you can use the new - --rebuild-keydb-caches command. - - * The entire key validation process (trustdb) has been revamped. - See the man page entries for --update-trustdb, --check-trustdb - and --no-auto-check-trustdb. - - * --trusted-keys is again obsolete, --edit can be used to set the - ownertrust of any key to ultimately trusted. - - * A subkey is never used to sign keys. - - * Read only keyrings are now handled as expected. - - -Noteworthy changes in version 1.0.6 (2001-05-29) +Noteworthy changes in version 0.3.8 (2002-06-25) ------------------------------------------------ - * Security fix for a format string bug in the tty code. - - * Fixed format string bugs in all PO files. + * The protect-tool has now a feature to extract a private RSA key + from a PKCS-12 file and convert it into the gpg-agent format. - * Removed Russian translation due to too many bugs. The FTP - server has an unofficial but better translation in the contrib - directory. + * A bunch of big fixes and changes for improved interoperability. - * Fixed expire time calculation and keyserver access. + * gpgsm can now create non-detached signatures. - * The usual set of minor bug fixes and enhancements. - - * non-writable keyrings are now correctly handled. - - -Noteworthy changes in version 1.0.5 (2001-04-29) +Noteworthy changes in version 0.3.7 (2002-06-04) ------------------------------------------------ - * WARNING: The semantics of --verify have changed to address a - problem with detached signature detection. --verify now ignores - signed material given on stdin unless this is requested by using - a "-" as the name for the file with the signed material. Please - check all your detached signature handling applications and make - sure that they don't pipe the signed material to stdin without - using a filename together with "-" on the the command line. - - * WARNING: Corrected hash calculation for input data larger than - 512M - it was just wrong, so you might notice bad signature in - some very big files. It may be wise to keep an old copy of - GnuPG around. - - * Secret keys are no longer imported unless you use the new option - --allow-secret-key-import. This is a kludge and future versions will - handle it in another way. - - * New command "showpref" in the --edit-key menu to show an easier - to understand preference listing. - - * There is now the notation of a primary user ID. For example, it - is printed with a signature verification as the first user ID; - revoked user IDs are not printed there anymore. In general the - primary user ID is the one with the latest self-signature. - - * New --charset=utf-8 to bypass all internal conversions. - - * Large File Support (LFS) is now working. - - * New options: --ignore-crc-error, --no-sig-create-check, - --no-sig-cache, --fixed_list_mode, --no-expensive-trust-checks, - --enable-special-filenames and --use-agent. See man page. - - * New command --pipemode, which can be used to run gpg as a - co-process. Currently only the verification of detached - signatures are working. See doc/DETAILS. - - * Keyserver support for the W32 version. + * More user friendly output for --list-keys without --with-colons. + New --list-sigs to show the certification path. - * Rewritten key selection code so that GnuPG can better cope with - multiple subkeys, expire dates and so. The drawback is that it - is slower. + * gpg-agent handles concurrent connections. - * A whole lot of bug fixes. + * gpgsm --import can now handle certs-only messages. - * The verification status of self-signatures are now cached. To - increase the speed of key list operations for existing keys you - can do the following in your GnuPG homedir (~/.gnupg): - cp pubring.gpg pubring.gpg.save && gpg --export-all >x && \ - rm pubring.gpg && gpg --import x - Only v4 keys (i.e not the old RSA keys) benefit from this caching. - - * New translations: Estonian, Turkish. - - -Noteworthy changes in version 1.0.4 (2000-10-17) +Noteworthy changes in version 0.3.6 (2002-05-03) ------------------------------------------------ - * Fixed a serious bug which could lead to false signature verification - results when more than one signature is fed to gpg. This is the - primary reason for releasing this version. - - * New utility gpgv which is a stripped down version of gpg to - be used to verify signatures against a list of trusted keys. - - * Rijndael (AES) is now supported and listed with top preference. - - * --with-colons now works with --print-md[s]. + * Some cleanups. -Noteworthy changes in version 1.0.3 (2000-09-18) +Noteworthy changes in version 0.3.5 (2002-04-15) ------------------------------------------------ + + * Checks key usage and uses the authorithyKeyIdentifier. - * Fixed problems with piping to/from other MS-Windows software - - * Expiration time of the primary key can be changed again. - - * Revoked user IDs are now marked in the output of --list-key - - * New options --show-session-key and --override-session-key - to help the British folks to somewhat minimize the danger - of this Orwellian RIP bill. - - * New options --merge-only and --try-all-secrets. - - * New configuration option --with-egd-socket. - - * The --trusted-key option is back after it left us with 0.9.5 - - * RSA is supported. Key generation does not yet work but will come - soon. - - * CAST5 and SHA-1 are now the default algorithms to protect the key - and for symmetric-only encryption. This should solve a couple - of compatibility problems because the old algorithms are optional - according to RFC2440 - - * Twofish and MDC enhanced encryption is now used. PGP 7 supports - this. Older versions of GnuPG don't support it, so they should be - upgraded to at least 1.0.2 - - -Noteworthy changes in version 1.0.2 (2000-07-12) ----------------------------------------------- - - * Fixed expiration handling of encryption keys. - - * Add an experimental feature to do unattended key generation. - - * The user is now asked for the reason of revocation as required - by the new OpenPGP draft. - - * There is a ~/.gnupg/random_seed file now which saves the - state of the internal RNG and increases system performance - somewhat. This way the full entropy source is only used in - cases were it is really required. - Use the option --no-random-seed-file to disable this feature. - - * New options --ignore-time-conflict and --lock-never. - - * Some fixes for the W32 version. - - * The entropy.dll is not anymore used by the W32 version but replaced - by code derived from Cryptlib. - - * Encryption is now much faster: About 2 times for 1k bit keys - and 8 times for 4k keys. - - * New encryption keys are generated in a way which allows a much - faster decryption. - - * New command --export-secret-subkeys which outputs the - the _primary_ key with it's secret parts deleted. This is - useful for automated decryption/signature creation as it - allows to keep the real secret primary key offline and - thereby protecting the key certificates and allowing to - create revocations for the subkeys. See the FAQ for a - procedure to install such secret keys. - - * Keygeneration now writes to the first writeable keyring or - as default to the one in the homedirectory. Prior versions - ignored all --keyring options. - - * New option --command-fd to take user input from a file descriptor; - to be used with --status-fd by software which uses GnuPG as a backend. - - * There is a new status PROGRESS which is used to show progress during - key generation. - - * Support for the new MDC encryption packets. To create them either - --force-mdc must be use or cipher algorithm with a blocksize other - than 64 bits is to be used. --openpgp currently disables MDC packets - entirely. This option should not yet be used. - - * New option --no-auto-key-retrieve to disable retrieving of - a missing public key from a keyserver, when a keyserver has been set. - - * Danish translation - -Noteworthy changes in version 1.0.1 (1999-12-16) ------------------------------------ - - * New command --verify-files. New option --fast-list-mode. - - * $http_proxy is now used when --honor-http-proxy is set. - - * Fixed some minor bugs and the problem with conventional encrypted - packets which did use the gpg v3 partial length headers. - - * Add Indonesian and Portugese translations. - - * Fixed a bug with symmetric-only encryption using the non-default 3DES. - The option --emulate-3des-s2k-bug may be used to decrypt documents - which have been encrypted this way; this should be done immediately - as this workaround will be remove in 1.1 - - * Can now handle (but not display) PGP's photo IDs. I don't know the - format of that packet but after stripping a few bytes from the start - it looks like a JPEG (at least my test data). Handling of this - package is required because otherwise it would mix up the - self signatures and you can't import those keys. - - * Passing non-ascii user IDs on the commandline should now work in all - cases. - - * New keys are now generated with an additional preference to Blowfish. - - * Removed the GNU Privacy Handbook from the distribution as it will go - into a separate one. - - -Noteworthy changes in version 1.0.0 (1999-09-07) ------------------------------------ - - * Add a very preliminary version of the GNU Privacy Handbook to - the distribution (lynx doc/gph/index.html). - - * Changed the version number to GnuPG 2001 ;-) - - -Noteworthy changes in version 0.9.11 ------------------------------------- - - * UTF-8 strings are now correctly printed (if --charset is set correctly). - Output of --with-colons remains C-style escaped UTF-8. - - * Workaround for a problem with PGP 5 detached signature in textmode. - - * Fixed a problem when importing new subkeys (duplicated signatures). - -Noteworthy changes in version 0.9.10 ------------------------------------- - - * Some strange new options to help pgpgpg - - * Cleaned up the dox a bit. - - -Noteworthy changes in version 0.9.9 ------------------------------------ - - * New options --[no-]utf8-strings. - - * New edit-menu commands "enable" and "disable" for entire keys. - - * You will be asked for a filename if gpg cannot deduce one. - - * Changes to support libtool which is needed for the development - of libgcrypt. - - * New script tools/lspgpot to help transferring assigned - trustvalues from PGP to GnuPG. - - * New commands --lsign-key and made --sign-key a shortcut for --edit - and sign. - - * New options (#122--126 ;-) --[no-]default-recipient[-self], - --disable-{cipher,pubkey}-algo. See the man page. - - * Enhanced info output in case of multiple recipients and fixed exit code. - - * New option --allow-non-selfsigned-uid to work around a problem with - the German IN way of separating signing and encryption keys. - - -Noteworthy changes in version 0.9.8 ------------------------------------ - - * New subcommand "delsig" in the edit menu. - - * The name of the output file is not anymore the one which is - embedded in the processed message, but the used filename with - the extension stripped. To revert to the old behaviour you can - use the option --use-embedded-filename. - - * Another hack to cope with pgp2 generated detached signatures. - - * latin-2 character set works (--charset=iso-8859-2). - - * New option --with-key-data to list the public key parameters. - New option -N to insert notations and a --set-policy-url. - A couple of other options to allow reseting of options. - - * Better support for HPUX. - - -Noteworthy changes in version 0.9.7 ------------------------------------ - - * Add some work arounds for a bugs in pgp 2 which led to bad signatures - when used with canonical texts in some cases. - - * Enhanced some status outputs. - -Noteworthy changes in version 0.9.6 ------------------------------------ - - * Twofish is now statically linked by default. The experimental 128 bit - version is now disabled. Full support will be available as soon as - the OpenPGP WG has decided on an interpretation of rfc2440. - - * Dropped support for the ancient Blowfish160 which is not OpenPGP. - - * Merged gpgm and gpg into one binary. - - * Add "revsig" and "revkey" commands to the edit menu. It is now - possible to revoke signature and subkeys. - - -Noteworthy changes in version 0.9.5 ------------------------------------ - - * New command "lsign" in the keyedit menu to create non-exportable - signatures. Removed --trusted-keys option. - - * A bunch of changes to the key validation code. - - * --list-trust-path now has an optional --with-colons format. - - * New command --recv-keys to import keys from an keyserver. - - -Noteworthy changes in version 0.9.4 ------------------------------------ - - * New configure option --enable-static-rnd=[egd|linux|unix|none] - to select a random gathering module for static linking. - - * The original text is now verbatim copied to a cleartext signed message. - - * Bugfixes but there are still a couple of bugs. - - -Noteworthy changes in version 0.9.3 ------------------------------------ - - * Changed the internal design of getkey which now allows a - efficient lookup of multiple keys and add a word match mode. - - * New options --[no-]encrypt-to. - - * Some changes to the configure stuff. Switched to automake 1.4. - Removed intl/ from CVS, autogen.sh now uses gettextize. - - * Preferences now include Twofish. Removed preference to Blowfish with - a special hack to suppress the "not listed in preferences" warning; - this is to allow us to switch completely to Twofish in the near future. - - * Changed the locking stuff. - - * Print all user ids of a good signature. - - -Noteworthy changes in version 0.9.2 ------------------------------------ - - * add some additional time warp checks. - - * Option --keyserver and command --send-keys to utilize HKP servers. - - * Upgraded to zlib 1.1.3 and fixed an inflate bug - - * More cleanup on the cleartext signatures. - - -Noteworthy changes in version 0.9.1 ------------------------------------ - - * Polish language support. - - * When querying the passphrase, the key ID of the primary key is - displayed along with the one of the used secondary key. - - * Fixed a bug occurring when decrypting pgp 5 encrypted messages, - fixed an infinite loop bug in the 3DES code and in the code - which looks for trusted signatures. - - * Fixed a bug in the mpi library which caused signatures not to - compare okay. - - * Rewrote the handling of cleartext signatures; the code is now - better maintainable (I hope so). - - * New status output VALIDSIG only for valid signatures together - with the fingerprint of the signer's key. - - -Noteworthy changes in version 0.9.0 ------------------------------------ - - * --export does now only exports rfc2440 compatible keys; the - old behaviour is available with --export-all. - Generation of v3 ElGamal (sign and encrypt) keys is not longer - supported. - - * Fixed the uncompress bug. - - * Rewrote the rndunix module. There are two environment variables - used for debugging now: GNUPG_RNDUNIX_DBG give the file to write - debugging information (use "-" for stdout) and if GNUPG_RNDUNIX_DBGALL - is set, all programs which are only tried are also printed. - - * New option --escape-from-lines to "dash-escape" "From " lines to - prevent mailers to change them to ">From ". This is not enabled by - default because it is not in compliance with rfc2440 - however, you - should turn it on. - - -Noteworthy changes in version 0.4.5 ------------------------------------ - - * The keyrings and the trustdb is now locked, so that - other GnuPG processes won't damage these files. You - may want to put the option --lock-once into your options file. - - * The latest self-signatures are now used; this enables --import - to see updated preferences etc. - - * Import of subkeys should now work. - - * Random gathering modules may now be loaded as extensions. Add - such a module for most Unices but it is very experimental! - - * Brazilian language support. - - -Noteworthy changes in version 0.4.4 ------------------------------------ - - * Fixed the way the key expiration time is stored. If you have - an expiration time on your key you should fix it with --edit-key - and the command "expire". I apologize for this inconvenience. - - * Add option --charset to support "koi8-r" encoding of user ids. - (Not yet tested). - - * Preferences should now work again. You should run - "gpgm --check-trustdb \*" to rebuild all preferences. - - * Checking of certificates should now work but this needs a lot - of testing. Key validation values are now cached in the - trustdb; they should be recalculated as needed, but you may - use --check-trustdb or --update-trustdb to do this. - - * Spanish translation by Urko Lusa. - - * Patch files are from now on signed. See the man page - for the new option --not-dash-escaped. - - * New syntax: --edit-key [] - If you run it without --batch the commands are executed and then - you are put into normal mode unless you use "quit" or "save" as - one of the commands. When in batch mode, the program quits after - the last command, so you have to use "save" if you did some changes. - It does not yet work completely, but may be used to list so the - keys etc. - - -Noteworthy changes in version 0.4.3 ------------------------------------ - - * Fixed the gettext configure bug. - - * Kludge for RSA keys: keyid and length of a RSA key are - correctly reported, but you get an error if you try to use - this key (If you do not have the non-US version). - - * Experimental support for keyrings stored in a GDBM database. - This is *much* faster than a standard keyring. You will notice - that the import gets slower with time; the reason is that all - new keys are used to verify signatures of previous inserted - keys. Use "--keyring gnupg-gdbm:". This is - not (yet) supported for secret keys. - - * A Russian language file in the distribution (alternatives are in - the contrib directory of the FTP servers) - - * commandline option processing now works as expected for GNU programs - with the exception that you can't mix options and normal arguments. - - * Now --list-key lists all matching keys. This is needed in some - other places too. - - -Noteworthy changes in version 0.4.2 ------------------------------------ - - * This is only a snapshot: There are still a few bugs. - - * Fixed this huge memory leak. - - * Redesigned the trust database: You should run "gpgm --check-trustdb". - New command --update-trustdb, which adds new key from the public - keyring into your trustdb - - * Fixed a bug in the armor code, leading to invalid packet errors. - (a workaround for this was to use --no-armor). The shorten line - length (64 instead of 72) fixes a problem with pgp5 and keyservers. - - * comment packets are not anymore generated. "--export" filters - them out. One Exception: The comment packets in a secret keyring - are still used because they carry the factorization of the public - prime product. - - * --import now only looks for KEYBLOCK headers, so you can now simply - remove the "- " in front of such a header if someone accidently signed - such a message or the keyblock is part of a cleartext signed message. - - * --with-colons now lists the key expiration time and not anymore - the valid period. - - * Some keyblocks created with old releases have a wrong sequence - of packets, so that the keyservers don't accept these keys. - Simply using "--edit-key" fixes the problem. - - * New option --force-v3-sigs to generate signed messages which are - compatible to PGP 5. - - * Add some code to support DLD (for non ELF systems) - but this is - not tested because my BSD box is currently broken. - - * New command "expire" in the edit-key menu. - - - -Noteworthy changes in version 0.4.1 ------------------------------------ - * A secondary key is used when the primary key is specified but cannot - be used for the operation (if it is a sign-only key). - - * GNUPG can now handle concatenated armored messages: There is still a - bug if different kinds of messages are mixed. - - * Iterated+Salted passphrases now work. If want to be sure that PGP5 - is able to handle them you may want to use the options - "--s2k-mode 3 --s2k-cipher-algo cast5 --s2k-digest-algo sha1" - when changing a passphrase. - - * doc/OpenPGP talks about OpenPGP compliance, doc/HACKING gives - a few hints about the internal structure. - - * Checked gnupg against the August 1998 draft (07) and I believe - it is in compliance with this document (except for one point). - - * Fixed some bugs in the import merging code and rewrote some - code for the trustdb. - - -Noteworthy changes in version 0.4.0 ------------------------------------ - * Triple DES is now supported. Michael Roth did this piece of - needed work. We have now all the coded needed to be OpenPGP - compliant. - - * Added a simple rpm spec file (see INSTALL). - - * detached and armored signatures are now using "PGP SIGNATURE", - except when --rfc1991 is used. - - * All times which are not in the yyyy-mm-dd format are now printed - in local time. - - -Noteworthy changes in version 0.3.5 ------------------------------------ - * New option --throw-keyid to create anonymous enciphered messages. - If gpg detects such a message it tires all available secret keys - in turn so decode it. This is a gnupg extension and not in OpenPGP - but it has been discussed there and afaik some products use this - scheme too (Suggested by Nimrod Zimmerman). - - * Fixed a bug with 5 byte length headers. - - * --delete-[secret-]key is now also available in gpgm. - - * cleartext signatures are not anymore converted to LF only. - - * Fixed a trustdb problem. Run "gpgm --check-trustdb" to fix old - trust dbs. - - * Building in another directory should now work. - - * Weak key detection mechanism (Niklas Hernaeus). - - -Noteworthy changes in version 0.3.4 ------------------------------------ - * New options --comment and --set-filename; see g10/OPTIONS - - * yes/no, y/n localized. - - * Fixed some bugs. - -Noteworthy changes in version 0.3.3 ------------------------------------ - * IMPORTANT: I found yet another bug in the way the secret keys - are encrypted - I did it the way pgp 2.x did it, but OpenPGP - and pgp 5.x specify another (in some aspects simpler) method. - To convert your secret keys you have to do this: - 1. Build the new release but don't install it and keep - a copy of the old program. - 2. Disable the network, make sure that you are the only - user, be sure that there are no Trojan horses etc .... - 3. Use your old gpg (version 0.3.[12]) and set the - passphrases of ALL your secret keys to empty! - (gpg --change-passphrase your-user-id). - 4. Save your ownertrusts (see the next point) - 5. rm ~/.gnupg/trustdb.gpg - 6. install the new version of gpg (0.3.3) - 7. For every secret key call "gpg --edit-key your-user-id", - enter "passwd" at the prompt, follow the instructions and - change your password back, enter "save" to store it. - 8. Restore the ownertrust (see next point). - - * The format of the trust database has changed; you must delete - the old one, so gnupg can create a new one. - IMPORTANT: Use version 0.3.[12] to save your assigned ownertrusts - ("gpgm --list-ownertrust >saved-trust"); then build this new version - and restore the ownertrust with this new version - ("gpgm --import-ownertrust saved-trust"). Please note that - --list-ownertrust has been renamed to --export-ownertrust in this - release and it does now only export defined ownertrusts. - - * The command --edit-key now provides a commandline driven menu - which can be used for various tasks. --sign-key is only an - an alias to --edit-key and maybe removed in future: use the - command "sign" of this new menu - you can select which user ids - you want to sign. - - * Alternate user ids can now be created an signed. - - * Owner trust values can now be changed with --edit-key (trust) - - * GNUPG can now run as a coprocess; this enables sophisticated - frontends. tools/shmtest.c is a simple sample implementation. - This needs some more work: all tty_xxx() are to be replaced - by cpr_xxx() and some changes in the display logics is needed. - - * Removed options --gen-prime and --gen-random. - - * Removed option --add-key; use --edit-key instead. - - * Removed option --change-passphrase; use --edit-key instead. - - * Signatures are now checked even if the output file could not - be created. Command "--verify" tries to find the detached data. - - * gpg now disables core dumps. - - * compress and symmetric cipher preferences are now used. - Because there is no 3DES yet, this is replaced by Blowfish. - - * We have added the Twofish as an experimental cipher algorithm. - Many thanks to Matthew Skala for doing this work. - Twofish is the AES submission from Schneier et al.; see - "www.counterpane.com/twofish.html" for more information. - - * Started with a help system: If you enter a question mark at some - prompt; you should get a specific help for this prompt. - - * There is no more backup copy of the secret keyring. - - * A lot of new bugs. I think this release is not as stable as - the previous one. - - -Noteworthy changes in version 0.3.2 ------------------------------------ - * Fixed some bugs when using --textmode (-seat) - - * Now displays the trust status of a positive verified message. - - * Keyrings are now scanned in the sequence they are added with - --[secret-]keyring. Note that the default keyring is implicitly - added as the very first one unless --no-default-keyring is used. - - * Fixed setuid and dlopen bug. - -Noteworthy changes in version 0.3.1 ------------------------------------ - * Partial headers are now written in the OpenPGP format if - a key in a v4 packet is used. - - * Removed some unused options, removed the gnupg.sig stuff. - - * Key lookup by name now returns a key which can be used for - the desired action. - - * New options --list-ownertrust (gpgm) to make a backup copy - of the ownertrust values you assigned. - - * clear signature headers are now in compliance with OpenPGP. - -Noteworthy changes in version 0.3.0 ------------------------------------ - - * New option --emulate-checksum-bug. If your passphrase does not - work anymore, use this option and --change-passphrase to rewrite - your passphrase. - - * More complete v4 key support: Preferences and expiration time - is set into the self signature. - - * Key generation defaults to DSA/ElGamal keys, so that new keys are - interoperable with pgp5 - - * DSA key generation is faster and key generation does not anymore - remove entropy from the random generator (the primes are public - parameters, so there is really no need for a cryptographic secure - prime number generator which we had used). - - * A complete new structure for representing the key parameters. - - * Removed most public key knowledge into the cipher library. - - * Support for dynamic loading of new algorithms. - - * Moved tiger to an extension module. - - -Noteworthy changes in version 0.2.19 ------------------------------------- - - * Replaced /dev/urandom in checks with new tool mk-tdata. - - * Some assembler file cleanups; some more functions for the Alpha. - - * Tiger has now the OpenPGP assigned number 6. Because the OID has - changed, old signatures using this algorithm can't be verified. - - * gnupg now encrypts the compressed packed and not any longer in the - reverse order; anyway it can decrypt both versions. Thanks to Tom - for telling me this (not security related) bug. - - * --add-key works and you are now able to generate subkeys. - - * It is now possible to generate ElGamal keys in v4 packets to create - valid OpenPGP keys. - - * Some new features for better integration into MUAs. - - -Noteworthy changes in version 0.2.18 ------------------------------------- - - * Splitted cipher/random.c, add new option "--disable-dev-random" - to configure to support the development of a random source for - other systems. Prepared sourcefiles rand-unix.c, rand-w32.c - and rand-dummy.c (which is used to allow compilation on systems - without a random source). - - * Fixed a small bug in the key generation (it was possible that 48 bits - of a key were not taken from the random pool) - - * Add key generation for DSA and v4 signatures. - - * Add a function trap_unaligned(), so that a SIGBUS is issued on - Alphas and not the slow emulation code is used. And success: rmd160 - raised a SIGBUS. - - * Enhanced the formatting facility of argparse and changed the use of - \r,\v to @ because gettext does not like it. - - * New option "--compress-algo 1" to allow the creation of compressed - messages which are readable by PGP and "--print-md" (gpgm) to make - speed measurement easier. - - -Noteworthy changes in version 0.2.17 ------------------------------------- - - * Comment packets are now of private type 61. - - * Passphrase code still used a 160 bit blowfish key, added a - silly workaround. Please change your passphrase again - sorry. - - * Conventional encryption now uses a type 3 packet to describe the - used algorithms. - - * The new algorithm number for Blowfish is 20, 16 is still used for - encryption only; for signing it is only used when it is in a v3 packet, - so that GNUPG keys are still valid. - - -Noteworthy changes in version 0.2.16 ------------------------------------- - - * Add experimental support for the TIGER/192 message digest algorithm. - (But there is only a dummy ASN OID). - - * Standard cipher is now Blowfish with 128 bit key in OpenPGP's CFB - mode. I renamed the old cipher to Blowfish160. Because the OpenPGP - group refused to assign me a number for Blowfish160, I have to - drop support for this in the future. You should use - "--change-passphrase" to recode your current passphrase with 128 - bit Blowfish. - - -Noteworthy changes in version 0.2.15 ------------------------------------- - - * Fixed a bug with the old checksum calculation for secret keys. - If you run the program without --batch, a warning does inform - you if your secret key needs to be converted; simply use - --change-passphrase to recalculate the checksum. Please do this - soon, as the compatible mode will be removed sometime in the future. - - * CAST5 works (using the PGP's special CFB mode). - - * Again somewhat more PGP 5 compatible. - - * Some new test cases - -Noteworthy changes in version 0.2.14 ------------------------------------- - - * Changed the internal handling of keyrings. - - * Add support to list PGP 5 keyrings with subkeys - - * Timestamps of signatures are now verified. - - * A expiration time can now be specified during key generation. - - * Some speedups for Blowfish and SHA-1, rewrote SHA-1 transform. - Reduced the amount of random bytes needed for key generation in - some cases. - - -Noteworthy changes in version 0.2.13 ------------------------------------- - - * Verify of DSA signatures works. - - * Re-implemented the slower random number generator. - - -Noteworthy changes in version 0.2.12 ------------------------------------- - - * --delete-key checks that there is no secret key. The new - option --delete-secret-key maybe used to delete a secret key. - - * "-kv" now works as expected. Options "--list-{keys,sigs]" - and "--check-sigs" are now working. - - * New options "--verify" and "--decrypt" to better support integration - into MUAs (partly done for Mutt). - - * New option "--with-colons" to make parsing of key lists easier. - -Noteworthy changes in version 0.2.11 ------------------------------------- - - * GPG now asks for a recipient's name if option "-r" is not used. - - * If there is no good trust path, the program asks whether to use - the public keys anyway. - - * "--delete-key" works for public keys. What semantics shall I use - when there is a secret key too? Delete the secret key or leave him - and auto-regenerate the public key, next time the secret key is used? - -Noteworthy changes in version 0.2.10 ------------------------------------- - - * Code for the alpha is much faster (about 20 times); the data - was misaligned and the kernel traps this, so nearly all time - was used by system to trap the misalignments and to write - syslog messages. Shame on me and thanks to Ralph for - pointing me at this while drinking some beer yesterday. - - * Changed some configure options and add an option - --disable-m-guard to remove the memory checking code - and to compile everything with optimization on. - - * New environment variable GNUPGHOME, which can be used to set - another homedir than ~/.gnupg. Changed default homedir for - Windoze version to c:/gnupg. - - * Fixed detached signatures; detached PGP signatures caused a SEGV. - - * The Windoze version works (as usual w/o a strong RNG). - - -Noteworthy changes in version 0.2.9 ------------------------------------ - - * Fixed FreeBSD bug. - - * Added a simple man page. - - * Switched to automake1.2f and a newer gettext. - -Noteworthy changes in version 0.2.8 ------------------------------------ - - * Changed the name to GNUPG, the binaries are called gpg and gpgm. - You must rename rename the directory "~/.g10" to ~/.gnupg/, rename - {pub,sec}ring.g10 to {pub,sec}ring.gpg, trustdb.g10 to trustdb.gpg - and g10.sig to gnupg.sig. - - * New or changed passphrases are now salted. - - -Noteworthy changes in version 0.2.7 ------------------------------------ - - * New command "gen-revoke" to create a key revocation certificate. - - * New option "homedir" to set the homedir (which defaults to "~/.g10"). - This directory is created if it does not exists (only the last - part of the name and not the complete hierarchy) - - * Command "import" works. (Try: "finger gcrypt@ftp.guug.de|g10 --import") - - * New commands "dearmor/enarmor" for g10maint. These are mainly - used for internal test purposes. - - * Option --version now conforming to the GNU standards and lists - the available ciphers, message digests and public key algorithms. - - * Assembler code for m68k (not tested). - - * "make check" works. - -Noteworthy changes in version 0.2.6 ------------------------------------ - - * Option "--export" works. - - -Noteworthy changes in version 0.2.5 ------------------------------------ - - * Added zlib for systems which don't have it. - Use "./configure --with-zlib" to link with the static version. - - * Generalized some more functions and rewrote the encoding of - message digests into MPIs. - - * Enhanced the checkit script - - -Noteworthy changes in version 0.2.4 ------------------------------------ - - * nearly doubled the speed of the ElGamal signature verification. - - * backup copies of keyrings are created. - - * assembler stuff for Pentium; gives about 15% better performance. - - * fixed a lot of bugs. - - -Noteworthy changes in version 0.2.3 ------------------------------------ - - * Found a bug in the calculation of ELG fingerprints. This is now - fixed, but all existing fingerprints and keyids for ELG keys - are not any more valid. - - * armor should now work; including clear signed text. - - * moved some options to the new program g10maint - - * It's now 64 bit clean and runs fine on an alpha--linux. - - * Key generation is much faster now. I fixed this by using not - so strong random number for the primes (this was a bug because the - ElGamal primes are public parameters and it does not make sense - to generate them from strong random). The real secret is the x value - which is still generated from strong (okay: /dev/random) random bits. - - * added option "--status-fd": see g10/OPTIONS - - * We have secure memory on systems which support mlock(). - It is not complete yet, because we do not have signal handler - which does a cleanup in very case. - We should also check the ulimit for the user in the case - that the admin does not have set a limit on locked pages. - - * started with internationalization support. - - * The logic to handle the web of trust is now implemented. It is - has some bugs; but I'm going to change the algorithm anyway. - It works by calculating the trustlevel on the fly. It may ask - you to provide trust parameters if the calculated trust probability - is too low. I will write a paper which discusses this new approach. - - * a couple of changes to the configure script. - - * New option "--quick-random" which uses a much quicker random - number generator. Keys generated while this option is in effect - are flags with "INSECURE!" in the user-id. This is a development - only option. - - * Read support for new version packets (OpenPGP). - - * Comment packets are now of correct OpenPGP type 16. Old comment - packets written by G10 are detected because they always start with - a hash which is an invalid version byte. - - * The string "(INSECURE!)" is appended to a new user-id if this - is generated on a system without a good random number generator. + * Basic SC support for TCOS card using a patched version of OpenSC. -Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2002 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 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. + 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. diff --git a/README b/README index da477639d..93dc1c8f0 100644 --- a/README +++ b/README @@ -1,652 +1,372 @@ +NewPG is a temporary protect to work on GnuPG extensions. It will be +merged into the regular GnuPG sources for a GnuPG 2.0 release. - GnuPG - The GNU Privacy Guard - ------------------------------- - Version 1.3 +jnlib/ utility functions +assuan/ assuan protocol library +kbx/ keybox library +sm/ the gpgsm program +agent/ the gpg-agent +scd/ the smartcard daemon - Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +Libksba and Libgcrypt are required to build it. - 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. +Assuan and Keybox are both designed to be source include-able. - 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. +A texinfo manual `gnupg.info' will get installed. Some commands and +options given below. - Intro - ----- +COMMANDS +======== - GnuPG is GNU's tool for secure communication and data storage. - It can be used to encrypt data and to create digital signatures. - It includes an advanced key management facility and is compliant - with the proposed OpenPGP Internet standard as described in RFC2440. +gpgsm: +------ - GnuPG works best on GNU/Linux or *BSD systems. Most other Unices - are also supported but are not as well tested as the Free Unices. - See http://www.gnupg.org/gnupg.html#supsys for a list of systems - which are known to work. +--learn-card - See the file COPYING for copyright and warranty information. + Read tinformation about the private keys from the smartcard and + import the certificates from there. - Because GnuPG does not use use any patented algorithm it cannot be - compatible with PGP2 versions. PGP 2.x uses IDEA (which is patented - worldwide). +--export - The default algorithms are DSA and ElGamal, but RSA is also - supported. ElGamal for signing is available, but because of the - larger size of such signatures it is deprecated (Please note that - the GnuPG implementation of ElGamal signatures is *not* insecure). - Symmetric algorithms are: AES, 3DES, Blowfish, CAST5 and Twofish. - Digest algorithms available are MD5, RIPEMD160 and SHA1. + Export all certificates storein the Keybox or those specified on + the commandline. When using --armor a few informational lines are + prepended before each block. - Installation - ------------ - Please read the file INSTALL and the sections in this file - related to the installation. Here is a quick summary: +OPTIONS +======= - 1) Check that you have unmodified sources. See below on how to do - this. Don't skip it - this is an important step! +gpgsm: +------ - 2) Unpack the TAR. With GNU tar you can do it this way: - "tar xzvf gnupg-x.y.z.tar.gz" +--include-certs - 3) "cd gnupg-x.y.z" + 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 - 4) "./configure" + Chnage the deault name of the policy file - 5) "make" +--enable-policy-checks +--disable-policy-checks - 6) "make install" + By default policy checks are enabled. These options may be used to + change it. - 7) You end up with a "gpg" binary in /usr/local/bin. +--enable-crl-checks +--disable-crl-checks - 8) To avoid swapping out of sensitive data, you can install "gpg" as - suid root. If you don't do so, you may want to add the option - "no-secmem-warning" to ~/.gnupg/gpg.conf + 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 - How to Verify the Source - ------------------------ - In order to check that the version of GnuPG which you are going to - install is an original and unmodified one, you can do it in one of - the following ways: + 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 - a) If you already have a trusted Version of GnuPG installed, you - can simply check the supplied signature: + 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 envrionment varaibale DIRMNGR_INFO is not set or a running + dirmngr can't be connected. - $ gpg --verify gnupg-x.y.z.tar.gz.asc +--no-secmem-warning - This checks that the detached signature gnupg-x.y.z.tar.gz.asc - is indeed a a signature of gnupg-x.y.z.tar.gz. The key used to - create this signature is: + Don't print the warning "no secure memory" - "pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) " +--armor - If you do not have this key, you can get it from the source in - the file doc/samplekeys.asc (use "gpg --import doc/samplekeys.asc" - to add it to the keyring) or from any keyserver. You have to - make sure that this is really the key and not a faked one. You - can do this by comparing the output of: + Create PEM ecoded output. Default is binary output. - $ gpg --fingerprint 0x57548DCD +--base64 - with the fingerprint published elsewhere. + Create Base-64 encoded output; i.e. PEM without the header lines. - Please note, that you have to use an old version of GnuPG to - do all this stuff. *Never* use the version which you are going - to check! +--assume-armor + Assume the input data is PEM encoded. Default is to autodetect the + encoding but this is may fail. - b) If you don't have any of the above programs, you have to verify - the MD5 checksum: +--assume-base64 - $ md5sum gnupg-x.y.z.tar.gz + Assume the input data is plain base-64 encoded. - This should yield an output _similar_ to this: +--assume-binary - fd9351b26b3189c1d577f0970f9dcadc gnupg-x.y.z.tar.gz + Assume the input data is binary encoded. - Now check that this checksum is _exactly_ the same as the one - published via the announcement list and probably via Usenet. +--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 - Documentation - ------------- - The manual will be distributed separate under the name "gph". - An online version of the latest manual draft is available at the - GnuPG web pages: + Set the user to be used for signing. The default is the first + secret key found in the database. - http://www.gnupg.org/gph/ +--with-key-data - A list of frequently asked questions is available in GnuPG's - distibution in the file doc/FAQ and online as: + Displays extra information with the --list-keys commands. Especiall + a line tagged "grp" si printed which tells you the keygrip of a + key. This is string is for example used as the filename of the + secret key. - http://www.gnupg.org/faq.html - A couple of HOWTO documents are available online; for a listing see: - http://www.gnupg.org/docs.html#howtos +gpg-agent: +--------- - A man page with a description of all commands and options gets installed - along with the program. +--pinentry-program + Specify the PINentry program. The default value is + "../../pinentry/kpinentry/kpinentry" so you most likely want to + specify it. - Introduction - ------------ - Here is a brief overview on how to use GnuPG - it is strongly suggested - that you read the manual and other information about the use of - cryptography. GnuPG is only a tool, secure usage requires that - YOU KNOW WHAT YOU ARE DOING. +--no-grab - If you already have a DSA key from PGP 5 (they call them DH/ElGamal) - you can simply copy the pgp keyrings over the GnuPG keyrings after - running gpg once to create the correct directory. + Tel 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. - The normal way to create a key is + - gpg --gen-key - This asks some questions and then starts key generation. To create - good random numbers for the key parameters, GnuPG needs to gather - enough noise (entropy) from your system. If you see no progress - during key generation you should start some other activities such - as mouse moves or hitting on the CTRL and SHIFT keys. - Generate a key ONLY on a machine where you have direct physical - access - don't do it over the network or on a machine used also - by others - especially if you have no access to the root account. +FILES +===== - When you are asked for a passphrase use a good one which you can - easy remember. Don't make the passphrase too long because you have - to type it for every decryption or signing; but, - AND THIS IS VERY - IMPORTANT - use a good one that is not easily to guess because the - security of the whole system relies on your secret key and the - passphrase that protects it when someone gains access to your secret - keyring. A good way to select a passphrase is to figure out a short - nonsense sentence which makes some sense for you and modify it by - inserting extra spaces, non-letters and changing the case of some - characters - this is really easy to remember especially if you - associate some pictures with it. +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: - Next, you should create a revocation certificate in case someone - gets knowledge of your secret key or you forgot your passphrase +gpgsm.conf - gpg --gen-revoke your_user_id + 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. - Run this command and store the revocation certificate away. The output - is always ASCII armored, so that you can print it and (hopefully - never) re-create it if your electronic media fails. +gpg-agent.conf + + Options for gpg-agent - Now you can use your key to create digital signatures +scdaemon.conf - gpg -s file + Options for scdaemon. - This creates a file "file.gpg" which is compressed and has a - signature attached. +dirmngr.conf - gpg -sa file + Options for the DirMngr which is not part of this package and + the option file wilol most likely be moved to /etc - Same as above, but creates a file "file.asc" which is ASCII armored - and and ready for sending by mail. It is better to use your - mailers features to create signatures (The mailer uses GnuPG to do - this) because the mailer has the ability to MIME encode such - signatures - but this is not a security issue. +gpg.conf + + Options for gpg. Note that old versions of gpg use the + filename `options' instead of `gpg.conf'. - gpg -s -o out file +policies.txt - Creates a signature of "file", but writes the output to the file - "out". + A list of allowed CA policies. This file should give the + object identifiers of the policies line by line. emptry lines + and lines startung with a hash mark are ignored. - Everyone who knows your public key (you can and should publish - your key by putting it on a key server, a web page or in your .plan - file) is now able to check whether you really signed this text + ++++++++++ + 2.289.9.9 + ++++++++++ - gpg --verify file +trustlist.txt - GnuPG now checks whether the signature is valid and prints an - appropriate message. If the signature is good, you know at least - that the person (or machine) has access to the secret key which - corresponds to the published public key. + 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. - If you run gpg without an option it will verify the signature and - create a new file that is identical to the original. gpg can also - run as a filter, so that you can pipe data to verify trough it +random_seed - cat signed-file | gpg | wc -l + Used internally for keeping the state of the RNG over + invocations. - which will check the signature of signed-file and then display the - number of lines in the original file. +pubring.kbx - To send a message encrypted to someone you can use + The database file with the certificates. - gpg -e -r heine file +pubring.gpg - This encrypts "file" with the public key of the user "heine" and - writes it to "file.gpg" + The database file with the OpenPGP public keys. This will + eventually be merged with pubring.kbx - echo "hello" | gpg -ea -r heine | mail heine - - Ditto, but encrypts "hello\n" and mails it as ASCII armored message - to the user with the mail address heine. - - gpg -se -r heine file - - This encrypts "file" with the public key of "heine" and writes it - to "file.gpg" after signing it with your user id. - - gpg -se -r heine -u Suttner file - - Ditto, but sign the file with your alternative user id "Suttner" - - - GnuPG has some options to help you publish public keys. This is - called "exporting" a key, thus - - gpg --export >all-my-keys - - exports all the keys in the keyring and writes them (in a binary - format) to "all-my-keys". You may then mail "all-my-keys" as an - MIME attachment to someone else or put it on an FTP server. To - export only some user IDs, you give them as arguments on the command - line. - - To mail a public key or put it on a web page you have to create - the key in ASCII armored format - - gpg --export --armor | mail panther@tiger.int - - This will send all your public keys to your friend panther. - - If you have received a key from someone else you can put it - into your public keyring. This is called "importing" - - gpg --import [filenames] - - New keys are appended to your keyring and already existing - keys are updated. Note that GnuPG does not import keys that - are not self-signed. - - Because anyone can claim that a public key belongs to her - we must have some way to check that a public key really belongs - to the owner. This can be achieved by comparing the key during - a phone call. Sure, it is not very easy to compare a binary file - by reading the complete hex dump of the file - GnuPG (and nearly - every other program used for management of cryptographic keys) - provides other solutions. - - gpg --fingerprint - - prints the so called "fingerprint" of the given username which - is a sequence of hex bytes (which you may have noticed in mail - sigs or on business cards) that uniquely identifies the public - key - different keys will always have different fingerprints. - It is easy to compare fingerprints by phone and I suggest - that you print your fingerprint on the back of your business - card. To see the fingerprints of the secondary keys, you can - give the command twice; but this is normally not needed. - - If you don't know the owner of the public key you are in trouble. - Suppose however that friend of yours knows someone who knows someone - who has met the owner of the public key at some computer conference. - Suppose that all the people between you and the public key holder - may now act as introducers to you. Introducers signing keys thereby - certify that they know the owner of the keys they sign. If you then - trust all the introducers to have correctly signed other keys, you - can be be sure that the other key really belongs to the one who - claims to own it.. - - There are 2 steps to validate a key: - 1. First check that there is a complete chain - of signed keys from the public key you want to use - and your key and verify each signature. - 2. Make sure that you have full trust in the certificates - of all the introduces between the public key holder and - you. - Step 2 is the more complicated part because there is no easy way - for a computer to decide who is trustworthy and who is not. GnuPG - leaves this decision to you and will ask you for a trust value - (here also referenced as the owner-trust of a key) for every key - needed to check the chain of certificates. You may choose from: - a) "I don't know" - then it is not possible to use any - of the chains of certificates, in which this key is used - as an introducer, to validate the target key. Use this if - you don't know the introducer. - b) "I do not trust" - Use this if you know that the introducer - does not do a good job in certifying other keys. The effect - is the same as with a) but for a) you may later want to - change the value because you got new information about this - introducer. - c) "I trust marginally" - Use this if you assume that the - introducer knows what he is doing. Together with some - other marginally trusted keys, GnuPG validates the target - key then as good. - d) "I fully trust" - Use this if you really know that this - introducer does a good job when certifying other keys. - If all the introducer are of this trust value, GnuPG - normally needs only one chain of signatures to validate - a target key okay. (But this may be adjusted with the help - of some options). - This information is confidential because it gives your personal - opinion on the trustworthiness of someone else. Therefore this data - is not stored in the keyring but in the "trustdb" - (~/.gnupg/trustdb.gpg). Do not assign a high trust value just - because the introducer is a friend of yours - decide how well she - understands the implications of key signatures and you may want to - tell her more about public key cryptography so you can later change - the trust value you assigned. - - Okay, here is how GnuPG helps you with key management. Most stuff - is done with the --edit-key command - - gpg --edit-key - - GnuPG displays some information about the key and then prompts - for a command (enter "help" to see a list of commands and see - the man page for a more detailed explanation). To sign a key - you select the user ID you want to sign by entering the number - that is displayed in the leftmost column (or do nothing if the - key has only one user ID) and then enter the command "sign" and - follow all the prompts. When you are ready, give the command - "save" (or use "quit" to cancel your actions). - - If you want to sign the key with another of your user IDs, you - must give an "-u" option on the command line together with the - "--edit-key". - - Normally you want to sign only one user ID because GnuPG - uses only one and this keeps the public key certificate - small. Because such key signatures are very important you - should make sure that the signatories of your key sign a user ID - which is very likely to stay for a long time - choose one with an - email address you have full control of or do not enter an email - address at all. In future GnuPG will have a way to tell which - user ID is the one with an email address you prefer - because - you have no signatures on this email address it is easy to change - this address. Remember, your signatories sign your public key (the - primary one) together with one of your user IDs - so it is not possible - to change the user ID later without voiding all the signatures. - - Tip: If you hear about a key signing party on a computer conference - join it because this is a very convenient way to get your key - certified (But remember that signatures have nothing to to with the - trust you assign to a key). - - - 8 Ways to Specify a User ID - -------------------------- - There are several ways to specify a user ID, here are some examples. - - * Only by the short keyid (prepend a zero if it begins with A..F): - - "234567C4" - "0F34E556E" - "01347A56A" - "0xAB123456 - - * By a complete keyid: - - "234AABBCC34567C4" - "0F323456784E56EAB" - "01AB3FED1347A5612" - "0x234AABBCC34567C4" - - * By a fingerprint: - - "1234343434343434C434343434343434" - "123434343434343C3434343434343734349A3434" - "0E12343434343434343434EAB3484343434343434" - - The first one is MD5 the others are ripemd160 or sha1. - - * By an exact string: - - "=Heinrich Heine " - - * By an email address: - - "" - - * By word match - - "+Heinrich Heine duesseldorf" - - All words must match exactly (not case sensitive) and appear in - any order in the user ID. Words are any sequences of letters, - digits, the underscore and characters with bit 7 set. - - * Or by the usual substring: - - "Heine" - "*Heine" - - The '*' indicates substring search explicitly. - - - Batch mode - ---------- - If you use the option "--batch", GnuPG runs in non-interactive mode and - never prompts for input data. This does not even allow entering the - passphrase. Until we have a better solution (something like ssh-agent), - you can use the option "--passphrase-fd n", which works like PGP's - PGPPASSFD. +secring.gpg - Batch mode also causes GnuPG to terminate as soon as a BAD signature is - detected. + The database file with the OpenPGP secret keys. This will be + removed when gpg is changed to make use of the gpg-agent. - Exit status - ----------- - GnuPG returns with an exit status of 1 if in batch mode and a bad signature - has been detected or 2 or higher for all other errors. You should parse - stderr or, better, the output of the fd specified with --status-fd to get - detailed information about the errors. +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. - Configure options - ----------------- - Here is a list of configure options which are sometime useful - for installation. - --enable-static-rnd= - Force the use of the random byte gathering - module . Default is either to use /dev/random - or the auto mode. Value for name: - egd - Use the module which accesses the - Entropy Gathering Daemon. See the webpages - for more information about it. - unix - Use the standard Unix module which does not - have a very good performance. - linux - Use the module which accesses /dev/random. - This is the first choice and the default one - for GNU/Linux or *BSD. - auto - Compile linux, egd and unix in and - automagically select at runtime. - - --with-egd-socket= - This is only used when EGD is used as random - gatherer. GnuPG uses by default "~/.gnupg/entropy" - as the socket to connect EGD. Using this option the - socket name can be changed. You may use any filename - here with 2 exceptions: a filename starting with - "~/" uses the socket in the homedirectory of the user - and one starting with a "=" uses a socket in the - GnuPG homedirectory which is bye default "~/.gnupg". - - --with-included-zlib - Forces usage of the local zlib sources. Default is - to use the (shared) library of the system. - - --with-included-gettext - Forces usage of the local gettext sources instead of - the one provided by your system. - - --disable-nls - Disable NLS support (See the file ABOUT-NLS) - - --enable-m-guard - Enable the integrated malloc checking code. Please - note that this feature does not work on all CPUs - (e.g. SunOS 5.7 on UltraSparc-2) and might give - you a bus error. - - --disable-dynload - If you have problems with dynamic loading, this - option disables all dynamic loading stuff. Note - that the use of dynamic linking is very limited. - - --disable-asm - Do not use assembler modules. It is not possible - to use this on some CPU types. - - --disable-exec - Disable all remote program execution. This - disables photo ID viewing as well as all keyserver - types aside from HKP. - - --disable-photo-viewers - Disable only photo ID viewing. - - --disable-keyserver-helpers - Disable only keyserver helpers (not including - HKP). - - --disable-keyserver-path - Disables the user's ability to use the exec-path - feature to add additional search directories when - executing a keyserver helper. - - --with-photo-viewer=FIXED_VIEWER - Force the photo viewer to be FIXED_VIEWER and - disable any ability for the user to change it in - their options file. +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 + + * Exact match on an email address. + + This is indicated by enclosing the email address in the usual way + with left and right angles + + Example: + + + + * 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. - Installation Problems - --------------------- - If you get unresolved externals "gettext" you should run configure - again with the option "--with-included-gettext"; this is version - 0.10.35 which is available at alpha.gnu.org. - - If you have other compile problems, try the configure options - "--with-included-zlib" or "--disable-nls" (See ABOUT-NLS) or - --disable-dynload. + Example: - We can't check all assembler files, so if you have problems - assembling them (or the program crashes) use --disable-asm with - ./configure. The configure scripts may consider several - subdirectories to get all available assembler files; be sure to - delete the correct ones. The assembler replacements are in C and - in mpi/generic; never delete udiv-qrnnd.S in any CPU directory, - because there may be no C substitute. Don't forget to delete - "config.cache" and run "./config.status --recheck". + +Heinrich Heine duesseldorf - Some make tools are broken - the best solution is to use GNU's - make. Try gmake or grab the sources from a GNU archive and - install them. + * [NEW] Exact match by subject's DN - On some OSF systems you may get unresolved externals. This is a - libtool problem and the workaround is to manually remove all the - "-lc -lz" but the last one from the linker line and execute them - manually. - - On some architectures you see warnings like: - longlong.h:175: warning: function declaration isn't a prototype - or - http.c:647: warning: cast increases required alignment of target type - This doesn't matter and we know about it (actually it is due to - some warning options which we have enabled for gcc) - - - Specific problems on some machines - ---------------------------------- - - * IBM RS/6000 running AIX: - - Due to a change in gcc (since version 2.8) the MPI stuff may - not build. In this case try to run configure using: - CFLAGS="-g -O2 -mcpu=powerpc" ./configure + This is indicated by a leading slash, directly followed by the + rfc2253 encoded DN of the subject. - * Compaq C V6.2 for alpha: + Example: - You may want to use the option "-msg-disable ptrmismatch1" - to get rid of the sign/unsigned char mismatch warnings. + /CN=Henrich Heine,O=Poets,L=Paris,C=FR - * SVR4.2 (ESIX V4.2 cc) + * [NEW] Excact match by issuer's DN - Due to problems with the ESIX as, you probably want to do - CFLAGS="-O -K pentium" ./configure --disable-asm - Reported by Reinhard Wobst. + 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 + Example: + #/CN=Root Cert,O=Poets,L=Paris,C=FR - The Random Device - ----------------- + * [NEW] Exact match by serial number and subject's DN - Random devices are available in Linux, FreeBSD and OpenBSD. - Operating systems without a random devices must use another - entropy collector. + 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. - This collector works by running a lot of commands that yield more - or less unpredictable output and feds this as entropy into the - random generator - It should work reliably but you should check - whether it produces good output for your version of Unix. There - are some debug options to help you (see cipher/rndunix.c). + Example: + #4F03/CN=Root Cert,O=Poets,L=Paris,C=FR - Creating an RPM package - ----------------------- - The file scripts/gnupg.spec is used to build a RPM package (both - binary and src): - 1. copy the spec file into /usr/src/redhat/SPECS - 2. copy the tar file into /usr/src/redhat/SOURCES - 3. type: rpm -ba SPECS/gnupg.spec + * Substring match - Or use the -t (--tarbuild) option of rpm: - 1. rpm -ta gnupg-x.x.x.tar.gz + By case insensitive substring matching. This is the default mode + but applications may want to explicitly indicate this by putting + the asterisk in front. - The binary rpm file can now be found in /usr/src/redhat/RPMS, source - rpm in /usr/src/redhat/SRPMS + Example: + Heine + *Heine - How to Get More Information - --------------------------- - The primary WWW page is "http://www.gnupg.org" - The primary FTP site is "ftp://ftp.gnupg.org/gcrypt/" +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. - See http://www.gnupg.org/mirrors.html for a list of mirrors - and use them if possible. You may also find GnuPG mirrored on - some of the regular GNU mirrors. +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. - We have some mailing lists dedicated to GnuPG: +Some of the search modes are not yet implemented ;-) - gnupg-announce@gnupg.org For important announcements like - new versions and such stuff. - This is a moderated list and has - very low traffic. - gnupg-users@gnupg.org For general user discussion and - help. +How to import a private key +=========================== +There is some limited support to import a private key from a PKCS-12 +file. Note, that this does only import the private key and not any +certificates available in that file. - gnupg-devel@gnupg.org GnuPG developers main forum. + gpg-protect-tool --p12-import --store foo.p12 - You subscribe to one of the list by sending mail with a subject - of "subscribe" to x-request@gnupg.org, where x is the name of the - mailing list (gnupg-announce, gnupg-users, etc.). An archive of - the mailing lists is available at http://lists.gnupg.org . +This require that the gpg-agent is running, alternative you may give +the passphrase on the commandline using the option "-P " - +however this is in general not a good idea. If that key already +exists, the protect-tool refuses to store it unless you use the option +"--force". - Please direct bug reports to or post - them direct to the mailing list . +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. - Please direct questions about GnuPG to the users mailing list or - one of the pgp newsgroups; please do not direct questions to one - of the authors directly as we are busy working on improvements - and bug fixes. Both mailing lists are watched by the authors - and we try to answer questions when time allows us to do so. + gpg-protect-tool --p12-export foo.key >foo.p12 - Commercial grade support for GnuPG is available; please see - the GNU service directory or search other resources. diff --git a/THANKS b/THANKS index e54cf65bd..9047c1c18 100644 --- a/THANKS +++ b/THANKS @@ -1,232 +1,3 @@ -GnuPG was originally written by Werner Koch. Other people contributed by -reporting problems, suggesting various improvements or submitting actual -code. Here is a list of those people. Help me keep it complete and free of -errors. -Adam Mitchell adam@cafe21.org -Albert Chin china@thewrittenword.com -Alec Habig habig@budoe2.bu.edu -Allan Clark allanc@sco.com -Anand Kumria wildfire@progsoc.uts.edu.au -Andreas Haumer andreas@xss.co.at -Anthony Mulcahy anthony@kcn.ne.jp -Ariel T Glenn ariel@columbia.edu -Bob Mathews bobmathews@mindspring.com -Bodo Moeller Bodo_Moeller@public.uni-hamburg.de -Brendan O'Dea bod@debian.org -Brenno de Winter brenno@dewinter.com -Brian M. Carlson karlsson@hal-pc.org -Brian Moore bem@cmc.net -Brian Warner warner@lothar.com -Bryan Fullerton bryanf@samurai.com -Caskey L. Dickson caskey@technocage.com -Cees van de Griend cees-list@griend.xs4all.nl -Charles Levert charles@comm.polymtl.ca -Chip Salzenberg chip@valinux.com -Chris Adams cmadams@hiwaay.net -Christian Biere christianbiere@gmx.de -Christian Kurz shorty@debian.org -Christian von Roques roques@pond.sub.org -Christopher Oliver oliver@fritz.traverse.net -Christian Recktenwald chris@citecs.de -Dan Winship danw@helixcode.com -Daniel Eisenbud eisenbud@cs.swarthmore.edu -Daniel Koening dan@mail.isis.de -Daniel Resare daniel@resare.com -Dave Dykstra dwd@bell-labs.com -David C Niemi niemi@tuxers.net -David Champion dgc@uchicago.edu -David D. Scribner dscribner@bigfoot.com -David Ellement ellement@sdd.hp.com -David Hallinan hallinan@rtd.com -David Hollenberg dhollen@ISI.EDU -David Mathog MATHOG@seqaxp.bio.caltech.edu -David R. Bergstein dbergstein@home.com -David Shaw dshaw@jabberwocky.com -Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de -Dimitri dmitri@advantrix.com -Dirk Lattermann dlatt@t-online.de -Dirk Meyer dirk.meyer@dinoex.sub.org -Disastry Disastry@saiknes.lv -Douglas Calvert dfc@anize.org -Ed Boraas ecxjo@esperanto.org -Edmund GRIMLEY EVANS edmundo@rano.org -Edwin Woudt edwin@woudt.nl -Enzo Michelangeli em@MailAndNews.com -Ernst Molitor ernst.molitor@uni-bonn.de -Fabio Coatti cova@ferrara.linux.it -Felix von Leitner leitner@amdiv.de -fish stiqz fish@analog.org -Florian Weimer Florian.Weimer@rus.uni-stuttgart.de -Francesco Potorti pot@gnu.org -Frank Donahoe fdonahoe@wilkes1.wilkes.edu -Frank Heckenbach heckenb@mi.uni-erlangen.de -Frank Stajano frank.stajano@cl.cam.ac.uk -Frank Tobin ftobin@uiuc.edu -Gabriel Rosenkoetter gr@eclipsed.net -Gal Quri gael@lautre.net -Gene Carter gcarter@lanier.com -Georg Schwarz georg.schwarz@iname.com -Giampaolo Tomassoni g.tomassoni@libero.it -Gilbert Fernandes gilbert_fernandes@hotmail.com -Greg Louis glouis@dynamicro.on.ca -Greg Troxel gdt@ir.bbn.com -Gregory Steuck steuck@iname.com -Geoff Keating geoffk@ozemail.com.au -Harald Denker harry@hal.westfalen.de -Holger Baust Holger.Baust@freenet-ag.de -Hendrik Buschkamp buschkamp@rheumanet.org -Holger Schurig holger@d.om.org -Holger Smolinski smolinsk@de.ibm.com -Holger Trapp Holger.Trapp@informatik.tu-chemnitz.de -Hugh Daniel hugh@toad.com -Huy Le huyle@ugcs.caltech.edu -Ian McKellar imckellar@harvestroad.com.au -Ingo Klcker kloecker@kde.org -Ivo Timmermans itimmermans@bigfoot.com -Jan Krueger max@physics.otago.ac.nz -Jan Niehusmann jan@gondor.com -Janusz A. Urbanowicz alex@bofh.torun.pl -James Troup james@nocrew.org -Jean-loup Gailly gzip@prep.ai.mit.edu -Jeff Long long@kestrel.cc.ukans.edu -Jeffery Von Ronne jronne@ics.uci.edu -Jens Bachem bachem@rrz.uni-koeln.de -Jeroen C. van Gelderen jeroen@vangelderen.org -J Horacio MG homega@ciberia.es -J. Michael Ashley jashley@acm.org -Jim Bauer jfbauer@home.com -Jim Small cavenewt@my-deja.com -Joachim Backes backes@rhrk.uni-kl.de -Joe Rhett jrhett@isite.net -John A. Martin jam@jamux.com -Johnny Teveen j.tevessen@gmx.de -Jrg Schilling schilling@fokus.gmd.de -Jos Backus Jos.Backus@nl.origin-it.com -Jun Kuriyama kuriyama@sky.rim.or.jp -Kahil D. Jallad kdj4@cs.columbia.edu -Karl Fogel kfogel@guanabana.onshore.com -Karsten Thygesen karthy@kom.auc.dk -Katsuhiro Kondou kondou@nec.co.jp -Kazu Yamamoto kazu@iijlab.net -Keith Clayton keith@claytons.org -Kevin Ryde user42@zip.com.au -Klaus Singvogel ks@caldera.de -Kurt Garloff garloff@suse.de -Lars Kellogg-Stedman lars@bu.edu -L. Sassaman rabbi@quickie.net -M Taylor mctaylor@privacy.nb.ca -Marcel Waldvogel mwa@arl.wustl.edu -Marco d'Itri md@linux.it -Marco Parrone marc0@autistici.org -Marcus Brinkmann Marcus.Brinkmann@ruhr-uni-bochum.de -Mark Adler madler@alumni.caltech.edu -Mark Elbrecht snowball3@bigfoot.com -Mark Pettit pettit@yahoo-inc.com -Markus Friedl Markus.Friedl@informatik.uni-erlangen.de -Martin Kahlert martin.kahlert@provi.de -Martin Hamilton -Martin Schulte schulte@thp.uni-koeln.de -Matt Kraai kraai@alumni.carnegiemellon.edu -Matthew Skala mskala@ansuz.sooke.bc.ca -Matthew Wilcox matthew@wil.cx -Matthias Urlichs smurf@noris.de -Max Valianskiy maxcom@maxcom.ml.org -Michael Engels michael.engels@uni-duesseldorf.de -Michael Fischer v. Mollard mfvm@gmx.de -Michael Roth mroth@nessie.de -Michael Sobolev mss@despair.transas.com -Michael Tokarev mjt@tls.msk.ru -Nicolas Graner Nicolas.Graner@cri.u-psud.fr -Mike McEwan mike@lotusland.demon.co.uk -Neal H Walfield neal@cs.uml.edu -NIIBE Yutaka gniibe@chroot.org -Niklas Hernaeus -Nimrod Zimerman zimerman@forfree.at -N J Doye nic@niss.ac.uk -Oliver Haakert haakert@hsp.de -Oskari Jskelinen f33003a@cc.hut.fi -Pascal Scheffers Pascal@scheffers.net -Paul D. Smith psmith@baynetworks.com -Per Cederqvist ceder@lysator.liu.se -Phil Blundell pb@debian.org -Philippe Laliberte arsphl@oeil.qc.ca -Peter Fales psfales@lucent.com -Peter Gutmann pgut001@cs.auckland.ac.nz -Peter Marschall Peter.Marschall@gedos.de -Peter Valchev pvalchev@openbsd.org -Piotr Krukowiecki piotr@pingu.ii.uj.edu.pl -QingLong qinglong@bolizm.ihep.su -Ralph Gillen gillen@theochem.uni-duesseldorf.de -Rat ratinox@peorth.gweep.net -Reinhard Wobst R.Wobst@ifw-dresden.de -Rmi Guyomarch rguyom@mail.dotcom.fr -Reuben Sumner rasumner@wisdom.weizmann.ac.il -Richard Outerbridge outer@interlog.com -Robert Joop rj@rainbow.in-berlin.de -Roddy Strachan roddy@satlink.com.au -Roger Sondermann r.so@bigfoot.com -Roland Rosenfeld roland@spinnaker.rhein.de -Roman Pavlik rp@tns.cz -Ross Golder rossigee@bigfoot.com -Ryan Malayter rmalayter@bai.org -Sam Roberts sam@cogent.ca -Sami Tolvanen sami@tolvanen.com -Sean MacLennan seanm@netwinder.org -Sebastian Klemke packet@convergence.de -Serge Munhoven munhoven@mema.ucl.ac.be -SL Baur steve@xemacs.org -Stefan Bellon sbellon@sbellon.de -Stefan Karrmann S.Karrmann@gmx.net -Stefan Keller dres@cs.tu-berlin.de -Steffen Ullrich ccrlphr@xensei.com -Steffen Zahn zahn@berlin.snafu.de -Steven Bakker steven@icoe.att.com -Steven Murdoch sjmurdoch@bigfoot.com -Susanne Schultz schultz@hsp.de -Ted Cabeen secabeen@pobox.com -Thiago Jung Bauermann jungmann@cwb.matrix.com.br -Thomas Roessler roessler@guug.de -Tim Mooney mooney@dogbert.cc.ndsu.nodak.edu -Timo Schulz towaday@freakmail.de -TOGAWA Satoshi Satoshi.Togawa@jp.yokogawa.com -Tom Spindler dogcow@home.merit.edu -Tom Zerucha tzeruch@ceddec.com -Tomas Fasth tomas.fasth@twinspot.net -Tommi Komulainen Tommi.Komulainen@iki.fi -Thomas Klausner wiz@danbala.ifoer.tuwien.ac.at -Tomasz Kozlowski tomek@rentec.com -Thomas Mikkelsen tbm@image.dk -Ulf Mller 3umoelle@informatik.uni-hamburg.de -Urko Lusa ulusa@euskalnet.net -Vincent P. Broman broman@spawar.navy.mil -W Lewis wiml@hhhh.org -Walter Hofmann Walter.Hofmann@physik.stud.uni-erlangen.de -Walter Koch koch@hsp.de -Wayne Chapeskie waynec@spinnaker.com -Werner Koch wk@gnupg.org -Wim Vandeputte bunbun@reptile.rug.ac.be -Winona Brown win@huh.org -Yosiaki IIDA iida@ring.gr.jp -Yoshihiro Kajiki kajiki@ylug.org - nbecker@hns.com -Thanks to the German Unix User Group for sponsoring this project, -Martin Hamilton for hosting the first mailing list and OpenIT for -cheap hosting conditions. - -The development of this software has partly been funded by the German -Ministry for Economics and Technology under grant VIB3-68553.168-001/1999. - -Many thanks to my wife Gerlinde for having so much patience with -me while hacking late in the evening. - - Copyright 1998, 1999, 2000, 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. +Richard Lefebvre rick@CERCA.UMontreal.CA diff --git a/TODO b/TODO index b013c6f81..379a1780a 100644 --- a/TODO +++ b/TODO @@ -1,104 +1,61 @@ - * Reword the "Not enough entropy" messages. + -*- outline -*- - * Do we need a configure test for putenv? +* src/base64 +** Make parsing more robust +Currently we don't cope with overlong lines in the best way. - * Check for consistent spelling of user ID, key ID etc. - Replace "user id not found" in getkey.c by "no valid user ID found". - - * Describe some pitfalls when using EGD. Check that ~/.gnupg/entropy - really is the default. What about needed permission? +* 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). - * Using an expired key for signing should give an error message - "expired key" and not "unusable key'. Furthermore the error should - also be thrown when the default key has expired. Reported by - Eric.VanBuggenhaut add AdValvas.be. +* sm/certreqgen.c +** Improve error reporting +** Do some basic checks on the supplied DNs - * pause scrolling help in --edit-key and elsewhere. +* 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. - * getkey does not return revoked/expired keys - therefore it is not - possible to override it. +* sm/decrypt.c +** replace leading zero in integer hack by a cleaner solution - * Selection using +wordlist does not work. - What about adding a feature -word to the +wordlist search mode. +* sm/sign.c +** Don't hardcode the use of RSA. - * Check the changes to the gpg random gatherer on all W32 platforms. +* sm/gpgsm.c +** Support --output +** mark all unimplemented commands and options. - * Show more info does not work from edit->trust +* sm/keydb.c +** Check file permissions +** Write a keybox header and check for that magic value. +** Check that all error code mapping is done. +** Remove the inter-module dependencies between gpgsm and keybox - * Check that no secret temporary results are stored in the result parameter - of the mpi functions. We have already done this for mpi-mul.c - * We need another special packet at the end of a clearsign message to mark - it's end and allow for multiple signature for one message. And - add a real grammar to the code in mainproc.c +* agent/command.c +** Make sure that secure memory is used where appropriate +** Implement option passing per connection (DISPLAY and TTY) - * If there is no secure memory, allocate more memory for the secure - memory block or do it in all cases. +* agent/pkdecrypt.c, agent/pksign.c +** Don't use stdio to return results. - * add some minor things vor VMS. +* agent/protect-tool.c +** Export and import certificates along with the secret key. +** Make it more comfortable; i.e. copy files to the correct place. - * Use DSA keys with the test suite (partly done) +* Move pkcs-1 encoding into libgcrypt. - * Fix the bug in the mips assembler code +* Use a MAC to protect some files. - * Add a way to show the fingerprint of an key signator's keys +* sm/export.c +** Return an error code or a status info per user ID. - * Add an is_valid flag to each user ID. - * Replace the printing of the user name by [self-signature] when - appropriate so that a key listing does not get clobbered. - * Concatenated encryption messages don't work corectly - only the - first one is processed. - - * Add option to put the list of recipients (from the encryption - layer) into the signatures notation data. - - * --disable-asm should still assemble _udiv_qrnnd when needed - - * Get new assembler stuff from gmp 3.1 - - * use DEL and ^H for erasing the previous character (util/ttyio.c). - or better readline. - - * add test cases for invalid data (scrambled armor or other random data) - - * add checking of armor trailers. Try to detect garbled header - lines. Often one dash is missing due to sloppy cut+paste; so add - a warning note like the one for QP. - - * the pubkey encrypt functions should do some sanity checks. - - * "gpg filename.tar.gz.asc" should work like --verify (-sab). - - * for messages created with "-t", it might make sense to append the - verification status of the message to the output (i.e. write something to - the --output file and not only to stderr. However the problem is - that we consider the message transpatrent and don't have any - indication of the used character set. To implement this feature - we need to make sure that all output is plain 7 bit ascii but - given that we need to print a user name, this does not make sense - at all. The only way this can be implemented is by assuming that - the message is encoded in utf8 and hope tht everyone starts to use - utf8 instead of latin-1 or whatever RSN. Hmmm, I myself should - start with this. - - * keyflags don't distinguish between {certify,signature}-only. - - * Instead of issuing a "signature packet without keyid" gpg should - try to get the keyID from a corresponding one-pass signature - packet (See bug report 817). This is not easy to do as we don't - store the one-pass packets. - - * cat foo | gpg --sign | gpg --list-packets - Does not list the signature packet. - - * When presenting the result of a verification show the user ID with - the highest trust level first instead of the primary one. - - -Things we won't do ------------------- - - * New option --file-remove path-to-wipe-program ? diff --git a/acinclude.m4 b/acinclude.m4 index 4a2c91672..e4ba95cb2 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -17,14 +17,6 @@ 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_MSG_PRINT(STRING) -dnl print a message -dnl -define(GNUPG_MSG_PRINT, - [ echo $ac_n "$1"" $ac_c" 1>&AC_FD_MSG - ]) - - dnl GNUPG_CHECK_TYPEDEF(TYPE, HAVE_NAME) dnl Check whether a typedef exists and create a #define $2 if it exists dnl @@ -44,315 +36,95 @@ AC_DEFUN(GNUPG_CHECK_TYPEDEF, ]) -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/pub/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, - [ if test "$cross_compiling" = yes; then - AC_MSG_WARN(cross compiling; assuming little 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 - #include ], [ - #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 - #include ], [ - #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=little - ) - 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 ], + [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_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 - ]) - -dnl GNUPG_CHECK_CACHE -dnl -define(GNUPG_CHECK_CACHE, - [ AC_MSG_CHECKING(cached information) - gnupg_hostcheck="$target" - AC_CACHE_VAL(gnupg_cv_hostcheck, [ gnupg_cv_hostcheck="$gnupg_hostcheck" ]) - if test "$gnupg_cv_hostcheck" != "$gnupg_hostcheck"; then - AC_MSG_RESULT(changed) - AC_MSG_WARN(config.cache exists!) - AC_MSG_ERROR(you must do 'make distclean' first to compile for - different target or different parameters.) - else - AC_MSG_RESULT(ok) + 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 ]) -###################################################################### -# Check for -fPIC etc (taken from libtool) -# This sets CFLAGS_PIC to the required flags -# NO_PIC to yes if it is not possible to -# generate PIC -###################################################################### -dnl GNUPG_CHECK_PIC -dnl -define(GNUPG_CHECK_PIC, - [ AC_MSG_CHECKING(for option to create PIC) - CFLAGS_PIC= - NO_PIC=no - if test "$cross_compiling" = yes; then - AC_MSG_RESULT(assume none) - else - if test "$GCC" = yes; then - CFLAGS_PIC="-fPIC" - else - case "$host_os" in - aix3* | aix4*) - # All rs/6000 code is PIC - # but is there any non-rs/6000 AIX platform? - ;; - hpux9* | hpux10*) - CFLAGS_PIC="+Z" - ;; - - irix5* | irix6*) - # PIC (with -KPIC) is the default. - ;; - - osf3* | osf4*) - # FIXME - pic_flag is probably required for - # hppa*-osf* and i860-osf* - ;; - - sco3.2v5*) - CFLAGS_PIC='-Kpic' - ;; - - solaris2* | solaris7* ) - CFLAGS_PIC='-KPIC' - ;; +# 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 + ]) - sunos4*) - CFLAGS_PIC='-PIC' - ;; - *) - NO_PIC=yes - ;; - esac - fi - case "$host_cpu" in - rs6000 | powerpc | powerpcle) - # Yippee! All RS/6000 and PowerPC code is position-independent. - CFLAGS_PIC="" - ;; +# 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 - - if test "$NO_PIC" = yes; then - AC_MSG_RESULT(not possible) - else - if test -z "$CFLAGS_PIC"; then - AC_MSG_RESULT(none) - else - AC_MSG_RESULT($CFLAGS_PIC) + _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 for export-dynamic flag -# This sets CFLAGS_EXPORTDYNAMIC to the required flags -###################################################################### -dnl GNUPG_CHECK_EXPORTDYNAMIC -dnl -define(GNUPG_CHECK_EXPORTDYNAMIC, - [ AC_MSG_CHECKING(how to specify -export-dynamic) - if test "$cross_compiling" = yes; then - AC_MSG_RESULT(assume none) - CFLAGS_EXPORTDYNAMIC="" - else - AC_CACHE_VAL(gnupg_cv_export_dynamic,[ - if AC_TRY_COMMAND([${CC-cc} $CFLAGS -Wl,--version 2>&1 | - grep "GNU ld" >/dev/null]); then - # using gnu's linker - gnupg_cv_export_dynamic="-Wl,-export-dynamic" - else - case "$host_os" in - hpux* ) - gnupg_cv_export_dynamic="-Wl,-E" - ;; - * ) - gnupg_cv_export_dynamic="" - ;; - esac - fi - ]) - AC_MSG_RESULT($gnupg_cv_export_dynamic) - CFLAGS_EXPORTDYNAMIC="$gnupg_cv_export_dynamic" - fi - ]) - -##################################################################### -# Check for SysV IPC (from GIMP) -# And see whether we have a SHM_LOCK (FreeBSD does not have it). -##################################################################### -dnl GNUPG_CHECK_IPC -dnl -define(GNUPG_CHECK_IPC, - [ AC_CHECK_HEADERS(sys/ipc.h sys/shm.h) - if test "$ac_cv_header_sys_shm_h" = "yes"; then - AC_MSG_CHECKING(whether IPC_RMID allowes subsequent attaches) - AC_CACHE_VAL(gnupg_cv_ipc_rmid_deferred_release, - AC_TRY_RUN([ - #include - #include - #include - int main() - { - int id; - char *shmaddr; - id = shmget (IPC_PRIVATE, 4, IPC_CREAT | 0777); - if (id == -1) - exit (2); - shmaddr = shmat (id, 0, 0); - shmctl (id, IPC_RMID, 0); - if ((char*) shmat (id, 0, 0) == (char*) -1) - { - shmdt (shmaddr); - exit (1); - } - shmdt (shmaddr); - shmdt (shmaddr); - exit (0); - } - ], - gnupg_cv_ipc_rmid_deferred_release="yes", - gnupg_cv_ipc_rmid_deferred_release="no", - gnupg_cv_ipc_rmid_deferred_release="assume-no") - ) - if test "$gnupg_cv_ipc_rmid_deferred_release" = "yes"; then - AC_DEFINE(IPC_RMID_DEFERRED_RELEASE,1, - [Defined if we can do a deferred shm release]) - AC_MSG_RESULT(yes) - else - if test "$gnupg_cv_ipc_rmid_deferred_release" = "no"; then - AC_MSG_RESULT(no) - else - AC_MSG_RESULT([assuming no]) - fi - fi - - AC_MSG_CHECKING(whether SHM_LOCK is available) - AC_CACHE_VAL(gnupg_cv_ipc_have_shm_lock, - AC_TRY_COMPILE([#include - #include - #include ],[ - int shm_id; - shmctl(shm_id, SHM_LOCK, 0); - ], - gnupg_cv_ipc_have_shm_lock="yes", - gnupg_cv_ipc_have_shm_lock="no" - ) - ) - if test "$gnupg_cv_ipc_have_shm_lock" = "yes"; then - AC_DEFINE(IPC_HAVE_SHM_LOCK,1, - [Defined if a SysV shared memory supports the LOCK flag]) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - 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) @@ -448,295 +220,206 @@ define(GNUPG_CHECK_MLOCK, ]) -################################################################ -# GNUPG_PROG_NM - find the path to a BSD-compatible name lister -AC_DEFUN(GNUPG_PROG_NM, -[AC_MSG_CHECKING([for BSD-compatible nm]) -AC_CACHE_VAL(ac_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - ac_cv_path_NM="$NM" -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/nm; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - ac_cv_path_NM="$ac_dir/nm -B" - elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then - ac_cv_path_NM="$ac_dir/nm -p" - else - ac_cv_path_NM="$ac_dir/nm" - fi - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm -fi]) -NM="$ac_cv_path_NM" -AC_MSG_RESULT([$NM]) -AC_SUBST(NM) -]) - -# GNUPG_SYS_NM_PARSE - Check for command ro grab the raw symbol name followed -# by C symbol name from nm. -AC_DEFUN(GNUPG_SYS_NM_PARSE, -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([GNUPG_PROG_NM])dnl -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output]) -AC_CACHE_VAL(ac_cv_sys_global_symbol_pipe, -[# These are sane defaults that work on at least a few old systems. -# {They come from Ultrix. What could be older than Ultrix?!! ;)} - -changequote(,)dnl -# Character class describing NM global symbol codes. -ac_symcode='[BCDEGRSTU]' - -# Regexp to match symbols that can be accessed directly from C. -ac_sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform the above into a raw symbol and a C symbol. -ac_symxfrm='\1 \1' - -# Define system-specific variables. -case "$host_os" in -aix*) - ac_symcode='[BCDTU]' - ;; -freebsd* | netbsd* | openbsd* | bsdi* | sunos* | cygwin32* | mingw32*) - ac_sympat='_\([_A-Za-z][_A-Za-z0-9]*\)' - ac_symxfrm='_\1 \1' - ;; -irix*) - # Cannot use undefined symbols on IRIX because inlined functions mess us up. - ac_symcode='[BCDEGRST]' - ;; -solaris*) - ac_symcode='[BDTU]' - ;; -esac -# If we're using GNU nm, then use its standard symbol codes. -if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then - ac_symcode='[ABCDGISTUW]' -fi - -case "$host_os" in -cygwin32* | mingw32*) - # We do not want undefined symbols on cygwin32. The user must - # arrange to define them via -l arguments. - ac_symcode='[ABCDGISTW]' - ;; -esac -changequote([,])dnl - -# Write the raw and C identifiers. -ac_cv_sys_global_symbol_pipe="sed -n -e 's/^.* $ac_symcode $ac_sympat$/$ac_symxfrm/p'" - -# Check to see that the pipe works correctly. -ac_pipe_works=no -cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then +dnl [copied from libgcrypt] +dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for liblibgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS +dnl +AC_DEFUN(AM_PATH_LIBGCRYPT, +[ AC_ARG_WITH(libgcrypt-prefix, + AC_HELP_STRING([--with-libgcrypt-prefix=PFX], + [prefix where LIBGCRYPT is installed (optional)]), + libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") + if test x$libgcrypt_config_prefix != x ; then + libgcrypt_config_args="$libgcrypt_config_args --prefix=$libgcrypt_config_prefix" + if test x${LIBGCRYPT_CONFIG+set} != xset ; then + LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config + fi + fi - # Try sorting and uniquifying the output. - if sort "$ac_nlist" | uniq > "$ac_nlist"T; then - mv -f "$ac_nlist"T "$ac_nlist" - ac_wcout=`wc "$ac_nlist" 2>/dev/null` -changequote(,)dnl - ac_count=`echo "X$ac_wcout" | sed -e 's,^X,,' -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` -changequote([,])dnl - (test "$ac_count" -ge 0) 2>/dev/null || ac_count=-1 - else - rm -f "$ac_nlist"T - ac_count=-1 + AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) + min_libgcrypt_version=ifelse([$1], ,0.4.4,$1) + AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) + ok=no + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --version` + major=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $libgcrypt_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 + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBGCRYPT_CFLAGS) + AC_SUBST(LIBGCRYPT_LIBS) +]) - # Make sure that we snagged all the symbols we need. - if egrep ' nm_test_var$' "$ac_nlist" >/dev/null; then - if egrep ' nm_test_func$' "$ac_nlist" >/dev/null; then - cat < conftest.c -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - sed 's/^.* \(.*\)$/extern char \1;/' < "$ac_nlist" >> conftest.c - - cat <> conftest.c -#if defined (__STDC__) && __STDC__ -# define __ptr_t void * -#else -# define __ptr_t char * -#endif - -/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ -int dld_preloaded_symbol_count = $ac_count; -/* The mapping between symbol names and symbols. */ -struct { - char *name; - __ptr_t address; -} -changequote(,)dnl -dld_preloaded_symbols[] = -changequote([,])dnl -{ -EOF - sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$ac_nlist" >> conftest.c - cat <<\EOF >> conftest.c - {0, (__ptr_t) 0} -}; +dnl [Copied from libksba] +dnl AM_PATH_KSBA([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libksba and define KSBA_CFLAGS and KSBA_LIBS +dnl +AC_DEFUN(AM_PATH_KSBA, +[ AC_ARG_WITH(ksba-prefix, + AC_HELP_STRING([--with-ksba-prefix=PFX], + [prefix where KSBA is installed (optional)]), + ksba_config_prefix="$withval", ksba_config_prefix="") + if test x$ksba_config_prefix != x ; then + ksba_config_args="$ksba_config_args --prefix=$ksba_config_prefix" + if test x${KSBA_CONFIG+set} != xset ; then + KSBA_CONFIG=$ksba_config_prefix/bin/ksba-config + fi + fi -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftestm.$ac_objext - ac_save_LIBS="$LIBS" - ac_save_CFLAGS="$CFLAGS" - LIBS="conftestm.$ac_objext" - CFLAGS="$CFLAGS$no_builtin_flag" - if AC_TRY_EVAL(ac_link) && test -s conftest; then - ac_pipe_works=yes - else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.c >&AC_FD_CC + AC_PATH_PROG(KSBA_CONFIG, ksba-config, no) + min_ksba_version=ifelse([$1], ,0.4.4,$1) + AC_MSG_CHECKING(for KSBA - version >= $min_ksba_version) + ok=no + if test "$KSBA_CONFIG" != "no" ; then + req_major=`echo $min_ksba_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_ksba_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_ksba_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + ksba_config_version=`$KSBA_CONFIG $ksba_config_args --version` + major=`echo $ksba_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $ksba_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $ksba_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 - LIBS="$ac_save_LIBS" - CFLAGS="$ac_save_CFLAGS" - else - echo "cannot find nm_test_func in $ac_nlist" >&AC_FD_CC - fi - else - echo "cannot find nm_test_var in $ac_nlist" >&AC_FD_CC fi + fi + if test $ok = yes; then + KSBA_CFLAGS=`$KSBA_CONFIG $ksba_config_args --cflags` + KSBA_LIBS=`$KSBA_CONFIG $ksba_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) else - echo "cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + KSBA_CFLAGS="" + KSBA_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) fi -else - echo "$progname: failed program was:" >&AC_FD_CC - cat conftest.c >&AC_FD_CC -fi -rm -rf conftest* - -# Do not use the global_symbol_pipe unless it works. -test "$ac_pipe_works" = yes || ac_cv_sys_global_symbol_pipe= + AC_SUBST(KSBA_CFLAGS) + AC_SUBST(KSBA_LIBS) ]) -ac_result=yes -if test -z "$ac_cv_sys_global_symbol_pipe"; then - ac_result=no -fi -AC_MSG_RESULT($ac_result) -]) -# GNUPG_SYS_LIBTOOL_CYGWIN32 - find tools needed on cygwin32 -AC_DEFUN(GNUPG_SYS_LIBTOOL_CYGWIN32, -[AC_CHECK_TOOL(DLLTOOL, dlltool, false) -AC_CHECK_TOOL(AS, as, false) -]) -# GNUPG_SYS_SYMBOL_UNDERSCORE - does the compiler prefix global symbols -# with an underscore? -AC_DEFUN(GNUPG_SYS_SYMBOL_UNDERSCORE, -[tmp_do_check="no" -case "${target}" in - i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp | *-*-cygwin) - ac_cv_sys_symbol_underscore=yes - ;; - *) - if test "$cross_compiling" = yes; then - ac_cv_sys_symbol_underscore=yes - else - tmp_do_check="yes" - fi - ;; -esac +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 -if test "$tmp_do_check" = "yes"; then -AC_REQUIRE([GNUPG_PROG_NM])dnl -AC_REQUIRE([GNUPG_SYS_NM_PARSE])dnl -AC_MSG_CHECKING([for _ prefix in compiled symbols]) -AC_CACHE_VAL(ac_cv_sys_symbol_underscore, -[ac_cv_sys_symbol_underscore=no -cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then - # See whether the symbols have a leading underscore. - if egrep '^_nm_test_func' "$ac_nlist" >/dev/null; then - ac_cv_sys_symbol_underscore=yes - else - if egrep '^nm_test_func ' "$ac_nlist" >/dev/null; then - : - else - echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC - 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` + 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 - echo "configure: cannot run $ac_cv_sys_global_symbol_pipe" >&AC_FD_CC + OPENSC_CFLAGS="" + OPENSC_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) fi -else - echo "configure: failed program was:" >&AC_FD_CC - cat conftest.c >&AC_FD_CC -fi -rm -rf conftest* -]) -else -AC_MSG_CHECKING([for _ prefix in compiled symbols]) -fi -AC_MSG_RESULT($ac_cv_sys_symbol_underscore) -if test x$ac_cv_sys_symbol_underscore = xyes; then - AC_DEFINE(WITH_SYMBOL_UNDERSCORE,1, - [Defined if compiled symbols have a leading underscore]) -fi + AC_SUBST(OPENSC_CFLAGS) + AC_SUBST(OPENSC_LIBS) ]) -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 -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_DIRECT_H -# include -#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 -]) diff --git a/autogen.sh b/autogen.sh index 41ae4e272..29f4b7ae5 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,5 +1,163 @@ #!/bin/sh +# Run this to generate all the initial makefiles, etc. +# It is only needed for the CVS version. -autogen_sh="`dirname $0`/scripts/autogen.sh" -exec $autogen_sh $* +# have_version(prog, list of executables, required version) +# +# Returns true and sets $prog to the first executable with the +# required minimum major.minor. +have_version () +{ + found=0 + for prog in $2 : + do + ver=$($prog --version \ + | gawk '{ if (match($0, /[0-9]+\.[0-9]+/)) + { + print substr($0, RSTART, RLENGTH); ok=1; exit 0; + } + } + + END { + if (! ok) + exit 1; + }') + + if test $? = 0 + then + if expr 0$ver '>=' 0$3 >/dev/null 2>&1 + then + echo Using $prog + found=1 + export $1="$prog" + break + fi + fi + done + + if test 0$found = 01 + then + true + else + echo "*** Error. Could not find an appropriate executable for $1 with " + echo "at least version $3." + false + fi +} + +PGM=NEWPG +lib_config_files="" +autoconf_vers=2.52 +automake_vers=1.5 +aclocal_vers=1.5 +#libtool_vers=1.3 + +DIE=no +if test "$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 + +if ! have_version autoconf "$autoconf autoconf" $autoconf_vers +then + DIE="yes" +fi + +if have_version automake "$automake automake automake-1.6" $automake_vers +then + if ! have_version aclocal "$aclocal aclocal aclocal-1.6" $aclocal_vers + then + DIE='yes' + fi +else + DIE='yes' +fi + +#if (libtool --version) < /dev/null > /dev/null 2>&1 ; then +# if (libtool --version | awk 'NR==1 { if( $4 >= '$libtool_vers') \ +# exit 1; exit 0; }'); +# then +# echo "**Error**: "\`libtool\'" is too old." +# echo ' (version ' $libtool_vers ' or newer is required)' +# DIE="yes" +# fi +#else +# echo +# echo "**Error**: You must have "\`libtool\'" installed to compile $PGM." +# echo ' (version ' $libtool_vers ' or newer is required)' +# DIE="yes" +#fi + +if test "$DIE" = "yes"; then + exit 1 +fi + +#echo "Running libtoolize... Ignore non-fatal messages." +#echo "no" | libtoolize + +echo "Running gettextize... Ignore non-fatal messages." +echo "no" | gettextize + +echo "Running $aclocal" +$aclocal +echo "Running autoheader..." +autoheader +echo "Running $automake --gnu -a" +$automake --gnu -a +echo "Running $autoconf" +$autoconf diff --git a/configure.ac b/configure.ac index 18ea461b6..8294fb3c4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,470 +1,110 @@ -dnl Configure.ac script for GnuPG -dnl Copyright (C) 1998, 1999, 2000, 2001, 2002 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 -dnl (Process this file with autoconf to produce a configure script.) -dnlAC_REVISION($Revision$)dnl - +# configure.ac - for NewPG +# 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 + +# Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) - -# Remember to change the version number immediately *after* a release -# and remove the "-cvs" or "rc" suffix immediately *before* a release. -AC_INIT(gnupg, 1.3.1-cvs, bug-gnupg@gnu.org) -# Set development_version to yes if the minor number is odd or you -# feel that the default check for a development version is not -# sufficient. -development_version=yes - +# Version number: Remember to change it immediately *after* a release. +# Add a "-cvs" prefix for non-released code. +AC_INIT(newpg, 0.9.3-cvs, gpa-dev@gnupg.org) +NEED_LIBGCRYPT_VERSION=1.1.8 +NEED_KSBA_VERSION=0.4.4 +NEED_OPENSC_VERSION=0.7.0 ALL_LINGUAS="de" PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION -AC_CONFIG_AUX_DIR(scripts) -AC_CONFIG_SRCDIR(g10/g10.c) -AC_CANONICAL_TARGET() -AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AM_MAINTAINER_MODE -AC_SUBST(PACKAGE) -AC_SUBST(VERSION) -AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) -AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) -AC_DEFINE(_GNU_SOURCE,1,[Some tests rely on this (stpcpy) and it should be used for new programs anyway]) - -dnl -dnl Check for random module options -dnl -AC_MSG_CHECKING([which random module to use]) -AC_ARG_ENABLE(static-rnd, - [ --enable-static-rnd=[egd|unix|linux|auto] ], -[use_static_rnd=$enableval], [use_static_rnd=default] ) - -if test "$use_static_rnd" = no; then - use_static_rnd=default -fi - -case "$use_static_rnd" in - egd | linux | unix | default ) - AC_MSG_RESULT($use_static_rnd) - ;; - auto ) - AC_MSG_RESULT(automagically selected at runtime) - ;; - * ) - AC_MSG_RESULT(invalid argument) - AC_MSG_ERROR(there is no random module rnd$use_static_rnd) - ;; -esac - -AC_ARG_WITH(egd-socket, - [ --with-egd-socket=NAME use NAME for the EGD socket], - egd_socket_name="$withval", egd_socket_name="" ) -AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name", - [Define if you don't want the default EGD socket name. - For details see cipher/rndegd.c]) - - -dnl -dnl See whether the user wants to disable checking for /dev/random - -AC_MSG_CHECKING([whether use of /dev/random is requested]) -AC_ARG_ENABLE(dev-random, -[ --disable-dev-random disable the use of dev random], - try_dev_random=$enableval, try_dev_random=yes) -AC_MSG_RESULT($try_dev_random) - - -dnl -dnl Check other options -dnl - -# We don't need idea but some people claim that they need it for -# research etc., so we allow to place an idea source code into the -# cipher directory and statically link it if available, otherwise we -# link to a stub. We don't use AC_CHECK_FILE to avoid caching. -AC_MSG_CHECKING(for extra cipher modules) -tmp="" -if test -f $srcdir/cipher/idea.c; then - IDEA_O=idea.o - tmp=idea -else - IDEA_O=idea-stub.o - tmp=no -fi -AC_SUBST(IDEA_O) -AC_MSG_RESULT($tmp) - -# if the static idea is present, disable dynload. -if test "$IDEA_O" = idea-stub.o ; then - AC_MSG_CHECKING([whether use of extensions is requested]) - AC_ARG_ENABLE(dynload, - [ --disable-dynload disable use of extensions], - try_dynload=$enableval, try_dynload=yes) - AC_MSG_RESULT($try_dynload) -else - try_dynload=no -fi - -AC_MSG_CHECKING([whether assembler modules are requested]) -AC_ARG_ENABLE(asm, -[ --disable-asm do not use assembler modules], - try_asm_modules=$enableval, try_asm_modules=yes) -AC_MSG_RESULT($try_asm_modules) - -AC_MSG_CHECKING([whether memory guard is requested]) -AC_ARG_ENABLE(m-guard, - [ --enable-m-guard enable memory guard facility], - use_m_guard=$enableval, use_m_guard=no) -AC_MSG_RESULT($use_m_guard) -if test "$use_m_guard" = yes ; then - AC_DEFINE(M_GUARD,1,[Define to use the (obsolete) malloc guarding feature]) -fi - -AC_MSG_CHECKING([whether to enable old-style TIGER digest support]) -AC_ARG_ENABLE(old-tiger, - [ --enable-old-tiger enable old-style TIGER digest support], - old_tiger=$enableval, old_tiger=no) -AC_MSG_RESULT($old_tiger) -if test "$old_tiger" = yes ; then - AC_DEFINE(USE_OLD_TIGER,1,[Define to use the old fake OID for TIGER digest support]) -fi - -AC_MSG_CHECKING([whether to enable external program execution]) -AC_ARG_ENABLE(exec, - [ --disable-exec disable all external program execution], - use_exec=$enableval, use_exec=yes) -AC_MSG_RESULT($use_exec) -if test "$use_exec" = no ; then - AC_DEFINE(NO_EXEC,1,[Define to disable all external program execution]) -fi - -if test "$use_exec" = yes ; then - AC_MSG_CHECKING([whether to enable photo ID viewing]) - AC_ARG_ENABLE(photo-viewers, - [ --disable-photo-viewers disable photo ID viewers], - [if test "$enableval" = no ; then - AC_DEFINE(DISABLE_PHOTO_VIEWER,1,[define to disable photo viewing]) - fi],enableval=yes) - gnupg_cv_enable_photo_viewers=$enableval - AC_MSG_RESULT($enableval) - - if test "$gnupg_cv_enable_photo_viewers" = yes ; then - AC_MSG_CHECKING([whether to use a fixed photo ID viewer]) - AC_ARG_WITH(photo-viewer, - [ --with-photo-viewer=FIXED_VIEWER set a fixed photo ID viewer], - [if test "$withval" = yes ; then - withval=no - elif test "$withval" != no ; then - AC_DEFINE_UNQUOTED(FIXED_PHOTO_VIEWER,"$withval", - [if set, restrict photo-viewer to this]) - fi],withval=no) - AC_MSG_RESULT($withval) - fi +# Some status variables to give feedback at the end of a configure run +have_ksba=no +have_opensc=no +have_pth=no - AC_MSG_CHECKING([whether to enable external keyserver helpers]) - AC_ARG_ENABLE(keyserver-helpers, - [ --disable-keyserver-helpers disable all external keyserver support], - [if test "$enableval" = no ; then - AC_DEFINE(DISABLE_KEYSERVER_HELPERS,1, - [define to disable keyserver helpers]) - fi],enableval=yes) - gnupg_cv_enable_keyserver_helpers=$enableval - AC_MSG_RESULT($enableval) - - if test "$gnupg_cv_enable_keyserver_helpers" = yes ; then - AC_MSG_CHECKING([whether LDAP keyserver support is requested]) - AC_ARG_ENABLE(ldap, - [ --disable-ldap disable LDAP keyserver interface], - try_ldap=$enableval, try_ldap=yes) - AC_MSG_RESULT($try_ldap) - - AC_MSG_CHECKING([whether HKP keyserver support is requested]) - AC_ARG_ENABLE(hkp, - [ --disable-hkp disable HKP keyserver interface], - try_hkp=$enableval, try_hkp=yes) - AC_MSG_RESULT($try_hkp) - - if test "$try_hkp" = yes ; then - AC_SUBST(GPGKEYS_HKP,"gpgkeys_hkp") - fi - - AC_MSG_CHECKING([whether email keyserver support is requested]) - AC_ARG_ENABLE(mailto, - [ --disable-mailto disable email keyserver interface], - try_mailto=$enableval, try_mailto=yes) - AC_MSG_RESULT($try_mailto) - fi - - AC_MSG_CHECKING([whether keyserver exec-path is enabled]) - AC_ARG_ENABLE(keyserver-path, - [ --disable-keyserver-path disable the exec-path option for keyserver helpers], - [if test "$enableval" = no ; then - AC_DEFINE(DISABLE_KEYSERVER_PATH,1,[define to disable exec-path for keyserver helpers]) - fi],enableval=yes) - AC_MSG_RESULT($enableval) - fi +GNUPG_BUILD_PROGRAM(gpg, no) +GNUPG_BUILD_PROGRAM(gpgsm, yes) +GNUPG_BUILD_PROGRAM(agent, yes) +GNUPG_BUILD_PROGRAM(scdaemon, yes) -AC_MSG_CHECKING([whether included zlib is requested]) -AC_ARG_WITH(included-zlib, - [ --with-included-zlib use the zlib code included here], -[g10_force_zlib=yes], [g10_force_zlib=no] ) -AC_MSG_RESULT($g10_force_zlib) +AH_TOP([ +/* We need this, because some autoconf tests rely on this (e.g. stpcpy) + and it should be used for new programs anyway. */ +#define _GNU_SOURCE 1 +]) -dnl -dnl Check whether we want to use Linux capabilities -dnl -AC_MSG_CHECKING([whether use of capabilities is requested]) -AC_ARG_WITH(capabilities, - [ --with-capabilities use linux capabilities [default=no]], -[use_capabilities="$withval"],[use_capabilities=no]) -AC_MSG_RESULT($use_capabilities) +AH_BOTTOM([ +/* Some global constants. */ +#ifdef HAVE_DRIVE_LETTERS +#define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" +#else +#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" +#endif +#define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" +]) -AH_BOTTOM([ -#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) -#define EXEC_TEMPFILE_ONLY -#endif -#include "g10defs.h" -]) +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) +AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT, "$PACKAGE_BUGREPORT", + [Bug report address]) +AC_DEFINE_UNQUOTED(NEED_LIBGCRYPT_VERSION, "$NEED_LIBGCRYPT_VERSION", + [Required version of Libgcrypt]) +AC_DEFINE_UNQUOTED(NEED_KSBA_VERSION, "$NEED_KSBA_VERSION", + [Required version of Libksba]) -AM_MAINTAINER_MODE -dnl Checks for programs. -AC_PROG_MAKE_SET -AM_SANITY_CHECK +# Checks for programs. missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_PROG_AWK AC_PROG_CC AC_PROG_CPP -AC_PATH_PROG(PERL,"perl") -AC_ISC_POSIX -AC_SYS_LARGEFILE AC_PROG_INSTALL -AC_PROG_AWK -AC_CHECK_PROG(DOCBOOK_TO_MAN, docbook-to-man, yes, no) -AM_CONDITIONAL(HAVE_DOCBOOK_TO_MAN, test "$ac_cv_prog_DOCBOOK_TO_MAN" = yes) -GNUPG_CHECK_FAQPROG -GNUPG_CHECK_DOCBOOK_TO_TEXI - -MPI_OPT_FLAGS="" +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_RANLIB +#AC_ARG_PROGRAM +if test "$GCC" = yes; then + CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" +fi -try_gettext=yes case "${target}" in - *-*-mingw32*|*-*-cygwin*) - # special stuff for Windoze NT - ac_cv_have_dev_random=no - AC_DEFINE(USE_ONLY_8DOT3,1, - [set this to limit filenames to the 8.3 format]) - AC_DEFINE(HAVE_DRIVE_LETTERS,1, - [defined if we must run on a stupid file system]) + *-*-mingw32*) + PRINTABLE_OS_NAME="MingW32" AC_DEFINE(HAVE_DOSISH_SYSTEM,1, [defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) with special properties like no file modes]) - AC_DEFINE(USE_SIMPLE_GETTEXT,1, - [because the Unix gettext has too much overhead on - MingW32 systems and these systems lack Posix functions, - we use a simplified version of gettext]) - try_gettext="no" - ;; - i?86-emx-os2 | i?86-*-os2*emx ) - # OS/2 with the EMX environment - ac_cv_have_dev_random=no - AC_DEFINE(HAVE_DRIVE_LETTERS) - AC_DEFINE(HAVE_DOSISH_SYSTEM) - try_gettext="no" - ;; - - i?86-*-msdosdjgpp*) - # DOS with the DJGPP environment - ac_cv_have_dev_random=no - AC_DEFINE(HAVE_DRIVE_LETTERS) - AC_DEFINE(HAVE_DOSISH_SYSTEM) - try_gettext="no" - ;; - - *-*-freebsd*) - # FreeBSD - CPPFLAGS="$CPPFLAGS -I/usr/local/include" - LDFLAGS="$LDFLAGS -L/usr/local/lib" - ;; - - *-*-hpux*) - if test -z "$GCC" ; then - CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" - fi - ;; - *-dec-osf4*) - if test -z "$GCC" ; then - # Suppress all warnings - # to get rid of the unsigned/signed char mismatch warnings. - CFLAGS="$CFLAGS -w" - fi - ;; - *-dec-osf5*) - if test -z "$GCC" ; then - # Use the newer compiler `-msg_disable ptrmismatch' to - # get rid of the unsigned/signed char mismatch warnings. - # Using this may hide other pointer mismatch warnings, but - # it at least lets other warning classes through - CFLAGS="$CFLAGS -msg_disable ptrmismatch" - fi - ;; - m68k-atari-mint) - ;; - *) - ;; -esac - -AC_SUBST(MPI_OPT_FLAGS) -GNUPG_SYS_SYMBOL_UNDERSCORE - -dnl Must check for network library requirements before doing link tests -dnl for ldap, for example. If ldap libs are static (or dynamic and without -dnl ELF runtime link paths), then link will fail and LDAP support won't -dnl be detected. - -AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname, - [NETLIBS="-lnsl $NETLIBS"])) -AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt, - [NETLIBS="-lsocket $NETLIBS"])) - -# Try and link a LDAP test program to weed out unusable LDAP -# libraries. -lldap [-llber [-lresolv]] is for OpenLDAP. OpenLDAP in -# general is terrible with creating weird dependencies. If all else -# fails, the user can play guess-the-dependency by using something -# like LDAPLIBS="-lfoo" ./configure - -if test "$try_ldap" = yes ; then - for MY_LDAPLIBS in ${LDAPLIBS+"$LDAPLIBS"} "-lldap" "-lldap -llber" "-lldap -llber -lresolv"; do - _ldap_save_libs=$LIBS - LIBS="$MY_LDAPLIBS $NETLIBS $LIBS" - - AC_MSG_CHECKING([whether LDAP via \"$MY_LDAPLIBS\" is present and sane]) - AC_TRY_LINK([#include ],[ldap_open("foobar",1234);], - [gnupg_cv_func_ldap_init=yes],[gnupg_cv_func_ldap_init=no]) - AC_MSG_RESULT([$gnupg_cv_func_ldap_init]) - - if test $gnupg_cv_func_ldap_init = no; then - AC_MSG_CHECKING([whether I can make LDAP be sane with lber.h]) - AC_TRY_LINK([#include -#include ],[ldap_open("foobar",1234);], - [gnupg_cv_func_ldaplber_init=yes],[gnupg_cv_func_ldaplber_init=no]) - AC_MSG_RESULT([$gnupg_cv_func_ldaplber_init]) - fi - - if test "$gnupg_cv_func_ldaplber_init" = yes ; then - AC_DEFINE(NEED_LBER_H,1,[Define if the LDAP library requires including lber.h before ldap.h]) - fi - - if test "$gnupg_cv_func_ldap_init" = yes || \ - test "$gnupg_cv_func_ldaplber_init" = yes ; then - LDAPLIBS=$MY_LDAPLIBS - GPGKEYS_LDAP="gpgkeys_ldap" - - AC_MSG_CHECKING([whether LDAP supports ldap_get_option]) - - if test "$gnupg_cv_func_ldap_init" = yes ; then - AC_TRY_LINK([#include ], - [ldap_get_option((void *)0,0,(void *)0);], - [gnupg_cv_func_ldap_get_option=yes], - [gnupg_cv_func_ldap_get_option=no]) - else - AC_TRY_LINK([#include -#include ],[ldap_get_option((void *)0,0,(void *)0);], - [gnupg_cv_func_ldap_get_option=yes], - [gnupg_cv_func_ldap_get_option=no]) - fi - - AC_MSG_RESULT([$gnupg_cv_func_ldap_get_option]) - - if test "$gnupg_cv_func_ldap_get_option" = yes ; then - AC_DEFINE(HAVE_LDAP_GET_OPTION,1,[Define if the LDAP library has ldap_get_option]) - else - AC_MSG_CHECKING([whether LDAP supports ld_errno]) - - if test "$gnupg_cv_func_ldap_init" = yes ; then - AC_TRY_COMPILE([#include ], - [LDAP *ldap; ldap->ld_errno;], - [gnupg_cv_func_ldap_ld_errno=yes], - [gnupg_cv_func_ldap_ld_errno=no]) - else - AC_TRY_LINK([#include -#include ],[LDAP *ldap; ldap->ld_errno;], - [gnupg_cv_func_ldap_ld_errno=yes], - [gnupg_cv_func_ldap_ld_errno=no]) - fi - - AC_MSG_RESULT([$gnupg_cv_func_ldap_ld_errno]) - - if test "$gnupg_cv_func_ldap_ld_errno" = yes ; then - AC_DEFINE(HAVE_LDAP_LD_ERRNO,1,[Define if the LDAP library supports ld_errno]) - fi - fi - fi - - LIBS=$_ldap_save_libs - - if test "$GPGKEYS_LDAP" != "" ; then break; fi - done -fi - -AC_SUBST(GPGKEYS_LDAP) -AC_SUBST(LDAPLIBS) - -dnl This isn't necessarily sendmail itself, but anything that gives a -dnl sendmail-ish interface to the outside world. That includes qmail, -dnl postfix, etc. Basically, anything that can handle "sendmail -t". - -if test "$try_mailto" = yes ; then - AC_ARG_WITH(mailprog,[ --with-mailprog=NAME use "NAME -t" for mail transport],,with_mailprog=yes) - - if test "$with_mailprog" = yes ; then - AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib) - if test "$ac_cv_path_SENDMAIL" ; then - GPGKEYS_MAILTO="gpgkeys_mailto" - fi - elif test "$with_mailprog" != no ; then - AC_MSG_CHECKING([for a mail transport program]) - AC_SUBST(SENDMAIL,$with_mailprog) - AC_MSG_RESULT($with_mailprog) - GPGKEYS_MAILTO="gpgkeys_mailto" - fi -fi - -AC_SUBST(GPGKEYS_MAILTO) - -case "${target}" in - *-*-mingw32*) - PRINTABLE_OS_NAME="MingW32" - ;; - *-*-cygwin*) - PRINTABLE_OS_NAME="Cygwin32" ;; i?86-emx-os2 | i?86-*-os2*emx ) PRINTABLE_OS_NAME="OS/2" @@ -488,465 +128,229 @@ AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", [A human readable text with the name of the OS]) +# I know that it is in general not a good idea to evaluate bindir in +# the configuration but we want to hard code the defaults into some of +# the programs and doing this during a make install is not a good +# idea. We also have the problem that 2 of the programs are included +# in the package but the others are distributed in other packages. +eval my_default_bindir=${exec_prefix} +test "x${my_default_bindir}" = xNONE && my_default_bindir=${ac_default_prefix} +my_default_bindir=${my_default_bindir}/bin + +AC_ARG_WITH(agent-pgm, + [ --with-agent-pgm=PATH Use PATH as the default for the gpg-agent)], + gnupg_agent_pgm="$withval", + gnupg_agent_pgm="${my_default_bindir}/gpg-agent" ) +AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_AGENT, "$gnupg_agent_pgm", + [Default location of the gpg-agent program]) +AC_ARG_WITH(pinentry-pgm, + [ --with-pinentry-pgm=PATH Use PATH as the default for the pinentry)], + gnupg_pinentry_pgm="$withval", gnupg_pinentry_pgm="" ) +if test -z "$gnupg_pinentry_pgm"; then + gnupg_pinentry_pgm=${my_default_bindir}/pinentry +fi +AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_PINENTRY, "$gnupg_pinentry_pgm", + [Default location of the pinentry program]) +AC_ARG_WITH(scdaemon-pgm, + [ --with-scdaemon-pgm=PATH Use PATH as the default for the scdaemon)], + gnupg_scdaemon_pgm="$withval", gnupg_scdaemon_pgm="" ) +if test -z "$gnupg_scdaemon_pgm"; then + gnupg_scdaemon_pgm=${my_default_bindir}/scdaemon +fi +AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_SCDAEMON, "$gnupg_scdaemon_pgm", + [Default location of the scdaemon program]) +AC_ARG_WITH(dirmngr-pgm, + [ --with-dirmngr-pgm=PATH Use PATH as the default for the dirmngr)], + gnupg_dirmngr_pgm="$withval", gnupg_dirmngr_pgm="" ) +if test -z "$gnupg_dirmngr_pgm"; then + gnupg_dirmngr_pgm=${my_default_bindir}/dirmngr +fi +AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_DIRMNGR, "$gnupg_dirmngr_pgm", + [Default location of the dirmngr program]) + + # -# 1. Set names of random devices +# Checks for libraries. # -NAME_OF_DEV_RANDOM="/dev/random" -NAME_OF_DEV_URANDOM="/dev/urandom" -case "${target}" in - *-openbsd*) - NAME_OF_DEV_RANDOM="/dev/srandom" - NAME_OF_DEV_URANDOM="/dev/urandom" - ;; -esac -AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM", - [defined to the name of the strong random device]) -AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM", - [defined to the name of the weaker random device]) -AC_SUBST(MPI_OPT_FLAGS) +# +# Libgcrypt is our generic crypto library +# +#AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config) +#if test -n "$LIBGCRYPT_CONFIG"; then +# LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` +# LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` +#else +# AC_MSG_ERROR([[ +#*** +#*** You need libgcrypt to build this program. +#*** It should be available at the same place you +#*** got this software. +#***]]) +#fi +#AC_SUBST(LIBGCRYPT_CFLAGS) +#AC_SUBST(LIBGCRYPT_LIBS) +AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_VERSION",, + AC_MSG_ERROR([[ +*** +*** libgcrypt was not found. You may want to get it from +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libgcrypt/ +*** +]])) -dnl Checks for libraries. -if test "$try_gettext" = yes; then - AM_GNU_GETTEXT -else - USE_NLS=no - USE_INCLUDED_LIBINTL=no - BUILD_INCLUDED_LIBINTL=no - AC_SUBST(USE_NLS) - AC_SUBST(USE_INCLUDED_LIBINTL) - AC_SUBST(BUILD_INCLUDED_LIBINTL) +# +# libksba is our X.509 support library +# +AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) +if test "$have_ksba" = "no"; then + AC_MSG_ERROR([[ +*** +*** You need libksba to build this program.. +*** It should be available at the same place you +*** got this software. +***]]) fi -if test "$try_dynload" = yes ; then - AC_CHECK_LIB(dl,dlopen) - if test "$ac_cv_lib_dl_dlopen" = "yes"; then - AC_DEFINE(USE_DYNAMIC_LINKING,1, - [define to enable the use of extensions]) - AC_DEFINE(HAVE_DL_DLOPEN,1, - [Defined when the dlopen function family is available]) - else - AC_CHECK_FUNCS(dlopen) - if test "$ac_cv_func_dlopen" = "yes"; then - AC_DEFINE(USE_DYNAMIC_LINKING) - AC_DEFINE(HAVE_DL_DLOPEN) - fi - fi +# +# OpenSC is needed by the SCdaemon - if it is not availbale we won't +# build the SCdaemon +# +AM_PATH_OPENSC("$NEED_OPENSC_VERSION",have_opensc=yes,have_opensc=no) + + +# +# Check whether the (highly desirable) GNU Pth library is available +# +AC_ARG_WITH(pth-prefix, + AC_HELP_STRING([--with-pth-prefix=PFX], + [prefix where GNU Pth is installed (optional)]), + pth_config_prefix="$withval", pth_config_prefix="") +if test x$pth_config_prefix != x ; then + PTH_CONFIG="$pth_config_prefix/bin/pth-config" +fi +AC_PATH_PROG(PTH_CONFIG, pth-config, no) +if test "$PTH_CONFIG" = "no"; then + AC_MSG_WARN([[ +*** +*** To support concurrent access to the gpg-agent and the SCdaemon +*** we need the support of the GNU Portable Threads Library. +*** Download it from ftp://ftp.gnu.org/gnu/pth/ +*** On a Debian GNU/Linux system you might want to try +*** apt-get install libpth-dev +***]]) else - AC_MSG_CHECKING(for dynamic loading) - DYNLINK_LDFLAGS= - DYNLINK_MOD_CFLAGS= - AC_MSG_RESULT(has been disabled) + GNUPG_PTH_VERSION_CHECK(1.3.7) + if test $have_pth = yes; then + PTH_CFLAGS=`$PTH_CONFIG --cflags` + PTH_LIBS=`$PTH_CONFIG --libs` + AC_DEFINE(USE_GNU_PTH, 1, + [Defined if the GNU Portable Thread Library should be used]) + fi fi +AC_SUBST(PTH_CFLAGS) +AC_SUBST(PTH_LIBS) -dnl Checks for header files. + +AM_GNU_GETTEXT + + +# Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(unistd.h langinfo.h termio.h locale.h) +AC_CHECK_HEADERS([string.h locale.h]) -dnl Checks for typedefs, structures, and compiler characteristics. +# Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T -AC_TYPE_MODE_T AC_TYPE_SIGNAL AC_DECL_SYS_SIGLIST -GNUPG_CHECK_ENDIAN - - GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF) GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) -GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF) -GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF) - -AC_CHECK_SIZEOF(unsigned short, 2) -AC_CHECK_SIZEOF(unsigned int, 4) -AC_CHECK_SIZEOF(unsigned long, 4) -AC_CHECK_SIZEOF(unsigned long long, 0) - -if test "$ac_cv_sizeof_unsigned_short" = "0" \ - || test "$ac_cv_sizeof_unsigned_int" = "0" \ - || test "$ac_cv_sizeof_unsigned_long" = "0"; then - AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); -fi -dnl Checks for library functions. -AC_FUNC_FSEEKO -AC_FUNC_VPRINTF -AC_FUNC_FORK -AC_CHECK_FUNCS(strerror stpcpy strsep strlwr tcgetattr strtoul mmap) -AC_CHECK_FUNCS(strcasecmp strncasecmp) -AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) -AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) -AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat) -AC_REPLACE_FUNCS(mkdtemp) +GNUPG_SYS_SO_PEERCRED -# -# check for gethrtime and run a testprogram to see whether -# it is broken. It has been reported that some Solaris and HP UX systems -# raise an SIGILL -# -AC_CACHE_CHECK([for gethrtime], - [gnupg_cv_func_gethrtime], - [AC_TRY_LINK([#include ],[ - hrtime_t tv; - tv = gethrtime(); - ], - [gnupg_cv_func_gethrtime=yes], - [gnupg_cv_func_gethrtime=no]) - ]) -if test $gnupg_cv_func_gethrtime = yes; then - AC_DEFINE([HAVE_GETHRTIME], 1, - [Define if you have the `gethrtime(2)' function.]) - AC_CACHE_CHECK([whether gethrtime is broken], - [gnupg_cv_func_broken_gethrtime], - [AC_TRY_RUN([ - #include - int main () { - hrtime_t tv; - tv = gethrtime(); - } - ], - [gnupg_cv_func_broken_gethrtime=no], - [gnupg_cv_func_broken_gethrtime=yes], - [gnupg_cv_func_broken_gethrtime=assume-no]) - ]) - if test $gnupg_cv_func_broken_gethrtime = yes; then - AC_DEFINE([HAVE_BROKEN_GETHRTIME], 1, - [Define if `gethrtime(2)' does not work correctly i.e. issues a SIGILL.]) - fi -fi - - -GNUPG_CHECK_MLOCK -GNUPG_FUNC_MKDIR_TAKES_ONE_ARG - -dnl -dnl Check whether we can use Linux capabilities as requested -dnl -if test "$use_capabilities" = "yes" ; then -use_capabilities=no -AC_CHECK_HEADERS(sys/capability.h) -if test "$ac_cv_header_sys_capability_h" = "yes" ; then - AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1) - if test "$ac_cv_lib_cap_cap_init" = "yes"; then - AC_DEFINE(USE_CAPABILITIES,1, - [define if capabilities should be used]) - LIBS="$LIBS -lcap" - use_capabilities=yes - fi -fi -if test "$use_capabilities" = "no" ; then - AC_MSG_WARN([[ -*** -*** The use of capabilities on this system is not possible. -*** You need a recent Linux kernel and some patches: -*** fcaps-2.2.9-990610.patch (kernel patch for 2.2.9) -*** fcap-module-990613.tar.gz (kernel module) -*** libcap-1.92.tar.gz (user mode library and utilities) -*** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN -*** set (filesystems menu). Be warned: This code is *really* ALPHA. -***]]) -fi -fi +# Checks for library functions. +# These are needed by libjnlib - fixme: we should have a macros for them +AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) +AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) -GNUPG_CHECK_IPC -if test "$ac_cv_header_sys_shm_h" = "yes"; then - AC_DEFINE(USE_SHM_COPROCESSING,1, - [define if the shared memory interface should be made available]) -fi +AC_CHECK_FUNCS(sigaction sigprocmask) -dnl -dnl check whether we have a random device -dnl -if test "$try_dev_random" = yes ; then - AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, - [if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then - ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) - if test "$ac_cv_have_dev_random" = yes; then - AC_DEFINE(HAVE_DEV_RANDOM,1, - [defined if the system supports a random device] ) - fi -else - AC_MSG_CHECKING(for random device) - ac_cv_have_dev_random=no - AC_MSG_RESULT(has been disabled) -fi +AC_REPLACE_FUNCS(vasprintf) +AC_REPLACE_FUNCS(fopencookie) +# FIXME: Print a warning when that fopencookie is not available. +AC_REPLACE_FUNCS(mkdtemp) +AC_REPLACE_FUNCS(fseeko ftello) +# We use jnlib, so tell other modules about it +AC_DEFINE(HAVE_JNLIB_LOGGING, 1, + [Defined if jnlib style logging fucntions are available]) -dnl -dnl Figure out the default random module. -dnl -random_modules="" -if test "$use_static_rnd" = default; then - if test "$ac_cv_have_dev_random" = yes; then - random_modules="rndlinux" - else - case "${target}" in - *-*-mingw32*|*-*-cygwin*) - random_modules="rndw32" - ;; - i?86-emx-os2|i?86-*-os2*emx) - random_modules="rndos2" - ;; - m68k-atari-mint) - random_modules="rndatari" - ;; - i?86-*-msdosdjgpp*) - : - ;; - *) - random_modules="rndlinux rndegd rndunix" - AC_DEFINE(USE_ALL_RANDOM_MODULES, 1, - [Allow to select random modules at runtime.]) - ;; - esac - fi -else - if test "$use_static_rnd" = auto; then - random_modules="rndlinux rndegd rndunix" - AC_DEFINE(USE_ALL_RANDOM_MODULES, 1) - else - random_modules="rnd$use_static_rnd"; - fi -fi -if test -z "$random_modules"; then - AC_MSG_ERROR(no random module available) -fi -print_egd_warning=no -for rndmod in $random_modules "" ; do - case "$rndmod" in - rndlinux) - AC_DEFINE(USE_RNDLINUX,1, - [Defined if the /dev/random based RNG should be used.]) - ;; - rndunix) - AC_DEFINE(USE_RNDUNIX,1, - [Defined if the default Unix RNG should be used.]) - print_egd_warning=yes - ;; - rndegd) - AC_DEFINE(USE_RNDEGD,1, - [Defined if the EGD based RNG should be used.]) - EGDLIBS=$NETLIBS - AC_SUBST(EGDLIBS) - ;; - rndw32) - AC_DEFINE(USE_RNDW32,1, - [Defined if the Windows specific RNG should be used.]) - ;; - esac -done - -dnl setup assembler stuff -AC_MSG_CHECKING(for mpi assembler functions) -if test -f $srcdir/mpi/config.links ; then - . $srcdir/mpi/config.links - AC_CONFIG_LINKS("$mpi_ln_list") - ac_cv_mpi_extra_asm_modules="$mpi_extra_modules" - ac_cv_mpi_sflags="$mpi_sflags" - ac_cv_mpi_config_done="yes" - AC_MSG_RESULT(done) -else - AC_MSG_RESULT(failed) - AC_MSG_ERROR([mpi/config.links missing!]) -fi -MPI_EXTRA_ASM_OBJS="" -show_extraasm="" -if test "$ac_cv_mpi_extra_asm_modules" != ""; then -for i in $ac_cv_mpi_extra_asm_modules; do - show_extraasm="$show_extraasm $i" - MPI_EXTRA_ASM_OBJS="$MPI_EXTRA_ASM_OBJS $i.o" -done -fi -AC_SUBST(MPI_EXTRA_ASM_OBJS) -MPI_SFLAGS="$ac_cv_mpi_sflags" -AC_SUBST(MPI_SFLAGS) - -dnl Do we have zlib? Must do it here because Solaris failed -dnl when compiling a conftest (due to the "-lz" from LIBS). -use_local_zlib=yes -if test "$g10_force_zlib" = "yes"; then - : -else - _cppflags="${CPPFLAGS}" - _ldflags="${LDFLAGS}" - - AC_ARG_WITH(zlib, - [ --with-zlib=DIR use libz in DIR],[ - if test -d "$withval"; then - CPPFLAGS="${CPPFLAGS} -I$withval/include" - LDFLAGS="${LDFLAGS} -L$withval/lib" - fi - ]) - - AC_CHECK_HEADER(zlib.h, - AC_CHECK_LIB(z, deflateInit2_, - use_local_zlib=no - LIBS="$LIBS -lz", - CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), - CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) -fi - -if test "$use_local_zlib" = yes ; then - AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, true) - AC_CONFIG_LINKS(zlib.h:zlib/zlib.h zconf.h:zlib/zconf.h ) - ZLIBS="../zlib/libzlib.a" -else - AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, false) - ZLIBS= -fi -AC_SUBST(ZLIBS) - - -# Allow users to append something to the version string without -# flagging it as development version. The user version parts is -# considered everything after a dash. -if test "$development_version" != yes; then - changequote(,)dnl - tmp_pat='[a-zA-Z]' - changequote([,])dnl - if echo "$VERSION" | sed 's/-.*//' | grep "$tmp_pat" >/dev/null ; then - development_version=yes - fi -fi -if test "$development_version" = yes; then - AC_DEFINE(IS_DEVELOPMENT_VERSION,1, - [Defined if this is not a regular release]) +# +# Decide what to build +# +if test $have_opensc = no; then + build_scdaemon=no fi -AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) - -GNUPG_CHECK_GNUMAKE - -# add some extra libs here so that previous tests don't fail for -# mysterious reasons - the final link step should bail out. -case "${target}" in - *-*-mingw32*) - LIBS="$LIBS -lwsock32" - ;; - *) - ;; -esac - - -if test "$GCC" = yes; then - if test "$USE_MAINTAINER_MODE" = "yes"; then - CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" - else - CFLAGS="$CFLAGS -Wall" - fi +if test $have_ksba = no; then + build_gpgsm=no + build_scdaemon=no fi -AC_SUBST(NETLIBS) - - -if test "$print_egd_warning" = yes; then - AC_MSG_WARN([[ -*** -*** The performance of the UNIX random gatherer module is not very good -*** and it does not keep the entropy pool over multiple invocations of -*** GnuPG. The suggested way to overcome this problem is to use the -*** -*** Entropy Gathering Daemon (EGD) -*** -*** which provides a entropy source for the whole system. It is written -*** in Perl and available at the GnuPG FTP servers. For more information -*** consult the GnuPG webpages: -*** -*** http://www.gnupg.org/download.html#egd -*** -*** You may want to run ./configure with --enable-static-rnd=egd to use it. -***]]) +build_agent_threaded="" +if test "$build_agent" = "yes"; then + if test $have_pth = no; then + build_agent_threaded="(not multi-threaded)" + fi fi +build_scdaemon_threaded="" +if test "$build_scdaemon" = "yes"; then + if test $have_pth = no; then + build_scdaemon_threaded="(not multi-threaded)" + fi +fi -# Note the \\\\ for backslashes. Autoconf eats one layer, leaving \\ - -AC_SUBST(GNUPG_LIBEXECDIR,"${libexecdir}/gnupg") - -AC_CONFIG_COMMANDS(g10defs.h,[[ -cat >g10defs.tmp <>g10defs.tmp -if cmp -s g10defs.h g10defs.tmp 2>/dev/null; then - echo "g10defs.h is unchanged" - rm -f g10defs.tmp -else - rm -f g10defs.h - mv g10defs.tmp g10defs.h - echo "g10defs.h created" -fi -]],[[ -prefix=$prefix -exec_prefix=$exec_prefix -libdir=$libdir -libexecdir=$libexecdir -datadir=$datadir -DATADIRNAME=$DATADIRNAME -]]) +AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") +AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") +AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") AC_CONFIG_FILES([ Makefile intl/Makefile po/Makefile.in -util/Makefile -mpi/Makefile -cipher/Makefile -g10/Makefile -keyserver/Makefile -keyserver/gpgkeys_mailto -keyserver/gpgkeys_test +jnlib/Makefile +assuan/Makefile +common/Makefile +kbx/Makefile +sm/Makefile +agent/Makefile +scd/Makefile doc/Makefile -tools/Makefile -zlib/Makefile -checks/Makefile +tests/Makefile ]) AC_OUTPUT -# Give some feedback -echo -echo " Configured for: $PRINTABLE_OS_NAME ($target)" -if test -n "$show_extraasm"; then - echo " Extra cpu specific functions:$show_extraasm" -fi -echo + +echo " + NewPG v${VERSION} has been configured as follows: + + OpenPGP: $build_gpg + S/MIME: $build_gpgsm + Agent: $build_agent $build_agent_threaded + Smartcard: $build_scdaemon $build_scdaemon_threaded + + Default agent: $gnupg_agent_pgm + Default pinentry: $gnupg_pinentry_pgm + Default scdaemon: $gnupg_scdaemon_pgm + Default dirmngr: $gnupg_dirmngr_pgm +" -- cgit v1.2.3 From d3b880b74c3024b54b3f593462382b6136d30a37 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Sat, 19 Oct 2002 09:27:39 +0000 Subject: * configure.ac: Bumped version number to 1.9.0-cvs. --- ChangeLog | 2 ++ NEWS | 87 +++--------------------------------------------------------- README | 4 +-- configure.ac | 5 ++-- 4 files changed, 11 insertions(+), 87 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7595565e1..832ba26ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2002-10-19 Werner Koch + * configure.ac: Bumped version number to 1.9.0-cvs. + NewPG (Aegypten project) to GnuPG merge. 2002-09-20 Werner Koch diff --git a/NEWS b/NEWS index a2dc8126e..efacfbdd7 100644 --- a/NEWS +++ b/NEWS @@ -1,90 +1,11 @@ -Noteworthy changes in version 0.9.3 (unreleased) +Noteworthy changes in version 1.9.0 (unreleased) ------------------------------------------------ - -Noteworthy changes in version 0.9.2 (2002-09-20) ------------------------------------------------- - - * The default directory structure is created if it does no exists. - - * A few more diagnostics and a minor bug fixes. - - -Noteworthy changes in version 0.9.1 (2002-08-23) ------------------------------------------------- - - * Minor fixes. - - -Noteworthy changes in version 0.9.0 (2002-08-21) ------------------------------------------------- - - * The default homedir has changed from ~/.gnupg-test to ~/.gnupg. - - * To run gpg-agent or scdaemon in the background, the option --daemon - must be used. - -Noteworthy changes in version 0.3.10 (2002-08-10) -------------------------------------------------- - - * A key may be specified by a short fingerprint; either the last 4 or - 8 bytes of the SHA-1 fingerprint. - - * Very basic regression tests implemented. - - * Signing using more than one key works on the commandline and in - server mode. - - * --import does now try to import all certificates up the chain; this - usually works only when the new option --auto-issuer-key-retrieve - is also used. - - * New command --delete-key. Note that in contrast to gpg this is not - interactive. - -Noteworthy changes in version 0.3.9 (2002-07-01) ------------------------------------------------- - - * The protect-tool does now make use of the gpg-agent to query a - passphrase. - - * The default path of the daemons are now set to a more common value - and there are configure options to change them. - -Noteworthy changes in version 0.3.8 (2002-06-25) ------------------------------------------------- - - * The protect-tool has now a feature to extract a private RSA key - from a PKCS-12 file and convert it into the gpg-agent format. - - * A bunch of big fixes and changes for improved interoperability. - - * gpgsm can now create non-detached signatures. - -Noteworthy changes in version 0.3.7 (2002-06-04) ------------------------------------------------- - - * More user friendly output for --list-keys without --with-colons. - New --list-sigs to show the certification path. - - * gpg-agent handles concurrent connections. - - * gpgsm --import can now handle certs-only messages. - -Noteworthy changes in version 0.3.6 (2002-05-03) ------------------------------------------------- - - * Some cleanups. - -Noteworthy changes in version 0.3.5 (2002-04-15) ------------------------------------------------- - - * Checks key usage and uses the authorithyKeyIdentifier. - - * Basic SC support for TCOS card using a patched version of OpenSC. + * Merged stuff from the newpg branch and started this new + development branch. - Copyright 2002 g10 Code GmbH + 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 diff --git a/README b/README index 93dc1c8f0..7796a9436 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -NewPG is a temporary protect to work on GnuPG extensions. It will be -merged into the regular GnuPG sources for a GnuPG 2.0 release. +GnuPG 1.9 is a temporary protect to work on GnuPG extensions. It will +eventually lead to a GnuPG 2.0 release. jnlib/ utility functions assuan/ assuan protocol library diff --git a/configure.ac b/configure.ac index 8294fb3c4..ac31adf05 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# configure.ac - for NewPG +# configure.ac - for GnuPG # Copyright (C) 2001, 2002 Free Software Foundation, Inc, # # This file is part of GnuPG. @@ -21,7 +21,7 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(newpg, 0.9.3-cvs, gpa-dev@gnupg.org) +AC_INIT(newpg, 1.9.0-cvs, gpa-dev@gnupg.org) NEED_LIBGCRYPT_VERSION=1.1.8 NEED_KSBA_VERSION=0.4.4 NEED_OPENSC_VERSION=0.7.0 @@ -30,6 +30,7 @@ ALL_LINGUAS="de" PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION +AC_CONFIG_AUX_DIR(scripts) AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE($PACKAGE, $VERSION) -- cgit v1.2.3 From 11d5db1dcbfa4646e4106e1849044a8c448c93fd Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 9 Jan 2003 12:36:05 +0000 Subject: Updated from NewPG --- jnlib/ChangeLog | 124 ++++++ jnlib/Makefile.am | 40 ++ jnlib/README | 7 + jnlib/argparse.c | 997 ++++++++++++++++++++++++++++++++++++++++++++++++ jnlib/argparse.h | 67 ++++ jnlib/dotlock.c | 346 +++++++++++++++++ jnlib/dotlock.h | 32 ++ jnlib/libjnlib-config.h | 72 ++++ jnlib/logging.c | 347 +++++++++++++++++ jnlib/logging.h | 76 ++++ jnlib/mischelp.h | 43 +++ jnlib/stringhelp.c | 474 +++++++++++++++++++++++ jnlib/stringhelp.h | 84 ++++ jnlib/strlist.c | 133 +++++++ jnlib/strlist.h | 43 +++ jnlib/types.h | 101 +++++ jnlib/xmalloc.c | 88 +++++ jnlib/xmalloc.h | 31 ++ 18 files changed, 3105 insertions(+) create mode 100644 jnlib/ChangeLog create mode 100644 jnlib/Makefile.am create mode 100644 jnlib/README create mode 100644 jnlib/argparse.c create mode 100644 jnlib/argparse.h create mode 100644 jnlib/dotlock.c create mode 100644 jnlib/dotlock.h create mode 100644 jnlib/libjnlib-config.h create mode 100644 jnlib/logging.c create mode 100644 jnlib/logging.h create mode 100644 jnlib/mischelp.h create mode 100644 jnlib/stringhelp.c create mode 100644 jnlib/stringhelp.h create mode 100644 jnlib/strlist.c create mode 100644 jnlib/strlist.h create mode 100644 jnlib/types.h create mode 100644 jnlib/xmalloc.c create mode 100644 jnlib/xmalloc.h diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog new file mode 100644 index 000000000..41bf3d3bd --- /dev/null +++ b/jnlib/ChangeLog @@ -0,0 +1,124 @@ +2002-06-04 Werner Koch + + * stringhelp.c (print_sanitized_utf8_string): New. No real + implementation for now. + (print_sanitized_utf8_buffer): Ditto. + +2002-04-04 Werner Koch + + * logging.c (log_get_prefix): New. + +2002-03-15 Werner Koch + + * argparse.c (optfile_parse): Fixed missing argument handling. + +2002-02-25 Werner Koch + + * stringhelp.c (ascii_memcasemem): New. + +2002-02-14 Werner Koch + + * Makefile.am (INCLUDES): Add cflags for libgcrypt. + +2002-02-07 Werner Koch + + * logging.c (log_set_fd): New. + + * stringhelp.c (print_sanitized_buffer): New. + (print_sanitized_string): New. + +2002-01-24 Werner Koch + + * argparse.c (strusage): Set default copyright notice year to 2002. + + Fixed the copyright notice of this file, as it has always been + part of GnuPG and therefore belongs to the FSF. + +2001-11-01 Marcus Brinkmann + + * logging.c (log_printf): Do not initialize ARG_PTR with 0, we + don't know the correct type. Instead, run va_start and va_end + unconditionally. + Reported by Jose Carlos Garcia Sogo . + +2002-01-19 Werner Koch + + * logging.c (log_get_stream): New. + +2001-12-05 Werner Koch + + * logging.c (log_set_prefix): New. + (do_logv): Include prefix and pid only if enabled. Print time only + when explicitly enabled. + (log_logv): New. + * logging.h: Include log_logv() only when requested. + +2001-11-06 Werner Koch + + * strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c + +2001-08-30 Werner Koch + + * logging.c (log_printf): Don't pass NULL instead of arg_ptr. + +2001-07-19 Werner Koch + + * stringhelp.c (ascii_memistr,ascii_isupper,ascii_islower, + ascii_toupper,ascii_tolower, ascii_strcasecmp, ascii_memcasecmp): New. + +2000-07-26 10:02:51 Werner Koch (wk@habibti.openit.de) + + * stringhelp.c.: Add stdarg.h + * argparse.h: s/ulong/unsigned long/ although this should be defined + by types.h. + +2000-06-28 19:40:23 Werner Koch (wk@habibti.openit.de) + + * Makefile.am: Replaced second logging.c by .h + +2000-05-24 08:58:15 Werner Koch (wk@habibti.openit.de) + + * logging.c (log_get_errorcount): New. + +2000-05-24 08:44:47 Werner Koch (wk@habibti.openit.de) + + * stringhelp.c: Added a few filename related helper functions. + +2000-05-11 18:04:43 Werner Koch (wk@habibti.openit.de) + + * xmalloc.c (xstrcat2): Replaced stpcpy to quickly address W32 + problems. + +2000-05-02 19:43:38 Werner Koch (wk@habibti.openit.de) + + * xmalloc.c (xstrcat2): New. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch + + * README: New. + * Makefile.am: new. + * argparse.c argparse.h logging.c logging.h + mischelp.h stringhelp.c stringhelp.h xmalloc.c + xmalloc.h dotlock.c: Moved from ../util to here. + * dotlock.h: New. + * libjnlib-config.h: New. + + * logging.c (log_set_file): New. + (log_printf): New. + (do_logv): Add kludge to insert LFs. + + + *********************************************************** + * Please note that Jnlib is maintained as part of GnuPG. * + * You may find it source-copied in other packages. * + *********************************************************** + + Copyright 2000, 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. diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am new file mode 100644 index 000000000..303ffe3cb --- /dev/null +++ b/jnlib/Makefile.am @@ -0,0 +1,40 @@ +# Copyright (C) 1999, 2000, 2001 Feee Software Soundation, 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 = README + +# We need libgcrypt becuase libjnlib-confilig includes gcrypt.h +INCLUDES = -I$(top_srcdir)/intl $(LIBGCRYPT_CFLAGS) + +noinst_LIBRARIES = libjnlib.a + + +#libjnlib_a_LDFLAGS = +libjnlib_a_SOURCES = \ + libjnlib-config.h \ + stringhelp.c stringhelp.h \ + strlist.c strlist.h \ + argparse.c argparse.h \ + logging.c logging.h \ + dotlock.c dotlock.h \ + types.h mischelp.h + +# xmalloc.c xmalloc.h + diff --git a/jnlib/README b/jnlib/README new file mode 100644 index 000000000..e49ef4450 --- /dev/null +++ b/jnlib/README @@ -0,0 +1,7 @@ +jnlib - this is a collection of utility function which are +too small to put into a library. + +libjnlib-config.h should be be modified for each project +to make these functions fit into the software. Mainly these +are memory functions in case you need another allocator. + diff --git a/jnlib/argparse.c b/jnlib/argparse.c new file mode 100644 index 000000000..0eb99d452 --- /dev/null +++ b/jnlib/argparse.c @@ -0,0 +1,997 @@ +/* [argparse.c wk 17.06.97] Argument Parser for option handling + * 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 +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "mischelp.h" +#include "stringhelp.h" +#include "logging.h" +#include "argparse.h" + + +/********************************* + * @Summary arg_parse + * #include + * + * typedef struct { + * char *argc; pointer to argc (value subject to change) + * char ***argv; pointer to argv (value subject to change) + * unsigned flags; Global flags (DO NOT CHANGE) + * int err; print error about last option + * 1 = warning, 2 = abort + * int r_opt; return option + * int r_type; type of return value (0 = no argument found) + * union { + * int ret_int; + * long ret_long + * ulong ret_ulong; + * char *ret_str; + * } r; Return values + * struct { + * int idx; + * const char *last; + * void *aliases; + * } internal; DO NOT CHANGE + * } ARGPARSE_ARGS; + * + * typedef struct { + * int short_opt; + * const char *long_opt; + * unsigned flags; + * } ARGPARSE_OPTS; + * + * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts ); + * + * @Description + * This is my replacement for getopt(). See the example for a typical usage. + * Global flags are: + * Bit 0 : Do not remove options form argv + * Bit 1 : Do not stop at last option but return other args + * with r_opt set to -1. + * Bit 2 : Assume options and real args are mixed. + * Bit 3 : Do not use -- to stop option processing. + * Bit 4 : Do not skip the first arg. + * Bit 5 : allow usage of long option with only one dash + * Bit 6 : ignore --version + * all other bits must be set to zero, this value is modified by the + * function, so assume this is write only. + * Local flags (for each option): + * Bit 2-0 : 0 = does not take an argument + * 1 = takes int argument + * 2 = takes string argument + * 3 = takes long argument + * 4 = takes ulong argument + * Bit 3 : argument is optional (r_type will the be set to 0) + * Bit 4 : allow 0x etc. prefixed values. + * Bit 7 : this is a command and not an option + * You stop the option processing by setting opts to NULL, the function will + * then return 0. + * @Return Value + * Returns the args.r_opt or 0 if ready + * r_opt may be -2/-7 to indicate an unknown option/command. + * @See Also + * ArgExpand + * @Notes + * You do not need to process the options 'h', '--help' or '--version' + * because this function includes standard help processing; but if you + * specify '-h', '--help' or '--version' you have to do it yourself. + * The option '--' stops argument processing; if bit 1 is set the function + * continues to return normal arguments. + * To process float args or unsigned args you must use a string args and do + * the conversion yourself. + * @Example + * + * ARGPARSE_OPTS opts[] = { + * { 'v', "verbose", 0 }, + * { 'd', "debug", 0 }, + * { 'o', "output", 2 }, + * { 'c', "cross-ref", 2|8 }, + * { 'm', "my-option", 1|8 }, + * { 500, "have-no-short-option-for-this-long-option", 0 }, + * {0} }; + * ARGPARSE_ARGS pargs = { &argc, &argv, 0 } + * + * while( ArgParse( &pargs, &opts) ) { + * switch( pargs.r_opt ) { + * case 'v': opt.verbose++; break; + * case 'd': opt.debug++; break; + * case 'o': opt.outfile = pargs.r.ret_str; break; + * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; + * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; + * case 500: opt.a_long_one++; break + * default : pargs.err = 1; break; -- force warning output -- + * } + * } + * if( argc > 1 ) + * log_fatal( "Too many args"); + * + */ + +typedef struct alias_def_s *ALIAS_DEF; +struct alias_def_s { + ALIAS_DEF next; + char *name; /* malloced buffer with name, \0, value */ + const char *value; /* ptr into name */ +}; + +static const char *(*strusage_handler)( int ) = NULL; + +static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s); +static void show_help(ARGPARSE_OPTS *opts, unsigned flags); +static void show_version(void); + + +static void +initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) +{ + if( !(arg->flags & (1<<15)) ) { /* initialize this instance */ + arg->internal.idx = 0; + arg->internal.last = NULL; + arg->internal.inarg = 0; + arg->internal.stopped = 0; + arg->internal.aliases = NULL; + arg->internal.cur_alias = NULL; + arg->err = 0; + arg->flags |= 1<<15; /* mark initialized */ + if( *arg->argc < 0 ) + jnlib_log_bug("Invalid argument for ArgParse\n"); + } + + + if( arg->err ) { /* last option was erroneous */ + const char *s; + + if( filename ) { + if( arg->r_opt == -6 ) + s = "%s:%u: argument not expected\n"; + else if( arg->r_opt == -5 ) + s = "%s:%u: read error\n"; + else if( arg->r_opt == -4 ) + s = "%s:%u: keyword too long\n"; + else if( arg->r_opt == -3 ) + s = "%s:%u: missing argument\n"; + else if( arg->r_opt == -7 ) + s = "%s:%u: invalid command\n"; + else if( arg->r_opt == -10 ) + s = "%s:%u: invalid alias definition\n"; + else + s = "%s:%u: invalid option\n"; + jnlib_log_error(s, filename, *lineno ); + } + else { + if( arg->r_opt == -3 ) + s = "Missing argument for option \"%.50s\"\n"; + else if( arg->r_opt == -6 ) + s = "Option \"%.50s\" does not expect an argument\n"; + else if( arg->r_opt == -7 ) + s = "Invalid command \"%.50s\"\n"; + else if( arg->r_opt == -8 ) + s = "Option \"%.50s\" is ambiguous\n"; + else if( arg->r_opt == -9 ) + s = "Command \"%.50s\" is ambiguous\n"; + else + s = "Invalid option \"%.50s\"\n"; + jnlib_log_error(s, arg->internal.last? arg->internal.last:"[??]" ); + } + if( arg->err != 1 ) + exit(2); + arg->err = 0; + } + + /* clearout the return value union */ + arg->r.ret_str = NULL; + arg->r.ret_long= 0; +} + + +static void +store_alias( ARGPARSE_ARGS *arg, char *name, char *value ) +{ + /* TODO: replace this dummy function with a rea one + * and fix the probelms IRIX has with (ALIAS_DEV)arg.. + * used as lvalue + */ +#if 0 + ALIAS_DEF a = jnlib_xmalloc( sizeof *a ); + a->name = name; + a->value = value; + a->next = (ALIAS_DEF)arg->internal.aliases; + (ALIAS_DEF)arg->internal.aliases = a; +#endif +} + +/**************** + * Get options from a file. + * Lines starting with '#' are comment lines. + * Syntax is simply a keyword and the argument. + * Valid keywords are all keywords from the long_opt list without + * the leading dashes. The special keywords "help", "warranty" and "version" + * are not valid here. + * The special keyword "alias" may be used to store alias definitions, + * which are later expanded like long options. + * Caller must free returned strings. + * If called with FP set to NULL command line args are parse instead. + * + * Q: Should we allow the syntax + * keyword = value + * and accept for boolean options a value of 1/0, yes/no or true/false? + * Note: Abbreviation of options is here not allowed. + */ +int +optfile_parse( FILE *fp, const char *filename, unsigned *lineno, + ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) +{ + int state, i, c; + int idx=0; + char keyword[100]; + char *buffer = NULL; + size_t buflen = 0; + int inverse=0; + int in_alias=0; + + if( !fp ) /* same as arg_parse() in this case */ + return arg_parse( arg, opts ); + + initialize( arg, filename, lineno ); + + /* find the next keyword */ + state = i = 0; + for(;;) { + c=getc(fp); + if( c == '\n' || c== EOF ) { + if( c != EOF ) + ++*lineno; + if( state == -1 ) + break; + else if( state == 2 ) { + keyword[i] = 0; + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) + break; + idx = i; + arg->r_opt = opts[idx].short_opt; + if( inverse ) /* this does not have an effect, hmmm */ + arg->r_opt = -arg->r_opt; + if( !opts[idx].short_opt ) /* unknown command/option */ + arg->r_opt = (opts[idx].flags & 256)? -7:-2; + else if( !(opts[idx].flags & 7) ) /* does not take an arg */ + arg->r_type = 0; /* okay */ + else if( (opts[idx].flags & 8) ) /* argument is optional */ + arg->r_type = 0; /* okay */ + else /* required argument */ + arg->r_opt = -3; /* error */ + break; + } + else if( state == 3 ) { /* no argument found */ + if( in_alias ) + arg->r_opt = -3; /* error */ + else if( !(opts[idx].flags & 7) ) /* does not take an arg */ + arg->r_type = 0; /* okay */ + else if( (opts[idx].flags & 8) ) /* no optional argument */ + arg->r_type = 0; /* okay */ + else /* no required argument */ + arg->r_opt = -3; /* error */ + break; + } + else if( state == 4 ) { /* have an argument */ + if( in_alias ) { + if( !buffer ) + arg->r_opt = -6; + else { + char *p; + + buffer[i] = 0; + p = strpbrk( buffer, " \t" ); + if( p ) { + *p++ = 0; + trim_spaces( p ); + } + if( !p || !*p ) { + jnlib_free( buffer ); + arg->r_opt = -10; + } + else { + store_alias( arg, buffer, p ); + } + } + } + else if( !(opts[idx].flags & 7) ) /* does not take an arg */ + arg->r_opt = -6; /* error */ + else { + char *p; + if( !buffer ) { + keyword[i] = 0; + buffer = jnlib_xstrdup(keyword); + } + else + buffer[i] = 0; + + trim_spaces( buffer ); + p = buffer; + if( *p == '"' ) { /* remove quotes */ + p++; + if( *p && p[strlen(p)-1] == '"' ) + p[strlen(p)-1] = 0; + } + if( !set_opt_arg(arg, opts[idx].flags, p) ) + jnlib_free(buffer); + } + break; + } + else if( c == EOF ) { + if( ferror(fp) ) + arg->r_opt = -5; /* read error */ + else + arg->r_opt = 0; /* eof */ + break; + } + state = 0; + i = 0; + } + else if( state == -1 ) + ; /* skip */ + else if( !state && isspace(c) ) + ; /* skip leading white space */ + else if( !state && c == '#' ) + state = 1; /* start of a comment */ + else if( state == 1 ) + ; /* skip comments */ + else if( state == 2 && isspace(c) ) { + keyword[i] = 0; + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) + break; + idx = i; + arg->r_opt = opts[idx].short_opt; + if( !opts[idx].short_opt ) { + if( !strcmp( keyword, "alias" ) ) { + in_alias = 1; + state = 3; + } + else { + arg->r_opt = (opts[idx].flags & 256)? -7:-2; + state = -1; /* skip rest of line and leave */ + } + } + else + state = 3; + } + else if( state == 3 ) { /* skip leading spaces of the argument */ + if( !isspace(c) ) { + i = 0; + keyword[i++] = c; + state = 4; + } + } + else if( state == 4 ) { /* collect the argument */ + if( buffer ) { + if( i < buflen-1 ) + buffer[i++] = c; + else { + buflen += 50; + buffer = jnlib_xrealloc(buffer, buflen); + buffer[i++] = c; + } + } + else if( i < DIM(keyword)-1 ) + keyword[i++] = c; + else { + buflen = DIM(keyword)+50; + buffer = jnlib_xmalloc(buflen); + memcpy(buffer, keyword, i); + buffer[i++] = c; + } + } + else if( i >= DIM(keyword)-1 ) { + arg->r_opt = -4; /* keyword to long */ + state = -1; /* skip rest of line and leave */ + } + else { + keyword[i++] = c; + state = 2; + } + } + + return arg->r_opt; +} + + + +static int +find_long_option( ARGPARSE_ARGS *arg, + ARGPARSE_OPTS *opts, const char *keyword ) +{ + int i; + size_t n; + + /* Would be better if we can do a binary search, but it is not + possible to reorder our option table because we would mess + up our help strings - What we can do is: Build a nice option + lookup table wehn this function is first invoked */ + if( !*keyword ) + return -1; + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) + return i; + #if 0 + { + ALIAS_DEF a; + /* see whether it is an alias */ + for( a = args->internal.aliases; a; a = a->next ) { + if( !strcmp( a->name, keyword) ) { + /* todo: must parse the alias here */ + args->internal.cur_alias = a; + return -3; /* alias available */ + } + } + } + #endif + /* not found, see whether it is an abbreviation */ + /* aliases may not be abbreviated */ + n = strlen( keyword ); + for(i=0; opts[i].short_opt; i++ ) { + if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { + int j; + for(j=i+1; opts[j].short_opt; j++ ) { + if( opts[j].long_opt + && !strncmp( opts[j].long_opt, keyword, n ) ) + return -2; /* abbreviation is ambiguous */ + } + return i; + } + } + return -1; +} + +int +arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) +{ + int idx; + int argc; + char **argv; + char *s, *s2; + int i; + + initialize( arg, NULL, NULL ); + argc = *arg->argc; + argv = *arg->argv; + idx = arg->internal.idx; + + if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */ + argc--; argv++; idx++; + } + + next_one: + if( !argc ) { /* no more args */ + arg->r_opt = 0; + goto leave; /* ready */ + } + + s = *argv; + arg->internal.last = s; + + if( arg->internal.stopped && (arg->flags & (1<<1)) ) { + arg->r_opt = -1; /* not an option but a argument */ + arg->r_type = 2; + arg->r.ret_str = s; + argc--; argv++; idx++; /* set to next one */ + } + else if( arg->internal.stopped ) { /* ready */ + arg->r_opt = 0; + goto leave; + } + else if( *s == '-' && s[1] == '-' ) { /* long option */ + char *argpos; + + arg->internal.inarg = 0; + if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */ + arg->internal.stopped = 1; + argc--; argv++; idx++; + goto next_one; + } + + argpos = strchr( s+2, '=' ); + if( argpos ) + *argpos = 0; + i = find_long_option( arg, opts, s+2 ); + if( argpos ) + *argpos = '='; + + if( i < 0 && !strcmp( "help", s+2) ) + show_help(opts, arg->flags); + else if( i < 0 && !strcmp( "version", s+2) ) { + if( !(arg->flags & (1<<6)) ) { + show_version(); + exit(0); + } + } + else if( i < 0 && !strcmp( "warranty", s+2) ) { + puts( strusage(16) ); + exit(0); + } + else if( i < 0 && !strcmp( "dump-options", s+2) ) { + for(i=0; opts[i].short_opt; i++ ) { + if( opts[i].long_opt ) + printf( "--%s\n", opts[i].long_opt ); + } + fputs("--dump-options\n--help\n--version\n--warranty\n", stdout ); + exit(0); + } + + if( i == -2 ) /* ambiguous option */ + arg->r_opt = -8; + else if( i == -1 ) { + arg->r_opt = -2; + arg->r.ret_str = s+2; + } + else + arg->r_opt = opts[i].short_opt; + if( i < 0 ) + ; + else if( (opts[i].flags & 7) ) { + if( argpos ) { + s2 = argpos+1; + if( !*s2 ) + s2 = NULL; + } + else + s2 = argv[1]; + if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/ + arg->r_type = 0; /* because it is optional */ + } + else if( !s2 ) { + arg->r_opt = -3; /* missing argument */ + } + else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) { + /* the argument is optional and the next seems to be + * an option. We do not check this possible option + * but assume no argument */ + arg->r_type = 0; + } + else { + set_opt_arg(arg, opts[i].flags, s2); + if( !argpos ) { + argc--; argv++; idx++; /* skip one */ + } + } + } + else { /* does not take an argument */ + if( argpos ) + arg->r_type = -6; /* argument not expected */ + else + arg->r_type = 0; + } + argc--; argv++; idx++; /* set to next one */ + } + else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */ + int dash_kludge = 0; + i = 0; + if( !arg->internal.inarg ) { + arg->internal.inarg++; + if( arg->flags & (1<<5) ) { + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) { + dash_kludge=1; + break; + } + } + } + s += arg->internal.inarg; + + if( !dash_kludge ) { + for(i=0; opts[i].short_opt; i++ ) + if( opts[i].short_opt == *s ) + break; + } + + if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) + show_help(opts, arg->flags); + + arg->r_opt = opts[i].short_opt; + if( !opts[i].short_opt ) { + arg->r_opt = (opts[i].flags & 256)? -7:-2; + arg->internal.inarg++; /* point to the next arg */ + arg->r.ret_str = s; + } + else if( (opts[i].flags & 7) ) { + if( s[1] && !dash_kludge ) { + s2 = s+1; + set_opt_arg(arg, opts[i].flags, s2); + } + else { + s2 = argv[1]; + if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/ + arg->r_type = 0; /* because it is optional */ + } + else if( !s2 ) { + arg->r_opt = -3; /* missing argument */ + } + else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) { + /* the argument is optional and the next seems to be + * an option. We do not check this possible option + * but assume no argument */ + arg->r_type = 0; + } + else { + set_opt_arg(arg, opts[i].flags, s2); + argc--; argv++; idx++; /* skip one */ + } + } + s = "x"; /* so that !s[1] yields false */ + } + else { /* does not take an argument */ + arg->r_type = 0; + arg->internal.inarg++; /* point to the next arg */ + } + if( !s[1] || dash_kludge ) { /* no more concatenated short options */ + arg->internal.inarg = 0; + argc--; argv++; idx++; + } + } + else if( arg->flags & (1<<2) ) { + arg->r_opt = -1; /* not an option but a argument */ + arg->r_type = 2; + arg->r.ret_str = s; + argc--; argv++; idx++; /* set to next one */ + } + else { + arg->internal.stopped = 1; /* stop option processing */ + goto next_one; + } + + leave: + *arg->argc = argc; + *arg->argv = argv; + arg->internal.idx = idx; + return arg->r_opt; +} + + + +static int +set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s) +{ + int base = (flags & 16)? 0 : 10; + + switch( arg->r_type = (flags & 7) ) { + case 1: /* takes int argument */ + arg->r.ret_int = (int)strtol(s,NULL,base); + return 0; + case 3: /* takes long argument */ + arg->r.ret_long= strtol(s,NULL,base); + return 0; + case 4: /* takes ulong argument */ + arg->r.ret_ulong= strtoul(s,NULL,base); + return 0; + case 2: /* takes string argument */ + default: + arg->r.ret_str = s; + return 1; + } +} + + +static size_t +long_opt_strlen( ARGPARSE_OPTS *o ) +{ + size_t n = strlen(o->long_opt); + + if( o->description && *o->description == '|' ) { + const char *s; + + s=o->description+1; + if( *s != '=' ) + n++; + for(; *s && *s != '|'; s++ ) + n++; + } + return n; +} + +/**************** + * Print formatted help. The description string has some special + * meanings: + * - A description string which is "@" suppresses help output for + * this option + * - a description,ine which starts with a '@' and is followed by + * any other characters is printed as is; this may be used for examples + * ans such. + * - A description which starts with a '|' outputs the string between this + * bar and the next one as arguments of the long option. + */ +static void +show_help( ARGPARSE_OPTS *opts, unsigned flags ) +{ + const char *s; + + show_version(); + putchar('\n'); + s = strusage(41); + puts(s); + if( opts[0].description ) { /* auto format the option description */ + int i,j, indent; + /* get max. length of long options */ + for(i=indent=0; opts[i].short_opt; i++ ) { + if( opts[i].long_opt ) + if( !opts[i].description || *opts[i].description != '@' ) + if( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) + indent = j; + } + /* example: " -v, --verbose Viele Sachen ausgeben" */ + indent += 10; + if( *opts[0].description != '@' ) + puts("Options:"); + for(i=0; opts[i].short_opt; i++ ) { + s = _( opts[i].description ); + if( s && *s== '@' && !s[1] ) /* hide this line */ + continue; + if( s && *s == '@' ) { /* unindented comment only line */ + for(s++; *s; s++ ) { + if( *s == '\n' ) { + if( s[1] ) + putchar('\n'); + } + else + putchar(*s); + } + putchar('\n'); + continue; + } + + j = 3; + if( opts[i].short_opt < 256 ) { + printf(" -%c", opts[i].short_opt ); + if( !opts[i].long_opt ) { + if(s && *s == '|' ) { + putchar(' '); j++; + for(s++ ; *s && *s != '|'; s++, j++ ) + putchar(*s); + if( *s ) + s++; + } + } + } + else + fputs(" ", stdout); + if( opts[i].long_opt ) { + j += printf("%c --%s", opts[i].short_opt < 256?',':' ', + opts[i].long_opt ); + if(s && *s == '|' ) { + if( *++s != '=' ) { + putchar(' '); + j++; + } + for( ; *s && *s != '|'; s++, j++ ) + putchar(*s); + if( *s ) + s++; + } + fputs(" ", stdout); + j += 3; + } + for(;j < indent; j++ ) + putchar(' '); + if( s ) { + if( *s && j > indent ) { + putchar('\n'); + for(j=0;j < indent; j++ ) + putchar(' '); + } + for(; *s; s++ ) { + if( *s == '\n' ) { + if( s[1] ) { + putchar('\n'); + for(j=0;j < indent; j++ ) + putchar(' '); + } + } + else + putchar(*s); + } + } + putchar('\n'); + } + if( flags & 32 ) + puts("\n(A single dash may be used instead of the double ones)"); + } + if( (s=strusage(19)) ) { /* bug reports to ... */ + putchar('\n'); + fputs(s, stdout); + } + fflush(stdout); + exit(0); +} + +static void +show_version() +{ + const char *s; + int i; + /* version line */ + fputs(strusage(11), stdout); + if( (s=strusage(12)) ) + printf(" (%s)", s ); + printf(" %s\n", strusage(13) ); + /* additional version lines */ + for(i=20; i < 30; i++ ) + if( (s=strusage(i)) ) + printf("%s\n", s ); + /* copyright string */ + if( (s=strusage(14)) ) + printf("%s\n", s ); + /* copying conditions */ + if( (s=strusage(15)) ) + fputs(s, stdout); + /* thanks */ + if( (s=strusage(18)) ) + fputs(s, stdout); + /* additional program info */ + for(i=30; i < 40; i++ ) + if( (s=strusage(i)) ) + fputs( (const byte*)s, stdout); + fflush(stdout); +} + + +void +usage( int level ) +{ + if( !level ) { + fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13), + strusage(14) ); + fflush(stderr); + } + else if( level == 1 ) { + fputs(strusage(40),stderr); + exit(2); + } + else if( level == 2 ) { + puts(strusage(41)); + exit(0); + } +} + +/* Level + * 0: Copyright String auf stderr ausgeben + * 1: Kurzusage auf stderr ausgeben und beenden + * 2: Langusage auf stdout ausgeben und beenden + * 11: name of program + * 12: optional name of package which includes this program. + * 13: version string + * 14: copyright string + * 15: Short copying conditions (with LFs) + * 16: Long copying conditions (with LFs) + * 17: Optional printable OS name + * 18: Optional thanks list (with LFs) + * 19: Bug report info + *20..29: Additional lib version strings. + *30..39: Additional program info (with LFs) + * 40: short usage note (with LF) + * 41: long usage note (with LF) + */ +const char * +strusage( int level ) +{ + const char *p = strusage_handler? strusage_handler(level) : NULL; + + if( p ) + return p; + + switch( level ) { + case 11: p = "foo"; break; + case 13: p = "0.0"; break; + case 14: p = "Copyright (C) 2002 Free Software Foundation, Inc."; break; + case 15: p = +"This program comes with ABSOLUTELY NO WARRANTY.\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions. See the file COPYING for details.\n"; break; + case 16: p = +"This is free software; you can redistribute it and/or modify\n" +"it under the terms of the GNU General Public License as published by\n" +"the Free Software Foundation; either version 2 of the License, or\n" +"(at your option) any later version.\n\n" +"It is distributed in the hope that it will be useful,\n" +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +"GNU General Public License for more details.\n\n" +"You should have received a copy of the GNU General Public License\n" +"along with this program; if not, write to the Free Software\n" +"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"; + break; + case 40: /* short and long usage */ + case 41: p = ""; break; + } + + return p; +} + +void +set_strusage( const char *(*f)( int ) ) +{ + strusage_handler = f; +} + + +#ifdef TEST +static struct { + int verbose; + int debug; + char *outfile; + char *crf; + int myopt; + int echo; + int a_long_one; +}opt; + +int +main(int argc, char **argv) +{ + ARGPARSE_OPTS opts[] = { + { 'v', "verbose", 0 , "Laut sein"}, + { 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"}, + { 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"}, + { 'o', "output", 2 }, + { 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" }, + { 'm', "my-option", 1|8 }, + { 500, "a-long-option", 0 }, + {0} }; + ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 }; + int i; + + while( ArgParse( &pargs, opts) ) { + switch( pargs.r_opt ) { + case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break; + case 'v': opt.verbose++; break; + case 'e': opt.echo++; break; + case 'd': opt.debug++; break; + case 'o': opt.outfile = pargs.r.ret_str; break; + case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; + case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; + case 500: opt.a_long_one++; break; + default : pargs.err = 1; break; /* force warning output */ + } + } + for(i=0; i < argc; i++ ) + printf("%3d -> (%s)\n", i, argv[i] ); + puts("Options:"); + if( opt.verbose ) + printf(" verbose=%d\n", opt.verbose ); + if( opt.debug ) + printf(" debug=%d\n", opt.debug ); + if( opt.outfile ) + printf(" outfile=`%s'\n", opt.outfile ); + if( opt.crf ) + printf(" crffile=`%s'\n", opt.crf ); + if( opt.myopt ) + printf(" myopt=%d\n", opt.myopt ); + if( opt.a_long_one ) + printf(" a-long-one=%d\n", opt.a_long_one ); + if( opt.echo ) + printf(" echo=%d\n", opt.echo ); + return 0; +} +#endif + +/**** bottom of file ****/ diff --git a/jnlib/argparse.h b/jnlib/argparse.h new file mode 100644 index 000000000..e8922faa4 --- /dev/null +++ b/jnlib/argparse.h @@ -0,0 +1,67 @@ +/* argparse.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 LIBJNLIB_ARGPARSE_H +#define LIBJNLIB_ARGPARSE_H + +#include +#include "types.h" + +typedef struct { + int *argc; /* pointer to argc (value subject to change) */ + char ***argv; /* pointer to argv (value subject to change) */ + unsigned flags; /* Global flags (DO NOT CHANGE) */ + int err; /* print error about last option */ + /* 1 = warning, 2 = abort */ + int r_opt; /* return option */ + int r_type; /* type of return value (0 = no argument found)*/ + union { + int ret_int; + long ret_long; + unsigned long ret_ulong; + char *ret_str; + } r; /* Return values */ + struct { + int idx; + int inarg; + int stopped; + const char *last; + void *aliases; + const void *cur_alias; + } internal; /* DO NOT CHANGE */ +} ARGPARSE_ARGS; + +typedef struct { + int short_opt; + const char *long_opt; + unsigned flags; + const char *description; /* optional option description */ +} ARGPARSE_OPTS; + + + +int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, + ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +void usage( int level ); +const char *strusage( int level ); +void set_strusage( const char *(*f)( int ) ); + +#endif /*LIBJNLIB_ARGPARSE_H*/ diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c new file mode 100644 index 000000000..772c770e8 --- /dev/null +++ b/jnlib/dotlock.c @@ -0,0 +1,346 @@ +/* dotlock.c - dotfile locking + * Copyright (C) 1998,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 +#include +#include +#include +#include +#include +#include +#ifndef HAVE_DOSISH_SYSTEM +#include +#endif +#include +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "dotlock.h" + +struct dotlock_handle { + struct dotlock_handle *next; + char *tname; /* name of lockfile template */ + char *lockname; /* name of the real lockfile */ + int locked; /* lock status */ +}; + + +static DOTLOCK all_lockfiles; + +static int read_lockfile( const char *name ); +static void remove_lockfiles(void); + +/**************** + * Create a lockfile with the given name and return an object of + * type DOTLOCK which may be used later to actually do the lock. + * A cleanup routine gets installed to cleanup left over locks + * or other files used together with the lockmechanism. + * Althoug the function is called dotlock, this does not necessarily + * mean that real lockfiles are used - the function may decide to + * use fcntl locking. Calling the function with NULL only install + * the atexit handler and maybe used to assure that the cleanup + * is called after all other atexit handlers. + * + * Notes: This function creates a lock file in the same directory + * as file_to_lock with the name "file_to_lock.lock" + * A temporary file ".#lk..pid[.threadid] is used. + * This function does nothing for Windoze. + */ +DOTLOCK +create_dotlock( const char *file_to_lock ) +{ + static int initialized; + DOTLOCK h; + int fd = -1; + char pidstr[16]; + #ifndef HAVE_DOSISH_SYSTEM + struct utsname utsbuf; + #endif + const char *nodename; + const char *dirpart; + int dirpartlen; + + if( !initialized ) { + atexit( remove_lockfiles ); + initialized = 1; + } + if( !file_to_lock ) + return NULL; + + h = jnlib_xcalloc( 1, sizeof *h ); +#ifndef HAVE_DOSISH_SYSTEM + sprintf( pidstr, "%10d\n", (int)getpid() ); + /* fixme: add the hostname to the second line (FQDN or IP addr?) */ + + /* create a temporary file */ + if( uname( &utsbuf ) ) + nodename = "unknown"; + else + nodename = utsbuf.nodename; + + if( !(dirpart = strrchr( file_to_lock, '/' )) ) { + dirpart = "."; + dirpartlen = 1; + } + else { + dirpartlen = dirpart - file_to_lock; + dirpart = file_to_lock; + } + + #ifdef _REENTRANT + /* fixme: aquire mutex on all_lockfiles */ + #endif + h->next = all_lockfiles; + all_lockfiles = h; + + h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); + sprintf( h->tname, "%.*s/.#lk%p.%s.%d", + dirpartlen, dirpart, h, nodename, (int)getpid() ); + + do { + errno = 0; + fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); + } while( fd == -1 && errno == EINTR ); + if( fd == -1 ) { + all_lockfiles = h->next; + log_error( "failed to create temporary file `%s': %s\n", + h->tname, strerror(errno)); + jnlib_free(h->tname); + jnlib_free(h); + return NULL; + } + if( write(fd, pidstr, 11 ) != 11 ) { + all_lockfiles = h->next; + #ifdef _REENTRANT + /* release mutex */ + #endif + log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); + close(fd); + unlink(h->tname); + jnlib_free(h->tname); + jnlib_free(h); + return NULL; + } + if( close(fd) ) { + all_lockfiles = h->next; + #ifdef _REENTRANT + /* release mutex */ + #endif + log_error( "error closing `%s': %s\n", h->tname, strerror(errno)); + unlink(h->tname); + jnlib_free(h->tname); + jnlib_free(h); + return NULL; + } + + #ifdef _REENTRANT + /* release mutex */ + #endif +#endif /* !HAVE_DOSISH_SYSTEM */ + h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 ); + strcpy(stpcpy(h->lockname, file_to_lock), ".lock"); + return h; +} + +static int +maybe_deadlock( DOTLOCK h ) +{ + DOTLOCK r; + + for( r=all_lockfiles; r; r = r->next ) { + if( r != h && r->locked ) + return 1; + } + return 0; +} + +/**************** + * Do a lock on H. A TIMEOUT of 0 returns immediately, + * -1 waits forever (hopefully not), other + * values are timeouts in milliseconds. + * Returns: 0 on success + */ +int +make_dotlock( DOTLOCK h, long timeout ) +{ +#ifdef HAVE_DOSISH_SYSTEM + return 0; +#else + int pid; + const char *maybe_dead=""; + int backoff=0; + + if( h->locked ) { + log_debug("oops, `%s' is already locked\n", h->lockname ); + return 0; + } + + for(;;) { + if( !link(h->tname, h->lockname) ) { + /* fixme: better use stat to check the link count */ + h->locked = 1; + return 0; /* okay */ + } + if( errno != EEXIST ) { + log_error( "lock not made: link() failed: %s\n", strerror(errno) ); + return -1; + } + if( (pid = read_lockfile(h->lockname)) == -1 ) { + if( errno != ENOENT ) { + log_info("cannot read lockfile\n"); + return -1; + } + log_info( "lockfile disappeared\n"); + continue; + } + else if( pid == getpid() ) { + log_info( "Oops: lock already hold by us\n"); + h->locked = 1; + return 0; /* okay */ + } + else if( kill(pid, 0) && errno == ESRCH ) { + maybe_dead = " - probably dead"; + #if 0 /* we should not do this without checking the permissions */ + /* and the hostname */ + log_info( "removing stale lockfile (created by %d)", pid ); + #endif + } + if( timeout == -1 ) { + struct timeval tv; + log_info( "waiting for lock (hold by %d%s) %s...\n", + pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); + + + /* can't use sleep, cause signals may be blocked */ + tv.tv_sec = 1 + backoff; + tv.tv_usec = 0; + select(0, NULL, NULL, NULL, &tv); + if( backoff < 10 ) + backoff++ ; + } + else + return -1; + } + /*not reached */ +#endif /* !HAVE_DOSISH_SYSTEM */ +} + + +/**************** + * release a lock + * Returns: 0 := success + */ +int +release_dotlock( DOTLOCK h ) +{ +#ifdef HAVE_DOSISH_SYSTEM + return 0; +#else + int pid; + + if( !h->locked ) { + log_debug("oops, `%s' is not locked\n", h->lockname ); + return 0; + } + + pid = read_lockfile( h->lockname ); + if( pid == -1 ) { + log_error( "release_dotlock: lockfile error\n"); + return -1; + } + if( pid != getpid() ) { + log_error( "release_dotlock: not our lock (pid=%d)\n", pid); + return -1; + } + if( unlink( h->lockname ) ) { + log_error( "release_dotlock: error removing lockfile `%s'", + h->lockname); + return -1; + } + /* fixme: check that the link count is now 1 */ + h->locked = 0; + return 0; +#endif /* !HAVE_DOSISH_SYSTEM */ +} + + +/**************** + * Read the lock file and return the pid, returns -1 on error. + */ +static int +read_lockfile( const char *name ) +{ + #ifdef HAVE_DOSISH_SYSTEM + return 0; + #else + int fd, pid; + char pidstr[16]; + + if( (fd = open(name, O_RDONLY)) == -1 ) { + int e = errno; + log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) ); + errno = e; + return -1; + } + if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */ + log_debug("error reading lockfile `%s'", name ); + close(fd); + errno = 0; + return -1; + } + pidstr[10] = 0; /* terminate pid string */ + close(fd); + pid = atoi(pidstr); + if( !pid || pid == -1 ) { + log_error("invalid pid %d in lockfile `%s'", pid, name ); + errno = 0; + return -1; + } + return pid; + #endif +} + + +static void +remove_lockfiles() +{ + #ifndef HAVE_DOSISH_SYSTEM + DOTLOCK h, h2; + + h = all_lockfiles; + all_lockfiles = NULL; + + while( h ) { + h2 = h->next; + if( h->locked ) + unlink( h->lockname ); + unlink(h->tname); + jnlib_free(h->tname); + jnlib_free(h->lockname); + jnlib_free(h); + h = h2; + } + #endif +} + diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h new file mode 100644 index 000000000..7d45c8286 --- /dev/null +++ b/jnlib/dotlock.h @@ -0,0 +1,32 @@ +/* dotlock.h + * Copyright (C) 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 LIBJNLIB_DOTLOCK_H +#define LIBJNLIB_DOTLOCK_H + +struct dotlock_handle; +typedef struct dotlock_handle *DOTLOCK; + +DOTLOCK create_dotlock( const char *file_to_lock ); +int make_dotlock( DOTLOCK h, long timeout ); +int release_dotlock( DOTLOCK h ); + + +#endif /*LIBJNLIB_DOTLOCK_H*/ diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h new file mode 100644 index 000000000..ad7e353fd --- /dev/null +++ b/jnlib/libjnlib-config.h @@ -0,0 +1,72 @@ +/* libjnlib-config.h - local configuration of the jnlib functions + * Copyright (C) 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 + */ + +/**************** + * This header is to be included only by the files in this directory + * it should not be used by other modules. + */ + +#ifndef LIBJNLIB_CONFIG_H +#define LIBJNLIB_CONFIG_H + +#include /* gcry_malloc & Cie. */ +#include "logging.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 +#endif + +#ifdef ENABLE_NLS + #include + #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 */ + + +#define jnlib_xmalloc(a) gcry_xmalloc( (a) ) +#define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) ) +#define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) ) +#define jnlib_xstrdup(a) gcry_xstrdup( (a) ) +#define jnlib_free(a) gcry_free( (a) ) + +#define jnlib_log_debug log_debug +#define jnlib_log_info log_info +#define jnlib_log_error log_error +#define jnlib_log_fatal log_fatal +#define jnlib_log_bug log_bug + + +#endif /*LIBJNUTIL_CONFIG_H*/ diff --git a/jnlib/logging.c b/jnlib/logging.c new file mode 100644 index 000000000..647e757c6 --- /dev/null +++ b/jnlib/logging.c @@ -0,0 +1,347 @@ +/* logging.c - useful logging 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 + */ + + +/* This file should replace logger.c in the future - for now it is not + * used by GnuPG but by GPA. + * It is a quite simple implemenation but sufficient for most purposes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __MINGW32__ + #include +#endif + +#define JNLIB_NEED_LOG_LOGV 1 +#include "libjnlib-config.h" +#include "logging.h" + + +static FILE *logstream; +static char prefix_buffer[80]; +static int with_time; +static int with_prefix; +static int with_pid; + +static int missing_lf; +static int errorcount; + +#if 0 +static void +write2stderr( const char *s ) +{ + write( 2, s, strlen(s) ); +} + + +static void +do_die(int rc, const char *text ) +{ + write2stderr("\nFatal error: "); + write2stderr(text); + write2stderr("\n"); + abort(); +} +#endif + +int +log_get_errorcount (int clear) +{ + int n = errorcount; + if( clear ) + errorcount = 0; + return n; +} + +void +log_set_file( const char *name ) +{ + FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr; + if( !fp ) { + fprintf(stderr, "failed to open log file `%s': %s\n", + name, strerror(errno)); + return; + } + setvbuf( fp, NULL, _IOLBF, 0 ); + + if (logstream && logstream != stderr && logstream != stdout) + fclose( logstream ); + logstream = fp; + missing_lf = 0; +} + +void +log_set_fd (int fd) +{ + FILE *fp; + + if (fd == 1) + fp = stdout; + else if (fd == 2) + fp = stderr; + else + fp = fdopen (fd, "a"); + if (!fp) + { + fprintf (stderr, "failed to fdopen log fd %d: %s\n", + fd, strerror(errno)); + return; + } + setvbuf (fp, NULL, _IOLBF, 0); + + if (logstream && logstream != stderr && logstream != stdout) + fclose( logstream); + logstream = fp; + missing_lf = 0; +} + + +void +log_set_prefix (const char *text, unsigned int flags) +{ + if (text) + { + strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1); + prefix_buffer[sizeof (prefix_buffer)-1] = 0; + } + + with_prefix = (flags & 1); + with_time = (flags & 2); + with_pid = (flags & 4); +} + + +const char * +log_get_prefix (unsigned int *flags) +{ + if (flags) + { + *flags = 0; + if (with_prefix) + *flags |= 1; + if (with_time) + *flags |= 2; + if (with_pid) + *flags |=4; + } + return prefix_buffer; +} + +int +log_get_fd() +{ + return fileno(logstream?logstream:stderr); +} + +FILE * +log_get_stream () +{ + return logstream?logstream:stderr; +} + + +static void +do_logv( int level, const char *fmt, va_list arg_ptr ) +{ + if (!logstream) + logstream = stderr; + + if (missing_lf && level != JNLIB_LOG_CONT) + putc('\n', logstream ); + missing_lf = 0; + + if (level != JNLIB_LOG_CONT) + { /* Note this does not work for multiple line logging as we would + * need to print to a buffer first */ + if (with_time) + { + struct tm *tp; + time_t atime = time (NULL); + + tp = localtime (&atime); + fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec ); + } + if (with_prefix) + fputs (prefix_buffer, logstream); + if (with_pid) + fprintf (logstream, "[%u]", (unsigned int)getpid ()); + if (!with_time) + putc (':', logstream); + putc (' ', logstream); + } + + switch (level) + { + case JNLIB_LOG_BEGIN: break; + case JNLIB_LOG_CONT: break; + case JNLIB_LOG_INFO: break; + case JNLIB_LOG_WARN: break; + case JNLIB_LOG_ERROR: break; + case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break; + case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break; + case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break; + default: fprintf(logstream,"[Unknown log level %d]: ", level ); break; + } + + if (fmt) + { + vfprintf(logstream,fmt,arg_ptr) ; + if (*fmt && fmt[strlen(fmt)-1] != '\n') + missing_lf = 1; + } + + if (level == JNLIB_LOG_FATAL) + exit(2); + if (level == JNLIB_LOG_BUG) + abort(); +} + +static void +do_log( int level, const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + do_logv( level, fmt, arg_ptr ); + va_end(arg_ptr); +} + + +void +log_logv (int level, const char *fmt, va_list arg_ptr) +{ + do_logv (level, fmt, arg_ptr); +} + +void +log_info( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + do_logv( JNLIB_LOG_INFO, fmt, arg_ptr ); + va_end(arg_ptr); +} + +void +log_error( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + do_logv( JNLIB_LOG_ERROR, fmt, arg_ptr ); + va_end(arg_ptr); + /* protect against counter overflow */ + if( errorcount < 30000 ) + errorcount++; +} + + +void +log_fatal( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr ); + va_end(arg_ptr); + abort(); /* never called, bugs it makes the compiler happy */ +} + +void +log_bug( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + do_logv( JNLIB_LOG_BUG, fmt, arg_ptr ); + va_end(arg_ptr); + abort(); /* never called, but it makes the compiler happy */ +} + +void +log_debug( const char *fmt, ... ) +{ + va_list arg_ptr ; + + va_start( arg_ptr, fmt ) ; + do_logv( JNLIB_LOG_DEBUG, fmt, arg_ptr ); + va_end(arg_ptr); +} + + +void +log_printf (const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, fmt, arg_ptr); + va_end (arg_ptr); +} + +/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw + dump, with TEXT just an empty string, print a trailing linefeed, + otherwise print an entire debug line. */ +void +log_printhex (const char *text, const void *buffer, size_t length) +{ + if (text && *text) + log_debug ("%s ", text); + if (length) + { + const unsigned char *p = buffer; + log_printf ("%02X", *p); + for (length--, p++; length--; p++) + log_printf (" %02X", *p); + } + if (text) + log_printf ("\n"); +} + + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +void +bug_at( const char *file, int line, const char *func ) +{ + do_log( JNLIB_LOG_BUG, + ("... this is a bug (%s:%d:%s)\n"), file, line, func ); + abort(); /* never called, but it makes the compiler happy */ +} +#else +void +bug_at( const char *file, int line ) +{ + do_log( JNLIB_LOG_BUG, + _("you found a bug ... (%s:%d)\n"), file, line); + abort(); /* never called, but it makes the compiler happy */ +} +#endif + diff --git a/jnlib/logging.h b/jnlib/logging.h new file mode 100644 index 000000000..224db36e5 --- /dev/null +++ b/jnlib/logging.h @@ -0,0 +1,76 @@ +/* logging.h + * Copyright (C) 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 LIBJNLIB_LOGGING_H +#define LIBJNLIB_LOGGING_H + +#include +#include "mischelp.h" + + +int log_get_errorcount (int clear); +void log_set_file( const char *name ); +void log_set_fd (int fd); +void log_set_prefix (const char *text, unsigned int flags); +const char *log_get_prefix (unsigned int *flags); +int log_get_fd(void); +FILE *log_get_stream (void); + +#ifdef JNLIB_GCC_M_FUNCTION + void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR; +# define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ ) +#else + void bug_at( const char *file, int line ); +# define BUG() bug_at( __FILE__ , __LINE__ ) +#endif + +/* To avoid mandatory inclusion of stdarg and other stuff, do it only + if explicitly requested to do so. */ +#ifdef JNLIB_NEED_LOG_LOGV +#include +enum jnlib_log_levels { + JNLIB_LOG_BEGIN, + JNLIB_LOG_CONT, + JNLIB_LOG_INFO, + JNLIB_LOG_WARN, + JNLIB_LOG_ERROR, + JNLIB_LOG_FATAL, + JNLIB_LOG_BUG, + JNLIB_LOG_DEBUG +}; +void log_logv (int level, const char *fmt, va_list arg_ptr); +#endif /*JNLIB_NEED_LOG_LOGV*/ + + +void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); +void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); +void log_printhex (const char *text, const void *buffer, size_t length); + + +#endif /*LIBJNLIB_LOGGING_H*/ + + + + + diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h new file mode 100644 index 000000000..58c9250e2 --- /dev/null +++ b/jnlib/mischelp.h @@ -0,0 +1,43 @@ +/* mischelp.h + * Copyright (C) 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 LIBJNLIB_MISCHELP_H +#define LIBJNLIB_MISCHHELP_H + + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +# define JNLIB_GCC_M_FUNCTION 1 +# define JNLIB_GCC_A_NR __attribute__ ((noreturn)) +# define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) +# define JNLIB_GCC_A_NR_PRINTF( f, a ) \ + __attribute__ ((noreturn, format (printf,f,a))) +#else +# define JNLIB_GCC_A_NR +# define JNLIB_GCC_A_PRINTF( f, a ) +# define JNLIB_GCC_A_NR_PRINTF( f, a ) +#endif + + + +#endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c new file mode 100644 index 000000000..3c9baaef5 --- /dev/null +++ b/jnlib/stringhelp.c @@ -0,0 +1,474 @@ +/* stringhelp.c - standard string helper 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 +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "stringhelp.h" + + +/**************** + * look for the substring SUB in buffer and return a pointer to that + * substring in BUF or NULL if not found. + * Comparison is case-insensitive. + */ +const char * +memistr( const char *buf, size_t buflen, const char *sub ) +{ + const byte *t, *s ; + size_t n; + + for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) + if( toupper(*t) == toupper(*s) ) { + for( buf=t++, buflen = n--, s++; + n && toupper(*t) == toupper(*s); t++, s++, n-- ) + ; + if( !*s ) + return buf; + t = buf; n = buflen; s = sub ; + } + + return NULL ; +} + +/**************** + * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein + * '\0' angehngt. Ist n = 0, so geschieht nichts, ist Destination + * gleich NULL, so wird via jnlib_xmalloc Speicher besorgt, ist dann nicht + * gengend Speicher vorhanden, so bricht die funktion ab. + */ +char * +mem2str( char *dest , const void *src , size_t n ) +{ + char *d; + const char *s; + + if( n ) { + if( !dest ) + dest = jnlib_xmalloc( n ) ; + d = dest; + s = src ; + for(n--; n && *s; n-- ) + *d++ = *s++; + *d = '\0' ; + } + + return dest ; +} + + +/**************** + * remove leading and trailing white spaces + */ +char * +trim_spaces( char *str ) +{ + char *string, *p, *mark; + + string = str; + /* find first non space character */ + for( p=string; *p && isspace( *(byte*)p ) ; p++ ) + ; + /* move characters */ + for( (mark = NULL); (*string = *p); string++, p++ ) + if( isspace( *(byte*)p ) ) { + if( !mark ) + mark = string ; + } + else + mark = NULL ; + if( mark ) + *mark = '\0' ; /* remove trailing spaces */ + + return str ; +} + +/**************** + * remove trailing white spaces + */ +char * +trim_trailing_spaces( char *string ) +{ + char *p, *mark; + + for( mark = NULL, p = string; *p; p++ ) { + if( isspace( *(byte*)p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + if( mark ) + *mark = '\0' ; + + return string ; +} + + + +unsigned +trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) +{ + byte *p, *mark; + unsigned n; + + for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { + if( strchr(trimchars, *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if( mark ) { + *mark = 0; + return mark - line; + } + return len; +} + +/**************** + * remove trailing white spaces and return the length of the buffer + */ +unsigned +trim_trailing_ws( byte *line, unsigned len ) +{ + return trim_trailing_chars( line, len, " \t\r\n" ); +} + + +/*************** + * Extract from a given path the filename component. + * + */ +char * +make_basename(const char *filepath) +{ + char *p; + + if ( !(p=strrchr(filepath, '/')) ) + #ifdef HAVE_DRIVE_LETTERS + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) + #endif + { + return jnlib_xstrdup(filepath); + } + + return jnlib_xstrdup(p+1); +} + + + +/*************** + * Extract from a given filename the path prepended to it. + * If their isn't a path prepended to the filename, a dot + * is returned ('.'). + * + */ +char * +make_dirname(const char *filepath) +{ + char *dirname; + int dirname_length; + char *p; + + if ( !(p=strrchr(filepath, '/')) ) + #ifdef HAVE_DRIVE_LETTERS + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) + #endif + { + return jnlib_xstrdup("."); + } + + dirname_length = p-filepath; + dirname = jnlib_xmalloc(dirname_length+1); + strncpy(dirname, filepath, dirname_length); + dirname[dirname_length] = 0; + + return dirname; +} + + + +/**************** + * Construct a filename from the NULL terminated list of parts. + * Tilde expansion is done here. + */ +char * +make_filename( const char *first_part, ... ) +{ + va_list arg_ptr ; + size_t n; + const char *s; + char *name, *home, *p; + + va_start( arg_ptr, first_part ) ; + n = strlen(first_part)+1; + while( (s=va_arg(arg_ptr, const char *)) ) + n += strlen(s) + 1; + va_end(arg_ptr); + + home = NULL; + if( *first_part == '~' && first_part[1] == '/' + && (home = getenv("HOME")) && *home ) + n += strlen(home); + + name = jnlib_xmalloc(n); + p = home ? stpcpy(stpcpy(name,home), first_part+1) + : stpcpy(name, first_part); + va_start( arg_ptr, first_part ) ; + while( (s=va_arg(arg_ptr, const char *)) ) + p = stpcpy(stpcpy(p,"/"), s); + va_end(arg_ptr); + + return name; +} + + +int +compare_filenames( const char *a, const char *b ) +{ + /* ? check whether this is an absolute filename and + * resolve symlinks? + */ + #ifdef HAVE_DRIVE_LETTERS + return stricmp(a,b); + #else + return strcmp(a,b); + #endif +} + +/* Print a BUFFER to stream FP while replacing all control characters + and the character DELIM with standard C eescape sequences. Returns + the number of characters printed. */ +size_t +print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, int delim) +{ + const unsigned char *p = buffer; + size_t count = 0; + + for (; length; length--, p++, count++) + { + if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim) + { + putc ('\\', fp); + count++; + if (*p == '\n') + putc ('n', fp); + else if (*p == '\r') + putc ('r', fp); + else if (*p == '\f') + putc ('f', fp); + else if (*p == '\v') + putc ('v', fp); + else if (*p == '\b') + putc ('b', fp); + else if (!*p) + putc('0', fp); + else + { + fprintf (fp, "x%02x", *p); + count += 2; + } + } + else + putc (*p, fp); + } + + return count; +} + +size_t +print_sanitized_utf8_buffer (FILE *fp, const void *buffer, + size_t length, int delim) +{ + /* FIXME: convert to local characterset */ + return print_sanitized_buffer (fp, buffer, length, delim); +} + + +size_t +print_sanitized_string (FILE *fp, const char *string, int delim) +{ + return string? print_sanitized_buffer (fp, string, strlen (string), delim):0; +} + +size_t +print_sanitized_utf8_string (FILE *fp, const char *string, int delim) +{ + /* FIXME: convert to local characterset */ + return print_sanitized_string (fp, string, delim); +} + +/**************************************************** + ******** locale insensitive ctype functions ******** + ****************************************************/ +/* FIXME: replace them by a table lookup and macros */ +int +ascii_isupper (int c) +{ + return c >= 'A' && c <= 'Z'; +} + +int +ascii_islower (int c) +{ + return c >= 'a' && c <= 'z'; +} + +int +ascii_toupper (int c) +{ + if (c >= 'a' && c <= 'z') + c &= ~0x20; + return c; +} + +int +ascii_tolower (int c) +{ + if (c >= 'A' && c <= 'Z') + c |= 0x20; + return c; +} + + +int +ascii_strcasecmp( const char *a, const char *b ) +{ + if (a == b) + return 0; + + for (; *a && *b; a++, b++) { + if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b)) + break; + } + return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); +} + +int +ascii_memcasecmp( const char *a, const char *b, size_t n ) +{ + if (a == b) + return 0; + for ( ; n; n--, a++, b++ ) { + if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) ) + return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); + } + return 0; +} + +int +ascii_strcmp( const char *a, const char *b ) +{ + if (a == b) + return 0; + + for (; *a && *b; a++, b++) { + if (*a != *b ) + break; + } + return *a == *b? 0 : (*(signed char *)a - *(signed char *)b); +} + + +void * +ascii_memcasemem (const void *haystack, size_t nhaystack, + const void *needle, size_t nneedle) +{ + + if (!nneedle) + return (void*)haystack; /* finding an empty needle is really easy */ + if (nneedle <= nhaystack) + { + const unsigned char *a = haystack; + const unsigned char *b = a + nhaystack - nneedle; + + for (; a <= b; a++) + { + if ( !ascii_memcasecmp (a, needle, nneedle) ) + return (void *)a; + } + } + return NULL; +} + +/********************************************* + ********** missing string functions ********* + *********************************************/ + +#ifndef HAVE_STPCPY +char * +stpcpy(char *a,const char *b) +{ + while( *b ) + *a++ = *b++; + *a = 0; + + return (char*)a; +} +#endif + +#ifndef HAVE_STRLWR +char * +strlwr(char *s) +{ + char *p; + for(p=s; *p; p++ ) + *p = tolower(*p); + return s; +} +#endif + + +#ifndef HAVE_STRCASECMP +int +strcasecmp( const char *a, const char *b ) +{ + for( ; *a && *b; a++, b++ ) { + if( *a != *b && toupper(*a) != toupper(*b) ) + break; + } + return *(const byte*)a - *(const byte*)b; +} +#endif + + +/**************** + * mingw32/cpd has a memicmp() + */ +#ifndef HAVE_MEMICMP +int +memicmp( const char *a, const char *b, size_t n ) +{ + for( ; n; n--, a++, b++ ) + if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) ) + return *(const byte *)a - *(const byte*)b; + return 0; +} +#endif diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h new file mode 100644 index 000000000..027d30c72 --- /dev/null +++ b/jnlib/stringhelp.h @@ -0,0 +1,84 @@ +/* stringhelp.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 LIBJNLIB_STRINGHELP_H +#define LIBJNLIB_STRINGHELP_H + +#include "types.h" + +const char *memistr( const char *buf, size_t buflen, const char *sub ); +char *mem2str( char *, const void *, size_t); +char *trim_spaces( char *string ); +char *trim_trailing_spaces( char *string ); +unsigned int trim_trailing_chars( unsigned char *line, unsigned len, + const char *trimchars); +unsigned int trim_trailing_ws( unsigned char *line, unsigned len ); + + +char *make_basename(const char *filepath); +char *make_dirname(const char *filepath); +char *make_filename( const char *first_part, ... ); +int compare_filenames( const char *a, const char *b ); + +size_t print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, + int delim); +size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, + size_t length, int delim); +size_t print_sanitized_string (FILE *fp, const char *string, int delim); +size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); + + +const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); +int ascii_isupper (int c); +int ascii_islower (int c); +int ascii_toupper (int c); +int ascii_tolower (int c); +int ascii_strcasecmp( const char *a, const char *b ); +int ascii_memcasecmp( const char *a, const char *b, size_t n ); +void *ascii_memcasemem (const void *haystack, size_t nhaystack, + const void *needle, size_t nneedle); + + +#ifndef HAVE_MEMICMP +int memicmp( const char *a, const char *b, size_t n ); +#endif +#ifndef HAVE_STPCPY +char *stpcpy(char *a,const char *b); +#endif +#ifndef HAVE_STRLWR +char *strlwr(char *a); +#endif +#ifndef HAVE_STRTOUL + #define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif +#ifndef HAVE_MEMMOVE + #define memmove(d, s, n) bcopy((s), (d), (n)) +#endif +#ifndef HAVE_STRICMP + #define stricmp(a,b) strcasecmp( (a), (b) ) +#endif + +#ifndef STR + #define STR(v) #v +#endif +#define STR2(v) STR(v) + + +#endif /*LIBJNLIB_STRINGHELP_H*/ diff --git a/jnlib/strlist.c b/jnlib/strlist.c new file mode 100644 index 000000000..7cbaf5e02 --- /dev/null +++ b/jnlib/strlist.c @@ -0,0 +1,133 @@ +/* strlist.c - string helpers + * Copyright (C) 1998, 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 +#include +#include +#include +#include + +#include "libjnlib-config.h" +#include "strlist.h" + + +void +free_strlist( STRLIST sl ) +{ + STRLIST sl2; + + for(; sl; sl = sl2 ) { + sl2 = sl->next; + jnlib_free(sl); + } +} + + +STRLIST +add_to_strlist( STRLIST *list, const char *string ) +{ + STRLIST sl; + + sl = jnlib_xmalloc( sizeof *sl + strlen(string)); + sl->flags = 0; + strcpy(sl->d, string); + sl->next = *list; + *list = sl; + return sl; +} + +#if 0 +/**************** + * same as add_to_strlist() but if is_utf8 is *not* set a conversion + * to UTF8 is done + */ +STRLIST +add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +{ + STRLIST sl; + + if( is_utf8 ) + sl = add_to_strlist( list, string ); + else { + char *p = native_to_utf8( string ); + sl = add_to_strlist( list, p ); + m_free( p ); + } + return sl; +} +#endif + +STRLIST +append_to_strlist( STRLIST *list, const char *string ) +{ + STRLIST r, sl; + + sl = jnlib_xmalloc( sizeof *sl + strlen(string)); + sl->flags = 0; + strcpy(sl->d, string); + sl->next = NULL; + if( !*list ) + *list = sl; + else { + for( r = *list; r->next; r = r->next ) + ; + r->next = sl; + } + return sl; +} + +#if 0 +STRLIST +append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +{ + STRLIST sl; + + if( is_utf8 ) + sl = append_to_strlist( list, string ); + else { + char *p = native_to_utf8( string ); + sl = append_to_strlist( list, p ); + m_free( p ); + } + return sl; +} +#endif + +STRLIST +strlist_prev( STRLIST head, STRLIST node ) +{ + STRLIST n; + + for(n=NULL; head && head != node; head = head->next ) + n = head; + return n; +} + +STRLIST +strlist_last( STRLIST node ) +{ + if( node ) + for( ; node->next ; node = node->next ) + ; + return node; +} + + + diff --git a/jnlib/strlist.h b/jnlib/strlist.h new file mode 100644 index 000000000..53c0bc750 --- /dev/null +++ b/jnlib/strlist.h @@ -0,0 +1,43 @@ +/* strlist.h + * Copyright (C) 1998, 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 LIBJNLIB_STRLIST_H +#define LIBJNLIB_STRLIST_H + +struct string_list { + struct string_list *next; + unsigned int flags; + char d[1]; +}; +typedef struct string_list *STRLIST; + + +void free_strlist( STRLIST sl ); +STRLIST add_to_strlist( STRLIST *list, const char *string ); +STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST append_to_strlist( STRLIST *list, const char *string ); +STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST strlist_prev( STRLIST head, STRLIST node ); +STRLIST strlist_last( STRLIST node ); + +#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) + + +#endif /*LIBJNLIB_STRLIST_H*/ diff --git a/jnlib/types.h b/jnlib/types.h new file mode 100644 index 000000000..230d1502f --- /dev/null +++ b/jnlib/types.h @@ -0,0 +1,101 @@ +/* types.h + * Copyright (C) 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 LIBJNLIB_TYPES_H +#define LIBJNLIB_TYPES_H + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT + #undef SIZEOF_UNSIGNED_SHORT + #define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT + #undef SIZEOF_UNSIGNED_INT + #define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG + #undef SIZEOF_UNSIGNED_LONG + #define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include + + +#ifndef HAVE_BYTE_TYPEDEF + #undef byte /* maybe there is a macro with this name */ + typedef unsigned char byte; + #define HAVE_BYTE_TYPEDEF +#endif + +#ifndef HAVE_USHORT_TYPEDEF + #undef ushort /* maybe there is a macro with this name */ + typedef unsigned short ushort; + #define HAVE_USHORT_TYPEDEF +#endif + +#ifndef HAVE_ULONG_TYPEDEF + #undef ulong /* maybe there is a macro with this name */ + typedef unsigned long ulong; + #define HAVE_ULONG_TYPEDEF +#endif + +#ifndef HAVE_U16_TYPEDEF + #undef u16 /* maybe there is a macro with this name */ + #if SIZEOF_UNSIGNED_INT == 2 + typedef unsigned int u16; + #elif SIZEOF_UNSIGNED_SHORT == 2 + typedef unsigned short u16; + #else + #error no typedef for u16 + #endif + #define HAVE_U16_TYPEDEF +#endif + +#ifndef HAVE_U32_TYPEDEF + #undef u32 /* maybe there is a macro with this name */ + #if SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int u32; + #elif SIZEOF_UNSIGNED_LONG == 4 + typedef unsigned long u32; + #else + #error no typedef for u32 + #endif + #define HAVE_U32_TYPEDEF +#endif + +#ifndef HAVE_U64_TYPEDEF + #undef u64 /* maybe there is a macro with this name */ + #if SIZEOF_UNSIGNED_INT == 8 + typedef unsigned int u64; + #define HAVE_U64_TYPEDEF + #elif SIZEOF_UNSIGNED_LONG == 8 + typedef unsigned long u64; + #define HAVE_U64_TYPEDEF + #elif __GNUC__ >= 2 || defined(__SUNPRO_C) + typedef unsigned long long u64; + #define HAVE_U64_TYPEDEF + #endif +#endif + + + +#endif /*LIBJNLIB_TYPES_H*/ diff --git a/jnlib/xmalloc.c b/jnlib/xmalloc.c new file mode 100644 index 000000000..1cfaab9f7 --- /dev/null +++ b/jnlib/xmalloc.c @@ -0,0 +1,88 @@ +/* xmalloc.c - standard malloc wrappers + * Copyright (C) 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 +#include +#include +#include + +#include "libjnlib-config.h" +#include "xmalloc.h" + +static void +out_of_core(void) +{ + fputs("\nfatal: out of memory\n", stderr ); + exit(2); +} + + +void * +xmalloc( size_t n ) +{ + void *p = malloc( n ); + if( !p ) + out_of_core(); + return p; +} + +void * +xrealloc( void *a, size_t n ) +{ + void *p = realloc( a, n ); + if( !p ) + out_of_core(); + return p; +} + +void * +xcalloc( size_t n, size_t m ) +{ + void *p = calloc( n, m ); + if( !p ) + out_of_core(); + return p; +} + +char * +xstrdup( const char *string ) +{ + void *p = xmalloc( strlen(string)+1 ); + strcpy( p, string ); + return p; +} + + +char * +xstrcat2( const char *a, const char *b ) +{ + size_t n1; + char *p; + + if( !b ) + return xstrdup( a ); + + n1 = strlen(a); + p = xmalloc( n1 + strlen(b) + 1 ); + memcpy(p, a, n1 ); + strcpy(p+n1, b ); + return p; +} + diff --git a/jnlib/xmalloc.h b/jnlib/xmalloc.h new file mode 100644 index 000000000..150ef3664 --- /dev/null +++ b/jnlib/xmalloc.h @@ -0,0 +1,31 @@ +/* xmalloc.h + * Copyright (C) 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 LIBJNLIB_XMALLOC_H +#define LIBJNLIB_XMALLOC_H + +void *xmalloc( size_t n ); +void *xrealloc( void *a, size_t n ); +void *xcalloc( size_t n, size_t m ); +char *xstrdup( const char *string ); +char *xstrcat2( const char *a, const char *b ); + + +#endif /*LIBJNLIB_XMALLOC_H*/ -- cgit v1.2.3 From 3051135e16effcd5530acdcc2424775df4d88cea Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 9 Jan 2003 13:15:07 +0000 Subject: Updated from latest NewPG project --- ChangeLog | 15 +++++++++++++++ NEWS | 18 +++++++++++++++--- README | 4 ++-- TODO | 3 --- configure.ac | 29 ++++++++++++++++++++++++----- 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 832ba26ad..3458b7f65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2003-01-09 Werner Koch + + * 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 + + * 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 * configure.ac: Bumped version number to 1.9.0-cvs. diff --git a/NEWS b/NEWS index efacfbdd7..5c8a8342a 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,23 @@ Noteworthy changes in version 1.9.0 (unreleased) ------------------------------------------------ - * Merged stuff from the newpg branch and started this new - development branch. + * New gpgsm commands --call-dirmngr and --call-protect-tool. + * Changing a passphrase is now possible using "gpgsm --passwd" - Copyright 2002 Free Software Foundation, Inc. + * 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 diff --git a/README b/README index 7796a9436..cbc2e8a10 100644 --- a/README +++ b/README @@ -354,7 +354,7 @@ There is some limited support to import a private key from a PKCS-12 file. Note, that this does only import the private key and not any certificates available in that file. - gpg-protect-tool --p12-import --store foo.p12 + gpgsm --call-protect-tool --p12-import --store foo.p12 This require that the gpg-agent is running, alternative you may give the passphrase on the commandline using the option "-P " - @@ -367,6 +367,6 @@ 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. - gpg-protect-tool --p12-export foo.key >foo.p12 + gpgsm --call-protect-tool --p12-export foo.key >foo.p12 diff --git a/TODO b/TODO index 379a1780a..213cbb6d8 100644 --- a/TODO +++ b/TODO @@ -40,7 +40,6 @@ might want to have an agent context for each service request * agent/command.c ** Make sure that secure memory is used where appropriate -** Implement option passing per connection (DISPLAY and TTY) * agent/pkdecrypt.c, agent/pksign.c ** Don't use stdio to return results. @@ -57,5 +56,3 @@ might want to have an agent context for each service request ** Return an error code or a status info per user ID. - - diff --git a/configure.ac b/configure.ac index ac31adf05..07b38f973 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# configure.ac - for GnuPG +# configure.ac - for NewPG # Copyright (C) 2001, 2002 Free Software Foundation, Inc, # # This file is part of GnuPG. @@ -21,9 +21,9 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(newpg, 1.9.0-cvs, gpa-dev@gnupg.org) +AC_INIT(newpg, 1.9.0-cvs, gnupg-devel@gnupg.org) NEED_LIBGCRYPT_VERSION=1.1.8 -NEED_KSBA_VERSION=0.4.4 +NEED_KSBA_VERSION=0.4.6 NEED_OPENSC_VERSION=0.7.0 ALL_LINGUAS="de" @@ -138,6 +138,11 @@ eval my_default_bindir=${exec_prefix} test "x${my_default_bindir}" = xNONE && my_default_bindir=${ac_default_prefix} my_default_bindir=${my_default_bindir}/bin +# Same goes for the pkglibdir which is used to call the gpg-protect-tool. +eval my_default_pkglibdir=${exec_prefix} +test "x${my_default_pkglibdir}" = xNONE && my_default_pkglibdir=${ac_default_prefix} +my_default_pkglibdir=${my_default_pkglibdir}/lib/${PACKAGE_NAME} + AC_ARG_WITH(agent-pgm, [ --with-agent-pgm=PATH Use PATH as the default for the gpg-agent)], gnupg_agent_pgm="$withval", @@ -169,6 +174,15 @@ fi AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_DIRMNGR, "$gnupg_dirmngr_pgm", [Default location of the dirmngr program]) +AC_ARG_WITH(protect-tool, + [ --with-protect-tool=PATH Use PATH as the protect-tool)], + gnupg_protect_tool="$withval", gnupg_protect_tool="" ) +if test -z "$gnupg_protect_tool"; then + gnupg_protect_tool=${my_default_pkglibdir}/gpg-protect-tool +fi +AC_DEFINE_UNQUOTED(GNUPG_PROTECT_TOOL, "$gnupg_protect_tool", + [Name of the protect tool program]) + # # Checks for libraries. @@ -245,7 +259,8 @@ else GNUPG_PTH_VERSION_CHECK(1.3.7) if test $have_pth = yes; then PTH_CFLAGS=`$PTH_CONFIG --cflags` - PTH_LIBS=`$PTH_CONFIG --libs` + PTH_LIBS=`$PTH_CONFIG --ldflags` + PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs`" AC_DEFINE(USE_GNU_PTH, 1, [Defined if the GNU Portable Thread Library should be used]) fi @@ -279,14 +294,17 @@ GNUPG_SYS_SO_PEERCRED # These are needed by libjnlib - fixme: we should have a macros for them AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) +AC_CHECK_FUNCS(flockfile funlockfile) AC_CHECK_FUNCS(sigaction sigprocmask) AC_REPLACE_FUNCS(vasprintf) AC_REPLACE_FUNCS(fopencookie) -# FIXME: Print a warning when that fopencookie is not available. +# FIXME: Print a warning when fopencookie is not available. AC_REPLACE_FUNCS(mkdtemp) AC_REPLACE_FUNCS(fseeko ftello) +AC_REPLACE_FUNCS(isascii) +AC_REPLACE_FUNCS(putc_unlocked) # We use jnlib, so tell other modules about it AC_DEFINE(HAVE_JNLIB_LOGGING, 1, @@ -350,6 +368,7 @@ echo " Agent: $build_agent $build_agent_threaded Smartcard: $build_scdaemon $build_scdaemon_threaded + Protect tool: $gnupg_protect_tool Default agent: $gnupg_agent_pgm Default pinentry: $gnupg_pinentry_pgm Default scdaemon: $gnupg_scdaemon_pgm -- cgit v1.2.3 From e9177199289d39863e29526cb4986ec4a7d9bba8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 9 Jan 2003 13:24:01 +0000 Subject: Taken from NewPG --- doc/assuan.texi | 189 ++++++++++++++ doc/contrib.texi | 63 +++++ doc/fdl.texi | 401 +++++++++++++++++++++++++++++ doc/gnupg.texi | 171 +++++++++++++ doc/gpg-agent.texi | 739 +++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/gpgsm.texi | 738 ++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/gpl.texi | 397 ++++++++++++++++++++++++++++ doc/scdaemon.texi | 297 +++++++++++++++++++++ 8 files changed, 2995 insertions(+) create mode 100644 doc/assuan.texi create mode 100644 doc/contrib.texi create mode 100644 doc/fdl.texi create mode 100644 doc/gnupg.texi create mode 100644 doc/gpg-agent.texi create mode 100644 doc/gpgsm.texi create mode 100644 doc/gpl.texi create mode 100644 doc/scdaemon.texi diff --git a/doc/assuan.texi b/doc/assuan.texi new file mode 100644 index 000000000..fbf513ad8 --- /dev/null +++ b/doc/assuan.texi @@ -0,0 +1,189 @@ +@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 modula 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 [] +Request was successful. + +@item ERR @var{errorcode} [] +Request could not be fulfilled. The error codes are mostly application +specific except for a few common ones. + +@item S @var{keyword} +Informational output by the server, still processing the request. + +@item # +Comment line issued only for debugging purposes. Totally ignored. + +@item D +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}> +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} +@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 +@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 diff --git a/doc/contrib.texi b/doc/contrib.texi new file mode 100644 index 000000000..0b250eecc --- /dev/null +++ b/doc/contrib.texi @@ -0,0 +1,63 @@ +@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 desgned the system and wrote most of the original code. + +@end itemize + +FIXME: We need to copy a lot of credits from GnupG 1.0 to here. + + +We'd also like to thank the folks who have contributed time and energy in +testing GnuPG: + +@itemize @bullet +@item +Joe R. Hacker + +@item +And many others +@end itemize + +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. diff --git a/doc/fdl.texi b/doc/fdl.texi new file mode 100644 index 000000000..6e40e6df9 --- /dev/null +++ b/doc/fdl.texi @@ -0,0 +1,401 @@ +@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: diff --git a/doc/gnupg.texi b/doc/gnupg.texi new file mode 100644 index 000000000..de243a8f7 --- /dev/null +++ b/doc/gnupg.texi @@ -0,0 +1,171 @@ +\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 administartion 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 + +* 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 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 + + diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi new file mode 100644 index 000000000..61484485f --- /dev/null +++ b/doc/gpg-agent.texi @@ -0,0 +1,739 @@ +@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. + +@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 @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 --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{path} +@opindex pinentry-program +Use program @var{path} as the PIN entry. The default is installation +dependend and can be shown with the @code{--version} command. + +@item --scdaemon-program @var{path} +@opindex scdaemon-program +Use program @var{path} 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 SIGUSR1 +@cpindex SIGUSR1 +This signal increases the verbosity of the logging by one up to a value +of 5. + +@item SIGUSR2 +@cpindex SIGUSR2 +This signal decreases the verbosity of the logging by one. + +@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. + +@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 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 +@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 + ( + ( ) + ... + ( ))) +@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 +@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 +@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 +@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 + ( + ( ) + ... + ( ))) +@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 + S: OK key available + C: SIGKEY + 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 ) + (e ))) +@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 +@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 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}. + + + diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi new file mode 100644 index 000000000..4d91bda5b --- /dev/null +++ b/doc/gpgsm.texi @@ -0,0 +1,738 @@ +@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 filenames given as arguments should have an +absulte path 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 +@opindex list-keys +List all available certificates stored in the local key database. + +@item --list-secret-keys +@opindex list-secret-keys +List all available keys whenre a secret key is available. + +@item --list-external-keys @var{pattern} +@opindex list-keys +List certificates matching @var{pattern} using an external server. This +utilies the @code{dirmngr} service. + +@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 --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. + +@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. + +@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 filename of the +secret key. + +@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 @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-no-path-validation +@opindex debug-no-path-validation +This is actually not a debugging option but only useful as such. It +lets gpgsm bypass all certificate path validation checks. + +@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 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. + +@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. + diff --git a/doc/gpl.texi b/doc/gpl.texi new file mode 100644 index 000000000..ca0508fad --- /dev/null +++ b/doc/gpl.texi @@ -0,0 +1,397 @@ +@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. diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi new file mode 100644 index 000000000..55f9f8a0f --- /dev/null +++ b/doc/scdaemon.texi @@ -0,0 +1,297 @@ +@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. + +@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. + +@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 @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. + + +@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. +@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. + -- cgit v1.2.3 From 7b6f1902d02b0cec4a12d7b44b8d4583baa5bc0b Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Thu, 9 Jan 2003 13:29:36 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- agent/cache.c | 314 +++ common/isascii.c | 29 + common/putc_unlocked.c | 31 + common/signal.c | 226 +++ doc/ChangeLog | 593 ++++++ g10/delkey.c | 209 ++ g10/pubkey-enc.c | 307 +++ g10/status.h | 127 ++ include/_regex.h | 574 ++++++ include/distfiles | 15 + include/ttyio.h | 40 + include/zlib-riscos.h | 134 ++ po/de.po | 5254 ++++++++++++++++++++++++++++++++++++++++++++++++ scripts/config.guess | 1366 +++++++++++++ scripts/config.sub | 1471 ++++++++++++++ tests/ChangeLog | 68 + tests/Makefile.am | 78 + tests/asschk.c | 1059 ++++++++++ tests/inittests | 99 + 19 files changed, 11994 insertions(+) create mode 100644 agent/cache.c create mode 100644 common/isascii.c create mode 100644 common/putc_unlocked.c create mode 100644 common/signal.c create mode 100644 doc/ChangeLog create mode 100644 g10/delkey.c create mode 100644 g10/pubkey-enc.c create mode 100644 g10/status.h create mode 100644 include/_regex.h create mode 100644 include/distfiles create mode 100644 include/ttyio.h create mode 100644 include/zlib-riscos.h create mode 100644 po/de.po create mode 100755 scripts/config.guess create mode 100755 scripts/config.sub create mode 100644 tests/ChangeLog create mode 100644 tests/Makefile.am create mode 100644 tests/asschk.c create mode 100755 tests/inittests diff --git a/agent/cache.c b/agent/cache.c new file mode 100644 index 000000000..b6ab55085 --- /dev/null +++ b/agent/cache.c @@ -0,0 +1,314 @@ +/* cache.c - keep a cache of passphrases + * 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 + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <assert.h> + +#include "agent.h" + +struct secret_data_s { + int totallen; /* this includes the padding */ + int datalen; /* actual data length */ + char data[1]; +}; + +typedef struct cache_item_s *ITEM; +struct cache_item_s { + ITEM next; + time_t created; + time_t accessed; + int ttl; /* max. lifetime given in seonds */ + int lockcount; + struct secret_data_s *pw; + char key[1]; +}; + + +static ITEM thecache; + + +static void +release_data (struct secret_data_s *data) +{ + xfree (data); +} + +static struct secret_data_s * +new_data (const void *data, size_t length) +{ + struct secret_data_s *d; + int total; + + /* we pad the data to 32 bytes so that it get more complicated + finding something out by watching allocation patterns. This is + usally not possible but we better assume nothing about our + secure storage provider*/ + total = length + 32 - (length % 32); + + d = gcry_malloc_secure (sizeof *d + total - 1); + if (d) + { + d->totallen = total; + d->datalen = length; + memcpy (d->data, data, length); + } + return d; +} + + +/* check whether there are items to expire */ +static void +housekeeping (void) +{ + ITEM r, rprev; + time_t current = gnupg_get_time (); + + /* first expire the actual data */ + for (r=thecache; r; r = r->next) + { + if (!r->lockcount && r->pw && r->accessed + r->ttl < current) + { + if (DBG_CACHE) + log_debug (" expired `%s' (%ds after last access)\n", + r->key, r->ttl); + release_data (r->pw); + r->pw = NULL; + r->accessed = current; + } + } + + /* second, make sure that we also remove them based on the created stamp so + that the user has to enter it from time to time. We do this every hour */ + for (r=thecache; r; r = r->next) + { + if (!r->lockcount && r->pw && r->created + 60*60 < current) + { + if (DBG_CACHE) + log_debug (" expired `%s' (1h after creation)\n", r->key); + release_data (r->pw); + r->pw = NULL; + r->accessed = current; + } + } + + /* third, make sure that we don't have too many items in the list. + Expire old and unused entries after 30 minutes */ + for (rprev=NULL, r=thecache; r; ) + { + if (!r->pw && r->accessed + 60*30 < current) + { + if (r->lockcount) + { + log_error ("can't remove unused cache entry `%s' due to" + " lockcount=%d\n", + r->key, r->lockcount); + r->accessed += 60*10; /* next error message in 10 minutes */ + rprev = r; + r = r->next; + } + else + { + ITEM r2 = r->next; + if (DBG_CACHE) + log_debug (" removed `%s' (slot not used for 30m)\n", r->key); + xfree (r); + if (!rprev) + thecache = r2; + else + rprev->next = r2; + r = r2; + } + } + else + { + rprev = r; + r = r->next; + } + } +} + + +void +agent_flush_cache (void) +{ + ITEM r; + + if (DBG_CACHE) + log_debug ("agent_flush_cache\n"); + + for (r=thecache; r; r = r->next) + { + if (!r->lockcount && r->pw) + { + if (DBG_CACHE) + log_debug (" flushing `%s'\n", r->key); + release_data (r->pw); + r->pw = NULL; + r->accessed = 0; + } + else if (r->lockcount && r->pw) + { + if (DBG_CACHE) + log_debug (" marked `%s' for flushing\n", r->key); + r->accessed = 0; + r->ttl = 0; + } + } +} + + + +/* Store DATA of length DATALEN in the cache under KEY and mark it + with a maximum lifetime of TTL seconds. If there is already data + under this key, it will be replaced. Using a DATA of NULL deletes + the entry */ +int +agent_put_cache (const char *key, const char *data, int ttl) +{ + ITEM r; + + if (DBG_CACHE) + log_debug ("agent_put_cache `%s'\n", key); + housekeeping (); + + if (ttl < 1) + ttl = opt.def_cache_ttl; + if (!ttl) + return 0; + + for (r=thecache; r; r = r->next) + { + if (!r->lockcount && !strcmp (r->key, key)) + break; + } + if (r) + { /* replace */ + if (r->pw) + { + release_data (r->pw); + r->pw = NULL; + } + if (data) + { + r->created = r->accessed = gnupg_get_time (); + r->ttl = ttl; + r->pw = new_data (data, strlen (data)+1); + if (!r->pw) + log_error ("out of core while allocating new cache item\n"); + } + } + else if (data) + { /* simply insert */ + r = xtrycalloc (1, sizeof *r + strlen (key)); + if (!r) + log_error ("out of core while allocating new cache control\n"); + else + { + strcpy (r->key, key); + r->created = r->accessed = gnupg_get_time (); + r->ttl = ttl; + r->pw = new_data (data, strlen (data)+1); + if (!r->pw) + { + log_error ("out of core while allocating new cache item\n"); + xfree (r); + } + else + { + r->next = thecache; + thecache = r; + } + } + } + return 0; +} + + +/* Try to find an item in the cache */ +const char * +agent_get_cache (const char *key, void **cache_id) +{ + ITEM r; + + if (DBG_CACHE) + log_debug ("agent_get_cache `%s'...\n", key); + housekeeping (); + + /* first try to find one with no locks - this is an updated cache + entry: We might have entries with a lockcount and without a + lockcount. */ + for (r=thecache; r; r = r->next) + { + if (!r->lockcount && r->pw && !strcmp (r->key, key)) + { + /* put_cache does only put strings into the cache, so we + don't need the lengths */ + r->accessed = gnupg_get_time (); + if (DBG_CACHE) + log_debug ("... hit\n"); + r->lockcount++; + *cache_id = r; + return r->pw->data; + } + } + /* again, but this time get even one with a lockcount set */ + for (r=thecache; r; r = r->next) + { + if (r->pw && !strcmp (r->key, key)) + { + r->accessed = gnupg_get_time (); + if (DBG_CACHE) + log_debug ("... hit (locked)\n"); + r->lockcount++; + *cache_id = r; + return r->pw->data; + } + } + if (DBG_CACHE) + log_debug ("... miss\n"); + + *cache_id = NULL; + return NULL; +} + + +void +agent_unlock_cache_entry (void **cache_id) +{ + ITEM r; + + for (r=thecache; r; r = r->next) + { + if (r == *cache_id) + { + if (!r->lockcount) + log_error ("trying to unlock non-locked cache entry `%s'\n", + r->key); + else + r->lockcount--; + return; + } + } +} diff --git a/common/isascii.c b/common/isascii.c new file mode 100644 index 000000000..565c71664 --- /dev/null +++ b/common/isascii.c @@ -0,0 +1,29 @@ +/* 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); +} diff --git a/common/putc_unlocked.c b/common/putc_unlocked.c new file mode 100644 index 000000000..02c646130 --- /dev/null +++ b/common/putc_unlocked.c @@ -0,0 +1,31 @@ +/* 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); +} diff --git a/common/signal.c b/common/signal.c new file mode 100644 index 000000000..dc026c10f --- /dev/null +++ b/common/signal.c @@ -0,0 +1,226 @@ +/* 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); +} diff --git a/doc/ChangeLog b/doc/ChangeLog new file mode 100644 index 000000000..628793a90 --- /dev/null +++ b/doc/ChangeLog @@ -0,0 +1,593 @@ +2003-01-06 David Shaw <dshaw@jabberwocky.com> + + * DETAILS: Document disabled flag in capabilities field. + +2002-12-27 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify --no-permission-warning to note that the + permission warnings are not intended to be the be-all and end-all + in security checks. Add note to --group that when used on the + command line, it may be necessary to quote the argument so it is + not treated as multiple arguments. Noted by Stefan Bellon. + +2002-12-23 Werner Koch <wk@gnupg.org> + + * samplekeys.asc: Updated. + +2002-12-10 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify include-revoked and include-disabled so they + match what the program actually does. Noted by Dick Gevers. + + * gpg.sgml: Document %-expandos for policy URLs and notations. + + * gpg.sgml: Document --pgp8. Clarify that --pgp6 and --pgp7 + disable --throw-keyid. + +2002-12-05 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Document --no-mangle-dos-filenames. + +2002-12-01 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Point out that if the user absolutely must, it's + better to use --pgpX than forcing an algorithm manually. Better + still not to use anything, of course. + +2002-11-25 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Document --primary-keyring. Clarify + --s2k-cipher-algo, --s2k-digest-algo, + --personal-cipher-preferences, --personal-digest-preferences, and + --personal-compress-preferences. + + * gpg.sgml: Document --sig-policy-url, --cert-policy-url, + --sig-notation, --cert-notation. Clarify --show-notation and + --show-policy-url that policy URLs and notations can be used in + data signatures as well. Add note about '@' being a required + character in notation names. + +2002-11-21 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Add an interoperability section. + +2002-11-17 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Correct defaults for --s2k-mode and --s2k-digest-mode. + Noted by Haakon Riiser. + +2002-11-14 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: --compress-algo now allows algorithm names. + +2002-11-13 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Document --trust-model. + +2002-11-04 David Shaw <dshaw@jabberwocky.com> + + * KEYSERVER: New. Documents the --with-colons format for + keyserver listings. + + * DETAILS: Clarify meaning of 'u'. Noted by Timo. + +2002-11-03 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Document "tsign", clarify "setpref", clarify + --recipient, document --hidden-recipient, document + --hidden-encrypt-to, clarify --no-encrypt-to, clarify + --throw-keyid, document --no-throw-keyid. + +2002-10-25 Werner Koch <wk@gnupg.org> + + * README.W32: Add blurb on how to create a ZIP file, changed + requirement for mingw32 to 0.3.2. + +2002-10-24 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Document --refresh-keys. + +2002-10-19 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify --force-mdc, and document --disable-mdc. + +2002-10-12 Werner Koch <wk@gnupg.org> + + * DETAILS (KEY_CREATED): Enhanced by fingerprint. + +2002-10-03 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Note that '#' means secret-key-unavailable, and that + keyserver schemes are case-insensitive. + +2002-09-30 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Note that --pgp2 disables --textmode when encrypting. + +2002-09-20 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Some minor language cleanup. + +2002-09-20 Werner Koch <wk@gnupg.org> + + * DETAILS: s/XORed/ORed/. + +2002-09-15 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Add rebuild-keydb-caches. + +2002-09-12 David Shaw <dshaw@jabberwocky.com> + + * DETAILS: Fix batch key generation example. + +2002-09-11 Werner Koch <wk@gnupg.org> + + * Makefile.am (EXTRA_DIST): Include gnupg-32.reg + +2002-09-02 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Updated the charset option. + + * DETAILS: Added status IMPORT_OK. + + * gnupg.7: New mini man page. + +2002-08-30 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Document keyserver-option include-subkeys. Note that + honor-http-proxy is a keyserver-option now. + + * DETAILS: Add "Key not trusted" to INV_RECP status code. + +2002-08-23 Werner Koch <wk@gnupg.org> + + * faq.raw: Updated. New Maintainer is David D. Scribner. + +2002-08-22 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify meaning of keyserver option include-revoked. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * DETAILS: Added IMPORT_PROBLEM. + +2002-08-20 David Shaw <dshaw@jabberwocky.com> + + * DETAILS: Clarify that trust letters 'q' and '-' can be treated + identically. + + * gpg.sgml: Document --ignore-mdc-error. + +2002-08-06 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify that only long-form options can go in the + config file. + +2002-08-06 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Fixed doc regarding the name change of the option + file. + +2002-07-30 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify --edit/addrevoker (sensitive), and + --keyserver-options (--import/export-options may be used as well). + Document --import-options and --export-options with their various + options. --show-photos now works during signature verification as + well. Document --exec-path. Note in --simple-sk-checksum that + the passphrase must be changed for this to take effect. Note that + --pgp7 does not disable MDC. Document --no-mdc-warning. + +2002-07-25 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Document new --delete behaviour. + +2002-07-25 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify the differences between "pref" and "showpref". + Note in "setpref" that a list of available algorithms can be + printed with "gpg -v --version". Note in "updpref" that we don't + select keys via attribute uids, so preferences there will be + ignored. + +2002-07-01 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Clarify "group". + +2002-07-01 Werner Koch <wk@gnupg.org> + + * Makefile.am: Due to problems with VPATH builds we don't try to + build the texi vesions of the manual pages anymore automatically. + +2002-06-30 Werner Koch <wk@gnupg.org> + + * README.W32: Adjusted some descriptions. Fixed the regsitry + entry descriptions. + +2002-06-21 David Shaw <dshaw@jabberwocky.com> + + * DETAILS: Document "uat". + + * gpg.sgml: Document + --personal-{compress|digest|compress}-preferences, --group, and + add comments to --expert. + +2002-06-17 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Grammar fix. + +2002-06-03 David Shaw <dshaw@jabberwocky.com> + + * DETAILS: Details of ATTRIBUTE. + + * gpg.sgml: Document --attribute-fd + +2002-06-03 Timo Schulz <ts@winpt.org> + + * DETAILS: Add ATTRIBUTE. + +2002-05-31 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Add "edit/addrevoker". Document --desig-revoke. Note + that -z and --compress are the same option. Note that + --digest-algo can no longer violate OpenPGP with a non-160 bit + hash with DSA. Document --cert-digest-algo with suitable warnings + not to use it. Note the default s2k-cipher-algo is now CAST5. + Note that --force-v3-sigs overrides --ask-sig-expire. Revise + --expert documentation, as it is now definitely legal to have more + than one photo ID on a key. --preference-list is now + --default-preference-list with the new meaning. Document + --personal-preference-list. + + * DETAILS: Document "Revoker" for batch key generation. + +2002-05-22 Werner Koch <wk@gnupg.org> + + * gpg.sgml: sgml syntax fix. + +2002-05-12 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Fixed URL in the description section. + + * faq.raw: Minor typo fixes noted by kromJx@myrealbox.com. + +2002-05-11 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Typo fix. + +2002-05-07 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Add entries for --sk-comments, --no-sk-comments, + --pgp7, and --no-pgp7. Fix --pgp2 and --pgp6: the proper name is + --escape-from-lines and not --escape-from. + +2002-04-30 Timo Schulz <ts@winpt.org> + + * gpg.sgml: Add an entry for --encrypt-files and --decrypt-files. + +2002-04-29 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Fix minor error in --pgp6 documentation: it does not + imply --digest-algo MD5 + +2002-04-29 Werner Koch <wk@gnupg.org> + + * samplekeys.asc: Added gnupg distribution key 57548DCD. + + * faq.raw: Inserted Douglas Calvert as new maintainer. Acknowledge + Nils. Add entry about trust packet parsing problems. + +2002-04-24 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Add some documentation for + --edit/{addphoto|showphoto|nrsign|nrlsign}, and the difference + between %t and %T in photo viewer command lines. + +2002-04-23 Stefan Bellon <sbellon@sbellon.de> + + * gpg.sgml: Moved options from section "COMMANDS" to + section "OPTIONS". + +2002-04-20 David Shaw <dshaw@jabberwocky.com> + + * samplekeys.asc: Added 0x5B0358A2 + +2002-04-19 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Add "%t" flag for photo IDs, a note about primary + having different meanings for photo and regular IDs, rename + --default-check-level to --default-cert-check-level, add + --auto-check-trustdb, and --pgp6. + + * DETAILS: Add EXPSIG, EXPKEYSIG, and KEYEXPIRED. Add notes to + SIGEXPIRED (deprecated), and VALIDSIG (added expiration date). + Add "Preferences" command to unattended key generation + instructions. Also fixed a few typos. + + * samplekeys.asc: new (added to EXTRA_DIST in Makefile.am as well) + +2002-01-31 Marcus Brinkmann <marcus@g10code.de> + + * DETAILS: Fix a spelling error, correct IMPORTED_RES to IMPORT_RES, + correct INV_RECP (the second occurence) to NO_RECP. + +2002-04-03 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: auto-key-retrieve is a keyserver-option (noted by + Roger Sondermann). + +2002-03-27 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: --pgp2 also means --disable-mdc, --no-ask-sig-expire, + and --no-ask-cert-expire. It does not mean --no-force-v3-sigs + (noted by Timo). + +2002-03-27 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Add a few notes about --pgp2 meaning MIT PGP 2.6.2, + and keyserver details about HKP and NAI HKP. + +2002-03-18 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Change meaning of --allow-non-selfsigned-uid to match + change in code, and add --no-allow-non-selfsigned-uid. + +2002-03-13 Werner Koch <wk@gnupg.org> + + * faq.raw: Due to a lack of time Nils can't serve anymore as a + maintainer. Removed his address and setup a generic address. + +2002-03-06 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Add an entry for --export-ownertrust. Suggested by + Bernhard Reiter. + +2002-01-26 Timo Schulz <ts@winpt.org> + + * gnupg-w32.reg: New. Registry file for W32 in registry format. + +2002-01-26 Werner Koch <wk@gnupg.org> + + * gpg.sgml: A few words about --gpg-agent-info and GPG_AGENT_INFO. + +2002-01-25 Timo Schulz <ts@winpt.org> + + * README.W32: Modify the filename because now the .exe extension + is automatically added to the binary. + +2002-01-14 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Talk about PGP 5 and higher. + +2002-01-11 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Added documentation for --{no-}ask-cert-expire, + --{no-}ask-sig-expire, and revise --expert (it doesn't switch on + the expiration prompt anymore) and --default-check-level (to be + clearer as to what makes a good key check before signing). + +2002-01-07 Werner Koch <wk@gnupg.org> + + * DETAILS: Removed the comment that unattended key generation is + experimental. It is now a standard feature. + +2001-12-22 David Shaw <dshaw@jabberwocky.com> + + * gpg.sgml: Fixed a few typos. + + * gpg.sgml: Added documentation for --show-photos, + --no-show-photos, --photo-viewer, --nrsign-key, + --default-check-level, --search-keys, --keyserver-options, + --show-notation, --no-show-notation, --show-policy-url, + --no-show-policy-url, --for-your-eyes-only, + --no-for-your-eyes-only, --pgp2, --no-pgp2, + --no-permission-warning, --expert, --no-expert. + +2001-10-31 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Add a remark on how to get the long key ID. Suggested + by Sebastian Klemke. + +2001-10-23 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Add missing tag. + +2001-09-28 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Add a note on option parsing. + +2001-09-24 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Described --{update,check}-trustdb. + +2001-09-03 Werner Koch <wk@gnupg.org> + + * gpg.sgml, gpgv.sgml: Removed GDBM stuff. + +2001-08-29 Werner Koch <wk@gnupg.org> + + * faq.raw: Described how to delete a secret key w/o a public key + and changed the entry on updating the preferences. + +2001-08-08 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Documented --print-mds and marked the --print-md * as + deprecated because it does not work in the W32 version. Suggested + by John Kane. + (WARNINGS): Typo fix. + (--with-colons): Clarified that the output is in UTF-8. + +2001-08-01 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Added --ignore-valid-from + +2001-04-20 Werner Koch <wk@gnupg.org> + + * faq.raw (Maintained-by): Removed note that load-extension is not + available under Windoze. + + * gpg.sgml: Add new --charset UTF-8. + +2001-04-19 Werner Koch <wk@gnupg.org> + + * faq.raw: Add a note about dates displayed as ????-??-??. + +2001-04-17 Werner Koch <wk@gnupg.org> + + * Makefile.am (%.texi): Add rules to create .texi from .sgml. + However we can't automate this because automake does not like + .texi files as BUILT_SOURCES. + (%.dvi,%.ps): Removed these rules, because they are not needed + and get in the way of automake's dvi target + + * HACKING: Changed CVS description. + +2001-04-06 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Small typo fixes by Florian Weimer. + +2001-03-27 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Add --no-sig-cache and --no-sig-create-check. + +2001-03-23 Werner Koch <wk@gnupg.org> + + * DETAILS: New status UNEXPECTED. + +2001-03-13 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Described --fixed-list-mode. + +2001-03-06 Werner Koch <wk@gnupg.org> + + * gpgv.sgml: Changed some gpg to gpgv. Thanks to John A. Murdie. + +2001-03-03 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Tell something about the 0x12345678! key ID syntax. + +2001-01-18 Werner Koch <wk@gnupg.org> + + * README.W32: Changed building instructions for MinGW32/CPD 0.3 + +2001-01-09 Werner Koch <wk@gnupg.org> + + * DETAILS: Fixed docs for NEED_PASSPHRASE and added USERID_HINT. + +2000-11-30 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Fixed the description of --verify. Add a short note + the warnings sections. + +2000-10-19 Werner Koch <wk@gnupg.org> + + * gpg.sgml: Fixed doc for --allow-non-selfsigned-uid. + Add entry for --ignore-crc-error. + +2000-10-18 Werner Koch <wk@gnupg.org> + + * OpenPGP: Dropped the paragraph that RSA is not implemented. + +2000-10-14 Werner Koch <wk@gnupg.org> + + * faq.raw: Add an answer to the problem of multiple signatures. + +Wed Oct 4 15:50:18 CEST 2000 Werner Koch <wk@openit.de> + + * gpgv.sgml: New. + * Makefile.am: build it. + +Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> + + * faq.raw: New. + * Makefile.am: Support to build FAQs + +Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@> + + * gpg.sgml: Add a note about the availability of the GPH. + +2000-07-03 13:59:24 Werner Koch (wk@habibti.openit.de) + + * DETAILS, FAQ: Typo fixes by Yosiaki IIDA. + +2000-05-12 10:57:21 Werner Koch (wk@habibti.openit.de) + + * gpg.sgml: Documented --no-tty. + +2000-03-09 15:01:51 Werner Koch (wk@habibti.openit.de) + + * DETAILS: Ad a short blurb about unattended key generation. + +Wed Feb 9 15:33:44 CET 2000 Werner Koch <wk@gnupg.de> + + * gpg.sgml: Describe --ignore-time-conflict. + + * gpg.sgml: Fixed a few typos. Thanks to Holger Trapp. + +Wed Jan 5 11:51:17 CET 2000 Werner Koch <wk@gnupg.de> + + * FAQ: Enhanced answer for the 3des-s2k bug. + +Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de> + + * gpg.sgml: Add section about the user ID + +Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de> + + * gph: Removed the directory from the dist becuase it will + go into it's own package. + +Thu Sep 23 09:52:58 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * README.W32: New. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * Makefile.am (SUBDIRS): New subdir gph for the manual. + +Thu Jul 22 20:03:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * gpg.sgml (--always-trust): Added. + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * Makefile.am: Create a dummy man page if docbook-to-man is missing. + +Wed Jun 16 20:16:21 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * gpg1.pod: Removed. + * gpg.sgml: New. Replaces the pod file + * Makefile.am: Add rule to make a man file from sgml + +Tue Jun 15 12:21:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * Makefile.in.in: Use DESTDIR. + +Mon May 31 19:41:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * gpg.1pod: Enhanced the Bugs section (Michael). + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * gpg.1pod: Spelling and grammar corrections (John A. Martin) + * FAQ: Ditto. + * DETAILS: Ditto. + + + Copyright 1998, 1999, 2000, 2001 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. + + diff --git a/g10/delkey.c b/g10/delkey.c new file mode 100644 index 000000000..35c903cc0 --- /dev/null +++ b/g10/delkey.c @@ -0,0 +1,209 @@ +/* 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):G10ERR_INV_USER_ID; + if (rc) { + log_error (_("key `%s' not found: %s\n"), username, g10_errstr (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"), g10_errstr(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 = G10ERR_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 != G10ERR_NO_SECKEY ) { + log_error("%s: get secret key: %s\n", username, g10_errstr(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( 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"), g10_errstr(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, g10_errstr(rc) ); + return rc; + } + } + + return 0; +} diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c new file mode 100644 index 000000000..1c52ce4de --- /dev/null +++ b/g10/pubkey-enc.c @@ -0,0 +1,307 @@ +/* pubkey-enc.c - public key encoded packet 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 <string.h> +#include <assert.h> +#include "util.h" +#include "memory.h" +#include "packet.h" +#include "mpi.h" +#include "keydb.h" +#include "trustdb.h" +#include "cipher.h" +#include "status.h" +#include "options.h" +#include "main.h" +#include "i18n.h" + +static int get_it( PKT_pubkey_enc *k, + DEK *dek, PKT_secret_key *sk, u32 *keyid ); + + +/* check that the given algo is mentioned in one of the valid user IDs */ +static int +is_algo_in_prefs ( KBNODE keyblock, preftype_t type, int algo ) +{ + KBNODE k; + + for (k=keyblock; k; k=k->next) { + if (k->pkt->pkttype == PKT_USER_ID) { + PKT_user_id *uid = k->pkt->pkt.user_id; + prefitem_t *prefs = uid->prefs; + + if (uid->created && prefs && + !uid->is_revoked && !uid->is_expired ) { + for (; prefs->type; prefs++ ) + if (prefs->type == type && prefs->value == algo) + return 1; + } + } + } + return 0; +} + + +/**************** + * Get the session key from a pubkey enc packet and return + * it in DEK, which should have been allocated in secure memory. + */ +int +get_session_key( PKT_pubkey_enc *k, DEK *dek ) +{ + PKT_secret_key *sk = NULL; + int rc; + + rc = check_pubkey_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC); + if( rc ) + goto leave; + + if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) { + sk = m_alloc_clear( sizeof *sk ); + sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/ + if( !(rc = get_seckey( sk, k->keyid )) ) + rc = get_it( k, dek, sk, k->keyid ); + } + else { /* anonymous receiver: Try all available secret keys */ + void *enum_context = NULL; + u32 keyid[2]; + char *p; + + for(;;) { + if( sk ) + free_secret_key( sk ); + sk = m_alloc_clear( sizeof *sk ); + rc=enum_secret_keys( &enum_context, sk, 1, 0); + if( rc ) { + rc = G10ERR_NO_SECKEY; + break; + } + if( sk->pubkey_algo != k->pubkey_algo ) + continue; + keyid_from_sk( sk, keyid ); + log_info(_("anonymous recipient; trying secret key %08lX ...\n"), + (ulong)keyid[1] ); + + if(!opt.try_all_secrets && !is_status_enabled()) + { + p=get_last_passphrase(); + set_next_passphrase(p); + m_free(p); + } + + rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask + only + once */ + if( !rc ) + rc = get_it( k, dek, sk, keyid ); + if( !rc ) { + log_info(_("okay, we are the anonymous recipient.\n") ); + break; + } + } + enum_secret_keys( &enum_context, NULL, 0, 0 ); /* free context */ + } + + leave: + if( sk ) + free_secret_key( sk ); + return rc; +} + + +static int +get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) +{ + int rc; + MPI plain_dek = NULL; + byte *frame = NULL; + unsigned n, nframe; + u16 csum, csum2; + + rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey ); + if( rc ) + goto leave; + frame = mpi_get_buffer( plain_dek, &nframe, NULL ); + mpi_free( plain_dek ); plain_dek = NULL; + + /* Now get the DEK (data encryption key) from the frame + * + * Old versions encode the DEK in in this format (msb is left): + * + * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 + * + * Later versions encode the DEK like this: + * + * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) + * + * (mpi_get_buffer already removed the leading zero). + * + * RND are non-zero randow bytes. + * A is the cipher algorithm + * DEK is the encryption key (session key) with length k + * CSUM + */ + if( DBG_CIPHER ) + log_hexdump("DEK frame:", frame, nframe ); + n=0; + if( n + 7 > nframe ) + { rc = G10ERR_WRONG_SECKEY; goto leave; } + if( frame[n] == 1 && frame[nframe-1] == 2 ) { + log_info(_("old encoding of the DEK is not supported\n")); + rc = G10ERR_CIPHER_ALGO; + goto leave; + } + if( frame[n] != 2 ) /* somethink is wrong */ + { rc = G10ERR_WRONG_SECKEY; goto leave; } + for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ + ; + n++; /* and the zero byte */ + if( n + 4 > nframe ) + { rc = G10ERR_WRONG_SECKEY; goto leave; } + + dek->keylen = nframe - (n+1) - 2; + dek->algo = frame[n++]; + if( dek->algo == CIPHER_ALGO_IDEA ) + write_status(STATUS_RSA_OR_IDEA); + rc = check_cipher_algo( dek->algo ); + if( rc ) { + if( !opt.quiet && rc == G10ERR_CIPHER_ALGO ) { + log_info(_("cipher algorithm %d%s is unknown or disabled\n"), + dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); + if(dek->algo==CIPHER_ALGO_IDEA) + idea_cipher_warn(0); + } + dek->algo = 0; + goto leave; + } + if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) { + rc = G10ERR_WRONG_SECKEY; + goto leave; + } + + /* copy the key to DEK and compare the checksum */ + csum = frame[nframe-2] << 8; + csum |= frame[nframe-1]; + memcpy( dek->key, frame+n, dek->keylen ); + for( csum2=0, n=0; n < dek->keylen; n++ ) + csum2 += dek->key[n]; + if( csum != csum2 ) { + rc = G10ERR_WRONG_SECKEY; + goto leave; + } + if( DBG_CIPHER ) + log_hexdump("DEK is:", dek->key, dek->keylen ); + /* check that the algo is in the preferences and whether it has expired */ + { + PKT_public_key *pk = NULL; + KBNODE pkb = get_pubkeyblock (keyid); + + if( !pkb ) { + rc = -1; + log_error("oops: public key not found for preference check\n"); + } + else if( pkb->pkt->pkt.public_key->selfsigversion > 3 + && dek->algo != CIPHER_ALGO_3DES + && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) { + /* Don't print a note while we are not on verbose mode, + * the cipher is blowfish and the preferences have twofish + * listed */ + if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH + || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH)) + log_info(_( + "NOTE: cipher algorithm %d not found in preferences\n"), + dek->algo ); + } + + if (!rc) { + KBNODE k; + + for (k=pkb; k; k = k->next) { + if (k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ + u32 aki[2]; + keyid_from_pk(k->pkt->pkt.public_key, aki); + + if (aki[0]==keyid[0] && aki[1]==keyid[1]) { + pk = k->pkt->pkt.public_key; + break; + } + } + } + if (!pk) + BUG (); + if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { + log_info(_("NOTE: secret key %08lX expired at %s\n"), + (ulong)keyid[1], asctimestamp( pk->expiredate) ); + } + } + + if ( pk && pk->is_revoked ) { + log_info( _("NOTE: key has been revoked") ); + putc( '\n', log_stream() ); + show_revocation_reason( pk, 1 ); + } + + release_kbnode (pkb); + rc = 0; + } + + + leave: + mpi_free(plain_dek); + m_free(frame); + return rc; +} + + +/**************** + * Get the session key from the given string. + * String is supposed to be formatted as this: + * <algo-id>:<even-number-of-hex-digits> + */ +int +get_override_session_key( DEK *dek, const char *string ) +{ + const char *s; + int i; + + if ( !string ) + return G10ERR_BAD_KEY; + dek->algo = atoi(string); + if ( dek->algo < 1 ) + return G10ERR_BAD_KEY; + if ( !(s = strchr ( string, ':' )) ) + return G10ERR_BAD_KEY; + s++; + for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) { + int c = hextobyte ( s ); + if (c == -1) + return G10ERR_BAD_KEY; + dek->key[i] = c; + } + if ( *s ) + return G10ERR_BAD_KEY; + dek->keylen = i; + return 0; +} + diff --git a/g10/status.h b/g10/status.h new file mode 100644 index 000000000..44a7d6d32 --- /dev/null +++ b/g10/status.h @@ -0,0 +1,127 @@ +/* status.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_STATUS_H +#define G10_STATUS_H + + +#define STATUS_ENTER 1 +#define STATUS_LEAVE 2 +#define STATUS_ABORT 3 + +#define STATUS_GOODSIG 4 +#define STATUS_BADSIG 5 +#define STATUS_ERRSIG 6 + + +#define STATUS_BADARMOR 7 + +#define STATUS_RSA_OR_IDEA 8 +#define STATUS_KEYEXPIRED 9 +#define STATUS_KEYREVOKED 10 + +#define STATUS_TRUST_UNDEFINED 11 +#define STATUS_TRUST_NEVER 12 +#define STATUS_TRUST_MARGINAL 13 +#define STATUS_TRUST_FULLY 14 +#define STATUS_TRUST_ULTIMATE 15 + +#define STATUS_SHM_INFO 16 +#define STATUS_SHM_GET 17 +#define STATUS_SHM_GET_BOOL 18 +#define STATUS_SHM_GET_HIDDEN 19 + +#define STATUS_NEED_PASSPHRASE 20 +#define STATUS_VALIDSIG 21 +#define STATUS_SIG_ID 22 +#define STATUS_ENC_TO 23 +#define STATUS_NODATA 24 +#define STATUS_BAD_PASSPHRASE 25 +#define STATUS_NO_PUBKEY 26 +#define STATUS_NO_SECKEY 27 +#define STATUS_NEED_PASSPHRASE_SYM 28 +#define STATUS_DECRYPTION_FAILED 29 +#define STATUS_DECRYPTION_OKAY 30 +#define STATUS_MISSING_PASSPHRASE 31 +#define STATUS_GOOD_PASSPHRASE 32 +#define STATUS_GOODMDC 33 +#define STATUS_BADMDC 34 +#define STATUS_ERRMDC 35 +#define STATUS_IMPORTED 36 +#define STATUS_IMPORT_RES 37 +#define STATUS_FILE_START 38 +#define STATUS_FILE_DONE 39 +#define STATUS_FILE_ERROR 40 + +#define STATUS_BEGIN_DECRYPTION 41 +#define STATUS_END_DECRYPTION 42 +#define STATUS_BEGIN_ENCRYPTION 43 +#define STATUS_END_ENCRYPTION 44 + +#define STATUS_DELETE_PROBLEM 45 +#define STATUS_GET_BOOL 46 +#define STATUS_GET_LINE 47 +#define STATUS_GET_HIDDEN 48 +#define STATUS_GOT_IT 49 +#define STATUS_PROGRESS 50 +#define STATUS_SIG_CREATED 51 +#define STATUS_SESSION_KEY 52 +#define STATUS_NOTATION_NAME 53 +#define STATUS_NOTATION_DATA 54 +#define STATUS_POLICY_URL 55 +#define STATUS_BEGIN_STREAM 56 +#define STATUS_END_STREAM 57 +#define STATUS_KEY_CREATED 58 +#define STATUS_USERID_HINT 59 +#define STATUS_UNEXPECTED 60 +#define STATUS_INV_RECP 61 +#define STATUS_NO_RECP 62 +#define STATUS_ALREADY_SIGNED 63 +#define STATUS_SIGEXPIRED 64 +#define STATUS_EXPSIG 65 +#define STATUS_EXPKEYSIG 66 +#define STATUS_ATTRIBUTE 67 +#define STATUS_IMPORT_OK 68 +#define STATUS_IMPORT_CHECK 69 + +/*-- status.c --*/ +void set_status_fd ( int fd ); +int is_status_enabled ( void ); +void write_status ( int no ); +void write_status_text ( int no, const char *text ); +void write_status_buffer ( int no, + const char *buffer, size_t len, int wrap ); +void write_status_text_and_buffer ( int no, const char *text, + const char *buffer, size_t len, int wrap ); + +#ifdef USE_SHM_COPROCESSING + void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ); +#endif /*USE_SHM_COPROCESSING*/ + +int cpr_enabled(void); +char *cpr_get( const char *keyword, const char *prompt ); +char *cpr_get_no_help( const char *keyword, const char *prompt ); +char *cpr_get_utf8( const char *keyword, const char *prompt ); +char *cpr_get_hidden( const char *keyword, const char *prompt ); +void cpr_kill_prompt(void); +int cpr_get_answer_is_yes( const char *keyword, const char *prompt ); +int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ); + + +#endif /*G10_STATUS_H*/ diff --git a/include/_regex.h b/include/_regex.h new file mode 100644 index 000000000..fac441dc6 --- /dev/null +++ b/include/_regex.h @@ -0,0 +1,574 @@ +/* Definitions for data structures and routines for the regular + expression library. + Copyright (C) 1985,1989-93,1995-98,2000,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEX_H +#define _REGEX_H 1 + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* POSIX says that <sys/types.h> must be included (by the caller) before + <regex.h>. */ + +#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS +/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it + should be there. */ +# include <stddef.h> +#endif + +/* The following two types have to be signed and unsigned integer type + wide enough to hold a value of a pointer. For most ANSI compilers + ptrdiff_t and size_t should be likely OK. Still size of these two + types is 2 for Microsoft C. Ugh... */ +typedef long int s_reg_t; +typedef unsigned long int active_reg_t; + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned long int reg_syntax_t; + +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +#define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then `{...}' defines an interval, and \{ and \} + are literals. + If not set, then `\{...\}' defines an interval. */ +#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \<digit> matches <digit>. + If not set, then \<digit> is a back-reference. */ +#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* If this bit is set, succeed as soon as we match the whole pattern, + without further backtracking. */ +#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) + +/* If this bit is set, do not process the GNU regex operators. + If not set, then the GNU regex operators are recognized. */ +#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) + +/* If this bit is set, turn on internal regex debugging. + If not set, and debugging was on, turn it off. + This only works if regex.c is compiled -DDEBUG. + We define this bit always, so that all that's needed to turn on + debugging is to recompile regex.c; the calling code can always have + this bit set, and it won't affect anything in the normal case. */ +#define RE_DEBUG (RE_NO_GNU_OPS << 1) + +/* If this bit is set, a syntactically invalid interval is treated as + a string of ordinary characters. For example, the ERE 'a{1' is + treated as 'a\{1'. */ +#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +#define RE_SYNTAX_EMACS 0 + +#define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) + +#define RE_SYNTAX_GNU_AWK \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ + & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INTERVALS | RE_NO_GNU_OPS) + +#define RE_SYNTAX_GREP \ + (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ + | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ + | RE_NEWLINE_ALT) + +#define RE_SYNTAX_EGREP \ + (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ + | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ + | RE_NO_BK_VBAR) + +#define RE_SYNTAX_POSIX_EGREP \ + (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ + | RE_INVALID_INTERVAL_ORD) + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +#define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +#define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +#define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is + removed and RE_NO_BK_REFS is added. */ +#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +# undef RE_DUP_MAX +#endif +/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ +#define RE_DUP_MAX (0x7fff) + + +/* POSIX `cflags' bits (i.e., information for `regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (REG_EXTENDED << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (REG_ICASE << 1) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (REG_NEWLINE << 1) + + +/* POSIX `eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ +#ifdef _XOPEN_SOURCE + REG_ENOSYS = -1, /* This will never happen for this implementation. */ +#endif + + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT, /* Invalid pattern. */ + REG_ECOLLATE, /* Not implemented. */ + REG_ECTYPE, /* Invalid character class name. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_ESUBREG, /* Invalid back reference. */ + REG_EBRACK, /* Unmatched left bracket. */ + REG_EPAREN, /* Parenthesis imbalance. */ + REG_EBRACE, /* Unmatched \{. */ + REG_BADBR, /* Invalid contents of \{\}. */ + REG_ERANGE, /* Invalid range end. */ + REG_ESPACE, /* Ran out of memory. */ + REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + REG_EEND, /* Premature end. */ + REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields `buffer', `allocated', `fastmap', + `translate', and `no_sub' can be set. After the pattern has been + compiled, the `re_nsub' field is available. All other fields are + private to the regex routines. */ + +#ifndef RE_TRANSLATE_TYPE +# define RE_TRANSLATE_TYPE char * +#endif + +struct re_pattern_buffer +{ +/* [[[begin pattern_buffer]]] */ + /* Space that holds the compiled pattern. It is declared as + `unsigned char *' because its elements are + sometimes used as array indexes. */ + unsigned char *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long int allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long int used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t syntax; + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses + the fastmap, if there is one, to skip over impossible + starting points for matches. */ + char *fastmap; + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation + is applied to a pattern when it is compiled and to a string + when it is matched. */ + RE_TRANSLATE_TYPE translate; + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in `re_search_2', to see + whether or not we should use the fastmap, so we don't set + this absolutely perfectly; see `re_compile_fastmap' (the + `duplicate' case). */ + unsigned can_be_null : 1; + + /* If REGS_UNALLOCATED, allocate space in the `regs' structure + for `max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned regs_allocated : 2; + + /* Set to zero when `regex_compile' compiles a pattern; set to one + by `re_compile_fastmap' if it updates the fastmap. */ + unsigned fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the + beginning of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; + +/* [[[end pattern_buffer]]] */ +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_t; + + +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + unsigned num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + `re_match_2' returns information about at least this many registers + the first time a `regs' structure is passed. */ +#ifndef RE_NREGS +# define RE_NREGS 30 +#endif + + +/* POSIX specification for registers. Aside from the different names than + `re_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + +/* To avoid duplicating every routine declaration -- once with a + prototype (if we are ANSI), and once without (if we aren't) -- we + use the following macro to declare argument types. This + unfortunately clutters up the declarations a bit, but I think it's + worth it. */ + +#if __STDC__ + +# define _RE_ARGS(args) args + +#else /* not __STDC__ */ + +# define _RE_ARGS(args) () + +#endif /* not __STDC__ */ + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global `re_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. */ +extern const char *re_compile_pattern + _RE_ARGS ((const char *pattern, size_t length, + struct re_pattern_buffer *buffer)); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern int re_search + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, int range, struct re_registers *regs)); + + +/* Like `re_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern int re_search_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, int range, struct re_registers *regs, int stop)); + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, + int length, int start, struct re_registers *regs)); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 + _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, + int length1, const char *string2, int length2, + int start, struct re_registers *regs, int stop)); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least `NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers + _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends)); + +#if defined _REGEX_RE_COMP || defined _LIBC +# ifndef _CRAY +/* 4.2 bsd compatibility. */ +extern char *re_comp _RE_ARGS ((const char *)); +extern int re_exec _RE_ARGS ((const char *)); +# endif +#endif + +/* GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". */ +#ifndef __restrict +# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) +# if defined restrict || 199901L <= __STDC_VERSION__ +# define __restrict restrict +# else +# define __restrict +# endif +# endif +#endif +/* gcc 3.1 and up support the [restrict] syntax. */ +#ifndef __restrict_arr +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define __restrict_arr __restrict +# else +# define __restrict_arr +# endif +#endif + +/* POSIX compatibility. */ +extern int regcomp _RE_ARGS ((regex_t *__restrict __preg, + const char *__restrict __pattern, + int __cflags)); + +extern int regexec _RE_ARGS ((const regex_t *__restrict __preg, + const char *__restrict __string, size_t __nmatch, + regmatch_t __pmatch[__restrict_arr], + int __eflags)); + +extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg, + char *__errbuf, size_t __errbuf_size)); + +extern void regfree _RE_ARGS ((regex_t *__preg)); + + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* regex.h */ + +/* +Local variables: +make-backup-files: t +version-control: t +trim-versions-without-asking: nil +End: +*/ diff --git a/include/distfiles b/include/distfiles new file mode 100644 index 000000000..20a9091e6 --- /dev/null +++ b/include/distfiles @@ -0,0 +1,15 @@ +cipher.h +errors.h +iobuf.h +memory.h +mpi.h +ttyio.h +types.h +util.h +i18n.h +host2net.h +http.h +keyserver.h +_regex.h + +ChangeLog diff --git a/include/ttyio.h b/include/ttyio.h new file mode 100644 index 000000000..5f6557930 --- /dev/null +++ b/include/ttyio.h @@ -0,0 +1,40 @@ +/* ttyio.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_TTYIO_H +#define G10_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))); +#else + void tty_printf (const char *fmt, ... ); +#endif +void tty_print_string( byte *p, size_t n ); +void tty_print_utf8_string( byte *p, size_t n ); +void tty_print_utf8_string2( byte *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 /*G10_TTYIO_H*/ diff --git a/include/zlib-riscos.h b/include/zlib-riscos.h new file mode 100644 index 000000000..fad556bcb --- /dev/null +++ b/include/zlib-riscos.h @@ -0,0 +1,134 @@ +/* zlib-riscos.h + * 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 G10_ZLIB_RISCOS_H +#define G10_ZLIB_RISCOS_H + +#include <kernel.h> +#include <swis.h> + +static const char * const zlib_path[] = { + "System:310.Modules.ZLib", + NULL +}; + +#define ZLib_Compress 0x53AC0 +#define ZLib_Decompress 0x53AC1 +#define ZLib_CRC32 0x53AC2 +#define ZLib_Adler32 0x53AC3 +#define ZLib_Version 0x53AC4 +#define ZLib_ZCompress 0x53AC5 +#define ZLib_ZCompress2 0x53AC6 +#define ZLib_ZUncompress 0x53AC7 +#define ZLib_DeflateInit 0x53AC8 +#define ZLib_InflateInit 0x53AC9 +#define ZLib_DeflateInit2 0x53ACA +#define ZLib_InflateInit2 0x53ACB +#define ZLib_Deflate 0x53ACC +#define ZLib_DeflateEnd 0x53ACD +#define ZLib_Inflate 0x53ACE +#define ZLib_InflateEnd 0x53ACF +#define ZLib_DeflateSetDictionary 0x53AD0 +#define ZLib_DeflateCopy 0x53AD1 +#define ZLib_DeflateReset 0x53AD2 +#define ZLib_DeflateParams 0x53AD3 +#define ZLib_InflateSetDictionary 0x53AD4 +#define ZLib_InflateSync 0x53AD5 +#define ZLib_InflateReset 0x53AD6 +#define ZLib_GZOpen 0x53AD7 +#define ZLib_GZRead 0x53AD8 +#define ZLib_GRWrite 0x53AD9 +#define ZLib_GZFlush 0x53ADA +#define ZLib_GZClose 0x53ADB +#define ZLib_GZError 0x53ADC +#define ZLib_GZSeek 0x53ADD +#define ZLib_GZTell 0x53ADE +#define ZLib_GZEOF 0x53ADF +#define ZLib_TaskAssociate 0x53AE0 + +#define crc32(r0,r1,r2) \ + _swi(ZLib_CRC32, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define adler32(r0,r1,r2) \ + _swi(ZLib_Adler32, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define zlibVersion() \ + _swi(ZLib_Version, _RETURN(0)) +#define compress(r0,r1,r2,r3) \ + _swi(ZLib_ZCompress, _INR(0,3) | _RETURN(0)|_OUT(1), r0,r1,r2,r3, &r1) +#define compress2(r0,r1,r2,r3,r4) \ + _swi(ZLib_ZCompress2, _INR(0,4) | _RETURN(0)|_OUT(1), r0,r1,r2,r3,r4, &r1) +#define uncompress(r0,r1,r2,r3) \ + _swi(ZLib_ZUncompress, _INR(0,3) | _RETURN(0)|_OUT(1), r0,r1,r2,r3, &r1) +#define deflateInit_(r0,r1,r2,r3) \ + _swi(ZLib_DeflateInit, _INR(0,3) | _RETURN(0), r0,r1,r2,r3) +#define inflateInit_(r0,r1,r2) \ + _swi(ZLib_InflateInit, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define deflateInit2_(r0,r1,r2,r3,r4,r5,r6,r7) \ + _swi(ZLib_DeflateInit2, _INR(0,7) | _RETURN(0), r0,r1,r2,r3,r4,r5,r6,r7) +#define inflateInit2_(r0,r1,r2,r3) \ + _swi(ZLib_InflateInit2, _INR(0,3) | _RETURN(0), r0,r1,r2,r3) +#define deflate(r0,r1) \ + _swi(ZLib_Deflate, _INR(0,1) | _RETURN(0), r0,r1) +#define deflateEnd(r0) \ + _swi(ZLib_DeflateEnd, _IN(0) | _RETURN(0), r0) +#define inflate(r0,r1) \ + _swi(ZLib_Inflate, _INR(0,1) | _RETURN(0), r0,r1) +#define inflateEnd(r0) \ + _swi(ZLib_InflateEnd, _IN(0) | _RETURN(0), r0) +#define deflateSetDictionary(r0,r1,r2) \ + _swi(ZLib_DeflateSetDictionary, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define deflateCopy(r0,r1) \ + _swi(ZLib_DeflateCopy, _INR(0,1) | _RETURN(0), r0,r1) +#define deflateReset(r0) \ + _swi(ZLib_DeflateReset, _IN(0) | _RETURN(0), r0) +#define deflateParams(r0,r1,r2) \ + _swi(ZLib_DeflateParams, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define inflateSetDictionary(r0,r1,r2) \ + _swi(ZLib_InflateSetDictionary, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define inflateSync(r0) \ + _swi(ZLib_InflateSync, _IN(0) | _RETURN(0), r0) +#define inflateReset(r0) \ + _swi(ZLib_InflateReset, _IN(0) | _RETURN(0), r0) +#define gzopen(r0,r1) \ + _swi(ZLib_GZOpen, _INR(0,1) | _RETURN(0), r0) +#define gzdopen(r0,r1) BUG() +#define gzsetparams(r0,r1,r2) BUG() +#define gzread(r0,r1,r2) \ + _swi(ZLib_GZRead, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define gzwrite(r0,r1,r2) \ + _swi(ZLib_GZWrite, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define gzprintf(r0,r1,...) BUG() +#define gzputs(r0,r1) BUG() +#define gzgets(r0,r1,r2) BUG() +#define gzputc(r0,r1) BUG() +#define gzgetc(r0) BUG() +#define gzflush(r0,r1) \ + _swi(ZLib_GZFlush, _INR(0,1) | _RETURN(0), r0,r1) +#define gzclose(r0) \ + _swi(ZLib_GZClose, _IN(0) | _RETURN(0), r0) +#define gzerror(r0,r1) \ + _swi(ZLib_GZError, _IN(0) | _RETURN(0)|_OUT(1), r0, &r1) +#define gzseek(r0,r1,r2) \ + _swi(ZLib_GZSeek, _INR(0,2) | _RETURN(0), r0,r1,r2) +#define gzrewind(r0) BUG() +#define gztell(r0) \ + _swi(ZLib_GZTell, _IN(0) | _RETURN(0), r0) +#define gzeof(r0) \ + _swi(ZLib_GZEOF, _IN(0) | _RETURN(0), r0) + +#endif /* G10_ZLIB_RISCOS_H */ diff --git a/po/de.po b/po/de.po new file mode 100644 index 000000000..d11d8d9bc --- /dev/null +++ b/po/de.po @@ -0,0 +1,5254 @@ +# GnuPG german translation +# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +# Walter Koch <koch@hsp.de>, 1998, 1999, 2000, 2001 +msgid "" +msgstr "" +"Project-Id-Version: gnupg-1.0.7\n" +"POT-Creation-Date: 2002-11-11 19:56+0100\n" +"PO-Revision-Date: 2002-09-11 15:40+0200\n" +"Last-Translator: Walter Koch <koch@hsp.de>\n" +"Language-Team: German <de@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: util/secmem.c:90 +msgid "WARNING: using insecure memory!\n" +msgstr "WARNUNG: Sensible Daten knnten auf Platte ausgelagert werden.\n" + +#: util/secmem.c:91 +msgid "please see http://www.gnupg.org/faq.html for more information\n" +msgstr "siehe http://www.gnupg.org/de/faq.html fr weitere Informationen\n" + +# " Um dies zu vermeiden, kann das Programm suid(root) installiert werden.\n" +# " Bitte wenden Sie sich hierzu an den Systemadministrator.\n" +#: util/secmem.c:328 +msgid "operation is not possible without initialized secure memory\n" +msgstr "Vorgang ist ohne sicheren Hauptspeicher nicht mglich\n" + +#: util/secmem.c:329 +msgid "(you may have used the wrong program for this task)\n" +msgstr "" +"(mglicherweise haben Sie das falsche Programm fr diese Aufgabe benutzt)\n" + +#: util/miscutil.c:296 util/miscutil.c:331 +msgid "yes" +msgstr "ja" + +#: util/miscutil.c:297 util/miscutil.c:334 +msgid "yY" +msgstr "jJyY" + +#: util/miscutil.c:298 util/miscutil.c:332 +msgid "no" +msgstr "nein" + +#: util/miscutil.c:299 util/miscutil.c:335 +msgid "nN" +msgstr "nN" + +#: g10/keyedit.c:1032 util/miscutil.c:333 +msgid "quit" +msgstr "quit" + +#: util/miscutil.c:336 +msgid "qQ" +msgstr "qQ" + +#: util/errors.c:54 +msgid "general error" +msgstr "Allgemeiner Fehler" + +#: util/errors.c:55 +msgid "unknown packet type" +msgstr "Unbekannter Pakettyp" + +#: util/errors.c:56 +msgid "unknown version" +msgstr "Unbekannte Version" + +#: util/errors.c:57 +msgid "unknown pubkey algorithm" +msgstr "Unbekanntes Public-Key-Verfahren" + +#: util/errors.c:58 +msgid "unknown digest algorithm" +msgstr "Unbekanntes Hashverfahren" + +#: util/errors.c:59 +msgid "bad public key" +msgstr "Falscher ffentlicher Schssel" + +#: util/errors.c:60 +msgid "bad secret key" +msgstr "Falscher geheimer Schlssel" + +#: util/errors.c:61 +msgid "bad signature" +msgstr "Falsche Unterschrift" + +#: util/errors.c:62 +msgid "checksum error" +msgstr "Prfsummen-Fehler" + +#: util/errors.c:63 +msgid "bad passphrase" +msgstr "Falsches Mantra" + +#: util/errors.c:64 +msgid "public key not found" +msgstr "ffentlicher Schlssel nicht gefunden" + +#: util/errors.c:65 +msgid "unknown cipher algorithm" +msgstr "Unbekanntes Verschlsselungsverfahren" + +#: util/errors.c:66 +msgid "can't open the keyring" +msgstr "Der Schlsselbund kann nicht geffnet werden" + +#: util/errors.c:67 +msgid "invalid packet" +msgstr "Ungltiges Paket" + +#: util/errors.c:68 +msgid "invalid armor" +msgstr "Ungltige ASCII-Hlle" + +#: util/errors.c:69 +msgid "no such user id" +msgstr "Keine solche User-ID" + +#: util/errors.c:70 +msgid "secret key not available" +msgstr "Geheimer Schlssel ist nicht vorhanden" + +#: util/errors.c:71 +msgid "wrong secret key used" +msgstr "Falscher geheimer Schlssel benutzt" + +#: util/errors.c:72 +msgid "not supported" +msgstr "Wird nicht untersttzt" + +#: util/errors.c:73 +msgid "bad key" +msgstr "Falscher Schlssel" + +#: util/errors.c:74 +msgid "file read error" +msgstr "Dateilesefehler" + +#: util/errors.c:75 +msgid "file write error" +msgstr "Dateischreibfehler" + +#: util/errors.c:76 +msgid "unknown compress algorithm" +msgstr "Unbekanntes Komprimierverfahren" + +#: util/errors.c:77 +msgid "file open error" +msgstr "Fehler beim ffnen der Datei" + +#: util/errors.c:78 +msgid "file create error" +msgstr "Fehler beim Erzeugen der Datei" + +#: util/errors.c:79 +msgid "invalid passphrase" +msgstr "Ungltiges Mantra" + +#: util/errors.c:80 +msgid "unimplemented pubkey algorithm" +msgstr "nicht implementiertes ffentliches Schlsselverfahren" + +#: util/errors.c:81 +msgid "unimplemented cipher algorithm" +msgstr "Verschlsselungsverfahren ist nicht implementiert" + +#: util/errors.c:82 +msgid "unknown signature class" +msgstr "Unbekannte Unterschriftenklasse" + +#: util/errors.c:83 +msgid "trust database error" +msgstr "Fehler in der Trust-DB" + +#: util/errors.c:84 +msgid "bad MPI" +msgstr "Falsche MPI" + +#: util/errors.c:85 +msgid "resource limit" +msgstr "festdefinierte Ressourcenobergrenze erreicht" + +#: util/errors.c:86 +msgid "invalid keyring" +msgstr "Ungltiger Schlsselbund" + +#: util/errors.c:87 +msgid "bad certificate" +msgstr "Falsches Zertifikat" + +#: util/errors.c:88 +msgid "malformed user id" +msgstr "Ungnstig aufgebaute User-ID" + +#: util/errors.c:89 +msgid "file close error" +msgstr "Fehler beim Schlieen der Datei" + +#: util/errors.c:90 +msgid "file rename error" +msgstr "Fehler beim Umbenennen einer Datei" + +#: util/errors.c:91 +msgid "file delete error" +msgstr "Fehler beim Lschen einer Datei" + +#: util/errors.c:92 +msgid "unexpected data" +msgstr "Unerwartete Daten" + +#: util/errors.c:93 +msgid "timestamp conflict" +msgstr "Zeitangaben differieren" + +#: util/errors.c:94 +msgid "unusable pubkey algorithm" +msgstr "Unbenutzbares ffentliches Schlsselverfahren" + +#: util/errors.c:95 +msgid "file exists" +msgstr "Datei existiert bereits" + +#: util/errors.c:96 +msgid "weak key" +msgstr "Unsicherer Schlssel" + +#: util/errors.c:97 +msgid "invalid argument" +msgstr "Ungltiges Argument" + +#: util/errors.c:98 +msgid "bad URI" +msgstr "fehlerhafter URI" + +#: util/errors.c:99 +msgid "unsupported URI" +msgstr "Nicht untersttzter URI" + +#: util/errors.c:100 +msgid "network error" +msgstr "Netzwerkfehler" + +#: util/errors.c:102 +msgid "not encrypted" +msgstr "nicht verschlsselt" + +#: util/errors.c:103 +msgid "not processed" +msgstr "nicht bearbeitet" + +#. the key cannot be used for a specific usage +#: util/errors.c:105 +msgid "unusable public key" +msgstr "unbrauchbarer ffentlicher Schssel" + +#: util/errors.c:106 +msgid "unusable secret key" +msgstr "unbrauchbarer geheimer Schlssel" + +#: util/errors.c:107 +msgid "keyserver error" +msgstr "Schlsselserverfehler" + +#: util/logger.c:183 +msgid "ERROR: " +msgstr "" + +#: util/logger.c:186 +msgid "WARNING: " +msgstr "" + +#: util/logger.c:279 +#, c-format +msgid "... this is a bug (%s:%d:%s)\n" +msgstr "... dies ist ein Bug (Programmfehler) (%s:%d:%s)\n" + +#: util/logger.c:285 +#, c-format +msgid "you found a bug ... (%s:%d)\n" +msgstr "Sie haben eine Bug (Programmfehler) gefunden ... (%s:%d)\n" + +#: cipher/random.c:157 +msgid "no entropy gathering module detected\n" +msgstr "Kein Modul zum sammeln von Entropie vorhanden\n" + +#: cipher/random.c:381 g10/import.c:200 g10/keygen.c:1820 +#, c-format +msgid "can't open `%s': %s\n" +msgstr "'%s' kann nicht geffnet werden: %s\n" + +#: cipher/random.c:385 +#, c-format +msgid "can't stat `%s': %s\n" +msgstr "Status von '%s' ist nicht feststellbar: %s\n" + +#: cipher/random.c:390 +#, c-format +msgid "`%s' is not a regular file - ignored\n" +msgstr "'%s' ist keine normale Datei - sie bleibt unbeachtet\n" + +#: cipher/random.c:395 +msgid "note: random_seed file is empty\n" +msgstr "Hinweis: 'random_seed'-Datei ist leer\n" + +#: cipher/random.c:401 +msgid "WARNING: invalid size of random_seed file - not used\n" +msgstr "" +"WARNUNG: Falsche Gre der 'random_seed'-Datei - sie wird nicht verwendet\n" + +#: cipher/random.c:409 +#, c-format +msgid "can't read `%s': %s\n" +msgstr "'%s' ist unlesbar: %s\n" + +#: cipher/random.c:447 +msgid "note: random_seed file not updated\n" +msgstr "Hinweis: 'random_seed'-Datei bleibt unverndert\n" + +#: cipher/random.c:467 +#, c-format +msgid "can't create `%s': %s\n" +msgstr "'%s' kann nicht erzeugt werden: %s\n" + +#: cipher/random.c:474 +#, c-format +msgid "can't write `%s': %s\n" +msgstr "kann '%s' nicht schreiben: %s\n" + +#: cipher/random.c:477 +#, c-format +msgid "can't close `%s': %s\n" +msgstr "kann '%s' nicht schliessen: %s\n" + +#: cipher/random.c:723 +msgid "WARNING: using insecure random number generator!!\n" +msgstr "WARNUNG: Der Zufallsgenerator erzeugt keine echten Zufallszahlen!\n" + +#: cipher/random.c:724 +msgid "" +"The random number generator is only a kludge to let\n" +"it run - it is in no way a strong RNG!\n" +"\n" +"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" +"\n" +msgstr "" +"Der Zufallsgenerator (RNG) ist lediglich ein \"kludge\", damit das\n" +"Programms berhaupt luft - es ist KEINESFALLS ein starker RNG!\n" +"\n" +"BENUTZEN SIE DIE DURCH DIESES PROGRAMM ERZEUGTEN DATEN NICHT!\n" +"\n" + +#: cipher/rndlinux.c:134 +#, c-format +msgid "" +"\n" +"Not enough random bytes available. Please do some other work to give\n" +"the OS a chance to collect more entropy! (Need %d more bytes)\n" +msgstr "" +"\n" +"Es sind nicht gengend Zufallswerte vorhanden. Bitte fhren Sie andere\n" +"Arbeiten durch, damit das Betriebssystem weitere Entropie sammeln kann!\n" +"(Es werden noch %d Byte bentigt.)\n" + +#: g10/g10.c:316 +msgid "" +"@Commands:\n" +" " +msgstr "" +"@Befehle:\n" +" " + +#: g10/g10.c:318 +msgid "|[file]|make a signature" +msgstr "|[Datei]|Eine Unterschrift erzeugen" + +#: g10/g10.c:319 +msgid "|[file]|make a clear text signature" +msgstr "|[Datei]|Eine Klartextunterschrift erzeugen" + +#: g10/g10.c:320 +msgid "make a detached signature" +msgstr "Eine abgetrennte Unterschrift erzeugen" + +#: g10/g10.c:321 +msgid "encrypt data" +msgstr "Daten verschlsseln" + +#: g10/g10.c:322 +msgid "|[files]|encrypt files" +msgstr "|[Dateien]|Dateien verschlsseln" + +#: g10/g10.c:323 +msgid "encryption only with symmetric cipher" +msgstr "Daten symmetrisch verschlsseln" + +#: g10/g10.c:324 +msgid "store only" +msgstr "Nur speichern" + +#: g10/g10.c:325 +msgid "decrypt data (default)" +msgstr "Daten entschlsseln (Voreinstellung)" + +#: g10/g10.c:326 +msgid "|[files]|decrypt files" +msgstr "|[Dateien]|Dateien entschlsseln" + +#: g10/g10.c:327 +msgid "verify a signature" +msgstr "Signatur prfen" + +#: g10/g10.c:329 +msgid "list keys" +msgstr "Liste der Schlssel" + +#: g10/g10.c:331 +msgid "list keys and signatures" +msgstr "Liste der Schlssel und ihrer Signaturen" + +#: g10/g10.c:332 +msgid "check key signatures" +msgstr "Signaturen der Schlssel prfen" + +#: g10/g10.c:333 +msgid "list keys and fingerprints" +msgstr "Liste der Schlssel und ihrer \"Fingerabdrcke\"" + +#: g10/g10.c:334 +msgid "list secret keys" +msgstr "Liste der geheimen Schlssel" + +#: g10/g10.c:335 +msgid "generate a new key pair" +msgstr "Ein neues Schlsselpaar erzeugen" + +#: g10/g10.c:336 +msgid "remove keys from the public keyring" +msgstr "Schlssel aus dem ff. Schlsselbund entfernen" + +#: g10/g10.c:338 +msgid "remove keys from the secret keyring" +msgstr "Schlssel aus dem geh. Schlsselbund entfernen" + +#: g10/g10.c:339 +msgid "sign a key" +msgstr "Schlssel signieren" + +#: g10/g10.c:340 +msgid "sign a key locally" +msgstr "Schlssel nur fr diesen Rechner signieren" + +#: g10/g10.c:341 +msgid "sign a key non-revocably" +msgstr "Schlssel nicht widerrufbar signieren" + +#: g10/g10.c:342 +msgid "sign a key locally and non-revocably" +msgstr "Schlssel nur fr diesen Rechner und nicht-widerrufbar signieren" + +#: g10/g10.c:343 +msgid "sign or edit a key" +msgstr "Unterschreiben oder bearbeiten eines Schl." + +#: g10/g10.c:344 +msgid "generate a revocation certificate" +msgstr "Ein Schlsselwiderruf-Zertifikat erzeugen" + +#: g10/g10.c:346 +msgid "export keys" +msgstr "Schlssel exportieren" + +#: g10/g10.c:347 +msgid "export keys to a key server" +msgstr "Schlssel zu einem Schl.server exportieren" + +#: g10/g10.c:348 +msgid "import keys from a key server" +msgstr "Schlssel von einem Schl.server importieren" + +#: g10/g10.c:350 +msgid "search for keys on a key server" +msgstr "Schlssel auf einem Schl.server suchen" + +#: g10/g10.c:352 +msgid "update all keys from a keyserver" +msgstr "alle Schlssel per Schl.server aktualisieren" + +#: g10/g10.c:356 +msgid "import/merge keys" +msgstr "Schlssel importieren/kombinieren" + +#: g10/g10.c:358 +msgid "list only the sequence of packets" +msgstr "Lediglich Struktur der Datenpakete anzeigen" + +#: g10/g10.c:360 +msgid "export the ownertrust values" +msgstr "Exportieren der \"Owner trust\"-Werte" + +#: g10/g10.c:362 +msgid "import ownertrust values" +msgstr "Importieren der \"Owner trust\"-Werte" + +#: g10/g10.c:364 +msgid "update the trust database" +msgstr "ndern der \"Trust\"-Datenbank" + +#: g10/g10.c:366 +msgid "unattended trust database update" +msgstr "unbeaufsichtigtes ndern der \"Trust\"-Datenbank" + +#: g10/g10.c:367 +msgid "fix a corrupted trust database" +msgstr "Reparieren einer beschdigten \"Trust\"-Datenb." + +#: g10/g10.c:368 +msgid "De-Armor a file or stdin" +msgstr "Datei oder stdin von der ASCII-Hlle befreien" + +#: g10/g10.c:370 +msgid "En-Armor a file or stdin" +msgstr "Datei oder stdin in eine ASCII-Hlle einpacken" + +#: g10/g10.c:372 +msgid "|algo [files]|print message digests" +msgstr "|algo [Dateien]|Message-Digests fr die Dateien ausgeben" + +#: g10/g10.c:376 +msgid "" +"@\n" +"Options:\n" +" " +msgstr "" +"@\n" +"Optionen:\n" +" " + +#: g10/g10.c:378 +msgid "create ascii armored output" +msgstr "Ausgabe mit ASCII-Hlle versehen" + +#: g10/g10.c:380 +msgid "|NAME|encrypt for NAME" +msgstr "|NAME|Verschlsseln fr NAME" + +#: g10/g10.c:384 +msgid "|NAME|use NAME as default recipient" +msgstr "|NAME|NAME als voreingestellten Empfnger benutzen" + +#: g10/g10.c:386 +msgid "use the default key as default recipient" +msgstr "" +"Den Standardschlssel als voreingestellten\n" +"Empfnger benutzen" + +#: g10/g10.c:393 +msgid "use this user-id to sign or decrypt" +msgstr "Mit dieser User-ID signieren" + +#: g10/g10.c:394 +msgid "|N|set compress level N (0 disables)" +msgstr "Kompressionsstufe auf N setzen (0=keine)" + +#: g10/g10.c:396 +msgid "use canonical text mode" +msgstr "Textmodus benutzen" + +#: g10/g10.c:403 +msgid "use as output file" +msgstr "Als Ausgabedatei benutzen" + +#: g10/g10.c:404 +msgid "verbose" +msgstr "Detaillierte Informationen" + +#: g10/g10.c:405 +msgid "be somewhat more quiet" +msgstr "Etwas weniger Infos" + +#: g10/g10.c:406 +msgid "don't use the terminal at all" +msgstr "das Terminal gar nicht benutzen" + +#: g10/g10.c:407 +msgid "force v3 signatures" +msgstr "v3 Signaturen erzwingen" + +#: g10/g10.c:408 +msgid "do not force v3 signatures" +msgstr "v3 Signaturen nicht erzwingen" + +#: g10/g10.c:409 +msgid "force v4 key signatures" +msgstr "v4 Signaturen erzwingen" + +#: g10/g10.c:410 +msgid "do not force v4 key signatures" +msgstr "v4 Signaturen nicht erzwingen" + +#: g10/g10.c:411 +msgid "always use a MDC for encryption" +msgstr "Beim Verschlsseln ein Siegel (MDC) verwenden" + +#: g10/g10.c:413 +msgid "never use a MDC for encryption" +msgstr "Beim Verschlsseln niemals ein Siegel (MDC) verwenden" + +#: g10/g10.c:415 +msgid "do not make any changes" +msgstr "Keine wirklichen nderungen durchfhren" + +#: g10/g10.c:416 +msgid "prompt before overwriting" +msgstr "vor berschreiben nachfragen" + +#: g10/g10.c:417 +msgid "use the gpg-agent" +msgstr "den GPG-Agent verwenden" + +#: g10/g10.c:420 +msgid "batch mode: never ask" +msgstr "Stapelmodus: Keine Abfragen" + +#: g10/g10.c:421 +msgid "assume yes on most questions" +msgstr "\"Ja\" als Standardantwort annehmen" + +#: g10/g10.c:422 +msgid "assume no on most questions" +msgstr "\"Nein\" als Standardantwort annehmen" + +#: g10/g10.c:423 +msgid "add this keyring to the list of keyrings" +msgstr "Als ffentlichen Schlsselbund mitbenutzen" + +#: g10/g10.c:425 +msgid "add this secret keyring to the list" +msgstr "Als geheimen Schlsselbund mitbenutzen" + +#: g10/g10.c:426 +msgid "show which keyring a listed key is on" +msgstr "Anzeigen des Schlsselbundes, in dem ein Schlssel drin ist" + +#: g10/g10.c:427 +msgid "|NAME|use NAME as default secret key" +msgstr "|NAME|NAME als voreingestellten Schlssel benutzen" + +#: g10/g10.c:428 +msgid "|HOST|use this keyserver to lookup keys" +msgstr "|HOST|Schlssel bei diesem Server nachschlagen" + +#: g10/g10.c:432 +msgid "|NAME|set terminal charset to NAME" +msgstr "|NAME|Terminalzeichensatz NAME benutzen" + +#: g10/g10.c:433 +msgid "read options from file" +msgstr "Optionen aus der Datei lesen" + +#: g10/g10.c:437 +msgid "|FD|write status info to this FD" +msgstr "|FD|Statusinfo auf FD (Dateihandle) ausgeben" + +#: g10/g10.c:439 +msgid "|[file]|write status info to file" +msgstr "|[Datei]|Statusinfo in Datei schreiben" + +#: g10/g10.c:451 +msgid "|KEYID|ultimately trust this key" +msgstr "|KEYID|diesem Schlssel uneingeschrnkt vertrauen" + +#: g10/g10.c:452 +msgid "|FILE|load extension module FILE" +msgstr "|DATEI|Erweiterungsmodul DATEI laden" + +#: g10/g10.c:453 +msgid "emulate the mode described in RFC1991" +msgstr "Den in RFC1991 beschriebenen Modus nachahmen" + +#: g10/g10.c:454 +msgid "set all packet, cipher and digest options to OpenPGP behavior" +msgstr "" +"alle Paket-, Verschlsselungs- und\n" +"Hashoptionen auf OpenPGP-Verhalten einstellen" + +#: g10/g10.c:455 +msgid "set all packet, cipher and digest options to PGP 2.x behavior" +msgstr "" +"alle Paket-, Verschlsselungs- und\n" +"Hashoptionen auf PGP 2.X-Verhalten einstellen" + +#: g10/g10.c:461 +msgid "|N|use passphrase mode N" +msgstr "|N|Verwenden des Mantra-Modus N" + +#: g10/g10.c:463 +msgid "|NAME|use message digest algorithm NAME for passphrases" +msgstr "|NAME|Hashverfahren NAME fr Mantras benutzen" + +#: g10/g10.c:465 +msgid "|NAME|use cipher algorithm NAME for passphrases" +msgstr "|NAME|Verschl.verfahren NAME fr Mantras benutzen" + +#: g10/g10.c:467 +msgid "|NAME|use cipher algorithm NAME" +msgstr "|NAME|Verschl.verfahren NAME benutzen" + +#: g10/g10.c:468 +msgid "|NAME|use message digest algorithm NAME" +msgstr "|NAME|Hashverfahren NAME benutzen" + +#: g10/g10.c:470 +msgid "|N|use compress algorithm N" +msgstr "|N|Komprimierverfahren N benutzen" + +#: g10/g10.c:471 +msgid "throw keyid field of encrypted packets" +msgstr "Empfnger-ID verschlsselter Pakete entfernen" + +#: g10/g10.c:473 +msgid "Show Photo IDs" +msgstr "Foto-IDs anzeigen" + +#: g10/g10.c:474 +msgid "Don't show Photo IDs" +msgstr "Foto-IDs nicht anzeigen" + +#: g10/g10.c:475 +msgid "Set command line to view Photo IDs" +msgstr "Kommandozeilentext fr den Foto-Betrachter setzen" + +#: g10/g10.c:481 +msgid "" +"@\n" +"(See the man page for a complete listing of all commands and options)\n" +msgstr "" +"@\n" +"(Auf der \"man\"-Seite ist eine vollstndige Liste aller Kommandos und " +"Optionen)\n" + +#: g10/g10.c:484 +msgid "" +"@\n" +"Examples:\n" +"\n" +" -se -r Bob [file] sign and encrypt for user Bob\n" +" --clearsign [file] make a clear text signature\n" +" --detach-sign [file] make a detached signature\n" +" --list-keys [names] show keys\n" +" --fingerprint [names] show fingerprints\n" +msgstr "" +"@\n" +"Beispiele:\n" +"\n" +" -se -r Bob [Datei] Signieren und verschlsseln fr Benutzer Bob\n" +" --clearsign [Datei] Eine Klartextsignatur erzeugen\n" +" --detach-sign [Datei] Eine abgetrennte Signatur erzeugen\n" +" --list-keys [Namen] Schlssel anzeigen\n" +" --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\n" + +#: g10/g10.c:640 +msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n" +msgstr "" +"Berichte ber Programmfehler bitte in englisch an <gnupg-bugs@gnu.org>.\n" +"Sinn- oder Schreibfehler in den deutschen Texten bitte an <de@li.org>.\n" + +#: g10/g10.c:644 +msgid "Usage: gpg [options] [files] (-h for help)" +msgstr "Aufruf: gpg [Optionen] [Dateien] (-h fr Hilfe)" + +#: g10/g10.c:647 +msgid "" +"Syntax: gpg [options] [files]\n" +"sign, check, encrypt or decrypt\n" +"default operation depends on the input data\n" +msgstr "" +"Aufruf: gpg [Optionen] [Dateien]\n" +"Signieren, prfen, verschlsseln, entschlsseln.\n" +"Die voreingestellte Operation ist abhngig von den Eingabedaten.\n" + +#: g10/g10.c:658 +msgid "" +"\n" +"Supported algorithms:\n" +msgstr "" +"\n" +"Untersttzte Verfahren:\n" + +#: g10/g10.c:762 +msgid "usage: gpg [options] " +msgstr "Aufruf: gpg [Optionen] " + +#: g10/g10.c:830 +msgid "conflicting commands\n" +msgstr "Widersprchliche Befehle\n" + +#: g10/g10.c:848 +#, c-format +msgid "no = sign found in group definition \"%s\"\n" +msgstr "Kein '='-Zeichen in der Gruppendefinition \"%s\"\n" + +#: g10/g10.c:1008 +#, fuzzy, c-format +msgid "WARNING: unsafe ownership on homedir \"%s\"\n" +msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" + +#: g10/g10.c:1011 +#, fuzzy, c-format +msgid "WARNING: unsafe ownership on configuration file \"%s\"\n" +msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" + +#: g10/g10.c:1014 +#, fuzzy, c-format +msgid "WARNING: unsafe ownership on extension \"%s\"\n" +msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" + +#: g10/g10.c:1020 +#, fuzzy, c-format +msgid "WARNING: unsafe permissions on homedir \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" + +#: g10/g10.c:1023 +#, fuzzy, c-format +msgid "WARNING: unsafe permissions on configuration file \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" + +#: g10/g10.c:1026 +#, fuzzy, c-format +msgid "WARNING: unsafe permissions on extension \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" + +#: g10/g10.c:1032 +#, fuzzy, c-format +msgid "WARNING: unsafe enclosing directory ownership on homedir \"%s\"\n" +msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" + +#: g10/g10.c:1035 +#, fuzzy, c-format +msgid "" +"WARNING: unsafe enclosing directory ownership on configuration file \"%s\"\n" +msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" + +#: g10/g10.c:1038 +#, fuzzy, c-format +msgid "WARNING: unsafe enclosing directory ownership on extension \"%s\"\n" +msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" + +#: g10/g10.c:1044 +#, fuzzy, c-format +msgid "WARNING: unsafe enclosing directory permissions on homedir \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" + +#: g10/g10.c:1047 +#, fuzzy, c-format +msgid "" +"WARNING: unsafe enclosing directory permissions on configuration file \"%s" +"\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" + +#: g10/g10.c:1050 +#, fuzzy, c-format +msgid "WARNING: unsafe enclosing directory permissions on extension \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" + +#: g10/g10.c:1236 +#, c-format +msgid "NOTE: old default options file `%s' ignored\n" +msgstr "Hinweis: Alte voreingestellte Optionendatei '%s' wurde ignoriert\n" + +#: g10/g10.c:1272 +#, c-format +msgid "NOTE: no default option file `%s'\n" +msgstr "Hinweis: Keine voreingestellte Optionendatei '%s' vorhanden\n" + +#: g10/g10.c:1276 +#, c-format +msgid "option file `%s': %s\n" +msgstr "Optionendatei '%s': %s\n" + +#: g10/g10.c:1283 +#, c-format +msgid "reading options from `%s'\n" +msgstr "Optionen werden aus '%s' gelesen\n" + +#: g10/g10.c:1472 g10/g10.c:1805 g10/g10.c:1816 +#, c-format +msgid "NOTE: %s is not for normal use!\n" +msgstr "Hinweis: %s ist nicht fr den blichen Gebrauch gedacht!\n" + +#: g10/g10.c:1484 +#, c-format +msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" +msgstr "" +"Verschlsselungserweiterung \"%s\" wurde wegen falscher Rechte nicht " +"geladen\n" + +#: g10/g10.c:1627 +#, c-format +msgid "%s is not a valid character set\n" +msgstr "%s ist kein gltiger Zeichensatz.\n" + +#: g10/g10.c:1645 +msgid "could not parse keyserver URI\n" +msgstr "Schlsselserver-URI konnte nicht zerlegt werden\n" + +#: g10/g10.c:1654 +#, c-format +msgid "%s:%d: invalid import options\n" +msgstr "%s:%d: ungltige Import Option.\n" + +#: g10/g10.c:1657 +msgid "invalid import options\n" +msgstr "Ungltige Import Option\n" + +#: g10/g10.c:1664 +#, c-format +msgid "%s:%d: invalid export options\n" +msgstr "%s:%d: ungltige Export Option.\n" + +#: g10/g10.c:1667 +msgid "invalid export options\n" +msgstr "Ungltige export Option\n" + +#: g10/g10.c:1673 +#, c-format +msgid "unable to set exec-path to %s\n" +msgstr "Der Ausfhrungspfad konnte nicht auf %s gesetzt werden.\n" + +#: g10/g10.c:1794 +msgid "WARNING: program may create a core file!\n" +msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" + +#: g10/g10.c:1798 +#, c-format +msgid "WARNING: %s overrides %s\n" +msgstr "WARNUNG: %s ersetzt %s\n" + +#: g10/g10.c:1807 g10/g10.c:1826 +#, c-format +msgid "%s not allowed with %s!\n" +msgstr "%s kann nicht zusammen mit %s verwendet werden!\n" + +#: g10/g10.c:1810 +#, c-format +msgid "%s makes no sense with %s!\n" +msgstr "%s zusammen mit %s ist nicht sinnvoll!\n" + +#: g10/g10.c:1836 +msgid "you can only make detached or clear signatures while in --pgp2 mode\n" +msgstr "" +"Im --pgp2-Modus knnen Sie nur abgetrennte oder Klartextunterschriften " +"machen\n" + +#: g10/g10.c:1842 +msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" +msgstr "" +"Im --pgp2-Modus knnen Sie nicht gleichzeitig unterschreiben und " +"verschlsseln\n" + +#: g10/g10.c:1848 +msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" +msgstr "" +"Im --pgp2-Modus mssen Sie Dateien benutzen und knnen keine Pipes " +"verwenden.\n" + +#: g10/g10.c:1861 +msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" +msgstr "" +"Verschlssen einer Botschaft bentigt im --pgp2-Modus die IDEA-" +"Verschlsselung\n" + +#: g10/encode.c:409 g10/encode.c:459 g10/encode.c:710 g10/g10.c:1886 +#: g10/pkclist.c:821 g10/pkclist.c:859 g10/sign.c:647 g10/sign.c:879 +#, c-format +msgid "this message may not be usable by %s\n" +msgstr "Diese Botschaft knnte fr %s unbrauchbar sein\n" + +#: g10/g10.c:1934 g10/g10.c:1952 +msgid "selected cipher algorithm is invalid\n" +msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" + +#: g10/g10.c:1940 g10/g10.c:1958 +msgid "selected digest algorithm is invalid\n" +msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" + +#: g10/g10.c:1946 +msgid "selected certification digest algorithm is invalid\n" +msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" + +#: g10/g10.c:1961 +#, c-format +msgid "compress algorithm must be in range %d..%d\n" +msgstr "Das Komprimierverfahren mu im Bereich %d bis %d liegen\n" + +#: g10/g10.c:1963 +msgid "completes-needed must be greater than 0\n" +msgstr "completes-needed mssen grer als 0 sein\n" + +#: g10/g10.c:1965 +msgid "marginals-needed must be greater than 1\n" +msgstr "marginals-needed mssen grer als 1 sein\n" + +#: g10/g10.c:1967 +msgid "max-cert-depth must be in range 1 to 255\n" +msgstr "max-cert-depth mu im Bereich 1 bis 255 liegen\n" + +#: g10/g10.c:1970 +msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" +msgstr "Hinweis: Vom \"simple S2K\"-Modus (0) ist strikt abzuraten\n" + +#: g10/g10.c:1974 +msgid "invalid S2K mode; must be 0, 1 or 3\n" +msgstr "ungltiger \"simple S2K\"-Modus; Wert mu 0, 1 oder 3 sein\n" + +#: g10/g10.c:1978 +msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" +msgstr "ungltiger \"default-check-level\"; Wert mu 0, 1, 2 oder 3 sein\n" + +#: g10/g10.c:1984 +msgid "invalid default preferences\n" +msgstr "ungltige Standard Voreinstellungen\n" + +#: g10/g10.c:1992 +msgid "invalid personal cipher preferences\n" +msgstr "ungltige private Verschlsselungsvoreinstellungen\n" + +#: g10/g10.c:1996 +msgid "invalid personal digest preferences\n" +msgstr "ungltige private Hashvoreinstellungen\n" + +#: g10/g10.c:2000 +msgid "invalid personal compress preferences\n" +msgstr "ungltige private Komprimierungsvoreinstellungen\n" + +#: g10/g10.c:2093 +#, c-format +msgid "failed to initialize the TrustDB: %s\n" +msgstr "Die Trust-DB kann nicht initialisiert werden: %s\n" + +#: g10/g10.c:2103 +msgid "WARNING: recipients (-r) given without using public key encryption\n" +msgstr "" +"WARNUNG: Empfnger (-r) angegeben ohne Verwendung von Public-Key-Verfahren\n" + +#: g10/g10.c:2113 +msgid "--store [filename]" +msgstr "--store [Dateiname]" + +#: g10/g10.c:2120 +msgid "--symmetric [filename]" +msgstr "--symmetric [Dateiname]" + +#: g10/g10.c:2128 +msgid "--encrypt [filename]" +msgstr "--encrypt [Dateiname]" + +#: g10/g10.c:2145 +msgid "--sign [filename]" +msgstr "--sign [Dateiname]" + +#: g10/g10.c:2158 +msgid "--sign --encrypt [filename]" +msgstr "--sign --encrypt [Dateiname]" + +#: g10/g10.c:2172 +msgid "--sign --symmetric [filename]" +msgstr "--sign --symmetric [Dateiname]" + +#: g10/g10.c:2181 +msgid "--clearsign [filename]" +msgstr "--clearsign [Dateiname]" + +#: g10/g10.c:2199 +msgid "--decrypt [filename]" +msgstr "--decrypt [Dateiname]" + +#: g10/g10.c:2210 +msgid "--sign-key user-id" +msgstr "--sign-key User-ID" + +#: g10/g10.c:2218 +msgid "--lsign-key user-id" +msgstr "--lsign-key User-ID" + +#: g10/g10.c:2226 +msgid "--nrsign-key user-id" +msgstr "--nrsign-key User-ID" + +#: g10/g10.c:2234 +msgid "--nrlsign-key user-id" +msgstr "--nrlsign-key User-ID" + +#: g10/g10.c:2242 +msgid "--edit-key user-id [commands]" +msgstr "--edit-key User-ID [Befehle]" + +#: g10/encode.c:417 g10/g10.c:2298 g10/sign.c:790 +#, c-format +msgid "can't open %s: %s\n" +msgstr "'%s' kann nicht geffnet werden: %s\n" + +#: g10/g10.c:2313 +msgid "-k[v][v][v][c] [user-id] [keyring]" +msgstr "-k[v][v][v][c] [User-ID] [Schlsselbund]" + +#: g10/g10.c:2405 +#, c-format +msgid "dearmoring failed: %s\n" +msgstr "Entfernen der ASCII-Hlle ist fehlgeschlagen: %s\n" + +#: g10/g10.c:2413 +#, c-format +msgid "enarmoring failed: %s\n" +msgstr "Anbringen der ASCII-Hlle ist fehlgeschlagen: %s\n" + +#: g10/g10.c:2500 +#, c-format +msgid "invalid hash algorithm `%s'\n" +msgstr "Ungltiges Hashverfahren '%s'\n" + +#: g10/g10.c:2586 +msgid "[filename]" +msgstr "[Dateiname]" + +#: g10/g10.c:2590 +msgid "Go ahead and type your message ...\n" +msgstr "Auf geht's - Botschaft eintippen ...\n" + +#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2593 g10/verify.c:94 +#: g10/verify.c:139 +#, c-format +msgid "can't open `%s'\n" +msgstr "'%s' kann nicht geffnet werden\n" + +#: g10/g10.c:2807 +msgid "" +"a notation name must have only printable characters or spaces, and end with " +"an '='\n" +msgstr "" +"Ein \"notation\"-Name darf nur Buchstaben, Zahlen, Punkte oder Unterstriche " +"enthalten und mu mit einem '=' enden\n" + +#: g10/g10.c:2816 +msgid "a notation value must not use any control characters\n" +msgstr "Ein \"notation\"-Wert darf keine Kontrollzeichen verwenden\n" + +#: g10/g10.c:2853 +msgid "the given certification policy URL is invalid\n" +msgstr "Die angegebene Zertifikat-Richtlinien-URL ist ungltig\n" + +#: g10/g10.c:2855 +msgid "the given signature policy URL is invalid\n" +msgstr "Die angegebene Unterschriften-Richtlinien-URL ist ungltig\n" + +#: g10/armor.c:314 +#, c-format +msgid "armor: %s\n" +msgstr "ASCII-Hlle: %s\n" + +#: g10/armor.c:343 +msgid "invalid armor header: " +msgstr "Ungltige ASCII-Hlle" + +#: g10/armor.c:350 +msgid "armor header: " +msgstr "ASCII-Hlle: " + +#: g10/armor.c:361 +msgid "invalid clearsig header\n" +msgstr "Ungltige Klartextsignatur-Einleitung\n" + +#: g10/armor.c:413 +msgid "nested clear text signatures\n" +msgstr "verschachtelte Klartextunterschriften\n" + +#: g10/armor.c:537 +msgid "invalid dash escaped line: " +msgstr "Ungltige mit Bindestrich \"escapte\" Zeile: " + +#: g10/armor.c:549 +msgid "unexpected armor:" +msgstr "Unerwartete ASCII-Hlle:" + +#: g10/armor.c:675 g10/armor.c:1242 +#, c-format +msgid "invalid radix64 character %02x skipped\n" +msgstr "Ungltiges \"radix64\" Zeichen %02x ignoriert\n" + +#: g10/armor.c:718 +msgid "premature eof (no CRC)\n" +msgstr "vorzeitiges Dateiende (keine Prfsumme)\n" + +#: g10/armor.c:752 +msgid "premature eof (in CRC)\n" +msgstr "vorzeitiges Dateiende (innerhalb der Prfsumme)\n" + +#: g10/armor.c:756 +msgid "malformed CRC\n" +msgstr "Falsch aufgebaute Prfsumme\n" + +#: g10/armor.c:760 g10/armor.c:1279 +#, c-format +msgid "CRC error; %06lx - %06lx\n" +msgstr "Prfsummenfehler; %06lx - %06lx\n" + +#: g10/armor.c:780 +msgid "premature eof (in Trailer)\n" +msgstr "vorzeitiges Dateiende (im Nachsatz)\n" + +#: g10/armor.c:784 +msgid "error in trailer line\n" +msgstr "Fehler in der Nachsatzzeile\n" + +#: g10/armor.c:1057 +msgid "no valid OpenPGP data found.\n" +msgstr "Keine gltigen OpenPGP-Daten gefunden.\n" + +#: g10/armor.c:1062 +#, c-format +msgid "invalid armor: line longer than %d characters\n" +msgstr "ungltige ASCII-Hlle: Zeile ist lnger als %d Zeichen\n" + +#: g10/armor.c:1066 +msgid "" +"quoted printable character in armor - probably a buggy MTA has been used\n" +msgstr "" +"\"quoted printable\" Zeichen in der ASCII-Hlle gefunden - mglicherweise\n" +" war ein fehlerhafter E-Mail-Transporter(\"MTA\") die Ursache\n" + +#: g10/pkclist.c:62 +msgid "No reason specified" +msgstr "Kein Grund angegeben" + +#: g10/pkclist.c:64 +msgid "Key is superseded" +msgstr "Schlssel ist berholt" + +#: g10/pkclist.c:66 +msgid "Key has been compromised" +msgstr "Hinweis: Dieser Schlssel ist nicht mehr sicher" + +#: g10/pkclist.c:68 +msgid "Key is no longer used" +msgstr "Schlssel wird nicht mehr benutzt" + +#: g10/pkclist.c:70 +msgid "User ID is no longer valid" +msgstr "User-ID ist nicht mehr gltig" + +#: g10/pkclist.c:74 +msgid "reason for revocation: " +msgstr "Grund fr Widerruf: " + +#: g10/pkclist.c:91 +msgid "revocation comment: " +msgstr "Widerruf-Bemerkung: " + +#. a string with valid answers +#: g10/pkclist.c:264 +msgid "iImMqQsS" +msgstr "iImMqQsS" + +#: g10/pkclist.c:272 +#, c-format +msgid "" +"No trust value assigned to:\n" +"%4u%c/%08lX %s \"" +msgstr "" +"Es ist kein \"trust value\" zugewiesen fr:\n" +"%4u%c/%08lX %s \"" + +#: g10/mainproc.c:1428 g10/pkclist.c:300 +msgid " aka \"" +msgstr " alias \"" + +#: g10/keyedit.c:297 g10/pkclist.c:311 +msgid "" +"Please decide how far you trust this user to correctly\n" +"verify other users' keys (by looking at passports,\n" +"checking fingerprints from different sources...)?\n" +"\n" +msgstr "" +"Bitte entscheiden Sie, in wieweit Sie diesem User zutrauen,\n" +"Schlssel anderer User korrekt zu prfen (durch Vergleich\n" +"mit Lichtbildausweisen, Vergleich der Fingerabdrcke aus\n" +"unterschiedlichen Quellen ...)?\n" +"\n" + +#: g10/pkclist.c:315 +#, fuzzy, c-format +msgid " %d = I don't know\n" +msgstr " %d = Wei nicht so recht\n" + +#: g10/pkclist.c:317 +#, c-format +msgid " %d = I do NOT trust\n" +msgstr " %d = Nein, ihm traue ich NICHT\n" + +#: g10/pkclist.c:319 +#, c-format +msgid " %d = I trust marginally\n" +msgstr " %d = Ich vertraue ihm einigermaen\n" + +#: g10/pkclist.c:321 +#, c-format +msgid " %d = I trust fully\n" +msgstr " %d = Ich vertraue ihm vollstndig\n" + +#: g10/pkclist.c:323 +#, c-format +msgid " %d = I trust ultimately\n" +msgstr " %d = Ich vertraue ihm absolut\n" + +#. not yet implemented +#: g10/pkclist.c:326 +msgid " i = please show me more information\n" +msgstr " i = Bitte weitere Information anzeigen\n" + +#: g10/pkclist.c:329 +msgid " m = back to the main menu\n" +msgstr " m = Zurck zum Men\n" + +#: g10/pkclist.c:332 +msgid " s = skip this key\n" +msgstr " s = diesen Schlssel berSpringen\n" + +#: g10/pkclist.c:333 +msgid " q = quit\n" +msgstr " q = verlassen\n" + +#: g10/pkclist.c:337 +#, c-format +msgid "" +"The minimum trust level for this key is: %s\n" +"\n" +msgstr "" + +#: g10/pkclist.c:343 +msgid "Your decision? " +msgstr "Ihre Auswahl? " + +#: g10/pkclist.c:364 +msgid "Do you really want to set this key to ultimate trust? " +msgstr "Mchten Sie diesem Schlssel wirklich uneingeschrnkt vertrauen? " + +#: g10/pkclist.c:378 +msgid "Certificates leading to an ultimately trusted key:\n" +msgstr "Zertifikate fhren zu einem letztlich vertrauenswrdigen Schlssel:\n" + +#: g10/pkclist.c:453 +#, c-format +msgid "key %08lX: key has been revoked!\n" +msgstr "Schlssel %08lX: Schlssel wurde widerrufen\n" + +#: g10/pkclist.c:460 g10/pkclist.c:472 g10/pkclist.c:566 +msgid "Use this key anyway? " +msgstr "Diesen Schlssel trotzdem benutzen? " + +#: g10/pkclist.c:465 +#, c-format +msgid "key %08lX: subkey has been revoked!\n" +msgstr "Schlssel %08lX: Unterschlssel wurde widerrufen\n" + +#: g10/pkclist.c:486 +#, c-format +msgid "%08lX: key has expired\n" +msgstr "%08lX: Schlssel ist verfallen!\n" + +#: g10/pkclist.c:496 +#, c-format +msgid "" +"%08lX: There is no indication that this key really belongs to the owner\n" +msgstr "" +"%08lX: Es gibt keinen Hinweis, da die Signatur wirklich dem vorgeblichen " +"Besitzer gehrt.\n" + +#: g10/pkclist.c:502 +#, c-format +msgid "%08lX: We do NOT trust this key\n" +msgstr "%08lX: Wir haben KEIN Vertrauen zu diesem Schlssel!\n" + +#: g10/pkclist.c:508 +#, c-format +msgid "" +"%08lX: It is not sure that this key really belongs to the owner\n" +"but it is accepted anyway\n" +msgstr "" +"%08lX: Es ist nicht sicher, da dieser Schlssel wirklich dem vorgeblichen\n" +"Besitzer gehrt, aber er wird trotzdem akzeptiert\n" + +#: g10/pkclist.c:514 +msgid "This key probably belongs to the owner\n" +msgstr "" +"Dieser Schlssel gehrt hchstwahrscheinlich dem angegebenen Besitzer\n" + +#: g10/pkclist.c:519 +msgid "This key belongs to us\n" +msgstr "" +"Dieser Schlssel gehrt uns (da wir nmlich den geheimen Schlssel dazu " +"haben)\n" + +#: g10/pkclist.c:561 +msgid "" +"It is NOT certain that the key belongs to the person named\n" +"in the user ID. If you *really* know what you are doing,\n" +"you may answer the next question with yes\n" +"\n" +msgstr "" +"Es ist NICHT sicher, da der Schlssel dem vorgeblichen Besitzer gehrt.\n" +"Wenn Sie *wirklich* wissen, was Sie tun, knnen Sie die nchste\n" +"Frage mit ja beantworten\n" + +#: g10/pkclist.c:575 g10/pkclist.c:597 +msgid "WARNING: Using untrusted key!\n" +msgstr "WARNUNG: Ein Schlssel ohne gesichertes Vertrauen wird benutzt!\n" + +#: g10/pkclist.c:616 +msgid "WARNING: This key has been revoked by its owner!\n" +msgstr "WARNUNG: Dieser Schlssel wurde von seinem Besitzer widerrufen!\n" + +#: g10/pkclist.c:617 +msgid " This could mean that the signature is forgery.\n" +msgstr " Das knnte bedeuten, da die Signatur geflscht ist.\n" + +#: g10/pkclist.c:623 +msgid "WARNING: This subkey has been revoked by its owner!\n" +msgstr "WARNUNG: Dieser Unterschlssel wurde von seinem Besitzer widerrufen!\n" + +#: g10/pkclist.c:628 +msgid "Note: This key has been disabled.\n" +msgstr "Hinweis: Dieser Schlssel wurde abgeschaltet.\n" + +#: g10/pkclist.c:633 +msgid "Note: This key has expired!\n" +msgstr "Hinweis: Dieser Schlssel ist verfallen!\n" + +#: g10/pkclist.c:644 +msgid "WARNING: This key is not certified with a trusted signature!\n" +msgstr "WARNUNG: Dieser Schlssel trgt keine vertrauenswrdige Signatur!\n" + +#: g10/pkclist.c:646 +msgid "" +" There is no indication that the signature belongs to the owner.\n" +msgstr "" +" Es gibt keinen Hinweis, da die Signatur wirklich dem vorgeblichen " +"Besitzer gehrt.\n" + +#: g10/pkclist.c:654 +msgid "WARNING: We do NOT trust this key!\n" +msgstr "WARNUNG: Wir haben KEIN Vertrauen zu diesem Schlssel!\n" + +#: g10/pkclist.c:655 +msgid " The signature is probably a FORGERY.\n" +msgstr " Die Signatur ist wahrscheinlich eine FLSCHUNG.\n" + +#: g10/pkclist.c:663 +msgid "" +"WARNING: This key is not certified with sufficiently trusted signatures!\n" +msgstr "" +"WARNUNG: Dieser Schlssel ist nicht durch hinreichend vertrauenswrdige " +"Signaturen zertifiziert!\n" + +#: g10/pkclist.c:665 +msgid " It is not certain that the signature belongs to the owner.\n" +msgstr "" +" Es ist nicht sicher, da die Signatur wirklich dem vorgeblichen " +"Besitzer gehrt.\n" + +#: g10/encode.c:706 g10/pkclist.c:817 g10/pkclist.c:855 +#, c-format +msgid "you may not use %s while in %s mode\n" +msgstr "Die Benutzung von %s ist im %s-Modus nicht erlaubt.\n" + +#: g10/pkclist.c:832 g10/pkclist.c:868 g10/pkclist.c:1020 g10/pkclist.c:1080 +#, c-format +msgid "%s: skipped: %s\n" +msgstr "%s: bersprungen: %s\n" + +#: g10/pkclist.c:842 g10/pkclist.c:1052 +#, c-format +msgid "%s: skipped: public key already present\n" +msgstr "%s: bersprungen: ffentlicher Schlssel bereits vorhanden\n" + +#: g10/pkclist.c:885 +msgid "You did not specify a user ID. (you may use \"-r\")\n" +msgstr "" +"Sie haben keine User-ID angegeben (Sie knnen die Option \"-r\" verwenden).\n" + +#: g10/pkclist.c:898 +msgid "" +"\n" +"Enter the user ID. End with an empty line: " +msgstr "" +"\n" +"Geben Sie die User-ID ein. Beenden mit einer leeren Zeile: " + +#: g10/pkclist.c:914 +msgid "No such user ID.\n" +msgstr "Keine solche User-ID vorhanden.\n" + +#: g10/pkclist.c:919 g10/pkclist.c:995 +msgid "skipped: public key already set as default recipient\n" +msgstr "" +"bersprungen: ffentlicher Schlssel bereits als Standardempfnger gesetzt\n" + +#: g10/pkclist.c:937 +msgid "Public key is disabled.\n" +msgstr "ffentlicher Schlssel ist abgeschaltet.\n" + +#: g10/pkclist.c:944 +msgid "skipped: public key already set\n" +msgstr "bersprungen: ffentlicher Schlssel bereits gesetzt\n" + +#: g10/pkclist.c:987 +#, c-format +msgid "unknown default recipient `%s'\n" +msgstr "Unbekannter voreingestellter Empfnger '%s'\n" + +#: g10/pkclist.c:1032 +#, c-format +msgid "%s: skipped: public key is disabled\n" +msgstr "%s: bersprungen: ffentlicher Schlssel ist abgeschaltet\n" + +#: g10/pkclist.c:1087 +msgid "no valid addressees\n" +msgstr "Keine gltigen Adressaten\n" + +#: g10/keygen.c:184 +#, fuzzy, c-format +msgid "preference `%s' duplicated\n" +msgstr "Voreinstellung %c%lu ist doppelt\n" + +#: g10/keygen.c:191 +#, fuzzy +msgid "too many cipher preferences\n" +msgstr "zu viele `%c' Voreinstellungen\n" + +#: g10/keygen.c:193 +#, fuzzy +msgid "too many digest preferences\n" +msgstr "zu viele `%c' Voreinstellungen\n" + +#: g10/keygen.c:195 +#, fuzzy +msgid "too many compression preferences\n" +msgstr "zu viele `%c' Voreinstellungen\n" + +#: g10/keygen.c:265 +#, fuzzy, c-format +msgid "invalid item `%s' in preference string\n" +msgstr "Ungltiges Zeichen in den Voreinstellungen\n" + +#: g10/keygen.c:535 +msgid "writing direct signature\n" +msgstr "Die \"Direct Key Signature\" wird geschrieben\n" + +#: g10/keygen.c:574 +msgid "writing self signature\n" +msgstr "Die Eigenbeglaubigung wird geschrieben\n" + +#: g10/keygen.c:618 +msgid "writing key binding signature\n" +msgstr "Schreiben der \"key-binding\" Signatur\n" + +#: g10/keygen.c:672 g10/keygen.c:756 g10/keygen.c:847 +#, c-format +msgid "keysize invalid; using %u bits\n" +msgstr "Ungltig Schlssellnge; %u Bit werden verwendet\n" + +#: g10/keygen.c:677 g10/keygen.c:761 g10/keygen.c:852 +#, c-format +msgid "keysize rounded up to %u bits\n" +msgstr "Schlssellnge auf %u Bit aufgerundet\n" + +#: g10/keygen.c:952 +msgid "Please select what kind of key you want:\n" +msgstr "Bitte whlen Sie, welche Art von Schlssel Sie mchten:\n" + +#: g10/keygen.c:954 +#, c-format +msgid " (%d) DSA and ElGamal (default)\n" +msgstr " (%d) DSA und ElGamal (voreingestellt)\n" + +#: g10/keygen.c:955 +#, c-format +msgid " (%d) DSA (sign only)\n" +msgstr " (%d) DSA (nur signieren/beglaubigen)\n" + +#: g10/keygen.c:957 +#, c-format +msgid " (%d) ElGamal (encrypt only)\n" +msgstr " (%d) ElGamal (nur verschlsseln)\n" + +#: g10/keygen.c:959 +#, c-format +msgid " (%d) ElGamal (sign and encrypt)\n" +msgstr " (%d) ElGamal (signieren/beglaubigen und verschlsseln)\n" + +#: g10/keygen.c:960 +#, c-format +msgid " (%d) RSA (sign only)\n" +msgstr " (%d) RSA (nur signieren/beglaubigen)\n" + +#: g10/keygen.c:962 +#, c-format +msgid " (%d) RSA (encrypt only)\n" +msgstr " (%d) RSA (nur verschlsseln)\n" + +#: g10/keygen.c:964 +#, c-format +msgid " (%d) RSA (sign and encrypt)\n" +msgstr " (%d) RSA (signieren/beglaubigen und verschlsseln)\n" + +#: g10/keyedit.c:306 g10/keyedit.c:327 g10/keyedit.c:343 g10/keyedit.c:700 +#: g10/keygen.c:967 +msgid "Your selection? " +msgstr "Ihre Auswahl? " + +#: g10/keygen.c:977 g10/keygen.c:995 +msgid "The use of this algorithm is deprecated - create anyway? " +msgstr "" +"Von der Benutzung dieses Verfahrens ist abzuraten - Trotzdem erzeugen? " + +#: g10/keyedit.c:713 g10/keygen.c:1009 +msgid "Invalid selection.\n" +msgstr "Ungltige Auswahl.\n" + +#: g10/keygen.c:1022 +#, c-format +msgid "" +"About to generate a new %s keypair.\n" +" minimum keysize is 768 bits\n" +" default keysize is 1024 bits\n" +" highest suggested keysize is 2048 bits\n" +msgstr "" +"Es wird ein neues %s Schlsselpaar erzeugt.\n" +" kleinste Schlssellnge ist 768 Bit\n" +" standard Schlssellnge ist 1024 Bit\n" +" grte sinnvolle Schlssellnge ist 2048 Bit\n" + +#: g10/keygen.c:1031 +msgid "What keysize do you want? (1024) " +msgstr "Welche Schlssellnge wnschen Sie? (1024) " + +#: g10/keygen.c:1036 +msgid "DSA only allows keysizes from 512 to 1024\n" +msgstr "DSA erlaubt nur Schlssellngen von 512 bis 1024\n" + +#: g10/keygen.c:1038 +msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" +msgstr "zu kurz; 1024 ist die kleinste fr RSA mgliche Schlssellnge.\n" + +#: g10/keygen.c:1041 +msgid "keysize too small; 768 is smallest value allowed.\n" +msgstr "zu kurz; 768 ist die kleinste mgliche Schlssellnge.\n" + +#. It is ridiculous and an annoyance to use larger key sizes! +#. * GnuPG can handle much larger sizes; but it takes an eternity +#. * to create such a key (but less than the time the Sirius +#. * Computer Corporation needs to process one of the usual +#. * complaints) and {de,en}cryption although needs some time. +#. * So, before you complain about this limitation, I suggest that +#. * you start a discussion with Marvin about this theme and then +#. * do whatever you want. +#: g10/keygen.c:1052 +#, c-format +msgid "keysize too large; %d is largest value allowed.\n" +msgstr "Schsselgre zu hoch; %d ist der Maximalwert.\n" + +#: g10/keygen.c:1057 +msgid "" +"Keysizes larger than 2048 are not suggested because\n" +"computations take REALLY long!\n" +msgstr "" +"Schlssellngen grer als 2048 werden nicht empfohlen, da die\n" +"Berechnungen dann WIRKLICH lange brauchen!\n" + +#: g10/keygen.c:1060 +msgid "Are you sure that you want this keysize? " +msgstr "Sind Sie sicher, da Sie diese Schlssellnge wnschen? " + +#: g10/keygen.c:1061 +msgid "" +"Okay, but keep in mind that your monitor and keyboard radiation is also very " +"vulnerable to attacks!\n" +msgstr "" +"Gut, aber bitte denken Sie auch daran, da Monitor und Tastatur Daten " +"abstrahlen und diese leicht mitgelesen werden knnen.\n" + +#: g10/keygen.c:1070 +#, c-format +msgid "Requested keysize is %u bits\n" +msgstr "Die verlangte Schlssellnge betrgt %u Bit\n" + +#: g10/keygen.c:1073 g10/keygen.c:1077 +#, c-format +msgid "rounded up to %u bits\n" +msgstr "aufgerundet auf %u Bit\n" + +#: g10/keygen.c:1128 +msgid "" +"Please specify how long the key should be valid.\n" +" 0 = key does not expire\n" +" <n> = key expires in n days\n" +" <n>w = key expires in n weeks\n" +" <n>m = key expires in n months\n" +" <n>y = key expires in n years\n" +msgstr "" +"Bitte whlen Sie, wie lange der Schlssel gltig bleiben soll.\n" +" 0 = Schlssel verfllt nie\n" +" <n> = Schlssel verfllt nach n Tagen\n" +" <n>w = Schlssel verfllt nach n Wochen\n" +" <n>m = Schlssel verfllt nach n Monaten\n" +" <n>y = Schlssel verfllt nach n Jahren\n" + +#: g10/keygen.c:1137 +msgid "" +"Please specify how long the signature should be valid.\n" +" 0 = signature does not expire\n" +" <n> = signature expires in n days\n" +" <n>w = signature expires in n weeks\n" +" <n>m = signature expires in n months\n" +" <n>y = signature expires in n years\n" +msgstr "" +"Bitte whlen Sie, wie lange die Beglaubigung gltig bleiben soll.\n" +" 0 = Schlssel verfllt nie\n" +" <n> = Schlssel verfllt nach n Tagen\n" +" <n>w = Schlssel verfllt nach n Wochen\n" +" <n>m = Schlssel verfllt nach n Monaten\n" +" <n>y = Schlssel verfllt nach n Jahren\n" + +#: g10/keygen.c:1159 +msgid "Key is valid for? (0) " +msgstr "Wie lange bleibt der Schlssel gltig? (0) " + +#: g10/keygen.c:1161 +msgid "Signature is valid for? (0) " +msgstr "Wie lange bleibt die Beglaubigung gltig? (0) " + +#: g10/keygen.c:1166 +msgid "invalid value\n" +msgstr "Ungltiger Wert.\n" + +#: g10/keygen.c:1171 +#, c-format +msgid "%s does not expire at all\n" +msgstr "%s verfllt nie.\n" + +#. print the date when the key expires +#: g10/keygen.c:1178 +#, c-format +msgid "%s expires at %s\n" +msgstr "%s verfllt am %s\n" + +#: g10/keygen.c:1184 +msgid "" +"Your system can't display dates beyond 2038.\n" +"However, it will be correctly handled up to 2106.\n" +msgstr "" +"Ihr Rechner kann Daten jenseits des Jahres 2038 nicht anzeigen.\n" +"Trotzdem werden Daten bis 2106 korrekt verarbeitet.\n" + +#: g10/keygen.c:1189 +msgid "Is this correct (y/n)? " +msgstr "Ist dies richtig? (j/n) " + +#: g10/keygen.c:1232 +msgid "" +"\n" +"You need a User-ID to identify your key; the software constructs the user " +"id\n" +"from Real Name, Comment and Email Address in this form:\n" +" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n" +"\n" +msgstr "" +"\n" +"Sie bentigen eine User-ID, um Ihren Schlssel eindeutig zu machen; das\n" +"Programm baut diese User-ID aus Ihrem echten Namen, einem Kommentar und\n" +"Ihrer E-Mail-Adresse in dieser Form auf:\n" +" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n" +"\n" + +#: g10/keygen.c:1244 +msgid "Real name: " +msgstr "Ihr Name (\"Vorname Nachname\"): " + +#: g10/keygen.c:1252 +msgid "Invalid character in name\n" +msgstr "Ungltiges Zeichen im Namen\n" + +#: g10/keygen.c:1254 +msgid "Name may not start with a digit\n" +msgstr "Der Name darf nicht mit einer Ziffer beginnen.\n" + +#: g10/keygen.c:1256 +msgid "Name must be at least 5 characters long\n" +msgstr "Der Name mu min. 5 Zeichen lang sein.\n" + +#: g10/keygen.c:1264 +msgid "Email address: " +msgstr "E-Mail-Adresse: " + +#: g10/keygen.c:1275 +msgid "Not a valid email address\n" +msgstr "Diese E-Mail-Adresse ist ungltig\n" + +#: g10/keygen.c:1283 +msgid "Comment: " +msgstr "Kommentar: " + +#: g10/keygen.c:1289 +msgid "Invalid character in comment\n" +msgstr "Ungltiges Zeichen im Kommentar.\n" + +#: g10/keygen.c:1312 +#, c-format +msgid "You are using the `%s' character set.\n" +msgstr "Sie benutzen den Zeichensatz `%s'\n" + +#: g10/keygen.c:1318 +#, c-format +msgid "" +"You selected this USER-ID:\n" +" \"%s\"\n" +"\n" +msgstr "" +"Sie haben diese User-ID gewhlt:\n" +" \"%s\"\n" +"\n" + +#: g10/keygen.c:1322 +msgid "Please don't put the email address into the real name or the comment\n" +msgstr "Bitte keine E-Mailadressen als Namen oder Kommentar verwenden\n" + +#: g10/keygen.c:1327 +msgid "NnCcEeOoQq" +msgstr "NnKkEeFfBb" + +#: g10/keygen.c:1337 +msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " +msgstr "ndern: (N)ame, (K)ommentar, (E)-Mail oder (B)eenden? " + +#: g10/keygen.c:1338 +msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " +msgstr "ndern: (N)ame, (K)ommentar, (E)-Mail oder (F)ertig/(B)eenden? " + +#: g10/keygen.c:1357 +msgid "Please correct the error first\n" +msgstr "Bitte beseitigen Sie zuerst den Fehler\n" + +#: g10/keygen.c:1396 +msgid "" +"You need a Passphrase to protect your secret key.\n" +"\n" +msgstr "" +"Sie bentigen ein Mantra, um den geheimen Schlssel zu schtzen.\n" +"\n" + +#: g10/keyedit.c:918 g10/keygen.c:1404 +msgid "passphrase not correctly repeated; try again" +msgstr "Mantra wurde nicht richtig wiederholt; noch einmal versuchen" + +#: g10/keygen.c:1405 +#, c-format +msgid "%s.\n" +msgstr "%s.\n" + +#: g10/keygen.c:1411 +msgid "" +"You don't want a passphrase - this is probably a *bad* idea!\n" +"I will do it anyway. You can change your passphrase at any time,\n" +"using this program with the option \"--edit-key\".\n" +"\n" +msgstr "" +"Sie mchten kein Mantra - Dies ist *nicht* zu empfehlen!\n" +"Es ist trotzdem mglich. Sie knnen Ihr Mantra jederzeit\n" +"ndern, indem sie dieses Programm mit dem Befehl \"--edit-key\"\n" +"aufrufen.\n" +"\n" + +#: g10/keygen.c:1432 +msgid "" +"We need to generate a lot of random bytes. It is a good idea to perform\n" +"some other action (type on the keyboard, move the mouse, utilize the\n" +"disks) during the prime generation; this gives the random number\n" +"generator a better chance to gain enough entropy.\n" +msgstr "" +"Wir mssen eine ganze Menge Zufallswerte erzeugen. Sie knnen dies\n" +"untersttzen, indem Sie z.B. in einem anderen Fenster/Konsole irgendetwas\n" +"tippen, die Maus verwenden oder irgendwelche anderen Programme benutzen.\n" + +#: g10/keygen.c:1996 +msgid "DSA keypair will have 1024 bits.\n" +msgstr "Das DSA-Schlsselpaar wird 1024 Bit haben.\n" + +#: g10/keygen.c:2050 +msgid "Key generation canceled.\n" +msgstr "Schlsselerzeugung abgebrochen.\n" + +#: g10/keygen.c:2157 g10/keygen.c:2245 +#, c-format +msgid "writing public key to `%s'\n" +msgstr "schreiben des ffentlichen Schlssels nach '%s'\n" + +#: g10/keygen.c:2158 g10/keygen.c:2247 +#, c-format +msgid "writing secret key to `%s'\n" +msgstr "schreiben des geheimen Schlssels nach '%s'\n" + +#: g10/keygen.c:2234 +#, c-format +msgid "no writable public keyring found: %s\n" +msgstr "kein schreibbarer ffentlicher Schlsselbund gefunden: %s\n" + +#: g10/keygen.c:2240 +#, c-format +msgid "no writable secret keyring found: %s\n" +msgstr "kein schreibbarer geheimer Schlsselbund gefunden: %s\n" + +#: g10/keygen.c:2254 +#, c-format +msgid "error writing public keyring `%s': %s\n" +msgstr "Fehler beim Schreiben des ff. Schlsselbundes `%s': %s\n" + +#: g10/keygen.c:2261 +#, c-format +msgid "error writing secret keyring `%s': %s\n" +msgstr "Fehler beim Schreiben des geheimen Schlsselbundes `%s': %s\n" + +#: g10/keygen.c:2281 +msgid "public and secret key created and signed.\n" +msgstr "ffentlichen und geheimen Schlssel erzeugt und signiert.\n" + +#: g10/keygen.c:2282 +msgid "key marked as ultimately trusted.\n" +msgstr "Schlssel ist als uneingeschrnkt vertrauenswrdig gekennzeichnet.\n" + +#: g10/keygen.c:2293 +msgid "" +"Note that this key cannot be used for encryption. You may want to use\n" +"the command \"--edit-key\" to generate a secondary key for this purpose.\n" +msgstr "" +"Bitte beachten Sie, da dieser Schlssel nicht zum Verschlsseln benutzt\n" +"werden kann. Sie knnen aber mit dem Befehl \"--edit-key\" einen\n" +"Zweitschlssel fr diesem Zweck erzeugen.\n" + +#: g10/keygen.c:2305 g10/keygen.c:2415 +#, c-format +msgid "Key generation failed: %s\n" +msgstr "Schlsselerzeugung fehlgeschlagen: %s\n" + +#: g10/keygen.c:2351 g10/sign.c:257 +#, c-format +msgid "" +"key has been created %lu second in future (time warp or clock problem)\n" +msgstr "" +"Der Schlssel wurde %lu Sekunde in der Zukunft erzeugt (Zeitreise oder Uhren " +"stimmen nicht berein)\n" + +#: g10/keygen.c:2353 g10/sign.c:259 +#, c-format +msgid "" +"key has been created %lu seconds in future (time warp or clock problem)\n" +msgstr "" +"Der Schlssel wurde %lu Sekunden in der Zukunft erzeugt (Zeitreise oder " +"Uhren stimmen nicht berein)\n" + +#: g10/keygen.c:2362 +msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" +msgstr "HINWEIS: Unterschlssel fr v3-Schlssen sind nicht OpenPGP-konform\n" + +#: g10/keygen.c:2391 +msgid "Really create? " +msgstr "Wirklich erzeugen? " + +#: g10/decrypt.c:92 g10/encode.c:765 +msgid "--output doesn't work for this command\n" +msgstr "--output funktioniert nicht bei diesem Kommando\n" + +#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 +#: g10/tdbio.c:557 +#, c-format +msgid "%s: can't open: %s\n" +msgstr "%s: kann nicht geffnet werden: %s\n" + +#: g10/encode.c:205 g10/sign.c:1036 +#, c-format +msgid "error creating passphrase: %s\n" +msgstr "Fehler beim Erzeugen des Mantras: %s\n" + +#: g10/encode.c:210 +msgid "can't use a symmetric ESK packet due to the S2K mode\n" +msgstr "" +"Aufgrund des S2K-Modus kann ein symmetrisches ESK Packet nicht benutzt " +"werden\n" + +#: g10/encode.c:229 g10/encode.c:487 +#, c-format +msgid "`%s' already compressed\n" +msgstr "`%s' ist bereits komprimiert\n" + +#: g10/encode.c:296 g10/encode.c:523 +#, c-format +msgid "%s: WARNING: empty file\n" +msgstr "%s: WARNUNG: Leere Datei\n" + +#: g10/encode.c:407 +msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" +msgstr "" +"Im --pgp2-Modus kann nur fr RSA-Schlssel mit maximal 2048 Bit " +"verschlsselt werden\n" + +#: g10/encode.c:423 +#, c-format +msgid "reading from `%s'\n" +msgstr "Lesen von '%s'\n" + +#: g10/encode.c:457 +msgid "" +"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" +msgstr "" +"Die IDEA-Verschlsselung kann nicht mit allen Zielschlsseln verwendet " +"werden.\n" + +#: g10/encode.c:468 g10/encode.c:647 +#, c-format +msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" +msgstr "" +"Erzwungene Verwendung des symmetrischen Verschlsselungsverfahren %s (%d) " +"verletzt die Empfngervoreinstellungen\n" + +#: g10/encode.c:561 g10/sign.c:759 +#, c-format +msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" +msgstr "" +"Erzwungenes Kompressionsverfahren %s (%d) verletzt die " +"Empfngervoreinstellungen.\n" + +#: g10/encode.c:738 +#, c-format +msgid "%s/%s encrypted for: \"%s\"\n" +msgstr "%s/%s verschlsselt fr: %s\n" + +#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2452 +#, c-format +msgid "key `%s' not found: %s\n" +msgstr "Schlssel `%s' nicht gefunden: %s\n" + +#: g10/delkey.c:81 g10/export.c:213 +#, c-format +msgid "error reading keyblock: %s\n" +msgstr "Fehler beim Lesen des Schlsselblocks: %s\n" + +#: g10/export.c:222 +#, c-format +msgid "key %08lX: not a rfc2440 key - skipped\n" +msgstr "Schlssel %08lX: dies ist kein RFC2440-Schssel - bersprungen\n" + +#: g10/export.c:238 +#, c-format +msgid "key %08lX: not protected - skipped\n" +msgstr "Schlssel %08lX: ungeschtzt - bersprungen\n" + +#: g10/export.c:246 +#, c-format +msgid "key %08lX: PGP 2.x style key - skipped\n" +msgstr "Schlssel %08lX: PGP 2.x-artiger Schlssel - bersprungen\n" + +#: g10/export.c:347 +msgid "WARNING: nothing exported\n" +msgstr "WARNUNG: Nichts exportiert\n" + +#: g10/getkey.c:150 +msgid "too many entries in pk cache - disabled\n" +msgstr "zu viele Eintrge im pk-Cache - abgeschaltet\n" + +#. fixme: returning translatable constants instead of a user ID is +#. * not good because they are probably not utf-8 encoded. +#: g10/getkey.c:186 g10/getkey.c:2461 +msgid "[User id not found]" +msgstr "[User-ID nicht gefunden]" + +#: g10/getkey.c:1494 +#, c-format +msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" +msgstr "" +"Ungltiger Schlssel %08lX, gltig gemacht per --allow-non-selfsigned-uid\n" + +#: g10/getkey.c:2171 +#, c-format +msgid "using secondary key %08lX instead of primary key %08lX\n" +msgstr "" +"der Zweitschlssel %08lX wird anstelle des Hauptschlssels %08lX verwendet\n" + +#: g10/getkey.c:2218 +#, c-format +msgid "key %08lX: secret key without public key - skipped\n" +msgstr "" +"Schlssel %08lX: geheimer Schlssel, aber ohne ffentlichen Schlssel - " +"bersprungen\n" + +#: g10/import.c:270 +#, c-format +msgid "skipping block of type %d\n" +msgstr "berspringe den Block vom Typ %d\n" + +#: g10/import.c:279 +#, fuzzy, c-format +msgid "%lu keys processed so far\n" +msgstr "%lu Schlssel bislang bearbeitet\n" + +#: g10/import.c:284 +#, c-format +msgid "error reading `%s': %s\n" +msgstr "Fehler beim Lesen von `%s': %s\n" + +#: g10/import.c:296 +#, c-format +msgid "Total number processed: %lu\n" +msgstr "Anzahl insgesamt bearbeiteter Schlssel: %lu\n" + +#: g10/import.c:298 +#, c-format +msgid " skipped new keys: %lu\n" +msgstr " ignorierte neue Schlssel: %lu\n" + +#: g10/import.c:301 +#, c-format +msgid " w/o user IDs: %lu\n" +msgstr " ohne User-ID: %lu\n" + +#: g10/import.c:303 +#, c-format +msgid " imported: %lu" +msgstr " importiert: %lu" + +#: g10/import.c:309 +#, c-format +msgid " unchanged: %lu\n" +msgstr " unverndert: %lu\n" + +#: g10/import.c:311 +#, c-format +msgid " new user IDs: %lu\n" +msgstr " neue User-IDs: %lu\n" + +#: g10/import.c:313 +#, c-format +msgid " new subkeys: %lu\n" +msgstr " neue Unterschlssel: %lu\n" + +#: g10/import.c:315 +#, c-format +msgid " new signatures: %lu\n" +msgstr " neue Signaturen: %lu\n" + +#: g10/import.c:317 +#, c-format +msgid " new key revocations: %lu\n" +msgstr " neue Schlsselwiderrufe: %lu\n" + +#: g10/import.c:319 +#, c-format +msgid " secret keys read: %lu\n" +msgstr " gelesene geheime Schlssel: %lu\n" + +#: g10/import.c:321 +#, c-format +msgid " secret keys imported: %lu\n" +msgstr " geheime Schlssel importiert: %lu\n" + +#: g10/import.c:323 +#, c-format +msgid " secret keys unchanged: %lu\n" +msgstr " unvernderte geh.Schl.: %lu\n" + +#: g10/import.c:325 +#, c-format +msgid " not imported: %lu\n" +msgstr " nicht importiert: %lu\n" + +#: g10/import.c:593 g10/import.c:908 +#, c-format +msgid "key %08lX: no user ID\n" +msgstr "Schlssel %08lX: Keine User-ID\n" + +#: g10/import.c:609 +#, c-format +msgid "key %08lX: HKP subkey corruption repaired\n" +msgstr "Schlssel %08lX: HKP Unterschlsseldefekt repariert\n" + +#: g10/import.c:624 +#, c-format +msgid "key %08lX: accepted non self-signed user ID '%s'\n" +msgstr "Schlssel %08lX: Nicht eigenbeglaubigte User-ID `%s' bernommen\n" + +#: g10/import.c:631 +#, c-format +msgid "key %08lX: no valid user IDs\n" +msgstr "Schlssel %08lX: Keine gltigen User-IDs\n" + +#: g10/import.c:633 +msgid "this may be caused by a missing self-signature\n" +msgstr "dies knnte durch fehlende Eigenbeglaubigung verursacht worden sein\n" + +#: g10/import.c:643 g10/import.c:1001 +#, c-format +msgid "key %08lX: public key not found: %s\n" +msgstr "Schlssel %08lX: ffentlicher Schlssel nicht gefunden: %s\n" + +#: g10/import.c:648 +#, c-format +msgid "key %08lX: new key - skipped\n" +msgstr "Schlssel %08lX: neuer Schlssel - bersprungen\n" + +#: g10/import.c:657 +#, c-format +msgid "no writable keyring found: %s\n" +msgstr "kein schreibbarer Schlsselbund gefunden: %s\n" + +#: g10/import.c:662 g10/openfile.c:244 g10/sign.c:671 g10/sign.c:898 +#, c-format +msgid "writing to `%s'\n" +msgstr "Schreiben nach '%s'\n" + +#: g10/import.c:665 g10/import.c:750 g10/import.c:935 g10/import.c:1061 +#, c-format +msgid "error writing keyring `%s': %s\n" +msgstr "Fehler beim Schreiben des Schlsselbundes `%s': %s\n" + +#: g10/import.c:682 +#, c-format +msgid "key %08lX: public key \"%s\" imported\n" +msgstr "Schlssel %08lX: ffentlicher Schlssel \"%s\" importiert\n" + +#: g10/import.c:704 +#, c-format +msgid "key %08lX: doesn't match our copy\n" +msgstr "Schlssel %08lX: Stimmt nicht mit unserer Kopie berein\n" + +#: g10/import.c:721 g10/import.c:1018 +#, c-format +msgid "key %08lX: can't locate original keyblock: %s\n" +msgstr "" +"Schlssel %08lX: der lokale originale Schlsselblocks wurde nicht gefunden: %" +"s\n" + +#: g10/import.c:728 g10/import.c:1024 +#, c-format +msgid "key %08lX: can't read original keyblock: %s\n" +msgstr "" +"Schlssel %08lX: Lesefehler im lokalen originalen Schlsselblocks: %s\n" + +#: g10/import.c:759 +#, c-format +msgid "key %08lX: \"%s\" 1 new user ID\n" +msgstr "Schlssel %08lX: \"%s\" 1 neue User-ID\n" + +#: g10/import.c:762 +#, c-format +msgid "key %08lX: \"%s\" %d new user IDs\n" +msgstr "Schlssel %08lX: \"%s\" %d neue User-IDs\n" + +#: g10/import.c:765 +#, c-format +msgid "key %08lX: \"%s\" 1 new signature\n" +msgstr "Schlssel %08lX: \"%s\" 1 neue Signatur\n" + +#: g10/import.c:768 +#, c-format +msgid "key %08lX: \"%s\" %d new signatures\n" +msgstr "Schlssel %08lX: \"%s\" %d neue Signaturen\n" + +#: g10/import.c:771 +#, c-format +msgid "key %08lX: \"%s\" 1 new subkey\n" +msgstr "Schlssel %08lX: \"%s\" 1 neuer Unterschlssel\n" + +#: g10/import.c:774 +#, c-format +msgid "key %08lX: \"%s\" %d new subkeys\n" +msgstr "Schlssel %08lX: \"%s\" %d neue Unterschlssel\n" + +#: g10/import.c:793 +#, c-format +msgid "key %08lX: \"%s\" not changed\n" +msgstr "Schlssel %08lX: \"%s\" Nicht gendert\n" + +#: g10/import.c:914 +#, fuzzy, c-format +msgid "key %08lX: secret key with invalid cipher %d - skipped\n" +msgstr "" +"Schlssel %08lX: geheimer Schlssel, aber ohne ffentlichen Schlssel - " +"bersprungen\n" + +#: g10/import.c:929 +#, c-format +msgid "no default secret keyring: %s\n" +msgstr "Kein voreingestellter geheimer Schlsselbund: %s\n" + +#: g10/import.c:940 +#, c-format +msgid "key %08lX: secret key imported\n" +msgstr "Schlssel %08lX: Geheimer Schlssel importiert\n" + +#. we can't merge secret keys +#: g10/import.c:956 +#, c-format +msgid "key %08lX: already in secret keyring\n" +msgstr "Schlssel %08lX: Ist bereits im geheimen Schlsselbund\n" + +#: g10/import.c:966 +#, c-format +msgid "key %08lX: secret key not found: %s\n" +msgstr "Schlssel %08lX: geheimer Schlssel nicht gefunden: %s\n" + +#: g10/import.c:995 +#, c-format +msgid "key %08lX: no public key - can't apply revocation certificate\n" +msgstr "" +"Schlssel %08lX: Kein ffentlicher Schlssel - der Schlsselwiderruf kann " +"nicht angebracht werden\n" + +#: g10/import.c:1035 +#, c-format +msgid "key %08lX: invalid revocation certificate: %s - rejected\n" +msgstr "Schlssel %08lX: Ungltiges Widerrufzertifikat: %s - zurckgewiesen\n" + +#: g10/import.c:1067 +#, c-format +msgid "key %08lX: \"%s\" revocation certificate imported\n" +msgstr "Schlssel %08lX: \"%s\" Widerrufzertifikat importiert\n" + +#: g10/import.c:1115 +#, c-format +msgid "key %08lX: no user ID for signature\n" +msgstr "Schlssel %08lX: Keine User-ID fr Signatur\n" + +#: g10/import.c:1128 +#, c-format +msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" +msgstr "" +"Schlssel %08lX: Nicht untersttztes Public-Key-Verfahren fr User-ID \"%s" +"\"\n" + +#: g10/import.c:1130 +#, c-format +msgid "key %08lX: invalid self-signature on user id \"%s\"\n" +msgstr "Schlssel %08lX: Ungltige Eigenbeglaubigung fr User-ID \"%s\"\n" + +#: g10/import.c:1145 +#, fuzzy, c-format +msgid "key %08lX: no subkey for subkey binding signature\n" +msgstr "Schlssel %08lX: Kein Unterschlssel fr die Schlsselanbindung\n" + +#: g10/import.c:1153 g10/import.c:1194 +#, c-format +msgid "key %08lX: unsupported public key algorithm\n" +msgstr "Schlssel %08lX: Nicht untersttztes Public-Key-Verfahren\n" + +#: g10/import.c:1154 +#, c-format +msgid "key %08lX: invalid subkey binding\n" +msgstr "Schlssel %08lX: Ungltige Unterschlssel-Anbindung\n" + +#. Delete the last binding +#. sig since this one is +#. newer +#: g10/import.c:1166 +#, c-format +msgid "key %08lX: removed multiple subkey binding\n" +msgstr "Schlssel %08lX: Ungltige Unterschlssel-Anbindung entfernt\n" + +#: g10/import.c:1186 g10/sig-check.c:550 +#, fuzzy, c-format +msgid "key %08lX: no subkey for subkey revocation signature\n" +msgstr "Schlssel %08lX: Kein Unterschlssel fr den Schlsselwiderruf\n" + +#: g10/import.c:1195 +#, c-format +msgid "key %08lX: invalid subkey revocation\n" +msgstr "Schlssel %08lX: Ungltiger Unterschlsselwiderruf\n" + +#. Delete the last revocation +#. sig since this one is +#. newer +#: g10/import.c:1206 +#, fuzzy, c-format +msgid "key %08lX: removed multiple subkey revocation signatures\n" +msgstr "Schlssel %08lX: Mehrfacher Unterschlssel-Widerruf entfernt\n" + +#: g10/import.c:1243 +#, c-format +msgid "key %08lX: skipped user ID '" +msgstr "Schlssel %08lX: User-ID bergangen '" + +#: g10/import.c:1266 +#, c-format +msgid "key %08lX: skipped subkey\n" +msgstr "Schlssel %08lX: Unterschlssel ignoriert\n" + +#. here we violate the rfc a bit by still allowing +#. * to import non-exportable signature when we have the +#. * the secret key used to create this signature - it +#. * seems that this makes sense +#: g10/import.c:1292 +#, c-format +msgid "key %08lX: non exportable signature (class %02x) - skipped\n" +msgstr "" +"Schlssel %08lX: Nicht exportfhige Unterschrift (Klasse %02x) - bergangen\n" + +#: g10/import.c:1301 +#, c-format +msgid "key %08lX: revocation certificate at wrong place - skipped\n" +msgstr "Schlssel %08lX: Widerrufzertifikat an falschem Platz - bergangen\n" + +#: g10/import.c:1318 +#, c-format +msgid "key %08lX: invalid revocation certificate: %s - skipped\n" +msgstr "Schlssel %08lX: Ungltiges Widerrufzertifikat: %s - bergangen\n" + +#: g10/import.c:1330 +#, c-format +msgid "key %08lX: subkey signature in wrong place - skipped\n" +msgstr "Schlssel %08lX: Widerrufzertifikat an falschem Platz - bergangen\n" + +#: g10/import.c:1428 +#, c-format +msgid "key %08lX: duplicated user ID detected - merged\n" +msgstr "Schlssel %08lX: Doppelte User-ID entdeckt - zusammengefhrt\n" + +#: g10/import.c:1487 +#, c-format +msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" +msgstr "" +"WARNUNG: Schlssel %08lX ist u.U. widerrufen: hole Widerrufschlssel %08lX\n" + +#: g10/import.c:1501 +#, c-format +msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" +msgstr "" +"WARNUNG: Schlssel %08lX ist u.U. widerrufen: Widerrufschlssel %08lX ist " +"nicht vorhanden\n" + +#: g10/import.c:1558 +#, c-format +msgid "key %08lX: \"%s\" revocation certificate added\n" +msgstr "Schlssel %08lX: \"%s\" Widerrufzertifikat hinzugefgt\n" + +#: g10/import.c:1589 +#, c-format +msgid "key %08lX: direct key signature added\n" +msgstr "Schlssel %08lX: \"direct-key\"-Signaturen hinzugefgt\n" + +#: g10/keyedit.c:151 +msgid "[revocation]" +msgstr "[Widerruf]" + +#: g10/keyedit.c:152 +msgid "[self-signature]" +msgstr "[Eigenbeglaubigung]" + +#: g10/keyedit.c:223 g10/keylist.c:190 +msgid "1 bad signature\n" +msgstr "1 falsche Beglaubigung\n" + +#: g10/keyedit.c:225 g10/keylist.c:192 +#, c-format +msgid "%d bad signatures\n" +msgstr "%d falsche Beglaubigungen\n" + +#: g10/keyedit.c:227 g10/keylist.c:194 +msgid "1 signature not checked due to a missing key\n" +msgstr "1 Beglaubigung wegen fehlendem Schlssel nicht geprft\n" + +#: g10/keyedit.c:229 g10/keylist.c:196 +#, c-format +msgid "%d signatures not checked due to missing keys\n" +msgstr "%d Beglaubigungen wegen fehlenden Schlsseln nicht geprft\n" + +#: g10/keyedit.c:231 g10/keylist.c:198 +msgid "1 signature not checked due to an error\n" +msgstr "1 Beglaubigung aufgrund von Fehler nicht geprft\n" + +#: g10/keyedit.c:233 g10/keylist.c:200 +#, c-format +msgid "%d signatures not checked due to errors\n" +msgstr "%d Beglaubigungen aufgrund von Fehlern nicht geprft\n" + +#: g10/keyedit.c:235 +msgid "1 user ID without valid self-signature detected\n" +msgstr "Eine User-ID ohne gltige Eigenbeglaubigung entdeckt\n" + +#: g10/keyedit.c:237 +#, c-format +msgid "%d user IDs without valid self-signatures detected\n" +msgstr "%d User-IDs ohne gltige Eigenbeglaubigung entdeckt\n" + +#: g10/keyedit.c:300 +#, fuzzy, c-format +msgid " (%d) I trust marginally\n" +msgstr " %d = Ich vertraue ihm einigermaen\n" + +#: g10/keyedit.c:301 +#, fuzzy, c-format +msgid " (%d) I trust fully\n" +msgstr " %d = Ich vertraue ihm vollstndig\n" + +#: g10/keyedit.c:320 +msgid "" +"Please enter the depth of this trust signature.\n" +"A depth greater than 1 allows the key you are signing to make\n" +"trust signatures on your behalf.\n" +msgstr "" + +#: g10/keyedit.c:338 +msgid "Please enter a domain to restrict this signature, or enter for none.\n" +msgstr "" + +#: g10/keyedit.c:481 +#, c-format +msgid "User ID \"%s\" is revoked." +msgstr "User-ID \"%s\" ist widerrufen." + +#: g10/keyedit.c:488 g10/keyedit.c:605 g10/keyedit.c:663 g10/keyedit.c:1273 +msgid "Are you sure you still want to sign it? (y/N) " +msgstr "Wollen Sie ihn immmer noch beglaubigen? (j/N) " + +#: g10/keyedit.c:496 g10/keyedit.c:611 g10/keyedit.c:1279 +msgid " Unable to sign.\n" +msgstr " Beglaubigen ist nicht mglich.\n" + +#: g10/keyedit.c:501 +#, c-format +msgid "WARNING: user ID \"%s\" is not self-signed.\n" +msgstr "WARNUNG: User-ID \"%s\" ist nicht eigenbeglaubigt.\n" + +#: g10/keyedit.c:520 +#, c-format +msgid "" +"The self-signature on \"%s\"\n" +"is a PGP 2.x-style signature.\n" +msgstr "" +"Die Eigenbeglaubigung von \"%s\"\n" +"ist eine PGP 2.x artige Signatur.\n" + +#: g10/keyedit.c:529 +msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " +msgstr "Soll sie zu einer OpenPGP Eigenbeglaubigung gendert werden? (j/N) " + +#. It's a local sig, and we want to make a +#. exportable sig. +#: g10/keyedit.c:543 +#, c-format +msgid "" +"Your current signature on \"%s\"\n" +"is a local signature.\n" +msgstr "" +"Die derzeitige Beglaubigung von \"%s\"\n" +"ist nur fr diesen Rechner gltig.\n" + +#: g10/keyedit.c:547 +msgid "Do you want to promote it to a full exportable signature? (y/N) " +msgstr "" +"Soll sie zu einer voll exportierbaren Beglaubigung erhoben werden? (j/N) " + +#: g10/keyedit.c:567 +#, c-format +msgid "\"%s\" was already locally signed by key %08lX\n" +msgstr "\"%s\" wurde bereits durch Schlssel %08lX lokal beglaubigt\n" + +#: g10/keyedit.c:571 +#, c-format +msgid "\"%s\" was already signed by key %08lX\n" +msgstr "\"%s\" wurde bereits durch Schlssel %08lX beglaubigt\n" + +#: g10/keyedit.c:584 +#, c-format +msgid "Nothing to sign with key %08lX\n" +msgstr "Nichts zu beglaubigen fr Schlssel %08lX\n" + +#: g10/keyedit.c:599 +msgid "This key has expired!" +msgstr "Dieser Schlssel ist verfallen!" + +#: g10/keyedit.c:619 +#, c-format +msgid "This key is due to expire on %s.\n" +msgstr "Dieser Schlssel wird %s verfallen.\n" + +#: g10/keyedit.c:623 +msgid "Do you want your signature to expire at the same time? (Y/n) " +msgstr "Soll Ihre Beglaubigung zur selben Zeit verfallen? (J/n) " + +#: g10/keyedit.c:656 +msgid "" +"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " +"mode.\n" +msgstr "" +"Im --pgp2-Modus kann nur mit PGP-2.x-artigen Schlsseln unterschrieben " +"werden\n" + +#: g10/keyedit.c:658 +msgid "This would make the key unusable in PGP 2.x.\n" +msgstr "Dies wrde den Schlssel fr PGP 2.x unbrauchbar machen\n" + +#: g10/keyedit.c:683 +msgid "" +"How carefully have you verified the key you are about to sign actually " +"belongs\n" +"to the person named above? If you don't know what to answer, enter \"0\".\n" +msgstr "" +"Wie genau haben Sie berprft, ob der Schlssel, den Sie jetzt beglaubigen\n" +"wollen, wirklich der o.g. Person gehrt?\n" +"Wenn Sie darauf keine Antwort wissen, geben Sie \"0\" ein.\n" + +#: g10/keyedit.c:688 +#, c-format +msgid " (0) I will not answer.%s\n" +msgstr " (0) Ich antworte nicht.%s\n" + +#: g10/keyedit.c:690 +#, c-format +msgid " (1) I have not checked at all.%s\n" +msgstr " (1) Ich habe es berhaupt nicht berprft.%s\n" + +#: g10/keyedit.c:692 +#, c-format +msgid " (2) I have done casual checking.%s\n" +msgstr " (2) Ich habe es flchtig berprft.%s\n" + +#: g10/keyedit.c:694 +#, c-format +msgid " (3) I have done very careful checking.%s\n" +msgstr " (3) Ich habe es sehr sorgfltig berprft.%s\n" + +#: g10/keyedit.c:723 +msgid "" +"Are you really sure that you want to sign this key\n" +"with your key: \"" +msgstr "" +"Sind Sie wirklich sicher, da Sie vorstehenden Schlssel mit Ihrem\n" +"Schlssel beglaubigen wollen: \"" + +#: g10/keyedit.c:732 +msgid "" +"\n" +"This will be a self-signature.\n" +msgstr "" +"\n" +"Dies wird eine Eigenbeglaubigung sein.\n" + +#: g10/keyedit.c:736 +msgid "" +"\n" +"WARNING: the signature will not be marked as non-exportable.\n" +msgstr "" +"\n" +"WARNUNG: Die Unterschrift wird nicht als nicht-exportierbar markiert " +"werden.\n" + +#: g10/keyedit.c:741 +msgid "" +"\n" +"WARNING: the signature will not be marked as non-revocable.\n" +msgstr "" +"\n" +"Die Unterschrift wird nicht als nicht-widerrufbar markiert werden.\n" + +#: g10/keyedit.c:748 +msgid "" +"\n" +"The signature will be marked as non-exportable.\n" +msgstr "" +"\n" +"Die Unterschrift wird als nicht exportfhig markiert werden.\n" + +#: g10/keyedit.c:752 +msgid "" +"\n" +"The signature will be marked as non-revocable.\n" +msgstr "" +"\n" +"Die Unterschrift wird als nicht exportfhig markiert werden.\n" + +#: g10/keyedit.c:757 +msgid "" +"\n" +"I have not checked this key at all.\n" +msgstr "" +"\n" +"Ich habe diesen Schlssel berhaupt nicht berprft.\n" + +#: g10/keyedit.c:761 +msgid "" +"\n" +"I have checked this key casually.\n" +msgstr "" +"\n" +"Ich habe diesen Schlssel flchtig berprft.\n" + +#: g10/keyedit.c:765 +msgid "" +"\n" +"I have checked this key very carefully.\n" +msgstr "" +"\n" +"Ich habe diesen Schlssel sehr sorgfltig berprft.\n" + +#: g10/keyedit.c:774 +msgid "Really sign? " +msgstr "Wirklich unterschreiben? " + +#: g10/keyedit.c:819 g10/keyedit.c:3263 g10/keyedit.c:3325 g10/sign.c:308 +#, c-format +msgid "signing failed: %s\n" +msgstr "Beglaubigung fehlgeschlagen: %s\n" + +#: g10/keyedit.c:875 +msgid "This key is not protected.\n" +msgstr "Dieser Schlssel ist nicht geschtzt.\n" + +#: g10/keyedit.c:879 +msgid "Secret parts of primary key are not available.\n" +msgstr "Geheime Teile des Haupschlssels sind nicht vorhanden\n" + +#: g10/keyedit.c:883 +msgid "Key is protected.\n" +msgstr "Schlssel ist geschtzt.\n" + +#: g10/keyedit.c:903 +#, c-format +msgid "Can't edit this key: %s\n" +msgstr "Dieser Schlssel kann nicht editiert werden: %s\n" + +#: g10/keyedit.c:909 +msgid "" +"Enter the new passphrase for this secret key.\n" +"\n" +msgstr "" +"Geben Sie das neue Mantra fr diesen geheimen Schlssel ein.\n" +"\n" + +#: g10/keyedit.c:923 +msgid "" +"You don't want a passphrase - this is probably a *bad* idea!\n" +"\n" +msgstr "" +"Sie wollen kein Mantra - dies ist bestimmt *keine* gute Idee!\n" +"\n" + +#: g10/keyedit.c:926 +msgid "Do you really want to do this? " +msgstr "Mchten Sie dies wirklich tun? " + +#: g10/keyedit.c:990 +msgid "moving a key signature to the correct place\n" +msgstr "schiebe eine Beglaubigung an die richtige Stelle\n" + +#: g10/keyedit.c:1032 +msgid "quit this menu" +msgstr "Men verlassen" + +#: g10/keyedit.c:1033 +msgid "q" +msgstr "q" + +#: g10/keyedit.c:1034 +msgid "save" +msgstr "save" + +#: g10/keyedit.c:1034 +msgid "save and quit" +msgstr "speichern und Men verlassen" + +#: g10/keyedit.c:1035 +msgid "help" +msgstr "help" + +#: g10/keyedit.c:1035 +msgid "show this help" +msgstr "Diese Hilfe zeigen" + +#: g10/keyedit.c:1037 +msgid "fpr" +msgstr "fpr" + +#: g10/keyedit.c:1037 +msgid "show fingerprint" +msgstr "\"Fingerabdruck\" anzeigen" + +#: g10/keyedit.c:1038 +msgid "list" +msgstr "Liste der Schlssel" + +#: g10/keyedit.c:1038 +msgid "list key and user IDs" +msgstr "Schlssel und User-IDs auflisten" + +#: g10/keyedit.c:1039 +msgid "l" +msgstr "l" + +#: g10/keyedit.c:1040 +msgid "uid" +msgstr "uid" + +#: g10/keyedit.c:1040 +msgid "select user ID N" +msgstr "User-ID N auswhlen" + +#: g10/keyedit.c:1041 +msgid "key" +msgstr "key" + +#: g10/keyedit.c:1041 +msgid "select secondary key N" +msgstr "Zweitschlssel N auswhlen" + +#: g10/keyedit.c:1042 +msgid "check" +msgstr "check" + +#: g10/keyedit.c:1042 +msgid "list signatures" +msgstr "Liste der Signaturen" + +#: g10/keyedit.c:1043 +msgid "c" +msgstr "c" + +#: g10/keyedit.c:1044 +msgid "sign" +msgstr "sign" + +#: g10/keyedit.c:1044 +msgid "sign the key" +msgstr "Den Schlssel signieren" + +#: g10/keyedit.c:1045 +msgid "s" +msgstr "s" + +#: g10/keyedit.c:1046 +#, fuzzy +msgid "tsign" +msgstr "sign" + +#: g10/keyedit.c:1046 +#, fuzzy +msgid "make a trust signature" +msgstr "Eine abgetrennte Unterschrift erzeugen" + +#: g10/keyedit.c:1047 +msgid "lsign" +msgstr "lsign" + +#: g10/keyedit.c:1047 +msgid "sign the key locally" +msgstr "Den Schlssel nur fr diesen Rechner beglaubigen" + +#: g10/keyedit.c:1048 +msgid "nrsign" +msgstr "nrsign" + +#: g10/keyedit.c:1048 +msgid "sign the key non-revocably" +msgstr "Den Schlssel nicht-widerrufbar beglaubigen" + +#: g10/keyedit.c:1049 +msgid "nrlsign" +msgstr "nrlsign" + +#: g10/keyedit.c:1049 +msgid "sign the key locally and non-revocably" +msgstr "Den Schlssel nicht-widerrufbar und nur fr diesen Rechner signieren" + +#: g10/keyedit.c:1050 +msgid "debug" +msgstr "debug" + +#: g10/keyedit.c:1051 +msgid "adduid" +msgstr "adduid" + +#: g10/keyedit.c:1051 +msgid "add a user ID" +msgstr "Eine User-ID hinzufgen" + +#: g10/keyedit.c:1052 +msgid "addphoto" +msgstr "addphoto" + +#: g10/keyedit.c:1052 +msgid "add a photo ID" +msgstr "Eine Foto-ID hinzufgen" + +#: g10/keyedit.c:1053 +msgid "deluid" +msgstr "deluid" + +#: g10/keyedit.c:1053 +msgid "delete user ID" +msgstr "User-ID entfernen" + +#. delphoto is really deluid in disguise +#: g10/keyedit.c:1055 +msgid "delphoto" +msgstr "delphoto" + +#: g10/keyedit.c:1056 +msgid "addkey" +msgstr "addkey" + +#: g10/keyedit.c:1056 +msgid "add a secondary key" +msgstr "Einen Zweitschlssel hinzufgen" + +#: g10/keyedit.c:1057 +msgid "delkey" +msgstr "delkey" + +#: g10/keyedit.c:1057 +msgid "delete a secondary key" +msgstr "Einen Zweitschlssel entfernen" + +#: g10/keyedit.c:1058 +msgid "addrevoker" +msgstr "addrevoker" + +#: g10/keyedit.c:1058 +msgid "add a revocation key" +msgstr "Einen Widerrufschlssel hinzufgen" + +#: g10/keyedit.c:1059 +msgid "delsig" +msgstr "delsig" + +#: g10/keyedit.c:1059 +msgid "delete signatures" +msgstr "Signatur entfernen" + +#: g10/keyedit.c:1060 +msgid "expire" +msgstr "expire" + +#: g10/keyedit.c:1060 +msgid "change the expire date" +msgstr "ndern des Verfallsdatums" + +#: g10/keyedit.c:1061 +msgid "primary" +msgstr "primary" + +#: g10/keyedit.c:1061 +msgid "flag user ID as primary" +msgstr "User-ID als Haupt-User-ID kennzeichnen" + +#: g10/keyedit.c:1062 +msgid "toggle" +msgstr "toggle" + +#: g10/keyedit.c:1062 +msgid "toggle between secret and public key listing" +msgstr "Umschalten zwischen Anzeige geheimer und ffentlicher Schlssel" + +#: g10/keyedit.c:1064 +msgid "t" +msgstr "t" + +#: g10/keyedit.c:1065 +msgid "pref" +msgstr "pref" + +#: g10/keyedit.c:1065 +msgid "list preferences (expert)" +msgstr "Liste der Voreinstellungen (fr Experten)" + +#: g10/keyedit.c:1066 +msgid "showpref" +msgstr "showpref" + +#: g10/keyedit.c:1066 +msgid "list preferences (verbose)" +msgstr "Liste der Voreinstellungen (ausfhrlich)" + +#: g10/keyedit.c:1067 +msgid "setpref" +msgstr "setpref" + +#: g10/keyedit.c:1067 +msgid "set preference list" +msgstr "Liste der Voreinstellungen einstellen" + +#: g10/keyedit.c:1068 +msgid "updpref" +msgstr "updpref" + +#: g10/keyedit.c:1068 +msgid "updated preferences" +msgstr "genderte Voreinstellungen" + +#: g10/keyedit.c:1069 +msgid "passwd" +msgstr "passwd" + +#: g10/keyedit.c:1069 +msgid "change the passphrase" +msgstr "Das Mantra ndern" + +#: g10/keyedit.c:1070 +msgid "trust" +msgstr "trust" + +#: g10/keyedit.c:1070 +msgid "change the ownertrust" +msgstr "Den \"Owner trust\" ndern" + +#: g10/keyedit.c:1071 +msgid "revsig" +msgstr "revsig" + +#: g10/keyedit.c:1071 +msgid "revoke signatures" +msgstr "Signaturen widerrufen" + +#: g10/keyedit.c:1072 +msgid "revkey" +msgstr "revkey" + +#: g10/keyedit.c:1072 +msgid "revoke a secondary key" +msgstr "Einen Zweitschlssel widerrufen" + +#: g10/keyedit.c:1073 +msgid "disable" +msgstr "disable" + +#: g10/keyedit.c:1073 +msgid "disable a key" +msgstr "Schlssel abschalten" + +#: g10/keyedit.c:1074 +msgid "enable" +msgstr "enable" + +#: g10/keyedit.c:1074 +msgid "enable a key" +msgstr "Schlssel anschalten" + +#: g10/keyedit.c:1075 +msgid "showphoto" +msgstr "showphoto" + +#: g10/keyedit.c:1075 +msgid "show photo ID" +msgstr "Foto-ID anzeigen" + +#: g10/delkey.c:119 g10/keyedit.c:1095 +msgid "can't do that in batchmode\n" +msgstr "Dies kann im Batchmodus nicht durchgefhrt werden.\n" + +#: g10/keyedit.c:1132 +#, c-format +msgid "error reading secret keyblock `%s': %s\n" +msgstr "Fehler beim Lesen des geheimen Schlsselblocks `%s': %s\n" + +#: g10/keyedit.c:1150 +msgid "Secret key is available.\n" +msgstr "Geheimer Schlssel ist vorhanden.\n" + +#: g10/keyedit.c:1181 +msgid "Command> " +msgstr "Befehl> " + +#: g10/keyedit.c:1213 +msgid "Need the secret key to do this.\n" +msgstr "Hierzu wird der geheime Schlssel bentigt.\n" + +#: g10/keyedit.c:1217 +msgid "Please use the command \"toggle\" first.\n" +msgstr "Bitte verwenden sie zunchst den Befehl \"toggle\"\n" + +#: g10/keyedit.c:1267 +msgid "Key is revoked." +msgstr "Schlssel wurde widerrufen." + +#: g10/keyedit.c:1286 +msgid "Really sign all user IDs? " +msgstr "Wirklich alle User-IDs beglaubigen? " + +#: g10/keyedit.c:1287 +msgid "Hint: Select the user IDs to sign\n" +msgstr "Tip: Whlen Sie die User-IDs, die beglaubigt werden sollen\n" + +#: g10/keyedit.c:1313 +#, c-format +msgid "This command is not allowed while in %s mode.\n" +msgstr "Dieses Kommando ist im %s-Modus nicht erlaubt.\n" + +#: g10/keyedit.c:1333 g10/keyedit.c:1354 +msgid "You must select at least one user ID.\n" +msgstr "Zumindestens eine User-ID mu ausgewhlt werden.\n" + +#: g10/keyedit.c:1335 +msgid "You can't delete the last user ID!\n" +msgstr "Die letzte User-ID kann nicht gelscht werden!\n" + +#: g10/keyedit.c:1338 +msgid "Really remove all selected user IDs? " +msgstr "Mchten Sie alle ausgewhlten User-IDs wirklich entfernen? " + +#: g10/keyedit.c:1339 +msgid "Really remove this user ID? " +msgstr "Diese User-ID wirklich entfernen? " + +#: g10/keyedit.c:1377 g10/keyedit.c:1414 +msgid "You must select at least one key.\n" +msgstr "Zumindestens ein Schlssel mu ausgewhlt werden.\n" + +#: g10/keyedit.c:1381 +msgid "Do you really want to delete the selected keys? " +msgstr "Mchten Sie die ausgewhlten Schlssel wirklich entfernen? " + +#: g10/keyedit.c:1382 +msgid "Do you really want to delete this key? " +msgstr "Mchten Sie diesen Schlssel wirklich entfernen? " + +#: g10/keyedit.c:1418 +msgid "Do you really want to revoke the selected keys? " +msgstr "Mchten Sie die ausgewhlten Schlssel wirklich widerrufen? " + +#: g10/keyedit.c:1419 +msgid "Do you really want to revoke this key? " +msgstr "Mchten Sie diesen Schlssel wirklich wiederrufen? " + +#: g10/keyedit.c:1483 +#, fuzzy +msgid "Current preference list:\n" +msgstr "Liste der Voreinstellungen einstellen" + +#: g10/keyedit.c:1489 +msgid "Really update the preferences for the selected user IDs? " +msgstr "" +"Mchten Sie die Voreinstellungen der ausgewhlten User-IDs wirklich ndern? " + +#: g10/keyedit.c:1491 +msgid "Really update the preferences? " +msgstr "Die Voreinstellungen wirklich ndern? " + +#: g10/keyedit.c:1529 +msgid "Save changes? " +msgstr "nderungen speichern? " + +#: g10/keyedit.c:1532 +msgid "Quit without saving? " +msgstr "Beenden ohne zu speichern? " + +#: g10/keyedit.c:1543 +#, c-format +msgid "update failed: %s\n" +msgstr "nderung fehlgeschlagen: %s\n" + +#: g10/keyedit.c:1550 +#, c-format +msgid "update secret failed: %s\n" +msgstr "nderung des Geheimnisses fehlgeschlagen: %s\n" + +#: g10/keyedit.c:1557 +msgid "Key not changed so no update needed.\n" +msgstr "Schlssel ist nicht gendert worden, also ist kein Speichern ntig.\n" + +#: g10/keyedit.c:1569 +msgid "Invalid command (try \"help\")\n" +msgstr "Ungltiger Befehl (versuchen Sie's mal mit \"help\")\n" + +#: g10/keyedit.c:1885 +#, c-format +msgid "This key may be revoked by %s key " +msgstr "Dieser Schlssel knnte widerrufen worden sein von %s Schlssel " + +#: g10/keyedit.c:1889 +msgid " (sensitive)" +msgstr "(empfindlich)" + +#. Note, we use the same format string as in other show +#. functions to make the translation job easier. +#: g10/keyedit.c:1895 g10/keyedit.c:1921 g10/keyedit.c:2006 g10/keyedit.c:2021 +#, c-format +msgid "%s%c %4u%c/%08lX created: %s expires: %s" +msgstr "%s%c %4u%c/%08lX erstellt: %s verfllt: %s" + +#: g10/keyedit.c:1904 +#, c-format +msgid " trust: %c/%c" +msgstr " Vertrauen: %c/%c" + +#: g10/keyedit.c:1908 +msgid "This key has been disabled" +msgstr "Hinweis: Dieser Schlssel ist abgeschaltet" + +#: g10/keyedit.c:1937 +#, c-format +msgid "rev! subkey has been revoked: %s\n" +msgstr "rev! Unterschlssel wurde widerrufen: %s\n" + +#: g10/keyedit.c:1940 +msgid "rev- faked revocation found\n" +msgstr "rev- geflschter Schlsselwiderruf entdeckt\n" + +#: g10/keyedit.c:1942 +#, c-format +msgid "rev? problem checking revocation: %s\n" +msgstr "rev? Schwierigkeiten bei der Widerruf-berprfung: %s\n" + +#: g10/keyedit.c:1972 +msgid "There are no preferences on a PGP 2.x-style user ID.\n" +msgstr "PGP 2.x-artige Schlssel haben keine Voreinstellungen.\n" + +#: g10/keyedit.c:1980 +msgid "" +"Please note that the shown key validity is not necessarily correct\n" +"unless you restart the program.\n" +msgstr "" +"Bitte beachten Sie, da ohne einen Programmneustart die angezeigte\n" +"Schlsselgltigkeit nicht notwendigerweise korrekt ist.\n" + +#: g10/keyedit.c:2137 +msgid "" +"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " +"versions\n" +" of PGP to reject this key.\n" +msgstr "" +"WARNUNG: Dies ist ein PGP2-artiger Schlssel. Hinzufgen einer Foto-ID " +"knnte\n" +" bei einigen PGP-Versionen zur Zurckweisung des Schlssels fhren.\n" + +#: g10/keyedit.c:2142 g10/keyedit.c:2415 +msgid "Are you sure you still want to add it? (y/N) " +msgstr "Wollen Sie ihn immmer noch hinzufgen? (j/N) " + +#: g10/keyedit.c:2148 +msgid "You may not add a photo ID to a PGP2-style key.\n" +msgstr "Sie knnen einem PGP2-artigen Schlsel keine Foto-ID hinzufgen.\n" + +#: g10/keyedit.c:2283 +msgid "Delete this good signature? (y/N/q)" +msgstr "Diese korrekte Beglaubigung entfernen? (j/N/q)" + +#: g10/keyedit.c:2293 +msgid "Delete this invalid signature? (y/N/q)" +msgstr "Diese ungltige Beglaubigung entfernen= (j/N/q)" + +#: g10/keyedit.c:2297 +msgid "Delete this unknown signature? (y/N/q)" +msgstr "Diese unbekannte Beglaubigung entfernen? (j/N/q)" + +#: g10/keyedit.c:2303 +msgid "Really delete this self-signature? (y/N)" +msgstr "Eigenbeglaubigung wirklich entfernen? (j/N)" + +#: g10/keyedit.c:2317 +#, c-format +msgid "Deleted %d signature.\n" +msgstr "%d Beglaubigungen entfernt.\n" + +#: g10/keyedit.c:2318 +#, c-format +msgid "Deleted %d signatures.\n" +msgstr "%d Beglaubigungen entfernt.\n" + +#: g10/keyedit.c:2321 +msgid "Nothing deleted.\n" +msgstr "Nichts entfernt.\n" + +#: g10/keyedit.c:2410 +#, fuzzy +msgid "" +"WARNING: This is a PGP 2.x-style key. Adding a designated revoker may " +"cause\n" +" some versions of PGP to reject this key.\n" +msgstr "" +"WARNUNG: Dies ist ein PGP2-artiger Schlssel. Hinzufgen einer Foto-ID " +"knnte\n" +" bei einigen PGP-Versionen zur Zurckweisung des Schlssels fhren.\n" + +#: g10/keyedit.c:2421 +#, fuzzy +msgid "You may not add a designated revoker to a PGP 2.x-style key.\n" +msgstr "Sie knnen einem PGP2-artigen Schlsel keine Foto-ID hinzufgen.\n" + +#: g10/keyedit.c:2444 +msgid "Enter the user ID of the designated revoker: " +msgstr "Geben sie die User-ID des designierten Widerrufers ein: " + +#: g10/keyedit.c:2459 +msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" +msgstr "" +"Ein PGP 2.x-artiger Schlssel kann nicht als designierter Widerrufer " +"eingetragen werden\n" + +#. This actually causes no harm (after all, a key that +#. designates itself as a revoker is the same as a +#. regular key), but it's easy enough to check. +#: g10/keyedit.c:2474 +msgid "you cannot appoint a key as its own designated revoker\n" +msgstr "" +"Ein Schlssel kann nicht als sein eigener designierter Widerrufer agieren\n" + +#: g10/keyedit.c:2496 +#, fuzzy +msgid "this key has already been designated as a revoker\n" +msgstr "" +"Ein Schlssel kann nicht als sein eigener designierter Widerrufer agieren\n" + +#: g10/keyedit.c:2592 +msgid "Please remove selections from the secret keys.\n" +msgstr "Bitte entfernen Sie die Auswahl von den geheimen Schlsseln.\n" + +#: g10/keyedit.c:2598 +msgid "Please select at most one secondary key.\n" +msgstr "Bitte whlen Sie hchstens einen Zweitschlssel aus.\n" + +#: g10/keyedit.c:2602 +msgid "Changing expiration time for a secondary key.\n" +msgstr "ndern des Verfallsdatums des Zweitschlssels.\n" + +#: g10/keyedit.c:2604 +msgid "Changing expiration time for the primary key.\n" +msgstr "ndern des Verfallsdatums des Hauptschlssels.\n" + +#: g10/keyedit.c:2646 +msgid "You can't change the expiration date of a v3 key\n" +msgstr "Sie knnen das Verfallsdatum eines v3-Schlssels nicht ndern\n" + +#: g10/keyedit.c:2662 +msgid "No corresponding signature in secret ring\n" +msgstr "Keine entsprechende Signatur im geheimen Schlsselbund\n" + +#: g10/keyedit.c:2745 +msgid "Please select exactly one user ID.\n" +msgstr "Bitte genau eine User-ID auswhlen.\n" + +#: g10/keyedit.c:2782 g10/keyedit.c:2889 +#, c-format +msgid "skipping v3 self-signature on user id \"%s\"\n" +msgstr "berspringen der v3 Eigenbeglaubigung von User-ID \"%s\"\n" + +#: g10/keyedit.c:2949 +#, c-format +msgid "No user ID with index %d\n" +msgstr "Keine User-ID mit Index %d\n" + +#: g10/keyedit.c:2995 +#, c-format +msgid "No secondary key with index %d\n" +msgstr "Kein Zweitschlssel mit Index %d\n" + +#: g10/keyedit.c:3109 +msgid "user ID: \"" +msgstr "User-ID: \"" + +#: g10/keyedit.c:3114 +#, c-format +msgid "" +"\"\n" +"signed with your key %08lX at %s\n" +msgstr "" +"\"\n" +"unterschrieben mit Ihrem Schlssel %08lX um %s\n" + +#: g10/keyedit.c:3117 +#, c-format +msgid "" +"\"\n" +"locally signed with your key %08lX at %s\n" +msgstr "" +"\"\n" +"lokal unterschrieben mit Ihrem Schlssel %08lX um %s\n" + +#: g10/keyedit.c:3122 +#, c-format +msgid "This signature expired on %s.\n" +msgstr "Diese Unterschrift ist seit %s verfallen.\n" + +#: g10/keyedit.c:3126 +msgid "Are you sure you still want to revoke it? (y/N) " +msgstr "Wollen Sie ihn immmer noch widerrufen? (j/N) " + +#: g10/keyedit.c:3130 +msgid "Create a revocation certificate for this signature? (y/N) " +msgstr "Ein Widerrufszertifikat fr diese Unterschrift erzeugen (j/N)" + +#. FIXME: detect duplicates here +#: g10/keyedit.c:3155 +msgid "You have signed these user IDs:\n" +msgstr "Sie haben folgende User-IDs beglaubigt:\n" + +#: g10/keyedit.c:3174 +#, c-format +msgid " signed by %08lX at %s%s%s\n" +msgstr " beglaubigt durch %08lX um %s%s%s\n" + +#: g10/keyedit.c:3182 +#, c-format +msgid " revoked by %08lX at %s\n" +msgstr " widerrufen durch %08lX um %s\n" + +#: g10/keyedit.c:3202 +msgid "You are about to revoke these signatures:\n" +msgstr "Es werden nun folgende Beglaubigungen entfernt:\n" + +#: g10/keyedit.c:3212 +#, c-format +msgid " signed by %08lX at %s%s\n" +msgstr " beglaubigt durch %08lX am %s%s\n" + +#: g10/keyedit.c:3214 +msgid " (non-exportable)" +msgstr " (nicht-exportierbar)" + +#: g10/keyedit.c:3221 +msgid "Really create the revocation certificates? (y/N) " +msgstr "Wirklich ein Unterschrift-Widerrufszertifikat erzeugen? (j/N) " + +#: g10/keyedit.c:3251 +msgid "no secret key\n" +msgstr "Kein geheimer Schlssel\n" + +#: g10/keyedit.c:3406 +#, c-format +msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" +msgstr "" +"Anzeigen einer %s Photo ID (%ld Byte) fr Schlssel %08lX (User-ID %d)\n" + +#: g10/keylist.c:133 +msgid "Critical signature policy: " +msgstr "Krititische Beglaubigungsrichtlinie: " + +#: g10/keylist.c:135 +msgid "Signature policy: " +msgstr "Beglaubigungsrichtlinie: " + +#: g10/keylist.c:160 g10/keylist.c:183 g10/mainproc.c:769 g10/mainproc.c:778 +msgid "WARNING: invalid notation data found\n" +msgstr "WARNUNG: Ungltige \"Notation\"-Daten gefunden\n" + +#: g10/keylist.c:169 +msgid "Critical signature notation: " +msgstr "Krititische Beglaubigungs-\"Notation\": " + +#: g10/keylist.c:171 +msgid "Signature notation: " +msgstr "Beglaubigungs-\"Notation\": " + +#: g10/keylist.c:178 +msgid "not human readable" +msgstr "nicht als Klartext darstellbar" + +#: g10/keylist.c:267 +msgid "Keyring" +msgstr "Schlsselbund" + +#. of subkey +#: g10/keylist.c:536 g10/mainproc.c:905 +#, c-format +msgid " [expires: %s]" +msgstr " [verfllt: %s]" + +#: g10/keylist.c:1063 +msgid "Primary key fingerprint:" +msgstr "Haupt-Fingerabdruck =" + +#: g10/keylist.c:1065 +msgid " Subkey fingerprint:" +msgstr "Unter-Fingerabdruck =" + +#: g10/keylist.c:1072 +msgid " Primary key fingerprint:" +msgstr " Haupt-Fingerabdruck =" + +#: g10/keylist.c:1074 +msgid " Subkey fingerprint:" +msgstr " Unter-Fingerabdruck =" + +#. use tty +#: g10/keylist.c:1078 g10/keylist.c:1082 +#, fuzzy +msgid " Key fingerprint =" +msgstr " Schl.-Fingerabdruck =" + +#: g10/mainproc.c:248 +#, c-format +msgid "weird size for an encrypted session key (%d)\n" +msgstr "Seltsame Lnge des verschlsselten Session-Keys (%d)\n" + +#: g10/mainproc.c:259 +#, c-format +msgid "invalid symkey algorithm detected (%d)\n" +msgstr "Ungltiger Veschlsselungsalgorithmus entdeckt (%d)\n" + +#: g10/encr-data.c:66 g10/mainproc.c:288 +#, c-format +msgid "%s encrypted data\n" +msgstr "%s verschlsselte Daten\n" + +#: g10/encr-data.c:68 g10/mainproc.c:290 +#, c-format +msgid "encrypted with unknown algorithm %d\n" +msgstr "Mit unbekanntem Verfahren verschlsselt %d\n" + +#: g10/mainproc.c:318 +#, c-format +msgid "public key is %08lX\n" +msgstr "ffentlicher Schlssel ist %08lX\n" + +#: g10/mainproc.c:364 +msgid "public key encrypted data: good DEK\n" +msgstr "Mit ffentlichem Schssel verschlsselte Daten: Korrekte DEK\n" + +#: g10/mainproc.c:416 +#, c-format +msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" +msgstr "verschlsselt mit %u-Bit %s Schlssel, ID %08lX, erzeugt %s\n" + +# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( +# [kw] +#: g10/mainproc.c:426 +#, c-format +msgid "encrypted with %s key, ID %08lX\n" +msgstr "verschlsselt mit %s Schlssel, ID %08lX\n" + +#: g10/mainproc.c:440 +#, c-format +msgid "public key decryption failed: %s\n" +msgstr "Entschlsselung mit ffentlichem Schlssel fehlgeschlagen: %s\n" + +#: g10/mainproc.c:467 g10/mainproc.c:486 +#, c-format +msgid "assuming %s encrypted data\n" +msgstr "vermutlich %s-verschlsselte Daten\n" + +#: g10/mainproc.c:474 +#, c-format +msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" +msgstr "IDEA-Verschlsselung nicht verfgbar; versucht wird stattdessen %s\n" + +#: g10/mainproc.c:504 +msgid "decryption okay\n" +msgstr "Entschlsselung erfolgreich\n" + +#: g10/mainproc.c:511 +msgid "WARNING: encrypted message has been manipulated!\n" +msgstr "Warnung: Verschlsselte Botschaft ist manipuliert worden!\n" + +#: g10/mainproc.c:517 +#, c-format +msgid "decryption failed: %s\n" +msgstr "Entschlsselung fehlgeschlagen: %s\n" + +#: g10/mainproc.c:536 +msgid "NOTE: sender requested \"for-your-eyes-only\"\n" +msgstr "" +"Hinweis: Der Absender verlangte Vertraulichkeit(\"for-your-eyes-only\")\n" + +#: g10/mainproc.c:538 +#, c-format +msgid "original file name='%.*s'\n" +msgstr "Ursprnglicher Dateiname='%.*s'\n" + +#: g10/mainproc.c:713 +msgid "standalone revocation - use \"gpg --import\" to apply\n" +msgstr "" +"Einzelner Widerruf - verwenden Sie \"gpg --import\" um ihn anzuwenden\n" + +#: g10/mainproc.c:781 +msgid "Notation: " +msgstr "\"Notation\": " + +#: g10/mainproc.c:793 +msgid "Policy: " +msgstr "Richtlinie: " + +#: g10/mainproc.c:1248 +msgid "signature verification suppressed\n" +msgstr "Unterschriften-berprfung unterdrckt\n" + +#. plaintext before signatures but no one-pass packets +#: g10/mainproc.c:1290 g10/mainproc.c:1300 +msgid "can't handle these multiple signatures\n" +msgstr "diese Mehrfachunterschriften knnen nicht behandelt werden\n" + +# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( +#: g10/mainproc.c:1311 +#, c-format +msgid "Signature made %.*s using %s key ID %08lX\n" +msgstr "Unterschrift vom %.*s, %s Schlssel ID %08lX\n" + +#: g10/mainproc.c:1360 g10/mainproc.c:1393 +msgid "BAD signature from \"" +msgstr "FALSCHE Unterschrift von \"" + +#: g10/mainproc.c:1361 g10/mainproc.c:1394 +msgid "Expired signature from \"" +msgstr "Verfallene Unterschrift von \"" + +#: g10/mainproc.c:1362 g10/mainproc.c:1395 +msgid "Good signature from \"" +msgstr "Korrekte Unterschrift von \"" + +#: g10/mainproc.c:1397 +msgid "[uncertain]" +msgstr "[ungewi] " + +#: g10/mainproc.c:1489 +#, c-format +msgid "Can't check signature: %s\n" +msgstr "Unterschrift kann nicht geprft werden: %s\n" + +#: g10/mainproc.c:1558 g10/mainproc.c:1574 g10/mainproc.c:1636 +msgid "not a detached signature\n" +msgstr "keine abgetrennte Unterschrift\n" + +#: g10/mainproc.c:1585 +#, c-format +msgid "standalone signature of class 0x%02x\n" +msgstr "Einzelne Unterschrift der Klasse 0x%02x\n" + +#: g10/mainproc.c:1642 +msgid "old style (PGP 2.x) signature\n" +msgstr "Unterschrift nach alter (PGP 2.x) Art\n" + +#: g10/mainproc.c:1649 +msgid "invalid root packet detected in proc_tree()\n" +msgstr "ungltiges root-Paket in proc_tree() entdeckt\n" + +#: g10/misc.c:98 +#, c-format +msgid "can't disable core dumps: %s\n" +msgstr "core-dump-Dateierzeugung kann nicht abgeschaltet werden: %s\n" + +#: g10/misc.c:162 +msgid "Experimental algorithms should not be used!\n" +msgstr "Experimentiermethoden sollten nicht benutzt werden!\n" + +#: g10/misc.c:192 +msgid "this cipher algorithm is deprecated; please use a more standard one!\n" +msgstr "Es ist davon abzuraten, diese Verschlsselungsmethode zu benutzen!\n" + +#: g10/misc.c:300 +msgid "the IDEA cipher plugin is not present\n" +msgstr "das IDEA-Verschlsselungs-Plugin ist nicht vorhanden\n" + +#: g10/misc.c:301 +msgid "" +"please see http://www.gnupg.org/why-not-idea.html for more information\n" +msgstr "Fr weitere Info siehe http://www.gnupg.org/why-not-idea.html\n" + +#: g10/misc.c:509 +#, c-format +msgid "%s:%d: deprecated option \"%s\"\n" +msgstr "%s:%d: mibilligte Option \"%s\".\n" + +#: g10/misc.c:513 +#, c-format +msgid "WARNING: \"%s\" is a deprecated option\n" +msgstr "WARNUNG: \"%s\" ist eine mibilligte Option.\n" + +#: g10/misc.c:515 +#, c-format +msgid "please use \"%s%s\" instead\n" +msgstr "Bitte benutzen Sie stattdessen \"%s%s\".\n" + +#: g10/parse-packet.c:120 +#, c-format +msgid "can't handle public key algorithm %d\n" +msgstr "dieses Public-Key Verfahren %d kann nicht benutzt werden\n" + +#: g10/parse-packet.c:1072 +#, c-format +msgid "subpacket of type %d has critical bit set\n" +msgstr "Im Unterpaket des Typs %d ist das \"critical bit\" gesetzt\n" + +#: g10/passphrase.c:442 g10/passphrase.c:489 +msgid "gpg-agent is not available in this session\n" +msgstr "GPG-Agent ist in dieser Sitzung nicht vorhanden\n" + +#: g10/passphrase.c:450 +msgid "can't set client pid for the agent\n" +msgstr "Client-PID fr den Agent kann nicht gesetzt werden\n" + +#: g10/passphrase.c:458 +msgid "can't get server read FD for the agent\n" +msgstr "Server-Lese-Handle fr den Agent nicht verfgbar\n" + +#: g10/passphrase.c:465 +msgid "can't get server write FD for the agent\n" +msgstr "Server-Schreib-Handle fr den Agent nicht verfgbar\n" + +#: g10/passphrase.c:498 +msgid "malformed GPG_AGENT_INFO environment variable\n" +msgstr "fehlerhaft aufgebaute GPG_AGENT_INFO - Umgebungsvariable\n" + +#: g10/passphrase.c:511 +#, c-format +msgid "gpg-agent protocol version %d is not supported\n" +msgstr "GPG-Agent-Protokoll-Version %d wird nicht untersttzt\n" + +#: g10/passphrase.c:532 +#, c-format +msgid "can't connect to `%s': %s\n" +msgstr "Verbindung zu '%s' kann nicht aufgebaut werden: %s\n" + +#: g10/passphrase.c:554 +msgid "communication problem with gpg-agent\n" +msgstr "Kommunikationsproblem mit GPG-Agent\n" + +#: g10/passphrase.c:561 g10/passphrase.c:812 g10/passphrase.c:920 +msgid "problem with the agent - disabling agent use\n" +msgstr "" +"Schwierigkeiten mit dem Agenten - Agent-Ansteuerung wird abgeschaltet\n" + +#: g10/passphrase.c:631 g10/passphrase.c:1019 +#, c-format +msgid " (main key ID %08lX)" +msgstr " (Hauptschlssel-ID %08lX)" + +#: g10/passphrase.c:641 +#, c-format +msgid "" +"You need a passphrase to unlock the secret key for user:\n" +"\"%.*s\"\n" +"%u-bit %s key, ID %08lX, created %s%s\n" +msgstr "" +"Sie bentigen ein Mantra, um den geheimen Schlssel zu entsperren.\n" +"Benutzer: \"\"%.*s\"\n" +"%u-bit %s Schlssel, ID %08lX, erzeugt %s%s\n" + +#: g10/passphrase.c:662 +msgid "Enter passphrase\n" +msgstr "Geben Sie das Mantra ein\n" + +#: g10/passphrase.c:664 +msgid "Repeat passphrase\n" +msgstr "Geben Sie das Mantra nochmal ein\n" + +#: g10/passphrase.c:705 +msgid "passphrase too long\n" +msgstr "Mantra ist zu lang\n" + +#: g10/passphrase.c:718 +msgid "invalid response from agent\n" +msgstr "Falsche Antwort des Agenten\n" + +#: g10/passphrase.c:727 g10/passphrase.c:809 +msgid "cancelled by user\n" +msgstr "Abbruch durch Benutzer\n" + +#: g10/passphrase.c:729 g10/passphrase.c:891 +#, c-format +msgid "problem with the agent: agent returns 0x%lx\n" +msgstr "Schwierigkeiten mit dem Agenten: Agent antwortet 0x%lx\n" + +#: g10/passphrase.c:1005 +msgid "" +"\n" +"You need a passphrase to unlock the secret key for\n" +"user: \"" +msgstr "" +"\n" +"Sie bentigen ein Mantra, um den geheimen Schlssel zu entsperren.\n" +"Benutzer: \"" + +#: g10/passphrase.c:1014 +#, c-format +msgid "%u-bit %s key, ID %08lX, created %s" +msgstr "%u-Bit %s Schlssel, ID %08lX, erzeugt %s" + +#: g10/passphrase.c:1065 +msgid "can't query password in batchmode\n" +msgstr "Mantra kann im Batchmodus nicht abgefragt werden\n" + +#: g10/passphrase.c:1069 +msgid "Enter passphrase: " +msgstr "Geben Sie das Mantra ein: " + +#: g10/passphrase.c:1073 +msgid "Repeat passphrase: " +msgstr "Geben Sie das Mantra nochmal ein: " + +#: g10/plaintext.c:70 +msgid "data not saved; use option \"--output\" to save it\n" +msgstr "" +"Daten wurden nicht gespeichert; verwenden Sie dafr die Option \"--output\"\n" + +#: g10/plaintext.c:112 g10/plaintext.c:125 +#, c-format +msgid "error creating `%s': %s\n" +msgstr "Fehler beim Erstellen von `%s': %s\n" + +#: g10/plaintext.c:362 +msgid "Detached signature.\n" +msgstr "Abgetrennte Beglaubigungen.\n" + +#: g10/plaintext.c:366 +msgid "Please enter name of data file: " +msgstr "Bitte geben Sie den Namen der Datendatei ein: " + +#: g10/plaintext.c:387 +msgid "reading stdin ...\n" +msgstr "lese stdin ...\n" + +#: g10/plaintext.c:421 +msgid "no signed data\n" +msgstr "keine unterschriebene Daten\n" + +#: g10/plaintext.c:429 +#, c-format +msgid "can't open signed data `%s'\n" +msgstr "kann signierte Datei '%s' nicht ffnen.\n" + +#: g10/pubkey-enc.c:102 +#, c-format +msgid "anonymous recipient; trying secret key %08lX ...\n" +msgstr "Ungenannter Empfnger; Versuch mit geheimen Schlssel %08lX ...\n" + +#: g10/pubkey-enc.c:118 +msgid "okay, we are the anonymous recipient.\n" +msgstr "Alles klar, wir sind der ungenannte Empfnger.\n" + +#: g10/pubkey-enc.c:170 +msgid "old encoding of the DEK is not supported\n" +msgstr "alte Kodierung des DEK wird nicht untersttzt\n" + +#: g10/pubkey-enc.c:189 +#, c-format +msgid "cipher algorithm %d%s is unknown or disabled\n" +msgstr "Verschsselungsverfahren %d%s ist unbekannt oder abgeschaltet\n" + +#: g10/pubkey-enc.c:232 +#, c-format +msgid "NOTE: cipher algorithm %d not found in preferences\n" +msgstr "Hinweis: Verfahren %d ist kein bevorzugtes Verschlsselungsverfahren\n" + +#: g10/pubkey-enc.c:254 +#, c-format +msgid "NOTE: secret key %08lX expired at %s\n" +msgstr "Hinweis: geheimer Schlssel %08lX verfllt am %s\n" + +#: g10/pubkey-enc.c:260 +msgid "NOTE: key has been revoked" +msgstr "Hinweis: Schlssel wurde widerrufen" + +#: g10/seckey-cert.c:53 +msgid "secret key parts are not available\n" +msgstr "Teile des geheimen Schlssels sind nicht vorhanden\n" + +#: g10/seckey-cert.c:59 +#, c-format +msgid "protection algorithm %d%s is not supported\n" +msgstr "Schutzverfahren %d%s wird nicht untersttzt\n" + +#: g10/seckey-cert.c:234 +msgid "Invalid passphrase; please try again" +msgstr "Ungltiges Mantra; versuchen Sie es bitte noch einmal" + +#: g10/seckey-cert.c:235 +#, c-format +msgid "%s ...\n" +msgstr "%s ...\n" + +#: g10/seckey-cert.c:292 +msgid "WARNING: Weak key detected - please change passphrase again.\n" +msgstr "" +"WARNUNG: Unsicherer Schlssel entdeckt -\n" +" bitte Mantra nochmals wechseln.\n" + +#: g10/seckey-cert.c:330 +msgid "generating the deprecated 16-bit checksum for secret key protection\n" +msgstr "" +"Die mibilligte 16-bit Prfsumme wird zum Schutz des geheimen Schlssels " +"benutzt\n" + +#: g10/sig-check.c:73 +msgid "WARNING: signature digest conflict in message\n" +msgstr "WARNUNG: Widersprechende Hashverfahren in der signierten Nachricht\n" + +#: g10/sig-check.c:213 +#, c-format +msgid "" +"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " +"signatures!\n" +msgstr "" +"Schlssel %08lX: Dieser durch PGP erzeugte ElGamal-Schlssel ist fr " +"Signaturen NICHT sicher genug!\n" + +#: g10/sig-check.c:222 +#, c-format +msgid "public key %08lX is %lu second newer than the signature\n" +msgstr "" +"ffentlicher Schlssel %08lX ist um %lu Sekunde jnger als die Unterschrift\n" + +#: g10/sig-check.c:223 +#, c-format +msgid "public key %08lX is %lu seconds newer than the signature\n" +msgstr "" +"ffentlicher Schlssel %08lX ist um %lu Sekunden jnger als die " +"Unterschrift\n" + +#: g10/sig-check.c:232 +#, c-format +msgid "" +"key %08lX has been created %lu second in future (time warp or clock " +"problem)\n" +msgstr "" +"Der Schlssel %08lX wurde %lu Sekunde in der Zukunft erzeugt (Zeitreise oder " +"Uhren stimmen nicht berein)\n" + +#: g10/sig-check.c:234 +#, c-format +msgid "" +"key %08lX has been created %lu seconds in future (time warp or clock " +"problem)\n" +msgstr "" +"Der Schlssel %08lX wurde %lu Sekunden in der Zukunft erzeugt (Zeitreise " +"oder Uhren stimmen nicht berein)\n" + +#: g10/sig-check.c:247 +#, c-format +msgid "NOTE: signature key %08lX expired %s\n" +msgstr "Hinweis: Signaturschlssel %08lX ist am %s verfallen.\n" + +#: g10/sig-check.c:346 +#, c-format +msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" +msgstr "" +"Vermutlich eine FALSCHE Unterschrift von Schlssel %08lX, wegen unbekanntem " +"\"critical bit\"\n" + +#: g10/sign.c:103 +#, c-format +msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" +msgstr "" +"WARNUNG: \"Notation\" kann nicht %%-erweitert werden (zu gro). Verwende " +"\"unerweiterte\".\n" + +#: g10/sign.c:151 +#, c-format +msgid "" +"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" +msgstr "" +"WARNUNG: Richtlinien-URL kann nicht %%-erweitert werden (zu gro0). Verwende " +"\"unerweiterte\".\n" + +#: g10/sign.c:303 +#, c-format +msgid "checking created signature failed: %s\n" +msgstr "Prfung der erstellten Unterschrift ist fehlgeschlagen: %s\n" + +#: g10/sign.c:312 +#, c-format +msgid "%s signature from: \"%s\"\n" +msgstr "%s Unterschrift von: \"%s\"\n" + +#: g10/sign.c:462 +#, c-format +msgid "WARNING: `%s' is an empty file\n" +msgstr "WARNUNG: '%s' ist eine leere Datei.\n" + +#: g10/sign.c:645 +msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" +msgstr "" +"Im --pgp2-Modus kann nur mit PGP-2.x-artigen Schlsseln eine abgetrennte " +"Unterschrift erzeugt werden\n" + +#: g10/sign.c:666 g10/sign.c:893 +#, c-format +msgid "can't create %s: %s\n" +msgstr "%s kann nicht erzeugt werden: %s\n" + +#: g10/sign.c:691 +#, c-format +msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" +msgstr "" +"Erzwingen des Hashverfahrens %s (%d) verletzt die Empfngervoreinstellungen\n" + +#: g10/sign.c:785 +msgid "signing:" +msgstr "unterschreibe:" + +#: g10/sign.c:877 +msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" +msgstr "" +"Im --pgp2-Modus knnen Sie Klartextunterschriften nur mit PGP-2.x-artigen " +"Schlssel machen\n" + +#: g10/sign.c:1030 +#, c-format +msgid "%s encryption will be used\n" +msgstr "%s Verschlsselung wird verwendet\n" + +#: g10/textfilter.c:134 +#, c-format +msgid "can't handle text lines longer than %d characters\n" +msgstr "Textzeilen lnger als %d Zeichen knnen nicht benutzt werden\n" + +#: g10/textfilter.c:231 +#, c-format +msgid "input line longer than %d characters\n" +msgstr "Eingabezeile ist lnger als %d Zeichen\n" + +#: g10/tdbio.c:128 g10/tdbio.c:1389 +#, c-format +msgid "trustdb rec %lu: lseek failed: %s\n" +msgstr "trustdb Satz %lu: lseek fehlgeschlagen: %s\n" + +#: g10/tdbio.c:134 g10/tdbio.c:1396 +#, c-format +msgid "trustdb rec %lu: write failed (n=%d): %s\n" +msgstr "trustdb Satz %lu: write fehlgeschlagen (n=%d): %s\n" + +#: g10/tdbio.c:244 +msgid "trustdb transaction too large\n" +msgstr "trustdb Transaktion zu gro\n" + +#: g10/tdbio.c:459 +#, c-format +msgid "%s: can't access: %s\n" +msgstr "%s: kann nicht zugegriffen werden: %s\n" + +#: g10/tdbio.c:474 +#, c-format +msgid "%s: directory does not exist!\n" +msgstr "%s: Verzeichnis existiert nicht!\n" + +#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 +#, c-format +msgid "%s: can't create lock\n" +msgstr "%s: Sperre kann nicht erzeugt werden\n" + +#: g10/tdbio.c:486 g10/tdbio.c:548 +#, c-format +msgid "%s: can't make lock\n" +msgstr "%s: Sperre kann nicht erzeugt werden\n" + +#: g10/keyring.c:1453 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 +#, c-format +msgid "%s: can't create: %s\n" +msgstr "%s: kann nicht erzeugt werden: %s\n" + +#: g10/tdbio.c:507 +#, c-format +msgid "%s: failed to create version record: %s" +msgstr "%s: Fehler beim Erzeugen des Versionsatzes: %s" + +#: g10/tdbio.c:511 +#, c-format +msgid "%s: invalid trustdb created\n" +msgstr "%s: ungltige trust-db erzeugt\n" + +#: g10/tdbio.c:514 +#, c-format +msgid "%s: trustdb created\n" +msgstr "%s: trust-db erzeugt\n" + +#: g10/tdbio.c:554 +msgid "NOTE: trustdb not writable\n" +msgstr "Notiz: Die \"trustdb\" ist nicht schreibbar\n" + +#: g10/tdbio.c:570 +#, c-format +msgid "%s: invalid trustdb\n" +msgstr "%s: ungltige 'Trust'-Datenbank\n" + +#: g10/tdbio.c:602 +#, c-format +msgid "%s: failed to create hashtable: %s\n" +msgstr "%s: hashtable kann nicht erzeugt werden: %s\n" + +#: g10/tdbio.c:610 +#, c-format +msgid "%s: error updating version record: %s\n" +msgstr "%s: Fehler beim ndern des Versionsatzes: %s\n" + +#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 +#: g10/tdbio.c:1322 g10/tdbio.c:1349 +#, c-format +msgid "%s: error reading version record: %s\n" +msgstr "%s: Fehler beim Lesen des Versionsatzes: %s\n" + +#: g10/tdbio.c:639 g10/tdbio.c:685 +#, c-format +msgid "%s: error writing version record: %s\n" +msgstr "%s: Fehler beim Schreiben des Versionsatzes: %s\n" + +#: g10/tdbio.c:1124 +#, c-format +msgid "trustdb: lseek failed: %s\n" +msgstr "trustdb: lseek fehlgeschlagen: %s\n" + +#: g10/tdbio.c:1132 +#, c-format +msgid "trustdb: read failed (n=%d): %s\n" +msgstr "trustdb: read failed (n=%d): %s\n" + +#: g10/tdbio.c:1153 +#, c-format +msgid "%s: not a trustdb file\n" +msgstr "%s: keine trustdb Datei\n" + +#: g10/tdbio.c:1170 +#, c-format +msgid "%s: version record with recnum %lu\n" +msgstr "%s: version record with recnum %lu\n" + +#: g10/tdbio.c:1175 +#, c-format +msgid "%s: invalid file version %d\n" +msgstr "%s: invalid file version %d\n" + +#: g10/tdbio.c:1355 +#, c-format +msgid "%s: error reading free record: %s\n" +msgstr "%s: Fehler beim Lesen eines freien Satzes: %s\n" + +#: g10/tdbio.c:1363 +#, c-format +msgid "%s: error writing dir record: %s\n" +msgstr "%s: Fehler beim Schreiben eines Verzeichnis-Satzes: %s\n" + +#: g10/tdbio.c:1373 +#, c-format +msgid "%s: failed to zero a record: %s\n" +msgstr "%s: konnte einen Satz nicht Nullen: %s\n" + +#: g10/tdbio.c:1403 +#, c-format +msgid "%s: failed to append a record: %s\n" +msgstr "%s: konnte Satz nicht anhngen: %s\n" + +#: g10/tdbio.c:1448 +msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" +msgstr "" +"Die \"Trust\"-Datenbank ist beschdigt; verwenden Sie \"gpg --fix-trustdb" +"\".\n" + +#: g10/trustdb.c:213 +#, c-format +msgid "`%s' is not a valid long keyID\n" +msgstr "'%s' ist keine gltige lange Schlssel-ID\n" + +#: g10/trustdb.c:248 +#, c-format +msgid "key %08lX: accepted as trusted key\n" +msgstr "Schlssel %08lX: Akzeptiert als vertrauenswrdiger Schlssel\n" + +#: g10/trustdb.c:286 +#, c-format +msgid "key %08lX occurs more than once in the trustdb\n" +msgstr "Schlssel %08lX tritt mehr als einmal in der \"trustdb\" auf\n" + +#: g10/trustdb.c:302 +#, c-format +msgid "key %08lX: no public key for trusted key - skipped\n" +msgstr "" +"Schlssel %08lX: kein ffentlicher Schlssel fr den vertrauenswrdigen " +"Schlssel - bersprungen\n" + +#: g10/trustdb.c:311 +#, fuzzy, c-format +msgid "key %08lX marked as ultimately trusted\n" +msgstr "Schlssel ist als uneingeschrnkt vertrauenswrdig gekennzeichnet.\n" + +#: g10/trustdb.c:337 +#, c-format +msgid "trust record %lu, req type %d: read failed: %s\n" +msgstr "trust record %lu, req type %d: read failed: %s\n" + +#: g10/trustdb.c:343 +#, c-format +msgid "trust record %lu is not of requested type %d\n" +msgstr "Vertrauenssatz %lu ist nicht von der angeforderten Art %d\n" + +#: g10/trustdb.c:358 +#, c-format +msgid "trust record %lu, type %d: write failed: %s\n" +msgstr "trust record %lu, type %d: write failed: %s\n" + +#: g10/trustdb.c:373 +#, c-format +msgid "trustdb: sync failed: %s\n" +msgstr "\"Trust-DB\": sync fehlgeschlagen: %s\n" + +#: g10/trustdb.c:463 +#, fuzzy +msgid "unknown trust" +msgstr "Unbekannte Version" + +#: g10/trustdb.c:464 +#, fuzzy +msgid "expired" +msgstr "expire" + +#: g10/trustdb.c:465 +msgid "undefined trust" +msgstr "" + +#: g10/trustdb.c:466 +#, fuzzy +msgid "do NOT trust" +msgstr " %d = Nein, ihm traue ich NICHT\n" + +#: g10/trustdb.c:467 +msgid "marginal trust" +msgstr "" + +#: g10/trustdb.c:468 +#, fuzzy +msgid "full trust" +msgstr "trust" + +#: g10/trustdb.c:469 +#, fuzzy +msgid "ultimate trust" +msgstr "|KEYID|diesem Schlssel uneingeschrnkt vertrauen" + +#: g10/trustdb.c:504 +msgid "no need for a trustdb check\n" +msgstr "\"Trust-DB\"-berprfung nicht ntig\n" + +#: g10/trustdb.c:510 g10/trustdb.c:1912 +#, c-format +msgid "next trustdb check due at %s\n" +msgstr "nchste \"Trust-DB\"-Pflichtberprfung am %s\n" + +#: g10/trustdb.c:519 +#, fuzzy, c-format +msgid "no need for a trustdb check with \"%s\" trust model\n" +msgstr "\"Trust-DB\"-berprfung nicht ntig\n" + +#: g10/trustdb.c:536 +#, fuzzy, c-format +msgid "no need for a trustdb update with \"%s\" trust model\n" +msgstr "\"Trust-DB\"-berprfung nicht ntig\n" + +#: g10/trustdb.c:708 g10/trustdb.c:1073 +#, c-format +msgid "public key %08lX not found: %s\n" +msgstr "ffentlicher Schlssel %08lX nicht gefunden: %s\n" + +#: g10/trustdb.c:919 +msgid "checking the trustdb\n" +msgstr "\"Trust-DB\" wird berprft\n" + +#: g10/trustdb.c:1748 +#, c-format +msgid "public key of ultimately trusted key %08lX not found\n" +msgstr "" +"ff.Schlssel des uneingeschrnkt vertrautem Schlssel %08lX nicht gefunden\n" + +#: g10/trustdb.c:1854 +#, c-format +msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" +msgstr "" +"berprfen, Tiefe %d, unterschrieben =%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" + +#: g10/verify.c:108 +msgid "" +"the signature could not be verified.\n" +"Please remember that the signature file (.sig or .asc)\n" +"should be the first file given on the command line.\n" +msgstr "" +"Die Unterschrift konnte nicht berprft werden.\n" +"Denken Sie daran, da die Datei mit der Unterschrift (.sig oder .asc)\n" +"als erster in der Kommandozeile stehen sollte.\n" + +#: g10/verify.c:173 +#, c-format +msgid "input line %u too long or missing LF\n" +msgstr "Eingabezeile %u ist zu lang oder es fehlt ein LF\n" + +#: g10/skclist.c:129 g10/skclist.c:185 +msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" +msgstr "" +"Schlssel ist nicht als unsicher gekennzeichnet - er ist nur mit einem\n" +"echten Zufallsgenerator verwendbar\n" + +#: g10/skclist.c:157 +#, c-format +msgid "skipped `%s': duplicated\n" +msgstr "bersprungen '%s': doppelt\n" + +#: g10/skclist.c:164 g10/skclist.c:172 +#, c-format +msgid "skipped `%s': %s\n" +msgstr "bersprungen '%s': %s\n" + +#: g10/skclist.c:168 +msgid "skipped: secret key already present\n" +msgstr "bersprungen: geheimer Schlssel bereits vorhanden\n" + +#: g10/skclist.c:179 +#, c-format +msgid "" +"skipped `%s': this is a PGP generated ElGamal key which is not secure for " +"signatures!\n" +msgstr "" +"'%s bersprungen: Dies ist ein durch PGP erzeugter ElGamal-Schlssel. Das " +"ist fr Signaturen NICHT sicher genug!\n" + +#. do not overwrite +#: g10/openfile.c:84 +#, c-format +msgid "File `%s' exists. " +msgstr "Datei '%s' existiert bereits. " + +#: g10/openfile.c:86 +msgid "Overwrite (y/N)? " +msgstr "berschreiben (j/N)? " + +#: g10/openfile.c:119 +#, c-format +msgid "%s: unknown suffix\n" +msgstr "%s: unbekannte Dateinamenerweiterung\n" + +#: g10/openfile.c:141 +msgid "Enter new filename" +msgstr "Neuen Dateinamen eingeben" + +#: g10/openfile.c:184 +msgid "writing to stdout\n" +msgstr "Schreiben auf die Standardausgabe\n" + +#: g10/openfile.c:273 +#, c-format +msgid "assuming signed data in `%s'\n" +msgstr "die unterzeichneten Daten sind wohl in '%s'\n" + +#: g10/openfile.c:326 +#, c-format +msgid "new configuration file `%s' created\n" +msgstr "Neue Konfigurationsdatei `%s' erstellt\n" + +#: g10/openfile.c:353 +#, c-format +msgid "%s: can't create directory: %s\n" +msgstr "%s: Verzeichnis kann nicht erzeugt werden: %s\n" + +#: g10/openfile.c:356 +#, c-format +msgid "%s: directory created\n" +msgstr "%s: Verzeichnis erzeugt\n" + +#: g10/encr-data.c:91 +msgid "" +"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" +msgstr "" +"Warnung: Botschaft wurde mit einem unsicheren Schlssel verschlsselt.\n" + +#: g10/encr-data.c:98 +msgid "problem handling encrypted packet\n" +msgstr "Problem beim Bearbeiten des verschlsselten Pakets\n" + +#: g10/seskey.c:52 +msgid "weak key created - retrying\n" +msgstr "Unsicherer Schlssel erzeugt - neuer Versuch\n" + +#: g10/seskey.c:57 +#, c-format +msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" +msgstr "" +"Trotz %d-fachen Versuch konnte die Erzeugung eines unsicheren Schlssels fr " +"sym.Verschlsselung nicht vermieden werden!\n" + +#: g10/seskey.c:200 +msgid "DSA requires the use of a 160 bit hash algorithm\n" +msgstr "DSA bentigt einen 160-bit Hash Algorithmus\n" + +#: g10/delkey.c:120 g10/delkey.c:127 +msgid "(unless you specify the key by fingerprint)\n" +msgstr "(es sei denn, Sie geben den Schlssel mittels Fingerprint an)\n" + +#: g10/delkey.c:126 +msgid "can't do that in batchmode without \"--yes\"\n" +msgstr "Dies kann im Batchmodus ohne \"--yes\" nicht durchgefhrt werden.\n" + +#: g10/delkey.c:138 +msgid "Delete this key from the keyring? " +msgstr "Diesen Schlssel aus dem Schlsselbund lschen? " + +#: g10/delkey.c:146 +msgid "This is a secret key! - really delete? " +msgstr "Dies ist ein privater Schlssel! - Wirklich lschen? " + +#: g10/delkey.c:156 +#, c-format +msgid "deleting keyblock failed: %s\n" +msgstr "lschen des Schlsselblocks fehlgeschlagen: %s\n" + +#: g10/delkey.c:166 +msgid "ownertrust information cleared\n" +msgstr "Der \"Ownertrust\" wurde gelscht\n" + +#: g10/delkey.c:194 +#, c-format +msgid "there is a secret key for public key \"%s\"!\n" +msgstr "" +"Es gibt einen privaten Schlssel zu diesem ffentlichen Schlssel \"%s\"!\n" + +#: g10/delkey.c:196 +msgid "use option \"--delete-secret-keys\" to delete it first.\n" +msgstr "" +"Verwenden Sie zunchst das Kommando \"--delete-secret-key\", um ihn zu " +"entfernen.\n" + +#: g10/helptext.c:47 +msgid "" +"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." +msgstr "" +"Sie mssen selbst entscheiden, welchen Wert Sie hier eintragen; dieser Wert\n" +"wird niemals an eine dritte Seite weitergegeben. Wir brauchen diesen Wert,\n" +"um das \"Netz des Vertrauens\" aufzubauen. Dieses hat nichts mit dem\n" +"(implizit erzeugten) \"Netz der Zertifikate\" zu tun." + +#: g10/helptext.c:53 +msgid "" +"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" +msgstr "" +"Um das Web-of-Trust aufzubauen mu GnuPG wissen, welchen Schlsseln\n" +"uneingeschrnkt vertraut wird. Das sind blicherweise die Schlssel\n" +"auf deren geheimen Schlssel Sie Zugruff haben.\n" +"Antworten Sie mit \"yes\" um diesen Schlssel uneingeschrnkt zu vertrauen\n" + +#: g10/helptext.c:60 +msgid "If you want to use this revoked key anyway, answer \"yes\"." +msgstr "" +"Wenn Sie diesen widerrufenen Schlssel trotzdem benutzen wollen,\n" +"so antworten Sie mit \"ja\"." + +#: g10/helptext.c:64 +msgid "If you want to use this untrusted key anyway, answer \"yes\"." +msgstr "" +"Wenn Sie diesen nicht vertrauenswrdigen Schlssel trotzdem benutzen " +"wollen,\n" +"so antworten Sie mit \"ja\"." + +#: g10/helptext.c:68 +msgid "" +"Enter the user ID of the addressee to whom you want to send the message." +msgstr "Geben Sie die User-ID dessen ein, dem Sie die Botschaft senden wollen." + +#: g10/helptext.c:72 +msgid "" +"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." +msgstr "" +"Whlen Sie die zu verwendende Methode aus.\n" +"\n" +"DSA (alias DSS) bedeutet \"digital signature algorithm\" (Digitales\n" +" Unterschrift-Verfahren). Es kann nur zum Unterschreiben und Beglaubigen\n" +" benutzt werden. Dies ist das empfohlene Verfahren, da dessen berprfung\n" +" wesentlich schneller abluft, als die von \"ElGamal\".\n" +"\n" +"ElGamal ist ein Verfahren fr Unterschrift, Beglaubigung und " +"Verschlsselung\n" +" OpenPGP unterscheidet zwischen zwei Arten von ElGamal: eines nur zum\n" +" Unterschreiben/Beglaubigen und eines zustzlich zum Verschlsseln.\n" +" Eigentlich sind diese Arten identisch; allerdings mssen einige Parameter\n" +" auf eine besondere Art gewhlt werden, um einen sicheren Schlssel fr\n" +" Unterschriften zu erzeugen. Dieses Programm macht dies zwar so, aber " +"andere\n" +" Programme sind laut der OpenPGP-Spezifikation nicht verpflichtet, die\n" +" zweite Art (die mit zustzlichem Verschlsseln) zu verstehen.\n" +"\n" +"Der Hauptschlssel (\"primary Key\") mu auf jeden Fall zum Unterschreiben " +"fhig\n" +"sein. Deshalb kann ein nur-Verschlssel-ElGamal-Schlssel dafr nicht\n" +"verwendet werden." + +#: g10/helptext.c:92 +msgid "" +"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." +msgstr "" +"Obwohl diese Schlssel in RFC 2440 definiert sind, ist ihre Verwendung " +"nicht\n" +"empfohlen. Sie werden nmlich nicht von allen Programmen untersttzt.\n" +"Auerdem sind damit ezeugte Unterschriften recht gro und ihre berprfung\n" +"ist langsam." + +#: g10/helptext.c:98 +msgid "" +"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." +msgstr "" +"Normalerweise ist es nicht gut, denselben Schlssel zum unterschreiben\n" +"und verschlsseln zu nutzen. Dieses Verfahren sollte in speziellen\n" +"Anwendungsgebiten benutzt werden. Bitte lassen Sie sich zuerst von \n" +"einem Sicherheistexperten beraten." + +#: g10/helptext.c:105 +msgid "Enter the size of the key" +msgstr "Whlen Sie die gewnschte Schlssellnge" + +#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 +#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 +msgid "Answer \"yes\" or \"no\"" +msgstr "Geben Sie \"ja\" oder \"nein\" ein" + +#: g10/helptext.c:119 +msgid "" +"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." +msgstr "" +"Geben Sie den bentigten Wert so an, wie er im Prompt erscheint.\n" +"Es ist zwar mglich ein \"ISO\"-Datum (JJJJ-MM-DD) einzugeben, aber man\n" +"erhlt dann ggfs. keine brauchbaren Fehlermeldungen - stattdessen versucht\n" +"der Rechner den Wert als Intervall (von-bis) zu deuten." + +#: g10/helptext.c:131 +msgid "Enter the name of the key holder" +msgstr "Geben Sie den Namen des Schlsselinhabers ein" + +#: g10/helptext.c:136 +msgid "please enter an optional but highly suggested email address" +msgstr "" +"Geben Sie eine E-Mail-Adresse ein. Dies ist zwar nicht unbedingt notwendig,\n" +"aber sehr empfehlenswert." + +#: g10/helptext.c:140 +msgid "Please enter an optional comment" +msgstr "Geben Sie - bei Bedarf - einen Kommentar ein" + +#: g10/helptext.c:145 +msgid "" +"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." +msgstr "" +"N um den Namen zu ndern.\n" +"K um den Kommentar zu ndern.\n" +"E um die E-Mail-Adresse zu ndern.\n" +"F um mit der Schlsselerzeugung fortzusetzen.\n" +"B um die Schlsselerzeugung abbrechen." + +#: g10/helptext.c:154 +msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." +msgstr "" +"Geben Sie \"ja\" (oder nur \"j\") ein, um den Unterschlssel zu erzeugen." + +#: g10/helptext.c:162 +msgid "" +"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\"." +msgstr "" +"Wenn Sie die User-ID eines Schlssels beglaubigen wollen, sollten Sie " +"zunchst\n" +"sicherstellen, da der Schlssel demjenigen gehrt, der in der User-ID " +"genannt\n" +"ist. Fr Dritte ist es hilfreich zu wissen, wie gut diese Zuordnung " +"berprft\n" +"wurde.\n" +"\n" +"\"0\" zeigt, da Sie keine bestimmte Aussage ber die Sorgfalt der \n" +" Schlsselzuordnung machen.\n" +"\n" +"\"1\" Sie glauben, da der Schlssel der benannten Person gehrt,\n" +" aber Sie konnten oder nahmen die berpfung berhaupt nicht vor.\n" +" Dies ist hilfreich fr eine \"persona\"-berprfung, wobei man den\n" +" Schlssel eines Pseudonym-Trgers beglaubigt\n" +"\n" +"\"2\" Sie nahmen eine flchtige berprfung vor. Das heisst Sie haben z.B.\n" +" den Schlsselfingerabdruck kontrolliert und die User-ID des Schlssels\n" +" anhand des Fotos geprft.\n" +"\n" +"\"3\" Sie haben eine ausfhrlich Kontrolle des Schlssels vorgenommen.\n" +" Das kann z.B. die Kontrolle des Schlsselfingerabdrucks mit dem\n" +" Schlsselinhaber persnlich vorgenommen haben; da Sie die User-ID des\n" +" Schlssel anhand einer schwer zu flschenden Urkunde mit Foto (wie z.B.\n" +" einem Pa) abgeglichen haben und schliesslich per E-Mail-Verkehr die\n" +" E-Mail-Adresse als zum Schlsselbesitzer gehrig erkannt haben.\n" +"\n" +"Beachten Sie, da diese Beispiele fr die Antworten 2 und 3 *nur* Beispiele " +"sind.\n" +"Schluendlich ist es Ihre Sache, was Sie unter \"flchtig\" oder " +"\"ausfhrlich\"\n" +"verstehen, wenn Sie Schlssel Dritter beglaubigen.\n" +"\n" +"Wenn Sie nicht wissen, wie Sie antworten sollen, whlen Sie \"0\"." + +#: g10/helptext.c:200 +msgid "Answer \"yes\" is you want to sign ALL the user IDs" +msgstr "Geben Sie \"ja\" (oder nur \"j\") ein, um alle User-IDs zu beglaubigen" + +#: g10/helptext.c:204 +msgid "" +"Answer \"yes\" if you really want to delete this user ID.\n" +"All certificates are then also lost!" +msgstr "" +"Geben Sie \"ja\" (oder nur \"j\") ein, um diese User-ID zu LSCHEN.\n" +"Alle Zertifikate werden dann auch weg sein!" + +#: g10/helptext.c:209 +msgid "Answer \"yes\" if it is okay to delete the subkey" +msgstr "" +"Geben Sie \"ja\" (oder nur \"j\") ein, um diesen Unterschlssel zu lschen" + +#: g10/helptext.c:214 +msgid "" +"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." +msgstr "" +"Dies ist eine gltige Beglaubigung fr den Schlssel. Es ist normalerweise\n" +"unntig sie zu lschen. Sie ist mglicherweise sogar notwendig, um einen\n" +"Trust-Weg zu diesem oder einem durch diesen Schlssel beglaubigten " +"Schlssel\n" +"herzustellen." + +#: g10/helptext.c:219 +msgid "" +"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." +msgstr "" +"Diese Beglaubigung kann nicht geprft werden, da Sie den passenden " +"Schlssel\n" +"nicht besitzen. Sie sollten die Lschung der Beglaubigung verschieben, bis\n" +"sie wissen, welcher Schlssel verwendet wurde. Denn vielleicht wrde genau\n" +"diese Beglaubigung den \"Trust\"-Weg kompletieren." + +#: g10/helptext.c:225 +msgid "" +"The signature is not valid. It does make sense to remove it from\n" +"your keyring." +msgstr "" +"Diese Beglaubigung ist ungltig. Es ist sinnvoll sie aus Ihrem\n" +"Schlsselbund zu entfernen." + +#: g10/helptext.c:229 +msgid "" +"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." +msgstr "" +"Diese Beglaubigung bindet die User-ID an den Schlssel. Normalerweise ist\n" +"es nicht gut, solche Beglaubigungen zu entfernen. Um ehrlich zu sein:\n" +"Es knnte dann sein, da GnuPG diesen Schlssel gar nicht mehr benutzen " +"kann.\n" +"Sie sollten diese Eigenbeglaubigung also nur dann entfernen, wenn sie aus\n" +"irgendeinem Grund nicht gltig ist und eine zweite Beglaubigung verfgbar " +"ist." + +#: g10/helptext.c:237 +msgid "" +"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" +msgstr "" +"ndern der Voreinstellung aller User-IDs (oder nur der ausgewhlten)\n" +"auf die aktuelle Liste der Voreinstellung. Die Zeitangaben aller " +"betroffenen\n" +"Eigenbeglaubigungen werden um eine Sekunde vorgestellt.\n" + +#: g10/helptext.c:244 +msgid "Please enter the passhrase; this is a secret sentence \n" +msgstr "Bitte geben Sie das Mantra ein. Dies ist ein geheimer Satz \n" + +#: g10/helptext.c:250 +msgid "Please repeat the last passphrase, so you are sure what you typed in." +msgstr "" +"Um sicher zu gehen, da Sie sich bei der Eingabe des Mantras nicht\n" +"vertippt haben, geben Sie diese bitte nochmal ein. Nur wenn beide Eingaben\n" +"bereinstimmen, wird das Mantra akzeptiert." + +#: g10/helptext.c:254 +msgid "Give the name of the file to which the signature applies" +msgstr "" +"Geben Sie den Namen der Datei an, zu dem die abgetrennte Unterschrift gehrt" + +#: g10/helptext.c:259 +msgid "Answer \"yes\" if it is okay to overwrite the file" +msgstr "Geben Sie \"ja\" ein, wenn Sie die Datei berschreiben mchten" + +#: g10/helptext.c:264 +msgid "" +"Please enter a new filename. If you just hit RETURN the default\n" +"file (which is shown in brackets) will be used." +msgstr "" +"Geben Sie bitte einen neuen Dateinamen ein. Falls Sie nur die\n" +"Eingabetaste bettigen, wird der (in Klammern angezeigte) Standarddateiname\n" +"verwendet." + +#: g10/helptext.c:270 +msgid "" +"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" +msgstr "" +"Sie sollten einen Grund fr die Zertifizierung angeben. Je nach\n" +"Zusammenhang knnen Sie aus dieser Liste auswhlen:\n" +" \"Schlssel wurde kompromitiert\"\n" +" Falls Sie Grund zu der Annahme haben, da nicht berechtigte Personen\n" +" Zugriff zu Ihrem geheimen Schlssel hatten\n" +" \"Schlssel ist berholt\"\n" +" Falls Sie diesen Schlssel durch einem neuen ersetzt haben.\n" +" \"Schlssel wird nicht mehr benutzt\"\n" +" Falls Sie diesen Schlssel zurckgezogen haben.\n" +" \"User-ID ist nicht mehr gltig\"\n" +" Um bekanntzugeben, da die User-ID nicht mehr benutzt werden soll.\n" +" So weist man normalerweise auf eine ungltige E-Mailadresse hin.\n" + +#: g10/helptext.c:286 +msgid "" +"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" +msgstr "" +"Wenn Sie mchten, knnen Sie hier einen Text eingeben, der darlegt, warum\n" +"Sie diesen Widerruf herausgeben. Der Text sollte mglichst knapp sein.\n" +"Eine Leerzeile beendet die Eingabe.\n" + +#: g10/helptext.c:301 +msgid "No help available" +msgstr "Keine Hilfe vorhanden." + +#: g10/helptext.c:309 +#, c-format +msgid "No help available for `%s'" +msgstr "Keine Hilfe fr '%s' vorhanden." + +#: g10/keydb.c:182 +#, c-format +msgid "error creating keyring `%s': %s\n" +msgstr "Fehler beim Erzeugen des Schlsselbundes `%s': %s\n" + +#: g10/keydb.c:189 +#, c-format +msgid "keyring `%s' created\n" +msgstr "Schlsselbund `%s' erstellt\n" + +#: g10/keydb.c:608 +#, c-format +msgid "failed to rebuild keyring cache: %s\n" +msgstr "Schlsselbund-Cache konnte nicht neu erzeugt werden: %s\n" + +#: g10/keyring.c:1231 +msgid "WARNING: 2 files with confidential information exists.\n" +msgstr "Warnung: Zwei Dateien mit vertraulichem Inhalt vorhanden.\n" + +#: g10/keyring.c:1233 +#, c-format +msgid "%s is the unchanged one\n" +msgstr "%s ist der Unvernderte\n" + +#: g10/keyring.c:1234 +#, c-format +msgid "%s is the new one\n" +msgstr "%s ist der Neue\n" + +#: g10/keyring.c:1235 +msgid "Please fix this possible security flaw\n" +msgstr "Bitte diesen potentiellen Sicherheitsmangel beseitigen\n" + +#: g10/keyring.c:1351 +#, c-format +msgid "checking keyring `%s'\n" +msgstr "Prfen des Schlsselbundes `%s'\n" + +#: g10/keyring.c:1382 +#, fuzzy, c-format +msgid "%lu keys checked so far (%lu signatures)\n" +msgstr "%lu Schlssel geprft (%lu Beglaubigungen)\n" + +#: g10/keyring.c:1393 +#, c-format +msgid "%lu keys checked (%lu signatures)\n" +msgstr "%lu Schlssel geprft (%lu Beglaubigungen)\n" + +#: g10/keyring.c:1458 +#, c-format +msgid "%s: keyring created\n" +msgstr "%s: Schlsselbund erstellt\n" + +#~ msgid "preference %c%lu is not valid\n" +#~ msgstr "Voreinstellung %c%lu ist nicht gltig\n" + +#, fuzzy +#~ msgid " (default)" +#~ msgstr "Daten entschlsseln (Voreinstellung)" + +#~ msgid "requesting key %08lX from %s\n" +#~ msgstr "Schlssel %08lX wird von %s angefordert\n" + +#~ msgid "can't get key from keyserver: %s\n" +#~ msgstr "Schlssel ist beim Schlsselserver nicht erhltlich: %s\n" + +#~ msgid "error sending to `%s': %s\n" +#~ msgstr "Fehler beim Senden an `%s': %s\n" + +#~ msgid "success sending to `%s' (status=%u)\n" +#~ msgstr "Senden an `%s' erfolgreich (status=%u)\n" + +#~ msgid "failed sending to `%s': status=%u\n" +#~ msgstr "Senden an `%s' erfolglos (status=%u)\n" + +#~ msgid "this keyserver is not fully HKP compatible\n" +#~ msgstr "Dieser Schlsselserver ist nicht vollstndig HKP kompatibel\n" + +#~ msgid "searching for \"%s\" from HKP server %s\n" +#~ msgstr "suche nach \"%s\" auf HKP-Server %s\n" + +#~ msgid "can't search keyserver: %s\n" +#~ msgstr "kann Schlsselserver nicht durchsuchen: %s\n" + +#~ msgid "%lu keys so far checked (%lu signatures)\n" +#~ msgstr "%lu Schlssel bislang geprft (%lu Beglaubigungen)\n" + +#~ msgid "no values for group \"%s\"\n" +#~ msgstr "Keine Werte fr Gruppe \"%s\"\n" + +#, fuzzy +#~ msgid "" +#~ "you have to start GnuPG again, so it can read the new configuration file\n" +#~ msgstr "" +#~ "Sie mssen GnuPG noch einmal starten, damit es die neue " +#~ "Konfigurationsdatei liest\n" + +#~ msgid "changing permission of `%s' failed: %s\n" +#~ msgstr "ndern der Zugriffsrechte fr `%s' ist fehlgeschlagen: %s\n" + +#~ msgid "Fingerprint:" +#~ msgstr "Fingerabdruck:" + +#~ msgid " Fingerprint:" +#~ msgstr " Fingerabdruck:" + +#~ msgid "|NAME=VALUE|use this notation data" +#~ msgstr "|NAME=WERT|diese \"notation\"-Daten verwenden" + +#~ msgid "" +#~ "the first character of a notation name must be a letter or an underscore\n" +#~ msgstr "" +#~ "Das erste Zeichen eines \"notation\"-Namens mu ein Buchstabe oder\n" +#~ "ein Unterstrich sein\n" + +#~ msgid "dots in a notation name must be surrounded by other characters\n" +#~ msgstr "" +#~ "Punkte in einem \"notation\"-Namen mssen von anderen Zeichen umgeben " +#~ "sein\n" + +#~ msgid "" +#~ "WARNING: This key already has a photo ID.\n" +#~ " Adding another photo ID may confuse some versions of PGP.\n" +#~ msgstr "" +#~ "WARNUNG: Dieser Schlssel besitzt bereits eine Foto-ID.\n" +#~ " Ein hinzugefgte Foto-ID knnte einige Versionen von PGP " +#~ "verwirren.\n" + +#~ msgid "You may only have one photo ID on a key.\n" +#~ msgstr "Sie knnen nur eine Foto-ID fr diesen Schlssel haben.\n" + +#~ msgid "Are you sure you still want to sign it?\n" +#~ msgstr "Sind Sie sicher, da Sie dies wiklich unterschreiben mchten?\n" + +#~ msgid " Are you sure you still want to sign it?\n" +#~ msgstr " Sind Sie sicher, da Sie dies immer noch unterschreiben wollen?\n" + +#~ msgid "Really sign? (y/N) " +#~ msgstr "Wirklich unterschreiben? (j/N) " + +#~ msgid "key %08lX: our copy has no self-signature\n" +#~ msgstr "Schlssel %08lX: Unsere Kopie hat keine Eigenbeglaubigung\n" + +#~ msgid "Do you really need such a large keysize? " +#~ msgstr "Brauchen Sie wirklich einen derartig langen Schlssel? " + +#~ msgid " signed by %08lX at %s\n" +#~ msgstr " beglaubigt durch %08lX um %s\n" + +#~ msgid "--delete-secret-key user-id" +#~ msgstr "--delete-secret-key User-ID" + +#~ msgid "--delete-key user-id" +#~ msgstr "--delete-key User-ID" + +#~ msgid "--delete-secret-and-public-key user-id" +#~ msgstr "--delete-secret-and-public-key User-ID" + +#~ msgid "Enter the user ID: " +#~ msgstr "Geben Sie die User-ID ein: " + +#~ msgid "skipped: public key already set with --encrypt-to\n" +#~ msgstr "" +#~ "bersprungen: ffentlicher Schlssel bereits mittels --encrypt-to " +#~ "gesetzt\n" + +#~ msgid "" +#~ "\n" +#~ "WARNING: This is a PGP2-style key\n" +#~ msgstr "WARNUNG: '%s' ist eine leere Datei.\n" + +# valid user replies (not including 1..4) +#~ msgid "sSmMqQ" +#~ msgstr "sSmMqQ" + +#~ msgid "no keyserver known (use option --keyserver)\n" +#~ msgstr "Kein Schlsselserver bekannt (Option --keyserver verwenden)\n" + +#~ msgid "%s: not a valid key ID\n" +#~ msgstr "%s: Dies ist keine gltige Schlssel-ID\n" + +#~ msgid "duplicate (short) key ID %08lX\n" +#~ msgstr "ffentlicher Schlssel ist %08lX\n" + +#~ msgid "%lu key(s) to refresh\n" +#~ msgstr "\t%lu Schlssel mit Fehlern\n" + +#~ msgid "|[NAMES]|check the trust database" +#~ msgstr "|[NAMEN]|berprfen der \"Trust\"-Datenbank" + +#~ msgid "" +#~ "Could not find a valid trust path to the key. Let's see whether we\n" +#~ "can assign some missing owner trust values.\n" +#~ "\n" +#~ msgstr "" +#~ "Fr diesen Schlssel konnte kein gltiger \"Trust Path\" gefunden " +#~ "werden.\n" +#~ "Mal sehen, ob wir sonst irgendwie ein paar fehlende \"Owner trust\" " +#~ "Werte \n" +#~ "ermitteln knnen.\n" +#~ "\n" + +#~ msgid "" +#~ "No path leading to one of our keys found.\n" +#~ "\n" +#~ msgstr "" +#~ "Kein Pfad fhrt zu einem unserer Schlsseln.\n" +#~ "\n" + +#~ msgid "" +#~ "No certificates with undefined trust found.\n" +#~ "\n" +#~ msgstr "" +#~ "Keine Zertifikate mit undefiniertem Vertrauen gefunden.\n" +#~ "\n" + +#~ msgid "" +#~ "No trust values changed.\n" +#~ "\n" +#~ msgstr "" +#~ "Keine \"trust\" Werte gendert.\n" +#~ "\n" + +#~ msgid "%08lX: no info to calculate a trust probability\n" +#~ msgstr "" +#~ "%08lX: Keine Infos zur Berechnung der Vertrauenswahrscheinlichkeit " +#~ "vorgefunden\n" + +#~ msgid "%s: error checking key: %s\n" +#~ msgstr "%s: Fehler beim Prfen des Schlssels: %s\n" + +#~ msgid "too many entries in unk cache - disabled\n" +#~ msgstr "zu viele Eintrge im unk-Lager - abgeschaltet\n" + +#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" +#~ msgstr "" +#~ "Geheimer Schlssel %08lX nicht importiert (%s verwenden, um das zu " +#~ "ermglichen)\n" + +#~ msgid "update of trustdb failed: %s\n" +#~ msgstr "nderung der \"Trust-DB\" fehlgeschlagen: %s\n" + +#~ msgid "assuming bad MDC due to an unknown critical bit\n" +#~ msgstr "" +#~ "Vermutlich ist das Siegel (MDC) BESCHDIGT (wegen unbekanntem \"critical " +#~ "bit\")\n" + +#~ msgid "error reading dir record for LID %lu: %s\n" +#~ msgstr "Fehler beim Lesen des Dir-Satzes fr LID %lu: %s\n" + +#~ msgid "lid %lu: expected dir record, got type %d\n" +#~ msgstr "lid %lu: Dir-Satz erwartet, aber es kam Typ %d\n" + +#~ msgid "no primary key for LID %lu\n" +#~ msgstr "Kein Hauptschlssel fr LID %lu\n" + +#~ msgid "error reading primary key for LID %lu: %s\n" +#~ msgstr "Fehler beim Lesen den Hauptschlssels der LID %lu: %s\n" + +#~ msgid "get_dir_record: search_record failed: %s\n" +#~ msgstr "get_dir_record: search_record fehlgeschlagen: %s\n" + +#~ msgid "key %08lX: query record failed\n" +#~ msgstr "Schlssel %08lX: Satzabfrage fehlgeschlagen\n" + +#~ msgid "key %08lX: already in trusted key table\n" +#~ msgstr "Schlssel %08lX: Ist bereits in geheimer Schlsseltabelle\n" + +#~ msgid "NOTE: secret key %08lX is NOT protected.\n" +#~ msgstr "HINWEIS: Geheimer Schlssel %08lX ist NICHT geschtzt.\n" + +#~ msgid "key %08lX: secret and public key don't match\n" +#~ msgstr "" +#~ "Schlssel %08lX: geheimer und ffentlicher Schlssel passen nicht " +#~ "zusammen.\n" + +#~ msgid "enumerate secret keys failed: %s\n" +#~ msgstr "enum_secret_keys fehlgeschlagen: %s\n" + +#~ msgid "key %08lX.%lu: Good subkey binding\n" +#~ msgstr "Schlssel %08lX.%lu: Korrekte Unterschlssel-Anbindung\n" + +#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" +#~ msgstr "Schlssel %08lX.%lu: Ungltige Unterschlssel-Anbindung: %s\n" + +#~ msgid "key %08lX.%lu: Valid key revocation\n" +#~ msgstr "Schlssel %08lX.%lu: Gltiger Schlsselwiderruf\n" + +#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" +#~ msgstr "Schlssel %08lX.%lu: Ungltiger Schlsselwiderruf: %s\n" + +#~ msgid "Good self-signature" +#~ msgstr "Korrekte Eigenbeglaubigung" + +#~ msgid "Invalid self-signature" +#~ msgstr "Ungltige Eigenbeglaubigung" + +#~ msgid "Valid user ID revocation skipped due to a newer self signature" +#~ msgstr "" +#~ "Gltiger User-ID-Widerruf ignoriert, da eine neuere Eigenbeglaubigung " +#~ "vorliegt" + +#~ msgid "Valid user ID revocation" +#~ msgstr "Gltiger User-ID-Widerruf" + +#~ msgid "Invalid user ID revocation" +#~ msgstr "Ungltiger User-ID-Widerruf" + +#~ msgid "Valid certificate revocation" +#~ msgstr "Gltiger Zerifikat-Widerruf" + +#~ msgid "Good certificate" +#~ msgstr "Korrektes Zertifikat" + +#~ msgid "Invalid certificate revocation" +#~ msgstr "Ungltiger Zertifikatswiderruf" + +#~ msgid "Invalid certificate" +#~ msgstr "Ungltiges Zertifikat" + +#~ msgid "sig record %lu[%d] points to wrong record.\n" +#~ msgstr "Signatursatz %lu[%d] zeigt auf falschen Satz.\n" + +#~ msgid "duplicated certificate - deleted" +#~ msgstr "Doppelte Zertifikate - entfernt" + +#~ msgid "tdbio_search_dir failed: %s\n" +#~ msgstr "tdbio_search_dir fehlgeschlagen: %s\n" + +#~ msgid "lid ?: insert failed: %s\n" +#~ msgstr "lid ?: Einfgen fehlgeschlagen: %s\n" + +#~ msgid "lid %lu: insert failed: %s\n" +#~ msgstr "lid %lu: Einfgen fehlgeschlagen: %s\n" + +#~ msgid "lid %lu: inserted\n" +#~ msgstr "lid %lu: eingefgt\n" + +#~ msgid "error reading dir record: %s\n" +#~ msgstr "Fehler beim Lesen des Verz.Satzes: %s\n" + +#~ msgid "\t%lu keys inserted\n" +#~ msgstr "\t%lu Schlssel eingefgt\n" + +#~ msgid "enumerate keyblocks failed: %s\n" +#~ msgstr "enumerate Schlsselblock fehlgeschlagen: %s\n" + +#~ msgid "lid %lu: dir record w/o key - skipped\n" +#~ msgstr "lid %lu: Dir-Satz ohne Schlssel - bergangen\n" + +#~ msgid "\t%lu due to new pubkeys\n" +#~ msgstr "\t%lu wegen neuer Schlssel\n" + +#~ msgid "\t%lu keys skipped\n" +#~ msgstr "\t%lu Schlssel bersprungen\n" + +#~ msgid "\t%lu keys updated\n" +#~ msgstr "\t%lu Schlssel gendert\n" + +#~ msgid "Ooops, no keys\n" +#~ msgstr "Huch, keine Schlssel\n" + +#~ msgid "Ooops, no user IDs\n" +#~ msgstr "Huch, keine User-IDs\n" + +#~ msgid "check_trust: search dir record failed: %s\n" +#~ msgstr "check_trust: Suche nach Dir-Satz fehlgeschlagen: %s\n" + +#~ msgid "key %08lX: insert trust record failed: %s\n" +#~ msgstr "Schlssel %08lX: 'trust record' einfgen fehlgeschlagen: %s\n" + +#~ msgid "key %08lX.%lu: inserted into trustdb\n" +#~ msgstr "Schlssel %08lX.%lu: in \"trustdb\" eingefgt\n" + +#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" +#~ msgstr "" +#~ "Schlssel %08lX.%lu: wurde in der Zukunft erzeugt (Zeitreise oder Uhren " +#~ "stimmen nicht berein)\n" + +#~ msgid "key %08lX.%lu: expired at %s\n" +#~ msgstr "Schlssel %08lX.%lu: verfallen am %s\n" + +#~ msgid "key %08lX.%lu: trust check failed: %s\n" +#~ msgstr "Schlssel %08lX.%lu: Vertrauensprfung fehlgeschlagen: %s\n" + +#~ msgid "user '%s' not found: %s\n" +#~ msgstr "Benutzer '%s' nicht gefunden: %s\n" + +#~ msgid "problem finding '%s' in trustdb: %s\n" +#~ msgstr "Problem, '%s' in der Trust-DB zu finden: %s\n" + +#~ msgid "user '%s' not in trustdb - inserting\n" +#~ msgstr "User '%s' ist nicht in der 'Trust'-Datenbank - wird eingefgt\n" + +#~ msgid "failed to put '%s' into trustdb: %s\n" +#~ msgstr "konnte '%s' nicht in die 'Trust'-Datenbank hineintun: %s\n" + +#~ msgid "too many random bits requested; the limit is %d\n" +#~ msgstr "Zu viele Zufallswerte angefordert: Die Grenze liegt bei %d\n" + +#~ msgid "For info see http://www.gnupg.org" +#~ msgstr "Weitere Infos: siehe http://www.gnupg.org" + +#~ msgid "Do you really want to create a sign and encrypt key? " +#~ msgstr "" +#~ "Mchten Sie wirklich einen Unterschriften-/Verschlsselungschlssel " +#~ "erzeugen? " + +#~ msgid "%s: user not found: %s\n" +#~ msgstr "%s: Benutzer nicht gefunden: %s\n" + +#~ msgid "certificate read problem: %s\n" +#~ msgstr "Zertifikat Leseproblem: %s\n" + +#~ msgid "can't lock keyring `%s': %s\n" +#~ msgstr "kann Schlsselbund `%s' nicht sperren: %s\n" + +#~ msgid "%s: user not found\n" +#~ msgstr "%s: Benutzer nicht gefunden\n" + +#~ msgid "WARNING: can't yet handle long pref records\n" +#~ msgstr "WARNUNG: Lange 'Pref'-Records knnen noch nicht benutzt werden\n" + +#~ msgid "%s: can't create keyring: %s\n" +#~ msgstr "%s: Schlsselbund kann nicht erzeugt werden: %s\n" + +#~ msgid "invalid" +#~ msgstr "ungltig" + +#~ msgid "RSA key cannot be used in this version\n" +#~ msgstr "RSA-Schlssel knnen in dieser Version nicht verwendet werden\n" + +#~ msgid "No key for user ID\n" +#~ msgstr "Kein Schlssel fr User-ID\n" + +#~ msgid "No user ID for key\n" +#~ msgstr "Keine User-ID fr Schlssel\n" + +#~ msgid "no secret key for decryption available\n" +#~ msgstr "kein geheimer Schlssel zur Entschlsselung vorhanden\n" + +#~ msgid " (%d) ElGamal in a v3 packet\n" +#~ msgstr " (%d) ElGamal in einem v3-Paket\n" + +#~ msgid "Key generation can only be used in interactive mode\n" +#~ msgstr "" +#~ "Die Schlsselerzeugung kann nur im interaktiven Modus benutzt werden.\n" diff --git a/scripts/config.guess b/scripts/config.guess new file mode 100755 index 000000000..27d87fa73 --- /dev/null +++ b/scripts/config.guess @@ -0,0 +1,1366 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-11-08' + +# This file 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# This shell variable is my proudest work .. or something. --bje + +set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; +(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) + || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; +dummy=$tmpdir/dummy ; +files="$dummy.c $dummy.o $dummy.rel $dummy" ; +trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $files ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; +unset files' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + eval $set_cc_for_build + cat <<EOF >$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null + if test "$?" = 0 ; then + case `$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + 3-1307) + UNAME_MACHINE="alphaev7" + ;; + esac + fi + rm -f $dummy.s $dummy && rmdir $tmpdir + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy && rmdir $tmpdir + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c && rmdir $tmpdir + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 +rm -f $dummy.c $dummy && rmdir $tmpdir + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + ftp://ftp.gnu.org/pub/gnu/config/ + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/scripts/config.sub b/scripts/config.sub new file mode 100755 index 000000000..c4f0b2f52 --- /dev/null +++ b/scripts/config.sub @@ -0,0 +1,1471 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-11-08' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39 | mipstx39el \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic4x | c4x*) + basic_machine=tic4x-unknown + os=-coff + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/tests/ChangeLog b/tests/ChangeLog new file mode 100644 index 000000000..c6b3b9af1 --- /dev/null +++ b/tests/ChangeLog @@ -0,0 +1,68 @@ +2002-12-04 Werner Koch <wk@gnupg.org> + + * inittests (gpgsm.conf): Fake system time. + +2002-10-31 Neal H. Walfield <neal@g10code.de> + + * Makefile.am (inittests.stamp): Do not set LD_LIBRARY_PATH here. + (TESTS_ENVIRONMENT): Do it here. And also frob $(LIBGCRYPT_LIBS) + and $(PTH_LIBS). + +2002-10-31 Neal H. Walfield <neal@g10code.de> + + * asschk.c (die): New macro. + (read_assuan): If in verbose mode, dump the string that was read. + (write_assuan): Be more verbose on failure. + +2002-09-04 Neal H. Walfield <neal@g10code.de> + + * Makefile.am (inittests.stamp): Do not set LD_LIBRARY_PATH, but + rather prepend it. Be more robust and prefer printf over echo -n. + +2002-09-04 Marcus Brinkmann <marcus@g10code.de> + + * asschk.c (start_server): Close the parent's file descriptors in + the child. + (read_assuan): Variable NREAD removed. Cut off the received line + currectly if more than one line was read. + +2002-09-03 Neal H. Walfield <neal@g10code.de> + + * Makefile.am (inittests.stamp): Construct an LD_LIBRARY_PATH from + LDFLAGS. + +2002-08-09 Werner Koch <wk@gnupg.org> + + * asschk.c (cmd_getenv): New. + (expand_line): Allow / as variable name delimiter. + * sm-sign+verify, sm-verify: Use $srcdir so that a VPATH build works. + + * Makefile.am: Fixes for make dist. + * samplekets/Makefile.am: New. + +2002-08-08 Werner Koch <wk@gnupg.org> + + * asschk.c: Added some new features. + * runtest, inittests: New. + * text-1.txt, text-2.txt, text-3.txt: New. + * text-1.osig.pem, text-1.dsig.pem, text-1.osig-bad.pem: New. + * text-2.osig.pem, text-2.osig-bad.pem: New. + * samplekeys : New directory + * sm-verify, sm-sign+verify: The first test scripts. + +2002-08-06 Werner Koch <wk@gnupg.org> + + * Makefile.am, asschk.c: 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. + + diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 000000000..622b5fe58 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,78 @@ +# Makefile.am -tests makefile for libxtime +# 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 + +GPGSM = ../sm/gpgsm + +# We can't unset a variable here so we unset GPG_AGENT_INFO in runtest +TESTS_ENVIRONMENT = GNUPGHOME=`pwd` LC_ALL=C GPGSM=$(GPGSM) \ + LD_LIBRARY_PATH=$$(seen=0; \ + for i in $(LDFLAGS) $(LIBGCRYPT_LIBS) $(PTH_LIBS); \ + do \ + if echo "$$i" | egrep '^-L' >/dev/null 2>&1; \ + then \ + if test $$seen = 0; \ + then \ + seen=1; \ + else \ + printf ":"; \ + fi; \ + printf "%s" "$${i}" | sed 's/^-L//'; \ + fi; \ + done; \ + if test $$seen != 0 \ + && test x$${LD_LIBRARY_PATH} != x; \ + then \ + printf ":"; \ + fi; \ + printf "%s" "$${LD_LIBRARY_PATH}") $(srcdir)/runtest + +testscripts = sm-sign+verify sm-verify + +EXTRA_DIST = runtest inittests $(testscripts) \ + text-1.txt text-2.txt text-3.txt \ + text-1.osig.pem text-1.dsig.pem text-1.osig-bad.pem \ + text-2.osig.pem text-2.osig-bad.pem \ + samplekeys/32100C27173EF6E9C4E9A25D3D69F86D37A4F939.key \ + samplekeys/cert_g10code_pete1.pem \ + samplekeys/cert_g10code_test1.pem \ + samplekeys/cert_g10code_theo1.pem + +TESTS = $(testscripts) + +CLEANFILES = inittests.stamp x y y z out err + *.lock .\#lk* + +DISTCLEANFILES = pubring.kbx~ random_seed + +noinst_PROGRAMS = asschk + +asschk_SOURCES = asschk.c + + +all-local: inittests.stamp + +clean-local: + srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean + +inittests.stamp: inittests + srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests + echo timestamp >./inittests.stamp + diff --git a/tests/asschk.c b/tests/asschk.c new file mode 100644 index 000000000..83a8ca5af --- /dev/null +++ b/tests/asschk.c @@ -0,0 +1,1059 @@ +/* asschk.c - Assuan Server Checker + * 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 is a simple stand-alone Assuan server test program. We don't + want to use the assuan library because we don't want to hide errors + in that library. + + The script language is line based. Empty lines or lines containing + only white spaces are ignored, line with a hash sign as first non + white space character are treated as comments. + + A simple macro mechanism is implemnted. Macros are expanded before + a line is processed but after comment processing. Macros are only + expanded once and non existing macros expand to the empty string. + A macro is dereferenced by prefixing its name with a dollar sign; + the end of the name is currently indicated by a white space, a + dollar sign or a slash. To use a dollor sign verbatim, double it. + + A macro is assigned by prefixing a statement with the macro name + and an equal sign. The value is assigned verbatim if it does not + resemble a command, otherwise the return value of the command will + get assigned. The command "let" may be used to assign values + unambigiously and it should be used if the value starts with a + letter. + + Conditions are not yes implemented except for a simple evaluation + which yields false for an empty string or the string "0". The + result may be negated by prefixing with a '!'. + + The general syntax of a command is: + + [<name> =] <statement> [<args>] + + If NAME is not specifed but the statement returns a value it is + assigned to the name "?" so that it can be referenced using "$?". + The following commands are implemented: + + let <value> + Return VALUE. + + echo <value> + Print VALUE. + + openfile <filename> + Open file FILENAME for read access and retrun the file descriptor. + + createfile <filename> + Create file FILENAME, open for write access and retrun the file + descriptor. + + pipeserver <program> + Connect to the Assuan server PROGRAM. + + send <line> + Send LINE to the server. + + expect-ok + Expect an OK response from the server. Status and data out put + is ignored. + + expect-err + Expect an ERR response from the server. Status and data out put + is ignored. + + count-status <code> + Initialize the assigned variable to 0 and assign it as an counter for + status code CODE. This command must be called with an assignment. + + quit + Terminate the process. + + quit-if <condition> + Terminate the process if CONDITION evaluates to true. + + fail-if <condition> + Terminate the process with an exit code of 1 if CONDITION + evaluates to true. + + cmpfiles <first> <second> + Returns true when the content of the files FIRST and SECOND match. + + getenv <name> + Return the value of the environment variable NAME. + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +# define ATTR_PRINTF(f,a) __attribute__ ((format (printf,f,a))) +#else +# define ATTR_PRINTF(f,a) +#endif + +#define spacep(p) (*(p) == ' ' || *(p) == '\t') + +#define MAX_LINELEN 2048 + +typedef enum { + LINE_OK = 0, + LINE_ERR, + LINE_STAT, + LINE_DATA, + LINE_END, +} LINETYPE; + +typedef enum { + VARTYPE_SIMPLE = 0, + VARTYPE_FD, + VARTYPE_COUNTER +} VARTYPE; + + +struct variable_s { + struct variable_s *next; + VARTYPE type; + unsigned int count; + char *value; + char name[1]; +}; +typedef struct variable_s *VARIABLE; + + +static void die (const char *format, ...) ATTR_PRINTF(1,2); + + +/* Name of this program to be printed in error messages. */ +static const char *invocation_name; + +/* Talk a bit about what is going on. */ +static int opt_verbose; + +/* Option to ignore the echo command. */ +static int opt_no_echo; + +/* File descriptors used to communicate with the current server. */ +static int server_send_fd = -1; +static int server_recv_fd = -1; + +/* The Assuan protocol limits the line length to 1024, so we can + safely use a (larger) buffer. The buffer is filled using the + read_assuan(). */ +static char recv_line[MAX_LINELEN]; +/* Tell the status of the current line. */ +static LINETYPE recv_type; + +/* This is our variable storage. */ +static VARIABLE variable_list; + + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", invocation_name); + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); + + exit (1); +} + +#define die(format, args...) (die) ("%s: " format, __FUNCTION__ , ##args) + +static void +err (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", invocation_name); + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); +} + +static void * +xmalloc (size_t n) +{ + void *p = malloc (n); + if (!p) + die ("out of core"); + return p; +} + +static void * +xcalloc (size_t n, size_t m) +{ + void *p = calloc (n, m); + if (!p) + die ("out of core"); + return p; +} + +static char * +xstrdup (const char *s) +{ + char *p = xmalloc (strlen (s)+1); + strcpy (p, s); + return p; +} + + +/* Write LENGTH bytes from BUFFER to FD. */ +static int +writen (int fd, const char *buffer, size_t length) +{ + while (length) + { + int nwritten = write (fd, buffer, length); + + if (nwritten < 0) + { + if (errno == EINTR) + continue; + return -1; /* write error */ + } + length -= nwritten; + buffer += nwritten; + } + return 0; /* okay */ +} + + + + +/* Assuan specific stuff. */ + +/* Read a line from FD, store it in the global recv_line, analyze the + type and store that in recv_type. The function terminates on a + communication error. Returns a pointer into the inputline to the + first byte of the arguments. The parsing is very strict to match + excalty what we want to send. */ +static char * +read_assuan (int fd) +{ + static char pending[MAX_LINELEN]; + static size_t pending_len; + size_t nleft = sizeof recv_line; + char *buf = recv_line; + char *p; + + while (nleft > 0) + { + int n; + + if (pending_len) + { + if (pending_len >= nleft) + die ("received line too large"); + memcpy (buf, pending, pending_len); + n = pending_len; + pending_len = 0; + } + else + n = read (fd, buf, nleft); + + if (opt_verbose) + { + int i; + printf ("%s: read \"", __FUNCTION__); + for (i = 0; i < n; i ++) + putc (buf[i], stdout); + printf ("\"\n"); + } + + if (n < 0) + { + if (errno == EINTR) + continue; + die ("reading fd %d failed: %s", fd, strerror (errno)); + } + else if (!n) + die ("received incomplete line on fd %d", fd); + p = buf; + nleft -= n; + buf += n; + + for (; n && *p != '\n'; n--, p++) + ; + if (n) + { + if (n>1) + { + n--; + memcpy (pending, p + 1, n); + pending_len = n; + } + *p = '\0'; + break; + } + } + if (!nleft) + die ("received line too large"); + + p = recv_line; + if (p[0] == 'O' && p[1] == 'K' && (p[2] == ' ' || !p[2])) + { + recv_type = LINE_OK; + p += 3; + } + else if (p[0] == 'E' && p[1] == 'R' && p[2] == 'R' + && (p[3] == ' ' || !p[3])) + { + recv_type = LINE_ERR; + p += 4; + } + else if (p[0] == 'S' && (p[1] == ' ' || !p[1])) + { + recv_type = LINE_STAT; + p += 2; + } + else if (p[0] == 'D' && p[1] == ' ') + { + recv_type = LINE_DATA; + p += 2; + } + else if (p[0] == 'E' && p[1] == 'N' && p[2] == 'D' && !p[3]) + { + recv_type = LINE_END; + p += 3; + } + else + die ("invalid line type (%.5s)", p); + + return p; +} + +/* Write LINE to the server using FD. It is expected that the line + contains the terminating linefeed as last character. */ +static void +write_assuan (int fd, const char *line) +{ + char buffer[1026]; + size_t n = strlen (line); + + if (n > 1024) + die ("line too long for Assuan protocol"); + strcpy (buffer, line); + if (!n || buffer[n-1] != '\n') + buffer[n++] = '\n'; + + if (writen (fd, buffer, n)) + die ("sending line (\"%s\") to %d failed: %s", buffer, fd, + strerror (errno)); +} + + +/* Start the server with path PGMNAME and connect its stdout and + strerr to a newly created pipes; the file descriptors are then + store in the gloabl variables SERVER_SEND_FD and + SERVER_RECV_FD. The initial handcheck is performed.*/ +static void +start_server (const char *pgmname) +{ + int rp[2]; + int wp[2]; + pid_t pid; + + if (pipe (rp) < 0) + die ("pipe creation failed: %s", strerror (errno)); + if (pipe (wp) < 0) + die ("pipe creation failed: %s", strerror (errno)); + + fflush (stdout); + fflush (stderr); + pid = fork (); + if (pid < 0) + die ("fork failed"); + + if (!pid) + { + const char *arg0; + + arg0 = strrchr (pgmname, '/'); + if (arg0) + arg0++; + else + arg0 = pgmname; + + if (wp[0] != STDIN_FILENO) + { + if (dup2 (wp[0], STDIN_FILENO) == -1) + die ("dup2 failed in child: %s", strerror (errno)); + close (wp[0]); + } + if (rp[1] != STDOUT_FILENO) + { + if (dup2 (rp[1], STDOUT_FILENO) == -1) + die ("dup2 failed in child: %s", strerror (errno)); + close (rp[1]); + } + if (!opt_verbose) + { + int fd = open ("/dev/null", O_WRONLY); + if (fd == -1) + die ("can't open `/dev/null': %s", strerror (errno)); + if (dup2 (fd, STDERR_FILENO) == -1) + die ("dup2 failed in child: %s", strerror (errno)); + close (fd); + } + + close (wp[1]); + close (rp[0]); + execl (pgmname, arg0, "--server", NULL); + die ("exec failed for `%s': %s", pgmname, strerror (errno)); + } + close (wp[0]); + close (rp[1]); + server_send_fd = wp[1]; + server_recv_fd = rp[0]; + + read_assuan (server_recv_fd); + if (recv_type != LINE_OK) + die ("no greating message"); +} + + + + + +/* Script intepreter. */ + +static void +unset_var (const char *name) +{ + VARIABLE var; + + for (var=variable_list; var && strcmp (var->name, name); var = var->next) + ; + if (!var) + return; +/* fprintf (stderr, "unsetting `%s'\n", name); */ + + if (var->type == VARTYPE_FD && var->value) + { + int fd; + + fd = atoi (var->value); + if (fd != -1 && fd != 0 && fd != 1 && fd != 2) + close (fd); + } + + free (var->value); + var->value = NULL; + var->type = 0; + var->count = 0; +} + + +static void +set_type_var (const char *name, const char *value, VARTYPE type) +{ + VARIABLE var; + + if (!name) + name = "?"; + for (var=variable_list; var && strcmp (var->name, name); var = var->next) + ; + if (!var) + { + var = xcalloc (1, sizeof *var + strlen (name)); + strcpy (var->name, name); + var->next = variable_list; + variable_list = var; + } + else + free (var->value); + + if (var->type == VARTYPE_FD && var->value) + { + int fd; + + fd = atoi (var->value); + if (fd != -1 && fd != 0 && fd != 1 && fd != 2) + close (fd); + } + + var->type = type; + var->count = 0; + if (var->type == VARTYPE_COUNTER) + { + /* We need some extra sapce as scratch area for get_var. */ + var->value = xmalloc (strlen (value) + 1 + 20); + strcpy (var->value, value); + } + else + var->value = xstrdup (value); +} + +static void +set_var (const char *name, const char *value) +{ + set_type_var (name, value, 0); +} + + +static const char * +get_var (const char *name) +{ + VARIABLE var; + + for (var=variable_list; var && strcmp (var->name, name); var = var->next) + ; + if (!var) + return NULL; + if (var->type == VARTYPE_COUNTER && var->value) + { /* Use the scratch space allocated by set_var. */ + char *p = var->value + strlen(var->value)+1; + sprintf (p, "%u", var->count); + return p; + } + else + return var->value; +} + + +/* Incremente all counter type variables with NAME in their VALUE. */ +static void +inc_counter (const char *name) +{ + VARIABLE var; + + if (!*name) + return; + for (var=variable_list; var; var = var->next) + { + if (var->type == VARTYPE_COUNTER + && var->value && !strcmp (var->value, name)) + var->count++; + } +} + + +/* Expand variables in LINE and return a new allocated buffer if + required. The function might modify LINE if the expanded version + fits into it. */ +static char * +expand_line (char *buffer) +{ + char *line = buffer; + char *p, *pend; + const char *value; + size_t valuelen, n; + char *result = NULL; + + while (*line) + { + p = strchr (line, '$'); + if (!p) + return result; /* nothing more to expand */ + + if (p[1] == '$') /* quoted */ + { + memmove (p, p+1, strlen (p+1)+1); + line = p + 1; + continue; + } + for (pend=p+1; *pend && !spacep (pend) + && *pend != '$' && *pend != '/'; pend++) + ; + if (*pend) + { + int save = *pend; + *pend = 0; + value = get_var (p+1); + *pend = save; + } + else + value = get_var (p+1); + if (!value) + value = ""; + valuelen = strlen (value); + if (valuelen <= pend - p) + { + memcpy (p, value, valuelen); + p += valuelen; + n = pend - p; + if (n) + memmove (p, p+n, strlen (p+n)+1); + line = p; + } + else + { + char *src = result? result : buffer; + char *dst; + + dst = xmalloc (strlen (src) + valuelen + 1); + n = p - src; + memcpy (dst, src, n); + memcpy (dst + n, value, valuelen); + n += valuelen; + strcpy (dst + n, pend); + line = dst + n; + free (result); + result = dst; + } + } + return result; +} + + +/* Evaluate COND and return the result. */ +static int +eval_boolean (const char *cond) +{ + int true = 1; + + for ( ; *cond == '!'; cond++) + true = !true; + if (!*cond || (*cond == '0' && !cond[1])) + return !true; + return true; +} + + + + + +static void +cmd_let (const char *assign_to, char *arg) +{ + set_var (assign_to, arg); +} + + +static void +cmd_echo (const char *assign_to, char *arg) +{ + if (!opt_no_echo) + printf ("%s\n", arg); +} + +static void +cmd_send (const char *assign_to, char *arg) +{ + if (opt_verbose) + fprintf (stderr, "sending `%s'\n", arg); + write_assuan (server_send_fd, arg); +} + +static void +handle_status_line (char *arg) +{ + char *p; + + for (p=arg; *p && !spacep (p); p++) + ; + if (*p) + { + int save = *p; + *p = 0; + inc_counter (arg); + *p = save; + } + else + inc_counter (arg); +} + +static void +cmd_expect_ok (const char *assign_to, char *arg) +{ + if (opt_verbose) + fprintf (stderr, "expecting OK\n"); + do + { + char *p = read_assuan (server_recv_fd); + if (opt_verbose > 1) + fprintf (stderr, "got line `%s'\n", recv_line); + if (recv_type == LINE_STAT) + handle_status_line (p); + } + while (recv_type != LINE_OK && recv_type != LINE_ERR); + if (recv_type != LINE_OK) + die ("expected OK but got `%s'", recv_line); +} + +static void +cmd_expect_err (const char *assign_to, char *arg) +{ + if (opt_verbose) + fprintf (stderr, "expecting ERR\n"); + do + { + char *p = read_assuan (server_recv_fd); + if (opt_verbose > 1) + fprintf (stderr, "got line `%s'\n", recv_line); + if (recv_type == LINE_STAT) + handle_status_line (p); + } + while (recv_type != LINE_OK && recv_type != LINE_ERR); + if (recv_type != LINE_ERR) + die ("expected ERR but got `%s'", recv_line); +} + +static void +cmd_count_status (const char *assign_to, char *arg) +{ + char *p; + + if (!*assign_to || !*arg) + die ("syntax error: count-status requires an argument and a variable"); + + for (p=arg; *p && !spacep (p); p++) + ; + if (*p) + { + for (*p++ = 0; spacep (p); p++) + ; + if (*p) + die ("cmpfiles: syntax error"); + } + set_type_var (assign_to, arg, VARTYPE_COUNTER); +} + +static void +cmd_openfile (const char *assign_to, char *arg) +{ + int fd; + char numbuf[20]; + + do + fd = open (arg, O_RDONLY); + while (fd == -1 && errno == EINTR); + if (fd == -1) + die ("error opening `%s': %s", arg, strerror (errno)); + + sprintf (numbuf, "%d", fd); + set_type_var (assign_to, numbuf, VARTYPE_FD); +} + +static void +cmd_createfile (const char *assign_to, char *arg) +{ + int fd; + char numbuf[20]; + + do + fd = open (arg, O_WRONLY|O_CREAT|O_TRUNC, 0666); + while (fd == -1 && errno == EINTR); + if (fd == -1) + die ("error creating `%s': %s", arg, strerror (errno)); + + sprintf (numbuf, "%d", fd); + set_type_var (assign_to, numbuf, VARTYPE_FD); +} + + +static void +cmd_pipeserver (const char *assign_to, char *arg) +{ + if (!*arg) + die ("syntax error: servername missing"); + + start_server (arg); +} + + +static void +cmd_quit_if(const char *assign_to, char *arg) +{ + if (eval_boolean (arg)) + exit (0); +} + +static void +cmd_fail_if(const char *assign_to, char *arg) +{ + if (eval_boolean (arg)) + exit (1); +} + + +static void +cmd_cmpfiles (const char *assign_to, char *arg) +{ + char *p = arg; + char *second; + FILE *fp1, *fp2; + char buffer1[2048]; /* note: both must be of equal size. */ + char buffer2[2048]; + size_t nread1, nread2; + int rc = 0; + + set_var (assign_to, "0"); + for (p=arg; *p && !spacep (p); p++) + ; + if (!*p) + die ("cmpfiles: syntax error"); + for (*p++ = 0; spacep (p); p++) + ; + second = p; + for (; *p && !spacep (p); p++) + ; + if (*p) + { + for (*p++ = 0; spacep (p); p++) + ; + if (*p) + die ("cmpfiles: syntax error"); + } + + fp1 = fopen (arg, "rb"); + if (!fp1) + { + err ("can't open `%s': %s", arg, strerror (errno)); + return; + } + fp2 = fopen (second, "rb"); + if (!fp2) + { + err ("can't open `%s': %s", second, strerror (errno)); + fclose (fp1); + return; + } + while ( (nread1 = fread (buffer1, 1, sizeof buffer1, fp1))) + { + if (ferror (fp1)) + break; + nread2 = fread (buffer2, 1, sizeof buffer2, fp2); + if (ferror (fp2)) + break; + if (nread1 != nread2 || memcmp (buffer1, buffer2, nread1)) + { + rc = 1; + break; + } + } + if (feof (fp1) && feof (fp2) && !rc) + { + if (opt_verbose) + err ("files match"); + set_var (assign_to, "1"); + } + else if (!rc) + err ("cmpfiles: read error: %s", strerror (errno)); + else + err ("cmpfiles: mismatch"); + fclose (fp1); + fclose (fp2); +} + +static void +cmd_getenv (const char *assign_to, char *arg) +{ + const char *s; + s = *arg? getenv (arg):""; + set_var (assign_to, s? s:""); +} + + + + +/* Process the current script line LINE. */ +static int +interpreter (char *line) +{ + static struct { + const char *name; + void (*fnc)(const char*, char*); + } cmdtbl[] = { + { "let" , cmd_let }, + { "echo" , cmd_echo }, + { "send" , cmd_send }, + { "expect-ok" , cmd_expect_ok }, + { "expect-err", cmd_expect_err }, + { "count-status", cmd_count_status }, + { "openfile" , cmd_openfile }, + { "createfile", cmd_createfile }, + { "pipeserver", cmd_pipeserver }, + { "quit" , NULL }, + { "quit-if" , cmd_quit_if }, + { "fail-if" , cmd_fail_if }, + { "cmpfiles" , cmd_cmpfiles }, + { "getenv" , cmd_getenv }, + { NULL } + }; + char *p, *save_p; + int i, save_c; + char *stmt = NULL; + char *assign_to = NULL; + char *must_free = NULL; + + for ( ;spacep (line); line++) + ; + if (!*line || *line == '#') + return 0; /* empty or comment */ + p = expand_line (line); + if (p) + { + must_free = p; + line = p; + for ( ;spacep (line); line++) + ; + if (!*line || *line == '#') + { + free (must_free); + return 0; /* empty or comment */ + } + } + for (p=line; *p && !spacep (p) && *p != '='; p++) + ; + if (*p == '=') + { + *p = 0; + assign_to = line; + } + else if (*p) + { + for (*p++ = 0; spacep (p); p++) + ; + if (*p == '=') + assign_to = line; + } + if (!*line) + die ("syntax error"); + stmt = line; + save_c = 0; + save_p = NULL; + if (assign_to) + { /* this is an assignment */ + for (p++; spacep (p); p++) + ; + if (!*p) + { + unset_var (assign_to); + free (must_free); + return 0; + } + stmt = p; + for (; *p && !spacep (p); p++) + ; + if (*p) + { + save_p = p; + save_c = *p; + for (*p++ = 0; spacep (p); p++) + ; + } + } + for (i=0; cmdtbl[i].name && strcmp (stmt, cmdtbl[i].name); i++) + ; + if (!cmdtbl[i].name) + { + if (!assign_to) + die ("invalid statement `%s'\n", stmt); + if (save_p) + *save_p = save_c; + set_var (assign_to, stmt); + free (must_free); + return 0; + } + + if (cmdtbl[i].fnc) + cmdtbl[i].fnc (assign_to, p); + free (must_free); + return cmdtbl[i].fnc? 0:1; +} + + + +int +main (int argc, char **argv) +{ + char buffer[2048]; + char *p, *pend; + + if (!argc) + invocation_name = "asschk"; + else + { + invocation_name = *argv++; + argc--; + p = strrchr (invocation_name, '/'); + if (p) + invocation_name = p+1; + } + + + set_var ("?","1"); /* defaults to true */ + + for (; argc; argc--, argv++) + { + p = *argv; + if (*p != '-') + break; + if (!strcmp (p, "--verbose")) + opt_verbose++; + else if (!strcmp (p, "--no-echo")) + opt_no_echo++; + else if (*p == '-' && p[1] == 'D') + { + p += 2; + pend = strchr (p, '='); + if (pend) + { + int tmp = *pend; + *pend = 0; + set_var (p, pend+1); + *pend = tmp; + } + else + set_var (p, "1"); + } + else if (*p == '-' && p[1] == '-' && !p[2]) + { + argc--; argv++; + break; + } + else + break; + } + if (argc) + die ("usage: asschk [--verbose] {-D<name>[=<value>]}"); + + + while (fgets (buffer, sizeof buffer, stdin)) + { + p = strchr (buffer,'\n'); + if (!p) + die ("incomplete script line"); + *p = 0; + if (interpreter (buffer)) + break; + fflush (stdout); + } + return 0; +} + diff --git a/tests/inittests b/tests/inittests new file mode 100755 index 000000000..05a94eb68 --- /dev/null +++ b/tests/inittests @@ -0,0 +1,99 @@ +#!/bin/sh +# Copyright (C) 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. + +set -e + +sample_certs=' +cert_g10code_test1.pem +cert_g10code_pete1.pem +cert_g10code_theo1.pem +' + +private_keys=' +32100C27173EF6E9C4E9A25D3D69F86D37A4F939 +' + +clean_files=' +gpgsm.conf gpg-agent.conf trustlist.txt pubring.kbx +msg msg.sig msg.unsig +' + + +[ -z "$srcdir" ] && srcdir=. +[ -z "$GPGSM" ] && GPGSM=../sm/gpgsm + +if [ -d $srcdir/samplekeys ] \ + && grep TESTS_ENVIRONMENT Makefile >/dev/null 2>&1; then + : +else + # During make distclean the Makefile has already been removed, + # so we need this extra test. + if ! grep gnupg-test-directory testdir.stamp >/dev/null 2>&1; then + echo "inittests: please cd to the tests directory first" >&2 + exit 1 + fi +fi + +if [ "$1" = "--clean" ]; then + if [ -d private-keys-v1.d ]; then + rm private-keys-v1.d/* 2>/dev/null || true + rmdir private-keys-v1.d + fi + rm ${clean_files} testdir.stamp 2>/dev/null || true + exit 0 +fi + +if [ "$GNUPGHOME" != "`pwd`" ]; then + echo "inittests: please set GNUPGHOME to the test directory" >&2 + exit 1 +fi + +if [ -n "$GPG_AGENT_INFO" ]; then + echo "inittests: please unset GPG_AGENT_INFO" >&2 + exit 1 +fi + +# A stamp file used with --clean +echo gnupg-test-directory > testdir.stamp + + +# Create the private key directy if it does not exists and copy +# the sample keys. +[ -d private-keys-v1.d ] || mkdir private-keys-v1.d +for i in ${private_keys}; do + cat ${srcdir}/samplekeys/$i.key >private-keys-v1.d/$i.key +done + +# Create the configuration scripts +# Note, die to an expired test certificate, we need to use +# the faked system time option. +cat > gpgsm.conf <<EOF +no-secmem-warning +disable-crl-checks +agent-program ../agent/gpg-agent +faked-system-time 1038835799 +EOF + +cat > gpg-agent.conf <<EOF +no-grab +pinentry-program /home/wk/work/pinentry/gtk/pinentry-gtk +EOF + +cat > trustlist.txt <<EOF +# CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE +3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E S +EOF + +# Make sure that the sample certs are available but ignore errors here +# because we are not a test script. +for i in ${sample_certs}; do + $GPGSM --import ${srcdir}/samplekeys/$i || true +done -- cgit v1.2.3 From 81919e0d615d0dec913a5b708af96d76d0233c17 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Jan 2003 13:29:36 +0000 Subject: taken from NewPG --- doc/ChangeLog | 602 ++++++++++++-------------------------------------------- doc/Makefile.am | 77 ++------ 2 files changed, 144 insertions(+), 535 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 628793a90..9ef2473ab 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,586 +1,230 @@ -2003-01-06 David Shaw <dshaw@jabberwocky.com> +2002-12-04 Werner Koch <wk@gnupg.org> - * DETAILS: Document disabled flag in capabilities field. + Released 0.9.4. -2002-12-27 David Shaw <dshaw@jabberwocky.com> +2002-12-03 Werner Koch <wk@gnupg.org> - * gpg.sgml: Clarify --no-permission-warning to note that the - permission warnings are not intended to be the be-all and end-all - in security checks. Add note to --group that when used on the - command line, it may be necessary to quote the argument so it is - not treated as multiple arguments. Noted by Stefan Bellon. + * configure.ac (GNUPG_PROTECT_TOOL): New option --with-protect-tool. -2002-12-23 Werner Koch <wk@gnupg.org> +2002-11-25 Werner Koch <wk@gnupg.org> - * samplekeys.asc: Updated. + * configure.ac (NEED_KSBA_VERSION): Does now require 0.4.6. -2002-12-10 David Shaw <dshaw@jabberwocky.com> +2002-11-13 Werner Koch <wk@gnupg.org> - * gpg.sgml: Clarify include-revoked and include-disabled so they - match what the program actually does. Noted by Dick Gevers. + * README: Noted where to find gpg-protect-tool. - * gpg.sgml: Document %-expandos for policy URLs and notations. +2002-11-12 Werner Koch <wk@gnupg.org> - * gpg.sgml: Document --pgp8. Clarify that --pgp6 and --pgp7 - disable --throw-keyid. + * config.sub, config.guess: Updated from ftp.gnu.org/gnu/config + to version 2002-11-08. -2002-12-05 Werner Koch <wk@gnupg.org> +2002-11-11 Werner Koch <wk@gnupg.org> - * gpg.sgml: Document --no-mangle-dos-filenames. + Released 0.9.3. -2002-12-01 David Shaw <dshaw@jabberwocky.com> +2002-10-31 Neal H. Walfield <neal@g10code.de> - * gpg.sgml: Point out that if the user absolutely must, it's - better to use --pgpX than forcing an algorithm manually. Better - still not to use anything, of course. + * configure.ac: Check for flockfile and funlockfile. Check for + isascii and putc_unlocked replacing them if not found. -2002-11-25 David Shaw <dshaw@jabberwocky.com> +2002-10-31 Neal H. Walfield <neal@g10code.de> - * gpg.sgml: Document --primary-keyring. Clarify - --s2k-cipher-algo, --s2k-digest-algo, - --personal-cipher-preferences, --personal-digest-preferences, and - --personal-compress-preferences. - - * gpg.sgml: Document --sig-policy-url, --cert-policy-url, - --sig-notation, --cert-notation. Clarify --show-notation and - --show-policy-url that policy URLs and notations can be used in - data signatures as well. Add note about '@' being a required - character in notation names. - -2002-11-21 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Add an interoperability section. - -2002-11-17 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Correct defaults for --s2k-mode and --s2k-digest-mode. - Noted by Haakon Riiser. - -2002-11-14 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: --compress-algo now allows algorithm names. - -2002-11-13 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Document --trust-model. - -2002-11-04 David Shaw <dshaw@jabberwocky.com> - - * KEYSERVER: New. Documents the --with-colons format for - keyserver listings. - - * DETAILS: Clarify meaning of 'u'. Noted by Timo. - -2002-11-03 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Document "tsign", clarify "setpref", clarify - --recipient, document --hidden-recipient, document - --hidden-encrypt-to, clarify --no-encrypt-to, clarify - --throw-keyid, document --no-throw-keyid. - -2002-10-25 Werner Koch <wk@gnupg.org> - - * README.W32: Add blurb on how to create a ZIP file, changed - requirement for mingw32 to 0.3.2. - -2002-10-24 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Document --refresh-keys. - -2002-10-19 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Clarify --force-mdc, and document --disable-mdc. - -2002-10-12 Werner Koch <wk@gnupg.org> - - * DETAILS (KEY_CREATED): Enhanced by fingerprint. - -2002-10-03 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Note that '#' means secret-key-unavailable, and that - keyserver schemes are case-insensitive. - -2002-09-30 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Note that --pgp2 disables --textmode when encrypting. - -2002-09-20 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Some minor language cleanup. + * configure.ac (PTH_LIBS): If pth is found, add the output of + `$PTH_CONFIG --ldflags`, not just `$PTH_CONFIG --libs`. 2002-09-20 Werner Koch <wk@gnupg.org> - * DETAILS: s/XORed/ORed/. - -2002-09-15 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Add rebuild-keydb-caches. - -2002-09-12 David Shaw <dshaw@jabberwocky.com> - - * DETAILS: Fix batch key generation example. - -2002-09-11 Werner Koch <wk@gnupg.org> - - * Makefile.am (EXTRA_DIST): Include gnupg-32.reg - -2002-09-02 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Updated the charset option. - - * DETAILS: Added status IMPORT_OK. + Released 0.9.2. - * gnupg.7: New mini man page. +2002-09-05 Neal H. Walfield <neal@g10code.de> -2002-08-30 David Shaw <dshaw@jabberwocky.com> + * configure.ac: Check for makeinfo. - * gpg.sgml: Document keyserver-option include-subkeys. Note that - honor-http-proxy is a keyserver-option now. +2002-09-03 Neal H. Walfield <neal@g10code.de> - * DETAILS: Add "Key not trusted" to INV_RECP status code. + * 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> - * faq.raw: Updated. New Maintainer is David D. Scribner. + Released 0.9.1. -2002-08-22 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Clarify meaning of keyserver option include-revoked. + * 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> - * DETAILS: Added IMPORT_PROBLEM. - -2002-08-20 David Shaw <dshaw@jabberwocky.com> - - * DETAILS: Clarify that trust letters 'q' and '-' can be treated - identically. - - * gpg.sgml: Document --ignore-mdc-error. - -2002-08-06 David Shaw <dshaw@jabberwocky.com> + Released 0.9.0. - * gpg.sgml: Clarify that only long-form options can go in the - config file. + * configure.ac: Changed the default homedir to .gnupg. + * README-alpha: Removed. -2002-08-06 Werner Koch <wk@gnupg.org> +2002-08-19 Werner Koch <wk@gnupg.org> - * gpg.sgml: Fixed doc regarding the name change of the option - file. + * acinclude.m4: Removed -lpcsclite from KSBA_LIBS; copy+paste bug. -2002-07-30 David Shaw <dshaw@jabberwocky.com> +2002-08-13 Werner Koch <wk@gnupg.org> - * gpg.sgml: Clarify --edit/addrevoker (sensitive), and - --keyserver-options (--import/export-options may be used as well). - Document --import-options and --export-options with their various - options. --show-photos now works during signature verification as - well. Document --exec-path. Note in --simple-sk-checksum that - the passphrase must be changed for this to take effect. Note that - --pgp7 does not disable MDC. Document --no-mdc-warning. + * acinclude.m4 (AM_PATH_OPENSC, AM_PATH_KSBA): New. + * configure.ac: Use them. -2002-07-25 Werner Koch <wk@gnupg.org> +2002-08-10 Werner Koch <wk@gnupg.org> - * gpg.sgml: Document new --delete behaviour. - -2002-07-25 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Clarify the differences between "pref" and "showpref". - Note in "setpref" that a list of available algorithms can be - printed with "gpg -v --version". Note in "updpref" that we don't - select keys via attribute uids, so preferences there will be - ignored. + Released 0.3.10. + + * configure.ac (NEED_LIBKSBA_VERSION): Require 0.4.4. Add support + for gettext. -2002-07-01 David Shaw <dshaw@jabberwocky.com> +2002-07-22 Werner Koch <wk@gnupg.org> - * gpg.sgml: Clarify "group". + * configure.ac: Check for ftello and provide a replacement. 2002-07-01 Werner Koch <wk@gnupg.org> - * Makefile.am: Due to problems with VPATH builds we don't try to - build the texi vesions of the manual pages anymore automatically. - -2002-06-30 Werner Koch <wk@gnupg.org> - - * README.W32: Adjusted some descriptions. Fixed the regsitry - entry descriptions. - -2002-06-21 David Shaw <dshaw@jabberwocky.com> - - * DETAILS: Document "uat". - - * gpg.sgml: Document - --personal-{compress|digest|compress}-preferences, --group, and - add comments to --expert. - -2002-06-17 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Grammar fix. - -2002-06-03 David Shaw <dshaw@jabberwocky.com> - - * DETAILS: Details of ATTRIBUTE. - - * gpg.sgml: Document --attribute-fd - -2002-06-03 Timo Schulz <ts@winpt.org> - - * DETAILS: Add ATTRIBUTE. + Released 0.3.9. -2002-05-31 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Add "edit/addrevoker". Document --desig-revoke. Note - that -z and --compress are the same option. Note that - --digest-algo can no longer violate OpenPGP with a non-160 bit - hash with DSA. Document --cert-digest-algo with suitable warnings - not to use it. Note the default s2k-cipher-algo is now CAST5. - Note that --force-v3-sigs overrides --ask-sig-expire. Revise - --expert documentation, as it is now definitely legal to have more - than one photo ID on a key. --preference-list is now - --default-preference-list with the new meaning. Document - --personal-preference-list. - - * DETAILS: Document "Revoker" for batch key generation. - -2002-05-22 Werner Koch <wk@gnupg.org> - - * gpg.sgml: sgml syntax fix. + * README: Short note on how to export in pkcs-12 format. -2002-05-12 Werner Koch <wk@gnupg.org> +2002-06-29 Werner Koch <wk@gnupg.org> - * gpg.sgml: Fixed URL in the description section. + * configure.ac: Define --with options to set the default location + of the agent, scdaemon, pinentry and dirmngr. - * faq.raw: Minor typo fixes noted by kromJx@myrealbox.com. +2002-06-27 Werner Koch <wk@gnupg.org> -2002-05-11 Werner Koch <wk@gnupg.org> + * README: Short blurb on how to import a PKCS-12 file. - * gpg.sgml: Typo fix. + * configure.ac (AH_BOTTOM): New to define some constants. -2002-05-07 David Shaw <dshaw@jabberwocky.com> +2002-06-25 Werner Koch <wk@gnupg.org> - * gpg.sgml: Add entries for --sk-comments, --no-sk-comments, - --pgp7, and --no-pgp7. Fix --pgp2 and --pgp6: the proper name is - --escape-from-lines and not --escape-from. - -2002-04-30 Timo Schulz <ts@winpt.org> - - * gpg.sgml: Add an entry for --encrypt-files and --decrypt-files. + Released 0.3.8. -2002-04-29 David Shaw <dshaw@jabberwocky.com> + * configure.ac (NEED_LIBGCRYPT_VERSION): Set to 1.1.8. - * gpg.sgml: Fix minor error in --pgp6 documentation: it does not - imply --digest-algo MD5 +2002-06-12 Werner Koch <wk@gnupg.org> -2002-04-29 Werner Koch <wk@gnupg.org> + * configure.ac (NEED_LIBKSBA_VERSION): We need 0.4.3 now. - * samplekeys.asc: Added gnupg distribution key 57548DCD. +2002-06-04 Werner Koch <wk@gnupg.org> - * faq.raw: Inserted Douglas Calvert as new maintainer. Acknowledge - Nils. Add entry about trust packet parsing problems. + Released 0.3.7. -2002-04-24 David Shaw <dshaw@jabberwocky.com> +2002-05-21 Werner Koch <wk@gnupg.org> - * gpg.sgml: Add some documentation for - --edit/{addphoto|showphoto|nrsign|nrlsign}, and the difference - between %t and %T in photo viewer command lines. + * configure.ac: We now require libgcrypt 1.1.7 and libksba 0.4.2. -2002-04-23 Stefan Bellon <sbellon@sbellon.de> +2002-05-14 Werner Koch <wk@gnupg.org> - * gpg.sgml: Moved options from section "COMMANDS" to - section "OPTIONS". + * doc/: New + * configure.ac, Makefile.am: Added doc/ -2002-04-20 David Shaw <dshaw@jabberwocky.com> +2002-05-03 Werner Koch <wk@gnupg.org> - * samplekeys.asc: Added 0x5B0358A2 + Released 0.3.6. -2002-04-19 David Shaw <dshaw@jabberwocky.com> +2002-04-25 Werner Koch <wk@gnupg.org> - * gpg.sgml: Add "%t" flag for photo IDs, a note about primary - having different meanings for photo and regular IDs, rename - --default-check-level to --default-cert-check-level, add - --auto-check-trustdb, and --pgp6. + * configure.ac: Check for setlocale. - * DETAILS: Add EXPSIG, EXPKEYSIG, and KEYEXPIRED. Add notes to - SIGEXPIRED (deprecated), and VALIDSIG (added expiration date). - Add "Preferences" command to unattended key generation - instructions. Also fixed a few typos. - - * samplekeys.asc: new (added to EXTRA_DIST in Makefile.am as well) +2002-04-24 Marcus Brinkmann <marcus@g10code.de> -2002-01-31 Marcus Brinkmann <marcus@g10code.de> + * configure.ac: Check for locale.h. - * DETAILS: Fix a spelling error, correct IMPORTED_RES to IMPORT_RES, - correct INV_RECP (the second occurence) to NO_RECP. +2002-04-15 Werner Koch <wk@gnupg.org> -2002-04-03 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: auto-key-retrieve is a keyserver-option (noted by - Roger Sondermann). + Released 0.3.5. -2002-03-27 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: --pgp2 also means --disable-mdc, --no-ask-sig-expire, - and --no-ask-cert-expire. It does not mean --no-force-v3-sigs - (noted by Timo). - -2002-03-27 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Add a few notes about --pgp2 meaning MIT PGP 2.6.2, - and keyserver details about HKP and NAI HKP. - -2002-03-18 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Change meaning of --allow-non-selfsigned-uid to match - change in code, and add --no-allow-non-selfsigned-uid. - -2002-03-13 Werner Koch <wk@gnupg.org> - - * faq.raw: Due to a lack of time Nils can't serve anymore as a - maintainer. Removed his address and setup a generic address. - -2002-03-06 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Add an entry for --export-ownertrust. Suggested by - Bernhard Reiter. - -2002-01-26 Timo Schulz <ts@winpt.org> - - * gnupg-w32.reg: New. Registry file for W32 in registry format. - -2002-01-26 Werner Koch <wk@gnupg.org> - - * gpg.sgml: A few words about --gpg-agent-info and GPG_AGENT_INFO. - -2002-01-25 Timo Schulz <ts@winpt.org> - - * README.W32: Modify the filename because now the .exe extension - is automatically added to the binary. + * NEWS: Started to describe release notes. -2002-01-14 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Talk about PGP 5 and higher. - -2002-01-11 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Added documentation for --{no-}ask-cert-expire, - --{no-}ask-sig-expire, and revise --expert (it doesn't switch on - the expiration prompt anymore) and --default-check-level (to be - clearer as to what makes a good key check before signing). - -2002-01-07 Werner Koch <wk@gnupg.org> - - * DETAILS: Removed the comment that unattended key generation is - experimental. It is now a standard feature. - -2001-12-22 David Shaw <dshaw@jabberwocky.com> - - * gpg.sgml: Fixed a few typos. - - * gpg.sgml: Added documentation for --show-photos, - --no-show-photos, --photo-viewer, --nrsign-key, - --default-check-level, --search-keys, --keyserver-options, - --show-notation, --no-show-notation, --show-policy-url, - --no-show-policy-url, --for-your-eyes-only, - --no-for-your-eyes-only, --pgp2, --no-pgp2, - --no-permission-warning, --expert, --no-expert. - -2001-10-31 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Add a remark on how to get the long key ID. Suggested - by Sebastian Klemke. - -2001-10-23 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Add missing tag. - -2001-09-28 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Add a note on option parsing. - -2001-09-24 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Described --{update,check}-trustdb. - -2001-09-03 Werner Koch <wk@gnupg.org> - - * gpg.sgml, gpgv.sgml: Removed GDBM stuff. - -2001-08-29 Werner Koch <wk@gnupg.org> - - * faq.raw: Described how to delete a secret key w/o a public key - and changed the entry on updating the preferences. - -2001-08-08 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Documented --print-mds and marked the --print-md * as - deprecated because it does not work in the W32 version. Suggested - by John Kane. - (WARNINGS): Typo fix. - (--with-colons): Clarified that the output is in UTF-8. - -2001-08-01 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Added --ignore-valid-from - -2001-04-20 Werner Koch <wk@gnupg.org> - - * faq.raw (Maintained-by): Removed note that load-extension is not - available under Windoze. - - * gpg.sgml: Add new --charset UTF-8. - -2001-04-19 Werner Koch <wk@gnupg.org> - - * faq.raw: Add a note about dates displayed as ????-??-??. - -2001-04-17 Werner Koch <wk@gnupg.org> - - * Makefile.am (%.texi): Add rules to create .texi from .sgml. - However we can't automate this because automake does not like - .texi files as BUILT_SOURCES. - (%.dvi,%.ps): Removed these rules, because they are not needed - and get in the way of automake's dvi target + * configure.ac (NEED_LIBKSBA_VERSION, NEED_LIBGCRYPT_VERSION): Defined - * HACKING: Changed CVS description. +2002-04-01 Werner Koch <wk@gnupg.org> -2001-04-06 Werner Koch <wk@gnupg.org> + Released 0.3.4. - * gpg.sgml: Small typo fixes by Florian Weimer. +2002-03-18 Werner Koch <wk@gnupg.org> -2001-03-27 Werner Koch <wk@gnupg.org> + Released 0.3.3. - * gpg.sgml: Add --no-sig-cache and --no-sig-create-check. +2002-03-08 Werner Koch <wk@gnupg.org> -2001-03-23 Werner Koch <wk@gnupg.org> + * README: Add some explanation on how to specify a user ID. - * DETAILS: New status UNEXPECTED. - -2001-03-13 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Described --fixed-list-mode. - -2001-03-06 Werner Koch <wk@gnupg.org> - - * gpgv.sgml: Changed some gpg to gpgv. Thanks to John A. Murdie. - -2001-03-03 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Tell something about the 0x12345678! key ID syntax. - -2001-01-18 Werner Koch <wk@gnupg.org> - - * README.W32: Changed building instructions for MinGW32/CPD 0.3 - -2001-01-09 Werner Koch <wk@gnupg.org> - - * DETAILS: Fixed docs for NEED_PASSPHRASE and added USERID_HINT. - -2000-11-30 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Fixed the description of --verify. Add a short note - the warnings sections. - -2000-10-19 Werner Koch <wk@gnupg.org> - - * gpg.sgml: Fixed doc for --allow-non-selfsigned-uid. - Add entry for --ignore-crc-error. - -2000-10-18 Werner Koch <wk@gnupg.org> - - * OpenPGP: Dropped the paragraph that RSA is not implemented. - -2000-10-14 Werner Koch <wk@gnupg.org> - - * faq.raw: Add an answer to the problem of multiple signatures. - -Wed Oct 4 15:50:18 CEST 2000 Werner Koch <wk@openit.de> - - * gpgv.sgml: New. - * Makefile.am: build it. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> - - * faq.raw: New. - * Makefile.am: Support to build FAQs - -Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@> - - * gpg.sgml: Add a note about the availability of the GPH. - -2000-07-03 13:59:24 Werner Koch (wk@habibti.openit.de) - - * DETAILS, FAQ: Typo fixes by Yosiaki IIDA. - -2000-05-12 10:57:21 Werner Koch (wk@habibti.openit.de) - - * gpg.sgml: Documented --no-tty. - -2000-03-09 15:01:51 Werner Koch (wk@habibti.openit.de) - - * DETAILS: Ad a short blurb about unattended key generation. - -Wed Feb 9 15:33:44 CET 2000 Werner Koch <wk@gnupg.de> - - * gpg.sgml: Describe --ignore-time-conflict. - - * gpg.sgml: Fixed a few typos. Thanks to Holger Trapp. +2002-03-06 Werner Koch <wk@gnupg.org> -Wed Jan 5 11:51:17 CET 2000 Werner Koch <wk@gnupg.de> + Released 0.3.2. - * FAQ: Enhanced answer for the 3des-s2k bug. +2002-03-04 Werner Koch <wk@gnupg.org> -Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de> + Released 0.3.1. - * gpg.sgml: Add section about the user ID + * README: Explained some options and files. -Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de> +2002-02-14 Werner Koch <wk@gnupg.org> - * gph: Removed the directory from the dist becuase it will - go into it's own package. + * configure.ac: Fixed status messages related to presence of Pth. -Thu Sep 23 09:52:58 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> +2002-02-13 Werner Koch <wk@gnupg.org> - * README.W32: New. + * acinclude.m4 (GNUPG_SYS_SO_PEERCRED): New. + * configure.ac: use it. -Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> +2002-02-12 Werner Koch <wk@gnupg.org> + * configure.ac: Check for PTH. Provide replacement fucntions for + apsrintf and fopencookie. - * Makefile.am (SUBDIRS): New subdir gph for the manual. + * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): New. -Thu Jul 22 20:03:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> +2002-02-07 Werner Koch <wk@gnupg.org> + Released 0.3.0. - * gpg.sgml (--always-trust): Added. + * configure.ac: Require libgcrypt 1.1.6. -Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> +2002-02-01 Marcus Brinkmann <marcus@g10code.de> + * configure.ac (KSBA_CONFIG): Remove superfluous x in front of + variable. - * Makefile.am: Create a dummy man page if docbook-to-man is missing. +2002-01-26 Werner Koch <wk@gnupg.org> -Wed Jun 16 20:16:21 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + * 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 - * gpg1.pod: Removed. - * gpg.sgml: New. Replaces the pod file - * Makefile.am: Add rule to make a man file from sgml +2002-01-23 Werner Koch <wk@gnupg.org> -Tue Jun 15 12:21:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + * configure.ac (mkdtemp): See whether we have to provide a + replacement. +2001-12-18 Werner Koch <wk@gnupg.org> - * Makefile.in.in: Use DESTDIR. + Released 0.0.0. -Mon May 31 19:41:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> +2001-12-17 Werner Koch <wk@gnupg.org> - * gpg.1pod: Enhanced the Bugs section (Michael). + * acinclude.m4: Add AM_PATH_LIBGCRYPT macro. + * configure.ac: and use it here. Figure out the location of libksba -Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> +2001-12-15 Werner Koch <wk@gnupg.org> + * configure.ac (missing_dir): Bail out if asprintf and fopencookie + are not available. - * gpg.1pod: Spelling and grammar corrections (John A. Martin) - * FAQ: Ditto. - * DETAILS: Ditto. +2001-12-04 Werner Koch <wk@gnupg.org> + * configure.ac (HAVE_JNLIB_LOGGING): always define it. - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + 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 @@ -589,5 +233,5 @@ Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> 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. - + diff --git a/doc/Makefile.am b/doc/Makefile.am index 8f951191a..ccfc98fb2 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,7 +1,8 @@ -# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -# +# 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 @@ -16,67 +17,31 @@ # 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 create Makefile.in - -AUTOMAKE_OPTIONS = no-texinfo.tex - -EXTRA_DIST = DETAILS gpg.sgml gpg.1 gpgv.sgml gpgv.1 faq.raw FAQ faq.html \ - HACKING OpenPGP README.W32 samplekeys.asc gnupg.7 gnupg-w32.reg - -man_MANS = gpg.1 gpgv.1 gnupg.7 - -info_TEXINFOS = gpg.texi gpgv.texi - -# Need this to avoid building of dvis with automake 1.4 -DVIS = - -pkgdata_DATA = FAQ faq.html +## Process this file with automake to produce Makefile.in -BUILT_SOURCES = FAQ faq.html -# we can't add gpg.texi gpgv.texi here because automake does not like them to -# be built files. +EXTRA_DIST = autogen.sh -CLEANFILES = faq.raw.xref gpg.xml gpgv.xml - - -# We better build the texi versions manually. -#%.texi : %.xml -#if HAVE_DOCBOOK_TO_TEXI -# docbook2texi $< | sed 's,--,---,' \ -# | $(top_srcdir)/scripts/fix-db-texi $@ >$@ -#else -# : Warning: missing docbook to texinfo tools, cannot make $@ -# touch $@ -#endif -# -#%.xml : %.sgml -#if HAVE_DOCBOOK_TO_TEXI -# sgml2xml -x lower $< >$@ -#else -# : Warning: missing docbook to texinfo tools, cannot make $@ -# touch $@ -#endif -# - -%.1 : %.sgml -if HAVE_DOCBOOK_TO_MAN - docbook-to-man $< >$@ +if BUILD_GPGSM +sm = sm else - : Warning: missing docbook-to-man, cannot make $@ - echo ".TH $< 1" >$@ - echo "No man page due to missing docbook-to-man" >>$@ +sm = +endif +if BUILD_AGENT +agent = agent +else +agent = +endif +if BUILD_SCDAEMON +scd = scd +else +scd = endif +SUBDIRS = intl jnlib assuan common kbx ${sm} ${agent} ${scd} po doc tests -FAQ : faq.raw - $(FAQPROG) -f $< $@ || $(FAQPROG) -f $< $@ - -faq.html : faq.raw - $(FAQPROG) -h -f $< $@ 2>&1 || $(FAQPROG) -h -f $< $@ dist-hook: - @if test "`wc -c < gpg.1`" -lt 200; then \ - echo 'ERROR: dummy man page'; false; fi + @set -e; echo "$(VERSION)" > $(distdir)/VERSION -- cgit v1.2.3 From 01248e18b8aaa13882004699f7c81ac1ea28e1a7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Jan 2003 13:31:18 +0000 Subject: Taken from NewPG --- po/ChangeLog | 502 +---- po/POTFILES.in | 75 +- po/de.po | 5715 +++++++------------------------------------------------- 3 files changed, 763 insertions(+), 5529 deletions(-) diff --git a/po/ChangeLog b/po/ChangeLog index 0ced8c712..669dfbe30 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,501 +1,15 @@ -2002-10-18 Werner Koch <wk@gnupg.org> +2002-08-21 Werner Koch <wk@gnupg.org> - * POTFILES.in (hkp.c): Removed. + * de.po: Updated the translation. -2002-09-12 Werner Koch <wk@gnupg.org> +2002-08-10 Werner Koch <wk@gnupg.org> - * tr.po, el.po: Updated. + * Makefile.in.in: Installed from gettext-0.10.40. + * POTFILES.in: New. + * de.po: New. -2002-08-23 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-08-04 Werner Koch <wk@gnupg.org> - - * de.po: Fixed fuzzys and translated new strings. - * es.po, et.po, fr.po, gl.po, id.po, it.po, ja.po, tr.po: Updated - from TP site. - * ca.po: New from TP site. - -2002-04-30 Werner Koch <wk@gnupg.org> - - * ja.po: Updated, also a bit too late for the release. - -2002-04-29 Werner Koch <wk@gnupg.org> - - * pl.po: Update. - * el.po: Updated, removed one entry due to non-matching printf and - one removed one printf specifier. - - Fixed fuzzy entries due to the change of (y/N) to (Y/n) in most files. -2002-04-25 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-04-22 Werner Koch <wk@gnupg.org> - - * et.po, tr.po, cs.po, it.po, id.po: Updated. - -2002-04-19 Werner Koch <wk@gnupg.org> - - * de.po: Fixed fuzzies and added a few translations. - -2002-04-18 Werner Koch <wk@gnupg.org> - - * eo.po: Updated. - -2002-04-10 Werner Koch <wk@gnupg.org> - - * pl.po: Updated. - -2002-04-09 Werner Koch <wk@gnupg.org> - - * pt_BR.po: Updated the info entry - - * es.po: Fixed a c-format problem; for unknown reasons msgfmt -c - can't cope with swapped arguments. - - * de.po: Fuzzy fixes and a few new translations. - - * id.po: Fixed a format string mismatch. - - * eo.po, it.po, ja.po, sv.po: Updated with a somewhat newer - version from the TP. - - * es_ES.po: Removed - * es.po: and replaced with this updated version from the TP. - - * cs.po: New. Fixed for format string mismatches. - - * el.po, gl.po: New from TP. - -2002-04-06 Werner Koch <wk@gnupg.org> - - * fr.po: Updated. - -2002-04-02 Werner Koch <wk@gnupg.org> - - * de.po, de.glo: Updated. - -2002-03-08 Werner Koch <wk@gnupg.org> - - * et.po: Updated. - -2002-03-06 Werner Koch <wk@gnupg.org> - - * pt_PT.po: Removed. - * pt.po: and replaced by this updated one. My machine voted 30 to - 2 for just pt. So we go with the crowd. Thanks for Pedro Morais - for suggesting this. - -2002-03-05 Werner Koch <wk@gnupg.org> - - * tr.po, id.po: Updated. - -2002-03-03 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-03-03 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2001-10-23 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2001-09-07 Werner Koch <wk@gnupg.org> - - * POTFILES.in: Added new files. - -2001-07-26 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.38. - -2001-07-05 Werner Koch <wk@gnupg.org> - - * id.po: Updated - -2001-05-28 Werner Koch <wk@gnupg.org> - - * ru.po: Removed - too many format string bugs. - -2001-05-27 gettextize <bug-gnu-utils@gnu.org> - - * Makefile.in.in: Upgrade to gettext-0.10.38. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2001-05-27 Werner Koch <wk@gnupg.org> - - * tr.po: New copy from the TP Robot. - * da.po, de.po, eo.po, es_ES.po, et.po, id.po, ja.po, nl.po, - pt_BR.po, sv.po: Fixes to format string errors by Kurt Garloff. - It is not cleare whether they are all correct but at least they - won't give segv and minimize the risk of format string exploits. - * ru.po: Fixed the header entry. - - Fixed some fuzzy entries in all files. - -2001-05-06 Werner Koch <wk@gnupg.org> - - * id.po: Updated - -2001-04-27 Werner Koch <wk@gnupg.org> - - * de.po: Removed an extra "%s". - -2001-04-25 Werner Koch <wk@gnupg.org> - - * fr.po: Updated. - -2001-04-23 Werner Koch <wk@gnupg.org> - - * eo.po: Updated. - - * it.po: Updated. - -2001-04-22 Werner Koch <wk@gnupg.org> - - * pl.po: Updated. - -2001-04-17 Werner Koch <wk@gnupg.org> - - * et.po: New. - - * de.po: Updated. - -2001-04-16 Werner Koch <wk@gnupg.org> - - * pt_PT.po: Updated. - -2001-04-06 Werner Koch <wk@gnupg.org> - - * tr.po: New. - -2001-03-18 Werner Koch <wk@gnupg.org> - - * de.po, de.glo: Updated. - -2001-02-22 Werner Koch <wk@gnupg.org> - - * de.po, de.glo: Updated. - -2001-01-23 Werner Koch <wk@gnupg.org> - - * de.po: Removed superfluous \r. - -2001-01-14 Werner Koch <wk@gnupg.org> - - * de.po, de.glo: Updated. - -2000-12-19 Werner Koch <wk@gnupg.org> - - * pl.po: Updated. - - * ja.po: Justified one message. - -2000-10-23 Werner Koch <wk@gnupg.org> - - * ja.po: Updated. - -2000-10-19 Werner Koch <wk@gnupg.org> - - Fixed a typo in all files. - -2000-10-16 Werner Koch <wk@gnupg.org> - - * de.po, de.glo: Updated. - -Thu Sep 14 17:45:11 CEST 2000 Werner Koch <wk@openit.de> - - * eo.po: Updated. - -Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@> - - * da.po: New from the TP server - * eo.po: Updated from the TP server - * pl.po: Ditto. - * sv.po: Ditto. - - Small English spelling correction in all files. - -Wed Jul 5 13:28:45 CEST 2000 Werner Koch <wk@openit.de> - - * fr.po: Minor changes by Gael - -Wed Jun 14 12:27:09 CEST 2000 Werner Koch <wk@openit.de> - - * de.po, de.glo: Updated. - -2000-06-07 18:26:58 Werner Koch (wk@habibti.openit.de) - - * fr.po: New version from Gal - -2000-05-02 10:44:42 Werner Koch (wk@habibti.openit.de) - - * fr.po: New version from the TP Robot. - -2000-05-01 14:19:52 Werner Koch (wk@habibti.openit.de) - - * de.po: Updated. - * de.glo: Ditto. - -2000-03-15 15:37:08 Werner Koch (wk@habibti.openit.de) - - * de.po: Updated. - -Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de> - - * nl.po: New. By Ivo Timmermans. - -Wed Feb 16 16:25:09 CET 2000 Werner Koch <wk@gnupg.de> - - * eo.po : New. By Edmund. - -Wed Feb 16 14:09:00 CET 2000 Werner Koch <wk@gnupg.de> - - * ja.po: New. By Yosiaki - - * sv.po: New. By Daniel. - -Fri Feb 11 17:44:40 CET 2000 Werner Koch <wk@gnupg.de> - - * id.po: Updated. - -Thu Jan 6 16:56:18 CET 2000 Werner Koch <wk@gnupg.de> - - * Makefile.in.in: Is not longer maintained as a symlink because we - have a patch to work around a bug in non-gnu Make. - Fixed by Dave Dykstra. - -Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de> - - * pt_PT.po: Updated. - * de.po: Updated. - * it.po: Updated. - -Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.de> - - * de.po: Updated. - * pt_BR.po: Updated. - -Fri Nov 12 20:33:19 CET 1999 Werner Koch <wk@gnupg.de> - - * es_ES.po: Fixed 3 \n mismatches. - - * de.po: Updated. - -Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de> - - * es_ES.po: Updated. - - * pt_BR.po: Updated. - -Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de> - - * fr.po: Updated for 1.0.0d. - -Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de> - - * pl.po: New version by Alex. - -Thu Sep 23 06:26:28 1999 Werner Koch (wk@gnupg.org) - - * fr.po: Updated by Gal. - -Sat Sep 18 11:49:51 1999 Werner Koch (wk@gnupg.org) - - * id.po: New. Done by Tedi Heriyanto. - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * pt_PT.po: New. Done by Pedro Morais. - - * it.po: Updated by Marco. - -Tue Sep 7 16:23:36 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * pl.po: Updated. - -Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * fr.po: Imported and fixed a msgid. - * de.po: Ditto. - * pt_BR.po: Ditto. - - * POTFILES.in (delkey.c): New. - - * fr.po: Gal was the first to update it again. - -Wed Sep 1 15:30:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po: Updated. - -Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * it.po: Updated (Marco). - * de.po: Updated (Walter). - * pt_BR-po: Update (Thiago). - * fr.po: Updated (Gal). - -Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po: Updated (Walter). - -Mon Jul 26 09:34:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * it.po: Updated (Marco). - -Tue Jul 13 17:39:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po: Updated (Walter) - -Tue Jun 29 21:44:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * it.po: Updated (Marco). - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * pt_BR.po: Updated (Thiago). - -Thu Jun 10 14:18:23 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * it.po: Updated (Marco). - - * es_ES.po: Updated (Urko). - -Wed Jun 2 14:17:19 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * es_ES.po: Some patches (Urko Lusa). - -Mon May 31 19:41:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po: New version (Walter). - - * pl.po: New version (Alex). - -Tue May 25 19:50:32 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * fr.po: Imported new version. - -Mon May 17 21:54:43 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po, de.glo: New version from Walter. - -Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * fr.po: Imported new version. - -Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po: Imported update for 0.9.3 - -Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * pl.po: New version. - -Wed Jan 20 21:40:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * es_ES.po: Import of new version. - -Wed Jan 13 12:49:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * de.po de.glo: New version imported. - -Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * fr.po: Imported new version - -Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * pl.po: Janusz A. Urbanowicz contributed this one - -Thu Dec 17 18:31:15 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * fr.po: Imported new version - -Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * de.po: Imported new version. - -Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * *.po: Changed some english strings. - -Tue Dec 8 15:09:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * pt_BR.po: Add translation by Thiago Jung Bauermann. -Fri Nov 27 12:39:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * en.po: Removed - -Fri Nov 20 11:46:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * de.po: Imported new version - * de.glo: Glossary used for de.po. - -Sat Nov 14 10:16:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * es_ES.po: New translation by Urko Lusa. - -Tue Nov 10 10:48:02 1998 Werner Koch (wk@isil.d.shuttle.de) - - * it.po: Imported new version. - -Fri Oct 30 20:03:17 1998 Werner Koch (wk@isil.d.shuttle.de) - - * fr.po: Imported new version - -Mon Oct 12 09:08:09 1998 Werner Koch (wk@isil.d.shuttle.de) - - * it.po: Imported new version. - * de.po: Imported new version. - -Sun Oct 11 16:24:27 1998 Werner Koch (wk@isil.d.shuttle.de) - - * fr.po: Imported new version - -Wed Oct 7 13:12:00 1998 Werner Koch (wk@isil.d.shuttle.de) - - * Makefile.in.in: Fixed mkinstalldirs problems - -Mon Sep 21 15:03:44 1998 Werner Koch (wk@(none)) - - * it.po: New version from Marco d'Itri - -Mon Sep 21 09:28:54 1998 Werner Koch (wk@(none)) - - * fr.po: New version from Gal Quri - -Tue Aug 11 12:28:11 1998 Werner Koch (wk@(none)) - - * it.po: New file from Marco. - -Thu Jul 9 21:14:51 1998 Werner Koch (wk@isil.d.shuttle.de) - - * de.po: Fixed typos and added new translations. - -Fri Jun 26 11:44:24 1998 Werner Koch (wk@isil.d.shuttle.de) - - * it.po: New file from Marco. - -Thu May 28 10:44:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * it.po: Add small corrections from Marco - -Thu Apr 9 10:03:14 1998 Werner Koch (wk@isil.d.shuttle.de) - - * it.po: New version from Marco - -Fri Mar 13 09:43:19 1998 Werner Koch (wk@isil.d.shuttle.de) - - * it.po: New - - - - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + 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 @@ -504,5 +18,5 @@ Fri Mar 13 09:43:19 1998 Werner Koch (wk@isil.d.shuttle.de) 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. - + diff --git a/po/POTFILES.in b/po/POTFILES.in index 9a8c152dc..7cb83ded6 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,50 +1,33 @@ -# List of source files containing translatable strings for G10. -# Copyright (c) 1998 by Werner Koch (dd9jn) +# List of files with translatable strings. -# utility -util/secmem.c -util/argparse.c -util/miscutil.c -util/errors.c -util/logger.c +agent/gpg-agent.c +agent/protect-tool.c +agent/simple-pwquery.c +agent/divert-scd.c +agent/genkey.c +agent/query.c -# cipher -cipher/random.c -cipher/rndlinux.c +common/sysutils.c -# main program +jnlib/argparse.c +jnlib/logging.c -g10/g10.c -g10/armor.c -g10/pkclist.c -g10/keygen.c -g10/decrypt.c -g10/encode.c -g10/export.c -g10/getkey.c -g10/import.c -g10/keyedit.c -g10/keylist.c -g10/mainproc.c -g10/misc.c -g10/parse-packet.c -g10/passphrase.c -g10/plaintext.c -g10/pubkey-enc.c -g10/seckey-cert.c -g10/sig-check.c -g10/sign.c -g10/textfilter.c -g10/tdbio.c -g10/trustdb.c -g10/verify.c -g10/skclist.c -g10/status.c -g10/pubkey-enc.c -g10/openfile.c -g10/encr-data.c -g10/seskey.c -g10/delkey.c -g10/helptext.c -g10/keydb.c -g10/keyring.c +kbx/kbxutil.c + +scd/scdaemon.c + +sm/base64.c +sm/call-agent.c +sm/call-dirmngr.c +sm/certdump.c +sm/certlist.c +sm/certchain.c +sm/decrypt.c +sm/delete.c +sm/encrypt.c +sm/gpgsm.c +sm/import.c +sm/keydb.c +sm/keylist.c +sm/sign.c +sm/verify.c diff --git a/po/de.po b/po/de.po index d11d8d9bc..67ffdee9e 100644 --- a/po/de.po +++ b/po/de.po @@ -1,747 +1,806 @@ -# GnuPG german translation -# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -# Walter Koch <koch@hsp.de>, 1998, 1999, 2000, 2001 +# German translationn for NewPG which will soon be merged with GnuPG. +# Copyright (C) 2002 Free Software Foundation, Inc. +# Werner Koch <wk@gnupg.org>, 2002. +# msgid "" msgstr "" -"Project-Id-Version: gnupg-1.0.7\n" -"POT-Creation-Date: 2002-11-11 19:56+0100\n" -"PO-Revision-Date: 2002-09-11 15:40+0200\n" -"Last-Translator: Walter Koch <koch@hsp.de>\n" -"Language-Team: German <de@li.org>\n" +"Project-Id-Version: NewPG 0.9.3\n" +"POT-Creation-Date: 2002-12-04 20:14+0100\n" +"PO-Revision-Date: 2002-08-21 13:13+0200\n" +"Last-Translator: Werner Koch <wk@gnupg.org>\n" +"Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: util/secmem.c:90 -msgid "WARNING: using insecure memory!\n" -msgstr "WARNUNG: Sensible Daten knnten auf Platte ausgelagert werden.\n" +#: agent/gpg-agent.c:92 agent/protect-tool.c:85 scd/scdaemon.c:78 +msgid "" +"@Options:\n" +" " +msgstr "" +"@Optionen:\n" +" " -#: util/secmem.c:91 -msgid "please see http://www.gnupg.org/faq.html for more information\n" -msgstr "siehe http://www.gnupg.org/de/faq.html fr weitere Informationen\n" +#: agent/gpg-agent.c:94 scd/scdaemon.c:80 +msgid "run in server mode (foreground)" +msgstr "Im Server Modus ausfhren" -# " Um dies zu vermeiden, kann das Programm suid(root) installiert werden.\n" -# " Bitte wenden Sie sich hierzu an den Systemadministrator.\n" -#: util/secmem.c:328 -msgid "operation is not possible without initialized secure memory\n" -msgstr "Vorgang ist ohne sicheren Hauptspeicher nicht mglich\n" +#: agent/gpg-agent.c:95 scd/scdaemon.c:81 +msgid "run in daemon mode (background)" +msgstr "Im Daemon Modus ausfhren" -#: util/secmem.c:329 -msgid "(you may have used the wrong program for this task)\n" -msgstr "" -"(mglicherweise haben Sie das falsche Programm fr diese Aufgabe benutzt)\n" +#: agent/gpg-agent.c:96 kbx/kbxutil.c:72 scd/scdaemon.c:82 sm/gpgsm.c:287 +msgid "verbose" +msgstr "ausfhrlich" + +#: agent/gpg-agent.c:97 kbx/kbxutil.c:73 scd/scdaemon.c:83 sm/gpgsm.c:288 +msgid "be somewhat more quiet" +msgstr "etwas weniger Aussageb erzeugen" -#: util/miscutil.c:296 util/miscutil.c:331 -msgid "yes" -msgstr "ja" +#: agent/gpg-agent.c:98 scd/scdaemon.c:84 +msgid "sh-style command output" +msgstr "Ausgabe fr /bin/sh" -#: util/miscutil.c:297 util/miscutil.c:334 -msgid "yY" -msgstr "jJyY" +#: agent/gpg-agent.c:99 scd/scdaemon.c:85 +msgid "csh-style command output" +msgstr "Ausgabe fr /bin/csh" -#: util/miscutil.c:298 util/miscutil.c:332 -msgid "no" -msgstr "nein" +#: agent/gpg-agent.c:100 scd/scdaemon.c:86 sm/gpgsm.c:307 +msgid "read options from file" +msgstr "Konfigurationsoptionen aus Datei lesen" + +#: agent/gpg-agent.c:101 kbx/kbxutil.c:76 scd/scdaemon.c:87 +msgid "set debugging flags" +msgstr "Debug Flags setzen" -#: util/miscutil.c:299 util/miscutil.c:335 -msgid "nN" -msgstr "nN" +#: agent/gpg-agent.c:102 kbx/kbxutil.c:77 scd/scdaemon.c:88 +msgid "enable full debugging" +msgstr "Alle Debug Flags setzen" -#: g10/keyedit.c:1032 util/miscutil.c:333 -msgid "quit" -msgstr "quit" +#: agent/gpg-agent.c:104 scd/scdaemon.c:91 +msgid "do not detach from the console" +msgstr "Im Vordergrund laufen lassen" -#: util/miscutil.c:336 -msgid "qQ" -msgstr "qQ" +#: agent/gpg-agent.c:105 +msgid "do not grab keyboard and mouse" +msgstr "Tastatur und Maus nicht \"grabben\"" -#: util/errors.c:54 -msgid "general error" -msgstr "Allgemeiner Fehler" +#: agent/gpg-agent.c:106 scd/scdaemon.c:92 sm/gpgsm.c:290 +msgid "use a log file for the server" +msgstr "Logausgaben in eine Datei umlenken" -#: util/errors.c:55 -msgid "unknown packet type" -msgstr "Unbekannter Pakettyp" +#: agent/gpg-agent.c:107 +msgid "do not allow multiple connections" +msgstr "Nicht mehr als eine Verbindung erlauben" + +#: agent/gpg-agent.c:121 +msgid "ignore requests to change the TTY" +msgstr "" -#: util/errors.c:56 -msgid "unknown version" -msgstr "Unbekannte Version" +#: agent/gpg-agent.c:123 +msgid "ignore requests to change the X display" +msgstr "" -#: util/errors.c:57 -msgid "unknown pubkey algorithm" -msgstr "Unbekanntes Public-Key-Verfahren" +#: agent/gpg-agent.c:169 agent/protect-tool.c:113 scd/scdaemon.c:117 +#: sm/gpgsm.c:447 +msgid "Please report bugs to <" +msgstr "Fehlerberichte bitte an <" -#: util/errors.c:58 -msgid "unknown digest algorithm" -msgstr "Unbekanntes Hashverfahren" +#: agent/gpg-agent.c:169 agent/protect-tool.c:113 scd/scdaemon.c:117 +#: sm/gpgsm.c:447 +msgid ">.\n" +msgstr ">.\n" -#: util/errors.c:59 -msgid "bad public key" -msgstr "Falscher ffentlicher Schssel" +#: agent/gpg-agent.c:172 +msgid "Usage: gpg-agent [options] (-h for help)" +msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: util/errors.c:60 -msgid "bad secret key" -msgstr "Falscher geheimer Schlssel" +#: agent/gpg-agent.c:174 +msgid "" +"Syntax: gpg-agent [options] [command [args]]\n" +"Secret key management for GnuPG\n" +msgstr "" +"Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" +"Verwaltung von geheimen Schlssel fr GnuPG\n" -#: util/errors.c:61 -msgid "bad signature" -msgstr "Falsche Unterschrift" +#: agent/gpg-agent.c:343 agent/protect-tool.c:822 kbx/kbxutil.c:229 +#: scd/scdaemon.c:245 sm/gpgsm.c:628 +#, c-format +msgid "libgcrypt is too old (need %s, have %s)\n" +msgstr "" +"Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: util/errors.c:62 -msgid "checksum error" -msgstr "Prfsummen-Fehler" +#: agent/gpg-agent.c:414 scd/scdaemon.c:316 sm/gpgsm.c:722 +#, c-format +msgid "NOTE: no default option file `%s'\n" +msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: util/errors.c:63 -msgid "bad passphrase" -msgstr "Falsches Mantra" +#: agent/gpg-agent.c:419 agent/gpg-agent.c:829 scd/scdaemon.c:321 +#: sm/gpgsm.c:726 +#, c-format +msgid "option file `%s': %s\n" +msgstr "Konfigurationsdatei `%s': %s\n" -#: util/errors.c:64 -msgid "public key not found" -msgstr "ffentlicher Schlssel nicht gefunden" +#: agent/gpg-agent.c:427 scd/scdaemon.c:329 sm/gpgsm.c:733 +#, c-format +msgid "reading options from `%s'\n" +msgstr "Optionen werden aus `%s' gelesen\n" -#: util/errors.c:65 -msgid "unknown cipher algorithm" -msgstr "Unbekanntes Verschlsselungsverfahren" +#: agent/gpg-agent.c:519 scd/scdaemon.c:424 +msgid "please use the option `--daemon' to run the program in the background\n" +msgstr "" +"Bitte die Option `--daemon' nutzen um das Programm im Hintergund " +"auszufhren\n" -#: util/errors.c:66 -msgid "can't open the keyring" -msgstr "Der Schlsselbund kann nicht geffnet werden" +#: agent/gpg-agent.c:861 agent/gpg-agent.c:895 +#, c-format +msgid "can't create directory `%s': %s\n" +msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: util/errors.c:67 -msgid "invalid packet" -msgstr "Ungltiges Paket" +#: agent/gpg-agent.c:864 agent/gpg-agent.c:900 +#, c-format +msgid "directory `%s' created\n" +msgstr "Verzeichniss `%s' wurde erstellt\n" -#: util/errors.c:68 -msgid "invalid armor" -msgstr "Ungltige ASCII-Hlle" +#: agent/protect-tool.c:116 +msgid "Usage: gpg-protect-tool [options] (-h for help)\n" +msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" -#: util/errors.c:69 -msgid "no such user id" -msgstr "Keine solche User-ID" +#: agent/protect-tool.c:118 +msgid "" +"Syntax: gpg-protect-tool [options] [args]]\n" +"Secret key maintenance tool\n" +msgstr "" +"Syntax: gpg-protect-tool [Optionen] [Argumente]\n" +"Werkzeug zum Bearbeiten von geheimen Schlsseln\n" -#: util/errors.c:70 -msgid "secret key not available" -msgstr "Geheimer Schlssel ist nicht vorhanden" +#: agent/protect-tool.c:902 +msgid "Enter passphrase:" +msgstr "Bitte das Mantra (Passphrase) eingeben:" -#: util/errors.c:71 -msgid "wrong secret key used" -msgstr "Falscher geheimer Schlssel benutzt" +#: agent/protect-tool.c:903 +msgid "" +"Please enter the passphrase or the PIN\n" +"needed to complete this operation." +msgstr "" +"Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" +"wird bentigt um diese Aktion auszufhren." -#: util/errors.c:72 -msgid "not supported" -msgstr "Wird nicht untersttzt" +#: agent/simple-pwquery.c:272 +msgid "gpg-agent is not available in this session\n" +msgstr "Der gpg-agent ist nicht verfgbar\n" -#: util/errors.c:73 -msgid "bad key" -msgstr "Falscher Schlssel" +#: agent/simple-pwquery.c:281 sm/call-agent.c:195 +msgid "malformed GPG_AGENT_INFO environment variable\n" +msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: util/errors.c:74 -msgid "file read error" -msgstr "Dateilesefehler" +#: agent/simple-pwquery.c:293 sm/call-agent.c:207 +#, c-format +msgid "gpg-agent protocol version %d is not supported\n" +msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" -#: util/errors.c:75 -msgid "file write error" -msgstr "Dateischreibfehler" +#: agent/simple-pwquery.c:315 +#, c-format +msgid "can't connect to `%s': %s\n" +msgstr "Verbindung zu `%s' kann nicht aufgebaut werden: %s\n" -#: util/errors.c:76 -msgid "unknown compress algorithm" -msgstr "Unbekanntes Komprimierverfahren" +#: agent/simple-pwquery.c:326 +msgid "communication problem with gpg-agent\n" +msgstr "Kommunikationsproblem mit gpg-agent\n" -#: util/errors.c:77 -msgid "file open error" -msgstr "Fehler beim ffnen der Datei" +#: agent/simple-pwquery.c:336 +msgid "problem setting the gpg-agent options\n" +msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: util/errors.c:78 -msgid "file create error" -msgstr "Fehler beim Erzeugen der Datei" +#: agent/simple-pwquery.c:466 +msgid "canceled by user\n" +msgstr "Vom Benutzer abgebrochen\n" -#: util/errors.c:79 -msgid "invalid passphrase" -msgstr "Ungltiges Mantra" +#: agent/simple-pwquery.c:473 +msgid "problem with the agent\n" +msgstr "Problem mit dem Agenten\n" -#: util/errors.c:80 -msgid "unimplemented pubkey algorithm" -msgstr "nicht implementiertes ffentliches Schlsselverfahren" +#: agent/divert-scd.c:192 +#, c-format +msgid "Please enter the PIN%s%s%s to unlock the card" +msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" -#: util/errors.c:81 -msgid "unimplemented cipher algorithm" -msgstr "Verschlsselungsverfahren ist nicht implementiert" +#. okay +#: agent/genkey.c:82 +msgid "does not match - try again" +msgstr "Keine bereinstimmung - bitte nochmal versuchen" -#: util/errors.c:82 -msgid "unknown signature class" -msgstr "Unbekannte Unterschriftenklasse" +#: agent/genkey.c:109 +msgid "Please enter the passphrase to%0Ato protect your new key" +msgstr "" +"Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlssel zu schtzen" -#: util/errors.c:83 -msgid "trust database error" -msgstr "Fehler in der Trust-DB" +#: agent/genkey.c:111 agent/genkey.c:212 +msgid "Please re-enter this passphrase" +msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" -#: util/errors.c:84 -msgid "bad MPI" -msgstr "Falsche MPI" +#: agent/genkey.c:211 +msgid "Please enter the new passphrase" +msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: util/errors.c:85 -msgid "resource limit" -msgstr "festdefinierte Ressourcenobergrenze erreicht" +#: agent/query.c:255 +msgid "" +"Please enter your PIN, so that the secret key can be unlocked for this " +"session" +msgstr "" +"Bitte geben Sie Ihre PIN ein, so da der geheime Schlssel benutzt werden " +"kann" -#: util/errors.c:86 -msgid "invalid keyring" -msgstr "Ungltiger Schlsselbund" +#: agent/query.c:258 +msgid "" +"Please enter your passphrase, so that the secret key can be unlocked for " +"this session" +msgstr "" +"Bitte geben Sie Ihr Mantra (Passphrase) ein, so da der geheime Schlssel " +"benutzt werden kann" -#: util/errors.c:87 -msgid "bad certificate" -msgstr "Falsches Zertifikat" +#: agent/query.c:301 agent/query.c:313 +msgid "PIN too long" +msgstr "Die PIN ist zu lang" -#: util/errors.c:88 -msgid "malformed user id" -msgstr "Ungnstig aufgebaute User-ID" +#: agent/query.c:302 +msgid "Passphrase too long" +msgstr "Das Matra (Passphrase) ist zu lang" -#: util/errors.c:89 -msgid "file close error" -msgstr "Fehler beim Schlieen der Datei" +#: agent/query.c:310 +msgid "Invalid characters in PIN" +msgstr "Ungltige Zeichen in der PIN" -#: util/errors.c:90 -msgid "file rename error" -msgstr "Fehler beim Umbenennen einer Datei" +#: agent/query.c:315 +msgid "PIN too short" +msgstr "Die PIN ist zu kurz" -#: util/errors.c:91 -msgid "file delete error" -msgstr "Fehler beim Lschen einer Datei" +#: agent/query.c:326 +msgid "Bad PIN" +msgstr "Falsche PIN" -#: util/errors.c:92 -msgid "unexpected data" -msgstr "Unerwartete Daten" +#: agent/query.c:327 +msgid "Bad Passphrase" +msgstr "Falsches Mantra (Passphrase)" -#: util/errors.c:93 -msgid "timestamp conflict" -msgstr "Zeitangaben differieren" +#: agent/query.c:366 +msgid "Passphrase" +msgstr "Mantra" -#: util/errors.c:94 -msgid "unusable pubkey algorithm" -msgstr "Unbenutzbares ffentliches Schlsselverfahren" +#: common/sysutils.c:84 +#, c-format +msgid "can't disable core dumps: %s\n" +msgstr "" +"Das Erstellen eines Speicherabzugs (core-dump) kann nicht verhindert werden: " +"%s\n" -#: util/errors.c:95 -msgid "file exists" -msgstr "Datei existiert bereits" +#: common/sysutils.c:158 +#, c-format +msgid "Warning: unsafe ownership on %s \"%s\"\n" +msgstr "WARNUNG: Unsichere Besitzrechte fr %s \"%s\"\n" -#: util/errors.c:96 -msgid "weak key" -msgstr "Unsicherer Schlssel" +#: common/sysutils.c:190 +#, c-format +msgid "Warning: unsafe permissions on %s \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" -#: util/errors.c:97 -msgid "invalid argument" -msgstr "Ungltiges Argument" +#: jnlib/logging.c:343 +#, c-format +msgid "you found a bug ... (%s:%d)\n" +msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: util/errors.c:98 -msgid "bad URI" -msgstr "fehlerhafter URI" +#: kbx/kbxutil.c:61 sm/gpgsm.c:208 +msgid "" +"@Commands:\n" +" " +msgstr "" +"@Kommandos:\n" +" " -#: util/errors.c:99 -msgid "unsupported URI" -msgstr "Nicht untersttzter URI" +#: kbx/kbxutil.c:67 sm/gpgsm.c:237 +msgid "" +"@\n" +"Options:\n" +" " +msgstr "" +"@\n" +"Optionen:\n" +" " -#: util/errors.c:100 -msgid "network error" -msgstr "Netzwerkfehler" +#: kbx/kbxutil.c:69 sm/gpgsm.c:239 +msgid "create ascii armored output" +msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: util/errors.c:102 -msgid "not encrypted" -msgstr "nicht verschlsselt" +#: kbx/kbxutil.c:71 sm/gpgsm.c:286 +msgid "use as output file" +msgstr "als Ausgabedatei benutzen" -#: util/errors.c:103 -msgid "not processed" -msgstr "nicht bearbeitet" +#: kbx/kbxutil.c:74 sm/gpgsm.c:295 +msgid "do not make any changes" +msgstr "Keine nderungen durchfhren" -#. the key cannot be used for a specific usage -#: util/errors.c:105 -msgid "unusable public key" -msgstr "unbrauchbarer ffentlicher Schssel" +#: kbx/kbxutil.c:98 +msgid "Please report bugs to " +msgstr "Bite richten sie Berichte ber Bugs (Softwarefehler) an " -#: util/errors.c:106 -msgid "unusable secret key" -msgstr "unbrauchbarer geheimer Schlssel" +#: kbx/kbxutil.c:98 +msgid ".\n" +msgstr ".\n" -#: util/errors.c:107 -msgid "keyserver error" -msgstr "Schlsselserverfehler" +#: kbx/kbxutil.c:102 +msgid "Usage: kbxutil [options] [files] (-h for help)" +msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h fr Hilfe)" -#: util/logger.c:183 -msgid "ERROR: " +#: kbx/kbxutil.c:105 +msgid "" +"Syntax: kbxutil [options] [files]\n" +"list, export, import Keybox data\n" msgstr "" +"Syntax: kbxutil [Optionen] [Dateien]\n" +"Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: util/logger.c:186 -msgid "WARNING: " +#: scd/scdaemon.c:90 +msgid "|N|set OpenSC debug level to N" +msgstr "|N|Den OpenSC Debugstufe auf N setzen" + +#: scd/scdaemon.c:120 +msgid "Usage: scdaemon [options] (-h for help)" +msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" + +#: scd/scdaemon.c:122 +msgid "" +"Syntax: scdaemon [options] [command [args]]\n" +"Smartcard daemon for GnuPG\n" msgstr "" +"Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" +"Smartcard Daemon fr GnuPG\n" -#: util/logger.c:279 +#: sm/base64.c:295 #, c-format -msgid "... this is a bug (%s:%d:%s)\n" -msgstr "... dies ist ein Bug (Programmfehler) (%s:%d:%s)\n" +msgid "invalid radix64 character %02x skipped\n" +msgstr "Ungltiges Basis-64 Zeichen %02X wurde bergangen\n" -#: util/logger.c:285 +#: sm/call-agent.c:158 +msgid "no running gpg-agent - starting one\n" +msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" + +#: sm/call-agent.c:218 +msgid "can't connect to the agent - trying fall back\n" +msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" + +#: sm/call-dirmngr.c:153 +msgid "no running dirmngr - starting one\n" +msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" + +#: sm/call-dirmngr.c:190 +msgid "malformed DIRMNGR_INFO environment variable\n" +msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" + +#: sm/call-dirmngr.c:202 #, c-format -msgid "you found a bug ... (%s:%d)\n" -msgstr "Sie haben eine Bug (Programmfehler) gefunden ... (%s:%d)\n" +msgid "dirmngr protocol version %d is not supported\n" +msgstr "Die Dirmngr Protokollversion %d wird nicht untersttzt\n" + +#: sm/call-dirmngr.c:213 +msgid "can't connect to the dirmngr - trying fall back\n" +msgstr "" +"Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " +"versucht\n" + +#: sm/certdump.c:51 sm/certdump.c:99 +msgid "none" +msgstr "keine" -#: cipher/random.c:157 -msgid "no entropy gathering module detected\n" -msgstr "Kein Modul zum sammeln von Entropie vorhanden\n" +#: sm/certdump.c:119 +msgid "[none]" +msgstr "[keine]" -#: cipher/random.c:381 g10/import.c:200 g10/keygen.c:1820 +#: sm/certdump.c:121 +msgid "[error]" +msgstr "[Fehler]" + +#: sm/certdump.c:424 +msgid "[Error - No name]" +msgstr "[Fehler - Kein Name]" + +#: sm/certdump.c:433 +msgid "[Error - unknown encoding]" +msgstr "[Fehler - Unbekannte Kodierung]" + +#: sm/certdump.c:437 +msgid "[Error - invalid encoding]" +msgstr "[Fehler - Ungltige Kodierung]" + +#: sm/certdump.c:442 +msgid "[Error - invalid DN]" +msgstr "[Fehler - Ungltiger DN]" + +#: sm/certlist.c:52 +msgid "no key usage specified - accepted for encryption\n" +msgstr "" +"Schlsselverwendungszweck nicht vorhanden - wird zum Verschlsseln " +"akzeptiert\n" + +#: sm/certlist.c:53 +msgid "no key usage specified - accepted for signing\n" +msgstr "" +"Schlsselverwendungszweck nicht vorhanden - wird zum Signieren akzeptiert\n" + +#: sm/certlist.c:58 sm/keylist.c:82 #, c-format -msgid "can't open `%s': %s\n" -msgstr "'%s' kann nicht geffnet werden: %s\n" +msgid "error getting key usage information: %s\n" +msgstr "Fehler beim holen der Schlsselbenutzungsinformationen: %s\n" + +#: sm/certlist.c:67 +msgid "certificate should have not been used certification\n" +msgstr "Das Zertifikat hatte nicht zum Zertifizieren benutzt werden sollen\n" + +#: sm/certlist.c:76 +msgid "certificate should have not been used for encryption\n" +msgstr "Das Zertifikat hatte nicht zum Verschlsseln benutzt werden sollen\n" -#: cipher/random.c:385 +#: sm/certlist.c:77 +msgid "certificate should have not been used for signing\n" +msgstr "Das Zertifikat hatte nicht zum Signieren benutzt werden sollen\n" + +#: sm/certlist.c:78 +msgid "certificate is not usable for encryption\n" +msgstr "Das Zertifikat kann nicht zum Verschlsseln benutzt werden\n" + +#: sm/certlist.c:79 +msgid "certificate is not usable for signing\n" +msgstr "Das Zertifikat kann nicht zum Signieren benutzt werden\n" + +#: sm/certchain.c:59 #, c-format -msgid "can't stat `%s': %s\n" -msgstr "Status von '%s' ist nicht feststellbar: %s\n" +msgid "critical certificate extension %s is not supported\n" +msgstr "Die kritische Zertifikaterweiterung %s wird nicht untersttzt\n" + +#: sm/certchain.c:81 +msgid "issuer certificate is not marked as a CA\n" +msgstr "Das Herausgeberzertifikat ist fr eine CA nicht zulssig\n" -#: cipher/random.c:390 +#: sm/certchain.c:151 +msgid "note: certificate policy not allowed\n" +msgstr "Notiz: Die Zertifikatrichtilinie ist nicht erlaubt\n" + +#: sm/certchain.c:154 +msgid "certificate policy not allowed\n" +msgstr "Die Zertifikatrichtilinie ist nicht erlaubt\n" + +#: sm/certchain.c:280 +msgid "looking up issuer at external location\n" +msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" + +#: sm/certchain.c:298 #, c-format -msgid "`%s' is not a regular file - ignored\n" -msgstr "'%s' ist keine normale Datei - sie bleibt unbeachtet\n" +msgid "number of issuers matching: %d\n" +msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" + +#: sm/certchain.c:334 sm/certchain.c:433 sm/certchain.c:719 sm/decrypt.c:263 +#: sm/encrypt.c:377 sm/sign.c:315 sm/verify.c:116 +msgid "failed to allocated keyDB handle\n" +msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" -#: cipher/random.c:395 -msgid "note: random_seed file is empty\n" -msgstr "Hinweis: 'random_seed'-Datei ist leer\n" +#: sm/certchain.c:519 +msgid "the certificate has been revoked\n" +msgstr "Das Zertifikat wurde widerrufen\n" -#: cipher/random.c:401 -msgid "WARNING: invalid size of random_seed file - not used\n" +#: sm/certchain.c:523 +msgid "no CRL found for certificate\n" +msgstr "Keine CRL fr das Zertifikat vorhanden\n" + +#: sm/certchain.c:527 +msgid "the available CRL is too old\n" +msgstr "Die vorhandene CRL ist zu alt\n" + +#: sm/certchain.c:528 +msgid "please make sure that the \"dirmngr\" is properly installed\n" msgstr "" -"WARNUNG: Falsche Gre der 'random_seed'-Datei - sie wird nicht verwendet\n" +"Bite vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" -#: cipher/random.c:409 +#: sm/certchain.c:533 #, c-format -msgid "can't read `%s': %s\n" -msgstr "'%s' ist unlesbar: %s\n" +msgid "checking the CRL failed: %s\n" +msgstr "Die CRL konnte nicht geprft werden: %s\n" -#: cipher/random.c:447 -msgid "note: random_seed file not updated\n" -msgstr "Hinweis: 'random_seed'-Datei bleibt unverndert\n" +#: sm/certchain.c:562 +msgid "root certificate is not marked trusted\n" +msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert\n" -#: cipher/random.c:467 +#: sm/certchain.c:563 #, c-format -msgid "can't create `%s': %s\n" -msgstr "'%s' kann nicht erzeugt werden: %s\n" +msgid "fingerprint=%s\n" +msgstr "Fingerprint=%s\n" -#: cipher/random.c:474 -#, c-format -msgid "can't write `%s': %s\n" -msgstr "kann '%s' nicht schreiben: %s\n" +#: sm/certchain.c:568 +msgid "root certificate has now been marked as trusted\n" +msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" -#: cipher/random.c:477 +#: sm/certchain.c:582 #, c-format -msgid "can't close `%s': %s\n" -msgstr "kann '%s' nicht schliessen: %s\n" +msgid "checking the trust list failed: %s\n" +msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" + +#: sm/certchain.c:592 sm/import.c:127 +msgid "certificate chain too long\n" +msgstr "Der Zertifikatkette ist zu lang\n" -#: cipher/random.c:723 -msgid "WARNING: using insecure random number generator!!\n" -msgstr "WARNUNG: Der Zufallsgenerator erzeugt keine echten Zufallszahlen!\n" +#: sm/certchain.c:643 +#, c-format +msgid "certificate chain longer than allowed by CA (%d)\n" +msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)\n" -#: cipher/random.c:724 +#: sm/decrypt.c:128 msgid "" -"The random number generator is only a kludge to let\n" -"it run - it is in no way a strong RNG!\n" -"\n" -"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" -"\n" +"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" msgstr "" -"Der Zufallsgenerator (RNG) ist lediglich ein \"kludge\", damit das\n" -"Programms berhaupt luft - es ist KEINESFALLS ein starker RNG!\n" -"\n" -"BENUTZEN SIE DIE DURCH DIESES PROGRAMM ERZEUGTEN DATEN NICHT!\n" -"\n" +"WARNUNG: Die Nachricht wurde mich einem schwachen Schlssel (Weak Key) " +"erzeugt\n" + +#: sm/decrypt.c:333 +msgid "(this is the RC2 algorithm)\n" +msgstr "(Dies ist der RC-2 Algorithmus)\n" + +#: sm/decrypt.c:335 +msgid "(this does not seem to be an encrypted message)\n" +msgstr "(dies is wahrscheinlich keine verschlsselte Nachricht)\n" -#: cipher/rndlinux.c:134 +#: sm/delete.c:51 sm/delete.c:102 #, c-format -msgid "" -"\n" -"Not enough random bytes available. Please do some other work to give\n" -"the OS a chance to collect more entropy! (Need %d more bytes)\n" -msgstr "" -"\n" -"Es sind nicht gengend Zufallswerte vorhanden. Bitte fhren Sie andere\n" -"Arbeiten durch, damit das Betriebssystem weitere Entropie sammeln kann!\n" -"(Es werden noch %d Byte bentigt.)\n" +msgid "certificate `%s' not found: %s\n" +msgstr "Zertifikat `%s' nicht gefunden: %s\n" -#: g10/g10.c:316 -msgid "" -"@Commands:\n" -" " -msgstr "" -"@Befehle:\n" -" " +#: sm/delete.c:126 +#, c-format +msgid "duplicated certificate `%s' deleted\n" +msgstr "Doppeltes Zertifikat `%s' gelscht\n" + +#: sm/delete.c:128 +#, c-format +msgid "certificate `%s' deleted\n" +msgstr "Zertifikat `%s' gelscht\n" + +#: sm/delete.c:158 +#, c-format +msgid "deleting certificate \"%s\" failed: %s\n" +msgstr "Fehler beim Lschen des Zertifikats \"%s\": %s\n" + +#: sm/encrypt.c:105 +msgid "weak key created - retrying\n" +msgstr "Schwacher Schlssel - es wird erneut versucht\n" -#: g10/g10.c:318 +#: sm/encrypt.c:368 +msgid "no valid recipients given\n" +msgstr "Keine gltigen Empfnger angegeben\n" + +#: sm/gpgsm.c:210 msgid "|[file]|make a signature" -msgstr "|[Datei]|Eine Unterschrift erzeugen" +msgstr "|DATEI|Erzeufe eine Signatur" -#: g10/g10.c:319 +#: sm/gpgsm.c:211 msgid "|[file]|make a clear text signature" -msgstr "|[Datei]|Eine Klartextunterschrift erzeugen" +msgstr "|DATEI|Erzeuge eine Klartextsignatur" -#: g10/g10.c:320 +#: sm/gpgsm.c:212 msgid "make a detached signature" -msgstr "Eine abgetrennte Unterschrift erzeugen" +msgstr "Erzeuge eine abgetrennte Signatur" -#: g10/g10.c:321 +#: sm/gpgsm.c:213 msgid "encrypt data" -msgstr "Daten verschlsseln" - -#: g10/g10.c:322 -msgid "|[files]|encrypt files" -msgstr "|[Dateien]|Dateien verschlsseln" +msgstr "Verschlssele die Daten" -#: g10/g10.c:323 +#: sm/gpgsm.c:214 msgid "encryption only with symmetric cipher" -msgstr "Daten symmetrisch verschlsseln" +msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: g10/g10.c:324 -msgid "store only" -msgstr "Nur speichern" - -#: g10/g10.c:325 +#: sm/gpgsm.c:215 msgid "decrypt data (default)" -msgstr "Daten entschlsseln (Voreinstellung)" - -#: g10/g10.c:326 -msgid "|[files]|decrypt files" -msgstr "|[Dateien]|Dateien entschlsseln" +msgstr "Enschlssele die Daten" -#: g10/g10.c:327 +#: sm/gpgsm.c:216 msgid "verify a signature" -msgstr "Signatur prfen" +msgstr "berprfen einer Signatur" -#: g10/g10.c:329 +#: sm/gpgsm.c:218 msgid "list keys" -msgstr "Liste der Schlssel" +msgstr "Schlssel anzeigen" -#: g10/g10.c:331 -msgid "list keys and signatures" -msgstr "Liste der Schlssel und ihrer Signaturen" +#: sm/gpgsm.c:219 +msgid "list external keys" +msgstr "Externe Schlssel anzeigen" -#: g10/g10.c:332 -msgid "check key signatures" -msgstr "Signaturen der Schlssel prfen" - -#: g10/g10.c:333 -msgid "list keys and fingerprints" -msgstr "Liste der Schlssel und ihrer \"Fingerabdrcke\"" - -#: g10/g10.c:334 +#: sm/gpgsm.c:220 msgid "list secret keys" -msgstr "Liste der geheimen Schlssel" - -#: g10/g10.c:335 -msgid "generate a new key pair" -msgstr "Ein neues Schlsselpaar erzeugen" - -#: g10/g10.c:336 -msgid "remove keys from the public keyring" -msgstr "Schlssel aus dem ff. Schlsselbund entfernen" - -#: g10/g10.c:338 -msgid "remove keys from the secret keyring" -msgstr "Schlssel aus dem geh. Schlsselbund entfernen" - -#: g10/g10.c:339 -msgid "sign a key" -msgstr "Schlssel signieren" +msgstr "Geheime Schlssel anzeigen" -#: g10/g10.c:340 -msgid "sign a key locally" -msgstr "Schlssel nur fr diesen Rechner signieren" +#: sm/gpgsm.c:221 +msgid "list certificate chain" +msgstr "Schlssel mit Zertifikatekette anzeigen" -#: g10/g10.c:341 -msgid "sign a key non-revocably" -msgstr "Schlssel nicht widerrufbar signieren" - -#: g10/g10.c:342 -msgid "sign a key locally and non-revocably" -msgstr "Schlssel nur fr diesen Rechner und nicht-widerrufbar signieren" - -#: g10/g10.c:343 -msgid "sign or edit a key" -msgstr "Unterschreiben oder bearbeiten eines Schl." +#: sm/gpgsm.c:223 +msgid "list keys and fingerprints" +msgstr "Schlssel und Fingerprint anzeigen" -#: g10/g10.c:344 -msgid "generate a revocation certificate" -msgstr "Ein Schlsselwiderruf-Zertifikat erzeugen" +#: sm/gpgsm.c:224 +msgid "generate a new key pair" +msgstr "Neues Schlsselpaar erzeugen" -#: g10/g10.c:346 -msgid "export keys" -msgstr "Schlssel exportieren" +#: sm/gpgsm.c:225 +msgid "remove key from the public keyring" +msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: g10/g10.c:347 +#: sm/gpgsm.c:226 msgid "export keys to a key server" -msgstr "Schlssel zu einem Schl.server exportieren" +msgstr "Schlssen an eine Schlsselserver exportieren" -#: g10/g10.c:348 +#: sm/gpgsm.c:227 msgid "import keys from a key server" -msgstr "Schlssel von einem Schl.server importieren" +msgstr "Schlssel von einem Schlsselserver importieren" -#: g10/g10.c:350 -msgid "search for keys on a key server" -msgstr "Schlssel auf einem Schl.server suchen" +#: sm/gpgsm.c:228 +msgid "import certificates" +msgstr "Zertifikate importieren" -#: g10/g10.c:352 -msgid "update all keys from a keyserver" -msgstr "alle Schlssel per Schl.server aktualisieren" +#: sm/gpgsm.c:229 +msgid "export certificates" +msgstr "Zertifikate exportieren" -#: g10/g10.c:356 -msgid "import/merge keys" -msgstr "Schlssel importieren/kombinieren" +#: sm/gpgsm.c:230 +msgid "register a smartcard" +msgstr "Smartcard registrieren" -#: g10/g10.c:358 -msgid "list only the sequence of packets" -msgstr "Lediglich Struktur der Datenpakete anzeigen" +#: sm/gpgsm.c:231 +msgid "run in server mode" +msgstr "Im Server Modus ausfhren" -#: g10/g10.c:360 -msgid "export the ownertrust values" -msgstr "Exportieren der \"Owner trust\"-Werte" +#: sm/gpgsm.c:232 +msgid "pass a command to the dirmngr" +msgstr "" -#: g10/g10.c:362 -msgid "import ownertrust values" -msgstr "Importieren der \"Owner trust\"-Werte" +#: sm/gpgsm.c:234 +msgid "invoke gpg-protect-tool" +msgstr "" -#: g10/g10.c:364 -msgid "update the trust database" -msgstr "ndern der \"Trust\"-Datenbank" +#: sm/gpgsm.c:235 +msgid "change a passphrase" +msgstr "Das Mantra (Passphrase) ndern" -#: g10/g10.c:366 -msgid "unattended trust database update" -msgstr "unbeaufsichtigtes ndern der \"Trust\"-Datenbank" +#: sm/gpgsm.c:241 +msgid "create base-64 encoded output" +msgstr "Ausgabe im Basis-64 format erzeugen" -#: g10/g10.c:367 -msgid "fix a corrupted trust database" -msgstr "Reparieren einer beschdigten \"Trust\"-Datenb." +#: sm/gpgsm.c:243 +msgid "assume input is in PEM format" +msgstr "Eingabedaten sind im PEM Format" -#: g10/g10.c:368 -msgid "De-Armor a file or stdin" -msgstr "Datei oder stdin von der ASCII-Hlle befreien" +#: sm/gpgsm.c:245 +msgid "assume input is in base-64 format" +msgstr "Eingabedaten sin im Basis-64 Format" -#: g10/g10.c:370 -msgid "En-Armor a file or stdin" -msgstr "Datei oder stdin in eine ASCII-Hlle einpacken" +#: sm/gpgsm.c:247 +msgid "assume input is in binary format" +msgstr "Eingabedaten sind im Binrformat" -#: g10/g10.c:372 -msgid "|algo [files]|print message digests" -msgstr "|algo [Dateien]|Message-Digests fr die Dateien ausgeben" +#: sm/gpgsm.c:249 +msgid "|NAME|encrypt for NAME" +msgstr "|NAME|Verschlsseln fr NAME" -#: g10/g10.c:376 -msgid "" -"@\n" -"Options:\n" -" " -msgstr "" -"@\n" -"Optionen:\n" -" " +#: sm/gpgsm.c:252 +msgid "never consult a CRL" +msgstr "Niemals eine CRL konsultieren" -#: g10/g10.c:378 -msgid "create ascii armored output" -msgstr "Ausgabe mit ASCII-Hlle versehen" +#: sm/gpgsm.c:256 +msgid "|N|number of certificates to include" +msgstr "|N|Sende N Zertifikate mit" -#: g10/g10.c:380 -msgid "|NAME|encrypt for NAME" -msgstr "|NAME|Verschlsseln fr NAME" +#: sm/gpgsm.c:259 +msgid "|FILE|take policy information from FILE" +msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" + +#: sm/gpgsm.c:262 +msgid "do not check certificate policies" +msgstr "Zertikikatrichtlinien nicht berprfen" -#: g10/g10.c:384 +#: sm/gpgsm.c:266 +msgid "fetch missing issuer certificates" +msgstr "Fehlende Zertifikate automatisch holen" + +#: sm/gpgsm.c:270 msgid "|NAME|use NAME as default recipient" -msgstr "|NAME|NAME als voreingestellten Empfnger benutzen" +msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: g10/g10.c:386 +#: sm/gpgsm.c:272 msgid "use the default key as default recipient" -msgstr "" -"Den Standardschlssel als voreingestellten\n" -"Empfnger benutzen" +msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: g10/g10.c:393 +#: sm/gpgsm.c:278 msgid "use this user-id to sign or decrypt" -msgstr "Mit dieser User-ID signieren" +msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: g10/g10.c:394 +#: sm/gpgsm.c:281 msgid "|N|set compress level N (0 disables)" -msgstr "Kompressionsstufe auf N setzen (0=keine)" +msgstr "|N|Benutze Komprimierungsstufe N" -#: g10/g10.c:396 +#: sm/gpgsm.c:283 msgid "use canonical text mode" -msgstr "Textmodus benutzen" - -#: g10/g10.c:403 -msgid "use as output file" -msgstr "Als Ausgabedatei benutzen" - -#: g10/g10.c:404 -msgid "verbose" -msgstr "Detaillierte Informationen" - -#: g10/g10.c:405 -msgid "be somewhat more quiet" -msgstr "Etwas weniger Infos" +msgstr "" -#: g10/g10.c:406 +#: sm/gpgsm.c:289 msgid "don't use the terminal at all" -msgstr "das Terminal gar nicht benutzen" +msgstr "" -#: g10/g10.c:407 +#: sm/gpgsm.c:292 msgid "force v3 signatures" -msgstr "v3 Signaturen erzwingen" - -#: g10/g10.c:408 -msgid "do not force v3 signatures" -msgstr "v3 Signaturen nicht erzwingen" - -#: g10/g10.c:409 -msgid "force v4 key signatures" -msgstr "v4 Signaturen erzwingen" - -#: g10/g10.c:410 -msgid "do not force v4 key signatures" -msgstr "v4 Signaturen nicht erzwingen" +msgstr "" -#: g10/g10.c:411 +#: sm/gpgsm.c:293 msgid "always use a MDC for encryption" -msgstr "Beim Verschlsseln ein Siegel (MDC) verwenden" - -#: g10/g10.c:413 -msgid "never use a MDC for encryption" -msgstr "Beim Verschlsseln niemals ein Siegel (MDC) verwenden" - -#: g10/g10.c:415 -msgid "do not make any changes" -msgstr "Keine wirklichen nderungen durchfhren" - -#: g10/g10.c:416 -msgid "prompt before overwriting" -msgstr "vor berschreiben nachfragen" - -#: g10/g10.c:417 -msgid "use the gpg-agent" -msgstr "den GPG-Agent verwenden" +msgstr "" -#: g10/g10.c:420 +#. { oInteractive, "interactive", 0, N_("prompt before overwriting") }, +#. { oUseAgent, "use-agent",0, N_("use the gpg-agent")}, +#: sm/gpgsm.c:298 msgid "batch mode: never ask" -msgstr "Stapelmodus: Keine Abfragen" +msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: g10/g10.c:421 +#: sm/gpgsm.c:299 msgid "assume yes on most questions" -msgstr "\"Ja\" als Standardantwort annehmen" +msgstr "" -#: g10/g10.c:422 +#: sm/gpgsm.c:300 msgid "assume no on most questions" -msgstr "\"Nein\" als Standardantwort annehmen" +msgstr "" -#: g10/g10.c:423 +#: sm/gpgsm.c:302 msgid "add this keyring to the list of keyrings" -msgstr "Als ffentlichen Schlsselbund mitbenutzen" +msgstr "" -#: g10/g10.c:425 +#: sm/gpgsm.c:303 msgid "add this secret keyring to the list" -msgstr "Als geheimen Schlsselbund mitbenutzen" - -#: g10/g10.c:426 -msgid "show which keyring a listed key is on" -msgstr "Anzeigen des Schlsselbundes, in dem ein Schlssel drin ist" +msgstr "" -#: g10/g10.c:427 +#: sm/gpgsm.c:304 msgid "|NAME|use NAME as default secret key" -msgstr "|NAME|NAME als voreingestellten Schlssel benutzen" +msgstr "" -#: g10/g10.c:428 +#: sm/gpgsm.c:305 msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|Schlssel bei diesem Server nachschlagen" +msgstr "" -#: g10/g10.c:432 +#: sm/gpgsm.c:306 msgid "|NAME|set terminal charset to NAME" -msgstr "|NAME|Terminalzeichensatz NAME benutzen" - -#: g10/g10.c:433 -msgid "read options from file" -msgstr "Optionen aus der Datei lesen" +msgstr "" -#: g10/g10.c:437 +#: sm/gpgsm.c:313 msgid "|FD|write status info to this FD" -msgstr "|FD|Statusinfo auf FD (Dateihandle) ausgeben" - -#: g10/g10.c:439 -msgid "|[file]|write status info to file" -msgstr "|[Datei]|Statusinfo in Datei schreiben" - -#: g10/g10.c:451 -msgid "|KEYID|ultimately trust this key" -msgstr "|KEYID|diesem Schlssel uneingeschrnkt vertrauen" +msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: g10/g10.c:452 +#: sm/gpgsm.c:320 msgid "|FILE|load extension module FILE" -msgstr "|DATEI|Erweiterungsmodul DATEI laden" - -#: g10/g10.c:453 -msgid "emulate the mode described in RFC1991" -msgstr "Den in RFC1991 beschriebenen Modus nachahmen" - -#: g10/g10.c:454 -msgid "set all packet, cipher and digest options to OpenPGP behavior" -msgstr "" -"alle Paket-, Verschlsselungs- und\n" -"Hashoptionen auf OpenPGP-Verhalten einstellen" - -#: g10/g10.c:455 -msgid "set all packet, cipher and digest options to PGP 2.x behavior" msgstr "" -"alle Paket-, Verschlsselungs- und\n" -"Hashoptionen auf PGP 2.X-Verhalten einstellen" -#: g10/g10.c:461 -msgid "|N|use passphrase mode N" -msgstr "|N|Verwenden des Mantra-Modus N" - -#: g10/g10.c:463 -msgid "|NAME|use message digest algorithm NAME for passphrases" -msgstr "|NAME|Hashverfahren NAME fr Mantras benutzen" - -#: g10/g10.c:465 -msgid "|NAME|use cipher algorithm NAME for passphrases" -msgstr "|NAME|Verschl.verfahren NAME fr Mantras benutzen" - -#: g10/g10.c:467 +#: sm/gpgsm.c:326 msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAME|Verschl.verfahren NAME benutzen" +msgstr "|NAME|Den Verhsclsselungsalgrithmus NAME benutzen" -#: g10/g10.c:468 +#: sm/gpgsm.c:328 msgid "|NAME|use message digest algorithm NAME" -msgstr "|NAME|Hashverfahren NAME benutzen" +msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: g10/g10.c:470 +#: sm/gpgsm.c:330 msgid "|N|use compress algorithm N" -msgstr "|N|Komprimierverfahren N benutzen" - -#: g10/g10.c:471 -msgid "throw keyid field of encrypted packets" -msgstr "Empfnger-ID verschlsselter Pakete entfernen" +msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: g10/g10.c:473 -msgid "Show Photo IDs" -msgstr "Foto-IDs anzeigen" - -#: g10/g10.c:474 -msgid "Don't show Photo IDs" -msgstr "Foto-IDs nicht anzeigen" - -#: g10/g10.c:475 -msgid "Set command line to view Photo IDs" -msgstr "Kommandozeilentext fr den Foto-Betrachter setzen" - -#: g10/g10.c:481 +#: sm/gpgsm.c:336 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" msgstr "" "@\n" -"(Auf der \"man\"-Seite ist eine vollstndige Liste aller Kommandos und " -"Optionen)\n" +"(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: g10/g10.c:484 +#: sm/gpgsm.c:339 msgid "" "@\n" "Examples:\n" @@ -752,4503 +811,181 @@ msgid "" " --list-keys [names] show keys\n" " --fingerprint [names] show fingerprints\n" msgstr "" -"@\n" -"Beispiele:\n" -"\n" -" -se -r Bob [Datei] Signieren und verschlsseln fr Benutzer Bob\n" -" --clearsign [Datei] Eine Klartextsignatur erzeugen\n" -" --detach-sign [Datei] Eine abgetrennte Signatur erzeugen\n" -" --list-keys [Namen] Schlssel anzeigen\n" -" --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\n" - -#: g10/g10.c:640 -msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n" -msgstr "" -"Berichte ber Programmfehler bitte in englisch an <gnupg-bugs@gnu.org>.\n" -"Sinn- oder Schreibfehler in den deutschen Texten bitte an <de@li.org>.\n" -#: g10/g10.c:644 -msgid "Usage: gpg [options] [files] (-h for help)" -msgstr "Aufruf: gpg [Optionen] [Dateien] (-h fr Hilfe)" +#: sm/gpgsm.c:450 +msgid "Usage: gpgsm [options] [files] (-h for help)" +msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: g10/g10.c:647 +#: sm/gpgsm.c:453 msgid "" -"Syntax: gpg [options] [files]\n" -"sign, check, encrypt or decrypt\n" +"Syntax: gpgsm [options] [files]\n" +"sign, check, encrypt or decrypt using the S/MIME protocol\n" "default operation depends on the input data\n" msgstr "" -"Aufruf: gpg [Optionen] [Dateien]\n" -"Signieren, prfen, verschlsseln, entschlsseln.\n" -"Die voreingestellte Operation ist abhngig von den Eingabedaten.\n" +"Gebrauch: gpgsm [Optionen] [Dateien]\n" +"Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: g10/g10.c:658 +#: sm/gpgsm.c:460 msgid "" "\n" "Supported algorithms:\n" msgstr "" -"\n" -"Untersttzte Verfahren:\n" -#: g10/g10.c:762 -msgid "usage: gpg [options] " -msgstr "Aufruf: gpg [Optionen] " +#: sm/gpgsm.c:541 +msgid "usage: gpgsm [options] " +msgstr "Gebrauch: gpgsm [Optionen] " -#: g10/g10.c:830 +#: sm/gpgsm.c:574 msgid "conflicting commands\n" -msgstr "Widersprchliche Befehle\n" +msgstr "Widersprechende Kommandos\n" -#: g10/g10.c:848 +#: sm/gpgsm.c:633 #, c-format -msgid "no = sign found in group definition \"%s\"\n" -msgstr "Kein '='-Zeichen in der Gruppendefinition \"%s\"\n" - -#: g10/g10.c:1008 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on homedir \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1011 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on configuration file \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1014 -#, fuzzy, c-format -msgid "WARNING: unsafe ownership on extension \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" - -#: g10/g10.c:1020 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on homedir \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +msgid "libksba is too old (need %s, have %s)\n" +msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: g10/g10.c:1023 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on configuration file \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +#: sm/gpgsm.c:1027 +msgid "WARNING: program may create a core file!\n" +msgstr "" -#: g10/g10.c:1026 -#, fuzzy, c-format -msgid "WARNING: unsafe permissions on extension \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +#: sm/gpgsm.c:1037 +msgid "WARNING: running with faked system time: " +msgstr "" -#: g10/g10.c:1032 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on homedir \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" +#: sm/gpgsm.c:1056 +msgid "selected cipher algorithm is invalid\n" +msgstr "" -#: g10/g10.c:1035 -#, fuzzy, c-format -msgid "" -"WARNING: unsafe enclosing directory ownership on configuration file \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" +#: sm/gpgsm.c:1064 +msgid "selected digest algorithm is invalid\n" +msgstr "" -#: g10/g10.c:1038 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory ownership on extension \"%s\"\n" -msgstr "WARNUNG: Unsicheres Besitzverhltnis von %s \"%s\"\n" +#: sm/gpgsm.c:1096 +#, c-format +msgid "can't sign using `%s': %s\n" +msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: g10/g10.c:1044 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on homedir \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +#: sm/gpgsm.c:1118 +#, c-format +msgid "can't encrypt to `%s': %s\n" +msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: g10/g10.c:1047 -#, fuzzy, c-format -msgid "" -"WARNING: unsafe enclosing directory permissions on configuration file \"%s" -"\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +#: sm/gpgsm.c:1156 +msgid "--call-dirmngr <command> {args}" +msgstr "" -#: g10/g10.c:1050 -#, fuzzy, c-format -msgid "WARNING: unsafe enclosing directory permissions on extension \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +#: sm/gpgsm.c:1172 +msgid "--encrypt [datafile]" +msgstr "" -#: g10/g10.c:1236 -#, c-format -msgid "NOTE: old default options file `%s' ignored\n" -msgstr "Hinweis: Alte voreingestellte Optionendatei '%s' wurde ignoriert\n" +#: sm/gpgsm.c:1186 +msgid "--sign [datafile]" +msgstr "" -#: g10/g10.c:1272 -#, c-format -msgid "NOTE: no default option file `%s'\n" -msgstr "Hinweis: Keine voreingestellte Optionendatei '%s' vorhanden\n" +#: sm/gpgsm.c:1213 +msgid "--verify [signature [detached_data]]" +msgstr "" -#: g10/g10.c:1276 -#, c-format -msgid "option file `%s': %s\n" -msgstr "Optionendatei '%s': %s\n" +#: sm/gpgsm.c:1230 +msgid "--decrypt [filename]" +msgstr "" -#: g10/g10.c:1283 +#: sm/gpgsm.c:1408 sm/gpgsm.c:1441 #, c-format -msgid "reading options from `%s'\n" -msgstr "Optionen werden aus '%s' gelesen\n" +msgid "can't open `%s': %s\n" +msgstr "Datei `%s' kann nicht geffnet werden: %s\n" -#: g10/g10.c:1472 g10/g10.c:1805 g10/g10.c:1816 +#: sm/import.c:96 #, c-format -msgid "NOTE: %s is not for normal use!\n" -msgstr "Hinweis: %s ist nicht fr den blichen Gebrauch gedacht!\n" +msgid "total number processed: %lu\n" +msgstr "gesamte verarbeitete Anzahl: %lu\n" -#: g10/g10.c:1484 +#: sm/import.c:99 #, c-format -msgid "cipher extension \"%s\" not loaded due to unsafe permissions\n" -msgstr "" -"Verschlsselungserweiterung \"%s\" wurde wegen falscher Rechte nicht " -"geladen\n" +msgid " imported: %lu" +msgstr " importiert: %lu" -#: g10/g10.c:1627 +#: sm/import.c:103 #, c-format -msgid "%s is not a valid character set\n" -msgstr "%s ist kein gltiger Zeichensatz.\n" - -#: g10/g10.c:1645 -msgid "could not parse keyserver URI\n" -msgstr "Schlsselserver-URI konnte nicht zerlegt werden\n" +msgid " unchanged: %lu\n" +msgstr " nicht gendert: %lu\n" -#: g10/g10.c:1654 +#: sm/import.c:105 #, c-format -msgid "%s:%d: invalid import options\n" -msgstr "%s:%d: ungltige Import Option.\n" - -#: g10/g10.c:1657 -msgid "invalid import options\n" -msgstr "Ungltige Import Option\n" +msgid " not imported: %lu\n" +msgstr " nicht importiert: %lu\n" -#: g10/g10.c:1664 -#, c-format -msgid "%s:%d: invalid export options\n" -msgstr "%s:%d: ungltige Export Option.\n" +#: sm/import.c:174 +msgid "error storing certificate\n" +msgstr "Fehler beim speichern des Zertifikats\n" -#: g10/g10.c:1667 -msgid "invalid export options\n" -msgstr "Ungltige export Option\n" +#: sm/import.c:181 +msgid "basic certificate checks failed - not imported\n" +msgstr "Grundlegende Zertifikatprfungen fehlgeschlagen - nicht importiert\n" -#: g10/g10.c:1673 +#: sm/import.c:313 sm/import.c:345 #, c-format -msgid "unable to set exec-path to %s\n" -msgstr "Der Ausfhrungspfad konnte nicht auf %s gesetzt werden.\n" +msgid "error importing certificate: %s\n" +msgstr "Fehler beim Importieren des Zertifikats: %s\n" -#: g10/g10.c:1794 -msgid "WARNING: program may create a core file!\n" -msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" - -#: g10/g10.c:1798 +#: sm/keydb.c:188 #, c-format -msgid "WARNING: %s overrides %s\n" -msgstr "WARNUNG: %s ersetzt %s\n" +msgid "error creating keybox `%s': %s\n" +msgstr "Die \"Keybox\" `%s' konnte nicht erstellt werden: %s\n" -#: g10/g10.c:1807 g10/g10.c:1826 +#: sm/keydb.c:195 #, c-format -msgid "%s not allowed with %s!\n" -msgstr "%s kann nicht zusammen mit %s verwendet werden!\n" +msgid "keybox `%s' created\n" +msgstr "Die \"Keybox\" `%s' wurde erstellt\n" -#: g10/g10.c:1810 +#: sm/keydb.c:218 #, c-format -msgid "%s makes no sense with %s!\n" -msgstr "%s zusammen mit %s ist nicht sinnvoll!\n" +msgid "can't create lock for `%s'\n" +msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: g10/g10.c:1836 -msgid "you can only make detached or clear signatures while in --pgp2 mode\n" +#: sm/keydb.c:1233 +msgid "failed to get the fingerprint\n" msgstr "" -"Im --pgp2-Modus knnen Sie nur abgetrennte oder Klartextunterschriften " -"machen\n" -#: g10/g10.c:1842 -msgid "you can't sign and encrypt at the same time while in --pgp2 mode\n" +#: sm/keydb.c:1240 +msgid "failed to allocate keyDB handle\n" msgstr "" -"Im --pgp2-Modus knnen Sie nicht gleichzeitig unterschreiben und " -"verschlsseln\n" -#: g10/g10.c:1848 -msgid "you must use files (and not a pipe) when working with --pgp2 enabled.\n" +#: sm/keydb.c:1257 +#, c-format +msgid "problem looking for existing certificate: %s\n" msgstr "" -"Im --pgp2-Modus mssen Sie Dateien benutzen und knnen keine Pipes " -"verwenden.\n" -#: g10/g10.c:1861 -msgid "encrypting a message in --pgp2 mode requires the IDEA cipher\n" +#: sm/keydb.c:1265 +#, c-format +msgid "error finding writable keyDB: %s\n" msgstr "" -"Verschlssen einer Botschaft bentigt im --pgp2-Modus die IDEA-" -"Verschlsselung\n" -#: g10/encode.c:409 g10/encode.c:459 g10/encode.c:710 g10/g10.c:1886 -#: g10/pkclist.c:821 g10/pkclist.c:859 g10/sign.c:647 g10/sign.c:879 +#: sm/keydb.c:1273 #, c-format -msgid "this message may not be usable by %s\n" -msgstr "Diese Botschaft knnte fr %s unbrauchbar sein\n" - -#: g10/g10.c:1934 g10/g10.c:1952 -msgid "selected cipher algorithm is invalid\n" -msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" +msgid "error storing certificate: %s\n" +msgstr "" -#: g10/g10.c:1940 g10/g10.c:1958 -msgid "selected digest algorithm is invalid\n" -msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" +#: sm/verify.c:382 +msgid "Signature made " +msgstr "Signatur erzeugt am " -#: g10/g10.c:1946 -msgid "selected certification digest algorithm is invalid\n" -msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" +#: sm/verify.c:386 +msgid "[date not given]" +msgstr "[Datum nicht vorhanden]" -#: g10/g10.c:1961 +#: sm/verify.c:387 #, c-format -msgid "compress algorithm must be in range %d..%d\n" -msgstr "Das Komprimierverfahren mu im Bereich %d bis %d liegen\n" - -#: g10/g10.c:1963 -msgid "completes-needed must be greater than 0\n" -msgstr "completes-needed mssen grer als 0 sein\n" - -#: g10/g10.c:1965 -msgid "marginals-needed must be greater than 1\n" -msgstr "marginals-needed mssen grer als 1 sein\n" - -#: g10/g10.c:1967 -msgid "max-cert-depth must be in range 1 to 255\n" -msgstr "max-cert-depth mu im Bereich 1 bis 255 liegen\n" - -#: g10/g10.c:1970 -msgid "NOTE: simple S2K mode (0) is strongly discouraged\n" -msgstr "Hinweis: Vom \"simple S2K\"-Modus (0) ist strikt abzuraten\n" - -#: g10/g10.c:1974 -msgid "invalid S2K mode; must be 0, 1 or 3\n" -msgstr "ungltiger \"simple S2K\"-Modus; Wert mu 0, 1 oder 3 sein\n" - -#: g10/g10.c:1978 -msgid "invalid default-check-level; must be 0, 1, 2, or 3\n" -msgstr "ungltiger \"default-check-level\"; Wert mu 0, 1, 2 oder 3 sein\n" - -#: g10/g10.c:1984 -msgid "invalid default preferences\n" -msgstr "ungltige Standard Voreinstellungen\n" - -#: g10/g10.c:1992 -msgid "invalid personal cipher preferences\n" -msgstr "ungltige private Verschlsselungsvoreinstellungen\n" - -#: g10/g10.c:1996 -msgid "invalid personal digest preferences\n" -msgstr "ungltige private Hashvoreinstellungen\n" - -#: g10/g10.c:2000 -msgid "invalid personal compress preferences\n" -msgstr "ungltige private Komprimierungsvoreinstellungen\n" - -#: g10/g10.c:2093 -#, c-format -msgid "failed to initialize the TrustDB: %s\n" -msgstr "Die Trust-DB kann nicht initialisiert werden: %s\n" - -#: g10/g10.c:2103 -msgid "WARNING: recipients (-r) given without using public key encryption\n" -msgstr "" -"WARNUNG: Empfnger (-r) angegeben ohne Verwendung von Public-Key-Verfahren\n" - -#: g10/g10.c:2113 -msgid "--store [filename]" -msgstr "--store [Dateiname]" - -#: g10/g10.c:2120 -msgid "--symmetric [filename]" -msgstr "--symmetric [Dateiname]" - -#: g10/g10.c:2128 -msgid "--encrypt [filename]" -msgstr "--encrypt [Dateiname]" - -#: g10/g10.c:2145 -msgid "--sign [filename]" -msgstr "--sign [Dateiname]" - -#: g10/g10.c:2158 -msgid "--sign --encrypt [filename]" -msgstr "--sign --encrypt [Dateiname]" - -#: g10/g10.c:2172 -msgid "--sign --symmetric [filename]" -msgstr "--sign --symmetric [Dateiname]" - -#: g10/g10.c:2181 -msgid "--clearsign [filename]" -msgstr "--clearsign [Dateiname]" - -#: g10/g10.c:2199 -msgid "--decrypt [filename]" -msgstr "--decrypt [Dateiname]" - -#: g10/g10.c:2210 -msgid "--sign-key user-id" -msgstr "--sign-key User-ID" - -#: g10/g10.c:2218 -msgid "--lsign-key user-id" -msgstr "--lsign-key User-ID" - -#: g10/g10.c:2226 -msgid "--nrsign-key user-id" -msgstr "--nrsign-key User-ID" - -#: g10/g10.c:2234 -msgid "--nrlsign-key user-id" -msgstr "--nrlsign-key User-ID" - -#: g10/g10.c:2242 -msgid "--edit-key user-id [commands]" -msgstr "--edit-key User-ID [Befehle]" - -#: g10/encode.c:417 g10/g10.c:2298 g10/sign.c:790 -#, c-format -msgid "can't open %s: %s\n" -msgstr "'%s' kann nicht geffnet werden: %s\n" - -#: g10/g10.c:2313 -msgid "-k[v][v][v][c] [user-id] [keyring]" -msgstr "-k[v][v][v][c] [User-ID] [Schlsselbund]" - -#: g10/g10.c:2405 -#, c-format -msgid "dearmoring failed: %s\n" -msgstr "Entfernen der ASCII-Hlle ist fehlgeschlagen: %s\n" - -#: g10/g10.c:2413 -#, c-format -msgid "enarmoring failed: %s\n" -msgstr "Anbringen der ASCII-Hlle ist fehlgeschlagen: %s\n" - -#: g10/g10.c:2500 -#, c-format -msgid "invalid hash algorithm `%s'\n" -msgstr "Ungltiges Hashverfahren '%s'\n" - -#: g10/g10.c:2586 -msgid "[filename]" -msgstr "[Dateiname]" - -#: g10/g10.c:2590 -msgid "Go ahead and type your message ...\n" -msgstr "Auf geht's - Botschaft eintippen ...\n" - -#: g10/decrypt.c:60 g10/decrypt.c:106 g10/g10.c:2593 g10/verify.c:94 -#: g10/verify.c:139 -#, c-format -msgid "can't open `%s'\n" -msgstr "'%s' kann nicht geffnet werden\n" - -#: g10/g10.c:2807 -msgid "" -"a notation name must have only printable characters or spaces, and end with " -"an '='\n" -msgstr "" -"Ein \"notation\"-Name darf nur Buchstaben, Zahlen, Punkte oder Unterstriche " -"enthalten und mu mit einem '=' enden\n" - -#: g10/g10.c:2816 -msgid "a notation value must not use any control characters\n" -msgstr "Ein \"notation\"-Wert darf keine Kontrollzeichen verwenden\n" - -#: g10/g10.c:2853 -msgid "the given certification policy URL is invalid\n" -msgstr "Die angegebene Zertifikat-Richtlinien-URL ist ungltig\n" - -#: g10/g10.c:2855 -msgid "the given signature policy URL is invalid\n" -msgstr "Die angegebene Unterschriften-Richtlinien-URL ist ungltig\n" - -#: g10/armor.c:314 -#, c-format -msgid "armor: %s\n" -msgstr "ASCII-Hlle: %s\n" - -#: g10/armor.c:343 -msgid "invalid armor header: " -msgstr "Ungltige ASCII-Hlle" - -#: g10/armor.c:350 -msgid "armor header: " -msgstr "ASCII-Hlle: " - -#: g10/armor.c:361 -msgid "invalid clearsig header\n" -msgstr "Ungltige Klartextsignatur-Einleitung\n" - -#: g10/armor.c:413 -msgid "nested clear text signatures\n" -msgstr "verschachtelte Klartextunterschriften\n" - -#: g10/armor.c:537 -msgid "invalid dash escaped line: " -msgstr "Ungltige mit Bindestrich \"escapte\" Zeile: " - -#: g10/armor.c:549 -msgid "unexpected armor:" -msgstr "Unerwartete ASCII-Hlle:" - -#: g10/armor.c:675 g10/armor.c:1242 -#, c-format -msgid "invalid radix64 character %02x skipped\n" -msgstr "Ungltiges \"radix64\" Zeichen %02x ignoriert\n" - -#: g10/armor.c:718 -msgid "premature eof (no CRC)\n" -msgstr "vorzeitiges Dateiende (keine Prfsumme)\n" - -#: g10/armor.c:752 -msgid "premature eof (in CRC)\n" -msgstr "vorzeitiges Dateiende (innerhalb der Prfsumme)\n" - -#: g10/armor.c:756 -msgid "malformed CRC\n" -msgstr "Falsch aufgebaute Prfsumme\n" - -#: g10/armor.c:760 g10/armor.c:1279 -#, c-format -msgid "CRC error; %06lx - %06lx\n" -msgstr "Prfsummenfehler; %06lx - %06lx\n" - -#: g10/armor.c:780 -msgid "premature eof (in Trailer)\n" -msgstr "vorzeitiges Dateiende (im Nachsatz)\n" - -#: g10/armor.c:784 -msgid "error in trailer line\n" -msgstr "Fehler in der Nachsatzzeile\n" - -#: g10/armor.c:1057 -msgid "no valid OpenPGP data found.\n" -msgstr "Keine gltigen OpenPGP-Daten gefunden.\n" - -#: g10/armor.c:1062 -#, c-format -msgid "invalid armor: line longer than %d characters\n" -msgstr "ungltige ASCII-Hlle: Zeile ist lnger als %d Zeichen\n" - -#: g10/armor.c:1066 -msgid "" -"quoted printable character in armor - probably a buggy MTA has been used\n" -msgstr "" -"\"quoted printable\" Zeichen in der ASCII-Hlle gefunden - mglicherweise\n" -" war ein fehlerhafter E-Mail-Transporter(\"MTA\") die Ursache\n" - -#: g10/pkclist.c:62 -msgid "No reason specified" -msgstr "Kein Grund angegeben" - -#: g10/pkclist.c:64 -msgid "Key is superseded" -msgstr "Schlssel ist berholt" - -#: g10/pkclist.c:66 -msgid "Key has been compromised" -msgstr "Hinweis: Dieser Schlssel ist nicht mehr sicher" - -#: g10/pkclist.c:68 -msgid "Key is no longer used" -msgstr "Schlssel wird nicht mehr benutzt" - -#: g10/pkclist.c:70 -msgid "User ID is no longer valid" -msgstr "User-ID ist nicht mehr gltig" - -#: g10/pkclist.c:74 -msgid "reason for revocation: " -msgstr "Grund fr Widerruf: " - -#: g10/pkclist.c:91 -msgid "revocation comment: " -msgstr "Widerruf-Bemerkung: " - -#. a string with valid answers -#: g10/pkclist.c:264 -msgid "iImMqQsS" -msgstr "iImMqQsS" - -#: g10/pkclist.c:272 -#, c-format -msgid "" -"No trust value assigned to:\n" -"%4u%c/%08lX %s \"" -msgstr "" -"Es ist kein \"trust value\" zugewiesen fr:\n" -"%4u%c/%08lX %s \"" - -#: g10/mainproc.c:1428 g10/pkclist.c:300 -msgid " aka \"" -msgstr " alias \"" - -#: g10/keyedit.c:297 g10/pkclist.c:311 -msgid "" -"Please decide how far you trust this user to correctly\n" -"verify other users' keys (by looking at passports,\n" -"checking fingerprints from different sources...)?\n" -"\n" -msgstr "" -"Bitte entscheiden Sie, in wieweit Sie diesem User zutrauen,\n" -"Schlssel anderer User korrekt zu prfen (durch Vergleich\n" -"mit Lichtbildausweisen, Vergleich der Fingerabdrcke aus\n" -"unterschiedlichen Quellen ...)?\n" -"\n" - -#: g10/pkclist.c:315 -#, fuzzy, c-format -msgid " %d = I don't know\n" -msgstr " %d = Wei nicht so recht\n" - -#: g10/pkclist.c:317 -#, c-format -msgid " %d = I do NOT trust\n" -msgstr " %d = Nein, ihm traue ich NICHT\n" - -#: g10/pkclist.c:319 -#, c-format -msgid " %d = I trust marginally\n" -msgstr " %d = Ich vertraue ihm einigermaen\n" - -#: g10/pkclist.c:321 -#, c-format -msgid " %d = I trust fully\n" -msgstr " %d = Ich vertraue ihm vollstndig\n" - -#: g10/pkclist.c:323 -#, c-format -msgid " %d = I trust ultimately\n" -msgstr " %d = Ich vertraue ihm absolut\n" - -#. not yet implemented -#: g10/pkclist.c:326 -msgid " i = please show me more information\n" -msgstr " i = Bitte weitere Information anzeigen\n" - -#: g10/pkclist.c:329 -msgid " m = back to the main menu\n" -msgstr " m = Zurck zum Men\n" - -#: g10/pkclist.c:332 -msgid " s = skip this key\n" -msgstr " s = diesen Schlssel berSpringen\n" - -#: g10/pkclist.c:333 -msgid " q = quit\n" -msgstr " q = verlassen\n" - -#: g10/pkclist.c:337 -#, c-format -msgid "" -"The minimum trust level for this key is: %s\n" -"\n" -msgstr "" - -#: g10/pkclist.c:343 -msgid "Your decision? " -msgstr "Ihre Auswahl? " - -#: g10/pkclist.c:364 -msgid "Do you really want to set this key to ultimate trust? " -msgstr "Mchten Sie diesem Schlssel wirklich uneingeschrnkt vertrauen? " - -#: g10/pkclist.c:378 -msgid "Certificates leading to an ultimately trusted key:\n" -msgstr "Zertifikate fhren zu einem letztlich vertrauenswrdigen Schlssel:\n" - -#: g10/pkclist.c:453 -#, c-format -msgid "key %08lX: key has been revoked!\n" -msgstr "Schlssel %08lX: Schlssel wurde widerrufen\n" - -#: g10/pkclist.c:460 g10/pkclist.c:472 g10/pkclist.c:566 -msgid "Use this key anyway? " -msgstr "Diesen Schlssel trotzdem benutzen? " - -#: g10/pkclist.c:465 -#, c-format -msgid "key %08lX: subkey has been revoked!\n" -msgstr "Schlssel %08lX: Unterschlssel wurde widerrufen\n" - -#: g10/pkclist.c:486 -#, c-format -msgid "%08lX: key has expired\n" -msgstr "%08lX: Schlssel ist verfallen!\n" - -#: g10/pkclist.c:496 -#, c-format -msgid "" -"%08lX: There is no indication that this key really belongs to the owner\n" -msgstr "" -"%08lX: Es gibt keinen Hinweis, da die Signatur wirklich dem vorgeblichen " -"Besitzer gehrt.\n" - -#: g10/pkclist.c:502 -#, c-format -msgid "%08lX: We do NOT trust this key\n" -msgstr "%08lX: Wir haben KEIN Vertrauen zu diesem Schlssel!\n" - -#: g10/pkclist.c:508 -#, c-format -msgid "" -"%08lX: It is not sure that this key really belongs to the owner\n" -"but it is accepted anyway\n" -msgstr "" -"%08lX: Es ist nicht sicher, da dieser Schlssel wirklich dem vorgeblichen\n" -"Besitzer gehrt, aber er wird trotzdem akzeptiert\n" - -#: g10/pkclist.c:514 -msgid "This key probably belongs to the owner\n" -msgstr "" -"Dieser Schlssel gehrt hchstwahrscheinlich dem angegebenen Besitzer\n" - -#: g10/pkclist.c:519 -msgid "This key belongs to us\n" -msgstr "" -"Dieser Schlssel gehrt uns (da wir nmlich den geheimen Schlssel dazu " -"haben)\n" - -#: g10/pkclist.c:561 -msgid "" -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n" -"\n" -msgstr "" -"Es ist NICHT sicher, da der Schlssel dem vorgeblichen Besitzer gehrt.\n" -"Wenn Sie *wirklich* wissen, was Sie tun, knnen Sie die nchste\n" -"Frage mit ja beantworten\n" - -#: g10/pkclist.c:575 g10/pkclist.c:597 -msgid "WARNING: Using untrusted key!\n" -msgstr "WARNUNG: Ein Schlssel ohne gesichertes Vertrauen wird benutzt!\n" - -#: g10/pkclist.c:616 -msgid "WARNING: This key has been revoked by its owner!\n" -msgstr "WARNUNG: Dieser Schlssel wurde von seinem Besitzer widerrufen!\n" - -#: g10/pkclist.c:617 -msgid " This could mean that the signature is forgery.\n" -msgstr " Das knnte bedeuten, da die Signatur geflscht ist.\n" - -#: g10/pkclist.c:623 -msgid "WARNING: This subkey has been revoked by its owner!\n" -msgstr "WARNUNG: Dieser Unterschlssel wurde von seinem Besitzer widerrufen!\n" - -#: g10/pkclist.c:628 -msgid "Note: This key has been disabled.\n" -msgstr "Hinweis: Dieser Schlssel wurde abgeschaltet.\n" - -#: g10/pkclist.c:633 -msgid "Note: This key has expired!\n" -msgstr "Hinweis: Dieser Schlssel ist verfallen!\n" - -#: g10/pkclist.c:644 -msgid "WARNING: This key is not certified with a trusted signature!\n" -msgstr "WARNUNG: Dieser Schlssel trgt keine vertrauenswrdige Signatur!\n" - -#: g10/pkclist.c:646 -msgid "" -" There is no indication that the signature belongs to the owner.\n" -msgstr "" -" Es gibt keinen Hinweis, da die Signatur wirklich dem vorgeblichen " -"Besitzer gehrt.\n" - -#: g10/pkclist.c:654 -msgid "WARNING: We do NOT trust this key!\n" -msgstr "WARNUNG: Wir haben KEIN Vertrauen zu diesem Schlssel!\n" - -#: g10/pkclist.c:655 -msgid " The signature is probably a FORGERY.\n" -msgstr " Die Signatur ist wahrscheinlich eine FLSCHUNG.\n" - -#: g10/pkclist.c:663 -msgid "" -"WARNING: This key is not certified with sufficiently trusted signatures!\n" -msgstr "" -"WARNUNG: Dieser Schlssel ist nicht durch hinreichend vertrauenswrdige " -"Signaturen zertifiziert!\n" - -#: g10/pkclist.c:665 -msgid " It is not certain that the signature belongs to the owner.\n" -msgstr "" -" Es ist nicht sicher, da die Signatur wirklich dem vorgeblichen " -"Besitzer gehrt.\n" - -#: g10/encode.c:706 g10/pkclist.c:817 g10/pkclist.c:855 -#, c-format -msgid "you may not use %s while in %s mode\n" -msgstr "Die Benutzung von %s ist im %s-Modus nicht erlaubt.\n" - -#: g10/pkclist.c:832 g10/pkclist.c:868 g10/pkclist.c:1020 g10/pkclist.c:1080 -#, c-format -msgid "%s: skipped: %s\n" -msgstr "%s: bersprungen: %s\n" - -#: g10/pkclist.c:842 g10/pkclist.c:1052 -#, c-format -msgid "%s: skipped: public key already present\n" -msgstr "%s: bersprungen: ffentlicher Schlssel bereits vorhanden\n" - -#: g10/pkclist.c:885 -msgid "You did not specify a user ID. (you may use \"-r\")\n" -msgstr "" -"Sie haben keine User-ID angegeben (Sie knnen die Option \"-r\" verwenden).\n" - -#: g10/pkclist.c:898 -msgid "" -"\n" -"Enter the user ID. End with an empty line: " -msgstr "" -"\n" -"Geben Sie die User-ID ein. Beenden mit einer leeren Zeile: " - -#: g10/pkclist.c:914 -msgid "No such user ID.\n" -msgstr "Keine solche User-ID vorhanden.\n" - -#: g10/pkclist.c:919 g10/pkclist.c:995 -msgid "skipped: public key already set as default recipient\n" -msgstr "" -"bersprungen: ffentlicher Schlssel bereits als Standardempfnger gesetzt\n" - -#: g10/pkclist.c:937 -msgid "Public key is disabled.\n" -msgstr "ffentlicher Schlssel ist abgeschaltet.\n" - -#: g10/pkclist.c:944 -msgid "skipped: public key already set\n" -msgstr "bersprungen: ffentlicher Schlssel bereits gesetzt\n" - -#: g10/pkclist.c:987 -#, c-format -msgid "unknown default recipient `%s'\n" -msgstr "Unbekannter voreingestellter Empfnger '%s'\n" - -#: g10/pkclist.c:1032 -#, c-format -msgid "%s: skipped: public key is disabled\n" -msgstr "%s: bersprungen: ffentlicher Schlssel ist abgeschaltet\n" - -#: g10/pkclist.c:1087 -msgid "no valid addressees\n" -msgstr "Keine gltigen Adressaten\n" - -#: g10/keygen.c:184 -#, fuzzy, c-format -msgid "preference `%s' duplicated\n" -msgstr "Voreinstellung %c%lu ist doppelt\n" - -#: g10/keygen.c:191 -#, fuzzy -msgid "too many cipher preferences\n" -msgstr "zu viele `%c' Voreinstellungen\n" - -#: g10/keygen.c:193 -#, fuzzy -msgid "too many digest preferences\n" -msgstr "zu viele `%c' Voreinstellungen\n" - -#: g10/keygen.c:195 -#, fuzzy -msgid "too many compression preferences\n" -msgstr "zu viele `%c' Voreinstellungen\n" - -#: g10/keygen.c:265 -#, fuzzy, c-format -msgid "invalid item `%s' in preference string\n" -msgstr "Ungltiges Zeichen in den Voreinstellungen\n" - -#: g10/keygen.c:535 -msgid "writing direct signature\n" -msgstr "Die \"Direct Key Signature\" wird geschrieben\n" - -#: g10/keygen.c:574 -msgid "writing self signature\n" -msgstr "Die Eigenbeglaubigung wird geschrieben\n" - -#: g10/keygen.c:618 -msgid "writing key binding signature\n" -msgstr "Schreiben der \"key-binding\" Signatur\n" - -#: g10/keygen.c:672 g10/keygen.c:756 g10/keygen.c:847 -#, c-format -msgid "keysize invalid; using %u bits\n" -msgstr "Ungltig Schlssellnge; %u Bit werden verwendet\n" - -#: g10/keygen.c:677 g10/keygen.c:761 g10/keygen.c:852 -#, c-format -msgid "keysize rounded up to %u bits\n" -msgstr "Schlssellnge auf %u Bit aufgerundet\n" - -#: g10/keygen.c:952 -msgid "Please select what kind of key you want:\n" -msgstr "Bitte whlen Sie, welche Art von Schlssel Sie mchten:\n" - -#: g10/keygen.c:954 -#, c-format -msgid " (%d) DSA and ElGamal (default)\n" -msgstr " (%d) DSA und ElGamal (voreingestellt)\n" - -#: g10/keygen.c:955 -#, c-format -msgid " (%d) DSA (sign only)\n" -msgstr " (%d) DSA (nur signieren/beglaubigen)\n" - -#: g10/keygen.c:957 -#, c-format -msgid " (%d) ElGamal (encrypt only)\n" -msgstr " (%d) ElGamal (nur verschlsseln)\n" - -#: g10/keygen.c:959 -#, c-format -msgid " (%d) ElGamal (sign and encrypt)\n" -msgstr " (%d) ElGamal (signieren/beglaubigen und verschlsseln)\n" - -#: g10/keygen.c:960 -#, c-format -msgid " (%d) RSA (sign only)\n" -msgstr " (%d) RSA (nur signieren/beglaubigen)\n" - -#: g10/keygen.c:962 -#, c-format -msgid " (%d) RSA (encrypt only)\n" -msgstr " (%d) RSA (nur verschlsseln)\n" - -#: g10/keygen.c:964 -#, c-format -msgid " (%d) RSA (sign and encrypt)\n" -msgstr " (%d) RSA (signieren/beglaubigen und verschlsseln)\n" - -#: g10/keyedit.c:306 g10/keyedit.c:327 g10/keyedit.c:343 g10/keyedit.c:700 -#: g10/keygen.c:967 -msgid "Your selection? " -msgstr "Ihre Auswahl? " - -#: g10/keygen.c:977 g10/keygen.c:995 -msgid "The use of this algorithm is deprecated - create anyway? " -msgstr "" -"Von der Benutzung dieses Verfahrens ist abzuraten - Trotzdem erzeugen? " - -#: g10/keyedit.c:713 g10/keygen.c:1009 -msgid "Invalid selection.\n" -msgstr "Ungltige Auswahl.\n" - -#: g10/keygen.c:1022 -#, c-format -msgid "" -"About to generate a new %s keypair.\n" -" minimum keysize is 768 bits\n" -" default keysize is 1024 bits\n" -" highest suggested keysize is 2048 bits\n" -msgstr "" -"Es wird ein neues %s Schlsselpaar erzeugt.\n" -" kleinste Schlssellnge ist 768 Bit\n" -" standard Schlssellnge ist 1024 Bit\n" -" grte sinnvolle Schlssellnge ist 2048 Bit\n" - -#: g10/keygen.c:1031 -msgid "What keysize do you want? (1024) " -msgstr "Welche Schlssellnge wnschen Sie? (1024) " - -#: g10/keygen.c:1036 -msgid "DSA only allows keysizes from 512 to 1024\n" -msgstr "DSA erlaubt nur Schlssellngen von 512 bis 1024\n" - -#: g10/keygen.c:1038 -msgid "keysize too small; 1024 is smallest value allowed for RSA.\n" -msgstr "zu kurz; 1024 ist die kleinste fr RSA mgliche Schlssellnge.\n" - -#: g10/keygen.c:1041 -msgid "keysize too small; 768 is smallest value allowed.\n" -msgstr "zu kurz; 768 ist die kleinste mgliche Schlssellnge.\n" - -#. It is ridiculous and an annoyance to use larger key sizes! -#. * GnuPG can handle much larger sizes; but it takes an eternity -#. * to create such a key (but less than the time the Sirius -#. * Computer Corporation needs to process one of the usual -#. * complaints) and {de,en}cryption although needs some time. -#. * So, before you complain about this limitation, I suggest that -#. * you start a discussion with Marvin about this theme and then -#. * do whatever you want. -#: g10/keygen.c:1052 -#, c-format -msgid "keysize too large; %d is largest value allowed.\n" -msgstr "Schsselgre zu hoch; %d ist der Maximalwert.\n" - -#: g10/keygen.c:1057 -msgid "" -"Keysizes larger than 2048 are not suggested because\n" -"computations take REALLY long!\n" -msgstr "" -"Schlssellngen grer als 2048 werden nicht empfohlen, da die\n" -"Berechnungen dann WIRKLICH lange brauchen!\n" - -#: g10/keygen.c:1060 -msgid "Are you sure that you want this keysize? " -msgstr "Sind Sie sicher, da Sie diese Schlssellnge wnschen? " - -#: g10/keygen.c:1061 -msgid "" -"Okay, but keep in mind that your monitor and keyboard radiation is also very " -"vulnerable to attacks!\n" -msgstr "" -"Gut, aber bitte denken Sie auch daran, da Monitor und Tastatur Daten " -"abstrahlen und diese leicht mitgelesen werden knnen.\n" - -#: g10/keygen.c:1070 -#, c-format -msgid "Requested keysize is %u bits\n" -msgstr "Die verlangte Schlssellnge betrgt %u Bit\n" - -#: g10/keygen.c:1073 g10/keygen.c:1077 -#, c-format -msgid "rounded up to %u bits\n" -msgstr "aufgerundet auf %u Bit\n" - -#: g10/keygen.c:1128 -msgid "" -"Please specify how long the key should be valid.\n" -" 0 = key does not expire\n" -" <n> = key expires in n days\n" -" <n>w = key expires in n weeks\n" -" <n>m = key expires in n months\n" -" <n>y = key expires in n years\n" -msgstr "" -"Bitte whlen Sie, wie lange der Schlssel gltig bleiben soll.\n" -" 0 = Schlssel verfllt nie\n" -" <n> = Schlssel verfllt nach n Tagen\n" -" <n>w = Schlssel verfllt nach n Wochen\n" -" <n>m = Schlssel verfllt nach n Monaten\n" -" <n>y = Schlssel verfllt nach n Jahren\n" - -#: g10/keygen.c:1137 -msgid "" -"Please specify how long the signature should be valid.\n" -" 0 = signature does not expire\n" -" <n> = signature expires in n days\n" -" <n>w = signature expires in n weeks\n" -" <n>m = signature expires in n months\n" -" <n>y = signature expires in n years\n" -msgstr "" -"Bitte whlen Sie, wie lange die Beglaubigung gltig bleiben soll.\n" -" 0 = Schlssel verfllt nie\n" -" <n> = Schlssel verfllt nach n Tagen\n" -" <n>w = Schlssel verfllt nach n Wochen\n" -" <n>m = Schlssel verfllt nach n Monaten\n" -" <n>y = Schlssel verfllt nach n Jahren\n" - -#: g10/keygen.c:1159 -msgid "Key is valid for? (0) " -msgstr "Wie lange bleibt der Schlssel gltig? (0) " - -#: g10/keygen.c:1161 -msgid "Signature is valid for? (0) " -msgstr "Wie lange bleibt die Beglaubigung gltig? (0) " - -#: g10/keygen.c:1166 -msgid "invalid value\n" -msgstr "Ungltiger Wert.\n" - -#: g10/keygen.c:1171 -#, c-format -msgid "%s does not expire at all\n" -msgstr "%s verfllt nie.\n" - -#. print the date when the key expires -#: g10/keygen.c:1178 -#, c-format -msgid "%s expires at %s\n" -msgstr "%s verfllt am %s\n" - -#: g10/keygen.c:1184 -msgid "" -"Your system can't display dates beyond 2038.\n" -"However, it will be correctly handled up to 2106.\n" -msgstr "" -"Ihr Rechner kann Daten jenseits des Jahres 2038 nicht anzeigen.\n" -"Trotzdem werden Daten bis 2106 korrekt verarbeitet.\n" - -#: g10/keygen.c:1189 -msgid "Is this correct (y/n)? " -msgstr "Ist dies richtig? (j/n) " - -#: g10/keygen.c:1232 -msgid "" -"\n" -"You need a User-ID to identify your key; the software constructs the user " -"id\n" -"from Real Name, Comment and Email Address in this form:\n" -" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n" -"\n" -msgstr "" -"\n" -"Sie bentigen eine User-ID, um Ihren Schlssel eindeutig zu machen; das\n" -"Programm baut diese User-ID aus Ihrem echten Namen, einem Kommentar und\n" -"Ihrer E-Mail-Adresse in dieser Form auf:\n" -" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n" -"\n" - -#: g10/keygen.c:1244 -msgid "Real name: " -msgstr "Ihr Name (\"Vorname Nachname\"): " - -#: g10/keygen.c:1252 -msgid "Invalid character in name\n" -msgstr "Ungltiges Zeichen im Namen\n" - -#: g10/keygen.c:1254 -msgid "Name may not start with a digit\n" -msgstr "Der Name darf nicht mit einer Ziffer beginnen.\n" - -#: g10/keygen.c:1256 -msgid "Name must be at least 5 characters long\n" -msgstr "Der Name mu min. 5 Zeichen lang sein.\n" - -#: g10/keygen.c:1264 -msgid "Email address: " -msgstr "E-Mail-Adresse: " - -#: g10/keygen.c:1275 -msgid "Not a valid email address\n" -msgstr "Diese E-Mail-Adresse ist ungltig\n" - -#: g10/keygen.c:1283 -msgid "Comment: " -msgstr "Kommentar: " - -#: g10/keygen.c:1289 -msgid "Invalid character in comment\n" -msgstr "Ungltiges Zeichen im Kommentar.\n" - -#: g10/keygen.c:1312 -#, c-format -msgid "You are using the `%s' character set.\n" -msgstr "Sie benutzen den Zeichensatz `%s'\n" - -#: g10/keygen.c:1318 -#, c-format -msgid "" -"You selected this USER-ID:\n" -" \"%s\"\n" -"\n" -msgstr "" -"Sie haben diese User-ID gewhlt:\n" -" \"%s\"\n" -"\n" - -#: g10/keygen.c:1322 -msgid "Please don't put the email address into the real name or the comment\n" -msgstr "Bitte keine E-Mailadressen als Namen oder Kommentar verwenden\n" - -#: g10/keygen.c:1327 -msgid "NnCcEeOoQq" -msgstr "NnKkEeFfBb" - -#: g10/keygen.c:1337 -msgid "Change (N)ame, (C)omment, (E)mail or (Q)uit? " -msgstr "ndern: (N)ame, (K)ommentar, (E)-Mail oder (B)eenden? " - -#: g10/keygen.c:1338 -msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " -msgstr "ndern: (N)ame, (K)ommentar, (E)-Mail oder (F)ertig/(B)eenden? " - -#: g10/keygen.c:1357 -msgid "Please correct the error first\n" -msgstr "Bitte beseitigen Sie zuerst den Fehler\n" - -#: g10/keygen.c:1396 -msgid "" -"You need a Passphrase to protect your secret key.\n" -"\n" -msgstr "" -"Sie bentigen ein Mantra, um den geheimen Schlssel zu schtzen.\n" -"\n" - -#: g10/keyedit.c:918 g10/keygen.c:1404 -msgid "passphrase not correctly repeated; try again" -msgstr "Mantra wurde nicht richtig wiederholt; noch einmal versuchen" - -#: g10/keygen.c:1405 -#, c-format -msgid "%s.\n" -msgstr "%s.\n" - -#: g10/keygen.c:1411 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"I will do it anyway. You can change your passphrase at any time,\n" -"using this program with the option \"--edit-key\".\n" -"\n" -msgstr "" -"Sie mchten kein Mantra - Dies ist *nicht* zu empfehlen!\n" -"Es ist trotzdem mglich. Sie knnen Ihr Mantra jederzeit\n" -"ndern, indem sie dieses Programm mit dem Befehl \"--edit-key\"\n" -"aufrufen.\n" -"\n" - -#: g10/keygen.c:1432 -msgid "" -"We need to generate a lot of random bytes. It is a good idea to perform\n" -"some other action (type on the keyboard, move the mouse, utilize the\n" -"disks) during the prime generation; this gives the random number\n" -"generator a better chance to gain enough entropy.\n" -msgstr "" -"Wir mssen eine ganze Menge Zufallswerte erzeugen. Sie knnen dies\n" -"untersttzen, indem Sie z.B. in einem anderen Fenster/Konsole irgendetwas\n" -"tippen, die Maus verwenden oder irgendwelche anderen Programme benutzen.\n" - -#: g10/keygen.c:1996 -msgid "DSA keypair will have 1024 bits.\n" -msgstr "Das DSA-Schlsselpaar wird 1024 Bit haben.\n" - -#: g10/keygen.c:2050 -msgid "Key generation canceled.\n" -msgstr "Schlsselerzeugung abgebrochen.\n" - -#: g10/keygen.c:2157 g10/keygen.c:2245 -#, c-format -msgid "writing public key to `%s'\n" -msgstr "schreiben des ffentlichen Schlssels nach '%s'\n" - -#: g10/keygen.c:2158 g10/keygen.c:2247 -#, c-format -msgid "writing secret key to `%s'\n" -msgstr "schreiben des geheimen Schlssels nach '%s'\n" - -#: g10/keygen.c:2234 -#, c-format -msgid "no writable public keyring found: %s\n" -msgstr "kein schreibbarer ffentlicher Schlsselbund gefunden: %s\n" - -#: g10/keygen.c:2240 -#, c-format -msgid "no writable secret keyring found: %s\n" -msgstr "kein schreibbarer geheimer Schlsselbund gefunden: %s\n" - -#: g10/keygen.c:2254 -#, c-format -msgid "error writing public keyring `%s': %s\n" -msgstr "Fehler beim Schreiben des ff. Schlsselbundes `%s': %s\n" - -#: g10/keygen.c:2261 -#, c-format -msgid "error writing secret keyring `%s': %s\n" -msgstr "Fehler beim Schreiben des geheimen Schlsselbundes `%s': %s\n" - -#: g10/keygen.c:2281 -msgid "public and secret key created and signed.\n" -msgstr "ffentlichen und geheimen Schlssel erzeugt und signiert.\n" - -#: g10/keygen.c:2282 -msgid "key marked as ultimately trusted.\n" -msgstr "Schlssel ist als uneingeschrnkt vertrauenswrdig gekennzeichnet.\n" - -#: g10/keygen.c:2293 -msgid "" -"Note that this key cannot be used for encryption. You may want to use\n" -"the command \"--edit-key\" to generate a secondary key for this purpose.\n" -msgstr "" -"Bitte beachten Sie, da dieser Schlssel nicht zum Verschlsseln benutzt\n" -"werden kann. Sie knnen aber mit dem Befehl \"--edit-key\" einen\n" -"Zweitschlssel fr diesem Zweck erzeugen.\n" - -#: g10/keygen.c:2305 g10/keygen.c:2415 -#, c-format -msgid "Key generation failed: %s\n" -msgstr "Schlsselerzeugung fehlgeschlagen: %s\n" - -#: g10/keygen.c:2351 g10/sign.c:257 -#, c-format -msgid "" -"key has been created %lu second in future (time warp or clock problem)\n" -msgstr "" -"Der Schlssel wurde %lu Sekunde in der Zukunft erzeugt (Zeitreise oder Uhren " -"stimmen nicht berein)\n" - -#: g10/keygen.c:2353 g10/sign.c:259 -#, c-format -msgid "" -"key has been created %lu seconds in future (time warp or clock problem)\n" -msgstr "" -"Der Schlssel wurde %lu Sekunden in der Zukunft erzeugt (Zeitreise oder " -"Uhren stimmen nicht berein)\n" - -#: g10/keygen.c:2362 -msgid "NOTE: creating subkeys for v3 keys is not OpenPGP compliant\n" -msgstr "HINWEIS: Unterschlssel fr v3-Schlssen sind nicht OpenPGP-konform\n" - -#: g10/keygen.c:2391 -msgid "Really create? " -msgstr "Wirklich erzeugen? " - -#: g10/decrypt.c:92 g10/encode.c:765 -msgid "--output doesn't work for this command\n" -msgstr "--output funktioniert nicht bei diesem Kommando\n" - -#: g10/encode.c:177 g10/openfile.c:180 g10/openfile.c:301 g10/tdbio.c:496 -#: g10/tdbio.c:557 -#, c-format -msgid "%s: can't open: %s\n" -msgstr "%s: kann nicht geffnet werden: %s\n" - -#: g10/encode.c:205 g10/sign.c:1036 -#, c-format -msgid "error creating passphrase: %s\n" -msgstr "Fehler beim Erzeugen des Mantras: %s\n" - -#: g10/encode.c:210 -msgid "can't use a symmetric ESK packet due to the S2K mode\n" -msgstr "" -"Aufgrund des S2K-Modus kann ein symmetrisches ESK Packet nicht benutzt " -"werden\n" - -#: g10/encode.c:229 g10/encode.c:487 -#, c-format -msgid "`%s' already compressed\n" -msgstr "`%s' ist bereits komprimiert\n" - -#: g10/encode.c:296 g10/encode.c:523 -#, c-format -msgid "%s: WARNING: empty file\n" -msgstr "%s: WARNUNG: Leere Datei\n" - -#: g10/encode.c:407 -msgid "you can only encrypt to RSA keys of 2048 bits or less in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus kann nur fr RSA-Schlssel mit maximal 2048 Bit " -"verschlsselt werden\n" - -#: g10/encode.c:423 -#, c-format -msgid "reading from `%s'\n" -msgstr "Lesen von '%s'\n" - -#: g10/encode.c:457 -msgid "" -"unable to use the IDEA cipher for all of the keys you are encrypting to.\n" -msgstr "" -"Die IDEA-Verschlsselung kann nicht mit allen Zielschlsseln verwendet " -"werden.\n" - -#: g10/encode.c:468 g10/encode.c:647 -#, c-format -msgid "forcing symmetric cipher %s (%d) violates recipient preferences\n" -msgstr "" -"Erzwungene Verwendung des symmetrischen Verschlsselungsverfahren %s (%d) " -"verletzt die Empfngervoreinstellungen\n" - -#: g10/encode.c:561 g10/sign.c:759 -#, c-format -msgid "forcing compression algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"Erzwungenes Kompressionsverfahren %s (%d) verletzt die " -"Empfngervoreinstellungen.\n" - -#: g10/encode.c:738 -#, c-format -msgid "%s/%s encrypted for: \"%s\"\n" -msgstr "%s/%s verschlsselt fr: %s\n" - -#: g10/delkey.c:73 g10/export.c:190 g10/keyedit.c:2452 -#, c-format -msgid "key `%s' not found: %s\n" -msgstr "Schlssel `%s' nicht gefunden: %s\n" - -#: g10/delkey.c:81 g10/export.c:213 -#, c-format -msgid "error reading keyblock: %s\n" -msgstr "Fehler beim Lesen des Schlsselblocks: %s\n" - -#: g10/export.c:222 -#, c-format -msgid "key %08lX: not a rfc2440 key - skipped\n" -msgstr "Schlssel %08lX: dies ist kein RFC2440-Schssel - bersprungen\n" - -#: g10/export.c:238 -#, c-format -msgid "key %08lX: not protected - skipped\n" -msgstr "Schlssel %08lX: ungeschtzt - bersprungen\n" - -#: g10/export.c:246 -#, c-format -msgid "key %08lX: PGP 2.x style key - skipped\n" -msgstr "Schlssel %08lX: PGP 2.x-artiger Schlssel - bersprungen\n" - -#: g10/export.c:347 -msgid "WARNING: nothing exported\n" -msgstr "WARNUNG: Nichts exportiert\n" - -#: g10/getkey.c:150 -msgid "too many entries in pk cache - disabled\n" -msgstr "zu viele Eintrge im pk-Cache - abgeschaltet\n" - -#. fixme: returning translatable constants instead of a user ID is -#. * not good because they are probably not utf-8 encoded. -#: g10/getkey.c:186 g10/getkey.c:2461 -msgid "[User id not found]" -msgstr "[User-ID nicht gefunden]" - -#: g10/getkey.c:1494 -#, c-format -msgid "Invalid key %08lX made valid by --allow-non-selfsigned-uid\n" -msgstr "" -"Ungltiger Schlssel %08lX, gltig gemacht per --allow-non-selfsigned-uid\n" - -#: g10/getkey.c:2171 -#, c-format -msgid "using secondary key %08lX instead of primary key %08lX\n" -msgstr "" -"der Zweitschlssel %08lX wird anstelle des Hauptschlssels %08lX verwendet\n" - -#: g10/getkey.c:2218 -#, c-format -msgid "key %08lX: secret key without public key - skipped\n" -msgstr "" -"Schlssel %08lX: geheimer Schlssel, aber ohne ffentlichen Schlssel - " -"bersprungen\n" - -#: g10/import.c:270 -#, c-format -msgid "skipping block of type %d\n" -msgstr "berspringe den Block vom Typ %d\n" - -#: g10/import.c:279 -#, fuzzy, c-format -msgid "%lu keys processed so far\n" -msgstr "%lu Schlssel bislang bearbeitet\n" - -#: g10/import.c:284 -#, c-format -msgid "error reading `%s': %s\n" -msgstr "Fehler beim Lesen von `%s': %s\n" - -#: g10/import.c:296 -#, c-format -msgid "Total number processed: %lu\n" -msgstr "Anzahl insgesamt bearbeiteter Schlssel: %lu\n" - -#: g10/import.c:298 -#, c-format -msgid " skipped new keys: %lu\n" -msgstr " ignorierte neue Schlssel: %lu\n" - -#: g10/import.c:301 -#, c-format -msgid " w/o user IDs: %lu\n" -msgstr " ohne User-ID: %lu\n" - -#: g10/import.c:303 -#, c-format -msgid " imported: %lu" -msgstr " importiert: %lu" - -#: g10/import.c:309 -#, c-format -msgid " unchanged: %lu\n" -msgstr " unverndert: %lu\n" - -#: g10/import.c:311 -#, c-format -msgid " new user IDs: %lu\n" -msgstr " neue User-IDs: %lu\n" - -#: g10/import.c:313 -#, c-format -msgid " new subkeys: %lu\n" -msgstr " neue Unterschlssel: %lu\n" - -#: g10/import.c:315 -#, c-format -msgid " new signatures: %lu\n" -msgstr " neue Signaturen: %lu\n" - -#: g10/import.c:317 -#, c-format -msgid " new key revocations: %lu\n" -msgstr " neue Schlsselwiderrufe: %lu\n" - -#: g10/import.c:319 -#, c-format -msgid " secret keys read: %lu\n" -msgstr " gelesene geheime Schlssel: %lu\n" - -#: g10/import.c:321 -#, c-format -msgid " secret keys imported: %lu\n" -msgstr " geheime Schlssel importiert: %lu\n" - -#: g10/import.c:323 -#, c-format -msgid " secret keys unchanged: %lu\n" -msgstr " unvernderte geh.Schl.: %lu\n" - -#: g10/import.c:325 -#, c-format -msgid " not imported: %lu\n" -msgstr " nicht importiert: %lu\n" - -#: g10/import.c:593 g10/import.c:908 -#, c-format -msgid "key %08lX: no user ID\n" -msgstr "Schlssel %08lX: Keine User-ID\n" - -#: g10/import.c:609 -#, c-format -msgid "key %08lX: HKP subkey corruption repaired\n" -msgstr "Schlssel %08lX: HKP Unterschlsseldefekt repariert\n" - -#: g10/import.c:624 -#, c-format -msgid "key %08lX: accepted non self-signed user ID '%s'\n" -msgstr "Schlssel %08lX: Nicht eigenbeglaubigte User-ID `%s' bernommen\n" - -#: g10/import.c:631 -#, c-format -msgid "key %08lX: no valid user IDs\n" -msgstr "Schlssel %08lX: Keine gltigen User-IDs\n" - -#: g10/import.c:633 -msgid "this may be caused by a missing self-signature\n" -msgstr "dies knnte durch fehlende Eigenbeglaubigung verursacht worden sein\n" - -#: g10/import.c:643 g10/import.c:1001 -#, c-format -msgid "key %08lX: public key not found: %s\n" -msgstr "Schlssel %08lX: ffentlicher Schlssel nicht gefunden: %s\n" - -#: g10/import.c:648 -#, c-format -msgid "key %08lX: new key - skipped\n" -msgstr "Schlssel %08lX: neuer Schlssel - bersprungen\n" - -#: g10/import.c:657 -#, c-format -msgid "no writable keyring found: %s\n" -msgstr "kein schreibbarer Schlsselbund gefunden: %s\n" - -#: g10/import.c:662 g10/openfile.c:244 g10/sign.c:671 g10/sign.c:898 -#, c-format -msgid "writing to `%s'\n" -msgstr "Schreiben nach '%s'\n" - -#: g10/import.c:665 g10/import.c:750 g10/import.c:935 g10/import.c:1061 -#, c-format -msgid "error writing keyring `%s': %s\n" -msgstr "Fehler beim Schreiben des Schlsselbundes `%s': %s\n" - -#: g10/import.c:682 -#, c-format -msgid "key %08lX: public key \"%s\" imported\n" -msgstr "Schlssel %08lX: ffentlicher Schlssel \"%s\" importiert\n" - -#: g10/import.c:704 -#, c-format -msgid "key %08lX: doesn't match our copy\n" -msgstr "Schlssel %08lX: Stimmt nicht mit unserer Kopie berein\n" - -#: g10/import.c:721 g10/import.c:1018 -#, c-format -msgid "key %08lX: can't locate original keyblock: %s\n" -msgstr "" -"Schlssel %08lX: der lokale originale Schlsselblocks wurde nicht gefunden: %" -"s\n" - -#: g10/import.c:728 g10/import.c:1024 -#, c-format -msgid "key %08lX: can't read original keyblock: %s\n" -msgstr "" -"Schlssel %08lX: Lesefehler im lokalen originalen Schlsselblocks: %s\n" - -#: g10/import.c:759 -#, c-format -msgid "key %08lX: \"%s\" 1 new user ID\n" -msgstr "Schlssel %08lX: \"%s\" 1 neue User-ID\n" - -#: g10/import.c:762 -#, c-format -msgid "key %08lX: \"%s\" %d new user IDs\n" -msgstr "Schlssel %08lX: \"%s\" %d neue User-IDs\n" - -#: g10/import.c:765 -#, c-format -msgid "key %08lX: \"%s\" 1 new signature\n" -msgstr "Schlssel %08lX: \"%s\" 1 neue Signatur\n" - -#: g10/import.c:768 -#, c-format -msgid "key %08lX: \"%s\" %d new signatures\n" -msgstr "Schlssel %08lX: \"%s\" %d neue Signaturen\n" - -#: g10/import.c:771 -#, c-format -msgid "key %08lX: \"%s\" 1 new subkey\n" -msgstr "Schlssel %08lX: \"%s\" 1 neuer Unterschlssel\n" - -#: g10/import.c:774 -#, c-format -msgid "key %08lX: \"%s\" %d new subkeys\n" -msgstr "Schlssel %08lX: \"%s\" %d neue Unterschlssel\n" - -#: g10/import.c:793 -#, c-format -msgid "key %08lX: \"%s\" not changed\n" -msgstr "Schlssel %08lX: \"%s\" Nicht gendert\n" - -#: g10/import.c:914 -#, fuzzy, c-format -msgid "key %08lX: secret key with invalid cipher %d - skipped\n" -msgstr "" -"Schlssel %08lX: geheimer Schlssel, aber ohne ffentlichen Schlssel - " -"bersprungen\n" - -#: g10/import.c:929 -#, c-format -msgid "no default secret keyring: %s\n" -msgstr "Kein voreingestellter geheimer Schlsselbund: %s\n" - -#: g10/import.c:940 -#, c-format -msgid "key %08lX: secret key imported\n" -msgstr "Schlssel %08lX: Geheimer Schlssel importiert\n" - -#. we can't merge secret keys -#: g10/import.c:956 -#, c-format -msgid "key %08lX: already in secret keyring\n" -msgstr "Schlssel %08lX: Ist bereits im geheimen Schlsselbund\n" - -#: g10/import.c:966 -#, c-format -msgid "key %08lX: secret key not found: %s\n" -msgstr "Schlssel %08lX: geheimer Schlssel nicht gefunden: %s\n" - -#: g10/import.c:995 -#, c-format -msgid "key %08lX: no public key - can't apply revocation certificate\n" -msgstr "" -"Schlssel %08lX: Kein ffentlicher Schlssel - der Schlsselwiderruf kann " -"nicht angebracht werden\n" - -#: g10/import.c:1035 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - rejected\n" -msgstr "Schlssel %08lX: Ungltiges Widerrufzertifikat: %s - zurckgewiesen\n" - -#: g10/import.c:1067 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate imported\n" -msgstr "Schlssel %08lX: \"%s\" Widerrufzertifikat importiert\n" - -#: g10/import.c:1115 -#, c-format -msgid "key %08lX: no user ID for signature\n" -msgstr "Schlssel %08lX: Keine User-ID fr Signatur\n" - -#: g10/import.c:1128 -#, c-format -msgid "key %08lX: unsupported public key algorithm on user id \"%s\"\n" -msgstr "" -"Schlssel %08lX: Nicht untersttztes Public-Key-Verfahren fr User-ID \"%s" -"\"\n" - -#: g10/import.c:1130 -#, c-format -msgid "key %08lX: invalid self-signature on user id \"%s\"\n" -msgstr "Schlssel %08lX: Ungltige Eigenbeglaubigung fr User-ID \"%s\"\n" - -#: g10/import.c:1145 -#, fuzzy, c-format -msgid "key %08lX: no subkey for subkey binding signature\n" -msgstr "Schlssel %08lX: Kein Unterschlssel fr die Schlsselanbindung\n" - -#: g10/import.c:1153 g10/import.c:1194 -#, c-format -msgid "key %08lX: unsupported public key algorithm\n" -msgstr "Schlssel %08lX: Nicht untersttztes Public-Key-Verfahren\n" - -#: g10/import.c:1154 -#, c-format -msgid "key %08lX: invalid subkey binding\n" -msgstr "Schlssel %08lX: Ungltige Unterschlssel-Anbindung\n" - -#. Delete the last binding -#. sig since this one is -#. newer -#: g10/import.c:1166 -#, c-format -msgid "key %08lX: removed multiple subkey binding\n" -msgstr "Schlssel %08lX: Ungltige Unterschlssel-Anbindung entfernt\n" - -#: g10/import.c:1186 g10/sig-check.c:550 -#, fuzzy, c-format -msgid "key %08lX: no subkey for subkey revocation signature\n" -msgstr "Schlssel %08lX: Kein Unterschlssel fr den Schlsselwiderruf\n" - -#: g10/import.c:1195 -#, c-format -msgid "key %08lX: invalid subkey revocation\n" -msgstr "Schlssel %08lX: Ungltiger Unterschlsselwiderruf\n" - -#. Delete the last revocation -#. sig since this one is -#. newer -#: g10/import.c:1206 -#, fuzzy, c-format -msgid "key %08lX: removed multiple subkey revocation signatures\n" -msgstr "Schlssel %08lX: Mehrfacher Unterschlssel-Widerruf entfernt\n" - -#: g10/import.c:1243 -#, c-format -msgid "key %08lX: skipped user ID '" -msgstr "Schlssel %08lX: User-ID bergangen '" - -#: g10/import.c:1266 -#, c-format -msgid "key %08lX: skipped subkey\n" -msgstr "Schlssel %08lX: Unterschlssel ignoriert\n" - -#. here we violate the rfc a bit by still allowing -#. * to import non-exportable signature when we have the -#. * the secret key used to create this signature - it -#. * seems that this makes sense -#: g10/import.c:1292 -#, c-format -msgid "key %08lX: non exportable signature (class %02x) - skipped\n" -msgstr "" -"Schlssel %08lX: Nicht exportfhige Unterschrift (Klasse %02x) - bergangen\n" - -#: g10/import.c:1301 -#, c-format -msgid "key %08lX: revocation certificate at wrong place - skipped\n" -msgstr "Schlssel %08lX: Widerrufzertifikat an falschem Platz - bergangen\n" - -#: g10/import.c:1318 -#, c-format -msgid "key %08lX: invalid revocation certificate: %s - skipped\n" -msgstr "Schlssel %08lX: Ungltiges Widerrufzertifikat: %s - bergangen\n" - -#: g10/import.c:1330 -#, c-format -msgid "key %08lX: subkey signature in wrong place - skipped\n" -msgstr "Schlssel %08lX: Widerrufzertifikat an falschem Platz - bergangen\n" - -#: g10/import.c:1428 -#, c-format -msgid "key %08lX: duplicated user ID detected - merged\n" -msgstr "Schlssel %08lX: Doppelte User-ID entdeckt - zusammengefhrt\n" - -#: g10/import.c:1487 -#, c-format -msgid "WARNING: key %08lX may be revoked: fetching revocation key %08lX\n" -msgstr "" -"WARNUNG: Schlssel %08lX ist u.U. widerrufen: hole Widerrufschlssel %08lX\n" - -#: g10/import.c:1501 -#, c-format -msgid "WARNING: key %08lX may be revoked: revocation key %08lX not present.\n" -msgstr "" -"WARNUNG: Schlssel %08lX ist u.U. widerrufen: Widerrufschlssel %08lX ist " -"nicht vorhanden\n" - -#: g10/import.c:1558 -#, c-format -msgid "key %08lX: \"%s\" revocation certificate added\n" -msgstr "Schlssel %08lX: \"%s\" Widerrufzertifikat hinzugefgt\n" - -#: g10/import.c:1589 -#, c-format -msgid "key %08lX: direct key signature added\n" -msgstr "Schlssel %08lX: \"direct-key\"-Signaturen hinzugefgt\n" - -#: g10/keyedit.c:151 -msgid "[revocation]" -msgstr "[Widerruf]" - -#: g10/keyedit.c:152 -msgid "[self-signature]" -msgstr "[Eigenbeglaubigung]" - -#: g10/keyedit.c:223 g10/keylist.c:190 -msgid "1 bad signature\n" -msgstr "1 falsche Beglaubigung\n" - -#: g10/keyedit.c:225 g10/keylist.c:192 -#, c-format -msgid "%d bad signatures\n" -msgstr "%d falsche Beglaubigungen\n" - -#: g10/keyedit.c:227 g10/keylist.c:194 -msgid "1 signature not checked due to a missing key\n" -msgstr "1 Beglaubigung wegen fehlendem Schlssel nicht geprft\n" - -#: g10/keyedit.c:229 g10/keylist.c:196 -#, c-format -msgid "%d signatures not checked due to missing keys\n" -msgstr "%d Beglaubigungen wegen fehlenden Schlsseln nicht geprft\n" - -#: g10/keyedit.c:231 g10/keylist.c:198 -msgid "1 signature not checked due to an error\n" -msgstr "1 Beglaubigung aufgrund von Fehler nicht geprft\n" - -#: g10/keyedit.c:233 g10/keylist.c:200 -#, c-format -msgid "%d signatures not checked due to errors\n" -msgstr "%d Beglaubigungen aufgrund von Fehlern nicht geprft\n" - -#: g10/keyedit.c:235 -msgid "1 user ID without valid self-signature detected\n" -msgstr "Eine User-ID ohne gltige Eigenbeglaubigung entdeckt\n" - -#: g10/keyedit.c:237 -#, c-format -msgid "%d user IDs without valid self-signatures detected\n" -msgstr "%d User-IDs ohne gltige Eigenbeglaubigung entdeckt\n" - -#: g10/keyedit.c:300 -#, fuzzy, c-format -msgid " (%d) I trust marginally\n" -msgstr " %d = Ich vertraue ihm einigermaen\n" - -#: g10/keyedit.c:301 -#, fuzzy, c-format -msgid " (%d) I trust fully\n" -msgstr " %d = Ich vertraue ihm vollstndig\n" - -#: g10/keyedit.c:320 -msgid "" -"Please enter the depth of this trust signature.\n" -"A depth greater than 1 allows the key you are signing to make\n" -"trust signatures on your behalf.\n" -msgstr "" - -#: g10/keyedit.c:338 -msgid "Please enter a domain to restrict this signature, or enter for none.\n" -msgstr "" - -#: g10/keyedit.c:481 -#, c-format -msgid "User ID \"%s\" is revoked." -msgstr "User-ID \"%s\" ist widerrufen." - -#: g10/keyedit.c:488 g10/keyedit.c:605 g10/keyedit.c:663 g10/keyedit.c:1273 -msgid "Are you sure you still want to sign it? (y/N) " -msgstr "Wollen Sie ihn immmer noch beglaubigen? (j/N) " - -#: g10/keyedit.c:496 g10/keyedit.c:611 g10/keyedit.c:1279 -msgid " Unable to sign.\n" -msgstr " Beglaubigen ist nicht mglich.\n" - -#: g10/keyedit.c:501 -#, c-format -msgid "WARNING: user ID \"%s\" is not self-signed.\n" -msgstr "WARNUNG: User-ID \"%s\" ist nicht eigenbeglaubigt.\n" - -#: g10/keyedit.c:520 -#, c-format -msgid "" -"The self-signature on \"%s\"\n" -"is a PGP 2.x-style signature.\n" -msgstr "" -"Die Eigenbeglaubigung von \"%s\"\n" -"ist eine PGP 2.x artige Signatur.\n" - -#: g10/keyedit.c:529 -msgid "Do you want to promote it to an OpenPGP self-signature? (y/N) " -msgstr "Soll sie zu einer OpenPGP Eigenbeglaubigung gendert werden? (j/N) " - -#. It's a local sig, and we want to make a -#. exportable sig. -#: g10/keyedit.c:543 -#, c-format -msgid "" -"Your current signature on \"%s\"\n" -"is a local signature.\n" -msgstr "" -"Die derzeitige Beglaubigung von \"%s\"\n" -"ist nur fr diesen Rechner gltig.\n" - -#: g10/keyedit.c:547 -msgid "Do you want to promote it to a full exportable signature? (y/N) " -msgstr "" -"Soll sie zu einer voll exportierbaren Beglaubigung erhoben werden? (j/N) " - -#: g10/keyedit.c:567 -#, c-format -msgid "\"%s\" was already locally signed by key %08lX\n" -msgstr "\"%s\" wurde bereits durch Schlssel %08lX lokal beglaubigt\n" - -#: g10/keyedit.c:571 -#, c-format -msgid "\"%s\" was already signed by key %08lX\n" -msgstr "\"%s\" wurde bereits durch Schlssel %08lX beglaubigt\n" - -#: g10/keyedit.c:584 -#, c-format -msgid "Nothing to sign with key %08lX\n" -msgstr "Nichts zu beglaubigen fr Schlssel %08lX\n" - -#: g10/keyedit.c:599 -msgid "This key has expired!" -msgstr "Dieser Schlssel ist verfallen!" - -#: g10/keyedit.c:619 -#, c-format -msgid "This key is due to expire on %s.\n" -msgstr "Dieser Schlssel wird %s verfallen.\n" - -#: g10/keyedit.c:623 -msgid "Do you want your signature to expire at the same time? (Y/n) " -msgstr "Soll Ihre Beglaubigung zur selben Zeit verfallen? (J/n) " - -#: g10/keyedit.c:656 -msgid "" -"You may not make an OpenPGP signature on a PGP 2.x key while in --pgp2 " -"mode.\n" -msgstr "" -"Im --pgp2-Modus kann nur mit PGP-2.x-artigen Schlsseln unterschrieben " -"werden\n" - -#: g10/keyedit.c:658 -msgid "This would make the key unusable in PGP 2.x.\n" -msgstr "Dies wrde den Schlssel fr PGP 2.x unbrauchbar machen\n" - -#: g10/keyedit.c:683 -msgid "" -"How carefully have you verified the key you are about to sign actually " -"belongs\n" -"to the person named above? If you don't know what to answer, enter \"0\".\n" -msgstr "" -"Wie genau haben Sie berprft, ob der Schlssel, den Sie jetzt beglaubigen\n" -"wollen, wirklich der o.g. Person gehrt?\n" -"Wenn Sie darauf keine Antwort wissen, geben Sie \"0\" ein.\n" - -#: g10/keyedit.c:688 -#, c-format -msgid " (0) I will not answer.%s\n" -msgstr " (0) Ich antworte nicht.%s\n" - -#: g10/keyedit.c:690 -#, c-format -msgid " (1) I have not checked at all.%s\n" -msgstr " (1) Ich habe es berhaupt nicht berprft.%s\n" - -#: g10/keyedit.c:692 -#, c-format -msgid " (2) I have done casual checking.%s\n" -msgstr " (2) Ich habe es flchtig berprft.%s\n" - -#: g10/keyedit.c:694 -#, c-format -msgid " (3) I have done very careful checking.%s\n" -msgstr " (3) Ich habe es sehr sorgfltig berprft.%s\n" - -#: g10/keyedit.c:723 -msgid "" -"Are you really sure that you want to sign this key\n" -"with your key: \"" -msgstr "" -"Sind Sie wirklich sicher, da Sie vorstehenden Schlssel mit Ihrem\n" -"Schlssel beglaubigen wollen: \"" - -#: g10/keyedit.c:732 -msgid "" -"\n" -"This will be a self-signature.\n" -msgstr "" -"\n" -"Dies wird eine Eigenbeglaubigung sein.\n" - -#: g10/keyedit.c:736 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-exportable.\n" -msgstr "" -"\n" -"WARNUNG: Die Unterschrift wird nicht als nicht-exportierbar markiert " -"werden.\n" - -#: g10/keyedit.c:741 -msgid "" -"\n" -"WARNING: the signature will not be marked as non-revocable.\n" -msgstr "" -"\n" -"Die Unterschrift wird nicht als nicht-widerrufbar markiert werden.\n" - -#: g10/keyedit.c:748 -msgid "" -"\n" -"The signature will be marked as non-exportable.\n" -msgstr "" -"\n" -"Die Unterschrift wird als nicht exportfhig markiert werden.\n" - -#: g10/keyedit.c:752 -msgid "" -"\n" -"The signature will be marked as non-revocable.\n" -msgstr "" -"\n" -"Die Unterschrift wird als nicht exportfhig markiert werden.\n" - -#: g10/keyedit.c:757 -msgid "" -"\n" -"I have not checked this key at all.\n" -msgstr "" -"\n" -"Ich habe diesen Schlssel berhaupt nicht berprft.\n" - -#: g10/keyedit.c:761 -msgid "" -"\n" -"I have checked this key casually.\n" -msgstr "" -"\n" -"Ich habe diesen Schlssel flchtig berprft.\n" - -#: g10/keyedit.c:765 -msgid "" -"\n" -"I have checked this key very carefully.\n" -msgstr "" -"\n" -"Ich habe diesen Schlssel sehr sorgfltig berprft.\n" - -#: g10/keyedit.c:774 -msgid "Really sign? " -msgstr "Wirklich unterschreiben? " - -#: g10/keyedit.c:819 g10/keyedit.c:3263 g10/keyedit.c:3325 g10/sign.c:308 -#, c-format -msgid "signing failed: %s\n" -msgstr "Beglaubigung fehlgeschlagen: %s\n" - -#: g10/keyedit.c:875 -msgid "This key is not protected.\n" -msgstr "Dieser Schlssel ist nicht geschtzt.\n" - -#: g10/keyedit.c:879 -msgid "Secret parts of primary key are not available.\n" -msgstr "Geheime Teile des Haupschlssels sind nicht vorhanden\n" - -#: g10/keyedit.c:883 -msgid "Key is protected.\n" -msgstr "Schlssel ist geschtzt.\n" - -#: g10/keyedit.c:903 -#, c-format -msgid "Can't edit this key: %s\n" -msgstr "Dieser Schlssel kann nicht editiert werden: %s\n" - -#: g10/keyedit.c:909 -msgid "" -"Enter the new passphrase for this secret key.\n" -"\n" -msgstr "" -"Geben Sie das neue Mantra fr diesen geheimen Schlssel ein.\n" -"\n" - -#: g10/keyedit.c:923 -msgid "" -"You don't want a passphrase - this is probably a *bad* idea!\n" -"\n" -msgstr "" -"Sie wollen kein Mantra - dies ist bestimmt *keine* gute Idee!\n" -"\n" - -#: g10/keyedit.c:926 -msgid "Do you really want to do this? " -msgstr "Mchten Sie dies wirklich tun? " - -#: g10/keyedit.c:990 -msgid "moving a key signature to the correct place\n" -msgstr "schiebe eine Beglaubigung an die richtige Stelle\n" - -#: g10/keyedit.c:1032 -msgid "quit this menu" -msgstr "Men verlassen" - -#: g10/keyedit.c:1033 -msgid "q" -msgstr "q" - -#: g10/keyedit.c:1034 -msgid "save" -msgstr "save" - -#: g10/keyedit.c:1034 -msgid "save and quit" -msgstr "speichern und Men verlassen" - -#: g10/keyedit.c:1035 -msgid "help" -msgstr "help" - -#: g10/keyedit.c:1035 -msgid "show this help" -msgstr "Diese Hilfe zeigen" - -#: g10/keyedit.c:1037 -msgid "fpr" -msgstr "fpr" - -#: g10/keyedit.c:1037 -msgid "show fingerprint" -msgstr "\"Fingerabdruck\" anzeigen" - -#: g10/keyedit.c:1038 -msgid "list" -msgstr "Liste der Schlssel" - -#: g10/keyedit.c:1038 -msgid "list key and user IDs" -msgstr "Schlssel und User-IDs auflisten" - -#: g10/keyedit.c:1039 -msgid "l" -msgstr "l" - -#: g10/keyedit.c:1040 -msgid "uid" -msgstr "uid" - -#: g10/keyedit.c:1040 -msgid "select user ID N" -msgstr "User-ID N auswhlen" - -#: g10/keyedit.c:1041 -msgid "key" -msgstr "key" - -#: g10/keyedit.c:1041 -msgid "select secondary key N" -msgstr "Zweitschlssel N auswhlen" - -#: g10/keyedit.c:1042 -msgid "check" -msgstr "check" - -#: g10/keyedit.c:1042 -msgid "list signatures" -msgstr "Liste der Signaturen" - -#: g10/keyedit.c:1043 -msgid "c" -msgstr "c" - -#: g10/keyedit.c:1044 -msgid "sign" -msgstr "sign" - -#: g10/keyedit.c:1044 -msgid "sign the key" -msgstr "Den Schlssel signieren" - -#: g10/keyedit.c:1045 -msgid "s" -msgstr "s" - -#: g10/keyedit.c:1046 -#, fuzzy -msgid "tsign" -msgstr "sign" - -#: g10/keyedit.c:1046 -#, fuzzy -msgid "make a trust signature" -msgstr "Eine abgetrennte Unterschrift erzeugen" - -#: g10/keyedit.c:1047 -msgid "lsign" -msgstr "lsign" - -#: g10/keyedit.c:1047 -msgid "sign the key locally" -msgstr "Den Schlssel nur fr diesen Rechner beglaubigen" - -#: g10/keyedit.c:1048 -msgid "nrsign" -msgstr "nrsign" - -#: g10/keyedit.c:1048 -msgid "sign the key non-revocably" -msgstr "Den Schlssel nicht-widerrufbar beglaubigen" - -#: g10/keyedit.c:1049 -msgid "nrlsign" -msgstr "nrlsign" - -#: g10/keyedit.c:1049 -msgid "sign the key locally and non-revocably" -msgstr "Den Schlssel nicht-widerrufbar und nur fr diesen Rechner signieren" - -#: g10/keyedit.c:1050 -msgid "debug" -msgstr "debug" - -#: g10/keyedit.c:1051 -msgid "adduid" -msgstr "adduid" - -#: g10/keyedit.c:1051 -msgid "add a user ID" -msgstr "Eine User-ID hinzufgen" - -#: g10/keyedit.c:1052 -msgid "addphoto" -msgstr "addphoto" - -#: g10/keyedit.c:1052 -msgid "add a photo ID" -msgstr "Eine Foto-ID hinzufgen" - -#: g10/keyedit.c:1053 -msgid "deluid" -msgstr "deluid" - -#: g10/keyedit.c:1053 -msgid "delete user ID" -msgstr "User-ID entfernen" - -#. delphoto is really deluid in disguise -#: g10/keyedit.c:1055 -msgid "delphoto" -msgstr "delphoto" - -#: g10/keyedit.c:1056 -msgid "addkey" -msgstr "addkey" - -#: g10/keyedit.c:1056 -msgid "add a secondary key" -msgstr "Einen Zweitschlssel hinzufgen" - -#: g10/keyedit.c:1057 -msgid "delkey" -msgstr "delkey" - -#: g10/keyedit.c:1057 -msgid "delete a secondary key" -msgstr "Einen Zweitschlssel entfernen" - -#: g10/keyedit.c:1058 -msgid "addrevoker" -msgstr "addrevoker" - -#: g10/keyedit.c:1058 -msgid "add a revocation key" -msgstr "Einen Widerrufschlssel hinzufgen" - -#: g10/keyedit.c:1059 -msgid "delsig" -msgstr "delsig" - -#: g10/keyedit.c:1059 -msgid "delete signatures" -msgstr "Signatur entfernen" - -#: g10/keyedit.c:1060 -msgid "expire" -msgstr "expire" - -#: g10/keyedit.c:1060 -msgid "change the expire date" -msgstr "ndern des Verfallsdatums" - -#: g10/keyedit.c:1061 -msgid "primary" -msgstr "primary" - -#: g10/keyedit.c:1061 -msgid "flag user ID as primary" -msgstr "User-ID als Haupt-User-ID kennzeichnen" - -#: g10/keyedit.c:1062 -msgid "toggle" -msgstr "toggle" - -#: g10/keyedit.c:1062 -msgid "toggle between secret and public key listing" -msgstr "Umschalten zwischen Anzeige geheimer und ffentlicher Schlssel" - -#: g10/keyedit.c:1064 -msgid "t" -msgstr "t" - -#: g10/keyedit.c:1065 -msgid "pref" -msgstr "pref" - -#: g10/keyedit.c:1065 -msgid "list preferences (expert)" -msgstr "Liste der Voreinstellungen (fr Experten)" - -#: g10/keyedit.c:1066 -msgid "showpref" -msgstr "showpref" - -#: g10/keyedit.c:1066 -msgid "list preferences (verbose)" -msgstr "Liste der Voreinstellungen (ausfhrlich)" - -#: g10/keyedit.c:1067 -msgid "setpref" -msgstr "setpref" - -#: g10/keyedit.c:1067 -msgid "set preference list" -msgstr "Liste der Voreinstellungen einstellen" - -#: g10/keyedit.c:1068 -msgid "updpref" -msgstr "updpref" - -#: g10/keyedit.c:1068 -msgid "updated preferences" -msgstr "genderte Voreinstellungen" - -#: g10/keyedit.c:1069 -msgid "passwd" -msgstr "passwd" - -#: g10/keyedit.c:1069 -msgid "change the passphrase" -msgstr "Das Mantra ndern" - -#: g10/keyedit.c:1070 -msgid "trust" -msgstr "trust" - -#: g10/keyedit.c:1070 -msgid "change the ownertrust" -msgstr "Den \"Owner trust\" ndern" - -#: g10/keyedit.c:1071 -msgid "revsig" -msgstr "revsig" - -#: g10/keyedit.c:1071 -msgid "revoke signatures" -msgstr "Signaturen widerrufen" - -#: g10/keyedit.c:1072 -msgid "revkey" -msgstr "revkey" - -#: g10/keyedit.c:1072 -msgid "revoke a secondary key" -msgstr "Einen Zweitschlssel widerrufen" - -#: g10/keyedit.c:1073 -msgid "disable" -msgstr "disable" - -#: g10/keyedit.c:1073 -msgid "disable a key" -msgstr "Schlssel abschalten" - -#: g10/keyedit.c:1074 -msgid "enable" -msgstr "enable" - -#: g10/keyedit.c:1074 -msgid "enable a key" -msgstr "Schlssel anschalten" - -#: g10/keyedit.c:1075 -msgid "showphoto" -msgstr "showphoto" - -#: g10/keyedit.c:1075 -msgid "show photo ID" -msgstr "Foto-ID anzeigen" - -#: g10/delkey.c:119 g10/keyedit.c:1095 -msgid "can't do that in batchmode\n" -msgstr "Dies kann im Batchmodus nicht durchgefhrt werden.\n" - -#: g10/keyedit.c:1132 -#, c-format -msgid "error reading secret keyblock `%s': %s\n" -msgstr "Fehler beim Lesen des geheimen Schlsselblocks `%s': %s\n" - -#: g10/keyedit.c:1150 -msgid "Secret key is available.\n" -msgstr "Geheimer Schlssel ist vorhanden.\n" - -#: g10/keyedit.c:1181 -msgid "Command> " -msgstr "Befehl> " - -#: g10/keyedit.c:1213 -msgid "Need the secret key to do this.\n" -msgstr "Hierzu wird der geheime Schlssel bentigt.\n" - -#: g10/keyedit.c:1217 -msgid "Please use the command \"toggle\" first.\n" -msgstr "Bitte verwenden sie zunchst den Befehl \"toggle\"\n" - -#: g10/keyedit.c:1267 -msgid "Key is revoked." -msgstr "Schlssel wurde widerrufen." - -#: g10/keyedit.c:1286 -msgid "Really sign all user IDs? " -msgstr "Wirklich alle User-IDs beglaubigen? " - -#: g10/keyedit.c:1287 -msgid "Hint: Select the user IDs to sign\n" -msgstr "Tip: Whlen Sie die User-IDs, die beglaubigt werden sollen\n" - -#: g10/keyedit.c:1313 -#, c-format -msgid "This command is not allowed while in %s mode.\n" -msgstr "Dieses Kommando ist im %s-Modus nicht erlaubt.\n" - -#: g10/keyedit.c:1333 g10/keyedit.c:1354 -msgid "You must select at least one user ID.\n" -msgstr "Zumindestens eine User-ID mu ausgewhlt werden.\n" - -#: g10/keyedit.c:1335 -msgid "You can't delete the last user ID!\n" -msgstr "Die letzte User-ID kann nicht gelscht werden!\n" - -#: g10/keyedit.c:1338 -msgid "Really remove all selected user IDs? " -msgstr "Mchten Sie alle ausgewhlten User-IDs wirklich entfernen? " - -#: g10/keyedit.c:1339 -msgid "Really remove this user ID? " -msgstr "Diese User-ID wirklich entfernen? " - -#: g10/keyedit.c:1377 g10/keyedit.c:1414 -msgid "You must select at least one key.\n" -msgstr "Zumindestens ein Schlssel mu ausgewhlt werden.\n" - -#: g10/keyedit.c:1381 -msgid "Do you really want to delete the selected keys? " -msgstr "Mchten Sie die ausgewhlten Schlssel wirklich entfernen? " - -#: g10/keyedit.c:1382 -msgid "Do you really want to delete this key? " -msgstr "Mchten Sie diesen Schlssel wirklich entfernen? " - -#: g10/keyedit.c:1418 -msgid "Do you really want to revoke the selected keys? " -msgstr "Mchten Sie die ausgewhlten Schlssel wirklich widerrufen? " - -#: g10/keyedit.c:1419 -msgid "Do you really want to revoke this key? " -msgstr "Mchten Sie diesen Schlssel wirklich wiederrufen? " - -#: g10/keyedit.c:1483 -#, fuzzy -msgid "Current preference list:\n" -msgstr "Liste der Voreinstellungen einstellen" - -#: g10/keyedit.c:1489 -msgid "Really update the preferences for the selected user IDs? " -msgstr "" -"Mchten Sie die Voreinstellungen der ausgewhlten User-IDs wirklich ndern? " - -#: g10/keyedit.c:1491 -msgid "Really update the preferences? " -msgstr "Die Voreinstellungen wirklich ndern? " - -#: g10/keyedit.c:1529 -msgid "Save changes? " -msgstr "nderungen speichern? " - -#: g10/keyedit.c:1532 -msgid "Quit without saving? " -msgstr "Beenden ohne zu speichern? " - -#: g10/keyedit.c:1543 -#, c-format -msgid "update failed: %s\n" -msgstr "nderung fehlgeschlagen: %s\n" - -#: g10/keyedit.c:1550 -#, c-format -msgid "update secret failed: %s\n" -msgstr "nderung des Geheimnisses fehlgeschlagen: %s\n" - -#: g10/keyedit.c:1557 -msgid "Key not changed so no update needed.\n" -msgstr "Schlssel ist nicht gendert worden, also ist kein Speichern ntig.\n" - -#: g10/keyedit.c:1569 -msgid "Invalid command (try \"help\")\n" -msgstr "Ungltiger Befehl (versuchen Sie's mal mit \"help\")\n" - -#: g10/keyedit.c:1885 -#, c-format -msgid "This key may be revoked by %s key " -msgstr "Dieser Schlssel knnte widerrufen worden sein von %s Schlssel " - -#: g10/keyedit.c:1889 -msgid " (sensitive)" -msgstr "(empfindlich)" - -#. Note, we use the same format string as in other show -#. functions to make the translation job easier. -#: g10/keyedit.c:1895 g10/keyedit.c:1921 g10/keyedit.c:2006 g10/keyedit.c:2021 -#, c-format -msgid "%s%c %4u%c/%08lX created: %s expires: %s" -msgstr "%s%c %4u%c/%08lX erstellt: %s verfllt: %s" - -#: g10/keyedit.c:1904 -#, c-format -msgid " trust: %c/%c" -msgstr " Vertrauen: %c/%c" - -#: g10/keyedit.c:1908 -msgid "This key has been disabled" -msgstr "Hinweis: Dieser Schlssel ist abgeschaltet" - -#: g10/keyedit.c:1937 -#, c-format -msgid "rev! subkey has been revoked: %s\n" -msgstr "rev! Unterschlssel wurde widerrufen: %s\n" - -#: g10/keyedit.c:1940 -msgid "rev- faked revocation found\n" -msgstr "rev- geflschter Schlsselwiderruf entdeckt\n" - -#: g10/keyedit.c:1942 -#, c-format -msgid "rev? problem checking revocation: %s\n" -msgstr "rev? Schwierigkeiten bei der Widerruf-berprfung: %s\n" - -#: g10/keyedit.c:1972 -msgid "There are no preferences on a PGP 2.x-style user ID.\n" -msgstr "PGP 2.x-artige Schlssel haben keine Voreinstellungen.\n" - -#: g10/keyedit.c:1980 -msgid "" -"Please note that the shown key validity is not necessarily correct\n" -"unless you restart the program.\n" -msgstr "" -"Bitte beachten Sie, da ohne einen Programmneustart die angezeigte\n" -"Schlsselgltigkeit nicht notwendigerweise korrekt ist.\n" - -#: g10/keyedit.c:2137 -msgid "" -"WARNING: This is a PGP2-style key. Adding a photo ID may cause some " -"versions\n" -" of PGP to reject this key.\n" -msgstr "" -"WARNUNG: Dies ist ein PGP2-artiger Schlssel. Hinzufgen einer Foto-ID " -"knnte\n" -" bei einigen PGP-Versionen zur Zurckweisung des Schlssels fhren.\n" - -#: g10/keyedit.c:2142 g10/keyedit.c:2415 -msgid "Are you sure you still want to add it? (y/N) " -msgstr "Wollen Sie ihn immmer noch hinzufgen? (j/N) " - -#: g10/keyedit.c:2148 -msgid "You may not add a photo ID to a PGP2-style key.\n" -msgstr "Sie knnen einem PGP2-artigen Schlsel keine Foto-ID hinzufgen.\n" - -#: g10/keyedit.c:2283 -msgid "Delete this good signature? (y/N/q)" -msgstr "Diese korrekte Beglaubigung entfernen? (j/N/q)" - -#: g10/keyedit.c:2293 -msgid "Delete this invalid signature? (y/N/q)" -msgstr "Diese ungltige Beglaubigung entfernen= (j/N/q)" - -#: g10/keyedit.c:2297 -msgid "Delete this unknown signature? (y/N/q)" -msgstr "Diese unbekannte Beglaubigung entfernen? (j/N/q)" - -#: g10/keyedit.c:2303 -msgid "Really delete this self-signature? (y/N)" -msgstr "Eigenbeglaubigung wirklich entfernen? (j/N)" - -#: g10/keyedit.c:2317 -#, c-format -msgid "Deleted %d signature.\n" -msgstr "%d Beglaubigungen entfernt.\n" - -#: g10/keyedit.c:2318 -#, c-format -msgid "Deleted %d signatures.\n" -msgstr "%d Beglaubigungen entfernt.\n" - -#: g10/keyedit.c:2321 -msgid "Nothing deleted.\n" -msgstr "Nichts entfernt.\n" - -#: g10/keyedit.c:2410 -#, fuzzy -msgid "" -"WARNING: This is a PGP 2.x-style key. Adding a designated revoker may " -"cause\n" -" some versions of PGP to reject this key.\n" -msgstr "" -"WARNUNG: Dies ist ein PGP2-artiger Schlssel. Hinzufgen einer Foto-ID " -"knnte\n" -" bei einigen PGP-Versionen zur Zurckweisung des Schlssels fhren.\n" - -#: g10/keyedit.c:2421 -#, fuzzy -msgid "You may not add a designated revoker to a PGP 2.x-style key.\n" -msgstr "Sie knnen einem PGP2-artigen Schlsel keine Foto-ID hinzufgen.\n" - -#: g10/keyedit.c:2444 -msgid "Enter the user ID of the designated revoker: " -msgstr "Geben sie die User-ID des designierten Widerrufers ein: " - -#: g10/keyedit.c:2459 -msgid "cannot appoint a PGP 2.x style key as a designated revoker\n" -msgstr "" -"Ein PGP 2.x-artiger Schlssel kann nicht als designierter Widerrufer " -"eingetragen werden\n" - -#. This actually causes no harm (after all, a key that -#. designates itself as a revoker is the same as a -#. regular key), but it's easy enough to check. -#: g10/keyedit.c:2474 -msgid "you cannot appoint a key as its own designated revoker\n" -msgstr "" -"Ein Schlssel kann nicht als sein eigener designierter Widerrufer agieren\n" - -#: g10/keyedit.c:2496 -#, fuzzy -msgid "this key has already been designated as a revoker\n" -msgstr "" -"Ein Schlssel kann nicht als sein eigener designierter Widerrufer agieren\n" - -#: g10/keyedit.c:2592 -msgid "Please remove selections from the secret keys.\n" -msgstr "Bitte entfernen Sie die Auswahl von den geheimen Schlsseln.\n" - -#: g10/keyedit.c:2598 -msgid "Please select at most one secondary key.\n" -msgstr "Bitte whlen Sie hchstens einen Zweitschlssel aus.\n" - -#: g10/keyedit.c:2602 -msgid "Changing expiration time for a secondary key.\n" -msgstr "ndern des Verfallsdatums des Zweitschlssels.\n" - -#: g10/keyedit.c:2604 -msgid "Changing expiration time for the primary key.\n" -msgstr "ndern des Verfallsdatums des Hauptschlssels.\n" - -#: g10/keyedit.c:2646 -msgid "You can't change the expiration date of a v3 key\n" -msgstr "Sie knnen das Verfallsdatum eines v3-Schlssels nicht ndern\n" - -#: g10/keyedit.c:2662 -msgid "No corresponding signature in secret ring\n" -msgstr "Keine entsprechende Signatur im geheimen Schlsselbund\n" - -#: g10/keyedit.c:2745 -msgid "Please select exactly one user ID.\n" -msgstr "Bitte genau eine User-ID auswhlen.\n" - -#: g10/keyedit.c:2782 g10/keyedit.c:2889 -#, c-format -msgid "skipping v3 self-signature on user id \"%s\"\n" -msgstr "berspringen der v3 Eigenbeglaubigung von User-ID \"%s\"\n" - -#: g10/keyedit.c:2949 -#, c-format -msgid "No user ID with index %d\n" -msgstr "Keine User-ID mit Index %d\n" - -#: g10/keyedit.c:2995 -#, c-format -msgid "No secondary key with index %d\n" -msgstr "Kein Zweitschlssel mit Index %d\n" - -#: g10/keyedit.c:3109 -msgid "user ID: \"" -msgstr "User-ID: \"" - -#: g10/keyedit.c:3114 -#, c-format -msgid "" -"\"\n" -"signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"unterschrieben mit Ihrem Schlssel %08lX um %s\n" - -#: g10/keyedit.c:3117 -#, c-format -msgid "" -"\"\n" -"locally signed with your key %08lX at %s\n" -msgstr "" -"\"\n" -"lokal unterschrieben mit Ihrem Schlssel %08lX um %s\n" - -#: g10/keyedit.c:3122 -#, c-format -msgid "This signature expired on %s.\n" -msgstr "Diese Unterschrift ist seit %s verfallen.\n" - -#: g10/keyedit.c:3126 -msgid "Are you sure you still want to revoke it? (y/N) " -msgstr "Wollen Sie ihn immmer noch widerrufen? (j/N) " - -#: g10/keyedit.c:3130 -msgid "Create a revocation certificate for this signature? (y/N) " -msgstr "Ein Widerrufszertifikat fr diese Unterschrift erzeugen (j/N)" - -#. FIXME: detect duplicates here -#: g10/keyedit.c:3155 -msgid "You have signed these user IDs:\n" -msgstr "Sie haben folgende User-IDs beglaubigt:\n" - -#: g10/keyedit.c:3174 -#, c-format -msgid " signed by %08lX at %s%s%s\n" -msgstr " beglaubigt durch %08lX um %s%s%s\n" - -#: g10/keyedit.c:3182 -#, c-format -msgid " revoked by %08lX at %s\n" -msgstr " widerrufen durch %08lX um %s\n" - -#: g10/keyedit.c:3202 -msgid "You are about to revoke these signatures:\n" -msgstr "Es werden nun folgende Beglaubigungen entfernt:\n" - -#: g10/keyedit.c:3212 -#, c-format -msgid " signed by %08lX at %s%s\n" -msgstr " beglaubigt durch %08lX am %s%s\n" - -#: g10/keyedit.c:3214 -msgid " (non-exportable)" -msgstr " (nicht-exportierbar)" - -#: g10/keyedit.c:3221 -msgid "Really create the revocation certificates? (y/N) " -msgstr "Wirklich ein Unterschrift-Widerrufszertifikat erzeugen? (j/N) " - -#: g10/keyedit.c:3251 -msgid "no secret key\n" -msgstr "Kein geheimer Schlssel\n" - -#: g10/keyedit.c:3406 -#, c-format -msgid "Displaying %s photo ID of size %ld for key 0x%08lX (uid %d)\n" -msgstr "" -"Anzeigen einer %s Photo ID (%ld Byte) fr Schlssel %08lX (User-ID %d)\n" - -#: g10/keylist.c:133 -msgid "Critical signature policy: " -msgstr "Krititische Beglaubigungsrichtlinie: " - -#: g10/keylist.c:135 -msgid "Signature policy: " -msgstr "Beglaubigungsrichtlinie: " - -#: g10/keylist.c:160 g10/keylist.c:183 g10/mainproc.c:769 g10/mainproc.c:778 -msgid "WARNING: invalid notation data found\n" -msgstr "WARNUNG: Ungltige \"Notation\"-Daten gefunden\n" - -#: g10/keylist.c:169 -msgid "Critical signature notation: " -msgstr "Krititische Beglaubigungs-\"Notation\": " - -#: g10/keylist.c:171 -msgid "Signature notation: " -msgstr "Beglaubigungs-\"Notation\": " - -#: g10/keylist.c:178 -msgid "not human readable" -msgstr "nicht als Klartext darstellbar" - -#: g10/keylist.c:267 -msgid "Keyring" -msgstr "Schlsselbund" - -#. of subkey -#: g10/keylist.c:536 g10/mainproc.c:905 -#, c-format -msgid " [expires: %s]" -msgstr " [verfllt: %s]" - -#: g10/keylist.c:1063 -msgid "Primary key fingerprint:" -msgstr "Haupt-Fingerabdruck =" - -#: g10/keylist.c:1065 -msgid " Subkey fingerprint:" -msgstr "Unter-Fingerabdruck =" - -#: g10/keylist.c:1072 -msgid " Primary key fingerprint:" -msgstr " Haupt-Fingerabdruck =" - -#: g10/keylist.c:1074 -msgid " Subkey fingerprint:" -msgstr " Unter-Fingerabdruck =" - -#. use tty -#: g10/keylist.c:1078 g10/keylist.c:1082 -#, fuzzy -msgid " Key fingerprint =" -msgstr " Schl.-Fingerabdruck =" - -#: g10/mainproc.c:248 -#, c-format -msgid "weird size for an encrypted session key (%d)\n" -msgstr "Seltsame Lnge des verschlsselten Session-Keys (%d)\n" - -#: g10/mainproc.c:259 -#, c-format -msgid "invalid symkey algorithm detected (%d)\n" -msgstr "Ungltiger Veschlsselungsalgorithmus entdeckt (%d)\n" - -#: g10/encr-data.c:66 g10/mainproc.c:288 -#, c-format -msgid "%s encrypted data\n" -msgstr "%s verschlsselte Daten\n" - -#: g10/encr-data.c:68 g10/mainproc.c:290 -#, c-format -msgid "encrypted with unknown algorithm %d\n" -msgstr "Mit unbekanntem Verfahren verschlsselt %d\n" - -#: g10/mainproc.c:318 -#, c-format -msgid "public key is %08lX\n" -msgstr "ffentlicher Schlssel ist %08lX\n" - -#: g10/mainproc.c:364 -msgid "public key encrypted data: good DEK\n" -msgstr "Mit ffentlichem Schssel verschlsselte Daten: Korrekte DEK\n" - -#: g10/mainproc.c:416 -#, c-format -msgid "encrypted with %u-bit %s key, ID %08lX, created %s\n" -msgstr "verschlsselt mit %u-Bit %s Schlssel, ID %08lX, erzeugt %s\n" - -# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( -# [kw] -#: g10/mainproc.c:426 -#, c-format -msgid "encrypted with %s key, ID %08lX\n" -msgstr "verschlsselt mit %s Schlssel, ID %08lX\n" - -#: g10/mainproc.c:440 -#, c-format -msgid "public key decryption failed: %s\n" -msgstr "Entschlsselung mit ffentlichem Schlssel fehlgeschlagen: %s\n" - -#: g10/mainproc.c:467 g10/mainproc.c:486 -#, c-format -msgid "assuming %s encrypted data\n" -msgstr "vermutlich %s-verschlsselte Daten\n" - -#: g10/mainproc.c:474 -#, c-format -msgid "IDEA cipher unavailable, optimistically attempting to use %s instead\n" -msgstr "IDEA-Verschlsselung nicht verfgbar; versucht wird stattdessen %s\n" - -#: g10/mainproc.c:504 -msgid "decryption okay\n" -msgstr "Entschlsselung erfolgreich\n" - -#: g10/mainproc.c:511 -msgid "WARNING: encrypted message has been manipulated!\n" -msgstr "Warnung: Verschlsselte Botschaft ist manipuliert worden!\n" - -#: g10/mainproc.c:517 -#, c-format -msgid "decryption failed: %s\n" -msgstr "Entschlsselung fehlgeschlagen: %s\n" - -#: g10/mainproc.c:536 -msgid "NOTE: sender requested \"for-your-eyes-only\"\n" -msgstr "" -"Hinweis: Der Absender verlangte Vertraulichkeit(\"for-your-eyes-only\")\n" - -#: g10/mainproc.c:538 -#, c-format -msgid "original file name='%.*s'\n" -msgstr "Ursprnglicher Dateiname='%.*s'\n" - -#: g10/mainproc.c:713 -msgid "standalone revocation - use \"gpg --import\" to apply\n" -msgstr "" -"Einzelner Widerruf - verwenden Sie \"gpg --import\" um ihn anzuwenden\n" - -#: g10/mainproc.c:781 -msgid "Notation: " -msgstr "\"Notation\": " - -#: g10/mainproc.c:793 -msgid "Policy: " -msgstr "Richtlinie: " - -#: g10/mainproc.c:1248 -msgid "signature verification suppressed\n" -msgstr "Unterschriften-berprfung unterdrckt\n" - -#. plaintext before signatures but no one-pass packets -#: g10/mainproc.c:1290 g10/mainproc.c:1300 -msgid "can't handle these multiple signatures\n" -msgstr "diese Mehrfachunterschriften knnen nicht behandelt werden\n" - -# Scripte scannen lt. dl1bke auf "ID (0-9A-F)+" deswegen mu "ID" rein :-( -#: g10/mainproc.c:1311 -#, c-format -msgid "Signature made %.*s using %s key ID %08lX\n" -msgstr "Unterschrift vom %.*s, %s Schlssel ID %08lX\n" - -#: g10/mainproc.c:1360 g10/mainproc.c:1393 -msgid "BAD signature from \"" -msgstr "FALSCHE Unterschrift von \"" - -#: g10/mainproc.c:1361 g10/mainproc.c:1394 -msgid "Expired signature from \"" -msgstr "Verfallene Unterschrift von \"" - -#: g10/mainproc.c:1362 g10/mainproc.c:1395 -msgid "Good signature from \"" -msgstr "Korrekte Unterschrift von \"" - -#: g10/mainproc.c:1397 -msgid "[uncertain]" -msgstr "[ungewi] " - -#: g10/mainproc.c:1489 -#, c-format -msgid "Can't check signature: %s\n" -msgstr "Unterschrift kann nicht geprft werden: %s\n" - -#: g10/mainproc.c:1558 g10/mainproc.c:1574 g10/mainproc.c:1636 -msgid "not a detached signature\n" -msgstr "keine abgetrennte Unterschrift\n" - -#: g10/mainproc.c:1585 -#, c-format -msgid "standalone signature of class 0x%02x\n" -msgstr "Einzelne Unterschrift der Klasse 0x%02x\n" - -#: g10/mainproc.c:1642 -msgid "old style (PGP 2.x) signature\n" -msgstr "Unterschrift nach alter (PGP 2.x) Art\n" - -#: g10/mainproc.c:1649 -msgid "invalid root packet detected in proc_tree()\n" -msgstr "ungltiges root-Paket in proc_tree() entdeckt\n" - -#: g10/misc.c:98 -#, c-format -msgid "can't disable core dumps: %s\n" -msgstr "core-dump-Dateierzeugung kann nicht abgeschaltet werden: %s\n" - -#: g10/misc.c:162 -msgid "Experimental algorithms should not be used!\n" -msgstr "Experimentiermethoden sollten nicht benutzt werden!\n" - -#: g10/misc.c:192 -msgid "this cipher algorithm is deprecated; please use a more standard one!\n" -msgstr "Es ist davon abzuraten, diese Verschlsselungsmethode zu benutzen!\n" - -#: g10/misc.c:300 -msgid "the IDEA cipher plugin is not present\n" -msgstr "das IDEA-Verschlsselungs-Plugin ist nicht vorhanden\n" - -#: g10/misc.c:301 -msgid "" -"please see http://www.gnupg.org/why-not-idea.html for more information\n" -msgstr "Fr weitere Info siehe http://www.gnupg.org/why-not-idea.html\n" - -#: g10/misc.c:509 -#, c-format -msgid "%s:%d: deprecated option \"%s\"\n" -msgstr "%s:%d: mibilligte Option \"%s\".\n" - -#: g10/misc.c:513 -#, c-format -msgid "WARNING: \"%s\" is a deprecated option\n" -msgstr "WARNUNG: \"%s\" ist eine mibilligte Option.\n" - -#: g10/misc.c:515 -#, c-format -msgid "please use \"%s%s\" instead\n" -msgstr "Bitte benutzen Sie stattdessen \"%s%s\".\n" - -#: g10/parse-packet.c:120 -#, c-format -msgid "can't handle public key algorithm %d\n" -msgstr "dieses Public-Key Verfahren %d kann nicht benutzt werden\n" - -#: g10/parse-packet.c:1072 -#, c-format -msgid "subpacket of type %d has critical bit set\n" -msgstr "Im Unterpaket des Typs %d ist das \"critical bit\" gesetzt\n" - -#: g10/passphrase.c:442 g10/passphrase.c:489 -msgid "gpg-agent is not available in this session\n" -msgstr "GPG-Agent ist in dieser Sitzung nicht vorhanden\n" - -#: g10/passphrase.c:450 -msgid "can't set client pid for the agent\n" -msgstr "Client-PID fr den Agent kann nicht gesetzt werden\n" - -#: g10/passphrase.c:458 -msgid "can't get server read FD for the agent\n" -msgstr "Server-Lese-Handle fr den Agent nicht verfgbar\n" - -#: g10/passphrase.c:465 -msgid "can't get server write FD for the agent\n" -msgstr "Server-Schreib-Handle fr den Agent nicht verfgbar\n" - -#: g10/passphrase.c:498 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "fehlerhaft aufgebaute GPG_AGENT_INFO - Umgebungsvariable\n" - -#: g10/passphrase.c:511 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "GPG-Agent-Protokoll-Version %d wird nicht untersttzt\n" - -#: g10/passphrase.c:532 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "Verbindung zu '%s' kann nicht aufgebaut werden: %s\n" - -#: g10/passphrase.c:554 -msgid "communication problem with gpg-agent\n" -msgstr "Kommunikationsproblem mit GPG-Agent\n" - -#: g10/passphrase.c:561 g10/passphrase.c:812 g10/passphrase.c:920 -msgid "problem with the agent - disabling agent use\n" -msgstr "" -"Schwierigkeiten mit dem Agenten - Agent-Ansteuerung wird abgeschaltet\n" - -#: g10/passphrase.c:631 g10/passphrase.c:1019 -#, c-format -msgid " (main key ID %08lX)" -msgstr " (Hauptschlssel-ID %08lX)" - -#: g10/passphrase.c:641 -#, c-format -msgid "" -"You need a passphrase to unlock the secret key for user:\n" -"\"%.*s\"\n" -"%u-bit %s key, ID %08lX, created %s%s\n" -msgstr "" -"Sie bentigen ein Mantra, um den geheimen Schlssel zu entsperren.\n" -"Benutzer: \"\"%.*s\"\n" -"%u-bit %s Schlssel, ID %08lX, erzeugt %s%s\n" - -#: g10/passphrase.c:662 -msgid "Enter passphrase\n" -msgstr "Geben Sie das Mantra ein\n" - -#: g10/passphrase.c:664 -msgid "Repeat passphrase\n" -msgstr "Geben Sie das Mantra nochmal ein\n" - -#: g10/passphrase.c:705 -msgid "passphrase too long\n" -msgstr "Mantra ist zu lang\n" - -#: g10/passphrase.c:718 -msgid "invalid response from agent\n" -msgstr "Falsche Antwort des Agenten\n" - -#: g10/passphrase.c:727 g10/passphrase.c:809 -msgid "cancelled by user\n" -msgstr "Abbruch durch Benutzer\n" - -#: g10/passphrase.c:729 g10/passphrase.c:891 -#, c-format -msgid "problem with the agent: agent returns 0x%lx\n" -msgstr "Schwierigkeiten mit dem Agenten: Agent antwortet 0x%lx\n" - -#: g10/passphrase.c:1005 -msgid "" -"\n" -"You need a passphrase to unlock the secret key for\n" -"user: \"" -msgstr "" -"\n" -"Sie bentigen ein Mantra, um den geheimen Schlssel zu entsperren.\n" -"Benutzer: \"" - -#: g10/passphrase.c:1014 -#, c-format -msgid "%u-bit %s key, ID %08lX, created %s" -msgstr "%u-Bit %s Schlssel, ID %08lX, erzeugt %s" - -#: g10/passphrase.c:1065 -msgid "can't query password in batchmode\n" -msgstr "Mantra kann im Batchmodus nicht abgefragt werden\n" - -#: g10/passphrase.c:1069 -msgid "Enter passphrase: " -msgstr "Geben Sie das Mantra ein: " - -#: g10/passphrase.c:1073 -msgid "Repeat passphrase: " -msgstr "Geben Sie das Mantra nochmal ein: " - -#: g10/plaintext.c:70 -msgid "data not saved; use option \"--output\" to save it\n" -msgstr "" -"Daten wurden nicht gespeichert; verwenden Sie dafr die Option \"--output\"\n" - -#: g10/plaintext.c:112 g10/plaintext.c:125 -#, c-format -msgid "error creating `%s': %s\n" -msgstr "Fehler beim Erstellen von `%s': %s\n" - -#: g10/plaintext.c:362 -msgid "Detached signature.\n" -msgstr "Abgetrennte Beglaubigungen.\n" - -#: g10/plaintext.c:366 -msgid "Please enter name of data file: " -msgstr "Bitte geben Sie den Namen der Datendatei ein: " - -#: g10/plaintext.c:387 -msgid "reading stdin ...\n" -msgstr "lese stdin ...\n" - -#: g10/plaintext.c:421 -msgid "no signed data\n" -msgstr "keine unterschriebene Daten\n" - -#: g10/plaintext.c:429 -#, c-format -msgid "can't open signed data `%s'\n" -msgstr "kann signierte Datei '%s' nicht ffnen.\n" - -#: g10/pubkey-enc.c:102 -#, c-format -msgid "anonymous recipient; trying secret key %08lX ...\n" -msgstr "Ungenannter Empfnger; Versuch mit geheimen Schlssel %08lX ...\n" - -#: g10/pubkey-enc.c:118 -msgid "okay, we are the anonymous recipient.\n" -msgstr "Alles klar, wir sind der ungenannte Empfnger.\n" - -#: g10/pubkey-enc.c:170 -msgid "old encoding of the DEK is not supported\n" -msgstr "alte Kodierung des DEK wird nicht untersttzt\n" - -#: g10/pubkey-enc.c:189 -#, c-format -msgid "cipher algorithm %d%s is unknown or disabled\n" -msgstr "Verschsselungsverfahren %d%s ist unbekannt oder abgeschaltet\n" - -#: g10/pubkey-enc.c:232 -#, c-format -msgid "NOTE: cipher algorithm %d not found in preferences\n" -msgstr "Hinweis: Verfahren %d ist kein bevorzugtes Verschlsselungsverfahren\n" - -#: g10/pubkey-enc.c:254 -#, c-format -msgid "NOTE: secret key %08lX expired at %s\n" -msgstr "Hinweis: geheimer Schlssel %08lX verfllt am %s\n" - -#: g10/pubkey-enc.c:260 -msgid "NOTE: key has been revoked" -msgstr "Hinweis: Schlssel wurde widerrufen" - -#: g10/seckey-cert.c:53 -msgid "secret key parts are not available\n" -msgstr "Teile des geheimen Schlssels sind nicht vorhanden\n" - -#: g10/seckey-cert.c:59 -#, c-format -msgid "protection algorithm %d%s is not supported\n" -msgstr "Schutzverfahren %d%s wird nicht untersttzt\n" - -#: g10/seckey-cert.c:234 -msgid "Invalid passphrase; please try again" -msgstr "Ungltiges Mantra; versuchen Sie es bitte noch einmal" - -#: g10/seckey-cert.c:235 -#, c-format -msgid "%s ...\n" -msgstr "%s ...\n" - -#: g10/seckey-cert.c:292 -msgid "WARNING: Weak key detected - please change passphrase again.\n" -msgstr "" -"WARNUNG: Unsicherer Schlssel entdeckt -\n" -" bitte Mantra nochmals wechseln.\n" - -#: g10/seckey-cert.c:330 -msgid "generating the deprecated 16-bit checksum for secret key protection\n" -msgstr "" -"Die mibilligte 16-bit Prfsumme wird zum Schutz des geheimen Schlssels " -"benutzt\n" - -#: g10/sig-check.c:73 -msgid "WARNING: signature digest conflict in message\n" -msgstr "WARNUNG: Widersprechende Hashverfahren in der signierten Nachricht\n" - -#: g10/sig-check.c:213 -#, c-format -msgid "" -"key %08lX: this is a PGP generated ElGamal key which is NOT secure for " -"signatures!\n" -msgstr "" -"Schlssel %08lX: Dieser durch PGP erzeugte ElGamal-Schlssel ist fr " -"Signaturen NICHT sicher genug!\n" - -#: g10/sig-check.c:222 -#, c-format -msgid "public key %08lX is %lu second newer than the signature\n" -msgstr "" -"ffentlicher Schlssel %08lX ist um %lu Sekunde jnger als die Unterschrift\n" - -#: g10/sig-check.c:223 -#, c-format -msgid "public key %08lX is %lu seconds newer than the signature\n" -msgstr "" -"ffentlicher Schlssel %08lX ist um %lu Sekunden jnger als die " -"Unterschrift\n" - -#: g10/sig-check.c:232 -#, c-format -msgid "" -"key %08lX has been created %lu second in future (time warp or clock " -"problem)\n" -msgstr "" -"Der Schlssel %08lX wurde %lu Sekunde in der Zukunft erzeugt (Zeitreise oder " -"Uhren stimmen nicht berein)\n" - -#: g10/sig-check.c:234 -#, c-format -msgid "" -"key %08lX has been created %lu seconds in future (time warp or clock " -"problem)\n" -msgstr "" -"Der Schlssel %08lX wurde %lu Sekunden in der Zukunft erzeugt (Zeitreise " -"oder Uhren stimmen nicht berein)\n" - -#: g10/sig-check.c:247 -#, c-format -msgid "NOTE: signature key %08lX expired %s\n" -msgstr "Hinweis: Signaturschlssel %08lX ist am %s verfallen.\n" - -#: g10/sig-check.c:346 -#, c-format -msgid "assuming bad signature from key %08lX due to an unknown critical bit\n" -msgstr "" -"Vermutlich eine FALSCHE Unterschrift von Schlssel %08lX, wegen unbekanntem " -"\"critical bit\"\n" - -#: g10/sign.c:103 -#, c-format -msgid "WARNING: unable to %%-expand notation (too large). Using unexpanded.\n" -msgstr "" -"WARNUNG: \"Notation\" kann nicht %%-erweitert werden (zu gro). Verwende " -"\"unerweiterte\".\n" - -#: g10/sign.c:151 -#, c-format -msgid "" -"WARNING: unable to %%-expand policy url (too large). Using unexpanded.\n" -msgstr "" -"WARNUNG: Richtlinien-URL kann nicht %%-erweitert werden (zu gro0). Verwende " -"\"unerweiterte\".\n" - -#: g10/sign.c:303 -#, c-format -msgid "checking created signature failed: %s\n" -msgstr "Prfung der erstellten Unterschrift ist fehlgeschlagen: %s\n" - -#: g10/sign.c:312 -#, c-format -msgid "%s signature from: \"%s\"\n" -msgstr "%s Unterschrift von: \"%s\"\n" - -#: g10/sign.c:462 -#, c-format -msgid "WARNING: `%s' is an empty file\n" -msgstr "WARNUNG: '%s' ist eine leere Datei.\n" - -#: g10/sign.c:645 -msgid "you can only detach-sign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus kann nur mit PGP-2.x-artigen Schlsseln eine abgetrennte " -"Unterschrift erzeugt werden\n" - -#: g10/sign.c:666 g10/sign.c:893 -#, c-format -msgid "can't create %s: %s\n" -msgstr "%s kann nicht erzeugt werden: %s\n" - -#: g10/sign.c:691 -#, c-format -msgid "forcing digest algorithm %s (%d) violates recipient preferences\n" -msgstr "" -"Erzwingen des Hashverfahrens %s (%d) verletzt die Empfngervoreinstellungen\n" - -#: g10/sign.c:785 -msgid "signing:" -msgstr "unterschreibe:" - -#: g10/sign.c:877 -msgid "you can only clearsign with PGP 2.x style keys while in --pgp2 mode\n" -msgstr "" -"Im --pgp2-Modus knnen Sie Klartextunterschriften nur mit PGP-2.x-artigen " -"Schlssel machen\n" - -#: g10/sign.c:1030 -#, c-format -msgid "%s encryption will be used\n" -msgstr "%s Verschlsselung wird verwendet\n" - -#: g10/textfilter.c:134 -#, c-format -msgid "can't handle text lines longer than %d characters\n" -msgstr "Textzeilen lnger als %d Zeichen knnen nicht benutzt werden\n" - -#: g10/textfilter.c:231 -#, c-format -msgid "input line longer than %d characters\n" -msgstr "Eingabezeile ist lnger als %d Zeichen\n" - -#: g10/tdbio.c:128 g10/tdbio.c:1389 -#, c-format -msgid "trustdb rec %lu: lseek failed: %s\n" -msgstr "trustdb Satz %lu: lseek fehlgeschlagen: %s\n" - -#: g10/tdbio.c:134 g10/tdbio.c:1396 -#, c-format -msgid "trustdb rec %lu: write failed (n=%d): %s\n" -msgstr "trustdb Satz %lu: write fehlgeschlagen (n=%d): %s\n" - -#: g10/tdbio.c:244 -msgid "trustdb transaction too large\n" -msgstr "trustdb Transaktion zu gro\n" - -#: g10/tdbio.c:459 -#, c-format -msgid "%s: can't access: %s\n" -msgstr "%s: kann nicht zugegriffen werden: %s\n" - -#: g10/tdbio.c:474 -#, c-format -msgid "%s: directory does not exist!\n" -msgstr "%s: Verzeichnis existiert nicht!\n" - -#: g10/tdbio.c:484 g10/tdbio.c:502 g10/tdbio.c:545 -#, c-format -msgid "%s: can't create lock\n" -msgstr "%s: Sperre kann nicht erzeugt werden\n" - -#: g10/tdbio.c:486 g10/tdbio.c:548 -#, c-format -msgid "%s: can't make lock\n" -msgstr "%s: Sperre kann nicht erzeugt werden\n" - -#: g10/keyring.c:1453 g10/openfile.c:240 g10/openfile.c:310 g10/tdbio.c:492 -#, c-format -msgid "%s: can't create: %s\n" -msgstr "%s: kann nicht erzeugt werden: %s\n" - -#: g10/tdbio.c:507 -#, c-format -msgid "%s: failed to create version record: %s" -msgstr "%s: Fehler beim Erzeugen des Versionsatzes: %s" - -#: g10/tdbio.c:511 -#, c-format -msgid "%s: invalid trustdb created\n" -msgstr "%s: ungltige trust-db erzeugt\n" - -#: g10/tdbio.c:514 -#, c-format -msgid "%s: trustdb created\n" -msgstr "%s: trust-db erzeugt\n" - -#: g10/tdbio.c:554 -msgid "NOTE: trustdb not writable\n" -msgstr "Notiz: Die \"trustdb\" ist nicht schreibbar\n" - -#: g10/tdbio.c:570 -#, c-format -msgid "%s: invalid trustdb\n" -msgstr "%s: ungltige 'Trust'-Datenbank\n" - -#: g10/tdbio.c:602 -#, c-format -msgid "%s: failed to create hashtable: %s\n" -msgstr "%s: hashtable kann nicht erzeugt werden: %s\n" - -#: g10/tdbio.c:610 -#, c-format -msgid "%s: error updating version record: %s\n" -msgstr "%s: Fehler beim ndern des Versionsatzes: %s\n" - -#: g10/tdbio.c:626 g10/tdbio.c:662 g10/tdbio.c:676 g10/tdbio.c:706 -#: g10/tdbio.c:1322 g10/tdbio.c:1349 -#, c-format -msgid "%s: error reading version record: %s\n" -msgstr "%s: Fehler beim Lesen des Versionsatzes: %s\n" - -#: g10/tdbio.c:639 g10/tdbio.c:685 -#, c-format -msgid "%s: error writing version record: %s\n" -msgstr "%s: Fehler beim Schreiben des Versionsatzes: %s\n" - -#: g10/tdbio.c:1124 -#, c-format -msgid "trustdb: lseek failed: %s\n" -msgstr "trustdb: lseek fehlgeschlagen: %s\n" - -#: g10/tdbio.c:1132 -#, c-format -msgid "trustdb: read failed (n=%d): %s\n" -msgstr "trustdb: read failed (n=%d): %s\n" - -#: g10/tdbio.c:1153 -#, c-format -msgid "%s: not a trustdb file\n" -msgstr "%s: keine trustdb Datei\n" - -#: g10/tdbio.c:1170 -#, c-format -msgid "%s: version record with recnum %lu\n" -msgstr "%s: version record with recnum %lu\n" - -#: g10/tdbio.c:1175 -#, c-format -msgid "%s: invalid file version %d\n" -msgstr "%s: invalid file version %d\n" - -#: g10/tdbio.c:1355 -#, c-format -msgid "%s: error reading free record: %s\n" -msgstr "%s: Fehler beim Lesen eines freien Satzes: %s\n" - -#: g10/tdbio.c:1363 -#, c-format -msgid "%s: error writing dir record: %s\n" -msgstr "%s: Fehler beim Schreiben eines Verzeichnis-Satzes: %s\n" - -#: g10/tdbio.c:1373 -#, c-format -msgid "%s: failed to zero a record: %s\n" -msgstr "%s: konnte einen Satz nicht Nullen: %s\n" - -#: g10/tdbio.c:1403 -#, c-format -msgid "%s: failed to append a record: %s\n" -msgstr "%s: konnte Satz nicht anhngen: %s\n" - -#: g10/tdbio.c:1448 -msgid "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n" -msgstr "" -"Die \"Trust\"-Datenbank ist beschdigt; verwenden Sie \"gpg --fix-trustdb" -"\".\n" - -#: g10/trustdb.c:213 -#, c-format -msgid "`%s' is not a valid long keyID\n" -msgstr "'%s' ist keine gltige lange Schlssel-ID\n" - -#: g10/trustdb.c:248 -#, c-format -msgid "key %08lX: accepted as trusted key\n" -msgstr "Schlssel %08lX: Akzeptiert als vertrauenswrdiger Schlssel\n" - -#: g10/trustdb.c:286 -#, c-format -msgid "key %08lX occurs more than once in the trustdb\n" -msgstr "Schlssel %08lX tritt mehr als einmal in der \"trustdb\" auf\n" - -#: g10/trustdb.c:302 -#, c-format -msgid "key %08lX: no public key for trusted key - skipped\n" -msgstr "" -"Schlssel %08lX: kein ffentlicher Schlssel fr den vertrauenswrdigen " -"Schlssel - bersprungen\n" - -#: g10/trustdb.c:311 -#, fuzzy, c-format -msgid "key %08lX marked as ultimately trusted\n" -msgstr "Schlssel ist als uneingeschrnkt vertrauenswrdig gekennzeichnet.\n" - -#: g10/trustdb.c:337 -#, c-format -msgid "trust record %lu, req type %d: read failed: %s\n" -msgstr "trust record %lu, req type %d: read failed: %s\n" - -#: g10/trustdb.c:343 -#, c-format -msgid "trust record %lu is not of requested type %d\n" -msgstr "Vertrauenssatz %lu ist nicht von der angeforderten Art %d\n" - -#: g10/trustdb.c:358 -#, c-format -msgid "trust record %lu, type %d: write failed: %s\n" -msgstr "trust record %lu, type %d: write failed: %s\n" - -#: g10/trustdb.c:373 -#, c-format -msgid "trustdb: sync failed: %s\n" -msgstr "\"Trust-DB\": sync fehlgeschlagen: %s\n" - -#: g10/trustdb.c:463 -#, fuzzy -msgid "unknown trust" -msgstr "Unbekannte Version" - -#: g10/trustdb.c:464 -#, fuzzy -msgid "expired" -msgstr "expire" - -#: g10/trustdb.c:465 -msgid "undefined trust" -msgstr "" - -#: g10/trustdb.c:466 -#, fuzzy -msgid "do NOT trust" -msgstr " %d = Nein, ihm traue ich NICHT\n" - -#: g10/trustdb.c:467 -msgid "marginal trust" -msgstr "" - -#: g10/trustdb.c:468 -#, fuzzy -msgid "full trust" -msgstr "trust" - -#: g10/trustdb.c:469 -#, fuzzy -msgid "ultimate trust" -msgstr "|KEYID|diesem Schlssel uneingeschrnkt vertrauen" - -#: g10/trustdb.c:504 -msgid "no need for a trustdb check\n" -msgstr "\"Trust-DB\"-berprfung nicht ntig\n" - -#: g10/trustdb.c:510 g10/trustdb.c:1912 -#, c-format -msgid "next trustdb check due at %s\n" -msgstr "nchste \"Trust-DB\"-Pflichtberprfung am %s\n" - -#: g10/trustdb.c:519 -#, fuzzy, c-format -msgid "no need for a trustdb check with \"%s\" trust model\n" -msgstr "\"Trust-DB\"-berprfung nicht ntig\n" - -#: g10/trustdb.c:536 -#, fuzzy, c-format -msgid "no need for a trustdb update with \"%s\" trust model\n" -msgstr "\"Trust-DB\"-berprfung nicht ntig\n" - -#: g10/trustdb.c:708 g10/trustdb.c:1073 -#, c-format -msgid "public key %08lX not found: %s\n" -msgstr "ffentlicher Schlssel %08lX nicht gefunden: %s\n" - -#: g10/trustdb.c:919 -msgid "checking the trustdb\n" -msgstr "\"Trust-DB\" wird berprft\n" - -#: g10/trustdb.c:1748 -#, c-format -msgid "public key of ultimately trusted key %08lX not found\n" -msgstr "" -"ff.Schlssel des uneingeschrnkt vertrautem Schlssel %08lX nicht gefunden\n" - -#: g10/trustdb.c:1854 -#, c-format -msgid "checking at depth %d signed=%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" -msgstr "" -"berprfen, Tiefe %d, unterschrieben =%d ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n" - -#: g10/verify.c:108 -msgid "" -"the signature could not be verified.\n" -"Please remember that the signature file (.sig or .asc)\n" -"should be the first file given on the command line.\n" -msgstr "" -"Die Unterschrift konnte nicht berprft werden.\n" -"Denken Sie daran, da die Datei mit der Unterschrift (.sig oder .asc)\n" -"als erster in der Kommandozeile stehen sollte.\n" - -#: g10/verify.c:173 -#, c-format -msgid "input line %u too long or missing LF\n" -msgstr "Eingabezeile %u ist zu lang oder es fehlt ein LF\n" - -#: g10/skclist.c:129 g10/skclist.c:185 -msgid "key is not flagged as insecure - can't use it with the faked RNG!\n" -msgstr "" -"Schlssel ist nicht als unsicher gekennzeichnet - er ist nur mit einem\n" -"echten Zufallsgenerator verwendbar\n" - -#: g10/skclist.c:157 -#, c-format -msgid "skipped `%s': duplicated\n" -msgstr "bersprungen '%s': doppelt\n" - -#: g10/skclist.c:164 g10/skclist.c:172 -#, c-format -msgid "skipped `%s': %s\n" -msgstr "bersprungen '%s': %s\n" - -#: g10/skclist.c:168 -msgid "skipped: secret key already present\n" -msgstr "bersprungen: geheimer Schlssel bereits vorhanden\n" - -#: g10/skclist.c:179 -#, c-format -msgid "" -"skipped `%s': this is a PGP generated ElGamal key which is not secure for " -"signatures!\n" -msgstr "" -"'%s bersprungen: Dies ist ein durch PGP erzeugter ElGamal-Schlssel. Das " -"ist fr Signaturen NICHT sicher genug!\n" - -#. do not overwrite -#: g10/openfile.c:84 -#, c-format -msgid "File `%s' exists. " -msgstr "Datei '%s' existiert bereits. " - -#: g10/openfile.c:86 -msgid "Overwrite (y/N)? " -msgstr "berschreiben (j/N)? " - -#: g10/openfile.c:119 -#, c-format -msgid "%s: unknown suffix\n" -msgstr "%s: unbekannte Dateinamenerweiterung\n" - -#: g10/openfile.c:141 -msgid "Enter new filename" -msgstr "Neuen Dateinamen eingeben" - -#: g10/openfile.c:184 -msgid "writing to stdout\n" -msgstr "Schreiben auf die Standardausgabe\n" - -#: g10/openfile.c:273 -#, c-format -msgid "assuming signed data in `%s'\n" -msgstr "die unterzeichneten Daten sind wohl in '%s'\n" - -#: g10/openfile.c:326 -#, c-format -msgid "new configuration file `%s' created\n" -msgstr "Neue Konfigurationsdatei `%s' erstellt\n" - -#: g10/openfile.c:353 -#, c-format -msgid "%s: can't create directory: %s\n" -msgstr "%s: Verzeichnis kann nicht erzeugt werden: %s\n" - -#: g10/openfile.c:356 -#, c-format -msgid "%s: directory created\n" -msgstr "%s: Verzeichnis erzeugt\n" - -#: g10/encr-data.c:91 -msgid "" -"WARNING: message was encrypted with a weak key in the symmetric cipher.\n" -msgstr "" -"Warnung: Botschaft wurde mit einem unsicheren Schlssel verschlsselt.\n" - -#: g10/encr-data.c:98 -msgid "problem handling encrypted packet\n" -msgstr "Problem beim Bearbeiten des verschlsselten Pakets\n" - -#: g10/seskey.c:52 -msgid "weak key created - retrying\n" -msgstr "Unsicherer Schlssel erzeugt - neuer Versuch\n" - -#: g10/seskey.c:57 -#, c-format -msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" -msgstr "" -"Trotz %d-fachen Versuch konnte die Erzeugung eines unsicheren Schlssels fr " -"sym.Verschlsselung nicht vermieden werden!\n" - -#: g10/seskey.c:200 -msgid "DSA requires the use of a 160 bit hash algorithm\n" -msgstr "DSA bentigt einen 160-bit Hash Algorithmus\n" - -#: g10/delkey.c:120 g10/delkey.c:127 -msgid "(unless you specify the key by fingerprint)\n" -msgstr "(es sei denn, Sie geben den Schlssel mittels Fingerprint an)\n" - -#: g10/delkey.c:126 -msgid "can't do that in batchmode without \"--yes\"\n" -msgstr "Dies kann im Batchmodus ohne \"--yes\" nicht durchgefhrt werden.\n" - -#: g10/delkey.c:138 -msgid "Delete this key from the keyring? " -msgstr "Diesen Schlssel aus dem Schlsselbund lschen? " - -#: g10/delkey.c:146 -msgid "This is a secret key! - really delete? " -msgstr "Dies ist ein privater Schlssel! - Wirklich lschen? " - -#: g10/delkey.c:156 -#, c-format -msgid "deleting keyblock failed: %s\n" -msgstr "lschen des Schlsselblocks fehlgeschlagen: %s\n" - -#: g10/delkey.c:166 -msgid "ownertrust information cleared\n" -msgstr "Der \"Ownertrust\" wurde gelscht\n" - -#: g10/delkey.c:194 -#, c-format -msgid "there is a secret key for public key \"%s\"!\n" -msgstr "" -"Es gibt einen privaten Schlssel zu diesem ffentlichen Schlssel \"%s\"!\n" - -#: g10/delkey.c:196 -msgid "use option \"--delete-secret-keys\" to delete it first.\n" -msgstr "" -"Verwenden Sie zunchst das Kommando \"--delete-secret-key\", um ihn zu " -"entfernen.\n" - -#: g10/helptext.c:47 -msgid "" -"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." -msgstr "" -"Sie mssen selbst entscheiden, welchen Wert Sie hier eintragen; dieser Wert\n" -"wird niemals an eine dritte Seite weitergegeben. Wir brauchen diesen Wert,\n" -"um das \"Netz des Vertrauens\" aufzubauen. Dieses hat nichts mit dem\n" -"(implizit erzeugten) \"Netz der Zertifikate\" zu tun." - -#: g10/helptext.c:53 -msgid "" -"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" -msgstr "" -"Um das Web-of-Trust aufzubauen mu GnuPG wissen, welchen Schlsseln\n" -"uneingeschrnkt vertraut wird. Das sind blicherweise die Schlssel\n" -"auf deren geheimen Schlssel Sie Zugruff haben.\n" -"Antworten Sie mit \"yes\" um diesen Schlssel uneingeschrnkt zu vertrauen\n" - -#: g10/helptext.c:60 -msgid "If you want to use this revoked key anyway, answer \"yes\"." -msgstr "" -"Wenn Sie diesen widerrufenen Schlssel trotzdem benutzen wollen,\n" -"so antworten Sie mit \"ja\"." - -#: g10/helptext.c:64 -msgid "If you want to use this untrusted key anyway, answer \"yes\"." -msgstr "" -"Wenn Sie diesen nicht vertrauenswrdigen Schlssel trotzdem benutzen " -"wollen,\n" -"so antworten Sie mit \"ja\"." - -#: g10/helptext.c:68 -msgid "" -"Enter the user ID of the addressee to whom you want to send the message." -msgstr "Geben Sie die User-ID dessen ein, dem Sie die Botschaft senden wollen." - -#: g10/helptext.c:72 -msgid "" -"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." -msgstr "" -"Whlen Sie die zu verwendende Methode aus.\n" -"\n" -"DSA (alias DSS) bedeutet \"digital signature algorithm\" (Digitales\n" -" Unterschrift-Verfahren). Es kann nur zum Unterschreiben und Beglaubigen\n" -" benutzt werden. Dies ist das empfohlene Verfahren, da dessen berprfung\n" -" wesentlich schneller abluft, als die von \"ElGamal\".\n" -"\n" -"ElGamal ist ein Verfahren fr Unterschrift, Beglaubigung und " -"Verschlsselung\n" -" OpenPGP unterscheidet zwischen zwei Arten von ElGamal: eines nur zum\n" -" Unterschreiben/Beglaubigen und eines zustzlich zum Verschlsseln.\n" -" Eigentlich sind diese Arten identisch; allerdings mssen einige Parameter\n" -" auf eine besondere Art gewhlt werden, um einen sicheren Schlssel fr\n" -" Unterschriften zu erzeugen. Dieses Programm macht dies zwar so, aber " -"andere\n" -" Programme sind laut der OpenPGP-Spezifikation nicht verpflichtet, die\n" -" zweite Art (die mit zustzlichem Verschlsseln) zu verstehen.\n" -"\n" -"Der Hauptschlssel (\"primary Key\") mu auf jeden Fall zum Unterschreiben " -"fhig\n" -"sein. Deshalb kann ein nur-Verschlssel-ElGamal-Schlssel dafr nicht\n" -"verwendet werden." - -#: g10/helptext.c:92 -msgid "" -"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." -msgstr "" -"Obwohl diese Schlssel in RFC 2440 definiert sind, ist ihre Verwendung " -"nicht\n" -"empfohlen. Sie werden nmlich nicht von allen Programmen untersttzt.\n" -"Auerdem sind damit ezeugte Unterschriften recht gro und ihre berprfung\n" -"ist langsam." - -#: g10/helptext.c:98 -msgid "" -"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." -msgstr "" -"Normalerweise ist es nicht gut, denselben Schlssel zum unterschreiben\n" -"und verschlsseln zu nutzen. Dieses Verfahren sollte in speziellen\n" -"Anwendungsgebiten benutzt werden. Bitte lassen Sie sich zuerst von \n" -"einem Sicherheistexperten beraten." - -#: g10/helptext.c:105 -msgid "Enter the size of the key" -msgstr "Whlen Sie die gewnschte Schlssellnge" - -#: g10/helptext.c:109 g10/helptext.c:114 g10/helptext.c:126 g10/helptext.c:158 -#: g10/helptext.c:186 g10/helptext.c:191 g10/helptext.c:196 -msgid "Answer \"yes\" or \"no\"" -msgstr "Geben Sie \"ja\" oder \"nein\" ein" - -#: g10/helptext.c:119 -msgid "" -"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." -msgstr "" -"Geben Sie den bentigten Wert so an, wie er im Prompt erscheint.\n" -"Es ist zwar mglich ein \"ISO\"-Datum (JJJJ-MM-DD) einzugeben, aber man\n" -"erhlt dann ggfs. keine brauchbaren Fehlermeldungen - stattdessen versucht\n" -"der Rechner den Wert als Intervall (von-bis) zu deuten." - -#: g10/helptext.c:131 -msgid "Enter the name of the key holder" -msgstr "Geben Sie den Namen des Schlsselinhabers ein" - -#: g10/helptext.c:136 -msgid "please enter an optional but highly suggested email address" -msgstr "" -"Geben Sie eine E-Mail-Adresse ein. Dies ist zwar nicht unbedingt notwendig,\n" -"aber sehr empfehlenswert." - -#: g10/helptext.c:140 -msgid "Please enter an optional comment" -msgstr "Geben Sie - bei Bedarf - einen Kommentar ein" - -#: g10/helptext.c:145 -msgid "" -"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." -msgstr "" -"N um den Namen zu ndern.\n" -"K um den Kommentar zu ndern.\n" -"E um die E-Mail-Adresse zu ndern.\n" -"F um mit der Schlsselerzeugung fortzusetzen.\n" -"B um die Schlsselerzeugung abbrechen." - -#: g10/helptext.c:154 -msgid "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key." -msgstr "" -"Geben Sie \"ja\" (oder nur \"j\") ein, um den Unterschlssel zu erzeugen." - -#: g10/helptext.c:162 -msgid "" -"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\"." -msgstr "" -"Wenn Sie die User-ID eines Schlssels beglaubigen wollen, sollten Sie " -"zunchst\n" -"sicherstellen, da der Schlssel demjenigen gehrt, der in der User-ID " -"genannt\n" -"ist. Fr Dritte ist es hilfreich zu wissen, wie gut diese Zuordnung " -"berprft\n" -"wurde.\n" -"\n" -"\"0\" zeigt, da Sie keine bestimmte Aussage ber die Sorgfalt der \n" -" Schlsselzuordnung machen.\n" -"\n" -"\"1\" Sie glauben, da der Schlssel der benannten Person gehrt,\n" -" aber Sie konnten oder nahmen die berpfung berhaupt nicht vor.\n" -" Dies ist hilfreich fr eine \"persona\"-berprfung, wobei man den\n" -" Schlssel eines Pseudonym-Trgers beglaubigt\n" -"\n" -"\"2\" Sie nahmen eine flchtige berprfung vor. Das heisst Sie haben z.B.\n" -" den Schlsselfingerabdruck kontrolliert und die User-ID des Schlssels\n" -" anhand des Fotos geprft.\n" -"\n" -"\"3\" Sie haben eine ausfhrlich Kontrolle des Schlssels vorgenommen.\n" -" Das kann z.B. die Kontrolle des Schlsselfingerabdrucks mit dem\n" -" Schlsselinhaber persnlich vorgenommen haben; da Sie die User-ID des\n" -" Schlssel anhand einer schwer zu flschenden Urkunde mit Foto (wie z.B.\n" -" einem Pa) abgeglichen haben und schliesslich per E-Mail-Verkehr die\n" -" E-Mail-Adresse als zum Schlsselbesitzer gehrig erkannt haben.\n" -"\n" -"Beachten Sie, da diese Beispiele fr die Antworten 2 und 3 *nur* Beispiele " -"sind.\n" -"Schluendlich ist es Ihre Sache, was Sie unter \"flchtig\" oder " -"\"ausfhrlich\"\n" -"verstehen, wenn Sie Schlssel Dritter beglaubigen.\n" -"\n" -"Wenn Sie nicht wissen, wie Sie antworten sollen, whlen Sie \"0\"." - -#: g10/helptext.c:200 -msgid "Answer \"yes\" is you want to sign ALL the user IDs" -msgstr "Geben Sie \"ja\" (oder nur \"j\") ein, um alle User-IDs zu beglaubigen" - -#: g10/helptext.c:204 -msgid "" -"Answer \"yes\" if you really want to delete this user ID.\n" -"All certificates are then also lost!" -msgstr "" -"Geben Sie \"ja\" (oder nur \"j\") ein, um diese User-ID zu LSCHEN.\n" -"Alle Zertifikate werden dann auch weg sein!" - -#: g10/helptext.c:209 -msgid "Answer \"yes\" if it is okay to delete the subkey" -msgstr "" -"Geben Sie \"ja\" (oder nur \"j\") ein, um diesen Unterschlssel zu lschen" - -#: g10/helptext.c:214 -msgid "" -"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." -msgstr "" -"Dies ist eine gltige Beglaubigung fr den Schlssel. Es ist normalerweise\n" -"unntig sie zu lschen. Sie ist mglicherweise sogar notwendig, um einen\n" -"Trust-Weg zu diesem oder einem durch diesen Schlssel beglaubigten " -"Schlssel\n" -"herzustellen." - -#: g10/helptext.c:219 -msgid "" -"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." -msgstr "" -"Diese Beglaubigung kann nicht geprft werden, da Sie den passenden " -"Schlssel\n" -"nicht besitzen. Sie sollten die Lschung der Beglaubigung verschieben, bis\n" -"sie wissen, welcher Schlssel verwendet wurde. Denn vielleicht wrde genau\n" -"diese Beglaubigung den \"Trust\"-Weg kompletieren." - -#: g10/helptext.c:225 -msgid "" -"The signature is not valid. It does make sense to remove it from\n" -"your keyring." -msgstr "" -"Diese Beglaubigung ist ungltig. Es ist sinnvoll sie aus Ihrem\n" -"Schlsselbund zu entfernen." - -#: g10/helptext.c:229 -msgid "" -"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." -msgstr "" -"Diese Beglaubigung bindet die User-ID an den Schlssel. Normalerweise ist\n" -"es nicht gut, solche Beglaubigungen zu entfernen. Um ehrlich zu sein:\n" -"Es knnte dann sein, da GnuPG diesen Schlssel gar nicht mehr benutzen " -"kann.\n" -"Sie sollten diese Eigenbeglaubigung also nur dann entfernen, wenn sie aus\n" -"irgendeinem Grund nicht gltig ist und eine zweite Beglaubigung verfgbar " -"ist." - -#: g10/helptext.c:237 -msgid "" -"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" -msgstr "" -"ndern der Voreinstellung aller User-IDs (oder nur der ausgewhlten)\n" -"auf die aktuelle Liste der Voreinstellung. Die Zeitangaben aller " -"betroffenen\n" -"Eigenbeglaubigungen werden um eine Sekunde vorgestellt.\n" - -#: g10/helptext.c:244 -msgid "Please enter the passhrase; this is a secret sentence \n" -msgstr "Bitte geben Sie das Mantra ein. Dies ist ein geheimer Satz \n" - -#: g10/helptext.c:250 -msgid "Please repeat the last passphrase, so you are sure what you typed in." -msgstr "" -"Um sicher zu gehen, da Sie sich bei der Eingabe des Mantras nicht\n" -"vertippt haben, geben Sie diese bitte nochmal ein. Nur wenn beide Eingaben\n" -"bereinstimmen, wird das Mantra akzeptiert." - -#: g10/helptext.c:254 -msgid "Give the name of the file to which the signature applies" -msgstr "" -"Geben Sie den Namen der Datei an, zu dem die abgetrennte Unterschrift gehrt" - -#: g10/helptext.c:259 -msgid "Answer \"yes\" if it is okay to overwrite the file" -msgstr "Geben Sie \"ja\" ein, wenn Sie die Datei berschreiben mchten" - -#: g10/helptext.c:264 -msgid "" -"Please enter a new filename. If you just hit RETURN the default\n" -"file (which is shown in brackets) will be used." -msgstr "" -"Geben Sie bitte einen neuen Dateinamen ein. Falls Sie nur die\n" -"Eingabetaste bettigen, wird der (in Klammern angezeigte) Standarddateiname\n" -"verwendet." - -#: g10/helptext.c:270 -msgid "" -"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" -msgstr "" -"Sie sollten einen Grund fr die Zertifizierung angeben. Je nach\n" -"Zusammenhang knnen Sie aus dieser Liste auswhlen:\n" -" \"Schlssel wurde kompromitiert\"\n" -" Falls Sie Grund zu der Annahme haben, da nicht berechtigte Personen\n" -" Zugriff zu Ihrem geheimen Schlssel hatten\n" -" \"Schlssel ist berholt\"\n" -" Falls Sie diesen Schlssel durch einem neuen ersetzt haben.\n" -" \"Schlssel wird nicht mehr benutzt\"\n" -" Falls Sie diesen Schlssel zurckgezogen haben.\n" -" \"User-ID ist nicht mehr gltig\"\n" -" Um bekanntzugeben, da die User-ID nicht mehr benutzt werden soll.\n" -" So weist man normalerweise auf eine ungltige E-Mailadresse hin.\n" - -#: g10/helptext.c:286 -msgid "" -"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" -msgstr "" -"Wenn Sie mchten, knnen Sie hier einen Text eingeben, der darlegt, warum\n" -"Sie diesen Widerruf herausgeben. Der Text sollte mglichst knapp sein.\n" -"Eine Leerzeile beendet die Eingabe.\n" - -#: g10/helptext.c:301 -msgid "No help available" -msgstr "Keine Hilfe vorhanden." - -#: g10/helptext.c:309 -#, c-format -msgid "No help available for `%s'" -msgstr "Keine Hilfe fr '%s' vorhanden." - -#: g10/keydb.c:182 -#, c-format -msgid "error creating keyring `%s': %s\n" -msgstr "Fehler beim Erzeugen des Schlsselbundes `%s': %s\n" - -#: g10/keydb.c:189 -#, c-format -msgid "keyring `%s' created\n" -msgstr "Schlsselbund `%s' erstellt\n" - -#: g10/keydb.c:608 -#, c-format -msgid "failed to rebuild keyring cache: %s\n" -msgstr "Schlsselbund-Cache konnte nicht neu erzeugt werden: %s\n" - -#: g10/keyring.c:1231 -msgid "WARNING: 2 files with confidential information exists.\n" -msgstr "Warnung: Zwei Dateien mit vertraulichem Inhalt vorhanden.\n" - -#: g10/keyring.c:1233 -#, c-format -msgid "%s is the unchanged one\n" -msgstr "%s ist der Unvernderte\n" - -#: g10/keyring.c:1234 -#, c-format -msgid "%s is the new one\n" -msgstr "%s ist der Neue\n" - -#: g10/keyring.c:1235 -msgid "Please fix this possible security flaw\n" -msgstr "Bitte diesen potentiellen Sicherheitsmangel beseitigen\n" - -#: g10/keyring.c:1351 -#, c-format -msgid "checking keyring `%s'\n" -msgstr "Prfen des Schlsselbundes `%s'\n" - -#: g10/keyring.c:1382 -#, fuzzy, c-format -msgid "%lu keys checked so far (%lu signatures)\n" -msgstr "%lu Schlssel geprft (%lu Beglaubigungen)\n" - -#: g10/keyring.c:1393 -#, c-format -msgid "%lu keys checked (%lu signatures)\n" -msgstr "%lu Schlssel geprft (%lu Beglaubigungen)\n" - -#: g10/keyring.c:1458 -#, c-format -msgid "%s: keyring created\n" -msgstr "%s: Schlsselbund erstellt\n" - -#~ msgid "preference %c%lu is not valid\n" -#~ msgstr "Voreinstellung %c%lu ist nicht gltig\n" - -#, fuzzy -#~ msgid " (default)" -#~ msgstr "Daten entschlsseln (Voreinstellung)" - -#~ msgid "requesting key %08lX from %s\n" -#~ msgstr "Schlssel %08lX wird von %s angefordert\n" - -#~ msgid "can't get key from keyserver: %s\n" -#~ msgstr "Schlssel ist beim Schlsselserver nicht erhltlich: %s\n" - -#~ msgid "error sending to `%s': %s\n" -#~ msgstr "Fehler beim Senden an `%s': %s\n" - -#~ msgid "success sending to `%s' (status=%u)\n" -#~ msgstr "Senden an `%s' erfolgreich (status=%u)\n" - -#~ msgid "failed sending to `%s': status=%u\n" -#~ msgstr "Senden an `%s' erfolglos (status=%u)\n" - -#~ msgid "this keyserver is not fully HKP compatible\n" -#~ msgstr "Dieser Schlsselserver ist nicht vollstndig HKP kompatibel\n" - -#~ msgid "searching for \"%s\" from HKP server %s\n" -#~ msgstr "suche nach \"%s\" auf HKP-Server %s\n" - -#~ msgid "can't search keyserver: %s\n" -#~ msgstr "kann Schlsselserver nicht durchsuchen: %s\n" - -#~ msgid "%lu keys so far checked (%lu signatures)\n" -#~ msgstr "%lu Schlssel bislang geprft (%lu Beglaubigungen)\n" - -#~ msgid "no values for group \"%s\"\n" -#~ msgstr "Keine Werte fr Gruppe \"%s\"\n" - -#, fuzzy -#~ msgid "" -#~ "you have to start GnuPG again, so it can read the new configuration file\n" -#~ msgstr "" -#~ "Sie mssen GnuPG noch einmal starten, damit es die neue " -#~ "Konfigurationsdatei liest\n" - -#~ msgid "changing permission of `%s' failed: %s\n" -#~ msgstr "ndern der Zugriffsrechte fr `%s' ist fehlgeschlagen: %s\n" - -#~ msgid "Fingerprint:" -#~ msgstr "Fingerabdruck:" - -#~ msgid " Fingerprint:" -#~ msgstr " Fingerabdruck:" - -#~ msgid "|NAME=VALUE|use this notation data" -#~ msgstr "|NAME=WERT|diese \"notation\"-Daten verwenden" - -#~ msgid "" -#~ "the first character of a notation name must be a letter or an underscore\n" -#~ msgstr "" -#~ "Das erste Zeichen eines \"notation\"-Namens mu ein Buchstabe oder\n" -#~ "ein Unterstrich sein\n" - -#~ msgid "dots in a notation name must be surrounded by other characters\n" -#~ msgstr "" -#~ "Punkte in einem \"notation\"-Namen mssen von anderen Zeichen umgeben " -#~ "sein\n" - -#~ msgid "" -#~ "WARNING: This key already has a photo ID.\n" -#~ " Adding another photo ID may confuse some versions of PGP.\n" -#~ msgstr "" -#~ "WARNUNG: Dieser Schlssel besitzt bereits eine Foto-ID.\n" -#~ " Ein hinzugefgte Foto-ID knnte einige Versionen von PGP " -#~ "verwirren.\n" - -#~ msgid "You may only have one photo ID on a key.\n" -#~ msgstr "Sie knnen nur eine Foto-ID fr diesen Schlssel haben.\n" - -#~ msgid "Are you sure you still want to sign it?\n" -#~ msgstr "Sind Sie sicher, da Sie dies wiklich unterschreiben mchten?\n" - -#~ msgid " Are you sure you still want to sign it?\n" -#~ msgstr " Sind Sie sicher, da Sie dies immer noch unterschreiben wollen?\n" - -#~ msgid "Really sign? (y/N) " -#~ msgstr "Wirklich unterschreiben? (j/N) " - -#~ msgid "key %08lX: our copy has no self-signature\n" -#~ msgstr "Schlssel %08lX: Unsere Kopie hat keine Eigenbeglaubigung\n" - -#~ msgid "Do you really need such a large keysize? " -#~ msgstr "Brauchen Sie wirklich einen derartig langen Schlssel? " - -#~ msgid " signed by %08lX at %s\n" -#~ msgstr " beglaubigt durch %08lX um %s\n" - -#~ msgid "--delete-secret-key user-id" -#~ msgstr "--delete-secret-key User-ID" - -#~ msgid "--delete-key user-id" -#~ msgstr "--delete-key User-ID" - -#~ msgid "--delete-secret-and-public-key user-id" -#~ msgstr "--delete-secret-and-public-key User-ID" - -#~ msgid "Enter the user ID: " -#~ msgstr "Geben Sie die User-ID ein: " - -#~ msgid "skipped: public key already set with --encrypt-to\n" -#~ msgstr "" -#~ "bersprungen: ffentlicher Schlssel bereits mittels --encrypt-to " -#~ "gesetzt\n" - -#~ msgid "" -#~ "\n" -#~ "WARNING: This is a PGP2-style key\n" -#~ msgstr "WARNUNG: '%s' ist eine leere Datei.\n" - -# valid user replies (not including 1..4) -#~ msgid "sSmMqQ" -#~ msgstr "sSmMqQ" - -#~ msgid "no keyserver known (use option --keyserver)\n" -#~ msgstr "Kein Schlsselserver bekannt (Option --keyserver verwenden)\n" - -#~ msgid "%s: not a valid key ID\n" -#~ msgstr "%s: Dies ist keine gltige Schlssel-ID\n" - -#~ msgid "duplicate (short) key ID %08lX\n" -#~ msgstr "ffentlicher Schlssel ist %08lX\n" - -#~ msgid "%lu key(s) to refresh\n" -#~ msgstr "\t%lu Schlssel mit Fehlern\n" - -#~ msgid "|[NAMES]|check the trust database" -#~ msgstr "|[NAMEN]|berprfen der \"Trust\"-Datenbank" - -#~ msgid "" -#~ "Could not find a valid trust path to the key. Let's see whether we\n" -#~ "can assign some missing owner trust values.\n" -#~ "\n" -#~ msgstr "" -#~ "Fr diesen Schlssel konnte kein gltiger \"Trust Path\" gefunden " -#~ "werden.\n" -#~ "Mal sehen, ob wir sonst irgendwie ein paar fehlende \"Owner trust\" " -#~ "Werte \n" -#~ "ermitteln knnen.\n" -#~ "\n" - -#~ msgid "" -#~ "No path leading to one of our keys found.\n" -#~ "\n" -#~ msgstr "" -#~ "Kein Pfad fhrt zu einem unserer Schlsseln.\n" -#~ "\n" - -#~ msgid "" -#~ "No certificates with undefined trust found.\n" -#~ "\n" -#~ msgstr "" -#~ "Keine Zertifikate mit undefiniertem Vertrauen gefunden.\n" -#~ "\n" - -#~ msgid "" -#~ "No trust values changed.\n" -#~ "\n" -#~ msgstr "" -#~ "Keine \"trust\" Werte gendert.\n" -#~ "\n" - -#~ msgid "%08lX: no info to calculate a trust probability\n" -#~ msgstr "" -#~ "%08lX: Keine Infos zur Berechnung der Vertrauenswahrscheinlichkeit " -#~ "vorgefunden\n" - -#~ msgid "%s: error checking key: %s\n" -#~ msgstr "%s: Fehler beim Prfen des Schlssels: %s\n" - -#~ msgid "too many entries in unk cache - disabled\n" -#~ msgstr "zu viele Eintrge im unk-Lager - abgeschaltet\n" - -#~ msgid "secret key %08lX not imported (use %s to allow for it)\n" -#~ msgstr "" -#~ "Geheimer Schlssel %08lX nicht importiert (%s verwenden, um das zu " -#~ "ermglichen)\n" - -#~ msgid "update of trustdb failed: %s\n" -#~ msgstr "nderung der \"Trust-DB\" fehlgeschlagen: %s\n" - -#~ msgid "assuming bad MDC due to an unknown critical bit\n" -#~ msgstr "" -#~ "Vermutlich ist das Siegel (MDC) BESCHDIGT (wegen unbekanntem \"critical " -#~ "bit\")\n" - -#~ msgid "error reading dir record for LID %lu: %s\n" -#~ msgstr "Fehler beim Lesen des Dir-Satzes fr LID %lu: %s\n" - -#~ msgid "lid %lu: expected dir record, got type %d\n" -#~ msgstr "lid %lu: Dir-Satz erwartet, aber es kam Typ %d\n" - -#~ msgid "no primary key for LID %lu\n" -#~ msgstr "Kein Hauptschlssel fr LID %lu\n" - -#~ msgid "error reading primary key for LID %lu: %s\n" -#~ msgstr "Fehler beim Lesen den Hauptschlssels der LID %lu: %s\n" - -#~ msgid "get_dir_record: search_record failed: %s\n" -#~ msgstr "get_dir_record: search_record fehlgeschlagen: %s\n" - -#~ msgid "key %08lX: query record failed\n" -#~ msgstr "Schlssel %08lX: Satzabfrage fehlgeschlagen\n" - -#~ msgid "key %08lX: already in trusted key table\n" -#~ msgstr "Schlssel %08lX: Ist bereits in geheimer Schlsseltabelle\n" - -#~ msgid "NOTE: secret key %08lX is NOT protected.\n" -#~ msgstr "HINWEIS: Geheimer Schlssel %08lX ist NICHT geschtzt.\n" - -#~ msgid "key %08lX: secret and public key don't match\n" -#~ msgstr "" -#~ "Schlssel %08lX: geheimer und ffentlicher Schlssel passen nicht " -#~ "zusammen.\n" - -#~ msgid "enumerate secret keys failed: %s\n" -#~ msgstr "enum_secret_keys fehlgeschlagen: %s\n" - -#~ msgid "key %08lX.%lu: Good subkey binding\n" -#~ msgstr "Schlssel %08lX.%lu: Korrekte Unterschlssel-Anbindung\n" - -#~ msgid "key %08lX.%lu: Invalid subkey binding: %s\n" -#~ msgstr "Schlssel %08lX.%lu: Ungltige Unterschlssel-Anbindung: %s\n" - -#~ msgid "key %08lX.%lu: Valid key revocation\n" -#~ msgstr "Schlssel %08lX.%lu: Gltiger Schlsselwiderruf\n" - -#~ msgid "key %08lX.%lu: Invalid key revocation: %s\n" -#~ msgstr "Schlssel %08lX.%lu: Ungltiger Schlsselwiderruf: %s\n" - -#~ msgid "Good self-signature" -#~ msgstr "Korrekte Eigenbeglaubigung" - -#~ msgid "Invalid self-signature" -#~ msgstr "Ungltige Eigenbeglaubigung" - -#~ msgid "Valid user ID revocation skipped due to a newer self signature" -#~ msgstr "" -#~ "Gltiger User-ID-Widerruf ignoriert, da eine neuere Eigenbeglaubigung " -#~ "vorliegt" - -#~ msgid "Valid user ID revocation" -#~ msgstr "Gltiger User-ID-Widerruf" - -#~ msgid "Invalid user ID revocation" -#~ msgstr "Ungltiger User-ID-Widerruf" - -#~ msgid "Valid certificate revocation" -#~ msgstr "Gltiger Zerifikat-Widerruf" - -#~ msgid "Good certificate" -#~ msgstr "Korrektes Zertifikat" - -#~ msgid "Invalid certificate revocation" -#~ msgstr "Ungltiger Zertifikatswiderruf" - -#~ msgid "Invalid certificate" -#~ msgstr "Ungltiges Zertifikat" - -#~ msgid "sig record %lu[%d] points to wrong record.\n" -#~ msgstr "Signatursatz %lu[%d] zeigt auf falschen Satz.\n" - -#~ msgid "duplicated certificate - deleted" -#~ msgstr "Doppelte Zertifikate - entfernt" - -#~ msgid "tdbio_search_dir failed: %s\n" -#~ msgstr "tdbio_search_dir fehlgeschlagen: %s\n" - -#~ msgid "lid ?: insert failed: %s\n" -#~ msgstr "lid ?: Einfgen fehlgeschlagen: %s\n" - -#~ msgid "lid %lu: insert failed: %s\n" -#~ msgstr "lid %lu: Einfgen fehlgeschlagen: %s\n" - -#~ msgid "lid %lu: inserted\n" -#~ msgstr "lid %lu: eingefgt\n" - -#~ msgid "error reading dir record: %s\n" -#~ msgstr "Fehler beim Lesen des Verz.Satzes: %s\n" - -#~ msgid "\t%lu keys inserted\n" -#~ msgstr "\t%lu Schlssel eingefgt\n" - -#~ msgid "enumerate keyblocks failed: %s\n" -#~ msgstr "enumerate Schlsselblock fehlgeschlagen: %s\n" - -#~ msgid "lid %lu: dir record w/o key - skipped\n" -#~ msgstr "lid %lu: Dir-Satz ohne Schlssel - bergangen\n" - -#~ msgid "\t%lu due to new pubkeys\n" -#~ msgstr "\t%lu wegen neuer Schlssel\n" - -#~ msgid "\t%lu keys skipped\n" -#~ msgstr "\t%lu Schlssel bersprungen\n" - -#~ msgid "\t%lu keys updated\n" -#~ msgstr "\t%lu Schlssel gendert\n" - -#~ msgid "Ooops, no keys\n" -#~ msgstr "Huch, keine Schlssel\n" - -#~ msgid "Ooops, no user IDs\n" -#~ msgstr "Huch, keine User-IDs\n" - -#~ msgid "check_trust: search dir record failed: %s\n" -#~ msgstr "check_trust: Suche nach Dir-Satz fehlgeschlagen: %s\n" - -#~ msgid "key %08lX: insert trust record failed: %s\n" -#~ msgstr "Schlssel %08lX: 'trust record' einfgen fehlgeschlagen: %s\n" - -#~ msgid "key %08lX.%lu: inserted into trustdb\n" -#~ msgstr "Schlssel %08lX.%lu: in \"trustdb\" eingefgt\n" - -#~ msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" -#~ msgstr "" -#~ "Schlssel %08lX.%lu: wurde in der Zukunft erzeugt (Zeitreise oder Uhren " -#~ "stimmen nicht berein)\n" - -#~ msgid "key %08lX.%lu: expired at %s\n" -#~ msgstr "Schlssel %08lX.%lu: verfallen am %s\n" - -#~ msgid "key %08lX.%lu: trust check failed: %s\n" -#~ msgstr "Schlssel %08lX.%lu: Vertrauensprfung fehlgeschlagen: %s\n" - -#~ msgid "user '%s' not found: %s\n" -#~ msgstr "Benutzer '%s' nicht gefunden: %s\n" - -#~ msgid "problem finding '%s' in trustdb: %s\n" -#~ msgstr "Problem, '%s' in der Trust-DB zu finden: %s\n" - -#~ msgid "user '%s' not in trustdb - inserting\n" -#~ msgstr "User '%s' ist nicht in der 'Trust'-Datenbank - wird eingefgt\n" - -#~ msgid "failed to put '%s' into trustdb: %s\n" -#~ msgstr "konnte '%s' nicht in die 'Trust'-Datenbank hineintun: %s\n" - -#~ msgid "too many random bits requested; the limit is %d\n" -#~ msgstr "Zu viele Zufallswerte angefordert: Die Grenze liegt bei %d\n" - -#~ msgid "For info see http://www.gnupg.org" -#~ msgstr "Weitere Infos: siehe http://www.gnupg.org" - -#~ msgid "Do you really want to create a sign and encrypt key? " -#~ msgstr "" -#~ "Mchten Sie wirklich einen Unterschriften-/Verschlsselungschlssel " -#~ "erzeugen? " - -#~ msgid "%s: user not found: %s\n" -#~ msgstr "%s: Benutzer nicht gefunden: %s\n" - -#~ msgid "certificate read problem: %s\n" -#~ msgstr "Zertifikat Leseproblem: %s\n" - -#~ msgid "can't lock keyring `%s': %s\n" -#~ msgstr "kann Schlsselbund `%s' nicht sperren: %s\n" - -#~ msgid "%s: user not found\n" -#~ msgstr "%s: Benutzer nicht gefunden\n" - -#~ msgid "WARNING: can't yet handle long pref records\n" -#~ msgstr "WARNUNG: Lange 'Pref'-Records knnen noch nicht benutzt werden\n" - -#~ msgid "%s: can't create keyring: %s\n" -#~ msgstr "%s: Schlsselbund kann nicht erzeugt werden: %s\n" - -#~ msgid "invalid" -#~ msgstr "ungltig" - -#~ msgid "RSA key cannot be used in this version\n" -#~ msgstr "RSA-Schlssel knnen in dieser Version nicht verwendet werden\n" - -#~ msgid "No key for user ID\n" -#~ msgstr "Kein Schlssel fr User-ID\n" - -#~ msgid "No user ID for key\n" -#~ msgstr "Keine User-ID fr Schlssel\n" +msgid " using certificate ID %08lX\n" +msgstr "mittels Zertifikat ID %08lX\n" -#~ msgid "no secret key for decryption available\n" -#~ msgstr "kein geheimer Schlssel zur Entschlsselung vorhanden\n" +#: sm/verify.c:497 +msgid "Good signature from" +msgstr "Korrekte Signatur von" -#~ msgid " (%d) ElGamal in a v3 packet\n" -#~ msgstr " (%d) ElGamal in einem v3-Paket\n" +#: sm/verify.c:498 +msgid " aka" +msgstr " alias" -#~ msgid "Key generation can only be used in interactive mode\n" -#~ msgstr "" -#~ "Die Schlsselerzeugung kann nur im interaktiven Modus benutzt werden.\n" +#~ msgid " skipped new keys: %lu\n" +#~ msgstr " bersprungene Schlssel: %lu\n" -- cgit v1.2.3 From 687d5bafaaa568f6a109a85b2e1c1600c2d88ea1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Jan 2003 13:35:32 +0000 Subject: Copied wrong files. Fixed. --- doc/ChangeLog | 225 ++++++++------------------------------------------------ doc/Makefile.am | 35 ++------- 2 files changed, 37 insertions(+), 223 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 9ef2473ab..d15420cfc 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,230 +1,65 @@ 2002-12-04 Werner Koch <wk@gnupg.org> - Released 0.9.4. + * gpg-agent.texi (Agent Signals): New. 2002-12-03 Werner Koch <wk@gnupg.org> - * configure.ac (GNUPG_PROTECT_TOOL): New option --with-protect-tool. - -2002-11-25 Werner Koch <wk@gnupg.org> - - * configure.ac (NEED_KSBA_VERSION): Does now require 0.4.6. + * gpgsm.texi (Operational Commands): Add --passwd and + --call-protect-tool. + * gpg-agent.texi (Agent PASSWD): New 2002-11-13 Werner Koch <wk@gnupg.org> - * README: Noted where to find gpg-protect-tool. + * gpg-agent.texi (Invoking GPG-AGENT): Tell about GPG_TTY. 2002-11-12 Werner Koch <wk@gnupg.org> - * config.sub, config.guess: Updated from ftp.gnu.org/gnu/config - to version 2002-11-08. - -2002-11-11 Werner Koch <wk@gnupg.org> - - Released 0.9.3. - -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. - -2002-10-31 Neal H. Walfield <neal@g10code.de> - - * configure.ac (PTH_LIBS): If pth is found, add the output of - `$PTH_CONFIG --ldflags`, not just `$PTH_CONFIG --libs`. - -2002-09-20 Werner Koch <wk@gnupg.org> - - Released 0.9.2. + * gpgsm.texi (Operational Commands): Add --call-dirmngr. -2002-09-05 Neal H. Walfield <neal@g10code.de> +2002-09-25 Werner Koch <wk@gnupg.org> - * configure.ac: Check for makeinfo. + * gpg-agent.texi (Agent Options): Add --keep-tty and --keep-display. -2002-09-03 Neal H. Walfield <neal@g10code.de> +2002-09-12 Werner Koch <wk@gnupg.org> - * autogen.sh (have_version): New function. Generalize and - simplify logic for finding and determining the versions of GNU - programs. Use it. + * gpg-agent.texi (Invoking GPG-AGENT): Explained how to start only + one instance. -2002-08-23 Werner Koch <wk@gnupg.org> +2002-08-28 Werner Koch <wk@gnupg.org> - Released 0.9.1. + * gpg-agent.texi (Agent Options): Explained more options. + * scdaemon.texi (Scdaemon Options): Ditto. - * acinclude.m4 (AM_PATH_LIBGCRYPT): Updated from Libgcrypt. - (AM_PATH_OPENSC): Strip non-digits from the micro version. +2002-08-09 Werner Koch <wk@gnupg.org> -2002-08-21 Werner Koch <wk@gnupg.org> + * Makefile.am (gnupg_TEXINFOS): Include contrib.texi. - Released 0.9.0. +2002-08-06 Werner Koch <wk@gnupg.org> - * configure.ac: Changed the default homedir to .gnupg. - * README-alpha: Removed. + * gpgsm.texi: Added more options. -2002-08-19 Werner Koch <wk@gnupg.org> +2002-07-26 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. + * assuan.texi: New. + * gpgsm.texi, scdaemon.texi, gpg-agent.texi: Documented the Assuan + protocol used. 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. + * 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> - 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. + * gpgsm.texi (Invocation): Described the various debug flags. 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. - + * Makefile.am, gpgsm.texi: New. - Copyright 2001, 2002 Free Software Foundation, Inc. + 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 @@ -233,5 +68,3 @@ 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. - - diff --git a/doc/Makefile.am b/doc/Makefile.am index ccfc98fb2..78ae80a2e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,8 +1,7 @@ -# Makefile.am - main makefile for NewPG/GnuPG -# Copyright (C) 2001 Free Software Foundation, Inc. -# +# 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 @@ -19,29 +18,11 @@ ## Process this file with automake to produce Makefile.in -EXTRA_DIST = autogen.sh - -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 = intl jnlib assuan common kbx ${sm} ${agent} ${scd} po doc tests - - -dist-hook: - @set -e; echo "$(VERSION)" > $(distdir)/VERSION +info_TEXINFOS = gnupg.texi +gnupg_TEXINFOS = \ + gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi\ + contrib.texi gpl.texi fdl.texi +DISTCLEANFILES = gnupg.tmp gnupg.ops -- cgit v1.2.3 From 8cdc83cdb5c81404e46a699f52be68d6728a16b0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Apr 2003 10:37:24 +0000 Subject: * configure.ac (ALL_LINUGAS): Removed. * Makefile.am (ACLOCAL_AMFLAGS): New. * configure.ac (AM_GNU_GETTEXT_VERSION): New. Set to 0.11.5. --- ChangeLog | 20 ++++++++++++++++++ Makefile.am | 8 ++++---- README | 5 ++--- TODO | 15 ++++++++++++++ acinclude.m4 | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ autogen.sh | 8 ++++---- configure.ac | 35 ++++++++++++++++++++++--------- 7 files changed, 137 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3458b7f65..972c25204 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2003-04-29 Werner Koch <wk@gnupg.org> + + * 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. diff --git a/Makefile.am b/Makefile.am index ccfc98fb2..d9a09264f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,9 @@ ## Process this file with automake to produce Makefile.in -EXTRA_DIST = autogen.sh +ACLOCAL_AMFLAGS = -I m4 + +EXTRA_DIST = scripts/config.rpath autogen.sh if BUILD_GPGSM sm = sm @@ -37,11 +39,9 @@ else scd = endif -SUBDIRS = intl jnlib assuan common kbx ${sm} ${agent} ${scd} po doc tests +SUBDIRS = m4 intl jnlib common kbx ${sm} ${agent} ${scd} po doc tests dist-hook: @set -e; echo "$(VERSION)" > $(distdir)/VERSION - - diff --git a/README b/README index cbc2e8a10..b0b23c5f6 100644 --- a/README +++ b/README @@ -2,15 +2,14 @@ GnuPG 1.9 is a temporary protect to work on GnuPG extensions. It will eventually lead to a GnuPG 2.0 release. jnlib/ utility functions -assuan/ assuan protocol library kbx/ keybox library sm/ the gpgsm program agent/ the gpg-agent scd/ the smartcard daemon -Libksba and Libgcrypt are required to build it. +Libassuan, Libksba and Libgcrypt are required to build it. -Assuan and Keybox are both designed to be source include-able. +Keybox is designed to be source include-able. A texinfo manual `gnupg.info' will get installed. Some commands and options given below. diff --git a/TODO b/TODO index 213cbb6d8..9b277aa5e 100644 --- a/TODO +++ b/TODO @@ -55,4 +55,19 @@ might want to have an agent context for each service request * sm/export.c ** Return an error code or a status info per user ID. +* ALL +** Return IMPORT_OK status. + + + + + + + + + + + + + diff --git a/acinclude.m4 b/acinclude.m4 index e4ba95cb2..515640225 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -287,6 +287,73 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, AC_SUBST(LIBGCRYPT_LIBS) ]) +dnl [copied from libassuan 0.0.1] +dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS +dnl +AC_DEFUN(AM_PATH_LIBASSUAN, +[ AC_ARG_WITH(libassuan-prefix, + AC_HELP_STRING([--with-libassuan-prefix=PFX], + [prefix where LIBASSUAN is installed (optional)]), + libassuan_config_prefix="$withval", libassuan_config_prefix="") + if test x$libassuan_config_prefix != x ; then + libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix" + if test x${LIBASSUAN_CONFIG+set} != xset ; then + LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config + fi + fi + + AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no) + min_libassuan_version=ifelse([$1], ,0.0.1,$1) + AC_MSG_CHECKING(for LIBASSUAN - version >= $min_libassuan_version) + ok=no + if test "$LIBASSUAN_CONFIG" != "no" ; then + req_major=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + libassuan_config_version=`$LIBASSUAN_CONFIG $libassuan_config_args --version` + major=`echo $libassuan_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $libassuan_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $libassuan_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 + LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags` + LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + LIBASSUAN_CFLAGS="" + LIBASSUAN_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBASSUAN_CFLAGS) + AC_SUBST(LIBASSUAN_LIBS) +]) + + dnl [Copied from libksba] dnl AM_PATH_KSBA([MINIMUM-VERSION, diff --git a/autogen.sh b/autogen.sh index 29f4b7ae5..bf958dbcb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -150,11 +150,11 @@ fi #echo "Running libtoolize... Ignore non-fatal messages." #echo "no" | libtoolize -echo "Running gettextize... Ignore non-fatal messages." -echo "no" | gettextize +echo "Running autopoint" +autopoint -echo "Running $aclocal" -$aclocal +echo "Running $aclocal -I m4" +$aclocal -I m4 echo "Running autoheader..." autoheader echo "Running $automake --gnu -a" diff --git a/configure.ac b/configure.ac index 07b38f973..37125897d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ -# configure.ac - for NewPG -# Copyright (C) 2001, 2002 Free Software Foundation, Inc, +# configure.ac - for GnuPG 1.9 +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc, # # This file is part of GnuPG. # @@ -21,15 +21,17 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(newpg, 1.9.0-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.0-cvs, gnupg-devel@gnupg.org) NEED_LIBGCRYPT_VERSION=1.1.8 +NEED_LIBASSUAN_VERSION=0.0.1 NEED_KSBA_VERSION=0.4.6 NEED_OPENSC_VERSION=0.7.0 -ALL_LINGUAS="de" PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION +AM_GNU_GETTEXT_VERSION(0.11.5) + AC_CONFIG_AUX_DIR(scripts) AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) @@ -37,6 +39,7 @@ AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AM_MAINTAINER_MODE # Some status variables to give feedback at the end of a configure run +habe_libassuan=no have_ksba=no have_opensc=no have_pth=no @@ -214,6 +217,21 @@ AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_VERSION",, ]])) +# +# libassuan is used for IPC +# +AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION", + have_libasssuan=yes,have_libasssun=no) +if test "$have_libassuan" = "no"; then + AC_MSG_ERROR([[ +*** +*** You need libassuan to build this program.. +*** It should be available at the same place you +*** got this software. +***]]) +fi + + # # libksba is our X.509 support library # @@ -268,10 +286,8 @@ fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) - AM_GNU_GETTEXT - # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([string.h locale.h]) @@ -343,12 +359,11 @@ AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") -AC_CONFIG_FILES([ +AC_CONFIG_FILES([ m4/Makefile Makefile -intl/Makefile po/Makefile.in +intl/Makefile jnlib/Makefile -assuan/Makefile common/Makefile kbx/Makefile sm/Makefile @@ -361,7 +376,7 @@ AC_OUTPUT echo " - NewPG v${VERSION} has been configured as follows: + GnuPG v${VERSION} has been configured as follows: OpenPGP: $build_gpg S/MIME: $build_gpgsm -- cgit v1.2.3 From 0b05a740527901d43c772ea5f54ab7bf4aee7e50 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Apr 2003 10:41:31 +0000 Subject: * LINUGAS: NEW. --- po/ChangeLog | 14 ++++++++++++++ po/LINUGAS | 4 ++++ po/Makevars | 25 +++++++++++++++++++++++++ po/de.po | 6 ++---- 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 po/LINUGAS create mode 100644 po/Makevars diff --git a/po/ChangeLog b/po/ChangeLog index 669dfbe30..94547f3ea 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,17 @@ +2003-04-29 Werner Koch <wk@gnupg.org> + + * LINUGAS: NEW. + +2003-04-29 gettextize <bug-gnu-gettext@gnu.org> + + * Rules-quot: New file, from gettext-0.11.5. + * boldquot.sed: New file, from gettext-0.11.5. + * en@boldquot.header: New file, from gettext-0.11.5. + * en@quot.header: New file, from gettext-0.11.5. + * insert-header.sin: New file, from gettext-0.11.5. + * quot.sed: New file, from gettext-0.11.5. + * remove-potcdate.sin: New file, from gettext-0.11.5. + 2002-08-21 Werner Koch <wk@gnupg.org> * de.po: Updated the translation. diff --git a/po/LINUGAS b/po/LINUGAS new file mode 100644 index 000000000..eaa0fea22 --- /dev/null +++ b/po/LINUGAS @@ -0,0 +1,4 @@ +# Set of available languages. +de + + diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 000000000..8b09f53b0 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,25 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Free Software Foundation, Inc. + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = diff --git a/po/de.po b/po/de.po index 67ffdee9e..a7febc6c3 100644 --- a/po/de.po +++ b/po/de.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: NewPG 0.9.3\n" -"POT-Creation-Date: 2002-12-04 20:14+0100\n" +"POT-Creation-Date: 2003-04-29 12:08+0200\n" "PO-Revision-Date: 2002-08-21 13:13+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -205,12 +205,12 @@ msgstr "Problem mit dem Agenten\n" msgid "Please enter the PIN%s%s%s to unlock the card" msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" -#. okay #: agent/genkey.c:82 msgid "does not match - try again" msgstr "Keine bereinstimmung - bitte nochmal versuchen" #: agent/genkey.c:109 +#, c-format msgid "Please enter the passphrase to%0Ato protect your new key" msgstr "" "Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlssel zu schtzen" @@ -738,8 +738,6 @@ msgstr "" msgid "always use a MDC for encryption" msgstr "" -#. { oInteractive, "interactive", 0, N_("prompt before overwriting") }, -#. { oUseAgent, "use-agent",0, N_("use the gpg-agent")}, #: sm/gpgsm.c:298 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -- cgit v1.2.3 From c483f6227b22252a68c9c6ad29a05d5d2c057725 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Apr 2003 19:05:17 +0000 Subject: * 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. --- ChangeLog | 4 ++++ configure.ac | 30 ++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 972c25204..dd9c320fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ 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. diff --git a/configure.ac b/configure.ac index 37125897d..e075d7196 100644 --- a/configure.ac +++ b/configure.ac @@ -247,10 +247,14 @@ fi # -# OpenSC is needed by the SCdaemon - if it is not availbale we won't -# build the SCdaemon +# OpenSC is needed by the SCdaemon - if it is not availbale we can only +# build a limited SCdaemon # AM_PATH_OPENSC("$NEED_OPENSC_VERSION",have_opensc=yes,have_opensc=no) +if test $have_opensc = yes; then + AC_DEFINE(HAVE_OPENSC,1, + [defined if the OpenSC library is available]) +fi # @@ -330,10 +334,6 @@ AC_DEFINE(HAVE_JNLIB_LOGGING, 1, # # Decide what to build # -if test $have_opensc = no; then - build_scdaemon=no -fi - if test $have_ksba = no; then build_gpgsm=no build_scdaemon=no @@ -346,10 +346,19 @@ if test "$build_agent" = "yes"; then fi fi -build_scdaemon_threaded="" +build_scdaemon_extra="" if test "$build_scdaemon" = "yes"; then + tmp="" if test $have_pth = no; then - build_scdaemon_threaded="(not multi-threaded)" + build_scdaemon_extra="not multi-threaded" + tmp=", " + fi + if test $have_opensc = no; then + build_scdaemon_extra="${build_scdaemon_extra}${tmp}no pkcs#15" + tmp=", " + fi + if test -n "$build_scdaemon_extra"; then + build_scdaemon_extra="(${build_scdaemon_extra})" fi fi @@ -376,12 +385,12 @@ AC_OUTPUT echo " - GnuPG v${VERSION} has been configured as follows: + GnuPG v${VERSION} has been configured as follows: OpenPGP: $build_gpg S/MIME: $build_gpgsm Agent: $build_agent $build_agent_threaded - Smartcard: $build_scdaemon $build_scdaemon_threaded + Smartcard: $build_scdaemon $build_scdaemon_extra Protect tool: $gnupg_protect_tool Default agent: $gnupg_agent_pgm @@ -389,3 +398,4 @@ echo " Default scdaemon: $gnupg_scdaemon_pgm Default dirmngr: $gnupg_dirmngr_pgm " + -- cgit v1.2.3 From 18ab605bcc720a6c9115a9e1570e903b53f36b76 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Apr 2003 19:08:35 +0000 Subject: * scdaemon.c: New options --print-atr and --reader-port * apdu.c, apdu.h: New * card.c, card-p15.c, card-dinsig.c: Allow build without OpenSC. --- doc/scdaemon.texi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 55f9f8a0f..7b776c750 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -58,6 +58,11 @@ default mode is to create a socket and listen for commands there. 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 @@ -131,6 +136,11 @@ debugging. 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). @end table -- cgit v1.2.3 From efeb7657d636dc9992875588daeb016aec9c0fb0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Apr 2003 19:09:48 +0000 Subject: Update to gettext 0.11.5 --- m4/ChangeLog | 21 +++++++++++++++++++++ m4/Makefile.am | 1 + 2 files changed, 22 insertions(+) create mode 100644 m4/ChangeLog create mode 100644 m4/Makefile.am diff --git a/m4/ChangeLog b/m4/ChangeLog new file mode 100644 index 000000000..84a288341 --- /dev/null +++ b/m4/ChangeLog @@ -0,0 +1,21 @@ +2003-04-29 gettextize <bug-gnu-gettext@gnu.org> + + * codeset.m4: New file, from gettext-0.11.5. + * gettext.m4: New file, from gettext-0.11.5. + * glibc21.m4: New file, from gettext-0.11.5. + * iconv.m4: New file, from gettext-0.11.5. + * intdiv0.m4: New file, from gettext-0.11.5. + * inttypes.m4: New file, from gettext-0.11.5. + * inttypes_h.m4: New file, from gettext-0.11.5. + * inttypes-pri.m4: New file, from gettext-0.11.5. + * isc-posix.m4: New file, from gettext-0.11.5. + * lcmessage.m4: New file, from gettext-0.11.5. + * lib-ld.m4: New file, from gettext-0.11.5. + * lib-link.m4: New file, from gettext-0.11.5. + * lib-prefix.m4: New file, from gettext-0.11.5. + * progtest.m4: New file, from gettext-0.11.5. + * stdint_h.m4: New file, from gettext-0.11.5. + * uintmax_t.m4: New file, from gettext-0.11.5. + * ulonglong.m4: New file, from gettext-0.11.5. + * Makefile.am: New file. + diff --git a/m4/Makefile.am b/m4/Makefile.am new file mode 100644 index 000000000..42126ac73 --- /dev/null +++ b/m4/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 -- cgit v1.2.3 From a3d4ac6f3e76119a0e24362a3180f1dee6b17381 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 3 Jun 2003 19:55:50 +0000 Subject: Make use of libgpg-error --- README | 3 ++- TODO | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README b/README index b0b23c5f6..7aea069b3 100644 --- a/README +++ b/README @@ -7,7 +7,8 @@ sm/ the gpgsm program agent/ the gpg-agent scd/ the smartcard daemon -Libassuan, Libksba and Libgcrypt are required to build it. +You need the libgpg-error package. Libassuan, Libksba and Libgcrypt +are also required to build it. Keybox is designed to be source include-able. diff --git a/TODO b/TODO index 9b277aa5e..bd23ba6c0 100644 --- a/TODO +++ b/TODO @@ -36,7 +36,7 @@ might want to have an agent context for each service request ** Write a keybox header and check for that magic value. ** Check that all error code mapping is done. ** Remove the inter-module dependencies between gpgsm and keybox - +** Add an source_of_key field * agent/command.c ** Make sure that secure memory is used where appropriate -- cgit v1.2.3 From 7250331472efe70fac928fa06e51c7c80f2b715c Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Thu, 5 Jun 2003 07:14:21 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- agent/query.c | 473 +++ agent/sexp-parse.h | 98 + agent/trustlist.c | 306 ++ g10/ChangeLog | 8238 +++++++++++++++++++++++++++++++++++++++++++++++++++ g10/Makefile.am | 123 + g10/armor.c | 1336 +++++++++ g10/build-packet.c | 1196 ++++++++ g10/cipher.c | 152 + g10/compress.c | 324 ++ g10/decrypt.c | 141 + g10/encode.c | 811 +++++ g10/exec.c | 619 ++++ g10/exec.h | 43 + g10/export.c | 396 +++ g10/filter.h | 154 + g10/free-packet.c | 542 ++++ g10/g10.c | 3137 ++++++++++++++++++++ g10/getkey.c | 2611 ++++++++++++++++ g10/gpgv.c | 396 +++ g10/import.c | 1879 ++++++++++++ g10/kbnode.c | 399 +++ g10/keydb.c | 724 +++++ g10/keydb.h | 278 ++ g10/keyedit.c | 3672 +++++++++++++++++++++++ g10/keygen.c | 2523 ++++++++++++++++ g10/keyid.c | 518 ++++ g10/keylist.c | 1287 ++++++++ g10/keyring.c | 1573 ++++++++++ g10/keyring.h | 46 + g10/keyserver.c | 1378 +++++++++ g10/main.h | 241 ++ g10/mainproc.c | 1681 +++++++++++ g10/misc.c | 678 +++++ g10/openfile.c | 389 +++ g10/options.h | 241 ++ g10/options.skel | 208 ++ g10/packet.h | 510 ++++ g10/parse-packet.c | 2281 ++++++++++++++ g10/passphrase.c | 1238 ++++++++ g10/photoid.c | 333 +++ g10/photoid.h | 34 + g10/pkclist.c | 1376 +++++++++ g10/plaintext.c | 446 +++ g10/progress.c | 117 + g10/revoke.c | 690 +++++ g10/seckey-cert.c | 400 +++ g10/sig-check.c | 625 ++++ g10/sign.c | 1358 +++++++++ g10/signal.c | 217 ++ g10/status.c | 693 +++++ g10/tdbio.c | 1624 ++++++++++ g10/tdbio.h | 117 + g10/textfilter.c | 234 ++ g10/trustdb.c | 2129 +++++++++++++ g10/trustdb.h | 83 + g10/verify.c | 193 ++ include/ChangeLog | 373 +++ include/cipher.h | 205 ++ include/http.h | 82 + include/i18n.h | 54 + include/iobuf.h | 161 + include/memory.h | 93 + include/mpi.h | 196 ++ include/types.h | 141 + include/util.h | 304 ++ kbx/ChangeLog | 119 + kbx/keybox-defs.h | 186 ++ kbx/keybox-dump.c | 346 +++ kbx/keybox-file.c | 102 + kbx/keybox-init.c | 127 + kbx/keybox-search.c | 813 +++++ kbx/keybox-update.c | 437 +++ kbx/keybox.h | 101 + scd/atr.c | 287 ++ scd/atr.h | 28 + scd/card-dinsig.c | 260 ++ sm/base64.c | 624 ++++ 77 files changed, 58548 insertions(+) create mode 100644 agent/query.c create mode 100644 agent/sexp-parse.h create mode 100644 agent/trustlist.c create mode 100644 g10/ChangeLog create mode 100644 g10/Makefile.am create mode 100644 g10/armor.c create mode 100644 g10/build-packet.c create mode 100644 g10/cipher.c create mode 100644 g10/compress.c create mode 100644 g10/decrypt.c create mode 100644 g10/encode.c create mode 100644 g10/exec.c create mode 100644 g10/exec.h create mode 100644 g10/export.c create mode 100644 g10/filter.h create mode 100644 g10/free-packet.c create mode 100644 g10/g10.c create mode 100644 g10/getkey.c create mode 100644 g10/gpgv.c create mode 100644 g10/import.c create mode 100644 g10/kbnode.c create mode 100644 g10/keydb.c create mode 100644 g10/keydb.h create mode 100644 g10/keyedit.c create mode 100644 g10/keygen.c create mode 100644 g10/keyid.c create mode 100644 g10/keylist.c create mode 100644 g10/keyring.c create mode 100644 g10/keyring.h create mode 100644 g10/keyserver.c create mode 100644 g10/main.h create mode 100644 g10/mainproc.c create mode 100644 g10/misc.c create mode 100644 g10/openfile.c create mode 100644 g10/options.h create mode 100644 g10/options.skel create mode 100644 g10/packet.h create mode 100644 g10/parse-packet.c create mode 100644 g10/passphrase.c create mode 100644 g10/photoid.c create mode 100644 g10/photoid.h create mode 100644 g10/pkclist.c create mode 100644 g10/plaintext.c create mode 100644 g10/progress.c create mode 100644 g10/revoke.c create mode 100644 g10/seckey-cert.c create mode 100644 g10/sig-check.c create mode 100644 g10/sign.c create mode 100644 g10/signal.c create mode 100644 g10/status.c create mode 100644 g10/tdbio.c create mode 100644 g10/tdbio.h create mode 100644 g10/textfilter.c create mode 100644 g10/trustdb.c create mode 100644 g10/trustdb.h create mode 100644 g10/verify.c create mode 100644 include/ChangeLog create mode 100644 include/cipher.h create mode 100644 include/http.h create mode 100644 include/i18n.h create mode 100644 include/iobuf.h create mode 100644 include/memory.h create mode 100644 include/mpi.h create mode 100644 include/types.h create mode 100644 include/util.h create mode 100644 kbx/ChangeLog create mode 100644 kbx/keybox-defs.h create mode 100644 kbx/keybox-dump.c create mode 100644 kbx/keybox-file.c create mode 100644 kbx/keybox-init.c create mode 100644 kbx/keybox-search.c create mode 100644 kbx/keybox-update.c create mode 100644 kbx/keybox.h create mode 100644 scd/atr.c create mode 100644 scd/atr.h create mode 100644 scd/card-dinsig.c create mode 100644 sm/base64.c diff --git a/agent/query.c b/agent/query.c new file mode 100644 index 000000000..4a051965d --- /dev/null +++ b/agent/query.c @@ -0,0 +1,473 @@ +/* query.c - fork of the pinentry to query stuff from the user + * 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 <assert.h> +#include <unistd.h> +#include <sys/stat.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif + +#include "agent.h" +#include "i18n.h" +#include <assuan.h> + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + +static ASSUAN_CONTEXT entry_ctx = NULL; +#ifdef USE_GNU_PTH +static pth_mutex_t entry_lock = PTH_MUTEX_INIT; +#endif + +/* data to be passed to our callbacks */ +struct entry_parm_s { + int lines; + size_t size; + char *buffer; +}; + + + + +/* Unlock the pinentry so that another thread can start one and + disconnect that pinentry - we do this after the unlock so that a + stalled pinentry does not block other threads. Fixme: We should + have a timeout in Assuan for the disconnetc operation. */ +static int +unlock_pinentry (int rc) +{ + ASSUAN_CONTEXT ctx = entry_ctx; + +#ifdef USE_GNU_PTH + if (!pth_mutex_release (&entry_lock)) + { + log_error ("failed to release the entry lock\n"); + if (!rc) + rc = gpg_error (GPG_ERR_INTERNAL); + } +#endif + entry_ctx = NULL; + assuan_disconnect (ctx); + return rc; +} + +/* Fork off the pin entry if this has not already been done. Note, + that this function must always be used to aquire the lock for the + pinentry - we will serialize _all_ pinentry calls. + */ +static int +start_pinentry (CTRL ctrl) +{ + int rc; + const char *pgmname; + ASSUAN_CONTEXT ctx; + const char *argv[5]; + int no_close_list[3]; + int i; + +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&entry_lock, 0, NULL)) + { + log_error ("failed to acquire the entry lock\n"); + return gpg_error (GPG_ERR_INTERNAL); + } +#endif + + if (entry_ctx) + return 0; + + if (opt.verbose) + log_info ("starting a new PIN Entry\n"); + + if (fflush (NULL)) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error flushing pending output: %s\n", strerror (errno)); + return unlock_pinentry (tmperr); + } + + if (!opt.pinentry_program || !*opt.pinentry_program) + opt.pinentry_program = GNUPG_DEFAULT_PINENTRY; + if ( !(pgmname = strrchr (opt.pinentry_program, '/'))) + pgmname = opt.pinentry_program; + else + pgmname++; + + argv[0] = pgmname; + if (ctrl->display && !opt.keep_display) + { + argv[1] = "--display"; + argv[2] = ctrl->display; + argv[3] = NULL; + } + else + argv[1] = NULL; + + i=0; + if (!opt.running_detached) + { + 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 pinentry and perform initial handshaking */ + rc = assuan_pipe_connect (&ctx, opt.pinentry_program, (char**)argv, + no_close_list); + if (rc) + { + log_error ("can't connect to the PIN entry module: %s\n", + assuan_strerror (rc)); + return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY)); + } + entry_ctx = ctx; + + if (DBG_ASSUAN) + log_debug ("connection to PIN entry established\n"); + + rc = assuan_transact (entry_ctx, + opt.no_grab? "OPTION no-grab":"OPTION grab", + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + if (ctrl->ttyname) + { + char *optstr; + if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 ) + return unlock_pinentry (out_of_core ()); + rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, + NULL); + free (optstr); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + if (ctrl->ttytype) + { + char *optstr; + if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 ) + return unlock_pinentry (out_of_core ()); + rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, + NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + if (ctrl->lc_ctype) + { + char *optstr; + if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 ) + return unlock_pinentry (out_of_core ()); + rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, + NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + if (ctrl->lc_messages) + { + char *optstr; + if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 ) + return unlock_pinentry (out_of_core ()); + rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, + NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + return 0; +} + + +static AssuanError +getpin_cb (void *opaque, const void *buffer, size_t length) +{ + struct entry_parm_s *parm = opaque; + + if (!buffer) + return 0; + + /* we expect the pin to fit on one line */ + if (parm->lines || length >= parm->size) + return ASSUAN_Too_Much_Data; + + /* fixme: we should make sure that the assuan buffer is allocated in + secure memory or read the response byte by byte */ + memcpy (parm->buffer, buffer, length); + parm->buffer[length] = 0; + parm->lines++; + return 0; +} + + +static int +all_digitsp( const char *s) +{ + for (; *s && *s >= '0' && *s <= '9'; s++) + ; + return !*s; +} + + + +/* Call the Entry and ask for the PIN. We do check for a valid PIN + number here and repeat it as long as we have invalid formed + numbers. */ +int +agent_askpin (CTRL ctrl, + const char *desc_text, struct pin_entry_info_s *pininfo) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + struct entry_parm_s parm; + const char *errtext = NULL; + int is_pin = 0; + + if (opt.batch) + return 0; /* fixme: we should return BAD PIN */ + + if (!pininfo || pininfo->max_length < 1) + return gpg_error (GPG_ERR_INV_VALUE); + if (!desc_text && pininfo->min_digits) + desc_text = _("Please enter your PIN, so that the secret key " + "can be unlocked for this session"); + else if (!desc_text) + desc_text = _("Please enter your passphrase, so that the secret key " + "can be unlocked for this session"); + + is_pin = desc_text && strstr (desc_text, "PIN"); + + rc = start_pinentry (ctrl); + if (rc) + return rc; + + snprintf (line, DIM(line)-1, "SETDESC %s", desc_text); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + rc = assuan_transact (entry_ctx, + is_pin? "SETPROMPT PIN:" + : "SETPROMPT Passphrase:", + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++) + { + memset (&parm, 0, sizeof parm); + parm.size = pininfo->max_length; + parm.buffer = pininfo->pin; + + if (errtext) + { + /* fixme: should we show the try count? It must be translated */ + snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)", + errtext, pininfo->failed_tries+1, pininfo->max_tries); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + errtext = NULL; + } + + rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, + NULL, NULL, NULL, NULL); + if (rc == ASSUAN_Too_Much_Data) + errtext = is_pin? _("PIN too long") + : _("Passphrase too long"); + else if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + if (!errtext && pininfo->min_digits) + { + /* do some basic checks on the entered PIN. */ + if (!all_digitsp (pininfo->pin)) + errtext = _("Invalid characters in PIN"); + else if (pininfo->max_digits + && strlen (pininfo->pin) > pininfo->max_digits) + errtext = _("PIN too long"); + else if (strlen (pininfo->pin) < pininfo->min_digits) + errtext = _("PIN too short"); + } + + if (!errtext && pininfo->check_cb) + { + /* More checks by utilizing the optional callback. */ + pininfo->cb_errtext = NULL; + rc = pininfo->check_cb (pininfo); + if (rc == -1 && pininfo->cb_errtext) + errtext = pininfo->cb_errtext; + else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE + || gpg_err_code (rc) == GPG_ERR_BAD_PIN) + errtext = (is_pin? _("Bad PIN") + : _("Bad Passphrase")); + else if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + + if (!errtext) + return unlock_pinentry (0); /* okay, got a PIN or passphrase */ + } + + return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN + : GPG_ERR_BAD_PASSPHRASE)); +} + + + +/* Ask for the passphrase using the supplied arguments. The + passphrase is returned in RETPASS as an hex encoded string to be + freed by the caller */ +int +agent_get_passphrase (CTRL ctrl, + char **retpass, const char *desc, const char *prompt, + const char *errtext) +{ + + int rc; + char line[ASSUAN_LINELENGTH]; + struct entry_parm_s parm; + unsigned char *p, *hexstring; + int i; + + *retpass = NULL; + if (opt.batch) + return gpg_error (GPG_ERR_BAD_PASSPHRASE); + + rc = start_pinentry (ctrl); + if (rc) + return rc; + + if (!prompt) + prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase"); + + + if (desc) + snprintf (line, DIM(line)-1, "SETDESC %s", desc); + else + snprintf (line, DIM(line)-1, "RESET"); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + if (errtext) + { + snprintf (line, DIM(line)-1, "SETERROR %s", errtext); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + + memset (&parm, 0, sizeof parm); + parm.size = ASSUAN_LINELENGTH/2 - 5; + parm.buffer = gcry_malloc_secure (parm.size+10); + if (!parm.buffer) + return unlock_pinentry (out_of_core ()); + + assuan_begin_confidential (entry_ctx); + rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL); + if (rc) + { + xfree (parm.buffer); + return unlock_pinentry (map_assuan_err (rc)); + } + + hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1); + if (!hexstring) + { + gpg_error_t tmperr = out_of_core (); + xfree (parm.buffer); + return unlock_pinentry (tmperr); + } + + for (i=0, p=parm.buffer; *p; p++, i += 2) + sprintf (hexstring+i, "%02X", *p); + + xfree (parm.buffer); + *retpass = hexstring; + return unlock_pinentry (0); +} + + + +/* Pop up the PIN-entry, display the text and the prompt and ask the + user to confirm this. We return 0 for success, ie. the used + confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an + other error. */ +int +agent_get_confirmation (CTRL ctrl, + const char *desc, const char *ok, const char *cancel) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + + rc = start_pinentry (ctrl); + if (rc) + return rc; + + if (desc) + snprintf (line, DIM(line)-1, "SETDESC %s", desc); + else + snprintf (line, DIM(line)-1, "RESET"); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + if (ok) + { + snprintf (line, DIM(line)-1, "SETOK %s", ok); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + if (cancel) + { + snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + + rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL); + return unlock_pinentry (map_assuan_err (rc)); +} + + + diff --git a/agent/sexp-parse.h b/agent/sexp-parse.h new file mode 100644 index 000000000..338321f48 --- /dev/null +++ b/agent/sexp-parse.h @@ -0,0 +1,98 @@ +/* sexp-parse.h - S-Exp helper functions + * 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 SEXP_PARSE_H +#define SEXP_PARSE_H + +#include "../common/util.h" + +/* Return the length of the next S-Exp part and update the pointer to + the first data byte. 0 is return on error */ +static inline size_t +snext (unsigned char const **buf) +{ + const unsigned char *s; + int n; + + s = *buf; + for (n=0; *s && *s != ':' && digitp (s); s++) + n = n*10 + atoi_1 (s); + 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 int +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. */ +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*/ diff --git a/agent/trustlist.c b/agent/trustlist.c new file mode 100644 index 000000000..8575aedb0 --- /dev/null +++ b/agent/trustlist.c @@ -0,0 +1,306 @@ +/* trustlist.c - Maintain the list of trusted keys + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" +#include <assuan.h> /* fixme: need a way to avoid assuan calls here */ + +static const char headerblurb[] = +"# This is the list of trusted keys. Comments like this one and empty\n" +"# lines are allowed but keep in mind that the entire file is integrity\n" +"# protected by the use of a MAC, so changing the file does not make\n" +"# much sense without the knowledge of the MAC key. Lines do have a\n" +"# length limit but this is not serious limitation as the format of the\n" +"# entries is fixed and checked by gpg-agent: A non-comment line starts\n" +"# with optional white spaces, followed by exactly 40 hex character,\n" +"# optioanlly followed by a flag character which my either be 'P', 'S'\n" +"# or '*'. Additional data delimited with by a white space is ignored.\n" +"\n"; + + +static FILE *trustfp; + + +static int +open_list (int append) +{ + char *fname; + + fname = make_filename (opt.homedir, "trustlist.txt", NULL); + trustfp = fopen (fname, append? "a+":"r"); + if (!trustfp && errno == ENOENT) + { + trustfp = fopen (fname, "wx"); + if (!trustfp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("can't create `%s': %s\n", fname, strerror (errno)); + xfree (fname); + return tmperr; + } + fputs (headerblurb, trustfp); + fclose (trustfp); + trustfp = fopen (fname, append? "a+":"r"); + } + + if (!trustfp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("can't open `%s': %s\n", fname, strerror (errno)); + xfree (fname); + return tmperr; + } + + /*FIXME: check the MAC */ + + return 0; +} + + + +/* Read the trustlist and return entry by entry. KEY must point to a + buffer of at least 41 characters. KEYFLAG does return either 'P', + 'S' or '*'. + + Reading a valid entry return 0, EOF returns -1 any other error + returns the appropriate error code. */ +static int +read_list (char *key, int *keyflag) +{ + int rc; + int c, i; + char *p, line[256]; + + if (!trustfp) + { + rc = open_list (0); + if (rc) + return rc; + } + + do + { + if (!fgets (line, DIM(line)-1, trustfp) ) + { + if (feof (trustfp)) + return -1; + return gpg_error (gpg_err_code_from_errno (errno)); + } + + if (!*line || line[strlen(line)-1] != '\n') + { + /* eat until end of line */ + while ( (c=getc (trustfp)) != EOF && c != '\n') + ; + return gpg_error (*line? GPG_ERR_LINE_TOO_LONG + : GPG_ERR_INCOMPLETE_LINE); + } + + /* Allow for emty lines and spaces */ + for (p=line; spacep (p); p++) + ; + } + while (!*p || *p == '\n' || *p == '#'); + + for (i=0; hexdigitp (p+i) && i < 40; i++) + key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i]; + key[i] = 0; + if (i!=40 || !(spacep (p+i) || p[i] == '\n')) + { + log_error ("invalid formatted fingerprint in trustlist\n"); + return gpg_error (GPG_ERR_BAD_DATA); + } + assert (p[i]); + if (p[i] == '\n') + *keyflag = '*'; + else + { + i++; + if ( p[i] == 'P' || p[i] == 'p') + *keyflag = 'P'; + else if ( p[i] == 'S' || p[i] == 's') + *keyflag = 'S'; + else if ( p[i] == '*') + *keyflag = '*'; + else + { + log_error ("invalid keyflag in trustlist\n"); + return gpg_error (GPG_ERR_BAD_DATA); + } + i++; + if ( !(spacep (p+i) || p[i] == '\n')) + { + log_error ("invalid keyflag in trustlist\n"); + return gpg_error (GPG_ERR_BAD_DATA); + } + } + + return 0; +} + +/* check whether the given fpr is in our trustdb. We expect FPR to be + an all uppercase hexstring of 40 characters. */ +int +agent_istrusted (const char *fpr) +{ + int rc; + static char key[41]; + int keyflag; + + if (trustfp) + rewind (trustfp); + while (!(rc=read_list (key, &keyflag))) + { + if (!strcmp (key, fpr)) + return 0; + } + if (rc != -1) + { + /* error in the trustdb - close it to give the user a chance for + correction */ + fclose (trustfp); + trustfp = NULL; + } + return rc; +} + + +/* write all trust entries to FP */ +int +agent_listtrusted (void *assuan_context) +{ + int rc; + static char key[51]; + int keyflag; + + if (trustfp) + rewind (trustfp); + while (!(rc=read_list (key, &keyflag))) + { + key[40] = ' '; + key[41] = keyflag; + key[42] = '\n'; + assuan_send_data (assuan_context, key, 43); + assuan_send_data (assuan_context, NULL, 0); /* flush */ + } + if (rc == -1) + rc = 0; + if (rc) + { + /* error in the trustdb - close it to give the user a chance for + correction */ + fclose (trustfp); + trustfp = NULL; + } + return rc; +} + + +/* Insert the given fpr into our trustdb. We expect FPR to be an all + uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'. + This function does first check whether that key has alreay ben put + into the trustdb and returns success in this case. Before a FPR + actually gets inserted, the user is asked by means of the pin-entry + whether this is actual wants he want to do. +*/ +int +agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) +{ + int rc; + static char key[41]; + int keyflag; + char *desc; + + if (trustfp) + rewind (trustfp); + while (!(rc=read_list (key, &keyflag))) + { + if (!strcmp (key, fpr)) + return 0; + } + fclose (trustfp); + trustfp = NULL; + if (rc != -1) + return rc; /* error in the trustdb */ + + /* insert a new one */ + if (asprintf (&desc, + "Please verify that the certificate identified as:%%0A" + " \"%s\"%%0A" + "has the fingerprint:%%0A" + " %s", name, fpr) < 0 ) + return out_of_core (); + rc = agent_get_confirmation (ctrl, desc, "Correct", "No"); + free (desc); + if (rc) + return rc; + + if (asprintf (&desc, + "Do you ultimately trust%%0A" + " \"%s\"%%0A" + "to correctly certify user certificates?", + name) < 0 ) + return out_of_core (); + rc = agent_get_confirmation (ctrl, desc, "Yes", "No"); + free (desc); + if (rc) + return rc; + + /* now check again to avoid duplicates. Also open in append mode now */ + rc = open_list (1); + if (rc) + return rc; + rewind (trustfp); + while (!(rc=read_list (key, &keyflag))) + { + if (!strcmp (key, fpr)) + return 0; + } + if (rc != -1) + { + fclose (trustfp); + trustfp = NULL; + return rc; /* error in the trustdb */ + } + rc = 0; + + /* append the key */ + fflush (trustfp); + fputs ("\n# ", trustfp); + print_sanitized_string (trustfp, name, 0); + fprintf (trustfp, "\n%s %c\n", fpr, flag); + if (ferror (trustfp)) + rc = gpg_error (gpg_err_code_from_errno (errno)); + + /* close because we are in append mode */ + if (fclose (trustfp)) + rc = gpg_error (gpg_err_code_from_errno (errno)); + trustfp = NULL; + return rc; +} diff --git a/g10/ChangeLog b/g10/ChangeLog new file mode 100644 index 000000000..3db1b0ef1 --- /dev/null +++ b/g10/ChangeLog @@ -0,0 +1,8238 @@ +2003-06-03 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), keylist.c (list_keyblock_print): Add + "show-validity" and "show-long-keyid" list-options. + + * gpgv.c (get_validity, trust_value_to_string): Stubs. + + * g10.c (main): Use SAFE_VERSION instead of VERSION in the + version-specific gpg.conf file so it can be overridden on RISCOS. + +2003-06-01 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main), keylist.c (show_policy_url, show_notation), + mainproc.c (check_sig_and_print): Emulate the old policy and + notation behavior (display by default). Send to status-fd whether + it is displayed on the screen or not. + + * g10.c (main): Since we now have some options in devel that won't + work in a stable branch gpg.conf file, try for a version-specific + gpg.conf-VERSION file before falling back to gpg.conf. + + * main.h, options.h: Move various option flags to options.h. + +2003-05-31 David Shaw <dshaw@jabberwocky.com> + + * mainproc.c (check_sig_and_print), main.h, keylist.c + (show_policy, show_notation): Collapse the old print_notation_data + into show_policy() and show_notation() so there is only one + function to print notations and policy URLs. + + * options.h, main.h, g10.c (main), keyedit.c + (print_and_check_one_sig), keylist.c (list_one, + list_keyblock_print), pkclist.c (do_edit_ownertrust), sign.c + (mk_notation_and_policy): New "list-options" and "verify-options" + commands. These replace the existing + --show-photos/--no-show-photos, + --show-notation/--no-show-notation, + --show-policy-url/--no-show-policy-url, and --show-keyring + options. The new method is more flexible since a user can specify + (for example) showing photos during sig verification, but not in + key listings. The old options are emulated. + + * main.h, misc.c (parse_options): New general option line + parser. Fix the bug in the old version that did not handle report + syntax errors after a valid entry. + + * import.c (parse_import_options), export.c + (parse_export_options): Call it here instead of duplicating the + code. + +2003-05-30 David Shaw <dshaw@jabberwocky.com> + + * keylist.c (list_one): Don't show the keyring filename when in + --with-colons mode. Actually translate "Keyring" string. + + * mainproc.c (proc_tree): We can't currently handle multiple + signatures of different classes or digests (we'd pretty much have + to run a different hash context for each), but if they are all the + same, make an exception. This is Debian bug #194292. + + * sig-check.c (check_key_signature2): Make string translatable. + + * packet.h, getkey.c (fixup_uidnode): Mark real primary uids + differently than assumed primaries. + + * keyedit.c (no_primary_warning): Use the differently marked + primaries here in a new function to warn when an --edit-key + command might rearrange the self-sig dates enough to change which + uid is primary. + (menu_expire, menu_set_preferences): Use no_primary_warning() + here. + + * Makefile.am: Use @DLLIBS@ for -ldl. + +2003-05-26 David Shaw <dshaw@jabberwocky.com> + + * getkey.c (premerge_public_with_secret): Made "no secret subkey + for" warning a verbose item and translatable. (From wk on stable + branch) + + * sig-check.c (check_key_signature2): Made "no subkey for subkey + binding packet" a verbose item instead of a !quiet one. There are + too many garbled keys out in the wild. (From wk on stable branch) + + * filter.h: Remove const from WHAT. (From wk on stable branch) + + * progress.c (handle_progress): Store a copy of + NAME. (progress_filter): Release WHAT, make sure not to print a + NULL WHAT. (From wk on stable branch) + + * openfile.c (open_sigfile): Adjust free for new progress + semantics. (From wk on stable branch) + + * plaintext.c (ask_for_detached_datafile): Don't dealloc + pfx->WHAT. (From wk on stable branch) + + * seckey-cert.c (do_check): Issue the RSA_OR_IDEA status when the + cipher algo is IDEA to make it easier to track down the + problem. (From twoaday on stable branch) + +2003-05-24 David Shaw <dshaw@jabberwocky.com> + + * armor.c, g10.c, kbnode.c, misc.c, pkclist.c, sign.c, + build-packet.c, getkey.c, keydb.c, openfile.c, plaintext.c, + status.c, gpgv.c, keygen.c, options.h, sig-check.c, tdbio.h, + encode.c, mainproc.c, parse-packet.c, signal.c, textfilter.c: Edit + all preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. + +2003-05-21 David Shaw <dshaw@jabberwocky.com> + + * trustdb.h, trustdb.c (is_disabled), gpgv.c (is_disabled): Rename + is_disabled to cache_disabled_value, which now takes a pk and not + just the keyid. This is for speed since there is no need to + re-fetch a key when we already have that key handy. Cache the + result of the check so we don't need to hit the trustdb more than + once. + + * getkey.c (skip_disabled): New function to get a pk and call + is_disabled on it. (key_byname): Use it here. + + * packet.h, getkey.c (skip_disabled), keylist.c + (print_capabilities): New "pk_is_disabled" macro to retrieve the + cached disabled value if available, and fill it in via + cache_disabled_value if not available. + + * trustdb.c (get_validity): Cache the disabled value since we have + it handy and it might be useful later. + + * parse-packet.c (parse_key): Clear disabled flag when parsing a + new key. Just in case someone forgets to clear the whole key. + + * getkey.c (merge_selfsigs_main): Add an "if all else fails" path + for setting a single user ID primary when there are multiple set + primaries all at the same second, or no primaries set and the most + recent user IDs are at the same second, or no signed user IDs at + all. This is arbitrary, but deterministic. + + * exec.h, photoid.h: Add copyright message. + + * keylist.c (list_keyblock_print): Don't dump attribs for + revoked/expired/etc uids for non-colon key listings. This is for + consistency with --show-photos. + + * main.h, keylist.c (dump_attribs), mainproc.c + (check_sig_and_print): Dump attribs if --attrib-fd is set when + verifying signatures. + + * g10.c (main): New --gnupg option to disable the various + --openpgp, --pgpX, etc. options. This is the same as --no-XXXX + for those options. + + * revoke.c (ask_revocation_reason): Clear old reason if user + elects to repeat question. This is bug 153. + + * keyedit.c (sign_uids): Show keyid of the key making the + signature. + +2003-05-21 Werner Koch <wk@gnupg.org> + + * progress.c (handle_progress) + * sign.c (write_plaintext_packet) + * encode.c (encode_simple,encode_crypt): Make sure that a filename + of "-" is considered to be stdin so that iobuf_get_filelength + won't get called. This fixes bug 156 reported by Gregery Barton. + +2003-05-02 David Shaw <dshaw@jabberwocky.com> + + * packet.h, build-packet.c (build_sig_subpkt), export.c + (do_export_stream), import.c (remove_bad_stuff, import), + parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt): Remove + vestigal code for the old sig cache subpacket. This wasn't + completely harmless as it caused subpacket 101 to disappear on + import and export. + + * options.h, armor.c, cipher.c, g10.c, keyedit.c, pkclist.c, + sign.c, encode.c, getkey.c, revoke.c: The current flags for + different levels of PGP-ness are massively complex. This is step + one in simplifying them. No functional change yet, just use a + macro to check for compliance level. + + * sign.c (sign_file): Fix bug that causes spurious compression + preference warning. + + * sign.c (clearsign_file): Fix bug that prevents proper warning + message from appearing when clearsigning in --pgp2 mode with a + non-v3 RSA key. + + * main.h, misc.c (compliance_option_string, compliance_string, + compliance_failure), pkclist.c (build_pk_list), sign.c (sign_file, + clearsign_file), encode.c (encode_crypt, + write_pubkey_enc_from_list): New functions to put the "this + message may not be usable...." warning in one place. + + * options.h, g10.c (main): Part two of the simplification. Use a + single enum to indicate what we are compliant to (1991, 2440, + PGPx, etc.) + + * g10.c (main): Show errors for failure in export, send-keys, + recv-keys, and refresh-keys. + + * options.h, g10.c (main): Give algorithm warnings for algorithms + chosen against the --pgpX and --openpgp rules. + + * keydb.h, pkclist.c (algo_available): Make TIGER192 invalid in + --openpgp mode. + + * sign.c (sign_file), pkclist.c (algo_available): Allow passing a + hint of 0. + +2003-05-01 David Shaw <dshaw@jabberwocky.com> + + * tdbio.c (create_version_record): Only create new trustdbs with + TM_CLASSIC or TM_PGP. + + * trustdb.h, trustdb.c (trust_string, get_ownertrust_string, + get_validity_string, ask_ownertrust, validate_keys), pkclist.c + (do_edit_ownertrust): Rename trust_string to trust_value_to_string + for naming consistency. + + * trustdb.h, trustdb.c (string_to_trust_value): New function to + translate a string to a trust value. + + * g10.c (main): Use string_to_trust_value here for + --force-ownertrust. + + * options.h, g10.c (main), trustdb.c (trust_model_string, + init_trustdb, check_trustdb, update_trustdb, get_validity, + validate_one_keyblock): An "OpenPGP" trust model is misleading + since there is no official OpenPGP trust model. Use "PGP" + instead. + +2003-04-30 David Shaw <dshaw@jabberwocky.com> + + * build-packet.c (build_sig_subpkt): Comments. + + * exec.c (exec_write): Cast NULL to void* to properly terminate + varargs list. + + * keyedit.c (show_key_with_all_names): Just for safety, catch an + invalid pk algorithm. + + * sign.c (make_keysig_packet): Crucial that the call to mksubpkt + comes LAST before the calls to finalize the sig as that makes it + possible for the mksubpkt function to get a reliable pointer to + the subpacket area. + + * pkclist.c (do_we_trust_pre): If an untrusted key was chosen by a + particular user ID, use that ID as the one to ask about when + prompting whether to use the key anyway. + (build_pk_list): Similar change here when adding keys to the + recipient list. + + * trustdb.c (update_validity): Fix bug that prevented more than + one validity record per trust record. + (get_validity): When retrieving validity for a (user) supplied + user ID, return the validity for that user ID only, and do not + fall back to the general key validity. + (validate_one_keyblock): Some commentary on whether + non-self-signed user IDs belong in the web of trust (arguably, + they do). + +2003-04-27 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Add --no-textmode. + + * export.c (do_export_stream), keyedit.c (show_key_with_all_names, + menu_addrevoker), mainproc.c (check_sig_and_print), photoid.c + (show_photos), sign.c (mk_notation_and_policy), trustdb.c + (get_validity, reset_trust_records, validate_keys): Make some + strings translatable. + + * mainproc.c (check_sig_and_print): Show digest algorithm and sig + class when verifying a sig with --verbose on, and add version, pk + and hash algorithms and sig class to VALIDSIG. + + * parse-packet.c (enum_sig_subpkt): Make a warning message a + --verbose warning message since we don't need to warn every time + we see an unknown critical (we only need to invalidate the + signature). + + * trustdb.c (init_trustdb): Check the trustdb options even with + TM_AUTO since the auto may become TM_CLASSIC or TM_OPENPGP. + +2003-04-26 David Shaw <dshaw@jabberwocky.com> + + * sign.c (do_sign): Show the hash used when making a signature in + verbose mode. + + * tdbio.h, tdbio.c (tdbio_read_model): New function to return the + trust model used in a given trustdb. + + * options.h, g10.c (main), trustdb.c (init_trustdb, check_trustdb, + update_trustdb): Use tdbio_read_model to implement an "auto" trust + model which is set via the trustdb. + +2003-04-23 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_revoke_cert): Remove ultimate trust when + revoking an ultimately trusted key. + + * keyedit.c (sign_uids): Allow replacing expired signatures. + Allow duplicate signatures with --expert. + + * pkclist.c (check_signatures_trust): Don't display a null + fingerprint when checking a signature with --always-trust enabled. + + * filter.h (progress_filter_context_t), progress.c + (handle_progress), plaintext.c (ask_for_detached_datafile, + hash_datafiles): Fix compiler warnings. Make "what" constant. + + * build-packet.c (do_plaintext): Do not create invalid literal + packets with >255-byte names. + +2003-04-15 Werner Koch <wk@gnupg.org> + + * Makefile.am (AM_CFLAGS): Make use of AM_CFLAGS and AM_LDFLAGS. + + * g10.c, options.h: New option --enable-progress-filter. + * progress.c (handle_progress): Make use of it. + +2003-04-15 Marcus Brinkmann <marcus@g10code.de> + + * progress.c: New file. + * Makefile.am (common_source): Add progress.c. + * filter.h (progress_filter_context_t): New type. + (progress_filter, handle_progress): New prototypes. + * main.h (open_sigfile): New argument for prototype. + * openfile.c (open_sigfile): New argument to install progress + filter. + * encode.c (encode_simple): New variable PFX. Register + progress filter. Install text_filter after that. + (encode_crypt): Likewise. + * sign.c (sign_file): Likewise. + (clearsign_file): Likewise. + * decrypt.c (decrypt_message): Likewise. + (decrypt_messages): Likewise. + * verify.c (verify_signatures): Likewise. + (verify_one_file): Likewise. + * plaintext.c (hash_datafiles): Likewise. + (ask_for_detached_datafile): Likewise. + +2003-04-10 Werner Koch <wk@gnupg.org> + + * passphrase.c (read_passphrase_from_fd): Do a dummy read if the + agent is to be used. Noted by Ingo Klcker. + (agent_get_passphrase): Inhibit caching when we have no + fingerprint. This is required for key generation as well as for + symmetric only encryption. + + * passphrase .c (agent_get_passphrase): New arg CANCELED. + (passphrase_to_dek): Ditto. Passed to above. Changed all + callers to pass NULL. + * seckey-cert.c (do_check): New arg CANCELED. + (check_secret_key): Terminate loop when canceled. + + * keyedit.c (change_passphrase): Pass ERRTEXT untranslated to + passphrase_to_dek and translate where appropriate. + * seckey-cert.c (check_secret_key): Ditto. + * keygen.c (ask_passphrase): Ditto. + * passphrase.c (agent_get_passphrase): Translate the TRYAGAIN_TEXT. + Switch the codeset to utf-8. + +2003-04-09 Werner Koch <wk@gnupg.org> + + * decrypt.c (decrypt_messages): Fixed error handling; the function + used to re-loop with same file after an error. Reported by Joseph + Walton. + +2003-04-08 David Shaw <dshaw@jabberwocky.com> + + * main.h, g10.c (main), import.c (parse_import_options, + fix_pks_corruption): It's really PKS corruption, not HKP + corruption. Keep the old repair-hkp-subkey-bug command as an + alias. + + * g10.c (main): Rename --no-version to --no-emit-version for + consistency. Keep --no-version as an alias. + +2003-04-04 David Shaw <dshaw@jabberwocky.com> + + * pkclist.c (algo_available): PGP 8 can use the SHA-256 hash. + + * sign.c (sign_file, clearsign_file, sign_symencrypt_file): Remove + unused code. + +2003-04-01 Werner Koch <wk@gnupg.org> + + * mainproc.c (check_sig_and_print): Add primary key fpr to VALIDSIG + status. + +2003-03-24 David Shaw <dshaw@jabberwocky.com> + + * keydb.h: Err on the side of making an unknown signature a SIG + rather than a CERT. + + * import.c (delete_inv_parts): Discard any key signatures that + aren't key types (i.e. 0x00, 0x01, etc.) + + * g10.c (main): Add deprecated option warning for + --list-ownertrust. Add --compression-algo alias for + --compress-algo. Change --version output strings to match + "showpref" strings, and make translatable. + + * status.c (do_get_from_fd): Accept 'y' as well as 'Y' for + --command-fd boolean input. + + * trustdb.c: Fix typo (DISABLE_REGEXP -> DISABLE_REGEX) + + * keyedit.c (show_key_with_all_names_colon): Show no-ks-modify + flag. + +2003-03-11 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), keyserver.c (kopts): Add "try-dns-srv" + keyserver option. Defaults to on. + + * passphrase.c (agent_get_passphrase): Fix memory leak with + symmetric messages. Fix segfault with symmetric messages. Fix + incorrect prompt with symmetric messages. + +2003-03-10 Werner Koch <wk@gnupg.org> + + * compress.c (init_uncompress): Use a 15 bit window size so that + the output of implementations which don't run for PGP 2 + compatibility won't get garbled. + +2003-03-04 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (validate_keys): Mask the ownertrust when building the + list of fully valid keys so that disabled keys are still counted + in the web of trust. + (get_ownertrust_with_min): Do the same for the minimum ownertrust + calculation. + + * parse-packet.c (dump_sig_subpkt): Show the notation names for + not-human-readable notations. Fix cosmetic off-by-one length + counter. + + * options.skel: Add explantion and commented-out + "no-mangle-dos-filenames". + + * mainproc.c (proc_encrypted): Make string translatable. + + * keyserver.c (keyserver_spawn): Quote ':', '%', and any 8-bit + characters in the uid strings sent to the keyserver helper. + + * keyring.c (keyring_rebuild_cache): Lock the keyring while + rebuilding the signature caches to prevent another gpg from + tampering with the temporary copy. + + * keygen.c (keygen_set_std_prefs): Include AES192 and AES256 in + default prefs. + + * keyedit.c (show_prefs): Make strings translatable. + + * keydb.c: Double the maximum number of keyrings to 40. + + * gpgv.c (main): Fix bug #113 - gpgv should accept the + --ignore-time-conflict option. + + * g10.c (main): --openpgp disables --pgpX. Double the amount of + secure memory to 32k (keys are getting bigger these days). + + * Makefile.am: Makefile.am: Use @CAPLIBS@ to link in -lcap if we + are using capabilities. + +2003-02-26 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_spawn): Include various pieces of + information about the key in the data sent to the keyserver + helper. This allows the helper to use it in instructing a remote + server which may not have any actual OpenPGP smarts in parsing + keys. + + * main.h, export.c (export_pubkeys_stream, do_export_stream): Add + ability to return only the first match in an exported keyblock for + keyserver usage. This should be replaced at some point with a + more flexible solution where each key can be armored seperately. + +2003-02-22 David Shaw <dshaw@jabberwocky.com> + + * sign.c (sign_file): Do not push textmode filter onto an unopened + IOBUF (segfault). Noted by Marcus Brinkmann. Push and + reinitialize textmode filter for each file in a multiple file + list. + + * packet.h, getkey.c (fixup_uidnode), keyedit.c (show_prefs): Set + and show the keyserver no-modify flag. + + * keygen.c (add_keyserver_modify): New. + (keygen_upd_std_prefs): Call it here. + (keygen_set_std_prefs): Accept "ks-modify" and "no-ks-modify" as + prefs to set and unset keyserver modify flag. + + * g10.c (main): Accept "s1" in addition to "idea" to match the + other ciphers. + + * main.h, misc.c (idea_cipher_warn): We don't need this if IDEA + has been disabled. + +2003-02-21 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (keygen_set_std_prefs): Don't put AES or CAST5 in + default prefs if they are disabled. + + * g10.c (main): Use 3DES instead of CAST5 if we don't have CAST5 + support. Use 3DES for the s2k cipher in --openpgp mode. + (print_mds): #ifdef all of the optional digest algorithms. + +2003-02-12 David Shaw <dshaw@jabberwocky.com> + + * keydb.h, getkey.c (classify_user_id, classify_user_id2): Make + 'exact' a per-desc item. Merge into one function since + 'force_exact' is no longer needed. + (key_byname): Use new classify_user_id function, and new exact + flag in KEYDB_SEARCH_DESC. + + * keyring.h, keyring.c (keyring_search): Return an optional index + to show which KEYDB_SEARCH_DESC was the matching one. + + * keydb.h, keydb.c (keydb_search): Rename to keydb_search2, and + pass the optional index to keyring_search. Add a macro version of + keydb_search that calls this new function. + + * export.c (do_export_stream): If the keyid! syntax is used, + export only that specified key. If the key in question is a + subkey, export the primary plus that subkey only. + +2003-02-11 David Shaw <dshaw@jabberwocky.com> + + * exec.c (set_exec_path): Add debugging line. + + * g10.c (print_hex, print_mds): Print long hash strings a lot + neater. This assumes at least an 80-character display, as there + are a few other similar assumptions here and there. Users who + need unformatted hashes can still use with-colons. Check that + SHA384 and 512 are available before using them as they are no + longer always available. + + * Makefile.am: Use a local copy of libexecdir along with @PACKAGE@ + as GNUPG_LIBEXECDIR so it can be easily overridden at make time. + +2003-02-04 David Shaw <dshaw@jabberwocky.com> + + * armor.c (parse_hash_header, armor_filter): Accept the new SHAs + in the armor Hash: header. + + * g10.c (print_hex): Print long hash strings a little neater. + (print_mds): Add the new SHAs to the hash list. + +2003-02-02 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_revuid): Properly handle a nonselfsigned uid on + a v4 key (treat as a v4 revocation). + + * import.c (print_import_check): Do not re-utf8 convert user IDs. + +2003-01-27 David Shaw <dshaw@jabberwocky.com> + + * mainproc.c (list_node): Show signature expiration date in + with-colons sig records. + + * keylist.c (list_keyblock_colon), mainproc.c (list_node): Show + trust sig information in with-colons sig records. + +2003-01-16 David Shaw <dshaw@jabberwocky.com> + + * g10.c (add_group): Trim whitespace after a group name so it does + not matter where the user puts the = sign. + + * options.skel: Comment out the first three lines in case someone + manually copies the skel file to their homedir. + + * sign.c (clearsign_file): Only use pgp2mode with v3 keys and + MD5. This matches what we do when decoding such messages and + prevents creating a message (v3+RIPEMD/160) that we can't verify. + + * sig-check.c (signature_check2): Use G10ERR_GENERAL as the error + for signature digest conflict. BAD_SIGN implies that a signature + was checked and we may try and print out a user ID for a key that + doesn't exist. + +2003-01-15 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (init_trustdb, get_validity): Don't use a changed + trust model to indicate a dirty trustdb, and never auto-rebuild a + dirty trustdb with the "always" trust model. + + * g10.c (add_group): Last commit missed the \t ;) + +2003-01-14 David Shaw <dshaw@jabberwocky.com> + + * packet.h, parse-packet.c (setup_user_id), free-packet.c + (free_user_id), keydb.h, keyid.c (namehash_from_uid): New function + to rmd160-hash the contents of a user ID packet and cache it in + the uid object. + + * keylist.c (list_keyblock_colon): Use namehash in field 8 of + uids. Show dates for creation (selfsig date), and expiration in + fields 6 and 7. + + * trustdb.c (get_validity, get_validity_counts, update_validity): + Use new namehash function rather than hashing it locally. + +2003-01-14 Werner Koch <wk@gnupg.org> + + * g10.c (add_group): Fixed group parsing to allow more than one + delimiter in a row and also allow tab as delimiter. + +2003-01-12 David Shaw <dshaw@jabberwocky.com> + + * tdbio.c (tdbio_set_dbname): Fix assertion failure with + non-fully-qualified trustdb names. + +2003-01-11 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (get_validity_info, get_ownertrust_info, + trust_letter): Simplify by returning a ? for error directly. + + * keyedit.c (show_key_with_all_names): Use get_validity_string and + get_ownertrust_string to show full word versions of trust + (i.e. "full" instead of 'f'). + + * trustdb.h, trustdb.c (get_ownertrust_string, + get_validity_string): Same as get_ownertrust_info, and + get_validity_info, except returns a full string. + + * trustdb.c (get_ownertrust_with_min): New. Same as + 'get_ownertrust' but takes the min_ownertrust value into account. + +2003-01-10 David Shaw <dshaw@jabberwocky.com> + + * armor.c (armor_filter): Comment about PGP's end of line tab + problem. + + * trustdb.h, trustdb.c (trust_letter): Make + static. (get_ownertrust_info, get_validity_info): Don't mask the + trust level twice. + + * trustdb.h, gpgv.c, trustdb.c (get_validity, get_validity_info), + keylist.c (list_keyblock_colon), keyedit.c + (show_key_with_all_names_colon, menu_revuid): Pass a user ID in + rather than a namehash, so we only have to do the hashing in one + place. + + * packet.h, pkclist.c (build_pk_list), free-packet.c + (release_public_key_parts): Remove unused namehash element for + public keys. + +2003-01-07 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (keygen_set_std_prefs): Warn when setting an IDEA + preference when IDEA is not available. + +2003-01-06 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (get_validity_info): 'd' for disabled is not a + validity value any more. + + * packet.h, tdbio.h, tdbio.c (tdbio_read_record, + tdbio_write_record), trustdb.c (update_validity): Store temporary + full & marginal counts in the trustdb. + (clear_validity, get_validity_counts): Return and clear temp + counts. + (store_validation_status): Keep track of which keyids have been + stored. + (validate_one_keyblock, validate_key_list): Use per-uid copies of + the full & marginal counts so they can be recalled for multiple + levels. + (validate_keys): Only use unused keys for each new round. + (reset_unconnected_keys): Rename to reset_trust_records, and only + skip specifically excluded records. + + * keylist.c (print_capabilities): Show 'D' for disabled keys in + capabilities section. + + * trustdb.c (is_disabled): Remove incorrect comment. + +2003-01-03 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_one): Only do the work to create the status + display for interactive import if status is enabled. + + * keyring.c (keyring_search): skipfnc didn't work properly with + non-keyid searches. Noted by Stefan Bellon. + + * getkey.c (merge_selfsigs_main): Remove some unused code and make + sure that the pk selfsigversion member accounts for 1F direct + sigs. + +2003-01-02 Werner Koch <wk@gnupg.org> + + * keydb.c (keydb_add_resource): Don't assume that try_make_homedir + terminates but check again for the existence of the directory and + continue then. + * openfile.c (copy_options_file): Print a warning if the skeleton + file has active options. + +2002-12-29 David Shaw <dshaw@jabberwocky.com> + + * getkey.c (merge_selfsigs_main), main.h, sig-check.c + (check_key_signature2): Pass the ultimately trusted pk directly to + check_key_signature2 to avoid going through the key selection + mechanism. This prevents a deadly embrace when two keys without + selfsigs each sign the other. + +2002-12-27 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_refresh): Don't print the "refreshing..." + line if there are no keys to refresh or if there is no keyserver + set. + + * getkey.c (merge_selfsigs_main): Any valid user ID should make a + key valid, not just the last one. This also fixes Debian bug + #174276. + +2002-12-27 Stefan Bellon <sbellon@sbellon.de> + + * import.c (print_import_check): Changed int to size_t. + +2002-12-27 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (keyedit_menu, menu_revuid): Add "revuid" feature to + revoke a user ID. This is the same as issuing a revocation for + the self-signature, but a much simpler interface to do it. + +2002-12-26 David Shaw <dshaw@jabberwocky.com> + + * keydb.h, getkey.c (key_byname): Flag to enable or disable + including disabled keys. Keys specified via keyid (i.e. 0x...) + are always included. + + * getkey.c (get_pubkey_byname, get_seckey_byname2, + get_seckey_bynames), keyedit.c (keyedit_menu, menu_addrevoker): + Include disabled keys in these functions. + + * pkclist.c (build_pk_list): Do not include disabled keys for -r + or the key prompt. Do include disabled keys for the default key + and --encrypt-to. + + * trustdb.h, trustdb.c (is_disabled): New skipfnc for skipping + disabled keys. + + * gpgv.c (is_disabled): Stub. + + * keygen.c (keygen_add_key_expire): Properly handle updating a key + expiration to a no-expiration value. + + * keyedit.c (enable_disable_key): Comment. + + * import.c (import_one): When in interactive mode and --verbose, + don't repeat some key information twice. + +2002-12-22 Timo Schulz <ts@winpt.org> + + * import.c (print_import_check): New. + (import_one): Use it here. + Use merge_keys_and_selfsig in the interactive mode to avoid + wrong key information. + * status.h: Add new status code. + * status.c: Ditto. + +2002-12-13 David Shaw <dshaw@jabberwocky.com> + + * pkclist.c (do_we_trust): Tweak language to refer to the "named + user" rather than "owner". Noted by Stefan Bellon. + + * trustdb.h, trustdb.c (trustdb_pending_check): New function to + check if the trustdb needs a check. + + * import.c (import_keys_internal): Used here so we don't rebuild + the trustdb if it is still clean. + (import_one, chk_self_sigs): Only mark trustdb dirty if the key + that is being imported has any sigs other than self-sigs. + Suggested by Adrian von Bidder. + + * options.skel: Include the required '=' sign in the sample + 'group' option. Noted by Stefan Bellon. + + * import.c (chk_self_sigs): Don't try and check a subkey as if it + was a signature. + +2002-12-11 David Shaw <dshaw@jabberwocky.com> + + * tdbio.c (tdbio_read_record, tdbio_write_record): Compact the + RECTYPE_TRUST records a bit. + + * g10.c (main): Comment out --list-trust-path until it can be + implemented. + + * import.c (import_one): Warn when importing an Elgamal primary + that this may take some time (to verify self-sigs). + (chk_self_sigs): Try and cache all self-sigs so the keyblock is + written to the keyring with a good rich cache. + + * keygen.c (ask_algo): Make the Elgamal sign+encrypt warning + stronger, and remove the RSA sign+encrypt warning. + +2002-12-06 Stefan Bellon <sbellon@sbellon.de> + + * options.h: Fixed typo (mangle_dos_names instead of + mangle_dos_filenames). + +2002-12-05 Werner Koch <wk@gnupg.org> + + * g10.c: New options --[no-]mangle-dos-filenames. + * options.h (opt): Added mangle-dos-filenames. + * openfile.c (open_outfile) [USE_ONLY_8DOT3]: Truncate the + filename only when this option is set; this is the default. + +2002-12-04 David Shaw <dshaw@jabberwocky.com> + + * main.h, keyedit.c, keygen.c: Back out previous (2002-12-01) + change. Minimal isn't always best. + + * sign.c (update_keysig_packet): Use the current time rather then + a modification of the original signature time. Make sure that + this doesn't cause a time warp. + + * keygen.c (keygen_add_key_expire): Properly handle a key + expiration date in the past (use a duration of 0). + + * keyedit.c (menu_expire): Use update_keysig_packet so any sig + subpackets are maintained during the update. + + * build-packet.c (build_sig_subpkt): Mark sig expired or unexpired + when the sig expiration subpacket is added. + (build_sig_subpkt_from_sig): Handle making an expiration subpacket + from a sig that has already expired (use a duration of 0). + + * packet.h, sign.c (update_keysig_packet), keyedit.c + (menu_set_primary_uid, menu_set_preferences): Add ability to issue + 0x18 subkey binding sigs to update_keysig_packet and change all + callers. + + * trustdb.c (validate_keys): Show trust parameters when building + the trustdb, and make sure that the version record update was + successful. + (init_trustdb): If the current parameters aren't what was used for + building the trustdb, the trustdb is invalid. + + * tbio.c (tdbio_db_matches_options): Update to work with new + trustdbs. + +2002-12-03 David Shaw <dshaw@jabberwocky.com> + + * tdbio.h, tdbio.c (tdbio_read_record, tdbio_write_record): Store + trust model in the trustdb version record. + (tdbio_update_version_record): New function to update version + record values during a trustdb check or update. + (tdbio_dump_record): Show trust model in dump. + + * trustdb.c (validate_keys): Call tdbio_update_version_record on + success so that the correct options are stored in the trustdb. + + * options.h: rearrange trust models so that CLASSIC is 0 and + OPENPGP is 1. + + * options.h, g10.c (main), encode.c (write_pubkey_enc_from_list), + pkclist.c (algo_available), revoke.c (gen_revoke): Add --pgp8 + mode. This is basically identical to --pgp7 in all ways except + that signing subkeys, v4 data sigs (including expiration), and SK + comments are allowed. + + * getkey.c (finish_lookup): Comment. + + * main.h, keylist.c (reorder_keyblock), keyedit.c (keyedit_menu): + Reorder user ID display in the --edit-key menu to match that of + the --list-keys display. + + * g10.c (add_notation_data): Fix initialization. + +2002-12-01 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_expire): Don't lose key flags when changing the + expiration date of a subkey. This is not the most optimal + solution, but it is minimal change on the stable branch. + + * main.h, keygen.c (do_copy_key_flags): New function to copy key + flags, if any, from one sig to another. + (do_add_key_expire): New function to add key expiration to a sig. + (keygen_copy_flags_add_expire): New version of + keygen_add_key_expire that also copies key flags. + (keygen_add_key_flags_and_expire): Use do_add_key_expire. + + * import.c (fix_hkp_corruption): Comment. + +2002-11-25 Stefan Bellon <sbellon@sbellon.de> + + * plaintext.c (handle_plaintext) [__riscos__]: If nooutput is set, + no filetype is needed obviously. + +2002-11-24 David Shaw <dshaw@jabberwocky.com> + + * main.h, misc.c (default_cipher_algo, default_compress_algo): + New. Return the default algorithm by trying + --cipher-algo/--compress-algo, then the first item in the pref + list, then s2k-cipher-algo or ZIP. + + * sign.c (sign_file, sign_symencrypt_file), encode.c + (encode_simple, encode_crypt): Call default_cipher_algo and + default_compress_algo to get algorithms. + + * g10.c (main): Allow pref selection for compress algo with + --openpgp. + + * mainproc.c (proc_encrypted): Use --s2k-digest-algo for + passphrase mangling rather than --digest-algo. + + * sign.c (hash_for): If --digest-algo is not set, but + --personal-digest-preferences is, then use the first hash + algorithm in the personal list. If the signing algorithm is DSA, + then use the first 160-bit hash algorithm in the personal list. + If --pgp2 is set and it's a v3 RSA key, use MD5. + + * g10.c (main), keydb.c (keydb_add_resource, + keydb_locate_writable): Rename --default-keyring as + --primary-keyring. Stefan wins the naming contest. + +2002-11-23 David Shaw <dshaw@jabberwocky.com> + + * g10.c (add_notation_data): Disallow notation names that do not + contain a '@', unless --expert is set. This is to help prevent + people from polluting the (as yet unused) IETF namespace. + + * main.h: Comments about default algorithms. + + * photoid.c (image_type_to_string): Comments about 3-letter file + extensions. + + * encode.c (encode_simple), passphrase.c (passphrase_to_dek), + sign.c (sign_symencrypt_file): Use --s2k-digest-algo for + passphrase mangling rather than --digest-algo. + +2002-11-21 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (keygen_set_std_prefs): Properly handle an empty + preference string. + + * misc.c (string_to_compress_algo): "none" is a bad choice since + it conflicts with the "none" in setpref. + +2002-11-14 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Allow compression algorithm names as the argument + to --compress-algo. The old algorithm names still work for + backwards compatibility. + + * misc.c (string_to_compress_algo): Allow "none" as an alias for + "uncompressed". + +2002-11-13 Stefan Bellon <sbellon@sbellon.de> + + * getkey.c (get_pubkey_byfprint_fast): Fixed type incompatibility, + was unsigned char instead of byte. + +2002-11-13 David Shaw <dshaw@jabberwocky.com> + + * encode.c (encode_simple): Make sure that files larger than about + 4G use partial length encoding. This is required because OpenPGP + allows only for 32 bit length fields. From Werner on stable + branch. + + * getkey.c (get_pubkey_direct): Renamed to... + (get_pubkey_fast): this and made extern. + (get_pubkey_byfprint_fast): New. From Werner on stable branch. + + * keydb.h, import.c (import_one): Use get_pubkey_fast instead of + get_pubkey. We don't need a merged key and actually this might + lead to recursions. + (revocation_present): Likewise for search by fingerprint. From + Werner on stable branch. + + * g10.c (main): Try to create the trustdb even for non-colon-mode + list-key operations. This is required because getkey needs to + know whether a a key is ultimately trusted. From Werner on stable + branch. + + * exec.c [__CYGWIN32__]: Keep cygwin separate from Mingw32; + we don't need it here as it behaves more like a Posix system. + From Werner on stable branch. + + * passphrase.c (agent_get_passphrase): Ditto. From Werner on + stable branch. + + * tdbio.c (MY_O_BINARY): Need binary mode with Cygwin. From + Werner on stable branch. + + * g10.c, gpgv.c (main) [__CYGWIN32__]: Don't get the homedir from + the registry. From Werner on stable branch. + + * keyedit.c (show_key_with_all_names_colon): Make --with-colons + --edit display match the validity and trust of --with-colons + --list-keys. + + * passphrase.c (agent_send_all_options): Fix compile warning. + + * keylist.c (list_keyblock_colon): Validity for subkeys should + match that of the primary key, and not that of the last user ID. + + * getkey.c (merge_selfsigs): Revoked/expired/invalid primary keys + carry these facts onto all their subkeys, but only after the + subkey has a chance to be marked valid. This is to fix an + incorrect "invalid public key" error verifying a signature made by + a revoked signing subkey, with a valid unrevoked primary key. + +2002-11-09 Werner Koch <wk@gnupg.org> + + * passphrase.c (agent_send_all_options): Use tty_get_ttyname to + get the default ttyname. + +2002-11-07 David Shaw <dshaw@jabberwocky.com> + + * keyring.h, keyring.c (keyring_register_filename): Return the + pointer if a given keyring is registered twice. + + * keydb.h, keydb.c (keydb_add_resource): Use flags to indicate a + default keyring. + (keydb_locate_writable): Prefer the default keyring if possible. + + * g10.c (main): Add --default-keyring option. + +2002-11-06 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), trustdb.c (ask_ownertrust): Add + --force-ownertrust option for debugging purposes. This allows + setting a whole keyring to a given trust during an + --update-trustdb. Not for normal use - it's just easier than + hitting "4" all the time to test a large trustdb. + + * pubkey-enc.c (get_session_key): With hidden recipients or try a + given passphrase against all secret keys rather than trying all + secret keys in turn. Don't if --try-all-secrets or --status-fd is + enabled. + + * passphrase.c (passphrase_to_dek): Mode 1 means do a regular + passphrase query, but don't prompt with the key info. + + * seckey-cert.c (do_check, check_secret_key): A negative ask count + means to enable passphrase mode 1. + + * keydb.h, getkey.c (enum_secret_keys): Add flag to include + secret-parts-missing keys (or not) in the list. + +2002-11-05 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_search_prompt): When --with-colons is + enabled, don't try and fit the search output to the screen size - + just dump the whole list. + +2002-11-04 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_search_prompt): When --with-colons is + enabled, just dump the raw keyserver protocol to stdout and don't + print the menu. + + * keyserver.c (show_prompt): Don't show a prompt when command-fd + is being used. + + * trustdb.c (trust_model_string, check_trustdb, update_trustdb, + validate_one_keyblock): It's not clear what a trustdb rebuild or + check means with a trust model other than "classic" or "openpgp", + so disallow this. + +2002-11-03 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main): Add --trust-model option. Current + models are "openpgp" which is classic+trustsigs, "classic" which + is classic only, and "always" which is the same as the current + option --always-trust (which still works). Default is "openpgp". + + * trustdb.c (validate_one_keyblock): Use "openpgp" trust model to + enable trust sigs. + + * gpgv.c (main), mainproc.c (check_sig_and_print), pkclist.c + (do_we_trust, do_we_trust_pre, check_signatures_trust): Use new + --trust-model option in place of --always-trust. + + * keyedit.c (sign_mk_attrib, trustsig_prompt, sign_uids, + keyedit_menu): Prompt for and create a trust signature with + "tsign". This is functional, but needs better UI text. + + * build-packet.c (build_sig_subpkt): Able to build trust and + regexp subpackets. + + * pkclist.c (do_edit_ownertrust): Comment. + +2002-11-02 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (set_one_pref, keygen_set_std_prefs): Allow using the + full algorithm name (CAST5, SHA1) rather than the short form (S3, + H2). + + * main.h, keygen.c (keygen_get_std_prefs), keyedit.c + (keyedit_menu): Return and use a fake uid packet rather than a + string since we already have a nice parser/printer in + keyedit.c:show_prefs. + + * main.h, misc.c (string_to_compress_algo): New. + +2002-11-01 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Add --no-throw-keyid. + + * keydb.h, encode.c (write_pubkey_enc_from_list), g10.c (main), + pkclist.c (build_pk_list): Add --hidden-recipient (-R) and + --hidden-encrypt-to, which do a single-user variation on + --throw-keyid. The "hide this key" flag is carried in bit 0 of + the pk_list flags field. + + * keyserver.c (parse_keyrec): Fix shadowing warning. + +2002-10-31 Stefan Bellon <sbellon@sbellon.de> + + * compress.c (init_compress) [__riscos__]: Use + riscos_load_module() to load ZLib module. + + * g10.c (main) [__riscos__]: Renames due to changes in riscos.c + (e.g. prefixes all RISC OS specific functions with riscos_*). + * photoid.c (show_photos) [__riscos__]: Likewise. + * signal.c (got_fatal_signal) [__riscos__]: Likewise. + + * trustdb.c (check_regexp) [__riscos__]: Branch to RISC OS RegEx + handling. + +2002-10-31 David Shaw <dshaw@jabberwocky.com> + + * build-packet.c (do_plaintext), encode.c (encode_sesskey, + encode_simple, encode_crypt), sign.c (write_plaintext_packet): Use + wipememory() instead of memset() to wipe sensitive memory as the + memset() might be optimized away. + +2002-10-30 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (check_regexp): Modern regexps require REG_EXTENDED. + +2002-10-29 David Shaw <dshaw@jabberwocky.com> + + * packet.h, trustdb.h, trustdb.c (trust_string): New. Return a + string like "fully trusted", "marginally trusted", etc. + (get_min_ownertrust): New. Return minimum ownertrust. + (update_min_ownertrust): New. Set minimum ownertrust. + (check_regexp): New. Check a regular epression against a user ID. + (ask_ownertrust): Allow specifying a minimum value. + (get_ownertrust_info): Follow the minimum ownertrust when + returning a letter. + (clear_validity): Remove minimum ownertrust when a key becomes + invalid. + (release_key_items): Release regexp along with the rest of the + info. + (validate_one_keyblock, validate_keys): Build a trust sig chain + while validating. Call check_regexp for regexps. Use the minimum + ownertrust if the user does not specify a genuine ownertrust. + + * pkclist.c (do_edit_ownertrust): Only allow user to select a + trust level greater than the minimum value. + + * parse-packet.c (can_handle_critical): Can handle critical trust + and regexp subpackets. + + * trustdb.h, trustdb.c (clear_ownertrusts), delkey.c + (do_delete_key), import.c (import_one): Rename clear_ownertrust to + clear_ownertrusts and have it clear the min_ownertrust value as + well. + + * keylist.c (list_keyblock_print): Indent uid to match pub and + sig. + + * keyedit.c (print_and_check_one_sig, show_key_and_fingerprint, + menu_addrevoker), keylist.c (list_keyblock_print, + print_fingerprint): Show "T" or the trust depth for trust + signatures, and add spaces to some strings to make room for it. + + * packet.h, parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt, + parse_signature): Parse trust signature values. + + * tdbio.h, tdbio.c (tdbio_read_record, tdbio_write_record): + Reserve a byte for the minimum ownertrust value (for use with + trust signatures). + +2002-10-29 Stefan Bellon <sbellon@sbellon.de> + + * build-packet.c (calc_plaintext, do_plaintext): Removed RISC OS + specific filetype parts (it's now done in make_basename()). + + * plaintext.c (handle_plaintext): Tidied up RISC OS specific + filetype parts. + + * encode.c (encode_simple, encode_crypt): Added argument to + make_basename() call. + + * sign.c (write_plaintext_packet): Added argument to + make_basename() call. + +2002-10-28 Stefan Bellon <sbellon@sbellon.de> + + * build-packet.c (calc_plaintext, do_plaintext): Added filetype + handling for RISC OS' file types. + + * plaintext.c (handle_plaintext) [__riscos__]: Added filetype + handling for RISC OS' file types. + +2002-10-23 David Shaw <dshaw@jabberwocky.com> + + * main.h, import.c (sec_to_pub_keyblock, import_secret_one, + parse_import_options), g10.c (main): New import-option + "convert-sk-to-pk" to convert a secret key into a public key + during import. It is on by default. + +2002-10-23 Werner Koch <wk@gnupg.org> + + * pubkey-enc.c (get_it): Fix segv, test for revoked only when PK + has been assigned. + +2002-10-18 Timo Schulz <ts@winpt.org> + + * keylist.c: (print_pubkey_info): New. + (print_seckey_info): New. + * main.h: Prototypes for the new functions. + * delkey.c (do_delete_key): Use it here. + * revoke.c (gen_desig_revoke): Ditto. + +2002-10-17 Werner Koch <wk@gnupg.org> + + * pkclist.c (do_edit_ownertrust): Show all user IDs. This should + be enhanced to also show the current trust level. Suggested by + Florian Weimer. + +2002-10-17 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Handle --strict and --no-strict from the command + line before the options file is loaded. + +2002-10-15 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Disable --textmode when encrypting (symmetric or + pk) in --pgp2 mode as PGP 2 can't handle the unknown length + literal packet. Reported by Michael Richardson. + +2002-10-14 David Shaw <dshaw@jabberwocky.com> + + * keyserver-internal.h, keyserver.c (print_keyrec, parse_keyrec, + show_prompt, keyserver_search_prompt, keyserver_spawn): Go to + version 1 of the keyserver protocol. This is a better design, + similar to --with-colons, that allows for keys with multiple user + IDs rather than using multiple keys. It also matches the machine + readable pksd format. Also use a prettier --search-keys listing + format that can fill different size windows (currently set at 24 + lines). + +2002-10-12 Werner Koch <wk@gnupg.org> + + * keygen.c (print_status_key_created): New. + (do_generate_keypair): Use it to print the fingerprint. + (generate_subkeypair): Likewise. + +2002-10-11 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_addrevoker): Properly back out if the signature + fails. Also, do not allow appointing the same revoker twice, and + report ALREADY_SIGNED if the user tries it. + +2002-10-07 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_keys_internal): Missed one s/inp/inp2/. + + * keylist.c (print_capabilities): Properly indicate per-key + capabilities of sign&encrypt primary keys that have + secret-parts-missing (i.e. no capabilities at all) + + * mainproc.c (symkey_decrypt_sesskey): Fix compiler warning. + +2002-10-04 David Shaw <dshaw@jabberwocky.com> + + * getkey.c (get_pubkey_direct): Don't cache keys retrieved via + this function as they may not have all their fields filled in. + + * sig-check.c (signature_check2): Use new is_primary flag to check + rather than comparing main_keyid with keyid as this still works in + the case of a not fully filled in pk. + +2002-10-04 Werner Koch <wk@gnupg.org> + + * import.c (import_keys_internal): s/inp/inp2/ to avoid shadowing + warning. + + * passphrase.c (agent_get_passphrase): Fixed signed/unsigned char + problem in %-escaping. Noted by Ingo Klcker. + +2002-10-03 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main): Add --strict and --no-strict to switch + the log_warning severity level from info to error. + + * keylist.c (print_capabilities): Secret-parts-missing keys should + show that fact in the capabilities, and only primary signing keys + can certify other keys. + + * packet.h, parse_packet.c (parse_key): Add is_primary flag for + public keys (it already exists for secret keys). + +2002-10-02 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_secret_one): Check for an illegal (>110) + protection cipher when importing a secret key. + + * keylist.c (list_keyblock_print): Show a '#' for a + secret-parts-missing key. + + * parse_packet.c (parse_key): Some comments. + + * revoke.c (gen_revoke): Remove some debugging code. + + * trustdb.c (verify_own_keys): Make trusted-key a non-deprecated + option again. + + * seckey-cert.c (do_check): Don't give the IDEA warning unless the + cipher in question is in fact IDEA. + +2002-10-01 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_one): Make sure that a newly imported key + starts with a clean ownertrust. + +2002-10-01 Werner Koch <wk@gnupg.org> + + * getkey.c (get_pubkey_direct): New. + (merge_selfsigs_main): Use it here to look for an ultimately + trusted key. Using the full get_pubkey might lead to an + infinitive recursion. + +2002-09-29 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (parse_keyserver_uri): Force the keyserver URI + scheme to lowercase to be case-insensitive. + +2002-09-28 David Shaw <dshaw@jabberwocky.com> + + * export.c (do_export_stream): Comment. + + * sig-check.c (check_key_signature2): Properly handle a + non-designated revocation import. + +2002-09-26 Werner Koch <wk@gnupg.org> + + * g10.c (set_homedir): New. Changed all direct assignments to use + this. + * gpgv.c (set_homedir): Ditto. + +2002-09-25 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Link gpg with EGDLIBS (i.e. NETLIBS) as EGD uses + sockets. Remove the old NETLIBS variable since the keyserver + stuff is no longer internal. + +2002-09-24 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_keys_stream): Fix compiler type warning. + + * keyring.c (keyring_rebuild_cache), sig-check.c + (check_key_signature2), import.c (import, chk_self_sigs): Minor + language cleanups. + +2002-09-23 Stefan Bellon <sbellon@sbellon.de> + + * main.h: Introduced fast-import as import option. Removed + fast as separate option from prototypes. + * import.c (parse_import_options): Added fast-import option. + (import_*): Removed fast as separate option. + * g10.c (main): Added option fast-import, removed old fast + as separate argument. + * keyserver.c (keyserver_spawn): Removed old fast as separate + argument. + +2002-09-22 Stefan Bellon <sbellon@sbellon.de> + + * import.c (import_keys, import_keys_stream, + import_keys_internal): Added trustdb update/check to key import if + not fast-import and interactive set/no-auto-check-trustdb unset. + Avoided function clone by introducing import_keys_internal. + +2002-09-19 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_spawn): Properly handle line truncation. + Don't leak memory (~10-20 bytes) on searches. + (keyserver_search_prompt): Cleanup. + + * keylist.c (list_keyblock_colon): Show 1F direct key signatures + in --with-colons listing. + +2002-09-16 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_addrevoker): The direct key signature for + revocation keys must be at least v4 to carry the revocation key + subpacket. Add a PGP 2.x warning for revocation keys. + +2002-09-14 David Shaw <dshaw@jabberwocky.com> + + * g10.c (check_permissions): Rearrange strings to make translating + easier (don't incorporate string parts). + + * keyedit.c (sign_uids): Make strings translatable. + + * sig-check.c (check_key_signature2): Make string translatable. + +2002-09-13 David Shaw <dshaw@jabberwocky.com> + + * getkey.c (check_revocation_keys): Move.... + * main.h, sig-check.c (check_revocation_keys): to here. Also + return the signature_check error code rather than 0/1 and cache + the sig result. + + * sig-check.c (check_key_signature2): Divert to + check_revocation_keys if a revocation sig is made by someone other + than the pk owner. + + * getkey.c (merge_selfsigs_main): Tidy. + +2002-09-13 Werner Koch <wk@gnupg.org> + + * g10.c (main) [__MINGW32__]: Activate oLoadExtension. + +2002-09-12 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am, hkp.c, hkp.h, keyserver.c (keyserver_work): Remove + internal HKP support. + + * keyserver.c (keyserver_spawn): Remove whitespace after keyserver + commands. + +2002-09-10 David Shaw <dshaw@jabberwocky.com> + + * exec.c (expand_args): Remove loop left over from earlier + implementation. + (exec_write): Missed one tick. + +2002-09-10 Werner Koch <wk@gnupg.org> + + * g10.c, options.h: Removed option --emulate-checksum-bug. + * misc.c (checksum_u16_nobug): Removed. + (checksum_u16): Removed the bug emulation. + (checksum_mpi): Ditto. + (checksum_mpi_counted_nbits): Removed and replaced all calls + with checksum_mpi. + + * parse-packet.c (read_protected_v3_mpi): New. + (parse_key): Use it here to store it as an opaque MPI. + * seckey-cert.c (do_check): Changed the v3 unprotection to the new + why to store these keys. + (protect_secret_key): Likewise. + * build-packet.c (do_secret_key): And changed the writing. + + * tdbio.c (tdbio_set_dbname, open_db): Use new macro MY_O_BINARY + to avoid silly ifdefs. + (open_db): Fallback to RDONLY so that gpg may be used from a + RO-medium. + + * encode.c (encode_simple): Make sure we don't use an ESK packet + when we don't have a salt in the S2K. + + * misc.c (pct_expando) <case f>: Make sure that LEN is initialized. + + * exec.c (exec_finish): Use ticks to denote filenames in messages. + (make_tempdir, exec_write): Changed format of messages. + + * keyserver.c (print_keyinfo): Release USERID in on error. + (keyserver_work) [!DISABLE_KEYSERVER_HELPERS]: Exclude the unused + code. + +2002-09-09 Werner Koch <wk@gnupg.org> + + * parse-packet.c (make_attribute_uidname): Add new ar MAX_NAMELEN + for sanity checks. Changed both callers. Limit the size of an %s. + + * options.skel: Comment lock-once out, so that this file does not + change anything when copied to a new home directory. + * openfile.c (try_make_homedir): Don't exit after copying the + option skeleton. + + * options.h: Don't use a comma when declaring variables over more + than one line. + + * mainproc.c (symkey_decrypt_sesskey): Check length of the session + key. + + * hkp.c (dehtmlize): Use ascii_tolower to protect against weird + locales. Cast the argument for isspace for the sake of broken + HP/UXes. + (parse_hkp_index): s/ascii_memcasecmp/ascii_strncasecmp/. + + * g10.c: Removed option --emulate-3des-s2k-bug. + + * passphrase.c (hash_passphrase): Was used here. + + * export.c (parse_export_options) + * keyserver.c (parse_keyserver_options) + * import.c (parse_import_options) + * g10.c (check_permissions): s/ascii_memcasecmp/ascii_strncasecmp/. + +2002-09-09 David Shaw <dshaw@jabberwocky.com> + + * g10.c (add_group): Use '=' to separate group name from group + members. Use a better error message for when no = is found. + + * hkp.c (hkp_export): Use CRLF in headers. + +2002-09-03 David Shaw <dshaw@jabberwocky.com> + + * mainproc.c (print_pkenc_list): Don't increment the error counter + when printing the list of keys a message was encrypted to. This + would make gpg give a non-zero exit code even for completely valid + messages if the message was encrypted to more than one key that + the user owned. + +2002-09-02 Werner Koch <wk@gnupg.org> + + * g10.c (main): Try to set a default character set. Print the + used one in verbosity level 3. + * gpgv.c (main): Try to set a default character set. + + * status.c, status.h (STATUS_IMPORT_OK): New. + * import.c (import_one,import_secret_one): Print new status. + +2002-08-30 David Shaw <dshaw@jabberwocky.com> + + * pkclist.c (build_pk_list): Add new status code to indicate an + untrusted user. This (or a disabled key) fail with "unavailable + pubkey" (G10ERR_UNU_PUBKEY). + + * pkclist.c (build_pk_list): Fail if any recipient keys are + unusable. + + * options.skel: The PGP LDAP keyserver is back. Use MIT keyserver + as a sample rather than cryptnet as cryptnet does not support + searching yet. + + * keyedit.c (show_key_with_all_names): Fix error message + (preferences are userid/selfsig and not key specific). + +2002-08-30 Werner Koch <wk@gnupg.org> + + * pkclist.c (do_we_trust_pre): Changed the wording of a warning. + + * encode.c (encode_simple,encode_crypt): Use new style CTB for + compressssed packets when using MDC. We need to do this so that + concatenated messages are properly decrypted. Old style + compression assumes that it is the last packet; given that we + can't determine the length in advance, the uncompressor does not + know where to start. Actually we should use the new CTB always + but this would break PGP 2 compatibility. + + * parse-packet.c (parse): Special treatment for new style CTB + compressed packets. + + * build-packet.c (do_mdc): Removed. Was not used. + (do_encrypted_mdc): Count in the version number and the MDC packet. + +2002-08-28 David Shaw <dshaw@jabberwocky.com> + + * sig-check.c (do_check_messages, do_check): Show keyid in error + messages. + + * keyserver.c (print_keyinfo): More readable key listings for + --search-keys responses. + +2002-08-26 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (parse_hkp_index, dehtmlize): Move HTML functionality into + new "dehtmlize" function. Remove HTML before trying to parse each + line from the keyserver. If the keyserver provides key type + information in the listing, use it. + +2002-08-23 David Shaw <dshaw@jabberwocky.com> + + * sig-check.c (do_check, do_check_messages): Emit the usual sig + warnings even for cached sigs. This also serves to protect + against missing a sig expiring while cached. + + * getkey.c (merge_selfsigs_main): Don't check UID self-sigs twice. + +2002-08-22 David Shaw <dshaw@jabberwocky.com> + + * import.c (clean_subkeys, chk_self_sigs): Merge clean_subkeys + into chk_self_sigs. This improves efficiency as the same + signatures are not checked multiple times. Clarify when a subkey + is revoked (any revocation signature, even if it is dated before + the binding signature). + + * getkey.c (merge_selfsigs_subkey): Subkey revocation comments. + + * keylist.c (list_one): Stats are only for public key listings. + + * g10.c (main), options.skel: Default should be include-revoked + for keyserver operations. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * import.c (import_print_stats): Print new non_imported counter + which is currently not used because we terminate on errors. + +2002-08-20 David Shaw <dshaw@jabberwocky.com> + + * options.skel: Document no-include-attributes for + keyserver-options. + + * keylist.c, keyedit.c, keyserver.c, sign.c: Some TODOs and + comments. + + * export.c (do_export_stream): Fix noop bug in exporting sensitive + revocation keys. + + * pkclist.c (do_edit_ownertrust): Comment out the option for + showing trust paths until it can be implemented. + +2002-08-19 Werner Koch <wk@gnupg.org> + + * getkey.c (get_user_id_native): Renamed to .. + (get_user_id_printable): this. Filter out all dangerous + characters. Checked all usages. + (get_user_id_string_native): Renamed to.. + (get_user_id_string_printable): this. Filter out all dangerous + characters. Checked all usages. + * keyedit.c (show_basic_key_info): New. + * keylist.c (print_fingerprint): New mode 3. + * import.c (import_one): Use new function to display the user ID. + +2002-08-16 Timo Schulz <ts@winpt.org> + + * g10.c (main): Enable opt.interactive. + + * import.c (import_one): Ask the user if the key shall be + imported when the interactive mode is used. Useful to extract + selected keys from a file. + +2002-08-16 Werner Koch <wk@gnupg.org> + + * seckey-cert.c: Workaround to allow decryption of v3 keys created + with a bug in the mpi_get_secure_buffer. + +2002-08-14 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (parse_hkp_index): Properly handle really large keys + (5 digit key length) in HKP searches. + +2002-08-13 David Shaw <dshaw@jabberwocky.com> + + * encode.c (encode_simple): Fix problem with using compression + algo 2 and symmetric compressed files. + + * encode.c (encode_simple, encode_crypt): If we are not using a + MDC, compress even if a file is already compressed. This is to + help against the chosen ciphertext attack. + + * pkclist.c (select_algo_from_prefs): Fix requested algorithm bug + so the request succeeds even if the requested algorithm is not the + first found. + + * cipher.c (write_header), encode.c (use_mdc, encode_simple, + encode_crypt, encrypt_filter), g10.c (main): Be more eager to use + a MDC. We use a MDC if the keys directly support it, if the keys + list AES (any) or TWOFISH anywhere in the prefs, or if the cipher + chosen does not have a 64 bit blocksize. + +2002-08-08 David Shaw <dshaw@jabberwocky.com> + + * options.skel: Some language tweaks, and remove the + load-extension section for random gatherers. + + * keyring.c (create_tmp_file, rename_tmp_file): Create tmp files + with user-only permissions, but restore the original permissions + if the user has something special set. + + * openfile.c (copy_options_file): Create new options file + (gpg.conf) with user-only permissions. + + * keydb.c (keydb_add_resource): Create new keyrings with user-only + permissions. + + * tdbio.c (tdbio_set_dbname): Create new trustdbs with user-only + permissions. + +2002-08-07 David Shaw <dshaw@jabberwocky.com> + + * sig-check.c (signature_check2): Sanity check that the md has a + context for the hash that the sig is expecting. This can happen + if a onepass sig header does not match the actual sig, and also if + the clearsign "Hash:" header is missing or does not match the + actual sig. + + * keyedit.c (menu_revsig): Properly show a uid is revoked without + restarting gpg. This is Debian bug 124219, though their supplied + patch will not do the right thing. + + * main.h, tdbio.c (tdbio_set_dbname), misc.c (removed + check_permissions), keydb.c (keydb_add_resource), g10.c (main, + check_permissions): Significant reworking of the permission check + mechanism. The new behavior is to check everything in the homedir + by checking the homedir itself. If the user wants to put + (possibly shared) keyrings outside the homedir, they are not + checked. The options file and any extension files are checked + wherever they are, as well as their enclosing directories. This + is Debian bug 147760. + +2002-08-06 Stefan Bellon <sbellon@sbellon.de> + + * g10.c (main): Use of EXTSEP_S in new gpg.conf string. + * openfile.c (copy_options_file): Ditto. + +2002-08-06 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), mainproc.c (proc_encrypted): + --ignore-mdc-error option to turn a MDC check error into a + warning. + + * encode.c (encode_crypt), g10.c (main), sign.c (sign_file, + clearsign_file): Use the same --pgpX warning string everywhere to + ease translations. + + * encode.c (write_pubkey_enc_from_list): Warn when using + --throw-keyid with --pgpX. Noted by Vedaal Nistar. + + * revoke.c (export_minimal_pk, gen_desig_revoke, gen_revoke): + Export a minimal pk along with the revocation cert when in --pgpX + mode so that PGP can import it. + +2002-08-06 Werner Koch <wk@gnupg.org> + + * options.skel: Changed comments. + + * g10.c (main): Try to use "gpg.conf" as default option file. + * openfile.c (copy_options_file): Changed name of created file. + +2002-08-02 Werner Koch <wk@gnupg.org> + + * Makefile.am (LDFLAGS): Removed DYNLINK_LDFLAGS. + +2002-07-30 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), mainproc.c (proc_encrypted): Return a + decryption failed error if a MDC does not verify. Warn if a MDC + is not present (can disable via --no-mdc-warning). + + * exec.c (exec_write), g10.c (main), keyserver.c + (keyserver_spawn): Use new DISABLE_KEYSERVER_PATH rather than + FIXED_EXEC_PATH. + +2002-07-28 David Shaw <dshaw@jabberwocky.com> + + * sig-check.c (do_check): Properly validate v4 sigs with no hashed + section at all. + +2002-07-25 Werner Koch <wk@gnupg.org> + + * delkey.c (do_delete_key): Always allow to delete a key in batch mode + when specified by fingerprint. Suggested by Enzo Michelangeli. + +2002-07-25 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_revsig): Change "revsig" to honor selected uids + so the user can revoke sigs from particular uids only. + + * keylist.c (list_keyblock_print): Don't display expired uids in + --list-keys unless -v and not --list-sigs (just like revoked + uids). + + * exec.c, export.c, import.c, keyedit.c, keyserver.c, misc.c: + "Warning" -> "WARNING" + +2002-07-24 David Shaw <dshaw@jabberwocky.com> + + * main.h, import.c (parse_import_options, fix_hkp_corruption, + import_one, delete_inv_parts), g10.c (main): New import-option + "repair-hkp-subkey-bug", which repairs as much as possible the HKP + mangling multiple subkeys bug. It is on by default for keyserver + receives, and off by default for regular --import. + + * main.h, import.c (import, import_one, delete_inv_parts), hkp.c + (hkp_ask_import), keyserver.c (keyserver_spawn): Use keyserver + import options when doing keyserver receives. + + * options.h, exec.h, exec.c (set_exec_path, exec_write), g10.c + (main), keyserver.c (keyserver_spawn): If the user does not use + "exec-path", completely replace $PATH with GNUPG_LIBEXECDIR before + calling the keyserver helper. If the user does use "exec-path", + append GNUPG_LIBEXECDIR after the specified path. + +2002-07-23 David Shaw <dshaw@jabberwocky.com> + + * import.c (parse_import_options), export.c + (parse_export_options): Fix offset problem with reversed ("no-") + meanings. + + * import.c (delete_inv_parts): Discard subkey signatures (0x18 and + 0x28) if found in the userid section of the key. + + * sig-check.c (signature_check2): Signatures made by invalid + subkeys (bad/missing binding sig) are also invalid. + + * keylist.c (print_fingerprint): Show the primary as well as the + secondary key fingerprint in modes 1 & 2. + +2002-07-22 David Shaw <dshaw@jabberwocky.com> + + * options.h, main.h, g10.c (main), import.c + (parse_import_options, delete_inv_parts), keyserver.c + (parse_keyserver_options): add new --import-options option. The + only current flag is "allow-local-sigs". + + * g10.c (main): Don't disable MDC in pgp7 mode. + + * options.h, g10.c (main), keyserver.c (parse_keyserver_options): + Remove old keyserver-option include-attributes now that there is + an export-option for the same thing. + + * options.h, main.h, export.c (parse_export_options, + do_export_stream), g10.c (main): add new --export-options option. + Current flags are "include-non-rfc", "include-local-sigs", + "include-attributes", and "include-sensitive-revkeys". + + * options.h, hkp.c (hkp_export), keyserver.c + (parse_keyserver_options, keyserver_spawn): try passing unknown + keyserver options to export options, and if successful, use them + when doing a keyserver --send-key. + + * build-packet.c (build_sig_subpkt): We do not generate + SIGSUBPKT_PRIV_VERIFY_CACHE anymore. + + * revoke.c (gen_desig_revoke): Lots more comments about including + sensitive revkeys along with the revocation sig itself. + + * keyserver.c (parse_keyserver_options): Simpler implementation + that can skip one pass over the options. + +2002-07-18 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (keyedit_menu, menu_addrevoker): Allow specifying + "sensitive" as an argument to an addrevoker command. This sets + the 0x40 sensitive revoker flag. + + * revoke.c (gen_desig_revoke): When generating a designated + revocation, include the direct key sig that contains the + designated revoker subpacket. This allows sensitive designated + revocation subpackets to be exported. Also indicate which + revokers are sensitive in the first place. + +2002-07-17 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (show_key_with_all_names_colon): The 0x40 class bit in + a designated revoker means "sensitive", not "local". It's + exportable under the right circumstances. + + * main.h, options.h, export.c (do_export_stream), g10.c (main), + hkp.c (hkp_export), keyserver.c (keyserver_spawn: Add a flag to + skip attribute packets and their signatures while exporting. This + is to accomodate keyservers (pksd again) that choke on attributes. + Use keyserver-option "include-attributes" to control it. This + defaults to ON (i.e. don't skip). + +2002-07-09 David Shaw <dshaw@jabberwocky.com> + + * options.h, keyserver.c (parse_keyserver_uri, keyserver_spawn, + keyserver_work), hkp.c (hkp_ask_import, hkp_export, hkp_search): + Use a much more strict reading of RFC-2396 for the keyserver URIs. + Specifically, don't try and be smart about checking the value of + ":port" so long as it is all digits, and properly handle opaque + data (those scheme specific parts that do not start with "//"). + +2002-07-04 David Shaw <dshaw@jabberwocky.com> + + * photoid.c (get_default_photo_command, show_photos): Honor + FIXED_PHOTO_VIEWER and DISABLE_PHOTO_VIEWER. + + * mainproc.c (check_sig_and_print): Use --show-photos to show + photos when verifying a sig made by a key with a photo. + + * keyserver.c (parse_keyserver_uri): Properly parse a URI with no + :port section and an empty file path, but with a terminating '/'. + (keyserver_work): Honor DISABLE_KEYSERVER_HELPERS. + + * hkp.c (hkp_ask_import): Display keyserver URI as a URI, but only + if verbose. + + * exec.c, g10.c: USE_EXEC_PATH -> FIXED_EXEC_PATH + +2002-07-03 David Shaw <dshaw@jabberwocky.com> + + * exec.h, exec.c (set_exec_path, exec_write), g10.c (main): If + USE_EXEC_PATH is defined at compile time, use it to lock the + exec-path and not allow the user to change it. + +2002-07-02 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), keyserver.c (keyserver_refresh): + Maintain and use the original keyserver URI for cosmetics rather + than trying to recreate it when needed. + + * mainproc.c (check_sig_and_print): Properly disregard expired + uids. Make sure that the first uid listed is a real uid and not + an attribute (attributes should only be listed in the "aka" + section). When there are no valid textual userids, try for an + invalid textual userid before using any attribute uid. + +2002-07-01 David Shaw <dshaw@jabberwocky.com> + + * options.skel: Fix a few typos, clarify "group", and remove + sample photo viewers for Win32 since they are the defaults now. + + * parse-packet.c (make_attribute_uidname), keylist.c + (dump_attribs): Fix two typecast warnings. + + * packet.h, build-packet.c (build_attribute_subpkt), exec.c + (expand_args), mkdtemp.c (mkdtemp), photoid.c + (parse_image_header): Fix some signedness compiler warnings. + +2002-07-01 Werner Koch <wk@gnupg.org> + + * photoid.c (get_default_photo_command): Also use __MINGW32__ + instead of HAVE_DOSISH_SYSTEM. + + * encode.c (encode_symmetric): Do not use the new encryption code. + +2002-06-30 Werner Koch <wk@gnupg.org> + + * photoid.c: Use __MINGW32__ to include windows because + HAVE_DOSISH_SYSTEM is also set for OS/2 and plain DOS. Provide + constant missing in older mingw installations. + +2002-06-21 Stefan Bellon <sbellon@sbellon.de> + + * g10.c [__riscos__]: Moved RISC OS specific stuff to util/riscos.c + and include/util.h. + + * gpgv.c [__riscos__]: Likewise. + +2002-06-20 David Shaw <dshaw@jabberwocky.com> + + * keydb.h, pkclist.c (select_algo_from_prefs): Allow passing a + suggested algorithm which will be used if available. + + * encode.c (encode_crypt, encrypt_filter), sign.c (sign_file): Use + new select_algo_from_prefs feature to check if forcing an + algorithm would violate the recipient preferences. + + * photoid.c (get_default_photo_command, show_photos): Use + different default viewers on different platforms. Currently we + have Win 9x, Win NT (2k, xp), Mac OSX, RISC OS, and "everybody + else". These are #ifdefs as much as possible to avoid clutter. + + * g10.c (strusage, build_list), keyedit.c (show_prefs), main.h, + misc.c (compress_algo_to_string, check_compress_algo), pkclist.c + (algo_available), keygen.c (keygen_set_std_prefs): New + algo_to_string and check functions for compress algorithms. + +2002-06-20 Werner Koch <wk@gnupg.org> + + * misc.c (setsysinfo): Removed a #warning for Alpha's uniligedn + trap disabling - it is quite possible that this is a debug relict. + +2002-06-20 Stefan Bellon <sbellon@sbellon.de> + + * g10.c [__riscos__]: Added image file system feature. + + * gpgv.c [__riscos__]: Added image file system feature. + + * photoid.c (show_photos) [__riscos__]: Set RISC OS filetype of + photo id according to MIME type. + +2002-06-19 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (parse_hkp_index): Don't leak memory when failing out of a + bad HKP keyserver. + + * g10.c (add_notation_data): Relax slightly the rules as to what + can go into a notation name - 2440 allows "@", for example. + +2002-06-17 David Shaw <dshaw@jabberwocky.com> + + * import.c (clean_subkeys, import_one): Only allow at most 1 + binding sig and at most 1 revocation sig on a subkey, as per + 2440:11.1. + + * hkp.c (parse_hkp_index, hkp_search): Error if the keyserver + returns an unparseable HKP response. + +2002-06-15 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (show_key_with_all_names), keylist.c + (list_keyblock_print): Show "[expired]" before expired uids. + + * keyedit.c (show_key_with_all_names_colon), mainproc.c + (list_node), keylist.c (list_keyblock_colon): Show flag 'e' for + expired user ids. Use "uat" for user attribute packets instead of + "uid". Also use '<count> <length>' rather than the fake user id + string on attributes. + + * keygen.c (keygen_add_revkey): Remove unused code. + + * misc.c (check_permissions): Check directory permissions + properly - they are not special files. + + * pkclist.c (expand_id, expand_group, build_pk_list): When + expanding groups before building a pk list, inherit flags from the + original pre-expanded string. + + * pubkey-enc.c (is_algo_in_prefs): Don't use prefs from expired + uids. + +2002-06-14 David Shaw <dshaw@jabberwocky.com> + + * free-packet.c (copy_signature): Properly copy a signature that + carries a revocation key on it. + + * pkclist.c (expand_id, expand_group, build_pk_list): Groups now + work properly when used in the "Enter the user ID" prompt. + +2002-06-14 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (show_key_with_all_names): Display warning if a user + tries to show prefs on a v3 key with a v3 selfsig. + + * kbnode.c (dump_kbnode): Show if a uid is expired. + + * import.c (merge_blocks, import_revoke_cert): Show user ID + receiving a revocation certificate. + + * free-packet.c (cmp_user_ids): Properly compare attribute ids. + + * pkclist.c (expand_groups): Maintain the strlist flags while + expanding. Members of an expansion inherit their flags from the + expansion key. + + * options.h, cipher.c (write_header), g10.c (main), keygen.c + (keygen_set_std_prefs): remove the personal_mdc flag. It no + longer serves a purpose now that the personal preference lists are + split into cipher/digest/zip. + +2002-06-14 Timo Schulz <ts@winpt.org> + + * skclist.c (is_insecure): Implemented. + +2002-06-12 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_spawn): Properly handle PROGRAM responses + when they have a CRLF ending. Noted by Keith Ray. + + * keyserver.c (keyserver_spawn): Handle CRLF endings from + keyserver helpers. Also don't leak the last line worth of memory + from the keyserver response. + + * main.h, misc.c (deprecated_warning): New function to warn about + deprecated options and commands. + + * g10.c (main), keyserver-internal.h, keyserver.c + (parse_keyserver_uri): Use new deprecated function to warn about + honor-http-proxy, auto-key-retrieve, and x-broken-hkp. + +2002-06-11 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: link gpg with NETLIBS for the built-in HKP access. + +2002-06-10 David Shaw <dshaw@jabberwocky.com> + + * options.h, keyserver.c (keyserver_opts), g10.c (main): New + keyserver option "include-subkeys". This feature already existed, + but now can be turned off. It defaults to on. + + * options.h, keyserver.c (parse_keyserver_options, + keyserver_spawn): There are now enough options to justify making a + structure for the keyserver options rather than a page of + if-then-else-if-then-etc. + + * getkey.c (merge_keys_and_selfsig, merge_selfsigs_main): Fix bug + in calculating key expiration dates. + +2002-06-09 David Shaw <dshaw@jabberwocky.com> + + * keydb.h, getkey.c (get_user_id_native), import.c (import_one): + Display user ID while importing a key. Note this applies to both + --import and keyserver --recv-keys. + + * exec.c (exec_finish): Log unnatural exit (core dump, killed + manually, etc) for fork/exec/pipe child processes. + +2002-06-08 Timo Schulz <ts@winpt.org> + + * encode.c (encode_symmetric): Disable the compat flag + when the expert mode is enabled. + +2002-06-07 David Shaw <dshaw@jabberwocky.com> + + * options.skel, options.h, main.h, keydb.h, pkclist.c + (build_pk_list, expand_groups), g10.c (main, add_group): Add new + "group" command to allow one name to expand into multiple keys. + For simplicity, and to avoid potential loops, we only expand once + - you can't make an alias that points to an alias. + + * main.h, g10.c (main), keygen.c (build_personal_digest_list): + Simplify the default digest list - there is really no need for the + other hashes since they will never be used after SHA-1 in the + list. + + * options.skel, options.h, g10.c (main), hkp.c (hkp_ask_import, + hkp_export, hkp_search), keyserver.c (parse_keyserver_options, + parse_keyserver_uri, keyserver_work, keyserver_refresh): Make the + "x-broken-hkp" keyserver scheme into keyserver-option + "broken-http-proxy". Move honor_http_proxy into + keyserver_options. Canonicalize the three variations of "hkp", + "x-hkp", and "x-broken-hkp" into "hkp". + +2002-06-07 Stefan Bellon <sbellon@sbellon.de> + + * g10.c [__riscos__]: Added --attribute-file to do the same as + --attribute-fd, but with a filename not a fd as argument. + Added magic symbol for RISC OS to use different memory management. + + * gpgv.c [__riscos__]: Added magic symbol for RISC OS to use + different memory management. + +2002-06-06 David Shaw <dshaw@jabberwocky.com> + + * main.h, g10.c (main), keygen.c (build_personal_digest_list): Put + in a default digest preference list consisting of SHA-1, followed + by every other installed digest except MD5. Note this is the same + as having no digest preference at all except for SHA-1 being + favored. + + * options.h, g10.c (main), keygen.c (keygen_set_std_prefs), + pkclist.c (select_algo_from_prefs): Split + --personal-preference-list into three: + --personal-{cipher|digest|compress}-preferences. This allows a + user to set one without affecting another (i.e. setting only a + digest pref doesn't imply an empty cipher pref). + + * exec.c (exec_read): This is a safer way of guessing the return + value of system(). Noted by Stefan Bellon. + +2002-06-05 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (parse_hkp_index): Be more robust with keyservers + returning very unparseable responses. + + * exec.c (exec_read): Catch and display an error when the remote + process exits unnaturally (i.e. segfault) so the user knows what + happened. Also fix exec_write stub which has a different number + of arguments now. + +2002-06-05 Timo Schulz <ts@winpt.org> + + * encode.c (encode_simple): Ignore the new mode for RFC1991. + * mainproc.c (symkey_decrypt_sesskey): Better check for weird + keysizes. + +2002-06-05 Timo Schulz <ts@winpt.org> + + * encode.c (encode_sesskey): New. + (encode_simple): Use it here. But by default we use the compat + mode which supress to generate encrypted session keys. + +2002-06-05 Timo Schulz <ts@winpt.org> + + * mainproc.c (symkey_decrypt_sesskey): New. + (proc_symkey_enc): Support for encrypted session keys. + +2002-06-04 David Shaw <dshaw@jabberwocky.com> + + * sign.c (hash_for, sign_file): When encrypting and signing at the + same time, consult the various hash prefs to pick a hash algorithm + to use. Pass in a 160-bit hint if any of the signing keys are + DSA. + + * keydb.h, pkclist.c (select_algo_from_prefs, algo_available): + Pass a "hints" opaque pointer in to let the caller give hints as + to what algorithms would be acceptable. The only current hint is + for PREFTYPE_HASH to require a 160-bit hash for DSA. Change all + callers in encode.c (encode_crypt, encrypt_filter) and sign.c + (sign_file). If we settle on MD5 as the best algorithm based + solely on recepient keys and SHA1 is also a possibility, use SHA1 + unless the user intentionally chose MD5. This is as per 2440:13. + + * exec.c (make_tempdir): Fix duplicated filename problem. + +2002-06-03 David Shaw <dshaw@jabberwocky.com> + + * packet.h, parse-packet.c (enum_sig_subpkt): Report back from + enum_sig_subpkt when a subpacket is critical and change all + callers in keylist.c (show_policy_url, show_notation), mainproc.c + (print_notation_data), and pkclist.c (do_show_revocation_reason). + + * keylist.c (show_policy_url, show_notation): Display if the + policy or notation is critical. + +2002-06-03 David Shaw <dshaw@jabberwocky.com> + + * main.h, g10.c (main), keylist.c (dump_attribs, set_attrib_fd, + list_keyblock_print, list_keyblock_colon), status.h, status.c + (get_status_string): New --attribute-fd feature to dump the + contents of attribute subpackets for frontends. If --status-fd is + also used, then a new status tag ATTRIBUTE is provided for each + subpacket. + + * packet.h, getkey.c (fixup_uidnode, merge_selfsigs_main, + merge_selfsigs_subkey), parse-packet.c (setup_user_id): Keep track + of the expiration time of a user ID, and while we're at it, use + the expired flag from the selfsig rather than reparsing the + SIG_EXPIRE subpacket. + + * photoid.c (generate_photo_id): When adding a new photo ID, + showing the photo for confirmation is not safe when noninteractive + since the "user" may not be able to dismiss a viewer window. + Noted by Timo Schulz. + +2002-06-03 David Shaw <dshaw@jabberwocky.com> + + * options.skel: Sample photo viewers for Win32. + + * misc.c (pct_expando): Use the seckey for %k/%K if the pubkey is + not available. + + * photoid.h, photoid.c (show_photos): Include the seckey in case a + user tries to view a photo on a secret key, and change all callers + in keyedit.c (menu_showphoto), keylist.c (list_keyblock_print), + and photoid.c (generate_photo_id). + +2002-06-02 David Shaw <dshaw@jabberwocky.com> + + * photoid.c (show_photos): Work properly when not called with a + public key. + +2002-05-31 David Shaw <dshaw@jabberwocky.com> + + * sign.c (mk_notation_and_policy): Free unneeded buffer. + + * hkp.c (parse_hkp_index): Properly handle the '&' character + (i.e. "&amp;") in HKP responses. + + * getkey.c (merge_selfsigs_main): Fix reversed expiration time + check with self-sigs. + + * keyedit.c (sign_uids): When making a new self-sig on a v3 key, + make a v3 self-sig unless it is currently a v3 self-sig being + promoted to v4. + +2002-05-31 Timo Schulz <ts@winpt.org> + + * pkclist.c (do_show_revocation_reason): Don't use capital + letters for non-interactive output. + (show_revocation_reason): Now it is global. + * pubkey-enc.c (get_it): Show if the key has been revoked. + +2002-05-30 David Shaw <dshaw@jabberwocky.com> + + * sign.c (write_signature_packets, sign_file, clearsign_file, + sign_symencrypt_file): Make a v4 signature if a policy URL or + notation is set, unless v3 sigs are forced via rfc1991 or + force-v3-sigs. Also remove some doubled code and clarify an error + message (we don't sign in PGP2 mode - just detach-sign). + + * parse-packet.c (parse_one_sig_subpkt): Add KS_FLAGS to the "any + size" section. + +2002-05-29 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (keygen_set_std_prefs, add_feature_mdc): Use "mdc" and + "no-mdc" in the prefs string to allow switching on and off the MDC + feature. This is needed to properly export a key from GnuPG for + use on PGP which does not support MDC - without this, MDC-capable + implementations will still try and generate MDCs which will break + PGP. + + * keygen.c (keygen_get_std_prefs): Show "[mdc]" in prefs string if + it is enabled. + + * options.h, g10.c (main), cipher.c (write_header), keygen.c + (keygen_set_std_prefs): For consistency, allow the user to specify + mdc/no-mdc in the --personal-preference-list. If disabled, it + acts just like --disable-mdc. + +2002-05-29 David Shaw <dshaw@jabberwocky.com> + + * options.h, exec.c: Add some debugging info, using the 1024 debug + flag. + + * exec.c (win_system): New system()-like function for win32 that + does not return until the child process terminates. Of course, + this doesn't help if the process itself exits before it is + finished. + +2002-05-29 Werner Koch <wk@gnupg.org> + + * encode.c (encode_simple): Intialize PKT when --no-literal is used. + + * keyedit.c (show_key_with_all_names_colon): Renamed the record + for revocation keys to "rvk". + +2002-05-27 Werner Koch <wk@gnupg.org> + + * keyedit.c (show_key_with_all_names_colon): New. + (show_key_with_all_names): Divert to new function when required. + Sanitize printing of revoker name. + +2002-05-27 David Shaw <dshaw@jabberwocky.com> + + * build-packet.c (build_sig_subpkt): Handle setting sig flags for + certain subpacket types (notation, policy url, exportable, + revocable). keyedit.c (sign_mk_attrib): Flags no longer need to + be set here. + + * packet.h, parse-packet.c (parse_one_sig_subpkt), build-packet.c + (build_sig_subpkt): Call parse_one_sig_subpkt to sanity check + buffer lengths before building a sig subpacket. + +2002-05-26 David Shaw <dshaw@jabberwocky.com> + + * sign.c (mk_notation_and_policy): Include secret key to enable %s + expandos, and pass notations through pct_expando as well. + + * main.h, misc.c (pct_expando): Add %s and %S expandos for + signer's keyid. + +2002-05-25 David Shaw <dshaw@jabberwocky.com> + + * g10.c (strusage, build_list): Add compress algorithms to + --version list. Show algorithm numbers when --verbose --version + is done. + +2002-05-22 David Shaw <dshaw@jabberwocky.com> + + * options.h, main.h, keygen.c (keygen_set_set_prefs, + keygen_get_std_prefs, keygen_upd_std_prefs), keyedit.c + (keyedit_menu), g10.c (main), pkclist.c (select_algo_from_prefs): + Add --personal-preference-list which allows the user to factor in + their own preferred algorithms when the preference lists are + consulted. Obviously, this does not let the user violate a + recepient's preferences (and the RFC) - this only influences the + ranking of the agreed-on (and available) algorithms from the + recepients. Suggested by David Hollenberg. + + * options.h, keygen.c (keygen_set_std_prefs), g10.c (main): Rename + --preference-list to --default-preference-list (as that is what it + really is), and make it a true default in that if the user selects + "default" they get this list and not the compiled-in list. + +2002-05-22 Werner Koch <wk@gnupg.org> + + * g10.c (main): Add missing LF in a info printout and made it + translatable. Noted by Michael Tokarev. + +2002-05-21 Werner Koch <wk@gnupg.org> + + * g10.c (main): Removed the undef of USE_SHM_COPROCESSING which + was erroneously introduced on 2002-01-09. + + * signal.c (got_fatal_signal): Don't write the Nul to stderr. + Reported by David Hollenberg. + +2002-05-18 David Shaw <dshaw@jabberwocky.com> + + * main.h, g10.c (main), revoke.c (gen_desig_revoke): Generate a + designated revocation via --desig-revoke + + * keyedit.c (keyedit_menu, menu_addrevoker): New "addrevoker" + command to add a designated revoker to a key. + +2002-05-17 David Shaw <dshaw@jabberwocky.com> + + * gpgv.c: Add stub for get_ownertrust(). + + * g10.c (main): --allow-freeform-uid should be implied by + OpenPGP. Add --no-allow-freeform-uid. + + * keyedit.c (sign_uids): Issue a warning when signing a + non-selfsigned uid. + + * getkey.c (merge_selfsigs_main): If a key has no selfsigs, and + allow-non-selfsigned-uid is not set, still try and make the key + valid by checking all uids for a signature from an ultimately + trusted key. + +2002-05-16 David Shaw <dshaw@jabberwocky.com> + + * main.h, keygen.c (keygen_add_revkey): Add revocation key + subpackets to a signature (callable by + make_keysig_packet). (write_direct_sig): Write a 1F direct key + signature. (parse_revocation_key): Parse a string in + algo:fpr:sensitive format into a revocation + key. (get_parameter_revkey, do_generate_keypair): Call above + functions when prompted from a batch key generation file. + + * build-packet.c (build_sig_subpkt): Allow multiple revocation key + subpackets in a single sig. + + * keydb.h, getkey.c (get_seckey_byfprint): Same as + get_pubkey_byfprint, except for secret keys. We only know the + fingerprint of a revocation key, so this is needed to retrieve the + secret key needed to issue a revokation. + + * packet.h, parse-packet.c (parse_signature, parse_revkeys): Split + revkey parsing off into a new function that can be used to reparse + after manipulating the revkey list. + + * sign.c (make_keysig_packet): Ability to make 1F direct key + signatures. + +2002-05-15 David Shaw <dshaw@jabberwocky.com> + + * options.skel: keyserver.pgp.com is gone, so list pgp.surfnet.nl + as a sample LDAP server instead. + + * getkey.c (merge_selfsigs_main): Properly handle multiple + revocation keys in a single packet. Properly handle revocation + keys that are in out-of-order packets. Remove duplicates in + revocation key list. + +2002-05-14 Timo Schulz <ts@winpt.org> + + * exec.c (make_tempdir) [MINGW32]: Added missing '\'. + +2002-05-14 Stefan Bellon <sbellon@sbellon.de> + + * exec.c (make_tempdir): Make use of EXTSEP_S instead of hardcoded + dot as extension separator. + +2002-05-13 David Shaw <dshaw@jabberwocky.com> + + * photoid.c (show_photos): Use the long keyid as the filename for + the photo. Use the short keyid as the filename on 8.3 systems. + + * exec.h, exec.c (make_tempdir, exec_write, exec_finish): Allow + caller to specify filename. This should make things easier on + windows and macs where the file extension is required, but a whole + filename is even better. + + * keyedit.c (show_key_with_all_names, show_prefs): Show proper + prefs for a v4 key uid with no selfsig at all. + + * misc.c (check_permissions): Don't check permissions on + non-normal files (pipes, character devices, etc.) + +2002-05-11 Werner Koch <wk@gnupg.org> + + * mainproc.c (proc_symkey_enc): Avoid segv in case the parser + encountered an invalid packet. + + * keyserver.c (keyserver_export): Get confirmation before sending + all keys. + +2002-05-10 Stefan Bellon <sbellon@sbellon.de> + + * g10.c, hkp.c, keyedit.c, keyserver.c: Replaced all occurrances + of strcasecmp with ascii_strcasecmp and all occurrances of + strncasecmp with ascii_memcasecmp. + +2002-05-10 David Shaw <dshaw@jabberwocky.com> + + * packet.h, getkey.c (fixup_uidnode), keyedit.c (show_prefs): Show + assumed prefs for hash and compression as well as the cipher pref. + Show assumed prefs if there are no prefs at all on a v4 + self-signed key. + + * options.h, g10.c (main), sign.c (make_keysig_packet): New + --cert-digest-algo function to override the default key signing + hash algorithm. + +2002-05-09 David Shaw <dshaw@jabberwocky.com> + + * getkey.c (merge_selfsigs_main): Make sure the revocation key + list starts clean as this function may be called more than once + (e.g. from functions in --edit). + + * g10.c, encode.c (encode_crypt), sign.c (sign_file, + sign_symencrypt_file): Make --compress-algo work like the + documentation says. It should be like --cipher-algo and + --digest-algo in that it can override the preferences calculation + and impose the setting the user wants. No --compress-algo setting + allows the usual preferences calculation to take place. + + * main.h, compress.c (compress_filter): use new + DEFAULT_COMPRESS_ALGO define, and add a sanity check for compress + algo value. + +2002-05-08 David Shaw <dshaw@jabberwocky.com> + + * pkclist.c (select_algo_from_prefs): There is an assumed + compression preference for uncompressed data. + +2002-05-07 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), getkey.c (finish_lookup), pkclist.c + (algo_available): --pgp7, identical to --pgp6 except that it + permits a few algorithms that PGP 7 added: AES128, AES192, AES256, + and TWOFISH. Any more of these --pgpX flags, and it'll be time to + start looking at a generic --emulate-pgp X option. + + * export.c (do_export_stream): Warn the user when exporting a + secret key if it or any of its secret subkeys are protected with + SHA1 while simple_sk_checksum is set. + + * parse-packet.c (parse_key): Show when the SHA1 protection is + used in --list-packets. + + * options.h, build-packet.c (do_comment), g10.c (main): Rename + --no-comment as --sk-comments/--no-sk-comments (--no-comment still + works) and make the default be --no-sk-comments. + +2002-05-07 Werner Koch <wk@gnupg.org> + + * keygen.c (get_parameter_algo): Never allow generation of the + deprecated RSA-E or RSA-S flavors of PGP RSA. + (ask_algo): Allow generation of RSA sign and encrypt in expert + mode. Don't allow ElGamal S+E unless in expert mode. + * helptext.c: Added entry keygen.algo.rsa_se. + +2002-05-07 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (sign_uids): If --expert is set, allow re-signing a + uid to promote a v3 self-sig to a v4 one. This essentially + deletes the old v3 self-sig and replaces it with a v4 one. + + * packet.h, parse-packet.c (parse_key), getkey.c + (merge_keys_and_selfsig, merge_selfsigs_main): a v3 key with a v4 + self-sig must never let the v4 self-sig express a key expiration + time that extends beyond the original v3 expiration time. + +2002-05-06 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (sign_uids): When making a self-signature via "sign" + don't ask about sig level or expiration, and include the usual + preferences and such for v4 self-sigs. (menu_set_preferences): + Convert uids from UTF8 to native before printing. + + * keyedit.c (sign_uids): Convert uids from UTF8 to native before + printing. (menu_set_primary_uid): Show error if the user tries to + make a uid with a v3 self-sig primary. + +2002-05-05 David Shaw <dshaw@jabberwocky.com> + + * import.c (import_one): When merging with a key we already have, + don't let a key conflict (same keyid but different key) stop the + import: just skip the bad key and continue. + + * exec.c (make_tempdir): Under Win32, don't try environment + variables for temp directories - GetTempDir tries environment + variables internally, and it's better not to second-guess it in + case MS adds some sort of temp dir handling to Windows at some + point. + +2002-05-05 Timo Schulz <ts@winpt.org> + + * mainproc.c (proc_symkey_enc): Don't ask for a passphrase + in the list only mode. + +2002-05-05 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_refresh): --refresh-keys implies + --merge-only so as not to import keys with keyids that match the + ones being refreshed. Noted by Florian Weimer. + +2002-05-04 Stefan Bellon <sbellon@sbellon.de> + + * free-packet.c (copy_public_key): Don't call m_alloc(0), therefore + added consistency check for revkey and numrefkeys. + + * getkey.c (check_revocation_keys): Added consistency check for + revkey and numrefkeys. + + * keyedit.c (show_key_with_all_names): Likewise. + +2002-05-03 David Shaw <dshaw@jabberwocky.com> + + * photoid.c: Provide default image viewer for Win32. + + * misc.c (pct_expando): %t means extension, not name ("jpg", not + "jpeg"). + + * keyserver.c (keyserver_spawn), photoid.c (show_photos), exec.h, + exec.c: Allow the caller to determine the temp file extension when + starting an exec_write and change all callers. + + * keyedit.c (sign_uids): Nonrevocable key signatures cause an + automatic promotion to v4. + + * exec.c: Provide stubs for exec_ functions when NO_EXEC is + defined. + +2002-05-02 David Shaw <dshaw@jabberwocky.com> + + * photoid.h, photoid.c (parse_image_header, image_type_to_string): + Useful functions to return data about an image. + + * packet.h, parse-packet.c (make_attribute_uidname, + parse_attribute_subpkts, parse_attribute), photoid.h, photoid.c + (show_photos): Handle multiple images in a single attribute + packet. + + * main.h, misc.c (pct_expando), sign.c (mk_notation_and_policy), + photoid.c (show_photos): Simpler expando code that does not + require using compile-time string sizes. Call + image_type_to_string to get image strings (i.e. "jpg", + "image/jpeg"). Change all callers. + + * keyedit.c (menu_showphoto), keylist.c (list_keyblock_print): + Allow viewing multiple images within a single attribute packet. + + * gpgv.c: Various stubs for link happiness. + +2002-05-02 David Shaw <dshaw@jabberwocky.com> + + * build-packet.c (build_sig_subpkt), keyedit.c (sign_uids), + options.h, sign.c (mk_notation_and_policy), g10.c (main, + add_notation_data, add_policy_url (new), check_policy_url + (removed)): Allow multiple policy URLs on a given signature. + Split "--notation-data" into "--cert-notation" and + "--sig-notation" so the user can set different policies for key + and data signing. For backwards compatibility, "--notation-data" + sets both, as before. + +2002-05-02 Werner Koch <wk@gnupg.org> + + * options.skel: Removed the comment on trusted-keys because this + option is now deprecated. + +2002-05-01 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_adduid): 2440bis04 says that multiple attribute + packets on a given key are legal. + + * keyserver.c (keyserver_refresh): the fake v3 keyid hack applies + to "mailto" URLs as well since they are also served by pksd. + +2002-04-29 Werner Koch <wk@gnupg.org> + + Added a copyright year for files changed this year. + +2002-04-25 Werner Koch <wk@gnupg.org> + + * g10.c, options.h: New options --display, --ttyname, --ttytype, + --lc-ctype, --lc-messages to be used with future versions of the + gpg-agent. + * passphrase.c (agent_send_option,agent_send_all_options): New. + (agent_open): Send options to the agent. + + * trustdb.c (update_ownertrust, clear_ownertrust): Do an explicit + do_sync because revalidation_mark does it only if when the + timestamp actually changes. + +2002-04-23 David Shaw <dshaw@jabberwocky.com> + + * main.h, keygen.c (do_generate_keypair), keylist.c + (print_signature_stats, list_all, list_one, list_keyblock, + list_keyblock_print, list_keyblock_colon): After generating a new + key, show the key information (name, keyid, fingerprint, etc.) + Also do not print uncheckable signatures (missing key..) in + --check-sigs. Print statistics (N missing keys, etc.) after + --check-sigs. + + * keyedit.c (sign_uids): When signing a key with an expiration + date on it, the "Do you want your signature to expire at the same + time?" question should default to YES. + +2002-04-22 David Shaw <dshaw@jabberwocky.com> + + * parse-packet.c (parse_plaintext), packet.h, plaintext.c + (handle_plaintext): Fix bug in handling literal packets with + zero-length data (no data was being confused with partial body + length). + + * misc.c (pct_expando), options.skel: %t means extension ("jpg"). + %T means MIME type ("image/jpeg"). + + * import.c (import_one): Only trigger trust update if the keyring + is actually changed. + + * export.c (do_export_stream): Missing a m_free. + +2002-04-22 Stefan Bellon <sbellon@sbellon.de> + + * keyid.c (expirestr_from_sk, expirestr_from_sig): Added _() to + string constant. + + * exec.c (make_tempdir) [__riscos__]: Better placement of + temporary file. + +2002-04-20 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (generate_subkeypair): 2440bis04 adds that creating + subkeys on v3 keys is a MUST NOT. + + * getkey.c (finish_lookup): The --pgp6 "use the primary key" + behavior should only apply while data signing and not encryption. + Noted by Roger Sondermann. + +2002-04-19 Werner Koch <wk@gnupg.org> + + * keygen.c (keygen_set_std_prefs): Put back 3DES because the RFC + says it is good form to do so. + +2002-04-19 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_deluid): Only cause a trust update if we delete + a non-revoked user id. + + * hkp.c (hkp_ask_import), keyserver.c (parse_keyserver_options, + keyserver_spawn), options.h: Remove fast-import keyserver option + (no longer meaningful). + + * g10.c (main), keyedit.c (sign_uids), options.h: Change + --default-check-level to --default-cert-check-level as it makes + clear what it operates on. + + * g10.c (main): --pgp6 also implies --no-ask-sig-expire. + + * delkey.c (do_delete_key): Comment. + + * keyedit.c (sign_uids, keyedit_menu, menu_deluid, menu_delsig, + menu_expire, menu_revsig, menu_revkey): Only force a trustdb check + if we did something that changes it. + + * g10.c: add "--auto-check-trustdb" to override a + "--no-auto-check-trustdb" + +2002-04-19 Werner Koch <wk@gnupg.org> + + * tdbio.c (tdbio_write_nextcheck): Return a status whether the + stamp was actually changed. + * trustdb.c (revalidation_mark): Sync the changes. Removed the + sync operation done by its callers. + (get_validity): Add logic for maintaining a pending_check flag. + (clear_ownertrust): New. + + * keyedit.c (sign_uids): Don't call revalidation_mark depending on + primary_pk. + (keyedit_menu): Call revalidation_mark after "trust". + (show_key_with_all_names): Print a warning on the wrong listed key + validity. + + * delkey.c (do_delete_key): Clear the owenertrust information when + deleting a public key. + +2002-04-18 Werner Koch <wk@gnupg.org> + + * seskey.c (encode_md_value): Print an error message if a wrong + digest algorithm is used with DSA. Changed all callers to cope + with a NULL return. Problem noted by Imad R. Faiad. + +2002-04-18 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (mark_usable_uid_certs): Properly handle nonrevocable + signatures that can expire. In short, the only thing that can + override an unexpired nonrevocable signature is another unexpired + nonrevocable signature. + + * getkey.c (finish_lookup): Always use primary signing key for + signatures when --pgp6 is on since pgp6 and 7 do not understand + signatures made by signing subkeys. + +2002-04-18 Werner Koch <wk@gnupg.org> + + * trustdb.c (validate_keys): Never schedule a nextcheck into the + past. + (validate_key_list): New arg curtime use it to set next_expire. + (validate_one_keyblock): Take the current time from the caller. + (clear_validity, reset_unconnected_keys): New. + (validate_keys): Reset all unconnected keys. + + * getkey.c (premerge_public_with_secret): Fixed 0x12345678! syntax + for use with secret keys. + (lookup): Advance the searchmode after a search FIRST. + + * seckey-cert.c (do_check): Always calculate the old checksum for + use after unprotection. + + * g10.c, options.skel: New option --no-escape-from. Made + --escape-from and --force-v3-sigs the default and removed them + from the options skeleton. + +2002-04-16 Werner Koch <wk@gnupg.org> + + * parse-packet.c (parse_key): Support a SHA1 checksum as per + draft-rfc2440-bis04. + * packet.h (PKT_secret_key): Add field sha1chk. + * seckey-cert.c (do_check): Check the SHA1 checksum + (protect_secret_key): And create it. + * build-packet.c (do_secret_key): Mark it as sha-1 protected. + * g10.c, options.h: New option --simple-sk-checksum. + +2002-04-13 David Shaw <dshaw@jabberwocky.com> + + * parse-packet.c (parse_signature): Minor fix - signatures should + expire at their expiration time and not one second later. + + * keygen.c (proc_parameter_file): Allow specifying preferences + string (i.e. "s5 s2 z1 z2", etc) in a batchmode key generation + file. + + * keyedit.c (keyedit_menu): Print standard error message when + signing a revoked key (no new translation). + + * getkey.c (merge_selfsigs): Get the default set of key prefs from + the real (not attribute) primary uid. + +2002-04-12 David Shaw <dshaw@jabberwocky.com> + + * pkclist.c (build_pk_list): Fix bug that allowed a key to be + selected twice in batch mode if one instance was the default + recipient and the other was an encrypt-to. Noted by Stefan + Bellon. + + * parse-packet.c (dump_sig_subpkt): Show data in trust and regexp + sig subpackets. + + * keyedit.c (keyedit_menu): Use new function real_uids_left to + prevent deleting the last real (i.e. non-attribute) uid. Again, + according to the attribute draft. (menu_showphoto): Make another + string translatable. + +2002-04-11 David Shaw <dshaw@jabberwocky.com> + + * build-packet.c (build_sig_subpkt): Delete subpackets from both + hashed and unhashed area on update. (find_subpkt): No longer + needed. + + * keyedit.c (sign_uids): With --pgp2 on, refuse to sign a v3 key + with a v4 signature. As usual, --expert overrides. Try to tweak + some strings to a closer match so they can all be translated in + one place. Use different helptext keys to allow different help + text for different questions. + + * keygen.c (keygen_upd_std_prefs): Remove preferences from both + hashed and unhashed areas if they are not going to be used. + +2002-04-10 David Shaw <dshaw@jabberwocky.com> + + * misc.c (pct_expando), options.skel: Use %t to indicate type of a + photo ID (in this version, it's always "jpeg"). Also tweak string + expansion loop to minimize reallocs. + + * mainproc.c (do_check_sig): Variable type fix. + + * keyedit.c (menu_set_primary_uid): Differentiate between true + user IDs and attribute user IDs when making one of them primary. + That is, if we are making a user ID primary, we alter user IDs. + If we are making an attribute packet primary, we alter attribute + packets. This matches the language in the latest attribute packet + draft. + + * keyedit.c (sign_uids): No need for the empty string hack. + + * getkey.c (fixup_uidnode): Only accept preferences from the + hashed segment of the self-sig. + +2002-04-10 Werner Koch <wk@gnupg.org> + + * tdbio.c (migrate_from_v2): Fixed the offset to read the old + ownertrust value and only add entries to the table if we really + have a value. + +2002-04-08 David Shaw <dshaw@jabberwocky.com> + + * status.h, status.c (get_status_string): Add KEYEXPIRED, EXPSIG, + and EXPKEYSIG. Add "deprecated-use-keyexpired-instead" to + SIGEXPIRED. + + * sig-check.c (do_check): Start transition from SIGEXPIRED to + KEYEXPIRED, since the actual event is signature verification by an + expired key and not an expired signature. (do_signature_check, + packet.h): Rename as signature_check2, make public, and change all + callers. + + * mainproc.c (check_sig_and_print, do_check_sig): Use status + EXPSIG for an expired, but good, signature. Add the expiration + time (or 0) to the VALIDSIG status line. Use status KEYEXPSIG for + a good signature from an expired key. + + * g10.c (main): remove checks for no arguments now that argparse + does it. + +2002-04-06 Werner Koch <wk@gnupg.org> + + * keyring.c (keyring_get_keyblock): Disable the keylist mode here. + + * encode.c (encode_simple, encode_crypt): Only test on compressed + files if a compress level was not explicity set. + + * keygen.c (keygen_set_std_prefs): Removed Blowfish and Twofish + from the list of default preferences, swapped the preferences of + RMD160 and SHA1. Don't include a preference to 3DES unless the + IDEA kludge gets used. + + * free-packet.c (free_packet): call free_encrypted also for + PKT_ENCRYPTED_MDC. + + * compress.c (release_context): New. + (handle_compressed): Allocate the context and setup a closure to + release the context. This is required because there is no + guarabntee that the filter gets popped from the chain at the end + of the function. Problem noted by Timo and probably also the + cause for a couple of other reports. + (compress_filter): Use the release function if set. + + * tdbio.c [__CYGWIN32__]: Don't rename ftruncate. Noted by + Disastry. + + * parse-packet.c (parse_signature): Put parens around a bit test. + + * exec.c (make_tempdir): Double backslash for TMP directory + creation under Windows. Better strlen the DIRSEP_S constants for + allocation measurements. + + * decrypt.c (decrypt_messages): Release the passphrase aquired + by get_last_passphrase. + +2002-04-02 Werner Koch <wk@gnupg.org> + + * Makefile.am (EXTRA_DIST): Removed OPTIONS an pubring.asc - they + are no longer of any use. + +2002-04-03 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (parse_keyserver_options): fix auto-key-retrieve to + actually work as a keyserver-option (noted by Roger Sondermann). + + * keylist.c (reorder_keyblock): do not reorder the primary + attribute packet - the first user ID must be a genuine one. + +2002-03-31 David Shaw <dshaw@jabberwocky.com> + + * keylist.c (list_keyblock_colon): Fix ownertrust display with + --with-colons. + + * keygen.c (generate_user_id), photoid.c (generate_photo_id): + Properly initialize the user ID refcount. A few more "y/n" -> + "y/N" in photoid.c. + + * keyedit.c (ask_revoke_sig): Warn the user if they are about to + revoke an expired sig (not a problem, but they should know). Also + tweak a few prompts to change "y/n" to "y/N", which is how most + other prompts are written. + + * keyserver.c (keyserver_search_prompt): Control-d escapes the + keyserver search prompt. + + * pkclist.c (show_revocation_reason & callers): If a subkey is + considered revoked solely because the parent key is revoked, print + the revocation reason from the parent key. + + * trustdb.c (get_validity): Allow revocation/expiration to apply + to a uid/key with no entry in the trustdb. + +2002-03-29 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (printunquoted): unquote backslashes from keyserver + searches + + * hkp.c (write_quoted): quote backslashes from keyserver searches + +2002-03-26 Werner Koch <wk@gnupg.org> + + * keygen.c (ask_keysize): Removed the warning for key sizes > 1536. + +2002-03-25 Werner Koch <wk@gnupg.org> + + * keyedit.c (sign_uids): Use 2 strings and not a %s so that + translations can be done the right way. + * helptext.c: Fixed small typo. + +2002-03-23 David Shaw <dshaw@jabberwocky.com> + + * import.c (append_uid, merge_sigs): it is okay to import + completely non-signed uids now (with --allow-non-selfsigned-uid). + + * getkey.c (get_primary_uid, merge_selfsigs_main): do not choose + an attribute packet (i.e. photo) as primary uid. This prevents + oddities like "Good signature from [image of size 2671]". This is + still not perfect (one can still select an attribute packet as + primary in --edit), but is closer to the way the draft is going. + + * g10.c (build_list): algorithms should include 110. + + * g10.c (main): --pgp2 implies --no-ask-sig-expire and + --no-ask-cert-expire as those would cause a v4 sig/cert. + + * armor.c (is_armor_header): be more lenient in what constitutes a + valid armor header (i.e. -----BEGIN blah blah-----) as some + Windows programs seem to add spaces at the end. --openpgp makes + it strict again. + +2002-03-18 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_search_prompt): Properly handle a "no + keys found" case from the internal HKP code (external HKP is ok). + Also, make a COUNT -1 (i.e. streamed) keyserver response a little + more efficient. + + * g10.c (main): Add --no-allow-non-selfsigned-uid + +2002-03-17 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): --openpgp implies --allow-non-selfsigned-uid. + + * getkey.c (merge_selfsigs_main): If none of the uids are primary + (because none are valid) then pick the first to be primary (but + still invalid). This is for cosmetics in case some display needs + to print a user ID from a non-selfsigned key. Also use + --allow-non-selfsigned-uid to make such a key valid and not + --always-trust. The key is *not* automatically trusted via + --allow-non-selfsigned-uid. + + * mainproc.c (check_sig_and_print): Make sure non-selfsigned uids + print [uncertain] on verification even though one is primary now. + + * getkey.c (merge_selfsigs): If the main key is not valid, then + neither are the subkeys. + + * import.c (import_one): Allow --allow-non-selfsigned-uid to work + on completely unsigned keys. Print the uids in UTF8. Remove + mark_non_selfsigned_uids_valid(). + + * keyedit.c (show_key_with_all_names): Show revocation key as + UTF8. + + * sign.c (clearsign_file): Allow --not-dash-escaped to work with + v3 keys. + +2002-03-14 Werner Koch <wk@gnupg.org> + + * main.h: Changed the default algorithms to CAST5 and SHA1. + +2002-03-13 David Shaw <dshaw@jabberwocky.com> + + * import.c (chk_self_sigs): Show which user ID a bad self-sig + (invald sig or unsupported public key algorithm) resides on. + + * import.c (chk_self_sigs): any valid self-sig should mark a user + ID or subkey as valid - otherwise, an attacker could DoS the user + by inventing a bogus invalid self-signature. + +2002-03-07 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): make a few more strings translatable. + + * options.h, options.skel, g10.c (main), gpgv.c, mainproc.c + (check_sig_and_print), keyserver.c (parse_keyserver_options): + --auto-key-retrieve should really be a keyserver-option variable. + + * import.c (revocation_present): new function to print a warning + if a key is imported that has been revoked by designated revoker, + but the designated revoker is not present to verify the + revocation. If keyserver-options auto-key-retrieve is set, try + and fetch the designated revoker from the keyserver. + + * import.c (import_one): call revocation_present after importing a + new key. Note that this applies to --import, --recv-keys, and + --search-keys. + + * keyserver-internal.h, keyserver.c (keyserver_import_fprint): + import via fingerprint (for revocation keys). + + * keyserver.c (keyserver_import_keyid): much simpler + implementation now that we're using KEYDB_SEARCH_DESC internally. + +2002-03-04 David Shaw <dshaw@jabberwocky.com> + + * revoke.c (gen_revoke): do not prompt for revocation reason for + v3 revocations (unless force-v4-certs is on) since they wouldn't + be used anyway. + + * keyedit.c (menu_revsig): show the status of the sigs + (exportable? revocable?) to the user before prompting for which + sig to revoke. Also, make sure that local signatures get local + revocations. + + * keyedit.c (ask_revoke_sig): remind the user which sigs are + local. + + * g10.c (main): Add "exec-path" variable to override PATH for + execing programs. + + * export.c (do_export_stream): properly check return code from + classify_user_id to catch unclassifiable keys. + +2002-03-03 David Shaw <dshaw@jabberwocky.com> + + * parse-packet.c (parse_signature): variable type tweak for RISC + OS (from Stefan) + +2002-02-28 David Shaw <dshaw@jabberwocky.com> + + * getkey.c (check_revocation_keys): New function to check a + revocation against a list of potential revocation keys. Note the + loop-breaking code here. This is to prevent blowing up if A is + B's revocation key, while B is also A's. Note also that this is + written so that a revoked revoker can still issue revocations: + i.e. If A revokes B, but A is revoked, B is still revoked. I'm + not completely convinced this is the proper behavior, but it + matches how PGP does it. It does at least have the advantage of + much simpler code - my first version of this had lots of loop + maintaining code so you could chain revokers many levels deep and + if D was revoked, C was not, which meant that B was, and so on. + It was sort of scary, actually. + + * getkey.c (merge_selfsigs_main): Add any revocation keys onto the + pk. This is particularly interesting since we normally only get + data from the most recent 1F signature, but you need multiple 1F + sigs to properly handle revocation keys (PGP does it this way, and + a revocation key could be marked "sensitive" and hence in a + different signature). Also, if a pk has a revocation key set, + check for revocation sigs that were not made by us - if made by a + valid revocation key, mark the pk revoked. + + * packet.h, getkey.c (cache_public_key): do not cache key if + "dont_cache" is set. This allows the revocation key code to look + up a key and return information that may be inaccurate to prevent + loops without caching the fake data. + + * packet.h, sig-check.c (do_signature_check): Record if a + signature was made by a revoked pk. + + * packet.h, parse-packet.c (parse_one_sig_subpkt, + can_handle_critical, parse_signature): Get revocation key + information out of direct sigs. + + * keylist.c (list_keyblock_print): don't assume that the presence + of a 0x20 signature means the key is revoked. With revocation + keys, this may not be true if the revocation key is not around to + verify it or if verification failed. Also, 0x1F should get listed + as "sig", and not "unexpected signature class". + + * keyedit.c (show_key_with_all_names): Add a flag for printing + revoker information and change all callers. + + * import.c (merge_blocks): merge in any new direct key (0x1F) + sigs. + + * import.c (import_revoke_cert): don't keep processing after a + revocation is rejected. + + * import.c (delete_inv_parts): Allow importing a revocation + signature even if it was not issued by the key. This allows a + revocation key to issue it. Of course, the sig still needs to be + checked before we trust it. + + * free-packet.c (copy_public_key): Include a new copy of the + revocation keys when duping a pk. + + * free-packet.c (free_seckey_enc, release_public_key_parts): Free + any revocation keys that are attached to a sig or pk. + + * export.c (do_export_stream): Do not export signatures with + "sensitive" revocation keys in them. + +2002-02-27 David Shaw <dshaw@jabberwocky.com> + + * export.c (do_export_stream): Do not include v3 keys in a + --export-secret-subkeys export. + + * getkey.c (merge_selfsigs_main): If a key isn't valid (say, + because of no self-signature), allow --always-trust to force it + valid so it can be trusted. + +2002-02-25 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (hkp_ask_import), hkp.h, keyserver.c (all): treat key + lists internally as fingerprints when possible. All this is via + KEYDB_SEARCH_DESC - no point in reinventing the wheel. This allows + the helper program to search the keyserver by fingerprint if + desired (and the keyserver supports it). Note that automatic + fingerprint promotion during refresh only applies to v4 keys as a + v4 fingerprint can be easily changed into a long or short key id, + and a v3 cannot. + + * pubkey-enc.c, getkey.c, misc.c, main.h: Take two copies of + hextobyte() from pubkey-enc.c and getkey.c and make them into one + copy in misc.c. + +2002-02-22 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_search_prompt): Detect a "no keys found" + case even if the helper program does not explicitly say how many + keys were found. + + * hkp.c (parse_hkp_index): Bug fix - don't report non-revoked keys + as revoked in HKP key searches. + +2002-02-19 Werner Koch <wk@gnupg.org> + + * parse-packet.c (parse_trust): Made parsing more robust. + +2002-02-19 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (parse_hkp_index): Catch corruption in HKP index lines + (can be caused by broken or malicious keyservers). + + * keyserver.c (keyserver_work): Add KEYSERVER_NOT_SUPPORTED for + unsupported actions (say, a keyserver that has no way to search, + or a readonly keyserver that has no way to add). Also add a + USE_EXTERNAL_HKP define to disable the internal HKP keyserver + code. + +2002-02-14 Werner Koch <wk@gnupg.org> + + * g10.c: New option --no-use-agent. + + * pkclist.c (check_signatures_trust): Always print the warning for + unknown and undefined trust. Removed the did_add cruft. Reported + by Janusz A. Urbanowicz. + +2002-02-11 David Shaw <dshaw@jabberwocky.com> + + * hkp.c (parse_hkp_index): Bug fix - properly handle user IDs with + colons (":") in them while HKP searching. + +2002-02-09 David Shaw <dshaw@jabberwocky.com> + + * misc.c (pct_expando): More comments. + + * keydb.h, sign.c (mk_notation_and_policy): Clarify what is a sig + and what is a cert. A sig has sigclass 0x00, 0x01, 0x02, or 0x40, + and everything else is a cert. + + * g10.c (main), keyedit.c (keyedit_menu): Add a "nrlsign" for + nonrevocable and local key signatures. + + * g10.c (main): Add a --no-force-mdc to undo --force-mdc. + + * options.h, g10.c (main), cipher.c (write_header): Add a knob to + --disable-mdc/--no-disable-mdc. Off by default, of course, but is + used in --pgp2 and --pgp6 modes. + + * pkclist.c (build_pk_list): Allow specifying multiple users in + the "Enter the user ID" loop. Enter a blank line to stop. Show + each key+id as it is added. + + * keylist.c (show_policy_url), mainproc.c (print_notation_data): + It is not illegal (though possibly silly) to have multiple policy + URLs in a given signature, so print all that are present. + + * hkp.c (hkp_search): More efficient implementation of URL-ifying + code. + +2002-02-04 David Shaw <dshaw@jabberwocky.com> + + * main.h, misc.c (pct_expando): New function to generalize + %-expando processing in any arbitrary string. + + * photoid.c (show_photo): Call the new pct_expando function rather + than expand strings internally. + + * sign.c (mk_notation_and_policy): Show policy URLs and notations + when making a signature if show-policy/show-notation is on. + %-expand policy URLs during generation. This lets the user have + policy URLs of the form "http://notary.jabberwocky.com/keysign/%K" + which will generate a per-signature policy URL. + + * main.h, keylist.c (show_policy_url, show_notation): Add amount + to indent so the same function can be used in key listings as well + as during sig generation. Change all callers. + +2002-02-04 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c, options.h (parse_keyserver_options, keyidlist): + Workaround for the pksd and OKS keyserver bug that calculates v4 + RSA keyids as if they were v3. The workaround/hack is to fetch + both the v4 (e.g. 99242560) and v3 (e.g. 68FDDBC7) keyids. This + only happens for key refresh while using the HKP scheme and the + refresh-add-fake-v3-keyids keyserver option must be set. This + should stay off by default. + +2002-02-03 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_spawn): Bug fix - do not append keys to + each other when --sending more than one. + +2002-02-02 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c (main), keyedit.c (sign_uids), sign.c + (mk_notation_and_policy): Split "--set-policy-url" into + "--cert-policy-url" and "--sig-policy-url" so the user can set + different policies for key and data signing. For backwards + compatibility, "--set-policy-url" sets both, as before. + +2002-01-30 Werner Koch <wk@gnupg.org> + + * g10.c (main): --gen-random --armor does now output a base64 + encoded string. + +2002-01-28 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main), options.h, pkclist.c (algo_available): --pgp6 + flag. This is not nearly as involved as --pgp2. In short, it + turns off force_mdc, turns on no_comment, escape_from, and + force_v3_sigs, and sets compression to 1. It also restricts the + user to IDEA (if present), 3DES, CAST5, MD5, SHA1, and RIPEMD160. + See the comments above algo_available() for lots of discussion on + why you would want to do this. + +2002-01-27 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (keygen_set_std_prefs): Comment + + * keyedit.c (sign_uids): Bug fix - when signing with multiple + secret keys at the same time, make sure each key gets the sigclass + prompt. + + * exec.c (exec_finish): Close the iobuf and FILE before trying to + waitpid, so the remote process will get a SIGPIPE and exit. This + is only a factor when using a pipe to communicate. + + * exec.c (exec_write): Disable cache-on-close of the fd iobuf (is + this right? Why is a fd iobuf cached at all?) + +2002-01-26 Werner Koch <wk@gnupg.org> + + * g10.c, options.h: New option --gpg-agent-info + * passphrase.c (agent_open): Let it override the environment info. + * seckey-cert.c (check_secret_key): Always try 3 times when the + agent is enabled. + * options.skel: Describe --use-agent. + +2002-01-24 David Shaw <dshaw@jabberwocky.com> + + * pubkey-enc.c (is_algo_in_prefs, get_it): Only check preferences + against keys with v4 self sigs - there is really little point in + warning for every single non-IDEA message encrypted to an old key. + + * pkclist.c (select_algo_from_prefs): Only put in the fake IDEA + preference if --pgp2 is on. + + * mainproc.c (check_sig_and_print): Print "Expired" for expired + but good signatures (this still prints "BAD" for expired but bad + signatures). + +2002-01-23 David Shaw <dshaw@jabberwocky.com> + + * keygen.c (ask_keysize): Cosmetic: don't present a RSA signing + key as a "keypair" which can be 768 bits long (as RSA minimum is + 1024). + + * pubkey-enc.c (is_algo_in_prefs): Allow IDEA as a fake preference + for v3 keys with v3 selfsigs. + +2002-01-22 David Shaw <dshaw@jabberwocky.com> + + * packet.h, getkey.c (merge_selfsigs_main), pkclist.c + (select_algo_from_prefs): Implement the fake IDEA preference as + per RFC2440:12.1. This doesn't mean that IDEA will be used (the + plugin may not be present), but it does mean that a v3 key with a + v3 selfsig has an implicit IDEA preference instead of 3DES. v3 + keys with v4 selfsigs use preferences as normal. + + * encode.c (encode_crypt): if select_algo_from_prefs fails, this + means that we could not find a cipher that both keys like. Since + all v4 keys have an implicit 3DES preference, this means there is + a v3 key with a v3 selfsig in the list. Use 3DES in this case as + it is the safest option (we know the v4 key can handle it, and + we'll just hope the v3 key is being used in an implementation that + can handle it). If --pgp2 is on, warn the user what we're doing + since it'll probably break PGP2 compatibility. + + * g10.c (main): Do not force using IDEA for encrypted files in + --pgp2 mode - let the fake IDEA preference choose this for us for + better compatibility when encrypting to multiple keys, only some + of which are v3. + + * keygen.c (keygen_set_std_prefs): Put 3DES on the end of the + default cipher pref list (RFC2440: "...it is good form to place it + there explicitly."). If the user has the IDEA plugin installed, + put a preference for IDEA *after* 3DES to effectively disable its + use for everything except encrypting along with v3 keys. + + * encode.c, g10.c, sign.c: Change the PGP2 warning line from + "... will not be usable ..." to "... may not be usable ..." as the + user could be using one of the enhanced PGP2 variations. + + * helptext.c: Revise the sign_uid.class help text as suggested by + Stefan. + +2002-01-20 Werner Koch <wk@gnupg.org> + + * passphrase.c (passphrase_to_dek): Add tryagain_text arg to be + used with the agent. Changed all callers. + (agent_get_passphrase): Likewise and send it to the agent + * seckey-cert.c (do_check): New arg tryagain_text. + (check_secret_key): Pass the string to do_check. + * keygen.c (ask_passphrase): Set the error text is required. + * keyedit.c (change_passphrase): Ditto. + + * passphrase.c (agent_open): Disable opt.use_agent in case of a + problem with the agent. + (agent_get_passphrase): Ditto. + (passphrase_clear_cache): Ditto. + +2002-01-19 Werner Koch <wk@gnupg.org> + + * passphrase.c (agent_open): Add support for the new Assuan based + gpg-agent. New arg to return the used protocol version. + (agent_get_passphrase): Implemented new protocol here. + (passphrase_clear_cache): Ditto. + (readline): New. + +2002-01-15 Timo Schulz <ts@winpt.org> + + * encode.c (encode_crypt_files): Fail if --output is used. + + * g10.c: New command --decrypt-files. + + * decrypt.c (decrypt_messages): New. + +2002-01-09 David Shaw <dshaw@jabberwocky.com> + + * g10.c, misc.c, gpgv.c: move idea_cipher_warn to misc.c so gpgv.c + doesn't need a stub for it any longer. + + * g10.c (get_temp_dir), main.h: no longer used (it's in exec.c now) + + * g10.c (main), delkey.c (delete_keys), main.h : Allow + --delete-key (now --delete-keys, though --delete-key still works, + of course) to delete multiple keys in one go. This applies to + --delete-secret-key(s) and --delete-secret-and-public-key(s) as + well. + +2002-01-09 Timo Schulz <ts@winpt.org> + + * encode.c (encode_crypt_files): Now it behaves like verify_files. + + * g10.c (main): We don't need to check argc for encode_crypt_files + any longer. + +2002-01-09 Timo Schulz <ts@winpt.org> + + * exec.c: Include windows.h for dosish systems. + +2002-01-08 Timo Schulz <ts@winpt.org> + + * g10.c (main): New description for --encrypt-files. + +2002-01-08 Werner Koch <wk@gnupg.org> + + * g10.c (main): Must register the secring for encryption because + it is needed to figure out the default recipient. Reported by + Roger Sondermann. + +2002-01-05 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (menu_adduid): Require --expert before adding a photo + ID to a v3 key, and before adding a second photo ID to any key. + + * keyedit.c (keyedit_menu): Don't allow adding photo IDs in + rfc1991 or pgp2 mode. + + * getkey.c (merge_selfsigs_subkey): Permit v3 subkeys. Believe it + or not, this is allowed by rfc 2440, and both PGP 6 and PGP 7 work + fine with them. + + * g10.c, options.h, keyedit.c, sign.c: Move the "ask for + expiration" switch off of --expert, which was getting quite + overloaded, and onto ask-sig-expire and ask-cert-expire. Both + default to off. + + * g10.c (main): Change the default compression algo to 1, to be + more OpenPGP compliant (PGP also uses this, so it'll help with + interoperability problems as well). + + * encode.c (encode_crypt): Handle compression algo 2, since the + default is now 1. + + * build-packet.c (build_attribute_subpkt): Fix off-by-one error. + +2002-01-05 Werner Koch <wk@gnupg.org> + + * g10.c (main): Do not register the secret keyrings for certain + commands. + + * keydb.c (keydb_add_resource): Use access to test for keyring + existence. This avoids cached opened files which are bad under + RISC OS. + +2002-01-04 David Shaw <dshaw@jabberwocky.com> + + * sign.c (sign_file, sign_symencrypt_file): always use one-pass + packets unless rfc1991 is enabled. This allows a signature made + with a v3 key to work in PGP 6 and 7. Signatures made with v4 + keys are unchanged. + + * g10.c (main): Disallow non-detached signatures in PGP2 mode. + Move the "you must use files and not pipes" PGP2 warning up so all + the PGP2 stuff is together. + + * encode.c (encode_simple): Use the actual filesize instead of + partial length packets in the internal literal packet from a + symmetric message. This breaks PGP5(?), but fixes PGP2, 6, and 7. + It's a decent tradeoff. Note there was only an issue with + old-style RFC1991 symmetric messages. 2440-style messages in 6 + and 7 work with or without partial length packets. + +2002-01-03 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Removed --no-default-check-level option, as it is + not consistent with other "default" options. Plus, it is the same + as saying --default-check-level 0. + + * exec.c (exec_read): Disallow caching tempfile from child + process, as this keeps the file handle open and can cause unlink + problems on some platforms. + + * keyserver.c (keyserver_search_prompt): Minor tweak - don't + bother to transform keyids into textual form if they're just going + to be transformed back to numbers. + +2002-01-03 Timo Schulz <ts@winpt.org> + + * g10.c: New command --encrypt-files. + + * verify.c (print_file_status): Removed the static because + encode_crypt_files also uses this function. + + * main.h (print_files_status): New. + (encode_crypt_files): New. + + * encode.c (encode_crypt_files): New. + +2002-01-02 Stefan Bellon <sbellon@sbellon.de> + + * keyserver.c: Moved util.h include down in order to avoid + redefinition problems on RISC OS. + + * keyring.c (keyring_lock): Only lock keyrings that are writable. + + * keyring.c (keyring_update_keyblock): Close unused iobuf. + + * hkp.c (parse_hkp_index, hkp_search) [__riscos__]: Changed + unsigned char* to char* because of compiler issues. + + * exec.c (exec_finish) [__riscos__]: Invalidate close cache so + that file can be unlinked. + +2001-12-28 David Shaw <dshaw@jabberwocky.com> + + * g10.c (main): Use a different strlist to check extensions since + they need to be handled seperately now. + + * misc.c,main.h (check_permissions): Properly handle permission + and ownership checks on files in the lib directory + (e.g. /usr/local/lib/gnupg), which are owned by root and are + world-readable, and change all callers to specify extension or + per-user file. + + * photoid.c (show_photo), keyserver.c (keyserver_spawn): Bug fix - + don't call exec_finish if exec_write fails. + + * keyserver.c (keyserver_spawn): Look for OPTIONS from the + keyserver helper - specifically, a "OUTOFBAND" option for the + email keyserver. + + * mainproc.c (list_node), keylist.c (list_keyblock_colon), + import.c (delete_inv_parts), export.c (do_export_stream): Use + signature flags for exportability check rather than re-parsing the + subpacket. + + * keyid.c, keydb.h (get_lsign_letter): No longer needed. + +2001-12-27 David Shaw <dshaw@jabberwocky.com> + + * exec.c (exec_finish): Show errors when temp files cannot be + deleted for whatever reason. + + * exec.c (exec_read): Don't rely on WEXITSTATUS being present. + + * exec.c (make_tempdir): Add temp file creator for win32. Don't + create an incoming temp file if the exec is write-only. + + * keyserver.c (keyserver_spawn): Clean up error handling, for when + the spawn fails. + + * photoid.c (show_photo): Clean up error handling. + + * misc.c (check_permissions): Neaten. + +2001-12-25 David Shaw <dshaw@jabberwocky.com> + + * mkdtemp.c (mkdtemp): Add copyleft info and tweak the 'X' counter + to be a bit simpler. + + * keyserver.c, photoid.c: Remove unused headers left over from + when the exec functions lived there. + +2001-12-23 Timo Schulz <ts@winpt.org> + + * misc.c (check_permissions): Do not use it for W32 systems. + + * tdbio.c (migrate_from_v2): Define ftruncate as chsize() for W32. + + * mkdtemp.c: W32 support. + + * photoid.c: Ditto. + + * exec.c: Ditto. + +2001-12-22 David Shaw <dshaw@jabberwocky.com> + + * exec.c (make_tempdir): avoid compiler warning with const + + * mkdtemp.c (mkdtemp): catch the empty ("") string case in case + someone repurposes mkdtemp at some point. + + * photoid.c (generate_photo_id, show_photo): some type changes + from Stefan Bellon. + + * exec.c (make_tempdir): handle Win32 systems, suggested by Timo + Schulz. + +2001-12-22 Werner Koch <wk@gnupg.org> + + * encode.c (encode_simple, encode_crypt): i18n 2 strings. + +2001-12-22 Timo Schulz <ts@winpt.org> + + * encode.c (encode_simple, encode_crypt): Use is_file_compressed + to avoid to compress compressed files. + +2001-12-22 Werner Koch <wk@gnupg.org> + + * keyserver.c (keyserver_spawn): Removed some variables + declaration due to shadowing warnings. + + * build-packet.c (build_attribute_subpkt): s/index/idx/ to avoid + compiler warnig due to index(3). + + * getkey.c (get_ctx_handle): Use KEYDB_HANDLE as return value. + * keylist.c (list_one): Made resname const. + + * keyedit.c (keyedit_menu): Allow "addphoto" only when --openpgp is + not used. + + * options.skel: Changed one example photo viewer to qiv. + +2001-12-21 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: add exec.c, exec.h, photoid.c, and photoid.h + + * build-packet.c (build_attribute_subpkt): new function to build + the raw attribute subpacket. Note that attribute subpackets have + the same format as signature subpackets. + + * exec.c: new file with generic exec-a-program functionality. + Used by both photo IDs and keyserver helpers. This is pretty much + the same code that used to be keyserver specific, with some + changes to be usable generically. + + * free-packet.c (free_attributes (new)): function to free an + attribute packet. + + * gpgv.c: added stub show_photo + + * keyedit.c (keyedit_menu, menu_adduid, menu_showphoto): can add a + photo (calls generate_photo_id), or display a photo (calls + show_photo) from the --edit menu. New commands are "addphoto", + and "delphoto" (same as "deluid"). + + * keylist.c (list_keyblock_print): show photos during key list if + --show-photos enabled. + + * keyserver.c (keyserver_spawn): use the generic exec_xxx + functions to call keyserver helper. + + * g10.c, options.h: three new options - --{no-}show-photos, and + --photo-viewer to give the command line to display a picture. + + * options.skel: instructions for the photo viewer + + * parse-packet.c (parse_user_id, setup_user_id (new)): common code + for both user IDs and attribute IDs moved to setup_user_id. + + * parse-packet.c (make_attribute_uidname (new)): constructs a fake + "name" for attribute packets (e.g. "[image of size ...]") + + * parse-packet.c (parse_attribute (replaces parse_photo_id), + parse_attribute_subpkts): Builds an array of individual + attributes. Currently only handles attribute image / type jpeg + subpackets. + + * sign.c (hash_uid): Fix bug in signing attribute (formerly + photo_id) packets. + + * packet.h, and callers: globally change "photo_id" to "attribute" + and add structures for attributes. The packet format is generic + attributes, even though the only attribute type thus far defined + is jpeg. + +2001-12-21 David Shaw <dshaw@jabberwocky.com> + + * parse-packet.c (can_handle_critical): Can handle critical + revocation subpackets now. + + * trustdb.c (mark_usable_uid_certs): Disregard revocations for + nonrevocable sigs. Note that this allows a newer revocable + signature to override an older nonrevocable signature. + + * sign.c (make_keysig_packet): add a duration field and change all + callers. This makes make_keysig_packet closer to + write_signature_packets and removes some duplicated expiration + code. + + * keyedit.c (keyedit_menu, menu_revsig, sign_uids, + sign_mk_attrib): Add nrsign command, don't allow revoking a + nonrevocable signature, + + * g10.c (main): Add --nrsign option to nonrevocably sign a key + from the command line. + + * build-packet.c (build_sig_subpkt_from_sig): Comment to explain + the use of CRITICAL. + +2001-12-21 Werner Koch <wk@gnupg.org> + + * g10.c. options.h : New option --show-keyring + * getkey.c (get_ctx_handle): New. + * keylist.c (list_one): Implement option here. By David Champion. + +2001-12-20 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (keyserver_spawn): Use mkdtemp() to make temp + directory. + + * mkdtemp.c: replacement function for those platforms that don't + have mkdtemp (make a temp directory securely). + +2001-12-19 David Shaw <dshaw@jabberwocky.com> + + * misc.c (check_permissions): New function to stat() and ensure + the permissions of GNUPGHOME and the files have safe permissions. + + * keydb.c (keydb_add_resource): Check keyring permissions. + + * tdbio.c (tdbio_set_dbname): Check permissions of trustdb.gpg + + * keyserver.c (keyserver_spawn): Disable keyserver schemes that + involve running external programs if the options file has unsafe + permissions or ownership. + + * g10.c, options.h: New option --no-permission-warning to disable + the permission warning message(s). This also permits use of the + keyserver if it had been disabled (see above). Also check the + permissions/ownership of random_seed. + + * keyserver.c (keyserver_spawn): The new glibc prints a warning + when using mktemp() (the code was already secure, but the warning + was bound to cause confusion). Use a different implementation + based on get_random_bits() instead. Also try a few times to get + the temp dir before giving up. + +2001-12-19 Werner Koch <wk@gnupg.org> + + * g10.c, passphrase.c [CYGWIN32]: Allow this as an alias for MINGW32. + +2001-12-18 David Shaw <dshaw@jabberwocky.com> + + * g10.c (idea_cipher_warn): Add a flag to show the warning always + or once per session and change all callers (show always except for + the secret key protection and unknown cipher from an encrypted + message errors). Also make the strings translatable. + + * pubkey-enc.c (get_it): Add the IDEA cipher warning if the user + tries to decrypt an IDEA encrypted message without the IDEA + plugin. + + * keyserver.c (parse_keyserver_uri): More strict checking of the + keyserver URI. Specifically, fail if the ":port" section is + anything except a number between 1 and 65535. + +2001-12-17 David Shaw <dshaw@jabberwocky.com> + + * keyserver.c (print_keyinfo): No need to check for + control/illegal characters, as utf8_to_native does this for us. + + * mainproc.c (proc_encrypted): Use generic IDEA warning. + + * gpgv.c: add stub for idea_cipher_warn + + * g10.c, hkp.c, keyserver.c: Fix capitalization and plural issues. + + * encode.c (encode_crypt), sign.c (sign_file, clearsign_file): + disable pgp2 mode after the message is no longer pgp2 compatible. + + * g10.c (main): Tweak the PGP2.x IDEA warning to use the generic + warning, and not merely fail if the IDEA plugin isn't there. + + * g10.c (main, idea_cipher_warn), keygen.c (set_one_pref), + seckey-cert.c (do_check): Add a generic IDEA warning for when the + IDEA plugin is not present. This pops up when the user uses + "--cipher-algo idea", when setpref is used to set a "S1" + preference, and when a secret key protected with IDEA is used. + +2001-12-15 Werner Koch <wk@gnupg.org> + + * keyserver.c (keyserver_spawn): Assert that we have dropped privs. + +2001-12-13 Werner Koch <wk@gnupg.org> + + * pubkey-enc.c (get_session_key): Check that the public key + algorithm is indeed usable for en/decryption. This avoid a + strange error message from pubkey_decrypt if for some reasons a + bad algorithm indentifier is passed. + +2001-12-12 David Shaw <dshaw@jabberwocky.com> + + * Fixed some types for portability. Noted by Stefan Bellon. + +2001-12-11 Werner Koch <wk@gnupg.org> + + * hkp.c (hkp_export): Do not print possible control characters + from a keyserver response. + (parse_hkp_index): Made uid an unsigned char* because it is passed to + isspace(). + (hkp_search): Ditto for the char* vars. + + * g10.c (main): Print the IDEA warning also for -c and -se. + + * g10.c (get_temp_dir): Assert that we have dropped privs + + * encode.c (encode_crypt): Include the first key into the --pgp2 + check. + +2001-12-07 David Shaw <dshaw@jabberwocky.com> + + * g10.c, options.h: New option --pgp2. This is identical to + "--rfc1991 --cipher-algo idea --compress-algo 1 --digest-algo md5 + --force_v3_sigs" with the addition of an warning to advise the + user not to use a pipe (which would break pgp2 compatibility). + + * encode.c (encode_crypt): warn if the user tries to encrypt to + any key that is not RSA and <= 2048 bits when the --pgp2 option is + used. + + * sign.c (sign_file, clearsign_file): When using --pgp2, make a v3 + sig, and warn if the signature is made with a non-v3 key. + +2001-12-05 David Shaw <dshaw@jabberwocky.com> + + * sign.c (sign_file, clearsign_file, sign_symencrypt_file): Prompt + for sig expiration if --expert is set and --force-v3-sigs is not + set (v3 sigs cannot expire). + + * mainproc.c (check_sig_and_print): After checking a sig, print + expiration status. This causes a error return if the sig is + expired. + + * build-packet.c (build_sig_subpkt_from_sig): Include a critical + sig expiration subpacket if the sig is to expire. + + * keyedit.c (sign_uids): Do not sign an expired key unless + --expert is set, in which case prompt. Also, offer to expire a + signature when the key the user is signing expires. + + * keygen.c (ask_expire_interval): Add a value to determine whether + to prompt for a key or sig expiration and change all callers. + + * keyid.c: New functions: expirestr_from_sig and + colon_expirestr_from_sig. + + * keylist.c (list_keyblock_colon): Show sig expiration date in the + --with-colons listing. + + * sign.c (make_keysig_packet, write_signature_packets): Pass in an + optional timestamp for the signature packet, and change all + callers. + + * keyedit.c (sign_mk_attrib): Include a critical expiration + subpacket in the signature if an expiration date is given. + +2001-12-04 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (sign_uids): If the user tries to sign a + locally-signed key, allow the cert to be promoted to a full + exportable signature. This essentially deletes the old + non-exportable sig, and replaces it with a new exportable one. + +2001-12-04 David Shaw <dshaw@jabberwocky.com> + + * keyedit.c (keyedit_menu): Do not allow signing a revoked key + unless --expert is set, and ask even then. + + * keyedit.c (sign_uids): Do not allow signing a revoked UID unless + --expert is set, and ask even then. + + * g10.c, options.h : New option --expert + +2001-11-16 David Shaw <dshaw@jabberwocky.com> + + * Allow the user to select no compression via "--compress-algo 0" + on the command line. + + * keyedit.c (show_prefs): Show compression preferences in the + long-form "showpref" style. + + * keygen.c (set_one_pref): Permit setting a no-compression ("Z0") + preference. + + * getkey.c (fixup_uidnode): Fix compression preference corruption + bug. + +2001-12-02 David Shaw <dshaw@jabberwocky.com> + + * g10.c: Add advisory --for-your-eyes-only option as per section + 5.9 of 2440. + +2001-12-05 David Shaw <dshaw@jabberwocky.com> + + * Force a V4 sig if the user has a notation or policy URL set. + +2001-12-04 David Shaw <dshaw@jabberwocky.com> + + * g10.c: Add options --keyserver-options, --temp-directory, and + auto-key-retrieve (the opposite of no-auto-key-retrieve). + + * hkp.c (hkp_search): New function to handle searching a HKP + keyserver for a key + + * hkp.c (hkp_ask_import, hkp_export): Pretty large changes to make + them communicate via the generic functions in keyserver.c + + * keyserver.c: new file with generic keyserver routines for + getting keys from a keyserver, sending keys to a keyserver, and + searching for keys on a keyserver. Calls the internal HKP stuff + in hkp.c for HKP keyserver functions. Other calls are handled by + an external program which is spawned and written to and read from + via pipes. Platforms that don't have pipes use temp files. + +2001-11-20 David Shaw <dshaw@jabberwocky.com> + + * options.h, g10.c: New options show-notation, no-show-notation, + default-check-level, no-default-check-level, show-policy-url, + no-show-policy-url. + + * packet.h, sign.c (make_keysig_packet), parse-packet.c + (parse_signature), free-packet.c (free_seckey_enc): Fill in + structures for notation, policy, sig class, exportability, etc. + + * keyedit.c, keylist.c (print_and_check_one_sig, + list_keyblock_print): Show flags in signature display for cert + details (class, local, notation, policy, revocable). If selected, + show the notation and policy url. + + * keyedit.c (sign_uids): Prompt for and use different key sig + classes. + + * helptext.c (helptexts): Add help text to explain different + key signature classes + +2001-11-26 David Shaw <dshaw@jabberwocky.com> + + * trustdb.c (mark_usable_uid_certs): Fix segfault from bad + initialization and fix reversed key signature expiration check. + +2001-11-09 Werner Koch <wk@gnupg.org> + + * export.c (do_export_stream): Put all given names into a search + description and change the loop so that all matching names are + returned. + +2001-11-08 Werner Koch <wk@gnupg.org> + + * pubkey-enc.c (get_it): To reduce the number of questions on the + MLs print the the name of cipher algorithm 1 with the error message. + + * mainproc.c: Changed the way old rfc1991 encryption cipher is + selected. Based on a patch by W Lewis. + + * pkclist.c (do_edit_ownertrust): Allow to skip over keys, the non + working "show info" is now assigned to "i" + * trustdb.c (ask_ownertrust, validate_keys): Implement a real quit + here. Both are by David Shaw. + + * trustdb.c (validate_keys): Make sure next_exipire is initialized. + + * sign.c (make_keysig_packet): Use SHA-1 with v4 RSA keys. + + * g10.c, options.h : New option --[no-]froce-v4-certs. + * sign.c (make_keysig_packet): Create v4 sigs on v4 keys even with + a v3 key. Use that new option. By David Shaw + + * revoke.c (ask_revocation_reason): Allow to select "no reason". + By David Shaw. + + * keyid.c (fingerprint_from_sk): Calculation of an v3 fpr was + plain wrong - nearly the same code in fingerprint_from_pk is correct. + + * build-packet.c (do_secret_key): Added a few comments to the code. + +2001-11-07 Werner Koch <wk@gnupg.org> + + * g10.c (main): Print a warning when -r is used w/o encryption. + Suggested by Pascal Scheffers. + +2001-10-23 Werner Koch <wk@gnupg.org> + + * keyedit.c (keyedit_menu): Changed helptext for showpref + command. Suggested by Reinhard Wobst. + + * keyring.c (keyring_search): When marking the offtbl ready, take + into account that we may have more than one keyring. + +2001-10-22 Werner Koch <wk@gnupg.org> + + * Makefile.am: Do not use OMIT_DEPENDENCIES + + * build-packet.c (build_sig_subpkt): Default is now to put all + types of subpackets into the hashed area and only list those which + should go into the unhashed area. + +2001-10-18 Werner Koch <wk@gnupg.org> + + * keydb.c (keydb_add_resource): Rearranged the way we keep track + of the resource. There will now be an entry for each keyring here + and not in keyring.c itself. Store a token to allow creation of a + keyring handle. Changed all functions to utilize this new design. + (keydb_locate_writable): Make a real implementation. + * keyring.c (next_kr): Removed and changed all callers to set the + resource directly from the one given with the handle. + (keyring_is_writable): New. + (keyring_rebuild_cache): Add an arg to pass the token from keydb. + +2001-10-17 Werner Koch <wk@gnupg.org> + + * keyring.c (keyring_search): Enabled word search mode but print a + warning that it is buggy. + +2001-10-11 Werner Koch <wk@gnupg.org> + + * hkp.c (hkp_ask_import): No more need to set the port number for + the x-hkp scheme. + (hkp_export): Ditto. + +2001-10-06 Stefan Bellon <sbellon@sbellon.de> + + * passphrase.c [__riscos__]: Disabled agent specific stuff. + * g10.c: New option --no-force-v3-sigs. + +2001-10-04 Werner Koch <wk@gnupg.org> + + * export.c (do_export_stream): Do not push the compress filter + here because the context would run out of scope due to the + iobuf_close done by the caller. + (do_export): Do it here instead. + +2001-09-28 Werner Koch <wk@gnupg.org> + + * keyedit.c (sign_uids): Always use the primary key to sign keys. + * getkey.c (finish_lookup): Hack to return only the primary key if + a certification key has been requested. + + * trustdb.c (cmp_kid_for_make_key_array): Renamed to + (validate_one_keyblock): this and changed arg for direct calling. + (make_key_array): Renamed to + (validate_one_keyblock): this and changed args for direct calling. + (mark_usable_uid_certs, validate_one_keyblock) + (validate_key_list): Add next_expire arg to keep track of + expiration times. + (validate_keys): Ditto for UTKs and write the stamp. + + * tdbio.c (migrate_from_v2): Check return code of tbdio_sync. + + * tdbdump.c (import_ownertrust): Do a tdbio_sync(). + + * keyring.c: Made the offtbl an global object. + +2001-09-27 Werner Koch <wk@gnupg.org> + + * pkclist.c (do_edit_ownertrust): Allow settin of ultimate trust. + + * trustdb.c (mark_keyblock_seen): New. + (make_key_array): Use it to mark the subkeys too. + (validate_keys): Store validity for ultimatly trusted keys. + +2001-09-26 Werner Koch <wk@gnupg.org> + + * pkclist.c (check_signatures_trust, do_we_trust): Removed the + invocation of add_ownertrust. Minor changes to the wording. + (add_ownertrust, add_ownertrust_cb): Removed. + + * trustdb.c (get_validity): Allow to lookup the validity using a + subkey. + + * trustdb.c (new_key_hash_table): Increased the table size to 1024 + and changed the masks accordingly. + (validate): Changed stats printing. + (mark_usable_uid_certs): New. + (cmp_kid_for_make_key_array): Does now check the signatures and + figures out a usable one. + +2001-09-25 Werner Koch <wk@gnupg.org> + + * keyring.c (new_offset_item,release_offset_items) + (new_offset_hash_table, lookup_offset_hash_table) + (update_offset_hash_table, update_offset_hash_table_from_kb): New. + (keyring_search): Use a offset table to optimize search for + unknown keys. + (keyring_update_keyblock, keyring_insert_keyblock): Insert new + offsets. + * getkey.c (MAX_UNK_CACHE_ENTRIES): Removed the unknown keys + caching code. + + * g10.c, options.h, import.c: Removed the entire + allow-secret-key-import stuff because the validity is now + controlled by other means. + + * g10.c: New command --rebuild-keydb-caches. + * keydb.c (keydb_rebuild_caches): New. + * keyring.c (do_copy): Moved some code to + (create_tmp_file, rename_tmp_file, write_keyblock): new functions. + (keyring_rebuild_cache): New. + + * packet.h (PKT_ring_trust): Add sigcache field. + * parse-packet.c (parse_trust): Parse sigcache. + * keyring.c (do_copy): Always insert a sigcache packet. + (keyring_get_keyblock): Copy the sigcache packet to the signature. + * sig-check.c (cache_sig_result): Renamed from + cache_selfsig_result. Changed implementation to use the flag bits + and changed all callers. + (mdc_kludge_check): Removed this unused code. + (do_check): Do not set the sig flags here. + + * import.c (read_block): Make sure that ring_trust packets are + never imported. + * export.c (do_export_stream): and never export them. + + * trustdb.c (make_key_array): Skip revoked and expired keys. + +2001-09-24 Werner Koch <wk@gnupg.org> + + * g10.c, options.h: New option --no-auto-check-trustdb. + + * keygen.c (do_generate_keypair): Set newly created keys to + ultimately trusted. + + * tdbio.h, tdbio.c: Removed all support for records DIR, KEY, UID, + PREF, SIG, SDIR and CACH. Changed migration function to work + direct on the file. + (tdbio_read_nextcheck): New. + (tdbio_write_nextcheck): New. + +2001-09-21 Werner Koch <wk@gnupg.org> + + Revamped the entire key validation system. + * trustdb.c: Complete rewrite. No more validation on demand, + removed some functions, adjusted to all callers to use the new + and much simpler interface. Does not use the LID anymore. + * tdbio.c, tdbio.h: Add new record types trust and valid. Wrote a + migration function to convert to the new trustdb layout. + * getkey.c (classify_user_id2): Do not allow the use of the "#" + prefix. + * keydb.h: Removed the TDBIDX mode add a skipfnc to the + descriptor. + * keyring.c (keyring_search): Implemented skipfnc. + + * passphrase.c (agent_open): Add missing bracket. Include windows.h. + +2001-09-19 Werner Koch <wk@gnupg.org> + + * keylist.c (print_fingerprint): Renamed from fingerprint, made + global available. Added new arg to control the print style. + * mainproc.c (print_fingerprint): Removed. + * pkclist.c (print_fpr, fpr_info): Removed and changed callers to + use print_fingerprint. + * keyedit.c (show_fingerprint): Ditto. + + * passphrase.c (writen, readn) + (agent_open, agent_close) + (agent_get_passphrase) + (passphrase_clear_cache): Support for W32. Contributed by Timo. + + * import.c (import_one): Release keydb handles at 2 more places. + + * keyring.c (keyring_release): Close the iobuf. + (keyring_get_keyblock): Init ret_kb to NULL and store error contidion. + + * import.c (import_new_stats_handle): New. + (import_release_stats_handle): New. + (import_print_stats): Renamed from static fnc print_stats. + (import_keys, import_keys_stream): Add an optional status handle + arg and changed all callers. + * hkp.c (hkp_ask_import): Add an stats_handle arg and changed all + callers. + + * mainproc.c (print_pkenc_list): Use print_utf8_string2(). + +2001-09-18 Werner Koch <wk@gnupg.org> + + * g10.c: New command --refresh-keys. + * hkp.c (hkp_refresh_keys): New. Contributed by Timo Schulz. + + * parse-packet.c (parse): Stop on impossible packet lengths. + +2001-09-17 Werner Koch <wk@gnupg.org> + + * mainproc.c (print_notation_data): Wrap notation data status lines + after 50 chars. + + * mainproc.c (proc_pubkey_enc): Make option try-all-secrets work. + By disastry@saiknes.lv. + +2001-09-14 Werner Koch <wk@gnupg.org> + + * parse-packet.c (dump_sig_subpkt): List key server preferences + and show the revocable flag correctly. Contributed by David Shaw. + +2001-09-09 Werner Koch <wk@gnupg.org> + + * keyedit.c (keyedit_menu): No need to define another p. + + * keylist.c (print_capabilities): s/used/use/ so that it + does not shadow a global. + * sign.c (sign_file): Renamed arg encrypt to encryptflag + * keygen.c: Replaced all "usage" by "use". + * misc.c (openpgp_pk_algo_usage): Ditto. + + * pubkey-enc.c (get_it): Renamed arg k to enc so that the later + defined k does not shadow it. + + * parse-packet.c (parse_gpg_control): No need to define another i. + + * getkey.c (get_pubkey_byfprint): Must use the enum values and not + the fprint_len. + * keyring.c (keyring_search): Removed a non-sense break. Both + bugs pointed out by Stefan. + +2001-09-07 Werner Koch <wk@gnupg.org> + + * status.c, status.h: Added NO_RECP and ALREADY_SIGNED. + * pkclist.c (build_pk_list): Issue NO_RECP. + * keyedit.c (sign_uids): Added experimental ALREADY_SIGNED + + * hkp.c (hkp_import): Use log_error. Bug reported by Neal H + Walfield. + + * getkey.c (classify_user_id2): Change args to take the desc union + direct. It was a stupid idea to pass the individual fields of an + union to this function. Changed all callers. + (classify_user_id): Ditto and allow to pass NULL as the description. + +2001-09-06 Werner Koch <wk@gnupg.org> + + * getkey.c (fixup_uidnode): Features flag is now a bit vector. + * keygen.c (add_feature_mdc): Ditto. + + Revamped the entire key I/O code to be prepared for other ways of + key storages and to get rid of the existing shit. GDBM support has + gone. + * keydb.c: New + * keyring.c, keyring.h: New. + * ringedit.c: Removed. Moved some stuff to keyring.c + * getkey.c: Changed everything related to the key retrieving + functions which are now using the keydb_ functions. + (prepare_search, word_match_chars, word_match) + (prepare_word_match, compare_name): Moved to keyring.c + (get_pubkey_byname): Removed ctx arg and add ret_kdbhd + arg. Changed all callers. + (key_byname): Use get_pubkey_end to release the context and take + new ret_kbdhd arg. Changed all callers. + (classify_user_id2): Fill the 16 byte fingerprint up with 4 null + bytes not with zero bytes of value 4, tsss. + * import.c (import_one): Updated to use the new keydb interface. + (import_secret_one): Ditto. + (import_revoke_cert): Ditto. + * delkey.c (do_delete_key): Ditto. + * keyedit.c (keyedit_menu): Ditto. + (get_keyblock_byname): Removed. + * revoke.c (gen_revoke): Ditto. + * export.c (do_export_stream): Ditto. + * trustdb.c (update_trustdb): Ditto. + * g10.c, gpgv.c (main): Renamed add_keyblock_resource to + keydb_add_resource. + * Makefile.am: Added and removed files. + + * keydb.h: Moved KBNODE typedef and MAX_FINGERPRINT_LEN to + * global.h: this new header. + +2001-09-03 Werner Koch <wk@gnupg.org> + + * passphrase.c (agent_get_passphrase): Changed nread to size_t. + (passphrase_clear_cache): Ditto. + + * keyid.c (mk_datestr): Avoid trigraphs. + (fingerprint_from_pk): Cache the keyid in the pk. + + * options.h: Add opt.with_fingerprint so that we know whether the + corresponding options was used. + * g10.c (main): Set it here. + * pkclist.c (check_signatures_trust): Always print fingerprint + when this option is used. Mixed a minor memory leak. + + * status.c, status.h: New status INV_RECP. + * pkclist.c (build_pk_list): Issue this status. + +2001-08-31 Werner Koch <wk@gnupg.org> + + * parse-packet.c (parse_key,parse_pubkeyenc) + (parse_signature): Return error on reading bad MPIs. + + * mainproc.c (check_sig_and_print): Always print the user ID even + if it is not bound by a signature. Use the primary UID in the + status messages and encode them in UTF-8 + * status.c (write_status_text_and_buffer): New. + +2001-08-30 Werner Koch <wk@gnupg.org> + + * packet.h (sigsubpkttype_t): Add SIGSUBPKT_FEATURES. + (PKT_public_key, PKT_user_id): Add a flag for it. + * parse-packet.c, build-packet.c: Add support for them. + * getkey.c (fixup_uidnode, merge_selfsigs): Set the MDC flags. + * keygen.c (add_feature_mdc): New. + (keygen_upd_std_prefs): Always set the MDC feature. + * keyedit.c (show_prefs): List the MDC flag + * pkclist.c (select_mdc_from_pklist): New. + * encode.c (encode_crypt, encrypt_filter): Test whether MDC + should be used. + * cipher.c (write_header): Set MDC use depending on the above test. + Print more status info. + + * delkey.c (do_delete_key): Kludge to delete a secret key with no + public key available. + + * ringedit.c (find_secret_keyblock_direct): New. + * getkey.c (seckey_available): Simplified. + + * ringedit.c (cmp_seckey): Now compares the secret key against the + public key while ignoring all secret parts. + (keyring_search): Use a public key packet as arg. Allow to search + for subnkeys + (search): Likewise. Changed all callers. + (find_secret_keyblock_bypk): New. + (find_secret_keyblock_byname): First locate the pubkey and then + find the correponding secret key. + * parse-packet.c (parse): Renamed pkttype arg to onlykeypkts and + changed code accordingly. Changed all callers. + (search_packet): Removed pkttype arg. + * keyedit.c (keyedit_menu): First locate the public key and then + try to locate a secret key. + + * ringedit.c (locate_keyblock_by_fpr): Removed. + (locate_keyblock_by_keyid): Removed. + (find_keyblock_bysk): Removed. + + * sig-check.c (check_key_signature2): Print the keyid along with + the wrong sig class errors. + +2001-08-24 Werner Koch <wk@gnupg.org> + + * sign.c (sign_file): Stripped the disabled comment packet code. + (sign_file, sign_symencrypt_file): Moved common code to .. + (write_onepass_sig_packets): .. this new function. + (sign_file, clearsign_file, sign_symencrypt_file): Moved common + code to + (write_signature_packets): this new function. + (write_signature_packets, make_keysig_packet) + (update_keysig_packet): Moved common code to + (hash_uid, hash_sigclass_to_magic): these new functions + (sign_file, sign_symencrypt_file): Moved common code to + (write_plaintext_packet): this new function. + +2001-08-21 Stefan Bellon <sbellon@sbellon.de> + + * trustdb.c (query_trust_info): Changed trustlevel to signed int. + * g10.c [__riscos__]: Fixed handling of --use-agent --lock-multiple. + +2001-08-20 Werner Koch <wk@gnupg.org> + + * encr-data.c (decrypt_data): Keep track on whether we already + printed information about the used algorithm. + * mainproc.c (proc_encrypted): Removed the non-working IDEA hack + and print a message about the assumed algorithm. + * passphrase.c (passphrase_to_dek): Use the same algorithm as above. + (proc_symkey_enc): Print the algorithm, so that the user knows it + before entering the passphrase. + (proc_pubkey_enc, proc_pubkey_enc): Zero the DEK out. + * encode.c (encode_crypt, encrypt_filter): Ditto. + + * g10.c: Allow for --sign --symmetric. + * sign.c (sign_and_symencrypt): New. + + Applied patches from Stefan Bellon <sbellon@sbellon.de> to support + RISC OS. Nearly all of these patches are identified by the + __riscos__ macro. + * compress.c: Added a couple of casts. + * g10.c [__riscos__]: Some patches and new options foo-file similar + to all foo-fd options. + * gpgv.c, openfile.c, ringedit.c, tdbio.c: Minor fixes. Mainly + replaced hardcoded path separators with EXTSEP_S like macros. + * passprase.c [__riscos__]: Disabled agent stuff + * trustdb.c (check_trust): Changed r_trustlevel to signed int to + avoid mismatch problems in pkclist.c + * pkclist.c (add_ownertrust): Ditto. + * plaintext.c (handle_plaintext) [__riscos__]: Print a note when + file can't be created. + * options.h [__riscos__]: Use an extern unless included from the + main module. + * signal.c (got_fatal_signal) [__riscos__]: Close all files. + +2001-08-14 Werner Koch <wk@gnupg.org> + + * keygen.c (ask_algo): New arg r_usage. Allow for RSA keys. + (gen_rsa): Enabled the code. + (do_create): Enabled RSA branch. + (parse_parameter_usage): New. + (proc_parameter_file): Handle usage parameter. + (read_parameter_file): Ditto. + (generate_keypair): Ditto. + (generate_subkeypair): Ditto. + (do_generate_keypair): Ditto. + (do_add_key_flags): New. + (keygen_add_std_prefs): Use the new function. + (keygen_add_key_flags_and_expire): New. + (write_selfsig, write_keybinding): Handle new usage arg. + * build-packet.c (build_sig_subpkt): Make sure that key flags go + into the hashed area. + + * keygen.c (write_uid): Initialize the reference cunter. + + * keyedit.c (keyedit_menu): No more need to update the trustdb for + preferences. Added calls to merge keblock. + + * kbnode.c (dump_kbnode): Print some more flags. + +2001-08-10 Werner Koch <wk@gnupg.org> + + Revamped the preference handling. + + * packet.h (prefitem_t, preftype_t): New. + (PKT_public_key): Added a uid field. + (PKT_user_id): Added field to store preferences and a reference + counter. + * parse-packet.c (parse_user_id,parse_photo_id): Initialize them + * free-packet.c (free_user_id): Free them. + (copy_user_id): Removed. + (scopy_user_id): New. + (cmp_user_ids): Optimized for identical pointers. + (release_public_key_parts): Release the uid. + (copy_public_key_with_new_namehash): Removed. + (copy_prefs): New. + * keyedit.c (menu_adduid): Use the new shallow copy user id. + (show_prefs): Adjusted implementation. + (keyedit_menu): No more need to update the trustdb after changing + preferences. + * getkey.c (fixup_uidnode): Store preferences. + (find_by_name): Return a user id packet and remove namehash stuff. + (lookup): Removed the unused namehash stuff. + (finish_lookup): Added foundu arg. + (pk_from_block): Removed the namehash arg and changed all callers. + (merge_selfsigs): Copy prefs to all keys. + * trustdb.c (get_pref_data): Removed. + (is_algo_in_prefs): Removed. + (make_pref_record): Deleted and removed all class. + * pkclist.c (select_algo_from_prefs): Adjusted for the new + preference implementation. + * pubkey-enc.c (is_algo_in_prefs): New. + (get_it): Use that new function. + +2001-08-09 Werner Koch <wk@gnupg.org> + + * build-packet.c (build_sig_subpkt): Fixed calculation of + newarea->size. + + * g10.c (main): New option "--preference-list" + * keyedit.c (keyedit_menu): New commands "setpref" and "updpref". + (menu_set_preferences): New. + * keygen.c (keygen_set_std_prefs): New. + (set_one_pref): New. + (check_zip_algo): New. + (keygen_get_std_prefs): New. + (keygen_upd_std_prefs): New + (keygen_add_std_prefs): Move the pref setting code into the above fnc. + * build-packet.c (build_sig_subpkt): Updated the list of allowed + to update subpackets. + +2001-08-08 Werner Koch <wk@gnupg.org> + + * packet.h (subpktarea_t): New. + (PKT_signature): Use that type for hashed_data and unhashed_data and + removed the _data prefix from those fields. Changed all users. + * parse-packet.c (parse_signature): Changed allocation for that. + (parse_sig_subpkt): Changed declaration + (enum_sig_subpkt): Ditto and changed implementation accordingly. + * free-packet.c (cp_subpktarea): Renamed from cp_data_block and + adjusted implementation. Changed caller. + * sig-check.c (mdc_kludge_check): Adjusted the hashing. + (do_check): Ditto. + * sign.c (sign_file, clearsign_file, make_keysig_packet, + update_keysig_packet): Ditto. + * build-packet.c (build_sig_subpkt): Partial rewrite. + (find_subpkt): Adjusted and made static. + (delete_sig_subpkt): Adjusted. + (do_signature): Ditto. + + * keygen.c (ask_keysize): Do not print the notes about suggested + key sizes if just a DSA key is generated. + + * trustdb.c (add_ultimate_key): s/log_error/log_info/ for + duplicated inserted trusted keys. + +2001-08-07 Werner Koch <wk@gnupg.org> + + * sign.c (sleep): Redefine for W32. + + * g10.c, options.h: Set new flag opt.no_homedir_creation when + --no-options is given. + * openfile.c (try_make_homedir): Don't create the homedir in that case. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * armor.c (armor_filter): Removed the default comment string + because it could get us in trouble due to translations using non + ascii characters. + +2001-08-01 Werner Koch <wk@gnupg.org> + + * keylist.c (list_keyblock_print): Do not list revoked UIDs unless + in verbose mode and we do no signature listing. + + * getkey.c (finish_lookup): Skip subkeys which are not yet valid. + * g10.c, options.h: New option --ignore-valid-from. + + * sign.c (make_keysig_packet): Added new sigversion argument to + allow the caller to force generation of required signature + version. Changed all callers. Suggested by Thomas Roessler. + + * keyedit.c (sign_uids): Force v4 signature generation for local + sigs. Removed the check for local signature and pre-v4 keys. + +2001-07-27 Werner Koch <wk@gnupg.org> + + * keyedit.c (sign_uids): Check that we are not trying to to a + lsign with a pre-v4 key. Bug noticed by Thomas Roessler. + +2001-07-26 Werner Koch <wk@gnupg.org> + + * parse-packet.c (parse_photo_id): Reset all variables. + * getkey.c (merge_selfsigs_main): Removed checks on PHOTO_ID + because this is handled identically to a user ID. + +2001-07-06 Werner Koch <wk@gnupg.org> + + * cipher.c (write_header): Don't use MDC with --rfc1991. Suggested + by disastry@saiknes.lv. + +2001-07-05 Werner Koch <wk@gnupg.org> + + * g10.c, options.h: New option --preserve-permissions. + * ringedit.c (add_keyblock_resource): Use it here + (keyring_copy): and here. + + * trustdb.c (verify_own_keys): Be more silent on --quiet. + Suggested by Thomas Roessler. + * sig-check.c (check_key_signature2): Ditto. + * mainproc.c (proc_encrypted, proc_tree): Ditto + * getkey.c (lookup): Ditto. + +2001-07-04 Werner Koch <wk@gnupg.org> + + * ringedit.c (add_keyblock_resource): Restore filename in case of error. + +2001-06-25 Werner Koch <wk@gnupg.org> + + * kbnode.c (dump_kbnode): Print the signature timestamp. + + * keyedit.c (keyedit_menu): New menu point "primary". + (change_primary_uid_cb): New. + (menu_set_primary_uid): New. + * sign.c (update_keysig_packet): New. + * build-packet.c (build_sig_subpkt): Put the primary UID flag into + the hashed area. Allow update of some more packets. + +2001-06-15 Werner Koch <wk@gnupg.org> + + * getkey.c (merge_selfsigs): Exit gracefully when a secret key is + encountered. May happen if a secret key is in public keyring. + Reported by Francesco Potorti. + +2001-06-12 Werner Koch <wk@gnupg.org> + + * getkey.c (compare_name): Use ascii_memistr(), ascii_memcasecmp() + * keyedit.c (keyedit_menu): Use ascii_strcasecmp(). + * armor.c (radix64_read): Use ascii_toupper(). + * ringedit.c (do_bm_search): Ditto. + * keygen.c (read_parameter_file): Ditto. + * openfile.c (CMP_FILENAME): Ditto. + * g10.c (i18n_init): We can now use just LC_ALL. + +2001-05-29 Werner Koch <wk@gnupg.org> + + * keygen.c (generate_subkeypair): Print a warning if a subkey is + created on a v3 key. Suggested by Brian M. Carlson. + +2001-05-27 Werner Koch <wk@gnupg.org> + + * keyid.c (get_lsign_letter): New. + * keylist.c (list_keyblock_colon): Use it here. + * mainproc.c (list_node): and here. + + * getkey.c, packet.h, free-packet.c: Removed that useless key + created field; I dunno why I introducded this at all - the + creation time is always bound to the key packet and subject to + fingerprint calculation etc. + + * getkey.c (fixup_uidnode): Add keycreated arg and use this + instead of the signature timestamp to calculate the + help_key_expire. Bug reported by David R. Bergstein. + (merge_selfsigs_main): Correct key expiration time calculation. + (merge_selfsigs_subkey): Ditto. + +2001-05-25 Werner Koch <wk@gnupg.org> + + * revoke.c (gen_revoke): Add a cast to a tty_printf arg. + * delkey.c (do_delete_key): Ditto. + * keyedit.c (print_and_check_one_sig): Ditto. + (ask_revoke_sig): Ditto. + (menu_revsig): Ditto. + (check_all_keysigs): Removed unused arg. + +2001-05-23 Werner Koch <wk@gnupg.org> + + * g10.c (opts): Typo fix by Robert C. Ames. + +2001-05-06 Werner Koch <wk@gnupg.org> + + * revoke.c: Small typo fix + +2001-05-04 Werner Koch <wk@gnupg.org> + + * passphrase.c (passphrase_clear_cache): Shortcut if agent usage + is not enabled. + +2001-05-01 Werner Koch <wk@gnupg.org> + + * passphrase.c (writen): Replaced ssize_t by int. Thanks to + to Robert Joop for reporting that SunOS 4.1.4 does not have it. + +2001-04-28 Werner Koch <wk@gnupg.org> + + * getkey.c (merge_public_with_secret): pkttype was not set to subkey. + +2001-04-27 Werner Koch <wk@gnupg.org> + + * skclist.c (build_sk_list): Changed one log_debug to log_info. + +2001-04-25 Werner Koch <wk@gnupg.org> + + * keyedit.c (show_prefs): Add a verbose mode. + (show_key_with_all_names): Pass verbose flag for special value of + with_pref. + (keyedit_menu): New command "showpref" + (show_key_with_all_names): Mark revoked uids and the primary key. + +2001-04-24 Werner Koch <wk@gnupg.org> + + * getkey.c (get_primary_uid): Return a different string in case of + error and made it translatable. + + * build-packet.c (do_secret_key): Ugly, we wrote a zero + instead of the computed ndays. Thanks to M Taylor for complaining + about a secret key import problem. + +2001-04-23 Werner Koch <wk@gnupg.org> + + * hkp.c (hkp_ask_import): Allow to specify a port number for the + keyserver. Add a kudge to set the no_shutdown flag. + (hkp_export): Ditto. + * options.skel: Document the changes + +2001-04-20 Werner Koch <wk@gnupg.org> + + * options.skel: Add some more comments. + +2001-04-19 Werner Koch <wk@gnupg.org> + + * keyid.c (mk_datestr): New. Handles negative times. We must do + this because Windoze segvs on negative times passed to gmtime(). + Changed all datestr_from function to use this one. + + * keyid.c, keyid.h (colon_strtime): New. To implement the + fixed-list-mode. + (colon_datestr_from_pk): New. + (colon_datestr_from_sk): New. + (colon_datestr_from_sig): New. + * keylist.c (list_keyblock_colon): Use these functions here. + * mainproc.c (list_node): Ditto. + +2001-04-18 Werner Koch <wk@gnupg.org> + + * openfile.c (open_sigfile): Fixed the handling of ".sign". + * mainproc.c (proc_tree): Use iobuf_get_real_fname. + Both are by Vincent Broman. + +2001-04-14 Werner Koch <wk@gnupg.org> + + * getkey.c (fixup_uidnode): Removed check for !sig which is + pointless here. Thanks to Jan Niehusmann. + +2001-04-10 Werner Koch <wk@gnupg.org> + + * sig-check.c (check_key_signature2): Use log_info instead of + log_error so that messed up keys do not let gpg return an error. + Suggested by Christian Kurz. + + * getkey.c (merge_selfsigs_main): Do a fixup_uidnode only if we + have both, uid and sig. Thanks to M Taylor. + +2001-04-05 Werner Koch <wk@gnupg.org> + + * armor.c (unarmor_pump_new,unarmor_pump_release): New. + (unarmor_pump): New. + * pipemode.c (pipemode_filter): Use the unarmor_pump to handle + armored or non-armored detached signatures. We can't use the + regular armor_filter becuase this does only chack for armored + signatures the very first time. In pipemode we may have a mix of + armored and binary detached signatures. + * mainproc.c (proc_tree): Do not print the "old style" notice when + this is a pipemode processes detached signature. + (proc_plaintext): Special handling of pipemode detached sigs. + + * packet.h (CTRLPKT_PLAINTEXT_MARK): New. + * parse-packet.c (create_gpg_control): New. + * kbnode.c (dump_kbnode): Support it here. + * mainproc.c (check_sig_and_print): Fixed the check for bad + sequences of multiple signatures. + (proc_plaintext): Add the marker packet. + (proc_tree): We can now check multiple detached signatures. + +2001-04-02 Werner Koch <wk@gnupg.org> + + The length of encrypted packets for blocksizes != 8 was not + correct encoded. I think this is a minor problem, because we + usually use partial length packets. Kudos to Kahil D. Jallad for + pointing this out. + * packet.h: Add extralen to PKT_encrypted. + * cipher.c (write_header): Set extralen. + * build-packet.c (do_encrypted): Use extralen instead of const 10. + (do_encrypted_mdc): Ditto. + * parse-packet.c (parse_encrypted): Set extralen to 0 because we + don't know it here. + +2001-03-30 Werner Koch <wk@gnupg.org> + + * getkey.c (premerge_public_with_secret): Changed wording an add + the keyID to the info message. + +2001-03-29 Werner Koch <wk@gnupg.org> + + * getkey.c (premerge_public_with_secret): Use log_info instead of + log_error when no secret key was found for a public one. + Fix the usage if the secret parts of a key are not available. + + * openfile.c (ask_outfile_name): Trim spaces. + (open_outfile): Allow to enter an alternate filename. Thanks to + Stefan Bellon. + * plaintext.c (handle_plaintext): Ditto. + +2001-03-28 Werner Koch <wk@gnupg.org> + + * mainproc.c (do_check_sig): Allow direct key and subkey + revocation signature. + * sig-check.c (check_key_signature2): Check direct key signatures. + Print the signature class along with an error. + +2001-03-27 Werner Koch <wk@gnupg.org> + + * packet.h: Add a missing typedef to an enum. Thanks to Stefan Bellon. + + * g10.c: New option --no-sig-create-check. + * sign.c (do_sign): Implement it here. + * g10.c: New option --no-sig-cache. + * sig-check.c (check_key_signature2): Implement it here. + (cache_selfsig_result): and here. + + * keylist.c (list_keyblock): Removed debugging stuff. + + * getkey.c (cache_public_key): Made global. + * keygen.c (write_selfsig, write_keybinding): Cache the new key. + + * getkey.c (key_byname): Add new arg secmode and changed all + callers to request explicitly the mode. Deriving this information + from the other supplied parameters does not work if neither pk nor + sk are supplied. + +2001-03-25 Werner Koch <wk@gnupg.org> + + * packet.h (ctrlpkttype_t): New. + * mainproc.c (add_gpg_control,proc_plaintext,proc_tree): Use the + new enum values. + * pipemode.c (make_control): Ditto. + * armor.c (armor_filter): Ditto. + +2001-03-24 Werner Koch <wk@gnupg.org> + + * sign.c (do_sign): Verify the signature right after creation. + +2001-03-23 Werner Koch <wk@gnupg.org> + + * status.c, status.h (STATUS_UNEXPECTED): New. + * mainproc.c (do_proc_packets): And emit it here. + +2001-03-21 Werner Koch <wk@gnupg.org> + + * status.c: Add sys/types.h so that it runs on Ultrix. Reported + by Georg Schwarz.x + + * build-packet.c (build_sig_subpkt): Fixed generaton of packet + length header in case where 2 bytes headers are needed. Thanks to + Piotr Krukowiecki. + +2001-03-19 Werner Koch <wk@gnupg.org> + + * g10.c (main): the default keyring is no always used unless + --no-default-keyring is given. + + * ringedit.c (add_keyblock_resource): invalidate cache after file + creation. + +2001-03-15 Werner Koch <wk@gnupg.org> + + * keygen.c (ask_algo): Changed the warning of the ElGamal S+E Algo. + + * keylist.c (print_capabilities): New. + (list_keyblock_colon): and use it here. + +2001-03-13 Werner Koch <wk@gnupg.org> + + * main.c, options.h: New option --fixed_list_mode. + * keylist.c (list_keyblock_colon): use it here. + + * getkey.c (merge_keys_and_selfsig): Divert merging of public keys + to the function used in key selection.. + * keylist.c (is_uid_valid): Removed. + (list_keyblock): Splitted into .. + (list_keyblock_print, list_keyblock_colon): .. these. + functions. Changed them to use the flags set in the key lookup code. + (reorder_keyblock): New, so that primary user IDs are listed first. + + * ringedit.c (keyring_copy): flush the new iobuf chaces before + rename or remove operations. This is mainly needed for W32. + + * hkp.c [HAVE_DOSISH_SYSTEM]: Removed the disabled code because we + have now W32 socket support in ../util/http.c + + * skclist.c (key_present_in_sk_list): New. + (is_duplicated_entry): New. + (build_sk_list): Check for duplicates and do that before unlocking. + +2001-03-12 Werner Koch <wk@gnupg.org> + + * armor.c (parse_header_line): Removed double empty line check. + (parse_header_line): Replaced trim_trailing_ws with a counting + function so that we can adjust for the next read. + + * options.skel: Fixed 3 typos. By Thomas Klausner. Replaced the + keyserver example by a better working server. + + * parse-packet.c (parse_symkeyenc): Return Invalid_Packet on error. + (parse_pubkeyenc): Ditto. + (parse_onepass_sig): Ditto. + (parse_plaintext): Ditto. + (parse_encrypted): Ditto. + (parse_signature): Return error at other places too. + (parse_key): Ditto. + * g10.c (main): Set opt.list_packets to another value when invoked + with the --list-packets command. + * mainproc.c (do_proc_packets): Don's stop processing when running + under --list-packets command. + + * signal.c (do_sigaction): Removed. + (init_one_signal): New to replace the above. Needed to support + systems without sigactions. Suggested by Dave Dykstra. + (got_fatal_signal,init_signals): Use the above here. + (do_block): Use sigset() if sigprocmask() is not available. + + * armor.c (parse_hash_header): Test on TIGER192, which is the + correct value as per rfc2440. By Edwin Woudt. + +2001-03-08 Werner Koch <wk@gnupg.org> + + * misc.c: Include time.h. By James Troup. + + * getkey.c: Re-enabled the unknown user Id and PK caches and + increased their sizes. + + * getkey.c (merge_selfsigs_main): Set expire date and continue + processing even if we found a revoked key. + (merge_selfsigs_subkeys): Ditto. + + * packet.h: Add an is_revoked flag to the user_id packet. + * getkey.c (fixup_uidnode): Set that flag here. + (merge_selfsigs_main): Fix so that the latest signature is used to + find the self-signature for an UID. + * parse-packet.c (parse_user_id): Zero out all fields. + * mainproc.c (check_sig_and_print): Print the primary user ID + according the the node flag and then all other non-revoked user IDs. + (is_uid_revoked): Removed; it is now handled by the key selection code. + + Changed the year list of all copyright notices. + +2001-03-07 Werner Koch <wk@gnupg.org> + + * getkey.c (finish_lookup): Print an info message only in verbose mode. + +2001-03-05 Werner Koch <wk@gnupg.org> + + * packet.h: Replaced sigsubpkt_t value 101 by PRIV_VERIFY_CACHE. + We have never used the old value, so we can do this without any harm. + * parse-packet.c (dump_sig_subpkt): Ditto. + (parse_one_sig_subpkt): Parse that new sub packet. + * build-packet.c (build_sig_subpkt): Removed the old one from the + hashed area. + (delete_sig_subpkt): New. + (build_sig_subpkt): Allow an update of that new subpkt. + * sig-check.c (check_key_signature2): Add verification caching + (cache_selfsig_result): New. + * export.c (do_export_stream): Delete that sig subpkt before exporting. + * import.c (remove_bad_stuff): New. + (import): Apply that function to all imported data + +2001-03-03 Werner Koch <wk@gnupg.org> + + * getkey.c: Introduced a new lookup context flag "exact" and used + it in all place where we once used primary. + (classify_user_id2): Replaced the old function and add an extra + argument to return whether an exact keyID has been requested. + (key_byname): Removed the unused ctx.primary flag + (get_seckey_byname2): Ditto. + (finish_lookup): Changed debugging output. + +2001-03-02 Werner Koch <wk@gnupg.org> + + * keylist.c (list_one): Remove the merge key calls. + +2001-03-01 Werner Koch <wk@gnupg.org> + + * getkey.c (finish_lookup): Don't use it if we no specific usage + has been requested. + (merge_selfsigs_main): fix UID only if we have an signature. + (lookup): Return UNU_PUBKEY etc. instead of NO_PUBKEY if we found + a key but the requested usage does not allow this key. + * import.c (import_one): Take UNU_PUBKEY into account. + * mainproc.c (list_node): Ditto. + * keylist.c (list_keyblock): Ditto. + * keyedit.c (print_and_check_one_sig): Ditto. + +2001-02-09 Werner Koch <wk@gnupg.org> + + * delkey.c (delete_key): Removed that silly assert which rendered + the whole new stuff meaningless. + +2001-02-08 Werner Koch <wk@gnupg.org> + + * getkey.c (key_byname): It can happen that we have both, sk and pk + NULL, fix for that. + + * parse-packet.c (parse_one_sig_subpkt): Add support for + primary_uid and key_flags. + (can_handle_critical): Ditto + + * parse-packet.c (parse_encrypted): Fixed listing of pktlen for + MDC packets. + + * getkey.c: Backported the version of this file from gpg 1.1. this + involved some changes in other files too. + * parse-packet.c (parse_key): Clear req_usage. + * skclist.c (build_sk_list): Use req_usage to pass the usage + information to the lookup function. + * pkclist.c (build_pk_list): Ditto. + * free-packet.c (copy_public_parts_to_secret_key): New. + * keydb.h: Add IS_* macros to check the sig_class. + * misc.c (openpgp_cipher_test_algo): New. + (openpgp_pk_test_algo): New. + (openpgp_pk_algo_usage): New. + (openpgp_md_test_algo): New. + * packet.h: Add a few fields to PKT_{public,secret}_key and + PKT_user_id. + * seckey-cert.c (do_check): Use the new main_keyid field. + +2001-02-04 Werner Koch <wk@gnupg.org> + + * encr-data.c (decrypt_data): Catch error when we had problems to + parse the encrypted packet. By Timo. + +2001-01-29 Werner Koch <wk@gnupg.org> + + * g10.c (main): --batch does now set nogreeting. + + * delkey.c (do_delete_key): Fixed delete-both functionality. + +2001-01-22 Werner Koch <wk@gnupg.org> + + * g10.c: New command --delete-secret-and-public-key. + * delkey.c (delete_key): Add new arg allow_both. + (do_delete_key): Move most stuff from above to this new function. + +2001-01-12 Werner Koch <wk@gnupg.org> + + * passphrase.c (passphrase_to_dek): Use MD5 when IDEA is installed + and we have no S2K. + * mainproc.c (proc_encrypted): Likewise + +2001-01-11 Werner Koch <wk@gnupg.org> + + * sig-check.c (do_check): Print the signature key expire message + only in verbose mode and added the keyID. + +2001-01-09 Werner Koch <wk@gnupg.org> + + * status.c, status.h: New status USERID_HINT. + (write_status_text): Replace LF and CR int text by C-escape sequence. + + * passphrase.c (passphrase_to_dek): Fixed the NEED_PASSPHRASE + output. It does now always print 2 keyIDs. Emit the new + USERID_HINT. + +2001-01-08 Werner Koch <wk@gnupg.org> + + * g10.c, options.h: New option --no-expensive-trust-checks. + * keylist.c (list_keyblock): Act on this option. + +2001-01-04 Werner Koch <wk@gnupg.org> + + * g10.c (main): Set homedir only in the pre-parsing phase and + replace backslashes in the W32 version. + +2001-01-03 Werner Koch <wk@gnupg.org> + + * status.c, status.h : New status KEY_CREATED + * keygen.c (do_generate_keypair,generate_subkeypair): Emit it. + +2000-12-28 Werner Koch <wk@gnupg.org> + + * signal.c (got_fatal_signal): Remove lockfiles here because the + atexit stuff does not work due to the use of raise. Suggested by + Peter Fales. + * gpgv.c (remove_lockfiles): New stub. + +2000-12-19 Werner Koch <wk@gnupg.org> + + * status.c, status.h (cpr_get_no_help): New. + * keyedit.c (keyedit_menu): Use it here because we have our own + help list here. + +2000-12-18 Werner Koch <wk@gnupg.org> + + * mainproc.c (print_failed_pkenc): Don't print the sometimes + confusing message about unavailabe secret key. Renamed ... + (print_pkenc_list): ... to this and introduced failed arg. + (proc_encrypted): Print the failed encryption keys and then + the one to be used. + (proc_pubkey_enc): Store also the key we are going to use. + + * mainproc.c (check_sig_and_print): Don't list revoked user IDs. + (is_uid_revoked): New. + +2000-12-08 Werner Koch <wk@gnupg.org> + + * pipemode.c: Made the command work. Currently only for + non-armored detached signatures. + * mainproc.c (release_list): Reset the new pipemode vars. + (add_gpg_control): Handle the control packets for pipemode + * status.c, status.h: New stati {BEGIN,END}_STREAM. + +2000-12-07 Werner Koch <wk@gnupg.org> + + * g10.c: New option --allow-secret-key-import. + * import.c (import_keys,import_keys_stream): Honor this option. + (import): New arg allow_secret and pass that arg down to ... + (import_secret_one): to this and print a warning if secret key + importing is not allowed. + +2000-12-05 Werner Koch <wk@gnupg.org> + + * cipher.c (cipher_filter): Moved the end_encryption status ... + * encode.c (encode_simple,encode_crypt): to here + * sign.c (sign_file): and here. + + * status.c (mywrite): Removed. + (get_status_string): Removed the LFs from the strings. + (set_status_fd,is_status_enabed,write_status_text, + write_status_buffer): Replaced all mywrite by stdio calls and use + fdopen to create a strem. This is needed to make things smoother + in the W32 version. + +2000-12-04 Werner Koch <wk@gnupg.org> + + * import.c (merge_blocks): Increment n_sigs for revocations. + +2000-11-30 Werner Koch <wk@gnupg.org> + + * g10.c (main): Use iobuf_translate_file_handle for all options + with filehandles as arguments. This is function does some magic + for the W32 API. + + * verify.c (verify_signatures): Add a comment rant about the + detached signature problem. + * mainproc.c (proc_tree): Issue an error if a detached signature + is assumed but a standard one was found. + * plaintext.c (hash_datafiles): Don't fall back to read signature + from stdin. + * openfile.c (open_sigfile): Print verbose message only if the + file could be accessed. + +2000-11-24 Werner Koch <wk@gnupg.org> + + * passphrase.c [HAVE_DOSISH_SYSTEM]: Disabled all the agent stuff. + +2000-11-16 Werner Koch <wk@gnupg.org> + + * g10.c: New option --use-agent + * passphrase.c (agent_open,agent_close): New. + (agent_get_passphrase,agent_clear_passphrase): New. + (passphrase_clear_cache): New. + (passphrase_to_dek): Use the agent here. + * seckey-cert.c (do_check): Clear cached passphrases. + +2000-11-15 Werner Koch <wk@gnupg.org> + + * status.c (write_status_text): Moved the big switch to ... + (get_status_string): ... new function. + (write_status_buffer): New. + + * status.c (mywrite): New and replaced all write() by this. + + * status.c, status.h: Add 3 status lcodes for notaions and policy. + * mainproc.c (print_notation_data): Do status output of notations. + +2000-11-13 Werner Koch <wk@gnupg.org> + + * sign.c (clearsign_file): Use LF macro to print linefeed. + +2000-11-11 Paul Eggert <eggert@twinsun.com> + + Clean up the places in the code that incorrectly use "long" or + "unsigned long" for file offsets. The correct type to use is + "off_t". The difference is important on large-file hosts, + where "off_t" is longer than "long". + + * keydb.h (struct keyblock_pos_struct.offset): + Use off_t, not ulong, for file offsets. + * packet.h (dbg_search_packet, dbg_copy_some_packets, + search_packet, copy_some_packets): Likewise. + * parse-packet.c (parse, dbg_search_packet, search_packet, + dbg_copy_some_packets, copy_some_packets): Likewise. + * ringedit.c (keyring_search): Likewise. + + * parse-packet.c (parse): Do not use %lu to report file + offsets in error diagnostics; it's not portable. + * ringedit.c (keyring_search): Likewise. + +2000-11-09 Werner Koch <wk@gnupg.org> + + * g10.c (main): New option --enable-special-filenames. + +2000-11-07 Werner Koch <wk@gnupg.org> + + * g10.c (main): New command --pipemode. + * pipemode.c: New. + +2000-10-23 Werner Koch <wk@gnupg.org> + + * armor.c (armor_filter): Changed output of hdrlines, so that a CR + is emitted for DOS systems. + + * keygen.c (read_parameter_file): Add a cast for isspace(). + + * status.c (myread): Use SIGINT instead of SIGHUP for DOS. + +2000-10-19 Werner Koch <wk@gnupg.org> + + * g10.c: New option --ignore-crc-error + * armor.c (invalid_crc): New. + (radix64_read): Act on new option. + + * openfile.c (try_make_homedir): Klaus Singvogel fixed a stupid + error introduced on Sep 6th. + +2000-10-18 Werner Koch <wk@gnupg.org> + + * misc.c (print_cipher_algo_note): Don't print the note for AES. + Changed wording. + +2000-10-16 Werner Koch <wk@gnupg.org> + + * mainproc.c (do_proc_packets): Hack to fix the problem that + signatures are not detected when there is a MDC packet but no + compression packet. + + * g10.c (print_hashline): New. + (print_mds): Use above func with --with-colons. + + * mainproc.c (check_sig_and_print): Detect multiple signatures + and don't verify them. + +2000-10-14 Werner Koch <wk@gnupg.org> + + * mainproc.c (add_onepass_sig): There is an easier solution to the + error fixed yesterday; just check that we only have onepass + packets. However, the other solution provides an cleaner + interface and opens the path to get access to other information + from the armore headers. + (release_list): Reset some more variables. + +2000-10-13 Werner Koch <wk@gnupg.org> + + * mainproc.c (add_gpg_control): New. + (do_proc_packets): use it. + (proc_plaintext): Changed logic to detect clearsigns. + (proc_tree): Check the cleartext sig with some new code. + + * packet.h: New packet PKT_GPG_CONTROL. + * parse-packet.c (parse_gpg_control): New. + * misc.c (get_session_marker): New. + * armor.c (armor_filter): Replaced the faked 1-pass packet by the + new control packet. + + * keyedit.c (keyedit_menu): Allow batchmode with a command_fd. + * status.c (my_read): New. + (do_get_from_fd): use it. + +2000-10-12 Werner Koch <wk@gnupg.org> + + * keygen.c (keygen_add_std_prefs): Add Rijndael to the prefs. + +2000-10-07 Werner Koch <wk@gnupg.org> + + * gpgv.c: Add more stubs for ununsed code to make the binary smaller. + +Wed Oct 4 15:50:18 CEST 2000 Werner Koch <wk@openit.de> + + * sign.c (hash_for): New arg to take packet version in account, changed + call callers. + + * gpgv.c: New. + * Makefile.am: Rearranged source files so that gpgv can be build with + at least files as possible. + +Mon Sep 18 12:13:52 CEST 2000 Werner Koch <wk@openit.de> + + * hkp.c (not_implemented): Print a notice for W32 + +Fri Sep 15 18:40:36 CEST 2000 Werner Koch <wk@openit.de> + + * keygen.c (keygen_add_std_prefs): Changed order of preferences to + twofish, cast5, blowfish. + + * pkclist.c (algo_available): Removed hack to disable Twofish. + +Thu Sep 14 17:45:11 CEST 2000 Werner Koch <wk@openit.de> + + * parse-packet.c (dump_sig_subpkt): Dump key flags. Print special + warning in case of faked ARRs. + + * getkey.c (finsih_lookup): Hack so that for v4 RSA keys the subkey + is used for encryption. + +Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c (main): Default S2K algorithms are now SHA1 and CAST5 - this + should solve a lot of compatibility problems with other OpenPGP + apps because those algorithms are SHOULD and not optional. The old + way to force it was by using the --openpgp option whith the drawback + that this would disable a couple of workarounds for PGP. + + * g10.c (main): Don't set --quite along with --no-tty. By Frank Tobin. + + * misc.c (disable_core_dump): Don't display a warning here but a return + a status value and ... + * g10.c (main): ...print warnining here. Suggested by Sam Roberts. + +Wed Sep 13 18:12:34 CEST 2000 Werner Koch <wk@openit.de> + + * keyedit.c (keyedit_menu): Allow to use "debug" on the secret key. + + * ringedit.c (cmp_seckey): Fix for v4 RSA keys. + * seckey-cert.c (do_check): Workaround for PGP 7 bug. + +Wed Sep 6 17:55:47 CEST 2000 Werner Koch <wk@openit.de> + + * misc.c (print_pubkey_algo_note): Do not print the RSA notice. + * sig-check.c (do_signature_check): Do not emit the RSA status message. + * pubkey-enc.c (get_session_key): Ditto. + + * encode.c (encode_simple, encode_crypt): Fix for large files. + * sign.c (sign_file): Ditto. + +Wed Sep 6 14:59:09 CEST 2000 Werner Koch <wk@openit.de> + + * passphrase.c (hash_passphrase): Removed funny assert. Reported by + David Mathog. + + * openfile.c (try_make_homedir): Changes for non-Posix systems. + * g10.c (main): Take the default homedir from macro. + + * g10.c: The --trusted-key option is back. + * trustdb.c (verify_own_key): Handle this option. + (add_ultimate_key): Moved stuff from verify_own_key to this new func. + (register_trusted_key): New. + +Fri Aug 25 16:05:38 CEST 2000 Werner Koch <wk@openit.de> + + * parse-packet.c (dump_sig_subpkt): Print info about the ARR. + + * openfile.c (overwrite_filep): Always return okay if the file is + called /dev/null. + (make_outfile_name): Add ".sign" to the list of know extensions. + (open_sigfile): Ditto. + +Wed Aug 23 19:52:51 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c: New option --allow-freeform-uid. By Jeroen C. van Gelderen. + * keygen.c (ask_user_id): Implemented here. + +Fri Aug 4 14:23:05 CEST 2000 Werner Koch <wk@openit.de> + + * status.c (do_get_from_fd): Ooops, we used fd instead of opt.command_fd. + Thanks to Michael Tokarev. + +Tue Aug 1 20:06:23 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c: New opttion --try-all-secrets on suggestion from Matthias Urlichs. + * pubkey-enc.c (get_session_key): Quite easy to implement here. + +Thu Jul 27 17:33:04 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c: New option --merge-only. Suggested by Brendan O'Dea. + * import.c (import_one): Implemented it here + (import_secret_one): Ditto. + (print_stats): and give some stats. + +Thu Jul 27 12:01:00 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c: New options --show-session-key and --override-session-key + * pubkey-enc.c (hextobyte): New. + (get_override_session_key): New. + * mainproc.c (proc_pubkey_enc): Add session-key stuff. + * status.h, status.c (STATUS_SESSION_KEY): New. + +Thu Jul 27 10:02:38 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c (main): Use setmode(O_BINARY) for MSDOS while generating random bytes + (print_mds): Likewise for stdin. + * plaintext.c (handle_plaintext): Likewise for stdout. + +Mon Jul 24 10:30:17 CEST 2000 Werner Koch <wk@openit.de> + + * keyedit.c (menu_expire): expire date for primary key can be set again. + +Wed Jul 19 11:26:43 CEST 2000 Werner Koch <wk@openit.de> + + * keylist.c (is_uid_valid): New. + (list_keyblock): Print validity information for all user IDs. Note, this + has to be done at other places too; for now we have only minimal support. + +Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@openit.de> + + * helptext.c, pkclist.c: s/superseeded/superseded/ + +Mon Jul 10 16:08:57 CEST 2000 Werner Koch <wk@openit.de> + + * parse-packet.c (enum_sig_subpkt): Fixed testing on crtitical bit in case + of a NULL buffer. Reported by Peter Marschall. + +Wed Jul 5 13:28:45 CEST 2000 Werner Koch <wk@openit.de> + + * keyedit.c, keyid.c: Add some _() + + * argparse.c: Changed the flag to suppress --version handling to also + suppress --help. + +Wed Jun 28 11:54:44 CEST 2000 Werner Koch <wk@openit.de> + + * armor.c (armor_filter): Set sigclass to 0 in case of non-dash-escaped + clearsig. This makes this mode work again. + + * mainproc.c (proc_tree): Fixed handling of one-pass-sig packets in textmode. + Disabled the ugly workaround for PGP 5 - let's see whether thi breaks less + cases. Found by Ted Cabeen. + + * options.h (DBG_HASHING): New. All commented md_start_debug are now + controlled by this debug option. + + * sign.c (print_status_sig_created): New and called from 2 places. + + * keygen.c (gen_rsa): New, but commented. + (ask_algo): Commented support for RSA. + + * seckey-cert.c (protect_secret_key): Started to fix the code for v4 RSA + keys - it is not solved yet. However, we have time until, Sep 20th ;) + +Wed Jun 14 12:27:09 CEST 2000 Werner Koch <wk@openit.de> + + * status.c (init_shm_coprocessing): Changed the sequence of the get,attach + to cope with the changes in newer Linux kernels. This bug has been found + by <dmitri@advantrix.com> who also proposed this solution. Hopefully + this does not break gpg on to many systems. + + * cipher.c (write_header): Protect the IV with the MDC too. + * encr-data.c (decrypt_data): Likewise. + +Fri Jun 9 10:09:52 CEST 2000 Werner Koch <wk@openit.de> + + * g10.c: New options --no-auto-key-retrieve + * options.h (auto_key_retrieve): New. + * mainproc.c (check_sig_and_print): Implemented that. + +Wed Jun 7 19:19:09 CEST 2000 Werner Koch <wk@openit.de> + + * sig-check.c (do_check): Use EMULATE_MDENCODE also on v4 packets. + +Wed Jun 7 17:25:38 CEST 2000 Werner Koch <wk@openit.de> + + * cipher.c (write_header): Use plain CFB mode for MDC encrypted packets. + * encr-data.c (decrypt_data): Ditto. + +Mon Jun 5 23:41:54 CEST 2000 Werner Koch <wk@openit.de> + + * seskey.c (do_encode_md, encode_md_value): Add new arg v3compathack to work + around a bug in old versions. + * sig-check.c (do_check): use the aboved workaround when enabled. + * g10.c: New option --emulate-md-decode-bug + +Mon Jun 5 12:37:43 CEST 2000 Werner Koch <wk@openit.de> + + * build-packet.c (do_mdc): New. + (do_encrypted_mdc): Changed for the new proposal. + * parse-packet.c (parse_mdc): New. + (parse_encrypted): Fixed for the new proposal. + * packet.h (PKT_MDC): New. + * cipher.c (cipher_filter): Build the MDC packet here. + * g10.c (main): Enable --force-mdc. + * encr-data.c (mdc_decode_filter): Fixed for new MDC method + + * options.h(rfc2440): New. + * g10.c (main): Changed the selected values for --openpgp to not include + optional algorithms. + +Thu May 18 11:38:54 CEST 2000 Werner Koch <wk@openit.de> + + * keyedit.c (keyedit_menu): Add a keyword arg to the prompt. + + * status.c, status.h: Added 3 new status tokens. + * status.c (do_get_from_fd): New. + (cpr_enabled,cpr_get,cpr_get_hidden,cpr_kill_prompt, + cpr_get_answer_is_yes,cpr_get_answer_yes_no_quit): Modified to work + with the new function. + * g10.c: Add new option --command-fd. + + * status.c (progress_cb): New. + (set_status_fd): Register progress functions + +Fri May 12 14:01:20 CEST 2000 Werner Koch <wk@openit.de> + + * delkey.c (delete_key): Add 2 new status messages + * status.c, status.h (STATUS_DELETE_PROBLEM): New. + + Fixed years of copyright in all source files. + +Mon May 1 17:08:14 CEST 2000 Werner Koch <wk@openit.de> + + * trustdb.c (propagate_validity): Fixed the bug that only one uid + gets fully trusted even when all are signed by an ultimate key. + +Mon May 1 15:38:04 CEST 2000 Werner Koch <wk@openit.de> + + * getkey.c (key_byname): Always returned a defined context. Fixed + a segv for invalid user id specifications. Reported by Walter Koch. + + * getkey.c (get_user_id): I18ned "no user id" string. By Walter. + + * pkclist.c (do_show_revocation_reason): Typo fixes. + * helptext.c: Ditto. + + * armor.c (armor_filter): Fixed some CRLF issues. By Mike McEwan. + +Fri Apr 14 19:37:08 CEST 2000 Werner Koch <wk@openit.de> + + * pkclist.c (do_show_revocation_reason): New. + (show_revocation_reason): New and called at various places. + + * g10.c (main): Fixed small typo. + + * pkclist.c (do_we_trust): Act on always_trust but not for revoked + keys. Suggested by Chip Salzenberg. + + * g10.c: New option --lock-never. + + * ringedit.c (get_writable_keyblock_file): New. + * keygen.c (do_generate_keypair): Use this instead of the hardwired one. + + * keygen.c (ask_user_id): Check that the email address is in the + correct field. Suggested by Christian Kurz. + +Mon Apr 10 13:34:19 CEST 2000 Werner Koch <wk@openit.de> + + * keyedit.c (show_key_with_all_names): s/sbb/ssb/ + +Tue Mar 28 14:26:58 CEST 2000 Werner Koch <wk@openit.de> + + * trustdb.c (verify_own_keys): Do not print warning about unprotected + key when in quiet mode. + +Wed Mar 22 13:50:24 CET 2000 Werner Koch <wk@openit.de> + + * mainproc.c (print_userid): Do UTF8 conversion before printing. + * import.c (import_one): Ditto. + (import_secret_one): Ditto. + (delete_inv_parts): Ditto. + +Thu Mar 16 16:20:23 CET 2000 Werner Koch <wk@openit.de> + + * keylist.c (print_key_data): Handle a NULL pk gracefully. + + * getkey.c (merge_one_pk_and_selfsig): Fixed silly code for + getting the primary keys keyID but kept using the one from the + subkey. + * pubkey-enc.c (get_it): Print a note for expired subkeys. + + * getkey.c (has_expired): New. + (subkeys_expiretime): New. + (finish_lookup): Check for expired subkeys needed for encryption. + (merge_keys_and_selfsig): Fixed expiration date merging for subkeys. + + * keylist.c (list_keyblock): Print expiration time for "sub". + (list_one): Add missing merging for public keys. + * mainproc.c (list_node): Ditto. + +2000-03-14 13:49:38 Werner Koch (wk@habibti.openit.de) + + * keygen.c (keyedit_menu): Do not allow to use certain commands + while the secret key is selected. + +2000-03-09 12:53:09 Werner Koch (wk@habibti.openit.de) + + * keygen.c (ask_expire_interval): Movede parsig to ... + (parse_expire_string): ... this new function. And some new control + commands. + (proc_parameter_file): Add expire date parsing. + (do_generate_keypair): Allow the use of specified output files. + +2000-03-08 10:38:38 Werner Koch (wk@habibti.openit.de) + + * keygen.c (ask_algo): Removed is_v4 return value and the commented + code to create Elg keys in a v3 packet. Removed the rounding + of key sizes here. + (do_create): Likewise removed arg v4_packet. + (gen_elg): Likewise removed arg version. Now rounding keysizes here. + (gen_dsa): Rounding keysize now here. + (release_parameter_list): New + (get_parameter*): New. + (proc_parameter_file): New. + (read_parameter_file): New. + (generate_keypair): Splitted. Now uses read_parameter_file when in + batch mode. Additional argument to specify a parameter file. + (do_generate_keypair): Main bulk of above fucntion and uses the + parameter list. + (do_create): Don't print long notice in batch mode. + * g10.c (main): Allow batched key generation. + +Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de> + + * pubkey-enc.c (get_it): Print a note about unknown cipher algos. + + * g10.c (opts): Add a note to the help listing about the man page + and removed some options from the help listing. + + * keyedit.c (print_and_check_one_sig): Use a new function to truncate + the output of the user ID. Suggested by Jan-Benedict Glaw. + +Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de> + + * helptext.c: typo fix. + +Thu Feb 17 13:39:32 CET 2000 Werner Koch <wk@gnupg.de> + + * revoke.c: Removed a bunch of commented code. + + * packet.h (SIGSUBPKT_REVOC_REASON): New. + * build-packet.c (build_sig_subpkt): Support new sub packet. + * parse-packet.c (parse_one_sig_subpkt): Ditto. + (dump_sig_subpkt): Ditto. + * revoke.c (ask_revocation_reason): New. + (release_revocation_reason_info): New. + (revocation_reason_build_cb): New. + (gen_revoke): Ask for reason. + * main.h (struct revocation_reason_info): Add declaration. + * keyedit.c (menu_revsig): Add support for revocation reason. + (menu_revkey): Ditto. + (sign_uid_mk_attrib): Renamed to ... + (sign_mk_attrib): ... this, made static and add support for reasons. + +Tue Feb 15 08:48:13 CET 2000 Werner Koch <wk@gnupg.de> + + * build-packet.c (build_packet): Fixed fixing of old comment packets. + + * import.c (import_keys): Fixed importing from stdin when called with + nnames set to zero as it normally happens. + +Mon Feb 14 14:30:20 CET 2000 Werner Koch <wk@gnupg.de> + + * sig-check.c (check_key_signature2): Add new arg r_expired. + (do_signature_check): New arg to pass it down to ... + (do_check): New arg r-expire which is set when the signature + has expired. + * trustdb.c (check_sig_record): Set SIGF_EXPIRED flag and set + the expiretime to zero so that thi signature will not be checked + anymore. + +Fri Feb 11 17:44:40 CET 2000 Werner Koch <wk@gnupg.de> + + * g10.c (g10_exit): Update the random seed_file. + (main): Set the random seed file. New option --no-random-seed-file. + +Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de> + + * keyedit.c (menu_expire): Fixed segv due to unitialized sub_pk. + By Rmi. + +Thu Feb 10 11:39:41 CET 2000 Werner Koch <wk@gnupg.de> + + * keylist.c (list_keyblock): Don't print warnings in the middle of + regulat output lines. By Rmi. + + * sig-check.c: Include options.h + +Wed Feb 9 15:33:44 CET 2000 Werner Koch <wk@gnupg.de> + + * gpg.c: New option --ignore-time-conflict + * sig-check.c (do_check): Implemented this option. + * trustdb.c (check_trust): Ditto. + * sign.c (do_sign): Ditto. + * keygen.c (generate_subkeypair): Ditto. + + * encode.c (encode_simple): use iobuf_cancel after open failure. + Reported by Huy Le. + +Fri Jan 14 18:32:01 CET 2000 Werner Koch <wk@gnupg.de> + + * packet.h (STRING2KEY): Changed mode from byte to int. + * parse-packet.c (parse_key): Add the special GNU protection stuff + * build-packet.c (so_secret_key): Ditto. + * seckey-cert.c (do_check): Ditto. + * keyedit.c (change_passphrase): Ditto. + * export.c (export_secsubkeys): New. + (do_export_stream): Hack to export the primary key using mode 1001. + * g10.c: New command --export-secret-subkeys + +Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de> + + * armor.c (is_armored): Check for 1-pass-sig packets. Reported by + David Hallinan <hallinan@rtd.com>. + (armor_filter): Replaced one LF by the LF macro. Reported by + Wolfgang Redtenbacher. + +Wed Jan 5 11:51:17 CET 2000 Werner Koch <wk@gnupg.de> + + * g10.c (main): Reset new global flag opt.pgp2_workarounds + when --openpgp is used. + * mainproc.c (proc_plaintext): Do the PGP2,5 workarounds only + when the global flag is set. + (proc_tree): Ditto. + * textfilter.c (copy_clearsig_text): Ditto. + * armor.c (armor_filter): Ditto. + + * g10.c: New option --list-only + * mainproc.c (proc_tree): Don't do it if opt.list_only is active. + (proc_pubkey_enc): Implement option. + + * status.h, status.c ({BEGIN,END}_{EN,DE}CRYPTION): New. + * cipher.c (cipher_filter): New status outputs. + * mainproc.c (proc_encrypted): New status outputs. + +Fri Dec 31 14:08:15 CET 1999 Werner Koch <wk@gnupg.de> + + * armor.c (armor_filter): Made the "Comment:" header translatable. + + * hkp.c (hkp_import): Make sure that the program does not return + success when there is a connection problem. Reported by Phillip Jones. + +Sun Dec 19 15:22:26 CET 1999 Werner Koch <wk@gnupg.de> + + * armor.c (LF): Use this new macro at all places where a line LF + is needed. This way DOSish textfiles should be created when the + input data is also in dos mode. + * sign.c (LF): Ditto. + * textfilter.c (LF): Ditto. + (copy_clearsig_text): Disabled the forcing of CR,LF sequences + for DOS systems. + + * plaintext.c (handle_plaintext): Fixes for line endings on DOS. + and react on a LF in cleartext. + * armor.c (fake_packet): Restore the original line ending after + removing trailing spaces. + + * signal.c (got_fatal_signal): DOS fix. + +Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de> + + * mainproc.c (print_failed_pkenc): Fix for unknown algorithm. + Found by fygrave@epr0.org. + +Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.de> + + * hkp.c: i18n the strings. + +Sat Dec 4 15:32:20 CET 1999 Werner Koch <wk@gnupg.de> + + * trustdb.c (verify_key): Shortcut for ultimately trusted keys. + +Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de> + + * pkclist.c (build_pk_list): Validate the trust using the namehash + if this one has been set by the key lookup. + + * g10.c: Add --delete-secret-key to the help page. + + * openfile.c (copy_options_file): Made static. + (try_make_homedir): New. + * ringedit.c (add_keyblock_resource): Use the try_make_hoemdir logic. + * tdbio.c (tdbio_set_dbname): Likewise. + + * keygen.c (generate_user_id): Use m_alloc_clear() here. We should + better use an allocation function specific to the user_id packet. + + * keygen.c (keygen_add_std_prefs): Changed symmetric preferences + to include Blowfish again. This is due to it's better speed compared + to CAST5. + + * g10.c (strusage): Print the home directory. + + * armor.c (armor_filter): Take action on the cancel control msg. + * filter.h (armor_filter_context_t): Add cancel flag. + +Mon Nov 29 21:52:11 CET 1999 Werner Koch <wk@gnupg.de> + + * g10.c: New option --fast-list-mode .. + * keylist.c (list_keyblock): .. and implemented. + * mainproc.c (list_node): Ditto. + + * import.c (mark_non_selfsigned_uids_valid): Fixed the case that there + is a uid without any packet following. + +Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de> + + * mainproc.c (proc_plaintext): Never enable the hash processing + when skip_verify is active. + + * armor.c (parse_header_line): Stop parsing on a WS line too. + Suggested by Aric Cyr. + + * tdbdump.c (HEXTOBIN): Changed the name of the argument, so that + traditional cpp don't mess up the macros. Suggested by Jos Backus. + + * mainproc.c (list_node): Print the PK algo in the --with-colon mode. + * keylist.c (list_keyblock): Ditto. + + * signal.c (got_fatal_signal): Found the reason why exit(8) did not + work - it is better to set the disposition back to default before + raising the signal. Print the notice on stderr always. + +Fri Nov 12 20:33:19 CET 1999 Werner Koch <wk@gnupg.de> + + * g10.c (make_username): Swapped the logic. + * keylist.c (public_key_list): Now takes a STRLIST as arg and moved + the creation ot this list to the caller, so that he can copy with + UTF-conversion of user IDs. Changed all callers. + (secret_key_list): Likewise. + + * getkey.c (get_user_id_string_native): New and ... + * encode.c (write_pubkey_enc_from_list): ... use it here. + + * pubring.asc: Updated. + + * packet.h (PKT_PHOTO_ID): New. + * parse-packet.c (parse_photo_id): New. + * build-packet.c (do_user_id: Handle photo IDs. + (build_packet): Change CTB for photo IDs + * free-packet.c (free_user_id): Release memory used for photo IDs + * sig-check.c (hash_uid_node): Handle photo IDs too. + * trustdb.c (print_uid_from_keyblock): Hash photo ID. + (make_uid_records): Ditto. + * getkey.c (find_by_name): Ditto. + * keyedit.c (show_prefs): Ditto. + * keylist.c (list_keyblock): Ditto. + +Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de> + + * keygen.c (ask_expire_interval): Print a warning for systems + with a signed 32 time_t if the exiration time is beyoind 2038. + +Fri Oct 8 20:40:50 CEST 1999 Werner Koch <wk@gnupg.de> + + * ringedit.c (enum_keyblocks): The last fix way really stupid; + reverted and set rt to Unknown. + +Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de> + + * ringedit.c (enum_keyblocks): Zero the entire kbpos out on open. + + * g10.c (oEntropyDLL): Removed option. + (main): Made the warning on development versions more verbose. + + * g10.c (oHonorHttpProxy): New option. + * hkp.c (hkp_ask_import,hkp_export): Implement this option. + * options.skel: Enable this option for new installations + +Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de> + + * import.c (import_keys): Changed calling interface, adjusted caller. + (import): Moved printing of stats out ... + (print_stats): New. ... to here. + (import_keys_stream): Call stats print here. + (import_keys): Print stats as totals for all files. + + * tdbio.h (DIRF_NEWKEYS): New + * tdbio.c (tdbio_dump_record): Print the new flag. + * trustdb.c (check_trust_record): New arg sigs_only. Adapted all + callers. + (do_update_trust_record): Removed recheck arg and add a new sigs_only + do we can later improve on the performance. Changed all callers too. + (check_trustdb): Evalutate the new flag and add a status output. + Do a check when the dir record has not been checked. + (build_cert_tree): Evaluate the new flag. + (check_trust): Ditto. Do a trust_record check, when the dir record + is not marked as checked. + (mark_fresh_keys): New. + (clear_lid_table): New. + (sync_trustdb): New. + * import.c (import_keys): Call sync_trustdb() after processing. + (import_keys_stream): Ditto. + * tdbdump.c (import_ownertrust): Ditto. + + * import.c (import_revoke_cert): Notify the trust DB. + (do_update_trust_record): Use |= to set the REVOKED bit and not &=; + shame on me for this bad copy+paste introduced bug. + (do_we_trust): Add trustmask to allow revoked key override to work. + Chnaged are to allow return of a mofified trustlevel. Adapted the + one caller. + + * g10.c: New options --emulate-3des-s2k-bug + * passphrase.c (hash_passphrase): Implemented above. + + * mainproc.c (proc_tree): Check for standalone signatures. + (do_check_sig): Print a notice for a standalone revocation + (check_sig_and_print): Do not print an error for unchecked standalone + revocations. + +Tue Sep 28 20:54:37 CEST 1999 Werner Koch <wk@gnupg.de> + + * encode.c (encode_simple): Use new CTB when we don't have the + length of the file. This is somewhat strange as the comment above + indicates that this part is actually fixed for PGP 5 - maybe I simply + lost the source line, tsss. + + * armor.c (armor_filter): Set a flag if no OpenPGP data has been found. + * verify.c (verify_signatures): Add an error helptext. + +Thu Sep 23 19:24:30 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * openfile.c (open_outfile): Fixed the 8dot3 handling. + + * passphrase.c (passphrase_to_dek): Print uid using utf8 func. + * delkey.c (delete_key): Ditto. + * pkclist.c (show_paths,do_edit_ownertrust,do_we_trust): Ditto + (do_we_trust_pre): Ditto. + * trustdb.c (print_user_id,check_uidsigs): Ditto. + * revoke.c (gen_revoke,ask_revoke_sig): Ditto. + +Thu Sep 23 09:52:58 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * verify.c (print_file_status): New. + (verify_one_file): Moved status print to th new fnc. Add error status. + * status.c, status.h (STATUS_FILE_ERROR): New + +Wed Sep 22 10:14:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * openfile.c (make_outfile_name): Use case-insenstive compare for + DOS systems. Add ".pgp" to the list of know extensions. + (open_outfile): For DOS systems try to replace the suffiy instead of + appending it. + + * status.c, status.h: Add STATUS_FILE_{START,DONE}. + * verify.c (verify_one_file): Emit these new stati. + + * sign.c (clearsign_file): Avoid duplicated Entries in the "Hash:" + line. Those headers are now only _not_ printed when there are + only old-style keys _and_ all hashs are MD5. + +Mon Sep 20 12:24:41 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * verify.c (verify_files, ferify_one_file): New. + * g10.c: New command --verify-files + +Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c: Add UK spelling as alias for armor options ;-) + + * import.c (append_uid): Fixed a SEGV when there is no selfsig and + no subkey. + (merge_sigs): Ditto. Removed the assertion. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c: New option --entropy-dll-name + +Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * signal.c (got_fatal_signal): Print message using write(2) and + only for development versions. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * tdbio.c (tdbio_set_dbname): Use mkdir macro + * ringedit.c (add_keyblock_resource): Ditto. + +Fri Sep 3 10:04:45 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (build_pk_list): Skip keys set with --encrypt-to also + when asking for a key. + + * plaintext.c (handle_plaintext): Make sure that we don't read a + second EOF in the read loop for partial length packets. + + * mainproc.c (check_sig_and_print): print user ID as utf-8. + +Thu Sep 2 16:40:55 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * import.c (merge_blocks): First add new subkeys, then merge subkey + certificates. + (merge_sigs): Don't merge subkey signatures here. + +Wed Sep 1 15:30:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keygen.c (ask_expire_interval): Fixed bug related to cpr_xx (tnx + Francis J. Lacoste). + +Tue Aug 31 17:20:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * plaintext.c (do_hash): Hash CR,LF for a single CR. + (ask_for_detached_datafile): Changed arguments to be closer to + those of hash_datafiles and cleanup the code a bit. + * mainproc.c (proc_tree): Workaround for pgp5 textmode detached + signatures. Changed behavior of asking for data file to be the same + as with provided data files. + + * keylist.c (list_keyblock): Use UTF8 print functions. + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * import.c (chk_self_sigs): some s/log_error/log_info/ so that gpg + does not return an error if a key has some invalid packets. + + * helptext.c: Fixed some typos and changed the way the + translation works. The english text is now the keyword for gettext + and not anymore the keyword supplied to the function. Done after + some discussion with Walter who thinks this is much easier for the + translators. + + * misc.c (disable_core_dumps): Don't do it for DOSish systems. + + * signal.c (signal_name): Bounds check on signum. + +Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pubring.asc: Updated. + + * pkclist.c (do_we_trust_pre,check_signatures_trust): Do not print + the warning about --always_trust when --quiet is used. + + * pkclist.c (fpr_info): New and called at several places. + + * parse-packet.c (dump_sig_subpkt): List revocation key contents. + +Mon Jul 26 09:34:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (build_pk_list): Fixed typo in format string. + + * trustdb.c (create_shadow_dir): Don't translate the error string. + + * g10.c (main): Fixed spelling of user-id. + * getkey.c (find_by_name_pk,find_by_name_sk, + find_by_keyid,find_by_keyid_sk): Ditto and translate it. + * import.c (mark_non_selfsigned_uids_valid,delete_inv_parts): Ditto. + + +Mon Jul 26 01:01:39 CEST 1999 Michael Roth <mroth@nessie.de> + + * g10.c, options.h: New options --no-literal and --set-filesize + + * encode.c (encode_simple, encode_crypt): Support for the options + --no-literal and --set-filesize. + + * sign.c (sign_file): ditto. + +Fri Jul 23 13:53:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * ringedit.c (enum_keyblocks): Removed annoying error message in cases + when we have no keyring at all to enum. + + * getkey.c (classify_user_id): Rewrote to relax the recognition of + keyIDs and fingerprints (Michael). + + * mainproc.c (check_sig_and_print): Print status NO_PUBKEY. + (print_failed_pkenc): Print status NO_SECKEY. + + * import.c (mark_non_selfsigned_uids_valid): New. + * g10.c: New option --allow-non-selfsigned-uid. + + * pkclist.c (print_fpr): New. + (do_we_trust_pre): Print the fpr before asking whether to use the key + anyway. + (do_edit_ownertrust): Likewise. + +Thu Jul 22 20:03:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * ringedit.c (enum_keyblocks): Removed annoying error message in cases + when we have no keyring at all to enum. + + * getkey.c (classify_user_id): Rewrote to relax the recognition of + keyIDs and fingerprints (Michael). + + * mainproc.c (check_sig_and_print): Print status NO_PUBKEY. + (print_failed_pkenc): Print status NO_SECKEY. + + * import.c (mark_non_selfsigned_uids_valid): New. + * g10.c: New option --allow-non-selfsigned-uid. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c: New options --disable-{cipher,pubkey}-algo. + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * status.h (STATUS_IMPORTED): New. + * import.c (import): Print some status information (Holger Schurig). + + * g10.c (main): Make --no-greeting work again. Add a warning when + --force-mds is used. + +Tue Jul 13 17:39:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (do_edit_ownertrust): Changed the way help works. + (build_pk_list): Implemented default recipient stuff. + * g10.c: New options --default-recipient[-self] + (main): Suppress greeting in most cases, entering a passphrase or + a missing value is not considered to be interactive use. + Merged --print-md and --print-mds; the latter is now obsolete. + Changed the way --gen-random works and documented it. + Changed the way --gen-prime works and add a man entry. + * g10.c (MAINTAINER_OPTIONS): Removed. + +Mon Jul 12 18:45:57 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keyedit.c (keyedit_menu): Add arg sign_mode and changed callers + * g10.c (main): New command --lsign-key. + +Mon Jul 12 14:55:34 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mainproc.c (kidlist_item): New. + (release_list): Release failed pk-enc-list. + (print_failed_pkenc): New + (proc_encrypted): Print info about failed PK enc. + + * openfile.c (make_outfile_name): s/error/info/ + + * passphrase.c (passphrase_to_dek): Return an empty passphrase when + in batch mode and don't make the warning message fatal + * seckey-cert.c (check_secret_key): Try only once when in batch mode. + + * g10.c (make_username): New. + +Thu Jul 8 16:21:27 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * packet.h (PKT_ring_trust): New + * parse-packet.c (parse_trust): Store trust value + * build-packet (build_packet): Ignore ring trust packets. + * mainproc.c (add_ring_trust): New. + (list_node): Print "rtv" records. + * g10.c: New option --with-fingerprint. + + * trustdb.c (verify_own_keys): Don't insert if we are dry running + (check_trust): Ditto. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Support for libtool. + + * keygen.c (ask_expire_interval): Hack to allow for an expire date. + + * trustdb.c (do_update_trust_record,update_trust_record): Splitted. + (check_trust_record): New. + (check_trust,build_cert_tree): Check the dir record as needed. + (upd_pref_record): Removed. + (make_pref_record): New. + (propagate_validity): Stop as soon as we have enough validity. + + * tbdio.c (MAX_CACHE_ENTRIES_HARD): Increased the limit. + + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c (g10_exit): Dump random stats. + + * sig-check.c (check_key_signature,check_key_signature2): Enhanced + version and wrapper for old function. + (do_signature_check,signature_check): Ditto. + +Thu Jul 1 12:47:31 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * keyedit.c (show_key_with_all_names): Print a notice for disabled keys. + (enable_disable_keys): Add functionality + * pkclist.c (edit_ownertrust): preserve disabled state. + (build_pk_list): Skip disabled keys. + * trustdb.c (upd_one_ownertrust): Ditto. + (build_cert_tree): Mask the ownertrust. + (trust_letter): Mask the value. + (do_check): Take disabled flag into account. + + * passphrase.c (passphrase_to_dek): Add a pubkey_algo arg and changed + all callers. + + * g10.c (utf8_strings): 2 new options. + + * trustdb.c (insert_trust_record_by_pk): New, replaces the next one. + (insert_trust_record): Now takes a keyblock as arg. Changed all + callers to use the appropritae function. + + * openfile.c (ask_outfile_name): New. + * plaintext.c (handle_plaintext): Ask for filename if there is + no valid syntax. Don't use fname varbatim but filter it. + +Tue Jun 29 21:44:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * trustdb.h (TRUST_FLAG_DISABLED): New. + + * status.c (USE_CAPABILITIES): Capabilities support (Remi). + + * tdbio.c : Added new fields to the DIR record. + (tdbio_write_record): Fixed the update of the hash tables. + (tdbio_delete_record): Drop the record from the hash tables. + (drop_from_hashtbl): New. + + * status.c (cpr_get): Special online help mode. + * helptext.c ("keyedit.cmd"): Removed. + * keyedit.c (keyedit_menu): Use only help system. + (enable_disable_key): New bit doies not yet work. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * dearmor.c (enarmor_file): Fixed comment string. + * tdbdump.c (export_ownertrust): Text fix. + * tbio.c (tdbio_invalid): Ditto. + + * parse-packet.c (parse_key): Made temp buffer larger. + + * Makefile.am (install-data-local): Add missing backslashes + +Tue Jun 15 12:21:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c (main): Made iterated+salted the default S2K method. + + * Makefile.am (install-data-local): Use DESTDIR. + + * passphrase.c (passphrase_to_dek): Emit missing-passphrase while in + batchmode. + + * parse-packet.c (parse_pubkeyenc): Fixed a SEGV. + +Mon Jun 14 21:18:54 CEST 1999 Michael Roth <mroth@nessie.de> + + * g10.c: New options --openpgp, --no-tty, --emit-version, + --default-comment and --lock-multiple + +Thu Jun 10 14:18:23 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * free-packet.c (free_encrypted): Fixed EOF case (Remi). + (free_plaintext): Ditto. + + * helptext.c (keyedit.delsig.unknown): New (Remi). + * keyedit.c (print_and_check_one_sig): Add arg print_without_key and + changed all callers to make use of it (Remi): + +Tue Jun 8 13:36:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keylist.c (print_key_data): New and called elsewhere. + * g10.c: New option --with-key-data + +Wed Jun 2 14:17:19 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mainproc.c (proc_tree): Yet another bad hack to cope with + broken pgp2 created detached messages in textmode. + +Tue Jun 1 16:01:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * openfile.c (make_outfile_name): New. + * plaintext.c (handle_plaintext): Outputfile is now the inputfile + without the suffix. + * g10.c: New option --use-embedded-filename + +Mon May 31 19:41:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c (main): Fix for SHM init (Michael). + + * compress.c, encr-data.c, mdfilter.c, + plaintext.c, free-packet.c: Speed patches (Rmi). + +Thu May 27 09:40:55 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * status.c (cpr_get_answer_yes_no_quit): New. + * keyedit.c (menu_delsig): New. + (check_all_keysigs): Splitted. + (print_and_check_one_sig): New. + +Wed May 26 14:36:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * build-packet.c (build_sig_subpkt): Support large packets. + * parse-packet.c (enum_sig_subpkt): Replaces parse_sig_subpkt. + * mainproc.c (print_notation_data): Print all notation packets. + * g10.c (add_notation_data): Add a way to specify the critical flag. + (main): Add option --set-policy-url. + (check_policy_url): Basic checks. + * sign.c (mk_notation_and_policy): Replaces mk_notation. + + * parse-packet.c (can_handle_critical): Moved decision whether we can + handle critical subpacket to an extra function. + +Tue May 25 19:50:32 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * sign.c (sign_file): Always use compression algo 1 for signed + onyl file becuase we can be sure the the verifier supports other + algorithms. + + * build-packet.c (build_sig_subpkt): Support for notation data. + * sign.c (sign_file,clearsign_file,make_keysig_packet): Ditto. + (mk_notation): New. + * g10.c (add_notation_data): New and add option -N + * mainproc.c (print_notation_data): New. + (check_sig_and_print): Print any notation data of the signed text. + +Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (check_signatures_trust): Print a warning and return + immediateley if opt.always_trust is true. + + * g10.c (main): Corrected handling of no-default-keyring + + * pkclist.c (algo_available): Disable Twofish until we have settled + how to do the MDC. + + * hkp.c: Disable everything for mingw32 + +Sat May 22 22:47:26 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mainproc.c (check_sig_and_print): Add sig creation time to the + VALIDSIG status output. Add more info to the ERRSIG output. + * sig-check.c (signature_check): Add sig time after epoch to SIG_ID. + + * import.c (import_one): Merge duplicate user IDs. + (collapse_uids): New. + * kbnode.c (move_kbnode): New. + (remove_kbnode): New. + * keyedit.c (keyedit_menu): Call collapse_uids. + + * g10.c: new option --logger-fd. + + * import.c: s/log_*_f/log_*/ + +Thu May 20 14:04:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * misc.c (pull_in_libs): do the volatile only for gcc + + * sig-check (signature_check): Emit SIG_iD only for classes 0 and 1. + + * armor.c (armor_filter): Add detection of PGP2 created clearsigs. + (fake_packet): A tab is not a WS for pgp2 - handle this. + * textfilter.c (len_without_trailing_chars): New. + (copy_clearsig_text): Add pgp2mode arg. + * sign.c (clearsign_file): pass old_style to the above fnc. + + +Wed May 19 16:04:30 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c: New option --interactive. + + * mainproc.c (proc_plaintext): Add workaround for pgp2 bug + (do_check_sig): Ditto. + (proc_tree): Ditto. + * plaintext.c (do_hash): Ditto. + (hash_datafiles): Ditto, add an arg, changed all callers. + * mdfilter.c (md_filter): Add support for the alternate hash context. + +Mon May 17 21:54:43 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * parse-packet.c (parse_encrypted): Support for PKT_ENCRYPTED_MDC. + * build-packet.c (do_encrypted_mdc): Ditto. + * cipher.c (write_header): Add mdc hashing. + (cipher_filter): write out the hash. + * mainproc.c (do_proc_packets): Add PKT_ENCRYPTED_MDC. + * encr-data.c (decrypt_data): Add mdc hashing. + (mdc_decode_filter): New. + + * parse-packet.c (parse_sig_subpkt): Fixed stupid bug for subpkt + length calculation + (parse_signature): Fixed even more stupid bug. + +Sat May 8 19:28:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * build-packet.c (do_signature): Removed MDC hack. + * encode.c (encode_crypt_mdc): Removed. + * mainproc.c (do_check_sig): Removed MDC hack. + (check_sig_and_print): Ditto. + * parse-packet.c (parse_signature): Ditto. + * sig-check.c (mdc_kludge_check): Ditto. + * free-packte.c (copy_signature, free_seckey_enc): Ditto. + + * parse-packet.c (parse_signature,parse_key): Store data of + unknown algorithms with mpi_set_opaque inseatd of the old + faked data stuff. + (read_rest): Removed. + (read_rest2): Renamed to read_rest + * build-packet.c (write_fake_data): Use mpi_get_opaque. + * free-packet.c (cp_fake_data): Removed and cahnged all callers + to use mpi_copy. + (free_pubkey_enc,free_seckey_enc,release_public_key_parts, + release_secret_key_parts): Use mpi_free for opaque data. + +Thu May 6 14:18:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * trustdb.c (check_trust): Check for revoked subkeys. + * pkclist.c (do_we_trust): Handled revoked subkeys. + (do_we_trust_pre): Ditto. + (check_signatures_trust): Ditto. + + * build-packet.c (hash_public_key): Fix for ancient g10 keys. + + * mainproc.c (do_proc_packets): Return EOF if no data has been read. + * g10.c (main): Catch errors for default operation. + +Thu Apr 29 12:29:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * sign.c (sign_file): Fixed hashing in case of no subpackets. + (clearsign_file): Ditto. + (make_keysig_packet): Ditto. + +Wed Apr 28 13:03:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keyedit.c (keyedit_menu): Add new command revkey. + * (menu_revkey): New. + + +Mon Apr 26 17:48:15 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * parse-packet.c (parse_signature): Add the MDC hack. + * build-packet.c (do_signature): Ditto. + * free-packet.c (free_seckey_enc,copy_signature,cmp_signatures): Ditto. + * mainproc.c (do_check_sig): Ditto. + * sig-check.c (mdc_kludge_check): New. + * encode.c (encrypt_mdc_file): New. + + * keyedit.c (check_all_keysigs): List revocations. + * (menu_revsig): New. + * sign (make_keysig_packet): Support for class 0x30. + +Sun Apr 18 20:48:15 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (select_algo_from_prefs): Fixed the case that one key + has no preferences (Remi Guyomarch). + + keylist.c (list_keyblock): ulti_hack to propagate trust to all uids. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * seckey-cert.c (do_check): Use real IV instead of a 0 one, so that + it works even if the length of the IV doesn't match the blocksize. + Removed the save_iv stuff. + (protect_secret_key): Likewise. Create the IV here. + * packet.h (PKT_secret_key): Increased size of IV field and add a + ivlen field. + * parse-packet.c (parse_key): Use the len protect.ivlen. + * build-packet.c (do_secret_key). Ditto. + + * getkey.c (key_byname): Close keyblocks. + + * Makefile.am (gpgm): Removed this + * g10.c: Merged gpg and gpgm + + * import.c (import): Utilize option quiet. + * tdbio.c (tdbio_set_dbname): Ditto. + * ringedit.c (add_keyblock_resource,keyring_copy): Ditto. + + * keyedit.c (sign_uids): Add some batch support. + + * g10.c (main): add call to tty_batchmode. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * status.c (write_status_text): Some more status codes. + * passphrase_to_dek (passphrase_to_dek): add a status code. + * seckey_cert.c (check_secret_key): Likewise. + + * encr-data.c (decrypt_data): Reverse the last changes + * cipher.c (write_header): Ditto. + + * parse-packet.c (parse_key): Dropped kludge for ancient blowfish mode. + +Thu Apr 8 09:35:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mainproc.c (proc_encrypted): Add a new status output + * passphrase.c (passphrase_to_dek): Ditto. + * status.h status.c: Add new status tokens. + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * encr-data.c (decrypt_data): Fixes for 128 bit blocksize + * cipher.c (write_header): Ditto. + * seckey-cert.c (do_check): Ditto. + (protect_secret_key). Ditto. + * misc.c (print_cipher_algo_note): Twofish is now a standard algo. + + * keygen.c (do_create): Fixed spelling (Gal Quri) + (ask_keysize): Only allow keysizes up to 4096 + + * ringedit.c (add_keyblock_resource): chmod newly created secrings. + + * import.c (delete_inv_parts): Fixed accidently deleted subkeys. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c: Removed duped include (John Bley) + * mainproc.c: Ditto. + + * build-packet.c (hash_public_key): Fixed hashing of the header. + + * import.c (delete_inv_parts): Allow import of own non-exportable sigs. + +Sat Mar 20 13:59:47 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c (fake_packet): Fix for not not-dash-escaped + +Sat Mar 20 11:44:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c (main): Added command --recv-keys + * hkp.c (hkp_import): New. + +Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * trustdb.c (check_trust): add new arg add_fnc and changed all callers. + (do_check): Ditto. + (verify_key): Ditto. + (propagate_validity): Use the new add_fnc arg. + (print_user_id): Add the FILE arg. + (propagate_ownertrust): New. + * pkclist.c (add_ownertrust_cb): New and changed the add_ownertrust + logic. + + * getkey.c (get_keyblock_bylid): New. + * trustdb.c (print_uid_from_keyblock): New. + (dump_tn_tree_with_colons): New. + (list_trust_path): Add colon print mode. + + * trustdb.c (insert_trust_record): Always use the primary key. + + * encode.c (encode_simple): Added text_mode filter (Rmi Guyomarch) + (encode_crypt): Ditto. + + * mainproc.c (proc_pubkey_enc): Added status ENC_TO. + * armor.c (armor_filter): Added status NODATA. + * passphrase.c (passphrase_to_dek): Always print NEED_PASSPHRASE + * seckey_cert.c (check_secret_key): Added BAD_PASS status. + + * g10.c (main): Set g10_opt_homedir. + +Sun Mar 14 19:34:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keygen.c (do_create): Changed wording of the note (Hugh Daniel) + +Thu Mar 11 16:39:46 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * tdbdump.c: New + + * trustdb.c (walk_sigrecs,do_list_sigs,list_sigs, + list_records,list_trustdb,export_ownertrust,import_ownertrust): Moved + to tdbdump.c + (init_trustdb): renamed to setup_trustdb. Changed all callers. + (do_init_trustdb): renamed to init_trustdb(). + * trustdb.c (die_invalid_db): replaced by tdbio_invalid. + * tdbio.c (tdbio_invalid): New. + + * import.c (delete_inv_parts): Skip non exportable signatures. + * keyedit.c (sign_uid_mk_attrib): New. + (sign_uids): Add the local argument. + (keyedit_menu): New "lsign" command. + * trustdb.c (register_trusted_key): Removed this and all related stuff. + * g10.c (oTrustedKey): Removed option. + + * tdbio.h (dir.valcheck): New trustdb field. + * tdbio.c: Add support for this field + (tdbio_read_modify_stamp): New. + (tdbio_write_modify_stamp): New. + * trustdb.c (do_check): Check against this field. Removed cache update. + (verify_key): Add cache update. + (upd_uid_record): Some functional changes. + (upd_cert_record): Ditto + +Wed Mar 10 11:26:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keylist.c (list_keyblock): Fixed segv in uid. Print 'u' as + validity of sks. + +Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * getkey.c (classify_user_id): Add new mode 12 (#<lid>). + + * seckey-cert.c (check_secret_key): replaced error by info. + + * trustdb.c (query_trust_info): Add another arg, changed all callers. + (check_trust): Ditto. + (do_check): Ditto. + (verify_key): Handle namehash. + * keylist.c (list_keyblock): print trust info for user ids. + + * sig-check.c (signature_check): Add sig-created to status output. + +Tue Mar 2 16:44:57 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * textfilter.c (copy_clearsig_text): New. + (clearsign): Removed. + * sign.c (clearsign_file): does not use textfiler anymore. + + * keygen.c (ask_user_id): print a note about the used charset. + +Tue Mar 2 10:38:42 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * sig-check.c (signature_check): sig-id now works for all algos. + + * armor.c (armor_filter): Fixed armor bypassing. + +Sun Feb 28 19:11:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keygen.c (ask_user_id): Don't change the case of email addresses. + (has_invalid_email_chars): Adjusted. + + * keylist.c (list_one): Really list serect keys (Remi Guyomarch) + + * keyedit.c (menu_select_uid): Add some braces to make egcs happy. + (menu_select_key): Ditto. + + * mainproc.c (do_proc_packets): List sym-enc packets (Remi Guyomarch) + +Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (build_pk_list): Return error if there are no recipients. + + * sig-check.c (signature_check): New signature id feature. + * armor.c (make_radic64_string): New. + + * mainproc.c (proc_pubkey_enc): early check for seckey availability. + + * pkclist.c (do_we_trust_pre): print user id before asking. + + * ringedit.c (add_keyblock_resource,get_keyblock_handle): Cleaner + handling of default resource. + + +Thu Feb 25 18:47:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (algo_available): New. + (select_algo_from_prefs): Check whether algo is available. + + * ringedit.c (keyring_copy): Take care of opt.dry_run. + (do_gdbm_store): Ditto. + * openfile.c (open_outfile). Ditto. + (copy_options_file): Ditto. + * trustdb.c (update_trustdb): Ditto. + (clear_trust_checked_flag): Ditto. + (update_trust_record): Ditto. + (insert_trust_record): Ditto. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * keylist.c (secret_key_list): Now really list the secret key. + + * trustdb.c (do_init_trustdb): New. Init is now deferred. + +Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * getkey.c (lookup_sk): Return G10ERR_NO_SECKEY and not x_PUBKEY. + +Fri Feb 19 15:49:15 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (select_algo_from_prefs): retrieve LID if not there. + + * armor.c (fake_packet): Replaced ugly lineending handling. + + * g10.c (oNoEncryptTo): New. + * pkclist.c (build_pk_list): Implemented this option. + + * g10.c (main): Greeting is now printed to stderr and not to tty. + Use add_to_strlist() instead of direct coding. + + * import.c (import): Use iobuf_push_filter2. + + * mainproc.c (check_sig_and_print): Print all user ids + for good signatures. + * getkey.c (get_pubkeyblock): New. + + * import.c (chk_self_sigs): Fixed SEGV for unbounded class 0x18 keys. + (delete_inv_parts): Delete special marked packets. + +Tue Feb 16 14:10:02 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c (main): New option --encrypt-to + + * pkclist.c (build_pk_list): Implemented encrypt-to. + + * parse-packet.c (parse_user_id): Removed the hack to work with + utf-8 strings. + + * g10.c (main): Install lockfile cleanup handler. + * tdbio.c (cleanup): Removed: this is now handled by dotlock. + +Sat Feb 13 14:13:04 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * tdbio.c (tdbio_set_dbname): Init lockhandle for a new trustdb + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c (main): check for development version now in configure + + * tdbio.c (tdbio_write_record): Add uid.validity + (tdbio_read_record) : Ditto. + (tdbio_dump_record) : Ditto. + + * keygen.c (keygen_add_std_prefs): Replaced Blowfish by Twofish, + removed MD5 and Tiger. + * pubkey-enc.c (get_it): Suppress warning about missing Blowfish + in preferences in certain cases. + + * ringedit.c (lock_rentry,unlock_rentry): New. + + * getkey.c (key_byname): Pass ret_kb down to lookup_xx. + + * armor.c (armor_filter): No output of of empty comment lines. + Add option --no-version to suppress the output of the version string. + + * getkey.c: Release the getkey context for auto context variables. + +Sun Jan 24 18:16:26 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * getkey.c: Changed the internal design to allow simultaneous + lookup of multible user ids + (get_pubkey_bynames): New. + (get_seckey_bynames): New. + (get_seckey_next): New. + (get_seckey_end): New. + * keylist.c (list_one): Use the new functions. + + * keylist.c (list_keyblock): add a newline for normal listings. + + * g10.c (--recipient): New option name to replace --remote-user + + +Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * textfilter.c: Mostly rewritten + * plaintext.c (handle_plaintext): Use now text_filter semantics. + +Tue Jan 19 19:34:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * export.c (export_pubkeys_stream): New. + (do_export_stream): New. + * g10.c (aSendKeys): New command. + * hkp.c (hkp_export): New. + + * compress.c (do_uncompress): Hack for algo 1 and 1.1.3 + +Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * textfilter.c (text_filter): Now uses iobuf_read_line(). + (read_line): Removed. + + * armor.c (trim_trailing_spaces): Removed and replaced + by trim_trailing_ws from libutil + +Sat Jan 16 12:03:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * hkp.c (hkp_ask_import): Use only the short keyid + +Sat Jan 16 09:27:30 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * import.c (import_key_stream): New + (import): New, moved most of import_keys here. + * g10.c: New option --keyserver + * mainproc.c (check_sig_and_print): Hook to import a pubkey. + + * pref.c pref.h : Removed + + * hkp.c hkp.h: New + +Wed Jan 13 14:10:15 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c (radix64_read): Print an error if a bad armor was detected. + +Wed Jan 13 12:49:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c (radix64_read): Now handles malformed armors produced + by some buggy MUAs. + +Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * ringedit.c (find_keyblock_bysk): New. + + * skc_list.c (is_insecure): New. + (build_sk_list): usage check for insecure keys. + + * import.c (chk_self_sigs): Add handling for subkeys. + (delete_inv_parts): Skip unsigned subkeys + + * sig-check.c (do_check): Print info if the signature is older + than the key. + * keygen.c (generate_subkeypair): Fail on time warp. + * sign.c (do_sign): Ditto. + +Sun Jan 10 15:10:02 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c (fake_packet): Fixed not-dash-escaped bug. + +Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * sig-check.c (do_check): Output time diff on error + + * status.c (STATUS_VALIDSIG): New. + (is_status_enabled): New. + * mainproc.c (check_sig_and_print): Issue that status message. + + * plaintext.c (special_md_putc): Removed + + * armor.c (armor_filter): print error for truncated lines. + + * free-packet.c (free_encrypted): Revomed call to set_block_mode. + (free_plaintext): Ditto. + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (add_ownertrust): Fixed return value. + + * encr-data.c (decrypt_data): Disabled iobuf_set_limit and + iobuf_pop_filter stuff. + * compress.c (handle_compressed): Disabled iobuf_pop_filter. + + * packet.h (PKT_secret_key): Add is_primary flag. + * parse-packet.c (parse_key): Set this flag. + * passphrase.c (passphrase_to_dek): Kludge to print the primary + keyid - changed the API: keyid must now hold 2 keyids. + * getkey.c (get_primary_seckey): New. + * seckey-cert.c (do_check): pass primary keyid to passphrase query + + * tbdio.c (open_db): removed the atexit + (tdbio_set_dbname): and moved it to here. + + * armor.c: Rewrote large parts. + +Tue Dec 29 19:55:38 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * revoke.c (gen_revoke): Removed compression. + + * pkclist.c (do_we_trust_pre): special check for revoked keys + + * trustdb.c (update_trust_record): Fixed revoke flag. + +Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * misc.c (disable_core_dumps): Check for EINVAL (Atari) + + * getkey (merge_one_pk_and_selfsig): Fixed search of expiredate. + (merge_keys_and_selfsig): Ditto. + + * free-packet.c (cmp_public_keys): cmp expire only for v3 packets + (cmp_secret_keys): Ditto. + (cmp_public_secret_key): Ditto. + +Wed Dec 23 17:12:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c (find_header): Reset not_dashed at every header + +Wed Dec 23 13:18:14 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * pkclist.c (add_ownertrust): Refresh validity values. + + * trustdb.c (enum_cert_paths_print): New arg refresh. + + * ringedit.c: Fixed problems fix keyrings + * parse-packet.c (dbg_parse_packet): New debug functions. + + * getkey.c (getkey_disable_caches): New. + * import.c (import_keys): Disable caches. + +Thu Dec 17 18:31:15 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * misc.c (trap_unaligned): Only for glibc 1 + + * sign.c (write_dash_escaped): Now escapes "From " lines + * g10.c: New option --escape-from-lines + + * trustdb.c (sort_tsl_list): New + (list_trust_path): Now prints sorted list. + (enum_cert_paths): Likewise. + (enum_cert_paths_print): New. + (print_paths): New printing format. + * pkclist.c (add_ownertrust): New arg quit. + (edit_ownertrust): New quit selection and does not query + the recipients ownertrust anymore. + (add_ownertrust): Print the ceritficate path. + + +Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * parse-packet.c (parse_signature): Now checks for critical bit + (parse_sig_subpkt): Splitted. + (parse_one_sig_subpkt): New. + * sig-check.c (do_check): handle critical bit. + +Sun Dec 13 14:10:56 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * pcklist.c (select_algo_from_prefs): Preferences should + now work (lost the != ? ) + +Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * ringedit.c (gdbm_store): Fix for inserts + + * g10.c (main): New option --export-all + * export.c (export_pubkeys): New arg. + (do_export): Now may skip old keys. + + * status.c: Minor patches for Sun's cc + + * keygen.c (ask_algo): Disabled v3 ElGamal choice, rearranged + the numbers. Add a warning question when a sign+encrypt key + is selected. + + * g10.c (do_not_use_RSA): Removed. + * misc.c (print_pubkey_algo_note): New as replacement for the + do_not_use_RSA() and chnaged all callers. + (print_cipher_algo_note): New. + (print_hash_algo_note): New. + + * cipher.c (write_header): Add a call to print_cipher_algo_note. + * seckey-cert.c (protect_secret_key): Ditto + * sign.c (do_sign): Add a call to print_digest_algo_note. + + * getkey.c (get_long_user_id_string): New. + * mainproc.c (check_sig_and_print): Changed the format of the + status output. + + * encrypt.c (write_pubkey_enc_from_list): print used symmetric cipher. + + * pkclist.c (do_we_trust): Changed a message. + +Wed Dec 9 13:41:06 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * misc.c (trap_unaligned) [ALPHA]: Only if UAC_SIGBUS is defined. + + * sign.c (write_dash_escaped): Add the forgotten patch by Brian Moore. + + * compress.c (do_uncompress): Fixed the inflating bug. + + +Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * trustdb.c (upd_uid_record): Now uses the newest self-signature + (insert_trust_record): Now calls update with recheck set to true. + (register_trusted_key): New. + (verify_own_keys): Enhanced by list of trusted keys. + + * g10.c (main): Print a warning when a devel version is used. + (main): New option --trusted-key + + * import.c (merge_blocks): Fixed merging of new user ids and + added merging of subkeys. + (append_uid): Ditto. + (merge_keysig): New. + (append_key): New. + * getkey.c (merge_one_pk_and_selfsig): Get the expiration time + from the newest self-signature. + (merge_keys_and_selfsig): Ditto. + + * free-packet.c (cmp_secret_key): New. + + +Fri Nov 27 21:37:41 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * g10.c: New option --lock-once + * tdbio.c (open_db): Add an atexit + (cleanup): New. + (tdbio_sync): Add locking. + (tdbio_end_transaction): Ditto. + (put_record_into_cache): Ditto. + * ringedit.c (keyring_copy): Ditto. + (cleanup): New. + (add_keyblock_resource): Add an atexit. + +Fri Nov 27 15:30:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * armor.c (find_header): Another fix for clearsigs. + +Fri Nov 27 12:39:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + + * status.c (display_help): Removed. + * helptext.c: New and removed the N_() from all cpr_gets. + + +Fri Nov 20 16:54:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): New option --not-dash-escaped + * sign.c (write_dashed_escaped): Ditto. + * armor.c (find_header): Support for NotDashEscaped header. + + * getkey.c: print "disabled cache.." only if verbose is used. + +Thu Nov 19 07:17:31 1998 Werner Koch <werner.koch@guug.de> + + * parse-packet.c (dump_sig_subpkt): Fixed expire listing + * getkey.c (merge_keys_and_selfsig): Fixed expire calculation. + (merge_one_pk_and_selfsig): Ditto. + * keyedit.c (menu_expire). Ditto. + * keygen.c (keygen_add_key_expire): Ditto. + (ask_expire_interval): New and changed all local function to use + this instead. + (keygen_add_key_expire): Opaque should now be a public key; + changed all callers. + + * parse.packet.c (parse): use skip_rest to skip packets. + + * keyedit.c (keyedit_menu): New arg for cmdline cmds. + +Wed Nov 18 20:33:50 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (check_trustdb): Now rechecks all gived userids. + (collect_paths): Some fixes. + (upd_pref_records): Skips empty items, evaluate all items. + + * parse-packet.c (dump_sig_subpkt): Better listing of prefs. + (skip_packet): Now knows about marker packet + + * g10.c: removed cmd "--edit-sig". + + * pubring.asc: Updated. + +Sat Nov 14 14:01:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Changed syntax of --list-trust-path + * trustdb.c (list_trust_path): Replaced max_depth by + opt.max_cert_depth + +Fri Nov 13 07:39:58 1998 Werner Koch <werner.koch@guug.de> + + * trustdb.c (collect_paths): Removed a warning message. + (enum_trust_web): Removed. + (enum_cert_paths): New. + * pkclist.c (add_ownertrust): Changed to use enum_cert_paths. + (edit_ownertrust): Now list ceritficates on request. + (show_paths): New. + +Wed Nov 11 18:05:44 1998 Werner Koch <werner.koch@guug.de> + + * g10.c (main): New option --max-cert-depth + * tdbio.h: add new fields to ver and dir record. + * tdbio.c: read/write/dump of these fields. + (tdbio_db_matches_options): New. + * trustdb.c: replaced MAC_CERT_DEPTH by opt.max_cert_depth. + (do_check): cache validity and changed other functions + to reset the cached value. + + * keylist.c (list_one): Now lists the ownertrust. + * mainproc.c (list_node): Ditto. + +Tue Nov 10 10:08:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (g10_exit): Now looks at the new g10_errors_seen. + * mainproc.c (check_sig_and_print): Sets g10_errors_seen. + + * *.c : i18n many more strings. + + * ringedit.c (locate_keyblock_by_keyid): Add HAVE_LIBGDBM + (locate_keyblock_by_fpr): Ditto. + + * g10.c (main): removed unsused "int errors". + (main): Add new option --charset. + + * g10.c (main): special message for the unix newbie. + +Mon Nov 9 07:17:42 1998 Werner Koch <werner.koch@guug.de> + + * getkey.c (finish_lookup): Kludge to prefere algo 16. + + * trustdb.c (new_lid_table): Clear cached item. + + * status.c (cpr_get_utf8): New. + * pkclist.c (build_pk_list): Uses this. + +Sun Nov 8 17:20:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mainproc.c (check_sig_and_print): Why did I use strlen()-1 + in the printf? - This truncated the TZ. + +Sat Nov 7 15:57:28 1998 me,,, (wk@tobold) + + * getkey.c (lookup): Changes to support a read_next. + (get_pubkey): Fixed a memory leak. + + * keylist.c (list_one): Now lists all matching user IDs. + +Tue Nov 3 16:19:21 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (ask_user_id): Now converted to UTF-8 + + * g10.c (main): Kludge for pgp clearsigs and textmode. + +Fri Oct 30 16:40:39 1998 me,,, (wk@tobold) + + * signal.c (block_all_signals): New. + (unblock_all_signals): New + * tdbio.c (tdbio_end_transaction): Now blocks all signals. + + * trustdb.c (new_lid_table): Changed the representation of the + former local_lid_info stuff. + + * trustdb.c (update_trust_record): Reorganized the whole thing. + * sig-check.c (check_key_signature): Now handles class 0x28 + + +Wed Oct 28 18:56:33 1998 me,,, (wk@tobold) + + * export.c (do_export): Takes care of the exportable sig flag. + +Tue Oct 27 14:53:04 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (update_trust_record): New "fast" parameter. + +Sun Oct 25 19:32:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * openfile.c (copy_options_File): New. + * ringedit.c (add_keyblock_resource): Creates options file + * tdbio.c (tdbio_set_dbname): Ditto. + +Sat Oct 24 14:10:53 1998 brian moore <bem@cmc.net> + + * mainproc.c (proc_pubkey_enc): Don't release the DEK + (do_proc_packets): Ditto. + +Fri Oct 23 06:49:38 1998 me,,, (wk@tobold) + + * keyedit.c (keyedit_menu): Comments are now allowed + + * trustdb.c: Rewrote large parts. + + +Thu Oct 22 15:56:45 1998 Michael Roth (mroth@nessie.de) + + * encode.c: (encode_simple): Only the plain filename without + a given directory is stored in generated packets. + (encode_crypt): Ditto. + + * sign.c: (sign_file) Ditto. + + +Thu Oct 22 10:53:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (update_trust_record): Add new optional arg. + + * import.c (import_keys): Add statistics output + * trustdb.c (update_trustdb): Ditto. + (insert_trustdb): Ditto. + + * tdbio.c (tdbio_begin_transaction): New. + (tdbio_end_transaction): New. + (tdbio_cancel_transaction): New. + + * g10.c (main): New option --quit. + + * trustdb.c (check_hint_sig): No tests for user-id w/o sig. + This caused an assert while checking the sigs. + + * trustdb.c (upd_sig_record): Splitted into several functions. + + * import.c (import_keys): New arg "fast". + * g10.c (main): New command --fast-import. + +Wed Oct 21 18:19:36 1998 Michael Roth <mroth@nessie.de> + + * ringedit.c (add_keyblock_resource): Directory is now created. + * tdbio.c (tdbio_set_dbname): New info message. + +Wed Oct 21 11:52:04 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (update_trustdb): released keyblock in loop. + + * keylist.c (list_block): New. + (list_all): Changed to use list_block. + + * trustdb.c: Completed support for GDBM + + * sign.c (only_old_style): Changed the way force_v3 is handled + (sign_file): Ditto. + (clearsign_file): Ditto. + + * keygen.c (has_invalid_email_chars): Splitted into mailbox and + host part. + + * keylist.c (list_one): Add a merge_keys_and_selfsig. + * mainproc.c (proc_tree): Ditto. + +Sun Oct 18 11:49:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sign.c (only_old_style): Add option force_v3_sigs + (sign_file): Fixed a bug in sig->version + (clearsign_file): Ditto. + + * parse-packet.c (dump_sig_subpkt): New + + * keyedit.c (menu_expire): New. + * free-packet.c (cmp_signatures): New + + +Sat Oct 17 10:22:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c: changed output line length from 72 to 64. + + * keyedit.c (fix_keyblock): New. + +Fri Oct 16 10:24:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c: Rewrote most. + * tdbio.c: Add cache and generalized hash tables. + + * options.h (ENABLE_COMMENT_PACKETS): New but undef'ed. + * encode.c, sign.c, keygen.c: Disabled comment packets. + * export.c (do_export): Comment packets are never exported, + except for those in the secret keyring. + + * g10.c (main): Removed option do-no-export-rsa; should be + be replaced by a secpial tool. + * export.c (do_export): Removed the code for the above option. + + * armor.c (find_header): Support for new only_keyblocks. + * import.c (import_keys): Only looks for keyblock armors. + + * packet.h: replaced valid_days by expiredate and changed all users. + * build-packet.c (do_public_key): calculates valid-days + (do_secret_key): Ditto. + * parse-packet.c (parse_key): expiredate is calucated from the + valid_period in v3 packets. + * keyid.c (do_fingerprint_md): calculates valid_dates. + + * keygen.c (add_key_expire): fixed key expiration time for v4 packets. + + * armor.c (find_header): A LF in the first 28 bytes + was skipped for non-armored data. + +Thu Oct 8 11:35:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (is_armored): Add test on old comment packets. + + * tdbio.c (tdbio_search_dir_bypk): fixed memory leak. + + * getkey.c: Changed the caching algorithms. + +Wed Oct 7 19:33:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * kbnodes.c (unused_nodes): New. + +Wed Oct 7 11:15:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keyedit.c (sign_uids): Fixed a problem with SK which could caused + a save of an unprotected key. + (menu_adduid): Ditto. + + * keyedit.c (keyedit_menu): Prefs are now correctly listed for + new user ids. + + * trustdb.c (update_trust_record): New. + (insert_trust_record): Now makes use of update_trust_record. + +Tue Oct 6 16:18:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (read_record): replaces most of the tdbio_read_records. + (write_record): Ditto. + +Sat Oct 3 11:01:21 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (ask_alogo): enable ElGamal enc-only only for addmode. + +Wed Sep 30 10:15:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * import.c (import_one): Fixed update of wrong keyblock. + +Tue Sep 29 08:32:08 1998 me,,, (wk@tobold) + + * mainproc.c (proc_plaintext): Display note for special filename. + * plaintext.c (handle_plaintext): Suppress output of special file. + +Mon Sep 28 12:57:12 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (verify_own_keys): Add warning if a key is not protected. + + * passphrase (hash_passphrase): Fixed iterated+salted mode and + setup for keysizes > hashsize. + + * g10.c (main): New options: --s2k-{cipher,digest,mode}. + +Fri Sep 25 09:34:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c: Chnaged some help texts. + +Tue Sep 22 19:34:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * passphrase.c (read_passphrase_from_fd): fixed bug for long + passphrases. + +Mon Sep 21 11:28:05 1998 Werner Koch (wk@(none)) + + * getkey.c (lookup): Add code to use the sub key if the primary one + does not match the usage. + + * armor.c (armor_filter): New error message: no valid data found. + (radix64_read): Changes to support multiple messages. + (i18n.h): New. + * mainproc.c (add_onepass_sig): bug fix. + +Mon Sep 21 08:03:16 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pkclist.c (do_we_trust): Add keyid to most messages. + + * passphrase.c (read_passphrase_from_fd): New. + (have_static_passphrase): New + (get_passphrase_fd): Removed. + (set_passphrase_fd): Removed. + * g10.c (main): passphrase is now read here. + + * keyedit.c (keyedit_menu): "help" texts should now translate fine. + +Mon Sep 21 06:40:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * encode.c (encode_simple): Now disables compression + when --rfc1991 is used. + (encode_crypt): Ditto. + +Fri Sep 18 16:50:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * getkey.c (merge_key_and_selfsig): New. + +Fri Sep 18 10:20:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pkclist.c (select_algo_from_prefs): Removed 3DES kludge. + + * seskey.c (make_session_key): Fixed SERIOUS bug introduced + by adding the weak key detection code. + + * sign.c (sign_file): Changed aremor header in certain cases. + +Tue Sep 15 17:52:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mainproc.c (check_sig_and_print): Replaced ascime by asctimestamp. + +Mon Sep 14 11:40:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seskey.c (make_session_key): Now detects weak keys. + + * trustdb (clear_trust_checked_flag): New. + + * plaintext.c (handle_plaintext): Does no anymore suppress CR from + cleartext signed messages. + +Sun Sep 13 12:54:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (insert_trust_record): Fixed a stupid bug in the free + liunked list loops. + +Sat Sep 12 15:49:16 1998 Werner Koch (wk@isil.d.shuttle.de) + + * status.c (remove_shmid): New. + (init_shm_comprocess): Now sets permission to the real uid. + +Wed Sep 9 11:15:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h (PKT_pubkey_enc): New flah throw_keyid, and add logic to + implement it. + * g10.c (main): New Option --throw-keyid + + * getkey.c (enum_secret_keys): Add new ar and changed all callers. + +Tue Sep 8 20:04:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * delkey.c (delete_key): Moved from keyedit.c. + +Mon Sep 7 16:37:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (calc_length_header): New arg new_ctb to correctly + calculate the length of new style packets. + + * armor.c (is_armored): Checks for symkey_enc packets. + + * pkclist.c (select_algo_from_prefs): 3DEs substitute is now CAST5. + +Tue Aug 11 17:54:50 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (do_secret_key): Fixed handling of old keys. + + * getkey.c (compare_name): Fixed exact and email matching + + * openfile.c (open_outfile): Changed arguments and all callers. + +Tue Aug 11 09:14:35 1998 Werner Koch (wk@isil.d.shuttle.de) + + * encode.c (encode_simple): Applied option set-filename and comment. + (encode_crypt): Ditto. + * sign.c (sign_file): Ditto. + * armor.c (armor_filter): Applied option comment. + + * encode.c (encode_crypt): Moved init_packet to the begin. + (encode_simple): add an init_packet(). + + * comment (write_comment): Now enforces a hash sign as the 1st byte. + + * import.c (import_one): Add explanation for "no user ids". + + * compress.c (do_uncompress): Applied Brian Warner's patch to support + zlib 1.1.3 etc. + + * trustdb.c (check_trust): Fixed a problem after inserting new keys. + + * getkey (lookup): do not return the primary key if usage is given + (lookup_sk): Ditto and take usage into account. + + * status.c (cpr_get_answer_is_yes): add display_help. + +Mon Aug 10 10:11:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * getkey.c (lookup_sk): Now always returns the primary if arg + primary is true. + (lookup): Likewise. + (get_pubkey_byname): Now returns the primary key + (get_seckey_byname): Ditto. + + +Mon Aug 10 08:34:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keyid.c (pubkey_letter): ELG_E is now a small g. + +Sat Aug 8 17:26:12 1998 Werner Koch (wk@isil.d.shuttle.de) + + * openfile (overwrite_filep): Changed semantics and all callers. + +Sat Aug 8 12:17:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * status.c (display_help): New. + +Thu Aug 6 16:30:41 1998 Werner Koch,mobil,,, (wk@tobold) + + * seskey.c (encode_session_key): Now uses get_random_bits(). + +Thu Aug 6 07:34:56 1998 Werner Koch,mobil,,, (wk@tobold) + + * ringedit.c (keyring_copy): No more backupfiles for + secret keyrings and add additional warning in case of + a failed secret keyring operation. + +Wed Aug 5 11:54:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (check_opts): Moved to main. Changed def_cipher_algo + semantics and chnaged all users. + + * pubkey-enc.c (get_sssion_key): New informational output + about preferences. + + * parse-packet.c (parse_symkeyenc): Fixed salted+iterated S2K + (parse_key): Ditto. + * build-packet.c (do_secret_key): Ditto. + (do_symkey_enc): Ditto. + +Tue Aug 4 08:59:10 1998 Werner Koch (wk@isil.d.shuttle.de) + + * getkey.c (enum_secret_keys): Now returns only primary keys. + + * getkey (lookup): Now sets the new namehash field. + + * parse-packet.c (parse_sig_subpkt2): New. + + * sign.c (sign_file): one-pass sigs are now emiited reverse. + Preference data is considered when selecting the compress algo. + +Wed Jul 29 12:53:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * free-packet.c (copy_signature): New. + + * keygen.c (generate_subkeypair): rewritten + * g10.c (aKeyadd): Removed option --add-key + +Mon Jul 27 10:37:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seckey-cert.c (do_check): Additional check on cipher blocksize. + (protect_secret_key): Ditto. + * encr-data.c: Support for other blocksizes. + * cipher.c (write_header): Ditto. + +Fri Jul 24 16:47:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * kbnode.c (insert_kbnode): Changed semantics and all callers. + * keyedit.c : More or less a complete rewrite + +Wed Jul 22 17:10:04 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (write_sign_packet_header): New. + +Tue Jul 21 14:37:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * import.c (import_one): Now creates a trustdb record. + + * g10.c (main): New command --check-trustdb + +Mon Jul 20 11:15:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * genkey.c (generate_keypair): Default key is now DSA with + encryption only ElGamal subkey. + +Thu Jul 16 10:58:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keyid.c (keyid_from_fingerprint): New. + * getkey.c (get_pubkey_byfprint): New. + +Tue Jul 14 18:09:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keyid.c (fingerprint_from_pk): Add argument and changed all callers. + (fingerprint_from_sk): Ditto. + +Tue Jul 14 10:10:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * plaintext.c (handle_plaintext): Now returns create error if + the file could not be created or the user responded not to overwrite + the file. + * mainproc.c (proc_plaintext): Tries again if the file could not + be created to check the signature without output. + + * misc.c (disable_core_dumps): New. + * g10.c (main): disable coredumps for gpg + + * g10.c (MAINTAINER_OPTIONS): New to disable some options + +Mon Jul 13 16:47:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * plaintext.c (hash_datafiles): New arg for better support of + detached sigs. Changed all callers. + * mainproc.c (proc_signature_packets): Ditto. + + * g10.c (main): New option "compress-sigs" + * sig.c (sign_file): detached signatures are not anymore compressed + unless the option --compress-sigs is used. + +Thu Jul 9 19:54:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c: Fixes to allow zero length cleartext signatures + +Thu Jul 9 14:52:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (build_list): Now drops setuid. + (main): Changed the way keyrings and algorithms are registered . + +Wed Jul 8 14:17:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h (PKT_public_key): Add field keyid. + * parse-packet.c (parse_key): Reset the above field. + * keyid.c (keyid_from_pk): Use above field as cache. + + * tdbio.c, tdbio.h: New + * trustdb.c: Moved some functions to tdbio.c. + (print_keyid): New. + + * pkclist.c (check_signatures_trust): New. + +Wed Jul 8 10:45:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * plaintext.c (special_md_putc): New. + (handle_plaintext): add clearsig argument + * mainproc.c (proc_plaintext): detection of clearsig + * sign.c (write_dased_escaped): Changed clearsig format + +Tue Jul 7 18:56:19 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (find_header): Now makes sure that there is only one + empty line for clearsigs, as this is what OP now says. + +Mon Jul 6 13:09:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): New option default-secret-key + * getkey.c (get_seckey_byname): support for this option. + +Mon Jul 6 09:03:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * getkey.c (add_keyring): Keyrings are now added to end of the + list of keyrings. The first added keyringwill be created. + (add_secret_keyring): Likewise. + + * ringedit.c (add_keyblock_resource): Files are created here. + + * g10.c (aNOP): Removed + + * getkey.c (lookup): Add checking of usage for name lookups + * packet.h (pubkey_usage): Add a field which may be used to store + usage capabilities. + * pkclist.c (build_pk_list): getkey now called with usage arg. + * skclist.c (build_sk_list): Ditto. + + * sign.c (clearsign_file): Fixed "Hash:" headers + +Sat Jul 4 13:33:31 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (list_ownertrust): New. + * g10.c (aListOwnerTrust): New. + + * g10.c (def_pubkey_algo): Removed. + + * trustdb.c (verify_private_data): Removed and also the call to it. + (sign_private_data): Removed. + +Fri Jul 3 13:26:10 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (aEditKey): was aEditSig. Changed usage msg. + + * keyedit.c: Done some i18n stuff. + + * g10.c (do_not_use_RSA): New. + * sign.c (do_sign): Add call to above function. + * encode.c (write_pubkey_enc_from_list): Ditto. + +Thu Jul 2 21:01:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c: Now is able sto store data of unknown + algorithms. + * free-packet.c: Support for this. + * build-packet.c: Can write data of packet with unknown algos. + +Thu Jul 2 11:46:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c (parse): fixed 4 byte length header + +Wed Jul 1 12:36:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h (new_ctb): New field for some packets + * build-packet.c (build_packet): Support for new_ctb + * parse-packet.c (parse): Ditto. + +Mon Jun 29 12:54:45 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h: changed all "_cert" to "_key", "subcert" to "subkey". + + * free-packet.c (free_packet): Removed memory leak for subkeys. + +Sun Jun 28 18:32:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * import.c (import_keys): Renamed from import_pubkeys. + (import_secret_one): New. + + * g10.c (aExportSecret): New. + + * export.c (export_seckeys): New. + + * parse-packet.c (parse_certificate): Cleaned up. + (parse_packet): Trust packets are now considered as unknown. + (parse_pubkey_warning): New. + +Fri Jun 26 10:37:35 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (has_invalid_email_chars): New. + +Wed Jun 24 16:40:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (armor_filter): Now creates valid onepass_sig packets + with all detected hash algorithms. + * mainproc.c (proc_plaintext): Now uses the hash algos as specified + in the onepass_sig packets (if there are any) + +Mon Jun 22 11:54:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * plaintext.c (handle_plaintext): add arg to disable outout + * mainproc.c (proc_plaintext): disable output when in sigs_only mode. + +Thu Jun 18 13:17:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c: Removed all rsa packet stuff, chnaged defaults + for key generation. + +Sun Jun 14 21:28:31 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (checksum_u16): Fixed a stupid bug which caused a + wrong checksum calculation for the secret key protection and + add a backward compatibility option. + * g10.c (main): Add option --emulate-checksum-bug. + +Thu Jun 11 13:26:44 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h: Major changes to the structure of public key material + which is now stored in an array and not anaymore in a union of + algorithm specific structures. These is needed to make the system + more extendable and makes a lot of stuff much simpler. Changed + all over the system. + + * dsa.c, rsa.c, elg.c: Removed. + +Wed Jun 10 07:22:02 1998 Werner Koch,mobil,,, (wk@tobold) + + * g10.c ("load-extension"): New option. + +Mon Jun 8 22:23:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seckey-cert.c (do_check): Removed cipher constants + (protect_secret_key): Ditto. + +Fri May 29 10:00:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (query_trust_info): New. + * keylist.c (list_one): Add output of trust info + * mainproc (list_node): ditto. + * g10.c (main): full trustdb init if -with-colons and any of the + key list modes. + +Thu May 28 10:34:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * status.c (STATUS_RSA_OR_IDEA): New. + * sig-check.c (check_signature): Output special status message. + * pubkey-enc.c (get_session_key): Ditto. + + * mainproc.c (check_sig_and_print): Changed format of output. + * passpharse.c (passphrase_to_dek): Likewise. + +Wed May 27 13:46:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (aListSecretKeys): New option --list-secret-keys + * keylist.c (std_key_list): Renamed to public_key_list. + (secret_key_list): New + (list_one, list_all): Add support for secret keys. + * getkey.c (get_secret_keyring): New. + * mainproc.c (list_node): Add option --with-colons for secret keys + + * sig-check.c (check_key_signature): detection of selfsigs + * mainproc.c (list_node): fixed listing. + + * g10.c (aListSecretKeys): New option --always-trust + * pkclist.c (do_we_trust): Override per option added + + * status.c (write_status_text): Add a prefix to every output line. + +Wed May 27 07:49:21 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10 (--compress-keys): New. + * options.h (compress_keys): New. + * export.c (export_pubkeys): Only compresses with the new option. + +Tue May 26 11:24:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * passphrase.c (get_last_passphrase): New + (set_next_passphrase): New. + (passphrase_to_dek): add support for the above functions. + * keyedit.c (make_keysig_packet): Add sigclass 0x18, + changed all callers due to a new argument. + * keygen.c (write_keybinding): New + (generate_subkeypair): Add functionality + (ask_algo, ask_keysize, ask_valid_days): Broke out of generate_keypair + (ask_user_id, ask_passphrase): Ditto. + +Thu May 21 11:26:13 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c,gpgd.c (main): Does now return an int, so that egcs does + not complain. + + * armor.c (fake_packet): Removed erro message and add a noticed + that this part should be fixed. + + * sign.c (sign_file): Compression now comes in front of encryption. + * encode.c (encode_simple): Ditto. + (encode_crypt): Ditto. + +Tue May 19 16:18:19 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (fake_packet): Changed assertion to log_error + +Sat May 16 16:02:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (build_packet): Add SUBKEY packets. + +Fri May 15 17:57:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sign.c (hash_for): New and used in all places here. + * main.h (DEFAULT_): new macros. + * g10.c (opt.def_digest_algo): Now set to 0 + + * compress.c (init_compress): Add support for algo 1 + * options.h (def_compress_algo): New + * g10.c (main): New option --compress-algo + +Fri May 15 13:23:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (print_mds): New feature to print only one hash, + chnaged formatting. + +Thu May 14 15:36:24 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (trap_unaligned) [__alpha__]: New + * g10.c (trap_unaligned): Add call to this to track down SIGBUS + on Alphas (to avoid the slow emulation code). + +Wed May 13 11:48:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (do_signature): Support for v4 pakets. + * keyedit.c (make_keysig_packet): Ditto. + * build-packet.c (build_sig_subpkt_from_sig): New. + (build_sig_subpkt): New. + + * elg.c (g10_elg_sign): removed keyid_from_skc. + * dsa.c (g10_dsa_sign): Ditto. + * rsa.c (g10_rsa_sign): Ditto. + * keyedit.c (make_keysig_packet): Add call to keyid_from_skc + + * sign.c (clearsign_file): Support for v4 signatures. + (sign_file): Ditto. + +Wed May 6 09:31:24 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c (do_parse): add support for 5 byte length leader. + (parse_subpkt): Ditto. + * build-packet.c (write_new_header): Ditto. + + * packet.h (SIGSUBPKT_): New constants. + * parse-packet.c (parse_sig_subpkt): Changed name, made global, + and arg to return packet length, chnaged all callers + + +Tue May 5 22:11:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (gen_dsa): New. + * build_packet.c (do_secret_cert): Support for DSA + +Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * compress.c: doubled buffer sizes + * parse-packet.c (do_plaintext): now uses iobuf_read/write. + +Mon May 4 09:35:53 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seskey.c (encode_md_value): Add optional argument hash_algo, + changed all callers. + + * passphrase.c (make_dek_from_passphrase): Removed + * (get_passhrase_hash): Changed name to passphrase_to_dek, add arg, + changed all callers. + + * all: Introduced the new ELG identifier and added support for the + encryption only one (which is okay to use by GNUPG for signatures). + +Sun May 3 17:50:26 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h (PKT_OLD_COMMENT): New name for type 16. + * parse-packet.c (parse_comment): Now uses type 61 + +Fri May 1 12:44:39 1998 Werner Koch,mobil,,, (wk@tobold) + + * packet.h (count): Chnaged s2k count from byte to u32. + * seckey-cert.c (do_check): Changed s2k algo 3 to 4, changed + reading of count. + * build-packet.c (do_secret_cert): ditto. + * parse-packet.c (parse_certificate): ditto. + + * parse-packet.c (parse_symkeyenc): New. + * build-packet.c (do_symkey_enc): New. + +Thu Apr 30 16:33:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sign.c (clearsign_file): Fixed "Hash: " armor line. + +Tue Apr 28 14:27:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c (parse_subpkt): Some new types. + +Mon Apr 27 12:53:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Add option --skip-verify. + * mainproc.c (check_sig_and_print): Ditto. + + * g10.c (print_mds): Add output for Tiger. + + * sign.c (sign_file): Now uses partial length headers if used + in canonical textmode (kludge to fix a bug). + + * parse-packet.c (parse_certificate): Changed BLOWFISH id. + * pubkey-enc.c (get_session_key): Ditto. + * seskey.c (make_session_key): Ditto. + * seckey-cert.c (protect_secret_key,do_check): Add BLOWFISH160. + +Fri Apr 24 17:38:48 1998 Werner Koch,mobil,,, (wk@tobold) + + * sig-check.c (check_key_signature): Add sig-class 0x14..0x17 + * keyedit.c (sign-key): Some changes to start with support of + the above new sig-classes. + +Wed Apr 22 09:01:57 1998 Werner Koch,mobil,,, (wk@tobold) + + * getkey.c (compare_name): add email matching + +Tue Apr 21 16:17:12 1998 Werner Koch,mobil,,, (wk@tobold) + + * armor.c (armor_filter): fixed missing last LF before CSUM. + +Thu Apr 9 11:35:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seckey-cert.c (do_check): New; combines all the check functions + into one. + + * sign.c: removed all key management functions + * keyedit.c: New. + +Thu Apr 9 09:49:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * import.c (chk_self_sigs): Changed an error message. + +Wed Apr 8 16:19:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * packet.h: packet structs now uses structs from the pubkey, + removed all copy operations from packet to pubkey structs. + +Wed Apr 8 13:40:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (verify_own_certs): Fixed "public key not found". + + * getkey.c (key_byname): New, combines public and secret key search. + + * pkclist.c (build_pkc_list): Add new arg usage, changed all callers. + * skclist.c (build_skc_list): Likewise. + + * ringedit.c (find_keyblock, keyring_search2): Removed. + +Wed Apr 8 09:47:21 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sig-check.c (do_check): Applied small fix from Ulf Mller. + +Tue Apr 7 19:28:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c, encr-data.c, seckey-cert.c: Now uses cipher_xxxx + functions instead of blowfish_xxx or cast_xxx + +Tue Apr 7 11:04:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (g10maint.o): Changed the way it is created. + +Mon Apr 6 11:17:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c: New. + * keygen.c (checksum,checksum_u16,checksum_mpi): Moved to misc.c + * seckey-cert.c: Kludge for wrong ELG checksum implementation. + +Sat Apr 4 20:07:01 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_filter): Support for CAST5 + * encr-data.c (decode_filter): Ditto. + (decrypt_data): Ditto. + * seskey.c (make_session_key): Ditto. + * seckey-cert.c (check_elg, check_dsa): Ditto, + (protect_secret_key): Ditto. + * pubkey-enc.c (get_session_key): Ditto. + * passphrase.c (hash_passphrase): Ditto. + +Thu Apr 2 20:22:35 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gpgd.c: New + +Thu Apr 2 10:38:16 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (generate_keypair): Add valid_days stuff. + * trustdb.c (check_trust): Add check for valid_days. + +Wed Apr 1 16:15:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (generate_keypair): Addional question whether the + selected large keysize is really needed. + +Wed Apr 1 15:56:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seckey-cert.c (protect_secret_key): merged protect_xxx to here. + +Wed Apr 1 10:34:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (g10maint.c): Changed creation rule, so that it works + on FreeBSD (missing CFLAGS). + + * parse-packet.c (parse_subkey): Removed. + +Thu Mar 19 15:22:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * ringedit.c (keyring_enum): Fixed problem with reading too + many packets. Add support to read secret keyrings. + + * getkey.c (scan_keyring): Removed + (lookup): New to replace scan_keyring. + (scan_secret_keyring): Removed. + (lookup_skc): New. + +Wed Mar 18 11:47:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * ringedit.c (enum_keyblocks): New read mode 11. + + * keyid.c (elg_fingerprint_md): New and changed all other functions + to call this if the packet version is 4 or above. + +Tue Mar 17 20:46:16 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c (parse_certificate): Add listing support for subkeys. + +Tue Mar 17 20:32:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (is_armored): Allow marker packet. + +Thu Mar 12 13:36:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (check_trust): Checks timestamp of pubkey. + * sig-check. (do_check): Compares timestamps. + +Tue Mar 10 17:01:56 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Add call to init_signals. + * signal.c: New. + +Mon Mar 9 12:43:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c: New + * packet.h, free-packet.c, parse-packet.c : Add support for DSA + * sig-check.c, getkey.c, keyid.c, ringedit.c: Ditto. + * seckey-cert.c: Ditto. + + * packet.h : Moved .digest_algo of signature packets to outer + structure. Changed all references + +Sun Mar 8 13:06:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * openfile.c : Support for stdout filename "-". + + * mainproc.c (check_sig_and_print): Enhanced status output: + * status.c (write_status_text): New. + +Fri Mar 6 16:10:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * kbnode.c (clone_kbnode): Fixed private_flag. + + * mainproc.c (list_node): Output of string "Revoked" as user-id. + +Fri Mar 6 14:26:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Add userids to "-kv" and cleaned up this stuff. + +Fri Mar 6 12:45:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Changed semantics of the list-... commands + and added a new one. Removed option "-d" + + * decrypt.c: New. + + * trustdb.c (init_trustdb): Autocreate directory only if it ends + in "/.gnupg". + +Thu Mar 5 12:12:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mainproc.c (do_proc_packets): New. Common part of proc_packet. + (proc_signature_packets): special version to handle signature data. + * verify.c: New. + * g10.c (aVerify): New. + * plaintext.c (hash_datafiles): New. + * compress.c (handle_compressed): Add callback arg, changed caller. + +Thu Mar 5 10:20:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c: Is nom the common source for gpg and gpgm + * g10maint.c: Removed + * Makefile.am: Add rule to build g10maint.c + +Thu Mar 5 08:43:59 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Changed the way clear text sigs are faked. + +Wed Mar 4 19:47:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10maint.c (aMuttKeyList): New + * keylist.c: New. + +Wed Mar 4 17:20:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * getkey.c (get_pubkey_byname): Kludge to allow 0x prefix. + +Tue Mar 3 13:46:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10maint.c (main): New option --gen-random. + +Tue Mar 3 09:50:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (aDeleteSecretKey): New. + (aEditSig): Add option "--edit-key" as synonym for "--edit-sig". + (aDeleteSecretKey): New. + * getkey.c (seckey_available): New. + * sign.c (delete_key): Enhanced to delete secret keys, changed all + callers. + +Mon Mar 2 21:23:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pkc_list.c (build_pkc_list): Add interactive input of user ID. + +Mon Mar 2 20:54:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pkclist.c (do_we_trust_pre): New. + (add_ownertrust): Add message. + * trustdb.c (enum_trust_web): Quick fix. + +Mon Mar 2 13:50:53 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): New action aDeleteKey + * sign.c (delete_key): New. + +Sun Mar 1 16:38:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (do_check): No returns TRUST_UNDEFINED instead of + eof error. + +Fri Feb 27 18:14:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (find_header): Removed trailing CR on headers. + +Fri Feb 27 18:02:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * ringedit.c (keyring_search) [MINGW32]: Open and close file here + because rename does not work on open files. Chnaged callers. + +Fri Feb 27 16:43:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sig-check.c (do_check): Add an md_enable. + * mainproc.c (do_check_sig): Use md_open in case of detached sig + (proc_tree): Take detached sigs into account. + +Fri Feb 27 15:22:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): Make use of GNUPGHOME envvar. + * g10main.c (main): Ditto. + +Wed Feb 25 11:40:04 1998 Werner Koch (wk@isil.d.shuttle.de) + + * plaintext.c (ask_for_detached_datafile): add opt.verbose to + info output. + + * openfile.c (open_sigfile): Try also name ending in ".asc" + +Wed Feb 25 08:41:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * keygen.c (generate_keypair): Fixed memory overflow. + +Tue Feb 24 15:51:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c (parse_certificate): Support for S2K. + * build-packet.c (do_secret_cert): Ditto. + * keygen.c (gen_elg): Ditto. + * seckey-cert.c (check_elg): Ditto + (protect_elg): Ditto. + * sign.c (chnage_passphrase): Ditto. + * passphrase.c (get_passphrase_hash): Support for a salt and + changed all callers. + (make_dek_from_passphrase): Ditto. + +Tue Feb 24 12:30:56 1998 Werner Koch (wk@isil.d.shuttle.de) + + * build-packet.c (hash_public_cert): Disabled debug output. + +Fri Feb 20 17:22:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (init_trustdb) [MINGW32]: Removed 2nd mkdir arg. + (keyring_copy) [MINGW32]: Add a remove prior to the renames. + +Wed Feb 18 18:39:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (OMIT_DEPENDENCIES): New. + + * rsa.c: Replaced log_bug by BUG. + +Wed Feb 18 13:35:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mainproc.c (do_check_sig): Now uses hash_public_cert. + * parse-packet.c (parse_certificate): Removed hashing. + * packet.h (public_cert): Removed hash variable. + * free-packet.c (copy_public_cert, free_public_cert): Likewise. + + * sig-check.c (check_key_signatures): Changed semantics. + +Wed Feb 18 12:11:28 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (do_check): Add handling for revocation certificates. + (build_sigrecs): Ditto. + (check_sigs): Ditto. + +Wed Feb 18 09:31:04 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (armor_filter): Add afx->hdrlines. + * revoke.c (gen_revoke): Add comment line. + * dearmor.c (enarmor_file): Ditto. + + * sig-check.c (check_key_signature): Add handling for class 0x20. + * mainproc.c : Ditto. + +Tue Feb 17 21:24:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c : Add header lines "...ARMORED FILE .." + * dearmor.c (enarmor_file): New. + * g10maint.c (main): New option "--enarmor" + +Tue Feb 17 19:03:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mainproc.c : Changed a lot, because the packets are now stored + a simple linlked list and not anymore in a complicatd tree structure. + +Tue Feb 17 10:14:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * free_packet.c (cmp_public_certs): New. + (cmp_user_ids): New. + + * kbnode.c (clone_kbnode): New. + (release_kbnode): Add clone support. + + * ringedit.c (find_keyblock_bypkc): New. + + * sign.c (remove_keysigs): Self signatures are now skipped, + changed arguments and all callers. + + * import.c : Add functionality. + +Tue Feb 17 09:31:40 1998 Werner Koch (wk@isil.d.shuttle.de) + + * options.h (homedir): New option. + * g10.c, g10maint.c, getkey.c, keygen.c, trustdb.c (opt.homedir): New. + + * trustdb.c (init_trustdb): mkdir for hoem directory + (sign_private_data): Renamed "sig" to "g10.sig" + +Mon Feb 16 20:02:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * kbnode.c (commit_kbnode): New. + (delete_kbnode): removed unused first arg. Changed all Callers. + + * ringedit.c (keyblock_resource_name): New. + (get_keyblock_handle): NULL for filename returns default resource. + +Mon Feb 16 19:38:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sig-check.s (check_key_signature): Now uses the supplied + public key to check the signature and not any more the one + from the getkey.c + (do_check): New. + (check_signature): Most work moved to do_check. + +Mon Feb 16 14:48:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (find_header): Fixed another bug. + +Mon Feb 16 12:18:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * getkey.c (scan_keyring): Add handling of compressed keyrings. + +Mon Feb 16 10:44:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c, g10maint.c (strusage): Rewrote. + (build_list): New + +Mon Feb 16 08:58:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (use_armor): New. + +Sat Feb 14 14:30:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mainproc.c (proc_tree): Sigclass fix. + +Sat Feb 14 14:16:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * armor.c (armor_filter): Changed version and comment string. + * encode.c, sign.c, keygen.c: Changed all comment packet strings. + +Sat Feb 14 12:39:24 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (aGenRevoke): New command. + * revoke.c: New. + * sign.c (make_keysig_packet): Add support for sigclass 0x20. + +Fri Feb 13 20:18:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * ringedit.c (enum_keyblocks, keyring_enum): New. + +Fri Feb 13 19:33:40 1998 Werner Koch (wk@isil.d.shuttle.de) + + * export.c: Add functionality. + + * keygen.c (generate_keypair): Moved the leading comment behind the + key packet. + * kbnode.c (walk_kbnode): Fixed. + + * g10.c (main): listing armored keys now work. + +Fri Feb 13 16:17:43 1998 Werner Koch (wk@isil.d.shuttle.de) + + * parse-packet.c (parse_publickey, parse_signature): Fixed calls + to mpi_read used for ELG b. + +Fri Feb 13 15:13:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10.c (main): changed formatting of help output. + +Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo) + + * pubkey-enc.c (get_session_key): rewritten + + + Copyright 1998,1999,2000,2001,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. diff --git a/g10/Makefile.am b/g10/Makefile.am new file mode 100644 index 000000000..a7e3117f8 --- /dev/null +++ b/g10/Makefile.am @@ -0,0 +1,123 @@ +# 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 + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl +EXTRA_DIST = options.skel +# it seems that we can't use this with automake 1.5 +#OMIT_DEPENDENCIES = zlib.h zconf.h +libexecdir = @libexecdir@/@PACKAGE@ +if ! HAVE_DOSISH_SYSTEM +AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" +endif +needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a + +#noinst_PROGRAMS = gpgd +bin_PROGRAMS = gpg gpgv + +common_source = \ + global.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 \ + signal.c + +gpg_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 \ + exec.c exec.h + +gpgv_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@ +# gpg gets LIBOBJS to add in mkdtemp if the platform doesn't have it +gpg_LDADD = @LIBOBJS@ $(LDADD) @DLLIBS@ @EGDLIBS@ + +$(PROGRAMS): $(needed_libs) + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + $(INSTALL_DATA) $(srcdir)/options.skel \ + $(DESTDIR)$(pkgdatadir)/options.skel + @set -e;\ + if test -f $(DESTDIR)$(bindir)/gpgm ; then \ + echo "removing obsolete gpgm binary" ; \ + rm $(DESTDIR)$(bindir)/gpgm ; \ + fi diff --git a/g10/armor.c b/g10/armor.c new file mode 100644 index 000000000..f00742295 --- /dev/null +++ b/g10/armor.c @@ -0,0 +1,1336 @@ +/* armor.c - Armor flter + * 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 <ctype.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" +#include "i18n.h" + +#ifdef HAVE_DOSISH_SYSTEM +#define LF "\r\n" +#else +#define LF "\n" +#endif + +#define MAX_LINELEN 20000 + +#define CRCINIT 0xB704CE +#define CRCPOLY 0X864CFB +#define CRCUPDATE(a,c) do { \ + a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \ + a &= 0x00ffffff; \ + } while(0) +static u32 crc_table[256]; +static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; +static byte asctobin[256]; /* runtime initialized */ +static int is_initialized; + + +typedef enum { + fhdrHASArmor = 0, + fhdrNOArmor, + fhdrINIT, + fhdrINITCont, + fhdrINITSkip, + fhdrCHECKBegin, + fhdrWAITHeader, + fhdrWAITClearsig, + fhdrSKIPHeader, + fhdrCLEARSIG, + fhdrREADClearsig, + fhdrNullClearsig, + fhdrEMPTYClearsig, + fhdrCHECKClearsig, + fhdrCHECKClearsig2, + fhdrCHECKDashEscaped, + fhdrCHECKDashEscaped2, + fhdrCHECKDashEscaped3, + fhdrREADClearsigNext, + fhdrENDClearsig, + fhdrENDClearsigHelp, + fhdrTESTSpaces, + fhdrCLEARSIGSimple, + fhdrCLEARSIGSimpleNext, + fhdrTEXT, + fhdrTEXTSimple, + fhdrERROR, + fhdrERRORShow, + fhdrEOF +} fhdr_state_t; + + +/* if we encounter this armor string with this index, go + * into a mode which fakes packets and wait for the next armor */ +#define BEGIN_SIGNATURE 2 +#define BEGIN_SIGNED_MSG_IDX 3 +static char *head_strings[] = { + "BEGIN PGP MESSAGE", + "BEGIN PGP PUBLIC KEY BLOCK", + "BEGIN PGP SIGNATURE", + "BEGIN PGP SIGNED MESSAGE", + "BEGIN PGP ARMORED FILE", /* gnupg extension */ + "BEGIN PGP PRIVATE KEY BLOCK", + "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */ + NULL +}; +static char *tail_strings[] = { + "END PGP MESSAGE", + "END PGP PUBLIC KEY BLOCK", + "END PGP SIGNATURE", + "END dummy", + "END PGP ARMORED FILE", + "END PGP PRIVATE KEY BLOCK", + "END PGP SECRET KEY BLOCK", + NULL +}; + + + +static void +initialize(void) +{ + int i, j; + u32 t; + byte *s; + + /* init the crc lookup table */ + crc_table[0] = 0; + for(i=j=0; j < 128; j++ ) { + t = crc_table[j]; + if( t & 0x00800000 ) { + t <<= 1; + crc_table[i++] = t ^ CRCPOLY; + crc_table[i++] = t; + } + else { + t <<= 1; + crc_table[i++] = t; + crc_table[i++] = t ^ CRCPOLY; + } + } + /* build the helptable for radix64 to bin conversion */ + for(i=0; i < 256; i++ ) + asctobin[i] = 255; /* used to detect invalid characters */ + for(s=bintoasc,i=0; *s; s++,i++ ) + asctobin[*s] = i; + + is_initialized=1; +} + +/**************** + * Check whether this is an armored file or not See also + * parse-packet.c for details on this code For unknown historic + * reasons we use a string here but only the first byte will be used. + * Returns: True if it seems to be armored + */ +static int +is_armored( const byte *buf ) +{ + int ctb, pkttype; + + ctb = *buf; + if( !(ctb & 0x80) ) + return 1; /* invalid packet: assume it is armored */ + pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf); + switch( pkttype ) { + case PKT_MARKER: + case PKT_SYMKEY_ENC: + case PKT_ONEPASS_SIG: + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_PUBKEY_ENC: + case PKT_SIGNATURE: + case PKT_COMMENT: + case PKT_OLD_COMMENT: + case PKT_PLAINTEXT: + case PKT_COMPRESSED: + case PKT_ENCRYPTED: + return 0; /* seems to be a regular packet: not armored */ + } + + return 1; +} + + +/**************** + * Try to check whether the iobuf is armored + * Returns true if this may be the case; the caller should use the + * filter to do further processing. + */ +int +use_armor_filter( IOBUF a ) +{ + byte buf[1]; + int n; + + /* fixme: there might be a problem with iobuf_peek */ + n = iobuf_peek(a, buf, 1 ); + if( n == -1 ) + return 0; /* EOF, doesn't matter whether armored or not */ + if( !n ) + return 1; /* can't check it: try armored */ + return is_armored(buf); +} + + + + +static void +invalid_armor(void) +{ + write_status(STATUS_BADARMOR); + g10_exit(1); /* stop here */ +} + + +/**************** + * check whether the armor header is valid on a signed message. + * this is for security reasons: the header lines are not included in the + * hash and by using some creative formatting rules, Mallory could fake + * any text at the beginning of a document; assuming it is read with + * a simple viewer. We only allow the Hash Header. + */ +static int +parse_hash_header( const char *line ) +{ + const char *s, *s2; + unsigned found = 0; + + if( strlen(line) < 6 || strlen(line) > 60 ) + return 0; /* too short or too long */ + if( memcmp( line, "Hash:", 5 ) ) + return 0; /* invalid header */ + s = line+5; + for(s=line+5;;s=s2) { + for(; *s && (*s==' ' || *s == '\t'); s++ ) + ; + if( !*s ) + break; + for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ ) + ; + if( !strncmp( s, "RIPEMD160", s2-s ) ) + found |= 1; + else if( !strncmp( s, "SHA1", s2-s ) ) + found |= 2; + else if( !strncmp( s, "MD5", s2-s ) ) + found |= 4; + else if( !strncmp( s, "TIGER192", s2-s ) ) + found |= 8; + else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */ + found |= 8; + else if( !strncmp( s, "SHA256", s2-s ) ) + found |= 16; + else if( !strncmp( s, "SHA384", s2-s ) ) + found |= 32; + else if( !strncmp( s, "SHA512", s2-s ) ) + found |= 64; + else + return 0; + for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) + ; + if( *s2 && *s2 != ',' ) + return 0; + if( *s2 ) + s2++; + } + return found; +} + + + +/**************** + * Check whether this is a armor line. + * returns: -1 if it is not a armor header or the index number of the + * armor header. + */ +static int +is_armor_header( byte *line, unsigned len ) +{ + const char *s; + byte *save_p, *p; + int save_c; + int i; + + if( len < 15 ) + return -1; /* too short */ + if( memcmp( line, "-----", 5 ) ) + return -1; /* no */ + p = strstr( line+5, "-----"); + if( !p ) + return -1; + save_p = p; + p += 5; + + /* Some mail programs on Windows seem to add spaces to the end of + the line. This becomes strict if --openpgp is set. */ + + if(!RFC2440) + while(*p==' ') + p++; + + if( *p == '\r' ) + p++; + if( *p == '\n' ) + p++; + if( *p ) + return -1; /* garbage after dashes */ + save_c = *save_p; *save_p = 0; + p = line+5; + for(i=0; (s=head_strings[i]); i++ ) + if( !strcmp(s, p) ) + break; + *save_p = save_c; + if( !s ) + return -1; /* unknown armor line */ + + if( opt.verbose > 1 ) + log_info(_("armor: %s\n"), head_strings[i]); + return i; +} + + + +/**************** + * Parse a header lines + * Return 0: Empty line (end of header lines) + * -1: invalid header line + * >0: Good header line + */ +static int +parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) +{ + byte *p; + int hashes=0; + unsigned int len2; + + len2 = check_trailing_ws( line, len ); + if( !len2 ) { + afx->buffer_pos = len2; /* (it is not the fine way to do it here) */ + return 0; /* WS only: same as empty line */ + } + len = len2; + line[len2] = 0; + + p = strchr( line, ':'); + if( !p || !p[1] ) { + log_error(_("invalid armor header: ")); + print_string( stderr, line, len, 0 ); + putc('\n', stderr); + return -1; + } + + if( opt.verbose ) { + log_info(_("armor header: ")); + print_string( stderr, line, len, 0 ); + putc('\n', stderr); + } + + if( afx->in_cleartext ) { + if( (hashes=parse_hash_header( line )) ) + afx->hashes |= hashes; + else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) ) + afx->not_dash_escaped = 1; + else { + log_error(_("invalid clearsig header\n")); + return -1; + } + } + return 1; +} + + + +/* figure out whether the data is armored or not */ +static int +check_input( armor_filter_context_t *afx, IOBUF a ) +{ + int rc = 0; + int i; + byte *line; + unsigned len; + unsigned maxlen; + int hdr_line = -1; + + /* read the first line to see whether this is armored data */ + maxlen = MAX_LINELEN; + len = afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + line = afx->buffer; + if( !maxlen ) { + /* line has been truncated: assume not armored */ + afx->inp_checked = 1; + afx->inp_bypass = 1; + return 0; + } + + if( !len ) { + return -1; /* eof */ + } + + /* (the line is always a C string but maybe longer) */ + if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) ) + ; + else if( !is_armored( line ) ) { + afx->inp_checked = 1; + afx->inp_bypass = 1; + return 0; + } + + /* find the armor header */ + while(len) { + i = is_armor_header( line, len ); + if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) { + hdr_line = i; + if( hdr_line == BEGIN_SIGNED_MSG_IDX ) { + if( afx->in_cleartext ) { + log_error(_("nested clear text signatures\n")); + rc = G10ERR_INVALID_ARMOR; + } + afx->in_cleartext = 1; + } + break; + } + /* read the next line (skip all truncated lines) */ + do { + maxlen = MAX_LINELEN; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + line = afx->buffer; + len = afx->buffer_len; + } while( !maxlen ); + } + + /* parse the header lines */ + while(len) { + /* read the next line (skip all truncated lines) */ + do { + maxlen = MAX_LINELEN; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + line = afx->buffer; + len = afx->buffer_len; + } while( !maxlen ); + + i = parse_header_line( afx, line, len ); + if( i <= 0 ) { + if( i ) + rc = G10ERR_INVALID_ARMOR; + break; + } + } + + + if( rc ) + invalid_armor(); + else if( afx->in_cleartext ) + afx->faked = 1; + else { + afx->inp_checked = 1; + afx->crc = CRCINIT; + afx->idx = 0; + afx->radbuf[0] = 0; + } + + return rc; +} + + + +/**************** + * Fake a literal data packet and wait for the next armor line + * fixme: empty line handling and null length clear text signature are + * not implemented/checked. + */ +static int +fake_packet( armor_filter_context_t *afx, IOBUF a, + size_t *retn, byte *buf, size_t size ) +{ + int rc = 0; + size_t len = 0; + int lastline = 0; + unsigned maxlen, n; + byte *p; + + len = 2; /* reserve 2 bytes for the length header */ + size -= 2; /* and 2 for the terminating header */ + while( !rc && len < size ) { + /* copy what we have in the line buffer */ + if( afx->faked == 1 ) + afx->faked++; /* skip the first (empty) line */ + else { + while( len < size && afx->buffer_pos < afx->buffer_len ) + buf[len++] = afx->buffer[afx->buffer_pos++]; + if( len >= size ) + continue; + } + + /* read the next line */ + maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + if( !afx->buffer_len ) { + rc = -1; /* eof (should not happen) */ + continue; + } + if( !maxlen ) + afx->truncated++; + if( !afx->not_dash_escaped ) { + int crlf; + p = afx->buffer; + n = afx->buffer_len; + crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n'; + + /* PGP2 does not treat a tab as white space character */ + afx->buffer_len = trim_trailing_chars( p, n, + afx->pgp2mode ? " \r\n" : " \t\r\n"); + /* the buffer is always allocated with enough space to append + * the removed [CR], LF and a Nul + * The reason for this complicated procedure is to keep at least + * the original type of lineending - handling of the removed + * trailing spaces seems to be impossible in our method + * of faking a packet; either we have to use a temporary file + * or calculate the hash here in this module and somehow find + * a way to send the hash down the processing line (well, a special + * faked packet could do the job). + */ + if( crlf ) + afx->buffer[afx->buffer_len++] = '\r'; + afx->buffer[afx->buffer_len++] = '\n'; + afx->buffer[afx->buffer_len] = 0; + } + p = afx->buffer; + n = afx->buffer_len; + + if( n > 2 && *p == '-' ) { + /* check for dash escaped or armor header */ + if( p[1] == ' ' && !afx->not_dash_escaped ) { + /* issue a warning if it is not regular encoded */ + if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) { + log_info(_("invalid dash escaped line: ")); + print_string( stderr, p, n, 0 ); + putc('\n', stderr); + } + afx->buffer_pos = 2; /* skip */ + } + else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) { + int type = is_armor_header( p, n ); + if( afx->not_dash_escaped && type != BEGIN_SIGNATURE ) + ; /* this is okay */ + else { + if( type != BEGIN_SIGNATURE ) { + log_info(_("unexpected armor:")); + print_string( stderr, p, n, 0 ); + putc('\n', stderr); + } + lastline = 1; + rc = -1; + } + } + } + } + + buf[0] = (len-2) >> 8; + buf[1] = (len-2); + if( lastline ) { /* write last (ending) length header */ + if( buf[0] || buf[1] ) { /* only if we have some text */ + buf[len++] = 0; + buf[len++] = 0; + } + rc = 0; + afx->faked = 0; + afx->in_cleartext = 0; + /* and now read the header lines */ + afx->buffer_pos = 0; + for(;;) { + int i; + + /* read the next line (skip all truncated lines) */ + do { + maxlen = MAX_LINELEN; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + } while( !maxlen ); + p = afx->buffer; + n = afx->buffer_len; + if( !n ) { + rc = -1; + break; /* eof */ + } + i = parse_header_line( afx, p , n ); + if( i <= 0 ) { + if( i ) + invalid_armor(); + break; + } + } + afx->inp_checked = 1; + afx->crc = CRCINIT; + afx->idx = 0; + afx->radbuf[0] = 0; + } + + *retn = len; + return rc; +} + + +static int +invalid_crc(void) +{ + if ( opt.ignore_crc_error ) + return 0; + log_inc_errorcount(); + return G10ERR_INVALID_ARMOR; +} + + +static int +radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, + byte *buf, size_t size ) +{ + byte val; + int c=0, c2; /*init c because gcc is not clever enough for the continue*/ + int checkcrc=0; + int rc = 0; + size_t n = 0; + int idx, i; + u32 crc; + + crc = afx->crc; + idx = afx->idx; + val = afx->radbuf[0]; + for( n=0; n < size; ) { + + if( afx->buffer_pos < afx->buffer_len ) + c = afx->buffer[afx->buffer_pos++]; + else { /* read the next line */ + unsigned maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + if( !maxlen ) + afx->truncated++; + if( !afx->buffer_len ) + break; /* eof */ + continue; + } + + again: + if( c == '\n' || c == ' ' || c == '\r' || c == '\t' ) + continue; + else if( c == '=' ) { /* pad character: stop */ + /* some mailers leave quoted-printable encoded characters + * so we try to workaround this */ + if( afx->buffer_pos+2 < afx->buffer_len ) { + int cc1, cc2, cc3; + cc1 = afx->buffer[afx->buffer_pos]; + cc2 = afx->buffer[afx->buffer_pos+1]; + cc3 = afx->buffer[afx->buffer_pos+2]; + if( isxdigit(cc1) && isxdigit(cc2) + && strchr( "=\n\r\t ", cc3 )) { + /* well it seems to be the case - adjust */ + c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10); + c <<= 4; + c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10); + afx->buffer_pos += 2; + afx->qp_detected = 1; + goto again; + } + } + + if( idx == 1 ) + buf[n++] = val; + checkcrc++; + break; + } + else if( (c = asctobin[(c2=c)]) == 255 ) { + log_error(_("invalid radix64 character %02x skipped\n"), c2); + continue; + } + switch(idx) { + case 0: val = c << 2; break; + case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break; + case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break; + case 3: val |= c&0x3f; buf[n++] = val; break; + } + idx = (idx+1) % 4; + } + + for(i=0; i < n; i++ ) + crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]]; + crc &= 0x00ffffff; + afx->crc = crc; + afx->idx = idx; + afx->radbuf[0] = val; + + if( checkcrc ) { + afx->any_data = 1; + afx->inp_checked=0; + afx->faked = 0; + for(;;) { /* skip lf and pad characters */ + if( afx->buffer_pos < afx->buffer_len ) + c = afx->buffer[afx->buffer_pos++]; + else { /* read the next line */ + unsigned maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, &maxlen ); + if( !maxlen ) + afx->truncated++; + if( !afx->buffer_len ) + break; /* eof */ + continue; + } + if( c == '\n' || c == ' ' || c == '\r' + || c == '\t' || c == '=' ) + continue; + break; + } + if( c == -1 ) + log_error(_("premature eof (no CRC)\n")); + else { + u32 mycrc = 0; + idx = 0; + do { + if( (c = asctobin[c]) == 255 ) + break; + switch(idx) { + case 0: val = c << 2; break; + case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break; + case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break; + case 3: val |= c&0x3f; mycrc |= val; break; + } + for(;;) { + if( afx->buffer_pos < afx->buffer_len ) + c = afx->buffer[afx->buffer_pos++]; + else { /* read the next line */ + unsigned maxlen = MAX_LINELEN; + afx->buffer_pos = 0; + afx->buffer_len = iobuf_read_line( a, &afx->buffer, + &afx->buffer_size, + &maxlen ); + if( !maxlen ) + afx->truncated++; + if( !afx->buffer_len ) + break; /* eof */ + continue; + } + break; + } + if( !afx->buffer_len ) + break; /* eof */ + } while( ++idx < 4 ); + if( c == -1 ) { + log_info(_("premature eof (in CRC)\n")); + rc = invalid_crc(); + } + else if( idx != 4 ) { + log_info(_("malformed CRC\n")); + rc = invalid_crc(); + } + else if( mycrc != afx->crc ) { + log_info (_("CRC error; %06lx - %06lx\n"), + (ulong)afx->crc, (ulong)mycrc); + rc = invalid_crc(); + } + else { + rc = 0; + /* FIXME: Here we should emit another control packet, + * so that we know in mainproc that we are processing + * a clearsign message */ +#if 0 + for(rc=0;!rc;) { + rc = 0 /*check_trailer( &fhdr, c )*/; + if( !rc ) { + if( (c=iobuf_get(a)) == -1 ) + rc = 2; + } + } + if( rc == -1 ) + rc = 0; + else if( rc == 2 ) { + log_error(_("premature eof (in Trailer)\n")); + rc = G10ERR_INVALID_ARMOR; + } + else { + log_error(_("error in trailer line\n")); + rc = G10ERR_INVALID_ARMOR; + } +#endif + } + } + } + + if( !n ) + rc = -1; + + *retn = n; + return rc; +} + +/**************** + * This filter is used to handle the armor stuff + */ +int +armor_filter( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len) +{ + size_t size = *ret_len; + armor_filter_context_t *afx = opaque; + int rc=0, i, c; + byte radbuf[3]; + int idx, idx2; + size_t n=0; + u32 crc; +#if 0 + static FILE *fp ; + + if( !fp ) { + fp = fopen("armor.out", "w"); + assert(fp); + } +#endif + + if( DBG_FILTER ) + log_debug("armor-filter: control: %d\n", control ); + if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) { + n = 0; + if( afx->buffer_len ) { + for(; n < size && afx->buffer_pos < afx->buffer_len; n++ ) + buf[n++] = afx->buffer[afx->buffer_pos++]; + if( afx->buffer_pos >= afx->buffer_len ) + afx->buffer_len = 0; + } + for(; n < size; n++ ) { + if( (c=iobuf_get(a)) == -1 ) + break; + buf[n] = c & 0xff; + } + if( !n ) + rc = -1; + *ret_len = n; + } + else if( control == IOBUFCTRL_UNDERFLOW ) { + /* We need some space for the faked packet. The minmum required + * size is ~18 + length of the session marker */ + if( size < 50 ) + BUG(); /* supplied buffer too short */ + + if( afx->faked ) + rc = fake_packet( afx, a, &n, buf, size ); + else if( !afx->inp_checked ) { + rc = check_input( afx, a ); + if( afx->inp_bypass ) { + for(n=0; n < size && afx->buffer_pos < afx->buffer_len; ) + buf[n++] = afx->buffer[afx->buffer_pos++]; + if( afx->buffer_pos >= afx->buffer_len ) + afx->buffer_len = 0; + if( !n ) + rc = -1; + } + else if( afx->faked ) { + unsigned int hashes = afx->hashes; + const byte *sesmark; + size_t sesmarklen; + + sesmark = get_session_marker( &sesmarklen ); + if ( sesmarklen > 20 ) + BUG(); + + /* the buffer is at least 15+n*15 bytes long, so it + * is easy to construct the packets */ + + hashes &= 1|2|4|8|16|32|64; + if( !hashes ) { + hashes |= 4; /* default to MD 5 */ + /* This is non-ideal since PGP 5-8 have the same + end-of-line bugs as PGP 2. However, we only + enable pgp2mode if there is no Hash: header. */ + if( opt.pgp2_workarounds ) + afx->pgp2mode = 1; + } + n=0; + /* first a gpg control packet */ + buf[n++] = 0xff; /* new format, type 63, 1 length byte */ + n++; /* see below */ + memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen; + buf[n++] = CTRLPKT_CLEARSIGN_START; + buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */ + if( hashes & 1 ) + buf[n++] = DIGEST_ALGO_RMD160; + if( hashes & 2 ) + buf[n++] = DIGEST_ALGO_SHA1; + if( hashes & 4 ) + buf[n++] = DIGEST_ALGO_MD5; + if( hashes & 8 ) + buf[n++] = DIGEST_ALGO_TIGER; + if( hashes & 16 ) + buf[n++] = DIGEST_ALGO_SHA256; + if( hashes & 32 ) + buf[n++] = DIGEST_ALGO_SHA384; + if( hashes & 64 ) + buf[n++] = DIGEST_ALGO_SHA512; + buf[1] = n - 2; + + /* followed by a plaintext packet */ + buf[n++] = 0xaf; /* old packet format, type 11, var length */ + buf[n++] = 0; /* set the length header */ + buf[n++] = 6; + buf[n++] = 't'; /* canonical text mode */ + buf[n++] = 0; /* namelength */ + memset(buf+n, 0, 4); /* timestamp */ + n += 4; + } + else if( !rc ) + rc = radix64_read( afx, a, &n, buf, size ); + } + else + rc = radix64_read( afx, a, &n, buf, size ); +#if 0 + if( n ) + if( fwrite(buf, n, 1, fp ) != 1 ) + BUG(); +#endif + *ret_len = n; + } + else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) { + if( !afx->status ) { /* write the header line */ + const char *s; + + if( afx->what >= DIM(head_strings) ) + log_bug("afx->what=%d", afx->what); + iobuf_writestr(a, "-----"); + iobuf_writestr(a, head_strings[afx->what] ); + iobuf_writestr(a, "-----" LF ); + if( !opt.no_version ) + iobuf_writestr(a, "Version: GnuPG v" VERSION " (" + PRINTABLE_OS_NAME ")" LF ); + + /* write the comment string or a default one */ + s = opt.comment_string; + if( s && *s ) { + iobuf_writestr(a, "Comment: " ); + for( ; *s; s++ ) { + if( *s == '\n' ) + iobuf_writestr(a, "\\n" ); + else if( *s == '\r' ) + iobuf_writestr(a, "\\r" ); + else if( *s == '\v' ) + iobuf_writestr(a, "\\v" ); + else + iobuf_put(a, *s ); + } + iobuf_writestr(a, LF ); + } + + if ( afx->hdrlines ) { + for ( s = afx->hdrlines; *s; s++ ) { +#ifdef HAVE_DOSISH_SYSTEM + if ( *s == '\n' ) + iobuf_put( a, '\r'); +#endif + iobuf_put(a, *s ); + } + } + iobuf_writestr(a, LF ); + afx->status++; + afx->idx = 0; + afx->idx2 = 0; + afx->crc = CRCINIT; + + } + crc = afx->crc; + idx = afx->idx; + idx2 = afx->idx2; + for(i=0; i < idx; i++ ) + radbuf[i] = afx->radbuf[i]; + + for(i=0; i < size; i++ ) + crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]]; + crc &= 0x00ffffff; + + for( ; size; buf++, size-- ) { + radbuf[idx++] = *buf; + if( idx > 2 ) { + idx = 0; + c = bintoasc[(*radbuf >> 2) & 077]; + iobuf_put(a, c); + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + iobuf_put(a, c); + c = bintoasc[radbuf[2]&077]; + iobuf_put(a, c); + if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ + iobuf_writestr(a, LF ); + idx2=0; + } + } + } + for(i=0; i < idx; i++ ) + afx->radbuf[i] = radbuf[i]; + afx->idx = idx; + afx->idx2 = idx2; + afx->crc = crc; + } + else if( control == IOBUFCTRL_INIT ) { + if( !is_initialized ) + initialize(); + } + else if( control == IOBUFCTRL_CANCEL ) { + afx->cancel = 1; + } + else if( control == IOBUFCTRL_FREE ) { + if( afx->cancel ) + ; + else if( afx->status ) { /* pad, write cecksum, and bottom line */ + crc = afx->crc; + idx = afx->idx; + idx2 = afx->idx2; + for(i=0; i < idx; i++ ) + radbuf[i] = afx->radbuf[i]; + if( idx ) { + c = bintoasc[(*radbuf>>2)&077]; + iobuf_put(a, c); + if( idx == 1 ) { + c = bintoasc[((*radbuf << 4) & 060) & 077]; + iobuf_put(a, c); + iobuf_put(a, '='); + iobuf_put(a, '='); + } + else { /* 2 */ + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[((radbuf[1] << 2) & 074) & 077]; + iobuf_put(a, c); + iobuf_put(a, '='); + } + if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ + iobuf_writestr(a, LF ); + idx2=0; + } + } + /* may need a linefeed */ + if( idx2 ) + iobuf_writestr(a, LF ); + /* write the CRC */ + iobuf_put(a, '='); + radbuf[0] = crc >>16; + radbuf[1] = crc >> 8; + radbuf[2] = crc; + c = bintoasc[(*radbuf >> 2) & 077]; + iobuf_put(a, c); + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + iobuf_put(a, c); + c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + iobuf_put(a, c); + c = bintoasc[radbuf[2]&077]; + iobuf_put(a, c); + iobuf_writestr(a, LF ); + /* and the the trailer */ + if( afx->what >= DIM(tail_strings) ) + log_bug("afx->what=%d", afx->what); + iobuf_writestr(a, "-----"); + iobuf_writestr(a, tail_strings[afx->what] ); + iobuf_writestr(a, "-----" LF ); + } + else if( !afx->any_data && !afx->inp_bypass ) { + log_error(_("no valid OpenPGP data found.\n")); + afx->no_openpgp_data = 1; + write_status_text( STATUS_NODATA, "1" ); + } + if( afx->truncated ) + log_info(_("invalid armor: line longer than %d characters\n"), + MAX_LINELEN ); + /* issue an error to enforce dissemination of correct software */ + if( afx->qp_detected ) + log_error(_("quoted printable character in armor - " + "probably a buggy MTA has been used\n") ); + m_free( afx->buffer ); + afx->buffer = NULL; + } + else if( control == IOBUFCTRL_DESC ) + *(char**)buf = "armor_filter"; + return rc; +} + + +/**************** + * create a radix64 encoded string. + */ +char * +make_radix64_string( const byte *data, size_t len ) +{ + char *buffer, *p; + + buffer = p = m_alloc( (len+2)/3*4 + 1 ); + for( ; len >= 3 ; len -= 3, data += 3 ) { + *p++ = bintoasc[(data[0] >> 2) & 077]; + *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; + *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077]; + *p++ = bintoasc[data[2]&077]; + } + if( len == 2 ) { + *p++ = bintoasc[(data[0] >> 2) & 077]; + *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; + *p++ = bintoasc[((data[1]<<2)&074)]; + } + else if( len == 1 ) { + *p++ = bintoasc[(data[0] >> 2) & 077]; + *p++ = bintoasc[(data[0] <<4)&060]; + } + *p = 0; + return buffer; +} + + +/*********************************************** + * For the pipemode command we can't use the armor filter for various + * reasons, so we use this new unarmor_pump stuff to remove the armor + */ + +enum unarmor_state_e { + STA_init = 0, + STA_bypass, + STA_wait_newline, + STA_wait_dash, + STA_first_dash, + STA_compare_header, + STA_found_header_wait_newline, + STA_skip_header_lines, + STA_skip_header_lines_non_ws, + STA_read_data, + STA_wait_crc, + STA_read_crc, + STA_ready +}; + +struct unarmor_pump_s { + enum unarmor_state_e state; + byte val; + int checkcrc; + int pos; /* counts from 0..3 */ + u32 crc; + u32 mycrc; /* the one store in the data */ +}; + + + +UnarmorPump +unarmor_pump_new (void) +{ + UnarmorPump x; + + if( !is_initialized ) + initialize(); + x = m_alloc_clear (sizeof *x); + return x; +} + +void +unarmor_pump_release (UnarmorPump x) +{ + m_free (x); +} + +/* + * Get the next character from the ascii armor taken from the IOBUF + * created earlier by unarmor_pump_new(). + * Return: c = Character + * 256 = ignore this value + * -1 = End of current armor + * -2 = Premature EOF (not used) + * -3 = Invalid armor + */ +int +unarmor_pump (UnarmorPump x, int c) +{ + int rval = 256; /* default is to ignore the return value */ + + switch (x->state) { + case STA_init: + { + byte tmp[1]; + tmp[0] = c; + if ( is_armored (tmp) ) + x->state = c == '-'? STA_first_dash : STA_wait_newline; + else { + x->state = STA_bypass; + return c; + } + } + break; + case STA_bypass: + return c; /* return here to avoid crc calculation */ + case STA_wait_newline: + if (c == '\n') + x->state = STA_wait_dash; + break; + case STA_wait_dash: + x->state = c == '-'? STA_first_dash : STA_wait_newline; + break; + case STA_first_dash: /* just need for initalization */ + x->pos = 0; + x->state = STA_compare_header; + case STA_compare_header: + if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) { + if ( x->pos == 28 ) + x->state = STA_found_header_wait_newline; + } + else + x->state = c == '\n'? STA_wait_dash : STA_wait_newline; + break; + case STA_found_header_wait_newline: + /* to make CR,LF issues easier we simply allow for white space + behind the 5 dashes */ + if ( c == '\n' ) + x->state = STA_skip_header_lines; + else if ( c != '\r' && c != ' ' && c != '\t' ) + x->state = STA_wait_dash; /* garbage after the header line */ + break; + case STA_skip_header_lines: + /* i.e. wait for one empty line */ + if ( c == '\n' ) { + x->state = STA_read_data; + x->crc = CRCINIT; + x->val = 0; + x->pos = 0; + } + else if ( c != '\r' && c != ' ' && c != '\t' ) + x->state = STA_skip_header_lines_non_ws; + break; + case STA_skip_header_lines_non_ws: + /* like above but we already encountered non white space */ + if ( c == '\n' ) + x->state = STA_skip_header_lines; + break; + case STA_read_data: + /* fixme: we don't check for the trailing dash lines but rely + * on the armor stop characters */ + if( c == '\n' || c == ' ' || c == '\r' || c == '\t' ) + break; /* skip all kind of white space */ + + if( c == '=' ) { /* pad character: stop */ + if( x->pos == 1 ) /* in this case val has some value */ + rval = x->val; + x->state = STA_wait_crc; + break; + } + + { + int c2; + if( (c = asctobin[(c2=c)]) == 255 ) { + log_error(_("invalid radix64 character %02x skipped\n"), c2); + break; + } + } + + switch(x->pos) { + case 0: + x->val = c << 2; + break; + case 1: + x->val |= (c>>4)&3; + rval = x->val; + x->val = (c<<4)&0xf0; + break; + case 2: + x->val |= (c>>2)&15; + rval = x->val; + x->val = (c<<6)&0xc0; + break; + case 3: + x->val |= c&0x3f; + rval = x->val; + break; + } + x->pos = (x->pos+1) % 4; + break; + case STA_wait_crc: + if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' ) + break; /* skip ws and pad characters */ + /* assume that we are at the next line */ + x->state = STA_read_crc; + x->pos = 0; + x->mycrc = 0; + case STA_read_crc: + if( (c = asctobin[c]) == 255 ) { + rval = -1; /* ready */ + if( x->crc != x->mycrc ) { + log_info (_("CRC error; %06lx - %06lx\n"), + (ulong)x->crc, (ulong)x->mycrc); + if ( invalid_crc() ) + rval = -3; + } + x->state = STA_ready; /* not sure whether this is correct */ + break; + } + + switch(x->pos) { + case 0: + x->val = c << 2; + break; + case 1: + x->val |= (c>>4)&3; + x->mycrc |= x->val << 16; + x->val = (c<<4)&0xf0; + break; + case 2: + x->val |= (c>>2)&15; + x->mycrc |= x->val << 8; + x->val = (c<<6)&0xc0; + break; + case 3: + x->val |= c&0x3f; + x->mycrc |= x->val; + break; + } + x->pos = (x->pos+1) % 4; + break; + case STA_ready: + rval = -1; + break; + } + + if ( !(rval & ~255) ) { /* compute the CRC */ + x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval]; + x->crc &= 0x00ffffff; + } + + return rval; +} diff --git a/g10/build-packet.c b/g10/build-packet.c new file mode 100644 index 000000000..86aa07dc2 --- /dev/null +++ b/g10/build-packet.c @@ -0,0 +1,1196 @@ +/* build-packet.c - assemble packets and write them + * 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 "errors.h" +#include "iobuf.h" +#include "mpi.h" +#include "util.h" +#include "cipher.h" +#include "memory.h" +#include "options.h" + + +static int do_comment( IOBUF out, int ctb, PKT_comment *rem ); +static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); +static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); +static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk ); +static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); +static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); +static u32 calc_plaintext( PKT_plaintext *pt ); +static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); +static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); +static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); +static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); + +static int calc_header_length( u32 len, int new_ctb ); +static int write_16(IOBUF inp, u16 a); +static int write_32(IOBUF inp, u32 a); +static int write_header( IOBUF out, int ctb, u32 len ); +static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); +static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ); +static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); +static int write_version( IOBUF out, int ctb ); + +/**************** + * Build a packet and write it to INP + * Returns: 0 := okay + * >0 := error + * Note: Caller must free the packet + */ +int +build_packet( IOBUF out, PACKET *pkt ) +{ + int new_ctb=0, rc=0, ctb; + int pkttype; + + if( DBG_PACKET ) + log_debug("build_packet() type=%d\n", pkt->pkttype ); + assert( pkt->pkt.generic ); + + switch( (pkttype = pkt->pkttype) ) { + case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break; + case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; + case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; + case PKT_USER_ID: + if( pkt->pkt.user_id->attrib_data ) + pkttype = PKT_ATTRIBUTE; + break; + default: break; + } + + if( new_ctb || pkttype > 15 ) /* new format */ + ctb = 0xc0 | (pkttype & 0x3f); + else + ctb = 0x80 | ((pkttype & 15)<<2); + switch( pkttype ) { + case PKT_ATTRIBUTE: + case PKT_USER_ID: + rc = do_user_id( out, ctb, pkt->pkt.user_id ); + break; + case PKT_COMMENT: + rc = do_comment( out, ctb, pkt->pkt.comment ); + break; + case PKT_PUBLIC_SUBKEY: + case PKT_PUBLIC_KEY: + rc = do_public_key( out, ctb, pkt->pkt.public_key ); + break; + case PKT_SECRET_SUBKEY: + case PKT_SECRET_KEY: + rc = do_secret_key( out, ctb, pkt->pkt.secret_key ); + break; + case PKT_SYMKEY_ENC: + rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc ); + break; + case PKT_PUBKEY_ENC: + rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc ); + break; + case PKT_PLAINTEXT: + rc = do_plaintext( out, ctb, pkt->pkt.plaintext ); + break; + case PKT_ENCRYPTED: + rc = do_encrypted( out, ctb, pkt->pkt.encrypted ); + break; + case PKT_ENCRYPTED_MDC: + rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted ); + break; + case PKT_COMPRESSED: + rc = do_compressed( out, ctb, pkt->pkt.compressed ); + break; + case PKT_SIGNATURE: + rc = do_signature( out, ctb, pkt->pkt.signature ); + break; + case PKT_ONEPASS_SIG: + rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig ); + break; + case PKT_RING_TRUST: + break; /* ignore it (keyring.c does write it directly)*/ + case PKT_MDC: /* we write it directly, so we should never see it here. */ + default: + log_bug("invalid packet type in build_packet()\n"); + break; + } + + return rc; +} + +/**************** + * calculate the length of a packet described by PKT + */ +u32 +calc_packet_length( PACKET *pkt ) +{ + u32 n=0; + int new_ctb = 0; + + assert( pkt->pkt.generic ); + switch( pkt->pkttype ) { + case PKT_PLAINTEXT: + n = calc_plaintext( pkt->pkt.plaintext ); + new_ctb = pkt->pkt.plaintext->new_ctb; + break; + case PKT_ATTRIBUTE: + case PKT_USER_ID: + case PKT_COMMENT: + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_SYMKEY_ENC: + case PKT_PUBKEY_ENC: + case PKT_ENCRYPTED: + case PKT_SIGNATURE: + case PKT_ONEPASS_SIG: + case PKT_RING_TRUST: + case PKT_COMPRESSED: + default: + log_bug("invalid packet type in calc_packet_length()"); + break; + } + + n += calc_header_length(n, new_ctb); + return n; +} + +static void +write_fake_data( IOBUF out, MPI a ) +{ + if( a ) { + int i; + void *p; + + p = mpi_get_opaque( a, &i ); + iobuf_write( out, p, i ); + } +} + + +static int +do_comment( IOBUF out, int ctb, PKT_comment *rem ) +{ + if( opt.sk_comments ) { + write_header(out, ctb, rem->len); + if( iobuf_write( out, rem->data, rem->len ) ) + return G10ERR_WRITE_FILE; + } + return 0; +} + +static int +do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) +{ + if( uid->attrib_data ) { + write_header(out, ctb, uid->attrib_len); + if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) ) + return G10ERR_WRITE_FILE; + } + else { + write_header(out, ctb, uid->len); + if( iobuf_write( out, uid->name, uid->len ) ) + return G10ERR_WRITE_FILE; + } + return 0; +} + +static int +do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) +{ + int rc = 0; + int n, i; + IOBUF a = iobuf_temp(); + + if( !pk->version ) + iobuf_put( a, 3 ); + else + iobuf_put( a, pk->version ); + write_32(a, pk->timestamp ); + if( pk->version < 4 ) { + u16 ndays; + if( pk->expiredate ) + ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, ndays ); + } + iobuf_put(a, pk->pubkey_algo ); + n = pubkey_get_npkey( pk->pubkey_algo ); + if( !n ) + write_fake_data( a, pk->pkey[0] ); + for(i=0; i < n; i++ ) + mpi_write(a, pk->pkey[i] ); + + write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + +/**************** + * Make a hash value from the public key certificate + */ +void +hash_public_key( MD_HANDLE md, PKT_public_key *pk ) +{ + PACKET pkt; + int rc = 0; + int ctb; + ulong pktlen; + int c; + IOBUF a = iobuf_temp(); +#if 0 + FILE *fp = fopen("dump.pk", "a"); + int i=0; + + fprintf(fp, "\nHashing PK (v%d):\n", pk->version); +#endif + + /* build the packet */ + init_packet(&pkt); + pkt.pkttype = PKT_PUBLIC_KEY; + pkt.pkt.public_key = pk; + if( (rc = build_packet( a, &pkt )) ) + log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc)); + + if( !(pk->version == 3 && pk->pubkey_algo == 16) ) { + /* skip the constructed header but don't do this for our very old + * v3 ElG keys */ + ctb = iobuf_get_noeof(a); + pktlen = 0; + if( (ctb & 0x40) ) { + c = iobuf_get_noeof(a); + if( c < 192 ) + pktlen = c; + else if( c < 224 ) { + pktlen = (c - 192) * 256; + c = iobuf_get_noeof(a); + pktlen += c + 192; + } + else if( c == 255 ) { + pktlen = iobuf_get_noeof(a) << 24; + pktlen |= iobuf_get_noeof(a) << 16; + pktlen |= iobuf_get_noeof(a) << 8; + pktlen |= iobuf_get_noeof(a); + } + } + else { + int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); + for( ; lenbytes; lenbytes-- ) { + pktlen <<= 8; + pktlen |= iobuf_get_noeof(a); + } + } + /* hash a header */ + md_putc( md, 0x99 ); + pktlen &= 0xffff; /* can't handle longer packets */ + md_putc( md, pktlen >> 8 ); + md_putc( md, pktlen & 0xff ); + } + /* hash the packet body */ + while( (c=iobuf_get(a)) != -1 ) { +#if 0 + fprintf( fp," %02x", c ); + if( (++i == 24) ) { + putc('\n', fp); + i=0; + } +#endif + md_putc( md, c ); + } +#if 0 + putc('\n', fp); + fclose(fp); +#endif + iobuf_cancel(a); +} + + +static int +do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) +{ + int rc = 0; + int i, nskey, npkey; + IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */ + + /* Write the version number - if none is specified, use 3 */ + if( !sk->version ) + iobuf_put( a, 3 ); + else + iobuf_put( a, sk->version ); + write_32(a, sk->timestamp ); + + /* v3 needs the expiration time */ + if( sk->version < 4 ) { + u16 ndays; + if( sk->expiredate ) + ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); + else + ndays = 0; + write_16(a, ndays); + } + + iobuf_put(a, sk->pubkey_algo ); + + /* get number of secret and public parameters. They are held in + one array first the public ones, then the secret ones */ + nskey = pubkey_get_nskey( sk->pubkey_algo ); + npkey = pubkey_get_npkey( sk->pubkey_algo ); + + /* If we don't have any public parameters - which is the case if + we don't know the algorithm used - the parameters are stored as + one blob in a faked (opaque) MPI */ + if( !npkey ) { + write_fake_data( a, sk->skey[0] ); + goto leave; + } + assert( npkey < nskey ); + + /* Writing the public parameters is easy */ + for(i=0; i < npkey; i++ ) + mpi_write(a, sk->skey[i] ); + + /* build the header for protected (encrypted) secret parameters */ + if( sk->is_protected ) { + if( is_RSA(sk->pubkey_algo) && sk->version < 4 + && !sk->protect.s2k.mode ) { + /* the simple rfc1991 (v3) way */ + iobuf_put(a, sk->protect.algo ); + iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); + } + else { + /* OpenPGP protection according to rfc2440 */ + iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff ); + iobuf_put(a, sk->protect.algo ); + if( sk->protect.s2k.mode >= 1000 ) { + /* These modes are not possible in OpenPGP, we use them + to implement our extensions, 101 can be seen as a + private/experimental extension (this is not + specified in rfc2440 but the same scheme is used + for all other algorithm identifiers) */ + iobuf_put(a, 101 ); + iobuf_put(a, sk->protect.s2k.hash_algo ); + iobuf_write(a, "GNU", 3 ); + iobuf_put(a, sk->protect.s2k.mode - 1000 ); + } + else { + iobuf_put(a, sk->protect.s2k.mode ); + iobuf_put(a, sk->protect.s2k.hash_algo ); + } + if( sk->protect.s2k.mode == 1 + || sk->protect.s2k.mode == 3 ) + iobuf_write(a, sk->protect.s2k.salt, 8 ); + if( sk->protect.s2k.mode == 3 ) + iobuf_put(a, sk->protect.s2k.count ); + + /* For out special mode 1001 we do not need an IV */ + if( sk->protect.s2k.mode != 1001 ) + iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); + } + } + else + iobuf_put(a, 0 ); + + if( sk->protect.s2k.mode == 1001 ) + ; /* GnuPG extension - don't write a secret key at all */ + else if( sk->is_protected && sk->version >= 4 ) { + /* The secret key is protected - write it out as it is */ + byte *p; + assert( mpi_is_opaque( sk->skey[npkey] ) ); + p = mpi_get_opaque( sk->skey[npkey], &i ); + iobuf_write(a, p, i ); + } + else if( sk->is_protected ) { + /* The secret key is protected te old v4 way. */ + for( ; i < nskey; i++ ) { + byte *p; + int ndata; + + assert (mpi_is_opaque (sk->skey[i])); + p = mpi_get_opaque (sk->skey[i], &ndata); + iobuf_write (a, p, ndata); + } + write_16(a, sk->csum ); + } + else { + /* non-protected key */ + for( ; i < nskey; i++ ) + mpi_write(a, sk->skey[i] ); + write_16(a, sk->csum ); + } + + leave: + /* Build the header of the packet - which we must do after writing all + the other stuff, so that we know the length of the packet */ + write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); + /* And finally write it out the real stream */ + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); /* close the remporary buffer */ + return rc; +} + +static int +do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) +{ + int rc = 0; + IOBUF a = iobuf_temp(); + + assert( enc->version == 4 ); + switch( enc->s2k.mode ) { + case 0: case 1: case 3: break; + default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); + } + iobuf_put( a, enc->version ); + iobuf_put( a, enc->cipher_algo ); + iobuf_put( a, enc->s2k.mode ); + iobuf_put( a, enc->s2k.hash_algo ); + if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { + iobuf_write(a, enc->s2k.salt, 8 ); + if( enc->s2k.mode == 3 ) + iobuf_put(a, enc->s2k.count); + } + if( enc->seskeylen ) + iobuf_write(a, enc->seskey, enc->seskeylen ); + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + + + +static int +do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) +{ + int rc = 0; + int n, i; + IOBUF a = iobuf_temp(); + + write_version( a, ctb ); + if( enc->throw_keyid ) { + write_32(a, 0 ); /* don't tell Eve who can decrypt the message */ + write_32(a, 0 ); + } + else { + write_32(a, enc->keyid[0] ); + write_32(a, enc->keyid[1] ); + } + iobuf_put(a,enc->pubkey_algo ); + n = pubkey_get_nenc( enc->pubkey_algo ); + if( !n ) + write_fake_data( a, enc->data[0] ); + for(i=0; i < n; i++ ) + mpi_write(a, enc->data[i] ); + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + + + +static u32 +calc_plaintext( PKT_plaintext *pt ) +{ + return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; +} + +static int +do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) +{ + int i, rc = 0; + u32 n; + byte buf[1000]; /* this buffer has the plaintext! */ + int nbytes; + + /* Truncate namelen to the maximum 255 characters. This does mean + that a function that calls build_packet with an illegal literal + packet will get it back legalized. */ + if(pt->namelen>255) + pt->namelen=255; + + write_header(out, ctb, calc_plaintext( pt ) ); + iobuf_put(out, pt->mode ); + iobuf_put(out, pt->namelen ); + for(i=0; i < pt->namelen; i++ ) + iobuf_put(out, pt->name[i] ); + if( write_32(out, pt->timestamp ) ) + rc = G10ERR_WRITE_FILE; + + n = 0; + while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { + if( iobuf_write(out, buf, nbytes) == -1 ) { + rc = G10ERR_WRITE_FILE; + break; + } + n += nbytes; + } + wipememory(buf,1000); /* burn the buffer */ + if( !pt->len ) + iobuf_set_block_mode(out, 0 ); /* write end marker */ + else if( n != pt->len ) + log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", + (ulong)n, (ulong)pt->len ); + + return rc; +} + + + +static int +do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) +{ + int rc = 0; + u32 n; + + n = ed->len ? (ed->len + ed->extralen) : 0; + write_header(out, ctb, n ); + + /* This is all. The caller has to write the real data */ + + return rc; +} + +static int +do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) +{ + int rc = 0; + u32 n; + + assert( ed->mdc_method ); + + /* Take version number and the following MDC packet in account. */ + n = ed->len ? (ed->len + ed->extralen + 1 + 22) : 0; + write_header(out, ctb, n ); + iobuf_put(out, 1 ); /* version */ + + /* This is all. The caller has to write the real data */ + + return rc; +} + + +static int +do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) +{ + int rc = 0; + + /* We must use the old convention and don't use blockmode for tyhe + sake of PGP 2 compatibility. However if the new_ctb flag was + set, CTB is already formatted as new style and write_header2 + does create a partial length encoding using new the new + style. */ + write_header2(out, ctb, 0, 0, 0 ); + iobuf_put(out, cd->algorithm ); + + /* This is all. The caller has to write the real data */ + + return rc; +} + + +/**************** + * Delete all subpackets of type REQTYPE and return a bool whether a packet + * was deleted. + */ +int +delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype ) +{ + int buflen; + sigsubpkttype_t type; + byte *buffer, *bufstart; + size_t n; + size_t unused = 0; + int okay = 0; + + if( !area ) + return 0; + buflen = area->len; + buffer = area->data; + for(;;) { + if( !buflen ) { + okay = 1; + break; + } + bufstart = buffer; + n = *buffer++; buflen--; + if( n == 255 ) { + if( buflen < 4 ) + break; + n = (buffer[0] << 24) | (buffer[1] << 16) + | (buffer[2] << 8) | buffer[3]; + buffer += 4; + buflen -= 4; + } + else if( n >= 192 ) { + if( buflen < 2 ) + break; + n = (( n - 192 ) << 8) + *buffer + 192; + buffer++; + buflen--; + } + if( buflen < n ) + break; + + type = *buffer & 0x7f; + if( type == reqtype ) { + buffer++; + buflen--; + n--; + if( n > buflen ) + break; + buffer += n; /* point to next subpkt */ + buflen -= n; + memmove (bufstart, buffer, buflen); /* shift */ + unused += buffer - bufstart; + buffer = bufstart; + } + else { + buffer += n; buflen -=n; + } + } + + if (!okay) + log_error ("delete_subpkt: buffer shorter than subpacket\n"); + assert (unused <= area->len); + area->len -= unused; + return !!unused; +} + + +/**************** + * Create or update a signature subpacket for SIG of TYPE. This + * functions knows where to put the data (hashed or unhashed). The + * function may move data from the unhashed part to the hashed one. + * Note: All pointers into sig->[un]hashed (e.g. returned by + * parse_sig_subpkt) are not valid after a call to this function. The + * data to put into the subpaket should be in a buffer with a length + * of buflen. + */ +void +build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, + const byte *buffer, size_t buflen ) +{ + byte *p; + int critical, hashed; + subpktarea_t *oldarea, *newarea; + size_t nlen, n, n0; + + critical = (type & SIGSUBPKT_FLAG_CRITICAL); + type &= ~SIGSUBPKT_FLAG_CRITICAL; + + /* Sanity check buffer sizes */ + if(parse_one_sig_subpkt(buffer,buflen,type)<0) + BUG(); + + switch(type) + { + case SIGSUBPKT_NOTATION: + case SIGSUBPKT_POLICY: + case SIGSUBPKT_REV_KEY: + /* we do allow multiple subpackets */ + break; + + default: + /* we don't allow multiple subpackets */ + delete_sig_subpkt(sig->hashed,type); + delete_sig_subpkt(sig->unhashed,type); + break; + } + + /* Any special magic that needs to be done for this type so the + packet doesn't need to be reparsed? */ + switch(type) + { + case SIGSUBPKT_NOTATION: + sig->flags.notation=1; + break; + + case SIGSUBPKT_POLICY: + sig->flags.policy_url=1; + break; + + case SIGSUBPKT_EXPORTABLE: + if(buffer[0]) + sig->flags.exportable=1; + else + sig->flags.exportable=0; + break; + + case SIGSUBPKT_REVOCABLE: + if(buffer[0]) + sig->flags.revocable=1; + else + sig->flags.revocable=0; + break; + + case SIGSUBPKT_TRUST: + sig->trust_depth=buffer[0]; + sig->trust_value=buffer[1]; + break; + + case SIGSUBPKT_REGEXP: + sig->trust_regexp=buffer; + break; + + /* This should never happen since we don't currently allow + creating such a subpacket, but just in case... */ + case SIGSUBPKT_SIG_EXPIRE: + if(buffer_to_u32(buffer)+sig->timestamp<=make_timestamp()) + sig->flags.expired=1; + else + sig->flags.expired=0; + break; + + default: + break; + } + + if( (buflen+1) >= 8384 ) + nlen = 5; /* write 5 byte length header */ + else if( (buflen+1) >= 192 ) + nlen = 2; /* write 2 byte length header */ + else + nlen = 1; /* just a 1 byte length header */ + + switch( type ) { + /* The issuer being unhashed is a historical oddity. It + should work equally as well hashed. Of course, if even an + unhashed issuer is tampered with, it makes it awfully hard + to verify the sig... */ + case SIGSUBPKT_ISSUER: + hashed = 0; + break; + default: + hashed = 1; + break; + } + + if( critical ) + type |= SIGSUBPKT_FLAG_CRITICAL; + + oldarea = hashed? sig->hashed : sig->unhashed; + + /* Calculate new size of the area and allocate */ + n0 = oldarea? oldarea->len : 0; + n = n0 + nlen + 1 + buflen; /* length, type, buffer */ + if (oldarea && n <= oldarea->size) { /* fits into the unused space */ + newarea = oldarea; + /*log_debug ("updating area for type %d\n", type );*/ + } + else if (oldarea) { + newarea = m_realloc (oldarea, sizeof (*newarea) + n - 1); + newarea->size = n; + /*log_debug ("reallocating area for type %d\n", type );*/ + } + else { + newarea = m_alloc (sizeof (*newarea) + n - 1); + newarea->size = n; + /*log_debug ("allocating area for type %d\n", type );*/ + } + newarea->len = n; + + p = newarea->data + n0; + if (nlen == 5) { + *p++ = 255; + *p++ = (buflen+1) >> 24; + *p++ = (buflen+1) >> 16; + *p++ = (buflen+1) >> 8; + *p++ = (buflen+1); + *p++ = type; + memcpy (p, buffer, buflen); + } + else if (nlen == 2) { + *p++ = (buflen+1-192) / 256 + 192; + *p++ = (buflen+1-192) % 256; + *p++ = type; + memcpy (p, buffer, buflen); + } + else { + *p++ = buflen+1; + *p++ = type; + memcpy (p, buffer, buflen); + } + + if (hashed) + sig->hashed = newarea; + else + sig->unhashed = newarea; +} + +/**************** + * Put all the required stuff from SIG into subpackets of sig. + * Hmmm, should we delete those subpackets which are in a wrong area? + */ +void +build_sig_subpkt_from_sig( PKT_signature *sig ) +{ + u32 u; + byte buf[8]; + + u = sig->keyid[0]; + buf[0] = (u >> 24) & 0xff; + buf[1] = (u >> 16) & 0xff; + buf[2] = (u >> 8) & 0xff; + buf[3] = u & 0xff; + u = sig->keyid[1]; + buf[4] = (u >> 24) & 0xff; + buf[5] = (u >> 16) & 0xff; + buf[6] = (u >> 8) & 0xff; + buf[7] = u & 0xff; + build_sig_subpkt( sig, SIGSUBPKT_ISSUER, buf, 8 ); + + u = sig->timestamp; + buf[0] = (u >> 24) & 0xff; + buf[1] = (u >> 16) & 0xff; + buf[2] = (u >> 8) & 0xff; + buf[3] = u & 0xff; + build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 ); + + if(sig->expiredate) + { + if(sig->expiredate>sig->timestamp) + u=sig->expiredate-sig->timestamp; + else + u=0; + + buf[0] = (u >> 24) & 0xff; + buf[1] = (u >> 16) & 0xff; + buf[2] = (u >> 8) & 0xff; + buf[3] = u & 0xff; + + /* Mark this CRITICAL, so if any implementation doesn't + understand sigs that can expire, it'll just disregard this + sig altogether. */ + + build_sig_subpkt( sig, SIGSUBPKT_SIG_EXPIRE | SIGSUBPKT_FLAG_CRITICAL, + buf, 4 ); + } +} + +void +build_attribute_subpkt(PKT_user_id *uid,byte type, + const void *buf,u32 buflen, + const void *header,u32 headerlen) +{ + byte *attrib; + int idx; + + if(1+headerlen+buflen>8383) + idx=5; + else if(1+headerlen+buflen>191) + idx=2; + else + idx=1; + + /* realloc uid->attrib_data to the right size */ + + uid->attrib_data=m_realloc(uid->attrib_data, + uid->attrib_len+idx+1+headerlen+buflen); + + attrib=&uid->attrib_data[uid->attrib_len]; + + if(idx==5) + { + attrib[0]=255; + attrib[1]=(1+headerlen+buflen) >> 24; + attrib[2]=(1+headerlen+buflen) >> 16; + attrib[3]=(1+headerlen+buflen) >> 8; + attrib[4]=1+headerlen+buflen; + } + else if(idx==2) + { + attrib[0]=(1+headerlen+buflen-192) / 256 + 192; + attrib[1]=(1+headerlen+buflen-192) % 256; + } + else + attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */ + + attrib[idx++]=type; + + /* Tack on our data at the end */ + + if(headerlen>0) + memcpy(&attrib[idx],header,headerlen); + memcpy(&attrib[idx+headerlen],buf,buflen); + uid->attrib_len+=idx+headerlen+buflen; +} + +static int +do_signature( IOBUF out, int ctb, PKT_signature *sig ) +{ + int rc = 0; + int n, i; + IOBUF a = iobuf_temp(); + + if( !sig->version ) + iobuf_put( a, 3 ); + else + iobuf_put( a, sig->version ); + if( sig->version < 4 ) + iobuf_put(a, 5 ); /* constant */ + iobuf_put(a, sig->sig_class ); + if( sig->version < 4 ) { + write_32(a, sig->timestamp ); + write_32(a, sig->keyid[0] ); + write_32(a, sig->keyid[1] ); + } + iobuf_put(a, sig->pubkey_algo ); + iobuf_put(a, sig->digest_algo ); + if( sig->version >= 4 ) { + size_t nn; + /* timestamp and keyid must have been packed into the + * subpackets prior to the call of this function, because + * these subpackets are hashed */ + nn = sig->hashed? sig->hashed->len : 0; + write_16(a, nn); + if( nn ) + iobuf_write( a, sig->hashed->data, nn ); + nn = sig->unhashed? sig->unhashed->len : 0; + write_16(a, nn); + if( nn ) + iobuf_write( a, sig->unhashed->data, nn ); + } + iobuf_put(a, sig->digest_start[0] ); + iobuf_put(a, sig->digest_start[1] ); + n = pubkey_get_nsig( sig->pubkey_algo ); + if( !n ) + write_fake_data( a, sig->data[0] ); + for(i=0; i < n; i++ ) + mpi_write(a, sig->data[i] ); + + if( is_RSA(sig->pubkey_algo) && sig->version < 4 ) + write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); + else + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + +static int +do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) +{ + int rc = 0; + IOBUF a = iobuf_temp(); + + write_version( a, ctb ); + iobuf_put(a, ops->sig_class ); + iobuf_put(a, ops->digest_algo ); + iobuf_put(a, ops->pubkey_algo ); + write_32(a, ops->keyid[0] ); + write_32(a, ops->keyid[1] ); + iobuf_put(a, ops->last ); + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + iobuf_close(a); + return rc; +} + + +static int +write_16(IOBUF out, u16 a) +{ + iobuf_put(out, a>>8); + if( iobuf_put(out,a) ) + return -1; + return 0; +} + +static int +write_32(IOBUF out, u32 a) +{ + iobuf_put(out, a>> 24); + iobuf_put(out, a>> 16); + iobuf_put(out, a>> 8); + if( iobuf_put(out, a) ) + return -1; + return 0; +} + + +/**************** + * calculate the length of a header + */ +static int +calc_header_length( u32 len, int new_ctb ) +{ + if( !len ) + return 1; /* only the ctb */ + + if( new_ctb ) { + if( len < 192 ) + return 2; + if( len < 8384 ) + return 3; + else + return 6; + } + if( len < 256 ) + return 2; + if( len < 65536 ) + return 3; + + return 5; +} + +/**************** + * Write the CTB and the packet length + */ +static int +write_header( IOBUF out, int ctb, u32 len ) +{ + return write_header2( out, ctb, len, 0, 1 ); +} + + +static int +write_sign_packet_header( IOBUF out, int ctb, u32 len ) +{ + /* work around a bug in the pgp read function for signature packets, + * which are not correctly coded and silently assume at some + * point 2 byte length headers.*/ + iobuf_put(out, 0x89 ); + iobuf_put(out, len >> 8 ); + return iobuf_put(out, len ) == -1 ? -1:0; +} + +/**************** + * if HDRLEN is > 0, try to build a header of this length. + * we need this, so that we can hash packets without reading them again. + */ +static int +write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ) +{ + if( ctb & 0x40 ) + return write_new_header( out, ctb, len, hdrlen ); + + if( hdrlen ) { + if( !len ) + ctb |= 3; + else if( hdrlen == 2 && len < 256 ) + ; + else if( hdrlen == 3 && len < 65536 ) + ctb |= 1; + else + ctb |= 2; + } + else { + if( !len ) + ctb |= 3; + else if( len < 256 ) + ; + else if( len < 65536 ) + ctb |= 1; + else + ctb |= 2; + } + if( iobuf_put(out, ctb ) ) + return -1; + if( !len ) { + if( blkmode ) + iobuf_set_block_mode(out, 8196 ); + } + else { + if( ctb & 2 ) { + iobuf_put(out, len >> 24 ); + iobuf_put(out, len >> 16 ); + } + if( ctb & 3 ) + iobuf_put(out, len >> 8 ); + if( iobuf_put(out, len ) ) + return -1; + } + return 0; +} + + +static int +write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) +{ + if( hdrlen ) + log_bug("can't cope with hdrlen yet\n"); + + if( iobuf_put(out, ctb ) ) + return -1; + if( !len ) { + iobuf_set_partial_block_mode(out, 512 ); + } + else { + if( len < 192 ) { + if( iobuf_put(out, len ) ) + return -1; + } + else if( len < 8384 ) { + len -= 192; + if( iobuf_put( out, (len / 256) + 192) ) + return -1; + if( iobuf_put( out, (len % 256) ) ) + return -1; + } + else { + if( iobuf_put( out, 0xff ) ) + return -1; + if( iobuf_put( out, (len >> 24)&0xff ) ) + return -1; + if( iobuf_put( out, (len >> 16)&0xff ) ) + return -1; + if( iobuf_put( out, (len >> 8)&0xff ) ) + return -1; + if( iobuf_put( out, len & 0xff ) ) + return -1; + } + } + return 0; +} + +static int +write_version( IOBUF out, int ctb ) +{ + if( iobuf_put( out, 3 ) ) + return -1; + return 0; +} diff --git a/g10/cipher.c b/g10/cipher.c new file mode 100644 index 000000000..ab7c9b676 --- /dev/null +++ b/g10/cipher.c @@ -0,0 +1,152 @@ +/* cipher.c - En-/De-ciphering filter + * 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 <errno.h> +#include <assert.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 a ) +{ + PACKET pkt; + PKT_encrypted ed; + byte temp[18]; + unsigned blocksize; + unsigned nprefix; + + blocksize = cipher_get_blocksize( 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; + cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 ); + if ( DBG_HASHING ) + 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; + randomize_buffer( temp, nprefix, 1 ); + temp[nprefix] = temp[nprefix-2]; + temp[nprefix+1] = temp[nprefix-1]; + print_cipher_algo_note( cfx->dek->algo ); + cfx->cipher_hd = cipher_open( cfx->dek->algo, + cfx->dek->use_mdc? CIPHER_MODE_CFB + : CIPHER_MODE_AUTO_CFB, 1 ); +/* log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/ + cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); + cipher_setiv( cfx->cipher_hd, NULL, 0 ); +/* log_hexdump( "prefix", temp, nprefix+2 ); */ + if( cfx->mdc_hash ) /* hash the "IV" */ + md_write( cfx->mdc_hash, temp, nprefix+2 ); + cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2); + 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 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 ) + md_write( cfx->mdc_hash, buf, size ); + cipher_encrypt( cfx->cipher_hd, buf, buf, size); + if( iobuf_write( a, buf, size ) ) + rc = G10ERR_WRITE_FILE; + } + else if( control == IOBUFCTRL_FREE ) { + if( cfx->mdc_hash ) { + byte *hash; + int hashlen = md_digest_length( 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; + md_putc( cfx->mdc_hash, temp[0] ); + md_putc( cfx->mdc_hash, temp[1] ); + + md_final( cfx->mdc_hash ); + hash = md_read( cfx->mdc_hash, 0 ); + memcpy(temp+2, hash, 20); + cipher_encrypt( cfx->cipher_hd, temp, temp, 22 ); + md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL; + if( iobuf_write( a, temp, 22 ) ) + log_error("writing MDC packet failed\n" ); + } + cipher_close(cfx->cipher_hd); + } + else if( control == IOBUFCTRL_DESC ) { + *(char**)buf = "cipher_filter"; + } + return rc; +} diff --git a/g10/compress.c b/g10/compress.c new file mode 100644 index 000000000..8d9327cc3 --- /dev/null +++ b/g10/compress.c @@ -0,0 +1,324 @@ +/* compress.c - compress filter + * 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 <unistd.h> +#include <assert.h> +#include <errno.h> +#include <zlib.h> +#ifdef __riscos__ +# include "zlib-riscos.h" +#endif + +#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 = m_alloc( zfx->outbufsize ); +} + +static int +do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) +{ + 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 ); + + if( iobuf_write( a, zfx->outbuf, n ) ) { + log_debug("deflate: iobuf_write failed\n"); + return G10ERR_WRITE_FILE; + } + } 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 = m_alloc( zfx->inbufsize ); + zs->avail_in = 0; +} + +static int +do_uncompress( compress_filter_context_t *zfx, z_stream *zs, + IOBUF 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 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 = m_alloc_clear( 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 = m_alloc_clear( 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); + m_free(zs); + zfx->opaque = NULL; + m_free(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); + m_free(zs); + zfx->opaque = NULL; + m_free(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) +{ + m_free (ctx); +} + +/**************** + * Handle a compressed packet + */ +int +handle_compressed( void *procctx, PKT_compressed *cd, + int (*callback)(IOBUF, void *), void *passthru ) +{ + compress_filter_context_t *cfx; + int rc; + + if( cd->algorithm < 1 || cd->algorithm > 2 ) + return G10ERR_COMPR_ALGO; + cfx = m_alloc_clear (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; +} + diff --git a/g10/decrypt.c b/g10/decrypt.c new file mode 100644 index 000000000..df778d1ad --- /dev/null +++ b/g10/decrypt.c @@ -0,0 +1,141 @@ +/* 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 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 ) { + log_error(_("can't open `%s'\n"), print_fname_stdin(filename)); + return G10ERR_OPEN_FILE; + } + + 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 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), + g10_errstr(rc)); + p = get_last_passphrase(); + set_next_passphrase(p); + m_free (p); + + next_file: + /* Note that we emit file_done even after an error. */ + write_status( STATUS_FILE_DONE ); + m_free(output); + files++; + } + set_next_passphrase(NULL); +} + diff --git a/g10/encode.c b/g10/encode.c new file mode 100644 index 000000000..66ce57c35 --- /dev/null +++ b/g10/encode.c @@ -0,0 +1,811 @@ +/* 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 "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" + +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 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 = m_alloc_clear( sizeof *c ); + c->keylen = dek->keylen; + c->algo = dek->algo; + make_session_key( c ); + /*log_hexdump( "thekey", c->key, c->keylen );*/ + + buf[0] = c->algo; + memcpy( buf + 1, c->key, c->keylen ); + + hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); + cipher_setkey( hd, dek->key, dek->keylen ); + cipher_setiv( hd, NULL, 0 ); + cipher_encrypt( hd, buf, buf, c->keylen + 1 ); + 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) +{ + /* --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. */ + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_AES,NULL)==CIPHER_ALGO_AES) + return 1; + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_AES192,NULL)==CIPHER_ALGO_AES192) + return 1; + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_AES256,NULL)==CIPHER_ALGO_AES256) + return 1; + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_TWOFISH,NULL)==CIPHER_ALGO_TWOFISH) + return 1; + + /* Last try. Use MDC for the modern ciphers. */ + + if(cipher_get_blocksize(algo)!=8) + return 1; + + return 0; /* No MDC */ +} + +static int +encode_simple( const char *filename, int mode, int compat ) +{ + IOBUF 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)) ) { + log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]", + strerror(errno) ); + return G10ERR_OPEN_FILE; + } + + 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 = m_alloc_clear( 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 = G10ERR_PASSPHRASE; + m_free(cfx.dek); + m_free(s2k); + iobuf_close(inp); + log_error(_("error creating passphrase: %s\n"), g10_errstr(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 = cipher_get_keylen( default_cipher_algo() ) / 8; + encode_sesskey( cfx.dek, &dek, enckey ); + m_free( 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); + m_free(cfx.dek); + m_free(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 = m_alloc_clear( 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", g10_errstr(rc) ); + m_free(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, + iobuf_get_real_fname( inp ) ); + pt = m_alloc( sizeof *pt + strlen(s) - 1 ); + pt->namelen = strlen(s); + memcpy(pt->name, s, pt->namelen ); + m_free(s); + } + else { /* no filename */ + pt = m_alloc( 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", g10_errstr(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 (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; + log_error("copying input to output failed: %s\n", g10_errstr(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); + m_free(cfx.dek); + m_free(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 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)) ) { + log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]", + strerror(errno) ); + rc = G10ERR_OPEN_FILE; + 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 = m_alloc_secure_clear (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"), + cipher_algo_to_string(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_hexdump("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 = m_alloc( sizeof *pt + strlen(s) - 1 ); + pt->namelen = strlen(s); + memcpy(pt->name, s, pt->namelen ); + m_free(s); + } + else { /* no filename */ + pt = m_alloc( 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", g10_errstr(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 (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; + log_error("copying input to output failed: %s\n", + g10_errstr(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); + m_free(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 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 = m_alloc_secure_clear( 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"), + cipher_algo_to_string(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_hexdump("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 out ) +{ + PACKET pkt; + PKT_public_key *pk; + PKT_pubkey_enc *enc; + int rc; + + for( ; pk_list; pk_list = pk_list->next ) { + MPI frame; + + pk = pk_list->pk; + + print_pubkey_algo_note( pk->pubkey_algo ); + enc = m_alloc_clear( 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 = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey ); + mpi_free( frame ); + if( rc ) + log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) ); + else { + if( opt.verbose ) { + char *ustr = get_user_id_string_printable (enc->keyid); + log_info(_("%s/%s encrypted for: \"%s\"\n"), + pubkey_algo_to_string(enc->pubkey_algo), + cipher_algo_to_string(dek->algo), ustr ); + m_free(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", g10_errstr(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), g10_errstr(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), g10_errstr(rc) ); + write_status( STATUS_FILE_DONE ); + files++; + } + } +} diff --git a/g10/exec.c b/g10/exec.c new file mode 100644 index 000000000..0278438f6 --- /dev/null +++ b/g10/exec.c @@ -0,0 +1,619 @@ +/* exec.c - generic call-a-program code + * 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 <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 G10ERR_GENERAL; +} + +int exec_read(struct exec_info *info) { return G10ERR_GENERAL; } +int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; } +int set_exec_path(const char *path,int method) { return G10ERR_GENERAL; } + +#else /* ! NO_EXEC */ + +#ifndef HAVE_MKDTEMP +char *mkdtemp(char *template); +#endif + +#if defined (__MINGW32__) +/* 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=m_strdup(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); + m_free(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=m_alloc(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 G10ERR_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 (__MINGW32__) + tmp=m_alloc(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=m_alloc(strlen(tmp)+strlen(DIRSEP_S)+10+1); + + sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); + +#if defined (__MINGW32__) + m_free(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=m_alloc(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=m_alloc(strlen(info->tempdir)+ + strlen(DIRSEP_S)+strlen(nameout)+1); + sprintf(info->tempfile_out,"%s" DIRSEP_S "%s",info->tempdir,nameout); + } + } + + return info->madedir?0:G10ERR_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=m_alloc(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=m_realloc(info->command,size); + } + + strcat(info->command,append); + len+=strlen(append); + } + } + else + { + if(len==size-1) /* leave room for the \0 */ + { + size+=100; + info->command=m_realloc(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: + + m_free(info->command); + info->command=NULL; + + return G10ERR_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=G10ERR_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=m_alloc_clear(sizeof(struct exec_info)); + + if(name) + (*info)->name=m_strdup(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) + { + close(to[1]); + ret=G10ERR_WRITE_FILE; + goto fail; + } + + close(from[1]); + + (*info)->fromchild=iobuf_fdopen(from[0],"r"); + if((*info)->fromchild==NULL) + { + close(from[0]); + ret=G10ERR_READ_FILE; + 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) + { + log_error(_("can't create `%s': %s\n"), + (*info)->tempfile_in,strerror(errno)); + ret=G10ERR_WRITE_FILE; + goto fail; + } + + ret=0; + + fail: + return ret; +} + +int exec_read(struct exec_info *info) +{ + int ret=G10ERR_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 (__MINGW32__) + 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) + { + log_error(_("unable to read external program response: %s\n"), + strerror(errno)); + ret=G10ERR_READ_FILE; + 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)); + } + + m_free(info->command); + m_free(info->name); + m_free(info->tempdir); + m_free(info->tempfile_in); + m_free(info->tempfile_out); + m_free(info); + + return ret; +} +#endif /* ! NO_EXEC */ diff --git a/g10/exec.h b/g10/exec.h new file mode 100644 index 000000000..25369dc34 --- /dev/null +++ b/g10/exec.h @@ -0,0 +1,43 @@ +/* exec.h + * 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 + */ + +#ifndef _EXEC_H_ +#define _EXEC_H_ + +#include <unistd.h> +#include <stdio.h> +#include "iobuf.h" + +struct exec_info +{ + int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files; + pid_t child; + FILE *tochild; + IOBUF 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_ */ diff --git a/g10/export.c b/g10/export.c new file mode 100644 index 000000000..5783f6ac1 --- /dev/null +++ b/g10/export.c @@ -0,0 +1,396 @@ +/* export.c + * 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 "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 out, STRLIST users, int secret, + KBNODE *keyblock_out, unsigned int options, + int *any ); + +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}, + {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 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 ) +{ + return do_export( users, 1, 0 ); +} + +int +export_secsubkeys( STRLIST users ) +{ + return do_export( users, 2, 0 ); +} + +static int +do_export( STRLIST users, int secret, unsigned int options ) +{ + IOBUF 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( 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 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; + + *any = 0; + init_packet( &pkt ); + kdbhd = keydb_new (secret); + + if (!users) { + ndesc = 1; + desc = m_alloc_clear ( ndesc * sizeof *desc); + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + } + else { + for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) + ; + desc = m_alloc ( 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, g10_errstr (G10ERR_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"), g10_errstr(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; + 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; + } + + rc = build_packet( out, node->pkt ); + } + + if( rc ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + ++*any; + if(keyblock_out) + { + *keyblock_out=keyblock; + break; + } + } + if( rc == -1 ) + rc = 0; + + leave: + m_free(desc); + keydb_release (kdbhd); + if(rc || keyblock_out==NULL) + release_kbnode( keyblock ); + if( !*any ) + log_info(_("WARNING: nothing exported\n")); + return rc; +} diff --git a/g10/filter.h b/g10/filter.h new file mode 100644 index 000000000..9f235fd6b --- /dev/null +++ b/g10/filter.h @@ -0,0 +1,154 @@ +/* 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" + +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 a, byte *buf, size_t *ret_len); +void free_md_filter_context( md_filter_context_t *mfx ); + +/*-- armor.c --*/ +int use_armor_filter( IOBUF a ); +int armor_filter( void *opaque, int control, + IOBUF 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 chain, byte *buf, size_t *ret_len); + +/*-- cipher.c --*/ +int cipher_filter( void *opaque, int control, + IOBUF chain, byte *buf, size_t *ret_len); + +/*-- textfilter.c --*/ +int text_filter( void *opaque, int control, + IOBUF chain, byte *buf, size_t *ret_len); +int copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, + int escape_dash, int escape_from, int pgp2mode ); + +/*-- progress.c --*/ +int progress_filter (void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len); +void handle_progress (progress_filter_context_t *pfx, + IOBUF inp, const char *name); + +#endif /*G10_FILTER_H*/ diff --git a/g10/free-packet.c b/g10/free-packet.c new file mode 100644 index 000000000..ce3568ca5 --- /dev/null +++ b/g10/free-packet.c @@ -0,0 +1,542 @@ +/* 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 ) +{ + m_free(enc); +} + +void +free_pubkey_enc( PKT_pubkey_enc *enc ) +{ + int n, i; + n = pubkey_get_nenc( enc->pubkey_algo ); + if( !n ) + mpi_free(enc->data[0]); + for(i=0; i < n; i++ ) + mpi_free( enc->data[i] ); + m_free(enc); +} + +void +free_seckey_enc( PKT_signature *sig ) +{ + int n, i; + + n = pubkey_get_nsig( sig->pubkey_algo ); + if( !n ) + mpi_free(sig->data[0]); + for(i=0; i < n; i++ ) + mpi_free( sig->data[i] ); + + m_free(sig->revkey); + m_free(sig->hashed); + m_free(sig->unhashed); + m_free(sig); +} + + +void +release_public_key_parts( PKT_public_key *pk ) +{ + int n, i; + n = pubkey_get_npkey( pk->pubkey_algo ); + if( !n ) + mpi_free(pk->pkey[0]); + for(i=0; i < n; i++ ) { + mpi_free( pk->pkey[i] ); + pk->pkey[i] = NULL; + } + if (pk->prefs) { + m_free (pk->prefs); + pk->prefs = NULL; + } + if (pk->user_id) { + free_user_id (pk->user_id); + pk->user_id = NULL; + } + if (pk->revkey) { + m_free(pk->revkey); + pk->revkey=NULL; + pk->numrevkeys=0; + } +} + + +void +free_public_key( PKT_public_key *pk ) +{ + release_public_key_parts( pk ); + m_free(pk); +} + + +static subpktarea_t * +cp_subpktarea (subpktarea_t *s ) +{ + subpktarea_t *d; + + if( !s ) + return NULL; + d = m_alloc (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 = m_alloc ( 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 = m_alloc(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 = m_alloc(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 = m_alloc(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_free(sk->skey[0]); + for(i=0; i < n; i++ ) { + mpi_free( sk->skey[i] ); + sk->skey[i] = NULL; + } +} + +void +free_secret_key( PKT_secret_key *sk ) +{ + release_secret_key_parts( sk ); + m_free(sk); +} + +PKT_secret_key * +copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ) +{ + int n, i; + + if( !d ) + d = m_alloc(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 ) +{ + m_free(rem); +} + +void +free_attributes(PKT_user_id *uid) +{ + m_free(uid->attribs); + m_free(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); + m_free (uid->prefs); + m_free (uid->namehash); + m_free (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 ) + ; + } + m_free(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; + } + } + } + m_free(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; + } + } + } + m_free(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: + m_free( 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; +} diff --git a/g10/g10.c b/g10/g10.c new file mode 100644 index 000000000..8a7f09d13 --- /dev/null +++ b/g10/g10.c @@ -0,0 +1,3137 @@ +/* g10.c - The GnuPG utility (main for gpg) + * 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> +#include <assert.h> +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif +#ifdef HAVE_STAT +#include <sys/stat.h> /* for stat() */ +#endif + +#define INCLUDED_BY_MAIN_MODULE 1 +#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" +#include "g10defs.h" +#include "keyserver-internal.h" +#include "exec.h" + +enum cmd_and_opt_values { aNull = 0, + oArmor = 'a', + aDetachedSign = 'b', + aSym = 'c', + aDecrypt = 'd', + aEncr = 'e', + aEncrFiles, + oInteractive = 'i', + oKOption = 'k', + oDryRun = 'n', + oOutput = 'o', + oQuiet = 'q', + oRecipient = 'r', + oHiddenRecipient = 'R', + aSign = 's', + oTextmodeShort= 't', + oUser = 'u', + oVerbose = 'v', + oCompress = 'z', + oNotation = 'N', + oBatch = 500, + oSigNotation, + oCertNotation, + oShowNotation, + oNoShowNotation, + aDecryptFiles, + aClearsign, + aStore, + aKeygen, + aSignEncr, + aSignSym, + aSignKey, + aLSignKey, + aNRSignKey, + aNRLSignKey, + aListPackets, + aEditKey, + aDeleteKeys, + aDeleteSecretKeys, + aDeleteSecretAndPublicKeys, + aKMode, + aKModeC, + aImport, + aFastImport, + aVerify, + aVerifyFiles, + aListKeys, + aListSigs, + aListSecretKeys, + aSendKeys, + aRecvKeys, + aSearchKeys, + aExport, + aExportAll, + aExportSecret, + aExportSecretSub, + aCheckKeys, + aGenRevoke, + aDesigRevoke, + aPrimegen, + aPrintMD, + aPrintMDs, + aCheckTrustDB, + aUpdateTrustDB, + aFixTrustDB, + aListTrustDB, + aListTrustPath, + aExportOwnerTrust, + aListOwnerTrust, + aImportOwnerTrust, + aDeArmor, + aEnArmor, + aGenRandom, + aPipeMode, + aRebuildKeydbCaches, + aRefreshKeys, + + oTextmode, + oNoTextmode, + oExpert, + oNoExpert, + oAskSigExpire, + oNoAskSigExpire, + oAskCertExpire, + oNoAskCertExpire, + oFingerprint, + oWithFingerprint, + oAnswerYes, + oAnswerNo, + oDefCertCheckLevel, + oKeyring, + oPrimaryKeyring, + oSecretKeyring, + oShowKeyring, + oDefaultKey, + oDefRecipient, + oDefRecipientSelf, + oNoDefRecipient, + oOptions, + oDebug, + oDebugAll, + oStatusFD, +#ifdef __riscos__ + oStatusFile, +#endif /* __riscos__ */ + oAttributeFD, +#ifdef __riscos__ + oAttributeFile, +#endif /* __riscos__ */ + oSKComments, + oNoSKComments, + oEmitVersion, + oNoEmitVersion, + oCompletesNeeded, + oMarginalsNeeded, + oMaxCertDepth, + oLoadExtension, + oGnuPG, + oRFC1991, + oOpenPGP, + oPGP2, + oPGP6, + oPGP7, + oPGP8, + oCipherAlgo, + oDigestAlgo, + oCertDigestAlgo, + oCompressAlgo, + oPasswdFD, +#ifdef __riscos__ + oPasswdFile, +#endif /* __riscos__ */ + oCommandFD, +#ifdef __riscos__ + oCommandFile, +#endif /* __riscos__ */ + oQuickRandom, + oNoVerbose, + oTrustDBName, + oNoSecmemWarn, + oNoPermissionWarn, + oNoMDCWarn, + oNoArmor, + oNoDefKeyring, + oNoGreeting, + oNoTTY, + oNoOptions, + oNoBatch, + oHomedir, + oWithColons, + oWithKeyData, + oSkipVerify, + oCompressKeys, + oCompressSigs, + oAlwaysTrust, + oTrustModel, + oForceOwnertrust, + oEmuChecksumBug, + oRunAsShmCP, + oSetFilename, + oForYourEyesOnly, + oNoForYourEyesOnly, + oSetPolicyURL, + oSigPolicyURL, + oCertPolicyURL, + oShowPolicyURL, + oNoShowPolicyURL, + oUseEmbeddedFilename, + oComment, + oDefaultComment, + oThrowKeyid, + oNoThrowKeyid, + oShowPhotos, + oNoShowPhotos, + oPhotoViewer, + oForceV3Sigs, + oNoForceV3Sigs, + oForceV4Certs, + oNoForceV4Certs, + oForceMDC, + oNoForceMDC, + oDisableMDC, + oNoDisableMDC, + oS2KMode, + oS2KDigest, + oS2KCipher, + oSimpleSKChecksum, + oCharset, + oNotDashEscaped, + oEscapeFrom, + oNoEscapeFrom, + oLockOnce, + oLockMultiple, + oLockNever, + oKeyServer, + oKeyServerOptions, + oImportOptions, + oExportOptions, + oListOptions, + oVerifyOptions, + oTempDir, + oExecPath, + oEncryptTo, + oHiddenEncryptTo, + oNoEncryptTo, + oLoggerFD, +#ifdef __riscos__ + oLoggerFile, +#endif /* __riscos__ */ + oUtf8Strings, + oNoUtf8Strings, + oDisableCipherAlgo, + oDisablePubkeyAlgo, + oAllowNonSelfsignedUID, + oNoAllowNonSelfsignedUID, + oAllowFreeformUID, + oNoAllowFreeformUID, + oAllowSecretKeyImport, + oEnableSpecialFilenames, + oNoLiteral, + oSetFilesize, + oHonorHttpProxy, + oFastListMode, + oListOnly, + oIgnoreTimeConflict, + oIgnoreValidFrom, + oIgnoreCrcError, + oIgnoreMDCError, + oShowSessionKey, + oOverrideSessionKey, + oNoRandomSeedFile, + oAutoKeyRetrieve, + oNoAutoKeyRetrieve, + oUseAgent, + oNoUseAgent, + oGpgAgentInfo, + oMergeOnly, + oTryAllSecrets, + oTrustedKey, + oNoExpensiveTrustChecks, + oFixedListMode, + oNoSigCache, + oNoSigCreateCheck, + oAutoCheckTrustDB, + oNoAutoCheckTrustDB, + oPreservePermissions, + oDefaultPreferenceList, + oPersonalCipherPreferences, + oPersonalDigestPreferences, + oPersonalCompressPreferences, + oEmuMDEncodeBug, + oDisplay, + oTTYname, + oTTYtype, + oLCctype, + oLCmessages, + oGroup, + oStrict, + oNoStrict, + oMangleDosFilenames, + oNoMangleDosFilenames, + oEnableProgressFilter, +aTest }; + + +static ARGPARSE_OPTS opts[] = { + + { 300, NULL, 0, N_("@Commands:\n ") }, + + { aSign, "sign", 256, N_("|[file]|make a signature")}, + { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, + { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, + { aEncr, "encrypt", 256, N_("encrypt data")}, + { aEncrFiles, "encrypt-files", 256, N_("|[files]|encrypt files")}, + { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, + { aStore, "store", 256, N_("store only")}, + { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, + { aDecryptFiles, "decrypt-files", 256, N_("|[files]|decrypt files")}, + { aVerify, "verify" , 256, N_("verify a signature")}, + { aVerifyFiles, "verify-files" , 256, "@" }, + { aListKeys, "list-keys", 256, N_("list keys")}, + { aListKeys, "list-public-keys", 256, "@" }, + { aListSigs, "list-sigs", 256, N_("list keys and signatures")}, + { aCheckKeys, "check-sigs",256, N_("check key signatures")}, + { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, + { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, + { aKeygen, "gen-key", 256, N_("generate a new key pair")}, + { aDeleteKeys,"delete-keys",256,N_("remove keys from the public keyring")}, + { aDeleteSecretKeys, "delete-secret-keys",256, + N_("remove keys from the secret keyring")}, + { aSignKey, "sign-key" ,256, N_("sign a key")}, + { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, + { aNRSignKey, "nrsign-key" ,256, N_("sign a key non-revocably")}, + { aNRLSignKey, "nrlsign-key" ,256, N_("sign a key locally and non-revocably")}, + { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, + { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, + { aDesigRevoke, "desig-revoke",256, "@" }, + { aExport, "export" , 256, N_("export keys") }, + { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, + { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, + { aSearchKeys, "search-keys" , 256, + N_("search for keys on a key server") }, + { aRefreshKeys, "refresh-keys", 256, + N_("update all keys from a keyserver")}, + { aExportAll, "export-all" , 256, "@" }, + { aExportSecret, "export-secret-keys" , 256, "@" }, + { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, + { aImport, "import", 256 , N_("import/merge keys")}, + { aFastImport, "fast-import", 256 , "@"}, + { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, + { aExportOwnerTrust, + "export-ownertrust", 256, N_("export the ownertrust values")}, + { aImportOwnerTrust, + "import-ownertrust", 256, N_("import ownertrust values")}, + { aUpdateTrustDB, + "update-trustdb",0 , N_("update the trust database")}, + { aCheckTrustDB, + "check-trustdb",0 , N_("unattended trust database update")}, + { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, + { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") }, + { aDeArmor, "dearmour", 256, "@" }, + { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") }, + { aEnArmor, "enarmour", 256, "@" }, + { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, + { aPrimegen, "gen-prime" , 256, "@" }, + { aGenRandom, "gen-random" , 256, "@" }, + + { 301, NULL, 0, N_("@\nOptions:\n ") }, + + { oArmor, "armor", 0, N_("create ascii armored output")}, + { oArmor, "armour", 0, "@" }, + { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, + { oHiddenRecipient, "hidden-recipient", 2, "@" }, + { oRecipient, "remote-user", 2, "@"}, /* old option name */ + { oDefRecipient, "default-recipient" ,2, + N_("|NAME|use NAME as default recipient")}, + { oDefRecipientSelf, "default-recipient-self" ,0, + N_("use the default key as default recipient")}, + { oNoDefRecipient, "no-default-recipient", 0, "@" }, + { oTempDir, "temp-directory", 2, "@" }, + { oExecPath, "exec-path", 2, "@" }, + { oEncryptTo, "encrypt-to", 2, "@" }, + { oHiddenEncryptTo, "hidden-encrypt-to", 2, "@" }, + { oNoEncryptTo, "no-encrypt-to", 0, "@" }, + { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, + { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, + { oTextmodeShort, NULL, 0, "@"}, + { oTextmode, "textmode", 0, N_("use canonical text mode")}, + { oNoTextmode, "no-textmode", 0, "@"}, + { oExpert, "expert", 0, "@"}, + { oNoExpert, "no-expert", 0, "@"}, + { oAskSigExpire, "ask-sig-expire", 0, "@"}, + { oNoAskSigExpire, "no-ask-sig-expire", 0, "@"}, + { oAskCertExpire, "ask-cert-expire", 0, "@"}, + { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, + { oOutput, "output", 2, N_("use as output file")}, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, + { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, + { oNoForceV3Sigs, "no-force-v3-sigs", 0, N_("do not force v3 signatures") }, + { oForceV4Certs, "force-v4-certs", 0, N_("force v4 key signatures") }, + { oNoForceV4Certs, "no-force-v4-certs", 0, N_("do not force v4 key signatures") }, + { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, + { oNoForceMDC, "no-force-mdc", 0, "@" }, + { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") }, + { oNoDisableMDC, "no-disable-mdc", 0, "@" }, + { oDryRun, "dry-run", 0, N_("do not make any changes") }, + { oInteractive, "interactive", 0, N_("prompt before overwriting") }, + { oUseAgent, "use-agent",0, N_("use the gpg-agent")}, + { oNoUseAgent, "no-use-agent",0, "@"}, + { oGpgAgentInfo, "gpg-agent-info",2, "@"}, + { oBatch, "batch", 0, N_("batch mode: never ask")}, + { oAnswerYes, "yes", 0, N_("assume yes on most questions")}, + { oAnswerNo, "no", 0, N_("assume no on most questions")}, + { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, + { oPrimaryKeyring, "primary-keyring",2, "@" }, + { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, + { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")}, + { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, + { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, + { oKeyServerOptions, "keyserver-options",2,"@"}, + { oImportOptions, "import-options",2,"@"}, + { oExportOptions, "export-options",2,"@"}, + { oListOptions, "list-options",2,"@"}, + { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, + { oOptions, "options" , 2, N_("read options from file")}, + + { oDebug, "debug" ,4|16, "@"}, + { oDebugAll, "debug-all" ,0, "@"}, + { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, +#ifdef __riscos__ + { oStatusFile, "status-file" ,2, N_("|[file]|write status info to file") }, +#endif /* __riscos__ */ + { oAttributeFD, "attribute-fd" ,1, "@" }, +#ifdef __riscos__ + { oAttributeFile, "attribute-file" ,2, "@" }, +#endif /* __riscos__ */ + { oNoSKComments, "no-comment", 0, "@"}, + { oNoSKComments, "no-sk-comments", 0, "@"}, + { oSKComments, "sk-comments", 0, "@"}, + { oCompletesNeeded, "completes-needed", 1, "@"}, + { oMarginalsNeeded, "marginals-needed", 1, "@"}, + { oMaxCertDepth, "max-cert-depth", 1, "@" }, + { oTrustedKey, "trusted-key", 2, N_("|KEYID|ultimately trust this key")}, + { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")}, + { oGnuPG, "gnupg", 0, "@"}, + { oGnuPG, "no-pgp2", 0, "@"}, + { oGnuPG, "no-pgp6", 0, "@"}, + { oGnuPG, "no-pgp7", 0, "@"}, + { oGnuPG, "no-pgp8", 0, "@"}, + { oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")}, + { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")}, + { oPGP2, "pgp2", 0, N_("set all packet, cipher and digest options to PGP 2.x behavior")}, + { oPGP6, "pgp6", 0, "@"}, + { oPGP7, "pgp7", 0, "@"}, + { oPGP8, "pgp8", 0, "@"}, + { oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")}, + { oS2KDigest, "s2k-digest-algo",2, + N_("|NAME|use message digest algorithm NAME for passphrases")}, + { oS2KCipher, "s2k-cipher-algo",2, + N_("|NAME|use cipher algorithm NAME for passphrases")}, + { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, + { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, + { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")}, + { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, + { oCompressAlgo,"compress-algo",2,N_("|NAME|use compression algorithm NAME")}, + { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")}, + { oNoThrowKeyid, "no-throw-keyid", 0, "@" }, + { oShowPhotos, "show-photos", 0, "@" }, + { oNoShowPhotos, "no-show-photos", 0, "@" }, + { oPhotoViewer, "photo-viewer", 2, "@" }, + { oNotation, "notation-data", 2, "@" }, + { oSigNotation, "sig-notation", 2, "@" }, + { oCertNotation, "cert-notation", 2, "@" }, + + { 302, NULL, 0, N_( + "@\n(See the man page for a complete listing of all commands and options)\n" + )}, + + { 303, NULL, 0, N_("@\nExamples:\n\n" + " -se -r Bob [file] sign and encrypt for user Bob\n" + " --clearsign [file] make a clear text signature\n" + " --detach-sign [file] make a detached signature\n" + " --list-keys [names] show keys\n" + " --fingerprint [names] show fingerprints\n" ) }, + + /* hidden options */ + { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */ + { oCompressAlgo, "compression-algo", 1, "@"}, /* alias */ + { aPrintMDs, "print-mds" , 256, "@"}, /* old */ + { aListTrustDB, "list-trustdb",0 , "@"}, + /* Not yet used */ + /* { aListTrustPath, "list-trust-path",0, "@"}, */ + { aPipeMode, "pipemode", 0, "@" }, + { oKOption, NULL, 0, "@"}, + { oPasswdFD, "passphrase-fd",1, "@" }, +#ifdef __riscos__ + { oPasswdFile, "passphrase-file",2, "@" }, +#endif /* __riscos__ */ + { oCommandFD, "command-fd",1, "@" }, +#ifdef __riscos__ + { oCommandFile, "command-file",2, "@" }, +#endif /* __riscos__ */ + { oQuickRandom, "quick-random", 0, "@"}, + { oNoVerbose, "no-verbose", 0, "@"}, + { oTrustDBName, "trustdb-name", 2, "@" }, + { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */ + { oNoPermissionWarn, "no-permission-warning", 0, "@" }, + { oNoMDCWarn, "no-mdc-warning", 0, "@" }, + { oNoArmor, "no-armor", 0, "@"}, + { oNoArmor, "no-armour", 0, "@"}, + { oNoDefKeyring, "no-default-keyring", 0, "@" }, + { oNoGreeting, "no-greeting", 0, "@" }, + { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */ + { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ + { oNoBatch, "no-batch", 0, "@" }, + { oWithColons, "with-colons", 0, "@"}, + { oWithKeyData,"with-key-data", 0, "@"}, + { aListKeys, "list-key", 0, "@" }, /* alias */ + { aListSigs, "list-sig", 0, "@" }, /* alias */ + { aCheckKeys, "check-sig",0, "@" }, /* alias */ + { oSkipVerify, "skip-verify",0, "@" }, + { oCompressKeys, "compress-keys",0, "@"}, + { oCompressSigs, "compress-sigs",0, "@"}, + { oDefCertCheckLevel, "default-cert-check-level", 1, "@"}, + { oAlwaysTrust, "always-trust", 0, "@"}, + { oTrustModel, "trust-model", 2, "@"}, + { oForceOwnertrust, "force-ownertrust", 2, "@"}, + { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"}, + { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" }, + { oSetFilename, "set-filename", 2, "@" }, + { oForYourEyesOnly, "for-your-eyes-only", 0, "@" }, + { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" }, + { oSetPolicyURL, "set-policy-url", 2, "@" }, + { oSigPolicyURL, "sig-policy-url", 2, "@" }, + { oCertPolicyURL, "cert-policy-url", 2, "@" }, + { oShowPolicyURL, "show-policy-url", 0, "@" }, + { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, + { oShowNotation, "show-notation", 0, "@" }, + { oNoShowNotation, "no-show-notation", 0, "@" }, + { oComment, "comment", 2, "@" }, + { oDefaultComment, "default-comment", 0, "@" }, + { oEmitVersion, "emit-version", 0, "@"}, + { oNoEmitVersion, "no-emit-version", 0, "@"}, + { oNoEmitVersion, "no-version", 0, "@"}, /* alias */ + { oNotDashEscaped, "not-dash-escaped", 0, "@" }, + { oEscapeFrom, "escape-from-lines", 0, "@" }, + { oNoEscapeFrom, "no-escape-from-lines", 0, "@" }, + { oLockOnce, "lock-once", 0, "@" }, + { oLockMultiple, "lock-multiple", 0, "@" }, + { oLockNever, "lock-never", 0, "@" }, + { oLoggerFD, "logger-fd",1, "@" }, +#ifdef __riscos__ + { oLoggerFile, "logger-file",2, "@" }, +#endif /* __riscos__ */ + { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" }, + { oUtf8Strings, "utf8-strings", 0, "@" }, + { oNoUtf8Strings, "no-utf8-strings", 0, "@" }, + { oWithFingerprint, "with-fingerprint", 0, "@" }, + { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, + { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, + { oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" }, + { oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", 0, "@" }, + { oAllowFreeformUID, "allow-freeform-uid", 0, "@" }, + { oNoAllowFreeformUID, "no-allow-freeform-uid", 0, "@" }, + { oNoLiteral, "no-literal", 0, "@" }, + { oSetFilesize, "set-filesize", 20, "@" }, + { oHonorHttpProxy,"honor-http-proxy", 0, "@" }, + { oFastListMode,"fast-list-mode", 0, "@" }, + { oFixedListMode,"fixed-list-mode", 0, "@" }, + { oListOnly, "list-only", 0, "@"}, + { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, + { oIgnoreValidFrom, "ignore-valid-from", 0, "@" }, + { oIgnoreCrcError, "ignore-crc-error", 0,"@" }, + { oIgnoreMDCError, "ignore-mdc-error", 0,"@" }, + { oShowSessionKey, "show-session-key", 0, "@" }, + { oOverrideSessionKey, "override-session-key", 2, "@" }, + { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, + { oAutoKeyRetrieve, "auto-key-retrieve", 0, "@" }, + { oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" }, + { oNoSigCache, "no-sig-cache", 0, "@" }, + { oNoSigCreateCheck, "no-sig-create-check", 0, "@" }, + { oAutoCheckTrustDB, "auto-check-trustdb", 0, "@"}, + { oNoAutoCheckTrustDB, "no-auto-check-trustdb", 0, "@"}, + { oMergeOnly, "merge-only", 0, "@" }, + { oAllowSecretKeyImport, "allow-secret-key-import", 0, "@" }, + { oTryAllSecrets, "try-all-secrets", 0, "@" }, + { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" }, + { oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" }, + { aDeleteSecretAndPublicKeys, "delete-secret-and-public-keys",256, "@" }, + { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"}, + { oPreservePermissions, "preserve-permissions", 0, "@"}, + { oDefaultPreferenceList, "default-preference-list", 2, "@"}, + { oPersonalCipherPreferences, "personal-cipher-preferences", 2, "@"}, + { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, + { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, + { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, + { oDisplay, "display", 2, "@" }, + { oTTYname, "ttyname", 2, "@" }, + { oTTYtype, "ttytype", 2, "@" }, + { oLCctype, "lc-ctype", 2, "@" }, + { oLCmessages, "lc-messages", 2, "@" }, + { oGroup, "group", 2, "@" }, + { oStrict, "strict", 0, "@" }, + { oNoStrict, "no-strict", 0, "@" }, + { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" }, + { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" }, + { oEnableProgressFilter, "enable-progress-filter", 0, "@" }, +{0} }; + + + +int g10_errors_seen = 0; + +static int utf8_strings = 0; +static int maybe_setuid = 1; + +static char *build_list( const char *text, char letter, + const char *(*mapf)(int), int (*chkf)(int) ); +static void set_cmd( enum cmd_and_opt_values *ret_cmd, + enum cmd_and_opt_values new_cmd ); +static void print_mds( const char *fname, int algo ); +static void add_notation_data( const char *string, int which ); +static void add_policy_url( const char *string, int which ); + +#ifdef __riscos__ +RISCOS_GLOBAL_STATICS("GnuPG Heap") +#endif /* __riscos__ */ + +const char * +strusage( int level ) +{ + static char *digests, *pubkeys, *ciphers, *zips; + const char *p; + switch( level ) { + case 11: p = "gpg (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: gpg [options] [files] (-h for help)"); + break; + case 41: p = + _("Syntax: gpg [options] [files]\n" + "sign, check, encrypt or decrypt\n" + "default operation depends on the input data\n"); + break; + + case 31: p = "\nHome: "; break; +#ifndef __riscos__ + case 32: p = opt.homedir; break; +#else /* __riscos__ */ + case 32: p = make_filename(opt.homedir, NULL); break; +#endif /* __riscos__ */ + case 33: p = _("\nSupported algorithms:\n"); break; + case 34: + if( !pubkeys ) + pubkeys = build_list(_("Pubkey: "), 0, pubkey_algo_to_string, + check_pubkey_algo ); + p = pubkeys; + break; + case 35: + if( !ciphers ) + ciphers = build_list(_("Cipher: "), 'S', cipher_algo_to_string, + check_cipher_algo ); + p = ciphers; + break; + case 36: + if( !digests ) + digests = build_list(_("Hash: "), 'H', digest_algo_to_string, + check_digest_algo ); + p = digests; + break; + case 37: + if( !zips ) + zips = build_list(_("Compression: "),'Z',compress_algo_to_string, + check_compress_algo); + p = zips; + break; + + default: p = default_strusage(level); + } + return p; +} + + +static char * +build_list( const char *text, char letter, + const char * (*mapf)(int), int (*chkf)(int) ) +{ + int i; + const char *s; + size_t n=strlen(text)+2; + char *list, *p, *line=NULL; + + if( maybe_setuid ) + secmem_init( 0 ); /* drop setuid */ + + for(i=0; i <= 110; i++ ) + if( !chkf(i) && (s=mapf(i)) ) + n += strlen(s) + 7 + 2; + list = m_alloc( 21 + n ); *list = 0; + for(p=NULL, i=0; i <= 110; i++ ) { + if( !chkf(i) && (s=mapf(i)) ) { + if( !p ) { + p = stpcpy( list, text ); + line=p; + } + else + p = stpcpy( p, ", "); + + if(strlen(line)>60) { + int spaces=strlen(text); + + list=m_realloc(list,n+spaces+1); + /* realloc could move the block, so find the end again */ + p=list; + while(*p) + p++; + + p=stpcpy(p, "\n"); + line=p; + for(;spaces;spaces--) + p=stpcpy(p, " "); + } + + p = stpcpy(p, s ); + if(opt.verbose && letter) + { + char num[8]; + sprintf(num," (%c%d)",letter,i); + p = stpcpy(p,num); + } + } + } + if( p ) + p = stpcpy(p, "\n" ); + return list; +} + + +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE ); +#else +#ifdef ENABLE_NLS + setlocale( LC_ALL, "" ); + bindtextdomain( PACKAGE, G10_LOCALEDIR ); + textdomain( PACKAGE ); +#endif +#endif +} + +static void +wrong_args( const char *text) +{ + fputs(_("usage: gpg [options] "),stderr); + fputs(text,stderr); + putc('\n',stderr); + g10_exit(2); +} + + +static char * +make_username( const char *string ) +{ + char *p; + if( utf8_strings ) + p = m_strdup(string); + else + p = native_to_utf8( string ); + return p; +} + + +static void +set_debug(void) +{ + if( opt.debug & DBG_MEMORY_VALUE ) + memory_debug_mode = 1; + if( opt.debug & DBG_MEMSTAT_VALUE ) + memory_stat_debug_mode = 1; + if( opt.debug & DBG_MPI_VALUE ) + mpi_debug_mode = 1; + if( opt.debug & DBG_CIPHER_VALUE ) + g10c_debug_mode = 1; + if( opt.debug & DBG_IOBUF_VALUE ) + iobuf_debug_mode = 1; + +} + + +/* We need the home directory also in some other directories, so make + sure that both variables are always in sync. */ +static void +set_homedir (char *dir) +{ + if (!dir) + dir = ""; + g10_opt_homedir = opt.homedir = dir; +} + + +static void +set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) +{ + enum cmd_and_opt_values cmd = *ret_cmd; + + if( !cmd || cmd == new_cmd ) + cmd = new_cmd; + else if( cmd == aSign && new_cmd == aEncr ) + cmd = aSignEncr; + else if( cmd == aEncr && new_cmd == aSign ) + cmd = aSignEncr; + else if( cmd == aSign && new_cmd == aSym ) + cmd = aSignSym; + else if( cmd == aSym && new_cmd == aSign ) + cmd = aSignSym; + else if( cmd == aKMode && new_cmd == aSym ) + cmd = aKModeC; + else if( ( cmd == aSign && new_cmd == aClearsign ) + || ( cmd == aClearsign && new_cmd == aSign ) ) + cmd = aClearsign; + else { + log_error(_("conflicting commands\n")); + g10_exit(2); + } + + *ret_cmd = cmd; +} + + +static void add_group(char *string) +{ + char *name,*value; + struct groupitem *item; + STRLIST values=NULL; + + /* Break off the group name */ + name=strsep(&string,"="); + if(string==NULL) + { + log_error(_("no = sign found in group definition \"%s\"\n"),name); + return; + } + + trim_trailing_ws(name,strlen(name)); + + /* Break apart the values */ + while ((value= strsep(&string," \t"))) + { + if (*value) + add_to_strlist2 (&values,value,utf8_strings); + } + + item=m_alloc(sizeof(struct groupitem)); + item->name=name; + item->values=values; + item->next=opt.grouplist; + + opt.grouplist=item; +} + +/* We need to check three things. + + 0) The homedir. It must be x00, a directory, and owned by the + user. + + 1) The options file. Okay unless it or its containing directory is + group or other writable or not owned by us. disable exec in this + case. + + 2) Extensions. Same as #2. + + Returns true if the item is unsafe. */ +static int +check_permissions(const char *path,int item) +{ +#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM) + static int homedir_cache=-1; + char *tmppath,*dir; + struct stat statbuf,dirbuf; + int homedir=0,ret=0,checkonly=0; + int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0; + + if(opt.no_perm_warn) + return 0; + + assert(item==0 || item==1 || item==2); + + /* extensions may attach a path */ + if(item==2 && 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); + + /* If the item is located in the homedir, but isn't the homedir, + don't continue if we already checked the homedir itself. This is + to avoid user confusion with an extra options file warning which + could be rectified if the homedir itself had proper + permissions. */ + if(item!=0 && homedir_cache>-1 + && ascii_strncasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0) + { + ret=homedir_cache; + goto end; + } + + /* It's okay if the file or directory doesn't exist */ + if(stat(tmppath,&statbuf)!=0) + { + ret=0; + goto end; + } + + /* Now check the enclosing directory. 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,&dirbuf)!=0 || !S_ISDIR(dirbuf.st_mode)) + { + /* Weird error */ + ret=1; + goto end; + } + + m_free(dir); + + /* Assume failure */ + ret=1; + + if(item==0) + { + /* The homedir must be x00, a directory, and owned by the user. */ + + if(S_ISDIR(statbuf.st_mode)) + { + if(statbuf.st_uid==getuid()) + { + if((statbuf.st_mode & (S_IRWXG|S_IRWXO))==0) + ret=0; + else + perm=1; + } + else + own=1; + + homedir_cache=ret; + } + } + else if(item==1 || item==2) + { + /* The options or extension file. Okay unless it or its + containing directory is group or other writable or not owned + by us or root. */ + + if(S_ISREG(statbuf.st_mode)) + { + if(statbuf.st_uid==getuid() || statbuf.st_uid==0) + { + if((statbuf.st_mode & (S_IWGRP|S_IWOTH))==0) + { + /* it's not writable, so make sure the enclosing + directory is also not writable */ + if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) + { + if((dirbuf.st_mode & (S_IWGRP|S_IWOTH))==0) + ret=0; + else + enc_dir_perm=1; + } + else + enc_dir_own=1; + } + else + { + /* it's writable, so the enclosing directory had + better not let people get to it. */ + if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) + { + if((dirbuf.st_mode & (S_IRWXG|S_IRWXO))==0) + ret=0; + else + perm=enc_dir_perm=1; /* unclear which one to fix! */ + } + else + enc_dir_own=1; + } + } + else + own=1; + } + } + else + BUG(); + + if(!checkonly) + { + if(own) + { + if(item==0) + log_info(_("WARNING: unsafe ownership on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe ownership on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe ownership on " + "extension \"%s\"\n"),tmppath); + } + if(perm) + { + if(item==0) + log_info(_("WARNING: unsafe permissions on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe permissions on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe permissions on " + "extension \"%s\"\n"),tmppath); + } + if(enc_dir_own) + { + if(item==0) + log_info(_("WARNING: unsafe enclosing directory ownership on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe enclosing directory ownership on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe enclosing directory ownership on " + "extension \"%s\"\n"),tmppath); + } + if(enc_dir_perm) + { + if(item==0) + log_info(_("WARNING: unsafe enclosing directory permissions on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe enclosing directory permissions on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe enclosing directory permissions on " + "extension \"%s\"\n"),tmppath); + } + } + + end: + m_free(tmppath); + + if(homedir) + homedir_cache=ret; + + return ret; + +#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */ + + return 0; +} + +int +main( int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + IOBUF a; + int rc=0; + int orig_argc; + char **orig_argv; + const char *fname; + char *username; + int may_coredump; + STRLIST sl, remusr= NULL, locusr=NULL; + STRLIST nrings=NULL, sec_nrings=NULL; + armor_filter_context_t afx; + int detached_sig = 0; + FILE *configfp = NULL; + char *configname = NULL; + unsigned configlineno; + int parse_debug = 0; + int default_config = 1; + int default_keyring = 1; + int greeting = 0; + int nogreeting = 0; + int use_random_seed = 1; + enum cmd_and_opt_values cmd = 0; + const char *trustdb_name = NULL; + char *def_cipher_string = NULL; + char *def_digest_string = NULL; + char *def_compress_string = NULL; + char *cert_digest_string = NULL; + char *s2k_cipher_string = NULL; + char *s2k_digest_string = NULL; + char *pers_cipher_list = NULL; + char *pers_digest_list = NULL; + char *pers_compress_list = NULL; + int eyes_only=0; + int pwfd = -1; + int with_fpr = 0; /* make an option out of --fingerprint */ + int any_explicit_recipient = 0; +#ifdef USE_SHM_COPROCESSING + ulong requested_shm_size=0; +#endif + +#ifdef __riscos__ + riscos_global_defaults(); + opt.lock_once = 1; +#endif /* __riscos__ */ + + trap_unaligned(); + secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */ + /* Please note that we may running SUID(ROOT), so be very CAREFUL + * when adding any stuff between here and the call to + * secmem_init() somewhere after the option parsing + */ + log_set_name("gpg"); + secure_random_alloc(); /* put random number into secure memory */ + may_coredump = disable_core_dumps(); + init_signals(); + create_dotlock(NULL); /* register locking cleanup */ + i18n_init(); + opt.command_fd = -1; /* no command fd */ + opt.compress = -1; /* defaults to standard compress level */ + /* note: if you change these lines, look at oOpenPGP */ + opt.def_cipher_algo = 0; + opt.def_digest_algo = 0; + opt.cert_digest_algo = 0; + opt.def_compress_algo = -1; + opt.s2k_mode = 3; /* iterated+salted */ + opt.s2k_digest_algo = DIGEST_ALGO_SHA1; +#ifdef USE_CAST5 + opt.s2k_cipher_algo = CIPHER_ALGO_CAST5; +#else + opt.s2k_cipher_algo = CIPHER_ALGO_3DES; +#endif + opt.completes_needed = 1; + opt.marginals_needed = 3; + opt.max_cert_depth = 5; + opt.pgp2_workarounds = 1; + opt.force_v3_sigs = 1; + opt.escape_from = 1; + opt.import_options=IMPORT_SK2PK; + opt.export_options= + EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; + opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG; + opt.keyserver_options.export_options= + EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; + opt.keyserver_options.include_subkeys=1; + opt.keyserver_options.include_revoked=1; + opt.keyserver_options.try_dns_srv=1; + opt.verify_options=VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION; + opt.trust_model=TM_AUTO; + opt.mangle_dos_filenames = 1; + +#if defined (__MINGW32__) + set_homedir ( read_w32_registry_string( NULL, + "Software\\GNU\\GnuPG", "HomeDir" )); +#else + set_homedir ( getenv("GNUPGHOME") ); +#endif + if( !*opt.homedir ) + set_homedir ( GNUPG_HOMEDIR ); + + /* check whether we have a config file on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ + while( arg_parse( &pargs, opts) ) { + if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll ) + parse_debug++; + else if( pargs.r_opt == oOptions ) { + /* yes there is one, so we do not try the default one, but + * read the option file when it is encountered at the commandline + */ + default_config = 0; + } + else if( pargs.r_opt == oNoOptions ) + default_config = 0; /* --no-options */ + else if( pargs.r_opt == oHomedir ) + set_homedir ( pargs.r.ret_str ); + else if( pargs.r_opt == oNoPermissionWarn ) + opt.no_perm_warn=1; + else if (pargs.r_opt == oStrict ) + { + opt.strict=1; + log_set_strict(1); + } + else if (pargs.r_opt == oNoStrict ) + { + opt.strict=0; + log_set_strict(0); + } +#ifdef USE_SHM_COPROCESSING + else if( pargs.r_opt == oRunAsShmCP ) { + /* does not make sense in a options file, we do it here, + * so that we are the able to drop setuid as soon as possible */ + opt.shm_coprocess = 1; + requested_shm_size = pargs.r.ret_ulong; + } + else if ( pargs.r_opt == oStatusFD ) { + /* this is needed to ensure that the status-fd filedescriptor is + * initialized when init_shm_coprocessing() is called */ + set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); + } +#endif + } + +#ifdef HAVE_DOSISH_SYSTEM + if ( strchr (opt.homedir,'\\') ) { + char *d, *buf = m_alloc (strlen (opt.homedir)+1); + const char *s = opt.homedir; + for (d=buf,s=opt.homedir; *s; s++) + *d++ = *s == '\\'? '/': *s; + *d = 0; + set_homedir (buf); + } +#endif +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) { + init_shm_coprocessing(requested_shm_size, 1 ); + } +#endif + /* initialize the secure memory. */ + secmem_init( 32768 ); + maybe_setuid = 0; + /* Okay, we are now working under our real uid */ + + set_native_charset (NULL); /* Try to auto set the character set */ + + if( default_config ) + { + /* Try for a version specific config file first */ + configname = make_filename(opt.homedir, + "gpg" EXTSEP_S "conf-" SAFE_VERSION, NULL ); + if(access(configname,R_OK)) + { + m_free(configname); + configname = make_filename(opt.homedir, + "gpg" EXTSEP_S "conf", NULL ); + } + if (!access (configname, R_OK)) + { /* Print a warning when both config files are present. */ + char *p = make_filename(opt.homedir, "options", NULL ); + if (!access (p, R_OK)) + log_info (_("NOTE: old default options file `%s' ignored\n"), p); + m_free (p); + } + else + { /* Keep on using the old default one. */ + m_free (configname); + configname = make_filename(opt.homedir, "options", NULL ); + } + } + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + + /* By this point we have a homedir, and cannot change it. */ + check_permissions(opt.homedir,0); + + next_pass: + if( configname ) { + if(check_permissions(configname,1)) + { + /* If any options file is unsafe, then disable any external + programs for keyserver calls or photo IDs. Since the + external program to call is set in the options file, a + unsafe options file can lead to an arbitrary program + being run. */ + + opt.exec_disable=1; + } + + configlineno = 0; + configfp = fopen( configname, "r" ); + if( !configfp ) { + if( default_config ) { + if( parse_debug ) + log_info(_("NOTE: no default option file `%s'\n"), + configname ); + } + else { + log_error(_("option file `%s': %s\n"), + configname, strerror(errno) ); + g10_exit(2); + } + m_free(configname); configname = NULL; + } + if( parse_debug && configname ) + log_info(_("reading options from `%s'\n"), configname ); + default_config = 0; + } + + while( optfile_parse( configfp, configname, &configlineno, + &pargs, opts) ) { + switch( pargs.r_opt ) { + case aCheckKeys: set_cmd( &cmd, aCheckKeys); break; + case aListPackets: set_cmd( &cmd, aListPackets); break; + case aImport: set_cmd( &cmd, aImport); break; + case aFastImport: set_cmd( &cmd, aFastImport); break; + case aSendKeys: set_cmd( &cmd, aSendKeys); break; + case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; + case aSearchKeys: set_cmd( &cmd, aSearchKeys); break; + case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; + case aExport: set_cmd( &cmd, aExport); break; + case aExportAll: set_cmd( &cmd, aExportAll); break; + case aListKeys: set_cmd( &cmd, aListKeys); break; + case aListSigs: set_cmd( &cmd, aListSigs); break; + case aExportSecret: set_cmd( &cmd, aExportSecret); break; + case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break; + case aDeleteSecretKeys: set_cmd( &cmd, aDeleteSecretKeys); + greeting=1; break; + case aDeleteSecretAndPublicKeys: + set_cmd( &cmd, aDeleteSecretAndPublicKeys); + greeting=1; + break; + case aDeleteKeys: set_cmd( &cmd, aDeleteKeys); greeting=1; break; + + case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; + case aSym: set_cmd( &cmd, aSym); break; + + case aDecrypt: set_cmd( &cmd, aDecrypt); break; + case aDecryptFiles: set_cmd( &cmd, aDecryptFiles); break; + + case aEncr: set_cmd( &cmd, aEncr); break; + case aEncrFiles: set_cmd( &cmd, aEncrFiles ); break; + case aSign: set_cmd( &cmd, aSign ); break; + case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; + case aSignKey: set_cmd( &cmd, aSignKey); break; + case aLSignKey: set_cmd( &cmd, aLSignKey); break; + case aNRSignKey: set_cmd( &cmd, aNRSignKey); break; + case aNRLSignKey: set_cmd( &cmd, aNRLSignKey); break; + case aStore: set_cmd( &cmd, aStore); break; + case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break; + case aClearsign: set_cmd( &cmd, aClearsign); break; + case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; + case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; + case aVerify: set_cmd( &cmd, aVerify); break; + case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break; + case aPrimegen: set_cmd( &cmd, aPrimegen); break; + case aGenRandom: set_cmd( &cmd, aGenRandom); break; + case aPrintMD: set_cmd( &cmd, aPrintMD); break; + case aPrintMDs: set_cmd( &cmd, aPrintMDs); break; + case aListTrustDB: set_cmd( &cmd, aListTrustDB); break; + case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break; + case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break; + case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break; + case aListTrustPath: set_cmd( &cmd, aListTrustPath); break; + case aDeArmor: set_cmd( &cmd, aDeArmor); break; + case aEnArmor: set_cmd( &cmd, aEnArmor); break; + case aListOwnerTrust: + deprecated_warning(configname,configlineno, + "--list-ownertrust","--export-ownertrust",""); + case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break; + case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break; + case aPipeMode: set_cmd( &cmd, aPipeMode); break; + case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; + + case oArmor: opt.armor = 1; opt.no_armor=0; break; + case oOutput: opt.outfile = pargs.r.ret_str; break; + case oQuiet: opt.quiet = 1; break; + case oNoTTY: tty_no_terminal(1); break; + case oDryRun: opt.dry_run = 1; break; + case oInteractive: opt.interactive = 1; break; + case oVerbose: g10_opt_verbose++; + opt.verbose++; opt.list_sigs=1; break; + case oKOption: set_cmd( &cmd, aKMode ); break; + + case oBatch: opt.batch = 1; nogreeting = 1; break; + case oUseAgent: +#ifndef __riscos__ + opt.use_agent = 1; +#else /* __riscos__ */ + opt.use_agent = 0; + riscos_not_implemented("use-agent"); +#endif /* __riscos__ */ + break; + case oNoUseAgent: opt.use_agent = 0; break; + case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break; + case oAnswerYes: opt.answer_yes = 1; break; + case oAnswerNo: opt.answer_no = 1; break; + case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break; + case oPrimaryKeyring: + sl=append_to_strlist( &nrings, pargs.r.ret_str); + sl->flags=2; + break; + case oShowKeyring: opt.list_options|=LIST_SHOW_KEYRING; break; + case oDebug: opt.debug |= pargs.r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + case oStatusFD: + set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); + break; +#ifdef __riscos__ + case oStatusFile: + set_status_fd( iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + break; +#endif /* __riscos__ */ + case oAttributeFD: + set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1)); + break; +#ifdef __riscos__ + case oAttributeFile: + set_attrib_fd(iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + break; +#endif /* __riscos__ */ + case oLoggerFD: + log_set_logfile( NULL, + iobuf_translate_file_handle (pargs.r.ret_int, 1) ); + break; +#ifdef __riscos__ + case oLoggerFile: + log_set_logfile( NULL, + iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + break; +#endif /* __riscos__ */ + case oWithFingerprint: + opt.with_fingerprint = 1; + with_fpr=1; /*fall thru*/ + case oFingerprint: opt.fingerprint++; break; + case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break; + case oOptions: + /* config files may not be nested (silently ignore them) */ + if( !configfp ) { + m_free(configname); + configname = m_strdup(pargs.r.ret_str); + goto next_pass; + } + break; + case oNoArmor: opt.no_armor=1; opt.armor=0; break; + case oNoDefKeyring: default_keyring = 0; break; + case oDefCertCheckLevel: opt.def_cert_check_level=pargs.r.ret_int; break; + case oNoGreeting: nogreeting = 1; break; + case oNoVerbose: g10_opt_verbose = 0; + opt.verbose = 0; opt.list_sigs=0; break; + case oQuickRandom: quick_random_gen(1); break; + case oSKComments: opt.sk_comments=1; break; + case oNoSKComments: opt.sk_comments=0; break; + case oEmitVersion: opt.no_version=0; break; + case oNoEmitVersion: opt.no_version=1; break; + case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; + case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break; + case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break; + case oTrustDBName: trustdb_name = pargs.r.ret_str; break; + case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break; + case oDefRecipient: + if( *pargs.r.ret_str ) + opt.def_recipient = make_username(pargs.r.ret_str); + break; + case oDefRecipientSelf: + m_free(opt.def_recipient); opt.def_recipient = NULL; + opt.def_recipient_self = 1; + break; + case oNoDefRecipient: + m_free(opt.def_recipient); opt.def_recipient = NULL; + opt.def_recipient_self = 0; + break; + case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */ + case oHomedir: break; + case oNoBatch: opt.batch = 0; break; + case oWithKeyData: opt.with_key_data=1; /* fall thru */ + case oWithColons: opt.with_colons=':'; break; + + case oSkipVerify: opt.skip_verify=1; break; + case oCompressKeys: opt.compress_keys = 1; break; + case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; + /* There are many programs (like mutt) that call gpg with + --always-trust so keep this option around for a long + time. */ + case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break; + case oTrustModel: + if(ascii_strcasecmp(pargs.r.ret_str,"pgp")==0) + opt.trust_model=TM_PGP; + else if(ascii_strcasecmp(pargs.r.ret_str,"classic")==0) + opt.trust_model=TM_CLASSIC; + else if(ascii_strcasecmp(pargs.r.ret_str,"always")==0) + opt.trust_model=TM_ALWAYS; + else if(ascii_strcasecmp(pargs.r.ret_str,"auto")==0) + opt.trust_model=TM_AUTO; + else + log_error("unknown trust model \"%s\"\n",pargs.r.ret_str); + break; + case oForceOwnertrust: + log_info(_("NOTE: %s is not for normal use!\n"), + "--force-ownertrust"); + opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str); + if(opt.force_ownertrust==-1) + { + log_error("invalid ownertrust \"%s\"\n",pargs.r.ret_str); + opt.force_ownertrust=0; + } + break; + case oLoadExtension: +#ifndef __riscos__ +#if defined(USE_DYNAMIC_LINKING) || defined(__MINGW32__) + if(check_permissions(pargs.r.ret_str,2)) + log_info(_("cipher extension \"%s\" not loaded due to " + "unsafe permissions\n"),pargs.r.ret_str); + else + register_cipher_extension(orig_argc? *orig_argv:NULL, + pargs.r.ret_str); +#endif +#else /* __riscos__ */ + riscos_not_implemented("load-extension"); +#endif /* __riscos__ */ + break; + case oRFC1991: + opt.compliance = CO_RFC1991; + opt.force_v4_certs = 0; + opt.disable_mdc = 1; + opt.escape_from = 1; + break; + case oOpenPGP: + /* TODO: When 2440bis becomes a RFC, these may need + changing. */ + opt.compliance = CO_RFC2440; + opt.disable_mdc = 1; + opt.allow_non_selfsigned_uid = 1; + opt.allow_freeform_uid = 1; + opt.pgp2_workarounds = 0; + opt.escape_from = 0; + opt.force_v3_sigs = 0; + opt.compress_keys = 0; /* not mandated but we do it */ + opt.compress_sigs = 0; /* ditto. */ + opt.not_dash_escaped = 0; + opt.def_cipher_algo = 0; + opt.def_digest_algo = 0; + opt.cert_digest_algo = 0; + opt.def_compress_algo = -1; + opt.s2k_mode = 3; /* iterated+salted */ + opt.s2k_digest_algo = DIGEST_ALGO_SHA1; + opt.s2k_cipher_algo = CIPHER_ALGO_3DES; + break; + case oPGP2: opt.compliance = CO_PGP2; break; + case oPGP6: opt.compliance = CO_PGP6; break; + case oPGP7: opt.compliance = CO_PGP7; break; + case oPGP8: opt.compliance = CO_PGP8; break; + case oGnuPG: opt.compliance = CO_GNUPG; break; + case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; + case oCompressSigs: opt.compress_sigs = 1; break; + case oRunAsShmCP: +#ifndef __riscos__ +# ifndef USE_SHM_COPROCESSING + /* not possible in the option file, + * but we print the warning here anyway */ + log_error("shared memory coprocessing is not available\n"); +# endif +#else /* __riscos__ */ + riscos_not_implemented("run-as-shm-coprocess"); +#endif /* __riscos__ */ + break; + case oSetFilename: opt.set_filename = pargs.r.ret_str; break; + case oForYourEyesOnly: eyes_only = 1; break; + case oNoForYourEyesOnly: eyes_only = 0; break; + case oSetPolicyURL: + add_policy_url(pargs.r.ret_str,0); + add_policy_url(pargs.r.ret_str,1); + break; + case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break; + case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break; + case oShowPolicyURL: + opt.list_options|=LIST_SHOW_POLICY; + opt.verify_options|=VERIFY_SHOW_POLICY; + break; + case oNoShowPolicyURL: + opt.list_options&=~LIST_SHOW_POLICY; + opt.verify_options&=~VERIFY_SHOW_POLICY; + break; + case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; + case oComment: opt.comment_string = pargs.r.ret_str; break; + case oDefaultComment: opt.comment_string = NULL; break; + case oThrowKeyid: opt.throw_keyid = 1; break; + case oNoThrowKeyid: opt.throw_keyid = 0; break; + case oShowPhotos: + opt.list_options|=LIST_SHOW_PHOTOS; + opt.verify_options|=VERIFY_SHOW_PHOTOS; + break; + case oNoShowPhotos: + opt.list_options&=~LIST_SHOW_PHOTOS; + opt.verify_options&=~VERIFY_SHOW_PHOTOS; + break; + case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break; + case oForceV3Sigs: opt.force_v3_sigs = 1; break; + case oNoForceV3Sigs: opt.force_v3_sigs = 0; break; + case oForceV4Certs: opt.force_v4_certs = 1; break; + case oNoForceV4Certs: opt.force_v4_certs = 0; break; + case oForceMDC: opt.force_mdc = 1; break; + case oNoForceMDC: opt.force_mdc = 0; break; + case oDisableMDC: opt.disable_mdc = 1; break; + case oNoDisableMDC: opt.disable_mdc = 0; break; + case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; + case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break; + case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break; + case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break; + case oNoEncryptTo: opt.no_encrypt_to = 1; break; + case oEncryptTo: /* store the recipient in the second list */ + sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + sl->flags = 1; + break; + case oHiddenEncryptTo: /* store the recipient in the second list */ + sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + sl->flags = 1|2; + break; + case oRecipient: /* store the recipient */ + add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + any_explicit_recipient = 1; + break; + case oHiddenRecipient: /* store the recipient with a flag */ + sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + sl->flags = 2; + any_explicit_recipient = 1; + break; + case oTextmodeShort: opt.textmode = 2; break; + case oTextmode: opt.textmode=1; break; + case oNoTextmode: opt.textmode=0; break; + case oExpert: opt.expert = 1; break; + case oNoExpert: opt.expert = 0; break; + case oAskSigExpire: opt.ask_sig_expire = 1; break; + case oNoAskSigExpire: opt.ask_sig_expire = 0; break; + case oAskCertExpire: opt.ask_cert_expire = 1; break; + case oNoAskCertExpire: opt.ask_cert_expire = 0; break; + case oUser: /* store the local users */ + add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings ); + break; + case oCompress: opt.compress = pargs.r.ret_int; break; + case oPasswdFD: + pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); + break; +#ifdef __riscos__ + case oPasswdFile: + pwfd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); + break; +#endif /* __riscos__ */ + case oCommandFD: + opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0); + break; +#ifdef __riscos__ + case oCommandFile: + opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); + break; +#endif /* __riscos__ */ + case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break; + case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break; + case oCompressAlgo: + /* If it is all digits, stick a Z in front of it for + later. This is for backwards compatibility with + versions that took the compress algorithm number. */ + { + char *pt=pargs.r.ret_str; + while(*pt) + { + if(!isdigit(*pt)) + break; + + pt++; + } + + if(*pt=='\0') + { + def_compress_string=m_alloc(strlen(pargs.r.ret_str)+2); + strcpy(def_compress_string,"Z"); + strcat(def_compress_string,pargs.r.ret_str); + } + else + def_compress_string = m_strdup(pargs.r.ret_str); + } + break; + case oCertDigestAlgo: cert_digest_string = m_strdup(pargs.r.ret_str); break; + case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break; + case oNoPermissionWarn: opt.no_perm_warn=1; break; + case oNoMDCWarn: opt.no_mdc_warn=1; break; + case oCharset: + if( set_native_charset( pargs.r.ret_str ) ) + log_error(_("%s is not a valid character set\n"), + pargs.r.ret_str); + break; + case oNotDashEscaped: opt.not_dash_escaped = 1; break; + case oEscapeFrom: opt.escape_from = 1; break; + case oNoEscapeFrom: opt.escape_from = 0; break; + case oLockOnce: opt.lock_once = 1; break; + case oLockNever: disable_dotlock(); break; + case oLockMultiple: +#ifndef __riscos__ + opt.lock_once = 0; +#else /* __riscos__ */ + riscos_not_implemented("lock-multiple"); +#endif /* __riscos__ */ + break; + case oKeyServer: + opt.keyserver_uri=m_strdup(pargs.r.ret_str); + if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno)) + log_error(_("could not parse keyserver URI\n")); + break; + case oKeyServerOptions: + parse_keyserver_options(pargs.r.ret_str); + break; + case oImportOptions: + if(!parse_import_options(pargs.r.ret_str,&opt.import_options)) + { + if(configname) + log_error(_("%s:%d: invalid import options\n"), + configname,configlineno); + else + log_error(_("invalid import options\n")); + } + break; + case oExportOptions: + if(!parse_export_options(pargs.r.ret_str,&opt.export_options)) + { + if(configname) + log_error(_("%s:%d: invalid export options\n"), + configname,configlineno); + else + log_error(_("invalid export options\n")); + } + break; + case oListOptions: + { + struct parse_options lopts[]= + { + {"show-photos",LIST_SHOW_PHOTOS}, + {"show-policy-url",LIST_SHOW_POLICY}, + {"show-notation",LIST_SHOW_NOTATION}, + {"show-keyring",LIST_SHOW_KEYRING}, + {"show-validity",LIST_SHOW_VALIDITY}, + {"show-long-keyid",LIST_SHOW_LONG_KEYID}, + {NULL,0} + }; + + if(!parse_options(pargs.r.ret_str,&opt.list_options,lopts)) + { + if(configname) + log_error(_("%s:%d: invalid list options\n"), + configname,configlineno); + else + log_error(_("invalid list options\n")); + } + } + break; + case oVerifyOptions: + { + struct parse_options vopts[]= + { + {"show-photos",VERIFY_SHOW_PHOTOS}, + {"show-policy-url",VERIFY_SHOW_POLICY}, + {"show-notation",VERIFY_SHOW_NOTATION}, + {NULL,0} + }; + + if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts)) + { + if(configname) + log_error(_("%s:%d: invalid verify options\n"), + configname,configlineno); + else + log_error(_("invalid verify options\n")); + } + } + break; + case oTempDir: opt.temp_dir=pargs.r.ret_str; break; + case oExecPath: + if(set_exec_path(pargs.r.ret_str,0)) + log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str); + else + opt.exec_path_set=1; + break; + case oNotation: + add_notation_data( pargs.r.ret_str, 0 ); + add_notation_data( pargs.r.ret_str, 1 ); + break; + case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break; + case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break; + case oShowNotation: + opt.list_options|=LIST_SHOW_NOTATION; + opt.verify_options|=VERIFY_SHOW_NOTATION; + break; + case oNoShowNotation: + opt.list_options&=~LIST_SHOW_NOTATION; + opt.verify_options&=~VERIFY_SHOW_NOTATION; + break; + case oUtf8Strings: utf8_strings = 1; break; + case oNoUtf8Strings: utf8_strings = 0; break; + case oDisableCipherAlgo: + disable_cipher_algo( string_to_cipher_algo(pargs.r.ret_str) ); + break; + case oDisablePubkeyAlgo: + disable_pubkey_algo( string_to_pubkey_algo(pargs.r.ret_str) ); + break; + case oNoSigCache: opt.no_sig_cache = 1; break; + case oNoSigCreateCheck: opt.no_sig_create_check = 1; break; + case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break; + case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; + case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; + case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; + case oNoLiteral: opt.no_literal = 1; break; + case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; + case oHonorHttpProxy: + opt.keyserver_options.honor_http_proxy = 1; + deprecated_warning(configname,configlineno, + "--honor-http-proxy", + "--keyserver-options ", + "honor-http-proxy"); + break; + case oFastListMode: opt.fast_list_mode = 1; break; + case oFixedListMode: opt.fixed_list_mode = 1; break; + case oListOnly: opt.list_only=1; break; + case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; + case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; + case oIgnoreCrcError: opt.ignore_crc_error = 1; break; + case oIgnoreMDCError: opt.ignore_mdc_error = 1; break; + case oNoRandomSeedFile: use_random_seed = 0; break; + case oAutoKeyRetrieve: + case oNoAutoKeyRetrieve: + opt.keyserver_options.auto_key_retrieve= + (pargs.r_opt==oAutoKeyRetrieve); + deprecated_warning(configname,configlineno, + pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve": + "--no-auto-key-retrieve","--keyserver-options ", + pargs.r_opt==oAutoKeyRetrieve?"auto-key-retrieve": + "no-auto-key-retrieve"); + break; + case oShowSessionKey: opt.show_session_key = 1; break; + case oOverrideSessionKey: + opt.override_session_key = pargs.r.ret_str; + break; + case oMergeOnly: opt.merge_only = 1; break; + case oAllowSecretKeyImport: /* obsolete */ break; + case oTryAllSecrets: opt.try_all_secrets = 1; break; + case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break; + case oEnableSpecialFilenames: + iobuf_enable_special_filenames (1); + break; + case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break; + case oAutoCheckTrustDB: opt.no_auto_check_trustdb=0; break; + case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break; + case oPreservePermissions: opt.preserve_permissions=1; break; + case oDefaultPreferenceList: + opt.def_preference_list = pargs.r.ret_str; + break; + case oPersonalCipherPreferences: + pers_cipher_list=pargs.r.ret_str; + break; + case oPersonalDigestPreferences: + pers_digest_list=pargs.r.ret_str; + break; + case oPersonalCompressPreferences: + pers_compress_list=pargs.r.ret_str; + break; + case oDisplay: opt.display = pargs.r.ret_str; break; + case oTTYname: opt.ttyname = pargs.r.ret_str; break; + case oTTYtype: opt.ttytype = pargs.r.ret_str; break; + case oLCctype: opt.lc_ctype = pargs.r.ret_str; break; + case oLCmessages: opt.lc_messages = pargs.r.ret_str; break; + case oGroup: add_group(pargs.r.ret_str); break; + case oStrict: opt.strict=1; log_set_strict(1); break; + case oNoStrict: opt.strict=0; log_set_strict(0); break; + + case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break; + case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; + + case oEnableProgressFilter: opt.enable_progress_filter = 1; break; + + default : pargs.err = configfp? 1:2; break; + } + } + + if( configfp ) { + fclose( configfp ); + configfp = NULL; + m_free(configname); configname = NULL; + goto next_pass; + } + m_free( configname ); configname = NULL; + if( log_get_errorcount(0) ) + g10_exit(2); + if( nogreeting ) + greeting = 0; + + if( greeting ) { + fprintf(stderr, "%s %s; %s\n", + strusage(11), strusage(13), strusage(14) ); + fprintf(stderr, "%s\n", strusage(15) ); + } +#ifdef IS_DEVELOPMENT_VERSION + if( !opt.batch ) { + log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); + log_info("It is only intended for test purposes and should NOT be\n"); + log_info("used in a production environment or with production keys!\n"); + } +#endif + + if (opt.verbose > 2) + log_info ("using character set `%s'\n", get_native_charset ()); + + if( may_coredump && !opt.quiet ) + log_info(_("WARNING: program may create a core file!\n")); + + if (eyes_only) { + if (opt.set_filename) + log_info(_("WARNING: %s overrides %s\n"), + "--for-your-eyes-only","--set-filename"); + + opt.set_filename="_CONSOLE"; + } + + if (opt.no_literal) { + log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal"); + if (opt.textmode) + log_error(_("%s not allowed with %s!\n"), + "--textmode", "--no-literal" ); + if (opt.set_filename) + log_error(_("%s makes no sense with %s!\n"), + eyes_only?"--for-your-eyes-only":"--set-filename", + "--no-literal" ); + } + + if (opt.set_filesize) + log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize"); + if( opt.batch ) + tty_batchmode( 1 ); + + secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ + + set_debug(); + + /* Do these after the switch(), so they can override settings. */ + if(PGP2) + { + int unusable=0; + + if(cmd==aSign && !detached_sig) + { + log_info(_("you can only make detached or clear signatures " + "while in --pgp2 mode\n")); + unusable=1; + } + else if(cmd==aSignEncr || cmd==aSignSym) + { + log_info(_("you can't sign and encrypt at the " + "same time while in --pgp2 mode\n")); + unusable=1; + } + else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym)) + { + log_info(_("you must use files (and not a pipe) when " + "working with --pgp2 enabled.\n")); + unusable=1; + } + else if(cmd==aEncr || cmd==aSym) + { + /* Everything else should work without IDEA (except using + a secret key encrypted with IDEA and setting an IDEA + preference, but those have their own error + messages). */ + + if(check_cipher_algo(CIPHER_ALGO_IDEA)) + { + log_info(_("encrypting a message in --pgp2 mode requires " + "the IDEA cipher\n")); + idea_cipher_warn(1); + unusable=1; + } + else if(cmd==aSym) + { + /* This only sets IDEA for symmetric encryption + since it is set via select_algo_from_prefs for + pk encryption. */ + m_free(def_cipher_string); + def_cipher_string = m_strdup("idea"); + } + + /* PGP2 can't handle the output from the textmode + filter, so we disable it for anything that could + create a literal packet (only encryption and + symmetric encryption, since we disable signing + above). */ + if(!unusable) + opt.textmode=0; + } + + if(unusable) + compliance_failure(); + else + { + opt.force_mdc = 0; + opt.disable_mdc = 1; + opt.force_v4_certs = 0; + opt.sk_comments = 0; + opt.escape_from = 1; + opt.force_v3_sigs = 1; + opt.pgp2_workarounds = 1; + opt.ask_sig_expire = 0; + opt.ask_cert_expire = 0; + m_free(def_digest_string); + def_digest_string = m_strdup("md5"); + opt.def_compress_algo = 1; + } + } + else if(PGP6) + { + opt.sk_comments=0; + opt.escape_from=1; + opt.force_v3_sigs=1; + opt.ask_sig_expire=0; + opt.force_mdc=0; + opt.disable_mdc=1; + } + else if(PGP7) + { + opt.sk_comments=0; + opt.escape_from=1; + opt.force_v3_sigs=1; + opt.ask_sig_expire=0; + } + else if(PGP8) + { + opt.escape_from=1; + } + + /* must do this after dropping setuid, because string_to... + * may try to load an module */ + if( def_cipher_string ) { + opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string); + if(opt.def_cipher_algo==0 && + (ascii_strcasecmp(def_cipher_string,"idea")==0 + || ascii_strcasecmp(def_cipher_string,"s1")==0)) + idea_cipher_warn(1); + m_free(def_cipher_string); def_cipher_string = NULL; + if( check_cipher_algo(opt.def_cipher_algo) ) + log_error(_("selected cipher algorithm is invalid\n")); + } + if( def_digest_string ) { + opt.def_digest_algo = string_to_digest_algo(def_digest_string); + m_free(def_digest_string); def_digest_string = NULL; + if( check_digest_algo(opt.def_digest_algo) ) + log_error(_("selected digest algorithm is invalid\n")); + } + if( def_compress_string ) { + opt.def_compress_algo = string_to_compress_algo(def_compress_string); + m_free(def_compress_string); def_compress_string = NULL; + if( check_compress_algo(opt.def_compress_algo) ) + log_error(_("selected compression algorithm is invalid\n")); + } + if( cert_digest_string ) { + opt.cert_digest_algo = string_to_digest_algo(cert_digest_string); + m_free(cert_digest_string); cert_digest_string = NULL; + if( check_digest_algo(opt.cert_digest_algo) ) + log_error(_("selected certification digest algorithm is invalid\n")); + } + if( s2k_cipher_string ) { + opt.s2k_cipher_algo = string_to_cipher_algo(s2k_cipher_string); + m_free(s2k_cipher_string); s2k_cipher_string = NULL; + if( check_cipher_algo(opt.s2k_cipher_algo) ) + log_error(_("selected cipher algorithm is invalid\n")); + } + if( s2k_digest_string ) { + opt.s2k_digest_algo = string_to_digest_algo(s2k_digest_string); + m_free(s2k_digest_string); s2k_digest_string = NULL; + if( check_digest_algo(opt.s2k_digest_algo) ) + log_error(_("selected digest algorithm is invalid\n")); + } + if( opt.completes_needed < 1 ) + log_error(_("completes-needed must be greater than 0\n")); + if( opt.marginals_needed < 2 ) + log_error(_("marginals-needed must be greater than 1\n")); + if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 ) + log_error(_("max-cert-depth must be in range 1 to 255\n")); + switch( opt.s2k_mode ) { + case 0: + log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n")); + break; + case 1: case 3: break; + default: + log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); + } + + if(opt.def_cert_check_level<0 || opt.def_cert_check_level>3) + log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n")); + + /* This isn't actually needed, but does serve to error out if the + string is invalid. */ + if(opt.def_preference_list && + keygen_set_std_prefs(opt.def_preference_list,0)) + log_error(_("invalid default preferences\n")); + + /* We provide defaults for the personal digest list */ + if(!pers_digest_list) + pers_digest_list="h2"; + + if(pers_cipher_list && + keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM)) + log_error(_("invalid personal cipher preferences\n")); + + if(pers_digest_list && + keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH)) + log_error(_("invalid personal digest preferences\n")); + + if(pers_compress_list && + keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) + log_error(_("invalid personal compress preferences\n")); + + if( log_get_errorcount(0) ) + g10_exit(2); + + /* Check our chosen algorithms against the list of legal + algorithms. */ + + if(!GNUPG) + { + const char *badalg=NULL; + preftype_t badtype=PREFTYPE_NONE; + + if(opt.def_cipher_algo + && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL)) + { + badalg=cipher_algo_to_string(opt.def_cipher_algo); + badtype=PREFTYPE_SYM; + } + else if(opt.def_digest_algo + && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL)) + { + badalg=digest_algo_to_string(opt.def_digest_algo); + badtype=PREFTYPE_HASH; + } + else if(opt.cert_digest_algo + && !algo_available(PREFTYPE_HASH,opt.cert_digest_algo,NULL)) + { + badalg=digest_algo_to_string(opt.cert_digest_algo); + badtype=PREFTYPE_HASH; + } + else if(opt.def_compress_algo!=-1 + && !algo_available(PREFTYPE_ZIP,opt.def_compress_algo,NULL)) + { + badalg=compress_algo_to_string(opt.def_compress_algo); + badtype=PREFTYPE_ZIP; + } + + if(badalg) + { + switch(badtype) + { + case PREFTYPE_SYM: + log_info(_("you may not use cipher algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + case PREFTYPE_HASH: + log_info(_("you may not use digest algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + case PREFTYPE_ZIP: + log_info(_("you may not use compression algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + default: + BUG(); + } + + compliance_failure(); + } + } + + /* set the random seed file */ + if( use_random_seed ) { + char *p = make_filename(opt.homedir, "random_seed", NULL ); + set_random_seed_file(p); + m_free(p); + } + + if( !cmd && opt.fingerprint && !with_fpr ) { + set_cmd( &cmd, aListKeys); + } + + if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */ + if( cmd == aKModeC ) { + opt.fingerprint = 1; + cmd = aKMode; + } + opt.list_sigs = 0; + if( opt.verbose > 2 ) + opt.check_sigs++; + if( opt.verbose > 1 ) + opt.list_sigs++; + + opt.verbose = opt.verbose > 1; + g10_opt_verbose = opt.verbose; + } + + /* Compression algorithm 0 means no compression at all */ + if( opt.def_compress_algo == 0) + opt.compress = 0; + + /* kludge to let -sat generate a clear text signature */ + if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign ) + cmd = aClearsign; + + if( opt.verbose > 1 ) + set_packet_list_mode(1); + + /* Add the keyrings, but not for some special commands and not in + case of "-kvv userid keyring". Also avoid adding the secret + keyring for a couple of commands to avoid unneeded access in + case the secrings are stored on a floppy */ + if( cmd != aDeArmor && cmd != aEnArmor + && !(cmd == aKMode && argc == 2 ) ) + { + if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys + && cmd != aVerify && cmd != aVerifyFiles + && cmd != aSym) + { + if (!sec_nrings || default_keyring) /* add default secret rings */ + keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); + for (sl = sec_nrings; sl; sl = sl->next) + keydb_add_resource ( sl->d, 0, 1 ); + } + if( !nrings || default_keyring ) /* add default ring */ + keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0); + for(sl = nrings; sl; sl = sl->next ) + keydb_add_resource ( sl->d, sl->flags, 0 ); + } + FREE_STRLIST(nrings); + FREE_STRLIST(sec_nrings); + + + if( pwfd != -1 ) /* read the passphrase now. */ + read_passphrase_from_fd( pwfd ); + + fname = argc? *argv : NULL; + + switch( cmd ) { + case aPrimegen: + case aPrintMD: + case aPrintMDs: + case aGenRandom: + case aDeArmor: + case aEnArmor: + case aFixTrustDB: + break; + case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; + case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; + default: rc = setup_trustdb(1, trustdb_name ); break; + } + if( rc ) + log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc)); + + + switch (cmd) { + case aStore: + case aSym: + case aSign: + case aSignSym: + case aClearsign: + if (!opt.quiet && any_explicit_recipient) + log_info (_("WARNING: recipients (-r) given " + "without using public key encryption\n")); + break; + default: + break; + } + + switch( cmd ) { + case aStore: /* only store the file */ + if( argc > 1 ) + wrong_args(_("--store [filename]")); + if( (rc = encode_store(fname)) ) + log_error_f( print_fname_stdin(fname), + "store failed: %s\n", g10_errstr(rc) ); + break; + case aSym: /* encrypt the given file only with the symmetric cipher */ + if( argc > 1 ) + wrong_args(_("--symmetric [filename]")); + if( (rc = encode_symmetric(fname)) ) + log_error_f(print_fname_stdin(fname), + "symmetric encryption failed: %s\n",g10_errstr(rc) ); + break; + + case aEncr: /* encrypt the given file */ + if( argc > 1 ) + wrong_args(_("--encrypt [filename]")); + if( (rc = encode_crypt(fname,remusr)) ) + log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); + break; + + case aEncrFiles: /* encrypt the given files */ + encode_crypt_files(argc, argv, remusr); + break; + + case aSign: /* sign the given file */ + sl = NULL; + if( detached_sig ) { /* sign all files */ + for( ; argc; argc--, argv++ ) + add_to_strlist( &sl, *argv ); + } + else { + if( argc > 1 ) + wrong_args(_("--sign [filename]")); + if( argc ) { + sl = m_alloc_clear( sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + } + if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) + log_error("signing failed: %s\n", g10_errstr(rc) ); + free_strlist(sl); + break; + + case aSignEncr: /* sign and encrypt the given file */ + if( argc > 1 ) + wrong_args(_("--sign --encrypt [filename]")); + if( argc ) { + sl = m_alloc_clear( sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + else + sl = NULL; + if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) + log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); + free_strlist(sl); + break; + + case aSignSym: /* sign and conventionally encrypt the given file */ + if (argc > 1) + wrong_args(_("--sign --symmetric [filename]")); + rc = sign_symencrypt_file (fname, locusr); + if (rc) + log_error("%s: sign+symmetric failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); + break; + + case aClearsign: /* make a clearsig */ + if( argc > 1 ) + wrong_args(_("--clearsign [filename]")); + if( (rc = clearsign_file(fname, locusr, NULL)) ) + log_error("%s: clearsign failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); + break; + + case aVerify: + if( (rc = verify_signatures( argc, argv ) )) + log_error("verify signatures failed: %s\n", g10_errstr(rc) ); + break; + + case aVerifyFiles: + if( (rc = verify_files( argc, argv ) )) + log_error("verify files failed: %s\n", g10_errstr(rc) ); + break; + + case aDecrypt: + if( argc > 1 ) + wrong_args(_("--decrypt [filename]")); + if( (rc = decrypt_message( fname ) )) + log_error("decrypt_message failed: %s\n", g10_errstr(rc) ); + break; + + case aDecryptFiles: + decrypt_messages(argc, argv); + break; + + case aSignKey: /* sign the key given as argument */ + if( argc != 1 ) + wrong_args(_("--sign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 1 ); + m_free(username); + break; + + case aLSignKey: + if( argc != 1 ) + wrong_args(_("--lsign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 2 ); + m_free(username); + break; + + case aNRSignKey: + if( argc != 1 ) + wrong_args(_("--nrsign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 3 ); + m_free(username); + break; + + case aNRLSignKey: + if( argc != 1 ) + wrong_args(_("--nrlsign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 4 ); + m_free(username); + break; + + case aEditKey: /* Edit a key signature */ + if( !argc ) + wrong_args(_("--edit-key user-id [commands]")); + username = make_username( fname ); + if( argc > 1 ) { + sl = NULL; + for( argc--, argv++ ; argc; argc--, argv++ ) + append_to_strlist( &sl, *argv ); + keyedit_menu( username, locusr, sl, 0 ); + free_strlist(sl); + } + else + keyedit_menu(username, locusr, NULL, 0 ); + m_free(username); + break; + + case aDeleteKeys: + case aDeleteSecretKeys: + case aDeleteSecretAndPublicKeys: + sl = NULL; + /* I'm adding these in reverse order as add_to_strlist2 + reverses them again, and it's easier to understand in the + proper order :) */ + for( ; argc; argc-- ) + add_to_strlist2( &sl, argv[argc-1], utf8_strings ); + delete_keys(sl,cmd==aDeleteSecretKeys,cmd==aDeleteSecretAndPublicKeys); + free_strlist(sl); + break; + + case aCheckKeys: + opt.check_sigs = 1; + case aListSigs: + opt.list_sigs = 1; + case aListKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + public_key_list( sl ); + free_strlist(sl); + break; + case aListSecretKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + secret_key_list( sl ); + free_strlist(sl); + break; + + case aKMode: /* list keyring -- NOTE: This will be removed soon */ + if( argc < 2 ) { /* -kv [userid] */ + sl = NULL; + if (argc && **argv) + add_to_strlist2( &sl, *argv, utf8_strings ); + public_key_list( sl ); + free_strlist(sl); + } + else if( argc == 2 ) { /* -kv userid keyring */ + if( access( argv[1], R_OK ) ) { + log_error(_("can't open %s: %s\n"), + print_fname_stdin(argv[1]), strerror(errno)); + } + else { + /* add keyring (default keyrings are not registered in this + * special case */ + keydb_add_resource( argv[1], 0, 0 ); + sl = NULL; + if (**argv) + add_to_strlist2( &sl, *argv, utf8_strings ); + public_key_list( sl ); + free_strlist(sl); + } + } + else + wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") ); + break; + + case aKeygen: /* generate a key */ + if( opt.batch ) { + if( argc > 1 ) + wrong_args("--gen-key [parameterfile]"); + generate_keypair( argc? *argv : NULL ); + } + else { + if( argc ) + wrong_args("--gen-key"); + generate_keypair(NULL); + } + break; + + case aFastImport: + opt.import_options |= IMPORT_FAST_IMPORT; + case aImport: + import_keys( argc? argv:NULL, argc, NULL, opt.import_options ); + break; + + case aExport: + case aExportAll: + case aSendKeys: + case aRecvKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + if( cmd == aSendKeys ) + rc=keyserver_export( sl ); + else if( cmd == aRecvKeys ) + rc=keyserver_import( sl ); + else + rc=export_pubkeys( sl, opt.export_options ); + if(rc) + { + if(cmd==aSendKeys) + log_error(_("keyserver send failed: %s\n"),g10_errstr(rc)); + else if(cmd==aRecvKeys) + log_error(_("keyserver receive failed: %s\n"),g10_errstr(rc)); + else + log_error(_("key export failed: %s\n"),g10_errstr(rc)); + } + free_strlist(sl); + break; + + case aSearchKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + append_to_strlist2( &sl, *argv, utf8_strings ); + + rc=keyserver_search( sl ); + if(rc) + log_error(_("keyserver search failed: %s\n"),g10_errstr(rc)); + free_strlist(sl); + break; + + case aRefreshKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + rc=keyserver_refresh(sl); + if(rc) + log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc)); + free_strlist(sl); + break; + + case aExportSecret: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + export_seckeys( sl ); + free_strlist(sl); + break; + + case aExportSecretSub: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + export_secsubkeys( sl ); + free_strlist(sl); + break; + + case aGenRevoke: + if( argc != 1 ) + wrong_args("--gen-revoke user-id"); + username = make_username(*argv); + gen_revoke( username ); + m_free( username ); + break; + + case aDesigRevoke: + if( argc != 1 ) + wrong_args("--desig-revoke user-id"); + username = make_username(*argv); + gen_desig_revoke( username ); + m_free( username ); + break; + + case aDeArmor: + if( argc > 1 ) + wrong_args("--dearmor [file]"); + rc = dearmor_file( argc? *argv: NULL ); + if( rc ) + log_error(_("dearmoring failed: %s\n"), g10_errstr(rc)); + break; + + case aEnArmor: + if( argc > 1 ) + wrong_args("--enarmor [file]"); + rc = enarmor_file( argc? *argv: NULL ); + if( rc ) + log_error(_("enarmoring failed: %s\n"), g10_errstr(rc)); + break; + + + case aPrimegen: + { int mode = argc < 2 ? 0 : atoi(*argv); + + if( mode == 1 && argc == 2 ) { + mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1); + } + else if( mode == 2 && argc == 3 ) { + mpi_print( stdout, generate_elg_prime( + 0, atoi(argv[1]), + atoi(argv[2]), NULL,NULL ), 1); + } + else if( mode == 3 && argc == 3 ) { + MPI *factors; + mpi_print( stdout, generate_elg_prime( + 1, atoi(argv[1]), + atoi(argv[2]), NULL,&factors ), 1); + putchar('\n'); + mpi_print( stdout, factors[0], 1 ); /* print q */ + } + else if( mode == 4 && argc == 3 ) { + MPI g = mpi_alloc(1); + mpi_print( stdout, generate_elg_prime( + 0, atoi(argv[1]), + atoi(argv[2]), g, NULL ), 1); + putchar('\n'); + mpi_print( stdout, g, 1 ); + mpi_free(g); + } + else + wrong_args("--gen-prime mode bits [qbits] "); + putchar('\n'); + } + break; + + case aGenRandom: + { + int level = argc ? atoi(*argv):0; + int count = argc > 1 ? atoi(argv[1]): 0; + int endless = !count; + + if( argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0 ) + wrong_args("--gen-random 0|1|2 [count]"); + + while( endless || count ) { + byte *p; + /* Wee need a multiple of 3, so that in case of + armored output we get a correct string. No + linefolding is done, as it is best to levae this to + other tools */ + size_t n = !endless && count < 99? count : 99; + + p = get_random_bits( n*8, level, 0); +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(stdout), O_BINARY ); +#endif + if (opt.armor) { + char *tmp = make_radix64_string (p, n); + fputs (tmp, stdout); + m_free (tmp); + if (n%3 == 1) + putchar ('='); + if (n%3) + putchar ('='); + } else { + fwrite( p, n, 1, stdout ); + } + m_free(p); + if( !endless ) + count -= n; + } + if (opt.armor) + putchar ('\n'); + } + break; + + case aPrintMD: + if( argc < 1) + wrong_args("--print-md algo [files]"); + { + int all_algos = (**argv=='*' && !(*argv)[1]); + int algo = all_algos? 0 : string_to_digest_algo(*argv); + + if( !algo && !all_algos ) + log_error(_("invalid hash algorithm `%s'\n"), *argv ); + else { + argc--; argv++; + if( !argc ) + print_mds(NULL, algo); + else { + for(; argc; argc--, argv++ ) + print_mds(*argv, algo); + } + } + } + break; + + case aPrintMDs: /* old option */ + if( !argc ) + print_mds(NULL,0); + else { + for(; argc; argc--, argv++ ) + print_mds(*argv,0); + } + break; + + case aListTrustDB: + if( !argc ) + list_trustdb(NULL); + else { + for( ; argc; argc--, argv++ ) + list_trustdb( *argv ); + } + break; + + case aUpdateTrustDB: + if( argc ) + wrong_args("--update-trustdb"); + update_trustdb(); + break; + + case aCheckTrustDB: + /* Old versions allowed for arguments - ignore them */ + check_trustdb(); + break; + + case aFixTrustDB: + log_error("this command is not yet implemented.\n"); + log_error("A workaround is to use \"--export-ownertrust\", remove\n"); + log_error("the trustdb file and do an \"--import-ownertrust\".\n" ); + break; + + case aListTrustPath: + if( !argc ) + wrong_args("--list-trust-path <user-ids>"); + for( ; argc; argc--, argv++ ) { + username = make_username( *argv ); + list_trust_path( username ); + m_free(username); + } + break; + + case aExportOwnerTrust: + if( argc ) + wrong_args("--export-ownertrust"); + export_ownertrust(); + break; + + case aImportOwnerTrust: + if( argc > 1 ) + wrong_args("--import-ownertrust [file]"); + import_ownertrust( argc? *argv:NULL ); + break; + + case aPipeMode: + if ( argc ) + wrong_args ("--pipemode"); + run_in_pipemode (); + break; + + case aRebuildKeydbCaches: + if (argc) + wrong_args ("--rebuild-keydb-caches"); + keydb_rebuild_caches (); + break; + + case aListPackets: + opt.list_packets=2; + default: + if( argc > 1 ) + wrong_args(_("[filename]")); + /* Issue some output for the unix newbie */ + if( !fname && !opt.outfile && isatty( fileno(stdin) ) + && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) ) + log_info(_("Go ahead and type your message ...\n")); + + if( !(a = iobuf_open(fname)) ) + log_error(_("can't open `%s'\n"), print_fname_stdin(fname)); + else { + + if( !opt.no_armor ) { + if( use_armor_filter( a ) ) { + memset( &afx, 0, sizeof afx); + iobuf_push_filter( a, armor_filter, &afx ); + } + } + if( cmd == aListPackets ) { + set_packet_list_mode(1); + opt.list_packets=1; + } + rc = proc_packets(NULL, a ); + if( rc ) + log_error("processing message failed: %s\n", g10_errstr(rc) ); + iobuf_close(a); + } + break; + } + + /* cleanup */ + FREE_STRLIST(remusr); + FREE_STRLIST(locusr); + g10_exit(0); + return 8; /*NEVER REACHED*/ +} + + +void +g10_exit( int rc ) +{ + update_random_seed_file(); + if( opt.debug & DBG_MEMSTAT_VALUE ) { + m_print_stats("on exit"); + random_dump_stats(); + } + if( opt.debug ) + secmem_dump_stats(); + secmem_term(); + rc = rc? rc : log_get_errorcount(0)? 2 : + g10_errors_seen? 1 : 0; + exit(rc ); +} + + +/* Pretty-print hex hashes. This assumes at least an 80-character + display, but there are a few other similar assumptions in the + display code. */ +static void +print_hex( MD_HANDLE md, int algo, const char *fname ) +{ + int i,n,count,indent=0; + const byte *p; + + if(fname) + indent=printf("%s: ",fname); + + if(indent>40) + { + printf("\n"); + indent=0; + } + + if(algo==DIGEST_ALGO_RMD160) + indent+=printf("RMD160 = "); + else if(algo==DIGEST_ALGO_TIGER) + indent+=printf(" TIGER = "); + else if(algo>0) + indent+=printf("%6s = ",digest_algo_to_string(algo)); + else + algo=abs(algo); + + count=indent; + + p = md_read( md, algo ); + n = md_digest_length(algo); + + count+=printf("%02X",*p++); + + for(i=1;i<n;i++,p++) + { + if(n==16) + { + if(count+2>79) + { + printf("\n%*s",indent," "); + count=indent; + } + else + count+=printf(" "); + + if(!(i%8)) + count+=printf(" "); + } + else if (n==20) + { + if(!(i%2)) + { + if(count+4>79) + { + printf("\n%*s",indent," "); + count=indent; + } + else + count+=printf(" "); + } + + if(!(i%10)) + count+=printf(" "); + } + else + { + if(!(i%4)) + { + if(count+8>79) + { + printf("\n%*s",indent," "); + count=indent; + } + else + count+=printf(" "); + } + } + + count+=printf("%02X",*p); + } + + printf("\n"); +} + +static void +print_hashline( MD_HANDLE md, int algo, const char *fname ) +{ + int i, n; + const byte *p; + + if ( fname ) { + for (p = fname; *p; p++ ) { + if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) + printf("%%%02X", *p ); + else + putchar( *p ); + } + } + putchar(':'); + printf("%d:", algo ); + p = md_read( md, algo ); + n = md_digest_length(algo); + for(i=0; i < n ; i++, p++ ) + printf("%02X", *p ); + putchar(':'); + putchar('\n'); +} + +static void +print_mds( const char *fname, int algo ) +{ + FILE *fp; + char buf[1024]; + size_t n; + MD_HANDLE md; + + if( !fname ) { + fp = stdin; +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(fp) , O_BINARY ); +#endif + } + else { + fp = fopen( fname, "rb" ); + } + if( !fp ) { + log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); + return; + } + + md = md_open( 0, 0 ); + if( algo ) + md_enable( md, algo ); + else { + md_enable( md, DIGEST_ALGO_MD5 ); + md_enable( md, DIGEST_ALGO_SHA1 ); + md_enable( md, DIGEST_ALGO_RMD160 ); +#ifdef USE_TIGER192 + md_enable( md, DIGEST_ALGO_TIGER ); +#endif +#ifdef USE_SHA256 + md_enable( md, DIGEST_ALGO_SHA256 ); +#endif +#ifdef USE_SHA512 + md_enable( md, DIGEST_ALGO_SHA384 ); + md_enable( md, DIGEST_ALGO_SHA512 ); +#endif + } + + while( (n=fread( buf, 1, DIM(buf), fp )) ) + md_write( md, buf, n ); + if( ferror(fp) ) + log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); + else { + md_final(md); + if ( opt.with_colons ) { + if ( algo ) + print_hashline( md, algo, fname ); + else { + print_hashline( md, DIGEST_ALGO_MD5, fname ); + print_hashline( md, DIGEST_ALGO_SHA1, fname ); + print_hashline( md, DIGEST_ALGO_RMD160, fname ); +#ifdef USE_TIGER192 + print_hashline( md, DIGEST_ALGO_TIGER, fname ); +#endif +#ifdef USE_SHA256 + print_hashline( md, DIGEST_ALGO_SHA256, fname ); +#endif +#ifdef USE_SHA512 + print_hashline( md, DIGEST_ALGO_SHA384, fname ); + print_hashline( md, DIGEST_ALGO_SHA512, fname ); +#endif + } + } + else { + if( algo ) + print_hex(md,-algo,fname); + else { + print_hex( md, DIGEST_ALGO_MD5, fname ); + print_hex( md, DIGEST_ALGO_SHA1, fname ); + print_hex( md, DIGEST_ALGO_RMD160, fname ); +#ifdef USE_TIGER192 + print_hex( md, DIGEST_ALGO_TIGER, fname ); +#endif +#ifdef USE_SHA256 + print_hex( md, DIGEST_ALGO_SHA256, fname ); +#endif +#ifdef USE_SHA512 + print_hex( md, DIGEST_ALGO_SHA384, fname ); + print_hex( md, DIGEST_ALGO_SHA512, fname ); +#endif + } + } + } + md_close(md); + + if( fp != stdin ) + fclose(fp); +} + + +/**************** + * Check the supplied name,value string and add it to the notation + * data to be used for signatures. which==0 for sig notations, and 1 + * for cert notations. +*/ +static void +add_notation_data( const char *string, int which ) +{ + const char *s; + STRLIST sl,*notation_data; + int critical=0; + int highbit=0; + int saw_at=0; + + if(which) + notation_data=&opt.cert_notation_data; + else + notation_data=&opt.sig_notation_data; + + if( *string == '!' ) { + critical = 1; + string++; + } + + /* If and when the IETF assigns some official name tags, we'll + have to add them here. */ + + for( s=string ; *s != '='; s++ ) + { + if( *s=='@') + saw_at=1; + + if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) ) + { + log_error(_("a notation name must have only printable characters " + "or spaces, and end with an '='\n") ); + return; + } + } + + if(!saw_at && !opt.expert) + { + log_error( + _("a user notation name must contain the '@' character\n")); + return; + } + + /* we only support printable text - therefore we enforce the use + * of only printable characters (an empty value is valid) */ + for( s++; *s ; s++ ) { + if( iscntrl(*s) ) { + log_error(_("a notation value must not use " + "any control characters\n") ); + return; + } + else if( *s & 0x80 ) + highbit = 1; + } + + if( highbit ) /* must use UTF8 encoding */ + sl = add_to_strlist2( notation_data, string, utf8_strings ); + else + sl = add_to_strlist( notation_data, string ); + + if( critical ) + sl->flags |= 1; +} + + +static void +add_policy_url( const char *string, int which ) +{ + int i,critical=0; + STRLIST sl; + + if(*string=='!') + { + string++; + critical=1; + } + + for(i=0;i<strlen(string);i++) + if(string[i]&0x80 || iscntrl(string[i])) + break; + + if(i==0 || i<strlen(string)) + { + if(which) + log_error(_("the given certification policy URL is invalid\n")); + else + log_error(_("the given signature policy URL is invalid\n")); + } + + if(which) + sl=add_to_strlist( &opt.cert_policy_url, string ); + else + sl=add_to_strlist( &opt.sig_policy_url, string ); + + if(critical) + sl->flags |= 1; +} diff --git a/g10/getkey.c b/g10/getkey.c new file mode 100644 index 000000000..1944c2a8d --- /dev/null +++ b/g10/getkey.c @@ -0,0 +1,2611 @@ +/* getkey.c - Get a key from the database + * 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 <ctype.h> +#include "util.h" +#include "packet.h" +#include "memory.h" +#include "iobuf.h" +#include "keydb.h" +#include "options.h" +#include "main.h" +#include "trustdb.h" +#include "i18n.h" + +#define MAX_PK_CACHE_ENTRIES 200 +#define MAX_UID_CACHE_ENTRIES 200 + +#if MAX_PK_CACHE_ENTRIES < 2 +#error We need the cache for key creation +#endif + + +struct getkey_ctx_s { + int exact; + KBNODE keyblock; + KBPOS kbpos; + KBNODE found_key; /* pointer into some keyblock */ + int last_rc; + int req_usage; + int req_algo; + KEYDB_HANDLE kr_handle; + int not_allocated; + int nitems; + KEYDB_SEARCH_DESC items[1]; +}; + +#if 0 +static struct { + int any; + int okay_count; + int nokey_count; + int error_count; +} lkup_stats[21]; +#endif + +typedef struct keyid_list { + struct keyid_list *next; + u32 keyid[2]; +} *keyid_list_t; + + +#if MAX_PK_CACHE_ENTRIES + typedef struct pk_cache_entry { + struct pk_cache_entry *next; + u32 keyid[2]; + PKT_public_key *pk; + } *pk_cache_entry_t; + static pk_cache_entry_t pk_cache; + static int pk_cache_entries; /* number of entries in pk cache */ + static int pk_cache_disabled; +#endif + +#if MAX_UID_CACHE_ENTRIES < 5 +#error we really need the userid cache +#endif +typedef struct user_id_db { + struct user_id_db *next; + keyid_list_t keyids; + int len; + char name[1]; +} *user_id_db_t; +static user_id_db_t user_id_db; +static int uid_cache_entries; /* number of entries in uid cache */ + +static void merge_selfsigs( KBNODE keyblock ); +static int lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ); + +#if 0 +static void +print_stats() +{ + int i; + for(i=0; i < DIM(lkup_stats); i++ ) { + if( lkup_stats[i].any ) + fprintf(stderr, + "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n", + i, + lkup_stats[i].okay_count, + lkup_stats[i].nokey_count, + lkup_stats[i].error_count ); + } +} +#endif + + +void +cache_public_key( PKT_public_key *pk ) +{ +#if MAX_PK_CACHE_ENTRIES + pk_cache_entry_t ce; + u32 keyid[2]; + + if( pk_cache_disabled ) + return; + + if( pk->dont_cache ) + return; + + if( is_ELGAMAL(pk->pubkey_algo) + || pk->pubkey_algo == PUBKEY_ALGO_DSA + || is_RSA(pk->pubkey_algo) ) { + keyid_from_pk( pk, keyid ); + } + else + return; /* don't know how to get the keyid */ + + for( ce = pk_cache; ce; ce = ce->next ) + if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { + if( DBG_CACHE ) + log_debug("cache_public_key: already in cache\n"); + return; + } + + if( pk_cache_entries >= MAX_PK_CACHE_ENTRIES ) { + /* fixme: use another algorithm to free some cache slots */ + pk_cache_disabled=1; + if( opt.verbose > 1 ) + log_info(_("too many entries in pk cache - disabled\n")); + return; + } + pk_cache_entries++; + ce = m_alloc( sizeof *ce ); + ce->next = pk_cache; + pk_cache = ce; + ce->pk = copy_public_key( NULL, pk ); + ce->keyid[0] = keyid[0]; + ce->keyid[1] = keyid[1]; +#endif +} + + +/* + * Return the user ID from the given keyblock. + * We use the primary uid flag which has been set by the merge_selfsigs + * function. The returned value is only valid as long as then given + * keyblock is not changed + */ +static const char * +get_primary_uid ( KBNODE keyblock, size_t *uidlen ) +{ + KBNODE k; + const char *s; + + for (k=keyblock; k; k=k->next ) { + if ( k->pkt->pkttype == PKT_USER_ID + && !k->pkt->pkt.user_id->attrib_data + && k->pkt->pkt.user_id->is_primary ) { + *uidlen = k->pkt->pkt.user_id->len; + return k->pkt->pkt.user_id->name; + } + } + /* fixme: returning translatable constants instead of a user ID is + * not good because they are probably not utf-8 encoded. */ + s = _("[User id not found]"); + *uidlen = strlen (s); + return s; +} + + +static void +release_keyid_list ( keyid_list_t k ) +{ + while ( k ) { + keyid_list_t k2 = k->next; + m_free (k); + k = k2; + } +} + +/**************** + * Store the association of keyid and userid + * Feed only public keys to this function. + */ +static void +cache_user_id( KBNODE keyblock ) +{ + user_id_db_t r; + const char *uid; + size_t uidlen; + keyid_list_t keyids = NULL; + KBNODE k; + + for (k=keyblock; k; k = k->next ) { + if ( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + keyid_list_t a = m_alloc_clear ( sizeof *a ); + /* Hmmm: For a long list of keyids it might be an advantage + * to append the keys */ + keyid_from_pk( k->pkt->pkt.public_key, a->keyid ); + /* first check for duplicates */ + for(r=user_id_db; r; r = r->next ) { + keyid_list_t b = r->keyids; + for ( b = r->keyids; b; b = b->next ) { + if( b->keyid[0] == a->keyid[0] + && b->keyid[1] == a->keyid[1] ) { + if( DBG_CACHE ) + log_debug("cache_user_id: already in cache\n"); + release_keyid_list ( keyids ); + m_free ( a ); + return; + } + } + } + /* now put it into the cache */ + a->next = keyids; + keyids = a; + } + } + if ( !keyids ) + BUG (); /* No key no fun */ + + + uid = get_primary_uid ( keyblock, &uidlen ); + + if( uid_cache_entries >= MAX_UID_CACHE_ENTRIES ) { + /* fixme: use another algorithm to free some cache slots */ + r = user_id_db; + user_id_db = r->next; + release_keyid_list ( r->keyids ); + m_free(r); + uid_cache_entries--; + } + r = m_alloc( sizeof *r + uidlen-1 ); + r->keyids = keyids; + r->len = uidlen; + memcpy(r->name, uid, r->len); + r->next = user_id_db; + user_id_db = r; + uid_cache_entries++; +} + + +void +getkey_disable_caches() +{ +#if MAX_PK_CACHE_ENTRIES + { + pk_cache_entry_t ce, ce2; + + for( ce = pk_cache; ce; ce = ce2 ) { + ce2 = ce->next; + free_public_key( ce->pk ); + m_free( ce ); + } + pk_cache_disabled=1; + pk_cache_entries = 0; + pk_cache = NULL; + } +#endif + /* fixme: disable user id cache ? */ +} + + +static void +pk_from_block ( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE keyblock ) +{ + KBNODE a = ctx->found_key ? ctx->found_key : keyblock; + + assert ( a->pkt->pkttype == PKT_PUBLIC_KEY + || a->pkt->pkttype == PKT_PUBLIC_SUBKEY ); + + copy_public_key ( pk, a->pkt->pkt.public_key ); +} + +static void +sk_from_block ( GETKEY_CTX ctx, + PKT_secret_key *sk, KBNODE keyblock ) +{ + KBNODE a = ctx->found_key ? ctx->found_key : keyblock; + + assert ( a->pkt->pkttype == PKT_SECRET_KEY + || a->pkt->pkttype == PKT_SECRET_SUBKEY ); + + copy_secret_key( sk, a->pkt->pkt.secret_key); +} + + +/**************** + * Get a public key and store it into the allocated pk + * can be called with PK set to NULL to just read it into some + * internal structures. + */ +int +get_pubkey( PKT_public_key *pk, u32 *keyid ) +{ + int internal = 0; + int rc = 0; + +#if MAX_PK_CACHE_ENTRIES + { /* Try to get it from the cache */ + pk_cache_entry_t ce; + for( ce = pk_cache; ce; ce = ce->next ) { + if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { + if( pk ) + copy_public_key( pk, ce->pk ); + return 0; + } + } + } +#endif + /* more init stuff */ + if( !pk ) { + pk = m_alloc_clear( sizeof *pk ); + internal++; + } + + + /* do a lookup */ + { struct getkey_ctx_s ctx; + KBNODE kb = NULL; + memset( &ctx, 0, sizeof ctx ); + ctx.exact = 1; /* use the key ID exactly as given */ + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (0); + ctx.nitems = 1; + ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; + ctx.items[0].u.kid[0] = keyid[0]; + ctx.items[0].u.kid[1] = keyid[1]; + ctx.req_algo = pk->req_algo; + ctx.req_usage = pk->req_usage; + rc = lookup( &ctx, &kb, 0 ); + if ( !rc ) { + pk_from_block ( &ctx, pk, kb ); + } + get_pubkey_end( &ctx ); + release_kbnode ( kb ); + } + if( !rc ) + goto leave; + + rc = G10ERR_NO_PUBKEY; + + leave: + if( !rc ) + cache_public_key( pk ); + if( internal ) + free_public_key(pk); + return rc; +} + + +/* Get a public key and store it into the allocated pk. This function + differs from get_pubkey() in that it does not do a check of the key + to avoid recursion. It should be used only in very certain cases. */ +int +get_pubkey_fast (PKT_public_key *pk, u32 *keyid) +{ + int rc = 0; + KEYDB_HANDLE hd; + KBNODE keyblock; + + assert (pk); +#if MAX_PK_CACHE_ENTRIES + { /* Try to get it from the cache */ + pk_cache_entry_t ce; + + for (ce = pk_cache; ce; ce = ce->next) + { + if (ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1]) + { + if (pk) + copy_public_key (pk, ce->pk); + return 0; + } + } + } +#endif + + hd = keydb_new (0); + rc = keydb_search_kid (hd, keyid); + if (rc == -1) + { + keydb_release (hd); + return G10ERR_NO_PUBKEY; + } + rc = keydb_get_keyblock (hd, &keyblock); + keydb_release (hd); + if (rc) + { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + return G10ERR_NO_PUBKEY; + } + + assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY + || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY ); + copy_public_key (pk, keyblock->pkt->pkt.public_key ); + release_kbnode (keyblock); + + /* Not caching key here since it won't have all of the fields + properly set. */ + + return 0; +} + + + +KBNODE +get_pubkeyblock( u32 *keyid ) +{ + struct getkey_ctx_s ctx; + int rc = 0; + KBNODE keyblock = NULL; + + memset( &ctx, 0, sizeof ctx ); + /* no need to set exact here because we want the entire block */ + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (0); + ctx.nitems = 1; + ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; + ctx.items[0].u.kid[0] = keyid[0]; + ctx.items[0].u.kid[1] = keyid[1]; + rc = lookup( &ctx, &keyblock, 0 ); + get_pubkey_end( &ctx ); + + return rc ? NULL : keyblock; +} + + + + +/**************** + * Get a secret key and store it into sk + */ +int +get_seckey( PKT_secret_key *sk, u32 *keyid ) +{ + int rc; + struct getkey_ctx_s ctx; + KBNODE kb = NULL; + + memset( &ctx, 0, sizeof ctx ); + ctx.exact = 1; /* use the key ID exactly as given */ + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (1); + ctx.nitems = 1; + ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; + ctx.items[0].u.kid[0] = keyid[0]; + ctx.items[0].u.kid[1] = keyid[1]; + ctx.req_algo = sk->req_algo; + ctx.req_usage = sk->req_usage; + rc = lookup( &ctx, &kb, 1 ); + if ( !rc ) { + sk_from_block ( &ctx, sk, kb ); + } + get_seckey_end( &ctx ); + release_kbnode ( kb ); + + if( !rc ) { + /* check the secret key (this may prompt for a passprase to + * unlock the secret key + */ + rc = check_secret_key( sk, 0 ); + } + + return rc; +} + + +/**************** + * Check whether the secret key is available. This is just a fast + * check and does not tell us whether the secret key is valid. It + * merely tells other whether there is some secret key. + * Returns: 0 := key is available + * G10ERR_NO_SECKEY := not availabe + */ +int +seckey_available( u32 *keyid ) +{ + int rc; + KEYDB_HANDLE hd = keydb_new (1); + + rc = keydb_search_kid (hd, keyid); + if ( rc == -1 ) + rc = G10ERR_NO_SECKEY; + keydb_release (hd); + return rc; +} + + +/**************** + * Return the type of the user id: + * + * Please use the constants KEYDB_SERCH_MODE_xxx + * 0 = Invalid user ID + * 1 = exact match + * 2 = match a substring + * 3 = match an email address + * 4 = match a substring of an email address + * 5 = match an email address, but compare from end + * 6 = word match mode + * 10 = it is a short KEYID (don't care about keyid[0]) + * 11 = it is a long KEYID + * 12 = it is a trustdb index (keyid is looked up) + * 16 = it is a 16 byte fingerprint + * 20 = it is a 20 byte fingerprint + * 21 = Unified fingerprint :fpr:pk_algo: + * (We don't use pk_algo yet) + * + * Rules used: + * - If the username starts with 8,9,16 or 17 hex-digits (the first one + * must be in the range 0..9), this is considered a keyid; depending + * on the length a short or complete one. + * - If the username starts with 32,33,40 or 41 hex-digits (the first one + * must be in the range 0..9), this is considered a fingerprint. + * - If the username starts with a left angle, we assume it is a complete + * email address and look only at this part. + * - If the username starts with a colon we assume it is a unified + * key specfification. + * - If the username starts with a '.', we assume it is the ending + * part of an email address + * - If the username starts with an '@', we assume it is a part of an + * email address + * - If the userid start with an '=' an exact compare is done. + * - If the userid starts with a '*' a case insensitive substring search is + * done (This is the default). + * - If the userid starts with a '+' we will compare individual words + * and a match requires that all the words are in the userid. + * Words are delimited by white space or "()<>[]{}.@-+_,;/&!" + * (note that you can't search for these characters). Compare + * is not case sensitive. + */ + +int +classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) +{ + const char *s; + int hexprefix = 0; + int hexlength; + int mode = 0; + KEYDB_SEARCH_DESC dummy_desc; + + if (!desc) + desc = &dummy_desc; + + /* clear the structure so that the mode field is set to zero unless + * we set it to the correct value right at the end of this function */ + memset (desc, 0, sizeof *desc); + + /* skip leading spaces. Fixme: what is with trailing spaces? */ + for(s = name; *s && isspace(*s); s++ ) + ; + + switch (*s) { + case 0: /* empty string is an error */ + return 0; + + case '.': /* an email address, compare from end */ + mode = KEYDB_SEARCH_MODE_MAILEND; + s++; + desc->u.name = s; + break; + + case '<': /* an email address */ + mode = KEYDB_SEARCH_MODE_MAIL; + desc->u.name = s; + break; + + case '@': /* part of an email address */ + mode = KEYDB_SEARCH_MODE_MAILSUB; + s++; + desc->u.name = s; + break; + + case '=': /* exact compare */ + mode = KEYDB_SEARCH_MODE_EXACT; + s++; + desc->u.name = s; + break; + + case '*': /* case insensitive substring search */ + mode = KEYDB_SEARCH_MODE_SUBSTR; + s++; + desc->u.name = s; + break; + + case '+': /* compare individual words */ + mode = KEYDB_SEARCH_MODE_WORDS; + s++; + desc->u.name = s; + break; + + case '#': /* local user id */ + return 0; /* This is now obsolete and van't not be used anymore*/ + + case ':': /*Unified fingerprint */ + { + const char *se, *si; + int i; + + se = strchr( ++s,':'); + if ( !se ) + return 0; + for (i=0,si=s; si < se; si++, i++ ) { + if ( !strchr("01234567890abcdefABCDEF", *si ) ) + return 0; /* invalid digit */ + } + if (i != 32 && i != 40) + return 0; /* invalid length of fpr*/ + for (i=0,si=s; si < se; i++, si +=2) + desc->u.fpr[i] = hextobyte(si); + for ( ; i < 20; i++) + desc->u.fpr[i]= 0; + s = se + 1; + mode = KEYDB_SEARCH_MODE_FPR; + } + break; + + default: + if (s[0] == '0' && s[1] == 'x') { + hexprefix = 1; + s += 2; + } + + hexlength = strspn(s, "0123456789abcdefABCDEF"); + if (hexlength >= 8 && s[hexlength] =='!') { + desc->exact = 1; + hexlength++; /* just for the following check */ + } + + /* check if a hexadecimal number is terminated by EOS or blank */ + if (hexlength && s[hexlength] && !isspace(s[hexlength])) { + if (hexprefix) /* a "0x" prefix without correct */ + return 0; /* termination is an error */ + else /* The first chars looked like */ + hexlength = 0; /* a hex number, but really were not. */ + } + + if (desc->exact) + hexlength--; + + if (hexlength == 8 + || (!hexprefix && hexlength == 9 && *s == '0')){ + /* short keyid */ + if (hexlength == 9) + s++; + desc->u.kid[0] = 0; + desc->u.kid[1] = strtoul( s, NULL, 16 ); + mode = KEYDB_SEARCH_MODE_SHORT_KID; + } + else if (hexlength == 16 + || (!hexprefix && hexlength == 17 && *s == '0')) { + /* complete keyid */ + char buf[9]; + if (hexlength == 17) + s++; + mem2str(buf, s, 9 ); + desc->u.kid[0] = strtoul( buf, NULL, 16 ); + desc->u.kid[1] = strtoul( s+8, NULL, 16 ); + mode = KEYDB_SEARCH_MODE_LONG_KID; + } + else if (hexlength == 32 || (!hexprefix && hexlength == 33 + && *s == '0')) { + /* md5 fingerprint */ + int i; + if (hexlength == 33) + s++; + memset(desc->u.fpr+16, 0, 4); + for (i=0; i < 16; i++, s+=2) { + int c = hextobyte(s); + if (c == -1) + return 0; + desc->u.fpr[i] = c; + } + mode = KEYDB_SEARCH_MODE_FPR16; + } + else if (hexlength == 40 || (!hexprefix && hexlength == 41 + && *s == '0')) { + /* sha1/rmd160 fingerprint */ + int i; + if (hexlength == 41) + s++; + for (i=0; i < 20; i++, s+=2) { + int c = hextobyte(s); + if (c == -1) + return 0; + desc->u.fpr[i] = c; + } + mode = KEYDB_SEARCH_MODE_FPR20; + } + else { + if (hexprefix) /* This was a hex number with a prefix */ + return 0; /* and a wrong length */ + + desc->exact = 0; + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_SUBSTR; /* default mode */ + } + } + + desc->mode = mode; + return mode; +} + + +static int +skip_disabled(void *dummy,u32 *keyid) +{ + int rc,disabled=0; + PKT_public_key *pk=m_alloc_clear(sizeof(PKT_public_key)); + + rc = get_pubkey(pk, keyid); + if(rc) + { + log_error("error checking disabled status of %08lX: %s\n", + (ulong)keyid[1],g10_errstr(rc)); + goto leave; + } + + disabled=pk_is_disabled(pk); + + leave: + free_public_key(pk); + return disabled; +} + +/**************** + * Try to get the pubkey by the userid. This function looks for the + * first pubkey certificate which has the given name in a user_id. + * if pk/sk has the pubkey algo set, the function will only return + * a pubkey with that algo. + * The caller should provide storage for either the pk or the sk. + * If ret_kb is not NULL the function will return the keyblock there. + */ + +static int +key_byname( GETKEY_CTX *retctx, STRLIST namelist, + PKT_public_key *pk, PKT_secret_key *sk, + int secmode, int include_disabled, + KBNODE *ret_kb, KEYDB_HANDLE *ret_kdbhd ) +{ + int rc = 0; + int n; + STRLIST r; + GETKEY_CTX ctx; + KBNODE help_kb = NULL; + + if( retctx ) {/* reset the returned context in case of error */ + assert (!ret_kdbhd); /* not allowed because the handle is + stored in the context */ + *retctx = NULL; + } + if (ret_kdbhd) + *ret_kdbhd = NULL; + + /* build the search context */ + for(n=0, r=namelist; r; r = r->next ) + n++; + ctx = m_alloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items ); + ctx->nitems = n; + + for(n=0, r=namelist; r; r = r->next, n++ ) { + classify_user_id (r->d, &ctx->items[n]); + + if (ctx->items[n].exact) + ctx->exact = 1; + if (!ctx->items[n].mode) { + m_free (ctx); + return G10ERR_INV_USER_ID; + } + if(!include_disabled + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_LONG_KID + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR16 + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR20 + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR) + ctx->items[n].skipfnc=skip_disabled; + } + + ctx->kr_handle = keydb_new (secmode); + if ( !ret_kb ) + ret_kb = &help_kb; + + if( secmode ) { + if (sk) { + ctx->req_algo = sk->req_algo; + ctx->req_usage = sk->req_usage; + } + rc = lookup( ctx, ret_kb, 1 ); + if ( !rc && sk ) { + sk_from_block ( ctx, sk, *ret_kb ); + } + } + else { + if (pk) { + ctx->req_algo = pk->req_algo; + ctx->req_usage = pk->req_usage; + } + rc = lookup( ctx, ret_kb, 0 ); + if ( !rc && pk ) { + pk_from_block ( ctx, pk, *ret_kb ); + } + } + + release_kbnode ( help_kb ); + + if (retctx) /* caller wants the context */ + *retctx = ctx; + else { + if (ret_kdbhd) { + *ret_kdbhd = ctx->kr_handle; + ctx->kr_handle = NULL; + } + get_pubkey_end (ctx); + } + + return rc; +} + +/* + * Find a public key from NAME and returh the keyblock or the key. + * If ret_kdb is not NULL, the KEYDB handle used to locate this keyblock is + * returned and the caller is responsible for closing it. + */ +int +get_pubkey_byname (PKT_public_key *pk, + const char *name, KBNODE *ret_keyblock, + KEYDB_HANDLE *ret_kdbhd, int include_disabled ) +{ + int rc; + STRLIST namelist = NULL; + + add_to_strlist( &namelist, name ); + rc = key_byname( NULL, namelist, pk, NULL, 0, + include_disabled, ret_keyblock, ret_kdbhd); + free_strlist( namelist ); + return rc; +} + +int +get_pubkey_bynames( GETKEY_CTX *retctx, PKT_public_key *pk, + STRLIST names, KBNODE *ret_keyblock ) +{ + return key_byname( retctx, names, pk, NULL, 0, 1, ret_keyblock, NULL); +} + +int +get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) +{ + int rc; + + rc = lookup( ctx, ret_keyblock, 0 ); + if ( !rc && pk && ret_keyblock ) + pk_from_block ( ctx, pk, *ret_keyblock ); + + return rc; +} + + +void +get_pubkey_end( GETKEY_CTX ctx ) +{ + if( ctx ) { + memset (&ctx->kbpos, 0, sizeof ctx->kbpos); + keydb_release (ctx->kr_handle); + if( !ctx->not_allocated ) + m_free( ctx ); + } +} + + + + +/**************** + * Search for a key with the given fingerprint. + * FIXME: + * We should replace this with the _byname function. Thiscsan be done + * by creating a userID conforming to the unified fingerprint style. + */ +int +get_pubkey_byfprint( PKT_public_key *pk, + const byte *fprint, size_t fprint_len) +{ + int rc; + + if( fprint_len == 20 || fprint_len == 16 ) { + struct getkey_ctx_s ctx; + KBNODE kb = NULL; + + memset( &ctx, 0, sizeof ctx ); + ctx.exact = 1 ; + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (0); + ctx.nitems = 1; + ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16 + : KEYDB_SEARCH_MODE_FPR20; + memcpy( ctx.items[0].u.fpr, fprint, fprint_len ); + rc = lookup( &ctx, &kb, 0 ); + if (!rc && pk ) + pk_from_block ( &ctx, pk, kb ); + release_kbnode ( kb ); + get_pubkey_end( &ctx ); + } + else + rc = G10ERR_GENERAL; /* Oops */ + return rc; +} + + +/* Get a public key and store it into the allocated pk. This function + differs from get_pubkey_byfprint() in that it does not do a check + of the key to avoid recursion. It should be used only in very + certain cases. PK may be NULL to check just for the existance of + the key. */ +int +get_pubkey_byfprint_fast (PKT_public_key *pk, + const byte *fprint, size_t fprint_len) +{ + int rc = 0; + KEYDB_HANDLE hd; + KBNODE keyblock; + byte fprbuf[MAX_FINGERPRINT_LEN]; + int i; + + for (i=0; i < MAX_FINGERPRINT_LEN && i < fprint_len; i++) + fprbuf[i] = fprint[i]; + while (i < MAX_FINGERPRINT_LEN) + fprbuf[i++] = 0; + + hd = keydb_new (0); + rc = keydb_search_fpr (hd, fprbuf); + if (rc == -1) + { + keydb_release (hd); + return G10ERR_NO_PUBKEY; + } + rc = keydb_get_keyblock (hd, &keyblock); + keydb_release (hd); + if (rc) + { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + return G10ERR_NO_PUBKEY; + } + + assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY + || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY ); + if (pk) + copy_public_key (pk, keyblock->pkt->pkt.public_key ); + release_kbnode (keyblock); + + /* Not caching key here since it won't have all of the fields + properly set. */ + + return 0; +} + +/**************** + * Search for a key with the given fingerprint and return the + * complete keyblock which may have more than only this key. + */ +int +get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ) +{ + int rc; + + if( fprint_len == 20 || fprint_len == 16 ) { + struct getkey_ctx_s ctx; + + memset( &ctx, 0, sizeof ctx ); + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (0); + ctx.nitems = 1; + ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16 + : KEYDB_SEARCH_MODE_FPR20; + memcpy( ctx.items[0].u.fpr, fprint, fprint_len ); + rc = lookup( &ctx, ret_keyblock, 0 ); + get_pubkey_end( &ctx ); + } + else + rc = G10ERR_GENERAL; /* Oops */ + + return rc; +} + + +/**************** + * Get a secret key by name and store it into sk + * If NAME is NULL use the default key + */ +static int +get_seckey_byname2( GETKEY_CTX *retctx, + PKT_secret_key *sk, const char *name, int unprotect, + KBNODE *retblock ) +{ + STRLIST namelist = NULL; + int rc; + + if( !name && opt.def_secret_key && *opt.def_secret_key ) { + add_to_strlist( &namelist, opt.def_secret_key ); + rc = key_byname( retctx, namelist, NULL, sk, 1, 1, retblock, NULL ); + } + else if( !name ) { /* use the first one as default key */ + struct getkey_ctx_s ctx; + KBNODE kb = NULL; + + assert (!retctx ); /* do we need this at all */ + assert (!retblock); + memset( &ctx, 0, sizeof ctx ); + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (1); + ctx.nitems = 1; + ctx.items[0].mode = KEYDB_SEARCH_MODE_FIRST; + rc = lookup( &ctx, &kb, 1 ); + if (!rc && sk ) + sk_from_block ( &ctx, sk, kb ); + release_kbnode ( kb ); + get_seckey_end( &ctx ); + } + else { + add_to_strlist( &namelist, name ); + rc = key_byname( retctx, namelist, NULL, sk, 1, 1, retblock, NULL ); + } + + free_strlist( namelist ); + + if( !rc && unprotect ) + rc = check_secret_key( sk, 0 ); + + return rc; +} + +int +get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ) +{ + return get_seckey_byname2 ( NULL, sk, name, unlock, NULL ); +} + + +int +get_seckey_bynames( GETKEY_CTX *retctx, PKT_secret_key *sk, + STRLIST names, KBNODE *ret_keyblock ) +{ + return key_byname( retctx, names, NULL, sk, 1, 1, ret_keyblock, NULL ); +} + + +int +get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ) +{ + int rc; + + rc = lookup( ctx, ret_keyblock, 1 ); + if ( !rc && sk && ret_keyblock ) + sk_from_block ( ctx, sk, *ret_keyblock ); + + return rc; +} + + +void +get_seckey_end( GETKEY_CTX ctx ) +{ + get_pubkey_end( ctx ); +} + + +/**************** + * Search for a key with the given fingerprint. + * FIXME: + * We should replace this with the _byname function. Thiscsan be done + * by creating a userID conforming to the unified fingerprint style. + */ +int +get_seckey_byfprint( PKT_secret_key *sk, + const byte *fprint, size_t fprint_len) +{ + int rc; + + if( fprint_len == 20 || fprint_len == 16 ) { + struct getkey_ctx_s ctx; + KBNODE kb = NULL; + + memset( &ctx, 0, sizeof ctx ); + ctx.exact = 1 ; + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (1); + ctx.nitems = 1; + ctx.items[0].mode = fprint_len==16? KEYDB_SEARCH_MODE_FPR16 + : KEYDB_SEARCH_MODE_FPR20; + memcpy( ctx.items[0].u.fpr, fprint, fprint_len ); + rc = lookup( &ctx, &kb, 1 ); + if (!rc && sk ) + sk_from_block ( &ctx, sk, kb ); + release_kbnode ( kb ); + get_pubkey_end( &ctx ); + } + else + rc = G10ERR_GENERAL; /* Oops */ + return rc; +} + + +/************************************************ + ************* Merging stuff ******************** + ************************************************/ + +/**************** + * merge all selfsignatures with the keys. + * FIXME: replace this at least for the public key parts + * by merge_selfsigs. + * It is still used in keyedit.c and + * at 2 or 3 other places - check whether it is really needed. + * It might be needed by the key edit and import stuff because + * the keylock is changed. + */ +void +merge_keys_and_selfsig( KBNODE keyblock ) +{ + PKT_public_key *pk = NULL; + PKT_secret_key *sk = NULL; + PKT_signature *sig; + KBNODE k; + u32 kid[2] = { 0, 0 }; + u32 sigdate = 0; + + if (keyblock && keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) { + /* divert to our new function */ + merge_selfsigs (keyblock); + return; + } + /* still need the old one because the new one can't handle secret keys */ + + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + pk = k->pkt->pkt.public_key; sk = NULL; + if( pk->version < 4 ) + pk = NULL; /* not needed for old keys */ + else if( k->pkt->pkttype == PKT_PUBLIC_KEY ) + keyid_from_pk( pk, kid ); + else if( !pk->expiredate ) { /* and subkey */ + /* insert the expiration date here */ + /*FIXME!!! pk->expiredate = subkeys_expiretime( k, kid );*/ + } + sigdate = 0; + } + else if( k->pkt->pkttype == PKT_SECRET_KEY + || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { + pk = NULL; sk = k->pkt->pkt.secret_key; + if( sk->version < 4 ) + sk = NULL; + else if( k->pkt->pkttype == PKT_SECRET_KEY ) + keyid_from_sk( sk, kid ); + sigdate = 0; + } + else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE + && (sig=k->pkt->pkt.signature)->sig_class >= 0x10 + && sig->sig_class <= 0x30 && sig->version > 3 + && !(sig->sig_class == 0x18 || sig->sig_class == 0x28) + && sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) { + /* okay this is a self-signature which can be used. + * This is not used for subkey binding signature, becuase this + * is done above. + * FIXME: We should only use this if the signature is valid + * but this is time consuming - we must provide another + * way to handle this + */ + const byte *p; + u32 ed; + + p = parse_sig_subpkt( sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL ); + if( pk ) { + ed = p? pk->timestamp + buffer_to_u32(p):0; + if( sig->timestamp > sigdate ) { + pk->expiredate = ed; + sigdate = sig->timestamp; + } + } + else { + ed = p? sk->timestamp + buffer_to_u32(p):0; + if( sig->timestamp > sigdate ) { + sk->expiredate = ed; + sigdate = sig->timestamp; + } + } + } + + if(pk && (pk->expiredate==0 || + (pk->max_expiredate && pk->expiredate>pk->max_expiredate))) + pk->expiredate=pk->max_expiredate; + + if(sk && (sk->expiredate==0 || + (sk->max_expiredate && sk->expiredate>sk->max_expiredate))) + sk->expiredate=sk->max_expiredate; + } +} + +/* + * Apply information from SIGNODE (which is the valid self-signature + * associated with that UID) to the UIDNODE: + * - wether the UID has been revoked + * - assumed creation date of the UID + * - temporary store the keyflags here + * - temporary store the key expiration time here + * - mark whether the primary user ID flag hat been set. + * - store the preferences + */ +static void +fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) +{ + PKT_user_id *uid = uidnode->pkt->pkt.user_id; + PKT_signature *sig = signode->pkt->pkt.signature; + const byte *p, *sym, *hash, *zip; + size_t n, nsym, nhash, nzip; + + uid->created = 0; /* not created == invalid */ + if ( IS_UID_REV ( sig ) ) { + uid->is_revoked = 1; + return; /* has been revoked */ + } + + uid->created = sig->timestamp; /* this one is okay */ + uid->selfsigversion = sig->version; + /* If we got this far, it's not expired :) */ + uid->is_expired = 0; + uid->expiredate = sig->expiredate; + + /* store the key flags in the helper variable for later processing */ + uid->help_key_usage = 0; + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); + if ( p && n ) { + /* first octet of the keyflags */ + if ( (*p & 3) ) + uid->help_key_usage |= PUBKEY_USAGE_SIG; + if ( (*p & 12) ) + uid->help_key_usage |= PUBKEY_USAGE_ENC; + /* Note: we do not set the CERT flag here because it can be assumed + * that thre is no real policy to set it. */ + } + + /* ditto or the key expiration */ + uid->help_key_expire = 0; + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); + if ( p ) { + uid->help_key_expire = keycreated + buffer_to_u32(p); + } + + /* Set the primary user ID flag - we will later wipe out some + * of them to only have one in our keyblock */ + uid->is_primary = 0; + p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL ); + if ( p && *p ) + uid->is_primary = 2; + /* We could also query this from the unhashed area if it is not in + * the hased area and then later try to decide which is the better + * there should be no security problem with this. + * For now we only look at the hashed one. + */ + + /* Now build the preferences list. These must come from the + hashed section so nobody can modify the ciphers a key is + willing to accept. */ + p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_SYM, &n ); + sym = p; nsym = p?n:0; + p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_HASH, &n ); + hash = p; nhash = p?n:0; + p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_COMPR, &n ); + zip = p; nzip = p?n:0; + if (uid->prefs) + m_free (uid->prefs); + n = nsym + nhash + nzip; + if (!n) + uid->prefs = NULL; + else { + uid->prefs = m_alloc (sizeof (*uid->prefs) * (n+1)); + n = 0; + for (; nsym; nsym--, n++) { + uid->prefs[n].type = PREFTYPE_SYM; + uid->prefs[n].value = *sym++; + } + for (; nhash; nhash--, n++) { + uid->prefs[n].type = PREFTYPE_HASH; + uid->prefs[n].value = *hash++; + } + for (; nzip; nzip--, n++) { + uid->prefs[n].type = PREFTYPE_ZIP; + uid->prefs[n].value = *zip++; + } + uid->prefs[n].type = PREFTYPE_NONE; /* end of list marker */ + uid->prefs[n].value = 0; + } + + /* see whether we have the MDC feature */ + uid->mdc_feature = 0; + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n); + if (p && n && (p[0] & 0x01)) + uid->mdc_feature = 1; + + /* and the keyserver modify flag */ + uid->ks_modify = 1; + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n); + if (p && n && (p[0] & 0x80)) + uid->ks_modify = 0; +} + +static void +merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) +{ + PKT_public_key *pk = NULL; + KBNODE k; + u32 kid[2]; + u32 sigdate, uiddate, uiddate2; + KBNODE signode, uidnode, uidnode2; + u32 curtime = make_timestamp (); + unsigned int key_usage = 0; + u32 keytimestamp = 0; + u32 key_expire = 0; + int key_expire_seen = 0; + byte sigversion = 0; + + *r_revoked = 0; + if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) + BUG (); + pk = keyblock->pkt->pkt.public_key; + keytimestamp = pk->timestamp; + + keyid_from_pk( pk, kid ); + pk->main_keyid[0] = kid[0]; + pk->main_keyid[1] = kid[1]; + + if ( pk->version < 4 ) { + /* before v4 the key packet itself contains the expiration + * date and there was no way to change it, so we start with + * the one from the key packet */ + key_expire = pk->max_expiredate; + key_expire_seen = 1; + } + + /* first pass: find the latest direct key self-signature. + * We assume that the newest one overrides all others + */ + + /* In case this key was already merged */ + m_free(pk->revkey); + pk->revkey=NULL; + pk->numrevkeys=0; + + signode = NULL; + sigdate = 0; /* helper to find the latest signature */ + for(k=keyblock; k && k->pkt->pkttype != PKT_USER_ID; k = k->next ) { + if ( k->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = k->pkt->pkt.signature; + if ( sig->keyid[0] == kid[0] && sig->keyid[1]==kid[1] ) { + if ( check_key_signature( keyblock, k, NULL ) ) + ; /* signature did not verify */ + else if ( IS_KEY_REV (sig) ){ + /* key has been revoked - there is no way to override + * such a revocation, so we theoretically can stop now. + * We should not cope with expiration times for revocations + * here because we have to assume that an attacker can + * generate all kinds of signatures. However due to the + * fact that the key has been revoked it does not harm + * either and by continuing we gather some more info on + * that key. + */ + *r_revoked = 1; + } + else if ( IS_KEY_SIG (sig) ) { + /* Add any revocation keys onto the pk. This is + particularly interesting since we normally only + get data from the most recent 1F signature, but + you need multiple 1F sigs to properly handle + revocation keys (PGP does it this way, and a + revocation key could be sensitive and hence in a + different signature). */ + if(sig->revkey) { + int i; + + pk->revkey= + m_realloc(pk->revkey,sizeof(struct revocation_key)* + (pk->numrevkeys+sig->numrevkeys)); + + for(i=0;i<sig->numrevkeys;i++) + memcpy(&pk->revkey[pk->numrevkeys++], + sig->revkey[i], + sizeof(struct revocation_key)); + } + + if( sig->timestamp >= sigdate ) { + if(sig->flags.expired) + ; /* signature has expired - ignore it */ + else { + sigdate = sig->timestamp; + signode = k; + if( sig->version > sigversion ) + sigversion = sig->version; + + } + } + } + } + } + } + + /* Remove dupes from the revocation keys */ + + if(pk->revkey) + { + int i,j,x,changed=0; + + for(i=0;i<pk->numrevkeys;i++) + { + for(j=i+1;j<pk->numrevkeys;j++) + { + if(memcmp(&pk->revkey[i],&pk->revkey[j], + sizeof(struct revocation_key))==0) + { + /* remove j */ + + for(x=j;x<pk->numrevkeys-1;x++) + pk->revkey[x]=pk->revkey[x+1]; + + pk->numrevkeys--; + j--; + changed=1; + } + } + } + + if(changed) + pk->revkey=m_realloc(pk->revkey, + pk->numrevkeys*sizeof(struct revocation_key)); + } + + if ( signode ) { + /* some information from a direct key signature take precedence + * over the same information given in UID sigs. + */ + PKT_signature *sig = signode->pkt->pkt.signature; + const byte *p; + size_t n; + + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); + if ( p && n ) { + /* first octet of the keyflags */ + if ( (*p & 3) ) + key_usage |= PUBKEY_USAGE_SIG; + if ( (*p & 12) ) + key_usage |= PUBKEY_USAGE_ENC; + } + + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); + if ( p ) { + key_expire = keytimestamp + buffer_to_u32(p); + key_expire_seen = 1; + } + + /* mark that key as valid: one direct key signature should + * render a key as valid */ + pk->is_valid = 1; + } + + /* pass 1.5: look for key revocation signatures that were not made + by the key (i.e. did a revocation key issue a revocation for + us?). Only bother to do this if there is a revocation key in + the first place. */ + + if(pk->revkey) + for(k=keyblock; k && k->pkt->pkttype != PKT_USER_ID; k = k->next ) + { + if ( k->pkt->pkttype == PKT_SIGNATURE ) + { + PKT_signature *sig = k->pkt->pkt.signature; + + if(IS_KEY_REV(sig) && + (sig->keyid[0]!=kid[0] || sig->keyid[1]!=kid[1])) + { + /* Failure here means the sig did not verify, is was + not issued by a revocation key, or a revocation + key loop was broken. */ + + if(check_revocation_keys(pk,sig)==0) + *r_revoked=1; + + /* In the future handle subkey and cert revocations? + PGP doesn't, but it's in 2440. */ + } + } + } + + /* second pass: look at the self-signature of all user IDs */ + signode = uidnode = NULL; + sigdate = 0; /* helper to find the latest signature in one user ID */ + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next ) { + if ( k->pkt->pkttype == PKT_USER_ID ) { + if ( uidnode && signode ) + { + fixup_uidnode ( uidnode, signode, keytimestamp ); + pk->is_valid=1; + } + uidnode = k; + signode = NULL; + sigdate = 0; + } + else if ( k->pkt->pkttype == PKT_SIGNATURE && uidnode ) { + PKT_signature *sig = k->pkt->pkt.signature; + if ( sig->keyid[0] == kid[0] && sig->keyid[1]==kid[1] ) { + if ( check_key_signature( keyblock, k, NULL ) ) + ; /* signature did not verify */ + else if ( (IS_UID_SIG (sig) || IS_UID_REV (sig)) + && sig->timestamp >= sigdate ) { + /* Note: we allow to invalidate cert revocations + * by a newer signature. An attacker can't use this + * because a key should be revoced with a key revocation. + * The reason why we have to allow for that is that at + * one time an email address may become invalid but later + * the same email address may become valid again (hired, + * fired, hired again). + */ + if(sig->flags.expired) { + /* Expired uids don't get to be primary unless + they are the only uid there is. */ + uidnode->pkt->pkt.user_id->is_primary=0; + uidnode->pkt->pkt.user_id->is_expired=1; + uidnode->pkt->pkt.user_id->expiredate=sig->expiredate; + } + else { + sigdate = sig->timestamp; + signode = k; + if( sig->version > sigversion ) + sigversion = sig->version; + } + } + } + } + } + if ( uidnode && signode ) { + fixup_uidnode ( uidnode, signode, keytimestamp ); + pk->is_valid = 1; + } + + /* If the key isn't valid yet, and we have + --allow-non-selfsigned-uid set, then force it valid. */ + if(!pk->is_valid && opt.allow_non_selfsigned_uid) + { + if(opt.verbose) + log_info(_("Invalid key %08lX made valid by " + "--allow-non-selfsigned-uid\n"), + (ulong)keyid_from_pk(pk,NULL)); + + pk->is_valid = 1; + } + + /* The key STILL isn't valid, so try and find an ultimately + trusted signature. */ + if(!pk->is_valid) + { + uidnode=NULL; + + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k=k->next) + { + if ( k->pkt->pkttype == PKT_USER_ID ) + uidnode = k; + else if ( k->pkt->pkttype == PKT_SIGNATURE && uidnode ) + { + PKT_signature *sig = k->pkt->pkt.signature; + u32 dummy; + int dum2; + + if(sig->keyid[0] != kid[0] || sig->keyid[1]!=kid[1]) + { + PKT_public_key *ultimate_pk; + + ultimate_pk=m_alloc_clear(sizeof(*ultimate_pk)); + + /* We don't want to use the full get_pubkey to + avoid infinite recursion in certain cases. + There is no reason to check that an ultimately + trusted key is still valid - if it has been + revoked or the user should also renmove the + ultimate trust flag. */ + if(get_pubkey_fast(ultimate_pk,sig->keyid)==0 + && check_key_signature2(keyblock,k,ultimate_pk, + NULL,&dummy,&dum2)==0 + && get_ownertrust(ultimate_pk)==TRUST_ULTIMATE) + { + free_public_key(ultimate_pk); + pk->is_valid=1; + break; + } + + free_public_key(ultimate_pk); + } + } + } + } + + /* Record the highest selfsig version so we know if this is a v3 + key through and through, or a v3 key with a v4 selfsig + somewhere. This is useful in a few places to know if the key + must be treated as PGP2-style or OpenPGP-style. Note that a + selfsig revocation with a higher version number will also raise + this value. This is okay since such a revocation must be + issued by the user (i.e. it cannot be issued by someone else to + modify the key behavior.) */ + + pk->selfsigversion=sigversion; + + /* Now that we had a look at all user IDs we can now get some information + * from those user IDs. + */ + + if ( !key_usage ) { + /* find the latest user ID with key flags set */ + uiddate = 0; /* helper to find the latest user ID */ + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; + k = k->next ) { + if ( k->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = k->pkt->pkt.user_id; + if ( uid->help_key_usage && uid->created > uiddate ) { + key_usage = uid->help_key_usage; + uiddate = uid->created; + } + } + } + } + if ( !key_usage ) { /* no key flags at all: get it from the algo */ + key_usage = openpgp_pk_algo_usage ( pk->pubkey_algo ); + } + else { /* check that the usage matches the usage as given by the algo */ + int x = openpgp_pk_algo_usage ( pk->pubkey_algo ); + if ( x ) /* mask it down to the actual allowed usage */ + key_usage &= x; + } + pk->pubkey_usage = key_usage; + + if ( !key_expire_seen ) { + /* find the latest valid user ID with a key expiration set + * Note, that this may be a different one from the above because + * some user IDs may have no expiration date set */ + uiddate = 0; + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; + k = k->next ) { + if ( k->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = k->pkt->pkt.user_id; + if ( uid->help_key_expire && uid->created > uiddate ) { + key_expire = uid->help_key_expire; + uiddate = uid->created; + } + } + } + } + + /* Currently only v3 keys have a maximum expiration date, but I'll + bet v5 keys get this feature again. */ + if(key_expire==0 || (pk->max_expiredate && key_expire>pk->max_expiredate)) + key_expire=pk->max_expiredate; + + pk->has_expired = key_expire >= curtime? 0 : key_expire; + pk->expiredate = key_expire; + + /* Fixme: we should see how to get rid of the expiretime fields but + * this needs changes at other places too. */ + + /* and now find the real primary user ID and delete all others */ + uiddate = uiddate2 = 0; + uidnode = uidnode2 = NULL; + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next ) { + if ( k->pkt->pkttype == PKT_USER_ID && + !k->pkt->pkt.user_id->attrib_data) { + PKT_user_id *uid = k->pkt->pkt.user_id; + if (uid->is_primary) + { + if(uid->created > uiddate) + { + uiddate = uid->created; + uidnode = k; + } + else if(uid->created==uiddate && uidnode) + { + /* The dates are equal, so we need to do a + different (and arbitrary) comparison. This + should rarely, if ever, happen. It's good to + try and guarantee that two different GnuPG + users with two different keyrings at least pick + the same primary. */ + if(cmp_user_ids(uid,uidnode->pkt->pkt.user_id)>0) + uidnode=k; + } + } + else + { + if(uid->created > uiddate2) + { + uiddate2 = uid->created; + uidnode2 = k; + } + else if(uid->created==uiddate2 && uidnode2) + { + if(cmp_user_ids(uid,uidnode2->pkt->pkt.user_id)>0) + uidnode2=k; + } + } + } + } + if ( uidnode ) { + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; + k = k->next ) { + if ( k->pkt->pkttype == PKT_USER_ID && + !k->pkt->pkt.user_id->attrib_data) { + PKT_user_id *uid = k->pkt->pkt.user_id; + if ( k != uidnode ) + uid->is_primary = 0; + } + } + } + else if( uidnode2 ) { + /* none is flagged primary - use the latest user ID we have, + and disambiguate with the arbitrary packet comparison. */ + uidnode2->pkt->pkt.user_id->is_primary = 1; + } + else + { + /* None of our uids were self-signed, so pick the one that + sorts first to be the primary. This is the best we can do + here since there are no self sigs to date the uids. */ + + uidnode = NULL; + + for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; + k = k->next ) + { + if(k->pkt->pkttype==PKT_USER_ID + && !k->pkt->pkt.user_id->attrib_data) + { + if(!uidnode) + { + uidnode=k; + uidnode->pkt->pkt.user_id->is_primary=1; + continue; + } + else + { + if(cmp_user_ids(k->pkt->pkt.user_id, + uidnode->pkt->pkt.user_id)>0) + { + uidnode->pkt->pkt.user_id->is_primary=0; + uidnode=k; + uidnode->pkt->pkt.user_id->is_primary=1; + } + else + k->pkt->pkt.user_id->is_primary=0; /* just to be + safe */ + } + } + } + } +} + + +static void +merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) +{ + PKT_public_key *mainpk = NULL, *subpk = NULL; + PKT_signature *sig; + KBNODE k; + u32 mainkid[2]; + u32 sigdate = 0; + KBNODE signode; + u32 curtime = make_timestamp (); + unsigned int key_usage = 0; + u32 keytimestamp = 0; + u32 key_expire = 0; + const byte *p; + size_t n; + + if ( subnode->pkt->pkttype != PKT_PUBLIC_SUBKEY ) + BUG (); + mainpk = keyblock->pkt->pkt.public_key; + if ( mainpk->version < 4 ) + return; /* (actually this should never happen) */ + keyid_from_pk( mainpk, mainkid ); + subpk = subnode->pkt->pkt.public_key; + keytimestamp = subpk->timestamp; + + subpk->is_valid = 0; + subpk->main_keyid[0] = mainpk->main_keyid[0]; + subpk->main_keyid[1] = mainpk->main_keyid[1]; + + /* find the latest key binding self-signature. */ + signode = NULL; + sigdate = 0; /* helper to find the latest signature */ + for(k=subnode->next; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; + k = k->next ) { + if ( k->pkt->pkttype == PKT_SIGNATURE ) { + sig = k->pkt->pkt.signature; + if ( sig->keyid[0] == mainkid[0] && sig->keyid[1]==mainkid[1] ) { + if ( check_key_signature( keyblock, k, NULL ) ) + ; /* signature did not verify */ + else if ( IS_SUBKEY_REV (sig) ) { + /* Note that this means that the date on a + revocation sig does not matter - even if the + binding sig is dated after the revocation sig, + the subkey is still marked as revoked. This + seems ok, as it is just as easy to make new + subkeys rather than re-sign old ones as the + problem is in the distribution. Plus, PGP (7) + does this the same way. */ + subpk->is_revoked = 1; + /* although we could stop now, we continue to + * figure out other information like the old expiration + * time */ + } + else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) { + if(sig->flags.expired) + ; /* signature has expired - ignore it */ + else { + sigdate = sig->timestamp; + signode = k; + } + } + } + } + } + + if ( !signode ) { + return; /* no valid key binding */ + } + + subpk->is_valid = 1; + sig = signode->pkt->pkt.signature; + + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); + if ( p && n ) { + /* first octet of the keyflags */ + if ( (*p & 3) ) + key_usage |= PUBKEY_USAGE_SIG; + if ( (*p & 12) ) + key_usage |= PUBKEY_USAGE_ENC; + } + if ( !key_usage ) { /* no key flags at all: get it from the algo */ + key_usage = openpgp_pk_algo_usage ( subpk->pubkey_algo ); + } + else { /* check that the usage matches the usage as given by the algo */ + int x = openpgp_pk_algo_usage ( subpk->pubkey_algo ); + if ( x ) /* mask it down to the actual allowed usage */ + key_usage &= x; + } + subpk->pubkey_usage = key_usage; + + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); + if ( p ) + key_expire = keytimestamp + buffer_to_u32(p); + else + key_expire = 0; + subpk->has_expired = key_expire >= curtime? 0 : key_expire; + subpk->expiredate = key_expire; +} + + + +/* + * Merge information from the self-signatures with the key, so that + * we can later use them more easy. + * The function works by first applying the self signatures to the + * primary key and the to each subkey. + * Here are the rules we use to decide which inormation from which + * self-signature is used: + * We check all self signatures or validity and ignore all invalid signatures. + * All signatures are then ordered by their creation date .... + * For the primary key: + * FIXME the docs + */ +static void +merge_selfsigs( KBNODE keyblock ) +{ + KBNODE k; + int revoked; + PKT_public_key *main_pk; + prefitem_t *prefs; + int mdc_feature; + + if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) { + if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) { + log_error ("expected public key but found secret key " + "- must stop\n"); + /* we better exit here becuase a public key is expected at + other places too. FIXME: Figure this out earlier and + don't get to here at all */ + g10_exit (1); + } + BUG (); + } + + merge_selfsigs_main ( keyblock, &revoked ); + + /* now merge in the data from each of the subkeys */ + for(k=keyblock; k; k = k->next ) { + if ( k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + merge_selfsigs_subkey ( keyblock, k ); + } + } + + main_pk = keyblock->pkt->pkt.public_key; + if ( revoked || main_pk->has_expired || !main_pk->is_valid ) { + /* if the primary key is revoked, expired, or invalid we + * better set the appropriate flags on that key and all + * subkeys */ + for(k=keyblock; k; k = k->next ) { + if ( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + PKT_public_key *pk = k->pkt->pkt.public_key; + if(!main_pk->is_valid) + pk->is_valid = 0; + if(revoked) + pk->is_revoked = 1; + if(main_pk->has_expired) + pk->has_expired = main_pk->has_expired; + } + } + return; + } + + /* set the preference list of all keys to those of the primary real + * user ID. Note: we use these preferences when we don't know by + * which user ID the key has been selected. + * fixme: we should keep atoms of commonly used preferences or + * use reference counting to optimize the preference lists storage. + * FIXME: it might be better to use the intersection of + * all preferences. + * Do a similar thing for the MDC feature flag. + */ + prefs = NULL; + mdc_feature = 0; + for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) { + if (k->pkt->pkttype == PKT_USER_ID + && !k->pkt->pkt.user_id->attrib_data + && k->pkt->pkt.user_id->is_primary) { + prefs = k->pkt->pkt.user_id->prefs; + mdc_feature = k->pkt->pkt.user_id->mdc_feature; + break; + } + } + for(k=keyblock; k; k = k->next ) { + if ( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + PKT_public_key *pk = k->pkt->pkt.public_key; + if (pk->prefs) + m_free (pk->prefs); + pk->prefs = copy_prefs (prefs); + pk->mdc_feature = mdc_feature; + } + } +} + + +/* + * Merge the secret keys from secblock into the pubblock thereby + * replacing the public (sub)keys with their secret counterparts Hmmm: + * It might be better to get away from the concept of entire secret + * keys at all and have a way to store just the real secret parts + * from the key. + */ +static void +merge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) +{ + KBNODE pub; + + assert ( pubblock->pkt->pkttype == PKT_PUBLIC_KEY ); + assert ( secblock->pkt->pkttype == PKT_SECRET_KEY ); + + for (pub=pubblock; pub; pub = pub->next ) { + if ( pub->pkt->pkttype == PKT_PUBLIC_KEY ) { + PKT_public_key *pk = pub->pkt->pkt.public_key; + PKT_secret_key *sk = secblock->pkt->pkt.secret_key; + assert ( pub == pubblock ); /* only in the first node */ + /* there is nothing to compare in this case, so just replace + * some information */ + copy_public_parts_to_secret_key ( pk, sk ); + free_public_key ( pk ); + pub->pkt->pkttype = PKT_SECRET_KEY; + pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); + } + else if ( pub->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + KBNODE sec; + PKT_public_key *pk = pub->pkt->pkt.public_key; + + /* this is more complicated: it may happen that the sequence + * of the subkeys dosn't match, so we have to find the + * appropriate secret key */ + for (sec=secblock->next; sec; sec = sec->next ) { + if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = sec->pkt->pkt.secret_key; + if ( !cmp_public_secret_key ( pk, sk ) ) { + copy_public_parts_to_secret_key ( pk, sk ); + free_public_key ( pk ); + pub->pkt->pkttype = PKT_SECRET_SUBKEY; + pub->pkt->pkt.secret_key = copy_secret_key (NULL, sk); + break; + } + } + } + if ( !sec ) + BUG(); /* already checked in premerge */ + } + } +} + +/* This function checks that for every public subkey a corresponding + * secret subkey is available and deletes the public subkey otherwise. + * We need this function because we can't delete it later when we + * actually merge the secret parts into the pubring. + * The function also plays some games with the node flags. + */ +static void +premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) +{ + KBNODE last, pub; + + assert ( pubblock->pkt->pkttype == PKT_PUBLIC_KEY ); + assert ( secblock->pkt->pkttype == PKT_SECRET_KEY ); + + for (pub=pubblock,last=NULL; pub; last = pub, pub = pub->next ) { + pub->flag &= ~3; /* reset bits 0 and 1 */ + if ( pub->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + KBNODE sec; + PKT_public_key *pk = pub->pkt->pkt.public_key; + + for (sec=secblock->next; sec; sec = sec->next ) { + if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = sec->pkt->pkt.secret_key; + if ( !cmp_public_secret_key ( pk, sk ) ) { + if ( sk->protect.s2k.mode == 1001 ) { + /* The secret parts are not available so + we can't use that key for signing etc. + Fix the pubkey usage */ + pk->pubkey_usage &= ~PUBKEY_USAGE_SIG; + } + /* transfer flag bits 0 and 1 to the pubblock */ + pub->flag |= (sec->flag &3); + break; + } + } + } + if ( !sec ) { + KBNODE next, ll; + + if (opt.verbose) + log_info ( _("no secret subkey " + "for public subkey %08lX - ignoring\n"), + (ulong)keyid_from_pk (pk,NULL) ); + /* we have to remove the subkey in this case */ + assert ( last ); + /* find the next subkey */ + for (next=pub->next,ll=pub; + next && pub->pkt->pkttype != PKT_PUBLIC_SUBKEY; + ll = next, next = next->next ) + ; + /* make new link */ + last->next = next; + /* release this public subkey with all sigs */ + ll->next = NULL; + release_kbnode( pub ); + /* let the loop continue */ + pub = last; + } + } + } + /* We need to copy the found bits (0 and 1) from the secret key to + the public key. This has already been done for the subkeys but + got lost on the primary key - fix it here *. */ + pubblock->flag |= (secblock->flag & 3); +} + + + + +/* See see whether the key fits + * our requirements and in case we do not + * request the primary key, we should select + * a suitable subkey. + * FIXME: Check against PGP 7 whether we still need a kludge + * to favor type 16 keys over type 20 keys when type 20 + * has not been explitely requested. + * Returns: True when a suitable key has been found. + * + * We have to distinguish four cases: FIXME! + * 1. No usage and no primary key requested + * Examples for this case are that we have a keyID to be used + * for decrytion or verification. + * 2. No usage but primary key requested + * This is the case for all functions which work on an + * entire keyblock, e.g. for editing or listing + * 3. Usage and primary key requested + * FXME + * 4. Usage but no primary key requested + * FIXME + * FIXME: Tell what is going to happen here and something about the rationale + * Note: We don't use this function if no specific usage is requested; + * This way the getkey functions can be used for plain key listings. + * + * CTX ist the keyblock we are investigating, if FOUNDK is not NULL this + * is the key we actually found by looking at the keyid or a fingerprint and + * may eitehr point to the primary or one of the subkeys. + */ + +static int +finish_lookup (GETKEY_CTX ctx) +{ + KBNODE keyblock = ctx->keyblock; + KBNODE k; + KBNODE foundk = NULL; + PKT_user_id *foundu = NULL; +#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC) + unsigned int req_usage = ( ctx->req_usage & USAGE_MASK ); + /* Request the primary if we're certifying another key, and also + if signing data while --pgp6 or --pgp7 is on since pgp 6 and 7 + do not understand signatures made by a signing subkey. PGP 8 + does. */ + int req_prim = (ctx->req_usage & PUBKEY_USAGE_CERT) || + ((PGP6 || PGP7) && (ctx->req_usage & PUBKEY_USAGE_SIG)); + u32 latest_date; + KBNODE latest_key; + u32 curtime = make_timestamp (); + + assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ); + + ctx->found_key = NULL; + + if (ctx->exact) { + for (k=keyblock; k; k = k->next) { + if ( (k->flag & 1) ) { + assert ( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ); + foundk = k; + break; + } + } + } + + for (k=keyblock; k; k = k->next) { + if ( (k->flag & 2) ) { + assert (k->pkt->pkttype == PKT_USER_ID); + foundu = k->pkt->pkt.user_id; + break; + } + } + + if ( DBG_CACHE ) + log_debug( "finish_lookup: checking key %08lX (%s)(req_usage=%x)\n", + (ulong)keyid_from_pk( keyblock->pkt->pkt.public_key, NULL), + foundk? "one":"all", req_usage); + + if (!req_usage) { + latest_key = foundk? foundk:keyblock; + goto found; + } + + if (!req_usage) { + PKT_public_key *pk = foundk->pkt->pkt.public_key; + if (pk->user_id) + free_user_id (pk->user_id); + pk->user_id = scopy_user_id (foundu); + ctx->found_key = foundk; + cache_user_id( keyblock ); + return 1; /* found */ + } + + latest_date = 0; + latest_key = NULL; + /* do not look at subkeys if a certification key is requested */ + if ((!foundk || foundk->pkt->pkttype == PKT_PUBLIC_SUBKEY) && !req_prim) { + KBNODE nextk; + /* either start a loop or check just this one subkey */ + for (k=foundk?foundk:keyblock; k; k = nextk ) { + PKT_public_key *pk; + nextk = k->next; + if ( k->pkt->pkttype != PKT_PUBLIC_SUBKEY ) + continue; + if ( foundk ) + nextk = NULL; /* what a hack */ + pk = k->pkt->pkt.public_key; + if (DBG_CACHE) + log_debug( "\tchecking subkey %08lX\n", + (ulong)keyid_from_pk( pk, NULL)); + if ( !pk->is_valid ) { + if (DBG_CACHE) + log_debug( "\tsubkey not valid\n"); + continue; + } + if ( pk->is_revoked ) { + if (DBG_CACHE) + log_debug( "\tsubkey has been revoked\n"); + continue; + } + if ( pk->has_expired ) { + if (DBG_CACHE) + log_debug( "\tsubkey has expired\n"); + continue; + } + if ( pk->timestamp > curtime && !opt.ignore_valid_from ) { + if (DBG_CACHE) + log_debug( "\tsubkey not yet valid\n"); + continue; + } + + if ( !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) { + if (DBG_CACHE) + log_debug( "\tusage does not match: want=%x have=%x\n", + req_usage, pk->pubkey_usage ); + continue; + } + + if (DBG_CACHE) + log_debug( "\tsubkey looks fine\n"); + if ( pk->timestamp > latest_date ) { + latest_date = pk->timestamp; + latest_key = k; + } + } + } + + /* Okay now try the primary key unless we want an exact + * key ID match on a subkey */ + if ((!latest_key && !(ctx->exact && foundk != keyblock)) || req_prim) { + PKT_public_key *pk; + if (DBG_CACHE && !foundk && !req_prim ) + log_debug( "\tno suitable subkeys found - trying primary\n"); + pk = keyblock->pkt->pkt.public_key; + if ( !pk->is_valid ) { + if (DBG_CACHE) + log_debug( "\tprimary key not valid\n"); + } + else if ( pk->is_revoked ) { + if (DBG_CACHE) + log_debug( "\tprimary key has been revoked\n"); + } + else if ( pk->has_expired ) { + if (DBG_CACHE) + log_debug( "\tprimary key has expired\n"); + } + else if ( !((pk->pubkey_usage&USAGE_MASK) & req_usage) ) { + if (DBG_CACHE) + log_debug( "\tprimary key usage does not match: " + "want=%x have=%x\n", + req_usage, pk->pubkey_usage ); + } + else { /* okay */ + if (DBG_CACHE) + log_debug( "\tprimary key may be used\n"); + latest_key = keyblock; + latest_date = pk->timestamp; + } + } + + if ( !latest_key ) { + if (DBG_CACHE) + log_debug("\tno suitable key found - giving up\n"); + return 0; + } + + found: + if (DBG_CACHE) + log_debug( "\tusing key %08lX\n", + (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL) ); + + if (latest_key) { + PKT_public_key *pk = latest_key->pkt->pkt.public_key; + if (pk->user_id) + free_user_id (pk->user_id); + pk->user_id = scopy_user_id (foundu); + } + + ctx->found_key = latest_key; + + if (latest_key != keyblock && opt.verbose) { + log_info(_("using secondary key %08lX " + "instead of primary key %08lX\n"), + (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL), + (ulong)keyid_from_pk( keyblock->pkt->pkt.public_key, NULL) ); + } + + cache_user_id( keyblock ); + + return 1; /* found */ +} + + +static int +lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) +{ + int rc; + KBNODE secblock = NULL; /* helper */ + int no_suitable_key = 0; + + rc = 0; + while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems))) { + /* If we are searching for the first key we have to make sure + that the next interation does not no an implicit reset. + This can be triggered by an empty key ring. */ + if (ctx->nitems && ctx->items->mode == KEYDB_SEARCH_MODE_FIRST) + ctx->items->mode = KEYDB_SEARCH_MODE_NEXT; + + rc = keydb_get_keyblock (ctx->kr_handle, &ctx->keyblock); + if (rc) { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + rc = 0; + goto skip; + } + + if ( secmode ) { + /* find the correspondig public key and use this + * this one for the selection process */ + u32 aki[2]; + KBNODE k = ctx->keyblock; + + if (k->pkt->pkttype != PKT_SECRET_KEY) + BUG(); + + keyid_from_sk (k->pkt->pkt.secret_key, aki); + k = get_pubkeyblock (aki); + if( !k ) { + if (!opt.quiet) + log_info(_("key %08lX: secret key without public key " + "- skipped\n"), (ulong)aki[1] ); + goto skip; + } + secblock = ctx->keyblock; + ctx->keyblock = k; + + premerge_public_with_secret ( ctx->keyblock, secblock ); + } + + /* warning: node flag bits 0 and 1 should be preserved by + * merge_selfsigs. For secret keys, premerge did tranfer the + * keys to the keyblock */ + merge_selfsigs ( ctx->keyblock ); + if ( finish_lookup (ctx) ) { + no_suitable_key = 0; + if ( secmode ) { + merge_public_with_secret ( ctx->keyblock, + secblock); + release_kbnode (secblock); + secblock = NULL; + } + goto found; + } + else + no_suitable_key = 1; + + skip: + /* release resources and continue search */ + if ( secmode ) { + release_kbnode( secblock ); + secblock = NULL; + } + release_kbnode( ctx->keyblock ); + ctx->keyblock = NULL; + } + + found: + if( rc && rc != -1 ) + log_error("keydb_search failed: %s\n", g10_errstr(rc)); + + if( !rc ) { + *ret_keyblock = ctx->keyblock; /* return the keyblock */ + ctx->keyblock = NULL; + } + else if (rc == -1 && no_suitable_key) + rc = secmode ? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; + else if( rc == -1 ) + rc = secmode ? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; + + if ( secmode ) { + release_kbnode( secblock ); + secblock = NULL; + } + release_kbnode( ctx->keyblock ); + ctx->keyblock = NULL; + + ctx->last_rc = rc; + return rc; +} + + + + +/**************** + * FIXME: Replace by the generic function + * It does not work as it is right now - it is used at + * 2 places: a) to get the key for an anonyous recipient + * b) to get the ultimately trusted keys. + * The a) usage might have some problems. + * + * set with_subkeys true to include subkeys + * set with_spm true to include secret-parts-missing keys + * + * Enumerate all primary secret keys. Caller must use these procedure: + * 1) create a void pointer and initialize it to NULL + * 2) pass this void pointer by reference to this function + * and provide space for the secret key (pass a buffer for sk) + * 3) call this function as long as it does not return -1 + * to indicate EOF. + * 4) Always call this function a last time with SK set to NULL, + * so that can free it's context. + */ +int +enum_secret_keys( void **context, PKT_secret_key *sk, + int with_subkeys, int with_spm ) +{ + int rc=0; + struct { + int eof; + int first; + KEYDB_HANDLE hd; + KBNODE keyblock; + KBNODE node; + } *c = *context; + + + if( !c ) { /* make a new context */ + c = m_alloc_clear( sizeof *c ); + *context = c; + c->hd = keydb_new (1); + c->first = 1; + c->keyblock = NULL; + c->node = NULL; + } + + if( !sk ) { /* free the context */ + keydb_release (c->hd); + release_kbnode (c->keyblock); + m_free( c ); + *context = NULL; + return 0; + } + + if( c->eof ) + return -1; + + do { + /* get the next secret key from the current keyblock */ + for (; c->node; c->node = c->node->next) { + if ((c->node->pkt->pkttype == PKT_SECRET_KEY + || (with_subkeys + && c->node->pkt->pkttype == PKT_SECRET_SUBKEY) ) + && !(c->node->pkt->pkt.secret_key->protect.s2k.mode==1001 + && !with_spm)) { + copy_secret_key (sk, c->node->pkt->pkt.secret_key ); + c->node = c->node->next; + return 0; /* found */ + } + } + release_kbnode (c->keyblock); + c->keyblock = c->node = NULL; + + rc = c->first? keydb_search_first (c->hd) : keydb_search_next (c->hd); + c->first = 0; + if (rc) { + keydb_release (c->hd); c->hd = NULL; + c->eof = 1; + return -1; /* eof */ + } + + rc = keydb_get_keyblock (c->hd, &c->keyblock); + c->node = c->keyblock; + } while (!rc); + + return rc; /* error */ +} + + + +/********************************************* + *********** user ID printing helpers ******* + *********************************************/ + +/**************** + * Return a string with a printable representation of the user_id. + * this string must be freed by m_free. + */ +char* +get_user_id_string( u32 *keyid ) +{ + user_id_db_t r; + char *p; + int pass=0; + /* try it two times; second pass reads from key resources */ + do { + for(r=user_id_db; r; r = r->next ) { + keyid_list_t a; + for (a=r->keyids; a; a= a->next ) { + if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { + p = m_alloc( r->len + 10 ); + sprintf(p, "%08lX %.*s", + (ulong)keyid[1], r->len, r->name ); + return p; + } + } + } + } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); + p = m_alloc( 15 ); + sprintf(p, "%08lX [?]", (ulong)keyid[1] ); + return p; +} + + +char* +get_user_id_string_printable ( u32 *keyid ) +{ + char *p = get_user_id_string( keyid ); + char *p2 = utf8_to_native( p, strlen(p), 0 ); + m_free(p); + p = make_printable_string (p2, strlen (p2), 0); + m_free (p2); + return p; +} + + +char* +get_long_user_id_string( u32 *keyid ) +{ + user_id_db_t r; + char *p; + int pass=0; + /* try it two times; second pass reads from key resources */ + do { + for(r=user_id_db; r; r = r->next ) { + keyid_list_t a; + for (a=r->keyids; a; a= a->next ) { + if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { + p = m_alloc( r->len + 20 ); + sprintf(p, "%08lX%08lX %.*s", + (ulong)keyid[0], (ulong)keyid[1], + r->len, r->name ); + return p; + } + } + } + } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); + p = m_alloc( 25 ); + sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] ); + return p; +} + +char* +get_user_id( u32 *keyid, size_t *rn ) +{ + user_id_db_t r; + char *p; + int pass=0; + + /* try it two times; second pass reads from key resources */ + do { + for(r=user_id_db; r; r = r->next ) { + keyid_list_t a; + for (a=r->keyids; a; a= a->next ) { + if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { + p = m_alloc( r->len ); + memcpy(p, r->name, r->len ); + *rn = r->len; + return p; + } + } + } + } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); + p = m_strdup( _("[User id not found]") ); + *rn = strlen(p); + return p; +} + +char* +get_user_id_printable( u32 *keyid ) +{ + size_t rn; + char *p = get_user_id( keyid, &rn ); + char *p2 = utf8_to_native( p, rn, 0 ); + m_free(p); + p = make_printable_string (p2, strlen (p2), 0); + m_free (p2); + return p; +} + +KEYDB_HANDLE +get_ctx_handle(GETKEY_CTX ctx) +{ + return ctx->kr_handle; +} diff --git a/g10/gpgv.c b/g10/gpgv.c new file mode 100644 index 000000000..67ecceabf --- /dev/null +++ b/g10/gpgv.c @@ -0,0 +1,396 @@ +/* gpgv.c - The GnuPG signature verify utility + * 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 <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 "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" +#include "g10defs.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__ */ + +const char * +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 = default_strusage(level); + } + return p; +} + + + + +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE ); +#else +#ifdef ENABLE_NLS +#ifdef HAVE_LC_MESSAGES + setlocale( LC_TIME, "" ); + setlocale( LC_MESSAGES, "" ); +#else + setlocale( LC_ALL, "" ); +#endif + bindtextdomain( PACKAGE, G10_LOCALEDIR ); + textdomain( PACKAGE ); +#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__ */ + + log_set_name("gpgv"); + init_signals(); + 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 (__MINGW32__) + 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_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_logfile( NULL, pargs.r.ret_int ); 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", g10_errstr(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 ); +} + + +/* 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 G10ERR_GENERAL; +} +/* Stub: */ +int +get_override_session_key( DEK *dek, const char *string ) +{ + return G10ERR_GENERAL; +} +/* Stub: */ +int +decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) +{ + return G10ERR_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 G10ERR_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 ../cipher/random.c */ +void random_dump_stats(void) {} +int quick_random_gen( int onoff ) { return -1;} +void randomize_buffer( byte *buffer, size_t length, int level ) {} +int random_is_faked() { return -1;} +byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;} +void set_random_seed_file( const char *name ) {} +void update_random_seed_file() {} +void fast_random_poll() {} + +/* Stubs to avoid linking of ../cipher/primegen.c */ +void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {} +MPI generate_secret_prime( unsigned nbits ) { return NULL;} +MPI generate_public_prime( unsigned nbits ) { return NULL;} +MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, + MPI g, MPI **ret_factors ) { return NULL;} + +/* Do not link to ../cipher/rndlinux.c */ +void rndlinux_constructor(void) {} + + +/* 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( byte *p, size_t n ) { } +void tty_print_utf8_string( byte *p, size_t n ) {} +void tty_print_utf8_string2( 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 remove_lockfiles(void) {} diff --git a/g10/import.c b/g10/import.c new file mode 100644 index 000000000..1b955c412 --- /dev/null +++ b/g10/import.c @@ -0,0 +1,1879 @@ +/* import.c + * 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 "options.h" +#include "packet.h" +#include "errors.h" +#include "keydb.h" +#include "memory.h" +#include "util.h" +#include "trustdb.h" +#include "main.h" +#include "i18n.h" +#include "ttyio.h" +#include "status.h" +#include "keyserver-internal.h" + +struct stats_s { + ulong count; + ulong no_user_id; + ulong imported; + ulong imported_rsa; + ulong n_uids; + ulong n_sigs; + ulong n_subk; + ulong unchanged; + ulong n_revoc; + ulong secret_read; + ulong secret_imported; + ulong secret_dups; + ulong skipped_new_keys; + ulong not_imported; +}; + + +static int import( IOBUF inp, const char* fname, + struct stats_s *stats, unsigned int options ); +static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); +static void revocation_present(KBNODE keyblock); +static int import_one( const char *fname, KBNODE keyblock, + struct stats_s *stats, unsigned int options); +static int import_secret_one( const char *fname, KBNODE keyblock, + struct stats_s *stats, unsigned int options); +static int import_revoke_cert( const char *fname, KBNODE node, + struct stats_s *stats); +static int chk_self_sigs( const char *fname, KBNODE keyblock, + PKT_public_key *pk, u32 *keyid, int *non_self ); +static int delete_inv_parts( const char *fname, KBNODE keyblock, + u32 *keyid, unsigned int options ); +static int merge_blocks( const char *fname, KBNODE keyblock_orig, + KBNODE keyblock, u32 *keyid, + int *n_uids, int *n_sigs, int *n_subk ); +static int append_uid( KBNODE keyblock, KBNODE node, int *n_sigs, + const char *fname, u32 *keyid ); +static int append_key( KBNODE keyblock, KBNODE node, int *n_sigs, + const char *fname, u32 *keyid ); +static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, + const char *fname, u32 *keyid ); +static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, + const char *fname, u32 *keyid ); + +int +parse_import_options(char *str,unsigned int *options) +{ + struct parse_options import_opts[]= + { + {"allow-local-sigs",IMPORT_ALLOW_LOCAL_SIGS}, + {"repair-hkp-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG}, + {"repair-pks-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG}, + {"fast-import",IMPORT_FAST_IMPORT}, + {"convert-sk-to-pk",IMPORT_SK2PK}, + {NULL,0} + }; + + return parse_options(str,options,import_opts); +} + +void * +import_new_stats_handle (void) +{ + return m_alloc_clear ( sizeof (struct stats_s) ); +} + +void +import_release_stats_handle (void *p) +{ + m_free (p); +} + +/**************** + * Import the public keys from the given filename. Input may be armored. + * This function rejects all keys which are not validly self signed on at + * least one userid. Only user ids which are self signed will be imported. + * Other signatures are not checked. + * + * Actually this function does a merge. It works like this: + * + * - get the keyblock + * - check self-signatures and remove all userids and their signatures + * without/invalid self-signatures. + * - reject the keyblock, if we have no valid userid. + * - See whether we have this key already in one of our pubrings. + * If not, simply add it to the default keyring. + * - Compare the key and the self-signatures of the new and the one in + * our keyring. If they are different something weird is going on; + * ask what to do. + * - See whether we have only non-self-signature on one user id; if not + * ask the user what to do. + * - compare the signatures: If we already have this signature, check + * that they compare okay; if not, issue a warning and ask the user. + * (consider looking at the timestamp and use the newest?) + * - Simply add the signature. Can't verify here because we may not have + * the signature's public key yet; verification is done when putting it + * into the trustdb, which is done automagically as soon as this pubkey + * is used. + * - Proceed with next signature. + * + * Key revocation certificates have special handling. + * + */ +static int +import_keys_internal( IOBUF inp, char **fnames, int nnames, + void *stats_handle, unsigned int options ) +{ + int i, rc = 0; + struct stats_s *stats = stats_handle; + + if (!stats) + stats = import_new_stats_handle (); + + if (inp) { + rc = import( inp, "[stream]", stats, options); + } + else { + if( !fnames && !nnames ) + nnames = 1; /* Ohh what a ugly hack to jump into the loop */ + + for(i=0; i < nnames; i++ ) { + const char *fname = fnames? fnames[i] : NULL; + IOBUF inp2 = iobuf_open(fname); + if( !fname ) + fname = "[stdin]"; + if( !inp2 ) + log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); + else { + rc = import( inp2, fname, stats, options ); + iobuf_close(inp2); + if( rc ) + log_error("import from `%s' failed: %s\n", fname, + g10_errstr(rc) ); + } + if( !fname ) + break; + } + } + if (!stats_handle) { + import_print_stats (stats); + import_release_stats_handle (stats); + } + /* If no fast import and the trustdb is dirty (i.e. we added a key + or userID that had something other than a selfsig, a signature + that was other than a selfsig, or any revocation), then + update/check the trustdb if the user specified by setting + interactive or by not setting no-auto-check-trustdb */ + if (!(options&IMPORT_FAST_IMPORT) && trustdb_pending_check()) + { + if (opt.interactive) + update_trustdb(); + else if (!opt.no_auto_check_trustdb) + check_trustdb(); + } + + return rc; +} + +void +import_keys( char **fnames, int nnames, + void *stats_handle, unsigned int options ) +{ + import_keys_internal( NULL, fnames, nnames, stats_handle, options); +} + +int +import_keys_stream( IOBUF inp, void *stats_handle, unsigned int options ) +{ + return import_keys_internal( inp, NULL, 0, stats_handle, options); +} + +static int +import( IOBUF inp, const char* fname, + struct stats_s *stats, unsigned int options ) +{ + PACKET *pending_pkt = NULL; + KBNODE keyblock; + int rc = 0; + + getkey_disable_caches(); + + if( !opt.no_armor ) { /* armored reading is not disabled */ + armor_filter_context_t *afx = m_alloc_clear( sizeof *afx ); + afx->only_keyblocks = 1; + iobuf_push_filter2( inp, armor_filter, afx, 1 ); + } + + while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { + if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) + rc = import_one( fname, keyblock, stats, options ); + else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) + rc = import_secret_one( fname, keyblock, stats, options ); + else if( keyblock->pkt->pkttype == PKT_SIGNATURE + && keyblock->pkt->pkt.signature->sig_class == 0x20 ) + rc = import_revoke_cert( fname, keyblock, stats ); + else { + log_info( _("skipping block of type %d\n"), + keyblock->pkt->pkttype ); + } + release_kbnode(keyblock); + /* fixme: we should increment the not imported counter but this + does only make sense if we keep on going despite of errors. */ + if( rc ) + break; + if( !(++stats->count % 100) && !opt.quiet ) + log_info(_("%lu keys processed so far\n"), stats->count ); + } + if( rc == -1 ) + rc = 0; + else if( rc && rc != G10ERR_INV_KEYRING ) + log_error( _("error reading `%s': %s\n"), fname, g10_errstr(rc)); + + return rc; +} + + +void +import_print_stats (void *hd) +{ + struct stats_s *stats = hd; + + if( !opt.quiet ) { + log_info(_("Total number processed: %lu\n"), stats->count ); + if( stats->skipped_new_keys ) + log_info(_(" skipped new keys: %lu\n"), + stats->skipped_new_keys ); + if( stats->no_user_id ) + log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id ); + if( stats->imported || stats->imported_rsa ) { + log_info(_(" imported: %lu"), stats->imported ); + if( stats->imported_rsa ) + fprintf(stderr, " (RSA: %lu)", stats->imported_rsa ); + putc('\n', stderr); + } + if( stats->unchanged ) + log_info(_(" unchanged: %lu\n"), stats->unchanged ); + if( stats->n_uids ) + log_info(_(" new user IDs: %lu\n"), stats->n_uids ); + if( stats->n_subk ) + log_info(_(" new subkeys: %lu\n"), stats->n_subk ); + if( stats->n_sigs ) + log_info(_(" new signatures: %lu\n"), stats->n_sigs ); + if( stats->n_revoc ) + log_info(_(" new key revocations: %lu\n"), stats->n_revoc ); + if( stats->secret_read ) + log_info(_(" secret keys read: %lu\n"), stats->secret_read ); + if( stats->secret_imported ) + log_info(_(" secret keys imported: %lu\n"), stats->secret_imported ); + if( stats->secret_dups ) + log_info(_(" secret keys unchanged: %lu\n"), stats->secret_dups ); + if( stats->not_imported ) + log_info(_(" not imported: %lu\n"), stats->not_imported ); + } + + if( is_status_enabled() ) { + char buf[14*20]; + sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + stats->count, + stats->no_user_id, + stats->imported, + stats->imported_rsa, + stats->unchanged, + stats->n_uids, + stats->n_subk, + stats->n_sigs, + stats->n_revoc, + stats->secret_read, + stats->secret_imported, + stats->secret_dups, + stats->skipped_new_keys, + stats->not_imported ); + write_status_text( STATUS_IMPORT_RES, buf ); + } +} + + +/**************** + * Read the next keyblock from stream A. + * PENDING_PKT should be initialzed to NULL + * and not chnaged form the caller. + * Retunr: 0 = okay, -1 no more blocks or another errorcode. + */ +static int +read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) +{ + int rc; + PACKET *pkt; + KBNODE root = NULL; + int in_cert; + + if( *pending_pkt ) { + root = new_kbnode( *pending_pkt ); + *pending_pkt = NULL; + in_cert = 1; + } + else + in_cert = 0; + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + while( (rc=parse_packet(a, pkt)) != -1 ) { + if( rc ) { /* ignore errors */ + if( rc != G10ERR_UNKNOWN_PACKET ) { + log_error("read_block: read error: %s\n", g10_errstr(rc) ); + rc = G10ERR_INV_KEYRING; + goto ready; + } + free_packet( pkt ); + init_packet(pkt); + continue; + } + + if( !root && pkt->pkttype == PKT_SIGNATURE + && pkt->pkt.signature->sig_class == 0x20 ) { + /* this is a revocation certificate which is handled + * in a special way */ + root = new_kbnode( pkt ); + pkt = NULL; + goto ready; + } + + /* make a linked list of all packets */ + switch( pkt->pkttype ) { + case PKT_COMPRESSED: + if( pkt->pkt.compressed->algorithm < 1 + || pkt->pkt.compressed->algorithm > 2 ) { + rc = G10ERR_COMPR_ALGO; + goto ready; + } + { + compress_filter_context_t *cfx = m_alloc_clear( sizeof *cfx ); + cfx->algo = pkt->pkt.compressed->algorithm; + pkt->pkt.compressed->buf = NULL; + iobuf_push_filter2( a, compress_filter, cfx, 1 ); + } + free_packet( pkt ); + init_packet(pkt); + break; + + case PKT_RING_TRUST: + /* skip those packets */ + free_packet( pkt ); + init_packet(pkt); + break; + + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + if( in_cert ) { /* store this packet */ + *pending_pkt = pkt; + pkt = NULL; + goto ready; + } + in_cert = 1; + default: + if( in_cert ) { + if( !root ) + root = new_kbnode( pkt ); + else + add_kbnode( root, new_kbnode( pkt ) ); + pkt = m_alloc( sizeof *pkt ); + } + init_packet(pkt); + break; + } + } + ready: + if( rc == -1 && root ) + rc = 0; + + if( rc ) + release_kbnode( root ); + else + *ret_root = root; + free_packet( pkt ); + m_free( pkt ); + return rc; +} + +/* Walk through the subkeys on a pk to find if we have the PKS + disease: multiple subkeys with their binding sigs stripped, and the + sig for the first subkey placed after the last subkey. That is, + instead of "pk uid sig sub1 bind1 sub2 bind2 sub3 bind3" we have + "pk uid sig sub1 sub2 sub3 bind1". We can't do anything about sub2 + and sub3, as they are already lost, but we can try and rescue sub1 + by reordering the keyblock so that it reads "pk uid sig sub1 bind1 + sub2 sub3". Returns TRUE if the keyblock was modified. */ + +static int +fix_pks_corruption(KBNODE keyblock) +{ + int changed=0,keycount=0; + KBNODE node,last=NULL,sknode=NULL; + + /* First determine if we have the problem at all. Look for 2 or + more subkeys in a row, followed by a single binding sig. */ + for(node=keyblock;node;last=node,node=node->next) + { + if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY) + { + keycount++; + if(!sknode) + sknode=node; + } + else if(node->pkt->pkttype==PKT_SIGNATURE && + node->pkt->pkt.signature->sig_class==0x18 && + keycount>=2 && node->next==NULL) + { + /* We might have the problem, as this key has two subkeys in + a row without any intervening packets. */ + + /* Sanity check */ + if(last==NULL) + break; + + /* Temporarily attach node to sknode. */ + node->next=sknode->next; + sknode->next=node; + last->next=NULL; + + /* Note we aren't checking whether this binding sig is a + selfsig. This is not necessary here as the subkey and + binding sig will be rejected later if that is the + case. */ + if(check_key_signature(keyblock,node,NULL)) + { + /* Not a match, so undo the changes. */ + sknode->next=node->next; + last->next=node; + node->next=NULL; + break; + } + else + { + sknode->flag |= 1; /* Mark it good so we don't need to + check it again */ + changed=1; + break; + } + } + else + keycount=0; + } + + return changed; +} + + +static void +print_import_ok (PKT_public_key *pk, PKT_secret_key *sk, unsigned int reason) +{ + byte array[MAX_FINGERPRINT_LEN], *s; + char buf[MAX_FINGERPRINT_LEN*2+30], *p; + size_t i, n; + + sprintf (buf, "%u ", reason); + p = buf + strlen (buf); + + if (pk) + fingerprint_from_pk (pk, array, &n); + else + fingerprint_from_sk (sk, array, &n); + s = array; + for (i=0; i < n ; i++, s++, p += 2) + sprintf (p, "%02X", *s); + + write_status_text (STATUS_IMPORT_OK, buf); +} + +void +print_import_check (PKT_public_key * pk, PKT_user_id * id) +{ + char * buf; + byte fpr[24]; + u32 keyid[2]; + size_t i, pos = 0, n; + + buf = m_alloc (17+41+id->len+32); + keyid_from_pk (pk, keyid); + sprintf (buf, "%08X%08X ", keyid[0], keyid[1]); + pos = 17; + fingerprint_from_pk (pk, fpr, &n); + for (i = 0; i < n; i++, pos += 2) + sprintf (buf+pos, "%02X", fpr[i]); + strcat (buf, " "); + pos += 1; + strcat (buf, id->name); + write_status_text (STATUS_IMPORT_CHECK, buf); + m_free (buf); +} + +/**************** + * Try to import one keyblock. Return an error only in serious cases, but + * never for an invalid keyblock. It uses log_error to increase the + * internal errorcount, so that invalid input can be detected by programs + * which called g10. + */ +static int +import_one( const char *fname, KBNODE keyblock, + struct stats_s *stats, unsigned int options ) +{ + PKT_public_key *pk; + PKT_public_key *pk_orig; + KBNODE node, uidnode; + KBNODE keyblock_orig = NULL; + u32 keyid[2]; + int rc = 0; + int new_key = 0; + int mod_key = 0; + int non_self = 0; + + /* get the key and print some info about it */ + node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); + if( !node ) + BUG(); + + pk = node->pkt->pkt.public_key; + keyid_from_pk( pk, keyid ); + uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); + + if(pk->pubkey_algo==PUBKEY_ALGO_ELGAMAL) + log_info(_("NOTE: Elgamal primary key detected - " + "this may take some time to import\n")); + + if( opt.verbose && !opt.interactive ) { + log_info( "pub %4u%c/%08lX %s ", + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + (ulong)keyid[1], datestr_from_pk(pk) ); + if( uidnode ) + print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len ); + putc('\n', stderr); + } + if( !uidnode ) { + log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]); + return 0; + } + + if (opt.interactive) { + if(is_status_enabled()) + print_import_check (pk, uidnode->pkt->pkt.user_id); + merge_keys_and_selfsig (keyblock); + tty_printf ("\n"); + show_basic_key_info (keyblock); + tty_printf ("\n"); + if (!cpr_get_answer_is_yes ("import.okay", + "Do you want to import this key? (y/N) ")) + return 0; + } + + clear_kbnode_flags( keyblock ); + + if((options&IMPORT_REPAIR_PKS_SUBKEY_BUG) && fix_pks_corruption(keyblock)) + log_info(_("key %08lX: PKS subkey corruption repaired\n"), + (ulong)keyid[1]); + + rc = chk_self_sigs( fname, keyblock , pk, keyid, &non_self ); + if( rc ) + return rc== -1? 0:rc; + + /* If we allow such a thing, mark unsigned uids as valid */ + if( opt.allow_non_selfsigned_uid ) + for( node=keyblock; node; node = node->next ) + if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) ) + { + char *user=utf8_to_native(node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len,0); + node->flag |= 1; + log_info( _("key %08lX: accepted non self-signed user ID '%s'\n"), + (ulong)keyid[1],user); + m_free(user); + } + + if( !delete_inv_parts( fname, keyblock, keyid, options ) ) { + if( !opt.quiet ) { + log_info( _("key %08lX: no valid user IDs\n"), + (ulong)keyid[1]); + log_info(_("this may be caused by a missing self-signature\n")); + } + stats->no_user_id++; + return 0; + } + + /* do we have this key already in one of our pubrings ? */ + pk_orig = m_alloc_clear( sizeof *pk_orig ); + rc = get_pubkey_fast ( pk_orig, keyid ); + if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY ) { + log_error( _("key %08lX: public key not found: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + } + else if ( rc && opt.merge_only ) { + if( opt.verbose ) + log_info( _("key %08lX: new key - skipped\n"), (ulong)keyid[1] ); + rc = 0; + stats->skipped_new_keys++; + } + else if( rc ) { /* insert this key */ + KEYDB_HANDLE hd = keydb_new (0); + + rc = keydb_locate_writable (hd, NULL); + if (rc) { + log_error (_("no writable keyring found: %s\n"), g10_errstr (rc)); + keydb_release (hd); + return G10ERR_GENERAL; + } + if( opt.verbose > 1 ) + log_info (_("writing to `%s'\n"), keydb_get_resource_name (hd) ); + rc = keydb_insert_keyblock (hd, keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc)); + else + { + /* This should not be possible since we delete the + ownertrust when a key is deleted, but it can happen if + the keyring and trustdb are out of sync. It can also + be made to happen with the trusted-key command. */ + + clear_ownertrusts (pk); + if(non_self) + revalidation_mark (); + } + keydb_release (hd); + + /* we are ready */ + if( !opt.quiet ) { + char *p=get_user_id_printable (keyid); + log_info( _("key %08lX: public key \"%s\" imported\n"), + (ulong)keyid[1],p); + m_free(p); + } + if( is_status_enabled() ) { + char *us = get_long_user_id_string( keyid ); + write_status_text( STATUS_IMPORTED, us ); + m_free(us); + print_import_ok (pk,NULL, 1); + } + stats->imported++; + if( is_RSA( pk->pubkey_algo ) ) + stats->imported_rsa++; + new_key = 1; + } + else { /* merge */ + KEYDB_HANDLE hd; + int n_uids, n_sigs, n_subk; + + /* Compare the original against the new key; just to be sure nothing + * weird is going on */ + if( cmp_public_keys( pk_orig, pk ) ) { + log_error( _("key %08lX: doesn't match our copy\n"), + (ulong)keyid[1]); + goto leave; + } + + /* now read the original keyblock */ + hd = keydb_new (0); + { + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk (pk_orig, afp, &an); + while (an < MAX_FINGERPRINT_LEN) + afp[an++] = 0; + rc = keydb_search_fpr (hd, afp); + } + if( rc ) { + log_error (_("key %08lX: can't locate original keyblock: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + keydb_release (hd); + goto leave; + } + rc = keydb_get_keyblock (hd, &keyblock_orig ); + if (rc) { + log_error (_("key %08lX: can't read original keyblock: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + keydb_release (hd); + goto leave; + } + + collapse_uids( &keyblock ); + /* and try to merge the block */ + clear_kbnode_flags( keyblock_orig ); + clear_kbnode_flags( keyblock ); + n_uids = n_sigs = n_subk = 0; + rc = merge_blocks( fname, keyblock_orig, keyblock, + keyid, &n_uids, &n_sigs, &n_subk ); + if( rc ) { + keydb_release (hd); + goto leave; + } + if( n_uids || n_sigs || n_subk ) { + mod_key = 1; + /* keyblock_orig has been updated; write */ + rc = keydb_update_keyblock (hd, keyblock_orig); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + else if(non_self) + revalidation_mark (); + + /* we are ready */ + if( !opt.quiet ) { + char *p=get_user_id_printable(keyid); + if( n_uids == 1 ) + log_info( _("key %08lX: \"%s\" 1 new user ID\n"), + (ulong)keyid[1], p); + else if( n_uids ) + log_info( _("key %08lX: \"%s\" %d new user IDs\n"), + (ulong)keyid[1], p, n_uids ); + if( n_sigs == 1 ) + log_info( _("key %08lX: \"%s\" 1 new signature\n"), + (ulong)keyid[1], p); + else if( n_sigs ) + log_info( _("key %08lX: \"%s\" %d new signatures\n"), + (ulong)keyid[1], p, n_sigs ); + if( n_subk == 1 ) + log_info( _("key %08lX: \"%s\" 1 new subkey\n"), + (ulong)keyid[1], p); + else if( n_subk ) + log_info( _("key %08lX: \"%s\" %d new subkeys\n"), + (ulong)keyid[1], p, n_subk ); + m_free(p); + } + + stats->n_uids +=n_uids; + stats->n_sigs +=n_sigs; + stats->n_subk +=n_subk; + + if (is_status_enabled ()) + print_import_ok (pk, NULL, + ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0))); + } + else { + if (is_status_enabled ()) + print_import_ok (pk, NULL, 0); + + if( !opt.quiet ) { + char *p=get_user_id_printable(keyid); + log_info( _("key %08lX: \"%s\" not changed\n"), + (ulong)keyid[1],p); + m_free(p); + } + stats->unchanged++; + } + keydb_release (hd); hd = NULL; + } + + leave: + release_kbnode( keyblock_orig ); + free_public_key( pk_orig ); + + revocation_present(keyblock); + + return rc; +} + +/* Walk a secret keyblock and produce a public keyblock out of it. */ +static KBNODE +sec_to_pub_keyblock(KBNODE sec_keyblock) +{ + KBNODE secnode,pub_keyblock=NULL,ctx=NULL; + + while((secnode=walk_kbnode(sec_keyblock,&ctx,0))) + { + KBNODE pubnode; + + if(secnode->pkt->pkttype==PKT_SECRET_KEY || + secnode->pkt->pkttype==PKT_SECRET_SUBKEY) + { + /* Make a public key. We only need to convert enough to + write the keyblock out. */ + + PKT_secret_key *sk=secnode->pkt->pkt.secret_key; + PACKET *pkt=m_alloc_clear(sizeof(PACKET)); + PKT_public_key *pk=m_alloc_clear(sizeof(PKT_public_key)); + int n; + + if(secnode->pkt->pkttype==PKT_SECRET_KEY) + pkt->pkttype=PKT_PUBLIC_KEY; + else + pkt->pkttype=PKT_PUBLIC_SUBKEY; + + pkt->pkt.public_key=pk; + + pk->version=sk->version; + pk->timestamp=sk->timestamp; + pk->expiredate=sk->expiredate; + pk->pubkey_algo=sk->pubkey_algo; + + n=pubkey_get_npkey(pk->pubkey_algo); + if(n==0) + pk->pkey[0]=mpi_copy(sk->skey[0]); + else + { + int i; + + for(i=0;i<n;i++) + pk->pkey[i]=mpi_copy(sk->skey[i]); + } + + pubnode=new_kbnode(pkt); + } + else + { + pubnode=clone_kbnode(secnode); + } + + if(pub_keyblock==NULL) + pub_keyblock=pubnode; + else + add_kbnode(pub_keyblock,pubnode); + } + + return pub_keyblock; +} + +/**************** + * Ditto for secret keys. Handling is simpler than for public keys. + * We allow secret key importing only when allow is true, this is so + * that a secret key can not be imported accidently and thereby tampering + * with the trust calculation. + */ +static int +import_secret_one( const char *fname, KBNODE keyblock, + struct stats_s *stats, unsigned int options) +{ + PKT_secret_key *sk; + KBNODE node, uidnode; + u32 keyid[2]; + int rc = 0; + + /* get the key and print some info about it */ + node = find_kbnode( keyblock, PKT_SECRET_KEY ); + if( !node ) + BUG(); + + sk = node->pkt->pkt.secret_key; + keyid_from_sk( sk, keyid ); + uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); + + if( opt.verbose ) { + log_info( "sec %4u%c/%08lX %s ", + nbits_from_sk( sk ), + pubkey_letter( sk->pubkey_algo ), + (ulong)keyid[1], datestr_from_sk(sk) ); + if( uidnode ) + print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len ); + putc('\n', stderr); + } + stats->secret_read++; + + if( !uidnode ) { + log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]); + return 0; + } + + if(sk->protect.algo>110) + { + log_error(_("key %08lX: secret key with invalid cipher %d " + "- skipped\n"),(ulong)keyid[1],sk->protect.algo); + return 0; + } + + clear_kbnode_flags( keyblock ); + + /* do we have this key already in one of our secrings ? */ + rc = seckey_available( keyid ); + if( rc == G10ERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */ + KEYDB_HANDLE hd = keydb_new (1); + + /* get default resource */ + rc = keydb_locate_writable (hd, NULL); + if (rc) { + log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); + keydb_release (hd); + return G10ERR_GENERAL; + } + rc = keydb_insert_keyblock (hd, keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + keydb_release (hd); + /* we are ready */ + if( !opt.quiet ) + log_info( _("key %08lX: secret key imported\n"), (ulong)keyid[1]); + stats->secret_imported++; + if (is_status_enabled ()) + print_import_ok (NULL, sk, 1|16); + + if(options&IMPORT_SK2PK) + { + /* Try and make a public key out of this. */ + + KBNODE pub_keyblock=sec_to_pub_keyblock(keyblock); + import_one(fname,pub_keyblock,stats,opt.import_options); + release_kbnode(pub_keyblock); + } + + } + else if( !rc ) { /* we can't merge secret keys */ + log_error( _("key %08lX: already in secret keyring\n"), + (ulong)keyid[1]); + stats->secret_dups++; + if (is_status_enabled ()) + print_import_ok (NULL, sk, 16); + + /* TODO: if we ever do merge secret keys, make sure to handle + the sec_to_pub_keyblock feature as well. */ + } + else + log_error( _("key %08lX: secret key not found: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + + return rc; +} + + +/**************** + * Import a revocation certificate; this is a single signature packet. + */ +static int +import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) +{ + PKT_public_key *pk=NULL; + KBNODE onode, keyblock = NULL; + KEYDB_HANDLE hd = NULL; + u32 keyid[2]; + int rc = 0; + + assert( !node->next ); + assert( node->pkt->pkttype == PKT_SIGNATURE ); + assert( node->pkt->pkt.signature->sig_class == 0x20 ); + + keyid[0] = node->pkt->pkt.signature->keyid[0]; + keyid[1] = node->pkt->pkt.signature->keyid[1]; + + pk = m_alloc_clear( sizeof *pk ); + rc = get_pubkey( pk, keyid ); + if( rc == G10ERR_NO_PUBKEY ) { + log_info( _("key %08lX: no public key - " + "can't apply revocation certificate\n"), (ulong)keyid[1]); + rc = 0; + goto leave; + } + else if( rc ) { + log_error( _("key %08lX: public key not found: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + goto leave; + } + + /* read the original keyblock */ + hd = keydb_new (0); + { + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk (pk, afp, &an); + while (an < MAX_FINGERPRINT_LEN) + afp[an++] = 0; + rc = keydb_search_fpr (hd, afp); + } + if (rc) { + log_error (_("key %08lX: can't locate original keyblock: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + goto leave; + } + rc = keydb_get_keyblock (hd, &keyblock ); + if (rc) { + log_error (_("key %08lX: can't read original keyblock: %s\n"), + (ulong)keyid[1], g10_errstr(rc)); + goto leave; + } + + + /* it is okay, that node is not in keyblock because + * check_key_signature works fine for sig_class 0x20 in this + * special case. */ + rc = check_key_signature( keyblock, node, NULL); + if( rc ) { + log_error( _("key %08lX: invalid revocation certificate" + ": %s - rejected\n"), (ulong)keyid[1], g10_errstr(rc)); + goto leave; + } + + + /* check whether we already have this */ + for(onode=keyblock->next; onode; onode=onode->next ) { + if( onode->pkt->pkttype == PKT_USER_ID ) + break; + else if( onode->pkt->pkttype == PKT_SIGNATURE + && onode->pkt->pkt.signature->sig_class == 0x20 + && keyid[0] == onode->pkt->pkt.signature->keyid[0] + && keyid[1] == onode->pkt->pkt.signature->keyid[1] ) { + rc = 0; + goto leave; /* yes, we already know about it */ + } + } + + + /* insert it */ + insert_kbnode( keyblock, clone_kbnode(node), 0 ); + + /* and write the keyblock back */ + rc = keydb_update_keyblock (hd, keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + keydb_release (hd); hd = NULL; + /* we are ready */ + if( !opt.quiet ) { + char *p=get_user_id_printable (keyid); + log_info( _("key %08lX: \"%s\" revocation certificate imported\n"), + (ulong)keyid[1],p); + m_free(p); + } + stats->n_revoc++; + + /* If the key we just revoked was ultimately trusted, remove its + ultimate trust. This doesn't stop the user from putting the + ultimate trust back, but is a reasonable solution for now. */ + if(get_ownertrust(pk)==TRUST_ULTIMATE) + clear_ownertrusts(pk); + + revalidation_mark (); + + leave: + keydb_release (hd); + release_kbnode( keyblock ); + free_public_key( pk ); + return rc; +} + + +/**************** + * loop over the keyblock and check all self signatures. + * Mark all user-ids with a self-signature by setting flag bit 0. + * Mark all user-ids with an invalid self-signature by setting bit 1. + * This works also for subkeys, here the subkey is marked. Invalid or + * extra subkey sigs (binding or revocation) are marked for deletion. + * non_self is set to true if there are any sigs other than self-sigs + * in this keyblock. + */ +static int +chk_self_sigs( const char *fname, KBNODE keyblock, + PKT_public_key *pk, u32 *keyid, int *non_self ) +{ + KBNODE n,knode=NULL; + PKT_signature *sig; + int rc; + u32 bsdate=0,rsdate=0; + KBNODE bsnode=NULL,rsnode=NULL; + + for( n=keyblock; (n = find_next_kbnode(n, 0)); ) { + if(n->pkt->pkttype==PKT_PUBLIC_SUBKEY) + { + knode=n; + bsdate=0; + rsdate=0; + bsnode=NULL; + rsnode=NULL; + continue; + } + else if( n->pkt->pkttype != PKT_SIGNATURE ) + continue; + sig = n->pkt->pkt.signature; + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { + + /* This just caches the sigs for later use. That way we + import a fully-cached key which speeds things up. */ + if(!opt.no_sig_cache) + check_key_signature(keyblock,n,NULL); + + if( (sig->sig_class&~3) == 0x10 ) { + KBNODE unode = find_prev_kbnode( keyblock, n, PKT_USER_ID ); + if( !unode ) { + log_error( _("key %08lX: no user ID for signature\n"), + (ulong)keyid[1]); + return -1; /* the complete keyblock is invalid */ + } + + /* If it hasn't been marked valid yet, keep trying */ + if(!(unode->flag&1)) { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) + { + char *p=utf8_to_native(unode->pkt->pkt.user_id->name, + strlen(unode->pkt->pkt.user_id->name),0); + log_info( rc == G10ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key " + "algorithm on user id \"%s\"\n"): + _("key %08lX: invalid self-signature " + "on user id \"%s\"\n"), + (ulong)keyid[1],p); + m_free(p); + } + else + unode->flag |= 1; /* mark that signature checked */ + } + } + else if( sig->sig_class == 0x18 ) { + /* Note that this works based solely on the timestamps + like the rest of gpg. If the standard gets + revocation targets, this may need to be revised. */ + + if( !knode ) { + log_info( _("key %08lX: no subkey for subkey " + "binding signature\n"),(ulong)keyid[1]); + n->flag |= 4; /* delete this */ + } + else { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) { + log_info( rc == G10ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key algorithm\n"): + _("key %08lX: invalid subkey binding\n"), + (ulong)keyid[1]); + n->flag|=4; + } + else { + /* It's valid, so is it newer? */ + if(sig->timestamp>=bsdate) { + knode->flag |= 1; /* the subkey is valid */ + if(bsnode) { + bsnode->flag|=4; /* Delete the last binding + sig since this one is + newer */ + log_info(_("key %08lX: removed multiple subkey " + "binding\n"),(ulong)keyid[1]); + } + + bsnode=n; + bsdate=sig->timestamp; + } + else + n->flag|=4; /* older */ + } + } + } + else if( sig->sig_class == 0x28 ) { + /* We don't actually mark the subkey as revoked right + now, so just check that the revocation sig is the + most recent valid one. Note that we don't care if + the binding sig is newer than the revocation sig. + See the comment in getkey.c:merge_selfsigs_subkey for + more */ + if( !knode ) { + log_info( _("key %08lX: no subkey for subkey " + "revocation signature\n"),(ulong)keyid[1]); + n->flag |= 4; /* delete this */ + } + else { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) { + log_info( rc == G10ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key algorithm\n"): + _("key %08lX: invalid subkey revocation\n"), + (ulong)keyid[1]); + n->flag|=4; + } + else { + /* It's valid, so is it newer? */ + if(sig->timestamp>=rsdate) { + if(rsnode) { + rsnode->flag|=4; /* Delete the last revocation + sig since this one is + newer */ + log_info(_("key %08lX: removed multiple subkey " + "revocation signatures\n"),(ulong)keyid[1]); + } + + rsnode=n; + rsdate=sig->timestamp; + } + else + n->flag|=4; /* older */ + } + } + } + } + else + *non_self=1; + } + + return 0; +} + +/**************** + * delete all parts which are invalid and those signatures whose + * public key algorithm is not available in this implemenation; + * but consider RSA as valid, because parse/build_packets knows + * about it. + * returns: true if at least one valid user-id is left over. + */ +static int +delete_inv_parts( const char *fname, KBNODE keyblock, + u32 *keyid, unsigned int options) +{ + KBNODE node; + int nvalid=0, uid_seen=0, subkey_seen=0; + + for(node=keyblock->next; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + uid_seen = 1; + if( (node->flag & 2) || !(node->flag & 1) ) { + if( opt.verbose ) { + log_info( _("key %08lX: skipped user ID '"), + (ulong)keyid[1]); + print_utf8_string( stderr, node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len ); + fputs("'\n", stderr ); + } + delete_kbnode( node ); /* the user-id */ + /* and all following packets up to the next user-id */ + while( node->next + && node->next->pkt->pkttype != PKT_USER_ID + && node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY + && node->next->pkt->pkttype != PKT_SECRET_SUBKEY ){ + delete_kbnode( node->next ); + node = node->next; + } + } + else + nvalid++; + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + if( (node->flag & 2) || !(node->flag & 1) ) { + if( opt.verbose ) { + log_info( _("key %08lX: skipped subkey\n"), + (ulong)keyid[1]); + } + delete_kbnode( node ); /* the subkey */ + /* and all following signature packets */ + while( node->next + && node->next->pkt->pkttype == PKT_SIGNATURE ) { + delete_kbnode( node->next ); + node = node->next; + } + } + else + subkey_seen = 1; + } + else if( node->pkt->pkttype == PKT_SIGNATURE + && check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo) + && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA ) + delete_kbnode( node ); /* build_packet() can't handle this */ + else if( node->pkt->pkttype == PKT_SIGNATURE && + !node->pkt->pkt.signature->flags.exportable && + !(options&IMPORT_ALLOW_LOCAL_SIGS) && + seckey_available( node->pkt->pkt.signature->keyid ) ) { + /* here we violate the rfc a bit by still allowing + * to import non-exportable signature when we have the + * the secret key used to create this signature - it + * seems that this makes sense */ + log_info( _("key %08lX: non exportable signature " + "(class %02x) - skipped\n"), + (ulong)keyid[1], + node->pkt->pkt.signature->sig_class ); + delete_kbnode( node ); + } + else if( node->pkt->pkttype == PKT_SIGNATURE + && node->pkt->pkt.signature->sig_class == 0x20 ) { + if( uid_seen ) { + log_error( _("key %08lX: revocation certificate " + "at wrong place - skipped\n"), + (ulong)keyid[1]); + delete_kbnode( node ); + } + else { + /* If the revocation cert is from a different key than + the one we're working on don't check it - it's + probably from a revocation key and won't be + verifiable with this key anyway. */ + + if(node->pkt->pkt.signature->keyid[0]==keyid[0] && + node->pkt->pkt.signature->keyid[1]==keyid[1]) + { + int rc = check_key_signature( keyblock, node, NULL); + if( rc ) + { + log_error( _("key %08lX: invalid revocation " + "certificate: %s - skipped\n"), + (ulong)keyid[1], g10_errstr(rc)); + delete_kbnode( node ); + } + } + } + } + else if( node->pkt->pkttype == PKT_SIGNATURE && + (node->pkt->pkt.signature->sig_class == 0x18 || + node->pkt->pkt.signature->sig_class == 0x28) && + !subkey_seen ) { + log_error( _("key %08lX: subkey signature " + "in wrong place - skipped\n"), + (ulong)keyid[1]); + delete_kbnode( node ); + } + else if( node->pkt->pkttype == PKT_SIGNATURE + && !IS_CERT(node->pkt->pkt.signature)) + { + log_error(_("key %08lX: unexpected signature class (0x%02X) -" + " skipped\n"),(ulong)keyid[1], + node->pkt->pkt.signature->sig_class); + delete_kbnode(node); + } + else if( (node->flag & 4) ) /* marked for deletion */ + delete_kbnode( node ); + } + + /* note: because keyblock is the public key, it is never marked + * for deletion and so keyblock cannot change */ + commit_kbnode( &keyblock ); + return nvalid; +} + + +/**************** + * It may happen that the imported keyblock has duplicated user IDs. + * We check this here and collapse those user IDs together with their + * sigs into one. + * Returns: True if the keyblock hash changed. + */ +int +collapse_uids( KBNODE *keyblock ) +{ + KBNODE n, n2; + int in_uid; + int any=0; + u32 kid1; + + restart: + for( n = *keyblock; n; n = n->next ) { + if( n->pkt->pkttype != PKT_USER_ID ) + continue; + for( n2 = n->next; n2; n2 = n2->next ) { + if( n2->pkt->pkttype == PKT_USER_ID + && !cmp_user_ids( n->pkt->pkt.user_id, + n2->pkt->pkt.user_id ) ) { + /* found a duplicate */ + any = 1; + if( !n2->next + || n2->next->pkt->pkttype == PKT_USER_ID + || n2->next->pkt->pkttype == PKT_PUBLIC_SUBKEY + || n2->next->pkt->pkttype == PKT_SECRET_SUBKEY ) { + /* no more signatures: delete the user ID + * and start over */ + remove_kbnode( keyblock, n2 ); + } + else { + /* The simple approach: Move one signature and + * then start over to delete the next one :-( */ + move_kbnode( keyblock, n2->next, n->next ); + } + goto restart; + } + } + } + if( !any ) + return 0; + + restart_sig: + /* now we may have duplicate signatures on one user ID: fix this */ + for( in_uid = 0, n = *keyblock; n; n = n->next ) { + if( n->pkt->pkttype == PKT_USER_ID ) + in_uid = 1; + else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY + || n->pkt->pkttype == PKT_SECRET_SUBKEY ) + in_uid = 0; + else if( in_uid ) { + n2 = n; + do { + KBNODE ncmp = NULL; + for( ; n2; n2 = n2->next ) { + if( n2->pkt->pkttype == PKT_USER_ID + || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY + || n2->pkt->pkttype == PKT_SECRET_SUBKEY ) + break; + if( n2->pkt->pkttype != PKT_SIGNATURE ) + ; + else if( !ncmp ) + ncmp = n2; + else if( !cmp_signatures( ncmp->pkt->pkt.signature, + n2->pkt->pkt.signature )) { + remove_kbnode( keyblock, n2 ); + goto restart_sig; + } + } + n2 = ncmp? ncmp->next : NULL; + } while( n2 ); + } + } + + if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) + kid1 = keyid_from_pk( n->pkt->pkt.public_key, NULL ); + else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) + kid1 = keyid_from_sk( n->pkt->pkt.secret_key, NULL ); + else + kid1 = 0; + log_info(_("key %08lX: duplicated user ID detected - merged\n"), + (ulong)kid1); + + return 1; +} + +/* Check for a 0x20 revocation from a revocation key that is not + present. This gets called without the benefit of merge_xxxx so you + can't rely on pk->revkey and friends. */ +static void +revocation_present(KBNODE keyblock) +{ + KBNODE onode,inode; + PKT_public_key *pk=keyblock->pkt->pkt.public_key; + + for(onode=keyblock->next;onode;onode=onode->next) + { + /* If we reach user IDs, we're done. */ + if(onode->pkt->pkttype==PKT_USER_ID) + break; + + if(onode->pkt->pkttype==PKT_SIGNATURE && + onode->pkt->pkt.signature->sig_class==0x1F && + onode->pkt->pkt.signature->revkey) + { + int idx; + PKT_signature *sig=onode->pkt->pkt.signature; + + for(idx=0;idx<sig->numrevkeys;idx++) + { + u32 keyid[2]; + + keyid_from_fingerprint(sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN,keyid); + + for(inode=keyblock->next;inode;inode=inode->next) + { + /* If we reach user IDs, we're done. */ + if(inode->pkt->pkttype==PKT_USER_ID) + break; + + if(inode->pkt->pkttype==PKT_SIGNATURE && + inode->pkt->pkt.signature->sig_class==0x20 && + inode->pkt->pkt.signature->keyid[0]==keyid[0] && + inode->pkt->pkt.signature->keyid[1]==keyid[1]) + { + /* Okay, we have a revocation key, and a + revocation issued by it. Do we have the key + itself? */ + int rc; + + rc=get_pubkey_byfprint_fast (NULL,sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN); + if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + { + /* No, so try and get it */ + if(opt.keyserver_scheme && + opt.keyserver_options.auto_key_retrieve) + { + log_info(_("WARNING: key %08lX may be revoked: " + "fetching revocation key %08lX\n"), + (ulong)keyid_from_pk(pk,NULL), + (ulong)keyid[1]); + keyserver_import_fprint(sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN); + + /* Do we have it now? */ + rc=get_pubkey_byfprint_fast (NULL, + sig->revkey[idx]->fpr, + MAX_FINGERPRINT_LEN); + } + + if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + log_info(_("WARNING: key %08lX may be revoked: " + "revocation key %08lX not present.\n"), + (ulong)keyid_from_pk(pk,NULL), + (ulong)keyid[1]); + } + } + } + } + } + } +} + +/**************** + * compare and merge the blocks + * + * o compare the signatures: If we already have this signature, check + * that they compare okay; if not, issue a warning and ask the user. + * o Simply add the signature. Can't verify here because we may not have + * the signature's public key yet; verification is done when putting it + * into the trustdb, which is done automagically as soon as this pubkey + * is used. + * Note: We indicate newly inserted packets with flag bit 0 + */ +static int +merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, + u32 *keyid, int *n_uids, int *n_sigs, int *n_subk ) +{ + KBNODE onode, node; + int rc, found; + + /* 1st: handle revocation certificates */ + for(node=keyblock->next; node; node=node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) + break; + else if( node->pkt->pkttype == PKT_SIGNATURE + && node->pkt->pkt.signature->sig_class == 0x20 ) { + /* check whether we already have this */ + found = 0; + for(onode=keyblock_orig->next; onode; onode=onode->next ) { + if( onode->pkt->pkttype == PKT_USER_ID ) + break; + else if( onode->pkt->pkttype == PKT_SIGNATURE + && onode->pkt->pkt.signature->sig_class == 0x20 + && node->pkt->pkt.signature->keyid[0] + == onode->pkt->pkt.signature->keyid[0] + && node->pkt->pkt.signature->keyid[1] + == onode->pkt->pkt.signature->keyid[1] ) { + found = 1; + break; + } + } + if( !found ) { + char *p=get_user_id_printable (keyid); + KBNODE n2 = clone_kbnode(node); + insert_kbnode( keyblock_orig, n2, 0 ); + n2->flag |= 1; + ++*n_sigs; + log_info(_("key %08lX: \"%s\" revocation certificate added\n"), + (ulong)keyid[1],p); + m_free(p); + } + } + } + + /* 2nd: merge in any direct key (0x1F) sigs */ + for(node=keyblock->next; node; node=node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) + break; + else if( node->pkt->pkttype == PKT_SIGNATURE + && node->pkt->pkt.signature->sig_class == 0x1F ) { + /* check whether we already have this */ + found = 0; + for(onode=keyblock_orig->next; onode; onode=onode->next ) { + if( onode->pkt->pkttype == PKT_USER_ID ) + break; + else if( onode->pkt->pkttype == PKT_SIGNATURE + && onode->pkt->pkt.signature->sig_class == 0x1F + && !cmp_signatures(onode->pkt->pkt.signature, + node->pkt->pkt.signature)) { + found = 1; + break; + } + } + if( !found ) { + KBNODE n2 = clone_kbnode(node); + insert_kbnode( keyblock_orig, n2, 0 ); + n2->flag |= 1; + ++*n_sigs; + log_info( _("key %08lX: direct key signature added\n"), + (ulong)keyid[1]); + } + } + } + + /* 3rd: try to merge new certificates in */ + for(onode=keyblock_orig->next; onode; onode=onode->next ) { + if( !(onode->flag & 1) && onode->pkt->pkttype == PKT_USER_ID) { + /* find the user id in the imported keyblock */ + for(node=keyblock->next; node; node=node->next ) + if( node->pkt->pkttype == PKT_USER_ID + && !cmp_user_ids( onode->pkt->pkt.user_id, + node->pkt->pkt.user_id ) ) + break; + if( node ) { /* found: merge */ + rc = merge_sigs( onode, node, n_sigs, fname, keyid ); + if( rc ) + return rc; + } + } + } + + /* 4th: add new user-ids */ + for(node=keyblock->next; node; node=node->next ) { + if( node->pkt->pkttype == PKT_USER_ID) { + /* do we have this in the original keyblock */ + for(onode=keyblock_orig->next; onode; onode=onode->next ) + if( onode->pkt->pkttype == PKT_USER_ID + && !cmp_user_ids( onode->pkt->pkt.user_id, + node->pkt->pkt.user_id ) ) + break; + if( !onode ) { /* this is a new user id: append */ + rc = append_uid( keyblock_orig, node, n_sigs, fname, keyid); + if( rc ) + return rc; + ++*n_uids; + } + } + } + + /* 5th: add new subkeys */ + for(node=keyblock->next; node; node=node->next ) { + onode = NULL; + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + /* do we have this in the original keyblock? */ + for(onode=keyblock_orig->next; onode; onode=onode->next ) + if( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY + && !cmp_public_keys( onode->pkt->pkt.public_key, + node->pkt->pkt.public_key ) ) + break; + if( !onode ) { /* this is a new subkey: append */ + rc = append_key( keyblock_orig, node, n_sigs, fname, keyid); + if( rc ) + return rc; + ++*n_subk; + } + } + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + /* do we have this in the original keyblock? */ + for(onode=keyblock_orig->next; onode; onode=onode->next ) + if( onode->pkt->pkttype == PKT_SECRET_SUBKEY + && !cmp_secret_keys( onode->pkt->pkt.secret_key, + node->pkt->pkt.secret_key ) ) + break; + if( !onode ) { /* this is a new subkey: append */ + rc = append_key( keyblock_orig, node, n_sigs, fname, keyid); + if( rc ) + return rc; + ++*n_subk; + } + } + } + + /* 6th: merge subkey certificates */ + for(onode=keyblock_orig->next; onode; onode=onode->next ) { + if( !(onode->flag & 1) + && ( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY + || onode->pkt->pkttype == PKT_SECRET_SUBKEY) ) { + /* find the subkey in the imported keyblock */ + for(node=keyblock->next; node; node=node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && !cmp_public_keys( onode->pkt->pkt.public_key, + node->pkt->pkt.public_key ) ) + break; + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY + && !cmp_secret_keys( onode->pkt->pkt.secret_key, + node->pkt->pkt.secret_key ) ) + break; + } + if( node ) { /* found: merge */ + rc = merge_keysigs( onode, node, n_sigs, fname, keyid ); + if( rc ) + return rc; + } + } + } + + + return 0; +} + + +/**************** + * append the userid starting with NODE and all signatures to KEYBLOCK. + */ +static int +append_uid( KBNODE keyblock, KBNODE node, int *n_sigs, + const char *fname, u32 *keyid ) +{ + KBNODE n, n_where=NULL; + + assert(node->pkt->pkttype == PKT_USER_ID ); + + /* find the position */ + for( n = keyblock; n; n_where = n, n = n->next ) { + if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY + || n->pkt->pkttype == PKT_SECRET_SUBKEY ) + break; + } + if( !n ) + n_where = NULL; + + /* and append/insert */ + while( node ) { + /* we add a clone to the original keyblock, because this + * one is released first */ + n = clone_kbnode(node); + if( n_where ) { + insert_kbnode( n_where, n, 0 ); + n_where = n; + } + else + add_kbnode( keyblock, n ); + n->flag |= 1; + node->flag |= 1; + if( n->pkt->pkttype == PKT_SIGNATURE ) + ++*n_sigs; + + node = node->next; + if( node && node->pkt->pkttype != PKT_SIGNATURE ) + break; + } + + return 0; +} + + +/**************** + * Merge the sigs from SRC onto DST. SRC and DST are both a PKT_USER_ID. + * (how should we handle comment packets here?) + */ +static int +merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, + const char *fname, u32 *keyid ) +{ + KBNODE n, n2; + int found=0; + + assert(dst->pkt->pkttype == PKT_USER_ID ); + assert(src->pkt->pkttype == PKT_USER_ID ); + + for(n=src->next; n && n->pkt->pkttype != PKT_USER_ID; n = n->next ) { + if( n->pkt->pkttype != PKT_SIGNATURE ) + continue; + if( n->pkt->pkt.signature->sig_class == 0x18 + || n->pkt->pkt.signature->sig_class == 0x28 ) + continue; /* skip signatures which are only valid on subkeys */ + found = 0; + for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next){ + if( n2->pkt->pkttype == PKT_SIGNATURE + && n->pkt->pkt.signature->keyid[0] + == n2->pkt->pkt.signature->keyid[0] + && n->pkt->pkt.signature->keyid[1] + == n2->pkt->pkt.signature->keyid[1] + && n->pkt->pkt.signature->timestamp + <= n2->pkt->pkt.signature->timestamp + && n->pkt->pkt.signature->sig_class + == n2->pkt->pkt.signature->sig_class ) { + found++; + break; + } + } + if( !found ) { + /* This signature is new or newer, append N to DST. + * We add a clone to the original keyblock, because this + * one is released first */ + n2 = clone_kbnode(n); + insert_kbnode( dst, n2, PKT_SIGNATURE ); + n2->flag |= 1; + n->flag |= 1; + ++*n_sigs; + } + } + + return 0; +} + +/**************** + * Merge the sigs from SRC onto DST. SRC and DST are both a PKT_xxx_SUBKEY. + */ +static int +merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, + const char *fname, u32 *keyid ) +{ + KBNODE n, n2; + int found=0; + + assert( dst->pkt->pkttype == PKT_PUBLIC_SUBKEY + || dst->pkt->pkttype == PKT_SECRET_SUBKEY ); + + for(n=src->next; n ; n = n->next ) { + if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY + || n->pkt->pkttype == PKT_PUBLIC_KEY ) + break; + if( n->pkt->pkttype != PKT_SIGNATURE ) + continue; + found = 0; + for(n2=dst->next; n2; n2 = n2->next){ + if( n2->pkt->pkttype == PKT_PUBLIC_SUBKEY + || n2->pkt->pkttype == PKT_PUBLIC_KEY ) + break; + if( n2->pkt->pkttype == PKT_SIGNATURE + && n->pkt->pkt.signature->keyid[0] + == n2->pkt->pkt.signature->keyid[0] + && n->pkt->pkt.signature->keyid[1] + == n2->pkt->pkt.signature->keyid[1] + && n->pkt->pkt.signature->timestamp + <= n2->pkt->pkt.signature->timestamp + && n->pkt->pkt.signature->sig_class + == n2->pkt->pkt.signature->sig_class ) { + found++; + break; + } + } + if( !found ) { + /* This signature is new or newer, append N to DST. + * We add a clone to the original keyblock, because this + * one is released first */ + n2 = clone_kbnode(n); + insert_kbnode( dst, n2, PKT_SIGNATURE ); + n2->flag |= 1; + n->flag |= 1; + ++*n_sigs; + } + } + + return 0; +} + +/**************** + * append the subkey starting with NODE and all signatures to KEYBLOCK. + * Mark all new and copied packets by setting flag bit 0. + */ +static int +append_key( KBNODE keyblock, KBNODE node, int *n_sigs, + const char *fname, u32 *keyid ) +{ + KBNODE n; + + assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ); + + while( node ) { + /* we add a clone to the original keyblock, because this + * one is released first */ + n = clone_kbnode(node); + add_kbnode( keyblock, n ); + n->flag |= 1; + node->flag |= 1; + if( n->pkt->pkttype == PKT_SIGNATURE ) + ++*n_sigs; + + node = node->next; + if( node && node->pkt->pkttype != PKT_SIGNATURE ) + break; + } + + return 0; +} diff --git a/g10/kbnode.c b/g10/kbnode.c new file mode 100644 index 000000000..5df6d8d74 --- /dev/null +++ b/g10/kbnode.c @@ -0,0 +1,399 @@ +/* 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 "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 = m_alloc( 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 + m_free( 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 ); + m_free( 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 ); + m_free( 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 ); + m_free( 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); + } +} diff --git a/g10/keydb.c b/g10/keydb.c new file mode 100644 index 000000000..c67c36110 --- /dev/null +++ b/g10/keydb.c @@ -0,0 +1,724 @@ +/* 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 "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 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 = G10ERR_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 = m_strdup (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 = G10ERR_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 = G10ERR_OPEN_FILE; + 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 = G10ERR_OPEN_FILE; + *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 = G10ERR_OPEN_FILE; + 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 = G10ERR_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 = G10ERR_GENERAL; + goto leave; + } + + /* fixme: check directory permissions and print a warning */ + + leave: + if (rc) + log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc)); + else if (secret) + any_secret = 1; + else + any_public = 1; + m_free (filename); + return rc; +} + + + + +KEYDB_HANDLE +keydb_new (int secret) +{ + KEYDB_HANDLE hd; + int i, j; + + hd = m_alloc_clear (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) { + m_free (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; + } + } + + m_free (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 G10ERR_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 = G10ERR_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 G10ERR_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 = G10ERR_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 G10ERR_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 G10ERR_GENERAL; + + rc = lock_all (hd); + if (rc) + return rc; + + switch (hd->active[idx].type) { + case KEYDB_RESOURCE_TYPE_NONE: + rc = G10ERR_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 G10ERR_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 = G10ERR_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 G10ERR_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"), + g10_errstr (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 G10ERR_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 G10ERR_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); +} diff --git a/g10/keydb.h b/g10/keydb.h new file mode 100644 index 000000000..7be5e7fff --- /dev/null +++ b/g10/keydb.h @@ -0,0 +1,278 @@ +/* keydb.h - Key database + * 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_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 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 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 ); + +/*-- 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*/ diff --git a/g10/keyedit.c b/g10/keyedit.c new file mode 100644 index 000000000..d36623a6a --- /dev/null +++ b/g10/keyedit.c @@ -0,0 +1,3672 @@ +/* keyedit.c - keyedit stuff + * 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 <ctype.h> + +#include "options.h" +#include "packet.h" +#include "errors.h" +#include "iobuf.h" +#include "keydb.h" +#include "memory.h" +#include "photoid.h" +#include "util.h" +#include "main.h" +#include "trustdb.h" +#include "filter.h" +#include "ttyio.h" +#include "status.h" +#include "i18n.h" + +static void show_prefs( PKT_user_id *uid, int verbose ); +static void show_key_with_all_names( KBNODE keyblock, int only_marked, + int with_revoker, int with_fpr, int with_subkeys, int with_prefs ); +static void show_key_and_fingerprint( KBNODE keyblock ); +static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo ); +static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_delsig( KBNODE pub_keyblock ); +static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_addrevoker( KBNODE pub_keyblock, + KBNODE sec_keyblock, int sensitive ); +static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_select_uid( KBNODE keyblock, int idx ); +static int menu_select_key( KBNODE keyblock, int idx ); +static int count_uids( KBNODE keyblock ); +static int count_uids_with_flag( KBNODE keyblock, unsigned flag ); +static int count_keys_with_flag( KBNODE keyblock, unsigned flag ); +static int count_selected_uids( KBNODE keyblock ); +static int real_uids_left( KBNODE keyblock ); +static int count_selected_keys( KBNODE keyblock ); +static int menu_revsig( KBNODE keyblock ); +static int menu_revuid( KBNODE keyblock, KBNODE sec_keyblock ); +static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int enable_disable_key( KBNODE keyblock, int disable ); +static void menu_showphoto( KBNODE keyblock ); + +static int update_trust=0; + +#define CONTROL_D ('D' - 'A' + 1) + +#define NODFLG_BADSIG (1<<0) /* bad signature */ +#define NODFLG_NOKEY (1<<1) /* no public key */ +#define NODFLG_SIGERR (1<<2) /* other sig error */ + +#define NODFLG_MARK_A (1<<4) /* temporary mark */ +#define NODFLG_DELSIG (1<<5) /* to be deleted */ + +#define NODFLG_SELUID (1<<8) /* indicate the selected userid */ +#define NODFLG_SELKEY (1<<9) /* indicate the selected key */ +#define NODFLG_SELSIG (1<<10) /* indicate a selected signature */ + +struct sign_attrib { + int non_exportable,non_revocable; + struct revocation_reason_info *reason; + byte trust_depth,trust_value; + char *trust_regexp; +}; + +/**************** + * Print information about a signature, check it and return true + * if the signature is okay. NODE must be a signature packet. + */ +static int +print_and_check_one_sig( KBNODE keyblock, KBNODE node, + int *inv_sigs, int *no_key, int *oth_err, + int *is_selfsig, int print_without_key ) +{ + PKT_signature *sig = node->pkt->pkt.signature; + int rc, sigrc; + int is_rev = sig->sig_class == 0x30; + + /* TODO: Make sure a cached sig record here still has the pk that + issued it. See also keylist.c:list_keyblock_print */ + + switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) { + case 0: + node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); + sigrc = '!'; + break; + case G10ERR_BAD_SIGN: + node->flag = NODFLG_BADSIG; + sigrc = '-'; + if( inv_sigs ) + ++*inv_sigs; + break; + case G10ERR_NO_PUBKEY: + case G10ERR_UNU_PUBKEY: + node->flag = NODFLG_NOKEY; + sigrc = '?'; + if( no_key ) + ++*no_key; + break; + default: + node->flag = NODFLG_SIGERR; + sigrc = '%'; + if( oth_err ) + ++*oth_err; + break; + } + if( sigrc != '?' || print_without_key ) { + tty_printf("%s%c%c %c%c%c%c%c%c %08lX %s ", + is_rev? "rev":"sig",sigrc, + (sig->sig_class-0x10>0 && + sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', + sig->flags.exportable?' ':'L', + sig->flags.revocable?' ':'R', + sig->flags.policy_url?'P':' ', + sig->flags.notation?'N':' ', + sig->flags.expired?'X':' ', + (sig->trust_depth>9)?'T': + (sig->trust_depth>0)?'0'+sig->trust_depth:' ', + (ulong)sig->keyid[1], datestr_from_sig(sig)); + if( sigrc == '%' ) + tty_printf("[%s] ", g10_errstr(rc) ); + else if( sigrc == '?' ) + ; + else if( *is_selfsig ) { + tty_printf( is_rev? _("[revocation]") + : _("[self-signature]") ); + } + else { + size_t n; + char *p = get_user_id( sig->keyid, &n ); + tty_print_utf8_string2( p, n, 40 ); + m_free(p); + } + tty_printf("\n"); + + if(sig->flags.policy_url && (opt.list_options&LIST_SHOW_POLICY)) + show_policy_url(sig,3,0); + + if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) + show_notation(sig,3,0); + } + + return (sigrc == '!'); +} + + + +/**************** + * Check the keysigs and set the flags to indicate errors. + * Returns true if error found. + */ +static int +check_all_keysigs( KBNODE keyblock, int only_selected ) +{ + KBNODE kbctx; + KBNODE node; + int inv_sigs = 0; + int no_key = 0; + int oth_err = 0; + int has_selfsig = 0; + int mis_selfsig = 0; + int selected = !only_selected; + int anyuid = 0; + + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = node->pkt->pkt.user_id; + + if( only_selected ) + selected = (node->flag & NODFLG_SELUID); + if( selected ) { + tty_printf("uid "); + tty_print_utf8_string( uid->name, uid->len ); + tty_printf("\n"); + if( anyuid && !has_selfsig ) + mis_selfsig++; + has_selfsig = 0; + anyuid = 1; + } + } + else if( selected && node->pkt->pkttype == PKT_SIGNATURE + && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10 + || node->pkt->pkt.signature->sig_class == 0x30 ) ) { + int selfsig; + + if( print_and_check_one_sig( keyblock, node, &inv_sigs, + &no_key, &oth_err, &selfsig, 0 ) ) { + if( selfsig ) + has_selfsig = 1; + } + /* Hmmm: should we update the trustdb here? */ + } + } + if( !has_selfsig ) + mis_selfsig++; + if( inv_sigs == 1 ) + tty_printf(_("1 bad signature\n") ); + else if( inv_sigs ) + tty_printf(_("%d bad signatures\n"), inv_sigs ); + if( no_key == 1 ) + tty_printf(_("1 signature not checked due to a missing key\n") ); + else if( no_key ) + tty_printf(_("%d signatures not checked due to missing keys\n"), no_key ); + if( oth_err == 1 ) + tty_printf(_("1 signature not checked due to an error\n") ); + else if( oth_err ) + tty_printf(_("%d signatures not checked due to errors\n"), oth_err ); + if( mis_selfsig == 1 ) + tty_printf(_("1 user ID without valid self-signature detected\n")); + else if( mis_selfsig ) + tty_printf(_("%d user IDs without valid self-signatures detected\n"), + mis_selfsig); + + return inv_sigs || no_key || oth_err || mis_selfsig; +} + + + + +static int +sign_mk_attrib( PKT_signature *sig, void *opaque ) +{ + struct sign_attrib *attrib = opaque; + byte buf[8]; + + if( attrib->non_exportable ) { + buf[0] = 0; /* not exportable */ + build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 ); + } + + if( attrib->non_revocable ) { + buf[0] = 0; /* not revocable */ + build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 ); + } + + if( attrib->reason ) + revocation_reason_build_cb( sig, attrib->reason ); + + if(attrib->trust_depth) + { + /* Not critical. If someone doesn't understand trust sigs, + this can still be a valid regular signature. */ + buf[0] = attrib->trust_depth; + buf[1] = attrib->trust_value; + build_sig_subpkt(sig,SIGSUBPKT_TRUST,buf,2); + + /* Critical. If someone doesn't understands regexps, this + whole sig should be invalid. Note the +1 for the length - + regexps are null terminated. */ + if(attrib->trust_regexp) + build_sig_subpkt(sig,SIGSUBPKT_FLAG_CRITICAL|SIGSUBPKT_REGEXP, + attrib->trust_regexp, + strlen(attrib->trust_regexp)+1); + } + + return 0; +} + +static void +trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) +{ + char *p; + + *trust_value=0; + *trust_depth=0; + *regexp=NULL; + + tty_printf("\n"); + /* Same string as pkclist.c:do_edit_ownertrust */ + tty_printf(_( + "Please decide how far you trust this user to correctly\n" + "verify other users' keys (by looking at passports,\n" + "checking fingerprints from different sources...)?\n\n")); + tty_printf (_(" (%d) I trust marginally\n"), 1); + tty_printf (_(" (%d) I trust fully\n"), 2); + tty_printf("\n"); + + while(*trust_value==0) + { + p = cpr_get("trustsig_prompt.trust_value",_("Your selection? ")); + trim_spaces(p); + cpr_kill_prompt(); + /* 60 and 120 are as per RFC2440 */ + if(p[0]=='1' && !p[1]) + *trust_value=60; + else if(p[0]=='2' && !p[1]) + *trust_value=120; + m_free(p); + } + + tty_printf("\n"); + + tty_printf(_( + "Please enter the depth of this trust signature.\n" + "A depth greater than 1 allows the key you are signing to make\n" + "trust signatures on your behalf.\n")); + tty_printf("\n"); + + while(*trust_depth==0) + { + p = cpr_get("trustsig_prompt.trust_depth",_("Your selection? ")); + trim_spaces(p); + cpr_kill_prompt(); + *trust_depth=atoi(p); + m_free(p); + if(*trust_depth<1 || *trust_depth>255) + *trust_depth=0; + } + + tty_printf("\n"); + + tty_printf(_("Please enter a domain to restrict this signature, " + "or enter for none.\n")); + + tty_printf("\n"); + + p=cpr_get("trustsig_prompt.trust_regexp",_("Your selection? ")); + trim_spaces(p); + cpr_kill_prompt(); + + if(strlen(p)>0) + { + char *q=p; + int regexplen=100,ind; + + *regexp=m_alloc(regexplen); + + /* Now mangle the domain the user entered into a regexp. To do + this, \-escape everything that isn't alphanumeric, and attach + "<[^>]+[@.]" to the front, and ">$" to the end. */ + + strcpy(*regexp,"<[^>]+[@.]"); + ind=strlen(*regexp); + + while(*q) + { + if(!((*q>='A' && *q<='Z') + || (*q>='a' && *q<='z') || (*q>='0' && *q<='9'))) + (*regexp)[ind++]='\\'; + + (*regexp)[ind++]=*q; + + if((regexplen-ind)<3) + { + regexplen+=100; + *regexp=m_realloc(*regexp,regexplen); + } + + q++; + } + + (*regexp)[ind]='\0'; + strcat(*regexp,">$"); + } + + m_free(p); + tty_printf("\n"); +} + +/**************** + * Loop over all locusr and and sign the uids after asking. + * If no user id is marked, all user ids will be signed; + * if some user_ids are marked those will be signed. + */ +static int +sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, + int local, int nonrevocable, int trust ) +{ + int rc = 0; + SK_LIST sk_list = NULL; + SK_LIST sk_rover = NULL; + PKT_secret_key *sk = NULL; + KBNODE node, uidnode; + PKT_public_key *primary_pk=NULL; + int select_all = !count_selected_uids(keyblock); + int all_v3=1; + + /* Are there any non-v3 sigs on this key already? */ + if(PGP2) + for(node=keyblock;node;node=node->next) + if(node->pkt->pkttype==PKT_SIGNATURE && + node->pkt->pkt.signature->version>3) + { + all_v3=0; + break; + } + + /* build a list of all signators. + * + * We use the CERT flag to request the primary which must always + * be one which is capable of signing keys. I can't see a reason + * why to sign keys using a subkey. Implementation of USAGE_CERT + * is just a hack in getkey.c and does not mean that a subkey + * marked as certification capable will be used */ + rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT); + if( rc ) + goto leave; + + /* loop over all signators */ + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + u32 sk_keyid[2],pk_keyid[2]; + size_t n; + char *p,*trust_regexp=NULL; + int force_v4=0,class=0,selfsig=0; + u32 duration=0,timestamp=0; + byte trust_depth=0,trust_value=0; + + if(local || nonrevocable || trust || + opt.cert_policy_url || opt.cert_notation_data) + force_v4=1; + + /* we have to use a copy of the sk, because make_keysig_packet + * may remove the protection from sk and if we did other + * changes to the secret key, we would save the unprotected + * version */ + if( sk ) + free_secret_key(sk); + sk = copy_secret_key( NULL, sk_rover->sk ); + keyid_from_sk( sk, sk_keyid ); + /* set mark A for all selected user ids */ + for( node=keyblock; node; node = node->next ) { + if( select_all || (node->flag & NODFLG_SELUID) ) + node->flag |= NODFLG_MARK_A; + else + node->flag &= ~NODFLG_MARK_A; + } + /* reset mark for uids which are already signed */ + uidnode = NULL; + for( node=keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + primary_pk=node->pkt->pkt.public_key; + keyid_from_pk( primary_pk, pk_keyid ); + + /* Is this a self-sig? */ + if(pk_keyid[0]==sk_keyid[0] && pk_keyid[1]==sk_keyid[1]) + { + selfsig=1; + /* Do not force a v4 sig here, otherwise it would + be difficult to remake a v3 selfsig. If this + is a v3->v4 promotion case, then we set + force_v4 later anyway. */ + force_v4=0; + } + } + else if( node->pkt->pkttype == PKT_USER_ID ) { + uidnode = (node->flag & NODFLG_MARK_A)? node : NULL; + if(uidnode) + { + char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len, + 0); + + if(uidnode->pkt->pkt.user_id->is_revoked) + { + tty_printf(_("User ID \"%s\" is revoked."),user); + + if(opt.expert) + { + tty_printf("\n"); + /* No, so remove the mark and continue */ + if(!cpr_get_answer_is_yes("sign_uid.revoke_okay", + _("Are you sure you " + "still want to sign " + "it? (y/N) "))) + uidnode->flag &= ~NODFLG_MARK_A; + } + else + { + uidnode->flag &= ~NODFLG_MARK_A; + tty_printf(_(" Unable to sign.\n")); + } + } + else if(!uidnode->pkt->pkt.user_id->created) + { + tty_printf(_("WARNING: user ID \"%s\" is not " + "self-signed.\n"),user); + } + + m_free(user); + } + } + else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE + && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { + if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0] + && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) { + char buf[50]; + char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len, + 0); + + /* It's a v3 self-sig. Make it into a v4 self-sig? */ + if(node->pkt->pkt.signature->version<4 && selfsig) + { + tty_printf(_("The self-signature on \"%s\"\n" + "is a PGP 2.x-style signature.\n"),user); + + /* Note that the regular PGP2 warning below + still applies if there are no v4 sigs on + this key at all. */ + + if(opt.expert) + if(cpr_get_answer_is_yes("sign_uid.v4_promote_okay", + _("Do you want to promote " + "it to an OpenPGP self-" + "signature? (y/N) "))) + { + force_v4=1; + node->flag|=NODFLG_DELSIG; + m_free(user); + continue; + } + } + + /* Is the current signature expired? */ + if(node->pkt->pkt.signature->flags.expired) + { + tty_printf(_("Your current signature on \"%s\"\n" + "has expired.\n"),user); + + if(cpr_get_answer_is_yes("sign_uid.replace_expired_okay", + _("Do you want to issue a " + "new signature to replace " + "the expired one? (y/N) "))) + { + /* Mark these for later deletion. We + don't want to delete them here, just in + case the replacement signature doesn't + happen for some reason. We only delete + these after the replacement is already + in place. */ + + node->flag|=NODFLG_DELSIG; + m_free(user); + continue; + } + } + + if(!node->pkt->pkt.signature->flags.exportable && !local) + { + /* It's a local sig, and we want to make a + exportable sig. */ + tty_printf(_("Your current signature on \"%s\"\n" + "is a local signature.\n"),user); + + if(cpr_get_answer_is_yes("sign_uid.local_promote_okay", + _("Do you want to promote " + "it to a full exportable " + "signature? (y/N) "))) + { + /* Mark these for later deletion. We + don't want to delete them here, just in + case the replacement signature doesn't + happen for some reason. We only delete + these after the replacement is already + in place. */ + + node->flag|=NODFLG_DELSIG; + m_free(user); + continue; + } + } + + /* Fixme: see whether there is a revocation in which + * case we should allow to sign it again. */ + if (!node->pkt->pkt.signature->flags.exportable && local) + tty_printf(_( + "\"%s\" was already locally signed by key %08lX\n"), + user,(ulong)sk_keyid[1] ); + else + tty_printf(_( + "\"%s\" was already signed by key %08lX\n"), + user,(ulong)sk_keyid[1] ); + + if(opt.expert + && cpr_get_answer_is_yes("sign_uid.dupe_okay", + _("Do you want to sign it " + "again anyway? (y/N) "))) + { + /* Don't delete the old sig here since this is + an --expert thing. */ + m_free(user); + continue; + } + + sprintf (buf, "%08lX%08lX", + (ulong)sk->keyid[0], (ulong)sk->keyid[1] ); + write_status_text (STATUS_ALREADY_SIGNED, buf); + uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */ + + m_free(user); + } + } + } + /* check whether any uids are left for signing */ + if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) { + tty_printf(_("Nothing to sign with key %08lX\n"), + (ulong)sk_keyid[1] ); + continue; + } + /* Ask whether we really should sign these user id(s) */ + tty_printf("\n"); + show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 ); + tty_printf("\n"); + + if(primary_pk->expiredate && !selfsig) + { + u32 now=make_timestamp(); + + if(primary_pk->expiredate<=now) + { + tty_printf(_("This key has expired!")); + + if(opt.expert) + { + tty_printf(" "); + if(!cpr_get_answer_is_yes("sign_uid.expired_okay", + _("Are you sure you still " + "want to sign it? (y/N) "))) + continue; + } + else + { + tty_printf(_(" Unable to sign.\n")); + continue; + } + } + else + { + char *answer; + + tty_printf(_("This key is due to expire on %s.\n"), + expirestr_from_pk(primary_pk)); + + answer=cpr_get("sign_uid.expire", + _("Do you want your signature to " + "expire at the same time? (Y/n) ")); + if(answer_is_yes_no_default(answer,1)) + { + /* This fixes the signature timestamp we're going + to make as now. This is so the expiration date + is exactly correct, and not a few seconds off + (due to the time it takes to answer the + questions, enter the passphrase, etc). */ + timestamp=now; + duration=primary_pk->expiredate-now; + force_v4=1; + } + + cpr_kill_prompt(); + m_free(answer); + } + } + + /* Only ask for duration if we haven't already set it to match + the expiration of the pk */ + if(opt.ask_cert_expire && !duration && !selfsig) + duration=ask_expire_interval(1); + + if(duration) + force_v4=1; + + /* Is --pgp2 on, it's a v3 key, all the sigs on the key are + currently v3 and we're about to sign it with a v4 sig? If + so, danger! */ + if(PGP2 && all_v3 && + (sk->version>3 || force_v4) && primary_pk->version<=3) + { + tty_printf(_("You may not make an OpenPGP signature on a " + "PGP 2.x key while in --pgp2 mode.\n")); + tty_printf(_("This would make the key unusable in PGP 2.x.\n")); + + if(opt.expert) + { + if(!cpr_get_answer_is_yes("sign_uid.v4_on_v3_okay", + _("Are you sure you still " + "want to sign it? (y/N) "))) + continue; + + all_v3=0; + } + else + continue; + } + + if(selfsig) + ; + else + { + if(opt.batch) + class=0x10+opt.def_cert_check_level; + else + { + char *answer; + + tty_printf(_("How carefully have you verified the key you are " + "about to sign actually belongs\nto the person " + "named above? If you don't know what to " + "answer, enter \"0\".\n")); + tty_printf("\n"); + tty_printf(_(" (0) I will not answer.%s\n"), + opt.def_cert_check_level==0?" (default)":""); + tty_printf(_(" (1) I have not checked at all.%s\n"), + opt.def_cert_check_level==1?" (default)":""); + tty_printf(_(" (2) I have done casual checking.%s\n"), + opt.def_cert_check_level==2?" (default)":""); + tty_printf(_(" (3) I have done very careful checking.%s\n"), + opt.def_cert_check_level==3?" (default)":""); + tty_printf("\n"); + + while(class==0) + { + answer = cpr_get("sign_uid.class",_("Your selection? ")); + + if(answer[0]=='\0') + class=0x10+opt.def_cert_check_level; /* Default */ + else if(ascii_strcasecmp(answer,"0")==0) + class=0x10; /* Generic */ + else if(ascii_strcasecmp(answer,"1")==0) + class=0x11; /* Persona */ + else if(ascii_strcasecmp(answer,"2")==0) + class=0x12; /* Casual */ + else if(ascii_strcasecmp(answer,"3")==0) + class=0x13; /* Positive */ + else + tty_printf(_("Invalid selection.\n")); + + m_free(answer); + } + } + + if(trust) + trustsig_prompt(&trust_value,&trust_depth,&trust_regexp); + } + + tty_printf(_("Are you really sure that you want to sign this key\n" + "with your key: \"")); + p = get_user_id( sk_keyid, &n ); + tty_print_utf8_string( p, n ); + m_free(p); p = NULL; + tty_printf("\" (%08lX)\n",(ulong)sk_keyid[1]); + + if(selfsig) + { + tty_printf(_("\nThis will be a self-signature.\n")); + + if( local ) + tty_printf( + _("\nWARNING: the signature will not be marked " + "as non-exportable.\n")); + + if( nonrevocable ) + tty_printf( + _("\nWARNING: the signature will not be marked " + "as non-revocable.\n")); + } + else + { + if( local ) + tty_printf( + _("\nThe signature will be marked as non-exportable.\n")); + + if( nonrevocable ) + tty_printf( + _("\nThe signature will be marked as non-revocable.\n")); + + switch(class) + { + case 0x11: + tty_printf(_("\nI have not checked this key at all.\n")); + break; + + case 0x12: + tty_printf(_("\nI have checked this key casually.\n")); + break; + + case 0x13: + tty_printf(_("\nI have checked this key very carefully.\n")); + break; + } + } + + tty_printf("\n"); + + if( opt.batch && opt.answer_yes ) + ; + else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) ) + continue; + + /* now we can sign the user ids */ + reloop: /* (must use this, because we are modifing the list) */ + primary_pk = NULL; + for( node=keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) + primary_pk = node->pkt->pkt.public_key; + else if( node->pkt->pkttype == PKT_USER_ID + && (node->flag & NODFLG_MARK_A) ) { + PACKET *pkt; + PKT_signature *sig; + struct sign_attrib attrib; + + assert( primary_pk ); + memset( &attrib, 0, sizeof attrib ); + attrib.non_exportable = local; + attrib.non_revocable = nonrevocable; + attrib.trust_depth = trust_depth; + attrib.trust_value = trust_value; + attrib.trust_regexp = trust_regexp; + node->flag &= ~NODFLG_MARK_A; + + /* we force creation of a v4 signature for local + * signatures, otherwise we would not generate the + * subpacket with v3 keys and the signature becomes + * exportable */ + + if(selfsig) + rc = make_keysig_packet( &sig, primary_pk, + node->pkt->pkt.user_id, + NULL, + sk, + 0x13, 0, force_v4?4:0, 0, 0, + keygen_add_std_prefs, primary_pk); + else + rc = make_keysig_packet( &sig, primary_pk, + node->pkt->pkt.user_id, + NULL, + sk, + class, 0, force_v4?4:0, + timestamp, duration, + sign_mk_attrib, &attrib ); + if( rc ) { + log_error(_("signing failed: %s\n"), g10_errstr(rc)); + goto leave; + } + + *ret_modified = 1; /* we changed the keyblock */ + update_trust = 1; + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE ); + goto reloop; + } + } + + /* Delete any sigs that got promoted */ + for( node=keyblock; node; node = node->next ) + if( node->flag & NODFLG_DELSIG) + delete_kbnode(node); + } /* end loop over signators */ + + leave: + release_sk_list( sk_list ); + if( sk ) + free_secret_key(sk); + return rc; +} + + + +/**************** + * Change the passphrase of the primary and all secondary keys. + * We use only one passphrase for all keys. + */ +static int +change_passphrase( KBNODE keyblock ) +{ + int rc = 0; + int changed=0; + KBNODE node; + PKT_secret_key *sk; + char *passphrase = NULL; + int no_primary_secrets = 0; + + node = find_kbnode( keyblock, PKT_SECRET_KEY ); + if( !node ) { + log_error("Oops; secret key not found anymore!\n"); + goto leave; + } + sk = node->pkt->pkt.secret_key; + + switch( is_secret_key_protected( sk ) ) { + case -1: + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + tty_printf(_("This key is not protected.\n")); + break; + default: + if( sk->protect.s2k.mode == 1001 ) { + tty_printf(_("Secret parts of primary key are not available.\n")); + no_primary_secrets = 1; + } + else { + tty_printf(_("Key is protected.\n")); + rc = check_secret_key( sk, 0 ); + if( !rc ) + passphrase = get_last_passphrase(); + } + break; + } + + /* unprotect all subkeys (use the supplied passphrase or ask)*/ + for(node=keyblock; !rc && node; node = node->next ) { + if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *subsk = node->pkt->pkt.secret_key; + set_next_passphrase( passphrase ); + rc = check_secret_key( subsk, 0 ); + if( !rc && !passphrase ) + passphrase = get_last_passphrase(); + } + } + + if( rc ) + tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc)); + else { + DEK *dek = NULL; + STRING2KEY *s2k = m_alloc_secure( sizeof *s2k ); + const char *errtext = NULL; + + tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); + + set_next_passphrase( NULL ); + for(;;) { + s2k->mode = opt.s2k_mode; + s2k->hash_algo = opt.s2k_digest_algo; + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, + s2k, 2, errtext, NULL); + if( !dek ) { + errtext = N_("passphrase not correctly repeated; try again"); + tty_printf ("%s.\n", _(errtext)); + } + else if( !dek->keylen ) { + rc = 0; + tty_printf(_( "You don't want a passphrase -" + " this is probably a *bad* idea!\n\n")); + if( cpr_get_answer_is_yes("change_passwd.empty.okay", + _("Do you really want to do this? "))) + changed++; + break; + } + else { /* okay */ + rc = 0; + if( !no_primary_secrets ) { + sk->protect.algo = dek->algo; + sk->protect.s2k = *s2k; + rc = protect_secret_key( sk, dek ); + } + for(node=keyblock; !rc && node; node = node->next ) { + if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *subsk = node->pkt->pkt.secret_key; + subsk->protect.algo = dek->algo; + subsk->protect.s2k = *s2k; + rc = protect_secret_key( subsk, dek ); + } + } + if( rc ) + log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + else + changed++; + break; + } + } + m_free(s2k); + m_free(dek); + } + + leave: + m_free( passphrase ); + set_next_passphrase( NULL ); + return changed && !rc; +} + + +/**************** + * There are some keys out (due to a bug in gnupg), where the sequence + * of the packets is wrong. This function fixes that. + * Returns: true if the keyblock has been fixed. + * + * Note: This function does not work if there is more than one user ID. + */ +static int +fix_keyblock( KBNODE keyblock ) +{ + KBNODE node, last, subkey; + int fixed=0; + + /* locate key signatures of class 0x10..0x13 behind sub key packets */ + for( subkey=last=NULL, node = keyblock; node; + last=node, node = node->next ) { + switch( node->pkt->pkttype ) { + case PKT_PUBLIC_SUBKEY: + case PKT_SECRET_SUBKEY: + if( !subkey ) + subkey = last; /* actually it is the one before the subkey */ + break; + case PKT_SIGNATURE: + if( subkey ) { + PKT_signature *sig = node->pkt->pkt.signature; + if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) { + log_info(_( + "moving a key signature to the correct place\n")); + last->next = node->next; + node->next = subkey->next; + subkey->next = node; + node = last; + fixed=1; + } + } + break; + default: break; + } + } + + return fixed; +} + +/**************** + * Menu driven key editor. If sign_mode is true semi-automatical signing + * will be performed. commands are ignore in this case + * + * Note: to keep track of some selection we use node->mark MARKBIT_xxxx. + */ + +void +keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, + int sign_mode ) +{ + enum cmdids { cmdNONE = 0, + cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, + cmdTSIGN, cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY, + cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, + cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER, + cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, + cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, + cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP }; + static struct { const char *name; + enum cmdids id; + int need_sk; + int not_with_sk; + int signmode; + const char *desc; + } cmds[] = { + { N_("quit") , cmdQUIT , 0,0,1, N_("quit this menu") }, + { N_("q") , cmdQUIT , 0,0,1, NULL }, + { N_("save") , cmdSAVE , 0,0,1, N_("save and quit") }, + { N_("help") , cmdHELP , 0,0,1, N_("show this help") }, + { "?" , cmdHELP , 0,0,1, NULL }, + { N_("fpr") , cmdFPR , 0,0,1, N_("show fingerprint") }, + { N_("list") , cmdLIST , 0,0,1, N_("list key and user IDs") }, + { N_("l") , cmdLIST , 0,0,1, NULL }, + { N_("uid") , cmdSELUID , 0,0,1, N_("select user ID N") }, + { N_("key") , cmdSELKEY , 0,0,0, N_("select secondary key N") }, + { N_("check") , cmdCHECK , 0,0,1, N_("list signatures") }, + { N_("c") , cmdCHECK , 0,0,1, NULL }, + { N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") }, + { N_("s") , cmdSIGN , 0,1,1, NULL }, + { N_("tsign") , cmdTSIGN , 0,1,1, N_("make a trust signature")}, + { N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") }, + { N_("nrsign") , cmdNRSIGN , 0,1,1, N_("sign the key non-revocably") }, + { N_("nrlsign") , cmdNRLSIGN , 0,1,1, N_("sign the key locally and non-revocably") }, + { N_("debug") , cmdDEBUG , 0,0,0, NULL }, + { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") }, + { N_("addphoto"), cmdADDPHOTO , 1,1,0, N_("add a photo ID") }, + { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") }, + /* delphoto is really deluid in disguise */ + { N_("delphoto"), cmdDELUID , 0,1,0, NULL }, + { N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") }, + { N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") }, + { N_("addrevoker"),cmdADDREVOKER,1,1,0, N_("add a revocation key") }, + { N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") }, + { N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") }, + { N_("primary") , cmdPRIMARY , 1,1,0, N_("flag user ID as primary")}, + { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret " + "and public key listing") }, + { N_("t" ) , cmdTOGGLE , 1,0,0, NULL }, + { N_("pref") , cmdPREF , 0,1,0, N_("list preferences (expert)") }, + { N_("showpref"), cmdSHOWPREF , 0,1,0, N_("list preferences (verbose)") }, + { N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") }, + { N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") }, + { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") }, + { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") }, + { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") }, + { N_("revuid") , cmdREVUID , 1,1,0, N_("revoke a user ID") }, + { N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") }, + { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") }, + { N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") }, + { N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") }, + + { NULL, cmdNONE } }; + enum cmdids cmd = 0; + int rc = 0; + KBNODE keyblock = NULL; + KEYDB_HANDLE kdbhd = NULL; + KBNODE sec_keyblock = NULL; + KEYDB_HANDLE sec_kdbhd = NULL; + KBNODE cur_keyblock; + char *answer = NULL; + int redisplay = 1; + int modified = 0; + int sec_modified = 0; + int toggle; + int have_commands = !!commands; + + if ( opt.command_fd != -1 ) + ; + else if( opt.batch && !have_commands ) { + log_error(_("can't do that in batchmode\n")); + goto leave; + } + + if( sign_mode ) { + commands = NULL; + append_to_strlist( &commands, sign_mode == 1? "sign": + sign_mode == 2?"lsign": + sign_mode == 3?"nrsign":"nrlsign"); + have_commands = 1; + } + + /* get the public key */ + rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1); + if( rc ) + goto leave; + if( fix_keyblock( keyblock ) ) + modified++; + if( collapse_uids( &keyblock ) ) + modified++; + reorder_keyblock(keyblock); + + if( !sign_mode ) {/* see whether we have a matching secret key */ + PKT_public_key *pk = keyblock->pkt->pkt.public_key; + + sec_kdbhd = keydb_new (1); + { + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk (pk, afp, &an); + while (an < MAX_FINGERPRINT_LEN) + afp[an++] = 0; + rc = keydb_search_fpr (sec_kdbhd, afp); + } + if (!rc) { + rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock); + if (rc) { + log_error (_("error reading secret keyblock `%s': %s\n"), + username, g10_errstr(rc)); + } + else { + merge_keys_and_selfsig( sec_keyblock ); + if( fix_keyblock( sec_keyblock ) ) + sec_modified++; + } + } + + if (rc) { + sec_keyblock = NULL; + keydb_release (sec_kdbhd); sec_kdbhd = NULL; + rc = 0; + } + } + + if( sec_keyblock ) { + tty_printf(_("Secret key is available.\n")); + } + + toggle = 0; + cur_keyblock = keyblock; + for(;;) { /* main loop */ + int i, arg_number, photo; + const char *arg_string = ""; + char *p; + PKT_public_key *pk=keyblock->pkt->pkt.public_key; + + tty_printf("\n"); + if( redisplay ) { + show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 ); + tty_printf("\n"); + redisplay = 0; + } + do { + m_free(answer); + if( have_commands ) { + if( commands ) { + answer = m_strdup( commands->d ); + commands = commands->next; + } + else if( opt.batch ) { + answer = m_strdup("quit"); + } + else + have_commands = 0; + } + if( !have_commands ) { + answer = cpr_get_no_help("keyedit.prompt", _("Command> ")); + cpr_kill_prompt(); + } + trim_spaces(answer); + } while( *answer == '#' ); + + arg_number = 0; /* Yes, here is the init which egcc complains about */ + photo = 0; /* This too */ + if( !*answer ) + cmd = cmdLIST; + else if( *answer == CONTROL_D ) + cmd = cmdQUIT; + else if( isdigit( *answer ) ) { + cmd = cmdSELUID; + arg_number = atoi(answer); + } + 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; + } + if( sign_mode && !cmds[i].signmode ) + cmd = cmdINVCMD; + else if( cmds[i].need_sk && !sec_keyblock ) { + tty_printf(_("Need the secret key to do this.\n")); + cmd = cmdNOP; + } + else if( cmds[i].not_with_sk && sec_keyblock && toggle ) { + tty_printf(_("Please use the command \"toggle\" first.\n")); + cmd = cmdNOP; + } + else + cmd = cmds[i].id; + } + switch( cmd ) { + case cmdHELP: + for(i=0; cmds[i].name; i++ ) { + if( sign_mode && !cmds[i].signmode ) + ; + else if( cmds[i].need_sk && !sec_keyblock ) + ; /* skip if we do not have the secret key */ + else if( cmds[i].desc ) + tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); + } + break; + + case cmdLIST: + redisplay = 1; + break; + + case cmdFPR: + show_key_and_fingerprint( keyblock ); + break; + + case cmdSELUID: + if( menu_select_uid( cur_keyblock, arg_number ) ) + redisplay = 1; + break; + + case cmdSELKEY: + if( menu_select_key( cur_keyblock, arg_number ) ) + redisplay = 1; + break; + + case cmdCHECK: + /* we can only do this with the public key becuase the + * check functions can't cope with secret keys and it + * is questionable whether this would make sense at all */ + check_all_keysigs( keyblock, count_selected_uids(keyblock) ); + break; + + case cmdSIGN: /* sign (only the public key) */ + case cmdLSIGN: /* sign (only the public key) */ + case cmdNRSIGN: /* sign (only the public key) */ + case cmdNRLSIGN: /* sign (only the public key) */ + case cmdTSIGN: + if( pk->is_revoked ) + { + tty_printf(_("Key is revoked.")); + + if(opt.expert) + { + tty_printf(" "); + if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay", + _("Are you sure you still want " + "to sign it? (y/N) "))) + break; + } + else + { + tty_printf(_(" Unable to sign.\n")); + break; + } + } + + if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) { + if( !cpr_get_answer_is_yes("keyedit.sign_all.okay", + _("Really sign all user IDs? ")) ) { + tty_printf(_("Hint: Select the user IDs to sign\n")); + break; + } + } + if( !sign_uids( keyblock, locusr, &modified, + (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN), + (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN), + (cmd == cmdTSIGN)) + && sign_mode ) + goto do_cmd_save; + break; + + case cmdDEBUG: + dump_kbnode( cur_keyblock ); + break; + + case cmdTOGGLE: + toggle = !toggle; + cur_keyblock = toggle? sec_keyblock : keyblock; + redisplay = 1; + break; + + case cmdADDPHOTO: + if (RFC2440 || RFC1991 || PGP2) + { + tty_printf( + _("This command is not allowed while in %s mode.\n"), + RFC2440?"OpenPGP":PGP2?"PGP2":"RFC-1991"); + break; + } + photo=1; + /* fall through */ + + case cmdADDUID: + if( menu_adduid( keyblock, sec_keyblock, photo ) ) { + redisplay = 1; + sec_modified = modified = 1; + merge_keys_and_selfsig( sec_keyblock ); + merge_keys_and_selfsig( keyblock ); + } + break; + + case cmdDELUID: { + int n1; + + if( !(n1=count_selected_uids(keyblock)) ) + tty_printf(_("You must select at least one user ID.\n")); + else if( real_uids_left(keyblock) < 1 ) + tty_printf(_("You can't delete the last user ID!\n")); + else if( cpr_get_answer_is_yes( + "keyedit.remove.uid.okay", + n1 > 1? _("Really remove all selected user IDs? ") + : _("Really remove this user ID? ") + ) ) { + menu_deluid( keyblock, sec_keyblock ); + redisplay = 1; + modified = 1; + if( sec_keyblock ) + sec_modified = 1; + } + } + break; + + case cmdDELSIG: { + int n1; + + if( !(n1=count_selected_uids(keyblock)) ) + tty_printf(_("You must select at least one user ID.\n")); + else if( menu_delsig( keyblock ) ) { + /* no redisplay here, because it may scroll away some + * status output of delsig */ + modified = 1; + } + } + break; + + case cmdADDKEY: + if( generate_subkeypair( keyblock, sec_keyblock ) ) { + redisplay = 1; + sec_modified = modified = 1; + merge_keys_and_selfsig( sec_keyblock ); + merge_keys_and_selfsig( keyblock ); + } + break; + + + case cmdDELKEY: { + int n1; + + if( !(n1=count_selected_keys( keyblock )) ) + tty_printf(_("You must select at least one key.\n")); + else if( sec_keyblock && !cpr_get_answer_is_yes( + "keyedit.remove.subkey.okay", + n1 > 1? + _("Do you really want to delete the selected keys? "): + _("Do you really want to delete this key? ") + )) + ; + else { + menu_delkey( keyblock, sec_keyblock ); + redisplay = 1; + modified = 1; + if( sec_keyblock ) + sec_modified = 1; + } + } + break; + + case cmdADDREVOKER: + { + int sensitive=0; + + if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0) + sensitive=1; + if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) { + redisplay = 1; + sec_modified = modified = 1; + merge_keys_and_selfsig( sec_keyblock ); + merge_keys_and_selfsig( keyblock ); + } + } + break; + + case cmdREVUID: { + int n1; + + if( !(n1=count_selected_uids(keyblock)) ) + tty_printf(_("You must select at least one user ID.\n")); + else if( cpr_get_answer_is_yes( + "keyedit.revoke.uid.okay", + n1 > 1? _("Really revoke all selected user IDs? ") + : _("Really revoke this user ID? ") + ) ) { + if(menu_revuid(keyblock,sec_keyblock)) + { + modified=1; + redisplay=1; + } + } + } + break; + + case cmdREVKEY: { + int n1; + + if( !(n1=count_selected_keys( keyblock )) ) + tty_printf(_("You must select at least one key.\n")); + else if( sec_keyblock && !cpr_get_answer_is_yes( + "keyedit.revoke.subkey.okay", + n1 > 1? + _("Do you really want to revoke the selected keys? "): + _("Do you really want to revoke this key? ") + )) + ; + else { + if( menu_revkey( keyblock, sec_keyblock ) ) { + modified = 1; + /*sec_modified = 1;*/ + } + redisplay = 1; + } + } + break; + + case cmdEXPIRE: + if( menu_expire( keyblock, sec_keyblock ) ) { + merge_keys_and_selfsig( sec_keyblock ); + merge_keys_and_selfsig( keyblock ); + sec_modified = 1; + modified = 1; + redisplay = 1; + } + break; + + case cmdPRIMARY: + if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) { + merge_keys_and_selfsig( keyblock ); + modified = 1; + redisplay = 1; + } + break; + + case cmdPASSWD: + if( change_passphrase( sec_keyblock ) ) + sec_modified = 1; + break; + + case cmdTRUST: + show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 ); + tty_printf("\n"); + if( edit_ownertrust( find_kbnode( keyblock, + PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) ) { + redisplay = 1; + /* No real need to set update_trust here as + edit_ownertrust() calls revalidation_mark() + anyway. */ + update_trust=1; + } + break; + + case cmdPREF: + show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 ); + break; + + case cmdSHOWPREF: + show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 ); + break; + + case cmdSETPREF: + keygen_set_std_prefs ( !*arg_string? "default" : arg_string, 0); + break; + + case cmdUPDPREF: + { + PKT_user_id *temp=keygen_get_std_prefs(); + tty_printf(_("Current preference list:\n")); + show_prefs(temp,1); + m_free(temp); + } + if (cpr_get_answer_is_yes ("keyedit.updpref.okay", + count_selected_uids (keyblock)? + _("Really update the preferences" + " for the selected user IDs? "): + _("Really update the preferences? "))){ + + if ( menu_set_preferences (keyblock, sec_keyblock) ) { + merge_keys_and_selfsig (keyblock); + modified = 1; + redisplay = 1; + } + } + break; + + case cmdNOP: + break; + + case cmdREVSIG: + if( menu_revsig( keyblock ) ) { + redisplay = 1; + modified = 1; + } + break; + + case cmdENABLEKEY: + case cmdDISABLEKEY: + if( enable_disable_key( keyblock, cmd == cmdDISABLEKEY ) ) { + redisplay = 1; + modified = 1; + } + break; + + case cmdSHOWPHOTO: + menu_showphoto(keyblock); + break; + + case cmdQUIT: + if( have_commands ) + goto leave; + if( !modified && !sec_modified ) + goto leave; + if( !cpr_get_answer_is_yes("keyedit.save.okay", + _("Save changes? ")) ) { + if( cpr_enabled() + || cpr_get_answer_is_yes("keyedit.cancel.okay", + _("Quit without saving? ")) ) + goto leave; + break; + } + /* fall thru */ + case cmdSAVE: + do_cmd_save: + if( modified || sec_modified ) { + if( modified ) { + rc = keydb_update_keyblock (kdbhd, keyblock); + if( rc ) { + log_error(_("update failed: %s\n"), g10_errstr(rc) ); + break; + } + } + if( sec_modified ) { + rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock ); + if( rc ) { + log_error( _("update secret failed: %s\n"), + g10_errstr(rc) ); + break; + } + } + } + else + tty_printf(_("Key not changed so no update needed.\n")); + + if( update_trust ) + { + revalidation_mark (); + update_trust=0; + } + goto leave; + + case cmdINVCMD: + default: + tty_printf("\n"); + tty_printf(_("Invalid command (try \"help\")\n")); + break; + } + } /* end main loop */ + + leave: + release_kbnode( keyblock ); + release_kbnode( sec_keyblock ); + keydb_release (kdbhd); + m_free(answer); +} + + +/**************** + * show preferences of a public keyblock. + */ +static void +show_prefs (PKT_user_id *uid, int verbose) +{ + const prefitem_t fake={0,0}; + const prefitem_t *prefs; + int i; + + if( !uid ) + return; + + if( uid->prefs ) + prefs=uid->prefs; + else if(verbose) + prefs=&fake; + else + return; + + if (verbose) { + int any, des_seen=0, sha1_seen=0, uncomp_seen=0; + tty_printf (" "); + tty_printf (_("Cipher: ")); + for(i=any=0; prefs[i].type; i++ ) { + if( prefs[i].type == PREFTYPE_SYM ) { + const char *s = cipher_algo_to_string (prefs[i].value); + + if (any) + tty_printf (", "); + any = 1; + /* We don't want to display strings for experimental algos */ + if (s && prefs[i].value < 100 ) + tty_printf ("%s", s ); + else + tty_printf ("[%d]", prefs[i].value); + if (prefs[i].value == CIPHER_ALGO_3DES ) + des_seen = 1; + } + } + if (!des_seen) { + if (any) + tty_printf (", "); + tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES)); + } + tty_printf ("\n "); + tty_printf (_("Digest: ")); + for(i=any=0; prefs[i].type; i++ ) { + if( prefs[i].type == PREFTYPE_HASH ) { + const char *s = digest_algo_to_string (prefs[i].value); + + if (any) + tty_printf (", "); + any = 1; + /* We don't want to display strings for experimental algos */ + if (s && prefs[i].value < 100 ) + tty_printf ("%s", s ); + else + tty_printf ("[%d]", prefs[i].value); + if (prefs[i].value == DIGEST_ALGO_SHA1 ) + sha1_seen = 1; + } + } + if (!sha1_seen) { + if (any) + tty_printf (", "); + tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1)); + } + tty_printf ("\n "); + tty_printf (_("Compression: ")); + for(i=any=0; prefs[i].type; i++ ) { + if( prefs[i].type == PREFTYPE_ZIP ) { + const char *s=compress_algo_to_string(prefs[i].value); + + if (any) + tty_printf (", "); + any = 1; + /* We don't want to display strings for experimental algos */ + if (s && prefs[i].value < 100 ) + tty_printf ("%s", s ); + else + tty_printf ("[%d]", prefs[i].value); + if (prefs[i].value == 0 ) + uncomp_seen = 1; + } + } + if (!uncomp_seen) { + if (any) + tty_printf (", "); + else { + tty_printf ("%s",compress_algo_to_string(1)); + tty_printf (", "); + } + tty_printf ("%s",compress_algo_to_string(0)); + } + if(uid->mdc_feature || !uid->ks_modify) + { + tty_printf ("\n "); + tty_printf (_("Features: ")); + any=0; + if(uid->mdc_feature) + { + tty_printf ("MDC"); + any=1; + } + if(!uid->ks_modify) + { + if(any) + tty_printf (", "); + tty_printf (_("Keyserver no-modify")); + } + } + tty_printf("\n"); + } + else { + tty_printf(" "); + for(i=0; prefs[i].type; i++ ) { + tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' : + prefs[i].type == PREFTYPE_HASH ? 'H' : + prefs[i].type == PREFTYPE_ZIP ? 'Z':'?', + prefs[i].value); + } + if (uid->mdc_feature) + tty_printf (" [mdc]"); + if (!uid->ks_modify) + tty_printf (" [no-ks-modify]"); + tty_printf("\n"); + } +} + + +/* This is the version of show_key_with_all_names used when + opt.with_colons is used. It prints all available data in a easy to + parse format and does not translate utf8 */ +static void +show_key_with_all_names_colon (KBNODE keyblock) +{ + KBNODE node; + int i, j, ulti_hack=0; + byte pk_version=0; + PKT_public_key *primary=NULL; + + /* the keys */ + for ( node = keyblock; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_PUBLIC_KEY + || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) + { + PKT_public_key *pk = node->pkt->pkt.public_key; + u32 keyid[2]; + + if (node->pkt->pkttype == PKT_PUBLIC_KEY) + { + pk_version = pk->version; + primary=pk; + } + + keyid_from_pk (pk, keyid); + + fputs (node->pkt->pkttype == PKT_PUBLIC_KEY?"pub:":"sub:", stdout); + if (!pk->is_valid) + putchar ('i'); + else if (pk->is_revoked) + putchar ('r'); + else if (pk->has_expired) + putchar ('e'); + else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks )) + { + int trust = get_validity_info (pk, NULL); + if(trust=='u') + ulti_hack=1; + putchar (trust); + } + + printf (":%u:%d:%08lX%08lX:%lu:%lu:", + nbits_from_pk (pk), + pk->pubkey_algo, + (ulong)keyid[0], (ulong)keyid[1], + (ulong)pk->timestamp, + (ulong)pk->expiredate ); + if (pk->local_id) + printf ("%lu", pk->local_id); + putchar (':'); + if (node->pkt->pkttype==PKT_PUBLIC_KEY + && !(opt.fast_list_mode || opt.no_expensive_trust_checks )) + putchar(get_ownertrust_info (pk)); + putchar(':'); + putchar('\n'); + + print_fingerprint (pk, NULL, 0); + + /* print the revoker record */ + if( !pk->revkey && pk->numrevkeys ) + BUG(); + else + { + for (i=0; i < pk->numrevkeys; i++) + { + byte *p; + + printf ("rvk:::%d::::::", pk->revkey[i].algid); + p = pk->revkey[i].fpr; + for (j=0; j < 20; j++, p++ ) + printf ("%02X", *p); + printf (":%02x%s:\n", pk->revkey[i].class, + (pk->revkey[i].class&0x40)?"s":""); + } + } + } + } + + /* the user ids */ + i = 0; + for (node = keyblock; node; node = node->next) + { + if ( node->pkt->pkttype == PKT_USER_ID ) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + + ++i; + + if(uid->attrib_data) + printf("uat:"); + else + printf("uid:"); + + if ( uid->is_revoked ) + printf("r::::::::"); + else if ( uid->is_expired ) + printf("e::::::::"); + else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) + printf("::::::::"); + else + { + int uid_validity; + + if( primary && !ulti_hack ) + uid_validity = get_validity_info( primary, uid ); + else + uid_validity = 'u'; + printf("%c::::::::",uid_validity); + } + + if(uid->attrib_data) + printf ("%u %lu",uid->numattribs,uid->attrib_len); + else + print_string (stdout, uid->name, uid->len, ':'); + + putchar (':'); + /* signature class */ + putchar (':'); + /* capabilities */ + putchar (':'); + /* preferences */ + if (pk_version>3 || uid->selfsigversion>3) + { + const prefitem_t *prefs = uid->prefs; + + for (j=0; prefs && prefs[j].type; j++) + { + if (j) + putchar (' '); + printf ("%c%d", prefs[j].type == PREFTYPE_SYM ? 'S' : + prefs[j].type == PREFTYPE_HASH ? 'H' : + prefs[j].type == PREFTYPE_ZIP ? 'Z':'?', + prefs[j].value); + } + if (uid->mdc_feature) + printf (",mdc"); + if (!uid->ks_modify) + printf (",no-ks-modify"); + } + putchar (':'); + /* flags */ + printf ("%d,", i); + if (uid->is_primary) + putchar ('p'); + if (uid->is_revoked) + putchar ('r'); + if (uid->is_expired) + putchar ('e'); + if ((node->flag & NODFLG_SELUID)) + putchar ('s'); + if ((node->flag & NODFLG_MARK_A)) + putchar ('m'); + putchar (':'); + putchar('\n'); + } + } +} + + +/**************** + * Display the key a the user ids, if only_marked is true, do only + * so for user ids with mark A flag set and dont display the index number + */ +static void +show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, + int with_fpr, int with_subkeys, int with_prefs ) +{ + KBNODE node; + int i, rc; + int do_warn = 0; + byte pk_version=0; + + if (opt.with_colons) + { + show_key_with_all_names_colon (keyblock); + return; + } + + /* the keys */ + for( node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY + || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) { + PKT_public_key *pk = node->pkt->pkt.public_key; + const char *otrust="err",*trust="err"; + + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + /* do it here, so that debug messages don't clutter the + * output */ + static int did_warn = 0; + + trust = get_validity_string (pk, NULL); + otrust = get_ownertrust_string (pk); + + /* Show a warning once */ + if (!did_warn + && (get_validity (pk, NULL) & TRUST_FLAG_PENDING_CHECK)) { + did_warn = 1; + do_warn = 1; + } + + pk_version=pk->version; + } + + if(with_revoker) { + if( !pk->revkey && pk->numrevkeys ) + BUG(); + else + for(i=0;i<pk->numrevkeys;i++) { + u32 r_keyid[2]; + char *user; + const char *algo= + pubkey_algo_to_string(pk->revkey[i].algid); + + keyid_from_fingerprint(pk->revkey[i].fpr, + MAX_FINGERPRINT_LEN,r_keyid); + + user=get_user_id_string (r_keyid); + tty_printf (_("This key may be revoked by %s key "), + algo?algo:"?"); + tty_print_utf8_string (user, strlen (user)); + if ((pk->revkey[i].class&0x40)) + tty_printf (_(" (sensitive)")); + tty_printf ("\n"); + m_free(user); + } + } + + tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), + node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", + (node->flag & NODFLG_SELKEY)? '*':' ', + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + (ulong)keyid_from_pk(pk,NULL), + datestr_from_pk(pk), + expirestr_from_pk(pk) ); + tty_printf("\n"); + + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) + { + tty_printf(" "); + tty_printf(_("trust: %-13s"), otrust); + tty_printf(_("validity: %s"), trust ); + tty_printf("\n"); + if( node->pkt->pkttype == PKT_PUBLIC_KEY + && (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) + { + tty_printf("*** "); + tty_printf(_("This key has been disabled")); + tty_printf("\n"); + } + } + + if( node->pkt->pkttype == PKT_PUBLIC_KEY && with_fpr ) + { + print_fingerprint ( pk, NULL, 2 ); + tty_printf("\n"); + } + } + else if( node->pkt->pkttype == PKT_SECRET_KEY + || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) { + PKT_secret_key *sk = node->pkt->pkt.secret_key; + tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), + node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", + (node->flag & NODFLG_SELKEY)? '*':' ', + nbits_from_sk( sk ), + pubkey_letter( sk->pubkey_algo ), + (ulong)keyid_from_sk(sk,NULL), + datestr_from_sk(sk), + expirestr_from_sk(sk) ); + tty_printf("\n"); + } + else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE + && node->pkt->pkt.signature->sig_class == 0x28 ) { + PKT_signature *sig = node->pkt->pkt.signature; + + rc = check_key_signature( keyblock, node, NULL ); + if( !rc ) + tty_printf( _("rev! subkey has been revoked: %s\n"), + datestr_from_sig( sig ) ); + else if( rc == G10ERR_BAD_SIGN ) + tty_printf( _("rev- faked revocation found\n") ); + else if( rc ) + tty_printf( _("rev? problem checking revocation: %s\n"), + g10_errstr(rc) ); + } + } + /* the user ids */ + i = 0; + for( node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = node->pkt->pkt.user_id; + ++i; + if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){ + if( only_marked ) + tty_printf(" "); + else if( node->flag & NODFLG_SELUID ) + tty_printf("(%d)* ", i); + else if( uid->is_primary ) + tty_printf("(%d). ", i); + else + tty_printf("(%d) ", i); + if ( uid->is_revoked ) + tty_printf (_("[revoked] ")); + if ( uid->is_expired ) + tty_printf (_("[expired] ")); + tty_print_utf8_string( uid->name, uid->len ); + tty_printf("\n"); + if( with_prefs ) + { + if(pk_version>3 || uid->selfsigversion>3) + show_prefs (uid, with_prefs == 2); + else + tty_printf(_("There are no preferences on a " + "PGP 2.x-style user ID.\n")); + } + } + } + } + + if (do_warn) + tty_printf (_("Please note that the shown key validity " + "is not necessarily correct\n" + "unless you restart the program.\n")); + +} + + +/* Display basic key information. This fucntion is suitable to show + information on the key without any dependencies on the trustdb or + any other internal GnuPG stuff. KEYBLOCK may either be a public or + a secret key.*/ +void +show_basic_key_info ( KBNODE keyblock ) +{ + KBNODE node; + int i; + + /* The primary key */ + for (node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_PUBLIC_KEY) + { + PKT_public_key *pk = node->pkt->pkt.public_key; + + /* Note, we use the same format string as in other show + functions to make the translation job easier. */ + tty_printf (_("%s%c %4u%c/%08lX created: %s expires: %s"), + node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", + ' ', + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + (ulong)keyid_from_pk(pk,NULL), + datestr_from_pk(pk), + expirestr_from_pk(pk) ); + tty_printf("\n"); + print_fingerprint ( pk, NULL, 3 ); + tty_printf("\n"); + } + else if (node->pkt->pkttype == PKT_SECRET_KEY) + { + PKT_secret_key *sk = node->pkt->pkt.secret_key; + tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), + node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", + ' ', + nbits_from_sk( sk ), + pubkey_letter( sk->pubkey_algo ), + (ulong)keyid_from_sk(sk,NULL), + datestr_from_sk(sk), + expirestr_from_sk(sk) ); + tty_printf("\n"); + print_fingerprint (NULL, sk, 3 ); + tty_printf("\n"); + } + } + + /* The user IDs. */ + for (i=0, node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + ++i; + + tty_printf (" "); + if (uid->is_revoked) + tty_printf ("[revoked] "); + if ( uid->is_expired ) + tty_printf ("[expired] "); + tty_print_utf8_string (uid->name, uid->len); + tty_printf ("\n"); + } + } +} + +static void +show_key_and_fingerprint( KBNODE keyblock ) +{ + KBNODE node; + PKT_public_key *pk = NULL; + + for( node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + pk = node->pkt->pkt.public_key; + tty_printf("pub %4u%c/%08lX %s ", + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + (ulong)keyid_from_pk(pk,NULL), + datestr_from_pk(pk) ); + } + else if( node->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = node->pkt->pkt.user_id; + tty_print_utf8_string( uid->name, uid->len ); + break; + } + } + tty_printf("\n"); + if( pk ) + print_fingerprint( pk, NULL, 2 ); +} + + +/* Show a warning if no uids on the key have the primary uid flag + set. */ +static void +no_primary_warning(KBNODE keyblock, int uids) +{ + KBNODE node; + int select_all=1,have_uid=0,uid_count=0; + + if(uids) + select_all=!count_selected_uids(keyblock); + + /* TODO: if we ever start behaving differently with a primary or + non-primary attribute ID, we will need to check for attributes + here as well. */ + + for(node=keyblock; node; node = node->next) + { + if(node->pkt->pkttype==PKT_USER_ID + && node->pkt->pkt.user_id->attrib_data==NULL) + { + uid_count++; + + if((select_all || (node->flag & NODFLG_SELUID)) + && node->pkt->pkt.user_id->is_primary==2) + have_uid|=2; + else + have_uid|=1; + } + } + + if(uid_count>1 && have_uid&1 && !(have_uid&2)) + log_info(_("WARNING: no user ID has been marked as primary. This command " + "may\n cause a different user ID to become the assumed primary.\n")); +} + +/**************** + * Ask for a new user id, do the selfsignature and put it into + * both keyblocks. + * Return true if there is a new user id + */ +static int +menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) +{ + PKT_user_id *uid; + PKT_public_key *pk=NULL; + PKT_secret_key *sk=NULL; + PKT_signature *sig=NULL; + PACKET *pkt; + KBNODE node; + KBNODE pub_where=NULL, sec_where=NULL; + int rc; + + for( node = pub_keyblock; node; pub_where = node, node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) + pk = node->pkt->pkt.public_key; + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; + } + if( !node ) /* no subkey */ + pub_where = NULL; + for( node = sec_keyblock; node; sec_where = node, node = node->next ) { + if( node->pkt->pkttype == PKT_SECRET_KEY ) + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) + break; + } + if( !node ) /* no subkey */ + sec_where = NULL; + assert(pk && sk); + + if(photo) { + int hasattrib=0; + + for( node = pub_keyblock; node; node = node->next ) + if( node->pkt->pkttype == PKT_USER_ID && + node->pkt->pkt.user_id->attrib_data!=NULL) + { + hasattrib=1; + break; + } + + /* It is legal but bad for compatibility to add a photo ID to a + v3 key as it means that PGP2 will not be able to use that key + anymore. Also, PGP may not expect a photo on a v3 key. + Don't bother to ask this if the key already has a photo - any + damage has already been done at that point. -dms */ + if(pk->version==3 && !hasattrib) + { + if(opt.expert) + { + tty_printf(_("WARNING: This is a PGP2-style key. " + "Adding a photo ID may cause some versions\n" + " of PGP to reject this key.\n")); + + if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay", + _("Are you sure you still want " + "to add it? (y/N) "))) + return 0; + } + else + { + tty_printf(_("You may not add a photo ID to " + "a PGP2-style key.\n")); + return 0; + } + } + + uid = generate_photo_id(pk); + } else + uid = generate_user_id(); + if( !uid ) + return 0; + + rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, + keygen_add_std_prefs, pk ); + free_secret_key( sk ); + if( rc ) { + log_error("signing failed: %s\n", g10_errstr(rc) ); + free_user_id(uid); + return 0; + } + + /* insert/append to secret keyblock */ + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_USER_ID; + pkt->pkt.user_id = scopy_user_id(uid); + node = new_kbnode(pkt); + if( sec_where ) + insert_kbnode( sec_where, node, 0 ); + else + add_kbnode( sec_keyblock, node ); + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = copy_signature(NULL, sig); + if( sec_where ) + insert_kbnode( node, new_kbnode(pkt), 0 ); + else + add_kbnode( sec_keyblock, new_kbnode(pkt) ); + /* insert/append to public keyblock */ + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_USER_ID; + pkt->pkt.user_id = uid; + node = new_kbnode(pkt); + if( pub_where ) + insert_kbnode( pub_where, node, 0 ); + else + add_kbnode( pub_keyblock, node ); + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = copy_signature(NULL, sig); + if( pub_where ) + insert_kbnode( node, new_kbnode(pkt), 0 ); + else + add_kbnode( pub_keyblock, new_kbnode(pkt) ); + return 1; +} + + +/**************** + * Remove all selceted userids from the keyrings + */ +static void +menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + KBNODE node; + int selected=0; + + for( node = pub_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + selected = node->flag & NODFLG_SELUID; + if( selected ) { + /* Only cause a trust update if we delete a + non-revoked user id */ + if(!node->pkt->pkt.user_id->is_revoked) + update_trust=1; + delete_kbnode( node ); + if( sec_keyblock ) { + KBNODE snode; + int s_selected = 0; + PKT_user_id *uid = node->pkt->pkt.user_id; + for( snode = sec_keyblock; snode; snode = snode->next ) { + if( snode->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *suid = snode->pkt->pkt.user_id; + + s_selected = + (uid->len == suid->len + && !memcmp( uid->name, suid->name, uid->len)); + if( s_selected ) + delete_kbnode( snode ); + } + else if( s_selected + && snode->pkt->pkttype == PKT_SIGNATURE ) + delete_kbnode( snode ); + else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) + s_selected = 0; + } + } + } + } + else if( selected && node->pkt->pkttype == PKT_SIGNATURE ) + delete_kbnode( node ); + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + selected = 0; + } + commit_kbnode( &pub_keyblock ); + if( sec_keyblock ) + commit_kbnode( &sec_keyblock ); +} + + +static int +menu_delsig( KBNODE pub_keyblock ) +{ + KBNODE node; + PKT_user_id *uid = NULL; + int changed=0; + + for( node = pub_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL; + } + else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) { + int okay, valid, selfsig, inv_sig, no_key, other_err; + + tty_printf("uid "); + tty_print_utf8_string( uid->name, uid->len ); + tty_printf("\n"); + + okay = inv_sig = no_key = other_err = 0; + valid = print_and_check_one_sig( pub_keyblock, node, + &inv_sig, &no_key, &other_err, + &selfsig, 1 ); + + if( valid ) { + okay = cpr_get_answer_yes_no_quit( + "keyedit.delsig.valid", + _("Delete this good signature? (y/N/q)")); + + /* Only update trust if we delete a good signature. + The other two cases do not affect trust. */ + if(okay) + update_trust=1; + } + else if( inv_sig || other_err ) + okay = cpr_get_answer_yes_no_quit( + "keyedit.delsig.invalid", + _("Delete this invalid signature? (y/N/q)")); + else if( no_key ) + okay = cpr_get_answer_yes_no_quit( + "keyedit.delsig.unknown", + _("Delete this unknown signature? (y/N/q)")); + + if( okay == -1 ) + break; + if( okay && selfsig && !cpr_get_answer_is_yes( + "keyedit.delsig.selfsig", + _("Really delete this self-signature? (y/N)") )) + okay = 0; + if( okay ) { + delete_kbnode( node ); + changed++; + } + + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + uid = NULL; + } + + if( changed ) { + commit_kbnode( &pub_keyblock ); + tty_printf( changed == 1? _("Deleted %d signature.\n") + : _("Deleted %d signatures.\n"), changed ); + } + else + tty_printf( _("Nothing deleted.\n") ); + + return changed; +} + + +/**************** + * Remove some of the secondary keys + */ +static void +menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + KBNODE node; + int selected=0; + + for( node = pub_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + selected = node->flag & NODFLG_SELKEY; + if( selected ) { + delete_kbnode( node ); + if( sec_keyblock ) { + KBNODE snode; + int s_selected = 0; + u32 ki[2]; + + keyid_from_pk( node->pkt->pkt.public_key, ki ); + for( snode = sec_keyblock; snode; snode = snode->next ) { + if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) { + u32 ki2[2]; + + keyid_from_sk( snode->pkt->pkt.secret_key, ki2 ); + s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]); + if( s_selected ) + delete_kbnode( snode ); + } + else if( s_selected + && snode->pkt->pkttype == PKT_SIGNATURE ) + delete_kbnode( snode ); + else + s_selected = 0; + } + } + } + } + else if( selected && node->pkt->pkttype == PKT_SIGNATURE ) + delete_kbnode( node ); + else + selected = 0; + } + commit_kbnode( &pub_keyblock ); + if( sec_keyblock ) + commit_kbnode( &sec_keyblock ); + + /* No need to set update_trust here since signing keys are no + longer used to certify other keys, so there is no change in + trust when revoking/removing them */ +} + + +/**************** + * Ask for a new revoker, do the selfsignature and put it into + * both keyblocks. + * Return true if there is a new revoker + */ +static int +menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) +{ + PKT_public_key *pk=NULL,*revoker_pk=NULL; + PKT_secret_key *sk=NULL; + PKT_signature *sig=NULL; + PACKET *pkt; + struct revocation_key revkey; + size_t fprlen; + int rc; + + assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY); + + pk=pub_keyblock->pkt->pkt.public_key; + + if(pk->numrevkeys==0 && pk->version==3) + { + /* It is legal but bad for compatibility to add a revoker to a + v3 key as it means that PGP2 will not be able to use that key + anymore. Also, PGP may not expect a revoker on a v3 key. + Don't bother to ask this if the key already has a revoker - + any damage has already been done at that point. -dms */ + if(opt.expert) + { + tty_printf(_("WARNING: This is a PGP 2.x-style key. " + "Adding a designated revoker may cause\n" + " some versions of PGP to reject this key.\n")); + + if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay", + _("Are you sure you still want " + "to add it? (y/N) "))) + return 0; + } + else + { + tty_printf(_("You may not add a designated revoker to " + "a PGP 2.x-style key.\n")); + return 0; + } + } + + sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key); + + for(;;) + { + char *answer; + u32 keyid[2]; + char *p; + size_t n; + + if(revoker_pk) + free_public_key(revoker_pk); + + revoker_pk=m_alloc_clear(sizeof(*revoker_pk)); + + tty_printf("\n"); + + answer=cpr_get_utf8("keyedit.add_revoker", + _("Enter the user ID of the designated revoker: ")); + if(answer[0]=='\0' || answer[0]=='\004') + goto fail; + + rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); + + if(rc) + { + log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc)); + continue; + } + + fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen); + if(fprlen!=20) + { + log_error(_("cannot appoint a PGP 2.x style key as a " + "designated revoker\n")); + continue; + } + + revkey.class=0x80; + if(sensitive) + revkey.class|=0x40; + revkey.algid=revoker_pk->pubkey_algo; + + if(cmp_public_keys(revoker_pk,pk)==0) + { + /* This actually causes no harm (after all, a key that + designates itself as a revoker is the same as a + regular key), but it's easy enough to check. */ + log_error(_("you cannot appoint a key as its own " + "designated revoker\n")); + + continue; + } + + keyid_from_pk(pk,NULL); + + /* Does this revkey already exist? */ + if(!pk->revkey && pk->numrevkeys) + BUG(); + else + { + int i; + + for(i=0;i<pk->numrevkeys;i++) + { + if(memcmp(&pk->revkey[i],&revkey, + sizeof(struct revocation_key))==0) + { + char buf[50]; + + log_error(_("this key has already been designated " + "as a revoker\n")); + + sprintf(buf,"%08lX%08lX", + (ulong)pk->keyid[0],(ulong)pk->keyid[1]); + write_status_text(STATUS_ALREADY_SIGNED,buf); + + break; + } + } + + if(i<pk->numrevkeys) + continue; + } + + keyid_from_pk(revoker_pk,keyid); + + tty_printf("\npub %4u%c/%08lX %s ", + nbits_from_pk( revoker_pk ), + pubkey_letter( revoker_pk->pubkey_algo ), + (ulong)keyid[1], datestr_from_pk(pk) ); + + p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ); + m_free(p); + tty_printf("\n"); + print_fingerprint(revoker_pk,NULL,2); + tty_printf("\n"); + + tty_printf(_("WARNING: appointing a key as a designated revoker " + "cannot be undone!\n")); + + tty_printf("\n"); + + if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay", + _("Are you sure you want to appoint this " + "key as a designated revoker? (y/N): "))) + continue; + + free_public_key(revoker_pk); + revoker_pk=NULL; + break; + } + + /* The 1F signature must be at least v4 to carry the revocation key + subpacket. */ + rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0, + keygen_add_revkey,&revkey ); + if( rc ) + { + log_error("signing failed: %s\n", g10_errstr(rc) ); + goto fail; + } + + free_secret_key(sk); + sk=NULL; + + /* insert into secret keyblock */ + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = copy_signature(NULL, sig); + insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); + + /* insert into public keyblock */ + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); + + return 1; + + fail: + if(sk) + free_secret_key(sk); + if(sig) + free_seckey_enc(sig); + if(revoker_pk) + free_public_key(revoker_pk); + + return 0; +} + + +static int +menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + int n1, signumber, rc; + u32 expiredate; + int mainkey=0; + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk, *sub_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + + if( count_selected_keys( sec_keyblock ) ) { + tty_printf(_("Please remove selections from the secret keys.\n")); + return 0; + } + + n1 = count_selected_keys( pub_keyblock ); + if( n1 > 1 ) { + tty_printf(_("Please select at most one secondary key.\n")); + return 0; + } + else if( n1 ) + tty_printf(_("Changing expiration time for a secondary key.\n")); + else { + tty_printf(_("Changing expiration time for the primary key.\n")); + mainkey=1; + } + + no_primary_warning(pub_keyblock,0); + + expiredate = ask_expiredate(); + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = sub_pk = NULL; + uid = NULL; + signumber = 0; + for( node=pub_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + main_pk->expiredate = expiredate; + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && (node->flag & NODFLG_SELKEY ) ) { + sub_pk = node->pkt->pkt.public_key; + sub_pk->expiredate = expiredate; + } + else if( node->pkt->pkttype == PKT_USER_ID ) + uid = node->pkt->pkt.user_id; + else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE + && ( mainkey || sub_pk ) ) { + PKT_signature *sig = node->pkt->pkt.signature; + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && ( (mainkey && uid && (sig->sig_class&~3) == 0x10) + || (!mainkey && sig->sig_class == 0x18) ) ) { + /* this is a selfsignature which is to be replaced */ + PKT_signature *newsig; + PACKET *newpkt; + KBNODE sn; + int signumber2 = 0; + + signumber++; + + if( (mainkey && main_pk->version < 4) + || (!mainkey && sub_pk->version < 4 ) ) { + log_info(_( + "You can't change the expiration date of a v3 key\n")); + free_secret_key( sk ); + return 0; + } + + /* find the corresponding secret self-signature */ + for( sn=sec_keyblock; sn; sn = sn->next ) { + if( sn->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *b = sn->pkt->pkt.signature; + if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1] + && sig->sig_class == b->sig_class + && ++signumber2 == signumber ) + break; + } + } + if( !sn ) + log_info(_("No corresponding signature in secret ring\n")); + + if( mainkey ) + rc = update_keysig_packet(&newsig, sig, main_pk, uid, NULL, + sk, keygen_add_key_expire, main_pk); + else + rc = update_keysig_packet(&newsig, sig, main_pk, NULL, sub_pk, + sk, keygen_add_key_expire, sub_pk ); + if( rc ) { + log_error("make_keysig_packet failed: %s\n", + g10_errstr(rc)); + free_secret_key( sk ); + return 0; + } + /* replace the packet */ + newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + m_free( node->pkt ); + node->pkt = newpkt; + if( sn ) { + newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = copy_signature( NULL, newsig ); + free_packet( sn->pkt ); + m_free( sn->pkt ); + sn->pkt = newpkt; + } + sub_pk = NULL; + } + } + } + + free_secret_key( sk ); + update_trust=1; + return 1; +} + +static int +change_primary_uid_cb ( PKT_signature *sig, void *opaque ) +{ + byte buf[1]; + + /* first clear all primary uid flags so that we are sure none are + * lingering around */ + delete_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID); + delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID); + + /* if opaque is set,we want to set the primary id */ + if (opaque) { + buf[0] = 1; + build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 ); + } + + return 0; +} + + +/* + * Set the primary uid flag for the selected UID. We will also reset + * all other primary uid flags. For this to work with have to update + * all the signature timestamps. If we would do this with the current + * time, we lose quite a lot of information, so we use a a kludge to + * do this: Just increment the timestamp by one second which is + * sufficient to updated a signature during import. + */ +static int +menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected; + int attribute = 0; + int modified = 0; + + if ( count_selected_uids (pub_keyblock) != 1 ) { + tty_printf(_("Please select exactly one user ID.\n")); + return 0; + } + + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + + /* Is our selected uid an attribute packet? */ + for ( node=pub_keyblock; node; node = node->next ) + if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID) + attribute = (node->pkt->pkt.user_id->attrib_data!=NULL); + + for ( node=pub_keyblock; node; node = node->next ) { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + } + else if ( node->pkt->pkttype == PKT_USER_ID ) { + uid = node->pkt->pkt.user_id; + selected = node->flag & NODFLG_SELUID; + } + else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) + && attribute == (uid->attrib_data!=NULL)) { + if(sig->version < 4) { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + + log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + user); + m_free(user); + } + else { + /* This is a selfsignature which is to be replaced. + We can just ignore v3 signatures because they are + not able to carry the primary ID flag. We also + ignore self-sigs on user IDs that are not of the + same type that we are making primary. That is, if + we are making a user ID primary, we alter user IDs. + If we are making an attribute packet primary, we + alter attribute packets. */ + + /* FIXME: We must make sure that we only have one + self-signature per user ID here (not counting + revocations) */ + PKT_signature *newsig; + PACKET *newpkt; + const byte *p; + int action; + + /* see whether this signature has the primary UID flag */ + p = parse_sig_subpkt (sig->hashed, + SIGSUBPKT_PRIMARY_UID, NULL ); + if ( !p ) + p = parse_sig_subpkt (sig->unhashed, + SIGSUBPKT_PRIMARY_UID, NULL ); + if ( p && *p ) /* yes */ + action = selected? 0 : -1; + else /* no */ + action = selected? 1 : 0; + + if (action) { + int rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + change_primary_uid_cb, + action > 0? "x":NULL ); + if( rc ) { + log_error ("update_keysig_packet failed: %s\n", + g10_errstr(rc)); + free_secret_key( sk ); + return 0; + } + /* replace the packet */ + newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + m_free( node->pkt ); + node->pkt = newpkt; + modified = 1; + } + } + } + } + } + + free_secret_key( sk ); + return modified; +} + + +/* + * Set preferences to new values for the selected user IDs + */ +static int +menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected, select_all; + int modified = 0; + + no_primary_warning(pub_keyblock,1); + + select_all = !count_selected_uids (pub_keyblock); + + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + for ( node=pub_keyblock; node; node = node->next ) { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + } + else if ( node->pkt->pkttype == PKT_USER_ID ) { + uid = node->pkt->pkt.user_id; + selected = select_all || (node->flag & NODFLG_SELUID); + } + else if ( main_pk && uid && selected + && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) ) { + if( sig->version < 4 ) { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + + log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + user); + m_free(user); + } + else { + /* This is a selfsignature which is to be replaced + * We have to ignore v3 signatures because they are + * not able to carry the preferences */ + PKT_signature *newsig; + PACKET *newpkt; + int rc; + + rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + keygen_upd_std_prefs, + NULL ); + if( rc ) { + log_error ("update_keysig_packet failed: %s\n", + g10_errstr(rc)); + free_secret_key( sk ); + return 0; + } + /* replace the packet */ + newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + m_free( node->pkt ); + node->pkt = newpkt; + modified = 1; + } + } + } + } + + free_secret_key( sk ); + return modified; +} + + +/**************** + * Select one user id or remove all selection if index is 0. + * Returns: True if the selection changed; + */ +static int +menu_select_uid( KBNODE keyblock, int idx ) +{ + KBNODE node; + int i; + + /* first check that the index is valid */ + if( idx ) { + for( i=0, node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + if( ++i == idx ) + break; + } + } + if( !node ) { + tty_printf(_("No user ID with index %d\n"), idx ); + return 0; + } + } + else { /* reset all */ + for( i=0, node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) + node->flag &= ~NODFLG_SELUID; + } + return 1; + } + /* and toggle the new index */ + for( i=0, node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID ) { + if( ++i == idx ) { + if( (node->flag & NODFLG_SELUID) ) + node->flag &= ~NODFLG_SELUID; + else + node->flag |= NODFLG_SELUID; + } + } + } + + return 1; +} + +/**************** + * Select secondary keys + * Returns: True if the selection changed; + */ +static int +menu_select_key( KBNODE keyblock, int idx ) +{ + KBNODE node; + int i; + + /* first check that the index is valid */ + if( idx ) { + for( i=0, node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + if( ++i == idx ) + break; + } + } + if( !node ) { + tty_printf(_("No secondary key with index %d\n"), idx ); + return 0; + } + } + else { /* reset all */ + for( i=0, node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) + node->flag &= ~NODFLG_SELKEY; + } + return 1; + } + /* and set the new index */ + for( i=0, node = keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + if( ++i == idx ) { + if( (node->flag & NODFLG_SELKEY) ) + node->flag &= ~NODFLG_SELKEY; + else + node->flag |= NODFLG_SELKEY; + } + } + } + + return 1; +} + + +static int +count_uids_with_flag( KBNODE keyblock, unsigned flag ) +{ + KBNODE node; + int i=0; + + for( node = keyblock; node; node = node->next ) + if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) ) + i++; + return i; +} + +static int +count_keys_with_flag( KBNODE keyblock, unsigned flag ) +{ + KBNODE node; + int i=0; + + for( node = keyblock; node; node = node->next ) + if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY) + && (node->flag & flag) ) + i++; + return i; +} + +static int +count_uids( KBNODE keyblock ) +{ + KBNODE node; + int i=0; + + for( node = keyblock; node; node = node->next ) + if( node->pkt->pkttype == PKT_USER_ID ) + i++; + return i; +} + + +/**************** + * Returns true if there is at least one selected user id + */ +static int +count_selected_uids( KBNODE keyblock ) +{ + return count_uids_with_flag( keyblock, NODFLG_SELUID); +} + +static int +count_selected_keys( KBNODE keyblock ) +{ + return count_keys_with_flag( keyblock, NODFLG_SELKEY); +} + +/* returns how many real (i.e. not attribute) uids are unmarked */ +static int +real_uids_left( KBNODE keyblock ) +{ + KBNODE node; + int real=0; + + for(node=keyblock;node;node=node->next) + if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) && + !node->pkt->pkt.user_id->attrib_data) + real++; + + return real; +} + +/* + * Ask whether the signature should be revoked. If the user commits this, + * flag bit MARK_A is set on the signature and the user ID. + */ +static void +ask_revoke_sig( KBNODE keyblock, KBNODE node ) +{ + int doit=0; + PKT_signature *sig = node->pkt->pkt.signature; + KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID ); + + if( !unode ) { + log_error("Oops: no user ID for signature\n"); + return; + } + + tty_printf(_("user ID: \"")); + tty_print_utf8_string( unode->pkt->pkt.user_id->name, + unode->pkt->pkt.user_id->len ); + + if(sig->flags.exportable) + tty_printf(_("\"\nsigned with your key %08lX at %s\n"), + (ulong)sig->keyid[1], datestr_from_sig(sig) ); + else + tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"), + (ulong)sig->keyid[1], datestr_from_sig(sig) ); + + if(sig->flags.expired) + { + tty_printf(_("This signature expired on %s.\n"), + expirestr_from_sig(sig)); + /* Use a different question so we can have different help text */ + doit=cpr_get_answer_is_yes("ask_revoke_sig.expired", + _("Are you sure you still want to revoke it? (y/N) ")); + } + else + doit=cpr_get_answer_is_yes("ask_revoke_sig.one", + _("Create a revocation certificate for this signature? (y/N) ")); + + if(doit) { + node->flag |= NODFLG_MARK_A; + unode->flag |= NODFLG_MARK_A; + } +} + +/**************** + * Display all user ids of the current public key together with signatures + * done by one of our keys. Then walk over all this sigs and ask the user + * whether he wants to revoke this signature. + * Return: True when the keyblock has changed. + */ +static int +menu_revsig( KBNODE keyblock ) +{ + PKT_signature *sig; + PKT_public_key *primary_pk; + KBNODE node; + int changed = 0; + int rc, any, skip=1, all=!count_selected_uids(keyblock); + struct revocation_reason_info *reason = NULL; + + /* FIXME: detect duplicates here */ + tty_printf(_("You have signed these user IDs:\n")); + for( node = keyblock; node; node = node->next ) { + node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A); + if( node->pkt->pkttype == PKT_USER_ID ) { + if( node->flag&NODFLG_SELUID || all ) { + PKT_user_id *uid = node->pkt->pkt.user_id; + /* Hmmm: Should we show only UIDs with a signature? */ + tty_printf(" "); + tty_print_utf8_string( uid->name, uid->len ); + tty_printf("\n"); + skip=0; + } + else + skip=1; + } + else if( !skip && node->pkt->pkttype == PKT_SIGNATURE + && ((sig = node->pkt->pkt.signature), + !seckey_available(sig->keyid) ) ) { + if( (sig->sig_class&~3) == 0x10 ) { + tty_printf(_(" signed by %08lX at %s%s%s\n"), + (ulong)sig->keyid[1], datestr_from_sig(sig), + sig->flags.exportable?"":" (non-exportable)", + sig->flags.revocable?"":" (non-revocable)"); + if(sig->flags.revocable) + node->flag |= NODFLG_SELSIG; + } + else if( sig->sig_class == 0x30 ) { + tty_printf(_(" revoked by %08lX at %s\n"), + (ulong)sig->keyid[1], datestr_from_sig(sig) ); + } + } + } + + /* ask */ + for( node = keyblock; node; node = node->next ) { + if( !(node->flag & NODFLG_SELSIG) ) + continue; + ask_revoke_sig( keyblock, node ); + } + + /* present selected */ + any = 0; + for( node = keyblock; node; node = node->next ) { + if( !(node->flag & NODFLG_MARK_A) ) + continue; + if( !any ) { + any = 1; + tty_printf(_("You are about to revoke these signatures:\n")); + } + if( node->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = node->pkt->pkt.user_id; + tty_printf(" "); + tty_print_utf8_string( uid->name, uid->len ); + tty_printf("\n"); + } + else if( node->pkt->pkttype == PKT_SIGNATURE ) { + sig = node->pkt->pkt.signature; + tty_printf(_(" signed by %08lX at %s%s\n"), + (ulong)sig->keyid[1], datestr_from_sig(sig), + sig->flags.exportable?"":_(" (non-exportable)") ); + } + } + if( !any ) + return 0; /* none selected */ + + if( !cpr_get_answer_is_yes("ask_revoke_sig.okay", + _("Really create the revocation certificates? (y/N) ")) ) + return 0; /* forget it */ + + reason = ask_revocation_reason( 0, 1, 0 ); + if( !reason ) { /* user decided to cancel */ + return 0; + } + + /* now we can sign the user ids */ + reloop: /* (must use this, because we are modifing the list) */ + primary_pk = keyblock->pkt->pkt.public_key; + for( node=keyblock; node; node = node->next ) { + KBNODE unode; + PACKET *pkt; + struct sign_attrib attrib; + PKT_secret_key *sk; + + if( !(node->flag & NODFLG_MARK_A) + || node->pkt->pkttype != PKT_SIGNATURE ) + continue; + unode = find_prev_kbnode( keyblock, node, PKT_USER_ID ); + assert( unode ); /* we already checked this */ + + memset( &attrib, 0, sizeof attrib ); + attrib.reason = reason; + attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable; + + node->flag &= ~NODFLG_MARK_A; + sk = m_alloc_secure_clear( sizeof *sk ); + if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) { + log_info(_("no secret key\n")); + continue; + } + rc = make_keysig_packet( &sig, primary_pk, + unode->pkt->pkt.user_id, + NULL, + sk, + 0x30, 0, 0, 0, 0, + sign_mk_attrib, + &attrib ); + free_secret_key(sk); + if( rc ) { + log_error(_("signing failed: %s\n"), g10_errstr(rc)); + release_revocation_reason_info( reason ); + return changed; + } + changed = 1; /* we changed the keyblock */ + update_trust = 1; + /* Are we revoking our own uid? */ + if(primary_pk->keyid[0]==sig->keyid[0] && + primary_pk->keyid[1]==sig->keyid[1]) + unode->pkt->pkt.user_id->is_revoked=1; + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + insert_kbnode( unode, new_kbnode(pkt), 0 ); + goto reloop; + } + + release_revocation_reason_info( reason ); + return changed; +} + +/* Revoke a user ID (i.e. revoke a user ID selfsig). Return true if + keyblock changed. */ +static int +menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key; + PKT_secret_key *sk = copy_secret_key( NULL, + sec_keyblock->pkt->pkt.secret_key ); + KBNODE node; + int changed = 0; + int rc; + struct revocation_reason_info *reason = NULL; + + /* Note that this is correct as per the RFCs, but nevertheless + somewhat meaningless in the real world. 1991 did define the 0x30 + sig class, but PGP 2.x did not actually implement it, so it would + probably be safe to use v4 revocations everywhere. -ds */ + + for( node = pub_keyblock; node; node = node->next ) + if(pk->version>3 || (node->pkt->pkttype==PKT_USER_ID && + node->pkt->pkt.user_id->selfsigversion>3)) + { + if((reason = ask_revocation_reason( 0, 1, 4 ))) + break; + else + goto leave; + } + + reloop: /* (better this way because we are modifing the keyring) */ + for( node = pub_keyblock; node; node = node->next ) + if(node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID)) + { + PKT_user_id *uid=node->pkt->pkt.user_id; + + if(uid->is_revoked) + { + char *user=utf8_to_native(uid->name,uid->len,0); + log_info(_("user ID \"%s\" is already revoked\n"),user); + m_free(user); + } + else + { + PACKET *pkt; + PKT_signature *sig; + struct sign_attrib attrib; + u32 timestamp=make_timestamp(); + + if(uid->created>=timestamp) + { + /* Okay, this is a problem. The user ID selfsig was + created in the future, so we need to warn the user and + set our revocation timestamp one second after that so + everything comes out clean. */ + + log_info(_("WARNING: a user ID signature is dated %d" + " seconds in the future\n"),uid->created-timestamp); + + timestamp=uid->created+1; + } + + memset( &attrib, 0, sizeof attrib ); + attrib.reason = reason; + + node->flag &= ~NODFLG_SELUID; + + rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x30, 0, + (reason==NULL)?3:0, timestamp, 0, + sign_mk_attrib, &attrib ); + if( rc ) + { + log_error(_("signing failed: %s\n"), g10_errstr(rc)); + goto leave; + } + else + { + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + insert_kbnode( node, new_kbnode(pkt), 0 ); + + /* If the trustdb has an entry for this key+uid then the + trustdb needs an update. */ + if(!update_trust + && (get_validity(pk,uid)&TRUST_MASK)>=TRUST_UNDEFINED) + update_trust=1; + + changed = 1; + node->pkt->pkt.user_id->is_revoked=1; + + goto reloop; + } + } + } + + if(changed) + commit_kbnode( &pub_keyblock ); + + leave: + free_secret_key(sk); + release_revocation_reason_info( reason ); + return changed; +} + +/**************** + * Revoke some of the secondary keys. + * Hmmm: Should we add a revocation to the secret keyring too? + * Does its all make sense to duplicate most of the information? + */ +static int +menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_public_key *mainpk; + KBNODE node; + int changed = 0; + int rc; + struct revocation_reason_info *reason = NULL; + + reason = ask_revocation_reason( 1, 0, 0 ); + if( !reason ) { /* user decided to cancel */ + return 0; + } + + reloop: /* (better this way because we are modifing the keyring) */ + mainpk = pub_keyblock->pkt->pkt.public_key; + for( node = pub_keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && (node->flag & NODFLG_SELKEY) ) { + PACKET *pkt; + PKT_signature *sig; + PKT_secret_key *sk; + PKT_public_key *subpk = node->pkt->pkt.public_key; + struct sign_attrib attrib; + + memset( &attrib, 0, sizeof attrib ); + attrib.reason = reason; + + node->flag &= ~NODFLG_SELKEY; + sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key ); + rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk, + 0x28, 0, 0, 0, 0, + sign_mk_attrib, &attrib ); + free_secret_key(sk); + if( rc ) { + log_error(_("signing failed: %s\n"), g10_errstr(rc)); + release_revocation_reason_info( reason ); + return changed; + } + changed = 1; /* we changed the keyblock */ + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + insert_kbnode( node, new_kbnode(pkt), 0 ); + goto reloop; + } + } + commit_kbnode( &pub_keyblock ); + /*commit_kbnode( &sec_keyblock );*/ + + /* No need to set update_trust here since signing keys no longer + are used to certify other keys, so there is no change in trust + when revoking/removing them */ + + release_revocation_reason_info( reason ); + return changed; +} + +/* Note that update_ownertrust is going to mark the trustdb dirty when + enabling or disabling a key. This is arguably sub-optimal as + disabled keys are still counted in the web of trust, but perhaps + not worth adding extra complexity to change. -ds */ +static int +enable_disable_key( KBNODE keyblock, int disable ) +{ + PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY ) + ->pkt->pkt.public_key; + unsigned int trust, newtrust; + + trust = newtrust = get_ownertrust (pk); + newtrust &= ~TRUST_FLAG_DISABLED; + if( disable ) + newtrust |= TRUST_FLAG_DISABLED; + if( trust == newtrust ) + return 0; /* already in that state */ + update_ownertrust(pk, newtrust ); + return 0; +} + + +static void +menu_showphoto( KBNODE keyblock ) +{ + KBNODE node; + int select_all = !count_selected_uids(keyblock); + int count=0; + PKT_public_key *pk=NULL; + u32 keyid[2]; + + /* Look for the public key first. We have to be really, really, + explicit as to which photo this is, and what key it is a UID on + since people may want to sign it. */ + + for( node = keyblock; node; node = node->next ) + { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) + { + pk = node->pkt->pkt.public_key; + keyid_from_pk(pk, keyid); + } + else if( node->pkt->pkttype == PKT_USER_ID ) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + count++; + + if((select_all || (node->flag & NODFLG_SELUID)) && + uid->attribs!=NULL) + { + int i; + + for(i=0;i<uid->numattribs;i++) + { + byte type; + u32 size; + + if(uid->attribs[i].type==ATTRIB_IMAGE && + parse_image_header(&uid->attribs[i],&type,&size)) + { + tty_printf(_("Displaying %s photo ID of size %ld for " + "key 0x%08lX (uid %d)\n"), + image_type_to_string(type,1), + (ulong)size,(ulong)keyid[1],count); + show_photos(&uid->attribs[i],1,pk,NULL); + } + } + } + } + } +} diff --git a/g10/keygen.c b/g10/keygen.c new file mode 100644 index 000000000..ff6fec852 --- /dev/null +++ b/g10/keygen.c @@ -0,0 +1,2523 @@ +/* keygen.c - generate a key pair + * 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 <ctype.h> +#include <errno.h> +#include <assert.h> +#include "util.h" +#include "main.h" +#include "packet.h" +#include "cipher.h" +#include "ttyio.h" +#include "options.h" +#include "keydb.h" +#include "trustdb.h" +#include "status.h" +#include "i18n.h" + +#define MAX_PREFS 30 + +enum para_name { + pKEYTYPE, + pKEYLENGTH, + pKEYUSAGE, + pSUBKEYTYPE, + pSUBKEYLENGTH, + pSUBKEYUSAGE, + pNAMEREAL, + pNAMEEMAIL, + pNAMECOMMENT, + pPREFERENCES, + pREVOKER, + pUSERID, + pEXPIREDATE, + pKEYEXPIRE, /* in n seconds */ + pSUBKEYEXPIRE, /* in n seconds */ + pPASSPHRASE, + pPASSPHRASE_DEK, + pPASSPHRASE_S2K +}; + +struct para_data_s { + struct para_data_s *next; + int lnr; + enum para_name key; + union { + DEK *dek; + STRING2KEY *s2k; + u32 expire; + unsigned int usage; + struct revocation_key revkey; + char value[1]; + } u; +}; + +struct output_control_s { + int lnr; + int dryrun; + int use_files; + struct { + char *fname; + char *newfname; + IOBUF stream; + armor_filter_context_t afx; + } pub; + struct { + char *fname; + char *newfname; + IOBUF stream; + armor_filter_context_t afx; + } sec; +}; + + +struct opaque_data_usage_and_pk { + unsigned int usage; + PKT_public_key *pk; +}; + + +static int prefs_initialized = 0; +static byte sym_prefs[MAX_PREFS]; +static int nsym_prefs; +static byte hash_prefs[MAX_PREFS]; +static int nhash_prefs; +static byte zip_prefs[MAX_PREFS]; +static int nzip_prefs; +static int mdc_available,ks_modify; + +static void do_generate_keypair( struct para_data_s *para, + struct output_control_s *outctrl ); +static int write_keyblock( IOBUF out, KBNODE node ); + + +static void +write_uid( KBNODE root, const char *s ) +{ + PACKET *pkt = m_alloc_clear(sizeof *pkt ); + size_t n = strlen(s); + + pkt->pkttype = PKT_USER_ID; + pkt->pkt.user_id = m_alloc_clear( sizeof *pkt->pkt.user_id + n - 1 ); + pkt->pkt.user_id->len = n; + pkt->pkt.user_id->ref = 1; + strcpy(pkt->pkt.user_id->name, s); + add_kbnode( root, new_kbnode( pkt ) ); +} + +static void +do_add_key_flags (PKT_signature *sig, unsigned int use) +{ + byte buf[1]; + + if (!use) + return; + + buf[0] = 0; + if (use & PUBKEY_USAGE_SIG) + buf[0] |= 0x01 | 0x02; + if (use & PUBKEY_USAGE_ENC) + buf[0] |= 0x04 | 0x08; + build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1); +} + + +int +keygen_add_key_expire( PKT_signature *sig, void *opaque ) +{ + PKT_public_key *pk = opaque; + byte buf[8]; + u32 u; + + if( pk->expiredate ) { + if(pk->expiredate > pk->timestamp) + u= pk->expiredate - pk->timestamp; + else + u= 0; + + buf[0] = (u >> 24) & 0xff; + buf[1] = (u >> 16) & 0xff; + buf[2] = (u >> 8) & 0xff; + buf[3] = u & 0xff; + build_sig_subpkt( sig, SIGSUBPKT_KEY_EXPIRE, buf, 4 ); + } + else + { + /* Make sure we don't leave a key expiration subpacket lying + around */ + delete_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE); + } + + return 0; +} + +static int +keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque) +{ + struct opaque_data_usage_and_pk *oduap = opaque; + + do_add_key_flags (sig, oduap->usage); + return keygen_add_key_expire (sig, oduap->pk); +} + +static int +set_one_pref (int val, int type, const char *item, byte *buf, int *nbuf) +{ + int i; + + for (i=0; i < *nbuf; i++ ) + if (buf[i] == val) + { + log_info (_("preference `%s' duplicated\n"), item); + return -1; + } + + if (*nbuf >= MAX_PREFS) + { + if(type==1) + log_info(_("too many cipher preferences\n")); + else if(type==2) + log_info(_("too many digest preferences\n")); + else if(type==3) + log_info(_("too many compression preferences\n")); + else + BUG(); + + return -1; + } + + buf[(*nbuf)++] = val; + return 0; +} + +#ifdef USE_AES +#define AES "S9 S8 S7 " +#else +#define AES "" +#endif + +#ifdef USE_CAST5 +#define CAST5 "S3 " +#else +#define CAST5 "" +#endif + +/* + * Parse the supplied string and use it to set the standard + * preferences. The string may be in a form like the one printed by + * "pref" (something like: "S10 S3 H3 H2 Z2 Z1") or the actual + * cipher/hash/compress names. Use NULL to set the default + * preferences. Returns: 0 = okay + */ +int +keygen_set_std_prefs (const char *string,int personal) +{ + byte sym[MAX_PREFS], hash[MAX_PREFS], zip[MAX_PREFS]; + int nsym=0, nhash=0, nzip=0, val, rc=0; + int mdc=1, modify=0; /* mdc defaults on, modify defaults off. */ + + if (!string || !ascii_strcasecmp (string, "default")) { + if (opt.def_preference_list) + string=opt.def_preference_list; + else if ( !check_cipher_algo(CIPHER_ALGO_IDEA) ) + string = AES CAST5 "S2 S1 H2 H3 Z2 Z1"; + else + string = AES CAST5 "S2 H2 H3 Z2 Z1"; + + /* If we have it, IDEA goes *after* 3DES so it won't be used + unless we're encrypting along with a V3 key. Ideally, we + would only put the S1 preference in if the key was RSA and + <=2048 bits, as that is what won't break PGP2, but that is + difficult with the current code, and not really worth + checking as a non-RSA <=2048 bit key wouldn't be usable by + PGP2 anyway. -dms */ + } + else if (!ascii_strcasecmp (string, "none")) + string = ""; + + if(strlen(string)) + { + char *tok,*prefstring; + + prefstring=m_strdup(string); /* need a writable string! */ + + while((tok=strsep(&prefstring," ,"))) + { + if((val=string_to_cipher_algo(tok))) + { + if(set_one_pref(val,1,tok,sym,&nsym)) + rc=-1; + } + else if((val=string_to_digest_algo(tok))) + { + if(set_one_pref(val,2,tok,hash,&nhash)) + rc=-1; + } + else if((val=string_to_compress_algo(tok))>-1) + { + if(set_one_pref(val,3,tok,zip,&nzip)) + rc=-1; + } + else if (ascii_strcasecmp(tok,"mdc")==0) + mdc=1; + else if (ascii_strcasecmp(tok,"no-mdc")==0) + mdc=0; + else if (ascii_strcasecmp(tok,"ks-modify")==0) + modify=1; + else if (ascii_strcasecmp(tok,"no-ks-modify")==0) + modify=0; + else + { + log_info (_("invalid item `%s' in preference string\n"),tok); + + /* Complain if IDEA is not available. */ + if(ascii_strcasecmp(tok,"s1")==0 + || ascii_strcasecmp(tok,"idea")==0) + idea_cipher_warn(1); + + rc=-1; + } + } + + m_free(prefstring); + } + + if(!rc) + { + if(personal) + { + if(personal==PREFTYPE_SYM) + { + m_free(opt.personal_cipher_prefs); + + if(nsym==0) + opt.personal_cipher_prefs=NULL; + else + { + int i; + + opt.personal_cipher_prefs= + m_alloc(sizeof(prefitem_t *)*(nsym+1)); + + for (i=0; i<nsym; i++) + { + opt.personal_cipher_prefs[i].type = PREFTYPE_SYM; + opt.personal_cipher_prefs[i].value = sym[i]; + } + + opt.personal_cipher_prefs[i].type = PREFTYPE_NONE; + opt.personal_cipher_prefs[i].value = 0; + } + } + else if(personal==PREFTYPE_HASH) + { + m_free(opt.personal_digest_prefs); + + if(nhash==0) + opt.personal_digest_prefs=NULL; + else + { + int i; + + opt.personal_digest_prefs= + m_alloc(sizeof(prefitem_t *)*(nhash+1)); + + for (i=0; i<nhash; i++) + { + opt.personal_digest_prefs[i].type = PREFTYPE_HASH; + opt.personal_digest_prefs[i].value = hash[i]; + } + + opt.personal_digest_prefs[i].type = PREFTYPE_NONE; + opt.personal_digest_prefs[i].value = 0; + } + } + else if(personal==PREFTYPE_ZIP) + { + m_free(opt.personal_compress_prefs); + + if(nzip==0) + opt.personal_compress_prefs=NULL; + else + { + int i; + + opt.personal_compress_prefs= + m_alloc(sizeof(prefitem_t *)*(nzip+1)); + + for (i=0; i<nzip; i++) + { + opt.personal_compress_prefs[i].type = PREFTYPE_ZIP; + opt.personal_compress_prefs[i].value = zip[i]; + } + + opt.personal_compress_prefs[i].type = PREFTYPE_NONE; + opt.personal_compress_prefs[i].value = 0; + } + } + } + else + { + memcpy (sym_prefs, sym, (nsym_prefs=nsym)); + memcpy (hash_prefs, hash, (nhash_prefs=nhash)); + memcpy (zip_prefs, zip, (nzip_prefs=nzip)); + mdc_available = mdc; + ks_modify = modify; + prefs_initialized = 1; + } + } + + return rc; +} + +#undef CAST5 +#undef AES + +/* Return a fake user ID containing the preferences. Caller must + free. */ +PKT_user_id *keygen_get_std_prefs(void) +{ + int i,j=0; + PKT_user_id *uid=m_alloc_clear(sizeof(PKT_user_id)); + + if(!prefs_initialized) + keygen_set_std_prefs(NULL,0); + + uid->prefs=m_alloc((sizeof(prefitem_t *)* + (nsym_prefs+nhash_prefs+nzip_prefs+1))); + + for(i=0;i<nsym_prefs;i++,j++) + { + uid->prefs[j].type=PREFTYPE_SYM; + uid->prefs[j].value=sym_prefs[i]; + } + + for(i=0;i<nhash_prefs;i++,j++) + { + uid->prefs[j].type=PREFTYPE_HASH; + uid->prefs[j].value=hash_prefs[i]; + } + + for(i=0;i<nzip_prefs;i++,j++) + { + uid->prefs[j].type=PREFTYPE_ZIP; + uid->prefs[j].value=zip_prefs[i]; + } + + uid->prefs[j].type=PREFTYPE_NONE; + uid->prefs[j].value=0; + + uid->mdc_feature=mdc_available; + uid->ks_modify=ks_modify; + + return uid; +} + +static void +add_feature_mdc (PKT_signature *sig,int enabled) +{ + const byte *s; + size_t n; + int i; + char *buf; + + s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n ); + /* Already set or cleared */ + if (s && n && + ((enabled && (s[0] & 0x01)) || (!enabled && !(s[0] & 0x01)))) + return; + + if (!s || !n) { /* create a new one */ + n = 1; + buf = m_alloc_clear (n); + } + else { + buf = m_alloc (n); + memcpy (buf, s, n); + } + + if(enabled) + buf[0] |= 0x01; /* MDC feature */ + else + buf[0] &= ~0x01; + + /* Are there any bits set? */ + for(i=0;i<n;i++) + if(buf[i]!=0) + break; + + if(i==n) + delete_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES); + else + build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n); + + m_free (buf); +} + +static void +add_keyserver_modify (PKT_signature *sig,int enabled) +{ + const byte *s; + size_t n; + int i; + char *buf; + + /* The keyserver modify flag is a negative flag (i.e. no-modify) */ + enabled=!enabled; + + s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n ); + /* Already set or cleared */ + if (s && n && + ((enabled && (s[0] & 0x80)) || (!enabled && !(s[0] & 0x80)))) + return; + + if (!s || !n) { /* create a new one */ + n = 1; + buf = m_alloc_clear (n); + } + else { + buf = m_alloc (n); + memcpy (buf, s, n); + } + + if(enabled) + buf[0] |= 0x80; /* no-modify flag */ + else + buf[0] &= ~0x80; + + /* Are there any bits set? */ + for(i=0;i<n;i++) + if(buf[i]!=0) + break; + + if(i==n) + delete_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS); + else + build_sig_subpkt (sig, SIGSUBPKT_KS_FLAGS, buf, n); + + m_free (buf); +} + +int +keygen_upd_std_prefs( PKT_signature *sig, void *opaque ) +{ + if (!prefs_initialized) + keygen_set_std_prefs (NULL, 0); + + if (nsym_prefs) + build_sig_subpkt (sig, SIGSUBPKT_PREF_SYM, sym_prefs, nsym_prefs); + else + { + delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM); + delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_SYM); + } + + if (nhash_prefs) + build_sig_subpkt (sig, SIGSUBPKT_PREF_HASH, hash_prefs, nhash_prefs); + else + { + delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_HASH); + delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_HASH); + } + + if (nzip_prefs) + build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs); + else + { + delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR); + delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PREF_COMPR); + } + + /* Make sure that the MDC feature flag is set if needed */ + add_feature_mdc (sig,mdc_available); + add_keyserver_modify (sig,ks_modify); + + return 0; +} + + +/**************** + * Add preference to the self signature packet. + * This is only called for packets with version > 3. + + */ +int +keygen_add_std_prefs( PKT_signature *sig, void *opaque ) +{ + PKT_public_key *pk = opaque; + + do_add_key_flags (sig, pk->pubkey_usage); + keygen_add_key_expire( sig, opaque ); + keygen_upd_std_prefs (sig, opaque); + + return 0; +} + +int +keygen_add_revkey(PKT_signature *sig, void *opaque) +{ + struct revocation_key *revkey=opaque; + byte buf[2+MAX_FINGERPRINT_LEN]; + + buf[0]=revkey->class; + buf[1]=revkey->algid; + memcpy(&buf[2],revkey->fpr,MAX_FINGERPRINT_LEN); + + build_sig_subpkt(sig,SIGSUBPKT_REV_KEY,buf,2+MAX_FINGERPRINT_LEN); + + /* All sigs with revocation keys set are nonrevocable */ + sig->flags.revocable=0; + buf[0] = 0; + build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 ); + + parse_revkeys(sig); + + return 0; +} + +static int +write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, + struct revocation_key *revkey ) +{ + PACKET *pkt; + PKT_signature *sig; + int rc=0; + KBNODE node; + PKT_public_key *pk; + + if( opt.verbose ) + log_info(_("writing direct signature\n")); + + /* get the pk packet from the pub_tree */ + node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); + if( !node ) + BUG(); + pk = node->pkt->pkt.public_key; + + /* we have to cache the key, so that the verification of the signature + * creation is able to retrieve the public key */ + cache_public_key (pk); + + /* and make the signature */ + rc = make_keysig_packet(&sig,pk,NULL,NULL,sk,0x1F,0,0,0,0, + keygen_add_revkey,revkey); + if( rc ) { + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + return rc; + } + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + add_kbnode( root, new_kbnode( pkt ) ); + return rc; +} + +static int +write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, + unsigned int use ) +{ + PACKET *pkt; + PKT_signature *sig; + PKT_user_id *uid; + int rc=0; + KBNODE node; + PKT_public_key *pk; + + if( opt.verbose ) + log_info(_("writing self signature\n")); + + /* get the uid packet from the list */ + node = find_kbnode( root, PKT_USER_ID ); + if( !node ) + BUG(); /* no user id packet in tree */ + uid = node->pkt->pkt.user_id; + /* get the pk packet from the pub_tree */ + node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); + if( !node ) + BUG(); + pk = node->pkt->pkt.public_key; + pk->pubkey_usage = use; + /* we have to cache the key, so that the verification of the signature + * creation is able to retrieve the public key */ + cache_public_key (pk); + + /* and make the signature */ + rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, + keygen_add_std_prefs, pk ); + if( rc ) { + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + return rc; + } + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + add_kbnode( root, new_kbnode( pkt ) ); + return rc; +} + +static int +write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, + unsigned int use ) +{ + PACKET *pkt; + PKT_signature *sig; + int rc=0; + KBNODE node; + PKT_public_key *pk, *subpk; + struct opaque_data_usage_and_pk oduap; + + if( opt.verbose ) + log_info(_("writing key binding signature\n")); + + /* get the pk packet from the pub_tree */ + node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); + if( !node ) + BUG(); + pk = node->pkt->pkt.public_key; + /* we have to cache the key, so that the verification of the signature + * creation is able to retrieve the public key */ + cache_public_key (pk); + + /* find the last subkey */ + subpk = NULL; + for(node=pub_root; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + subpk = node->pkt->pkt.public_key; + } + if( !subpk ) + BUG(); + + /* and make the signature */ + oduap.usage = use; + oduap.pk = subpk; + rc = make_keysig_packet( &sig, pk, NULL, subpk, sk, 0x18, 0, 0, 0, 0, + keygen_add_key_flags_and_expire, &oduap ); + if( rc ) { + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + return rc; + } + + pkt = m_alloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + add_kbnode( root, new_kbnode( pkt ) ); + return rc; +} + + +static int +gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +{ + int rc; + int i; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + MPI skey[4]; + MPI *factors; + + assert( is_ELGAMAL(algo) ); + + if( nbits < 512 ) { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits ); + } + + if( (nbits % 32) ) { + nbits = ((nbits + 31) / 32) * 32; + log_info(_("keysize rounded up to %u bits\n"), nbits ); + } + + rc = pubkey_generate( algo, nbits, skey, &factors ); + if( rc ) { + log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + return rc; + } + + sk = m_alloc_clear( sizeof *sk ); + pk = m_alloc_clear( sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if( expireval ) { + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + } + sk->pubkey_algo = pk->pubkey_algo = algo; + pk->pkey[0] = mpi_copy( skey[0] ); + pk->pkey[1] = mpi_copy( skey[1] ); + pk->pkey[2] = mpi_copy( skey[2] ); + sk->skey[0] = skey[0]; + sk->skey[1] = skey[1]; + sk->skey[2] = skey[2]; + sk->skey[3] = skey[3]; + sk->is_protected = 0; + sk->protect.algo = 0; + + sk->csum = checksum_mpi( sk->skey[3] ); + if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); + + if( dek ) { + sk->protect.algo = dek->algo; + sk->protect.s2k = *s2k; + rc = protect_secret_key( sk, dek ); + if( rc ) { + log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + } + + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + /* don't know whether it makes sense to have the factors, so for now + * we store them in the secret keyring (but they are not secret) */ + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + for(i=0; factors[i]; i++ ) + add_kbnode( sec_root, + make_mpi_comment_node("#:ELG_factor:", factors[i] )); + + return 0; +} + + +/**************** + * Generate a DSA key + */ +static int +gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +{ + int rc; + int i; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + MPI skey[5]; + MPI *factors; + + if( nbits > 1024 || nbits < 512 ) { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits ); + } + + if( (nbits % 64) ) { + nbits = ((nbits + 63) / 64) * 64; + log_info(_("keysize rounded up to %u bits\n"), nbits ); + } + + rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors ); + if( rc ) { + log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + return rc; + } + + sk = m_alloc_clear( sizeof *sk ); + pk = m_alloc_clear( sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if( expireval ) { + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + } + sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; + pk->pkey[0] = mpi_copy( skey[0] ); + pk->pkey[1] = mpi_copy( skey[1] ); + pk->pkey[2] = mpi_copy( skey[2] ); + pk->pkey[3] = mpi_copy( skey[3] ); + sk->skey[0] = skey[0]; + sk->skey[1] = skey[1]; + sk->skey[2] = skey[2]; + sk->skey[3] = skey[3]; + sk->skey[4] = skey[4]; + sk->is_protected = 0; + sk->protect.algo = 0; + + sk->csum = checksum_mpi ( sk->skey[4] ); + if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); + + if( dek ) { + sk->protect.algo = dek->algo; + sk->protect.s2k = *s2k; + rc = protect_secret_key( sk, dek ); + if( rc ) { + log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + } + + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + /* don't know whether it makes sense to have the factors, so for now + * we store them in the secret keyring (but they are not secret) + * p = 2 * q * f1 * f2 * ... * fn + * We store only f1 to f_n-1; fn can be calculated because p and q + * are known. + */ + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + for(i=1; factors[i]; i++ ) /* the first one is q */ + add_kbnode( sec_root, + make_mpi_comment_node("#:DSA_factor:", factors[i] )); + + return 0; +} + + +/* + * Generate an RSA key. + */ +static int +gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +{ + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + MPI skey[6]; + MPI *factors; + + assert( is_RSA(algo) ); + + if( nbits < 1024 ) { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits ); + } + + if( (nbits % 32) ) { + nbits = ((nbits + 31) / 32) * 32; + log_info(_("keysize rounded up to %u bits\n"), nbits ); + } + + rc = pubkey_generate( algo, nbits, skey, &factors ); + if( rc ) { + log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + return rc; + } + + sk = m_alloc_clear( sizeof *sk ); + pk = m_alloc_clear( sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if( expireval ) { + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + } + sk->pubkey_algo = pk->pubkey_algo = algo; + pk->pkey[0] = mpi_copy( skey[0] ); + pk->pkey[1] = mpi_copy( skey[1] ); + sk->skey[0] = skey[0]; + sk->skey[1] = skey[1]; + sk->skey[2] = skey[2]; + sk->skey[3] = skey[3]; + sk->skey[4] = skey[4]; + sk->skey[5] = skey[5]; + sk->is_protected = 0; + sk->protect.algo = 0; + + sk->csum = checksum_mpi (sk->skey[2] ); + sk->csum += checksum_mpi (sk->skey[3] ); + sk->csum += checksum_mpi (sk->skey[4] ); + sk->csum += checksum_mpi (sk->skey[5] ); + if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); + + if( dek ) { + sk->protect.algo = dek->algo; + sk->protect.s2k = *s2k; + rc = protect_secret_key( sk, dek ); + if( rc ) { + log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + } + + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + pkt = m_alloc_clear(sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + return 0; +} + + +/**************** + * check valid days: + * return 0 on error or the multiplier + */ +static int +check_valid_days( const char *s ) +{ + if( !isdigit(*s) ) + return 0; + for( s++; *s; s++) + if( !isdigit(*s) ) + break; + if( !*s ) + return 1; + if( s[1] ) + return 0; /* e.g. "2323wc" */ + if( *s == 'd' || *s == 'D' ) + return 1; + if( *s == 'w' || *s == 'W' ) + return 7; + if( *s == 'm' || *s == 'M' ) + return 30; + if( *s == 'y' || *s == 'Y' ) + return 365; + return 0; +} + + +/**************** + * Returns: 0 to create both a DSA and a ElGamal key. + * and only if key flags are to be written the desired usage. + */ +static int +ask_algo (int addmode, unsigned int *r_usage) +{ + char *answer; + int algo; + + *r_usage = 0; + tty_printf(_("Please select what kind of key you want:\n")); + if( !addmode ) + tty_printf(_(" (%d) DSA and ElGamal (default)\n"), 1 ); + tty_printf( _(" (%d) DSA (sign only)\n"), 2 ); + if( addmode ) + tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 ); + if (opt.expert) + tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 4 ); + tty_printf( _(" (%d) RSA (sign only)\n"), 5 ); + if (addmode) + tty_printf( _(" (%d) RSA (encrypt only)\n"), 6 ); + if (opt.expert) + tty_printf( _(" (%d) RSA (sign and encrypt)\n"), 7 ); + + for(;;) { + answer = cpr_get("keygen.algo",_("Your selection? ")); + cpr_kill_prompt(); + algo = *answer? atoi(answer): 1; + m_free(answer); + if( algo == 1 && !addmode ) { + algo = 0; /* create both keys */ + break; + } + else if( algo == 7 && opt.expert ) { + algo = PUBKEY_ALGO_RSA; + *r_usage = PUBKEY_USAGE_ENC | PUBKEY_USAGE_SIG; + break; + } + else if( algo == 6 && addmode ) { + algo = PUBKEY_ALGO_RSA; + *r_usage = PUBKEY_USAGE_ENC; + break; + } + else if( algo == 5 ) { + algo = PUBKEY_ALGO_RSA; + *r_usage = PUBKEY_USAGE_SIG; + break; + } + else if( algo == 4 && opt.expert) + { + tty_printf(_( +"The use of this algorithm is only supported by GnuPG. You will not be\n" +"able to use this key to communicate with PGP users. This algorithm is also\n" +"very slow, and may not be as secure as the other choices.\n")); + + if( cpr_get_answer_is_yes("keygen.algo.elg_se", + _("Create anyway? "))) + { + algo = PUBKEY_ALGO_ELGAMAL; + break; + } + } + else if( algo == 3 && addmode ) { + algo = PUBKEY_ALGO_ELGAMAL_E; + break; + } + else if( algo == 2 ) { + algo = PUBKEY_ALGO_DSA; + break; + } + else + tty_printf(_("Invalid selection.\n")); + } + return algo; +} + + +static unsigned +ask_keysize( int algo ) +{ + char *answer; + unsigned nbits; + + if (algo != PUBKEY_ALGO_DSA && algo != PUBKEY_ALGO_RSA) { + tty_printf (_("About to generate a new %s keypair.\n" + " minimum keysize is 768 bits\n" + " default keysize is 1024 bits\n" + " highest suggested keysize is 2048 bits\n"), + pubkey_algo_to_string(algo) ); + } + + for(;;) { + answer = cpr_get("keygen.size", + _("What keysize do you want? (1024) ")); + cpr_kill_prompt(); + nbits = *answer? atoi(answer): 1024; + m_free(answer); + if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) ) + tty_printf(_("DSA only allows keysizes from 512 to 1024\n")); + else if( algo == PUBKEY_ALGO_RSA && nbits < 1024 ) + tty_printf(_("keysize too small;" + " 1024 is smallest value allowed for RSA.\n")); + else if( nbits < 768 ) + tty_printf(_("keysize too small;" + " 768 is smallest value allowed.\n")); + else if( nbits > 4096 ) { + /* It is ridiculous and an annoyance to use larger key sizes! + * GnuPG can handle much larger sizes; but it takes an eternity + * to create such a key (but less than the time the Sirius + * Computer Corporation needs to process one of the usual + * complaints) and {de,en}cryption although needs some time. + * So, before you complain about this limitation, I suggest that + * you start a discussion with Marvin about this theme and then + * do whatever you want. */ + tty_printf(_("keysize too large; %d is largest value allowed.\n"), + 4096); + } + else if( nbits > 2048 && !cpr_enabled() ) { + tty_printf( + _("Keysizes larger than 2048 are not suggested because\n" + "computations take REALLY long!\n")); + if( cpr_get_answer_is_yes("keygen.size.huge.okay",_( + "Are you sure that you want this keysize? ")) ) { + tty_printf(_("Okay, but keep in mind that your monitor " + "and keyboard radiation is also very vulnerable " + "to attacks!\n")); + break; + } + } + else + break; + } + tty_printf(_("Requested keysize is %u bits\n"), nbits ); + if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) { + nbits = ((nbits + 63) / 64) * 64; + tty_printf(_("rounded up to %u bits\n"), nbits ); + } + else if( (nbits % 32) ) { + nbits = ((nbits + 31) / 32) * 32; + tty_printf(_("rounded up to %u bits\n"), nbits ); + } + return nbits; +} + + +/**************** + * Parse an expire string and return it's value in days. + * Returns -1 on error. + */ +static int +parse_expire_string( const char *string ) +{ + int mult; + u32 abs_date=0; + u32 curtime = make_timestamp(); + int valid_days; + + if( !*string ) + valid_days = 0; + else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime ) { + /* This calculation is not perfectly okay because we + * are later going to simply multiply by 86400 and don't + * correct for leapseconds. A solution would be to change + * the whole implemenation to work with dates and not intervals + * which are required for v3 keys. + */ + valid_days = abs_date/86400-curtime/86400+1; + } + else if( (mult=check_valid_days(string)) ) { + valid_days = atoi(string) * mult; + if( valid_days < 0 || valid_days > 39447 ) + valid_days = 0; + } + else { + valid_days = -1; + } + return valid_days; +} + +/* object == 0 for a key, and 1 for a sig */ +u32 +ask_expire_interval(int object) +{ + char *answer; + int valid_days=0; + u32 interval = 0; + + switch(object) + { + case 0: + tty_printf(_("Please specify how long the key should be valid.\n" + " 0 = key does not expire\n" + " <n> = key expires in n days\n" + " <n>w = key expires in n weeks\n" + " <n>m = key expires in n months\n" + " <n>y = key expires in n years\n")); + break; + + case 1: + tty_printf(_("Please specify how long the signature should be valid.\n" + " 0 = signature does not expire\n" + " <n> = signature expires in n days\n" + " <n>w = signature expires in n weeks\n" + " <n>m = signature expires in n months\n" + " <n>y = signature expires in n years\n")); + break; + + default: + BUG(); + } + + /* Note: The elgamal subkey for DSA has no expiration date because + * it must be signed with the DSA key and this one has the expiration + * date */ + + answer = NULL; + for(;;) { + u32 curtime=make_timestamp(); + + m_free(answer); + if(object==0) + answer = cpr_get("keygen.valid",_("Key is valid for? (0) ")); + else + answer = cpr_get("siggen.valid",_("Signature is valid for? (0) ")); + cpr_kill_prompt(); + trim_spaces(answer); + valid_days = parse_expire_string( answer ); + if( valid_days < 0 ) { + tty_printf(_("invalid value\n")); + continue; + } + + if( !valid_days ) { + tty_printf(_("%s does not expire at all\n"), + object==0?"Key":"Signature"); + interval = 0; + } + else { + interval = valid_days * 86400L; + /* print the date when the key expires */ + tty_printf(_("%s expires at %s\n"), + object==0?"Key":"Signature", + asctimestamp((ulong)(curtime + interval) ) ); + /* FIXME: This check yields warning on alhas: + write a configure check and to this check here only for 32 bit machines */ + if( (time_t)((ulong)(curtime+interval)) < 0 ) + tty_printf(_("Your system can't display dates beyond 2038.\n" + "However, it will be correctly handled up to 2106.\n")); + } + + if( cpr_enabled() || cpr_get_answer_is_yes("keygen.valid.okay", + _("Is this correct (y/n)? ")) ) + break; + } + m_free(answer); + return interval; +} + +u32 +ask_expiredate() +{ + u32 x = ask_expire_interval(0); + return x? make_timestamp() + x : 0; +} + +static int +has_invalid_email_chars( const char *s ) +{ + int at_seen=0; + static char valid_chars[] = "01234567890_-." + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + for( ; *s; s++ ) { + if( *s & 0x80 ) + return 1; + if( *s == '@' ) + at_seen=1; + else if( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) ) + return 1; + else if( at_seen && !strchr( valid_chars, *s ) ) + return 1; + } + return 0; +} + + +static char * +ask_user_id( int mode ) +{ + char *answer; + char *aname, *acomment, *amail, *uid; + + if( !mode ) + tty_printf( _("\n" +"You need a User-ID to identify your key; the software constructs the user id\n" +"from Real Name, Comment and Email Address in this form:\n" +" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") ); + uid = aname = acomment = amail = NULL; + for(;;) { + char *p; + int fail=0; + + if( !aname ) { + for(;;) { + m_free(aname); + aname = cpr_get("keygen.name",_("Real name: ")); + trim_spaces(aname); + cpr_kill_prompt(); + + if( opt.allow_freeform_uid ) + break; + + if( strpbrk( aname, "<>" ) ) + tty_printf(_("Invalid character in name\n")); + else if( isdigit(*aname) ) + tty_printf(_("Name may not start with a digit\n")); + else if( strlen(aname) < 5 ) + tty_printf(_("Name must be at least 5 characters long\n")); + else + break; + } + } + if( !amail ) { + for(;;) { + m_free(amail); + amail = cpr_get("keygen.email",_("Email address: ")); + trim_spaces(amail); + cpr_kill_prompt(); + if( !*amail ) + break; /* no email address is okay */ + else if( has_invalid_email_chars(amail) + || string_count_chr(amail,'@') != 1 + || *amail == '@' + || amail[strlen(amail)-1] == '@' + || amail[strlen(amail)-1] == '.' + || strstr(amail, "..") ) + tty_printf(_("Not a valid email address\n")); + else + break; + } + } + if( !acomment ) { + for(;;) { + m_free(acomment); + acomment = cpr_get("keygen.comment",_("Comment: ")); + trim_spaces(acomment); + cpr_kill_prompt(); + if( !*acomment ) + break; /* no comment is okay */ + else if( strpbrk( acomment, "()" ) ) + tty_printf(_("Invalid character in comment\n")); + else + break; + } + } + + + m_free(uid); + uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10); + p = stpcpy(p, aname ); + if( *acomment ) + p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")"); + if( *amail ) + p = stpcpy(stpcpy(stpcpy(p," <"), amail),">"); + + /* append a warning if we do not have dev/random + * or it is switched into quick testmode */ + if( quick_random_gen(-1) ) + strcpy(p, " (INSECURE!)" ); + + /* print a note in case that UTF8 mapping has to be done */ + for(p=uid; *p; p++ ) { + if( *p & 0x80 ) { + tty_printf(_("You are using the `%s' character set.\n"), + get_native_charset() ); + break; + } + } + + tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid); + /* fixme: add a warning if this user-id already exists */ + if( !*amail && (strchr( aname, '@' ) || strchr( acomment, '@'))) { + fail = 1; + tty_printf(_("Please don't put the email address " + "into the real name or the comment\n") ); + } + + for(;;) { + const char *ansstr = _("NnCcEeOoQq"); + + if( strlen(ansstr) != 10 ) + BUG(); + if( cpr_enabled() ) { + answer = m_strdup(ansstr+6); + answer[1] = 0; + } + else { + answer = cpr_get("keygen.userid.cmd", fail? + _("Change (N)ame, (C)omment, (E)mail or (Q)uit? ") : + _("Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? ")); + cpr_kill_prompt(); + } + if( strlen(answer) > 1 ) + ; + else if( *answer == ansstr[0] || *answer == ansstr[1] ) { + m_free(aname); aname = NULL; + break; + } + else if( *answer == ansstr[2] || *answer == ansstr[3] ) { + m_free(acomment); acomment = NULL; + break; + } + else if( *answer == ansstr[4] || *answer == ansstr[5] ) { + m_free(amail); amail = NULL; + break; + } + else if( *answer == ansstr[6] || *answer == ansstr[7] ) { + if( fail ) { + tty_printf(_("Please correct the error first\n")); + } + else { + m_free(aname); aname = NULL; + m_free(acomment); acomment = NULL; + m_free(amail); amail = NULL; + break; + } + } + else if( *answer == ansstr[8] || *answer == ansstr[9] ) { + m_free(aname); aname = NULL; + m_free(acomment); acomment = NULL; + m_free(amail); amail = NULL; + m_free(uid); uid = NULL; + break; + } + m_free(answer); + } + m_free(answer); + if( !amail && !acomment && !amail ) + break; + m_free(uid); uid = NULL; + } + if( uid ) { + char *p = native_to_utf8( uid ); + m_free( uid ); + uid = p; + } + return uid; +} + + +static DEK * +ask_passphrase( STRING2KEY **ret_s2k ) +{ + DEK *dek = NULL; + STRING2KEY *s2k; + const char *errtext = NULL; + + tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); + + s2k = m_alloc_secure( sizeof *s2k ); + for(;;) { + s2k->mode = opt.s2k_mode; + s2k->hash_algo = opt.s2k_digest_algo; + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2, + errtext, NULL); + if( !dek ) { + errtext = N_("passphrase not correctly repeated; try again"); + tty_printf(_("%s.\n"), _(errtext)); + } + else if( !dek->keylen ) { + m_free(dek); dek = NULL; + m_free(s2k); s2k = NULL; + tty_printf(_( + "You don't want a passphrase - this is probably a *bad* idea!\n" + "I will do it anyway. You can change your passphrase at any time,\n" + "using this program with the option \"--edit-key\".\n\n")); + break; + } + else + break; /* okay */ + } + *ret_s2k = s2k; + return dek; +} + + +static int +do_create( int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root, + DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate ) +{ + int rc=0; + + if( !opt.batch ) + tty_printf(_( +"We need to generate a lot of random bytes. It is a good idea to perform\n" +"some other action (type on the keyboard, move the mouse, utilize the\n" +"disks) during the prime generation; this gives the random number\n" +"generator a better chance to gain enough entropy.\n") ); + + if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E ) + rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate); + else if( algo == PUBKEY_ALGO_DSA ) + rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate); + else if( algo == PUBKEY_ALGO_RSA ) + rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate); + else + BUG(); + +#ifdef ENABLE_COMMENT_PACKETS + if( !rc ) { + add_kbnode( pub_root, + make_comment_node("#created by GNUPG v" VERSION " (" + PRINTABLE_OS_NAME ")")); + add_kbnode( sec_root, + make_comment_node("#created by GNUPG v" VERSION " (" + PRINTABLE_OS_NAME ")")); + } +#endif + return rc; +} + + +/**************** + * Generate a new user id packet, or return NULL if canceled + */ +PKT_user_id * +generate_user_id() +{ + PKT_user_id *uid; + char *p; + size_t n; + + p = ask_user_id( 1 ); + if( !p ) + return NULL; + n = strlen(p); + uid = m_alloc_clear( sizeof *uid + n - 1 ); + uid->len = n; + strcpy(uid->name, p); + uid->ref = 1; + return uid; +} + + +static void +release_parameter_list( struct para_data_s *r ) +{ + struct para_data_s *r2; + + for( ; r ; r = r2 ) { + r2 = r->next; + if( r->key == pPASSPHRASE_DEK ) + m_free( r->u.dek ); + else if( r->key == pPASSPHRASE_S2K ) + m_free( r->u.s2k ); + + m_free(r); + } +} + +static struct para_data_s * +get_parameter( struct para_data_s *para, enum para_name key ) +{ + struct para_data_s *r; + + for( r = para; r && r->key != key; r = r->next ) + ; + return r; +} + +static const char * +get_parameter_value( struct para_data_s *para, enum para_name key ) +{ + struct para_data_s *r = get_parameter( para, key ); + return (r && *r->u.value)? r->u.value : NULL; +} + +static int +get_parameter_algo( struct para_data_s *para, enum para_name key ) +{ + int i; + struct para_data_s *r = get_parameter( para, key ); + if( !r ) + return -1; + if( isdigit( *r->u.value ) ) + i = atoi( r->u.value ); + else + i = string_to_pubkey_algo( r->u.value ); + if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S) + i = 0; /* we don't want to allow generation of these algorithms */ + return i; +} + +/* + * parse the usage parameter and set the keyflags. Return true on error. + */ +static int +parse_parameter_usage (const char *fname, + struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r = get_parameter( para, key ); + char *p, *pn; + unsigned int use; + + if( !r ) + return 0; /* none (this is an optional parameter)*/ + + use = 0; + pn = r->u.value; + while ( (p = strsep (&pn, " \t,")) ) { + if ( !*p) + ; + else if ( !ascii_strcasecmp (p, "sign") ) + use |= PUBKEY_USAGE_SIG; + else if ( !ascii_strcasecmp (p, "encrypt") ) + use |= PUBKEY_USAGE_ENC; + else { + log_error("%s:%d: invalid usage list\n", fname, r->lnr ); + return -1; /* error */ + } + } + r->u.usage = use; + return 0; +} + +static int +parse_revocation_key (const char *fname, + struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r = get_parameter( para, key ); + struct revocation_key revkey; + char *pn; + int i; + + if( !r ) + return 0; /* none (this is an optional parameter) */ + + pn = r->u.value; + + revkey.class=0x80; + revkey.algid=atoi(pn); + if(!revkey.algid) + goto fail; + + /* Skip to the fpr */ + while(*pn && *pn!=':') + pn++; + + if(*pn!=':') + goto fail; + + pn++; + + for(i=0;i<MAX_FINGERPRINT_LEN && *pn;i++,pn+=2) + { + int c=hextobyte(pn); + if(c==-1) + goto fail; + + revkey.fpr[i]=c; + } + + /* skip to the tag */ + while(*pn && *pn!='s' && *pn!='S') + pn++; + + if(ascii_strcasecmp(pn,"sensitive")==0) + revkey.class|=0x40; + + memcpy(&r->u.revkey,&revkey,sizeof(struct revocation_key)); + + return 0; + + fail: + log_error("%s:%d: invalid revocation key\n", fname, r->lnr ); + return -1; /* error */ +} + + +static u32 +get_parameter_u32( struct para_data_s *para, enum para_name key ) +{ + struct para_data_s *r = get_parameter( para, key ); + + if( !r ) + return 0; + if( r->key == pKEYEXPIRE || r->key == pSUBKEYEXPIRE ) + return r->u.expire; + if( r->key == pKEYUSAGE || r->key == pSUBKEYUSAGE ) + return r->u.usage; + + return (unsigned int)strtoul( r->u.value, NULL, 10 ); +} + +static unsigned int +get_parameter_uint( struct para_data_s *para, enum para_name key ) +{ + return get_parameter_u32( para, key ); +} + +static DEK * +get_parameter_dek( struct para_data_s *para, enum para_name key ) +{ + struct para_data_s *r = get_parameter( para, key ); + return r? r->u.dek : NULL; +} + +static STRING2KEY * +get_parameter_s2k( struct para_data_s *para, enum para_name key ) +{ + struct para_data_s *r = get_parameter( para, key ); + return r? r->u.s2k : NULL; +} + +static struct revocation_key * +get_parameter_revkey( struct para_data_s *para, enum para_name key ) +{ + struct para_data_s *r = get_parameter( para, key ); + return r? &r->u.revkey : NULL; +} + +static int +proc_parameter_file( struct para_data_s *para, const char *fname, + struct output_control_s *outctrl ) +{ + struct para_data_s *r; + const char *s1, *s2, *s3; + size_t n; + char *p; + int i; + + /* check that we have all required parameters */ + assert( get_parameter( para, pKEYTYPE ) ); + i = get_parameter_algo( para, pKEYTYPE ); + if( i < 1 || check_pubkey_algo2( i, PUBKEY_USAGE_SIG ) ) { + r = get_parameter( para, pKEYTYPE ); + log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); + return -1; + } + + if (parse_parameter_usage (fname, para, pKEYUSAGE)) + return -1; + + i = get_parameter_algo( para, pSUBKEYTYPE ); + if( i > 0 && check_pubkey_algo( i ) ) { + r = get_parameter( para, pSUBKEYTYPE ); + log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); + return -1; + } + if (i > 0 && parse_parameter_usage (fname, para, pSUBKEYUSAGE)) + return -1; + + + if( !get_parameter_value( para, pUSERID ) ) { + /* create the formatted user ID */ + s1 = get_parameter_value( para, pNAMEREAL ); + s2 = get_parameter_value( para, pNAMECOMMENT ); + s3 = get_parameter_value( para, pNAMEEMAIL ); + if( s1 || s2 || s3 ) { + n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0); + r = m_alloc_clear( sizeof *r + n + 20 ); + r->key = pUSERID; + p = r->u.value; + if( s1 ) + p = stpcpy(p, s1 ); + if( s2 ) + p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")"); + if( s3 ) + p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">"); + r->next = para; + para = r; + } + } + + /* Set preferences, if any. */ + keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0); + + /* Set revoker, if any. */ + if (parse_revocation_key (fname, para, pREVOKER)) + return -1; + + /* make DEK and S2K from the Passphrase */ + r = get_parameter( para, pPASSPHRASE ); + if( r && *r->u.value ) { + /* we have a plain text passphrase - create a DEK from it. + * It is a little bit ridiculous to keep it ih secure memory + * but becuase we do this alwasy, why not here */ + STRING2KEY *s2k; + DEK *dek; + + s2k = m_alloc_secure( sizeof *s2k ); + s2k->mode = opt.s2k_mode; + s2k->hash_algo = opt.s2k_digest_algo; + set_next_passphrase( r->u.value ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, + NULL, NULL); + set_next_passphrase( NULL ); + assert( dek ); + memset( r->u.value, 0, strlen(r->u.value) ); + + r = m_alloc_clear( sizeof *r ); + r->key = pPASSPHRASE_S2K; + r->u.s2k = s2k; + r->next = para; + para = r; + r = m_alloc_clear( sizeof *r ); + r->key = pPASSPHRASE_DEK; + r->u.dek = dek; + r->next = para; + para = r; + } + + /* make KEYEXPIRE from Expire-Date */ + r = get_parameter( para, pEXPIREDATE ); + if( r && *r->u.value ) { + i = parse_expire_string( r->u.value ); + if( i < 0 ) { + log_error("%s:%d: invalid expire date\n", fname, r->lnr ); + return -1; + } + r->u.expire = i * 86400L; + r->key = pKEYEXPIRE; /* change hat entry */ + /* also set it for the subkey */ + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pSUBKEYEXPIRE; + r->u.expire = i * 86400L; + r->next = para; + para = r; + } + + if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) { + log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr ); + return -1; + } + + do_generate_keypair( para, outctrl ); + return 0; +} + + +/**************** + * Kludge to allow non interactive key generation controlled + * by a parameter file (which currently is only stdin) + * Note, that string parameters are expected to be in UTF-8 + */ +static void +read_parameter_file( const char *fname ) +{ + static struct { const char *name; + enum para_name key; + } keywords[] = { + { "Key-Type", pKEYTYPE}, + { "Key-Length", pKEYLENGTH }, + { "Key-Usage", pKEYUSAGE }, + { "Subkey-Type", pSUBKEYTYPE }, + { "Subkey-Length", pSUBKEYLENGTH }, + { "Subkey-Usage", pSUBKEYUSAGE }, + { "Name-Real", pNAMEREAL }, + { "Name-Email", pNAMEEMAIL }, + { "Name-Comment", pNAMECOMMENT }, + { "Expire-Date", pEXPIREDATE }, + { "Passphrase", pPASSPHRASE }, + { "Preferences", pPREFERENCES }, + { "Revoker", pREVOKER }, + { NULL, 0 } + }; + FILE *fp; + char line[1024], *p; + int lnr; + const char *err = NULL; + struct para_data_s *para, *r; + int i; + struct output_control_s outctrl; + + memset( &outctrl, 0, sizeof( outctrl ) ); + + if( !fname || !*fname || !strcmp(fname,"-") ) { + fp = stdin; + fname = "-"; + } + else { + fp = fopen( fname, "r" ); + if( !fp ) { + log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); + return; + } + } + + lnr = 0; + err = NULL; + para = NULL; + while( fgets( line, DIM(line)-1, fp ) ) { + char *keyword, *value; + + lnr++; + if( *line && line[strlen(line)-1] != '\n' ) { + err = "line too long"; + break; + } + for( p = line; isspace(*(byte*)p); p++ ) + ; + if( !*p || *p == '#' ) + continue; + keyword = p; + if( *keyword == '%' ) { + for( ; !isspace(*(byte*)p); p++ ) + ; + if( *p ) + *p++ = 0; + for( ; isspace(*(byte*)p); p++ ) + ; + value = p; + trim_trailing_ws( value, strlen(value) ); + if( !ascii_strcasecmp( keyword, "%echo" ) ) + log_info("%s\n", value ); + else if( !ascii_strcasecmp( keyword, "%dry-run" ) ) + outctrl.dryrun = 1; + else if( !ascii_strcasecmp( keyword, "%commit" ) ) { + outctrl.lnr = lnr; + proc_parameter_file( para, fname, &outctrl ); + release_parameter_list( para ); + para = NULL; + } + else if( !ascii_strcasecmp( keyword, "%pubring" ) ) { + if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) ) + ; /* still the same file - ignore it */ + else { + m_free( outctrl.pub.newfname ); + outctrl.pub.newfname = m_strdup( value ); + outctrl.use_files = 1; + } + } + else if( !ascii_strcasecmp( keyword, "%secring" ) ) { + if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) ) + ; /* still the same file - ignore it */ + else { + m_free( outctrl.sec.newfname ); + outctrl.sec.newfname = m_strdup( value ); + outctrl.use_files = 1; + } + } + else + log_info("skipping control `%s' (%s)\n", keyword, value ); + + + continue; + } + + + if( !(p = strchr( p, ':' )) || p == keyword ) { + err = "missing colon"; + break; + } + if( *p ) + *p++ = 0; + for( ; isspace(*(byte*)p); p++ ) + ; + if( !*p ) { + err = "missing argument"; + break; + } + value = p; + trim_trailing_ws( value, strlen(value) ); + + for(i=0; keywords[i].name; i++ ) { + if( !ascii_strcasecmp( keywords[i].name, keyword ) ) + break; + } + if( !keywords[i].name ) { + err = "unknown keyword"; + break; + } + if( keywords[i].key != pKEYTYPE && !para ) { + err = "parameter block does not start with \"Key-Type\""; + break; + } + + if( keywords[i].key == pKEYTYPE && para ) { + outctrl.lnr = lnr; + proc_parameter_file( para, fname, &outctrl ); + release_parameter_list( para ); + para = NULL; + } + else { + for( r = para; r; r = r->next ) { + if( r->key == keywords[i].key ) + break; + } + if( r ) { + err = "duplicate keyword"; + break; + } + } + r = m_alloc_clear( sizeof *r + strlen( value ) ); + r->lnr = lnr; + r->key = keywords[i].key; + strcpy( r->u.value, value ); + r->next = para; + para = r; + } + if( err ) + log_error("%s:%d: %s\n", fname, lnr, err ); + else if( ferror(fp) ) { + log_error("%s:%d: read error: %s\n", fname, lnr, strerror(errno) ); + } + else if( para ) { + outctrl.lnr = lnr; + proc_parameter_file( para, fname, &outctrl ); + } + + if( outctrl.use_files ) { /* close open streams */ + iobuf_close( outctrl.pub.stream ); + iobuf_close( outctrl.sec.stream ); + m_free( outctrl.pub.fname ); + m_free( outctrl.pub.newfname ); + m_free( outctrl.sec.fname ); + m_free( outctrl.sec.newfname ); + } + + release_parameter_list( para ); + if( strcmp( fname, "-" ) ) + fclose(fp); +} + + +/**************** + * Generate a keypair + * (fname is only used in batch mode) + */ +void +generate_keypair( const char *fname ) +{ + unsigned int nbits; + char *uid = NULL; + DEK *dek; + STRING2KEY *s2k; + int algo; + unsigned int use; + int both = 0; + u32 expire; + struct para_data_s *para = NULL; + struct para_data_s *r; + struct output_control_s outctrl; + + memset( &outctrl, 0, sizeof( outctrl ) ); + + if( opt.batch ) { + read_parameter_file( fname ); + return; + } + + algo = ask_algo( 0, &use ); + if( !algo ) { /* default: DSA with ElG subkey of the specified size */ + both = 1; + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); + r->next = para; + para = r; + tty_printf(_("DSA keypair will have 1024 bits.\n")); + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pKEYLENGTH; + strcpy( r->u.value, "1024" ); + r->next = para; + para = r; + + algo = PUBKEY_ALGO_ELGAMAL_E; + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pSUBKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; + } + else { + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; + + if (use) { + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pKEYUSAGE; + sprintf( r->u.value, "%s%s", + (use & PUBKEY_USAGE_SIG)? "sign ":"", + (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); + r->next = para; + para = r; + } + + } + + nbits = ask_keysize( algo ); + r = m_alloc_clear( sizeof *r + 20 ); + r->key = both? pSUBKEYLENGTH : pKEYLENGTH; + sprintf( r->u.value, "%u", nbits); + r->next = para; + para = r; + + expire = ask_expire_interval(0); + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pKEYEXPIRE; + r->u.expire = expire; + r->next = para; + para = r; + r = m_alloc_clear( sizeof *r + 20 ); + r->key = pSUBKEYEXPIRE; + r->u.expire = expire; + r->next = para; + para = r; + + uid = ask_user_id(0); + if( !uid ) { + log_error(_("Key generation canceled.\n")); + release_parameter_list( para ); + return; + } + r = m_alloc_clear( sizeof *r + strlen(uid) ); + r->key = pUSERID; + strcpy( r->u.value, uid ); + r->next = para; + para = r; + + dek = ask_passphrase( &s2k ); + if( dek ) { + r = m_alloc_clear( sizeof *r ); + r->key = pPASSPHRASE_DEK; + r->u.dek = dek; + r->next = para; + para = r; + r = m_alloc_clear( sizeof *r ); + r->key = pPASSPHRASE_S2K; + r->u.s2k = s2k; + r->next = para; + para = r; + } + + proc_parameter_file( para, "[internal]", &outctrl ); + release_parameter_list( para ); +} + + +static void +print_status_key_created (int letter, PKT_public_key *pk) +{ + byte array[MAX_FINGERPRINT_LEN], *s; + char buf[MAX_FINGERPRINT_LEN*2+30], *p; + size_t i, n; + + p = buf; + *p++ = letter; + *p++ = ' '; + fingerprint_from_pk (pk, array, &n); + s = array; + for (i=0; i < n ; i++, s++, p += 2) + sprintf (p, "%02X", *s); + *p = 0; + write_status_text (STATUS_KEY_CREATED, buf); +} + +static void +do_generate_keypair( struct para_data_s *para, + struct output_control_s *outctrl ) +{ + KBNODE pub_root = NULL; + KBNODE sec_root = NULL; + PKT_secret_key *sk = NULL; + const char *s; + struct revocation_key *revkey; + int rc; + int did_sub = 0; + + if( outctrl->dryrun ) { + log_info("dry-run mode - key generation skipped\n"); + return; + } + + + if( outctrl->use_files ) { + if( outctrl->pub.newfname ) { + iobuf_close(outctrl->pub.stream); + outctrl->pub.stream = NULL; + m_free( outctrl->pub.fname ); + outctrl->pub.fname = outctrl->pub.newfname; + outctrl->pub.newfname = NULL; + + outctrl->pub.stream = iobuf_create( outctrl->pub.fname ); + if( !outctrl->pub.stream ) { + log_error("can't create `%s': %s\n", outctrl->pub.newfname, + strerror(errno) ); + return; + } + if( opt.armor ) { + outctrl->pub.afx.what = 1; + iobuf_push_filter( outctrl->pub.stream, armor_filter, + &outctrl->pub.afx ); + } + } + if( outctrl->sec.newfname ) { + iobuf_close(outctrl->sec.stream); + outctrl->sec.stream = NULL; + m_free( outctrl->sec.fname ); + outctrl->sec.fname = outctrl->sec.newfname; + outctrl->sec.newfname = NULL; + + outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); + if( !outctrl->sec.stream ) { + log_error("can't create `%s': %s\n", outctrl->sec.newfname, + strerror(errno) ); + return; + } + if( opt.armor ) { + outctrl->sec.afx.what = 5; + iobuf_push_filter( outctrl->sec.stream, armor_filter, + &outctrl->sec.afx ); + } + } + assert( outctrl->pub.stream ); + assert( outctrl->sec.stream ); + if( opt.verbose ) { + log_info(_("writing public key to `%s'\n"), outctrl->pub.fname ); + log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname ); + } + } + + + /* we create the packets as a tree of kbnodes. Because the structure + * we create is known in advance we simply generate a linked list + * The first packet is a dummy comment packet which we flag + * as deleted. The very first packet must always be a KEY packet. + */ + pub_root = make_comment_node("#"); delete_kbnode(pub_root); + sec_root = make_comment_node("#"); delete_kbnode(sec_root); + + rc = do_create( get_parameter_algo( para, pKEYTYPE ), + get_parameter_uint( para, pKEYLENGTH ), + pub_root, sec_root, + get_parameter_dek( para, pPASSPHRASE_DEK ), + get_parameter_s2k( para, pPASSPHRASE_S2K ), + &sk, + get_parameter_u32( para, pKEYEXPIRE ) ); + + if(!rc && (revkey=get_parameter_revkey(para,pREVOKER))) + { + rc=write_direct_sig(pub_root,pub_root,sk,revkey); + if(!rc) + write_direct_sig(sec_root,pub_root,sk,revkey); + } + + if( !rc && (s=get_parameter_value(para, pUSERID)) ) { + write_uid(pub_root, s ); + if( !rc ) + write_uid(sec_root, s ); + if( !rc ) + rc = write_selfsig(pub_root, pub_root, sk, + get_parameter_uint (para, pKEYUSAGE)); + if( !rc ) + rc = write_selfsig(sec_root, pub_root, sk, + get_parameter_uint (para, pKEYUSAGE)); + } + + if( get_parameter( para, pSUBKEYTYPE ) ) { + rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ), + get_parameter_uint( para, pSUBKEYLENGTH ), + pub_root, sec_root, + get_parameter_dek( para, pPASSPHRASE_DEK ), + get_parameter_s2k( para, pPASSPHRASE_S2K ), + NULL, + get_parameter_u32( para, pSUBKEYEXPIRE ) ); + if( !rc ) + rc = write_keybinding(pub_root, pub_root, sk, + get_parameter_uint (para, pSUBKEYUSAGE)); + if( !rc ) + rc = write_keybinding(sec_root, pub_root, sk, + get_parameter_uint (para, pSUBKEYUSAGE)); + did_sub = 1; + } + + + if( !rc && outctrl->use_files ) { /* direct write to specified files */ + rc = write_keyblock( outctrl->pub.stream, pub_root ); + if( rc ) + log_error("can't write public key: %s\n", g10_errstr(rc) ); + if( !rc ) { + rc = write_keyblock( outctrl->sec.stream, sec_root ); + if( rc ) + log_error("can't write secret key: %s\n", g10_errstr(rc) ); + } + + } + else if( !rc ) { /* write to the standard keyrings */ + KEYDB_HANDLE pub_hd = keydb_new (0); + KEYDB_HANDLE sec_hd = keydb_new (1); + + /* FIXME: we may have to create the keyring first */ + rc = keydb_locate_writable (pub_hd, NULL); + if (rc) + log_error (_("no writable public keyring found: %s\n"), + g10_errstr (rc)); + + if (!rc) { + rc = keydb_locate_writable (sec_hd, NULL); + if (rc) + log_error (_("no writable secret keyring found: %s\n"), + g10_errstr (rc)); + } + + if (!rc && opt.verbose) { + log_info(_("writing public key to `%s'\n"), + keydb_get_resource_name (pub_hd)); + log_info(_("writing secret key to `%s'\n"), + keydb_get_resource_name (sec_hd)); + } + + if (!rc) { + rc = keydb_insert_keyblock (pub_hd, pub_root); + if (rc) + log_error (_("error writing public keyring `%s': %s\n"), + keydb_get_resource_name (pub_hd), g10_errstr(rc)); + } + + if (!rc) { + rc = keydb_insert_keyblock (sec_hd, sec_root); + if (rc) + log_error (_("error writing secret keyring `%s': %s\n"), + keydb_get_resource_name (pub_hd), g10_errstr(rc)); + } + + keydb_release (pub_hd); + keydb_release (sec_hd); + + if (!rc) { + int no_enc_rsa = + get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA + && get_parameter_uint( para, pKEYUSAGE ) + && !(get_parameter_uint( para,pKEYUSAGE) & PUBKEY_USAGE_ENC); + PKT_public_key *pk = find_kbnode (pub_root, + PKT_PUBLIC_KEY)->pkt->pkt.public_key; + + update_ownertrust (pk, + ((get_ownertrust (pk) & ~TRUST_MASK) + | TRUST_ULTIMATE )); + + if (!opt.batch) { + tty_printf(_("public and secret key created and signed.\n") ); + tty_printf(_("key marked as ultimately trusted.\n") ); + tty_printf("\n"); + list_keyblock(pub_root,0,1,NULL); + } + + + if( !opt.batch + && ( get_parameter_algo( para, pKEYTYPE ) == PUBKEY_ALGO_DSA + || no_enc_rsa ) + && !get_parameter( para, pSUBKEYTYPE ) ) + { + tty_printf(_("Note that this key cannot be used for " + "encryption. You may want to use\n" + "the command \"--edit-key\" to generate a " + "secondary key for this purpose.\n") ); + } + } + } + + if( rc ) { + if( opt.batch ) + log_error("key generation failed: %s\n", g10_errstr(rc) ); + else + tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) ); + } + else { + PKT_public_key *pk = find_kbnode (pub_root, + PKT_PUBLIC_KEY)->pkt->pkt.public_key; + print_status_key_created (did_sub? 'B':'P', pk); + } + release_kbnode( pub_root ); + release_kbnode( sec_root ); + if( sk ) /* the unprotected secret key */ + free_secret_key(sk); +} + + +/**************** + * add a new subkey to an existing key. + * Returns true if a new key has been generated and put into the keyblocks. + */ +int +generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + int okay=0, rc=0; + KBNODE node; + PKT_secret_key *sk = NULL; /* this is the primary sk */ + int algo; + unsigned int use; + u32 expire; + unsigned nbits; + char *passphrase = NULL; + DEK *dek = NULL; + STRING2KEY *s2k = NULL; + u32 cur_time; + + /* break out the primary secret key */ + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + if( !node ) { + log_error("Oops; secret key not found anymore!\n"); + goto leave; + } + + /* make a copy of the sk to keep the protected one in the keyblock */ + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key ); + + cur_time = make_timestamp(); + if( sk->timestamp > cur_time ) { + ulong d = sk->timestamp - cur_time; + log_info( d==1 ? _("key has been created %lu second " + "in future (time warp or clock problem)\n") + : _("key has been created %lu seconds " + "in future (time warp or clock problem)\n"), d ); + if( !opt.ignore_time_conflict ) { + rc = G10ERR_TIME_CONFLICT; + goto leave; + } + } + + if (sk->version < 4) { + log_info (_("NOTE: creating subkeys for v3 keys " + "is not OpenPGP compliant\n")); + goto leave; + } + + /* unprotect to get the passphrase */ + switch( is_secret_key_protected( sk ) ) { + case -1: + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + tty_printf("This key is not protected.\n"); + break; + default: + tty_printf("Key is protected.\n"); + rc = check_secret_key( sk, 0 ); + if( !rc ) + passphrase = get_last_passphrase(); + break; + } + if( rc ) + goto leave; + + + algo = ask_algo( 1, &use ); + assert(algo); + nbits = ask_keysize( algo ); + expire = ask_expire_interval(0); + if( !cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay", + _("Really create? ") ) ) + goto leave; + + if( passphrase ) { + s2k = m_alloc_secure( sizeof *s2k ); + s2k->mode = opt.s2k_mode; + s2k->hash_algo = opt.s2k_digest_algo; + set_next_passphrase( passphrase ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, + NULL, NULL ); + } + + rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, + dek, s2k, NULL, expire ); + if( !rc ) + rc = write_keybinding(pub_keyblock, pub_keyblock, sk, use); + if( !rc ) + rc = write_keybinding(sec_keyblock, pub_keyblock, sk, use); + if( !rc ) { + okay = 1; + write_status_text (STATUS_KEY_CREATED, "S"); + } + + leave: + if( rc ) + log_error(_("Key generation failed: %s\n"), g10_errstr(rc) ); + m_free( passphrase ); + m_free( dek ); + m_free( s2k ); + if( sk ) /* release the copy of the (now unprotected) secret key */ + free_secret_key(sk); + set_next_passphrase( NULL ); + return okay; +} + +/**************** + * Write a keyblock to an output stream + */ +static int +write_keyblock( IOBUF out, KBNODE node ) +{ + for( ; node ; node = node->next ) { + int rc = build_packet( out, node->pkt ); + if( rc ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + return G10ERR_WRITE_FILE; + } + } + return 0; +} diff --git a/g10/keyid.c b/g10/keyid.c new file mode 100644 index 000000000..09f24e8ea --- /dev/null +++ b/g10/keyid.c @@ -0,0 +1,518 @@ +/* keyid.c - key ID and fingerprint handling + * 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 <errno.h> +#include <time.h> +#include <assert.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 MD_HANDLE +do_fingerprint_md( PKT_public_key *pk ) +{ + MD_HANDLE md; + unsigned n; + unsigned nb[PUBKEY_MAX_NPKEY]; + unsigned nn[PUBKEY_MAX_NPKEY]; + byte *pp[PUBKEY_MAX_NPKEY]; + int i; + int npkey = pubkey_get_npkey( pk->pubkey_algo ); + + md = md_open( pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); + n = pk->version < 4 ? 8 : 6; + for(i=0; i < npkey; i++ ) { + nb[i] = mpi_get_nbits(pk->pkey[i]); + pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL ); + n += 2 + nn[i]; + } + + md_putc( md, 0x99 ); /* ctb */ + md_putc( md, n >> 8 ); /* 2 byte length header */ + md_putc( md, n ); + if( pk->version < 4 ) + md_putc( md, 3 ); + else + md_putc( md, 4 ); + + { u32 a = pk->timestamp; + md_putc( md, a >> 24 ); + md_putc( md, a >> 16 ); + md_putc( md, a >> 8 ); + md_putc( md, a ); + } + if( pk->version < 4 ) { + u16 a; + + if( pk->expiredate ) + a = (u16)((pk->expiredate - pk->timestamp) / 86400L); + else + a = 0; + md_putc( md, a >> 8 ); + md_putc( md, a ); + } + md_putc( md, pk->pubkey_algo ); + for(i=0; i < npkey; i++ ) { + md_putc( md, nb[i]>>8); + md_putc( md, nb[i] ); + md_write( md, pp[i], nn[i] ); + m_free(pp[i]); + } + md_final( md ); + + return md; +} + +static MD_HANDLE +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 ); +} + + +/**************** + * 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) ) { + lowbits = pubkey_get_npkey(sk->pubkey_algo) ? + mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */ + } + else { + const byte *dp; + MD_HANDLE md; + md = do_fingerprint_md_sk(sk); + dp = 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]; + 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) ) { + lowbits = pubkey_get_npkey(pk->pubkey_algo) ? + mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */ + pk->keyid[0] = keyid[0]; + pk->keyid[1] = keyid[1]; + } + else { + const byte *dp; + MD_HANDLE md; + md = do_fingerprint_md(pk); + dp = 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]; + 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=m_alloc(20); + + if(uid->attrib_data) + rmd160_hash_buffer(uid->namehash,uid->attrib_data,uid->attrib_len); + else + rmd160_hash_buffer(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 *p, *buf; + const byte *dp; + size_t len; + unsigned int n; + + if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) { + /* RSA in version 3 packets is special */ + MD_HANDLE md; + + md = md_open( DIGEST_ALGO_MD5, 0); + if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) { + p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL ); + md_write( md, p, n ); + m_free(buf); + p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL ); + md_write( md, p, n ); + m_free(buf); + } + md_final(md); + if( !array ) + array = m_alloc( 16 ); + len = 16; + memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); + md_close(md); + } + else { + MD_HANDLE md; + md = do_fingerprint_md(pk); + dp = md_read( md, 0 ); + len = md_digest_length( md_get_algo( md ) ); + assert( len <= MAX_FINGERPRINT_LEN ); + if( !array ) + array = m_alloc( 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] ; + md_close(md); + } + + *ret_len = len; + return array; +} + +byte * +fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) +{ + byte *p, *buf; + const char *dp; + size_t len; + unsigned n; + + if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) { + /* RSA in version 3 packets is special */ + MD_HANDLE md; + + md = md_open( DIGEST_ALGO_MD5, 0); + if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) { + p = buf = mpi_get_buffer( sk->skey[0], &n, NULL ); + md_write( md, p, n ); + m_free(buf); + p = buf = mpi_get_buffer( sk->skey[1], &n, NULL ); + md_write( md, p, n ); + m_free(buf); + } + md_final(md); + if( !array ) + array = m_alloc( 16 ); + len = 16; + memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); + md_close(md); + } + else { + MD_HANDLE md; + md = do_fingerprint_md_sk(sk); + dp = md_read( md, 0 ); + len = md_digest_length( md_get_algo( md ) ); + assert( len <= MAX_FINGERPRINT_LEN ); + if( !array ) + array = m_alloc( len ); + memcpy(array, dp, len ); + md_close(md); + } + + *ret_len = len; + return array; +} + + + diff --git a/g10/keylist.c b/g10/keylist.c new file mode 100644 index 000000000..616cea8c9 --- /dev/null +++ b/g10/keylist.c @@ -0,0 +1,1287 @@ +/* keylist.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 "photoid.h" +#include "util.h" +#include "ttyio.h" +#include "trustdb.h" +#include "main.h" +#include "i18n.h" +#include "status.h" + +static void list_all(int); +static void list_one( STRLIST names, int secret); + +struct sig_stats +{ + int inv_sigs; + int no_key; + int oth_err; +}; + +static FILE *attrib_fp=NULL; + +/**************** + * List the keys + * If list is NULL, all available keys are listed + */ +void +public_key_list( STRLIST list ) +{ + if( !list ) + list_all(0); + else + list_one( list, 0 ); +} + +void +secret_key_list( STRLIST list ) +{ + if( !list ) + list_all(1); + else /* List by user id */ + list_one( list, 1 ); +} + +void +print_seckey_info (PKT_secret_key *sk) +{ + u32 sk_keyid[2]; + size_t n; + char *p; + + keyid_from_sk (sk, sk_keyid); + tty_printf ("\nsec %4u%c/%08lX %s ", + nbits_from_sk (sk), + pubkey_letter (sk->pubkey_algo), + (ulong)sk_keyid[1], datestr_from_sk (sk)); + + p = get_user_id (sk_keyid, &n); + tty_print_utf8_string (p, n); + m_free (p); + + tty_printf ("\n"); +} + +void +print_pubkey_info (PKT_public_key *pk) +{ + u32 pk_keyid[2]; + size_t n; + char *p; + + keyid_from_pk (pk, pk_keyid); + tty_printf ("\npub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); + + + p = get_user_id (pk_keyid, &n); + tty_print_utf8_string (p, n); + m_free (p); + + tty_printf ("\n\n"); +} + +/* + mode=0 for stdout. + mode=1 for log_info + status messages + mode=2 for status messages only +*/ + +void +show_policy_url(PKT_signature *sig,int indent,int mode) +{ + const byte *p; + size_t len; + int seq=0,crit; + FILE *fp=mode?log_stream():stdout; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit))) + { + if(mode!=2) + { + int i; + char *str; + + for(i=0;i<indent;i++) + putchar(' '); + + /* This isn't UTF8 as it is a URL(?) */ + if(crit) + str=_("Critical signature policy: "); + else + str=_("Signature policy: "); + if(mode) + log_info("%s",str); + else + printf("%s",str); + print_string(fp,p,len,0); + fprintf(fp,"\n"); + } + + if(mode) + write_status_buffer ( STATUS_POLICY_URL, p, len, 0 ); + } +} + +/* + mode=0 for stdout. + mode=1 for log_info + status messages + mode=2 for status messages only +*/ + +void +show_notation(PKT_signature *sig,int indent,int mode) +{ + const byte *p; + size_t len; + int seq=0,crit; + FILE *fp=mode?log_stream():stdout; + + /* There may be multiple notations in the same sig. */ + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) + if(len>=8) + { + int n1,n2; + + n1=(p[4]<<8)|p[5]; + n2=(p[6]<<8)|p[7]; + + if(8+n1+n2!=len) + { + log_info(_("WARNING: invalid notation data found\n")); + return; + } + + if(mode!=2) + { + int i; + char *str; + + for(i=0;i<indent;i++) + putchar(' '); + + /* This is UTF8 */ + if(crit) + str=_("Critical signature notation: "); + else + str=_("Signature notation: "); + if(mode) + log_info("%s",str); + else + printf("%s",str); + print_utf8_string(fp,p+8,n1); + fprintf(fp,"="); + + if(*p&0x80) + print_utf8_string(fp,p+8+n1,n2); + else + fprintf(fp,"[ %s ]",_("not human readable")); + + fprintf(fp,"\n"); + } + + if(mode) + { + write_status_buffer ( STATUS_NOTATION_NAME, p+8 , n1, 0 ); + write_status_buffer ( STATUS_NOTATION_DATA, p+8+n1, n2, 50 ); + } + } + else + log_info(_("WARNING: invalid notation data found\n")); +} + +static void +print_signature_stats(struct sig_stats *s) +{ + if( s->inv_sigs == 1 ) + tty_printf(_("1 bad signature\n") ); + else if( s->inv_sigs ) + tty_printf(_("%d bad signatures\n"), s->inv_sigs ); + if( s->no_key == 1 ) + tty_printf(_("1 signature not checked due to a missing key\n") ); + else if( s->no_key ) + tty_printf(_("%d signatures not checked due to missing keys\n"),s->no_key); + if( s->oth_err == 1 ) + tty_printf(_("1 signature not checked due to an error\n") ); + else if( s->oth_err ) + tty_printf(_("%d signatures not checked due to errors\n"), s->oth_err ); +} + +static void +list_all( int secret ) +{ + KEYDB_HANDLE hd; + KBNODE keyblock = NULL; + int rc=0; + const char *lastresname, *resname; + struct sig_stats stats; + + memset(&stats,0,sizeof(stats)); + + hd = keydb_new (secret); + if (!hd) + rc = G10ERR_GENERAL; + else + rc = keydb_search_first (hd); + if( rc ) { + if( rc != -1 ) + log_error("keydb_search_first failed: %s\n", g10_errstr(rc) ); + goto leave; + } + + lastresname = NULL; + do { + rc = keydb_get_keyblock (hd, &keyblock); + if (rc) { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + goto leave; + } + if(!opt.with_colons) + { + resname = keydb_get_resource_name (hd); + if (lastresname != resname ) + { + int i; + + printf("%s\n", resname ); + for(i=strlen(resname); i; i-- ) + putchar('-'); + putchar('\n'); + lastresname = resname; + } + } + merge_keys_and_selfsig( keyblock ); + list_keyblock( keyblock, secret, opt.fingerprint, + opt.check_sigs?&stats:NULL); + release_kbnode( keyblock ); + keyblock = NULL; + } while (!(rc = keydb_search_next (hd))); + if( rc && rc != -1 ) + log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); + + if(opt.check_sigs && !opt.with_colons) + print_signature_stats(&stats); + + leave: + release_kbnode (keyblock); + keydb_release (hd); +} + + +static void +list_one( STRLIST names, int secret ) +{ + int rc = 0; + KBNODE keyblock = NULL; + GETKEY_CTX ctx; + const char *resname; + char *keyring_str = _("Keyring"); + int i; + struct sig_stats stats; + + memset(&stats,0,sizeof(stats)); + + /* fixme: using the bynames function has the disadvantage that we + * don't know wether one of the names given was not found. OTOH, + * this function has the advantage to list the names in the + * sequence as defined by the keyDB and does not duplicate + * outputs. A solution could be do test whether all given have + * been listed (this needs a way to use the keyDB search + * functions) or to have the search function return indicators for + * found names. Yet another way is to use the keydb search + * facilities directly. */ + if( secret ) { + rc = get_seckey_bynames( &ctx, NULL, names, &keyblock ); + if( rc ) { + log_error("error reading key: %s\n", g10_errstr(rc) ); + get_seckey_end( ctx ); + return; + } + do { + if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) { + resname = keydb_get_resource_name (get_ctx_handle(ctx)); + printf("%s: %s\n", keyring_str, resname); + for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- ) + putchar('-'); + putchar('\n'); + } + list_keyblock( keyblock, 1, opt.fingerprint, NULL ); + release_kbnode( keyblock ); + } while( !get_seckey_next( ctx, NULL, &keyblock ) ); + get_seckey_end( ctx ); + } + else { + rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock ); + if( rc ) { + log_error("error reading key: %s\n", g10_errstr(rc) ); + get_pubkey_end( ctx ); + return; + } + do { + if ((opt.list_options&LIST_SHOW_KEYRING) && !opt.with_colons) { + resname = keydb_get_resource_name (get_ctx_handle(ctx)); + printf("%s: %s\n", keyring_str, resname); + for(i = strlen(resname) + strlen(keyring_str) + 2; i; i-- ) + putchar('-'); + putchar('\n'); + } + list_keyblock( keyblock, 0, opt.fingerprint, + opt.check_sigs?&stats:NULL ); + release_kbnode( keyblock ); + } while( !get_pubkey_next( ctx, NULL, &keyblock ) ); + get_pubkey_end( ctx ); + } + + if(opt.check_sigs && !opt.with_colons) + print_signature_stats(&stats); +} + +static void +print_key_data( PKT_public_key *pk, u32 *keyid ) +{ + int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; + int i; + + for(i=0; i < n; i++ ) { + printf("pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) ); + mpi_print(stdout, pk->pkey[i], 1 ); + putchar(':'); + putchar('\n'); + } +} + +static void +print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) +{ + if(pk || (sk && sk->protect.s2k.mode!=1001)) + { + unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage; + + if ( use & PUBKEY_USAGE_ENC ) + putchar ('e'); + + if ( use & PUBKEY_USAGE_SIG ) + { + putchar ('s'); + if( pk? pk->is_primary : sk->is_primary ) + putchar ('c'); + } + } + + if ( keyblock ) { /* figure out the usable capabilities */ + KBNODE k; + int enc=0, sign=0, cert=0, disabled=0; + + for (k=keyblock; k; k = k->next ) { + if ( k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + pk = k->pkt->pkt.public_key; + + if(pk->is_primary) + disabled=pk_is_disabled(pk); + + if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) { + if ( pk->pubkey_usage & PUBKEY_USAGE_ENC ) + enc = 1; + if ( pk->pubkey_usage & PUBKEY_USAGE_SIG ) + { + sign = 1; + if(pk->is_primary) + cert = 1; + } + } + } + else if ( k->pkt->pkttype == PKT_SECRET_KEY + || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { + sk = k->pkt->pkt.secret_key; + if ( sk->is_valid && !sk->is_revoked && !sk->has_expired + && sk->protect.s2k.mode!=1001 ) { + if ( sk->pubkey_usage & PUBKEY_USAGE_ENC ) + enc = 1; + if ( sk->pubkey_usage & PUBKEY_USAGE_SIG ) + { + sign = 1; + if(sk->is_primary) + cert = 1; + } + } + } + } + if (enc) + putchar ('E'); + if (sign) + putchar ('S'); + if (cert) + putchar ('C'); + if (disabled) + putchar ('D'); + } + + putchar(':'); +} + +void +dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk) +{ + int i; + + if(!attrib_fp) + return; + + for(i=0;i<uid->numattribs;i++) + { + if(is_status_enabled()) + { + byte array[MAX_FINGERPRINT_LEN], *p; + char buf[(MAX_FINGERPRINT_LEN*2)+90]; + size_t j,n; + + if(pk) + fingerprint_from_pk( pk, array, &n ); + else if(sk) + fingerprint_from_sk( sk, array, &n ); + else + BUG(); + + p = array; + for(j=0; j < n ; j++, p++ ) + sprintf(buf+2*j, "%02X", *p ); + + sprintf(buf+strlen(buf)," %lu %u %u %u %lu %lu %u", + (ulong)uid->attribs[i].len,uid->attribs[i].type,i+1, + uid->numattribs,(ulong)uid->created,(ulong)uid->expiredate, + ((uid->is_primary?0x01:0)| + (uid->is_revoked?0x02:0)| + (uid->is_expired?0x04:0))); + write_status_text(STATUS_ATTRIBUTE,buf); + } + + fwrite(uid->attribs[i].data,uid->attribs[i].len,1,attrib_fp); + } +} + +static void +list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) +{ + int rc = 0; + KBNODE kbctx; + KBNODE node; + PKT_public_key *pk; + PKT_secret_key *sk; + u32 keyid[2]; + int any=0; + struct sig_stats *stats=opaque; + int newformat=((opt.list_options&LIST_SHOW_VALIDITY) && !secret) + || (opt.list_options&LIST_SHOW_LONG_KEYID); + + /* get the keyid from the keyblock */ + node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); + if( !node ) { + log_error("Oops; key lost!\n"); + dump_kbnode( keyblock ); + return; + } + + if( secret ) + { + pk = NULL; + sk = node->pkt->pkt.secret_key; + keyid_from_sk( sk, keyid ); + + printf("sec%c %4u%c/",(sk->protect.s2k.mode==1001)?'#':' ', + nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo )); + + if(opt.list_options&LIST_SHOW_LONG_KEYID) + printf("%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); + else + printf("%08lX",(ulong)keyid[1]); + + printf(" %s%s",datestr_from_sk( sk ),newformat?"":" " ); + + if(newformat && sk->expiredate ) + printf(_(" [expires: %s]"), expirestr_from_sk( sk ) ); + } + else + { + int validity; + pk = node->pkt->pkt.public_key; + sk = NULL; + keyid_from_pk( pk, keyid ); + + validity=get_validity(pk,NULL); + + printf("pub %4u%c/", + nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo)); + + if(opt.list_options&LIST_SHOW_LONG_KEYID) + printf("%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); + else + printf("%08lX",(ulong)keyid[1]); + + printf(" %s%s",datestr_from_pk( pk ),newformat?"":" " ); + + /* We didn't include this before in the key listing, but there + is room in the new format, so why not? */ + if(newformat && pk->expiredate) + printf(_(" [expires: %s]"), expirestr_from_pk( pk ) ); + + if(opt.list_options&LIST_SHOW_VALIDITY) + printf(" [%s]",trust_value_to_string(validity)); + } + + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { + if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { + int indent; + /* don't list revoked or expired UIDS unless we are in + * verbose mode and signature listing has not been + * requested */ + if ( !opt.verbose && !opt.list_sigs && + (node->pkt->pkt.user_id->is_revoked || + node->pkt->pkt.user_id->is_expired )) + continue; + + if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) + dump_attribs(node->pkt->pkt.user_id,pk,sk); + + if(!any && newformat) + printf("\n"); + + if((opt.list_options&LIST_SHOW_VALIDITY) && pk) + { + const char *validity= + trust_value_to_string(get_validity(pk,node->pkt->pkt.user_id)); + + /* Includes the 3 spaces for [, ], and " ". */ + indent=((opt.list_options&LIST_SHOW_LONG_KEYID)?23:15) + -strlen(validity); + + if(indent<0) + indent=0; + + printf("uid%*s[%s] ",indent,"",validity); + } + else if(newformat) + printf("uid%*s",26,""); + else if(any) + printf("uid%*s",29,""); + + if ( node->pkt->pkt.user_id->is_revoked ) + fputs ("[revoked] ", stdout); + if ( node->pkt->pkt.user_id->is_expired ) + fputs ("[expired] ", stdout); + + print_utf8_string( stdout, node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len ); + putchar('\n'); + if( !any ) { + if( fpr ) + print_fingerprint( pk, sk, 0 ); + if( opt.with_key_data ) + print_key_data( pk, keyid ); + any = 1; + } + + if((opt.list_options&LIST_SHOW_PHOTOS) + && node->pkt->pkt.user_id->attribs!=NULL) + show_photos(node->pkt->pkt.user_id->attribs, + node->pkt->pkt.user_id->numattribs,pk,sk); + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + u32 keyid2[2]; + PKT_public_key *pk2 = node->pkt->pkt.public_key; + + if( !any ) { + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); /* of the main key */ + any = 1; + } + + keyid_from_pk( pk2, keyid2 ); + printf("sub %4u%c/", + nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo )); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + printf("%08lX%08lX",(ulong)keyid2[0],(ulong)keyid2[1]); + else + printf("%08lX",(ulong)keyid2[1]); + printf(" %s",datestr_from_pk(pk2)); + if( pk2->expiredate ) + printf(_(" [expires: %s]"), expirestr_from_pk( pk2 ) ); + putchar('\n'); + if( fpr > 1 ) + print_fingerprint( pk2, NULL, 0 ); + if( opt.with_key_data ) + print_key_data( pk2, keyid2 ); + } + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + u32 keyid2[2]; + PKT_secret_key *sk2 = node->pkt->pkt.secret_key; + + if( !any ) { + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); /* of the main key */ + any = 1; + } + + keyid_from_sk( sk2, keyid2 ); + printf("ssb %4u%c/", + nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo )); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + printf("%08lX%08lX",(ulong)keyid2[0],(ulong)keyid2[1]); + else + printf("%08lX",(ulong)keyid2[1]); + printf(" %s",datestr_from_sk( sk2 ) ); + if( sk2->expiredate ) + printf(_(" [expires: %s]"), expirestr_from_sk( sk2 ) ); + putchar('\n'); + if( fpr > 1 ) + print_fingerprint( NULL, sk2, 0 ); + } + else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + int sigrc; + char *sigstr; + + if( stats ) { + /*fflush(stdout);*/ + rc = check_key_signature( keyblock, node, NULL ); + switch( rc ) { + case 0: sigrc = '!'; break; + case G10ERR_BAD_SIGN: stats->inv_sigs++; sigrc = '-'; break; + case G10ERR_NO_PUBKEY: + case G10ERR_UNU_PUBKEY: stats->no_key++; continue; + default: stats->oth_err++; sigrc = '%'; break; + } + + /* TODO: Make sure a cached sig record here still has + the pk that issued it. See also + keyedit.c:print_and_check_one_sig */ + + } + else { + rc = 0; + sigrc = ' '; + } + + if( !any ) { /* no user id, (maybe a revocation follows)*/ + /* Check if the pk is really revoked - there could be a + 0x20 sig packet there even if we are not revoked + (say, if a revocation key issued the packet, but the + revocation key isn't present to verify it.) */ + if( sig->sig_class == 0x20 && pk->is_revoked ) + puts("[revoked]"); + else if( sig->sig_class == 0x18 ) + puts("[key binding]"); + else if( sig->sig_class == 0x28 ) + puts("[subkey revoked]"); + else + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); + any=1; + } + + if( sig->sig_class == 0x20 || sig->sig_class == 0x28 + || sig->sig_class == 0x30 ) + sigstr = "rev"; + else if( (sig->sig_class&~3) == 0x10 ) + sigstr = "sig"; + else if( sig->sig_class == 0x18 ) + sigstr = "sig"; + else if( sig->sig_class == 0x1F ) + sigstr = "sig"; + else { + printf("sig " + "[unexpected signature class 0x%02x]\n",sig->sig_class ); + continue; + } + + fputs( sigstr, stdout ); + printf("%c%c %c%c%c%c%c%c ", + sigrc,(sig->sig_class-0x10>0 && + sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', + sig->flags.exportable?' ':'L', + sig->flags.revocable?' ':'R', + sig->flags.policy_url?'P':' ', + sig->flags.notation?'N':' ', + sig->flags.expired?'X':' ', + (sig->trust_depth>9)?'T': + (sig->trust_depth>0)?'0'+sig->trust_depth:' '); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + printf("%08lX%08lX",(ulong)sig->keyid[0],(ulong)sig->keyid[1]); + else + printf("%08lX",(ulong)sig->keyid[1]); + printf(" %s ", datestr_from_sig(sig)); + if( sigrc == '%' ) + printf("[%s] ", g10_errstr(rc) ); + else if( sigrc == '?' ) + ; + else if ( !opt.fast_list_mode ) { + size_t n; + char *p = get_user_id( sig->keyid, &n ); + print_utf8_string( stdout, p, n ); + m_free(p); + } + putchar('\n'); + + if(sig->flags.policy_url && (opt.list_options&LIST_SHOW_POLICY)) + show_policy_url(sig,3,0); + + if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) + show_notation(sig,3,0); + + /* fixme: check or list other sigs here */ + } + } + putchar('\n'); +} + + +static void +list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) +{ + int rc = 0; + KBNODE kbctx; + KBNODE node; + PKT_public_key *pk; + PKT_secret_key *sk; + u32 keyid[2]; + int any=0; + int trustletter = 0; + int ulti_hack = 0; + + /* get the keyid from the keyblock */ + node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); + if( !node ) { + log_error("Oops; key lost!\n"); + dump_kbnode( keyblock ); + return; + } + + if( secret ) { + pk = NULL; + sk = node->pkt->pkt.secret_key; + keyid_from_sk( sk, keyid ); + printf("sec:u:%u:%d:%08lX%08lX:%s:%s:::", + nbits_from_sk( sk ), + sk->pubkey_algo, + (ulong)keyid[0],(ulong)keyid[1], + colon_datestr_from_sk( sk ), + colon_strtime (sk->expiredate) + /* fixme: add LID here */ ); + } + else { + pk = node->pkt->pkt.public_key; + sk = NULL; + keyid_from_pk( pk, keyid ); + fputs( "pub:", stdout ); + if ( !pk->is_valid ) + putchar ('i'); + else if ( pk->is_revoked ) + putchar ('r'); + else if ( pk->has_expired ) + putchar ('e'); + else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) + ; + else { + trustletter = get_validity_info ( pk, NULL ); + if( trustletter == 'u' ) + ulti_hack = 1; + putchar(trustletter); + } + printf(":%u:%d:%08lX%08lX:%s:%s:", + nbits_from_pk( pk ), + pk->pubkey_algo, + (ulong)keyid[0],(ulong)keyid[1], + colon_datestr_from_pk( pk ), + colon_strtime (pk->expiredate) ); + if( pk->local_id ) + printf("%lu", pk->local_id ); + putchar(':'); + if( !opt.fast_list_mode && !opt.no_expensive_trust_checks ) + putchar( get_ownertrust_info(pk) ); + putchar(':'); + } + + if (opt.fixed_list_mode) { + /* do not merge the first uid with the primary key */ + putchar(':'); + putchar(':'); + print_capabilities (pk, sk, keyblock); + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); + if( opt.with_key_data ) + print_key_data( pk, keyid ); + any = 1; + } + + + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { + if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { + PKT_user_id *uid=node->pkt->pkt.user_id; + if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) + dump_attribs(node->pkt->pkt.user_id,pk,sk); + /* + * Fixme: We need a is_valid flag here too + */ + if( any ) { + int i; + char *str=uid->attrib_data?"uat":"uid"; + if ( uid->is_revoked ) + printf("%s:r::::",str); + else if ( uid->is_expired ) + printf("%s:e::::",str); + else if ( opt.no_expensive_trust_checks ) { + printf("%s:::::",str); + } + else { + int uid_validity; + + if( pk && !ulti_hack ) + uid_validity=get_validity_info (pk, uid); + else + uid_validity = 'u'; + printf("%s:%c::::",str,uid_validity); + } + + printf("%s:",colon_strtime(uid->created)); + printf("%s:",colon_strtime(uid->expiredate)); + + namehash_from_uid(uid); + + for(i=0; i < 20; i++ ) + printf("%02X",uid->namehash[i]); + + printf("::"); + } + if(uid->attrib_data) + printf("%u %lu",uid->numattribs,uid->attrib_len); + else + print_string(stdout,uid->name,uid->len, ':' ); + putchar(':'); + if (any) + putchar('\n'); + else { + putchar(':'); + print_capabilities (pk, sk, keyblock); + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); + if( opt.with_key_data ) + print_key_data( pk, keyid ); + any = 1; + } + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + u32 keyid2[2]; + PKT_public_key *pk2 = node->pkt->pkt.public_key; + + if( !any ) { + putchar(':'); + putchar(':'); + print_capabilities (pk, sk, keyblock); + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); /* of the main key */ + any = 1; + } + + keyid_from_pk( pk2, keyid2 ); + fputs ("sub:", stdout ); + if ( !pk2->is_valid ) + putchar ('i'); + else if ( pk2->is_revoked ) + putchar ('r'); + else if ( pk2->has_expired ) + putchar ('e'); + else if ( opt.fast_list_mode || opt.no_expensive_trust_checks ) + ; + else { + /* trustletter should always be defined here */ + if(trustletter) + printf("%c", trustletter ); + } + printf(":%u:%d:%08lX%08lX:%s:%s:", + nbits_from_pk( pk2 ), + pk2->pubkey_algo, + (ulong)keyid2[0],(ulong)keyid2[1], + colon_datestr_from_pk( pk2 ), + colon_strtime (pk2->expiredate) + /* fixme: add LID and ownertrust here */ + ); + if( pk->local_id ) /* use the local_id of the main key??? */ + printf("%lu", pk->local_id ); + putchar(':'); + putchar(':'); + putchar(':'); + putchar(':'); + print_capabilities (pk2, NULL, NULL); + putchar('\n'); + if( fpr > 1 ) + print_fingerprint( pk2, NULL, 0 ); + if( opt.with_key_data ) + print_key_data( pk2, keyid2 ); + } + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + u32 keyid2[2]; + PKT_secret_key *sk2 = node->pkt->pkt.secret_key; + + if( !any ) { + putchar(':'); + putchar(':'); + print_capabilities (pk, sk, keyblock); + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); /* of the main key */ + any = 1; + } + + keyid_from_sk( sk2, keyid2 ); + printf("ssb::%u:%d:%08lX%08lX:%s:%s:::::", + nbits_from_sk( sk2 ), + sk2->pubkey_algo, + (ulong)keyid2[0],(ulong)keyid2[1], + colon_datestr_from_sk( sk2 ), + colon_strtime (sk2->expiredate) + /* fixme: add LID */ ); + print_capabilities (NULL, sk2, NULL); + putchar ('\n'); + if( fpr > 1 ) + print_fingerprint( NULL, sk2, 0 ); + } + else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + int sigrc; + char *sigstr; + + if( !any ) { /* no user id, (maybe a revocation follows)*/ + if( sig->sig_class == 0x20 ) + fputs("[revoked]:", stdout); + else if( sig->sig_class == 0x18 ) + fputs("[key binding]:", stdout); + else if( sig->sig_class == 0x28 ) + fputs("[subkey revoked]:", stdout); + else + putchar (':'); + putchar(':'); + print_capabilities (pk, sk, keyblock); + putchar('\n'); + if( fpr ) + print_fingerprint( pk, sk, 0 ); + any=1; + } + + if( sig->sig_class == 0x20 || sig->sig_class == 0x28 + || sig->sig_class == 0x30 ) + sigstr = "rev"; + else if( (sig->sig_class&~3) == 0x10 ) + sigstr = "sig"; + else if( sig->sig_class == 0x18 ) + sigstr = "sig"; + else if( sig->sig_class == 0x1F ) + sigstr = "sig"; + else { + printf ("sig::::::::::%02x%c:\n", + sig->sig_class, sig->flags.exportable?'x':'l'); + continue; + } + if( opt.check_sigs ) { + fflush(stdout); + rc = check_key_signature( keyblock, node, NULL ); + switch( rc ) { + case 0: sigrc = '!'; break; + case G10ERR_BAD_SIGN: sigrc = '-'; break; + case G10ERR_NO_PUBKEY: + case G10ERR_UNU_PUBKEY: sigrc = '?'; break; + default: sigrc = '%'; break; + } + } + else { + rc = 0; + sigrc = ' '; + } + fputs( sigstr, stdout ); + putchar(':'); + if( sigrc != ' ' ) + putchar(sigrc); + printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo, + (ulong)sig->keyid[0], (ulong)sig->keyid[1], + colon_datestr_from_sig(sig), + colon_expirestr_from_sig(sig)); + + if(sig->trust_depth || sig->trust_value) + printf("%d %d",sig->trust_depth,sig->trust_value); + printf(":"); + + if(sig->trust_regexp) + print_string(stdout,sig->trust_regexp, + strlen(sig->trust_regexp),':'); + printf(":"); + + if( sigrc == '%' ) + printf("[%s] ", g10_errstr(rc) ); + else if( sigrc == '?' ) + ; + else if ( !opt.fast_list_mode ) { + size_t n; + char *p = get_user_id( sig->keyid, &n ); + print_string( stdout, p, n, ':' ); + m_free(p); + } + printf(":%02x%c:\n", sig->sig_class,sig->flags.exportable?'x':'l'); + /* fixme: check or list other sigs here */ + } + } + if( !any ) {/* oops, no user id */ + putchar(':'); + putchar(':'); + print_capabilities (pk, sk, keyblock); + putchar('\n'); + } +} + +/* + * Reorder the keyblock so that the primary user ID (and not attribute + * packet) comes first. Fixme: Replace this by a generic sort + * function. */ +void +reorder_keyblock (KBNODE keyblock) +{ + KBNODE primary = NULL, primary0 = NULL, primary2 = NULL; + KBNODE last, node; + + for (node=keyblock; node; primary0=node, node = node->next) { + if( node->pkt->pkttype == PKT_USER_ID && + !node->pkt->pkt.user_id->attrib_data && + node->pkt->pkt.user_id->is_primary ) { + primary = primary2 = node; + for (node=node->next; node; primary2=node, node = node->next ) { + if( node->pkt->pkttype == PKT_USER_ID + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + break; + } + } + break; + } + } + if ( !primary ) + return; /* no primary key flag found (should not happen) */ + + for (last=NULL, node=keyblock; node; last = node, node = node->next) { + if( node->pkt->pkttype == PKT_USER_ID ) + break; + } + assert (node); + assert (last); /* the user ID is never the first packet */ + assert (primary0); /* ditto (this is the node before primary) */ + if ( node == primary ) + return; /* already the first one */ + + last->next = primary; + primary0->next = primary2->next; + primary2->next = node; +} + +void +list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ) +{ + reorder_keyblock (keyblock); + if (opt.with_colons) + list_keyblock_colon (keyblock, secret, fpr ); + else + list_keyblock_print (keyblock, secret, fpr, opaque ); +} + +/* + * standard function to print the finperprint. + * mode 0: as used in key listings, opt.with_colons is honored + * 1: print using log_info () + * 2: direct use of tty + * 3: direct use of tty but only primary key. + * modes 1 and 2 will try and print both subkey and primary key fingerprints + */ +void +print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) +{ + byte array[MAX_FINGERPRINT_LEN], *p; + size_t i, n; + FILE *fp; + const char *text; + int primary=0; + + if(sk) + { + if(sk->main_keyid[0]==sk->keyid[0] && sk->main_keyid[1]==sk->keyid[1]) + primary=1; + } + else + { + if(pk->main_keyid[0]==pk->keyid[0] && pk->main_keyid[1]==pk->keyid[1]) + primary=1; + } + + /* Just to be safe */ + if(mode&0x80 && !primary) + { + log_error("primary key is not really primary!\n"); + return; + } + + mode&=~0x80; + + if(!primary && (mode==1 || mode==2)) + { + if(sk) + { + PKT_secret_key *primary_sk=m_alloc_clear(sizeof(*primary_sk)); + get_seckey(primary_sk,sk->main_keyid); + print_fingerprint(NULL,primary_sk,mode|0x80); + free_secret_key(primary_sk); + } + else + { + PKT_public_key *primary_pk=m_alloc_clear(sizeof(*primary_pk)); + get_pubkey(primary_pk,pk->main_keyid); + print_fingerprint(primary_pk,NULL,mode|0x80); + free_public_key(primary_pk); + } + } + + if (mode == 1) { + fp = log_stream (); + if(primary) + text = _("Primary key fingerprint:"); + else + text = _(" Subkey fingerprint:"); + } + else if (mode == 2) { + fp = NULL; /* use tty */ + /* Translators: this should fit into 24 bytes to that the fingerprint + * data is properly aligned with the user ID */ + if(primary) + text = _(" Primary key fingerprint:"); + else + text = _(" Subkey fingerprint:"); + } + else if (mode == 3) { + fp = NULL; /* use tty */ + text = _(" Key fingerprint ="); + } + else { + fp = stdout; + text = _(" Key fingerprint ="); + } + + if (sk) + fingerprint_from_sk (sk, array, &n); + else + fingerprint_from_pk (pk, array, &n); + p = array; + if (opt.with_colons && !mode) { + fprintf (fp, "fpr:::::::::"); + for (i=0; i < n ; i++, p++ ) + fprintf (fp, "%02X", *p ); + putc(':', fp); + } + else { + if (fp) + fputs (text, fp); + else + tty_printf ("%s", text); + if (n == 20) { + for (i=0; i < n ; i++, i++, p += 2 ) { + if (fp) { + if (i == 10 ) + putc(' ', fp); + fprintf (fp, " %02X%02X", *p, p[1] ); + } + else { + if (i == 10 ) + tty_printf (" "); + tty_printf (" %02X%02X", *p, p[1]); + } + } + } + else { + for (i=0; i < n ; i++, p++ ) { + if (fp) { + if (i && !(i%8) ) + putc (' ', fp); + fprintf (fp, " %02X", *p ); + } + else { + if (i && !(i%8) ) + tty_printf (" "); + tty_printf (" %02X", *p ); + } + } + } + } + if (fp) + putc ('\n', fp); + else + tty_printf ("\n"); +} + +void set_attrib_fd(int fd) +{ + static int last_fd=-1; + + if ( fd != -1 && last_fd == fd ) + return; + + if ( attrib_fp && attrib_fp != stdout && attrib_fp != stderr ) + fclose (attrib_fp); + attrib_fp = NULL; + if ( fd == -1 ) + return; + + if( fd == 1 ) + attrib_fp = stdout; + else if( fd == 2 ) + attrib_fp = stderr; + else + attrib_fp = fdopen( fd, "w" ); + if( !attrib_fp ) { + log_fatal("can't open fd %d for attribute output: %s\n", + fd, strerror(errno)); + } + last_fd = fd; +} diff --git a/g10/keyring.c b/g10/keyring.c new file mode 100644 index 000000000..f8b6e1520 --- /dev/null +++ b/g10/keyring.c @@ -0,0 +1,1573 @@ +/* keyring.c - keyring file handling + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "util.h" +#include "keyring.h" +#include "packet.h" +#include "keydb.h" +#include "options.h" +#include "main.h" /*for check_key_signature()*/ +#include "i18n.h" + +/* off_item is a funny named for an object used to keep track of known + * keys. The idea was to use the offset to seek to the known keyblock, but + * this is not possible if more than one process is using the keyring. + */ +struct off_item { + struct off_item *next; + u32 kid[2]; + /*off_t off;*/ +}; + +typedef struct off_item **OffsetHashTable; + + +typedef struct keyring_name *KR_NAME; +struct keyring_name { + struct keyring_name *next; + int secret; + DOTLOCK lockhd; + int is_locked; + int did_full_scan; + char fname[1]; +}; +typedef struct keyring_name const * CONST_KR_NAME; + +static KR_NAME kr_names; +static int active_handles; + +static OffsetHashTable kr_offtbl; +static int kr_offtbl_ready; + + +struct keyring_handle { + CONST_KR_NAME resource; + int secret; /* this is for a secret keyring */ + struct { + CONST_KR_NAME kr; + IOBUF iobuf; + int eof; + int error; + } current; + struct { + CONST_KR_NAME kr; + off_t offset; + size_t pk_no; + size_t uid_no; + unsigned int n_packets; /*used for delete and update*/ + } found; + struct { + char *name; + char *pattern; + } word_match; +}; + + + +static int do_copy (int mode, const char *fname, KBNODE root, int secret, + off_t start_offset, unsigned int n_packets ); + + + +static struct off_item * +new_offset_item (void) +{ + struct off_item *k; + + k = m_alloc_clear (sizeof *k); + return k; +} + +#if 0 +static void +release_offset_items (struct off_item *k) +{ + struct off_item *k2; + + for (; k; k = k2) + { + k2 = k->next; + m_free (k); + } +} +#endif + +static OffsetHashTable +new_offset_hash_table (void) +{ + struct off_item **tbl; + + tbl = m_alloc_clear (2048 * sizeof *tbl); + return tbl; +} + +#if 0 +static void +release_offset_hash_table (OffsetHashTable tbl) +{ + int i; + + if (!tbl) + return; + for (i=0; i < 2048; i++) + release_offset_items (tbl[i]); + m_free (tbl); +} +#endif + +static struct off_item * +lookup_offset_hash_table (OffsetHashTable tbl, u32 *kid) +{ + struct off_item *k; + + for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next) + if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) + return k; + return NULL; +} + +static void +update_offset_hash_table (OffsetHashTable tbl, u32 *kid, off_t off) +{ + struct off_item *k; + + for (k = tbl[(kid[1] & 0x07ff)]; k; k = k->next) + { + if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) + { + /*k->off = off;*/ + return; + } + } + + k = new_offset_item (); + k->kid[0] = kid[0]; + k->kid[1] = kid[1]; + /*k->off = off;*/ + k->next = tbl[(kid[1] & 0x07ff)]; + tbl[(kid[1] & 0x07ff)] = k; +} + +static void +update_offset_hash_table_from_kb (OffsetHashTable tbl, KBNODE node, off_t off) +{ + for (; node; node = node->next) + { + if (node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + u32 aki[2]; + keyid_from_pk (node->pkt->pkt.public_key, aki); + update_offset_hash_table (tbl, aki, off); + } + } +} + +/* + * Register a filename for plain keyring files. ptr is set to a + * pointer to be used to create a handles etc, or the already-issued + * pointer if it has already been registered. The function returns 1 + * if a new keyring was registered. +*/ +int +keyring_register_filename (const char *fname, int secret, void **ptr) +{ + KR_NAME kr; + + if (active_handles) + BUG (); /* We don't allow that */ + + for (kr=kr_names; kr; kr = kr->next) + { + if ( !compare_filenames (kr->fname, fname) ) + { + *ptr=kr; + return 0; /* already registered */ + } + } + + kr = m_alloc (sizeof *kr + strlen (fname)); + strcpy (kr->fname, fname); + kr->secret = !!secret; + kr->lockhd = NULL; + kr->is_locked = 0; + kr->did_full_scan = 0; + /* keep a list of all issued pointers */ + kr->next = kr_names; + kr_names = kr; + + /* create the offset table the first time a function here is used */ + if (!kr_offtbl) + kr_offtbl = new_offset_hash_table (); + + *ptr=kr; + + return 1; +} + +int +keyring_is_writable (void *token) +{ + KR_NAME r = token; + + return r? !access (r->fname, W_OK) : 0; +} + + + +/* Create a new handle for the resource associated with TOKEN. SECRET + is just just as a cross-check. + + The returned handle must be released using keyring_release (). */ +KEYRING_HANDLE +keyring_new (void *token, int secret) +{ + KEYRING_HANDLE hd; + KR_NAME resource = token; + + assert (resource && !resource->secret == !secret); + + hd = m_alloc_clear (sizeof *hd); + hd->resource = resource; + hd->secret = !!secret; + active_handles++; + return hd; +} + +void +keyring_release (KEYRING_HANDLE hd) +{ + if (!hd) + return; + assert (active_handles > 0); + active_handles--; + m_free (hd->word_match.name); + m_free (hd->word_match.pattern); + iobuf_close (hd->current.iobuf); + m_free (hd); +} + + +const char * +keyring_get_resource_name (KEYRING_HANDLE hd) +{ + if (!hd || !hd->resource) + return NULL; + return hd->resource->fname; +} + + +/* + * Lock the keyring with the given handle, or unlok if yes is false. + * We ignore the handle and lock all registered files. + */ +int +keyring_lock (KEYRING_HANDLE hd, int yes) +{ + KR_NAME kr; + int rc = 0; + + if (yes) { + /* first make sure the lock handles are created */ + for (kr=kr_names; kr; kr = kr->next) { + if (!keyring_is_writable(kr)) + continue; + if (!kr->lockhd) { + kr->lockhd = create_dotlock( kr->fname ); + if (!kr->lockhd) { + log_info ("can't allocate lock for `%s'\n", kr->fname ); + rc = G10ERR_GENERAL; + } + } + } + if (rc) + return rc; + + /* and now set the locks */ + for (kr=kr_names; kr; kr = kr->next) { + if (!keyring_is_writable(kr)) + continue; + if (kr->is_locked) + ; + else if (make_dotlock (kr->lockhd, -1) ) { + log_info ("can't lock `%s'\n", kr->fname ); + rc = G10ERR_GENERAL; + } + else + kr->is_locked = 1; + } + } + + if (rc || !yes) { + for (kr=kr_names; kr; kr = kr->next) { + if (!keyring_is_writable(kr)) + continue; + if (!kr->is_locked) + ; + else if (release_dotlock (kr->lockhd)) + log_info ("can't unlock `%s'\n", kr->fname ); + else + kr->is_locked = 0; + } + } + + return rc; +} + + + +/* + * 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 +keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) +{ + PACKET *pkt; + int rc; + KBNODE keyblock = NULL, node, lastnode; + IOBUF a; + int in_cert = 0; + int pk_no = 0; + int uid_no = 0; + int save_mode; + + if (ret_kb) + *ret_kb = NULL; + + if (!hd->found.kr) + return -1; /* no successful search */ + + a = iobuf_open (hd->found.kr->fname); + if (!a) { + log_error ("can't open `%s'\n", hd->found.kr->fname); + return G10ERR_KEYRING_OPEN; + } + + if (iobuf_seek (a, hd->found.offset) ) { + log_error ("can't seek `%s'\n", hd->found.kr->fname); + iobuf_close(a); + return G10ERR_KEYRING_OPEN; + } + + pkt = m_alloc (sizeof *pkt); + init_packet (pkt); + hd->found.n_packets = 0;; + lastnode = NULL; + save_mode = set_packet_list_mode(0); + while ((rc=parse_packet (a, pkt)) != -1) { + hd->found.n_packets++; + if (rc == G10ERR_UNKNOWN_PACKET) { + free_packet (pkt); + init_packet (pkt); + continue; + } + if (rc) { + log_error ("keyring_get_keyblock: read error: %s\n", + g10_errstr(rc) ); + rc = G10ERR_INV_KEYRING; + break; + } + if (pkt->pkttype == PKT_COMPRESSED) { + log_error ("skipped compressed packet in keyring\n"); + free_packet(pkt); + init_packet(pkt); + continue; + } + + if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY + || pkt->pkttype == PKT_SECRET_KEY)) { + hd->found.n_packets--; /* fix counter */ + break; /* ready */ + } + + in_cert = 1; + if (pkt->pkttype == PKT_RING_TRUST) { + /*(this code is duplicated after the loop)*/ + if ( lastnode + && lastnode->pkt->pkttype == PKT_SIGNATURE + && (pkt->pkt.ring_trust->sigcache & 1) ) { + /* this is a ring trust packet with a checked signature + * status cache following directly a signature paket. + * Set the cache status into that signature packet */ + PKT_signature *sig = lastnode->pkt->pkt.signature; + + sig->flags.checked = 1; + sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); + } + /* reset lastnode, so that we set the cache status only from + * the ring trust packet immediately folling a signature */ + lastnode = NULL; + } + else { + node = lastnode = new_kbnode (pkt); + if (!keyblock) + keyblock = node; + else + add_kbnode (keyblock, node); + + if ( pkt->pkttype == PKT_PUBLIC_KEY + || pkt->pkttype == PKT_PUBLIC_SUBKEY + || pkt->pkttype == PKT_SECRET_KEY + || pkt->pkttype == PKT_SECRET_SUBKEY) { + if (++pk_no == hd->found.pk_no) + node->flag |= 1; + } + else if ( pkt->pkttype == PKT_USER_ID) { + if (++uid_no == hd->found.uid_no) + node->flag |= 2; + } + } + + pkt = m_alloc (sizeof *pkt); + init_packet(pkt); + } + set_packet_list_mode(save_mode); + + if (rc == -1 && keyblock) + rc = 0; /* got the entire keyblock */ + + if (rc || !ret_kb) + release_kbnode (keyblock); + else { + /*(duplicated form the loop body)*/ + if ( pkt && pkt->pkttype == PKT_RING_TRUST + && lastnode + && lastnode->pkt->pkttype == PKT_SIGNATURE + && (pkt->pkt.ring_trust->sigcache & 1) ) { + PKT_signature *sig = lastnode->pkt->pkt.signature; + sig->flags.checked = 1; + sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2); + } + *ret_kb = keyblock; + } + free_packet (pkt); + m_free (pkt); + iobuf_close(a); + + /* Make sure that future search operations fail immediately when + * we know that we are working on a invalid keyring + */ + if (rc == G10ERR_INV_KEYRING) + hd->current.error = rc; + + return rc; +} + +int +keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb) +{ + int rc; + + if (!hd->found.kr) + return -1; /* no successful prior search */ + + if (!hd->found.n_packets) { + /* need to know the number of packets - do a dummy get_keyblock*/ + rc = keyring_get_keyblock (hd, NULL); + if (rc) { + log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); + return rc; + } + if (!hd->found.n_packets) + BUG (); + } + + /* The open iobuf isn't needed anymore and in fact is a problem when + it comes to renaming the keyring files on some operating systems, + so close it here */ + iobuf_close(hd->current.iobuf); + hd->current.iobuf = NULL; + + /* do the update */ + rc = do_copy (3, hd->found.kr->fname, kb, hd->secret, + hd->found.offset, hd->found.n_packets ); + if (!rc) { + if (!hd->secret && kr_offtbl) + { + update_offset_hash_table_from_kb (kr_offtbl, kb, 0); + } + /* better reset the found info */ + hd->found.kr = NULL; + hd->found.offset = 0; + } + return rc; +} + +int +keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) +{ + int rc; + const char *fname; + + if (!hd) + fname = NULL; + else if (hd->found.kr) + fname = hd->found.kr->fname; + else if (hd->current.kr) + fname = hd->current.kr->fname; + else + fname = hd->resource? hd->resource->fname:NULL; + + if (!fname) + return G10ERR_GENERAL; + + /* close this one otherwise we will lose the position for + * a next search. Fixme: it would be better to adjust the position + * after the write opertions. + */ + iobuf_close (hd->current.iobuf); + hd->current.iobuf = NULL; + + /* do the insert */ + rc = do_copy (1, fname, kb, hd->secret, 0, 0 ); + if (!rc && !hd->secret && kr_offtbl) + { + update_offset_hash_table_from_kb (kr_offtbl, kb, 0); + } + + return rc; +} + + +int +keyring_delete_keyblock (KEYRING_HANDLE hd) +{ + int rc; + + if (!hd->found.kr) + return -1; /* no successful prior search */ + + if (!hd->found.n_packets) { + /* need to know the number of packets - do a dummy get_keyblock*/ + rc = keyring_get_keyblock (hd, NULL); + if (rc) { + log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); + return rc; + } + if (!hd->found.n_packets) + BUG (); + } + + /* close this one otherwise we will lose the position for + * a next search. Fixme: it would be better to adjust the position + * after the write opertions. + */ + iobuf_close (hd->current.iobuf); + hd->current.iobuf = NULL; + + /* do the delete */ + rc = do_copy (2, hd->found.kr->fname, NULL, hd->secret, + hd->found.offset, hd->found.n_packets ); + if (!rc) { + /* better reset the found info */ + hd->found.kr = NULL; + hd->found.offset = 0; + /* Delete is a rare operations, so we don't remove the keys + * from the offset table */ + } + return rc; +} + + + +/* + * Start the next search on this handle right at the beginning + */ +int +keyring_search_reset (KEYRING_HANDLE hd) +{ + assert (hd); + + hd->current.kr = NULL; + iobuf_close (hd->current.iobuf); + hd->current.iobuf = NULL; + hd->current.eof = 0; + hd->current.error = 0; + + hd->found.kr = NULL; + hd->found.offset = 0; + return 0; +} + + +static int +prepare_search (KEYRING_HANDLE hd) +{ + if (hd->current.error) + return hd->current.error; /* still in error state */ + + if (hd->current.kr && !hd->current.eof) { + if ( !hd->current.iobuf ) + return G10ERR_GENERAL; /* position invalid after a modify */ + return 0; /* okay */ + } + + if (!hd->current.kr && hd->current.eof) + return -1; /* still EOF */ + + if (!hd->current.kr) { /* start search with first keyring */ + hd->current.kr = hd->resource; + if (!hd->current.kr) { + hd->current.eof = 1; + return -1; /* keyring not available */ + } + assert (!hd->current.iobuf); + } + else { /* EOF */ + iobuf_close (hd->current.iobuf); + hd->current.iobuf = NULL; + hd->current.kr = NULL; + hd->current.eof = 1; + return -1; + } + + hd->current.eof = 0; + hd->current.iobuf = iobuf_open (hd->current.kr->fname); + if (!hd->current.iobuf) { + log_error ("can't open `%s'\n", hd->current.kr->fname ); + return (hd->current.error = G10ERR_OPEN_FILE); + } + + return 0; +} + + +/* A map of the all characters valid used for word_match() + * Valid characters are in in this table converted to uppercase. + * because the upper 128 bytes have special meaning, we assume + * that they are all valid. + * Note: We must use numerical values here in case that this program + * will be converted to those little blue HAL9000s with their strange + * EBCDIC character set (user ids are UTF-8). + * wk 2000-04-13: Hmmm, does this really make sense, given the fact that + * we can run gpg now on a S/390 running GNU/Linux, where the code + * translation is done by the device drivers? + */ +static const byte word_match_chars[256] = { + /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 40 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + /* 58 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 60 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 68 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + /* 78 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /* 88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + /* 90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + /* 98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + /* a0 */ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + /* a8 */ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + /* b0 */ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + /* b8 */ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + /* c0 */ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + /* c8 */ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + /* d0 */ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + /* d8 */ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + /* e0 */ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + /* e8 */ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + /* f0 */ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + /* f8 */ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +/**************** + * Do a word match (original user id starts with a '+'). + * The pattern is already tokenized to a more suitable format: + * There are only the real words in it delimited by one space + * and all converted to uppercase. + * + * Returns: 0 if all words match. + * + * Note: This algorithm is a straightforward one and not very + * fast. It works for UTF-8 strings. The uidlen should + * be removed but due to the fact that old versions of + * pgp don't use UTF-8 we still use the length; this should + * be fixed in parse-packet (and replace \0 by some special + * UTF-8 encoding) + */ +static int +word_match( const byte *uid, size_t uidlen, const byte *pattern ) +{ + size_t wlen, n; + const byte *p; + const byte *s; + + for( s=pattern; *s; ) { + do { + /* skip leading delimiters */ + while( uidlen && !word_match_chars[*uid] ) + uid++, uidlen--; + /* get length of the word */ + n = uidlen; p = uid; + while( n && word_match_chars[*p] ) + p++, n--; + wlen = p - uid; + /* and compare against the current word from pattern */ + for(n=0, p=uid; n < wlen && s[n] != ' ' && s[n] ; n++, p++ ) { + if( word_match_chars[*p] != s[n] ) + break; + } + if( n == wlen && (s[n] == ' ' || !s[n]) ) + break; /* found */ + uid += wlen; + uidlen -= wlen; + } while( uidlen ); + if( !uidlen ) + return -1; /* not found */ + + /* advance to next word in pattern */ + for(; *s != ' ' && *s ; s++ ) + ; + if( *s ) + s++ ; + } + return 0; /* found */ +} + +/**************** + * prepare word word_match; that is parse the name and + * build the pattern. + * caller has to free the returned pattern + */ +static char* +prepare_word_match (const byte *name) +{ + byte *pattern, *p; + int c; + + /* the original length is always enough for the pattern */ + p = pattern = m_alloc(strlen(name)+1); + do { + /* skip leading delimiters */ + while( *name && !word_match_chars[*name] ) + name++; + /* copy as long as we don't have a delimiter and convert + * to uppercase. + * fixme: how can we handle utf8 uppercasing */ + for( ; *name && (c=word_match_chars[*name]); name++ ) + *p++ = c; + *p++ = ' '; /* append pattern delimiter */ + } while( *name ); + p[-1] = 0; /* replace last pattern delimiter by EOS */ + + return pattern; +} + + + + +static int +compare_name (int mode, const char *name, const char *uid, size_t uidlen) +{ + int i; + const char *s, *se; + + if (mode == KEYDB_SEARCH_MODE_EXACT) { + for (i=0; name[i] && uidlen; i++, uidlen--) + if (uid[i] != name[i]) + break; + if (!uidlen && !name[i]) + return 0; /* found */ + } + else if (mode == KEYDB_SEARCH_MODE_SUBSTR) { + if (ascii_memistr( uid, uidlen, name )) + return 0; + } + else if ( mode == KEYDB_SEARCH_MODE_MAIL + || mode == KEYDB_SEARCH_MODE_MAILSUB + || mode == KEYDB_SEARCH_MODE_MAILEND) { + for (i=0, s= uid; i < uidlen && *s != '<'; s++, i++) + ; + if (i < uidlen) { + /* skip opening delim and one char and look for the closing one*/ + s++; i++; + for (se=s+1, i++; i < uidlen && *se != '>'; se++, i++) + ; + if (i < uidlen) { + i = se - s; + if (mode == KEYDB_SEARCH_MODE_MAIL) { + if( strlen(name)-2 == i + && !ascii_memcasecmp( s, name+1, i) ) + return 0; + } + else if (mode == KEYDB_SEARCH_MODE_MAILSUB) { + if( ascii_memistr( s, i, name ) ) + return 0; + } + else { /* email from end */ + /* nyi */ + } + } + } + } + else if (mode == KEYDB_SEARCH_MODE_WORDS) + return word_match (uid, uidlen, name); + else + BUG(); + + return -1; /* not found */ +} + + +/* + * Search through the keyring(s), starting at the current position, + * for a keyblock which contains one of the keys described in the DESC array. + */ +int +keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, + size_t ndesc, size_t *descindex) +{ + int rc; + PACKET pkt; + int save_mode; + off_t offset, main_offset; + size_t n; + int need_uid, need_words, need_keyid, need_fpr, any_skip; + int pk_no, uid_no; + int initial_skip; + int use_offtbl; + PKT_user_id *uid = NULL; + PKT_public_key *pk = NULL; + PKT_secret_key *sk = NULL; + u32 aki[2]; + + /* figure out what information we need */ + need_uid = need_words = need_keyid = need_fpr = any_skip = 0; + for (n=0; n < ndesc; n++) + { + switch (desc[n].mode) + { + case KEYDB_SEARCH_MODE_EXACT: + case KEYDB_SEARCH_MODE_SUBSTR: + case KEYDB_SEARCH_MODE_MAIL: + case KEYDB_SEARCH_MODE_MAILSUB: + case KEYDB_SEARCH_MODE_MAILEND: + need_uid = 1; + break; + case KEYDB_SEARCH_MODE_WORDS: + need_uid = 1; + need_words = 1; + break; + case KEYDB_SEARCH_MODE_SHORT_KID: + case KEYDB_SEARCH_MODE_LONG_KID: + need_keyid = 1; + break; + case KEYDB_SEARCH_MODE_FPR16: + case KEYDB_SEARCH_MODE_FPR20: + case KEYDB_SEARCH_MODE_FPR: + need_fpr = 1; + break; + case KEYDB_SEARCH_MODE_FIRST: + /* always restart the search in this mode */ + keyring_search_reset (hd); + break; + default: break; + } + if (desc[n].skipfnc) + { + any_skip = 1; + need_keyid = 1; + } + } + + rc = prepare_search (hd); + if (rc) + return rc; + + use_offtbl = !hd->secret && kr_offtbl; + if (!use_offtbl) + ; + else if (!kr_offtbl_ready) + need_keyid = 1; + else if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID) + { + struct off_item *oi; + + oi = lookup_offset_hash_table (kr_offtbl, desc[0].u.kid); + if (!oi) + { /* We know that we don't have this key */ + hd->found.kr = NULL; + hd->current.eof = 1; + return -1; + } + /* We could now create a positive search status and return. + * However the problem is that another instance of gpg may + * have changed the keyring so that the offsets are not valid + * anymore - therefore we don't do it + */ + } + + if (need_words) + { + const char *name = NULL; + + log_debug ("word search mode does not yet work\n"); + /* FIXME: here is a long standing bug in our function and in addition we + just use the first search description */ + for (n=0; n < ndesc && !name; n++) + { + if (desc[n].mode == KEYDB_SEARCH_MODE_WORDS) + name = desc[n].u.name; + } + assert (name); + if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) + { + /* name changed */ + m_free (hd->word_match.name); + m_free (hd->word_match.pattern); + hd->word_match.name = m_strdup (name); + hd->word_match.pattern = prepare_word_match (name); + } + name = hd->word_match.pattern; + } + + init_packet(&pkt); + save_mode = set_packet_list_mode(0); + + hd->found.kr = NULL; + main_offset = 0; + pk_no = uid_no = 0; + initial_skip = 1; /* skip until we see the start of a keyblock */ + while (!(rc=search_packet (hd->current.iobuf, &pkt, &offset, need_uid))) + { + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + if (pkt.pkttype == PKT_PUBLIC_KEY || pkt.pkttype == PKT_SECRET_KEY) + { + main_offset = offset; + pk_no = uid_no = 0; + initial_skip = 0; + } + if (initial_skip) + { + free_packet (&pkt); + continue; + } + + pk = NULL; + sk = NULL; + uid = NULL; + if ( pkt.pkttype == PKT_PUBLIC_KEY + || pkt.pkttype == PKT_PUBLIC_SUBKEY) + { + pk = pkt.pkt.public_key; + ++pk_no; + + if (need_fpr) { + fingerprint_from_pk (pk, afp, &an); + while (an < 20) /* fill up to 20 bytes */ + afp[an++] = 0; + } + if (need_keyid) + keyid_from_pk (pk, aki); + + if (use_offtbl && !kr_offtbl_ready) + update_offset_hash_table (kr_offtbl, aki, main_offset); + } + else if (pkt.pkttype == PKT_USER_ID) + { + uid = pkt.pkt.user_id; + ++uid_no; + } + else if ( pkt.pkttype == PKT_SECRET_KEY + || pkt.pkttype == PKT_SECRET_SUBKEY) + { + sk = pkt.pkt.secret_key; + ++pk_no; + + if (need_fpr) { + fingerprint_from_sk (sk, afp, &an); + while (an < 20) /* fill up to 20 bytes */ + afp[an++] = 0; + } + if (need_keyid) + keyid_from_sk (sk, aki); + + } + + for (n=0; n < ndesc; n++) + { + switch (desc[n].mode) { + case KEYDB_SEARCH_MODE_NONE: + BUG (); + break; + case KEYDB_SEARCH_MODE_EXACT: + case KEYDB_SEARCH_MODE_SUBSTR: + case KEYDB_SEARCH_MODE_MAIL: + case KEYDB_SEARCH_MODE_MAILSUB: + case KEYDB_SEARCH_MODE_MAILEND: + case KEYDB_SEARCH_MODE_WORDS: + if ( uid && !compare_name (desc[n].mode, + desc[n].u.name, + uid->name, uid->len)) + goto found; + break; + + case KEYDB_SEARCH_MODE_SHORT_KID: + if ((pk||sk) && desc[n].u.kid[1] == aki[1]) + goto found; + break; + case KEYDB_SEARCH_MODE_LONG_KID: + if ((pk||sk) && desc[n].u.kid[0] == aki[0] + && desc[n].u.kid[1] == aki[1]) + goto found; + break; + case KEYDB_SEARCH_MODE_FPR16: + if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 16)) + goto found; + break; + case KEYDB_SEARCH_MODE_FPR20: + case KEYDB_SEARCH_MODE_FPR: + if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20)) + goto found; + break; + case KEYDB_SEARCH_MODE_FIRST: + if (pk||sk) + goto found; + break; + case KEYDB_SEARCH_MODE_NEXT: + if (pk||sk) + goto found; + break; + default: + rc = G10ERR_INV_ARG; + goto found; + } + } + free_packet (&pkt); + continue; + found: + /* Record which desc we matched on. Note this value is only + meaningful if this function returns with no errors. */ + if(descindex) + *descindex=n; + for (n=any_skip?0:ndesc; n < ndesc; n++) + { + if (desc[n].skipfnc + && desc[n].skipfnc (desc[n].skipfncvalue, aki)) + break; + } + if (n == ndesc) + goto real_found; + free_packet (&pkt); + } + real_found: + if (!rc) + { + hd->found.offset = main_offset; + hd->found.kr = hd->current.kr; + hd->found.pk_no = (pk||sk)? pk_no : 0; + hd->found.uid_no = uid? uid_no : 0; + } + else if (rc == -1) + { + hd->current.eof = 1; + /* if we scanned all keyrings, we are sure that + * all known key IDs are in our offtbl, mark that. */ + if (use_offtbl && !kr_offtbl_ready) + { + KR_NAME kr; + + /* First set the did_full_scan flag for this keyring (ignore + secret keyrings) */ + for (kr=kr_names; kr; kr = kr->next) + { + if (!kr->secret && hd->resource == kr) + { + kr->did_full_scan = 1; + break; + } + } + /* Then check whether all flags are set and if so, mark the + offtbl ready */ + for (kr=kr_names; kr; kr = kr->next) + { + if (!kr->secret && !kr->did_full_scan) + break; + } + if (!kr) + kr_offtbl_ready = 1; + } + } + else + hd->current.error = rc; + + free_packet(&pkt); + set_packet_list_mode(save_mode); + return rc; +} + + +static int +create_tmp_file (const char *template, + char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) +{ + char *bakfname, *tmpfname; + mode_t oldmask; + + *r_bakfname = NULL; + *r_tmpfname = NULL; + +# ifdef USE_ONLY_8DOT3 + /* Here is another Windoze bug?: + * you cant rename("pubring.gpg.tmp", "pubring.gpg"); + * but rename("pubring.gpg.tmp", "pubring.aaa"); + * works. So we replace .gpg by .bak or .tmp + */ + if (strlen (template) > 4 + && !strcmp (template+strlen(template)-4, EXTSEP_S "gpg") ) + { + bakfname = m_alloc (strlen (template) + 1); + strcpy (bakfname, template); + strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak"); + + tmpfname = m_alloc (strlen( template ) + 1 ); + strcpy (tmpfname,template); + strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp"); + } + else + { /* file does not end with gpg; hmmm */ + bakfname = m_alloc (strlen( template ) + 5); + strcpy (stpcpy(bakfname, template), EXTSEP_S "bak"); + + tmpfname = m_alloc (strlen( template ) + 5); + strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp"); + } +# else /* Posix file names */ + bakfname = m_alloc (strlen( template ) + 2); + strcpy (stpcpy (bakfname,template),"~"); + + tmpfname = m_alloc (strlen( template ) + 5); + strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp"); +# endif /* Posix filename */ + + /* Create the temp file with limited access */ + oldmask=umask(077); + *r_fp = iobuf_create (tmpfname); + umask(oldmask); + if (!*r_fp) { + log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) ); + m_free (tmpfname); + m_free (bakfname); + return G10ERR_OPEN_FILE; + } + + *r_bakfname = bakfname; + *r_tmpfname = tmpfname; + return 0; +} + + +static int +rename_tmp_file (const char *bakfname, const char *tmpfname, + const char *fname, int secret ) +{ + int rc=0; + + /* invalidate close caches*/ + iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); + iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); + iobuf_ioctl (NULL, 2, 0, (char*)fname ); + + /* first make a backup file except for secret keyrings */ + if (!secret) + { +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + remove (bakfname); +#endif + if (rename (fname, bakfname) ) + { + log_error ("renaming `%s' to `%s' failed: %s\n", + fname, bakfname, strerror(errno) ); + return G10ERR_RENAME_FILE; + } + } + + /* then rename the file */ +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + remove( fname ); +#endif + if (rename (tmpfname, fname) ) + { + log_error ("renaming `%s' to `%s' failed: %s\n", + tmpfname, fname, strerror(errno) ); + rc = G10ERR_RENAME_FILE; + if (secret) + { + log_info(_("WARNING: 2 files with confidential" + " information exists.\n")); + log_info(_("%s is the unchanged one\n"), fname ); + log_info(_("%s is the new one\n"), tmpfname ); + log_info(_("Please fix this possible security flaw\n")); + } + return rc; + } + + /* Now make sure the file has the same permissions as the original */ + +#ifndef HAVE_DOSISH_SYSTEM + { + struct stat statbuf; + + statbuf.st_mode=S_IRUSR | S_IWUSR; + + if(((secret && !opt.preserve_permissions) || + (stat(bakfname,&statbuf)==0)) && + (chmod(fname,statbuf.st_mode)==0)) + ; + else + log_error("WARNING: unable to restore permissions to `%s': %s", + fname,strerror(errno)); + } +#endif + + return 0; +} + + +static int +write_keyblock (IOBUF fp, KBNODE keyblock) +{ + KBNODE kbctx = NULL, node; + int rc; + + while ( (node = walk_kbnode (keyblock, &kbctx, 0)) ) + { + if (node->pkt->pkttype == PKT_RING_TRUST) + continue; /* we write it later on our own */ + + if ( (rc = build_packet (fp, node->pkt) )) + { + log_error ("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + return rc; + } + if (node->pkt->pkttype == PKT_SIGNATURE) + { /* always write a signature cache packet */ + PKT_signature *sig = node->pkt->pkt.signature; + unsigned int cacheval = 0; + + if (sig->flags.checked) + { + cacheval |= 1; + if (sig->flags.valid) + cacheval |= 2; + } + iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/ + iobuf_put (fp, 2); /* 2 bytes */ + iobuf_put (fp, 0); /* unused */ + if (iobuf_put (fp, cacheval)) { + log_error ("writing sigcache packet failed\n"); + return G10ERR_WRITE_FILE; + } + } + } + return 0; +} + +/* + * Walk over all public keyrings, check the signatures and replace the + * keyring with a new one where the signature cache is then updated. + * This is only done for the public keyrings. + */ +int +keyring_rebuild_cache (void *token) +{ + KEYRING_HANDLE hd; + KEYDB_SEARCH_DESC desc; + KBNODE keyblock = NULL, node; + const char *lastresname = NULL, *resname; + IOBUF tmpfp = NULL; + char *tmpfilename = NULL; + char *bakfilename = NULL; + int rc; + ulong count = 0, sigcount = 0; + + hd = keyring_new (token, 0); + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FIRST; + + rc=keyring_lock (hd, 1); + if(rc) + goto leave; + + while ( !(rc = keyring_search (hd, &desc, 1, NULL)) ) + { + desc.mode = KEYDB_SEARCH_MODE_NEXT; + resname = keyring_get_resource_name (hd); + if (lastresname != resname ) + { /* we have switched to a new keyring - commit changes */ + if (tmpfp) + { + if (iobuf_close (tmpfp)) + { + log_error ("error closing `%s': %s\n", + tmpfilename, strerror (errno)); + rc = G10ERR_CLOSE_FILE; + goto leave; + } + /* because we have switched resources, we can be sure that + * the original file is closed */ + tmpfp = NULL; + } + rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, + lastresname, 0) : 0; + m_free (tmpfilename); tmpfilename = NULL; + m_free (bakfilename); bakfilename = NULL; + if (rc) + goto leave; + lastresname = resname; + if (!opt.quiet) + log_info (_("checking keyring `%s'\n"), resname); + rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp); + if (rc) + goto leave; + } + + release_kbnode (keyblock); + rc = keyring_get_keyblock (hd, &keyblock); + if (rc) + { + log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc)); + goto leave; + } + assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY); + + /* check all signature to set the signature's cache flags */ + for (node=keyblock; node; node=node->next) + { + if (node->pkt->pkttype == PKT_SIGNATURE) + { + check_key_signature (keyblock, node, NULL); + sigcount++; + } + } + + /* write the keyblock to the temporary file */ + rc = write_keyblock (tmpfp, keyblock); + if (rc) + goto leave; + + if ( !(++count % 50) && !opt.quiet) + log_info(_("%lu keys checked so far (%lu signatures)\n"), + count, sigcount ); + + } /* end main loop */ + if (rc == -1) + rc = 0; + if (rc) + { + log_error ("keyring_search failed: %s\n", g10_errstr(rc)); + goto leave; + } + log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount ); + if (tmpfp) + { + if (iobuf_close (tmpfp)) + { + log_error ("error closing `%s': %s\n", + tmpfilename, strerror (errno)); + rc = G10ERR_CLOSE_FILE; + goto leave; + } + /* because we have switched resources, we can be sure that + * the original file is closed */ + tmpfp = NULL; + } + rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, + lastresname, 0) : 0; + m_free (tmpfilename); tmpfilename = NULL; + m_free (bakfilename); bakfilename = NULL; + + leave: + if (tmpfp) + iobuf_cancel (tmpfp); + m_free (tmpfilename); + m_free (bakfilename); + release_kbnode (keyblock); + keyring_lock (hd, 0); + keyring_release (hd); + return rc; +} + + +/**************** + * Perform insert/delete/update operation. + * mode 1 = insert + * 2 = delete + * 3 = update + */ +static int +do_copy (int mode, const char *fname, KBNODE root, int secret, + off_t start_offset, unsigned int n_packets ) +{ + IOBUF fp, newfp; + int rc=0; + char *bakfname = NULL; + char *tmpfname = NULL; + + /* Open the source file. Because we do a rname, we have to check the + permissions of the file */ + if (access (fname, W_OK)) + return G10ERR_WRITE_FILE; + + fp = iobuf_open (fname); + if (mode == 1 && !fp && errno == ENOENT) { + /* insert mode but file does not exist: create a new file */ + KBNODE kbctx, node; + mode_t oldmask; + + oldmask=umask(077); + newfp = iobuf_create (fname); + umask(oldmask); + if( !newfp ) { + log_error (_("%s: can't create: %s\n"), + fname, strerror(errno)); + return G10ERR_OPEN_FILE; + } + if( !opt.quiet ) + log_info(_("%s: keyring created\n"), fname ); + + kbctx=NULL; + while ( (node = walk_kbnode( root, &kbctx, 0 )) ) { + if( (rc = build_packet( newfp, node->pkt )) ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + iobuf_cancel(newfp); + return G10ERR_WRITE_FILE; + } + } + if( iobuf_close(newfp) ) { + log_error ("%s: close failed: %s\n", fname, strerror(errno)); + return G10ERR_CLOSE_FILE; + } + return 0; /* ready */ + } + + if( !fp ) { + log_error ("%s: can't open: %s\n", fname, strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + + /* create the new file */ + rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); + if (rc) { + iobuf_close(fp); + goto leave; + } + if( mode == 1 ) { /* insert */ + /* copy everything to the new file */ + rc = copy_all_packets (fp, newfp); + if( rc != -1 ) { + log_error("%s: copy to `%s' failed: %s\n", + fname, tmpfname, g10_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + rc = 0; + } + + if( mode == 2 || mode == 3 ) { /* delete or update */ + /* copy first part to the new file */ + rc = copy_some_packets( fp, newfp, start_offset ); + if( rc ) { /* should never get EOF here */ + log_error ("%s: copy to `%s' failed: %s\n", + fname, tmpfname, g10_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + /* skip this keyblock */ + assert( n_packets ); + rc = skip_some_packets( fp, n_packets ); + if( rc ) { + log_error("%s: skipping %u packets failed: %s\n", + fname, n_packets, g10_errstr(rc)); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + } + + if( mode == 1 || mode == 3 ) { /* insert or update */ + rc = write_keyblock (newfp, root); + if (rc) { + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + } + + if( mode == 2 || mode == 3 ) { /* delete or update */ + /* copy the rest */ + rc = copy_all_packets( fp, newfp ); + if( rc != -1 ) { + log_error("%s: copy to `%s' failed: %s\n", + fname, tmpfname, g10_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + rc = 0; + } + + /* close both files */ + if( iobuf_close(fp) ) { + log_error("%s: close failed: %s\n", fname, strerror(errno) ); + rc = G10ERR_CLOSE_FILE; + goto leave; + } + if( iobuf_close(newfp) ) { + log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); + rc = G10ERR_CLOSE_FILE; + goto leave; + } + + rc = rename_tmp_file (bakfname, tmpfname, fname, secret); + + leave: + m_free(bakfname); + m_free(tmpfname); + return rc; +} diff --git a/g10/keyring.h b/g10/keyring.h new file mode 100644 index 000000000..528557a70 --- /dev/null +++ b/g10/keyring.h @@ -0,0 +1,46 @@ +/* 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*/ diff --git a/g10/keyserver.c b/g10/keyserver.c new file mode 100644 index 000000000..7759de198 --- /dev/null +++ b/g10/keyserver.c @@ -0,0 +1,1378 @@ +/* keyserver.c - generic keyserver code + * 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 <ctype.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include "filter.h" +#include "keydb.h" +#include "status.h" +#include "exec.h" +#include "main.h" +#include "i18n.h" +#include "iobuf.h" +#include "memory.h" +#include "ttyio.h" +#include "options.h" +#include "packet.h" +#include "keyserver-internal.h" +#include "util.h" + +#define GET 0 +#define SEND 1 +#define SEARCH 2 + +struct keyrec +{ + KEYDB_SEARCH_DESC desc; + time_t createtime,expiretime; + int size,flags; + byte type; + IOBUF uidbuf; + int lines; +}; + +struct kopts +{ + char *name; + int tell; /* tell remote process about this one */ + int *flag; +} keyserver_opts[]= +{ + {"include-revoked",1,&opt.keyserver_options.include_revoked}, + {"include-disabled",1,&opt.keyserver_options.include_disabled}, + {"include-subkeys",1,&opt.keyserver_options.include_subkeys}, + {"keep-temp-files",0,&opt.keyserver_options.keep_temp_files}, + {"honor-http-proxy",1,&opt.keyserver_options.honor_http_proxy}, + {"broken-http-proxy",1,&opt.keyserver_options.broken_http_proxy}, + {"refresh-add-fake-v3-keyids",0,&opt.keyserver_options.fake_v3_keyids}, + {"auto-key-retrieve",0,&opt.keyserver_options.auto_key_retrieve}, + {"try-dns-srv",1,&opt.keyserver_options.try_dns_srv}, + {NULL} +}; + +static int keyserver_work(int action,STRLIST list, + KEYDB_SEARCH_DESC *desc,int count); + +void +parse_keyserver_options(char *options) +{ + char *tok; + + while((tok=strsep(&options," ,"))) + { + int i,hit=0; + + if(tok[0]=='\0') + continue; + + for(i=0;keyserver_opts[i].name;i++) + { + if(ascii_strcasecmp(tok,keyserver_opts[i].name)==0) + { + *(keyserver_opts[i].flag)=1; + hit=1; + break; + } + else if(ascii_strncasecmp("no-",tok,3)==0 && + ascii_strcasecmp(&tok[3],keyserver_opts[i].name)==0) + { + *(keyserver_opts[i].flag)=0; + hit=1; + break; + } + } + + /* These options need more than just a flag */ + if(!hit) + { + if(ascii_strcasecmp(tok,"verbose")==0) + opt.keyserver_options.verbose++; + else if(ascii_strcasecmp(tok,"no-verbose")==0) + opt.keyserver_options.verbose--; +#ifdef EXEC_TEMPFILE_ONLY + else if(ascii_strcasecmp(tok,"use-temp-files")==0 || + ascii_strcasecmp(tok,"no-use-temp-files")==0) + log_info(_("WARNING: keyserver option \"%s\" is not used " + "on this platform\n"),tok); +#else + else if(ascii_strcasecmp(tok,"use-temp-files")==0) + opt.keyserver_options.use_temp_files=1; + else if(ascii_strcasecmp(tok,"no-use-temp-files")==0) + opt.keyserver_options.use_temp_files=0; +#endif + else + if(!parse_import_options(tok, + &opt.keyserver_options.import_options) && + !parse_export_options(tok, + &opt.keyserver_options.export_options)) + add_to_strlist(&opt.keyserver_options.other,tok); + } + } +} + +int +parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) +{ + int assume_hkp=0; + + assert(uri!=NULL); + + opt.keyserver_host=NULL; + opt.keyserver_port=NULL; + opt.keyserver_opaque=NULL; + + /* Get the scheme */ + + opt.keyserver_scheme=strsep(&uri,":"); + if(uri==NULL) + { + /* Assume HKP if there is no scheme */ + assume_hkp=1; + uri=opt.keyserver_scheme; + opt.keyserver_scheme="hkp"; + } + else + { + /* Force to lowercase */ + char *i; + + for(i=opt.keyserver_scheme;*i!='\0';i++) + *i=ascii_tolower(*i); + } + + if(ascii_strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0) + { + deprecated_warning(configname,configlineno,"x-broken-hkp", + "--keyserver-options ","broken-http-proxy"); + opt.keyserver_scheme="hkp"; + opt.keyserver_options.broken_http_proxy=1; + } + else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0) + { + /* Canonicalize this to "hkp" so it works with both the internal + and external keyserver interface. */ + opt.keyserver_scheme="hkp"; + } + + if(assume_hkp || (uri[0]=='/' && uri[1]=='/')) + { + /* Two slashes means network path. */ + + /* Skip over the "//", if any */ + if(!assume_hkp) + uri+=2; + + /* Get the host */ + opt.keyserver_host=strsep(&uri,":/"); + if(opt.keyserver_host[0]=='\0') + return G10ERR_BAD_URI; + + if(uri==NULL || uri[0]=='\0') + opt.keyserver_port=NULL; + else + { + char *ch; + + /* Get the port */ + opt.keyserver_port=strsep(&uri,"/"); + + /* Ports are digits only */ + ch=opt.keyserver_port; + while(*ch!='\0') + { + if(!isdigit(*ch)) + return G10ERR_BAD_URI; + + ch++; + } + + /* It would seem to be reasonable to limit the range of the + ports to values between 1-65535, but RFC 1738 and 1808 + imply there is no limit. Of course, the real world has + limits. */ + } + + /* (any path part of the URI is discarded for now as no keyserver + uses it yet) */ + } + else if(uri[0]!='/') + { + /* No slash means opaque. Just record the opaque blob and get + out. */ + opt.keyserver_opaque=uri; + return 0; + } + else + { + /* One slash means absolute path. We don't need to support that + yet. */ + return G10ERR_BAD_URI; + } + + if(opt.keyserver_scheme[0]=='\0') + return G10ERR_BAD_URI; + + return 0; +} + +static void +print_keyrec(int number,struct keyrec *keyrec) +{ + int i; + + iobuf_writebyte(keyrec->uidbuf,0); + iobuf_flush_temp(keyrec->uidbuf); + printf("(%d)\t%s ",number,iobuf_get_temp_buffer(keyrec->uidbuf)); + + if(keyrec->size>0) + printf("%d bit ",keyrec->size); + + if(keyrec->type) + { + const char *str=pubkey_algo_to_string(keyrec->type); + + if(str) + printf("%s ",str); + else + printf("unknown "); + } + + switch(keyrec->desc.mode) + { + case KEYDB_SEARCH_MODE_SHORT_KID: + printf("key %08lX",(ulong)keyrec->desc.u.kid[1]); + break; + + case KEYDB_SEARCH_MODE_LONG_KID: + printf("key %08lX%08lX",(ulong)keyrec->desc.u.kid[0], + (ulong)keyrec->desc.u.kid[1]); + break; + + case KEYDB_SEARCH_MODE_FPR16: + printf("key "); + for(i=0;i<16;i++) + printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]); + break; + + case KEYDB_SEARCH_MODE_FPR20: + printf("key "); + for(i=0;i<20;i++) + printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]); + break; + + default: + BUG(); + break; + } + + if(keyrec->createtime>0) + printf(", created %s",strtimestamp(keyrec->createtime)); + + if(keyrec->expiretime>0) + printf(", expires %s",strtimestamp(keyrec->expiretime)); + + if(keyrec->flags&1) + printf(" (%s)",("revoked")); + if(keyrec->flags&2) + printf(" (%s)",("disabled")); + if(keyrec->flags&4) + printf(" (%s)",("expired")); + + printf("\n"); +} + +/* Returns a keyrec (which must be freed) once a key is complete, and + NULL otherwise. Call with a NULL keystring once key parsing is + complete to return any unfinished keys. */ +static struct keyrec * +parse_keyrec(char *keystring) +{ + static struct keyrec *work=NULL; + struct keyrec *ret=NULL; + char *record; + int i; + + if(keystring==NULL) + { + if(work==NULL) + return NULL; + else if(work->desc.mode==KEYDB_SEARCH_MODE_NONE) + { + m_free(work); + return NULL; + } + else + { + ret=work; + work=NULL; + return ret; + } + } + + if(work==NULL) + { + work=m_alloc_clear(sizeof(struct keyrec)); + work->uidbuf=iobuf_temp(); + } + + /* Remove trailing whitespace */ + for(i=strlen(keystring);i>0;i--) + if(isspace(keystring[i-1])) + keystring[i-1]='\0'; + else + break; + + if((record=strsep(&keystring,":"))==NULL) + return ret; + + if(ascii_strcasecmp("pub",record)==0) + { + char *tok; + + if(work->desc.mode) + { + ret=work; + work=m_alloc_clear(sizeof(struct keyrec)); + work->uidbuf=iobuf_temp(); + } + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + classify_user_id(tok,&work->desc); + if(work->desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID + && work->desc.mode!=KEYDB_SEARCH_MODE_LONG_KID + && work->desc.mode!=KEYDB_SEARCH_MODE_FPR16 + && work->desc.mode!=KEYDB_SEARCH_MODE_FPR20) + { + work->desc.mode=KEYDB_SEARCH_MODE_NONE; + return ret; + } + + /* Note all items after this are optional. This allows us to + have a pub line as simple as pub:keyid and nothing else. */ + + work->lines++; + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + work->type=atoi(tok); + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + work->size=atoi(tok); + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + work->createtime=atoi(tok); + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + work->expiretime=atoi(tok); + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + while(*tok) + switch(*tok++) + { + case 'r': + case 'R': + work->flags|=1; + break; + + case 'd': + case 'D': + work->flags|=2; + break; + + case 'e': + case 'E': + work->flags|=4; + break; + } + + if(work->expiretime && work->expiretime<=make_timestamp()) + work->flags|=4; + } + else if(ascii_strcasecmp("uid",record)==0 && work->desc.mode) + { + char *userid,*tok,*decoded; + + if((tok=strsep(&keystring,":"))==NULL) + return ret; + + if(strlen(tok)==0) + return ret; + + userid=tok; + + /* By definition, de-%-encoding is always smaller than the + original string so we can decode in place. */ + + i=0; + + while(*tok) + if(tok[0]=='%' && tok[1] && tok[2]) + { + if((userid[i]=hextobyte(&tok[1]))==-1) + userid[i]='?'; + + i++; + tok+=3; + } + else + userid[i++]=*tok++; + + /* We don't care about the other info provided in the uid: line + since no keyserver supports marking userids with timestamps + or revoked/expired/disabled yet. */ + + /* No need to check for control characters, as utf8_to_native + does this for us. */ + + decoded=utf8_to_native(userid,i,0); + iobuf_writestr(work->uidbuf,decoded); + m_free(decoded); + iobuf_writestr(work->uidbuf,"\n\t"); + work->lines++; + } + + /* Ignore any records other than "pri" and "uid" for easy future + growth. */ + + return ret; +} + +/* TODO: do this as a list sent to keyserver_work rather than calling + it once for each key to get the correct counts after the import + (cosmetics, really) and to better take advantage of the keyservers + that can do multiple fetches in one go (LDAP). */ +static int +show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) +{ + char *answer; + + if(count && opt.command_fd==-1) + { + static int from=1; + tty_printf("Keys %d-%d of %d for \"%s\". ",from,numdesc,count,search); + from=numdesc+1; + } + + answer=cpr_get_no_help("keysearch.prompt", + _("Enter number(s), N)ext, or Q)uit > ")); + /* control-d */ + if(answer[0]=='\x04') + { + printf("Q\n"); + answer[0]='q'; + } + + if(answer[0]=='q' || answer[0]=='Q') + { + m_free(answer); + return 1; + } + else if(atoi(answer)>=1 && atoi(answer)<=numdesc) + { + char *split=answer,*num; + + while((num=strsep(&split," ,"))!=NULL) + if(atoi(num)>=1 && atoi(num)<=numdesc) + keyserver_work(GET,NULL,&desc[atoi(num)-1],1); + + m_free(answer); + return 1; + } + + return 0; +} + +/* Count and searchstr are just for cosmetics. If the count is too + small, it will grow safely. If negative it disables the "Key x-y + of z" messages. */ +static void +keyserver_search_prompt(IOBUF buffer,const char *searchstr) +{ + int i=0,validcount=0,started=0,header=0,count=1; + unsigned int maxlen,buflen; + KEYDB_SEARCH_DESC *desc; + byte *line=NULL; + /* TODO: Something other than 23? That's 24-1 (the prompt). */ + int maxlines=23,numlines=0; + + desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC)); + + for(;;) + { + struct keyrec *keyrec; + int rl; + + maxlen=1024; + rl=iobuf_read_line(buffer,&line,&buflen,&maxlen); + + if(opt.with_colons) + { + if(!header && ascii_strncasecmp("SEARCH ",line,7)==0 + && ascii_strncasecmp(" BEGIN",&line[strlen(line)-7],6)==0) + { + header=1; + continue; + } + else if(ascii_strncasecmp("SEARCH ",line,7)==0 + && ascii_strncasecmp(" END",&line[strlen(line)-5],4)==0) + continue; + + printf("%s",line); + } + + /* Look for an info: line. The only current info: values + defined are the version and key count. */ + if(!started && rl>0 && ascii_strncasecmp("info:",line,5)==0) + { + char *tok,*str=&line[5]; + + if((tok=strsep(&str,":"))!=NULL) + { + int version; + + if(sscanf(tok,"%d",&version)!=1) + version=1; + + if(version!=1) + { + log_error(_("invalid keyserver protocol " + "(us %d!=handler %d)\n"),1,version); + break; + } + } + + if((tok=strsep(&str,":"))!=NULL && sscanf(tok,"%d",&count)==1) + { + if(count==0) + goto notfound; + else if(count<0) + count=10; + else + validcount=1; + + desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); + } + + started=1; + continue; + } + + if(rl==0) + { + keyrec=parse_keyrec(NULL); + + if(keyrec==NULL) + { + if(i==0) + { + count=0; + break; + } + + if(i!=count) + validcount=0; + + for(;;) + { + if(show_prompt(desc,i,validcount?count:0,searchstr)) + break; + validcount=0; + } + + break; + } + } + else + keyrec=parse_keyrec(line); + + if(i==count) + { + /* keyserver helper sent more keys than they claimed in the + info: line. */ + count+=10; + desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); + validcount=0; + } + + if(keyrec) + { + desc[i]=keyrec->desc; + + if(!opt.with_colons) + { + if(numlines+keyrec->lines>maxlines) + { + if(show_prompt(desc,i,validcount?count:0,searchstr)) + break; + else + numlines=0; + } + + print_keyrec(i+1,keyrec); + } + + numlines+=keyrec->lines; + iobuf_close(keyrec->uidbuf); + m_free(keyrec); + + started=1; + i++; + } + } + + m_free(desc); + m_free(line); + + notfound: + if(count==0) + { + if(searchstr) + log_info(_("key \"%s\" not found on keyserver\n"),searchstr); + else + log_info(_("key not found on keyserver\n")); + return; + } +} + +#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" +#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" + +static int +keyserver_spawn(int action,STRLIST list, + KEYDB_SEARCH_DESC *desc,int count,int *prog) +{ + int ret=0,i,gotversion=0,outofband=0; + STRLIST temp; + unsigned int maxlen,buflen; + char *command=NULL,*searchstr=NULL; + byte *line=NULL; + struct kopts *kopts; + struct exec_info *spawn; + +#ifdef EXEC_TEMPFILE_ONLY + opt.keyserver_options.use_temp_files=1; +#endif + + /* Push the libexecdir into path. If DISABLE_KEYSERVER_PATH is set, + use the 0 arg to replace the path. */ +#ifdef DISABLE_KEYSERVER_PATH + set_exec_path(GNUPG_LIBEXECDIR,0); +#else + set_exec_path(GNUPG_LIBEXECDIR,opt.exec_path_set); +#endif + + /* Build the filename for the helper to execute */ + command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); + strcpy(command,"gpgkeys_"); + strcat(command,opt.keyserver_scheme); + + if(opt.keyserver_options.use_temp_files) + { + if(opt.keyserver_options.keep_temp_files) + { + command=m_realloc(command,strlen(command)+ + strlen(KEYSERVER_ARGS_KEEP)+1); + strcat(command,KEYSERVER_ARGS_KEEP); + } + else + { + command=m_realloc(command,strlen(command)+ + strlen(KEYSERVER_ARGS_NOKEEP)+1); + strcat(command,KEYSERVER_ARGS_NOKEEP); + } + + ret=exec_write(&spawn,NULL,command,NULL,0,0); + } + else + ret=exec_write(&spawn,command,NULL,NULL,0,0); + + if(ret) + return ret; + + fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n"); + fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(spawn->tochild,"PROGRAM %s\n",VERSION); + + if(opt.keyserver_opaque) + fprintf(spawn->tochild,"OPAQUE %s\n",opt.keyserver_opaque); + else + { + if(opt.keyserver_host) + fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host); + + if(opt.keyserver_port) + fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port); + } + + /* Write options */ + + for(i=0,kopts=keyserver_opts;kopts[i].name;i++) + if(*(kopts[i].flag) && kopts[i].tell) + fprintf(spawn->tochild,"OPTION %s\n",kopts[i].name); + + for(i=0;i<opt.keyserver_options.verbose;i++) + fprintf(spawn->tochild,"OPTION verbose\n"); + + temp=opt.keyserver_options.other; + + for(;temp;temp=temp->next) + fprintf(spawn->tochild,"OPTION %s\n",temp->d); + + switch(action) + { + case GET: + { + fprintf(spawn->tochild,"COMMAND GET\n\n"); + + /* Which keys do we want? */ + + for(i=0;i<count;i++) + { + if(desc[i].mode==KEYDB_SEARCH_MODE_FPR20) + { + int f; + + fprintf(spawn->tochild,"0x"); + + for(f=0;f<MAX_FINGERPRINT_LEN;f++) + fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]); + + fprintf(spawn->tochild,"\n"); + } + else if(desc[i].mode==KEYDB_SEARCH_MODE_FPR16) + { + int f; + + fprintf(spawn->tochild,"0x"); + + for(f=0;f<16;f++) + fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]); + + fprintf(spawn->tochild,"\n"); + } + else if(desc[i].mode==KEYDB_SEARCH_MODE_LONG_KID) + fprintf(spawn->tochild,"0x%08lX%08lX\n", + (ulong)desc[i].u.kid[0], + (ulong)desc[i].u.kid[1]); + else + fprintf(spawn->tochild,"0x%08lX\n", + (ulong)desc[i].u.kid[1]); + } + + fprintf(spawn->tochild,"\n"); + + break; + } + + case SEND: + { + STRLIST key; + + /* Note the extra \n here to send an empty keylist block */ + fprintf(spawn->tochild,"COMMAND SEND\n\n\n"); + + for(key=list;key!=NULL;key=key->next) + { + armor_filter_context_t afx; + IOBUF buffer=iobuf_temp(); + KBNODE block; + + temp=NULL; + add_to_strlist(&temp,key->d); + + memset(&afx,0,sizeof(afx)); + afx.what=1; + iobuf_push_filter(buffer,armor_filter,&afx); + + /* TODO: Don't use the keyblock hack here - instead, + output each key as a different ascii armored blob with + its own INFO section. */ + + if(export_pubkeys_stream(buffer,temp,&block, + opt.keyserver_options.export_options)==-1) + iobuf_close(buffer); + else + { + KBNODE node; + + iobuf_flush_temp(buffer); + + merge_keys_and_selfsig(block); + + fprintf(spawn->tochild,"INFO %s BEGIN\n",key->d); + + for(node=block;node;node=node->next) + { + switch(node->pkt->pkttype) + { + default: + continue; + + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + { + PKT_public_key *pk=node->pkt->pkt.public_key; + + keyid_from_pk(pk,NULL); + + fprintf(spawn->tochild,"%sb:%08lX%08lX:%u:%u:%u:%u:", + node->pkt->pkttype==PKT_PUBLIC_KEY?"pu":"su", + (ulong)pk->keyid[0],(ulong)pk->keyid[1], + pk->pubkey_algo, + nbits_from_pk(pk), + pk->timestamp, + pk->expiredate); + + if(pk->is_revoked) + fprintf(spawn->tochild,"r"); + if(pk->has_expired) + fprintf(spawn->tochild,"e"); + + fprintf(spawn->tochild,"\n"); + + break; + } + + case PKT_USER_ID: + { + PKT_user_id *uid=node->pkt->pkt.user_id; + int r; + + if(uid->attrib_data) + continue; + + fprintf(spawn->tochild,"uid:"); + + /* Quote ':', '%', and any 8-bit + characters */ + for(r=0;r<uid->len;r++) + { + if(uid->name[r]==':' || uid->name[r]=='%' + || uid->name[r]&0x80) + fprintf(spawn->tochild,"%%%02X",uid->name[r]); + else + fprintf(spawn->tochild,"%c",uid->name[r]); + } + + fprintf(spawn->tochild,":%u:%u:", + uid->created,uid->expiredate); + + if(uid->is_revoked) + fprintf(spawn->tochild,"r"); + if(uid->is_expired) + fprintf(spawn->tochild,"e"); + + fprintf(spawn->tochild,"\n"); + } + } + } + + fprintf(spawn->tochild,"INFO %s END\n",key->d); + + fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d); + fwrite(iobuf_get_temp_buffer(buffer), + iobuf_get_temp_length(buffer),1,spawn->tochild); + fprintf(spawn->tochild,"KEY %s END\n",key->d); + + iobuf_close(buffer); + release_kbnode(block); + } + + free_strlist(temp); + } + + break; + } + + case SEARCH: + { + STRLIST key; + + fprintf(spawn->tochild,"COMMAND SEARCH\n\n"); + + /* Which keys do we want? Remember that the gpgkeys_ program + is going to lump these together into a search string. */ + + for(key=list;key!=NULL;key=key->next) + { + fprintf(spawn->tochild,"%s\n",key->d); + if(key!=list) + { + searchstr=m_realloc(searchstr, + strlen(searchstr)+strlen(key->d)+2); + strcat(searchstr," "); + } + else + { + searchstr=m_alloc(strlen(key->d)+1); + searchstr[0]='\0'; + } + + strcat(searchstr,key->d); + } + + fprintf(spawn->tochild,"\n"); + + break; + } + + default: + log_fatal(_("no keyserver action!\n")); + break; + } + + /* Done sending, so start reading. */ + ret=exec_read(spawn); + if(ret) + goto fail; + + /* Now handle the response */ + + for(;;) + { + int plen; + char *ptr; + + maxlen=1024; + if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) + { + ret=G10ERR_READ_FILE; + goto fail; /* i.e. EOF */ + } + + ptr=line; + + /* remove trailing whitespace */ + plen=strlen(ptr); + while(plen>0 && isspace(ptr[plen-1])) + plen--; + plen[ptr]='\0'; + + if(*ptr=='\0') + break; + + if(ascii_strncasecmp(ptr,"VERSION ",8)==0) + { + gotversion=1; + + if(atoi(&ptr[8])!=KEYSERVER_PROTO_VERSION) + { + log_error(_("invalid keyserver protocol (us %d!=handler %d)\n"), + KEYSERVER_PROTO_VERSION,atoi(&ptr[8])); + goto fail; + } + } + else if(ascii_strncasecmp(ptr,"PROGRAM ",8)==0) + { + if(ascii_strncasecmp(&ptr[8],VERSION,strlen(VERSION))!=0) + log_info(_("WARNING: keyserver handler from a different " + "version of GnuPG (%s)\n"),&ptr[8]); + } + else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0) + outofband=1; /* Currently the only OPTION */ + } + + if(!gotversion) + { + log_error(_("keyserver did not send VERSION\n")); + goto fail; + } + + if(!outofband) + switch(action) + { + case GET: + { + void *stats_handle; + + stats_handle=import_new_stats_handle(); + + /* Slurp up all the key data. In the future, it might be + nice to look for KEY foo OUTOFBAND and FAILED indicators. + It's harmless to ignore them, but ignoring them does make + gpg complain about "no valid OpenPGP data found". One + way to do this could be to continue parsing this + line-by-line and make a temp iobuf for each key. */ + + import_keys_stream(spawn->fromchild,stats_handle, + opt.keyserver_options.import_options); + + import_print_stats(stats_handle); + import_release_stats_handle(stats_handle); + + break; + } + + /* Nothing to do here */ + case SEND: + break; + + case SEARCH: + { + keyserver_search_prompt(spawn->fromchild,searchstr); + + break; + } + + default: + log_fatal(_("no keyserver action!\n")); + break; + } + + fail: + m_free(line); + + *prog=exec_finish(spawn); + + return ret; +} + +static int +keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) +{ + int rc=0,ret=0; + + if(opt.keyserver_scheme==NULL) + { + log_error(_("no keyserver known (use option --keyserver)\n")); + return G10ERR_BAD_URI; + } + +#ifdef DISABLE_KEYSERVER_HELPERS + + log_error(_("external keyserver calls are not supported in this build\n")); + return G10ERR_KEYSERVER; + +#else + /* Spawn a handler */ + + rc=keyserver_spawn(action,list,desc,count,&ret); + if(ret) + { + switch(ret) + { + case KEYSERVER_SCHEME_NOT_FOUND: + log_error(_("no handler for keyserver scheme \"%s\"\n"), + opt.keyserver_scheme); + break; + + case KEYSERVER_NOT_SUPPORTED: + log_error(_("action \"%s\" not supported with keyserver " + "scheme \"%s\"\n"), + action==GET?"get":action==SEND?"send": + action==SEARCH?"search":"unknown", + opt.keyserver_scheme); + break; + + case KEYSERVER_VERSION_ERROR: + log_error(_("gpgkeys_%s does not support handler version %d\n"), + opt.keyserver_scheme,KEYSERVER_PROTO_VERSION); + break; + + case KEYSERVER_INTERNAL_ERROR: + default: + log_error(_("keyserver internal error\n")); + break; + } + + return G10ERR_KEYSERVER; + } + + if(rc) + { + log_error(_("keyserver communications error: %s\n"),g10_errstr(rc)); + + return rc; + } + + return 0; +#endif /* ! DISABLE_KEYSERVER_HELPERS*/ +} + +int +keyserver_export(STRLIST users) +{ + /* We better ask for confirmation when the user entered --send-keys + without arguments. Sending all keys might not be the thing he + intended to do */ + if (users || opt.batch || opt.answer_yes) + ; + else if ( !cpr_get_answer_is_yes + ("keyserver_export.send_all", + _("Do you really want to send all your " + "public keys to the keyserver? (y/N) "))) + return -1; + + return keyserver_work(SEND,users,NULL,0); +} + +int +keyserver_import(STRLIST users) +{ + KEYDB_SEARCH_DESC *desc; + int num=100,count=0; + int rc=0; + + /* Build a list of key ids */ + desc=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); + + for(;users;users=users->next) + { + classify_user_id (users->d, &desc[count]); + if(desc[count].mode!=KEYDB_SEARCH_MODE_SHORT_KID && + desc[count].mode!=KEYDB_SEARCH_MODE_LONG_KID && + desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 && + desc[count].mode!=KEYDB_SEARCH_MODE_FPR20) + { + log_error(_("skipping invalid key ID \"%s\"\n"),users->d); + continue; + } + + count++; + if(count==num) + { + num+=100; + desc=m_realloc(desc,sizeof(KEYDB_SEARCH_DESC)*num); + } + } + + if(count>0) + rc=keyserver_work(GET,NULL,desc,count); + + m_free(desc); + + return rc; +} + +int +keyserver_import_fprint(const byte *fprint,size_t fprint_len) +{ + KEYDB_SEARCH_DESC desc; + + memset(&desc,0,sizeof(desc)); + + if(fprint_len==16) + desc.mode=KEYDB_SEARCH_MODE_FPR16; + else if(fprint_len==20) + desc.mode=KEYDB_SEARCH_MODE_FPR20; + else + return -1; + + memcpy(desc.u.fpr,fprint,fprint_len); + + return keyserver_work(GET,NULL,&desc,1); +} + +int +keyserver_import_keyid(u32 *keyid) +{ + KEYDB_SEARCH_DESC desc; + + memset(&desc,0,sizeof(desc)); + + desc.mode=KEYDB_SEARCH_MODE_LONG_KID; + desc.u.kid[0]=keyid[0]; + desc.u.kid[1]=keyid[1]; + + return keyserver_work(GET,NULL,&desc,1); +} + +/* code mostly stolen from do_export_stream */ +static int +keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) +{ + int rc=0,ndesc,num=100; + KBNODE keyblock=NULL,node; + KEYDB_HANDLE kdbhd; + KEYDB_SEARCH_DESC *desc; + STRLIST sl; + + *count=0; + + *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); + + kdbhd=keydb_new(0); + + if(!users) + { + ndesc = 1; + desc = m_alloc_clear ( ndesc * sizeof *desc); + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + } + else + { + for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) + ; + desc = m_alloc ( 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, g10_errstr (G10ERR_INV_USER_ID)); + } + } + + while (!(rc = keydb_search (kdbhd, desc, ndesc))) + { + 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"), g10_errstr(rc) ); + goto leave; + } + + if((node=find_kbnode(keyblock,PKT_PUBLIC_KEY))) + { + /* This is to work around a bug in some keyservers (pksd and + OKS) that calculate v4 RSA keyids as if they were v3 RSA. + The answer is to refresh both the correct v4 keyid + (e.g. 99242560) and the fake v3 keyid (e.g. 68FDDBC7). + This only happens for key refresh using the HKP scheme + and if the refresh-add-fake-v3-keyids keyserver option is + set. */ + if(fakev3 && is_RSA(node->pkt->pkt.public_key->pubkey_algo) && + node->pkt->pkt.public_key->version>=4) + { + (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; + mpi_get_keyid(node->pkt->pkt.public_key->pkey[0], + (*klist)[*count].u.kid); + (*count)++; + + if(*count==num) + { + num+=100; + *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); + } + } + + /* v4 keys get full fingerprints. v3 keys get long keyids. + This is because it's easy to calculate any sort of key id + from a v4 fingerprint, but not a v3 fingerprint. */ + + if(node->pkt->pkt.public_key->version<4) + { + (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; + keyid_from_pk(node->pkt->pkt.public_key, + (*klist)[*count].u.kid); + } + else + { + size_t dummy; + + (*klist)[*count].mode=KEYDB_SEARCH_MODE_FPR20; + fingerprint_from_pk(node->pkt->pkt.public_key, + (*klist)[*count].u.fpr,&dummy); + } + + (*count)++; + + if(*count==num) + { + num+=100; + *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); + } + } + } + + if(rc==-1) + rc=0; + + leave: + m_free(desc); + keydb_release(kdbhd); + release_kbnode(keyblock); + + return rc; +} + +/* Note this is different than the original HKP refresh. It allows + usernames to refresh only part of the keyring. */ + +int +keyserver_refresh(STRLIST users) +{ + int rc,count,fakev3=0; + KEYDB_SEARCH_DESC *desc; + + /* We switch merge_only on during a refresh, as 'refresh' should + never import new keys, even if their keyids match. Is it worth + preserving the old merge_only value here? */ + opt.merge_only=1; + + /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO + scheme, then enable fake v3 keyid generation. */ + if(opt.keyserver_options.fake_v3_keyids && opt.keyserver_scheme && + (ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0 || + ascii_strcasecmp(opt.keyserver_scheme,"mailto")==0)) + fakev3=1; + + rc=keyidlist(users,&desc,&count,fakev3); + if(rc) + return rc; + + if(count>0) + { + if(opt.keyserver_uri) + { + if(count==1) + log_info(_("refreshing 1 key from %s\n"),opt.keyserver_uri); + else + log_info(_("refreshing %d keys from %s\n"), + count,opt.keyserver_uri); + } + + rc=keyserver_work(GET,NULL,desc,count); + } + + m_free(desc); + + return rc; +} + +int +keyserver_search(STRLIST tokens) +{ + if(tokens) + return keyserver_work(SEARCH,tokens,NULL,0); + else + return 0; +} diff --git a/g10/main.h b/g10/main.h new file mode 100644 index 000000000..a7526c8bc --- /dev/null +++ b/g10/main.h @@ -0,0 +1,241 @@ +/* main.h + * 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 + */ +#ifndef G10_MAIN_H +#define G10_MAIN_H +#include "types.h" +#include "iobuf.h" +#include "mpi.h" +#include "cipher.h" +#include "keydb.h" + +/* It could be argued that the default cipher should be 3DES rather + than CAST5, and the default compression should be 0 + (i.e. uncompressed) rather than 1 (zip). */ +#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5 +#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1 +#define DEFAULT_COMPRESS_ALGO 1 + +typedef struct { + int header_okay; + PK_LIST pk_list; + cipher_filter_context_t cfx; +} encrypt_filter_context_t; + +struct groupitem +{ + char *name; + STRLIST values; + struct groupitem *next; +}; + +/*-- g10.c --*/ +extern int g10_errors_seen; + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) + void g10_exit(int rc) __attribute__ ((noreturn)); +#else + void g10_exit(int rc); +#endif +void print_pubkey_algo_note( int algo ); +void print_cipher_algo_note( int algo ); +void print_digest_algo_note( int algo ); + +/*-- armor.c --*/ +char *make_radix64_string( const byte *data, size_t len ); + +/*-- misc.c --*/ +void trap_unaligned(void); +int disable_core_dumps(void); +u16 checksum_u16( unsigned n ); +u16 checksum( byte *p, unsigned n ); +u16 checksum_mpi( MPI a ); +u32 buffer_to_u32( const byte *buffer ); +const byte *get_session_marker( size_t *rlen ); +int openpgp_cipher_test_algo( int algo ); +int openpgp_pk_test_algo( int algo, unsigned int usage_flags ); +int openpgp_pk_algo_usage ( int algo ); +int openpgp_md_test_algo( int algo ); + +#ifdef USE_IDEA +void idea_cipher_warn( int show ); +#else +#define idea_cipher_warn(a) +#endif + +struct expando_args +{ + PKT_public_key *pk; + PKT_secret_key *sk; + byte imagetype; +}; + +char *pct_expando(const char *string,struct expando_args *args); +int hextobyte( const char *s ); +void deprecated_warning(const char *configname,unsigned int configlineno, + const char *option,const char *repl1,const char *repl2); +const char *compress_algo_to_string(int algo); +int string_to_compress_algo(const char *string); +int check_compress_algo(int algo); +int default_cipher_algo(void); +int default_compress_algo(void); +const char *compliance_option_string(void); +void compliance_failure(void); + +struct parse_options +{ + char *name; + unsigned int bit; +}; + +int parse_options(char *str,unsigned int *options,struct parse_options *opts); + +/*-- helptext.c --*/ +void display_online_help( const char *keyword ); + +/*-- encode.c --*/ +int encode_symmetric( const char *filename ); +int encode_store( const char *filename ); +int encode_crypt( const char *filename, STRLIST remusr ); +void encode_crypt_files(int nfiles, char **files, STRLIST remusr); +int encrypt_filter( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len); + + +/*-- sign.c --*/ +int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ); +int sign_file( STRLIST filenames, int detached, STRLIST locusr, + int do_encrypt, STRLIST remusr, const char *outfile ); +int clearsign_file( const char *fname, STRLIST locusr, const char *outfile ); +int sign_symencrypt_file (const char *fname, STRLIST locusr); + +/*-- sig-check.c --*/ +int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig); +int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); +int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, + int *is_selfsig, u32 *r_expiredate, int *r_expired ); + +/*-- delkey.c --*/ +int delete_keys( STRLIST names, int secret, int allow_both ); + +/*-- keyedit.c --*/ +void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds, + int sign_mode ); +void show_basic_key_info (KBNODE keyblock); + +/*-- keygen.c --*/ +u32 ask_expire_interval(int object); +u32 ask_expiredate(void); +void generate_keypair( const char *fname ); +int keygen_set_std_prefs (const char *string,int personal); +PKT_user_id *keygen_get_std_prefs (void); +int keygen_add_key_expire( PKT_signature *sig, void *opaque ); +int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); +int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); +int keygen_add_revkey(PKT_signature *sig, void *opaque); +int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); + +/*-- openfile.c --*/ +int overwrite_filep( const char *fname ); +char *make_outfile_name( const char *iname ); +char *ask_outfile_name( const char *name, size_t namelen ); +int open_outfile( const char *iname, int mode, IOBUF *a ); +IOBUF open_sigfile( const char *iname, progress_filter_context_t *pfx ); +void try_make_homedir( const char *fname ); + +/*-- seskey.c --*/ +void make_session_key( DEK *dek ); +MPI encode_session_key( DEK *dek, unsigned nbits ); +MPI encode_md_value( int pubkey_algo, MD_HANDLE md, + int hash_algo, unsigned nbits, int v3compathack ); + +/*-- comment.c --*/ +KBNODE make_comment_node( const char *s ); +KBNODE make_mpi_comment_node( const char *s, MPI a ); + +/*-- import.c --*/ +int parse_import_options(char *str,unsigned int *options); +void import_keys( char **fnames, int nnames, + void *stats_hd, unsigned int options ); +int import_keys_stream( IOBUF inp, + void *stats_hd, unsigned int options ); +void *import_new_stats_handle (void); +void import_release_stats_handle (void *p); +void import_print_stats (void *hd); + +int collapse_uids( KBNODE *keyblock ); + +/*-- export.c --*/ +int parse_export_options(char *str,unsigned int *options); +int export_pubkeys( STRLIST users, unsigned int options ); +int export_pubkeys_stream( IOBUF out, STRLIST users, + KBNODE *keyblock_out, unsigned int options ); +int export_seckeys( STRLIST users ); +int export_secsubkeys( STRLIST users ); + +/* dearmor.c --*/ +int dearmor_file( const char *fname ); +int enarmor_file( const char *fname ); + +/*-- revoke.c --*/ +struct revocation_reason_info; +int gen_revoke( const char *uname ); +int gen_desig_revoke( const char *uname ); +int revocation_reason_build_cb( PKT_signature *sig, void *opaque ); +struct revocation_reason_info * + ask_revocation_reason( int key_rev, int cert_rev, int hint ); +void release_revocation_reason_info( struct revocation_reason_info *reason ); + +/*-- keylist.c --*/ +void public_key_list( STRLIST list ); +void secret_key_list( STRLIST list ); +void reorder_keyblock (KBNODE keyblock); +void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); +void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); +void show_policy_url(PKT_signature *sig,int indent,int mode); +void show_notation(PKT_signature *sig,int indent,int mode); +void dump_attribs(const PKT_user_id *uid, + PKT_public_key *pk,PKT_secret_key *sk); +void set_attrib_fd(int fd); +void print_seckey_info (PKT_secret_key *sk); +void print_pubkey_info (PKT_public_key *pk); + +/*-- verify.c --*/ +void print_file_status( int status, const char *name, int what ); +int verify_signatures( int nfiles, char **files ); +int verify_files( int nfiles, char **files ); + +/*-- decrypt.c --*/ +int decrypt_message( const char *filename ); +void decrypt_messages(int nfiles, char **files); + +/*-- plaintext.c --*/ +int hash_datafiles( MD_HANDLE md, MD_HANDLE md2, + STRLIST files, const char *sigfilename, int textmode ); + +/*-- pipemode.c --*/ +void run_in_pipemode (void); + +/*-- signal.c --*/ +void init_signals(void); +void pause_on_sigusr( int which ); +void block_all_signals(void); +void unblock_all_signals(void); + +#endif /*G10_MAIN_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c new file mode 100644 index 000000000..faba197fe --- /dev/null +++ b/g10/mainproc.c @@ -0,0 +1,1681 @@ +/* mainproc.c - handle 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 <time.h> + +#include "packet.h" +#include "iobuf.h" +#include "memory.h" +#include "options.h" +#include "util.h" +#include "cipher.h" +#include "keydb.h" +#include "filter.h" +#include "main.h" +#include "status.h" +#include "i18n.h" +#include "trustdb.h" +#include "keyserver-internal.h" +#include "photoid.h" + + +struct kidlist_item { + struct kidlist_item *next; + u32 kid[2]; + int pubkey_algo; + int reason; +}; + + + +/**************** + * Structure to hold the context + */ +typedef struct mainproc_context *CTX; +struct mainproc_context { + struct mainproc_context *anchor; /* may be useful in the future */ + PKT_public_key *last_pubkey; + PKT_secret_key *last_seckey; + PKT_user_id *last_user_id; + md_filter_context_t mfx; + int sigs_only; /* process only signatures and reject all other stuff */ + int encrypt_only; /* process only encrytion messages */ + STRLIST signed_data; + const char *sigfilename; + DEK *dek; + int last_was_session_key; + KBNODE list; /* the current list of packets */ + int have_data; + IOBUF iobuf; /* used to get the filename etc. */ + int trustletter; /* temp usage in list_node */ + ulong local_id; /* ditto */ + struct kidlist_item *pkenc_list; /* list of encryption packets */ + struct { + int op; + int stop_now; + } pipemode; +}; + + +static int do_proc_packets( CTX c, IOBUF a ); + +static void list_node( CTX c, KBNODE node ); +static void proc_tree( CTX c, KBNODE node ); + + +static void +release_list( CTX c ) +{ + if( !c->list ) + return; + proc_tree(c, c->list ); + release_kbnode( c->list ); + while( c->pkenc_list ) { + struct kidlist_item *tmp = c->pkenc_list->next; + m_free( c->pkenc_list ); + c->pkenc_list = tmp; + } + c->pkenc_list = NULL; + c->list = NULL; + c->have_data = 0; + c->last_was_session_key = 0; + c->pipemode.op = 0; + c->pipemode.stop_now = 0; + m_free(c->dek); c->dek = NULL; +} + + +static int +add_onepass_sig( CTX c, PACKET *pkt ) +{ + KBNODE node; + + if( c->list ) { /* add another packet */ + /* We can only append another onepass packet if the list + * does contain only onepass packets */ + for( node=c->list; node && node->pkt->pkttype == PKT_ONEPASS_SIG; + node = node->next ) + ; + if( node ) { + /* this is not the case, so we flush the current thing and + * allow this packet to start a new verification thing */ + release_list( c ); + c->list = new_kbnode( pkt ); + } + else + add_kbnode( c->list, new_kbnode( pkt )); + } + else /* insert the first one */ + c->list = node = new_kbnode( pkt ); + + return 1; +} + + +static int +add_gpg_control( CTX c, PACKET *pkt ) +{ + if ( pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START ) { + /* New clear text signature. + * Process the last one and reset everything */ + release_list(c); + } + else if ( pkt->pkt.gpg_control->control == CTRLPKT_PIPEMODE ) { + /* Pipemode control packet */ + if ( pkt->pkt.gpg_control->datalen < 2 ) + log_fatal ("invalid pipemode control packet length\n"); + if (pkt->pkt.gpg_control->data[0] == 1) { + /* start the whole thing */ + assert ( !c->list ); /* we should be in a pretty virgin state */ + assert ( !c->pipemode.op ); + c->pipemode.op = pkt->pkt.gpg_control->data[1]; + } + else if (pkt->pkt.gpg_control->data[0] == 2) { + /* the signed material follows in a plaintext packet */ + assert ( c->pipemode.op == 'B' ); + } + else if (pkt->pkt.gpg_control->data[0] == 3) { + assert ( c->pipemode.op == 'B' ); + release_list (c); + /* and tell the outer loop to terminate */ + c->pipemode.stop_now = 1; + } + else + log_fatal ("invalid pipemode control packet code\n"); + return 0; /* no need to store the packet */ + } + + if( c->list ) /* add another packet */ + add_kbnode( c->list, new_kbnode( pkt )); + else /* insert the first one */ + c->list = new_kbnode( pkt ); + + return 1; +} + + + +static int +add_user_id( CTX c, PACKET *pkt ) +{ + if( !c->list ) { + log_error("orphaned user ID\n" ); + return 0; + } + add_kbnode( c->list, new_kbnode( pkt ) ); + return 1; +} + +static int +add_subkey( CTX c, PACKET *pkt ) +{ + if( !c->list ) { + log_error("subkey w/o mainkey\n" ); + return 0; + } + add_kbnode( c->list, new_kbnode( pkt ) ); + return 1; +} + +static int +add_ring_trust( CTX c, PACKET *pkt ) +{ + if( !c->list ) { + log_error("ring trust w/o key\n" ); + return 0; + } + add_kbnode( c->list, new_kbnode( pkt ) ); + return 1; +} + + +static int +add_signature( CTX c, PACKET *pkt ) +{ + KBNODE node; + + if( pkt->pkttype == PKT_SIGNATURE && !c->list ) { + /* This is the first signature for the following datafile. + * GPG does not write such packets; instead it always uses + * onepass-sig packets. The drawback of PGP's method + * of prepending the signature to the data is + * that it is not possible to make a signature from data read + * from stdin. (GPG is able to read PGP stuff anyway.) */ + node = new_kbnode( pkt ); + c->list = node; + return 1; + } + else if( !c->list ) + return 0; /* oops (invalid packet sequence)*/ + else if( !c->list->pkt ) + BUG(); /* so nicht */ + + /* add a new signature node id at the end */ + node = new_kbnode( pkt ); + add_kbnode( c->list, node ); + return 1; +} + +static void +symkey_decrypt_sesskey( DEK *dek, byte *sesskey, size_t slen ) +{ + CIPHER_HANDLE hd; + int n; + + if ( slen < 17 || slen > 33 ) { + log_error ( _("weird size for an encrypted session key (%d)\n"), + (int)slen); + return; + } + hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); + cipher_setkey( hd, dek->key, dek->keylen ); + cipher_setiv( hd, NULL, 0 ); + cipher_decrypt( hd, sesskey, sesskey, slen ); + cipher_close( hd ); + /* check first byte (the cipher algo) */ + if ( sesskey[0] > 10 ) { + log_error ( _("invalid symkey algorithm detected (%d)\n"), + sesskey[0] ); + return; + } + n = cipher_get_keylen (sesskey[0]) / 8; + if (n > DIM(dek->key)) + BUG (); + /* now we replace the dek components with the real session key + to decrypt the contents of the sequencing packet. */ + dek->keylen = cipher_get_keylen( sesskey[0] ) / 8; + dek->algo = sesskey[0]; + memcpy( dek->key, sesskey + 1, dek->keylen ); + /*log_hexdump( "thekey", dek->key, dek->keylen );*/ +} + +static void +proc_symkey_enc( CTX c, PACKET *pkt ) +{ + PKT_symkey_enc *enc; + + enc = pkt->pkt.symkey_enc; + if (!enc) + log_error ("invalid symkey encrypted packet\n"); + else { + int algo = enc->cipher_algo; + const char *s; + + s = cipher_algo_to_string (algo); + if( s ) + log_info(_("%s encrypted data\n"), s ); + else + log_info(_("encrypted with unknown algorithm %d\n"), algo ); + + c->last_was_session_key = 2; + if ( opt.list_only ) + goto leave; + c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL, NULL ); + if (c->dek) + c->dek->algo_info_printed = 1; + if ( c->dek && enc->seskeylen ) + symkey_decrypt_sesskey( c->dek, enc->seskey, enc->seskeylen ); + } +leave: + free_packet(pkt); +} + +static void +proc_pubkey_enc( CTX c, PACKET *pkt ) +{ + PKT_pubkey_enc *enc; + int result = 0; + + /* check whether the secret key is available and store in this case */ + c->last_was_session_key = 1; + enc = pkt->pkt.pubkey_enc; + /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ + /* Hmmm: why do I have this algo check here - anyway there is + * function to check it. */ + if( opt.verbose ) + log_info(_("public key is %08lX\n"), (ulong)enc->keyid[1] ); + + if( is_status_enabled() ) { + char buf[50]; + sprintf(buf, "%08lX%08lX %d 0", + (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo ); + write_status_text( STATUS_ENC_TO, buf ); + } + + if( !opt.list_only && opt.override_session_key ) { + /* It does not make much sense to store the session key in + * secure memory because it has already been passed on the + * command line and the GCHQ knows about it */ + c->dek = m_alloc_clear( sizeof *c->dek ); + result = get_override_session_key ( c->dek, opt.override_session_key ); + if ( result ) { + m_free(c->dek); c->dek = NULL; + } + } + else if( is_ELGAMAL(enc->pubkey_algo) + || enc->pubkey_algo == PUBKEY_ALGO_DSA + || is_RSA(enc->pubkey_algo) ) { + if ( !c->dek && ((!enc->keyid[0] && !enc->keyid[1]) + || opt.try_all_secrets + || !seckey_available( enc->keyid )) ) { + if( opt.list_only ) + result = -1; + else { + c->dek = m_alloc_secure_clear( sizeof *c->dek ); + if( (result = get_session_key( enc, c->dek )) ) { + /* error: delete the DEK */ + m_free(c->dek); c->dek = NULL; + } + } + } + else + result = G10ERR_NO_SECKEY; + } + else + result = G10ERR_PUBKEY_ALGO; + + if( result == -1 ) + ; + else { + if( !result ) { + if( opt.verbose > 1 ) + log_info( _("public key encrypted data: good DEK\n") ); + if ( opt.show_session_key ) { + int i; + char *buf = m_alloc ( c->dek->keylen*2 + 20 ); + sprintf ( buf, "%d:", c->dek->algo ); + for(i=0; i < c->dek->keylen; i++ ) + sprintf(buf+strlen(buf), "%02X", c->dek->key[i] ); + log_info( "session key: \"%s\"\n", buf ); + write_status_text ( STATUS_SESSION_KEY, buf ); + } + } + /* store it for later display */ + { + struct kidlist_item *x = m_alloc( sizeof *x ); + x->kid[0] = enc->keyid[0]; + x->kid[1] = enc->keyid[1]; + x->pubkey_algo = enc->pubkey_algo; + x->reason = result; + x->next = c->pkenc_list; + c->pkenc_list = x; + } + } + free_packet(pkt); +} + + + +/**************** + * Print the list of public key encrypted packets which we could + * not decrypt. + */ +static void +print_pkenc_list( struct kidlist_item *list, int failed ) +{ + for( ; list; list = list->next ) { + PKT_public_key *pk; + const char *algstr; + + if ( failed && !list->reason ) + continue; + if ( !failed && list->reason ) + continue; + + algstr = pubkey_algo_to_string( list->pubkey_algo ); + pk = m_alloc_clear( sizeof *pk ); + + if( !algstr ) + algstr = "[?]"; + pk->pubkey_algo = list->pubkey_algo; + if( !get_pubkey( pk, list->kid ) ) { + size_t n; + char *p; + log_info( _("encrypted with %u-bit %s key, ID %08lX, created %s\n"), + nbits_from_pk( pk ), algstr, (ulong)list->kid[1], + strtimestamp(pk->timestamp) ); + fputs(" \"", log_stream() ); + p = get_user_id( list->kid, &n ); + print_utf8_string2 ( log_stream(), p, n, '"' ); + m_free(p); + fputs("\"\n", log_stream() ); + } + else { + log_info(_("encrypted with %s key, ID %08lX\n"), + algstr, (ulong) list->kid[1] ); + } + free_public_key( pk ); + + if( list->reason == G10ERR_NO_SECKEY ) { + if( is_status_enabled() ) { + char buf[20]; + sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], + (ulong)list->kid[1] ); + write_status_text( STATUS_NO_SECKEY, buf ); + } + } + else if (list->reason) + log_info(_("public key decryption failed: %s\n"), + g10_errstr(list->reason)); + } +} + + +static void +proc_encrypted( CTX c, PACKET *pkt ) +{ + int result = 0; + + if (!opt.quiet) { + print_pkenc_list ( c->pkenc_list, 1 ); + print_pkenc_list ( c->pkenc_list, 0 ); + } + + write_status( STATUS_BEGIN_DECRYPTION ); + + /*log_debug("dat: %sencrypted data\n", c->dek?"":"conventional ");*/ + if( opt.list_only ) + result = -1; + else if( !c->dek && !c->last_was_session_key ) { + int algo; + STRING2KEY s2kbuf, *s2k = NULL; + + /* assume this is old style conventional encrypted data */ + if ( (algo = opt.def_cipher_algo)) + log_info (_("assuming %s encrypted data\n"), + cipher_algo_to_string(algo)); + else if ( check_cipher_algo(CIPHER_ALGO_IDEA) ) { + algo = opt.def_cipher_algo; + if (!algo) + algo = opt.s2k_cipher_algo; + idea_cipher_warn(1); + log_info (_("IDEA cipher unavailable, " + "optimistically attempting to use %s instead\n"), + cipher_algo_to_string(algo)); + } + else { + algo = CIPHER_ALGO_IDEA; + if (!opt.s2k_digest_algo) { + /* If no digest is given we assume MD5 */ + s2kbuf.mode = 0; + s2kbuf.hash_algo = DIGEST_ALGO_MD5; + s2k = &s2kbuf; + } + log_info (_("assuming %s encrypted data\n"), "IDEA"); + } + + c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL, NULL ); + if (c->dek) + c->dek->algo_info_printed = 1; + } + else if( !c->dek ) + result = G10ERR_NO_SECKEY; + if( !result ) + result = decrypt_data( c, pkt->pkt.encrypted, c->dek ); + + m_free(c->dek); c->dek = NULL; + if( result == -1 ) + ; + else if( !result || (result==G10ERR_BAD_SIGN && opt.ignore_mdc_error)) { + write_status( STATUS_DECRYPTION_OKAY ); + if( opt.verbose > 1 ) + log_info(_("decryption okay\n")); + if( pkt->pkt.encrypted->mdc_method && !result ) + write_status( STATUS_GOODMDC ); + else if(!opt.no_mdc_warn) + log_info (_("WARNING: message was not integrity protected\n")); + } + else if( result == G10ERR_BAD_SIGN ) { + log_error(_("WARNING: encrypted message has been manipulated!\n")); + write_status( STATUS_BADMDC ); + write_status( STATUS_DECRYPTION_FAILED ); + } + else { + write_status( STATUS_DECRYPTION_FAILED ); + log_error(_("decryption failed: %s\n"), g10_errstr(result)); + /* Hmmm: does this work when we have encrypted using multiple + * ways to specify the session key (symmmetric and PK)*/ + } + free_packet(pkt); + c->last_was_session_key = 0; + write_status( STATUS_END_DECRYPTION ); +} + + + +static void +proc_plaintext( CTX c, PACKET *pkt ) +{ + PKT_plaintext *pt = pkt->pkt.plaintext; + int any, clearsig, only_md5, rc; + KBNODE n; + + if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) + log_info(_("NOTE: sender requested \"for-your-eyes-only\"\n")); + else if( opt.verbose ) + log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name); + free_md_filter_context( &c->mfx ); + c->mfx.md = md_open( 0, 0); + /* fixme: we may need to push the textfilter if we have sigclass 1 + * and no armoring - Not yet tested + * Hmmm, why don't we need it at all if we have sigclass 1 + * Should we assume that plaintext in mode 't' has always sigclass 1?? + * See: Russ Allbery's mail 1999-02-09 + */ + any = clearsig = only_md5 = 0; + for(n=c->list; n; n = n->next ) { + if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { + if( n->pkt->pkt.onepass_sig->digest_algo ) { + md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); + if( !any && n->pkt->pkt.onepass_sig->digest_algo + == DIGEST_ALGO_MD5 ) + only_md5 = 1; + else + only_md5 = 0; + any = 1; + } + if( n->pkt->pkt.onepass_sig->sig_class != 0x01 ) + only_md5 = 0; + } + else if( n->pkt->pkttype == PKT_GPG_CONTROL + && n->pkt->pkt.gpg_control->control + == CTRLPKT_CLEARSIGN_START ) { + size_t datalen = n->pkt->pkt.gpg_control->datalen; + const byte *data = n->pkt->pkt.gpg_control->data; + + /* check that we have at least the sigclass and one hash */ + if ( datalen < 2 ) + log_fatal("invalid control packet CTRLPKT_CLEARSIGN_START\n"); + /* Note that we don't set the clearsig flag for not-dash-escaped + * documents */ + clearsig = (*data == 0x01); + for( data++, datalen--; datalen; datalen--, data++ ) + md_enable( c->mfx.md, *data ); + any = 1; + break; /* no pass signature pakets are expected */ + } + } + + if( !any && !opt.skip_verify ) { + /* no onepass sig packet: enable all standard algos */ + md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); + md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); + md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); + } + if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) { + /* This is a kludge to work around a bug in pgp2. It does only + * catch those mails which are armored. To catch the non-armored + * pgp mails we could see whether there is the signature packet + * in front of the plaintext. If someone needs this, send me a patch. + */ + c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0); + } + if ( DBG_HASHING ) { + md_start_debug( c->mfx.md, "verify" ); + if ( c->mfx.md2 ) + md_start_debug( c->mfx.md2, "verify2" ); + } + if ( c->pipemode.op == 'B' ) + rc = handle_plaintext( pt, &c->mfx, 1, 0 ); + else { + rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); + if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { + /* can't write output but we hash it anyway to + * check the signature */ + rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); + } + } + if( rc ) + log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); + free_packet(pkt); + c->last_was_session_key = 0; + + /* We add a marker control packet instead of the plaintext packet. + * This is so that we can later detect invalid packet sequences. + */ + n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK, NULL, 0)); + if (c->list) + add_kbnode (c->list, n); + else + c->list = n; +} + + +static int +proc_compressed_cb( IOBUF a, void *info ) +{ + return proc_signature_packets( info, a, ((CTX)info)->signed_data, + ((CTX)info)->sigfilename ); +} + +static int +proc_encrypt_cb( IOBUF a, void *info ) +{ + return proc_encryption_packets( info, a ); +} + +static void +proc_compressed( CTX c, PACKET *pkt ) +{ + PKT_compressed *zd = pkt->pkt.compressed; + int rc; + + /*printf("zip: compressed data packet\n");*/ + if( c->sigs_only ) + rc = handle_compressed( c, zd, proc_compressed_cb, c ); + else if( c->encrypt_only ) + rc = handle_compressed( c, zd, proc_encrypt_cb, c ); + else + rc = handle_compressed( c, zd, NULL, NULL ); + if( rc ) + log_error("uncompressing failed: %s\n", g10_errstr(rc)); + free_packet(pkt); + c->last_was_session_key = 0; +} + +/**************** + * check the signature + * Returns: 0 = valid signature or an error code + */ +static int +do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) +{ + PKT_signature *sig; + MD_HANDLE md = NULL, md2 = NULL; + int algo, rc, dum2; + u32 dummy; + + if(!is_expkey) + is_expkey=&dum2; + + assert( node->pkt->pkttype == PKT_SIGNATURE ); + if( is_selfsig ) + *is_selfsig = 0; + sig = node->pkt->pkt.signature; + + algo = sig->digest_algo; + if( (rc=check_digest_algo(algo)) ) + return rc; + + if( sig->sig_class == 0x00 ) { + if( c->mfx.md ) + md = md_copy( c->mfx.md ); + else /* detached signature */ + md = md_open( 0, 0 ); /* signature_check() will enable the md*/ + } + else if( sig->sig_class == 0x01 ) { + /* how do we know that we have to hash the (already hashed) text + * in canonical mode ??? (calculating both modes???) */ + if( c->mfx.md ) { + md = md_copy( c->mfx.md ); + if( c->mfx.md2 ) + md2 = md_copy( c->mfx.md2 ); + } + else { /* detached signature */ + log_debug("Do we really need this here?"); + md = md_open( 0, 0 ); /* signature_check() will enable the md*/ + md2 = md_open( 0, 0 ); + } + } + else if( (sig->sig_class&~3) == 0x10 + || sig->sig_class == 0x18 + || sig->sig_class == 0x1f + || sig->sig_class == 0x20 + || sig->sig_class == 0x28 + || sig->sig_class == 0x30 ) { + if( c->list->pkt->pkttype == PKT_PUBLIC_KEY + || c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + return check_key_signature( c->list, node, is_selfsig ); + } + else if( sig->sig_class == 0x20 ) { + log_info(_("standalone revocation - " + "use \"gpg --import\" to apply\n")); + return G10ERR_NOT_PROCESSED; + } + else { + log_error("invalid root packet for sigclass %02x\n", + sig->sig_class); + return G10ERR_SIG_CLASS; + } + } + else + return G10ERR_SIG_CLASS; + rc = signature_check2( sig, md, &dummy, is_expkey ); + if( rc == G10ERR_BAD_SIGN && md2 ) + rc = signature_check2( sig, md2, &dummy, is_expkey ); + md_close(md); + md_close(md2); + + return rc; +} + + +static void +print_userid( PACKET *pkt ) +{ + if( !pkt ) + BUG(); + if( pkt->pkttype != PKT_USER_ID ) { + printf("ERROR: unexpected packet type %d", pkt->pkttype ); + return; + } + if( opt.with_colons ) + { + if(pkt->pkt.user_id->attrib_data) + printf("%u %lu", + pkt->pkt.user_id->numattribs, + pkt->pkt.user_id->attrib_len); + else + print_string( stdout, pkt->pkt.user_id->name, + pkt->pkt.user_id->len, ':'); + } + else + print_utf8_string( stdout, pkt->pkt.user_id->name, + pkt->pkt.user_id->len ); +} + + +/**************** + * List the certificate in a user friendly way + */ + +static void +list_node( CTX c, KBNODE node ) +{ + int any=0; + int mainkey; + + if( !node ) + ; + else if( (mainkey = (node->pkt->pkttype == PKT_PUBLIC_KEY) ) + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + PKT_public_key *pk = node->pkt->pkt.public_key; + + if( opt.with_colons ) { + u32 keyid[2]; + keyid_from_pk( pk, keyid ); + if( mainkey ) { + c->local_id = pk->local_id; + c->trustletter = opt.fast_list_mode? + 0 : get_validity_info( pk, NULL ); + } + printf("%s:", mainkey? "pub":"sub" ); + if( c->trustletter ) + putchar( c->trustletter ); + printf(":%u:%d:%08lX%08lX:%s:%s:", + nbits_from_pk( pk ), + pk->pubkey_algo, + (ulong)keyid[0],(ulong)keyid[1], + colon_datestr_from_pk( pk ), + colon_strtime (pk->expiredate) ); + if( c->local_id ) + printf("%lu", c->local_id ); + putchar(':'); + if( mainkey && !opt.fast_list_mode ) + putchar( get_ownertrust_info (pk) ); + putchar(':'); + if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) { + putchar('\n'); any=1; + if( opt.fingerprint ) + print_fingerprint( pk, NULL, 0 ); + printf("rtv:1:%u:\n", + node->next->pkt->pkt.ring_trust->trustval ); + } + } + else + printf("%s %4u%c/%08lX %s ", + mainkey? "pub":"sub", + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + (ulong)keyid_from_pk( pk, NULL ), + datestr_from_pk( pk ) ); + + if( mainkey ) { + /* and now list all userids with their signatures */ + for( node = node->next; node; node = node->next ) { + if( node->pkt->pkttype == PKT_SIGNATURE ) { + if( !any ) { + if( node->pkt->pkt.signature->sig_class == 0x20 ) + puts("[revoked]"); + else + putchar('\n'); + any = 1; + } + list_node(c, node ); + } + else if( node->pkt->pkttype == PKT_USER_ID ) { + if( any ) { + if( opt.with_colons ) + printf("%s:::::::::", + node->pkt->pkt.user_id->attrib_data?"uat":"uid"); + else + printf( "uid%*s", 28, "" ); + } + print_userid( node->pkt ); + if( opt.with_colons ) + putchar(':'); + putchar('\n'); + if( opt.fingerprint && !any ) + print_fingerprint( pk, NULL, 0 ); + if( node->next + && node->next->pkt->pkttype == PKT_RING_TRUST ) { + printf("rtv:2:%u:\n", + node->next->pkt->pkt.ring_trust->trustval ); + } + any=1; + } + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + if( !any ) { + putchar('\n'); + any = 1; + } + list_node(c, node ); + } + } + } + else if( pk->expiredate ) { /* of subkey */ + printf(_(" [expires: %s]"), expirestr_from_pk( pk ) ); + } + + if( !any ) + putchar('\n'); + if( !mainkey && opt.fingerprint > 1 ) + print_fingerprint( pk, NULL, 0 ); + } + else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) ) + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = node->pkt->pkt.secret_key; + + if( opt.with_colons ) { + u32 keyid[2]; + keyid_from_sk( sk, keyid ); + printf("%s::%u:%d:%08lX%08lX:%s:%s:::", + mainkey? "sec":"ssb", + nbits_from_sk( sk ), + sk->pubkey_algo, + (ulong)keyid[0],(ulong)keyid[1], + colon_datestr_from_sk( sk ), + colon_strtime (sk->expiredate) + /* fixme: add LID */ ); + } + else + printf("%s %4u%c/%08lX %s ", + mainkey? "sec":"ssb", + nbits_from_sk( sk ), + pubkey_letter( sk->pubkey_algo ), + (ulong)keyid_from_sk( sk, NULL ), + datestr_from_sk( sk ) ); + if( mainkey ) { + /* and now list all userids with their signatures */ + for( node = node->next; node; node = node->next ) { + if( node->pkt->pkttype == PKT_SIGNATURE ) { + if( !any ) { + if( node->pkt->pkt.signature->sig_class == 0x20 ) + puts("[revoked]"); + else + putchar('\n'); + any = 1; + } + list_node(c, node ); + } + else if( node->pkt->pkttype == PKT_USER_ID ) { + if( any ) { + if( opt.with_colons ) + printf("%s:::::::::", + node->pkt->pkt.user_id->attrib_data?"uat":"uid"); + else + printf( "uid%*s", 28, "" ); + } + print_userid( node->pkt ); + if( opt.with_colons ) + putchar(':'); + putchar('\n'); + if( opt.fingerprint && !any ) + print_fingerprint( NULL, sk, 0 ); + any=1; + } + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { + if( !any ) { + putchar('\n'); + any = 1; + } + list_node(c, node ); + } + } + } + if( !any ) + putchar('\n'); + if( !mainkey && opt.fingerprint > 1 ) + print_fingerprint( NULL, sk, 0 ); + } + else if( node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + int is_selfsig = 0; + int rc2=0; + size_t n; + char *p; + int sigrc = ' '; + + if( !opt.list_sigs ) + return; + + if( sig->sig_class == 0x20 || sig->sig_class == 0x30 ) + fputs("rev", stdout); + else + fputs("sig", stdout); + if( opt.check_sigs ) { + fflush(stdout); + switch( (rc2=do_check_sig( c, node, &is_selfsig, NULL )) ) { + case 0: sigrc = '!'; break; + case G10ERR_BAD_SIGN: sigrc = '-'; break; + case G10ERR_NO_PUBKEY: + case G10ERR_UNU_PUBKEY: sigrc = '?'; break; + default: sigrc = '%'; break; + } + } + else { /* check whether this is a self signature */ + u32 keyid[2]; + + if( c->list->pkt->pkttype == PKT_PUBLIC_KEY + || c->list->pkt->pkttype == PKT_SECRET_KEY ) { + if( c->list->pkt->pkttype == PKT_PUBLIC_KEY ) + keyid_from_pk( c->list->pkt->pkt.public_key, keyid ); + else + keyid_from_sk( c->list->pkt->pkt.secret_key, keyid ); + + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) + is_selfsig = 1; + } + } + if( opt.with_colons ) { + putchar(':'); + if( sigrc != ' ' ) + putchar(sigrc); + printf("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo, + (ulong)sig->keyid[0], (ulong)sig->keyid[1], + colon_datestr_from_sig(sig), + colon_expirestr_from_sig(sig)); + + if(sig->trust_depth || sig->trust_value) + printf("%d %d",sig->trust_depth,sig->trust_value); + printf(":"); + + if(sig->trust_regexp) + print_string(stdout,sig->trust_regexp, + strlen(sig->trust_regexp),':'); + printf(":"); + } + else + printf("%c %08lX %s ", + sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig)); + if( sigrc == '%' ) + printf("[%s] ", g10_errstr(rc2) ); + else if( sigrc == '?' ) + ; + else if( is_selfsig ) { + if( opt.with_colons ) + putchar(':'); + fputs( sig->sig_class == 0x18? "[keybind]":"[selfsig]", stdout); + if( opt.with_colons ) + putchar(':'); + } + else if( !opt.fast_list_mode ) { + p = get_user_id( sig->keyid, &n ); + print_string( stdout, p, n, opt.with_colons ); + m_free(p); + } + if( opt.with_colons ) + printf(":%02x%c:", sig->sig_class, sig->flags.exportable?'x':'l'); + putchar('\n'); + } + else + log_error("invalid node with packet of type %d\n", node->pkt->pkttype); +} + + + +int +proc_packets( void *anchor, IOBUF a ) +{ + int rc; + CTX c = m_alloc_clear( sizeof *c ); + + c->anchor = anchor; + rc = do_proc_packets( c, a ); + m_free( c ); + return rc; +} + + + +int +proc_signature_packets( void *anchor, IOBUF a, + STRLIST signedfiles, const char *sigfilename ) +{ + CTX c = m_alloc_clear( sizeof *c ); + int rc; + + c->anchor = anchor; + c->sigs_only = 1; + c->signed_data = signedfiles; + c->sigfilename = sigfilename; + rc = do_proc_packets( c, a ); + m_free( c ); + return rc; +} + +int +proc_encryption_packets( void *anchor, IOBUF a ) +{ + CTX c = m_alloc_clear( sizeof *c ); + int rc; + + c->anchor = anchor; + c->encrypt_only = 1; + rc = do_proc_packets( c, a ); + m_free( c ); + return rc; +} + + +int +do_proc_packets( CTX c, IOBUF a ) +{ + PACKET *pkt = m_alloc( sizeof *pkt ); + int rc=0; + int any_data=0; + int newpkt; + + c->iobuf = a; + init_packet(pkt); + while( (rc=parse_packet(a, pkt)) != -1 ) { + any_data = 1; + if( rc ) { + free_packet(pkt); + /* stop processing when an invalid packet has been encountered + * but don't do so when we are doing a --list-packet. */ + if( rc == G10ERR_INVALID_PACKET && opt.list_packets != 2 ) + break; + continue; + } + newpkt = -1; + if( opt.list_packets ) { + switch( pkt->pkttype ) { + case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; + case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; + case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + default: newpkt = 0; break; + } + } + else if( c->sigs_only ) { + switch( pkt->pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_USER_ID: + case PKT_SYMKEY_ENC: + case PKT_PUBKEY_ENC: + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: + write_status_text( STATUS_UNEXPECTED, "0" ); + rc = G10ERR_UNEXPECTED; + goto leave; + case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; + case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; + case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; + case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; + default: newpkt = 0; break; + } + } + else if( c->encrypt_only ) { + switch( pkt->pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_USER_ID: + write_status_text( STATUS_UNEXPECTED, "0" ); + rc = G10ERR_UNEXPECTED; + goto leave; + case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; + case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; + case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; + case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; + case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; + case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; + default: newpkt = 0; break; + } + } + else { + switch( pkt->pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + release_list( c ); + c->list = new_kbnode( pkt ); + newpkt = 1; + break; + case PKT_PUBLIC_SUBKEY: + case PKT_SECRET_SUBKEY: + newpkt = add_subkey( c, pkt ); + break; + case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break; + case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; + case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break; + case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break; + case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; + case PKT_COMPRESSED: proc_compressed( c, pkt ); break; + case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break; + case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; + case PKT_RING_TRUST: newpkt = add_ring_trust( c, pkt ); break; + default: newpkt = 0; break; + } + } + /* This is a very ugly construct and frankly, I don't remember why + * I used it. Adding the MDC check here is a hack. + * The right solution is to initiate another context for encrypted + * packet and not to reuse the current one ... It works right + * when there is a compression packet inbetween which adds just + * an extra layer. + * Hmmm: Rewrite this whole module here?? + */ + if( pkt->pkttype != PKT_SIGNATURE && pkt->pkttype != PKT_MDC ) + c->have_data = pkt->pkttype == PKT_PLAINTEXT; + + if( newpkt == -1 ) + ; + else if( newpkt ) { + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + } + else + free_packet(pkt); + if ( c->pipemode.stop_now ) { + /* we won't get an EOF in pipemode, so we have to + * break the loop here */ + rc = -1; + break; + } + } + if( rc == G10ERR_INVALID_PACKET ) + write_status_text( STATUS_NODATA, "3" ); + if( any_data ) + rc = 0; + else if( rc == -1 ) + write_status_text( STATUS_NODATA, "2" ); + + + leave: + release_list( c ); + m_free(c->dek); + free_packet( pkt ); + m_free( pkt ); + free_md_filter_context( &c->mfx ); + return rc; +} + + +static int +check_sig_and_print( CTX c, KBNODE node ) +{ + PKT_signature *sig = node->pkt->pkt.signature; + const char *astr, *tstr; + int rc, is_expkey=0; + + if( opt.skip_verify ) { + log_info(_("signature verification suppressed\n")); + return 0; + } + + /* It is not in all cases possible to check multiple signatures: + * PGP 2 (which is also allowed by OpenPGP), does use the packet + * sequence: sig+data, OpenPGP does use onepas+data=sig and GnuPG + * sometimes uses (because I did'nt read the specs right) data+sig. + * Because it is possible to create multiple signatures with + * different packet sequence (e.g. data+sig and sig+data) it might + * not be possible to get it right: let's say we have: + * data+sig, sig+data,sig+data and we have not yet encountered the last + * data, we could also see this a one data with 2 signatures and then + * data+sig. + * To protect against this we check that all signatures follow + * without any intermediate packets. Note, that we won't get this + * error when we use onepass packets or cleartext signatures because + * we reset the list every time + * + * FIXME: Now that we have these marker packets, we should create a + * real grammar and check against this. + */ + { + KBNODE n; + int n_sig=0; + + for (n=c->list; n; n=n->next ) { + if ( n->pkt->pkttype == PKT_SIGNATURE ) + n_sig++; + } + if (n_sig > 1) { /* more than one signature - check sequence */ + int tmp, onepass; + + for (tmp=onepass=0,n=c->list; n; n=n->next ) { + if (n->pkt->pkttype == PKT_ONEPASS_SIG) + onepass++; + else if (n->pkt->pkttype == PKT_GPG_CONTROL + && n->pkt->pkt.gpg_control->control + == CTRLPKT_CLEARSIGN_START ) { + onepass++; /* handle the same way as a onepass */ + } + else if ( (tmp && n->pkt->pkttype != PKT_SIGNATURE) ) { + log_error(_("can't handle these multiple signatures\n")); + return 0; + } + else if ( n->pkt->pkttype == PKT_SIGNATURE ) + tmp = 1; + else if (!tmp && !onepass + && n->pkt->pkttype == PKT_GPG_CONTROL + && n->pkt->pkt.gpg_control->control + == CTRLPKT_PLAINTEXT_MARK ) { + /* plaintext before signatures but no one-pass packets*/ + log_error(_("can't handle these multiple signatures\n")); + return 0; + } + } + } + } + + tstr = asctimestamp(sig->timestamp); + astr = pubkey_algo_to_string( sig->pubkey_algo ); + log_info(_("Signature made %.*s using %s key ID %08lX\n"), + (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); + + rc = do_check_sig(c, node, NULL, &is_expkey ); + if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { + if( keyserver_import_keyid ( sig->keyid )==0 ) + rc = do_check_sig(c, node, NULL, &is_expkey ); + } + if( !rc || rc == G10ERR_BAD_SIGN ) { + KBNODE un, keyblock; + int count=0, statno; + char keyid_str[50]; + + if(rc) + statno=STATUS_BADSIG; + else if(sig->flags.expired) + statno=STATUS_EXPSIG; + else if(is_expkey) + statno=STATUS_EXPKEYSIG; + else + statno=STATUS_GOODSIG; + + keyblock = get_pubkeyblock( sig->keyid ); + + sprintf (keyid_str, "%08lX%08lX [uncertain] ", + (ulong)sig->keyid[0], (ulong)sig->keyid[1]); + + /* find and print the primary user ID */ + for( un=keyblock; un; un = un->next ) { + if( un->pkt->pkttype != PKT_USER_ID ) + continue; + if ( !un->pkt->pkt.user_id->created ) + continue; + if ( un->pkt->pkt.user_id->is_revoked ) + continue; + if ( un->pkt->pkt.user_id->is_expired ) + continue; + if ( !un->pkt->pkt.user_id->is_primary ) + continue; + /* We want the textual user ID here */ + if ( un->pkt->pkt.user_id->attrib_data ) + continue; + + keyid_str[17] = 0; /* cut off the "[uncertain]" part */ + write_status_text_and_buffer (statno, keyid_str, + un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len, + -1 ); + + log_info(rc? _("BAD signature from \"") + : sig->flags.expired ? _("Expired signature from \"") + : _("Good signature from \"")); + print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len ); + fputs("\"\n", log_stream() ); + count++; + } + if( !count ) { /* just in case that we have no valid textual + userid */ + /* Try for an invalid textual userid */ + for( un=keyblock; un; un = un->next ) { + if( un->pkt->pkttype == PKT_USER_ID && + !un->pkt->pkt.user_id->attrib_data ) + break; + } + + /* Try for any userid at all */ + if(!un) { + for( un=keyblock; un; un = un->next ) { + if( un->pkt->pkttype == PKT_USER_ID ) + break; + } + } + + if (opt.trust_model==TM_ALWAYS || !un) + keyid_str[17] = 0; /* cut off the "[uncertain]" part */ + + write_status_text_and_buffer (statno, keyid_str, + un? un->pkt->pkt.user_id->name:"[?]", + un? un->pkt->pkt.user_id->len:3, + -1 ); + + log_info(rc? _("BAD signature from \"") + : sig->flags.expired ? _("Expired signature from \"") + : _("Good signature from \"")); + if (opt.trust_model!=TM_ALWAYS && un) { + fputs(_("[uncertain]"), log_stream() ); + putc(' ', log_stream() ); + } + print_utf8_string( log_stream(), + un? un->pkt->pkt.user_id->name:"[?]", + un? un->pkt->pkt.user_id->len:3 ); + fputs("\"\n", log_stream() ); + } + + /* If we have a good signature and already printed + * the primary user ID, print all the other user IDs */ + if ( count && !rc ) { + PKT_public_key *pk=NULL; + for( un=keyblock; un; un = un->next ) { + if(un->pkt->pkttype==PKT_PUBLIC_KEY) + pk=un->pkt->pkt.public_key; + if( un->pkt->pkttype != PKT_USER_ID ) + continue; + if ( un->pkt->pkt.user_id->is_revoked ) + continue; + if ( un->pkt->pkt.user_id->is_expired ) + continue; + /* Only skip textual primaries */ + if ( un->pkt->pkt.user_id->is_primary && + !un->pkt->pkt.user_id->attrib_data ) + continue; + + if(un->pkt->pkt.user_id->attrib_data) + { + dump_attribs(un->pkt->pkt.user_id,pk,NULL); + + if(opt.verify_options&VERIFY_SHOW_PHOTOS) + show_photos(un->pkt->pkt.user_id->attribs, + un->pkt->pkt.user_id->numattribs,pk,NULL); + } + + log_info( _(" aka \"")); + print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len ); + fputs("\"\n", log_stream() ); + } + } + release_kbnode( keyblock ); + + if( !rc ) + { + show_notation(sig,0,1); + show_policy_url(sig,0,1); + } + + if( !rc && is_status_enabled() ) { + /* print a status response with the fingerprint */ + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + + if( !get_pubkey( pk, sig->keyid ) ) { + byte array[MAX_FINGERPRINT_LEN], *p; + char buf[MAX_FINGERPRINT_LEN*4+90], *bufp; + size_t i, n; + + bufp = buf; + fingerprint_from_pk( pk, array, &n ); + p = array; + for(i=0; i < n ; i++, p++, bufp += 2) + sprintf(bufp, "%02X", *p ); + /* TODO: Replace the reserved '0' in the field below + with bits for status flags (policy url, notation, + etc.). Remember to make the buffer larger to + match! */ + sprintf(bufp, " %s %lu %lu %d 0 %d %d %02X ", + strtimestamp( sig->timestamp ), + (ulong)sig->timestamp,(ulong)sig->expiredate, + sig->version,sig->pubkey_algo,sig->digest_algo, + sig->sig_class); + bufp = bufp + strlen (bufp); + if (!pk->is_primary) { + u32 akid[2]; + + akid[0] = pk->main_keyid[0]; + akid[1] = pk->main_keyid[1]; + free_public_key (pk); + pk = m_alloc_clear( sizeof *pk ); + if (get_pubkey (pk, akid)) { + /* impossible error, we simply return a zeroed out fpr */ + n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; + memset (array, 0, n); + } + else + fingerprint_from_pk( pk, array, &n ); + } + p = array; + for(i=0; i < n ; i++, p++, bufp += 2) + sprintf(bufp, "%02X", *p ); + write_status_text( STATUS_VALIDSIG, buf ); + } + free_public_key( pk ); + } + + if( !rc ) + rc = check_signatures_trust( sig ); + + if(sig->flags.expired) + { + log_info(_("Signature expired %s\n"), + asctimestamp(sig->expiredate)); + rc=G10ERR_GENERAL; /* need a better error here? */ + } + else if(sig->expiredate) + log_info(_("Signature expires %s\n"),asctimestamp(sig->expiredate)); + + if(opt.verbose) + log_info(_("%s signature, digest algorithm %s\n"), + sig->sig_class==0x00?_("binary"): + sig->sig_class==0x01?_("textmode"):_("unknown"), + digest_algo_to_string(sig->digest_algo)); + + if( rc ) + g10_errors_seen = 1; + if( opt.batch && rc ) + g10_exit(1); + } + else { + char buf[50]; + sprintf(buf, "%08lX%08lX %d %d %02x %lu %d", + (ulong)sig->keyid[0], (ulong)sig->keyid[1], + sig->pubkey_algo, sig->digest_algo, + sig->sig_class, (ulong)sig->timestamp, rc ); + write_status_text( STATUS_ERRSIG, buf ); + if( rc == G10ERR_NO_PUBKEY ) { + buf[16] = 0; + write_status_text( STATUS_NO_PUBKEY, buf ); + } + if( rc != G10ERR_NOT_PROCESSED ) + log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); + } + return rc; +} + + +/**************** + * Process the tree which starts at node + */ +static void +proc_tree( CTX c, KBNODE node ) +{ + KBNODE n1; + int rc; + + if( opt.list_packets || opt.list_only ) + return; + + /* we must skip our special plaintext marker packets here becuase + they may be the root packet. These packets are only used in + addionla checks and skipping them here doesn't matter */ + while ( node + && node->pkt->pkttype == PKT_GPG_CONTROL + && node->pkt->pkt.gpg_control->control + == CTRLPKT_PLAINTEXT_MARK ) { + node = node->next; + } + if (!node) + return; + + c->local_id = 0; + c->trustletter = ' '; + if( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + merge_keys_and_selfsig( node ); + list_node( c, node ); + } + else if( node->pkt->pkttype == PKT_SECRET_KEY ) { + merge_keys_and_selfsig( node ); + list_node( c, node ); + } + else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) { + /* check all signatures */ + if( !c->have_data ) { + free_md_filter_context( &c->mfx ); + /* prepare to create all requested message digests */ + c->mfx.md = md_open(0, 0); + + /* fixme: why looking for the signature packet and not 1passpacket*/ + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { + md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo); + } + /* ask for file and hash it */ + if( c->sigs_only ) { + rc = hash_datafiles( c->mfx.md, NULL, + c->signed_data, c->sigfilename, + n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); + } + else { + rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2, + iobuf_get_real_fname(c->iobuf), + n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); + } + if( rc ) { + log_error("can't hash datafile: %s\n", g10_errstr(rc)); + return; + } + } + else if ( c->signed_data ) { + log_error (_("not a detached signature\n") ); + return; + } + + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) + check_sig_and_print( c, n1 ); + } + else if( node->pkt->pkttype == PKT_GPG_CONTROL + && node->pkt->pkt.gpg_control->control + == CTRLPKT_CLEARSIGN_START ) { + /* clear text signed message */ + if( !c->have_data ) { + log_error("cleartext signature without data\n" ); + return; + } + else if ( c->signed_data ) { + log_error (_("not a detached signature\n") ); + return; + } + + for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) + check_sig_and_print( c, n1 ); + } + else if( node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + int multiple_ok=1; + + n1=find_next_kbnode(node, PKT_SIGNATURE); + if(n1) + { + byte class=sig->sig_class; + byte hash=sig->digest_algo; + + for(; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE))) + { + /* We can't currently handle multiple signatures of + different classes or digests (we'd pretty much have + to run a different hash context for each), but if + they are all the same, make an exception. */ + if(n1->pkt->pkt.signature->sig_class!=class + || n1->pkt->pkt.signature->digest_algo!=hash) + { + multiple_ok=0; + log_info(_("WARNING: multiple signatures detected. " + "Only the first will be checked.\n")); + break; + } + } + } + + if( sig->sig_class != 0x00 && sig->sig_class != 0x01 ) + log_info(_("standalone signature of class 0x%02x\n"), + sig->sig_class); + else if( !c->have_data ) { + /* detached signature */ + free_md_filter_context( &c->mfx ); + c->mfx.md = md_open(sig->digest_algo, 0); + if( !opt.pgp2_workarounds ) + ; + else if( sig->digest_algo == DIGEST_ALGO_MD5 + && is_RSA( sig->pubkey_algo ) ) { + /* enable a workaround for a pgp2 bug */ + c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0 ); + } + else if( sig->digest_algo == DIGEST_ALGO_SHA1 + && sig->pubkey_algo == PUBKEY_ALGO_DSA + && sig->sig_class == 0x01 ) { + /* enable the workaround also for pgp5 when the detached + * signature has been created in textmode */ + c->mfx.md2 = md_open( sig->digest_algo, 0 ); + } +#if 0 /* workaround disabled */ + /* Here we have another hack to work around a pgp 2 bug + * It works by not using the textmode for detached signatures; + * this will let the first signature check (on md) fail + * but the second one (on md2) which adds an extra CR should + * then produce the "correct" hash. This is very, very ugly + * hack but it may help in some cases (and break others) + */ + /* c->mfx.md2? 0 :(sig->sig_class == 0x01) */ +#endif + if ( DBG_HASHING ) { + md_start_debug( c->mfx.md, "verify" ); + if ( c->mfx.md2 ) + md_start_debug( c->mfx.md2, "verify2" ); + } + if( c->sigs_only ) { + rc = hash_datafiles( c->mfx.md, c->mfx.md2, + c->signed_data, c->sigfilename, + (sig->sig_class == 0x01) ); + } + else { + rc = ask_for_detached_datafile( c->mfx.md, c->mfx.md2, + iobuf_get_real_fname(c->iobuf), + (sig->sig_class == 0x01) ); + } + if( rc ) { + log_error("can't hash datafile: %s\n", g10_errstr(rc)); + return; + } + } + else if ( c->signed_data ) { + log_error (_("not a detached signature\n") ); + return; + } + else if ( c->pipemode.op == 'B' ) + ; /* this is a detached signature trough the pipemode handler */ + else if (!opt.quiet) + log_info(_("old style (PGP 2.x) signature\n")); + + if(multiple_ok) + for( n1 = node; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )) ) + check_sig_and_print( c, n1 ); + else + check_sig_and_print( c, node ); + } + else { + dump_kbnode (c->list); + log_error(_("invalid root packet detected in proc_tree()\n")); + dump_kbnode (node); + } +} diff --git a/g10/misc.c b/g10/misc.c new file mode 100644 index 000000000..1b8e6172a --- /dev/null +++ b/g10/misc.c @@ -0,0 +1,678 @@ +/* misc.c - miscellaneous functions + * 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 <unistd.h> +#include <errno.h> +#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 "main.h" +#include "photoid.h" +#include "options.h" +#include "i18n.h" + + +const char *g10m_revision_string(int); +const char *g10c_revision_string(int); +const char *g10u_revision_string(int); + +#ifdef __GNUC__ +volatile +#endif + void +pull_in_libs(void) +{ + g10m_revision_string(0); + g10c_revision_string(0); + g10u_revision_string(0); +} + + +#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 +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() +{ +#ifdef HAVE_DOSISH_SYSTEM + return 0; +#else +#ifdef HAVE_SETRLIMIT + struct rlimit limit; + + limit.rlim_cur = 0; + limit.rlim_max = 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 +} + + + +u16 +checksum_u16( unsigned n ) +{ + u16 a; + + a = (n >> 8) & 0xff; + a += n & 0xff; + return a; +} + + +u16 +checksum( byte *p, unsigned n ) +{ + u16 a; + + for(a=0; n; n-- ) + a += *p++; + return a; +} + +u16 +checksum_mpi( MPI a ) +{ + u16 csum; + byte *buffer; + unsigned nbytes; + unsigned nbits; + + buffer = mpi_get_buffer( a, &nbytes, NULL ); + nbits = mpi_get_nbits(a); + csum = checksum_u16( nbits ); + csum += checksum( buffer, nbytes ); + m_free( buffer ); + return csum; +} + +u32 +buffer_to_u32( const byte *buffer ) +{ + unsigned long a; + a = *buffer << 24; + a |= buffer[1] << 16; + a |= buffer[2] << 8; + a |= buffer[3]; + return a; +} + + +static void +no_exp_algo(void) +{ + static int did_note = 0; + + if( !did_note ) { + did_note = 1; + log_info(_("Experimental algorithms should not be used!\n")); + } +} + +void +print_pubkey_algo_note( int algo ) +{ + if( algo >= 100 && algo <= 110 ) + no_exp_algo(); +} + +void +print_cipher_algo_note( int algo ) +{ + if( algo >= 100 && algo <= 110 ) + no_exp_algo(); + else if( algo == CIPHER_ALGO_3DES + || algo == CIPHER_ALGO_CAST5 + || algo == CIPHER_ALGO_BLOWFISH + || algo == CIPHER_ALGO_TWOFISH + || algo == CIPHER_ALGO_RIJNDAEL + || algo == CIPHER_ALGO_RIJNDAEL192 + || algo == CIPHER_ALGO_RIJNDAEL256 + ) + ; + else { + static int did_note = 0; + + if( !did_note ) { + did_note = 1; + log_info(_("this cipher algorithm is deprecated; " + "please use a more standard one!\n")); + } + } +} + +void +print_digest_algo_note( int algo ) +{ + if( algo >= 100 && algo <= 110 ) + no_exp_algo(); +} + + +/* 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; +} + +/**************** + * Wrapper around the libgcrypt function with addional checks on + * openPGP contraints for the algo ID. + */ +int +openpgp_cipher_test_algo( int algo ) +{ + if( algo < 0 || algo > 110 ) + return G10ERR_CIPHER_ALGO; + return check_cipher_algo(algo); +} + +int +openpgp_pk_test_algo( int algo, unsigned int usage_flags ) +{ + if( algo < 0 || algo > 110 ) + return G10ERR_PUBKEY_ALGO; + return check_pubkey_algo2( algo, usage_flags ); +} + +int +openpgp_pk_algo_usage ( int algo ) +{ + int use = 0; + + /* they are hardwired in gpg 1.0 */ + switch ( algo ) { + case PUBKEY_ALGO_RSA: + use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; + break; + case PUBKEY_ALGO_RSA_E: + use = PUBKEY_USAGE_ENC; + break; + case PUBKEY_ALGO_RSA_S: + use = PUBKEY_USAGE_SIG; + break; + case PUBKEY_ALGO_ELGAMAL_E: + use = PUBKEY_USAGE_ENC; + break; + case PUBKEY_ALGO_DSA: + use = PUBKEY_USAGE_SIG; + break; + case PUBKEY_ALGO_ELGAMAL: + use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; + break; + default: + break; + } + return use; +} + +int +openpgp_md_test_algo( int algo ) +{ + if( algo < 0 || algo > 110 ) + return G10ERR_DIGEST_ALGO; + return check_digest_algo(algo); +} + +#ifdef USE_IDEA +/* Special warning for the IDEA cipher */ +void +idea_cipher_warn(int show) +{ + static int warned=0; + + if(!warned || show) + { + log_info(_("the IDEA cipher plugin is not present\n")); + log_info(_("please see http://www.gnupg.org/why-not-idea.html " + "for more information\n")); + warned=1; + } +} +#endif + +/* Expand %-strings. Returns a string which must be m_freed. Returns + NULL if the string cannot be expanded (too large). */ +char * +pct_expando(const char *string,struct expando_args *args) +{ + const char *ch=string; + int idx=0,maxlen=0,done=0; + u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0}; + char *ret=NULL; + + if(args->pk) + keyid_from_pk(args->pk,pk_keyid); + + if(args->sk) + keyid_from_sk(args->sk,sk_keyid); + + if(!args->pk && args->sk) + keyid_from_sk(args->sk,pk_keyid); + + while(*ch!='\0') + { + char *str=NULL; + + if(!done) + { + /* 8192 is way bigger than we'll need here */ + if(maxlen>=8192) + goto fail; + + maxlen+=1024; + ret=m_realloc(ret,maxlen); + } + + done=0; + + if(*ch=='%') + { + switch(*(ch+1)) + { + case 's': /* short key id */ + if(idx+8<maxlen) + { + sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]); + idx+=8; + done=1; + } + break; + + case 'S': /* long key id */ + if(idx+16<maxlen) + { + sprintf(&ret[idx],"%08lX%08lX", + (ulong)sk_keyid[0],(ulong)sk_keyid[1]); + idx+=16; + done=1; + } + break; + + case 'k': /* short key id */ + if(idx+8<maxlen) + { + sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]); + idx+=8; + done=1; + } + break; + + case 'K': /* long key id */ + if(idx+16<maxlen) + { + sprintf(&ret[idx],"%08lX%08lX", + (ulong)pk_keyid[0],(ulong)pk_keyid[1]); + idx+=16; + done=1; + } + break; + + case 'f': /* fingerprint */ + { + byte array[MAX_FINGERPRINT_LEN]; + size_t len; + int i; + + if(args->pk) + fingerprint_from_pk(args->pk,array,&len); + else + memset(array,0, (len=MAX_FINGERPRINT_LEN)); + + if(idx+(len*2)<maxlen) + { + for(i=0;i<len;i++) + { + sprintf(&ret[idx],"%02X",array[i]); + idx+=2; + } + done=1; + } + } + break; + + case 't': /* e.g. "jpg" */ + str=image_type_to_string(args->imagetype,0); + /* fall through */ + + case 'T': /* e.g. "image/jpeg" */ + if(str==NULL) + str=image_type_to_string(args->imagetype,2); + + if(idx+strlen(str)<maxlen) + { + strcpy(&ret[idx],str); + idx+=strlen(str); + done=1; + } + break; + + case '%': + if(idx+1<maxlen) + { + ret[idx++]='%'; + ret[idx]='\0'; + done=1; + } + break; + + /* Any unknown %-keys (like %i, %o, %I, and %O) are + passed through for later expansion. Note this also + handles the case where the last character in the + string is a '%' - the terminating \0 will end up here + and properly terminate the string. */ + default: + if(idx+2<maxlen) + { + ret[idx++]='%'; + ret[idx++]=*(ch+1); + ret[idx]='\0'; + done=1; + } + break; + } + + if(done) + ch++; + } + else + { + if(idx+1<maxlen) + { + ret[idx++]=*ch; + ret[idx]='\0'; + done=1; + } + } + + if(done) + ch++; + } + + return ret; + + fail: + m_free(ret); + return NULL; +} + +int +hextobyte( const char *s ) +{ + int c; + + if( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if( *s >= 'a' && *s <= 'f' ) + c = 16 * (10 + *s - 'a'); + else + return -1; + s++; + if( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if( *s >= 'a' && *s <= 'f' ) + c += 10 + *s - 'a'; + else + return -1; + return c; +} + +void +deprecated_warning(const char *configname,unsigned int configlineno, + const char *option,const char *repl1,const char *repl2) +{ + if(configname) + { + if(strncmp("--",option,2)==0) + option+=2; + + if(strncmp("--",repl1,2)==0) + repl1+=2; + + log_info(_("%s:%d: deprecated option \"%s\"\n"), + configname,configlineno,option); + } + else + log_info(_("WARNING: \"%s\" is a deprecated option\n"),option); + + log_info(_("please use \"%s%s\" instead\n"),repl1,repl2); +} + +const char * +compress_algo_to_string(int algo) +{ + const char *s="?"; + + switch(algo) + { + case 0: + s="Uncompressed"; + break; + + case 1: + s="ZIP"; + break; + + case 2: + s="ZLIB"; + break; + } + + return s; +} + +int +string_to_compress_algo(const char *string) +{ + if(ascii_strcasecmp(string,"uncompressed")==0) + return 0; + else if(ascii_strcasecmp(string,"zip")==0) + return 1; + else if(ascii_strcasecmp(string,"zlib")==0) + return 2; + else if(ascii_strcasecmp(string,"z0")==0) + return 0; + else if(ascii_strcasecmp(string,"z1")==0) + return 1; + else if(ascii_strcasecmp(string,"z2")==0) + return 2; + else + return -1; +} + +int +check_compress_algo(int algo) +{ + if(algo>=0 && algo<=2) + return 0; + + return G10ERR_COMPR_ALGO; +} + +int +default_cipher_algo(void) +{ + if(opt.def_cipher_algo) + return opt.def_cipher_algo; + else if(opt.personal_cipher_prefs) + return opt.personal_cipher_prefs[0].value; + else + return opt.s2k_cipher_algo; +} + +/* There is no default_digest_algo function, but see + sign.c:hash_for */ + +int +default_compress_algo(void) +{ + if(opt.def_compress_algo!=-1) + return opt.def_compress_algo; + else if(opt.personal_compress_prefs) + return opt.personal_compress_prefs[0].value; + else + return DEFAULT_COMPRESS_ALGO; +} + +const char * +compliance_option_string(void) +{ + switch(opt.compliance) + { + case CO_RFC2440: + return "--openpgp"; + case CO_PGP2: + return "--pgp2"; + case CO_PGP6: + return "--pgp6"; + case CO_PGP7: + return "--pgp7"; + case CO_PGP8: + return "--pgp8"; + default: + return "???"; + } +} + +static const char * +compliance_string(void) +{ + switch(opt.compliance) + { + case CO_RFC2440: + return "OpenPGP"; + case CO_PGP2: + return "PGP 2.x"; + case CO_PGP6: + return "PGP 6.x"; + case CO_PGP7: + return "PGP 7.x"; + case CO_PGP8: + return "PGP 8.x"; + default: + return "???"; + } +} + +void +compliance_failure(void) +{ + log_info(_("this message may not be usable by %s\n"),compliance_string()); + opt.compliance=CO_GNUPG; +} + +int +parse_options(char *str,unsigned int *options,struct parse_options *opts) +{ + char *tok; + + while((tok=strsep(&str," ,"))) + { + int i,rev=0; + + if(tok[0]=='\0') + continue; + + if(ascii_strncasecmp("no-",tok,3)==0) + { + rev=1; + tok+=3; + } + + for(i=0;opts[i].name;i++) + { + if(ascii_strcasecmp(opts[i].name,tok)==0) + { + if(rev) + *options&=~opts[i].bit; + else + *options|=opts[i].bit; + break; + } + } + + if(!opts[i].name) + return 0; + } + + return 1; +} diff --git a/g10/openfile.c b/g10/openfile.c new file mode 100644 index 000000000..6f4541e80 --- /dev/null +++ b/g10/openfile.c @@ -0,0 +1,389 @@ +/* openfile.c + * 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 <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include "util.h" +#include "memory.h" +#include "ttyio.h" +#include "options.h" +#include "main.h" +#include "status.h" +#include "i18n.h" + +#ifdef USE_ONLY_8DOT3 +#define SKELEXT ".skl" +#else +#define SKELEXT EXTSEP_S "skel" +#endif + +#if defined (HAVE_DRIVE_LETTERS) || defined (__riscos__) +#define CMP_FILENAME(a,b) ascii_strcasecmp( (a), (b) ) +#else +#define CMP_FILENAME(a,b) strcmp( (a), (b) ) +#endif + +#ifdef MKDIR_TAKES_ONE_ARG +#undef mkdir +#define mkdir(a,b) mkdir(a) +#endif + +/* FIXME: Implement opt.interactive. */ + +/**************** + * Check whether FNAME exists and ask if it's okay to overwrite an + * existing one. + * Returns: True: it's okay to overwrite or the file does not exist + * False: Do not overwrite + */ +int +overwrite_filep( const char *fname ) +{ + if( !fname || (*fname == '-' && !fname[1]) ) + return 1; /* writing to stdout is always okay */ + + if( access( fname, F_OK ) ) + return 1; /* does not exist */ + +#ifndef HAVE_DOSISH_SYSTEM + if ( !strcmp ( fname, "/dev/null" ) ) + return 1; /* does not do any harm */ +#endif + + /* fixme: add some backup stuff in case of overwrite */ + if( opt.answer_yes ) + return 1; + if( opt.answer_no || opt.batch ) + return 0; /* do not overwrite */ + + tty_printf(_("File `%s' exists. "), fname); + if( cpr_get_answer_is_yes("openfile.overwrite.okay", + _("Overwrite (y/N)? ")) ) + return 1; + return 0; +} + + +/**************** + * Strip know extensions from iname and return a newly allocated + * filename. Return NULL if we can't do that. + */ +char * +make_outfile_name( const char *iname ) +{ + size_t n; + + if( (!iname || (*iname=='-' && !iname[1]) )) + return m_strdup("-"); + + n = strlen(iname); + if( n > 4 && ( !CMP_FILENAME(iname+n-4, EXTSEP_S "gpg") + || !CMP_FILENAME(iname+n-4, EXTSEP_S "pgp") + || !CMP_FILENAME(iname+n-4, EXTSEP_S "sig") + || !CMP_FILENAME(iname+n-4, EXTSEP_S "asc") ) ) { + char *buf = m_strdup( iname ); + buf[n-4] = 0; + return buf; + } + else if( n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign") ) { + char *buf = m_strdup( iname ); + buf[n-5] = 0; + return buf; + } + + log_info(_("%s: unknown suffix\n"), iname ); + return NULL; +} + + +/**************** + * Ask for a outputfilename and use the given one as default. + * Return NULL if no file has been given or it is not possible to + * ask the user. + */ +char * +ask_outfile_name( const char *name, size_t namelen ) +{ + size_t n; + const char *s; + char *prompt; + char *fname; + char *defname; + + if( opt.batch ) + return NULL; + + s = _("Enter new filename"); + + n = strlen(s) + namelen + 10; + defname = name && namelen? make_printable_string( name, namelen, 0): NULL; + prompt = m_alloc(n); + if( defname ) + sprintf(prompt, "%s [%s]: ", s, defname ); + else + sprintf(prompt, "%s: ", s ); + fname = cpr_get("openfile.askoutname", prompt ); + cpr_kill_prompt(); + m_free(prompt); + if( !*fname ) { + m_free( fname ); fname = NULL; + fname = defname; defname = NULL; + } + m_free(defname); + if (fname) + trim_spaces (fname); + return fname; +} + + +/**************** + * Make an output filename for the inputfile INAME. + * Returns an IOBUF and an errorcode + * Mode 0 = use ".gpg" + * 1 = use ".asc" + * 2 = use ".sig" + */ +int +open_outfile( const char *iname, int mode, IOBUF *a ) +{ + int rc = 0; + + *a = NULL; + if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) { + if( !(*a = iobuf_create(NULL)) ) { + log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) ); + rc = G10ERR_CREATE_FILE; + } + else if( opt.verbose ) + log_info(_("writing to stdout\n")); + } + else { + char *buf = NULL; + const char *name; + + if( opt.dry_run ) + name = "/dev/null"; + else if( opt.outfile ) + name = opt.outfile; + else { +#ifdef USE_ONLY_8DOT3 + if (opt.mangle_dos_filenames) + { + /* It is quite common DOS system to have only one dot in a + * a filename So if we have something like this, we simple + * replace the suffix execpt in cases where the suffix is + * larger than 3 characters and not the same as. + * We should really map the filenames to 8.3 but this tends to + * be more complicated and is probaly a duty of the filesystem + */ + char *dot; + const char *newsfx = mode==1 ? ".asc" : + mode==2 ? ".sig" : ".gpg"; + + buf = m_alloc(strlen(iname)+4+1); + strcpy(buf,iname); + dot = strchr(buf, '.' ); + if ( dot && dot > buf && dot[1] && strlen(dot) <= 4 + && CMP_FILENAME(newsfx, dot) ) + { + strcpy(dot, newsfx ); + } + else if ( dot && !dot[1] ) /* don't duplicate a dot */ + strcpy( dot, newsfx+1 ); + else + strcat ( buf, newsfx ); + } + if (!buf) +#endif /* USE_ONLY_8DOT3 */ + { + buf = m_alloc(strlen(iname)+4+1); + strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" : + mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"); + } + name = buf; + } + + rc = 0; + while( !overwrite_filep (name) ) + { + char *tmp = ask_outfile_name (NULL, 0); + if ( !tmp || !*tmp ) + { + m_free (tmp); + rc = G10ERR_FILE_EXISTS; + break; + } + m_free (buf); + name = buf = tmp; + } + + if( !rc ) + { + if( !(*a = iobuf_create( name )) ) + { + log_error(_("%s: can't create: %s\n"), name, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + } + else if( opt.verbose ) + log_info(_("writing to `%s'\n"), name ); + } + m_free(buf); + } + + return rc; +} + + +/**************** + * Try to open a file without the extension ".sig" or ".asc" + * Return NULL if such a file is not available. + */ +IOBUF +open_sigfile( const char *iname, progress_filter_context_t *pfx ) +{ + IOBUF a = NULL; + size_t len; + + if( iname && !(*iname == '-' && !iname[1]) ) { + len = strlen(iname); + if( len > 4 && ( !strcmp(iname + len - 4, EXTSEP_S "sig") + || ( len > 5 && !strcmp(iname + len - 5, EXTSEP_S "sign") ) + || !strcmp(iname + len - 4, EXTSEP_S "asc")) ) { + char *buf; + buf = m_strdup(iname); + buf[len-(buf[len-1]=='n'?5:4)] = 0 ; + a = iobuf_open( buf ); + if( a && opt.verbose ) + log_info(_("assuming signed data in `%s'\n"), buf ); + if (a && pfx) + handle_progress (pfx, a, buf); + m_free(buf); + } + } + return a; +} + +/**************** + * Copy the option file skeleton to the given directory. + */ +static void +copy_options_file( const char *destdir ) +{ + const char *datadir = GNUPG_DATADIR; + char *fname; + FILE *src, *dst; + int linefeeds=0; + int c; + mode_t oldmask; + int esc = 0; + int any_option = 0; + + if( opt.dry_run ) + return; + + fname = m_alloc( strlen(datadir) + strlen(destdir) + 15 ); + strcpy(stpcpy(fname, datadir), DIRSEP_S "options" SKELEXT ); + src = fopen( fname, "r" ); + if( !src ) { + log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); + m_free(fname); + return; + } + strcpy(stpcpy(fname, destdir), DIRSEP_S "gpg" EXTSEP_S "conf" ); + oldmask=umask(077); + dst = fopen( fname, "w" ); + umask(oldmask); + if( !dst ) { + log_error(_("%s: can't create: %s\n"), fname, strerror(errno) ); + fclose( src ); + m_free(fname); + return; + } + + while( (c=getc(src)) != EOF ) { + if( linefeeds < 3 ) { + if( c == '\n' ) + linefeeds++; + } + else { + putc( c, dst ); + if (c== '\n') + esc = 1; + else if (esc == 1) { + if (c == ' ' || c == '\t') + ; + else if (c == '#') + esc = 2; + else + any_option = 1; + } + } + } + fclose( dst ); + fclose( src ); + log_info(_("new configuration file `%s' created\n"), fname ); + if (any_option) + log_info (_("WARNING: options in `%s'" + " are not yet active during this run\n"), + fname); + m_free(fname); +} + + +void +try_make_homedir( const char *fname ) +{ + const char *defhome = GNUPG_HOMEDIR; + + /* Create the directory only if the supplied directory name + * is the same as the default one. This way we avoid to create + * arbitrary directories when a non-default homedirectory is used. + * To cope with HOME, we do compare only the suffix if we see that + * the default homedir does start with a tilde. + */ + if( opt.dry_run || opt.no_homedir_creation ) + return; + + if ( ( *defhome == '~' + && ( strlen(fname) >= strlen (defhome+1) + && !strcmp(fname+strlen(fname)-strlen(defhome+1), + defhome+1 ) )) + || ( *defhome != '~' + && !compare_filenames( fname, defhome ) ) + ) { + if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) ) + log_fatal( _("%s: can't create directory: %s\n"), + fname, strerror(errno) ); + else if( !opt.quiet ) + log_info( _("%s: directory created\n"), fname ); + copy_options_file( fname ); +/* log_info(_("you have to start GnuPG again, " */ +/* "so it can read the new configuration file\n") ); */ +/* g10_exit(1); */ + } +} diff --git a/g10/options.h b/g10/options.h new file mode 100644 index 000000000..1a70277dc --- /dev/null +++ b/g10/options.h @@ -0,0 +1,241 @@ +/* options.h + * 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 + */ +#ifndef G10_OPTIONS_H +#define G10_OPTIONS_H + +#include <types.h> +#include "main.h" +#include "packet.h" + +#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */ + +#ifndef EXTERN_UNLESS_MAIN_MODULE +/* Norcraft can't cope with common symbols */ +#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 +struct { + int verbose; + int quiet; + unsigned debug; + int armor; + int compress; + char *outfile; + int dry_run; + int list_only; + int textmode; + int expert; + int ask_sig_expire; + int ask_cert_expire; + int batch; /* run in batch mode */ + int answer_yes; /* answer yes on most questions */ + int answer_no; /* answer no on most questions */ + int check_sigs; /* check key signatures */ + int with_colons; + int with_key_data; + int with_fingerprint; /* opt --with-fingerprint active */ + int fingerprint; /* list fingerprints */ + int list_sigs; /* list signatures */ + int no_armor; + int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/ + int def_cipher_algo; + int force_v3_sigs; + int force_v4_certs; + int force_mdc; + int disable_mdc; + int def_digest_algo; + int cert_digest_algo; + int def_compress_algo; + const char *def_secret_key; + char *def_recipient; + int def_recipient_self; + int def_cert_check_level; + int sk_comments; + int no_version; + int marginals_needed; + int completes_needed; + int max_cert_depth; + const char *homedir; + + char *display; /* 5 options to be passed to the gpg-agent */ + char *ttyname; + char *ttytype; + char *lc_ctype; + char *lc_messages; + + int skip_verify; + int compress_keys; + int compress_sigs; + /* TM_CLASSIC must be zero to accomodate trustdbs generated before + we started storing the trust model inside the trustdb. */ + enum {TM_CLASSIC=0, TM_PGP=1, TM_ALWAYS, TM_AUTO} trust_model; + unsigned int force_ownertrust; + enum + { + CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8 + } compliance; + int pgp2_workarounds; + unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ + int shm_coprocess; + const char *set_filename; + const char *comment_string; + int throw_keyid; + const char *photo_viewer; + int s2k_mode; + int s2k_digest_algo; + int s2k_cipher_algo; + int simple_sk_checksum; /* create the deprecated rfc2440 secret + key protection*/ + int not_dash_escaped; + int escape_from; + int lock_once; + char *keyserver_uri; + char *keyserver_scheme; + char *keyserver_host; + char *keyserver_port; + char *keyserver_opaque; + struct + { + int verbose; + int include_revoked; + int include_disabled; + int include_subkeys; + int honor_http_proxy; + int broken_http_proxy; + int use_temp_files; + int keep_temp_files; + int fake_v3_keyids; + int auto_key_retrieve; + int try_dns_srv; + unsigned int import_options; + unsigned int export_options; + STRLIST other; + } keyserver_options; + int exec_disable; + int exec_path_set; + unsigned int import_options; + unsigned int export_options; + unsigned int list_options; + unsigned int verify_options; + char *def_preference_list; + prefitem_t *personal_cipher_prefs; + prefitem_t *personal_digest_prefs; + prefitem_t *personal_compress_prefs; + int no_perm_warn; + int no_mdc_warn; + char *temp_dir; + int no_encrypt_to; + int interactive; + STRLIST sig_notation_data; + STRLIST cert_notation_data; + STRLIST sig_policy_url; + STRLIST cert_policy_url; + int use_embedded_filename; + int allow_non_selfsigned_uid; + int allow_freeform_uid; + int no_literal; + ulong set_filesize; + int fast_list_mode; + int fixed_list_mode; + int ignore_time_conflict; + int ignore_valid_from; + int ignore_crc_error; + int ignore_mdc_error; + int command_fd; + const char *override_session_key; + int show_session_key; + int use_agent; + const char *gpg_agent_info; + int merge_only; + int try_all_secrets; + int no_expensive_trust_checks; + int no_sig_cache; + int no_sig_create_check; + int no_auto_check_trustdb; + int preserve_permissions; + int no_homedir_creation; + struct groupitem *grouplist; + int strict; + int mangle_dos_filenames; + int enable_progress_filter; +} opt; + + +#define EMUBUG_MDENCODE 4 + +#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ +#define DBG_MPI_VALUE 2 /* debug mpi details */ +#define DBG_CIPHER_VALUE 4 /* debug cipher handling */ + /* (may reveal sensitive data) */ +#define DBG_FILTER_VALUE 8 /* debug internal filter handling */ +#define DBG_IOBUF_VALUE 16 /* debug iobuf stuff */ +#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ +#define DBG_CACHE_VALUE 64 /* debug the cacheing */ +#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ +#define DBG_TRUST_VALUE 256 /* debug the trustdb */ +#define DBG_HASHING_VALUE 512 /* debug hashing operations */ +#define DBG_EXTPROG_VALUE 1024 /* debug external program calls */ + + +#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) +#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) +#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) +#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) +#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) +#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) + +#define GNUPG (opt.compliance==CO_GNUPG) +#define RFC1991 (opt.compliance==CO_RFC1991 || opt.compliance==CO_PGP2) +#define RFC2440 (opt.compliance==CO_RFC2440) +#define PGP2 (opt.compliance==CO_PGP2) +#define PGP6 (opt.compliance==CO_PGP6) +#define PGP7 (opt.compliance==CO_PGP7) +#define PGP8 (opt.compliance==CO_PGP8) + +/* Various option flags */ + +#define IMPORT_ALLOW_LOCAL_SIGS 1 +#define IMPORT_REPAIR_PKS_SUBKEY_BUG 2 +#define IMPORT_FAST_IMPORT 4 +#define IMPORT_SK2PK 8 + +#define EXPORT_INCLUDE_NON_RFC 1 +#define EXPORT_INCLUDE_LOCAL_SIGS 2 +#define EXPORT_INCLUDE_ATTRIBUTES 4 +#define EXPORT_INCLUDE_SENSITIVE_REVKEYS 8 + +#define LIST_SHOW_PHOTOS 1 +#define LIST_SHOW_POLICY 2 +#define LIST_SHOW_NOTATION 4 +#define LIST_SHOW_KEYRING 8 +#define LIST_SHOW_VALIDITY 16 +#define LIST_SHOW_LONG_KEYID 32 + +#define VERIFY_SHOW_PHOTOS 1 +#define VERIFY_SHOW_POLICY 2 +#define VERIFY_SHOW_NOTATION 4 + +#endif /*G10_OPTIONS_H*/ diff --git a/g10/options.skel b/g10/options.skel new file mode 100644 index 000000000..e50f66ffe --- /dev/null +++ b/g10/options.skel @@ -0,0 +1,208 @@ +# These first three lines are not copied to the gpg.conf file in +# the users home directory. +# $Id$ +# Options for GnuPG +# Copyright 1998, 1999, 2000, 2001, 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. +# +# Unless you specify which option file to use (with the command line +# option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf +# by default. +# +# An options file can contain any long options which are available in +# GnuPG. If the first non white space character of a line is a '#', +# this line is ignored. Empty lines are also ignored. +# +# See the man page for a list of options. + +# Uncomment the following option to get rid of the copyright notice + +#no-greeting + +# If you have more than 1 secret key in your keyring, you may want to +# uncomment the following option and set your preferred keyid. + +#default-key 621CC013 + +# If you do not pass a recipient to gpg, it will ask for one. Using +# this option you can encrypt to a default key. Key validation will +# not be done in this case. The second form uses the default key as +# default recipient. + +#default-recipient some-user-id +#default-recipient-self + +# By default GnuPG creates version 3 signatures for data files. This +# is not strictly OpenPGP compliant but PGP 6 and most versions of PGP +# 7 require them. To disable this behavior, you may use this option +# or --openpgp. + +#no-force-v3-sigs + +# Because some mailers change lines starting with "From " to ">From " +# it is good to handle such lines in a special way when creating +# cleartext signatures; all other PGP versions do it this way too. +# To enable full OpenPGP compliance you may want to use this option. + +#no-escape-from-lines + +# If you do not use the Latin-1 (ISO-8859-1) charset, you should tell +# GnuPG which is the native character set. Please check the man page +# for supported character sets. This character set is only used for +# metadata and not for the actual message which does not undergo any +# translation. Note that future version of GnuPG will change to UTF-8 +# as default character set. + +#charset utf-8 + +# Group names may be defined like this: +# group mynames = paige 0x12345678 joe patti +# +# Any time "mynames" is a recipient (-r or --recipient), it will be +# expanded to the names "paige", "joe", and "patti", and the key ID +# "0x12345678". Note there is only one level of expansion - you +# cannot make an group that points to another group. Note also that +# if there are spaces in the recipient name, this will appear as two +# recipients. In these cases it is better to use the key ID. + +#group mynames = paige 0x12345678 joe patti + +# Some old Windows platforms require 8.3 filenames. If your system +# can handle long filenames, uncomment this. + +#no-mangle-dos-filenames + +# Lock the file only once for the lifetime of a process. If you do +# not define this, the lock will be obtained and released every time +# it is needed - normally this is not needed. + +#lock-once + +# GnuPG can send and receive keys to and from a keyserver. These +# servers can be HKP, email, or LDAP (if GnuPG is built with LDAP +# support). +# +# Example HKP keyserver: +# x-hkp://pgp.mit.edu +# +# Example email keyserver: +# mailto:pgp-public-keys@keys.nl.pgp.net +# +# Example LDAP keyservers: +# ldap://pgp.surfnet.nl:11370 +# ldap://keyserver.pgp.com +# +# Regular URL syntax applies, and you can set an alternate port +# through the usual method: +# x-hkp://keyserver.example.net:22742 +# +# If you have problems connecting to a HKP server through a buggy http +# proxy, you can use keyserver option broken-http-proxy (see below), +# but first you should make sure that you have read the man page +# regarding proxies (keyserver option honor-http-proxy) +# +# Most users just set the name and type of their preferred keyserver. +# Most servers do synchronize with each other and DNS round-robin may +# give you a quasi-random server each time. + +#keyserver x-hkp://pgp.mit.edu +#keyserver mailto:pgp-public-keys@keys.nl.pgp.net +#keyserver ldap://pgp.surfnet.nl:11370 +#keyserver ldap://keyserver.pgp.com + +# Common options for keyserver functions: +# +# include-disabled = when searching, include keys marked as "disabled" +# on the keyserver (not all keyservers support this). +# +# no-include-revoked = when searching, do not include keys marked as +# "revoked" on the keyserver. +# +# verbose = show more information as the keys are fetched. +# Can be used more than once to increase the amount +# of information shown. +# +# use-temp-files = use temporary files instead of a pipe to talk to the +# keyserver. Some platforms (Win32 for one) always +# have this on. +# +# keep-temp-files = do not delete temporary files after using them +# (really only useful for debugging) +# +# honor-http-proxy = if the keyserver uses HTTP, honor the http_proxy +# environment variable +# +# broken-http-proxy = try to work around a buggy HTTP proxy +# +# auto-key-retrieve = automatically fetch keys as needed from the keyserver +# when verifying signatures or when importing keys that +# have been revoked by a revocation key that is not +# present on the keyring. +# +# no-include-attributes = do not include attribute IDs (aka "photo IDs") +# when sending keys to the keyserver. + +#keyserver-options auto-key-retrieve + +# Uncomment this line to display photo user IDs in key listings and +# when a signature from a key with a photo is verified. + +#show-photos + +# Use this program to display photo user IDs +# +# %i is expanded to a temporary file that contains the photo. +# %I is the same as %i, but the file isn't deleted afterwards by GnuPG. +# %k is expanded to the key ID of the key. +# %K is expanded to the long OpenPGP key ID of the key. +# %t is expanded to the extension of the image (e.g. "jpg"). +# %T is expanded to the MIME type of the image (e.g. "image/jpeg"). +# %f is expanded to the fingerprint of the key. +# %% is %, of course. +# +# If %i or %I are not present, then the photo is supplied to the +# viewer on standard input. If your platform supports it, standard +# input is the best way to do this as it avoids the time and effort in +# generating and then cleaning up a secure temp file. +# +# The default program is "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin" +# On Mac OS X and Windows, the default is to use your regular JPEG image +# viewer. +# +# Some other viewers: +# photo-viewer "qiv %i" +# photo-viewer "ee %i" +# photo-viewer "display -title 'KeyID 0x%k'" +# +# This one saves a copy of the photo ID in your home directory: +# photo-viewer "cat > ~/photoid-for-key-%k.%t" +# +# Use your MIME handler to view photos: +# photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG" + +# Passphrase agent +# +# We support the old experimental passphrase agent protocol as well as +# the new Assuan based one (currently available in the "newpg" package +# at ftp.gnupg.org/gcrypt/alpha/aegypten/). To make use of the agent, +# you have to run an agent as daemon and use the option +# +# use-agent +# +# which tries to use the agent but will fallback to the regular mode +# if there is a problem connecting to the agent. The normal way to +# locate the agent is by looking at the environment variable +# GPG_AGENT_INFO which should have been set during gpg-agent startup. +# In certain situations the use of this variable is not possible, thus +# the option +# +# --gpg-agent-info=<path>:<pid>:1 +# +# may be used to override it. diff --git a/g10/packet.h b/g10/packet.h new file mode 100644 index 000000000..c391c53a4 --- /dev/null +++ b/g10/packet.h @@ -0,0 +1,510 @@ +/* packet.h - packet definitions + * 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 + */ + +#ifndef G10_PACKET_H +#define G10_PACKET_H + +#include "types.h" +#include "iobuf.h" +#include "mpi.h" +#include "cipher.h" +#include "filter.h" +#include "global.h" + +#define DEBUG_PARSE_PACKET 1 + +typedef enum { + PKT_NONE =0, + PKT_PUBKEY_ENC =1, /* public key encrypted packet */ + PKT_SIGNATURE =2, /* secret key encrypted packet */ + PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/ + PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/ + PKT_SECRET_KEY =5, /* secret key */ + PKT_PUBLIC_KEY =6, /* public key */ + PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */ + PKT_COMPRESSED =8, /* compressed data packet */ + PKT_ENCRYPTED =9, /* conventional encrypted data */ + PKT_MARKER =10, /* marker packet (OpenPGP) */ + PKT_PLAINTEXT =11, /* plaintext data with filename and mode */ + PKT_RING_TRUST =12, /* keyring trust packet */ + PKT_USER_ID =13, /* user id packet */ + PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */ + PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */ + PKT_ATTRIBUTE =17, /* PGP's attribute packet */ + PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */ + PKT_MDC =19, /* manipulation detection code packet */ + PKT_COMMENT =61, /* new comment packet (private) */ + PKT_GPG_CONTROL =63 /* internal control packet */ +} pkttype_t; + +typedef struct packet_struct PACKET; + +/* PKT_GPG_CONTROL types */ +typedef enum { + CTRLPKT_CLEARSIGN_START = 1, + CTRLPKT_PIPEMODE = 2, + CTRLPKT_PLAINTEXT_MARK =3 +} ctrlpkttype_t; + +typedef enum { + PREFTYPE_NONE = 0, + PREFTYPE_SYM = 1, + PREFTYPE_HASH = 2, + PREFTYPE_ZIP = 3 +} preftype_t; + +typedef struct { + byte type; + byte value; +} prefitem_t; + +typedef struct { + int mode; + byte hash_algo; + byte salt[8]; + u32 count; +} STRING2KEY; + +typedef struct { + byte version; + byte cipher_algo; /* cipher algorithm used */ + STRING2KEY s2k; + byte seskeylen; /* keylength in byte or 0 for no seskey */ + byte seskey[1]; +} PKT_symkey_enc; + +typedef struct { + u32 keyid[2]; /* 64 bit keyid */ + byte version; + byte pubkey_algo; /* algorithm used for public key scheme */ + byte throw_keyid; + MPI data[PUBKEY_MAX_NENC]; +} PKT_pubkey_enc; + + +typedef struct { + u32 keyid[2]; /* 64 bit keyid */ + byte sig_class; /* sig classification */ + byte digest_algo; /* algorithm used for digest */ + byte pubkey_algo; /* algorithm used for public key scheme */ + byte last; /* a stupid flag */ +} PKT_onepass_sig; + + +typedef struct { + size_t size; /* allocated */ + size_t len; /* used */ + byte data[1]; +} subpktarea_t; + +struct revocation_key { + byte class; + byte algid; + byte fpr[MAX_FINGERPRINT_LEN]; +}; + +typedef struct { + ulong local_id; /* internal use, valid if > 0 */ + struct { + unsigned checked:1; /* signature has been checked */ + unsigned valid:1; /* signature is good (if checked is set) */ + unsigned unknown_critical:1; + unsigned exportable:1; + unsigned revocable:1; + unsigned policy_url:1; /* Policy URL is present */ + unsigned notation:1; /* At least one notation is present */ + unsigned expired:1; + } flags; + u32 keyid[2]; /* 64 bit keyid */ + u32 timestamp; /* signature made */ + u32 expiredate; /* expires at this date or 0 if not at all */ + byte version; + byte sig_class; /* sig classification, append for MD calculation*/ + byte pubkey_algo; /* algorithm used for public key scheme */ + /* (PUBKEY_ALGO_xxx) */ + byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */ + byte trust_depth; + byte trust_value; + const byte *trust_regexp; + struct revocation_key **revkey; + int numrevkeys; + subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */ + subpktarea_t *unhashed; /* ditto for unhashed data */ + byte digest_start[2]; /* first 2 bytes of the digest */ + MPI data[PUBKEY_MAX_NSIG]; +} PKT_signature; + +#define ATTRIB_IMAGE 1 + +/* This is the cooked form of attributes */ +struct user_attribute { + byte type; + const byte *data; + u32 len; +}; + +typedef struct { + int ref; /* reference counter */ + int len; /* length of the name */ + struct user_attribute *attribs; + int numattribs; + byte *attrib_data; /* if this is not NULL, the packet is an attribute */ + unsigned long attrib_len; + byte *namehash; + int help_key_usage; + u32 help_key_expire; + int help_full_count; + int help_marginal_count; + int is_primary; /* 2 if set via the primary flag, 1 if calculated */ + int is_revoked; + int is_expired; + u32 expiredate; /* expires at this date or 0 if not at all */ + prefitem_t *prefs; /* list of preferences (may be NULL)*/ + int mdc_feature; + int ks_modify; + u32 created; /* according to the self-signature */ + byte selfsigversion; + char name[1]; +} PKT_user_id; + + +/**************** + * Note about the pkey/skey elements: We assume that the secret keys + * has the same elemts as the public key at the begin of the array, so + * that npkey < nskey and it is possible to compare the secret and + * public keys by comparing the first npkey elements of pkey againts skey. + */ +typedef struct { + u32 timestamp; /* key made */ + u32 expiredate; /* expires at this date or 0 if not at all */ + u32 max_expiredate; /* must not expire past this date */ + byte hdrbytes; /* number of header bytes */ + byte version; + byte selfsigversion; /* highest version of all of the self-sigs */ + byte pubkey_algo; /* algorithm used for public key scheme */ + byte pubkey_usage; /* for now only used to pass it to getkey() */ + byte req_usage; /* hack to pass a request to getkey() */ + byte req_algo; /* Ditto */ + u32 has_expired; /* set to the expiration date if expired */ + int is_revoked; /* key has been revoked */ + int is_valid; /* key (especially subkey) is valid */ + int dont_cache; /* do not cache this */ + ulong local_id; /* internal use, valid if > 0 */ + u32 main_keyid[2]; /* keyid of the primary key */ + u32 keyid[2]; /* calculated by keyid_from_pk() */ + byte is_primary; + byte is_disabled; /* 0 for unset, 1 for enabled, 2 for disabled. */ + prefitem_t *prefs; /* list of preferences (may be NULL) */ + int mdc_feature; /* mdc feature set */ + PKT_user_id *user_id; /* if != NULL: found by that uid */ + struct revocation_key *revkey; + int numrevkeys; + u32 trust_timestamp; + byte trust_depth; + byte trust_value; + const byte *trust_regexp; + MPI pkey[PUBKEY_MAX_NPKEY]; +} PKT_public_key; + +/* Evaluates as true if the pk is disabled, and false if it isn't. If + there is no disable value cached, fill one in. */ +#define pk_is_disabled(a) (((a)->is_disabled)?((a)->is_disabled==2):(cache_disabled_value((a)))) + +typedef struct { + u32 timestamp; /* key made */ + u32 expiredate; /* expires at this date or 0 if not at all */ + u32 max_expiredate; /* must not expire past this date */ + byte hdrbytes; /* number of header bytes */ + byte version; + byte pubkey_algo; /* algorithm used for public key scheme */ + byte pubkey_usage; + byte req_usage; + byte req_algo; + u32 has_expired; /* set to the expiration date if expired */ + int is_revoked; /* key has been revoked */ + int is_valid; /* key (especially subkey) is valid */ + u32 main_keyid[2]; /* keyid of the primary key */ + u32 keyid[2]; + byte is_primary; + byte is_protected; /* The secret info is protected and must */ + /* be decrypted before use, the protected */ + /* MPIs are simply (void*) pointers to memory */ + /* and should never be passed to a mpi_xxx() */ + struct { + byte algo; /* cipher used to protect the secret information*/ + byte sha1chk; /* SHA1 is used instead of a 16 bit checksum */ + STRING2KEY s2k; + byte ivlen; /* used length of the iv */ + byte iv[16]; /* initialization vector for CFB mode */ + } protect; + MPI skey[PUBKEY_MAX_NSKEY]; + u16 csum; /* checksum */ +} PKT_secret_key; + + +typedef struct { + int len; /* length of data */ + char data[1]; +} PKT_comment; + +typedef struct { + u32 len; /* reserved */ + byte new_ctb; + byte algorithm; + IOBUF buf; /* IOBUF reference */ +} PKT_compressed; + +typedef struct { + u32 len; /* length of encrypted data */ + int extralen; /* this is (blocksize+2) */ + byte new_ctb; /* uses a new CTB */ + byte mdc_method; /* > 0: integrity protected encrypted data packet */ + IOBUF buf; /* IOBUF reference */ +} PKT_encrypted; + +typedef struct { + byte hash[20]; +} PKT_mdc; + +typedef struct { + unsigned int trustval; + unsigned int sigcache; +} PKT_ring_trust; + +typedef struct { + u32 len; /* length of encrypted data */ + IOBUF buf; /* IOBUF reference */ + byte new_ctb; + byte is_partial; /* partial length encoded */ + int mode; + u32 timestamp; + int namelen; + char name[1]; +} PKT_plaintext; + +typedef struct { + int control; + size_t datalen; + char data[1]; +} PKT_gpg_control; + +/* combine all packets into a union */ +struct packet_struct { + pkttype_t pkttype; + union { + void *generic; + PKT_symkey_enc *symkey_enc; /* PKT_SYMKEY_ENC */ + PKT_pubkey_enc *pubkey_enc; /* PKT_PUBKEY_ENC */ + PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */ + PKT_signature *signature; /* PKT_SIGNATURE */ + PKT_public_key *public_key; /* PKT_PUBLIC_[SUB)KEY */ + PKT_secret_key *secret_key; /* PKT_SECRET_[SUB]KEY */ + PKT_comment *comment; /* PKT_COMMENT */ + PKT_user_id *user_id; /* PKT_USER_ID */ + PKT_compressed *compressed; /* PKT_COMPRESSED */ + PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */ + PKT_mdc *mdc; /* PKT_MDC */ + PKT_ring_trust *ring_trust; /* PKT_RING_TRUST */ + PKT_plaintext *plaintext; /* PKT_PLAINTEXT */ + PKT_gpg_control *gpg_control; /* PKT_GPG_CONTROL */ + } pkt; +}; + +#define init_packet(a) do { (a)->pkttype = 0; \ + (a)->pkt.generic = NULL; \ + } while(0) + +typedef enum { + SIGSUBPKT_TEST_CRITICAL=-3, + SIGSUBPKT_LIST_UNHASHED=-2, + SIGSUBPKT_LIST_HASHED =-1, + SIGSUBPKT_NONE = 0, + SIGSUBPKT_SIG_CREATED = 2, /* signature creation time */ + SIGSUBPKT_SIG_EXPIRE = 3, /* signature expiration time */ + SIGSUBPKT_EXPORTABLE = 4, /* exportable */ + SIGSUBPKT_TRUST = 5, /* trust signature */ + SIGSUBPKT_REGEXP = 6, /* regular expression */ + SIGSUBPKT_REVOCABLE = 7, /* revocable */ + SIGSUBPKT_KEY_EXPIRE = 9, /* key expiration time */ + SIGSUBPKT_ARR =10, /* additional recipient request */ + SIGSUBPKT_PREF_SYM =11, /* preferred symmetric algorithms */ + SIGSUBPKT_REV_KEY =12, /* revocation key */ + SIGSUBPKT_ISSUER =16, /* issuer key ID */ + SIGSUBPKT_NOTATION =20, /* notation data */ + SIGSUBPKT_PREF_HASH =21, /* preferred hash algorithms */ + SIGSUBPKT_PREF_COMPR =22, /* preferred compression algorithms */ + SIGSUBPKT_KS_FLAGS =23, /* key server preferences */ + SIGSUBPKT_PREF_KS =24, /* preferred key server */ + SIGSUBPKT_PRIMARY_UID =25, /* primary user id */ + SIGSUBPKT_POLICY =26, /* policy URL */ + SIGSUBPKT_KEY_FLAGS =27, /* key flags */ + SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ + SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ + SIGSUBPKT_FEATURES =30, /* feature flags */ + + SIGSUBPKT_FLAG_CRITICAL=128 +} sigsubpkttype_t; + + +/*-- mainproc.c --*/ +int proc_packets( void *ctx, IOBUF a ); +int proc_signature_packets( void *ctx, IOBUF a, + STRLIST signedfiles, const char *sigfile ); +int proc_encryption_packets( void *ctx, IOBUF a ); +int list_packets( IOBUF a ); + +/*-- parse-packet.c --*/ +int set_packet_list_mode( int mode ); + +#if DEBUG_PARSE_PACKET +int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, + const char* file, int lineno ); +int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, + const char* file, int lineno ); +int dbg_copy_all_packets( IOBUF inp, IOBUF out, + const char* file, int lineno ); +int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, + const char* file, int lineno ); +int dbg_skip_some_packets( IOBUF inp, unsigned n, + const char* file, int lineno ); +#define search_packet( a,b,c,d ) \ + dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) +#define parse_packet( a, b ) \ + dbg_parse_packet( (a), (b), __FILE__, __LINE__ ) +#define copy_all_packets( a,b ) \ + dbg_copy_all_packets((a),(b), __FILE__, __LINE__ ) +#define copy_some_packets( a,b,c ) \ + dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ ) +#define skip_some_packets( a,b ) \ + dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) +#else +int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ); +int parse_packet( IOBUF inp, PACKET *ret_pkt); +int copy_all_packets( IOBUF inp, IOBUF out ); +int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ); +int skip_some_packets( IOBUF inp, unsigned n ); +#endif + +const byte *enum_sig_subpkt ( const subpktarea_t *subpkts, + sigsubpkttype_t reqtype, + size_t *ret_n, int *start, int *critical ); +const byte *parse_sig_subpkt ( const subpktarea_t *buffer, + sigsubpkttype_t reqtype, + size_t *ret_n ); +const byte *parse_sig_subpkt2 ( PKT_signature *sig, + sigsubpkttype_t reqtype, + size_t *ret_n ); +int parse_one_sig_subpkt( const byte *buffer, size_t n, int type ); +void parse_revkeys(PKT_signature *sig); +int parse_attribute_subpkts(PKT_user_id *uid); +void make_attribute_uidname(PKT_user_id *uid, size_t max_namelen); +PACKET *create_gpg_control ( ctrlpkttype_t type, + const byte *data, + size_t datalen ); + +/*-- build-packet.c --*/ +int build_packet( IOBUF inp, PACKET *pkt ); +u32 calc_packet_length( PACKET *pkt ); +void hash_public_key( MD_HANDLE md, PKT_public_key *pk ); +void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, + const byte *buffer, size_t buflen ); +void build_sig_subpkt_from_sig( PKT_signature *sig ); +int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); +void build_attribute_subpkt(PKT_user_id *uid,byte type, + const void *buf,u32 buflen, + const void *header,u32 headerlen); + +/*-- free-packet.c --*/ +void free_symkey_enc( PKT_symkey_enc *enc ); +void free_pubkey_enc( PKT_pubkey_enc *enc ); +void free_seckey_enc( PKT_signature *enc ); +int digest_algo_from_sig( PKT_signature *sig ); +void release_public_key_parts( PKT_public_key *pk ); +void free_public_key( PKT_public_key *key ); +void release_secret_key_parts( PKT_secret_key *sk ); +void free_secret_key( PKT_secret_key *sk ); +void free_attributes(PKT_user_id *uid); +void free_user_id( PKT_user_id *uid ); +void free_comment( PKT_comment *rem ); +void free_packet( PACKET *pkt ); +prefitem_t *copy_prefs (const prefitem_t *prefs); +PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); +void copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk ); +PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ); +PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); +PKT_user_id *scopy_user_id (PKT_user_id *sd ); +int cmp_public_keys( PKT_public_key *a, PKT_public_key *b ); +int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b ); +int cmp_signatures( PKT_signature *a, PKT_signature *b ); +int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk ); +int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); + + +/*-- sig-check.c --*/ +int signature_check( PKT_signature *sig, MD_HANDLE digest ); +int signature_check2( PKT_signature *sig, MD_HANDLE digest, + u32 *r_expiredate, int *r_expired ); + +/*-- seckey-cert.c --*/ +int is_secret_key_protected( PKT_secret_key *sk ); +int check_secret_key( PKT_secret_key *sk, int retries ); +int protect_secret_key( PKT_secret_key *sk, DEK *dek ); + +/*-- pubkey-enc.c --*/ +int get_session_key( PKT_pubkey_enc *k, DEK *dek ); +int get_override_session_key( DEK *dek, const char *string ); + +/*-- compress.c --*/ +int handle_compressed( void *ctx, PKT_compressed *cd, + int (*callback)(IOBUF, void *), void *passthru ); + +/*-- encr-data.c --*/ +int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek ); + +/*-- plaintext.c --*/ +int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, + int nooutput, int clearsig ); +int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, + const char *inname, int textmode ); + +/*-- comment.c --*/ +int write_comment( IOBUF out, const char *s ); + +/*-- sign.c --*/ +int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, + PKT_user_id *uid, PKT_public_key *subpk, + PKT_secret_key *sk, int sigclass, int digest_algo, + int sigversion, u32 timestamp, u32 duration, + int (*mksubpkt)(PKT_signature *, void *), + void *opaque ); +int update_keysig_packet( PKT_signature **ret_sig, + PKT_signature *orig_sig, + PKT_public_key *pk, + PKT_user_id *uid, + PKT_public_key *subpk, + PKT_secret_key *sk, + int (*mksubpkt)(PKT_signature *, void *), + void *opaque ); + +/*-- keygen.c --*/ +PKT_user_id *generate_user_id(void); + +#endif /*G10_PACKET_H*/ diff --git a/g10/parse-packet.c b/g10/parse-packet.c new file mode 100644 index 000000000..a881840b2 --- /dev/null +++ b/g10/parse-packet.c @@ -0,0 +1,2281 @@ +/* parse-packet.c - read 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 "filter.h" +#include "photoid.h" +#include "options.h" +#include "main.h" +#include "i18n.h" + +static int mpi_print_mode = 0; +static int list_mode = 0; + +static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts, + off_t *retpos, int *skip, IOBUF out, int do_skip +#ifdef DEBUG_PARSE_PACKET + ,const char *dbg_w, const char *dbg_f, int dbg_l +#endif + ); +static int copy_packet( IOBUF inp, IOBUF out, int pkttype, + unsigned long pktlen ); +static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ); +static void skip_rest( IOBUF inp, unsigned long pktlen ); +static void *read_rest( IOBUF inp, size_t pktlen ); +static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_signature *sig ); +static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_onepass_sig *ops ); +static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, + byte *hdr, int hdrlen, PACKET *packet ); +static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); +static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb); +static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb ); +static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb); +static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb); +static int parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet ); + +static unsigned short +read_16(IOBUF inp) +{ + unsigned short a; + a = iobuf_get_noeof(inp) << 8; + a |= iobuf_get_noeof(inp); + return a; +} + +static unsigned long +read_32(IOBUF inp) +{ + unsigned long a; + a = iobuf_get_noeof(inp) << 24; + a |= iobuf_get_noeof(inp) << 16; + a |= iobuf_get_noeof(inp) << 8; + a |= iobuf_get_noeof(inp); + return a; +} + + +int +set_packet_list_mode( int mode ) +{ + int old = list_mode; + list_mode = mode; + mpi_print_mode = DBG_MPI; + return old; +} + +static void +unknown_pubkey_warning( int algo ) +{ + static byte unknown_pubkey_algos[256]; + + algo &= 0xff; + if( !unknown_pubkey_algos[algo] ) { + if( opt.verbose ) + log_info(_("can't handle public key algorithm %d\n"), algo ); + unknown_pubkey_algos[algo] = 1; + } +} + +/**************** + * Parse a Packet and return it in packet + * Returns: 0 := valid packet in pkt + * -1 := no more packets + * >0 := error + * Note: The function may return an error and a partly valid packet; + * caller must free this packet. + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l ) +{ + int skip, rc; + + do { + rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l ); + } while( skip ); + return rc; +} +#else +int +parse_packet( IOBUF inp, PACKET *pkt ) +{ + int skip, rc; + + do { + rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 ); + } while( skip ); + return rc; +} +#endif + +/**************** + * Like parse packet, but only return secret or public (sub)key packets. + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, + const char *dbg_f, int dbg_l ) +{ + int skip, rc; + + do { + rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l ); + } while( skip ); + return rc; +} +#else +int +search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ) +{ + int skip, rc; + + do { + rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0 ); + } while( skip ); + return rc; +} +#endif + +/**************** + * Copy all packets from INP to OUT, thereby removing unused spaces. + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_copy_all_packets( IOBUF inp, IOBUF out, + const char *dbg_f, int dbg_l ) +{ + PACKET pkt; + int skip, rc=0; + do { + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l ))); + return rc; +} +#else +int +copy_all_packets( IOBUF inp, IOBUF out ) +{ + PACKET pkt; + int skip, rc=0; + do { + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 ))); + return rc; +} +#endif + +/**************** + * Copy some packets from INP to OUT, thereby removing unused spaces. + * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets) + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, + const char *dbg_f, int dbg_l ) +{ + PACKET pkt; + int skip, rc=0; + do { + if( iobuf_tell(inp) >= stopoff ) + return 0; + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, + "some", dbg_f, dbg_l )) ); + return rc; +} +#else +int +copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ) +{ + PACKET pkt; + int skip, rc=0; + do { + if( iobuf_tell(inp) >= stopoff ) + return 0; + init_packet(&pkt); + } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) ); + return rc; +} +#endif + +/**************** + * Skip over N packets + */ +#ifdef DEBUG_PARSE_PACKET +int +dbg_skip_some_packets( IOBUF inp, unsigned n, + const char *dbg_f, int dbg_l ) +{ + int skip, rc=0; + PACKET pkt; + + for( ;n && !rc; n--) { + init_packet(&pkt); + rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l ); + } + return rc; +} +#else +int +skip_some_packets( IOBUF inp, unsigned n ) +{ + int skip, rc=0; + PACKET pkt; + + for( ;n && !rc; n--) { + init_packet(&pkt); + rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 ); + } + return rc; +} +#endif + + +/**************** + * Parse packet. Set the variable skip points to 1 if the packet + * should be skipped; this is the case if either ONLYKEYPKTS is set + * and the parsed packet isn't one or the + * packet-type is 0, indicating deleted stuff. + * if OUT is not NULL, a special copymode is used. + */ +static int +parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, + int *skip, IOBUF out, int do_skip +#ifdef DEBUG_PARSE_PACKET + ,const char *dbg_w, const char *dbg_f, int dbg_l +#endif + ) +{ + int rc=0, c, ctb, pkttype, lenbytes; + unsigned long pktlen; + byte hdr[8]; + int hdrlen; + int new_ctb = 0; + int with_uid = (onlykeypkts == 2); + + *skip = 0; + assert( !pkt->pkt.generic ); + if( retpos ) + *retpos = iobuf_tell(inp); + + if( (ctb = iobuf_get(inp)) == -1 ) { + rc = -1; + goto leave; + } + hdrlen=0; + hdr[hdrlen++] = ctb; + if( !(ctb & 0x80) ) { + log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + pktlen = 0; + new_ctb = !!(ctb & 0x40); + if( new_ctb ) { + pkttype = ctb & 0x3f; + if( (c = iobuf_get(inp)) == -1 ) { + log_error("%s: 1st length byte missing\n", iobuf_where(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + if (pkttype == PKT_COMPRESSED) { + iobuf_set_partial_block_mode(inp, c & 0xff); + pktlen = 0;/* to indicate partial length */ + } + else { + hdr[hdrlen++] = c; + if( c < 192 ) + pktlen = c; + else if( c < 224 ) { + pktlen = (c - 192) * 256; + if( (c = iobuf_get(inp)) == -1 ) { + log_error("%s: 2nd length byte missing\n", + iobuf_where(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + hdr[hdrlen++] = c; + pktlen += c + 192; + } + else if( c == 255 ) { + pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24; + pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16; + pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8; + if( (c = iobuf_get(inp)) == -1 ) { + log_error("%s: 4 byte length invalid\n", + iobuf_where(inp) ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + pktlen |= (hdr[hdrlen++] = c ); + } + else { /* partial body length */ + iobuf_set_partial_block_mode(inp, c & 0xff); + pktlen = 0;/* to indicate partial length */ + } + } + } + else { + pkttype = (ctb>>2)&0xf; + lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); + if( !lenbytes ) { + pktlen = 0; /* don't know the value */ + if( pkttype != PKT_COMPRESSED ) + iobuf_set_block_mode(inp, 1); + } + else { + for( ; lenbytes; lenbytes-- ) { + pktlen <<= 8; + pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp); + } + } + } + + if (pktlen == 0xffffffff) { + /* with a some probability this is caused by a problem in the + * the uncompressing layer - in some error cases it just loops + * and spits out 0xff bytes. */ + log_error ("%s: garbled packet detected\n", iobuf_where(inp) ); + g10_exit (2); + } + + if( out && pkttype ) { + if( iobuf_write( out, hdr, hdrlen ) == -1 ) + rc = G10ERR_WRITE_FILE; + else + rc = copy_packet(inp, out, pkttype, pktlen ); + goto leave; + } + + if (with_uid && pkttype == PKT_USER_ID) + ; + else if( do_skip + || !pkttype + || (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY + && pkttype != PKT_PUBLIC_KEY + && pkttype != PKT_SECRET_SUBKEY + && pkttype != PKT_SECRET_KEY ) ) { + skip_rest(inp, pktlen); + *skip = 1; + rc = 0; + goto leave; + } + + if( DBG_PACKET ) { +#ifdef DEBUG_PARSE_PACKET + log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n", + iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"", + dbg_w, dbg_f, dbg_l ); +#else + log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n", + iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" ); +#endif + } + pkt->pkttype = pkttype; + rc = G10ERR_UNKNOWN_PACKET; /* default error */ + switch( pkttype ) { + case PKT_PUBLIC_KEY: + case PKT_PUBLIC_SUBKEY: + pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key ); + rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); + break; + case PKT_SECRET_KEY: + case PKT_SECRET_SUBKEY: + pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key ); + rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); + break; + case PKT_SYMKEY_ENC: + rc = parse_symkeyenc( inp, pkttype, pktlen, pkt ); + break; + case PKT_PUBKEY_ENC: + rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt ); + break; + case PKT_SIGNATURE: + pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature ); + rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); + break; + case PKT_ONEPASS_SIG: + pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig ); + rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig ); + break; + case PKT_USER_ID: + rc = parse_user_id(inp, pkttype, pktlen, pkt ); + break; + case PKT_ATTRIBUTE: + pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */ + rc = parse_attribute(inp, pkttype, pktlen, pkt); + break; + case PKT_OLD_COMMENT: + case PKT_COMMENT: + rc = parse_comment(inp, pkttype, pktlen, pkt); + break; + case PKT_RING_TRUST: + parse_trust(inp, pkttype, pktlen, pkt); + rc = 0; + break; + case PKT_PLAINTEXT: + rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb ); + break; + case PKT_COMPRESSED: + rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb ); + break; + case PKT_ENCRYPTED: + case PKT_ENCRYPTED_MDC: + rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb ); + break; + case PKT_MDC: + rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb ); + break; + case PKT_GPG_CONTROL: + rc = parse_gpg_control(inp, pkttype, pktlen, pkt ); + break; + default: + skip_packet(inp, pkttype, pktlen); + break; + } + + leave: + if( !rc && iobuf_error(inp) ) + rc = G10ERR_INV_KEYRING; + return rc; +} + +static void +dump_hex_line( int c, int *i ) +{ + if( *i && !(*i%8) ) { + if( *i && !(*i%24) ) + printf("\n%4d:", *i ); + else + putchar(' '); + } + if( c == -1 ) + printf(" EOF" ); + else + printf(" %02x", c ); + ++*i; +} + + +static int +copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen ) +{ + int n; + char buf[100]; + + if( iobuf_in_block_mode(inp) ) { + while( (n = iobuf_read( inp, buf, 100 )) != -1 ) + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + else if( !pktlen && pkttype == PKT_COMPRESSED ) { + log_debug("copy_packet: compressed!\n"); + /* compressed packet, copy till EOF */ + while( (n = iobuf_read( inp, buf, 100 )) != -1 ) + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + else { + for( ; pktlen; pktlen -= n ) { + n = pktlen > 100 ? 100 : pktlen; + n = iobuf_read( inp, buf, n ); + if( n == -1 ) + return G10ERR_READ_FILE; + if( iobuf_write(out, buf, n ) ) + return G10ERR_WRITE_FILE; /* write error */ + } + } + return 0; +} + + +static void +skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) +{ + if( list_mode ) { + if( pkttype == PKT_MARKER ) + fputs(":marker packet:\n", stdout ); + else + printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen); + if( pkttype ) { + int c, i=0 ; + if( pkttype != PKT_MARKER ) + fputs("dump:", stdout ); + if( iobuf_in_block_mode(inp) ) { + while( (c=iobuf_get(inp)) != -1 ) + dump_hex_line(c, &i); + } + else { + for( ; pktlen; pktlen-- ) + dump_hex_line(iobuf_get(inp), &i); + } + putchar('\n'); + return; + } + } + skip_rest(inp,pktlen); +} + +static void +skip_rest( IOBUF inp, unsigned long pktlen ) +{ + if( iobuf_in_block_mode(inp) ) { + while( iobuf_get(inp) != -1 ) + ; + } + else { + for( ; pktlen; pktlen-- ) + if( iobuf_get(inp) == -1 ) + break; + } +} + + +static void * +read_rest( IOBUF inp, size_t pktlen ) +{ + byte *p; + int i; + + if( iobuf_in_block_mode(inp) ) { + log_error("read_rest: can't store stream data\n"); + p = NULL; + } + else { + p = m_alloc( pktlen ); + for(i=0; pktlen; pktlen--, i++ ) + p[i] = iobuf_get(inp); + } + return p; +} + + + +static int +parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + PKT_symkey_enc *k; + int rc = 0; + int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen; + + if( pktlen < 4 ) { + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + version = iobuf_get_noeof(inp); pktlen--; + if( version != 4 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, version); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */ + log_error("packet(%d) too large\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + cipher_algo = iobuf_get_noeof(inp); pktlen--; + s2kmode = iobuf_get_noeof(inp); pktlen--; + hash_algo = iobuf_get_noeof(inp); pktlen--; + switch( s2kmode ) { + case 0: /* simple s2k */ + minlen = 0; + break; + case 1: /* salted s2k */ + minlen = 8; + break; + case 3: /* iterated+salted s2k */ + minlen = 9; + break; + default: + log_error("unknown S2K %d\n", s2kmode ); + goto leave; + } + if( minlen > pktlen ) { + log_error("packet with S2K %d too short\n", s2kmode ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + seskeylen = pktlen - minlen; + k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc + + seskeylen - 1 ); + k->version = version; + k->cipher_algo = cipher_algo; + k->s2k.mode = s2kmode; + k->s2k.hash_algo = hash_algo; + if( s2kmode == 1 || s2kmode == 3 ) { + for(i=0; i < 8 && pktlen; i++, pktlen-- ) + k->s2k.salt[i] = iobuf_get_noeof(inp); + } + if( s2kmode == 3 ) { + k->s2k.count = iobuf_get(inp); pktlen--; + } + k->seskeylen = seskeylen; + for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) + k->seskey[i] = iobuf_get_noeof(inp); + assert( !pktlen ); + + if( list_mode ) { + printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n", + version, cipher_algo, s2kmode, hash_algo); + if( s2kmode == 1 || s2kmode == 3 ) { + printf("\tsalt "); + for(i=0; i < 8; i++ ) + printf("%02x", k->s2k.salt[i]); + if( s2kmode == 3 ) + printf(", count %lu\n", (ulong)k->s2k.count ); + printf("\n"); + } + } + + leave: + skip_rest(inp, pktlen); + return rc; +} + +static int +parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + unsigned int n; + int rc = 0; + int i, ndata; + PKT_pubkey_enc *k; + + k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc); + if( pktlen < 12 ) { + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + k->version = iobuf_get_noeof(inp); pktlen--; + if( k->version != 2 && k->version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, k->version); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + k->keyid[0] = read_32(inp); pktlen -= 4; + k->keyid[1] = read_32(inp); pktlen -= 4; + k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; + k->throw_keyid = 0; /* only used as flag for build_packet */ + if( list_mode ) + printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", + k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]); + + ndata = pubkey_get_nenc(k->pubkey_algo); + if( !ndata ) { + if( list_mode ) + printf("\tunsupported algorithm %d\n", k->pubkey_algo ); + unknown_pubkey_warning( k->pubkey_algo ); + k->data[0] = NULL; /* no need to store the encrypted data */ + } + else { + for( i=0; i < ndata; i++ ) { + n = pktlen; + k->data[i] = mpi_read(inp, &n, 0); pktlen -=n; + if( list_mode ) { + printf("\tdata: "); + mpi_print(stdout, k->data[i], mpi_print_mode ); + putchar('\n'); + } + if (!k->data[i]) + rc = G10ERR_INVALID_PACKET; + } + } + + leave: + skip_rest(inp, pktlen); + return rc; +} + + +static void +dump_sig_subpkt( int hashed, int type, int critical, + const byte *buffer, size_t buflen, size_t length ) +{ + const char *p=NULL; + int i; + + /* The CERT has warning out with explains how to use GNUPG to + * detect the ARRs - we print our old message here when it is a faked + * ARR and add an additional notice */ + if ( type == SIGSUBPKT_ARR && !hashed ) { + printf("\tsubpkt %d len %u (additional recipient request)\n" + "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically " + "encrypt to this key and thereby reveal the plaintext to " + "the owner of this ARR key. Detailed info follows:\n", + type, (unsigned)length ); + } + + buffer++; + length--; + + printf("\t%s%ssubpkt %d len %u (", /*)*/ + critical ? "critical ":"", + hashed ? "hashed ":"", type, (unsigned)length ); + if( length > buflen ) { + printf("too short: buffer is only %u)\n", (unsigned)buflen ); + return; + } + switch( type ) { + case SIGSUBPKT_SIG_CREATED: + if( length >= 4 ) + printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) ); + break; + case SIGSUBPKT_SIG_EXPIRE: + if( length >= 4 ) + printf("sig expires after %s", + strtimevalue( buffer_to_u32(buffer) ) ); + break; + case SIGSUBPKT_EXPORTABLE: + if( length ) + printf("%sexportable", *buffer? "":"not "); + break; + case SIGSUBPKT_TRUST: + if(length!=2) + p="[invalid trust subpacket]"; + else + printf("trust signature of depth %d, value %d",buffer[0],buffer[1]); + break; + case SIGSUBPKT_REGEXP: + if(!length) + p="[invalid regexp subpacket]"; + else + printf("regular expression: \"%s\"",buffer); + break; + case SIGSUBPKT_REVOCABLE: + if( length ) + printf("%srevocable", *buffer? "":"not "); + break; + case SIGSUBPKT_KEY_EXPIRE: + if( length >= 4 ) + printf("key expires after %s", + strtimevalue( buffer_to_u32(buffer) ) ); + break; + case SIGSUBPKT_PREF_SYM: + fputs("pref-sym-algos:", stdout ); + for( i=0; i < length; i++ ) + printf(" %d", buffer[i] ); + break; + case SIGSUBPKT_REV_KEY: + fputs("revocation key: ", stdout ); + if( length < 22 ) + p = "[too short]"; + else { + printf("c=%02x a=%d f=", buffer[0], buffer[1] ); + for( i=2; i < length; i++ ) + printf("%02X", buffer[i] ); + } + break; + case SIGSUBPKT_ISSUER: + if( length >= 8 ) + printf("issuer key ID %08lX%08lX", + (ulong)buffer_to_u32(buffer), + (ulong)buffer_to_u32(buffer+4) ); + break; + case SIGSUBPKT_NOTATION: + { + fputs("notation: ", stdout ); + if( length < 8 ) + p = "[too short]"; + else { + const byte *s = buffer; + size_t n1, n2; + + n1 = (s[4] << 8) | s[5]; + n2 = (s[6] << 8) | s[7]; + s += 8; + if( 8+n1+n2 != length ) + p = "[error]"; + else { + print_string( stdout, s, n1, ')' ); + putc( '=', stdout ); + + if( *buffer & 0x80 ) + print_string( stdout, s+n1, n2, ')' ); + else + p = "[not human readable]"; + } + } + } + break; + case SIGSUBPKT_PREF_HASH: + fputs("pref-hash-algos:", stdout ); + for( i=0; i < length; i++ ) + printf(" %d", buffer[i] ); + break; + case SIGSUBPKT_PREF_COMPR: + fputs("pref-zip-algos:", stdout ); + for( i=0; i < length; i++ ) + printf(" %d", buffer[i] ); + break; + case SIGSUBPKT_KS_FLAGS: + fputs("key server preferences:",stdout); + for(i=0;i<length;i++) + printf(" %02X", buffer[i]); + break; + case SIGSUBPKT_PREF_KS: + p = "preferred key server"; + break; + case SIGSUBPKT_PRIMARY_UID: + p = "primary user ID"; + break; + case SIGSUBPKT_POLICY: + fputs("policy: ", stdout ); + print_string( stdout, buffer, length, ')' ); + break; + case SIGSUBPKT_KEY_FLAGS: + fputs ( "key flags:", stdout ); + for( i=0; i < length; i++ ) + printf(" %02X", buffer[i] ); + break; + case SIGSUBPKT_SIGNERS_UID: + p = "signer's user ID"; + break; + case SIGSUBPKT_REVOC_REASON: + if( length ) { + printf("revocation reason 0x%02x (", *buffer ); + print_string( stdout, buffer+1, length-1, ')' ); + p = ")"; + } + break; + case SIGSUBPKT_ARR: + fputs("Big Brother's key (ignored): ", stdout ); + if( length < 22 ) + p = "[too short]"; + else { + printf("c=%02x a=%d f=", buffer[0], buffer[1] ); + for( i=2; i < length; i++ ) + printf("%02X", buffer[i] ); + } + break; + case SIGSUBPKT_FEATURES: + fputs ( "features:", stdout ); + for( i=0; i < length; i++ ) + printf(" %02x", buffer[i] ); + break; + default: + if(type>=100 && type<=110) + p="experimental / private subpacket"; + else + p = "?"; + break; + } + + printf("%s)\n", p? p: ""); +} + +/**************** + * Returns: >= 0 offset into buffer + * -1 unknown type + * -2 unsupported type + * -3 subpacket too short + */ +int +parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) +{ + switch( type ) { + case SIGSUBPKT_REV_KEY: + if(n < 22) + break; + return 0; + case SIGSUBPKT_SIG_CREATED: + case SIGSUBPKT_SIG_EXPIRE: + case SIGSUBPKT_KEY_EXPIRE: + if( n < 4 ) + break; + return 0; + case SIGSUBPKT_KEY_FLAGS: + case SIGSUBPKT_KS_FLAGS: + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + case SIGSUBPKT_POLICY: + case SIGSUBPKT_FEATURES: + case SIGSUBPKT_REGEXP: + return 0; + case SIGSUBPKT_EXPORTABLE: + case SIGSUBPKT_REVOCABLE: + if( !n ) + break; + return 0; + case SIGSUBPKT_ISSUER: /* issuer key ID */ + if( n < 8 ) + break; + return 0; + case SIGSUBPKT_NOTATION: + if( n < 8 ) /* minimum length needed */ + break; + return 0; + case SIGSUBPKT_REVOC_REASON: + if( !n ) + break; + return 0; + case SIGSUBPKT_PRIMARY_UID: + if ( n != 1 ) + break; + return 0; + case SIGSUBPKT_TRUST: + if ( n != 2 ) + break; + return 0; + default: return -1; + } + return -3; +} + + +static int +can_handle_critical( const byte *buffer, size_t n, int type ) +{ + switch( type ) { + case SIGSUBPKT_NOTATION: + if( n >= 8 && (*buffer & 0x80) ) + return 1; /* human readable is handled */ + return 0; + + case SIGSUBPKT_SIG_CREATED: + case SIGSUBPKT_SIG_EXPIRE: + case SIGSUBPKT_KEY_EXPIRE: + case SIGSUBPKT_EXPORTABLE: + case SIGSUBPKT_REVOCABLE: + case SIGSUBPKT_REV_KEY: + case SIGSUBPKT_ISSUER:/* issuer key ID */ + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + case SIGSUBPKT_KEY_FLAGS: + case SIGSUBPKT_PRIMARY_UID: + case SIGSUBPKT_FEATURES: + case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */ + case SIGSUBPKT_TRUST: + case SIGSUBPKT_REGEXP: + return 1; + + default: + return 0; + } +} + + +const byte * +enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype, + size_t *ret_n, int *start, int *critical ) +{ + const byte *buffer; + int buflen; + int type; + int critical_dummy; + int offset; + size_t n; + int seq = 0; + int reqseq = start? *start: 0; + + if(!critical) + critical=&critical_dummy; + + if( !pktbuf || reqseq == -1 ) { + /* return some value different from NULL to indicate that + * there is no critical bit we do not understand. The caller + * will never use the value. Yes I know, it is an ugly hack */ + return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&pktbuf : NULL; + } + buffer = pktbuf->data; + buflen = pktbuf->len; + while( buflen ) { + n = *buffer++; buflen--; + if( n == 255 ) { /* 4 byte length header */ + if( buflen < 4 ) + goto too_short; + n = (buffer[0] << 24) | (buffer[1] << 16) + | (buffer[2] << 8) | buffer[3]; + buffer += 4; + buflen -= 4; + } + else if( n >= 192 ) { /* 2 byte special encoded length header */ + if( buflen < 2 ) + goto too_short; + n = (( n - 192 ) << 8) + *buffer + 192; + buffer++; + buflen--; + } + if( buflen < n ) + goto too_short; + type = *buffer; + if( type & 0x80 ) { + type &= 0x7f; + *critical = 1; + } + else + *critical = 0; + if( !(++seq > reqseq) ) + ; + else if( reqtype == SIGSUBPKT_TEST_CRITICAL ) { + if( *critical ) { + if( n-1 > buflen+1 ) + goto too_short; + if( !can_handle_critical(buffer+1, n-1, type ) ) + { + if(opt.verbose) + log_info(_("subpacket of type %d has " + "critical bit set\n"),type); + if( start ) + *start = seq; + return NULL; /* this is an error */ + } + } + } + else if( reqtype < 0 ) /* list packets */ + dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED, + type, *critical, buffer, buflen, n ); + else if( type == reqtype ) { /* found */ + buffer++; + n--; + if( n > buflen ) + goto too_short; + if( ret_n ) + *ret_n = n; + offset = parse_one_sig_subpkt(buffer, n, type ); + switch( offset ) { + case -3: + log_error("subpacket of type %d too short\n", type); + return NULL; + case -2: + return NULL; + case -1: + BUG(); /* not yet needed */ + default: + break; + } + if( start ) + *start = seq; + return buffer+offset; + } + buffer += n; buflen -=n; + } + if( reqtype == SIGSUBPKT_TEST_CRITICAL ) + return buffer; /* as value true to indicate that there is no */ + /* critical bit we don't understand */ + if( start ) + *start = -1; + return NULL; /* end of packets; not found */ + + too_short: + log_error("buffer shorter than subpacket\n"); + if( start ) + *start = -1; + return NULL; +} + + +const byte * +parse_sig_subpkt (const subpktarea_t *buffer, sigsubpkttype_t reqtype, + size_t *ret_n) +{ + return enum_sig_subpkt( buffer, reqtype, ret_n, NULL, NULL ); +} + +const byte * +parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype, + size_t *ret_n ) +{ + const byte *p; + + p = parse_sig_subpkt (sig->hashed, reqtype, ret_n ); + if( !p ) + p = parse_sig_subpkt (sig->unhashed, reqtype, ret_n ); + return p; +} + +/* Find all revocation keys. Look in hashed area only. */ +void parse_revkeys(PKT_signature *sig) +{ + struct revocation_key *revkey; + int seq=0; + size_t len; + + if(sig->sig_class!=0x1F) + return; + + while((revkey= + (struct revocation_key *)enum_sig_subpkt(sig->hashed, + SIGSUBPKT_REV_KEY, + &len,&seq,NULL))) + { + if(len==sizeof(struct revocation_key) && + (revkey->class&0x80)) /* 0x80 bit must be set */ + { + sig->revkey=m_realloc(sig->revkey, + sizeof(struct revocation_key *)*(sig->numrevkeys+1)); + sig->revkey[sig->numrevkeys]=revkey; + sig->numrevkeys++; + } + } +} + +static int +parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_signature *sig ) +{ + int md5_len=0; + unsigned n; + int is_v4=0; + int rc=0; + int i, ndata; + + if( pktlen < 16 ) { + log_error("packet(%d) too short\n", pkttype); + goto leave; + } + sig->version = iobuf_get_noeof(inp); pktlen--; + if( sig->version == 4 ) + is_v4=1; + else if( sig->version != 2 && sig->version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, sig->version); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + + if( !is_v4 ) { + md5_len = iobuf_get_noeof(inp); pktlen--; + } + sig->sig_class = iobuf_get_noeof(inp); pktlen--; + if( !is_v4 ) { + sig->timestamp = read_32(inp); pktlen -= 4; + sig->keyid[0] = read_32(inp); pktlen -= 4; + sig->keyid[1] = read_32(inp); pktlen -= 4; + } + sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--; + sig->digest_algo = iobuf_get_noeof(inp); pktlen--; + sig->flags.exportable=1; + sig->flags.revocable=1; + if( is_v4 ) { /* read subpackets */ + n = read_16(inp); pktlen -= 2; /* length of hashed data */ + if( n > 10000 ) { + log_error("signature packet: hashed data too long\n"); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + if( n ) { + sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 ); + sig->hashed->size = n; + sig->hashed->len = n; + if( iobuf_read (inp, sig->hashed->data, n ) != n ) { + log_error ("premature eof while reading " + "hashed signature data\n"); + rc = -1; + goto leave; + } + pktlen -= n; + } + n = read_16(inp); pktlen -= 2; /* length of unhashed data */ + if( n > 10000 ) { + log_error("signature packet: unhashed data too long\n"); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + if( n ) { + /* we add 8 extra bytes so that we have space for the signature + * status cache. Well we are wasting this if there is a cache + * packet already, but in the other case it avoids an realloc */ + sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 ); + sig->unhashed->size = n + 8; + sig->unhashed->len = n; + if( iobuf_read(inp, sig->unhashed->data, n ) != n ) { + log_error("premature eof while reading " + "unhashed signature data\n"); + rc = -1; + goto leave; + } + pktlen -= n; + } + } + + if( pktlen < 5 ) { /* sanity check */ + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + + sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--; + sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--; + + if( is_v4 && sig->pubkey_algo ) { /*extract required information */ + const byte *p; + size_t len; + + /* set sig->flags.unknown_critical if there is a + * critical bit set for packets which we do not understand */ + if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL) + || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL, + NULL) ) + { + sig->flags.unknown_critical = 1; + } + + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL ); + if( !p ) + log_error("signature packet without timestamp\n"); + else + sig->timestamp = buffer_to_u32(p); + p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); + if( !p ) + log_error("signature packet without keyid\n"); + else { + sig->keyid[0] = buffer_to_u32(p); + sig->keyid[1] = buffer_to_u32(p+4); + } + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL); + if(p) + sig->expiredate=sig->timestamp+buffer_to_u32(p); + if(sig->expiredate && sig->expiredate<=make_timestamp()) + sig->flags.expired=1; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL); + if(p) + sig->flags.policy_url=1; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL); + if(p) + sig->flags.notation=1; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_REVOCABLE,NULL); + if(p && *p==0) + sig->flags.revocable=0; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_TRUST,&len); + if(p && len==2) + { + sig->trust_depth=p[0]; + sig->trust_value=p[1]; + + /* Only look for a regexp if there is also a trust + subpacket. */ + sig->trust_regexp= + parse_sig_subpkt(sig->hashed,SIGSUBPKT_REGEXP,&len); + + /* If the regular expression is of 0 length, there is no + regular expression. */ + if(len==0) + sig->trust_regexp=NULL; + } + + /* We accept the exportable subpacket from either the hashed + or unhashed areas as older versions of gpg put it in the + unhashed area. In theory, anyway, we should never see this + packet off of a local keyring. */ + + p=parse_sig_subpkt2(sig,SIGSUBPKT_EXPORTABLE,NULL); + if(p && *p==0) + sig->flags.exportable=0; + + /* Find all revocation keys. */ + if(sig->sig_class==0x1F) + parse_revkeys(sig); + } + + if( list_mode ) { + printf(":signature packet: algo %d, keyid %08lX%08lX\n" + "\tversion %d, created %lu, md5len %d, sigclass %02x\n" + "\tdigest algo %d, begin of digest %02x %02x\n", + sig->pubkey_algo, + (ulong)sig->keyid[0], (ulong)sig->keyid[1], + sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class, + sig->digest_algo, + sig->digest_start[0], sig->digest_start[1] ); + if( is_v4 ) { + parse_sig_subpkt (sig->hashed, SIGSUBPKT_LIST_HASHED, NULL ); + parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL); + } + } + + ndata = pubkey_get_nsig(sig->pubkey_algo); + if( !ndata ) { + if( list_mode ) + printf("\tunknown algorithm %d\n", sig->pubkey_algo ); + unknown_pubkey_warning( sig->pubkey_algo ); + /* we store the plain material in data[0], so that we are able + * to write it back with build_packet() */ + sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen ); + pktlen = 0; + } + else { + for( i=0; i < ndata; i++ ) { + n = pktlen; + sig->data[i] = mpi_read(inp, &n, 0 ); + pktlen -=n; + if( list_mode ) { + printf("\tdata: "); + mpi_print(stdout, sig->data[i], mpi_print_mode ); + putchar('\n'); + } + if (!sig->data[i]) + rc = G10ERR_INVALID_PACKET; + } + } + + leave: + skip_rest(inp, pktlen); + return rc; +} + + +static int +parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, + PKT_onepass_sig *ops ) +{ + int version; + int rc = 0; + + if( pktlen < 13 ) { + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + version = iobuf_get_noeof(inp); pktlen--; + if( version != 3 ) { + log_error("onepass_sig with unknown version %d\n", version); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + ops->sig_class = iobuf_get_noeof(inp); pktlen--; + ops->digest_algo = iobuf_get_noeof(inp); pktlen--; + ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--; + ops->keyid[0] = read_32(inp); pktlen -= 4; + ops->keyid[1] = read_32(inp); pktlen -= 4; + ops->last = iobuf_get_noeof(inp); pktlen--; + if( list_mode ) + printf(":onepass_sig packet: keyid %08lX%08lX\n" + "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n", + (ulong)ops->keyid[0], (ulong)ops->keyid[1], + version, ops->sig_class, + ops->digest_algo, ops->pubkey_algo, ops->last ); + + + leave: + skip_rest(inp, pktlen); + return rc; +} + + +static MPI +read_protected_v3_mpi (IOBUF inp, unsigned long *length) +{ + int c; + unsigned int nbits, nbytes; + unsigned char *buf, *p; + MPI val; + + if (*length < 2) + { + log_error ("mpi too small\n"); + return NULL; + } + + if ((c=iobuf_get (inp)) == -1) + return NULL; + --*length; + nbits = c << 8; + if ((c=iobuf_get(inp)) == -1) + return NULL; + --*length; + nbits |= c; + + if (nbits > 16384) + { + log_error ("mpi too large (%u bits)\n", nbits); + return NULL; + } + nbytes = (nbits+7) / 8; + buf = p = m_alloc (2 + nbytes); + *p++ = nbits >> 8; + *p++ = nbits; + for (; nbytes && length; nbytes--, --*length) + *p++ = iobuf_get (inp); + if (nbytes) + { + log_error ("packet shorter tham mpi\n"); + m_free (buf); + return NULL; + } + + /* convert buffer into an opaque MPI */ + val = mpi_set_opaque (NULL, buf, p-buf); + return val; +} + + +static int +parse_key( IOBUF inp, int pkttype, unsigned long pktlen, + byte *hdr, int hdrlen, PACKET *pkt ) +{ + int i, version, algorithm; + unsigned n; + unsigned long timestamp, expiredate, max_expiredate; + int npkey, nskey; + int is_v4=0; + int rc=0; + + version = iobuf_get_noeof(inp); pktlen--; + if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) { + /* early versions of G10 use old PGP comments packets; + * luckily all those comments are started by a hash */ + if( list_mode ) { + printf(":rfc1991 comment packet: \"" ); + for( ; pktlen; pktlen-- ) { + int c; + c = iobuf_get_noeof(inp); + if( c >= ' ' && c <= 'z' ) + putchar(c); + else + printf("\\x%02x", c ); + } + printf("\"\n"); + } + skip_rest(inp, pktlen); + return 0; + } + else if( version == 4 ) + is_v4=1; + else if( version != 2 && version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, version); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + + if( pktlen < 11 ) { + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + + timestamp = read_32(inp); pktlen -= 4; + if( is_v4 ) { + expiredate = 0; /* have to get it from the selfsignature */ + max_expiredate = 0; + } + else { + unsigned short ndays; + ndays = read_16(inp); pktlen -= 2; + if( ndays ) + expiredate = timestamp + ndays * 86400L; + else + expiredate = 0; + + max_expiredate=expiredate; + } + algorithm = iobuf_get_noeof(inp); pktlen--; + if( list_mode ) + printf(":%s key packet:\n" + "\tversion %d, algo %d, created %lu, expires %lu\n", + pkttype == PKT_PUBLIC_KEY? "public" : + pkttype == PKT_SECRET_KEY? "secret" : + pkttype == PKT_PUBLIC_SUBKEY? "public sub" : + pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??", + version, algorithm, timestamp, expiredate ); + + if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = pkt->pkt.secret_key; + + sk->timestamp = timestamp; + sk->expiredate = expiredate; + sk->max_expiredate = max_expiredate; + sk->hdrbytes = hdrlen; + sk->version = version; + sk->is_primary = pkttype == PKT_SECRET_KEY; + sk->pubkey_algo = algorithm; + sk->req_usage = 0; + sk->pubkey_usage = 0; /* not yet used */ + } + else { + PKT_public_key *pk = pkt->pkt.public_key; + + pk->timestamp = timestamp; + pk->expiredate = expiredate; + pk->max_expiredate = max_expiredate; + pk->hdrbytes = hdrlen; + pk->version = version; + pk->is_primary = pkttype == PKT_PUBLIC_KEY; + pk->pubkey_algo = algorithm; + pk->req_usage = 0; + pk->pubkey_usage = 0; /* not yet used */ + pk->is_revoked = 0; + pk->is_disabled = 0; + pk->keyid[0] = 0; + pk->keyid[1] = 0; + } + nskey = pubkey_get_nskey( algorithm ); + npkey = pubkey_get_npkey( algorithm ); + if( !npkey ) { + if( list_mode ) + printf("\tunknown algorithm %d\n", algorithm ); + unknown_pubkey_warning( algorithm ); + } + + + if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { + PKT_secret_key *sk = pkt->pkt.secret_key; + byte temp[16]; + + if( !npkey ) { + sk->skey[0] = mpi_set_opaque( NULL, + read_rest(inp, pktlen), pktlen ); + pktlen = 0; + goto leave; + } + + for(i=0; i < npkey; i++ ) { + n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; + if( list_mode ) { + printf( "\tskey[%d]: ", i); + mpi_print(stdout, sk->skey[i], mpi_print_mode ); + putchar('\n'); + } + if (!sk->skey[i]) + rc = G10ERR_INVALID_PACKET; + } + if (rc) /* one of the MPIs were bad */ + goto leave; + sk->protect.algo = iobuf_get_noeof(inp); pktlen--; + sk->protect.sha1chk = 0; + if( sk->protect.algo ) { + sk->is_protected = 1; + sk->protect.s2k.count = 0; + if( sk->protect.algo == 254 || sk->protect.algo == 255 ) { + if( pktlen < 3 ) { + rc = G10ERR_INVALID_PACKET; + goto leave; + } + sk->protect.sha1chk = (sk->protect.algo == 254); + sk->protect.algo = iobuf_get_noeof(inp); pktlen--; + /* Note that a sk->protect.algo > 110 is illegal, but + I'm not erroring on it here as otherwise there + would be no way to delete such a key. */ + sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--; + sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--; + /* check for the special GNU extension */ + if( is_v4 && sk->protect.s2k.mode == 101 ) { + for(i=0; i < 4 && pktlen; i++, pktlen-- ) + temp[i] = iobuf_get_noeof(inp); + if( i < 4 || memcmp( temp, "GNU", 3 ) ) { + if( list_mode ) + printf( "\tunknown S2K %d\n", + sk->protect.s2k.mode ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + /* here we know that it is a gnu extension + * What follows is the GNU protection mode: + * All values have special meanings + * and they are mapped in the mode with a base of 1000. + */ + sk->protect.s2k.mode = 1000 + temp[3]; + } + switch( sk->protect.s2k.mode ) { + case 1: + case 3: + for(i=0; i < 8 && pktlen; i++, pktlen-- ) + temp[i] = iobuf_get_noeof(inp); + memcpy(sk->protect.s2k.salt, temp, 8 ); + break; + } + switch( sk->protect.s2k.mode ) { + case 0: if( list_mode ) printf( "\tsimple S2K" ); + break; + case 1: if( list_mode ) printf( "\tsalted S2K" ); + break; + case 3: if( list_mode ) printf( "\titer+salt S2K" ); + break; + case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" ); + break; + default: + if( list_mode ) + printf( "\tunknown %sS2K %d\n", + sk->protect.s2k.mode < 1000? "":"GNU ", + sk->protect.s2k.mode ); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + + if( list_mode ) { + printf(", algo: %d,%s hash: %d", + sk->protect.algo, + sk->protect.sha1chk?" SHA1 protection," + :" simple checksum,", + sk->protect.s2k.hash_algo ); + if( sk->protect.s2k.mode == 1 + || sk->protect.s2k.mode == 3 ) { + printf(", salt: "); + for(i=0; i < 8; i++ ) + printf("%02x", sk->protect.s2k.salt[i]); + } + putchar('\n'); + } + + if( sk->protect.s2k.mode == 3 ) { + if( pktlen < 1 ) { + rc = G10ERR_INVALID_PACKET; + goto leave; + } + sk->protect.s2k.count = iobuf_get(inp); + pktlen--; + if( list_mode ) + printf("\tprotect count: %lu\n", + (ulong)sk->protect.s2k.count); + } + } + /* Note that a sk->protect.algo > 110 is illegal, but I'm + not erroring on it here as otherwise there would be no + way to delete such a key. */ + else { /* old version; no S2K, so we set mode to 0, hash MD5 */ + sk->protect.s2k.mode = 0; + sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5; + if( list_mode ) + printf( "\tprotect algo: %d (hash algo: %d)\n", + sk->protect.algo, sk->protect.s2k.hash_algo ); + } + /* It is really ugly that we don't know the size + * of the IV here in cases we are not aware of the algorithm. + * so a + * sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo); + * won't work. The only solution I see is to hardwire it here. + * NOTE: if you change the ivlen above 16, don't forget to + * enlarge temp. + */ + switch( sk->protect.algo ) { + case 7: case 8: case 9: /* reserved for AES */ + case 10: /* Twofish */ + sk->protect.ivlen = 16; + break; + default: + sk->protect.ivlen = 8; + } + if( sk->protect.s2k.mode == 1001 ) + sk->protect.ivlen = 0; + + if( pktlen < sk->protect.ivlen ) { + rc = G10ERR_INVALID_PACKET; + goto leave; + } + for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- ) + temp[i] = iobuf_get_noeof(inp); + if( list_mode ) { + printf( "\tprotect IV: "); + for(i=0; i < sk->protect.ivlen; i++ ) + printf(" %02x", temp[i] ); + putchar('\n'); + } + memcpy(sk->protect.iv, temp, sk->protect.ivlen ); + } + else + sk->is_protected = 0; + /* It does not make sense to read it into secure memory. + * If the user is so careless, not to protect his secret key, + * we can assume, that he operates an open system :=(. + * So we put the key into secure memory when we unprotect it. */ + if( sk->protect.s2k.mode == 1001 ) { + /* better set some dummy stuff here */ + sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10); + pktlen = 0; + } + else if( is_v4 && sk->is_protected ) { + /* ugly; the length is encrypted too, so we read all + * stuff up to the end of the packet into the first + * skey element */ + sk->skey[npkey] = mpi_set_opaque(NULL, + read_rest(inp, pktlen), pktlen ); + pktlen = 0; + if( list_mode ) { + printf("\tencrypted stuff follows\n"); + } + } + else { /* v3 method: the mpi length is not encrypted */ + for(i=npkey; i < nskey; i++ ) { + if ( sk->is_protected ) { + sk->skey[i] = read_protected_v3_mpi (inp, &pktlen); + if( list_mode ) + printf( "\tskey[%d]: [encrypted]\n", i); + } + else { + n = pktlen; + sk->skey[i] = mpi_read(inp, &n, 0 ); + pktlen -=n; + if( list_mode ) { + printf( "\tskey[%d]: ", i); + mpi_print(stdout, sk->skey[i], mpi_print_mode ); + putchar('\n'); + } + } + + if (!sk->skey[i]) + rc = G10ERR_INVALID_PACKET; + } + if (rc) + goto leave; + + sk->csum = read_16(inp); pktlen -= 2; + if( list_mode ) { + printf("\tchecksum: %04hx\n", sk->csum); + } + } + } + else { + PKT_public_key *pk = pkt->pkt.public_key; + + if( !npkey ) { + pk->pkey[0] = mpi_set_opaque( NULL, + read_rest(inp, pktlen), pktlen ); + pktlen = 0; + goto leave; + } + + for(i=0; i < npkey; i++ ) { + n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; + if( list_mode ) { + printf( "\tpkey[%d]: ", i); + mpi_print(stdout, pk->pkey[i], mpi_print_mode ); + putchar('\n'); + } + if (!pk->pkey[i]) + rc = G10ERR_INVALID_PACKET; + } + if (rc) + goto leave; + } + + leave: + skip_rest(inp, pktlen); + return rc; +} + +/* Attribute subpackets have the same format as v4 signature + subpackets. This is not part of OpenPGP, but is done in several + versions of PGP nevertheless. */ +int +parse_attribute_subpkts(PKT_user_id *uid) +{ + size_t n; + int count=0; + struct user_attribute *attribs=NULL; + const byte *buffer=uid->attrib_data; + int buflen=uid->attrib_len; + byte type; + + m_free(uid->attribs); + + while(buflen) + { + n = *buffer++; buflen--; + if( n == 255 ) { /* 4 byte length header */ + if( buflen < 4 ) + goto too_short; + n = (buffer[0] << 24) | (buffer[1] << 16) + | (buffer[2] << 8) | buffer[3]; + buffer += 4; + buflen -= 4; + } + else if( n >= 192 ) { /* 2 byte special encoded length header */ + if( buflen < 2 ) + goto too_short; + n = (( n - 192 ) << 8) + *buffer + 192; + buffer++; + buflen--; + } + if( buflen < n ) + goto too_short; + + attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute)); + memset(&attribs[count],0,sizeof(struct user_attribute)); + + type=*buffer; + buffer++; + buflen--; + n--; + + attribs[count].type=type; + attribs[count].data=buffer; + attribs[count].len=n; + buffer+=n; + buflen-=n; + count++; + } + + uid->attribs=attribs; + uid->numattribs=count; + return count; + + too_short: + log_error("buffer shorter than attribute subpacket\n"); + uid->attribs=attribs; + uid->numattribs=count; + return count; +} + +static void setup_user_id(PACKET *packet) +{ + packet->pkt.user_id->ref = 1; + packet->pkt.user_id->attribs = NULL; + packet->pkt.user_id->attrib_data = NULL; + packet->pkt.user_id->attrib_len = 0; + packet->pkt.user_id->is_primary = 0; + packet->pkt.user_id->is_revoked = 0; + packet->pkt.user_id->is_expired = 0; + packet->pkt.user_id->expiredate = 0; + packet->pkt.user_id->created = 0; + packet->pkt.user_id->help_key_usage = 0; + packet->pkt.user_id->help_key_expire = 0; + packet->pkt.user_id->prefs = NULL; + packet->pkt.user_id->namehash = NULL; +} + +static int +parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + byte *p; + + packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); + packet->pkt.user_id->len = pktlen; + + setup_user_id(packet); + + p = packet->pkt.user_id->name; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + *p = 0; + + if( list_mode ) { + int n = packet->pkt.user_id->len; + printf(":user ID packet: \""); + /* fixme: Hey why don't we replace this with print_string?? */ + for(p=packet->pkt.user_id->name; n; p++, n-- ) { + if( *p >= ' ' && *p <= 'z' ) + putchar(*p); + else + printf("\\x%02x", *p ); + } + printf("\"\n"); + } + return 0; +} + + +void +make_attribute_uidname(PKT_user_id *uid, size_t max_namelen) +{ + assert ( max_namelen > 70 ); + if(uid->numattribs<=0) + sprintf(uid->name,"[bad attribute packet of size %lu]",uid->attrib_len); + else if(uid->numattribs>1) + sprintf(uid->name,"[%d attributes of size %lu]", + uid->numattribs,uid->attrib_len); + else + { + /* Only one attribute, so list it as the "user id" */ + + if(uid->attribs->type==ATTRIB_IMAGE) + { + u32 len; + byte type; + + if(parse_image_header(uid->attribs,&type,&len)) + sprintf(uid->name,"[%.20s image of size %lu]", + image_type_to_string(type,1),(ulong)len); + else + sprintf(uid->name,"[invalid image]"); + } + else + sprintf(uid->name,"[unknown attribute of size %lu]", + (ulong)uid->attribs->len); + } + + uid->len = strlen(uid->name); +} + +static int +parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + byte *p; + +#define EXTRA_UID_NAME_SPACE 71 + packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + + EXTRA_UID_NAME_SPACE); + + setup_user_id(packet); + + packet->pkt.user_id->attrib_data = m_alloc(pktlen); + packet->pkt.user_id->attrib_len = pktlen; + p = packet->pkt.user_id->attrib_data; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + + /* Now parse out the individual attribute subpackets. This is + somewhat pointless since there is only one currently defined + attribute type (jpeg), but it is correct by the spec. */ + parse_attribute_subpkts(packet->pkt.user_id); + + make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE); + + if( list_mode ) { + printf(":attribute packet: %s\n", packet->pkt.user_id->name ); + } + return 0; +} + + +static int +parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +{ + byte *p; + + packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1); + packet->pkt.comment->len = pktlen; + p = packet->pkt.comment->data; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + + if( list_mode ) { + int n = packet->pkt.comment->len; + printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT? + "OpenPGP draft " : "" ); + for(p=packet->pkt.comment->data; n; p++, n-- ) { + if( *p >= ' ' && *p <= 'z' ) + putchar(*p); + else + printf("\\x%02x", *p ); + } + printf("\"\n"); + } + return 0; +} + + +static void +parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) +{ + int c; + + if (pktlen) + { + c = iobuf_get_noeof(inp); + pktlen--; + pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust ); + pkt->pkt.ring_trust->trustval = c; + pkt->pkt.ring_trust->sigcache = 0; + if (!c && pktlen==1) + { + c = iobuf_get_noeof (inp); + pktlen--; + /* we require that bit 7 of the sigcache is 0 (easier eof handling)*/ + if ( !(c & 0x80) ) + pkt->pkt.ring_trust->sigcache = c; + } + if( list_mode ) + printf(":trust packet: flag=%02x sigcache=%02x\n", + pkt->pkt.ring_trust->trustval, + pkt->pkt.ring_trust->sigcache); + } + else + { + if( list_mode ) + printf(":trust packet: empty\n"); + } + skip_rest (inp, pktlen); +} + + +static int +parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + int rc = 0; + int mode, namelen, partial=0; + PKT_plaintext *pt; + byte *p; + int c, i; + + if( pktlen && pktlen < 6 ) { + log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + /* A packet length of zero indicates partial body length. A zero + data length isn't a zero length packet due to the header (mode, + name, etc), so this is accurate. */ + if(pktlen==0) + partial=1; + mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; + namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; + pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1); + pt->new_ctb = new_ctb; + pt->mode = mode; + pt->namelen = namelen; + pt->is_partial = partial; + if( pktlen ) { + for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ ) + pt->name[i] = iobuf_get_noeof(inp); + } + else { + for( i=0; i < namelen; i++ ) + if( (c=iobuf_get(inp)) == -1 ) + break; + else + pt->name[i] = c; + } + pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4; + pt->len = pktlen; + pt->buf = inp; + pktlen = 0; + + if( list_mode ) { + printf(":literal data packet:\n" + "\tmode %c, created %lu, name=\"", + mode >= ' ' && mode <'z'? mode : '?', + (ulong)pt->timestamp ); + for(p=pt->name,i=0; i < namelen; p++, i++ ) { + if( *p >= ' ' && *p <= 'z' ) + putchar(*p); + else + printf("\\x%02x", *p ); + } + printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len ); + } + + leave: + return rc; +} + + +static int +parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + PKT_compressed *zd; + + /* pktlen is here 0, but data follows + * (this should be the last object in a file or + * the compress algorithm should know the length) + */ + zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed ); + zd->algorithm = iobuf_get_noeof(inp); + zd->len = 0; /* not used */ + zd->new_ctb = new_ctb; + zd->buf = inp; + if( list_mode ) + printf(":compressed packet: algo=%d\n", zd->algorithm); + return 0; +} + + +static int +parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + int rc = 0; + PKT_encrypted *ed; + unsigned long orig_pktlen = pktlen; + + ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); + ed->len = pktlen; + /* we don't know the extralen which is (cipher_blocksize+2) + because the algorithm ist not specified in this packet. + However, it is only important to know this for some sanity + checks on the packet length - it doesn't matter that we can't + do it */ + ed->extralen = 0; + ed->buf = NULL; + ed->new_ctb = new_ctb; + ed->mdc_method = 0; + if( pkttype == PKT_ENCRYPTED_MDC ) { + /* fixme: add some pktlen sanity checks */ + int version; + + version = iobuf_get_noeof(inp); + if (orig_pktlen) + pktlen--; + if( version != 1 ) { + log_error("encrypted_mdc packet with unknown version %d\n", + version); + /*skip_rest(inp, pktlen); should we really do this? */ + rc = G10ERR_INVALID_PACKET; + goto leave; + } + ed->mdc_method = DIGEST_ALGO_SHA1; + } + if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */ + log_error("packet(%d) too short\n", pkttype); + rc = G10ERR_INVALID_PACKET; + skip_rest(inp, pktlen); + goto leave; + } + if( list_mode ) { + if( orig_pktlen ) + printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen); + else + printf(":encrypted data packet:\n\tlength: unknown\n"); + if( ed->mdc_method ) + printf("\tmdc_method: %d\n", ed->mdc_method ); + } + + ed->buf = inp; + pktlen = 0; + + leave: + return rc; +} + + +static int +parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb ) +{ + int rc = 0; + PKT_mdc *mdc; + byte *p; + + mdc = pkt->pkt.mdc= m_alloc(sizeof *pkt->pkt.mdc ); + if( list_mode ) + printf(":mdc packet: length=%lu\n", pktlen); + if( !new_ctb || pktlen != 20 ) { + log_error("mdc_packet with invalid encoding\n"); + rc = G10ERR_INVALID_PACKET; + goto leave; + } + p = mdc->hash; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + + leave: + return rc; +} + + +/* + * This packet is internally generated by PGG (by armor.c) to + * transfer some information to the lower layer. To make sure that + * this packet is really a GPG faked one and not one comming from outside, + * we first check that tehre is a unique tag in it. + * The format of such a control packet is: + * n byte session marker + * 1 byte control type CTRLPKT_xxxxx + * m byte control data + */ + +static int +parse_gpg_control( IOBUF inp, + int pkttype, unsigned long pktlen, PACKET *packet ) +{ + byte *p; + const byte *sesmark; + size_t sesmarklen; + int i; + + if ( list_mode ) + printf(":packet 63: length %lu ", pktlen); + + sesmark = get_session_marker ( &sesmarklen ); + if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */ + goto skipit; + for( i=0; i < sesmarklen; i++, pktlen-- ) { + if ( sesmark[i] != iobuf_get_noeof(inp) ) + goto skipit; + } + if ( list_mode ) + puts ("- gpg control packet"); + + packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control + + pktlen - 1); + packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--; + packet->pkt.gpg_control->datalen = pktlen; + p = packet->pkt.gpg_control->data; + for( ; pktlen; pktlen--, p++ ) + *p = iobuf_get_noeof(inp); + + return 0; + + skipit: + if ( list_mode ) { + int c; + + i=0; + printf("- private (rest length %lu)\n", pktlen); + if( iobuf_in_block_mode(inp) ) { + while( (c=iobuf_get(inp)) != -1 ) + dump_hex_line(c, &i); + } + else { + for( ; pktlen; pktlen-- ) + dump_hex_line(iobuf_get(inp), &i); + } + putchar('\n'); + } + skip_rest(inp,pktlen); + return G10ERR_INVALID_PACKET; +} + +/* create a gpg control packet to be used internally as a placeholder */ +PACKET * +create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen ) +{ + PACKET *packet; + byte *p; + + packet = m_alloc( sizeof *packet ); + init_packet(packet); + packet->pkttype = PKT_GPG_CONTROL; + packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control + + datalen - 1); + packet->pkt.gpg_control->control = type; + packet->pkt.gpg_control->datalen = datalen; + p = packet->pkt.gpg_control->data; + for( ; datalen; datalen--, p++ ) + *p = *data++; + + return packet; +} diff --git a/g10/passphrase.c b/g10/passphrase.c new file mode 100644 index 000000000..769276221 --- /dev/null +++ b/g10/passphrase.c @@ -0,0 +1,1238 @@ +/* passphrase.c - Get a passphrase + * 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 <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#if !defined(HAVE_DOSISH_SYSTEM) && !defined(__riscos__) +#include <sys/socket.h> +#include <sys/un.h> +#endif +#if defined (__MINGW32__) || defined (__CYGWIN32__) +# include <windows.h> +#endif +#include <errno.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif + +#include "util.h" +#include "memory.h" +#include "options.h" +#include "ttyio.h" +#include "cipher.h" +#include "keydb.h" +#include "main.h" +#include "i18n.h" +#include "status.h" + + +enum gpga_protocol_codes { + /* Request codes */ + GPGA_PROT_GET_VERSION = 1, + GPGA_PROT_GET_PASSPHRASE = 2, + GPGA_PROT_CLEAR_PASSPHRASE= 3, + GPGA_PROT_SHUTDOWN = 4, + GPGA_PROT_FLUSH = 5, + + /* Reply codes */ + GPGA_PROT_REPLY_BASE = 0x10000, + GPGA_PROT_OKAY = 0x10001, + GPGA_PROT_GOT_PASSPHRASE = 0x10002, + + /* Error codes */ + GPGA_PROT_ERROR_BASE = 0x20000, + GPGA_PROT_PROTOCOL_ERROR = 0x20001, + GPGA_PROT_INVALID_REQUEST= 0x20002, + GPGA_PROT_CANCELED = 0x20003, + GPGA_PROT_NO_PASSPHRASE = 0x20004, + GPGA_PROT_BAD_PASSPHRASE = 0x20005, + GPGA_PROT_INVALID_DATA = 0x20006, + GPGA_PROT_NOT_IMPLEMENTED= 0x20007, + GPGA_PROT_UI_PROBLEM = 0x20008 +}; + + +#define buftou32( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ + (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3))) +#define u32tobuf( p, a ) do { \ + ((byte*)p)[0] = (byte)((a) >> 24); \ + ((byte*)p)[1] = (byte)((a) >> 16); \ + ((byte*)p)[2] = (byte)((a) >> 8); \ + ((byte*)p)[3] = (byte)((a) ); \ + } while(0) + +#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)) + + + +static char *fd_passwd = NULL; +static char *next_pw = NULL; +static char *last_pw = NULL; + +#if defined (__MINGW32__) +static int read_fd = 0; +static int write_fd = 0; +#endif + +static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ); + +int +have_static_passphrase() +{ + if ( opt.use_agent ) + return 0; + return !!fd_passwd; +} + +/**************** + * Set the passphrase to be used for the next query and only for the next + * one. + */ +void +set_next_passphrase( const char *s ) +{ + m_free(next_pw); + next_pw = NULL; + if( s ) { + next_pw = m_alloc_secure( strlen(s)+1 ); + strcpy(next_pw, s ); + } +} + +/**************** + * Get the last passphrase used in passphrase_to_dek. + * Note: This removes the passphrase from this modules and + * the caller must free the result. May return NULL: + */ +char * +get_last_passphrase() +{ + char *p = last_pw; + last_pw = NULL; + return p; +} + + +void +read_passphrase_from_fd( int fd ) +{ + int i, len; + char *pw; + + if ( opt.use_agent ) + { /* Not used but we have to do a dummy read, so that it won't end + up at the begin of the message if the quite usual trick to + prepend the passphtrase to the message is used. */ + char buf[1]; + + while (!(read (fd, buf, 1) != 1 || *buf == '\n' )) + ; + *buf = 0; + return; + } + + if (!opt.batch ) + tty_printf("Reading passphrase from file descriptor %d ...", fd ); + for (pw = NULL, i = len = 100; ; i++ ) + { + if (i >= len-1 ) + { + char *pw2 = pw; + len += 100; + pw = m_alloc_secure( len ); + if( pw2 ) + memcpy(pw, pw2, i ); + else + i=0; + } + if (read( fd, pw+i, 1) != 1 || pw[i] == '\n' ) + break; + } + pw[i] = 0; + if (!opt.batch) + tty_printf("\b\b\b \n" ); + + m_free( fd_passwd ); + fd_passwd = pw; +} + +static int +writen ( int fd, const void *buf, size_t nbytes ) +{ +#if defined (__MINGW32__) + DWORD nwritten, nleft = nbytes; + + while (nleft > 0) { + if ( !WriteFile( (HANDLE)write_fd, buf, nleft, &nwritten, NULL) ) { + log_error("write failed: ec=%d\n", (int)GetLastError()); + return -1; + } + /*log_info("** WriteFile fd=%d nytes=%d nwritten=%d\n", + write_fd, nbytes, (int)nwritten);*/ + Sleep(100); + + nleft -= nwritten; + buf = (const BYTE *)buf + nwritten; + } +#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + /* not implemented */ +#else + size_t nleft = nbytes; + int nwritten; + + while( nleft > 0 ) { + nwritten = write( fd, buf, nleft ); + if( nwritten < 0 ) { + if ( errno == EINTR ) + nwritten = 0; + else { + log_error ( "write() failed: %s\n", strerror (errno) ); + return -1; + } + } + nleft -= nwritten; + buf = (const char*)buf + nwritten; + } +#endif + + return 0; +} + + +static int +readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) +{ +#if defined (__MINGW32__) + DWORD nread, nleft = buflen; + + while (nleft > 0) { + if ( !ReadFile( (HANDLE)read_fd, buf, nleft, &nread, NULL) ) { + log_error("read() error: ec=%d\n", (int)GetLastError()); + return -1; + } + if (!nread || GetLastError() == ERROR_BROKEN_PIPE) + break; + /*log_info("** ReadFile fd=%d buflen=%d nread=%d\n", + read_fd, buflen, (int)nread);*/ + Sleep(100); + + nleft -= nread; + buf = (BYTE *)buf + nread; + } + if (ret_nread) + *ret_nread = buflen - nleft; + +#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + /* not implemented */ +#else + size_t nleft = buflen; + int nread; + char *p; + + p = buf; + while( nleft > 0 ) { + nread = read ( fd, buf, nleft ); + if( nread < 0 ) { + if (nread == EINTR) + nread = 0; + else { + log_error ( "read() error: %s\n", strerror (errno) ); + return -1; + } + } + else if( !nread ) + break; /* EOF */ + nleft -= nread; + buf = (char*)buf + nread; + } + if( ret_nread ) + *ret_nread = buflen - nleft; +#endif + + return 0; +} + +/* read an entire line */ +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 -1; /* read error */ + } + else if (!n) + { + return -1; /* 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 temporary hack until we use + the assuna lib in gpg. So it is okay to forget + about pending bytes */ + } + } + + return nread; +} + + + +#if !defined (__riscos__) + +#if !defined (__MINGW32__) +/* For the new Assuan protocol we may have to send options */ +static int +agent_send_option (int fd, const char *name, const char *value) +{ + char buf[200]; + int nread; + char *line; + int i; + + line = m_alloc (7 + strlen (name) + 1 + strlen (value) + 2); + strcpy (stpcpy (stpcpy (stpcpy ( + stpcpy (line, "OPTION "), name), "="), value), "\n"); + i = writen (fd, line, strlen (line)); + m_free (line); + if (i) + return -1; + + /* get response */ + nread = readline (fd, buf, DIM(buf)-1); + if (nread < 3) + return -1; + + if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) + return 0; /* okay */ + + return -1; +} + +static int +agent_send_all_options (int fd) +{ + char *dft_display = NULL; + const char *dft_ttyname = NULL; + char *dft_ttytype = NULL; + char *old_lc = NULL; + char *dft_lc = NULL; + int rc = 0; + + dft_display = getenv ("DISPLAY"); + if (opt.display || dft_display) + { + if (agent_send_option (fd, "display", + opt.display ? opt.display : dft_display)) + return -1; + } + + if (!opt.ttyname) + dft_ttyname = tty_get_ttyname (); + if (opt.ttyname || dft_ttyname) + { + if (agent_send_option (fd, "ttyname", + opt.ttyname ? opt.ttyname : dft_ttyname)) + return -1; + } + + dft_ttytype = getenv ("TERM"); + if (opt.ttytype || (dft_ttyname && dft_ttytype)) + { + if (agent_send_option (fd, "ttytype", + opt.ttyname ? opt.ttytype : dft_ttytype)) + return -1; + } + +#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) + old_lc = setlocale (LC_CTYPE, NULL); + if (old_lc) + old_lc = m_strdup (old_lc); + dft_lc = setlocale (LC_CTYPE, ""); +#endif + if (opt.lc_ctype || (dft_ttyname && dft_lc)) + { + rc = agent_send_option (fd, "lc-ctype", + opt.lc_ctype ? opt.lc_ctype : dft_lc); + } +#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) + if (old_lc) + { + setlocale (LC_CTYPE, old_lc); + m_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 = m_strdup (old_lc); + dft_lc = setlocale (LC_MESSAGES, ""); +#endif + if (opt.lc_messages || (dft_ttyname && dft_lc)) + { + rc = agent_send_option (fd, "lc-messages", + opt.lc_messages ? opt.lc_messages : dft_lc); + } +#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) + if (old_lc) + { + setlocale (LC_MESSAGES, old_lc); + m_free (old_lc); + } +#endif + return rc; +} +#endif /*!__MINGW32__*/ + + +/* + * Open a connection to the agent and send the magic string + * Returns: -1 on error or an filedescriptor for urther processing + */ + +static int +agent_open (int *ret_prot) +{ +#if defined (__MINGW32__) + int fd; + char *infostr, *p; + HANDLE h; + char pidstr[128]; + + *ret_prot = 0; + if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentPID")) + || *infostr == '0') { + log_error( _("gpg-agent is not available in this session\n")); + return -1; + } + free(infostr); + + sprintf(pidstr, "%u", (unsigned int)GetCurrentProcessId()); + if (write_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentCID", pidstr)) { + log_error( _("can't set client pid for the agent\n") ); + return -1; + } + h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); + SetEvent(h); + Sleep(50); /* some time for the server */ + if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentReadFD")) ) { + log_error( _("can't get server read FD for the agent\n") ); + return -1; + } + read_fd = atol(p); + free(p); + if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", + "agentWriteFD")) ) { + log_error ( _("can't get server write FD for the agent\n") ); + return -1; + } + write_fd = atol(p); + free(p); + fd = 0; + + if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { + fd = -1; + } +#else /* Posix */ + + int fd; + char *infostr, *p; + struct sockaddr_un client_addr; + size_t len; + int prot; + + if (opt.gpg_agent_info) + infostr = m_strdup (opt.gpg_agent_info); + else + { + infostr = getenv ( "GPG_AGENT_INFO" ); + if ( !infostr ) { + log_error (_("gpg-agent is not available in this session\n")); + opt.use_agent = 0; + return -1; + } + infostr = m_strdup ( infostr ); + } + + if ( !(p = strchr ( infostr, ':')) || p == infostr + || (p-infostr)+1 >= sizeof client_addr.sun_path ) { + log_error( _("malformed GPG_AGENT_INFO environment variable\n")); + m_free (infostr ); + opt.use_agent = 0; + return -1; + } + *p++ = 0; + /* See whether this is the new gpg-agent using the Assuna protocl. + This agent identifies itself by have an info string with a + version number in the 3rd field. */ + while (*p && *p != ':') + p++; + prot = *p? atoi (p+1) : 0; + if ( prot < 0 || prot > 1) { + log_error (_("gpg-agent protocol version %d is not supported\n"),prot); + m_free (infostr ); + opt.use_agent = 0; + return -1; + } + *ret_prot = prot; + + if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { + log_error ("can't create socket: %s\n", strerror(errno) ); + m_free (infostr ); + opt.use_agent = 0; + return -1; + } + + 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 ) { + log_error ( _("can't connect to `%s': %s\n"), + infostr, strerror (errno) ); + m_free (infostr ); + close (fd ); + opt.use_agent = 0; + return -1; + } + m_free (infostr); + + if (!prot) { + if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { + close (fd); + fd = -1; + } + } + else { /* assuan based gpg-agent */ + char line[200]; + int nread; + + nread = readline (fd, line, DIM(line)); + if (nread < 3 || !(line[0] == 'O' && line[1] == 'K' + && (line[2] == '\n' || line[2] == ' ')) ) { + log_error ( _("communication problem with gpg-agent\n")); + close (fd ); + opt.use_agent = 0; + return -1; + } + + if (agent_send_all_options (fd)) { + log_error (_("problem with the agent - disabling agent use\n")); + close (fd); + opt.use_agent = 0; + return -1; + } + + } +#endif + + return fd; +} + + +static void +agent_close ( int fd ) +{ +#if defined (__MINGW32__) + HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); + ResetEvent(h); +#else + close (fd); +#endif +} +#endif /* !__riscos__ */ + + + +/* + * Ask the GPG Agent for the passphrase. + * Mode 0: Allow cached passphrase + * 1: No cached passphrase FIXME: Not really implemented + * 2: Ditto, but change the text to "repeat entry" + * + * Note that TRYAGAIN_TEXT must not be translated. If canceled is not + * NULL, the function does set it to 1 if the user canceled the + * operation. + */ +static char * +agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, + int *canceled) +{ +#if defined(__riscos__) + return NULL; +#else + size_t n; + char *atext = NULL; + char buf[50]; + int fd = -1; + int nread; + u32 reply; + char *pw = NULL; + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + byte fpr[MAX_FINGERPRINT_LEN]; + int have_fpr = 0; + int prot; + char *orig_codeset = NULL; + + if (canceled) + *canceled = 0; + +#if MAX_FINGERPRINT_LEN < 20 +#error agent needs a 20 byte fingerprint +#endif + + memset (fpr, 0, MAX_FINGERPRINT_LEN ); + if( keyid && get_pubkey( pk, keyid ) ) + { + free_public_key( pk ); + pk = NULL; /* oops: no key for some reason */ + } + +#ifdef ENABLE_NLS + /* The Assuan agent protol requires us to trasnmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset) + { /* We only switch when we are able to restore the codeset later. */ + orig_codeset = m_strdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE, "utf-8")) + orig_codeset = NULL; + } +#endif + + if ( (fd = agent_open (&prot)) == -1 ) + goto failure; + + if ( !mode && pk && keyid ) + { + char *uid; + size_t uidlen; + const char *algo_name = pubkey_algo_to_string ( pk->pubkey_algo ); + const char *timestr; + char *maink; + const char *fmtstr; + + if ( !algo_name ) + algo_name = "?"; + + fmtstr = _(" (main key ID %08lX)"); + maink = m_alloc ( strlen (fmtstr) + 20 ); + if( keyid[2] && keyid[3] && keyid[0] != keyid[2] + && keyid[1] != keyid[3] ) + sprintf( maink, fmtstr, (ulong)keyid[3] ); + else + *maink = 0; + + uid = get_user_id ( keyid, &uidlen ); + timestr = strtimestamp (pk->timestamp); + fmtstr = _("You need a passphrase to unlock the" + " secret key for user:\n" + "\"%.*s\"\n" + "%u-bit %s key, ID %08lX, created %s%s\n" ); + atext = m_alloc ( 100 + strlen (fmtstr) + + uidlen + 15 + strlen(algo_name) + 8 + + strlen (timestr) + strlen (maink) ); + sprintf (atext, fmtstr, + uidlen, uid, + nbits_from_pk (pk), algo_name, (ulong)keyid[1], timestr, + maink ); + m_free (uid); + m_free (maink); + + { + size_t dummy; + fingerprint_from_pk( pk, fpr, &dummy ); + have_fpr = 1; + } + + } + else if (mode == 2 ) + atext = m_strdup ( _("Repeat passphrase\n") ); + else + atext = m_strdup ( _("Enter passphrase\n") ); + + if (!prot) + { /* old style protocol */ + n = 4 + 20 + strlen (atext); + u32tobuf (buf, n ); + u32tobuf (buf+4, GPGA_PROT_GET_PASSPHRASE ); + memcpy (buf+8, fpr, 20 ); + if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) ) + goto failure; + m_free (atext); atext = NULL; + + /* get response */ + if ( readn ( fd, buf, 12, &nread ) ) + goto failure; + + if ( nread < 8 ) + { + log_error ( "response from agent too short\n" ); + goto failure; + } + n = buftou32 ( buf ); + reply = buftou32 ( buf + 4 ); + if ( reply == GPGA_PROT_GOT_PASSPHRASE ) + { + size_t pwlen; + size_t nn; + + if ( nread < 12 || n < 8 ) + { + log_error ( "response from agent too short\n" ); + goto failure; + } + pwlen = buftou32 ( buf + 8 ); + nread -= 12; + n -= 8; + if ( pwlen > n || n > 1000 ) + { + log_error (_("passphrase too long\n")); + /* or protocol error */ + goto failure; + } + /* we read the whole block in one chunk to give no hints + * on how long the passhrase actually is - this wastes some bytes + * but because we already have this padding we should not loosen + * this by issuing 2 read calls */ + pw = m_alloc_secure ( n+1 ); + if ( readn ( fd, pw, n, &nn ) ) + goto failure; + if ( n != nn ) + { + log_error (_("invalid response from agent\n")); + goto failure; + } + pw[pwlen] = 0; /* make a C String */ + agent_close (fd); + free_public_key( pk ); +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif + m_free (orig_codeset); + return pw; + } + else if ( reply == GPGA_PROT_CANCELED ) + { + log_info ( _("cancelled by user\n") ); + if (canceled) + *canceled = 1; + } + else + log_error ( _("problem with the agent: agent returns 0x%lx\n"), + (ulong)reply ); + } + else + { /* The new Assuan protocol */ + char *line, *p; + const unsigned char *s; + int i; + + if (!tryagain_text) + tryagain_text = "X"; + else + tryagain_text = _(tryagain_text); + + /* We allocate 2 time the needed space for atext so that there + is nenough space for escaping */ + line = m_alloc (15 + 46 + + 3*strlen (tryagain_text) + 3*strlen (atext) + 2); + strcpy (line, "GET_PASSPHRASE "); + p = line+15; + if (!mode && have_fpr) + { + for (i=0; i < 20; i++, p +=2 ) + sprintf (p, "%02X", fpr[i]); + } + else + *p++ = 'X'; /* no caching */ + *p++ = ' '; + for (i=0, s=tryagain_text; *s; s++) + { + if (*s < ' ' || *s == '+') + { + sprintf (p, "%%%02X", *s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p++ = ' '; + *p++ = 'X'; /* Use the standard prompt */ + *p++ = ' '; + /* copy description */ + for (i=0, s= atext; *s; s++) + { + if (*s < ' ' || *s == '+') + { + sprintf (p, "%%%02X", *s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p++ = '\n'; + i = writen (fd, line, p - line); + m_free (line); + if (i) + goto failure; + m_free (atext); atext = NULL; + + /* get response */ + pw = m_alloc_secure (500); + nread = readline (fd, pw, 499); + if (nread < 3) + goto failure; + + 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 */ + agent_close (fd); + free_public_key( pk ); +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif + m_free (orig_codeset); + return pw; + } + else if (nread > 7 && !memcmp (pw, "ERR 111", 7) + && (pw[7] == ' ' || pw[7] == '\n') ) + { + log_info (_("cancelled by user\n") ); + if (canceled) + *canceled = 1; + } + else + { + log_error (_("problem with the agent - disabling agent use\n")); + opt.use_agent = 0; + } + } + + + failure: +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif + m_free (atext); + if ( fd != -1 ) + agent_close (fd); + m_free (pw ); + free_public_key( pk ); + + return NULL; +#endif /* Posix or W32 */ +} + +/* + * Clear the cached passphrase + */ +void +passphrase_clear_cache ( u32 *keyid, int algo ) +{ +#if defined(__riscos__) + return ; +#else + size_t n; + char buf[200]; + int fd = -1; + size_t nread; + u32 reply; + PKT_public_key *pk; + byte fpr[MAX_FINGERPRINT_LEN]; + int prot; + +#if MAX_FINGERPRINT_LEN < 20 +#error agent needs a 20 byte fingerprint +#endif + + if (!opt.use_agent) + return; + + pk = m_alloc_clear ( sizeof *pk ); + memset (fpr, 0, MAX_FINGERPRINT_LEN ); + if( !keyid || get_pubkey( pk, keyid ) ) + { + log_debug ("oops, no key in passphrase_clear_cache\n"); + goto failure; /* oops: no key for some reason */ + } + + { + size_t dummy; + fingerprint_from_pk( pk, fpr, &dummy ); + } + + if ( (fd = agent_open (&prot)) == -1 ) + goto failure; + + if (!prot) + { + n = 4 + 20; + u32tobuf (buf, n ); + u32tobuf (buf+4, GPGA_PROT_CLEAR_PASSPHRASE ); + memcpy (buf+8, fpr, 20 ); + if ( writen ( fd, buf, 28 ) ) + goto failure; + + /* get response */ + if ( readn ( fd, buf, 8, &nread ) ) + goto failure; + + if ( nread < 8 ) { + log_error ( "response from agent too short\n" ); + goto failure; + } + + reply = buftou32 ( buf + 4 ); + if ( reply != GPGA_PROT_OKAY && reply != GPGA_PROT_NO_PASSPHRASE ) + { + log_error ( _("problem with the agent: agent returns 0x%lx\n"), + (ulong)reply ); + } + } + else + { /* The assuan protocol */ + char *line, *p; + int i; + + line = m_alloc (17 + 40 + 2); + strcpy (line, "CLEAR_PASSPHRASE "); + p = line+17; + for (i=0; i < 20; i++, p +=2 ) + sprintf (p, "%02X", fpr[i]); + *p++ = '\n'; + i = writen (fd, line, p - line); + m_free (line); + if (i) + goto failure; + + /* get response */ + nread = readline (fd, buf, DIM(buf)-1); + if (nread < 3) + goto failure; + + if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) + ; + else + { + log_error (_("problem with the agent - disabling agent use\n")); + opt.use_agent = 0; + } + } + + failure: + if (fd != -1) + agent_close (fd); + free_public_key( pk ); +#endif /* Posix or W32 */ +} + + + + +/**************** + * Get a passphrase for the secret key with KEYID, display TEXT + * if the user needs to enter the passphrase. + * mode 0 = standard, 1 = same but don't show key info, + * 2 = create new passphrase + * Returns: a DEK with a session key; caller must free + * or NULL if the passphrase was not correctly repeated. + * (only for mode 2) + * a dek->keylen of 0 means: no passphrase entered. + * (only for mode 2) + * + * pubkey_algo is only informational. Note that TRYAGAIN_TEXT must + * not be translated as this is done within this function (required to + * switch to utf-8 when the agent is in use). If CANCELED is not + * NULL, it is set to 1 if the user choosed to cancel the operation, + * otherwise it will be set to 0. + */ +DEK * +passphrase_to_dek( u32 *keyid, int pubkey_algo, + int cipher_algo, STRING2KEY *s2k, int mode, + const char *tryagain_text, int *canceled) +{ + char *pw = NULL; + DEK *dek; + STRING2KEY help_s2k; + + if (canceled) + *canceled = 0; + + if( !s2k ) { + /* This is used for the old rfc1991 mode + * Note: This must match the code in encode.c with opt.rfc1991 set */ + s2k = &help_s2k; + s2k->mode = 0; + s2k->hash_algo = opt.s2k_digest_algo; + } + + if( !next_pw && is_status_enabled() ) { + char buf[50]; + + if( keyid ) { + u32 used_kid[2]; + char *us; + + if( keyid[2] && keyid[3] ) { + used_kid[0] = keyid[2]; + used_kid[1] = keyid[3]; + } + else { + used_kid[0] = keyid[0]; + used_kid[1] = keyid[1]; + } + + us = get_long_user_id_string( keyid ); + write_status_text( STATUS_USERID_HINT, us ); + m_free(us); + + sprintf( buf, "%08lX%08lX %08lX%08lX %d 0", + (ulong)keyid[0], (ulong)keyid[1], + (ulong)used_kid[0], (ulong)used_kid[1], + pubkey_algo ); + + write_status_text( STATUS_NEED_PASSPHRASE, buf ); + } + else { + sprintf( buf, "%d %d %d", cipher_algo, s2k->mode, s2k->hash_algo ); + write_status_text( STATUS_NEED_PASSPHRASE_SYM, buf ); + } + } + + if( keyid && !opt.batch && !next_pw && mode!=1 ) { + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + size_t n; + char *p; + + tty_printf(_("\nYou need a passphrase to unlock the secret key for\n" + "user: \"") ); + p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ); + m_free(p); + tty_printf("\"\n"); + + if( !get_pubkey( pk, keyid ) ) { + const char *s = pubkey_algo_to_string( pk->pubkey_algo ); + tty_printf( _("%u-bit %s key, ID %08lX, created %s"), + nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1], + strtimestamp(pk->timestamp) ); + if( keyid[2] && keyid[3] && keyid[0] != keyid[2] + && keyid[1] != keyid[3] ) + tty_printf( _(" (main key ID %08lX)"), (ulong)keyid[3] ); + tty_printf("\n"); + } + + tty_printf("\n"); + free_public_key( pk ); + } + + agent_died: + if( next_pw ) { + pw = next_pw; + next_pw = NULL; + } + else if ( opt.use_agent ) { + pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, + tryagain_text, canceled ); + if (!pw) + { + if (!opt.use_agent) + goto agent_died; + pw = m_strdup (""); + } + if( *pw && mode == 2 ) { + char *pw2 = agent_get_passphrase ( keyid, 2, NULL, canceled ); + if (!pw2) + { + if (!opt.use_agent) + { + m_free (pw); + pw = NULL; + goto agent_died; + } + pw2 = m_strdup (""); + } + if( strcmp(pw, pw2) ) { + m_free(pw2); + m_free(pw); + return NULL; + } + m_free(pw2); + } + } + else if( fd_passwd ) { + pw = m_alloc_secure( strlen(fd_passwd)+1 ); + strcpy( pw, fd_passwd ); + } + else if( opt.batch ) { + log_error(_("can't query password in batchmode\n")); + pw = m_strdup( "" ); /* return an empty passphrase */ + } + else { + pw = cpr_get_hidden("passphrase.enter", _("Enter passphrase: ") ); + tty_kill_prompt(); + if( mode == 2 && !cpr_enabled() ) { + char *pw2 = cpr_get_hidden("passphrase.repeat", + _("Repeat passphrase: ") ); + tty_kill_prompt(); + if( strcmp(pw, pw2) ) { + m_free(pw2); + m_free(pw); + return NULL; + } + m_free(pw2); + } + } + + if( !pw || !*pw ) + write_status( STATUS_MISSING_PASSPHRASE ); + + dek = m_alloc_secure_clear ( sizeof *dek ); + dek->algo = cipher_algo; + if( !*pw && mode == 2 ) + dek->keylen = 0; + else + hash_passphrase( dek, pw, s2k, mode==2 ); + m_free(last_pw); + last_pw = pw; + return dek; +} + + +/**************** + * Hash a passphrase using the supplied s2k. If create is true, create + * a new salt or what else must be filled into the s2k for a new key. + * always needs: dek->algo, s2k->mode, s2k->hash_algo. + */ +static void +hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) +{ + MD_HANDLE md; + int pass, i; + int used = 0; + int pwlen = strlen(pw); + + assert( s2k->hash_algo ); + dek->keylen = cipher_get_keylen( dek->algo ) / 8; + if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) + BUG(); + + md = md_open( s2k->hash_algo, 1); + for(pass=0; used < dek->keylen ; pass++ ) { + if( pass ) { + md_reset(md); + for(i=0; i < pass; i++ ) /* preset the hash context */ + md_putc(md, 0 ); + } + + if( s2k->mode == 1 || s2k->mode == 3 ) { + int len2 = pwlen + 8; + ulong count = len2; + + if( create && !pass ) { + randomize_buffer(s2k->salt, 8, 1); + if( s2k->mode == 3 ) + s2k->count = 96; /* 65536 iterations */ + } + + if( s2k->mode == 3 ) { + count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6); + if( count < len2 ) + count = len2; + } + /* a little bit complicated because we need a ulong for count */ + while( count > len2 ) { /* maybe iterated+salted */ + md_write( md, s2k->salt, 8 ); + md_write( md, pw, pwlen ); + count -= len2; + } + if( count < 8 ) + md_write( md, s2k->salt, count ); + else { + md_write( md, s2k->salt, 8 ); + count -= 8; + md_write( md, pw, count ); + } + } + else + md_write( md, pw, pwlen ); + md_final( md ); + i = md_digest_length( s2k->hash_algo ); + if( i > dek->keylen - used ) + i = dek->keylen - used; + memcpy( dek->key+used, md_read(md, s2k->hash_algo), i ); + used += i; + } + md_close(md); +} + diff --git a/g10/photoid.c b/g10/photoid.c new file mode 100644 index 000000000..b311bfa09 --- /dev/null +++ b/g10/photoid.c @@ -0,0 +1,333 @@ +/* photoid.c - photo ID handling code + * 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 <string.h> +#ifdef __MINGW32__ +# include <windows.h> +# ifndef VER_PLATFORM_WIN32_WINDOWS +# define VER_PLATFORM_WIN32_WINDOWS 1 +# endif +#endif +#include "packet.h" +#include "status.h" +#include "exec.h" +#include "keydb.h" +#include "util.h" +#include "i18n.h" +#include "iobuf.h" +#include "memory.h" +#include "options.h" +#include "main.h" +#include "photoid.h" + +/* Generate a new photo id packet, or return NULL if canceled */ +PKT_user_id *generate_photo_id(PKT_public_key *pk) +{ + PKT_user_id *uid; + int error=1,i; + unsigned int len; + char *filename=NULL; + byte *photo=NULL; + byte header[16]; + IOBUF file; + + header[0]=0x10; /* little side of photo header length */ + header[1]=0; /* big side of photo header length */ + header[2]=1; /* 1 == version of photo header */ + header[3]=1; /* 1 == JPEG */ + + for(i=4;i<16;i++) /* The reserved bytes */ + header[i]=0; + +#define EXTRA_UID_NAME_SPACE 71 + uid=m_alloc_clear(sizeof(*uid)+71); + + printf(_("\nPick an image to use for your photo ID. " + "The image must be a JPEG file.\n" + "Remember that the image is stored within your public key. " + "If you use a\n" + "very large picture, your key will become very large as well!\n" + "Keeping the image close to 240x288 is a good size to use.\n")); + + while(photo==NULL) + { + printf("\n"); + + m_free(filename); + + filename=cpr_get("photoid.jpeg.add", + _("Enter JPEG filename for photo ID: ")); + + if(strlen(filename)==0) + goto scram; + + file=iobuf_open(filename); + if(!file) + { + log_error(_("Unable to open photo \"%s\": %s\n"), + filename,strerror(errno)); + continue; + } + + len=iobuf_get_filelength(file); + if(len>6144) + { + printf("This JPEG is really large (%d bytes) !\n",len); + if(!cpr_get_answer_is_yes("photoid.jpeg.size", + _("Are you sure you want to use it (y/N)? "))) + { + iobuf_close(file); + continue; + } + } + + photo=m_alloc(len); + iobuf_read(file,photo,len); + iobuf_close(file); + + /* Is it a JPEG? */ + if(photo[0]!=0xFF || photo[1]!=0xD8 || + photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F') + { + log_error(_("\"%s\" is not a JPEG file\n"),filename); + m_free(photo); + photo=NULL; + continue; + } + + /* Build the packet */ + build_attribute_subpkt(uid,1,photo,len,header,16); + parse_attribute_subpkts(uid); + make_attribute_uidname(uid, EXTRA_UID_NAME_SPACE); + + /* Showing the photo is not safe when noninteractive since the + "user" may not be able to dismiss a viewer window! */ + if(opt.command_fd==-1) + { + show_photos(uid->attribs,uid->numattribs,pk,NULL); + switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay", + _("Is this photo correct (y/N/q)? "))) + { + case -1: + goto scram; + case 0: + free_attributes(uid); + m_free(photo); + photo=NULL; + continue; + } + } + } + + error=0; + uid->ref=1; + + scram: + m_free(filename); + m_free(photo); + + if(error) + { + free_attributes(uid); + m_free(uid); + return NULL; + } + + return uid; +} + +/* Returns 0 for error, 1 for valid */ +int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len) +{ + u16 headerlen; + + if(attr->len<3) + return 0; + + /* For historical reasons (i.e. "oops!"), the header length is + little endian. */ + headerlen=(attr->data[1]<<8) | attr->data[0]; + + if(headerlen>attr->len) + return 0; + + if(type && attr->len>=4) + { + if(attr->data[2]==1) /* header version 1 */ + *type=attr->data[3]; + else + *type=0; + } + + *len=attr->len-headerlen; + + if(*len==0) + return 0; + + return 1; +} + +/* style==0 for extension, 1 for name, 2 for MIME type. Remember that + the "name" style string could be used in a user ID name field, so + make sure it is not too big (see parse-packet.c:parse_attribute). + Extensions should be 3 characters long for the best cross-platform + compatibility. */ +char *image_type_to_string(byte type,int style) +{ + char *string; + + switch(type) + { + case 1: /* jpeg */ + if(style==0) + string="jpg"; + else if(style==1) + string="jpeg"; + else + string="image/jpeg"; + break; + + default: + if(style==0) + string="bin"; + else if(style==1) + string="unknown"; + else + string="image/x-unknown"; + break; + } + + return string; +} + +#if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER) +static const char *get_default_photo_command(void) +{ +#if defined(__MINGW32__) + OSVERSIONINFO osvi; + + memset(&osvi,0,sizeof(osvi)); + osvi.dwOSVersionInfoSize=sizeof(osvi); + GetVersionEx(&osvi); + + if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS) + return "start /w %i"; + else + return "cmd /c start /w %i"; +#elif defined(__APPLE__) + /* OS X. This really needs more than just __APPLE__. */ + return "open %I"; +#elif defined(__riscos__) + return "Filer_Run %I"; +#else + return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin"; +#endif +} +#endif + +void show_photos(const struct user_attribute *attrs, + int count,PKT_public_key *pk,PKT_secret_key *sk) +{ +#ifndef DISABLE_PHOTO_VIEWER + int i; + struct expando_args args; + u32 len; + u32 kid[2]={0,0}; + + memset(&args,0,sizeof(args)); + args.pk=pk; + args.sk=sk; + + if(pk) + keyid_from_pk(pk,kid); + else if(sk) + keyid_from_sk(sk,kid); + + for(i=0;i<count;i++) + if(attrs[i].type==ATTRIB_IMAGE && + parse_image_header(&attrs[i],&args.imagetype,&len)) + { + char *command,*name; + struct exec_info *spawn; + int offset=attrs[i].len-len; + +#ifdef FIXED_PHOTO_VIEWER + opt.photo_viewer=FIXED_PHOTO_VIEWER; +#else + if(!opt.photo_viewer) + opt.photo_viewer=get_default_photo_command(); +#endif + + /* make command grow */ + command=pct_expando(opt.photo_viewer,&args); + if(!command) + goto fail; + + name=m_alloc(16+strlen(EXTSEP_S)+ + strlen(image_type_to_string(args.imagetype,0))+1); + + /* Make the filename. Notice we are not using the image + encoding type for more than cosmetics. Most external image + viewers can handle a multitude of types, and even if one + cannot understand a particular type, we have no way to know + which. The spec permits this, by the way. -dms */ + +#ifdef USE_ONLY_8DOT3 + sprintf(name,"%08lX" EXTSEP_S "%s",(ulong)kid[1], + image_type_to_string(args.imagetype,0)); +#else + sprintf(name,"%08lX%08lX" EXTSEP_S "%s",(ulong)kid[0],(ulong)kid[1], + image_type_to_string(args.imagetype,0)); +#endif + + if(exec_write(&spawn,NULL,command,name,1,1)!=0) + { + m_free(name); + goto fail; + } + +#ifdef __riscos__ + riscos_set_filetype_by_mimetype(spawn->tempfile_in, + image_type_to_string(args.imagetype,2)); +#endif + + m_free(name); + + fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild); + + if(exec_read(spawn)!=0) + { + exec_finish(spawn); + goto fail; + } + + if(exec_finish(spawn)!=0) + goto fail; + } + + return; + + fail: + log_error(_("unable to display photo ID!\n")); +#endif +} diff --git a/g10/photoid.h b/g10/photoid.h new file mode 100644 index 000000000..187ca5ba2 --- /dev/null +++ b/g10/photoid.h @@ -0,0 +1,34 @@ +/* photoid.h + * 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 + */ + +/* Photo ID functions */ + +#ifndef _PHOTOID_H_ +#define _PHOTOID_H_ + +#include "packet.h" + +PKT_user_id *generate_photo_id(PKT_public_key *pk); +int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len); +char *image_type_to_string(byte type,int style); +void show_photos(const struct user_attribute *attrs, + int count,PKT_public_key *pk,PKT_secret_key *sk); + +#endif /* !_PHOTOID_H_ */ diff --git a/g10/pkclist.c b/g10/pkclist.c new file mode 100644 index 000000000..e6c826963 --- /dev/null +++ b/g10/pkclist.c @@ -0,0 +1,1376 @@ +/* pkclist.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 "trustdb.h" +#include "ttyio.h" +#include "status.h" +#include "photoid.h" +#include "i18n.h" + + +#define CONTROL_D ('D' - 'A' + 1) + + +/**************** + * Show the revocation reason as it is stored with the given signature + */ +static void +do_show_revocation_reason( PKT_signature *sig ) +{ + size_t n, nn; + const byte *p, *pp; + int seq = 0; + const char *text; + + while( (p = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REVOC_REASON, + &n, &seq, NULL )) ) { + if( !n ) + continue; /* invalid - just skip it */ + + if( *p == 0 ) + text = _("No reason specified"); + else if( *p == 0x01 ) + text = _("Key is superseded"); + else if( *p == 0x02 ) + text = _("Key has been compromised"); + else if( *p == 0x03 ) + text = _("Key is no longer used"); + else if( *p == 0x20 ) + text = _("User ID is no longer valid"); + else + text = NULL; + + log_info( _("reason for revocation: ") ); + if( text ) + fputs( text, log_stream() ); + else + fprintf( log_stream(), "code=%02x", *p ); + putc( '\n', log_stream() ); + n--; p++; + pp = NULL; + do { + /* We don't want any empty lines, so skip them */ + while( n && *p == '\n' ) { + p++; + n--; + } + if( n ) { + pp = memchr( p, '\n', n ); + nn = pp? pp - p : n; + log_info( _("revocation comment: ") ); + print_string( log_stream(), p, nn, 0 ); + putc( '\n', log_stream() ); + p += nn; n -= nn; + } + } while( pp ); + } +} + +/* Mode 0: try and find the revocation based on the pk (i.e. check + subkeys, etc.) Mode 1: use only the revocation on the main pk */ + +void +show_revocation_reason( PKT_public_key *pk, int mode ) +{ + /* Hmmm, this is not so easy becuase we have to duplicate the code + * used in the trustbd to calculate the keyflags. We need to find + * a clean way to check revocation certificates on keys and + * signatures. And there should be no duplicate code. Because we + * enter this function only when the trustdb told us that we have + * a revoked key, we could simply look for a revocation cert and + * display this one, when there is only one. Let's try to do this + * until we have a better solution. */ + KBNODE node, keyblock = NULL; + byte fingerprint[MAX_FINGERPRINT_LEN]; + size_t fingerlen; + int rc; + + /* get the keyblock */ + fingerprint_from_pk( pk, fingerprint, &fingerlen ); + rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen ); + if( rc ) { /* that should never happen */ + log_debug( "failed to get the keyblock\n"); + return; + } + + for( node=keyblock; node; node = node->next ) { + if( (mode && node->pkt->pkttype == PKT_PUBLIC_KEY) || + ( ( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + && !cmp_public_keys( node->pkt->pkt.public_key, pk ) ) ) + break; + } + if( !node ) { + log_debug("Oops, PK not in keyblock\n"); + release_kbnode( keyblock ); + return; + } + /* now find the revocation certificate */ + for( node = node->next; node ; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; + if( node->pkt->pkttype == PKT_SIGNATURE + && (node->pkt->pkt.signature->sig_class == 0x20 + || node->pkt->pkt.signature->sig_class == 0x28 ) ) { + /* FIXME: we should check the signature here */ + do_show_revocation_reason ( node->pkt->pkt.signature ); + break; + } + } + + /* We didn't find it, so check if the whole key is revoked */ + if(!node && !mode) + show_revocation_reason(pk,1); + + release_kbnode( keyblock ); +} + + +static void +show_paths (const PKT_public_key *pk, int only_first ) +{ + log_debug("not yet implemented\n"); +#if 0 + void *context = NULL; + unsigned otrust, validity; + int last_level, level; + + last_level = 0; + while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){ + char *p; + int c, rc; + size_t n; + u32 keyid[2]; + PKT_public_key *pk ; + + if( level < last_level && only_first ) + break; + last_level = level; + + rc = keyid_from_lid( lid, keyid ); + + if( rc ) { + log_error("ooops: can't get keyid for lid %lu\n", lid); + return; + } + + pk = m_alloc_clear( sizeof *pk ); + rc = get_pubkey( pk, keyid ); + if( rc ) { + log_error("key %08lX: public key not found: %s\n", + (ulong)keyid[1], g10_errstr(rc) ); + return; + } + + tty_printf("%*s%4u%c/%08lX.%lu %s \"", + level*2, "", + nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), + (ulong)keyid[1], lid, datestr_from_pk( pk ) ); + + c = trust_letter(otrust); + if( c ) + putchar( c ); + else + printf( "%02x", otrust ); + putchar('/'); + c = trust_letter(validity); + if( c ) + putchar( c ); + else + printf( "%02x", validity ); + putchar(' '); + + p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ), + m_free(p); + tty_printf("\"\n"); + free_public_key( pk ); + } + enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */ +#endif + tty_printf("\n"); +} + + + + +/**************** + * mode: 0 = standard + * 1 = Without key info and additional menu option 'm' + * this does also add an option to set the key to ultimately trusted. + * Returns: + * -2 = nothing changed - caller should show some additional info + * -1 = quit operation + * 0 = nothing changed + * 1 = new ownertrust now in new_trust + */ +static int +do_edit_ownertrust (PKT_public_key *pk, int mode, + unsigned *new_trust, int defer_help ) +{ + char *p; + size_t n; + u32 keyid[2]; + int changed=0; + int quit=0; + int show=0; + int min_num; + int did_help=defer_help; + unsigned int minimum=get_min_ownertrust(pk); + + switch(minimum) + { + default: min_num=0; break; + case TRUST_UNDEFINED: min_num=1; break; + case TRUST_NEVER: min_num=2; break; + case TRUST_MARGINAL: min_num=3; break; + case TRUST_FULLY: min_num=4; break; + } + + keyid_from_pk (pk, keyid); + for(;;) { + /* a string with valid answers */ + const char *ans = _("iImMqQsS"); + + if( !did_help ) + { + if( !mode ) + { + KBNODE keyblock, un; + + tty_printf(_("No trust value assigned to:\n" + "%4u%c/%08lX %s \""), + nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), + (ulong)keyid[1], datestr_from_pk( pk ) ); + p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ), + m_free(p); + tty_printf("\"\n"); + + keyblock = get_pubkeyblock (keyid); + if (!keyblock) + BUG (); + for (un=keyblock; un; un = un->next) { + if (un->pkt->pkttype != PKT_USER_ID ) + continue; + if (un->pkt->pkt.user_id->is_revoked ) + continue; + if (un->pkt->pkt.user_id->is_expired ) + continue; + /* Only skip textual primaries */ + if (un->pkt->pkt.user_id->is_primary && + !un->pkt->pkt.user_id->attrib_data ) + continue; + + if((opt.verify_options&VERIFY_SHOW_PHOTOS) + && un->pkt->pkt.user_id->attrib_data) + show_photos(un->pkt->pkt.user_id->attribs, + un->pkt->pkt.user_id->numattribs,pk,NULL); + + tty_printf (" %s", _(" aka \"")); + tty_print_utf8_string (un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len ); + tty_printf("\"\n"); + } + + print_fingerprint (pk, NULL, 2); + tty_printf("\n"); + } + /* This string also used in keyedit.c:sign_uids */ + tty_printf (_( + "Please decide how far you trust this user to correctly\n" + "verify other users' keys (by looking at passports,\n" + "checking fingerprints from different sources...)?\n\n")); + if(min_num<=1) + tty_printf (_(" %d = I don't know\n"), 1); + if(min_num<=2) + tty_printf (_(" %d = I do NOT trust\n"), 2); + if(min_num<=3) + tty_printf (_(" %d = I trust marginally\n"), 3); + if(min_num<=4) + tty_printf (_(" %d = I trust fully\n"), 4); + if (mode) + tty_printf (_(" %d = I trust ultimately\n"), 5); +#if 0 + /* not yet implemented */ + tty_printf (_(" i = please show me more information\n") ); +#endif + if( mode ) + tty_printf(_(" m = back to the main menu\n")); + else + { + tty_printf(_(" s = skip this key\n")); + tty_printf(_(" q = quit\n")); + } + tty_printf("\n"); + if(minimum) + tty_printf(_("The minimum trust level for this key is: %s\n\n"), + trust_value_to_string(minimum)); + did_help = 1; + } + if( strlen(ans) != 8 ) + BUG(); + p = cpr_get("edit_ownertrust.value",_("Your decision? ")); + trim_spaces(p); + cpr_kill_prompt(); + if( !*p ) + did_help = 0; + else if( *p && p[1] ) + ; + else if( !p[1] && ((*p >= '0'+min_num) && *p <= (mode?'5':'4')) ) + { + unsigned int trust; + switch( *p ) + { + case '1': trust = TRUST_UNDEFINED; break; + case '2': trust = TRUST_NEVER ; break; + case '3': trust = TRUST_MARGINAL ; break; + case '4': trust = TRUST_FULLY ; break; + case '5': trust = TRUST_ULTIMATE ; break; + default: BUG(); + } + if (trust == TRUST_ULTIMATE + && !cpr_get_answer_is_yes ("edit_ownertrust.set_ultimate.okay", + _("Do you really want to set this key" + " to ultimate trust? "))) + ; /* no */ + else + { + *new_trust = trust; + changed = 1; + break; + } + } +#if 0 + /* not yet implemented */ + else if( *p == ans[0] || *p == ans[1] ) + { + tty_printf(_("Certificates leading to an ultimately trusted key:\n")); + show = 1; + break; + } +#endif + else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) + { + break ; /* back to the menu */ + } + else if( !mode && (*p == ans[6] || *p == ans[7] ) ) + { + break; /* skip */ + } + else if( !mode && (*p == ans[4] || *p == ans[5] ) ) + { + quit = 1; + break ; /* back to the menu */ + } + m_free(p); p = NULL; + } + m_free(p); + return show? -2: quit? -1 : changed; +} + +/* + * Display a menu to change the ownertrust of the key PK (which should + * be a primary key). + * For mode values see do_edit_ownertrust () + */ +int +edit_ownertrust (PKT_public_key *pk, int mode ) +{ + unsigned int trust; + int no_help = 0; + + for(;;) + { + switch ( do_edit_ownertrust (pk, mode, &trust, no_help ) ) + { + case -1: /* quit */ + return -1; + case -2: /* show info */ + show_paths(pk, 1); + no_help = 1; + break; + case 1: /* trust value set */ + trust &= ~TRUST_FLAG_DISABLED; + trust |= get_ownertrust (pk) & TRUST_FLAG_DISABLED; + update_ownertrust (pk, trust ); + return 1; + default: + return 0; + } + } +} + + +/**************** + * Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL + * Returns: true if we trust. + */ +static int +do_we_trust( PKT_public_key *pk, unsigned int *trustlevel ) +{ + unsigned int trustmask = 0; + + /* FIXME: get_pubkey_byname already checks the validity and won't + * return keys which are either expired or revoked - so these + * question here won't get triggered. We have to find a solution + * for this. It might make sense to have a function in getkey.c + * which does only the basic checks and returns even revoked and + * expired keys. This fnction could then also returhn a list of + * keys if the speicified name is ambiguous + */ + if( (*trustlevel & TRUST_FLAG_REVOKED) ) { + log_info(_("key %08lX: key has been revoked!\n"), + (ulong)keyid_from_pk( pk, NULL) ); + show_revocation_reason( pk, 0 ); + if( opt.batch ) + return 0; /* no */ + + if( !cpr_get_answer_is_yes("revoked_key.override", + _("Use this key anyway? ")) ) + return 0; /* no */ + trustmask |= TRUST_FLAG_REVOKED; + } + if( (*trustlevel & TRUST_FLAG_SUB_REVOKED) ) { + log_info(_("key %08lX: subkey has been revoked!\n"), + (ulong)keyid_from_pk( pk, NULL) ); + show_revocation_reason( pk, 0 ); + if( opt.batch ) + return 0; + + if( !cpr_get_answer_is_yes("revoked_key.override", + _("Use this key anyway? ")) ) + return 0; + trustmask |= TRUST_FLAG_SUB_REVOKED; + } + *trustlevel &= ~trustmask; + + if( opt.trust_model==TM_ALWAYS ) { + if( opt.verbose ) + log_info("No trust check due to --trust-model always option\n"); + return 1; + } + + switch( (*trustlevel & TRUST_MASK) ) { + case TRUST_EXPIRED: + log_info(_("%08lX: key has expired\n"), + (ulong)keyid_from_pk( pk, NULL) ); + return 0; /* no */ + + default: + log_error ("invalid trustlevel %u returned from validation layer\n", + *trustlevel); + /* fall thru */ + case TRUST_UNKNOWN: + case TRUST_UNDEFINED: + log_info(_("%08lX: There is no assurance this key belongs " + "to the named user\n"),(ulong)keyid_from_pk( pk, NULL) ); + return 0; /* no */ + + /* No way to get here? */ + case TRUST_NEVER: + log_info(_("%08lX: We do NOT trust this key\n"), + (ulong)keyid_from_pk( pk, NULL) ); + return 0; /* no */ + + case TRUST_MARGINAL: + log_info(_("%08lX: There is limited assurance this key belongs " + "to the named user\n"),(ulong)keyid_from_pk(pk,NULL)); + return 1; /* yes */ + + case TRUST_FULLY: + if( opt.verbose ) + log_info(_("This key probably belongs to the named user\n")); + return 1; /* yes */ + + case TRUST_ULTIMATE: + if( opt.verbose ) + log_info(_("This key belongs to us\n")); + return 1; /* yes */ + } + + return 1; /* yes */ +} + + + +/**************** + * wrapper around do_we_trust, so we can ask whether to use the + * key anyway. + */ +static int +do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel ) +{ + int rc; + + rc = do_we_trust( pk, &trustlevel ); + + if( (trustlevel & TRUST_FLAG_REVOKED) && !rc ) + return 0; + if( (trustlevel & TRUST_FLAG_SUB_REVOKED) && !rc ) + return 0; + + if( !opt.batch && !rc ) { + u32 keyid[2]; + + keyid_from_pk( pk, keyid); + tty_printf( "%4u%c/%08lX %s \"", + nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), + (ulong)keyid[1], datestr_from_pk( pk ) ); + /* If the pk was chosen by a particular user ID, this is the + one to ask about. */ + if(pk->user_id) + tty_print_utf8_string(pk->user_id->name,pk->user_id->len); + else + { + size_t n; + char *p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ); + m_free(p); + } + tty_printf("\"\n"); + print_fingerprint (pk, NULL, 2); + tty_printf("\n"); + + tty_printf(_( +"It is NOT certain that the key belongs to the person named\n" +"in the user ID. If you *really* know what you are doing,\n" +"you may answer the next question with yes\n\n")); + + if( cpr_get_answer_is_yes("untrusted_key.override", + _("Use this key anyway? ")) ) + rc = 1; + + /* Hmmm: Should we set a flag to tell the user about + * his decision the next time he encrypts for this recipient? + */ + } + else if( opt.trust_model==TM_ALWAYS && !rc ) { + if( !opt.quiet ) + log_info(_("WARNING: Using untrusted key!\n")); + rc = 1; + } + return rc; +} + + + +/**************** + * Check whether we can trust this signature. + * Returns: Error if we shall not trust this signatures. + */ +int +check_signatures_trust( PKT_signature *sig ) +{ + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + unsigned int trustlevel; + int rc=0; + + rc = get_pubkey( pk, sig->keyid ); + if (rc) + { /* this should not happen */ + log_error("Ooops; the key vanished - can't check the trust\n"); + rc = G10ERR_NO_PUBKEY; + goto leave; + } + + if ( opt.trust_model==TM_ALWAYS ) + { + if( !opt.quiet ) + log_info(_("WARNING: Using untrusted key!\n")); + if (opt.with_fingerprint) + print_fingerprint (pk, NULL, 1); + goto leave; + } + + trustlevel = get_validity (pk, NULL); + + if ( (trustlevel & TRUST_FLAG_REVOKED) ) + { + write_status( STATUS_KEYREVOKED ); + log_info(_("WARNING: This key has been revoked by its owner!\n")); + log_info(_(" This could mean that the signature is forgery.\n")); + show_revocation_reason( pk, 0 ); + } + else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) ) + { + write_status( STATUS_KEYREVOKED ); + log_info(_("WARNING: This subkey has been revoked by its owner!\n")); + show_revocation_reason( pk, 0 ); + } + + if ((trustlevel & TRUST_FLAG_DISABLED)) + log_info (_("Note: This key has been disabled.\n")); + + switch ( (trustlevel & TRUST_MASK) ) + { + case TRUST_EXPIRED: + log_info(_("Note: This key has expired!\n")); + print_fingerprint (pk, NULL, 1); + break; + + default: + log_error ("invalid trustlevel %u returned from validation layer\n", + trustlevel); + /* fall thru */ + case TRUST_UNKNOWN: + case TRUST_UNDEFINED: + write_status( STATUS_TRUST_UNDEFINED ); + log_info(_("WARNING: This key is not certified with" + " a trusted signature!\n")); + log_info(_(" There is no indication that the " + "signature belongs to the owner.\n" )); + print_fingerprint (pk, NULL, 1); + break; + + case TRUST_NEVER: + /* currently we won't get that status */ + write_status( STATUS_TRUST_NEVER ); + log_info(_("WARNING: We do NOT trust this key!\n")); + log_info(_(" The signature is probably a FORGERY.\n")); + if (opt.with_fingerprint) + print_fingerprint (pk, NULL, 1); + rc = G10ERR_BAD_SIGN; + break; + + case TRUST_MARGINAL: + write_status( STATUS_TRUST_MARGINAL ); + log_info(_("WARNING: This key is not certified with" + " sufficiently trusted signatures!\n")); + log_info(_(" It is not certain that the" + " signature belongs to the owner.\n" )); + print_fingerprint (pk, NULL, 1); + break; + + case TRUST_FULLY: + write_status( STATUS_TRUST_FULLY ); + if (opt.with_fingerprint) + print_fingerprint (pk, NULL, 1); + break; + + case TRUST_ULTIMATE: + write_status( STATUS_TRUST_ULTIMATE ); + if (opt.with_fingerprint) + print_fingerprint (pk, NULL, 1); + break; + } + + leave: + free_public_key( pk ); + return rc; +} + + +void +release_pk_list( PK_LIST pk_list ) +{ + PK_LIST pk_rover; + + for( ; pk_list; pk_list = pk_rover ) { + pk_rover = pk_list->next; + free_public_key( pk_list->pk ); + m_free( pk_list ); + } +} + + +static int +key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk) +{ + for( ; pk_list; pk_list = pk_list->next) + if (cmp_public_keys(pk_list->pk, pk) == 0) + return 0; + + return -1; +} + + +/**************** + * Return a malloced string with a default reciepient if there is any + */ +static char * +default_recipient(void) +{ + PKT_secret_key *sk; + byte fpr[MAX_FINGERPRINT_LEN+1]; + size_t n; + char *p; + int i; + + if( opt.def_recipient ) + return m_strdup( opt.def_recipient ); + if( !opt.def_recipient_self ) + return NULL; + sk = m_alloc_clear( sizeof *sk ); + i = get_seckey_byname( sk, NULL, 0 ); + if( i ) { + free_secret_key( sk ); + return NULL; + } + n = MAX_FINGERPRINT_LEN; + fingerprint_from_sk( sk, fpr, &n ); + free_secret_key( sk ); + p = m_alloc( 2*n+3 ); + *p++ = '0'; + *p++ = 'x'; + for(i=0; i < n; i++ ) + sprintf( p+2*i, "%02X", fpr[i] ); + p -= 2; + return p; +} + +static int +expand_id(const char *id,STRLIST *into,unsigned int flags) +{ + struct groupitem *groups; + int count=0; + + for(groups=opt.grouplist;groups;groups=groups->next) + { + /* need strcasecmp() here, as this should be localized */ + if(strcasecmp(groups->name,id)==0) + { + STRLIST each,sl; + + /* this maintains the current utf8-ness */ + for(each=groups->values;each;each=each->next) + { + sl=add_to_strlist(into,each->d); + sl->flags=flags; + count++; + } + + break; + } + } + + return count; +} + +/* For simplicity, and to avoid potential loops, we only expand once - + you can't make an alias that points to an alias. */ +static STRLIST +expand_group(STRLIST input) +{ + STRLIST sl,output=NULL,rover; + + for(rover=input;rover;rover=rover->next) + if(expand_id(rover->d,&output,rover->flags)==0) + { + /* Didn't find any groups, so use the existing string */ + sl=add_to_strlist(&output,rover->d); + sl->flags=rover->flags; + } + + return output; +} + +int +build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) +{ + PK_LIST pk_list = NULL; + PKT_public_key *pk=NULL; + int rc=0; + int any_recipients=0; + STRLIST rov,remusr; + char *def_rec = NULL; + + if(opt.grouplist) + remusr=expand_group(rcpts); + else + remusr=rcpts; + + /* check whether there are any recipients in the list and build the + * list of the encrypt-to ones (we always trust them) */ + for( rov = remusr; rov; rov = rov->next ) { + if( !(rov->flags & 1) ) + { + any_recipients = 1; + + if((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8)) + { + log_info(_("you may not use %s while in %s mode\n"), + "--hidden-recipient", + compliance_option_string()); + + compliance_failure(); + } + } + else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { + pk = m_alloc_clear( sizeof *pk ); + pk->req_usage = use; + /* We can encrypt-to a disabled key */ + if( (rc = get_pubkey_byname( pk, rov->d, NULL, NULL, 1 )) ) { + free_public_key( pk ); pk = NULL; + log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + rov->d, strlen (rov->d), -1); + goto fail; + } + else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { + /* Skip the actual key if the key is already present + * in the list */ + if (key_present_in_pk_list(pk_list, pk) == 0) { + free_public_key(pk); pk = NULL; + log_info(_("%s: skipped: public key already present\n"), + rov->d); + } + else { + PK_LIST r; + r = m_alloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = (rov->flags&2)?1:0; + pk_list = r; + + if(r->flags&1 && (PGP2 || PGP6 || PGP7 || PGP8)) + { + log_info(_("you may not use %s while in %s mode\n"), + "--hidden-encrypt-to", + compliance_option_string()); + + compliance_failure(); + } + } + } + else { + free_public_key( pk ); pk = NULL; + log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + rov->d, strlen (rov->d), -1); + goto fail; + } + } + } + + if( !any_recipients && !opt.batch ) { /* ask */ + int have_def_rec; + char *answer=NULL; + STRLIST backlog=NULL; + + def_rec = default_recipient(); + have_def_rec = !!def_rec; + if( !have_def_rec ) + tty_printf(_( + "You did not specify a user ID. (you may use \"-r\")\n")); + for(;;) { + rc = 0; + m_free(answer); + if( have_def_rec ) { + answer = def_rec; + def_rec = NULL; + } + else if(backlog) { + answer=pop_strlist(&backlog); + } + else { + answer = cpr_get_utf8("pklist.user_id.enter", + _("\nEnter the user ID. End with an empty line: ")); + trim_spaces(answer); + cpr_kill_prompt(); + } + if( !answer || !*answer ) { + m_free(answer); + break; + } + if(expand_id(answer,&backlog,0)) + continue; + if( pk ) + free_public_key( pk ); + pk = m_alloc_clear( sizeof *pk ); + pk->req_usage = use; + rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); + if( rc ) + tty_printf(_("No such user ID.\n")); + else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { + if( have_def_rec ) { + if (key_present_in_pk_list(pk_list, pk) == 0) { + free_public_key(pk); pk = NULL; + log_info(_("skipped: public key " + "already set as default recipient\n") ); + } + else { + PK_LIST r = m_alloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = 0; /* no throwing default ids */ + pk_list = r; + } + any_recipients = 1; + continue; + } + else { + int trustlevel; + + trustlevel = get_validity (pk, pk->user_id); + if( (trustlevel & TRUST_FLAG_DISABLED) ) { + tty_printf(_("Public key is disabled.\n") ); + } + else if( do_we_trust_pre( pk, trustlevel ) ) { + /* Skip the actual key if the key is already present + * in the list */ + if (key_present_in_pk_list(pk_list, pk) == 0) { + free_public_key(pk); pk = NULL; + log_info(_("skipped: public key already set\n") ); + } + else { + PK_LIST r; + u32 keyid[2]; + + keyid_from_pk( pk, keyid); + tty_printf("Added %4u%c/%08lX %s \"", + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + (ulong)keyid[1], + datestr_from_pk( pk ) ); + if(pk->user_id) + tty_print_utf8_string(pk->user_id->name, + pk->user_id->len); + else + { + size_t n; + char *p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ); + m_free(p); + } + tty_printf("\"\n"); + + r = m_alloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = 0; /* no throwing interactive ids */ + pk_list = r; + } + any_recipients = 1; + continue; + } + } + } + m_free(def_rec); def_rec = NULL; + have_def_rec = 0; + } + if( pk ) { + free_public_key( pk ); + pk = NULL; + } + } + else if( !any_recipients && (def_rec = default_recipient()) ) { + pk = m_alloc_clear( sizeof *pk ); + pk->req_usage = use; + /* The default recipient may be disabled */ + rc = get_pubkey_byname( pk, def_rec, NULL, NULL, 1 ); + if( rc ) + log_error(_("unknown default recipient `%s'\n"), def_rec ); + else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { + /* Mark any_recipients here since the default recipient + would have been used if it wasn't already there. It + doesn't really matter if we got this key from the default + recipient or an encrypt-to. */ + any_recipients = 1; + if (key_present_in_pk_list(pk_list, pk) == 0) + log_info(_("skipped: public key already set as default recipient\n")); + else { + PK_LIST r = m_alloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = 0; /* no throwing default ids */ + pk_list = r; + } + } + if( pk ) { + free_public_key( pk ); + pk = NULL; + } + m_free(def_rec); def_rec = NULL; + } + else { + any_recipients = 0; + for(; remusr; remusr = remusr->next ) { + if( (remusr->flags & 1) ) + continue; /* encrypt-to keys are already handled */ + + pk = m_alloc_clear( sizeof *pk ); + pk->req_usage = use; + if( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0 )) ) { + free_public_key( pk ); pk = NULL; + log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + remusr->d, strlen (remusr->d), + -1); + goto fail; + } + else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { + int trustlevel; + + trustlevel = get_validity (pk, pk->user_id); + if( (trustlevel & TRUST_FLAG_DISABLED) ) { + free_public_key(pk); pk = NULL; + log_info(_("%s: skipped: public key is disabled\n"), + remusr->d); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + remusr->d, + strlen (remusr->d), + -1); + rc=G10ERR_UNU_PUBKEY; + goto fail; + } + else if( do_we_trust_pre( pk, trustlevel ) ) { + /* note: do_we_trust may have changed the trustlevel */ + + /* We have at least one valid recipient. It doesn't matters + * if this recipient is already present. */ + any_recipients = 1; + + /* Skip the actual key if the key is already present + * in the list */ + if (key_present_in_pk_list(pk_list, pk) == 0) { + free_public_key(pk); pk = NULL; + log_info(_("%s: skipped: public key already present\n"), + remusr->d); + } + else { + PK_LIST r; + r = m_alloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = (remusr->flags&2)?1:0; + pk_list = r; + } + } + else { /* we don't trust this pk */ + free_public_key( pk ); pk = NULL; + write_status_text_and_buffer (STATUS_INV_RECP, "10 ", + remusr->d, + strlen (remusr->d), + -1); + rc=G10ERR_UNU_PUBKEY; + goto fail; + } + } + else { + free_public_key( pk ); pk = NULL; + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + remusr->d, + strlen (remusr->d), + -1); + log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); + goto fail; + } + } + } + + if( !rc && !any_recipients ) { + log_error(_("no valid addressees\n")); + write_status_text (STATUS_NO_RECP, "0"); + rc = G10ERR_NO_USER_ID; + } + + fail: + + if( rc ) + release_pk_list( pk_list ); + else + *ret_pk_list = pk_list; + if(opt.grouplist) + free_strlist(remusr); + return rc; +} + + +/* In pgp6 mode, disallow all ciphers except IDEA (1), 3DES (2), and + CAST5 (3), all hashes except MD5 (1), SHA1 (2), and RIPEMD160 (3), + and all compressions except none (0) and ZIP (1). pgp7 and pgp8 + mode expands the cipher list to include AES128 (7), AES192 (8), + AES256 (9), and TWOFISH (10). pgp8 adds the SHA-256 hash (8). For + a true PGP key all of this is unneeded as they are the only items + present in the preferences subpacket, but checking here covers the + weird case of encrypting to a key that had preferences from a + different implementation which was then used with PGP. I am not + completely comfortable with this as the right thing to do, as it + slightly alters the list of what the user is supposedly requesting. + It is not against the RFC however, as the preference chosen will + never be one that the user didn't specify somewhere ("The + implementation may use any mechanism to pick an algorithm in the + intersection"), and PGP has no mechanism to fix such a broken + preference list, so I'm including it. -dms */ + +int +algo_available( preftype_t preftype, int algo, void *hint ) +{ + if( preftype == PREFTYPE_SYM ) + { + if(PGP6 && (algo != CIPHER_ALGO_IDEA + && algo != CIPHER_ALGO_3DES + && algo != CIPHER_ALGO_CAST5)) + return 0; + + if((PGP7 || PGP8) && (algo != CIPHER_ALGO_IDEA + && algo != CIPHER_ALGO_3DES + && algo != CIPHER_ALGO_CAST5 + && algo != CIPHER_ALGO_AES + && algo != CIPHER_ALGO_AES192 + && algo != CIPHER_ALGO_AES256 + && algo != CIPHER_ALGO_TWOFISH)) + return 0; + + return algo && !check_cipher_algo( algo ); + } + else if( preftype == PREFTYPE_HASH ) + { + if(hint && ((*(int *)hint) != md_digest_length(algo))) + return 0; + + if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5 + && algo != DIGEST_ALGO_SHA1 + && algo != DIGEST_ALGO_RMD160)) + return 0; + + + if(PGP8 && (algo != DIGEST_ALGO_MD5 + && algo != DIGEST_ALGO_SHA1 + && algo != DIGEST_ALGO_RMD160 + && algo != DIGEST_ALGO_SHA256)) + return 0; + + /* TIGER is not allowed any longer according to 2440bis. */ + if( RFC2440 && algo == DIGEST_ALGO_TIGER ) + return 0; + + return algo && !check_digest_algo( algo ); + } + else if( preftype == PREFTYPE_ZIP ) + { + if((PGP6 || PGP7 || PGP8) && (algo != COMPRESS_ALGO_NONE + && algo != COMPRESS_ALGO_ZIP)) + return 0; + + return !check_compress_algo( algo ); + } + else + return 0; +} + + + +/**************** + * Return -1 if we could not find an algorithm. + */ +int +select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, void *hint) +{ + PK_LIST pkr; + u32 bits[8]; + const prefitem_t *prefs; + int i, j; + int compr_hack=0; + int any; + + if( !pk_list ) + return -1; + + memset( bits, ~0, 8 * sizeof *bits ); + for( pkr = pk_list; pkr; pkr = pkr->next ) { + u32 mask[8]; + + memset( mask, 0, 8 * sizeof *mask ); + if( preftype == PREFTYPE_SYM ) { + if( PGP2 && + pkr->pk->version < 4 && + pkr->pk->selfsigversion < 4 ) + mask[0] |= (1<<1); /* IDEA is implicitly there for v3 keys + with v3 selfsigs (rfc2440:12.1) if + --pgp2 mode is on. This doesn't + mean it's actually available, of + course. */ + else + mask[0] |= (1<<2); /* 3DES is implicitly there for everyone else */ + } + else if( preftype == PREFTYPE_HASH ) { + /* While I am including this code for completeness, note + that currently --pgp2 mode locks the hash at MD5, so this + function will never even be called. Even if the hash + wasn't locked at MD5, we don't support sign+encrypt in + --pgp2 mode, and that's the only time PREFTYPE_HASH is + used anyway. -dms */ + if( PGP2 && + pkr->pk->version < 4 && + pkr->pk->selfsigversion < 4 ) + mask[0] |= (1<<1); /* MD5 is there for v3 keys with v3 + selfsigs when --pgp2 is on. */ + else + mask[0] |= (1<<2); /* SHA1 is there for everyone else */ + } + else if( preftype == PREFTYPE_ZIP ) + mask[0] |= (1<<0); /* Uncompressed is implicit */ + + if (pkr->pk->user_id) /* selected by user ID */ + prefs = pkr->pk->user_id->prefs; + else + prefs = pkr->pk->prefs; + + any = 0; + if( prefs ) { + for (i=0; prefs[i].type; i++ ) { + if( prefs[i].type == preftype ) { + mask[prefs[i].value/32] |= 1 << (prefs[i].value%32); + any = 1; + } + } + } + + if( (!prefs || !any) && preftype == PREFTYPE_ZIP ) { + mask[0] |= 3; /* asume no_compression and old pgp */ + compr_hack = 1; + } + +#if 0 + log_debug("pref mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", + (ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4], + (ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]); +#endif + for(i=0; i < 8; i++ ) + bits[i] &= mask[i]; +#if 0 + log_debug("pref bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n", + (ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4], + (ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]); +#endif + } + /* usable algorithms are now in bits + * We now use the last key from pk_list to select + * the algorithm we want to use. there are no + * preferences for the last key, we select the one + * corresponding to first set bit. + */ + i = -1; + any = 0; + + /* Can we use the requested algorithm? */ + if(request>-1 && (bits[request/32] & (1<<(request%32))) && + algo_available(preftype,request,hint)) + return request; + + /* If we have personal prefs set, use them instead of the last key */ + if(preftype==PREFTYPE_SYM && opt.personal_cipher_prefs) + prefs=opt.personal_cipher_prefs; + else if(preftype==PREFTYPE_HASH && opt.personal_digest_prefs) + prefs=opt.personal_digest_prefs; + else if(preftype==PREFTYPE_ZIP && opt.personal_compress_prefs) + prefs=opt.personal_compress_prefs; + + if( prefs ) { + for(j=0; prefs[j].type; j++ ) { + if( prefs[j].type == preftype ) { + if( (bits[prefs[j].value/32] & (1<<(prefs[j].value%32))) ) { + if( algo_available( preftype, prefs[j].value, hint ) ) { + any = 1; + i = prefs[j].value; + break; + } + } + } + } + } + if( !prefs || !any ) { + for(j=0; j < 256; j++ ) + if( (bits[j/32] & (1<<(j%32))) ) { + if( algo_available( preftype, j, hint ) ) { + i = j; + break; + } + } + } + +#if 0 + log_debug("prefs of type %d: selected %d\n", preftype, i ); +#endif + if( compr_hack && !i ) { + /* selected no compression, but we should check whether + * algorithm 1 is also available (the ordering is not relevant + * in this case). */ + if( bits[0] & (1<<1) ) + i = 1; /* yep; we can use compression algo 1 */ + } + + /* "If you are building an authentication system, the recipient + may specify a preferred signing algorithm. However, the signer + would be foolish to use a weak algorithm simply because the + recipient requests it." RFC2440:13. If we settle on MD5, and + SHA1 is also available, use SHA1 instead. Of course, if the + user intentionally chose MD5 (by putting it in their personal + prefs), then we should do what they say. */ + + if(preftype==PREFTYPE_HASH && + i==DIGEST_ALGO_MD5 && (bits[0] & (1<<DIGEST_ALGO_SHA1))) + { + i=DIGEST_ALGO_SHA1; + + if(opt.personal_digest_prefs) + for(j=0; prefs[j].type; j++ ) + if(opt.personal_digest_prefs[j].type==PREFTYPE_HASH && + opt.personal_digest_prefs[j].value==DIGEST_ALGO_MD5) + { + i=DIGEST_ALGO_MD5; + break; + } + } + + return i; +} + +/* + * Select the MDC flag from the pk_list. We can only use MDC if all recipients + * support this feature + */ +int +select_mdc_from_pklist (PK_LIST pk_list) +{ + PK_LIST pkr; + + if( !pk_list ) + return 0; + + for (pkr = pk_list; pkr; pkr = pkr->next) { + int mdc; + + if (pkr->pk->user_id) /* selected by user ID */ + mdc = pkr->pk->user_id->mdc_feature; + else + mdc = pkr->pk->mdc_feature; + if (!mdc) + return 0; /* at least one recipient does not support it */ + } + return 1; /* can be used */ +} diff --git a/g10/plaintext.c b/g10/plaintext.c new file mode 100644 index 000000000..89043026c --- /dev/null +++ b/g10/plaintext.c @@ -0,0 +1,446 @@ +/* plaintext.c - process plaintext packets + * 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> +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif + +#include "util.h" +#include "memory.h" +#include "options.h" +#include "packet.h" +#include "ttyio.h" +#include "filter.h" +#include "main.h" +#include "status.h" +#include "i18n.h" + + + +/**************** + * Handle a plaintext packet. If MFX is not NULL, update the MDs + * Note: we should use the filter stuff here, but we have to add some + * easy mimic to set a read limit, so we calculate only the + * bytes from the plaintext. + */ +int +handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, + int nooutput, int clearsig ) +{ + char *fname = NULL; + FILE *fp = NULL; + int rc = 0; + int c; + int convert = pt->mode == 't'; +#ifdef __riscos__ + int filetype = 0xfff; +#endif + + /* create the filename as C string */ + if( nooutput ) + ; + else if( opt.outfile ) { + fname = m_alloc( strlen( opt.outfile ) + 1); + strcpy(fname, opt.outfile ); + } + else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) { + log_info(_("data not saved; use option \"--output\" to save it\n")); + nooutput = 1; + } + else if( !opt.use_embedded_filename ) { + fname = make_outfile_name( iobuf_get_real_fname(pt->buf) ); + if( !fname ) + fname = ask_outfile_name( pt->name, pt->namelen ); + if( !fname ) { + rc = G10ERR_CREATE_FILE; + goto leave; + } + } + else { + fname = make_printable_string( pt->name, pt->namelen, 0 ); + } + + if( nooutput ) + ; + else if( !*fname || (*fname=='-' && !fname[1])) { + /* no filename or "-" given; write to stdout */ + fp = stdout; +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(fp) , O_BINARY ); +#endif + } + else { + while( !overwrite_filep (fname) ) { + char *tmp = ask_outfile_name (NULL, 0); + if ( !tmp || !*tmp ) { + m_free (tmp); + rc = G10ERR_CREATE_FILE; + goto leave; + } + m_free (fname); + fname = tmp; + } + } + +#ifndef __riscos__ + if( fp || nooutput ) + ; + else if( !(fp = fopen(fname,"wb")) ) { + log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + goto leave; + } +#else /* __riscos__ */ + /* Convert all '.' in fname to '/' -- we don't create directories! */ + for( c=0; fname[c]; ++c ) + if( fname[c] == '.' ) + fname[c] = '/'; + + if( fp || nooutput ) + ; + else { + fp = fopen(fname,"wb"); + if( !fp ) { + log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + if (errno == 106) + log_info("Do output file and input file have the same name?\n"); + goto leave; + } + + /* If there's a ,xxx extension in the embedded filename, + use that, else check whether the user input (in fname) + has a ,xxx appended, then use that in preference */ + if( (c = riscos_get_filetype_from_string( pt->name, + pt->namelen )) != -1 ) + filetype = c; + if( (c = riscos_get_filetype_from_string( fname, + strlen(fname) )) != -1 ) + filetype = c; + riscos_set_filetype_by_number(fname, filetype); + } +#endif /* __riscos__ */ + + if( !pt->is_partial ) { + /* we have an actual length (which might be zero). */ + assert( !clearsig ); + if( convert ) { /* text mode */ + for( ; pt->len; pt->len-- ) { + if( (c = iobuf_get(pt->buf)) == -1 ) { + log_error("Problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); + rc = G10ERR_READ_FILE; + goto leave; + } + if( mfx->md ) + md_putc(mfx->md, c ); +#ifndef HAVE_DOSISH_SYSTEM + if( c == '\r' ) /* convert to native line ending */ + continue; /* fixme: this hack might be too simple */ +#endif + if( fp ) { + if( putc( c, fp ) == EOF ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + } + } + else { /* binary mode */ + byte *buffer = m_alloc( 32768 ); + while( pt->len ) { + int len = pt->len > 32768 ? 32768 : pt->len; + len = iobuf_read( pt->buf, buffer, len ); + if( len == -1 ) { + log_error("Problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); + rc = G10ERR_READ_FILE; + m_free( buffer ); + goto leave; + } + if( mfx->md ) + md_write( mfx->md, buffer, len ); + if( fp ) { + if( fwrite( buffer, 1, len, fp ) != len ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + m_free( buffer ); + goto leave; + } + } + pt->len -= len; + } + m_free( buffer ); + } + } + else if( !clearsig ) { + if( convert ) { /* text mode */ + while( (c = iobuf_get(pt->buf)) != -1 ) { + if( mfx->md ) + md_putc(mfx->md, c ); +#ifndef HAVE_DOSISH_SYSTEM + if( convert && c == '\r' ) + continue; /* fixme: this hack might be too simple */ +#endif + if( fp ) { + if( putc( c, fp ) == EOF ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + } + } + else { /* binary mode */ + byte *buffer = m_alloc( 32768 ); + int eof; + for( eof=0; !eof; ) { + /* Why do we check for len < 32768: + * If we won't, we would practically read 2 EOFs but + * the first one has already popped the block_filter + * off and therefore we don't catch the boundary. + * So, always assume EOF if iobuf_read returns less bytes + * then requested */ + int len = iobuf_read( pt->buf, buffer, 32768 ); + if( len == -1 ) + break; + if( len < 32768 ) + eof = 1; + if( mfx->md ) + md_write( mfx->md, buffer, len ); + if( fp ) { + if( fwrite( buffer, 1, len, fp ) != len ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + m_free( buffer ); + goto leave; + } + } + } + m_free( buffer ); + } + pt->buf = NULL; + } + else { /* clear text signature - don't hash the last cr,lf */ + int state = 0; + + while( (c = iobuf_get(pt->buf)) != -1 ) { + if( fp ) { + if( putc( c, fp ) == EOF ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } + if( !mfx->md ) + continue; + if( state == 2 ) { + md_putc(mfx->md, '\r' ); + md_putc(mfx->md, '\n' ); + state = 0; + } + if( !state ) { + if( c == '\r' ) + state = 1; + else if( c == '\n' ) + state = 2; + else + md_putc(mfx->md, c ); + } + else if( state == 1 ) { + if( c == '\n' ) + state = 2; + else { + md_putc(mfx->md, '\r' ); + if( c == '\r' ) + state = 1; + else { + state = 0; + md_putc(mfx->md, c ); + } + } + } + } + pt->buf = NULL; + } + + if( fp && fp != stdout && fclose(fp) ) { + log_error("Error closing `%s': %s\n", fname, strerror(errno) ); + fp = NULL; + rc = G10ERR_WRITE_FILE; + goto leave; + } + fp = NULL; + + leave: + if( fp && fp != stdout ) + fclose(fp); + m_free(fname); + return rc; +} + +static void +do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode ) +{ + text_filter_context_t tfx; + int c; + + if( textmode ) { + memset( &tfx, 0, sizeof tfx); + iobuf_push_filter( fp, text_filter, &tfx ); + } + if( md2 ) { /* work around a strange behaviour in pgp2 */ + /* It seems that at least PGP5 converts a single CR to a CR,LF too */ + int lc = -1; + while( (c = iobuf_get(fp)) != -1 ) { + if( c == '\n' && lc == '\r' ) + md_putc(md2, c); + else if( c == '\n' ) { + md_putc(md2, '\r'); + md_putc(md2, c); + } + else if( c != '\n' && lc == '\r' ) { + md_putc(md2, '\n'); + md_putc(md2, c); + } + else + md_putc(md2, c); + + if( md ) + md_putc(md, c ); + lc = c; + } + } + else { + while( (c = iobuf_get(fp)) != -1 ) { + if( md ) + md_putc(md, c ); + } + } +} + + +/**************** + * Ask for the detached datafile and calculate the digest from it. + * INFILE is the name of the input file. + */ +int +ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, + const char *inname, int textmode ) +{ + progress_filter_context_t pfx; + char *answer = NULL; + IOBUF fp; + int rc = 0; + + fp = open_sigfile( inname, &pfx ); /* open default file */ + + if( !fp && !opt.batch ) { + int any=0; + tty_printf(_("Detached signature.\n")); + do { + m_free(answer); + answer = cpr_get("detached_signature.filename", + _("Please enter name of data file: ")); + cpr_kill_prompt(); + if( any && !*answer ) { + rc = G10ERR_READ_FILE; + goto leave; + } + fp = iobuf_open(answer); + if( !fp && errno == ENOENT ) { + tty_printf("No such file, try again or hit enter to quit.\n"); + any++; + } + else if( !fp ) { + log_error("can't open `%s': %s\n", answer, strerror(errno) ); + rc = G10ERR_READ_FILE; + goto leave; + } + } while( !fp ); + } + + if( !fp ) { + if( opt.verbose ) + log_info(_("reading stdin ...\n")); + fp = iobuf_open( NULL ); + assert(fp); + } + do_hash( md, md2, fp, textmode ); + iobuf_close(fp); + + leave: + m_free(answer); + return rc; +} + + + +/**************** + * Hash the given files and append the hash to hash context md. + * If FILES is NULL, hash stdin. + */ +int +hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, + const char *sigfilename, int textmode ) +{ + progress_filter_context_t pfx; + IOBUF fp; + STRLIST sl; + + if( !files ) { + /* check whether we can open the signed material */ + fp = open_sigfile( sigfilename, &pfx ); + if( fp ) { + do_hash( md, md2, fp, textmode ); + iobuf_close(fp); + return 0; + } + log_error (_("no signed data\n")); + return G10ERR_OPEN_FILE; + } + + + for (sl=files; sl; sl = sl->next ) { + fp = iobuf_open( sl->d ); + if( !fp ) { + log_error(_("can't open signed data `%s'\n"), + print_fname_stdin(sl->d)); + return G10ERR_OPEN_FILE; + } + handle_progress (&pfx, fp, sl->d); + do_hash( md, md2, fp, textmode ); + iobuf_close(fp); + } + + return 0; +} diff --git a/g10/progress.c b/g10/progress.c new file mode 100644 index 000000000..bb414faae --- /dev/null +++ b/g10/progress.c @@ -0,0 +1,117 @@ +/* progress.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 <stdio.h> + +#include "iobuf.h" +#include "filter.h" +#include "status.h" +#include "util.h" +#include "options.h" + +/**************** + * The filter is used to report progress to the user. + */ +int +progress_filter (void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len) +{ + int rc = 0; + progress_filter_context_t *pfx = opaque; + + if (control == IOBUFCTRL_INIT) + { + char buffer[50]; + + pfx->last = 0; + pfx->offset = 0; + pfx->last_time = make_timestamp (); + + sprintf (buffer, "%.20s ? %lu %lu", + pfx->what? pfx->what : "?", + pfx->offset, + pfx->total); + write_status_text (STATUS_PROGRESS, buffer); + } + else if (control == IOBUFCTRL_UNDERFLOW) + { + u32 timestamp = make_timestamp (); + int len = iobuf_read (a, buf, *ret_len); + + if (len >= 0) + { + pfx->offset += len; + *ret_len = len; + } + else + { + *ret_len = 0; + rc = -1; + } + if ((len == -1 && pfx->offset != pfx->last) + || timestamp - pfx->last_time > 0) + { + char buffer[50]; + + sprintf (buffer, "%.20s ? %lu %lu", + pfx->what? pfx->what : "?", + pfx->offset, + pfx->total); + write_status_text (STATUS_PROGRESS, buffer); + + pfx->last = pfx->offset; + pfx->last_time = timestamp; + } + } + else if (control == IOBUFCTRL_FREE) + { + /* Note, that we must always dealloc resources of a filter + within the filter handler and not anywhere else. (We set it + to NULL and check all uses just in case.) */ + m_free (pfx->what); + pfx->what = NULL; + } + else if (control == IOBUFCTRL_DESC) + *(char**)buf = "progress_filter"; + return rc; +} + +void +handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name) +{ + off_t filesize = 0; + + if (!opt.enable_progress_filter) + return; + + if (!is_status_enabled ()) + return; + + if (name && *name && !(*name == '-' && !name[1])) + filesize = iobuf_get_filelength (inp); + else if (opt.set_filesize) + filesize = opt.set_filesize; + + /* register the progress filter */ + pfx->what = m_strdup (name ? name : "stdin"); + pfx->total = filesize; + iobuf_push_filter (inp, progress_filter, pfx); +} diff --git a/g10/revoke.c b/g10/revoke.c new file mode 100644 index 000000000..a45d2d623 --- /dev/null +++ b/g10/revoke.c @@ -0,0 +1,690 @@ +/* revoke.c + * 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 "keydb.h" +#include "memory.h" +#include "util.h" +#include "main.h" +#include "ttyio.h" +#include "status.h" +#include "i18n.h" + + +struct revocation_reason_info { + int code; + char *desc; +}; + + +int +revocation_reason_build_cb( PKT_signature *sig, void *opaque ) +{ + struct revocation_reason_info *reason = opaque; + char *ud = NULL; + byte *buffer; + size_t buflen = 1; + + if(!reason) + return 0; + + if( reason->desc ) { + ud = native_to_utf8( reason->desc ); + buflen += strlen(ud); + } + buffer = m_alloc( buflen ); + *buffer = reason->code; + if( ud ) { + memcpy(buffer+1, ud, strlen(ud) ); + m_free( ud ); + } + + build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen ); + m_free( buffer ); + return 0; +} + +/* Outputs a minimal pk (as defined by 2440) from a keyblock. A + minimal pk consists of the public key packet and a user ID. We try + and pick a user ID that has a uid signature, and include it if + possible. */ +static int +export_minimal_pk(IOBUF out,KBNODE keyblock, + PKT_signature *revsig,PKT_signature *revkey) +{ + KBNODE node; + PACKET pkt; + PKT_user_id *uid=NULL; + PKT_signature *selfsig=NULL; + u32 keyid[2]; + int rc; + + node=find_kbnode(keyblock,PKT_PUBLIC_KEY); + if(!node) + { + log_error(_("key incomplete\n")); + return G10ERR_GENERAL; + } + + keyid_from_pk(node->pkt->pkt.public_key,keyid); + + pkt=*node->pkt; + rc=build_packet(out,&pkt); + if(rc) + { + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + return rc; + } + + init_packet(&pkt); + pkt.pkttype=PKT_SIGNATURE; + + /* the revocation itself, if any. 2440 likes this to come first. */ + if(revsig) + { + pkt.pkt.signature=revsig; + rc=build_packet(out,&pkt); + if(rc) + { + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + return rc; + } + } + + /* If a revkey in a 1F sig is present, include it too */ + if(revkey) + { + pkt.pkt.signature=revkey; + rc=build_packet(out,&pkt); + if(rc) + { + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + return rc; + } + } + + while(!selfsig) + { + KBNODE signode; + + node=find_next_kbnode(node,PKT_USER_ID); + if(!node) + { + /* We're out of user IDs - none were self-signed. */ + if(uid) + break; + else + { + log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]); + return G10ERR_GENERAL; + } + } + + if(node->pkt->pkt.user_id->attrib_data) + continue; + + uid=node->pkt->pkt.user_id; + signode=node; + + while((signode=find_next_kbnode(signode,PKT_SIGNATURE))) + { + if(keyid[0]==signode->pkt->pkt.signature->keyid[0] && + keyid[1]==signode->pkt->pkt.signature->keyid[1] && + IS_UID_SIG(signode->pkt->pkt.signature)) + { + selfsig=signode->pkt->pkt.signature; + break; + } + } + } + + pkt.pkttype=PKT_USER_ID; + pkt.pkt.user_id=uid; + + rc=build_packet(out,&pkt); + if(rc) + { + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + return rc; + } + + if(selfsig) + { + pkt.pkttype=PKT_SIGNATURE; + pkt.pkt.signature=selfsig; + + rc=build_packet(out,&pkt); + if(rc) + { + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + return rc; + } + } + + return 0; +} + +/**************** + * Generate a revocation certificate for UNAME via a designated revoker + */ +int +gen_desig_revoke( const char *uname ) +{ + int rc = 0; + armor_filter_context_t afx; + PKT_public_key *pk = NULL; + PKT_secret_key *sk = NULL; + PKT_signature *sig = NULL; + IOBUF out = NULL; + struct revocation_reason_info *reason = NULL; + KEYDB_HANDLE kdbhd; + KEYDB_SEARCH_DESC desc; + KBNODE keyblock=NULL,node; + u32 keyid[2]; + int i,any=0; + + if( opt.batch ) { + log_error(_("sorry, can't do this in batch mode\n")); + return G10ERR_GENERAL; + } + + memset( &afx, 0, sizeof afx); + + kdbhd = keydb_new (0); + classify_user_id (uname, &desc); + rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + if (rc) { + log_error (_("key `%s' not found: %s\n"),uname, g10_errstr (rc)); + goto leave; + } + + rc = keydb_get_keyblock (kdbhd, &keyblock ); + if( rc ) { + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + goto leave; + } + + /* To parse the revkeys */ + merge_keys_and_selfsig(keyblock); + + /* get the key from the keyblock */ + node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); + if( !node ) + BUG (); + + pk=node->pkt->pkt.public_key; + + keyid_from_pk(pk,keyid); + + /* Are we a designated revoker for this key? */ + + if(!pk->revkey && pk->numrevkeys) + BUG(); + + for(i=0;i<pk->numrevkeys;i++) + { + if(sk) + free_secret_key(sk); + + sk=m_alloc_clear(sizeof(*sk)); + + rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN); + + /* We have the revocation key */ + if(!rc) + { + PKT_signature *revkey = NULL; + + any = 1; + + print_pubkey_info (pk); + tty_printf ("\n"); + + tty_printf (_("To be revoked by:\n")); + print_seckey_info (sk); + + if(pk->revkey[i].class&0x40) + tty_printf(_("(This is a sensitive revocation key)\n")); + tty_printf("\n"); + + if( !cpr_get_answer_is_yes("gen_desig_revoke.okay", + _("Create a revocation certificate for this key? ")) ) + continue; + + /* get the reason for the revocation (this is always v4) */ + reason = ask_revocation_reason( 1, 0, 1 ); + if( !reason ) + continue; + + rc = check_secret_key( sk, 0 ); + if( rc ) + continue; + + if( !opt.armor ) + tty_printf(_("ASCII armored output forced.\n")); + + if( (rc = open_outfile( NULL, 0, &out )) ) + goto leave; + + afx.what = 1; + afx.hdrlines = "Comment: A revocation certificate should follow\n"; + iobuf_push_filter( out, armor_filter, &afx ); + + /* create it */ + rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, + 0, 0, 0, + revocation_reason_build_cb, reason ); + if( rc ) { + log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); + goto leave; + } + + /* Spit out a minimal pk as well, since otherwise there is + no way to know which key to attach this revocation to. + Also include the direct key signature that contains + this revocation key. We're allowed to include + sensitive revocation keys along with a revocation, as + this may be the only time the recipient has seen it. + Note that this means that if we have multiple different + sensitive revocation keys in a given direct key + signature, we're going to include them all here. This + is annoying, but the good outweighs the bad, since + without including this a sensitive revoker can't really + do their job. People should not include multiple + sensitive revocation keys in one signature: 2440 says + "Note that it may be appropriate to isolate this + subpacket within a separate signature so that it is not + combined with other subpackets that need to be + exported." -dms */ + + while(!revkey) + { + KBNODE signode; + + signode=find_next_kbnode(node,PKT_SIGNATURE); + if(!signode) + break; + + node=signode; + + if(keyid[0]==signode->pkt->pkt.signature->keyid[0] && + keyid[1]==signode->pkt->pkt.signature->keyid[1] && + IS_KEY_SIG(signode->pkt->pkt.signature)) + { + int j; + + for(j=0;j<signode->pkt->pkt.signature->numrevkeys;j++) + { + if(pk->revkey[i].class== + signode->pkt->pkt.signature->revkey[j]->class && + pk->revkey[i].algid== + signode->pkt->pkt.signature->revkey[j]->algid && + memcmp(pk->revkey[i].fpr, + signode->pkt->pkt.signature->revkey[j]->fpr, + MAX_FINGERPRINT_LEN)==0) + { + revkey=signode->pkt->pkt.signature; + break; + } + } + } + } + + if(!revkey) + BUG(); + + rc=export_minimal_pk(out,keyblock,sig,revkey); + if(rc) + goto leave; + + /* and issue a usage notice */ + tty_printf(_("Revocation certificate created.\n")); + break; + } + } + + if(!any) + log_error(_("no revocation keys found for `%s'\n"),uname); + + leave: + if( pk ) + free_public_key( pk ); + if( sk ) + free_secret_key( sk ); + if( sig ) + free_seckey_enc( sig ); + + if( rc ) + iobuf_cancel(out); + else + iobuf_close(out); + release_revocation_reason_info( reason ); + return rc; +} + + +/**************** + * Generate a revocation certificate for UNAME + */ +int +gen_revoke( const char *uname ) +{ + int rc = 0; + armor_filter_context_t afx; + PACKET pkt; + PKT_secret_key *sk; /* used as pointer into a kbnode */ + PKT_public_key *pk = NULL; + PKT_signature *sig = NULL; + u32 sk_keyid[2]; + IOBUF out = NULL; + KBNODE keyblock = NULL, pub_keyblock = NULL; + KBNODE node; + KEYDB_HANDLE kdbhd; + struct revocation_reason_info *reason = NULL; + KEYDB_SEARCH_DESC desc; + + if( opt.batch ) { + log_error(_("sorry, can't do this in batch mode\n")); + return G10ERR_GENERAL; + } + + memset( &afx, 0, sizeof afx); + init_packet( &pkt ); + + /* search the userid: + * We don't want the whole getkey stuff here but the entire keyblock + */ + kdbhd = keydb_new (1); + classify_user_id (uname, &desc); + rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + if (rc) { + log_error (_("secret key `%s' not found: %s\n"), + uname, g10_errstr (rc)); + goto leave; + } + + rc = keydb_get_keyblock (kdbhd, &keyblock ); + if( rc ) { + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + goto leave; + } + + /* get the keyid from the keyblock */ + node = find_kbnode( keyblock, PKT_SECRET_KEY ); + if( !node ) + BUG (); + + /* fixme: should make a function out of this stuff, + * it's used all over the source */ + sk = node->pkt->pkt.secret_key; + keyid_from_sk( sk, sk_keyid ); + print_seckey_info (sk); + + pk = m_alloc_clear( sizeof *pk ); + + /* FIXME: We should get the public key direct from the secret one */ + + pub_keyblock=get_pubkeyblock(sk_keyid); + if(!pub_keyblock) + { + log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) ); + goto leave; + } + + node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY); + if(!node) + BUG(); + + pk=node->pkt->pkt.public_key; + + if( cmp_public_secret_key( pk, sk ) ) { + log_error(_("public key does not match secret key!\n") ); + rc = G10ERR_GENERAL; + goto leave; + } + + tty_printf("\n"); + if( !cpr_get_answer_is_yes("gen_revoke.okay", + _("Create a revocation certificate for this key? ")) ){ + rc = 0; + goto leave; + } + + if(sk->version>=4 || opt.force_v4_certs) { + /* get the reason for the revocation */ + reason = ask_revocation_reason( 1, 0, 1 ); + if( !reason ) { /* user decided to cancel */ + rc = 0; + goto leave; + } + } + + switch( is_secret_key_protected( sk ) ) { + case -1: + log_error(_("unknown protection algorithm\n")); + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + tty_printf(_("NOTE: This key is not protected!\n")); + break; + default: + rc = check_secret_key( sk, 0 ); + break; + } + if( rc ) + goto leave; + + + if( !opt.armor ) + tty_printf(_("ASCII armored output forced.\n")); + + if( (rc = open_outfile( NULL, 0, &out )) ) + goto leave; + + afx.what = 1; + afx.hdrlines = "Comment: A revocation certificate should follow\n"; + iobuf_push_filter( out, armor_filter, &afx ); + + /* create it */ + rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, + opt.force_v4_certs?4:0, 0, 0, + revocation_reason_build_cb, reason ); + if( rc ) { + log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); + goto leave; + } + + if(PGP2 || PGP6 || PGP7 || PGP8) + { + /* Use a minimal pk for PGPx mode, since PGP can't import bare + revocation certificates. */ + rc=export_minimal_pk(out,pub_keyblock,sig,NULL); + if(rc) + goto leave; + } + else + { + init_packet( &pkt ); + pkt.pkttype = PKT_SIGNATURE; + pkt.pkt.signature = sig; + + rc = build_packet( out, &pkt ); + if( rc ) { + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + goto leave; + } + } + + /* and issue a usage notice */ + tty_printf(_("Revocation certificate created.\n\n" +"Please move it to a medium which you can hide away; if Mallory gets\n" +"access to this certificate he can use it to make your key unusable.\n" +"It is smart to print this certificate and store it away, just in case\n" +"your media become unreadable. But have some caution: The print system of\n" +"your machine might store the data and make it available to others!\n")); + + leave: + if( sig ) + free_seckey_enc( sig ); + release_kbnode( keyblock ); + release_kbnode( pub_keyblock ); + keydb_release (kdbhd); + if( rc ) + iobuf_cancel(out); + else + iobuf_close(out); + release_revocation_reason_info( reason ); + return rc; +} + + + +struct revocation_reason_info * +ask_revocation_reason( int key_rev, int cert_rev, int hint ) +{ + int code=-1; + char *description = NULL; + struct revocation_reason_info *reason; + const char *text_0 = _("No reason specified"); + const char *text_1 = _("Key has been compromised"); + const char *text_2 = _("Key is superseded"); + const char *text_3 = _("Key is no longer used"); + const char *text_4 = _("User ID is no longer valid"); + const char *code_text = NULL; + + do { + code=-1; + m_free(description); + description = NULL; + + tty_printf(_("Please select the reason for the revocation:\n")); + tty_printf( " 0 = %s\n", text_0 ); + if( key_rev ) + tty_printf(" 1 = %s\n", text_1 ); + if( key_rev ) + tty_printf(" 2 = %s\n", text_2 ); + if( key_rev ) + tty_printf(" 3 = %s\n", text_3 ); + if( cert_rev ) + tty_printf(" 4 = %s\n", text_4 ); + tty_printf( " Q = %s\n", _("Cancel") ); + if( hint ) + tty_printf(_("(Probably you want to select %d here)\n"), hint ); + + while(code==-1) { + int n; + char *answer = cpr_get("ask_revocation_reason.code", + _("Your decision? ")); + trim_spaces( answer ); + cpr_kill_prompt(); + if( *answer == 'q' || *answer == 'Q') + return NULL; /* cancel */ + if( hint && !*answer ) + n = hint; + else if(!isdigit( *answer ) ) + n = -1; + else + n = atoi(answer); + m_free(answer); + if( n == 0 ) { + code = 0x00; /* no particular reason */ + code_text = text_0; + } + else if( key_rev && n == 1 ) { + code = 0x02; /* key has been compromised */ + code_text = text_1; + } + else if( key_rev && n == 2 ) { + code = 0x01; /* key is superseded */ + code_text = text_2; + } + else if( key_rev && n == 3 ) { + code = 0x03; /* key is no longer used */ + code_text = text_3; + } + else if( cert_rev && n == 4 ) { + code = 0x20; /* uid is no longer valid */ + code_text = text_4; + } + else + tty_printf(_("Invalid selection.\n")); + } + + tty_printf(_("Enter an optional description; " + "end it with an empty line:\n") ); + for(;;) { + char *answer = cpr_get("ask_revocation_reason.text", "> " ); + trim_trailing_ws( answer, strlen(answer) ); + cpr_kill_prompt(); + if( !*answer ) { + m_free(answer); + break; + } + + { + char *p = make_printable_string( answer, strlen(answer), 0 ); + m_free(answer); + answer = p; + } + + if( !description ) + description = m_strdup(answer); + else { + char *p = m_alloc( strlen(description) + strlen(answer) + 2 ); + strcpy(stpcpy(stpcpy( p, description),"\n"),answer); + m_free(description); + description = p; + } + m_free(answer); + } + + tty_printf(_("Reason for revocation: %s\n"), code_text ); + if( !description ) + tty_printf(_("(No description given)\n") ); + else + tty_printf("%s\n", description ); + + } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay", + _("Is this okay? ")) ); + + reason = m_alloc( sizeof *reason ); + reason->code = code; + reason->desc = description; + return reason; +} + +void +release_revocation_reason_info( struct revocation_reason_info *reason ) +{ + if( reason ) { + m_free( reason->desc ); + m_free( reason ); + } +} diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c new file mode 100644 index 000000000..76f0ee28d --- /dev/null +++ b/g10/seckey-cert.c @@ -0,0 +1,400 @@ +/* seckey-cert.c - secret key certificate packet 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 <string.h> +#include <assert.h> +#include "util.h" +#include "memory.h" +#include "packet.h" +#include "mpi.h" +#include "keydb.h" +#include "cipher.h" +#include "main.h" +#include "options.h" +#include "i18n.h" +#include "status.h" + + +static int +do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, + int *canceled ) +{ + byte *buffer; + u16 csum=0; + int i, res; + unsigned nbytes; + + if( sk->is_protected ) { /* remove the protection */ + DEK *dek = NULL; + u32 keyid[4]; /* 4! because we need two of them */ + CIPHER_HANDLE cipher_hd=NULL; + PKT_secret_key *save_sk; + + if( sk->protect.s2k.mode == 1001 ) { + log_info(_("secret key parts are not available\n")); + return G10ERR_GENERAL; + } + if( sk->protect.algo == CIPHER_ALGO_NONE ) + BUG(); + if( check_cipher_algo( sk->protect.algo ) ) { + log_info(_("protection algorithm %d%s is not supported\n"), + sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" ); + if (sk->protect.algo==CIPHER_ALGO_IDEA) + { + write_status (STATUS_RSA_OR_IDEA); + idea_cipher_warn (0); + } + return G10ERR_CIPHER_ALGO; + } + keyid_from_sk( sk, keyid ); + keyid[2] = keyid[3] = 0; + if( !sk->is_primary ) { + keyid[2] = sk->main_keyid[0]; + keyid[3] = sk->main_keyid[1]; + } + dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo, + &sk->protect.s2k, mode, + tryagain_text, canceled ); + if (!dek && canceled && *canceled) + return G10ERR_GENERAL; + + cipher_hd = cipher_open( sk->protect.algo, + CIPHER_MODE_AUTO_CFB, 1); + cipher_setkey( cipher_hd, dek->key, dek->keylen ); + m_free(dek); + save_sk = copy_secret_key( NULL, sk ); + cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); + csum = 0; + if( sk->version >= 4 ) { + int ndata; + byte *p, *data; + u16 csumc = 0; + + i = pubkey_get_npkey(sk->pubkey_algo); + assert( mpi_is_opaque( sk->skey[i] ) ); + p = mpi_get_opaque( sk->skey[i], &ndata ); + if ( ndata > 1 ) + csumc = p[ndata-2] << 8 | p[ndata-1]; + data = m_alloc_secure( ndata ); + cipher_decrypt( cipher_hd, data, p, ndata ); + mpi_free( sk->skey[i] ); sk->skey[i] = NULL ; + p = data; + if (sk->protect.sha1chk) { + /* This is the new SHA1 checksum method to detect + tampering with the key as used by the Klima/Rosa + attack */ + sk->csum = 0; + csum = 1; + if( ndata < 20 ) + log_error("not enough bytes for SHA-1 checksum\n"); + else { + MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1); + if (!h) + BUG(); /* algo not available */ + md_write (h, data, ndata - 20); + md_final (h); + if (!memcmp (md_read (h, DIGEST_ALGO_SHA1), + data + ndata - 20, 20) ) { + /* digest does match. We have to keep the old + style checksum in sk->csum, so that the + test used for unprotected keys does work. + This test gets used when we are adding new + keys. */ + sk->csum = csum = checksum (data, ndata-20); + } + md_close (h); + } + } + else { + if( ndata < 2 ) { + log_error("not enough bytes for checksum\n"); + sk->csum = 0; + csum = 1; + } + else { + csum = checksum( data, ndata-2); + sk->csum = data[ndata-2] << 8 | data[ndata-1]; + if ( sk->csum != csum ) { + /* This is a PGP 7.0.0 workaround */ + sk->csum = csumc; /* take the encrypted one */ + } + } + } + + /* must check it here otherwise the mpi_read_xx would fail + because the length may have an arbitrary value */ + if( sk->csum == csum ) { + for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + nbytes = ndata; + sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 ); + ndata -= nbytes; + p += nbytes; + } + /* Note: at this point ndata should be 2 for a simple + checksum or 20 for the sha1 digest */ + } + m_free(data); + } + else { + for(i=pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + byte *p; + int ndata; + unsigned int dummy; + + assert (mpi_is_opaque (sk->skey[i])); + p = mpi_get_opaque (sk->skey[i], &ndata); + assert (ndata >= 2); + assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2); + buffer = m_alloc_secure (ndata); + cipher_sync (cipher_hd); + buffer[0] = p[0]; + buffer[1] = p[1]; + cipher_decrypt (cipher_hd, buffer+2, p+2, ndata-2); + csum += checksum (buffer, ndata); + mpi_free (sk->skey[i]); + dummy = ndata; + sk->skey[i] = mpi_read_from_buffer (buffer, &dummy, 1); + assert (sk->skey[i]); + m_free (buffer); +/* csum += checksum_mpi (sk->skey[i]); */ + } + } + cipher_close( cipher_hd ); + /* now let's see whether we have used the right passphrase */ + if( csum != sk->csum ) { + copy_secret_key( sk, save_sk ); + passphrase_clear_cache ( keyid, sk->pubkey_algo ); + free_secret_key( save_sk ); + return G10ERR_BAD_PASS; + } + /* the checksum may fail, so we also check the key itself */ + res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey ); + if( res ) { + copy_secret_key( sk, save_sk ); + passphrase_clear_cache ( keyid, sk->pubkey_algo ); + free_secret_key( save_sk ); + return G10ERR_BAD_PASS; + } + free_secret_key( save_sk ); + sk->is_protected = 0; + } + else { /* not protected, assume it is okay if the checksum is okay */ + csum = 0; + for(i=pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + csum += checksum_mpi( sk->skey[i] ); + } + if( csum != sk->csum ) + return G10ERR_CHECKSUM; + } + + return 0; +} + + + +/**************** + * Check the secret key + * Ask up to 3 (or n) times for a correct passphrase + * If n is negative, disable the key info prompt and make n=abs(n) + */ +int +check_secret_key( PKT_secret_key *sk, int n ) +{ + int rc = G10ERR_BAD_PASS; + int i,mode; + + if(n<0) + { + n=abs(n); + mode=1; + } + else + mode=0; + + if( n < 1 ) + n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */ + + for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) { + int canceled = 0; + const char *tryagain = NULL; + if (i) { + tryagain = N_("Invalid passphrase; please try again"); + log_info (_("%s ...\n"), _(tryagain)); + } + rc = do_check( sk, tryagain, mode, &canceled ); + if( rc == G10ERR_BAD_PASS && is_status_enabled() ) { + u32 kid[2]; + char buf[50]; + + keyid_from_sk( sk, kid ); + sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]); + write_status_text( STATUS_BAD_PASSPHRASE, buf ); + } + if( have_static_passphrase() || canceled) + break; + } + + if( !rc ) + write_status( STATUS_GOOD_PASSPHRASE ); + + return rc; +} + +/**************** + * check whether the secret key is protected. + * Returns: 0 not protected, -1 on error or the protection algorithm + */ +int +is_secret_key_protected( PKT_secret_key *sk ) +{ + return sk->is_protected? sk->protect.algo : 0; +} + + + +/**************** + * Protect the secret key with the passphrase from DEK + */ +int +protect_secret_key( PKT_secret_key *sk, DEK *dek ) +{ + int i,j, rc = 0; + byte *buffer; + unsigned nbytes; + u16 csum; + + if( !dek ) + return 0; + + if( !sk->is_protected ) { /* okay, apply the protection */ + CIPHER_HANDLE cipher_hd=NULL; + + if( check_cipher_algo( sk->protect.algo ) ) + rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */ + else { + print_cipher_algo_note( sk->protect.algo ); + cipher_hd = cipher_open( sk->protect.algo, + CIPHER_MODE_AUTO_CFB, 1 ); + if( cipher_setkey( cipher_hd, dek->key, dek->keylen ) ) + log_info(_("WARNING: Weak key detected" + " - please change passphrase again.\n")); + sk->protect.ivlen = cipher_get_blocksize( sk->protect.algo ); + assert( sk->protect.ivlen <= DIM(sk->protect.iv) ); + if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 ) + BUG(); /* yes, we are very careful */ + randomize_buffer(sk->protect.iv, sk->protect.ivlen, 1); + cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); + if( sk->version >= 4 ) { + byte *bufarr[PUBKEY_MAX_NSKEY]; + unsigned narr[PUBKEY_MAX_NSKEY]; + unsigned nbits[PUBKEY_MAX_NSKEY]; + int ndata=0; + byte *p, *data; + + for(j=0, i = pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) { + assert( !mpi_is_opaque( sk->skey[i] ) ); + bufarr[j] = mpi_get_buffer( sk->skey[i], &narr[j], NULL ); + nbits[j] = mpi_get_nbits( sk->skey[i] ); + ndata += narr[j] + 2; + } + for( ; j < PUBKEY_MAX_NSKEY; j++ ) + bufarr[j] = NULL; + ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */ + + data = m_alloc_secure( ndata ); + p = data; + for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) { + p[0] = nbits[j] >> 8 ; + p[1] = nbits[j]; + p += 2; + memcpy(p, bufarr[j], narr[j] ); + p += narr[j]; + m_free(bufarr[j]); + } + + if (opt.simple_sk_checksum) { + log_info (_("generating the deprecated 16-bit checksum" + " for secret key protection\n")); + csum = checksum( data, ndata-2); + sk->csum = csum; + *p++ = csum >> 8; + *p++ = csum; + sk->protect.sha1chk = 0; + } + else { + MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1); + if (!h) + BUG(); /* algo not available */ + md_write (h, data, ndata - 20); + md_final (h); + memcpy (p, md_read (h, DIGEST_ALGO_SHA1), 20); + p += 20; + md_close (h); + sk->csum = csum = 0; + sk->protect.sha1chk = 1; + } + assert( p == data+ndata ); + + cipher_encrypt( cipher_hd, data, data, ndata ); + for(i = pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + mpi_free( sk->skey[i] ); + sk->skey[i] = NULL; + } + i = pubkey_get_npkey(sk->pubkey_algo); + sk->skey[i] = mpi_set_opaque(NULL, data, ndata ); + } + else { + csum = 0; + for(i=pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { + byte *data; + unsigned int nbits; + + csum += checksum_mpi (sk->skey[i]); + buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL ); + cipher_sync (cipher_hd); + assert ( !mpi_is_opaque (sk->skey[i]) ); + data = m_alloc (nbytes+2); + nbits = mpi_get_nbits (sk->skey[i]); + assert (nbytes == (nbits + 7)/8); + data[0] = nbits >> 8; + data[1] = nbits; + cipher_encrypt (cipher_hd, data+2, buffer, nbytes); + m_free( buffer ); + + mpi_free (sk->skey[i]); + sk->skey[i] = mpi_set_opaque (NULL, data, nbytes+2); + } + sk->csum = csum; + } + sk->is_protected = 1; + cipher_close( cipher_hd ); + } + } + return rc; +} + diff --git a/g10/sig-check.c b/g10/sig-check.c new file mode 100644 index 000000000..c99187928 --- /dev/null +++ b/g10/sig-check.c @@ -0,0 +1,625 @@ +/* sig-check.c - Check a signature + * 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 <assert.h> +#include "util.h" +#include "packet.h" +#include "memory.h" +#include "mpi.h" +#include "keydb.h" +#include "cipher.h" +#include "main.h" +#include "status.h" +#include "i18n.h" +#include "options.h" + +struct cmp_help_context_s { + PKT_signature *sig; + MD_HANDLE md; +}; + +static int do_check( PKT_public_key *pk, PKT_signature *sig, + MD_HANDLE digest, int *r_expired ); + +/**************** + * Check the signature which is contained in SIG. + * The MD_HANDLE should be currently open, so that this function + * is able to append some data, before finalizing the digest. + */ +int +signature_check( PKT_signature *sig, MD_HANDLE digest ) +{ + u32 dummy; + int dum2; + return signature_check2( sig, digest, &dummy, &dum2 ); +} + +int +signature_check2( PKT_signature *sig, MD_HANDLE digest, + u32 *r_expiredate, int *r_expired ) +{ + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + int rc=0; + + *r_expiredate = 0; + + /* Sanity check that the md has a context for the hash that the + sig is expecting. This can happen if a onepass sig header does + not match the actual sig, and also if the clearsign "Hash:" + header is missing or does not match the actual sig. */ + + if(!md_algo_present(digest,sig->digest_algo)) { + log_info(_("WARNING: signature digest conflict in message\n")); + rc=G10ERR_GENERAL; + } + else if( get_pubkey( pk, sig->keyid ) ) + rc = G10ERR_NO_PUBKEY; + else if(!pk->is_valid && !pk->is_primary) + rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an + invalid subkey */ + else { + *r_expiredate = pk->expiredate; + rc = do_check( pk, sig, digest, r_expired ); + } + + free_public_key( pk ); + + if( !rc && sig->sig_class < 2 && is_status_enabled() ) { + /* This signature id works best with DLP algorithms because + * they use a random parameter for every signature. Instead of + * this sig-id we could have also used the hash of the document + * and the timestamp, but the drawback of this is, that it is + * not possible to sign more than one identical document within + * one second. Some remote batch processing applications might + * like this feature here */ + MD_HANDLE md; + u32 a = sig->timestamp; + int i, nsig = pubkey_get_nsig( sig->pubkey_algo ); + byte *p, *buffer; + + md = md_open( DIGEST_ALGO_RMD160, 0); + md_putc( digest, sig->pubkey_algo ); + md_putc( digest, sig->digest_algo ); + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); + for(i=0; i < nsig; i++ ) { + unsigned n = mpi_get_nbits( sig->data[i]); + + md_putc( md, n>>8); + md_putc( md, n ); + p = mpi_get_buffer( sig->data[i], &n, NULL ); + md_write( md, p, n ); + m_free(p); + } + md_final( md ); + p = make_radix64_string( md_read( md, 0 ), 20 ); + buffer = m_alloc( strlen(p) + 60 ); + sprintf( buffer, "%s %s %lu", + p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp ); + write_status_text( STATUS_SIG_ID, buffer ); + m_free(buffer); + m_free(p); + md_close(md); + } + + return rc; +} + + +/**************** + * This function gets called by pubkey_verify() if the algorithm needs it. + */ +static int +cmp_help( void *opaque, MPI result ) +{ +#if 0 /* we do not use this anymore */ + int rc=0, i, j, c, old_enc; + byte *dp; + const byte *asn; + size_t mdlen, asnlen; + struct cmp_help_context_s *ctx = opaque; + PKT_signature *sig = ctx->sig; + MD_HANDLE digest = ctx->md; + + old_enc = 0; + for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) { + if( !j ) { + if( !i && c != 1 ) + break; + else if( i && c == 0xff ) + ; /* skip the padding */ + else if( i && !c ) + j++; + else + break; + } + else if( ++j == 18 && c != 1 ) + break; + else if( j == 19 && c == 0 ) { + old_enc++; + break; + } + } + if( old_enc ) { + log_error("old encoding scheme is not supported\n"); + return G10ERR_GENERAL; + } + + if( (rc=check_digest_algo(sig->digest_algo)) ) + return rc; /* unsupported algo */ + asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen ); + + for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0; + i++, j-- ) + if( asn[j] != c ) + break; + if( j != -1 || mpi_getbyte(result, i) ) + return G10ERR_BAD_PUBKEY; /* ASN is wrong */ + for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) + if( c != 0xff ) + break; + i++; + if( c != sig->digest_algo || mpi_getbyte(result, i) ) { + /* Padding or leading bytes in signature is wrong */ + return G10ERR_BAD_PUBKEY; + } + if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0] + || mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) { + /* Wrong key used to check the signature */ + return G10ERR_BAD_PUBKEY; + } + + dp = md_read( digest, sig->digest_algo ); + for(i=mdlen-1; i >= 0; i--, dp++ ) { + if( mpi_getbyte( result, i ) != *dp ) + return G10ERR_BAD_SIGN; + } + return 0; +#else + return -1; +#endif +} + +static int +do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) +{ + u32 cur_time; + + *r_expired = 0; + if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { + log_info(_("key %08lX: this is a PGP generated " + "ElGamal key which is NOT secure for signatures!\n"), + (ulong)keyid_from_pk(pk,NULL)); + return G10ERR_PUBKEY_ALGO; + } + + if( pk->timestamp > sig->timestamp ) { + ulong d = pk->timestamp - sig->timestamp; + log_info( d==1 + ? _("public key %08lX is %lu second newer than the signature\n") + : _("public key %08lX is %lu seconds newer than the signature\n"), + (ulong)keyid_from_pk(pk,NULL),d ); + if( !opt.ignore_time_conflict ) + return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */ + } + + cur_time = make_timestamp(); + if( pk->timestamp > cur_time ) { + ulong d = pk->timestamp - cur_time; + log_info( d==1 ? _("key %08lX has been created %lu second " + "in future (time warp or clock problem)\n") + : _("key %08lX has been created %lu seconds " + "in future (time warp or clock problem)\n"), + (ulong)keyid_from_pk(pk,NULL),d ); + if( !opt.ignore_time_conflict ) + return G10ERR_TIME_CONFLICT; + } + + if( pk->expiredate && pk->expiredate < cur_time ) { + char buf[11]; + if (opt.verbose) { + u32 tmp_kid[2]; + + keyid_from_pk( pk, tmp_kid ); + log_info(_("NOTE: signature key %08lX expired %s\n"), + (ulong)tmp_kid[1], asctimestamp( pk->expiredate ) ); + } + /* SIGEXPIRED is deprecated. Use KEYEXPIRED. */ + sprintf(buf,"%lu",(ulong)pk->expiredate); + write_status_text(STATUS_KEYEXPIRED,buf); + write_status(STATUS_SIGEXPIRED); + *r_expired = 1; + } + + return 0; +} + + +static int +do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, + int *r_expired ) +{ + MPI result = NULL; + int rc=0; + struct cmp_help_context_s ctx; + + if( (rc=do_check_messages(pk,sig,r_expired)) ) + return rc; + if( (rc=check_digest_algo(sig->digest_algo)) ) + return rc; + if( (rc=check_pubkey_algo(sig->pubkey_algo)) ) + return rc; + + /* make sure the digest algo is enabled (in case of a detached signature)*/ + md_enable( digest, sig->digest_algo ); + + /* complete the digest */ + if( sig->version >= 4 ) + md_putc( digest, sig->version ); + md_putc( digest, sig->sig_class ); + if( sig->version < 4 ) { + u32 a = sig->timestamp; + md_putc( digest, (a >> 24) & 0xff ); + md_putc( digest, (a >> 16) & 0xff ); + md_putc( digest, (a >> 8) & 0xff ); + md_putc( digest, a & 0xff ); + } + else { + byte buf[6]; + size_t n; + md_putc( digest, sig->pubkey_algo ); + md_putc( digest, sig->digest_algo ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (digest, (n >> 8) ); + md_putc (digest, n ); + md_write (digest, sig->hashed->data, n); + n += 6; + } + else { + /* Two octets for the (empty) length of the hashed + section. */ + md_putc (digest, 0); + md_putc (digest, 0); + n = 6; + } + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + md_write( digest, buf, 6 ); + } + md_final( digest ); + + result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, + mpi_get_nbits(pk->pkey[0]), 0 ); + if (!result) + return G10ERR_GENERAL; + ctx.sig = sig; + ctx.md = digest; + rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, + cmp_help, &ctx ); + mpi_free( result ); + if( (opt.emulate_bugs & EMUBUG_MDENCODE) + && rc == G10ERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) { + /* In this case we try again because old GnuPG versions didn't encode + * the hash right. There is no problem with DSA however */ + result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, + mpi_get_nbits(pk->pkey[0]), (sig->version < 5) ); + if (!result) + rc = G10ERR_GENERAL; + else { + ctx.sig = sig; + ctx.md = digest; + rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, + cmp_help, &ctx ); + } + } + + if( !rc && sig->flags.unknown_critical ) { + log_info(_("assuming bad signature from key %08lX due to an unknown critical bit\n"),(ulong)keyid_from_pk(pk,NULL)); + rc = G10ERR_BAD_SIGN; + } + + return rc; +} + + +static void +hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) +{ + PKT_user_id *uid = unode->pkt->pkt.user_id; + + assert( unode->pkt->pkttype == PKT_USER_ID ); + if( uid->attrib_data ) { + if( sig->version >=4 ) { + byte buf[5]; + buf[0] = 0xd1; /* packet of type 17 */ + buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ + buf[2] = uid->attrib_len >> 16; + buf[3] = uid->attrib_len >> 8; + buf[4] = uid->attrib_len; + md_write( md, buf, 5 ); + } + md_write( md, uid->attrib_data, uid->attrib_len ); + } + else { + if( sig->version >=4 ) { + byte buf[5]; + buf[0] = 0xb4; /* indicates a userid packet */ + buf[1] = uid->len >> 24; /* always use 4 length bytes */ + buf[2] = uid->len >> 16; + buf[3] = uid->len >> 8; + buf[4] = uid->len; + md_write( md, buf, 5 ); + } + md_write( md, uid->name, uid->len ); + } +} + +static void +cache_sig_result ( PKT_signature *sig, int result ) +{ + if ( !result ) { + sig->flags.checked = 1; + sig->flags.valid = 1; + } + else if ( result == G10ERR_BAD_SIGN ) { + sig->flags.checked = 1; + sig->flags.valid = 0; + } + else { + sig->flags.checked = 0; + sig->flags.valid = 0; + } +} + + +/* Check the revocation keys to see if any of them have revoked our + pk. sig is the revocation sig. pk is the key it is on. This code + will need to be modified if gpg ever becomes multi-threaded. Note + that this guarantees that a designated revocation sig will never be + considered valid unless it is actually valid, as well as being + issued by a revocation key in a valid direct signature. Note that + this is written so that a revoked revoker can still issue + revocations: i.e. If A revokes B, but A is revoked, B is still + revoked. I'm not completely convinced this is the proper behavior, + but it matches how PGP does it. -dms */ + +/* Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not + revoked */ +int +check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) +{ + static int busy=0; + int i,rc=G10ERR_GENERAL; + + assert(IS_KEY_REV(sig)); + assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1])); + + if(busy) + { + /* return -1 (i.e. not revoked), but mark the pk as uncacheable + as we don't really know its revocation status until it is + checked directly. */ + + pk->dont_cache=1; + return rc; + } + + busy=1; + + /* printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1], + (ulong)sig->keyid[1]); */ + + /* is the issuer of the sig one of our revokers? */ + if( !pk->revkey && pk->numrevkeys ) + BUG(); + else + for(i=0;i<pk->numrevkeys;i++) + { + u32 keyid[2]; + + keyid_from_fingerprint(pk->revkey[i].fpr,MAX_FINGERPRINT_LEN,keyid); + + if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1]) + { + MD_HANDLE md; + + md=md_open(sig->digest_algo,0); + hash_public_key(md,pk); + rc=signature_check(sig,md); + cache_sig_result(sig,rc); + break; + } + } + + busy=0; + + return rc; +} + +/**************** + * check the signature pointed to by NODE. This is a key signature. + * If the function detects a self-signature, it uses the PK from + * ROOT and does not read any public key. + */ +int +check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) +{ + u32 dummy; + int dum2; + return check_key_signature2(root, node, NULL, is_selfsig, &dummy, &dum2 ); +} + +/* If check_pk is set, then use it to check the signature in node + rather than getting it from root or the keydb. */ +int +check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, + int *is_selfsig, u32 *r_expiredate, int *r_expired ) +{ + MD_HANDLE md; + PKT_public_key *pk; + PKT_signature *sig; + int algo; + int rc; + + if( is_selfsig ) + *is_selfsig = 0; + *r_expiredate = 0; + *r_expired = 0; + assert( node->pkt->pkttype == PKT_SIGNATURE ); + assert( root->pkt->pkttype == PKT_PUBLIC_KEY ); + + pk = root->pkt->pkt.public_key; + sig = node->pkt->pkt.signature; + algo = sig->digest_algo; + + /* check whether we have cached the result of a previous signature check.*/ + if ( !opt.no_sig_cache ) { + if (sig->flags.checked) { /*cached status available*/ + if( is_selfsig ) { + u32 keyid[2]; + + keyid_from_pk( pk, keyid ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) + *is_selfsig = 1; + } + if((rc=do_check_messages(pk,sig,r_expired))) + return rc; + return sig->flags.valid? 0 : G10ERR_BAD_SIGN; + } + } + + if( (rc=check_digest_algo(algo)) ) + return rc; + + if( sig->sig_class == 0x20 ) { /* key revocation */ + u32 keyid[2]; + keyid_from_pk( pk, keyid ); + + /* is it a designated revoker? */ + if(keyid[0]!=sig->keyid[0] || keyid[1]!=sig->keyid[1]) + rc=check_revocation_keys(pk,sig); + else + { + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + rc = do_check( pk, sig, md, r_expired ); + cache_sig_result ( sig, rc ); + md_close(md); + } + } + else if( sig->sig_class == 0x28 ) { /* subkey revocation */ + KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); + + if( snode ) { + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_public_key( md, snode->pkt->pkt.public_key ); + rc = do_check( pk, sig, md, r_expired ); + cache_sig_result ( sig, rc ); + md_close(md); + } + else { + if (!opt.quiet) + log_info (_("key %08lX: no subkey for subkey " + "revocation signature\n"), + (ulong)keyid_from_pk (pk, NULL)); + rc = G10ERR_SIG_CLASS; + } + } + else if( sig->sig_class == 0x18 ) { /* key binding */ + KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); + + if( snode ) { + if( is_selfsig ) { /* does this make sense????? */ + u32 keyid[2]; /* it should always be a selfsig */ + + keyid_from_pk( pk, keyid ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) + *is_selfsig = 1; + } + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_public_key( md, snode->pkt->pkt.public_key ); + rc = do_check( pk, sig, md, r_expired ); + cache_sig_result ( sig, rc ); + md_close(md); + } + else { + if (opt.verbose) + log_info(_("key %08lX: no subkey for subkey " + "binding signature\n"), + (ulong)keyid_from_pk (pk, NULL)); + rc = G10ERR_SIG_CLASS; + } + } + else if( sig->sig_class == 0x1f ) { /* direct key signature */ + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + rc = do_check( pk, sig, md, r_expired ); + cache_sig_result ( sig, rc ); + md_close(md); + } + else { /* all other classes */ + KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID ); + + if( unode ) { + u32 keyid[2]; + + keyid_from_pk( pk, keyid ); + md = md_open( algo, 0 ); + hash_public_key( md, pk ); + hash_uid_node( unode, md, sig ); + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) + { + if( is_selfsig ) + *is_selfsig = 1; + rc = do_check( pk, sig, md, r_expired ); + } + else if (check_pk) + rc=do_check(check_pk,sig,md,r_expired); + else + rc = signature_check2( sig, md, r_expiredate, r_expired ); + + cache_sig_result ( sig, rc ); + md_close(md); + } + else { + if (!opt.quiet) + log_info ("key %08lX: no user ID for key signature packet " + "of class %02x\n", + (ulong)keyid_from_pk (pk, NULL), sig->sig_class ); + rc = G10ERR_SIG_CLASS; + } + } + + return rc; +} diff --git a/g10/sign.c b/g10/sign.c new file mode 100644 index 000000000..73286fcb3 --- /dev/null +++ b/g10/sign.c @@ -0,0 +1,1358 @@ +/* sign.c - sign 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 <unistd.h> /* need sleep() */ + +#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 "ttyio.h" +#include "trustdb.h" +#include "status.h" +#include "i18n.h" + + +#ifdef HAVE_DOSISH_SYSTEM +#define LF "\r\n" +void __stdcall Sleep(ulong); +#define sleep(a) Sleep((a)*1000) +#else +#define LF "\n" +#endif + +static int recipient_digest_algo=0; + +/**************** + * Create a notation. It is assumed that the stings in STRLIST + * are already checked to contain only printable data and have a valid + * NAME=VALUE format. + */ +static void +mk_notation_and_policy( PKT_signature *sig, + PKT_public_key *pk, PKT_secret_key *sk ) +{ + const char *string; + char *s=NULL; + byte *buf; + unsigned n1, n2; + STRLIST nd=NULL,pu=NULL; + struct expando_args args; + + memset(&args,0,sizeof(args)); + args.pk=pk; + args.sk=sk; + + /* notation data */ + if(IS_SIG(sig) && opt.sig_notation_data) + { + if(sig->version<4) + log_info("can't put notation data into v3 signatures\n"); + else + nd=opt.sig_notation_data; + } + else if( IS_CERT(sig) && opt.cert_notation_data ) + { + if(sig->version<4) + log_info("can't put notation data into v3 key signatures\n"); + else + nd=opt.cert_notation_data; + } + + for( ; nd; nd = nd->next ) { + char *expanded; + + string = nd->d; + s = strchr( string, '=' ); + if( !s ) + BUG(); /* we have already parsed this */ + n1 = s - string; + s++; + + expanded=pct_expando(s,&args); + if(!expanded) + { + log_error(_("WARNING: unable to %%-expand notation " + "(too large). Using unexpanded.\n")); + expanded=m_strdup(s); + } + + n2 = strlen(expanded); + buf = m_alloc( 8 + n1 + n2 ); + buf[0] = 0x80; /* human readable */ + buf[1] = buf[2] = buf[3] = 0; + buf[4] = n1 >> 8; + buf[5] = n1; + buf[6] = n2 >> 8; + buf[7] = n2; + memcpy(buf+8, string, n1 ); + memcpy(buf+8+n1, expanded, n2 ); + build_sig_subpkt( sig, SIGSUBPKT_NOTATION + | ((nd->flags & 1)? SIGSUBPKT_FLAG_CRITICAL:0), + buf, 8+n1+n2 ); + m_free(expanded); + m_free(buf); + } + + if(opt.list_options&LIST_SHOW_NOTATION) + show_notation(sig,0,0); + + /* set policy URL */ + if( IS_SIG(sig) && opt.sig_policy_url ) + { + if(sig->version<4) + log_info("can't put a policy URL into v3 signatures\n"); + else + pu=opt.sig_policy_url; + } + else if( IS_CERT(sig) && opt.cert_policy_url ) + { + if(sig->version<4) + log_info("can't put a policy URL into v3 key signatures\n"); + else + pu=opt.cert_policy_url; + } + + for(;pu;pu=pu->next) + { + string = pu->d; + + s=pct_expando(string,&args); + if(!s) + { + log_error(_("WARNING: unable to %%-expand policy url " + "(too large). Using unexpanded.\n")); + s=m_strdup(string); + } + + build_sig_subpkt(sig,SIGSUBPKT_POLICY| + ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0), + s,strlen(s)); + + m_free(s); + } + + if(opt.list_options&LIST_SHOW_POLICY) + show_policy_url(sig,0,0); +} + + +/* + * Helper to hash a user ID packet. + */ +static void +hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid) +{ + if ( sigversion >= 4 ) { + byte buf[5]; + + if(uid->attrib_data) { + buf[0] = 0xd1; /* indicates an attribute packet */ + buf[1] = uid->attrib_len >> 24; /* always use 4 length bytes */ + buf[2] = uid->attrib_len >> 16; + buf[3] = uid->attrib_len >> 8; + buf[4] = uid->attrib_len; + } + else { + buf[0] = 0xb4; /* indicates a userid packet */ + buf[1] = uid->len >> 24; /* always use 4 length bytes */ + buf[2] = uid->len >> 16; + buf[3] = uid->len >> 8; + buf[4] = uid->len; + } + md_write( md, buf, 5 ); + } + + if(uid->attrib_data) + md_write (md, uid->attrib_data, uid->attrib_len ); + else + md_write (md, uid->name, uid->len ); +} + + +/* + * Helper to hash some parts from the signature + */ +static void +hash_sigversion_to_magic (MD_HANDLE md, const PKT_signature *sig) +{ + if (sig->version >= 4) + md_putc (md, sig->version); + md_putc (md, sig->sig_class); + if (sig->version < 4) { + u32 a = sig->timestamp; + md_putc (md, (a >> 24) & 0xff ); + md_putc (md, (a >> 16) & 0xff ); + md_putc (md, (a >> 8) & 0xff ); + md_putc (md, a & 0xff ); + } + else { + byte buf[6]; + size_t n; + + md_putc (md, sig->pubkey_algo); + md_putc (md, sig->digest_algo); + if (sig->hashed) { + n = sig->hashed->len; + md_putc (md, (n >> 8) ); + md_putc (md, n ); + md_write (md, sig->hashed->data, n ); + n += 6; + } + else { + md_putc (md, 0); /* always hash the length of the subpacket*/ + md_putc (md, 0); + n = 6; + } + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + md_write (md, buf, 6); + } +} + + +static int +do_sign( PKT_secret_key *sk, PKT_signature *sig, + MD_HANDLE md, int digest_algo ) +{ + MPI frame; + byte *dp; + int rc; + + if( sk->timestamp > sig->timestamp ) { + ulong d = sk->timestamp - sig->timestamp; + log_info( d==1 ? _("key has been created %lu second " + "in future (time warp or clock problem)\n") + : _("key has been created %lu seconds " + "in future (time warp or clock problem)\n"), d ); + if( !opt.ignore_time_conflict ) + return G10ERR_TIME_CONFLICT; + } + + + print_pubkey_algo_note(sk->pubkey_algo); + + if( !digest_algo ) + digest_algo = md_get_algo(md); + + print_digest_algo_note( digest_algo ); + dp = md_read( md, digest_algo ); + sig->digest_algo = digest_algo; + sig->digest_start[0] = dp[0]; + sig->digest_start[1] = dp[1]; + frame = encode_md_value( sk->pubkey_algo, md, + digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); + if (!frame) + return G10ERR_GENERAL; + rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); + mpi_free(frame); + if (!rc && !opt.no_sig_create_check) { + /* check that the signature verification worked and nothing is + * fooling us e.g. by a bug in the signature create + * code or by deliberately introduced faults. */ + PKT_public_key *pk = m_alloc_clear (sizeof *pk); + + if( get_pubkey( pk, sig->keyid ) ) + rc = G10ERR_NO_PUBKEY; + else { + frame = encode_md_value (pk->pubkey_algo, md, + sig->digest_algo, + mpi_get_nbits(pk->pkey[0]), 0); + if (!frame) + rc = G10ERR_GENERAL; + else + rc = pubkey_verify (pk->pubkey_algo, frame, + sig->data, pk->pkey, + NULL, NULL ); + mpi_free (frame); + } + if (rc) + log_error (_("checking created signature failed: %s\n"), + g10_errstr (rc)); + free_public_key (pk); + } + if( rc ) + log_error(_("signing failed: %s\n"), g10_errstr(rc) ); + else { + if( opt.verbose ) { + char *ustr = get_user_id_string_printable (sig->keyid); + log_info(_("%s/%s signature from: \"%s\"\n"), + pubkey_algo_to_string(sk->pubkey_algo), + digest_algo_to_string(sig->digest_algo), + ustr ); + m_free(ustr); + } + } + return rc; +} + + + +int +complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ) +{ + int rc=0; + + if( !(rc=check_secret_key( sk, 0 )) ) + rc = do_sign( sk, sig, md, 0 ); + return rc; +} + +static int +hash_for(int pubkey_algo, int packet_version ) +{ + if( opt.def_digest_algo ) + return opt.def_digest_algo; + else if( recipient_digest_algo ) + return recipient_digest_algo; + else if(PGP2 && pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 ) + { + /* Old-style PGP only understands MD5 */ + return DIGEST_ALGO_MD5; + } + else if( pubkey_algo == PUBKEY_ALGO_DSA ) + { + /* We need a 160-bit hash for DSA, so we can't just take the first + in the pref list */ + + if(opt.personal_digest_prefs) + { + prefitem_t *prefs; + + for(prefs=opt.personal_digest_prefs;prefs->type;prefs++) + if(md_digest_length(prefs->value)==20) + return prefs->value; + } + + return DIGEST_ALGO_SHA1; + } + else if( opt.personal_digest_prefs ) + { + /* It's not DSA, so we can use whatever the first hash algorithm + is in the pref list */ + return opt.personal_digest_prefs[0].value; + } + else + return DEFAULT_DIGEST_ALGO; +} + +static int +only_old_style( SK_LIST sk_list ) +{ + SK_LIST sk_rover = NULL; + int old_style = 0; + + /* if there are only old style capable key we use the old sytle */ + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + PKT_secret_key *sk = sk_rover->sk; + if( sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) + old_style = 1; + else + return 0; + } + return old_style; +} + + +static void +print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what ) +{ + byte array[MAX_FINGERPRINT_LEN], *p; + char buf[100+MAX_FINGERPRINT_LEN*2]; + size_t i, n; + + sprintf(buf, "%c %d %d %02x %lu ", + what, sig->pubkey_algo, sig->digest_algo, sig->sig_class, + (ulong)sig->timestamp ); + + fingerprint_from_sk( sk, array, &n ); + p = buf + strlen(buf); + for(i=0; i < n ; i++ ) + sprintf(p+2*i, "%02X", array[i] ); + + write_status_text( STATUS_SIG_CREATED, buf ); +} + + +/* + * Loop over the secret certificates in SK_LIST and build the one pass + * signature packets. OpenPGP says that the data should be bracket by + * the onepass-sig and signature-packet; so we build these onepass + * packet here in reverse order + */ +static int +write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) +{ + int skcount; + SK_LIST sk_rover; + + for (skcount=0, sk_rover=sk_list; sk_rover; sk_rover = sk_rover->next) + skcount++; + + for (; skcount; skcount--) { + PKT_secret_key *sk; + PKT_onepass_sig *ops; + PACKET pkt; + int i, rc; + + for (i=0, sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + if (++i == skcount) + break; + } + + sk = sk_rover->sk; + ops = m_alloc_clear (sizeof *ops); + ops->sig_class = sigclass; + ops->digest_algo = hash_for (sk->pubkey_algo, sk->version); + ops->pubkey_algo = sk->pubkey_algo; + keyid_from_sk (sk, ops->keyid); + ops->last = (skcount == 1); + + init_packet(&pkt); + pkt.pkttype = PKT_ONEPASS_SIG; + pkt.pkt.onepass_sig = ops; + rc = build_packet (out, &pkt); + free_packet (&pkt); + if (rc) { + log_error ("build onepass_sig packet failed: %s\n", + g10_errstr(rc)); + return rc; + } + } + + return 0; +} + +/* + * Helper to write the plaintext (literal data) packet + */ +static int +write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) +{ + PKT_plaintext *pt = NULL; + u32 filesize; + int rc = 0; + + if (!opt.no_literal) { + if (fname || opt.set_filename) { + char *s = make_basename (opt.set_filename? opt.set_filename + : fname, + iobuf_get_real_fname(inp)); + pt = m_alloc (sizeof *pt + strlen(s) - 1); + pt->namelen = strlen (s); + memcpy (pt->name, s, pt->namelen); + m_free (s); + } + else { /* no filename */ + pt = m_alloc (sizeof *pt - 1); + pt->namelen = 0; + } + } + + /* try to calculate the length of the data */ + if (fname && *fname && !(*fname=='-' && !fname[1])) { + if( !(filesize = iobuf_get_filelength(inp)) ) + log_info (_("WARNING: `%s' is an empty file\n"), fname); + + /* we can't yet encode the length of very large files, + * so we switch to partial length encoding in this case */ + if (filesize >= IOBUF_FILELENGTH_LIMIT) + filesize = 0; + + /* because the text_filter modifies the length of the + * data, it is not possible to know the used length + * without a double read of the file - to avoid that + * we simple use partial length packets. + */ + if ( ptmode == 't' ) + filesize = 0; + } + else { + filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ + } + + if (!opt.no_literal) { + PACKET pkt; + + pt->timestamp = make_timestamp (); + pt->mode = ptmode; + pt->len = filesize; + pt->new_ctb = !pt->len && !RFC1991; + pt->buf = inp; + init_packet(&pkt); + pkt.pkttype = PKT_PLAINTEXT; + pkt.pkt.plaintext = pt; + /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ + if( (rc = build_packet (out, &pkt)) ) + log_error ("build_packet(PLAINTEXT) failed: %s\n", + g10_errstr(rc) ); + pt->buf = NULL; + } + else { + byte copy_buffer[4096]; + int bytes_copied; + + while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) + if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; + log_error ("copying input to output failed: %s\n", + g10_errstr(rc)); + break; + } + wipememory(copy_buffer,4096); /* burn buffer */ + } + /* fixme: it seems that we never freed pt/pkt */ + + return rc; +} + +/* + * Write the signatures from the SK_LIST to OUT. HASH must be a non-finalized + * hash which will not be changes here. + */ +static int +write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, + int sigclass, u32 timestamp, u32 duration, + int status_letter) +{ + SK_LIST sk_rover; + + /* loop over the secret certificates */ + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { + PKT_secret_key *sk; + PKT_signature *sig; + MD_HANDLE md; + int rc; + + sk = sk_rover->sk; + + /* build the signature packet */ + sig = m_alloc_clear (sizeof *sig); + if(opt.force_v3_sigs || RFC1991) + sig->version=3; + else if(duration || opt.sig_policy_url || opt.sig_notation_data) + sig->version=4; + else + sig->version=sk->version; + keyid_from_sk (sk, sig->keyid); + sig->digest_algo = hash_for (sk->pubkey_algo, sk->version); + sig->pubkey_algo = sk->pubkey_algo; + if(timestamp) + sig->timestamp = timestamp; + else + sig->timestamp = make_timestamp(); + if(duration) + sig->expiredate = sig->timestamp+duration; + sig->sig_class = sigclass; + + md = md_copy (hash); + + if (sig->version >= 4) + build_sig_subpkt_from_sig (sig); + mk_notation_and_policy (sig, NULL, sk); + + hash_sigversion_to_magic (md, sig); + md_final (md); + + rc = do_sign( sk, sig, md, hash_for (sig->pubkey_algo, sk->version) ); + md_close (md); + + if( !rc ) { /* and write it */ + PACKET pkt; + + init_packet(&pkt); + pkt.pkttype = PKT_SIGNATURE; + pkt.pkt.signature = sig; + rc = build_packet (out, &pkt); + if (!rc && is_status_enabled()) { + print_status_sig_created ( sk, sig, status_letter); + } + free_packet (&pkt); + if (rc) + log_error ("build signature packet failed: %s\n", + g10_errstr(rc) ); + } + if( rc ) + return rc;; + } + + return 0; +} + +/**************** + * Sign the files whose names are in FILENAME. + * If DETACHED has the value true, + * make a detached signature. If FILENAMES->d is NULL read from stdin + * and ignore the detached mode. Sign the file with all secret keys + * which can be taken from LOCUSR, if this is NULL, use the default one + * If ENCRYPTFLAG is true, use REMUSER (or ask if it is NULL) to encrypt the + * signed data for these users. + * If OUTFILE is not NULL; this file is used for output and the function + * does not ask for overwrite permission; output is then always + * uncompressed, non-armored and in binary mode. + */ +int +sign_file( STRLIST filenames, int detached, STRLIST locusr, + int encryptflag, STRLIST remusr, const char *outfile ) +{ + const char *fname; + armor_filter_context_t afx; + compress_filter_context_t zfx; + md_filter_context_t mfx; + text_filter_context_t tfx; + progress_filter_context_t pfx; + encrypt_filter_context_t efx; + IOBUF inp = NULL, out = NULL; + PACKET pkt; + int rc = 0; + PK_LIST pk_list = NULL; + SK_LIST sk_list = NULL; + SK_LIST sk_rover = NULL; + int multifile = 0; + u32 duration=0; + + memset( &afx, 0, sizeof afx); + memset( &zfx, 0, sizeof zfx); + memset( &mfx, 0, sizeof mfx); + memset( &efx, 0, sizeof efx); + init_packet( &pkt ); + + if( filenames ) { + fname = filenames->d; + multifile = !!filenames->next; + } + else + fname = NULL; + + if( fname && filenames->next && (!detached || encryptflag) ) + log_bug("multiple files can only be detached signed"); + + if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) + duration=ask_expire_interval(1); + + if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) + goto leave; + + if(PGP2 && !only_old_style(sk_list)) + { + log_info(_("you can only detach-sign with PGP 2.x style keys " + "while in --pgp2 mode\n")); + compliance_failure(); + } + + if(encryptflag && (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC ))) + goto leave; + + /* prepare iobufs */ + if( multifile ) /* have list of filenames */ + inp = NULL; /* we do it later */ + else { + if( !(inp = iobuf_open(fname)) ) { + log_error("can't open %s: %s\n", fname? fname: "[stdin]", + strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + + handle_progress (&pfx, inp, fname); + } + + if( outfile ) { + if( !(out = iobuf_create( outfile )) ) { + log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + goto leave; + } + else if( opt.verbose ) + log_info(_("writing to `%s'\n"), outfile ); + } + else if( (rc = open_outfile( fname, opt.armor? 1: detached? 2:0, &out ))) + goto leave; + + /* prepare to calculate the MD over the input */ + if( opt.textmode && !outfile && !multifile ) + { + memset( &tfx, 0, sizeof tfx); + iobuf_push_filter( inp, text_filter, &tfx ); + } + + mfx.md = md_open(0, 0); + + /* If we're encrypting and signing, it is reasonable to pick the + hash algorithm to use out of the recepient key prefs. */ + if(pk_list) + { + if(opt.def_digest_algo) + { + if(!opt.expert && + select_algo_from_prefs(pk_list,PREFTYPE_HASH, + opt.def_digest_algo, + NULL)!=opt.def_digest_algo) + log_info(_("forcing digest algorithm %s (%d) " + "violates recipient preferences\n"), + digest_algo_to_string(opt.def_digest_algo), + opt.def_digest_algo); + } + else + { + int hashlen=0,algo; + + /* Of course, if the recipient asks for something + unreasonable (like a non-160-bit hash for DSA, for + example), then don't do it. Check all sk's - if any + are DSA, then the hash must be 160-bit. In the future + this can be more complex with different hashes for each + sk, but so long as there is only one signing algorithm + with hash restrictions, this is ok. -dms */ + + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) + if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA) + hashlen=20; + + if((algo= + select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1, + hashlen?&hashlen:NULL))>0) + recipient_digest_algo=algo; + } + } + + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + PKT_secret_key *sk = sk_rover->sk; + md_enable(mfx.md, hash_for(sk->pubkey_algo, sk->version )); + } + + if( !multifile ) + iobuf_push_filter( inp, md_filter, &mfx ); + + if( detached && !encryptflag && !RFC1991 ) + afx.what = 2; + + if( opt.armor && !outfile ) + iobuf_push_filter( out, armor_filter, &afx ); + + if( encryptflag ) { + efx.pk_list = pk_list; + /* fixme: set efx.cfx.datalen if known */ + iobuf_push_filter( out, encrypt_filter, &efx ); + } + + if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) + { + int compr_algo=opt.def_compress_algo; + + /* If not forced by user */ + if(compr_algo==-1) + { + /* If we're not encrypting, then select_algo_from_prefs + will fail and we'll end up with the default. If we are + encrypting, select_algo_from_prefs cannot fail since + there is an assumed preference for uncompressed data. + Still, if it did fail, we'll also end up with the + default. */ + + if((compr_algo= + select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1) + compr_algo=default_compress_algo(); + } + else if(!opt.expert && pk_list + && 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 ) + { + zfx.algo = compr_algo; + iobuf_push_filter( out, compress_filter, &zfx ); + } + } + + /* Write the one-pass signature packets if needed */ + if (!detached && !RFC1991) { + rc = write_onepass_sig_packets (sk_list, out, + opt.textmode && !outfile ? 0x01:0x00); + if (rc) + goto leave; + } + + /* setup the inner packet */ + if( detached ) { + if( multifile ) { + STRLIST sl; + + if( opt.verbose ) + log_info(_("signing:") ); + /* must walk reverse trough this list */ + for( sl = strlist_last(filenames); sl; + sl = strlist_prev( filenames, sl ) ) { + if( !(inp = iobuf_open(sl->d)) ) { + log_error(_("can't open %s: %s\n"), + sl->d, strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + handle_progress (&pfx, inp, sl->d); + if( opt.verbose ) + fprintf(stderr, " `%s'", sl->d ); + if(opt.textmode) + { + memset( &tfx, 0, sizeof tfx); + iobuf_push_filter( inp, text_filter, &tfx ); + } + iobuf_push_filter( inp, md_filter, &mfx ); + while( iobuf_get(inp) != -1 ) + ; + iobuf_close(inp); inp = NULL; + } + if( opt.verbose ) + putc( '\n', stderr ); + } + else { + /* read, so that the filter can calculate the digest */ + while( iobuf_get(inp) != -1 ) + ; + } + } + else { + rc = write_plaintext_packet (out, inp, fname, + opt.textmode && !outfile ? 't':'b'); + } + + /* catch errors from above */ + if (rc) + goto leave; + + /* write the signatures */ + rc = write_signature_packets (sk_list, out, mfx.md, + opt.textmode && !outfile? 0x01 : 0x00, + 0, duration, detached ? 'D':'S'); + if( rc ) + goto leave; + + + leave: + if( rc ) + iobuf_cancel(out); + else { + iobuf_close(out); + if (encryptflag) + write_status( STATUS_END_ENCRYPTION ); + } + iobuf_close(inp); + md_close( mfx.md ); + release_sk_list( sk_list ); + release_pk_list( pk_list ); + recipient_digest_algo=0; + return rc; +} + + + +/**************** + * make a clear signature. note that opt.armor is not needed + */ +int +clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) +{ + armor_filter_context_t afx; + progress_filter_context_t pfx; + MD_HANDLE textmd = NULL; + IOBUF inp = NULL, out = NULL; + PACKET pkt; + int rc = 0; + SK_LIST sk_list = NULL; + SK_LIST sk_rover = NULL; + int old_style = RFC1991; + int only_md5 = 0; + u32 duration=0; + + memset( &afx, 0, sizeof afx); + init_packet( &pkt ); + + if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) + duration=ask_expire_interval(1); + + if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) + goto leave; + + if( !old_style && !duration ) + old_style = only_old_style( sk_list ); + + if(PGP2 && !only_old_style(sk_list)) + { + log_info(_("you can only clearsign with PGP 2.x style keys " + "while in --pgp2 mode\n")); + compliance_failure(); + } + + /* prepare iobufs */ + if( !(inp = iobuf_open(fname)) ) { + log_error("can't open %s: %s\n", fname? fname: "[stdin]", + strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + handle_progress (&pfx, inp, fname); + + if( outfile ) { + if( !(out = iobuf_create( outfile )) ) { + log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + goto leave; + } + else if( opt.verbose ) + log_info(_("writing to `%s'\n"), outfile ); + } + else if( (rc = open_outfile( fname, 1, &out )) ) + goto leave; + + iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF ); + + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + PKT_secret_key *sk = sk_rover->sk; + if( hash_for(sk->pubkey_algo, sk->version) == DIGEST_ALGO_MD5 ) + only_md5 = 1; + else { + only_md5 = 0; + break; + } + } + + if( !(old_style && only_md5) ) { + const char *s; + int any = 0; + byte hashs_seen[256]; + + memset( hashs_seen, 0, sizeof hashs_seen ); + iobuf_writestr(out, "Hash: " ); + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + PKT_secret_key *sk = sk_rover->sk; + int i = hash_for(sk->pubkey_algo, sk->version); + + if( !hashs_seen[ i & 0xff ] ) { + s = digest_algo_to_string( i ); + if( s ) { + hashs_seen[ i & 0xff ] = 1; + if( any ) + iobuf_put(out, ',' ); + iobuf_writestr(out, s ); + any = 1; + } + } + } + assert(any); + iobuf_writestr(out, LF ); + } + + if( opt.not_dash_escaped ) + iobuf_writestr( out, + "NotDashEscaped: You need GnuPG to verify this message" LF ); + iobuf_writestr(out, LF ); + + textmd = md_open(0, 0); + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { + PKT_secret_key *sk = sk_rover->sk; + md_enable(textmd, hash_for(sk->pubkey_algo, sk->version)); + } + if ( DBG_HASHING ) + md_start_debug( textmd, "clearsign" ); + copy_clearsig_text( out, inp, textmd, !opt.not_dash_escaped, + opt.escape_from, (old_style && only_md5) ); + /* fixme: check for read errors */ + + /* now write the armor */ + afx.what = 2; + iobuf_push_filter( out, armor_filter, &afx ); + + /* write the signatures */ + rc=write_signature_packets (sk_list, out, textmd, 0x01, 0, duration, 'C'); + if( rc ) + goto leave; + + leave: + if( rc ) + iobuf_cancel(out); + else + iobuf_close(out); + iobuf_close(inp); + md_close( textmd ); + release_sk_list( sk_list ); + return rc; +} + +/* + * Sign and conventionally encrypt the given file. + * FIXME: Far too much code is duplicated - revamp the whole file. + */ +int +sign_symencrypt_file (const char *fname, STRLIST locusr) +{ + armor_filter_context_t afx; + progress_filter_context_t pfx; + compress_filter_context_t zfx; + md_filter_context_t mfx; + text_filter_context_t tfx; + cipher_filter_context_t cfx; + IOBUF inp = NULL, out = NULL; + PACKET pkt; + STRING2KEY *s2k = NULL; + int rc = 0; + SK_LIST sk_list = NULL; + SK_LIST sk_rover = NULL; + int algo; + u32 duration=0; + + memset( &afx, 0, sizeof afx); + memset( &zfx, 0, sizeof zfx); + memset( &mfx, 0, sizeof mfx); + memset( &tfx, 0, sizeof tfx); + memset( &cfx, 0, sizeof cfx); + init_packet( &pkt ); + + if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) + duration=ask_expire_interval(1); + + rc = build_sk_list (locusr, &sk_list, 1, PUBKEY_USAGE_SIG); + if (rc) + goto leave; + + /* prepare iobufs */ + inp = iobuf_open(fname); + if( !inp ) { + log_error("can't open %s: %s\n", fname? fname: "[stdin]", + strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + handle_progress (&pfx, inp, fname); + + /* prepare key */ + s2k = m_alloc_clear( sizeof *s2k ); + s2k->mode = RFC1991? 0:opt.s2k_mode; + s2k->hash_algo = opt.s2k_digest_algo; + + algo = default_cipher_algo(); + if (!opt.quiet || !opt.batch) + log_info (_("%s encryption will be used\n"), + cipher_algo_to_string(algo) ); + cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, NULL); + + if (!cfx.dek || !cfx.dek->keylen) { + rc = G10ERR_PASSPHRASE; + log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); + goto leave; + } + + /* now create the outfile */ + rc = open_outfile (fname, opt.armor? 1:0, &out); + if (rc) + goto leave; + + /* prepare to calculate the MD over the input */ + if (opt.textmode) + iobuf_push_filter (inp, text_filter, &tfx); + mfx.md = md_open(0, 0); + + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { + PKT_secret_key *sk = sk_rover->sk; + md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version )); + } + + iobuf_push_filter (inp, md_filter, &mfx); + + /* Push armor output filter */ + if (opt.armor) + iobuf_push_filter (out, armor_filter, &afx); + + /* Write the symmetric key packet */ + /*(current filters: armor)*/ + if (!RFC1991) { + PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); + enc->version = 4; + enc->cipher_algo = cfx.dek->algo; + enc->s2k = *s2k; + pkt.pkttype = PKT_SYMKEY_ENC; + pkt.pkt.symkey_enc = enc; + if( (rc = build_packet( out, &pkt )) ) + log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); + m_free(enc); + } + + /* Push the encryption filter */ + iobuf_push_filter( out, cipher_filter, &cfx ); + + /* Push the Zip filter */ + if (opt.compress && default_compress_algo()) + { + zfx.algo = default_compress_algo(); + iobuf_push_filter( out, compress_filter, &zfx ); + } + + /* Write the one-pass signature packets */ + /*(current filters: zip - encrypt - armor)*/ + if (!RFC1991) { + rc = write_onepass_sig_packets (sk_list, out, + opt.textmode? 0x01:0x00); + if (rc) + goto leave; + } + + /* Pipe data through all filters; i.e. write the signed stuff */ + /*(current filters: zip - encrypt - armor)*/ + rc = write_plaintext_packet (out, inp, fname, opt.textmode ? 't':'b'); + if (rc) + goto leave; + + /* Write the signatures */ + /*(current filters: zip - encrypt - armor)*/ + rc = write_signature_packets (sk_list, out, mfx.md, + opt.textmode? 0x01 : 0x00, + 0, duration, 'S'); + if( rc ) + goto leave; + + + leave: + if( rc ) + iobuf_cancel(out); + else { + iobuf_close(out); + write_status( STATUS_END_ENCRYPTION ); + } + iobuf_close(inp); + release_sk_list( sk_list ); + md_close( mfx.md ); + m_free(cfx.dek); + m_free(s2k); + return rc; +} + + +/**************** + * Create a signature packet for the given public key certificate and + * the user id and return it in ret_sig. User signature class SIGCLASS + * user-id is not used (and may be NULL if sigclass is 0x20) If + * DIGEST_ALGO is 0 the function selects an appropriate one. + * SIGVERSION gives the minimal required signature packet version; + * this is needed so that special properties like local sign are not + * applied (actually: dropped) when a v3 key is used. TIMESTAMP is + * the timestamp to use for the signature. 0 means "now" */ +int +make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, + PKT_user_id *uid, PKT_public_key *subpk, + PKT_secret_key *sk, + int sigclass, int digest_algo, + int sigversion, u32 timestamp, u32 duration, + int (*mksubpkt)(PKT_signature *, void *), void *opaque + ) +{ + PKT_signature *sig; + int rc=0; + MD_HANDLE md; + + assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F + || sigclass == 0x20 || sigclass == 0x18 + || sigclass == 0x30 || sigclass == 0x28 ); + + if (opt.force_v4_certs) + sigversion = 4; + + if (sigversion < sk->version) + sigversion = sk->version; + + /* If you are making a signature on a v4 key using your v3 key, it + doesn't make sense to generate a v3 sig. After all, no v3-only + PGP implementation could understand the v4 key in the first + place. Note that this implies that a signature on an attribute + uid is usually going to be v4 as well, since they are not + generally found on v3 keys. */ + if (sigversion < pk->version) + sigversion = pk->version; + + if( !digest_algo ) + { + /* Basically, this means use SHA1 always unless it's a v3 RSA + key making a v3 cert (use MD5), or the user specified + something (use whatever they said). They still must use a + 160-bit hash with DSA, or the signature will fail. Note + that this still allows the caller of make_keysig_packet to + override the user setting if it must. */ + + if(opt.cert_digest_algo) + digest_algo=opt.cert_digest_algo; + else if((sk->pubkey_algo==PUBKEY_ALGO_RSA || + sk->pubkey_algo==PUBKEY_ALGO_RSA_S) && + pk->version<4 && sigversion < 4) + digest_algo = DIGEST_ALGO_MD5; + else + digest_algo = DIGEST_ALGO_SHA1; + } + + md = md_open( digest_algo, 0 ); + + /* hash the public key certificate and the user id */ + hash_public_key( md, pk ); + if( sigclass == 0x18 || sigclass == 0x28 ) { /* subkey binding/revocation*/ + hash_public_key( md, subpk ); + } + else if( sigclass != 0x1F && sigclass != 0x20 ) { + hash_uid (md, sigversion, uid); + } + /* and make the signature packet */ + sig = m_alloc_clear( sizeof *sig ); + sig->version = sigversion; + sig->flags.exportable=1; + sig->flags.revocable=1; + keyid_from_sk( sk, sig->keyid ); + sig->pubkey_algo = sk->pubkey_algo; + sig->digest_algo = digest_algo; + if(timestamp) + sig->timestamp=timestamp; + else + sig->timestamp=make_timestamp(); + if(duration) + sig->expiredate=sig->timestamp+duration; + sig->sig_class = sigclass; + if( sig->version >= 4 ) + build_sig_subpkt_from_sig( sig ); + mk_notation_and_policy( sig, pk, sk ); + + /* Crucial that the call to mksubpkt comes LAST before the calls + to finalize the sig as that makes it possible for the mksubpkt + function to get a reliable pointer to the subpacket area. */ + if( sig->version >= 4 && mksubpkt ) + rc = (*mksubpkt)( sig, opaque ); + + if( !rc ) { + hash_sigversion_to_magic (md, sig); + md_final(md); + + rc = complete_sig( sig, sk, md ); + } + + md_close( md ); + if( rc ) + free_seckey_enc( sig ); + else + *ret_sig = sig; + return rc; +} + + + +/**************** + * Create a new signature packet based on an existing one. + * Only user ID signatures are supported for now. + * TODO: Merge this with make_keysig_packet. + */ +int +update_keysig_packet( PKT_signature **ret_sig, + PKT_signature *orig_sig, + PKT_public_key *pk, + PKT_user_id *uid, + PKT_public_key *subpk, + PKT_secret_key *sk, + int (*mksubpkt)(PKT_signature *, void *), + void *opaque + ) +{ + PKT_signature *sig; + int rc=0; + MD_HANDLE md; + + if ((!orig_sig || !pk || !sk) + || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) + || (orig_sig->sig_class == 0x18 && !subpk)) + return G10ERR_GENERAL; + + md = md_open( orig_sig->digest_algo, 0 ); + + /* hash the public key certificate and the user id */ + hash_public_key( md, pk ); + + if( orig_sig->sig_class == 0x18 ) + hash_public_key( md, subpk ); + else + hash_uid (md, orig_sig->version, uid); + + /* create a new signature packet */ + sig = copy_signature (NULL, orig_sig); + + /* We need to create a new timestamp so that new sig expiration + calculations are done correctly... */ + sig->timestamp=make_timestamp(); + + /* ... but we won't make a timestamp earlier than the existing + one. */ + while(sig->timestamp<=orig_sig->timestamp) + { + sleep(1); + sig->timestamp=make_timestamp(); + } + + /* Note that already expired sigs will remain expired (with a + duration of 0) since build-packet.c:build_sig_subpkt_from_sig + detects this case. */ + + if( sig->version >= 4 ) + { + /* Put the updated timestamp into the sig. Note that this + will automagically lower any sig expiration dates to + correctly correspond to the differences in the timestamps + (i.e. the duration will shrink). */ + build_sig_subpkt_from_sig( sig ); + + if (mksubpkt) + rc = (*mksubpkt)(sig, opaque); + } + + if (!rc) { + hash_sigversion_to_magic (md, sig); + md_final(md); + + rc = complete_sig( sig, sk, md ); + } + + md_close (md); + if( rc ) + free_seckey_enc (sig); + else + *ret_sig = sig; + return rc; +} diff --git a/g10/signal.c b/g10/signal.c new file mode 100644 index 000000000..1028ab705 --- /dev/null +++ b/g10/signal.c @@ -0,0 +1,217 @@ +/* signal.c - signal handling + * 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 <signal.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "options.h" +#include "errors.h" +#include "memory.h" +#include "util.h" +#include "main.h" +#include "ttyio.h" + + +static volatile int caught_fatal_sig = 0; +static volatile int caught_sigusr1 = 0; + +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; + + secmem_term(); + /* better don't transtale these messages */ + write(2, "\n", 1 ); + s = log_get_name(); 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); + remove_lockfiles (); +#ifdef __riscos__ + riscos_close_fds (); +#endif /* __riscos__ */ + raise( sig ); +} + + +static RETSIGTYPE +got_usr_signal( int sig ) +{ + caught_sigusr1 = 1; +} + + +void +init_signals() +{ +#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 +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; + sigrelse(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 +block_all_signals() +{ + do_block(1); +} + +void +unblock_all_signals() +{ + do_block(0); +} diff --git a/g10/status.c b/g10/status.c new file mode 100644 index 000000000..cc30db79b --- /dev/null +++ b/g10/status.c @@ -0,0 +1,693 @@ +/* status.c + * 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 <unistd.h> +#include <signal.h> +#ifdef USE_SHM_COPROCESSING +#ifdef USE_CAPABILITIES +#include <sys/capability.h> +#endif +#ifdef HAVE_SYS_IPC_H +#include <sys/types.h> +#include <sys/ipc.h> +#endif +#ifdef HAVE_SYS_SHM_H +#include <sys/shm.h> +#endif +#if defined(HAVE_MLOCK) +#include <sys/mman.h> +#endif +#endif +#include "util.h" +#include "status.h" +#include "ttyio.h" +#include "options.h" +#include "main.h" +#include "i18n.h" +#include "cipher.h" /* for progress functions */ + +#define CONTROL_D ('D' - 'A' + 1) + + + +static FILE *statusfp; + +#ifdef USE_SHM_COPROCESSING + static int shm_id = -1; + static volatile char *shm_area; + static size_t shm_size; + static int shm_is_locked; +#endif /*USE_SHM_COPROCESSING*/ + + +static void +progress_cb ( void *ctx, int c ) +{ + char buf[50]; + + if ( c == '\n' ) + sprintf ( buf, "%.20s X 100 100", (char*)ctx ); + else + sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c ); + write_status_text ( STATUS_PROGRESS, buf ); +} + +static const char * +get_status_string ( int no ) +{ + const char *s; + + switch( no ) { + case STATUS_ENTER : s = "ENTER"; break; + case STATUS_LEAVE : s = "LEAVE"; break; + case STATUS_ABORT : s = "ABORT"; break; + case STATUS_GOODSIG: s = "GOODSIG"; break; + case STATUS_KEYEXPIRED: s = "KEYEXPIRED"; break; + case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; + case STATUS_BADSIG : s = "BADSIG"; break; + case STATUS_ERRSIG : s = "ERRSIG"; break; + case STATUS_BADARMOR : s = "BADARMOR"; break; + case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; + case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; + case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; + case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; + case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; + case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; + case STATUS_GET_BOOL : s = "GET_BOOL"; break; + case STATUS_GET_LINE : s = "GET_LINE"; break; + case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break; + case STATUS_GOT_IT : s = "GOT_IT"; break; + case STATUS_SHM_INFO : s = "SHM_INFO"; break; + case STATUS_SHM_GET : s = "SHM_GET"; break; + case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; + case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; + case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; + case STATUS_VALIDSIG : s = "VALIDSIG"; break; + case STATUS_SIG_ID : s = "SIG_ID"; break; + case STATUS_ENC_TO : s = "ENC_TO"; break; + case STATUS_NODATA : s = "NODATA"; break; + case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; + case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; + case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; + case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; + case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; + case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; + case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; + case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; + case STATUS_GOODMDC : s = "GOODMDC"; break; + case STATUS_BADMDC : s = "BADMDC"; break; + case STATUS_ERRMDC : s = "ERRMDC"; break; + case STATUS_IMPORTED : s = "IMPORTED"; break; + case STATUS_IMPORT_OK : s = "IMPORT_OK"; break; + case STATUS_IMPORT_CHECK : s = "IMPORT_CHECK"; break; + case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; + case STATUS_FILE_START : s = "FILE_START"; break; + case STATUS_FILE_DONE : s = "FILE_DONE"; break; + case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; + case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break; + case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break; + case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break; + case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break; + case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break; + case STATUS_PROGRESS : s = "PROGRESS"; break; + case STATUS_SIG_CREATED : s = "SIG_CREATED"; break; + case STATUS_SESSION_KEY : s = "SESSION_KEY"; break; + case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break; + case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break; + case STATUS_POLICY_URL : s = "POLICY_URL" ; break; + case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break; + case STATUS_END_STREAM : s = "END_STREAM"; break; + case STATUS_KEY_CREATED : s = "KEY_CREATED"; break; + case STATUS_USERID_HINT : s = "USERID_HINT"; break; + case STATUS_UNEXPECTED : s = "UNEXPECTED"; break; + case STATUS_INV_RECP : s = "INV_RECP"; break; + case STATUS_NO_RECP : s = "NO_RECP"; break; + case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break; + case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; + case STATUS_EXPSIG : s = "EXPSIG"; break; + case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; + case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; + default: s = "?"; break; + } + return s; +} + +void +set_status_fd ( int fd ) +{ + static int last_fd = -1; + + if ( fd != -1 && last_fd == fd ) + return; + + if ( statusfp && statusfp != stdout && statusfp != stderr ) + fclose (statusfp); + statusfp = NULL; + if ( fd == -1 ) + return; + + if( fd == 1 ) + statusfp = stdout; + else if( fd == 2 ) + statusfp = stderr; + else + statusfp = fdopen( fd, "w" ); + if( !statusfp ) { + log_fatal("can't open fd %d for status output: %s\n", + fd, strerror(errno)); + } + last_fd = fd; + register_primegen_progress ( progress_cb, "primegen" ); + register_pk_dsa_progress ( progress_cb, "pk_dsa" ); + register_pk_elg_progress ( progress_cb, "pk_elg" ); +} + +int +is_status_enabled() +{ + return !!statusfp; +} + +void +write_status ( int no ) +{ + write_status_text( no, NULL ); +} + +void +write_status_text ( int no, const char *text) +{ + if( !statusfp ) + return; /* not enabled */ + + fputs ( "[GNUPG:] ", statusfp ); + fputs ( get_status_string (no), statusfp ); + if( text ) { + putc ( ' ', statusfp ); + for (; *text; text++) { + if (*text == '\n') + fputs ( "\\n", statusfp ); + else if (*text == '\r') + fputs ( "\\r", statusfp ); + else + putc ( *(const byte *)text, statusfp ); + } + } + putc ('\n',statusfp); + fflush (statusfp); +} + + +/* + * Write a status line with a buffer using %XX escapes. If WRAP is > + * 0 wrap the line after this length. If STRING is not NULL it will + * be prepended to the buffer, no escaping is done for string. + * A wrap of -1 forces spaces not to be encoded as %20. + */ +void +write_status_text_and_buffer ( int no, const char *string, + const char *buffer, size_t len, int wrap ) +{ + const char *s, *text; + int esc, first; + int lower_limit = ' '; + size_t n, count, dowrap; + + if( !statusfp ) + return; /* not enabled */ + + if (wrap == -1) { + lower_limit--; + wrap = 0; + } + + text = get_status_string (no); + count = dowrap = first = 1; + do { + if (dowrap) { + fprintf (statusfp, "[GNUPG:] %s ", text ); + count = dowrap = 0; + if (first && string) { + fputs (string, statusfp); + count += strlen (string); + } + first = 0; + } + for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) { + if ( *s == '%' || *(const byte*)s <= lower_limit + || *(const byte*)s == 127 ) + esc = 1; + if ( wrap && ++count > wrap ) { + dowrap=1; + break; + } + } + if (esc) { + s--; n++; + } + if (s != buffer) + fwrite (buffer, s-buffer, 1, statusfp ); + if ( esc ) { + fprintf (statusfp, "%%%02X", *(const byte*)s ); + s++; n--; + } + buffer = s; + len = n; + if ( dowrap && len ) + putc ( '\n', statusfp ); + } while ( len ); + + putc ('\n',statusfp); + fflush (statusfp); +} + +void +write_status_buffer ( int no, const char *buffer, size_t len, int wrap ) +{ + write_status_text_and_buffer (no, NULL, buffer, len, wrap); +} + + + +#ifdef USE_SHM_COPROCESSING + +#ifndef IPC_RMID_DEFERRED_RELEASE +static void +remove_shmid( void ) +{ + if( shm_id != -1 ) { + shmctl ( shm_id, IPC_RMID, 0); + shm_id = -1; + } +} +#endif + +void +init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ) +{ + char buf[100]; + struct shmid_ds shmds; + +#ifndef IPC_RMID_DEFERRED_RELEASE + atexit( remove_shmid ); +#endif + requested_shm_size = (requested_shm_size + 4095) & ~4095; + if ( requested_shm_size > 2 * 4096 ) + log_fatal("too much shared memory requested; only 8k are allowed\n"); + shm_size = 4096 /* one page for us */ + requested_shm_size; + + shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 ); + if ( shm_id == -1 ) + log_fatal("can't get %uk of shared memory: %s\n", + (unsigned)shm_size/1024, strerror(errno)); + +#if !defined(IPC_HAVE_SHM_LOCK) \ + && defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) + /* part of the old code which uses mlock */ + shm_area = shmat( shm_id, 0, 0 ); + if ( shm_area == (char*)-1 ) + log_fatal("can't attach %uk shared memory: %s\n", + (unsigned)shm_size/1024, strerror(errno)); + log_debug("mapped %uk shared memory at %p, id=%d\n", + (unsigned)shm_size/1024, shm_area, shm_id ); + if( lock_mem ) { +#ifdef USE_CAPABILITIES + cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); +#endif + /* (need the cast for Solaris with Sun's workshop compilers) */ + if ( mlock ( (char*)shm_area, shm_size) ) + log_info("locking shared memory %d failed: %s\n", + shm_id, strerror(errno)); + else + shm_is_locked = 1; +#ifdef USE_CAPABILITIES + cap_set_proc( cap_from_text("cap_ipc_lock+p") ); +#endif + } + +#ifdef IPC_RMID_DEFERRED_RELEASE + if( shmctl( shm_id, IPC_RMID, 0) ) + log_fatal("shmctl IPC_RMDID of %d failed: %s\n", + shm_id, strerror(errno)); +#endif + + if( shmctl( shm_id, IPC_STAT, &shmds ) ) + log_fatal("shmctl IPC_STAT of %d failed: %s\n", + shm_id, strerror(errno)); + if( shmds.shm_perm.uid != getuid() ) { + shmds.shm_perm.uid = getuid(); + if( shmctl( shm_id, IPC_SET, &shmds ) ) + log_fatal("shmctl IPC_SET of %d failed: %s\n", + shm_id, strerror(errno)); + } + +#else /* this is the new code which handles the changes in the SHM + * semantics introduced with Linux 2.4. The changes is that we + * now change the permissions and then attach to the memory. + */ + + if( lock_mem ) { +#ifdef USE_CAPABILITIES + cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); +#endif +#ifdef IPC_HAVE_SHM_LOCK + if ( shmctl (shm_id, SHM_LOCK, 0) ) + log_info("locking shared memory %d failed: %s\n", + shm_id, strerror(errno)); + else + shm_is_locked = 1; +#else + log_info("Locking shared memory %d failed: No way to do it\n", shm_id ); +#endif +#ifdef USE_CAPABILITIES + cap_set_proc( cap_from_text("cap_ipc_lock+p") ); +#endif + } + + if( shmctl( shm_id, IPC_STAT, &shmds ) ) + log_fatal("shmctl IPC_STAT of %d failed: %s\n", + shm_id, strerror(errno)); + if( shmds.shm_perm.uid != getuid() ) { + shmds.shm_perm.uid = getuid(); + if( shmctl( shm_id, IPC_SET, &shmds ) ) + log_fatal("shmctl IPC_SET of %d failed: %s\n", + shm_id, strerror(errno)); + } + + shm_area = shmat( shm_id, 0, 0 ); + if ( shm_area == (char*)-1 ) + log_fatal("can't attach %uk shared memory: %s\n", + (unsigned)shm_size/1024, strerror(errno)); + log_debug("mapped %uk shared memory at %p, id=%d\n", + (unsigned)shm_size/1024, shm_area, shm_id ); + +#ifdef IPC_RMID_DEFERRED_RELEASE + if( shmctl( shm_id, IPC_RMID, 0) ) + log_fatal("shmctl IPC_RMDID of %d failed: %s\n", + shm_id, strerror(errno)); +#endif + +#endif + /* write info; Protocol version, id, size, locked size */ + sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(), + shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 ); + write_status_text( STATUS_SHM_INFO, buf ); +} + +/**************** + * Request a string from client + * If bool, returns static string on true (do not free) or NULL for false + */ +static char * +do_shm_get( const char *keyword, int hidden, int bool ) +{ + size_t n; + byte *p; + char *string; + + if( !shm_area ) + BUG(); + + shm_area[0] = 0; /* msb of length of control block */ + shm_area[1] = 32; /* and lsb */ + shm_area[2] = 1; /* indicate that we are waiting on a reply */ + shm_area[3] = 0; /* clear data available flag */ + + write_status_text( bool? STATUS_SHM_GET_BOOL : + hidden? STATUS_SHM_GET_HIDDEN : STATUS_SHM_GET, keyword ); + + do { + pause_on_sigusr(1); + if( shm_area[0] || shm_area[1] != 32 || shm_area[2] != 1 ) + log_fatal("client modified shm control block - abort\n"); + } while( !shm_area[3] ); + shm_area[2] = 0; /* reset request flag */ + p = (byte*)shm_area+32; + n = p[0] << 8 | p[1]; + p += 2; + if( n+32+2+1 > 4095 ) + log_fatal("client returns too large data (%u bytes)\n", (unsigned)n ); + + if( bool ) + return p[0]? "" : NULL; + + string = hidden? m_alloc_secure( n+1 ) : m_alloc( n+1 ); + memcpy(string, p, n ); + string[n] = 0; /* make sure it is a string */ + if( hidden ) /* invalidate the memory */ + memset( p, 0, n ); + + return string; +} + +#endif /* USE_SHM_COPROCESSING */ + +static int +myread(int fd, void *buf, size_t count) +{ + int rc; + do { + rc = read( fd, buf, count ); + } while ( rc == -1 && errno == EINTR ); + if ( !rc && count ) { + static int eof_emmited=0; + if ( eof_emmited < 3 ) { + *(char*)buf = CONTROL_D; + rc = 1; + eof_emmited++; + } + else { /* Ctrl-D not caught - do something reasonable */ +#ifdef HAVE_DOSISH_SYSTEM + raise (SIGINT); /* nothing to hangup under DOS */ +#else + raise (SIGHUP); /* no more input data */ +#endif + } + } + return rc; +} + + + +/**************** + * Request a string from the client over the command-fd + * If bool, returns static string on true (do not free) or NULL for false + */ +static char * +do_get_from_fd( const char *keyword, int hidden, int bool ) +{ + int i, len; + char *string; + + write_status_text( bool? STATUS_GET_BOOL : + hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword ); + + for( string = NULL, i = len = 200; ; i++ ) { + if( i >= len-1 ) { + char *save = string; + len += 100; + string = hidden? m_alloc_secure ( len ) : m_alloc ( len ); + if( save ) + memcpy(string, save, i ); + else + i=0; + } + /* Hmmm: why not use our read_line function here */ + if( myread( opt.command_fd, string+i, 1) != 1 || string[i] == '\n' ) + break; + else if ( string[i] == CONTROL_D ) { + /* found ETX - cancel the line and return a sole ETX */ + string[0] = CONTROL_D; + i=1; + break; + } + } + string[i] = 0; + + write_status( STATUS_GOT_IT ); + + if( bool ) /* Fixme: is this correct??? */ + return (string[0] == 'Y' || string[0] == 'y') ? "" : NULL; + + return string; +} + + + +int +cpr_enabled() +{ + if( opt.command_fd != -1 ) + return 1; +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return 1; +#endif + return 0; +} + +char * +cpr_get_no_help( const char *keyword, const char *prompt ) +{ + char *p; + + if( opt.command_fd != -1 ) + return do_get_from_fd ( keyword, 0, 0 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return do_shm_get( keyword, 0, 0 ); +#endif + for(;;) { + p = tty_get( prompt ); + return p; + } +} + +char * +cpr_get( const char *keyword, const char *prompt ) +{ + char *p; + + if( opt.command_fd != -1 ) + return do_get_from_fd ( keyword, 0, 0 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return do_shm_get( keyword, 0, 0 ); +#endif + for(;;) { + p = tty_get( prompt ); + if( *p=='?' && !p[1] && !(keyword && !*keyword)) { + m_free(p); + display_online_help( keyword ); + } + else + return p; + } +} + + +char * +cpr_get_utf8( const char *keyword, const char *prompt ) +{ + char *p; + p = cpr_get( keyword, prompt ); + if( p ) { + char *utf8 = native_to_utf8( p ); + m_free( p ); + p = utf8; + } + return p; +} + +char * +cpr_get_hidden( const char *keyword, const char *prompt ) +{ + char *p; + + if( opt.command_fd != -1 ) + return do_get_from_fd ( keyword, 1, 0 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return do_shm_get( keyword, 1, 0 ); +#endif + for(;;) { + p = tty_get_hidden( prompt ); + if( *p == '?' && !p[1] ) { + m_free(p); + display_online_help( keyword ); + } + else + return p; + } +} + +void +cpr_kill_prompt(void) +{ + if( opt.command_fd != -1 ) + return; +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return; +#endif + tty_kill_prompt(); + return; +} + +int +cpr_get_answer_is_yes( const char *keyword, const char *prompt ) +{ + int yes; + char *p; + + if( opt.command_fd != -1 ) + return !!do_get_from_fd ( keyword, 0, 1 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return !!do_shm_get( keyword, 0, 1 ); +#endif + for(;;) { + p = tty_get( prompt ); + trim_spaces(p); /* it is okay to do this here */ + if( *p == '?' && !p[1] ) { + m_free(p); + display_online_help( keyword ); + } + else { + tty_kill_prompt(); + yes = answer_is_yes(p); + m_free(p); + return yes; + } + } +} + +int +cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) +{ + int yes; + char *p; + + if( opt.command_fd != -1 ) + return !!do_get_from_fd ( keyword, 0, 1 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return !!do_shm_get( keyword, 0, 1 ); +#endif + for(;;) { + p = tty_get( prompt ); + trim_spaces(p); /* it is okay to do this here */ + if( *p == '?' && !p[1] ) { + m_free(p); + display_online_help( keyword ); + } + else { + tty_kill_prompt(); + yes = answer_is_yes_no_quit(p); + m_free(p); + return yes; + } + } +} diff --git a/g10/tdbio.c b/g10/tdbio.c new file mode 100644 index 000000000..bc609adee --- /dev/null +++ b/g10/tdbio.c @@ -0,0 +1,1624 @@ +/* tdbio.c + * 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 <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "errors.h" +#include "iobuf.h" +#include "memory.h" +#include "util.h" +#include "options.h" +#include "main.h" +#include "i18n.h" +#include "trustdb.h" +#include "tdbio.h" + +#if defined(HAVE_DOSISH_SYSTEM) +#define ftruncate chsize +#endif + +#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) +#define MY_O_BINARY O_BINARY +#else +#define MY_O_BINARY 0 +#endif + + +/**************** + * Yes, this is a very simple implementation. We should really + * use a page aligned buffer and read complete pages. + * To implement a simple trannsaction system, this is sufficient. + */ +typedef struct cache_ctrl_struct *CACHE_CTRL; +struct cache_ctrl_struct { + CACHE_CTRL next; + struct { + unsigned used:1; + unsigned dirty:1; + } flags; + ulong recno; + char data[TRUST_RECORD_LEN]; +}; + +#define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased while in a */ +#define MAX_CACHE_ENTRIES_HARD 10000 /* transaction to this one */ +static CACHE_CTRL cache_list; +static int cache_entries; +static int cache_is_dirty; + +/* a type used to pass infomation to cmp_krec_fpr */ +struct cmp_krec_fpr_struct { + int pubkey_algo; + const char *fpr; + int fprlen; +}; + +/* a type used to pass infomation to cmp_[s]dir */ +struct cmp_xdir_struct { + int pubkey_algo; + u32 keyid[2]; +}; + + +static char *db_name; +static DOTLOCK lockhandle; +static int is_locked; +static int db_fd = -1; +static int in_transaction; + +static void open_db(void); +static void migrate_from_v2 (void); + + + +/************************************* + ************* record cache ********** + *************************************/ + +/**************** + * Get the data from therecord cache and return a + * pointer into that cache. Caller should copy + * the return data. NULL is returned on a cache miss. + */ +static const char * +get_record_from_cache( ulong recno ) +{ + CACHE_CTRL r; + + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->recno == recno ) + return r->data; + } + return NULL; +} + + +static int +write_cache_item( CACHE_CTRL r ) +{ + int n; + + if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb rec %lu: lseek failed: %s\n"), + r->recno, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + n = write( db_fd, r->data, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), + r->recno, n, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + r->flags.dirty = 0; + return 0; +} + +/**************** + * Put data into the cache. This function may flush the + * some cache entries if there is not enough space available. + */ +int +put_record_into_cache( ulong recno, const char *data ) +{ + CACHE_CTRL r, unused; + int dirty_count = 0; + int clean_count = 0; + + /* see whether we already cached this one */ + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( !r->flags.used ) { + if( !unused ) + unused = r; + } + else if( r->recno == recno ) { + if( !r->flags.dirty ) { + /* Hmmm: should we use a a copy and compare? */ + if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) { + r->flags.dirty = 1; + cache_is_dirty = 1; + } + } + memcpy( r->data, data, TRUST_RECORD_LEN ); + return 0; + } + if( r->flags.used ) { + if( r->flags.dirty ) + dirty_count++; + else + clean_count++; + } + } + /* not in the cache: add a new entry */ + if( unused ) { /* reuse this entry */ + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_is_dirty = 1; + cache_entries++; + return 0; + } + /* see whether we reached the limit */ + if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */ + r = m_alloc( sizeof *r ); + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + r->next = cache_list; + cache_list = r; + cache_is_dirty = 1; + cache_entries++; + return 0; + } + /* cache is full: discard some clean entries */ + if( clean_count ) { + int n = clean_count / 3; /* discard a third of the clean entries */ + if( !n ) + n = 1; + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( r->flags.used && !r->flags.dirty ) { + if( !unused ) + unused = r; + r->flags.used = 0; + cache_entries--; + if( !--n ) + break; + } + } + assert( unused ); + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_is_dirty = 1; + cache_entries++; + return 0; + } + /* no clean entries: have to flush some dirty entries */ + if( in_transaction ) { + /* but we can't do this while in a transaction + * we increase the cache size instead */ + if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */ + if( opt.debug && !(cache_entries % 100) ) + log_debug("increasing tdbio cache size\n"); + r = m_alloc( sizeof *r ); + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + r->next = cache_list; + cache_list = r; + cache_is_dirty = 1; + cache_entries++; + return 0; + } + log_info(_("trustdb transaction too large\n")); + return G10ERR_RESOURCE_LIMIT; + } + if( dirty_count ) { + int n = dirty_count / 5; /* discard some dirty entries */ + if( !n ) + n = 1; + if( !is_locked ) { + if( make_dotlock( lockhandle, -1 ) ) + log_fatal("can't acquire lock - giving up\n"); + else + is_locked = 1; + } + for( unused = NULL, r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + int rc = write_cache_item( r ); + if( rc ) + return rc; + if( !unused ) + unused = r; + r->flags.used = 0; + cache_entries--; + if( !--n ) + break; + } + } + if( !opt.lock_once ) { + if( !release_dotlock( lockhandle ) ) + is_locked = 0; + } + assert( unused ); + r = unused; + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + cache_is_dirty = 1; + cache_entries++; + return 0; + } + BUG(); +} + + +int +tdbio_is_dirty() +{ + return cache_is_dirty; +} + + +/**************** + * Flush the cache. This cannot be used while in a transaction. + */ +int +tdbio_sync() +{ + CACHE_CTRL r; + int did_lock = 0; + + if( db_fd == -1 ) + open_db(); + if( in_transaction ) + log_bug("tdbio: syncing while in transaction\n"); + + if( !cache_is_dirty ) + return 0; + + if( !is_locked ) { + if( make_dotlock( lockhandle, -1 ) ) + log_fatal("can't acquire lock - giving up\n"); + else + is_locked = 1; + did_lock = 1; + } + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + int rc = write_cache_item( r ); + if( rc ) + return rc; + } + } + cache_is_dirty = 0; + if( did_lock && !opt.lock_once ) { + if( !release_dotlock( lockhandle ) ) + is_locked = 0; + } + + return 0; +} + + + +/**************** + * Simple transactions system: + * Everything between begin_transaction and end/cancel_transaction + * is not immediatly written but at the time of end_transaction. + * + */ +int +tdbio_begin_transaction() +{ + int rc; + + if( in_transaction ) + log_bug("tdbio: nested transactions\n"); + /* flush everything out */ + rc = tdbio_sync(); + if( rc ) + return rc; + in_transaction = 1; + return 0; +} + +int +tdbio_end_transaction() +{ + int rc; + + if( !in_transaction ) + log_bug("tdbio: no active transaction\n"); + if( !is_locked ) { + if( make_dotlock( lockhandle, -1 ) ) + log_fatal("can't acquire lock - giving up\n"); + else + is_locked = 1; + } + block_all_signals(); + in_transaction = 0; + rc = tdbio_sync(); + unblock_all_signals(); + if( !opt.lock_once ) { + if( !release_dotlock( lockhandle ) ) + is_locked = 0; + } + return rc; +} + +int +tdbio_cancel_transaction() +{ + CACHE_CTRL r; + + if( !in_transaction ) + log_bug("tdbio: no active transaction\n"); + + /* remove all dirty marked entries, so that the original ones + * are read back the next time */ + if( cache_is_dirty ) { + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + r->flags.used = 0; + cache_entries--; + } + } + cache_is_dirty = 0; + } + + in_transaction = 0; + return 0; +} + + + +/******************************************************** + **************** cached I/O functions ****************** + ********************************************************/ + +static void +cleanup(void) +{ + if( is_locked ) { + if( !release_dotlock(lockhandle) ) + is_locked = 0; + } +} + +/* Caller must sync */ +int +tdbio_update_version_record (void) +{ + TRUSTREC rec; + int rc; + + memset( &rec, 0, sizeof rec ); + + rc=tdbio_read_record( 0, &rec, RECTYPE_VER); + if(rc==0) + { + rec.r.ver.created = make_timestamp(); + rec.r.ver.marginals = opt.marginals_needed; + rec.r.ver.completes = opt.completes_needed; + rec.r.ver.cert_depth = opt.max_cert_depth; + rec.r.ver.trust_model = opt.trust_model; + rc=tdbio_write_record(&rec); + } + + return rc; +} + +static int +create_version_record (void) +{ + TRUSTREC rec; + int rc; + + memset( &rec, 0, sizeof rec ); + rec.r.ver.version = 3; + rec.r.ver.created = make_timestamp(); + rec.r.ver.marginals = opt.marginals_needed; + rec.r.ver.completes = opt.completes_needed; + rec.r.ver.cert_depth = opt.max_cert_depth; + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + rec.r.ver.trust_model = opt.trust_model; + else + rec.r.ver.trust_model = TM_PGP; + rec.rectype = RECTYPE_VER; + rec.recnum = 0; + rc = tdbio_write_record( &rec ); + if( !rc ) + tdbio_sync(); + return rc; +} + + + +int +tdbio_set_dbname( const char *new_dbname, int create ) +{ + char *fname; + static int initialized = 0; + + if( !initialized ) { + atexit( cleanup ); + initialized = 1; + } + + if(new_dbname==NULL) + fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "gpg", NULL); + else if (*new_dbname != DIRSEP_C ) + { + if (strchr(new_dbname, DIRSEP_C) ) + fname = make_filename (new_dbname, NULL); + else + fname = make_filename (opt.homedir, new_dbname, NULL); + } + else + fname = m_strdup (new_dbname); + + if( access( fname, R_OK ) ) { + if( errno != ENOENT ) { + log_error( _("%s: can't access: %s\n"), fname, strerror(errno) ); + m_free(fname); + return G10ERR_TRUSTDB; + } + if( create ) { + FILE *fp; + TRUSTREC rec; + int rc; + char *p = strrchr( fname, DIRSEP_C ); + mode_t oldmask; + + assert(p); + *p = 0; + if( access( fname, F_OK ) ) { + try_make_homedir( fname ); + log_fatal( _("%s: directory does not exist!\n"), fname ); + } + *p = DIRSEP_C; + + m_free(db_name); + db_name = fname; +#ifdef __riscos__ + if( !lockhandle ) + lockhandle = create_dotlock( db_name ); + if( !lockhandle ) + log_fatal( _("%s: can't create lock\n"), db_name ); + if( make_dotlock( lockhandle, -1 ) ) + log_fatal( _("%s: can't make lock\n"), db_name ); +#endif /* __riscos__ */ + oldmask=umask(077); + fp =fopen( fname, "wb" ); + umask(oldmask); + if( !fp ) + log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) ); + fclose(fp); + db_fd = open( db_name, O_RDWR | MY_O_BINARY ); + if( db_fd == -1 ) + log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + +#ifndef __riscos__ + if( !lockhandle ) + lockhandle = create_dotlock( db_name ); + if( !lockhandle ) + log_fatal( _("%s: can't create lock\n"), db_name ); +#endif /* !__riscos__ */ + + rc = create_version_record (); + if( rc ) + log_fatal( _("%s: failed to create version record: %s"), + fname, g10_errstr(rc)); + /* and read again to check that we are okay */ + if( tdbio_read_record( 0, &rec, RECTYPE_VER ) ) + log_fatal( _("%s: invalid trustdb created\n"), db_name ); + + if( !opt.quiet ) + log_info(_("%s: trustdb created\n"), db_name); + + return 0; + } + } + m_free(db_name); + db_name = fname; + return 0; +} + + +const char * +tdbio_get_dbname() +{ + return db_name; +} + + + +static void +open_db() +{ + byte buf[10]; + int n; + TRUSTREC rec; + + assert( db_fd == -1 ); + + if (!lockhandle ) + lockhandle = create_dotlock( db_name ); + if (!lockhandle ) + log_fatal( _("%s: can't create lock\n"), db_name ); +#ifdef __riscos__ + if (make_dotlock( lockhandle, -1 ) ) + log_fatal( _("%s: can't make lock\n"), db_name ); +#endif /* __riscos__ */ + db_fd = open (db_name, O_RDWR | MY_O_BINARY ); + if (db_fd == -1 && errno == EACCES) { + db_fd = open (db_name, O_RDONLY | MY_O_BINARY ); + if (db_fd != -1) + log_info (_("NOTE: trustdb not writable\n")); + } + if ( db_fd == -1 ) + log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + + /* check whether we need to do a version migration */ + do + n = read (db_fd, buf, 5); + while (n==-1 && errno == EINTR); + if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5)) + { + migrate_from_v2 (); + } + + /* read the version record */ + if (tdbio_read_record (0, &rec, RECTYPE_VER ) ) + log_fatal( _("%s: invalid trustdb\n"), db_name ); +} + + +/**************** + * Make a hashtable: type 0 = trust hash + */ +static void +create_hashtable( TRUSTREC *vr, int type ) +{ + TRUSTREC rec; + off_t offset; + ulong recnum; + int i, n, rc; + + offset = lseek( db_fd, 0, SEEK_END ); + if( offset == -1 ) + log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) ); + recnum = offset / TRUST_RECORD_LEN; + assert(recnum); /* this is will never be the first record */ + + if( !type ) + vr->r.ver.trusthashtbl = recnum; + + /* Now write the records */ + n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD; + for(i=0; i < n; i++, recnum++ ) { + memset( &rec, 0, sizeof rec ); + rec.rectype = RECTYPE_HTBL; + rec.recnum = recnum; + rc = tdbio_write_record( &rec ); + if( rc ) + log_fatal( _("%s: failed to create hashtable: %s\n"), + db_name, g10_errstr(rc)); + } + /* update the version record */ + rc = tdbio_write_record( vr ); + if( !rc ) + rc = tdbio_sync(); + if( rc ) + log_fatal( _("%s: error updating version record: %s\n"), + db_name, g10_errstr(rc)); +} + + +int +tdbio_db_matches_options() +{ + static int yes_no = -1; + + if( yes_no == -1 ) + { + TRUSTREC vr; + int rc; + + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + + yes_no = vr.r.ver.marginals == opt.marginals_needed + && vr.r.ver.completes == opt.completes_needed + && vr.r.ver.cert_depth == opt.max_cert_depth + && vr.r.ver.trust_model == opt.trust_model; + } + + return yes_no; +} + +byte +tdbio_read_model(void) +{ + TRUSTREC vr; + int rc; + + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + return vr.r.ver.trust_model; +} + +/**************** + * Return the nextstamp value. + */ +ulong +tdbio_read_nextcheck () +{ + TRUSTREC vr; + int rc; + + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + return vr.r.ver.nextcheck; +} + +/* Return true when the stamp was actually changed. */ +int +tdbio_write_nextcheck (ulong stamp) +{ + TRUSTREC vr; + int rc; + + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + + if (vr.r.ver.nextcheck == stamp) + return 0; + + vr.r.ver.nextcheck = stamp; + rc = tdbio_write_record( &vr ); + if( rc ) + log_fatal( _("%s: error writing version record: %s\n"), + db_name, g10_errstr(rc) ); + return 1; +} + + + +/**************** + * Return the record number of the trusthash tbl or create a new one. + */ +static ulong +get_trusthashrec(void) +{ + static ulong trusthashtbl; /* record number of the trust hashtable */ + + if( !trusthashtbl ) { + TRUSTREC vr; + int rc; + + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + if( !vr.r.ver.trusthashtbl ) + create_hashtable( &vr, 0 ); + + trusthashtbl = vr.r.ver.trusthashtbl; + } + return trusthashtbl; +} + + + +/**************** + * Update a hashtable. + * table gives the start of the table, key and keylen is the key, + * newrecnum is the record number to insert. + */ +static int +upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) +{ + TRUSTREC lastrec, rec; + ulong hashrec, item; + int msb; + int level=0; + int rc, i; + + hashrec = table; + next_level: + msb = key[level]; + hashrec += msb / ITEMS_PER_HTBL_RECORD; + rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); + if( rc ) { + log_error( db_name, "upd_hashtable: read failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; + if( !item ) { /* insert a new item into the hash table */ + rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum; + rc = tdbio_write_record( &rec ); + if( rc ) { + log_error( db_name, "upd_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + else if( item != newrecnum ) { /* must do an update */ + lastrec = rec; + rc = tdbio_read_record( item, &rec, 0 ); + if( rc ) { + log_error( "upd_hashtable: read item failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + if( rec.rectype == RECTYPE_HTBL ) { + hashrec = item; + level++; + if( level >= keylen ) { + log_error( "hashtable has invalid indirections.\n"); + return G10ERR_TRUSTDB; + } + goto next_level; + } + else if( rec.rectype == RECTYPE_HLST ) { /* extend list */ + /* see whether the key is already in this list */ + for(;;) { + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + if( rec.r.hlst.rnum[i] == newrecnum ) { + return 0; /* okay, already in the list */ + } + } + if( rec.r.hlst.next ) { + rc = tdbio_read_record( rec.r.hlst.next, + &rec, RECTYPE_HLST); + if( rc ) { + log_error( "upd_hashtable: read hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + else + break; /* not there */ + } + /* find the next free entry and put it in */ + for(;;) { + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + if( !rec.r.hlst.rnum[i] ) { + rec.r.hlst.rnum[i] = newrecnum; + rc = tdbio_write_record( &rec ); + if( rc ) + log_error( "upd_hashtable: write hlst failed: %s\n", + g10_errstr(rc) ); + return rc; /* done */ + } + } + if( rec.r.hlst.next ) { + rc = tdbio_read_record( rec.r.hlst.next, + &rec, RECTYPE_HLST ); + if( rc ) { + log_error( "upd_hashtable: read hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + else { /* add a new list record */ + rec.r.hlst.next = item = tdbio_new_recnum(); + rc = tdbio_write_record( &rec ); + if( rc ) { + log_error( "upd_hashtable: write hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + memset( &rec, 0, sizeof rec ); + rec.rectype = RECTYPE_HLST; + rec.recnum = item; + rec.r.hlst.rnum[0] = newrecnum; + rc = tdbio_write_record( &rec ); + if( rc ) + log_error( "upd_hashtable: write ext hlst failed: %s\n", + g10_errstr(rc) ); + return rc; /* done */ + } + } /* end loop over hlst slots */ + } + else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */ + if( rec.recnum == newrecnum ) { + return 0; + } + item = rec.recnum; /* save number of key record */ + memset( &rec, 0, sizeof rec ); + rec.rectype = RECTYPE_HLST; + rec.recnum = tdbio_new_recnum(); + rec.r.hlst.rnum[0] = item; /* old keyrecord */ + rec.r.hlst.rnum[1] = newrecnum; /* and new one */ + rc = tdbio_write_record( &rec ); + if( rc ) { + log_error( "upd_hashtable: write new hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + /* update the hashtable record */ + lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum; + rc = tdbio_write_record( &lastrec ); + if( rc ) + log_error( "upd_hashtable: update htbl failed: %s\n", + g10_errstr(rc) ); + return rc; /* ready */ + } + else { + log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n", + table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); + list_trustdb(NULL); + return G10ERR_TRUSTDB; + } + } + + return 0; +} + + +/**************** + * Drop an entry from a hashtable + * table gives the start of the table, key and keylen is the key, + */ +static int +drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) +{ + TRUSTREC rec; + ulong hashrec, item; + int msb; + int level=0; + int rc, i; + + hashrec = table; + next_level: + msb = key[level]; + hashrec += msb / ITEMS_PER_HTBL_RECORD; + rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); + if( rc ) { + log_error( db_name, "drop_from_hashtable: read failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; + if( !item ) /* not found - forget about it */ + return 0; + + if( item == recnum ) { /* tables points direct to the record */ + rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0; + rc = tdbio_write_record( &rec ); + if( rc ) + log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + rc = tdbio_read_record( item, &rec, 0 ); + if( rc ) { + log_error( "drop_from_hashtable: read item failed: %s\n", + g10_errstr(rc) ); + return rc; + } + + if( rec.rectype == RECTYPE_HTBL ) { + hashrec = item; + level++; + if( level >= keylen ) { + log_error( "hashtable has invalid indirections.\n"); + return G10ERR_TRUSTDB; + } + goto next_level; + } + + if( rec.rectype == RECTYPE_HLST ) { + for(;;) { + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + if( rec.r.hlst.rnum[i] == recnum ) { + rec.r.hlst.rnum[i] = 0; /* drop */ + rc = tdbio_write_record( &rec ); + if( rc ) + log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + if( rec.r.hlst.next ) { + rc = tdbio_read_record( rec.r.hlst.next, + &rec, RECTYPE_HLST); + if( rc ) { + log_error( "drop_from_hashtable: read hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + else + return 0; /* key not in table */ + } + } + + log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n", + table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); + return G10ERR_TRUSTDB; +} + + + +/**************** + * Lookup a record via the hashtable tablewith key/keylen and return the + * result in rec. cmp() should return if the record is the desired one. + * Returns -1 if not found, 0 if found or another errocode + */ +static int +lookup_hashtable( ulong table, const byte *key, size_t keylen, + int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata, + TRUSTREC *rec ) +{ + int rc; + ulong hashrec, item; + int msb; + int level=0; + + hashrec = table; + next_level: + msb = key[level]; + hashrec += msb / ITEMS_PER_HTBL_RECORD; + rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL ); + if( rc ) { + log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) ); + return rc; + } + + item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; + if( !item ) + return -1; /* not found */ + + rc = tdbio_read_record( item, rec, 0 ); + if( rc ) { + log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) ); + return rc; + } + if( rec->rectype == RECTYPE_HTBL ) { + hashrec = item; + level++; + if( level >= keylen ) { + log_error( db_name, "hashtable has invalid indirections\n"); + return G10ERR_TRUSTDB; + } + goto next_level; + } + else if( rec->rectype == RECTYPE_HLST ) { + for(;;) { + int i; + + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + if( rec->r.hlst.rnum[i] ) { + TRUSTREC tmp; + + rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 ); + if( rc ) { + log_error( "lookup_hashtable: read item failed: %s\n", + g10_errstr(rc) ); + return rc; + } + if( (*cmpfnc)( cmpdata, &tmp ) ) { + *rec = tmp; + return 0; + } + } + } + if( rec->r.hlst.next ) { + rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST ); + if( rc ) { + log_error( "lookup_hashtable: read hlst failed: %s\n", + g10_errstr(rc) ); + return rc; + } + } + else + return -1; /* not found */ + } + } + + + if( (*cmpfnc)( cmpdata, rec ) ) + return 0; /* really found */ + + return -1; /* no: not found */ +} + + +/**************** + * Update the trust hashtbl or create the table if it does not exist + */ +static int +update_trusthashtbl( TRUSTREC *tr ) +{ + return upd_hashtable( get_trusthashrec(), + tr->r.trust.fingerprint, 20, tr->recnum ); +} + + + +void +tdbio_dump_record( TRUSTREC *rec, FILE *fp ) +{ + int i; + ulong rnum = rec->recnum; + + fprintf(fp, "rec %5lu, ", rnum ); + + switch( rec->rectype ) { + case 0: fprintf(fp, "blank\n"); + break; + case RECTYPE_VER: fprintf(fp, + "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d nc=%lu (%s)\n", + rec->r.ver.trusthashtbl, + rec->r.ver.firstfree, + rec->r.ver.marginals, + rec->r.ver.completes, + rec->r.ver.cert_depth, + rec->r.ver.trust_model, + rec->r.ver.nextcheck, + strtimestamp(rec->r.ver.nextcheck) + ); + break; + case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next ); + break; + case RECTYPE_HTBL: + fprintf(fp, "htbl,"); + for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) + fprintf(fp, " %lu", rec->r.htbl.item[i] ); + putc('\n', fp); + break; + case RECTYPE_HLST: + fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next ); + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) + fprintf(fp, " %lu", rec->r.hlst.rnum[i] ); + putc('\n', fp); + break; + case RECTYPE_TRUST: + fprintf(fp, "trust "); + for(i=0; i < 20; i++ ) + fprintf(fp, "%02X", rec->r.trust.fingerprint[i] ); + fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust, + rec->r.trust.depth, rec->r.trust.validlist); + break; + case RECTYPE_VALID: + fprintf(fp, "valid "); + for(i=0; i < 20; i++ ) + fprintf(fp, "%02X", rec->r.valid.namehash[i] ); + fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity, + rec->r.valid.next); + break; + default: + fprintf(fp, "unknown type %d\n", rec->rectype ); + break; + } +} + +/**************** + * read the record with number recnum + * returns: -1 on error, 0 on success + */ +int +tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) +{ + byte readbuf[TRUST_RECORD_LEN]; + const byte *buf, *p; + int rc = 0; + int n, i; + + if( db_fd == -1 ) + open_db(); + buf = get_record_from_cache( recnum ); + if( !buf ) { + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); + return G10ERR_READ_FILE; + } + n = read( db_fd, readbuf, TRUST_RECORD_LEN); + if( !n ) { + return -1; /* eof */ + } + else if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb: read failed (n=%d): %s\n"), n, + strerror(errno) ); + return G10ERR_READ_FILE; + } + buf = readbuf; + } + rec->recnum = recnum; + rec->dirty = 0; + p = buf; + rec->rectype = *p++; + if( expected && rec->rectype != expected ) { + log_error("%lu: read expected rec type %d, got %d\n", + recnum, expected, rec->rectype ); + return G10ERR_TRUSTDB; + } + p++; /* skip reserved byte */ + switch( rec->rectype ) { + case 0: /* unused (free) record */ + break; + case RECTYPE_VER: /* version record */ + if( memcmp(buf+1, "gpg", 3 ) ) { + log_error( _("%s: not a trustdb file\n"), db_name ); + rc = G10ERR_TRUSTDB; + } + p += 2; /* skip "gpg" */ + rec->r.ver.version = *p++; + rec->r.ver.marginals = *p++; + rec->r.ver.completes = *p++; + rec->r.ver.cert_depth = *p++; + rec->r.ver.trust_model = *p++; + p += 3; + rec->r.ver.created = buftoulong(p); p += 4; + rec->r.ver.nextcheck = buftoulong(p); p += 4; + p += 4; + p += 4; + rec->r.ver.firstfree =buftoulong(p); p += 4; + p += 4; + rec->r.ver.trusthashtbl =buftoulong(p); p += 4; + if( recnum ) { + log_error( _("%s: version record with recnum %lu\n"), db_name, + (ulong)recnum ); + rc = G10ERR_TRUSTDB; + } + else if( rec->r.ver.version != 3 ) { + log_error( _("%s: invalid file version %d\n"), db_name, + rec->r.ver.version ); + rc = G10ERR_TRUSTDB; + } + break; + case RECTYPE_FREE: + rec->r.free.next = buftoulong(p); p += 4; + break; + case RECTYPE_HTBL: + for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) { + rec->r.htbl.item[i] = buftoulong(p); p += 4; + } + break; + case RECTYPE_HLST: + rec->r.hlst.next = buftoulong(p); p += 4; + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + rec->r.hlst.rnum[i] = buftoulong(p); p += 4; + } + break; + case RECTYPE_TRUST: + memcpy( rec->r.trust.fingerprint, p, 20); p+=20; + rec->r.trust.ownertrust = *p++; + rec->r.trust.depth = *p++; + rec->r.trust.min_ownertrust = *p++; + p++; + rec->r.trust.validlist = buftoulong(p); p += 4; + break; + case RECTYPE_VALID: + memcpy( rec->r.valid.namehash, p, 20); p+=20; + rec->r.valid.validity = *p++; + rec->r.valid.next = buftoulong(p); p += 4; + rec->r.valid.full_count = *p++; + rec->r.valid.marginal_count = *p++; + break; + default: + log_error( "%s: invalid record type %d at recnum %lu\n", + db_name, rec->rectype, (ulong)recnum ); + rc = G10ERR_TRUSTDB; + break; + } + + return rc; +} + +/**************** + * Write the record at RECNUM + */ +int +tdbio_write_record( TRUSTREC *rec ) +{ + byte buf[TRUST_RECORD_LEN], *p; + int rc = 0; + int i; + ulong recnum = rec->recnum; + + if( db_fd == -1 ) + open_db(); + + memset(buf, 0, TRUST_RECORD_LEN); + p = buf; + *p++ = rec->rectype; p++; + switch( rec->rectype ) { + case 0: /* unused record */ + break; + case RECTYPE_VER: /* version record */ + if( recnum ) + BUG(); + memcpy(p-1, "gpg", 3 ); p += 2; + *p++ = rec->r.ver.version; + *p++ = rec->r.ver.marginals; + *p++ = rec->r.ver.completes; + *p++ = rec->r.ver.cert_depth; + *p++ = rec->r.ver.trust_model; + p += 3; + ulongtobuf(p, rec->r.ver.created); p += 4; + ulongtobuf(p, rec->r.ver.nextcheck); p += 4; + p += 4; + p += 4; + ulongtobuf(p, rec->r.ver.firstfree ); p += 4; + p += 4; + ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4; + break; + + case RECTYPE_FREE: + ulongtobuf(p, rec->r.free.next); p += 4; + break; + + + case RECTYPE_HTBL: + for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) { + ulongtobuf( p, rec->r.htbl.item[i]); p += 4; + } + break; + + case RECTYPE_HLST: + ulongtobuf( p, rec->r.hlst.next); p += 4; + for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4; + } + break; + + case RECTYPE_TRUST: + memcpy( p, rec->r.trust.fingerprint, 20); p += 20; + *p++ = rec->r.trust.ownertrust; + *p++ = rec->r.trust.depth; + *p++ = rec->r.trust.min_ownertrust; + p++; + ulongtobuf( p, rec->r.trust.validlist); p += 4; + break; + + case RECTYPE_VALID: + memcpy( p, rec->r.valid.namehash, 20); p += 20; + *p++ = rec->r.valid.validity; + ulongtobuf( p, rec->r.valid.next); p += 4; + *p++ = rec->r.valid.full_count; + *p++ = rec->r.valid.marginal_count; + break; + + default: + BUG(); + } + + rc = put_record_into_cache( recnum, buf ); + if( rc ) + ; + else if( rec->rectype == RECTYPE_TRUST ) + rc = update_trusthashtbl( rec ); + + return rc; +} + +int +tdbio_delete_record( ulong recnum ) +{ + TRUSTREC vr, rec; + int rc; + + /* Must read the record fist, so we can drop it from the hash tables */ + rc = tdbio_read_record( recnum, &rec, 0 ); + if( rc ) + ; + else if( rec.rectype == RECTYPE_TRUST ) { + rc = drop_from_hashtable( get_trusthashrec(), + rec.r.trust.fingerprint, 20, rec.recnum ); + } + + if( rc ) + return rc; + + /* now we can chnage it to a free record */ + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + + rec.recnum = recnum; + rec.rectype = RECTYPE_FREE; + rec.r.free.next = vr.r.ver.firstfree; + vr.r.ver.firstfree = recnum; + rc = tdbio_write_record( &rec ); + if( !rc ) + rc = tdbio_write_record( &vr ); + return rc; +} + +/**************** + * create a new record and return its record number + */ +ulong +tdbio_new_recnum() +{ + off_t offset; + ulong recnum; + TRUSTREC vr, rec; + int rc; + + /* look for unused records */ + rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); + if( rc ) + log_fatal( _("%s: error reading version record: %s\n"), + db_name, g10_errstr(rc) ); + if( vr.r.ver.firstfree ) { + recnum = vr.r.ver.firstfree; + rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE ); + if( rc ) { + log_error( _("%s: error reading free record: %s\n"), + db_name, g10_errstr(rc) ); + return rc; + } + /* update dir record */ + vr.r.ver.firstfree = rec.r.free.next; + rc = tdbio_write_record( &vr ); + if( rc ) { + log_error( _("%s: error writing dir record: %s\n"), + db_name, g10_errstr(rc) ); + return rc; + } + /*zero out the new record */ + memset( &rec, 0, sizeof rec ); + rec.rectype = 0; /* unused record */ + rec.recnum = recnum; + rc = tdbio_write_record( &rec ); + if( rc ) + log_fatal(_("%s: failed to zero a record: %s\n"), + db_name, g10_errstr(rc)); + } + else { /* not found, append a new record */ + offset = lseek( db_fd, 0, SEEK_END ); + if( offset == -1 ) + log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) ); + recnum = offset / TRUST_RECORD_LEN; + assert(recnum); /* this is will never be the first record */ + /* we must write a record, so that the next call to this function + * returns another recnum */ + memset( &rec, 0, sizeof rec ); + rec.rectype = 0; /* unused record */ + rec.recnum = recnum; + rc = 0; + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error(_("trustdb rec %lu: lseek failed: %s\n"), + recnum, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + } + else { + int n = write( db_fd, &rec, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), + recnum, n, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + } + } + + if( rc ) + log_fatal(_("%s: failed to append a record: %s\n"), + db_name, g10_errstr(rc)); + } + return recnum ; +} + + + +static int +cmp_trec_fpr ( void *fpr, const TRUSTREC *rec ) +{ + return rec->rectype == RECTYPE_TRUST + && !memcmp( rec->r.trust.fingerprint, fpr, 20); +} + + +int +tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec ) +{ + int rc; + + /* locate the trust record using the hash table */ + rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20, + cmp_trec_fpr, (void*)fingerprint, rec ); + return rc; +} + +int +tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec) +{ + byte fingerprint[MAX_FINGERPRINT_LEN]; + size_t fingerlen; + + fingerprint_from_pk( pk, fingerprint, &fingerlen ); + for (; fingerlen < 20; fingerlen++ ) + fingerprint[fingerlen] = 0; + return tdbio_search_trust_byfpr (fingerprint, rec); +} + + + +void +tdbio_invalid(void) +{ + log_error(_( + "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") ); + g10_exit(2); +} + +/* + * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2) + * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs + * only to scan the tdb and insert new the new trust records. The old ones are + * obsolte from now on + */ +static void +migrate_from_v2 () +{ + TRUSTREC rec; + int i, n; + struct { + ulong keyrecno; + byte ot; + byte okay; + byte fpr[20]; + } *ottable; + int ottable_size, ottable_used; + byte oldbuf[40]; + ulong recno; + int rc, count; + + ottable_size = 5; + ottable = m_alloc (ottable_size * sizeof *ottable); + ottable_used = 0; + + /* We have some restrictions here. We can't use the version record + * and we can't use any of the old hashtables because we dropped the + * code. So we first collect all ownertrusts and then use a second + * pass fo find the associated keys. We have to do this all without using + * the regular record read functions. + */ + + /* get all the ownertrusts */ + if (lseek (db_fd, 0, SEEK_SET ) == -1 ) + log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); + for (recno=0;;recno++) + { + do + n = read (db_fd, oldbuf, 40); + while (n==-1 && errno == EINTR); + if (!n) + break; /* eof */ + if (n != 40) + log_fatal ("migrate_vfrom_v2: read error or short read\n"); + + if (*oldbuf != 2) + continue; + + /* v2 dir record */ + if (ottable_used == ottable_size) + { + ottable_size += 1000; + ottable = m_realloc (ottable, ottable_size * sizeof *ottable); + } + ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); + ottable[ottable_used].ot = oldbuf[18]; + ottable[ottable_used].okay = 0; + memset (ottable[ottable_used].fpr,0, 20); + if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot) + ottable_used++; + } + log_info ("found %d ownertrust records\n", ottable_used); + + /* Read again and find the fingerprints */ + if (lseek (db_fd, 0, SEEK_SET ) == -1 ) + log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); + for (recno=0;;recno++) + { + do + n = read (db_fd, oldbuf, 40); + while (n==-1 && errno == EINTR); + if (!n) + break; /* eof */ + if (n != 40) + log_fatal ("migrate_from_v2: read error or short read\n"); + + if (*oldbuf != 3) + continue; + + /* v2 key record */ + for (i=0; i < ottable_used; i++) + { + if (ottable[i].keyrecno == recno) + { + memcpy (ottable[i].fpr, oldbuf+20, 20); + ottable[i].okay = 1; + break; + } + } + } + + /* got everything - create the v3 trustdb */ + if (ftruncate (db_fd, 0)) + log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) ); + if (create_version_record ()) + log_fatal ("failed to recreate version record of `%s'\n", db_name); + + /* access the hash table, so it is store just after the version record, + * this is not needed put a dump is more pretty */ + get_trusthashrec (); + + /* And insert the old ownertrust values */ + count = 0; + for (i=0; i < ottable_used; i++) + { + if (!ottable[i].okay) + continue; + + memset (&rec, 0, sizeof rec); + rec.recnum = tdbio_new_recnum (); + rec.rectype = RECTYPE_TRUST; + memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20); + rec.r.trust.ownertrust = ottable[i].ot; + if (tdbio_write_record (&rec)) + log_fatal ("failed to write trust record of `%s'\n", db_name); + count++; + } + + revalidation_mark (); + rc = tdbio_sync (); + if (rc) + log_fatal ("failed to sync `%s'\n", db_name); + log_info ("migrated %d version 2 ownertrusts\n", count); + m_free (ottable); +} + + + diff --git a/g10/tdbio.h b/g10/tdbio.h new file mode 100644 index 000000000..708e06d2b --- /dev/null +++ b/g10/tdbio.h @@ -0,0 +1,117 @@ +/* tdbio.h - Trust database I/O functions + * 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 + */ + +#ifndef G10_TDBIO_H +#define G10_TDBIO_H + +#include "host2net.h" + +#define TRUST_RECORD_LEN 40 +#define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5) +#define ITEMS_PER_HTBL_RECORD ((TRUST_RECORD_LEN-2)/4) +#define ITEMS_PER_HLST_RECORD ((TRUST_RECORD_LEN-6)/5) +#define ITEMS_PER_PREF_RECORD (TRUST_RECORD_LEN-10) +#if ITEMS_PER_PREF_RECORD % 2 +#error ITEMS_PER_PREF_RECORD must be even +#endif +#define MAX_LIST_SIGS_DEPTH 20 + + +#define RECTYPE_VER 1 +#define RECTYPE_HTBL 10 +#define RECTYPE_HLST 11 +#define RECTYPE_TRUST 12 +#define RECTYPE_VALID 13 +#define RECTYPE_FREE 254 + + +struct trust_record { + int rectype; + int mark; + int dirty; /* for now only used internal by functions */ + struct trust_record *next; /* help pointer to build lists in memory */ + ulong recnum; + union { + struct { /* version record: */ + byte version; /* should be 3 */ + byte marginals; + byte completes; + byte cert_depth; + byte trust_model; + ulong created; /* timestamp of trustdb creation */ + ulong nextcheck; /* timestamp of next scheduled check */ + ulong reserved; + ulong reserved2; + ulong firstfree; + ulong reserved3; + ulong trusthashtbl; + } ver; + struct { /* free record */ + ulong next; + } free; + struct { + ulong item[ITEMS_PER_HTBL_RECORD]; + } htbl; + struct { + ulong next; + ulong rnum[ITEMS_PER_HLST_RECORD]; /* of another record */ + } hlst; + struct { + byte fingerprint[20]; + byte ownertrust; + byte depth; + ulong validlist; + byte min_ownertrust; + } trust; + struct { + byte namehash[20]; + ulong next; + byte validity; + byte full_count; + byte marginal_count; + } valid; + } r; +}; +typedef struct trust_record TRUSTREC; + +/*-- tdbio.c --*/ +int tdbio_update_version_record(void); +int tdbio_set_dbname( const char *new_dbname, int create ); +const char *tdbio_get_dbname(void); +void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); +int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); +int tdbio_write_record( TRUSTREC *rec ); +int tdbio_db_matches_options(void); +byte tdbio_read_model(void); +ulong tdbio_read_nextcheck (void); +int tdbio_write_nextcheck (ulong stamp); +int tdbio_is_dirty(void); +int tdbio_sync(void); +int tdbio_begin_transaction(void); +int tdbio_end_transaction(void); +int tdbio_cancel_transaction(void); +int tdbio_delete_record( ulong recnum ); +ulong tdbio_new_recnum(void); +int tdbio_search_trust_byfpr(const byte *fingerprint, TRUSTREC *rec ); +int tdbio_search_trust_bypk(PKT_public_key *pk, TRUSTREC *rec ); + +void tdbio_invalid(void); + +#endif /*G10_TDBIO_H*/ diff --git a/g10/textfilter.c b/g10/textfilter.c new file mode 100644 index 000000000..6f3fe1bbf --- /dev/null +++ b/g10/textfilter.c @@ -0,0 +1,234 @@ +/* textfilter.c + * 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 <errno.h> +#include <assert.h> + +#include "errors.h" +#include "iobuf.h" +#include "memory.h" +#include "util.h" +#include "filter.h" +#include "i18n.h" +#include "options.h" + +#ifdef HAVE_DOSISH_SYSTEM +#define LF "\r\n" +#else +#define LF "\n" +#endif + +#define MAX_LINELEN 19995 /* a little bit smaller than in armor.c */ + /* to make sure that a warning is displayed while */ + /* creating a message */ + +static unsigned +len_without_trailing_chars( byte *line, unsigned len, const char *trimchars ) +{ + byte *p, *mark; + unsigned n; + + for(mark=NULL, p=line, n=0; n < len; n++, p++ ) { + if( strchr( trimchars, *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + return mark? (mark - line) : len; +} + +unsigned +len_without_trailing_ws( byte *line, unsigned len ) +{ + return len_without_trailing_chars( line, len, " \t\r\n" ); +} + + + + +static int +standard( text_filter_context_t *tfx, IOBUF a, + byte *buf, size_t size, size_t *ret_len) +{ + int rc=0; + size_t len = 0; + unsigned maxlen; + + assert( size > 10 ); + size -= 2; /* reserve 2 bytes to append CR,LF */ + while( !rc && len < size ) { + int lf_seen; + + while( len < size && tfx->buffer_pos < tfx->buffer_len ) + buf[len++] = tfx->buffer[tfx->buffer_pos++]; + if( len >= size ) + continue; + + /* read the next line */ + maxlen = MAX_LINELEN; + tfx->buffer_pos = 0; + tfx->buffer_len = iobuf_read_line( a, &tfx->buffer, + &tfx->buffer_size, &maxlen ); + if( !maxlen ) + tfx->truncated++; + if( !tfx->buffer_len ) { + if( !len ) + rc = -1; /* eof */ + break; + } + lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n'; + tfx->buffer_len = trim_trailing_ws( tfx->buffer, tfx->buffer_len ); + if( lf_seen ) { + tfx->buffer[tfx->buffer_len++] = '\r'; + tfx->buffer[tfx->buffer_len++] = '\n'; + } + } + *ret_len = len; + return rc; +} + + + + +/**************** + * The filter is used to make canonical text: Lines are terminated by + * CR, LF, trailing white spaces are removed. + */ +int +text_filter( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len) +{ + size_t size = *ret_len; + text_filter_context_t *tfx = opaque; + int rc=0; + + if( control == IOBUFCTRL_UNDERFLOW ) { + rc = standard( tfx, a, buf, size, ret_len ); + } + else if( control == IOBUFCTRL_FREE ) { + if( tfx->truncated ) + log_error(_("can't handle text lines longer than %d characters\n"), + MAX_LINELEN ); + m_free( tfx->buffer ); + tfx->buffer = NULL; + } + else if( control == IOBUFCTRL_DESC ) + *(char**)buf = "text_filter"; + return rc; +} + + +/**************** + * Copy data from INP to OUT and do some escaping if requested. + * md is updated as required by rfc2440 + */ +int +copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, + int escape_dash, int escape_from, int pgp2mode ) +{ + unsigned maxlen; + byte *buffer = NULL; /* malloced buffer */ + unsigned bufsize; /* and size of this buffer */ + unsigned n; + int truncated = 0; + int pending_lf = 0; + + if( !opt.pgp2_workarounds ) + pgp2mode = 0; + + if( !escape_dash ) + escape_from = 0; + + for(;;) { + maxlen = MAX_LINELEN; + n = iobuf_read_line( inp, &buffer, &bufsize, &maxlen ); + if( !maxlen ) + truncated++; + + if( !n ) + break; /* read_line has returned eof */ + + /* update the message digest */ + if( escape_dash ) { + if( pending_lf ) { + md_putc( md, '\r' ); + md_putc( md, '\n' ); + } + md_write( md, buffer, + len_without_trailing_chars( buffer, n, + pgp2mode? " \r\n":" \t\r\n")); + } + else + md_write( md, buffer, n ); + pending_lf = buffer[n-1] == '\n'; + + /* write the output */ + if( ( escape_dash && *buffer == '-') + || ( escape_from && n > 4 && !memcmp(buffer, "From ", 5 ) ) ) { + iobuf_put( out, '-' ); + iobuf_put( out, ' ' ); + } + +#if 0 /*defined(HAVE_DOSISH_SYSTEM)*/ + /* We don't use this anymore because my interpretation of rfc2440 7.1 + * is that there is no conversion needed. If one decides to + * clearsign a unix file on a DOS box he will get a mixed line endings. + * If at some point it turns out, that a conversion is a nice feature + * we can make an option out of it. + */ + /* make sure the lines do end in CR,LF */ + if( n > 1 && ( (buffer[n-2] == '\r' && buffer[n-1] == '\n' ) + || (buffer[n-2] == '\n' && buffer[n-1] == '\r'))) { + iobuf_write( out, buffer, n-2 ); + iobuf_put( out, '\r'); + iobuf_put( out, '\n'); + } + else if( n && buffer[n-1] == '\n' ) { + iobuf_write( out, buffer, n-1 ); + iobuf_put( out, '\r'); + iobuf_put( out, '\n'); + } + else + iobuf_write( out, buffer, n ); + +#else + iobuf_write( out, buffer, n ); +#endif + } + + /* at eof */ + if( !pending_lf ) { /* make sure that the file ends with a LF */ + iobuf_writestr( out, LF ); + if( !escape_dash ) + md_putc( md, '\n' ); + } + + if( truncated ) + log_info(_("input line longer than %d characters\n"), MAX_LINELEN ); + + return 0; /* okay */ +} diff --git a/g10/trustdb.c b/g10/trustdb.c new file mode 100644 index 000000000..457d83b9d --- /dev/null +++ b/g10/trustdb.c @@ -0,0 +1,2129 @@ +/* trustdb.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 <assert.h> + +#ifndef DISABLE_REGEX +#include <sys/types.h> +#ifdef USE_GNU_REGEX +#include "_regex.h" +#else +#include <regex.h> +#endif +#endif /* !DISABLE_REGEX */ + +#include "errors.h" +#include "iobuf.h" +#include "keydb.h" +#include "memory.h" +#include "util.h" +#include "options.h" +#include "packet.h" +#include "main.h" +#include "i18n.h" +#include "tdbio.h" +#include "trustdb.h" + + +/* + * A structure to store key identification as well as some stuff needed + * for validation + */ +struct key_item { + struct key_item *next; + unsigned int ownertrust,min_ownertrust; + byte trust_depth; + byte trust_value; + char *trust_regexp; + u32 kid[2]; +}; + + +typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */ + +/* + * Structure to keep track of keys, this is used as an array wherre + * the item right after the last one has a keyblock set to NULL. + * Maybe we can drop this thing and replace it by key_item + */ +struct key_array { + KBNODE keyblock; +}; + + +/* control information for the trust DB */ +static struct { + int init; + int level; + char *dbname; +} trustdb_args; + +/* some globals */ +static struct key_item *user_utk_list; /* temp. used to store --trusted-keys */ +static struct key_item *utk_list; /* all ultimately trusted keys */ + +static int pending_check_trustdb; + +static int validate_keys (int interactive); + + +/********************************************** + ************* some helpers ******************* + **********************************************/ + +static struct key_item * +new_key_item (void) +{ + struct key_item *k; + + k = m_alloc_clear (sizeof *k); + return k; +} + +static void +release_key_items (struct key_item *k) +{ + struct key_item *k2; + + for (; k; k = k2) + { + k2 = k->next; + m_free (k->trust_regexp); + m_free (k); + } +} + +/* + * For fast keylook up we need a hash table. Each byte of a KeyIDs + * should be distributed equally over the 256 possible values (except + * for v3 keyIDs but we consider them as not important here). So we + * can just use 10 bits to index a table of 1024 key items. + * Possible optimization: Don not use key_items but other hash_table when the + * duplicates lists gets too large. + */ +static KeyHashTable +new_key_hash_table (void) +{ + struct key_item **tbl; + + tbl = m_alloc_clear (1024 * sizeof *tbl); + return tbl; +} + +static void +release_key_hash_table (KeyHashTable tbl) +{ + int i; + + if (!tbl) + return; + for (i=0; i < 1024; i++) + release_key_items (tbl[i]); + m_free (tbl); +} + +/* + * Returns: True if the keyID is in the given hash table + */ +static int +test_key_hash_table (KeyHashTable tbl, u32 *kid) +{ + struct key_item *k; + + for (k = tbl[(kid[1] & 0x03ff)]; k; k = k->next) + if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) + return 1; + return 0; +} + +/* + * Add a new key to the hash table. The key is identified by its key ID. + */ +static void +add_key_hash_table (KeyHashTable tbl, u32 *kid) +{ + struct key_item *k, *kk; + + for (k = tbl[(kid[1] & 0x03ff)]; k; k = k->next) + if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) + return; /* already in table */ + + kk = new_key_item (); + kk->kid[0] = kid[0]; + kk->kid[1] = kid[1]; + kk->next = tbl[(kid[1] & 0x03ff)]; + tbl[(kid[1] & 0x03ff)] = kk; +} + +/* + * Release a key_array + */ +static void +release_key_array ( struct key_array *keys ) +{ + struct key_array *k; + + if (keys) { + for (k=keys; k->keyblock; k++) + release_kbnode (k->keyblock); + m_free (keys); + } +} + + +/********************************************* + ********** Initialization ***************** + *********************************************/ + + + +/* + * Used to register extra ultimately trusted keys - this has to be done + * before initializing the validation module. + * FIXME: Should be replaced by a function to add those keys to the trustdb. + */ +void +register_trusted_key( const char *string ) +{ + KEYDB_SEARCH_DESC desc; + struct key_item *k; + + if (classify_user_id (string, &desc) != KEYDB_SEARCH_MODE_LONG_KID ) { + log_error(_("`%s' is not a valid long keyID\n"), string ); + return; + } + + k = new_key_item (); + k->kid[0] = desc.u.kid[0]; + k->kid[1] = desc.u.kid[1]; + k->next = user_utk_list; + user_utk_list = k; +} + +/* + * Helper to add a key to the global list of ultimately trusted keys. + * Retruns: true = inserted, false = already in in list. + */ +static int +add_utk (u32 *kid) +{ + struct key_item *k; + + for (k = utk_list; k; k = k->next) + { + if (k->kid[0] == kid[0] && k->kid[1] == kid[1]) + { + return 0; + } + } + + k = new_key_item (); + k->kid[0] = kid[0]; + k->kid[1] = kid[1]; + k->ownertrust = TRUST_ULTIMATE; + k->next = utk_list; + utk_list = k; + if( opt.verbose > 1 ) + log_info(_("key %08lX: accepted as trusted key\n"), (ulong)kid[1]); + return 1; +} + + +/**************** + * Verify that all our secret keys are usable and put them into the utk_list. + */ +static void +verify_own_keys(void) +{ + TRUSTREC rec; + ulong recnum; + int rc; + struct key_item *k; + + if (utk_list) + return; + + /* scan the trustdb to find all ultimately trusted keys */ + for (recnum=1; !tdbio_read_record (recnum, &rec, 0); recnum++ ) + { + if ( rec.rectype == RECTYPE_TRUST + && (rec.r.trust.ownertrust & TRUST_MASK) == TRUST_ULTIMATE) + { + byte *fpr = rec.r.trust.fingerprint; + int fprlen; + u32 kid[2]; + + /* Problem: We do only use fingerprints in the trustdb but + * we need the keyID here to indetify the key; we can only + * use that ugly hack to distinguish between 16 and 20 + * butes fpr - it does not work always so we better change + * the whole validation code to only work with + * fingerprints */ + fprlen = (!fpr[16] && !fpr[17] && !fpr[18] && !fpr[19])? 16:20; + keyid_from_fingerprint (fpr, fprlen, kid); + if (!add_utk (kid)) + log_info(_("key %08lX occurs more than once in the trustdb\n"), + (ulong)kid[1]); + } + } + + /* Put any --trusted-key keys into the trustdb */ + for (k = user_utk_list; k; k = k->next) + { + if ( add_utk (k->kid) ) + { /* not yet in trustDB as ultimately trusted */ + PKT_public_key pk; + + memset (&pk, 0, sizeof pk); + rc = get_pubkey (&pk, k->kid); + if (rc) { + log_info(_("key %08lX: no public key for trusted key - skipped\n"), + (ulong)k->kid[1] ); + } + else { + update_ownertrust (&pk, + ((get_ownertrust (&pk) & ~TRUST_MASK) + | TRUST_ULTIMATE )); + release_public_key_parts (&pk); + } + log_info (_("key %08lX marked as ultimately trusted\n"), + (ulong)k->kid[1]); + } + } + + + /* release the helper table table */ + release_key_items (user_utk_list); + user_utk_list = NULL; + return; +} + + +/********************************************* + *********** TrustDB stuff ******************* + *********************************************/ + +/* + * Read a record but die if it does not exist + */ +static void +read_record (ulong recno, TRUSTREC *rec, int rectype ) +{ + int rc = tdbio_read_record (recno, rec, rectype); + if (rc) + { + log_error(_("trust record %lu, req type %d: read failed: %s\n"), + recno, rec->rectype, g10_errstr(rc) ); + tdbio_invalid(); + } + if (rectype != rec->rectype) + { + log_error(_("trust record %lu is not of requested type %d\n"), + rec->recnum, rectype); + tdbio_invalid(); + } +} + +/* + * Write a record and die on error + */ +static void +write_record (TRUSTREC *rec) +{ + int rc = tdbio_write_record (rec); + if (rc) + { + log_error(_("trust record %lu, type %d: write failed: %s\n"), + rec->recnum, rec->rectype, g10_errstr(rc) ); + tdbio_invalid(); + } +} + +/* + * sync the TrustDb and die on error + */ +static void +do_sync(void) +{ + int rc = tdbio_sync (); + if(rc) + { + log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) ); + g10_exit(2); + } +} + +static const char * +trust_model_string(void) +{ + switch(opt.trust_model) + { + case TM_PGP: return "PGP"; + case TM_CLASSIC: return "classic"; + case TM_ALWAYS: return "always"; + default: return "unknown"; + } +} + +/**************** + * Perform some checks over the trustdb + * level 0: only open the db + * 1: used for initial program startup + */ +int +setup_trustdb( int level, const char *dbname ) +{ + /* just store the args */ + if( trustdb_args.init ) + return 0; + trustdb_args.level = level; + trustdb_args.dbname = dbname? m_strdup(dbname): NULL; + return 0; +} + +void +init_trustdb() +{ + int rc=0; + int level = trustdb_args.level; + const char* dbname = trustdb_args.dbname; + + if( trustdb_args.init ) + return; + + trustdb_args.init = 1; + + if ( !level || level==1) + { + rc = tdbio_set_dbname( dbname, !!level ); + if( !rc ) + { + if( !level ) + return; + + /* verify that our own keys are in the trustDB + * or move them to the trustdb. */ + verify_own_keys(); + + /* should we check whether there is no other ultimately trusted + * key in the database? */ + } + } + else + BUG(); + if( rc ) + log_fatal("can't init trustdb: %s\n", g10_errstr(rc) ); + + if(opt.trust_model==TM_AUTO) + { + /* Try and set the trust model off of whatever the trustdb says + it is. */ + opt.trust_model=tdbio_read_model(); + + /* Sanity check this ;) */ + if(opt.trust_model!=TM_PGP && opt.trust_model!=TM_CLASSIC) + { + log_info(_("unable to use unknown trust model (%d) - " + "assuming %s trust model\n"),opt.trust_model,"PGP"); + opt.trust_model=TM_PGP; + } + + if(opt.verbose) + log_info(_("using %s trust model\n"),trust_model_string()); + } + + if((opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + && !tdbio_db_matches_options()) + pending_check_trustdb=1; +} + + + + +/*********************************************** + ************* Print helpers **************** + ***********************************************/ + +/**************** + * This function returns a letter for a trustvalue Trust flags + * are ignore. + */ +static int +trust_letter (unsigned int value) +{ + switch( (value & TRUST_MASK) ) + { + case TRUST_UNKNOWN: return '-'; + case TRUST_EXPIRED: return 'e'; + case TRUST_UNDEFINED: return 'q'; + case TRUST_NEVER: return 'n'; + case TRUST_MARGINAL: return 'm'; + case TRUST_FULLY: return 'f'; + case TRUST_ULTIMATE: return 'u'; + default: return '?'; + } +} + +/* The strings here are similar to those in + pkclist.c:do_edit_ownertrust() */ +const char * +trust_value_to_string (unsigned int value) +{ + switch( (value & TRUST_MASK) ) + { + case TRUST_UNKNOWN: return _("unknown"); + case TRUST_EXPIRED: return _("expired"); + case TRUST_UNDEFINED: return _("undefined"); + case TRUST_NEVER: return _("never"); + case TRUST_MARGINAL: return _("marginal"); + case TRUST_FULLY: return _("full"); + case TRUST_ULTIMATE: return _("ultimate"); + default: return "err"; + } +} + +int +string_to_trust_value (const char *str) +{ + if(ascii_strcasecmp(str,"undefined")==0) + return TRUST_UNDEFINED; + else if(ascii_strcasecmp(str,"never")==0) + return TRUST_NEVER; + else if(ascii_strcasecmp(str,"marginal")==0) + return TRUST_MARGINAL; + else if(ascii_strcasecmp(str,"full")==0) + return TRUST_FULLY; + else if(ascii_strcasecmp(str,"ultimate")==0) + return TRUST_ULTIMATE; + else + return -1; +} + +/**************** + * Recreate the WoT but do not ask for new ownertrusts. Special + * feature: In batch mode and without a forced yes, this is only done + * when a check is due. This can be used to run the check from a crontab + */ +void +check_trustdb () +{ + init_trustdb(); + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + { + if (opt.batch && !opt.answer_yes) + { + ulong scheduled; + + scheduled = tdbio_read_nextcheck (); + if (!scheduled) + { + log_info (_("no need for a trustdb check\n")); + return; + } + + if (scheduled > make_timestamp ()) + { + log_info (_("next trustdb check due at %s\n"), + strtimestamp (scheduled)); + return; + } + } + + validate_keys (0); + } + else + log_info (_("no need for a trustdb check with \"%s\" trust model\n"), + trust_model_string()); +} + + +/* + * Recreate the WoT. + */ +void +update_trustdb() +{ + init_trustdb(); + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + validate_keys (1); + else + log_info (_("no need for a trustdb update with \"%s\" trust model\n"), + trust_model_string()); +} + +void +revalidation_mark (void) +{ + init_trustdb(); + /* we simply set the time for the next check to 1 (far back in 1970) + * so that a --update-trustdb will be scheduled */ + if (tdbio_write_nextcheck (1)) + do_sync (); + pending_check_trustdb = 1; +} + +int +trustdb_pending_check(void) +{ + return pending_check_trustdb; +} + + +/*********************************************** + *********** Ownertrust et al. **************** + ***********************************************/ + +static int +read_trust_record (PKT_public_key *pk, TRUSTREC *rec) +{ + int rc; + + init_trustdb(); + rc = tdbio_search_trust_bypk (pk, rec); + if (rc == -1) + return -1; /* no record yet */ + if (rc) + { + log_error ("trustdb: searching trust record failed: %s\n", + g10_errstr (rc)); + return rc; + } + + if (rec->rectype != RECTYPE_TRUST) + { + log_error ("trustdb: record %lu is not a trust record\n", + rec->recnum); + return G10ERR_TRUSTDB; + } + + return 0; +} + +/**************** + * Return the assigned ownertrust value for the given public key. + * The key should be the primary key. + */ +unsigned int +get_ownertrust ( PKT_public_key *pk) +{ + TRUSTREC rec; + int rc; + + rc = read_trust_record (pk, &rec); + if (rc == -1) + return TRUST_UNKNOWN; /* no record yet */ + if (rc) + { + tdbio_invalid (); + return rc; /* actually never reached */ + } + + return rec.r.trust.ownertrust; +} + +unsigned int +get_min_ownertrust (PKT_public_key *pk) +{ + TRUSTREC rec; + int rc; + + rc = read_trust_record (pk, &rec); + if (rc == -1) + return TRUST_UNKNOWN; /* no record yet */ + if (rc) + { + tdbio_invalid (); + return rc; /* actually never reached */ + } + + return rec.r.trust.min_ownertrust; +} + +/* + * Same as get_ownertrust but this takes the minimum ownertrust value + * into into account, and will bump up the value as needed. + */ +static int +get_ownertrust_with_min (PKT_public_key *pk) +{ + unsigned int otrust,otrust_min; + + otrust = (get_ownertrust (pk) & TRUST_MASK); + otrust_min = get_min_ownertrust (pk); + if(otrust<otrust_min) + { + /* If the trust that the user has set is less than the trust + that was calculated from a trust signature chain, use the + higher of the two. We do this here and not in + get_ownertrust since the underlying ownertrust should not + really be set - just the appearance of the ownertrust. */ + + otrust=otrust_min; + } + + return otrust; +} + +/* + * Same as get_ownertrust but return a trust letter instead of an + * value. This takes the minimum ownertrust value into account. + */ +int +get_ownertrust_info (PKT_public_key *pk) +{ + return trust_letter(get_ownertrust_with_min(pk)); +} + +/* + * Same as get_ownertrust but return a trust string instead of an + * value. This takes the minimum ownertrust value into account. + */ +const char * +get_ownertrust_string (PKT_public_key *pk) +{ + return trust_value_to_string(get_ownertrust_with_min(pk)); +} + +/* + * Set the trust value of the given public key to the new value. + * The key should be a primary one. + */ +void +update_ownertrust (PKT_public_key *pk, unsigned int new_trust ) +{ + TRUSTREC rec; + int rc; + + rc = read_trust_record (pk, &rec); + if (!rc) + { + if (DBG_TRUST) + log_debug ("update ownertrust from %u to %u\n", + (unsigned int)rec.r.trust.ownertrust, new_trust ); + if (rec.r.trust.ownertrust != new_trust) + { + rec.r.trust.ownertrust = new_trust; + write_record( &rec ); + revalidation_mark (); + do_sync (); + } + } + else if (rc == -1) + { /* no record yet - create a new one */ + size_t dummy; + + if (DBG_TRUST) + log_debug ("insert ownertrust %u\n", new_trust ); + + memset (&rec, 0, sizeof rec); + rec.recnum = tdbio_new_recnum (); + rec.rectype = RECTYPE_TRUST; + fingerprint_from_pk (pk, rec.r.trust.fingerprint, &dummy); + rec.r.trust.ownertrust = new_trust; + write_record (&rec); + revalidation_mark (); + do_sync (); + rc = 0; + } + else + { + tdbio_invalid (); + } +} + +static void +update_min_ownertrust (u32 *kid, unsigned int new_trust ) +{ + PKT_public_key *pk; + TRUSTREC rec; + int rc; + + pk = m_alloc_clear (sizeof *pk); + rc = get_pubkey (pk, kid); + if (rc) + { + log_error (_("public key %08lX not found: %s\n"), + (ulong)kid[1], g10_errstr(rc) ); + return; + } + + rc = read_trust_record (pk, &rec); + if (!rc) + { + if (DBG_TRUST) + log_debug ("key %08lX: update min_ownertrust from %u to %u\n", + (ulong)kid[1],(unsigned int)rec.r.trust.min_ownertrust, + new_trust ); + if (rec.r.trust.min_ownertrust != new_trust) + { + rec.r.trust.min_ownertrust = new_trust; + write_record( &rec ); + revalidation_mark (); + do_sync (); + } + } + else if (rc == -1) + { /* no record yet - create a new one */ + size_t dummy; + + if (DBG_TRUST) + log_debug ("insert min_ownertrust %u\n", new_trust ); + + memset (&rec, 0, sizeof rec); + rec.recnum = tdbio_new_recnum (); + rec.rectype = RECTYPE_TRUST; + fingerprint_from_pk (pk, rec.r.trust.fingerprint, &dummy); + rec.r.trust.min_ownertrust = new_trust; + write_record (&rec); + revalidation_mark (); + do_sync (); + rc = 0; + } + else + { + tdbio_invalid (); + } +} + +/* Clear the ownertrust and min_ownertrust values. Return true if a + change actually happened. */ +int +clear_ownertrusts (PKT_public_key *pk) +{ + TRUSTREC rec; + int rc; + + rc = read_trust_record (pk, &rec); + if (!rc) + { + if (DBG_TRUST) + { + log_debug ("clearing ownertrust (old value %u)\n", + (unsigned int)rec.r.trust.ownertrust); + log_debug ("clearing min_ownertrust (old value %u)\n", + (unsigned int)rec.r.trust.min_ownertrust); + } + if (rec.r.trust.ownertrust || rec.r.trust.min_ownertrust) + { + rec.r.trust.ownertrust = 0; + rec.r.trust.min_ownertrust = 0; + write_record( &rec ); + revalidation_mark (); + do_sync (); + return 1; + } + } + else if (rc != -1) + { + tdbio_invalid (); + } + return 0; +} + +/* + * Note: Caller has to do a sync + */ +static void +update_validity (PKT_public_key *pk, PKT_user_id *uid, + int depth, int validity) +{ + TRUSTREC trec, vrec; + int rc; + ulong recno; + + namehash_from_uid(uid); + + rc = read_trust_record (pk, &trec); + if (rc && rc != -1) + { + tdbio_invalid (); + return; + } + if (rc == -1) /* no record yet - create a new one */ + { + size_t dummy; + + rc = 0; + memset (&trec, 0, sizeof trec); + trec.recnum = tdbio_new_recnum (); + trec.rectype = RECTYPE_TRUST; + fingerprint_from_pk (pk, trec.r.trust.fingerprint, &dummy); + trec.r.trust.ownertrust = 0; + } + + /* locate an existing one */ + recno = trec.r.trust.validlist; + while (recno) + { + read_record (recno, &vrec, RECTYPE_VALID); + if ( !memcmp (vrec.r.valid.namehash, uid->namehash, 20) ) + break; + recno = vrec.r.valid.next; + } + + if (!recno) /* insert a new validity record */ + { + memset (&vrec, 0, sizeof vrec); + vrec.recnum = tdbio_new_recnum (); + vrec.rectype = RECTYPE_VALID; + memcpy (vrec.r.valid.namehash, uid->namehash, 20); + vrec.r.valid.next = trec.r.trust.validlist; + trec.r.trust.validlist = vrec.recnum; + } + vrec.r.valid.validity = validity; + vrec.r.valid.full_count = uid->help_full_count; + vrec.r.valid.marginal_count = uid->help_marginal_count; + write_record (&vrec); + trec.r.trust.depth = depth; + write_record (&trec); +} + + +/* reset validity for all user IDs. Caller must sync. */ +static int +clear_validity (PKT_public_key *pk) +{ + TRUSTREC trec, vrec; + int rc; + ulong recno; + int any = 0; + + rc = read_trust_record (pk, &trec); + if (rc && rc != -1) + { + tdbio_invalid (); + return 0; + } + if (rc == -1) /* no record yet - no need to clear it then ;-) */ + return 0; + + /* Clear minimum ownertrust, if any */ + if(trec.r.trust.min_ownertrust) + { + trec.r.trust.min_ownertrust=0; + write_record(&trec); + } + + recno = trec.r.trust.validlist; + while (recno) + { + read_record (recno, &vrec, RECTYPE_VALID); + if ((vrec.r.valid.validity & TRUST_MASK) + || vrec.r.valid.marginal_count || vrec.r.valid.full_count) + { + vrec.r.valid.validity &= ~TRUST_MASK; + vrec.r.valid.marginal_count = vrec.r.valid.full_count = 0; + write_record (&vrec); + any = 1; + } + recno = vrec.r.valid.next; + } + + return any; +} + +/*********************************************** + ********* Query trustdb values ************** + ***********************************************/ + +/* Return true if key is disabled */ +int +cache_disabled_value(PKT_public_key *pk) +{ + int rc; + TRUSTREC trec; + int disabled=0; + + if(pk->is_disabled) + return (pk->is_disabled==2); + + init_trustdb(); + + rc = read_trust_record (pk, &trec); + if (rc && rc != -1) + { + tdbio_invalid (); + goto leave; + } + if (rc == -1) /* no record found, so assume not disabled */ + goto leave; + + if(trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) + disabled=1; + + /* Cache it for later so we don't need to look at the trustdb every + time */ + if(disabled) + pk->is_disabled=2; + else + pk->is_disabled=1; + + leave: + return disabled; +} + +/* + * Return the validity information for PK. If the namehash is not + * NULL, the validity of the corresponsing user ID is returned, + * otherwise, a reasonable value for the entire key is returned. + */ +unsigned int +get_validity (PKT_public_key *pk, PKT_user_id *uid) +{ + static int did_nextcheck; + TRUSTREC trec, vrec; + int rc; + ulong recno; + unsigned int validity; + u32 kid[2]; + PKT_public_key *main_pk; + + if(uid) + namehash_from_uid(uid); + + init_trustdb (); + if (!did_nextcheck + && (opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)) + { + ulong scheduled; + + did_nextcheck = 1; + scheduled = tdbio_read_nextcheck (); + if (scheduled && scheduled <= make_timestamp ()) + { + if (opt.no_auto_check_trustdb) + { + pending_check_trustdb = 1; + log_info (_("please do a --check-trustdb\n")); + } + else + { + log_info (_("checking the trustdb\n")); + validate_keys (0); + } + } + } + + keyid_from_pk (pk, kid); + if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1]) + { /* this is a subkey - get the mainkey */ + main_pk = m_alloc_clear (sizeof *main_pk); + rc = get_pubkey (main_pk, pk->main_keyid); + if (rc) + { + log_error ("error getting main key %08lX of subkey %08lX: %s\n", + (ulong)pk->main_keyid[1], (ulong)kid[1], g10_errstr(rc)); + validity = TRUST_UNKNOWN; + goto leave; + } + } + else + main_pk = pk; + + rc = read_trust_record (main_pk, &trec); + if (rc && rc != -1) + { + tdbio_invalid (); + return 0; + } + if (rc == -1) /* no record found */ + { + validity = TRUST_UNKNOWN; + goto leave; + } + + /* loop over all user IDs */ + recno = trec.r.trust.validlist; + validity = 0; + while (recno) + { + read_record (recno, &vrec, RECTYPE_VALID); + + if(uid) + { + /* If a user ID is given we return the validity for that + user ID ONLY. If the namehash is not found, then there + is no validity at all (i.e. the user ID wasn't + signed). */ + if(memcmp(vrec.r.valid.namehash,uid->namehash,20)==0) + { + validity=(vrec.r.valid.validity & TRUST_MASK); + break; + } + } + else + { + /* If no namehash is given, we take the maximum validity + over all user IDs */ + if ( validity < (vrec.r.valid.validity & TRUST_MASK) ) + validity = (vrec.r.valid.validity & TRUST_MASK); + } + + recno = vrec.r.valid.next; + } + + if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) ) + { + validity |= TRUST_FLAG_DISABLED; + pk->is_disabled=2; + } + else + pk->is_disabled=1; + + leave: + /* set some flags direct from the key */ + if (main_pk->is_revoked) + validity |= TRUST_FLAG_REVOKED; + if (main_pk != pk && pk->is_revoked) + validity |= TRUST_FLAG_SUB_REVOKED; + /* Note: expiration is a trust value and not a flag - don't know why + * I initially designed it that way */ + if (main_pk->has_expired || pk->has_expired) + validity = (validity & ~TRUST_MASK) | TRUST_EXPIRED; + + if (pending_check_trustdb) + validity |= TRUST_FLAG_PENDING_CHECK; + + if (main_pk != pk) + free_public_key (main_pk); + return validity; +} + +int +get_validity_info (PKT_public_key *pk, PKT_user_id *uid) +{ + int trustlevel; + + trustlevel = get_validity (pk, uid); + if( trustlevel & TRUST_FLAG_REVOKED ) + return 'r'; + return trust_letter ( trustlevel ); +} + +const char * +get_validity_string (PKT_public_key *pk, PKT_user_id *uid) +{ + int trustlevel; + + trustlevel = get_validity (pk, uid); + if( trustlevel & TRUST_FLAG_REVOKED ) + return _("revoked"); + return trust_value_to_string(trustlevel); +} + +static void +get_validity_counts (PKT_public_key *pk, PKT_user_id *uid) +{ + TRUSTREC trec, vrec; + ulong recno; + + if(pk==NULL || uid==NULL) + BUG(); + + namehash_from_uid(uid); + + uid->help_marginal_count=uid->help_full_count=0; + + init_trustdb (); + + if(read_trust_record (pk, &trec)!=0) + return; + + /* loop over all user IDs */ + recno = trec.r.trust.validlist; + while (recno) + { + read_record (recno, &vrec, RECTYPE_VALID); + + if(memcmp(vrec.r.valid.namehash,uid->namehash,20)==0) + { + uid->help_marginal_count=vrec.r.valid.marginal_count; + uid->help_full_count=vrec.r.valid.full_count; + /* printf("Fetched marginal %d, full %d\n",uid->help_marginal_count,uid->help_full_count); */ + break; + } + + recno = vrec.r.valid.next; + } +} + +void +list_trust_path( const char *username ) +{ +} + +/**************** + * Enumerate all keys, which are needed to build all trust paths for + * the given key. This function does not return the key itself or + * the ultimate key (the last point in cerificate chain). Only + * certificate chains which ends up at an ultimately trusted key + * are listed. If ownertrust or validity is not NULL, the corresponding + * value for the returned LID is also returned in these variable(s). + * + * 1) create a void pointer and initialize it to NULL + * 2) pass this void pointer by reference to this function. + * Set lid to the key you want to enumerate and pass it by reference. + * 3) call this function as long as it does not return -1 + * to indicate EOF. LID does contain the next key used to build the web + * 4) Always call this function a last time with LID set to NULL, + * so that it can free its context. + * + * Returns: -1 on EOF or the level of the returned LID + */ +int +enum_cert_paths( void **context, ulong *lid, + unsigned *ownertrust, unsigned *validity ) +{ + return -1; +} + + +/**************** + * Print the current path + */ +void +enum_cert_paths_print( void **context, FILE *fp, + int refresh, ulong selected_lid ) +{ + return; +} + + + +/**************************************** + *********** NEW NEW NEW **************** + ****************************************/ + +static int +ask_ownertrust (u32 *kid,int minimum) +{ + PKT_public_key *pk; + int rc; + int ot; + + pk = m_alloc_clear (sizeof *pk); + rc = get_pubkey (pk, kid); + if (rc) + { + log_error (_("public key %08lX not found: %s\n"), + (ulong)kid[1], g10_errstr(rc) ); + return TRUST_UNKNOWN; + } + + if(opt.force_ownertrust) + { + log_info("force trust for key %08lX%08lX to %s\n", + (ulong)kid[0],(ulong)kid[1], + trust_value_to_string(opt.force_ownertrust)); + update_ownertrust(pk,opt.force_ownertrust); + ot=opt.force_ownertrust; + } + else + { + ot=edit_ownertrust(pk,0); + if(ot>0) + ot = get_ownertrust (pk); + else if(ot==0) + ot = minimum?minimum:TRUST_UNDEFINED; + else + ot = -1; /* quit */ + } + + free_public_key( pk ); + + return ot; +} + + +static void +mark_keyblock_seen (KeyHashTable tbl, KBNODE node) +{ + for ( ;node; node = node->next ) + if (node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + u32 aki[2]; + + keyid_from_pk (node->pkt->pkt.public_key, aki); + add_key_hash_table (tbl, aki); + } +} + + +static void +dump_key_array (int depth, struct key_array *keys) +{ + struct key_array *kar; + + for (kar=keys; kar->keyblock; kar++) + { + KBNODE node = kar->keyblock; + u32 kid[2]; + + keyid_from_pk(node->pkt->pkt.public_key, kid); + printf ("%d:%08lX%08lX:K::%c::::\n", + depth, (ulong)kid[0], (ulong)kid[1], '?'); + + for (; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID) + { + int len = node->pkt->pkt.user_id->len; + + if (len > 30) + len = 30; + printf ("%d:%08lX%08lX:U:::%c:::", + depth, (ulong)kid[0], (ulong)kid[1], + (node->flag & 4)? 'f': + (node->flag & 2)? 'm': + (node->flag & 1)? 'q':'-'); + print_string (stdout, node->pkt->pkt.user_id->name, len, ':'); + putchar (':'); + putchar ('\n'); + } + } + } +} + + +static void +store_validation_status (int depth, KBNODE keyblock, KeyHashTable stored) +{ + KBNODE node; + int status; + int any = 0; + + for (node=keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + if (node->flag & 4) + status = TRUST_FULLY; + else if (node->flag & 2) + status = TRUST_MARGINAL; + else if (node->flag & 1) + status = TRUST_UNDEFINED; + else + status = 0; + + if (status) + { + update_validity (keyblock->pkt->pkt.public_key, + uid, depth, status); + + mark_keyblock_seen(stored,keyblock); + + any = 1; + } + } + } + + if (any) + do_sync (); +} + +/* + * check whether the signature sig is in the klist k + */ +static struct key_item * +is_in_klist (struct key_item *k, PKT_signature *sig) +{ + for (; k; k = k->next) + { + if (k->kid[0] == sig->keyid[0] && k->kid[1] == sig->keyid[1]) + return k; + } + return NULL; +} + +/* + * Mark the signature of the given UID which are used to certify it. + * To do this, we first revmove all signatures which are not valid and + * from the remain ones we look for the latest one. If this is not a + * certification revocation signature we mark the signature by setting + * node flag bit 8. Note that flag bits 9 and 10 are used for internal + * purposes. + */ +static void +mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, + u32 *main_kid, struct key_item *klist, + u32 curtime, u32 *next_expire) +{ + KBNODE node; + PKT_signature *sig; + + /* first check all signatures */ + for (node=uidnode->next; node; node = node->next) + { + node->flag &= ~(1<<8 | 1<<9 | 1<<10); + if (node->pkt->pkttype == PKT_USER_ID + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + break; /* ready */ + if (node->pkt->pkttype != PKT_SIGNATURE) + continue; + + sig = node->pkt->pkt.signature; + if (sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1]) + continue; /* ignore self-signatures */ + if (!IS_UID_SIG(sig) && !IS_UID_REV(sig)) + continue; /* we only look at these signature classes */ + if (!is_in_klist (klist, sig)) + continue; /* no need to check it then */ + if (check_key_signature (keyblock, node, NULL)) + continue; /* ignore invalid signatures */ + node->flag |= 1<<9; + } + /* reset the remaining flags */ + for (; node; node = node->next) + node->flag &= ~(1<<8 | 1<<9 | 1 << 10); + + /* kbnode flag usage: bit 9 is here set for signatures to consider, + * bit 10 will be set by the loop to keep track of keyIDs already + * processed, bit 8 will be set for the usable signatures */ + + /* for each cert figure out the latest valid one */ + for (node=uidnode->next; node; node = node->next) + { + KBNODE n, signode; + u32 kid[2]; + u32 sigdate; + + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + break; + if ( !(node->flag & (1<<9)) ) + continue; /* not a node to look at */ + if ( (node->flag & (1<<10)) ) + continue; /* signature with a keyID already processed */ + node->flag |= (1<<10); /* mark this node as processed */ + sig = node->pkt->pkt.signature; + signode = node; + sigdate = sig->timestamp; + kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1]; + for (n=uidnode->next; n; n = n->next) + { + if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY) + break; + if ( !(n->flag & (1<<9)) ) + continue; + if ( (n->flag & (1<<10)) ) + continue; /* shortcut already processed signatures */ + sig = n->pkt->pkt.signature; + if (kid[0] != sig->keyid[0] || kid[1] != sig->keyid[1]) + continue; + n->flag |= (1<<10); /* mark this node as processed */ + + /* If signode is nonrevocable and unexpired and n isn't, + then take signode (skip). It doesn't matter which is + older: if signode was older then we don't want to take n + as signode is nonrevocable. If n was older then we're + automatically fine. */ + + if(((IS_UID_SIG(signode->pkt->pkt.signature) && + !signode->pkt->pkt.signature->flags.revocable && + (signode->pkt->pkt.signature->expiredate==0 || + signode->pkt->pkt.signature->expiredate>curtime))) && + (!(IS_UID_SIG(n->pkt->pkt.signature) && + !n->pkt->pkt.signature->flags.revocable && + (n->pkt->pkt.signature->expiredate==0 || + n->pkt->pkt.signature->expiredate>curtime)))) + continue; + + /* If n is nonrevocable and unexpired and signode isn't, + then take n. Again, it doesn't matter which is older: if + n was older then we don't want to take signode as n is + nonrevocable. If signode was older then we're + automatically fine. */ + + if((!(IS_UID_SIG(signode->pkt->pkt.signature) && + !signode->pkt->pkt.signature->flags.revocable && + (signode->pkt->pkt.signature->expiredate==0 || + signode->pkt->pkt.signature->expiredate>curtime))) && + ((IS_UID_SIG(n->pkt->pkt.signature) && + !n->pkt->pkt.signature->flags.revocable && + (n->pkt->pkt.signature->expiredate==0 || + n->pkt->pkt.signature->expiredate>curtime)))) + { + signode = n; + sigdate = sig->timestamp; + continue; + } + + /* At this point, if it's newer, it goes in as the only + remaining possibilities are signode and n are both either + revocable or expired or both nonrevocable and unexpired. + If the timestamps are equal take the later ordered + packet, presuming that the key packets are hopefully in + their original order. */ + + if (sig->timestamp >= sigdate) + { + signode = n; + sigdate = sig->timestamp; + } + } + sig = signode->pkt->pkt.signature; + if (IS_UID_SIG (sig)) + { /* this seems to be a usable one which is not revoked. + * Just need to check whether there is an expiration time, + * We do the expired certification after finding a suitable + * certification, the assumption is that a signator does not + * want that after the expiration of his certificate the + * system falls back to an older certification which has a + * different expiration time */ + const byte *p; + u32 expire; + + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL ); + expire = p? sig->timestamp + buffer_to_u32(p) : 0; + + if (expire==0 || expire > curtime ) + { + signode->flag |= (1<<8); /* yeah, found a good cert */ + if (expire && expire < *next_expire) + *next_expire = expire; + } + } + } +} + +/* Used by validate_one_keyblock to confirm a regexp within a trust + signature. Returns 1 for match, and 0 for no match or regex + error. */ +static int +check_regexp(const char *exp,const char *string) +{ +#ifdef DISABLE_REGEX + /* When DISABLE_REGEX is defined, assume all regexps do not + match. */ + return 0; +#elif defined(__riscos__) + return riscos_check_regexp(exp, string, DBG_TRUST); +#else + int ret; + regex_t pat; + + if(regcomp(&pat,exp,REG_ICASE|REG_NOSUB|REG_EXTENDED)!=0) + return 0; + + ret=regexec(&pat,string,0,NULL,0); + + regfree(&pat); + + if(DBG_TRUST) + log_debug("regexp \"%s\" on \"%s\": %s\n",exp,string,ret==0?"YES":"NO"); + + return (ret==0); +#endif +} + +/* + * Return true if the key is signed by one of the keys in the given + * key ID list. User IDs with a valid signature are marked by node + * flags as follows: + * flag bit 0: There is at least one signature + * 1: There is marginal confidence that this is a legitimate uid + * 2: There is full confidence that this is a legitimate uid. + * 8: Used for internal purposes. + * 9: Ditto (in mark_usable_uid_certs()) + * 10: Ditto (ditto) + * This function assumes that all kbnode flags are cleared on entry. + */ +static int +validate_one_keyblock (KBNODE kb, struct key_item *klist, + u32 curtime, u32 *next_expire) +{ + struct key_item *kr; + KBNODE node, uidnode=NULL; + PKT_user_id *uid=NULL; + PKT_public_key *pk = kb->pkt->pkt.public_key; + u32 main_kid[2]; + int issigned=0, any_signed = 0; + + keyid_from_pk(pk, main_kid); + for (node=kb; node; node = node->next) + { + /* A bit of discussion here: is it better for the web of trust + to be built among only self-signed uids? On the one hand, a + self-signed uid is a statement that the key owner definitely + intended that uid to be there, but on the other hand, a + signed (but not self-signed) uid does carry trust, of a sort, + even if it is a statement being made by people other than the + key owner "through" the uids on the key owner's key. I'm + going with the latter. -dshaw */ + + /* && node->pkt->pkt.user_id->created) */ + if (node->pkt->pkttype == PKT_USER_ID) + { + if (uidnode && issigned) + { + if (uid->help_full_count >= opt.completes_needed + || uid->help_marginal_count >= opt.marginals_needed ) + uidnode->flag |= 4; + else if (uid->help_full_count || uid->help_marginal_count) + uidnode->flag |= 2; + uidnode->flag |= 1; + any_signed = 1; + } + uidnode = node; + uid=uidnode->pkt->pkt.user_id; +#if 0 + /* If the selfsig is going to expire... This is disabled as + we do count un-self-signed uids in the web of trust. */ + if(uid->expiredate && uid->expiredate<*next_expire) + *next_expire = uid->expiredate; +#endif + issigned = 0; + get_validity_counts(pk,uid); + mark_usable_uid_certs (kb, uidnode, main_kid, klist, + curtime, next_expire); + } + else if (node->pkt->pkttype == PKT_SIGNATURE + && (node->flag & (1<<8)) && uid) + { + /* Note that we are only seeing unrevoked sigs here */ + PKT_signature *sig = node->pkt->pkt.signature; + + kr = is_in_klist (klist, sig); + /* If the trust_regexp does not match, it's as if the sig + did not exist. This is safe for non-trust sigs as well + since we don't accept a regexp on the sig unless it's a + trust sig. */ + if (kr && (kr->trust_regexp==NULL || opt.trust_model!=TM_PGP || + (uidnode && check_regexp(kr->trust_regexp, + uidnode->pkt->pkt.user_id->name)))) + { + if(DBG_TRUST && opt.trust_model==TM_PGP && sig->trust_depth) + log_debug("trust sig on %s, sig depth is %d, kr depth is %d\n", + uidnode->pkt->pkt.user_id->name,sig->trust_depth, + kr->trust_depth); + + /* Are we part of a trust sig chain? We always favor + the latest trust sig, rather than the greater or + lesser trust sig or value. I could make a decent + argument for any of these cases, but this seems to be + what PGP does, and I'd like to be compatible. -dms */ + if(opt.trust_model==TM_PGP && sig->trust_depth + && pk->trust_timestamp<=sig->timestamp + && (sig->trust_depth<=kr->trust_depth + || kr->ownertrust==TRUST_ULTIMATE)) + { + /* If we got here, we know that: + + this is a trust sig. + + it's a newer trust sig than any previous trust + sig on this key (not uid). + + it is legal in that it was either generated by an + ultimate key, or a key that was part of a trust + chain, and the depth does not violate the + original trust sig. + + if there is a regexp attached, it matched + successfully. + */ + + if(DBG_TRUST) + log_debug("replacing trust value %d with %d and " + "depth %d with %d\n", + pk->trust_value,sig->trust_value, + pk->trust_depth,sig->trust_depth); + + pk->trust_value=sig->trust_value; + pk->trust_depth=sig->trust_depth-1; + + /* If the trust sig contains a regexp, record it + on the pk for the next round. */ + if(sig->trust_regexp) + pk->trust_regexp=sig->trust_regexp; + } + + if (kr->ownertrust == TRUST_ULTIMATE) + uid->help_full_count = opt.completes_needed; + else if (kr->ownertrust == TRUST_FULLY) + uid->help_full_count++; + else if (kr->ownertrust == TRUST_MARGINAL) + uid->help_marginal_count++; + issigned = 1; + } + } + } + + if (uidnode && issigned) + { + if (uid->help_full_count >= opt.completes_needed + || uid->help_marginal_count >= opt.marginals_needed ) + uidnode->flag |= 4; + else if (uid->help_full_count || uid->help_marginal_count) + uidnode->flag |= 2; + uidnode->flag |= 1; + any_signed = 1; + } + + return any_signed; +} + + +static int +search_skipfnc (void *opaque, u32 *kid) +{ + return test_key_hash_table ((KeyHashTable)opaque, kid); +} + + +/* + * Scan all keys and return a key_array of all suitable keys from + * kllist. The caller has to pass keydb handle so that we don't use + * to create our own. Returns either a key_array or NULL in case of + * an error. No results found are indicated by an empty array. + * Caller hast to release the returned array. + */ +static struct key_array * +validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, + struct key_item *klist, u32 curtime, u32 *next_expire) +{ + KBNODE keyblock = NULL; + struct key_array *keys = NULL; + size_t nkeys, maxkeys; + int rc; + KEYDB_SEARCH_DESC desc; + + maxkeys = 1000; + keys = m_alloc ((maxkeys+1) * sizeof *keys); + nkeys = 0; + + rc = keydb_search_reset (hd); + if (rc) + { + log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); + m_free (keys); + return NULL; + } + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FIRST; + desc.skipfnc = search_skipfnc; + desc.skipfncvalue = full_trust; + rc = keydb_search (hd, &desc, 1); + if (rc == -1) + { + keys[nkeys].keyblock = NULL; + return keys; + } + if (rc) + { + log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); + m_free (keys); + return NULL; + } + + desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */ + do + { + PKT_public_key *pk; + + rc = keydb_get_keyblock (hd, &keyblock); + if (rc) + { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + m_free (keys); + return NULL; + } + + if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY) + { + log_debug ("ooops: invalid pkttype %d encountered\n", + keyblock->pkt->pkttype); + dump_kbnode (keyblock); + release_kbnode(keyblock); + continue; + } + + /* prepare the keyblock for further processing */ + merge_keys_and_selfsig (keyblock); + clear_kbnode_flags (keyblock); + pk = keyblock->pkt->pkt.public_key; + if (pk->has_expired || pk->is_revoked) + { + /* it does not make sense to look further at those keys */ + mark_keyblock_seen (full_trust, keyblock); + } + else if (validate_one_keyblock (keyblock, klist, curtime, next_expire)) + { + KBNODE node; + + if (pk->expiredate && pk->expiredate >= curtime + && pk->expiredate < *next_expire) + *next_expire = pk->expiredate; + + if (nkeys == maxkeys) { + maxkeys += 1000; + keys = m_realloc (keys, (maxkeys+1) * sizeof *keys); + } + keys[nkeys++].keyblock = keyblock; + + /* Optimization - if all uids are fully trusted, then we + never need to consider this key as a candidate again. */ + + for (node=keyblock; node; node = node->next) + if (node->pkt->pkttype == PKT_USER_ID && !(node->flag & 4)) + break; + + if(node==NULL) + mark_keyblock_seen (full_trust, keyblock); + + keyblock = NULL; + } + + release_kbnode (keyblock); + keyblock = NULL; + } + while ( !(rc = keydb_search (hd, &desc, 1)) ); + if (rc && rc != -1) + { + log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); + m_free (keys); + return NULL; + } + + keys[nkeys].keyblock = NULL; + return keys; +} + +/* Caller must sync */ +static void +reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude) +{ + int rc; + KBNODE keyblock = NULL; + KEYDB_SEARCH_DESC desc; + int count = 0, nreset = 0; + + rc = keydb_search_reset (hd); + if (rc) + { + log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); + return; + } + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FIRST; + if(exclude) + { + desc.skipfnc = search_skipfnc; + desc.skipfncvalue = exclude; + } + rc = keydb_search (hd, &desc, 1); + if (rc && rc != -1 ) + log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); + else if (!rc) + { + desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */ + do + { + rc = keydb_get_keyblock (hd, &keyblock); + if (rc) + { + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + break; + } + count++; + + if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY) /* paranoid assertion*/ + { + nreset += clear_validity (keyblock->pkt->pkt.public_key); + release_kbnode (keyblock); + } + } + while ( !(rc = keydb_search (hd, &desc, 1)) ); + if (rc && rc != -1) + log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); + } + if (opt.verbose) + log_info (_("%d keys processed (%d validity counts cleared)\n"), + count, nreset); +} + +/* + * Run the key validation procedure. + * + * This works this way: + * Step 1: Find all ultimately trusted keys (UTK). + * mark them all as seen and put them into klist. + * Step 2: loop max_cert_times + * Step 3: if OWNERTRUST of any key in klist is undefined + * ask user to assign ownertrust + * Step 4: Loop over all keys in the keyDB which are not marked seen + * Step 5: if key is revoked or expired + * mark key as seen + * continue loop at Step 4 + * Step 6: For each user ID of that key signed by a key in klist + * Calculate validity by counting trusted signatures. + * Set validity of user ID + * Step 7: If any signed user ID was found + * mark key as seen + * End Loop + * Step 8: Build a new klist from all fully trusted keys from step 6 + * End Loop + * Ready + * + */ +static int +validate_keys (int interactive) +{ + int rc = 0; + int quit=0; + struct key_item *klist = NULL; + struct key_item *k; + struct key_array *keys = NULL; + struct key_array *kar; + KEYDB_HANDLE kdb = NULL; + KBNODE node; + int depth; + int key_count; + int ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate; + KeyHashTable stored,used,full_trust; + u32 start_time, next_expire; + + start_time = make_timestamp (); + next_expire = 0xffffffff; /* set next expire to the year 2106 */ + stored = new_key_hash_table (); + used = new_key_hash_table (); + full_trust = new_key_hash_table (); + /* Fixme: Instead of always building a UTK list, we could just build it + * here when needed */ + if (!utk_list) + { + log_info (_("no ultimately trusted keys found\n")); + goto leave; + } + + kdb = keydb_new (0); + + reset_trust_records (kdb,NULL); + + /* mark all UTKs as used and fully_trusted and set validity to + ultimate */ + for (k=utk_list; k; k = k->next) + { + KBNODE keyblock; + PKT_public_key *pk; + + keyblock = get_pubkeyblock (k->kid); + if (!keyblock) + { + log_error (_("public key of ultimately" + " trusted key %08lX not found\n"), (ulong)k->kid[1]); + continue; + } + mark_keyblock_seen (used, keyblock); + mark_keyblock_seen (stored, keyblock); + mark_keyblock_seen (full_trust, keyblock); + pk = keyblock->pkt->pkt.public_key; + for (node=keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID) + update_validity (pk, node->pkt->pkt.user_id, 0, TRUST_ULTIMATE); + } + if ( pk->expiredate && pk->expiredate >= start_time + && pk->expiredate < next_expire) + next_expire = pk->expiredate; + + release_kbnode (keyblock); + do_sync (); + } + + klist = utk_list; + + log_info(_("%d marginal(s) needed, %d complete(s) needed, %s trust model\n"), + opt.marginals_needed,opt.completes_needed,trust_model_string()); + + for (depth=0; depth < opt.max_cert_depth; depth++) + { + /* See whether we should assign ownertrust values to the keys in + utk_list. */ + ot_unknown = ot_undefined = ot_never = 0; + ot_marginal = ot_full = ot_ultimate = 0; + for (k=klist; k; k = k->next) + { + int min=0; + + /* 120 and 60 are as per RFC2440 */ + if(k->trust_value>=120) + min=TRUST_FULLY; + else if(k->trust_value>=60) + min=TRUST_MARGINAL; + + if(min!=k->min_ownertrust) + update_min_ownertrust(k->kid,min); + + if (interactive && k->ownertrust == TRUST_UNKNOWN) + { + k->ownertrust = ask_ownertrust (k->kid,min); + + if (k->ownertrust == -1) + { + quit=1; + goto leave; + } + } + + /* This can happen during transition from an old trustdb + before trust sigs. It can also happen if a user uses two + different versions of GnuPG or changes the --trust-model + setting. */ + if(k->ownertrust<min) + { + if(DBG_TRUST) + log_debug("key %08lX: " + "overriding ownertrust \"%s\" with \"%s\"\n", + (ulong)k->kid[1], + trust_value_to_string(k->ownertrust), + trust_value_to_string(min)); + + k->ownertrust=min; + } + + if (k->ownertrust == TRUST_UNKNOWN) + ot_unknown++; + else if (k->ownertrust == TRUST_UNDEFINED) + ot_undefined++; + else if (k->ownertrust == TRUST_NEVER) + ot_never++; + else if (k->ownertrust == TRUST_MARGINAL) + ot_marginal++; + else if (k->ownertrust == TRUST_FULLY) + ot_full++; + else if (k->ownertrust == TRUST_ULTIMATE) + ot_ultimate++; + } + + /* Find all keys which are signed by a key in kdlist */ + keys = validate_key_list (kdb, full_trust, klist, + start_time, &next_expire); + if (!keys) + { + log_error ("validate_key_list failed\n"); + rc = G10ERR_GENERAL; + goto leave; + } + + for (key_count=0, kar=keys; kar->keyblock; kar++, key_count++) + ; + + /* Store the calculated valididation status somewhere */ + if (opt.verbose > 1) + dump_key_array (depth, keys); + + for (kar=keys; kar->keyblock; kar++) + store_validation_status (depth, kar->keyblock, stored); + + log_info (_("checking at depth %d valid=%d" + " ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n"), + depth, key_count, ot_unknown, ot_undefined, + ot_never, ot_marginal, ot_full, ot_ultimate ); + + /* Build a new kdlist from all fully valid keys in KEYS */ + if (klist != utk_list) + release_key_items (klist); + klist = NULL; + for (kar=keys; kar->keyblock; kar++) + { + for (node=kar->keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID && (node->flag & 4)) + { + u32 kid[2]; + + /* have we used this key already? */ + keyid_from_pk (kar->keyblock->pkt->pkt.public_key, kid); + if(test_key_hash_table(used,kid)==0) + { + /* Normally we add both the primary and subkey + ids to the hash via mark_keyblock_seen, but + since we aren't using this hash as a skipfnc, + that doesn't matter here. */ + add_key_hash_table (used,kid); + k = new_key_item (); + k->kid[0]=kid[0]; + k->kid[1]=kid[1]; + k->ownertrust = + (get_ownertrust (kar->keyblock->pkt->pkt.public_key) + & TRUST_MASK); + k->min_ownertrust = + get_min_ownertrust(kar->keyblock->pkt->pkt.public_key); + k->trust_depth= + kar->keyblock->pkt->pkt.public_key->trust_depth; + k->trust_value= + kar->keyblock->pkt->pkt.public_key->trust_value; + if(kar->keyblock->pkt->pkt.public_key->trust_regexp) + k->trust_regexp= + m_strdup(kar->keyblock->pkt-> + pkt.public_key->trust_regexp); + k->next = klist; + klist = k; + break; + } + } + } + } + release_key_array (keys); + keys = NULL; + if (!klist) + break; /* no need to dive in deeper */ + } + + leave: + keydb_release (kdb); + release_key_array (keys); + release_key_items (klist); + release_key_hash_table (full_trust); + release_key_hash_table (used); + release_key_hash_table (stored); + if (!rc && !quit) /* mark trustDB as checked */ + { + if (next_expire == 0xffffffff || next_expire < start_time ) + tdbio_write_nextcheck (0); + else + { + tdbio_write_nextcheck (next_expire); + log_info (_("next trustdb check due at %s\n"), + strtimestamp (next_expire)); + } + + if(tdbio_update_version_record()!=0) + { + log_error(_("unable to update trustdb version record: " + "write failed: %s\n"), g10_errstr(rc)); + tdbio_invalid(); + } + + do_sync (); + pending_check_trustdb = 0; + } + + return rc; +} diff --git a/g10/trustdb.h b/g10/trustdb.h new file mode 100644 index 000000000..720385a06 --- /dev/null +++ b/g10/trustdb.h @@ -0,0 +1,83 @@ +/* trustdb.h - Trust database + * 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 + */ + +#ifndef G10_TRUSTDB_H +#define G10_TRUSTDB_H + + +/* Trust values must be sorted in ascending order */ +#define TRUST_MASK 15 +#define TRUST_UNKNOWN 0 /* o: not yet calculated/assigned */ +#define TRUST_EXPIRED 1 /* e: calculation may be invalid */ +#define TRUST_UNDEFINED 2 /* q: not enough information for calculation */ +#define TRUST_NEVER 3 /* n: never trust this pubkey */ +#define TRUST_MARGINAL 4 /* m: marginally trusted */ +#define TRUST_FULLY 5 /* f: fully trusted */ +#define TRUST_ULTIMATE 6 /* u: ultimately trusted */ +/* trust values not covered by the mask */ +#define TRUST_FLAG_REVOKED 32 /* r: revoked */ +#define TRUST_FLAG_SUB_REVOKED 64 /* r: revoked but for subkeys */ +#define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */ +#define TRUST_FLAG_PENDING_CHECK 256 /* a check-trustdb is pending */ + +/*-- trustdb.c --*/ +void register_trusted_key( const char *string ); +void check_trustdb (void); +void update_trustdb (void); +int setup_trustdb( int level, const char *dbname ); +void init_trustdb( void ); +void sync_trustdb( void ); + +const char *trust_value_to_string (unsigned int value); +int string_to_trust_value (const char *str); + +void revalidation_mark (void); +int trustdb_pending_check(void); + +int cache_disabled_value(PKT_public_key *pk); + +unsigned int get_validity (PKT_public_key *pk, PKT_user_id *uid); +int get_validity_info (PKT_public_key *pk, PKT_user_id *uid); +const char *get_validity_string (PKT_public_key *pk, PKT_user_id *uid); + +void list_trust_path( const char *username ); +int enum_cert_paths( void **context, ulong *lid, + unsigned *ownertrust, unsigned *validity ); +void enum_cert_paths_print( void **context, FILE *fp, + int refresh, ulong selected_lid ); + +unsigned int get_ownertrust (PKT_public_key *pk); +unsigned int get_min_ownertrust (PKT_public_key *pk); +int get_ownertrust_info (PKT_public_key *pk); +const char *get_ownertrust_string (PKT_public_key *pk); + +void update_ownertrust (PKT_public_key *pk, unsigned int new_trust ); +int clear_ownertrusts (PKT_public_key *pk); + +/*-- tdbdump.c --*/ +void list_trustdb(const char *username); +void export_ownertrust(void); +void import_ownertrust(const char *fname); + +/*-- pkclist.c --*/ +int edit_ownertrust (PKT_public_key *pk, int mode ); + +#endif /*G10_TRUSTDB_H*/ diff --git a/g10/verify.c b/g10/verify.c new file mode 100644 index 000000000..705a45746 --- /dev/null +++ b/g10/verify.c @@ -0,0 +1,193 @@ +/* verify.c - verify signed data + * 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 <errno.h> +#include <assert.h> +#include <unistd.h> /* for isatty() */ + +#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 "filter.h" +#include "ttyio.h" +#include "i18n.h" + + + +/**************** + * Assume that the input is a signature and verify it without + * generating any output. With no arguments, the signature packet + * is read from stdin (it may be a detached signature when not + * used in batch mode). If only a sigfile is given, it may be a complete + * signature or a detached signature in which case the signed stuff + * is expected from stdin. With more than 1 argument, the first should + * be a detached signature and the remaining files are the signed stuff. + */ + +int +verify_signatures( int nfiles, char **files ) +{ + IOBUF fp; + armor_filter_context_t afx; + progress_filter_context_t pfx; + const char *sigfile; + int i, rc; + STRLIST sl; + + memset( &afx, 0, sizeof afx); + /* decide whether we should handle a detached or a normal signature, + * which is needed so that the code later can hash the correct data and + * not have a normal signature act as detached signature and ignoring the + * indended signed material from the 2nd file or stdin. + * 1. gpg <file - normal + * 2. gpg file - normal (or detached) + * 3. gpg file <file2 - detached + * 4. gpg file file2 - detached + * The question is how decide between case 2 and 3? The only way + * we can do it is by reading one byte from stdin and the unget + * it; the problem here is that we may be reading from the + * terminal (which could be detected using isatty() but won't work + * when under contol of a pty using program (e.g. expect)) and + * might get us in trouble when stdin is used for another purpose + * (--passphrase-fd 0). So we have to break with the behaviour + * prior to gpg 1.0.4 by assuming that case 3 is a normal + * signature (where file2 is ignored and require for a detached + * signature to indicate signed material comes from stdin by using + * case 4 with a file2 of "-". + * + * Actually we don't have to change anything here but can handle + * that all quite easily in mainproc.c + */ + + + sigfile = nfiles? *files : NULL; + + /* open the signature file */ + fp = iobuf_open(sigfile); + if( !fp ) { + log_error(_("can't open `%s'\n"), print_fname_stdin(sigfile)); + return G10ERR_OPEN_FILE; + } + handle_progress (&pfx, fp, sigfile); + + if( !opt.no_armor && use_armor_filter( fp ) ) + iobuf_push_filter( fp, armor_filter, &afx ); + + sl = NULL; + for(i=1 ; i < nfiles; i++ ) + add_to_strlist( &sl, files[i] ); + rc = proc_signature_packets( NULL, fp, sl, sigfile ); + free_strlist(sl); + iobuf_close(fp); + if( afx.no_openpgp_data && rc == -1 ) { + log_error(_("the signature could not be verified.\n" + "Please remember that the signature file (.sig or .asc)\n" + "should be the first file given on the command line.\n") ); + rc = 0; + } + + return rc; +} + + +void +print_file_status( int status, const char *name, int what ) +{ + char *p = m_alloc(strlen(name)+10); + sprintf(p, "%d %s", what, name ); + write_status_text( status, p ); + m_free(p); +} + + +static int +verify_one_file( const char *name ) +{ + IOBUF fp; + armor_filter_context_t afx; + progress_filter_context_t pfx; + int rc; + + print_file_status( STATUS_FILE_START, name, 1 ); + fp = iobuf_open(name); + if( !fp ) { + print_file_status( STATUS_FILE_ERROR, name, 1 ); + log_error(_("can't open `%s'\n"), print_fname_stdin(name)); + return G10ERR_OPEN_FILE; + } + handle_progress (&pfx, fp, name); + + if( !opt.no_armor ) { + if( use_armor_filter( fp ) ) { + memset( &afx, 0, sizeof afx); + iobuf_push_filter( fp, armor_filter, &afx ); + } + } + + rc = proc_signature_packets( NULL, fp, NULL, name ); + iobuf_close(fp); + write_status( STATUS_FILE_DONE ); + return rc; +} + +/**************** + * Verify each file given in the files array or read the names of the + * files from stdin. + * Note: This function can not handle detached signatures. + */ +int +verify_files( int nfiles, char **files ) +{ + int i; + + if( !nfiles ) { /* read the filenames from stdin */ + 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 G10ERR_GENERAL; + } + /* This code does not work on MSDOS but how cares there are + * also no script languages available. We don't strip any + * spaces, so that we can process nearly all filenames */ + line[strlen(line)-1] = 0; + verify_one_file( line ); + } + + } + else { /* take filenames from the array */ + for(i=0; i < nfiles; i++ ) + verify_one_file( files[i] ); + } + return 0; +} diff --git a/include/ChangeLog b/include/ChangeLog new file mode 100644 index 000000000..3df94bb43 --- /dev/null +++ b/include/ChangeLog @@ -0,0 +1,373 @@ +2003-05-24 David Shaw <dshaw@jabberwocky.com> + + * cipher.h, i18n.h, iobuf.h, memory.h, mpi.h, types.h, util.h: + Edit all preprocessor instructions to remove whitespace before the + '#'. This is not required by C89, but there are some compilers + out there that don't like it. + +2003-05-14 David Shaw <dshaw@jabberwocky.com> + + * types.h: Add initializer macros for 64-bit unsigned type. + +2003-05-02 David Shaw <dshaw@jabberwocky.com> + + * cipher.h: Add constants for compression algorithms. + +2003-03-11 David Shaw <dshaw@jabberwocky.com> + + * http.h: Add HTTP_FLAG_TRY_SRV. + +2003-02-11 David Shaw <dshaw@jabberwocky.com> + + * types.h: Try and use uint64_t for a 64-bit type. + +2003-02-04 David Shaw <dshaw@jabberwocky.com> + + * cipher.h: Add constants for new SHAs. + +2002-11-13 David Shaw <dshaw@jabberwocky.com> + + * util.h [__CYGWIN32__]: Don't need the registry prototypes. From + Werner on stable branch. + +2002-11-06 David Shaw <dshaw@jabberwocky.com> + + * util.h: Add wipememory2() macro (same as wipememory, but can + specify the byte to wipe with). + +2002-10-31 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Prefixed all RISC OS prototypes with + riscos_* + + * zlib-riscos.h: New. This is macro magic in order to make the + zlib library calls indeed call the RISC OS ZLib module. + +2002-10-31 David Shaw <dshaw@jabberwocky.com> + + * util.h: Add wipememory() macro. + +2002-10-29 Stefan Bellon <sbellon@sbellon.de> + + * util.h: Added parameter argument to make_basename() needed for + filetype support. + [__riscos__]: Added prototype. + +2002-10-28 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Added prototypes for new filetype support. + +2002-10-19 David Shaw <dshaw@jabberwocky.com> + + * distfiles, _regex.h: Add _regex.h from glibc 2.3.1. + +2002-10-14 David Shaw <dshaw@jabberwocky.com> + + * keyserver.h: Go to KEYSERVER_PROTO_VERSION 1. + +2002-10-08 David Shaw <dshaw@jabberwocky.com> + + * keyserver.h: Add new error code KEYSERVER_UNREACHABLE. + +2002-10-03 David Shaw <dshaw@jabberwocky.com> + + * util.h: Add new log_warning logger command which can be switched + between log_info and log_error via log_set_strict. + +2002-09-24 David Shaw <dshaw@jabberwocky.com> + + * keyserver.h: Add some new error codes for better GPA support. + +2002-09-10 Werner Koch <wk@gnupg.org> + + * mpi.h (mpi_is_protected, mpi_set_protect_flag) + (mpi_clear_protect_flag): Removed. + (mpi_get_nbit_info, mpi_set_nbit_info): Removed. + +2002-08-13 David Shaw <dshaw@jabberwocky.com> + + * cipher.h: Add AES aliases for RIJNDAEL algo numbers. + +2002-08-07 David Shaw <dshaw@jabberwocky.com> + + * cipher.h: Add md_algo_present(). + +2002-08-06 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Added riscos_getchar(). + +2002-06-21 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Further moving away of RISC OS specific + stuff from general code. + +2002-06-20 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Added riscos_set_filetype(). + +2002-06-14 David Shaw <dshaw@jabberwocky.com> + + * util.h: Add pop_strlist() from strgutil.c. + +2002-06-07 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: RISC OS needs strings.h for strcasecmp() + and strncasecmp(). + +2002-05-22 Werner Koch <wk@gnupg.org> + + * util.h: Add strncasecmp. Removed stricmp and memicmp. + +2002-05-10 Stefan Bellon <sbellon@sbellon.de> + + * mpi.h: New function mpi_debug_alloc_like for M_DEBUG. + + * util.h [__riscos__]: Make use of __func__ that later + Norcroft compiler provides. + + * memory.h: Fixed wrong definition of m_alloc_secure_clear. + +2002-04-23 David Shaw <dshaw@jabberwocky.com> + + * util.h: New function answer_is_yes_no_default() to give a + default answer. + +2002-04-22 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Removed riscos_open, riscos_fopen and + riscos_fstat as those special versions aren't needed anymore. + +2002-02-19 David Shaw <dshaw@jabberwocky.com> + + * keyserver.h: Add KEYSERVER_NOT_SUPPORTED for unsupported actions + (say, a keyserver that has no way to search, or a readonly + keyserver that has no way to add). + +2002-01-02 Stefan Bellon <sbellon@sbellon.de> + + * util.h [__riscos__]: Updated prototype list. + + * types.h [__riscos__]: Changed comment wording. + +2001-12-27 David Shaw <dshaw@jabberwocky.com> + + * KEYSERVER_SCHEME_NOT_FOUND should be 127 to match the POSIX + system() (via /bin/sh) way of signaling this. + + * Added G10ERR_KEYSERVER + +2001-12-27 Werner Koch <wk@gnupg.org> + + * util.h [MINGW32]: Fixed name of include file. + +2001-12-22 Timo Schulz <ts@winpt.org> + + * util.h (is_file_compressed): New. + +2001-12-19 Werner Koch <wk@gnupg.org> + + * util.h [CYGWIN32]: Allow this as an alias for MINGW32. Include + stdarg.h becuase we use the va_list type. By Disastry. + +2001-09-28 Werner Koch <wk@gnupg.org> + + * cipher.h (PUBKEY_USAGE_CERT): New. + +2001-09-07 Werner Koch <wk@gnupg.org> + + * util.h: Add strsep(). + +2001-08-30 Werner Koch <wk@gnupg.org> + + * cipher.h (DEK): Added use_mdc. + +2001-08-24 Werner Koch <wk@gnupg.org> + + * cipher.h (md_write): Made buf arg const. + +2001-08-20 Werner Koch <wk@gnupg.org> + + * cipher.h (DEK): Added algo_info_printed; + + * util.h [__riscos__]: Added prototypes and made sure that we + never use __attribute__. + * cipher.h, iobuf.h, memory.h, mpi.h [__riscos__]: extern hack. + * i18n.h [__riscos__]: Use another include file + +2001-05-30 Werner Koch <wk@gnupg.org> + + * ttyio.h (tty_printf): Add missing parenthesis for non gcc. + * http.h: Removed trailing comma to make old ccs happy. Both are + by Albert Chin. + +2001-05-25 Werner Koch <wk@gnupg.org> + + * ttyio.h (tty_printf): Add printf attribute. + +2001-04-23 Werner Koch <wk@gnupg.org> + + * http.h: New flag HTTP_FLAG_NO_SHUTDOWN. + +2001-04-13 Werner Koch <wk@gnupg.org> + + * iobuf.h: Removed iobuf_fopen. + +2001-03-01 Werner Koch <wk@gnupg.org> + + * errors.h (G10ERR_UNU_SECKEY,G10ERR_UNU_PUBKEY): New + +2000-11-30 Werner Koch <wk@gnupg.org> + + * iobuf.h (iobuf_translate_file_handle): Add prototype. + +2000-11-11 Paul Eggert <eggert@twinsun.com> + + * iobuf.h (iobuf_get_filelength): Now returns off_t, not u32. + (struct iobuf_struct, iobuf_set_limit, + iobuf_tell, iobuf_seek): Use off_t, not ulong, for file offsets. + +2000-10-12 Werner Koch <wk@gnupg.org> + + * mpi.h: Changed the way mpi_limb_t is defined. + +Wed Sep 6 17:55:47 CEST 2000 Werner Koch <wk@openit.de> + + * iobuf.c (IOBUF_FILELENGTH_LIMIT): New. + +2000-03-14 14:03:43 Werner Koch (wk@habibti.openit.de) + + * types.h (HAVE_U64_TYPEDEF): Defined depending on configure test. + +Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de> + + * types.h (HAVE_U64_TYPEDEF): Add a test for _LONGLONG which fixes + this long living SGI bug. Reported by Alec Habig. + +Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de> + + * iobuf.h (IOBUFCTRL_CANCEL): Nww. + +Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de> + + * errors.h (G10ERR_NOT_PROCESSED): New. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * i18n.h: Add support for simple-gettext. + +Tue Jun 29 21:44:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * util.h (stricmp): Use strcasecmp as replacement. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * cipher.h (MD_HANDLE): Assigned a structure name. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.h (BLOWFISH160): Removed. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.h (DEK): increased max. key length to 32 bytes + + +Sat Feb 20 21:40:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * g10lib.h: Removed file and changed all files that includes this. + +Tue Feb 16 14:10:02 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * types.h (STRLIST): Add field flags. + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.h (CIPHER_ALGO_TWOFISH): Chnaged ID to 10 and renamed + the old experimenatl algorithm to xx_OLD. + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * cipher.h (MD_BUFFER_SIZE): Removed. + +Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * types.h: fix for SUNPRO_C + +Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * mpi.h (MPI): Changed the structure name to gcry_mpi and + changed all users. + +Tue Oct 20 11:40:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * iobuf.h (iobuf_get_temp_buffer): New. + +Tue Oct 13 12:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * iobuf.h (iobuf_get): Now uses .nofast + (iobuf_get2): Removed. + +Mon Sep 14 09:17:22 1998 Werner Koch (wk@(none)) + + * util.h (HAVE_ATEXIT): New. + (HAVE_RAISE): New. + +Mon Jul 6 10:41:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h (PUBKEY_USAGE_): New. + +Mon Jul 6 09:49:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * iobuf.h (iobuf_set_error): New. + (iobuf_error): New. + +Sat Jun 13 17:31:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * g10lib.h: New as interface for the g10lib. + +Mon Jun 8 22:14:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h (CIPHER_ALGO_CAST5): Changed name from .. CAST + +Thu May 21 13:25:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h: removed ROT 5 and changed one id and add dummy + +Tue May 19 18:09:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h (DIGEST_ALGO_TIGER): Chnaged id from 101 to 6. + +Mon May 4 16:37:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h (PUBKEY_ALGO_ELGAMAL_E): New, with value of the + old one. + * (is_ELGAMAL, is_RSA): New macros + +Sun Apr 26 14:35:24 1998 Werner Koch (wk@isil.d.shuttle.de) + + * types.h: New type u64 + +Mon Mar 9 12:59:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h: Included dsa.h. + +Tue Mar 3 15:11:21 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h (random.h): Add new header and move all relevalt + functions to this header. + + + Copyright 1998, 1999, 2000, 2001 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. + + diff --git a/include/cipher.h b/include/cipher.h new file mode 100644 index 000000000..23a5aeb0d --- /dev/null +++ b/include/cipher.h @@ -0,0 +1,205 @@ +/* cipher.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_CIPHER_H +#define G10_CIPHER_H + +#define DBG_CIPHER g10c_debug_mode + +#include "mpi.h" +#include "../cipher/random.h" + + +#define CIPHER_ALGO_NONE 0 +#define CIPHER_ALGO_IDEA 1 +#define CIPHER_ALGO_3DES 2 +#define CIPHER_ALGO_CAST5 3 +#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ +#define CIPHER_ALGO_SAFER_SK128 5 +#define CIPHER_ALGO_DES_SK 6 +#define CIPHER_ALGO_AES 7 +#define CIPHER_ALGO_AES192 8 +#define CIPHER_ALGO_AES256 9 +#define CIPHER_ALGO_RIJNDAEL CIPHER_ALGO_AES +#define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192 +#define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256 +#define CIPHER_ALGO_TWOFISH 10 /* twofish 256 bit */ +#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */ +#define CIPHER_ALGO_TWOFISH_OLD 102 /* experimental: twofish 128 bit */ +#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ + +#define PUBKEY_ALGO_RSA 1 +#define PUBKEY_ALGO_RSA_E 2 /* RSA encrypt only */ +#define PUBKEY_ALGO_RSA_S 3 /* RSA sign only */ +#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not for v3)*/ +#define PUBKEY_ALGO_DSA 17 +#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ + +#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ +#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ +#define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/ + +#define DIGEST_ALGO_MD5 1 +#define DIGEST_ALGO_SHA1 2 +#define DIGEST_ALGO_RMD160 3 +#define DIGEST_ALGO_TIGER 6 +#define DIGEST_ALGO_SHA256 8 +#define DIGEST_ALGO_SHA384 9 +#define DIGEST_ALGO_SHA512 10 + +#define COMPRESS_ALGO_NONE 0 +#define COMPRESS_ALGO_ZIP 1 +#define COMPRESS_ALGO_ZLIB 2 + +#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ + || (a)==PUBKEY_ALGO_RSA_S ) +#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) + +typedef struct { + int algo; + int keylen; + int algo_info_printed; + int use_mdc; + byte key[32]; /* this is the largest used keylen (256 bit) */ +} DEK; + +struct cipher_handle_s; +typedef struct cipher_handle_s *CIPHER_HANDLE; + + +#define CIPHER_MODE_ECB 1 +#define CIPHER_MODE_CFB 2 +#define CIPHER_MODE_PHILS_CFB 3 +#define CIPHER_MODE_AUTO_CFB 4 +#define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */ +#define CIPHER_MODE_CBC 6 + +struct md_digest_list_s; + +struct gcry_md_context { + int secure; + FILE *debug; + int finalized; + struct md_digest_list_s *list; + int bufcount; + int bufsize; + byte buffer[1]; +}; + +typedef struct gcry_md_context *MD_HANDLE; + +#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 g10c_debug_mode; +EXTERN_UNLESS_MAIN_MODULE int g10_opt_verbose; +EXTERN_UNLESS_MAIN_MODULE const char *g10_opt_homedir; + + +/*-- dynload.c --*/ +void register_cipher_extension( const char *mainpgm, const char *fname ); + +/*-- md.c --*/ +int string_to_digest_algo( const char *string ); +const char * digest_algo_to_string( int algo ); +int check_digest_algo( int algo ); +MD_HANDLE md_open( int algo, int secure ); +void md_enable( MD_HANDLE hd, int algo ); +MD_HANDLE md_copy( MD_HANDLE a ); +void md_reset( MD_HANDLE a ); +void md_close(MD_HANDLE a); +void md_write( MD_HANDLE a, const byte *inbuf, size_t inlen); +void md_final(MD_HANDLE a); +byte *md_read( MD_HANDLE a, int algo ); +int md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen ); +int md_get_algo( MD_HANDLE a ); +int md_algo_present( MD_HANDLE a, int algo ); +int md_digest_length( int algo ); +const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); +void md_start_debug( MD_HANDLE a, const char *suffix ); +void md_stop_debug( MD_HANDLE a ); +#define md_is_secure(a) ((a)->secure) +#define md_putc(h,c) \ + do { \ + if( (h)->bufcount == (h)->bufsize ) \ + md_write( (h), NULL, 0 ); \ + (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ + } while(0) + +void rmd160_hash_buffer (char *outbuf, const char *buffer, size_t length); + + +/*-- cipher.c --*/ +int string_to_cipher_algo( const char *string ); +const char * cipher_algo_to_string( int algo ); +void disable_cipher_algo( int algo ); +int check_cipher_algo( int algo ); +unsigned cipher_get_keylen( int algo ); +unsigned cipher_get_blocksize( int algo ); +CIPHER_HANDLE cipher_open( int algo, int mode, int secure ); +void cipher_close( CIPHER_HANDLE c ); +int cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ); +void cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ); +void cipher_encrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); +void cipher_decrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); +void cipher_sync( CIPHER_HANDLE c ); + +/*-- pubkey.c --*/ +#define PUBKEY_MAX_NPKEY 4 +#define PUBKEY_MAX_NSKEY 6 +#define PUBKEY_MAX_NSIG 2 +#define PUBKEY_MAX_NENC 2 + +int string_to_pubkey_algo( const char *string ); +const char * pubkey_algo_to_string( int algo ); +void disable_pubkey_algo( int algo ); +int check_pubkey_algo( int algo ); +int check_pubkey_algo2( int algo, unsigned use ); +int pubkey_get_npkey( int algo ); +int pubkey_get_nskey( int algo ); +int pubkey_get_nsig( int algo ); +int pubkey_get_nenc( int algo ); +unsigned pubkey_nbits( int algo, MPI *pkey ); +int pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); +int pubkey_check_secret_key( int algo, MPI *skey ); +int pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); +int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); +int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); +int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp)(void *, MPI), void *opaque ); + +/*-- smallprime.c --*/ +extern ushort small_prime_numbers[]; + +/*-- primegen.c --*/ +void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ); +MPI generate_secret_prime( unsigned nbits ); +MPI generate_public_prime( unsigned nbits ); +MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, + MPI g, MPI **factors ); + +/*-- elsewhere --*/ +void register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data ); +void register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data ); + +#endif /*G10_CIPHER_H*/ diff --git a/include/http.h b/include/http.h new file mode 100644 index 000000000..b53ac9f9f --- /dev/null +++ b/include/http.h @@ -0,0 +1,82 @@ +/* http.h - HTTP protocol handler + * Copyright (C) 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_HTTP_H +#define G10_HTTP_H 1 + +#include "iobuf.h" + +struct uri_tuple { + struct uri_tuple *next; + const char *name; /* a pointer into name */ + char *value; /* a pointer to value (a Nul is always appended) */ + size_t valuelen; /* and the real length of the value */ + /* because the value may contain embedded Nuls */ +}; +typedef struct uri_tuple *URI_TUPLE; + +struct parsed_uri { + /* all these pointers point into buffer; most stuff is not escaped */ + char *scheme; /* pointer to the scheme string (lowercase) */ + char *host; /* host (converted to lowercase) */ + ushort port; /* port (always set if the host is set) */ + char *path; /* the path */ + URI_TUPLE params; /* ";xxxxx" */ + URI_TUPLE query; /* "?xxx=yyy" */ + char buffer[1]; /* buffer which holds a (modified) copy of the URI */ +}; +typedef struct parsed_uri *PARSED_URI; + +typedef enum { + HTTP_REQ_GET = 1, + HTTP_REQ_HEAD = 2, + HTTP_REQ_POST = 3 +} HTTP_REQ_TYPE; + +enum { /* put flag values into an enum, so that gdb can display them */ + HTTP_FLAG_TRY_PROXY = 1, + HTTP_FLAG_NO_SHUTDOWN = 2, + HTTP_FLAG_TRY_SRV = 3 +}; + +struct http_context { + int initialized; + unsigned int status_code; + int sock; + int in_data; + IOBUF fp_read; + IOBUF fp_write; + int is_http_0_9; + PARSED_URI uri; + HTTP_REQ_TYPE req_type; + byte *buffer; /* line buffer */ + unsigned buffer_size; + unsigned int flags; +}; +typedef struct http_context *HTTP_HD; + +int http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, + unsigned int flags ); +void http_start_data( HTTP_HD hd ); +int http_wait_response( HTTP_HD hd, unsigned int *ret_status ); +void http_close( HTTP_HD hd ); + +int http_open_document( HTTP_HD hd, const char *document, unsigned int flags ); + +#endif /*G10_HTTP_H*/ diff --git a/include/i18n.h b/include/i18n.h new file mode 100644 index 000000000..20c2570ab --- /dev/null +++ b/include/i18n.h @@ -0,0 +1,54 @@ +/* i18n.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_I18N_H +#define G10_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> /* suggested by Ernst Molitor */ +#endif + +#ifdef ENABLE_NLS +#ifndef __riscos__ +#include <libintl.h> +#else +#include "libgettext.h" +#endif /* __riscos__ */ +#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 /*G10_I18N_H*/ diff --git a/include/iobuf.h b/include/iobuf.h new file mode 100644 index 000000000..9ae774207 --- /dev/null +++ b/include/iobuf.h @@ -0,0 +1,161 @@ +/* iobuf.h - I/O buffer + * 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_IOBUF_H +#define G10_IOBUF_H + +#include "types.h" + + +#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; + +/* 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 chain, byte *buf, size_t *len); + void *filter_ov; /* value for opaque */ + int filter_ov_owner; + char *real_fname; + IOBUF 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 iobuf_alloc(int use, size_t bufsize); +IOBUF iobuf_temp(void); +IOBUF iobuf_temp_with_content( const char *buffer, size_t length ); +IOBUF iobuf_open( const char *fname ); +IOBUF iobuf_fdopen( int fd, const char *mode ); +IOBUF iobuf_sockopen( int fd, const char *mode ); +IOBUF iobuf_create( const char *fname ); +IOBUF iobuf_append( const char *fname ); +IOBUF iobuf_openrw( const char *fname ); +int iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ); +int iobuf_close( IOBUF iobuf ); +int iobuf_cancel( IOBUF iobuf ); + +int iobuf_push_filter( IOBUF a, int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), void *ov ); +int iobuf_push_filter2( IOBUF a, + int (*f)(void *opaque, int control, + IOBUF chain, byte *buf, size_t *len), + void *ov, int rel_ov ); +int iobuf_flush(IOBUF a); +void iobuf_clear_eof(IOBUF a); +#define iobuf_set_error(a) do { (a)->error = 1; } while(0) +#define iobuf_error(a) ((a)->error) + +void iobuf_set_limit( IOBUF a, off_t nlimit ); + +off_t iobuf_tell( IOBUF a ); +int iobuf_seek( IOBUF a, off_t newpos ); + +int iobuf_readbyte(IOBUF a); +int iobuf_read(IOBUF a, byte *buf, unsigned buflen ); +unsigned iobuf_read_line( IOBUF a, byte **addr_of_buffer, + unsigned *length_of_buffer, unsigned *max_length ); +int iobuf_peek(IOBUF a, byte *buf, unsigned buflen ); +int iobuf_writebyte(IOBUF a, unsigned c); +int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); +int iobuf_writestr(IOBUF a, const char *buf ); + +void iobuf_flush_temp( IOBUF temp ); +int iobuf_write_temp( IOBUF a, IOBUF temp ); +size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ); +void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ); + +off_t iobuf_get_filelength( IOBUF a ); +#define IOBUF_FILELENGTH_LIMIT 0xffffffff +const char *iobuf_get_real_fname( IOBUF a ); +const char *iobuf_get_fname( IOBUF a ); + +void iobuf_set_block_mode( IOBUF a, size_t n ); +void iobuf_set_partial_block_mode( IOBUF a, size_t len ); +int iobuf_in_block_mode( IOBUF 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 /*G10_IOBUF_H*/ diff --git a/include/memory.h b/include/memory.h new file mode 100644 index 000000000..959f2999e --- /dev/null +++ b/include/memory.h @@ -0,0 +1,93 @@ +/* memory.h - memory allocation + * 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_MEMORY_H +#define G10_MEMORY_H + +#ifdef M_DEBUG +#ifndef STR +#define STR(v) #v +#endif +#ifndef __riscos__ +#define M_DBGINFO(a) __FUNCTION__ "["__FILE__ ":" STR(a) "]" +#else /* __riscos__ */ +#define M_DBGINFO(a) "["__FILE__ ":" STR(a) "]" +#endif /* __riscos__ */ +#define m_alloc(n) m_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +#define m_alloc_clear(n) m_debug_alloc_clear((n), M_DBGINFO(__LINE__) ) +#define m_alloc_secure(n) m_debug_alloc((n), M_DBGINFO(__LINE__) ) +#define m_alloc_secure_clear(n) m_debug_alloc_secure_clear((n), M_DBGINFO(__LINE__) ) +#define m_realloc(n,m) m_debug_realloc((n),(m), M_DBGINFO(__LINE__) ) +#define m_free(n) m_debug_free((n), M_DBGINFO(__LINE__) ) +#define m_check(n) m_debug_check((n), M_DBGINFO(__LINE__) ) +/*#define m_copy(a) m_debug_copy((a), M_DBGINFO(__LINE__) )*/ +#define m_strdup(a) m_debug_strdup((a), M_DBGINFO(__LINE__) ) + +void *m_debug_alloc( size_t n, const char *info ); +void *m_debug_alloc_clear( size_t n, const char *info ); +void *m_debug_alloc_secure( size_t n, const char *info ); +void *m_debug_alloc_secure_clear( size_t n, const char *info ); +void *m_debug_realloc( void *a, size_t n, const char *info ); +void m_debug_free( void *p, const char *info ); +void m_debug_check( const void *a, const char *info ); +/*void *m_debug_copy( const void *a, const char *info );*/ +char *m_debug_strdup( const char *a, const char *info ); + +#else +void *m_alloc( size_t n ); +void *m_alloc_clear( size_t n ); +void *m_alloc_secure( size_t n ); +void *m_alloc_secure_clear( size_t n ); +void *m_realloc( void *a, size_t n ); +void m_free( void *p ); +void m_check( const void *a ); +/*void *m_copy( const void *a );*/ +char *m_strdup( const char * a); +#endif + +size_t m_size( const void *a ); +void m_print_stats(const char *prefix); + +/*-- secmem.c --*/ +void secmem_init( size_t npool ); +void secmem_term( void ); +void *secmem_malloc( size_t size ); +void *secmem_realloc( void *a, size_t newsize ); +void secmem_free( void *a ); +int m_is_secure( const void *p ); +void secmem_dump_stats(void); +void secmem_set_flags( unsigned flags ); +unsigned secmem_get_flags(void); + + +#define DBG_MEMORY memory_debug_mode +#define DBG_MEMSTAT memory_stat_debug_mode + +#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 memory_debug_mode; +EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; + +#endif /*G10_MEMORY_H*/ diff --git a/include/mpi.h b/include/mpi.h new file mode 100644 index 000000000..3198584a2 --- /dev/null +++ b/include/mpi.h @@ -0,0 +1,196 @@ +/* mpi.h - Multi Precision Integers + * Copyright (C) 1994, 1996, 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 + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#ifndef G10_MPI_H +#define G10_MPI_H + +#include <config.h> +#include <stdio.h> +#include "iobuf.h" +#include "types.h" +#include "memory.h" + +#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT + typedef unsigned int mpi_limb_t; + typedef signed int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG + typedef unsigned long int mpi_limb_t; + typedef signed long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG + typedef unsigned long long int mpi_limb_t; + typedef signed long long int mpi_limb_signed_t; +#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT + typedef unsigned short int mpi_limb_t; + typedef signed short int mpi_limb_signed_t; +#else +#error BYTES_PER_MPI_LIMB does not match any C type +#endif +#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB) + +#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 + +#define DBG_MPI mpi_debug_mode +EXTERN_UNLESS_MAIN_MODULE int mpi_debug_mode; + + +struct gcry_mpi { + int alloced; /* array size (# of allocated limbs) */ + int nlimbs; /* number of valid limbs */ + int nbits; /* the real number of valid bits (info only) */ + int sign; /* indicates a negative number */ + unsigned flags; /* bit 0: array must be allocated in secure memory space */ + /* bit 1: not used */ + /* bit 2: the limb is a pointer to some m_alloced data */ + mpi_limb_t *d; /* array with the limbs */ +}; + +typedef struct gcry_mpi *MPI; + +#define MPI_NULL NULL + +#define mpi_get_nlimbs(a) ((a)->nlimbs) +#define mpi_is_neg(a) ((a)->sign) + +/*-- mpiutil.c --*/ + +#ifdef M_DEBUG +#define mpi_alloc(n) mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) ) +#define mpi_alloc_secure(n) mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) ) +#define mpi_alloc_like(n) mpi_debug_alloc_like((n), M_DBGINFO( __LINE__ ) ) +#define mpi_free(a) mpi_debug_free((a), M_DBGINFO(__LINE__) ) +#define mpi_resize(a,b) mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) ) +#define mpi_copy(a) mpi_debug_copy((a), M_DBGINFO(__LINE__) ) +MPI mpi_debug_alloc( unsigned nlimbs, const char *info ); +MPI mpi_debug_alloc_secure( unsigned nlimbs, const char *info ); +MPI mpi_debug_alloc_like( MPI a, const char *info ); +void mpi_debug_free( MPI a, const char *info ); +void mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ); +MPI mpi_debug_copy( MPI a, const char *info ); +#else +MPI mpi_alloc( unsigned nlimbs ); +MPI mpi_alloc_secure( unsigned nlimbs ); +MPI mpi_alloc_like( MPI a ); +void mpi_free( MPI a ); +void mpi_resize( MPI a, unsigned nlimbs ); +MPI mpi_copy( MPI a ); +#endif +#define mpi_is_opaque(a) ((a) && ((a)->flags&4)) +MPI mpi_set_opaque( MPI a, void *p, int len ); +void *mpi_get_opaque( MPI a, int *len ); +#define mpi_is_secure(a) ((a) && ((a)->flags&1)) +void mpi_set_secure( MPI a ); +void mpi_clear( MPI a ); +void mpi_set( MPI w, MPI u); +void mpi_set_ui( MPI w, ulong u); +MPI mpi_alloc_set_ui( unsigned long u); +void mpi_m_check( MPI a ); +void mpi_swap( MPI a, MPI b); + +/*-- mpicoder.c --*/ +int mpi_write( IOBUF out, MPI a ); +#ifdef M_DEBUG +#define mpi_read(a,b,c) mpi_debug_read((a),(b),(c), M_DBGINFO( __LINE__ ) ) +MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info); +#else +MPI mpi_read(IOBUF inp, unsigned *nread, int secure); +#endif +MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure); +int mpi_fromstr(MPI val, const char *str); +int mpi_print( FILE *fp, MPI a, int mode ); +void g10_log_mpidump( const char *text, MPI a ); +u32 mpi_get_keyid( MPI a, u32 *keyid ); +byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ); +byte *mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ); +void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ); + +#define log_mpidump g10_log_mpidump + +/*-- mpi-add.c --*/ +void mpi_add_ui(MPI w, MPI u, ulong v ); +void mpi_add(MPI w, MPI u, MPI v); +void mpi_addm(MPI w, MPI u, MPI v, MPI m); +void mpi_sub_ui(MPI w, MPI u, ulong v ); +void mpi_sub( MPI w, MPI u, MPI v); +void mpi_subm( MPI w, MPI u, MPI v, MPI m); + +/*-- mpi-mul.c --*/ +void mpi_mul_ui(MPI w, MPI u, ulong v ); +void mpi_mul_2exp( MPI w, MPI u, ulong cnt); +void mpi_mul( MPI w, MPI u, MPI v); +void mpi_mulm( MPI w, MPI u, MPI v, MPI m); + +/*-- mpi-div.c --*/ +ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ); +void mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ); +void mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ); +void mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ); +void mpi_tdiv_r( MPI rem, MPI num, MPI den); +void mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den); +void mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ); +int mpi_divisible_ui(MPI dividend, ulong divisor ); + +/*-- mpi-gcd.c --*/ +int mpi_gcd( MPI g, MPI a, MPI b ); + +/*-- mpi-pow.c --*/ +void mpi_pow( MPI w, MPI u, MPI v); +void mpi_powm( MPI res, MPI base, MPI exp, MPI mod); + +/*-- mpi-mpow.c --*/ +void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod); + +/*-- mpi-cmp.c --*/ +int mpi_cmp_ui( MPI u, ulong v ); +int mpi_cmp( MPI u, MPI v ); + +/*-- mpi-scan.c --*/ +int mpi_getbyte( MPI a, unsigned idx ); +void mpi_putbyte( MPI a, unsigned idx, int value ); +unsigned mpi_trailing_zeros( MPI a ); + +/*-- mpi-bit.c --*/ +void mpi_normalize( MPI a ); +unsigned mpi_get_nbits( MPI a ); +int mpi_test_bit( MPI a, unsigned n ); +void mpi_set_bit( MPI a, unsigned n ); +void mpi_set_highbit( MPI a, unsigned n ); +void mpi_clear_highbit( MPI a, unsigned n ); +void mpi_clear_bit( MPI a, unsigned n ); +void mpi_rshift( MPI x, MPI a, unsigned n ); + +/*-- mpi-inv.c --*/ +void mpi_invm( MPI x, MPI u, MPI v ); + +#endif /*G10_MPI_H*/ diff --git a/include/types.h b/include/types.h new file mode 100644 index 000000000..fc5381965 --- /dev/null +++ b/include/types.h @@ -0,0 +1,141 @@ +/* types.h - some common typedefs + * 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_TYPES_H +#define G10_TYPES_H + +#ifdef HAVE_INTTYPES_H +/* For uint64_t */ +#include <inttypes.h> +#endif + +/* The AC_CHECK_SIZEOF() in configure fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT +#undef SIZEOF_UNSIGNED_SHORT +#define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT +#undef SIZEOF_UNSIGNED_INT +#define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG +#undef SIZEOF_UNSIGNED_LONG +#define SIZEOF_UNSIGNED_LONG 4 +#endif + + +#include <sys/types.h> + + +#ifndef HAVE_BYTE_TYPEDEF +#undef byte /* maybe there is a macro with this name */ +#ifndef __riscos__ +typedef unsigned char byte; +#else +/* Norcroft treats char = unsigned char as legal assignment + but char* = unsigned char* as illegal assignment + and the same applies to the signed variants as well */ +typedef char byte; +#endif +#define HAVE_BYTE_TYPEDEF +#endif + +#ifndef HAVE_USHORT_TYPEDEF +#undef ushort /* maybe there is a macro with this name */ +typedef unsigned short ushort; +#define HAVE_USHORT_TYPEDEF +#endif + +#ifndef HAVE_ULONG_TYPEDEF +#undef ulong /* maybe there is a macro with this name */ +typedef unsigned long ulong; +#define HAVE_ULONG_TYPEDEF +#endif + +#ifndef HAVE_U16_TYPEDEF +#undef u16 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 2 +typedef unsigned int u16; +#elif SIZEOF_UNSIGNED_SHORT == 2 +typedef unsigned short u16; +#else +#error no typedef for u16 +#endif +#define HAVE_U16_TYPEDEF +#endif + +#ifndef HAVE_U32_TYPEDEF +#undef u32 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 4 +typedef unsigned int u32; +#elif SIZEOF_UNSIGNED_LONG == 4 +typedef unsigned long u32; +#else +#error no typedef for u32 +#endif +#define HAVE_U32_TYPEDEF +#endif + +/**************** + * Warning: Some systems segfault when this u64 typedef and + * the dummy code in cipher/md.c is not available. Examples are + * Solaris and IRIX. + */ +#ifndef HAVE_U64_TYPEDEF +#undef u64 /* maybe there is a macro with this name */ +#if SIZEOF_UNSIGNED_INT == 8 +typedef unsigned int u64; +#define U64_C(c) (c ## U) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG == 8 +typedef unsigned long u64; +#define U64_C(c) (c ## UL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long u64; +#define U64_C(c) (c ## ULL) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UINT64_T == 8 +typedef uint64_t u64; +#define U64_C(c) (UINT64_C(c)) +#define HAVE_U64_TYPEDEF +#endif +#endif + +typedef union { + int a; + short b; + char c[1]; + long d; +#ifdef HAVE_U64_TYPEDEF + u64 e; +#endif + float f; + double g; +} PROPERLY_ALIGNED_TYPE; + +typedef struct string_list { + struct string_list *next; + unsigned int flags; + char d[1]; +} *STRLIST; + +#endif /*G10_TYPES_H*/ diff --git a/include/util.h b/include/util.h new file mode 100644 index 000000000..c3d0189c6 --- /dev/null +++ b/include/util.h @@ -0,0 +1,304 @@ +/* util.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_UTIL_H +#define G10_UTIL_H + +#if defined (__MINGW32__) || defined (__CYGWIN32__) +#include <stdarg.h> +#endif + +#include "types.h" +#include "errors.h" +#include "types.h" +#include "mpi.h" + + +typedef struct { + int *argc; /* pointer to argc (value subject to change) */ + char ***argv; /* pointer to argv (value subject to change) */ + unsigned flags; /* Global flags (DO NOT CHANGE) */ + int err; /* print error about last option */ + /* 1 = warning, 2 = abort */ + int r_opt; /* return option */ + int r_type; /* type of return value (0 = no argument found)*/ + union { + int ret_int; + long ret_long; + ulong ret_ulong; + char *ret_str; + } r; /* Return values */ + struct { + int idx; + int inarg; + int stopped; + const char *last; + void *aliases; + const void *cur_alias; + } internal; /* DO NOT CHANGE */ +} ARGPARSE_ARGS; + +typedef struct { + int short_opt; + const char *long_opt; + unsigned flags; + const char *description; /* optional option description */ +} ARGPARSE_OPTS; + +/*-- logger.c --*/ +void log_set_logfile( const char *name, int fd ); +FILE *log_stream(void); +void g10_log_print_prefix(const char *text); +void log_set_name( const char *name ); +const char *log_get_name(void); +void log_set_pid( int pid ); +int log_get_errorcount( int clear ); +void log_inc_errorcount(void); +int log_set_strict(int val); +void g10_log_hexdump( const char *text, const char *buf, size_t len ); + +#if defined (__riscos__) \ + || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) + void g10_log_bug( const char *fmt, ... ) + __attribute__ ((noreturn, format (printf,1,2))); + void g10_log_bug0( const char *, int, const char * ) __attribute__ ((noreturn)); + void g10_log_fatal( const char *fmt, ... ) + __attribute__ ((noreturn, format (printf,1,2))); + void g10_log_error( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); + void g10_log_info( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); + void g10_log_warning( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); + void g10_log_debug( const char *fmt, ... ) __attribute__ ((format (printf,1,2))); + void g10_log_fatal_f( const char *fname, const char *fmt, ... ) + __attribute__ ((noreturn, format (printf,2,3))); + void g10_log_error_f( const char *fname, const char *fmt, ... ) + __attribute__ ((format (printf,2,3))); + void g10_log_info_f( const char *fname, const char *fmt, ... ) + __attribute__ ((format (printf,2,3))); + void g10_log_debug_f( const char *fname, const char *fmt, ... ) + __attribute__ ((format (printf,2,3))); +#ifndef __riscos__ +#define BUG() g10_log_bug0( __FILE__ , __LINE__, __FUNCTION__ ) +#else +#define BUG() g10_log_bug0( __FILE__ , __LINE__, __func__ ) +#endif +#else + void g10_log_bug( const char *fmt, ... ); + void g10_log_bug0( const char *, int ); + void g10_log_fatal( const char *fmt, ... ); + void g10_log_error( const char *fmt, ... ); + void g10_log_info( const char *fmt, ... ); + void g10_log_warning( const char *fmt, ... ); + void g10_log_debug( const char *fmt, ... ); + void g10_log_fatal_f( const char *fname, const char *fmt, ... ); + void g10_log_error_f( const char *fname, const char *fmt, ... ); + void g10_log_info_f( const char *fname, const char *fmt, ... ); + void g10_log_debug_f( const char *fname, const char *fmt, ... ); +#define BUG() g10_log_bug0( __FILE__ , __LINE__ ) +#endif + +#define log_hexdump g10_log_hexdump +#define log_bug g10_log_bug +#define log_bug0 g10_log_bug0 +#define log_fatal g10_log_fatal +#define log_error g10_log_error +#define log_info g10_log_info +#define log_warning g10_log_warning +#define log_debug g10_log_debug +#define log_fatal_f g10_log_fatal_f +#define log_error_f g10_log_error_f +#define log_info_f g10_log_info_f +#define log_debug_f g10_log_debug_f + + +/*-- errors.c --*/ +const char * g10_errstr( int no ); + +/*-- argparse.c --*/ +int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, + ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); +void usage( int level ); +const char *default_strusage( int level ); + + +/*-- (main program) --*/ +const char *strusage( int level ); + + +/*-- dotlock.c --*/ +struct dotlock_handle; +typedef struct dotlock_handle *DOTLOCK; + +void disable_dotlock(void); +DOTLOCK create_dotlock( const char *file_to_lock ); +int make_dotlock( DOTLOCK h, long timeout ); +int release_dotlock( DOTLOCK h ); +void remove_lockfiles (void); + +/*-- fileutil.c --*/ +char * make_basename(const char *filepath, const char *inputpath); +char * make_dirname(const char *filepath); +char *make_filename( const char *first_part, ... ); +int compare_filenames( const char *a, const char *b ); +const char *print_fname_stdin( const char *s ); +const char *print_fname_stdout( const char *s ); +int is_file_compressed(const char *s, int *r_status); + + +/*-- miscutil.c --*/ +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 */ +void print_string( FILE *fp, const byte *p, size_t n, int delim ); +void print_utf8_string( FILE *fp, const byte *p, size_t n ); +void print_utf8_string2( FILE *fp, const byte *p, size_t n, int delim); +char *make_printable_string( const byte *p, size_t n, int delim ); +int answer_is_yes_no_default( const char *s, int def_answer ); +int answer_is_yes( const char *s ); +int answer_is_yes_no_quit( const char *s ); + +/*-- strgutil.c --*/ +void free_strlist( STRLIST sl ); +#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) +STRLIST add_to_strlist( STRLIST *list, const char *string ); +STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST append_to_strlist( STRLIST *list, const char *string ); +STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +STRLIST strlist_prev( STRLIST head, STRLIST node ); +STRLIST strlist_last( STRLIST node ); +char *pop_strlist( STRLIST *list ); +const char *memistr( const char *buf, size_t buflen, const char *sub ); +const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); +char *mem2str( char *, const void *, size_t); +char *trim_spaces( char *string ); +unsigned int trim_trailing_chars( byte *line, unsigned int len, + const char *trimchars); +unsigned int trim_trailing_ws( byte *line, unsigned len ); +unsigned int check_trailing_chars( const byte *line, unsigned int len, + const char *trimchars ); +unsigned int check_trailing_ws( const byte *line, unsigned int len ); +int string_count_chr( const char *string, int c ); +int set_native_charset( const char *newset ); +const char* get_native_charset(void); +char *native_to_utf8( const char *string ); +char *utf8_to_native( const char *string, size_t length, int delim); +int check_utf8_string( const char *string ); + +int ascii_isupper (int c); +int ascii_islower (int c); +int ascii_toupper (int c); +int ascii_tolower (int c); +int ascii_strcasecmp( const char *a, const char *b ); +int ascii_strncasecmp( const char *a, const char *b, size_t n); +int ascii_memcasecmp( const char *a, const char *b, size_t n); + +#ifndef HAVE_STPCPY +char *stpcpy(char *a,const char *b); +#endif +#ifndef HAVE_STRLWR +char *strlwr(char *a); +#endif +#ifndef HAVE_STRSEP +char *strsep (char **stringp, const char *delim); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp( const char *, const char *b); +#endif +#ifndef HAVE_STRNCASECMP +int strncasecmp (const char *, const char *b, size_t n); +#endif +#ifndef HAVE_STRTOUL +#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif +#ifndef HAVE_MEMMOVE +#define memmove(d, s, n) bcopy((s), (d), (n)) +#endif + +#if defined (__MINGW32__) +/*-- w32reg.c --*/ +char *read_w32_registry_string( const char *root, + const char *dir, const char *name ); +int write_w32_registry_string(const char *root, const char *dir, + const char *name, const char *value); + +/*-- strgutil.c --*/ +int vasprintf ( char **result, const char *format, va_list args); +#endif + +/**** other missing stuff ****/ +#ifndef HAVE_ATEXIT /* For SunOS */ +#define atexit(a) (on_exit((a),0)) +#endif + +#ifndef HAVE_RAISE +#define raise(a) kill(getpid(), (a)) +#endif + +/******** some macros ************/ +#ifndef STR +#define STR(v) #v +#endif +#define STR2(v) STR(v) +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) + +#define wipememory2(_ptr,_set,_len) do { volatile char *_vptr=(volatile char *)(_ptr); size_t _vlen=(_len); while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + +/******* RISC OS stuff ***********/ +#ifdef __riscos__ +/* needed for strcasecmp() */ +#include <strings.h> +/* needed for filename munging */ +#include <unixlib/local.h> +/* needed for image file system feature */ +#include <unixlib/features.h> +void riscos_global_defaults(void); +#define RISCOS_GLOBAL_STATICS(a) const char *__dynamic_da_name = (a); +int riscos_load_module(const char *name, const char * const path[], int fatal); +int riscos_get_filetype_from_string(const char *string, int len); +int riscos_get_filetype(const char *filename); +void riscos_set_filetype_by_number(const char *filename, int type); +void riscos_set_filetype_by_mimetype(const char *filename, const char *mimetype); +pid_t riscos_getpid(void); +int riscos_kill(pid_t pid, int sig); +int riscos_access(const char *path, int amode); +int riscos_getchar(void); +char *riscos_make_basename(const char *filepath, const char *inputpath); +int riscos_check_regexp(const char *exp, const char *string, int debug); +int riscos_fdopenfile(const char *filename, const int allow_write); +void riscos_close_fds(void); +int riscos_renamefile(const char *old, const char *new); +char *riscos_gstrans(const char *old); +void riscos_not_implemented(const char *feature); +#ifdef DEBUG +void riscos_dump_fdlist(void); +void riscos_list_openfiles(void); +#endif +#ifndef __RISCOS__C__ +#define getpid riscos_getpid +#define kill(a,b) riscos_kill((a),(b)) +#define access(a,b) riscos_access((a),(b)) +#endif /* !__RISCOS__C__ */ +#endif /* __riscos__ */ + +#endif /*G10_UTIL_H*/ diff --git a/kbx/ChangeLog b/kbx/ChangeLog new file mode 100644 index 000000000..af6e6b016 --- /dev/null +++ b/kbx/ChangeLog @@ -0,0 +1,119 @@ +2003-06-03 Werner Koch <wk@gnupg.org> + + Changed all error codes in all files to the new libgpg-error scheme. + + * keybox-defs.h: Include gpg-error.h . + (KeyboxError): Removed. + * Makefile.am: Removed keybox-error.c stuff. + +2002-11-14 Werner Koch <wk@gnupg.org> + + * keybox-search.c (blob_cmp_name) <compare all names>: Fixed + length compare; there is no 0 stored since nearly a year. + +2002-10-31 Neal H. Walfield <neal@g10code.de> + + * Makefile.am (AM_CPPFLAGS): Fix ytpo. + +2002-08-10 Werner Koch <wk@gnupg.org> + + * keybox-search.c (blob_cmp_fpr_part): New. + (has_short_kid, has_long_kid): Implemented. + +2002-07-22 Werner Koch <wk@gnupg.org> + + * keybox-defs.h: New BLOBTYPTE_EMPTY. + * keybox-dump.c (_keybox_dump_blob): Handle new type. + * keybox-file.c (_keybox_read_blob): Skip over empty blobs. Store + the file offset. + * keybox-blob.c (_keybox_new_blob): Add new arg OFF. + (_keybox_get_blob_fileoffset): New. + * keybox-update.c (keybox_delete): Implemented. + +2002-06-19 Werner Koch <wk@gnupg.org> + + * keybox-init.c (keybox_set_ephemeral): New. + * keybox-blob.c (create_blob_header): Store ephemeral flag. + (_keybox_create_x509_blob): Pass epheermal flag on. + * keybox-update.c (keybox_insert_cert): Ditto. + * keybox-search.c (blob_get_blob_flags): New. + (keybox_search): Ignore ephemeral blobs when not in ephemeral mode. + + * keybox-dump.c (_keybox_dump_blob): Print blob flags as strings. + +2002-02-25 Werner Koch <wk@gnupg.org> + + * keybox-search.c (blob_cmp_mail): Use case-insensitive compare + because mail addresses are in general case insensitive (well + RFC2822 allows for case sensitive mailbox parts, but this is in + general considired a Bad Thing). Add additional substr parameter + to allow for substring matches within the mail address. Change + all callers to pass this along. + (blob_cmp_name): Likewise but do the case-insensitive search only + in sub string mode. + (keybox_search): Implement MAILSUB and SUBSTR mode. + +2002-01-21 Werner Koch <wk@gnupg.org> + + * keybox-search.c (keybox_search): Allow KEYDB_SEARCH_MODE_FPR20. + +2002-01-15 Werner Koch <wk@gnupg.org> + + * keybox-search.c (blob_cmp_fpr): New. + (has_fingerprint): Implemented; + +2001-12-20 Werner Koch <wk@gnupg.org> + + * keybox-blob.c (_keybox_create_x509_blob): Skip the leading + parenthesis of the serial number's S-exp. + (_keybox_create_x509_blob): And fixed length calculation. + (create_blob_header): Don't add an offset when writing the serial. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * Makefile.am (AM_CPPFLAGS): Add flags for libksba + + * keybox-blob.c (_keybox_create_x509_blob): Use + gcry_sexp_canon_len to get the length of the serial number. + (_keybox_release_blob): Need to use a new serialbuf to free the memory. + +2001-12-17 Werner Koch <wk@gnupg.org> + + * keybox-search.c: Changed the way the serial number is + represented. + +2001-12-15 Werner Koch <wk@gnupg.org> + + * keybox-search.c (blob_cmp_name): There is no terminating 0 stored + for the uid; fixed length compare. + +2001-12-14 Werner Koch <wk@gnupg.org> + + * keybox-blob.c (x509_email_kludge): New. + (_keybox_create_x509_blob): Insert an extra email address if the + subject's DN has an email part. + * keybox-defs.h: Added the xtoi_2 and digitp macros. + +2001-12-13 Werner Koch <wk@gnupg.org> + + * keybox-search.c (blob_cmp_name): Kludge to allow searching for + more than one name. + (has_subject_or_alt): New. + (blob_cmp_mail): New. + (has_mail): New. + (keybox_search): Implemented exact search and exact mail search. + + * kbx/keybox-blob.c (_keybox_create_x509_blob): Insert alternate + names. + + + Copyright 2001 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 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. + \ No newline at end of file diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h new file mode 100644 index 000000000..e4578d76b --- /dev/null +++ b/kbx/keybox-defs.h @@ -0,0 +1,186 @@ +/* keybox-defs.h - interal Keybox defintions + * 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 KEYBOX_DEFS_H +#define KEYBOX_DEFS_H 1 + +#include <sys/types.h> /* off_t */ +#include "keybox.h" + +#ifdef GPG_ERR_SOURCE_DEFAULT +#error GPG_ERR_SOURCE_DEFAULT already defined +#endif +#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_KEYBOX +#include <gpg-error.h> + + +#ifndef HAVE_BYTE_TYPEDEF +typedef unsigned char byte; /* fixme */ +#endif +#ifndef HAVE_U16_TYPEDEF +typedef unsigned short u16; /* fixme */ +#endif +#ifndef HAVE_U32_TYPEDEF +typedef unsigned int u32; /* fixme */ +#endif + +enum { + BLOBTYPE_EMPTY = 0, + BLOBTYPE_HEADER = 1, + BLOBTYPE_PGP = 2, + BLOBTYPE_X509 = 3 +}; + + +typedef struct keyboxblob *KEYBOXBLOB; + + +typedef struct keybox_name *KB_NAME; +typedef struct keybox_name const * CONST_KB_NAME; +struct keybox_name { + struct keybox_name *next; + int secret; + /*DOTLOCK lockhd;*/ + int is_locked; + int did_full_scan; + char fname[1]; +}; + + + +struct keybox_handle { + CONST_KB_NAME kb; + int secret; /* this is for a secret keybox */ + FILE *fp; + int eof; + int error; + int ephemeral; + struct { + KEYBOXBLOB blob; + off_t offset; + size_t pk_no; + size_t uid_no; + unsigned int n_packets; /*used for delete and update*/ + } found; + struct { + char *name; + char *pattern; + } word_match; +}; + + +/* Don't know whether this is needed: */ +/* static struct { */ +/* const char *homedir; */ +/* int dry_run; */ +/* int quiet; */ +/* int verbose; */ +/* int preserve_permissions; */ +/* } keybox_opt; */ + + +/*-- keybox-blob.c --*/ +#ifdef KEYBOX_WITH_OPENPGP + /* fixme */ +#endif /*KEYBOX_WITH_OPENPGP*/ +#ifdef KEYBOX_WITH_X509 +int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert, + unsigned char *sha1_digest, int as_ephemeral); +#endif /*KEYBOX_WITH_X509*/ + +int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, + off_t off); +void _keybox_release_blob (KEYBOXBLOB blob); +const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); +off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); + +/*-- keybox-file.c --*/ +int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); +int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp); + +/*-- keybox-dump.c --*/ +int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); +int _keybox_dump_file (const char *filename, FILE *outfp); + + +/*-- keybox-util.c --*/ +void *_keybox_malloc (size_t n); +void *_keybox_calloc (size_t n, size_t m); +void *_keybox_realloc (void *p, size_t n); +void _keybox_free (void *p); + +#define xtrymalloc(a) _keybox_malloc ((a)) +#define xtrycalloc(a,b) _keybox_calloc ((a),(b)) +#define xtryrealloc(a,b) _keybox_realloc((a),(b)) +#define xfree(a) _keybox_free ((a)) + + +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) +#ifndef STR + #define STR(v) #v +#endif +#define STR2(v) STR(v) + +/* + a couple of handy macros +*/ + +#define return_if_fail(expr) do { \ + if (!(expr)) { \ + fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ + __FILE__, __LINE__, #expr ); \ + return; \ + } } while (0) +#define return_null_if_fail(expr) do { \ + if (!(expr)) { \ + fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ + __FILE__, __LINE__, #expr ); \ + return NULL; \ + } } while (0) +#define return_val_if_fail(expr,val) do { \ + if (!(expr)) { \ + fprintf (stderr, "%s:%d: assertion `%s' failed\n", \ + __FILE__, __LINE__, #expr ); \ + return (val); \ + } } while (0) +#define never_reached() do { \ + fprintf (stderr, "%s:%d: oops; should never get here\n", \ + __FILE__, __LINE__ ); \ + } while (0) + + +/* some macros to replace ctype ones and avoid locale problems */ +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +/* 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)) + + +#endif /*KEYBOX_DEFS_H*/ + + diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c new file mode 100644 index 000000000..2177bedae --- /dev/null +++ b/kbx/keybox-dump.c @@ -0,0 +1,346 @@ +/* keybox-dump.c - Debug helpers + * 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 <stdio.h> +#include <string.h> +#include <errno.h> + +#include "keybox-defs.h" + +static ulong +get32 (const byte *buffer) +{ + ulong a; + a = *buffer << 24; + a |= buffer[1] << 16; + a |= buffer[2] << 8; + a |= buffer[3]; + return a; +} + +static ulong +get16 (const byte *buffer) +{ + ulong a; + a = *buffer << 8; + a |= buffer[1]; + return a; +} + +void +print_string (FILE *fp, const byte *p, size_t n, int delim) +{ + for ( ; n; n--, p++ ) + { + if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim) + { + putc('\\', fp); + if( *p == '\n' ) + putc('n', fp); + else if( *p == '\r' ) + putc('r', fp); + else if( *p == '\f' ) + putc('f', fp); + else if( *p == '\v' ) + putc('v', fp); + else if( *p == '\b' ) + putc('b', fp); + else if( !*p ) + putc('0', fp); + else + fprintf(fp, "x%02x", *p ); + } + else + putc(*p, fp); + } +} + + +static int +dump_header_blob (const byte *buffer, size_t length, FILE *fp) +{ + fprintf (fp, "Version: %d\n", buffer[5]); + if ( memcmp (buffer+8, "KBXf", 4)) + fprintf (fp, "[Error: invalid magic number]\n"); + return 0; +} + + +/* Dump one block to FP */ +int +_keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) +{ + const byte *buffer; + size_t length; + int type; + ulong n, nkeys, keyinfolen; + ulong nuids, uidinfolen; + ulong nsigs, siginfolen; + ulong rawdata_off, rawdata_len; + ulong nserial; + const byte *p; + + buffer = _keybox_get_blob_image (blob, &length); + + if (length < 40) + { + fprintf (fp, "[blob too short]\n"); + return -1; + } + + n = get32( buffer ); + if (n > length) + fprintf (fp, "[blob larger than length - output truncated]\n"); + else + length = n; /* ignore the rest */ + + fprintf (fp, "Length: %lu\n", n ); + type = buffer[4]; + switch (type) + { + case BLOBTYPE_EMPTY: + fprintf (fp, "Type: Empty\n"); + return 0; + + case BLOBTYPE_HEADER: + fprintf (fp, "Type: Header\n"); + return dump_header_blob (buffer, length, fp); + case BLOBTYPE_PGP: + fprintf (fp, "Type: OpenPGP\n"); + break; + case BLOBTYPE_X509: + fprintf (fp, "Type: X.509\n"); + break; + default: + fprintf (fp, "Type: %d\n", type); + fprintf (fp, "[can't dump this blob type]\n"); + return 0; + } + fprintf (fp, "Version: %d\n", buffer[5]); + + n = get16 (buffer + 6); + fprintf( fp, "Blob-Flags: %04lX", n); + if (n) + { + int any = 0; + + fputs (" (", fp); + if ((n & 1)) + { + fputs ("secret", fp); + any++; + } + if ((n & 2)) + { + if (any) + putc (',', fp); + fputs ("ephemeral", fp); + any++; + } + putc (')', fp); + } + putc ('\n', fp); + + rawdata_off = get32 (buffer + 8); + rawdata_len = get32 (buffer + 12); + + fprintf( fp, "Data-Offset: %lu\n", rawdata_off ); + fprintf( fp, "Data-Length: %lu\n", rawdata_len ); + + nkeys = get16 (buffer + 16); + fprintf (fp, "Key-Count: %lu\n", nkeys ); + if (!nkeys) + fprintf (fp, "[Error: no keys]\n"); + if (nkeys > 1 && type == BLOBTYPE_X509) + fprintf (fp, "[Error: only one key allowed for X509]\n"); + + keyinfolen = get16 (buffer + 18 ); + fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen); + /* fixme: check bounds */ + p = buffer + 20; + for (n=0; n < nkeys; n++, p += keyinfolen) + { + int i; + ulong kidoff, kflags; + + fprintf (fp, "Key-Fpr[%lu]: ", n ); + for (i=0; i < 20; i++ ) + fprintf (fp, "%02X", p[i]); + kidoff = get32 (p + 20); + fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff ); + fprintf (fp, "Key-Kid[%lu]: ", n ); + /* fixme: check bounds */ + for (i=0; i < 8; i++ ) + fprintf (fp, "%02X", buffer[kidoff+i] ); + kflags = get16 (p + 24 ); + fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags); + } + + /* serial number */ + fputs ("Serial-No: ", fp); + nserial = get16 (p); + p += 2; + if (!nserial) + fputs ("none", fp); + else + { + for (; nserial; nserial--, p++) + fprintf (fp, "%02X", *p); + } + putc ('\n', fp); + + /* user IDs */ + nuids = get16 (p); + fprintf (fp, "Uid-Count: %lu\n", nuids ); + uidinfolen = get16 (p + 2); + fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen); + /* fixme: check bounds */ + p += 4; + for (n=0; n < nuids; n++, p += uidinfolen) + { + ulong uidoff, uidlen, uflags; + + uidoff = get32( p ); + uidlen = get32( p+4 ); + if (type == BLOBTYPE_X509 && !n) + { + fprintf (fp, "Issuer-Off: %lu\n", uidoff ); + fprintf (fp, "Issuer-Len: %lu\n", uidlen ); + fprintf (fp, "Issuer: \""); + } + else if (type == BLOBTYPE_X509 && n == 1) + { + fprintf (fp, "Subject-Off: %lu\n", uidoff ); + fprintf (fp, "Subject-Len: %lu\n", uidlen ); + fprintf (fp, "Subject: \""); + } + else + { + fprintf (fp, "Uid-Off[%lu]: %lu\n", n, uidoff ); + fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen ); + fprintf (fp, "Uid[%lu]: \"", n ); + } + print_string (fp, buffer+uidoff, uidlen, '\"'); + fputs ("\"\n", fp); + uflags = get16 (p + 8); + if (type == BLOBTYPE_X509 && !n) + { + fprintf (fp, "Issuer-Flags: %04lX\n", uflags ); + fprintf (fp, "Issuer-Validity: %d\n", p[10] ); + } + else if (type == BLOBTYPE_X509 && n == 1) + { + fprintf (fp, "Subject-Flags: %04lX\n", uflags ); + fprintf (fp, "Subject-Validity: %d\n", p[10] ); + } + else + { + fprintf (fp, "Uid-Flags[%lu]: %04lX\n", n, uflags ); + fprintf (fp, "Uid-Validity[%lu]: %d\n", n, p[10] ); + } + } + + nsigs = get16 (p); + fprintf (fp, "Sig-Count: %lu\n", nsigs ); + siginfolen = get16 (p + 2); + fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen ); + /* fixme: check bounds */ + p += 4; + for (n=0; n < nsigs; n++, p += siginfolen) + { + ulong sflags; + + sflags = get32 (p); + fprintf (fp, "Sig-Expire[%lu]: ", n ); + if (!sflags) + fputs ("[not checked]", fp); + else if (sflags == 1 ) + fputs ("[missing key]", fp); + else if (sflags == 2 ) + fputs ("[bad signature]", fp); + else if (sflags < 0x10000000) + fprintf (fp, "[bad flag %0lx]", sflags); + else if (sflags == 0xffffffff) + fputs ("0", fp ); + else + fputs ("a time"/*strtimestamp( sflags )*/, fp ); + putc ('\n', fp ); + } + + fprintf (fp, "Ownertrust: %d\n", p[0] ); + fprintf (fp, "All-Validity: %d\n", p[1] ); + p += 4; + n = get32 (p); p += 4; + fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" ); + n = get32 (p ); p += 4; + fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ ); + n = get32 (p ); p += 4; + fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ ); + n = get32 (p ); p += 4; + fprintf (fp, "Reserved-Space: %lu\n", n ); + + /* check that the keyblock is at the correct offset and other bounds */ + /*fprintf (fp, "Blob-Checksum: [MD5-hash]\n");*/ + return 0; +} + + + +int +_keybox_dump_file (const char *filename, FILE *outfp) +{ + FILE *fp; + KEYBOXBLOB blob; + int rc; + unsigned long count = 0; + + if (!filename) + { + filename = "-"; + fp = stdin; + } + else + fp = fopen (filename, "rb"); + if (!fp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + fprintf (outfp, "can't open `%s': %s\n", filename, strerror(errno)); + return tmperr; + } + + while ( !(rc = _keybox_read_blob (&blob, fp)) ) + { + fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); + _keybox_dump_blob (blob, outfp); + _keybox_release_blob (blob); + fprintf (outfp, "END-RECORD\n"); + count++; + } + if (rc == -1) + rc = 0; + if (rc) + fprintf (outfp, "error reading `%s': %s\n", filename, gpg_strerror (rc)); + + if (fp != stdin) + fclose (fp); + return rc; +} diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c new file mode 100644 index 000000000..fc9321478 --- /dev/null +++ b/kbx/keybox-file.c @@ -0,0 +1,102 @@ +/* keybox-file.c - file oeprations + * 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 <stdio.h> +#include <string.h> +#include <errno.h> + +#include "keybox-defs.h" + +/* Read a block at the current postion and return it in r_blob. + r_blob may be NULL to simply skip the current block */ +int +_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) +{ + char *image; + size_t imagelen = 0; + int c1, c2, c3, c4, type; + int rc; + off_t off; + + again: + *r_blob = NULL; + off = ftello (fp); + if (off == (off_t)-1) + return gpg_error (gpg_err_code_from_errno (errno)); + + if ((c1 = getc (fp)) == EOF + || (c2 = getc (fp)) == EOF + || (c3 = getc (fp)) == EOF + || (c4 = getc (fp)) == EOF + || (type = getc (fp)) == EOF) + { + if ( c1 == EOF && !ferror (fp) ) + return -1; /* eof */ + return gpg_error (gpg_err_code_from_errno (errno)); + } + + imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; + if (imagelen > 500000) /* sanity check */ + return gpg_error (GPG_ERR_TOO_LARGE); + + if (imagelen < 5) + return gpg_error (GPG_ERR_TOO_SHORT); + + if (!type) + { + /* special treatment for empty blobs. */ + if (fseek (fp, imagelen-5, SEEK_CUR)) + return gpg_error (gpg_err_code_from_errno (errno)); + goto again; + } + + image = xtrymalloc (imagelen); + if (!image) + return gpg_error (gpg_err_code_from_errno (errno)); + + image[0] = c1; image[1] = c2; image[2] = c3; image[3] = c4; image[4] = type; + if (fread (image+5, imagelen-5, 1, fp) != 1) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + xfree (image); + return tmperr; + } + + rc = r_blob? _keybox_new_blob (r_blob, image, imagelen, off) : 0; + if (rc || !r_blob) + xfree (image); + return rc; +} + + +/* Write the block to the current file position */ +int +_keybox_write_blob (KEYBOXBLOB blob, FILE *fp) +{ + const char *image; + size_t length; + + image = _keybox_get_blob_image (blob, &length); + if (fwrite (image, length, 1, fp) != 1) + return gpg_error (gpg_err_code_from_errno (errno)); + return 0; +} diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c new file mode 100644 index 000000000..e11c4f09c --- /dev/null +++ b/kbx/keybox-init.c @@ -0,0 +1,127 @@ +/* keybox-init.c - Initalization of the library + * 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 + */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> + +#include "keybox-defs.h" + +#define compare_filenames strcmp + +static KB_NAME kb_names; + + +/* + Register a filename for plain keybox files. Returns a pointer to be + used to create a handles etc or NULL to indicate that it has already + been registered */ +void * +keybox_register_file (const char *fname, int secret) +{ + KB_NAME kr; + + for (kr=kb_names; kr; kr = kr->next) + { + if ( !compare_filenames (kr->fname, fname) ) + return NULL; /* already registered */ + } + + kr = xtrymalloc (sizeof *kr + strlen (fname)); + if (!kr) + return NULL; + strcpy (kr->fname, fname); + kr->secret = !!secret; + /* kr->lockhd = NULL;*/ + kr->is_locked = 0; + kr->did_full_scan = 0; + /* keep a list of all issued pointers */ + kr->next = kb_names; + kb_names = kr; + + /* create the offset table the first time a function here is used */ +/* if (!kb_offtbl) */ +/* kb_offtbl = new_offset_hash_table (); */ + + return kr; +} + +int +keybox_is_writable (void *token) +{ + KB_NAME r = token; + + return r? !access (r->fname, W_OK) : 0; +} + + + +/* Create a new handle for the resource associated with TOKEN. SECRET + is just a cross-check. + + The returned handle must be released using keybox_release (). */ +KEYBOX_HANDLE +keybox_new (void *token, int secret) +{ + KEYBOX_HANDLE hd; + KB_NAME resource = token; + + assert (resource && !resource->secret == !secret); + hd = xtrycalloc (1, sizeof *hd); + if (hd) + { + hd->kb = resource; + hd->secret = !!secret; + } + return hd; +} + +void +keybox_release (KEYBOX_HANDLE hd) +{ + if (!hd) + return; + _keybox_release_blob (hd->found.blob); + xfree (hd->word_match.name); + xfree (hd->word_match.pattern); + xfree (hd); +} + + +const char * +keybox_get_resource_name (KEYBOX_HANDLE hd) +{ + if (!hd || !hd->kb) + return NULL; + return hd->kb->fname; +} + +int +keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes) +{ + if (!hd) + return gpg_error (GPG_ERR_INV_HANDLE); + hd->ephemeral = yes; + return 0; +} + diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c new file mode 100644 index 000000000..231a32d42 --- /dev/null +++ b/kbx/keybox-search.c @@ -0,0 +1,813 @@ +/* keybox-search.c - Search operations + * 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 <stdio.h> +#include <string.h> +#include <assert.h> +#include <errno.h> + +#include "../jnlib/stringhelp.h" /* ascii_xxxx() */ +#include "keybox-defs.h" + +#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)) + +struct sn_array_s { + int snlen; + unsigned char *sn; +}; + + + +static ulong +get32 (const byte *buffer) +{ + ulong a; + a = *buffer << 24; + a |= buffer[1] << 16; + a |= buffer[2] << 8; + a |= buffer[3]; + return a; +} + +static ulong +get16 (const byte *buffer) +{ + ulong a; + a = *buffer << 8; + a |= buffer[1]; + return a; +} + + + +static int +blob_get_type (KEYBOXBLOB blob) +{ + const unsigned char *buffer; + size_t length; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 40) + return -1; /* blob too short */ + + return buffer[4]; +} + +static unsigned int +blob_get_blob_flags (KEYBOXBLOB blob) +{ + const unsigned char *buffer; + size_t length; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 8) + return 0; /* oops */ + + return get16 (buffer + 6); +} + + +static int +blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) +{ + const unsigned char *buffer; + size_t length; + size_t pos, off; + size_t nkeys, keyinfolen; + size_t nserial; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 40) + return 0; /* blob too short */ + + /*keys*/ + nkeys = get16 (buffer + 16); + keyinfolen = get16 (buffer + 18 ); + if (keyinfolen < 28) + return 0; /* invalid blob */ + pos = 20 + keyinfolen*nkeys; + if (pos+2 > length) + return 0; /* out of bounds */ + + /*serial*/ + nserial = get16 (buffer+pos); + off = pos + 2; + if (off+nserial > length) + return 0; /* out of bounds */ + + return nserial == snlen && !memcmp (buffer+off, sn, snlen); +} + + +static int +blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr) +{ + const unsigned char *buffer; + size_t length; + size_t pos, off; + size_t nkeys, keyinfolen; + int idx; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 40) + return 0; /* blob too short */ + + /*keys*/ + nkeys = get16 (buffer + 16); + keyinfolen = get16 (buffer + 18 ); + if (keyinfolen < 28) + return 0; /* invalid blob */ + pos = 20; + if (pos + keyinfolen*nkeys > length) + return 0; /* out of bounds */ + + for (idx=0; idx < nkeys; idx++) + { + off = pos + idx*keyinfolen; + if (!memcmp (buffer + off, fpr, 20)) + return 1; /* found */ + } + return 0; /* not found */ +} + +static int +blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr, + int fproff, int fprlen) +{ + const unsigned char *buffer; + size_t length; + size_t pos, off; + size_t nkeys, keyinfolen; + int idx; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 40) + return 0; /* blob too short */ + + /*keys*/ + nkeys = get16 (buffer + 16); + keyinfolen = get16 (buffer + 18 ); + if (keyinfolen < 28) + return 0; /* invalid blob */ + pos = 20; + if (pos + keyinfolen*nkeys > length) + return 0; /* out of bounds */ + + for (idx=0; idx < nkeys; idx++) + { + off = pos + idx*keyinfolen; + if (!memcmp (buffer + off + fproff, fpr, fprlen)) + return 1; /* found */ + } + return 0; /* not found */ +} + + +static int +blob_cmp_name (KEYBOXBLOB blob, int idx, + const char *name, size_t namelen, int substr) +{ + const unsigned char *buffer; + size_t length; + size_t pos, off, len; + size_t nkeys, keyinfolen; + size_t nuids, uidinfolen; + size_t nserial; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 40) + return 0; /* blob too short */ + + /*keys*/ + nkeys = get16 (buffer + 16); + keyinfolen = get16 (buffer + 18 ); + if (keyinfolen < 28) + return 0; /* invalid blob */ + pos = 20 + keyinfolen*nkeys; + if (pos+2 > length) + return 0; /* out of bounds */ + + /*serial*/ + nserial = get16 (buffer+pos); + pos += 2 + nserial; + if (pos+4 > length) + return 0; /* out of bounds */ + + /* user ids*/ + nuids = get16 (buffer + pos); pos += 2; + uidinfolen = get16 (buffer + pos); pos += 2; + if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */) + return 0; /* invalid blob */ + if (pos + uidinfolen*nuids > length) + return 0; /* out of bounds */ + + if (idx < 0) + { /* compare all names starting with that (negated) index */ + idx = -idx; + + for ( ;idx < nuids; idx++) + { + size_t mypos = pos; + + mypos += idx*uidinfolen; + off = get32 (buffer+mypos); + len = get32 (buffer+mypos+4); + if (off+len > length) + return 0; /* error: better stop here out of bounds */ + if (len < 1) + continue; /* empty name */ + if (substr) + { + if (ascii_memcasemem (buffer+off, len, name, namelen)) + return 1; /* found */ + } + else + { + if (len == namelen && !memcmp (buffer+off, name, len)) + return 1; /* found */ + } + } + return 0; /* not found */ + } + else + { + if (idx > nuids) + return 0; /* no user ID with that idx */ + pos += idx*uidinfolen; + off = get32 (buffer+pos); + len = get32 (buffer+pos+4); + if (off+len > length) + return 0; /* out of bounds */ + if (len < 1) + return 0; /* empty name */ + + if (substr) + { + return !!ascii_memcasemem (buffer+off, len, name, namelen); + } + else + { + return len == namelen && !memcmp (buffer+off, name, len); + } + } +} + + +/* compare all email addresses of the subject. With SUBSTR given as + True a substring search is done in the mail address */ +static int +blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr) +{ + const unsigned char *buffer; + size_t length; + size_t pos, off, len; + size_t nkeys, keyinfolen; + size_t nuids, uidinfolen; + size_t nserial; + int idx; + + /* fixme: this code is common to blob_cmp_mail */ + buffer = _keybox_get_blob_image (blob, &length); + if (length < 40) + return 0; /* blob too short */ + + /*keys*/ + nkeys = get16 (buffer + 16); + keyinfolen = get16 (buffer + 18 ); + if (keyinfolen < 28) + return 0; /* invalid blob */ + pos = 20 + keyinfolen*nkeys; + if (pos+2 > length) + return 0; /* out of bounds */ + + /*serial*/ + nserial = get16 (buffer+pos); + pos += 2 + nserial; + if (pos+4 > length) + return 0; /* out of bounds */ + + /* user ids*/ + nuids = get16 (buffer + pos); pos += 2; + uidinfolen = get16 (buffer + pos); pos += 2; + if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */) + return 0; /* invalid blob */ + if (pos + uidinfolen*nuids > length) + return 0; /* out of bounds */ + + if (namelen < 1) + return 0; + + for (idx=1 ;idx < nuids; idx++) + { + size_t mypos = pos; + + mypos += idx*uidinfolen; + off = get32 (buffer+mypos); + len = get32 (buffer+mypos+4); + if (off+len > length) + return 0; /* error: better stop here out of bounds */ + if (len < 2 || buffer[off] != '<') + continue; /* empty name or trailing 0 not stored */ + len--; /* one back */ + if ( len < 3 || buffer[off+len] != '>') + continue; /* not a proper email address */ + len--; + if (substr) + { + if (ascii_memcasemem (buffer+off+1, len, name, namelen)) + return 1; /* found */ + } + else + { + if (len == namelen && !ascii_memcasecmp (buffer+off+1, name, len)) + return 1; /* found */ + } + } + return 0; /* not found */ +} + + + + +/* + The has_foo functions are used as helpers for search +*/ +static int +has_short_kid (KEYBOXBLOB blob, const unsigned char *kid) +{ + return blob_cmp_fpr_part (blob, kid+4, 16, 4); +} + +static int +has_long_kid (KEYBOXBLOB blob, const unsigned char *kid) +{ + return blob_cmp_fpr_part (blob, kid, 12, 8); +} + +static int +has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr) +{ + return blob_cmp_fpr (blob, fpr); +} + + +static int +has_issuer (KEYBOXBLOB blob, const char *name) +{ + size_t namelen; + + return_val_if_fail (name, 0); + + if (blob_get_type (blob) != BLOBTYPE_X509) + return 0; + + namelen = strlen (name); + return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0); +} + +static int +has_issuer_sn (KEYBOXBLOB blob, const char *name, + const unsigned char *sn, int snlen) +{ + size_t namelen; + + return_val_if_fail (name, 0); + return_val_if_fail (sn, 0); + + if (blob_get_type (blob) != BLOBTYPE_X509) + return 0; + + namelen = strlen (name); + + return (blob_cmp_sn (blob, sn, snlen) + && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0)); +} + +static int +has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) +{ + return_val_if_fail (sn, 0); + + if (blob_get_type (blob) != BLOBTYPE_X509) + return 0; + return blob_cmp_sn (blob, sn, snlen); +} + +static int +has_subject (KEYBOXBLOB blob, const char *name) +{ + size_t namelen; + + return_val_if_fail (name, 0); + + if (blob_get_type (blob) != BLOBTYPE_X509) + return 0; + + namelen = strlen (name); + return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0); +} + +static int +has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr) +{ + size_t namelen; + + return_val_if_fail (name, 0); + + if (blob_get_type (blob) != BLOBTYPE_X509) + return 0; + + namelen = strlen (name); + return blob_cmp_name (blob, -1 /* all subject names*/, name, + namelen, substr); +} + + +static int +has_mail (KEYBOXBLOB blob, const char *name, int substr) +{ + size_t namelen; + + return_val_if_fail (name, 0); + + if (blob_get_type (blob) != BLOBTYPE_X509) + return 0; + + namelen = strlen (name); + if (namelen && name[namelen-1] == '>') + namelen--; + return blob_cmp_mail (blob, name, namelen, substr); +} + + +static void +release_sn_array (struct sn_array_s *array, size_t size) +{ + size_t n; + + for (n=0; n < size; n++) + xfree (array[n].sn); + xfree (array); +} + + +/* + + The search API + +*/ + +int +keybox_search_reset (KEYBOX_HANDLE hd) +{ + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + if (hd->found.blob) + { + _keybox_release_blob (hd->found.blob); + hd->found.blob = NULL; + } + + if (hd->fp) + { + fclose (hd->fp); + hd->fp = NULL; + } + hd->error = 0; + hd->eof = 0; + return 0; +} + + +/* Note: When in ephemeral mode the search function does visit all + blobs but in standard mode, blobs flagged as ephemeral are ignored. */ +int +keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) +{ + int rc; + size_t n; + int need_words, any_skip; + KEYBOXBLOB blob = NULL; + struct sn_array_s *sn_array = NULL; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + /* clear last found result */ + if (hd->found.blob) + { + _keybox_release_blob (hd->found.blob); + hd->found.blob = NULL; + } + + if (hd->error) + return hd->error; /* still in error state */ + if (hd->eof) + return -1; /* still EOF */ + + /* figure out what information we need */ + need_words = any_skip = 0; + for (n=0; n < ndesc; n++) + { + switch (desc[n].mode) + { + case KEYDB_SEARCH_MODE_WORDS: + need_words = 1; + break; + case KEYDB_SEARCH_MODE_FIRST: + /* always restart the search in this mode */ + keybox_search_reset (hd); + break; + default: + break; + } + if (desc[n].skipfnc) + any_skip = 1; + if (desc[n].snlen == -1 && !sn_array) + { + sn_array = xtrycalloc (ndesc, sizeof *sn_array); + if (!sn_array) + return (hd->error = gpg_error (gpg_err_code_from_errno (errno))); + } + } + + if (!hd->fp) + { + hd->fp = fopen (hd->kb->fname, "rb"); + if (!hd->fp) + { + hd->error = gpg_error (gpg_err_code_from_errno (errno)); + xfree (sn_array); + return hd->error; + } + } + + /* kludge: we need to convert an SN given as hexstring to it's + binary representation - in some cases we are not able to store it + in the search descriptor, because due to its usgae it is not + possible to free allocated memory */ + if (sn_array) + { + const unsigned char *s; + int i, odd; + size_t snlen; + + for (n=0; n < ndesc; n++) + { + if (!desc[n].sn) + ; + else if (desc[n].snlen == -1) + { + unsigned char *sn; + + s = desc[n].sn; + for (i=0; *s && *s != '/'; s++, i++) + ; + odd = (i & 1); + snlen = (i+1)/2; + sn_array[n].sn = xtrymalloc (snlen); + if (!sn_array[n].sn) + { + hd->error = gpg_error (gpg_err_code_from_errno (errno)); + release_sn_array (sn_array, n); + return hd->error; + } + sn_array[n].snlen = snlen; + sn = sn_array[n].sn; + s = desc[n].sn; + if (odd) + { + *sn++ = xtoi_1 (s); + s++; + } + for (; *s && *s != '/'; s += 2) + *sn++ = xtoi_2 (s); + } + else + { + const unsigned char *sn; + + sn = desc[n].sn; + snlen = desc[n].snlen; + sn_array[n].sn = xtrymalloc (snlen); + if (!sn_array[n].sn) + { + hd->error = gpg_error (gpg_err_code_from_errno (errno)); + release_sn_array (sn_array, n); + return hd->error; + } + sn_array[n].snlen = snlen; + memcpy (sn_array[n].sn, sn, snlen); + } + } + } + + + for (;;) + { + unsigned int blobflags; + + _keybox_release_blob (blob); blob = NULL; + rc = _keybox_read_blob (&blob, hd->fp); + if (rc) + break; + + blobflags = blob_get_blob_flags (blob); + if (!hd->ephemeral && (blobflags & 2)) + continue; /* not in ephemeral mode but blob is flagged ephemeral */ + + for (n=0; n < ndesc; n++) + { + switch (desc[n].mode) + { + case KEYDB_SEARCH_MODE_NONE: + never_reached (); + break; + case KEYDB_SEARCH_MODE_EXACT: + if (has_subject_or_alt (blob, desc[n].u.name, 0)) + goto found; + break; + case KEYDB_SEARCH_MODE_MAIL: + if (has_mail (blob, desc[n].u.name, 0)) + goto found; + break; + case KEYDB_SEARCH_MODE_MAILSUB: + if (has_mail (blob, desc[n].u.name, 1)) + goto found; + break; + case KEYDB_SEARCH_MODE_SUBSTR: + if (has_subject_or_alt (blob, desc[n].u.name, 1)) + goto found; + break; + case KEYDB_SEARCH_MODE_MAILEND: + case KEYDB_SEARCH_MODE_WORDS: + never_reached (); /* not yet implemented */ + break; + case KEYDB_SEARCH_MODE_ISSUER: + if (has_issuer (blob, desc[n].u.name)) + goto found; + break; + case KEYDB_SEARCH_MODE_ISSUER_SN: + if (has_issuer_sn (blob, desc[n].u.name, + sn_array? sn_array[n].sn : desc[n].sn, + sn_array? sn_array[n].snlen : desc[n].snlen)) + goto found; + break; + case KEYDB_SEARCH_MODE_SN: + if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn, + sn_array? sn_array[n].snlen : desc[n].snlen)) + goto found; + break; + case KEYDB_SEARCH_MODE_SUBJECT: + if (has_subject (blob, desc[n].u.name)) + goto found; + break; + case KEYDB_SEARCH_MODE_SHORT_KID: + if (has_short_kid (blob, desc[n].u.kid)) + goto found; + break; + case KEYDB_SEARCH_MODE_LONG_KID: + if (has_long_kid (blob, desc[n].u.kid)) + goto found; + break; + case KEYDB_SEARCH_MODE_FPR: + case KEYDB_SEARCH_MODE_FPR20: + if (has_fingerprint (blob, desc[n].u.fpr)) + goto found; + break; + case KEYDB_SEARCH_MODE_FIRST: + goto found; + break; + case KEYDB_SEARCH_MODE_NEXT: + goto found; + break; + default: + rc = gpg_error (GPG_ERR_INV_VALUE); + goto found; + } + } + continue; + found: + for (n=any_skip?0:ndesc; n < ndesc; n++) + { +/* if (desc[n].skipfnc */ +/* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */ +/* break; */ + } + if (n == ndesc) + break; /* got it */ + } + + if (!rc) + { + hd->found.blob = blob; + } + else if (rc == -1) + { + _keybox_release_blob (blob); + hd->eof = 1; + } + else + { + _keybox_release_blob (blob); + hd->error = rc; + } + + if (sn_array) + release_sn_array (sn_array, ndesc); + + return rc; +} + + + + +/* + Functions to return a certificate or a keyblock. To be used after + a successful search operation. +*/ +#ifdef KEYBOX_WITH_X509 +/* + Return the last found cert. Caller must free it. + */ +int +keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert) +{ + const unsigned char *buffer; + size_t length; + size_t cert_off, cert_len; + KsbaReader reader = NULL; + KsbaCert cert = NULL; + int rc; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + if (!hd->found.blob) + return gpg_error (GPG_ERR_NOTHING_FOUND); + + if (blob_get_type (hd->found.blob) != BLOBTYPE_X509) + return gpg_error (GPG_ERR_WRONG_BLOB_TYPE); + + buffer = _keybox_get_blob_image (hd->found.blob, &length); + if (length < 40) + return gpg_error (GPG_ERR_TOO_SHORT); + cert_off = get32 (buffer+8); + cert_len = get32 (buffer+12); + if (cert_off+cert_len > length) + return gpg_error (GPG_ERR_TOO_SHORT); + + reader = ksba_reader_new (); + if (!reader) + return gpg_error (GPG_ERR_ENOMEM); + rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len); + if (rc) + { + ksba_reader_release (reader); + /* fixme: need to map the error codes */ + return gpg_error (GPG_ERR_GENERAL); + } + + cert = ksba_cert_new (); + if (!cert) + { + ksba_reader_release (reader); + return gpg_error (GPG_ERR_ENOMEM); + } + + rc = ksba_cert_read_der (cert, reader); + if (rc) + { + ksba_cert_release (cert); + ksba_reader_release (reader); + /* fixme: need to map the error codes */ + return gpg_error (GPG_ERR_GENERAL); + } + + *r_cert = cert; + ksba_reader_release (reader); + return 0; +} + +#endif /*KEYBOX_WITH_X509*/ diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c new file mode 100644 index 000000000..52ad258b0 --- /dev/null +++ b/kbx/keybox-update.c @@ -0,0 +1,437 @@ +/* keybox-update.c - keybox update operations + * 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 <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include "keybox-defs.h" + +#define EXTSEP_S "." + + +static int +create_tmp_file (const char *template, + char **r_bakfname, char **r_tmpfname, FILE **r_fp) +{ + char *bakfname, *tmpfname; + + *r_bakfname = NULL; + *r_tmpfname = NULL; + +# ifdef USE_ONLY_8DOT3 + /* Here is another Windoze bug?: + * you cant rename("pubring.kbx.tmp", "pubring.kbx"); + * but rename("pubring.kbx.tmp", "pubring.aaa"); + * works. So we replace .kbx by .bak or .tmp + */ + if (strlen (template) > 4 + && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") ) + { + bakfname = xtrymalloc (strlen (template) + 1); + if (!bakfname) + return gpg_error (gpg_err_code_from_errno (errno)); + strcpy (bakfname, template); + strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak"); + + tmpfname = xtrymalloc (strlen (template) + 1); + if (!tmpfname) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + xfree (bakfname); + return tmperr; + } + strcpy (tmpfname,template); + strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp"); + } + else + { /* file does not end with kbx; hmmm */ + bakfname = xtrymalloc ( strlen (template) + 5); + if (!bakfname) + return gpg_error (gpg_err_code_from_errno (errno)); + strcpy (stpcpy (bakfname, template), EXTSEP_S "bak"); + + tmpfname = xtrymalloc ( strlen (template) + 5); + if (!tmpfname) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + xfree (bakfname); + return tmperr; + } + strcpy (stpcpy (tmpfname, template), EXTSEP_S "tmp"); + } +# else /* Posix file names */ + bakfname = xtrymalloc (strlen (template) + 2); + if (!bakfname) + return gpg_error (gpg_err_code_from_errno (errno)); + strcpy (stpcpy (bakfname,template),"~"); + + tmpfname = xtrymalloc ( strlen (template) + 5); + if (!tmpfname) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + xfree (bakfname); + return tmperr; + } + strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp"); +# endif /* Posix filename */ + + *r_fp = fopen (tmpfname, "wb"); + if (!*r_fp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + xfree (tmpfname); + xfree (bakfname); + return tmperr; + } + + *r_bakfname = bakfname; + *r_tmpfname = tmpfname; + return 0; +} + + +static int +rename_tmp_file (const char *bakfname, const char *tmpfname, + const char *fname, int secret ) +{ + int rc=0; + + /* restrict the permissions for secret keyboxs */ +#ifndef HAVE_DOSISH_SYSTEM +/* if (secret && !opt.preserve_permissions) */ +/* { */ +/* if (chmod (tmpfname, S_IRUSR | S_IWUSR) ) */ +/* { */ +/* log_debug ("chmod of `%s' failed: %s\n", */ +/* tmpfname, strerror(errno) ); */ +/* return KEYBOX_Write_File; */ +/* } */ +/* } */ +#endif + + /* fixme: invalidate close caches (not used with stdio)*/ +/* iobuf_ioctl (NULL, 2, 0, (char*)tmpfname ); */ +/* iobuf_ioctl (NULL, 2, 0, (char*)bakfname ); */ +/* iobuf_ioctl (NULL, 2, 0, (char*)fname ); */ + + /* first make a backup file except for secret keyboxs */ + if (!secret) + { +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + remove (bakfname); +#endif + if (rename (fname, bakfname) ) + { + return gpg_error (gpg_err_code_from_errno (errno)); + } + } + + /* then rename the file */ +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + remove (fname); +#endif + if (rename (tmpfname, fname) ) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + if (secret) + { +/* log_info ("WARNING: 2 files with confidential" */ +/* " information exists.\n"); */ +/* log_info ("%s is the unchanged one\n", fname ); */ +/* log_info ("%s is the new one\n", tmpfname ); */ +/* log_info ("Please fix this possible security flaw\n"); */ + } + return rc; + } + + return 0; +} + + + +/* Perform insert/delete/update operation. + mode 1 = insert + 2 = delete + 3 = update +*/ +static int +blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, + int secret, off_t start_offset, unsigned int n_packets ) +{ + FILE *fp, *newfp; + int rc=0; + char *bakfname = NULL; + char *tmpfname = NULL; + char buffer[4096]; + int nread, nbytes; + + /* Open the source file. Because we do a rename, we have to check the + permissions of the file */ + if (access (fname, W_OK)) + return gpg_error (gpg_err_code_from_errno (errno)); + + fp = fopen (fname, "rb"); + if (mode == 1 && !fp && errno == ENOENT) + { /* insert mode but file does not exist: create a new keybox file */ + newfp = fopen (fname, "wb"); + if (!newfp ) + { + return gpg_error (gpg_err_code_from_errno (errno)); + } + + rc = _keybox_write_blob (blob, newfp); + if (rc) + { + return rc; + } + if ( fclose (newfp) ) + { + return gpg_error (gpg_err_code_from_errno (errno)); + } + +/* if (chmod( fname, S_IRUSR | S_IWUSR )) */ +/* { */ +/* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */ +/* return KEYBOX_File_Error; */ +/* } */ + return 0; /* ready */ + } + + if (!fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + + /* create the new file */ + rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); + if (rc) + { + fclose(fp); + goto leave; + } + + /* prepare for insert */ + if (mode == 1) + { + /* copy everything to the new file */ + while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) + { + if (fwrite (buffer, nread, 1, newfp) != 1) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + } + if (ferror (fp)) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + } + + /* prepare for delete or update */ + if ( mode == 2 || mode == 3 ) + { + off_t current = 0; + + /* copy first part to the new file */ + while ( current < start_offset ) + { + nbytes = DIM(buffer); + if (current + nbytes > start_offset) + nbytes = start_offset - current; + nread = fread (buffer, 1, nbytes, fp); + if (!fread) + break; + current += nread; + + if (fwrite (buffer, nread, 1, newfp) != 1) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + } + if (ferror (fp)) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + + /* skip this blob */ + rc = _keybox_read_blob (NULL, fp); + if (rc) + return rc; + } + + /* Do an insert or update */ + if ( mode == 1 || mode == 3 ) + { + rc = _keybox_write_blob (blob, newfp); + if (rc) + return rc; + } + + /* copy the rest of the packet for an delete or update */ + if (mode == 2 || mode == 3) + { + while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) + { + if (fwrite (buffer, nread, 1, newfp) != 1) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + } + if (ferror (fp)) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + } + + /* close both files */ + if (fclose(fp)) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + fclose (newfp); + goto leave; + } + if (fclose(newfp)) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + + rc = rename_tmp_file (bakfname, tmpfname, fname, secret); + + leave: + xfree(bakfname); + xfree(tmpfname); + return rc; +} + + + + +#ifdef KEYBOX_WITH_X509 +int +keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, + unsigned char *sha1_digest) +{ + int rc; + const char *fname; + KEYBOXBLOB blob; + + if (!hd) + return gpg_error (GPG_ERR_INV_HANDLE); + if (!hd->kb) + return gpg_error (GPG_ERR_INV_HANDLE); + fname = hd->kb->fname; + if (!fname) + return gpg_error (GPG_ERR_INV_HANDLE); + + /* close this one otherwise we will mess up the position for a next + search. Fixme: it would be better to adjust the position after + the write opertions. */ + if (hd->fp) + { + fclose (hd->fp); + hd->fp = NULL; + } + + rc = _keybox_create_x509_blob (&blob, cert, sha1_digest, hd->ephemeral); + if (!rc) + { + rc = blob_filecopy (1, fname, blob, hd->secret, 0, 0 ); + _keybox_release_blob (blob); + /* if (!rc && !hd->secret && kb_offtbl) */ + /* { */ + /* update_offset_hash_table_from_kb (kb_offtbl, kb, 0); */ + /* } */ + } + return rc; +} + +int +keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert, + unsigned char *sha1_digest) +{ + return -1; +} + + +#endif /*KEYBOX_WITH_X509*/ + + +int +keybox_delete (KEYBOX_HANDLE hd) +{ + off_t off; + const char *fname; + FILE *fp; + int rc; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + if (!hd->found.blob) + return gpg_error (GPG_ERR_NOTHING_FOUND); + if (!hd->kb) + return gpg_error (GPG_ERR_INV_HANDLE); + fname = hd->kb->fname; + if (!fname) + return gpg_error (GPG_ERR_INV_HANDLE); + + off = _keybox_get_blob_fileoffset (hd->found.blob); + if (off == (off_t)-1) + return gpg_error (GPG_ERR_GENERAL); + off += 4; + + if (hd->fp) + { + fclose (hd->fp); + hd->fp = NULL; + } + + fp = fopen (hd->kb->fname, "r+b"); + if (!fp) + return gpg_error (gpg_err_code_from_errno (errno)); + + if (fseeko (fp, off, SEEK_SET)) + rc = gpg_error (gpg_err_code_from_errno (errno)); + else if (putc (0, fp) == EOF) + rc = gpg_error (gpg_err_code_from_errno (errno)); + else + rc = 0; + + if (fclose (fp)) + { + if (!rc) + rc = gpg_error (gpg_err_code_from_errno (errno)); + } + + return rc; +} + + diff --git a/kbx/keybox.h b/kbx/keybox.h new file mode 100644 index 000000000..5fe5516d4 --- /dev/null +++ b/kbx/keybox.h @@ -0,0 +1,101 @@ +/* keybox.h - Keybox operations + * 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 KEYBOX_H +#define KEYBOX_H 1 +#ifdef __cplusplus +extern "C" { +#if 0 + } +#endif +#endif + +#include "keybox-search-desc.h" + +#define KEYBOX_WITH_OPENPGP 1 +#define KEYBOX_WITH_X509 1 + + +#ifdef KEYBOX_WITH_OPENPGP +# undef KEYBOX_WITH_OPENPGP +/*#include <lib-to-handle-gpg-data-structs.h>*/ +#endif + +#ifdef KEYBOX_WITH_X509 +# include <ksba.h> +#endif + + + +typedef struct keybox_handle *KEYBOX_HANDLE; + + +/*-- keybox-init.c --*/ +void *keybox_register_file (const char *fname, int secret); +int keybox_is_writable (void *token); + +KEYBOX_HANDLE keybox_new (void *token, int secret); +void keybox_release (KEYBOX_HANDLE hd); +const char *keybox_get_resource_name (KEYBOX_HANDLE hd); +int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes); + + +/*-- keybox-search.c --*/ +#ifdef KEYBOX_WITH_X509 +int keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *ret_cert); +#endif /*KEYBOX_WITH_X509*/ + +int keybox_search_reset (KEYBOX_HANDLE hd); +int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc); + + +/*-- keybox-update.c --*/ +#ifdef KEYBOX_WITH_X509 +int keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, + unsigned char *sha1_digest); +int keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert, + unsigned char *sha1_digest); +#endif /*KEYBOX_WITH_X509*/ + +int keybox_delete (KEYBOX_HANDLE hd); + + +/*-- --*/ + +#if 0 +int keybox_lock (KEYBOX_HANDLE hd, int yes); +int keybox_get_keyblock (KEYBOX_HANDLE hd, KBNODE *ret_kb); +int keybox_locate_writable (KEYBOX_HANDLE hd); +int keybox_search_reset (KEYBOX_HANDLE hd); +int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); +int keybox_rebuild_cache (void *); +#endif + + +/*-- keybox-util.c --*/ +void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), + void *(*new_realloc_func)(void *p, size_t n), + void (*new_free_func)(void*) ); + + +#ifdef __cplusplus +} +#endif +#endif /*KEYBOX_H*/ diff --git a/scd/atr.c b/scd/atr.c new file mode 100644 index 000000000..4e15aad50 --- /dev/null +++ b/scd/atr.c @@ -0,0 +1,287 @@ +/* atr.c - ISO 7816 ATR fucntions + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> +#include <assert.h> + +#include "scdaemon.h" +#include "apdu.h" +#include "atr.h" + +static int const fi_table[16] = { 0, 372, 558, 744, 1116,1488, 1860, -1, + -1, 512, 768, 1024, 1536, 2048, -1, -1 }; +static int const di_table[16] = { -1, 1, 2, 4, 8, 16, -1, -1, + 0, -1, -2, -4, -8, -16, -32, -64}; + + +/* Dump the ATR of the card at SLOT in a human readable format to + stream FP. */ +int +atr_dump (int slot, FILE *fp) +{ + unsigned char *atrbuffer, *atr; + size_t atrlen; + int have_ta, have_tb, have_tc, have_td; + int n_historical; + int idx, val; + unsigned char chksum; + + atr = atrbuffer = apdu_get_atr (slot, &atrlen); + if (!atr) + return gpg_error (GPG_ERR_GENERAL); + + fprintf (fp, "Info on ATR of length %u at slot %d\n", + (unsigned int)atrlen, slot); + if (!atrlen) + { + fprintf (fp, "error: empty ATR\n"); + goto bailout; + } + + + if (*atr == 0x3b) + fputs ("direct convention\n", fp); + else if (*atr == 0x3f) + fputs ("inverse convention\n", fp); + else + fprintf (fp,"error: invalid TS character 0x%02x\n", *atr); + if (!--atrlen) + goto bailout; + atr++; + + chksum = *atr; + for (idx=1; idx < atrlen-1; idx++) + chksum ^= atr[idx]; + + have_ta = !!(*atr & 0x10); + have_tb = !!(*atr & 0x20); + have_tc = !!(*atr & 0x40); + have_td = !!(*atr & 0x80); + n_historical = (*atr & 0x0f); + fprintf (fp, "%d historical characters indicated\n", n_historical); + + if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen) + fputs ("error: ATR shorter than indicated by format character\n", fp); + if (!--atrlen) + goto bailout; + atr++; + + if (have_ta) + { + fputs ("TA1: F=", fp); + val = fi_table[(*atr >> 4) & 0x0f]; + if (!val) + fputs ("internal clock", fp); + else if (val == -1) + fputs ("RFU", fp); + else + fprintf (fp, "%d", val); + fputs (" D=", fp); + val = di_table[*atr & 0x0f]; + if (!val) + fputs ("[impossible value]\n", fp); + else if (val == -1) + fputs ("RFU\n", fp); + else if (val < 0 ) + fprintf (fp, "1/%d\n", val); + else + fprintf (fp, "%d\n", val); + + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_tb) + { + fprintf (fp, "TB1: II=%d PI1=%d%s\n", (*atr >> 5) & 3, *atr & 0x1f, + (*atr & 0x80)? " [high bit not cleared]":""); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_tc) + { + if (*atr == 255) + fputs ("TC1: guard time shortened to 1 etu\n", fp); + else + fprintf (fp, "TC1: (extra guard time) N=%d\n", *atr); + + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_td) + { + have_ta = !!(*atr & 0x10); + have_tb = !!(*atr & 0x20); + have_tc = !!(*atr & 0x40); + have_td = !!(*atr & 0x80); + fprintf (fp, "TD1: protocol T%d supported\n", *atr & 0x0f); + + if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen) + fputs ("error: ATR shorter than indicated by format character\n", fp); + + if (!--atrlen) + goto bailout; + atr++; + } + else + have_ta = have_tb = have_tc = have_td = 0; + + if (have_ta) + { + fprintf (fp, "TA2: (PTS) %stoggle, %splicit, T=%02X\n", + (*atr & 0x80)? "no-":"", + (*atr & 0x10)? "im": "ex", + (*atr & 0x0f)); + if ((*atr & 0x60)) + fprintf (fp, "note: reserved bits are set (TA2=0x%02X)\n", *atr); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_tb) + { + fprintf (fp, "TB2: PI2=%d\n", *atr); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_tc) + { + fprintf (fp, "TC2: PWI=%d\n", *atr); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_td) + { + have_ta = !!(*atr & 0x10); + have_tb = !!(*atr & 0x20); + have_tc = !!(*atr & 0x40); + have_td = !!(*atr & 0x80); + fprintf (fp, "TD2: protocol T%d supported\n", *atr & 0x0f); + + if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen) + fputs ("error: ATR shorter than indicated by format character\n", fp); + + if (!--atrlen) + goto bailout; + atr++; + } + else + have_ta = have_tb = have_tc = have_td = 0; + + for (idx = 3; have_ta || have_tb || have_tc || have_td; idx++) + { + if (have_ta) + { + fprintf (fp, "TA%d: IFSC=%d\n", idx, *atr); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_tb) + { + fprintf (fp, "TB%d: BWI=%d CWI=%d\n", + idx, (*atr >> 4) & 0x0f, *atr & 0x0f); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_tc) + { + fprintf (fp, "TC%d: 0x%02X\n", idx, *atr); + if (!--atrlen) + goto bailout; + atr++; + } + + if (have_td) + { + have_ta = !!(*atr & 0x10); + have_tb = !!(*atr & 0x20); + have_tc = !!(*atr & 0x40); + have_td = !!(*atr & 0x80); + fprintf (fp, "TD%d: protocol T%d supported\n", idx, *atr & 0x0f); + + if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen) + fputs ("error: ATR shorter than indicated by format character\n", + fp); + + if (!--atrlen) + goto bailout; + atr++; + } + else + have_ta = have_tb = have_tc = have_td = 0; + } + + if (n_historical + 1 > atrlen) + fputs ("error: ATR shorter than required for historical bytes " + "and checksum\n", fp); + + if (n_historical) + { + fputs ("Historical:", fp); + for (; n_historical && atrlen ; n_historical--, atrlen--, atr++) + fprintf (fp, " %02X", *atr); + putchar ('\n'); + } + + if (!atrlen) + fputs ("error: checksum missing\n", fp); + else if (*atr == chksum) + fprintf (fp, "TCK: %02X (good)\n", *atr); + else + fprintf (fp, "TCK: %02X (bad; calculated %02X)\n", *atr, chksum); + + atrlen--; + if (atrlen) + fprintf (fp, "error: %u bytes garbage at end of ATR\n", + (unsigned int)atrlen ); + + bailout: + xfree (atrbuffer); + + return 0; +} + + + + + + + + + diff --git a/scd/atr.h b/scd/atr.h new file mode 100644 index 000000000..5fdd57457 --- /dev/null +++ b/scd/atr.h @@ -0,0 +1,28 @@ +/* atr.h - ISO 7816 ATR functions + * 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 ATR_H +#define ATR_H + +int atr_dump (int slot, FILE *fp); + + + +#endif /*ATR_H*/ diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c new file mode 100644 index 000000000..391a51da8 --- /dev/null +++ b/scd/card-dinsig.c @@ -0,0 +1,260 @@ +/* card-dinsig.c - German signature law (DINSIG) functions + * 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 + */ + +/* The German signature law and its bylaw (SigG and SigV) is currently + used with an interface specification described in DIN V 66291-1. + The AID to be used is: 'D27600006601'. + + The file IDs for certificates utilize the generic format: + Cxyz + C being the hex digit 'C' (12). + x being the service indicator: + '0' := SigG conform digital signature. + '1' := entity authentication. + '2' := key encipherment. + '3' := data encipherment. + '4' := key agreement. + other values are reserved for future use. + y being the security environment number using '0' for cards + not supporting a SE number. + z being the certificate type: + '0' := C.CH (base certificate of ard holder) or C.ICC. + '1' .. '7' := C.CH (business or professional certificate + of card holder. + '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA). + 'E' := C.RCA (self certified certificate of the Root-CA). + 'F' := reserved. + + The file IDs used by default are: + '1F00' EF.SSD (security service descriptor). [o,o] + '2F02' EF.GDO (global data objects) [m,m] + 'A000' EF.PROT (signature log). Cyclic file with 20 records of 53 byte. + Read and update after user authentication. [o,o] + 'B000' EF.PK.RCA.DS (public keys of Root-CA). Size is 512b or size + of keys. [m (unless a 'C00E' is present),m] + 'B001' EF.PK.CA.DS (public keys of CAs). Size is 512b or size + of keys. [o,o] + 'C00n' EF.C.CH.DS (digital signature certificate of card holder) + with n := 0 .. 7. Size is 2k or size of cert. Read and + update allowed after user authentication. [m,m] + 'C00m' EF.C.CA.DS (digital signature certificate of CA) + with m := 8 .. E. Size is 1k or size of cert. Read always + allowed, update after uder authentication. [o,o] + 'C100' EF.C.ICC.AUT (AUT certificate of ICC) [o,m] + 'C108' EF.C.CA.AUT (AUT certificate of CA) [o,m] + 'D000' EF.DM (display message) [-,m] + + The letters in brackets indicate optional or mandatory files: The + first for card terminals under full control and the second for + "business" card terminals. + + FIXME: Needs a lot more explanation. + +*/ + + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifdef HAVE_OPENSC +#include <opensc/pkcs15.h> +#include <ksba.h> + +#include "scdaemon.h" +#include "card-common.h" + +static int dinsig_read_cert (CARD card, const char *certidstr, + unsigned char **cert, size_t *ncert); + + + +/* See card.c for interface description. Frankly we don't do any real + enumeration but just check whether the well know files are + available. */ +static int +dinsig_enum_keypairs (CARD card, int idx, + unsigned char *keygrip, char **keyid) +{ + int rc; + unsigned char *buf; + size_t buflen; + KsbaError krc; + KsbaCert cert; + + /* fixme: We should locate the application via the EF(DIR) and not + assume a Netkey card */ + if (!idx) + rc = dinsig_read_cert (card, "DINSIG-DF01.C000", &buf, &buflen); + else if (idx == 1) + rc = dinsig_read_cert (card, "DINSIG-DF01.C200", &buf, &buflen); + else + rc = -1; + if (rc) + return rc; + + cert = ksba_cert_new (); + if (!cert) + { + gpg_error_t tmperr = out_of_core (); + xfree (buf); + return tmperr; + } + + krc = ksba_cert_init_from_mem (cert, buf, buflen); + xfree (buf); + if (krc) + { + log_error ("failed to parse the certificate at idx %d: %s\n", + idx, ksba_strerror (krc)); + ksba_cert_release (cert); + return gpg_error (GPG_ERR_CARD); + } + if (card_help_get_keygrip (cert, keygrip)) + { + log_error ("failed to calculate the keygrip at index %d\n", idx); + ksba_cert_release (cert); + return gpg_error (GPG_ERR_CARD); + } + ksba_cert_release (cert); + + /* return the iD */ + if (keyid) + { + *keyid = xtrymalloc (17); + if (!*keyid) + return out_of_core (); + if (!idx) + strcpy (*keyid, "DINSIG-DF01.C000"); + else + strcpy (*keyid, "DINSIG-DF01.C200"); + } + + return 0; +} + + + +/* See card.c for interface description */ +static int +dinsig_read_cert (CARD card, const char *certidstr, + unsigned char **cert, size_t *ncert) +{ + int rc; + struct sc_path path; + struct sc_file *file; + unsigned char *buf; + int buflen; + + if (!strcmp (certidstr, "DINSIG-DF01.C000")) + sc_format_path ("3F00DF01C000", &path); + else if (!strcmp (certidstr, "DINSIG-DF01.C200")) + sc_format_path ("3F00DF01C200", &path); + else + return gpg_error (GPG_ERR_INV_ID); + + rc = sc_select_file (card->scard, &path, &file); + if (rc) + { + log_error ("sc_select_file failed: %s\n", sc_strerror (rc)); + return map_sc_err (rc); + } + if (file->type != SC_FILE_TYPE_WORKING_EF + || file->ef_structure != SC_FILE_EF_TRANSPARENT) + { + log_error ("wrong type or structure of certificate EF\n"); + sc_file_free (file); + return gpg_error (GPG_ERR_CARD); + } + if (file->size < 20) /* check against a somewhat arbitrary length */ + { + log_error ("certificate EF too short\n"); + sc_file_free (file); + return gpg_error (GPG_ERR_CARD); + } + buf = xtrymalloc (file->size); + if (!buf) + { + gpg_error_t tmperr = out_of_core (); + sc_file_free (file); + return tmperr; + } + + rc = sc_read_binary (card->scard, 0, buf, file->size, 0); + if (rc >= 0 && rc != file->size) + { + log_error ("short read on certificate EF\n"); + sc_file_free (file); + xfree (buf); + return gpg_error (GPG_ERR_CARD); + } + sc_file_free (file); + if (rc < 0) + { + log_error ("error reading certificate EF: %s\n", sc_strerror (rc)); + xfree (buf); + return map_sc_err (rc); + } + buflen = rc; + + /* The object is not a plain certificate but wrapped into id-at + userCertificate - fixme: we should check the specs and decided + whether libksba should support it */ + if (buflen > 9 && buf[0] == 0x30 && buf[4] == 6 && buf[5] == 3 + && buf[6] == 0x55 && buf[7] == 4 && buf[8] == 0x24) + { + /* We have to strip the padding. Although this is a good idea + anyway, we have to do it due to a KSBA problem; KSBA does not + work correct when the buffer is larger than the ASN.1 + structure and the certificates here are padded with FF. So + as a workaround we look at the outer structure to get the + size of the entire thing and adjust the buflen. We can only + do this when there is a 2 byte length field */ + size_t seqlen; + if (buf[1] == 0x82) + { + seqlen = ((buf[2] << 8) | buf[3]) + 4; + if (seqlen < buflen) + buflen = seqlen; + } + memmove (buf, buf+9, buflen-9); + buflen -= 9; + } + + *cert = buf; + *ncert = buflen; + return 0; +} + + + + +/* Bind our operations to the card */ +void +card_dinsig_bind (CARD card) +{ + card->fnc.enum_keypairs = dinsig_enum_keypairs; + card->fnc.read_cert = dinsig_read_cert; + +} +#endif /*HAVE_OPENSC*/ diff --git a/sm/base64.c b/sm/base64.c new file mode 100644 index 000000000..07f546e85 --- /dev/null +++ b/sm/base64.c @@ -0,0 +1,624 @@ +/* base64.c + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include <ksba.h> + +#include "gpgsm.h" +#include "i18n.h" + +#ifdef HAVE_DOSISH_SYSTEM + #define LF "\r\n" +#else + #define LF "\n" +#endif + +/* data used by the reader callbacks */ +struct reader_cb_parm_s { + FILE *fp; + unsigned char line[1024]; + int linelen; + int readpos; + int have_lf; + unsigned long line_counter; + + int autodetect; /* try to detect the input encoding */ + int assume_pem; /* assume input encoding is PEM */ + int assume_base64; /* assume input is base64 encoded */ + + int identified; + int is_pem; + int is_base64; + int stop_seen; + int might_be_smime; + + struct { + int idx; + unsigned char val; + int stop_seen; + } base64; +}; + +/* data used by the writer callbacks */ +struct writer_cb_parm_s { + FILE *fp; + const char *pem_name; + + int wrote_begin; + int did_finish; + + struct { + int idx; + int quad_count; + unsigned char radbuf[4]; + } base64; + +}; + + +/* context for this module's functions */ +struct base64_context_s { + union { + struct reader_cb_parm_s rparm; + struct writer_cb_parm_s wparm; + } u; +}; + + +/* The base-64 character list */ +static unsigned char bintoasc[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; +/* The reverse base-64 list */ +static unsigned char asctobin[256] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff +}; + + +static int +has_only_base64 (const unsigned char *line, int linelen) +{ + if (linelen < 20) + return 0; + for (; linelen; line++, linelen--) + { + if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n')) + break; + if ( !strchr (bintoasc, *line) ) + return 0; + } + return 1; /* yes */ +} + +static int +is_empty_line (const unsigned char *line, int linelen) +{ + if (linelen >= 2 && *line == '\r' && line[1] == '\n') + return 1; + if (linelen >= 1 && *line == '\n') + return 1; + return 0; +} + + +static int +base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) +{ + struct reader_cb_parm_s *parm = cb_value; + size_t n; + int c, c2; + + *nread = 0; + if (!buffer) + return -1; /* not supported */ + + next: + if (!parm->linelen) + { + /* read an entire line or up to the size of the buffer */ + parm->line_counter++; + parm->have_lf = 0; + for (n=0; n < DIM(parm->line);) + { + c = getc (parm->fp); + if (c == EOF) + { + if (ferror (parm->fp)) + return -1; + break; + } + parm->line[n++] = c; + if (c == '\n') + { + parm->have_lf = 1; + /* Fixme: we need to skip overlong lines while detecting + the dashed lines */ + break; + } + } + parm->linelen = n; + if (!n) + return -1; /* eof */ + parm->readpos = 0; + } + + if (!parm->identified) + { + if (!parm->autodetect) + { + if (parm->assume_pem) + { + /* wait for the header line */ + parm->linelen = parm->readpos = 0; + if (!parm->have_lf || strncmp (parm->line, "-----BEGIN ", 11) + || !strncmp (parm->line+11, "PGP ", 4)) + goto next; + parm->is_pem = 1; + } + else if (parm->assume_base64) + parm->is_base64 = 1; + } + else if (parm->line_counter == 1 && !parm->have_lf) + { + /* first line too long - assume DER encoding */ + parm->is_pem = 0; + } + else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30) + { + /* the very first byte does pretty much look like a SEQUENCE tag*/ + parm->is_pem = 0; + } + else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11) + && strncmp (parm->line+11, "PGP ", 4) ) + { + /* Fixme: we must only compare if the line really starts at + the beginning */ + parm->is_pem = 1; + parm->linelen = parm->readpos = 0; + } + else if ( parm->have_lf && parm->line_counter == 1 + && parm->linelen >= 13 + && !ascii_memcasecmp (parm->line, "Content-Type:", 13)) + { /* might be a S/MIME body */ + parm->might_be_smime = 1; + parm->linelen = parm->readpos = 0; + goto next; + } + else if (parm->might_be_smime == 1 + && is_empty_line (parm->line, parm->linelen)) + { + parm->might_be_smime = 2; + parm->linelen = parm->readpos = 0; + goto next; + } + else if (parm->might_be_smime == 2) + { + parm->might_be_smime = 0; + if ( !has_only_base64 (parm->line, parm->linelen)) + { + parm->linelen = parm->readpos = 0; + goto next; + } + parm->is_pem = 1; + } + else + { + parm->linelen = parm->readpos = 0; + goto next; + } + parm->identified = 1; + parm->base64.stop_seen = 0; + parm->base64.idx = 0; + } + + + n = 0; + if (parm->is_pem || parm->is_base64) + { + if (parm->is_pem && parm->have_lf + && !strncmp (parm->line, "-----END ", 9)) + { + parm->identified = 0; + parm->linelen = parm->readpos = 0; + /* let us return 0 */ + } + else if (parm->stop_seen) + { /* skip the rest of the line */ + parm->linelen = parm->readpos = 0; + } + else + { + int idx = parm->base64.idx; + unsigned char val = parm->base64.val; + + while (n < count && parm->readpos < parm->linelen ) + { + c = parm->line[parm->readpos++]; + if (c == '\n' || c == ' ' || c == '\r' || c == '\t') + continue; + if (c == '=') + { /* pad character: stop */ + if (idx == 1) + buffer[n++] = val; + parm->stop_seen = 1; + break; + } + if( (c = asctobin[(c2=c)]) == 255 ) + { + log_error (_("invalid radix64 character %02x skipped\n"), + c2); + continue; + } + switch (idx) + { + case 0: + val = c << 2; + break; + case 1: + val |= (c>>4)&3; + buffer[n++] = val; + val = (c<<4)&0xf0; + break; + case 2: + val |= (c>>2)&15; + buffer[n++] = val; + val = (c<<6)&0xc0; + break; + case 3: + val |= c&0x3f; + buffer[n++] = val; + break; + } + idx = (idx+1) % 4; + } + if (parm->readpos == parm->linelen) + parm->linelen = parm->readpos = 0; + + parm->base64.idx = idx; + parm->base64.val = val; + } + } + else + { /* DER encoded */ + while (n < count && parm->readpos < parm->linelen) + buffer[n++] = parm->line[parm->readpos++]; + if (parm->readpos == parm->linelen) + parm->linelen = parm->readpos = 0; + } + + *nread = n; + return 0; +} + + + +static int +simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) +{ + struct reader_cb_parm_s *parm = cb_value; + size_t n; + int c = 0; + + *nread = 0; + if (!buffer) + return -1; /* not supported */ + + for (n=0; n < count; n++) + { + c = getc (parm->fp); + if (c == EOF) + { + if ( ferror (parm->fp) ) + return -1; + if (n) + break; /* return what we have before an EOF */ + return -1; + } + *(byte *)buffer++ = c; + } + + *nread = n; + return 0; +} + + + + +static int +base64_writer_cb (void *cb_value, const void *buffer, size_t count) +{ + struct writer_cb_parm_s *parm = cb_value; + unsigned char radbuf[4]; + int i, c, idx, quad_count; + const unsigned char *p; + FILE *fp = parm->fp; + + if (!count) + return 0; + + if (!parm->wrote_begin) + { + if (parm->pem_name) + { + fputs ("-----BEGIN ", fp); + fputs (parm->pem_name, fp); + fputs ("-----\n", fp); + } + parm->wrote_begin = 1; + parm->base64.idx = 0; + parm->base64.quad_count = 0; + } + + idx = parm->base64.idx; + quad_count = parm->base64.quad_count; + for (i=0; i < idx; i++) + radbuf[i] = parm->base64.radbuf[i]; + + for (p=buffer; count; p++, count--) + { + radbuf[idx++] = *p; + if (idx > 2) + { + idx = 0; + c = bintoasc[(*radbuf >> 2) & 077]; + putc (c, fp); + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + putc (c, fp); + c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + putc (c, fp); + c = bintoasc[radbuf[2]&077]; + putc (c, fp); + if (++quad_count >= (64/4)) + { + fputs (LF, fp); + quad_count = 0; + } + } + } + for (i=0; i < idx; i++) + parm->base64.radbuf[i] = radbuf[i]; + parm->base64.idx = idx; + parm->base64.quad_count = quad_count; + + return ferror (fp) ? KSBA_Write_Error:0; +} + +static int +base64_finish_write (struct writer_cb_parm_s *parm) +{ + unsigned char radbuf[4]; + int i, c, idx, quad_count; + FILE *fp = parm->fp; + + if (!parm->wrote_begin) + return 0; /* nothing written */ + + /* flush the base64 encoding */ + idx = parm->base64.idx; + quad_count = parm->base64.quad_count; + for (i=0; i < idx; i++) + radbuf[i] = parm->base64.radbuf[i]; + + if (idx) + { + c = bintoasc[(*radbuf>>2)&077]; + putc (c, fp); + if (idx == 1) + { + c = bintoasc[((*radbuf << 4) & 060) & 077]; + putc (c, fp); + putc ('=', fp); + putc ('=', fp); + } + else + { + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; + putc (c, fp); + c = bintoasc[((radbuf[1] << 2) & 074) & 077]; + putc (c, fp); + putc ('=', fp); + + } + if (++quad_count >= (64/4)) + { + fputs (LF, fp); + quad_count = 0; + } + } + + if (quad_count) + fputs (LF, fp); + + if (parm->pem_name) + { + fputs ("-----END ", fp); + fputs (parm->pem_name, fp); + fputs ("-----\n", fp); + } + return ferror (fp)? gpg_error (gpg_err_code_from_errno (errno)) : 0; +} + + + + +/* Create a reader for the given file descriptor. Depending on the + control information an input decoding is automagically choosen. + The function returns a Base64Context object which must be passed to + the gpgme_destroy_reader function. The created KsbaReader object + is also returned, but the caller must not call the + ksba_reader_release function on. */ +int +gpgsm_create_reader (Base64Context *ctx, + CTRL ctrl, FILE *fp, KsbaReader *r_reader) +{ + int rc; + KsbaReader r; + + *r_reader = NULL; + *ctx = xtrycalloc (1, sizeof **ctx); + if (!*ctx) + return OUT_OF_CORE (errno); + + r = ksba_reader_new (); + if (!r) + { + xfree (*ctx); *ctx = NULL; + return gpg_error (GPG_ERR_ENOMEM); + } + + (*ctx)->u.rparm.fp = fp; + if (ctrl->is_pem) + { + (*ctx)->u.rparm.assume_pem = 1; + (*ctx)->u.rparm.assume_base64 = 1; + rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); + } + else if (ctrl->is_base64) + { + (*ctx)->u.rparm.assume_base64 = 1; + rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); + } + else if (ctrl->autodetect_encoding) + { + (*ctx)->u.rparm.autodetect = 1; + rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); + } + else + rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm); + + if (rc) + { + ksba_reader_release (r); + xfree (*ctx); *ctx = NULL; + return map_ksba_err (rc); + } + + *r_reader = r; + return 0; +} + + +void +gpgsm_destroy_reader (Base64Context ctx) +{ + xfree (ctx); +} + + + +/* Create a writer for the given stream. Depending on the control + information an output encoding is automagically choosen. The + function returns a Base64Context object which must be passed to the + gpgme_destroy_writer function. The created KsbaWriter object is + also returned, but the caller must not call the ksba_reader_release + function on. */ +int +gpgsm_create_writer (Base64Context *ctx, + CTRL ctrl, FILE *fp, KsbaWriter *r_writer) +{ + int rc; + KsbaWriter w; + + *r_writer = NULL; + *ctx = xtrycalloc (1, sizeof **ctx); + if (!*ctx) + return OUT_OF_CORE (errno); + + w = ksba_writer_new (); + if (!w) + { + xfree (*ctx); *ctx = NULL; + return gpg_error (GPG_ERR_ENOMEM); + } + + if (ctrl->create_pem || ctrl->create_base64) + { + (*ctx)->u.wparm.fp = fp; + if (ctrl->create_pem) + (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name + : "CMS OBJECT"; + rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm); + } + else + rc = ksba_writer_set_file (w, fp); + + if (rc) + { + ksba_writer_release (w); + xfree (*ctx); *ctx = NULL; + return map_ksba_err (rc); + } + + *r_writer = w; + return 0; +} + + +int +gpgsm_finish_writer (Base64Context ctx) +{ + struct writer_cb_parm_s *parm; + + if (!ctx) + return gpg_error (GPG_ERR_INV_VALUE); + parm = &ctx->u.wparm; + if (parm->did_finish) + return 0; /* already done */ + parm->did_finish = 1; + if (!parm->fp) + return 0; /* callback was not used */ + return base64_finish_write (parm); +} + +void +gpgsm_destroy_writer (Base64Context ctx) +{ + xfree (ctx); +} -- cgit v1.2.3 From b7b07d36e89ce30b2cf4774ed0e36d2403777bab Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 5 Jun 2003 07:14:21 +0000 Subject: A small step for GnuPG but a huge leap for error codes. (Sorry, it does not build currently - I need to check it in to avoid duplicate work.) --- ChangeLog | 4 + Makefile.am | 8 +- configure.ac | 4 +- g10/ChangeLog | 7 + g10/Makefile.am | 13 +- g10/call-agent.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ g10/call-agent.h | 34 +++++ g10/g10.c | 3 + g10/gpg.h | 33 +++++ g10/options.h | 2 +- include/errors.h | 11 +- 11 files changed, 514 insertions(+), 12 deletions(-) create mode 100644 g10/call-agent.c create mode 100644 g10/call-agent.h create mode 100644 g10/gpg.h diff --git a/ChangeLog b/ChangeLog index dd9c320fc..d2a1453de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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 diff --git a/Makefile.am b/Makefile.am index d9a09264f..74e622051 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,6 +23,11 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = scripts/config.rpath autogen.sh +if BUILD_GPG +gpg = g10 +else +gpg = +endif if BUILD_GPGSM sm = sm else @@ -39,9 +44,10 @@ else scd = endif -SUBDIRS = m4 intl jnlib common kbx ${sm} ${agent} ${scd} po doc tests +SUBDIRS = m4 intl jnlib common kbx ${gpg} ${sm} ${agent} ${scd} po doc tests dist-hook: @set -e; echo "$(VERSION)" > $(distdir)/VERSION + diff --git a/configure.ac b/configure.ac index e075d7196..2f0bf9d64 100644 --- a/configure.ac +++ b/configure.ac @@ -44,7 +44,7 @@ have_ksba=no have_opensc=no have_pth=no -GNUPG_BUILD_PROGRAM(gpg, no) +GNUPG_BUILD_PROGRAM(gpg, yes) GNUPG_BUILD_PROGRAM(gpgsm, yes) GNUPG_BUILD_PROGRAM(agent, yes) GNUPG_BUILD_PROGRAM(scdaemon, yes) @@ -363,6 +363,7 @@ if test "$build_scdaemon" = "yes"; then fi +AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") @@ -375,6 +376,7 @@ intl/Makefile jnlib/Makefile common/Makefile kbx/Makefile +g10/Makefile sm/Makefile agent/Makefile scd/Makefile diff --git a/g10/ChangeLog b/g10/ChangeLog index 3db1b0ef1..176ec10fa 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +2003-06-04 Werner Koch <wk@gnupg.org> + + * Makefile.am: Add new files, link gpg with libgpg-error. + * g10.c, options.h: New option --agent-program. + * call-agent.c: New. + * gpg.h, call-agent.h: New. + 2003-06-03 David Shaw <dshaw@jabberwocky.com> * options.h, g10.c (main), keylist.c (list_keyblock_print): Add diff --git a/g10/Makefile.am b/g10/Makefile.am index a7e3117f8..91438741a 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -24,16 +24,17 @@ EXTRA_DIST = options.skel # it seems that we can't use this with automake 1.5 #OMIT_DEPENDENCIES = zlib.h zconf.h libexecdir = @libexecdir@/@PACKAGE@ -if ! HAVE_DOSISH_SYSTEM -AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" -endif +# FIXME: Windows support currently not enabled +#if ! HAVE_DOSISH_SYSTEM +#AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" +#endif needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a #noinst_PROGRAMS = gpgd bin_PROGRAMS = gpg gpgv common_source = \ - global.h \ + global.h gpg.h \ build-packet.c \ compress.c \ filter.h \ @@ -93,6 +94,7 @@ gpg_SOURCES = g10.c \ keyserver.c \ keyserver-internal.h \ photoid.c photoid.h \ + call-agent.c call-agent.h \ exec.c exec.h gpgv_SOURCES = gpgv.c \ @@ -107,8 +109,7 @@ gpgv_SOURCES = gpgv.c \ # $(common_source) LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ -# gpg gets LIBOBJS to add in mkdtemp if the platform doesn't have it -gpg_LDADD = @LIBOBJS@ $(LDADD) @DLLIBS@ @EGDLIBS@ +gpg_LDADD = $(LDADD) @DLLIBS@ @EGDLIBS@ -lgpg-error $(PROGRAMS): $(needed_libs) diff --git a/g10/call-agent.c b/g10/call-agent.c new file mode 100644 index 000000000..6cc514dca --- /dev/null +++ b/g10/call-agent.c @@ -0,0 +1,407 @@ +/* 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> +#include <gcrypt.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#include <assuan.h> + +#include "gpg.h" +#include "i18n.h" + +static ASSUAN_CONTEXT agent_ctx = NULL; +static int force_pipe_server = 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; +}; + +struct learn_parm_s { + int error; + ASSUAN_CONTEXT ctx; + struct membuf *data; +}; + + +/* 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) + { + 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 OUT_OF_CORE (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 OUT_OF_CORE (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 OUT_OF_CORE (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 OUT_OF_CORE (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 = OUT_OF_CORE (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 OUT_OF_CORE (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 = OUT_OF_CORE (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; +} + + +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; +} + + + +#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); +} + + +/* Ask the agent to change the passphrase of the key identified by + HEXKEYGRIP. */ +int +agent_passwd (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, "PASSWD %s", hexkeygrip); + line[DIM(line)-1] = 0; + + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + return map_assuan_err (rc); +} + diff --git a/g10/call-agent.h b/g10/call-agent.h new file mode 100644 index 000000000..fbb11958c --- /dev/null +++ b/g10/call-agent.h @@ -0,0 +1,34 @@ +/* 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 + +/* 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); + +/* Ask the agent to let the user change the passphrase of the secret + key identified by HEXKEYGRIP. */ +int agent_passwd (const char *hexkeygrip); + + + + +#endif /*GNUPG_G10_CALL_AGENT_H*/ diff --git a/g10/g10.c b/g10/g10.c index 8a7f09d13..d17422c12 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -303,6 +303,7 @@ enum cmd_and_opt_values { aNull = 0, oPersonalDigestPreferences, oPersonalCompressPreferences, oEmuMDEncodeBug, + oAgentProgram, oDisplay, oTTYname, oTTYtype, @@ -610,6 +611,7 @@ static ARGPARSE_OPTS opts[] = { { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, + { oAgentProgram, "agent-program", 2 , "@" }, { oDisplay, "display", 2, "@" }, { oTTYname, "ttyname", 2, "@" }, { oTTYtype, "ttytype", 2, "@" }, @@ -1876,6 +1878,7 @@ main( int argc, char **argv ) case oPersonalCompressPreferences: pers_compress_list=pargs.r.ret_str; break; + case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; case oDisplay: opt.display = pargs.r.ret_str; break; case oTTYname: opt.ttyname = pargs.r.ret_str; break; case oTTYtype: opt.ttytype = pargs.r.ret_str; break; diff --git a/g10/gpg.h b/g10/gpg.h new file mode 100644 index 000000000..ca7699bca --- /dev/null +++ b/g10/gpg.h @@ -0,0 +1,33 @@ +/* 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 + +#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*/ diff --git a/g10/options.h b/g10/options.h index 1a70277dc..a68dc52c4 100644 --- a/g10/options.h +++ b/g10/options.h @@ -79,7 +79,7 @@ struct { int completes_needed; int max_cert_depth; const char *homedir; - + const char *agent_program; char *display; /* 5 options to be passed to the gpg-agent */ char *ttyname; char *ttytype; diff --git a/include/errors.h b/include/errors.h index 0dde0f9b5..8e1de0f16 100644 --- a/include/errors.h +++ b/include/errors.h @@ -17,8 +17,13 @@ * 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_ERRORS_H -#define G10_ERRORS_H +#ifndef GNUPG_INCLUDE_ERRORS_H +#define GNUPG_INCLUDE_ERRORS_H + +#if 0 +#error Remove this file after replacing all error codes with those +#error from libgpg-error. The numerical values are identical, though. +#endif #define G10ERR_GENERAL 1 #define G10ERR_UNKNOWN_PACKET 2 @@ -81,4 +86,4 @@ char *strerror( int n ); #endif -#endif /*G10_ERRORS_H*/ +#endif /*GNUPG_INCLUDE_ERRORS_H*/ -- cgit v1.2.3 From c0c2c58054923d506f61ce9a71d509b48a381211 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Jun 2003 19:56:13 +0000 Subject: Finished the bulk of changes for gnupg 1.9. This included switching to libgcrypt functions, using shared error codes from libgpg-error, replacing the old functions we used to have in ../util by those in ../jnlib and ../common, renaming the malloc functions and a couple of types. Note, that not all changes are listed below becuause they are too similar and done at far too many places. As of today the code builds using the current libgcrypt from CVS but it is very unlikely that it actually works. --- ChangeLog | 10 + TODO | 14 - acinclude.m4 | 152 ++++++++- configure.ac | 791 ++++++++++++++++++++++++++++++++++++++++++----- g10/ChangeLog | 69 ++++- g10/Makefile.am | 19 +- g10/armor.c | 31 +- g10/build-packet.c | 204 ++++++------ g10/call-agent.c | 24 +- g10/cipher.c | 73 +++-- g10/comment.c | 38 ++- g10/compress.c | 43 +-- g10/dearmor.c | 11 +- g10/decrypt.c | 13 +- g10/delkey.c | 16 +- g10/encode.c | 138 +++++---- g10/encr-data.c | 83 ++--- g10/exec.c | 66 ++-- g10/exec.h | 6 +- g10/export.c | 21 +- g10/filter.h | 19 +- g10/free-packet.c | 68 ++-- g10/g10.c | 441 +++++++++++++++----------- g10/getkey.c | 100 +++--- g10/global.h | 2 + g10/gpg.h | 5 + g10/gpgv.c | 48 +-- g10/helptext.c | 2 + g10/import.c | 126 ++++---- g10/kbnode.c | 12 +- g10/keydb.c | 55 ++-- g10/keydb.h | 3 +- g10/keyedit.c | 156 +++++----- g10/keygen.c | 299 +++++++++--------- g10/keyid.c | 208 ++++++++----- g10/keylist.c | 50 +-- g10/keyring.c | 158 +++++----- g10/keyserver-internal.h | 2 +- g10/keyserver.c | 94 +++--- g10/main.h | 42 ++- g10/mainproc.c | 256 +++++++-------- g10/mdfilter.c | 10 +- g10/misc.c | 326 ++++++++++++++++--- g10/mkdtemp.c | 2 +- g10/openfile.c | 52 ++-- g10/packet.h | 61 ++-- g10/parse-packet.c | 259 ++++++++-------- g10/passphrase.c | 143 ++++----- g10/photoid.c | 24 +- g10/pipemode.c | 4 +- g10/pkclist.c | 98 +++--- g10/pkglue.c | 278 +++++++++++++++++ g10/pkglue.h | 34 ++ g10/plaintext.c | 120 +++---- g10/progress.c | 9 +- g10/pubkey-enc.c | 65 ++-- g10/revoke.c | 80 ++--- g10/seckey-cert.c | 209 ++++++++----- g10/seskey.c | 146 +++++---- g10/sig-check.c | 249 ++++++--------- g10/sign.c | 200 ++++++------ g10/signal.c | 6 +- g10/skclist.c | 66 +--- g10/status.c | 23 +- g10/tdbdump.c | 23 +- g10/tdbio.c | 131 ++++---- g10/textfilter.c | 19 +- g10/trustdb.c | 73 ++--- g10/verify.c | 22 +- include/ChangeLog | 12 + include/cipher.h | 167 ++-------- include/errors.h | 16 +- include/iobuf.h | 161 ---------- include/mpi.h | 7 +- include/ttyio.h | 40 --- include/types.h | 6 - include/util.h | 20 +- jnlib/ChangeLog | 35 ++- jnlib/Makefile.am | 1 + jnlib/dotlock.c | 122 ++++++-- jnlib/dotlock.h | 12 +- jnlib/logging.c | 17 +- jnlib/logging.h | 1 + jnlib/mischelp.h | 13 +- jnlib/stringhelp.c | 173 ++++++++++- jnlib/stringhelp.h | 8 +- jnlib/strlist.c | 20 +- jnlib/strlist.h | 5 +- jnlib/utf8conv.c | 448 +++++++++++++++++++++++++++ jnlib/utf8conv.h | 31 ++ 90 files changed, 5084 insertions(+), 2931 deletions(-) create mode 100644 g10/pkglue.c create mode 100644 g10/pkglue.h delete mode 100644 include/iobuf.h delete mode 100644 include/ttyio.h create mode 100644 jnlib/utf8conv.c create mode 100644 jnlib/utf8conv.h diff --git a/ChangeLog b/ChangeLog index d2a1453de..2efc1bf23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +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. diff --git a/TODO b/TODO index bd23ba6c0..431f2a2ea 100644 --- a/TODO +++ b/TODO @@ -57,17 +57,3 @@ might want to have an agent context for each service request * ALL ** Return IMPORT_OK status. - - - - - - - - - - - - - - diff --git a/acinclude.m4 b/acinclude.m4 index 515640225..42377380b 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,5 +1,5 @@ dnl macros to configure gnupg -dnl Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +dnl Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. dnl dnl This file is part of GnuPG. dnl @@ -36,6 +36,127 @@ AC_DEFUN(GNUPG_CHECK_TYPEDEF, ]) +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) @@ -125,12 +246,11 @@ AC_DEFUN(GNUPG_PTH_VERSION_CHECK, 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, @@ -220,6 +340,32 @@ define(GNUPG_CHECK_MLOCK, ]) +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 [copied from libgcrypt] dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, diff --git a/configure.ac b/configure.ac index 2f0bf9d64..b02e55fc6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,6 @@ # configure.ac - for GnuPG 1.9 -# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc, +# Copyright (C) 1998, 1999, 2000, 2001, 2002, +# 2003 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -22,11 +23,16 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. AC_INIT(gnupg, 1.9.0-cvs, gnupg-devel@gnupg.org) +# Set development_version to yes if the minor number is odd or you +# feel that the default check for a development version is not +# sufficient. +development_version=yes NEED_LIBGCRYPT_VERSION=1.1.8 NEED_LIBASSUAN_VERSION=0.0.1 NEED_KSBA_VERSION=0.4.6 NEED_OPENSC_VERSION=0.7.0 + PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION @@ -35,8 +41,10 @@ AM_GNU_GETTEXT_VERSION(0.11.5) AC_CONFIG_AUX_DIR(scripts) AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) +AC_CANONICAL_TARGET() AM_INIT_AUTOMAKE($PACKAGE, $VERSION) -AM_MAINTAINER_MODE + +AC_GNU_SOURCE # Some status variables to give feedback at the end of a configure run habe_libassuan=no @@ -50,24 +58,6 @@ GNUPG_BUILD_PROGRAM(agent, yes) GNUPG_BUILD_PROGRAM(scdaemon, yes) -AH_TOP([ -/* We need this, because some autoconf tests rely on this (e.g. stpcpy) - and it should be used for new programs anyway. */ -#define _GNU_SOURCE 1 -]) - -AH_BOTTOM([ -/* Some global constants. */ -#ifdef HAVE_DRIVE_LETTERS -#define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" -#else -#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" -#endif -#define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" -]) - - - AC_SUBST(PACKAGE) AC_SUBST(VERSION) AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) @@ -82,56 +72,6 @@ AC_DEFINE_UNQUOTED(NEED_KSBA_VERSION, "$NEED_KSBA_VERSION", -# Checks for programs. -missing_dir=`cd $ac_aux_dir && pwd` -AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) -AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) -AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) -AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) -AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) -AC_PROG_AWK -AC_PROG_CC -AC_PROG_CPP -AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_MAKE_SET -AC_PROG_RANLIB -#AC_ARG_PROGRAM - -if test "$GCC" = yes; then - CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" -fi - -case "${target}" in - *-*-mingw32*) - PRINTABLE_OS_NAME="MingW32" - AC_DEFINE(HAVE_DOSISH_SYSTEM,1, - [defined if we run on some of the PCDOS like systems - (DOS, Windoze. OS/2) with special properties like - no file modes]) - ;; - i?86-emx-os2 | i?86-*-os2*emx ) - PRINTABLE_OS_NAME="OS/2" - ;; - i?86-*-msdosdjgpp*) - PRINTABLE_OS_NAME="MSDOS/DJGPP" - try_dynload=no - ;; - *-linux*) - PRINTABLE_OS_NAME="GNU/Linux" - ;; -dnl let that after linux to avoid gnu-linux problems - *-gnu*) - PRINTABLE_OS_NAME="GNU/Hurd" - ;; - *) - PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` - ;; -esac -AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", - [A human readable text with the name of the OS]) - - # I know that it is in general not a good idea to evaluate bindir in # the configuration but we want to hard code the defaults into some of # the programs and doing this during a make install is not a good @@ -187,6 +127,221 @@ AC_DEFINE_UNQUOTED(GNUPG_PROTECT_TOOL, "$gnupg_protect_tool", [Name of the protect tool program]) + +AC_MSG_CHECKING([whether to enable external program execution]) +AC_ARG_ENABLE(exec, + AC_HELP_STRING([--disable-exec],[disable all external program execution]), + use_exec=$enableval) +AC_MSG_RESULT($use_exec) +if test "$use_exec" = no ; then + AC_DEFINE(NO_EXEC,1,[Define to disable all external program execution]) +fi + +if test "$use_exec" = yes ; then + AC_MSG_CHECKING([whether to enable photo ID viewing]) + AC_ARG_ENABLE(photo-viewers, + [ --disable-photo-viewers disable photo ID viewers], + [if test "$enableval" = no ; then + AC_DEFINE(DISABLE_PHOTO_VIEWER,1,[define to disable photo viewing]) + fi],enableval=yes) + gnupg_cv_enable_photo_viewers=$enableval + AC_MSG_RESULT($enableval) + + if test "$gnupg_cv_enable_photo_viewers" = yes ; then + AC_MSG_CHECKING([whether to use a fixed photo ID viewer]) + AC_ARG_WITH(photo-viewer, + [ --with-photo-viewer=FIXED_VIEWER set a fixed photo ID viewer], + [if test "$withval" = yes ; then + withval=no + elif test "$withval" != no ; then + AC_DEFINE_UNQUOTED(FIXED_PHOTO_VIEWER,"$withval", + [if set, restrict photo-viewer to this]) + fi],withval=no) + AC_MSG_RESULT($withval) + fi + + AC_MSG_CHECKING([whether to enable external keyserver helpers]) + AC_ARG_ENABLE(keyserver-helpers, + [ --disable-keyserver-helpers disable all external keyserver support], + [if test "$enableval" = no ; then + AC_DEFINE(DISABLE_KEYSERVER_HELPERS,1, + [define to disable keyserver helpers]) + fi],enableval=yes) + gnupg_cv_enable_keyserver_helpers=$enableval + AC_MSG_RESULT($enableval) + + if test "$gnupg_cv_enable_keyserver_helpers" = yes ; then + AC_MSG_CHECKING([whether LDAP keyserver support is requested]) + AC_ARG_ENABLE(ldap, + [ --disable-ldap disable LDAP keyserver interface], + try_ldap=$enableval, try_ldap=yes) + AC_MSG_RESULT($try_ldap) + + AC_MSG_CHECKING([whether HKP keyserver support is requested]) + AC_ARG_ENABLE(hkp, + [ --disable-hkp disable HKP keyserver interface], + try_hkp=$enableval, try_hkp=yes) + AC_MSG_RESULT($try_hkp) + + if test "$try_hkp" = yes ; then + AC_SUBST(GPGKEYS_HKP,"gpgkeys_hkp$EXEEXT") + fi + + AC_MSG_CHECKING([whether email keyserver support is requested]) + AC_ARG_ENABLE(mailto, + [ --disable-mailto disable email keyserver interface], + try_mailto=$enableval, try_mailto=yes) + AC_MSG_RESULT($try_mailto) + fi + + AC_MSG_CHECKING([whether keyserver exec-path is enabled]) + AC_ARG_ENABLE(keyserver-path, + [ --disable-keyserver-path disable the exec-path option for keyserver helpers], + [if test "$enableval" = no ; then + AC_DEFINE(DISABLE_KEYSERVER_PATH,1,[define to disable exec-path for keyserver helpers]) + fi],enableval=yes) + AC_MSG_RESULT($enableval) + fi + +AC_MSG_CHECKING([whether the included zlib is requested]) +AC_ARG_WITH(included-zlib, + [ --with-included-zlib use the zlib code included here], +[g10_force_zlib=yes], [g10_force_zlib=no] ) +AC_MSG_RESULT($g10_force_zlib) + +dnl +dnl Check whether we want to use Linux capabilities +dnl +AC_MSG_CHECKING([whether use of capabilities is requested]) +AC_ARG_WITH(capabilities, + [ --with-capabilities use linux capabilities [default=no]], +[use_capabilities="$withval"],[use_capabilities=no]) +AC_MSG_RESULT($use_capabilities) + + +AH_BOTTOM([ +/* Some global constants. */ +#ifdef HAVE_DRIVE_LETTERS +#define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" +#else +#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg2" +#endif +#define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" + +#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) +#define EXEC_TEMPFILE_ONLY +#endif + +/* Tell libgcrypt not to use its own libgpg-error implementation. */ +#define USE_LIBGPG_ERROR 1 + +#include "g10defs.h" + +]) + +AM_MAINTAINER_MODE + +# Checks for programs. +AC_PROG_MAKE_SET +AM_SANITY_CHECK +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_RANLIB +AC_CHECK_TOOL(AR, ar, :) +AC_PATH_PROG(PERL,"perl") +AC_ISC_POSIX +AC_SYS_LARGEFILE +AC_CHECK_PROG(DOCBOOK_TO_MAN, docbook-to-man, yes, no) +AM_CONDITIONAL(HAVE_DOCBOOK_TO_MAN, test "$ac_cv_prog_DOCBOOK_TO_MAN" = yes) +GNUPG_CHECK_FAQPROG +GNUPG_CHECK_DOCBOOK_TO_TEXI + + +try_gettext=yes +have_dosish_system=no +case "${target}" in + *-*-mingw32*) + # special stuff for Windoze NT + ac_cv_have_dev_random=no + AC_DEFINE(USE_ONLY_8DOT3,1, + [set this to limit filenames to the 8.3 format]) + AC_DEFINE(HAVE_DRIVE_LETTERS,1, + [defined if we must run on a stupid file system]) + AC_DEFINE(USE_SIMPLE_GETTEXT,1, + [because the Unix gettext has too much overhead on + MingW32 systems and these systems lack Posix functions, + we use a simplified version of gettext]) + have_dosish_system=yes + try_gettext="no" + ;; + i?86-emx-os2 | i?86-*-os2*emx ) + # OS/2 with the EMX environment + ac_cv_have_dev_random=no + AC_DEFINE(HAVE_DRIVE_LETTERS) + have_dosish_system=yes + try_gettext="no" + ;; + + i?86-*-msdosdjgpp*) + # DOS with the DJGPP environment + ac_cv_have_dev_random=no + AC_DEFINE(HAVE_DRIVE_LETTERS) + have_dosish_system=yes + try_gettext="no" + ;; + + *-*-freebsd*) + # FreeBSD + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + ;; + + *-*-hpux*) + if test -z "$GCC" ; then + CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" + fi + ;; + *-dec-osf4*) + if test -z "$GCC" ; then + # Suppress all warnings + # to get rid of the unsigned/signed char mismatch warnings. + CFLAGS="$CFLAGS -w" + fi + ;; + *-dec-osf5*) + if test -z "$GCC" ; then + # Use the newer compiler `-msg_disable ptrmismatch' to + # get rid of the unsigned/signed char mismatch warnings. + # Using this may hide other pointer mismatch warnings, but + # it at least lets other warning classes through + CFLAGS="$CFLAGS -msg_disable ptrmismatch" + fi + ;; + m68k-atari-mint) + ;; + *) + ;; +esac + +if test "$have_dosish_system" = yes; then + AC_DEFINE(HAVE_DOSISH_SYSTEM,1, + [defined if we run on some of the PCDOS like systems + (DOS, Windoze. OS/2) with special properties like + no file modes]) +fi +AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) + + # # Checks for libraries. # @@ -290,11 +445,199 @@ fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) -AM_GNU_GETTEXT + +dnl Must check for network library requirements before doing link tests +dnl for ldap, for example. If ldap libs are static (or dynamic and without +dnl ELF runtime link paths), then link will fail and LDAP support won't +dnl be detected. + +AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname, + [NETLIBS="-lnsl $NETLIBS"])) +AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt, + [NETLIBS="-lsocket $NETLIBS"])) + +dnl Now try for the resolver functions so we can use DNS SRV + +AC_ARG_ENABLE(dns-srv, + AC_HELP_STRING([--disable-dns-srv],[disable the use of DNS SRV in HKP]), + use_dns_srv=$enableval,use_dns_srv=yes) + +if test x"$try_hkp" = xyes && test x"$use_dns_srv" = xyes ; then + _srv_save_libs=$LIBS + LIBS="" + # the double underscore thing is a glibc-ism? + AC_SEARCH_LIBS(res_query,resolv bind,, + AC_SEARCH_LIBS(__res_query,resolv bind,,use_dns_srv=no)) + AC_SEARCH_LIBS(dn_expand,resolv bind,, + AC_SEARCH_LIBS(__dn_expand,resolv bind,,use_dns_srv=no)) + AC_SEARCH_LIBS(dn_skipname,resolv bind,, + AC_SEARCH_LIBS(__dn_skipname,resolv bind,,use_dns_srv=no)) + + if test x"$use_dns_srv" = xyes ; then + AC_DEFINE(USE_DNS_SRV,1,[define to use DNS SRV]) + SRVLIBS=$LIBS + else + AC_MSG_WARN([Resolver functions not found. Disabling DNS SRV.]) + fi + LIBS=$_srv_save_libs +fi + +AC_SUBST(SRVLIBS) + +# Try and link a LDAP test program to weed out unusable LDAP +# libraries. -lldap [-llber [-lresolv]] is for OpenLDAP. OpenLDAP in +# general is terrible with creating weird dependencies. If all else +# fails, the user can play guess-the-dependency by using something +# like ./configure LDAPLIBS="-Lfoo -lbar" + +if test "$try_ldap" = yes ; then + for MY_LDAPLIBS in ${LDAPLIBS+"$LDAPLIBS"} "-lldap" "-lldap -llber" "-lldap -llber -lresolv"; do + _ldap_save_libs=$LIBS + LIBS="$MY_LDAPLIBS $NETLIBS $LIBS" + + AC_MSG_CHECKING([whether LDAP via \"$MY_LDAPLIBS\" is present and sane]) + AC_TRY_LINK([#include <ldap.h>],[ldap_open("foobar",1234);], + [gnupg_cv_func_ldap_init=yes],[gnupg_cv_func_ldap_init=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldap_init]) + + if test $gnupg_cv_func_ldap_init = no; then + AC_MSG_CHECKING([whether I can make LDAP be sane with lber.h]) + AC_TRY_LINK([#include <lber.h> +#include <ldap.h>],[ldap_open("foobar",1234);], + [gnupg_cv_func_ldaplber_init=yes],[gnupg_cv_func_ldaplber_init=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldaplber_init]) + fi + + if test "$gnupg_cv_func_ldaplber_init" = yes ; then + AC_DEFINE(NEED_LBER_H,1,[Define if the LDAP library requires including lber.h before ldap.h]) + fi + + if test "$gnupg_cv_func_ldap_init" = yes || \ + test "$gnupg_cv_func_ldaplber_init" = yes ; then + LDAPLIBS=$MY_LDAPLIBS + GPGKEYS_LDAP="gpgkeys_ldap$EXEEXT" + + AC_MSG_CHECKING([whether LDAP supports ldap_get_option]) + + if test "$gnupg_cv_func_ldap_init" = yes ; then + AC_TRY_LINK([#include <ldap.h>], + [ldap_get_option((void *)0,0,(void *)0);], + [gnupg_cv_func_ldap_get_option=yes], + [gnupg_cv_func_ldap_get_option=no]) + else + AC_TRY_LINK([#include <lber.h> +#include <ldap.h>],[ldap_get_option((void *)0,0,(void *)0);], + [gnupg_cv_func_ldap_get_option=yes], + [gnupg_cv_func_ldap_get_option=no]) + fi + + AC_MSG_RESULT([$gnupg_cv_func_ldap_get_option]) + + if test "$gnupg_cv_func_ldap_get_option" = yes ; then + AC_DEFINE(HAVE_LDAP_GET_OPTION,1,[Define if the LDAP library has ldap_get_option]) + else + AC_MSG_CHECKING([whether LDAP supports ld_errno]) + + if test "$gnupg_cv_func_ldap_init" = yes ; then + AC_TRY_COMPILE([#include <ldap.h>], + [LDAP *ldap; ldap->ld_errno;], + [gnupg_cv_func_ldap_ld_errno=yes], + [gnupg_cv_func_ldap_ld_errno=no]) + else + AC_TRY_LINK([#include <lber.h> +#include <ldap.h>],[LDAP *ldap; ldap->ld_errno;], + [gnupg_cv_func_ldap_ld_errno=yes], + [gnupg_cv_func_ldap_ld_errno=no]) + fi + + AC_MSG_RESULT([$gnupg_cv_func_ldap_ld_errno]) + + if test "$gnupg_cv_func_ldap_ld_errno" = yes ; then + AC_DEFINE(HAVE_LDAP_LD_ERRNO,1,[Define if the LDAP library supports ld_errno]) + fi + fi + fi + + LIBS=$_ldap_save_libs + + if test "$GPGKEYS_LDAP" != "" ; then break; fi + done +fi + +AC_SUBST(GPGKEYS_LDAP) +AC_SUBST(LDAPLIBS) + +dnl This isn't necessarily sendmail itself, but anything that gives a +dnl sendmail-ish interface to the outside world. That includes qmail, +dnl postfix, etc. Basically, anything that can handle "sendmail -t". + +if test "$try_mailto" = yes ; then + AC_ARG_WITH(mailprog,[ --with-mailprog=NAME use "NAME -t" for mail transport],,with_mailprog=yes) + + if test "$with_mailprog" = yes ; then + AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib) + if test "$ac_cv_path_SENDMAIL" ; then + GPGKEYS_MAILTO="gpgkeys_mailto" + fi + elif test "$with_mailprog" != no ; then + AC_MSG_CHECKING([for a mail transport program]) + AC_SUBST(SENDMAIL,$with_mailprog) + AC_MSG_RESULT($with_mailprog) + GPGKEYS_MAILTO="gpgkeys_mailto" + fi +fi + +AC_SUBST(GPGKEYS_MAILTO) + +case "${target}" in + *-*-mingw32*) + PRINTABLE_OS_NAME="MingW32" + ;; + *-*-cygwin*) + PRINTABLE_OS_NAME="Cygwin" + ;; + i?86-emx-os2 | i?86-*-os2*emx ) + PRINTABLE_OS_NAME="OS/2" + ;; + i?86-*-msdosdjgpp*) + PRINTABLE_OS_NAME="MSDOS/DJGPP" + try_dynload=no + ;; + *-linux*) + PRINTABLE_OS_NAME="GNU/Linux" + ;; +dnl let that after linux to avoid gnu-linux problems + *-gnu*) + PRINTABLE_OS_NAME="GNU/Hurd" + ;; + *) + PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` + ;; +esac +AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", + [A human readable text with the name of the OS]) + + +if test "$try_gettext" = yes; then + AM_GNU_GETTEXT(,[need-ngettext]) + + # gettext requires some extra checks. These really should be part of + # the basic AM_GNU_GETTEXT macro. TODO: move other gettext-specific + # function checks to here. + + AC_CHECK_FUNCS(strchr) +else + USE_NLS=no + USE_INCLUDED_LIBINTL=no + BUILD_INCLUDED_LIBINTL=no + AC_SUBST(USE_NLS) + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(BUILD_INCLUDED_LIBINTL) +fi # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([string.h locale.h]) +AC_CHECK_HEADERS(string.h unistd.h langinfo.h termio.h locale.h) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -303,34 +646,270 @@ AC_TYPE_SIZE_T AC_TYPE_SIGNAL AC_DECL_SYS_SIGLIST +GNUPG_CHECK_ENDIAN + GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF) GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) +GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF) +GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF) + +AC_CHECK_SIZEOF(unsigned short) +AC_CHECK_SIZEOF(unsigned int) +AC_CHECK_SIZEOF(unsigned long) +AC_CHECK_SIZEOF(unsigned long long) +AC_CHECK_SIZEOF(uint64_t) + +if test "$ac_cv_sizeof_unsigned_short" = "0" \ + || test "$ac_cv_sizeof_unsigned_int" = "0" \ + || test "$ac_cv_sizeof_unsigned_long" = "0"; then + AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); +fi + +dnl Do we have any 64-bit data types? +if test "$ac_cv_sizeof_unsigned_int" != "8" \ + && test "$ac_cv_sizeof_unsigned_long" != "8" \ + && test "$ac_cv_sizeof_unsigned_long_long" != "8" \ + && test "$ac_cv_sizeof_uint64_t" != "8"; then + AC_MSG_WARN([No 64-bit types. Disabling TIGER/192, SHA-384, and SHA-512]) +else + if test x"$use_tiger192" = xyes ; then + AC_SUBST(TIGER_O,tiger.o) + AC_DEFINE(USE_TIGER192,1,[Define to include the TIGER/192 digest]) + fi + + if test "$use_old_tiger192" = yes ; then + AC_SUBST(TIGER_O,tiger.o) + AC_DEFINE(USE_TIGER192,1,[Define to include the TIGER/192 digest]) + AC_DEFINE(USE_OLD_TIGER,1,[Define to use the old fake OID for TIGER/192 digest support]) + fi + + if test x"$use_sha512" = xyes ; then + AC_SUBST(SHA512_O,sha512.o) + AC_DEFINE(USE_SHA512,1,[Define to include the SHA-384 and SHA-512 digests]) + fi +fi GNUPG_SYS_SO_PEERCRED # Checks for library functions. +AC_FUNC_FSEEKO +AC_FUNC_VPRINTF +AC_FUNC_FORK +AC_CHECK_FUNCS(strerror stpcpy strsep strlwr tcgetattr strtoul mmap) +AC_CHECK_FUNCS(strcasecmp strncasecmp ctermid times) +AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) +AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) +AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat) # These are needed by libjnlib - fixme: we should have a macros for them AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) AC_CHECK_FUNCS(flockfile funlockfile) -AC_CHECK_FUNCS(sigaction sigprocmask) - AC_REPLACE_FUNCS(vasprintf) AC_REPLACE_FUNCS(fopencookie) -# FIXME: Print a warning when fopencookie is not available. AC_REPLACE_FUNCS(mkdtemp) AC_REPLACE_FUNCS(fseeko ftello) AC_REPLACE_FUNCS(isascii) AC_REPLACE_FUNCS(putc_unlocked) +# +# check for gethrtime and run a testprogram to see whether +# it is broken. It has been reported that some Solaris and HP UX systems +# raise an SIGILL +# +AC_CACHE_CHECK([for gethrtime], + [gnupg_cv_func_gethrtime], + [AC_TRY_LINK([#include <sys/times.h>],[ + hrtime_t tv; + tv = gethrtime(); + ], + [gnupg_cv_func_gethrtime=yes], + [gnupg_cv_func_gethrtime=no]) + ]) +if test $gnupg_cv_func_gethrtime = yes; then + AC_DEFINE([HAVE_GETHRTIME], 1, + [Define if you have the `gethrtime(2)' function.]) + AC_CACHE_CHECK([whether gethrtime is broken], + [gnupg_cv_func_broken_gethrtime], + [AC_TRY_RUN([ + #include <sys/times.h> + int main () { + hrtime_t tv; + tv = gethrtime(); + } + ], + [gnupg_cv_func_broken_gethrtime=no], + [gnupg_cv_func_broken_gethrtime=yes], + [gnupg_cv_func_broken_gethrtime=assume-no]) + ]) + if test $gnupg_cv_func_broken_gethrtime = yes; then + AC_DEFINE([HAVE_BROKEN_GETHRTIME], 1, + [Define if `gethrtime(2)' does not work correctly i.e. issues a SIGILL.]) + fi +fi + + +GNUPG_CHECK_MLOCK +GNUPG_FUNC_MKDIR_TAKES_ONE_ARG + +dnl +dnl Check whether we can use Linux capabilities as requested +dnl +if test "$use_capabilities" = "yes" ; then +use_capabilities=no +AC_CHECK_HEADERS(sys/capability.h) +if test "$ac_cv_header_sys_capability_h" = "yes" ; then + AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1) + if test "$ac_cv_lib_cap_cap_init" = "yes"; then + AC_DEFINE(USE_CAPABILITIES,1, + [define if capabilities should be used]) + AC_SUBST(CAPLIBS,"-lcap") + use_capabilities=yes + fi +fi +if test "$use_capabilities" = "no" ; then + AC_MSG_WARN([[ +*** +*** The use of capabilities on this system is not possible. +*** You need a recent Linux kernel and some patches: +*** fcaps-2.2.9-990610.patch (kernel patch for 2.2.9) +*** fcap-module-990613.tar.gz (kernel module) +*** libcap-1.92.tar.gz (user mode library and utilities) +*** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN +*** set (filesystems menu). Be warned: This code is *really* ALPHA. +***]]) +fi +fi + + +# Sanity check regex. Tests adapted from mutt. + +AC_MSG_CHECKING([whether regular expression support is requested]) +AC_ARG_ENABLE(regex, +[ --disable-regex do not handle regular expressions in trust sigs], + use_regex=$enableval, use_regex=yes) +AC_MSG_RESULT($use_regex) + +if test "$use_regex" = yes ; then + AC_MSG_CHECKING([whether the included regex lib is requested]) + AC_ARG_WITH(included-regex, + [ --with-included-regex use the included GNU regex library], + [gnupg_cv_included_regex=yes],[gnupg_cv_included_regex=no]) + AC_MSG_RESULT($gnupg_cv_included_regex) + + if test $gnupg_cv_included_regex = no ; then + # Does the system have regex functions at all? + AC_CHECK_FUNC(regcomp,gnupg_cv_included_regex=no, + gnupg_cv_included_regex=yes) + fi + + if test $gnupg_cv_included_regex = no ; then + AC_CACHE_CHECK([whether your system's regexp library is broken], + [gnupg_cv_regex_broken], + AC_TRY_RUN([ +#include <unistd.h> +#include <regex.h> +main() { regex_t blah ; regmatch_t p; p.rm_eo = p.rm_eo; return regcomp(&blah, "foo.*bar", REG_NOSUB) || regexec (&blah, "foobar", 0, NULL, 0); }], + gnupg_cv_regex_broken=no, gnupg_cv_regex_broken=yes, gnupg_cv_regex_broken=yes)) + + if test $gnupg_cv_regex_broken = yes ; then + AC_MSG_WARN(your regex is broken - using the included GNU regex instead.) + gnupg_cv_included_regex=yes + fi + fi + + if test $gnupg_cv_included_regex = yes; then + AC_DEFINE(USE_GNU_REGEX,1,[ Define if you want to use the included regex lib ]) + AC_SUBST(REGEX_O,regex.o) + fi +else + + AC_DEFINE(DISABLE_REGEX,1,[ Define to disable regular expression support ]) +fi + +dnl Do we have zlib? Must do it here because Solaris failed +dnl when compiling a conftest (due to the "-lz" from LIBS). +use_local_zlib=yes +if test "$g10_force_zlib" = "yes"; then + : +else + _cppflags="${CPPFLAGS}" + _ldflags="${LDFLAGS}" + + AC_ARG_WITH(zlib, + [ --with-zlib=DIR use libz in DIR],[ + if test -d "$withval"; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + ]) + + AC_CHECK_HEADER(zlib.h, + AC_CHECK_LIB(z, deflateInit2_, + use_local_zlib=no + LIBS="$LIBS -lz", + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) +fi + +if test "$use_local_zlib" = yes ; then + AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, true) + AC_CONFIG_LINKS(zlib.h:zlib/zlib.h zconf.h:zlib/zconf.h ) + ZLIBS="../zlib/libzlib.a" +else + AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, false) + ZLIBS= +fi +AC_SUBST(ZLIBS) + +# Allow users to append something to the version string without +# flagging it as development version. The user version parts is +# considered everything after a dash. +if test "$development_version" != yes; then + changequote(,)dnl + tmp_pat='[a-zA-Z]' + changequote([,])dnl + if echo "$VERSION" | sed 's/-.*//' | grep "$tmp_pat" >/dev/null ; then + development_version=yes + fi +fi +if test "$development_version" = yes; then + AC_DEFINE(IS_DEVELOPMENT_VERSION,1, + [Defined if this is not a regular release]) +fi + +AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) + +GNUPG_CHECK_GNUMAKE + +# add some extra libs here so that previous tests don't fail for +# mysterious reasons - the final link step should bail out. +case "${target}" in + *-*-mingw32*) + LIBS="$LIBS -lwsock32" + ;; + *) + ;; +esac + + +if test "$GCC" = yes; then + if test "$USE_MAINTAINER_MODE" = "yes"; then + CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" + else + CFLAGS="$CFLAGS -Wall" + fi +fi + +AC_SUBST(NETLIBS) + + # We use jnlib, so tell other modules about it AC_DEFINE(HAVE_JNLIB_LOGGING, 1, [Defined if jnlib style logging fucntions are available]) - # # Decide what to build # @@ -369,6 +948,64 @@ AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") +AC_CONFIG_COMMANDS(g10defs.h,[[ +cat >g10defs.tmp <<G10EOF +/* Generated automatically by configure */ +/* FIXME: Shouldn't we replace GNUPG_HOMEDIR by GNUPG_DEFAULT_HOMEDIR + and we propably can get rid of g10defs.h */ +#ifdef HAVE_DRIVE_LETTERS +/*#define G10_LOCALEDIR "c:\\\\lib\\\\gnupg\\\\locale"*/ +#define GNUPG_LIBDIR "c:\\\\lib\\\\gnupg" +#define GNUPG_LIBEXECDIR "c:\\\\lib\\\\gnupg" +#define GNUPG_DATADIR "c:\\\\lib\\\\gnupg" +#define GNUPG_HOMEDIR "c:\\\\gnupg" +#else +/*#define G10_LOCALEDIR "${datadir}/locale"*/ +#define GNUPG_LIBDIR "${libdir}/gnupg" +#define GNUPG_DATADIR "${datadir}/gnupg" +#ifdef __VMS +#define GNUPG_HOMEDIR "/SYS\$LOGIN/gnupg" +#else +#define GNUPG_HOMEDIR "~/.gnupg2" +#endif +#endif +/* those are here to be redefined by handcrafted g10defs.h. + Please note that the string version must not contain more + than one character because the using code assumes strlen()==1 */ +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\\\' +#define EXTSEP_C '.' +#define DIRSEP_S "\\\\" +#define EXTSEP_S "." +#else +#define DIRSEP_C '/' +#define EXTSEP_C '.' +#define DIRSEP_S "/" +#define EXTSEP_S "." +#endif +/* This is the same as VERSION, but should be overridden if the + platform cannot handle things like dots '.' in filenames. */ +#define SAFE_VERSION VERSION +G10EOF +## Do we really need the following? It defines BYTES_PER-MPI_LIMB +## cat mpi/mpi-asm-defs.h >>g10defs.tmp +if cmp -s g10defs.h g10defs.tmp 2>/dev/null; then + echo "g10defs.h is unchanged" + rm -f g10defs.tmp +else + rm -f g10defs.h + mv g10defs.tmp g10defs.h + echo "g10defs.h created" +fi +]],[[ +prefix=$prefix +exec_prefix=$exec_prefix +libdir=$libdir +libexecdir=$libexecdir +datadir=$datadir +DATADIRNAME=$DATADIRNAME +]]) + AC_CONFIG_FILES([ m4/Makefile Makefile po/Makefile.in @@ -389,6 +1026,8 @@ AC_OUTPUT echo " GnuPG v${VERSION} has been configured as follows: + Platform: $PRINTABLE_OS_NAME ($target) + OpenPGP: $build_gpg S/MIME: $build_gpgsm Agent: $build_agent $build_agent_threaded diff --git a/g10/ChangeLog b/g10/ChangeLog index 176ec10fa..1ff227fdc 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,4 +1,71 @@ -2003-06-04 Werner Koch <wk@gnupg.org> +2003-06-18 Werner Koch <wk@gnupg.org> + + Finished the bulk of changes for gnupg 1.9. This included + switching to libgcrypt functions, using shared error codes from + libgpg-error, replacing the old functions we used to have in + ../util by those in ../jnlib and ../common, renaming the malloc + functions and a couple of types. Note, that not all changes are + listed below becuause they are too similar and done at far too + many places. As of today the code builds using the current + libgcrypt from CVS but it is very unlikely that it actually works. + + * sig-check.c (cmp_help): Removed. Was never used. + + * pkglue.c: New. Most stuff taken from gnupg 1.1.2. + * pkglue.h: New. + + * misc.c (pull_in_libs): Removed. + + * keygen.c (count_chr): New. + (ask_user_id): Removed faked RNG support. + + * misc.c (openpgp_md_map_name,openpgp_cipher_map_name) + (openpgp_pk_map_name): New. + + * skclist.c (build_sk_list): Removed faked RNG support. + (is_insecure): Removed. + + * comment.c (make_mpi_comment_node): Use gcry MPI print function. + + * keyid.c (v3_keyid): New. + + * misc.c (mpi_write,mpi_write_opaque,mpi_read,mpi_read_opaque) + (mpi_print): New. Taken from gnupg 1.1.2. + (checksum_mpi): Replaced by implementation from 1.1.2. + + * g10.c (my_strusage): Renamed from strusage and return NULL + instead calling a default function. + (add_to_strlist2): New. Taken from ../util/strgutil.c of gnupg 1.2. + + * plaintext.c (handle_plaintext): New arg CREATE_FILE to cope with + the fact that gpg-error does not have this error code anymore. + + * mainproc.c (symkey_decrypt_sesskey): Ditto. + + * seskey.c (make_session_key): Adjusted for use with libgcrypt. + (encode_session_key): Ditto. + (do_encode_md): Ditto. + (encode_md_value): Ditto. + + * keyring.c: Use libgpg-error instead of READ_ERROR etc. + + * g10.c: Adjusted all algorithm name/id mapping functions. + (set_debug): Pass MPI and CRYPTO debug values to libgcrypt. + + * Makefile.am (INCLUDES): Define LOCALEDIR and the default error + source. + + * g10.c (i18n_init): s/G10_LOCALEDIR/LOCALEDIR/. + + Renamed m_alloc et al to xmalloc et al. + s/g10_errstr/gpg_strerror/ + s/MPI/gcry_mpi_t/ + Adjusted all md_open calls to the libgcrypt API. + + * build-packet.c (do_comment): Return error code from iobuf write + function. + (do_user_id): Ditto. + (do_public_key): Ditto. * Makefile.am: Add new files, link gpg with libgpg-error. * g10.c, options.h: New option --agent-program. diff --git a/g10/Makefile.am b/g10/Makefile.am index 91438741a..6940be67a 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -19,16 +19,17 @@ ## Process this file with automake to produce Makefile.in -INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl +localedir = $(datadir)/locale +INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/include -I$(top_srcdir)/intl -DLOCALEDIR=\"$(localedir)\" + EXTRA_DIST = options.skel # it seems that we can't use this with automake 1.5 #OMIT_DEPENDENCIES = zlib.h zconf.h libexecdir = @libexecdir@/@PACKAGE@ -# FIXME: Windows support currently not enabled -#if ! HAVE_DOSISH_SYSTEM -#AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" -#endif -needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a +if ! HAVE_DOSISH_SYSTEM +AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" +endif +needed_libs = ../common/libcommon.a ../jnlib/libjnlib.a #noinst_PROGRAMS = gpgd bin_PROGRAMS = gpg gpgv @@ -62,6 +63,7 @@ common_source = \ plaintext.c \ sig-check.c \ keylist.c \ + pkglue.c pkglue.h \ signal.c gpg_SOURCES = g10.c \ @@ -108,8 +110,9 @@ gpgv_SOURCES = gpgv.c \ # ks-db.h \ # $(common_source) -LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ -gpg_LDADD = $(LDADD) @DLLIBS@ @EGDLIBS@ -lgpg-error +LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ +gpg_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error +gpgv_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error $(PROGRAMS): $(needed_libs) diff --git a/g10/armor.c b/g10/armor.c index f00742295..c6930e22a 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -27,6 +27,7 @@ #include <assert.h> #include <ctype.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "memory.h" @@ -192,7 +193,7 @@ is_armored( const byte *buf ) * filter to do further processing. */ int -use_armor_filter( IOBUF a ) +use_armor_filter( iobuf_t a ) { byte buf[1]; int n; @@ -337,7 +338,7 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) int hashes=0; unsigned int len2; - len2 = check_trailing_ws( line, len ); + len2 = length_sans_trailing_ws( line, len ); if( !len2 ) { afx->buffer_pos = len2; /* (it is not the fine way to do it here) */ return 0; /* WS only: same as empty line */ @@ -376,7 +377,7 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) /* figure out whether the data is armored or not */ static int -check_input( armor_filter_context_t *afx, IOBUF a ) +check_input( armor_filter_context_t *afx, iobuf_t a ) { int rc = 0; int i; @@ -418,7 +419,7 @@ check_input( armor_filter_context_t *afx, IOBUF a ) if( hdr_line == BEGIN_SIGNED_MSG_IDX ) { if( afx->in_cleartext ) { log_error(_("nested clear text signatures\n")); - rc = G10ERR_INVALID_ARMOR; + rc = GPG_ERR_INV_ARMOR; } afx->in_cleartext = 1; } @@ -448,7 +449,7 @@ check_input( armor_filter_context_t *afx, IOBUF a ) i = parse_header_line( afx, line, len ); if( i <= 0 ) { if( i ) - rc = G10ERR_INVALID_ARMOR; + rc = GPG_ERR_INV_ARMOR; break; } } @@ -476,7 +477,7 @@ check_input( armor_filter_context_t *afx, IOBUF a ) * not implemented/checked. */ static int -fake_packet( armor_filter_context_t *afx, IOBUF a, +fake_packet( armor_filter_context_t *afx, iobuf_t a, size_t *retn, byte *buf, size_t size ) { int rc = 0; @@ -615,12 +616,12 @@ invalid_crc(void) if ( opt.ignore_crc_error ) return 0; log_inc_errorcount(); - return G10ERR_INVALID_ARMOR; + return GPG_ERR_INV_ARMOR; } static int -radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, +radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn, byte *buf, size_t size ) { byte val; @@ -785,11 +786,11 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, rc = 0; else if( rc == 2 ) { log_error(_("premature eof (in Trailer)\n")); - rc = G10ERR_INVALID_ARMOR; + rc = GPG_ERR_INV_ARMOR; } else { log_error(_("error in trailer line\n")); - rc = G10ERR_INVALID_ARMOR; + rc = GPG_ERR_INV_ARMOR; } #endif } @@ -808,7 +809,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, */ int armor_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; armor_filter_context_t *afx = opaque; @@ -1081,7 +1082,7 @@ armor_filter( void *opaque, int control, if( afx->qp_detected ) log_error(_("quoted printable character in armor - " "probably a buggy MTA has been used\n") ); - m_free( afx->buffer ); + xfree ( afx->buffer ); afx->buffer = NULL; } else if( control == IOBUFCTRL_DESC ) @@ -1098,7 +1099,7 @@ make_radix64_string( const byte *data, size_t len ) { char *buffer, *p; - buffer = p = m_alloc( (len+2)/3*4 + 1 ); + buffer = p = xmalloc ( (len+2)/3*4 + 1 ); for( ; len >= 3 ; len -= 3, data += 3 ) { *p++ = bintoasc[(data[0] >> 2) & 077]; *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; @@ -1158,14 +1159,14 @@ unarmor_pump_new (void) if( !is_initialized ) initialize(); - x = m_alloc_clear (sizeof *x); + x = xcalloc (1,sizeof *x); return x; } void unarmor_pump_release (UnarmorPump x) { - m_free (x); + xfree (x); } /* diff --git a/g10/build-packet.c b/g10/build-packet.c index 86aa07dc2..a3177525e 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -25,6 +25,7 @@ #include <string.h> #include <assert.h> +#include "gpg.h" #include "packet.h" #include "errors.h" #include "iobuf.h" @@ -35,28 +36,28 @@ #include "options.h" -static int do_comment( IOBUF out, int ctb, PKT_comment *rem ); -static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); -static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); -static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk ); -static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); -static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); +static int do_comment( iobuf_t out, int ctb, PKT_comment *rem ); +static int do_user_id( iobuf_t out, int ctb, PKT_user_id *uid ); +static int do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ); +static int do_secret_key( iobuf_t out, int ctb, PKT_secret_key *pk ); +static int do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ); +static int do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ); static u32 calc_plaintext( PKT_plaintext *pt ); -static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); -static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); -static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); -static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); -static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); -static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); +static int do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ); +static int do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ); +static int do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ); +static int do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ); +static int do_signature( iobuf_t out, int ctb, PKT_signature *sig ); +static int do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ); static int calc_header_length( u32 len, int new_ctb ); -static int write_16(IOBUF inp, u16 a); -static int write_32(IOBUF inp, u32 a); -static int write_header( IOBUF out, int ctb, u32 len ); -static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); -static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ); -static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); -static int write_version( IOBUF out, int ctb ); +static int write_16(iobuf_t inp, u16 a); +static int write_32(iobuf_t inp, u32 a); +static int write_header( iobuf_t out, int ctb, u32 len ); +static int write_sign_packet_header( iobuf_t out, int ctb, u32 len ); +static int write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode ); +static int write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ); +static int write_version( iobuf_t out, int ctb ); /**************** * Build a packet and write it to INP @@ -65,7 +66,7 @@ static int write_version( IOBUF out, int ctb ); * Note: Caller must free the packet */ int -build_packet( IOBUF out, PACKET *pkt ) +build_packet( iobuf_t out, PACKET *pkt ) { int new_ctb=0, rc=0, ctb; int pkttype; @@ -179,51 +180,56 @@ calc_packet_length( PACKET *pkt ) } static void -write_fake_data( IOBUF out, MPI a ) +write_fake_data( iobuf_t out, gcry_mpi_t a ) { if( a ) { - int i; + unsigned int n; void *p; - p = mpi_get_opaque( a, &i ); - iobuf_write( out, p, i ); + assert( gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque (a, &n); + iobuf_write (out, p, (n+7)/8); } } static int -do_comment( IOBUF out, int ctb, PKT_comment *rem ) +do_comment (iobuf_t out, int ctb, PKT_comment *rem) { - if( opt.sk_comments ) { - write_header(out, ctb, rem->len); - if( iobuf_write( out, rem->data, rem->len ) ) - return G10ERR_WRITE_FILE; + int rc = 0; + + if (opt.sk_comments) + { + write_header(out, ctb, rem->len); + rc = iobuf_write( out, rem->data, rem->len ); } - return 0; + return rc; } static int -do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) +do_user_id( iobuf_t out, int ctb, PKT_user_id *uid ) { - if( uid->attrib_data ) { - write_header(out, ctb, uid->attrib_len); - if( iobuf_write( out, uid->attrib_data, uid->attrib_len ) ) - return G10ERR_WRITE_FILE; + int rc; + + if (uid->attrib_data) + { + write_header (out, ctb, uid->attrib_len); + rc = iobuf_write (out, uid->attrib_data, uid->attrib_len ); } - else { - write_header(out, ctb, uid->len); - if( iobuf_write( out, uid->name, uid->len ) ) - return G10ERR_WRITE_FILE; + else + { + write_header (out, ctb, uid->len); + rc = iobuf_write (out, uid->name, uid->len ); } - return 0; + return rc; } static int -do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) +do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ) { int rc = 0; int n, i; - IOBUF a = iobuf_temp(); + iobuf_t a = iobuf_temp(); if( !pk->version ) iobuf_put( a, 3 ); @@ -246,8 +252,7 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) mpi_write(a, pk->pkey[i] ); write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; + rc = iobuf_write_temp (out, a); iobuf_close(a); return rc; @@ -265,7 +270,7 @@ hash_public_key( MD_HANDLE md, PKT_public_key *pk ) int ctb; ulong pktlen; int c; - IOBUF a = iobuf_temp(); + iobuf_t a = iobuf_temp(); #if 0 FILE *fp = fopen("dump.pk", "a"); int i=0; @@ -278,7 +283,7 @@ hash_public_key( MD_HANDLE md, PKT_public_key *pk ) pkt.pkttype = PKT_PUBLIC_KEY; pkt.pkt.public_key = pk; if( (rc = build_packet( a, &pkt )) ) - log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc)); + log_fatal("build public_key for hashing failed: %s\n", gpg_strerror (rc)); if( !(pk->version == 3 && pk->pubkey_algo == 16) ) { /* skip the constructed header but don't do this for our very old @@ -309,10 +314,10 @@ hash_public_key( MD_HANDLE md, PKT_public_key *pk ) } } /* hash a header */ - md_putc( md, 0x99 ); + gcry_md_putc ( md, 0x99 ); pktlen &= 0xffff; /* can't handle longer packets */ - md_putc( md, pktlen >> 8 ); - md_putc( md, pktlen & 0xff ); + gcry_md_putc ( md, pktlen >> 8 ); + gcry_md_putc ( md, pktlen & 0xff ); } /* hash the packet body */ while( (c=iobuf_get(a)) != -1 ) { @@ -323,7 +328,7 @@ hash_public_key( MD_HANDLE md, PKT_public_key *pk ) i=0; } #endif - md_putc( md, c ); + gcry_md_putc ( md, c ); } #if 0 putc('\n', fp); @@ -334,11 +339,11 @@ hash_public_key( MD_HANDLE md, PKT_public_key *pk ) static int -do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) +do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) { int rc = 0; int i, nskey, npkey; - IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */ + iobuf_t a = iobuf_temp(); /* build in a self-enlarging buffer */ /* Write the version number - if none is specified, use 3 */ if( !sk->version ) @@ -366,7 +371,7 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) /* If we don't have any public parameters - which is the case if we don't know the algorithm used - the parameters are stored as - one blob in a faked (opaque) MPI */ + one blob in a faked (opaque) gcry_mpi_t */ if( !npkey ) { write_fake_data( a, sk->skey[0] ); goto leave; @@ -423,19 +428,19 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) else if( sk->is_protected && sk->version >= 4 ) { /* The secret key is protected - write it out as it is */ byte *p; - assert( mpi_is_opaque( sk->skey[npkey] ) ); - p = mpi_get_opaque( sk->skey[npkey], &i ); - iobuf_write(a, p, i ); + assert( gcry_mpi_get_flag( sk->skey[npkey], GCRYMPI_FLAG_OPAQUE ) ); + p = gcry_mpi_get_opaque( sk->skey[npkey], &i ); + iobuf_write(a, p, (i+7)/8 ); } else if( sk->is_protected ) { - /* The secret key is protected te old v4 way. */ + /* The secret key is protected the old v4 way. */ for( ; i < nskey; i++ ) { byte *p; - int ndata; + size_t n; - assert (mpi_is_opaque (sk->skey[i])); - p = mpi_get_opaque (sk->skey[i], &ndata); - iobuf_write (a, p, ndata); + assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque( sk->skey[i], &n ); + iobuf_write (a, p, (n+7)/8); } write_16(a, sk->csum ); } @@ -451,18 +456,17 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) the other stuff, so that we know the length of the packet */ write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); /* And finally write it out the real stream */ - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; + rc = iobuf_write_temp (out, a ); iobuf_close(a); /* close the remporary buffer */ return rc; } static int -do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) +do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ) { int rc = 0; - IOBUF a = iobuf_temp(); + iobuf_t a = iobuf_temp(); assert( enc->version == 4 ); switch( enc->s2k.mode ) { @@ -482,8 +486,7 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) iobuf_write(a, enc->seskey, enc->seskeylen ); write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; + rc = iobuf_write_temp (out, a); iobuf_close(a); return rc; @@ -493,11 +496,11 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) static int -do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) +do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ) { int rc = 0; int n, i; - IOBUF a = iobuf_temp(); + iobuf_t a = iobuf_temp(); write_version( a, ctb ); if( enc->throw_keyid ) { @@ -516,8 +519,7 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) mpi_write(a, enc->data[i] ); write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; + rc = iobuf_write_temp (out, a); iobuf_close(a); return rc; @@ -533,7 +535,7 @@ calc_plaintext( PKT_plaintext *pt ) } static int -do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) +do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ) { int i, rc = 0; u32 n; @@ -551,15 +553,13 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) iobuf_put(out, pt->namelen ); for(i=0; i < pt->namelen; i++ ) iobuf_put(out, pt->name[i] ); - if( write_32(out, pt->timestamp ) ) - rc = G10ERR_WRITE_FILE; + rc = write_32 (out, pt->timestamp); n = 0; while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { - if( iobuf_write(out, buf, nbytes) == -1 ) { - rc = G10ERR_WRITE_FILE; - break; - } + rc = iobuf_write(out, buf, nbytes); + if (rc) + break; n += nbytes; } wipememory(buf,1000); /* burn the buffer */ @@ -575,7 +575,7 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) static int -do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) +do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; @@ -589,7 +589,7 @@ do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) } static int -do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) +do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; @@ -608,7 +608,7 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) static int -do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) +do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ) { int rc = 0; @@ -816,12 +816,12 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, /*log_debug ("updating area for type %d\n", type );*/ } else if (oldarea) { - newarea = m_realloc (oldarea, sizeof (*newarea) + n - 1); + newarea = xrealloc (oldarea, sizeof (*newarea) + n - 1); newarea->size = n; /*log_debug ("reallocating area for type %d\n", type );*/ } else { - newarea = m_alloc (sizeof (*newarea) + n - 1); + newarea = xmalloc (sizeof (*newarea) + n - 1); newarea->size = n; /*log_debug ("allocating area for type %d\n", type );*/ } @@ -922,7 +922,7 @@ build_attribute_subpkt(PKT_user_id *uid,byte type, /* realloc uid->attrib_data to the right size */ - uid->attrib_data=m_realloc(uid->attrib_data, + uid->attrib_data=xrealloc(uid->attrib_data, uid->attrib_len+idx+1+headerlen+buflen); attrib=&uid->attrib_data[uid->attrib_len]; @@ -954,11 +954,11 @@ build_attribute_subpkt(PKT_user_id *uid,byte type, } static int -do_signature( IOBUF out, int ctb, PKT_signature *sig ) +do_signature( iobuf_t out, int ctb, PKT_signature *sig ) { int rc = 0; int n, i; - IOBUF a = iobuf_temp(); + iobuf_t a = iobuf_temp(); if( !sig->version ) iobuf_put( a, 3 ); @@ -1000,8 +1000,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); else write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; + rc = iobuf_write_temp (out, a); iobuf_close(a); return rc; @@ -1009,10 +1008,10 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) static int -do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) +do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) { int rc = 0; - IOBUF a = iobuf_temp(); + iobuf_t a = iobuf_temp(); write_version( a, ctb ); iobuf_put(a, ops->sig_class ); @@ -1023,8 +1022,7 @@ do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) iobuf_put(a, ops->last ); write_header(out, ctb, iobuf_get_temp_length(a) ); - if( iobuf_write_temp( out, a ) ) - rc = G10ERR_WRITE_FILE; + rc = iobuf_write_temp (out, a); iobuf_close(a); return rc; @@ -1032,23 +1030,19 @@ do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) static int -write_16(IOBUF out, u16 a) +write_16(iobuf_t out, u16 a) { iobuf_put(out, a>>8); - if( iobuf_put(out,a) ) - return -1; - return 0; + return iobuf_put(out,a); } static int -write_32(IOBUF out, u32 a) +write_32(iobuf_t out, u32 a) { iobuf_put(out, a>> 24); iobuf_put(out, a>> 16); iobuf_put(out, a>> 8); - if( iobuf_put(out, a) ) - return -1; - return 0; + return iobuf_put (out, a); } @@ -1081,14 +1075,14 @@ calc_header_length( u32 len, int new_ctb ) * Write the CTB and the packet length */ static int -write_header( IOBUF out, int ctb, u32 len ) +write_header( iobuf_t out, int ctb, u32 len ) { return write_header2( out, ctb, len, 0, 1 ); } static int -write_sign_packet_header( IOBUF out, int ctb, u32 len ) +write_sign_packet_header( iobuf_t out, int ctb, u32 len ) { /* work around a bug in the pgp read function for signature packets, * which are not correctly coded and silently assume at some @@ -1103,7 +1097,7 @@ write_sign_packet_header( IOBUF out, int ctb, u32 len ) * we need this, so that we can hash packets without reading them again. */ static int -write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ) +write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode ) { if( ctb & 0x40 ) return write_new_header( out, ctb, len, hdrlen ); @@ -1149,7 +1143,7 @@ write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode ) static int -write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) +write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ) { if( hdrlen ) log_bug("can't cope with hdrlen yet\n"); @@ -1188,7 +1182,7 @@ write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) } static int -write_version( IOBUF out, int ctb ) +write_version( iobuf_t out, int ctb ) { if( iobuf_put( out, 3 ) ) return -1; diff --git a/g10/call-agent.c b/g10/call-agent.c index 6cc514dca..e888820cc 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -30,14 +30,21 @@ #include <unistd.h> #include <time.h> #include <assert.h> -#include <gcrypt.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 = 0; @@ -175,7 +182,7 @@ start_agent (void) char *optstr; if (asprintf (&optstr, "OPTION display=%s", opt.display ? opt.display : dft_display) < 0) - return OUT_OF_CORE (errno); + return gpg_error_from_errno (errno); rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); free (optstr); @@ -193,7 +200,7 @@ start_agent (void) char *optstr; if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname ? opt.ttyname : dft_ttyname) < 0) - return OUT_OF_CORE (errno); + return gpg_error_from_errno (errno); rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); free (optstr); @@ -206,7 +213,7 @@ start_agent (void) char *optstr; if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttyname ? opt.ttytype : dft_ttytype) < 0) - return OUT_OF_CORE (errno); + return gpg_error_from_errno (errno); rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); free (optstr); @@ -219,7 +226,8 @@ start_agent (void) { old_lc = strdup (old_lc); if (!old_lc) - return OUT_OF_CORE (errno); + return gpg_error_from_errno (errno); + } dft_lc = setlocale (LC_CTYPE, ""); #endif @@ -228,7 +236,7 @@ start_agent (void) char *optstr; if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0) - rc = OUT_OF_CORE (errno); + rc = gpg_error_from_errno (errno); else { rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, @@ -253,7 +261,7 @@ start_agent (void) { old_lc = strdup (old_lc); if (!old_lc) - return OUT_OF_CORE (errno); + return gpg_error_from_errno (errno); } dft_lc = setlocale (LC_MESSAGES, ""); #endif @@ -262,7 +270,7 @@ start_agent (void) char *optstr; if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages ? opt.lc_messages : dft_lc) < 0) - rc = OUT_OF_CORE (errno); + rc = gpg_error_from_errno (errno); else { rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL, diff --git a/g10/cipher.c b/g10/cipher.c index ab7c9b676..3d51a874a 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -1,5 +1,5 @@ /* cipher.c - En-/De-ciphering filter - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,7 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "memory.h" @@ -40,15 +41,16 @@ static void -write_header( cipher_filter_context_t *cfx, IOBUF a ) +write_header( cipher_filter_context_t *cfx, iobuf_t a ) { PACKET pkt; PKT_encrypted ed; byte temp[18]; - unsigned blocksize; - unsigned nprefix; + unsigned int blocksize; + unsigned int nprefix; + gpg_error_t rc; - blocksize = cipher_get_blocksize( cfx->dek->algo ); + blocksize = gcry_cipher_get_algo_blklen ( cfx->dek->algo ); if( blocksize < 8 || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); @@ -58,9 +60,9 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) ed.new_ctb = !ed.len && !RFC1991; if( cfx->dek->use_mdc ) { ed.mdc_method = DIGEST_ALGO_SHA1; - cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 ); + gcry_md_open (&cfx->mdc_hash, GCRY_MD_SHA1, 0 ); if ( DBG_HASHING ) - md_start_debug( cfx->mdc_hash, "creatmdc" ); + gcry_md_start_debug ( cfx->mdc_hash, "creatmdc" ); } { @@ -76,21 +78,28 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) if( build_packet( a, &pkt )) log_bug("build_packet(ENCR_DATA) failed\n"); nprefix = blocksize; - randomize_buffer( temp, nprefix, 1 ); + 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 ); - cfx->cipher_hd = cipher_open( cfx->dek->algo, - cfx->dek->use_mdc? CIPHER_MODE_CFB - : CIPHER_MODE_AUTO_CFB, 1 ); + 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 );*/ - cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); - cipher_setiv( cfx->cipher_hd, NULL, 0 ); + 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" */ - md_write( cfx->mdc_hash, temp, nprefix+2 ); - cipher_encrypt( cfx->cipher_hd, temp, temp, nprefix+2); - cipher_sync( cfx->cipher_hd ); + 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; } @@ -102,7 +111,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) */ int cipher_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; cipher_filter_context_t *cfx = opaque; @@ -117,36 +126,40 @@ cipher_filter( void *opaque, int control, write_header( cfx, a ); } if( cfx->mdc_hash ) - md_write( cfx->mdc_hash, buf, size ); - cipher_encrypt( cfx->cipher_hd, buf, buf, size); - if( iobuf_write( a, buf, size ) ) - rc = G10ERR_WRITE_FILE; + 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 = md_digest_length( md_get_algo( cfx->mdc_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; - md_putc( cfx->mdc_hash, temp[0] ); - md_putc( cfx->mdc_hash, temp[1] ); + gcry_md_putc ( cfx->mdc_hash, temp[0] ); + gcry_md_putc ( cfx->mdc_hash, temp[1] ); - md_final( cfx->mdc_hash ); - hash = md_read( cfx->mdc_hash, 0 ); + gcry_md_final ( cfx->mdc_hash ); + hash = gcry_md_read ( cfx->mdc_hash, 0 ); memcpy(temp+2, hash, 20); - cipher_encrypt( cfx->cipher_hd, temp, temp, 22 ); - md_close( cfx->mdc_hash ); cfx->mdc_hash = NULL; - if( iobuf_write( a, temp, 22 ) ) + 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" ); } - cipher_close(cfx->cipher_hd); + gcry_cipher_close (cfx->cipher_hd); } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "cipher_filter"; } return rc; } + + + diff --git a/g10/comment.c b/g10/comment.c index 6d27e481b..3108351e4 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -1,5 +1,5 @@ /* comment.c - write comment stuff - * Copyright (C) 1998 Free Software Foundation, Inc. + * Copyright (C) 1998, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -37,7 +37,7 @@ int -write_comment( IOBUF out, const char *s ) +write_comment( iobuf_t out, const char *s ) { PACKET pkt; size_t n = strlen(s); @@ -45,18 +45,18 @@ write_comment( IOBUF out, const char *s ) pkt.pkttype = PKT_COMMENT; if( *s != '#' ) { - pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n ); + 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 = m_alloc( sizeof *pkt.pkt.comment + n - 1 ); + 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", g10_errstr(rc) ); + log_error("build_packet(comment) failed: %s\n", gpg_strerror (rc) ); free_packet( &pkt ); return rc; } @@ -68,9 +68,9 @@ make_comment_node( const char *s ) PACKET *pkt; size_t n = strlen(s); - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_COMMENT; - pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 ); + pkt->pkt.comment = xmalloc ( sizeof *pkt->pkt.comment + n - 1 ); pkt->pkt.comment->len = n; strcpy(pkt->pkt.comment->data, s); return new_kbnode( pkt ); @@ -78,25 +78,29 @@ make_comment_node( const char *s ) KBNODE -make_mpi_comment_node( const char *s, MPI a ) +make_mpi_comment_node( const char *s, gcry_mpi_t a ) { PACKET *pkt; - byte *buf, *p, *pp; - unsigned n1, nb1; + byte *buf, *pp; + size_t n1, nb1; size_t n = strlen(s); nb1 = mpi_get_nbits( a ); - p = buf = mpi_get_buffer( a, &n1, NULL ); - pkt = m_alloc_clear( sizeof *pkt ); + if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, &n1, a)) + BUG (); + /* fixme: allocate it on the stack */ + buf = xmalloc (n1); + if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, &n1, a)) + BUG (); + + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_COMMENT; - pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 ); + 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); - pp[n+1] = nb1 >> 8; - pp[n+2] = nb1 ; - memcpy(pp+n+3, p, n1 ); - m_free(buf); + memcpy(pp+n+1, buf, n1 ); + xfree (buf); return new_kbnode( pkt ); } diff --git a/g10/compress.c b/g10/compress.c index 8d9327cc3..7dce1790a 100644 --- a/g10/compress.c +++ b/g10/compress.c @@ -1,5 +1,6 @@ /* compress.c - compress filter - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +31,7 @@ # include "zlib-riscos.h" #endif +#include "gpg.h" #include "util.h" #include "memory.h" #include "packet.h" @@ -73,12 +75,13 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs ) } zfx->outbufsize = 8192; - zfx->outbuf = m_alloc( zfx->outbufsize ); + zfx->outbuf = xmalloc ( zfx->outbufsize ); } static int -do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) +do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, iobuf_t a ) { + gpg_error_t rc; int zrc; unsigned n; @@ -108,10 +111,12 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) (unsigned)zs->avail_in, (unsigned)zs->avail_out, (unsigned)n, zrc ); - if( iobuf_write( a, zfx->outbuf, n ) ) { + rc = iobuf_write (a, zfx->outbuf, n); + if (rc) + { log_debug("deflate: iobuf_write failed\n"); - return G10ERR_WRITE_FILE; - } + return rc; + } } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) ); return 0; } @@ -140,13 +145,13 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs ) } zfx->inbufsize = 2048; - zfx->inbuf = m_alloc( zfx->inbufsize ); + zfx->inbuf = xmalloc ( zfx->inbufsize ); zs->avail_in = 0; } static int do_uncompress( compress_filter_context_t *zfx, z_stream *zs, - IOBUF a, size_t *ret_len ) + iobuf_t a, size_t *ret_len ) { int zrc; int rc=0; @@ -210,7 +215,7 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, int compress_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; compress_filter_context_t *zfx = opaque; @@ -219,7 +224,7 @@ compress_filter( void *opaque, int control, if( control == IOBUFCTRL_UNDERFLOW ) { if( !zfx->status ) { - zs = zfx->opaque = m_alloc_clear( sizeof *zs ); + zs = zfx->opaque = xcalloc (1, sizeof *zs ); init_uncompress( zfx, zs ); zfx->status = 1; } @@ -250,7 +255,7 @@ compress_filter( void *opaque, int control, pkt.pkt.compressed = &cd; if( build_packet( a, &pkt )) log_bug("build_packet(PKT_COMPRESSED) failed\n"); - zs = zfx->opaque = m_alloc_clear( sizeof *zs ); + zs = zfx->opaque = xcalloc (1, sizeof *zs ); init_compress( zfx, zs ); zfx->status = 2; } @@ -266,9 +271,9 @@ compress_filter( void *opaque, int control, else if( control == IOBUFCTRL_FREE ) { if( zfx->status == 1 ) { inflateEnd(zs); - m_free(zs); + xfree (zs); zfx->opaque = NULL; - m_free(zfx->outbuf); zfx->outbuf = NULL; + xfree (zfx->outbuf); zfx->outbuf = NULL; } else if( zfx->status == 2 ) { #ifndef __riscos__ @@ -279,9 +284,9 @@ compress_filter( void *opaque, int control, zs->avail_in = 0; do_compress( zfx, zs, Z_FINISH, a ); deflateEnd(zs); - m_free(zs); + xfree (zs); zfx->opaque = NULL; - m_free(zfx->outbuf); zfx->outbuf = NULL; + xfree (zfx->outbuf); zfx->outbuf = NULL; } if (zfx->release) zfx->release (zfx); @@ -295,7 +300,7 @@ compress_filter( void *opaque, int control, static void release_context (compress_filter_context_t *ctx) { - m_free (ctx); + xfree (ctx); } /**************** @@ -303,14 +308,14 @@ release_context (compress_filter_context_t *ctx) */ int handle_compressed( void *procctx, PKT_compressed *cd, - int (*callback)(IOBUF, void *), void *passthru ) + int (*callback)(iobuf_t, void *), void *passthru ) { compress_filter_context_t *cfx; int rc; if( cd->algorithm < 1 || cd->algorithm > 2 ) - return G10ERR_COMPR_ALGO; - cfx = m_alloc_clear (sizeof *cfx); + 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 ); diff --git a/g10/dearmor.c b/g10/dearmor.c index 4ec8fa012..4f9fa2db7 100644 --- a/g10/dearmor.c +++ b/g10/dearmor.c @@ -1,5 +1,5 @@ /* dearmor.c - Armor utility - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,7 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "memory.h" @@ -42,7 +43,7 @@ int dearmor_file( const char *fname ) { armor_filter_context_t afx; - IOBUF inp = NULL, out = NULL; + iobuf_t inp = NULL, out = NULL; int rc = 0; int c; @@ -50,9 +51,9 @@ dearmor_file( const char *fname ) /* 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) ); - rc = G10ERR_OPEN_FILE; goto leave; } @@ -84,7 +85,7 @@ int enarmor_file( const char *fname ) { armor_filter_context_t afx; - IOBUF inp = NULL, out = NULL; + iobuf_t inp = NULL, out = NULL; int rc = 0; int c; @@ -92,9 +93,9 @@ enarmor_file( const char *fname ) /* 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) ); - rc = G10ERR_OPEN_FILE; goto leave; } diff --git a/g10/decrypt.c b/g10/decrypt.c index df778d1ad..98a270cfb 100644 --- a/g10/decrypt.c +++ b/g10/decrypt.c @@ -49,7 +49,7 @@ int decrypt_message( const char *filename ) { - IOBUF fp; + iobuf_t fp; armor_filter_context_t afx; progress_filter_context_t pfx; int rc; @@ -58,8 +58,9 @@ decrypt_message( const char *filename ) /* 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 G10ERR_OPEN_FILE; + return rc; } handle_progress (&pfx, fp, filename); @@ -85,7 +86,7 @@ decrypt_message( const char *filename ) void decrypt_messages(int nfiles, char **files) { - IOBUF fp; + iobuf_t fp; armor_filter_context_t afx; progress_filter_context_t pfx; char *p, *output = NULL; @@ -125,15 +126,15 @@ decrypt_messages(int nfiles, char **files) iobuf_close(fp); if (rc) log_error("%s: decryption failed: %s\n", print_fname_stdin(*files), - g10_errstr(rc)); + gpg_strerror (rc)); p = get_last_passphrase(); set_next_passphrase(p); - m_free (p); + xfree (p); next_file: /* Note that we emit file_done even after an error. */ write_status( STATUS_FILE_DONE ); - m_free(output); + xfree (output); files++; } set_next_passphrase(NULL); diff --git a/g10/delkey.c b/g10/delkey.c index 35c903cc0..34a2e1b32 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -68,9 +68,9 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) 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):G10ERR_INV_USER_ID; + rc = desc.mode? keydb_search (hd, &desc, 1):GPG_ERR_INV_USER_ID; if (rc) { - log_error (_("key `%s' not found: %s\n"), username, g10_errstr (rc)); + log_error (_("key `%s' not found: %s\n"), username, gpg_strerror (rc)); write_status_text( STATUS_DELETE_PROBLEM, "1" ); goto leave; } @@ -78,7 +78,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) /* read the keyblock */ rc = keydb_get_keyblock (hd, &keyblock ); if (rc) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -86,7 +86,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY ); if( !node ) { log_error("Oops; key not found anymore!\n"); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; goto leave; } @@ -103,8 +103,8 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) rc = -1; goto leave; } - else if( rc != G10ERR_NO_SECKEY ) { - log_error("%s: get secret key: %s\n", username, g10_errstr(rc) ); + else if( rc != GPG_ERR_NO_SECKEY ) { + log_error("%s: get secret key: %s\n", username, gpg_strerror (rc) ); } else rc = 0; @@ -153,7 +153,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) if( okay ) { rc = keydb_delete_keyblock (hd); if (rc) { - log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) ); + log_error (_("deleting keyblock failed: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -200,7 +200,7 @@ delete_keys( STRLIST names, int secret, int allow_both ) } if(rc) { - log_error("%s: delete key failed: %s\n", names->d, g10_errstr(rc) ); + log_error("%s: delete key failed: %s\n", names->d, gpg_strerror (rc) ); return rc; } } diff --git a/g10/encode.c b/g10/encode.c index 66ce57c35..ba40c0aef 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -26,6 +26,7 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" @@ -38,9 +39,11 @@ #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 out ); +static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out ); @@ -77,13 +80,14 @@ encode_store( const char *filename ) static void encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey ) { +#warning This functions needs a review. CIPHER_HANDLE hd; DEK *c; byte buf[33]; assert ( dek->keylen < 32 ); - c = m_alloc_clear( sizeof *c ); + c = xcalloc (1, sizeof *c ); c->keylen = dek->keylen; c->algo = dek->algo; make_session_key( c ); @@ -92,11 +96,12 @@ encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey ) buf[0] = c->algo; memcpy( buf + 1, c->key, c->keylen ); - hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); - cipher_setkey( hd, dek->key, dek->keylen ); - cipher_setiv( hd, NULL, 0 ); - cipher_encrypt( hd, buf, buf, c->keylen + 1 ); - cipher_close( hd ); + + gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1 ); + gcry_cipher_setkey( hd, dek->key, dek->keylen ); + 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 */ @@ -143,7 +148,7 @@ use_mdc(PK_LIST pk_list,int algo) /* Last try. Use MDC for the modern ciphers. */ - if(cipher_get_blocksize(algo)!=8) + if( gcry_cipher_get_algo_blklen (algo) != 8) return 1; return 0; /* No MDC */ @@ -152,7 +157,7 @@ use_mdc(PK_LIST pk_list,int algo) static int encode_simple( const char *filename, int mode, int compat ) { - IOBUF inp, out; + iobuf_t inp, out; PACKET pkt; DEK *dek = NULL; PKT_plaintext *pt = NULL; @@ -176,9 +181,10 @@ encode_simple( const char *filename, int mode, int compat ) /* 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 G10ERR_OPEN_FILE; + return rc; } handle_progress (&pfx, inp, filename); @@ -194,18 +200,18 @@ encode_simple( const char *filename, int mode, int compat ) cfx.dek = NULL; if( mode ) { - s2k = m_alloc_clear( sizeof *s2k ); + 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 = G10ERR_PASSPHRASE; - m_free(cfx.dek); - m_free(s2k); + rc = gpg_error (GPG_ERR_INV_PASSPHRASE); + xfree (cfx.dek); + xfree (s2k); iobuf_close(inp); - log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); + log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) ); return rc; } if (!compat && s2k->mode != 1 && s2k->mode != 3) { @@ -215,9 +221,9 @@ encode_simple( const char *filename, int mode, int compat ) } if ( !compat ) { - seskeylen = cipher_get_keylen( default_cipher_algo() ) / 8; + seskeylen = gcry_cipher_get_algo_keylen (default_cipher_algo()); encode_sesskey( cfx.dek, &dek, enckey ); - m_free( cfx.dek ); cfx.dek = dek; + xfree (cfx.dek); cfx.dek = dek; } cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo); @@ -233,8 +239,8 @@ encode_simple( const char *filename, int mode, int compat ) if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) { iobuf_cancel(inp); - m_free(cfx.dek); - m_free(s2k); + xfree (cfx.dek); + xfree (s2k); return rc; } @@ -249,7 +255,7 @@ encode_simple( const char *filename, int mode, int compat ) } #endif if( s2k && !RFC1991 ) { - PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 ); + PKT_symkey_enc *enc = xcalloc (1, sizeof *enc + seskeylen + 1 ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; enc->s2k = *s2k; @@ -260,23 +266,25 @@ encode_simple( const char *filename, int mode, int compat ) pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if( (rc = build_packet( out, &pkt )) ) - log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); - m_free(enc); + 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, - iobuf_get_real_fname( inp ) ); - pt = m_alloc( sizeof *pt + strlen(s) - 1 ); + 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 ); - m_free(s); + xfree (s); } else { /* no filename */ - pt = m_alloc( sizeof *pt - 1 ); + pt = xmalloc ( sizeof *pt - 1 ); pt->namelen = 0; } } @@ -342,7 +350,7 @@ encode_simple( const char *filename, int mode, int compat ) /* do the work */ if (!opt.no_literal) { if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet failed: %s\n", g10_errstr(rc) ); + log_error("build_packet failed: %s\n", gpg_strerror (rc) ); } else { /* user requested not to create a literal packet, @@ -350,9 +358,8 @@ encode_simple( const char *filename, int mode, int compat ) byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", g10_errstr(rc) ); + 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 */ @@ -370,8 +377,8 @@ encode_simple( const char *filename, int mode, int compat ) if (pt) pt->buf = NULL; free_packet(&pkt); - m_free(cfx.dek); - m_free(s2k); + xfree (cfx.dek); + xfree (s2k); return rc; } @@ -382,7 +389,7 @@ encode_simple( const char *filename, int mode, int compat ) int encode_crypt( const char *filename, STRLIST remusr ) { - IOBUF inp = NULL, out = NULL; + iobuf_t inp = NULL, out = NULL; PACKET pkt; PKT_plaintext *pt = NULL; int rc = 0, rc2 = 0; @@ -419,9 +426,9 @@ encode_crypt( const char *filename, STRLIST remusr ) /* 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) ); - rc = G10ERR_OPEN_FILE; goto leave; } else if( opt.verbose ) @@ -447,7 +454,7 @@ encode_crypt( const char *filename, STRLIST remusr ) } #endif /* create a session key */ - cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek); + 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 @@ -473,7 +480,7 @@ encode_crypt( const char *filename, STRLIST remusr ) opt.def_cipher_algo,NULL)!=opt.def_cipher_algo) log_info(_("forcing symmetric cipher %s (%d) " "violates recipient preferences\n"), - cipher_algo_to_string(opt.def_cipher_algo), + gcry_cipher_algo_name (opt.def_cipher_algo), opt.def_cipher_algo); cfx.dek->algo = opt.def_cipher_algo; @@ -501,7 +508,7 @@ encode_crypt( const char *filename, STRLIST remusr ) make_session_key( cfx.dek ); if( DBG_CIPHER ) - log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); + log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen ); rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out ); if( rc ) @@ -511,15 +518,15 @@ encode_crypt( const char *filename, STRLIST remusr ) /* 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 = m_alloc( sizeof *pt + strlen(s) - 1 ); + : filename + /* ,iobuf_get_real_fname( inp )*/ ); + pt = xmalloc ( sizeof *pt + strlen(s) - 1 ); pt->namelen = strlen(s); memcpy(pt->name, s, pt->namelen ); - m_free(s); + xfree (s); } else { /* no filename */ - pt = m_alloc( sizeof *pt - 1 ); + pt = xmalloc ( sizeof *pt - 1 ); pt->namelen = 0; } } @@ -590,7 +597,7 @@ encode_crypt( const char *filename, STRLIST remusr ) /* do the work */ if (!opt.no_literal) { if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet failed: %s\n", g10_errstr(rc) ); + log_error("build_packet failed: %s\n", gpg_strerror (rc) ); } else { /* user requested not to create a literal packet, so we copy @@ -598,10 +605,9 @@ encode_crypt( const char *filename, STRLIST remusr ) byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; + if ((rc=iobuf_write(out, copy_buffer, bytes_copied))) { log_error("copying input to output failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); break; } wipememory(copy_buffer, 4096); /* burn buffer */ @@ -619,7 +625,7 @@ encode_crypt( const char *filename, STRLIST remusr ) if( pt ) pt->buf = NULL; free_packet(&pkt); - m_free(cfx.dek); + xfree (cfx.dek); release_pk_list( pk_list ); return rc; } @@ -632,7 +638,7 @@ encode_crypt( const char *filename, STRLIST remusr ) */ int encrypt_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; encrypt_filter_context_t *efx = opaque; @@ -643,7 +649,7 @@ encrypt_filter( void *opaque, int control, } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { - efx->cfx.dek = m_alloc_secure_clear( sizeof *efx->cfx.dek ); + 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 = @@ -661,7 +667,7 @@ encrypt_filter( void *opaque, int control, NULL)!=opt.def_cipher_algo) log_info(_("forcing symmetric cipher %s (%d) " "violates recipient preferences\n"), - cipher_algo_to_string(opt.def_cipher_algo), + gcry_cipher_algo_name (opt.def_cipher_algo), opt.def_cipher_algo); efx->cfx.dek->algo = opt.def_cipher_algo; @@ -671,8 +677,8 @@ encrypt_filter( void *opaque, int control, make_session_key( efx->cfx.dek ); if( DBG_CIPHER ) - log_hexdump("DEK is: ", - efx->cfx.dek->key, efx->cfx.dek->keylen ); + 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 ) @@ -698,7 +704,7 @@ encrypt_filter( void *opaque, int control, * 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 out ) +write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out ) { PACKET pkt; PKT_public_key *pk; @@ -706,12 +712,12 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) int rc; for( ; pk_list; pk_list = pk_list->next ) { - MPI frame; + gcry_mpi_t frame; pk = pk_list->pk; print_pubkey_algo_note( pk->pubkey_algo ); - enc = m_alloc_clear( sizeof *enc ); + 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)); @@ -738,17 +744,17 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) */ frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo, pk->pkey ) ); - rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey ); - mpi_free( frame ); + rc = pk_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey ); + gcry_mpi_release ( frame ); if( rc ) - log_error("pubkey_encrypt failed: %s\n", g10_errstr(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"), - pubkey_algo_to_string(enc->pubkey_algo), - cipher_algo_to_string(dek->algo), ustr ); - m_free(ustr); + gcry_pk_algo_name (enc->pubkey_algo), + gcry_cipher_algo_name (dek->algo), ustr ); + xfree (ustr); } /* and write it */ init_packet(&pkt); @@ -756,7 +762,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) pkt.pkt.pubkey_enc = enc; rc = build_packet( out, &pkt ); if( rc ) - log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc)); + log_error("build_packet(pubkey_enc) failed: %s\n", gpg_strerror (rc)); } free_pubkey_enc(enc); if( rc ) @@ -792,7 +798,7 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr) 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), g10_errstr(rc) ); + print_fname_stdin(line), gpg_strerror (rc) ); write_status( STATUS_FILE_DONE ); } } @@ -803,7 +809,7 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr) 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), g10_errstr(rc) ); + print_fname_stdin(*files), gpg_strerror (rc) ); write_status( STATUS_FILE_DONE ); files++; } diff --git a/g10/encr-data.c b/g10/encr-data.c index c8a8c85db..074408404 100644 --- a/g10/encr-data.c +++ b/g10/encr-data.c @@ -1,5 +1,5 @@ /* encr-data.c - process an encrypted data packet - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,6 +23,8 @@ #include <stdlib.h> #include <string.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "memory.h" #include "packet.h" @@ -32,9 +34,9 @@ #include "i18n.h" -static int mdc_decode_filter( void *opaque, int control, IOBUF a, +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 a, +static int decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len); typedef struct { @@ -61,16 +63,16 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) memset( &dfx, 0, sizeof dfx ); if( opt.verbose && !dek->algo_info_printed ) { - const char *s = cipher_algo_to_string( dek->algo ); - if( s ) + 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=check_cipher_algo(dek->algo)) ) + if( (rc=openpgp_cipher_test_algo(dek->algo)) ) goto leave; - blocksize = cipher_get_blocksize(dek->algo); + blocksize = gcry_cipher_get_algo_blklen (dek->algo); if( !blocksize || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); nprefix = blocksize; @@ -78,20 +80,29 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) BUG(); if( ed->mdc_method ) { - dfx.mdc_hash = md_open( ed->mdc_method, 0 ); + gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 ); if ( DBG_HASHING ) - md_start_debug(dfx.mdc_hash, "checkmdc"); + gcry_md_start_debug (dfx.mdc_hash, "checkmdc"); } - dfx.cipher_hd = cipher_open( dek->algo, - ed->mdc_method? CIPHER_MODE_CFB - : CIPHER_MODE_AUTO_CFB, 1 ); -/* log_hexdump( "thekey", dek->key, dek->keylen );*/ - rc = cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen ); - if( rc == G10ERR_WEAK_KEY ) + 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", g10_errstr(rc) ); + log_error("key setup failed: %s\n", gpg_strerror (rc) ); goto leave; } if (!ed->buf) { @@ -99,9 +110,9 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) goto leave; } - cipher_setiv( dfx.cipher_hd, NULL, 0 ); + gcry_cipher_setiv (dfx.cipher_hd, NULL, 0); - if( ed->len ) { + if (ed->len) { for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) { if( (c=iobuf_get(ed->buf)) == -1 ) break; @@ -116,17 +127,17 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) else temp[i] = c; } - cipher_decrypt( dfx.cipher_hd, temp, temp, nprefix+2); - cipher_sync( dfx.cipher_hd ); + 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 = G10ERR_BAD_KEY; + rc = GPG_ERR_BAD_KEY; goto leave; } if( dfx.mdc_hash ) - md_write( dfx.mdc_hash, temp, nprefix+2 ); + gcry_md_write( dfx.mdc_hash, temp, nprefix+2 ); if( ed->mdc_method ) iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx ); @@ -136,23 +147,23 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) proc_packets( procctx, ed->buf ); ed->buf = NULL; if( ed->mdc_method && dfx.eof_seen == 2 ) - rc = G10ERR_INVALID_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); else if( ed->mdc_method ) { /* check the mdc */ - int datalen = md_digest_length( ed->mdc_method ); + int datalen = gcry_md_get_algo_dlen (ed->mdc_method); - cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 20); - md_final( dfx.mdc_hash ); + gcry_cipher_decrypt (dfx.cipher_hd, dfx.defer, 20, NULL, 0); + gcry_md_final ( dfx.mdc_hash ); if( datalen != 20 - || memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) ) - rc = G10ERR_BAD_SIGN; - /*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/ + || 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: - cipher_close(dfx.cipher_hd); - md_close( dfx.mdc_hash ); + gcry_cipher_close(dfx.cipher_hd); + gcry_md_close ( dfx.mdc_hash ); return rc; } @@ -160,7 +171,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) /* I think we should merge this with cipher_filter */ static int -mdc_decode_filter( void *opaque, int control, IOBUF a, +mdc_decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) { decode_filter_ctx_t *dfx = opaque; @@ -218,8 +229,8 @@ mdc_decode_filter( void *opaque, int control, IOBUF a, } if( n ) { - cipher_decrypt( dfx->cipher_hd, buf, buf, n); - md_write( dfx->mdc_hash, buf, n ); + gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0); + gcry_md_write( dfx->mdc_hash, buf, n ); } else { assert( dfx->eof_seen ); @@ -234,7 +245,7 @@ mdc_decode_filter( void *opaque, int control, IOBUF a, } static int -decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) +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; @@ -245,7 +256,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) n = iobuf_read( a, buf, size ); if( n == -1 ) n = 0; if( n ) - cipher_decrypt( fc->cipher_hd, buf, buf, n); + gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0); else rc = -1; /* eof */ *ret_len = n; diff --git a/g10/exec.c b/g10/exec.c index 0278438f6..f3b58aa3c 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -46,12 +46,12 @@ 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 G10ERR_GENERAL; + return GPG_ERR_GENERAL; } -int exec_read(struct exec_info *info) { return G10ERR_GENERAL; } -int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; } -int set_exec_path(const char *path,int method) { return G10ERR_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 */ @@ -71,7 +71,7 @@ static int win_system(const char *command) /* We must use a copy of the command as CreateProcess modifies this argument. */ - string=m_strdup(command); + string=xstrdup (command); memset(&pi,0,sizeof(pi)); memset(&si,0,sizeof(si)); @@ -85,7 +85,7 @@ static int win_system(const char *command) CloseHandle(pi.hProcess); CloseHandle(pi.hThread); - m_free(string); + xfree (string); return 0; } @@ -101,7 +101,7 @@ int set_exec_path(const char *path,int method) if(method==1 && (curpath=getenv("PATH"))) curlen=strlen(curpath)+1; - p=m_alloc(5+curlen+strlen(path)+1); + p=xmalloc (5+curlen+strlen(path)+1); strcpy(p,"PATH="); if(curpath) @@ -120,7 +120,7 @@ int set_exec_path(const char *path,int method) set_exec_path multiple times. */ if(putenv(p)!=0) - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; else return 0; } @@ -140,7 +140,7 @@ static int make_tempdir(struct exec_info *info) if(tmp==NULL) { #if defined (__MINGW32__) - tmp=m_alloc(256); + tmp=xmalloc (256); if(GetTempPath(256,tmp)==0) strcpy(tmp,"c:\\windows\\temp"); else @@ -172,12 +172,12 @@ static int make_tempdir(struct exec_info *info) #endif } - info->tempdir=m_alloc(strlen(tmp)+strlen(DIRSEP_S)+10+1); + info->tempdir=xmalloc (strlen(tmp)+strlen(DIRSEP_S)+10+1); sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); #if defined (__MINGW32__) - m_free(tmp); + xfree (tmp); #endif if(mkdtemp(info->tempdir)==NULL) @@ -187,19 +187,19 @@ static int make_tempdir(struct exec_info *info) { info->madedir=1; - info->tempfile_in=m_alloc(strlen(info->tempdir)+ + 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=m_alloc(strlen(info->tempdir)+ + 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:G10ERR_GENERAL; + return info->madedir?0:GPG_ERR_GENERAL; } /* Expands %i and %o in the args to the full temp files within the @@ -216,7 +216,7 @@ static int expand_args(struct exec_info *info,const char *args_in) log_debug("expanding string \"%s\"\n",args_in); size=100; - info->command=m_alloc(size); + info->command=xmalloc (size); len=0; info->command[0]='\0'; @@ -273,7 +273,7 @@ static int expand_args(struct exec_info *info,const char *args_in) applen=100; size+=applen; - info->command=m_realloc(info->command,size); + info->command=xrealloc(info->command,size); } strcat(info->command,append); @@ -285,7 +285,7 @@ static int expand_args(struct exec_info *info,const char *args_in) if(len==size-1) /* leave room for the \0 */ { size+=100; - info->command=m_realloc(info->command,size); + info->command=xrealloc(info->command,size); } info->command[len++]=*ch; @@ -303,10 +303,10 @@ static int expand_args(struct exec_info *info,const char *args_in) fail: - m_free(info->command); + xfree (info->command); info->command=NULL; - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } /* Either handles the tempfile creation, or the fork/exec. If it @@ -318,7 +318,7 @@ static int expand_args(struct exec_info *info,const char *args_in) int exec_write(struct exec_info **info,const char *program, const char *args_in,const char *name,int writeonly,int binary) { - int ret=G10ERR_GENERAL; + int ret=GPG_ERR_GENERAL; if(opt.exec_disable && !opt.no_perm_warn) { @@ -338,10 +338,10 @@ int exec_write(struct exec_info **info,const char *program, if(program==NULL && args_in==NULL) BUG(); - *info=m_alloc_clear(sizeof(struct exec_info)); + *info=xcalloc (1,sizeof(struct exec_info)); if(name) - (*info)->name=m_strdup(name); + (*info)->name=xstrdup (name); (*info)->binary=binary; (*info)->writeonly=writeonly; @@ -449,8 +449,8 @@ int exec_write(struct exec_info **info,const char *program, (*info)->tochild=fdopen(to[1],binary?"wb":"w"); if((*info)->tochild==NULL) { + ret = gpg_error_from_errno (errno); close(to[1]); - ret=G10ERR_WRITE_FILE; goto fail; } @@ -459,8 +459,8 @@ int exec_write(struct exec_info **info,const char *program, (*info)->fromchild=iobuf_fdopen(from[0],"r"); if((*info)->fromchild==NULL) { + ret = gpg_error_from_errno (errno); close(from[0]); - ret=G10ERR_READ_FILE; goto fail; } @@ -478,9 +478,9 @@ int exec_write(struct exec_info **info,const char *program, (*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)); - ret=G10ERR_WRITE_FILE; goto fail; } @@ -492,7 +492,7 @@ int exec_write(struct exec_info **info,const char *program, int exec_read(struct exec_info *info) { - int ret=G10ERR_GENERAL; + int ret=GPG_ERR_GENERAL; fclose(info->tochild); info->tochild=NULL; @@ -545,9 +545,9 @@ int exec_read(struct exec_info *info) 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)); - ret=G10ERR_READ_FILE; goto fail; } @@ -607,12 +607,12 @@ int exec_finish(struct exec_info *info) info->tempdir,strerror(errno)); } - m_free(info->command); - m_free(info->name); - m_free(info->tempdir); - m_free(info->tempfile_in); - m_free(info->tempfile_out); - m_free(info); + xfree (info->command); + xfree (info->name); + xfree (info->tempdir); + xfree (info->tempfile_in); + xfree (info->tempfile_out); + xfree (info); return ret; } diff --git a/g10/exec.h b/g10/exec.h index 25369dc34..eda406894 100644 --- a/g10/exec.h +++ b/g10/exec.h @@ -1,5 +1,5 @@ /* exec.h - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,14 +23,14 @@ #include <unistd.h> #include <stdio.h> -#include "iobuf.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 fromchild; + iobuf_t fromchild; char *command,*name,*tempdir,*tempfile_in,*tempfile_out; }; diff --git a/g10/export.c b/g10/export.c index 5783f6ac1..6c2c19f14 100644 --- a/g10/export.c +++ b/g10/export.c @@ -35,7 +35,7 @@ #include "i18n.h" static int do_export( STRLIST users, int secret, unsigned int options ); -static int do_export_stream( IOBUF out, STRLIST users, int secret, +static int do_export_stream( iobuf_t out, STRLIST users, int secret, KBNODE *keyblock_out, unsigned int options, int *any ); @@ -71,7 +71,7 @@ export_pubkeys( STRLIST users, unsigned int options ) * been exported */ int -export_pubkeys_stream( IOBUF out, STRLIST users, +export_pubkeys_stream( iobuf_t out, STRLIST users, KBNODE *keyblock_out, unsigned int options ) { int any, rc; @@ -97,7 +97,7 @@ export_secsubkeys( STRLIST users ) static int do_export( STRLIST users, int secret, unsigned int options ) { - IOBUF out = NULL; + iobuf_t out = NULL; int any, rc; armor_filter_context_t afx; compress_filter_context_t zfx; @@ -129,7 +129,7 @@ do_export( STRLIST users, int secret, unsigned int options ) 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 out, STRLIST users, int secret, +do_export_stream( iobuf_t out, STRLIST users, int secret, KBNODE *keyblock_out, unsigned int options, int *any ) { int rc = 0; @@ -147,20 +147,20 @@ do_export_stream( IOBUF out, STRLIST users, int secret, if (!users) { ndesc = 1; - desc = m_alloc_clear ( ndesc * sizeof *desc); + 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 = m_alloc ( ndesc * sizeof *desc); + 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, g10_errstr (G10ERR_INV_USER_ID)); + sl->d, gpg_strerror (GPG_ERR_INV_USER_ID)); } /* it would be nice to see which of the given users did @@ -181,7 +181,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, /* read the keyblock */ rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -370,8 +370,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, if( rc ) { log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - rc = G10ERR_WRITE_FILE; + node->pkt->pkttype, gpg_strerror (rc) ); goto leave; } } @@ -386,7 +385,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, rc = 0; leave: - m_free(desc); + xfree (desc); keydb_release (kdbhd); if(rc || keyblock_out==NULL) release_kbnode( keyblock ); diff --git a/g10/filter.h b/g10/filter.h index 9f235fd6b..12c5cebed 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -22,6 +22,7 @@ #include "types.h" #include "cipher.h" +#include "iobuf.h" typedef struct { MD_HANDLE md; /* catch all */ @@ -120,35 +121,35 @@ typedef struct { /* encrypt_filter_context_t defined in main.h */ /*-- mdfilter.c --*/ -int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); +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 a ); +int use_armor_filter( iobuf_t a ); int armor_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); + 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 chain, byte *buf, size_t *ret_len); + iobuf_t chain, byte *buf, size_t *ret_len); /*-- cipher.c --*/ int cipher_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); + iobuf_t chain, byte *buf, size_t *ret_len); /*-- textfilter.c --*/ int text_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); -int copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, + 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 a, byte *buf, size_t *ret_len); + iobuf_t a, byte *buf, size_t *ret_len); void handle_progress (progress_filter_context_t *pfx, - IOBUF inp, const char *name); + iobuf_t inp, const char *name); #endif /*G10_FILTER_H*/ diff --git a/g10/free-packet.c b/g10/free-packet.c index ce3568ca5..7ced327f5 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -36,7 +36,7 @@ void free_symkey_enc( PKT_symkey_enc *enc ) { - m_free(enc); + xfree (enc); } void @@ -45,10 +45,10 @@ free_pubkey_enc( PKT_pubkey_enc *enc ) int n, i; n = pubkey_get_nenc( enc->pubkey_algo ); if( !n ) - mpi_free(enc->data[0]); + mpi_release (enc->data[0]); for(i=0; i < n; i++ ) - mpi_free( enc->data[i] ); - m_free(enc); + mpi_release ( enc->data[i] ); + xfree (enc); } void @@ -58,14 +58,14 @@ free_seckey_enc( PKT_signature *sig ) n = pubkey_get_nsig( sig->pubkey_algo ); if( !n ) - mpi_free(sig->data[0]); + mpi_release (sig->data[0]); for(i=0; i < n; i++ ) - mpi_free( sig->data[i] ); + mpi_release ( sig->data[i] ); - m_free(sig->revkey); - m_free(sig->hashed); - m_free(sig->unhashed); - m_free(sig); + xfree (sig->revkey); + xfree (sig->hashed); + xfree (sig->unhashed); + xfree (sig); } @@ -75,13 +75,13 @@ release_public_key_parts( PKT_public_key *pk ) int n, i; n = pubkey_get_npkey( pk->pubkey_algo ); if( !n ) - mpi_free(pk->pkey[0]); + mpi_release (pk->pkey[0]); for(i=0; i < n; i++ ) { - mpi_free( pk->pkey[i] ); + mpi_release ( pk->pkey[i] ); pk->pkey[i] = NULL; } if (pk->prefs) { - m_free (pk->prefs); + xfree (pk->prefs); pk->prefs = NULL; } if (pk->user_id) { @@ -89,7 +89,7 @@ release_public_key_parts( PKT_public_key *pk ) pk->user_id = NULL; } if (pk->revkey) { - m_free(pk->revkey); + xfree (pk->revkey); pk->revkey=NULL; pk->numrevkeys=0; } @@ -100,7 +100,7 @@ void free_public_key( PKT_public_key *pk ) { release_public_key_parts( pk ); - m_free(pk); + xfree (pk); } @@ -111,7 +111,7 @@ cp_subpktarea (subpktarea_t *s ) if( !s ) return NULL; - d = m_alloc (sizeof (*d) + s->size - 1 ); + d = xmalloc (sizeof (*d) + s->size - 1 ); d->size = s->size; d->len = s->len; memcpy (d->data, s->data, s->len); @@ -132,7 +132,7 @@ copy_prefs (const prefitem_t *prefs) for (n=0; prefs[n].type; n++) ; - new = m_alloc ( sizeof (*new) * (n+1)); + 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; @@ -150,7 +150,7 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s) int n, i; if( !d ) - d = m_alloc(sizeof *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); @@ -164,7 +164,7 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s) if( !s->revkey && s->numrevkeys ) BUG(); if( s->numrevkeys ) { - d->revkey = m_alloc(sizeof(struct revocation_key)*s->numrevkeys); + d->revkey = xmalloc (sizeof(struct revocation_key)*s->numrevkeys); memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys); } else @@ -200,7 +200,7 @@ copy_signature( PKT_signature *d, PKT_signature *s ) int n, i; if( !d ) - d = m_alloc(sizeof *d); + d = xmalloc (sizeof *d); memcpy( d, s, sizeof *d ); n = pubkey_get_nsig( s->pubkey_algo ); if( !n ) @@ -241,9 +241,9 @@ release_secret_key_parts( PKT_secret_key *sk ) n = pubkey_get_nskey( sk->pubkey_algo ); if( !n ) - mpi_free(sk->skey[0]); + mpi_release (sk->skey[0]); for(i=0; i < n; i++ ) { - mpi_free( sk->skey[i] ); + mpi_release ( sk->skey[i] ); sk->skey[i] = NULL; } } @@ -252,7 +252,7 @@ void free_secret_key( PKT_secret_key *sk ) { release_secret_key_parts( sk ); - m_free(sk); + xfree (sk); } PKT_secret_key * @@ -261,7 +261,7 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ) int n, i; if( !d ) - d = m_alloc(sizeof *d); + d = xmalloc (sizeof *d); memcpy( d, s, sizeof *d ); n = pubkey_get_nskey( s->pubkey_algo ); if( !n ) @@ -276,14 +276,14 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ) void free_comment( PKT_comment *rem ) { - m_free(rem); + xfree (rem); } void free_attributes(PKT_user_id *uid) { - m_free(uid->attribs); - m_free(uid->attrib_data); + xfree (uid->attribs); + xfree (uid->attrib_data); uid->attribs=NULL; uid->attrib_data=NULL; @@ -298,9 +298,9 @@ free_user_id (PKT_user_id *uid) return; free_attributes(uid); - m_free (uid->prefs); - m_free (uid->namehash); - m_free (uid); + xfree (uid->prefs); + xfree (uid->namehash); + xfree (uid); } void @@ -312,7 +312,7 @@ free_compressed( PKT_compressed *zd ) while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 ) ; } - m_free(zd); + xfree (zd); } void @@ -333,7 +333,7 @@ free_encrypted( PKT_encrypted *ed ) } } } - m_free(ed); + xfree (ed); } @@ -355,7 +355,7 @@ free_plaintext( PKT_plaintext *pt ) } } } - m_free(pt); + xfree (pt); } /**************** @@ -405,7 +405,7 @@ free_packet( PACKET *pkt ) free_plaintext( pkt->pkt.plaintext ); break; default: - m_free( pkt->pkt.generic ); + xfree ( pkt->pkt.generic ); break; } pkt->pkt.generic = NULL; diff --git a/g10/g10.c b/g10/g10.c index d17422c12..cf6240d55 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -34,6 +34,7 @@ #endif #define INCLUDED_BY_MAIN_MODULE 1 +#include "gpg.h" #include "packet.h" #include "iobuf.h" #include "memory.h" @@ -48,7 +49,6 @@ #include "ttyio.h" #include "i18n.h" #include "status.h" -#include "g10defs.h" #include "keyserver-internal.h" #include "exec.h" @@ -644,8 +644,15 @@ static void add_policy_url( const char *string, int which ); RISCOS_GLOBAL_STATICS("GnuPG Heap") #endif /* __riscos__ */ -const char * -strusage( int level ) +static int +pk_test_algo (int algo) +{ + return openpgp_pk_test_algo (algo, 0); +} + + +static const char * +my_strusage( int level ) { static char *digests, *pubkeys, *ciphers, *zips; const char *p; @@ -676,20 +683,20 @@ strusage( int level ) case 33: p = _("\nSupported algorithms:\n"); break; case 34: if( !pubkeys ) - pubkeys = build_list(_("Pubkey: "), 0, pubkey_algo_to_string, - check_pubkey_algo ); + pubkeys = build_list(_("Pubkey: "), 0, gcry_pk_algo_name, + pk_test_algo ); p = pubkeys; break; case 35: if( !ciphers ) - ciphers = build_list(_("Cipher: "), 'S', cipher_algo_to_string, - check_cipher_algo ); + ciphers = build_list(_("Cipher: "), 'S', gcry_cipher_algo_name, + openpgp_cipher_test_algo ); p = ciphers; break; case 36: if( !digests ) - digests = build_list(_("Hash: "), 'H', digest_algo_to_string, - check_digest_algo ); + digests = build_list(_("Hash: "), 'H', gcry_md_algo_name, + openpgp_md_test_algo ); p = digests; break; case 37: @@ -699,7 +706,7 @@ strusage( int level ) p = zips; break; - default: p = default_strusage(level); + default: p = NULL; } return p; } @@ -715,12 +722,12 @@ build_list( const char *text, char letter, char *list, *p, *line=NULL; if( maybe_setuid ) - secmem_init( 0 ); /* drop setuid */ + gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* drop setuid */ for(i=0; i <= 110; i++ ) if( !chkf(i) && (s=mapf(i)) ) n += strlen(s) + 7 + 2; - list = m_alloc( 21 + n ); *list = 0; + list = xmalloc ( 21 + n ); *list = 0; for(p=NULL, i=0; i <= 110; i++ ) { if( !chkf(i) && (s=mapf(i)) ) { if( !p ) { @@ -733,7 +740,7 @@ build_list( const char *text, char letter, if(strlen(line)>60) { int spaces=strlen(text); - list=m_realloc(list,n+spaces+1); + list = xrealloc(list,n+spaces+1); /* realloc could move the block, so find the end again */ p=list; while(*p) @@ -768,7 +775,7 @@ i18n_init(void) #else #ifdef ENABLE_NLS setlocale( LC_ALL, "" ); - bindtextdomain( PACKAGE, G10_LOCALEDIR ); + bindtextdomain( PACKAGE, LOCALEDIR ); textdomain( PACKAGE ); #endif #endif @@ -784,32 +791,58 @@ wrong_args( const char *text) } +static void +log_set_strict (int yesno) +{ + /* FIXME-XXX*/ +} + static char * make_username( const char *string ) { char *p; if( utf8_strings ) - p = m_strdup(string); + p = xstrdup (string); else p = native_to_utf8( string ); return p; } +/* + * same as add_to_strlist() but if is_utf8 is *not* set a conversion + * to UTF8 is done + */ +static STRLIST +add_to_strlist2 ( STRLIST *list, const char *string, int is_utf8) +{ + STRLIST sl; + + if (is_utf8) + sl = add_to_strlist( list, string ); + else + { + char *p = native_to_utf8( string ); + sl = add_to_strlist( list, p ); + xfree( p ); + } + return sl; +} + + static void set_debug(void) { - if( opt.debug & DBG_MEMORY_VALUE ) - memory_debug_mode = 1; - if( opt.debug & DBG_MEMSTAT_VALUE ) - memory_stat_debug_mode = 1; - if( opt.debug & DBG_MPI_VALUE ) - mpi_debug_mode = 1; - if( opt.debug & DBG_CIPHER_VALUE ) - g10c_debug_mode = 1; - if( opt.debug & DBG_IOBUF_VALUE ) - iobuf_debug_mode = 1; - + if (opt.debug & DBG_MEMORY_VALUE ) + memory_debug_mode = 1; + if (opt.debug & DBG_MEMSTAT_VALUE ) + memory_stat_debug_mode = 1; + if (opt.debug & DBG_MPI_VALUE) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); + if (opt.debug & DBG_CIPHER_VALUE ) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); + if (opt.debug & DBG_IOBUF_VALUE ) + iobuf_debug_mode = 1; } @@ -876,7 +909,7 @@ static void add_group(char *string) add_to_strlist2 (&values,value,utf8_strings); } - item=m_alloc(sizeof(struct groupitem)); + item=xmalloc (sizeof(struct groupitem)); item->name=name; item->values=values; item->next=opt.grouplist; @@ -920,7 +953,7 @@ check_permissions(const char *path,int item) tmppath=make_filename(GNUPG_LIBDIR,path,NULL); } else - tmppath=m_strdup(path); + tmppath=xstrdup (path); /* If the item is located in the homedir, but isn't the homedir, don't continue if we already checked the homedir itself. This is @@ -953,7 +986,7 @@ check_permissions(const char *path,int item) goto end; } - m_free(dir); + xfree (dir); /* Assume failure */ ret=1; @@ -1076,7 +1109,7 @@ check_permissions(const char *path,int item) } end: - m_free(tmppath); + xfree (tmppath); if(homedir) homedir_cache=ret; @@ -1092,7 +1125,7 @@ int main( int argc, char **argv ) { ARGPARSE_ARGS pargs; - IOBUF a; + iobuf_t a; int rc=0; int orig_argc; char **orig_argv; @@ -1137,17 +1170,31 @@ main( int argc, char **argv ) #endif /* __riscos__ */ trap_unaligned(); - secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */ + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + /* We don't need any locking in libgcrypt unless we use any kind of + threading. */ + gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING); /* Please note that we may running SUID(ROOT), so be very CAREFUL * when adding any stuff between here and the call to * secmem_init() somewhere after the option parsing */ - log_set_name("gpg"); - secure_random_alloc(); /* put random number into secure memory */ + log_set_prefix ("gpg", 1); + /* check that the libraries are suitable. Do it here because the + option parse may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + may_coredump = disable_core_dumps(); - init_signals(); - create_dotlock(NULL); /* register locking cleanup */ + init_signals (); /* why not gnupg_init_signals. */ + create_dotlock (NULL); /* register locking cleanup */ i18n_init(); + opt.command_fd = -1; /* no command fd */ opt.compress = -1; /* defaults to standard compress level */ /* note: if you change these lines, look at oOpenPGP */ @@ -1238,7 +1285,7 @@ main( int argc, char **argv ) #ifdef HAVE_DOSISH_SYSTEM if ( strchr (opt.homedir,'\\') ) { - char *d, *buf = m_alloc (strlen (opt.homedir)+1); + char *d, *buf = xmalloc (strlen (opt.homedir)+1); const char *s = opt.homedir; for (d=buf,s=opt.homedir; *s; s++) *d++ = *s == '\\'? '/': *s; @@ -1251,11 +1298,13 @@ main( int argc, char **argv ) init_shm_coprocessing(requested_shm_size, 1 ); } #endif - /* initialize the secure memory. */ - secmem_init( 32768 ); + /* Initialize the secure memory. */ + gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); maybe_setuid = 0; /* Okay, we are now working under our real uid */ + /* malloc hooks gohere ... */ + set_native_charset (NULL); /* Try to auto set the character set */ if( default_config ) @@ -1265,7 +1314,7 @@ main( int argc, char **argv ) "gpg" EXTSEP_S "conf-" SAFE_VERSION, NULL ); if(access(configname,R_OK)) { - m_free(configname); + xfree (configname); configname = make_filename(opt.homedir, "gpg" EXTSEP_S "conf", NULL ); } @@ -1274,11 +1323,11 @@ main( int argc, char **argv ) char *p = make_filename(opt.homedir, "options", NULL ); if (!access (p, R_OK)) log_info (_("NOTE: old default options file `%s' ignored\n"), p); - m_free (p); + xfree (p); } else { /* Keep on using the old default one. */ - m_free (configname); + xfree (configname); configname = make_filename(opt.homedir, "options", NULL ); } } @@ -1317,7 +1366,7 @@ main( int argc, char **argv ) configname, strerror(errno) ); g10_exit(2); } - m_free(configname); configname = NULL; + xfree (configname); configname = NULL; } if( parse_debug && configname ) log_info(_("reading options from `%s'\n"), configname ); @@ -1437,8 +1486,7 @@ main( int argc, char **argv ) break; #endif /* __riscos__ */ case oLoggerFD: - log_set_logfile( NULL, - iobuf_translate_file_handle (pargs.r.ret_int, 1) ); + log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1)); break; #ifdef __riscos__ case oLoggerFile: @@ -1454,8 +1502,8 @@ main( int argc, char **argv ) case oOptions: /* config files may not be nested (silently ignore them) */ if( !configfp ) { - m_free(configname); - configname = m_strdup(pargs.r.ret_str); + xfree (configname); + configname = xstrdup (pargs.r.ret_str); goto next_pass; } break; @@ -1465,7 +1513,8 @@ main( int argc, char **argv ) case oNoGreeting: nogreeting = 1; break; case oNoVerbose: g10_opt_verbose = 0; opt.verbose = 0; opt.list_sigs=0; break; - case oQuickRandom: quick_random_gen(1); break; + /* disabled for now: + case oQuickRandom: quick_random_gen(1); break; */ case oSKComments: opt.sk_comments=1; break; case oNoSKComments: opt.sk_comments=0; break; case oEmitVersion: opt.no_version=0; break; @@ -1480,11 +1529,11 @@ main( int argc, char **argv ) opt.def_recipient = make_username(pargs.r.ret_str); break; case oDefRecipientSelf: - m_free(opt.def_recipient); opt.def_recipient = NULL; + xfree (opt.def_recipient); opt.def_recipient = NULL; opt.def_recipient_self = 1; break; case oNoDefRecipient: - m_free(opt.def_recipient); opt.def_recipient = NULL; + xfree (opt.def_recipient); opt.def_recipient = NULL; opt.def_recipient_self = 0; break; case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */ @@ -1621,8 +1670,8 @@ main( int argc, char **argv ) case oDisableMDC: opt.disable_mdc = 1; break; case oNoDisableMDC: opt.disable_mdc = 0; break; case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; - case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break; - case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break; + case oS2KDigest: s2k_digest_string = xstrdup (pargs.r.ret_str); break; + case oS2KCipher: s2k_cipher_string = xstrdup (pargs.r.ret_str); break; case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break; case oNoEncryptTo: opt.no_encrypt_to = 1; break; case oEncryptTo: /* store the recipient in the second list */ @@ -1671,8 +1720,8 @@ main( int argc, char **argv ) opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); break; #endif /* __riscos__ */ - case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break; - case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break; + case oCipherAlgo: def_cipher_string = xstrdup (pargs.r.ret_str); break; + case oDigestAlgo: def_digest_string = xstrdup (pargs.r.ret_str); break; case oCompressAlgo: /* If it is all digits, stick a Z in front of it for later. This is for backwards compatibility with @@ -1689,16 +1738,19 @@ main( int argc, char **argv ) if(*pt=='\0') { - def_compress_string=m_alloc(strlen(pargs.r.ret_str)+2); + def_compress_string=xmalloc (strlen(pargs.r.ret_str)+2); strcpy(def_compress_string,"Z"); strcat(def_compress_string,pargs.r.ret_str); } else - def_compress_string = m_strdup(pargs.r.ret_str); + def_compress_string = xstrdup (pargs.r.ret_str); } break; - case oCertDigestAlgo: cert_digest_string = m_strdup(pargs.r.ret_str); break; - case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break; + case oCertDigestAlgo: cert_digest_string = xstrdup (pargs.r.ret_str); break; + case oNoSecmemWarn: +#warning add secmem_get_flags +/* secmem_set_flags( secmem_get_flags() | 1 ); */ + break; case oNoPermissionWarn: opt.no_perm_warn=1; break; case oNoMDCWarn: opt.no_mdc_warn=1; break; case oCharset: @@ -1719,7 +1771,7 @@ main( int argc, char **argv ) #endif /* __riscos__ */ break; case oKeyServer: - opt.keyserver_uri=m_strdup(pargs.r.ret_str); + opt.keyserver_uri=xstrdup (pargs.r.ret_str); if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno)) log_error(_("could not parse keyserver URI\n")); break; @@ -1813,11 +1865,19 @@ main( int argc, char **argv ) case oUtf8Strings: utf8_strings = 1; break; case oNoUtf8Strings: utf8_strings = 0; break; case oDisableCipherAlgo: - disable_cipher_algo( string_to_cipher_algo(pargs.r.ret_str) ); - break; + { + int algo = gcry_cipher_map_name (pargs.r.ret_str); + gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, + &algo, sizeof algo); + } + break; case oDisablePubkeyAlgo: - disable_pubkey_algo( string_to_pubkey_algo(pargs.r.ret_str) ); - break; + { + int algo = gcry_pk_map_name (pargs.r.ret_str); + gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, + &algo, sizeof algo ); + } + break; case oNoSigCache: opt.no_sig_cache = 1; break; case oNoSigCreateCheck: opt.no_sig_create_check = 1; break; case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break; @@ -1900,10 +1960,10 @@ main( int argc, char **argv ) if( configfp ) { fclose( configfp ); configfp = NULL; - m_free(configname); configname = NULL; + xfree (configname); configname = NULL; goto next_pass; } - m_free( configname ); configname = NULL; + xfree ( configname ); configname = NULL; if( log_get_errorcount(0) ) g10_exit(2); if( nogreeting ) @@ -1952,8 +2012,10 @@ main( int argc, char **argv ) if( opt.batch ) tty_batchmode( 1 ); +#warning fix that +#if 0 secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ - +#endif set_debug(); /* Do these after the switch(), so they can override settings. */ @@ -1986,7 +2048,7 @@ main( int argc, char **argv ) preference, but those have their own error messages). */ - if(check_cipher_algo(CIPHER_ALGO_IDEA)) + if(openpgp_cipher_test_algo (CIPHER_ALGO_IDEA)) { log_info(_("encrypting a message in --pgp2 mode requires " "the IDEA cipher\n")); @@ -1998,8 +2060,8 @@ main( int argc, char **argv ) /* This only sets IDEA for symmetric encryption since it is set via select_algo_from_prefs for pk encryption. */ - m_free(def_cipher_string); - def_cipher_string = m_strdup("idea"); + xfree (def_cipher_string); + def_cipher_string = xstrdup ("idea"); } /* PGP2 can't handle the output from the textmode @@ -2024,8 +2086,8 @@ main( int argc, char **argv ) opt.pgp2_workarounds = 1; opt.ask_sig_expire = 0; opt.ask_cert_expire = 0; - m_free(def_digest_string); - def_digest_string = m_strdup("md5"); + xfree (def_digest_string); + def_digest_string = xstrdup ("md5"); opt.def_compress_algo = 1; } } @@ -2053,43 +2115,43 @@ main( int argc, char **argv ) /* must do this after dropping setuid, because string_to... * may try to load an module */ if( def_cipher_string ) { - opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string); + opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string); if(opt.def_cipher_algo==0 && (ascii_strcasecmp(def_cipher_string,"idea")==0 || ascii_strcasecmp(def_cipher_string,"s1")==0)) idea_cipher_warn(1); - m_free(def_cipher_string); def_cipher_string = NULL; - if( check_cipher_algo(opt.def_cipher_algo) ) + xfree (def_cipher_string); def_cipher_string = NULL; + if( openpgp_cipher_test_algo (opt.def_cipher_algo) ) log_error(_("selected cipher algorithm is invalid\n")); } if( def_digest_string ) { - opt.def_digest_algo = string_to_digest_algo(def_digest_string); - m_free(def_digest_string); def_digest_string = NULL; - if( check_digest_algo(opt.def_digest_algo) ) + opt.def_digest_algo = gcry_md_map_name (def_digest_string); + xfree (def_digest_string); def_digest_string = NULL; + if( openpgp_md_test_algo (opt.def_digest_algo) ) log_error(_("selected digest algorithm is invalid\n")); } if( def_compress_string ) { opt.def_compress_algo = string_to_compress_algo(def_compress_string); - m_free(def_compress_string); def_compress_string = NULL; + xfree (def_compress_string); def_compress_string = NULL; if( check_compress_algo(opt.def_compress_algo) ) log_error(_("selected compression algorithm is invalid\n")); } if( cert_digest_string ) { - opt.cert_digest_algo = string_to_digest_algo(cert_digest_string); - m_free(cert_digest_string); cert_digest_string = NULL; - if( check_digest_algo(opt.cert_digest_algo) ) + opt.cert_digest_algo = gcry_md_map_name (cert_digest_string); + xfree (cert_digest_string); cert_digest_string = NULL; + if( openpgp_md_test_algo(opt.cert_digest_algo) ) log_error(_("selected certification digest algorithm is invalid\n")); } if( s2k_cipher_string ) { - opt.s2k_cipher_algo = string_to_cipher_algo(s2k_cipher_string); - m_free(s2k_cipher_string); s2k_cipher_string = NULL; - if( check_cipher_algo(opt.s2k_cipher_algo) ) + opt.s2k_cipher_algo = gcry_cipher_map_name (s2k_cipher_string); + xfree (s2k_cipher_string); s2k_cipher_string = NULL; + if( openpgp_cipher_test_algo (opt.s2k_cipher_algo) ) log_error(_("selected cipher algorithm is invalid\n")); } if( s2k_digest_string ) { - opt.s2k_digest_algo = string_to_digest_algo(s2k_digest_string); - m_free(s2k_digest_string); s2k_digest_string = NULL; - if( check_digest_algo(opt.s2k_digest_algo) ) + opt.s2k_digest_algo = gcry_md_map_name (s2k_digest_string); + xfree (s2k_digest_string); s2k_digest_string = NULL; + if( openpgp_md_test_algo (opt.s2k_digest_algo) ) log_error(_("selected digest algorithm is invalid\n")); } if( opt.completes_needed < 1 ) @@ -2143,32 +2205,32 @@ main( int argc, char **argv ) const char *badalg=NULL; preftype_t badtype=PREFTYPE_NONE; - if(opt.def_cipher_algo - && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL)) + if (opt.def_cipher_algo + && !algo_available (PREFTYPE_SYM,opt.def_cipher_algo,NULL)) { - badalg=cipher_algo_to_string(opt.def_cipher_algo); - badtype=PREFTYPE_SYM; + badalg = gcry_cipher_algo_name (opt.def_cipher_algo); + badtype = PREFTYPE_SYM; } - else if(opt.def_digest_algo - && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL)) + else if (opt.def_digest_algo + && !algo_available (PREFTYPE_HASH,opt.def_digest_algo,NULL)) { - badalg=digest_algo_to_string(opt.def_digest_algo); - badtype=PREFTYPE_HASH; + badalg = gcry_md_algo_name (opt.def_digest_algo); + badtype = PREFTYPE_HASH; } - else if(opt.cert_digest_algo - && !algo_available(PREFTYPE_HASH,opt.cert_digest_algo,NULL)) + else if (opt.cert_digest_algo + && !algo_available (PREFTYPE_HASH,opt.cert_digest_algo,NULL)) { - badalg=digest_algo_to_string(opt.cert_digest_algo); - badtype=PREFTYPE_HASH; + badalg = gcry_md_algo_name (opt.cert_digest_algo); + badtype = PREFTYPE_HASH; } - else if(opt.def_compress_algo!=-1 - && !algo_available(PREFTYPE_ZIP,opt.def_compress_algo,NULL)) + else if (opt.def_compress_algo!=-1 + && !algo_available (PREFTYPE_ZIP,opt.def_compress_algo,NULL)) { - badalg=compress_algo_to_string(opt.def_compress_algo); - badtype=PREFTYPE_ZIP; + badalg = compress_algo_to_string (opt.def_compress_algo); + badtype = PREFTYPE_ZIP; } - if(badalg) + if (badalg) { switch(badtype) { @@ -2198,8 +2260,11 @@ main( int argc, char **argv ) /* set the random seed file */ if( use_random_seed ) { char *p = make_filename(opt.homedir, "random_seed", NULL ); +#warning No random seed file yet +#if 0 set_random_seed_file(p); - m_free(p); +#endif + xfree (p); } if( !cmd && opt.fingerprint && !with_fpr ) { @@ -2276,7 +2341,7 @@ main( int argc, char **argv ) default: rc = setup_trustdb(1, trustdb_name ); break; } if( rc ) - log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc)); + log_error(_("failed to initialize the TrustDB: %s\n"), gpg_strerror (rc)); switch (cmd) { @@ -2298,22 +2363,23 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("--store [filename]")); if( (rc = encode_store(fname)) ) - log_error_f( print_fname_stdin(fname), - "store failed: %s\n", g10_errstr(rc) ); + log_error ("\b%s: store failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); break; case aSym: /* encrypt the given file only with the symmetric cipher */ if( argc > 1 ) wrong_args(_("--symmetric [filename]")); if( (rc = encode_symmetric(fname)) ) - log_error_f(print_fname_stdin(fname), - "symmetric encryption failed: %s\n",g10_errstr(rc) ); + log_error ("\b%s: symmetric encryption failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); break; case aEncr: /* encrypt the given file */ if( argc > 1 ) wrong_args(_("--encrypt [filename]")); if( (rc = encode_crypt(fname,remusr)) ) - log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); + log_error("%s: encryption failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); break; case aEncrFiles: /* encrypt the given files */ @@ -2330,12 +2396,12 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("--sign [filename]")); if( argc ) { - sl = m_alloc_clear( sizeof *sl + strlen(fname)); + sl = xcalloc (1, sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } } if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) - log_error("signing failed: %s\n", g10_errstr(rc) ); + log_error("signing failed: %s\n", gpg_strerror (rc) ); free_strlist(sl); break; @@ -2343,13 +2409,13 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("--sign --encrypt [filename]")); if( argc ) { - sl = m_alloc_clear( sizeof *sl + strlen(fname)); + sl = xcalloc (1, sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } else sl = NULL; if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) - log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); + log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); free_strlist(sl); break; @@ -2359,7 +2425,7 @@ main( int argc, char **argv ) rc = sign_symencrypt_file (fname, locusr); if (rc) log_error("%s: sign+symmetric failed: %s\n", - print_fname_stdin(fname), g10_errstr(rc) ); + print_fname_stdin(fname), gpg_strerror (rc) ); break; case aClearsign: /* make a clearsig */ @@ -2367,24 +2433,24 @@ main( int argc, char **argv ) wrong_args(_("--clearsign [filename]")); if( (rc = clearsign_file(fname, locusr, NULL)) ) log_error("%s: clearsign failed: %s\n", - print_fname_stdin(fname), g10_errstr(rc) ); + print_fname_stdin(fname), gpg_strerror (rc) ); break; case aVerify: if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", g10_errstr(rc) ); + log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); break; case aVerifyFiles: if( (rc = verify_files( argc, argv ) )) - log_error("verify files failed: %s\n", g10_errstr(rc) ); + log_error("verify files failed: %s\n", gpg_strerror (rc) ); break; case aDecrypt: if( argc > 1 ) wrong_args(_("--decrypt [filename]")); if( (rc = decrypt_message( fname ) )) - log_error("decrypt_message failed: %s\n", g10_errstr(rc) ); + log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); break; case aDecryptFiles: @@ -2396,7 +2462,7 @@ main( int argc, char **argv ) wrong_args(_("--sign-key user-id")); username = make_username( fname ); keyedit_menu(fname, locusr, NULL, 1 ); - m_free(username); + xfree (username); break; case aLSignKey: @@ -2404,7 +2470,7 @@ main( int argc, char **argv ) wrong_args(_("--lsign-key user-id")); username = make_username( fname ); keyedit_menu(fname, locusr, NULL, 2 ); - m_free(username); + xfree (username); break; case aNRSignKey: @@ -2412,7 +2478,7 @@ main( int argc, char **argv ) wrong_args(_("--nrsign-key user-id")); username = make_username( fname ); keyedit_menu(fname, locusr, NULL, 3 ); - m_free(username); + xfree (username); break; case aNRLSignKey: @@ -2420,7 +2486,7 @@ main( int argc, char **argv ) wrong_args(_("--nrlsign-key user-id")); username = make_username( fname ); keyedit_menu(fname, locusr, NULL, 4 ); - m_free(username); + xfree (username); break; case aEditKey: /* Edit a key signature */ @@ -2436,7 +2502,7 @@ main( int argc, char **argv ) } else keyedit_menu(username, locusr, NULL, 0 ); - m_free(username); + xfree (username); break; case aDeleteKeys: @@ -2534,11 +2600,11 @@ main( int argc, char **argv ) if(rc) { if(cmd==aSendKeys) - log_error(_("keyserver send failed: %s\n"),g10_errstr(rc)); + log_error(_("keyserver send failed: %s\n"),gpg_strerror (rc)); else if(cmd==aRecvKeys) - log_error(_("keyserver receive failed: %s\n"),g10_errstr(rc)); + log_error(_("keyserver receive failed: %s\n"),gpg_strerror (rc)); else - log_error(_("key export failed: %s\n"),g10_errstr(rc)); + log_error(_("key export failed: %s\n"),gpg_strerror (rc)); } free_strlist(sl); break; @@ -2546,11 +2612,20 @@ main( int argc, char **argv ) case aSearchKeys: sl = NULL; for( ; argc; argc--, argv++ ) - append_to_strlist2( &sl, *argv, utf8_strings ); + { + if (utf8_strings) + sl = append_to_strlist ( &sl, *argv ); + else + { + char *p = native_to_utf8 ( *argv ); + sl = append_to_strlist( &sl, p ); + xfree( p ); + } + } rc=keyserver_search( sl ); if(rc) - log_error(_("keyserver search failed: %s\n"),g10_errstr(rc)); + log_error(_("keyserver search failed: %s\n"),gpg_strerror (rc)); free_strlist(sl); break; @@ -2560,7 +2635,7 @@ main( int argc, char **argv ) add_to_strlist2( &sl, *argv, utf8_strings ); rc=keyserver_refresh(sl); if(rc) - log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc)); + log_error(_("keyserver refresh failed: %s\n"),gpg_strerror (rc)); free_strlist(sl); break; @@ -2585,7 +2660,7 @@ main( int argc, char **argv ) wrong_args("--gen-revoke user-id"); username = make_username(*argv); gen_revoke( username ); - m_free( username ); + xfree ( username ); break; case aDesigRevoke: @@ -2593,7 +2668,7 @@ main( int argc, char **argv ) wrong_args("--desig-revoke user-id"); username = make_username(*argv); gen_desig_revoke( username ); - m_free( username ); + xfree ( username ); break; case aDeArmor: @@ -2601,7 +2676,7 @@ main( int argc, char **argv ) wrong_args("--dearmor [file]"); rc = dearmor_file( argc? *argv: NULL ); if( rc ) - log_error(_("dearmoring failed: %s\n"), g10_errstr(rc)); + log_error(_("dearmoring failed: %s\n"), gpg_strerror (rc)); break; case aEnArmor: @@ -2609,11 +2684,12 @@ main( int argc, char **argv ) wrong_args("--enarmor [file]"); rc = enarmor_file( argc? *argv: NULL ); if( rc ) - log_error(_("enarmoring failed: %s\n"), g10_errstr(rc)); + log_error(_("enarmoring failed: %s\n"), gpg_strerror (rc)); break; case aPrimegen: +#if 0 /*FIXME-XXX*/ { int mode = argc < 2 ? 0 : atoi(*argv); if( mode == 1 && argc == 2 ) { @@ -2625,7 +2701,7 @@ main( int argc, char **argv ) atoi(argv[2]), NULL,NULL ), 1); } else if( mode == 3 && argc == 3 ) { - MPI *factors; + gcry_mpi_t *factors; mpi_print( stdout, generate_elg_prime( 1, atoi(argv[1]), atoi(argv[2]), NULL,&factors ), 1); @@ -2633,7 +2709,7 @@ main( int argc, char **argv ) mpi_print( stdout, factors[0], 1 ); /* print q */ } else if( mode == 4 && argc == 3 ) { - MPI g = mpi_alloc(1); + gcry_mpi_t g = mpi_alloc(1); mpi_print( stdout, generate_elg_prime( 0, atoi(argv[1]), atoi(argv[2]), g, NULL ), 1); @@ -2645,6 +2721,7 @@ main( int argc, char **argv ) wrong_args("--gen-prime mode bits [qbits] "); putchar('\n'); } +#endif break; case aGenRandom: @@ -2664,14 +2741,14 @@ main( int argc, char **argv ) other tools */ size_t n = !endless && count < 99? count : 99; - p = get_random_bits( n*8, level, 0); + p = gcry_random_bytes (n, level); #ifdef HAVE_DOSISH_SYSTEM setmode ( fileno(stdout), O_BINARY ); #endif if (opt.armor) { char *tmp = make_radix64_string (p, n); fputs (tmp, stdout); - m_free (tmp); + xfree (tmp); if (n%3 == 1) putchar ('='); if (n%3) @@ -2679,7 +2756,7 @@ main( int argc, char **argv ) } else { fwrite( p, n, 1, stdout ); } - m_free(p); + xfree (p); if( !endless ) count -= n; } @@ -2693,7 +2770,7 @@ main( int argc, char **argv ) wrong_args("--print-md algo [files]"); { int all_algos = (**argv=='*' && !(*argv)[1]); - int algo = all_algos? 0 : string_to_digest_algo(*argv); + int algo = all_algos? 0 : gcry_md_map_name (*argv); if( !algo && !all_algos ) log_error(_("invalid hash algorithm `%s'\n"), *argv ); @@ -2750,7 +2827,7 @@ main( int argc, char **argv ) for( ; argc; argc--, argv++ ) { username = make_username( *argv ); list_trust_path( username ); - m_free(username); + xfree (username); } break; @@ -2804,7 +2881,7 @@ main( int argc, char **argv ) } rc = proc_packets(NULL, a ); if( rc ) - log_error("processing message failed: %s\n", g10_errstr(rc) ); + log_error("processing message failed: %s\n", gpg_strerror (rc) ); iobuf_close(a); } break; @@ -2821,14 +2898,14 @@ main( int argc, char **argv ) void g10_exit( int rc ) { - update_random_seed_file(); - if( opt.debug & DBG_MEMSTAT_VALUE ) { - m_print_stats("on exit"); - random_dump_stats(); - } - if( opt.debug ) - secmem_dump_stats(); - secmem_term(); + /* FIXME-XX update_random_seed_file(); */ +/* if( opt.debug & DBG_MEMSTAT_VALUE ) { */ +/* m_print_stats("on exit"); */ +/* random_dump_stats(); */ +/* } */ +/* if( opt.debug ) */ +/* secmem_dump_stats(); */ + gcry_control (GCRYCTL_TERM_SECMEM ); rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0; exit(rc ); @@ -2858,14 +2935,14 @@ print_hex( MD_HANDLE md, int algo, const char *fname ) else if(algo==DIGEST_ALGO_TIGER) indent+=printf(" TIGER = "); else if(algo>0) - indent+=printf("%6s = ",digest_algo_to_string(algo)); + indent+=printf("%6s = ", gcry_md_algo_name (algo)); else algo=abs(algo); count=indent; - p = md_read( md, algo ); - n = md_digest_length(algo); + p = gcry_md_read (md, algo); + n = gcry_md_get_algo_dlen (algo); count+=printf("%02X",*p++); @@ -2936,8 +3013,8 @@ print_hashline( MD_HANDLE md, int algo, const char *fname ) } putchar(':'); printf("%d:", algo ); - p = md_read( md, algo ); - n = md_digest_length(algo); + p = gcry_md_read (md, algo ); + n = gcry_md_get_algo_dlen (algo); for(i=0; i < n ; i++, p++ ) printf("%02X", *p ); putchar(':'); @@ -2966,47 +3043,47 @@ print_mds( const char *fname, int algo ) return; } - md = md_open( 0, 0 ); + gcry_md_open (&md, 0, 0 ); if( algo ) - md_enable( md, algo ); + gcry_md_enable ( md, algo ); else { - md_enable( md, DIGEST_ALGO_MD5 ); - md_enable( md, DIGEST_ALGO_SHA1 ); - md_enable( md, DIGEST_ALGO_RMD160 ); + gcry_md_enable (md, GCRY_MD_MD5 ); + gcry_md_enable (md, GCRY_MD_SHA1 ); + gcry_md_enable (md, GCRY_MD_RMD160 ); #ifdef USE_TIGER192 - md_enable( md, DIGEST_ALGO_TIGER ); + gcry_md_enable (md, GCRY_MD_TIGER ); #endif #ifdef USE_SHA256 - md_enable( md, DIGEST_ALGO_SHA256 ); + gcry_md_enable (md, GCRY_MD_SHA256 ); #endif #ifdef USE_SHA512 - md_enable( md, DIGEST_ALGO_SHA384 ); - md_enable( md, DIGEST_ALGO_SHA512 ); + gcry_md_enable (md, GCRY_MD_SHA384 ); + gcry_md_enable (md, GCRY_MD_SHA512 ); #endif } while( (n=fread( buf, 1, DIM(buf), fp )) ) - md_write( md, buf, n ); + gcry_md_write (md, buf, n); if( ferror(fp) ) log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); else { - md_final(md); + gcry_md_final (md); if ( opt.with_colons ) { if ( algo ) print_hashline( md, algo, fname ); else { - print_hashline( md, DIGEST_ALGO_MD5, fname ); - print_hashline( md, DIGEST_ALGO_SHA1, fname ); - print_hashline( md, DIGEST_ALGO_RMD160, fname ); + print_hashline( md, GCRY_MD_MD5, fname ); + print_hashline( md, GCRY_MD_SHA1, fname ); + print_hashline( md, GCRY_MD_RMD160, fname ); #ifdef USE_TIGER192 - print_hashline( md, DIGEST_ALGO_TIGER, fname ); + print_hashline( md, GCRY_MD_TIGER, fname ); #endif #ifdef USE_SHA256 - print_hashline( md, DIGEST_ALGO_SHA256, fname ); + print_hashline( md, GCRY_MD_SHA256, fname ); #endif #ifdef USE_SHA512 - print_hashline( md, DIGEST_ALGO_SHA384, fname ); - print_hashline( md, DIGEST_ALGO_SHA512, fname ); + print_hashline( md, GCRY_MD_SHA384, fname ); + print_hashline( md, GCRY_MD_SHA512, fname ); #endif } } @@ -3014,23 +3091,23 @@ print_mds( const char *fname, int algo ) if( algo ) print_hex(md,-algo,fname); else { - print_hex( md, DIGEST_ALGO_MD5, fname ); - print_hex( md, DIGEST_ALGO_SHA1, fname ); - print_hex( md, DIGEST_ALGO_RMD160, fname ); + print_hex( md, GCRY_MD_MD5, fname ); + print_hex( md, GCRY_MD_SHA1, fname ); + print_hex( md, GCRY_MD_RMD160, fname ); #ifdef USE_TIGER192 - print_hex( md, DIGEST_ALGO_TIGER, fname ); + print_hex( md, GCRY_MD_TIGER, fname ); #endif #ifdef USE_SHA256 - print_hex( md, DIGEST_ALGO_SHA256, fname ); + print_hex( md, GCRY_MD_SHA256, fname ); #endif #ifdef USE_SHA512 - print_hex( md, DIGEST_ALGO_SHA384, fname ); - print_hex( md, DIGEST_ALGO_SHA512, fname ); + print_hex( md, GCRY_MD_SHA384, fname ); + print_hex( md, GCRY_MD_SHA512, fname ); #endif } } } - md_close(md); + gcry_md_close (md); if( fp != stdin ) fclose(fp); diff --git a/g10/getkey.c b/g10/getkey.c index 1944c2a8d..79fcaf3e2 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -25,6 +25,8 @@ #include <string.h> #include <assert.h> #include <ctype.h> + +#include "gpg.h" #include "util.h" #include "packet.h" #include "memory.h" @@ -152,7 +154,7 @@ cache_public_key( PKT_public_key *pk ) return; } pk_cache_entries++; - ce = m_alloc( sizeof *ce ); + ce = xmalloc ( sizeof *ce ); ce->next = pk_cache; pk_cache = ce; ce->pk = copy_public_key( NULL, pk ); @@ -195,7 +197,7 @@ release_keyid_list ( keyid_list_t k ) { while ( k ) { keyid_list_t k2 = k->next; - m_free (k); + xfree (k); k = k2; } } @@ -216,7 +218,7 @@ cache_user_id( KBNODE keyblock ) for (k=keyblock; k; k = k->next ) { if ( k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - keyid_list_t a = m_alloc_clear ( sizeof *a ); + keyid_list_t a = xcalloc (1, sizeof *a ); /* Hmmm: For a long list of keyids it might be an advantage * to append the keys */ keyid_from_pk( k->pkt->pkt.public_key, a->keyid ); @@ -229,7 +231,7 @@ cache_user_id( KBNODE keyblock ) if( DBG_CACHE ) log_debug("cache_user_id: already in cache\n"); release_keyid_list ( keyids ); - m_free ( a ); + xfree ( a ); return; } } @@ -250,10 +252,10 @@ cache_user_id( KBNODE keyblock ) r = user_id_db; user_id_db = r->next; release_keyid_list ( r->keyids ); - m_free(r); + xfree (r); uid_cache_entries--; } - r = m_alloc( sizeof *r + uidlen-1 ); + r = xmalloc ( sizeof *r + uidlen-1 ); r->keyids = keyids; r->len = uidlen; memcpy(r->name, uid, r->len); @@ -273,7 +275,7 @@ getkey_disable_caches() for( ce = pk_cache; ce; ce = ce2 ) { ce2 = ce->next; free_public_key( ce->pk ); - m_free( ce ); + xfree ( ce ); } pk_cache_disabled=1; pk_cache_entries = 0; @@ -333,7 +335,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid ) #endif /* more init stuff */ if( !pk ) { - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); internal++; } @@ -361,7 +363,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid ) if( !rc ) goto leave; - rc = G10ERR_NO_PUBKEY; + rc = GPG_ERR_NO_PUBKEY; leave: if( !rc ) @@ -404,14 +406,14 @@ get_pubkey_fast (PKT_public_key *pk, u32 *keyid) if (rc == -1) { keydb_release (hd); - return G10ERR_NO_PUBKEY; + return GPG_ERR_NO_PUBKEY; } rc = keydb_get_keyblock (hd, &keyblock); keydb_release (hd); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - return G10ERR_NO_PUBKEY; + log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); + return GPG_ERR_NO_PUBKEY; } assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY @@ -494,7 +496,7 @@ get_seckey( PKT_secret_key *sk, u32 *keyid ) * check and does not tell us whether the secret key is valid. It * merely tells other whether there is some secret key. * Returns: 0 := key is available - * G10ERR_NO_SECKEY := not availabe + * GPG_ERR_NO_SECKEY := not availabe */ int seckey_available( u32 *keyid ) @@ -504,7 +506,7 @@ seckey_available( u32 *keyid ) rc = keydb_search_kid (hd, keyid); if ( rc == -1 ) - rc = G10ERR_NO_SECKEY; + rc = GPG_ERR_NO_SECKEY; keydb_release (hd); return rc; } @@ -729,13 +731,13 @@ static int skip_disabled(void *dummy,u32 *keyid) { int rc,disabled=0; - PKT_public_key *pk=m_alloc_clear(sizeof(PKT_public_key)); + PKT_public_key *pk=xcalloc (1,sizeof(PKT_public_key)); rc = get_pubkey(pk, keyid); if(rc) { log_error("error checking disabled status of %08lX: %s\n", - (ulong)keyid[1],g10_errstr(rc)); + (ulong)keyid[1],gpg_strerror (rc)); goto leave; } @@ -778,7 +780,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, /* build the search context */ for(n=0, r=namelist; r; r = r->next ) n++; - ctx = m_alloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items ); + ctx = xcalloc (1,sizeof *ctx + (n-1)*sizeof ctx->items ); ctx->nitems = n; for(n=0, r=namelist; r; r = r->next, n++ ) { @@ -787,8 +789,8 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, if (ctx->items[n].exact) ctx->exact = 1; if (!ctx->items[n].mode) { - m_free (ctx); - return G10ERR_INV_USER_ID; + xfree (ctx); + return GPG_ERR_INV_USER_ID; } if(!include_disabled && ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID @@ -886,7 +888,7 @@ get_pubkey_end( GETKEY_CTX ctx ) memset (&ctx->kbpos, 0, sizeof ctx->kbpos); keydb_release (ctx->kr_handle); if( !ctx->not_allocated ) - m_free( ctx ); + xfree ( ctx ); } } @@ -924,7 +926,7 @@ get_pubkey_byfprint( PKT_public_key *pk, get_pubkey_end( &ctx ); } else - rc = G10ERR_GENERAL; /* Oops */ + rc = GPG_ERR_GENERAL; /* Oops */ return rc; } @@ -954,14 +956,14 @@ get_pubkey_byfprint_fast (PKT_public_key *pk, if (rc == -1) { keydb_release (hd); - return G10ERR_NO_PUBKEY; + return GPG_ERR_NO_PUBKEY; } rc = keydb_get_keyblock (hd, &keyblock); keydb_release (hd); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - return G10ERR_NO_PUBKEY; + log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); + return GPG_ERR_NO_PUBKEY; } assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY @@ -1000,7 +1002,7 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, get_pubkey_end( &ctx ); } else - rc = G10ERR_GENERAL; /* Oops */ + rc = GPG_ERR_GENERAL; /* Oops */ return rc; } @@ -1118,7 +1120,7 @@ get_seckey_byfprint( PKT_secret_key *sk, get_pubkey_end( &ctx ); } else - rc = G10ERR_GENERAL; /* Oops */ + rc = GPG_ERR_GENERAL; /* Oops */ return rc; } @@ -1290,12 +1292,12 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PREF_COMPR, &n ); zip = p; nzip = p?n:0; if (uid->prefs) - m_free (uid->prefs); + xfree (uid->prefs); n = nsym + nhash + nzip; if (!n) uid->prefs = NULL; else { - uid->prefs = m_alloc (sizeof (*uid->prefs) * (n+1)); + uid->prefs = xmalloc (sizeof (*uid->prefs) * (n+1)); n = 0; for (; nsym; nsym--, n++) { uid->prefs[n].type = PREFTYPE_SYM; @@ -1364,7 +1366,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) */ /* In case this key was already merged */ - m_free(pk->revkey); + xfree (pk->revkey); pk->revkey=NULL; pk->numrevkeys=0; @@ -1400,7 +1402,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) int i; pk->revkey= - m_realloc(pk->revkey,sizeof(struct revocation_key)* + xrealloc(pk->revkey,sizeof(struct revocation_key)* (pk->numrevkeys+sig->numrevkeys)); for(i=0;i<sig->numrevkeys;i++) @@ -1451,7 +1453,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) } if(changed) - pk->revkey=m_realloc(pk->revkey, + pk->revkey=xrealloc(pk->revkey, pk->numrevkeys*sizeof(struct revocation_key)); } @@ -1594,7 +1596,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) { PKT_public_key *ultimate_pk; - ultimate_pk=m_alloc_clear(sizeof(*ultimate_pk)); + ultimate_pk=xcalloc (1,sizeof(*ultimate_pk)); /* We don't want to use the full get_pubkey to avoid infinite recursion in certain cases. @@ -1969,7 +1971,7 @@ merge_selfsigs( KBNODE keyblock ) || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { PKT_public_key *pk = k->pkt->pkt.public_key; if (pk->prefs) - m_free (pk->prefs); + xfree (pk->prefs); pk->prefs = copy_prefs (prefs); pk->mdc_feature = mdc_feature; } @@ -2326,7 +2328,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) rc = keydb_get_keyblock (ctx->kr_handle, &ctx->keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); rc = 0; goto skip; } @@ -2383,16 +2385,16 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) found: if( rc && rc != -1 ) - log_error("keydb_search failed: %s\n", g10_errstr(rc)); + log_error("keydb_search failed: %s\n", gpg_strerror (rc)); if( !rc ) { *ret_keyblock = ctx->keyblock; /* return the keyblock */ ctx->keyblock = NULL; } else if (rc == -1 && no_suitable_key) - rc = secmode ? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; + rc = secmode ? GPG_ERR_UNUSABLE_SECKEY : GPG_ERR_UNUSABLE_PUBKEY; else if( rc == -1 ) - rc = secmode ? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; + rc = secmode ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY; if ( secmode ) { release_kbnode( secblock ); @@ -2442,7 +2444,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk, if( !c ) { /* make a new context */ - c = m_alloc_clear( sizeof *c ); + c = xcalloc (1, sizeof *c ); *context = c; c->hd = keydb_new (1); c->first = 1; @@ -2453,7 +2455,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk, if( !sk ) { /* free the context */ keydb_release (c->hd); release_kbnode (c->keyblock); - m_free( c ); + xfree ( c ); *context = NULL; return 0; } @@ -2514,7 +2516,7 @@ get_user_id_string( u32 *keyid ) keyid_list_t a; for (a=r->keyids; a; a= a->next ) { if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = m_alloc( r->len + 10 ); + p = xmalloc ( r->len + 10 ); sprintf(p, "%08lX %.*s", (ulong)keyid[1], r->len, r->name ); return p; @@ -2522,7 +2524,7 @@ get_user_id_string( u32 *keyid ) } } } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = m_alloc( 15 ); + p = xmalloc ( 15 ); sprintf(p, "%08lX [?]", (ulong)keyid[1] ); return p; } @@ -2533,9 +2535,9 @@ get_user_id_string_printable ( u32 *keyid ) { char *p = get_user_id_string( keyid ); char *p2 = utf8_to_native( p, strlen(p), 0 ); - m_free(p); + xfree (p); p = make_printable_string (p2, strlen (p2), 0); - m_free (p2); + xfree (p2); return p; } @@ -2552,7 +2554,7 @@ get_long_user_id_string( u32 *keyid ) keyid_list_t a; for (a=r->keyids; a; a= a->next ) { if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = m_alloc( r->len + 20 ); + p = xmalloc ( r->len + 20 ); sprintf(p, "%08lX%08lX %.*s", (ulong)keyid[0], (ulong)keyid[1], r->len, r->name ); @@ -2561,7 +2563,7 @@ get_long_user_id_string( u32 *keyid ) } } } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = m_alloc( 25 ); + p = xmalloc ( 25 ); sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] ); return p; } @@ -2579,7 +2581,7 @@ get_user_id( u32 *keyid, size_t *rn ) keyid_list_t a; for (a=r->keyids; a; a= a->next ) { if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = m_alloc( r->len ); + p = xmalloc ( r->len ); memcpy(p, r->name, r->len ); *rn = r->len; return p; @@ -2587,7 +2589,7 @@ get_user_id( u32 *keyid, size_t *rn ) } } } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = m_strdup( _("[User id not found]") ); + p = xstrdup ( _("[User id not found]") ); *rn = strlen(p); return p; } @@ -2598,9 +2600,9 @@ get_user_id_printable( u32 *keyid ) size_t rn; char *p = get_user_id( keyid, &rn ); char *p2 = utf8_to_native( p, rn, 0 ); - m_free(p); + xfree (p); p = make_printable_string (p2, strlen (p2), 0); - m_free (p2); + xfree (p2); return p; } diff --git a/g10/global.h b/g10/global.h index 3c4e59ec4..d1c554dce 100644 --- a/g10/global.h +++ b/g10/global.h @@ -26,4 +26,6 @@ typedef struct kbnode_struct *KBNODE; typedef struct keydb_search_desc KEYDB_SEARCH_DESC; +#include "gpg.h" + #endif /*GPG_GLOBAL_H*/ diff --git a/g10/gpg.h b/g10/gpg.h index ca7699bca..bf61411f7 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -20,6 +20,11 @@ #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 diff --git a/g10/gpgv.c b/g10/gpgv.c index 67ecceabf..91574a78b 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -30,6 +30,7 @@ #endif #define INCLUDED_BY_MAIN_MODULE 1 +#include "gpg.h" #include "packet.h" #include "iobuf.h" #include "memory.h" @@ -82,8 +83,8 @@ int g10_errors_seen = 0; RISCOS_GLOBAL_STATICS("GnuPG (gpgv) Heap") #endif /* __riscos__ */ -const char * -strusage( int level ) +static const char * +my_strusage( int level ) { const char *p; switch( level ) { @@ -103,7 +104,7 @@ strusage( int level ) "Check signatures against known trusted keys\n"); break; - default: p = default_strusage(level); + default: p = NULL; } return p; } @@ -124,7 +125,7 @@ i18n_init(void) #else setlocale( LC_ALL, "" ); #endif - bindtextdomain( PACKAGE, G10_LOCALEDIR ); + bindtextdomain( PACKAGE, LOCALEDIR ); textdomain( PACKAGE ); #endif #endif @@ -144,7 +145,8 @@ main( int argc, char **argv ) riscos_global_defaults(); #endif /* __riscos__ */ - log_set_name("gpgv"); + set_strusage (my_strusage); + log_set_prefix ("gpgv", 1); init_signals(); i18n_init(); opt.command_fd = -1; /* no command fd */ @@ -177,7 +179,9 @@ main( int argc, char **argv ) 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_logfile( NULL, 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; @@ -200,7 +204,7 @@ main( int argc, char **argv ) FREE_STRLIST(nrings); if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", g10_errstr(rc) ); + log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); /* cleanup */ g10_exit(0); @@ -287,19 +291,19 @@ keyserver_import_keyid( u32 *keyid, void *dummy ) int get_session_key( PKT_pubkey_enc *k, DEK *dek ) { - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } /* Stub: */ int get_override_session_key( DEK *dek, const char *string ) { - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } /* Stub: */ int decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) { - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } @@ -317,7 +321,7 @@ display_online_help( const char *keyword ) int check_secret_key( PKT_secret_key *sk, int n ) { - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } /* Stub: @@ -355,26 +359,6 @@ void cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) {} void cipher_sync( CIPHER_HANDLE c ) {} -/* Stubs to avoid linking to ../cipher/random.c */ -void random_dump_stats(void) {} -int quick_random_gen( int onoff ) { return -1;} -void randomize_buffer( byte *buffer, size_t length, int level ) {} -int random_is_faked() { return -1;} -byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;} -void set_random_seed_file( const char *name ) {} -void update_random_seed_file() {} -void fast_random_poll() {} - -/* Stubs to avoid linking of ../cipher/primegen.c */ -void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {} -MPI generate_secret_prime( unsigned nbits ) { return NULL;} -MPI generate_public_prime( unsigned nbits ) { return NULL;} -MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **ret_factors ) { return NULL;} - -/* Do not link to ../cipher/rndlinux.c */ -void rndlinux_constructor(void) {} - /* Stubs to avoid linking to ../util/ttyio.c */ int tty_batchmode( int onoff ) { return 0; } @@ -393,4 +377,4 @@ 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 remove_lockfiles(void) {} +void dotlock_remove_lockfiles(void) {} diff --git a/g10/helptext.c b/g10/helptext.c index 0150c549c..4a65314eb 100644 --- a/g10/helptext.c +++ b/g10/helptext.c @@ -22,6 +22,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> + +#include "gpg.h" #include "util.h" #include "ttyio.h" #include "main.h" diff --git a/g10/import.c b/g10/import.c index 1b955c412..94e8914ec 100644 --- a/g10/import.c +++ b/g10/import.c @@ -56,9 +56,9 @@ struct stats_s { }; -static int import( IOBUF inp, const char* fname, +static int import( iobuf_t inp, const char* fname, struct stats_s *stats, unsigned int options ); -static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); +static int read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ); static void revocation_present(KBNODE keyblock); static int import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, unsigned int options); @@ -101,13 +101,13 @@ parse_import_options(char *str,unsigned int *options) void * import_new_stats_handle (void) { - return m_alloc_clear ( sizeof (struct stats_s) ); + return xcalloc (1, sizeof (struct stats_s) ); } void import_release_stats_handle (void *p) { - m_free (p); + xfree (p); } /**************** @@ -142,7 +142,7 @@ import_release_stats_handle (void *p) * */ static int -import_keys_internal( IOBUF inp, char **fnames, int nnames, +import_keys_internal( iobuf_t inp, char **fnames, int nnames, void *stats_handle, unsigned int options ) { int i, rc = 0; @@ -160,7 +160,7 @@ import_keys_internal( IOBUF inp, char **fnames, int nnames, for(i=0; i < nnames; i++ ) { const char *fname = fnames? fnames[i] : NULL; - IOBUF inp2 = iobuf_open(fname); + iobuf_t inp2 = iobuf_open(fname); if( !fname ) fname = "[stdin]"; if( !inp2 ) @@ -170,7 +170,7 @@ import_keys_internal( IOBUF inp, char **fnames, int nnames, iobuf_close(inp2); if( rc ) log_error("import from `%s' failed: %s\n", fname, - g10_errstr(rc) ); + gpg_strerror (rc) ); } if( !fname ) break; @@ -204,13 +204,13 @@ import_keys( char **fnames, int nnames, } int -import_keys_stream( IOBUF inp, void *stats_handle, unsigned int options ) +import_keys_stream( iobuf_t inp, void *stats_handle, unsigned int options ) { return import_keys_internal( inp, NULL, 0, stats_handle, options); } static int -import( IOBUF inp, const char* fname, +import( iobuf_t inp, const char* fname, struct stats_s *stats, unsigned int options ) { PACKET *pending_pkt = NULL; @@ -220,7 +220,7 @@ import( IOBUF inp, const char* fname, getkey_disable_caches(); if( !opt.no_armor ) { /* armored reading is not disabled */ - armor_filter_context_t *afx = m_alloc_clear( sizeof *afx ); + armor_filter_context_t *afx = xcalloc (1, sizeof *afx ); afx->only_keyblocks = 1; iobuf_push_filter2( inp, armor_filter, afx, 1 ); } @@ -247,8 +247,8 @@ import( IOBUF inp, const char* fname, } if( rc == -1 ) rc = 0; - else if( rc && rc != G10ERR_INV_KEYRING ) - log_error( _("error reading `%s': %s\n"), fname, g10_errstr(rc)); + else if( rc && rc != GPG_ERR_INV_KEYRING ) + log_error( _("error reading `%s': %s\n"), fname, gpg_strerror (rc)); return rc; } @@ -321,7 +321,7 @@ import_print_stats (void *hd) * Retunr: 0 = okay, -1 no more blocks or another errorcode. */ static int -read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) +read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ) { int rc; PACKET *pkt; @@ -335,13 +335,13 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) } else in_cert = 0; - pkt = m_alloc( sizeof *pkt ); + pkt = xmalloc ( sizeof *pkt ); init_packet(pkt); while( (rc=parse_packet(a, pkt)) != -1 ) { if( rc ) { /* ignore errors */ - if( rc != G10ERR_UNKNOWN_PACKET ) { - log_error("read_block: read error: %s\n", g10_errstr(rc) ); - rc = G10ERR_INV_KEYRING; + if( rc != GPG_ERR_UNKNOWN_PACKET ) { + log_error("read_block: read error: %s\n", gpg_strerror (rc) ); + rc = GPG_ERR_INV_KEYRING; goto ready; } free_packet( pkt ); @@ -363,11 +363,11 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) case PKT_COMPRESSED: if( pkt->pkt.compressed->algorithm < 1 || pkt->pkt.compressed->algorithm > 2 ) { - rc = G10ERR_COMPR_ALGO; + rc = GPG_ERR_COMPR_ALGO; goto ready; } { - compress_filter_context_t *cfx = m_alloc_clear( sizeof *cfx ); + compress_filter_context_t *cfx = xcalloc (1, sizeof *cfx ); cfx->algo = pkt->pkt.compressed->algorithm; pkt->pkt.compressed->buf = NULL; iobuf_push_filter2( a, compress_filter, cfx, 1 ); @@ -396,7 +396,7 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) root = new_kbnode( pkt ); else add_kbnode( root, new_kbnode( pkt ) ); - pkt = m_alloc( sizeof *pkt ); + pkt = xmalloc ( sizeof *pkt ); } init_packet(pkt); break; @@ -411,7 +411,7 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) else *ret_root = root; free_packet( pkt ); - m_free( pkt ); + xfree ( pkt ); return rc; } @@ -513,7 +513,7 @@ print_import_check (PKT_public_key * pk, PKT_user_id * id) u32 keyid[2]; size_t i, pos = 0, n; - buf = m_alloc (17+41+id->len+32); + buf = xmalloc (17+41+id->len+32); keyid_from_pk (pk, keyid); sprintf (buf, "%08X%08X ", keyid[0], keyid[1]); pos = 17; @@ -524,7 +524,7 @@ print_import_check (PKT_public_key * pk, PKT_user_id * id) pos += 1; strcat (buf, id->name); write_status_text (STATUS_IMPORT_CHECK, buf); - m_free (buf); + xfree (buf); } /**************** @@ -607,7 +607,7 @@ import_one( const char *fname, KBNODE keyblock, node->flag |= 1; log_info( _("key %08lX: accepted non self-signed user ID '%s'\n"), (ulong)keyid[1],user); - m_free(user); + xfree (user); } if( !delete_inv_parts( fname, keyblock, keyid, options ) ) { @@ -621,11 +621,12 @@ import_one( const char *fname, KBNODE keyblock, } /* do we have this key already in one of our pubrings ? */ - pk_orig = m_alloc_clear( sizeof *pk_orig ); + pk_orig = xcalloc (1, sizeof *pk_orig ); rc = get_pubkey_fast ( pk_orig, keyid ); - if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY ) { + if( rc && gpg_err_code (rc) != GPG_ERR_NO_PUBKEY + && gpg_err_code (rc) != GPG_ERR_UNUSABLE_PUBKEY ) { log_error( _("key %08lX: public key not found: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); } else if ( rc && opt.merge_only ) { if( opt.verbose ) @@ -638,16 +639,16 @@ import_one( const char *fname, KBNODE keyblock, rc = keydb_locate_writable (hd, NULL); if (rc) { - log_error (_("no writable keyring found: %s\n"), g10_errstr (rc)); + log_error (_("no writable keyring found: %s\n"), gpg_strerror (rc)); keydb_release (hd); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } if( opt.verbose > 1 ) log_info (_("writing to `%s'\n"), keydb_get_resource_name (hd) ); rc = keydb_insert_keyblock (hd, keyblock ); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc)); + keydb_get_resource_name (hd), gpg_strerror (rc)); else { /* This should not be possible since we delete the @@ -666,12 +667,12 @@ import_one( const char *fname, KBNODE keyblock, char *p=get_user_id_printable (keyid); log_info( _("key %08lX: public key \"%s\" imported\n"), (ulong)keyid[1],p); - m_free(p); + xfree (p); } if( is_status_enabled() ) { char *us = get_long_user_id_string( keyid ); write_status_text( STATUS_IMPORTED, us ); - m_free(us); + xfree (us); print_import_ok (pk,NULL, 1); } stats->imported++; @@ -704,14 +705,14 @@ import_one( const char *fname, KBNODE keyblock, } if( rc ) { log_error (_("key %08lX: can't locate original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); keydb_release (hd); goto leave; } rc = keydb_get_keyblock (hd, &keyblock_orig ); if (rc) { log_error (_("key %08lX: can't read original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); keydb_release (hd); goto leave; } @@ -733,7 +734,7 @@ import_one( const char *fname, KBNODE keyblock, rc = keydb_update_keyblock (hd, keyblock_orig); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc) ); + keydb_get_resource_name (hd), gpg_strerror (rc) ); else if(non_self) revalidation_mark (); @@ -758,7 +759,7 @@ import_one( const char *fname, KBNODE keyblock, else if( n_subk ) log_info( _("key %08lX: \"%s\" %d new subkeys\n"), (ulong)keyid[1], p, n_subk ); - m_free(p); + xfree (p); } stats->n_uids +=n_uids; @@ -777,7 +778,7 @@ import_one( const char *fname, KBNODE keyblock, char *p=get_user_id_printable(keyid); log_info( _("key %08lX: \"%s\" not changed\n"), (ulong)keyid[1],p); - m_free(p); + xfree (p); } stats->unchanged++; } @@ -810,8 +811,8 @@ sec_to_pub_keyblock(KBNODE sec_keyblock) write the keyblock out. */ PKT_secret_key *sk=secnode->pkt->pkt.secret_key; - PACKET *pkt=m_alloc_clear(sizeof(PACKET)); - PKT_public_key *pk=m_alloc_clear(sizeof(PKT_public_key)); + PACKET *pkt=xcalloc (1,sizeof(PACKET)); + PKT_public_key *pk=xcalloc (1,sizeof(PKT_public_key)); int n; if(secnode->pkt->pkttype==PKT_SECRET_KEY) @@ -905,20 +906,20 @@ import_secret_one( const char *fname, KBNODE keyblock, /* do we have this key already in one of our secrings ? */ rc = seckey_available( keyid ); - if( rc == G10ERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */ + if( rc == GPG_ERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */ KEYDB_HANDLE hd = keydb_new (1); /* get default resource */ rc = keydb_locate_writable (hd, NULL); if (rc) { - log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); + log_error (_("no default secret keyring: %s\n"), gpg_strerror (rc)); keydb_release (hd); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } rc = keydb_insert_keyblock (hd, keyblock ); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc) ); + keydb_get_resource_name (hd), gpg_strerror (rc) ); keydb_release (hd); /* we are ready */ if( !opt.quiet ) @@ -949,7 +950,7 @@ import_secret_one( const char *fname, KBNODE keyblock, } else log_error( _("key %08lX: secret key not found: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); return rc; } @@ -974,9 +975,9 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) keyid[0] = node->pkt->pkt.signature->keyid[0]; keyid[1] = node->pkt->pkt.signature->keyid[1]; - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); rc = get_pubkey( pk, keyid ); - if( rc == G10ERR_NO_PUBKEY ) { + if( rc == GPG_ERR_NO_PUBKEY ) { log_info( _("key %08lX: no public key - " "can't apply revocation certificate\n"), (ulong)keyid[1]); rc = 0; @@ -984,7 +985,7 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) } else if( rc ) { log_error( _("key %08lX: public key not found: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); goto leave; } @@ -1001,13 +1002,13 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) } if (rc) { log_error (_("key %08lX: can't locate original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); goto leave; } rc = keydb_get_keyblock (hd, &keyblock ); if (rc) { log_error (_("key %08lX: can't read original keyblock: %s\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); goto leave; } @@ -1018,7 +1019,7 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) rc = check_key_signature( keyblock, node, NULL); if( rc ) { log_error( _("key %08lX: invalid revocation certificate" - ": %s - rejected\n"), (ulong)keyid[1], g10_errstr(rc)); + ": %s - rejected\n"), (ulong)keyid[1], gpg_strerror (rc)); goto leave; } @@ -1044,14 +1045,14 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) rc = keydb_update_keyblock (hd, keyblock ); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), g10_errstr(rc) ); + keydb_get_resource_name (hd), gpg_strerror (rc) ); keydb_release (hd); hd = NULL; /* we are ready */ if( !opt.quiet ) { char *p=get_user_id_printable (keyid); log_info( _("key %08lX: \"%s\" revocation certificate imported\n"), (ulong)keyid[1],p); - m_free(p); + xfree (p); } stats->n_revoc++; @@ -1125,13 +1126,13 @@ chk_self_sigs( const char *fname, KBNODE keyblock, { char *p=utf8_to_native(unode->pkt->pkt.user_id->name, strlen(unode->pkt->pkt.user_id->name),0); - log_info( rc == G10ERR_PUBKEY_ALGO ? + log_info( rc == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key " "algorithm on user id \"%s\"\n"): _("key %08lX: invalid self-signature " "on user id \"%s\"\n"), (ulong)keyid[1],p); - m_free(p); + xfree (p); } else unode->flag |= 1; /* mark that signature checked */ @@ -1150,7 +1151,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock, else { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - log_info( rc == G10ERR_PUBKEY_ALGO ? + log_info( rc == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey binding\n"), (ulong)keyid[1]); @@ -1191,7 +1192,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock, else { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - log_info( rc == G10ERR_PUBKEY_ALGO ? + log_info( rc == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey revocation\n"), (ulong)keyid[1]); @@ -1281,7 +1282,8 @@ delete_inv_parts( const char *fname, KBNODE keyblock, subkey_seen = 1; } else if( node->pkt->pkttype == PKT_SIGNATURE - && check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo) + && openpgp_pk_test_algo( node->pkt->pkt.signature + ->pubkey_algo, 0) && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA ) delete_kbnode( node ); /* build_packet() can't handle this */ else if( node->pkt->pkttype == PKT_SIGNATURE && @@ -1320,7 +1322,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, { log_error( _("key %08lX: invalid revocation " "certificate: %s - skipped\n"), - (ulong)keyid[1], g10_errstr(rc)); + (ulong)keyid[1], gpg_strerror (rc)); delete_kbnode( node ); } } @@ -1489,7 +1491,8 @@ revocation_present(KBNODE keyblock) rc=get_pubkey_byfprint_fast (NULL,sig->revkey[idx]->fpr, MAX_FINGERPRINT_LEN); - if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + if ( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY + || gpg_err_code (rc) == GPG_ERR_UNUSABLE_PUBKEY) { /* No, so try and get it */ if(opt.keyserver_scheme && @@ -1508,7 +1511,8 @@ revocation_present(KBNODE keyblock) MAX_FINGERPRINT_LEN); } - if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY + || gpg_err_code (rc) == GPG_ERR_UNUSABLE_PUBKEY) log_info(_("WARNING: key %08lX may be revoked: " "revocation key %08lX not present.\n"), (ulong)keyid_from_pk(pk,NULL), @@ -1568,7 +1572,7 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, ++*n_sigs; log_info(_("key %08lX: \"%s\" revocation certificate added\n"), (ulong)keyid[1],p); - m_free(p); + xfree (p); } } } diff --git a/g10/kbnode.c b/g10/kbnode.c index 5df6d8d74..58daad871 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -23,6 +23,8 @@ #include <stdlib.h> #include <string.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "memory.h" #include "packet.h" @@ -41,7 +43,7 @@ alloc_node(void) if( n ) unused_nodes = n->next; else - n = m_alloc( sizeof *n ); + n = xmalloc ( sizeof *n ); n->next = NULL; n->pkt = NULL; n->flag = 0; @@ -58,7 +60,7 @@ free_node( KBNODE n ) n->next = unused_nodes; unused_nodes = n; #else - m_free( n ); + xfree ( n ); #endif } } @@ -94,7 +96,7 @@ release_kbnode( KBNODE n ) n2 = n->next; if( !is_cloned_kbnode(n) ) { free_packet( n->pkt ); - m_free( n->pkt ); + xfree ( n->pkt ); } free_node( n ); n = n2; @@ -267,7 +269,7 @@ commit_kbnode( KBNODE *root ) nl->next = n->next; if( !is_cloned_kbnode(n) ) { free_packet( n->pkt ); - m_free( n->pkt ); + xfree ( n->pkt ); } free_node( n ); changed = 1; @@ -291,7 +293,7 @@ remove_kbnode( KBNODE *root, KBNODE node ) nl->next = n->next; if( !is_cloned_kbnode(n) ) { free_packet( n->pkt ); - m_free( n->pkt ); + xfree ( n->pkt ); } free_node( n ); } diff --git a/g10/keydb.c b/g10/keydb.c index c67c36110..b64f38cbc 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -28,6 +28,7 @@ #include <sys/stat.h> #include <unistd.h> +#include "gpg.h" #include "util.h" #include "options.h" #include "main.h" /*try_make_homedir ()*/ @@ -84,7 +85,7 @@ keydb_add_resource (const char *url, int flags, int secret) { static int any_secret, any_public; const char *resname = url; - IOBUF iobuf = NULL; + iobuf_t iobuf = NULL; char *filename = NULL; int force=(flags&1); int rc = 0; @@ -103,7 +104,7 @@ keydb_add_resource (const char *url, int flags, int secret) #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) else if (strchr (resname, ':')) { log_error ("invalid key resource URL `%s'\n", url ); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; goto leave; } #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ @@ -116,7 +117,7 @@ keydb_add_resource (const char *url, int flags, int secret) filename = make_filename (opt.homedir, resname, NULL); } else - filename = m_strdup (resname); + filename = xstrdup (resname); if (!force) force = secret? !any_secret : !any_public; @@ -145,7 +146,7 @@ keydb_add_resource (const char *url, int flags, int secret) switch (rt) { case KEYDB_RESOURCE_TYPE_NONE: log_error ("unknown type of key resource `%s'\n", url ); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; goto leave; case KEYDB_RESOURCE_TYPE_KEYRING: @@ -156,7 +157,7 @@ keydb_add_resource (const char *url, int flags, int secret) if (!force) { - rc = G10ERR_OPEN_FILE; + rc = gpg_error_from_errno (errno); goto leave; } @@ -174,7 +175,7 @@ keydb_add_resource (const char *url, int flags, int secret) } if (access (filename, F_OK)) { - rc = G10ERR_OPEN_FILE; + rc = gpg_error_from_errno (errno); *last_slash_in_filename = DIRSEP_C; goto leave; } @@ -188,7 +189,7 @@ keydb_add_resource (const char *url, int flags, int secret) { log_error ( _("error creating keyring `%s': %s\n"), filename, strerror(errno)); - rc = G10ERR_OPEN_FILE; + rc = gpg_error_from_errno (errno); goto leave; } @@ -203,7 +204,7 @@ keydb_add_resource (const char *url, int flags, int secret) if(keyring_register_filename (filename, secret, &token)) { if (used_resources >= MAX_KEYDB_RESOURCES) - rc = G10ERR_RESOURCE_LIMIT; + rc = GPG_ERR_RESOURCE_LIMIT; else { if(flags&2) @@ -227,7 +228,7 @@ keydb_add_resource (const char *url, int flags, int secret) default: log_error ("resource type of `%s' not supported\n", url); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; goto leave; } @@ -235,12 +236,12 @@ keydb_add_resource (const char *url, int flags, int secret) leave: if (rc) - log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc)); + log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror (rc)); else if (secret) any_secret = 1; else any_public = 1; - m_free (filename); + xfree (filename); return rc; } @@ -253,7 +254,7 @@ keydb_new (int secret) KEYDB_HANDLE hd; int i, j; - hd = m_alloc_clear (sizeof *hd); + hd = xcalloc (1,sizeof *hd); hd->found = -1; assert (used_resources <= MAX_KEYDB_RESOURCES); @@ -271,7 +272,7 @@ keydb_new (int secret) 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) { - m_free (hd); + xfree (hd); return NULL; /* fixme: release all previously allocated handles*/ } j++; @@ -305,7 +306,7 @@ keydb_release (KEYDB_HANDLE hd) } } - m_free (hd); + xfree (hd); } @@ -413,14 +414,14 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) int rc = 0; if (!hd) - return G10ERR_INV_ARG; + 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 = G10ERR_GENERAL; /* oops */ + rc = GPG_ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb); @@ -439,7 +440,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) int rc = 0; if (!hd) - return G10ERR_INV_ARG; + return GPG_ERR_INV_ARG; if ( hd->found < 0 || hd->found >= hd->used) return -1; /* nothing found */ @@ -453,7 +454,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ + rc = GPG_ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb); @@ -475,7 +476,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) int idx; if (!hd) - return G10ERR_INV_ARG; + return GPG_ERR_INV_ARG; if( opt.dry_run ) return 0; @@ -485,7 +486,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) else if ( hd->current >= 0 && hd->current < hd->used) idx = hd->current; else - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; rc = lock_all (hd); if (rc) @@ -493,7 +494,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) switch (hd->active[idx].type) { case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ + rc = GPG_ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb); @@ -514,7 +515,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd) int rc = -1; if (!hd) - return G10ERR_INV_ARG; + return GPG_ERR_INV_ARG; if ( hd->found < 0 || hd->found >= hd->used) return -1; /* nothing found */ @@ -528,7 +529,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd) switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ + rc = GPG_ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_delete_keyblock (hd->active[hd->found].u.kr); @@ -551,7 +552,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) int rc; if (!hd) - return G10ERR_INV_ARG; + return GPG_ERR_INV_ARG; rc = keydb_search_reset (hd); /* this does reset hd->current */ if (rc) @@ -613,7 +614,7 @@ keydb_rebuild_caches (void) rc = keyring_rebuild_cache (all_resources[i].token); if (rc) log_error (_("failed to rebuild keyring cache: %s\n"), - g10_errstr (rc)); + gpg_strerror (rc)); break; } } @@ -630,7 +631,7 @@ keydb_search_reset (KEYDB_HANDLE hd) int i, rc = 0; if (!hd) - return G10ERR_INV_ARG; + return GPG_ERR_INV_ARG; hd->current = 0; hd->found = -1; @@ -659,7 +660,7 @@ keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, int rc = -1; if (!hd) - return G10ERR_INV_ARG; + return GPG_ERR_INV_ARG; while (rc == -1 && hd->current >= 0 && hd->current < hd->used) { switch (hd->active[hd->current].type) { diff --git a/g10/keydb.h b/g10/keydb.h index 7be5e7fff..6652db32a 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -75,7 +75,7 @@ struct keyblock_pos_struct { enum resource_type rt; off_t offset; /* position information */ unsigned count; /* length of the keyblock in packets */ - IOBUF fp; /* used by enum_keyblocks */ + iobuf_t fp; /* used by enum_keyblocks */ int secret; /* working on a secret keyring */ PACKET *pkt; /* ditto */ int valid; @@ -235,6 +235,7 @@ 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 ); diff --git a/g10/keyedit.c b/g10/keyedit.c index d36623a6a..38248a3d0 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -27,6 +27,7 @@ #include <assert.h> #include <ctype.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" @@ -107,19 +108,20 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, /* TODO: Make sure a cached sig record here still has the pk that issued it. See also keylist.c:list_keyblock_print */ - switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) { + rc = check_key_signature (keyblock, node, is_selfsig); + switch ( gpg_err_code (rc) ) { case 0: node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); sigrc = '!'; break; - case G10ERR_BAD_SIGN: + case GPG_ERR_BAD_SIGNATURE: node->flag = NODFLG_BADSIG; sigrc = '-'; if( inv_sigs ) ++*inv_sigs; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: + case GPG_ERR_NO_PUBKEY: + case GPG_ERR_UNUSABLE_PUBKEY: node->flag = NODFLG_NOKEY; sigrc = '?'; if( no_key ) @@ -146,7 +148,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, (sig->trust_depth>0)?'0'+sig->trust_depth:' ', (ulong)sig->keyid[1], datestr_from_sig(sig)); if( sigrc == '%' ) - tty_printf("[%s] ", g10_errstr(rc) ); + tty_printf("[%s] ", gpg_strerror (rc) ); else if( sigrc == '?' ) ; else if( *is_selfsig ) { @@ -157,7 +159,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, size_t n; char *p = get_user_id( sig->keyid, &n ); tty_print_utf8_string2( p, n, 40 ); - m_free(p); + xfree (p); } tty_printf("\n"); @@ -313,7 +315,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) *trust_value=60; else if(p[0]=='2' && !p[1]) *trust_value=120; - m_free(p); + xfree (p); } tty_printf("\n"); @@ -330,7 +332,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) trim_spaces(p); cpr_kill_prompt(); *trust_depth=atoi(p); - m_free(p); + xfree (p); if(*trust_depth<1 || *trust_depth>255) *trust_depth=0; } @@ -351,7 +353,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) char *q=p; int regexplen=100,ind; - *regexp=m_alloc(regexplen); + *regexp=xmalloc (regexplen); /* Now mangle the domain the user entered into a regexp. To do this, \-escape everything that isn't alphanumeric, and attach @@ -371,7 +373,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) if((regexplen-ind)<3) { regexplen+=100; - *regexp=m_realloc(*regexp,regexplen); + *regexp=xrealloc(*regexp,regexplen); } q++; @@ -381,7 +383,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) strcat(*regexp,">$"); } - m_free(p); + xfree (p); tty_printf("\n"); } @@ -504,7 +506,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, "self-signed.\n"),user); } - m_free(user); + xfree (user); } } else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE @@ -534,7 +536,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, { force_v4=1; node->flag|=NODFLG_DELSIG; - m_free(user); + xfree (user); continue; } } @@ -558,7 +560,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, in place. */ node->flag|=NODFLG_DELSIG; - m_free(user); + xfree (user); continue; } } @@ -583,7 +585,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, in place. */ node->flag|=NODFLG_DELSIG; - m_free(user); + xfree (user); continue; } } @@ -606,7 +608,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, { /* Don't delete the old sig here since this is an --expert thing. */ - m_free(user); + xfree (user); continue; } @@ -615,7 +617,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, write_status_text (STATUS_ALREADY_SIGNED, buf); uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */ - m_free(user); + xfree (user); } } } @@ -675,7 +677,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, } cpr_kill_prompt(); - m_free(answer); + xfree (answer); } } @@ -752,7 +754,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, else tty_printf(_("Invalid selection.\n")); - m_free(answer); + xfree (answer); } } @@ -764,7 +766,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, "with your key: \"")); p = get_user_id( sk_keyid, &n ); tty_print_utf8_string( p, n ); - m_free(p); p = NULL; + xfree (p); p = NULL; tty_printf("\" (%08lX)\n",(ulong)sk_keyid[1]); if(selfsig) @@ -856,14 +858,14 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, timestamp, duration, sign_mk_attrib, &attrib ); if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); + log_error(_("signing failed: %s\n"), gpg_strerror (rc)); goto leave; } *ret_modified = 1; /* we changed the keyblock */ update_trust = 1; - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE ); @@ -909,7 +911,7 @@ change_passphrase( KBNODE keyblock ) switch( is_secret_key_protected( sk ) ) { case -1: - rc = G10ERR_PUBKEY_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; break; case 0: tty_printf(_("This key is not protected.\n")); @@ -940,10 +942,10 @@ change_passphrase( KBNODE keyblock ) } if( rc ) - tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc)); + tty_printf(_("Can't edit this key: %s\n"), gpg_strerror (rc)); else { DEK *dek = NULL; - STRING2KEY *s2k = m_alloc_secure( sizeof *s2k ); + STRING2KEY *s2k = xmalloc_secure ( sizeof *s2k ); const char *errtext = NULL; tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); @@ -983,18 +985,18 @@ change_passphrase( KBNODE keyblock ) } } if( rc ) - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); else changed++; break; } } - m_free(s2k); - m_free(dek); + xfree (s2k); + xfree (dek); } leave: - m_free( passphrase ); + xfree ( passphrase ); set_next_passphrase( NULL ); return changed && !rc; } @@ -1172,7 +1174,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock); if (rc) { log_error (_("error reading secret keyblock `%s': %s\n"), - username, g10_errstr(rc)); + username, gpg_strerror (rc)); } else { merge_keys_and_selfsig( sec_keyblock ); @@ -1207,14 +1209,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, redisplay = 0; } do { - m_free(answer); + xfree (answer); if( have_commands ) { if( commands ) { - answer = m_strdup( commands->d ); + answer = xstrdup ( commands->d ); commands = commands->next; } else if( opt.batch ) { - answer = m_strdup("quit"); + answer = xstrdup ("quit"); } else have_commands = 0; @@ -1543,7 +1545,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, PKT_user_id *temp=keygen_get_std_prefs(); tty_printf(_("Current preference list:\n")); show_prefs(temp,1); - m_free(temp); + xfree (temp); } if (cpr_get_answer_is_yes ("keyedit.updpref.okay", count_selected_uids (keyblock)? @@ -1601,7 +1603,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, if( modified ) { rc = keydb_update_keyblock (kdbhd, keyblock); if( rc ) { - log_error(_("update failed: %s\n"), g10_errstr(rc) ); + log_error(_("update failed: %s\n"), gpg_strerror (rc) ); break; } } @@ -1609,7 +1611,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock ); if( rc ) { log_error( _("update secret failed: %s\n"), - g10_errstr(rc) ); + gpg_strerror (rc) ); break; } } @@ -1636,7 +1638,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, release_kbnode( keyblock ); release_kbnode( sec_keyblock ); keydb_release (kdbhd); - m_free(answer); + xfree (answer); } @@ -1666,7 +1668,7 @@ show_prefs (PKT_user_id *uid, int verbose) tty_printf (_("Cipher: ")); for(i=any=0; prefs[i].type; i++ ) { if( prefs[i].type == PREFTYPE_SYM ) { - const char *s = cipher_algo_to_string (prefs[i].value); + const char *s = gcry_cipher_algo_name (prefs[i].value); if (any) tty_printf (", "); @@ -1683,13 +1685,13 @@ show_prefs (PKT_user_id *uid, int verbose) if (!des_seen) { if (any) tty_printf (", "); - tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES)); + tty_printf ("%s", gcry_cipher_algo_name (CIPHER_ALGO_3DES)); } tty_printf ("\n "); tty_printf (_("Digest: ")); for(i=any=0; prefs[i].type; i++ ) { if( prefs[i].type == PREFTYPE_HASH ) { - const char *s = digest_algo_to_string (prefs[i].value); + const char *s = gcry_md_algo_name (prefs[i].value); if (any) tty_printf (", "); @@ -1706,7 +1708,7 @@ show_prefs (PKT_user_id *uid, int verbose) if (!sha1_seen) { if (any) tty_printf (", "); - tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1)); + tty_printf ("%s", gcry_md_algo_name (DIGEST_ALGO_SHA1)); } tty_printf ("\n "); tty_printf (_("Compression: ")); @@ -1984,7 +1986,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, u32 r_keyid[2]; char *user; const char *algo= - pubkey_algo_to_string(pk->revkey[i].algid); + gcry_pk_algo_name (pk->revkey[i].algid); keyid_from_fingerprint(pk->revkey[i].fpr, MAX_FINGERPRINT_LEN,r_keyid); @@ -1996,7 +1998,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, if ((pk->revkey[i].class&0x40)) tty_printf (_(" (sensitive)")); tty_printf ("\n"); - m_free(user); + xfree (user); } } @@ -2052,11 +2054,11 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, if( !rc ) tty_printf( _("rev! subkey has been revoked: %s\n"), datestr_from_sig( sig ) ); - else if( rc == G10ERR_BAD_SIGN ) + else if( gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) tty_printf( _("rev- faked revocation found\n") ); else if( rc ) tty_printf( _("rev? problem checking revocation: %s\n"), - g10_errstr(rc) ); + gpg_strerror (rc) ); } } /* the user ids */ @@ -2311,13 +2313,13 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) keygen_add_std_prefs, pk ); free_secret_key( sk ); if( rc ) { - log_error("signing failed: %s\n", g10_errstr(rc) ); + log_error("signing failed: %s\n", gpg_strerror (rc) ); free_user_id(uid); return 0; } /* insert/append to secret keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_USER_ID; pkt->pkt.user_id = scopy_user_id(uid); node = new_kbnode(pkt); @@ -2325,7 +2327,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) insert_kbnode( sec_where, node, 0 ); else add_kbnode( sec_keyblock, node ); - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = copy_signature(NULL, sig); if( sec_where ) @@ -2333,7 +2335,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) else add_kbnode( sec_keyblock, new_kbnode(pkt) ); /* insert/append to public keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_USER_ID; pkt->pkt.user_id = uid; node = new_kbnode(pkt); @@ -2341,7 +2343,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) insert_kbnode( pub_where, node, 0 ); else add_kbnode( pub_keyblock, node ); - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = copy_signature(NULL, sig); if( pub_where ) @@ -2586,7 +2588,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) if(revoker_pk) free_public_key(revoker_pk); - revoker_pk=m_alloc_clear(sizeof(*revoker_pk)); + revoker_pk=xcalloc (1,sizeof(*revoker_pk)); tty_printf("\n"); @@ -2599,7 +2601,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) if(rc) { - log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc)); + log_error (_("key `%s' not found: %s\n"),answer,gpg_strerror (rc)); continue; } @@ -2667,7 +2669,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ); - m_free(p); + xfree (p); tty_printf("\n"); print_fingerprint(revoker_pk,NULL,2); tty_printf("\n"); @@ -2693,7 +2695,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) keygen_add_revkey,&revkey ); if( rc ) { - log_error("signing failed: %s\n", g10_errstr(rc) ); + log_error("signing failed: %s\n", gpg_strerror (rc) ); goto fail; } @@ -2701,13 +2703,13 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) sk=NULL; /* insert into secret keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = copy_signature(NULL, sig); insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); /* insert into public keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); @@ -2821,23 +2823,23 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) sk, keygen_add_key_expire, sub_pk ); if( rc ) { log_error("make_keysig_packet failed: %s\n", - g10_errstr(rc)); + gpg_strerror (rc)); free_secret_key( sk ); return 0; } /* replace the packet */ - newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt = xcalloc (1, sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = newsig; free_packet( node->pkt ); - m_free( node->pkt ); + xfree ( node->pkt ); node->pkt = newpkt; if( sn ) { - newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt = xcalloc (1, sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = copy_signature( NULL, newsig ); free_packet( sn->pkt ); - m_free( sn->pkt ); + xfree ( sn->pkt ); sn->pkt = newpkt; } sub_pk = NULL; @@ -2930,7 +2932,7 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) log_info(_("skipping v3 self-signature on user id \"%s\"\n"), user); - m_free(user); + xfree (user); } else { /* This is a selfsignature which is to be replaced. @@ -2969,16 +2971,16 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) action > 0? "x":NULL ); if( rc ) { log_error ("update_keysig_packet failed: %s\n", - g10_errstr(rc)); + gpg_strerror (rc)); free_secret_key( sk ); return 0; } /* replace the packet */ - newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt = xcalloc (1, sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = newsig; free_packet( node->pkt ); - m_free( node->pkt ); + xfree ( node->pkt ); node->pkt = newpkt; modified = 1; } @@ -3039,7 +3041,7 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) log_info(_("skipping v3 self-signature on user id \"%s\"\n"), user); - m_free(user); + xfree (user); } else { /* This is a selfsignature which is to be replaced @@ -3056,16 +3058,16 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) NULL ); if( rc ) { log_error ("update_keysig_packet failed: %s\n", - g10_errstr(rc)); + gpg_strerror (rc)); free_secret_key( sk ); return 0; } /* replace the packet */ - newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt = xcalloc (1, sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = newsig; free_packet( node->pkt ); - m_free( node->pkt ); + xfree ( node->pkt ); node->pkt = newpkt; modified = 1; } @@ -3397,7 +3399,7 @@ menu_revsig( KBNODE keyblock ) attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable; node->flag &= ~NODFLG_MARK_A; - sk = m_alloc_secure_clear( sizeof *sk ); + sk = xcalloc_secure (1, sizeof *sk ); if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) { log_info(_("no secret key\n")); continue; @@ -3411,7 +3413,7 @@ menu_revsig( KBNODE keyblock ) &attrib ); free_secret_key(sk); if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); + log_error(_("signing failed: %s\n"), gpg_strerror (rc)); release_revocation_reason_info( reason ); return changed; } @@ -3421,7 +3423,7 @@ menu_revsig( KBNODE keyblock ) if(primary_pk->keyid[0]==sig->keyid[0] && primary_pk->keyid[1]==sig->keyid[1]) unode->pkt->pkt.user_id->is_revoked=1; - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( unode, new_kbnode(pkt), 0 ); @@ -3470,7 +3472,7 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock ) { char *user=utf8_to_native(uid->name,uid->len,0); log_info(_("user ID \"%s\" is already revoked\n"),user); - m_free(user); + xfree (user); } else { @@ -3502,12 +3504,12 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock ) sign_mk_attrib, &attrib ); if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); + log_error(_("signing failed: %s\n"), gpg_strerror (rc)); goto leave; } else { - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( node, new_kbnode(pkt), 0 ); @@ -3575,13 +3577,13 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) sign_mk_attrib, &attrib ); free_secret_key(sk); if( rc ) { - log_error(_("signing failed: %s\n"), g10_errstr(rc)); + log_error(_("signing failed: %s\n"), gpg_strerror (rc)); release_revocation_reason_info( reason ); return changed; } changed = 1; /* we changed the keyblock */ - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( node, new_kbnode(pkt), 0 ); diff --git a/g10/keygen.c b/g10/keygen.c index ff6fec852..041a495bd 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -26,6 +26,8 @@ #include <ctype.h> #include <errno.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "main.h" #include "packet.h" @@ -81,13 +83,13 @@ struct output_control_s { struct { char *fname; char *newfname; - IOBUF stream; + iobuf_t stream; armor_filter_context_t afx; } pub; struct { char *fname; char *newfname; - IOBUF stream; + iobuf_t stream; armor_filter_context_t afx; } sec; }; @@ -110,17 +112,17 @@ static int mdc_available,ks_modify; static void do_generate_keypair( struct para_data_s *para, struct output_control_s *outctrl ); -static int write_keyblock( IOBUF out, KBNODE node ); +static int write_keyblock( iobuf_t out, KBNODE node ); static void write_uid( KBNODE root, const char *s ) { - PACKET *pkt = m_alloc_clear(sizeof *pkt ); + PACKET *pkt = xcalloc (1,sizeof *pkt ); size_t n = strlen(s); pkt->pkttype = PKT_USER_ID; - pkt->pkt.user_id = m_alloc_clear( sizeof *pkt->pkt.user_id + n - 1 ); + pkt->pkt.user_id = xcalloc (1, sizeof *pkt->pkt.user_id + n - 1 ); pkt->pkt.user_id->len = n; pkt->pkt.user_id->ref = 1; strcpy(pkt->pkt.user_id->name, s); @@ -241,7 +243,7 @@ keygen_set_std_prefs (const char *string,int personal) if (!string || !ascii_strcasecmp (string, "default")) { if (opt.def_preference_list) string=opt.def_preference_list; - else if ( !check_cipher_algo(CIPHER_ALGO_IDEA) ) + else if ( !openpgp_cipher_test_algo(CIPHER_ALGO_IDEA) ) string = AES CAST5 "S2 S1 H2 H3 Z2 Z1"; else string = AES CAST5 "S2 H2 H3 Z2 Z1"; @@ -261,16 +263,16 @@ keygen_set_std_prefs (const char *string,int personal) { char *tok,*prefstring; - prefstring=m_strdup(string); /* need a writable string! */ + prefstring=xstrdup (string); /* need a writable string! */ while((tok=strsep(&prefstring," ,"))) { - if((val=string_to_cipher_algo(tok))) + if((val=openpgp_cipher_map_name(tok))) { if(set_one_pref(val,1,tok,sym,&nsym)) rc=-1; } - else if((val=string_to_digest_algo(tok))) + else if((val=openpgp_md_map_name(tok))) { if(set_one_pref(val,2,tok,hash,&nhash)) rc=-1; @@ -301,7 +303,7 @@ keygen_set_std_prefs (const char *string,int personal) } } - m_free(prefstring); + xfree (prefstring); } if(!rc) @@ -310,7 +312,7 @@ keygen_set_std_prefs (const char *string,int personal) { if(personal==PREFTYPE_SYM) { - m_free(opt.personal_cipher_prefs); + xfree (opt.personal_cipher_prefs); if(nsym==0) opt.personal_cipher_prefs=NULL; @@ -319,7 +321,7 @@ keygen_set_std_prefs (const char *string,int personal) int i; opt.personal_cipher_prefs= - m_alloc(sizeof(prefitem_t *)*(nsym+1)); + xmalloc (sizeof(prefitem_t *)*(nsym+1)); for (i=0; i<nsym; i++) { @@ -333,7 +335,7 @@ keygen_set_std_prefs (const char *string,int personal) } else if(personal==PREFTYPE_HASH) { - m_free(opt.personal_digest_prefs); + xfree (opt.personal_digest_prefs); if(nhash==0) opt.personal_digest_prefs=NULL; @@ -342,7 +344,7 @@ keygen_set_std_prefs (const char *string,int personal) int i; opt.personal_digest_prefs= - m_alloc(sizeof(prefitem_t *)*(nhash+1)); + xmalloc (sizeof(prefitem_t *)*(nhash+1)); for (i=0; i<nhash; i++) { @@ -356,7 +358,7 @@ keygen_set_std_prefs (const char *string,int personal) } else if(personal==PREFTYPE_ZIP) { - m_free(opt.personal_compress_prefs); + xfree (opt.personal_compress_prefs); if(nzip==0) opt.personal_compress_prefs=NULL; @@ -365,7 +367,7 @@ keygen_set_std_prefs (const char *string,int personal) int i; opt.personal_compress_prefs= - m_alloc(sizeof(prefitem_t *)*(nzip+1)); + xmalloc (sizeof(prefitem_t *)*(nzip+1)); for (i=0; i<nzip; i++) { @@ -400,12 +402,12 @@ keygen_set_std_prefs (const char *string,int personal) PKT_user_id *keygen_get_std_prefs(void) { int i,j=0; - PKT_user_id *uid=m_alloc_clear(sizeof(PKT_user_id)); + PKT_user_id *uid=xcalloc (1,sizeof(PKT_user_id)); if(!prefs_initialized) keygen_set_std_prefs(NULL,0); - uid->prefs=m_alloc((sizeof(prefitem_t *)* + uid->prefs=xmalloc ((sizeof(prefitem_t *)* (nsym_prefs+nhash_prefs+nzip_prefs+1))); for(i=0;i<nsym_prefs;i++,j++) @@ -451,10 +453,10 @@ add_feature_mdc (PKT_signature *sig,int enabled) if (!s || !n) { /* create a new one */ n = 1; - buf = m_alloc_clear (n); + buf = xcalloc (1,n); } else { - buf = m_alloc (n); + buf = xmalloc (n); memcpy (buf, s, n); } @@ -473,7 +475,7 @@ add_feature_mdc (PKT_signature *sig,int enabled) else build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n); - m_free (buf); + xfree (buf); } static void @@ -495,10 +497,10 @@ add_keyserver_modify (PKT_signature *sig,int enabled) if (!s || !n) { /* create a new one */ n = 1; - buf = m_alloc_clear (n); + buf = xcalloc (1,n); } else { - buf = m_alloc (n); + buf = xmalloc (n); memcpy (buf, s, n); } @@ -517,7 +519,7 @@ add_keyserver_modify (PKT_signature *sig,int enabled) else build_sig_subpkt (sig, SIGSUBPKT_KS_FLAGS, buf, n); - m_free (buf); + xfree (buf); } int @@ -624,11 +626,11 @@ write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, rc = make_keysig_packet(&sig,pk,NULL,NULL,sk,0x1F,0,0,0,0, keygen_add_revkey,revkey); if( rc ) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + log_error("make_keysig_packet failed: %s\n", gpg_strerror (rc) ); return rc; } - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; add_kbnode( root, new_kbnode( pkt ) ); @@ -668,11 +670,11 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, keygen_add_std_prefs, pk ); if( rc ) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + log_error("make_keysig_packet failed: %s\n", gpg_strerror (rc) ); return rc; } - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; add_kbnode( root, new_kbnode( pkt ) ); @@ -717,11 +719,11 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, rc = make_keysig_packet( &sig, pk, NULL, subpk, sk, 0x18, 0, 0, 0, 0, keygen_add_key_flags_and_expire, &oduap ); if( rc ) { - log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); + log_error("make_keysig_packet failed: %s\n", gpg_strerror (rc) ); return rc; } - pkt = m_alloc_clear( sizeof *pkt ); + pkt = xcalloc (1, sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; add_kbnode( root, new_kbnode( pkt ) ); @@ -738,8 +740,8 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PACKET *pkt; PKT_secret_key *sk; PKT_public_key *pk; - MPI skey[4]; - MPI *factors; + gcry_mpi_t skey[4]; + gcry_mpi_t *factors; assert( is_ELGAMAL(algo) ); @@ -753,14 +755,15 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, log_info(_("keysize rounded up to %u bits\n"), nbits ); } - rc = pubkey_generate( algo, nbits, skey, &factors ); +#warning need to implement this + rc = -1 /*pubkey_generate( algo, nbits, skey, &factors )*/; if( rc ) { - log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); return rc; } - sk = m_alloc_clear( sizeof *sk ); - pk = m_alloc_clear( sizeof *pk ); + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = 4; if( expireval ) { @@ -786,21 +789,21 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, sk->protect.s2k = *s2k; rc = protect_secret_key( sk, dek ); if( rc ) { - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); free_public_key(pk); free_secret_key(sk); return rc; } } - pkt = m_alloc_clear(sizeof *pkt); + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; pkt->pkt.public_key = pk; add_kbnode(pub_root, new_kbnode( pkt )); /* don't know whether it makes sense to have the factors, so for now * we store them in the secret keyring (but they are not secret) */ - pkt = m_alloc_clear(sizeof *pkt); + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; pkt->pkt.secret_key = sk; add_kbnode(sec_root, new_kbnode( pkt )); @@ -824,8 +827,8 @@ gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PACKET *pkt; PKT_secret_key *sk; PKT_public_key *pk; - MPI skey[5]; - MPI *factors; + gcry_mpi_t skey[5]; + gcry_mpi_t *factors; if( nbits > 1024 || nbits < 512 ) { nbits = 1024; @@ -837,14 +840,15 @@ gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, log_info(_("keysize rounded up to %u bits\n"), nbits ); } - rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors ); +#warning need to implement this + rc = -1 /*pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors )*/; if( rc ) { - log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); return rc; } - sk = m_alloc_clear( sizeof *sk ); - pk = m_alloc_clear( sizeof *pk ); + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = 4; if( expireval ) { @@ -872,14 +876,14 @@ gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, sk->protect.s2k = *s2k; rc = protect_secret_key( sk, dek ); if( rc ) { - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); free_public_key(pk); free_secret_key(sk); return rc; } } - pkt = m_alloc_clear(sizeof *pkt); + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; pkt->pkt.public_key = pk; add_kbnode(pub_root, new_kbnode( pkt )); @@ -890,7 +894,7 @@ gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, * We store only f1 to f_n-1; fn can be calculated because p and q * are known. */ - pkt = m_alloc_clear(sizeof *pkt); + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; pkt->pkt.secret_key = sk; add_kbnode(sec_root, new_kbnode( pkt )); @@ -913,8 +917,8 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PACKET *pkt; PKT_secret_key *sk; PKT_public_key *pk; - MPI skey[6]; - MPI *factors; + gcry_mpi_t skey[6]; + gcry_mpi_t *factors; assert( is_RSA(algo) ); @@ -928,14 +932,15 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, log_info(_("keysize rounded up to %u bits\n"), nbits ); } - rc = pubkey_generate( algo, nbits, skey, &factors ); +#warning need to implement this + rc = -1 /*pubkey_generate( algo, nbits, skey, &factors )*/; if( rc ) { - log_error("pubkey_generate failed: %s\n", g10_errstr(rc) ); + log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); return rc; } - sk = m_alloc_clear( sizeof *sk ); - pk = m_alloc_clear( sizeof *pk ); + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = 4; if( expireval ) { @@ -965,19 +970,19 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, sk->protect.s2k = *s2k; rc = protect_secret_key( sk, dek ); if( rc ) { - log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); free_public_key(pk); free_secret_key(sk); return rc; } } - pkt = m_alloc_clear(sizeof *pkt); + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; pkt->pkt.public_key = pk; add_kbnode(pub_root, new_kbnode( pkt )); - pkt = m_alloc_clear(sizeof *pkt); + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; pkt->pkt.secret_key = sk; add_kbnode(sec_root, new_kbnode( pkt )); @@ -1043,7 +1048,7 @@ ask_algo (int addmode, unsigned int *r_usage) answer = cpr_get("keygen.algo",_("Your selection? ")); cpr_kill_prompt(); algo = *answer? atoi(answer): 1; - m_free(answer); + xfree (answer); if( algo == 1 && !addmode ) { algo = 0; /* create both keys */ break; @@ -1103,7 +1108,7 @@ ask_keysize( int algo ) " minimum keysize is 768 bits\n" " default keysize is 1024 bits\n" " highest suggested keysize is 2048 bits\n"), - pubkey_algo_to_string(algo) ); + gcry_pk_algo_name (algo) ); } for(;;) { @@ -1111,7 +1116,7 @@ ask_keysize( int algo ) _("What keysize do you want? (1024) ")); cpr_kill_prompt(); nbits = *answer? atoi(answer): 1024; - m_free(answer); + xfree (answer); if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) ) tty_printf(_("DSA only allows keysizes from 512 to 1024\n")); else if( algo == PUBKEY_ALGO_RSA && nbits < 1024 ) @@ -1234,7 +1239,7 @@ ask_expire_interval(int object) for(;;) { u32 curtime=make_timestamp(); - m_free(answer); + xfree (answer); if(object==0) answer = cpr_get("keygen.valid",_("Key is valid for? (0) ")); else @@ -1269,7 +1274,7 @@ ask_expire_interval(int object) _("Is this correct (y/n)? ")) ) break; } - m_free(answer); + xfree (answer); return interval; } @@ -1280,6 +1285,19 @@ ask_expiredate() return x? make_timestamp() + x : 0; } + +static int +count_chr( const char *string, int c ) +{ + int count; + + for (count=0; *string; string++ ) + if ( *string == c ) + count++; + return count; +} + + static int has_invalid_email_chars( const char *s ) { @@ -1320,7 +1338,7 @@ ask_user_id( int mode ) if( !aname ) { for(;;) { - m_free(aname); + xfree (aname); aname = cpr_get("keygen.name",_("Real name: ")); trim_spaces(aname); cpr_kill_prompt(); @@ -1340,14 +1358,14 @@ ask_user_id( int mode ) } if( !amail ) { for(;;) { - m_free(amail); + xfree (amail); amail = cpr_get("keygen.email",_("Email address: ")); trim_spaces(amail); cpr_kill_prompt(); if( !*amail ) break; /* no email address is okay */ else if( has_invalid_email_chars(amail) - || string_count_chr(amail,'@') != 1 + || count_chr(amail,'@') != 1 || *amail == '@' || amail[strlen(amail)-1] == '@' || amail[strlen(amail)-1] == '.' @@ -1359,7 +1377,7 @@ ask_user_id( int mode ) } if( !acomment ) { for(;;) { - m_free(acomment); + xfree (acomment); acomment = cpr_get("keygen.comment",_("Comment: ")); trim_spaces(acomment); cpr_kill_prompt(); @@ -1373,19 +1391,14 @@ ask_user_id( int mode ) } - m_free(uid); - uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10); + xfree (uid); + uid = p = xmalloc (strlen(aname)+strlen(amail)+strlen(acomment)+12+10); p = stpcpy(p, aname ); if( *acomment ) p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")"); if( *amail ) p = stpcpy(stpcpy(stpcpy(p," <"), amail),">"); - /* append a warning if we do not have dev/random - * or it is switched into quick testmode */ - if( quick_random_gen(-1) ) - strcpy(p, " (INSECURE!)" ); - /* print a note in case that UTF8 mapping has to be done */ for(p=uid; *p; p++ ) { if( *p & 0x80 ) { @@ -1409,7 +1422,7 @@ ask_user_id( int mode ) if( strlen(ansstr) != 10 ) BUG(); if( cpr_enabled() ) { - answer = m_strdup(ansstr+6); + answer = xstrdup (ansstr+6); answer[1] = 0; } else { @@ -1421,15 +1434,15 @@ ask_user_id( int mode ) if( strlen(answer) > 1 ) ; else if( *answer == ansstr[0] || *answer == ansstr[1] ) { - m_free(aname); aname = NULL; + xfree (aname); aname = NULL; break; } else if( *answer == ansstr[2] || *answer == ansstr[3] ) { - m_free(acomment); acomment = NULL; + xfree (acomment); acomment = NULL; break; } else if( *answer == ansstr[4] || *answer == ansstr[5] ) { - m_free(amail); amail = NULL; + xfree (amail); amail = NULL; break; } else if( *answer == ansstr[6] || *answer == ansstr[7] ) { @@ -1437,29 +1450,29 @@ ask_user_id( int mode ) tty_printf(_("Please correct the error first\n")); } else { - m_free(aname); aname = NULL; - m_free(acomment); acomment = NULL; - m_free(amail); amail = NULL; + xfree (aname); aname = NULL; + xfree (acomment); acomment = NULL; + xfree (amail); amail = NULL; break; } } else if( *answer == ansstr[8] || *answer == ansstr[9] ) { - m_free(aname); aname = NULL; - m_free(acomment); acomment = NULL; - m_free(amail); amail = NULL; - m_free(uid); uid = NULL; + xfree (aname); aname = NULL; + xfree (acomment); acomment = NULL; + xfree (amail); amail = NULL; + xfree (uid); uid = NULL; break; } - m_free(answer); + xfree (answer); } - m_free(answer); + xfree (answer); if( !amail && !acomment && !amail ) break; - m_free(uid); uid = NULL; + xfree (uid); uid = NULL; } if( uid ) { char *p = native_to_utf8( uid ); - m_free( uid ); + xfree ( uid ); uid = p; } return uid; @@ -1475,7 +1488,7 @@ ask_passphrase( STRING2KEY **ret_s2k ) tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); - s2k = m_alloc_secure( sizeof *s2k ); + s2k = xmalloc_secure ( sizeof *s2k ); for(;;) { s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; @@ -1486,8 +1499,8 @@ ask_passphrase( STRING2KEY **ret_s2k ) tty_printf(_("%s.\n"), _(errtext)); } else if( !dek->keylen ) { - m_free(dek); dek = NULL; - m_free(s2k); s2k = NULL; + xfree (dek); dek = NULL; + xfree (s2k); s2k = NULL; tty_printf(_( "You don't want a passphrase - this is probably a *bad* idea!\n" "I will do it anyway. You can change your passphrase at any time,\n" @@ -1552,7 +1565,7 @@ generate_user_id() if( !p ) return NULL; n = strlen(p); - uid = m_alloc_clear( sizeof *uid + n - 1 ); + uid = xcalloc (1, sizeof *uid + n - 1 ); uid->len = n; strcpy(uid->name, p); uid->ref = 1; @@ -1568,11 +1581,11 @@ release_parameter_list( struct para_data_s *r ) for( ; r ; r = r2 ) { r2 = r->next; if( r->key == pPASSPHRASE_DEK ) - m_free( r->u.dek ); + xfree ( r->u.dek ); else if( r->key == pPASSPHRASE_S2K ) - m_free( r->u.s2k ); + xfree ( r->u.s2k ); - m_free(r); + xfree (r); } } @@ -1603,7 +1616,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key ) if( isdigit( *r->u.value ) ) i = atoi( r->u.value ); else - i = string_to_pubkey_algo( r->u.value ); + i = openpgp_pk_map_name ( r->u.value ); if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S) i = 0; /* we don't want to allow generation of these algorithms */ return i; @@ -1750,7 +1763,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, /* check that we have all required parameters */ assert( get_parameter( para, pKEYTYPE ) ); i = get_parameter_algo( para, pKEYTYPE ); - if( i < 1 || check_pubkey_algo2( i, PUBKEY_USAGE_SIG ) ) { + if( i < 1 || openpgp_pk_test_algo ( i, PUBKEY_USAGE_SIG ) ) { r = get_parameter( para, pKEYTYPE ); log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); return -1; @@ -1760,7 +1773,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, return -1; i = get_parameter_algo( para, pSUBKEYTYPE ); - if( i > 0 && check_pubkey_algo( i ) ) { + if( i > 0 && openpgp_pk_test_algo ( i, 0 ) ) { r = get_parameter( para, pSUBKEYTYPE ); log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); return -1; @@ -1776,7 +1789,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, s3 = get_parameter_value( para, pNAMEEMAIL ); if( s1 || s2 || s3 ) { n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0); - r = m_alloc_clear( sizeof *r + n + 20 ); + r = xcalloc (1, sizeof *r + n + 20 ); r->key = pUSERID; p = r->u.value; if( s1 ) @@ -1806,7 +1819,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, STRING2KEY *s2k; DEK *dek; - s2k = m_alloc_secure( sizeof *s2k ); + s2k = xmalloc_secure ( sizeof *s2k ); s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; set_next_passphrase( r->u.value ); @@ -1816,12 +1829,12 @@ proc_parameter_file( struct para_data_s *para, const char *fname, assert( dek ); memset( r->u.value, 0, strlen(r->u.value) ); - r = m_alloc_clear( sizeof *r ); + r = xcalloc (1, sizeof *r ); r->key = pPASSPHRASE_S2K; r->u.s2k = s2k; r->next = para; para = r; - r = m_alloc_clear( sizeof *r ); + r = xcalloc (1, sizeof *r ); r->key = pPASSPHRASE_DEK; r->u.dek = dek; r->next = para; @@ -1839,7 +1852,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, r->u.expire = i * 86400L; r->key = pKEYEXPIRE; /* change hat entry */ /* also set it for the subkey */ - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pSUBKEYEXPIRE; r->u.expire = i * 86400L; r->next = para; @@ -1943,8 +1956,8 @@ read_parameter_file( const char *fname ) if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) ) ; /* still the same file - ignore it */ else { - m_free( outctrl.pub.newfname ); - outctrl.pub.newfname = m_strdup( value ); + xfree ( outctrl.pub.newfname ); + outctrl.pub.newfname = xstrdup ( value ); outctrl.use_files = 1; } } @@ -1952,8 +1965,8 @@ read_parameter_file( const char *fname ) if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) ) ; /* still the same file - ignore it */ else { - m_free( outctrl.sec.newfname ); - outctrl.sec.newfname = m_strdup( value ); + xfree ( outctrl.sec.newfname ); + outctrl.sec.newfname = xstrdup ( value ); outctrl.use_files = 1; } } @@ -2009,7 +2022,7 @@ read_parameter_file( const char *fname ) break; } } - r = m_alloc_clear( sizeof *r + strlen( value ) ); + r = xcalloc (1, sizeof *r + strlen( value ) ); r->lnr = lnr; r->key = keywords[i].key; strcpy( r->u.value, value ); @@ -2029,10 +2042,10 @@ read_parameter_file( const char *fname ) if( outctrl.use_files ) { /* close open streams */ iobuf_close( outctrl.pub.stream ); iobuf_close( outctrl.sec.stream ); - m_free( outctrl.pub.fname ); - m_free( outctrl.pub.newfname ); - m_free( outctrl.sec.fname ); - m_free( outctrl.sec.newfname ); + xfree ( outctrl.pub.fname ); + xfree ( outctrl.pub.newfname ); + xfree ( outctrl.sec.fname ); + xfree ( outctrl.sec.newfname ); } release_parameter_list( para ); @@ -2070,34 +2083,34 @@ generate_keypair( const char *fname ) algo = ask_algo( 0, &use ); if( !algo ) { /* default: DSA with ElG subkey of the specified size */ both = 1; - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYTYPE; sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); r->next = para; para = r; tty_printf(_("DSA keypair will have 1024 bits.\n")); - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYLENGTH; strcpy( r->u.value, "1024" ); r->next = para; para = r; algo = PUBKEY_ALGO_ELGAMAL_E; - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pSUBKEYTYPE; sprintf( r->u.value, "%d", algo ); r->next = para; para = r; } else { - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYTYPE; sprintf( r->u.value, "%d", algo ); r->next = para; para = r; if (use) { - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYUSAGE; sprintf( r->u.value, "%s%s", (use & PUBKEY_USAGE_SIG)? "sign ":"", @@ -2109,19 +2122,19 @@ generate_keypair( const char *fname ) } nbits = ask_keysize( algo ); - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = both? pSUBKEYLENGTH : pKEYLENGTH; sprintf( r->u.value, "%u", nbits); r->next = para; para = r; expire = ask_expire_interval(0); - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYEXPIRE; r->u.expire = expire; r->next = para; para = r; - r = m_alloc_clear( sizeof *r + 20 ); + r = xcalloc (1, sizeof *r + 20 ); r->key = pSUBKEYEXPIRE; r->u.expire = expire; r->next = para; @@ -2133,7 +2146,7 @@ generate_keypair( const char *fname ) release_parameter_list( para ); return; } - r = m_alloc_clear( sizeof *r + strlen(uid) ); + r = xcalloc (1, sizeof *r + strlen(uid) ); r->key = pUSERID; strcpy( r->u.value, uid ); r->next = para; @@ -2141,12 +2154,12 @@ generate_keypair( const char *fname ) dek = ask_passphrase( &s2k ); if( dek ) { - r = m_alloc_clear( sizeof *r ); + r = xcalloc (1, sizeof *r ); r->key = pPASSPHRASE_DEK; r->u.dek = dek; r->next = para; para = r; - r = m_alloc_clear( sizeof *r ); + r = xcalloc (1, sizeof *r ); r->key = pPASSPHRASE_S2K; r->u.s2k = s2k; r->next = para; @@ -2198,7 +2211,7 @@ do_generate_keypair( struct para_data_s *para, if( outctrl->pub.newfname ) { iobuf_close(outctrl->pub.stream); outctrl->pub.stream = NULL; - m_free( outctrl->pub.fname ); + xfree ( outctrl->pub.fname ); outctrl->pub.fname = outctrl->pub.newfname; outctrl->pub.newfname = NULL; @@ -2217,7 +2230,7 @@ do_generate_keypair( struct para_data_s *para, if( outctrl->sec.newfname ) { iobuf_close(outctrl->sec.stream); outctrl->sec.stream = NULL; - m_free( outctrl->sec.fname ); + xfree ( outctrl->sec.fname ); outctrl->sec.fname = outctrl->sec.newfname; outctrl->sec.newfname = NULL; @@ -2298,11 +2311,11 @@ do_generate_keypair( struct para_data_s *para, if( !rc && outctrl->use_files ) { /* direct write to specified files */ rc = write_keyblock( outctrl->pub.stream, pub_root ); if( rc ) - log_error("can't write public key: %s\n", g10_errstr(rc) ); + log_error("can't write public key: %s\n", gpg_strerror (rc) ); if( !rc ) { rc = write_keyblock( outctrl->sec.stream, sec_root ); if( rc ) - log_error("can't write secret key: %s\n", g10_errstr(rc) ); + log_error("can't write secret key: %s\n", gpg_strerror (rc) ); } } @@ -2314,13 +2327,13 @@ do_generate_keypair( struct para_data_s *para, rc = keydb_locate_writable (pub_hd, NULL); if (rc) log_error (_("no writable public keyring found: %s\n"), - g10_errstr (rc)); + gpg_strerror (rc)); if (!rc) { rc = keydb_locate_writable (sec_hd, NULL); if (rc) log_error (_("no writable secret keyring found: %s\n"), - g10_errstr (rc)); + gpg_strerror (rc)); } if (!rc && opt.verbose) { @@ -2334,14 +2347,14 @@ do_generate_keypair( struct para_data_s *para, rc = keydb_insert_keyblock (pub_hd, pub_root); if (rc) log_error (_("error writing public keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), g10_errstr(rc)); + keydb_get_resource_name (pub_hd), gpg_strerror (rc)); } if (!rc) { rc = keydb_insert_keyblock (sec_hd, sec_root); if (rc) log_error (_("error writing secret keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), g10_errstr(rc)); + keydb_get_resource_name (pub_hd), gpg_strerror (rc)); } keydb_release (pub_hd); @@ -2382,9 +2395,9 @@ do_generate_keypair( struct para_data_s *para, if( rc ) { if( opt.batch ) - log_error("key generation failed: %s\n", g10_errstr(rc) ); + log_error("key generation failed: %s\n", gpg_strerror (rc) ); else - tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) ); + tty_printf(_("Key generation failed: %s\n"), gpg_strerror (rc) ); } else { PKT_public_key *pk = find_kbnode (pub_root, @@ -2435,7 +2448,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) : _("key has been created %lu seconds " "in future (time warp or clock problem)\n"), d ); if( !opt.ignore_time_conflict ) { - rc = G10ERR_TIME_CONFLICT; + rc = GPG_ERR_TIME_CONFLICT; goto leave; } } @@ -2449,7 +2462,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) /* unprotect to get the passphrase */ switch( is_secret_key_protected( sk ) ) { case -1: - rc = G10ERR_PUBKEY_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; break; case 0: tty_printf("This key is not protected.\n"); @@ -2474,7 +2487,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) goto leave; if( passphrase ) { - s2k = m_alloc_secure( sizeof *s2k ); + s2k = xmalloc_secure ( sizeof *s2k ); s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; set_next_passphrase( passphrase ); @@ -2495,10 +2508,10 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) leave: if( rc ) - log_error(_("Key generation failed: %s\n"), g10_errstr(rc) ); - m_free( passphrase ); - m_free( dek ); - m_free( s2k ); + log_error(_("Key generation failed: %s\n"), gpg_strerror (rc) ); + xfree ( passphrase ); + xfree ( dek ); + xfree ( s2k ); if( sk ) /* release the copy of the (now unprotected) secret key */ free_secret_key(sk); set_next_passphrase( NULL ); @@ -2509,14 +2522,14 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) * Write a keyblock to an output stream */ static int -write_keyblock( IOBUF out, KBNODE node ) +write_keyblock( iobuf_t out, KBNODE node ) { for( ; node ; node = node->next ) { int rc = build_packet( out, node->pkt ); if( rc ) { log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - return G10ERR_WRITE_FILE; + node->pkt->pkttype, gpg_strerror (rc) ); + return rc; } } return 0; diff --git a/g10/keyid.c b/g10/keyid.c index 09f24e8ea..78b637481 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -1,5 +1,5 @@ /* keyid.c - key ID and fingerprint handling - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,8 @@ #include <errno.h> #include <time.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "main.h" #include "packet.h" @@ -48,10 +50,10 @@ pubkey_letter( int algo ) } } -static MD_HANDLE +static gcry_md_hd_t do_fingerprint_md( PKT_public_key *pk ) { - MD_HANDLE md; + gcry_md_hd_t md; unsigned n; unsigned nb[PUBKEY_MAX_NPKEY]; unsigned nn[PUBKEY_MAX_NPKEY]; @@ -59,27 +61,35 @@ do_fingerprint_md( PKT_public_key *pk ) int i; int npkey = pubkey_get_npkey( pk->pubkey_algo ); - md = md_open( pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); + 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++ ) { - nb[i] = mpi_get_nbits(pk->pkey[i]); - pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL ); + size_t nbytes; + + if (gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &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, pk->pkey[i] )) + BUG (); + nn[i] = nbytes; n += 2 + nn[i]; } - md_putc( md, 0x99 ); /* ctb */ - md_putc( md, n >> 8 ); /* 2 byte length header */ - md_putc( md, n ); + 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 ) - md_putc( md, 3 ); + gcry_md_putc ( md, 3 ); else - md_putc( md, 4 ); + gcry_md_putc ( md, 4 ); { u32 a = pk->timestamp; - md_putc( md, a >> 24 ); - md_putc( md, a >> 16 ); - md_putc( md, a >> 8 ); - md_putc( md, a ); + 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; @@ -88,22 +98,22 @@ do_fingerprint_md( PKT_public_key *pk ) a = (u16)((pk->expiredate - pk->timestamp) / 86400L); else a = 0; - md_putc( md, a >> 8 ); - md_putc( md, a ); + gcry_md_putc ( md, a >> 8 ); + gcry_md_putc ( md, a ); } - md_putc( md, pk->pubkey_algo ); + gcry_md_putc ( md, pk->pubkey_algo ); for(i=0; i < npkey; i++ ) { - md_putc( md, nb[i]>>8); - md_putc( md, nb[i] ); - md_write( md, pp[i], nn[i] ); - m_free(pp[i]); + gcry_md_putc ( md, nb[i]>>8); + gcry_md_putc ( md, nb[i] ); + gcry_md_write( md, pp[i], nn[i] ); + xfree (pp[i]); } - md_final( md ); + gcry_md_final ( md ); return md; } -static MD_HANDLE +static gcry_md_hd_t do_fingerprint_md_sk( PKT_secret_key *sk ) { PKT_public_key pk; @@ -121,6 +131,31 @@ do_fingerprint_md_sk( PKT_secret_key *sk ) } +u32 +v3_keyid (gcry_mpi_t a, u32 *ki) +{ + byte *buffer; + size_t nbytes; + + if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, &nbytes, a )) + BUG (); + /* fixme: allocate it on the stack */ + buffer = xmalloc (nbytes); + if (gcry_mpi_print( GCRYMPI_FMT_USG, buffer, &nbytes, 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. @@ -135,18 +170,19 @@ keyid_from_sk( PKT_secret_key *sk, u32 *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) ? - mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */ + v3_keyid (sk->skey[0], keyid) : 0; } else { const byte *dp; - MD_HANDLE md; + gcry_md_hd_t md; md = do_fingerprint_md_sk(sk); - dp = md_read( md, 0 ); + 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]; - md_close(md); + gcry_md_close (md); } return lowbits; @@ -172,20 +208,21 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid ) 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) ? - mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */ + v3_keyid (pk->pkey[0], keyid) : 0 ; pk->keyid[0] = keyid[0]; pk->keyid[1] = keyid[1]; } else { const byte *dp; - MD_HANDLE md; + gcry_md_hd_t md; md = do_fingerprint_md(pk); - dp = md_read( md, 0 ); + 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]; - md_close(md); + gcry_md_close (md); pk->keyid[0] = keyid[0]; pk->keyid[1] = keyid[1]; } @@ -246,12 +283,14 @@ namehash_from_uid(PKT_user_id *uid) { if(uid->namehash==NULL) { - uid->namehash=m_alloc(20); + uid->namehash=xmalloc (20); if(uid->attrib_data) - rmd160_hash_buffer(uid->namehash,uid->attrib_data,uid->attrib_len); + gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash, + uid->attrib_data,uid->attrib_len); else - rmd160_hash_buffer(uid->namehash,uid->name,uid->len); + gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash, + uid->name,uid->len); } return uid->namehash; @@ -427,43 +466,54 @@ colon_expirestr_from_sig (PKT_signature *sig) byte * fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len ) { - byte *p, *buf; + byte *buf; const byte *dp; size_t len; - unsigned int n; if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) { /* RSA in version 3 packets is special */ - MD_HANDLE md; + gcry_md_hd_t md; - md = md_open( DIGEST_ALGO_MD5, 0); + gcry_md_open (&md, DIGEST_ALGO_MD5, 0); if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) { - p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL ); - md_write( md, p, n ); - m_free(buf); - p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL ); - md_write( md, p, n ); - m_free(buf); + size_t nbytes; + + if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, pk->pkey[0])) + BUG (); + /* fixme: allocate it on the stack */ + buf = xmalloc(nbytes); + if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, &nbytes, pk->pkey[0])) + BUG (); + gcry_md_write (md, buf, nbytes); + xfree (buf); + if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, pk->pkey[1])) + BUG (); + /* fixme: allocate it on the stack */ + buf = xmalloc(nbytes); + if (gcry_mpi_print( GCRYMPI_FMT_USG, buf, &nbytes, pk->pkey[1])) + BUG (); + gcry_md_write( md, buf, nbytes ); + xfree(buf); } - md_final(md); + gcry_md_final (md); if( !array ) - array = m_alloc( 16 ); + array = xmalloc ( 16 ); len = 16; - memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); - md_close(md); + memcpy(array, gcry_md_read (md, DIGEST_ALGO_MD5), 16 ); + gcry_md_close (md); } else { - MD_HANDLE md; + gcry_md_hd_t md; md = do_fingerprint_md(pk); - dp = md_read( md, 0 ); - len = md_digest_length( md_get_algo( md ) ); + 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 = m_alloc( len ); + 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] ; - md_close(md); + gcry_md_close (md); } *ret_len = len; @@ -473,41 +523,53 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len ) byte * fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) { - byte *p, *buf; + byte *buf; const char *dp; size_t len; - unsigned n; if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) { /* RSA in version 3 packets is special */ - MD_HANDLE md; + gcry_md_hd_t md; - md = md_open( DIGEST_ALGO_MD5, 0); + gcry_md_open (&md, DIGEST_ALGO_MD5, 0); if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) { - p = buf = mpi_get_buffer( sk->skey[0], &n, NULL ); - md_write( md, p, n ); - m_free(buf); - p = buf = mpi_get_buffer( sk->skey[1], &n, NULL ); - md_write( md, p, n ); - m_free(buf); + size_t nbytes; + + if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, sk->skey[0])) + BUG (); + /* fixme: allocate it on the stack */ + buf = xmalloc(nbytes); + if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, &nbytes, sk->skey[0])) + BUG (); + gcry_md_write (md, buf, nbytes); + xfree (buf); + if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, sk->skey[1])) + BUG (); + /* fixme: allocate it on the stack */ + buf = xmalloc(nbytes); + if (gcry_mpi_print( GCRYMPI_FMT_USG, buf, &nbytes, sk->skey[1])) + BUG (); + gcry_md_write( md, buf, nbytes ); + xfree(buf); } - md_final(md); + gcry_md_final (md); if( !array ) - array = m_alloc( 16 ); + array = xmalloc ( 16 ); len = 16; - memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); - md_close(md); + memcpy(array, gcry_md_read (md, DIGEST_ALGO_MD5), 16 ); + gcry_md_close (md); } else { - MD_HANDLE md; + gcry_md_hd_t md; + md = do_fingerprint_md_sk(sk); - dp = md_read( md, 0 ); - len = md_digest_length( md_get_algo( md ) ); + 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 = m_alloc( len ); + array = xmalloc ( len ); memcpy(array, dp, len ); - md_close(md); + gcry_md_close (md); } *ret_len = len; diff --git a/g10/keylist.c b/g10/keylist.c index 616cea8c9..ef2cb5676 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -88,7 +88,7 @@ print_seckey_info (PKT_secret_key *sk) p = get_user_id (sk_keyid, &n); tty_print_utf8_string (p, n); - m_free (p); + xfree (p); tty_printf ("\n"); } @@ -109,7 +109,7 @@ print_pubkey_info (PKT_public_key *pk) p = get_user_id (pk_keyid, &n); tty_print_utf8_string (p, n); - m_free (p); + xfree (p); tty_printf ("\n\n"); } @@ -126,7 +126,7 @@ show_policy_url(PKT_signature *sig,int indent,int mode) const byte *p; size_t len; int seq=0,crit; - FILE *fp=mode?log_stream():stdout; + FILE *fp=mode?log_get_stream():stdout; while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,&len,&seq,&crit))) { @@ -168,7 +168,7 @@ show_notation(PKT_signature *sig,int indent,int mode) const byte *p; size_t len; int seq=0,crit; - FILE *fp=mode?log_stream():stdout; + FILE *fp=mode?log_get_stream():stdout; /* There may be multiple notations in the same sig. */ @@ -254,12 +254,12 @@ list_all( int secret ) hd = keydb_new (secret); if (!hd) - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; else rc = keydb_search_first (hd); if( rc ) { if( rc != -1 ) - log_error("keydb_search_first failed: %s\n", g10_errstr(rc) ); + log_error("keydb_search_first failed: %s\n", gpg_strerror (rc) ); goto leave; } @@ -267,7 +267,7 @@ list_all( int secret ) do { rc = keydb_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); goto leave; } if(!opt.with_colons) @@ -291,7 +291,7 @@ list_all( int secret ) keyblock = NULL; } while (!(rc = keydb_search_next (hd))); if( rc && rc != -1 ) - log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); + log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); if(opt.check_sigs && !opt.with_colons) print_signature_stats(&stats); @@ -327,7 +327,7 @@ list_one( STRLIST names, int secret ) if( secret ) { rc = get_seckey_bynames( &ctx, NULL, names, &keyblock ); if( rc ) { - log_error("error reading key: %s\n", g10_errstr(rc) ); + log_error("error reading key: %s\n", gpg_strerror (rc) ); get_seckey_end( ctx ); return; } @@ -347,7 +347,7 @@ list_one( STRLIST names, int secret ) else { rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock ); if( rc ) { - log_error("error reading key: %s\n", g10_errstr(rc) ); + log_error("error reading key: %s\n", gpg_strerror (rc) ); get_pubkey_end( ctx ); return; } @@ -680,11 +680,11 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) if( stats ) { /*fflush(stdout);*/ rc = check_key_signature( keyblock, node, NULL ); - switch( rc ) { + switch( gpg_err_code (rc) ) { case 0: sigrc = '!'; break; - case G10ERR_BAD_SIGN: stats->inv_sigs++; sigrc = '-'; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: stats->no_key++; continue; + case GPG_ERR_BAD_SIGNATURE: stats->inv_sigs++; sigrc = '-'; break; + case GPG_ERR_NO_PUBKEY: + case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue; default: stats->oth_err++; sigrc = '%'; break; } @@ -748,14 +748,14 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) printf("%08lX",(ulong)sig->keyid[1]); printf(" %s ", datestr_from_sig(sig)); if( sigrc == '%' ) - printf("[%s] ", g10_errstr(rc) ); + printf("[%s] ", gpg_strerror (rc) ); else if( sigrc == '?' ) ; else if ( !opt.fast_list_mode ) { size_t n; char *p = get_user_id( sig->keyid, &n ); print_utf8_string( stdout, p, n ); - m_free(p); + xfree (p); } putchar('\n'); @@ -1024,11 +1024,11 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) if( opt.check_sigs ) { fflush(stdout); rc = check_key_signature( keyblock, node, NULL ); - switch( rc ) { + switch( gpg_err_code (rc) ) { case 0: sigrc = '!'; break; - case G10ERR_BAD_SIGN: sigrc = '-'; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: sigrc = '?'; break; + case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; + case GPG_ERR_NO_PUBKEY: + case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; default: sigrc = '%'; break; } } @@ -1055,14 +1055,14 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) printf(":"); if( sigrc == '%' ) - printf("[%s] ", g10_errstr(rc) ); + printf("[%s] ", gpg_strerror (rc) ); else if( sigrc == '?' ) ; else if ( !opt.fast_list_mode ) { size_t n; char *p = get_user_id( sig->keyid, &n ); print_string( stdout, p, n, ':' ); - m_free(p); + xfree (p); } printf(":%02x%c:\n", sig->sig_class,sig->flags.exportable?'x':'l'); /* fixme: check or list other sigs here */ @@ -1170,14 +1170,14 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) { if(sk) { - PKT_secret_key *primary_sk=m_alloc_clear(sizeof(*primary_sk)); + PKT_secret_key *primary_sk=xcalloc (1,sizeof(*primary_sk)); get_seckey(primary_sk,sk->main_keyid); print_fingerprint(NULL,primary_sk,mode|0x80); free_secret_key(primary_sk); } else { - PKT_public_key *primary_pk=m_alloc_clear(sizeof(*primary_pk)); + PKT_public_key *primary_pk=xcalloc (1,sizeof(*primary_pk)); get_pubkey(primary_pk,pk->main_keyid); print_fingerprint(primary_pk,NULL,mode|0x80); free_public_key(primary_pk); @@ -1185,7 +1185,7 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) } if (mode == 1) { - fp = log_stream (); + fp = log_get_stream (); if(primary) text = _("Primary key fingerprint:"); else diff --git a/g10/keyring.c b/g10/keyring.c index f8b6e1520..cc1150065 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -1,5 +1,5 @@ /* keyring.c - keyring file handling - * Copyright (C) 2001 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -28,6 +28,7 @@ #include <sys/types.h> #include <sys/stat.h> +#include "gpg.h" #include "util.h" #include "keyring.h" #include "packet.h" @@ -72,7 +73,7 @@ struct keyring_handle { int secret; /* this is for a secret keyring */ struct { CONST_KR_NAME kr; - IOBUF iobuf; + iobuf_t iobuf; int eof; int error; } current; @@ -101,7 +102,7 @@ new_offset_item (void) { struct off_item *k; - k = m_alloc_clear (sizeof *k); + k = xcalloc (1,sizeof *k); return k; } @@ -114,7 +115,7 @@ release_offset_items (struct off_item *k) for (; k; k = k2) { k2 = k->next; - m_free (k); + xfree (k); } } #endif @@ -124,7 +125,7 @@ new_offset_hash_table (void) { struct off_item **tbl; - tbl = m_alloc_clear (2048 * sizeof *tbl); + tbl = xcalloc (1,2048 * sizeof *tbl); return tbl; } @@ -138,7 +139,7 @@ release_offset_hash_table (OffsetHashTable tbl) return; for (i=0; i < 2048; i++) release_offset_items (tbl[i]); - m_free (tbl); + xfree (tbl); } #endif @@ -213,7 +214,7 @@ keyring_register_filename (const char *fname, int secret, void **ptr) } } - kr = m_alloc (sizeof *kr + strlen (fname)); + kr = xmalloc (sizeof *kr + strlen (fname)); strcpy (kr->fname, fname); kr->secret = !!secret; kr->lockhd = NULL; @@ -254,7 +255,7 @@ keyring_new (void *token, int secret) assert (resource && !resource->secret == !secret); - hd = m_alloc_clear (sizeof *hd); + hd = xcalloc (1,sizeof *hd); hd->resource = resource; hd->secret = !!secret; active_handles++; @@ -268,10 +269,10 @@ keyring_release (KEYRING_HANDLE hd) return; assert (active_handles > 0); active_handles--; - m_free (hd->word_match.name); - m_free (hd->word_match.pattern); + xfree (hd->word_match.name); + xfree (hd->word_match.pattern); iobuf_close (hd->current.iobuf); - m_free (hd); + xfree (hd); } @@ -303,7 +304,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes) kr->lockhd = create_dotlock( kr->fname ); if (!kr->lockhd) { log_info ("can't allocate lock for `%s'\n", kr->fname ); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; } } } @@ -318,7 +319,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes) ; else if (make_dotlock (kr->lockhd, -1) ) { log_info ("can't lock `%s'\n", kr->fname ); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; } else kr->is_locked = 1; @@ -355,7 +356,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) PACKET *pkt; int rc; KBNODE keyblock = NULL, node, lastnode; - IOBUF a; + iobuf_t a; int in_cert = 0; int pk_no = 0; int uid_no = 0; @@ -370,31 +371,31 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) a = iobuf_open (hd->found.kr->fname); if (!a) { log_error ("can't open `%s'\n", hd->found.kr->fname); - return G10ERR_KEYRING_OPEN; + return GPG_ERR_KEYRING_OPEN; } if (iobuf_seek (a, hd->found.offset) ) { log_error ("can't seek `%s'\n", hd->found.kr->fname); iobuf_close(a); - return G10ERR_KEYRING_OPEN; + return GPG_ERR_KEYRING_OPEN; } - pkt = m_alloc (sizeof *pkt); + pkt = xmalloc (sizeof *pkt); init_packet (pkt); hd->found.n_packets = 0;; lastnode = NULL; save_mode = set_packet_list_mode(0); while ((rc=parse_packet (a, pkt)) != -1) { hd->found.n_packets++; - if (rc == G10ERR_UNKNOWN_PACKET) { + if (rc == GPG_ERR_UNKNOWN_PACKET) { free_packet (pkt); init_packet (pkt); continue; } if (rc) { log_error ("keyring_get_keyblock: read error: %s\n", - g10_errstr(rc) ); - rc = G10ERR_INV_KEYRING; + gpg_strerror (rc) ); + rc = GPG_ERR_INV_KEYRING; break; } if (pkt->pkttype == PKT_COMPRESSED) { @@ -448,7 +449,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) } } - pkt = m_alloc (sizeof *pkt); + pkt = xmalloc (sizeof *pkt); init_packet(pkt); } set_packet_list_mode(save_mode); @@ -471,13 +472,13 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) *ret_kb = keyblock; } free_packet (pkt); - m_free (pkt); + xfree (pkt); iobuf_close(a); /* Make sure that future search operations fail immediately when * we know that we are working on a invalid keyring */ - if (rc == G10ERR_INV_KEYRING) + if (rc == GPG_ERR_INV_KEYRING) hd->current.error = rc; return rc; @@ -495,7 +496,7 @@ keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb) /* need to know the number of packets - do a dummy get_keyblock*/ rc = keyring_get_keyblock (hd, NULL); if (rc) { - log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); + log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc)); return rc; } if (!hd->found.n_packets) @@ -539,7 +540,7 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) fname = hd->resource? hd->resource->fname:NULL; if (!fname) - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; /* close this one otherwise we will lose the position for * a next search. Fixme: it would be better to adjust the position @@ -571,7 +572,7 @@ keyring_delete_keyblock (KEYRING_HANDLE hd) /* need to know the number of packets - do a dummy get_keyblock*/ rc = keyring_get_keyblock (hd, NULL); if (rc) { - log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); + log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc)); return rc; } if (!hd->found.n_packets) @@ -628,7 +629,7 @@ prepare_search (KEYRING_HANDLE hd) if (hd->current.kr && !hd->current.eof) { if ( !hd->current.iobuf ) - return G10ERR_GENERAL; /* position invalid after a modify */ + return GPG_ERR_GENERAL; /* position invalid after a modify */ return 0; /* okay */ } @@ -654,8 +655,9 @@ prepare_search (KEYRING_HANDLE hd) hd->current.eof = 0; hd->current.iobuf = iobuf_open (hd->current.kr->fname); if (!hd->current.iobuf) { + hd->current.error = gpg_error_from_errno (errno); log_error ("can't open `%s'\n", hd->current.kr->fname ); - return (hd->current.error = G10ERR_OPEN_FILE); + return hd->current.error; } return 0; @@ -774,7 +776,7 @@ prepare_word_match (const byte *name) int c; /* the original length is always enough for the pattern */ - p = pattern = m_alloc(strlen(name)+1); + p = pattern = xmalloc (strlen(name)+1); do { /* skip leading delimiters */ while( *name && !word_match_chars[*name] ) @@ -951,9 +953,9 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, if ( !hd->word_match.name || strcmp (hd->word_match.name, name) ) { /* name changed */ - m_free (hd->word_match.name); - m_free (hd->word_match.pattern); - hd->word_match.name = m_strdup (name); + xfree (hd->word_match.name); + xfree (hd->word_match.pattern); + hd->word_match.name = xstrdup (name); hd->word_match.pattern = prepare_word_match (name); } name = hd->word_match.pattern; @@ -1069,7 +1071,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, goto found; break; default: - rc = G10ERR_INV_ARG; + rc = GPG_ERR_INV_ARG; goto found; } } @@ -1139,7 +1141,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, static int create_tmp_file (const char *template, - char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) + char **r_bakfname, char **r_tmpfname, iobuf_t *r_fp) { char *bakfname, *tmpfname; mode_t oldmask; @@ -1156,27 +1158,27 @@ create_tmp_file (const char *template, if (strlen (template) > 4 && !strcmp (template+strlen(template)-4, EXTSEP_S "gpg") ) { - bakfname = m_alloc (strlen (template) + 1); + bakfname = xmalloc (strlen (template) + 1); strcpy (bakfname, template); strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak"); - tmpfname = m_alloc (strlen( template ) + 1 ); + tmpfname = xmalloc (strlen( template ) + 1 ); strcpy (tmpfname,template); strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp"); } else { /* file does not end with gpg; hmmm */ - bakfname = m_alloc (strlen( template ) + 5); + bakfname = xmalloc (strlen( template ) + 5); strcpy (stpcpy(bakfname, template), EXTSEP_S "bak"); - tmpfname = m_alloc (strlen( template ) + 5); + tmpfname = xmalloc (strlen( template ) + 5); strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp"); } # else /* Posix file names */ - bakfname = m_alloc (strlen( template ) + 2); + bakfname = xmalloc (strlen( template ) + 2); strcpy (stpcpy (bakfname,template),"~"); - tmpfname = m_alloc (strlen( template ) + 5); + tmpfname = xmalloc (strlen( template ) + 5); strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp"); # endif /* Posix filename */ @@ -1185,10 +1187,11 @@ create_tmp_file (const char *template, *r_fp = iobuf_create (tmpfname); umask(oldmask); if (!*r_fp) { + int tmperr = gpg_error_from_errno (errno); log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) ); - m_free (tmpfname); - m_free (bakfname); - return G10ERR_OPEN_FILE; + xfree (tmpfname); + xfree (bakfname); + return tmperr; } *r_bakfname = bakfname; @@ -1216,9 +1219,10 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, #endif if (rename (fname, bakfname) ) { + int tmperr = gpg_error_from_errno (errno); log_error ("renaming `%s' to `%s' failed: %s\n", fname, bakfname, strerror(errno) ); - return G10ERR_RENAME_FILE; + return tmperr; } } @@ -1228,9 +1232,9 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, #endif if (rename (tmpfname, fname) ) { + rc = gpg_error_from_errno (errno); log_error ("renaming `%s' to `%s' failed: %s\n", tmpfname, fname, strerror(errno) ); - rc = G10ERR_RENAME_FILE; if (secret) { log_info(_("WARNING: 2 files with confidential" @@ -1265,7 +1269,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, static int -write_keyblock (IOBUF fp, KBNODE keyblock) +write_keyblock (iobuf_t fp, KBNODE keyblock) { KBNODE kbctx = NULL, node; int rc; @@ -1278,7 +1282,7 @@ write_keyblock (IOBUF fp, KBNODE keyblock) if ( (rc = build_packet (fp, node->pkt) )) { log_error ("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); + node->pkt->pkttype, gpg_strerror (rc) ); return rc; } if (node->pkt->pkttype == PKT_SIGNATURE) @@ -1296,8 +1300,9 @@ write_keyblock (IOBUF fp, KBNODE keyblock) iobuf_put (fp, 2); /* 2 bytes */ iobuf_put (fp, 0); /* unused */ if (iobuf_put (fp, cacheval)) { + int tmperr = gpg_error_from_errno (errno); log_error ("writing sigcache packet failed\n"); - return G10ERR_WRITE_FILE; + return tmperr; } } } @@ -1316,7 +1321,7 @@ keyring_rebuild_cache (void *token) KEYDB_SEARCH_DESC desc; KBNODE keyblock = NULL, node; const char *lastresname = NULL, *resname; - IOBUF tmpfp = NULL; + iobuf_t tmpfp = NULL; char *tmpfilename = NULL; char *bakfilename = NULL; int rc; @@ -1340,9 +1345,9 @@ keyring_rebuild_cache (void *token) { if (iobuf_close (tmpfp)) { + rc = gpg_error_from_errno (errno); log_error ("error closing `%s': %s\n", tmpfilename, strerror (errno)); - rc = G10ERR_CLOSE_FILE; goto leave; } /* because we have switched resources, we can be sure that @@ -1351,8 +1356,8 @@ keyring_rebuild_cache (void *token) } rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, lastresname, 0) : 0; - m_free (tmpfilename); tmpfilename = NULL; - m_free (bakfilename); bakfilename = NULL; + xfree (tmpfilename); tmpfilename = NULL; + xfree (bakfilename); bakfilename = NULL; if (rc) goto leave; lastresname = resname; @@ -1367,7 +1372,7 @@ keyring_rebuild_cache (void *token) rc = keyring_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc)); + log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc)); goto leave; } assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY); @@ -1396,7 +1401,7 @@ keyring_rebuild_cache (void *token) rc = 0; if (rc) { - log_error ("keyring_search failed: %s\n", g10_errstr(rc)); + log_error ("keyring_search failed: %s\n", gpg_strerror (rc)); goto leave; } log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount ); @@ -1404,9 +1409,9 @@ keyring_rebuild_cache (void *token) { if (iobuf_close (tmpfp)) { + rc = gpg_error_from_errno (errno); log_error ("error closing `%s': %s\n", tmpfilename, strerror (errno)); - rc = G10ERR_CLOSE_FILE; goto leave; } /* because we have switched resources, we can be sure that @@ -1415,14 +1420,14 @@ keyring_rebuild_cache (void *token) } rc = lastresname? rename_tmp_file (bakfilename, tmpfilename, lastresname, 0) : 0; - m_free (tmpfilename); tmpfilename = NULL; - m_free (bakfilename); bakfilename = NULL; + xfree (tmpfilename); tmpfilename = NULL; + xfree (bakfilename); bakfilename = NULL; leave: if (tmpfp) iobuf_cancel (tmpfp); - m_free (tmpfilename); - m_free (bakfilename); + xfree (tmpfilename); + xfree (bakfilename); release_kbnode (keyblock); keyring_lock (hd, 0); keyring_release (hd); @@ -1440,7 +1445,7 @@ static int do_copy (int mode, const char *fname, KBNODE root, int secret, off_t start_offset, unsigned int n_packets ) { - IOBUF fp, newfp; + iobuf_t fp, newfp; int rc=0; char *bakfname = NULL; char *tmpfname = NULL; @@ -1448,7 +1453,8 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, /* Open the source file. Because we do a rname, we have to check the permissions of the file */ if (access (fname, W_OK)) - return G10ERR_WRITE_FILE; + return gpg_error_from_errno (errno); + fp = iobuf_open (fname); if (mode == 1 && !fp && errno == ENOENT) { @@ -1460,9 +1466,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, newfp = iobuf_create (fname); umask(oldmask); if( !newfp ) { + int tmperr = gpg_error_from_errno (errno); log_error (_("%s: can't create: %s\n"), fname, strerror(errno)); - return G10ERR_OPEN_FILE; + return tmperr; } if( !opt.quiet ) log_info(_("%s: keyring created\n"), fname ); @@ -1471,21 +1478,22 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, while ( (node = walk_kbnode( root, &kbctx, 0 )) ) { if( (rc = build_packet( newfp, node->pkt )) ) { log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); + node->pkt->pkttype, gpg_strerror (rc) ); iobuf_cancel(newfp); - return G10ERR_WRITE_FILE; + return rc; } } - if( iobuf_close(newfp) ) { + if (iobuf_close(newfp)) { + int tmperr = gpg_error_from_errno (errno); log_error ("%s: close failed: %s\n", fname, strerror(errno)); - return G10ERR_CLOSE_FILE; + return tmperr; } return 0; /* ready */ } if( !fp ) { + rc = gpg_error_from_errno (errno); log_error ("%s: can't open: %s\n", fname, strerror(errno) ); - rc = G10ERR_OPEN_FILE; goto leave; } @@ -1500,7 +1508,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = copy_all_packets (fp, newfp); if( rc != -1 ) { log_error("%s: copy to `%s' failed: %s\n", - fname, tmpfname, g10_errstr(rc) ); + fname, tmpfname, gpg_strerror (rc) ); iobuf_close(fp); iobuf_cancel(newfp); goto leave; @@ -1513,7 +1521,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = copy_some_packets( fp, newfp, start_offset ); if( rc ) { /* should never get EOF here */ log_error ("%s: copy to `%s' failed: %s\n", - fname, tmpfname, g10_errstr(rc) ); + fname, tmpfname, gpg_strerror (rc) ); iobuf_close(fp); iobuf_cancel(newfp); goto leave; @@ -1523,7 +1531,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = skip_some_packets( fp, n_packets ); if( rc ) { log_error("%s: skipping %u packets failed: %s\n", - fname, n_packets, g10_errstr(rc)); + fname, n_packets, gpg_strerror (rc)); iobuf_close(fp); iobuf_cancel(newfp); goto leave; @@ -1544,7 +1552,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = copy_all_packets( fp, newfp ); if( rc != -1 ) { log_error("%s: copy to `%s' failed: %s\n", - fname, tmpfname, g10_errstr(rc) ); + fname, tmpfname, gpg_strerror (rc) ); iobuf_close(fp); iobuf_cancel(newfp); goto leave; @@ -1554,20 +1562,20 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, /* close both files */ if( iobuf_close(fp) ) { + rc = gpg_error_from_errno (errno); log_error("%s: close failed: %s\n", fname, strerror(errno) ); - rc = G10ERR_CLOSE_FILE; goto leave; } if( iobuf_close(newfp) ) { + rc = gpg_error_from_errno (errno); log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); - rc = G10ERR_CLOSE_FILE; goto leave; } rc = rename_tmp_file (bakfname, tmpfname, fname, secret); leave: - m_free(bakfname); - m_free(tmpfname); + xfree (bakfname); + xfree (tmpfname); return rc; } diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index c341578fa..314d7898e 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -5,7 +5,7 @@ #include <time.h> #include "keyserver.h" -#include "iobuf.h" +#include "../common/iobuf.h" #include "types.h" void parse_keyserver_options(char *options); diff --git a/g10/keyserver.c b/g10/keyserver.c index 7759de198..e4f56ca3b 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1,5 +1,5 @@ /* keyserver.c - generic keyserver code - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -24,6 +24,8 @@ #include <string.h> #include <stdlib.h> #include <assert.h> + +#include "gpg.h" #include "filter.h" #include "keydb.h" #include "status.h" @@ -48,7 +50,7 @@ struct keyrec time_t createtime,expiretime; int size,flags; byte type; - IOBUF uidbuf; + iobuf_t uidbuf; int lines; }; @@ -186,7 +188,7 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) /* Get the host */ opt.keyserver_host=strsep(&uri,":/"); if(opt.keyserver_host[0]=='\0') - return G10ERR_BAD_URI; + return GPG_ERR_BAD_URI; if(uri==NULL || uri[0]=='\0') opt.keyserver_port=NULL; @@ -202,7 +204,7 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) while(*ch!='\0') { if(!isdigit(*ch)) - return G10ERR_BAD_URI; + return GPG_ERR_BAD_URI; ch++; } @@ -227,11 +229,11 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) { /* One slash means absolute path. We don't need to support that yet. */ - return G10ERR_BAD_URI; + return GPG_ERR_BAD_URI; } if(opt.keyserver_scheme[0]=='\0') - return G10ERR_BAD_URI; + return GPG_ERR_BAD_URI; return 0; } @@ -250,7 +252,7 @@ print_keyrec(int number,struct keyrec *keyrec) if(keyrec->type) { - const char *str=pubkey_algo_to_string(keyrec->type); + const char *str = gcry_pk_algo_name (keyrec->type); if(str) printf("%s ",str); @@ -319,7 +321,7 @@ parse_keyrec(char *keystring) return NULL; else if(work->desc.mode==KEYDB_SEARCH_MODE_NONE) { - m_free(work); + xfree (work); return NULL; } else @@ -332,7 +334,7 @@ parse_keyrec(char *keystring) if(work==NULL) { - work=m_alloc_clear(sizeof(struct keyrec)); + work=xcalloc (1,sizeof(struct keyrec)); work->uidbuf=iobuf_temp(); } @@ -353,7 +355,7 @@ parse_keyrec(char *keystring) if(work->desc.mode) { ret=work; - work=m_alloc_clear(sizeof(struct keyrec)); + work=xcalloc (1,sizeof(struct keyrec)); work->uidbuf=iobuf_temp(); } @@ -458,7 +460,7 @@ parse_keyrec(char *keystring) decoded=utf8_to_native(userid,i,0); iobuf_writestr(work->uidbuf,decoded); - m_free(decoded); + xfree (decoded); iobuf_writestr(work->uidbuf,"\n\t"); work->lines++; } @@ -496,7 +498,7 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) if(answer[0]=='q' || answer[0]=='Q') { - m_free(answer); + xfree (answer); return 1; } else if(atoi(answer)>=1 && atoi(answer)<=numdesc) @@ -507,7 +509,7 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) if(atoi(num)>=1 && atoi(num)<=numdesc) keyserver_work(GET,NULL,&desc[atoi(num)-1],1); - m_free(answer); + xfree (answer); return 1; } @@ -518,7 +520,7 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) small, it will grow safely. If negative it disables the "Key x-y of z" messages. */ static void -keyserver_search_prompt(IOBUF buffer,const char *searchstr) +keyserver_search_prompt(iobuf_t buffer,const char *searchstr) { int i=0,validcount=0,started=0,header=0,count=1; unsigned int maxlen,buflen; @@ -527,7 +529,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr) /* TODO: Something other than 23? That's 24-1 (the prompt). */ int maxlines=23,numlines=0; - desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC)); + desc=xmalloc (count*sizeof(KEYDB_SEARCH_DESC)); for(;;) { @@ -582,7 +584,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr) else validcount=1; - desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); + desc=xrealloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); } started=1; @@ -622,7 +624,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr) /* keyserver helper sent more keys than they claimed in the info: line. */ count+=10; - desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); + desc=xrealloc(desc,count*sizeof(KEYDB_SEARCH_DESC)); validcount=0; } @@ -645,15 +647,15 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr) numlines+=keyrec->lines; iobuf_close(keyrec->uidbuf); - m_free(keyrec); + xfree (keyrec); started=1; i++; } } - m_free(desc); - m_free(line); + xfree (desc); + xfree (line); notfound: if(count==0) @@ -694,7 +696,7 @@ keyserver_spawn(int action,STRLIST list, #endif /* Build the filename for the helper to execute */ - command=m_alloc(strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); + command=xmalloc (strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); strcpy(command,"gpgkeys_"); strcat(command,opt.keyserver_scheme); @@ -702,13 +704,13 @@ keyserver_spawn(int action,STRLIST list, { if(opt.keyserver_options.keep_temp_files) { - command=m_realloc(command,strlen(command)+ + command=xrealloc(command,strlen(command)+ strlen(KEYSERVER_ARGS_KEEP)+1); strcat(command,KEYSERVER_ARGS_KEEP); } else { - command=m_realloc(command,strlen(command)+ + command=xrealloc(command,strlen(command)+ strlen(KEYSERVER_ARGS_NOKEEP)+1); strcat(command,KEYSERVER_ARGS_NOKEEP); } @@ -806,7 +808,7 @@ keyserver_spawn(int action,STRLIST list, for(key=list;key!=NULL;key=key->next) { armor_filter_context_t afx; - IOBUF buffer=iobuf_temp(); + iobuf_t buffer=iobuf_temp(); KBNODE block; temp=NULL; @@ -930,13 +932,13 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"%s\n",key->d); if(key!=list) { - searchstr=m_realloc(searchstr, + searchstr=xrealloc(searchstr, strlen(searchstr)+strlen(key->d)+2); strcat(searchstr," "); } else { - searchstr=m_alloc(strlen(key->d)+1); + searchstr=xmalloc (strlen(key->d)+1); searchstr[0]='\0'; } @@ -968,7 +970,7 @@ keyserver_spawn(int action,STRLIST list, maxlen=1024; if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) { - ret=G10ERR_READ_FILE; + ret = iobuf_error (spawn->fromchild); goto fail; /* i.e. EOF */ } @@ -1052,7 +1054,7 @@ keyserver_spawn(int action,STRLIST list, } fail: - m_free(line); + xfree (line); *prog=exec_finish(spawn); @@ -1067,13 +1069,13 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) if(opt.keyserver_scheme==NULL) { log_error(_("no keyserver known (use option --keyserver)\n")); - return G10ERR_BAD_URI; + return GPG_ERR_BAD_URI; } #ifdef DISABLE_KEYSERVER_HELPERS log_error(_("external keyserver calls are not supported in this build\n")); - return G10ERR_KEYSERVER; + return GPG_ERR_KEYSERVER; #else /* Spawn a handler */ @@ -1107,12 +1109,12 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) break; } - return G10ERR_KEYSERVER; + return GPG_ERR_KEYSERVER; } if(rc) { - log_error(_("keyserver communications error: %s\n"),g10_errstr(rc)); + log_error(_("keyserver communications error: %s\n"),gpg_strerror (rc)); return rc; } @@ -1146,7 +1148,7 @@ keyserver_import(STRLIST users) int rc=0; /* Build a list of key ids */ - desc=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); + desc=xmalloc (sizeof(KEYDB_SEARCH_DESC)*num); for(;users;users=users->next) { @@ -1164,14 +1166,14 @@ keyserver_import(STRLIST users) if(count==num) { num+=100; - desc=m_realloc(desc,sizeof(KEYDB_SEARCH_DESC)*num); + desc=xrealloc(desc,sizeof(KEYDB_SEARCH_DESC)*num); } } if(count>0) rc=keyserver_work(GET,NULL,desc,count); - m_free(desc); + xfree (desc); return rc; } @@ -1221,21 +1223,21 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) *count=0; - *klist=m_alloc(sizeof(KEYDB_SEARCH_DESC)*num); + *klist=xmalloc (sizeof(KEYDB_SEARCH_DESC)*num); kdbhd=keydb_new(0); if(!users) { ndesc = 1; - desc = m_alloc_clear ( ndesc * sizeof *desc); + 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 = m_alloc ( ndesc * sizeof *desc); + desc = xmalloc ( ndesc * sizeof *desc); for (ndesc=0, sl=users; sl; sl = sl->next) { @@ -1243,7 +1245,7 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) ndesc++; else log_error (_("key `%s' not found: %s\n"), - sl->d, g10_errstr (G10ERR_INV_USER_ID)); + sl->d, gpg_strerror (GPG_ERR_INV_USER_ID)); } } @@ -1256,7 +1258,7 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -1273,14 +1275,14 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) node->pkt->pkt.public_key->version>=4) { (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - mpi_get_keyid(node->pkt->pkt.public_key->pkey[0], - (*klist)[*count].u.kid); + v3_keyid (node->pkt->pkt.public_key->pkey[0], + (*klist)[*count].u.kid); (*count)++; if(*count==num) { num+=100; - *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); + *klist=xrealloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); } } @@ -1308,7 +1310,7 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) if(*count==num) { num+=100; - *klist=m_realloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); + *klist=xrealloc(*klist,sizeof(KEYDB_SEARCH_DESC)*num); } } } @@ -1317,7 +1319,7 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) rc=0; leave: - m_free(desc); + xfree (desc); keydb_release(kdbhd); release_kbnode(keyblock); @@ -1363,7 +1365,7 @@ keyserver_refresh(STRLIST users) rc=keyserver_work(GET,NULL,desc,count); } - m_free(desc); + xfree (desc); return rc; } diff --git a/g10/main.h b/g10/main.h index a7526c8bc..a4f4e3b84 100644 --- a/g10/main.h +++ b/g10/main.h @@ -20,7 +20,8 @@ #ifndef G10_MAIN_H #define G10_MAIN_H #include "types.h" -#include "iobuf.h" +#include "gpg.h" +#include "../common/iobuf.h" #include "mpi.h" #include "cipher.h" #include "keydb.h" @@ -65,13 +66,16 @@ void trap_unaligned(void); int disable_core_dumps(void); u16 checksum_u16( unsigned n ); u16 checksum( byte *p, unsigned n ); -u16 checksum_mpi( MPI a ); +u16 checksum_mpi( gcry_mpi_t a ); u32 buffer_to_u32( const byte *buffer ); const byte *get_session_marker( size_t *rlen ); int openpgp_cipher_test_algo( int algo ); int openpgp_pk_test_algo( int algo, unsigned int usage_flags ); int openpgp_pk_algo_usage ( int algo ); int openpgp_md_test_algo( int algo ); +int openpgp_md_map_name (const char *string); +int openpgp_cipher_map_name (const char *string); +int openpgp_pk_map_name (const char *string); #ifdef USE_IDEA void idea_cipher_warn( int show ); @@ -106,6 +110,24 @@ struct parse_options int parse_options(char *str,unsigned int *options,struct parse_options *opts); + +/* Temporary helpers. */ +int pubkey_get_npkey( int algo ); +int pubkey_get_nskey( int algo ); +int pubkey_get_nsig( int algo ); +int pubkey_get_nenc( int algo ); +unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey ); + +/* MPI helpers. */ +int mpi_write( iobuf_t out, gcry_mpi_t a ); +int mpi_write_opaque( iobuf_t out, gcry_mpi_t a ); +gcry_mpi_t mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure ); +gcry_mpi_t mpi_read_opaque(iobuf_t inp, unsigned int *ret_nread ); +int mpi_print( FILE *fp, gcry_mpi_t a, int mode ); + + + + /*-- helptext.c --*/ void display_online_help( const char *keyword ); @@ -115,7 +137,7 @@ int encode_store( const char *filename ); int encode_crypt( const char *filename, STRLIST remusr ); void encode_crypt_files(int nfiles, char **files, STRLIST remusr); int encrypt_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len); + iobuf_t a, byte *buf, size_t *ret_len); /*-- sign.c --*/ @@ -155,25 +177,25 @@ int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); int overwrite_filep( const char *fname ); char *make_outfile_name( const char *iname ); char *ask_outfile_name( const char *name, size_t namelen ); -int open_outfile( const char *iname, int mode, IOBUF *a ); -IOBUF open_sigfile( const char *iname, progress_filter_context_t *pfx ); +int open_outfile( const char *iname, int mode, iobuf_t *a ); +iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx ); void try_make_homedir( const char *fname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); -MPI encode_session_key( DEK *dek, unsigned nbits ); -MPI encode_md_value( int pubkey_algo, MD_HANDLE md, +gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits ); +gcry_mpi_t encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits, int v3compathack ); /*-- comment.c --*/ KBNODE make_comment_node( const char *s ); -KBNODE make_mpi_comment_node( const char *s, MPI a ); +KBNODE make_mpi_comment_node( const char *s, gcry_mpi_t a ); /*-- import.c --*/ int parse_import_options(char *str,unsigned int *options); void import_keys( char **fnames, int nnames, void *stats_hd, unsigned int options ); -int import_keys_stream( IOBUF inp, +int import_keys_stream( iobuf_t inp, void *stats_hd, unsigned int options ); void *import_new_stats_handle (void); void import_release_stats_handle (void *p); @@ -184,7 +206,7 @@ int collapse_uids( KBNODE *keyblock ); /*-- export.c --*/ int parse_export_options(char *str,unsigned int *options); int export_pubkeys( STRLIST users, unsigned int options ); -int export_pubkeys_stream( IOBUF out, STRLIST users, +int export_pubkeys_stream( iobuf_t out, STRLIST users, KBNODE *keyblock_out, unsigned int options ); int export_seckeys( STRLIST users ); int export_secsubkeys( STRLIST users ); diff --git a/g10/mainproc.c b/g10/mainproc.c index faba197fe..e9b7a4b66 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -68,7 +68,7 @@ struct mainproc_context { int last_was_session_key; KBNODE list; /* the current list of packets */ int have_data; - IOBUF iobuf; /* used to get the filename etc. */ + iobuf_t iobuf; /* used to get the filename etc. */ int trustletter; /* temp usage in list_node */ ulong local_id; /* ditto */ struct kidlist_item *pkenc_list; /* list of encryption packets */ @@ -79,7 +79,7 @@ struct mainproc_context { }; -static int do_proc_packets( CTX c, IOBUF a ); +static int do_proc_packets( CTX c, iobuf_t a ); static void list_node( CTX c, KBNODE node ); static void proc_tree( CTX c, KBNODE node ); @@ -94,7 +94,7 @@ release_list( CTX c ) release_kbnode( c->list ); while( c->pkenc_list ) { struct kidlist_item *tmp = c->pkenc_list->next; - m_free( c->pkenc_list ); + xfree ( c->pkenc_list ); c->pkenc_list = tmp; } c->pkenc_list = NULL; @@ -103,7 +103,7 @@ release_list( CTX c ) c->last_was_session_key = 0; c->pipemode.op = 0; c->pipemode.stop_now = 0; - m_free(c->dek); c->dek = NULL; + xfree (c->dek); c->dek = NULL; } @@ -249,25 +249,25 @@ symkey_decrypt_sesskey( DEK *dek, byte *sesskey, size_t slen ) (int)slen); return; } - hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 ); - cipher_setkey( hd, dek->key, dek->keylen ); - cipher_setiv( hd, NULL, 0 ); - cipher_decrypt( hd, sesskey, sesskey, slen ); - cipher_close( hd ); + gcry_cipher_open ( &hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1 ); + gcry_cipher_setkey( hd, dek->key, dek->keylen ); + gcry_cipher_setiv( hd, NULL, 0 ); + gcry_cipher_decrypt( hd, sesskey, slen, NULL, 0); + gcry_cipher_close( hd ); /* check first byte (the cipher algo) */ if ( sesskey[0] > 10 ) { log_error ( _("invalid symkey algorithm detected (%d)\n"), sesskey[0] ); return; } - n = cipher_get_keylen (sesskey[0]) / 8; + n = gcry_cipher_get_algo_keylen (sesskey[0]); if (n > DIM(dek->key)) BUG (); /* now we replace the dek components with the real session key to decrypt the contents of the sequencing packet. */ - dek->keylen = cipher_get_keylen( sesskey[0] ) / 8; + dek->keylen = gcry_cipher_get_algo_keylen (sesskey[0]); dek->algo = sesskey[0]; - memcpy( dek->key, sesskey + 1, dek->keylen ); + memcpy (dek->key, sesskey + 1, dek->keylen); /*log_hexdump( "thekey", dek->key, dek->keylen );*/ } @@ -283,8 +283,8 @@ proc_symkey_enc( CTX c, PACKET *pkt ) int algo = enc->cipher_algo; const char *s; - s = cipher_algo_to_string (algo); - if( s ) + s = gcry_cipher_algo_name (algo); + if (s && *s) log_info(_("%s encrypted data\n"), s ); else log_info(_("encrypted with unknown algorithm %d\n"), algo ); @@ -328,10 +328,10 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) /* It does not make much sense to store the session key in * secure memory because it has already been passed on the * command line and the GCHQ knows about it */ - c->dek = m_alloc_clear( sizeof *c->dek ); + c->dek = xcalloc (1, sizeof *c->dek ); result = get_override_session_key ( c->dek, opt.override_session_key ); if ( result ) { - m_free(c->dek); c->dek = NULL; + xfree (c->dek); c->dek = NULL; } } else if( is_ELGAMAL(enc->pubkey_algo) @@ -343,18 +343,18 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) if( opt.list_only ) result = -1; else { - c->dek = m_alloc_secure_clear( sizeof *c->dek ); + c->dek = xcalloc_secure (1, sizeof *c->dek); if( (result = get_session_key( enc, c->dek )) ) { /* error: delete the DEK */ - m_free(c->dek); c->dek = NULL; + xfree (c->dek); c->dek = NULL; } } } else - result = G10ERR_NO_SECKEY; + result = GPG_ERR_NO_SECKEY; } else - result = G10ERR_PUBKEY_ALGO; + result = GPG_ERR_PUBKEY_ALGO; if( result == -1 ) ; @@ -364,7 +364,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) log_info( _("public key encrypted data: good DEK\n") ); if ( opt.show_session_key ) { int i; - char *buf = m_alloc ( c->dek->keylen*2 + 20 ); + char *buf = xmalloc ( c->dek->keylen*2 + 20 ); sprintf ( buf, "%d:", c->dek->algo ); for(i=0; i < c->dek->keylen; i++ ) sprintf(buf+strlen(buf), "%02X", c->dek->key[i] ); @@ -374,7 +374,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) } /* store it for later display */ { - struct kidlist_item *x = m_alloc( sizeof *x ); + struct kidlist_item *x = xmalloc ( sizeof *x ); x->kid[0] = enc->keyid[0]; x->kid[1] = enc->keyid[1]; x->pubkey_algo = enc->pubkey_algo; @@ -404,11 +404,11 @@ print_pkenc_list( struct kidlist_item *list, int failed ) if ( !failed && list->reason ) continue; - algstr = pubkey_algo_to_string( list->pubkey_algo ); - pk = m_alloc_clear( sizeof *pk ); + algstr = gcry_pk_algo_name (list->pubkey_algo); + pk = xcalloc (1, sizeof *pk ); - if( !algstr ) - algstr = "[?]"; + if (!algstr || !*algstr) + algstr = "[?]"; pk->pubkey_algo = list->pubkey_algo; if( !get_pubkey( pk, list->kid ) ) { size_t n; @@ -416,11 +416,11 @@ print_pkenc_list( struct kidlist_item *list, int failed ) log_info( _("encrypted with %u-bit %s key, ID %08lX, created %s\n"), nbits_from_pk( pk ), algstr, (ulong)list->kid[1], strtimestamp(pk->timestamp) ); - fputs(" \"", log_stream() ); + fputs(" \"", log_get_stream() ); p = get_user_id( list->kid, &n ); - print_utf8_string2 ( log_stream(), p, n, '"' ); - m_free(p); - fputs("\"\n", log_stream() ); + print_utf8_string2 ( log_get_stream(), p, n, '"' ); + xfree (p); + fputs("\"\n", log_get_stream() ); } else { log_info(_("encrypted with %s key, ID %08lX\n"), @@ -428,7 +428,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) } free_public_key( pk ); - if( list->reason == G10ERR_NO_SECKEY ) { + if( list->reason == GPG_ERR_NO_SECKEY ) { if( is_status_enabled() ) { char buf[20]; sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], @@ -438,7 +438,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) } else if (list->reason) log_info(_("public key decryption failed: %s\n"), - g10_errstr(list->reason)); + gpg_strerror (list->reason)); } } @@ -465,22 +465,22 @@ proc_encrypted( CTX c, PACKET *pkt ) /* assume this is old style conventional encrypted data */ if ( (algo = opt.def_cipher_algo)) log_info (_("assuming %s encrypted data\n"), - cipher_algo_to_string(algo)); - else if ( check_cipher_algo(CIPHER_ALGO_IDEA) ) { + gcry_cipher_algo_name (algo)); + else if ( gcry_cipher_test_algo(CIPHER_ALGO_IDEA) ) { algo = opt.def_cipher_algo; if (!algo) algo = opt.s2k_cipher_algo; idea_cipher_warn(1); log_info (_("IDEA cipher unavailable, " "optimistically attempting to use %s instead\n"), - cipher_algo_to_string(algo)); + gcry_cipher_algo_name (algo)); } else { algo = CIPHER_ALGO_IDEA; if (!opt.s2k_digest_algo) { /* If no digest is given we assume MD5 */ s2kbuf.mode = 0; - s2kbuf.hash_algo = DIGEST_ALGO_MD5; + s2kbuf.hash_algo = GCRY_MD_MD5; s2k = &s2kbuf; } log_info (_("assuming %s encrypted data\n"), "IDEA"); @@ -491,14 +491,15 @@ proc_encrypted( CTX c, PACKET *pkt ) c->dek->algo_info_printed = 1; } else if( !c->dek ) - result = G10ERR_NO_SECKEY; + result = GPG_ERR_NO_SECKEY; if( !result ) result = decrypt_data( c, pkt->pkt.encrypted, c->dek ); - m_free(c->dek); c->dek = NULL; + xfree (c->dek); c->dek = NULL; if( result == -1 ) ; - else if( !result || (result==G10ERR_BAD_SIGN && opt.ignore_mdc_error)) { + else if( !result || (gpg_err_code (result)==GPG_ERR_BAD_SIGNATURE + && opt.ignore_mdc_error)) { write_status( STATUS_DECRYPTION_OKAY ); if( opt.verbose > 1 ) log_info(_("decryption okay\n")); @@ -507,14 +508,14 @@ proc_encrypted( CTX c, PACKET *pkt ) else if(!opt.no_mdc_warn) log_info (_("WARNING: message was not integrity protected\n")); } - else if( result == G10ERR_BAD_SIGN ) { + else if( gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE ) { log_error(_("WARNING: encrypted message has been manipulated!\n")); write_status( STATUS_BADMDC ); write_status( STATUS_DECRYPTION_FAILED ); } else { write_status( STATUS_DECRYPTION_FAILED ); - log_error(_("decryption failed: %s\n"), g10_errstr(result)); + log_error(_("decryption failed: %s\n"), gpg_strerror (result)); /* Hmmm: does this work when we have encrypted using multiple * ways to specify the session key (symmmetric and PK)*/ } @@ -537,7 +538,7 @@ proc_plaintext( CTX c, PACKET *pkt ) else if( opt.verbose ) log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name); free_md_filter_context( &c->mfx ); - c->mfx.md = md_open( 0, 0); + gcry_md_open (&c->mfx.md, 0, 0); /* fixme: we may need to push the textfilter if we have sigclass 1 * and no armoring - Not yet tested * Hmmm, why don't we need it at all if we have sigclass 1 @@ -548,7 +549,7 @@ proc_plaintext( CTX c, PACKET *pkt ) for(n=c->list; n; n = n->next ) { if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { if( n->pkt->pkt.onepass_sig->digest_algo ) { - md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); + gcry_md_enable ( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); if( !any && n->pkt->pkt.onepass_sig->digest_algo == DIGEST_ALGO_MD5 ) only_md5 = 1; @@ -572,7 +573,7 @@ proc_plaintext( CTX c, PACKET *pkt ) * documents */ clearsig = (*data == 0x01); for( data++, datalen--; datalen; datalen--, data++ ) - md_enable( c->mfx.md, *data ); + gcry_md_enable ( c->mfx.md, *data ); any = 1; break; /* no pass signature pakets are expected */ } @@ -580,9 +581,9 @@ proc_plaintext( CTX c, PACKET *pkt ) if( !any && !opt.skip_verify ) { /* no onepass sig packet: enable all standard algos */ - md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); - md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); - md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); + gcry_md_enable ( c->mfx.md, DIGEST_ALGO_RMD160 ); + gcry_md_enable ( c->mfx.md, DIGEST_ALGO_SHA1 ); + gcry_md_enable ( c->mfx.md, DIGEST_ALGO_MD5 ); } if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) { /* This is a kludge to work around a bug in pgp2. It does only @@ -590,25 +591,27 @@ proc_plaintext( CTX c, PACKET *pkt ) * pgp mails we could see whether there is the signature packet * in front of the plaintext. If someone needs this, send me a patch. */ - c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0); + gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0); } if ( DBG_HASHING ) { - md_start_debug( c->mfx.md, "verify" ); + gcry_md_start_debug ( c->mfx.md, "verify" ); if ( c->mfx.md2 ) - md_start_debug( c->mfx.md2, "verify2" ); + gcry_md_start_debug ( c->mfx.md2, "verify2" ); } if ( c->pipemode.op == 'B' ) - rc = handle_plaintext( pt, &c->mfx, 1, 0 ); + rc = handle_plaintext( pt, &c->mfx, 1, 0, NULL ); else { - rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); - if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { + int failed; + + rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig, &failed); + if( rc && failed && !c->sigs_only) { /* can't write output but we hash it anyway to * check the signature */ - rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); + rc = handle_plaintext( pt, &c->mfx, 1, clearsig, NULL ); } } if( rc ) - log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); + log_error( "handle plaintext failed: %s\n", gpg_strerror (rc)); free_packet(pkt); c->last_was_session_key = 0; @@ -624,14 +627,14 @@ proc_plaintext( CTX c, PACKET *pkt ) static int -proc_compressed_cb( IOBUF a, void *info ) +proc_compressed_cb( iobuf_t a, void *info ) { return proc_signature_packets( info, a, ((CTX)info)->signed_data, ((CTX)info)->sigfilename ); } static int -proc_encrypt_cb( IOBUF a, void *info ) +proc_encrypt_cb( iobuf_t a, void *info ) { return proc_encryption_packets( info, a ); } @@ -650,7 +653,7 @@ proc_compressed( CTX c, PACKET *pkt ) else rc = handle_compressed( c, zd, NULL, NULL ); if( rc ) - log_error("uncompressing failed: %s\n", g10_errstr(rc)); + log_error("uncompressing failed: %s\n", gpg_strerror (rc)); free_packet(pkt); c->last_was_session_key = 0; } @@ -676,27 +679,29 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) sig = node->pkt->pkt.signature; algo = sig->digest_algo; - if( (rc=check_digest_algo(algo)) ) + if( (rc = gcry_md_test_algo(algo)) ) return rc; if( sig->sig_class == 0x00 ) { if( c->mfx.md ) - md = md_copy( c->mfx.md ); + gcry_md_copy (&md,c->mfx.md); else /* detached signature */ - md = md_open( 0, 0 ); /* signature_check() will enable the md*/ + gcry_md_open (&md, 0, 0 ); /* signature_check() will + enable the md*/ } else if( sig->sig_class == 0x01 ) { /* how do we know that we have to hash the (already hashed) text * in canonical mode ??? (calculating both modes???) */ if( c->mfx.md ) { - md = md_copy( c->mfx.md ); - if( c->mfx.md2 ) - md2 = md_copy( c->mfx.md2 ); + gcry_md_copy (&md, c->mfx.md); + if (c->mfx.md2) + gcry_md_copy (&md2, c->mfx.md2); } else { /* detached signature */ log_debug("Do we really need this here?"); - md = md_open( 0, 0 ); /* signature_check() will enable the md*/ - md2 = md_open( 0, 0 ); + gcry_md_open (&md, 0, 0 ); /* signature_check() will + enable the md*/ + gcry_md_open (&md2, 0, 0 ); } } else if( (sig->sig_class&~3) == 0x10 @@ -712,21 +717,21 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) else if( sig->sig_class == 0x20 ) { log_info(_("standalone revocation - " "use \"gpg --import\" to apply\n")); - return G10ERR_NOT_PROCESSED; + return GPG_ERR_NOT_PROCESSED; } else { log_error("invalid root packet for sigclass %02x\n", sig->sig_class); - return G10ERR_SIG_CLASS; + return GPG_ERR_SIG_CLASS; } } else - return G10ERR_SIG_CLASS; + return GPG_ERR_SIG_CLASS; rc = signature_check2( sig, md, &dummy, is_expkey ); - if( rc == G10ERR_BAD_SIGN && md2 ) + if( gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2 ) rc = signature_check2( sig, md2, &dummy, is_expkey ); - md_close(md); - md_close(md2); + gcry_md_close (md); + gcry_md_close (md2); return rc; } @@ -947,12 +952,13 @@ list_node( CTX c, KBNODE node ) fputs("sig", stdout); if( opt.check_sigs ) { fflush(stdout); - switch( (rc2=do_check_sig( c, node, &is_selfsig, NULL )) ) { - case 0: sigrc = '!'; break; - case G10ERR_BAD_SIGN: sigrc = '-'; break; - case G10ERR_NO_PUBKEY: - case G10ERR_UNU_PUBKEY: sigrc = '?'; break; - default: sigrc = '%'; break; + switch( gpg_err_code (rc2=do_check_sig( c, node, + &is_selfsig, NULL )) ) { + case 0: sigrc = '!'; break; + case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; + case GPG_ERR_NO_PUBKEY: + case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; + default: sigrc = '%'; break; } } else { /* check whether this is a self signature */ @@ -991,7 +997,7 @@ list_node( CTX c, KBNODE node ) printf("%c %08lX %s ", sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig)); if( sigrc == '%' ) - printf("[%s] ", g10_errstr(rc2) ); + printf("[%s] ", gpg_strerror (rc2) ); else if( sigrc == '?' ) ; else if( is_selfsig ) { @@ -1004,7 +1010,7 @@ list_node( CTX c, KBNODE node ) else if( !opt.fast_list_mode ) { p = get_user_id( sig->keyid, &n ); print_string( stdout, p, n, opt.with_colons ); - m_free(p); + xfree (p); } if( opt.with_colons ) printf(":%02x%c:", sig->sig_class, sig->flags.exportable?'x':'l'); @@ -1017,24 +1023,24 @@ list_node( CTX c, KBNODE node ) int -proc_packets( void *anchor, IOBUF a ) +proc_packets( void *anchor, iobuf_t a ) { int rc; - CTX c = m_alloc_clear( sizeof *c ); + CTX c = xcalloc (1, sizeof *c ); c->anchor = anchor; rc = do_proc_packets( c, a ); - m_free( c ); + xfree ( c ); return rc; } int -proc_signature_packets( void *anchor, IOBUF a, +proc_signature_packets( void *anchor, iobuf_t a, STRLIST signedfiles, const char *sigfilename ) { - CTX c = m_alloc_clear( sizeof *c ); + CTX c = xcalloc (1, sizeof *c ); int rc; c->anchor = anchor; @@ -1042,28 +1048,28 @@ proc_signature_packets( void *anchor, IOBUF a, c->signed_data = signedfiles; c->sigfilename = sigfilename; rc = do_proc_packets( c, a ); - m_free( c ); + xfree ( c ); return rc; } int -proc_encryption_packets( void *anchor, IOBUF a ) +proc_encryption_packets( void *anchor, iobuf_t a ) { - CTX c = m_alloc_clear( sizeof *c ); + CTX c = xcalloc (1, sizeof *c ); int rc; c->anchor = anchor; c->encrypt_only = 1; rc = do_proc_packets( c, a ); - m_free( c ); + xfree ( c ); return rc; } int -do_proc_packets( CTX c, IOBUF a ) +do_proc_packets( CTX c, iobuf_t a ) { - PACKET *pkt = m_alloc( sizeof *pkt ); + PACKET *pkt = xmalloc ( sizeof *pkt ); int rc=0; int any_data=0; int newpkt; @@ -1076,7 +1082,7 @@ do_proc_packets( CTX c, IOBUF a ) free_packet(pkt); /* stop processing when an invalid packet has been encountered * but don't do so when we are doing a --list-packet. */ - if( rc == G10ERR_INVALID_PACKET && opt.list_packets != 2 ) + if( gpg_err_code (rc) == GPG_ERR_INV_PACKET && opt.list_packets != 2 ) break; continue; } @@ -1101,7 +1107,7 @@ do_proc_packets( CTX c, IOBUF a ) case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: write_status_text( STATUS_UNEXPECTED, "0" ); - rc = G10ERR_UNEXPECTED; + rc = GPG_ERR_UNEXPECTED; goto leave; case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; @@ -1117,7 +1123,7 @@ do_proc_packets( CTX c, IOBUF a ) case PKT_SECRET_KEY: case PKT_USER_ID: write_status_text( STATUS_UNEXPECTED, "0" ); - rc = G10ERR_UNEXPECTED; + rc = GPG_ERR_UNEXPECTED; goto leave; case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; @@ -1171,7 +1177,7 @@ do_proc_packets( CTX c, IOBUF a ) if( newpkt == -1 ) ; else if( newpkt ) { - pkt = m_alloc( sizeof *pkt ); + pkt = xmalloc ( sizeof *pkt ); init_packet(pkt); } else @@ -1183,7 +1189,7 @@ do_proc_packets( CTX c, IOBUF a ) break; } } - if( rc == G10ERR_INVALID_PACKET ) + if( rc == GPG_ERR_INV_PACKET ) write_status_text( STATUS_NODATA, "3" ); if( any_data ) rc = 0; @@ -1193,9 +1199,9 @@ do_proc_packets( CTX c, IOBUF a ) leave: release_list( c ); - m_free(c->dek); + xfree (c->dek); free_packet( pkt ); - m_free( pkt ); + xfree ( pkt ); free_md_filter_context( &c->mfx ); return rc; } @@ -1269,16 +1275,16 @@ check_sig_and_print( CTX c, KBNODE node ) } tstr = asctimestamp(sig->timestamp); - astr = pubkey_algo_to_string( sig->pubkey_algo ); + astr = gcry_pk_algo_name (sig->pubkey_algo); log_info(_("Signature made %.*s using %s key ID %08lX\n"), (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); rc = do_check_sig(c, node, NULL, &is_expkey ); - if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { + if( rc == GPG_ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { if( keyserver_import_keyid ( sig->keyid )==0 ) rc = do_check_sig(c, node, NULL, &is_expkey ); } - if( !rc || rc == G10ERR_BAD_SIGN ) { + if( !rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) { KBNODE un, keyblock; int count=0, statno; char keyid_str[50]; @@ -1322,9 +1328,9 @@ check_sig_and_print( CTX c, KBNODE node ) log_info(rc? _("BAD signature from \"") : sig->flags.expired ? _("Expired signature from \"") : _("Good signature from \"")); - print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, + print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len ); - fputs("\"\n", log_stream() ); + fputs("\"\n", log_get_stream() ); count++; } if( !count ) { /* just in case that we have no valid textual @@ -1356,13 +1362,13 @@ check_sig_and_print( CTX c, KBNODE node ) : sig->flags.expired ? _("Expired signature from \"") : _("Good signature from \"")); if (opt.trust_model!=TM_ALWAYS && un) { - fputs(_("[uncertain]"), log_stream() ); - putc(' ', log_stream() ); + fputs(_("[uncertain]"), log_get_stream() ); + putc(' ', log_get_stream() ); } - print_utf8_string( log_stream(), + print_utf8_string( log_get_stream(), un? un->pkt->pkt.user_id->name:"[?]", un? un->pkt->pkt.user_id->len:3 ); - fputs("\"\n", log_stream() ); + fputs("\"\n", log_get_stream() ); } /* If we have a good signature and already printed @@ -1393,9 +1399,9 @@ check_sig_and_print( CTX c, KBNODE node ) } log_info( _(" aka \"")); - print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, + print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len ); - fputs("\"\n", log_stream() ); + fputs("\"\n", log_get_stream() ); } } release_kbnode( keyblock ); @@ -1408,7 +1414,7 @@ check_sig_and_print( CTX c, KBNODE node ) if( !rc && is_status_enabled() ) { /* print a status response with the fingerprint */ - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + PKT_public_key *pk = xcalloc (1, sizeof *pk ); if( !get_pubkey( pk, sig->keyid ) ) { byte array[MAX_FINGERPRINT_LEN], *p; @@ -1436,7 +1442,7 @@ check_sig_and_print( CTX c, KBNODE node ) akid[0] = pk->main_keyid[0]; akid[1] = pk->main_keyid[1]; free_public_key (pk); - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); if (get_pubkey (pk, akid)) { /* impossible error, we simply return a zeroed out fpr */ n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; @@ -1460,7 +1466,7 @@ check_sig_and_print( CTX c, KBNODE node ) { log_info(_("Signature expired %s\n"), asctimestamp(sig->expiredate)); - rc=G10ERR_GENERAL; /* need a better error here? */ + rc=GPG_ERR_GENERAL; /* need a better error here? */ } else if(sig->expiredate) log_info(_("Signature expires %s\n"),asctimestamp(sig->expiredate)); @@ -1469,7 +1475,7 @@ check_sig_and_print( CTX c, KBNODE node ) log_info(_("%s signature, digest algorithm %s\n"), sig->sig_class==0x00?_("binary"): sig->sig_class==0x01?_("textmode"):_("unknown"), - digest_algo_to_string(sig->digest_algo)); + gcry_md_algo_name (sig->digest_algo)); if( rc ) g10_errors_seen = 1; @@ -1483,12 +1489,12 @@ check_sig_and_print( CTX c, KBNODE node ) sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp, rc ); write_status_text( STATUS_ERRSIG, buf ); - if( rc == G10ERR_NO_PUBKEY ) { + if( rc == GPG_ERR_NO_PUBKEY ) { buf[16] = 0; write_status_text( STATUS_NO_PUBKEY, buf ); } - if( rc != G10ERR_NOT_PROCESSED ) - log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); + if( rc != GPG_ERR_NOT_PROCESSED ) + log_error(_("Can't check signature: %s\n"), gpg_strerror (rc) ); } return rc; } @@ -1534,11 +1540,11 @@ proc_tree( CTX c, KBNODE node ) if( !c->have_data ) { free_md_filter_context( &c->mfx ); /* prepare to create all requested message digests */ - c->mfx.md = md_open(0, 0); + gcry_md_open (&c->mfx.md, 0, 0); /* fixme: why looking for the signature packet and not 1passpacket*/ for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { - md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo); + gcry_md_enable ( c->mfx.md, n1->pkt->pkt.signature->digest_algo); } /* ask for file and hash it */ if( c->sigs_only ) { @@ -1552,7 +1558,7 @@ proc_tree( CTX c, KBNODE node ) n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); } if( rc ) { - log_error("can't hash datafile: %s\n", g10_errstr(rc)); + log_error("can't hash datafile: %s\n", gpg_strerror (rc)); return; } } @@ -1613,20 +1619,20 @@ proc_tree( CTX c, KBNODE node ) else if( !c->have_data ) { /* detached signature */ free_md_filter_context( &c->mfx ); - c->mfx.md = md_open(sig->digest_algo, 0); + gcry_md_open (&c->mfx.md, sig->digest_algo, 0); if( !opt.pgp2_workarounds ) ; else if( sig->digest_algo == DIGEST_ALGO_MD5 && is_RSA( sig->pubkey_algo ) ) { /* enable a workaround for a pgp2 bug */ - c->mfx.md2 = md_open( DIGEST_ALGO_MD5, 0 ); + gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0 ); } else if( sig->digest_algo == DIGEST_ALGO_SHA1 && sig->pubkey_algo == PUBKEY_ALGO_DSA && sig->sig_class == 0x01 ) { /* enable the workaround also for pgp5 when the detached * signature has been created in textmode */ - c->mfx.md2 = md_open( sig->digest_algo, 0 ); + gcry_md_open (&c->mfx.md2, sig->digest_algo, 0 ); } #if 0 /* workaround disabled */ /* Here we have another hack to work around a pgp 2 bug @@ -1639,9 +1645,9 @@ proc_tree( CTX c, KBNODE node ) /* c->mfx.md2? 0 :(sig->sig_class == 0x01) */ #endif if ( DBG_HASHING ) { - md_start_debug( c->mfx.md, "verify" ); + gcry_md_start_debug ( c->mfx.md, "verify" ); if ( c->mfx.md2 ) - md_start_debug( c->mfx.md2, "verify2" ); + gcry_md_start_debug ( c->mfx.md2, "verify2" ); } if( c->sigs_only ) { rc = hash_datafiles( c->mfx.md, c->mfx.md2, @@ -1654,7 +1660,7 @@ proc_tree( CTX c, KBNODE node ) (sig->sig_class == 0x01) ); } if( rc ) { - log_error("can't hash datafile: %s\n", g10_errstr(rc)); + log_error("can't hash datafile: %s\n", gpg_strerror (rc)); return; } } diff --git a/g10/mdfilter.c b/g10/mdfilter.c index d6ccacecf..b58189146 100644 --- a/g10/mdfilter.c +++ b/g10/mdfilter.c @@ -38,7 +38,7 @@ */ int md_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; md_filter_context_t *mfx = opaque; @@ -50,9 +50,9 @@ md_filter( void *opaque, int control, i = iobuf_read( a, buf, size ); if( i == -1 ) i = 0; if( i ) { - md_write(mfx->md, buf, i ); + gcry_md_write(mfx->md, buf, i ); if( mfx->md2 ) - md_write(mfx->md2, buf, i ); + gcry_md_write(mfx->md2, buf, i ); } else rc = -1; /* eof */ @@ -67,8 +67,8 @@ md_filter( void *opaque, int control, void free_md_filter_context( md_filter_context_t *mfx ) { - md_close(mfx->md); - md_close(mfx->md2); + gcry_md_close (mfx->md); + gcry_md_close (mfx->md2); mfx->md = NULL; mfx->md2 = NULL; mfx->maxbuf_size = 0; diff --git a/g10/misc.c b/g10/misc.c index 1b8e6172a..19586624f 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1,5 +1,6 @@ /* misc.c - miscellaneous functions - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -24,6 +25,7 @@ #include <string.h> #include <unistd.h> #include <errno.h> +#include <assert.h> #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 #include <asm/sysinfo.h> #include <asm/unistd.h> @@ -33,27 +35,15 @@ #include <sys/time.h> #include <sys/resource.h> #endif + +#include "gpg.h" #include "util.h" #include "main.h" #include "photoid.h" #include "options.h" #include "i18n.h" - -const char *g10m_revision_string(int); -const char *g10c_revision_string(int); -const char *g10u_revision_string(int); - -#ifdef __GNUC__ -volatile -#endif - void -pull_in_libs(void) -{ - g10m_revision_string(0); - g10c_revision_string(0); - g10u_revision_string(0); -} +#define MAX_EXTERN_MPI_BITS 16384 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 @@ -125,19 +115,26 @@ checksum( byte *p, unsigned n ) } u16 -checksum_mpi( MPI a ) +checksum_mpi( gcry_mpi_t a ) { - u16 csum; - byte *buffer; - unsigned nbytes; - unsigned nbits; - - buffer = mpi_get_buffer( a, &nbytes, NULL ); - nbits = mpi_get_nbits(a); - csum = checksum_u16( nbits ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - return csum; + int rc; + u16 csum; + byte *buffer; + size_t nbytes; + + rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a ); + if (rc) + BUG (); + /* fixme: for numbers not in secure memory we should use a stack + * based buffer and only allocate a larger one if mpi_print return + * an error */ + buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes) : gcry_xmalloc(nbytes); + rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a ); + if (rc) + BUG (); + csum = checksum (buffer, nbytes ); + xfree (buffer ); + return csum; } u32 @@ -238,16 +235,18 @@ int openpgp_cipher_test_algo( int algo ) { if( algo < 0 || algo > 110 ) - return G10ERR_CIPHER_ALGO; - return check_cipher_algo(algo); + return GPG_ERR_CIPHER_ALGO; + return gcry_cipher_test_algo (algo); } int openpgp_pk_test_algo( int algo, unsigned int usage_flags ) { - if( algo < 0 || algo > 110 ) - return G10ERR_PUBKEY_ALGO; - return check_pubkey_algo2( algo, usage_flags ); + size_t value = usage_flags; + + if (algo < 0 || algo > 110) + return GPG_ERR_PUBKEY_ALGO; + return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &value); } int @@ -285,8 +284,29 @@ int openpgp_md_test_algo( int algo ) { if( algo < 0 || algo > 110 ) - return G10ERR_DIGEST_ALGO; - return check_digest_algo(algo); + return GPG_ERR_DIGEST_ALGO; + return gcry_md_test_algo (algo); +} + +int +openpgp_md_map_name (const char *string) +{ + int i = gcry_md_map_name (string); + return i < 0 || i > 110? 0 : i; +} + +int +openpgp_cipher_map_name (const char *string) +{ + int i = gcry_cipher_map_name (string); + return i < 0 || i > 110? 0 : i; +} + +int +openpgp_pk_map_name (const char *string) +{ + int i = gcry_pk_map_name (string); + return i < 0 || i > 110? 0 : i; } #ifdef USE_IDEA @@ -336,7 +356,7 @@ pct_expando(const char *string,struct expando_args *args) goto fail; maxlen+=1024; - ret=m_realloc(ret,maxlen); + ret= xrealloc(ret,maxlen); } done=0; @@ -467,7 +487,7 @@ pct_expando(const char *string,struct expando_args *args) return ret; fail: - m_free(ret); + xfree (ret); return NULL; } @@ -565,7 +585,7 @@ check_compress_algo(int algo) if(algo>=0 && algo<=2) return 0; - return G10ERR_COMPR_ALGO; + return GPG_ERR_COMPR_ALGO; } int @@ -676,3 +696,233 @@ parse_options(char *str,unsigned int *options,struct parse_options *opts) return 1; } + + + +/* Temporary helper. */ +int +pubkey_get_npkey( int algo ) +{ + int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 ); + return n > 0? n : 0; +} + +/* Temporary helper. */ +int +pubkey_get_nskey( int algo ) +{ + int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 ); + return n > 0? n : 0; +} + +/* Temporary helper. */ +int +pubkey_get_nsig( int algo ) +{ + int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 ); + return n > 0? n : 0; +} + +/* Temporary helper. */ +int +pubkey_get_nenc( int algo ) +{ + int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 ); + return n > 0? n : 0; +} + + +/* Temporary helper. */ +unsigned int +pubkey_nbits( int algo, gcry_mpi_t *key ) +{ + int rc, nbits; + gcry_sexp_t sexp; + + if( algo == GCRY_PK_DSA ) { + rc = gcry_sexp_build ( &sexp, NULL, + "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", + key[0], key[1], key[2], key[3] ); + } + else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) { + rc = gcry_sexp_build ( &sexp, NULL, + "(public-key(elg(p%m)(g%m)(y%m)))", + key[0], key[1], key[2] ); + } + else if( algo == GCRY_PK_RSA ) { + rc = gcry_sexp_build ( &sexp, NULL, + "(public-key(rsa(n%m)(e%m)))", + key[0], key[1] ); + } + else + return 0; + + if ( rc ) + BUG (); + + nbits = gcry_pk_get_nbits( sexp ); + gcry_sexp_release( sexp ); + return nbits; +} + + +/* MPI helper functions. */ + + +/**************** + * write an mpi to out. + */ +int +mpi_write( iobuf_t out, gcry_mpi_t a ) +{ + char buffer[(MAX_EXTERN_MPI_BITS+7)/8]; + size_t nbytes; + int rc; + + nbytes = (MAX_EXTERN_MPI_BITS+7)/8; + rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a ); + if( !rc ) + rc = iobuf_write( out, buffer, nbytes ); + + return rc; +} + +/**************** + * Writye a MPI to out, but in this case it is an opaque one, + * s used vor v3 protected keys. + */ +int +mpi_write_opaque( iobuf_t out, gcry_mpi_t a ) +{ + size_t nbytes, nbits; + int rc; + char *p; + + assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) ); + p = gcry_mpi_get_opaque( a, &nbits ); + nbytes = (nbits+7) / 8; + iobuf_put( out, nbits >> 8 ); + iobuf_put( out, nbits ); + rc = iobuf_write( out, p, nbytes ); + return rc; +} + + +/**************** + * Read an external representation of an mpi and return the MPI + * The external format is a 16 bit unsigned value stored in network byte order, + * giving the number of bits for the following integer. The integer is stored + * with MSB first (left padded with zeroes to align on a byte boundary). + */ +gcry_mpi_t +mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure) +{ + int c, c1, c2, i; + unsigned int nbits, nbytes, nread=0; + gcry_mpi_t a = NULL; + byte *buf = NULL; + byte *p; + + if( (c = c1 = iobuf_get(inp)) == -1 ) + goto leave; + nbits = c << 8; + if( (c = c2 = iobuf_get(inp)) == -1 ) + goto leave; + nbits |= c; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + nread = 2; + nbytes = (nbits+7) / 8; + buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 ); + p = buf; + p[0] = c1; + p[1] = c2; + for( i=0 ; i < nbytes; i++ ) { + p[i+2] = iobuf_get(inp) & 0xff; + nread++; + } + nread += nbytes; + if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, &nread ) ) + a = NULL; + + leave: + gcry_free(buf); + if( nread > *ret_nread ) + log_bug("mpi larger than packet"); + else + *ret_nread = nread; + return a; +} + +/**************** + * Same as mpi_read but the value is stored as an opaque MPI. + * This function is used to read encrypted MPI of v3 packets. + */ +gcry_mpi_t +mpi_read_opaque(iobuf_t inp, unsigned *ret_nread ) +{ + int c, c1, c2, i; + unsigned nbits, nbytes, nread=0; + gcry_mpi_t a = NULL; + byte *buf = NULL; + byte *p; + + if( (c = c1 = iobuf_get(inp)) == -1 ) + goto leave; + nbits = c << 8; + if( (c = c2 = iobuf_get(inp)) == -1 ) + goto leave; + nbits |= c; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + nread = 2; + nbytes = (nbits+7) / 8; + buf = gcry_xmalloc( nbytes ); + p = buf; + for( i=0 ; i < nbytes; i++ ) { + p[i] = iobuf_get(inp) & 0xff; + } + nread += nbytes; + a = gcry_mpi_set_opaque(NULL, buf, nbits ); + buf = NULL; + + leave: + gcry_free(buf); + if( nread > *ret_nread ) + log_bug("mpi larger than packet"); + else + *ret_nread = nread; + return a; +} + + +int +mpi_print( FILE *fp, gcry_mpi_t a, int mode ) +{ + int n=0; + + if( !a ) + return fprintf(fp, "[MPI_NULL]"); + if( !mode ) { + unsigned int n1; + n1 = gcry_mpi_get_nbits(a); + n += fprintf(fp, "[%u bits]", n1); + } + else { + int rc; + char *buffer; + + rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, (void **)&buffer, NULL, a ); + assert( !rc ); + fputs( buffer, fp ); + n += strlen(buffer); + gcry_free( buffer ); + } + return n; +} + + diff --git a/g10/mkdtemp.c b/g10/mkdtemp.c index 3abdc1da6..55e5b189f 100644 --- a/g10/mkdtemp.c +++ b/g10/mkdtemp.c @@ -85,7 +85,7 @@ char *mkdtemp(char *template) if(remaining>0) sprintf(marker,"%X",randombits[idx]&0xF); - m_free(randombits); + xfree (randombits); if(mkdir(template,0700)==0) break; diff --git a/g10/openfile.c b/g10/openfile.c index 6f4541e80..b36e0d8e0 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -28,6 +28,8 @@ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> + +#include "gpg.h" #include "util.h" #include "memory.h" #include "ttyio.h" @@ -99,19 +101,19 @@ make_outfile_name( const char *iname ) size_t n; if( (!iname || (*iname=='-' && !iname[1]) )) - return m_strdup("-"); + return xstrdup ("-"); n = strlen(iname); if( n > 4 && ( !CMP_FILENAME(iname+n-4, EXTSEP_S "gpg") || !CMP_FILENAME(iname+n-4, EXTSEP_S "pgp") || !CMP_FILENAME(iname+n-4, EXTSEP_S "sig") || !CMP_FILENAME(iname+n-4, EXTSEP_S "asc") ) ) { - char *buf = m_strdup( iname ); + char *buf = xstrdup ( iname ); buf[n-4] = 0; return buf; } else if( n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign") ) { - char *buf = m_strdup( iname ); + char *buf = xstrdup ( iname ); buf[n-5] = 0; return buf; } @@ -142,19 +144,19 @@ ask_outfile_name( const char *name, size_t namelen ) n = strlen(s) + namelen + 10; defname = name && namelen? make_printable_string( name, namelen, 0): NULL; - prompt = m_alloc(n); + prompt = xmalloc (n); if( defname ) sprintf(prompt, "%s [%s]: ", s, defname ); else sprintf(prompt, "%s: ", s ); fname = cpr_get("openfile.askoutname", prompt ); cpr_kill_prompt(); - m_free(prompt); + xfree (prompt); if( !*fname ) { - m_free( fname ); fname = NULL; + xfree ( fname ); fname = NULL; fname = defname; defname = NULL; } - m_free(defname); + xfree (defname); if (fname) trim_spaces (fname); return fname; @@ -163,21 +165,21 @@ ask_outfile_name( const char *name, size_t namelen ) /**************** * Make an output filename for the inputfile INAME. - * Returns an IOBUF and an errorcode + * Returns an iobuf_t and an errorcode * Mode 0 = use ".gpg" * 1 = use ".asc" * 2 = use ".sig" */ int -open_outfile( const char *iname, int mode, IOBUF *a ) +open_outfile( const char *iname, int mode, iobuf_t *a ) { int rc = 0; *a = NULL; if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) { if( !(*a = iobuf_create(NULL)) ) { + rc = gpg_error_from_errno (errno); log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) ); - rc = G10ERR_CREATE_FILE; } else if( opt.verbose ) log_info(_("writing to stdout\n")); @@ -205,7 +207,7 @@ open_outfile( const char *iname, int mode, IOBUF *a ) const char *newsfx = mode==1 ? ".asc" : mode==2 ? ".sig" : ".gpg"; - buf = m_alloc(strlen(iname)+4+1); + buf = xmalloc (strlen(iname)+4+1); strcpy(buf,iname); dot = strchr(buf, '.' ); if ( dot && dot > buf && dot[1] && strlen(dot) <= 4 @@ -221,7 +223,7 @@ open_outfile( const char *iname, int mode, IOBUF *a ) if (!buf) #endif /* USE_ONLY_8DOT3 */ { - buf = m_alloc(strlen(iname)+4+1); + buf = xmalloc (strlen(iname)+4+1); strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" : mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"); } @@ -234,11 +236,11 @@ open_outfile( const char *iname, int mode, IOBUF *a ) char *tmp = ask_outfile_name (NULL, 0); if ( !tmp || !*tmp ) { - m_free (tmp); - rc = G10ERR_FILE_EXISTS; + xfree (tmp); + rc = GPG_ERR_EEXIST; break; } - m_free (buf); + xfree (buf); name = buf = tmp; } @@ -246,13 +248,13 @@ open_outfile( const char *iname, int mode, IOBUF *a ) { if( !(*a = iobuf_create( name )) ) { + rc = gpg_error_from_errno (errno); log_error(_("%s: can't create: %s\n"), name, strerror(errno) ); - rc = G10ERR_CREATE_FILE; } else if( opt.verbose ) log_info(_("writing to `%s'\n"), name ); } - m_free(buf); + xfree (buf); } return rc; @@ -263,10 +265,10 @@ open_outfile( const char *iname, int mode, IOBUF *a ) * Try to open a file without the extension ".sig" or ".asc" * Return NULL if such a file is not available. */ -IOBUF +iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx ) { - IOBUF a = NULL; + iobuf_t a = NULL; size_t len; if( iname && !(*iname == '-' && !iname[1]) ) { @@ -275,14 +277,14 @@ open_sigfile( const char *iname, progress_filter_context_t *pfx ) || ( len > 5 && !strcmp(iname + len - 5, EXTSEP_S "sign") ) || !strcmp(iname + len - 4, EXTSEP_S "asc")) ) { char *buf; - buf = m_strdup(iname); + buf = xstrdup (iname); buf[len-(buf[len-1]=='n'?5:4)] = 0 ; a = iobuf_open( buf ); if( a && opt.verbose ) log_info(_("assuming signed data in `%s'\n"), buf ); if (a && pfx) handle_progress (pfx, a, buf); - m_free(buf); + xfree (buf); } } return a; @@ -306,12 +308,12 @@ copy_options_file( const char *destdir ) if( opt.dry_run ) return; - fname = m_alloc( strlen(datadir) + strlen(destdir) + 15 ); + fname = xmalloc ( strlen(datadir) + strlen(destdir) + 15 ); strcpy(stpcpy(fname, datadir), DIRSEP_S "options" SKELEXT ); src = fopen( fname, "r" ); if( !src ) { log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); - m_free(fname); + xfree (fname); return; } strcpy(stpcpy(fname, destdir), DIRSEP_S "gpg" EXTSEP_S "conf" ); @@ -321,7 +323,7 @@ copy_options_file( const char *destdir ) if( !dst ) { log_error(_("%s: can't create: %s\n"), fname, strerror(errno) ); fclose( src ); - m_free(fname); + xfree (fname); return; } @@ -351,7 +353,7 @@ copy_options_file( const char *destdir ) log_info (_("WARNING: options in `%s'" " are not yet active during this run\n"), fname); - m_free(fname); + xfree (fname); } diff --git a/g10/packet.h b/g10/packet.h index c391c53a4..81851373d 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -1,6 +1,6 @@ /* packet.h - packet definitions - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -22,9 +22,12 @@ #ifndef G10_PACKET_H #define G10_PACKET_H +#include "gpg.h" +#include <gcrypt.h> + #include "types.h" -#include "iobuf.h" -#include "mpi.h" +#include "../common/iobuf.h" +#include "../jnlib/strlist.h" #include "cipher.h" #include "filter.h" #include "global.h" @@ -96,7 +99,7 @@ typedef struct { byte version; byte pubkey_algo; /* algorithm used for public key scheme */ byte throw_keyid; - MPI data[PUBKEY_MAX_NENC]; + gcry_mpi_t data[PUBKEY_MAX_NENC]; } PKT_pubkey_enc; @@ -149,7 +152,7 @@ typedef struct { subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */ subpktarea_t *unhashed; /* ditto for unhashed data */ byte digest_start[2]; /* first 2 bytes of the digest */ - MPI data[PUBKEY_MAX_NSIG]; + gcry_mpi_t data[PUBKEY_MAX_NSIG]; } PKT_signature; #define ATTRIB_IMAGE 1 @@ -221,7 +224,7 @@ typedef struct { byte trust_depth; byte trust_value; const byte *trust_regexp; - MPI pkey[PUBKEY_MAX_NPKEY]; + gcry_mpi_t pkey[PUBKEY_MAX_NPKEY]; } PKT_public_key; /* Evaluates as true if the pk is disabled, and false if it isn't. If @@ -255,7 +258,7 @@ typedef struct { byte ivlen; /* used length of the iv */ byte iv[16]; /* initialization vector for CFB mode */ } protect; - MPI skey[PUBKEY_MAX_NSKEY]; + gcry_mpi_t skey[PUBKEY_MAX_NSKEY]; u16 csum; /* checksum */ } PKT_secret_key; @@ -269,7 +272,7 @@ typedef struct { u32 len; /* reserved */ byte new_ctb; byte algorithm; - IOBUF buf; /* IOBUF reference */ + iobuf_t buf; /* iobuf_t reference */ } PKT_compressed; typedef struct { @@ -277,7 +280,7 @@ typedef struct { int extralen; /* this is (blocksize+2) */ byte new_ctb; /* uses a new CTB */ byte mdc_method; /* > 0: integrity protected encrypted data packet */ - IOBUF buf; /* IOBUF reference */ + iobuf_t buf; /* iobuf_t reference */ } PKT_encrypted; typedef struct { @@ -291,7 +294,7 @@ typedef struct { typedef struct { u32 len; /* length of encrypted data */ - IOBUF buf; /* IOBUF reference */ + iobuf_t buf; /* iobuf_t reference */ byte new_ctb; byte is_partial; /* partial length encoded */ int mode; @@ -365,25 +368,25 @@ typedef enum { /*-- mainproc.c --*/ -int proc_packets( void *ctx, IOBUF a ); -int proc_signature_packets( void *ctx, IOBUF a, +int proc_packets( void *ctx, iobuf_t a ); +int proc_signature_packets( void *ctx, iobuf_t a, STRLIST signedfiles, const char *sigfile ); -int proc_encryption_packets( void *ctx, IOBUF a ); -int list_packets( IOBUF a ); +int proc_encryption_packets( void *ctx, iobuf_t a ); +int list_packets( iobuf_t a ); /*-- parse-packet.c --*/ int set_packet_list_mode( int mode ); #if DEBUG_PARSE_PACKET -int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, +int dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid, const char* file, int lineno ); -int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, +int dbg_parse_packet( iobuf_t inp, PACKET *ret_pkt, const char* file, int lineno ); -int dbg_copy_all_packets( IOBUF inp, IOBUF out, +int dbg_copy_all_packets( iobuf_t inp, iobuf_t out, const char* file, int lineno ); -int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, +int dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff, const char* file, int lineno ); -int dbg_skip_some_packets( IOBUF inp, unsigned n, +int dbg_skip_some_packets( iobuf_t inp, unsigned n, const char* file, int lineno ); #define search_packet( a,b,c,d ) \ dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) @@ -396,11 +399,11 @@ int dbg_skip_some_packets( IOBUF inp, unsigned n, #define skip_some_packets( a,b ) \ dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) #else -int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ); -int parse_packet( IOBUF inp, PACKET *ret_pkt); -int copy_all_packets( IOBUF inp, IOBUF out ); -int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ); -int skip_some_packets( IOBUF inp, unsigned n ); +int search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid ); +int parse_packet( iobuf_t inp, PACKET *ret_pkt); +int copy_all_packets( iobuf_t inp, iobuf_t out ); +int copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff ); +int skip_some_packets( iobuf_t inp, unsigned n ); #endif const byte *enum_sig_subpkt ( const subpktarea_t *subpkts, @@ -421,7 +424,7 @@ PACKET *create_gpg_control ( ctrlpkttype_t type, size_t datalen ); /*-- build-packet.c --*/ -int build_packet( IOBUF inp, PACKET *pkt ); +int build_packet( iobuf_t inp, PACKET *pkt ); u32 calc_packet_length( PACKET *pkt ); void hash_public_key( MD_HANDLE md, PKT_public_key *pk ); void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, @@ -474,19 +477,19 @@ int get_override_session_key( DEK *dek, const char *string ); /*-- compress.c --*/ int handle_compressed( void *ctx, PKT_compressed *cd, - int (*callback)(IOBUF, void *), void *passthru ); + int (*callback)(iobuf_t, void *), void *passthru ); /*-- encr-data.c --*/ int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek ); /*-- plaintext.c --*/ int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, - int nooutput, int clearsig ); + int nooutput, int clearsig, int *create_failed ); int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, const char *inname, int textmode ); /*-- comment.c --*/ -int write_comment( IOBUF out, const char *s ); +int write_comment( iobuf_t out, const char *s ); /*-- sign.c --*/ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, diff --git a/g10/parse-packet.c b/g10/parse-packet.c index a881840b2..c1a716b1d 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -40,48 +40,48 @@ static int mpi_print_mode = 0; static int list_mode = 0; -static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts, - off_t *retpos, int *skip, IOBUF out, int do_skip +static int parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, + off_t *retpos, int *skip, iobuf_t out, int do_skip #ifdef DEBUG_PARSE_PACKET ,const char *dbg_w, const char *dbg_f, int dbg_l #endif ); -static int copy_packet( IOBUF inp, IOBUF out, int pkttype, +static int copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen ); -static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ); -static void skip_rest( IOBUF inp, unsigned long pktlen ); -static void *read_rest( IOBUF inp, size_t pktlen ); -static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, +static void skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen ); +static void skip_rest( iobuf_t inp, unsigned long pktlen ); +static void *read_rest( iobuf_t inp, size_t pktlen ); +static int parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_signature *sig ); -static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_onepass_sig *ops ); -static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *packet ); -static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, +static void parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet, int new_ctb); -static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet, int new_ctb ); -static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet, int new_ctb); -static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet, int new_ctb); -static int parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen, +static int parse_gpg_control( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ); static unsigned short -read_16(IOBUF inp) +read_16(iobuf_t inp) { unsigned short a; a = iobuf_get_noeof(inp) << 8; @@ -90,7 +90,7 @@ read_16(IOBUF inp) } static unsigned long -read_32(IOBUF inp) +read_32(iobuf_t inp) { unsigned long a; a = iobuf_get_noeof(inp) << 24; @@ -106,7 +106,7 @@ set_packet_list_mode( int mode ) { int old = list_mode; list_mode = mode; - mpi_print_mode = DBG_MPI; + /* FIXME(gcrypt) mpi_print_mode = DBG_MPI; */ return old; } @@ -133,7 +133,7 @@ unknown_pubkey_warning( int algo ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l ) +dbg_parse_packet( iobuf_t inp, PACKET *pkt, const char *dbg_f, int dbg_l ) { int skip, rc; @@ -144,7 +144,7 @@ dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l ) } #else int -parse_packet( IOBUF inp, PACKET *pkt ) +parse_packet( iobuf_t inp, PACKET *pkt ) { int skip, rc; @@ -160,7 +160,7 @@ parse_packet( IOBUF inp, PACKET *pkt ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, +dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid, const char *dbg_f, int dbg_l ) { int skip, rc; @@ -172,7 +172,7 @@ dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, } #else int -search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ) +search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid ) { int skip, rc; @@ -188,7 +188,7 @@ search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_copy_all_packets( IOBUF inp, IOBUF out, +dbg_copy_all_packets( iobuf_t inp, iobuf_t out, const char *dbg_f, int dbg_l ) { PACKET pkt; @@ -200,7 +200,7 @@ dbg_copy_all_packets( IOBUF inp, IOBUF out, } #else int -copy_all_packets( IOBUF inp, IOBUF out ) +copy_all_packets( iobuf_t inp, iobuf_t out ) { PACKET pkt; int skip, rc=0; @@ -217,7 +217,7 @@ copy_all_packets( IOBUF inp, IOBUF out ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, +dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff, const char *dbg_f, int dbg_l ) { PACKET pkt; @@ -232,7 +232,7 @@ dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, } #else int -copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ) +copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff ) { PACKET pkt; int skip, rc=0; @@ -250,7 +250,7 @@ copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_skip_some_packets( IOBUF inp, unsigned n, +dbg_skip_some_packets( iobuf_t inp, unsigned n, const char *dbg_f, int dbg_l ) { int skip, rc=0; @@ -264,7 +264,7 @@ dbg_skip_some_packets( IOBUF inp, unsigned n, } #else int -skip_some_packets( IOBUF inp, unsigned n ) +skip_some_packets( iobuf_t inp, unsigned n ) { int skip, rc=0; PACKET pkt; @@ -286,8 +286,8 @@ skip_some_packets( IOBUF inp, unsigned n ) * if OUT is not NULL, a special copymode is used. */ static int -parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, - int *skip, IOBUF out, int do_skip +parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, + int *skip, iobuf_t out, int do_skip #ifdef DEBUG_PARSE_PACKET ,const char *dbg_w, const char *dbg_f, int dbg_l #endif @@ -313,7 +313,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, hdr[hdrlen++] = ctb; if( !(ctb & 0x80) ) { log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } pktlen = 0; @@ -322,7 +322,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, pkttype = ctb & 0x3f; if( (c = iobuf_get(inp)) == -1 ) { log_error("%s: 1st length byte missing\n", iobuf_where(inp) ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } if (pkttype == PKT_COMPRESSED) { @@ -338,7 +338,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, if( (c = iobuf_get(inp)) == -1 ) { log_error("%s: 2nd length byte missing\n", iobuf_where(inp) ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } hdr[hdrlen++] = c; @@ -351,7 +351,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, if( (c = iobuf_get(inp)) == -1 ) { log_error("%s: 4 byte length invalid\n", iobuf_where(inp) ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } pktlen |= (hdr[hdrlen++] = c ); @@ -387,9 +387,8 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, } if( out && pkttype ) { - if( iobuf_write( out, hdr, hdrlen ) == -1 ) - rc = G10ERR_WRITE_FILE; - else + rc = iobuf_write( out, hdr, hdrlen ); + if (!rc) rc = copy_packet(inp, out, pkttype, pktlen ); goto leave; } @@ -419,16 +418,16 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, #endif } pkt->pkttype = pkttype; - rc = G10ERR_UNKNOWN_PACKET; /* default error */ + rc = GPG_ERR_UNKNOWN_PACKET; /* default error */ switch( pkttype ) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: - pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key ); + pkt->pkt.public_key = xcalloc (1,sizeof *pkt->pkt.public_key ); rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); break; case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: - pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key ); + pkt->pkt.secret_key = xcalloc (1,sizeof *pkt->pkt.secret_key ); rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); break; case PKT_SYMKEY_ENC: @@ -438,11 +437,11 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt ); break; case PKT_SIGNATURE: - pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature ); + pkt->pkt.signature = xcalloc (1,sizeof *pkt->pkt.signature ); rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); break; case PKT_ONEPASS_SIG: - pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig ); + pkt->pkt.onepass_sig = xcalloc (1,sizeof *pkt->pkt.onepass_sig ); rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig ); break; case PKT_USER_ID: @@ -483,7 +482,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, leave: if( !rc && iobuf_error(inp) ) - rc = G10ERR_INV_KEYRING; + rc = GPG_ERR_INV_KEYRING; return rc; } @@ -505,31 +504,31 @@ dump_hex_line( int c, int *i ) static int -copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen ) +copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen ) { - int n; + int rc, n; char buf[100]; if( iobuf_in_block_mode(inp) ) { while( (n = iobuf_read( inp, buf, 100 )) != -1 ) - if( iobuf_write(out, buf, n ) ) - return G10ERR_WRITE_FILE; /* write error */ + if( (rc = iobuf_write(out, buf, n )) ) + return rc; /* write error */ } else if( !pktlen && pkttype == PKT_COMPRESSED ) { log_debug("copy_packet: compressed!\n"); /* compressed packet, copy till EOF */ while( (n = iobuf_read( inp, buf, 100 )) != -1 ) - if( iobuf_write(out, buf, n ) ) - return G10ERR_WRITE_FILE; /* write error */ + if( (rc = iobuf_write(out, buf, n )) ) + return rc; /* write error */ } else { for( ; pktlen; pktlen -= n ) { n = pktlen > 100 ? 100 : pktlen; n = iobuf_read( inp, buf, n ); if( n == -1 ) - return G10ERR_READ_FILE; - if( iobuf_write(out, buf, n ) ) - return G10ERR_WRITE_FILE; /* write error */ + return GPG_ERR_GENERAL; /* FIXME(gcrypt): read error*/; + if( (rc = iobuf_write(out, buf, n )) ) + return rc; /* write error */ } } return 0; @@ -537,7 +536,7 @@ copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen ) static void -skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) +skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen ) { if( list_mode ) { if( pkttype == PKT_MARKER ) @@ -564,7 +563,7 @@ skip_packet( IOBUF inp, int pkttype, unsigned long pktlen ) } static void -skip_rest( IOBUF inp, unsigned long pktlen ) +skip_rest( iobuf_t inp, unsigned long pktlen ) { if( iobuf_in_block_mode(inp) ) { while( iobuf_get(inp) != -1 ) @@ -579,7 +578,7 @@ skip_rest( IOBUF inp, unsigned long pktlen ) static void * -read_rest( IOBUF inp, size_t pktlen ) +read_rest( iobuf_t inp, size_t pktlen ) { byte *p; int i; @@ -589,7 +588,7 @@ read_rest( IOBUF inp, size_t pktlen ) p = NULL; } else { - p = m_alloc( pktlen ); + p = xmalloc ( pktlen ); for(i=0; pktlen; pktlen--, i++ ) p[i] = iobuf_get(inp); } @@ -599,7 +598,7 @@ read_rest( IOBUF inp, size_t pktlen ) static int -parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) { PKT_symkey_enc *k; int rc = 0; @@ -607,18 +606,18 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) if( pktlen < 4 ) { log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version != 4 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */ log_error("packet(%d) too large\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } cipher_algo = iobuf_get_noeof(inp); pktlen--; @@ -640,11 +639,11 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) } if( minlen > pktlen ) { log_error("packet with S2K %d too short\n", s2kmode ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } seskeylen = pktlen - minlen; - k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc + k = packet->pkt.symkey_enc = xcalloc (1, sizeof *packet->pkt.symkey_enc + seskeylen - 1 ); k->version = version; k->cipher_algo = cipher_algo; @@ -681,23 +680,23 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) } static int -parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) { unsigned int n; int rc = 0; int i, ndata; PKT_pubkey_enc *k; - k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc); + k = packet->pkt.pubkey_enc = xcalloc (1,sizeof *packet->pkt.pubkey_enc); if( pktlen < 12 ) { log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } k->version = iobuf_get_noeof(inp); pktlen--; if( k->version != 2 && k->version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, k->version); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } k->keyid[0] = read_32(inp); pktlen -= 4; @@ -725,7 +724,7 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) putchar('\n'); } if (!k->data[i]) - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; } } @@ -1151,7 +1150,7 @@ void parse_revkeys(PKT_signature *sig) if(len==sizeof(struct revocation_key) && (revkey->class&0x80)) /* 0x80 bit must be set */ { - sig->revkey=m_realloc(sig->revkey, + sig->revkey=xrealloc(sig->revkey, sizeof(struct revocation_key *)*(sig->numrevkeys+1)); sig->revkey[sig->numrevkeys]=revkey; sig->numrevkeys++; @@ -1160,7 +1159,7 @@ void parse_revkeys(PKT_signature *sig) } static int -parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, +parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_signature *sig ) { int md5_len=0; @@ -1178,7 +1177,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, is_v4=1; else if( sig->version != 2 && sig->version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, sig->version); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } @@ -1199,11 +1198,11 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, n = read_16(inp); pktlen -= 2; /* length of hashed data */ if( n > 10000 ) { log_error("signature packet: hashed data too long\n"); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } if( n ) { - sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 ); + sig->hashed = xmalloc (sizeof (*sig->hashed) + n - 1 ); sig->hashed->size = n; sig->hashed->len = n; if( iobuf_read (inp, sig->hashed->data, n ) != n ) { @@ -1217,14 +1216,14 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, n = read_16(inp); pktlen -= 2; /* length of unhashed data */ if( n > 10000 ) { log_error("signature packet: unhashed data too long\n"); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } if( n ) { /* we add 8 extra bytes so that we have space for the signature * status cache. Well we are wasting this if there is a cache * packet already, but in the other case it avoids an realloc */ - sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 ); + sig->unhashed = xmalloc (sizeof(*sig->unhashed) + n + 8 - 1 ); sig->unhashed->size = n + 8; sig->unhashed->len = n; if( iobuf_read(inp, sig->unhashed->data, n ) != n ) { @@ -1239,7 +1238,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, if( pktlen < 5 ) { /* sanity check */ log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } @@ -1357,7 +1356,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, putchar('\n'); } if (!sig->data[i]) - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; } } @@ -1368,7 +1367,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, static int -parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, +parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_onepass_sig *ops ) { int version; @@ -1376,13 +1375,13 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, if( pktlen < 13 ) { log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version != 3 ) { log_error("onepass_sig with unknown version %d\n", version); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } ops->sig_class = iobuf_get_noeof(inp); pktlen--; @@ -1405,13 +1404,13 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, } -static MPI -read_protected_v3_mpi (IOBUF inp, unsigned long *length) +static gcry_mpi_t +read_protected_v3_mpi (iobuf_t inp, unsigned long *length) { int c; unsigned int nbits, nbytes; unsigned char *buf, *p; - MPI val; + gcry_mpi_t val; if (*length < 2) { @@ -1434,7 +1433,7 @@ read_protected_v3_mpi (IOBUF inp, unsigned long *length) return NULL; } nbytes = (nbits+7) / 8; - buf = p = m_alloc (2 + nbytes); + buf = p = xmalloc (2 + nbytes); *p++ = nbits >> 8; *p++ = nbits; for (; nbytes && length; nbytes--, --*length) @@ -1442,18 +1441,18 @@ read_protected_v3_mpi (IOBUF inp, unsigned long *length) if (nbytes) { log_error ("packet shorter tham mpi\n"); - m_free (buf); + xfree (buf); return NULL; } - /* convert buffer into an opaque MPI */ + /* convert buffer into an opaque gcry_mpi_t */ val = mpi_set_opaque (NULL, buf, p-buf); return val; } static int -parse_key( IOBUF inp, int pkttype, unsigned long pktlen, +parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *pkt ) { int i, version, algorithm; @@ -1486,13 +1485,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, is_v4=1; else if( version != 2 && version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } if( pktlen < 11 ) { log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } @@ -1579,7 +1578,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, putchar('\n'); } if (!sk->skey[i]) - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; } if (rc) /* one of the MPIs were bad */ goto leave; @@ -1590,7 +1589,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, sk->protect.s2k.count = 0; if( sk->protect.algo == 254 || sk->protect.algo == 255 ) { if( pktlen < 3 ) { - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } sk->protect.sha1chk = (sk->protect.algo == 254); @@ -1608,7 +1607,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, if( list_mode ) printf( "\tunknown S2K %d\n", sk->protect.s2k.mode ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } /* here we know that it is a gnu extension @@ -1640,7 +1639,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, printf( "\tunknown %sS2K %d\n", sk->protect.s2k.mode < 1000? "":"GNU ", sk->protect.s2k.mode ); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } @@ -1661,7 +1660,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, if( sk->protect.s2k.mode == 3 ) { if( pktlen < 1 ) { - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } sk->protect.s2k.count = iobuf_get(inp); @@ -1701,7 +1700,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, sk->protect.ivlen = 0; if( pktlen < sk->protect.ivlen ) { - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- ) @@ -1722,7 +1721,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, * So we put the key into secure memory when we unprotect it. */ if( sk->protect.s2k.mode == 1001 ) { /* better set some dummy stuff here */ - sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10); + sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10); pktlen = 0; } else if( is_v4 && sk->is_protected ) { @@ -1755,7 +1754,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, } if (!sk->skey[i]) - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; } if (rc) goto leave; @@ -1784,7 +1783,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, putchar('\n'); } if (!pk->pkey[i]) - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; } if (rc) goto leave; @@ -1808,7 +1807,7 @@ parse_attribute_subpkts(PKT_user_id *uid) int buflen=uid->attrib_len; byte type; - m_free(uid->attribs); + xfree (uid->attribs); while(buflen) { @@ -1831,7 +1830,7 @@ parse_attribute_subpkts(PKT_user_id *uid) if( buflen < n ) goto too_short; - attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute)); + attribs=xrealloc(attribs,(count+1)*sizeof(struct user_attribute)); memset(&attribs[count],0,sizeof(struct user_attribute)); type=*buffer; @@ -1876,11 +1875,11 @@ static void setup_user_id(PACKET *packet) } static int -parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; - packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen); + packet->pkt.user_id = xmalloc (sizeof *packet->pkt.user_id + pktlen); packet->pkt.user_id->len = pktlen; setup_user_id(packet); @@ -1939,17 +1938,17 @@ make_attribute_uidname(PKT_user_id *uid, size_t max_namelen) } static int -parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; #define EXTRA_UID_NAME_SPACE 71 - packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + packet->pkt.user_id = xmalloc (sizeof *packet->pkt.user_id + EXTRA_UID_NAME_SPACE); setup_user_id(packet); - packet->pkt.user_id->attrib_data = m_alloc(pktlen); + packet->pkt.user_id->attrib_data = xmalloc (pktlen); packet->pkt.user_id->attrib_len = pktlen; p = packet->pkt.user_id->attrib_data; for( ; pktlen; pktlen--, p++ ) @@ -1970,11 +1969,11 @@ parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) static int -parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; - packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1); + packet->pkt.comment = xmalloc (sizeof *packet->pkt.comment + pktlen - 1); packet->pkt.comment->len = pktlen; p = packet->pkt.comment->data; for( ; pktlen; pktlen--, p++ ) @@ -1997,7 +1996,7 @@ parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) static void -parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) +parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { int c; @@ -2005,7 +2004,7 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { c = iobuf_get_noeof(inp); pktlen--; - pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust ); + pkt->pkt.ring_trust = xmalloc ( sizeof *pkt->pkt.ring_trust ); pkt->pkt.ring_trust->trustval = c; pkt->pkt.ring_trust->sigcache = 0; if (!c && pktlen==1) @@ -2031,7 +2030,7 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) static int -parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, +parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt, int new_ctb ) { int rc = 0; @@ -2042,7 +2041,7 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, if( pktlen && pktlen < 6 ) { log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } /* A packet length of zero indicates partial body length. A zero @@ -2052,7 +2051,7 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, partial=1; mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; - pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1); + pt = pkt->pkt.plaintext = xmalloc (sizeof *pkt->pkt.plaintext + namelen -1); pt->new_ctb = new_ctb; pt->mode = mode; pt->namelen = namelen; @@ -2093,7 +2092,7 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, static int -parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, +parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt, int new_ctb ) { PKT_compressed *zd; @@ -2102,7 +2101,7 @@ parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, * (this should be the last object in a file or * the compress algorithm should know the length) */ - zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed ); + zd = pkt->pkt.compressed = xmalloc (sizeof *pkt->pkt.compressed ); zd->algorithm = iobuf_get_noeof(inp); zd->len = 0; /* not used */ zd->new_ctb = new_ctb; @@ -2114,14 +2113,14 @@ parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, static int -parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, +parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt, int new_ctb ) { int rc = 0; PKT_encrypted *ed; unsigned long orig_pktlen = pktlen; - ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); + ed = pkt->pkt.encrypted = xmalloc (sizeof *pkt->pkt.encrypted ); ed->len = pktlen; /* we don't know the extralen which is (cipher_blocksize+2) because the algorithm ist not specified in this packet. @@ -2143,14 +2142,14 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, log_error("encrypted_mdc packet with unknown version %d\n", version); /*skip_rest(inp, pktlen); should we really do this? */ - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } ed->mdc_method = DIGEST_ALGO_SHA1; } if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */ log_error("packet(%d) too short\n", pkttype); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; skip_rest(inp, pktlen); goto leave; } @@ -2172,19 +2171,19 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, static int -parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, +parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt, int new_ctb ) { int rc = 0; PKT_mdc *mdc; byte *p; - mdc = pkt->pkt.mdc= m_alloc(sizeof *pkt->pkt.mdc ); + mdc = pkt->pkt.mdc= xmalloc (sizeof *pkt->pkt.mdc ); if( list_mode ) printf(":mdc packet: length=%lu\n", pktlen); if( !new_ctb || pktlen != 20 ) { log_error("mdc_packet with invalid encoding\n"); - rc = G10ERR_INVALID_PACKET; + rc = GPG_ERR_INV_PACKET; goto leave; } p = mdc->hash; @@ -2208,7 +2207,7 @@ parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, */ static int -parse_gpg_control( IOBUF inp, +parse_gpg_control( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; @@ -2229,7 +2228,7 @@ parse_gpg_control( IOBUF inp, if ( list_mode ) puts ("- gpg control packet"); - packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control + packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control + pktlen - 1); packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--; packet->pkt.gpg_control->datalen = pktlen; @@ -2256,7 +2255,7 @@ parse_gpg_control( IOBUF inp, putchar('\n'); } skip_rest(inp,pktlen); - return G10ERR_INVALID_PACKET; + return GPG_ERR_INV_PACKET; } /* create a gpg control packet to be used internally as a placeholder */ @@ -2266,10 +2265,10 @@ create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen ) PACKET *packet; byte *p; - packet = m_alloc( sizeof *packet ); + packet = xmalloc ( sizeof *packet ); init_packet(packet); packet->pkttype = PKT_GPG_CONTROL; - packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control + packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control + datalen - 1); packet->pkt.gpg_control->control = type; packet->pkt.gpg_control->datalen = datalen; diff --git a/g10/passphrase.c b/g10/passphrase.c index 769276221..41cd31f91 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -40,6 +40,7 @@ #include <langinfo.h> #endif +#include "gpg.h" #include "util.h" #include "memory.h" #include "options.h" @@ -122,10 +123,10 @@ have_static_passphrase() void set_next_passphrase( const char *s ) { - m_free(next_pw); + xfree (next_pw); next_pw = NULL; if( s ) { - next_pw = m_alloc_secure( strlen(s)+1 ); + next_pw = gcry_xmalloc_secure ( strlen(s)+1 ); strcpy(next_pw, s ); } } @@ -170,7 +171,7 @@ read_passphrase_from_fd( int fd ) { char *pw2 = pw; len += 100; - pw = m_alloc_secure( len ); + pw = gcry_xmalloc_secure ( len ); if( pw2 ) memcpy(pw, pw2, i ); else @@ -183,7 +184,7 @@ read_passphrase_from_fd( int fd ) if (!opt.batch) tty_printf("\b\b\b \n" ); - m_free( fd_passwd ); + xfree ( fd_passwd ); fd_passwd = pw; } @@ -337,11 +338,11 @@ agent_send_option (int fd, const char *name, const char *value) char *line; int i; - line = m_alloc (7 + strlen (name) + 1 + strlen (value) + 2); + line = xmalloc (7 + strlen (name) + 1 + strlen (value) + 2); strcpy (stpcpy (stpcpy (stpcpy ( stpcpy (line, "OPTION "), name), "="), value), "\n"); i = writen (fd, line, strlen (line)); - m_free (line); + xfree (line); if (i) return -1; @@ -394,7 +395,7 @@ agent_send_all_options (int fd) #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) old_lc = setlocale (LC_CTYPE, NULL); if (old_lc) - old_lc = m_strdup (old_lc); + old_lc = xstrdup (old_lc); dft_lc = setlocale (LC_CTYPE, ""); #endif if (opt.lc_ctype || (dft_ttyname && dft_lc)) @@ -406,7 +407,7 @@ agent_send_all_options (int fd) if (old_lc) { setlocale (LC_CTYPE, old_lc); - m_free (old_lc); + xfree (old_lc); } #endif if (rc) @@ -415,7 +416,7 @@ agent_send_all_options (int fd) #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) old_lc = setlocale (LC_MESSAGES, NULL); if (old_lc) - old_lc = m_strdup (old_lc); + old_lc = xstrdup (old_lc); dft_lc = setlocale (LC_MESSAGES, ""); #endif if (opt.lc_messages || (dft_ttyname && dft_lc)) @@ -427,7 +428,7 @@ agent_send_all_options (int fd) if (old_lc) { setlocale (LC_MESSAGES, old_lc); - m_free (old_lc); + xfree (old_lc); } #endif return rc; @@ -495,7 +496,7 @@ agent_open (int *ret_prot) int prot; if (opt.gpg_agent_info) - infostr = m_strdup (opt.gpg_agent_info); + infostr = xstrdup (opt.gpg_agent_info); else { infostr = getenv ( "GPG_AGENT_INFO" ); @@ -504,13 +505,13 @@ agent_open (int *ret_prot) opt.use_agent = 0; return -1; } - infostr = m_strdup ( infostr ); + infostr = xstrdup ( infostr ); } if ( !(p = strchr ( infostr, ':')) || p == infostr || (p-infostr)+1 >= sizeof client_addr.sun_path ) { log_error( _("malformed GPG_AGENT_INFO environment variable\n")); - m_free (infostr ); + xfree (infostr ); opt.use_agent = 0; return -1; } @@ -523,7 +524,7 @@ agent_open (int *ret_prot) prot = *p? atoi (p+1) : 0; if ( prot < 0 || prot > 1) { log_error (_("gpg-agent protocol version %d is not supported\n"),prot); - m_free (infostr ); + xfree (infostr ); opt.use_agent = 0; return -1; } @@ -531,7 +532,7 @@ agent_open (int *ret_prot) if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { log_error ("can't create socket: %s\n", strerror(errno) ); - m_free (infostr ); + xfree (infostr ); opt.use_agent = 0; return -1; } @@ -545,12 +546,12 @@ agent_open (int *ret_prot) if( connect( fd, (struct sockaddr*)&client_addr, len ) == -1 ) { log_error ( _("can't connect to `%s': %s\n"), infostr, strerror (errno) ); - m_free (infostr ); + xfree (infostr ); close (fd ); opt.use_agent = 0; return -1; } - m_free (infostr); + xfree (infostr); if (!prot) { if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { @@ -623,7 +624,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, int nread; u32 reply; char *pw = NULL; - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + PKT_public_key *pk = xcalloc (1, sizeof *pk ); byte fpr[MAX_FINGERPRINT_LEN]; int have_fpr = 0; int prot; @@ -652,7 +653,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, #endif if (orig_codeset) { /* We only switch when we are able to restore the codeset later. */ - orig_codeset = m_strdup (orig_codeset); + orig_codeset = xstrdup (orig_codeset); if (!bind_textdomain_codeset (PACKAGE, "utf-8")) orig_codeset = NULL; } @@ -665,7 +666,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, { char *uid; size_t uidlen; - const char *algo_name = pubkey_algo_to_string ( pk->pubkey_algo ); + const char *algo_name = gcry_pk_algo_name ( pk->pubkey_algo ); const char *timestr; char *maink; const char *fmtstr; @@ -674,7 +675,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, algo_name = "?"; fmtstr = _(" (main key ID %08lX)"); - maink = m_alloc ( strlen (fmtstr) + 20 ); + maink = xmalloc ( strlen (fmtstr) + 20 ); if( keyid[2] && keyid[3] && keyid[0] != keyid[2] && keyid[1] != keyid[3] ) sprintf( maink, fmtstr, (ulong)keyid[3] ); @@ -687,15 +688,15 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, " secret key for user:\n" "\"%.*s\"\n" "%u-bit %s key, ID %08lX, created %s%s\n" ); - atext = m_alloc ( 100 + strlen (fmtstr) + atext = xmalloc ( 100 + strlen (fmtstr) + uidlen + 15 + strlen(algo_name) + 8 + strlen (timestr) + strlen (maink) ); sprintf (atext, fmtstr, uidlen, uid, nbits_from_pk (pk), algo_name, (ulong)keyid[1], timestr, maink ); - m_free (uid); - m_free (maink); + xfree (uid); + xfree (maink); { size_t dummy; @@ -705,9 +706,9 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, } else if (mode == 2 ) - atext = m_strdup ( _("Repeat passphrase\n") ); + atext = xstrdup ( _("Repeat passphrase\n") ); else - atext = m_strdup ( _("Enter passphrase\n") ); + atext = xstrdup ( _("Enter passphrase\n") ); if (!prot) { /* old style protocol */ @@ -717,7 +718,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, memcpy (buf+8, fpr, 20 ); if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) ) goto failure; - m_free (atext); atext = NULL; + xfree (atext); atext = NULL; /* get response */ if ( readn ( fd, buf, 12, &nread ) ) @@ -753,7 +754,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, * on how long the passhrase actually is - this wastes some bytes * but because we already have this padding we should not loosen * this by issuing 2 read calls */ - pw = m_alloc_secure ( n+1 ); + pw = xmalloc_secure ( n+1 ); if ( readn ( fd, pw, n, &nn ) ) goto failure; if ( n != nn ) @@ -768,7 +769,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, if (orig_codeset) bind_textdomain_codeset (PACKAGE, orig_codeset); #endif - m_free (orig_codeset); + xfree (orig_codeset); return pw; } else if ( reply == GPGA_PROT_CANCELED ) @@ -794,7 +795,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, /* We allocate 2 time the needed space for atext so that there is nenough space for escaping */ - line = m_alloc (15 + 46 + line = xmalloc (15 + 46 + 3*strlen (tryagain_text) + 3*strlen (atext) + 2); strcpy (line, "GET_PASSPHRASE "); p = line+15; @@ -836,13 +837,13 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, } *p++ = '\n'; i = writen (fd, line, p - line); - m_free (line); + xfree (line); if (i) goto failure; - m_free (atext); atext = NULL; + xfree (atext); atext = NULL; /* get response */ - pw = m_alloc_secure (500); + pw = xmalloc_secure (500); nread = readline (fd, pw, 499); if (nread < 3) goto failure; @@ -860,7 +861,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, if (orig_codeset) bind_textdomain_codeset (PACKAGE, orig_codeset); #endif - m_free (orig_codeset); + xfree (orig_codeset); return pw; } else if (nread > 7 && !memcmp (pw, "ERR 111", 7) @@ -883,10 +884,10 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, if (orig_codeset) bind_textdomain_codeset (PACKAGE, orig_codeset); #endif - m_free (atext); + xfree (atext); if ( fd != -1 ) agent_close (fd); - m_free (pw ); + xfree (pw ); free_public_key( pk ); return NULL; @@ -918,7 +919,7 @@ passphrase_clear_cache ( u32 *keyid, int algo ) if (!opt.use_agent) return; - pk = m_alloc_clear ( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); memset (fpr, 0, MAX_FINGERPRINT_LEN ); if( !keyid || get_pubkey( pk, keyid ) ) { @@ -964,14 +965,14 @@ passphrase_clear_cache ( u32 *keyid, int algo ) char *line, *p; int i; - line = m_alloc (17 + 40 + 2); + line = xmalloc (17 + 40 + 2); strcpy (line, "CLEAR_PASSPHRASE "); p = line+17; for (i=0; i < 20; i++, p +=2 ) sprintf (p, "%02X", fpr[i]); *p++ = '\n'; i = writen (fd, line, p - line); - m_free (line); + xfree (line); if (i) goto failure; @@ -1054,7 +1055,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, us = get_long_user_id_string( keyid ); write_status_text( STATUS_USERID_HINT, us ); - m_free(us); + xfree (us); sprintf( buf, "%08lX%08lX %08lX%08lX %d 0", (ulong)keyid[0], (ulong)keyid[1], @@ -1070,7 +1071,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, } if( keyid && !opt.batch && !next_pw && mode!=1 ) { - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + PKT_public_key *pk = xcalloc (1, sizeof *pk ); size_t n; char *p; @@ -1078,11 +1079,11 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, "user: \"") ); p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ); - m_free(p); + xfree (p); tty_printf("\"\n"); if( !get_pubkey( pk, keyid ) ) { - const char *s = pubkey_algo_to_string( pk->pubkey_algo ); + const char *s = gcry_pk_algo_name ( pk->pubkey_algo ); tty_printf( _("%u-bit %s key, ID %08lX, created %s"), nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1], strtimestamp(pk->timestamp) ); @@ -1108,7 +1109,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, { if (!opt.use_agent) goto agent_died; - pw = m_strdup (""); + pw = xstrdup (""); } if( *pw && mode == 2 ) { char *pw2 = agent_get_passphrase ( keyid, 2, NULL, canceled ); @@ -1116,27 +1117,27 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, { if (!opt.use_agent) { - m_free (pw); + xfree (pw); pw = NULL; goto agent_died; } - pw2 = m_strdup (""); + pw2 = xstrdup (""); } if( strcmp(pw, pw2) ) { - m_free(pw2); - m_free(pw); + xfree (pw2); + xfree (pw); return NULL; } - m_free(pw2); + xfree (pw2); } } else if( fd_passwd ) { - pw = m_alloc_secure( strlen(fd_passwd)+1 ); + pw = xmalloc_secure ( strlen(fd_passwd)+1 ); strcpy( pw, fd_passwd ); } else if( opt.batch ) { log_error(_("can't query password in batchmode\n")); - pw = m_strdup( "" ); /* return an empty passphrase */ + pw = xstrdup ( "" ); /* return an empty passphrase */ } else { pw = cpr_get_hidden("passphrase.enter", _("Enter passphrase: ") ); @@ -1146,24 +1147,24 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, _("Repeat passphrase: ") ); tty_kill_prompt(); if( strcmp(pw, pw2) ) { - m_free(pw2); - m_free(pw); + xfree (pw2); + xfree (pw); return NULL; } - m_free(pw2); + xfree (pw2); } } if( !pw || !*pw ) write_status( STATUS_MISSING_PASSPHRASE ); - dek = m_alloc_secure_clear ( sizeof *dek ); + dek = xcalloc_secure (1, sizeof *dek ); dek->algo = cipher_algo; if( !*pw && mode == 2 ) dek->keylen = 0; else hash_passphrase( dek, pw, s2k, mode==2 ); - m_free(last_pw); + xfree (last_pw); last_pw = pw; return dek; } @@ -1183,16 +1184,16 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) int pwlen = strlen(pw); assert( s2k->hash_algo ); - dek->keylen = cipher_get_keylen( dek->algo ) / 8; + dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) BUG(); - md = md_open( s2k->hash_algo, 1); + gcry_md_open (&md, s2k->hash_algo, 1); for(pass=0; used < dek->keylen ; pass++ ) { if( pass ) { - md_reset(md); + gcry_md_reset(md); for(i=0; i < pass; i++ ) /* preset the hash context */ - md_putc(md, 0 ); + gcry_md_putc (md, 0 ); } if( s2k->mode == 1 || s2k->mode == 3 ) { @@ -1200,7 +1201,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) ulong count = len2; if( create && !pass ) { - randomize_buffer(s2k->salt, 8, 1); + gcry_randomize(s2k->salt, 8, GCRY_STRONG_RANDOM ); if( s2k->mode == 3 ) s2k->count = 96; /* 65536 iterations */ } @@ -1212,27 +1213,27 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) } /* a little bit complicated because we need a ulong for count */ while( count > len2 ) { /* maybe iterated+salted */ - md_write( md, s2k->salt, 8 ); - md_write( md, pw, pwlen ); + gcry_md_write( md, s2k->salt, 8 ); + gcry_md_write( md, pw, pwlen ); count -= len2; } if( count < 8 ) - md_write( md, s2k->salt, count ); + gcry_md_write( md, s2k->salt, count ); else { - md_write( md, s2k->salt, 8 ); + gcry_md_write( md, s2k->salt, 8 ); count -= 8; - md_write( md, pw, count ); + gcry_md_write( md, pw, count ); } } else - md_write( md, pw, pwlen ); - md_final( md ); - i = md_digest_length( s2k->hash_algo ); + gcry_md_write( md, pw, pwlen ); + gcry_md_final ( md ); + i = gcry_md_get_algo_dlen (s2k->hash_algo); if( i > dek->keylen - used ) i = dek->keylen - used; - memcpy( dek->key+used, md_read(md, s2k->hash_algo), i ); + memcpy( dek->key+used, gcry_md_read (md, s2k->hash_algo), i ); used += i; } - md_close(md); + gcry_md_close (md); } diff --git a/g10/photoid.c b/g10/photoid.c index b311bfa09..1dd6edeca 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -49,7 +49,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) char *filename=NULL; byte *photo=NULL; byte header[16]; - IOBUF file; + iobuf_t file; header[0]=0x10; /* little side of photo header length */ header[1]=0; /* big side of photo header length */ @@ -60,7 +60,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) header[i]=0; #define EXTRA_UID_NAME_SPACE 71 - uid=m_alloc_clear(sizeof(*uid)+71); + uid=xcalloc (1,sizeof(*uid)+71); printf(_("\nPick an image to use for your photo ID. " "The image must be a JPEG file.\n" @@ -73,7 +73,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) { printf("\n"); - m_free(filename); + xfree (filename); filename=cpr_get("photoid.jpeg.add", _("Enter JPEG filename for photo ID: ")); @@ -101,7 +101,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) } } - photo=m_alloc(len); + photo=xmalloc (len); iobuf_read(file,photo,len); iobuf_close(file); @@ -110,7 +110,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F') { log_error(_("\"%s\" is not a JPEG file\n"),filename); - m_free(photo); + xfree (photo); photo=NULL; continue; } @@ -132,7 +132,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) goto scram; case 0: free_attributes(uid); - m_free(photo); + xfree (photo); photo=NULL; continue; } @@ -143,13 +143,13 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) uid->ref=1; scram: - m_free(filename); - m_free(photo); + xfree (filename); + xfree (photo); if(error) { free_attributes(uid); - m_free(uid); + xfree (uid); return NULL; } @@ -283,7 +283,7 @@ void show_photos(const struct user_attribute *attrs, if(!command) goto fail; - name=m_alloc(16+strlen(EXTSEP_S)+ + name=xmalloc (16+strlen(EXTSEP_S)+ strlen(image_type_to_string(args.imagetype,0))+1); /* Make the filename. Notice we are not using the image @@ -302,7 +302,7 @@ void show_photos(const struct user_attribute *attrs, if(exec_write(&spawn,NULL,command,name,1,1)!=0) { - m_free(name); + xfree (name); goto fail; } @@ -311,7 +311,7 @@ void show_photos(const struct user_attribute *attrs, image_type_to_string(args.imagetype,2)); #endif - m_free(name); + xfree (name); fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild); diff --git a/g10/pipemode.c b/g10/pipemode.c index f3351277e..9f2ddfdb5 100644 --- a/g10/pipemode.c +++ b/g10/pipemode.c @@ -85,7 +85,7 @@ make_control ( byte *buf, int code, int operation ) static int pipemode_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; struct pipemode_context_s *stx = opaque; @@ -291,7 +291,7 @@ pipemode_filter( void *opaque, int control, void run_in_pipemode(void) { - IOBUF fp; + iobuf_t fp; armor_filter_context_t afx; struct pipemode_context_s stx; int rc; diff --git a/g10/pkclist.c b/g10/pkclist.c index e6c826963..5a4aa250f 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -74,10 +74,10 @@ do_show_revocation_reason( PKT_signature *sig ) log_info( _("reason for revocation: ") ); if( text ) - fputs( text, log_stream() ); + fputs( text, log_get_stream () ); else - fprintf( log_stream(), "code=%02x", *p ); - putc( '\n', log_stream() ); + fprintf( log_get_stream (), "code=%02x", *p ); + putc( '\n', log_get_stream () ); n--; p++; pp = NULL; do { @@ -90,8 +90,8 @@ do_show_revocation_reason( PKT_signature *sig ) pp = memchr( p, '\n', n ); nn = pp? pp - p : n; log_info( _("revocation comment: ") ); - print_string( log_stream(), p, nn, 0 ); - putc( '\n', log_stream() ); + print_string( log_get_stream(), p, nn, 0 ); + putc( '\n', log_get_stream() ); p += nn; n -= nn; } } while( pp ); @@ -186,11 +186,11 @@ show_paths (const PKT_public_key *pk, int only_first ) return; } - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); rc = get_pubkey( pk, keyid ); if( rc ) { log_error("key %08lX: public key not found: %s\n", - (ulong)keyid[1], g10_errstr(rc) ); + (ulong)keyid[1], gpg_strerror (rc) ); return; } @@ -214,7 +214,7 @@ show_paths (const PKT_public_key *pk, int only_first ) p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ), - m_free(p); + xfree (p); tty_printf("\"\n"); free_public_key( pk ); } @@ -276,7 +276,7 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, (ulong)keyid[1], datestr_from_pk( pk ) ); p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ), - m_free(p); + xfree (p); tty_printf("\"\n"); keyblock = get_pubkeyblock (keyid); @@ -395,9 +395,9 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, quit = 1; break ; /* back to the menu */ } - m_free(p); p = NULL; + xfree (p); p = NULL; } - m_free(p); + xfree (p); return show? -2: quit? -1 : changed; } @@ -558,7 +558,7 @@ do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel ) size_t n; char *p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ); - m_free(p); + xfree (p); } tty_printf("\"\n"); print_fingerprint (pk, NULL, 2); @@ -594,7 +594,7 @@ do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel ) int check_signatures_trust( PKT_signature *sig ) { - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + PKT_public_key *pk = xcalloc (1, sizeof *pk ); unsigned int trustlevel; int rc=0; @@ -602,7 +602,7 @@ check_signatures_trust( PKT_signature *sig ) if (rc) { /* this should not happen */ log_error("Ooops; the key vanished - can't check the trust\n"); - rc = G10ERR_NO_PUBKEY; + rc = GPG_ERR_NO_PUBKEY; goto leave; } @@ -662,7 +662,7 @@ check_signatures_trust( PKT_signature *sig ) log_info(_(" The signature is probably a FORGERY.\n")); if (opt.with_fingerprint) print_fingerprint (pk, NULL, 1); - rc = G10ERR_BAD_SIGN; + rc = gpg_error (GPG_ERR_BAD_SIGNATURE); break; case TRUST_MARGINAL: @@ -701,7 +701,7 @@ release_pk_list( PK_LIST pk_list ) for( ; pk_list; pk_list = pk_rover ) { pk_rover = pk_list->next; free_public_key( pk_list->pk ); - m_free( pk_list ); + xfree ( pk_list ); } } @@ -730,10 +730,10 @@ default_recipient(void) int i; if( opt.def_recipient ) - return m_strdup( opt.def_recipient ); + return xstrdup ( opt.def_recipient ); if( !opt.def_recipient_self ) return NULL; - sk = m_alloc_clear( sizeof *sk ); + sk = xcalloc (1, sizeof *sk ); i = get_seckey_byname( sk, NULL, 0 ); if( i ) { free_secret_key( sk ); @@ -742,7 +742,7 @@ default_recipient(void) n = MAX_FINGERPRINT_LEN; fingerprint_from_sk( sk, fpr, &n ); free_secret_key( sk ); - p = m_alloc( 2*n+3 ); + p = xmalloc ( 2*n+3 ); *p++ = '0'; *p++ = 'x'; for(i=0; i < n; i++ ) @@ -829,17 +829,17 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) } } else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); pk->req_usage = use; /* We can encrypt-to a disabled key */ if( (rc = get_pubkey_byname( pk, rov->d, NULL, NULL, 1 )) ) { free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); + log_error(_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) ); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", rov->d, strlen (rov->d), -1); goto fail; } - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { + else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use )) ) { /* Skip the actual key if the key is already present * in the list */ if (key_present_in_pk_list(pk_list, pk) == 0) { @@ -849,7 +849,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) } else { PK_LIST r; - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = (rov->flags&2)?1:0; @@ -867,7 +867,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) } else { free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); + log_error(_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) ); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", rov->d, strlen (rov->d), -1); goto fail; @@ -887,13 +887,13 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) "You did not specify a user ID. (you may use \"-r\")\n")); for(;;) { rc = 0; - m_free(answer); + xfree (answer); if( have_def_rec ) { answer = def_rec; def_rec = NULL; } - else if(backlog) { - answer=pop_strlist(&backlog); + else if (backlog) { + answer = strlist_pop (&backlog); } else { answer = cpr_get_utf8("pklist.user_id.enter", @@ -902,19 +902,19 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) cpr_kill_prompt(); } if( !answer || !*answer ) { - m_free(answer); + xfree (answer); break; } if(expand_id(answer,&backlog,0)) continue; if( pk ) free_public_key( pk ); - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); pk->req_usage = use; rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); if( rc ) tty_printf(_("No such user ID.\n")); - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use)) ) { if( have_def_rec ) { if (key_present_in_pk_list(pk_list, pk) == 0) { free_public_key(pk); pk = NULL; @@ -922,7 +922,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) "already set as default recipient\n") ); } else { - PK_LIST r = m_alloc( sizeof *r ); + PK_LIST r = xmalloc ( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* no throwing default ids */ @@ -963,11 +963,11 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) size_t n; char *p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ); - m_free(p); + xfree (p); } tty_printf("\"\n"); - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* no throwing interactive ids */ @@ -978,7 +978,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) } } } - m_free(def_rec); def_rec = NULL; + xfree (def_rec); def_rec = NULL; have_def_rec = 0; } if( pk ) { @@ -987,13 +987,13 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) } } else if( !any_recipients && (def_rec = default_recipient()) ) { - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); pk->req_usage = use; /* The default recipient may be disabled */ rc = get_pubkey_byname( pk, def_rec, NULL, NULL, 1 ); if( rc ) log_error(_("unknown default recipient `%s'\n"), def_rec ); - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use)) ) { /* Mark any_recipients here since the default recipient would have been used if it wasn't already there. It doesn't really matter if we got this key from the default @@ -1002,7 +1002,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) if (key_present_in_pk_list(pk_list, pk) == 0) log_info(_("skipped: public key already set as default recipient\n")); else { - PK_LIST r = m_alloc( sizeof *r ); + PK_LIST r = xmalloc ( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* no throwing default ids */ @@ -1013,7 +1013,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) free_public_key( pk ); pk = NULL; } - m_free(def_rec); def_rec = NULL; + xfree (def_rec); def_rec = NULL; } else { any_recipients = 0; @@ -1021,17 +1021,17 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) if( (remusr->flags & 1) ) continue; /* encrypt-to keys are already handled */ - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); pk->req_usage = use; if( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0 )) ) { free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); + log_error(_("%s: skipped: %s\n"), remusr->d, gpg_strerror (rc) ); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", remusr->d, strlen (remusr->d), -1); goto fail; } - else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { + else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use )) ) { int trustlevel; trustlevel = get_validity (pk, pk->user_id); @@ -1043,7 +1043,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) remusr->d, strlen (remusr->d), -1); - rc=G10ERR_UNU_PUBKEY; + rc = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); goto fail; } else if( do_we_trust_pre( pk, trustlevel ) ) { @@ -1062,7 +1062,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) } else { PK_LIST r; - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = (remusr->flags&2)?1:0; @@ -1075,7 +1075,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) remusr->d, strlen (remusr->d), -1); - rc=G10ERR_UNU_PUBKEY; + rc = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); goto fail; } } @@ -1085,7 +1085,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) remusr->d, strlen (remusr->d), -1); - log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); + log_error(_("%s: skipped: %s\n"), remusr->d, gpg_strerror (rc) ); goto fail; } } @@ -1094,7 +1094,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) if( !rc && !any_recipients ) { log_error(_("no valid addressees\n")); write_status_text (STATUS_NO_RECP, "0"); - rc = G10ERR_NO_USER_ID; + rc = GPG_ERR_NO_USER_ID; } fail: @@ -1145,11 +1145,11 @@ algo_available( preftype_t preftype, int algo, void *hint ) && algo != CIPHER_ALGO_TWOFISH)) return 0; - return algo && !check_cipher_algo( algo ); + return algo && !gcry_cipher_test_algo (algo); } else if( preftype == PREFTYPE_HASH ) { - if(hint && ((*(int *)hint) != md_digest_length(algo))) + if(hint && ((*(int *)hint) != gcry_md_get_algo_dlen (algo))) return 0; if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5 @@ -1168,7 +1168,7 @@ algo_available( preftype_t preftype, int algo, void *hint ) if( RFC2440 && algo == DIGEST_ALGO_TIGER ) return 0; - return algo && !check_digest_algo( algo ); + return algo && !gcry_md_test_algo( algo ); } else if( preftype == PREFTYPE_ZIP ) { diff --git a/g10/pkglue.c b/g10/pkglue.c new file mode 100644 index 000000000..3e378822c --- /dev/null +++ b/g10/pkglue.c @@ -0,0 +1,278 @@ +/* pkglue.c - public key operations glue code + * Copyright (C) 2000, 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 "util.h" +#include "pkglue.h" + + + +/**************** + * Emulate our old PK interface here - sometime in the future we might + * change the internal design to directly fit to libgcrypt. + */ +int +pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) +{ + gcry_sexp_t s_sig, s_hash, s_skey, list; + int rc; + + /* make a sexp from skey */ + if (algo == GCRY_PK_DSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4]); + } + else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3]); + } + else + return GPG_ERR_PUBKEY_ALGO; + + if (rc) + BUG (); + + /* put hash into a S-Exp s_hash */ + if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) + BUG (); + + rc = gcry_pk_sign (&s_sig, s_hash, s_skey); + gcry_sexp_release (s_hash); + gcry_sexp_release (s_skey); + + if (rc) + ; + else + { + list = gcry_sexp_find_token (s_sig, "r", 0); + assert (list); + data[0] = gcry_sexp_nth_mpi (list, 1, 0); + assert (data[0]); + gcry_sexp_release (list); + + list = gcry_sexp_find_token (s_sig, "s", 0); + assert (list); + data[1] = gcry_sexp_nth_mpi (list, 1, 0); + assert (data[1]); + gcry_sexp_release (list); + } + + + gcry_sexp_release (s_sig); + return rc; +} + +/**************** + * Emulate our old PK interface here - sometime in the future we might + * change the internal design to directly fit to libgcrypt. + */ +int +pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) +{ + gcry_sexp_t s_sig, s_hash, s_pkey; + int rc; + + /* make a sexp from pkey */ + if (algo == GCRY_PK_DSA) + { + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", + pkey[0], pkey[1], pkey[2], pkey[3]); + } + else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(elg(p%m)(g%m)(y%m)))", + pkey[0], pkey[1], pkey[2]); + } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); + } + else + return GPG_ERR_PUBKEY_ALGO; + + if (rc) + BUG (); + + /* put hash into a S-Exp s_hash */ + if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) + BUG (); + + /* put data into a S-Exp s_sig */ + if (algo == GCRY_PK_DSA) + { + rc = gcry_sexp_build (&s_sig, NULL, + "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); + } + else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_sig, NULL, + "(sig-val(elg(r%m)(s%m)))", data[0], data[1]); + } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]); + } + else + BUG (); + + if (rc) + BUG (); + + + rc = gcry_pk_verify (s_sig, s_hash, s_pkey); + gcry_sexp_release (s_sig); + gcry_sexp_release (s_hash); + gcry_sexp_release (s_pkey); + return rc; +} + + + + +/**************** + * Emulate our old PK interface here - sometime in the future we might + * change the internal design to directly fit to libgcrypt. + */ +int +pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) +{ + gcry_sexp_t s_ciph, s_data, s_pkey; + int rc; + + /* make a sexp from pkey */ + if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(elg(p%m)(g%m)(y%m)))", + pkey[0], pkey[1], pkey[2]); + } + else + return GPG_ERR_PUBKEY_ALGO; + + if (rc) + BUG (); + + /* put the data into a simple list */ + if (gcry_sexp_build (&s_data, NULL, "%m", data)) + BUG (); + + /* pass it to libgcrypt */ + rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); + gcry_sexp_release (s_data); + gcry_sexp_release (s_pkey); + + if (rc) + ; + else + { /* add better error handling or make gnupg use S-Exp directly */ + gcry_sexp_t list = gcry_sexp_find_token (s_ciph, "a", 0); + assert (list); + resarr[0] = gcry_sexp_nth_mpi (list, 1, 0); + assert (resarr[0]); + gcry_sexp_release (list); + + list = gcry_sexp_find_token (s_ciph, "b", 0); + assert (list); + resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); + assert (resarr[1]); + gcry_sexp_release (list); + } + + gcry_sexp_release (s_ciph); + return rc; +} + + + +/**************** + * Emulate our old PK interface here - sometime in the future we might + * change the internal design to directly fit to libgcrypt. + */ +int +pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, + gcry_mpi_t * skey) +{ + gcry_sexp_t s_skey, s_data, s_plain; + int rc; + + *result = NULL; + /* make a sexp from skey */ + if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3]); + } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4], + skey[5]); + } + else + return GPG_ERR_PUBKEY_ALGO; + + if (rc) + BUG (); + + /* put data into a S-Exp s_data */ + if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_data, NULL, + "(enc-val(elg(a%m)(b%m)))", data[0], data[1]); + } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]); + } + else + BUG (); + + if (rc) + BUG (); + + rc = gcry_pk_decrypt (&s_plain, s_data, s_skey); + gcry_sexp_release (s_skey); + gcry_sexp_release (s_data); + if (rc) + return rc; + + *result = gcry_sexp_nth_mpi (s_plain, 0, 0); + gcry_sexp_release (s_plain); + if (!*result) + return -1; /* oops */ + + return 0; +} diff --git a/g10/pkglue.h b/g10/pkglue.h new file mode 100644 index 000000000..3065d66aa --- /dev/null +++ b/g10/pkglue.h @@ -0,0 +1,34 @@ +/* pkglue.h - public key operations definitions + * 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_PKGLUE_H +#define GNUPG_G10_PKGLUE_H + +int pk_sign (int algo, gcry_mpi_t *data, gcry_mpi_t hash, + gcry_mpi_t *skey); +int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, + gcry_mpi_t *pkey); +int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *pkey); +int pk_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey); + + +#endif /*GNUPG_G10_PKGLUE_H*/ diff --git a/g10/plaintext.c b/g10/plaintext.c index 89043026c..d84a523fe 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -1,5 +1,6 @@ /* plaintext.c - process plaintext packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -28,6 +29,7 @@ #include <fcntl.h> /* for setmode() */ #endif +#include "gpg.h" #include "util.h" #include "memory.h" #include "options.h" @@ -48,7 +50,7 @@ */ int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, - int nooutput, int clearsig ) + int nooutput, int clearsig, int *create_failed ) { char *fname = NULL; FILE *fp = NULL; @@ -58,12 +60,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, #ifdef __riscos__ int filetype = 0xfff; #endif + int dummy_create_failed; + + if (!create_failed) + create_failed = &dummy_create_failed; + *create_failed = 0; /* create the filename as C string */ if( nooutput ) ; else if( opt.outfile ) { - fname = m_alloc( strlen( opt.outfile ) + 1); + fname = xmalloc ( strlen( opt.outfile ) + 1); strcpy(fname, opt.outfile ); } else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) { @@ -75,7 +82,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( !fname ) fname = ask_outfile_name( pt->name, pt->namelen ); if( !fname ) { - rc = G10ERR_CREATE_FILE; + *create_failed = 1; + rc = GPG_ERR_GENERAL; goto leave; } } @@ -96,11 +104,12 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, while( !overwrite_filep (fname) ) { char *tmp = ask_outfile_name (NULL, 0); if ( !tmp || !*tmp ) { - m_free (tmp); - rc = G10ERR_CREATE_FILE; + xfree (tmp); + *create_failed = 1; + rc = GPG_ERR_GENERAL; goto leave; } - m_free (fname); + xfree (fname); fname = tmp; } } @@ -109,8 +118,9 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( fp || nooutput ) ; else if( !(fp = fopen(fname,"wb")) ) { + rc = gpg_error_from_errno (errno); log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - rc = G10ERR_CREATE_FILE; + *create_failed = 1; goto leave; } #else /* __riscos__ */ @@ -124,8 +134,9 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, else { fp = fopen(fname,"wb"); if( !fp ) { + rc == gpg_error_from_errno (errno); log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - rc = G10ERR_CREATE_FILE; + *create_failed = 1; if (errno == 106) log_info("Do output file and input file have the same name?\n"); goto leave; @@ -150,76 +161,76 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( convert ) { /* text mode */ for( ; pt->len; pt->len-- ) { if( (c = iobuf_get(pt->buf)) == -1 ) { + rc = gpg_error_from_errno (errno); log_error("Problem reading source (%u bytes remaining)\n", (unsigned)pt->len); - rc = G10ERR_READ_FILE; goto leave; } if( mfx->md ) - md_putc(mfx->md, c ); + gcry_md_putc (mfx->md, c ); #ifndef HAVE_DOSISH_SYSTEM if( c == '\r' ) /* convert to native line ending */ continue; /* fixme: this hack might be too simple */ #endif if( fp ) { - if( putc( c, fp ) == EOF ) { + if( putc( c, fp ) == EOF ) { + rc = gpg_error_from_errno (errno); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; goto leave; } } } } else { /* binary mode */ - byte *buffer = m_alloc( 32768 ); + byte *buffer = xmalloc ( 32768 ); while( pt->len ) { int len = pt->len > 32768 ? 32768 : pt->len; len = iobuf_read( pt->buf, buffer, len ); if( len == -1 ) { + rc = gpg_error_from_errno (errno); log_error("Problem reading source (%u bytes remaining)\n", (unsigned)pt->len); - rc = G10ERR_READ_FILE; - m_free( buffer ); + xfree ( buffer ); goto leave; } if( mfx->md ) - md_write( mfx->md, buffer, len ); + gcry_md_write( mfx->md, buffer, len ); if( fp ) { - if( fwrite( buffer, 1, len, fp ) != len ) { + if( fwrite( buffer, 1, len, fp ) != len ) { + rc = gpg_error_from_errno (errno); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - m_free( buffer ); + xfree ( buffer ); goto leave; } } pt->len -= len; } - m_free( buffer ); + xfree ( buffer ); } } else if( !clearsig ) { if( convert ) { /* text mode */ while( (c = iobuf_get(pt->buf)) != -1 ) { if( mfx->md ) - md_putc(mfx->md, c ); + gcry_md_putc (mfx->md, c ); #ifndef HAVE_DOSISH_SYSTEM if( convert && c == '\r' ) continue; /* fixme: this hack might be too simple */ #endif if( fp ) { - if( putc( c, fp ) == EOF ) { + if( putc( c, fp ) == EOF ) { + rc = gpg_error_from_errno (errno); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; goto leave; } } } } else { /* binary mode */ - byte *buffer = m_alloc( 32768 ); + byte *buffer = xmalloc ( 32768 ); int eof; for( eof=0; !eof; ) { /* Why do we check for len < 32768: @@ -234,18 +245,18 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( len < 32768 ) eof = 1; if( mfx->md ) - md_write( mfx->md, buffer, len ); + gcry_md_write( mfx->md, buffer, len ); if( fp ) { if( fwrite( buffer, 1, len, fp ) != len ) { + rc = gpg_error_from_errno (errno); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; - m_free( buffer ); + xfree ( buffer ); goto leave; } } } - m_free( buffer ); + xfree ( buffer ); } pt->buf = NULL; } @@ -255,17 +266,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, while( (c = iobuf_get(pt->buf)) != -1 ) { if( fp ) { if( putc( c, fp ) == EOF ) { + rc = gpg_error_from_errno (errno); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; goto leave; } } if( !mfx->md ) continue; if( state == 2 ) { - md_putc(mfx->md, '\r' ); - md_putc(mfx->md, '\n' ); + gcry_md_putc (mfx->md, '\r' ); + gcry_md_putc (mfx->md, '\n' ); state = 0; } if( !state ) { @@ -274,18 +285,18 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, else if( c == '\n' ) state = 2; else - md_putc(mfx->md, c ); + gcry_md_putc (mfx->md, c ); } else if( state == 1 ) { if( c == '\n' ) state = 2; else { - md_putc(mfx->md, '\r' ); + gcry_md_putc (mfx->md, '\r' ); if( c == '\r' ) state = 1; else { state = 0; - md_putc(mfx->md, c ); + gcry_md_putc (mfx->md, c ); } } } @@ -294,9 +305,9 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } if( fp && fp != stdout && fclose(fp) ) { + rc = gpg_error_from_errno (errno); log_error("Error closing `%s': %s\n", fname, strerror(errno) ); fp = NULL; - rc = G10ERR_WRITE_FILE; goto leave; } fp = NULL; @@ -304,12 +315,12 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, leave: if( fp && fp != stdout ) fclose(fp); - m_free(fname); + xfree (fname); return rc; } static void -do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode ) +do_hash( MD_HANDLE md, MD_HANDLE md2, iobuf_t fp, int textmode ) { text_filter_context_t tfx; int c; @@ -323,27 +334,27 @@ do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode ) int lc = -1; while( (c = iobuf_get(fp)) != -1 ) { if( c == '\n' && lc == '\r' ) - md_putc(md2, c); + gcry_md_putc (md2, c); else if( c == '\n' ) { - md_putc(md2, '\r'); - md_putc(md2, c); + gcry_md_putc (md2, '\r'); + gcry_md_putc (md2, c); } else if( c != '\n' && lc == '\r' ) { - md_putc(md2, '\n'); - md_putc(md2, c); + gcry_md_putc (md2, '\n'); + gcry_md_putc (md2, c); } else - md_putc(md2, c); + gcry_md_putc (md2, c); if( md ) - md_putc(md, c ); + gcry_md_putc (md, c ); lc = c; } } else { while( (c = iobuf_get(fp)) != -1 ) { if( md ) - md_putc(md, c ); + gcry_md_putc (md, c ); } } } @@ -359,7 +370,7 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, { progress_filter_context_t pfx; char *answer = NULL; - IOBUF fp; + iobuf_t fp; int rc = 0; fp = open_sigfile( inname, &pfx ); /* open default file */ @@ -368,12 +379,12 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, int any=0; tty_printf(_("Detached signature.\n")); do { - m_free(answer); + xfree (answer); answer = cpr_get("detached_signature.filename", _("Please enter name of data file: ")); cpr_kill_prompt(); if( any && !*answer ) { - rc = G10ERR_READ_FILE; + rc = GPG_ERR_GENERAL; goto leave; } fp = iobuf_open(answer); @@ -382,8 +393,8 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, any++; } else if( !fp ) { + rc = gpg_error_from_errno (errno); log_error("can't open `%s': %s\n", answer, strerror(errno) ); - rc = G10ERR_READ_FILE; goto leave; } } while( !fp ); @@ -399,7 +410,7 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, iobuf_close(fp); leave: - m_free(answer); + xfree (answer); return rc; } @@ -414,7 +425,7 @@ hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, const char *sigfilename, int textmode ) { progress_filter_context_t pfx; - IOBUF fp; + iobuf_t fp; STRLIST sl; if( !files ) { @@ -426,16 +437,17 @@ hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, return 0; } log_error (_("no signed data\n")); - return G10ERR_OPEN_FILE; + return GPG_ERR_NO_DATA; } for (sl=files; sl; sl = sl->next ) { fp = iobuf_open( sl->d ); if( !fp ) { + int tmperr = gpg_error_from_errno (errno); log_error(_("can't open signed data `%s'\n"), print_fname_stdin(sl->d)); - return G10ERR_OPEN_FILE; + return tmperr; } handle_progress (&pfx, fp, sl->d); do_hash( md, md2, fp, textmode ); diff --git a/g10/progress.c b/g10/progress.c index bb414faae..9d9805065 100644 --- a/g10/progress.c +++ b/g10/progress.c @@ -21,6 +21,7 @@ #include <config.h> #include <stdio.h> +#include "gpg.h" #include "iobuf.h" #include "filter.h" #include "status.h" @@ -32,7 +33,7 @@ */ int progress_filter (void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { int rc = 0; progress_filter_context_t *pfx = opaque; @@ -86,7 +87,7 @@ progress_filter (void *opaque, int control, /* Note, that we must always dealloc resources of a filter within the filter handler and not anywhere else. (We set it to NULL and check all uses just in case.) */ - m_free (pfx->what); + xfree (pfx->what); pfx->what = NULL; } else if (control == IOBUFCTRL_DESC) @@ -95,7 +96,7 @@ progress_filter (void *opaque, int control, } void -handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name) +handle_progress (progress_filter_context_t *pfx, iobuf_t inp, const char *name) { off_t filesize = 0; @@ -111,7 +112,7 @@ handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name) filesize = opt.set_filesize; /* register the progress filter */ - pfx->what = m_strdup (name ? name : "stdin"); + pfx->what = xstrdup (name ? name : "stdin"); pfx->total = filesize; iobuf_push_filter (inp, progress_filter, pfx); } diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 1c52ce4de..b5837b24e 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -1,5 +1,6 @@ /* pubkey-enc.c - public key encoded packet handling - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,6 +24,8 @@ #include <stdlib.h> #include <string.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "memory.h" #include "packet.h" @@ -34,6 +37,7 @@ #include "options.h" #include "main.h" #include "i18n.h" +#include "pkglue.h" static int get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ); @@ -72,12 +76,12 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) PKT_secret_key *sk = NULL; int rc; - rc = check_pubkey_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC); + rc = openpgp_pk_test_algo (k->pubkey_algo, PUBKEY_USAGE_ENC); if( rc ) goto leave; if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) { - sk = m_alloc_clear( sizeof *sk ); + sk = xcalloc (1, sizeof *sk ); sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/ if( !(rc = get_seckey( sk, k->keyid )) ) rc = get_it( k, dek, sk, k->keyid ); @@ -90,10 +94,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) for(;;) { if( sk ) free_secret_key( sk ); - sk = m_alloc_clear( sizeof *sk ); + sk = xcalloc (1, sizeof *sk ); rc=enum_secret_keys( &enum_context, sk, 1, 0); if( rc ) { - rc = G10ERR_NO_SECKEY; + rc = GPG_ERR_NO_SECKEY; break; } if( sk->pubkey_algo != k->pubkey_algo ) @@ -106,7 +110,7 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) { p=get_last_passphrase(); set_next_passphrase(p); - m_free(p); + xfree (p); } rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask @@ -133,16 +137,17 @@ static int get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) { int rc; - MPI plain_dek = NULL; + gcry_mpi_t plain_dek = NULL; byte *frame = NULL; unsigned n, nframe; u16 csum, csum2; - rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, enc->data, sk->skey ); + rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey); if( rc ) - goto leave; - frame = mpi_get_buffer( plain_dek, &nframe, NULL ); - mpi_free( plain_dek ); plain_dek = NULL; + goto leave; + if ( gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek)) + BUG(); + gcry_mpi_release (plain_dek); plain_dek = NULL; /* Now get the DEK (data encryption key) from the frame * @@ -162,30 +167,30 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) * CSUM */ if( DBG_CIPHER ) - log_hexdump("DEK frame:", frame, nframe ); + log_printhex ("DEK frame:", frame, nframe ); n=0; if( n + 7 > nframe ) - { rc = G10ERR_WRONG_SECKEY; goto leave; } + { rc = GPG_ERR_WRONG_SECKEY; goto leave; } if( frame[n] == 1 && frame[nframe-1] == 2 ) { log_info(_("old encoding of the DEK is not supported\n")); - rc = G10ERR_CIPHER_ALGO; + rc = GPG_ERR_CIPHER_ALGO; goto leave; } if( frame[n] != 2 ) /* somethink is wrong */ - { rc = G10ERR_WRONG_SECKEY; goto leave; } + { rc = GPG_ERR_WRONG_SECKEY; goto leave; } for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ ; n++; /* and the zero byte */ if( n + 4 > nframe ) - { rc = G10ERR_WRONG_SECKEY; goto leave; } + { rc = GPG_ERR_WRONG_SECKEY; goto leave; } dek->keylen = nframe - (n+1) - 2; dek->algo = frame[n++]; if( dek->algo == CIPHER_ALGO_IDEA ) write_status(STATUS_RSA_OR_IDEA); - rc = check_cipher_algo( dek->algo ); + rc = openpgp_cipher_test_algo (dek->algo); if( rc ) { - if( !opt.quiet && rc == G10ERR_CIPHER_ALGO ) { + if( !opt.quiet && rc == GPG_ERR_CIPHER_ALGO ) { log_info(_("cipher algorithm %d%s is unknown or disabled\n"), dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); if(dek->algo==CIPHER_ALGO_IDEA) @@ -194,8 +199,8 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) dek->algo = 0; goto leave; } - if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) { - rc = G10ERR_WRONG_SECKEY; + if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) { + rc = GPG_ERR_WRONG_SECKEY; goto leave; } @@ -206,11 +211,11 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) for( csum2=0, n=0; n < dek->keylen; n++ ) csum2 += dek->key[n]; if( csum != csum2 ) { - rc = G10ERR_WRONG_SECKEY; + rc = GPG_ERR_WRONG_SECKEY; goto leave; } if( DBG_CIPHER ) - log_hexdump("DEK is:", dek->key, dek->keylen ); + log_printhex ("DEK is:", dek->key, dek->keylen ); /* check that the algo is in the preferences and whether it has expired */ { PKT_public_key *pk = NULL; @@ -258,7 +263,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) if ( pk && pk->is_revoked ) { log_info( _("NOTE: key has been revoked") ); - putc( '\n', log_stream() ); + putc( '\n', log_get_stream() ); show_revocation_reason( pk, 1 ); } @@ -268,8 +273,8 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) leave: - mpi_free(plain_dek); - m_free(frame); + gcry_mpi_release (plain_dek); + xfree (frame); return rc; } @@ -286,21 +291,21 @@ get_override_session_key( DEK *dek, const char *string ) int i; if ( !string ) - return G10ERR_BAD_KEY; + return GPG_ERR_BAD_KEY; dek->algo = atoi(string); if ( dek->algo < 1 ) - return G10ERR_BAD_KEY; + return GPG_ERR_BAD_KEY; if ( !(s = strchr ( string, ':' )) ) - return G10ERR_BAD_KEY; + return GPG_ERR_BAD_KEY; s++; for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) { int c = hextobyte ( s ); if (c == -1) - return G10ERR_BAD_KEY; + return GPG_ERR_BAD_KEY; dek->key[i] = c; } if ( *s ) - return G10ERR_BAD_KEY; + return GPG_ERR_BAD_KEY; dek->keylen = i; return 0; } diff --git a/g10/revoke.c b/g10/revoke.c index a45d2d623..80e32a32e 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -59,15 +59,15 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque ) ud = native_to_utf8( reason->desc ); buflen += strlen(ud); } - buffer = m_alloc( buflen ); + buffer = xmalloc ( buflen ); *buffer = reason->code; if( ud ) { memcpy(buffer+1, ud, strlen(ud) ); - m_free( ud ); + xfree ( ud ); } build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen ); - m_free( buffer ); + xfree ( buffer ); return 0; } @@ -76,7 +76,7 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque ) and pick a user ID that has a uid signature, and include it if possible. */ static int -export_minimal_pk(IOBUF out,KBNODE keyblock, +export_minimal_pk(iobuf_t out,KBNODE keyblock, PKT_signature *revsig,PKT_signature *revkey) { KBNODE node; @@ -90,7 +90,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, if(!node) { log_error(_("key incomplete\n")); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } keyid_from_pk(node->pkt->pkt.public_key,keyid); @@ -99,7 +99,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); return rc; } @@ -113,7 +113,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); return rc; } } @@ -125,7 +125,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); return rc; } } @@ -143,7 +143,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, else { log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } } @@ -171,7 +171,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); return rc; } @@ -183,7 +183,7 @@ export_minimal_pk(IOBUF out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); return rc; } } @@ -202,7 +202,7 @@ gen_desig_revoke( const char *uname ) PKT_public_key *pk = NULL; PKT_secret_key *sk = NULL; PKT_signature *sig = NULL; - IOBUF out = NULL; + iobuf_t out = NULL; struct revocation_reason_info *reason = NULL; KEYDB_HANDLE kdbhd; KEYDB_SEARCH_DESC desc; @@ -212,22 +212,22 @@ gen_desig_revoke( const char *uname ) if( opt.batch ) { log_error(_("sorry, can't do this in batch mode\n")); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } memset( &afx, 0, sizeof afx); kdbhd = keydb_new (0); classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID; if (rc) { - log_error (_("key `%s' not found: %s\n"),uname, g10_errstr (rc)); + log_error (_("key `%s' not found: %s\n"),uname, gpg_strerror (rc)); goto leave; } rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -253,7 +253,7 @@ gen_desig_revoke( const char *uname ) if(sk) free_secret_key(sk); - sk=m_alloc_clear(sizeof(*sk)); + sk=xcalloc (1,sizeof(*sk)); rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN); @@ -302,7 +302,7 @@ gen_desig_revoke( const char *uname ) 0, 0, 0, revocation_reason_build_cb, reason ); if( rc ) { - log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); + log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc)); goto leave; } @@ -403,7 +403,7 @@ gen_revoke( const char *uname ) PKT_public_key *pk = NULL; PKT_signature *sig = NULL; u32 sk_keyid[2]; - IOBUF out = NULL; + iobuf_t out = NULL; KBNODE keyblock = NULL, pub_keyblock = NULL; KBNODE node; KEYDB_HANDLE kdbhd; @@ -412,7 +412,7 @@ gen_revoke( const char *uname ) if( opt.batch ) { log_error(_("sorry, can't do this in batch mode\n")); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } memset( &afx, 0, sizeof afx); @@ -423,16 +423,16 @@ gen_revoke( const char *uname ) */ kdbhd = keydb_new (1); classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID; if (rc) { log_error (_("secret key `%s' not found: %s\n"), - uname, g10_errstr (rc)); + uname, gpg_strerror (rc)); goto leave; } rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -447,14 +447,14 @@ gen_revoke( const char *uname ) keyid_from_sk( sk, sk_keyid ); print_seckey_info (sk); - pk = m_alloc_clear( sizeof *pk ); + pk = xcalloc (1, sizeof *pk ); /* FIXME: We should get the public key direct from the secret one */ pub_keyblock=get_pubkeyblock(sk_keyid); if(!pub_keyblock) { - log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) ); + log_error(_("no corresponding public key: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -466,7 +466,7 @@ gen_revoke( const char *uname ) if( cmp_public_secret_key( pk, sk ) ) { log_error(_("public key does not match secret key!\n") ); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; goto leave; } @@ -489,7 +489,7 @@ gen_revoke( const char *uname ) switch( is_secret_key_protected( sk ) ) { case -1: log_error(_("unknown protection algorithm\n")); - rc = G10ERR_PUBKEY_ALGO; + rc = GPG_ERR_PUBKEY_ALGO; break; case 0: tty_printf(_("NOTE: This key is not protected!\n")); @@ -517,7 +517,7 @@ gen_revoke( const char *uname ) opt.force_v4_certs?4:0, 0, 0, revocation_reason_build_cb, reason ); if( rc ) { - log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); + log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc)); goto leave; } @@ -537,7 +537,7 @@ gen_revoke( const char *uname ) rc = build_packet( out, &pkt ); if( rc ) { - log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); + log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); goto leave; } } @@ -581,7 +581,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) do { code=-1; - m_free(description); + xfree (description); description = NULL; tty_printf(_("Please select the reason for the revocation:\n")); @@ -612,7 +612,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) n = -1; else n = atoi(answer); - m_free(answer); + xfree (answer); if( n == 0 ) { code = 0x00; /* no particular reason */ code_text = text_0; @@ -644,25 +644,25 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) trim_trailing_ws( answer, strlen(answer) ); cpr_kill_prompt(); if( !*answer ) { - m_free(answer); + xfree (answer); break; } { char *p = make_printable_string( answer, strlen(answer), 0 ); - m_free(answer); + xfree (answer); answer = p; } if( !description ) - description = m_strdup(answer); + description = xstrdup (answer); else { - char *p = m_alloc( strlen(description) + strlen(answer) + 2 ); + char *p = xmalloc ( strlen(description) + strlen(answer) + 2 ); strcpy(stpcpy(stpcpy( p, description),"\n"),answer); - m_free(description); + xfree (description); description = p; } - m_free(answer); + xfree (answer); } tty_printf(_("Reason for revocation: %s\n"), code_text ); @@ -674,7 +674,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay", _("Is this okay? ")) ); - reason = m_alloc( sizeof *reason ); + reason = xmalloc ( sizeof *reason ); reason->code = code; reason->desc = description; return reason; @@ -684,7 +684,7 @@ void release_revocation_reason_info( struct revocation_reason_info *reason ) { if( reason ) { - m_free( reason->desc ); - m_free( reason ); + xfree ( reason->desc ); + xfree ( reason ); } } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 76f0ee28d..573c78f7a 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -1,5 +1,6 @@ /* seckey-cert.c - secret key certificate packet handling - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,6 +24,8 @@ #include <stdlib.h> #include <string.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "memory.h" #include "packet.h" @@ -33,7 +36,7 @@ #include "options.h" #include "i18n.h" #include "status.h" - +#include "pkglue.h" static int do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, @@ -43,6 +46,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, u16 csum=0; int i, res; unsigned nbytes; + gpg_error_t rc; if( sk->is_protected ) { /* remove the protection */ DEK *dek = NULL; @@ -52,11 +56,11 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, if( sk->protect.s2k.mode == 1001 ) { log_info(_("secret key parts are not available\n")); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } if( sk->protect.algo == CIPHER_ALGO_NONE ) BUG(); - if( check_cipher_algo( sk->protect.algo ) ) { + if( openpgp_cipher_test_algo( sk->protect.algo ) ) { log_info(_("protection algorithm %d%s is not supported\n"), sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" ); if (sk->protect.algo==CIPHER_ALGO_IDEA) @@ -64,7 +68,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, write_status (STATUS_RSA_OR_IDEA); idea_cipher_warn (0); } - return G10ERR_CIPHER_ALGO; + return GPG_ERR_CIPHER_ALGO; } keyid_from_sk( sk, keyid ); keyid[2] = keyid[3] = 0; @@ -76,28 +80,39 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, &sk->protect.s2k, mode, tryagain_text, canceled ); if (!dek && canceled && *canceled) - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; + + rc = gcry_cipher_open (&cipher_hd, sk->protect.algo, + GCRY_CIPHER_MODE_CFB, + GCRY_CIPHER_SECURE + | (sk->protect.algo >= 100 ? + 0 : GCRY_CIPHER_ENABLE_SYNC)); + if (rc) + log_fatal ("cipher open failed: %s\n", gpg_strerror (rc) ); + + rc = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen); + if (rc) + log_fatal ("set key failed: %s\n", gpg_strerror (rc) ); - cipher_hd = cipher_open( sk->protect.algo, - CIPHER_MODE_AUTO_CFB, 1); - cipher_setkey( cipher_hd, dek->key, dek->keylen ); - m_free(dek); + xfree (dek); save_sk = copy_secret_key( NULL, sk ); - cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); + gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen); csum = 0; if( sk->version >= 4 ) { int ndata; + unsigned int ndatabits; byte *p, *data; u16 csumc = 0; i = pubkey_get_npkey(sk->pubkey_algo); - assert( mpi_is_opaque( sk->skey[i] ) ); - p = mpi_get_opaque( sk->skey[i], &ndata ); + assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE )); + p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits ); + ndata = (ndatabits+7)/8; if ( ndata > 1 ) csumc = p[ndata-2] << 8 | p[ndata-1]; - data = m_alloc_secure( ndata ); - cipher_decrypt( cipher_hd, data, p, ndata ); - mpi_free( sk->skey[i] ); sk->skey[i] = NULL ; + data = gcry_xmalloc_secure ( ndata ); + gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata ); + gcry_mpi_release ( sk->skey[i] ); sk->skey[i] = NULL ; p = data; if (sk->protect.sha1chk) { /* This is the new SHA1 checksum method to detect @@ -108,12 +123,13 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, if( ndata < 20 ) log_error("not enough bytes for SHA-1 checksum\n"); else { - MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1); - if (!h) + gcry_md_hd_t h; + + if ( gcry_md_open (&h, DIGEST_ALGO_SHA1, 1)) BUG(); /* algo not available */ - md_write (h, data, ndata - 20); - md_final (h); - if (!memcmp (md_read (h, DIGEST_ALGO_SHA1), + gcry_md_write (h, data, ndata - 20); + gcry_md_final (h); + if (!memcmp (gcry_md_read (h, DIGEST_ALGO_SHA1), data + ndata - 20, 20) ) { /* digest does match. We have to keep the old style checksum in sk->csum, so that the @@ -122,7 +138,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, keys. */ sk->csum = csum = checksum (data, ndata-20); } - md_close (h); + gcry_md_close (h); } } else { @@ -146,56 +162,68 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, if( sk->csum == csum ) { for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { nbytes = ndata; - sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 ); + assert( gcry_is_secure( p ) ); + res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP, + p, &nbytes); + if( res ) + log_bug ("gcry_mpi_scan failed in do_check: %s\n", + gpg_strerror (res)); ndata -= nbytes; p += nbytes; } /* Note: at this point ndata should be 2 for a simple checksum or 20 for the sha1 digest */ } - m_free(data); + xfree (data); } else { for(i=pubkey_get_npkey(sk->pubkey_algo); i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { byte *p; int ndata; - unsigned int dummy; + unsigned int ndatabits; - assert (mpi_is_opaque (sk->skey[i])); - p = mpi_get_opaque (sk->skey[i], &ndata); + assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits ); + ndata = (ndatabits+7)/8; assert (ndata >= 2); assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2); - buffer = m_alloc_secure (ndata); - cipher_sync (cipher_hd); + buffer = gcry_xmalloc_secure (ndata); + gcry_cipher_sync (cipher_hd); buffer[0] = p[0]; buffer[1] = p[1]; - cipher_decrypt (cipher_hd, buffer+2, p+2, ndata-2); + gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2, + p+2, ndata-2); csum += checksum (buffer, ndata); - mpi_free (sk->skey[i]); - dummy = ndata; - sk->skey[i] = mpi_read_from_buffer (buffer, &dummy, 1); + gcry_mpi_release (sk->skey[i]); + res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG, + buffer, &ndata ); + if( res ) + log_bug ("gcry_mpi_scan failed in do_check: %s\n", + gpg_strerror (res)); + assert (sk->skey[i]); - m_free (buffer); + xfree (buffer); /* csum += checksum_mpi (sk->skey[i]); */ } } - cipher_close( cipher_hd ); + gcry_cipher_close (cipher_hd); /* now let's see whether we have used the right passphrase */ if( csum != sk->csum ) { copy_secret_key( sk, save_sk ); passphrase_clear_cache ( keyid, sk->pubkey_algo ); free_secret_key( save_sk ); - return G10ERR_BAD_PASS; + return gpg_error (GPG_ERR_BAD_PASSPHRASE); } /* the checksum may fail, so we also check the key itself */ - res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey ); - if( res ) { - copy_secret_key( sk, save_sk ); - passphrase_clear_cache ( keyid, sk->pubkey_algo ); - free_secret_key( save_sk ); - return G10ERR_BAD_PASS; - } +#warning fixme - we need to reenable this +/* res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey ); */ +/* if( res ) { */ +/* copy_secret_key( sk, save_sk ); */ +/* passphrase_clear_cache ( keyid, sk->pubkey_algo ); */ +/* free_secret_key( save_sk ); */ +/* return gpg_error (GPG_ERR_BAD_PASSPHRASE); */ +/* } */ free_secret_key( save_sk ); sk->is_protected = 0; } @@ -206,7 +234,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, csum += checksum_mpi( sk->skey[i] ); } if( csum != sk->csum ) - return G10ERR_CHECKSUM; + return GPG_ERR_CHECKSUM; } return 0; @@ -222,7 +250,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, int check_secret_key( PKT_secret_key *sk, int n ) { - int rc = G10ERR_BAD_PASS; + int rc = gpg_error (GPG_ERR_BAD_PASSPHRASE); int i,mode; if(n<0) @@ -236,7 +264,7 @@ check_secret_key( PKT_secret_key *sk, int n ) if( n < 1 ) n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */ - for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) { + for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) { int canceled = 0; const char *tryagain = NULL; if (i) { @@ -244,7 +272,8 @@ check_secret_key( PKT_secret_key *sk, int n ) log_info (_("%s ...\n"), _(tryagain)); } rc = do_check( sk, tryagain, mode, &canceled ); - if( rc == G10ERR_BAD_PASS && is_status_enabled() ) { + if( gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE + && is_status_enabled() ) { u32 kid[2]; char buf[50]; @@ -291,21 +320,31 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) if( !sk->is_protected ) { /* okay, apply the protection */ CIPHER_HANDLE cipher_hd=NULL; - if( check_cipher_algo( sk->protect.algo ) ) - rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */ + if( openpgp_cipher_test_algo( sk->protect.algo ) ) + { + rc = gpg_error (GPG_ERR_CIPHER_ALGO); /* unsupport + protection + algorithm */ + } else { print_cipher_algo_note( sk->protect.algo ); - cipher_hd = cipher_open( sk->protect.algo, - CIPHER_MODE_AUTO_CFB, 1 ); - if( cipher_setkey( cipher_hd, dek->key, dek->keylen ) ) + rc = gcry_cipher_open (&cipher_hd, sk->protect.algo, + GCRY_CIPHER_MODE_CFB, + GCRY_CIPHER_SECURE + | (sk->protect.algo >= 100 ? + 0 : GCRY_CIPHER_ENABLE_SYNC) ); + if (rc) + BUG(); + if( gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen ) ) log_info(_("WARNING: Weak key detected" " - please change passphrase again.\n")); - sk->protect.ivlen = cipher_get_blocksize( sk->protect.algo ); + sk->protect.ivlen = gcry_cipher_get_algo_blklen(sk->protect.algo); assert( sk->protect.ivlen <= DIM(sk->protect.iv) ); if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 ) BUG(); /* yes, we are very careful */ - randomize_buffer(sk->protect.iv, sk->protect.ivlen, 1); - cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); + gcry_randomize (sk->protect.iv, sk->protect.ivlen, + GCRY_STRONG_RANDOM); + gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); if( sk->version >= 4 ) { byte *bufarr[PUBKEY_MAX_NSKEY]; unsigned narr[PUBKEY_MAX_NSKEY]; @@ -315,16 +354,21 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) for(j=0, i = pubkey_get_npkey(sk->pubkey_algo); i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) { - assert( !mpi_is_opaque( sk->skey[i] ) ); - bufarr[j] = mpi_get_buffer( sk->skey[i], &narr[j], NULL ); - nbits[j] = mpi_get_nbits( sk->skey[i] ); + assert( !gcry_mpi_get_flag( sk->skey[i], + GCRYMPI_FLAG_OPAQUE )); + + if( gcry_mpi_aprint( GCRYMPI_FMT_USG, (void**)bufarr+j, + narr+j, sk->skey[i])) + BUG(); + + nbits[j] = gcry_mpi_get_nbits( sk->skey[i] ); ndata += narr[j] + 2; } for( ; j < PUBKEY_MAX_NSKEY; j++ ) bufarr[j] = NULL; ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */ - data = m_alloc_secure( ndata ); + data = xmalloc_secure ( ndata ); p = data; for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) { p[0] = nbits[j] >> 8 ; @@ -332,7 +376,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) p += 2; memcpy(p, bufarr[j], narr[j] ); p += narr[j]; - m_free(bufarr[j]); + xfree (bufarr[j]); } if (opt.simple_sk_checksum) { @@ -345,27 +389,28 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) sk->protect.sha1chk = 0; } else { - MD_HANDLE h = md_open (DIGEST_ALGO_SHA1, 1); - if (!h) + gcry_md_hd_t h; + + if (gcry_md_open (&h, GCRY_MD_SHA1, 1)) BUG(); /* algo not available */ - md_write (h, data, ndata - 20); - md_final (h); - memcpy (p, md_read (h, DIGEST_ALGO_SHA1), 20); + gcry_md_write (h, data, ndata - 20); + gcry_md_final (h); + memcpy (p, gcry_md_read (h, GCRY_MD_SHA1), 20); p += 20; - md_close (h); + gcry_md_close (h); sk->csum = csum = 0; sk->protect.sha1chk = 1; } assert( p == data+ndata ); - cipher_encrypt( cipher_hd, data, data, ndata ); + gcry_cipher_encrypt( cipher_hd, data, ndata, NULL, 0 ); for(i = pubkey_get_npkey(sk->pubkey_algo); i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - mpi_free( sk->skey[i] ); + gcry_mpi_release ( sk->skey[i] ); sk->skey[i] = NULL; } i = pubkey_get_npkey(sk->pubkey_algo); - sk->skey[i] = mpi_set_opaque(NULL, data, ndata ); + sk->skey[i] = gcry_mpi_set_opaque(NULL, data, ndata*8); } else { csum = 0; @@ -375,26 +420,30 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) unsigned int nbits; csum += checksum_mpi (sk->skey[i]); - buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL ); - cipher_sync (cipher_hd); - assert ( !mpi_is_opaque (sk->skey[i]) ); - data = m_alloc (nbytes+2); - nbits = mpi_get_nbits (sk->skey[i]); + if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &buffer, + &nbytes, sk->skey[i] ) ) + BUG(); + gcry_cipher_sync (cipher_hd); + assert (!gcry_mpi_get_flag( sk->skey[i], + GCRYMPI_FLAG_OPAQUE )); + data = xmalloc (nbytes+2); + nbits = gcry_mpi_get_nbits (sk->skey[i]); assert (nbytes == (nbits + 7)/8); data[0] = nbits >> 8; data[1] = nbits; - cipher_encrypt (cipher_hd, data+2, buffer, nbytes); - m_free( buffer ); + gcry_cipher_encrypt (cipher_hd, data+2, nbytes, + buffer, nbytes); + xfree ( buffer ); - mpi_free (sk->skey[i]); - sk->skey[i] = mpi_set_opaque (NULL, data, nbytes+2); + gcry_mpi_release (sk->skey[i]); + sk->skey[i] = gcry_mpi_set_opaque (NULL, data, + (nbytes+2)*8); } sk->csum = csum; } sk->is_protected = 1; - cipher_close( cipher_hd ); + gcry_cipher_close( cipher_hd ); } } return rc; } - diff --git a/g10/seskey.c b/g10/seskey.c index fc912eeb5..9eeed2c74 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -1,5 +1,5 @@ /* seskey.c - make sesssion keys etc. - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,6 +23,8 @@ #include <stdlib.h> #include <string.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "cipher.h" #include "mpi.h" @@ -36,26 +38,35 @@ void make_session_key( DEK *dek ) { - CIPHER_HANDLE chd; - int i, rc; - - dek->keylen = cipher_get_keylen( dek->algo ) / 8; - - chd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 ); - randomize_buffer( dek->key, dek->keylen, 1 ); - for(i=0; i < 16; i++ ) { - rc = cipher_setkey( chd, dek->key, dek->keylen ); - if( !rc ) { - cipher_close( chd ); - return; - } - log_info(_("weak key created - retrying\n") ); - /* Renew the session key until we get a non-weak key. */ - randomize_buffer( dek->key, dek->keylen, 1 ); + gcry_cipher_hd_t chd; + int i, rc; + + dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); + + if (gcry_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB, + (GCRY_CIPHER_SECURE + | (dek->algo >= 100 ? + 0 : GCRY_CIPHER_ENABLE_SYNC))) ) + BUG(); + + gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); + for (i=0; i < 16; i++ ) + { + rc = gcry_cipher_setkey (chd, dek->key, dek->keylen); + if (!rc) + { + gcry_cipher_close (chd); + return; + } + if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) + BUG(); + log_info (_("weak key created - retrying\n") ); + /* Renew the session key until we get a non-weak key. */ + gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); } - log_fatal(_( - "cannot avoid weak key for symmetric cipher; tried %d times!\n"), - i); + + log_fatal (_("cannot avoid weak key for symmetric cipher; " + "tried %d times!\n"), i); } @@ -64,15 +75,15 @@ make_session_key( DEK *dek ) * for packing the session key. * returns: A mpi with the session key (caller must free) */ -MPI -encode_session_key( DEK *dek, unsigned nbits ) +gcry_mpi_t +encode_session_key (DEK *dek, unsigned int nbits) { int nframe = (nbits+7) / 8; byte *p; byte *frame; int i,n; u16 csum; - MPI a; + gcry_mpi_t a; /* the current limitation is that we can only use a session key * whose length is a multiple of BITS_PER_MPI_LIMB @@ -99,13 +110,13 @@ encode_session_key( DEK *dek, unsigned nbits ) for( p = dek->key, i=0; i < dek->keylen; i++ ) csum += *p++; - frame = m_alloc_secure( nframe ); + frame = gcry_xmalloc_secure ( nframe ); n = 0; frame[n++] = 0; frame[n++] = 2; i = nframe - 6 - dek->keylen; assert( i > 0 ); - p = get_random_bits( i*8, 1, 1 ); + p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); /* replace zero bytes by new values */ for(;;) { int j, k; @@ -118,14 +129,14 @@ encode_session_key( DEK *dek, unsigned nbits ) if( !k ) break; /* okay: no zero bytes */ k += k/128; /* better get some more */ - pp = get_random_bits( k*8, 1, 1); + pp = gcry_random_bytes_secure( k, GCRY_STRONG_RANDOM); for(j=0; j < i && k ; j++ ) if( !p[j] ) p[j] = pp[--k]; - m_free(pp); + xfree (pp); } memcpy( frame+n, p, i ); - m_free(p); + xfree (p); n += i; frame[n++] = 0; frame[n++] = dek->algo; @@ -133,21 +144,21 @@ encode_session_key( DEK *dek, unsigned nbits ) frame[n++] = csum >>8; frame[n++] = csum; assert( n == nframe ); - a = mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); - mpi_set_buffer( a, frame, nframe, 0 ); - m_free(frame); + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe)) + BUG(); + xfree (frame); return a; } -static MPI -do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, +static gcry_mpi_t +do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, const byte *asn, size_t asnlen, int v3compathack ) { int nframe = (nbits+7) / 8; byte *frame; int i,n; - MPI a; + gcry_mpi_t a; if( len + asnlen + 4 > nframe ) log_bug("can't encode a %d bit MD into a %d bits frame\n", @@ -159,7 +170,7 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, * * PAD consists of FF bytes. */ - frame = md_is_secure(md)? m_alloc_secure( nframe ) : m_alloc( nframe ); + frame = gcry_md_is_secure (md)? xmalloc_secure (nframe): xmalloc (nframe); n = 0; frame[n++] = 0; frame[n++] = v3compathack? algo : 1; /* block type */ @@ -168,13 +179,11 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, memset( frame+n, 0xff, i ); n += i; frame[n++] = 0; memcpy( frame+n, asn, asnlen ); n += asnlen; - memcpy( frame+n, md_read(md, algo), len ); n += len; + memcpy( frame+n, gcry_md_read (md, algo), len ); n += len; assert( n == nframe ); - a = md_is_secure(md)? - mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ) - : mpi_alloc( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); - mpi_set_buffer( a, frame, nframe, 0 ); - m_free(frame); + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe )) + BUG(); + xfree (frame); return a; } @@ -185,33 +194,40 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, * which did put the algo identifier inseatd of the block type 1 into * the encoded value. Setting this flag forces the old behaviour. */ -MPI -encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, - unsigned nbits, int v3compathack ) +gcry_mpi_t +encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo, + unsigned int nbits, int v3compathack ) { - int algo = hash_algo? hash_algo : md_get_algo(md); - const byte *asn; - size_t asnlen, mdlen; - MPI frame; - - if( pubkey_algo == PUBKEY_ALGO_DSA ) { - mdlen = md_digest_length (hash_algo); - if (mdlen != 20) { - log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); - return NULL; + int algo = hash_algo? hash_algo : gcry_md_get_algo (md); + gcry_mpi_t frame; + + if (pubkey_algo == GCRY_PK_DSA) + { + size_t n = gcry_md_get_algo_dlen(hash_algo); + if (n != 20) + { + log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); + return NULL; } - - frame = md_is_secure(md)? mpi_alloc_secure((md_digest_length(hash_algo) - +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ) - : mpi_alloc((md_digest_length(hash_algo) - +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); - mpi_set_buffer( frame, md_read(md, hash_algo), - md_digest_length(hash_algo), 0 ); + if (gcry_mpi_scan( &frame, GCRYMPI_FMT_USG, + gcry_md_read (md, hash_algo), &n ) ) + BUG(); } - else { - asn = md_asn_oid( algo, &asnlen, &mdlen ); - frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen, v3compathack); + else + { + byte *asn; + size_t asnlen; + + if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen ) ) + log_fatal("can't get OID of algo %d: %s\n", + algo, gcry_strerror(-1)); + asn = xmalloc (asnlen); + if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) ) + BUG(); + frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ), + nbits, asn, asnlen, v3compathack ); + xfree (asn); } - return frame; + return frame; } diff --git a/g10/sig-check.c b/g10/sig-check.c index c99187928..ae5c32eaf 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -1,5 +1,6 @@ /* sig-check.c - Check a signature - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,6 +24,8 @@ #include <stdlib.h> #include <string.h> #include <assert.h> + +#include "gpg.h" #include "util.h" #include "packet.h" #include "memory.h" @@ -33,6 +36,7 @@ #include "status.h" #include "i18n.h" #include "options.h" +#include "pkglue.h" struct cmp_help_context_s { PKT_signature *sig; @@ -59,7 +63,7 @@ int signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, int *r_expired ) { - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + PKT_public_key *pk = xcalloc (1, sizeof *pk ); int rc=0; *r_expiredate = 0; @@ -69,14 +73,14 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, not match the actual sig, and also if the clearsign "Hash:" header is missing or does not match the actual sig. */ - if(!md_algo_present(digest,sig->digest_algo)) { + if(!gcry_md_is_enabled (digest,sig->digest_algo)) { log_info(_("WARNING: signature digest conflict in message\n")); - rc=G10ERR_GENERAL; + rc=GPG_ERR_GENERAL; } else if( get_pubkey( pk, sig->keyid ) ) - rc = G10ERR_NO_PUBKEY; + rc = GPG_ERR_NO_PUBKEY; else if(!pk->is_valid && !pk->is_primary) - rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an + rc=GPG_ERR_BAD_PUBKEY; /* you cannot have a good sig from an invalid subkey */ else { *r_expiredate = pk->expiredate; @@ -93,116 +97,43 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, * not possible to sign more than one identical document within * one second. Some remote batch processing applications might * like this feature here */ - MD_HANDLE md; + gcry_md_hd_t md; u32 a = sig->timestamp; int i, nsig = pubkey_get_nsig( sig->pubkey_algo ); byte *p, *buffer; - md = md_open( DIGEST_ALGO_RMD160, 0); - md_putc( digest, sig->pubkey_algo ); - md_putc( digest, sig->digest_algo ); - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); + gcry_md_open (&md, GCRY_MD_RMD160, 0); + gcry_md_putc( digest, sig->pubkey_algo ); + gcry_md_putc( digest, sig->digest_algo ); + gcry_md_putc( digest, (a >> 24) & 0xff ); + gcry_md_putc( digest, (a >> 16) & 0xff ); + gcry_md_putc( digest, (a >> 8) & 0xff ); + gcry_md_putc( digest, a & 0xff ); for(i=0; i < nsig; i++ ) { - unsigned n = mpi_get_nbits( sig->data[i]); - - md_putc( md, n>>8); - md_putc( md, n ); - p = mpi_get_buffer( sig->data[i], &n, NULL ); - md_write( md, p, n ); - m_free(p); + size_t n; + void *tmp; + + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &tmp, &n, sig->data[i])) + BUG(); + + gcry_md_write (md, tmp, n); + xfree (tmp); } - md_final( md ); - p = make_radix64_string( md_read( md, 0 ), 20 ); - buffer = m_alloc( strlen(p) + 60 ); + gcry_md_final( md ); + p = make_radix64_string( gcry_md_read( md, 0 ), 20 ); + buffer = xmalloc ( strlen(p) + 60 ); sprintf( buffer, "%s %s %lu", p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp ); write_status_text( STATUS_SIG_ID, buffer ); - m_free(buffer); - m_free(p); - md_close(md); + xfree (buffer); + xfree (p); + gcry_md_close(md); } return rc; } -/**************** - * This function gets called by pubkey_verify() if the algorithm needs it. - */ -static int -cmp_help( void *opaque, MPI result ) -{ -#if 0 /* we do not use this anymore */ - int rc=0, i, j, c, old_enc; - byte *dp; - const byte *asn; - size_t mdlen, asnlen; - struct cmp_help_context_s *ctx = opaque; - PKT_signature *sig = ctx->sig; - MD_HANDLE digest = ctx->md; - - old_enc = 0; - for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) { - if( !j ) { - if( !i && c != 1 ) - break; - else if( i && c == 0xff ) - ; /* skip the padding */ - else if( i && !c ) - j++; - else - break; - } - else if( ++j == 18 && c != 1 ) - break; - else if( j == 19 && c == 0 ) { - old_enc++; - break; - } - } - if( old_enc ) { - log_error("old encoding scheme is not supported\n"); - return G10ERR_GENERAL; - } - - if( (rc=check_digest_algo(sig->digest_algo)) ) - return rc; /* unsupported algo */ - asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen ); - - for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0; - i++, j-- ) - if( asn[j] != c ) - break; - if( j != -1 || mpi_getbyte(result, i) ) - return G10ERR_BAD_PUBKEY; /* ASN is wrong */ - for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) - if( c != 0xff ) - break; - i++; - if( c != sig->digest_algo || mpi_getbyte(result, i) ) { - /* Padding or leading bytes in signature is wrong */ - return G10ERR_BAD_PUBKEY; - } - if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0] - || mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) { - /* Wrong key used to check the signature */ - return G10ERR_BAD_PUBKEY; - } - - dp = md_read( digest, sig->digest_algo ); - for(i=mdlen-1; i >= 0; i--, dp++ ) { - if( mpi_getbyte( result, i ) != *dp ) - return G10ERR_BAD_SIGN; - } - return 0; -#else - return -1; -#endif -} - static int do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) { @@ -213,7 +144,7 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) log_info(_("key %08lX: this is a PGP generated " "ElGamal key which is NOT secure for signatures!\n"), (ulong)keyid_from_pk(pk,NULL)); - return G10ERR_PUBKEY_ALGO; + return GPG_ERR_PUBKEY_ALGO; } if( pk->timestamp > sig->timestamp ) { @@ -223,7 +154,7 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) : _("public key %08lX is %lu seconds newer than the signature\n"), (ulong)keyid_from_pk(pk,NULL),d ); if( !opt.ignore_time_conflict ) - return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */ + return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature */ } cur_time = make_timestamp(); @@ -235,7 +166,7 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) "in future (time warp or clock problem)\n"), (ulong)keyid_from_pk(pk,NULL),d ); if( !opt.ignore_time_conflict ) - return G10ERR_TIME_CONFLICT; + return GPG_ERR_TIME_CONFLICT; } if( pk->expiredate && pk->expiredate < cur_time ) { @@ -262,48 +193,49 @@ static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, int *r_expired ) { - MPI result = NULL; + gcry_mpi_t result = NULL; int rc=0; struct cmp_help_context_s ctx; if( (rc=do_check_messages(pk,sig,r_expired)) ) return rc; - if( (rc=check_digest_algo(sig->digest_algo)) ) + if( (rc=gcry_md_test_algo(sig->digest_algo)) ) return rc; - if( (rc=check_pubkey_algo(sig->pubkey_algo)) ) + if( (rc=gcry_pk_test_algo(sig->pubkey_algo)) ) return rc; - /* make sure the digest algo is enabled (in case of a detached signature)*/ - md_enable( digest, sig->digest_algo ); + /* make sure the digest algo is enabled (in case of a detached + signature)*/ + gcry_md_enable( digest, sig->digest_algo ); /* complete the digest */ if( sig->version >= 4 ) - md_putc( digest, sig->version ); - md_putc( digest, sig->sig_class ); + gcry_md_putc( digest, sig->version ); + gcry_md_putc( digest, sig->sig_class ); if( sig->version < 4 ) { u32 a = sig->timestamp; - md_putc( digest, (a >> 24) & 0xff ); - md_putc( digest, (a >> 16) & 0xff ); - md_putc( digest, (a >> 8) & 0xff ); - md_putc( digest, a & 0xff ); + gcry_md_putc( digest, (a >> 24) & 0xff ); + gcry_md_putc( digest, (a >> 16) & 0xff ); + gcry_md_putc( digest, (a >> 8) & 0xff ); + gcry_md_putc( digest, a & 0xff ); } else { byte buf[6]; size_t n; - md_putc( digest, sig->pubkey_algo ); - md_putc( digest, sig->digest_algo ); + gcry_md_putc( digest, sig->pubkey_algo ); + gcry_md_putc( digest, sig->digest_algo ); if( sig->hashed ) { n = sig->hashed->len; - md_putc (digest, (n >> 8) ); - md_putc (digest, n ); - md_write (digest, sig->hashed->data, n); + gcry_md_putc (digest, (n >> 8) ); + gcry_md_putc (digest, n ); + gcry_md_write (digest, sig->hashed->data, n); n += 6; } else { /* Two octets for the (empty) length of the hashed section. */ - md_putc (digest, 0); - md_putc (digest, 0); + gcry_md_putc (digest, 0); + gcry_md_putc (digest, 0); n = 6; } /* add some magic */ @@ -313,38 +245,39 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, buf[3] = n >> 16; buf[4] = n >> 8; buf[5] = n; - md_write( digest, buf, 6 ); + gcry_md_write( digest, buf, 6 ); } - md_final( digest ); + gcry_md_final (digest); result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, mpi_get_nbits(pk->pkey[0]), 0 ); if (!result) - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; ctx.sig = sig; ctx.md = digest; - rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, - cmp_help, &ctx ); - mpi_free( result ); + rc = pk_verify ( pk->pubkey_algo, result, sig->data, pk->pkey); + gcry_mpi_release ( result ); if( (opt.emulate_bugs & EMUBUG_MDENCODE) - && rc == G10ERR_BAD_SIGN && is_ELGAMAL(pk->pubkey_algo) ) { + && gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE + && is_ELGAMAL(pk->pubkey_algo) ) { /* In this case we try again because old GnuPG versions didn't encode * the hash right. There is no problem with DSA however */ result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, mpi_get_nbits(pk->pkey[0]), (sig->version < 5) ); if (!result) - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; else { ctx.sig = sig; ctx.md = digest; - rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey, - cmp_help, &ctx ); + rc = pk_verify (pk->pubkey_algo, result, sig->data, pk->pkey); } } if( !rc && sig->flags.unknown_critical ) { - log_info(_("assuming bad signature from key %08lX due to an unknown critical bit\n"),(ulong)keyid_from_pk(pk,NULL)); - rc = G10ERR_BAD_SIGN; + log_info(_("assuming bad signature from key %08lX " + "due to an unknown critical bit\n"), + (ulong)keyid_from_pk(pk,NULL)); + rc = gpg_error (GPG_ERR_BAD_SIGNATURE); } return rc; @@ -365,9 +298,9 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) buf[2] = uid->attrib_len >> 16; buf[3] = uid->attrib_len >> 8; buf[4] = uid->attrib_len; - md_write( md, buf, 5 ); + gcry_md_write( md, buf, 5 ); } - md_write( md, uid->attrib_data, uid->attrib_len ); + gcry_md_write( md, uid->attrib_data, uid->attrib_len ); } else { if( sig->version >=4 ) { @@ -377,9 +310,9 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) buf[2] = uid->len >> 16; buf[3] = uid->len >> 8; buf[4] = uid->len; - md_write( md, buf, 5 ); + gcry_md_write( md, buf, 5 ); } - md_write( md, uid->name, uid->len ); + gcry_md_write( md, uid->name, uid->len ); } } @@ -390,7 +323,7 @@ cache_sig_result ( PKT_signature *sig, int result ) sig->flags.checked = 1; sig->flags.valid = 1; } - else if ( result == G10ERR_BAD_SIGN ) { + else if ( gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE ) { sig->flags.checked = 1; sig->flags.valid = 0; } @@ -418,7 +351,7 @@ int check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) { static int busy=0; - int i,rc=G10ERR_GENERAL; + int i,rc=GPG_ERR_GENERAL; assert(IS_KEY_REV(sig)); assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1])); @@ -450,9 +383,9 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1]) { - MD_HANDLE md; + gcry_md_hd_t md; - md=md_open(sig->digest_algo,0); + gcry_md_open (&md, sig->digest_algo,0); hash_public_key(md,pk); rc=signature_check(sig,md); cache_sig_result(sig,rc); @@ -513,12 +446,12 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, } if((rc=do_check_messages(pk,sig,r_expired))) return rc; - return sig->flags.valid? 0 : G10ERR_BAD_SIGN; + return sig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE); } } - if( (rc=check_digest_algo(algo)) ) - return rc; + if( (rc=gcry_md_test_algo(algo)) ) + return rc; if( sig->sig_class == 0x20 ) { /* key revocation */ u32 keyid[2]; @@ -529,30 +462,30 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, rc=check_revocation_keys(pk,sig); else { - md = md_open( algo, 0 ); + gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); rc = do_check( pk, sig, md, r_expired ); cache_sig_result ( sig, rc ); - md_close(md); + gcry_md_close(md); } } else if( sig->sig_class == 0x28 ) { /* subkey revocation */ KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); if( snode ) { - md = md_open( algo, 0 ); + gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); rc = do_check( pk, sig, md, r_expired ); cache_sig_result ( sig, rc ); - md_close(md); + gcry_md_close(md); } else { if (!opt.quiet) log_info (_("key %08lX: no subkey for subkey " "revocation signature\n"), (ulong)keyid_from_pk (pk, NULL)); - rc = G10ERR_SIG_CLASS; + rc = GPG_ERR_SIG_CLASS; } } else if( sig->sig_class == 0x18 ) { /* key binding */ @@ -566,27 +499,27 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) *is_selfsig = 1; } - md = md_open( algo, 0 ); + gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); rc = do_check( pk, sig, md, r_expired ); cache_sig_result ( sig, rc ); - md_close(md); + gcry_md_close(md); } else { if (opt.verbose) log_info(_("key %08lX: no subkey for subkey " "binding signature\n"), (ulong)keyid_from_pk (pk, NULL)); - rc = G10ERR_SIG_CLASS; + rc = GPG_ERR_SIG_CLASS; } } else if( sig->sig_class == 0x1f ) { /* direct key signature */ - md = md_open( algo, 0 ); + gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); rc = do_check( pk, sig, md, r_expired ); cache_sig_result ( sig, rc ); - md_close(md); + gcry_md_close(md); } else { /* all other classes */ KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID ); @@ -595,7 +528,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, u32 keyid[2]; keyid_from_pk( pk, keyid ); - md = md_open( algo, 0 ); + gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_uid_node( unode, md, sig ); if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) @@ -610,14 +543,14 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, rc = signature_check2( sig, md, r_expiredate, r_expired ); cache_sig_result ( sig, rc ); - md_close(md); + gcry_md_close(md); } else { if (!opt.quiet) log_info ("key %08lX: no user ID for key signature packet " "of class %02x\n", (ulong)keyid_from_pk (pk, NULL), sig->sig_class ); - rc = G10ERR_SIG_CLASS; + rc = GPG_ERR_SIG_CLASS; } } diff --git a/g10/sign.c b/g10/sign.c index 73286fcb3..fa9e9ea3f 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -40,7 +40,7 @@ #include "trustdb.h" #include "status.h" #include "i18n.h" - +#include "pkglue.h" #ifdef HAVE_DOSISH_SYSTEM #define LF "\r\n" @@ -103,11 +103,11 @@ mk_notation_and_policy( PKT_signature *sig, { log_error(_("WARNING: unable to %%-expand notation " "(too large). Using unexpanded.\n")); - expanded=m_strdup(s); + expanded=xstrdup (s); } n2 = strlen(expanded); - buf = m_alloc( 8 + n1 + n2 ); + buf = xmalloc ( 8 + n1 + n2 ); buf[0] = 0x80; /* human readable */ buf[1] = buf[2] = buf[3] = 0; buf[4] = n1 >> 8; @@ -119,8 +119,8 @@ mk_notation_and_policy( PKT_signature *sig, build_sig_subpkt( sig, SIGSUBPKT_NOTATION | ((nd->flags & 1)? SIGSUBPKT_FLAG_CRITICAL:0), buf, 8+n1+n2 ); - m_free(expanded); - m_free(buf); + xfree (expanded); + xfree (buf); } if(opt.list_options&LIST_SHOW_NOTATION) @@ -151,14 +151,14 @@ mk_notation_and_policy( PKT_signature *sig, { log_error(_("WARNING: unable to %%-expand policy url " "(too large). Using unexpanded.\n")); - s=m_strdup(string); + s=xstrdup (string); } build_sig_subpkt(sig,SIGSUBPKT_POLICY| ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0), s,strlen(s)); - m_free(s); + xfree (s); } if(opt.list_options&LIST_SHOW_POLICY) @@ -189,13 +189,13 @@ hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid) buf[3] = uid->len >> 8; buf[4] = uid->len; } - md_write( md, buf, 5 ); + gcry_md_write( md, buf, 5 ); } if(uid->attrib_data) - md_write (md, uid->attrib_data, uid->attrib_len ); + gcry_md_write (md, uid->attrib_data, uid->attrib_len ); else - md_write (md, uid->name, uid->len ); + gcry_md_write (md, uid->name, uid->len ); } @@ -206,31 +206,31 @@ static void hash_sigversion_to_magic (MD_HANDLE md, const PKT_signature *sig) { if (sig->version >= 4) - md_putc (md, sig->version); - md_putc (md, sig->sig_class); + gcry_md_putc (md, sig->version); + gcry_md_putc (md, sig->sig_class); if (sig->version < 4) { u32 a = sig->timestamp; - md_putc (md, (a >> 24) & 0xff ); - md_putc (md, (a >> 16) & 0xff ); - md_putc (md, (a >> 8) & 0xff ); - md_putc (md, a & 0xff ); + gcry_md_putc (md, (a >> 24) & 0xff ); + gcry_md_putc (md, (a >> 16) & 0xff ); + gcry_md_putc (md, (a >> 8) & 0xff ); + gcry_md_putc (md, a & 0xff ); } else { byte buf[6]; size_t n; - md_putc (md, sig->pubkey_algo); - md_putc (md, sig->digest_algo); + gcry_md_putc (md, sig->pubkey_algo); + gcry_md_putc (md, sig->digest_algo); if (sig->hashed) { n = sig->hashed->len; - md_putc (md, (n >> 8) ); - md_putc (md, n ); - md_write (md, sig->hashed->data, n ); + gcry_md_putc (md, (n >> 8) ); + gcry_md_putc (md, n ); + gcry_md_write (md, sig->hashed->data, n ); n += 6; } else { - md_putc (md, 0); /* always hash the length of the subpacket*/ - md_putc (md, 0); + gcry_md_putc (md, 0); /* always hash the length of the subpacket*/ + gcry_md_putc (md, 0); n = 6; } /* add some magic */ @@ -240,7 +240,7 @@ hash_sigversion_to_magic (MD_HANDLE md, const PKT_signature *sig) buf[3] = n >> 16; buf[4] = n >> 8; buf[5] = n; - md_write (md, buf, 6); + gcry_md_write (md, buf, 6); } } @@ -249,7 +249,7 @@ static int do_sign( PKT_secret_key *sk, PKT_signature *sig, MD_HANDLE md, int digest_algo ) { - MPI frame; + gcry_mpi_t frame; byte *dp; int rc; @@ -260,61 +260,60 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, : _("key has been created %lu seconds " "in future (time warp or clock problem)\n"), d ); if( !opt.ignore_time_conflict ) - return G10ERR_TIME_CONFLICT; + return GPG_ERR_TIME_CONFLICT; } print_pubkey_algo_note(sk->pubkey_algo); if( !digest_algo ) - digest_algo = md_get_algo(md); + digest_algo = gcry_md_get_algo(md); print_digest_algo_note( digest_algo ); - dp = md_read( md, digest_algo ); + dp = gcry_md_read ( md, digest_algo ); sig->digest_algo = digest_algo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; frame = encode_md_value( sk->pubkey_algo, md, digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); if (!frame) - return G10ERR_GENERAL; - rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); - mpi_free(frame); + return GPG_ERR_GENERAL; + rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); + gcry_mpi_release (frame); if (!rc && !opt.no_sig_create_check) { /* check that the signature verification worked and nothing is * fooling us e.g. by a bug in the signature create * code or by deliberately introduced faults. */ - PKT_public_key *pk = m_alloc_clear (sizeof *pk); + PKT_public_key *pk = xcalloc (1,sizeof *pk); if( get_pubkey( pk, sig->keyid ) ) - rc = G10ERR_NO_PUBKEY; + rc = GPG_ERR_NO_PUBKEY; else { frame = encode_md_value (pk->pubkey_algo, md, sig->digest_algo, mpi_get_nbits(pk->pkey[0]), 0); if (!frame) - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; else - rc = pubkey_verify (pk->pubkey_algo, frame, - sig->data, pk->pkey, - NULL, NULL ); - mpi_free (frame); + rc = pk_verify (pk->pubkey_algo, frame, + sig->data, pk->pkey); + gcry_mpi_release (frame); } if (rc) log_error (_("checking created signature failed: %s\n"), - g10_errstr (rc)); + gpg_strerror (rc)); free_public_key (pk); } if( rc ) - log_error(_("signing failed: %s\n"), g10_errstr(rc) ); + log_error(_("signing failed: %s\n"), gpg_strerror (rc) ); else { if( opt.verbose ) { char *ustr = get_user_id_string_printable (sig->keyid); log_info(_("%s/%s signature from: \"%s\"\n"), - pubkey_algo_to_string(sk->pubkey_algo), - digest_algo_to_string(sig->digest_algo), + gcry_pk_algo_name (sk->pubkey_algo), + gcry_md_algo_name (sig->digest_algo), ustr ); - m_free(ustr); + xfree (ustr); } } return rc; @@ -354,7 +353,7 @@ hash_for(int pubkey_algo, int packet_version ) prefitem_t *prefs; for(prefs=opt.personal_digest_prefs;prefs->type;prefs++) - if(md_digest_length(prefs->value)==20) + if(gcry_md_get_algo_dlen (prefs->value) == 20) return prefs->value; } @@ -415,7 +414,7 @@ print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what ) * packet here in reverse order */ static int -write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) +write_onepass_sig_packets (SK_LIST sk_list, iobuf_t out, int sigclass ) { int skcount; SK_LIST sk_rover; @@ -435,7 +434,7 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) } sk = sk_rover->sk; - ops = m_alloc_clear (sizeof *ops); + ops = xcalloc (1,sizeof *ops); ops->sig_class = sigclass; ops->digest_algo = hash_for (sk->pubkey_algo, sk->version); ops->pubkey_algo = sk->pubkey_algo; @@ -449,7 +448,7 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) free_packet (&pkt); if (rc) { log_error ("build onepass_sig packet failed: %s\n", - g10_errstr(rc)); + gpg_strerror (rc)); return rc; } } @@ -461,7 +460,7 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) * Helper to write the plaintext (literal data) packet */ static int -write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) +write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) { PKT_plaintext *pt = NULL; u32 filesize; @@ -470,15 +469,15 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) if (!opt.no_literal) { if (fname || opt.set_filename) { char *s = make_basename (opt.set_filename? opt.set_filename - : fname, - iobuf_get_real_fname(inp)); - pt = m_alloc (sizeof *pt + strlen(s) - 1); + : fname + /*, iobuf_get_real_fname(inp)*/); + pt = xmalloc (sizeof *pt + strlen(s) - 1); pt->namelen = strlen (s); memcpy (pt->name, s, pt->namelen); - m_free (s); + xfree (s); } else { /* no filename */ - pt = m_alloc (sizeof *pt - 1); + pt = xmalloc (sizeof *pt - 1); pt->namelen = 0; } } @@ -519,7 +518,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ if( (rc = build_packet (out, &pkt)) ) log_error ("build_packet(PLAINTEXT) failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); pt->buf = NULL; } else { @@ -527,10 +526,9 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; + if ( (rc=iobuf_write(out, copy_buffer, bytes_copied) )) { log_error ("copying input to output failed: %s\n", - g10_errstr(rc)); + gpg_strerror (rc)); break; } wipememory(copy_buffer,4096); /* burn buffer */ @@ -545,7 +543,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) * hash which will not be changes here. */ static int -write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, +write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, int sigclass, u32 timestamp, u32 duration, int status_letter) { @@ -561,7 +559,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, sk = sk_rover->sk; /* build the signature packet */ - sig = m_alloc_clear (sizeof *sig); + sig = xcalloc (1,sizeof *sig); if(opt.force_v3_sigs || RFC1991) sig->version=3; else if(duration || opt.sig_policy_url || opt.sig_notation_data) @@ -579,17 +577,17 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, sig->expiredate = sig->timestamp+duration; sig->sig_class = sigclass; - md = md_copy (hash); + gcry_md_copy (&md, hash); if (sig->version >= 4) build_sig_subpkt_from_sig (sig); mk_notation_and_policy (sig, NULL, sk); hash_sigversion_to_magic (md, sig); - md_final (md); + gcry_md_final (md); rc = do_sign( sk, sig, md, hash_for (sig->pubkey_algo, sk->version) ); - md_close (md); + gcry_md_close (md); if( !rc ) { /* and write it */ PACKET pkt; @@ -604,7 +602,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, free_packet (&pkt); if (rc) log_error ("build signature packet failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); } if( rc ) return rc;; @@ -636,7 +634,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, text_filter_context_t tfx; progress_filter_context_t pfx; encrypt_filter_context_t efx; - IOBUF inp = NULL, out = NULL; + iobuf_t inp = NULL, out = NULL; PACKET pkt; int rc = 0; PK_LIST pk_list = NULL; @@ -682,9 +680,9 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, inp = NULL; /* we do it later */ else { if( !(inp = iobuf_open(fname)) ) { + rc = gpg_error_from_errno (errno); log_error("can't open %s: %s\n", fname? fname: "[stdin]", strerror(errno) ); - rc = G10ERR_OPEN_FILE; goto leave; } @@ -693,8 +691,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( outfile ) { if( !(out = iobuf_create( outfile )) ) { + rc = gpg_error_from_errno (errno); log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); - rc = G10ERR_CREATE_FILE; goto leave; } else if( opt.verbose ) @@ -710,7 +708,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, iobuf_push_filter( inp, text_filter, &tfx ); } - mfx.md = md_open(0, 0); + gcry_md_open (&mfx.md, 0, 0); /* If we're encrypting and signing, it is reasonable to pick the hash algorithm to use out of the recepient key prefs. */ @@ -724,7 +722,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, NULL)!=opt.def_digest_algo) log_info(_("forcing digest algorithm %s (%d) " "violates recipient preferences\n"), - digest_algo_to_string(opt.def_digest_algo), + gcry_md_algo_name (opt.def_digest_algo), opt.def_digest_algo); } else @@ -752,7 +750,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - md_enable(mfx.md, hash_for(sk->pubkey_algo, sk->version )); + gcry_md_enable (mfx.md, hash_for(sk->pubkey_algo, sk->version )); } if( !multifile ) @@ -822,9 +820,9 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, for( sl = strlist_last(filenames); sl; sl = strlist_prev( filenames, sl ) ) { if( !(inp = iobuf_open(sl->d)) ) { + rc = gpg_error_from_errno (errno); log_error(_("can't open %s: %s\n"), sl->d, strerror(errno) ); - rc = G10ERR_OPEN_FILE; goto leave; } handle_progress (&pfx, inp, sl->d); @@ -875,7 +873,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, write_status( STATUS_END_ENCRYPTION ); } iobuf_close(inp); - md_close( mfx.md ); + gcry_md_close ( mfx.md ); release_sk_list( sk_list ); release_pk_list( pk_list ); recipient_digest_algo=0; @@ -893,7 +891,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) armor_filter_context_t afx; progress_filter_context_t pfx; MD_HANDLE textmd = NULL; - IOBUF inp = NULL, out = NULL; + iobuf_t inp = NULL, out = NULL; PACKET pkt; int rc = 0; SK_LIST sk_list = NULL; @@ -923,17 +921,17 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) /* 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) ); - rc = G10ERR_OPEN_FILE; goto leave; } handle_progress (&pfx, inp, fname); if( outfile ) { if( !(out = iobuf_create( outfile )) ) { + rc = gpg_error_from_errno (errno); log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); - rc = G10ERR_CREATE_FILE; goto leave; } else if( opt.verbose ) @@ -966,7 +964,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) int i = hash_for(sk->pubkey_algo, sk->version); if( !hashs_seen[ i & 0xff ] ) { - s = digest_algo_to_string( i ); + s = gcry_md_algo_name (i); if( s ) { hashs_seen[ i & 0xff ] = 1; if( any ) @@ -985,13 +983,13 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) "NotDashEscaped: You need GnuPG to verify this message" LF ); iobuf_writestr(out, LF ); - textmd = md_open(0, 0); + gcry_md_open (&textmd, 0, 0); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - md_enable(textmd, hash_for(sk->pubkey_algo, sk->version)); + gcry_md_enable (textmd, hash_for(sk->pubkey_algo, sk->version)); } if ( DBG_HASHING ) - md_start_debug( textmd, "clearsign" ); + gcry_md_start_debug ( textmd, "clearsign" ); copy_clearsig_text( out, inp, textmd, !opt.not_dash_escaped, opt.escape_from, (old_style && only_md5) ); /* fixme: check for read errors */ @@ -1011,7 +1009,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) else iobuf_close(out); iobuf_close(inp); - md_close( textmd ); + gcry_md_close ( textmd ); release_sk_list( sk_list ); return rc; } @@ -1029,7 +1027,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) md_filter_context_t mfx; text_filter_context_t tfx; cipher_filter_context_t cfx; - IOBUF inp = NULL, out = NULL; + iobuf_t inp = NULL, out = NULL; PACKET pkt; STRING2KEY *s2k = NULL; int rc = 0; @@ -1055,27 +1053,27 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* prepare iobufs */ inp = iobuf_open(fname); if( !inp ) { + rc = gpg_error_from_errno (errno); log_error("can't open %s: %s\n", fname? fname: "[stdin]", strerror(errno) ); - rc = G10ERR_OPEN_FILE; goto leave; } handle_progress (&pfx, inp, fname); /* prepare key */ - s2k = m_alloc_clear( sizeof *s2k ); + s2k = xcalloc (1, sizeof *s2k ); s2k->mode = RFC1991? 0:opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; algo = default_cipher_algo(); if (!opt.quiet || !opt.batch) log_info (_("%s encryption will be used\n"), - cipher_algo_to_string(algo) ); + gcry_cipher_algo_name (algo) ); cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, NULL); if (!cfx.dek || !cfx.dek->keylen) { - rc = G10ERR_PASSPHRASE; - log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); + rc = gpg_error (GPG_ERR_INV_PASSPHRASE); + log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -1087,11 +1085,11 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* prepare to calculate the MD over the input */ if (opt.textmode) iobuf_push_filter (inp, text_filter, &tfx); - mfx.md = md_open(0, 0); + gcry_md_open (&mfx.md, 0, 0); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { PKT_secret_key *sk = sk_rover->sk; - md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version )); + gcry_md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version )); } iobuf_push_filter (inp, md_filter, &mfx); @@ -1103,15 +1101,15 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* Write the symmetric key packet */ /*(current filters: armor)*/ if (!RFC1991) { - PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); + PKT_symkey_enc *enc = xcalloc (1, sizeof *enc ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; enc->s2k = *s2k; pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if( (rc = build_packet( out, &pkt )) ) - log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); - m_free(enc); + log_error("build symkey packet failed: %s\n", gpg_strerror (rc) ); + xfree (enc); } /* Push the encryption filter */ @@ -1157,9 +1155,9 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) } iobuf_close(inp); release_sk_list( sk_list ); - md_close( mfx.md ); - m_free(cfx.dek); - m_free(s2k); + gcry_md_close ( mfx.md ); + xfree (cfx.dek); + xfree (s2k); return rc; } @@ -1224,7 +1222,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, digest_algo = DIGEST_ALGO_SHA1; } - md = md_open( digest_algo, 0 ); + gcry_md_open (&md, digest_algo, 0 ); /* hash the public key certificate and the user id */ hash_public_key( md, pk ); @@ -1235,7 +1233,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, hash_uid (md, sigversion, uid); } /* and make the signature packet */ - sig = m_alloc_clear( sizeof *sig ); + sig = xcalloc (1, sizeof *sig ); sig->version = sigversion; sig->flags.exportable=1; sig->flags.revocable=1; @@ -1261,12 +1259,12 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, if( !rc ) { hash_sigversion_to_magic (md, sig); - md_final(md); + gcry_md_final (md); rc = complete_sig( sig, sk, md ); } - md_close( md ); + gcry_md_close ( md ); if( rc ) free_seckey_enc( sig ); else @@ -1299,9 +1297,9 @@ update_keysig_packet( PKT_signature **ret_sig, if ((!orig_sig || !pk || !sk) || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) || (orig_sig->sig_class == 0x18 && !subpk)) - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; - md = md_open( orig_sig->digest_algo, 0 ); + gcry_md_open (&md, orig_sig->digest_algo, 0); /* hash the public key certificate and the user id */ hash_public_key( md, pk ); @@ -1344,12 +1342,12 @@ update_keysig_packet( PKT_signature **ret_sig, if (!rc) { hash_sigversion_to_magic (md, sig); - md_final(md); + gcry_md_final (md); rc = complete_sig( sig, sk, md ); } - md_close (md); + gcry_md_close (md); if( rc ) free_seckey_enc (sig); else diff --git a/g10/signal.c b/g10/signal.c index 1028ab705..90c0841d8 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -88,17 +88,17 @@ got_fatal_signal( int sig ) raise( sig ); caught_fatal_sig = 1; - secmem_term(); + gcry_control (GCRYCTL_TERM_SECMEM ); /* better don't transtale these messages */ write(2, "\n", 1 ); - s = log_get_name(); if( s ) write(2, s, strlen(s) ); + s = "?" /* FIXME: log_get_name()*/; 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); - remove_lockfiles (); + dotlock_remove_lockfiles (); #ifdef __riscos__ riscos_close_fds (); #endif /* __riscos__ */ diff --git a/g10/skclist.c b/g10/skclist.c index 1f7a3919a..67d9eb2f9 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -43,41 +43,11 @@ release_sk_list( SK_LIST sk_list ) for( ; sk_list; sk_list = sk_rover ) { sk_rover = sk_list->next; free_secret_key( sk_list->sk ); - m_free( sk_list ); + xfree ( sk_list ); } } -/* Check that we are only using keys which don't have - * the string "(insecure!)" or "not secure" or "do not use" - * in one of the user ids - */ -static int -is_insecure( PKT_secret_key *sk ) -{ - u32 keyid[2]; - KBNODE node = NULL, u; - int insecure = 0; - - keyid_from_sk( sk, keyid ); - node = get_pubkeyblock( keyid ); - for ( u = node; u; u = u->next ) { - if ( u->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *id = u->pkt->pkt.user_id; - if ( id->attrib_data ) - continue; /* skip attribute packets */ - if ( strstr( id->name, "(insecure!)" ) - || strstr( id->name, "not secure" ) - || strstr( id->name, "do not use" ) ) { - insecure = 1; - break; - } - } - } - release_kbnode( node ); - - return insecure; -} static int key_present_in_sk_list(SK_LIST sk_list, PKT_secret_key *sk) @@ -110,13 +80,13 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, if( !locusr ) { /* use the default one */ PKT_secret_key *sk; - sk = m_alloc_clear( sizeof *sk ); + sk = xcalloc (1, sizeof *sk ); sk->req_usage = use; if( (rc = get_seckey_byname( sk, NULL, unlock )) ) { free_secret_key( sk ); sk = NULL; - log_error("no default secret key: %s\n", g10_errstr(rc) ); + log_error("no default secret key: %s\n", gpg_strerror (rc) ); } - else if( !(rc=check_pubkey_algo2(sk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) { SK_LIST r; if( sk->version == 4 && (use & PUBKEY_USAGE_SIG) @@ -125,13 +95,8 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, "ElGamal key which is NOT secure for signatures!\n"); free_secret_key( sk ); sk = NULL; } - else if( random_is_faked() && !is_insecure( sk ) ) { - log_info(_("key is not flagged as insecure - " - "can't use it with the faked RNG!\n")); - free_secret_key( sk ); sk = NULL; - } else { - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->sk = sk; sk = NULL; r->next = sk_list; r->mark = 0; @@ -140,7 +105,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, } else { free_secret_key( sk ); sk = NULL; - log_error("invalid default secret key: %s\n", g10_errstr(rc) ); + log_error("invalid default secret key: %s\n", gpg_strerror (rc) ); } } else { @@ -157,11 +122,11 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, log_error(_("skipped `%s': duplicated\n"), locusr->d ); continue; } - sk = m_alloc_clear( sizeof *sk ); + sk = xcalloc (1, sizeof *sk ); sk->req_usage = use; if( (rc = get_seckey_byname( sk, locusr->d, 0 )) ) { free_secret_key( sk ); sk = NULL; - log_error(_("skipped `%s': %s\n"), locusr->d, g10_errstr(rc) ); + log_error(_("skipped `%s': %s\n"), locusr->d, gpg_strerror (rc) ); } else if ( key_present_in_sk_list(sk_list, sk) == 0) { free_secret_key(sk); sk = NULL; @@ -169,9 +134,9 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, } else if ( unlock && (rc = check_secret_key( sk, 0 )) ) { free_secret_key( sk ); sk = NULL; - log_error(_("skipped `%s': %s\n"), locusr->d, g10_errstr(rc) ); + log_error(_("skipped `%s': %s\n"), locusr->d, gpg_strerror (rc) ); } - else if( !(rc=check_pubkey_algo2(sk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) { SK_LIST r; if( sk->version == 4 && (use & PUBKEY_USAGE_SIG) @@ -181,13 +146,8 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, locusr->d ); free_secret_key( sk ); sk = NULL; } - else if( random_is_faked() && !is_insecure( sk ) ) { - log_info(_("key is not flagged as insecure - " - "can't use it with the faked RNG!\n")); - free_secret_key( sk ); sk = NULL; - } else { - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->sk = sk; sk = NULL; r->next = sk_list; r->mark = 0; @@ -196,7 +156,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, } else { free_secret_key( sk ); sk = NULL; - log_error("skipped `%s': %s\n", locusr->d, g10_errstr(rc) ); + log_error("skipped `%s': %s\n", locusr->d, gpg_strerror (rc) ); } } } @@ -204,7 +164,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, if( !rc && !sk_list ) { log_error("no valid signators\n"); - rc = G10ERR_NO_USER_ID; + rc = GPG_ERR_NO_USER_ID; } if( rc ) diff --git a/g10/status.c b/g10/status.c index cc30db79b..32e59eef5 100644 --- a/g10/status.c +++ b/g10/status.c @@ -40,6 +40,8 @@ #include <sys/mman.h> #endif #endif + +#include "gpg.h" #include "util.h" #include "status.h" #include "ttyio.h" @@ -179,9 +181,12 @@ set_status_fd ( int fd ) fd, strerror(errno)); } last_fd = fd; +#warning fixme: register progress CBs +#if 0 register_primegen_progress ( progress_cb, "primegen" ); register_pk_dsa_progress ( progress_cb, "pk_dsa" ); register_pk_elg_progress ( progress_cb, "pk_elg" ); +#endif } int @@ -453,7 +458,7 @@ do_shm_get( const char *keyword, int hidden, int bool ) if( bool ) return p[0]? "" : NULL; - string = hidden? m_alloc_secure( n+1 ) : m_alloc( n+1 ); + string = hidden? xmalloc_secure ( n+1 ) : xmalloc ( n+1 ); memcpy(string, p, n ); string[n] = 0; /* make sure it is a string */ if( hidden ) /* invalidate the memory */ @@ -508,7 +513,7 @@ do_get_from_fd( const char *keyword, int hidden, int bool ) if( i >= len-1 ) { char *save = string; len += 100; - string = hidden? m_alloc_secure ( len ) : m_alloc ( len ); + string = hidden? xmalloc_secure ( len ) : xmalloc ( len ); if( save ) memcpy(string, save, i ); else @@ -579,7 +584,7 @@ cpr_get( const char *keyword, const char *prompt ) for(;;) { p = tty_get( prompt ); if( *p=='?' && !p[1] && !(keyword && !*keyword)) { - m_free(p); + xfree (p); display_online_help( keyword ); } else @@ -595,7 +600,7 @@ cpr_get_utf8( const char *keyword, const char *prompt ) p = cpr_get( keyword, prompt ); if( p ) { char *utf8 = native_to_utf8( p ); - m_free( p ); + xfree ( p ); p = utf8; } return p; @@ -615,7 +620,7 @@ cpr_get_hidden( const char *keyword, const char *prompt ) for(;;) { p = tty_get_hidden( prompt ); if( *p == '?' && !p[1] ) { - m_free(p); + xfree (p); display_online_help( keyword ); } else @@ -652,13 +657,13 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt ) p = tty_get( prompt ); trim_spaces(p); /* it is okay to do this here */ if( *p == '?' && !p[1] ) { - m_free(p); + xfree (p); display_online_help( keyword ); } else { tty_kill_prompt(); yes = answer_is_yes(p); - m_free(p); + xfree (p); return yes; } } @@ -680,13 +685,13 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) p = tty_get( prompt ); trim_spaces(p); /* it is okay to do this here */ if( *p == '?' && !p[1] ) { - m_free(p); + xfree (p); display_online_help( keyword ); } else { tty_kill_prompt(); yes = answer_is_yes_no_quit(p); - m_free(p); + xfree (p); return yes; } } diff --git a/g10/tdbdump.c b/g10/tdbdump.c index cd46f1f5a..3f9e8b388 100644 --- a/g10/tdbdump.c +++ b/g10/tdbdump.c @@ -1,5 +1,5 @@ /* tdbdump.c - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +30,7 @@ #include <fcntl.h> #include <unistd.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "keydb.h" @@ -57,7 +58,7 @@ write_record( TRUSTREC *rec ) if( !rc ) return; log_error(_("trust record %lu, type %d: write failed: %s\n"), - rec->recnum, rec->rectype, g10_errstr(rc) ); + rec->recnum, rec->rectype, gpg_strerror (rc) ); tdbio_invalid(); } @@ -137,7 +138,7 @@ import_ownertrust( const char *fname ) is_stdin = 1; } else if( !(fp = fopen( fname, "r" )) ) { - log_error_f(fname, _("can't open file: %s\n"), strerror(errno) ); + log_error ( _("can't open `%s': %s\n"), fname, strerror(errno) ); return; } @@ -148,7 +149,7 @@ import_ownertrust( const char *fname ) continue; n = strlen(line); if( line[n-1] != '\n' ) { - log_error_f(fname, _("line too long\n") ); + log_error (_("\b%s: line too long\n"), fname ); /* ... or last line does not have a LF */ break; /* can't continue */ } @@ -156,16 +157,16 @@ import_ownertrust( const char *fname ) if( !isxdigit(*p) ) break; if( *p != ':' ) { - log_error_f(fname, _("error: missing colon\n") ); + log_error (_("\b%s: error: missing colon\n"), fname ); continue; } fprlen = p - line; if( fprlen != 32 && fprlen != 40 ) { - log_error_f(fname, _("error: invalid fingerprint\n") ); + log_error (_("\b%s: error: invalid fingerprint\n"), fname ); continue; } if( sscanf(p, ":%u:", &otrust ) != 1 ) { - log_error_f(fname, _("error: no ownertrust value\n") ); + log_error (_("\b%s: error: no ownertrust value\n"), fname ); continue; } if( !otrust ) @@ -201,11 +202,11 @@ import_ownertrust( const char *fname ) any = 1; } else /* error */ - log_error_f(fname, _("error finding trust record: %s\n"), - g10_errstr(rc)); + log_error (_("\b%s: error finding trust record: %s\n"), + fname, gpg_strerror (rc)); } if( ferror(fp) ) - log_error_f(fname, _("read error: %s\n"), strerror(errno) ); + log_error (_("\b%s: read error: %s\n"), fname, strerror(errno) ); if( !is_stdin ) fclose(fp); @@ -214,7 +215,7 @@ import_ownertrust( const char *fname ) revalidation_mark (); rc = tdbio_sync (); if (rc) - log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) ); + log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) ); } } diff --git a/g10/tdbio.c b/g10/tdbio.c index bc609adee..d8af2ef8a 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -29,6 +29,7 @@ #include <fcntl.h> #include <unistd.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "memory.h" @@ -123,17 +124,20 @@ static int write_cache_item( CACHE_CTRL r ) { int n; + gpg_error_t rc; if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + rc = gpg_error_from_errno (errno); log_error(_("trustdb rec %lu: lseek failed: %s\n"), r->recno, strerror(errno) ); - return G10ERR_WRITE_FILE; + return rc; } n = write( db_fd, r->data, TRUST_RECORD_LEN); if( n != TRUST_RECORD_LEN ) { + rc = gpg_error_from_errno (errno); log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), r->recno, n, strerror(errno) ); - return G10ERR_WRITE_FILE; + return rc; } r->flags.dirty = 0; return 0; @@ -187,7 +191,7 @@ put_record_into_cache( ulong recno, const char *data ) } /* see whether we reached the limit */ if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */ - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->flags.used = 1; r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); @@ -230,7 +234,7 @@ put_record_into_cache( ulong recno, const char *data ) if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */ if( opt.debug && !(cache_entries % 100) ) log_debug("increasing tdbio cache size\n"); - r = m_alloc( sizeof *r ); + r = xmalloc ( sizeof *r ); r->flags.used = 1; r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); @@ -242,7 +246,7 @@ put_record_into_cache( ulong recno, const char *data ) return 0; } log_info(_("trustdb transaction too large\n")); - return G10ERR_RESOURCE_LIMIT; + return GPG_ERR_RESOURCE_LIMIT; } if( dirty_count ) { int n = dirty_count / 5; /* discard some dirty entries */ @@ -488,13 +492,13 @@ tdbio_set_dbname( const char *new_dbname, int create ) fname = make_filename (opt.homedir, new_dbname, NULL); } else - fname = m_strdup (new_dbname); + fname = xstrdup (new_dbname); if( access( fname, R_OK ) ) { if( errno != ENOENT ) { log_error( _("%s: can't access: %s\n"), fname, strerror(errno) ); - m_free(fname); - return G10ERR_TRUSTDB; + xfree (fname); + return GPG_ERR_TRUSTDB; } if( create ) { FILE *fp; @@ -511,7 +515,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) } *p = DIRSEP_C; - m_free(db_name); + xfree (db_name); db_name = fname; #ifdef __riscos__ if( !lockhandle ) @@ -541,7 +545,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) rc = create_version_record (); if( rc ) log_fatal( _("%s: failed to create version record: %s"), - fname, g10_errstr(rc)); + fname, gpg_strerror (rc)); /* and read again to check that we are okay */ if( tdbio_read_record( 0, &rec, RECTYPE_VER ) ) log_fatal( _("%s: invalid trustdb created\n"), db_name ); @@ -552,7 +556,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) return 0; } } - m_free(db_name); + xfree (db_name); db_name = fname; return 0; } @@ -636,7 +640,7 @@ create_hashtable( TRUSTREC *vr, int type ) rc = tdbio_write_record( &rec ); if( rc ) log_fatal( _("%s: failed to create hashtable: %s\n"), - db_name, g10_errstr(rc)); + db_name, gpg_strerror (rc)); } /* update the version record */ rc = tdbio_write_record( vr ); @@ -644,7 +648,7 @@ create_hashtable( TRUSTREC *vr, int type ) rc = tdbio_sync(); if( rc ) log_fatal( _("%s: error updating version record: %s\n"), - db_name, g10_errstr(rc)); + db_name, gpg_strerror (rc)); } @@ -661,7 +665,7 @@ tdbio_db_matches_options() rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); yes_no = vr.r.ver.marginals == opt.marginals_needed && vr.r.ver.completes == opt.completes_needed @@ -681,7 +685,7 @@ tdbio_read_model(void) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); return vr.r.ver.trust_model; } @@ -697,7 +701,7 @@ tdbio_read_nextcheck () rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); return vr.r.ver.nextcheck; } @@ -711,7 +715,7 @@ tdbio_write_nextcheck (ulong stamp) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); if (vr.r.ver.nextcheck == stamp) return 0; @@ -720,7 +724,7 @@ tdbio_write_nextcheck (ulong stamp) rc = tdbio_write_record( &vr ); if( rc ) log_fatal( _("%s: error writing version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); return 1; } @@ -741,7 +745,7 @@ get_trusthashrec(void) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); if( !vr.r.ver.trusthashtbl ) create_hashtable( &vr, 0 ); @@ -773,7 +777,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { log_error( db_name, "upd_hashtable: read failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } @@ -783,7 +787,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( db_name, "upd_hashtable: write htbl failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } } @@ -792,7 +796,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { log_error( "upd_hashtable: read item failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } @@ -801,7 +805,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) level++; if( level >= keylen ) { log_error( "hashtable has invalid indirections.\n"); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } goto next_level; } @@ -818,7 +822,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) &rec, RECTYPE_HLST); if( rc ) { log_error( "upd_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } } @@ -833,7 +837,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( "upd_hashtable: write hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; /* done */ } } @@ -842,7 +846,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) &rec, RECTYPE_HLST ); if( rc ) { log_error( "upd_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } } @@ -851,7 +855,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( "upd_hashtable: write hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } memset( &rec, 0, sizeof rec ); @@ -861,7 +865,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( "upd_hashtable: write ext hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; /* done */ } } /* end loop over hlst slots */ @@ -879,7 +883,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( "upd_hashtable: write new hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } /* update the hashtable record */ @@ -887,14 +891,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &lastrec ); if( rc ) log_error( "upd_hashtable: update htbl failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; /* ready */ } else { log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n", table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); list_trustdb(NULL); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } } @@ -922,7 +926,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { log_error( db_name, "drop_from_hashtable: read failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } @@ -935,14 +939,14 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { log_error( "drop_from_hashtable: read item failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } @@ -951,7 +955,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) level++; if( level >= keylen ) { log_error( "hashtable has invalid indirections.\n"); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } goto next_level; } @@ -964,7 +968,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } } @@ -973,7 +977,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) &rec, RECTYPE_HLST); if( rc ) { log_error( "drop_from_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } } @@ -984,7 +988,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n", table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } @@ -1010,7 +1014,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL ); if( rc ) { - log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) ); + log_error( db_name, "lookup_hashtable failed: %s\n", gpg_strerror (rc) ); return rc; } @@ -1020,7 +1024,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( item, rec, 0 ); if( rc ) { - log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) ); + log_error( db_name, "hashtable read failed: %s\n", gpg_strerror (rc) ); return rc; } if( rec->rectype == RECTYPE_HTBL ) { @@ -1028,7 +1032,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, level++; if( level >= keylen ) { log_error( db_name, "hashtable has invalid indirections\n"); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } goto next_level; } @@ -1043,7 +1047,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 ); if( rc ) { log_error( "lookup_hashtable: read item failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } if( (*cmpfnc)( cmpdata, &tmp ) ) { @@ -1056,7 +1060,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST ); if( rc ) { log_error( "lookup_hashtable: read hlst failed: %s\n", - g10_errstr(rc) ); + gpg_strerror (rc) ); return rc; } } @@ -1159,17 +1163,19 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) buf = get_record_from_cache( recnum ); if( !buf ) { if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + rc = gpg_error_from_errno (errno); log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return G10ERR_READ_FILE; + return rc; } n = read( db_fd, readbuf, TRUST_RECORD_LEN); if( !n ) { return -1; /* eof */ } else if( n != TRUST_RECORD_LEN ) { + rc = gpg_error_from_errno (errno); log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) ); - return G10ERR_READ_FILE; + return rc; } buf = readbuf; } @@ -1180,7 +1186,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) if( expected && rec->rectype != expected ) { log_error("%lu: read expected rec type %d, got %d\n", recnum, expected, rec->rectype ); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } p++; /* skip reserved byte */ switch( rec->rectype ) { @@ -1189,7 +1195,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) case RECTYPE_VER: /* version record */ if( memcmp(buf+1, "gpg", 3 ) ) { log_error( _("%s: not a trustdb file\n"), db_name ); - rc = G10ERR_TRUSTDB; + rc = GPG_ERR_TRUSTDB; } p += 2; /* skip "gpg" */ rec->r.ver.version = *p++; @@ -1208,12 +1214,12 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) if( recnum ) { log_error( _("%s: version record with recnum %lu\n"), db_name, (ulong)recnum ); - rc = G10ERR_TRUSTDB; + rc = GPG_ERR_TRUSTDB; } else if( rec->r.ver.version != 3 ) { log_error( _("%s: invalid file version %d\n"), db_name, rec->r.ver.version ); - rc = G10ERR_TRUSTDB; + rc = GPG_ERR_TRUSTDB; } break; case RECTYPE_FREE: @@ -1248,7 +1254,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) default: log_error( "%s: invalid record type %d at recnum %lu\n", db_name, rec->rectype, (ulong)recnum ); - rc = G10ERR_TRUSTDB; + rc = GPG_ERR_TRUSTDB; break; } @@ -1364,7 +1370,7 @@ tdbio_delete_record( ulong recnum ) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); rec.recnum = recnum; rec.rectype = RECTYPE_FREE; @@ -1391,13 +1397,13 @@ tdbio_new_recnum() rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); if( vr.r.ver.firstfree ) { recnum = vr.r.ver.firstfree; rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE ); if( rc ) { log_error( _("%s: error reading free record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); return rc; } /* update dir record */ @@ -1405,7 +1411,7 @@ tdbio_new_recnum() rc = tdbio_write_record( &vr ); if( rc ) { log_error( _("%s: error writing dir record: %s\n"), - db_name, g10_errstr(rc) ); + db_name, gpg_strerror (rc) ); return rc; } /*zero out the new record */ @@ -1415,7 +1421,7 @@ tdbio_new_recnum() rc = tdbio_write_record( &rec ); if( rc ) log_fatal(_("%s: failed to zero a record: %s\n"), - db_name, g10_errstr(rc)); + db_name, gpg_strerror (rc)); } else { /* not found, append a new record */ offset = lseek( db_fd, 0, SEEK_END ); @@ -1430,22 +1436,22 @@ tdbio_new_recnum() rec.recnum = recnum; rc = 0; if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + rc = gpg_error_from_errno (errno); log_error(_("trustdb rec %lu: lseek failed: %s\n"), recnum, strerror(errno) ); - rc = G10ERR_WRITE_FILE; } else { int n = write( db_fd, &rec, TRUST_RECORD_LEN); if( n != TRUST_RECORD_LEN ) { + rc = gpg_error_from_errno (errno); log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), recnum, n, strerror(errno) ); - rc = G10ERR_WRITE_FILE; } } if( rc ) log_fatal(_("%s: failed to append a record: %s\n"), - db_name, g10_errstr(rc)); + db_name, gpg_strerror (rc)); } return recnum ; } @@ -1516,7 +1522,7 @@ migrate_from_v2 () int rc, count; ottable_size = 5; - ottable = m_alloc (ottable_size * sizeof *ottable); + ottable = xmalloc (ottable_size * sizeof *ottable); ottable_used = 0; /* We have some restrictions here. We can't use the version record @@ -1546,7 +1552,7 @@ migrate_from_v2 () if (ottable_used == ottable_size) { ottable_size += 1000; - ottable = m_realloc (ottable, ottable_size * sizeof *ottable); + ottable = xrealloc (ottable, ottable_size * sizeof *ottable); } ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); ottable[ottable_used].ot = oldbuf[18]; @@ -1617,8 +1623,5 @@ migrate_from_v2 () if (rc) log_fatal ("failed to sync `%s'\n", db_name); log_info ("migrated %d version 2 ownertrusts\n", count); - m_free (ottable); + xfree (ottable); } - - - diff --git a/g10/textfilter.c b/g10/textfilter.c index 6f3fe1bbf..a3ea4b138 100644 --- a/g10/textfilter.c +++ b/g10/textfilter.c @@ -25,6 +25,7 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "memory.h" @@ -71,7 +72,7 @@ len_without_trailing_ws( byte *line, unsigned len ) static int -standard( text_filter_context_t *tfx, IOBUF a, +standard( text_filter_context_t *tfx, iobuf_t a, byte *buf, size_t size, size_t *ret_len) { int rc=0; @@ -120,7 +121,7 @@ standard( text_filter_context_t *tfx, IOBUF a, */ int text_filter( void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len) + iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; text_filter_context_t *tfx = opaque; @@ -133,7 +134,7 @@ text_filter( void *opaque, int control, if( tfx->truncated ) log_error(_("can't handle text lines longer than %d characters\n"), MAX_LINELEN ); - m_free( tfx->buffer ); + xfree ( tfx->buffer ); tfx->buffer = NULL; } else if( control == IOBUFCTRL_DESC ) @@ -147,7 +148,7 @@ text_filter( void *opaque, int control, * md is updated as required by rfc2440 */ int -copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, +copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md, int escape_dash, int escape_from, int pgp2mode ) { unsigned maxlen; @@ -175,15 +176,15 @@ copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, /* update the message digest */ if( escape_dash ) { if( pending_lf ) { - md_putc( md, '\r' ); - md_putc( md, '\n' ); + gcry_md_putc( md, '\r' ); + gcry_md_putc( md, '\n' ); } - md_write( md, buffer, + gcry_md_write( md, buffer, len_without_trailing_chars( buffer, n, pgp2mode? " \r\n":" \t\r\n")); } else - md_write( md, buffer, n ); + gcry_md_write( md, buffer, n ); pending_lf = buffer[n-1] == '\n'; /* write the output */ @@ -224,7 +225,7 @@ copy_clearsig_text( IOBUF out, IOBUF inp, MD_HANDLE md, if( !pending_lf ) { /* make sure that the file ends with a LF */ iobuf_writestr( out, LF ); if( !escape_dash ) - md_putc( md, '\n' ); + gcry_md_putc( md, '\n' ); } if( truncated ) diff --git a/g10/trustdb.c b/g10/trustdb.c index 457d83b9d..16bd96e49 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -34,6 +34,7 @@ #endif #endif /* !DISABLE_REGEX */ +#include "gpg.h" #include "errors.h" #include "iobuf.h" #include "keydb.h" @@ -98,7 +99,7 @@ new_key_item (void) { struct key_item *k; - k = m_alloc_clear (sizeof *k); + k = xcalloc (1,sizeof *k); return k; } @@ -110,8 +111,8 @@ release_key_items (struct key_item *k) for (; k; k = k2) { k2 = k->next; - m_free (k->trust_regexp); - m_free (k); + xfree (k->trust_regexp); + xfree (k); } } @@ -128,7 +129,7 @@ new_key_hash_table (void) { struct key_item **tbl; - tbl = m_alloc_clear (1024 * sizeof *tbl); + tbl = xcalloc (1,1024 * sizeof *tbl); return tbl; } @@ -141,7 +142,7 @@ release_key_hash_table (KeyHashTable tbl) return; for (i=0; i < 1024; i++) release_key_items (tbl[i]); - m_free (tbl); + xfree (tbl); } /* @@ -188,7 +189,7 @@ release_key_array ( struct key_array *keys ) if (keys) { for (k=keys; k->keyblock; k++) release_kbnode (k->keyblock); - m_free (keys); + xfree (keys); } } @@ -335,7 +336,7 @@ read_record (ulong recno, TRUSTREC *rec, int rectype ) if (rc) { log_error(_("trust record %lu, req type %d: read failed: %s\n"), - recno, rec->rectype, g10_errstr(rc) ); + recno, rec->rectype, gpg_strerror (rc) ); tdbio_invalid(); } if (rectype != rec->rectype) @@ -356,7 +357,7 @@ write_record (TRUSTREC *rec) if (rc) { log_error(_("trust record %lu, type %d: write failed: %s\n"), - rec->recnum, rec->rectype, g10_errstr(rc) ); + rec->recnum, rec->rectype, gpg_strerror (rc) ); tdbio_invalid(); } } @@ -370,7 +371,7 @@ do_sync(void) int rc = tdbio_sync (); if(rc) { - log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) ); + log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) ); g10_exit(2); } } @@ -399,7 +400,7 @@ setup_trustdb( int level, const char *dbname ) if( trustdb_args.init ) return 0; trustdb_args.level = level; - trustdb_args.dbname = dbname? m_strdup(dbname): NULL; + trustdb_args.dbname = dbname? xstrdup (dbname): NULL; return 0; } @@ -434,7 +435,7 @@ init_trustdb() else BUG(); if( rc ) - log_fatal("can't init trustdb: %s\n", g10_errstr(rc) ); + log_fatal("can't init trustdb: %s\n", gpg_strerror (rc) ); if(opt.trust_model==TM_AUTO) { @@ -607,7 +608,7 @@ read_trust_record (PKT_public_key *pk, TRUSTREC *rec) if (rc) { log_error ("trustdb: searching trust record failed: %s\n", - g10_errstr (rc)); + gpg_strerror (rc)); return rc; } @@ -615,7 +616,7 @@ read_trust_record (PKT_public_key *pk, TRUSTREC *rec) { log_error ("trustdb: record %lu is not a trust record\n", rec->recnum); - return G10ERR_TRUSTDB; + return GPG_ERR_TRUSTDB; } return 0; @@ -760,12 +761,12 @@ update_min_ownertrust (u32 *kid, unsigned int new_trust ) TRUSTREC rec; int rc; - pk = m_alloc_clear (sizeof *pk); + pk = xcalloc (1,sizeof *pk); rc = get_pubkey (pk, kid); if (rc) { log_error (_("public key %08lX not found: %s\n"), - (ulong)kid[1], g10_errstr(rc) ); + (ulong)kid[1], gpg_strerror (rc) ); return; } @@ -1029,12 +1030,12 @@ get_validity (PKT_public_key *pk, PKT_user_id *uid) keyid_from_pk (pk, kid); if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1]) { /* this is a subkey - get the mainkey */ - main_pk = m_alloc_clear (sizeof *main_pk); + main_pk = xcalloc (1,sizeof *main_pk); rc = get_pubkey (main_pk, pk->main_keyid); if (rc) { log_error ("error getting main key %08lX of subkey %08lX: %s\n", - (ulong)pk->main_keyid[1], (ulong)kid[1], g10_errstr(rc)); + (ulong)pk->main_keyid[1], (ulong)kid[1], gpg_strerror (rc)); validity = TRUST_UNKNOWN; goto leave; } @@ -1223,12 +1224,12 @@ ask_ownertrust (u32 *kid,int minimum) int rc; int ot; - pk = m_alloc_clear (sizeof *pk); + pk = xcalloc (1,sizeof *pk); rc = get_pubkey (pk, kid); if (rc) { log_error (_("public key %08lX not found: %s\n"), - (ulong)kid[1], g10_errstr(rc) ); + (ulong)kid[1], gpg_strerror (rc) ); return TRUST_UNKNOWN; } @@ -1712,14 +1713,14 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, KEYDB_SEARCH_DESC desc; maxkeys = 1000; - keys = m_alloc ((maxkeys+1) * sizeof *keys); + keys = xmalloc ((maxkeys+1) * sizeof *keys); nkeys = 0; rc = keydb_search_reset (hd); if (rc) { - log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); - m_free (keys); + log_error ("keydb_search_reset failed: %s\n", gpg_strerror (rc)); + xfree (keys); return NULL; } @@ -1735,8 +1736,8 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, } if (rc) { - log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); - m_free (keys); + log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc)); + xfree (keys); return NULL; } @@ -1748,8 +1749,8 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, rc = keydb_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); - m_free (keys); + log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); + xfree (keys); return NULL; } @@ -1781,7 +1782,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, if (nkeys == maxkeys) { maxkeys += 1000; - keys = m_realloc (keys, (maxkeys+1) * sizeof *keys); + keys = xrealloc (keys, (maxkeys+1) * sizeof *keys); } keys[nkeys++].keyblock = keyblock; @@ -1804,8 +1805,8 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, while ( !(rc = keydb_search (hd, &desc, 1)) ); if (rc && rc != -1) { - log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); - m_free (keys); + log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); + xfree (keys); return NULL; } @@ -1825,7 +1826,7 @@ reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude) rc = keydb_search_reset (hd); if (rc) { - log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); + log_error ("keydb_search_reset failed: %s\n", gpg_strerror (rc)); return; } @@ -1838,7 +1839,7 @@ reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude) } rc = keydb_search (hd, &desc, 1); if (rc && rc != -1 ) - log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); + log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc)); else if (!rc) { desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */ @@ -1847,7 +1848,7 @@ reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude) rc = keydb_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); break; } count++; @@ -1860,7 +1861,7 @@ reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude) } while ( !(rc = keydb_search (hd, &desc, 1)) ); if (rc && rc != -1) - log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); + log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); } if (opt.verbose) log_info (_("%d keys processed (%d validity counts cleared)\n"), @@ -2027,7 +2028,7 @@ validate_keys (int interactive) if (!keys) { log_error ("validate_key_list failed\n"); - rc = G10ERR_GENERAL; + rc = GPG_ERR_GENERAL; goto leave; } @@ -2081,7 +2082,7 @@ validate_keys (int interactive) kar->keyblock->pkt->pkt.public_key->trust_value; if(kar->keyblock->pkt->pkt.public_key->trust_regexp) k->trust_regexp= - m_strdup(kar->keyblock->pkt-> + xstrdup (kar->keyblock->pkt-> pkt.public_key->trust_regexp); k->next = klist; klist = k; @@ -2117,7 +2118,7 @@ validate_keys (int interactive) if(tdbio_update_version_record()!=0) { log_error(_("unable to update trustdb version record: " - "write failed: %s\n"), g10_errstr(rc)); + "write failed: %s\n"), gpg_strerror (rc)); tdbio_invalid(); } diff --git a/g10/verify.c b/g10/verify.c index 705a45746..cfa373637 100644 --- a/g10/verify.c +++ b/g10/verify.c @@ -54,7 +54,7 @@ int verify_signatures( int nfiles, char **files ) { - IOBUF fp; + iobuf_t fp; armor_filter_context_t afx; progress_filter_context_t pfx; const char *sigfile; @@ -92,8 +92,10 @@ verify_signatures( int nfiles, char **files ) /* open the signature file */ fp = iobuf_open(sigfile); if( !fp ) { - log_error(_("can't open `%s'\n"), print_fname_stdin(sigfile)); - return G10ERR_OPEN_FILE; + rc = gpg_error_from_errno (errno); + log_error(_("can't open `%s': %s\n"), + print_fname_stdin(sigfile), strerror (errno)); + return rc; } handle_progress (&pfx, fp, sigfile); @@ -120,17 +122,17 @@ verify_signatures( int nfiles, char **files ) void print_file_status( int status, const char *name, int what ) { - char *p = m_alloc(strlen(name)+10); + char *p = xmalloc (strlen(name)+10); sprintf(p, "%d %s", what, name ); write_status_text( status, p ); - m_free(p); + xfree (p); } static int verify_one_file( const char *name ) { - IOBUF fp; + iobuf_t fp; armor_filter_context_t afx; progress_filter_context_t pfx; int rc; @@ -138,9 +140,11 @@ verify_one_file( const char *name ) print_file_status( STATUS_FILE_START, name, 1 ); fp = iobuf_open(name); if( !fp ) { + rc = gpg_error_from_errno (errno); + log_error(_("can't open `%s': %s\n"), + print_fname_stdin(name), strerror (errno)); print_file_status( STATUS_FILE_ERROR, name, 1 ); - log_error(_("can't open `%s'\n"), print_fname_stdin(name)); - return G10ERR_OPEN_FILE; + return rc; } handle_progress (&pfx, fp, name); @@ -175,7 +179,7 @@ verify_files( int nfiles, char **files ) lno++; if( !*line || line[strlen(line)-1] != '\n' ) { log_error(_("input line %u too long or missing LF\n"), lno ); - return G10ERR_GENERAL; + return GPG_ERR_GENERAL; } /* This code does not work on MSDOS but how cares there are * also no script languages available. We don't strip any diff --git a/include/ChangeLog b/include/ChangeLog index 3df94bb43..0b1001c3b 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,15 @@ +2003-06-11 Werner Koch <wk@gnupg.org> + + * cipher.h: Include gcrypt.h and mapped cipher algo names to + gcrypt ones. Removed twofish_old and skipjack. Removed all + handle definitions and other raerely used stuff. This file will + eventually be entirely removed. + + +2003-06-10 Werner Koch <wk@gnupg.org> + + * types.h (struct strlist): Removed. + 2003-05-24 David Shaw <dshaw@jabberwocky.com> * cipher.h, i18n.h, iobuf.h, memory.h, mpi.h, types.h, util.h: diff --git a/include/cipher.h b/include/cipher.h index 23a5aeb0d..3058a2ce0 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -22,46 +22,42 @@ #define DBG_CIPHER g10c_debug_mode -#include "mpi.h" -#include "../cipher/random.h" - - -#define CIPHER_ALGO_NONE 0 -#define CIPHER_ALGO_IDEA 1 -#define CIPHER_ALGO_3DES 2 -#define CIPHER_ALGO_CAST5 3 -#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */ -#define CIPHER_ALGO_SAFER_SK128 5 -#define CIPHER_ALGO_DES_SK 6 -#define CIPHER_ALGO_AES 7 -#define CIPHER_ALGO_AES192 8 -#define CIPHER_ALGO_AES256 9 +#include <gcrypt.h> + +#define CIPHER_ALGO_NONE GCRY_CIPHER_NONE +#define CIPHER_ALGO_IDEA GCRY_CIPHER_IDEA +#define CIPHER_ALGO_3DES GCRY_CIPHER_3DES +#define CIPHER_ALGO_CAST5 GCRY_CIPHER_CAST5 +#define CIPHER_ALGO_BLOWFISH GCRY_CIPHER_BLOWFISH /* 128 bit */ +#define CIPHER_ALGO_SAFER_SK128 GCRY_CIPHER_SK128 +#define CIPHER_ALGO_DES_SK GCRY_CIPHER_DES_SK +#define CIPHER_ALGO_AES GCRY_CIPHER_AES +#define CIPHER_ALGO_AES192 GCRY_CIPHER_AES192 +#define CIPHER_ALGO_AES256 GCRY_CIPHER_AES256 #define CIPHER_ALGO_RIJNDAEL CIPHER_ALGO_AES #define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192 #define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256 -#define CIPHER_ALGO_TWOFISH 10 /* twofish 256 bit */ -#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */ -#define CIPHER_ALGO_TWOFISH_OLD 102 /* experimental: twofish 128 bit */ +#define CIPHER_ALGO_TWOFISH GCRY_CIPHER_TWOFISH /* 256 bit */ #define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ -#define PUBKEY_ALGO_RSA 1 -#define PUBKEY_ALGO_RSA_E 2 /* RSA encrypt only */ -#define PUBKEY_ALGO_RSA_S 3 /* RSA sign only */ -#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not for v3)*/ -#define PUBKEY_ALGO_DSA 17 -#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ +#define PUBKEY_ALGO_RSA GCRY_PK_RSA +#define PUBKEY_ALGO_RSA_E GCRY_PK_RSA_E +#define PUBKEY_ALGO_RSA_S GCRY_PK_RSA_S +#define PUBKEY_ALGO_ELGAMAL_E GCRY_PK_ELG_E +#define PUBKEY_ALGO_DSA GCRY_PK_DSA +#define PUBKEY_ALGO_ELGAMAL GCRY_PK_ELG -#define PUBKEY_USAGE_SIG 1 /* key is good for signatures */ -#define PUBKEY_USAGE_ENC 2 /* key is good for encryption */ +#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN +#define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR #define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/ -#define DIGEST_ALGO_MD5 1 -#define DIGEST_ALGO_SHA1 2 -#define DIGEST_ALGO_RMD160 3 -#define DIGEST_ALGO_TIGER 6 -#define DIGEST_ALGO_SHA256 8 -#define DIGEST_ALGO_SHA384 9 -#define DIGEST_ALGO_SHA512 10 +#define DIGEST_ALGO_MD5 GCRY_MD_MD5 +#define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 +#define DIGEST_ALGO_RMD160 GCRY_MD_RMD160 +#define DIGEST_ALGO_TIGER GCRY_MD_TIGER +#define DIGEST_ALGO_SHA256 GCRY_MD_SHA256 +#define DIGEST_ALGO_SHA384 GCRY_MD_SHA384 +#define DIGEST_ALGO_SHA512 GCRY_MD_SHA512 #define COMPRESS_ALGO_NONE 0 #define COMPRESS_ALGO_ZIP 1 @@ -79,30 +75,6 @@ typedef struct { byte key[32]; /* this is the largest used keylen (256 bit) */ } DEK; -struct cipher_handle_s; -typedef struct cipher_handle_s *CIPHER_HANDLE; - - -#define CIPHER_MODE_ECB 1 -#define CIPHER_MODE_CFB 2 -#define CIPHER_MODE_PHILS_CFB 3 -#define CIPHER_MODE_AUTO_CFB 4 -#define CIPHER_MODE_DUMMY 5 /* used with algo DUMMY for no encryption */ -#define CIPHER_MODE_CBC 6 - -struct md_digest_list_s; - -struct gcry_md_context { - int secure; - FILE *debug; - int finalized; - struct md_digest_list_s *list; - int bufcount; - int bufsize; - byte buffer[1]; -}; - -typedef struct gcry_md_context *MD_HANDLE; #ifndef EXTERN_UNLESS_MAIN_MODULE #if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE) @@ -116,90 +88,13 @@ EXTERN_UNLESS_MAIN_MODULE int g10_opt_verbose; EXTERN_UNLESS_MAIN_MODULE const char *g10_opt_homedir; -/*-- dynload.c --*/ -void register_cipher_extension( const char *mainpgm, const char *fname ); - -/*-- md.c --*/ -int string_to_digest_algo( const char *string ); -const char * digest_algo_to_string( int algo ); -int check_digest_algo( int algo ); -MD_HANDLE md_open( int algo, int secure ); -void md_enable( MD_HANDLE hd, int algo ); -MD_HANDLE md_copy( MD_HANDLE a ); -void md_reset( MD_HANDLE a ); -void md_close(MD_HANDLE a); -void md_write( MD_HANDLE a, const byte *inbuf, size_t inlen); -void md_final(MD_HANDLE a); -byte *md_read( MD_HANDLE a, int algo ); -int md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen ); -int md_get_algo( MD_HANDLE a ); -int md_algo_present( MD_HANDLE a, int algo ); -int md_digest_length( int algo ); -const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen ); -void md_start_debug( MD_HANDLE a, const char *suffix ); -void md_stop_debug( MD_HANDLE a ); -#define md_is_secure(a) ((a)->secure) -#define md_putc(h,c) \ - do { \ - if( (h)->bufcount == (h)->bufsize ) \ - md_write( (h), NULL, 0 ); \ - (h)->buffer[(h)->bufcount++] = (c) & 0xff; \ - } while(0) - -void rmd160_hash_buffer (char *outbuf, const char *buffer, size_t length); - - -/*-- cipher.c --*/ -int string_to_cipher_algo( const char *string ); -const char * cipher_algo_to_string( int algo ); -void disable_cipher_algo( int algo ); -int check_cipher_algo( int algo ); -unsigned cipher_get_keylen( int algo ); -unsigned cipher_get_blocksize( int algo ); -CIPHER_HANDLE cipher_open( int algo, int mode, int secure ); -void cipher_close( CIPHER_HANDLE c ); -int cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ); -void cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen ); -void cipher_encrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); -void cipher_decrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); -void cipher_sync( CIPHER_HANDLE c ); - -/*-- pubkey.c --*/ + #define PUBKEY_MAX_NPKEY 4 #define PUBKEY_MAX_NSKEY 6 #define PUBKEY_MAX_NSIG 2 #define PUBKEY_MAX_NENC 2 -int string_to_pubkey_algo( const char *string ); -const char * pubkey_algo_to_string( int algo ); -void disable_pubkey_algo( int algo ); -int check_pubkey_algo( int algo ); -int check_pubkey_algo2( int algo, unsigned use ); -int pubkey_get_npkey( int algo ); -int pubkey_get_nskey( int algo ); -int pubkey_get_nsig( int algo ); -int pubkey_get_nenc( int algo ); -unsigned pubkey_nbits( int algo, MPI *pkey ); -int pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors ); -int pubkey_check_secret_key( int algo, MPI *skey ); -int pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey ); -int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey ); -int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); -int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaque ); - -/*-- smallprime.c --*/ -extern ushort small_prime_numbers[]; - -/*-- primegen.c --*/ -void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ); -MPI generate_secret_prime( unsigned nbits ); -MPI generate_public_prime( unsigned nbits ); -MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **factors ); - -/*-- elsewhere --*/ -void register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data ); -void register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data ); +#define MD_HANDLE gcry_md_hd_t +#define CIPHER_HANDLE gcry_cipher_hd_t #endif /*G10_CIPHER_H*/ diff --git a/include/errors.h b/include/errors.h index 8e1de0f16..ed437fa99 100644 --- a/include/errors.h +++ b/include/errors.h @@ -1,4 +1,4 @@ -/* errors.h - erro code +/* errors.h - error code * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * * This file is part of GNUPG. @@ -25,6 +25,8 @@ #error from libgpg-error. The numerical values are identical, though. #endif + +#if 0 /* Not used anymore. */ #define G10ERR_GENERAL 1 #define G10ERR_UNKNOWN_PACKET 2 #define G10ERR_UNKNOWN_VERSION 3 /* Unknown version (in packet) */ @@ -80,10 +82,20 @@ #define G10ERR_UNU_PUBKEY 53 #define G10ERR_UNU_SECKEY 54 #define G10ERR_KEYSERVER 55 - +#endif #ifndef HAVE_STRERROR char *strerror( int n ); #endif #endif /*GNUPG_INCLUDE_ERRORS_H*/ + + + + + + + + + + diff --git a/include/iobuf.h b/include/iobuf.h deleted file mode 100644 index 9ae774207..000000000 --- a/include/iobuf.h +++ /dev/null @@ -1,161 +0,0 @@ -/* iobuf.h - I/O buffer - * 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_IOBUF_H -#define G10_IOBUF_H - -#include "types.h" - - -#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; - -/* 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 chain, byte *buf, size_t *len); - void *filter_ov; /* value for opaque */ - int filter_ov_owner; - char *real_fname; - IOBUF 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 iobuf_alloc(int use, size_t bufsize); -IOBUF iobuf_temp(void); -IOBUF iobuf_temp_with_content( const char *buffer, size_t length ); -IOBUF iobuf_open( const char *fname ); -IOBUF iobuf_fdopen( int fd, const char *mode ); -IOBUF iobuf_sockopen( int fd, const char *mode ); -IOBUF iobuf_create( const char *fname ); -IOBUF iobuf_append( const char *fname ); -IOBUF iobuf_openrw( const char *fname ); -int iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval ); -int iobuf_close( IOBUF iobuf ); -int iobuf_cancel( IOBUF iobuf ); - -int iobuf_push_filter( IOBUF a, int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), void *ov ); -int iobuf_push_filter2( IOBUF a, - int (*f)(void *opaque, int control, - IOBUF chain, byte *buf, size_t *len), - void *ov, int rel_ov ); -int iobuf_flush(IOBUF a); -void iobuf_clear_eof(IOBUF a); -#define iobuf_set_error(a) do { (a)->error = 1; } while(0) -#define iobuf_error(a) ((a)->error) - -void iobuf_set_limit( IOBUF a, off_t nlimit ); - -off_t iobuf_tell( IOBUF a ); -int iobuf_seek( IOBUF a, off_t newpos ); - -int iobuf_readbyte(IOBUF a); -int iobuf_read(IOBUF a, byte *buf, unsigned buflen ); -unsigned iobuf_read_line( IOBUF a, byte **addr_of_buffer, - unsigned *length_of_buffer, unsigned *max_length ); -int iobuf_peek(IOBUF a, byte *buf, unsigned buflen ); -int iobuf_writebyte(IOBUF a, unsigned c); -int iobuf_write(IOBUF a, byte *buf, unsigned buflen ); -int iobuf_writestr(IOBUF a, const char *buf ); - -void iobuf_flush_temp( IOBUF temp ); -int iobuf_write_temp( IOBUF a, IOBUF temp ); -size_t iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen ); -void iobuf_unget_and_close_temp( IOBUF a, IOBUF temp ); - -off_t iobuf_get_filelength( IOBUF a ); -#define IOBUF_FILELENGTH_LIMIT 0xffffffff -const char *iobuf_get_real_fname( IOBUF a ); -const char *iobuf_get_fname( IOBUF a ); - -void iobuf_set_block_mode( IOBUF a, size_t n ); -void iobuf_set_partial_block_mode( IOBUF a, size_t len ); -int iobuf_in_block_mode( IOBUF 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 /*G10_IOBUF_H*/ diff --git a/include/mpi.h b/include/mpi.h index 3198584a2..424e591a0 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -30,6 +30,11 @@ #ifndef G10_MPI_H #define G10_MPI_H +#include <gcrypt.h> + +#if 0 + + #include <config.h> #include <stdio.h> #include "iobuf.h" @@ -192,5 +197,5 @@ void mpi_rshift( MPI x, MPI a, unsigned n ); /*-- mpi-inv.c --*/ void mpi_invm( MPI x, MPI u, MPI v ); - +#endif #endif /*G10_MPI_H*/ diff --git a/include/ttyio.h b/include/ttyio.h deleted file mode 100644 index 5f6557930..000000000 --- a/include/ttyio.h +++ /dev/null @@ -1,40 +0,0 @@ -/* ttyio.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_TTYIO_H -#define G10_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))); -#else - void tty_printf (const char *fmt, ... ); -#endif -void tty_print_string( byte *p, size_t n ); -void tty_print_utf8_string( byte *p, size_t n ); -void tty_print_utf8_string2( byte *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 /*G10_TTYIO_H*/ diff --git a/include/types.h b/include/types.h index fc5381965..838897aa5 100644 --- a/include/types.h +++ b/include/types.h @@ -132,10 +132,4 @@ typedef union { double g; } PROPERLY_ALIGNED_TYPE; -typedef struct string_list { - struct string_list *next; - unsigned int flags; - char d[1]; -} *STRLIST; - #endif /*G10_TYPES_H*/ diff --git a/include/util.h b/include/util.h index c3d0189c6..ca5e5e431 100644 --- a/include/util.h +++ b/include/util.h @@ -20,6 +20,9 @@ #ifndef G10_UTIL_H #define G10_UTIL_H +#warning oops, using old util.h +#if 0 /* Dont use it anymore */ + #if defined (__MINGW32__) || defined (__CYGWIN32__) #include <stdarg.h> #endif @@ -126,9 +129,6 @@ void g10_log_hexdump( const char *text, const char *buf, size_t len ); #define log_debug_f g10_log_debug_f -/*-- errors.c --*/ -const char * g10_errstr( int no ); - /*-- argparse.c --*/ int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, @@ -177,15 +177,9 @@ int answer_is_yes( const char *s ); int answer_is_yes_no_quit( const char *s ); /*-- strgutil.c --*/ -void free_strlist( STRLIST sl ); -#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) -STRLIST add_to_strlist( STRLIST *list, const char *string ); -STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); -STRLIST append_to_strlist( STRLIST *list, const char *string ); -STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); -STRLIST strlist_prev( STRLIST head, STRLIST node ); -STRLIST strlist_last( STRLIST node ); -char *pop_strlist( STRLIST *list ); + +#include "../jnlib/strlist.h" + const char *memistr( const char *buf, size_t buflen, const char *sub ); const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); char *mem2str( char *, const void *, size_t); @@ -301,4 +295,6 @@ void riscos_list_openfiles(void); #endif /* !__RISCOS__C__ */ #endif /* __riscos__ */ +#endif + #endif /*G10_UTIL_H*/ diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 41bf3d3bd..594eb340b 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,36 @@ +2003-06-18 Werner Koch <wk@gnupg.org> + + * strlist.c (strlist_pop): New. + + * dotlock.c (dotlock_remove_lockfiles): Prefixed with dotlock_ and + made global. + +2003-06-17 Werner Koch <wk@gnupg.org> + + * stringhelp.c (length_sans_trailing_chars) + (length_sans_trailing_ws): New. + + * logging.c (log_inc_errorcount): New. + + * stringhelp.c (print_sanitized_utf8_buffer): Implement utf8 + conversion. + (sanitize_buffer): New. Based on gnupg 1.3.2 make_printable_string. + + * dotlock.c: Updated to match the version from 1.3.2 + * utf8conv.c: New. Code taken from strgutil.c of gnupg 1.3.2. + * utf8conv.h: New. + +2003-06-16 Werner Koch <wk@gnupg.org> + + * logging.c (do_logv): Hack to optionally suppress a leading space. + + * stringhelp.c (ascii_strncasecmp): New. Taken from gnupg 1.3. + (ascii_memistr): New. Taken from gnupg 1.3 + +2003-06-13 Werner Koch <wk@gnupg.org> + + * mischelp.h (wipememory2,wipememory): New. Taken from GnuPG 1.3.2. + 2002-06-04 Werner Koch <wk@gnupg.org> * stringhelp.c (print_sanitized_utf8_string): New. No real @@ -113,7 +146,7 @@ Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> * You may find it source-copied in other packages. * *********************************************************** - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 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 diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index 303ffe3cb..ae1cf6be2 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -31,6 +31,7 @@ libjnlib_a_SOURCES = \ libjnlib-config.h \ stringhelp.c stringhelp.h \ strlist.c strlist.h \ + utf8conv.c utf8conv.h \ argparse.c argparse.h \ logging.c logging.h \ dotlock.c dotlock.h \ diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index 772c770e8..7240fafeb 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -1,5 +1,5 @@ /* dotlock.c - dotfile locking - * Copyright (C) 1998,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 1998,2000,2001,2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -42,13 +42,20 @@ struct dotlock_handle { char *tname; /* name of lockfile template */ char *lockname; /* name of the real lockfile */ int locked; /* lock status */ + int disable; /* locking */ }; -static DOTLOCK all_lockfiles; +static volatile DOTLOCK all_lockfiles; +static int never_lock; static int read_lockfile( const char *name ); -static void remove_lockfiles(void); + +void +disable_dotlock(void) +{ + never_lock = 1; +} /**************** * Create a lockfile with the given name and return an object of @@ -81,13 +88,23 @@ create_dotlock( const char *file_to_lock ) int dirpartlen; if( !initialized ) { - atexit( remove_lockfiles ); + atexit( dotlock_remove_lockfiles ); initialized = 1; } if( !file_to_lock ) return NULL; h = jnlib_xcalloc( 1, sizeof *h ); + if( never_lock ) { + h->disable = 1; +#ifdef _REENTRANT + /* fixme: aquire mutex on all_lockfiles */ +#endif + h->next = all_lockfiles; + all_lockfiles = h; + return h; + } + #ifndef HAVE_DOSISH_SYSTEM sprintf( pidstr, "%10d\n", (int)getpid() ); /* fixme: add the hostname to the second line (FQDN or IP addr?) */ @@ -98,8 +115,17 @@ create_dotlock( const char *file_to_lock ) else nodename = utsbuf.nodename; - if( !(dirpart = strrchr( file_to_lock, '/' )) ) { - dirpart = "."; +#ifdef __riscos__ + { + char *iter = (char *) nodename; + for (; iter[0]; iter++) + if (iter[0] == '.') + iter[0] = '/'; + } +#endif /* __riscos__ */ + + if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) { + dirpart = EXTSEP_S; dirpartlen = 1; } else { @@ -114,8 +140,13 @@ create_dotlock( const char *file_to_lock ) all_lockfiles = h; h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); - sprintf( h->tname, "%.*s/.#lk%p.%s.%d", +#ifndef __riscos__ + sprintf( h->tname, "%.*s/.#lk%p.%s.%d", dirpartlen, dirpart, h, nodename, (int)getpid() ); +#else /* __riscos__ */ + sprintf( h->tname, "%.*s.lk%p/%s/%d", + dirpartlen, dirpart, h, nodename, (int)getpid() ); +#endif /* __riscos__ */ do { errno = 0; @@ -147,7 +178,8 @@ create_dotlock( const char *file_to_lock ) #ifdef _REENTRANT /* release mutex */ #endif - log_error( "error closing `%s': %s\n", h->tname, strerror(errno)); + log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); + close(fd); unlink(h->tname); jnlib_free(h->tname); jnlib_free(h); @@ -159,7 +191,7 @@ create_dotlock( const char *file_to_lock ) #endif #endif /* !HAVE_DOSISH_SYSTEM */ h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 ); - strcpy(stpcpy(h->lockname, file_to_lock), ".lock"); + strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); return h; } @@ -191,12 +223,19 @@ make_dotlock( DOTLOCK h, long timeout ) const char *maybe_dead=""; int backoff=0; + if( h->disable ) { + return 0; + } + if( h->locked ) { +#ifndef __riscos__ log_debug("oops, `%s' is already locked\n", h->lockname ); +#endif /* !__riscos__ */ return 0; } for(;;) { +#ifndef __riscos__ if( !link(h->tname, h->lockname) ) { /* fixme: better use stat to check the link count */ h->locked = 1; @@ -206,6 +245,16 @@ make_dotlock( DOTLOCK h, long timeout ) log_error( "lock not made: link() failed: %s\n", strerror(errno) ); return -1; } +#else /* __riscos__ */ + if( !renamefile(h->tname, h->lockname) ) { + h->locked = 1; + return 0; /* okay */ + } + if( errno != EEXIST ) { + log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); + return -1; + } +#endif /* __riscos__ */ if( (pid = read_lockfile(h->lockname)) == -1 ) { if( errno != ENOENT ) { log_info("cannot read lockfile\n"); @@ -215,20 +264,27 @@ make_dotlock( DOTLOCK h, long timeout ) continue; } else if( pid == getpid() ) { - log_info( "Oops: lock already hold by us\n"); + log_info( "Oops: lock already held by us\n"); h->locked = 1; return 0; /* okay */ } else if( kill(pid, 0) && errno == ESRCH ) { +#ifndef __riscos__ maybe_dead = " - probably dead"; - #if 0 /* we should not do this without checking the permissions */ +#if 0 /* we should not do this without checking the permissions */ /* and the hostname */ log_info( "removing stale lockfile (created by %d)", pid ); - #endif +#endif +#else /* __riscos__ */ + /* we are *pretty* sure that the other task is dead and therefore + we remove the other lock file */ + maybe_dead = " - probably dead - removing lock"; + unlink(h->lockname); +#endif /* __riscos__ */ } if( timeout == -1 ) { struct timeval tv; - log_info( "waiting for lock (hold by %d%s) %s...\n", + log_info( "waiting for lock (held by %d%s) %s...\n", pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); @@ -259,6 +315,10 @@ release_dotlock( DOTLOCK h ) #else int pid; + if( h->disable ) { + return 0; + } + if( !h->locked ) { log_debug("oops, `%s' is not locked\n", h->lockname ); return 0; @@ -273,11 +333,19 @@ release_dotlock( DOTLOCK h ) log_error( "release_dotlock: not our lock (pid=%d)\n", pid); return -1; } +#ifndef __riscos__ if( unlink( h->lockname ) ) { log_error( "release_dotlock: error removing lockfile `%s'", h->lockname); return -1; } +#else /* __riscos__ */ + if( renamefile(h->lockname, h->tname) ) { + log_error( "release_dotlock: error renaming lockfile `%s' to `%s'", + h->lockname, h->tname); + return -1; + } +#endif /* __riscos__ */ /* fixme: check that the link count is now 1 */ h->locked = 0; return 0; @@ -291,9 +359,9 @@ release_dotlock( DOTLOCK h ) static int read_lockfile( const char *name ) { - #ifdef HAVE_DOSISH_SYSTEM +#ifdef HAVE_DOSISH_SYSTEM return 0; - #else +#else int fd, pid; char pidstr[16]; @@ -312,20 +380,24 @@ read_lockfile( const char *name ) pidstr[10] = 0; /* terminate pid string */ close(fd); pid = atoi(pidstr); +#ifndef __riscos__ if( !pid || pid == -1 ) { +#else /* __riscos__ */ + if( (!pid && riscos_getpid()) || pid == -1 ) { +#endif /* __riscos__ */ log_error("invalid pid %d in lockfile `%s'", pid, name ); errno = 0; return -1; } return pid; - #endif +#endif } -static void -remove_lockfiles() +void +dotlock_remove_lockfiles() { - #ifndef HAVE_DOSISH_SYSTEM +#ifndef HAVE_DOSISH_SYSTEM DOTLOCK h, h2; h = all_lockfiles; @@ -333,14 +405,16 @@ remove_lockfiles() while( h ) { h2 = h->next; - if( h->locked ) + if (!h->disable ) { + if( h->locked ) unlink( h->lockname ); - unlink(h->tname); - jnlib_free(h->tname); - jnlib_free(h->lockname); + unlink(h->tname); + jnlib_free(h->tname); + jnlib_free(h->lockname); + } jnlib_free(h); h = h2; } - #endif +#endif } diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h index 7d45c8286..9235687df 100644 --- a/jnlib/dotlock.h +++ b/jnlib/dotlock.h @@ -24,9 +24,13 @@ struct dotlock_handle; typedef struct dotlock_handle *DOTLOCK; -DOTLOCK create_dotlock( const char *file_to_lock ); -int make_dotlock( DOTLOCK h, long timeout ); -int release_dotlock( DOTLOCK h ); - +void disable_dotlock (void); +DOTLOCK create_dotlock(const char *file_to_lock); +int make_dotlock (DOTLOCK h, long timeout); +int release_dotlock (DOTLOCK h); +void dotlock_remove_lockfiles (void); #endif /*LIBJNLIB_DOTLOCK_H*/ + + + diff --git a/jnlib/logging.c b/jnlib/logging.c index 647e757c6..913d01b6f 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -1,5 +1,5 @@ /* logging.c - useful logging functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -78,6 +78,12 @@ log_get_errorcount (int clear) return n; } +void +log_inc_errorcount (void) +{ + errorcount++; +} + void log_set_file( const char *name ) { @@ -194,7 +200,12 @@ do_logv( int level, const char *fmt, va_list arg_ptr ) fprintf (logstream, "[%u]", (unsigned int)getpid ()); if (!with_time) putc (':', logstream); - putc (' ', logstream); + /* A leading backspace suppresses the extra space so that we can + correclty output, programname, filename and linenumber. */ + if (fmt && *fmt == '\b') + fmt++; + else + putc (' ', logstream); } switch (level) @@ -272,7 +283,7 @@ log_fatal( const char *fmt, ... ) va_start( arg_ptr, fmt ) ; do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr ); va_end(arg_ptr); - abort(); /* never called, bugs it makes the compiler happy */ + abort(); /* never called, but it makes the compiler happy */ } void diff --git a/jnlib/logging.h b/jnlib/logging.h index 224db36e5..78d2b020d 100644 --- a/jnlib/logging.h +++ b/jnlib/logging.h @@ -26,6 +26,7 @@ int log_get_errorcount (int clear); +void log_inc_errorcount (void); void log_set_file( const char *name ); void log_set_fd (int fd); void log_set_prefix (const char *text, unsigned int flags); diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h index 58c9250e2..54da4cc1f 100644 --- a/jnlib/mischelp.h +++ b/jnlib/mischelp.h @@ -1,5 +1,5 @@ /* mischelp.h - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -39,5 +39,16 @@ #endif +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + + #endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 3c9baaef5..e2744a5ac 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -1,5 +1,5 @@ /* stringhelp.c - standard string helper functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,7 @@ #include <ctype.h> #include "libjnlib-config.h" +#include "utf8conv.h" #include "stringhelp.h" @@ -52,6 +53,25 @@ memistr( const char *buf, size_t buflen, const char *sub ) return NULL ; } +const char * +ascii_memistr( const char *buf, size_t buflen, const char *sub ) +{ + const byte *t, *s ; + size_t n; + + for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) + if( ascii_toupper(*t) == ascii_toupper(*s) ) { + for( buf=t++, buflen = n--, s++; + n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- ) + ; + if( !*s ) + return buf; + t = buf; n = buflen; s = sub ; + } + + return NULL ; +} + /**************** * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein * '\0' angehngt. Ist n = 0, so geschieht nichts, ist Destination @@ -127,7 +147,6 @@ trim_trailing_spaces( char *string ) } - unsigned trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) { @@ -159,6 +178,39 @@ trim_trailing_ws( byte *line, unsigned len ) return trim_trailing_chars( line, len, " \t\r\n" ); } +size_t +length_sans_trailing_chars (const unsigned char *line, size_t len, + const char *trimchars ) +{ + const unsigned char *p, *mark; + size_t n; + + for( mark=NULL, p=line, n=0; n < len; n++, p++ ) + { + if (strchr (trimchars, *p )) + { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if (mark) + return mark - line; + return len; +} + +/**************** + * remove trailing white spaces and return the length of the buffer + */ +size_t +length_sans_trailing_ws (const unsigned char *line, size_t len) +{ + return length_sans_trailing_chars (line, len, " \t\r\n"); +} + + /*************** * Extract from a given path the filename component. @@ -256,18 +308,19 @@ compare_filenames( const char *a, const char *b ) /* ? check whether this is an absolute filename and * resolve symlinks? */ - #ifdef HAVE_DRIVE_LETTERS +#ifdef HAVE_DRIVE_LETTERS return stricmp(a,b); - #else +#else return strcmp(a,b); - #endif +#endif } /* Print a BUFFER to stream FP while replacing all control characters - and the character DELIM with standard C eescape sequences. Returns + and the character DELIM with standard C escape sequences. Returns the number of characters printed. */ size_t -print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, int delim) +print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, + int delim) { const unsigned char *p = buffer; size_t count = 0; @@ -307,8 +360,26 @@ size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim) { - /* FIXME: convert to local characterset */ - return print_sanitized_buffer (fp, buffer, length, delim); + const char *p = buffer; + size_t i; + + /* We can handle plain ascii simpler, so check for it first. */ + for (i=0; i < length; i++ ) + { + if ( (p[i] & 0x80) ) + break; + } + if (i < length) + { + char *buf = utf8_to_native (p, length, delim); + /*(utf8 conversion already does the control character quoting)*/ + i = strlen (buf); + fputs (buf, fp); + jnlib_free (buf); + return i; + } + else + return print_sanitized_buffer (fp, p, length, delim); } @@ -325,6 +396,63 @@ print_sanitized_utf8_string (FILE *fp, const char *string, int delim) return print_sanitized_string (fp, string, delim); } +/* Create a string from the buffer P of length N which is suitable for + printing. Caller must release the created string using xfree. */ +char * +sanitize_buffer (const unsigned char *p, size_t n, int delim) +{ + size_t save_n, buflen; + const byte *save_p; + char *buffer, *d; + + /* first count length */ + for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) + { + if ( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim + || (delim && *p=='\\')) + { + if ( *p=='\n' || *p=='\r' || *p=='\f' + || *p=='\v' || *p=='\b' || !*p ) + buflen += 2; + else + buflen += 4; + } + else + buflen++; + } + p = save_p; + n = save_n; + /* and now make the string */ + d = buffer = jnlib_xmalloc( buflen ); + for ( ; n; n--, p++ ) + { + if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim + ||(delim && *p=='\\')) { + *d++ = '\\'; + if( *p == '\n' ) + *d++ = 'n'; + else if( *p == '\r' ) + *d++ = 'r'; + else if( *p == '\f' ) + *d++ = 'f'; + else if( *p == '\v' ) + *d++ = 'v'; + else if( *p == '\b' ) + *d++ = 'b'; + else if( !*p ) + *d++ = '0'; + else { + sprintf(d, "x%02x", *p ); + d += 2; + } + } + else + *d++ = *p; + } + *d = 0; + return buffer; +} + /**************************************************** ******** locale insensitive ctype functions ******** ****************************************************/ @@ -371,6 +499,33 @@ ascii_strcasecmp( const char *a, const char *b ) return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); } +int +ascii_strncasecmp (const char *a, const char *b, size_t n) +{ + const unsigned char *p1 = (const unsigned char *)a; + const unsigned char *p2 = (const unsigned char *)b; + unsigned char c1, c2; + + if (p1 == p2 || !n ) + return 0; + + do + { + c1 = ascii_tolower (*p1); + c2 = ascii_tolower (*p2); + + if ( !--n || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + return c1 - c2; +} + + int ascii_memcasecmp( const char *a, const char *b, size_t n ) { diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index 027d30c72..fe5786e59 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -1,5 +1,5 @@ /* stringhelp.h - * Copyright (C) 1998,1999,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 1998,1999,2000,2001,2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +30,9 @@ char *trim_trailing_spaces( char *string ); unsigned int trim_trailing_chars( unsigned char *line, unsigned len, const char *trimchars); unsigned int trim_trailing_ws( unsigned char *line, unsigned len ); +size_t length_sans_trailing_chars (const unsigned char *line, size_t len, + const char *trimchars ); +size_t length_sans_trailing_ws (const unsigned char *line, size_t len); char *make_basename(const char *filepath); @@ -43,6 +46,7 @@ size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim); size_t print_sanitized_string (FILE *fp, const char *string, int delim); size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); +char *sanitize_buffer (const unsigned char *p, size_t n, int delim); const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); @@ -51,7 +55,9 @@ int ascii_islower (int c); int ascii_toupper (int c); int ascii_tolower (int c); int ascii_strcasecmp( const char *a, const char *b ); +int ascii_strncasecmp (const char *a, const char *b, size_t n); int ascii_memcasecmp( const char *a, const char *b, size_t n ); +const char *ascii_memistr ( const char *buf, size_t buflen, const char *sub); void *ascii_memcasemem (const void *haystack, size_t nhaystack, const void *needle, size_t nneedle); diff --git a/jnlib/strlist.c b/jnlib/strlist.c index 7cbaf5e02..063c89c7e 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -56,7 +56,7 @@ add_to_strlist( STRLIST *list, const char *string ) #if 0 /**************** * same as add_to_strlist() but if is_utf8 is *not* set a conversion - * to UTF8 is done + * to UTF8 is done */ STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) @@ -130,4 +130,22 @@ strlist_last( STRLIST node ) } +char * +strlist_pop (STRLIST *list) +{ + char *str=NULL; + STRLIST sl=*list; + + if(sl) + { + str=jnlib_xmalloc(strlen(sl->d)+1); + strcpy(str,sl->d); + + *list=sl->next; + jnlib_free(sl); + } + + return str; +} + diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 53c0bc750..443408f16 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -31,11 +31,12 @@ typedef struct string_list *STRLIST; void free_strlist( STRLIST sl ); STRLIST add_to_strlist( STRLIST *list, const char *string ); -STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +/*STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 );*/ STRLIST append_to_strlist( STRLIST *list, const char *string ); -STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +/*STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 );*/ STRLIST strlist_prev( STRLIST head, STRLIST node ); STRLIST strlist_last( STRLIST node ); +char * strlist_pop (STRLIST *list); #define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c new file mode 100644 index 000000000..691176766 --- /dev/null +++ b/jnlib/utf8conv.c @@ -0,0 +1,448 @@ +/* utf8conf.c - UTF8 character set conversion + * Copyright (C) 1994, 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 <string.h> +#include <stdarg.h> +#include <ctype.h> +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif + +#include "libjnlib-config.h" +#include "stringhelp.h" +#include "utf8conv.h" + + +static ushort koi8_unicode[128] = { + 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, + 0x252c, 0x2534, 0x253c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590, + 0x2591, 0x2592, 0x2593, 0x2320, 0x25a0, 0x2219, 0x221a, 0x2248, + 0x2264, 0x2265, 0x00a0, 0x2321, 0x00b0, 0x00b2, 0x00b7, 0x00f7, + 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, + 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, + 0x255f, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, + 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x00a9, + 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, + 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, + 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, + 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a +}; + +static ushort latin2_unicode[128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, + 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, + 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, + 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +}; + + +static const char *active_charset_name = "iso-8859-1"; +static ushort *active_charset = NULL; +static int no_translation = 0; + +int +set_native_charset (const char *newset) +{ + if (!newset) +#ifdef HAVE_LANGINFO_CODESET + newset = nl_langinfo (CODESET); +#else + newset = "8859-1"; +#endif + + if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) + { + newset += 3; + if (*newset == '-' || *newset == '_') + newset++; + } + + if (!*newset + || !ascii_strcasecmp (newset, "8859-1") + || !ascii_strcasecmp (newset, "8859-15")) + { + active_charset_name = "iso-8859-1"; + no_translation = 0; + active_charset = NULL; + } + else if (!ascii_strcasecmp (newset, "8859-2")) + { + active_charset_name = "iso-8859-2"; + no_translation = 0; + active_charset = latin2_unicode; + } + else if (!ascii_strcasecmp (newset, "koi8-r")) + { + active_charset_name = "koi8-r"; + no_translation = 0; + active_charset = koi8_unicode; + } + else if (!ascii_strcasecmp (newset, "utf8") + || !ascii_strcasecmp (newset, "utf-8")) + { + active_charset_name = "utf-8"; + no_translation = 1; + active_charset = NULL; + } + else + return -1; + return 0; +} + +const char * +get_native_charset () +{ + return active_charset_name; +} + +/**************** + * Convert string, which is in native encoding to UTF8 and return the + * new allocated UTF8 string. + */ +char * +native_to_utf8 (const char *string) +{ + const byte *s; + char *buffer; + byte *p; + size_t length = 0; + + if (no_translation) + { + buffer = jnlib_xstrdup (string); + } + else if (active_charset) + { + for (s = string; *s; s++) + { + length++; + if (*s & 0x80) + length += 2; /* we may need 3 bytes */ + } + buffer = jnlib_xmalloc (length + 1); + for (p = buffer, s = string; *s; s++) + { + if ((*s & 0x80)) + { + ushort val = active_charset[*s & 0x7f]; + if (val < 0x0800) + { + *p++ = 0xc0 | ((val >> 6) & 0x1f); + *p++ = 0x80 | (val & 0x3f); + } + else + { + *p++ = 0xe0 | ((val >> 12) & 0x0f); + *p++ = 0x80 | ((val >> 6) & 0x3f); + *p++ = 0x80 | (val & 0x3f); + } + } + else + *p++ = *s; + } + *p = 0; + } + else + { + for (s = string; *s; s++) + { + length++; + if (*s & 0x80) + length++; + } + buffer = jnlib_xmalloc (length + 1); + for (p = buffer, s = string; *s; s++) + { + if (*s & 0x80) + { + *p++ = 0xc0 | ((*s >> 6) & 3); + *p++ = 0x80 | (*s & 0x3f); + } + else + *p++ = *s; + } + *p = 0; + } + return buffer; +} + + +/* Convert string, which is in UTF8 to native encoding. Replace + * illegal encodings by some "\xnn" and quote all control + * characters. A character with value DELIM will always be quoted, it + * must be a vanilla ASCII character. */ +char * +utf8_to_native (const char *string, size_t length, int delim) +{ + int nleft; + int i; + byte encbuf[8]; + int encidx; + const byte *s; + size_t n; + byte *buffer = NULL, *p = NULL; + unsigned long val = 0; + size_t slen; + int resync = 0; + + /* 1. pass (p==NULL): count the extended utf-8 characters */ + /* 2. pass (p!=NULL): create string */ + for (;;) + { + for (slen = length, nleft = encidx = 0, n = 0, s = string; slen; + s++, slen--) + { + if (resync) + { + if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd))) + { + /* still invalid */ + if (p) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4; + continue; + } + resync = 0; + } + if (!nleft) + { + if (!(*s & 0x80)) + { /* plain ascii */ + if (*s < 0x20 || *s == 0x7f || *s == delim || + (delim && *s == '\\')) + { + n++; + if (p) + *p++ = '\\'; + switch (*s) + { + case '\n': + n++; + if (p) + *p++ = 'n'; + break; + case '\r': + n++; + if (p) + *p++ = 'r'; + break; + case '\f': + n++; + if (p) + *p++ = 'f'; + break; + case '\v': + n++; + if (p) + *p++ = 'v'; + break; + case '\b': + n++; + if (p) + *p++ = 'b'; + break; + case 0: + n++; + if (p) + *p++ = '0'; + break; + default: + n += 3; + if (p) + { + sprintf (p, "x%02x", *s); + p += 3; + } + break; + } + } + else + { + if (p) + *p++ = *s; + n++; + } + } + else if ((*s & 0xe0) == 0xc0) + { /* 110x xxxx */ + val = *s & 0x1f; + nleft = 1; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xf0) == 0xe0) + { /* 1110 xxxx */ + val = *s & 0x0f; + nleft = 2; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xf8) == 0xf0) + { /* 1111 0xxx */ + val = *s & 0x07; + nleft = 3; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xfc) == 0xf8) + { /* 1111 10xx */ + val = *s & 0x03; + nleft = 4; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xfe) == 0xfc) + { /* 1111 110x */ + val = *s & 0x01; + nleft = 5; + encidx = 0; + encbuf[encidx++] = *s; + } + else + { /* invalid encoding: print as \xnn */ + if (p) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4; + resync = 1; + } + } + else if (*s < 0x80 || *s >= 0xc0) + { /* invalid */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4 + 4 * encidx; + nleft = 0; + encidx = 0; + resync = 1; + } + else + { + encbuf[encidx++] = *s; + val <<= 6; + val |= *s & 0x3f; + if (!--nleft) + { /* ready */ + if (no_translation) + { + if (p) + { + for (i = 0; i < encidx; i++) + *p++ = encbuf[i]; + } + n += encidx; + encidx = 0; + } + else if (active_charset) + { /* table lookup */ + for (i = 0; i < 128; i++) + { + if (active_charset[i] == val) + break; + } + if (i < 128) + { /* we can print this one */ + if (p) + *p++ = i + 128; + n++; + } + else + { /* we do not have a translation: print utf8 */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + } + n += encidx * 4; + encidx = 0; + } + } + else + { /* native set */ + if (val >= 0x80 && val < 256) + { + n++; /* we can simply print this character */ + if (p) + *p++ = val; + } + else + { /* we do not have a translation: print utf8 */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + } + n += encidx * 4; + encidx = 0; + } + } + } + + } + } + if (!buffer) + { /* allocate the buffer after the first pass */ + buffer = p = jnlib_xmalloc (n + 1); + } + else + { + *p = 0; /* make a string */ + return buffer; + } + } +} diff --git a/jnlib/utf8conv.h b/jnlib/utf8conv.h new file mode 100644 index 000000000..6e2ce9944 --- /dev/null +++ b/jnlib/utf8conv.h @@ -0,0 +1,31 @@ +/* utf8conf.h + * 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 LIBJNLIB_UTF8CONF_H +#define LIBJNLIB_UTF8CONF_H + +int set_native_charset (const char *newset); +const char *get_native_charset (void); + +char *native_to_utf8 (const char *string); +char *utf8_to_native (const char *string, size_t length, int delim); + + +#endif /*LIBJNLIB_UTF8CONF_H*/ -- cgit v1.2.3 From b7bd5e8088ae0318ca5c82daa60881ac3f7e6e54 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 23 Jun 2003 15:16:12 +0000 Subject: Fixes to the libgcrypt switch. Basically works now. --- g10/ChangeLog | 20 +++++++++++++++++ g10/import.c | 11 +++++----- g10/keyid.c | 10 ++++----- g10/keyring.c | 6 +++--- g10/mainproc.c | 11 +++++----- g10/misc.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++-------- g10/pubkey-enc.c | 2 +- 7 files changed, 96 insertions(+), 29 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 1ff227fdc..b4db7b5f0 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,23 @@ +2003-06-23 Werner Koch <wk@gnupg.org> + + * keyid.c (do_fingerprint_md): Made it work again. + +2003-06-19 Werner Koch <wk@gnupg.org> + + Fixed all "==" comparisons against error code constants to use + gpg_err_code(). + + * import.c (import_secret_one): + (import_revoke_cert): + (chk_self_sigs): + + * misc.c (openpgp_md_map_name): Check also for the Hx format. + (openpgp_cipher_map_name): Check also for the Sx format. + (pubkey_get_npkey): Adjusted for changed gcrypt API. + (pubkey_get_nskey): Ditto. + (pubkey_get_nsig): Ditto. + (pubkey_get_nenc): Ditto. + 2003-06-18 Werner Koch <wk@gnupg.org> Finished the bulk of changes for gnupg 1.9. This included diff --git a/g10/import.c b/g10/import.c index 94e8914ec..84d60a1b3 100644 --- a/g10/import.c +++ b/g10/import.c @@ -906,7 +906,8 @@ import_secret_one( const char *fname, KBNODE keyblock, /* do we have this key already in one of our secrings ? */ rc = seckey_available( keyid ); - if( rc == GPG_ERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */ + if( gpg_err_code (rc) == GPG_ERR_NO_SECKEY && !opt.merge_only ) { + /* simply insert this key */ KEYDB_HANDLE hd = keydb_new (1); /* get default resource */ @@ -977,7 +978,7 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) pk = xcalloc (1, sizeof *pk ); rc = get_pubkey( pk, keyid ); - if( rc == GPG_ERR_NO_PUBKEY ) { + if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY ) { log_info( _("key %08lX: no public key - " "can't apply revocation certificate\n"), (ulong)keyid[1]); rc = 0; @@ -1126,7 +1127,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock, { char *p=utf8_to_native(unode->pkt->pkt.user_id->name, strlen(unode->pkt->pkt.user_id->name),0); - log_info( rc == GPG_ERR_PUBKEY_ALGO ? + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key " "algorithm on user id \"%s\"\n"): _("key %08lX: invalid self-signature " @@ -1151,7 +1152,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock, else { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - log_info( rc == GPG_ERR_PUBKEY_ALGO ? + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey binding\n"), (ulong)keyid[1]); @@ -1192,7 +1193,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock, else { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - log_info( rc == GPG_ERR_PUBKEY_ALGO ? + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey revocation\n"), (ulong)keyid[1]); diff --git a/g10/keyid.c b/g10/keyid.c index 78b637481..49a316db5 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -54,15 +54,15 @@ static gcry_md_hd_t do_fingerprint_md( PKT_public_key *pk ) { gcry_md_hd_t md; - unsigned n; - unsigned nb[PUBKEY_MAX_NPKEY]; - unsigned nn[PUBKEY_MAX_NPKEY]; + 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); + gcry_md_start_debug (md,"keyid"); n = pk->version < 4 ? 8 : 6; for(i=0; i < npkey; i++ ) { size_t nbytes; @@ -74,7 +74,7 @@ do_fingerprint_md( PKT_public_key *pk ) if (gcry_mpi_print ( GCRYMPI_FMT_PGP, pp[i], &nbytes, pk->pkey[i] )) BUG (); nn[i] = nbytes; - n += 2 + nn[i]; + n += nn[i]; } gcry_md_putc ( md, 0x99 ); /* ctb */ @@ -103,8 +103,6 @@ do_fingerprint_md( PKT_public_key *pk ) } gcry_md_putc ( md, pk->pubkey_algo ); for(i=0; i < npkey; i++ ) { - gcry_md_putc ( md, nb[i]>>8); - gcry_md_putc ( md, nb[i] ); gcry_md_write( md, pp[i], nn[i] ); xfree (pp[i]); } diff --git a/g10/keyring.c b/g10/keyring.c index cc1150065..4639e9462 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -125,7 +125,7 @@ new_offset_hash_table (void) { struct off_item **tbl; - tbl = xcalloc (1,2048 * sizeof *tbl); + tbl = xcalloc (2048, sizeof *tbl); return tbl; } @@ -387,7 +387,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) save_mode = set_packet_list_mode(0); while ((rc=parse_packet (a, pkt)) != -1) { hd->found.n_packets++; - if (rc == GPG_ERR_UNKNOWN_PACKET) { + if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) { free_packet (pkt); init_packet (pkt); continue; @@ -478,7 +478,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) /* Make sure that future search operations fail immediately when * we know that we are working on a invalid keyring */ - if (rc == GPG_ERR_INV_KEYRING) + if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING) hd->current.error = rc; return rc; diff --git a/g10/mainproc.c b/g10/mainproc.c index e9b7a4b66..969c65066 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -428,7 +428,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) } free_public_key( pk ); - if( list->reason == GPG_ERR_NO_SECKEY ) { + if( gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY ) { if( is_status_enabled() ) { char buf[20]; sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], @@ -1189,7 +1189,7 @@ do_proc_packets( CTX c, iobuf_t a ) break; } } - if( rc == GPG_ERR_INV_PACKET ) + if( gpg_err_code (rc) == GPG_ERR_INV_PACKET ) write_status_text( STATUS_NODATA, "3" ); if( any_data ) rc = 0; @@ -1280,7 +1280,8 @@ check_sig_and_print( CTX c, KBNODE node ) (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); rc = do_check_sig(c, node, NULL, &is_expkey ); - if( rc == GPG_ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { + if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY + && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { if( keyserver_import_keyid ( sig->keyid )==0 ) rc = do_check_sig(c, node, NULL, &is_expkey ); } @@ -1482,14 +1483,14 @@ check_sig_and_print( CTX c, KBNODE node ) if( opt.batch && rc ) g10_exit(1); } - else { + else { char buf[50]; sprintf(buf, "%08lX%08lX %d %d %02x %lu %d", (ulong)sig->keyid[0], (ulong)sig->keyid[1], sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp, rc ); write_status_text( STATUS_ERRSIG, buf ); - if( rc == GPG_ERR_NO_PUBKEY ) { + if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY ) { buf[16] = 0; write_status_text( STATUS_NO_PUBKEY, buf ); } diff --git a/g10/misc.c b/g10/misc.c index 19586624f..5cdad1598 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -244,6 +244,9 @@ openpgp_pk_test_algo( int algo, unsigned int usage_flags ) { size_t value = usage_flags; + if (algo == GCRY_PK_ELG_E) + algo = GCRY_PK_ELG; +#warning need to handle the usage here? if (algo < 0 || algo > 110) return GPG_ERR_PUBKEY_ALGO; return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &value); @@ -292,6 +295,18 @@ int openpgp_md_map_name (const char *string) { int i = gcry_md_map_name (string); + + if (!i && (string[0]=='H' || string[0]=='h')) + { /* Didn't find it, so try the Hx format */ + long val; + char *endptr; + + string++; + + val=strtol(string,&endptr,10); + if (*string!='\0' && *endptr=='\0' && !openpgp_md_test_algo(val)) + i = val; + } return i < 0 || i > 110? 0 : i; } @@ -299,6 +314,18 @@ int openpgp_cipher_map_name (const char *string) { int i = gcry_cipher_map_name (string); + + if (!i && (string[0]=='S' || string[0]=='s')) + { /* Didn't find it, so try the Sx format */ + long val; + char *endptr; + + string++; + + val=strtol(string,&endptr,10); + if (*string!='\0' && *endptr=='\0' && !openpgp_cipher_test_algo(val)) + i = val; + } return i < 0 || i > 110? 0 : i; } @@ -703,32 +730,52 @@ parse_options(char *str,unsigned int *options,struct parse_options *opts) int pubkey_get_npkey( int algo ) { - int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 ); - return n > 0? n : 0; + size_t n; + + if (algo == GCRY_PK_ELG_E) + algo = GCRY_PK_ELG; + if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &n)) + n = 0; + return n; } /* Temporary helper. */ int pubkey_get_nskey( int algo ) { - int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 ); - return n > 0? n : 0; + size_t n; + + if (algo == GCRY_PK_ELG_E) + algo = GCRY_PK_ELG; + if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &n )) + n = 0; + return n; } /* Temporary helper. */ int pubkey_get_nsig( int algo ) { - int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 ); - return n > 0? n : 0; + size_t n; + + if (algo == GCRY_PK_ELG_E) + algo = GCRY_PK_ELG; + if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &n)) + n = 0; + return n; } /* Temporary helper. */ int pubkey_get_nenc( int algo ) { - int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 ); - return n > 0? n : 0; + size_t n; + + if (algo == GCRY_PK_ELG_E) + algo = GCRY_PK_ELG; + if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &n )) + n = 0; + return n; } @@ -788,7 +835,7 @@ mpi_write( iobuf_t out, gcry_mpi_t a ) } /**************** - * Writye a MPI to out, but in this case it is an opaque one, + * Writyeg a MPI to out, but in this case it is an opaque one, * s used vor v3 protected keys. */ int diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index b5837b24e..b08394e4a 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -190,7 +190,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) write_status(STATUS_RSA_OR_IDEA); rc = openpgp_cipher_test_algo (dek->algo); if( rc ) { - if( !opt.quiet && rc == GPG_ERR_CIPHER_ALGO ) { + if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) { log_info(_("cipher algorithm %d%s is unknown or disabled\n"), dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); if(dek->algo==CIPHER_ALGO_IDEA) -- cgit v1.2.3 From 5c46f134e22d57fafc901c95350fad11efc10516 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 27 Jun 2003 20:53:09 +0000 Subject: Key generation and signing using the OpenPGP card does rudimentary work. --- NEWS | 2 + g10/ChangeLog | 22 ++ g10/Makefile.am | 3 +- g10/build-packet.c | 10 +- g10/call-agent.c | 311 ++++++++++++++++-- g10/call-agent.h | 39 +++ g10/g10.c | 13 +- g10/gpgv.c | 2 +- g10/keyedit.c | 4 + g10/keygen.c | 926 ++++++++++++++++++++++++++++++++++++----------------- g10/parse-packet.c | 32 +- g10/passphrase.c | 2 +- g10/seckey-cert.c | 3 + g10/seskey.c | 5 + g10/sign.c | 148 +++++---- g10/tdbio.c | 5 +- 16 files changed, 1140 insertions(+), 387 deletions(-) diff --git a/NEWS b/NEWS index 5c8a8342a..794ad11f1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ Noteworthy changes in version 1.9.0 (unreleased) ------------------------------------------------ + * 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" diff --git a/g10/ChangeLog b/g10/ChangeLog index b4db7b5f0..023f66b0d 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,25 @@ +2003-06-27 Werner Koch <wk@gnupg.org> + + * seckey-cert.c (check_secret_key): Bypass the unprotection for + mode 1002. + * sign.c (do_sign): Handle card case (i.e. mode 1002). + +2003-06-26 Werner Koch <wk@gnupg.org> + + * build-packet.c (do_secret_key): Implement special protection + mode 1002. + * parse-packet.c (parse_key): Likewise. + + * keygen.c (smartcard_gen_key): New. + * call-agent.c (agent_scd_setattr): New. + +2003-06-24 Werner Koch <wk@gnupg.org> + + * Makefile.am: Removed signal.c + + * g10.c (emergency_cleanup): New. + (main): Use gnupg_init_signals and register malloc for assuan. + 2003-06-23 Werner Koch <wk@gnupg.org> * keyid.c (do_fingerprint_md): Made it work again. diff --git a/g10/Makefile.am b/g10/Makefile.am index 6940be67a..3137bb894 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -63,8 +63,7 @@ common_source = \ plaintext.c \ sig-check.c \ keylist.c \ - pkglue.c pkglue.h \ - signal.c + pkglue.c pkglue.h gpg_SOURCES = g10.c \ $(common_source) \ diff --git a/g10/build-packet.c b/g10/build-packet.c index a3177525e..afc123624 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -415,8 +415,9 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) if( sk->protect.s2k.mode == 3 ) iobuf_put(a, sk->protect.s2k.count ); - /* For out special mode 1001 we do not need an IV */ - if( sk->protect.s2k.mode != 1001 ) + /* For out special modes 1001 and 1002 we do not need an IV */ + if( sk->protect.s2k.mode != 1001 + && sk->protect.s2k.mode != 1002 ) iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); } } @@ -425,6 +426,11 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) if( sk->protect.s2k.mode == 1001 ) ; /* GnuPG extension - don't write a secret key at all */ + else if( sk->protect.s2k.mode == 1002 ) + { /* GnuPG extension - divert to OpenPGP smartcard. */ + iobuf_put(a, 0 ); /* length of the serial number or 0 for unknown. */ + /* fixme: write the serial number. */ + } else if( sk->is_protected && sk->version >= 4 ) { /* The secret key is protected - write it out as it is */ byte *p; diff --git a/g10/call-agent.c b/g10/call-agent.c index e888820cc..67aa333ee 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -47,7 +47,7 @@ #endif static ASSUAN_CONTEXT agent_ctx = NULL; -static int force_pipe_server = 0; +static int force_pipe_server = 1; /* FIXME: set this back to 0. */ struct cipher_parm_s { ASSUAN_CONTEXT ctx; @@ -61,11 +61,6 @@ struct genkey_parm_s { size_t sexplen; }; -struct learn_parm_s { - int error; - ASSUAN_CONTEXT ctx; - struct membuf *data; -}; /* Try to connect to the agent via socket or fork it off and work by @@ -292,16 +287,59 @@ start_agent (void) } -static AssuanError -membuf_data_cb (void *opaque, const void *buffer, size_t length) +/* 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) { - membuf_t *data = opaque; + char *buffer, *d; - if (buffer) - put_membuf (data, buffer, length); - return 0; + 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 */ } - + #if 0 @@ -391,25 +429,258 @@ agent_havekey (const char *hexkeygrip) } -/* Ask the agent to change the passphrase of the key identified by - HEXKEYGRIP. */ +static AssuanError +learn_status_cb (void *opaque, const char *line) +{ + struct agent_card_info_s *parm = opaque; + const char *keyword = line; + int keywordlen; + + log_debug ("got status line `%s'\n", line); + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + + if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen)) + { + parm->disp_name = unescape_status_string (line); + } + else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY_URL", keywordlen)) + { + parm->pubkey_url = unescape_status_string (line); + } + else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) + { + int no = atoi (line); + while (!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_passwd (const char *hexkeygrip) +agent_learn (struct agent_card_info_s *info) { int rc; - char line[ASSUAN_LINELENGTH]; rc = start_agent (); if (rc) return rc; - if (!hexkeygrip || strlen (hexkeygrip) != 40) + 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); +} + + + +/* 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); - snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip); - line[DIM(line)-1] = 0; + /* 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 (!spacep (line)) + line++; + while (spacep (line)) + line++; + + rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0); + 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 *keyid, 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 rc; + + init_membuf (&data, 1024); + snprintf (line, DIM(line)-1, "SCD PKSIGN %s", keyid); + 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 rc; + } + *r_buf = get_membuf (&data, r_buflen); + + return 0; +} + + + + + + + + + + + + + + + + + + + + + diff --git a/g10/call-agent.h b/g10/call-agent.h index fbb11958c..c620268f2 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -20,10 +20,46 @@ #ifndef GNUPG_G10_CALL_AGENT_H #define GNUPG_G10_CALL_AGENT_H + +struct agent_card_info_s { + int error; /* private. */ + char *disp_name; /* malloced. */ + char *pubkey_url; /* malloced. */ + char fpr1valid; + char fpr2valid; + char fpr3valid; + char fpr1[20]; + char fpr2[20]; + char fpr3[20]; +}; + +struct agent_card_genkey_s { + char fprvalid; + char fpr[20]; + u32 created_at; + gcry_mpi_t n; + gcry_mpi_t e; +}; + +/* Return card info. */ +int agent_learn (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); + /* Ask the agent to let the user change the passphrase of the secret key identified by HEXKEYGRIP. */ int agent_passwd (const char *hexkeygrip); @@ -31,4 +67,7 @@ int agent_passwd (const char *hexkeygrip); + + #endif /*GNUPG_G10_CALL_AGENT_H*/ + diff --git a/g10/g10.c b/g10/g10.c index cf6240d55..6909e0404 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -639,6 +639,7 @@ static void set_cmd( enum cmd_and_opt_values *ret_cmd, static void print_mds( const char *fname, int algo ); static void add_notation_data( const char *string, int which ); static void add_policy_url( const char *string, int which ); +static void emergency_cleanup (void); #ifdef __riscos__ RISCOS_GLOBAL_STATICS("GnuPG Heap") @@ -1191,7 +1192,7 @@ main( int argc, char **argv ) gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); may_coredump = disable_core_dumps(); - init_signals (); /* why not gnupg_init_signals. */ + gnupg_init_signals (0, emergency_cleanup); create_dotlock (NULL); /* register locking cleanup */ i18n_init(); @@ -1303,7 +1304,8 @@ main( int argc, char **argv ) maybe_setuid = 0; /* Okay, we are now working under our real uid */ - /* malloc hooks gohere ... */ + /* malloc hooks go here ... */ + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); set_native_charset (NULL); /* Try to auto set the character set */ @@ -2894,6 +2896,13 @@ main( int argc, char **argv ) return 8; /*NEVER REACHED*/ } +/* Note: This function is used by signal handlers!. */ +static void +emergency_cleanup (void) +{ + gcry_control (GCRYCTL_TERM_SECMEM ); +} + void g10_exit( int rc ) diff --git a/g10/gpgv.c b/g10/gpgv.c index 91574a78b..da108d225 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -147,7 +147,7 @@ main( int argc, char **argv ) set_strusage (my_strusage); log_set_prefix ("gpgv", 1); - init_signals(); + gnupg_init_signals(0, NULL); i18n_init(); opt.command_fd = -1; /* no command fd */ opt.pgp2_workarounds = 1; diff --git a/g10/keyedit.c b/g10/keyedit.c index 38248a3d0..11e2d870e 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -921,6 +921,10 @@ change_passphrase( KBNODE keyblock ) tty_printf(_("Secret parts of primary key are not available.\n")); no_primary_secrets = 1; } + else if( sk->protect.s2k.mode == 1002 ) { + tty_printf(_("Secret key is actually stored on a card.\n")); + no_primary_secrets = 1; + } else { tty_printf(_("Key is protected.\n")); rc = check_secret_key( sk, 0 ); diff --git a/g10/keygen.c b/g10/keygen.c index 041a495bd..328647f03 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -38,6 +38,8 @@ #include "trustdb.h" #include "status.h" #include "i18n.h" +#include "call-agent.h" + #define MAX_PREFS 30 @@ -111,8 +113,11 @@ static int nzip_prefs; static int mdc_available,ks_modify; static void do_generate_keypair( struct para_data_s *para, - struct output_control_s *outctrl ); -static int write_keyblock( iobuf_t out, KBNODE node ); + struct output_control_s *outctrl, int card); +static int write_keyblock( iobuf_t out, KBNODE node ); +static int check_smartcard (void); +static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, u32 expireval); + static void @@ -1752,7 +1757,7 @@ get_parameter_revkey( struct para_data_s *para, enum para_name key ) static int proc_parameter_file( struct para_data_s *para, const char *fname, - struct output_control_s *outctrl ) + struct output_control_s *outctrl, int card ) { struct para_data_s *r; const char *s1, *s2, *s3; @@ -1814,8 +1819,8 @@ proc_parameter_file( struct para_data_s *para, const char *fname, r = get_parameter( para, pPASSPHRASE ); if( r && *r->u.value ) { /* we have a plain text passphrase - create a DEK from it. - * It is a little bit ridiculous to keep it ih secure memory - * but becuase we do this alwasy, why not here */ + * It is a little bit ridiculous to keep it in secure memory + * but because we do this always, why not here. */ STRING2KEY *s2k; DEK *dek; @@ -1864,7 +1869,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, return -1; } - do_generate_keypair( para, outctrl ); + do_generate_keypair( para, outctrl, card); return 0; } @@ -1948,7 +1953,7 @@ read_parameter_file( const char *fname ) outctrl.dryrun = 1; else if( !ascii_strcasecmp( keyword, "%commit" ) ) { outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl ); + proc_parameter_file( para, fname, &outctrl, 0 ); release_parameter_list( para ); para = NULL; } @@ -2008,7 +2013,7 @@ read_parameter_file( const char *fname ) if( keywords[i].key == pKEYTYPE && para ) { outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl ); + proc_parameter_file( para, fname, &outctrl, 0 ); release_parameter_list( para ); para = NULL; } @@ -2036,7 +2041,7 @@ read_parameter_file( const char *fname ) } else if( para ) { outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl ); + proc_parameter_file( para, fname, &outctrl, 0 ); } if( outctrl.use_files ) { /* close open streams */ @@ -2061,113 +2066,139 @@ read_parameter_file( const char *fname ) void generate_keypair( const char *fname ) { - unsigned int nbits; - char *uid = NULL; - DEK *dek; - STRING2KEY *s2k; - int algo; - unsigned int use; - int both = 0; - u32 expire; - struct para_data_s *para = NULL; - struct para_data_s *r; - struct output_control_s outctrl; - - memset( &outctrl, 0, sizeof( outctrl ) ); - - if( opt.batch ) { - read_parameter_file( fname ); - return; + unsigned int nbits; + char *uid = NULL; + DEK *dek; + STRING2KEY *s2k; + int algo; + unsigned int use; + int both = 0; + int card = 0; + u32 expire; + struct para_data_s *para = NULL; + struct para_data_s *r; + struct output_control_s outctrl; + + memset (&outctrl, 0, sizeof (outctrl)); + + if (opt.batch) + { + read_parameter_file( fname ); + return; } - algo = ask_algo( 0, &use ); - if( !algo ) { /* default: DSA with ElG subkey of the specified size */ - both = 1; - r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); - r->next = para; - para = r; - tty_printf(_("DSA keypair will have 1024 bits.\n")); - r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYLENGTH; - strcpy( r->u.value, "1024" ); - r->next = para; - para = r; - - algo = PUBKEY_ALGO_ELGAMAL_E; - r = xcalloc (1, sizeof *r + 20 ); - r->key = pSUBKEYTYPE; - sprintf( r->u.value, "%d", algo ); - r->next = para; - para = r; + do + { + card = check_smartcard (); + if (card < 0) + return; + if (card > 1) + log_error (_("can't generate subkey here\n")); } - else { - r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo ); - r->next = para; - para = r; + while (card > 1); - if (use) { - r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYUSAGE; - sprintf( r->u.value, "%s%s", - (use & PUBKEY_USAGE_SIG)? "sign ":"", - (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); - r->next = para; - para = r; + if (card) + { + algo = PUBKEY_ALGO_RSA; + use = PUBKEY_USAGE_SIG; + } + else + algo = ask_algo (0, &use); + + if (!algo) + { /* default: DSA with ElG subkey of the specified size */ + both = 1; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); + r->next = para; + para = r; + tty_printf(_("DSA keypair will have 1024 bits.\n")); + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYLENGTH; + strcpy( r->u.value, "1024" ); + r->next = para; + para = r; + + algo = PUBKEY_ALGO_ELGAMAL_E; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pSUBKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; + } + else + { + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; + + if (use) + { + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYUSAGE; + sprintf( r->u.value, "%s%s", + (use & PUBKEY_USAGE_SIG)? "sign ":"", + (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); + r->next = para; + para = r; } - } - nbits = ask_keysize( algo ); - r = xcalloc (1, sizeof *r + 20 ); - r->key = both? pSUBKEYLENGTH : pKEYLENGTH; - sprintf( r->u.value, "%u", nbits); - r->next = para; - para = r; - - expire = ask_expire_interval(0); - r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYEXPIRE; - r->u.expire = expire; - r->next = para; - para = r; - r = xcalloc (1, sizeof *r + 20 ); - r->key = pSUBKEYEXPIRE; - r->u.expire = expire; - r->next = para; - para = r; - - uid = ask_user_id(0); - if( !uid ) { - log_error(_("Key generation canceled.\n")); - release_parameter_list( para ); - return; - } - r = xcalloc (1, sizeof *r + strlen(uid) ); - r->key = pUSERID; - strcpy( r->u.value, uid ); - r->next = para; - para = r; - - dek = ask_passphrase( &s2k ); - if( dek ) { - r = xcalloc (1, sizeof *r ); - r->key = pPASSPHRASE_DEK; - r->u.dek = dek; - r->next = para; - para = r; - r = xcalloc (1, sizeof *r ); - r->key = pPASSPHRASE_S2K; - r->u.s2k = s2k; - r->next = para; - para = r; + if (!card) + { + nbits = ask_keysize( algo ); + r = xcalloc (1, sizeof *r + 20 ); + r->key = both? pSUBKEYLENGTH : pKEYLENGTH; + sprintf( r->u.value, "%u", nbits); + r->next = para; + para = r; } + + expire = ask_expire_interval(0); + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYEXPIRE; + r->u.expire = expire; + r->next = para; + para = r; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pSUBKEYEXPIRE; + r->u.expire = expire; + r->next = para; + para = r; + + uid = ask_user_id(0); + if (!uid) + { + log_error(_("Key generation canceled.\n")); + release_parameter_list( para ); + return; + } + r = xcalloc (1, sizeof *r + strlen(uid) ); + r->key = pUSERID; + strcpy( r->u.value, uid ); + r->next = para; + para = r; - proc_parameter_file( para, "[internal]", &outctrl ); - release_parameter_list( para ); + dek = card? NULL : ask_passphrase( &s2k ); + if (dek) + { + r = xcalloc (1, sizeof *r ); + r->key = pPASSPHRASE_DEK; + r->u.dek = dek; + r->next = para; + para = r; + r = xcalloc (1, sizeof *r ); + r->key = pPASSPHRASE_S2K; + r->u.s2k = s2k; + r->next = para; + para = r; + } + + proc_parameter_file (para, "[internal]", &outctrl, card); + release_parameter_list (para); } @@ -2189,225 +2220,271 @@ print_status_key_created (int letter, PKT_public_key *pk) write_status_text (STATUS_KEY_CREATED, buf); } + + static void -do_generate_keypair( struct para_data_s *para, - struct output_control_s *outctrl ) +do_generate_keypair (struct para_data_s *para, + struct output_control_s *outctrl, int card) { - KBNODE pub_root = NULL; - KBNODE sec_root = NULL; - PKT_secret_key *sk = NULL; - const char *s; - struct revocation_key *revkey; - int rc; - int did_sub = 0; - - if( outctrl->dryrun ) { - log_info("dry-run mode - key generation skipped\n"); - return; + KBNODE pub_root = NULL; + KBNODE sec_root = NULL; + PKT_secret_key *sk = NULL; + const char *s; + struct revocation_key *revkey; + int rc; + int did_sub = 0; + + if (outctrl->dryrun) + { + log_info ("dry-run mode - key generation skipped\n"); + return; } - if( outctrl->use_files ) { - if( outctrl->pub.newfname ) { - iobuf_close(outctrl->pub.stream); - outctrl->pub.stream = NULL; - xfree ( outctrl->pub.fname ); - outctrl->pub.fname = outctrl->pub.newfname; - outctrl->pub.newfname = NULL; - - outctrl->pub.stream = iobuf_create( outctrl->pub.fname ); - if( !outctrl->pub.stream ) { - log_error("can't create `%s': %s\n", outctrl->pub.newfname, - strerror(errno) ); - return; + if (outctrl->use_files) + { + if (outctrl->pub.newfname) + { + iobuf_close (outctrl->pub.stream); + outctrl->pub.stream = NULL; + xfree (outctrl->pub.fname); + outctrl->pub.fname = outctrl->pub.newfname; + outctrl->pub.newfname = NULL; + + outctrl->pub.stream = iobuf_create (outctrl->pub.fname); + if (!outctrl->pub.stream) + { + log_error ("can't create `%s': %s\n", outctrl->pub.newfname, + strerror (errno)); + return; } - if( opt.armor ) { - outctrl->pub.afx.what = 1; - iobuf_push_filter( outctrl->pub.stream, armor_filter, - &outctrl->pub.afx ); + if (opt.armor) + { + outctrl->pub.afx.what = 1; + iobuf_push_filter (outctrl->pub.stream, armor_filter, + &outctrl->pub.afx); } } - if( outctrl->sec.newfname ) { - iobuf_close(outctrl->sec.stream); - outctrl->sec.stream = NULL; - xfree ( outctrl->sec.fname ); - outctrl->sec.fname = outctrl->sec.newfname; - outctrl->sec.newfname = NULL; - - outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); - if( !outctrl->sec.stream ) { - log_error("can't create `%s': %s\n", outctrl->sec.newfname, - strerror(errno) ); - return; + if (outctrl->sec.newfname) + { + iobuf_close (outctrl->sec.stream); + outctrl->sec.stream = NULL; + xfree (outctrl->sec.fname); + outctrl->sec.fname = outctrl->sec.newfname; + outctrl->sec.newfname = NULL; + + outctrl->sec.stream = iobuf_create (outctrl->sec.fname); + if (!outctrl->sec.stream) + { + log_error ("can't create `%s': %s\n", outctrl->sec.newfname, + strerror (errno)); + return; } - if( opt.armor ) { - outctrl->sec.afx.what = 5; - iobuf_push_filter( outctrl->sec.stream, armor_filter, - &outctrl->sec.afx ); + if (opt.armor) + { + outctrl->sec.afx.what = 5; + iobuf_push_filter (outctrl->sec.stream, armor_filter, + &outctrl->sec.afx); } } - assert( outctrl->pub.stream ); - assert( outctrl->sec.stream ); - if( opt.verbose ) { - log_info(_("writing public key to `%s'\n"), outctrl->pub.fname ); - log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname ); - } + assert (outctrl->pub.stream); + assert (outctrl->sec.stream); + if (opt.verbose) + { + log_info (_("writing public key to `%s'\n"), outctrl->pub.fname); + if (card) + log_info (_("writing secret key stub to `%s'\n"), + outctrl->sec.fname); + else + log_info (_("writing secret key to `%s'\n"), outctrl->sec.fname); + } } - /* we create the packets as a tree of kbnodes. Because the structure - * we create is known in advance we simply generate a linked list - * The first packet is a dummy comment packet which we flag - * as deleted. The very first packet must always be a KEY packet. - */ - pub_root = make_comment_node("#"); delete_kbnode(pub_root); - sec_root = make_comment_node("#"); delete_kbnode(sec_root); - - rc = do_create( get_parameter_algo( para, pKEYTYPE ), - get_parameter_uint( para, pKEYLENGTH ), - pub_root, sec_root, - get_parameter_dek( para, pPASSPHRASE_DEK ), - get_parameter_s2k( para, pPASSPHRASE_S2K ), - &sk, - get_parameter_u32( para, pKEYEXPIRE ) ); - - if(!rc && (revkey=get_parameter_revkey(para,pREVOKER))) - { - rc=write_direct_sig(pub_root,pub_root,sk,revkey); - if(!rc) - write_direct_sig(sec_root,pub_root,sk,revkey); - } - - if( !rc && (s=get_parameter_value(para, pUSERID)) ) { - write_uid(pub_root, s ); - if( !rc ) - write_uid(sec_root, s ); - if( !rc ) - rc = write_selfsig(pub_root, pub_root, sk, - get_parameter_uint (para, pKEYUSAGE)); - if( !rc ) - rc = write_selfsig(sec_root, pub_root, sk, - get_parameter_uint (para, pKEYUSAGE)); - } - - if( get_parameter( para, pSUBKEYTYPE ) ) { - rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ), - get_parameter_uint( para, pSUBKEYLENGTH ), - pub_root, sec_root, - get_parameter_dek( para, pPASSPHRASE_DEK ), - get_parameter_s2k( para, pPASSPHRASE_S2K ), - NULL, - get_parameter_u32( para, pSUBKEYEXPIRE ) ); - if( !rc ) - rc = write_keybinding(pub_root, pub_root, sk, - get_parameter_uint (para, pSUBKEYUSAGE)); - if( !rc ) - rc = write_keybinding(sec_root, pub_root, sk, - get_parameter_uint (para, pSUBKEYUSAGE)); - did_sub = 1; + /* We create the packets as a tree of kbnodes. Because the structure + * we create is known in advance we simply generate a linked list. + * The first packet is a dummy comment packet which we flag + * as deleted. The very first packet must always be a KEY packet. + */ + pub_root = make_comment_node ("#"); + delete_kbnode (pub_root); + sec_root = make_comment_node ("#"); + delete_kbnode (sec_root); + if (!card) + { + rc = do_create (get_parameter_algo (para, pKEYTYPE), + get_parameter_uint (para, pKEYLENGTH), + pub_root, sec_root, + get_parameter_dek (para, pPASSPHRASE_DEK), + get_parameter_s2k (para, pPASSPHRASE_S2K), + &sk, get_parameter_u32 (para, pKEYEXPIRE)); + } + else + { + rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root, + get_parameter_u32 (para, pKEYEXPIRE)); + if (!rc) + { + sk = sec_root->next->pkt->pkt.secret_key; + assert (sk); + } + } + if (!rc && (revkey = get_parameter_revkey (para, pREVOKER))) + { + rc = write_direct_sig (pub_root, pub_root, sk, revkey); + if (!rc) + write_direct_sig (sec_root, pub_root, sk, revkey); + } - if( !rc && outctrl->use_files ) { /* direct write to specified files */ - rc = write_keyblock( outctrl->pub.stream, pub_root ); - if( rc ) - log_error("can't write public key: %s\n", gpg_strerror (rc) ); - if( !rc ) { - rc = write_keyblock( outctrl->sec.stream, sec_root ); - if( rc ) - log_error("can't write secret key: %s\n", gpg_strerror (rc) ); + if (!rc && (s = get_parameter_value (para, pUSERID))) + { + write_uid (pub_root, s); + if (!rc) + write_uid (sec_root, s); + if (!rc) + rc = write_selfsig (pub_root, pub_root, sk, + get_parameter_uint (para, pKEYUSAGE)); + if (!rc) + rc = write_selfsig (sec_root, pub_root, sk, + get_parameter_uint (para, pKEYUSAGE)); + } + + if (get_parameter (para, pSUBKEYTYPE)) + { + rc = do_create (get_parameter_algo (para, pSUBKEYTYPE), + get_parameter_uint (para, pSUBKEYLENGTH), + pub_root, sec_root, + get_parameter_dek (para, pPASSPHRASE_DEK), + get_parameter_s2k (para, pPASSPHRASE_S2K), + NULL, get_parameter_u32 (para, pSUBKEYEXPIRE)); + if (!rc) + rc = write_keybinding (pub_root, pub_root, sk, + get_parameter_uint (para, pSUBKEYUSAGE)); + if (!rc) + rc = write_keybinding (sec_root, pub_root, sk, + get_parameter_uint (para, pSUBKEYUSAGE)); + did_sub = 1; + } + + + if (!rc && outctrl->use_files) + { /* direct write to specified files */ + rc = write_keyblock (outctrl->pub.stream, pub_root); + if (rc) + log_error ("can't write public key: %s\n", gpg_strerror (rc)); + if (!rc) + { + rc = write_keyblock (outctrl->sec.stream, sec_root); + if (rc) + log_error ("can't write secret key: %s\n", gpg_strerror (rc)); } } - else if( !rc ) { /* write to the standard keyrings */ - KEYDB_HANDLE pub_hd = keydb_new (0); - KEYDB_HANDLE sec_hd = keydb_new (1); + else if (!rc) + { /* write to the standard keyrings */ + KEYDB_HANDLE pub_hd = keydb_new (0); + KEYDB_HANDLE sec_hd = keydb_new (1); - /* FIXME: we may have to create the keyring first */ - rc = keydb_locate_writable (pub_hd, NULL); - if (rc) - log_error (_("no writable public keyring found: %s\n"), - gpg_strerror (rc)); + /* FIXME: we may have to create the keyring first */ + rc = keydb_locate_writable (pub_hd, NULL); + if (rc) + log_error (_("no writable public keyring found: %s\n"), + gpg_strerror (rc)); - if (!rc) { - rc = keydb_locate_writable (sec_hd, NULL); - if (rc) - log_error (_("no writable secret keyring found: %s\n"), - gpg_strerror (rc)); - } + if (!rc) + { + rc = keydb_locate_writable (sec_hd, NULL); + if (rc) + log_error (_("no writable secret keyring found: %s\n"), + gpg_strerror (rc)); + } - if (!rc && opt.verbose) { - log_info(_("writing public key to `%s'\n"), - keydb_get_resource_name (pub_hd)); - log_info(_("writing secret key to `%s'\n"), - keydb_get_resource_name (sec_hd)); - } + if (!rc && opt.verbose) + { + log_info (_("writing public key to `%s'\n"), + keydb_get_resource_name (pub_hd)); + if (card) + log_info (_("writing secret key stub to `%s'\n"), + keydb_get_resource_name (sec_hd)); + else + log_info (_("writing secret key to `%s'\n"), + keydb_get_resource_name (sec_hd)); + } - if (!rc) { - rc = keydb_insert_keyblock (pub_hd, pub_root); - if (rc) - log_error (_("error writing public keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), gpg_strerror (rc)); - } + if (!rc) + { + rc = keydb_insert_keyblock (pub_hd, pub_root); + if (rc) + log_error (_("error writing public keyring `%s': %s\n"), + keydb_get_resource_name (pub_hd), gpg_strerror (rc)); + } - if (!rc) { - rc = keydb_insert_keyblock (sec_hd, sec_root); - if (rc) - log_error (_("error writing secret keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), gpg_strerror (rc)); - } + if (!rc) + { + rc = keydb_insert_keyblock (sec_hd, sec_root); + if (rc) + log_error (_("error writing secret keyring `%s': %s\n"), + keydb_get_resource_name (pub_hd), gpg_strerror (rc)); + } + + keydb_release (pub_hd); + keydb_release (sec_hd); + + if (!rc) + { + int no_enc_rsa = + get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_RSA + && get_parameter_uint (para, pKEYUSAGE) + && !(get_parameter_uint (para, pKEYUSAGE) & PUBKEY_USAGE_ENC); + PKT_public_key *pk = find_kbnode (pub_root, + PKT_PUBLIC_KEY)->pkt->pkt. + public_key; + + update_ownertrust (pk, + ((get_ownertrust (pk) & ~TRUST_MASK) + | TRUST_ULTIMATE)); + + if (!opt.batch) + { + tty_printf (_("public and secret key created and signed.\n")); + tty_printf (_("key marked as ultimately trusted.\n")); + tty_printf ("\n"); + list_keyblock (pub_root, 0, 1, NULL); + } - keydb_release (pub_hd); - keydb_release (sec_hd); - - if (!rc) { - int no_enc_rsa = - get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA - && get_parameter_uint( para, pKEYUSAGE ) - && !(get_parameter_uint( para,pKEYUSAGE) & PUBKEY_USAGE_ENC); - PKT_public_key *pk = find_kbnode (pub_root, - PKT_PUBLIC_KEY)->pkt->pkt.public_key; - - update_ownertrust (pk, - ((get_ownertrust (pk) & ~TRUST_MASK) - | TRUST_ULTIMATE )); - - if (!opt.batch) { - tty_printf(_("public and secret key created and signed.\n") ); - tty_printf(_("key marked as ultimately trusted.\n") ); - tty_printf("\n"); - list_keyblock(pub_root,0,1,NULL); - } - - if( !opt.batch - && ( get_parameter_algo( para, pKEYTYPE ) == PUBKEY_ALGO_DSA - || no_enc_rsa ) - && !get_parameter( para, pSUBKEYTYPE ) ) + if (!opt.batch + && (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_DSA + || no_enc_rsa) && !get_parameter (para, pSUBKEYTYPE)) { - tty_printf(_("Note that this key cannot be used for " - "encryption. You may want to use\n" - "the command \"--edit-key\" to generate a " - "secondary key for this purpose.\n") ); + tty_printf (_("Note that this key cannot be used for " + "encryption. You may want to use\n" + "the command \"--edit-key\" to generate a " + "secondary key for this purpose.\n")); } } } - if( rc ) { - if( opt.batch ) - log_error("key generation failed: %s\n", gpg_strerror (rc) ); - else - tty_printf(_("Key generation failed: %s\n"), gpg_strerror (rc) ); + if (rc) + { + if (opt.batch) + log_error ("key generation failed: %s\n", gpg_strerror (rc)); + else + tty_printf (_("Key generation failed: %s\n"), gpg_strerror (rc)); } - else { - PKT_public_key *pk = find_kbnode (pub_root, - PKT_PUBLIC_KEY)->pkt->pkt.public_key; - print_status_key_created (did_sub? 'B':'P', pk); + else + { + PKT_public_key *pk = find_kbnode (pub_root, + PKT_PUBLIC_KEY)->pkt->pkt.public_key; + print_status_key_created (did_sub ? 'B' : 'P', pk); } - release_kbnode( pub_root ); - release_kbnode( sec_root ); - if( sk ) /* the unprotected secret key */ - free_secret_key(sk); + + release_kbnode (pub_root); + release_kbnode (sec_root); + if (sk && !card) /* The unprotected secret key unless we have */ + free_secret_key (sk); /* shallow copy in card mode. */ } @@ -2534,3 +2611,268 @@ write_keyblock( iobuf_t out, KBNODE node ) } return 0; } + + +static void +show_sha1_fpr (const unsigned char *fpr) +{ + int i; + + if (fpr) + { + for (i=0; i < 20 ; i+=2, fpr += 2 ) + { + if (i == 10 ) + tty_printf (" "); + tty_printf (" %02X%02X", *fpr, fpr[1]); + } + } + else + tty_printf ("[none]"); + tty_printf ("\n"); +} + +static void +show_smartcard (struct agent_card_info_s *info) +{ + /* FIXME: Sanitize what we show. */ + tty_printf ("Name of cardholder: %s\n", + info->disp_name && *info->disp_name? info->disp_name + : "[not set]"); + tty_printf ("URL of public key : %s\n", + info->pubkey_url && *info->pubkey_url? info->pubkey_url + : "[not set]"); + tty_printf ("Signature key ....: "); + show_sha1_fpr (info->fpr1valid? info->fpr1:NULL); + tty_printf ("Encryption key....: "); + show_sha1_fpr (info->fpr2valid? info->fpr2:NULL); + tty_printf ("Authentication key: "); + show_sha1_fpr (info->fpr3valid? info->fpr3:NULL); +} + + +static char * +smartcard_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 +smartcard_change_name (const char *current_name) +{ + char *surname = NULL, *givenname = NULL; + char *isoname, *p; + int rc; + + surname = smartcard_get_one_name ("keygen.smartcard.surname", + _("Cardholder's surname: ")); + givenname = smartcard_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 = '<'; + + 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)); + + return rc; +} + + +/* Check whether a smartcatrd is available and alow to select it as + the target for key generation. + + Return values: -1 = Quit generation + 0 = No smartcard + 1 = Generate primary key + 2 = generate subkey +*/ +static int +check_smartcard (void) +{ + struct agent_card_info_s info; + int rc; + + rc = agent_learn (&info); + if (rc) + { + tty_printf (_("OpenPGP card not available: %s\n"), + gpg_strerror (rc)); + return 0; + } + + tty_printf (_("OpenPGP card with serial number %s detected\n"), "xxx"); + + + for (;;) + { + char *answer; + int reread = 0; + + tty_printf ("\n"); + show_smartcard (&info); + + tty_printf ("\n" + "N - change cardholder name\n" + "U - change public key URL\n" + "1 - generate signature key\n" + "2 - generate encryption key\n" + "3 - generate authentication key\n" + "Q - quit\n" + "\n"); + + answer = cpr_get("keygen.smartcard.menu",_("Your selection? ")); + cpr_kill_prompt(); + if (strlen (answer) != 1) + continue; + + rc = 0; + if ( *answer == 'N' || *answer == 'n') + { + if (!smartcard_change_name (info.disp_name)) + reread = 1; + } + else if ( *answer == 'U' || *answer == 'u') + { + } + else if ( *answer == '1' || *answer == '2') + { + rc = *answer - '0'; + break; + } + else if ( *answer == '3' ) + { + tty_printf (_("Generation of authentication key" + " not yet implemented\n")); + } + else if ( *answer == 'q' || *answer == 'Q') + { + rc = -1; + break; + } + + if (reread) + { + xfree (info.disp_name); info.disp_name = NULL; + xfree (info.pubkey_url); info.pubkey_url = NULL; + rc = agent_learn (&info); + if (rc) + { + tty_printf (_("OpenPGP card not anymore available: %s\n"), + gpg_strerror (rc)); + g10_exit (1); + } + reread = 0; + } + } + + xfree (info.disp_name); + xfree (info.pubkey_url); + + return rc; +} + + + +static int +gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, + u32 expireval) +{ + int rc; + struct agent_card_genkey_s info; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + + assert (algo == PUBKEY_ALGO_RSA); + + rc = agent_scd_genkey (&info, keyno, 0); + if (gpg_err_code (rc) == GPG_ERR_EEXIST) + { + tty_printf ("\n"); + log_error ("WARNING: key does already exists!\n"); + tty_printf ("\n"); + if ( cpr_get_answer_is_yes( "keygen.card.replace_key", + _("Replace existing key? "))) + rc = agent_scd_genkey (&info, keyno, 1); + } + + if (rc) + { + log_error ("key generation failed: %s\n", gpg_strerror (rc)); + return rc; + } + if ( !info.n || !info.e ) + { + log_error ("communication error with SCD\n"); + gcry_mpi_release (info.n); + gcry_mpi_release (info.e); + return gpg_error (GPG_ERR_GENERAL); + } + + + pk = xcalloc (1, sizeof *pk ); + sk = xcalloc (1, sizeof *sk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if (expireval) + sk->expiredate = pk->expiredate = pk->timestamp + expireval; + sk->pubkey_algo = pk->pubkey_algo = algo; + pk->pkey[0] = info.n; + pk->pkey[1] = info.e; + sk->skey[0] = mpi_copy (pk->pkey[0]); + sk->skey[1] = mpi_copy (pk->pkey[1]); + sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->is_protected = 1; + sk->protect.s2k.mode = 1002; + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = keyno == 1 ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = keyno == 1 ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + return 0; +} + diff --git a/g10/parse-packet.c b/g10/parse-packet.c index c1a716b1d..fc9e2559f 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1634,6 +1634,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, break; case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" ); break; + case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K"); + break; default: if( list_mode ) printf( "\tunknown %sS2K %d\n", @@ -1669,6 +1671,31 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, printf("\tprotect count: %lu\n", (ulong)sk->protect.s2k.count); } + else if( sk->protect.s2k.mode == 1002 ) { + size_t snlen; + /* Read the serial number. */ + if (pktlen < 1) { + rc = GPG_ERR_INV_PACKET; + goto leave; + } + snlen = iobuf_get (inp); + pktlen--; + if (pktlen < snlen || snlen == -1) { + rc = GPG_ERR_INV_PACKET; + goto leave; + } + + if( list_mode ) { + printf("\tserial-number: "); + for (;snlen; snlen--) + printf ("%02X", (unsigned int)iobuf_get_noeof (inp)); + putchar ('\n'); + } + else { + for (;snlen; snlen--) + iobuf_get_noeof (inp); + } + } } /* Note that a sk->protect.algo > 110 is illegal, but I'm not erroring on it here as otherwise there would be no @@ -1698,6 +1725,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, } if( sk->protect.s2k.mode == 1001 ) sk->protect.ivlen = 0; + else if( sk->protect.s2k.mode == 1002 ) + sk->protect.ivlen = 0; if( pktlen < sk->protect.ivlen ) { rc = GPG_ERR_INV_PACKET; @@ -1719,7 +1748,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, * If the user is so careless, not to protect his secret key, * we can assume, that he operates an open system :=(. * So we put the key into secure memory when we unprotect it. */ - if( sk->protect.s2k.mode == 1001 ) { + if( sk->protect.s2k.mode == 1001 + || sk->protect.s2k.mode == 1002 ) { /* better set some dummy stuff here */ sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10); pktlen = 0; diff --git a/g10/passphrase.c b/g10/passphrase.c index 41cd31f91..d00340109 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -794,7 +794,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, tryagain_text = _(tryagain_text); /* We allocate 2 time the needed space for atext so that there - is nenough space for escaping */ + is enough space for escaping */ line = xmalloc (15 + 46 + 3*strlen (tryagain_text) + 3*strlen (atext) + 2); strcpy (line, "GET_PASSPHRASE "); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 573c78f7a..dff463c53 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -253,6 +253,9 @@ check_secret_key( PKT_secret_key *sk, int n ) int rc = gpg_error (GPG_ERR_BAD_PASSPHRASE); int i,mode; + if (sk && sk->is_protected && sk->protect.s2k.mode == 1002) + return 0; /* Let the scdaemon handle it. */ + if(n<0) { n=abs(n); diff --git a/g10/seskey.c b/g10/seskey.c index 9eeed2c74..5d0490cdf 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -231,3 +231,8 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo, return frame; } + + + + + diff --git a/g10/sign.c b/g10/sign.c index fa9e9ea3f..86159a4a1 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -249,74 +249,94 @@ static int do_sign( PKT_secret_key *sk, PKT_signature *sig, MD_HANDLE md, int digest_algo ) { - gcry_mpi_t frame; - byte *dp; - int rc; - - if( sk->timestamp > sig->timestamp ) { - ulong d = sk->timestamp - sig->timestamp; - log_info( d==1 ? _("key has been created %lu second " - "in future (time warp or clock problem)\n") - : _("key has been created %lu seconds " - "in future (time warp or clock problem)\n"), d ); - if( !opt.ignore_time_conflict ) - return GPG_ERR_TIME_CONFLICT; + gcry_mpi_t frame; + byte *dp; + int rc; + + if( sk->timestamp > sig->timestamp ) { + ulong d = sk->timestamp - sig->timestamp; + log_info( d==1 ? _("key has been created %lu second " + "in future (time warp or clock problem)\n") + : _("key has been created %lu seconds " + "in future (time warp or clock problem)\n"), d ); + if( !opt.ignore_time_conflict ) + return GPG_ERR_TIME_CONFLICT; + } + + print_pubkey_algo_note(sk->pubkey_algo); + + if( !digest_algo ) + digest_algo = gcry_md_get_algo(md); + + print_digest_algo_note( digest_algo ); + dp = gcry_md_read ( md, digest_algo ); + sig->digest_algo = digest_algo; + sig->digest_start[0] = dp[0]; + sig->digest_start[1] = dp[1]; + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { /* FIXME: Note that we do only support RSA for now. */ + char *rbuf; + size_t rbuflen; + + /* FIXME: We need to pass the correct keyid or better the + fingerprint to the scdaemon. */ + rc = agent_scd_pksign ("nokeyid", digest_algo, + gcry_md_read (md, digest_algo), + gcry_md_get_algo_dlen (digest_algo), + &rbuf, &rbuflen); + if (!rc) + { + unsigned int nbytes = rbuflen; + if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, rbuf, &nbytes )) + BUG (); + } } - - - print_pubkey_algo_note(sk->pubkey_algo); - - if( !digest_algo ) - digest_algo = gcry_md_get_algo(md); - - print_digest_algo_note( digest_algo ); - dp = gcry_md_read ( md, digest_algo ); - sig->digest_algo = digest_algo; - sig->digest_start[0] = dp[0]; - sig->digest_start[1] = dp[1]; - frame = encode_md_value( sk->pubkey_algo, md, - digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); - if (!frame) + else + { + frame = encode_md_value( sk->pubkey_algo, md, + digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); + if (!frame) return GPG_ERR_GENERAL; - rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); - gcry_mpi_release (frame); - if (!rc && !opt.no_sig_create_check) { - /* check that the signature verification worked and nothing is - * fooling us e.g. by a bug in the signature create - * code or by deliberately introduced faults. */ - PKT_public_key *pk = xcalloc (1,sizeof *pk); - - if( get_pubkey( pk, sig->keyid ) ) - rc = GPG_ERR_NO_PUBKEY; - else { - frame = encode_md_value (pk->pubkey_algo, md, - sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), 0); - if (!frame) - rc = GPG_ERR_GENERAL; - else - rc = pk_verify (pk->pubkey_algo, frame, - sig->data, pk->pkey); - gcry_mpi_release (frame); - } - if (rc) - log_error (_("checking created signature failed: %s\n"), - gpg_strerror (rc)); - free_public_key (pk); + rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); + gcry_mpi_release (frame); } - if( rc ) - log_error(_("signing failed: %s\n"), gpg_strerror (rc) ); + if (!rc && !opt.no_sig_create_check) { + /* check that the signature verification worked and nothing is + * fooling us e.g. by a bug in the signature create + * code or by deliberately introduced faults. */ + PKT_public_key *pk = xcalloc (1,sizeof *pk); + + if( get_pubkey( pk, sig->keyid ) ) + rc = GPG_ERR_NO_PUBKEY; else { - if( opt.verbose ) { - char *ustr = get_user_id_string_printable (sig->keyid); - log_info(_("%s/%s signature from: \"%s\"\n"), - gcry_pk_algo_name (sk->pubkey_algo), - gcry_md_algo_name (sig->digest_algo), - ustr ); - xfree (ustr); - } + frame = encode_md_value (pk->pubkey_algo, md, + sig->digest_algo, + mpi_get_nbits(pk->pkey[0]), 0); + if (!frame) + rc = GPG_ERR_GENERAL; + else + rc = pk_verify (pk->pubkey_algo, frame, + sig->data, pk->pkey); + gcry_mpi_release (frame); } - return rc; + if (rc) + log_error (_("checking created signature failed: %s\n"), + gpg_strerror (rc)); + free_public_key (pk); + } + if( rc ) + log_error(_("signing failed: %s\n"), gpg_strerror (rc) ); + else { + if( opt.verbose ) { + char *ustr = get_user_id_string_printable (sig->keyid); + log_info(_("%s/%s signature from: \"%s\"\n"), + gcry_pk_algo_name (sk->pubkey_algo), + gcry_md_algo_name (sig->digest_algo), + ustr ); + xfree (ustr); + } + } + return rc; } @@ -1170,7 +1190,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) * SIGVERSION gives the minimal required signature packet version; * this is needed so that special properties like local sign are not * applied (actually: dropped) when a v3 key is used. TIMESTAMP is - * the timestamp to use for the signature. 0 means "now" */ + * the timestamp to use for the signature. 0 means "now". */ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, diff --git a/g10/tdbio.c b/g10/tdbio.c index d8af2ef8a..39239be20 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -372,10 +372,11 @@ tdbio_end_transaction() else is_locked = 1; } - block_all_signals(); +#warning block_all_signals is not yet available in ../common/signals.c + /* block_all_signals(); */ in_transaction = 0; rc = tdbio_sync(); - unblock_all_signals(); +/* unblock_all_signals(); */ if( !opt.lock_once ) { if( !release_dotlock( lockhandle ) ) is_locked = 0; -- cgit v1.2.3 From 39046ea7ec221efa9db946230ddc9fb3e65d19ab Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 1 Jul 2003 08:34:45 +0000 Subject: * app-openpgp.c (store_fpr): Fixed fingerprint calculation. * keygen.c (gen_card_key): Obviously we should use the creation date received from SCDAEMON, so that the fingerprints will match. * sign.c (do_sign): Pass the serialno to the sign code. * keyid.c (serialno_and_fpr_from_sk): New. --- g10/ChangeLog | 20 ++++++++++++++++++++ g10/build-packet.c | 9 ++++++--- g10/call-agent.c | 52 +++++++++++++++++++++++++++------------------------- g10/call-agent.h | 1 + g10/keydb.h | 6 +++++- g10/keygen.c | 48 ++++++++++++++++++++++++++++++++++++++---------- g10/keyid.c | 30 +++++++++++++++++++++++++++++- g10/packet.h | 2 +- g10/parse-packet.c | 23 ++++++++--------------- g10/seskey.c | 6 ++++-- g10/sign.c | 7 ++++--- 11 files changed, 143 insertions(+), 61 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 023f66b0d..bf394f211 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,23 @@ +2003-07-01 Werner Koch <wk@gnupg.org> + + * keygen.c (gen_card_key): Obviously we should use the creation + date received from SCDAEMON, so that the fingerprints will match. + * sign.c (do_sign): Pass the serialno to the sign code. + * keyid.c (serialno_and_fpr_from_sk): New. + +2003-06-30 Werner Koch <wk@gnupg.org> + + * call-agent.h (agent_card_info_s): Add field serialno. + * call-agent.c (store_serialno): New. + (learn_status_cb): Store the serial number. + * keygen.c (gen_card_key): Store the serial number + (check_smartcard): New argument to return the serial number. + (generate_keypair): Get the serial number from check_smartcard and + store it as a parameter. + * parse-packet.c (parse_key): Use the protect.iv field to store the + serial number. + * build-packet.c (do_secret_key): Write the serial number. + 2003-06-27 Werner Koch <wk@gnupg.org> * seckey-cert.c (check_secret_key): Bypass the unprotection for diff --git a/g10/build-packet.c b/g10/build-packet.c index afc123624..a24bdfcc6 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -415,7 +415,7 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) if( sk->protect.s2k.mode == 3 ) iobuf_put(a, sk->protect.s2k.count ); - /* For out special modes 1001 and 1002 we do not need an IV */ + /* For our special modes 1001 and 1002 we do not need an IV */ if( sk->protect.s2k.mode != 1001 && sk->protect.s2k.mode != 1002 ) iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); @@ -428,8 +428,11 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) ; /* GnuPG extension - don't write a secret key at all */ else if( sk->protect.s2k.mode == 1002 ) { /* GnuPG extension - divert to OpenPGP smartcard. */ - iobuf_put(a, 0 ); /* length of the serial number or 0 for unknown. */ - /* fixme: write the serial number. */ + iobuf_put(a, sk->protect.ivlen ); /* length of the serial + number or 0 for no serial + number. */ + /* The serial number gets stored in the IV field. */ + iobuf_write(a, sk->protect.iv, sk->protect.ivlen); } else if( sk->is_protected && sk->version >= 4 ) { /* The secret key is protected - write it out as it is */ diff --git a/g10/call-agent.c b/g10/call-agent.c index 67aa333ee..d38e4c0fc 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -340,6 +340,26 @@ unhexify_fpr (const char *hexstr, unsigned char *fpr) 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 @@ -442,7 +462,11 @@ learn_status_cb (void *opaque, const char *line) while (spacep (line)) line++; - if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen)) + if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) + { + parm->serialno = store_serialno (line); + } + else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen)) { parm->disp_name = unescape_status_string (line); } @@ -619,7 +643,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length) /* Send a sign command to the scdaemon via gpg-agent's pass thru mechanism. */ int -agent_scd_pksign (const char *keyid, int hashalgo, +agent_scd_pksign (const char *serialno, int hashalgo, const unsigned char *indata, size_t indatalen, char **r_buf, size_t *r_buflen) { @@ -649,7 +673,7 @@ agent_scd_pksign (const char *keyid, int hashalgo, return rc; init_membuf (&data, 1024); - snprintf (line, DIM(line)-1, "SCD PKSIGN %s", keyid); + 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); @@ -662,25 +686,3 @@ agent_scd_pksign (const char *keyid, int hashalgo, return 0; } - - - - - - - - - - - - - - - - - - - - - - diff --git a/g10/call-agent.h b/g10/call-agent.h index c620268f2..2169a5319 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -23,6 +23,7 @@ struct agent_card_info_s { int error; /* private. */ + char *serialno; /* malloced hex string. */ char *disp_name; /* malloced. */ char *pubkey_url; /* malloced. */ char fpr1valid; diff --git a/g10/keydb.h b/g10/keydb.h index 6652db32a..4920e88a1 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -1,5 +1,5 @@ /* keydb.h - Key database - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -259,6 +259,10 @@ 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 ); diff --git a/g10/keygen.c b/g10/keygen.c index 328647f03..5dab70ff1 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -61,7 +61,8 @@ enum para_name { pSUBKEYEXPIRE, /* in n seconds */ pPASSPHRASE, pPASSPHRASE_DEK, - pPASSPHRASE_S2K + pPASSPHRASE_S2K, + pSERIALNO }; struct para_data_s { @@ -115,8 +116,9 @@ static int mdc_available,ks_modify; static void do_generate_keypair( struct para_data_s *para, struct output_control_s *outctrl, int card); static int write_keyblock( iobuf_t out, KBNODE node ); -static int check_smartcard (void); -static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, u32 expireval); +static int check_smartcard (char **); +static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, + u32 expireval, struct para_data_s *para); @@ -2078,6 +2080,7 @@ generate_keypair( const char *fname ) struct para_data_s *para = NULL; struct para_data_s *r; struct output_control_s outctrl; + char *serialno = NULL; memset (&outctrl, 0, sizeof (outctrl)); @@ -2089,7 +2092,8 @@ generate_keypair( const char *fname ) do { - card = check_smartcard (); + xfree (serialno); serialno = NULL; + card = check_smartcard (&serialno); if (card < 0) return; if (card > 1) @@ -2097,6 +2101,16 @@ generate_keypair( const char *fname ) } while (card > 1); + if (serialno) + { + r = xcalloc (1, sizeof *r + strlen (serialno) ); + r->key = pSERIALNO; + strcpy( r->u.value, serialno); + r->next = para; + para = r; + xfree (serialno); serialno = NULL; + } + if (card) { algo = PUBKEY_ALGO_RSA; @@ -2156,7 +2170,7 @@ generate_keypair( const char *fname ) r->next = para; para = r; } - + expire = ask_expire_interval(0); r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYEXPIRE; @@ -2322,7 +2336,7 @@ do_generate_keypair (struct para_data_s *para, else { rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root, - get_parameter_u32 (para, pKEYEXPIRE)); + get_parameter_u32 (para, pKEYEXPIRE), para); if (!rc) { sk = sec_root->next->pkt->pkt.secret_key; @@ -2725,7 +2739,7 @@ smartcard_change_name (const char *current_name) 2 = generate subkey */ static int -check_smartcard (void) +check_smartcard (char **r_serialno) { struct agent_card_info_s info; int rc; @@ -2738,7 +2752,8 @@ check_smartcard (void) return 0; } - tty_printf (_("OpenPGP card with serial number %s detected\n"), "xxx"); + tty_printf (_("OpenPGP card no. %s detected\n"), + info.serialno? info.serialno : "[none]"); for (;;) @@ -2790,6 +2805,7 @@ check_smartcard (void) if (reread) { + xfree (info.serialno); info.serialno = NULL; xfree (info.disp_name); info.disp_name = NULL; xfree (info.pubkey_url); info.pubkey_url = NULL; rc = agent_learn (&info); @@ -2803,6 +2819,10 @@ check_smartcard (void) } } + if (r_serialno && rc > 0) + *r_serialno = info.serialno; + else + xfree (info.serialno); xfree (info.disp_name); xfree (info.pubkey_url); @@ -2813,9 +2833,10 @@ check_smartcard (void) static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, - u32 expireval) + u32 expireval, struct para_data_s *para) { int rc; + const char *s; struct agent_card_genkey_s info; PACKET *pkt; PKT_secret_key *sk; @@ -2850,7 +2871,7 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, pk = xcalloc (1, sizeof *pk ); sk = xcalloc (1, sizeof *sk ); - sk->timestamp = pk->timestamp = make_timestamp(); + sk->timestamp = pk->timestamp = info.created_at; sk->version = pk->version = 4; if (expireval) sk->expiredate = pk->expiredate = pk->timestamp + expireval; @@ -2862,6 +2883,13 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); sk->is_protected = 1; sk->protect.s2k.mode = 1002; + s = get_parameter_value (para, pSERIALNO); + if (s) + { + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); + } pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = keyno == 1 ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; diff --git a/g10/keyid.c b/g10/keyid.c index 49a316db5..54a79bcdb 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -62,7 +62,6 @@ do_fingerprint_md( PKT_public_key *pk ) gcry_md_open (&md, pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); - gcry_md_start_debug (md,"keyid"); n = pk->version < 4 ? 8 : 6; for(i=0; i < npkey; i++ ) { size_t nbytes; @@ -575,4 +574,33 @@ fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) } +/* 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; +} + + + + + + + diff --git a/g10/packet.h b/g10/packet.h index 81851373d..dc5b1583a 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -193,7 +193,7 @@ typedef struct { * Note about the pkey/skey elements: We assume that the secret keys * has the same elemts as the public key at the begin of the array, so * that npkey < nskey and it is possible to compare the secret and - * public keys by comparing the first npkey elements of pkey againts skey. + * public keys by comparing the first npkey elements of pkey against skey. */ typedef struct { u32 timestamp; /* key made */ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index fc9e2559f..57a6d3d7b 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1562,6 +1562,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *sk = pkt->pkt.secret_key; byte temp[16]; + size_t snlen = 0; if( !npkey ) { sk->skey[0] = mpi_set_opaque( NULL, @@ -1672,7 +1673,6 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, (ulong)sk->protect.s2k.count); } else if( sk->protect.s2k.mode == 1002 ) { - size_t snlen; /* Read the serial number. */ if (pktlen < 1) { rc = GPG_ERR_INV_PACKET; @@ -1684,17 +1684,6 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, rc = GPG_ERR_INV_PACKET; goto leave; } - - if( list_mode ) { - printf("\tserial-number: "); - for (;snlen; snlen--) - printf ("%02X", (unsigned int)iobuf_get_noeof (inp)); - putchar ('\n'); - } - else { - for (;snlen; snlen--) - iobuf_get_noeof (inp); - } } } /* Note that a sk->protect.algo > 110 is illegal, but I'm @@ -1725,9 +1714,12 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, } if( sk->protect.s2k.mode == 1001 ) sk->protect.ivlen = 0; - else if( sk->protect.s2k.mode == 1002 ) - sk->protect.ivlen = 0; + else if( sk->protect.s2k.mode == 1002 ) { + if (snlen > 16) + log_info ("WARNING: serial number of card truncated\n"); + sk->protect.ivlen = snlen < 16? snlen : 16; + } if( pktlen < sk->protect.ivlen ) { rc = GPG_ERR_INV_PACKET; goto leave; @@ -1735,7 +1727,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- ) temp[i] = iobuf_get_noeof(inp); if( list_mode ) { - printf( "\tprotect IV: "); + printf( sk->protect.s2k.mode == 1002? "\tserial-number: " + : "\tprotect IV: "); for(i=0; i < sk->protect.ivlen; i++ ) printf(" %02x", temp[i] ); putchar('\n'); diff --git a/g10/seskey.c b/g10/seskey.c index 5d0490cdf..ae22032a1 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -215,12 +215,14 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo, } else { + gpg_error_t rc; byte *asn; size_t asnlen; - if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen ) ) + rc = gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen); + if (rc) log_fatal("can't get OID of algo %d: %s\n", - algo, gcry_strerror(-1)); + algo, gpg_strerror (rc)); asn = xmalloc (asnlen); if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) ) BUG(); diff --git a/g10/sign.c b/g10/sign.c index 86159a4a1..d9ce074d4 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -277,13 +277,14 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, { /* FIXME: Note that we do only support RSA for now. */ char *rbuf; size_t rbuflen; + char *snbuf; - /* FIXME: We need to pass the correct keyid or better the - fingerprint to the scdaemon. */ - rc = agent_scd_pksign ("nokeyid", digest_algo, + snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); + rc = agent_scd_pksign (snbuf, digest_algo, gcry_md_read (md, digest_algo), gcry_md_get_algo_dlen (digest_algo), &rbuf, &rbuflen); + xfree (snbuf); if (!rc) { unsigned int nbytes = rbuflen; -- cgit v1.2.3 From 1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 3 Jul 2003 18:08:16 +0000 Subject: * options.h (DBG_CIPHER): Reintroduced it. * seskey.c (encode_session_key): Debug output of the session key. * pubkey-enc.c (get_it): Handle card case. * call-agent.c (agent_scd_pkdecrypt): New. * pkglue.c (pk_encrypt): Add RSA support. * g10.c (main): Default to --use-agent. * keygen.c (show_smartcard): Print info about the public key. (check_smartcard): Check for existing key here. (gen_card_key): And not anymore here. (fpr_is_zero): New. (generate_keypair): Generate both keys for a card. (smartcard_change_url): Nw. --- g10/ChangeLog | 22 +++++ g10/call-agent.c | 60 +++++++++++- g10/call-agent.h | 10 +- g10/g10.c | 4 + g10/getkey.c | 2 +- g10/keyedit.c | 2 +- g10/keygen.c | 196 ++++++++++++++++++++++++++----------- g10/options.h | 1 + g10/pkglue.c | 26 ++++- g10/pubkey-enc.c | 286 ++++++++++++++++++++++++++++++------------------------ g10/seckey-cert.c | 5 +- g10/seskey.c | 8 +- g10/sign.c | 2 + 13 files changed, 422 insertions(+), 202 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index bf394f211..681f4cd55 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,25 @@ +2003-07-03 Werner Koch <wk@gnupg.org> + + * options.h (DBG_CIPHER): Reintroduced it. + * seskey.c (encode_session_key): Debug output of the session key. + + * pubkey-enc.c (get_it): Handle card case. + * call-agent.c (agent_scd_pkdecrypt): New. + * pkglue.c (pk_encrypt): Add RSA support. + + * g10.c (main): Default to --use-agent. + + * keygen.c (show_smartcard): Print info about the public key. + (check_smartcard): Check for existing key here. + (gen_card_key): And not anymore here. + (fpr_is_zero): New. + (generate_keypair): Generate both keys for a card. + (smartcard_change_url): Nw. + +2003-07-02 Werner Koch <wk@gnupg.org> + + * seckey-cert.c (is_secret_key_protected): Let it handle mode 1002. + 2003-07-01 Werner Koch <wk@gnupg.org> * keygen.c (gen_card_key): Obviously we should use the creation diff --git a/g10/call-agent.c b/g10/call-agent.c index d38e4c0fc..ca4236538 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -456,7 +456,6 @@ learn_status_cb (void *opaque, const char *line) const char *keyword = line; int keywordlen; - log_debug ("got status line `%s'\n", line); for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) ; while (spacep (line)) @@ -470,7 +469,7 @@ learn_status_cb (void *opaque, const char *line) { parm->disp_name = unescape_status_string (line); } - else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY_URL", keywordlen)) + else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen)) { parm->pubkey_url = unescape_status_string (line); } @@ -670,7 +669,7 @@ agent_scd_pksign (const char *serialno, int hashalgo, sprintf (p, "%02X", indata[i]); rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return rc; + return map_assuan_err (rc); init_membuf (&data, 1024); snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno); @@ -680,9 +679,62 @@ agent_scd_pksign (const char *serialno, int hashalgo, if (rc) { xfree (get_membuf (&data, &len)); - return rc; + 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; +} + diff --git a/g10/call-agent.h b/g10/call-agent.h index 2169a5319..a6edecf47 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -61,12 +61,10 @@ int agent_scd_pksign (const char *keyid, int hashalgo, const unsigned char *indata, size_t indatalen, char **r_buf, size_t *r_buflen); -/* Ask the agent to let the user change the passphrase of the secret - key identified by HEXKEYGRIP. */ -int agent_passwd (const char *hexkeygrip); - - - +/* 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); diff --git a/g10/g10.c b/g10/g10.c index 6909e0404..d48dada5e 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1228,6 +1228,7 @@ main( int argc, char **argv ) opt.verify_options=VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION; opt.trust_model=TM_AUTO; opt.mangle_dos_filenames = 1; + opt.use_agent = 1; #if defined (__MINGW32__) set_homedir ( read_w32_registry_string( NULL, @@ -1984,6 +1985,9 @@ main( int argc, char **argv ) } #endif +#warning locking does not work - disabled + disable_dotlock (); + if (opt.verbose > 2) log_info ("using character set `%s'\n", get_native_charset ()); diff --git a/g10/getkey.c b/g10/getkey.c index 79fcaf3e2..c13d96dfb 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -898,7 +898,7 @@ get_pubkey_end( GETKEY_CTX ctx ) /**************** * Search for a key with the given fingerprint. * FIXME: - * We should replace this with the _byname function. Thiscsan be done + * We should replace this with the _byname function. This can be done * by creating a userID conforming to the unified fingerprint style. */ int diff --git a/g10/keyedit.c b/g10/keyedit.c index 11e2d870e..85f2b92e9 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -923,7 +923,7 @@ change_passphrase( KBNODE keyblock ) } else if( sk->protect.s2k.mode == 1002 ) { tty_printf(_("Secret key is actually stored on a card.\n")); - no_primary_secrets = 1; + goto leave; } else { tty_printf(_("Key is protected.\n")); diff --git a/g10/keygen.c b/g10/keygen.c index 5dab70ff1..bfa76d601 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2096,8 +2096,6 @@ generate_keypair( const char *fname ) card = check_smartcard (&serialno); if (card < 0) return; - if (card > 1) - log_error (_("can't generate subkey here\n")); } while (card > 1); @@ -2114,55 +2112,75 @@ generate_keypair( const char *fname ) if (card) { algo = PUBKEY_ALGO_RSA; - use = PUBKEY_USAGE_SIG; - } - else - algo = ask_algo (0, &use); - if (!algo) - { /* default: DSA with ElG subkey of the specified size */ - both = 1; r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYTYPE; - sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); + sprintf( r->u.value, "%d", algo ); r->next = para; para = r; - tty_printf(_("DSA keypair will have 1024 bits.\n")); r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYLENGTH; - strcpy( r->u.value, "1024" ); + r->key = pKEYUSAGE; + strcpy (r->u.value, "sign"); r->next = para; para = r; - - algo = PUBKEY_ALGO_ELGAMAL_E; + r = xcalloc (1, sizeof *r + 20 ); r->key = pSUBKEYTYPE; sprintf( r->u.value, "%d", algo ); r->next = para; para = r; - } - else - { r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo ); + r->key = pSUBKEYUSAGE; + strcpy (r->u.value, "encrypt"); r->next = para; para = r; + } + else + { + algo = ask_algo (0, &use); - if (use) + if (!algo) + { /* default: DSA with ElG subkey of the specified size */ + both = 1; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); + r->next = para; + para = r; + tty_printf(_("DSA keypair will have 1024 bits.\n")); + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYLENGTH; + strcpy( r->u.value, "1024" ); + r->next = para; + para = r; + + algo = PUBKEY_ALGO_ELGAMAL_E; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pSUBKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; + } + else { r = xcalloc (1, sizeof *r + 20 ); - r->key = pKEYUSAGE; - sprintf( r->u.value, "%s%s", - (use & PUBKEY_USAGE_SIG)? "sign ":"", - (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo ); r->next = para; para = r; + + if (use) + { + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYUSAGE; + sprintf( r->u.value, "%s%s", + (use & PUBKEY_USAGE_SIG)? "sign ":"", + (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); + r->next = para; + para = r; + } } - } - if (!card) - { nbits = ask_keysize( algo ); r = xcalloc (1, sizeof *r + 20 ); r->key = both? pSUBKEYLENGTH : pKEYLENGTH; @@ -2367,12 +2385,21 @@ do_generate_keypair (struct para_data_s *para, if (get_parameter (para, pSUBKEYTYPE)) { - rc = do_create (get_parameter_algo (para, pSUBKEYTYPE), - get_parameter_uint (para, pSUBKEYLENGTH), - pub_root, sec_root, - get_parameter_dek (para, pPASSPHRASE_DEK), - get_parameter_s2k (para, pPASSPHRASE_S2K), - NULL, get_parameter_u32 (para, pSUBKEYEXPIRE)); + if (!card) + { + rc = do_create (get_parameter_algo (para, pSUBKEYTYPE), + get_parameter_uint (para, pSUBKEYLENGTH), + pub_root, sec_root, + get_parameter_dek (para, pPASSPHRASE_DEK), + get_parameter_s2k (para, pPASSPHRASE_S2K), + NULL, get_parameter_u32 (para, pSUBKEYEXPIRE)); + } + else + { + rc = gen_card_key (PUBKEY_ALGO_RSA, 2, pub_root, sec_root, + get_parameter_u32 (para, pKEYEXPIRE), para); + } + if (!rc) rc = write_keybinding (pub_root, pub_root, sk, get_parameter_uint (para, pSUBKEYUSAGE)); @@ -2642,13 +2669,15 @@ show_sha1_fpr (const unsigned char *fpr) } } else - tty_printf ("[none]"); + tty_printf (" [none]"); tty_printf ("\n"); } static void show_smartcard (struct agent_card_info_s *info) { + PKT_public_key *pk = xcalloc (1, sizeof *pk); + /* FIXME: Sanitize what we show. */ tty_printf ("Name of cardholder: %s\n", info->disp_name && *info->disp_name? info->disp_name @@ -2656,12 +2685,17 @@ show_smartcard (struct agent_card_info_s *info) tty_printf ("URL of public key : %s\n", info->pubkey_url && *info->pubkey_url? info->pubkey_url : "[not set]"); - tty_printf ("Signature key ....: "); + tty_printf ("Signature key ....:"); show_sha1_fpr (info->fpr1valid? info->fpr1:NULL); - tty_printf ("Encryption key....: "); + tty_printf ("Encryption key....:"); show_sha1_fpr (info->fpr2valid? info->fpr2:NULL); - tty_printf ("Authentication key: "); + tty_printf ("Authentication key:"); show_sha1_fpr (info->fpr3valid? info->fpr3:NULL); + + if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20)) + print_pubkey_info (pk); + + free_public_key( pk ); } @@ -2726,17 +2760,48 @@ smartcard_change_name (const char *current_name) if (rc) log_error ("error setting Name: %s\n", gpg_strerror (rc)); + xfree (isoname); + return rc; +} + + +static int +smartcard_change_url (const char *current_url) +{ + char *url; + int rc; + + url = cpr_get ("keygen.smartcard.url", _("URL to retrieve public key: ")); + if (!url) + return -1; + trim_spaces (url); + cpr_kill_prompt (); + + 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; } +/* 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); +} + /* Check whether a smartcatrd is available and alow to select it as the target for key generation. Return values: -1 = Quit generation 0 = No smartcard - 1 = Generate primary key - 2 = generate subkey + 1 = Generate keypair */ static int check_smartcard (char **r_serialno) @@ -2767,9 +2832,8 @@ check_smartcard (char **r_serialno) tty_printf ("\n" "N - change cardholder name\n" "U - change public key URL\n" - "1 - generate signature key\n" - "2 - generate encryption key\n" - "3 - generate authentication key\n" + "K - generate signature and encryption key\n" + "A - generate authentication key\n" "Q - quit\n" "\n"); @@ -2786,13 +2850,31 @@ check_smartcard (char **r_serialno) } else if ( *answer == 'U' || *answer == 'u') { + if (!smartcard_change_url (info.pubkey_url)) + reread = 1; } - else if ( *answer == '1' || *answer == '2') + else if ( *answer == 'K' || *answer == 'k') { - rc = *answer - '0'; - break; + if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) + || (info.fpr2valid && !fpr_is_zero (info.fpr2))) + { + tty_printf ("\n"); + log_error ("WARNING: key does already exists!\n"); + tty_printf ("\n"); + if ( cpr_get_answer_is_yes( "keygen.card.replace_key", + _("Replace existing key? "))) + { + rc = 1; + break; + } + } + else + { + rc = 1; + break; + } } - else if ( *answer == '3' ) + else if ( *answer == 'A' || *answer == 'a' ) { tty_printf (_("Generation of authentication key" " not yet implemented\n")); @@ -2844,16 +2926,16 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, assert (algo == PUBKEY_ALGO_RSA); - rc = agent_scd_genkey (&info, keyno, 0); - if (gpg_err_code (rc) == GPG_ERR_EEXIST) - { - tty_printf ("\n"); - log_error ("WARNING: key does already exists!\n"); - tty_printf ("\n"); - if ( cpr_get_answer_is_yes( "keygen.card.replace_key", - _("Replace existing key? "))) - rc = agent_scd_genkey (&info, keyno, 1); - } + rc = agent_scd_genkey (&info, keyno, 1); +/* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */ +/* { */ +/* tty_printf ("\n"); */ +/* log_error ("WARNING: key does already exists!\n"); */ +/* tty_printf ("\n"); */ +/* if ( cpr_get_answer_is_yes( "keygen.card.replace_key", */ +/* _("Replace existing key? "))) */ +/* rc = agent_scd_genkey (&info, keyno, 1); */ +/* } */ if (rc) { diff --git a/g10/options.h b/g10/options.h index a68dc52c4..85d83e572 100644 --- a/g10/options.h +++ b/g10/options.h @@ -201,6 +201,7 @@ struct { #define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) +#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE) #define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) #define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) diff --git a/g10/pkglue.c b/g10/pkglue.c index 3e378822c..7920a5223 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -177,6 +177,12 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) "(public-key(elg(p%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2]); } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(rsa(n%m)(e%m)))", + pkey[0], pkey[1]); + } else return GPG_ERR_PUBKEY_ALGO; @@ -202,11 +208,14 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) assert (resarr[0]); gcry_sexp_release (list); - list = gcry_sexp_find_token (s_ciph, "b", 0); - assert (list); - resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); - assert (resarr[1]); - gcry_sexp_release (list); + if (algo != GCRY_PK_RSA) + { + list = gcry_sexp_find_token (s_ciph, "b", 0); + assert (list); + resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); + assert (resarr[1]); + gcry_sexp_release (list); + } } gcry_sexp_release (s_ciph); @@ -276,3 +285,10 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, return 0; } + + + + + + + diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index b08394e4a..d052546e3 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -38,6 +38,7 @@ #include "main.h" #include "i18n.h" #include "pkglue.h" +#include "call-agent.h" static int get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ); @@ -136,146 +137,181 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) static int get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) { - int rc; - gcry_mpi_t plain_dek = NULL; - byte *frame = NULL; - unsigned n, nframe; - u16 csum, csum2; + int rc; + gcry_mpi_t plain_dek = NULL; + byte *frame = NULL; + unsigned n, nframe; + u16 csum, csum2; + int card = 0; - rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey); - if( rc ) - goto leave; - if ( gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek)) - BUG(); - gcry_mpi_release (plain_dek); plain_dek = NULL; - - /* Now get the DEK (data encryption key) from the frame - * - * Old versions encode the DEK in in this format (msb is left): - * - * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 - * - * Later versions encode the DEK like this: - * - * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) - * - * (mpi_get_buffer already removed the leading zero). - * - * RND are non-zero randow bytes. - * A is the cipher algorithm - * DEK is the encryption key (session key) with length k - * CSUM - */ - if( DBG_CIPHER ) - log_printhex ("DEK frame:", frame, nframe ); - n=0; - if( n + 7 > nframe ) - { rc = GPG_ERR_WRONG_SECKEY; goto leave; } - if( frame[n] == 1 && frame[nframe-1] == 2 ) { - log_info(_("old encoding of the DEK is not supported\n")); - rc = GPG_ERR_CIPHER_ALGO; - goto leave; + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { /* FIXME: Note that we do only support RSA for now. */ + char *rbuf; + size_t rbuflen; + char *snbuf; + void *indata = NULL; + unsigned int indatalen; + + snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); + + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, + enc->data[0])) + BUG(); + + rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen); + xfree (snbuf); + xfree (indata); + if (rc) + goto leave; + + frame = rbuf; + nframe = rbuflen; + card = 1; } - if( frame[n] != 2 ) /* somethink is wrong */ - { rc = GPG_ERR_WRONG_SECKEY; goto leave; } - for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ - ; - n++; /* and the zero byte */ - if( n + 4 > nframe ) - { rc = GPG_ERR_WRONG_SECKEY; goto leave; } - - dek->keylen = nframe - (n+1) - 2; - dek->algo = frame[n++]; - if( dek->algo == CIPHER_ALGO_IDEA ) - write_status(STATUS_RSA_OR_IDEA); - rc = openpgp_cipher_test_algo (dek->algo); - if( rc ) { - if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) { - log_info(_("cipher algorithm %d%s is unknown or disabled\n"), - dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); - if(dek->algo==CIPHER_ALGO_IDEA) - idea_cipher_warn(0); - } - dek->algo = 0; - goto leave; + else + { + void *indata; + + rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey); + if( rc ) + goto leave; + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &nframe, plain_dek)) + BUG(); + frame = indata; + gcry_mpi_release (plain_dek); plain_dek = NULL; } - if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) { - rc = GPG_ERR_WRONG_SECKEY; - goto leave; + + + /* Now get the DEK (data encryption key) from the frame + * + * Old versions encode the DEK in in this format (msb is left): + * + * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 + * + * Later versions encode the DEK like this: + * + * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) + * + * (mpi_get_buffer already removed the leading zero). + * + * RND are non-zero randow bytes. + * A is the cipher algorithm + * DEK is the encryption key (session key) with length k + * CSUM + */ + if( DBG_CIPHER ) + log_printhex ("DEK frame:", frame, nframe ); + n=0; + if (!card) + { + if( n + 7 > nframe ) + { rc = GPG_ERR_WRONG_SECKEY; goto leave; } + if( frame[n] == 1 && frame[nframe-1] == 2 ) { + log_info(_("old encoding of the DEK is not supported\n")); + rc = GPG_ERR_CIPHER_ALGO; + goto leave; + } + if( frame[n] != 2 ) /* somethink is wrong */ + { rc = GPG_ERR_WRONG_SECKEY; goto leave; } + for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ + ; + n++; /* and the zero byte */ } - /* copy the key to DEK and compare the checksum */ - csum = frame[nframe-2] << 8; - csum |= frame[nframe-1]; - memcpy( dek->key, frame+n, dek->keylen ); - for( csum2=0, n=0; n < dek->keylen; n++ ) - csum2 += dek->key[n]; - if( csum != csum2 ) { - rc = GPG_ERR_WRONG_SECKEY; - goto leave; + if( n + 4 > nframe ) + { rc = GPG_ERR_WRONG_SECKEY; goto leave; } + dek->keylen = nframe - (n+1) - 2; + dek->algo = frame[n++]; + if( dek->algo == CIPHER_ALGO_IDEA ) + write_status(STATUS_RSA_OR_IDEA); + rc = openpgp_cipher_test_algo (dek->algo); + if( rc ) { + if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) { + log_info(_("cipher algorithm %d%s is unknown or disabled\n"), + dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); + if(dek->algo==CIPHER_ALGO_IDEA) + idea_cipher_warn(0); } - if( DBG_CIPHER ) - log_printhex ("DEK is:", dek->key, dek->keylen ); - /* check that the algo is in the preferences and whether it has expired */ - { - PKT_public_key *pk = NULL; - KBNODE pkb = get_pubkeyblock (keyid); + dek->algo = 0; + goto leave; + } + if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) { + rc = GPG_ERR_WRONG_SECKEY; + goto leave; + } - if( !pkb ) { - rc = -1; - log_error("oops: public key not found for preference check\n"); - } - else if( pkb->pkt->pkt.public_key->selfsigversion > 3 - && dek->algo != CIPHER_ALGO_3DES - && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) { - /* Don't print a note while we are not on verbose mode, - * the cipher is blowfish and the preferences have twofish - * listed */ - if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH - || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH)) - log_info(_( - "NOTE: cipher algorithm %d not found in preferences\n"), - dek->algo ); - } + /* copy the key to DEK and compare the checksum */ + csum = frame[nframe-2] << 8; + csum |= frame[nframe-1]; + memcpy( dek->key, frame+n, dek->keylen ); + for( csum2=0, n=0; n < dek->keylen; n++ ) + csum2 += dek->key[n]; + if( csum != csum2 ) { + rc = GPG_ERR_WRONG_SECKEY; + goto leave; + } + if( DBG_CIPHER ) + log_printhex ("DEK is:", dek->key, dek->keylen ); + /* check that the algo is in the preferences and whether it has expired */ + { + PKT_public_key *pk = NULL; + KBNODE pkb = get_pubkeyblock (keyid); + + if( !pkb ) { + rc = -1; + log_error("oops: public key not found for preference check\n"); + } + else if( pkb->pkt->pkt.public_key->selfsigversion > 3 + && dek->algo != CIPHER_ALGO_3DES + && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) { + /* Don't print a note while we are not on verbose mode, + * the cipher is blowfish and the preferences have twofish + * listed */ + if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH + || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH)) + log_info(_( + "NOTE: cipher algorithm %d not found in preferences\n"), + dek->algo ); + } - if (!rc) { - KBNODE k; + if (!rc) { + KBNODE k; - for (k=pkb; k; k = k->next) { - if (k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ - u32 aki[2]; - keyid_from_pk(k->pkt->pkt.public_key, aki); - - if (aki[0]==keyid[0] && aki[1]==keyid[1]) { - pk = k->pkt->pkt.public_key; - break; - } - } - } - if (!pk) - BUG (); - if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { - log_info(_("NOTE: secret key %08lX expired at %s\n"), - (ulong)keyid[1], asctimestamp( pk->expiredate) ); - } - } + for (k=pkb; k; k = k->next) { + if (k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ + u32 aki[2]; + keyid_from_pk(k->pkt->pkt.public_key, aki); - if ( pk && pk->is_revoked ) { - log_info( _("NOTE: key has been revoked") ); - putc( '\n', log_get_stream() ); - show_revocation_reason( pk, 1 ); + if (aki[0]==keyid[0] && aki[1]==keyid[1]) { + pk = k->pkt->pkt.public_key; + break; + } } + } + if (!pk) + BUG (); + if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { + log_info(_("NOTE: secret key %08lX expired at %s\n"), + (ulong)keyid[1], asctimestamp( pk->expiredate) ); + } + } - release_kbnode (pkb); - rc = 0; + if ( pk && pk->is_revoked ) { + log_info( _("NOTE: key has been revoked") ); + putc( '\n', log_get_stream() ); + show_revocation_reason( pk, 1 ); } + release_kbnode (pkb); + rc = 0; + } - leave: - gcry_mpi_release (plain_dek); - xfree (frame); - return rc; + + leave: + gcry_mpi_release (plain_dek); + xfree (frame); + return rc; } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index dff463c53..65be7a468 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -297,11 +297,14 @@ check_secret_key( PKT_secret_key *sk, int n ) /**************** * check whether the secret key is protected. * Returns: 0 not protected, -1 on error or the protection algorithm + * -2 indicates a card stub. */ int is_secret_key_protected( PKT_secret_key *sk ) { - return sk->is_protected? sk->protect.algo : 0; + return sk->is_protected? + sk->protect.s2k.mode == 1002? -2 + : sk->protect.algo : 0; } diff --git a/g10/seskey.c b/g10/seskey.c index ae22032a1..11ebe17aa 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -30,7 +30,7 @@ #include "mpi.h" #include "main.h" #include "i18n.h" - +#include "options.h" /**************** * Make a session key and put it into DEK @@ -143,7 +143,11 @@ encode_session_key (DEK *dek, unsigned int nbits) memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen; frame[n++] = csum >>8; frame[n++] = csum; - assert( n == nframe ); + assert (n == nframe); + + if (DBG_CIPHER) + log_printhex ("encoded session key:", frame, nframe ); + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe)) BUG(); xfree (frame); diff --git a/g10/sign.c b/g10/sign.c index d9ce074d4..fa1e07b87 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -41,6 +41,8 @@ #include "status.h" #include "i18n.h" #include "pkglue.h" +#include "call-agent.h" + #ifdef HAVE_DOSISH_SYSTEM #define LF "\r\n" -- cgit v1.2.3 From ca3818df83444227a32b1cc5521a9e641ba86d66 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 3 Jul 2003 18:09:55 +0000 Subject: * cipher.h (DBG_CIPHER,g10c_debug_mode): Removed. --- include/ChangeLog | 5 ++++- include/cipher.h | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/ChangeLog b/include/ChangeLog index 0b1001c3b..7d8191a2d 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,10 +1,13 @@ +2003-07-03 Werner Koch <wk@gnupg.org> + + * cipher.h (DBG_CIPHER,g10c_debug_mode): Removed. + 2003-06-11 Werner Koch <wk@gnupg.org> * cipher.h: Include gcrypt.h and mapped cipher algo names to gcrypt ones. Removed twofish_old and skipjack. Removed all handle definitions and other raerely used stuff. This file will eventually be entirely removed. - 2003-06-10 Werner Koch <wk@gnupg.org> diff --git a/include/cipher.h b/include/cipher.h index 3058a2ce0..56a1b2000 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -20,8 +20,6 @@ #ifndef G10_CIPHER_H #define G10_CIPHER_H -#define DBG_CIPHER g10c_debug_mode - #include <gcrypt.h> #define CIPHER_ALGO_NONE GCRY_CIPHER_NONE @@ -83,7 +81,6 @@ typedef struct { #define EXTERN_UNLESS_MAIN_MODULE #endif #endif -EXTERN_UNLESS_MAIN_MODULE int g10c_debug_mode; EXTERN_UNLESS_MAIN_MODULE int g10_opt_verbose; EXTERN_UNLESS_MAIN_MODULE const char *g10_opt_homedir; -- cgit v1.2.3 From 89a3dbae85f4541db77c51a4ea768c60e66ec292 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 4 Jul 2003 09:40:19 +0000 Subject: Minor changes to make make dist work correctly. --- Makefile.am | 16 ++++++++++++++-- include/distfiles | 2 -- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 74e622051..9f5c443d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,10 +44,22 @@ else scd = endif -SUBDIRS = m4 intl jnlib common kbx ${gpg} ${sm} ${agent} ${scd} po doc tests +SUBDIRS = m4 intl jnlib common kbx \ + ${gpg} ${sm} ${agent} ${scd} po doc tests + dist-hook: - @set -e; echo "$(VERSION)" > $(distdir)/VERSION + @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 + diff --git a/include/distfiles b/include/distfiles index 20a9091e6..b11749d78 100644 --- a/include/distfiles +++ b/include/distfiles @@ -1,9 +1,7 @@ cipher.h errors.h -iobuf.h memory.h mpi.h -ttyio.h types.h util.h i18n.h -- cgit v1.2.3 From 4622a2180defd68f7ddd06c4e130b02114573238 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 16 Jul 2003 13:45:15 +0000 Subject: * export.c (parse_export_options): New option sexp-format. (export_seckeys,export_secsubkeys): Check sexp-format option. (do_export): Ignore armor for sexp format. (do_export_stream): Handle sexp-format. (write_sexp_line,write_sexp_keyparm, build_sexp_seckey): New. (build_sexp): New. --- g10/ChangeLog | 9 +++ g10/export.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- g10/keygen.c | 2 + g10/keyid.c | 1 + g10/main.h | 2 +- g10/options.h | 6 ++ 6 files changed, 199 insertions(+), 30 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 681f4cd55..db19713a8 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2003-07-16 Werner Koch <wk@gnupg.org> + + * export.c (parse_export_options): New option sexp-format. + (export_seckeys,export_secsubkeys): Check sexp-format option. + (do_export): Ignore armor for sexp format. + (do_export_stream): Handle sexp-format. + (write_sexp_line,write_sexp_keyparm, build_sexp_seckey): New. + (build_sexp): New. + 2003-07-03 Werner Koch <wk@gnupg.org> * options.h (DBG_CIPHER): Reintroduced it. diff --git a/g10/export.c b/g10/export.c index 6c2c19f14..32addfa4a 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1,5 +1,6 @@ /* export.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -38,6 +39,7 @@ 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) @@ -48,6 +50,7 @@ parse_export_options(char *str,unsigned int *options) {"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? */ }; @@ -85,43 +88,51 @@ export_pubkeys_stream( iobuf_t out, STRLIST users, int export_seckeys( STRLIST users ) { - return do_export( users, 1, 0 ); + /* 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 ) { - return do_export( users, 2, 0 ); + /* 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 ) +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; + 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( opt.armor ) { - afx.what = secret?5:1; - iobuf_push_filter( out, armor_filter, &afx ); + 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 ); } - 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; + rc = do_export_stream (out, users, secret, NULL, options, &any ); + + if (rc || !any) + iobuf_cancel (out); + else + iobuf_close (out); + return rc; } @@ -140,6 +151,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, KEYDB_SEARCH_DESC *desc = NULL; KEYDB_HANDLE kdbhd; STRLIST sl; + int indent = 0; *any = 0; init_packet( &pkt ); @@ -346,7 +358,10 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, */ int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode; node->pkt->pkt.secret_key->protect.s2k.mode = 1001; - rc = build_packet( out, node->pkt ); + 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 { @@ -365,7 +380,10 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, sha1_warned=1; } - rc = build_packet( out, node->pkt ); + if ((options&EXPORT_SEXP_FORMAT)) + rc = build_sexp (out, node->pkt, &indent); + else + rc = build_packet (out, node->pkt); } if( rc ) { @@ -374,6 +392,13 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, goto leave; } } + if ((options&EXPORT_SEXP_FORMAT) && indent) + { + for (; indent; indent--) + iobuf_put (out, ')'); + iobuf_put (out, '\n'); + } + ++*any; if(keyblock_out) { @@ -381,6 +406,12 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, break; } } + if ((options&EXPORT_SEXP_FORMAT) && indent) + { + for (; indent; indent--) + iobuf_put (out, ')'); + iobuf_put (out, '\n'); + } if( rc == -1 ) rc = 0; @@ -393,3 +424,123 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, 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; + char *buffer; + + write_sexp_line (out, indent, "("); + iobuf_writestr (out, name); + iobuf_writestr (out, " #"); + + rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void **)&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; +} + diff --git a/g10/keygen.c b/g10/keygen.c index bfa76d601..740dce571 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2986,3 +2986,5 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, return 0; } + + diff --git a/g10/keyid.c b/g10/keyid.c index 54a79bcdb..4587fadee 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -62,6 +62,7 @@ do_fingerprint_md( PKT_public_key *pk ) gcry_md_open (&md, pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); + gcry_md_start_debug (md, "fpr"); n = pk->version < 4 ? 8 : 6; for(i=0; i < npkey; i++ ) { size_t nbytes; diff --git a/g10/main.h b/g10/main.h index a4f4e3b84..2a9d5eda7 100644 --- a/g10/main.h +++ b/g10/main.h @@ -183,7 +183,7 @@ void try_make_homedir( const char *fname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); -gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits ); +gcry_mpi_t encode_session_key( DEK *dek, unsigned int nbits); gcry_mpi_t encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits, int v3compathack ); diff --git a/g10/options.h b/g10/options.h index 85d83e572..9eda2e252 100644 --- a/g10/options.h +++ b/g10/options.h @@ -227,6 +227,8 @@ struct { #define EXPORT_INCLUDE_LOCAL_SIGS 2 #define EXPORT_INCLUDE_ATTRIBUTES 4 #define EXPORT_INCLUDE_SENSITIVE_REVKEYS 8 +#define EXPORT_SEXP_FORMAT 16 + #define LIST_SHOW_PHOTOS 1 #define LIST_SHOW_POLICY 2 @@ -240,3 +242,7 @@ struct { #define VERIFY_SHOW_NOTATION 4 #endif /*G10_OPTIONS_H*/ + + + + -- cgit v1.2.3 From 44f4303bcfe1ce47717c57838d13ebd872fde0fd Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 23 Jul 2003 07:11:06 +0000 Subject: * keygen.c (generate_keypair): Create an AUTHKEYTYPE entry for cards. (do_generate_keypair): Abd generate the authkey. (check_smartcard): Changed menu accordingly. --- g10/ChangeLog | 14 +++++++ g10/Makefile.am | 1 + g10/call-agent.c | 52 ++++++++++++++++++++++++- g10/call-agent.h | 6 +++ g10/card-util.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ g10/g10.c | 15 +++++++ g10/keygen.c | 44 +++++++++++++-------- g10/keyid.c | 2 +- g10/main.h | 3 ++ g10/sign.c | 38 +++++++++++++++++- 10 files changed, 272 insertions(+), 20 deletions(-) create mode 100644 g10/card-util.c diff --git a/g10/ChangeLog b/g10/ChangeLog index db19713a8..f7fdea707 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,17 @@ +2003-07-23 Werner Koch <wk@gnupg.org> + + * keygen.c (generate_keypair): Create an AUTHKEYTYPE entry for cards. + (do_generate_keypair): Abd generate the authkey. + (check_smartcard): Changed menu accordingly. + +2003-07-22 Werner Koch <wk@gnupg.org> + + * g10.c: New command --change-pin. + * card-util.c: New. + * call-agent.c (agent_scd_change_pin): New. + (agent_release_card_info): New. + * keygen.c (check_smartcard): Use it here. + 2003-07-16 Werner Koch <wk@gnupg.org> * export.c (parse_export_options): New option sexp-format. diff --git a/g10/Makefile.am b/g10/Makefile.am index 3137bb894..d6984941e 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -96,6 +96,7 @@ gpg_SOURCES = g10.c \ keyserver-internal.h \ photoid.c photoid.h \ call-agent.c call-agent.h \ + card-util.c \ exec.c exec.h gpgv_SOURCES = gpgv.c \ diff --git a/g10/call-agent.c b/g10/call-agent.c index ca4236538..3b40cd0dd 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -449,6 +449,19 @@ agent_havekey (const char *hexkeygrip) } +/* 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->pubkey_url); info->pubkey_url = NULL; + info->fpr1valid = info->fpr2valid = info->fpr3valid = 0; +} + static AssuanError learn_status_cb (void *opaque, const char *line) { @@ -509,7 +522,6 @@ agent_learn (struct agent_card_info_s *info) return map_assuan_err (rc); } - /* Send an setattr command to the SCdaemon. */ int @@ -672,7 +684,12 @@ agent_scd_pksign (const char *serialno, int hashalgo, return map_assuan_err (rc); init_membuf (&data, 1024); - snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno); +#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); @@ -738,3 +755,34 @@ agent_scd_pkdecrypt (const char *serialno, return 0; } + +/* Change the PIN of an OpenPGP card or reset the retry counter. + CHVNO 1: Change the digital signature PIN + 2: Change the decryption and authentication PIN + 3: Change the admin PIN + 101: Set a new digital signature PIN and reset the retry counter + 102: Set a decryption and authentication PIN + and reset the retry counter + */ +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); +} + diff --git a/g10/call-agent.h b/g10/call-agent.h index a6edecf47..434295e79 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -42,6 +42,10 @@ struct agent_card_genkey_s { 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); @@ -66,6 +70,8 @@ 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); #endif /*GNUPG_G10_CALL_AGENT_H*/ diff --git a/g10/card-util.c b/g10/card-util.c new file mode 100644 index 000000000..36c432aee --- /dev/null +++ b/g10/card-util.c @@ -0,0 +1,117 @@ +/* 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> + +#include "gpg.h" +#include "util.h" +#include "i18n.h" +#include "options.h" +#include "main.h" +#include "call-agent.h" + + +/* 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; + int reset_mode = 0; + + 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; + int reread = 0; + + tty_printf ("\n"); + tty_printf ("1 - change signature PIN\n" + "2 - change decryption and authentication PIN\n" + "3 - change Admin's PIN\n" + "R - toggle reset retry counter mode\n" + "Q - quit\n"); + tty_printf ("\n"); + if (reset_mode) + { + tty_printf ("Reset Retry Counter mode active\n"); + tty_printf ("\n"); + } + + answer = cpr_get("cardutil.change_pin.menu",_("Your selection? ")); + cpr_kill_prompt(); + if (strlen (answer) != 1) + continue; + + rc = 0; + if (reset_mode && *answer == '3') + { + tty_printf ("Sorry, reset of the Admin PIN's retry counter " + "is not possible.\n"); + } + else if (*answer == '1' || *answer == '2' || *answer == '3') + { + rc = agent_scd_change_pin (*answer - '0' + (reset_mode?100:0)); + if (rc) + tty_printf ("Error changing/resetting the PIN: %s\n", + gpg_strerror (rc)); + else + tty_printf ("New PIN successfully set.\n"); + } + else if (*answer == 'r' || *answer == 'R') + { + reset_mode = !reset_mode; + } + else if (*answer == 'q' || *answer == 'Q') + { + break; + } + } + +} + + + + + diff --git a/g10/g10.c b/g10/g10.c index d48dada5e..b7ad9d746 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -128,6 +128,7 @@ enum cmd_and_opt_values { aNull = 0, aPipeMode, aRebuildKeydbCaches, aRefreshKeys, + aChangePIN, oTextmode, oNoTextmode, @@ -362,6 +363,8 @@ static ARGPARSE_OPTS opts[] = { { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, + { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, + { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, { aExportOwnerTrust, "export-ownertrust", 256, N_("export the ownertrust values")}, @@ -1441,6 +1444,8 @@ main( int argc, char **argv ) case aPipeMode: set_cmd( &cmd, aPipeMode); break; case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; + case aChangePIN: set_cmd (&cmd, aChangePIN); break; + case oArmor: opt.armor = 1; opt.no_armor=0; break; case oOutput: opt.outfile = pargs.r.ret_str; break; case oQuiet: opt.quiet = 1; break; @@ -2341,6 +2346,7 @@ main( int argc, char **argv ) case aDeArmor: case aEnArmor: case aFixTrustDB: + case aChangePIN: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; @@ -2861,6 +2867,15 @@ main( int argc, char **argv ) keydb_rebuild_caches (); break; + case aChangePIN: + if (!argc) + change_pin (0); + else if (argc == 1) + change_pin ( atoi (*argv)); + else + wrong_args ("--change-pin [no]"); + break; + case aListPackets: opt.list_packets=2; default: diff --git a/g10/keygen.c b/g10/keygen.c index 740dce571..e2552085a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -50,6 +50,7 @@ enum para_name { pSUBKEYTYPE, pSUBKEYLENGTH, pSUBKEYUSAGE, + pAUTHKEYTYPE, pNAMEREAL, pNAMEEMAIL, pNAMECOMMENT, @@ -2134,6 +2135,12 @@ generate_keypair( const char *fname ) strcpy (r->u.value, "encrypt"); r->next = para; para = r; + + r = xcalloc (1, sizeof *r + 20 ); + r->key = pAUTHKEYTYPE; + sprintf( r->u.value, "%d", algo ); + r->next = para; + para = r; } else { @@ -2409,6 +2416,18 @@ do_generate_keypair (struct para_data_s *para, did_sub = 1; } + if (card && get_parameter (para, pAUTHKEYTYPE)) + { + rc = gen_card_key (PUBKEY_ALGO_RSA, 3, pub_root, sec_root, + get_parameter_u32 (para, pKEYEXPIRE), para); + + /* FIXME: Change the usage to AUTH. */ + if (!rc) + rc = write_keybinding (pub_root, pub_root, sk, PUBKEY_USAGE_SIG); + if (!rc) + rc = write_keybinding (sec_root, pub_root, sk, PUBKEY_USAGE_SIG); + } + if (!rc && outctrl->use_files) { /* direct write to specified files */ @@ -2832,8 +2851,7 @@ check_smartcard (char **r_serialno) tty_printf ("\n" "N - change cardholder name\n" "U - change public key URL\n" - "K - generate signature and encryption key\n" - "A - generate authentication key\n" + "K - generate all keys\n" "Q - quit\n" "\n"); @@ -2856,7 +2874,8 @@ check_smartcard (char **r_serialno) else if ( *answer == 'K' || *answer == 'k') { if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) - || (info.fpr2valid && !fpr_is_zero (info.fpr2))) + || (info.fpr2valid && !fpr_is_zero (info.fpr2)) + || (info.fpr3valid && !fpr_is_zero (info.fpr3))) { tty_printf ("\n"); log_error ("WARNING: key does already exists!\n"); @@ -2874,11 +2893,6 @@ check_smartcard (char **r_serialno) break; } } - else if ( *answer == 'A' || *answer == 'a' ) - { - tty_printf (_("Generation of authentication key" - " not yet implemented\n")); - } else if ( *answer == 'q' || *answer == 'Q') { rc = -1; @@ -2887,9 +2901,7 @@ check_smartcard (char **r_serialno) if (reread) { - xfree (info.serialno); info.serialno = NULL; - xfree (info.disp_name); info.disp_name = NULL; - xfree (info.pubkey_url); info.pubkey_url = NULL; + agent_release_card_info (&info); rc = agent_learn (&info); if (rc) { @@ -2902,11 +2914,11 @@ check_smartcard (char **r_serialno) } if (r_serialno && rc > 0) - *r_serialno = info.serialno; - else - xfree (info.serialno); - xfree (info.disp_name); - xfree (info.pubkey_url); + { + *r_serialno = info.serialno; + info.serialno = NULL; + } + agent_release_card_info (&info); return rc; } diff --git a/g10/keyid.c b/g10/keyid.c index 4587fadee..ea0632dcc 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -62,7 +62,7 @@ do_fingerprint_md( PKT_public_key *pk ) gcry_md_open (&md, pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0); - gcry_md_start_debug (md, "fpr"); + n = pk->version < 4 ? 8 : 6; for(i=0; i < npkey; i++ ) { size_t nbytes; diff --git a/g10/main.h b/g10/main.h index 2a9d5eda7..991c09a3d 100644 --- a/g10/main.h +++ b/g10/main.h @@ -254,6 +254,9 @@ int hash_datafiles( MD_HANDLE md, MD_HANDLE md2, /*-- pipemode.c --*/ void run_in_pipemode (void); +/*-- card-util.c --*/ +void change_pin (int no); + /*-- signal.c --*/ void init_signals(void); void pause_on_sigusr( int which ); diff --git a/g10/sign.c b/g10/sign.c index fa1e07b87..bdeb37d07 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -275,7 +275,43 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, sig->digest_algo = digest_algo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; - if (sk->is_protected && sk->protect.s2k.mode == 1002) +#if 0 + if (sk->is_protected && sk->protect.s2k.mode == 1002 && !sk->is_primary) + { /* Temporary hack to test tey auth command. */ + char *rbuf; + size_t rbuflen; + char *snbuf; + char *tmpbuf; + size_t tmp_n; + + frame = encode_md_value( sk->pubkey_algo, md, + digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); + if (!frame) + return GPG_ERR_GENERAL; + + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, (void **)&tmpbuf, &tmp_n, frame )) + BUG (); + for (; tmp_n && *tmpbuf; tmp_n--, tmpbuf++) + ; + assert (tmp_n); + tmp_n--; + tmpbuf++; + + snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); + rc = agent_scd_pksign (snbuf, 0, + tmpbuf, tmp_n, + &rbuf, &rbuflen); + xfree (snbuf); + if (!rc) + { + unsigned int nbytes = rbuflen; + if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, rbuf, &nbytes )) + BUG (); + } + } + else +#endif + if (sk->is_protected && sk->protect.s2k.mode == 1002) { /* FIXME: Note that we do only support RSA for now. */ char *rbuf; size_t rbuflen; -- cgit v1.2.3 From 0fe6a1287fe447afb852dd9b4734c374c90d0740 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 24 Jul 2003 09:06:43 +0000 Subject: * g10.c: New command --card-status. * card-util.c (card_status): New. * call-agent.c (learn_status_cb): Parse more information. * keylist.c (print_pubkey_info): Add FP arg for optinal printing to a stream. Changed all callers. --- g10/ChangeLog | 9 ++++ g10/call-agent.c | 52 ++++++++++++++++++++ g10/call-agent.h | 9 ++++ g10/card-util.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- g10/delkey.c | 2 +- g10/g10.c | 10 ++++ g10/keygen.c | 2 +- g10/keylist.c | 30 +++++++++--- g10/main.h | 4 +- g10/revoke.c | 2 +- 10 files changed, 253 insertions(+), 13 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f7fdea707..a7f8d4eb7 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2003-07-24 Werner Koch <wk@gnupg.org> + + * g10.c: New command --card-status. + * card-util.c (card_status): New. + * call-agent.c (learn_status_cb): Parse more information. + + * keylist.c (print_pubkey_info): Add FP arg for optinal printing + to a stream. Changed all callers. + 2003-07-23 Werner Koch <wk@gnupg.org> * keygen.c (generate_keypair): Create an AUTHKEYTYPE entry for cards. diff --git a/g10/call-agent.c b/g10/call-agent.c index 3b40cd0dd..ed4fa9054 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -458,7 +458,9 @@ agent_release_card_info (struct agent_card_info_s *info) 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; } @@ -468,6 +470,7 @@ 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++) ; @@ -482,10 +485,59 @@ learn_status_cb (void *opaque, const char *line) { parm->disp_name = unescape_status_string (line); } + else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen)) + { + 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)) { parm->pubkey_url = unescape_status_string (line); } + else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen)) + { + 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 (!spacep (p)) + p++; + while (spacep (p)) + p++; + for (i=0; *p && i < 3; i++) + { + parm->chvmaxlen[i] = atoi (p); + while (!spacep (p)) + p++; + while (spacep (p)) + p++; + } + for (i=0; *p && i < 3; i++) + { + parm->chvretry[i] = atoi (p); + while (!spacep (p)) + p++; + while (spacep (p)) + p++; + } + xfree (buf); + } + } else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) { int no = atoi (line); diff --git a/g10/call-agent.h b/g10/call-agent.h index 434295e79..e8abfbc7b 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -25,13 +25,22 @@ 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 { diff --git a/g10/card-util.c b/g10/card-util.c index 36c432aee..9f665cc74 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -28,6 +28,8 @@ #include "gpg.h" #include "util.h" #include "i18n.h" +#include "ttyio.h" +#include "status.h" #include "options.h" #include "main.h" #include "call-agent.h" @@ -64,7 +66,6 @@ change_pin (int chvno) for (;;) { char *answer; - int reread = 0; tty_printf ("\n"); tty_printf ("1 - change signature PIN\n" @@ -111,6 +112,149 @@ change_pin (int chvno) } +static const char * +get_manufacturer (unsigned int no) +{ + 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 ) + putc (' ', fp); + fprintf (fp, " %02X%02X", *fpr, fpr[1]); + } + } + else + fputs (" [none]", fp); + putc ('\n', fp); +} + + +static void +print_name (FILE *fp, const char *text, const char *name) +{ + fputs (text, fp); + + if (name && *name) + print_utf8_string2 (fp, name, strlen (name), '\n'); + else + fputs (_("[not set]"), fp); + putc ('\n', fp); +} + +static void +print_isoname (FILE *fp, const char *text, const char *name) +{ + fputs (text, fp); + + 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; + print_utf8_string2 (fp, given, strlen (given), '\n'); + if (*buf) + putc (' ', fp); + } + print_utf8_string2 (fp, buf, strlen (buf), '\n'); + xfree (buf); + } + else + fputs (_("[not set]"), fp); + putc ('\n', fp); +} + + +/* Print all available information about the current card. */ +void +card_status (FILE *fp) +{ + struct agent_card_info_s info; + PKT_public_key *pk = xcalloc (1, sizeof *pk); + int rc; + + rc = agent_learn (&info); + if (rc) + { + log_error (_("OpenPGP card not available: %s\n"), + gpg_strerror (rc)); + return; + } + + fprintf (fp, "Application ID ...: %s\n", + info.serialno? info.serialno : "[none]"); + if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) + || strlen (info.serialno) != 32 ) + { + log_info ("not an OpenPGP card\n"); + agent_release_card_info (&info); + } + 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]); + fprintf (fp, "Manufacturer .....: %s\n", + get_manufacturer (xtoi_2(info.serialno+16)*256 + + xtoi_2 (info.serialno+18))); + fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20); + + print_isoname (fp, "Name of cardholder: ", info.disp_name); + print_name (fp, "Language prefs ...: ", info.disp_lang); + 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); + fprintf (fp, "Signature PIN ....: %s\n", + info.chv1_cached? _("cached"): _("not cached")); + fprintf (fp, "Max. PIN lengths .: %d %d %d\n", + info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); + fprintf (fp, "PIN retry counter : %d %d %d\n", + info.chvretry[0], info.chvretry[1], info.chvretry[2]); + fputs ("Signature key ....:", fp); + print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL); + fputs ("Encryption key....:", fp); + print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL); + fputs ("Authentication key:", fp); + print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL); + fputs ("General key info..: ", fp); + if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) + print_pubkey_info (fp, pk); + else + fputs ("[none]\n", fp); + fprintf (fp, "Signature counter : %lu\n", info.sig_counter); + + free_public_key (pk); + agent_release_card_info (&info); +} + + + + + + diff --git a/g10/delkey.c b/g10/delkey.c index 34a2e1b32..6263dec47 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -130,7 +130,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) if( secret ) print_seckey_info( sk ); else - print_pubkey_info( pk ); + print_pubkey_info (NULL, pk ); tty_printf( "\n" ); yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay" diff --git a/g10/g10.c b/g10/g10.c index b7ad9d746..2f0a78cd0 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -128,6 +128,7 @@ enum cmd_and_opt_values { aNull = 0, aPipeMode, aRebuildKeydbCaches, aRefreshKeys, + aCardStatus, aChangePIN, oTextmode, @@ -363,6 +364,7 @@ static ARGPARSE_OPTS opts[] = { { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, + { aCardStatus, "card-status", 256, N_("print the card status")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, @@ -1444,6 +1446,7 @@ main( int argc, char **argv ) case aPipeMode: set_cmd( &cmd, aPipeMode); break; case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; + case aCardStatus: set_cmd (&cmd, aCardStatus); break; case aChangePIN: set_cmd (&cmd, aChangePIN); break; case oArmor: opt.armor = 1; opt.no_armor=0; break; @@ -2346,6 +2349,7 @@ main( int argc, char **argv ) case aDeArmor: case aEnArmor: case aFixTrustDB: + case aCardStatus: case aChangePIN: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; @@ -2867,6 +2871,12 @@ main( int argc, char **argv ) keydb_rebuild_caches (); break; + case aCardStatus: + if (argc) + wrong_args ("--card-status"); + card_status (stdout); + break; + case aChangePIN: if (!argc) change_pin (0); diff --git a/g10/keygen.c b/g10/keygen.c index e2552085a..515d4867a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2712,7 +2712,7 @@ show_smartcard (struct agent_card_info_s *info) show_sha1_fpr (info->fpr3valid? info->fpr3:NULL); if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20)) - print_pubkey_info (pk); + print_pubkey_info (NULL, pk); free_public_key( pk ); } diff --git a/g10/keylist.c b/g10/keylist.c index ef2cb5676..b5549fb47 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -93,25 +93,39 @@ print_seckey_info (PKT_secret_key *sk) tty_printf ("\n"); } +/* Print information about the public key. With FP passed as NULL, + the tty output interface is used, otherwise output is directted to + the given stream. */ void -print_pubkey_info (PKT_public_key *pk) +print_pubkey_info (FILE *fp, PKT_public_key *pk) { u32 pk_keyid[2]; size_t n; char *p; keyid_from_pk (pk, pk_keyid); - tty_printf ("\npub %4u%c/%08lX %s ", - nbits_from_pk (pk), - pubkey_letter (pk->pubkey_algo), - (ulong)pk_keyid[1], datestr_from_pk (pk)); - + if (fp) + fprintf (fp, "pub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); + else + tty_printf ("\npub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); p = get_user_id (pk_keyid, &n); - tty_print_utf8_string (p, n); + if (fp) + print_utf8_string2 (fp, p, n, '\n'); + else + tty_print_utf8_string (p, n); xfree (p); - tty_printf ("\n\n"); + if (fp) + putc ('\n', fp); + else + tty_printf ("\n\n"); } /* diff --git a/g10/main.h b/g10/main.h index 991c09a3d..cb81192d3 100644 --- a/g10/main.h +++ b/g10/main.h @@ -236,7 +236,7 @@ void dump_attribs(const PKT_user_id *uid, PKT_public_key *pk,PKT_secret_key *sk); void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); -void print_pubkey_info (PKT_public_key *pk); +void print_pubkey_info (FILE *fp, PKT_public_key *pk); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); @@ -256,6 +256,8 @@ void run_in_pipemode (void); /*-- card-util.c --*/ void change_pin (int no); +void card_status (FILE *fp); + /*-- signal.c --*/ void init_signals(void); diff --git a/g10/revoke.c b/g10/revoke.c index 80e32a32e..cf1bfe17a 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -264,7 +264,7 @@ gen_desig_revoke( const char *uname ) any = 1; - print_pubkey_info (pk); + print_pubkey_info (NULL, pk); tty_printf ("\n"); tty_printf (_("To be revoked by:\n")); -- cgit v1.2.3 From 979ed0ca26a5ae5538fc5b2aad0a8f2cdd2aae86 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 28 Jul 2003 08:59:18 +0000 Subject: Adjusted for use with current libgcrypt (1.1.42). --- configure.ac | 2 +- g10/ChangeLog | 4 ++++ g10/call-agent.c | 2 +- g10/comment.c | 4 ++-- g10/export.c | 4 ++-- g10/keyid.c | 26 ++++++++++++++------------ g10/misc.c | 14 +++++++------- g10/pubkey-enc.c | 7 ++----- g10/seckey-cert.c | 9 ++++----- g10/seskey.c | 6 +++--- g10/sig-check.c | 2 +- g10/sign.c | 8 ++++---- 12 files changed, 45 insertions(+), 43 deletions(-) diff --git a/configure.ac b/configure.ac index b02e55fc6..6f7782b1c 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,7 @@ AC_INIT(gnupg, 1.9.0-cvs, gnupg-devel@gnupg.org) # feel that the default check for a development version is not # sufficient. development_version=yes -NEED_LIBGCRYPT_VERSION=1.1.8 +NEED_LIBGCRYPT_VERSION=1.1.42 NEED_LIBASSUAN_VERSION=0.0.1 NEED_KSBA_VERSION=0.4.6 NEED_OPENSC_VERSION=0.7.0 diff --git a/g10/ChangeLog b/g10/ChangeLog index a7f8d4eb7..23a79cf72 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2003-07-27 Werner Koch <wk@gnupg.org> + + Adjusted for gcry_mpi_print and gcry_mpi_scan API change. + 2003-07-24 Werner Koch <wk@gnupg.org> * g10.c: New command --card-status. diff --git a/g10/call-agent.c b/g10/call-agent.c index ed4fa9054..00d124f0b 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -647,7 +647,7 @@ scd_genkey_cb (void *opaque, const char *line) while (spacep (line)) line++; - rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0); + 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)) diff --git a/g10/comment.c b/g10/comment.c index 3108351e4..ab5d2941e 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -86,11 +86,11 @@ make_mpi_comment_node( const char *s, gcry_mpi_t a ) size_t n = strlen(s); nb1 = mpi_get_nbits( a ); - if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, &n1, 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, a)) + if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, n1, &n1, a)) BUG (); pkt = xcalloc (1, sizeof *pkt ); diff --git a/g10/export.c b/g10/export.c index 32addfa4a..43d1b21ed 100644 --- a/g10/export.c +++ b/g10/export.c @@ -441,13 +441,13 @@ static int write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) { int rc; - char *buffer; + unsigned char *buffer; write_sexp_line (out, indent, "("); iobuf_writestr (out, name); iobuf_writestr (out, " #"); - rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void **)&buffer, NULL, a); + rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); assert (!rc); iobuf_writestr (out, buffer); iobuf_writestr (out, "#)"); diff --git a/g10/keyid.c b/g10/keyid.c index ea0632dcc..aaa70cccb 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -67,11 +67,12 @@ do_fingerprint_md( PKT_public_key *pk ) for(i=0; i < npkey; i++ ) { size_t nbytes; - if (gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, pk->pkey[i] )) + 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, pk->pkey[i] )) + if (gcry_mpi_print ( GCRYMPI_FMT_PGP, pp[i], nbytes, &nbytes, + pk->pkey[i] )) BUG (); nn[i] = nbytes; n += nn[i]; @@ -135,11 +136,11 @@ v3_keyid (gcry_mpi_t a, u32 *ki) byte *buffer; size_t nbytes; - if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, &nbytes, a )) + 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, a )) + if (gcry_mpi_print( GCRYMPI_FMT_USG, buffer, nbytes, NULL, a )) BUG (); if (nbytes < 8) /* oops */ ki[0] = ki[1] = 0; @@ -476,19 +477,20 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len ) if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) { size_t nbytes; - if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, pk->pkey[0])) + 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, pk->pkey[0])) + 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, &nbytes, pk->pkey[1])) + 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, pk->pkey[1])) + if (gcry_mpi_print( GCRYMPI_FMT_USG, buf, nbytes, NULL,pk->pkey[1])) BUG (); gcry_md_write( md, buf, nbytes ); xfree(buf); @@ -533,19 +535,19 @@ fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) { size_t nbytes; - if (gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, sk->skey[0])) + 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, sk->skey[0])) + 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, &nbytes, sk->skey[1])) + 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, sk->skey[1])) + if (gcry_mpi_print( GCRYMPI_FMT_USG, buf,nbytes, NULL, sk->skey[1])) BUG (); gcry_md_write( md, buf, nbytes ); xfree(buf); diff --git a/g10/misc.c b/g10/misc.c index 5cdad1598..ad04ce76f 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -122,14 +122,14 @@ checksum_mpi( gcry_mpi_t a ) byte *buffer; size_t nbytes; - rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a ); + rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a ); if (rc) BUG (); /* fixme: for numbers not in secure memory we should use a stack * based buffer and only allocate a larger one if mpi_print return * an error */ - buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes) : gcry_xmalloc(nbytes); - rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a ); + buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes):gcry_xmalloc(nbytes); + rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a ); if (rc) BUG (); csum = checksum (buffer, nbytes ); @@ -827,7 +827,7 @@ mpi_write( iobuf_t out, gcry_mpi_t a ) int rc; nbytes = (MAX_EXTERN_MPI_BITS+7)/8; - rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a ); + rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); if( !rc ) rc = iobuf_write( out, buffer, nbytes ); @@ -891,7 +891,7 @@ mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure) nread++; } nread += nbytes; - if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, &nread ) ) + if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) ) a = NULL; leave: @@ -961,9 +961,9 @@ mpi_print( FILE *fp, gcry_mpi_t a, int mode ) } else { int rc; - char *buffer; + unsigned char *buffer; - rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, (void **)&buffer, NULL, a ); + rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, &buffer, NULL, a ); assert( !rc ); fputs( buffer, fp ); n += strlen(buffer); diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index d052546e3..4b45b9f5c 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -149,7 +149,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) char *rbuf; size_t rbuflen; char *snbuf; - void *indata = NULL; + unsigned char *indata = NULL; unsigned int indatalen; snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); @@ -170,14 +170,11 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) } else { - void *indata; - rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey); if( rc ) goto leave; - if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &nframe, plain_dek)) + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek)) BUG(); - frame = indata; gcry_mpi_release (plain_dek); plain_dek = NULL; } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 65be7a468..c9bddd2ff 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -161,10 +161,9 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, because the length may have an arbitrary value */ if( sk->csum == csum ) { for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - nbytes = ndata; assert( gcry_is_secure( p ) ); res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP, - p, &nbytes); + p, ndata, &nbytes); if( res ) log_bug ("gcry_mpi_scan failed in do_check: %s\n", gpg_strerror (res)); @@ -197,7 +196,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, csum += checksum (buffer, ndata); gcry_mpi_release (sk->skey[i]); res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG, - buffer, &ndata ); + buffer, ndata, &ndata ); if( res ) log_bug ("gcry_mpi_scan failed in do_check: %s\n", gpg_strerror (res)); @@ -352,7 +351,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) GCRY_STRONG_RANDOM); gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); if( sk->version >= 4 ) { - byte *bufarr[PUBKEY_MAX_NSKEY]; + unsigned char *bufarr[PUBKEY_MAX_NSKEY]; unsigned narr[PUBKEY_MAX_NSKEY]; unsigned nbits[PUBKEY_MAX_NSKEY]; int ndata=0; @@ -363,7 +362,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE )); - if( gcry_mpi_aprint( GCRYMPI_FMT_USG, (void**)bufarr+j, + if( gcry_mpi_aprint( GCRYMPI_FMT_USG, bufarr+j, narr+j, sk->skey[i])) BUG(); diff --git a/g10/seskey.c b/g10/seskey.c index 11ebe17aa..be2535ace 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -148,7 +148,7 @@ encode_session_key (DEK *dek, unsigned int nbits) if (DBG_CIPHER) log_printhex ("encoded session key:", frame, nframe ); - if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe)) + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe)) BUG(); xfree (frame); return a; @@ -185,7 +185,7 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, memcpy( frame+n, asn, asnlen ); n += asnlen; memcpy( frame+n, gcry_md_read (md, algo), len ); n += len; assert( n == nframe ); - if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, &nframe )) + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe )) BUG(); xfree (frame); return a; @@ -214,7 +214,7 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo, return NULL; } if (gcry_mpi_scan( &frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), &n ) ) + gcry_md_read (md, hash_algo), n, &n ) ) BUG(); } else diff --git a/g10/sig-check.c b/g10/sig-check.c index ae5c32eaf..4547c6e12 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -111,7 +111,7 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, gcry_md_putc( digest, a & 0xff ); for(i=0; i < nsig; i++ ) { size_t n; - void *tmp; + unsigned char *tmp; if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &tmp, &n, sig->data[i])) BUG(); diff --git a/g10/sign.c b/g10/sign.c index bdeb37d07..493bfb4d9 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -304,8 +304,8 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, xfree (snbuf); if (!rc) { - unsigned int nbytes = rbuflen; - if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, rbuf, &nbytes )) + if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, + rbuf, rbuflen, NULL )) BUG (); } } @@ -325,8 +325,8 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, xfree (snbuf); if (!rc) { - unsigned int nbytes = rbuflen; - if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, rbuf, &nbytes )) + if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, + rbuf, rbuflen, NULL)) BUG (); } } -- cgit v1.2.3 From 6f7ed0590060cc013946e192f725545445e6c39f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Jul 2003 08:53:19 +0000 Subject: * gpgsm.c (main): Add secmem features and set the random seed file. (gpgsm_exit): Update the random seed file and enable debug output. * g10.c (main): Add secmem features and set the random seed file. (g10_exit): Update the random seed file. * parse-packet.c (parse_signature,read_protected_v3_mpi) (parse_key): Fixed use of mpi_set_opaque. * keygen.c (gen_card_key): Ditto. --- g10/ChangeLog | 23 ++ g10/comment.c | 13 +- g10/g10.c | 40 ++-- g10/keygen.c | 656 ++++++++++++++++++++++++++++++++++++----------------- g10/main.h | 1 + g10/parse-packet.c | 20 +- g10/seckey-cert.c | 2 +- g10/status.c | 23 +- 8 files changed, 518 insertions(+), 260 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 23a79cf72..335f28fdf 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,26 @@ +2003-07-29 Werner Koch <wk@gnupg.org> + + * g10.c (main): Add secmem features and set the random seed file. + (g10_exit): Update the random seed file. + + * parse-packet.c (parse_signature,read_protected_v3_mpi) + (parse_key): Fixed use of mpi_set_opaque. + * keygen.c (gen_card_key): Ditto. + +2003-07-28 Werner Koch <wk@gnupg.org> + + * status.c (progress_cb): Adjusted for use with Libcgrypt. + (set_status_fd): Register that callback. + + * keygen.c (smartcard_change_login_data): New. + (smartcard_change_lang): New. + (smartcard_change_sex): New. + (check_smartcard): Add menu entries to edit the above. + (gen_elg,gen_dsa,gen_rsa): Reimplemented in terms of Libgcrypt. + (genhelp_protect, genhelp_factors, key_from_sexp): New. + * comment.c (make_comment_node_from_buffer): New. + (make_comment_node): Reimplemented in terms of above. + 2003-07-27 Werner Koch <wk@gnupg.org> Adjusted for gcry_mpi_print and gcry_mpi_scan API change. diff --git a/g10/comment.c b/g10/comment.c index ab5d2941e..b52104cd7 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -63,19 +63,24 @@ write_comment( iobuf_t out, const char *s ) KBNODE -make_comment_node( const char *s ) +make_comment_node_from_buffer (const char *s, size_t n) { PACKET *pkt; - size_t n = strlen(s); - pkt = xcalloc (1, sizeof *pkt ); + pkt = gcry_xcalloc( 1, sizeof *pkt ); pkt->pkttype = PKT_COMMENT; - pkt->pkt.comment = xmalloc ( sizeof *pkt->pkt.comment + n - 1 ); + 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 ) diff --git a/g10/g10.c b/g10/g10.c index 2f0a78cd0..f89556184 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -32,6 +32,7 @@ #ifdef HAVE_STAT #include <sys/stat.h> /* for stat() */ #endif +#include <assuan.h> #define INCLUDED_BY_MAIN_MODULE 1 #include "gpg.h" @@ -1759,8 +1760,7 @@ main( int argc, char **argv ) break; case oCertDigestAlgo: cert_digest_string = xstrdup (pargs.r.ret_str); break; case oNoSecmemWarn: -#warning add secmem_get_flags -/* secmem_set_flags( secmem_get_flags() | 1 ); */ + gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break; case oNoPermissionWarn: opt.no_perm_warn=1; break; case oNoMDCWarn: opt.no_mdc_warn=1; break; @@ -1993,9 +1993,6 @@ main( int argc, char **argv ) } #endif -#warning locking does not work - disabled - disable_dotlock (); - if (opt.verbose > 2) log_info ("using character set `%s'\n", get_native_charset ()); @@ -2026,10 +2023,7 @@ main( int argc, char **argv ) if( opt.batch ) tty_batchmode( 1 ); -#warning fix that -#if 0 - secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */ -#endif + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); set_debug(); /* Do these after the switch(), so they can override settings. */ @@ -2274,10 +2268,7 @@ main( int argc, char **argv ) /* set the random seed file */ if( use_random_seed ) { char *p = make_filename(opt.homedir, "random_seed", NULL ); -#warning No random seed file yet -#if 0 - set_random_seed_file(p); -#endif + gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); xfree (p); } @@ -2936,17 +2927,18 @@ emergency_cleanup (void) void g10_exit( int rc ) { - /* FIXME-XX update_random_seed_file(); */ -/* if( opt.debug & DBG_MEMSTAT_VALUE ) { */ -/* m_print_stats("on exit"); */ -/* random_dump_stats(); */ -/* } */ -/* if( opt.debug ) */ -/* secmem_dump_stats(); */ - gcry_control (GCRYCTL_TERM_SECMEM ); - rc = rc? rc : log_get_errorcount(0)? 2 : - g10_errors_seen? 1 : 0; - exit(rc ); + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); + if (opt.debug & DBG_MEMSTAT_VALUE) + { + gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); + gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + } + if (opt.debug) + gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); + emergency_cleanup (); + rc = rc? rc : log_get_errorcount(0)? 2 : + g10_errors_seen? 1 : 0; + exit (rc ); } diff --git a/g10/keygen.c b/g10/keygen.c index 515d4867a..210bbc897 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -740,86 +740,198 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, static int -gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, + const char *topname, const char *elems) { - int rc; - int i; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_mpi_t skey[4]; - gcry_mpi_t *factors; + gcry_sexp_t list, l2; + const char *s; + int i, idx; + int rc = 0; + + list = gcry_sexp_find_token (sexp, topname, 0); + if (!list) + return gpg_error (GPG_ERR_INV_OBJ); + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + if (!list) + return gpg_error (GPG_ERR_NO_OBJ); + + for (idx=0,s=elems; *s; s++, idx++) + { + l2 = gcry_sexp_find_token (list, s, 1); + if (!l2) + { + rc = gpg_error (GPG_ERR_NO_OBJ); /* required parameter not found */ + goto leave; + } + array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + if (!array[idx]) + { + rc = gpg_error (GPG_ERR_INV_OBJ); /* required parameter invalid */ + goto leave; + } + } + gcry_sexp_release (list); + + leave: + if (rc) + { + for (i=0; i<idx; i++) + { + xfree (array[i]); + array[i] = NULL; + } + gcry_sexp_release (list); + } + return rc; +} - assert( is_ELGAMAL(algo) ); - if( nbits < 512 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); +static int +genhelp_protect (DEK *dek, STRING2KEY *s2k, PKT_secret_key *sk) +{ + int rc = 0; + + if (dek) + { + sk->protect.algo = dek->algo; + sk->protect.s2k = *s2k; + rc = protect_secret_key (sk, dek); + if (rc) + log_error ("protect_secret_key failed: %s\n", gpg_strerror (rc) ); } - if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - log_info(_("keysize rounded up to %u bits\n"), nbits ); + return rc; +} + +static void +genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root) +{ + size_t n; + char *buf; + + if (misc_key_info) + { + /* DSA: don't know whether it makes sense to have the factors, so for now + we store them in the secret keyring (but they are not secret) + p = 2 * q * f1 * f2 * ... * fn + We store only f1 to f_n-1; fn can be calculated because p and q + are known. */ + n = gcry_sexp_sprint (misc_key_info, 0, NULL, 0); + buf = xmalloc (n+4); + strcpy (buf, "#::"); + n = gcry_sexp_sprint (misc_key_info, 0, buf+3, n); + if (n) + { + n += 3; + add_kbnode (sec_root, make_comment_node_from_buffer (buf, n)); + } + xfree (buf); + gcry_sexp_release (misc_key_info); } +} -#warning need to implement this - rc = -1 /*pubkey_generate( algo, nbits, skey, &factors )*/; - if( rc ) { - log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); - return rc; + +static int +gen_elg(int algo, unsigned int nbits, + KBNODE pub_root, KBNODE sec_root, DEK *dek, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +{ + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; + gcry_sexp_t misc_key_info; + + assert (is_ELGAMAL(algo)); + + if (nbits < 512) + { + nbits = 1024; + log_info (_("keysize invalid; using %u bits\n"), nbits); } - sk = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = algo; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - pk->pkey[2] = mpi_copy( skey[2] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi( sk->skey[3] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - if( dek ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - if( rc ) { - log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } + if ((nbits % 32)) + { + nbits = ((nbits + 31) / 32) * 32; + log_info (_("keysize rounded up to %u bits\n"), nbits); + } + + rc = gcry_sexp_build ( &s_parms, NULL, + "(genkey(%s(nbits %d)))", + algo == GCRY_PK_ELG_E ? "openpgp-elg" : + algo == GCRY_PK_ELG ? "elg" : "x-oops" , + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + return rc; } - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); + sk = xcalloc (1, sizeof *sk); + pk = xcalloc (1, sizeof *pk); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if (expireval) + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + sk->pubkey_algo = pk->pubkey_algo = algo; - /* don't know whether it makes sense to have the factors, so for now - * we store them in the secret keyring (but they are not secret) */ - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - for(i=0; factors[i]; i++ ) - add_kbnode( sec_root, - make_mpi_comment_node("#:ELG_factor:", factors[i] )); + rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + return rc; + } + rc = key_from_sexp (sk->skey, s_key, "private-key", "pgyx"); + if (rc) + { + log_error("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + return rc; + } + misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); + gcry_sexp_release (s_key); - return 0; + sk->is_protected = 0; + sk->protect.algo = 0; + + sk->csum = checksum_mpi (sk->skey[3]); + if (ret_sk) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key (NULL, sk); + + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + gcry_sexp_release (misc_key_info); + return rc; + } + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + /* don't know whether it makes sense to have the factors, so for now + * we store them in the secret keyring (but they are not secret) */ + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + genhelp_factors (misc_key_info, sec_root); + + return 0; } @@ -827,90 +939,96 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, * Generate a DSA key */ static int -gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) +gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { - int rc; - int i; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_mpi_t skey[5]; - gcry_mpi_t *factors; + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; + gcry_sexp_t misc_key_info; - if( nbits > 1024 || nbits < 512 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); + if (nbits > 1024 || nbits < 512) + { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits); } - if( (nbits % 64) ) { - nbits = ((nbits + 63) / 64) * 64; - log_info(_("keysize rounded up to %u bits\n"), nbits ); + if ((nbits % 64)) + { + nbits = ((nbits + 63) / 64) * 64; + log_info (_("keysize rounded up to %u bits\n"), nbits); } -#warning need to implement this - rc = -1 /*pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors )*/; - if( rc ) { - log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); - return rc; + rc = gcry_sexp_build (&s_parms, NULL, + "(genkey(dsa(nbits %d)))", + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + return rc; } - sk = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - pk->pkey[2] = mpi_copy( skey[2] ); - pk->pkey[3] = mpi_copy( skey[3] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->skey[4] = skey[4]; - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi ( sk->skey[4] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - if( dek ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - if( rc ) { - log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if (expireval) + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; + + rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); + gcry_sexp_release (s_key); + return rc; } + rc = key_from_sexp (sk->skey, s_key, "private-key", "pqgyx"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + return rc; + } + misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); + gcry_sexp_release (s_key); - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - /* don't know whether it makes sense to have the factors, so for now - * we store them in the secret keyring (but they are not secret) - * p = 2 * q * f1 * f2 * ... * fn - * We store only f1 to f_n-1; fn can be calculated because p and q - * are known. - */ - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - for(i=1; factors[i]; i++ ) /* the first one is q */ - add_kbnode( sec_root, - make_mpi_comment_node("#:DSA_factor:", factors[i] )); + sk->is_protected = 0; + sk->protect.algo = 0; - return 0; + sk->csum = checksum_mpi ( sk->skey[4] ); + if (ret_sk) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); + + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + gcry_sexp_release (misc_key_info); + return rc; + } + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + genhelp_factors (misc_key_info, sec_root); + + return 0; } @@ -921,81 +1039,93 @@ static int gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_mpi_t skey[6]; - gcry_mpi_t *factors; + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; - assert( is_RSA(algo) ); + assert (is_RSA(algo)); - if( nbits < 1024 ) { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits ); + if (nbits < 1024) + { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits); } - if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - log_info(_("keysize rounded up to %u bits\n"), nbits ); + if ((nbits % 32)) + { + nbits = ((nbits + 31) / 32) * 32; + log_info (_("keysize rounded up to %u bits\n"), nbits); } -#warning need to implement this - rc = -1 /*pubkey_generate( algo, nbits, skey, &factors )*/; - if( rc ) { - log_error("pubkey_generate failed: %s\n", gpg_strerror (rc) ); - return rc; + rc = gcry_sexp_build (&s_parms, NULL, + "(genkey(rsa(nbits %d)))", + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + return rc; } - sk = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } - sk->pubkey_algo = pk->pubkey_algo = algo; - pk->pkey[0] = mpi_copy( skey[0] ); - pk->pkey[1] = mpi_copy( skey[1] ); - sk->skey[0] = skey[0]; - sk->skey[1] = skey[1]; - sk->skey[2] = skey[2]; - sk->skey[3] = skey[3]; - sk->skey[4] = skey[4]; - sk->skey[5] = skey[5]; - sk->is_protected = 0; - sk->protect.algo = 0; - - sk->csum = checksum_mpi (sk->skey[2] ); - sk->csum += checksum_mpi (sk->skey[3] ); - sk->csum += checksum_mpi (sk->skey[4] ); - sk->csum += checksum_mpi (sk->skey[5] ); - if( ret_sk ) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); - - if( dek ) { - sk->protect.algo = dek->algo; - sk->protect.s2k = *s2k; - rc = protect_secret_key( sk, dek ); - if( rc ) { - log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); - free_public_key(pk); - free_secret_key(sk); - return rc; - } + sk = xcalloc (1, sizeof *sk ); + pk = xcalloc (1, sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if (expireval) + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + sk->pubkey_algo = pk->pubkey_algo = algo; + + rc = key_from_sexp (pk->pkey, s_key, "public-key", "ne"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); + gcry_sexp_release (s_key); + return rc; + } + rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + return rc; } + gcry_sexp_release (s_key); - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); + sk->is_protected = 0; + sk->protect.algo = 0; - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); + sk->csum = checksum_mpi (sk->skey[2] ); + sk->csum += checksum_mpi (sk->skey[3] ); + sk->csum += checksum_mpi (sk->skey[4] ); + sk->csum += checksum_mpi (sk->skey[5] ); + if (ret_sk) /* not a subkey: return an unprotected version of the sk */ + *ret_sk = copy_secret_key (NULL, sk); - return 0; + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + return rc; + } + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode (pub_root, new_kbnode( pkt )); + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + return 0; } @@ -1271,8 +1401,9 @@ ask_expire_interval(int object) tty_printf(_("%s expires at %s\n"), object==0?"Key":"Signature", asctimestamp((ulong)(curtime + interval) ) ); - /* FIXME: This check yields warning on alhas: - write a configure check and to this check here only for 32 bit machines */ + /* FIXME: This check yields warning some machines: write a + configure check and do this check here only for 32 bit + machines */ if( (time_t)((ulong)(curtime+interval)) < 0 ) tty_printf(_("Your system can't display dates beyond 2038.\n" "However, it will be correctly handled up to 2106.\n")); @@ -2803,6 +2934,97 @@ smartcard_change_url (const char *current_url) return rc; } +static int +smartcard_change_login_data (void) +{ + char *data; + int rc; + + data = cpr_get ("keygen.smartcard.login_data", + _("Login data (account name): ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + 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 +smartcard_change_lang (void) +{ + char *data, *p; + int rc; + + data = cpr_get ("keygen.smartcard.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 +smartcard_change_sex (void) +{ + char *data; + const char *str; + int rc; + + data = cpr_get ("keygen.smartcard.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; +} + /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */ static int @@ -2851,6 +3073,9 @@ check_smartcard (char **r_serialno) tty_printf ("\n" "N - change cardholder name\n" "U - change public key URL\n" + "D - change login data\n" + "L - change language preferences\n" + "S - change sex\n" "K - generate all keys\n" "Q - quit\n" "\n"); @@ -2871,6 +3096,21 @@ check_smartcard (char **r_serialno) if (!smartcard_change_url (info.pubkey_url)) reread = 1; } + else if ( *answer == 'D' || *answer == 'd') + { + if (!smartcard_change_login_data ()) + reread = 1; + } + else if ( *answer == 'L' || *answer == 'l') + { + if (!smartcard_change_lang ()) + reread = 1; + } + else if ( *answer == 'S' || *answer == 's') + { + if (!smartcard_change_sex ()) + reread = 1; + } else if ( *answer == 'K' || *answer == 'k') { if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) @@ -2972,9 +3212,9 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, sk->pubkey_algo = pk->pubkey_algo = algo; pk->pkey[0] = info.n; pk->pkey[1] = info.e; - sk->skey[0] = mpi_copy (pk->pkey[0]); - sk->skey[1] = mpi_copy (pk->pkey[1]); - sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->skey[0] = gcry_mpi_copy (pk->pkey[0]); + sk->skey[1] = gcry_mpi_copy (pk->pkey[1]); + sk->skey[2] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); sk->is_protected = 1; sk->protect.s2k.mode = 1002; s = get_parameter_value (para, pSERIALNO); diff --git a/g10/main.h b/g10/main.h index cb81192d3..2e1377ea4 100644 --- a/g10/main.h +++ b/g10/main.h @@ -188,6 +188,7 @@ gcry_mpi_t encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits, int v3compathack ); /*-- comment.c --*/ +KBNODE make_comment_node_from_buffer (const char *s, size_t n); KBNODE make_comment_node( const char *s ); KBNODE make_mpi_comment_node( const char *s, gcry_mpi_t a ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 57a6d3d7b..f70cc3f69 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1342,7 +1342,8 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, unknown_pubkey_warning( sig->pubkey_algo ); /* we store the plain material in data[0], so that we are able * to write it back with build_packet() */ - sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen ); + sig->data[0] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; } else { @@ -1446,7 +1447,7 @@ read_protected_v3_mpi (iobuf_t inp, unsigned long *length) } /* convert buffer into an opaque gcry_mpi_t */ - val = mpi_set_opaque (NULL, buf, p-buf); + val = gcry_mpi_set_opaque (NULL, buf, (p-buf)*8); return val; } @@ -1565,8 +1566,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, size_t snlen = 0; if( !npkey ) { - sk->skey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen), pktlen ); + sk->skey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; goto leave; } @@ -1744,15 +1745,16 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, if( sk->protect.s2k.mode == 1001 || sk->protect.s2k.mode == 1002 ) { /* better set some dummy stuff here */ - sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10); + sk->skey[npkey] = gcry_mpi_set_opaque(NULL, xstrdup ("dummydata"), + 10*8); pktlen = 0; } else if( is_v4 && sk->is_protected ) { /* ugly; the length is encrypted too, so we read all * stuff up to the end of the packet into the first * skey element */ - sk->skey[npkey] = mpi_set_opaque(NULL, - read_rest(inp, pktlen), pktlen ); + sk->skey[npkey] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; if( list_mode ) { printf("\tencrypted stuff follows\n"); @@ -1792,8 +1794,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_public_key *pk = pkt->pkt.public_key; if( !npkey ) { - pk->pkey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen), pktlen ); + pk->pkey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen), + pktlen*8 ); pktlen = 0; goto leave; } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index c9bddd2ff..5a7db4c97 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -323,7 +323,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) return 0; if( !sk->is_protected ) { /* okay, apply the protection */ - CIPHER_HANDLE cipher_hd=NULL; + gcry_cipher_hd_t cipher_hd=NULL; if( openpgp_cipher_test_algo( sk->protect.algo ) ) { diff --git a/g10/status.c b/g10/status.c index 32e59eef5..432ec575c 100644 --- a/g10/status.c +++ b/g10/status.c @@ -65,15 +65,15 @@ static FILE *statusfp; static void -progress_cb ( void *ctx, int c ) +progress_cb (void *ctx, const char *what, int printchar, int current, int total) { - char buf[50]; - - if ( c == '\n' ) - sprintf ( buf, "%.20s X 100 100", (char*)ctx ); - else - sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c ); - write_status_text ( STATUS_PROGRESS, buf ); + char buf[150]; + + if (printchar == '\n') + printchar = 'X'; + + sprintf (buf, "%.20s %c %d %d", what, printchar, current, total); + write_status_text (STATUS_PROGRESS, buf); } static const char * @@ -181,12 +181,7 @@ set_status_fd ( int fd ) fd, strerror(errno)); } last_fd = fd; -#warning fixme: register progress CBs -#if 0 - register_primegen_progress ( progress_cb, "primegen" ); - register_pk_dsa_progress ( progress_cb, "pk_dsa" ); - register_pk_elg_progress ( progress_cb, "pk_elg" ); -#endif + gcry_set_progress_handler (progress_cb, NULL); } int -- cgit v1.2.3 From eba8c186578ff18536998b9554dc2230485a21b0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 31 Jul 2003 15:45:11 +0000 Subject: minor changes to make make distcheck happy --- ChangeLog | 4 ++++ Makefile.am | 5 ++++- configure.ac | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2efc1bf23..b846f27a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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 diff --git a/Makefile.am b/Makefile.am index 9f5c443d5..be749a5c1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,6 +22,7 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = scripts/config.rpath autogen.sh +DISTCLEANFILES = g10defs.h if BUILD_GPG gpg = g10 @@ -45,7 +46,9 @@ scd = endif SUBDIRS = m4 intl jnlib common kbx \ - ${gpg} ${sm} ${agent} ${scd} po doc tests + ${gpg} ${sm} ${agent} ${scd} po doc + +#tests diff --git a/configure.ac b/configure.ac index 6f7782b1c..9d8aef9ee 100644 --- a/configure.ac +++ b/configure.ac @@ -1018,9 +1018,9 @@ sm/Makefile agent/Makefile scd/Makefile doc/Makefile -tests/Makefile ]) AC_OUTPUT +#tests/Makefile echo " -- cgit v1.2.3 From 9ca4830a5b8392bc7bb01211407c876fd40b49d4 Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Tue, 5 Aug 2003 17:11:04 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- agent/ChangeLog | 565 +++++++++++ agent/Makefile.am | 62 ++ agent/agent.h | 226 +++++ agent/call-scd.c | 661 +++++++++++++ agent/command.c | 782 +++++++++++++++ agent/divert-scd.c | 319 +++++++ agent/findkey.c | 359 +++++++ agent/genkey.c | 240 +++++ agent/gpg-agent.c | 1063 +++++++++++++++++++++ agent/learncard.c | 448 +++++++++ agent/minip12.c | 1140 ++++++++++++++++++++++ agent/minip12.h | 33 + agent/pkdecrypt.c | 138 +++ agent/pksign.c | 185 ++++ agent/protect-tool.c | 977 +++++++++++++++++++ agent/protect.c | 971 +++++++++++++++++++ agent/simple-pwquery.c | 486 ++++++++++ common/ChangeLog | 219 +++++ common/Makefile.am | 58 ++ common/README | 11 + common/errors.h | 110 +++ common/gettime.c | 250 +++++ common/iobuf.c | 2415 +++++++++++++++++++++++++++++++++++++++++++++++ common/iobuf.h | 170 ++++ common/maperror.c | 157 +++ common/membuf.c | 89 ++ common/membuf.h | 41 + common/miscellaneous.c | 126 +++ common/simple-pwquery.c | 486 ++++++++++ common/simple-pwquery.h | 69 ++ common/ttyio.c | 508 ++++++++++ common/ttyio.h | 40 + common/util.h | 120 +++ common/yesno.c | 96 ++ kbx/Makefile.am | 52 + kbx/kbxutil.c | 339 +++++++ kbx/keybox-blob.c | 1008 ++++++++++++++++++++ scd/ChangeLog | 242 +++++ scd/Makefile.am | 72 ++ scd/apdu.c | 558 +++++++++++ scd/apdu.h | 73 ++ scd/app-common.h | 128 +++ scd/app-openpgp.c | 1482 +++++++++++++++++++++++++++++ scd/app.c | 278 ++++++ scd/card-common.h | 73 ++ scd/card-p15.c | 502 ++++++++++ scd/card.c | 564 +++++++++++ scd/command.c | 1034 ++++++++++++++++++++ scd/iso7816.c | 371 ++++++++ scd/iso7816.h | 56 ++ scd/sc-copykeys.c | 731 ++++++++++++++ scd/sc-investigate.c | 209 ++++ scd/scdaemon.c | 638 +++++++++++++ scd/scdaemon.h | 127 +++ sm/ChangeLog | 816 ++++++++++++++++ sm/Makefile.am | 55 ++ sm/call-agent.c | 713 ++++++++++++++ sm/call-dirmngr.c | 632 +++++++++++++ sm/certchain.c | 793 ++++++++++++++++ sm/certcheck.c | 300 ++++++ sm/certdump.c | 457 +++++++++ sm/certlist.c | 315 +++++++ sm/certreqgen.c | 699 ++++++++++++++ sm/decrypt.c | 506 ++++++++++ sm/delete.c | 165 ++++ sm/encrypt.c | 550 +++++++++++ sm/export.c | 249 +++++ sm/fingerprint.c | 271 ++++++ sm/gpgsm.c | 1458 ++++++++++++++++++++++++++++ sm/gpgsm.h | 274 ++++++ sm/import.c | 349 +++++++ sm/keydb.c | 1282 +++++++++++++++++++++++++ sm/keylist.c | 617 ++++++++++++ sm/server.c | 1070 +++++++++++++++++++++ sm/sign.c | 621 ++++++++++++ sm/verify.c | 550 +++++++++++ 76 files changed, 34899 insertions(+) create mode 100644 agent/ChangeLog create mode 100644 agent/Makefile.am create mode 100644 agent/agent.h create mode 100644 agent/call-scd.c create mode 100644 agent/command.c create mode 100644 agent/divert-scd.c create mode 100644 agent/findkey.c create mode 100644 agent/genkey.c create mode 100644 agent/gpg-agent.c create mode 100644 agent/learncard.c create mode 100644 agent/minip12.c create mode 100644 agent/minip12.h create mode 100644 agent/pkdecrypt.c create mode 100644 agent/pksign.c create mode 100644 agent/protect-tool.c create mode 100644 agent/protect.c create mode 100644 agent/simple-pwquery.c create mode 100644 common/ChangeLog create mode 100644 common/Makefile.am create mode 100644 common/README create mode 100644 common/errors.h create mode 100644 common/gettime.c create mode 100644 common/iobuf.c create mode 100644 common/iobuf.h create mode 100644 common/maperror.c create mode 100644 common/membuf.c create mode 100644 common/membuf.h create mode 100644 common/miscellaneous.c create mode 100644 common/simple-pwquery.c create mode 100644 common/simple-pwquery.h create mode 100644 common/ttyio.c create mode 100644 common/ttyio.h create mode 100644 common/util.h create mode 100644 common/yesno.c create mode 100644 kbx/Makefile.am create mode 100644 kbx/kbxutil.c create mode 100644 kbx/keybox-blob.c create mode 100644 scd/ChangeLog create mode 100644 scd/Makefile.am create mode 100644 scd/apdu.c create mode 100644 scd/apdu.h create mode 100644 scd/app-common.h create mode 100644 scd/app-openpgp.c create mode 100644 scd/app.c create mode 100644 scd/card-common.h create mode 100644 scd/card-p15.c create mode 100644 scd/card.c create mode 100644 scd/command.c create mode 100644 scd/iso7816.c create mode 100644 scd/iso7816.h create mode 100644 scd/sc-copykeys.c create mode 100644 scd/sc-investigate.c create mode 100644 scd/scdaemon.c create mode 100644 scd/scdaemon.h create mode 100644 sm/ChangeLog create mode 100644 sm/Makefile.am create mode 100644 sm/call-agent.c create mode 100644 sm/call-dirmngr.c create mode 100644 sm/certchain.c create mode 100644 sm/certcheck.c create mode 100644 sm/certdump.c create mode 100644 sm/certlist.c create mode 100644 sm/certreqgen.c create mode 100644 sm/decrypt.c create mode 100644 sm/delete.c create mode 100644 sm/encrypt.c create mode 100644 sm/export.c create mode 100644 sm/fingerprint.c create mode 100644 sm/gpgsm.c create mode 100644 sm/gpgsm.h create mode 100644 sm/import.c create mode 100644 sm/keydb.c create mode 100644 sm/keylist.c create mode 100644 sm/server.c create mode 100644 sm/sign.c create mode 100644 sm/verify.c diff --git a/agent/ChangeLog b/agent/ChangeLog new file mode 100644 index 000000000..10f4d45fa --- /dev/null +++ b/agent/ChangeLog @@ -0,0 +1,565 @@ +2003-07-31 Werner Koch <wk@gnupg.org> + + * Makefile.am (gpg_agent_LDADD): Added INTLLIBS. + (gpg_protect_tool_SOURCES): Added simple-pwquery.[ch] + +2003-07-27 Werner Koch <wk@gnupg.org> + + Adjusted for gcry_mpi_print and gcry_mpi_scan API change. + +2003-07-15 Werner Koch <wk@gnupg.org> + + * simple-pwquery.c, simple-pwquery.h: Moved to ../common. + * Makefile.am (gpg_protect_tool_LDADD): Add simple-pwquery.o. + Removed it from xx_SOURCES. + +2003-07-04 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (handle_connections): Kludge to allow use of Pth 1 + and 2. + +2003-06-30 Werner Koch <wk@gnupg.org> + + * call-scd.c (learn_status_cb): Store the serialno in PARM. + +2003-06-26 Werner Koch <wk@gnupg.org> + + * call-scd.c (agent_card_serialno): Don't do a RESET anymore. + +2003-06-25 Werner Koch <wk@gnupg.org> + + * command.c (cmd_scd): New. + * call-scd.c (agent_card_scd): New. + * divert-scd.c (divert_generic_cmd): New + + * call-scd.c (agent_card_learn): New callback args SINFO. + (learn_status_cb): Pass all other status lines to the sinfo + callback. + * learncard.c (release_sinfo, sinfo_cb): New. + (agent_handle_learn): Pass the new cb to the learn function and + pass the collected information back to the client's assuan + connection. + + * gpg-agent.c (main): Moved pth_init before gcry_check_version. + +2003-06-24 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (handle_connections): Adjusted for Pth 2.0 + + Adjusted for changes in the libgcrypt API. Some more fixes for the + libgpg-error stuff. + +2003-06-04 Werner Koch <wk@gnupg.org> + + Renamed error codes from INVALID to INV and removed _ERROR suffixes. + +2003-06-03 Werner Koch <wk@gnupg.org> + + Changed all error codes in all files to the new libgpg-error scheme. + + * agent.h: Include gpg-error.h and errno.h + * Makefile.am: Link with libgpg-error + + * query.c: assuan.h is now a system header. + * genkey.c (agent_genkey): Fixed silly use of xmalloc by + xtrymalloc. + +2003-04-29 Werner Koch <wk@gnupg.org> + + * command.c (register_commands): Adjusted for new Assuan semantics. + + * Makefile.am: Don't override LDFLAGS. + +2002-12-04 Werner Koch <wk@gnupg.org> + + * gpg-agent.c: New variable config_filename. + (parse_rereadable_options): New. + (main): Use it here. Add setting of default values, set + config_filename. + (reread_configuration): Filled with actual code. + +2002-12-03 Werner Koch <wk@gnupg.org> + + * protect-tool.c (read_key): Don't run make_canonical on a NULL + buffer. + + * command.c (parse_hexstring): New. + (cmd_sethash): Use it. + (parse_keygrip): New. + (cmd_havekey, cmd_sigkey): Use it. + (cmd_passwd): New. + * genkey.c (agent_protect_and_store): New. + (store_key): Add arg FORCE. + (agent_genkey): Pass false to this force of store_key. + +2002-11-13 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): Switch all messages to utf-8. + + * simple-pwquery.c (agent_send_all_options): Use $GPG_TTY and + stdin with ttyname. + + * cache.c (new_data): Uiih - /sizeof d/sizeof *d/. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * command.c (option_handler): Fix keep_tty check. + +2002-11-06 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): Make sure we have a default ttyname. + * command.c (option_handler): Check opt.keep_tty here + * query.c (start_pinentry): but not anymore here. + +2002-11-05 Werner Koch <wk@gnupg.org> + + * agent.h (opt,server_control_s): Move display and lc_ variables + to the control struct so that they are per connection. + * gpg-agent.c (agent_init_default_ctrl): New. + (main): Assign those command line options to new default_* variables. + Reset DISPLAY in server mode so that tehre is no implicit default. + * command.c (start_command_handler): Initialize and deinitialize + the control values. + (option_handler): Work on the ctrl values and not on the opt. + * query.c (start_pinentry): New argument CTRL to set the display + connection specific. Changed all callers to pass this value. + (agent_askpin,agent_get_passphrase,agent_get_confirmation): Add + CTRL arg and pass it ot start_pinentry. + * command.c (cmd_get_passphrase): Pass CTRL argument. + * trustlist.c (agent_marktrusted): Add CTRL argument + * command.c (cmd_marktrusted): Pass CTRL argument + * divert-scd.c (ask_for_card): Add CTRL arg. + (divert_pksign,divert_pkdecrypt): Ditto. Changed caller. + (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both + users. + * findkey.c (unprotect): Add CTRL arg. + (agent_key_from_file): Ditto. + + * query.c (unlock_pinentry): Disconnect the pinentry so that we + start a new one for each request. This is required to support + clients with different environments (e.g. X magic cookies). + +2002-09-05 Neal H. Walfield <neal@cs.uml.edu> + + * gpg-agent.c (main) [USE_GNU_PTH]: No need to call + assuan_set_io_func as assuan is smart. + +2002-09-25 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (handle_signal): Flush cache on SIGHUP. + * cache.c (agent_flush_cache): New. + + * gpg-agent.c, agent.h: Add --keep-display and --keep-tty. + * query.c (start_pinentry): Implement them. The option passing + needs more thoughts. + +2002-09-09 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (create_private_keys_directory) + (create_directories): New. + (main): Try to create a home directory. + +2002-09-04 Neal H. Walfield <neal@g10code.de> + + * gpg-agent.c (main): Use sigaction, not signal. + +2002-09-03 Neal H. Walfield <neal@g10code.de> + + * findkey.c: Include <fcntl.h>. + (agent_write_private_key): Prefer POSIX compatibity, open and + fdopen, over the simplicity of GNU extensions, fopen(file, "x"). + +2002-08-22 Werner Koch <wk@gnupg.org> + + * query.c (agent_askpin): Provide the default desc text depending + on the pininfo. Do the basic PIN verification only when + min_digits is set. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * query.c (agent_askpin): Hack to show the right default prompt. + (agent_get_passphrase): Ditto. + + * trans.c: Removed and replaced all usages with standard _() + + * divert-scd.c (getpin_cb): Pass a more descritive text to the + pinentry. + + * Makefile.am: Renamed the binary protect-tool to gpg-protect-tool. + * protect-tool.c: Removed the note about internal use only. + + * gpg-agent.c (main): New option --daemon so that the program is + not accidently started in the background. + +2002-08-16 Werner Koch <wk@gnupg.org> + + * call-scd.c (learn_status_cb): Handle CERTINFO status. + (agent_card_learn): Add args for certinfo cb. + * learncard.c (release_certinfo,certinfo_cb): New. + (send_cert_back): New. With factored out code from .. + (agent_handle_learn): here. Return certinfo stuff. + +2002-07-26 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): New option --ignore-cache-for-signing. + * command.c (option_handler): New server option + use-cache-for-signing defaulting to true. + (cmd_pksign): handle global and per session option. + * findkey.c (agent_key_from_file, unprotect): New arg + ignore_cache. Changed all callers. + * pksign.c (agent_pksign): Likewise. + +2002-06-29 Werner Koch <wk@gnupg.org> + + * query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY. + * call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON. + +2002-06-28 Werner Koch <wk@gnupg.org> + + * protect-tool.c (export_p12_file): New. + (main): New command --p12-export. + * minip12.c (create_final,p12_build,compute_tag_length): New. + (store_tag_length): New. + +2002-06-27 Werner Koch <wk@gnupg.org> + + * minip12.c (crypt_block): Renamed from decrypt_block, add arg to + allow encryption. + + * Makefile.am (pkglib_PROGRAMS): Put protect-tool there. + + * findkey.c (agent_write_private_key,agent_key_from_file) + (agent_key_available): Use GNUPG_PRIVATE_KEYS_DIR constant. + * gpg-agent.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. + + * protect-tool.c (store_private_key): New. + (import_p12_file): Store the new file if requested. + (main): New options --force and --store. + + * gpg-agent.c (main): Set a global flag when running detached. + * query.c (start_pinentry): Pass the list of FD to keep in the + child when not running detached. + * call-scd.c (start_scd): Ditto. + +2002-06-26 Werner Koch <wk@gnupg.org> + + * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted) + (cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_get_passphrase) + (cmd_learn): Print an error message for a failed operation. + + * simple-pwquery.c, simple-pwquery.h: New. + * protect-tool. (get_passphrase): New, used to get a passphrase + from the agent if none was given on the command line. + +2002-06-25 Werner Koch <wk@gnupg.org> + + * protect-tool.c (rsa_key_check): New. + (import_p12_file): New. + (main): New command --p12-import. + * minip12.c, minip12.h: New. + +2002-06-24 Werner Koch <wk@gnupg.org> + + * protect-tool.c (read_file): New. + (read_key): Factored most code out to read_file. + +2002-06-17 Werner Koch <wk@gnupg.org> + + * agent.h: Add a callback function to the pin_entry_info structure. + * query.c (agent_askpin): Use the callback to check for a correct + PIN. Removed the start_err_text argument because it is not + anymore needed; changed callers. + * findkey.c (unprotect): Replace our own check loop by a callback. + (try_unprotect_cb): New. + * genkey.c (reenter_compare_cb): New. + (agent_genkey): Use this callback here. Fixed setting of the pi2 + variable and a segv in case of an empty PIN. + + * divert-scd.c (getpin_cb): Removed some unused stuff and + explained what we still have to change. + +2002-06-12 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): New option --disable-pth. + +2002-06-11 Werner Koch <wk@gnupg.org> + + * protect-tool.c: Add command --show-keygrip + (show_keygrip): New. + +2002-05-23 Werner Koch <wk@gnupg.org> + + * call-scd.c: Seirialized all scdaeom access when using Pth. + + * cache.c: Made the cache Pth-thread-safe. + (agent_unlock_cache_entry): New. + * findkey.c (unprotect): Unlock the returned cache value. + * command.c (cmd_get_passphrase): Ditto. + + * gpg-agent.c (main): Register pth_read/write with Assuan. + +2002-05-22 Werner Koch <wk@gnupg.org> + + * query.c: Serialized all pinentry access when using Pth. + + * gpg-agent.c (handle_signal,start_connection_thread) + (handle_connections): New + (main): Use the new Pth stuff to allow concurrent connections. + * command.c (start_command_handler): Add new arg FD so that the + fucntion can also be used for an already connected socket. + * Makefile.am: Link with Pth. + +2002-05-14 Werner Koch <wk@gnupg.org> + + * cache.c (housekeeping, agent_put_cache): Use our time() wrapper. + +2002-04-26 Werner Koch <wk@gnupg.org> + + * cache.c (agent_put_cache): Reinitialize the creation time and + the ttl when reusing a slot. + + * call-scd.c (start_scd): Print debug messages only with debug + flags set. + * query.c (start_pinentry): Ditto. + +2002-04-25 Marcus Brinkmann <marcus@g10code.de> + + * agent.h (agent_get_confirmation): Replace paramter prompt with + two parameters ok and cancel. + * query.c (agent_get_confirmation): Likewise. Implement this. + * trustlist.c (agent_marktrusted): Fix invocation of + agent_get_confirmation. + * divert-scd.c (ask_for_card): Likewise. + +2002-04-24 Marcus Brinkmann <marcus@g10code.de> + + * agent.h (struct opt): Add members display, ttyname, ttytype, + lc_ctype, and lc_messages. + * gpg-agent.c (enum cmd_and_opt_values): Add oDisplay, oTTYname, + oTTYtype, oLCctype, and LCmessages. + (main): Handle these options. + * command.c (option_handler): New function. + (register_commands): Register option handler. + * query.c (start_pinentry): Pass the various display and tty + options to the pinentry. + +2002-04-05 Werner Koch <wk@gnupg.org> + + * protect-tool.c (show_file): New. Used as default action. + +2002-03-28 Werner Koch <wk@gnupg.org> + + * divert-scd.c (encode_md_for_card): Don't do the pkcs-1 padding, + the scdaemon should take care of it. + (ask_for_card): Hack to not display the trailing zero. + +2002-03-11 Werner Koch <wk@gnupg.org> + + * learncard.c (kpinfo_cb): Remove the content restrictions from + the keyID. + +2002-03-06 Werner Koch <wk@gnupg.org> + + * learncard.c: New. + * divert-scd.c (ask_for_card): The serial number is binary so + convert it to hex here. + * findkey.c (agent_write_private_key): New. + * genkey.c (store_key): And use it here. + + * pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done. + * divert-scd.c (divert_pkdecrypt): Changed interface and + implemented it. + +2002-03-05 Werner Koch <wk@gnupg.org> + + * call-scd.c (inq_needpin): New. + (agent_card_pksign): Add getpin_cb args. + (agent_card_pkdecrypt): New. + +2002-03-04 Werner Koch <wk@gnupg.org> + + * pksign.c (agent_pksign): Changed how the diversion is done. + * divert-scd.c (divert_pksign): Changed interface and implemented it. + (encode_md_for_card): New. + * call-scd.c (agent_card_pksign): New. + +2002-02-28 Werner Koch <wk@gnupg.org> + + * pksign.c (agent_pksign): Detect whether a Smartcard is to be + used and divert the operation in this case. + * pkdecrypt.c (agent_pkdecrypt): Likewise + * findkey.c (agent_key_from_file): Add optional arg shadow_info + and have it return information about a shadowed key. + * protect.c (agent_get_shadow_info): New. + + * protect.c (snext,sskip,smatch): Moved to + * sexp-parse.h: new file. + * divert-scd.c: New. + +2002-02-27 Werner Koch <wk@gnupg.org> + + * protect.c (agent_shadow_key): New. + + * command.c (cmd_learn): New command LEARN. + * gpg-agent.c: New option --scdaemon-program. + * call-scd.c (start_scd): New. Based on query.c + * query.c: Add 2 more arguments to all uses of assuan_transact. + +2002-02-18 Werner Koch <wk@gnupg.org> + + * findkey.c (unprotect): Show an error message for a bad passphrase. + + * command.c (cmd_marktrusted): Implemented. + * trustlist.c (agent_marktrusted): New. + (open_list): Add APPEND arg. + + * query.c (agent_get_confirmation): New. + +2002-02-06 Werner Koch <wk@gnupg.org> + + * cache.c (housekeeping): Fixed linking in the remove case. + +2002-02-01 Werner Koch <wk@gnupg.org> + + * gpg-agent.c: New option --default-cache-ttl. + * cache.c (agent_put_cache): Use it. + + * cache.c: Add a few debug outputs. + + * protect.c (agent_private_key_type): New. + * agent.h: Add PRIVATE_KEY_ enums. + * findkey.c (agent_key_from_file): Use it to decide whether we + have to unprotect a key. + (unprotect): Cache the passphrase. + + * findkey.c (agent_key_from_file,agent_key_available): The key + files do now require a ".key" suffix to make a script's life + easier. + * genkey.c (store_key): Ditto. + +2002-01-31 Werner Koch <wk@gnupg.org> + + * genkey.c (store_key): Protect the key. + (agent_genkey): Ask for the passphrase. + * findkey.c (unprotect): Actually unprotect the key. + * query.c (agent_askpin): Add an optional start_err_text. + +2002-01-30 Werner Koch <wk@gnupg.org> + + * protect.c: New. + (hash_passphrase): Based on the GnuPG 1.0.6 version. + * protect-tool.c: New + +2002-01-29 Werner Koch <wk@gnupg.org> + + * findkey.c (agent_key_available): New. + * command.c (cmd_havekey): New. + (register_commands): And register new command. + +2002-01-20 Werner Koch <wk@gnupg.org> + + * command.c (cmd_get_passphrase): Remove the plus signs. + + * query.c (start_pinentry): Send no-grab option to pinentry + * gpg-agent.c (main): Move variable grab as no_grab to agent.h. + +2002-01-19 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): Disable core dumps. + + * cache.c: New. + * command.c (cmd_get_passphrase): Use the cache. + (cmd_clear_passphrase): Ditto. + + * gpg-agent.c: Removed unused cruft and implement the socket + based server. + (my_strusage): Take bug report address from configure.ac. + * command.c (start_command_handler): Add an argument to start as + regular server. + (start_command_handler): Enable Assuan logging. + +2002-01-15 Werner Koch <wk@gnupg.org> + + * trustlist.c: New. + * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New. + +2002-01-07 Werner Koch <wk@gnupg.org> + + * genkey.c: Store the secret part and return the public part. + +2002-01-03 Werner Koch <wk@gnupg.org> + + * command.c (cmd_get_passphrase): New. + (cmd_clear_passphrase): New. + * query.c (agent_get_passphrase): New. + +2002-01-02 Werner Koch <wk@gnupg.org> + + * genkey.c: New. + * command.c (cmd_genkey): New. + + * command.c (rc_to_assuan_status): Removed and changed all callers + to use map_to_assuan_status. + +2001-12-19 Werner Koch <wk@gnupg.org> + + * keyformat.txt: New. + +2001-12-19 Marcus Brinkmann <marcus@g10code.de> + + * query.c (start_pinentry): Add new argument to assuan_pipe_connect. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * Makefile.am: Use LIBGCRYPT macros + +2001-12-14 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): New option --batch. New option --debug-wait + n, so that it is possible to attach gdb when used in server mode. + * query.c (agent_askpin): Don't ask in batch mode. + + * command.c: Removed the conversion macros as they are now in + ../common/util.h. + +2001-12-14 Marcus Brinkmann <marcus@g10code.de> + + * query.c (LINELENGTH): Removed. + (agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH. + +2001-11-19 Werner Koch <wk@gnupg.org> + + * gpg-agent.c: Removed all GUI code, removed code for old + protocol. New code to use the Assuan protocol as a server and + also to communicate with a new ask-passphrase utility. + +2000-11-22 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): csh support by Dan Winship, new options --sh + and --csh and set default by consulting $SHELL. + +Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de> + + * gpg-agent.c (passphrase_dialog): Cleanup the window and added the + user supplied text to the window. + (main): Fixed segv in gtk_init when used without a command to start. + + * gpg-agent.c: --flush option. + (req_flush): New. + (req_clear_passphrase): Implemented. + +Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de> + + * gpg-agent.c: New. + * Makefile.am: 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. diff --git a/agent/Makefile.am b/agent/Makefile.am new file mode 100644 index 000000000..400aa2fd2 --- /dev/null +++ b/agent/Makefile.am @@ -0,0 +1,62 @@ +# 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 + +localedir = $(datadir)/locale +INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" + +bin_PROGRAMS = gpg-agent +pkglib_PROGRAMS = gpg-protect-tool + +AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS) \ + $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) + +gpg_agent_SOURCES = \ + gpg-agent.c agent.h \ + command.c \ + query.c \ + cache.c \ + trans.c \ + findkey.c \ + pksign.c \ + pkdecrypt.c \ + genkey.c \ + protect.c \ + trustlist.c \ + divert-scd.c \ + call-scd.c \ + learncard.c \ + sexp-parse.h + + +gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ + -lgpg-error @INTLLIBS@ + +gpg_protect_tool_SOURCES = \ + protect-tool.c \ + protect.c \ + simple-pwquery.c simple-pwquery.h \ + minip12.c minip12.h + +gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \ + ../common/libcommon.a ../common/libsimple-pwquery.a \ + $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ + + diff --git a/agent/agent.h b/agent/agent.h new file mode 100644 index 000000000..eb4f4e32d --- /dev/null +++ b/agent/agent.h @@ -0,0 +1,226 @@ +/* agent.h - Global definitions for 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 + */ + +#ifndef AGENT_H +#define AGENT_H + +#ifdef GPG_ERR_SOURCE_DEFAULT +#error GPG_ERR_SOURCE_DEFAULT already defined +#endif +#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGAGENT +#include <gpg-error.h> +#include <errno.h> + +#include <gcrypt.h> +#include "../common/util.h" +#include "../common/errors.h" + +/* Convenience function to be used instead of returning the old + GNUPG_Out_Of_Core. */ +static __inline__ gpg_error_t +out_of_core (void) +{ + return gpg_error (gpg_err_code_from_errno (errno)); +} + +#define MAX_DIGEST_LEN 24 + +/* A large struct name "opt" to keep global flags */ +struct { + unsigned int debug; /* debug flags (DBG_foo_VALUE) */ + int verbose; /* verbosity level */ + int quiet; /* be as quiet as possible */ + int dry_run; /* don't change any persistent data */ + int batch; /* batch mode */ + const char *homedir; /* configuration directory name */ + const char *pinentry_program; + const char *scdaemon_program; + int no_grab; /* don't let the pinentry grab the keyboard */ + unsigned long def_cache_ttl; + + int running_detached; /* we are running detached from the tty. */ + + int ignore_cache_for_signing; + int keep_tty; /* don't switch the TTY (for pinentry) on request */ + int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ +} opt; + + +#define DBG_COMMAND_VALUE 1 /* debug commands i/o */ +#define DBG_MPI_VALUE 2 /* debug mpi details */ +#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ +#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ +#define DBG_CACHE_VALUE 64 /* debug the caching */ +#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ +#define DBG_HASHING_VALUE 512 /* debug hashing operations */ +#define DBG_ASSUAN_VALUE 1024 + +#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE) +#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) +#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) +#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) +#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) +#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) + +struct server_local_s; + +struct server_control_s { + struct server_local_s *server_local; + char *display; + char *ttyname; + char *ttytype; + char *lc_ctype; + char *lc_messages; + struct { + int algo; + unsigned char value[MAX_DIGEST_LEN]; + int valuelen; + } digest; + char keygrip[20]; + int have_keygrip; + +}; +typedef struct server_control_s *CTRL; + + +struct pin_entry_info_s { + int min_digits; /* min. number of digits required or 0 for freeform entry */ + int max_digits; /* max. number of allowed digits allowed*/ + int max_tries; + int failed_tries; + int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */ + void *check_cb_arg; /* optional argument which might be of use in the CB */ + const char *cb_errtext; /* used by the cb to displaye a specific error */ + size_t max_length; /* allocated length of the buffer */ + char pin[1]; +}; + + +enum { + PRIVATE_KEY_UNKNOWN = 0, + PRIVATE_KEY_CLEAR = 1, + PRIVATE_KEY_PROTECTED = 2, + PRIVATE_KEY_SHADOWED = 3 +}; + +/*-- gpg-agent.c --*/ +void agent_exit (int rc); /* also implemented in other tools */ +void agent_init_default_ctrl (struct server_control_s *ctrl); + +/*-- command.c --*/ +void start_command_handler (int, int); + +/*-- findkey.c --*/ +int agent_write_private_key (const unsigned char *grip, + const void *buffer, size_t length, int force); +gcry_sexp_t agent_key_from_file (CTRL ctrl, const unsigned char *grip, + unsigned char **shadow_info, + int ignore_cache); +int agent_key_available (const unsigned char *grip); + +/*-- query.c --*/ +int agent_askpin (CTRL ctrl, + const char *desc_text, struct pin_entry_info_s *pininfo); +int agent_get_passphrase (CTRL ctrl, char **retpass, + const char *desc, const char *prompt, + const char *errtext); +int agent_get_confirmation (CTRL ctrl, const char *desc, const char *ok, + const char *cancel); + +/*-- cache.c --*/ +void agent_flush_cache (void); +int agent_put_cache (const char *key, const char *data, int ttl); +const char *agent_get_cache (const char *key, void **cache_id); +void agent_unlock_cache_entry (void **cache_id); + + +/*-- pksign.c --*/ +int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache); + +/*-- pkdecrypt.c --*/ +int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, + FILE *outfp); + +/*-- genkey.c --*/ +int agent_genkey (CTRL ctrl, + const char *keyparam, size_t keyparmlen, FILE *outfp); +int agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey); + +/*-- protect.c --*/ +int agent_protect (const unsigned char *plainkey, const char *passphrase, + unsigned char **result, size_t *resultlen); +int agent_unprotect (const unsigned char *protectedkey, const char *passphrase, + unsigned char **result, size_t *resultlen); +int agent_private_key_type (const unsigned char *privatekey); +int agent_shadow_key (const unsigned char *pubkey, + const unsigned char *shadow_info, + unsigned char **result); +int agent_get_shadow_info (const unsigned char *shadowkey, + unsigned char const **shadow_info); + + +/*-- trustlist.c --*/ +int agent_istrusted (const char *fpr); +int agent_listtrusted (void *assuan_context); +int agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag); + + +/*-- divert-scd.c --*/ +int divert_pksign (CTRL ctrl, + const unsigned char *digest, size_t digestlen, int algo, + const unsigned char *shadow_info, unsigned char **r_sig); +int divert_pkdecrypt (CTRL ctrl, + const unsigned char *cipher, + const unsigned char *shadow_info, + char **r_buf, size_t *r_len); +int divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context); + + +/*-- call-scd.c --*/ +int agent_card_learn (void (*kpinfo_cb)(void*, const char *), + void *kpinfo_cb_arg, + void (*certinfo_cb)(void*, const char *), + void *certinfo_cb_arg, + void (*sinfo_cb)(void*, const char *, + size_t, const char *), + void *sinfo_cb_arg); +int agent_card_serialno (char **r_serialno); +int agent_card_pksign (const char *keyid, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen); +int agent_card_pkdecrypt (const char *keyid, + int (*getpin_cb)(void *, const char *, char*,size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen); +int agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen); +int agent_card_readkey (const char *id, unsigned char **r_buf); +int agent_card_scd (const char *cmdline, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, void *assuan_context); + + +/*-- learncard.c --*/ +int agent_handle_learn (void *assuan_context); + + +#endif /*AGENT_H*/ diff --git a/agent/call-scd.c b/agent/call-scd.c new file mode 100644 index 000000000..14487f1e3 --- /dev/null +++ b/agent/call-scd.c @@ -0,0 +1,661 @@ +/* call-scd.c - fork of the scdaemon to do SC operations + * 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 + */ + +/* Fixme: For now we have serialized all access to the scdaemon which + make sense becuase the scdaemon can't handle concurrent connections + right now. We should however keep a list of connections and lock + just that connection - it migth make sense to implemtn parts of + this in Assuan.*/ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif + +#include "agent.h" +#include <assuan.h> + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + +static ASSUAN_CONTEXT scd_ctx = NULL; +#ifdef USE_GNU_PTH +static pth_mutex_t scd_lock = PTH_MUTEX_INIT; +#endif + +/* callback parameter for learn card */ +struct learn_parm_s { + void (*kpinfo_cb)(void*, const char *); + void *kpinfo_cb_arg; + void (*certinfo_cb)(void*, const char *); + void *certinfo_cb_arg; + void (*sinfo_cb)(void*, const char *, size_t, const char *); + void *sinfo_cb_arg; +}; + +struct inq_needpin_s { + ASSUAN_CONTEXT ctx; + int (*getpin_cb)(void *, const char *, char*, size_t); + void *getpin_cb_arg; +}; + +struct membuf { + size_t len; + size_t size; + char *buf; + int out_of_core; +}; + + + +/* 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. */ + +static void +init_membuf (struct membuf *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 = 1; +} + +static void +put_membuf (struct membuf *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 = 1; + return; + } + mb->buf = p; + } + memcpy (mb->buf + mb->len, buf, len); + mb->len += len; +} + +static void * +get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ + return p; +} + + + + +static int +unlock_scd (int rc) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_release (&scd_lock)) + { + log_error ("failed to release the SCD lock\n"); + if (!rc) + rc = gpg_error (GPG_ERR_INTERNAL); + } +#endif + return rc; +} + +/* Fork off the SCdaemon if this has not already been done */ +static int +start_scd (void) +{ + int rc; + const char *pgmname; + ASSUAN_CONTEXT ctx; + const char *argv[3]; + int no_close_list[3]; + int i; + +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&scd_lock, 0, NULL)) + { + log_error ("failed to acquire the SCD lock\n"); + return gpg_error (GPG_ERR_INTERNAL); + } +#endif + + if (scd_ctx) + return 0; /* No need to serialize things because the agent is + expected to tun as a single-thread (or may be in + future using libpth) */ + + if (opt.verbose) + log_info ("no running SCdaemon - starting it\n"); + + if (fflush (NULL)) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error flushing pending output: %s\n", strerror (errno)); + return unlock_scd (tmperr); + } + + if (!opt.scdaemon_program || !*opt.scdaemon_program) + opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON; + if ( !(pgmname = strrchr (opt.scdaemon_program, '/'))) + pgmname = opt.scdaemon_program; + else + pgmname++; + + argv[0] = pgmname; + argv[1] = "--server"; + argv[2] = NULL; + + i=0; + if (!opt.running_detached) + { + 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 pinentry and perform initial handshaking */ + rc = assuan_pipe_connect (&ctx, opt.scdaemon_program, (char**)argv, + no_close_list); + if (rc) + { + log_error ("can't connect to the SCdaemon: %s\n", + assuan_strerror (rc)); + return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON)); + } + scd_ctx = ctx; + + if (DBG_ASSUAN) + log_debug ("connection to SCdaemon established\n"); + return 0; +} + + + +static AssuanError +learn_status_cb (void *opaque, const char *line) +{ + struct learn_parm_s *parm = opaque; + const char *keyword = line; + int keywordlen; + + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen)) + { + parm->certinfo_cb (parm->certinfo_cb_arg, line); + } + else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen)) + { + parm->kpinfo_cb (parm->kpinfo_cb_arg, line); + } + else if (keywordlen && *line) + { + parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line); + } + + return 0; +} + +/* Perform the learn command and return a list of all private keys + stored on the card. */ +int +agent_card_learn (void (*kpinfo_cb)(void*, const char *), + void *kpinfo_cb_arg, + void (*certinfo_cb)(void*, const char *), + void *certinfo_cb_arg, + void (*sinfo_cb)(void*, const char *, size_t, const char *), + void *sinfo_cb_arg) +{ + int rc; + struct learn_parm_s parm; + + rc = start_scd (); + if (rc) + return rc; + + memset (&parm, 0, sizeof parm); + parm.kpinfo_cb = kpinfo_cb; + parm.kpinfo_cb_arg = kpinfo_cb_arg; + parm.certinfo_cb = certinfo_cb; + parm.certinfo_cb_arg = certinfo_cb_arg; + parm.sinfo_cb = sinfo_cb; + parm.sinfo_cb_arg = sinfo_cb_arg; + rc = assuan_transact (scd_ctx, "LEARN --force", + NULL, NULL, NULL, NULL, + learn_status_cb, &parm); + if (rc) + return unlock_scd (map_assuan_err (rc)); + + return unlock_scd (0); +} + + + +static AssuanError +get_serialno_cb (void *opaque, const char *line) +{ + char **serialno = opaque; + const char *keyword = line; + const char *s; + int keywordlen, n; + + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + + if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) + { + if (*serialno) + return ASSUAN_Unexpected_Status; + for (n=0,s=line; hexdigitp (s); s++, n++) + ; + if (!n || (n&1)|| !(spacep (s) || !*s) ) + return ASSUAN_Invalid_Status; + *serialno = xtrymalloc (n+1); + if (!*serialno) + return ASSUAN_Out_Of_Core; + memcpy (*serialno, line, n); + (*serialno)[n] = 0; + } + + return 0; +} + +/* Return the serial number of the card or an appropriate error. The + serial number is returned as a hexstring. */ +int +agent_card_serialno (char **r_serialno) +{ + int rc; + char *serialno = NULL; + + rc = start_scd (); + if (rc) + return rc; + + /* Hmm, do we really need this reset - scddaemon should do this or + we can do this if we for some reason figure out that the + operation might have failed due to a missing RESET. Hmmm, I feel + this is really SCdaemon's duty */ +/* rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); */ +/* if (rc) */ +/* return unlock_scd (map_assuan_err (rc)); */ + + rc = assuan_transact (scd_ctx, "SERIALNO", + NULL, NULL, NULL, NULL, + get_serialno_cb, &serialno); + if (rc) + { + xfree (serialno); + return unlock_scd (map_assuan_err (rc)); + } + *r_serialno = serialno; + return unlock_scd (0); +} + + +static AssuanError +membuf_data_cb (void *opaque, const void *buffer, size_t length) +{ + struct membuf *data = opaque; + + if (buffer) + put_membuf (data, buffer, length); + return 0; +} + +/* Handle the NEEDPIN inquiry. */ +static AssuanError +inq_needpin (void *opaque, const char *line) +{ + struct inq_needpin_s *parm = opaque; + char *pin; + size_t pinlen; + int rc; + + if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))) + { + log_error ("unsupported inquiry `%s'\n", line); + return ASSUAN_Inquire_Unknown; + } + line += 7; + + pinlen = 90; + pin = gcry_malloc_secure (pinlen); + if (!pin) + return ASSUAN_Out_Of_Core; + + rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen); + if (rc) + rc = ASSUAN_Canceled; + if (!rc) + rc = assuan_send_data (parm->ctx, pin, pinlen); + xfree (pin); + + return rc; +} + + + +/* Create a signature using the current card */ +int +agent_card_pksign (const char *keyid, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen) +{ + int rc, i; + char *p, line[ASSUAN_LINELENGTH]; + struct membuf data; + struct inq_needpin_s inqparm; + size_t len; + unsigned char *sigbuf; + size_t sigbuflen; + + *r_buf = NULL; + rc = start_scd (); + if (rc) + return rc; + + if (indatalen*2 + 50 > DIM(line)) + return unlock_scd (gpg_error (GPG_ERR_GENERAL)); + + sprintf (line, "SETDATA "); + p = line + strlen (line); + for (i=0; i < indatalen ; i++, p += 2 ) + sprintf (p, "%02X", indata[i]); + rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_scd (map_assuan_err (rc)); + + init_membuf (&data, 1024); + inqparm.ctx = scd_ctx; + inqparm.getpin_cb = getpin_cb; + inqparm.getpin_cb_arg = getpin_cb_arg; + snprintf (line, DIM(line)-1, "PKSIGN %s", keyid); + line[DIM(line)-1] = 0; + rc = assuan_transact (scd_ctx, line, + membuf_data_cb, &data, + inq_needpin, &inqparm, + NULL, NULL); + if (rc) + { + xfree (get_membuf (&data, &len)); + return unlock_scd (map_assuan_err (rc)); + } + sigbuf = get_membuf (&data, &sigbuflen); + + /* create an S-expression from it which is formatted like this: + "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */ + *r_buflen = 21 + 11 + sigbuflen + 4; + *r_buf = xtrymalloc (*r_buflen); + if (!*r_buf) + { + gpg_error_t tmperr = out_of_core (); + xfree (*r_buf); + return unlock_scd (tmperr); + } + p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" ); + sprintf (p, "%u:", (unsigned int)sigbuflen); + p += strlen (p); + memcpy (p, sigbuf, sigbuflen); + p += sigbuflen; + strcpy (p, ")))"); + xfree (sigbuf); + + assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL)); + return unlock_scd (0); +} + +/* Decipher INDATA using the current card. Note that the returned value is */ +int +agent_card_pkdecrypt (const char *keyid, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen) +{ + int rc, i; + char *p, line[ASSUAN_LINELENGTH]; + struct membuf data; + struct inq_needpin_s inqparm; + size_t len; + + *r_buf = NULL; + rc = start_scd (); + if (rc) + return rc; + + /* FIXME: use secure memory where appropriate */ + if (indatalen*2 + 50 > DIM(line)) + return unlock_scd (gpg_error (GPG_ERR_GENERAL)); + + sprintf (line, "SETDATA "); + p = line + strlen (line); + for (i=0; i < indatalen ; i++, p += 2 ) + sprintf (p, "%02X", indata[i]); + rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_scd (map_assuan_err (rc)); + + init_membuf (&data, 1024); + inqparm.ctx = scd_ctx; + inqparm.getpin_cb = getpin_cb; + inqparm.getpin_cb_arg = getpin_cb_arg; + snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid); + line[DIM(line)-1] = 0; + rc = assuan_transact (scd_ctx, line, + membuf_data_cb, &data, + inq_needpin, &inqparm, + NULL, NULL); + if (rc) + { + xfree (get_membuf (&data, &len)); + return unlock_scd (map_assuan_err (rc)); + } + *r_buf = get_membuf (&data, r_buflen); + if (!*r_buf) + return unlock_scd (gpg_error (GPG_ERR_ENOMEM)); + + return unlock_scd (0); +} + + + +/* Read a certificate with ID into R_BUF and R_BUFLEN. */ +int +agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + struct membuf data; + size_t len; + + *r_buf = NULL; + rc = start_scd (); + if (rc) + return rc; + + init_membuf (&data, 1024); + snprintf (line, DIM(line)-1, "READCERT %s", id); + line[DIM(line)-1] = 0; + rc = assuan_transact (scd_ctx, line, + membuf_data_cb, &data, + NULL, NULL, + NULL, NULL); + if (rc) + { + xfree (get_membuf (&data, &len)); + return unlock_scd (map_assuan_err (rc)); + } + *r_buf = get_membuf (&data, r_buflen); + if (!*r_buf) + return unlock_scd (gpg_error (GPG_ERR_ENOMEM)); + + return unlock_scd (0); +} + + + +/* Read a key with ID and return it in an allocate buffer pointed to + by r_BUF as a valid S-expression. */ +int +agent_card_readkey (const char *id, unsigned char **r_buf) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + struct membuf data; + size_t len, buflen; + + *r_buf = NULL; + rc = start_scd (); + if (rc) + return rc; + + init_membuf (&data, 1024); + snprintf (line, DIM(line)-1, "READKEY %s", id); + line[DIM(line)-1] = 0; + rc = assuan_transact (scd_ctx, line, + membuf_data_cb, &data, + NULL, NULL, + NULL, NULL); + if (rc) + { + xfree (get_membuf (&data, &len)); + return unlock_scd (map_assuan_err (rc)); + } + *r_buf = get_membuf (&data, &buflen); + if (!*r_buf) + return unlock_scd (gpg_error (GPG_ERR_ENOMEM)); + + if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL)) + { + xfree (*r_buf); *r_buf = NULL; + return unlock_scd (gpg_error (GPG_ERR_INV_VALUE)); + } + + return unlock_scd (0); +} + + + + +static AssuanError +pass_status_thru (void *opaque, const char *line) +{ + ASSUAN_CONTEXT ctx = opaque; + char keyword[200]; + int i; + + for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++) + keyword[i] = *line; + keyword[i] = 0; + /* truncate any remaining keyword stuff. */ + for (; *line && !spacep (line); line++) + ; + while (spacep (line)) + line++; + + assuan_write_status (ctx, keyword, line); + return 0; +} + +static AssuanError +pass_data_thru (void *opaque, const void *buffer, size_t length) +{ + ASSUAN_CONTEXT ctx = opaque; + + assuan_send_data (ctx, buffer, length); + return 0; +} + + +/* Send the line CMDLINE with command for the SCDdaemon to it and send + all status messages back. This command is used as a general quoting + mechanism to pass everything verbatim to SCDAEMOPN. The PIN + inquirey is handled inside gpg-agent. */ +int +agent_card_scd (const char *cmdline, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, void *assuan_context) +{ + int rc; + struct inq_needpin_s inqparm; + + rc = start_scd (); + if (rc) + return rc; + + inqparm.ctx = scd_ctx; + inqparm.getpin_cb = getpin_cb; + inqparm.getpin_cb_arg = getpin_cb_arg; + rc = assuan_transact (scd_ctx, cmdline, + pass_data_thru, assuan_context, + inq_needpin, &inqparm, + pass_status_thru, assuan_context); + if (rc) + { + return unlock_scd (map_assuan_err (rc)); + } + + return unlock_scd (0); +} + + diff --git a/agent/command.c b/agent/command.c new file mode 100644 index 000000000..ed4ea6b02 --- /dev/null +++ b/agent/command.c @@ -0,0 +1,782 @@ +/* command.c - gpg-agent command handler + * 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 + */ + +/* FIXME: we should not use the default assuan buffering but setup + some buffering in secure mempory to protect session keys etc. */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include <assuan.h> + +#include "agent.h" + +/* maximum allowed size of the inquired ciphertext */ +#define MAXLEN_CIPHERTEXT 4096 +/* maximum allowed size of the key parameters */ +#define MAXLEN_KEYPARAM 1024 + +#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) + + +#if MAX_DIGEST_LEN < 20 +#error MAX_DIGEST_LEN shorter than keygrip +#endif + +/* Data used to associate an Assuan context with local server data */ +struct server_local_s { + ASSUAN_CONTEXT assuan_ctx; + int message_fd; + int use_cache_for_signing; +}; + + + + + +static void +reset_notify (ASSUAN_CONTEXT ctx) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + memset (ctrl->keygrip, 0, 20); + ctrl->have_keygrip = 0; + ctrl->digest.valuelen = 0; +} + + +/* Check whether the option NAME appears in LINE */ +static int +has_option (const char *line, const char *name) +{ + const char *s; + int n = strlen (name); + + s = strstr (line, name); + return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); +} + +/* Parse a hex string. Return an Assuan error code or 0 on success and the + length of the parsed string in LEN. */ +static int +parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len) +{ + const char *p; + size_t n; + + /* parse the hash value */ + for (p=string, n=0; hexdigitp (p); p++, n++) + ; + if (*p) + return set_error (Parameter_Error, "invalid hexstring"); + if ((n&1)) + return set_error (Parameter_Error, "odd number of digits"); + *len = n; + return 0; +} + +/* Parse the keygrip in STRING into the provided buffer BUF. BUF must + provide space for 20 bytes. BUF is not changed if the fucntions + returns an error. */ +static int +parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf) +{ + int rc; + size_t n; + const unsigned char *p; + + rc = parse_hexstring (ctx, string, &n); + if (rc) + return rc; + n /= 2; + if (n != 20) + return set_error (Parameter_Error, "invalid length of keygrip"); + + for (p=string, n=0; n < 20; p += 2, n++) + buf[n] = xtoi_2 (p); + + return 0; +} + + + + +/* ISTRUSTED <hexstring_with_fingerprint> + + Return OK when we have an entry with this fingerprint in our + trustlist */ +static int +cmd_istrusted (ASSUAN_CONTEXT ctx, char *line) +{ + int rc, n, i; + char *p; + char fpr[41]; + + /* parse the fingerprint value */ + for (p=line,n=0; hexdigitp (p); p++, n++) + ; + if (*p || !(n == 40 || n == 32)) + return set_error (Parameter_Error, "invalid fingerprint"); + i = 0; + if (n==32) + { + strcpy (fpr, "00000000"); + i += 8; + } + for (p=line; i < 40; p++, i++) + fpr[i] = *p >= 'a'? (*p & 0xdf): *p; + fpr[i] = 0; + rc = agent_istrusted (fpr); + if (!rc) + return 0; + else if (rc == -1) + return ASSUAN_Not_Trusted; + else + { + log_error ("command is_trusted failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); + } +} + +/* LISTTRUSTED + + List all entries from the trustlist */ +static int +cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line) +{ + int rc = agent_listtrusted (ctx); + if (rc) + log_error ("command listtrusted failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + +/* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name> + + Store a new key in into the trustlist*/ +static int +cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc, n, i; + char *p; + char fpr[41]; + int flag; + + /* parse the fingerprint value */ + for (p=line,n=0; hexdigitp (p); p++, n++) + ; + if (!spacep (p) || !(n == 40 || n == 32)) + return set_error (Parameter_Error, "invalid fingerprint"); + i = 0; + if (n==32) + { + strcpy (fpr, "00000000"); + i += 8; + } + for (p=line; i < 40; p++, i++) + fpr[i] = *p >= 'a'? (*p & 0xdf): *p; + fpr[i] = 0; + + while (spacep (p)) + p++; + flag = *p++; + if ( (flag != 'S' && flag != 'P') || !spacep (p) ) + return set_error (Parameter_Error, "invalid flag - must be P or S"); + while (spacep (p)) + p++; + + rc = agent_marktrusted (ctrl, p, fpr, flag); + if (rc) + log_error ("command marktrusted failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + + + +/* HAVEKEY <hexstring_with_keygrip> + + Return success when the secret key is available */ +static int +cmd_havekey (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + unsigned char buf[20]; + + rc = parse_keygrip (ctx, line, buf); + if (rc) + return rc; + + if (agent_key_available (buf)) + return ASSUAN_No_Secret_Key; + + return 0; +} + + +/* SIGKEY <hexstring_with_keygrip> + SETKEY <hexstring_with_keygrip> + + Set the key used for a sign or decrypt operation */ +static int +cmd_sigkey (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + CTRL ctrl = assuan_get_pointer (ctx); + + rc = parse_keygrip (ctx, line, ctrl->keygrip); + if (rc) + return rc; + ctrl->have_keygrip = 1; + return 0; +} + + +/* SETHASH <algonumber> <hexstring> + + The client can use this command to tell the server about the data + (which usually is a hash) to be signed. */ +static int +cmd_sethash (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + size_t n; + char *p; + CTRL ctrl = assuan_get_pointer (ctx); + unsigned char *buf; + char *endp; + int algo; + + /* parse the algo number and check it */ + algo = (int)strtoul (line, &endp, 10); + for (line = endp; *line == ' ' || *line == '\t'; line++) + ; + if (!algo || gcry_md_test_algo (algo)) + return set_error (Unsupported_Algorithm, NULL); + ctrl->digest.algo = algo; + + /* parse the hash value */ + rc = parse_hexstring (ctx, line, &n); + if (rc) + return rc; + n /= 2; + if (n != 16 && n != 20 && n != 24 && n != 32) + return set_error (Parameter_Error, "unsupported length of hash"); + if (n > MAX_DIGEST_LEN) + return set_error (Parameter_Error, "hash value to long"); + + buf = ctrl->digest.value; + ctrl->digest.valuelen = n; + for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++) + buf[n] = xtoi_2 (p); + for (; n < ctrl->digest.valuelen; n++) + buf[n] = 0; + return 0; +} + + +/* PKSIGN <options> + + Perform the actual sign operation. Neither input nor output are + sensitive to eavesdropping */ +static int +cmd_pksign (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + int ignore_cache = 0; + CTRL ctrl = assuan_get_pointer (ctx); + + if (opt.ignore_cache_for_signing) + ignore_cache = 1; + else if (!ctrl->server_local->use_cache_for_signing) + ignore_cache = 1; + + rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache); + if (rc) + log_error ("command pksign failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + +/* PKDECRYPT <options> + + Perform the actual decrypt operation. Input is not + sensitive to eavesdropping */ +static int +cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + CTRL ctrl = assuan_get_pointer (ctx); + char *value; + size_t valuelen; + + /* First inquire the data to decrypt */ + rc = assuan_inquire (ctx, "CIPHERTEXT", + &value, &valuelen, MAXLEN_CIPHERTEXT); + if (rc) + return rc; + + rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx)); + xfree (value); + if (rc) + log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + +/* GENKEY + + Generate a new key, store the secret part and return the public + part. Here is an example transaction: + + 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 +*/ + +static int +cmd_genkey (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *value; + size_t valuelen; + + /* First inquire the parameters */ + rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM); + if (rc) + return rc; + + rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx)); + xfree (value); + if (rc) + log_error ("command genkey failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + +static void +plus_to_blank (char *s) +{ + for (; *s; s++) + { + if (*s == '+') + *s = ' '; + } +} + +/* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>] + + 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 specal handling of passphrases. This command uses a syntax + which helps clients to use the agent with minimum effort. 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. +*/ + +static int +cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + const char *pw; + char *response; + char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL; + char *p; + void *cache_marker; + + /* parse the stuff */ + for (p=line; *p == ' '; p++) + ; + cacheid = p; + p = strchr (cacheid, ' '); + if (p) + { + *p++ = 0; + while (*p == ' ') + p++; + errtext = p; + p = strchr (errtext, ' '); + if (p) + { + *p++ = 0; + while (*p == ' ') + p++; + prompt = p; + p = strchr (prompt, ' '); + if (p) + { + *p++ = 0; + while (*p == ' ') + p++; + desc = p; + p = strchr (desc, ' '); + if (p) + *p = 0; /* ignore garbage */ + } + } + } + if (!cacheid || !*cacheid || strlen (cacheid) > 50) + return set_error (Parameter_Error, "invalid length of cacheID"); + if (!desc) + return set_error (Parameter_Error, "no description given"); + + if (!strcmp (cacheid, "X")) + cacheid = NULL; + if (!strcmp (errtext, "X")) + errtext = NULL; + if (!strcmp (prompt, "X")) + prompt = NULL; + if (!strcmp (desc, "X")) + desc = NULL; + + /* Note: we store the hexified versions in the cache. */ + pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL; + if (pw) + { + assuan_begin_confidential (ctx); + rc = assuan_set_okay_line (ctx, pw); + agent_unlock_cache_entry (&cache_marker); + } + else + { + /* Note, that we only need to replace the + characters and + should leave the other escaping in place because the escaped + string is send verbatim to the pinentry which does the + unescaping (but not the + replacing) */ + if (errtext) + plus_to_blank (errtext); + if (prompt) + plus_to_blank (prompt); + if (desc) + plus_to_blank (desc); + + rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext); + if (!rc) + { + if (cacheid) + agent_put_cache (cacheid, response, 0); + assuan_begin_confidential (ctx); + rc = assuan_set_okay_line (ctx, response); + xfree (response); + } + } + + if (rc) + log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + +/* CLEAR_PASSPHRASE <cache_id> + + may be used to invalidate the cache entry for a passphrase. The + function returns with OK even when there is no cached passphrase. +*/ + +static int +cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line) +{ + char *cacheid = NULL; + char *p; + + /* parse the stuff */ + for (p=line; *p == ' '; p++) + ; + cacheid = p; + p = strchr (cacheid, ' '); + if (p) + *p = 0; /* ignore garbage */ + if (!cacheid || !*cacheid || strlen (cacheid) > 50) + return set_error (Parameter_Error, "invalid length of cacheID"); + + agent_put_cache (cacheid, NULL, 0); + return 0; +} + + +/* LEARN [--send] + + Learn something about the currently inserted smartcard. With + --send the new certificates are send back. */ +static int +cmd_learn (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + + rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL); + if (rc) + log_error ("command learn failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + + +/* PASSWD <hexstring_with_keygrip> + + Change the passphrase/PID for the key identified by keygrip in LINE. */ +static int +cmd_passwd (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char grip[20]; + gcry_sexp_t s_skey = NULL; + unsigned char *shadow_info = NULL; + + rc = parse_keygrip (ctx, line, grip); + if (rc) + return rc; /* we can't jump to leave because this is already an + Assuan error code. */ + + s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1); + if (!s_skey && !shadow_info) + rc = gpg_error (GPG_ERR_NO_SECKEY); + else if (!s_skey) + { + log_error ("changing a smartcard PIN is not yet supported\n"); + rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + else + rc = agent_protect_and_store (ctrl, s_skey); + + gcry_sexp_release (s_skey); + xfree (shadow_info); + if (rc) + log_error ("command passwd failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + +/* SCD <commands to pass to the scdaemon> + + This is a general quote command to redirect everything to the + SCDAEMON. */ +static int +cmd_scd (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + + rc = divert_generic_cmd (ctrl, line, ctx); + + return map_to_assuan_status (rc); +} + + + +static int +option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + if (!strcmp (key, "display")) + { + if (ctrl->display) + free (ctrl->display); + ctrl->display = strdup (value); + if (!ctrl->display) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "ttyname")) + { + if (!opt.keep_tty) + { + if (ctrl->ttyname) + free (ctrl->ttyname); + ctrl->ttyname = strdup (value); + if (!ctrl->ttyname) + return ASSUAN_Out_Of_Core; + } + } + else if (!strcmp (key, "ttytype")) + { + if (!opt.keep_tty) + { + if (ctrl->ttytype) + free (ctrl->ttytype); + ctrl->ttytype = strdup (value); + if (!ctrl->ttytype) + return ASSUAN_Out_Of_Core; + } + } + else if (!strcmp (key, "lc-ctype")) + { + if (ctrl->lc_ctype) + free (ctrl->lc_ctype); + ctrl->lc_ctype = strdup (value); + if (!ctrl->lc_ctype) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "lc-messages")) + { + if (ctrl->lc_messages) + free (ctrl->lc_messages); + ctrl->lc_messages = strdup (value); + if (!ctrl->lc_messages) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "use-cache-for-signing")) + ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0; + else + return ASSUAN_Invalid_Option; + + return 0; +} + + +/* Tell the assuan library about our commands */ +static int +register_commands (ASSUAN_CONTEXT ctx) +{ + static struct { + const char *name; + int (*handler)(ASSUAN_CONTEXT, char *line); + } table[] = { + { "ISTRUSTED", cmd_istrusted }, + { "HAVEKEY", cmd_havekey }, + { "SIGKEY", cmd_sigkey }, + { "SETKEY", cmd_sigkey }, + { "SETHASH", cmd_sethash }, + { "PKSIGN", cmd_pksign }, + { "PKDECRYPT", cmd_pkdecrypt }, + { "GENKEY", cmd_genkey }, + { "GET_PASSPHRASE", cmd_get_passphrase }, + { "CLEAR_PASSPHRASE", cmd_clear_passphrase }, + { "LISTTRUSTED", cmd_listtrusted }, + { "MARKTRUSTED", cmd_marktrusted }, + { "LEARN", cmd_learn }, + { "PASSWD", cmd_passwd }, + { "INPUT", NULL }, + { "OUTPUT", NULL }, + { "SCD", cmd_scd }, + { NULL } + }; + int i, rc; + + for (i=0; table[i].name; i++) + { + rc = assuan_register_command (ctx, table[i].name, table[i].handler); + if (rc) + return rc; + } + assuan_register_reset_notify (ctx, reset_notify); + assuan_register_option_handler (ctx, option_handler); + return 0; +} + + +/* Startup the server. If LISTEN_FD and FD is given as -1, this is a simple + piper server, otherwise it is a regular server */ +void +start_command_handler (int listen_fd, int fd) +{ + int rc; + ASSUAN_CONTEXT ctx; + struct server_control_s ctrl; + + memset (&ctrl, 0, sizeof ctrl); + agent_init_default_ctrl (&ctrl); + + if (listen_fd == -1 && fd == -1) + { + int filedes[2]; + + filedes[0] = 0; + filedes[1] = 1; + rc = assuan_init_pipe_server (&ctx, filedes); + } + else if (listen_fd != -1) + { + rc = assuan_init_socket_server (&ctx, listen_fd); + } + else + { + rc = assuan_init_connected_socket_server (&ctx, fd); + } + if (rc) + { + log_error ("failed to initialize the server: %s\n", + assuan_strerror(rc)); + agent_exit (2); + } + rc = register_commands (ctx); + if (rc) + { + log_error ("failed to register commands with Assuan: %s\n", + assuan_strerror(rc)); + agent_exit (2); + } + + assuan_set_pointer (ctx, &ctrl); + ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); + ctrl.server_local->assuan_ctx = ctx; + ctrl.server_local->message_fd = -1; + ctrl.server_local->use_cache_for_signing = 1; + + if (DBG_ASSUAN) + assuan_set_log_stream (ctx, log_get_stream ()); + + for (;;) + { + rc = assuan_accept (ctx); + if (rc == -1) + { + break; + } + else if (rc) + { + log_info ("Assuan accept problem: %s\n", assuan_strerror (rc)); + break; + } + + rc = assuan_process (ctx); + if (rc) + { + log_info ("Assuan processing failed: %s\n", assuan_strerror (rc)); + continue; + } + } + + + assuan_deinit_server (ctx); + if (ctrl.display) + free (ctrl.display); + if (ctrl.ttyname) + free (ctrl.ttyname); + if (ctrl.ttytype) + free (ctrl.ttytype); + if (ctrl.lc_ctype) + free (ctrl.lc_ctype); + if (ctrl.lc_messages) + free (ctrl.lc_messages); +} + diff --git a/agent/divert-scd.c b/agent/divert-scd.c new file mode 100644 index 000000000..69f184474 --- /dev/null +++ b/agent/divert-scd.c @@ -0,0 +1,319 @@ +/* divert-scd.c - divert operations to the scdaemon + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" +#include "sexp-parse.h" +#include "i18n.h" + + +static int +ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) +{ + int rc, i; + const unsigned char *s; + size_t n; + char *serialno; + int no_card = 0; + char *desc; + char *want_sn, *want_kid; + int want_sn_displen; + + *r_kid = NULL; + s = shadow_info; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + want_sn = xtrymalloc (n*2+1); + if (!want_sn) + return out_of_core (); + for (i=0; i < n; i++) + sprintf (want_sn+2*i, "%02X", s[i]); + s += n; + /* We assume that a 20 byte serial number is a standard one which + seems to have the property to have a zero in the last nibble. We + don't display this '0' because it may confuse the user */ + want_sn_displen = strlen (want_sn); + if (want_sn_displen == 20 && want_sn[19] == '0') + want_sn_displen--; + + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + want_kid = xtrymalloc (n+1); + if (!want_kid) + { + gpg_error_t tmperr = out_of_core (); + xfree (want_sn); + return tmperr; + } + memcpy (want_kid, s, n); + want_kid[n] = 0; + + for (;;) + { + rc = agent_card_serialno (&serialno); + if (!rc) + { + log_debug ("detected card with S/N %s\n", serialno); + i = strcmp (serialno, want_sn); + xfree (serialno); + serialno = NULL; + if (!i) + { + xfree (want_sn); + *r_kid = want_kid; + return 0; /* yes, we have the correct card */ + } + } + else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT) + { + log_debug ("no card present\n"); + rc = 0; + no_card = 1; + } + else + { + log_error ("error accesing card: %s\n", gpg_strerror (rc)); + } + + if (!rc) + { + if (asprintf (&desc, + "%s:%%0A%%0A" + " \"%.*s\"", + no_card? "Please insert the card with serial number" + : "Please remove the current card and " + "insert the one with serial number", + want_sn_displen, want_sn) < 0) + { + rc = out_of_core (); + } + else + { + rc = agent_get_confirmation (ctrl, desc, NULL, NULL); + free (desc); + } + } + if (rc) + { + xfree (want_sn); + xfree (want_kid); + return rc; + } + } +} + + +/* Put the DIGEST into an DER encoded comtainer and return it in R_VAL. */ +static int +encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo, + unsigned char **r_val, size_t *r_len) +{ + byte *frame; + byte asn[100]; + size_t asnlen; + + asnlen = DIM(asn); + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + log_error ("no object identifier for algo %d\n", algo); + return gpg_error (GPG_ERR_INTERNAL); + } + + frame = xtrymalloc (asnlen + digestlen); + if (!frame) + return out_of_core (); + memcpy (frame, asn, asnlen); + memcpy (frame+asnlen, digest, digestlen); + if (DBG_CRYPTO) + log_printhex ("encoded hash:", frame, asnlen+digestlen); + + *r_val = frame; + *r_len = asnlen+digestlen; + return 0; +} + + +/* Callback used to ask for the PIN which should be set into BUF. The + buf has been allocated by the caller and is of size MAXBUF which + includes the terminating null. The function should return an UTF-8 + string with the passphrase, the buffer may optionally be padded + with arbitrary characters */ +static int +getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) +{ + struct pin_entry_info_s *pi; + int rc; + char *desc; + CTRL ctrl = opaque; + + if (maxbuf < 2) + return gpg_error (GPG_ERR_INV_VALUE); + + + /* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole + mess because we should call the card's verify function from the + pinentry check pin CB. */ + pi = gcry_calloc_secure (1, sizeof (*pi) + 100); + pi->max_length = maxbuf-1; + pi->min_digits = 0; /* we want a real passphrase */ + pi->max_digits = 8; + pi->max_tries = 3; + + if ( asprintf (&desc, _("Please enter the PIN%s%s%s to unlock the card"), + info? " (`":"", + info? info:"", + info? "')":"") < 0) + desc = NULL; + rc = agent_askpin (ctrl, desc?desc:info, pi); + free (desc); + if (!rc) + { + strncpy (buf, pi->pin, maxbuf-1); + buf[maxbuf-1] = 0; + } + xfree (pi); + return rc; +} + + + + +int +divert_pksign (CTRL ctrl, + const unsigned char *digest, size_t digestlen, int algo, + const unsigned char *shadow_info, unsigned char **r_sig) +{ + int rc; + char *kid; + size_t siglen; + char *sigval; + unsigned char *data; + size_t ndata; + + rc = ask_for_card (ctrl, shadow_info, &kid); + if (rc) + return rc; + + rc = encode_md_for_card (digest, digestlen, algo, + &data, &ndata); + if (rc) + return rc; + + rc = agent_card_pksign (kid, getpin_cb, ctrl, + data, ndata, &sigval, &siglen); + if (!rc) + *r_sig = sigval; + xfree (data); + xfree (kid); + + return rc; +} + + +/* Decrypt the the value given asn an S-expression in CIPHER using the + key identified by SHADOW_INFO and return the plaintext in an + allocated buffer in R_BUF. */ +int +divert_pkdecrypt (CTRL ctrl, + const unsigned char *cipher, + const unsigned char *shadow_info, + char **r_buf, size_t *r_len) +{ + int rc; + char *kid; + const unsigned char *s; + size_t n; + const unsigned char *ciphertext; + size_t ciphertextlen; + char *plaintext; + size_t plaintextlen; + + s = cipher; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "enc-val")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "rsa")) + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "a")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + ciphertext = s; + ciphertextlen = n; + + rc = ask_for_card (ctrl, shadow_info, &kid); + if (rc) + return rc; + + rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl, + ciphertext, ciphertextlen, + &plaintext, &plaintextlen); + if (!rc) + { + *r_buf = plaintext; + *r_len = plaintextlen; + } + xfree (kid); + return rc; +} + + +int +divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context) +{ + return agent_card_scd (cmdline, getpin_cb, ctrl, assuan_context); +} + + + + + diff --git a/agent/findkey.c b/agent/findkey.c new file mode 100644 index 000000000..db36cb1b9 --- /dev/null +++ b/agent/findkey.c @@ -0,0 +1,359 @@ +/* findkey.c - locate the secret key + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> +#include <assert.h> + +#include "agent.h" + +/* Helper to pass data to the check callback of the unprotect function. */ +struct try_unprotect_arg_s { + const unsigned char *protected_key; + unsigned char *unprotected_key; +}; + + + +int +agent_write_private_key (const unsigned char *grip, + const void *buffer, size_t length, int force) +{ + int i; + char *fname; + FILE *fp; + char hexgrip[40+4+1]; + + for (i=0; i < 20; i++) + sprintf (hexgrip+2*i, "%02X", grip[i]); + strcpy (hexgrip+40, ".key"); + + fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); + if (force) + fp = fopen (fname, "wb"); + else + { + int fd; + + if (!access (fname, F_OK)) + { + log_error ("secret key file `%s' already exists\n", fname); + xfree (fname); + return gpg_error (GPG_ERR_GENERAL); + } + + /* We would like to create FNAME but only if it does not already + exist. We cannot make this guarantee just using POSIX (GNU + provides the "x" opentype for fopen, however, this is not + portable). Thus, we use the more flexible open function and + then use fdopen to obtain a stream. + + The mode parameter to open is what fopen uses. It will be + combined with the process' umask automatically. */ + fd = open (fname, O_CREAT | O_EXCL | O_RDWR, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (fd < 0) + fp = 0; + else + { + fp = fdopen (fd, "wb"); + if (!fp) + { + int save_e = errno; + close (fd); + errno = save_e; + } + } + } + + if (!fp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("can't create `%s': %s\n", fname, strerror (errno)); + xfree (fname); + return tmperr; + } + + if (fwrite (buffer, length, 1, fp) != 1) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error writing `%s': %s\n", fname, strerror (errno)); + fclose (fp); + remove (fname); + xfree (fname); + return tmperr; + } + if ( fclose (fp) ) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error closing `%s': %s\n", fname, strerror (errno)); + remove (fname); + xfree (fname); + return tmperr; + } + + xfree (fname); + return 0; +} + + +/* Callback function to try the unprotection from the passpharse query + code. */ +static int +try_unprotect_cb (struct pin_entry_info_s *pi) +{ + struct try_unprotect_arg_s *arg = pi->check_cb_arg; + size_t dummy; + + assert (!arg->unprotected_key); + return agent_unprotect (arg->protected_key, pi->pin, + &arg->unprotected_key, &dummy); +} + + +/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP + should be the hex encoded keygrip of that key to be used with the + caching mechanism. */ +static int +unprotect (CTRL ctrl, + unsigned char **keybuf, const unsigned char *grip, int ignore_cache) +{ + struct pin_entry_info_s *pi; + struct try_unprotect_arg_s arg; + int rc, i; + unsigned char *result; + size_t resultlen; + char hexgrip[40+1]; + + for (i=0; i < 20; i++) + sprintf (hexgrip+2*i, "%02X", grip[i]); + hexgrip[40] = 0; + + /* first try to get it from the cache - if there is none or we can't + unprotect it, we fall back to ask the user */ + if (!ignore_cache) + { + void *cache_marker; + const char *pw = agent_get_cache (hexgrip, &cache_marker); + if (pw) + { + rc = agent_unprotect (*keybuf, pw, &result, &resultlen); + agent_unlock_cache_entry (&cache_marker); + if (!rc) + { + xfree (*keybuf); + *keybuf = result; + return 0; + } + rc = 0; + } + } + + pi = gcry_calloc_secure (1, sizeof (*pi) + 100); + pi->max_length = 100; + pi->min_digits = 0; /* we want a real passphrase */ + pi->max_digits = 8; + pi->max_tries = 3; + pi->check_cb = try_unprotect_cb; + arg.protected_key = *keybuf; + arg.unprotected_key = NULL; + pi->check_cb_arg = &arg; + + rc = agent_askpin (ctrl, NULL, pi); + if (!rc) + { + assert (arg.unprotected_key); + agent_put_cache (hexgrip, pi->pin, 0); + xfree (*keybuf); + *keybuf = arg.unprotected_key; + } + xfree (pi); + return rc; +} + + + +/* Return the secret key as an S-Exp after locating it using the grip. + Returns NULL if key is not available or the operation should be + diverted to a token. In the latter case shadow_info will point to + an allocated S-Expression with the shadow_info part from the file. + With IGNORE_CACHE passed as true the passphrase is not taken from + the cache.*/ +gcry_sexp_t +agent_key_from_file (CTRL ctrl, + const unsigned char *grip, unsigned char **shadow_info, + int ignore_cache) +{ + int i, rc; + char *fname; + FILE *fp; + struct stat st; + unsigned char *buf; + size_t len, buflen, erroff; + gcry_sexp_t s_skey; + char hexgrip[40+4+1]; + + if (shadow_info) + *shadow_info = NULL; + + for (i=0; i < 20; i++) + sprintf (hexgrip+2*i, "%02X", grip[i]); + strcpy (hexgrip+40, ".key"); + + fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); + fp = fopen (fname, "rb"); + if (!fp) + { + log_error ("can't open `%s': %s\n", fname, strerror (errno)); + xfree (fname); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + log_error ("can't stat `%s': %s\n", fname, strerror (errno)); + xfree (fname); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + log_error ("error reading `%s': %s\n", fname, strerror (errno)); + xfree (fname); + fclose (fp); + xfree (buf); + return NULL; + } + + rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); + xfree (fname); + fclose (fp); + xfree (buf); + if (rc) + { + log_error ("failed to build S-Exp (off=%u): %s\n", + (unsigned int)erroff, gpg_strerror (rc)); + return NULL; + } + len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xtrymalloc (len); + if (!buf) + { + gcry_sexp_release (s_skey); + return NULL; + } + len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + gcry_sexp_release (s_skey); + + switch (agent_private_key_type (buf)) + { + case PRIVATE_KEY_CLEAR: + break; /* no unprotection needed */ + case PRIVATE_KEY_PROTECTED: + rc = unprotect (ctrl, &buf, grip, ignore_cache); + if (rc) + log_error ("failed to unprotect the secret key: %s\n", + gpg_strerror (rc)); + break; + case PRIVATE_KEY_SHADOWED: + if (shadow_info) + { + const unsigned char *s; + size_t n; + + rc = agent_get_shadow_info (buf, &s); + if (!rc) + { + n = gcry_sexp_canon_len (s, 0, NULL,NULL); + assert (n); + *shadow_info = xtrymalloc (n); + if (!*shadow_info) + rc = out_of_core (); + else + { + memcpy (*shadow_info, s, n); + rc = 0; + } + } + if (rc) + log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc)); + } + rc = -1; /* ugly interface: we return an error but keep a value + in shadow_info. */ + break; + default: + log_error ("invalid private key format\n"); + rc = gpg_error (GPG_ERR_BAD_SECKEY); + break; + } + if (rc) + { + xfree (buf); + return NULL; + } + + /* arggg FIXME: does scan support secure memory? */ + rc = gcry_sexp_sscan (&s_skey, &erroff, + buf, gcry_sexp_canon_len (buf, 0, NULL, NULL)); + xfree (buf); + if (rc) + { + log_error ("failed to build S-Exp (off=%u): %s\n", + (unsigned int)erroff, gpg_strerror (rc)); + return NULL; + } + + return s_skey; +} + +/* Return the secret key as an S-Exp after locating it using the grip. + Returns NULL if key is not available. 0 = key is available */ +int +agent_key_available (const unsigned char *grip) +{ + int i; + char *fname; + char hexgrip[40+4+1]; + + for (i=0; i < 20; i++) + sprintf (hexgrip+2*i, "%02X", grip[i]); + strcpy (hexgrip+40, ".key"); + + fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); + i = !access (fname, R_OK)? 0 : -1; + xfree (fname); + return i; +} + + + diff --git a/agent/genkey.c b/agent/genkey.c new file mode 100644 index 000000000..0a0577f17 --- /dev/null +++ b/agent/genkey.c @@ -0,0 +1,240 @@ +/* pksign.c - Generate a keypair + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> + +#include "agent.h" +#include "i18n.h" + +static int +store_key (gcry_sexp_t private, const char *passphrase, int force) +{ + int rc; + char *buf; + size_t len; + unsigned char grip[20]; + + if ( !gcry_pk_get_keygrip (private, grip) ) + { + log_error ("can't calculate keygrip\n"); + return gpg_error (GPG_ERR_GENERAL); + } + + len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = gcry_malloc_secure (len); + if (!buf) + return out_of_core (); + len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + + if (passphrase) + { + unsigned char *p; + + rc = agent_protect (buf, passphrase, &p, &len); + if (rc) + { + xfree (buf); + return rc; + } + xfree (buf); + buf = p; + } + + rc = agent_write_private_key (grip, buf, len, force); + xfree (buf); + return rc; +} + +/* Callback function to compare the first entered PIN with the one + currently being entered. */ +static int +reenter_compare_cb (struct pin_entry_info_s *pi) +{ + const char *pin1 = pi->check_cb_arg; + + if (!strcmp (pin1, pi->pin)) + return 0; /* okay */ + pi->cb_errtext = _("does not match - try again"); + return -1; +} + + + +/* Generate a new keypair according to the parameters given in + KEYPARAM */ +int +agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, + FILE *outfp) +{ + gcry_sexp_t s_keyparam, s_key, s_private, s_public; + struct pin_entry_info_s *pi, *pi2; + int rc; + size_t len; + char *buf; + + rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen); + if (rc) + { + log_error ("failed to convert keyparam: %s\n", gpg_strerror (rc)); + return gpg_error (GPG_ERR_INV_DATA); + } + + /* Get the passphrase now, cause key generation may take a while. */ + { + const char *text1 = _("Please enter the passphrase to%0A" + "to protect your new key"); + const char *text2 = _("Please re-enter this passphrase"); + + pi = gcry_calloc_secure (2, sizeof (*pi) + 100); + pi2 = pi + (sizeof *pi + 100); + pi->max_length = 100; + pi->max_tries = 3; + pi2->max_length = 100; + pi2->max_tries = 3; + pi2->check_cb = reenter_compare_cb; + pi2->check_cb_arg = pi->pin; + + rc = agent_askpin (ctrl, text1, pi); + if (!rc) + rc = agent_askpin (ctrl, text2, pi2); + if (rc) + return rc; + if (!*pi->pin) + { + xfree (pi); + pi = NULL; /* User does not want a passphrase. */ + } + } + + rc = gcry_pk_genkey (&s_key, s_keyparam ); + gcry_sexp_release (s_keyparam); + if (rc) + { + log_error ("key generation failed: %s\n", gpg_strerror (rc)); + xfree (pi); + return map_gcry_err (rc); + } + + /* break out the parts */ + s_private = gcry_sexp_find_token (s_key, "private-key", 0); + if (!s_private) + { + log_error ("key generation failed: invalid return value\n"); + gcry_sexp_release (s_key); + xfree (pi); + return gpg_error (GPG_ERR_INV_DATA); + } + s_public = gcry_sexp_find_token (s_key, "public-key", 0); + if (!s_public) + { + log_error ("key generation failed: invalid return value\n"); + gcry_sexp_release (s_private); + gcry_sexp_release (s_key); + xfree (pi); + return gpg_error (GPG_ERR_INV_DATA); + } + gcry_sexp_release (s_key); s_key = NULL; + + /* store the secret key */ + log_debug ("storing private key\n"); + rc = store_key (s_private, pi? pi->pin:NULL, 0); + xfree (pi); pi = NULL; + gcry_sexp_release (s_private); + if (rc) + { + gcry_sexp_release (s_public); + return rc; + } + + /* return the public key */ + log_debug ("returning public key\n"); + len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xtrymalloc (len); + if (!buf) + { + gpg_error_t tmperr = out_of_core (); + gcry_sexp_release (s_private); + gcry_sexp_release (s_public); + return tmperr; + } + len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + if (fwrite (buf, len, 1, outfp) != 1) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error writing public key: %s\n", strerror (errno)); + gcry_sexp_release (s_private); + gcry_sexp_release (s_public); + xfree (buf); + return tmperr; + } + gcry_sexp_release (s_public); + xfree (buf); + + return 0; +} + + + +/* Apply a new passpahrse to the key S_SKEY and store it. */ +int +agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey) +{ + struct pin_entry_info_s *pi, *pi2; + int rc; + + { + const char *text1 = _("Please enter the new passphrase"); + const char *text2 = _("Please re-enter this passphrase"); + + pi = gcry_calloc_secure (2, sizeof (*pi) + 100); + pi2 = pi + (sizeof *pi + 100); + pi->max_length = 100; + pi->max_tries = 3; + pi2->max_length = 100; + pi2->max_tries = 3; + pi2->check_cb = reenter_compare_cb; + pi2->check_cb_arg = pi->pin; + + rc = agent_askpin (ctrl, text1, pi); + if (!rc) + rc = agent_askpin (ctrl, text2, pi2); + if (rc) + return rc; + if (!*pi->pin) + { + xfree (pi); + pi = NULL; /* User does not want a passphrase. */ + } + } + + rc = store_key (s_skey, pi? pi->pin:NULL, 1); + xfree (pi); + return 0; +} diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c new file mode 100644 index 000000000..675f2be3f --- /dev/null +++ b/agent/gpg-agent.c @@ -0,0 +1,1063 @@ +/* gpg-agent.c - The GnuPG Agent + * Copyright (C) 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 <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <time.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <signal.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif + +#define JNLIB_NEED_LOG_LOGV +#include "agent.h" +#include <assuan.h> /* malloc hooks */ + +#include "i18n.h" +#include "sysutils.h" + + +enum cmd_and_opt_values +{ aNull = 0, + oCsh = 'c', + oQuiet = 'q', + oSh = 's', + oVerbose = 'v', + + oNoVerbose = 500, + oOptions, + oDebug, + oDebugAll, + oDebugWait, + oNoGreeting, + oNoOptions, + oHomedir, + oNoDetach, + oNoGrab, + oLogFile, + oServer, + oDaemon, + oBatch, + + oPinentryProgram, + oDisplay, + oTTYname, + oTTYtype, + oLCctype, + oLCmessages, + oScdaemonProgram, + oDefCacheTTL, + oDisablePth, + + oIgnoreCacheForSigning, + oKeepTTY, + oKeepDISPLAY, + +aTest }; + + + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oServer, "server", 0, N_("run in server mode (foreground)") }, + { oDaemon, "daemon", 0, N_("run in daemon mode (background)") }, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oSh, "sh", 0, N_("sh-style command output") }, + { oCsh, "csh", 0, N_("csh-style command output") }, + { oOptions, "options" , 2, N_("read options from file")}, + { oDebug, "debug" ,4|16, N_("set debugging flags")}, + { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, + { oDebugWait,"debug-wait",1, "@"}, + { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, + { oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")}, + { oLogFile, "log-file" ,2, N_("use a log file for the server")}, + { oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")}, + + { oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" }, + { oDisplay, "display", 2, "set the display" }, + { oTTYname, "ttyname", 2, "set the tty terminal node name" }, + { oTTYtype, "ttytype", 2, "set the tty terminal type" }, + { oLCctype, "lc-ctype", 2, "set the tty LC_CTYPE value" }, + { oLCmessages, "lc-messages", 2, "set the tty LC_MESSAGES value" }, + + { oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" }, + { oDefCacheTTL, "default-cache-ttl", 4, + "|N|expire cached PINs after N seconds"}, + { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, + "do not use the PIN cache when signing"}, + { oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")}, + { oKeepDISPLAY, "keep-display", + 0, N_("ignore requests to change the X display")}, + {0} +}; + + +static volatile int caught_fatal_sig = 0; + +/* flag to indicate that a shutdown was requested */ +static int shutdown_pending; + + +/* It is possible that we are currently running under setuid permissions */ +static int maybe_setuid = 1; + +/* Name of the communication socket */ +static char socket_name[128]; + +/* Default values for options passed to the pinentry. */ +static char *default_display; +static char *default_ttyname; +static char *default_ttytype; +static char *default_lc_ctype; +static char *default_lc_messages; + +/* Name of a config file, which will be reread on a HUP if it is not NULL. */ +static char *config_filename; + + +/* Local prototypes. */ +static void create_directories (void); +#ifdef USE_GNU_PTH +static void handle_connections (int listen_fd); +#endif + + + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "gpg-agent (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: gpg-agent [options] (-h for help)"); + break; + case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n" + "Secret key management for GnuPG\n"); + break; + + default: p = NULL; + } + return p; +} + + + +static void +i18n_init (void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE ); +#else +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif +#endif +} + + + +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* translate the log levels */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; + } + log_logv (level, fmt, arg_ptr); +} + + +static void +cleanup (void) +{ + if (*socket_name) + { + char *p; + + remove (socket_name); + p = strrchr (socket_name, '/'); + if (p) + { + *p = 0; + rmdir (socket_name); + *p = '/'; + } + *socket_name = 0; + } +} + + +static RETSIGTYPE +cleanup_sh (int sig) +{ + if (caught_fatal_sig) + raise (sig); + caught_fatal_sig = 1; + + /* gcry_control( GCRYCTL_TERM_SECMEM );*/ + cleanup (); + +#ifndef HAVE_DOSISH_SYSTEM + { /* reset action to default action and raise signal again */ + struct sigaction nact; + nact.sa_handler = SIG_DFL; + sigemptyset( &nact.sa_mask ); + nact.sa_flags = 0; + sigaction( sig, &nact, NULL); + } +#endif + raise( sig ); +} + + +/* Handle options which are allowed to be reset after program start. + Return true when the current option in PARGS could be handled and + false if not. As a special feature, passing a value of NULL for + PARGS, resets the options to the default. */ +static int +parse_rereadable_options (ARGPARSE_ARGS *pargs) +{ + if (!pargs) + { /* reset mode */ + opt.quiet = 0; + opt.verbose = 0; + opt.debug = 0; + opt.no_grab = 0; + opt.pinentry_program = NULL; + opt.scdaemon_program = NULL; + opt.def_cache_ttl = 10*60; /* default to 10 minutes */ + opt.ignore_cache_for_signing = 0; + return 1; + } + + switch (pargs->r_opt) + { + case oQuiet: opt.quiet = 1; break; + case oVerbose: opt.verbose++; break; + + case oDebug: opt.debug |= pargs->r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + + case oNoGrab: opt.no_grab = 1; break; + + case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break; + case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break; + + case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break; + + case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; + + default: + return 0; /* not handled */ + } + return 1; /* handled */ +} + + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + int orig_argc; + int may_coredump; + char **orig_argv; + FILE *configfp = NULL; + char *configname = NULL; + const char *shell; + unsigned configlineno; + int parse_debug = 0; + int default_config =1; + int greeting = 0; + int nogreeting = 0; + int pipe_server = 0; + int is_daemon = 0; + int nodetach = 0; + int csh_style = 0; + char *logfile = NULL; + int debug_wait = 0; + int disable_pth = 0; + + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + /* Please note that we may running SUID(ROOT), so be very CAREFUL + when adding any stuff between here and the call to INIT_SECMEM() + somewhere after the option parsing */ + log_set_prefix ("gpg-agent", 1|4); + i18n_init (); + + /* We need to initialize Pth before libgcrypt, because the libgcrypt + initialization done by gcry_check_version internally sets up its + mutex system. Note that one must not link against pth if + USE_GNU_PTH is not defined. */ +#ifdef USE_GNU_PTH + if (!pth_init ()) + { + log_error ("failed to initialize the Pth library\n"); + exit (1); + } +#endif /*USE_GNU_PTH*/ + + /* check that the libraries are suitable. Do it here because + the option parsing may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + + gcry_set_log_handler (my_gcry_logger, NULL); + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + + may_coredump = disable_core_dumps (); + + parse_rereadable_options (NULL); /* Reset them to default values. */ + + shell = getenv ("SHELL"); + if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) + csh_style = 1; + + opt.homedir = getenv("GNUPGHOME"); + if (!opt.homedir || !*opt.homedir) + opt.homedir = GNUPG_DEFAULT_HOMEDIR; + + + /* check whether we have a config file on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ + while (arg_parse( &pargs, opts)) + { + if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) + parse_debug++; + else if (pargs.r_opt == oOptions) + { /* yes there is one, so we do not try the default one, but + read the option file when it is encountered at the + commandline */ + default_config = 0; + } + else if (pargs.r_opt == oNoOptions) + default_config = 0; /* --no-options */ + else if (pargs.r_opt == oHomedir) + opt.homedir = pargs.r.ret_str; + } + + /* initialize the secure memory. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + maybe_setuid = 0; + + /* + Now we are now working under our real uid + */ + + + if (default_config) + configname = make_filename (opt.homedir, "gpg-agent.conf", NULL ); + + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + next_pass: + if (configname) + { + configlineno = 0; + configfp = fopen (configname, "r"); + if (!configfp) + { + if (default_config) + { + if( parse_debug ) + log_info (_("NOTE: no default option file `%s'\n"), + configname ); + } + else + { + log_error (_("option file `%s': %s\n"), + configname, strerror(errno) ); + exit(2); + } + xfree (configname); + configname = NULL; + } + if (parse_debug && configname ) + log_info (_("reading options from `%s'\n"), configname ); + default_config = 0; + } + + while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) + { + if (parse_rereadable_options (&pargs)) + continue; /* Already handled */ + switch (pargs.r_opt) + { + case oBatch: opt.batch=1; break; + + case oDebugWait: debug_wait = pargs.r.ret_int; break; + + case oOptions: + /* config files may not be nested (silently ignore them) */ + if (!configfp) + { + xfree(configname); + configname = xstrdup(pargs.r.ret_str); + goto next_pass; + } + break; + case oNoGreeting: nogreeting = 1; break; + case oNoVerbose: opt.verbose = 0; break; + case oNoOptions: break; /* no-options */ + case oHomedir: opt.homedir = pargs.r.ret_str; break; + case oNoDetach: nodetach = 1; break; + case oLogFile: logfile = pargs.r.ret_str; break; + case oCsh: csh_style = 1; break; + case oSh: csh_style = 0; break; + case oServer: pipe_server = 1; break; + case oDaemon: is_daemon = 1; break; + case oDisablePth: disable_pth = 1; break; + + case oDisplay: default_display = xstrdup (pargs.r.ret_str); break; + case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break; + case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break; + case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break; + case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break; + + case oKeepTTY: opt.keep_tty = 1; break; + case oKeepDISPLAY: opt.keep_display = 1; break; + + default : pargs.err = configfp? 1:2; break; + } + } + if (configfp) + { + fclose( configfp ); + configfp = NULL; + /* Keep a copy of the name so that it can be read on SIGHUP. */ + config_filename = configname; + configname = NULL; + goto next_pass; + } + xfree (configname); + configname = NULL; + if (log_get_errorcount(0)) + exit(2); + if (nogreeting ) + greeting = 0; + + if (greeting) + { + fprintf (stderr, "%s %s; %s\n", + strusage(11), strusage(13), strusage(14) ); + fprintf (stderr, "%s\n", strusage(15) ); + } +#ifdef IS_DEVELOPMENT_VERSION + log_info ("NOTE: this is a development version!\n"); +#endif + + + if (atexit (cleanup)) + { + log_error ("atexit failed\n"); + cleanup (); + exit (1); + } + + create_directories (); + + if (debug_wait && pipe_server) + { + log_debug ("waiting for debugger - my pid is %u .....\n", + (unsigned int)getpid()); + sleep (debug_wait); + log_debug ("... okay\n"); + } + + if (!pipe_server && !is_daemon) + log_info (_("please use the option `--daemon'" + " to run the program in the background\n")); + +#ifdef ENABLE_NLS + /* gpg-agent usdually does not ooutput any messages becuase it runs + in the background. For log files it is acceptable to have + messages always encoded in utf-8. We switch here to utf-8, so + that commands like --help still give native messages. It is far + easier to swicthnonly once instead of for every message and it + actually helps when more then one thread is active (avoids + required an extra copy step). */ + bind_textdomain_codeset (PACKAGE, "UTF-8"); +#endif + + /* now start with logging to a file if this is desired */ + if (logfile) + { + log_set_file (logfile); + log_set_prefix (NULL, 1|2|4); + } + + /* Make sure that we have a default ttyname. */ + if (!default_ttyname && ttyname (1)) + default_ttyname = xstrdup (ttyname (1)); + if (!default_ttytype && getenv ("TERM")) + default_ttytype = xstrdup (getenv ("TERM")); + + if (pipe_server) + { /* this is the simple pipe based server */ + start_command_handler (-1, -1); + } + else if (!is_daemon) + ; + else + { /* regular server mode */ + int fd; + pid_t pid; + int len; + struct sockaddr_un serv_addr; + char *p; + + /* Remove the DISPLAY variable so that a pinentry does not + default to a specific display. There is still a default + display when gpg-agent weas started using --display or a + client requested this using an OPTION command. */ + if (!opt.keep_display) + unsetenv ("DISPLAY"); + + *socket_name = 0; + snprintf (socket_name, DIM(socket_name)-1, + "/tmp/gpg-XXXXXX/S.gpg-agent"); + socket_name[DIM(socket_name)-1] = 0; + p = strrchr (socket_name, '/'); + if (!p) + BUG (); + *p = 0;; + if (!mkdtemp(socket_name)) + { + log_error ("can't create directory `%s': %s\n", + socket_name, strerror(errno) ); + exit (1); + } + *p = '/'; + + if (strchr (socket_name, ':') ) + { + log_error ("colons are not allowed in the socket name\n"); + exit (1); + } + if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) + { + log_error ("name of socket too long\n"); + exit (1); + } + + + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + log_error ("can't create socket: %s\n", strerror(errno) ); + exit (1); + } + + memset (&serv_addr, 0, sizeof serv_addr); + serv_addr.sun_family = AF_UNIX; + strcpy (serv_addr.sun_path, socket_name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen(serv_addr.sun_path) + 1); + + if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1) + { + log_error ("error binding socket to `%s': %s\n", + serv_addr.sun_path, strerror (errno) ); + close (fd); + exit (1); + } + + if (listen (fd, 5 ) == -1) + { + log_error ("listen() failed: %s\n", strerror (errno)); + close (fd); + exit (1); + } + + if (opt.verbose) + log_info ("listening on socket `%s'\n", socket_name ); + + + fflush (NULL); + pid = fork (); + if (pid == (pid_t)-1) + { + log_fatal ("fork failed: %s\n", strerror (errno) ); + exit (1); + } + else if (pid) + { /* we are the parent */ + char *infostr; + + close (fd); + + /* create the info string: <name>:<pid>:<protocol_version> */ + if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1", + socket_name, (ulong)pid ) < 0) + { + log_error ("out of core\n"); + kill (pid, SIGTERM); + exit (1); + } + *socket_name = 0; /* don't let cleanup() remove the socket - + the child should do this from now on */ + if (argc) + { /* run the program given on the commandline */ + if (putenv (infostr)) + { + log_error ("failed to set environment: %s\n", + strerror (errno) ); + kill (pid, SIGTERM ); + exit (1); + } + execvp (argv[0], argv); + log_error ("failed to run the command: %s\n", strerror (errno)); + kill (pid, SIGTERM); + exit (1); + } + else + { + /* print the environment string, so that the caller can use + shell's eval to set it */ + if (csh_style) + { + *strchr (infostr, '=') = ' '; + printf ( "setenv %s\n", infostr); + } + else + { + printf ( "%s; export GPG_AGENT_INFO;\n", infostr); + } + free (infostr); + exit (0); + } + /*NEVER REACHED*/ + } /* end parent */ + + + /* this is the child */ + + /* detach from tty and put process into a new session */ + if (!nodetach ) + { + int i; + + /* close stdin, stdout and stderr unless it is the log stream */ + for (i=0; i <= 2; i++) + { + if ( log_get_fd () != i) + close (i); + } + if (setsid() == -1) + { + log_error ("setsid() failed: %s\n", strerror(errno) ); + cleanup (); + exit (1); + } + opt.running_detached = 1; + } + + if (chdir("/")) + { + log_error ("chdir to / failed: %s\n", strerror (errno)); + exit (1); + } + + +#ifdef USE_GNU_PTH + if (!disable_pth) + { + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGPIPE, &sa, NULL); + handle_connections (fd); + } + else +#endif /*!USE_GNU_PTH*/ + /* setup signals */ + { + struct sigaction oact, nact; + + nact.sa_handler = cleanup_sh; + sigemptyset (&nact.sa_mask); + nact.sa_flags = 0; + + sigaction (SIGHUP, NULL, &oact); + if (oact.sa_handler != SIG_IGN) + sigaction (SIGHUP, &nact, NULL); + sigaction( SIGTERM, NULL, &oact ); + if (oact.sa_handler != SIG_IGN) + sigaction (SIGTERM, &nact, NULL); + nact.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &nact, NULL); + sigaction (SIGINT, &nact, NULL); + + start_command_handler (fd, -1); + } + close (fd); + } + + return 0; +} + +void +agent_exit (int rc) +{ + /*FIXME: update_random_seed_file();*/ +#if 1 + /* at this time a bit annoying */ + if (opt.debug & DBG_MEMSTAT_VALUE) + { + gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); + gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + } + if (opt.debug) + gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); +#endif + gcry_control (GCRYCTL_TERM_SECMEM ); + rc = rc? rc : log_get_errorcount(0)? 2 : 0; + exit (rc); +} + + +void +agent_init_default_ctrl (struct server_control_s *ctrl) +{ + /* Note we ignore malloc errors because we can't do much about it + and the request will fail anyway shortly after this + initialization. */ + if (ctrl->display) + free (ctrl->display); + ctrl->display = default_display? strdup (default_display) : NULL; + + if (ctrl->ttyname) + free (ctrl->ttyname); + ctrl->ttyname = default_ttyname? strdup (default_ttyname) : NULL; + + if (ctrl->ttytype) + free (ctrl->ttytype); + ctrl->ttytype = default_ttytype? strdup (default_ttytype) : NULL; + + if (ctrl->lc_ctype) + free (ctrl->lc_ctype); + ctrl->lc_ctype = default_lc_ctype? strdup (default_lc_ctype) : NULL; + + if (ctrl->lc_messages) + free (ctrl->lc_messages); + ctrl->lc_messages = default_lc_messages? strdup (default_lc_messages) : NULL; +} + + +/* Reread parts of the configuration. Note, that this function is + obviously not thread-safe and should only be called from the PTH + signal handler. + + Fixme: Due to the way the argument parsing works, we create a + memory leak here for all string type arguments. There is currently + no clean way to tell whether the memory for the argument has been + allocated or points into the process' original arguments. Unless + we have a mechanism to tell this, we need to live on with this. */ +static void +reread_configuration (void) +{ + ARGPARSE_ARGS pargs; + FILE *fp; + unsigned int configlineno = 0; + int dummy; + + if (!config_filename) + return; /* No config file. */ + + fp = fopen (config_filename, "r"); + if (!fp) + { + log_error (_("option file `%s': %s\n"), + config_filename, strerror(errno) ); + return; + } + + parse_rereadable_options (NULL); /* Start from the default values. */ + + memset (&pargs, 0, sizeof pargs); + dummy = 0; + pargs.argc = &dummy; + pargs.flags = 1; /* do not remove the args */ + while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) ) + { + if (pargs.r_opt < -1) + pargs.err = 1; /* Print a warning. */ + else /* Try to parse this option - ignore unchangeable ones. */ + parse_rereadable_options (&pargs); + } + fclose (fp); +} + + +static void +create_private_keys_directory (const char *home) +{ + char *fname; + struct stat statbuf; + + fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL); + if (stat (fname, &statbuf) && errno == ENOENT) + { + if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR )) + log_error (_("can't create directory `%s': %s\n"), + fname, strerror(errno) ); + else if (!opt.quiet) + log_info (_("directory `%s' created\n"), fname); + } + xfree (fname); +} + +/* Create the directory only if the supplied directory name is the + same as the default one. This way we avoid to create arbitrary + directories when a non-default home directory is used. To cope + with HOME, we compare only the suffix if we see that the default + homedir does start with a tilde. We don't stop here in case of + problems because other functions will throw an error anyway.*/ +static void +create_directories (void) +{ + struct stat statbuf; + const char *defhome = GNUPG_DEFAULT_HOMEDIR; + char *home; + + home = make_filename (opt.homedir, NULL); + if ( stat (home, &statbuf) ) + { + if (errno == ENOENT) + { + if ( (*defhome == '~' + && (strlen (home) >= strlen (defhome+1) + && !strcmp (home + strlen(home) + - strlen (defhome+1), defhome+1))) + || (*defhome != '~' && !strcmp (home, defhome) ) + ) + { + if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR )) + log_error (_("can't create directory `%s': %s\n"), + home, strerror(errno) ); + else + { + if (!opt.quiet) + log_info (_("directory `%s' created\n"), home); + create_private_keys_directory (home); + } + } + } + else + log_error ("error stat-ing `%s': %s\n", home, strerror (errno)); + } + else if ( !S_ISDIR(statbuf.st_mode)) + { + log_error ("can't use `%s' as home directory\n", home); + } + else /* exists and is a directory. */ + { + create_private_keys_directory (home); + } + xfree (home); +} + + + +#ifdef USE_GNU_PTH +static void +handle_signal (int signo) +{ + switch (signo) + { + case SIGHUP: + log_info ("SIGHUP received - " + "re-reading configuration and flushing cache\n"); + agent_flush_cache (); + reread_configuration (); + break; + + case SIGUSR1: + if (opt.verbose < 5) + opt.verbose++; + log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose); + break; + + case SIGUSR2: + if (opt.verbose) + opt.verbose--; + log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose ); + break; + + case SIGTERM: + if (!shutdown_pending) + log_info ("SIGTERM received - shutting down ...\n"); + else + log_info ("SIGTERM received - still %ld running threads\n", + pth_ctrl( PTH_CTRL_GETTHREADS )); + shutdown_pending++; + if (shutdown_pending > 2) + { + log_info ("shutdown forced\n"); + log_info ("%s %s stopped\n", strusage(11), strusage(13) ); + cleanup (); + agent_exit (0); + } + break; + + case SIGINT: + log_info ("SIGINT received - immediate shutdown\n"); + log_info( "%s %s stopped\n", strusage(11), strusage(13)); + cleanup (); + agent_exit (0); + break; + + default: + log_info ("signal %d received - no action defined\n", signo); + } +} + + +static void * +start_connection_thread (void *arg) +{ + int fd = (int)arg; + + if (opt.verbose) + log_info ("handler for fd %d started\n", fd); + start_command_handler (-1, fd); + if (opt.verbose) + log_info ("handler for fd %d terminated\n", fd); + + return NULL; +} + + +static void +handle_connections (int listen_fd) +{ + pth_attr_t tattr; + pth_event_t ev; + sigset_t sigs; + int signo; + struct sockaddr_un paddr; + socklen_t plen = sizeof( paddr ); + int fd; + + tattr = pth_attr_new(); + pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024); + pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent"); + + sigemptyset (&sigs ); + sigaddset (&sigs, SIGHUP); + sigaddset (&sigs, SIGUSR1); + sigaddset (&sigs, SIGUSR2); + sigaddset (&sigs, SIGINT); + sigaddset (&sigs, SIGTERM); + ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); + + for (;;) + { + if (shutdown_pending) + { + if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1) + break; /* ready */ + + /* Do not accept anymore connections and wait for existing + connections to terminate */ + signo = 0; + pth_wait (ev); + if (pth_event_occurred (ev) && signo) + handle_signal (signo); + continue; + } + + fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { +#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ + if (pth_event_status (ev) == PTH_STATUS_OCCURRED) +#else + if (pth_event_occurred (ev)) +#endif + { + handle_signal (signo); + continue; + } + log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); + pth_sleep(1); + continue; + } + + if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } + } + + pth_event_free (ev, PTH_FREE_ALL); + cleanup (); + log_info ("%s %s stopped\n", strusage(11), strusage(13)); +} +#endif /*USE_GNU_PTH*/ diff --git a/agent/learncard.c b/agent/learncard.c new file mode 100644 index 000000000..28a74f972 --- /dev/null +++ b/agent/learncard.c @@ -0,0 +1,448 @@ +/* learncard.c - Handle the LEARN command + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" +#include <assuan.h> + +struct keypair_info_s { + struct keypair_info_s *next; + int no_cert; + char *id; /* points into grip */ + char hexgrip[1]; +}; +typedef struct keypair_info_s *KEYPAIR_INFO; + +struct kpinfo_cb_parm_s { + int error; + KEYPAIR_INFO info; +}; + + +struct certinfo_s { + struct certinfo_s *next; + int type; + int done; + char id[1]; +}; +typedef struct certinfo_s *CERTINFO; + +struct certinfo_cb_parm_s { + int error; + CERTINFO info; +}; + + +struct sinfo_s { + struct sinfo_s *next; + char *data; /* Points into keyword. */ + char keyword[1]; +}; +typedef struct sinfo_s *SINFO; + +struct sinfo_cb_parm_s { + int error;; + SINFO info; +}; + + + +static void +release_keypair_info (KEYPAIR_INFO info) +{ + while (info) + { + KEYPAIR_INFO tmp = info->next; + xfree (info); + info = tmp; + } +} + +static void +release_certinfo (CERTINFO info) +{ + while (info) + { + CERTINFO tmp = info->next; + xfree (info); + info = tmp; + } +} + +static void +release_sinfo (SINFO info) +{ + while (info) + { + SINFO tmp = info->next; + xfree (info); + info = tmp; + } +} + + + +/* This callback is used by agent_card_learn and passed the content of + all KEYPAIRINFO lines. It merely stores this data away */ +static void +kpinfo_cb (void *opaque, const char *line) +{ + struct kpinfo_cb_parm_s *parm = opaque; + KEYPAIR_INFO item; + char *p; + + if (parm->error) + return; /* no need to gather data after an error coccured */ + item = xtrycalloc (1, sizeof *item + strlen (line)); + if (!item) + { + parm->error = out_of_core (); + return; + } + strcpy (item->hexgrip, line); + for (p = item->hexgrip; hexdigitp (p); p++) + ; + if (p == item->hexgrip && *p == 'X' && spacep (p+1)) + { + item->no_cert = 1; + p++; + } + else if ((p - item->hexgrip) != 40 || !spacep (p)) + { /* not a 20 byte hex keygrip or not followed by a space */ + parm->error = gpg_error (GPG_ERR_INV_RESPONSE); + xfree (item); + return; + } + *p++ = 0; + while (spacep (p)) + p++; + item->id = p; + while (*p && !spacep (p)) + p++; + if (p == item->id) + { /* invalid ID string */ + parm->error = gpg_error (GPG_ERR_INV_RESPONSE); + xfree (item); + return; + } + *p = 0; /* ignore trailing stuff */ + + /* store it */ + item->next = parm->info; + parm->info = item; +} + + +/* This callback is used by agent_card_learn and passed the content of + all CERTINFO lines. It merely stores this data away */ +static void +certinfo_cb (void *opaque, const char *line) +{ + struct certinfo_cb_parm_s *parm = opaque; + CERTINFO item; + int type; + char *p, *pend; + + if (parm->error) + return; /* no need to gather data after an error coccured */ + + type = strtol (line, &p, 10); + while (spacep (p)) + p++; + for (pend = p; *pend && !spacep (pend); pend++) + ; + if (p == pend || !*p) + { + parm->error = gpg_error (GPG_ERR_INV_RESPONSE); + return; + } + *pend = 0; /* ignore trailing stuff */ + + item = xtrycalloc (1, sizeof *item + strlen (p)); + if (!item) + { + parm->error = out_of_core (); + return; + } + item->type = type; + strcpy (item->id, p); + /* store it */ + item->next = parm->info; + parm->info = item; +} + + +/* This callback is used by agent_card_learn and passed the content of + all SINFO lines. It merely stores this data away */ +static void +sinfo_cb (void *opaque, const char *keyword, size_t keywordlen, + const char *data) +{ + struct sinfo_cb_parm_s *sparm = opaque; + SINFO item; + + if (sparm->error) + return; /* no need to gather data after an error coccured */ + + item = xtrycalloc (1, sizeof *item + keywordlen + 1 + strlen (data)); + if (!item) + { + sparm->error = out_of_core (); + return; + } + memcpy (item->keyword, keyword, keywordlen); + item->data = item->keyword + keywordlen; + *item->data = 0; + item->data++; + strcpy (item->data, data); + /* store it */ + item->next = sparm->info; + sparm->info = item; +} + + +/* Create an S-expression with the shadow info. */ +static unsigned char * +make_shadow_info (const char *serialno, const char *idstring) +{ + const char *s; + unsigned char *info, *p; + char numbuf[21]; + int n; + + for (s=serialno, n=0; *s && s[1]; s += 2) + n++; + + info = p = xtrymalloc (1 + 21 + n + + 21 + strlen (idstring) + 1 + 1); + *p++ = '('; + sprintf (numbuf, "%d:", n); + p = stpcpy (p, numbuf); + for (s=serialno; *s && s[1]; s += 2) + *p++ = xtoi_2 (s); + sprintf (numbuf, "%d:", strlen (idstring)); + p = stpcpy (p, numbuf); + p = stpcpy (p, idstring); + *p++ = ')'; + *p = 0; + return info; +} + +static int +send_cert_back (const char *id, void *assuan_context) +{ + int rc; + char *derbuf; + size_t derbuflen; + + rc = agent_card_readcert (id, &derbuf, &derbuflen); + if (rc) + { + log_error ("error reading certificate: %s\n", + gpg_strerror (rc)); + return rc; + } + + rc = assuan_send_data (assuan_context, derbuf, derbuflen); + xfree (derbuf); + if (!rc) + rc = assuan_send_data (assuan_context, NULL, 0); + if (!rc) + rc = assuan_write_line (assuan_context, "END"); + if (rc) + { + log_error ("sending certificate failed: %s\n", + assuan_strerror (rc)); + return map_assuan_err (rc); + } + return 0; +} + +/* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new + certificates are send via Assuan */ +int +agent_handle_learn (void *assuan_context) +{ + int rc; + struct kpinfo_cb_parm_s parm; + struct certinfo_cb_parm_s cparm; + struct sinfo_cb_parm_s sparm; + char *serialno = NULL; + KEYPAIR_INFO item; + SINFO sitem; + unsigned char grip[20]; + char *p; + int i; + static int certtype_list[] = { + 101, /* trusted */ + 102, /* useful */ + 100, /* regular */ + -1 /* end of list */ + }; + + + memset (&parm, 0, sizeof parm); + memset (&cparm, 0, sizeof cparm); + memset (&sparm, 0, sizeof sparm); + + /* Check whether a card is present and get the serial number */ + rc = agent_card_serialno (&serialno); + if (rc) + goto leave; + + /* now gather all the available info */ + rc = agent_card_learn (kpinfo_cb, &parm, certinfo_cb, &cparm, + sinfo_cb, &sparm); + if (!rc && (parm.error || cparm.error || sparm.error)) + rc = parm.error? parm.error : cparm.error? cparm.error : sparm.error; + if (rc) + { + log_debug ("agent_card_learn failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + log_info ("card has S/N: %s\n", serialno); + + /* Pass on all the collected status information. */ + if (assuan_context) + { + for (sitem = sparm.info; sitem; sitem = sitem->next) + { + assuan_write_status (assuan_context, sitem->keyword, sitem->data); + } + } + + /* Write out the certificates in a standard order. */ + for (i=0; certtype_list[i] != -1; i++) + { + CERTINFO citem; + for (citem = cparm.info; citem; citem = citem->next) + { + if (certtype_list[i] != citem->type) + continue; + + if (opt.verbose) + log_info (" id: %s (type=%d)\n", + citem->id, citem->type); + + if (assuan_context) + { + rc = send_cert_back (citem->id, assuan_context); + if (rc) + goto leave; + citem->done = 1; + } + } + } + + for (item = parm.info; item; item = item->next) + { + unsigned char *pubkey, *shdkey; + size_t n; + + if (opt.verbose) + log_info (" id: %s (grip=%s)\n", item->id, item->hexgrip); + + if (item->no_cert) + continue; /* no public key yet available */ + + for (p=item->hexgrip, i=0; i < 20; p += 2, i++) + grip[i] = xtoi_2 (p); + + if (!agent_key_available (grip)) + continue; + + /* unknown - store it */ + rc = agent_card_readkey (item->id, &pubkey); + if (rc) + { + log_debug ("agent_card_readkey failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + { + unsigned char *shadow_info = make_shadow_info (serialno, item->id); + if (!shadow_info) + { + rc = gpg_error (GPG_ERR_ENOMEM); + xfree (pubkey); + goto leave; + } + rc = agent_shadow_key (pubkey, shadow_info, &shdkey); + xfree (shadow_info); + } + xfree (pubkey); + if (rc) + { + log_error ("shadowing the key failed: %s\n", gpg_strerror (rc)); + goto leave; + } + n = gcry_sexp_canon_len (shdkey, 0, NULL, NULL); + assert (n); + + rc = agent_write_private_key (grip, shdkey, n, 0); + xfree (shdkey); + if (rc) + { + log_error ("error writing key: %s\n", gpg_strerror (rc)); + goto leave; + } + + if (opt.verbose) + log_info ("stored\n"); + + if (assuan_context) + { + CERTINFO citem; + + /* only send the certificate if we have not done so before */ + for (citem = cparm.info; citem; citem = citem->next) + { + if (!strcmp (citem->id, item->id)) + break; + } + if (!citem) + { + rc = send_cert_back (item->id, assuan_context); + if (rc) + goto leave; + } + } + } + + + leave: + xfree (serialno); + release_keypair_info (parm.info); + release_certinfo (cparm.info); + release_sinfo (sparm.info); + return rc; +} + + diff --git a/agent/minip12.c b/agent/minip12.c new file mode 100644 index 000000000..255fef096 --- /dev/null +++ b/agent/minip12.c @@ -0,0 +1,1140 @@ +/* minip12.c - A minimal pkcs-12 implementation. + * 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 + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <gcrypt.h> + +#undef TEST + +#ifdef TEST +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#endif + +#include "../jnlib/logging.h" +#include "minip12.h" + +#ifndef DIM +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#endif + +enum +{ + UNIVERSAL = 0, + APPLICATION = 1, + CONTEXT = 2, + PRIVATE = 3 +}; + + +enum +{ + TAG_NONE = 0, + TAG_BOOLEAN = 1, + TAG_INTEGER = 2, + TAG_BIT_STRING = 3, + TAG_OCTET_STRING = 4, + TAG_NULL = 5, + TAG_OBJECT_ID = 6, + TAG_OBJECT_DESCRIPTOR = 7, + TAG_EXTERNAL = 8, + TAG_REAL = 9, + TAG_ENUMERATED = 10, + TAG_EMBEDDED_PDV = 11, + TAG_UTF8_STRING = 12, + TAG_REALTIVE_OID = 13, + TAG_SEQUENCE = 16, + TAG_SET = 17, + TAG_NUMERIC_STRING = 18, + TAG_PRINTABLE_STRING = 19, + TAG_TELETEX_STRING = 20, + TAG_VIDEOTEX_STRING = 21, + TAG_IA5_STRING = 22, + TAG_UTC_TIME = 23, + TAG_GENERALIZED_TIME = 24, + TAG_GRAPHIC_STRING = 25, + TAG_VISIBLE_STRING = 26, + TAG_GENERAL_STRING = 27, + TAG_UNIVERSAL_STRING = 28, + TAG_CHARACTER_STRING = 29, + TAG_BMP_STRING = 30 +}; + + +static unsigned char const oid_data[9] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; +static unsigned char const oid_encryptedData[9] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; +static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 }; +static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 }; + +static unsigned char const oid_rsaEncryption[9] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; + + +static unsigned char const data_3desiter1024[30] = { + 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E, + 0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x02, 0x02, 0x04, 0x00 }; +#define DATA_3DESITER1024_SALT_OFF 18 + + +struct buffer_s +{ + unsigned char *buffer; + size_t length; +}; + + +struct tag_info +{ + int class; + int is_constructed; + unsigned long tag; + unsigned long length; /* length part of the TLV */ + int nhdr; + int ndef; /* It is an indefinite length */ +}; + + +/* Parse the buffer at the address BUFFER which is of SIZE and return + the tag and the length part from the TLV triplet. Update BUFFER + and SIZE on success. */ +static int +parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti) +{ + int c; + unsigned long tag; + const unsigned char *buf = *buffer; + size_t length = *size; + + ti->length = 0; + ti->ndef = 0; + ti->nhdr = 0; + + /* Get the tag */ + if (!length) + return -1; /* premature eof */ + c = *buf++; length--; + ti->nhdr++; + + ti->class = (c & 0xc0) >> 6; + ti->is_constructed = !!(c & 0x20); + tag = c & 0x1f; + + if (tag == 0x1f) + { + tag = 0; + do + { + tag <<= 7; + if (!length) + return -1; /* premature eof */ + c = *buf++; length--; + ti->nhdr++; + tag |= c & 0x7f; + } + while (c & 0x80); + } + ti->tag = tag; + + /* Get the length */ + if (!length) + return -1; /* prematureeof */ + c = *buf++; length--; + ti->nhdr++; + + if ( !(c & 0x80) ) + ti->length = c; + else if (c == 0x80) + ti->ndef = 1; + else if (c == 0xff) + return -1; /* forbidden length value */ + else + { + unsigned long len = 0; + int count = c & 0x7f; + + for (; count; count--) + { + len <<= 8; + if (!length) + return -1; /* premature_eof */ + c = *buf++; length--; + ti->nhdr++; + len |= c & 0xff; + } + ti->length = len; + } + + if (ti->class == UNIVERSAL && !ti->tag) + ti->length = 0; + + if (ti->length > length) + return -1; /* data larger than buffer. */ + + *buffer = buf; + *size = length; + return 0; +} + + +static int +string_to_key (int id, char *salt, int iter, const char *pw, + int req_keylen, unsigned char *keybuf) +{ + int rc, i, j; + gcry_md_hd_t md; + gcry_mpi_t num_b1 = NULL; + int pwlen; + unsigned char hash[20], buf_b[64], buf_i[128], *p; + size_t cur_keylen; + size_t n; + + cur_keylen = 0; + pwlen = strlen (pw); + if (pwlen > 63/2) + { + log_error ("password too long\n"); + return -1; + } + + /* Store salt and password in BUF_I */ + p = buf_i; + for(i=0; i < 64; i++) + *p++ = salt [i%8]; + for(i=j=0; i < 64; i += 2) + { + *p++ = 0; + *p++ = pw[j]; + if (++j > pwlen) /* Note, that we include the trailing zero */ + j = 0; + } + + for (;;) + { + rc = gcry_md_open (&md, GCRY_MD_SHA1, 0); + if (rc) + { + log_error ( "gcry_md_open failed: %s\n", gpg_strerror (rc)); + return rc; + } + for(i=0; i < 64; i++) + gcry_md_putc (md, id); + gcry_md_write (md, buf_i, 128); + memcpy (hash, gcry_md_read (md, 0), 20); + gcry_md_close (md); + for (i=1; i < iter; i++) + gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20); + + for (i=0; i < 20 && cur_keylen < req_keylen; i++) + keybuf[cur_keylen++] = hash[i]; + if (cur_keylen == req_keylen) + { + gcry_mpi_release (num_b1); + return 0; /* ready */ + } + + /* need more bytes. */ + for(i=0; i < 64; i++) + buf_b[i] = hash[i % 20]; + rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, 64, &n); + if (rc) + { + log_error ( "gcry_mpi_scan failed: %s\n", gpg_strerror (rc)); + return -1; + } + gcry_mpi_add_ui (num_b1, num_b1, 1); + for (i=0; i < 128; i += 64) + { + gcry_mpi_t num_ij; + + rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, 64, &n); + if (rc) + { + log_error ( "gcry_mpi_scan failed: %s\n", + gpg_strerror (rc)); + return -1; + } + gcry_mpi_add (num_ij, num_ij, num_b1); + gcry_mpi_clear_highbit (num_ij, 64*8); + rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, 64, &n, num_ij); + if (rc) + { + log_error ( "gcry_mpi_print failed: %s\n", + gpg_strerror (rc)); + return -1; + } + gcry_mpi_release (num_ij); + } + } +} + + +static int +set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw) +{ + unsigned char keybuf[24]; + int rc; + + if (string_to_key (1, salt, iter, pw, 24, keybuf)) + return -1; + rc = gcry_cipher_setkey (chd, keybuf, 24); + if (rc) + { + log_error ( "gcry_cipher_setkey failed: %s\n", gpg_strerror (rc)); + return -1; + } + + if (string_to_key (2, salt, iter, pw, 8, keybuf)) + return -1; + rc = gcry_cipher_setiv (chd, keybuf, 8); + if (rc) + { + log_error ("gcry_cipher_setiv failed: %s\n", gpg_strerror (rc)); + return -1; + } + return 0; +} + + +static void +crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, + const char *pw, int encrypt) +{ + gcry_cipher_hd_t chd; + int rc; + + rc = gcry_cipher_open (&chd, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); + if (rc) + { + log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(-1)); + return; + } + if (set_key_iv (chd, salt, iter, pw)) + goto leave; + + rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0) + : gcry_cipher_decrypt (chd, buffer, length, NULL, 0); + + if (rc) + { + log_error ( "en/de-crytion failed: %s\n", gpg_strerror (rc)); + goto leave; + } + +/* { */ +/* FILE *fp = fopen("inner.der", "wb"); */ +/* fwrite (buffer, 1, length, fp); */ +/* fclose (fp); */ +/* } */ + + leave: + gcry_cipher_close (chd); +} + + + + +static int +parse_bag_encrypted_data (const unsigned char *buffer, size_t length, + int startoffset) +{ + struct tag_info ti; + const unsigned char *p = buffer; + size_t n = length; + const char *where; + + where = "start"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_SEQUENCE) + goto bailout; + + where = "bag.encryptedData.version"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 0) + goto bailout; + p++; n--; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_SEQUENCE) + goto bailout; + + where = "bag.encryptedData.data"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data) + || memcmp (p, oid_data, DIM(oid_data))) + goto bailout; + p += DIM(oid_data); + n -= DIM(oid_data); + + /* fixme: continue parsing */ + + return 0; + bailout: + log_error ("encrptedData error at \"%s\", offset %u\n", + where, (p - buffer)+startoffset); + return -1; +} + +static gcry_mpi_t * +parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, + const char *pw) +{ + int rc; + struct tag_info ti; + const unsigned char *p = buffer; + size_t n = length; + const char *where; + char salt[8]; + unsigned int iter; + int len; + unsigned char *plain = NULL; + gcry_mpi_t *result = NULL; + int result_count, i; + + where = "start"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING) + goto bailout; + + where = "data.outerseqs"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + + where = "data.objectidentifier"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag) + || memcmp (p, oid_pkcs_12_pkcs_8ShroudedKeyBag, + DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag))) + goto bailout; + p += DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag); + n -= DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag); + + where = "shrouded,outerseqs"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC) + || memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC, + DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC))) + goto bailout; + p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC); + n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC); + + where = "3des-params"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 ) + goto bailout; + memcpy (salt, p, 8); + p += 8; + n -= 8; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_INTEGER || !ti.length ) + goto bailout; + for (iter=0; ti.length; ti.length--) + { + iter <<= 8; + iter |= (*p++) & 0xff; + n--; + } + + where = "3des-ciphertext"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length ) + goto bailout; + + log_info ("%lu bytes of 3DES encrypted text\n", ti.length); + + plain = gcry_malloc_secure (ti.length); + if (!plain) + { + log_error ("error allocating decryption buffer\n"); + goto bailout; + } + memcpy (plain, p, ti.length); + crypt_block (plain, ti.length, salt, iter, pw, 0); + n = ti.length; + startoffset = 0; + buffer = p = plain; + + where = "decrypted-text"; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER + || ti.length != 1 || *p) + goto bailout; + p++; n--; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + len = ti.length; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (len < ti.nhdr) + goto bailout; + len -= ti.nhdr; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_rsaEncryption) + || memcmp (p, oid_rsaEncryption, + DIM(oid_rsaEncryption))) + goto bailout; + p += DIM (oid_rsaEncryption); + n -= DIM (oid_rsaEncryption); + if (len < ti.length) + goto bailout; + len -= ti.length; + if (n < len) + goto bailout; + p += len; + n -= len; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_OCTET_STRING) + goto bailout; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + len = ti.length; + + result = gcry_calloc (10, sizeof *result); + if (!result) + { + log_error ( "error allocating result array\n"); + goto bailout; + } + result_count = 0; + + where = "reading.key-parameters"; + for (result_count=0; len && result_count < 9;) + { + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER) + goto bailout; + if (len < ti.nhdr) + goto bailout; + len -= ti.nhdr; + if (len < ti.length) + goto bailout; + len -= ti.length; + if (!result_count && ti.length == 1 && !*p) + ; /* ignore the very first one if it is a 0 */ + else + { + rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p, + ti.length, NULL); + if (rc) + { + log_error ("error parsing key parameter: %s\n", + gpg_strerror (rc)); + goto bailout; + } + result_count++; + } + p += ti.length; + n -= ti.length; + } + if (len) + goto bailout; + + return result; + + bailout: + gcry_free (plain); + if (result) + { + for (i=0; result[i]; i++) + gcry_mpi_release (result[i]); + gcry_free (result); + } + log_error ( "data error at \"%s\", offset %u\n", + where, (p - buffer) + startoffset); + return NULL; +} + + +/* Parse a PKCS12 object and return an array of MPI representing the + secret key parameters. This is a very limited inplementation in + that it is only able to look for 3DES encoded enctyptedData and + tries to extract the first private key object it finds. In case of + an error NULL is returned. */ +gcry_mpi_t * +p12_parse (const unsigned char *buffer, size_t length, const char *pw) +{ + struct tag_info ti; + const unsigned char *p = buffer; + size_t n = length; + const char *where; + int bagseqlength, len; + + where = "pfx"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_SEQUENCE) + goto bailout; + + where = "pfxVersion"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 3) + goto bailout; + p++; n--; + + where = "authSave"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data) + || memcmp (p, oid_data, DIM(oid_data))) + goto bailout; + p += DIM(oid_data); + n -= DIM(oid_data); + + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING) + goto bailout; + + where = "bags"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE) + goto bailout; + bagseqlength = ti.length; + while (bagseqlength) + { + /*log_debug ( "at offset %u\n", (p - buffer));*/ + where = "bag-sequence"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE) + goto bailout; + + if (bagseqlength < ti.nhdr) + goto bailout; + bagseqlength -= ti.nhdr; + if (bagseqlength < ti.length) + goto bailout; + bagseqlength -= ti.length; + len = ti.length; + + if (parse_tag (&p, &n, &ti)) + goto bailout; + len -= ti.nhdr; + if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData) + && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData))) + { + p += DIM(oid_encryptedData); + n -= DIM(oid_encryptedData); + len -= DIM(oid_encryptedData); + where = "bag.encryptedData"; + if (parse_bag_encrypted_data (p, n, (p - buffer))) + goto bailout; + } + else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data) + && !memcmp (p, oid_data, DIM(oid_data))) + { + p += DIM(oid_data); + n -= DIM(oid_data); + len -= DIM(oid_data); + return parse_bag_data (p, n, (p-buffer), pw); + } + else + log_info ( "unknown bag type - skipped\n"); + + if (len < 0 || len > n) + goto bailout; + p += len; + n -= len; + } + + return NULL; + bailout: + log_error ("error at \"%s\", offset %u\n", where, (p - buffer)); + return NULL; +} + + + +static size_t +compute_tag_length (size_t n) +{ + int needed = 0; + + if (n < 128) + needed += 2; /* tag and one length byte */ + else if (n < 256) + needed += 3; /* tag, number of length bytes, 1 length byte */ + else if (n < 65536) + needed += 4; /* tag, number of length bytes, 2 length bytes */ + else + { + log_error ("object too larger to encode\n"); + return 0; + } + return needed; +} + +static unsigned char * +store_tag_length (unsigned char *p, int tag, size_t n) +{ + if (tag == TAG_SEQUENCE) + tag |= 0x20; /* constructed */ + + *p++ = tag; + if (n < 128) + *p++ = n; + else if (n < 256) + { + *p++ = 0x81; + *p++ = n; + } + else if (n < 65536) + { + *p++ = 0x82; + *p++ = n >> 8; + *p++ = n; + } + + return p; +} + + +/* Create the final PKCS-12 object from the sequences contained in + SEQLIST. That array is terminated with an NULL object */ +static unsigned char * +create_final (struct buffer_s *sequences, size_t *r_length) +{ + int i; + size_t needed = 0; + size_t n, outseqlen, notsooutseqlen, out0taglen, octstrlen, inseqlen; + unsigned char *result, *p; + size_t resultlen; + + for (i=0; sequences[i].buffer; i++) + needed += sequences[i].length; + /* This goes into a sequences. */ + inseqlen = needed; + n = compute_tag_length (needed); + needed += n; + /* And encapsulate all in an octet string. */ + octstrlen = needed; + n = compute_tag_length (needed); + needed += n; + /* And tag it with [0]. */ + out0taglen = needed; + n = compute_tag_length (needed); + needed += n; + /* Prepend an data OID. */ + needed += 2 + DIM (oid_data); + /* This all into a sequences. */ + notsooutseqlen = needed; + n = compute_tag_length (needed); + needed += n; + /* Prepend the version integer 3. */ + needed += 3; + /* And the final sequence. */ + outseqlen = needed; + n = compute_tag_length (needed); + needed += n; + + result = gcry_malloc (needed); + if (!result) + { + log_error ("error allocating buffer\n"); + return NULL; + } + p = result; + + /* Store the very outer sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, outseqlen); + /* Store the version integer 3. */ + *p++ = TAG_INTEGER; + *p++ = 1; + *p++ = 3; + /* Store another sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, notsooutseqlen); + /* Store the data OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); + memcpy (p, oid_data, DIM (oid_data)); + p += DIM (oid_data); + /* Next comes a context tag. */ + p = store_tag_length (p, 0xa0, out0taglen); + /* And an octet string. */ + p = store_tag_length (p, TAG_OCTET_STRING, octstrlen); + /* And the inner sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, inseqlen); + /* And append all the buffers. */ + for (i=0; sequences[i].buffer; i++) + { + memcpy (p, sequences[i].buffer, sequences[i].length); + p += sequences[i].length; + } + + /* Ready. */ + resultlen = p - result; + if (needed != resultlen) + log_debug ("length mismatch: %u, %u\n", needed, resultlen); + + *r_length = resultlen; + return result; +} + + +/* Expect the RSA key parameters in KPARMS and a password in + PW. Create a PKCS structure from it and return it as well as the + length in R_LENGTH; return NULL in case of an error. */ +unsigned char * +p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length) +{ + int rc, i; + size_t needed, n; + unsigned char *plain, *p, *cipher; + size_t plainlen, cipherlen; + size_t outseqlen, oidseqlen, octstrlen, inseqlen; + size_t out0taglen, in0taglen, outoctstrlen; + size_t aseq1len, aseq2len, aseq3len; + char salt[8]; + + needed = 3; /* The version(?) integer of value 0. */ + for (i=0; kparms[i]; i++) + { + n = 0; + rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]); + if (rc) + { + log_error ("error formatting parameter: %s\n", gpg_strerror (rc)); + return NULL; + } + needed += n; + n = compute_tag_length (n); + if (!n) + return NULL; + needed += n; + } + if (i != 8) + { + log_error ("invalid paramters for p12_build\n"); + return NULL; + } + /* Now this all goes into a sequence. */ + inseqlen = needed; + n = compute_tag_length (needed); + if (!n) + return NULL; + needed += n; + /* Encapsulate all into an octet string. */ + octstrlen = needed; + n = compute_tag_length (needed); + if (!n) + return NULL; + needed += n; + /* Prepend the object identifier sequence. */ + oidseqlen = 2 + DIM (oid_rsaEncryption) + 2; + needed += 2 + oidseqlen; + /* The version number. */ + needed += 3; + /* And finally put the whole thing into a sequence. */ + outseqlen = needed; + n = compute_tag_length (needed); + if (!n) + return NULL; + needed += n; + + /* allocate 8 extra bytes for padding */ + plain = gcry_malloc_secure (needed+8); + if (!plain) + { + log_error ("error allocating encryption buffer\n"); + return NULL; + } + + /* And now fill the plaintext buffer. */ + p = plain; + p = store_tag_length (p, TAG_SEQUENCE, outseqlen); + /* Store version. */ + *p++ = TAG_INTEGER; + *p++ = 1; + *p++ = 0; + /* Store object identifier sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, oidseqlen); + p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption)); + memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption)); + p += DIM (oid_rsaEncryption); + *p++ = TAG_NULL; + *p++ = 0; + /* Start with the octet string. */ + p = store_tag_length (p, TAG_OCTET_STRING, octstrlen); + p = store_tag_length (p, TAG_SEQUENCE, inseqlen); + /* Store the key parameters. */ + *p++ = TAG_INTEGER; + *p++ = 1; + *p++ = 0; + for (i=0; kparms[i]; i++) + { + n = 0; + rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]); + if (rc) + { + log_error ("oops: error formatting parameter: %s\n", + gpg_strerror (rc)); + gcry_free (plain); + return NULL; + } + p = store_tag_length (p, TAG_INTEGER, n); + + n = plain + needed - p; + rc = gcry_mpi_print (GCRYMPI_FMT_STD, p, n, &n, kparms[i]); + if (rc) + { + log_error ("oops: error storing parameter: %s\n", + gpg_strerror (rc)); + gcry_free (plain); + return NULL; + } + p += n; + } + + plainlen = p - plain; + assert (needed == plainlen); + /* Append some pad characters; we already allocated extra space. */ + n = 8 - plainlen % 8; + for (;(plainlen % 8); plainlen++) + *p++ = n; + + { + FILE *fp = fopen("inner-out.der", "wb"); + fwrite (plain, 1, plainlen, fp); + fclose (fp); + } + + + /* Encrypt it and prepend a lot of stupid things. */ + gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); + crypt_block (plain, plainlen, salt, 1024, pw, 1); + /* the data goes into an octet string. */ + needed = compute_tag_length (plainlen); + needed += plainlen; + /* we prepend the the algorithm identifier (we use a pre-encoded one)*/ + needed += DIM (data_3desiter1024); + /* we put a sequence around. */ + aseq3len = needed; + needed += compute_tag_length (needed); + /* Prepend it with a [0] tag. */ + in0taglen = needed; + needed += compute_tag_length (needed); + /* Prepend that shroudedKeyBag OID. */ + needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); + /* Put it all into two sequence. */ + aseq2len = needed; + needed += compute_tag_length ( needed); + aseq1len = needed; + needed += compute_tag_length (needed); + /* This all goes into an octet string. */ + outoctstrlen = needed; + needed += compute_tag_length (needed); + /* Prepend it with a [0] tag. */ + out0taglen = needed; + needed += compute_tag_length (needed); + /* Prepend the data OID. */ + needed += 2 + DIM (oid_data); + /* And a sequence. */ + outseqlen = needed; + needed += compute_tag_length (needed); + + cipher = gcry_malloc (needed); + if (!cipher) + { + log_error ("error allocating buffer\n"); + gcry_free (plain); + return NULL; + } + p = cipher; + /* Store the first sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, outseqlen); + /* Store the data OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); + memcpy (p, oid_data, DIM (oid_data)); + p += DIM (oid_data); + /* Next comes a context tag. */ + p = store_tag_length (p, 0xa0, out0taglen); + /* And an octet string. */ + p = store_tag_length (p, TAG_OCTET_STRING, outoctstrlen); + /* Two sequences. */ + p = store_tag_length (p, TAG_SEQUENCE, aseq1len); + p = store_tag_length (p, TAG_SEQUENCE, aseq2len); + /* Store the shroudedKeyBag OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); + memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag, + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); + p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); + /* Next comes a context tag. */ + p = store_tag_length (p, 0xa0, in0taglen); + /* And a sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, aseq3len); + /* Now for the pre-encoded algorithm indentifier and the salt. */ + memcpy (p, data_3desiter1024, DIM (data_3desiter1024)); + memcpy (p + DATA_3DESITER1024_SALT_OFF, salt, 8); + p += DIM (data_3desiter1024); + /* And finally the octet string with the encrypted data. */ + p = store_tag_length (p, TAG_OCTET_STRING, plainlen); + memcpy (p, plain, plainlen); + p += plainlen; + cipherlen = p - cipher; + + if (needed != cipherlen) + log_debug ("length mismatch: %u, %u\n", needed, cipherlen); + gcry_free (plain); + + { + struct buffer_s seqlist[2]; + + seqlist[0].buffer = cipher; + seqlist[0].length = cipherlen; + seqlist[1].buffer = NULL; + seqlist[1].length = 0; + + cipher = create_final (seqlist, &cipherlen); + gcry_free (seqlist[0].buffer); + } + + *r_length = cipherlen; + return cipher; +} + + +#ifdef TEST +int +main (int argc, char **argv) +{ + FILE *fp; + struct stat st; + char *buf; + size_t buflen; + GcryMPI *result; + + if (argc != 3) + { + fprintf (stderr, "usage: testp12 file passphrase\n"); + return 1; + } + + gcry_control (GCRYCTL_DISABLE_SECMEM, NULL); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL); + + fp = fopen (argv[1], "rb"); + if (!fp) + { + fprintf (stderr, "can't open `%s': %s\n", argv[1], strerror (errno)); + return 1; + } + + if (fstat (fileno(fp), &st)) + { + fprintf (stderr, "can't stat `%s': %s\n", argv[1], strerror (errno)); + return 1; + } + + buflen = st.st_size; + buf = gcry_malloc (buflen+1); + if (!buf || fread (buf, buflen, 1, fp) != 1) + { + fprintf (stderr, "error reading `%s': %s\n", argv[1], strerror (errno)); + return 1; + } + fclose (fp); + + result = p12_parse (buf, buflen, argv[2]); + if (result) + { + int i, rc; + char *buf; + + for (i=0; result[i]; i++) + { + rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, + NULL, result[i]); + if (rc) + printf ("%d: [error printing number: %s]\n", + i, gpg_strerror (rc)); + else + { + printf ("%d: %s\n", i, buf); + gcry_free (buf); + } + } + } + + return 0; + +} +#endif /* TEST */ diff --git a/agent/minip12.h b/agent/minip12.h new file mode 100644 index 000000000..122215549 --- /dev/null +++ b/agent/minip12.h @@ -0,0 +1,33 @@ +/* minip12.h - Global definitions for the minimal pkcs-12 implementation. + * 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 MINIP12_H +#define MINIP12_H + +#include <gcrypt.h> + +gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length, + const char *pw); + +unsigned char *p12_build (gcry_mpi_t *kparms, const char *pw, + size_t *r_length); + + +#endif /*MINIP12_H*/ diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c new file mode 100644 index 000000000..543a82737 --- /dev/null +++ b/agent/pkdecrypt.c @@ -0,0 +1,138 @@ +/* pkdecrypt.c - public key decryption (well, acually using a secret key) + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" + + +/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp. + Try to get the key from CTRL and write the decoded stuff back to + OUTFP. */ +int +agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, + FILE *outfp) +{ + gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL; + unsigned char *shadow_info = NULL; + int rc; + char *buf = NULL; + size_t len; + + if (!ctrl->have_keygrip) + { + log_error ("speculative decryption not yet supported\n"); + rc = gpg_error (GPG_ERR_NO_SECKEY); + goto leave; + } + + rc = gcry_sexp_sscan (&s_cipher, NULL, ciphertext, ciphertextlen); + if (rc) + { + log_error ("failed to convert ciphertext: %s\n", gpg_strerror (rc)); + rc = gpg_error (GPG_ERR_INV_DATA); + goto leave; + } + + if (DBG_CRYPTO) + { + log_printhex ("keygrip:", ctrl->keygrip, 20); + log_printhex ("cipher: ", ciphertext, ciphertextlen); + } + s_skey = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0); + if (!s_skey && !shadow_info) + { + log_error ("failed to read the secret key\n"); + rc = gpg_error (GPG_ERR_NO_SECKEY); + goto leave; + } + + if (!s_skey) + { /* divert operation to the smartcard */ + + if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL)) + { + rc = gpg_error (GPG_ERR_INV_SEXP); + goto leave; + } + + rc = divert_pkdecrypt (ctrl, ciphertext, shadow_info, &buf, &len ); + if (rc) + { + log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc)); + goto leave; + } + /* FIXME: don't use buffering and change the protocol to return + a complete S-expression and not just a part. */ + fprintf (outfp, "%u:", (unsigned int)len); + fwrite (buf, 1, len, outfp); + putc (0, outfp); + } + else + { /* no smartcard, but a private key */ + if (DBG_CRYPTO) + { + log_debug ("skey: "); + gcry_sexp_dump (s_skey); + } + + rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey); + if (rc) + { + log_error ("decryption failed: %s\n", gpg_strerror (rc)); + rc = map_gcry_err (rc); + goto leave; + } + + if (DBG_CRYPTO) + { + log_debug ("plain: "); + gcry_sexp_dump (s_plain); + } + len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xmalloc (len); + len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + /* FIXME: we must make sure that no buffering takes place or we are + in full control of the buffer memory (easy to do) - should go + into assuan. */ + fwrite (buf, 1, len, outfp); + } + + + leave: + gcry_sexp_release (s_skey); + gcry_sexp_release (s_plain); + gcry_sexp_release (s_cipher); + xfree (buf); + xfree (shadow_info); + return rc; +} + + diff --git a/agent/pksign.c b/agent/pksign.c new file mode 100644 index 000000000..fba2c652c --- /dev/null +++ b/agent/pksign.c @@ -0,0 +1,185 @@ +/* pksign.c - public key signing (well, acually using a secret key) + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" + + +static int +do_encode_md (const unsigned char *digest, size_t digestlen, int algo, + unsigned int nbits, gcry_mpi_t *r_val) +{ + int nframe = (nbits+7) / 8; + byte *frame; + int i, n; + byte asn[100]; + size_t asnlen; + + asnlen = DIM(asn); + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + log_error ("no object identifier for algo %d\n", algo); + return gpg_error (GPG_ERR_INTERNAL); + } + + if (digestlen + asnlen + 4 > nframe ) + { + log_error ("can't encode a %d bit MD into a %d bits frame\n", + (int)(digestlen*8), (int)nbits); + return gpg_error (GPG_ERR_INTERNAL); + } + + /* We encode the MD in this way: + * + * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) + * + * PAD consists of FF bytes. + */ + frame = xtrymalloc (nframe); + if (!frame) + return out_of_core (); + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - digestlen - asnlen -3 ; + assert ( i > 1 ); + memset ( frame+n, 0xff, i ); n += i; + frame[n++] = 0; + memcpy ( frame+n, asn, asnlen ); n += asnlen; + memcpy ( frame+n, digest, digestlen ); n += digestlen; + assert ( n == nframe ); + if (DBG_CRYPTO) + log_printhex ("encoded hash:", frame, nframe); + + gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe); + xfree (frame); + return 0; +} + + +/* SIGN whatever information we have accumulated in CTRL and write it + back to OUTFP. */ +int +agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) +{ + gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL; + gcry_mpi_t frame = NULL; + unsigned char *shadow_info = NULL; + int rc; + char *buf = NULL; + size_t len; + + if (!ctrl->have_keygrip) + return gpg_error (GPG_ERR_NO_SECKEY); + + s_skey = agent_key_from_file (ctrl, + ctrl->keygrip, &shadow_info, ignore_cache); + if (!s_skey && !shadow_info) + { + log_error ("failed to read the secret key\n"); + rc = gpg_error (GPG_ERR_NO_SECKEY); + goto leave; + } + + if (!s_skey) + { /* divert operation to the smartcard */ + unsigned char *sigbuf; + + rc = divert_pksign (ctrl, + ctrl->digest.value, + ctrl->digest.valuelen, + ctrl->digest.algo, + shadow_info, &sigbuf); + if (rc) + { + log_error ("smartcard signing failed: %s\n", gpg_strerror (rc)); + goto leave; + } + len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL); + assert (len); + buf = sigbuf; + } + else + { /* no smartcard, but a private key */ + + /* put the hash into a sexp */ + rc = do_encode_md (ctrl->digest.value, + ctrl->digest.valuelen, + ctrl->digest.algo, + gcry_pk_get_nbits (s_skey), + &frame); + if (rc) + goto leave; + if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) + BUG (); + + if (DBG_CRYPTO) + { + log_debug ("skey: "); + gcry_sexp_dump (s_skey); + } + + /* sign */ + rc = gcry_pk_sign (&s_sig, s_hash, s_skey); + if (rc) + { + log_error ("signing failed: %s\n", gpg_strerror (rc)); + rc = map_gcry_err (rc); + goto leave; + } + + if (DBG_CRYPTO) + { + log_debug ("result: "); + gcry_sexp_dump (s_sig); + } + + len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xmalloc (len); + len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + } + + /* FIXME: we must make sure that no buffering takes place or we are + in full control of the buffer memory (easy to do) - should go + into assuan. */ + fwrite (buf, 1, len, outfp); + + leave: + gcry_sexp_release (s_skey); + gcry_sexp_release (s_hash); + gcry_sexp_release (s_sig); + gcry_mpi_release (frame); + xfree (buf); + xfree (shadow_info); + return rc; +} + + diff --git a/agent/protect-tool.c b/agent/protect-tool.c new file mode 100644 index 000000000..e518c5672 --- /dev/null +++ b/agent/protect-tool.c @@ -0,0 +1,977 @@ +/* protect-tool.c - A tool to test the secret key protection + * 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 + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <sys/stat.h> +#include <unistd.h> + +#define JNLIB_NEED_LOG_LOGV +#include "agent.h" +#include "minip12.h" +#include "simple-pwquery.h" +#include "i18n.h" + +enum cmd_and_opt_values +{ aNull = 0, + oVerbose = 'v', + oArmor = 'a', + oPassphrase = 'P', + + oProtect = 'p', + oUnprotect = 'u', + + oNoVerbose = 500, + oShadow, + oShowShadowInfo, + oShowKeygrip, + + oP12Import, + oP12Export, + oStore, + oForce, + +aTest }; + +struct rsa_secret_key_s + { + gcry_mpi_t n; /* public modulus */ + gcry_mpi_t e; /* public exponent */ + gcry_mpi_t d; /* exponent */ + gcry_mpi_t p; /* prime p. */ + gcry_mpi_t q; /* prime q. */ + gcry_mpi_t u; /* inverse of p mod q. */ + }; + + +static int opt_armor; +static int opt_store; +static int opt_force; +static const char *passphrase; + +static const char *get_passphrase (void); +static int store_private_key (const unsigned char *grip, + const void *buffer, size_t length, int force); + + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oVerbose, "verbose", 0, "verbose" }, + { oArmor, "armor", 0, "write output in advanced format" }, + { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, + { oProtect, "protect", 256, "protect a private key"}, + { oUnprotect, "unprotect", 256, "unprotect a private key"}, + { oShadow, "shadow", 256, "create a shadow entry for a priblic key"}, + { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"}, + { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""}, + + { oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"}, + { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"}, + { oStore, "store", 0, "store the created key in the appropriate place"}, + { oForce, "force", 0, "force overwriting"}, + {0} +}; + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "gpg-protect-tool (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n"); + break; + case 41: p = _("Syntax: gpg-protect-tool [options] [args]]\n" + "Secret key maintenance tool\n"); + break; + + default: p = NULL; + } + return p; +} + + + +static void +i18n_init (void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE ); +#else +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif +#endif +} + + + +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* translate the log levels */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; } + log_logv (level, fmt, arg_ptr); +} + + +/* static void */ +/* print_mpi (const char *text, gcry_mpi_t a) */ +/* { */ +/* char *buf; */ +/* void *bufaddr = &buf; */ +/* int rc; */ + +/* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */ +/* if (rc) */ +/* log_info ("%s: [error printing number: %s]\n", text, gpg_strerror (rc)); */ +/* else */ +/* { */ +/* log_info ("%s: %s\n", text, buf); */ +/* gcry_free (buf); */ +/* } */ +/* } */ + + + +static unsigned char * +make_canonical (const char *fname, const char *buf, size_t buflen) +{ + int rc; + size_t erroff, len; + gcry_sexp_t sexp; + unsigned char *result; + + rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); + if (rc) + { + log_error ("invalid S-Expression in `%s' (off=%u): %s\n", + fname, (unsigned int)erroff, gpg_strerror (rc)); + return NULL; + } + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + result = xmalloc (len); + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len); + assert (len); + gcry_sexp_release (sexp); + return result; +} + +static char * +make_advanced (const unsigned char *buf, size_t buflen) +{ + int rc; + size_t erroff, len; + gcry_sexp_t sexp; + unsigned char *result; + + rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); + if (rc) + { + log_error ("invalid canonical S-Expression (off=%u): %s\n", + (unsigned int)erroff, gpg_strerror (rc)); + return NULL; + } + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); + assert (len); + result = xmalloc (len); + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len); + assert (len); + gcry_sexp_release (sexp); + return result; +} + + +static char * +read_file (const char *fname, size_t *r_length) +{ + FILE *fp; + struct stat st; + char *buf; + size_t buflen; + + fp = fopen (fname, "rb"); + if (!fp) + { + log_error ("can't open `%s': %s\n", fname, strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + log_error ("can't stat `%s': %s\n", fname, strerror (errno)); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + log_error ("error reading `%s': %s\n", fname, strerror (errno)); + fclose (fp); + xfree (buf); + return NULL; + } + fclose (fp); + + *r_length = buflen; + return buf; +} + + +static unsigned char * +read_key (const char *fname) +{ + char *buf; + size_t buflen; + unsigned char *key; + + buf = read_file (fname, &buflen); + if (!buf) + return NULL; + key = make_canonical (fname, buf, buflen); + xfree (buf); + return key; +} + + + +static void +read_and_protect (const char *fname) +{ + int rc; + unsigned char *key; + unsigned char *result; + size_t resultlen; + + key = read_key (fname); + if (!key) + return; + + rc = agent_protect (key, get_passphrase (), &result, &resultlen); + xfree (key); + if (rc) + { + log_error ("protecting the key failed: %s\n", gpg_strerror (rc)); + return; + } + + if (opt_armor) + { + char *p = make_advanced (result, resultlen); + xfree (result); + if (!p) + return; + result = p; + resultlen = strlen (p); + } + + fwrite (result, resultlen, 1, stdout); + xfree (result); +} + + +static void +read_and_unprotect (const char *fname) +{ + int rc; + unsigned char *key; + unsigned char *result; + size_t resultlen; + + key = read_key (fname); + if (!key) + return; + + rc = agent_unprotect (key, get_passphrase (), &result, &resultlen); + xfree (key); + if (rc) + { + log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc)); + return; + } + + if (opt_armor) + { + char *p = make_advanced (result, resultlen); + xfree (result); + if (!p) + return; + result = p; + resultlen = strlen (p); + } + + fwrite (result, resultlen, 1, stdout); + xfree (result); +} + + + +static void +read_and_shadow (const char *fname) +{ + int rc; + unsigned char *key; + unsigned char *result; + size_t resultlen; + + key = read_key (fname); + if (!key) + return; + + rc = agent_shadow_key (key, "(8:313233342:43)", &result); + xfree (key); + if (rc) + { + log_error ("shadowing the key failed: %s\n", gpg_strerror (rc)); + return; + } + resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL); + assert (resultlen); + + if (opt_armor) + { + char *p = make_advanced (result, resultlen); + xfree (result); + if (!p) + return; + result = p; + resultlen = strlen (p); + } + + fwrite (result, resultlen, 1, stdout); + xfree (result); +} + +static void +show_shadow_info (const char *fname) +{ + int rc; + unsigned char *key; + const unsigned char *info; + size_t infolen; + + key = read_key (fname); + if (!key) + return; + + rc = agent_get_shadow_info (key, &info); + xfree (key); + if (rc) + { + log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc)); + return; + } + infolen = gcry_sexp_canon_len (info, 0, NULL,NULL); + assert (infolen); + + if (opt_armor) + { + char *p = make_advanced (info, infolen); + if (!p) + return; + fwrite (p, strlen (p), 1, stdout); + xfree (p); + } + else + fwrite (info, infolen, 1, stdout); +} + + +static void +show_file (const char *fname) +{ + unsigned char *key; + size_t keylen; + char *p; + + key = read_key (fname); + if (!key) + return; + + keylen = gcry_sexp_canon_len (key, 0, NULL,NULL); + assert (keylen); + + p = make_advanced (key, keylen); + xfree (key); + if (p) + { + fwrite (p, strlen (p), 1, stdout); + xfree (p); + } +} + +static void +show_keygrip (const char *fname) +{ + unsigned char *key; + gcry_sexp_t private; + unsigned char grip[20]; + int i; + + key = read_key (fname); + if (!key) + return; + + if (gcry_sexp_new (&private, key, 0, 0)) + { + log_error ("gcry_sexp_new failed\n"); + return; + } + xfree (key); + + if (!gcry_pk_get_keygrip (private, grip)) + { + log_error ("can't calculate keygrip\n"); + return; + } + gcry_sexp_release (private); + + for (i=0; i < 20; i++) + printf ("%02X", grip[i]); + putchar ('\n'); +} + + +static int +rsa_key_check (struct rsa_secret_key_s *skey) +{ + int err = 0; + gcry_mpi_t t = gcry_mpi_snew (0); + gcry_mpi_t t1 = gcry_mpi_snew (0); + gcry_mpi_t t2 = gcry_mpi_snew (0); + gcry_mpi_t phi = gcry_mpi_snew (0); + + /* check that n == p * q */ + gcry_mpi_mul (t, skey->p, skey->q); + if (gcry_mpi_cmp( t, skey->n) ) + { + log_error ("RSA oops: n != p * q\n"); + err++; + } + + /* check that p is less than q */ + if (gcry_mpi_cmp (skey->p, skey->q) > 0) + { + gcry_mpi_t tmp; + + log_info ("swapping secret primes\n"); + tmp = gcry_mpi_copy (skey->p); + gcry_mpi_set (skey->p, skey->q); + gcry_mpi_set (skey->q, tmp); + gcry_mpi_release (tmp); + /* and must recompute u of course */ + gcry_mpi_invm (skey->u, skey->p, skey->q); + } + + /* check that e divides neither p-1 nor q-1 */ + gcry_mpi_sub_ui (t, skey->p, 1 ); + gcry_mpi_div (NULL, t, t, skey->e, 0); + if (!gcry_mpi_cmp_ui( t, 0) ) + { + log_error ("RSA oops: e divides p-1\n"); + err++; + } + gcry_mpi_sub_ui (t, skey->q, 1); + gcry_mpi_div (NULL, t, t, skey->e, 0); + if (!gcry_mpi_cmp_ui( t, 0)) + { + log_info ( "RSA oops: e divides q-1\n" ); + err++; + } + + /* check that d is correct. */ + gcry_mpi_sub_ui (t1, skey->p, 1); + gcry_mpi_sub_ui (t2, skey->q, 1); + gcry_mpi_mul (phi, t1, t2); + gcry_mpi_invm (t, skey->e, phi); + if (gcry_mpi_cmp (t, skey->d)) + { /* no: try universal exponent. */ + gcry_mpi_gcd (t, t1, t2); + gcry_mpi_div (t, NULL, phi, t, 0); + gcry_mpi_invm (t, skey->e, t); + if (gcry_mpi_cmp (t, skey->d)) + { + log_error ("RSA oops: bad secret exponent\n"); + err++; + } + } + + /* check for correctness of u */ + gcry_mpi_invm (t, skey->p, skey->q); + if (gcry_mpi_cmp (t, skey->u)) + { + log_info ( "RSA oops: bad u parameter\n"); + err++; + } + + if (err) + log_info ("RSA secret key check failed\n"); + + gcry_mpi_release (t); + gcry_mpi_release (t1); + gcry_mpi_release (t2); + gcry_mpi_release (phi); + + return err? -1:0; +} + + +static void +import_p12_file (const char *fname) +{ + char *buf; + unsigned char *result; + size_t buflen, resultlen; + int i; + int rc; + gcry_mpi_t *kparms; + struct rsa_secret_key_s sk; + gcry_sexp_t s_key; + unsigned char *key; + unsigned char grip[20]; + + /* fixme: we should release some stuff on error */ + + buf = read_file (fname, &buflen); + if (!buf) + return; + + kparms = p12_parse (buf, buflen, get_passphrase ()); + xfree (buf); + if (!kparms) + { + log_error ("error parsing or decrypting the PKCS-1 file\n"); + return; + } + for (i=0; kparms[i]; i++) + ; + if (i != 8) + { + log_error ("invalid structure of private key\n"); + return; + } + + +/* print_mpi (" n", kparms[0]); */ +/* print_mpi (" e", kparms[1]); */ +/* print_mpi (" d", kparms[2]); */ +/* print_mpi (" p", kparms[3]); */ +/* print_mpi (" q", kparms[4]); */ +/* print_mpi ("dmp1", kparms[5]); */ +/* print_mpi ("dmq1", kparms[6]); */ +/* print_mpi (" u", kparms[7]); */ + + sk.n = kparms[0]; + sk.e = kparms[1]; + sk.d = kparms[2]; + sk.q = kparms[3]; + sk.p = kparms[4]; + sk.u = kparms[7]; + if (rsa_key_check (&sk)) + return; +/* print_mpi (" n", sk.n); */ +/* print_mpi (" e", sk.e); */ +/* print_mpi (" d", sk.d); */ +/* print_mpi (" p", sk.p); */ +/* print_mpi (" q", sk.q); */ +/* print_mpi (" u", sk.u); */ + + /* Create an S-expresion from the parameters. */ + rc = gcry_sexp_build (&s_key, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL); + for (i=0; i < 8; i++) + gcry_mpi_release (kparms[i]); + gcry_free (kparms); + if (rc) + { + log_error ("failed to created S-expression from key: %s\n", + gpg_strerror (rc)); + return; + } + + /* Compute the keygrip. */ + if (!gcry_pk_get_keygrip (s_key, grip)) + { + log_error ("can't calculate keygrip\n"); + return; + } + log_info ("keygrip: "); + for (i=0; i < 20; i++) + log_printf ("%02X", grip[i]); + log_printf ("\n"); + + /* convert to canonical encoding */ + buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, NULL, 0); + assert (buflen); + key = gcry_xmalloc_secure (buflen); + buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, key, buflen); + assert (buflen); + gcry_sexp_release (s_key); + + + rc = agent_protect (key, get_passphrase (), &result, &resultlen); + xfree (key); + if (rc) + { + log_error ("protecting the key failed: %s\n", gpg_strerror (rc)); + return; + } + + if (opt_armor) + { + char *p = make_advanced (result, resultlen); + xfree (result); + if (!p) + return; + result = p; + resultlen = strlen (p); + } + + if (opt_store) + store_private_key (grip, result, resultlen, opt_force); + else + fwrite (result, resultlen, 1, stdout); + + xfree (result); +} + + + +static gcry_mpi_t * +sexp_to_kparms (gcry_sexp_t sexp) +{ + gcry_sexp_t list, l2; + const char *name; + const char *s; + size_t n; + int i, idx; + const char *elems; + gcry_mpi_t *array; + + list = gcry_sexp_find_token (sexp, "private-key", 0 ); + if(!list) + return NULL; + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + name = gcry_sexp_nth_data (list, 0, &n); + if(!name || n != 3 || memcmp (name, "rsa", 3)) + { + gcry_sexp_release (list); + return NULL; + } + + /* Parameter names used with RSA. */ + elems = "nedpqu"; + array = xcalloc (strlen(elems) + 1, sizeof *array); + for (idx=0, s=elems; *s; s++, idx++ ) + { + l2 = gcry_sexp_find_token (list, s, 1); + if (!l2) + { + for (i=0; i<idx; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (list); + return NULL; /* required parameter not found */ + } + array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + if (!array[idx]) + { + for (i=0; i<idx; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (list); + return NULL; /* required parameter is invalid */ + } + } + + gcry_sexp_release (list); + return array; +} + + + + +static void +export_p12_file (const char *fname) +{ + gcry_mpi_t kparms[9], *kp; + unsigned char *key; + size_t keylen; + gcry_sexp_t private; + struct rsa_secret_key_s sk; + int i; + + key = read_key (fname); + if (!key) + return; + + if (gcry_sexp_new (&private, key, 0, 0)) + { + log_error ("gcry_sexp_new failed\n"); + return; + } + xfree (key); + + kp = sexp_to_kparms (private); + gcry_sexp_release (private); + if (!kp) + { + log_error ("error converting key parameters\n"); + return; + } + sk.n = kp[0]; + sk.e = kp[1]; + sk.d = kp[2]; + sk.p = kp[3]; + sk.q = kp[4]; + sk.u = kp[5]; + xfree (kp); + + + kparms[0] = sk.n; + kparms[1] = sk.e; + kparms[2] = sk.d; + kparms[3] = sk.q; + kparms[4] = sk.p; + kparms[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */ + gcry_mpi_sub_ui (kparms[5], kparms[3], 1); + gcry_mpi_mod (kparms[5], sk.d, kparms[5]); + kparms[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */ + gcry_mpi_sub_ui (kparms[6], kparms[4], 1); + gcry_mpi_mod (kparms[6], sk.d, kparms[6]); + kparms[7] = sk.u; + kparms[8] = NULL; + + key = p12_build (kparms, get_passphrase (), &keylen); + for (i=0; i < 8; i++) + gcry_mpi_release (kparms[i]); + if (!key) + return; + + fwrite (key, keylen, 1, stdout); + xfree (key); +} + + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + int cmd = 0; + + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + log_set_prefix ("gpg-protect-tool", 1); + i18n_init (); + + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + gcry_set_log_handler (my_gcry_logger, NULL); + + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + while (arg_parse (&pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: opt.verbose++; break; + case oArmor: opt_armor=1; break; + + case oProtect: cmd = oProtect; break; + case oUnprotect: cmd = oUnprotect; break; + case oShadow: cmd = oShadow; break; + case oShowShadowInfo: cmd = oShowShadowInfo; break; + case oShowKeygrip: cmd = oShowKeygrip; break; + case oP12Import: cmd = oP12Import; break; + case oP12Export: cmd = oP12Export; break; + + case oPassphrase: passphrase = pargs.r.ret_str; break; + case oStore: opt_store = 1; break; + case oForce: opt_force = 1; break; + + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit(2); + + if (argc != 1) + usage (1); + + if (cmd == oProtect) + read_and_protect (*argv); + else if (cmd == oUnprotect) + read_and_unprotect (*argv); + else if (cmd == oShadow) + read_and_shadow (*argv); + else if (cmd == oShowShadowInfo) + show_shadow_info (*argv); + else if (cmd == oShowKeygrip) + show_keygrip (*argv); + else if (cmd == oP12Import) + import_p12_file (*argv); + else if (cmd == oP12Export) + export_p12_file (*argv); + else + show_file (*argv); + + agent_exit (0); + return 8; /*NOTREACHED*/ +} + +void +agent_exit (int rc) +{ + rc = rc? rc : log_get_errorcount(0)? 2 : 0; + exit (rc); +} + + +/* Return the passphrase string and ask the agent if it has not been + set from the command line. */ +static const char * +get_passphrase (void) +{ + char *pw; + int err; + + if (passphrase) + return passphrase; + + pw = simple_pwquery (NULL,NULL, + _("Enter passphrase:"), + _("Please enter the passphrase or the PIN\n" + "needed to complete this operation."), + &err); + if (!pw) + { + if (err) + log_error ("error while asking for the passphrase\n"); + else + log_info ("cancelled\n"); + agent_exit (0); + } + passphrase = pw; + return passphrase; +} + + +static int +store_private_key (const unsigned char *grip, + const void *buffer, size_t length, int force) +{ + int i; + const char *homedir; + char *fname; + FILE *fp; + char hexgrip[40+4+1]; + + for (i=0; i < 20; i++) + sprintf (hexgrip+2*i, "%02X", grip[i]); + strcpy (hexgrip+40, ".key"); + + homedir = getenv("GNUPGHOME"); + if (!homedir || !*homedir) + homedir = GNUPG_DEFAULT_HOMEDIR; + + fname = make_filename (homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); + if (force) + fp = fopen (fname, "wb"); + else + { + if (!access (fname, F_OK)) + { + log_error ("secret key file `%s' already exists\n", fname); + xfree (fname); + return -1; + } + fp = fopen (fname, "wbx"); /* FIXME: the x is a GNU extension - let + configure check whether this actually + works */ + } + + if (!fp) + { + log_error ("can't create `%s': %s\n", fname, strerror (errno)); + xfree (fname); + return -1; + } + + if (fwrite (buffer, length, 1, fp) != 1) + { + log_error ("error writing `%s': %s\n", fname, strerror (errno)); + fclose (fp); + remove (fname); + xfree (fname); + return -1; + } + if ( fclose (fp) ) + { + log_error ("error closing `%s': %s\n", fname, strerror (errno)); + remove (fname); + xfree (fname); + return -1; + } + log_info ("secret key stored as `%s'\n", fname); + + xfree (fname); + return 0; +} diff --git a/agent/protect.c b/agent/protect.c new file mode 100644 index 000000000..e438d53b4 --- /dev/null +++ b/agent/protect.c @@ -0,0 +1,971 @@ +/* protect.c - Un/Protect a secret key + * 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 <assert.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "agent.h" + +#include "sexp-parse.h" + +#define PROT_CIPHER GCRY_CIPHER_AES +#define PROT_CIPHER_STRING "aes" +#define PROT_CIPHER_KEYLEN (128/8) + + +/* A table containing the information needed to create a protected + private key */ +static struct { + const char *algo; + const char *parmlist; + int prot_from, prot_to; +} protect_info[] = { + { "rsa", "nedpqu", 2, 5 }, + { NULL } +}; + + +static int +hash_passphrase (const char *passphrase, int hashalgo, + int s2kmode, + const unsigned char *s2ksalt, unsigned long s2kcount, + unsigned char *key, size_t keylen); + + + +/* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to + a 20 byte buffer. This function is suitable for any algorithms. */ +static int +calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) +{ + const unsigned char *hash_begin, *hash_end; + const unsigned char *s; + size_t n; + + s = plainkey; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "private-key")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + hash_begin = s; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; /* skip over the algorithm name */ + + while (*s == '(') + { + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; + if ( *s != ')' ) + return gpg_error (GPG_ERR_INV_SEXP); + s++; + } + if (*s != ')') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + hash_end = s; + + gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash, + hash_begin, hash_end - hash_begin); + + return 0; +} + + + +/* Encrypt the parameter block starting at PROTBEGIN with length + PROTLEN using the utf8 encoded key PASSPHRASE and return the entire + encrypted block in RESULT or ereturn with an error code. SHA1HASH + is the 20 byte SHA-1 hash required for the integrity code. + + The parameter block is expected to be an incomplete S-Expression of + the form (example in advanced format): + + (d #046129F..[some bytes not shown]..81#) + (p #00e861b..[some bytes not shown]..f1#) + (q #00f7a7c..[some bytes not shown]..61#) + (u #304559a..[some bytes not shown]..9b#) + + the returned block is the S-Expression: + + (protected mode (parms) encrypted_octet_string) + +*/ +static int +do_encryption (const char *protbegin, size_t protlen, + const char *passphrase, const unsigned char *sha1hash, + unsigned char **result, size_t *resultlen) +{ + gcry_cipher_hd_t hd; + const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"; + int blklen, enclen, outlen; + char *iv = NULL; + int rc; + char *outbuf = NULL; + char *p; + int saltpos, ivpos, encpos; + + rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC, + GCRY_CIPHER_SECURE); + if (rc) + return rc; + + + /* We need to work on a copy of the data because this makes it + easier to add the trailer and the padding and more important we + have to prefix the text with 2 parenthesis, so we have to + allocate enough space for: + + ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding + + We always append a full block of random bytes as padding but + encrypt only what is needed for a full blocksize */ + blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER); + outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen; + enclen = outlen/blklen * blklen; + outbuf = gcry_malloc_secure (outlen); + if (!outbuf) + rc = out_of_core (); + if (!rc) + { + /* allocate random bytes to be used as IV, padding and s2k salt*/ + iv = gcry_random_bytes (blklen*2+8, GCRY_WEAK_RANDOM); + if (!iv) + rc = gpg_error (GPG_ERR_ENOMEM); + else + rc = gcry_cipher_setiv (hd, iv, blklen); + } + if (!rc) + { + unsigned char *key; + size_t keylen = PROT_CIPHER_KEYLEN; + + key = gcry_malloc_secure (keylen); + if (!key) + rc = out_of_core (); + else + { + rc = hash_passphrase (passphrase, GCRY_MD_SHA1, + 3, iv+2*blklen, 96, key, keylen); + if (!rc) + rc = gcry_cipher_setkey (hd, key, keylen); + xfree (key); + } + } + if (!rc) + { + p = outbuf; + *p++ = '('; + *p++ = '('; + memcpy (p, protbegin, protlen); + p += protlen; + memcpy (p, ")(4:hash4:sha120:", 17); + p += 17; + memcpy (p, sha1hash, 20); + p += 20; + *p++ = ')'; + *p++ = ')'; + memcpy (p, iv+blklen, blklen); + p += blklen; + assert ( p - outbuf == outlen); + rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0); + } + gcry_cipher_close (hd); + if (rc) + { + xfree (iv); + xfree (outbuf); + return rc; + } + + /* Now allocate the buffer we want to return. This is + + (protected openpgp-s2k3-sha1-aes-cbc + ((sha1 salt no_of_iterations) 16byte_iv) + encrypted_octet_string) + + in canoncical format of course. We use asprintf and %n modifier + and spaces as palceholders. */ + asprintf (&p, + "(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)", + (int)strlen (modestr), modestr, + &saltpos, + blklen, &ivpos, blklen, "", + enclen, &encpos, enclen, ""); + if (p) + { /* asprintf does not use our malloc system */ + char *psave = p; + p = xtrymalloc (strlen (psave)+1); + if (p) + strcpy (p, psave); + free (psave); + } + if (!p) + { + gpg_error_t tmperr = out_of_core (); + xfree (iv); + xfree (outbuf); + return tmperr; + } + *resultlen = strlen (p); + *result = p; + memcpy (p+saltpos, iv+2*blklen, 8); + memcpy (p+ivpos, iv, blklen); + memcpy (p+encpos, outbuf, enclen); + xfree (iv); + xfree (outbuf); + return 0; +} + + + +/* Protect the key encoded in canonical format in plainkey. We assume + a valid S-Exp here. */ +int +agent_protect (const unsigned char *plainkey, const char *passphrase, + unsigned char **result, size_t *resultlen) +{ + int rc; + const unsigned char *s; + const unsigned char *hash_begin, *hash_end; + const unsigned char *prot_begin, *prot_end, *real_end; + size_t n; + int c, infidx, i; + unsigned char hashvalue[20]; + unsigned char *protected; + size_t protectedlen; + int depth = 0; + unsigned char *p; + + s = plainkey; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "private-key")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + depth++; + hash_begin = s; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + + for (infidx=0; protect_info[infidx].algo + && !smatch (&s, n, protect_info[infidx].algo); infidx++) + ; + if (!protect_info[infidx].algo) + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + + prot_begin = prot_end = NULL; + for (i=0; (c=protect_info[infidx].parmlist[i]); i++) + { + if (i == protect_info[infidx].prot_from) + prot_begin = s; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (n != 1 || c != *s) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s +=n; /* skip value */ + if (*s != ')') + return gpg_error (GPG_ERR_INV_SEXP); + depth--; + if (i == protect_info[infidx].prot_to) + prot_end = s; + s++; + } + if (*s != ')' || !prot_begin || !prot_end ) + return gpg_error (GPG_ERR_INV_SEXP); + depth--; + hash_end = s; + s++; + /* skip to the end of the S-exp */ + assert (depth == 1); + rc = sskip (&s, &depth); + if (rc) + return rc; + assert (!depth); + real_end = s-1; + + gcry_md_hash_buffer (GCRY_MD_SHA1, hashvalue, + hash_begin, hash_end - hash_begin + 1); + + rc = do_encryption (prot_begin, prot_end - prot_begin + 1, + passphrase, hashvalue, + &protected, &protectedlen); + if (rc) + return rc; + + /* Now create the protected version of the key. Note that the 10 + extra bytes are for for the inserted "protected-" string (the + beginning of the plaintext reads: "((11:private-key(" ). */ + *resultlen = (10 + + (prot_begin-plainkey) + + protectedlen + + (real_end-prot_end)); + *result = p = xtrymalloc (*resultlen); + if (!p) + { + gpg_error_t tmperr = out_of_core (); + xfree (protected); + return tmperr; + } + memcpy (p, "(21:protected-", 14); + p += 14; + memcpy (p, plainkey+4, prot_begin - plainkey - 4); + p += prot_begin - plainkey - 4; + memcpy (p, protected, protectedlen); + p += protectedlen; + memcpy (p, prot_end+1, real_end - prot_end); + p += real_end - prot_end; + assert ( p - *result == *resultlen); + xfree (protected); + return 0; +} + + +/* Do the actual decryption and check the return list for consistency. */ +static int +do_decryption (const unsigned char *protected, size_t protectedlen, + const char *passphrase, + const unsigned char *s2ksalt, unsigned long s2kcount, + const unsigned char *iv, size_t ivlen, + unsigned char **result) +{ + int rc = 0; + int blklen; + gcry_cipher_hd_t hd; + unsigned char *outbuf; + size_t reallen; + + blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER); + if (protectedlen < 4 || (protectedlen%blklen)) + return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); + + rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC, + GCRY_CIPHER_SECURE); + if (rc) + return rc; + + outbuf = gcry_malloc_secure (protectedlen); + if (!outbuf) + rc = out_of_core (); + if (!rc) + rc = gcry_cipher_setiv (hd, iv, ivlen); + if (!rc) + { + unsigned char *key; + size_t keylen = PROT_CIPHER_KEYLEN; + + key = gcry_malloc_secure (keylen); + if (!key) + rc = out_of_core (); + else + { + rc = hash_passphrase (passphrase, GCRY_MD_SHA1, + 3, s2ksalt, s2kcount, key, keylen); + if (!rc) + rc = gcry_cipher_setkey (hd, key, keylen); + xfree (key); + } + } + if (!rc) + rc = gcry_cipher_decrypt (hd, outbuf, protectedlen, + protected, protectedlen); + gcry_cipher_close (hd); + if (rc) + { + xfree (outbuf); + return rc; + } + /* do a quick check first */ + if (*outbuf != '(' && outbuf[1] != '(') + { + xfree (outbuf); + return gpg_error (GPG_ERR_BAD_PASSPHRASE); + } + /* check that we have a consistent S-Exp */ + reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL); + if (!reallen || (reallen + blklen < protectedlen) ) + { + xfree (outbuf); + return gpg_error (GPG_ERR_BAD_PASSPHRASE); + } + *result = outbuf; + return 0; +} + + +/* Merge the parameter list contained in CLEARTEXT with the original + protect lists PROTECTEDKEY by replacing the list at REPLACEPOS. + Return the new list in RESULT and the MIC value in the 20 byte + buffer SHA1HASH. */ +static int +merge_lists (const unsigned char *protectedkey, + size_t replacepos, + const unsigned char *cleartext, + unsigned char *sha1hash, unsigned char **result) +{ + size_t n, newlistlen; + unsigned char *newlist, *p; + const unsigned char *s; + const unsigned char *startpos, *endpos; + int i, rc; + + if (replacepos < 26) + return gpg_error (GPG_ERR_BUG); + + /* Estimate the required size of the resulting list. We have a large + safety margin of >20 bytes (MIC hash from CLEARTEXT and the + removed "protected-" */ + newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL); + if (!newlistlen) + return gpg_error (GPG_ERR_BUG); + n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL); + if (!n) + return gpg_error (GPG_ERR_BUG); + newlistlen += n; + newlist = gcry_malloc_secure (newlistlen); + if (!newlist) + return out_of_core (); + + /* Copy the initial segment */ + strcpy (newlist, "(11:private-key"); + p = newlist + 15; + memcpy (p, protectedkey+15+10, replacepos-15-10); + p += replacepos-15-10; + + /* copy the cleartext */ + s = cleartext; + if (*s != '(' && s[1] != '(') + return gpg_error (GPG_ERR_BUG); /*we already checked this */ + s += 2; + startpos = s; + while ( *s == '(' ) + { + s++; + n = snext (&s); + if (!n) + goto invalid_sexp; + s += n; + n = snext (&s); + if (!n) + goto invalid_sexp; + s += n; + if ( *s != ')' ) + goto invalid_sexp; + s++; + } + if ( *s != ')' ) + goto invalid_sexp; + endpos = s; + s++; + /* short intermezzo: Get the MIC */ + if (*s != '(') + goto invalid_sexp; + s++; + n = snext (&s); + if (!smatch (&s, n, "hash")) + goto invalid_sexp; + n = snext (&s); + if (!smatch (&s, n, "sha1")) + goto invalid_sexp; + n = snext (&s); + if (n != 20) + goto invalid_sexp; + memcpy (sha1hash, s, 20); + s += n; + if (*s != ')') + goto invalid_sexp; + /* end intermezzo */ + + /* append the parameter list */ + memcpy (p, startpos, endpos - startpos); + p += endpos - startpos; + + /* skip overt the protected list element in the original list */ + s = protectedkey + replacepos; + assert (*s == '('); + s++; + i = 1; + rc = sskip (&s, &i); + if (rc) + goto failure; + startpos = s; + i = 2; /* we are inside this level */ + rc = sskip (&s, &i); + if (rc) + goto failure; + assert (s[-1] == ')'); + endpos = s; /* one behind the end of the list */ + + /* append the rest */ + memcpy (p, startpos, endpos - startpos); + p += endpos - startpos; + + /* ready */ + *result = newlist; + return 0; + + failure: + xfree (newlist); + return rc; + + invalid_sexp: + xfree (newlist); + return gpg_error (GPG_ERR_INV_SEXP); +} + + + +/* Unprotect the key encoded in canonical format. We assume a valid + S-Exp here. */ +int +agent_unprotect (const unsigned char *protectedkey, const char *passphrase, + unsigned char **result, size_t *resultlen) +{ + int rc; + const unsigned char *s; + size_t n; + int infidx, i; + unsigned char sha1hash[20], sha1hash2[20]; + const unsigned char *s2ksalt; + unsigned long s2kcount; + const unsigned char *iv; + const unsigned char *prot_begin; + unsigned char *cleartext; + unsigned char *final; + + s = protectedkey; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "protected-private-key")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + + for (infidx=0; protect_info[infidx].algo + && !smatch (&s, n, protect_info[infidx].algo); infidx++) + ; + if (!protect_info[infidx].algo) + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + + /* now find the list with the protected information. Here is an + example for such a list: + (protected openpgp-s2k3-sha1-aes-cbc + ((sha1 <salt> <count>) <Initialization_Vector>) + <encrypted_data>) + */ + for (;;) + { + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + prot_begin = s; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (smatch (&s, n, "protected")) + break; + s += n; + i = 1; + rc = sskip (&s, &i); + if (rc) + return rc; + } + /* found */ + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc")) + return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION); + if (*s != '(' || s[1] != '(') + return gpg_error (GPG_ERR_INV_SEXP); + s += 2; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "sha1")) + return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION); + n = snext (&s); + if (n != 8) + return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); + s2ksalt = s; + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); + /* We expect a list close as next, so we can simply use strtoul() + here. We might want to check that we only have digits - but this + is nothing we should worry about */ + if (s[n] != ')' ) + return gpg_error (GPG_ERR_INV_SEXP); + s2kcount = strtoul (s, NULL, 10); + if (!s2kcount) + return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); + s += n; + s++; /* skip list end */ + + n = snext (&s); + if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */ + return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); + iv = s; + s += n; + if (*s != ')' ) + return gpg_error (GPG_ERR_INV_SEXP); + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + + rc = do_decryption (s, n, + passphrase, s2ksalt, s2kcount, + iv, 16, + &cleartext); + if (rc) + return rc; + + rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext, + sha1hash, &final); + xfree (cleartext); + if (rc) + return rc; + + rc = calculate_mic (final, sha1hash2); + if (!rc && memcmp (sha1hash, sha1hash2, 20)) + rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION); + if (rc) + { + xfree (final); + return rc; + } + + *result = final; + *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL); + return 0; +} + +/* Check the type of the private key, this is one of the constants: + PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the + value 0), PRIVATE_KEY_CLEAR for an unprotected private key. + PRIVATE_KEY_PROTECTED for an protected private key or + PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored + elsewhere. */ +int +agent_private_key_type (const unsigned char *privatekey) +{ + const unsigned char *s; + size_t n; + + s = privatekey; + if (*s != '(') + return PRIVATE_KEY_UNKNOWN; + s++; + n = snext (&s); + if (!n) + return PRIVATE_KEY_UNKNOWN; + if (smatch (&s, n, "protected-private-key")) + return PRIVATE_KEY_PROTECTED; + if (smatch (&s, n, "shadowed-private-key")) + return PRIVATE_KEY_SHADOWED; + if (smatch (&s, n, "private-key")) + return PRIVATE_KEY_CLEAR; + return PRIVATE_KEY_UNKNOWN; +} + + + +/* Transform a passphrase into a suitable key of length KEYLEN and + store this key in the caller provided buffer KEY. The caller must + provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on + that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable + value is 96). + + Returns an error code on failure. */ +static int +hash_passphrase (const char *passphrase, int hashalgo, + int s2kmode, + const unsigned char *s2ksalt, + unsigned long s2kcount, + unsigned char *key, size_t keylen) +{ + int rc; + gcry_md_hd_t md; + int pass, i; + int used = 0; + int pwlen = strlen (passphrase); + + if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3) + || !hashalgo || !keylen || !key || !passphrase) + return gpg_error (GPG_ERR_INV_VALUE); + if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt) + return gpg_error (GPG_ERR_INV_VALUE); + + rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE); + if (rc) + return rc; + + for (pass=0; used < keylen; pass++) + { + if (pass) + { + gcry_md_reset (md); + for (i=0; i < pass; i++) /* preset the hash context */ + gcry_md_putc (md, 0); + } + + if (s2kmode == 1 || s2kmode == 3) + { + int len2 = pwlen + 8; + unsigned long count = len2; + + if (s2kmode == 3) + { + count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6); + if (count < len2) + count = len2; + } + + while (count > len2) + { + gcry_md_write (md, s2ksalt, 8); + gcry_md_write (md, passphrase, pwlen); + count -= len2; + } + if (count < 8) + gcry_md_write (md, s2ksalt, count); + else + { + gcry_md_write (md, s2ksalt, 8); + count -= 8; + gcry_md_write (md, passphrase, count); + } + } + else + gcry_md_write (md, passphrase, pwlen); + + gcry_md_final (md); + i = gcry_md_get_algo_dlen (hashalgo); + if (i > keylen - used) + i = keylen - used; + memcpy (key+used, gcry_md_read (md, hashalgo), i); + used += i; + } + gcry_md_close(md); + return 0; +} + + + +/* Create a shadow key from a public key. We use the shadow protocol + "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting + S-expression is returned in an allocated buffer RESULT will point + to. The input parameters are expected to be valid canonilized + S-expressions */ +int +agent_shadow_key (const unsigned char *pubkey, + const unsigned char *shadow_info, + unsigned char **result) +{ + const unsigned char *s; + const unsigned char *point; + size_t n; + int depth = 0; + unsigned char *p; + size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL); + size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL); + + if (!pubkey_len || !shadow_info_len) + return gpg_error (GPG_ERR_INV_VALUE); + s = pubkey; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "public-key")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; /* skip over the algorithm name */ + + while (*s != ')') + { + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s +=n; /* skip value */ + if (*s != ')') + return gpg_error (GPG_ERR_INV_SEXP); + depth--; + s++; + } + point = s; /* insert right before the point */ + depth--; + s++; + assert (depth == 1); + + /* calculate required length by taking in account: the "shadowed-" + prefix, the "shadowed", "t1-v1" as well as some parenthesis */ + n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1; + *result = p = xtrymalloc (n); + if (!p) + return out_of_core (); + p = stpcpy (p, "(20:shadowed-private-key"); + /* (10:public-key ...)*/ + memcpy (p, pubkey+14, point - (pubkey+14)); + p += point - (pubkey+14); + p = stpcpy (p, "(8:shadowed5:t1-v1"); + memcpy (p, shadow_info, shadow_info_len); + p += shadow_info_len; + *p++ = ')'; + memcpy (p, point, pubkey_len - (point - pubkey)); + p += pubkey_len - (point - pubkey); + + return 0; +} + +/* Parse a canonical encoded shadowed key and return a pointer to the + inner list with the shadow_info */ +int +agent_get_shadow_info (const unsigned char *shadowkey, + unsigned char const **shadow_info) +{ + const unsigned char *s; + size_t n; + int depth = 0; + + s = shadowkey; + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (!smatch (&s, n, "shadowed-private-key")) + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s += n; /* skip over the algorithm name */ + + for (;;) + { + if (*s == ')') + return gpg_error (GPG_ERR_UNKNOWN_SEXP); + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + depth++; + s++; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (smatch (&s, n, "shadowed")) + break; + s += n; + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + s +=n; /* skip value */ + if (*s != ')') + return gpg_error (GPG_ERR_INV_SEXP); + depth--; + s++; + } + /* found the shadowed list, s points to the protocol */ + n = snext (&s); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + if (smatch (&s, n, "t1-v1")) + { + if (*s != '(') + return gpg_error (GPG_ERR_INV_SEXP); + *shadow_info = s; + } + else + return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + return 0; +} + diff --git a/agent/simple-pwquery.c b/agent/simple-pwquery.c new file mode 100644 index 000000000..e870122cb --- /dev/null +++ b/agent/simple-pwquery.c @@ -0,0 +1,486 @@ +/* simple-pwquery.c - A simple password query client 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 ) + { +#ifdef SPWQ_USE_LOGGING + log_error (_("gpg-agent is not available in this session\n")); +#endif + return SPWQ_NO_AGENT; + } + + 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 poiinter 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; + char *p = buffer; + + for (i=0; text[i]; i++) + { + if (text[i] < ' ' || text[i] == '+') + { + sprintf (p, "%%%02X", text[i]); + p += 3; + } + else if (text[i] == ' ') + *p++ = '+'; + else + *p++ = text[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; +} diff --git a/common/ChangeLog b/common/ChangeLog new file mode 100644 index 000000000..4870a4a5d --- /dev/null +++ b/common/ChangeLog @@ -0,0 +1,219 @@ +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. + + diff --git a/common/Makefile.am b/common/Makefile.am new file mode 100644 index 000000000..2b99a19eb --- /dev/null +++ b/common/Makefile.am @@ -0,0 +1,58 @@ +# 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 +#INCLUDES = + +noinst_LIBRARIES = libcommon.a libsimple-pwquery.a + +AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) + +libcommon_a_SOURCES = \ + util.h i18n.h \ + errors.h \ + maperror.c \ + sysutils.c sysutils.h \ + cryptmiss.c \ + gettime.c \ + yesno.c \ + miscellaneous.c \ + membuf.c membuf.h \ + iobuf.c iobuf.h \ + ttyio.c ttyio.h \ + signal.c + + +libcommon_a_LIBADD = @LIBOBJS@ + +libsimple_pwquery_a_SOURCES = \ + simple-pwquery.c simple-pwquery.h + +libsimple_pwquery_a_LIBADD = @LIBOBJS@ + + + + + + + + + diff --git a/common/README b/common/README new file mode 100644 index 000000000..a90224bab --- /dev/null +++ b/common/README @@ -0,0 +1,11 @@ +Stuff used by several modules of GnuPG. + +These directories use it: + +gpg +sm +agent + +These directories don't use it: + +kbx \ No newline at end of file diff --git a/common/errors.h b/common/errors.h new file mode 100644 index 000000000..a5643f08a --- /dev/null +++ b/common/errors.h @@ -0,0 +1,110 @@ +/* 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_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 +}; + + +/*-- 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*/ diff --git a/common/gettime.c b/common/gettime.c new file mode 100644 index 000000000..a7914d348 --- /dev/null +++ b/common/gettime.c @@ -0,0 +1,250 @@ +/* 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; +} + +/* 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"); + 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; +} + + + + + + + + + + + + + + diff --git a/common/iobuf.c b/common/iobuf.c new file mode 100644 index 000000000..773e2993b --- /dev/null +++ b/common/iobuf.c @@ -0,0 +1,2415 @@ +/* iobuf.c - file 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 <ctype.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#ifdef HAVE_DOSISH_SYSTEM +#include <windows.h> +#endif +#ifdef __riscos__ +#include <kernel.h> +#include <swis.h> +#endif /* __riscos__ */ + +#include "memory.h" +#include "util.h" +#include "iobuf.h" + +#undef FILE_FILTER_USES_STDIO + +#ifdef HAVE_DOSISH_SYSTEM +#define USE_SETMODE 1 +#endif + +#ifdef FILE_FILTER_USES_STDIO +#define my_fileno(a) fileno ((a)) +#define my_fopen_ro(a,b) fopen ((a),(b)) +#define my_fopen(a,b) fopen ((a),(b)) +typedef FILE *FILEP_OR_FD; +#define INVALID_FP NULL +#define FILEP_OR_FD_FOR_STDIN (stdin) +#define FILEP_OR_FD_FOR_STDOUT (stdout) +typedef struct +{ + FILE *fp; /* open file handle */ + int keep_open; + int no_cache; + int print_only_name; /* flags indicating that fname is not a real file */ + char fname[1]; /* name of the file */ +} +file_filter_ctx_t; +#else +#define my_fileno(a) (a) +#define my_fopen_ro(a,b) fd_cache_open ((a),(b)) +#define my_fopen(a,b) direct_open ((a),(b)) +#ifdef HAVE_DOSISH_SYSTEM +typedef HANDLE FILEP_OR_FD; +#define INVALID_FP ((HANDLE)-1) +#define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE)) +#define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE)) +#undef USE_SETMODE +#else +typedef int FILEP_OR_FD; +#define INVALID_FP (-1) +#define FILEP_OR_FD_FOR_STDIN (0) +#define FILEP_OR_FD_FOR_STDOUT (1) +#endif +typedef struct +{ + FILEP_OR_FD fp; /* open file handle */ + int keep_open; + int no_cache; + int eof_seen; + int print_only_name; /* flags indicating that fname is not a real file */ + char fname[1]; /* name of the file */ +} +file_filter_ctx_t; + +struct close_cache_s +{ + struct close_cache_s *next; + FILEP_OR_FD fp; + char fname[1]; +}; +typedef struct close_cache_s *CLOSE_CACHE; +static CLOSE_CACHE close_cache; +#endif + +#ifdef __MINGW32__ +typedef struct +{ + int sock; + int keep_open; + int no_cache; + int eof_seen; + int print_only_name; /* flags indicating that fname is not a real file */ + char fname[1]; /* name of the file */ +} +sock_filter_ctx_t; +#endif /*__MINGW32__*/ + +/* The first partial length header block must be of size 512 + * to make it easier (and efficienter) we use a min. block size of 512 + * for all chunks (but the last one) */ +#define OP_MIN_PARTIAL_CHUNK 512 +#define OP_MIN_PARTIAL_CHUNK_2POW 9 + +typedef struct +{ + int use; + size_t size; + size_t count; + int partial; /* 1 = partial header, 2 in last partial packet */ + char *buffer; /* used for partial header */ + size_t buflen; /* used size of buffer */ + int first_c; /* of partial header (which is > 0) */ + int eof; +} +block_filter_ctx_t; + +static int special_names_enabled; + +static int underflow (iobuf_t a); +static int translate_file_handle (int fd, int for_write); + +#ifndef FILE_FILTER_USES_STDIO + +/* + * Invalidate (i.e. close) a cached iobuf + */ +static void +fd_cache_invalidate (const char *fname) +{ + CLOSE_CACHE cc; + + assert (fname); + if (DBG_IOBUF) + log_debug ("fd_cache_invalidate (%s)\n", fname); + + for (cc = close_cache; cc; cc = cc->next) + { + if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname)) + { + if (DBG_IOBUF) + log_debug (" did (%s)\n", cc->fname); +#ifdef HAVE_DOSISH_SYSTEM + CloseHandle (cc->fp); +#else + close (cc->fp); +#endif + cc->fp = INVALID_FP; + } + } +} + + + +static FILEP_OR_FD +direct_open (const char *fname, const char *mode) +{ +#ifdef HAVE_DOSISH_SYSTEM + unsigned long da, cd, sm; + HANDLE hfile; + + /* Note, that we do not handle all mode combinations */ + + /* According to the ReactOS source it seems that open() of the + * standard MSW32 crt does open the file in share mode which is + * something new for MS applications ;-) + */ + if (strchr (mode, '+')) + { + fd_cache_invalidate (fname); + da = GENERIC_READ | GENERIC_WRITE; + cd = OPEN_EXISTING; + sm = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + else if (strchr (mode, 'w')) + { + fd_cache_invalidate (fname); + da = GENERIC_WRITE; + cd = CREATE_ALWAYS; + sm = FILE_SHARE_WRITE; + } + else + { + da = GENERIC_READ; + cd = OPEN_EXISTING; + sm = FILE_SHARE_READ; + } + + hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL); + return hfile; +#else + int oflag; + int cflag = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + + /* Note, that we do not handle all mode combinations */ + if (strchr (mode, '+')) + { + fd_cache_invalidate (fname); + oflag = O_RDWR; + } + else if (strchr (mode, 'w')) + { + fd_cache_invalidate (fname); + oflag = O_WRONLY | O_CREAT | O_TRUNC; + } + else + { + oflag = O_RDONLY; + } +#ifdef O_BINARY + if (strchr (mode, 'b')) + oflag |= O_BINARY; +#endif +#ifndef __riscos__ + return open (fname, oflag, cflag); +#else + { + struct stat buf; + int rc = stat (fname, &buf); + + /* Don't allow iobufs on directories */ + if (!rc && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode)) + return __set_errno (EISDIR); + else + return open (fname, oflag, cflag); + } +#endif +#endif +} + + +/* + * Instead of closing an FD we keep it open and cache it for later reuse + * Note that this caching strategy only works if the process does not chdir. + */ +static void +fd_cache_close (const char *fname, FILEP_OR_FD fp) +{ + CLOSE_CACHE cc; + + assert (fp); + if (!fname || !*fname) + { +#ifdef HAVE_DOSISH_SYSTEM + CloseHandle (fp); +#else + close (fp); +#endif + if (DBG_IOBUF) + log_debug ("fd_cache_close (%p) real\n", (void *) fp); + return; + } + /* try to reuse a slot */ + for (cc = close_cache; cc; cc = cc->next) + { + if (cc->fp == INVALID_FP && !strcmp (cc->fname, fname)) + { + cc->fp = fp; + if (DBG_IOBUF) + log_debug ("fd_cache_close (%s) used existing slot\n", fname); + return; + } + } + /* add a new one */ + if (DBG_IOBUF) + log_debug ("fd_cache_close (%s) new slot created\n", fname); + cc = xcalloc (1, sizeof *cc + strlen (fname)); + strcpy (cc->fname, fname); + cc->fp = fp; + cc->next = close_cache; + close_cache = cc; +} + +/* + * Do an direct_open on FNAME but first try to reuse one from the fd_cache + */ +static FILEP_OR_FD +fd_cache_open (const char *fname, const char *mode) +{ + CLOSE_CACHE cc; + + assert (fname); + for (cc = close_cache; cc; cc = cc->next) + { + if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname)) + { + FILEP_OR_FD fp = cc->fp; + cc->fp = INVALID_FP; + if (DBG_IOBUF) + log_debug ("fd_cache_open (%s) using cached fp\n", fname); +#ifdef HAVE_DOSISH_SYSTEM + if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff) + { + log_error ("rewind file failed on handle %p: ec=%d\n", + fp, (int) GetLastError ()); + fp = INVALID_FP; + } +#else + if (lseek (fp, 0, SEEK_SET) == (off_t) - 1) + { + log_error ("can't rewind fd %d: %s\n", fp, strerror (errno)); + fp = INVALID_FP; + } +#endif + return fp; + } + } + if (DBG_IOBUF) + log_debug ("fd_cache_open (%s) not cached\n", fname); + return direct_open (fname, mode); +} + + +#endif /*FILE_FILTER_USES_STDIO */ + + +/**************** + * Read data from a file into buf which has an allocated length of *LEN. + * return the number of read bytes in *LEN. OPAQUE is the FILE * of + * the stream. A is not used. + * control may be: + * IOBUFCTRL_INIT: called just before the function is linked into the + * list of function. This can be used to prepare internal + * data structures of the function. + * IOBUFCTRL_FREE: called just before the function is removed from the + * list of functions and can be used to release internal + * data structures or close a file etc. + * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer + * with new stuff. *RET_LEN is the available size of the + * buffer, and should be set to the number of bytes + * which were put into the buffer. The function + * returns 0 to indicate success, -1 on EOF and + * GPG_ERR_xxxxx for other errors. + * + * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff. + * *RET_LAN is the number of bytes in BUF. + * + * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The + * filter may take appropriate action on this message. + */ +static int +file_filter (void *opaque, int control, iobuf_t chain, byte * buf, + size_t * ret_len) +{ + file_filter_ctx_t *a = opaque; + FILEP_OR_FD f = a->fp; + size_t size = *ret_len; + size_t nbytes = 0; + int rc = 0; + +#ifdef FILE_FILTER_USES_STDIO + if (control == IOBUFCTRL_UNDERFLOW) + { + assert (size); /* need a buffer */ + if (feof (f)) + { /* On terminals you could easiely read as many EOFs as you call */ + rc = -1; /* fread() or fgetc() repeatly. Every call will block until you press */ + *ret_len = 0; /* CTRL-D. So we catch this case before we call fread() again. */ + } + else + { + clearerr (f); + nbytes = fread (buf, 1, size, f); + if (feof (f) && !nbytes) + { + rc = -1; /* okay: we can return EOF now. */ + } + else if (ferror (f) && errno != EPIPE) + { + rc = gpg_error_from_errno (errno); + log_error ("%s: read error: %s\n", a->fname, strerror (errno)); + } + *ret_len = nbytes; + } + } + else if (control == IOBUFCTRL_FLUSH) + { + if (size) + { + clearerr (f); + nbytes = fwrite (buf, 1, size, f); + if (ferror (f)) + { + rc = gpg_error_from_errno (errno); + log_error ("%s: write error: %s\n", a->fname, strerror (errno)); + } + } + *ret_len = nbytes; + } + else if (control == IOBUFCTRL_INIT) + { + a->keep_open = a->no_cache = 0; + } + else if (control == IOBUFCTRL_DESC) + { + *(char **) buf = "file_filter"; + } + else if (control == IOBUFCTRL_FREE) + { + if (f != stdin && f != stdout) + { + if (DBG_IOBUF) + log_debug ("%s: close fd %d\n", a->fname, fileno (f)); + if (!a->keep_open) + fclose (f); + } + f = NULL; + xfree (a); /* we can free our context now */ + } +#else /* !stdio implementation */ + + if (control == IOBUFCTRL_UNDERFLOW) + { + assert (size); /* need a buffer */ + if (a->eof_seen) + { + rc = -1; + *ret_len = 0; + } + else + { +#ifdef HAVE_DOSISH_SYSTEM + unsigned long nread; + + nbytes = 0; + if (!ReadFile (f, buf, size, &nread, NULL)) + { + int ec = (int) GetLastError (); + if (ec != ERROR_BROKEN_PIPE) + { + rc = gpg_error_from_errno (ec); + log_error ("%s: read error: ec=%d\n", a->fname, ec); + } + } + else if (!nread) + { + a->eof_seen = 1; + rc = -1; + } + else + { + nbytes = nread; + } + +#else + + int n; + + nbytes = 0; + do + { + n = read (f, buf, size); + } + while (n == -1 && errno == EINTR); + if (n == -1) + { /* error */ + if (errno != EPIPE) + { + rc = gpg_error_from_errno (errno); + log_error ("%s: read error: %s\n", + a->fname, strerror (errno)); + } + } + else if (!n) + { /* eof */ + a->eof_seen = 1; + rc = -1; + } + else + { + nbytes = n; + } +#endif + *ret_len = nbytes; + } + } + else if (control == IOBUFCTRL_FLUSH) + { + if (size) + { +#ifdef HAVE_DOSISH_SYSTEM + byte *p = buf; + unsigned long n; + + nbytes = size; + do + { + if (size && !WriteFile (f, p, nbytes, &n, NULL)) + { + int ec = (int) GetLastError (); + rc = gpg_error_from_errno (ec); + log_error ("%s: write error: ec=%d\n", a->fname, ec); + break; + } + p += n; + nbytes -= n; + } + while (nbytes); + nbytes = p - buf; +#else + byte *p = buf; + int n; + + nbytes = size; + do + { + do + { + n = write (f, p, nbytes); + } + while (n == -1 && errno == EINTR); + if (n > 0) + { + p += n; + nbytes -= n; + } + } + while (n != -1 && nbytes); + if (n == -1) + { + rc = gpg_error_from_errno (errno); + log_error ("%s: write error: %s\n", a->fname, strerror (errno)); + } + nbytes = p - buf; +#endif + } + *ret_len = nbytes; + } + else if (control == IOBUFCTRL_INIT) + { + a->eof_seen = 0; + a->keep_open = 0; + a->no_cache = 0; + } + else if (control == IOBUFCTRL_DESC) + { + *(char **) buf = "file_filter(fd)"; + } + else if (control == IOBUFCTRL_FREE) + { +#ifdef HAVE_DOSISH_SYSTEM + if (f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT) + { + if (DBG_IOBUF) + log_debug ("%s: close handle %p\n", a->fname, f); + if (!a->keep_open) + fd_cache_close (a->no_cache ? NULL : a->fname, f); + } +#else + if ((int) f != 0 && (int) f != 1) + { + if (DBG_IOBUF) + log_debug ("%s: close fd %d\n", a->fname, f); + if (!a->keep_open) + fd_cache_close (a->no_cache ? NULL : a->fname, f); + } + f = INVALID_FP; +#endif + xfree (a); /* we can free our context now */ + } +#endif /* !stdio implementation */ + return rc; +} + +#ifdef __MINGW32__ +/* Becuase sockets are an special object under Lose32 we have to + * use a special filter */ +static int +sock_filter (void *opaque, int control, iobuf_t chain, byte * buf, + size_t * ret_len) +{ + sock_filter_ctx_t *a = opaque; + size_t size = *ret_len; + size_t nbytes = 0; + int rc = 0; + + if (control == IOBUFCTRL_UNDERFLOW) + { + assert (size); /* need a buffer */ + if (a->eof_seen) + { + rc = -1; + *ret_len = 0; + } + else + { + int nread; + + nread = recv (a->sock, buf, size, 0); + if (nread == SOCKET_ERROR) + { + int ec = (int) WSAGetLastError (); + rc = gpg_error_from_errno (ec); + log_error ("socket read error: ec=%d\n", ec); + } + else if (!nread) + { + a->eof_seen = 1; + rc = -1; + } + else + { + nbytes = nread; + } + *ret_len = nbytes; + } + } + else if (control == IOBUFCTRL_FLUSH) + { + if (size) + { + byte *p = buf; + int n; + + nbytes = size; + do + { + n = send (a->sock, p, nbytes, 0); + if (n == SOCKET_ERROR) + { + int ec = (int) WSAGetLastError (); + rc = gpg_error_from_errno (ec); + log_error ("socket write error: ec=%d\n", ec); + break; + } + p += n; + nbytes -= n; + } + while (nbytes); + nbytes = p - buf; + } + *ret_len = nbytes; + } + else if (control == IOBUFCTRL_INIT) + { + a->eof_seen = 0; + a->keep_open = 0; + a->no_cache = 0; + } + else if (control == IOBUFCTRL_DESC) + { + *(char **) buf = "sock_filter"; + } + else if (control == IOBUFCTRL_FREE) + { + if (!a->keep_open) + closesocket (a->sock); + xfree (a); /* we can free our context now */ + } + return rc; +} +#endif /*__MINGW32__*/ + +/**************** + * This is used to implement the block write mode. + * Block reading is done on a byte by byte basis in readbyte(), + * without a filter + */ +static int +block_filter (void *opaque, int control, iobuf_t chain, byte * buf, + size_t * ret_len) +{ + block_filter_ctx_t *a = opaque; + size_t size = *ret_len; + int c, needed, rc = 0; + char *p; + + if (control == IOBUFCTRL_UNDERFLOW) + { + size_t n = 0; + + p = buf; + assert (size); /* need a buffer */ + if (a->eof) /* don't read any further */ + rc = -1; + while (!rc && size) + { + if (!a->size) + { /* get the length bytes */ + if (a->partial == 2) + { + a->eof = 1; + if (!n) + rc = -1; + break; + } + else if (a->partial) + { + /* These OpenPGP introduced huffman like encoded length + * bytes are really a mess :-( */ + if (a->first_c) + { + c = a->first_c; + a->first_c = 0; + } + else if ((c = iobuf_get (chain)) == -1) + { + log_error ("block_filter: 1st length byte missing\n"); + rc = GPG_ERR_BAD_DATA; + break; + } + if (c < 192) + { + a->size = c; + a->partial = 2; + if (!a->size) + { + a->eof = 1; + if (!n) + rc = -1; + break; + } + } + else if (c < 224) + { + a->size = (c - 192) * 256; + if ((c = iobuf_get (chain)) == -1) + { + log_error + ("block_filter: 2nd length byte missing\n"); + rc = GPG_ERR_BAD_DATA; + break; + } + a->size += c + 192; + a->partial = 2; + if (!a->size) + { + a->eof = 1; + if (!n) + rc = -1; + break; + } + } + else if (c == 255) + { + a->size = iobuf_get (chain) << 24; + a->size |= iobuf_get (chain) << 16; + a->size |= iobuf_get (chain) << 8; + if ((c = iobuf_get (chain)) == -1) + { + log_error ("block_filter: invalid 4 byte length\n"); + rc = GPG_ERR_BAD_DATA; + break; + } + a->size |= c; + } + else + { /* next partial body length */ + a->size = 1 << (c & 0x1f); + } + /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */ + } + else + { /* the gnupg partial length scheme - much better :-) */ + c = iobuf_get (chain); + a->size = c << 8; + c = iobuf_get (chain); + a->size |= c; + if (c == -1) + { + log_error ("block_filter: error reading length info\n"); + rc = GPG_ERR_BAD_DATA; + } + if (!a->size) + { + a->eof = 1; + if (!n) + rc = -1; + break; + } + } + } + + while (!rc && size && a->size) + { + needed = size < a->size ? size : a->size; + c = iobuf_read (chain, p, needed); + if (c < needed) + { + if (c == -1) + c = 0; + log_error + ("block_filter %p: read error (size=%lu,a->size=%lu)\n", + a, (ulong) size + c, (ulong) a->size + c); + rc = GPG_ERR_BAD_DATA; + } + else + { + size -= c; + a->size -= c; + p += c; + n += c; + } + } + } + *ret_len = n; + } + else if (control == IOBUFCTRL_FLUSH) + { + if (a->partial) + { /* the complicated openpgp scheme */ + size_t blen, n, nbytes = size + a->buflen; + + assert (a->buflen <= OP_MIN_PARTIAL_CHUNK); + if (nbytes < OP_MIN_PARTIAL_CHUNK) + { + /* not enough to write a partial block out; so we store it */ + if (!a->buffer) + a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK); + memcpy (a->buffer + a->buflen, buf, size); + a->buflen += size; + } + else + { /* okay, we can write out something */ + /* do this in a loop to use the most efficient block lengths */ + p = buf; + do + { + /* find the best matching block length - this is limited + * by the size of the internal buffering */ + for (blen = OP_MIN_PARTIAL_CHUNK * 2, + c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes; + blen *= 2, c++) + ; + blen /= 2; + c--; + /* write the partial length header */ + assert (c <= 0x1f); /*;-) */ + c |= 0xe0; + iobuf_put (chain, c); + if ((n = a->buflen)) + { /* write stuff from the buffer */ + assert (n == OP_MIN_PARTIAL_CHUNK); + if (iobuf_write (chain, a->buffer, n)) + rc = gpg_error_from_errno (errno); + a->buflen = 0; + nbytes -= n; + } + if ((n = nbytes) > blen) + n = blen; + if (n && iobuf_write (chain, p, n)) + rc = gpg_error_from_errno (errno); + p += n; + nbytes -= n; + } + while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK); + /* store the rest in the buffer */ + if (!rc && nbytes) + { + assert (!a->buflen); + assert (nbytes < OP_MIN_PARTIAL_CHUNK); + if (!a->buffer) + a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK); + memcpy (a->buffer, p, nbytes); + a->buflen = nbytes; + } + } + } + else + { /* the gnupg scheme (which is not openpgp compliant) */ + size_t avail, n; + + for (p = buf; !rc && size;) + { + n = size; + avail = a->size - a->count; + if (!avail) + { + if (n > a->size) + { + iobuf_put (chain, (a->size >> 8) & 0xff); + iobuf_put (chain, a->size & 0xff); + avail = a->size; + a->count = 0; + } + else + { + iobuf_put (chain, (n >> 8) & 0xff); + iobuf_put (chain, n & 0xff); + avail = n; + a->count = a->size - n; + } + } + if (n > avail) + n = avail; + if (iobuf_write (chain, p, n)) + rc = gpg_error_from_errno (errno); + a->count += n; + p += n; + size -= n; + } + } + } + else if (control == IOBUFCTRL_INIT) + { + if (DBG_IOBUF) + log_debug ("init block_filter %p\n", a); + if (a->partial) + a->count = 0; + else if (a->use == 1) + a->count = a->size = 0; + else + a->count = a->size; /* force first length bytes */ + a->eof = 0; + a->buffer = NULL; + a->buflen = 0; + } + else if (control == IOBUFCTRL_DESC) + { + *(char **) buf = "block_filter"; + } + else if (control == IOBUFCTRL_FREE) + { + if (a->use == 2) + { /* write the end markers */ + if (a->partial) + { + u32 len; + /* write out the remaining bytes without a partial header + * the length of this header may be 0 - but if it is + * the first block we are not allowed to use a partial header + * and frankly we can't do so, because this length must be + * a power of 2. This is _really_ complicated because we + * have to check the possible length of a packet prior + * to it's creation: a chain of filters becomes complicated + * and we need a lot of code to handle compressed packets etc. + * :-((((((( + */ + /* construct header */ + len = a->buflen; + /*log_debug("partial: remaining length=%u\n", len ); */ + if (len < 192) + rc = iobuf_put (chain, len); + else if (len < 8384) + { + if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192))) + rc = iobuf_put (chain, ((len - 192) % 256)); + } + else + { /* use a 4 byte header */ + if (!(rc = iobuf_put (chain, 0xff))) + if (!(rc = iobuf_put (chain, (len >> 24) & 0xff))) + if (!(rc = iobuf_put (chain, (len >> 16) & 0xff))) + if (!(rc = iobuf_put (chain, (len >> 8) & 0xff))) + rc = iobuf_put (chain, len & 0xff); + } + if (!rc && len) + rc = iobuf_write (chain, a->buffer, len); + if (rc) + { + log_error ("block_filter: write error: %s\n", + strerror (errno)); + rc = gpg_error_from_errno (errno); + } + xfree (a->buffer); + a->buffer = NULL; + a->buflen = 0; + } + else + { + iobuf_writebyte (chain, 0); + iobuf_writebyte (chain, 0); + } + } + else if (a->size) + { + log_error ("block_filter: pending bytes!\n"); + } + if (DBG_IOBUF) + log_debug ("free block_filter %p\n", a); + xfree (a); /* we can free our context now */ + } + + return rc; +} + + +static void +print_chain (iobuf_t a) +{ + if (!DBG_IOBUF) + return; + for (; a; a = a->chain) + { + size_t dummy_len = 0; + const char *desc = "[none]"; + + if (a->filter) + a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL, + (byte *) & desc, &dummy_len); + + log_debug ("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n", + a->no, a->subno, desc, a->filter_eof, + (int) a->d.start, (int) a->d.len); + } +} + +int +iobuf_print_chain (iobuf_t a) +{ + print_chain (a); + return 0; +} + +/**************** + * Allocate a new io buffer, with no function assigned. + * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer + * BUFSIZE is a suggested buffer size. + */ +iobuf_t +iobuf_alloc (int use, size_t bufsize) +{ + iobuf_t a; + static int number = 0; + + a = xcalloc (1, sizeof *a); + a->use = use; + a->d.buf = xmalloc (bufsize); + a->d.size = bufsize; + a->no = ++number; + a->subno = 0; + a->opaque = NULL; + a->real_fname = NULL; + return a; +} + +int +iobuf_close (iobuf_t a) +{ + iobuf_t a2; + size_t dummy_len = 0; + int rc = 0; + + if (a && a->directfp) + { + fclose (a->directfp); + xfree (a->real_fname); + if (DBG_IOBUF) + log_debug ("iobuf_close -> %p\n", a->directfp); + return 0; + } + + for (; a && !rc; a = a2) + { + a2 = a->chain; + if (a->use == 2 && (rc = iobuf_flush (a))) + log_error ("iobuf_flush failed on close: %s\n", gpg_strerror (rc)); + + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc); + if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, + a->chain, NULL, &dummy_len))) + log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc)); + xfree (a->real_fname); + if (a->d.buf) + { + memset (a->d.buf, 0, a->d.size); /* erase the buffer */ + xfree (a->d.buf); + } + xfree (a); + } + return rc; +} + +int +iobuf_cancel (iobuf_t a) +{ + const char *s; + iobuf_t a2; + int rc; +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + char *remove_name = NULL; +#endif + + if (a && a->use == 2) + { + s = iobuf_get_real_fname (a); + if (s && *s) + { +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + remove_name = m_strdup (s); +#else + remove (s); +#endif + } + } + + /* send a cancel message to all filters */ + for (a2 = a; a2; a2 = a2->chain) + { + size_t dummy; + if (a2->filter) + a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy); + } + + rc = iobuf_close (a); +#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) + if (remove_name) + { + /* Argg, MSDOS does not allow to remove open files. So + * we have to do it here */ + remove (remove_name); + xfree (remove_name); + } +#endif + return rc; +} + + +/**************** + * create a temporary iobuf, which can be used to collect stuff + * in an iobuf and later be written by iobuf_write_temp() to another + * iobuf. + */ +iobuf_t +iobuf_temp () +{ + iobuf_t a; + + a = iobuf_alloc (3, 8192); + + return a; +} + +iobuf_t +iobuf_temp_with_content (const char *buffer, size_t length) +{ + iobuf_t a; + + a = iobuf_alloc (3, length); + memcpy (a->d.buf, buffer, length); + a->d.len = length; + + return a; +} + +void +iobuf_enable_special_filenames (int yes) +{ + special_names_enabled = yes; +} + +/* + * see whether the filename has the for "-&nnnn", where n is a + * non-zero number. + * Returns this number or -1 if it is not the case. + */ +static int +check_special_filename (const char *fname) +{ + if (special_names_enabled && fname && *fname == '-' && fname[1] == '&') + { + int i; + + fname += 2; + for (i = 0; isdigit (fname[i]); i++) + ; + if (!fname[i]) + return atoi (fname); + } + return -1; +} + +/**************** + * Create a head iobuf for reading from a file + * returns: NULL if an error occures and sets errno + */ +iobuf_t +iobuf_open (const char *fname) +{ + iobuf_t a; + FILEP_OR_FD fp; + file_filter_ctx_t *fcx; + size_t len; + int print_only = 0; + int fd; + + if (!fname || (*fname == '-' && !fname[1])) + { + fp = FILEP_OR_FD_FOR_STDIN; +#ifdef USE_SETMODE + setmode (my_fileno (fp), O_BINARY); +#endif + fname = "[stdin]"; + print_only = 1; + } + else if ((fd = check_special_filename (fname)) != -1) + return iobuf_fdopen (translate_file_handle (fd, 0), "rb"); + else if ((fp = my_fopen_ro (fname, "rb")) == INVALID_FP) + return NULL; + a = iobuf_alloc (1, 8192); + fcx = xmalloc (sizeof *fcx + strlen (fname)); + fcx->fp = fp; + fcx->print_only_name = print_only; + strcpy (fcx->fname, fname); + if (!print_only) + a->real_fname = xstrdup (fname); + a->filter = file_filter; + a->filter_ov = fcx; + file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: open `%s' fd=%d\n", + a->no, a->subno, fname, (int) my_fileno (fcx->fp)); + + return a; +} + +/**************** + * Create a head iobuf for reading from a file + * returns: NULL if an error occures and sets errno + */ +iobuf_t +iobuf_fdopen (int fd, const char *mode) +{ + iobuf_t a; + FILEP_OR_FD fp; + file_filter_ctx_t *fcx; + size_t len; + +#ifdef FILE_FILTER_USES_STDIO + if (!(fp = fdopen (fd, mode))) + return NULL; +#else + fp = (FILEP_OR_FD) fd; +#endif + a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192); + fcx = xmalloc (sizeof *fcx + 20); + fcx->fp = fp; + fcx->print_only_name = 1; + sprintf (fcx->fname, "[fd %d]", fd); + a->filter = file_filter; + a->filter_ov = fcx; + file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname); + iobuf_ioctl (a, 3, 1, NULL); /* disable fd caching */ + return a; +} + + +iobuf_t +iobuf_sockopen (int fd, const char *mode) +{ + iobuf_t a; +#ifdef __MINGW32__ + sock_filter_ctx_t *scx; + size_t len; + + a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192); + scx = m_alloc (sizeof *scx + 25); + scx->sock = fd; + scx->print_only_name = 1; + sprintf (scx->fname, "[sock %d]", fd); + a->filter = sock_filter; + a->filter_ov = scx; + sock_filter (scx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname); + iobuf_ioctl (a, 3, 1, NULL); /* disable fd caching */ +#else + a = iobuf_fdopen (fd, mode); +#endif + return a; +} + +/**************** + * create an iobuf for writing to a file; the file will be created. + */ +iobuf_t +iobuf_create (const char *fname) +{ + iobuf_t a; + FILEP_OR_FD fp; + file_filter_ctx_t *fcx; + size_t len; + int print_only = 0; + int fd; + + if (!fname || (*fname == '-' && !fname[1])) + { + fp = FILEP_OR_FD_FOR_STDOUT; +#ifdef USE_SETMODE + setmode (my_fileno (fp), O_BINARY); +#endif + fname = "[stdout]"; + print_only = 1; + } + else if ((fd = check_special_filename (fname)) != -1) + return iobuf_fdopen (translate_file_handle (fd, 1), "wb"); + else if ((fp = my_fopen (fname, "wb")) == INVALID_FP) + return NULL; + a = iobuf_alloc (2, 8192); + fcx = xmalloc (sizeof *fcx + strlen (fname)); + fcx->fp = fp; + fcx->print_only_name = print_only; + strcpy (fcx->fname, fname); + if (!print_only) + a->real_fname = xstrdup (fname); + a->filter = file_filter; + a->filter_ov = fcx; + file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc); + + return a; +} + +/**************** + * append to an iobuf; if the file does not exist, create it. + * cannot be used for stdout. + * Note: This is not used. + */ +#if 0 /* not used */ +iobuf_t +iobuf_append (const char *fname) +{ + iobuf_t a; + FILE *fp; + file_filter_ctx_t *fcx; + size_t len; + + if (!fname) + return NULL; + else if (!(fp = my_fopen (fname, "ab"))) + return NULL; + a = iobuf_alloc (2, 8192); + fcx = m_alloc (sizeof *fcx + strlen (fname)); + fcx->fp = fp; + strcpy (fcx->fname, fname); + a->real_fname = m_strdup (fname); + a->filter = file_filter; + a->filter_ov = fcx; + file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc); + + return a; +} +#endif + +iobuf_t +iobuf_openrw (const char *fname) +{ + iobuf_t a; + FILEP_OR_FD fp; + file_filter_ctx_t *fcx; + size_t len; + + if (!fname) + return NULL; + else if ((fp = my_fopen (fname, "r+b")) == INVALID_FP) + return NULL; + a = iobuf_alloc (2, 8192); + fcx = xmalloc (sizeof *fcx + strlen (fname)); + fcx->fp = fp; + strcpy (fcx->fname, fname); + a->real_fname = xstrdup (fname); + a->filter = file_filter; + a->filter_ov = fcx; + file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len); + file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc); + + return a; +} + + +int +iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval) +{ + if (cmd == 1) + { /* keep system filepointer/descriptor open */ + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: ioctl `%s' keep=%d\n", + a ? a->no : -1, a ? a->subno : -1, a ? a->desc : "?", + intval); + for (; a; a = a->chain) + if (!a->chain && a->filter == file_filter) + { + file_filter_ctx_t *b = a->filter_ov; + b->keep_open = intval; + return 0; + } +#ifdef __MINGW32__ + else if (!a->chain && a->filter == sock_filter) + { + sock_filter_ctx_t *b = a->filter_ov; + b->keep_open = intval; + return 0; + } +#endif + } + else if (cmd == 2) + { /* invalidate cache */ + if (DBG_IOBUF) + log_debug ("iobuf-*.*: ioctl `%s' invalidate\n", + ptrval ? (char *) ptrval : "?"); + if (!a && !intval && ptrval) + { +#ifndef FILE_FILTER_USES_STDIO + fd_cache_invalidate (ptrval); +#endif + return 0; + } + } + else if (cmd == 3) + { /* disallow/allow caching */ + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: ioctl `%s' no_cache=%d\n", + a ? a->no : -1, a ? a->subno : -1, a ? a->desc : "?", + intval); + for (; a; a = a->chain) + if (!a->chain && a->filter == file_filter) + { + file_filter_ctx_t *b = a->filter_ov; + b->no_cache = intval; + return 0; + } +#ifdef __MINGW32__ + else if (!a->chain && a->filter == sock_filter) + { + sock_filter_ctx_t *b = a->filter_ov; + b->no_cache = intval; + return 0; + } +#endif + } + + return -1; +} + + +/**************** + * Register an i/o filter. + */ +int +iobuf_push_filter (iobuf_t a, + int (*f) (void *opaque, int control, + iobuf_t chain, byte * buf, size_t * len), + void *ov) +{ + return iobuf_push_filter2 (a, f, ov, 0); +} + +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) +{ + iobuf_t b; + size_t dummy_len = 0; + int rc = 0; + + if (a->directfp) + BUG (); + + if (a->use == 2 && (rc = iobuf_flush (a))) + return rc; + /* make a copy of the current stream, so that + * A is the new stream and B the original one. + * The contents of the buffers are transferred to the + * new stream. + */ + b = xmalloc (sizeof *b); + memcpy (b, a, sizeof *b); + /* fixme: it is stupid to keep a copy of the name at every level + * but we need the name somewhere because the name known by file_filter + * may have been released when we need the name of the file */ + b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL; + /* remove the filter stuff from the new stream */ + a->filter = NULL; + a->filter_ov = NULL; + a->filter_ov_owner = 0; + a->filter_eof = 0; + if (a->use == 3) + a->use = 2; /* make a write stream from a temp stream */ + + if (a->use == 2) + { /* allocate a fresh buffer for the + original stream */ + b->d.buf = xmalloc (a->d.size); + b->d.len = 0; + b->d.start = 0; + } + else + { /* allocate a fresh buffer for the new + stream */ + a->d.buf = xmalloc (a->d.size); + a->d.len = 0; + a->d.start = 0; + } + /* disable nlimit for the new stream */ + a->ntotal = b->ntotal + b->nbytes; + a->nlimit = a->nbytes = 0; + a->nofast &= ~1; + /* make a link from the new stream to the original stream */ + a->chain = b; + a->opaque = b->opaque; + + /* setup the function on the new stream */ + a->filter = f; + a->filter_ov = ov; + a->filter_ov_owner = rel_ov; + + a->subno = b->subno + 1; + f (ov, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &dummy_len); + + if (DBG_IOBUF) + { + log_debug ("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc); + print_chain (a); + } + + /* now we can initialize the new function if we have one */ + if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain, + NULL, &dummy_len))) + log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc)); + return rc; +} + +/**************** + * Remove an i/o filter. + */ +int +pop_filter (iobuf_t a, int (*f) (void *opaque, int control, + iobuf_t chain, byte * buf, size_t * len), + void *ov) +{ + iobuf_t b; + size_t dummy_len = 0; + int rc = 0; + + if (a->directfp) + BUG (); + + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc); + if (!a->filter) + { /* this is simple */ + b = a->chain; + assert (b); + xfree (a->d.buf); + xfree (a->real_fname); + memcpy (a, b, sizeof *a); + xfree (b); + return 0; + } + for (b = a; b; b = b->chain) + if (b->filter == f && (!ov || b->filter_ov == ov)) + break; + if (!b) + log_bug ("pop_filter(): filter function not found\n"); + + /* flush this stream if it is an output stream */ + if (a->use == 2 && (rc = iobuf_flush (b))) + { + log_error ("iobuf_flush failed in pop_filter: %s\n", gpg_strerror (rc)); + return rc; + } + /* and tell the filter to free it self */ + if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain, + NULL, &dummy_len))) + { + log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc)); + return rc; + } + if (b->filter_ov && b->filter_ov_owner) + { + xfree (b->filter_ov); + b->filter_ov = NULL; + } + + + /* and see how to remove it */ + if (a == b && !b->chain) + log_bug ("can't remove the last filter from the chain\n"); + else if (a == b) + { /* remove the first iobuf from the chain */ + /* everything from b is copied to a. This is save because + * a flush has been done on the to be removed entry + */ + b = a->chain; + xfree (a->d.buf); + xfree (a->real_fname); + memcpy (a, b, sizeof *a); + xfree (b); + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno); + } + else if (!b->chain) + { /* remove the last iobuf from the chain */ + log_bug ("Ohh jeee, trying to remove a head filter\n"); + } + else + { /* remove an intermediate iobuf from the chain */ + log_bug ("Ohh jeee, trying to remove an intermediate filter\n"); + } + + return rc; +} + + +/**************** + * read underflow: read more bytes into the buffer and return + * the first byte or -1 on EOF. + */ +static int +underflow (iobuf_t a) +{ + size_t len; + int rc; + + assert (a->d.start == a->d.len); + if (a->use == 3) + return -1; /* EOF because a temp buffer can't do an underflow */ + + if (a->filter_eof) + { + if (a->chain) + { + iobuf_t b = a->chain; + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: pop `%s' in underflow\n", + a->no, a->subno, a->desc); + xfree (a->d.buf); + xfree (a->real_fname); + memcpy (a, b, sizeof *a); + xfree (b); + print_chain (a); + } + else + a->filter_eof = 0; /* for the top level filter */ + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: underflow: eof (due to filter eof)\n", + a->no, a->subno); + return -1; /* return one(!) EOF */ + } + if (a->error) + { + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: error\n", a->no, a->subno); + return -1; + } + + if (a->directfp) + { + FILE *fp = a->directfp; + + len = fread (a->d.buf, 1, a->d.size, fp); + if (len < a->d.size) + { + if (ferror (fp)) + a->error = gpg_error_from_errno (errno); + } + a->d.len = len; + a->d.start = 0; + return len ? a->d.buf[a->d.start++] : -1; + } + + + if (a->filter) + { + len = a->d.size; + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: underflow: req=%lu\n", + a->no, a->subno, (ulong) len); + rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain, + a->d.buf, &len); + if (DBG_IOBUF) + { + log_debug ("iobuf-%d.%d: underflow: got=%lu rc=%d\n", + a->no, a->subno, (ulong) len, rc); +/* if( a->no == 1 ) */ +/* log_hexdump (" data:", a->d.buf, len); */ + } + if (a->use == 1 && rc == -1) + { /* EOF: we can remove the filter */ + size_t dummy_len = 0; + + /* and tell the filter to free itself */ + if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain, + NULL, &dummy_len))) + log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc)); + if (a->filter_ov && a->filter_ov_owner) + { + xfree (a->filter_ov); + a->filter_ov = NULL; + } + a->filter = NULL; + a->desc = NULL; + a->filter_ov = NULL; + a->filter_eof = 1; + if (!len && a->chain) + { + iobuf_t b = a->chain; + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: pop `%s' in underflow (!len)\n", + a->no, a->subno, a->desc); + xfree (a->d.buf); + xfree (a->real_fname); + memcpy (a, b, sizeof *a); + xfree (b); + print_chain (a); + } + } + else if (rc) + a->error = rc; + + if (!len) + { + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: underflow: eof\n", a->no, a->subno); + return -1; + } + a->d.len = len; + a->d.start = 0; + return a->d.buf[a->d.start++]; + } + else + { + if (DBG_IOBUF) + log_debug ("iobuf-%d.%d: underflow: eof (no filter)\n", + a->no, a->subno); + return -1; /* no filter; return EOF */ + } +} + + +int +iobuf_flush (iobuf_t a) +{ + size_t len; + int rc; + + if (a->directfp) + return 0; + + if (a->use == 3) + { /* increase the temp buffer */ + char *newbuf; + size_t newsize = a->d.size + 8192; + + if (DBG_IOBUF) + log_debug ("increasing temp iobuf from %lu to %lu\n", + (ulong) a->d.size, (ulong) newsize); + newbuf = xmalloc (newsize); + memcpy (newbuf, a->d.buf, a->d.len); + xfree (a->d.buf); + a->d.buf = newbuf; + a->d.size = newsize; + return 0; + } + else if (a->use != 2) + log_bug ("flush on non-output iobuf\n"); + else if (!a->filter) + log_bug ("iobuf_flush: no filter\n"); + len = a->d.len; + rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len); + if (!rc && len != a->d.len) + { + log_info ("iobuf_flush did not write all!\n"); + rc = GPG_ERR_INTERNAL; + } + else if (rc) + a->error = rc; + a->d.len = 0; + + return rc; +} + + +/**************** + * Read a byte from the iobuf; returns -1 on EOF + */ +int +iobuf_readbyte (iobuf_t a) +{ + int c; + + /* nlimit does not work together with unget */ + /* nbytes is also not valid! */ + if (a->unget.buf) + { + if (a->unget.start < a->unget.len) + return a->unget.buf[a->unget.start++]; + xfree (a->unget.buf); + a->unget.buf = NULL; + a->nofast &= ~2; + } + + if (a->nlimit && a->nbytes >= a->nlimit) + return -1; /* forced EOF */ + + if (a->d.start < a->d.len) + { + c = a->d.buf[a->d.start++]; + } + else if ((c = underflow (a)) == -1) + return -1; /* EOF */ + + a->nbytes++; + return c; +} + + +int +iobuf_read (iobuf_t a, byte * buf, unsigned buflen) +{ + int c, n; + + if (a->unget.buf || a->nlimit) + { + /* handle special cases */ + for (n = 0; n < buflen; n++) + { + if ((c = iobuf_readbyte (a)) == -1) + { + if (!n) + return -1; /* eof */ + break; + } + else if (buf) + *buf = c; + if (buf) + buf++; + } + return n; + } + + n = 0; + do + { + if (n < buflen && a->d.start < a->d.len) + { + unsigned size = a->d.len - a->d.start; + if (size > buflen - n) + size = buflen - n; + if (buf) + memcpy (buf, a->d.buf + a->d.start, size); + n += size; + a->d.start += size; + if (buf) + buf += size; + } + if (n < buflen) + { + if ((c = underflow (a)) == -1) + { + a->nbytes += n; + return n ? n : -1 /*EOF*/; + } + if (buf) + *buf++ = c; + n++; + } + } + while (n < buflen); + a->nbytes += n; + return n; +} + + +/**************** + * Have a look at the iobuf. + * NOTE: This only works in special cases. + */ +int +iobuf_peek (iobuf_t a, byte * buf, unsigned buflen) +{ + int n = 0; + + if (a->filter_eof) + return -1; + + if (!(a->d.start < a->d.len)) + { + if (underflow (a) == -1) + return -1; + /* and unget this character */ + assert (a->d.start == 1); + a->d.start = 0; + } + + for (n = 0; n < buflen && (a->d.start + n) < a->d.len; n++, buf++) + *buf = a->d.buf[n]; + return n; +} + + + + +int +iobuf_writebyte (iobuf_t a, unsigned c) +{ + int rc; + + if (a->directfp) + BUG (); + + if (a->d.len == a->d.size) + if ((rc=iobuf_flush (a))) + return rc; + + assert (a->d.len < a->d.size); + a->d.buf[a->d.len++] = c; + return 0; +} + + +int +iobuf_write (iobuf_t a, byte * buf, unsigned buflen) +{ + int rc; + + if (a->directfp) + BUG (); + + do + { + if (buflen && a->d.len < a->d.size) + { + unsigned size = a->d.size - a->d.len; + if (size > buflen) + size = buflen; + memcpy (a->d.buf + a->d.len, buf, size); + buflen -= size; + buf += size; + a->d.len += size; + } + if (buflen) + { + rc = iobuf_flush (a); + if (rc) + return rc; + } + } + while (buflen); + return 0; +} + + +int +iobuf_writestr (iobuf_t a, const char *buf) +{ + int rc; + + for (; *buf; buf++) + if ((rc=iobuf_writebyte (a, *buf))) + return rc; + return 0; +} + + + +/**************** + * copy the contents of TEMP to A. + */ +int +iobuf_write_temp (iobuf_t a, iobuf_t temp) +{ + while (temp->chain) + pop_filter (temp, temp->filter, NULL); + return iobuf_write (a, temp->d.buf, temp->d.len); +} + +/**************** + * copy the contents of the temp io stream to BUFFER. + */ +size_t +iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen) +{ + size_t n = a->d.len; + + if (n > buflen) + n = buflen; + memcpy (buffer, a->d.buf, n); + return n; +} + + +/**************** + * Call this function to terminate processing of the temp stream + * without closing it. This removes all filters from the stream + * makes sure that iobuf_get_temp_{buffer,length}() returns correct + * values. + */ +void +iobuf_flush_temp (iobuf_t temp) +{ + while (temp->chain) + pop_filter (temp, temp->filter, NULL); +} + + +/**************** + * Set a limit on how many bytes may be read from the input stream A. + * Setting the limit to 0 disables this feature. + */ +void +iobuf_set_limit (iobuf_t a, off_t nlimit) +{ + if (nlimit) + a->nofast |= 1; + else + a->nofast &= ~1; + a->nlimit = nlimit; + a->ntotal += a->nbytes; + a->nbytes = 0; +} + + + +/**************** + * Return the length of an open file + */ +off_t +iobuf_get_filelength (iobuf_t a) +{ + struct stat st; + + if (a->directfp) + { + FILE *fp = a->directfp; + + if (!fstat (fileno (fp), &st)) + return st.st_size; + log_error ("fstat() failed: %s\n", strerror (errno)); + return 0; + } + + /* Hmmm: file_filter may have already been removed */ + for (; a; a = a->chain) + if (!a->chain && a->filter == file_filter) + { + file_filter_ctx_t *b = a->filter_ov; + FILEP_OR_FD fp = b->fp; + +#if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO) + ulong size; + + if ((size = GetFileSize (fp, NULL)) != 0xffffffff) + return size; + log_error ("GetFileSize for handle %p failed: ec=%d\n", + fp, (int) GetLastError ()); +#else + if (!fstat (my_fileno (fp), &st)) + return st.st_size; + log_error ("fstat() failed: %s\n", strerror (errno)); +#endif + break; + } + + return 0; +} + +/**************** + * Tell the file position, where the next read will take place + */ +off_t +iobuf_tell (iobuf_t a) +{ + return a->ntotal + a->nbytes; +} + + +#if !defined(HAVE_FSEEKO) && !defined(fseeko) + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif +#ifndef LONG_MAX +# define LONG_MAX ((long) ((unsigned long) -1 >> 1)) +#endif +#ifndef LONG_MIN +# define LONG_MIN (-1 - LONG_MAX) +#endif + +/**************** + * A substitute for fseeko, for hosts that don't have it. + */ +static int +fseeko (FILE * stream, off_t newpos, int whence) +{ + while (newpos != (long) newpos) + { + long pos = newpos < 0 ? LONG_MIN : LONG_MAX; + if (fseek (stream, pos, whence) != 0) + return -1; + newpos -= pos; + whence = SEEK_CUR; + } + return fseek (stream, (long) newpos, whence); +} +#endif + +/**************** + * This is a very limited implementation. It simply discards all internal + * buffering and removes all filters but the first one. + */ +int +iobuf_seek (iobuf_t a, off_t newpos) +{ + file_filter_ctx_t *b = NULL; + + if (a->directfp) + { + FILE *fp = a->directfp; + if (fseeko (fp, newpos, SEEK_SET)) + { + log_error ("can't seek: %s\n", strerror (errno)); + return -1; + } + clearerr (fp); + } + else + { + for (; a; a = a->chain) + { + if (!a->chain && a->filter == file_filter) + { + b = a->filter_ov; + break; + } + } + if (!a) + return -1; +#ifdef FILE_FILTER_USES_STDIO + if (fseeko (b->fp, newpos, SEEK_SET)) + { + log_error ("can't fseek: %s\n", strerror (errno)); + return -1; + } +#else +#ifdef HAVE_DOSISH_SYSTEM + if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff) + { + log_error ("SetFilePointer failed on handle %p: ec=%d\n", + b->fp, (int) GetLastError ()); + return -1; + } +#else + if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1) + { + log_error ("can't lseek: %s\n", strerror (errno)); + return -1; + } +#endif +#endif + } + a->d.len = 0; /* discard buffer */ + a->d.start = 0; + a->nbytes = 0; + a->nlimit = 0; + a->nofast &= ~1; + a->ntotal = newpos; + a->error = 0; + /* remove filters, but the last */ + if (a->chain) + log_debug ("pop_filter called in iobuf_seek - please report\n"); + while (a->chain) + pop_filter (a, a->filter, NULL); + + return 0; +} + + + + + + +/**************** + * Retrieve the real filename + */ +const char * +iobuf_get_real_fname (iobuf_t a) +{ + if (a->real_fname) + return a->real_fname; + + /* the old solution */ + for (; a; a = a->chain) + if (!a->chain && a->filter == file_filter) + { + file_filter_ctx_t *b = a->filter_ov; + return b->print_only_name ? NULL : b->fname; + } + + return NULL; +} + + +/**************** + * Retrieve the filename + */ +const char * +iobuf_get_fname (iobuf_t a) +{ + for (; a; a = a->chain) + if (!a->chain && a->filter == file_filter) + { + file_filter_ctx_t *b = a->filter_ov; + return b->fname; + } + + return NULL; +} + +/**************** + * Start the block write mode, see rfc1991.new for details. + * A value of 0 for N stops this mode (flushes and writes + * the end marker) + */ +void +iobuf_set_block_mode (iobuf_t a, size_t n) +{ + block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx); + + assert (a->use == 1 || a->use == 2); + ctx->use = a->use; + if (!n) + { + if (a->use == 1) + log_debug ("pop_filter called in set_block_mode - please report\n"); + pop_filter (a, block_filter, NULL); + } + else + { + ctx->size = n; /* only needed for use 2 */ + iobuf_push_filter (a, block_filter, ctx); + } +} + +/**************** + * enable partial block mode as described in the OpenPGP draft. + * LEN is the first length byte on read, but ignored on writes. + */ +void +iobuf_set_partial_block_mode (iobuf_t a, size_t len) +{ + block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx); + + assert (a->use == 1 || a->use == 2); + ctx->use = a->use; + if (!len) + { + if (a->use == 1) + log_debug ("pop_filter called in set_partial_block_mode" + " - please report\n"); + pop_filter (a, block_filter, NULL); + } + else + { + ctx->partial = 1; + ctx->size = 0; + ctx->first_c = len; + iobuf_push_filter (a, block_filter, ctx); + } +} + + +/**************** + * Checks whether the stream is in block mode + * Note: This does not work if other filters are pushed on the stream. + */ +int +iobuf_in_block_mode (iobuf_t a) +{ + if (a && a->filter == block_filter) + return 1; /* yes */ + return 0; /* no */ +} + + +/**************** + * Same as fgets() but if the buffer is too short a larger one will + * be allocated up to some limit *max_length. + * A line is considered a byte stream ending in a LF. + * Returns the length of the line. EOF is indicated by a line of + * length zero. The last LF may be missing due to an EOF. + * is max_length is zero on return, the line has been truncated. + * + * Note: The buffer is allocated with enough space to append a CR,LF,EOL + */ +unsigned int +iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, + unsigned *length_of_buffer, unsigned *max_length) +{ + int c; + char *buffer = *addr_of_buffer; + unsigned length = *length_of_buffer; + unsigned nbytes = 0; + unsigned maxlen = *max_length; + char *p; + + if (!buffer) + { /* must allocate a new buffer */ + length = 256; + buffer = xmalloc (length); + *addr_of_buffer = buffer; + *length_of_buffer = length; + } + + length -= 3; /* reserve 3 bytes (cr,lf,eol) */ + p = buffer; + while ((c = iobuf_get (a)) != -1) + { + if (nbytes == length) + { /* increase the buffer */ + if (length > maxlen) + { /* this is out limit */ + /* skip the rest of the line */ + while (c != '\n' && (c = iobuf_get (a)) != -1) + ; + *p++ = '\n'; /* always append a LF (we have reserved space) */ + nbytes++; + *max_length = 0; /* indicate truncation */ + break; + } + length += 3; /* correct for the reserved byte */ + length += length < 1024 ? 256 : 1024; + buffer = xrealloc (buffer, length); + *addr_of_buffer = buffer; + *length_of_buffer = length; + length -= 3; /* and reserve again */ + p = buffer + nbytes; + } + *p++ = c; + nbytes++; + if (c == '\n') + break; + } + *p = 0; /* make sure the line is a string */ + + return nbytes; +} + +/* This is the non iobuf specific function */ +int +iobuf_translate_file_handle (int fd, int for_write) +{ +#ifdef __MINGW32__ + { + int x; + + if (fd <= 2) + return fd; /* do not do this for error, stdin, stdout, stderr */ + + x = _open_osfhandle (fd, for_write ? 1 : 0); + if (x == -1) + log_error ("failed to translate osfhandle %p\n", (void *) fd); + else + { + /*log_info ("_open_osfhandle %p yields %d%s\n", + (void*)fd, x, for_write? " for writing":"" ); */ + fd = x; + } + } +#endif + return fd; +} + +static int +translate_file_handle (int fd, int for_write) +{ +#ifdef __MINGW32__ +#ifdef FILE_FILTER_USES_STDIO + fd = iobuf_translate_file_handle (fd, for_write); +#else + { + int x; + + if (fd == 0) + x = (int) GetStdHandle (STD_INPUT_HANDLE); + else if (fd == 1) + x = (int) GetStdHandle (STD_OUTPUT_HANDLE); + else if (fd == 2) + x = (int) GetStdHandle (STD_ERROR_HANDLE); + else + x = fd; + + if (x == -1) + log_debug ("GetStdHandle(%d) failed: ec=%d\n", + fd, (int) GetLastError ()); + + fd = x; + } +#endif +#endif + return fd; +} diff --git a/common/iobuf.h b/common/iobuf.h new file mode 100644 index 000000000..0af94e22d --- /dev/null +++ b/common/iobuf.h @@ -0,0 +1,170 @@ +/* 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*/ diff --git a/common/maperror.c b/common/maperror.c new file mode 100644 index 000000000..13657bece --- /dev/null +++ b/common/maperror.c @@ -0,0 +1,157 @@ +/* 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" + +/* Note: we might want to wrap this in a macro to get our hands on + the line and file where the error occured */ +int +map_ksba_err (int err) +{ + switch (err) + { + case -1: + case 0: + break; + + case KSBA_Out_Of_Core: err = GPG_ERR_ENOMEM; break; + case KSBA_Invalid_Value: err = GPG_ERR_INV_VALUE; break; + case KSBA_Not_Implemented: err = GPG_ERR_NOT_IMPLEMENTED; break; + case KSBA_Conflict: err = GPG_ERR_CONFLICT; break; + case KSBA_Read_Error: err = GPG_ERR_EIO; break; + case KSBA_Write_Error: err = GPG_ERR_EIO; break; + case KSBA_No_Data: err = GPG_ERR_NO_DATA; break; + case KSBA_Bug: err = GPG_ERR_BUG; break; + case KSBA_Unsupported_Algorithm: err = GPG_ERR_UNSUPPORTED_ALGORITHM; break; + case KSBA_Invalid_Index: err = GPG_ERR_INV_INDEX; break; + case KSBA_Invalid_Sexp: err = GPG_ERR_INV_SEXP; break; + case KSBA_Unknown_Sexp: err = GPG_ERR_UNKNOWN_SEXP; break; + + default: + err = GPG_ERR_GENERAL; + break; + } + return err; +} + + +int +map_gcry_err (int err) +{ + return err; +} + +int +map_kbx_err (int err) +{ + return err; +} + +/* 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; + + 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); +} + + + + + + + + + + + diff --git a/common/membuf.c b/common/membuf.c new file mode 100644 index 000000000..69e4ab908 --- /dev/null +++ b/common/membuf.c @@ -0,0 +1,89 @@ +/* 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; +} diff --git a/common/membuf.h b/common/membuf.h new file mode 100644 index 000000000..c199363cc --- /dev/null +++ b/common/membuf.h @@ -0,0 +1,41 @@ +/* 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*/ diff --git a/common/miscellaneous.c b/common/miscellaneous.c new file mode 100644 index 000000000..bdb12c574 --- /dev/null +++ b/common/miscellaneous.c @@ -0,0 +1,126 @@ +/* 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; +} + + + diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c new file mode 100644 index 000000000..afdc4e2a4 --- /dev/null +++ b/common/simple-pwquery.c @@ -0,0 +1,486 @@ +/* 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 ) + { +#ifdef SPWQ_USE_LOGGING + log_error (_("gpg-agent is not available in this session\n")); +#endif + return SPWQ_NO_AGENT; + } + + 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 poiinter 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; + char *p = buffer; + + for (i=0; text[i]; i++) + { + if (text[i] < ' ' || text[i] == '+') + { + sprintf (p, "%%%02X", text[i]); + p += 3; + } + else if (text[i] == ' ') + *p++ = '+'; + else + *p++ = text[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; +} diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h new file mode 100644 index 000000000..5947c42b5 --- /dev/null +++ b/common/simple-pwquery.h @@ -0,0 +1,69 @@ +/* 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*/ diff --git a/common/ttyio.c b/common/ttyio.c new file mode 100644 index 000000000..fd748009e --- /dev/null +++ b/common/ttyio.c @@ -0,0 +1,508 @@ +/* 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 __MINGW32__ /* 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 __MINGW32__ /* 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(__MINGW32__) + { + 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 __MINGW32__ + { + 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( byte *p, size_t n ) +{ + if (no_terminal) + return; + + if( !initialized ) + init_ttyfp(); + +#ifdef __MINGW32__ + /* 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( 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( 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 __MINGW32__ /* 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 __MINGW32__ + 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; +} diff --git a/common/ttyio.h b/common/ttyio.h new file mode 100644 index 000000000..b3ca7dcaf --- /dev/null +++ b/common/ttyio.h @@ -0,0 +1,40 @@ +/* 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))); +#else +void tty_printf (const char *fmt, ... ); +#endif +void tty_print_string (unsigned char *p, size_t n); +void tty_print_utf8_string (unsigned char *p, size_t n); +void tty_print_utf8_string2 (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*/ diff --git a/common/util.h b/common/util.h new file mode 100644 index 000000000..045851481 --- /dev/null +++ b/common/util.h @@ -0,0 +1,120 @@ +/* util.h - Utility functions for Gnupg + * 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 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 - use only them */ +#define xtrymalloc(a) gcry_malloc ((a)) +#define xtrycalloc(a,b) gcry_calloc ((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)) + +/*-- maperror.c --*/ +int map_ksba_err (int err); +int map_gcry_err (int err); +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_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 */ + +/*-- 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); + + +/*-- miscellaneous.c --*/ +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, ...); +#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')) +/* 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)) + + + +#endif /*GNUPG_COMMON_UTIL_H*/ diff --git a/common/yesno.c b/common/yesno.c new file mode 100644 index 000000000..2a96b4e5d --- /dev/null +++ b/common/yesno.c @@ -0,0 +1,96 @@ +/* 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; +} diff --git a/kbx/Makefile.am b/kbx/Makefile.am new file mode 100644 index 000000000..4f0c40043 --- /dev/null +++ b/kbx/Makefile.am @@ -0,0 +1,52 @@ +# Keybox Makefile +# 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 + +## Process this file with automake to produce Makefile.in + +localedir = $(datadir)/locale +INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" + +EXTRA_DIST = mkerrors +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \ + $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) + +noinst_LIBRARIES = libkeybox.a +bin_PROGRAMS = kbxutil + +common_sources = \ + keybox.h keybox-defs.h keybox-search-desc.h \ + keybox-util.c \ + keybox-init.c \ + keybox-blob.c \ + keybox-file.c \ + keybox-search.c \ + keybox-update.c \ + keybox-dump.c + + +libkeybox_a_SOURCES = $(common_sources) + +kbxutil_SOURCES = kbxutil.c $(common_sources) +kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ + -lgpg-error @INTLLIBS@ + + + + + diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c new file mode 100644 index 000000000..abca4faa9 --- /dev/null +++ b/kbx/kbxutil.c @@ -0,0 +1,339 @@ +/* kbxutil.c - The Keybox utility + * Copyright (C) 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include "../jnlib/logging.h" +#include "../jnlib/argparse.h" +#include "../jnlib/stringhelp.h" +#include "../common/i18n.h" +#include "keybox-defs.h" + +#include <gcrypt.h> + + +enum cmd_and_opt_values { + aNull = 0, + oArmor = 'a', + oDryRun = 'n', + oOutput = 'o', + oQuiet = 'q', + oVerbose = 'v', + + aNoSuchCmd = 500, /* force other values not to be a letter */ + aFindByFpr, + aFindByKid, + aFindByUid, + + oDebug, + oDebugAll, + + oNoArmor, + + + aTest +}; + + +static ARGPARSE_OPTS opts[] = { + { 300, NULL, 0, N_("@Commands:\n ") }, + + { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, + { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, + { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, + + { 301, NULL, 0, N_("@\nOptions:\n ") }, + + { oArmor, "armor", 0, N_("create ascii armored output")}, + { oArmor, "armour", 0, "@" }, + { oOutput, "output", 2, N_("use as output file")}, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oDryRun, "dry-run", 0, N_("do not make any changes") }, + + { oDebug, "debug" ,4|16, N_("set debugging flags")}, + { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, + + {0} /* end of list */ +}; + + +void myexit (int rc); + +int keybox_errors_seen = 0; + + +static const char * +my_strusage( int level ) +{ + const char *p; + switch( level ) { + case 11: p = "kbxutil (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = + _("Please report bugs to " PACKAGE_BUGREPORT ".\n"); + break; + case 1: + case 40: p = + _("Usage: kbxutil [options] [files] (-h for help)"); + break; + case 41: p = + _("Syntax: kbxutil [options] [files]\n" + "list, export, import Keybox data\n"); + break; + + + default: p = NULL; + } + return p; +} + + +static void +i18n_init(void) +{ + #ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE ); + #else + #ifdef ENABLE_NLS + #ifdef HAVE_LC_MESSAGES + setlocale( LC_TIME, "" ); + setlocale( LC_MESSAGES, "" ); + #else + setlocale( LC_ALL, "" ); + #endif + bindtextdomain( PACKAGE, LOCALEDIR ); + textdomain( PACKAGE ); + #endif + #endif +} + + +/* static void */ +/* wrong_args( const char *text ) */ +/* { */ +/* log_error("usage: kbxutil %s\n", text); */ +/* myexit ( 1 ); */ +/* } */ + + +#if 0 +static int +hextobyte( const byte *s ) +{ + int c; + + if( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if( *s >= 'a' && *s <= 'f' ) + c = 16 * (10 + *s - 'a'); + else + return -1; + s++; + if( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if( *s >= 'a' && *s <= 'f' ) + c += 10 + *s - 'a'; + else + return -1; + return c; +} +#endif + +#if 0 +static char * +format_fingerprint ( const char *s ) +{ + int i, c; + byte fpr[20]; + + for (i=0; i < 20 && *s; ) { + if ( *s == ' ' || *s == '\t' ) { + s++; + continue; + } + c = hextobyte(s); + if (c == -1) { + return NULL; + } + fpr[i++] = c; + s += 2; + } + return gcry_xstrdup ( fpr ); +} +#endif + +#if 0 +static int +format_keyid ( const char *s, u32 *kid ) +{ + char helpbuf[9]; + switch ( strlen ( s ) ) { + case 8: + kid[0] = 0; + kid[1] = strtoul( s, NULL, 16 ); + return 10; + + case 16: + mem2str( helpbuf, s, 9 ); + kid[0] = strtoul( helpbuf, NULL, 16 ); + kid[1] = strtoul( s+8, NULL, 16 ); + return 11; + } + return 0; /* error */ +} +#endif + + +int +main( int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + enum cmd_and_opt_values cmd = 0; + + set_strusage( my_strusage ); + /*log_set_name("kbxutil"); fixme */ +#if 0 + /* check that the libraries are suitable. Do it here because + * the option parse may need services of the library */ + if ( !gcry_check_version ( "1.1.4" ) ) + { + log_fatal(_("libgcrypt is too old (need %s, have %s)\n"), + "1.1.4", gcry_check_version(NULL) ); + } +#endif + + /*create_dotlock(NULL); register locking cleanup */ + i18n_init(); + + /* We need to use the gcry malloc function because jnlib does use them */ + keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); + + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + while (arg_parse( &pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: + /*opt.verbose++;*/ + /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/ + break; + case oDebug: + /*opt.debug |= pargs.r.ret_ulong; */ + break; + case oDebugAll: + /*opt.debug = ~0;*/ + break; + + case aFindByFpr: + case aFindByKid: + case aFindByUid: + cmd = pargs.r_opt; + break; + + default: + pargs.err = 2; + break; + } + } + if (log_get_errorcount(0) ) + myexit(2); + + if (!cmd) + { /* default is to list a KBX file */ + if (!argc) + _keybox_dump_file (NULL, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_file (*argv, stdout); + } + } +#if 0 + else if ( cmd == aFindByFpr ) { + char *fpr; + if ( argc != 2 ) + wrong_args ("kbxfile foingerprint"); + fpr = format_fingerprint ( argv[1] ); + if ( !fpr ) + log_error ("invalid formatted fingerprint\n"); + else { + kbxfile_search_by_fpr ( argv[0], fpr ); + gcry_free ( fpr ); + } + } + else if ( cmd == aFindByKid ) { + u32 kid[2]; + int mode; + + if ( argc != 2 ) + wrong_args ("kbxfile short-or-long-keyid"); + mode = format_keyid ( argv[1], kid ); + if ( !mode ) + log_error ("invalid formatted keyID\n"); + else { + kbxfile_search_by_kid ( argv[0], kid, mode ); + } + } + else if ( cmd == aFindByUid ) { + if ( argc != 2 ) + wrong_args ("kbxfile userID"); + kbxfile_search_by_uid ( argv[0], argv[1] ); + } +#endif + else + log_error ("unsupported action\n"); + + myexit(0); + return 8; /*NEVER REACHED*/ +} + + +void +myexit( int rc ) +{ + /* if( opt.debug & DBG_MEMSTAT_VALUE ) {*/ +/* gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); */ +/* gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); */ + /* }*/ +/* if( opt.debug ) */ +/* gcry_control( GCRYCTL_DUMP_SECMEM_STATS ); */ + rc = rc? rc : log_get_errorcount(0)? 2 : + keybox_errors_seen? 1 : 0; + exit(rc ); +} + + diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c new file mode 100644 index 000000000..5ad1d2610 --- /dev/null +++ b/kbx/keybox-blob.c @@ -0,0 +1,1008 @@ +/* keybox-blob.c - KBX Blob handling + * Copyright (C) 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 + */ + + +/* The keybox data formats + +The KeyBox uses an augmented OpenPGP/X.509 key format. This makes +random access to a keyblock/Certificate easier and also gives the +opportunity to store additional information (e.g. the fingerprint) +along with the key. All integers are stored in network byte order, +offsets are counted from the beginning of the Blob. + +The first record of a plain KBX file has a special format: + + u32 length of the first record + byte Blob type (1) + byte version number (1) + byte reserved + byte reserved + u32 magic 'KBXf' + byte pgp_marginals used for validity calculation of this file + byte pgp_completes ditto. + byte pgp_cert_depth ditto. + +The OpenPGP and X.509 blob are verry similiar, things which are +X.509 specific are noted like [X.509: xxx] + + u32 length of this blob (including these 4 bytes) + byte Blob type (2) [X509: 3] + byte version number of this blob type (1) + u16 Blob flags + bit 0 = contains secret key material + bit 1 = ephemeral blob (e.g. used while quering external resources) + + u32 offset to the OpenPGP keyblock or X509 DER encoded certificate + u32 and its length + u16 number of keys (at least 1!) [X509: always 1] + u16 size of additional key information + n times: + b20 The keys fingerprint + (fingerprints are always 20 bytes, MD5 left padded with zeroes) + u32 offset to the n-th key's keyID (a keyID is always 8 byte) + or 0 if not known which is the case opnly for X509. + u16 special key flags + bit 0 = + u16 reserved + u16 size of serialnumber(may be zero) + n u16 (see above) bytes of serial number + u16 number of user IDs + u16 size of additional user ID information + n times: + u32 offset to the n-th user ID + u32 length of this user ID. + u16 special user ID flags. + bit 0 = + byte validity + byte reserved + [For X509, the first user ID is the ISsuer, the second the subject + and the others are subjectAltNames] + u16 number of signatures + u16 size of signature information (4) + u32 expiration time of signature with some special values: + 0x00000000 = not checked + 0x00000001 = missing key + 0x00000002 = bad signature + 0x10000000 = valid and expires at some date in 1978. + 0xffffffff = valid and does not expire + u8 assigned ownertrust [X509: no used] + u8 all_validity [X509: no used] + u16 reserved + u32 recheck_after + u32 Newest timestamp in the keyblock (useful for KS syncronsiation?) + u32 Blob created at + u32 size of reserved space (not including this field) + reserved space + + Here we might want to put other data + + Here comes the keyblock + + maybe we put a signature here later. + + b16 MD5 checksum (useful for KS syncronisation), we might also want to use + a mac here. + b4 resevered + +*/ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "keybox-defs.h" +#include <gcrypt.h> + +#ifdef KEYBOX_WITH_OPENPGP +/* include stuff to parse the packets */ +#endif +#ifdef KEYBOX_WITH_X509 +#include <ksba.h> +#endif + + + +/* special values of the signature status */ +#define SF_NONE(a) ( !(a) ) +#define SF_NOKEY(a) ((a) & (1<<0)) +#define SF_BAD(a) ((a) & (1<<1)) +#define SF_VALID(a) ((a) & (1<<29)) + + +struct membuf { + size_t len; + size_t size; + char *buf; + int out_of_core; +}; + + +/* #if MAX_FINGERPRINT_LEN < 20 */ +/* #error fingerprints are 20 bytes */ +/* #endif */ + +struct keyboxblob_key { + char fpr[20]; + u32 off_kid; + ulong off_kid_addr; + u16 flags; +}; +struct keyboxblob_uid { + ulong off_addr; + char *name; /* used only with x509 */ + u32 len; + u16 flags; + byte validity; +}; + +struct keyid_list { + struct keyid_list *next; + int seqno; + byte kid[8]; +}; + +struct fixup_list { + struct fixup_list *next; + u32 off; + u32 val; +}; + + +struct keyboxblob { + byte *blob; + size_t bloblen; + off_t fileoffset; + + /* stuff used only by keybox_create_blob */ + unsigned char *serialbuf; + const unsigned char *serial; + size_t seriallen; + int nkeys; + struct keyboxblob_key *keys; + int nuids; + struct keyboxblob_uid *uids; + int nsigs; + u32 *sigs; + struct fixup_list *fixups; + int fixup_out_of_core; + + struct keyid_list *temp_kids; + struct membuf bufbuf; /* temporary store for the blob */ + struct membuf *buf; +}; + + + +/* A simple implemnation 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. */ + +static void +init_membuf (struct membuf *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 = 1; +} + +static void +put_membuf (struct membuf *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 = 1; + return; + } + mb->buf = p; + } + memcpy (mb->buf + mb->len, buf, len); + mb->len += len; +} + +static void * +get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ + return p; +} + + +static void +put8 (struct membuf *mb, byte a ) +{ + put_membuf (mb, &a, 1); +} + +static void +put16 (struct membuf *mb, u16 a ) +{ + unsigned char tmp[2]; + tmp[0] = a>>8; + tmp[1] = a; + put_membuf (mb, tmp, 2); +} + +static void +put32 (struct membuf *mb, u32 a ) +{ + unsigned char tmp[4]; + tmp[0] = a>>24; + tmp[1] = a>>16; + tmp[2] = a>>8; + tmp[3] = a; + put_membuf (mb, tmp, 4); +} + + +/* Store a value in the fixup list */ +static void +add_fixup (KEYBOXBLOB blob, u32 off, u32 val) +{ + struct fixup_list *fl; + + if (blob->fixup_out_of_core) + return; + + fl = xtrycalloc(1, sizeof *fl); + if (!fl) + blob->fixup_out_of_core = 1; + else + { + fl->off = off; + fl->val = val; + fl->next = blob->fixups; + blob->fixups = fl; + } +} + + +/* + Some wrappers +*/ + +static u32 +make_timestamp (void) +{ + return time(NULL); +} + + + +#ifdef KEYBOX_WITH_OPENPGP +/* + OpenPGP specific stuff +*/ + + +/* + We must store the keyid at some place because we can't calculate the + offset yet. This is only used for v3 keyIDs. Function returns an + index value for later fixup or -1 for out of core. The value must be + a non-zero value */ +static int +pgp_temp_store_kid (KEYBOXBLOB blob, PKT_public_key *pk) +{ + struct keyid_list *k, *r; + + k = xtrymalloc (sizeof *k); + if (!k) + return -1; + k->kid[0] = pk->keyid[0] >> 24 ; + k->kid[1] = pk->keyid[0] >> 16 ; + k->kid[2] = pk->keyid[0] >> 8 ; + k->kid[3] = pk->keyid[0] ; + k->kid[4] = pk->keyid[0] >> 24 ; + k->kid[5] = pk->keyid[0] >> 16 ; + k->kid[6] = pk->keyid[0] >> 8 ; + k->kid[7] = pk->keyid[0] ; + k->seqno = 0; + k->next = blob->temp_kids; + blob->temp_kids = k; + for (r=k; r; r = r->next) + k->seqno++; + + return k->seqno; +} + +static int +pgp_create_key_part (KEYBOXBLOB blob, KBNODE keyblock) +{ + KBNODE node; + size_t fprlen; + int n; + + for (n=0, node = keyblock; node; node = node->next) + { + if ( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + { + PKT_public_key *pk = node->pkt->pkt.public_key; + char tmp[20]; + + fingerprint_from_pk (pk, tmp , &fprlen); + memcpy (blob->keys[n].fpr, tmp, 20); + if ( fprlen != 20 ) /*v3 fpr - shift right and fill with zeroes*/ + { + assert (fprlen == 16); + memmove (blob->keys[n].fpr+4, blob->keys[n].fpr, 16); + memset (blob->keys[n].fpr, 0, 4); + blob->keys[n].off_kid = pgp_temp_store_kid (blob, pk); + } + else + { + blob->keys[n].off_kid = 0; /* will be fixed up later */ + } + blob->keys[n].flags = 0; + n++; + } + else if ( node->pkt->pkttype == PKT_SECRET_KEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) + { + never_reached (); /* actually not yet implemented */ + } + } + assert (n == blob->nkeys); + return 0; +} + +static int +pgp_create_uid_part (KEYBOXBLOB blob, KBNODE keyblock) +{ + KBNODE node; + int n; + + for (n=0, node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_USER_ID) + { + PKT_user_id *u = node->pkt->pkt.user_id; + + blob->uids[n].len = u->len; + blob->uids[n].flags = 0; + blob->uids[n].validity = 0; + n++; + } + } + assert (n == blob->nuids); + return 0; +} + +static int +pgp_create_sig_part (KEYBOXBLOB blob, KBNODE keyblock) +{ + KBNODE node; + int n; + + for (n=0, node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_SIGNATURE) + { + PKT_signature *sig = node->pkt->pkt.signature; + + blob->sigs[n] = 0; /* FIXME: check the signature here */ + n++; + } + } + assert( n == blob->nsigs ); + return 0; +} + +static int +pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) +{ + struct membuf *a = blob->buf; + KBNODE node; + int rc; + int n; + u32 kbstart = a->len; + + add_fixup (blob, kbstart); + + for (n = 0, node = keyblock; node; node = node->next) + { + rc = build_packet ( a, node->pkt ); + if ( rc ) { + gpg_log_error ("build_packet(%d) for keyboxblob failed: %s\n", + node->pkt->pkttype, gpg_errstr(rc) ); + return GPGERR_WRITE_FILE; + } + if ( node->pkt->pkttype == PKT_USER_ID ) + { + PKT_user_id *u = node->pkt->pkt.user_id; + /* build_packet has set the offset of the name into u ; + * now we can do the fixup */ + add_fixup (blob, blob->uids[n].off_addr, u->stored_at); + n++; + } + } + assert (n == blob->nuids); + + add_fixup (blob, a->len - kbstart); + return 0; +} + +#endif /*KEYBOX_WITH_OPENPGP*/ + + +#ifdef KEYBOX_WITH_X509 +/* + X.509 specific stuff + */ + +/* Write the raw certificate out */ +static int +x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert) +{ + struct membuf *a = blob->buf; + const unsigned char *image; + size_t length; + u32 kbstart = a->len; + + /* Store our offset for later fixup */ + add_fixup (blob, 8, kbstart); + + image = ksba_cert_get_image (cert, &length); + if (!image) + return gpg_error (GPG_ERR_GENERAL); + put_membuf (a, image, length); + + add_fixup (blob, 12, a->len - kbstart); + return 0; +} + +#endif /*KEYBOX_WITH_X509*/ + +/* Write a stored keyID out to the buffer */ +static void +write_stored_kid (KEYBOXBLOB blob, int seqno) +{ + struct keyid_list *r; + + for ( r = blob->temp_kids; r; r = r->next ) + { + if (r->seqno == seqno ) + { + put_membuf (blob->buf, r->kid, 8); + return; + } + } + never_reached (); +} + +/* Release a list of key IDs */ +static void +release_kid_list (struct keyid_list *kl) +{ + struct keyid_list *r, *r2; + + for ( r = kl; r; r = r2 ) + { + r2 = r->next; + xfree (r); + } +} + + + +static int +create_blob_header (KEYBOXBLOB blob, int blobtype, int as_ephemeral) +{ + struct membuf *a = blob->buf; + int i; + + put32 ( a, 0 ); /* blob length, needs fixup */ + put8 ( a, blobtype); + put8 ( a, 1 ); /* blob type version */ + put16 ( a, as_ephemeral? 2:0 ); /* blob flags */ + + put32 ( a, 0 ); /* offset to the raw data, needs fixup */ + put32 ( a, 0 ); /* length of the raw data, needs fixup */ + + put16 ( a, blob->nkeys ); + put16 ( a, 20 + 4 + 2 + 2 ); /* size of key info */ + for ( i=0; i < blob->nkeys; i++ ) + { + put_membuf (a, blob->keys[i].fpr, 20); + blob->keys[i].off_kid_addr = a->len; + put32 ( a, 0 ); /* offset to keyid, fixed up later */ + put16 ( a, blob->keys[i].flags ); + put16 ( a, 0 ); /* reserved */ + } + + put16 (a, blob->seriallen); /*fixme: check that it fits into 16 bits*/ + if (blob->serial) + put_membuf (a, blob->serial, blob->seriallen); + + put16 ( a, blob->nuids ); + put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */ + for (i=0; i < blob->nuids; i++) + { + blob->uids[i].off_addr = a->len; + put32 ( a, 0 ); /* offset to userid, fixed up later */ + put32 ( a, blob->uids[i].len ); + put16 ( a, blob->uids[i].flags ); + put8 ( a, 0 ); /* validity */ + put8 ( a, 0 ); /* reserved */ + } + + put16 ( a, blob->nsigs ); + put16 ( a, 4 ); /* size of sig info */ + for (i=0; i < blob->nsigs; i++) + { + put32 ( a, blob->sigs[i]); + } + + put8 ( a, 0 ); /* assigned ownertrust */ + put8 ( a, 0 ); /* validity of all user IDs */ + put16 ( a, 0 ); /* reserved */ + put32 ( a, 0 ); /* time of next recheck */ + put32 ( a, 0 ); /* newest timestamp (none) */ + put32 ( a, make_timestamp() ); /* creation time */ + put32 ( a, 0 ); /* size of reserved space */ + /* reserved space (which is currently of size 0) */ + + /* space where we write keyIDs and and other stuff so that the + pointers can actually point to somewhere */ + if (blobtype == BLOBTYPE_PGP) + { + /* We need to store the keyids for all pgp v3 keys because those key + IDs are not part of the fingerprint. While we are doing that, we + fixup all the keyID offsets */ + for (i=0; i < blob->nkeys; i++ ) + { + if (blob->keys[i].off_kid) + { /* this is a v3 one */ + add_fixup (blob, blob->keys[i].off_kid_addr, a->len); + write_stored_kid (blob, blob->keys[i].off_kid); + } + else + { /* the better v4 key IDs - just store an offset 8 bytes back */ + add_fixup (blob, blob->keys[i].off_kid_addr, + blob->keys[i].off_kid_addr - 8); + } + } + } + + if (blobtype == BLOBTYPE_X509) + { + /* We don't want to point to ASN.1 encoded UserIDs (DNs) but to + the utf-8 string represenation of them */ + for (i=0; i < blob->nuids; i++ ) + { + if (blob->uids[i].name) + { /* this is a v3 one */ + add_fixup (blob, blob->uids[i].off_addr, a->len); + put_membuf (blob->buf, blob->uids[i].name, blob->uids[i].len); + } + } + } + + return 0; +} + + + +static int +create_blob_trailer (KEYBOXBLOB blob) +{ + return 0; +} + + +static int +create_blob_finish (KEYBOXBLOB blob) +{ + struct membuf *a = blob->buf; + byte *p; + char *pp; + int i; + size_t n; + + /* write a placeholder for the checksum */ + for (i = 0; i < 16; i++ ) + put32 (a, 0); /* Hmmm: why put32() ?? */ + + /* get the memory area */ + p = get_membuf (a, &n); + if (!p) + return gpg_error (GPG_ERR_ENOMEM); + assert (n >= 20); + + /* fixup the length */ + add_fixup (blob, 0, n); + + /* do the fixups */ + if (blob->fixup_out_of_core) + return gpg_error (GPG_ERR_ENOMEM); + + { + struct fixup_list *fl; + for (fl = blob->fixups; fl; fl = fl->next) + { + assert (fl->off+4 <= n); + p[fl->off+0] = fl->val >> 24; + p[fl->off+1] = fl->val >> 16; + p[fl->off+2] = fl->val >> 8; + p[fl->off+3] = fl->val; + } + } + + /* calculate and store the MD5 checksum */ + gcry_md_hash_buffer (GCRY_MD_MD5, p + n - 16, p, n - 16); + + pp = xtrymalloc (n); + if ( !pp ) + return gpg_error (gpg_err_code_from_errno (errno)); + memcpy (pp , p, n); + blob->blob = pp; + blob->bloblen = n; + + return 0; +} + + +#ifdef KEYBOX_WITH_OPENPGP + +int +_keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral) +{ + int rc = 0; + KBNODE node; + KEYBOXBLOB blob; + + *r_blob = NULL; + blob = xtrycalloc (1, sizeof *blob); + if (!blob) + return gpg_error (gpg_err_code_from_errno (errno)); + + /* fixme: Do some sanity checks on the keyblock */ + + /* count userids and keys so that we can allocate the arrays */ + for (node = keyblock; node; node = node->next) + { + switch (node->pkt->pkttype) + { + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + case PKT_PUBLIC_SUBKEY: + case PKT_SECRET_SUBKEY: blob->nkeys++; break; + case PKT_USER_ID: blob->nuids++; break; + case PKT_SIGNATURE: blob->nsigs++; break; + default: break; + } + } + + blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys ); + blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids ); + blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs ); + if (!blob->keys || !blob->uids || !blob->sigs) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + rc = pgp_create_key_part ( blob, keyblock ); + if (rc) + goto leave; + rc = pgp_create_uid_part ( blob, keyblock ); + if (rc) + goto leave; + rc = pgp_create_sig_part ( blob, keyblock ); + if (rc) + goto leave; + + init_membuf (&blob->bufbuf, 1024); + blob->buf = &blob->bufbuf; + rc = create_blob_header (blob, BLOBTYPE_OPENPGP, as_ephemeral); + if (rc) + goto leave; + rc = pgp_create_blob_keyblock (blob, keyblock); + if (rc) + goto leave; + rc = create_blob_trailer (blob); + if (rc) + goto leave; + rc = create_blob_finish ( blob ); + if (rc) + goto leave; + + + leave: + release_kid_list (blob->temp_kids); + blob->temp_kids = NULL; + if (rc) + { + keybox_release_blob (blob); + *r_blob = NULL; + } + else + { + *r_blob = blob; + } + return rc; +} +#endif /*KEYBOX_WITH_OPENPGP*/ + +#ifdef KEYBOX_WITH_X509 + +/* return an allocated string with the email address extracted from a + DN */ +static char * +x509_email_kludge (const char *name) +{ + const unsigned char *p; + unsigned char *buf; + int n; + + if (strncmp (name, "1.2.840.113549.1.9.1=#", 22)) + return NULL; + /* This looks pretty much like an email address in the subject's DN + we use this to add an additional user ID entry. This way, + openSSL generated keys get a nicer and usable listing */ + name += 22; + for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++) + ; + if (*p != '#' || !n) + return NULL; + buf = xtrymalloc (n+3); + if (!buf) + return NULL; /* oops, out of core */ + *buf = '<'; + for (n=1, p=name; *p != '#'; p +=2, n++) + buf[n] = xtoi_2 (p); + buf[n++] = '>'; + buf[n] = 0; + return buf; +} + + + +/* Note: We should move calculation of the digest into libksba and + remove that parameter */ +int +_keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert, + unsigned char *sha1_digest, int as_ephemeral) +{ + int i, rc = 0; + KEYBOXBLOB blob; + unsigned char *p; + unsigned char **names = NULL; + size_t max_names; + + *r_blob = NULL; + blob = xtrycalloc (1, sizeof *blob); + if( !blob ) + return gpg_error (gpg_err_code_from_errno (errno)); + + p = ksba_cert_get_serial (cert); + if (p) + { + size_t n, len; + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (n < 2) + { + xfree (p); + return gpg_error (GPG_ERR_GENERAL); + } + blob->serialbuf = p; + p++; n--; /* skip '(' */ + for (len=0; n && *p && *p != ':' && digitp (p); n--, p++) + len = len*10 + atoi_1 (p); + if (*p != ':') + { + xfree (blob->serialbuf); + blob->serialbuf = NULL; + return gpg_error (GPG_ERR_GENERAL); + } + p++; + blob->serial = p; + blob->seriallen = len; + } + + blob->nkeys = 1; + + /* create list of names */ + blob->nuids = 0; + max_names = 100; + names = xtrymalloc (max_names * sizeof *names); + if (!names) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + p = ksba_cert_get_issuer (cert, 0); + if (!p) + { + rc = gpg_error (GPG_ERR_MISSING_VALUE); + goto leave; + } + names[blob->nuids++] = p; + for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) + { + + if (blob->nuids >= max_names) + { + unsigned char **tmp; + + max_names += 100; + tmp = xtryrealloc (names, max_names * sizeof *names); + if (!tmp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + } + names[blob->nuids++] = p; + if (!i && (p=x509_email_kludge (p))) + names[blob->nuids++] = p; /* due to !i we don't need to check bounds*/ + } + + /* space for signature information */ + blob->nsigs = 1; + + blob->keys = xtrycalloc (blob->nkeys, sizeof *blob->keys ); + blob->uids = xtrycalloc (blob->nuids, sizeof *blob->uids ); + blob->sigs = xtrycalloc (blob->nsigs, sizeof *blob->sigs ); + if (!blob->keys || !blob->uids || !blob->sigs) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + memcpy (blob->keys[0].fpr, sha1_digest, 20); + blob->keys[0].off_kid = 0; /* We don't have keyids */ + blob->keys[0].flags = 0; + + /* issuer and subject names */ + for (i=0; i < blob->nuids; i++) + { + blob->uids[i].name = names[i]; + blob->uids[i].len = strlen(names[i]); + names[i] = NULL; + blob->uids[i].flags = 0; + blob->uids[i].validity = 0; + } + xfree (names); + names = NULL; + + /* signatures */ + blob->sigs[0] = 0; /* not yet checked */ + + /* Create a temporary buffer for further processing */ + init_membuf (&blob->bufbuf, 1024); + blob->buf = &blob->bufbuf; + /* write out what we already have */ + rc = create_blob_header (blob, BLOBTYPE_X509, as_ephemeral); + if (rc) + goto leave; + rc = x509_create_blob_cert (blob, cert); + if (rc) + goto leave; + rc = create_blob_trailer (blob); + if (rc) + goto leave; + rc = create_blob_finish ( blob ); + if (rc) + goto leave; + + + leave: + release_kid_list (blob->temp_kids); + blob->temp_kids = NULL; + if (blob && names) + { + for (i=0; i < blob->nuids; i++) + xfree (names[i]); + } + xfree (names); + if (rc) + { + _keybox_release_blob (blob); + *r_blob = NULL; + } + else + { + *r_blob = blob; + } + return rc; +} +#endif /*KEYBOX_WITH_X509*/ + + + +int +_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off) +{ + KEYBOXBLOB blob; + + *r_blob = NULL; + blob = xtrycalloc (1, sizeof *blob); + if (!blob) + return gpg_error (gpg_err_code_from_errno (errno)); + + blob->blob = image; + blob->bloblen = imagelen; + blob->fileoffset = off; + *r_blob = blob; + return 0; +} + +void +_keybox_release_blob (KEYBOXBLOB blob) +{ + int i; + if (!blob) + return; + /* hmmm: release membuf here?*/ + xfree (blob->keys ); + xfree (blob->serialbuf); + for (i=0; i < blob->nuids; i++) + xfree (blob->uids[i].name); + xfree (blob->uids ); + xfree (blob->sigs ); + xfree (blob->blob ); + xfree (blob ); +} + + + +const char * +_keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n ) +{ + *n = blob->bloblen; + return blob->blob; +} + +off_t +_keybox_get_blob_fileoffset (KEYBOXBLOB blob) +{ + return blob->fileoffset; +} + diff --git a/scd/ChangeLog b/scd/ChangeLog new file mode 100644 index 000000000..ad4b0518c --- /dev/null +++ b/scd/ChangeLog @@ -0,0 +1,242 @@ +2003-07-31 Werner Koch <wk@gnupg.org> + + * Makefile.am (scdaemon_LDADD): Added INTLLIBS. + +2003-07-28 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (do_setattr): Change implementation. Allow all + useful DOs. + +2003-07-27 Werner Koch <wk@gnupg.org> + + Adjusted for gcry_mpi_print and gcry_mpi_scan API change. + +2003-07-24 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (do_learn_status): Print more status information. + (app_select_openpgp): Store the card version. + (store_fpr): Add argument card_version and fix DOs for old cards. + (app_openpgp_storekey): Likewise. + +2003-07-23 Werner Koch <wk@gnupg.org> + + * command.c (cmd_pkauth): New. + (cmd_setdata): Check whether data was given at all to avoid + passing 0 to malloc. + + * app.c (app_auth): New. + * app-openpgp.c (do_auth): New. + +2003-07-22 Werner Koch <wk@gnupg.org> + + * command.c (cmd_passwd): New. + * app.c (app_change_pin): New. + * app-openpgp.c (do_change_pin): New. + * iso7816.c (iso7816_reset_retry_counter): Implemented. + + * sc-investigate.c (main): New option --gen-random. + * iso7816.c (iso7816_get_challenge): Don't create APDUs with a + length larger than 255. + +2003-07-17 Werner Koch <wk@gnupg.org> + + * command.c (cmd_random): New command RANDOM. + + * iso7816.c (map_sw): New. Use it in this file to return + meaningful error messages. Changed all public fucntions to return + a gpg_error_t. + (iso7816_change_reference_data): New. + * apdu.c (apdu_open_reader): Use faked status words for soem + system errors. + +2003-07-16 Werner Koch <wk@gnupg.org> + + * apdu.c (apdu_send_simple): Use apdu_send_le so that we can + specify not to send Le as it should be. + +2003-07-15 Werner Koch <wk@gnupg.org> + + * Makefile.am: Add sc-copykeys program. + * sc-copykeys.c: New. + * app-openpgp.c (app_openpgp_storekey): New. + (app_openpgp_cardinfo): New. + (count_bits): New. + (store_fpr): And use it here to get the actual length in bit. + +2003-07-03 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (do_setattr): Add setting of the URL. + (app_select_openpgp): Dump card data only in very verbose mode. + (do_decipher): New. + +2003-07-02 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (get_sig_counter): New. + (do_sign): Print the signature counter and enable the PIN callback. + (do_genkey): Implement the PIN callback. + +2003-07-01 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (store_fpr): Fixed fingerprint calculation. + +2003-06-26 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (find_tlv): Fixed length header parsing. + + * app.c (app_genkey): New. + * command.c (cmd_genkey): New. + +2003-06-25 Werner Koch <wk@gnupg.org> + + * command.c (percent_plus_unescape): New. + (cmd_setattr): New. + +2003-06-24 Werner Koch <wk@gnupg.org> + + * command.c (send_status_info): New. + + * app-openpgp.c (app_select_openpgp): Replace SLOT arg by APP arg + and setup the function pointers in APP on success. Changed callers. + * app.c: New. + * app-common.h: New. + * scdaemon.h (APP): New type to handle applications. + (server_control_s): Add an APP context field. + + * command.c (cmd_serialno): Handle applications. + (cmd_pksign): Ditto. + (cmd_pkdecrypt): Ditto. + (reset_notify): Ditto. + (cmd_learn): For now return error for application contexts. + (cmd_readcert): Ditto. + (cmd_readkey): Ditto. + +2003-06-04 Werner Koch <wk@gnupg.org> + + * card.c (map_sc_err): Renamed gpg_make_err to gpg_err_make. + + Renamed error codes from INVALID to INV and removed _ERROR suffixes. + +2003-06-03 Werner Koch <wk@gnupg.org> + + Changed all error codes in all files to the new libgpg-error scheme. + + * scdaemon.h: Include gpg-error.h and errno.h + * card.c (map_sc_err): Use unknown for the error source. + * Makefile.am: Link with libgpg-error + +2003-05-14 Werner Koch <wk@gnupg.org> + + * atr.c, atr.h: New. + * sc-investigate.c: Dump the ATR in a human readable format. + +2003-05-08 Werner Koch <wk@gnupg.org> + + * scdaemon.h (DBG_CARD_IO_VALUE): New. + + * sc-investigate.c: New. + * scdaemon.c (main): Removed --print-atr option. + + * iso7816.c, iso7816.h, app-openpgp.c: New. + +2003-04-29 Werner Koch <wk@gnupg.org> + + * scdaemon.c: New options --print-atr and --reader-port + * apdu.c, apdu.h: New + + * card.c, card-p15.c, card-dinsig.c: Allow build without OpenSC. + + * Makefile.am (LDFLAGS): Removed. + + * command.c (register_commands): Adjusted for new Assuan semantics. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main): New option --daemon so that the program is + not accidently started in the background. + +2002-08-16 Werner Koch <wk@gnupg.org> + + * scdaemon.c: Include i18n.h. + + * card-common.h (struct p15_private_s): Forward declaration. Add + it to card_ctx_s. + * card.c (card_close): Make sure private data is released. + (card_enum_certs): New. + * card-p15.c (p15_release_private_data): New. + (init_private_data): New to work around an OpenSC weirdness. + (p15_enum_keypairs): Do an OpenSC get_objects only once. + (p15_enum_certs): New. + (card_p15_bind): Bind new function. + * command.c (cmd_learn): Return information about the certificates. + +2002-08-09 Werner Koch <wk@gnupg.org> + + * card.c (card_get_serial_and_stamp): Use the tokeinfo serial + number as a fallback. Add a special prefix for serial numbers. + +2002-07-30 Werner Koch <wk@gnupg.org> + + Changes to cope with OpenSC 0.7.0: + + * card.c: Removed the check for the packed opensc version. + Changed include file names of opensc. + (map_sc_err): Adjusted error codes for new opensc version. + * card-p15.c: Changed include filename of opensc. + * card-dinsig.c: Ditto. + + * card-p15.c (p15_decipher): Add flags argument to OpenSC call. + +2002-07-24 Werner Koch <wk@gnupg.org> + + * card.c (find_simple_tlv, find_iccsn): New. + (card_get_serial_and_stamp): Improved serial number parser. + +2002-06-27 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. + +2002-06-15 Werner Koch <wk@gnupg.org> + + * card-dinsig.c: Documented some stuff from the DIN norm. + +2002-04-15 Werner Koch <wk@gnupg.org> + + * command.c (cmd_pksign, cmd_pkdecrypt): Use a copy of the key ID. + +2002-04-12 Werner Koch <wk@gnupg.org> + + * scdaemon.c: New option --debug-sc N. + * card.c (card_open): set it here. + + * card-p15.c (p15_prepare_key): Factored out common code from ... + (p15_sign, p15_decipher): here and made the decryption work the + regular way. + +2002-04-10 Werner Koch <wk@gnupg.org> + + * card.c (card_open): Return immediately when no reader is available. + +2002-03-27 Werner Koch <wk@gnupg.org> + + * card.c (card_open, card_close): Adjusted for changes in OpenSC. + +2002-03-10 Werner Koch <wk@gnupg.org> + + * card-p15.c, card-dinsig.c, card-common.h: New. + * card.c: Factored most code out to the new modules, so that we + can better support different types of card applications. + +2002-01-26 Werner Koch <wk@gnupg.org> + + * scdaemon.c scdaemon.h, command.c: New. Based on the code from + the gpg-agent. + + 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. diff --git a/scd/Makefile.am b/scd/Makefile.am new file mode 100644 index 000000000..0771beb60 --- /dev/null +++ b/scd/Makefile.am @@ -0,0 +1,72 @@ +# 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 + +## Process this file with automake to produce Makefile.in + +localedir = $(datadir)/locale +INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" + +bin_PROGRAMS = scdaemon sc-investigate sc-copykeys + +AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ + $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) + +scdaemon_SOURCES = \ + scdaemon.c scdaemon.h \ + command.c card.c \ + card-common.h \ + card-p15.c card-dinsig.c \ + apdu.c apdu.h \ + iso7816.c iso7816.h \ + app.c app-common.h \ + app-openpgp.c + +scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ + -lgpg-error @INTLLIBS@ -ldl + +sc_investigate_SOURCES = \ + sc-investigate.c scdaemon.h \ + apdu.c apdu.h \ + iso7816.c iso7816.h \ + app.c app-common.h \ + app-openpgp.c \ + atr.c atr.h + +sc_investigate_LDADD = \ + ../jnlib/libjnlib.a ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) @INTLLIBS@ -lgpg-error -ldl + + +sc_copykeys_SOURCES = \ + sc-copykeys.c scdaemon.h \ + apdu.c apdu.h \ + iso7816.c iso7816.h \ + app.c app-common.h \ + app-openpgp.c \ + atr.c atr.h + +sc_copykeys_LDADD = \ + ../jnlib/libjnlib.a ../common/libcommon.a \ + ../common/libsimple-pwquery.a \ + $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ -ldl + + + + + diff --git a/scd/apdu.c b/scd/apdu.c new file mode 100644 index 000000000..6fec584b9 --- /dev/null +++ b/scd/apdu.c @@ -0,0 +1,558 @@ +/* apdu.c - ISO 7816 APDU functions and low level I/O + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> +#include <assert.h> + +#include "scdaemon.h" +#include "apdu.h" + +#define HAVE_CTAPI 1 + +#define MAX_READER 4 /* Number of readers we support concurrently. */ +#define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for + insertion of the card (1 = don't wait). */ + + + +/* A global table to keep track of active readers. */ +static struct { + int used; /* True if slot is used. */ + unsigned short port; /* port number0 = unused, 1 - dev/tty */ + int status; + unsigned char atr[33]; + size_t atrlen; +} reader_table[MAX_READER]; + + +/* ct API function pointer. */ +static char (*CT_init) (unsigned short ctn, unsigned short Pn); +static char (*CT_data) (unsigned short ctn, unsigned char *dad, + unsigned char *sad, unsigned short lc, + unsigned char *cmd, unsigned short *lr, + unsigned char *rsp); +static char (*CT_close) (unsigned short ctn); + + + + + +/* + Helper + */ + + +/* Find an unused reader slot for PORT and put it into the reader + table. Return -1 on error or the index into the reader table. */ +static int +new_reader_slot (int port) +{ + int i, reader = -1; + + if (port < 0 || port > 0xffff) + { + log_error ("new_reader_slot: invalid port %d requested\n", port); + return -1; + } + + for (i=0; i < MAX_READER; i++) + { + if (reader_table[i].used && reader_table[i].port == port) + { + log_error ("new_reader_slot: requested port %d already in use\n", + reader); + return -1; + } + else if (!reader_table[i].used && reader == -1) + reader = i; + } + if (reader == -1) + { + log_error ("new_reader_slot: out of slots\n"); + return -1; + } + reader_table[reader].used = 1; + reader_table[reader].port = port; + return reader; +} + + +static void +dump_reader_status (int reader) +{ + log_info ("reader %d: %s\n", reader, + reader_table[reader].status == 1? "Processor ICC present" : + reader_table[reader].status == 0? "Memory ICC present" : + "ICC not present" ); + + if (reader_table[reader].status != -1) + { + log_info ("reader %d: ATR=", reader); + log_printhex ("", reader_table[reader].atr, + reader_table[reader].atrlen); + } +} + + + +#ifdef HAVE_CTAPI +/* + ct API Interface + */ + +static const char * +ct_error_string (int err) +{ + switch (err) + { + case 0: return "okay"; + case -1: return "invalid data"; + case -8: return "ct error"; + case -10: return "transmission error"; + case -11: return "memory allocation error"; + case -128: return "HTSI error"; + default: return "unknown CT-API error"; + } +} + +/* Wait for the card in READER and activate it. Return -1 on error or + 0 on success. */ +static int +ct_activate_card (int reader) +{ + int rc, count; + + for (count = 0; count < CARD_CONNECT_TIMEOUT; count++) + { + unsigned char dad[1], sad[1], cmd[11], buf[256]; + unsigned short buflen; + + if (count) + sleep (1); /* FIXME: we should use a more reliable timer. */ + + /* Check whether card has been inserted. */ + dad[0] = 1; /* Destination address: CT. */ + sad[0] = 2; /* Source address: Host. */ + + cmd[0] = 0x20; /* Class byte. */ + cmd[1] = 0x13; /* Request status. */ + cmd[2] = 0x00; /* From kernel. */ + cmd[3] = 0x80; /* Return card's DO. */ + cmd[4] = 0x00; + + buflen = DIM(buf); + + rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf); + if (rc || buflen < 2 || buf[buflen-2] != 0x90) + { + log_error ("ct_activate_card: can't get status of reader %d: %s\n", + reader, ct_error_string (rc)); + return -1; + } + + if (buf[0] == 0x05) + { /* Connected, now activate the card. */ + dad[0] = 1; /* Destination address: CT. */ + sad[0] = 2; /* Source address: Host. */ + + cmd[0] = 0x20; /* Class byte. */ + cmd[1] = 0x12; /* Request ICC. */ + cmd[2] = 0x01; /* From first interface. */ + cmd[3] = 0x01; /* Return card's ATR. */ + cmd[4] = 0x00; + + buflen = DIM(buf); + + rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf); + if (rc || buflen < 2 || buf[buflen-2] != 0x90) + { + log_error ("ct_activate_card(%d): activation failed: %s\n", + reader, ct_error_string (rc)); + return -1; + } + + /* Store the type and the ATR. */ + if (buflen - 2 > DIM (reader_table[0].atr)) + { + log_error ("ct_activate_card(%d): ATR too long\n", reader); + return -1; + } + + reader_table[reader].status = buf[buflen - 1]; + memcpy (reader_table[reader].atr, buf, buflen - 2); + reader_table[reader].atrlen = buflen - 2; + return 0; + } + + } + + log_info ("ct_activate_card(%d): timeout waiting for card\n", reader); + return -1; +} + + +/* Open a reader and return an internal handle for it. PORT is a + non-negative value with the port number of the reader. USB readers + do have port numbers starting at 32769. */ +static int +open_ct_reader (int port) +{ + int rc, reader; + + reader = new_reader_slot (port); + if (reader == -1) + return reader; + + rc = CT_init (reader, (unsigned short)port); + if (rc) + { + log_error ("apdu_open_ct_reader failed on port %d: %s\n", + port, ct_error_string (rc)); + reader_table[reader].used = 0; + return -1; + } + + rc = ct_activate_card (reader); + if (rc) + { + reader_table[reader].used = 0; + return -1; + } + + dump_reader_status (reader); + return reader; +} + + +/* Actually send the APDU of length APDULEN to SLOT and return a + maximum of *BUFLEN data in BUFFER, the actual retruned size will be + set to BUFLEN. Returns: CT API error code. */ +static int +ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) +{ + int rc; + unsigned char dad[1], sad[1]; + unsigned short ctbuflen; + + dad[0] = 0; /* Destination address: Card. */ + sad[0] = 2; /* Source address: Host. */ + ctbuflen = *buflen; + if (DBG_CARD_IO) + log_printhex (" CT_data:", apdu, apdulen); + rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer); + *buflen = ctbuflen; + + /* FIXME: map the errorcodes to GNUPG ones, so that they can be + shared between CTAPI and PCSC. */ + return rc; +} + + +#endif /*HAVE_CTAPI*/ + + +#ifdef HAVE_PCSC +/* + PC/SC Interface + */ + + +#endif /*HAVE_PCSC*/ + + +/* + Driver Access + */ + +/* Open the reader and return an internal slot number or -1 on + error. */ +int +apdu_open_reader (int port) +{ + static int ct_api_loaded; + + if (!ct_api_loaded) + { + void *handle; + + handle = dlopen ("libtowitoko.so", RTLD_LAZY); + if (!handle) + { + log_error ("apdu_open_reader: failed to open driver: %s", + dlerror ()); + return -1; + } + CT_init = dlsym (handle, "CT_init"); + CT_data = dlsym (handle, "CT_data"); + CT_close = dlsym (handle, "CT_close"); + if (!CT_init || !CT_data || !CT_close) + { + log_error ("apdu_open_reader: invalid driver\n"); + dlclose (handle); + return -1; + } + ct_api_loaded = 1; + } + return open_ct_reader (port); +} + + +unsigned char * +apdu_get_atr (int slot, size_t *atrlen) +{ + char *buf; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return NULL; + + buf = xtrymalloc (reader_table[slot].atrlen); + if (!buf) + return NULL; + memcpy (buf, reader_table[slot].atr, reader_table[slot].atrlen); + *atrlen = reader_table[slot].atrlen; + return buf; +} + + +static const char * +error_string (int slot, int rc) +{ +#ifdef HAVE_CTAPI + return ct_error_string (rc); +#elif defined(HAVE_PCSC) + return "?"; +#else + return "?"; +#endif +} + + +/* Dispatcher for the actual send_apdu fucntion. */ +static int +send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) +{ +#ifdef HAVE_CTAPI + return ct_send_apdu (slot, apdu, apdulen, buffer, buflen); +#elif defined(HAVE_PCSC) + return SW_HOST_NO_DRIVER; +#else + return SW_HOST_NO_DRIVER; +#endif +} + +/* Send an APDU to the card in SLOT. The APDU is created from all + given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1 + for LC won't sent this field and the data field; in this case DATA + must also be passed as NULL. The return value is the status word + or -1 for an invalid SLOT or other non card related error. If + RETBUF is not NULL, it will receive an allocated buffer with the + returned data. The length of that data will be put into + *RETBUFLEN. The caller is reponsible for releasing the buffer even + in case of errors. */ +int +apdu_send_le(int slot, int class, int ins, int p0, int p1, + int lc, const char *data, int le, + unsigned char **retbuf, size_t *retbuflen) +{ + unsigned char result[256+10]; /* 10 extra in case of bugs in the driver. */ + size_t resultlen = 256; + unsigned char apdu[5+256+1]; + size_t apdulen; + int rc, sw; + + if (DBG_CARD_IO) + log_debug ("send apdu: c=%02X i=%02X p0=%02X p1=%02X lc=%d le=%d\n", + class, ins, p0, p1, lc, le); + + if (lc != -1 && (lc > 255 || lc < 0)) + return SW_WRONG_LENGTH; + if (le != -1 && (le > 256 || le < 1)) + return SW_WRONG_LENGTH; + if ((!data && lc != -1) || (data && lc == -1)) + return SW_HOST_INV_VALUE; + + apdulen = 0; + apdu[apdulen++] = class; + apdu[apdulen++] = ins; + apdu[apdulen++] = p0; + apdu[apdulen++] = p1; + if (lc != -1) + { + apdu[apdulen++] = lc; + memcpy (apdu+apdulen, data, lc); + apdulen += lc; + } + if (le != -1) + apdu[apdulen++] = le; /* Truncation is okay becuase 0 means 256. */ + assert (sizeof (apdu) >= apdulen); + /* As safeguard don't pass any garbage from the stack to the driver. */ + memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + if (rc || resultlen < 2) + { + log_error ("apdu_send_simple(%d) failed: %s\n", + slot, error_string (slot, rc)); + return SW_HOST_INCOMPLETE_CARD_RESPONSE; + } + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + /* store away the returned data but strip the statusword. */ + resultlen -= 2; + if (DBG_CARD_IO) + { + log_debug (" response: sw=%04X datalen=%d\n", sw, resultlen); + if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA)) + log_printhex (" dump: ", result, resultlen); + } + + if (sw == SW_SUCCESS) + { + if (retbuf) + { + *retbuf = xtrymalloc (resultlen? resultlen : 1); + if (!*retbuf) + return SW_HOST_OUT_OF_CORE; + *retbuflen = resultlen; + memcpy (*retbuf, result, resultlen); + } + } + else if ((sw & 0xff00) == SW_MORE_DATA) + { + unsigned char *p = NULL, *tmp; + size_t bufsize = 4096; + + /* It is likely that we need to return much more data, so we + start off with a large buffer. */ + if (retbuf) + { + *retbuf = p = xtrymalloc (bufsize); + if (!*retbuf) + return SW_HOST_OUT_OF_CORE; + assert (resultlen < bufsize); + memcpy (p, result, resultlen); + p += resultlen; + } + + do + { + int len = (sw & 0x00ff); + + log_debug ("apdu_send_simple(%d): %d more bytes available\n", + slot, len); + apdulen = 0; + apdu[apdulen++] = class; + apdu[apdulen++] = 0xC0; + apdu[apdulen++] = 0; + apdu[apdulen++] = 0; + apdu[apdulen++] = 64; /* that is 256 bytes for Le */ + memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + if (rc || resultlen < 2) + { + log_error ("apdu_send_simple(%d) for get response failed: %s\n", + slot, error_string (slot, rc)); + return SW_HOST_INCOMPLETE_CARD_RESPONSE; + } + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + resultlen -= 2; + if (DBG_CARD_IO) + { + log_debug (" more: sw=%04X datalen=%d\n", sw, resultlen); + if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA)) + log_printhex (" dump: ", result, resultlen); + } + + if ((sw & 0xff00) == SW_MORE_DATA || sw == SW_SUCCESS) + { + if (retbuf) + { + if (p - *retbuf + resultlen > bufsize) + { + bufsize += resultlen > 4096? resultlen: 4096; + tmp = xtryrealloc (*retbuf, bufsize); + if (!tmp) + return SW_HOST_OUT_OF_CORE; + p = tmp + (p - *retbuf); + *retbuf = tmp; + } + memcpy (p, result, resultlen); + p += resultlen; + } + } + else + log_info ("apdu_send_simple(%d) " + "got unexpected status %04X from get response\n", + slot, sw); + } + while ((sw & 0xff00) == SW_MORE_DATA); + + if (retbuf) + { + *retbuflen = p - *retbuf; + tmp = xtryrealloc (*retbuf, *retbuflen); + if (tmp) + *retbuf = tmp; + } + } + if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS) + log_printhex (" dump: ", *retbuf, *retbuflen); + + return sw; +} + +/* Send an APDU to the card in SLOT. The APDU is created from all + given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for + LC won't sent this field and the data field; in this case DATA must + also be passed as NULL. The return value is the status word or -1 + for an invalid SLOT or other non card related error. If RETBUF is + not NULL, it will receive an allocated buffer with the returned + data. The length of that data will be put into *RETBUFLEN. The + caller is reponsible for releasing the buffer even in case of + errors. */ +int +apdu_send (int slot, int class, int ins, int p0, int p1, + int lc, const char *data, unsigned char **retbuf, size_t *retbuflen) +{ + return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256, + retbuf, retbuflen); +} + +/* Send an APDU to the card in SLOT. The APDU is created from all + given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for + LC won't sent this field and the data field; in this case DATA must + also be passed as NULL. The return value is the status word or -1 + for an invalid SLOT or other non card related error. No data will be + returned. */ +int +apdu_send_simple (int slot, int class, int ins, int p0, int p1, + int lc, const char *data) +{ + return apdu_send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL); +} + + + + diff --git a/scd/apdu.h b/scd/apdu.h new file mode 100644 index 000000000..44166a3fe --- /dev/null +++ b/scd/apdu.h @@ -0,0 +1,73 @@ +/* apdu.h - ISO 7816 APDU functions and low level I/O + * 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 APDU_H +#define APDU_H + +/* ISO 7816 values for the statusword are defined here because they + should not be visible to the users of the actual ISO command + API. */ +enum { + SW_MORE_DATA = 0x6100, /* Note: that the low byte must be + masked of.*/ + SW_EEPROM_FAILURE = 0x6581, + SW_WRONG_LENGTH = 0x6700, + SW_CHV_WRONG = 0x6982, + SW_CHV_BLOCKED = 0x6983, + SW_USE_CONDITIONS = 0x6985, + SW_NOT_SUPPORTED = 0x6a81, + SW_BAD_PARAMETER = 0x6a80, /* (in the data field) */ + SW_REF_NOT_FOUND = 0x6a88, + SW_BAD_P0_P1 = 0x6b00, + SW_INS_NOT_SUP = 0x6d00, + SW_CLA_NOT_SUP = 0x6e00, + SW_SUCCESS = 0x9000, + + /* The follwoing statuswords are no real ones but used to map host + OS errors into status words. A status word is 16 bit so that + those values can't be issued by a card. */ + SW_HOST_OUT_OF_CORE = 0x10001, /* No way yet to differentiate + between errnos on a failed malloc. */ + SW_HOST_INV_VALUE = 0x10002, + SW_HOST_INCOMPLETE_CARD_RESPONSE = 0x10003, +}; + + + +/* Note , that apdu_open_reader returns no status word but -1 on error. */ +int apdu_open_reader (int port); +unsigned char *apdu_get_atr (int slot, size_t *atrlen); + + +/* The apdu send functions do return status words. */ +int apdu_send_simple (int slot, int class, int ins, int p0, int p1, + int lc, const char *data); +int apdu_send (int slot, int class, int ins, int p0, int p1, + int lc, const char *data, + unsigned char **retbuf, size_t *retbuflen); +int apdu_send_le (int slot, int class, int ins, int p0, int p1, + int lc, const char *data, int le, + unsigned char **retbuf, size_t *retbuflen); + + +#endif /*APDU_H*/ + + + diff --git a/scd/app-common.h b/scd/app-common.h new file mode 100644 index 000000000..282f82715 --- /dev/null +++ b/scd/app-common.h @@ -0,0 +1,128 @@ +/* app-common.h - Common declarations for all card applications + * 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_SCD_APP_COMMON_H +#define GNUPG_SCD_APP_COMMON_H + +struct app_ctx_s { + int initialized; /* The application has been initialied and the + function pointers may be used. Note that for + unsupported operations the particular + function pointer is set to NULL */ + int slot; /* Used reader. */ + unsigned char *serialno; /* Serialnumber in raw form, allocated. */ + size_t serialnolen; /* Length in octets of serialnumber. */ + unsigned int card_version; + int did_chv1; + int did_chv2; + int did_chv3; + struct { + int (*learn_status) (APP app, CTRL ctrl); + int (*setattr) (APP app, const char *name, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *value, size_t valuelen); + int (*sign) (APP app, + const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); + int (*auth) (APP app, const char *keyidstr, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen); + int (*decipher) (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen); + int (*genkey) (APP app, CTRL ctrl, + const char *keynostr, unsigned int flags, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); + int (*change_pin) (APP app, CTRL ctrl, + const char *chvnostr, int reset_mode, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); + } fnc; + + +}; + +/*-- app.c --*/ +APP select_application (void); +int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); +int app_write_learn_status (APP app, CTRL ctrl); +int app_setattr (APP app, const char *name, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *value, size_t valuelen); +int app_sign (APP app, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); +int app_auth (APP app, const char *keyidstr, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen); +int app_decipher (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); +int app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); +int app_get_challenge (APP app, size_t nbytes, unsigned char *buffer); +int app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); + + +/*-- app-openpgp.c --*/ +int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen); + +int app_openpgp_cardinfo (APP app, + char **serialno, + char **disp_name, + char **pubkey_url, + unsigned char **fpr1, + unsigned char **fpr2, + unsigned char **fpr3); +int app_openpgp_storekey (APP app, int keyno, + unsigned char *template, size_t template_len, + time_t created_at, + const unsigned char *m, size_t mlen, + const unsigned char *e, size_t elen, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); +int app_openpgp_readkey (APP app, int keyno, + unsigned char **m, size_t *mlen, + unsigned char **e, size_t *elen); + + +#endif /*GNUPG_SCD_APP_COMMON_H*/ + + + diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c new file mode 100644 index 000000000..09a19699d --- /dev/null +++ b/scd/app-openpgp.c @@ -0,0 +1,1482 @@ +/* app-openpgp.c - The OpenPGP card application. + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "scdaemon.h" +#include "app-common.h" +#include "iso7816.h" + + + +static struct { + int tag; + int constructed; + int get_from; /* Constructed DO with this DO or 0 for direct access. */ + int binary; + char *desc; +} data_objects[] = { + { 0x005E, 0, 0, 1, "Login Data" }, + { 0x5F50, 0, 0, 0, "URL" }, + { 0x0065, 1, 0, 1, "Cardholder Related Data"}, + { 0x005B, 0, 0x65, 0, "Name" }, + { 0x5F2D, 0, 0x65, 0, "Language preferences" }, + { 0x5F35, 0, 0x65, 0, "Sex" }, + { 0x006E, 1, 0, 1, "Application Related Data" }, + { 0x004F, 0, 0x6E, 1, "AID" }, + { 0x0073, 1, 0, 1, "Discretionary Data Objects" }, + { 0x0047, 0, 0x6E, 1, "Card Capabilities" }, + { 0x00C0, 0, 0x6E, 1, "Extended Card Capabilities" }, + { 0x00C1, 0, 0x6E, 1, "Algorithm Attributes Signature" }, + { 0x00C2, 0, 0x6E, 1, "Algorithm Attributes Decryption" }, + { 0x00C3, 0, 0x6E, 1, "Algorithm Attributes Authentication" }, + { 0x00C4, 0, 0x6E, 1, "CHV Status Bytes" }, + { 0x00C5, 0, 0x6E, 1, "Fingerprints" }, + { 0x00C6, 0, 0x6E, 1, "CA Fingerprints" }, + { 0x007A, 1, 0, 1, "Security Support Template" }, + { 0x0093, 0, 0x7A, 1, "Digital Signature Counter" }, + { 0 } +}; + + +static unsigned long get_sig_counter (APP app); + + +/* Locate a TLV encoded data object in BUFFER of LENGTH and + return a pointer to value as well as its length in NBYTES. Return + NULL if it was not found. Note, that the function does not check + whether the value fits into the provided buffer. + + FIXME: Move this to an extra file, it is mostly duplicated from card.c. +*/ +static const unsigned char * +find_tlv (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes, int nestlevel) +{ + const unsigned char *s = buffer; + size_t n = length; + size_t len; + int this_tag; + int composite; + + for (;;) + { + buffer = s; + if (n < 2) + return NULL; /* buffer definitely too short for tag and length. */ + if (!*s || *s == 0xff) + { /* Skip optional filler between TLV objects. */ + s++; + n--; + continue; + } + composite = !!(*s & 0x20); + if ((*s & 0x1f) == 0x1f) + { /* more tag bytes to follow */ + s++; + n--; + if (n < 2) + return NULL; /* buffer definitely too short for tag and length. */ + if ((*s & 0x1f) == 0x1f) + return NULL; /* We support only up to 2 bytes. */ + this_tag = (s[-1] << 8) | (s[0] & 0x7f); + } + else + this_tag = s[0]; + len = s[1]; + s += 2; n -= 2; + if (len < 0x80) + ; + else if (len == 0x81) + { /* One byte length follows. */ + if (!n) + return NULL; /* we expected 1 more bytes with the length. */ + len = s[0]; + s++; n--; + } + else if (len == 0x82) + { /* Two byte length follows. */ + if (n < 2) + return NULL; /* we expected 2 more bytes with the length. */ + len = (s[0] << 8) | s[1]; + s += 2; n -= 2; + } + else + return NULL; /* APDU limit is 65535, thus it does not make + sense to assume longer length fields. */ + + if (composite && nestlevel < 100) + { /* Dive into this composite DO after checking for too deep + nesting. */ + const unsigned char *tmp_s; + size_t tmp_len; + + tmp_s = find_tlv (s, len, tag, &tmp_len, nestlevel+1); + if (tmp_s) + { + *nbytes = tmp_len; + return tmp_s; + } + } + + if (this_tag == tag) + { + *nbytes = len; + return s; + } + if (len > n) + return NULL; /* buffer too short to skip to the next tag. */ + s += len; n -= len; + } +} + + +/* Get the DO identified by TAG from the card in SLOT and return a + buffer with its content in RESULT and NBYTES. The return value is + NULL if not found or a pointer which must be used to release the + buffer holding value. */ +static void * +get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes) +{ + int rc, i; + unsigned char *buffer; + size_t buflen; + unsigned char *value; + size_t valuelen; + + *result = NULL; + *nbytes = 0; + for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++) + ; + + value = NULL; + rc = -1; + if (data_objects[i].tag && data_objects[i].get_from) + { + rc = iso7816_get_data (slot, data_objects[i].get_from, + &buffer, &buflen); + if (!rc) + { + const unsigned char *s; + + s = find_tlv (buffer, buflen, tag, &valuelen, 0); + if (!s) + value = NULL; /* not found */ + else if (valuelen > buflen - (s - buffer)) + { + log_error ("warning: constructed DO too short\n"); + value = NULL; + xfree (buffer); buffer = NULL; + } + else + value = buffer + (s - buffer); + } + } + + if (!value) /* Not in a constructed DO, try simple. */ + { + rc = iso7816_get_data (slot, tag, &buffer, &buflen); + if (!rc) + { + value = buffer; + valuelen = buflen; + } + } + + if (!rc) + { + *nbytes = valuelen; + *result = value; + return buffer; + } + return NULL; +} + +#if 0 /* not used */ +static void +dump_one_do (int slot, int tag) +{ + int rc, i; + unsigned char *buffer; + size_t buflen; + const char *desc; + int binary; + const unsigned char *value; + size_t valuelen; + + for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++) + ; + desc = data_objects[i].tag? data_objects[i].desc : "?"; + binary = data_objects[i].tag? data_objects[i].binary : 1; + + value = NULL; + rc = -1; + if (data_objects[i].tag && data_objects[i].get_from) + { + rc = iso7816_get_data (slot, data_objects[i].get_from, + &buffer, &buflen); + if (!rc) + { + value = find_tlv (buffer, buflen, tag, &valuelen, 0); + if (!value) + ; /* not found */ + else if (valuelen > buflen - (value - buffer)) + { + log_error ("warning: constructed DO too short\n"); + value = NULL; + xfree (buffer); buffer = NULL; + } + } + } + + if (!value) /* Not in a constructed DO, try simple. */ + { + rc = iso7816_get_data (slot, tag, &buffer, &buflen); + if (!rc) + { + value = buffer; + valuelen = buflen; + } + } + if (rc == 0x6a88) + log_info ("DO `%s' not available\n", desc); + else if (rc) + log_info ("DO `%s' not available (rc=%04X)\n", desc, rc); + else + { + if (binary) + { + log_info ("DO `%s': ", desc); + log_printhex ("", value, valuelen); + } + else + log_info ("DO `%s': `%.*s'\n", + desc, (int)valuelen, value); /* FIXME: sanitize */ + xfree (buffer); + } +} +#endif /*not used*/ + + +static void +dump_all_do (int slot) +{ + int rc, i, j; + unsigned char *buffer; + size_t buflen; + + for (i=0; data_objects[i].tag; i++) + { + if (data_objects[i].get_from) + continue; + + rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen); + if (rc == 0x6a88) + ; + else if (rc) + log_info ("DO `%s' not available (rc=%04X)\n", + data_objects[i].desc, rc); + else + { + if (data_objects[i].binary) + { + log_info ("DO `%s': ", data_objects[i].desc); + log_printhex ("", buffer, buflen); + } + else + log_info ("DO `%s': `%.*s'\n", + data_objects[i].desc, + (int)buflen, buffer); /* FIXME: sanitize */ + } + + if (data_objects[i].constructed) + { + for (j=0; data_objects[j].tag; j++) + { + const unsigned char *value; + size_t valuelen; + + if (j==i || data_objects[i].tag != data_objects[j].get_from) + continue; + value = find_tlv (buffer, buflen, + data_objects[j].tag, &valuelen, 0); + if (!value) + ; /* not found */ + else if (valuelen > buflen - (value - buffer)) + log_error ("warning: constructed DO too short\n"); + else + { + if (data_objects[j].binary) + { + log_info ("DO `%s': ", data_objects[j].desc); + log_printhex ("", value, valuelen); + } + else + log_info ("DO `%s': `%.*s'\n", + data_objects[j].desc, + (int)valuelen, value); /* FIXME: sanitize */ + } + } + } + xfree (buffer); buffer = NULL; + } +} + + +/* Count the number of bits, assuming the A represents an unsigned big + integer of length LEN bytes. */ +static unsigned int +count_bits (const unsigned char *a, size_t len) +{ + unsigned int n = len * 8; + int i; + + for (; len && !*a; len--, a++, n -=8) + ; + if (len) + { + for (i=7; i && !(*a & (1<<i)); i--) + n--; + } + return n; +} + +/* Note, that FPR must be at least 20 bytes. */ +static int +store_fpr (int slot, int keynumber, u32 timestamp, + const unsigned char *m, size_t mlen, + const unsigned char *e, size_t elen, + unsigned char *fpr, unsigned int card_version) +{ + unsigned int n, nbits; + unsigned char *buffer, *p; + int rc; + + for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */ + ; + for (; elen && !*e; elen--, e++) /* strip leading zeroes */ + ; + + n = 6 + 2 + mlen + 2 + elen; + p = buffer = xtrymalloc (3 + n); + if (!buffer) + return out_of_core (); + + *p++ = 0x99; /* ctb */ + *p++ = n >> 8; /* 2 byte length header */ + *p++ = n; + *p++ = 4; /* key packet version */ + *p++ = timestamp >> 24; + *p++ = timestamp >> 16; + *p++ = timestamp >> 8; + *p++ = timestamp; + *p++ = 1; /* RSA */ + nbits = count_bits (m, mlen); + *p++ = nbits >> 8; + *p++ = nbits; + memcpy (p, m, mlen); p += mlen; + nbits = count_bits (e, elen); + *p++ = nbits >> 8; + *p++ = nbits; + memcpy (p, e, elen); p += elen; + + log_printhex ("fprbuf:", buffer, n+3); + gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3); + + xfree (buffer); + + rc = iso7816_put_data (slot, (card_version > 0x0007? 0xC7 : 0xC6) + + keynumber, fpr, 20); + if (rc) + log_error ("failed to store the fingerprint: rc=%04X\n", rc); + + return rc; +} + + +static void +send_fpr_if_not_null (CTRL ctrl, const char *keyword, + int number, const unsigned char *fpr) +{ + int i; + char buf[41]; + char numbuf[25]; + + for (i=0; i < 20 && !fpr[i]; i++) + ; + if (i==20) + return; /* All zero. */ + for (i=0; i< 20; i++) + sprintf (buf+2*i, "%02X", fpr[i]); + if (number == -1) + *numbuf = 0; /* Don't print the key number */ + else + sprintf (numbuf, "%d", number); + send_status_info (ctrl, keyword, + numbuf, (size_t)strlen(numbuf), + buf, (size_t)strlen (buf), NULL, 0); +} + +static void +send_key_data (CTRL ctrl, const char *name, + const unsigned char *a, size_t alen) +{ + char *p, *buf = xmalloc (alen*2+1); + + for (p=buf; alen; a++, alen--, p += 2) + sprintf (p, "%02X", *a); + + send_status_info (ctrl, "KEY-DATA", + name, (size_t)strlen(name), + buf, (size_t)strlen (buf), + NULL, 0); + xfree (buf); +} + + + +static int +do_learn_status (APP app, CTRL ctrl) +{ + void *relptr; + unsigned char *value; + size_t valuelen; + int i; + + relptr = get_one_do (app->slot, 0x005B, &value, &valuelen); + if (relptr) + { + send_status_info (ctrl, "DISP-NAME", value, valuelen, NULL, 0); + xfree (relptr); + } + relptr = get_one_do (app->slot, 0x5F2D, &value, &valuelen); + if (relptr) + { + send_status_info (ctrl, "DISP-LANG", value, valuelen, NULL, 0); + xfree (relptr); + } + relptr = get_one_do (app->slot, 0x5F35, &value, &valuelen); + if (relptr) + { + send_status_info (ctrl, "DISP-SEX", value, valuelen, NULL, 0); + xfree (relptr); + } + relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen); + if (relptr) + { + send_status_info (ctrl, "PUBKEY-URL", value, valuelen, NULL, 0); + xfree (relptr); + } + relptr = get_one_do (app->slot, 0x005E, &value, &valuelen); + if (relptr) + { + send_status_info (ctrl, "LOGIN-DATA", value, valuelen, NULL, 0); + xfree (relptr); + } + + relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen); + if (relptr && valuelen >= 60) + { + for (i=0; i < 3; i++) + send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20); + } + xfree (relptr); + relptr = get_one_do (app->slot, 0x00C6, &value, &valuelen); + if (relptr && valuelen >= 60) + { + for (i=0; i < 3; i++) + send_fpr_if_not_null (ctrl, "CA-FPR", i+1, value+i*20); + } + xfree (relptr); + relptr = get_one_do (app->slot, 0x00C4, &value, &valuelen); + if (relptr) + { + char numbuf[7*23]; + + for (i=0,*numbuf=0; i < valuelen && i < 7; i++) + sprintf (numbuf+strlen (numbuf), " %d", value[i]); + send_status_info (ctrl, "CHV-STATUS", numbuf, strlen (numbuf), NULL, 0); + xfree (relptr); + } + + { + unsigned long ul = get_sig_counter (app); + char numbuf[23]; + + sprintf (numbuf, "%lu", ul); + send_status_info (ctrl, "SIG-COUNTER", numbuf, strlen (numbuf), NULL, 0); + } + return 0; +} + + +/* Handle the SETATTR operation. All arguments are already basically + checked. */ +static int +do_setattr (APP app, const char *name, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *value, size_t valuelen) +{ + gpg_error_t rc; + int idx; + static struct { + const char *name; + int tag; + } table[] = { + { "DISP-NAME", 0x005B }, + { "LOGIN-DATA", 0x005E }, + { "DISP-LANG", 0x5F2D }, + { "DISP-SEX", 0x5F35 }, + { "PUBKEY-URL", 0x5F50 }, + { "CHV-STATUS-1", 0x00C4 }, + { "CA-FPR-1", 0x00CA }, + { "CA-FPR-2", 0x00CB }, + { "CA-FPR-3", 0x00CC }, + { NULL, 0 } + }; + + + for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++) + ; + if (!table[idx].name) + return gpg_error (GPG_ERR_INV_NAME); + + if (!app->did_chv3) + { + char *pinvalue; + + rc = pincb (pincb_arg, "Admin PIN (CHV3)", + &pinvalue); +/* pinvalue = xstrdup ("12345678"); */ +/* rc = 0; */ + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV3 failed\n"); + rc = gpg_error (GPG_ERR_GENERAL); + return rc; + } + app->did_chv3 = 1; + } + + rc = iso7816_put_data (app->slot, table[idx].tag, value, valuelen); + if (rc) + log_error ("failed to set `%s': %s\n", table[idx].name, gpg_strerror (rc)); + /* FIXME: If this fails we should *once* try again after + doing a verify command, so that in case of a problem with + tracking the verify operation we have a fallback. */ + + return rc; +} + +/* Handle the PASSWD command. */ +static int +do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc = 0; + int chvno = atoi (chvnostr); + char *pinvalue; + + if (reset_mode && chvno == 3) + { + rc = gpg_error (GPG_ERR_INV_ID); + goto leave; + } + else if (reset_mode || chvno == 3) + { + rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + if (rc) + { + log_error ("error getting PIN: %s\n", gpg_strerror (rc)); + goto leave; + } + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV3 failed: rc=%04X\n", rc); + goto leave; + } + } + else if (chvno == 1) + { + rc = pincb (pincb_arg, "Signature PIN", &pinvalue); + if (rc) + { + log_error ("error getting PIN: %s\n", gpg_strerror (rc)); + goto leave; + } + rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV1 failed: rc=%04X\n", rc); + goto leave; + } + } + else if (chvno == 2) + { + rc = pincb (pincb_arg, "Decryption PIN", &pinvalue); + if (rc) + { + log_error ("error getting PIN: %s\n", gpg_strerror (rc)); + goto leave; + } + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV2 failed: rc=%04X\n", rc); + goto leave; + } + } + else + { + rc = gpg_error (GPG_ERR_INV_ID); + goto leave; + } + + + rc = pincb (pincb_arg, chvno == 1? "New Signature PIN" : + chvno == 2? "New Decryption PIN" : + chvno == 3? "New Admin PIN" : "?", &pinvalue); + if (rc) + { + log_error ("error getting new PIN: %s\n", gpg_strerror (rc)); + goto leave; + } + + if (reset_mode) + rc = iso7816_reset_retry_counter (app->slot, 0x80 + chvno, + pinvalue, strlen (pinvalue)); + else + rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, + NULL, 0, + pinvalue, strlen (pinvalue)); + xfree (pinvalue); + + + leave: + return rc; +} + + + +/* Handle the GENKEY command. */ +static int +do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc; + int i; + char numbuf[30]; + unsigned char fprbuf[20]; + const unsigned char *fpr; + const unsigned char *keydata, *m, *e; + unsigned char *buffer; + size_t buflen, keydatalen, n, mlen, elen; + time_t created_at; + int keyno = atoi (keynostr); + int force = (flags & 1); + time_t start_at; + + if (keyno < 1 || keyno > 3) + return gpg_error (GPG_ERR_INV_ID); + keyno--; + + rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); + if (rc) + { + log_error ("error reading application data\n"); + return gpg_error (GPG_ERR_GENERAL); + } + fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0); + if (!fpr || n != 60) + { + rc = gpg_error (GPG_ERR_GENERAL); + log_error ("error reading fingerprint DO\n"); + goto leave; + } + fpr += 20*keyno; + for (i=0; i < 20 && !fpr[i]; i++) + ; + if (i!=20 && !force) + { + rc = gpg_error (GPG_ERR_EEXIST); + log_error ("key already exists\n"); + goto leave; + } + else if (i!=20) + log_info ("existing key will be replaced\n"); + else + log_info ("generating new key\n"); + + { + char *pinvalue; + rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + if (rc) + { + log_error ("error getting PIN: %s\n", gpg_strerror (rc)); + return rc; + } + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + } + if (rc) + { + log_error ("verify CHV3 failed: rc=%04X\n", rc); + goto leave; + } + + xfree (buffer); buffer = NULL; +#if 1 + log_info ("please wait while key is being generated ...\n"); + start_at = time (NULL); + rc = iso7816_generate_keypair +#else +#warning key generation temporary replaced by reading an existing key. + rc = iso7816_read_public_key +#endif + (app->slot, + keyno == 0? "\xB6" : + keyno == 1? "\xB8" : "\xA4", + 2, + &buffer, &buflen); + if (rc) + { + rc = gpg_error (GPG_ERR_CARD); + log_error ("generating key failed\n"); + goto leave; + } + log_info ("key generation completed (%d seconds)\n", + (int)(time (NULL) - start_at)); + keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0); + if (!keydata) + { + rc = gpg_error (GPG_ERR_CARD); + log_error ("response does not contain the public key data\n"); + goto leave; + } + + m = find_tlv (keydata, keydatalen, 0x0081, &mlen, 0); + if (!m) + { + rc = gpg_error (GPG_ERR_CARD); + log_error ("response does not contain the RSA modulus\n"); + goto leave; + } +/* log_printhex ("RSA n:", m, mlen); */ + send_key_data (ctrl, "n", m, mlen); + + e = find_tlv (keydata, keydatalen, 0x0082, &elen, 0); + if (!e) + { + rc = gpg_error (GPG_ERR_CARD); + log_error ("response does not contain the RSA public exponent\n"); + goto leave; + } +/* log_printhex ("RSA e:", e, elen); */ + send_key_data (ctrl, "e", e, elen); + + created_at = gnupg_get_time (); + sprintf (numbuf, "%lu", (unsigned long)created_at); + send_status_info (ctrl, "KEY-CREATED-AT", + numbuf, (size_t)strlen(numbuf), NULL, 0); + + rc = store_fpr (app->slot, keyno, (u32)created_at, + m, mlen, e, elen, fprbuf, app->card_version); + if (rc) + goto leave; + send_fpr_if_not_null (ctrl, "KEY-FPR", -1, fprbuf); + + + leave: + xfree (buffer); + return rc; +} + + +static unsigned long +get_sig_counter (APP app) +{ + void *relptr; + unsigned char *value; + size_t valuelen; + unsigned long ul; + + relptr = get_one_do (app->slot, 0x0093, &value, &valuelen); + if (!relptr) + return 0; + if (valuelen == 3 ) + ul = (value[0] << 16) | (value[1] << 8) | value[2]; + else + { + log_error ("invalid structure of OpenPGP card (DO 0x93)\n"); + ul = 0; + } + xfree (relptr); + return ul; +} + +static int +compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr) +{ + const unsigned char *fpr; + unsigned char *buffer; + size_t buflen, n; + int rc, i; + + assert (keyno >= 1 && keyno <= 3); + + rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); + if (rc) + { + log_error ("error reading application data\n"); + return gpg_error (GPG_ERR_GENERAL); + } + fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0); + if (!fpr || n != 60) + { + xfree (buffer); + log_error ("error reading fingerprint DO\n"); + return gpg_error (GPG_ERR_GENERAL); + } + fpr += (keyno-1)*20; + for (i=0; i < 20; i++) + if (sha1fpr[i] != fpr[i]) + { + xfree (buffer); + return gpg_error (GPG_ERR_WRONG_SECKEY); + } + xfree (buffer); + return 0; +} + + + +/* Compute a digital signature on INDATA which is expected to be the + raw message digest. For this application the KEYIDSTR consists of + the serialnumber and the fingerprint delimited by a slash. + + Note that this fucntion may return the error code + GPG_ERR_WRONG_CARD to indicate that the card currently present does + not match the one required for the requested action (e.g. the + serial number does not match). */ +static int +do_sign (APP app, const char *keyidstr, int hashalgo, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + int rc; + unsigned char data[35]; + unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */ + const char *s; + int n; + const char *fpr = NULL; + unsigned long sigcount; + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + if (indatalen != 20) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check whether an OpenPGP card of any version has been requested. */ + if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 32) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* no fingerprint given: we allow this for now. */ + else if (*s == '/') + fpr = s + 1; + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; n < 16; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + + if (app->serialnolen != 16) + return gpg_error (GPG_ERR_INV_CARD); + if (memcmp (app->serialno, tmp_sn, 16)) + return gpg_error (GPG_ERR_WRONG_CARD); + + /* If a fingerprint has been specified check it against the one on + the card. This is allows for a meaningful error message in case + the key on the card has been replaced but the shadow information + known to gpg was not updated. If there is no fingerprint, gpg + will detect a bogus signature anyway due to the + verify-after-signing feature. */ + if (fpr) + { + for (s=fpr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 40) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* okay */ + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=fpr, n=0; n < 20; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + rc = compare_fingerprint (app, 1, tmp_sn); + if (rc) + return rc; + } + + if (hashalgo == GCRY_MD_SHA1) + memcpy (data, sha1_prefix, 15); + else if (hashalgo == GCRY_MD_RMD160) + memcpy (data, rmd160_prefix, 15); + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data+15, indata, indatalen); + + sigcount = get_sig_counter (app); + log_info ("signatures created so far: %lu\n", sigcount); + + /* FIXME: Check whether we are really required to enter the PIN for + each signature. There is a DO for this. */ + if (!app->did_chv1 || 1) + { + char *pinvalue; + + { + char *prompt; + if (asprintf (&prompt, "Signature PIN [sigs done: %lu]", sigcount) < 0) + return gpg_error_from_errno (errno); + rc = pincb (pincb_arg, prompt, &pinvalue); + free (prompt); + } +/* pinvalue = xstrdup ("123456"); */ +/* rc = 0; */ + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV1 failed\n"); + rc = gpg_error (GPG_ERR_GENERAL); + return rc; + } + app->did_chv1 = 1; + } + + rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + return rc; +} + +/* Compute a digital signature using the INTERNAL AUTHENTICATE command + on INDATA which is expected to be the raw message digest. For this + application the KEYIDSTR consists of the serialnumber and the + fingerprint delimited by a slash. + + Note that this fucntion may return the error code + GPG_ERR_WRONG_CARD to indicate that the card currently present does + not match the one required for the requested action (e.g. the + serial number does not match). */ +static int +do_auth (APP app, const char *keyidstr, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */ + const char *s; + int n; + const char *fpr = NULL; + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + if (indatalen > 50) /* For a 1024 bit key. */ + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check whether an OpenPGP card of any version has been requested. */ + if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 32) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* no fingerprint given: we allow this for now. */ + else if (*s == '/') + fpr = s + 1; + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; n < 16; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + + if (app->serialnolen != 16) + return gpg_error (GPG_ERR_INV_CARD); + if (memcmp (app->serialno, tmp_sn, 16)) + return gpg_error (GPG_ERR_WRONG_CARD); + + /* If a fingerprint has been specified check it against the one on + the card. This is allows for a meaningful error message in case + the key on the card has been replaced but the shadow information + known to gpg was not updated. If there is no fingerprint, gpg + will detect a bogus signature anyway due to the + verify-after-signing feature. */ + if (fpr) + { + for (s=fpr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 40) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* okay */ + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=fpr, n=0; n < 20; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + rc = compare_fingerprint (app, 3, tmp_sn); + if (rc) + return rc; + } + + if (!app->did_chv2) + { + char *pinvalue; + + rc = pincb (pincb_arg, "Authentication/Decryption PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV2 failed\n"); + rc = gpg_error (GPG_ERR_GENERAL); + return rc; + } + app->did_chv2 = 1; + } + + rc = iso7816_internal_authenticate (app->slot, indata, indatalen, + outdata, outdatalen); + return rc; +} + + +static int +do_decipher (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */ + const char *s; + int n; + const char *fpr = NULL; + + if (!keyidstr || !*keyidstr || !indatalen) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check whether an OpenPGP card of any version has been requested. */ + if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 32) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* no fingerprint given: we allow this for now. */ + else if (*s == '/') + fpr = s + 1; + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; n < 16; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + + if (app->serialnolen != 16) + return gpg_error (GPG_ERR_INV_CARD); + if (memcmp (app->serialno, tmp_sn, 16)) + return gpg_error (GPG_ERR_WRONG_CARD); + + /* If a fingerprint has been specified check it against the one on + the card. This is allows for a meaningful error message in case + the key on the card has been replaced but the shadow information + known to gpg was not updated. If there is no fingerprint, the + decryption will won't produce the right plaintext anyway. */ + if (fpr) + { + for (s=fpr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 40) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* okay */ + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=fpr, n=0; n < 20; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + rc = compare_fingerprint (app, 2, tmp_sn); + if (rc) + return rc; + } + + if (!app->did_chv2) + { + char *pinvalue; + + rc = pincb (pincb_arg, "Decryption PIN", &pinvalue); +/* pinvalue = xstrdup ("123456"); */ +/* rc = 0; */ + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV2 failed\n"); + rc = gpg_error (GPG_ERR_GENERAL); + return rc; + } + app->did_chv2 = 1; + } + + rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen); + return rc; +} + + + + +/* Select the OpenPGP application on the card in SLOT. This function + must be used before any other OpenPGP application functions. */ +int +app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) +{ + static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 }; + int slot = app->slot; + int rc; + unsigned char *buffer; + size_t buflen; + + rc = iso7816_select_application (slot, aid, sizeof aid); + if (!rc) + { + /* fixme: get the full AID and check that the version is okay + with us. */ + rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); + if (rc) + goto leave; + if (opt.verbose) + { + log_info ("got AID: "); + log_printhex ("", buffer, buflen); + } + + if (sn) + { + *sn = buffer; + *snlen = buflen; + app->card_version = buffer[6] << 8; + app->card_version |= buffer[7]; + } + else + xfree (buffer); + + if (opt.verbose > 1) + dump_all_do (slot); + + app->fnc.learn_status = do_learn_status; + app->fnc.setattr = do_setattr; + app->fnc.genkey = do_genkey; + app->fnc.sign = do_sign; + app->fnc.auth = do_auth; + app->fnc.decipher = do_decipher; + app->fnc.change_pin = do_change_pin; + } + +leave: + return rc; +} + + + +/* This function is a hack to retrieve essential information about the + card to be displayed by simple tools. It mostly resembles what the + LEARN command returns. All parameters return allocated strings or + buffers or NULL if the data object is not available. All returned + values are sanitized. */ +int +app_openpgp_cardinfo (APP app, + char **serialno, + char **disp_name, + char **pubkey_url, + unsigned char **fpr1, + unsigned char **fpr2, + unsigned char **fpr3) +{ + int rc; + void *relptr; + unsigned char *value; + size_t valuelen; + + if (serialno) + { + time_t dummy; + + *serialno = NULL; + rc = app_get_serial_and_stamp (app, serialno, &dummy); + if (rc) + { + log_error ("error getting serial number: %s\n", gpg_strerror (rc)); + return rc; + } + } + + if (disp_name) + { + *disp_name = NULL; + relptr = get_one_do (app->slot, 0x005B, &value, &valuelen); + if (relptr) + { + *disp_name = make_printable_string (value, valuelen, 0); + xfree (relptr); + } + } + + if (pubkey_url) + { + *pubkey_url = NULL; + relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen); + if (relptr) + { + *pubkey_url = make_printable_string (value, valuelen, 0); + xfree (relptr); + } + } + + if (fpr1) + *fpr1 = NULL; + if (fpr2) + *fpr2 = NULL; + if (fpr3) + *fpr3 = NULL; + relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen); + if (relptr && valuelen >= 60) + { + if (fpr1) + { + *fpr1 = xmalloc (20); + memcpy (*fpr1, value + 0, 20); + } + if (fpr2) + { + *fpr2 = xmalloc (20); + memcpy (*fpr2, value + 20, 20); + } + if (fpr3) + { + *fpr3 = xmalloc (20); + memcpy (*fpr3, value + 40, 20); + } + } + xfree (relptr); + + return 0; +} + + + +/* This function is currently only used by the sc-copykeys program to + store a key on the smartcard. APP ist the application handle, + KEYNO is the number of the key and PINCB, PINCB_ARG are used to ask + for the SO PIN. TEMPLATE and TEMPLATE_LEN describe a buffer with + the key template to store. CREATED_AT is the timestamp used to + create the fingerprint. M, MLEN is the RSA modulus and E, ELEN the + RSA public exponent. This function silently overwrites an existing + key.*/ +int +app_openpgp_storekey (APP app, int keyno, + unsigned char *template, size_t template_len, + time_t created_at, + const unsigned char *m, size_t mlen, + const unsigned char *e, size_t elen, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc; + unsigned char fprbuf[20]; + + if (keyno < 1 || keyno > 3) + return gpg_error (GPG_ERR_INV_ID); + keyno--; + + { + char *pinvalue; + rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + if (rc) + { + log_error ("error getting PIN: %s\n", gpg_strerror (rc)); + return rc; + } + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + } + if (rc) + { + log_error ("verify CHV3 failed: rc=%04X\n", rc); + goto leave; + } + + rc = iso7816_put_data (app->slot, + (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, + template, template_len); + if (rc) + { + log_error ("failed to store the key: rc=%04X\n", rc); + rc = gpg_error (GPG_ERR_CARD); + goto leave; + } + +/* log_printhex ("RSA n:", m, mlen); */ +/* log_printhex ("RSA e:", e, elen); */ + + rc = store_fpr (app->slot, keyno, (u32)created_at, + m, mlen, e, elen, fprbuf, app->card_version); + + leave: + return rc; +} + + +/* Utility function for external tools: Read the public RSA key at + KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */ +int +app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, + unsigned char **e, size_t *elen) +{ + int rc; + const unsigned char *keydata, *a; + unsigned char *buffer; + size_t buflen, keydatalen, alen; + + *m = NULL; + *e = NULL; + + if (keyno < 1 || keyno > 3) + return gpg_error (GPG_ERR_INV_ID); + keyno--; + + rc = iso7816_read_public_key(app->slot, + keyno == 0? "\xB6" : + keyno == 1? "\xB8" : "\xA4", + 2, + &buffer, &buflen); + if (rc) + { + rc = gpg_error (GPG_ERR_CARD); + log_error ("reading key failed\n"); + goto leave; + } + + keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0); + if (!keydata) + { + log_error ("response does not contain the public key data\n"); + rc = gpg_error (GPG_ERR_CARD); + goto leave; + } + + a = find_tlv (keydata, keydatalen, 0x0081, &alen, 0); + if (!a) + { + log_error ("response does not contain the RSA modulus\n"); + rc = gpg_error (GPG_ERR_CARD); + goto leave; + } + *mlen = alen; + *m = xmalloc (alen); + memcpy (*m, a, alen); + + a = find_tlv (keydata, keydatalen, 0x0082, &alen, 0); + if (!e) + { + log_error ("response does not contain the RSA public exponent\n"); + rc = gpg_error (GPG_ERR_CARD); + goto leave; + } + *elen = alen; + *e = xmalloc (alen); + memcpy (*e, a, alen); + + leave: + xfree (buffer); + if (rc) + { + xfree (*m); *m = NULL; + xfree (*e); *e = NULL; + } + return rc; +} diff --git a/scd/app.c b/scd/app.c new file mode 100644 index 000000000..7a85df336 --- /dev/null +++ b/scd/app.c @@ -0,0 +1,278 @@ +/* app.c - Application selection. + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +#include "scdaemon.h" +#include "app-common.h" +#include "apdu.h" +#include "iso7816.h" + +/* The select the best fitting application and return a context. + Returns NULL if no application was found or no card is present. */ +APP +select_application (void) +{ + int reader_port = 32768; /* First USB reader. */ + int slot; + int rc; + APP app; + + slot = apdu_open_reader (reader_port); + if (slot == -1) + { + log_error ("card reader not available\n"); + return NULL; + } + + app = xtrycalloc (1, sizeof *app); + if (!app) + { + rc = out_of_core (); + log_info ("error allocating context: %s\n", gpg_strerror (rc)); + /*apdu_close_reader (slot);*/ + return NULL; + } + + app->slot = slot; + rc = app_select_openpgp (app, &app->serialno, &app->serialnolen); + if (rc) + { +/* apdu_close_reader (slot); */ + log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + xfree (app); + return NULL; + } + + app->initialized = 1; + return app; +} + + + +/* Retrieve the serial number and the time of the last update of the + card. The serial number is returned as a malloced string (hex + encoded) in SERIAL and the time of update is returned in STAMP. If + no update time is available the returned value is 0. Caller must + free SERIAL unless the function returns an error. */ +int +app_get_serial_and_stamp (APP app, char **serial, time_t *stamp) +{ + unsigned char *buf, *p; + int i; + + if (!app || !serial || !stamp) + return gpg_error (GPG_ERR_INV_VALUE); + + *serial = NULL; + *stamp = 0; /* not available */ + + buf = xtrymalloc (app->serialnolen * 2 + 1); + if (!buf) + return gpg_error_from_errno (errno); + for (p=buf, i=0; i < app->serialnolen; p +=2, i++) + sprintf (p, "%02X", app->serialno[i]); + *p = 0; + *serial = buf; + return 0; +} + + +/* Write out the application specifig status lines for the LEARN + command. */ +int +app_write_learn_status (APP app, CTRL ctrl) +{ + if (!app) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.learn_status) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + return app->fnc.learn_status (app, ctrl); +} + + +/* Perform a SETATTR operation. */ +int +app_setattr (APP app, const char *name, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *value, size_t valuelen) +{ + if (!app || !name || !*name || !value) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.setattr) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen); +} + +/* Create the signature and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; it + should return the PIN in an allocated buffer and put it into PIN. */ +int +app_sign (APP app, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + + if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.sign) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = app->fnc.sign (app, keyidstr, hashalgo, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + if (opt.verbose) + log_info ("operation sign result: %s\n", gpg_strerror (rc)); + return rc; +} + +/* Create the signature using the INTERNAL AUTHENTICATE command and + return the allocated result in OUTDATA. If a PIN is required the + PINCB will be used to ask for the PIN; it should return the PIN in + an allocated buffer and put it into PIN. */ +int +app_auth (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + + if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.auth) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = app->fnc.auth (app, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + if (opt.verbose) + log_info ("operation auth result: %s\n", gpg_strerror (rc)); + return rc; +} + + +/* Decrypt the data in INDATA and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; it + should return the PIN in an allocated buffer and put it into PIN. */ +int +app_decipher (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + + if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.decipher) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = app->fnc.decipher (app, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + if (opt.verbose) + log_info ("operation decipher result: %s\n", gpg_strerror (rc)); + return rc; +} + + +/* Perform a SETATTR operation. */ +int +app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc; + + if (!app || !keynostr || !*keynostr || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.genkey) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg); + if (opt.verbose) + log_info ("operation genkey result: %s\n", gpg_strerror (rc)); + return rc; +} + + +/* Perform a GET CHALLENGE operation. This fucntion is special as it + directly accesses the card without any application specific + wrapper. */ +int +app_get_challenge (APP app, size_t nbytes, unsigned char *buffer) +{ + if (!app || !nbytes || !buffer) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + return iso7816_get_challenge (app->slot, nbytes, buffer); +} + + + +/* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */ +int +app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc; + + if (!app || !chvnostr || !*chvnostr || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.change_pin) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg); + if (opt.verbose) + log_info ("operation change_pin result: %s\n", gpg_strerror (rc)); + return rc; +} + + + + + + diff --git a/scd/card-common.h b/scd/card-common.h new file mode 100644 index 000000000..31f0dfe8f --- /dev/null +++ b/scd/card-common.h @@ -0,0 +1,73 @@ +/* card-common.h - Common declarations for all card types + * 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 + */ + +#ifndef CARD_COMMON_H +#define CARD_COMMON_H + +/* Declaration of private data structure used by card-p15.c */ +struct p15private_s; + + +struct card_ctx_s { + int reader; /* used reader */ + struct sc_context *ctx; + struct sc_card *scard; + struct sc_pkcs15_card *p15card; /* only if there is a pkcs15 application */ + struct p15private_s *p15priv; /* private data used by card-p15.c */ + + struct { + int initialized; /* the card has been initialied and the function + pointers may be used. However for + unsupported operations the particular + function pointer is set to NULL */ + + int (*enum_keypairs) (CARD card, int idx, + unsigned char *keygrip, char **keyid); + int (*enum_certs) (CARD card, int idx, char **certid, int *certtype); + int (*read_cert) (CARD card, const char *certidstr, + unsigned char **cert, size_t *ncert); + int (*sign) (CARD card, + const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); + int (*decipher) (CARD card, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen); + } fnc; + +}; + +/*-- card.c --*/ +gpg_error_t map_sc_err (int rc); +int card_help_get_keygrip (KsbaCert cert, unsigned char *array); + +/*-- card-15.c --*/ +void p15_release_private_data (CARD card); + +/* constructors */ +void card_p15_bind (CARD card); +void card_dinsig_bind (CARD card); + + +#endif /*CARD_COMMON_H*/ diff --git a/scd/card-p15.c b/scd/card-p15.c new file mode 100644 index 000000000..3cf4ba519 --- /dev/null +++ b/scd/card-p15.c @@ -0,0 +1,502 @@ +/* card-p15.c - PKCS-15 based card access + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifdef HAVE_OPENSC +#include <opensc/pkcs15.h> +#include <ksba.h> + +#include "scdaemon.h" +#include "card-common.h" + + +struct p15private_s { + int n_prkey_rsa_objs; + struct sc_pkcs15_object *prkey_rsa_objs[32]; + int n_cert_objs; + struct sc_pkcs15_object *cert_objs[32]; +}; + + +/* Allocate private data. */ +static int +init_private_data (CARD card) +{ + struct p15private_s *priv; + int rc; + + if (card->p15priv) + return 0; /* already done. */ + + priv = xtrycalloc (1, sizeof *priv); + if (!priv) + return out_of_core (); + + /* OpenSC (0.7.0) is a bit strange in that the get_objects functions + tries to be a bit too clever and implicitly does an enumeration + which eventually leads to the fact that every call to this + fucntion returns one more macthing object. The old code in + p15_enum_keypairs assume that it would alwyas return the same + numer of objects and used this to figure out what the last object + enumerated is. We now do an enum_objects just once and keep it + in the private data. */ + rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, + priv->prkey_rsa_objs, + DIM (priv->prkey_rsa_objs)); + if (rc < 0) + { + log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); + xfree (priv); + return gpg_error (GPG_ERR_CARD); + } + priv->n_prkey_rsa_objs = rc; + + /* Read all certificate objects. */ + rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509, + priv->cert_objs, + DIM (priv->cert_objs)); + if (rc < 0) + { + log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); + xfree (priv); + return gpg_error (GPG_ERR_CARD); + } + priv->n_cert_objs = rc; + + card->p15priv = priv; + return 0; +} + + +/* Release private data used in this module. */ +void +p15_release_private_data (CARD card) +{ + if (!card->p15priv) + return; + xfree (card->p15priv); + card->p15priv = NULL; +} + + + +/* See card.c for interface description */ +static int +p15_enum_keypairs (CARD card, int idx, + unsigned char *keygrip, char **keyid) +{ + int rc; + KsbaError krc; + struct p15private_s *priv; + struct sc_pkcs15_object *tmpobj; + int nobjs; + struct sc_pkcs15_prkey_info *pinfo; + struct sc_pkcs15_cert_info *certinfo; + struct sc_pkcs15_cert *certder; + KsbaCert cert; + + rc = init_private_data (card); + if (rc) + return rc; + priv = card->p15priv; + nobjs = priv->n_prkey_rsa_objs; + rc = 0; + if (idx >= nobjs) + return -1; + pinfo = priv->prkey_rsa_objs[idx]->data; + + /* now we need to read the certificate so that we can calculate the + keygrip */ + rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj); + if (rc) + { + log_info ("certificate for private key %d not found: %s\n", + idx, sc_strerror (rc)); + /* note, that we return the ID anyway */ + rc = gpg_error (GPG_ERR_MISSING_CERTIFICATE); + goto return_keyid; + } + certinfo = tmpobj->data; + rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder); + if (rc) + { + log_info ("failed to read certificate for private key %d: %s\n", + idx, sc_strerror (rc)); + return gpg_error (GPG_ERR_CARD); + } + + cert = ksba_cert_new (); + if (!cert) + { + gpg_error_t tmperr = out_of_core (); + sc_pkcs15_free_certificate (certder); + return tmperr; + } + krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len); + sc_pkcs15_free_certificate (certder); + if (krc) + { + log_error ("failed to parse the certificate for private key %d: %s\n", + idx, ksba_strerror (krc)); + ksba_cert_release (cert); + return gpg_error (GPG_ERR_CARD); + } + if (card_help_get_keygrip (cert, keygrip)) + { + log_error ("failed to calculate the keygrip of private key %d\n", idx); + ksba_cert_release (cert); + return gpg_error (GPG_ERR_CARD); + } + ksba_cert_release (cert); + + rc = 0; + return_keyid: + if (keyid) + { + char *p; + int i; + + *keyid = p = xtrymalloc (9+pinfo->id.len*2+1); + if (!*keyid) + return out_of_core (); + p = stpcpy (p, "P15-5015."); + for (i=0; i < pinfo->id.len; i++, p += 2) + sprintf (p, "%02X", pinfo->id.value[i]); + *p = 0; + } + + return rc; +} + +/* See card.c for interface description */ +static int +p15_enum_certs (CARD card, int idx, char **certid, int *type) +{ + int rc; + struct p15private_s *priv; + struct sc_pkcs15_object *obj; + struct sc_pkcs15_cert_info *cinfo; + int nobjs; + + rc = init_private_data (card); + if (rc) + return rc; + priv = card->p15priv; + nobjs = priv->n_cert_objs; + rc = 0; + if (idx >= nobjs) + return -1; + obj = priv->cert_objs[idx]; + cinfo = obj->data; + + if (certid) + { + char *p; + int i; + + *certid = p = xtrymalloc (9+cinfo->id.len*2+1); + if (!*certid) + return out_of_core (); + p = stpcpy (p, "P15-5015."); + for (i=0; i < cinfo->id.len; i++, p += 2) + sprintf (p, "%02X", cinfo->id.value[i]); + *p = 0; + } + if (type) + { + if (!obj->df) + *type = 0; /* unknown */ + else if (obj->df->type == SC_PKCS15_CDF) + *type = 100; + else if (obj->df->type == SC_PKCS15_CDF_TRUSTED) + *type = 101; + else if (obj->df->type == SC_PKCS15_CDF_USEFUL) + *type = 102; + else + *type = 0; /* error -> unknown */ + } + + return rc; +} + + + +static int +idstr_to_id (const char *idstr, struct sc_pkcs15_id *id) +{ + const char *s; + int n; + + /* For now we only support the standard DF */ + if (strncmp (idstr, "P15-5015.", 9) ) + return gpg_error (GPG_ERR_INV_ID); + for (s=idstr+9, n=0; hexdigitp (s); s++, n++) + ; + if (*s || (n&1)) + return gpg_error (GPG_ERR_INV_ID); /*invalid or odd number of digits*/ + n /= 2; + if (!n || n > SC_PKCS15_MAX_ID_SIZE) + return gpg_error (GPG_ERR_INV_ID); /* empty or too large */ + for (s=idstr+9, n=0; *s; s += 2, n++) + id->value[n] = xtoi_2 (s); + id->len = n; + return 0; +} + + +/* See card.c for interface description */ +static int +p15_read_cert (CARD card, const char *certidstr, + unsigned char **cert, size_t *ncert) +{ + struct sc_pkcs15_object *tmpobj; + struct sc_pkcs15_id certid; + struct sc_pkcs15_cert_info *certinfo; + struct sc_pkcs15_cert *certder; + int rc; + + if (!card || !certidstr || !cert || !ncert) + return gpg_error (GPG_ERR_INV_VALUE); + if (!card->p15card) + return gpg_error (GPG_ERR_NO_PKCS15_APP); + + rc = idstr_to_id (certidstr, &certid); + if (rc) + return rc; + + rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj); + if (rc) + { + log_info ("certificate '%s' not found: %s\n", + certidstr, sc_strerror (rc)); + return -1; + } + certinfo = tmpobj->data; + rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder); + if (rc) + { + log_info ("failed to read certificate '%s': %s\n", + certidstr, sc_strerror (rc)); + return gpg_error (GPG_ERR_CARD); + } + + *cert = xtrymalloc (certder->data_len); + if (!*cert) + { + gpg_error_t tmperr = out_of_core (); + sc_pkcs15_free_certificate (certder); + return tmperr; + } + memcpy (*cert, certder->data, certder->data_len); + *ncert = certder->data_len; + sc_pkcs15_free_certificate (certder); + return 0; +} + + + + + +static int +p15_prepare_key (CARD card, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, struct sc_pkcs15_object **r_keyobj) +{ + struct sc_pkcs15_id keyid; + struct sc_pkcs15_pin_info *pin; + struct sc_pkcs15_object *keyobj, *pinobj; + char *pinvalue; + int rc; + + rc = idstr_to_id (keyidstr, &keyid); + if (rc) + return rc; + + rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj); + if (rc < 0) + { + log_error ("private key not found: %s\n", sc_strerror(rc)); + return gpg_error (GPG_ERR_NO_SECRET_KEY); + } + + rc = sc_pkcs15_find_pin_by_auth_id (card->p15card, + &keyobj->auth_id, &pinobj); + if (rc) + { + log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc)); + return gpg_error (GPG_ERR_BAD_PIN_METHOD); + } + pin = pinobj->data; + + /* Fixme: pack this into a verification loop */ + /* Fixme: we might want to pass pin->min_length and + pin->stored_length */ + rc = pincb (pincb_arg, pinobj->label, &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc)); + return rc; + } + + rc = sc_pkcs15_verify_pin (card->p15card, pin, + pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_info ("PIN verification failed: %s\n", sc_strerror (rc)); + return gpg_error (GPG_ERR_BAD_PIN); + } + + /* fixme: check wheter we need to release KEYOBJ in case of an error */ + *r_keyobj = keyobj; + return 0; +} + + +/* See card.c for interface description */ +static int +p15_sign (CARD card, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + unsigned int cryptflags; + struct sc_pkcs15_object *keyobj; + int rc; + unsigned char *outbuf = NULL; + size_t outbuflen; + + if (hashalgo != GCRY_MD_SHA1) + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + + rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj); + if (rc) + return rc; + + cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1; + + outbuflen = 1024; + outbuf = xtrymalloc (outbuflen); + if (!outbuf) + return out_of_core (); + + rc = sc_pkcs15_compute_signature (card->p15card, keyobj, + cryptflags, + indata, indatalen, + outbuf, outbuflen ); + if (rc < 0) + { + log_error ("failed to create signature: %s\n", sc_strerror (rc)); + rc = gpg_error (GPG_ERR_CARD); + } + else + { + *outdatalen = rc; + *outdata = outbuf; + outbuf = NULL; + rc = 0; + } + + xfree (outbuf); + return rc; +} + + +/* See card.c for description */ +static int +p15_decipher (CARD card, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + struct sc_pkcs15_object *keyobj; + int rc; + unsigned char *outbuf = NULL; + size_t outbuflen; + + rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj); + if (rc) + return rc; + + if (card && card->scard && card->scard->driver + && !strcasecmp (card->scard->driver->short_name, "tcos")) + { + /* very ugly hack to force the use of a local key. We need this + until we have fixed the initialization code for TCOS cards */ + struct sc_pkcs15_prkey_info *prkey = keyobj->data; + if ( !(prkey->key_reference & 0x80)) + { + prkey->key_reference |= 0x80; + log_debug ("using TCOS hack to force the use of local keys\n"); + } + if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6') + { + prkey->key_reference |= 1; + log_debug ("warning: using even more TCOS hacks\n"); + } + } + + outbuflen = indatalen < 256? 256 : indatalen; + outbuf = xtrymalloc (outbuflen); + if (!outbuf) + return out_of_core (); + + rc = sc_pkcs15_decipher (card->p15card, keyobj, + 0, + indata, indatalen, + outbuf, outbuflen); + if (rc < 0) + { + log_error ("failed to decipher the data: %s\n", sc_strerror (rc)); + rc = gpg_error (GPG_ERR_CARD); + } + else + { + *outdatalen = rc; + *outdata = outbuf; + outbuf = NULL; + rc = 0; + } + + xfree (outbuf); + return rc; +} + + + +/* Bind our operations to the card */ +void +card_p15_bind (CARD card) +{ + card->fnc.enum_keypairs = p15_enum_keypairs; + card->fnc.enum_certs = p15_enum_certs; + card->fnc.read_cert = p15_read_cert; + card->fnc.sign = p15_sign; + card->fnc.decipher = p15_decipher; +} +#endif /*HAVE_OPENSC*/ diff --git a/scd/card.c b/scd/card.c new file mode 100644 index 000000000..02b7bfdbf --- /dev/null +++ b/scd/card.c @@ -0,0 +1,564 @@ +/* card.c - SCdaemon card functions + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifdef HAVE_OPENSC +#include <opensc/pkcs15.h> +#endif +#include <ksba.h> + +#include "scdaemon.h" +#include "card-common.h" + +/* Map the SC error codes to the GNUPG ones */ +gpg_error_t +map_sc_err (int rc) +{ + gpg_err_code_t e; + + switch (rc) + { + case 0: e = 0; break; +#ifdef HAVE_OPENSC + case SC_ERROR_NOT_SUPPORTED: e = GPG_ERR_NOT_SUPPORTED; break; + case SC_ERROR_PKCS15_APP_NOT_FOUND: e = GPG_ERR_NO_PKCS15_APP; break; + case SC_ERROR_OUT_OF_MEMORY: e = GPG_ERR_ENOMEM; break; + case SC_ERROR_CARD_NOT_PRESENT: e = GPG_ERR_CARD_NOT_PRESENT; break; + case SC_ERROR_CARD_REMOVED: e = GPG_ERR_CARD_REMOVED; break; + case SC_ERROR_INVALID_CARD: e = GPG_ERR_INV_CARD; break; +#endif + default: e = GPG_ERR_CARD; break; + } + return gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, e); +} + +/* Get the keygrip from CERT, return 0 on success */ +int +card_help_get_keygrip (KsbaCert cert, unsigned char *array) +{ + gcry_sexp_t s_pkey; + int rc; + KsbaSexp p; + size_t n; + + p = ksba_cert_get_public_key (cert); + if (!p) + return -1; /* oops */ + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + return -1; /* libksba did not return a proper S-expression */ + rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + xfree (p); + if (rc) + return -1; /* can't parse that S-expression */ + array = gcry_pk_get_keygrip (s_pkey, array); + gcry_sexp_release (s_pkey); + if (!array) + return -1; /* failed to calculate the keygrip */ + return 0; +} + + + + + + + +/* Create a new context for the card and figures out some basic + information of the card. Detects whgether a PKCS_15 application is + stored. + + Common errors: GPG_ERR_CARD_NOT_PRESENT */ +int +card_open (CARD *rcard) +{ +#ifdef HAVE_OPENSC + CARD card; + int rc; + + card = xtrycalloc (1, sizeof *card); + if (!card) + return out_of_core (); + card->reader = 0; + + rc = sc_establish_context (&card->ctx, "scdaemon"); + if (rc) + { + log_error ("failed to establish SC context: %s\n", sc_strerror (rc)); + rc = map_sc_err (rc); + goto leave; + } + if (card->reader >= card->ctx->reader_count) + { + log_error ("no card reader available\n"); + rc = gpg_error (GPG_ERR_CARD); + goto leave; + } + card->ctx->error_file = log_get_stream (); + card->ctx->debug = opt.debug_sc; + card->ctx->debug_file = log_get_stream (); + + if (sc_detect_card_presence (card->ctx->reader[card->reader], 0) != 1) + { + rc = gpg_error (GPG_ERR_CARD_NOT_PRESENT); + goto leave; + } + + rc = sc_connect_card (card->ctx->reader[card->reader], 0, &card->scard); + if (rc) + { + log_error ("failed to connect card in reader %d: %s\n", + card->reader, sc_strerror (rc)); + rc = map_sc_err (rc); + goto leave; + } + if (opt.verbose) + log_info ("connected to card in reader %d using driver `%s'\n", + card->reader, card->scard->driver->name); + + rc = sc_lock (card->scard); + if (rc) + { + log_error ("can't lock card in reader %d: %s\n", + card->reader, sc_strerror (rc)); + rc = map_sc_err (rc); + goto leave; + } + + + leave: + if (rc) + card_close (card); + else + *rcard = card; + + return rc; +#else + return gpg_error (GPG_ERR_NOT_SUPPORTED); +#endif +} + + +/* Close a card and release all resources */ +void +card_close (CARD card) +{ + if (card) + { +#ifdef HAVE_OPENSC + if (card->p15card) + { + sc_pkcs15_unbind (card->p15card); + card->p15card = NULL; + } + if (card->p15priv) + p15_release_private_data (card); + if (card->scard) + { + sc_unlock (card->scard); + sc_disconnect_card (card->scard, 0); + card->scard = NULL; + } + if (card->ctx) + { + sc_release_context (card->ctx); + card->ctx = NULL; + } +#endif + xfree (card); + } +} + +/* Locate a simple TLV encoded data object in BUFFER of LENGTH and + return a pointer to value as well as its length in NBYTES. Return + NULL if it was not found. Note, that the function does not check + whether the value fits into the provided buffer. */ +#ifdef HAVE_OPENSC +static const char * +find_simple_tlv (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes) +{ + const char *s = buffer; + size_t n = length; + size_t len; + + for (;;) + { + buffer = s; + if (n < 2) + return NULL; /* buffer too short for tag and length. */ + len = s[1]; + s += 2; n -= 2; + if (len == 255) + { + if (n < 2) + return NULL; /* we expected 2 more bytes with the length. */ + len = (s[0] << 8) | s[1]; + s += 2; n -= 2; + } + if (*buffer == tag) + { + *nbytes = len; + return s; + } + if (len > n) + return NULL; /* buffer too short to skip to the next tag. */ + s += len; n -= len; + } +} +#endif /*HAVE_OPENSC*/ + +/* Find the ICC Serial Number within the provided BUFFER of LENGTH + (which should contain the GDO file) and return it as a hex encoded + string and allocated string in SERIAL. Return an error code when + the ICCSN was not found. */ +#ifdef HAVE_OPENSC +static int +find_iccsn (const unsigned char *buffer, size_t length, char **serial) +{ + size_t n; + const unsigned char *s; + char *p; + + s = find_simple_tlv (buffer, length, 0x5A, &n); + if (!s) + return gpg_error (GPG_ERR_CARD); + length -= s - buffer; + if (n > length) + { + /* Oops, it does not fit into the buffer. This is an invalid + encoding (or the buffer is too short. However, I have some + test cards with such an invalid encoding and therefore I use + this ugly workaround to return something I can further + experiment with. */ + if (n == 0x0D && length+1 == n) + { + log_debug ("enabling BMI testcard workaround\n"); + n--; + } + else + return gpg_error (GPG_ERR_CARD); /* Bad encoding; does + not fit into buffer. */ + } + if (!n) + return gpg_error (GPG_ERR_CARD); /* Well, that is too short. */ + + *serial = p = xtrymalloc (2*n+1); + if (!*serial) + return out_of_core (); + for (; n; n--, p += 2, s++) + sprintf (p, "%02X", *s); + *p = 0; + return 0; +} +#endif /*HAVE_OPENSC*/ + +/* Retrieve the serial number and the time of the last update of the + card. The serial number is returned as a malloced string (hex + encoded) in SERIAL and the time of update is returned in STAMP. + If no update time is available the returned value is 0. The serial + is mandatory for a PKCS_15 application and an error will be + returned if this value is not availbale. For non-PKCS-15 cards a + serial number is constructed by other means. Caller must free + SERIAL unless the function returns an error. */ +int +card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp) +{ +#ifdef HAVE_OPENSC + int rc; + struct sc_path path; + struct sc_file *file; + unsigned char buf[256]; + int buflen; +#endif + + if (!card || !serial || !stamp) + return gpg_error (GPG_ERR_INV_VALUE); + + *serial = NULL; + *stamp = 0; /* not available */ + +#ifdef HAVE_OPENSC + if (!card->fnc.initialized) + { + card->fnc.initialized = 1; + /* The first use of this card tries to figure out the type of the card + and sets up the function pointers. */ + rc = sc_pkcs15_bind (card->scard, &card->p15card); + if (rc) + { + if (rc != SC_ERROR_PKCS15_APP_NOT_FOUND) + log_error ("binding of existing PKCS-15 failed in reader %d: %s\n", + card->reader, sc_strerror (rc)); + card->p15card = NULL; + rc = 0; + } + if (card->p15card) + card_p15_bind (card); + else + card_dinsig_bind (card); + card->fnc.initialized = 1; + } + + + /* We should lookup the iso 7812-1 and 8583-3 - argh ISO + practice is suppressing innovation - IETF rules! So we + always get the serialnumber from the 2F02 GDO file. */ + /* FIXME: in case we can't parse the 2F02 EF and we have a P15 card, + we should get the serial number from the respective P15 file */ + sc_format_path ("3F002F02", &path); + rc = sc_select_file (card->scard, &path, &file); + if (rc) + { + log_error ("sc_select_file failed: %s\n", sc_strerror (rc)); + return gpg_error (GPG_ERR_CARD); + } + if (file->type != SC_FILE_TYPE_WORKING_EF + || file->ef_structure != SC_FILE_EF_TRANSPARENT) + { + log_error ("wrong type or structure of GDO file\n"); + sc_file_free (file); + return gpg_error (GPG_ERR_CARD); + } + + if (!file->size || file->size >= DIM(buf) ) + { /* FIXME: Use a real parser */ + log_error ("unsupported size of GDO file (%d)\n", file->size); + sc_file_free (file); + return gpg_error (GPG_ERR_CARD); + } + buflen = file->size; + + rc = sc_read_binary (card->scard, 0, buf, buflen, 0); + sc_file_free (file); + if (rc < 0) + { + log_error ("error reading GDO file: %s\n", sc_strerror (rc)); + return gpg_error (GPG_ERR_CARD); + } + if (rc != buflen) + { + log_error ("short read on GDO file\n"); + return gpg_error (GPG_ERR_CARD); + } + + rc = find_iccsn (buf, buflen, serial); + if (gpg_err_code (rc) == GPG_ERR_CARD) + log_error ("invalid structure of GDO file\n"); + if (!rc && card->p15card && !strcmp (*serial, "D27600000000000000000000")) + { /* This is a German card with a silly serial number. Try to get + the serial number from the EF(TokenInfo). We indicate such a + serial number by the using the prefix: "FF0100". */ + const char *efser = card->p15card->serial_number; + char *p; + + if (!efser) + efser = ""; + + xfree (*serial); + *serial = NULL; + p = xtrymalloc (strlen (efser) + 7); + if (!p) + rc = out_of_core (); + else + { + strcpy (p, "FF0100"); + strcpy (p+6, efser); + *serial = p; + } + } + else if (!rc && **serial == 'F' && (*serial)[1] == 'F') + { /* The serial number starts with our special prefix. This + requires that we put our default prefix "FF0000" in front. */ + char *p = xtrymalloc (strlen (*serial) + 7); + if (!p) + { + xfree (*serial); + *serial = NULL; + rc = out_of_core (); + } + else + { + strcpy (p, "FF0000"); + strcpy (p+6, *serial); + xfree (*serial); + *serial = p; + } + } + return rc; +#else + return gpg_error (GPG_ERR_NOT_SUPPORTED); +#endif +} + + +/* Enumerate all keypairs on the card and return the Keygrip as well + as the internal identification of the key. KEYGRIP must be a + caller provided buffer with a size of 20 bytes which will receive + the KEYGRIP of the keypair. If KEYID is not NULL, it returns the + ID field of the key in allocated memory; this is a string without + spaces. The function returns -1 when all keys have been + enumerated. Note that the error GPG_ERR_MISSING_CERTIFICATE may be + returned if there is just the private key but no public key (ie.e a + certificate) available. Applications might want to continue + enumerating after this error.*/ +int +card_enum_keypairs (CARD card, int idx, + unsigned char *keygrip, + char **keyid) +{ + int rc; + + if (keyid) + *keyid = NULL; + + if (!card || !keygrip) + return gpg_error (GPG_ERR_INV_VALUE); + if (idx < 0) + return gpg_error (GPG_ERR_INV_INDEX); + if (!card->fnc.initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!card->fnc.enum_keypairs) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = card->fnc.enum_keypairs (card, idx, keygrip, keyid); + if (opt.verbose) + log_info ("card operation enum_keypairs result: %s\n", + gpg_strerror (rc)); + return rc; +} + + +/* Enumerate all trusted certificates available on the card, return + their ID in CERT and the type in CERTTYPE. Types of certificates + are: + 0 := Unknown + 100 := Regular X.509 cert + 101 := Trusted X.509 cert + 102 := Useful X.509 cert + */ +int +card_enum_certs (CARD card, int idx, char **certid, int *certtype) +{ + int rc; + + if (certid) + *certid = NULL; + + if (!card) + return gpg_error (GPG_ERR_INV_VALUE); + if (idx < 0) + return gpg_error (GPG_ERR_INV_INDEX); + if (!card->fnc.initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!card->fnc.enum_certs) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = card->fnc.enum_certs (card, idx, certid, certtype); + if (opt.verbose) + log_info ("card operation enum_certs result: %s\n", + gpg_strerror (rc)); + return rc; +} + + + +/* Read the certificate identified by CERTIDSTR which is the + hexadecimal encoded ID of the certificate, prefixed with the string + "3F005015.". The certificate is return in DER encoded form in CERT + and NCERT. */ +int +card_read_cert (CARD card, const char *certidstr, + unsigned char **cert, size_t *ncert) +{ + int rc; + + if (!card || !certidstr || !cert || !ncert) + return gpg_error (GPG_ERR_INV_VALUE); + if (!card->fnc.initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!card->fnc.read_cert) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = card->fnc.read_cert (card, certidstr, cert, ncert); + if (opt.verbose) + log_info ("card operation read_cert result: %s\n", gpg_strerror (rc)); + return rc; +} + + +/* Create the signature and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; it + should return the PIN in an allocated buffer and put it into PIN. */ +int +card_sign (CARD card, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + + if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!card->fnc.initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!card->fnc.sign) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = card->fnc.sign (card, keyidstr, hashalgo, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + if (opt.verbose) + log_info ("card operation sign result: %s\n", gpg_strerror (rc)); + return rc; +} + + +/* Create the signature and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; it + should return the PIN in an allocated buffer and put it into PIN. */ +int +card_decipher (CARD card, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + int rc; + + if (!card || !indata || !indatalen || !outdata || !outdatalen || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!card->fnc.initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!card->fnc.decipher) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = card->fnc.decipher (card, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + if (opt.verbose) + log_info ("card operation decipher result: %s\n", gpg_strerror (rc)); + return rc; +} + diff --git a/scd/command.c b/scd/command.c new file mode 100644 index 000000000..c53af84f9 --- /dev/null +++ b/scd/command.c @@ -0,0 +1,1034 @@ +/* command.c - SCdaemon command handler + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <ksba.h> + +#include <assuan.h> + +#include "scdaemon.h" +#include "app-common.h" + +/* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */ +#define MAXLEN_PIN 100 + +#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) + +/* Data used to associate an Assuan context with local server data */ +struct server_local_s { + ASSUAN_CONTEXT assuan_ctx; +}; + + +/* Check whether the option NAME appears in LINE */ +static int +has_option (const char *line, const char *name) +{ + const char *s; + int n = strlen (name); + + s = strstr (line, name); + return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); +} + + + + +/* Note, that this reset_notify is also used for cleanup purposes. */ +static void +reset_notify (ASSUAN_CONTEXT ctx) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + if (ctrl->card_ctx) + { + card_close (ctrl->card_ctx); + ctrl->card_ctx = NULL; + xfree (ctrl->in_data.value); + ctrl->in_data.value = NULL; + } + if (ctrl->app_ctx) + { + /* FIXME: close the application. */ + xfree (ctrl->app_ctx); + ctrl->app_ctx = NULL; + } +} + + +static int +option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) +{ + return 0; +} + + +/* If the card has not yet been opened, do it. Note that this + function returns an Assuan error, so don't map the error a second + time */ +static AssuanError +open_card (CTRL ctrl) +{ + if (ctrl->app_ctx) + return 0; /* Already initialized for one specific application. */ + if (ctrl->card_ctx) + return 0; /* Already initialized using a card context. */ + + ctrl->app_ctx = select_application (); + if (!ctrl->app_ctx) + { /* No application found - fall back to old mode. */ + int rc = card_open (&ctrl->card_ctx); + if (rc) + return map_to_assuan_status (rc); + } + return 0; +} + + +/* Do the percent and plus/space unescaping in place and return tghe + length of the valid buffer. */ +static size_t +percent_plus_unescape (unsigned char *string) +{ + unsigned char *p = string; + size_t n = 0; + + while (*string) + { + if (*string == '%' && string[1] && string[2]) + { + string++; + *p++ = xtoi_2 (string); + n++; + string+= 2; + } + else if (*string == '+') + { + *p++ = ' '; + n++; + string++; + } + else + { + *p++ = *string++; + n++; + } + } + + return n; +} + + + +/* SERIALNO + + Return the serial number of the card using a status reponse. This + functon should be used to check for the presence of a card. + + This function is special in that it can be used to reset the card. + Most other functions 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 calls this function. + */ +static int +cmd_serialno (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc = 0; + char *serial_and_stamp; + char *serial; + time_t stamp; + + if ((rc = open_card (ctrl))) + return rc; + + if (ctrl->app_ctx) + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); + else + rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); + if (rc) + return map_to_assuan_status (rc); + rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); + xfree (serial); + if (rc < 0) + return ASSUAN_Out_Of_Core; + rc = 0; + assuan_write_status (ctx, "SERIALNO", serial_and_stamp); + free (serial_and_stamp); + return 0; +} + + + + +/* LEARN [--force] + + Learn all useful information of the currently inserted card. When + used without the force options, the command might do an INQUIRE + like this: + + INQUIRE KNOWNCARDP <hexstring_with_serialNumber> <timestamp> + + The client should just send an "END" if the processing should go on + or a "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: + + S APPTYPE <apptype> + + This returns the type of the application, currently the strings: + + P15 = PKCS-15 structure used + DINSIG = DIN SIG + OPENPGP = OpenPGP card + + are implemented. These strings are aliases for the AID + + S KEYPAIRINFO <hexstring_with_keygrip> <hexstring_with_id> + + If there is no certificate yet stored on the card a single "X" is + returned as the keygrip. In addition to the keypair info, information + about all certificates stored on the card is also returned: + + S CERTINFO <certtype> <hexstring_with_id> + + Where CERTTYPE is a number indicating the type of certificate: + 0 := Unknown + 100 := Regular X.509 cert + 101 := Trusted X.509 cert + 102 := Useful X.509 cert + + For certain cards, more information will be returned: + + S KEY-FPR <no> <hexstring> + + For OpenPGP cards this returns the stored fingerprints of the + keys. This can be used check whether a key is available on the + card. NO may be 1, 2 or 3. + + S CA-FPR <no> <hexstring> + + Similar to above, these are the fingerprints of keys assumed to be + ultimately trusted. + + S DISP-NAME <name_of_card_holder> + + The name of the card holder as stored on the card; percent + aescaping takes place, spaces are encoded as '+' + + S PUBKEY-URL <url> + + The URL to be used for locating the entire public key. + +*/ +static int +cmd_learn (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc = 0; + int idx; + + if ((rc = open_card (ctrl))) + return rc; + + /* Unless the force option is used we try a shortcut by identifying + the card using a serial number and inquiring the client with + that. The client may choose to cancel the operation if he already + knows about this card */ + { + char *serial_and_stamp; + char *serial; + time_t stamp; + + if (ctrl->app_ctx) + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); + else + rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); + if (rc) + return map_to_assuan_status (rc); + rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); + xfree (serial); + if (rc < 0) + return ASSUAN_Out_Of_Core; + rc = 0; + assuan_write_status (ctx, "SERIALNO", serial_and_stamp); + + if (!has_option (line, "--force")) + { + char *command; + + rc = asprintf (&command, "KNOWNCARDP %s", serial_and_stamp); + if (rc < 0) + { + free (serial_and_stamp); + return ASSUAN_Out_Of_Core; + } + rc = 0; + rc = assuan_inquire (ctx, command, NULL, NULL, 0); + free (command); /* (must use standard free here) */ + if (rc) + { + if (rc != ASSUAN_Canceled) + log_error ("inquire KNOWNCARDP failed: %s\n", + assuan_strerror (rc)); + free (serial_and_stamp); + return rc; + } + /* not canceled, so we have to proceeed */ + } + free (serial_and_stamp); + } + + /* Return information about the certificates. */ + if (ctrl->app_ctx) + rc = -1; /* This information is not yet available for applications. */ + for (idx=0; !rc; idx++) + { + char *certid; + int certtype; + + rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype); + if (!rc) + { + char *buf; + + buf = xtrymalloc (40 + 1 + strlen (certid) + 1); + if (!buf) + rc = out_of_core (); + else + { + sprintf (buf, "%d %s", certtype, certid); + assuan_write_status (ctx, "CERTINFO", buf); + xfree (buf); + } + } + xfree (certid); + } + if (rc == -1) + rc = 0; + + + /* Return information about the keys. */ + if (ctrl->app_ctx) + rc = -1; /* This information is not yet available for applications. */ + for (idx=0; !rc; idx++) + { + unsigned char keygrip[20]; + char *keyid; + int no_cert = 0; + + rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid); + if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid) + { + /* this does happen with an incomplete personalized + card; i.e. during the time we have stored the key on the + card but not stored the certificate; probably becuase it + has not yet been received back from the CA. Note that we + must release KEYID in this case. */ + rc = 0; + no_cert = 1; + } + if (!rc) + { + char *buf, *p; + + buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1); + if (!buf) + rc = out_of_core (); + else + { + int i; + + if (no_cert) + *p++ = 'X'; + else + { + for (i=0; i < 20; i++, p += 2) + sprintf (p, "%02X", keygrip[i]); + } + *p++ = ' '; + strcpy (p, keyid); + assuan_write_status (ctx, "KEYPAIRINFO", buf); + xfree (buf); + } + } + xfree (keyid); + } + if (rc == -1) + rc = 0; + + if (!rc && ctrl->app_ctx) + rc = app_write_learn_status (ctrl->app_ctx, ctrl); + + + return map_to_assuan_status (rc); +} + + + +/* READCERT <hexified_certid> + + */ +static int +cmd_readcert (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char *cert; + size_t ncert; + + if ((rc = open_card (ctrl))) + return rc; + + if (ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); + if (rc) + { + log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); + } + if (!rc) + { + rc = assuan_send_data (ctx, cert, ncert); + xfree (cert); + if (rc) + return rc; + } + + return map_to_assuan_status (rc); +} + + +/* READKEY <hexified_certid> + + Return the public key for the given cert or key ID as an standard + S-Expression. */ +static int +cmd_readkey (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char *cert = NULL; + size_t ncert, n; + KsbaCert kc = NULL; + KsbaSexp p; + + if ((rc = open_card (ctrl))) + return rc; + + if (ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); + if (rc) + { + log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + kc = ksba_cert_new (); + if (!kc) + { + rc = out_of_core (); + xfree (cert); + goto leave; + } + rc = ksba_cert_init_from_mem (kc, cert, ncert); + if (rc) + { + log_error ("failed to parse the certificate: %s\n", ksba_strerror (rc)); + rc = map_ksba_err (rc); + goto leave; + } + + p = ksba_cert_get_public_key (kc); + if (!p) + { + rc = gpg_error (GPG_ERR_NO_PUBKEY); + goto leave; + } + + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + rc = assuan_send_data (ctx, p, n); + rc = map_assuan_err (rc); + xfree (p); + + + leave: + ksba_cert_release (kc); + xfree (cert); + return map_to_assuan_status (rc); +} + + + + +/* SETDATA <hexstring> + + The client should use this command to tell us the data he want to + sign. */ +static int +cmd_setdata (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int n; + char *p; + unsigned char *buf; + + /* parse the hexstring */ + for (p=line,n=0; hexdigitp (p); p++, n++) + ; + if (*p) + return set_error (Parameter_Error, "invalid hexstring"); + if (!n) + return set_error (Parameter_Error, "no data given"); + if ((n&1)) + return set_error (Parameter_Error, "odd number of digits"); + n /= 2; + buf = xtrymalloc (n); + if (!buf) + return ASSUAN_Out_Of_Core; + + ctrl->in_data.value = buf; + ctrl->in_data.valuelen = n; + for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++) + buf[n] = xtoi_2 (p); + return 0; +} + + + +static int +pin_cb (void *opaque, const char *info, char **retstr) +{ + ASSUAN_CONTEXT ctx = opaque; + char *command; + int rc; + char *value; + size_t valuelen; + + *retstr = NULL; + log_debug ("asking for PIN '%s'\n", info); + + rc = asprintf (&command, "NEEDPIN %s", info); + if (rc < 0) + return out_of_core (); + + /* FIXME: Write an inquire function which returns the result in + secure memory */ + rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); + free (command); + if (rc) + return map_assuan_err (rc); + + if (!valuelen || value[valuelen-1]) + { + /* We require that the returned value is an UTF-8 string */ + xfree (value); + return gpg_error (GPG_ERR_INV_RESPONSE); + } + *retstr = value; + return 0; +} + + +/* PKSIGN <hexified_id> + + */ +static int +cmd_pksign (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char *outdata; + size_t outdatalen; + char *keyidstr; + + if ((rc = open_card (ctrl))) + return rc; + + /* We have to use a copy of the key ID because the function may use + the pin_cb which in turn uses the assuan line buffer and thus + overwriting the original line with the keyid */ + keyidstr = strdup (line); + if (!keyidstr) + return ASSUAN_Out_Of_Core; + + if (ctrl->app_ctx) + rc = app_sign (ctrl->app_ctx, + keyidstr, GCRY_MD_SHA1, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + else + rc = card_sign (ctrl->card_ctx, + keyidstr, GCRY_MD_SHA1, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + free (keyidstr); + if (rc) + { + log_error ("card_sign failed: %s\n", gpg_strerror (rc)); + } + else + { + rc = assuan_send_data (ctx, outdata, outdatalen); + xfree (outdata); + if (rc) + return rc; /* that is already an assuan error code */ + } + + return map_to_assuan_status (rc); +} + +/* PKAUTH <hexified_id> + + */ +static int +cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char *outdata; + size_t outdatalen; + char *keyidstr; + + if ((rc = open_card (ctrl))) + return rc; + + if (!ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + /* We have to use a copy of the key ID because the function may use + the pin_cb which in turn uses the assuan line buffer and thus + overwriting the original line with the keyid */ + keyidstr = strdup (line); + if (!keyidstr) + return ASSUAN_Out_Of_Core; + + rc = app_auth (ctrl->app_ctx, + keyidstr, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + free (keyidstr); + if (rc) + { + log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc)); + } + else + { + rc = assuan_send_data (ctx, outdata, outdatalen); + xfree (outdata); + if (rc) + return rc; /* that is already an assuan error code */ + } + + return map_to_assuan_status (rc); +} + +/* PKDECRYPT <hexified_id> + + */ +static int +cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char *outdata; + size_t outdatalen; + char *keyidstr; + + if ((rc = open_card (ctrl))) + return rc; + + keyidstr = strdup (line); + if (!keyidstr) + return ASSUAN_Out_Of_Core; + if (ctrl->app_ctx) + rc = app_decipher (ctrl->app_ctx, + keyidstr, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + else + rc = card_decipher (ctrl->card_ctx, + keyidstr, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + free (keyidstr); + if (rc) + { + log_error ("card_create_signature failed: %s\n", gpg_strerror (rc)); + } + else + { + rc = assuan_send_data (ctx, outdata, outdatalen); + xfree (outdata); + if (rc) + return rc; /* that is already an assuan error code */ + } + + return map_to_assuan_status (rc); +} + + +/* SETATTR <name> <value> + + This command is used to store data on a a smartcard. The allowed + names and values are depend on the currently selected smartcard + application. NAME and VALUE must be percent and '+' escaped. + + However, the curent implementation assumes that Name is not escaped; + this works as long as noone uses arbitrary escaping. + + A PIN will be requested for most NAMEs. See the corresponding + setattr function of the actually used application (app-*.c) for + details. */ +static int +cmd_setattr (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *keyword; + int keywordlen; + size_t nbytes; + + if ((rc = open_card (ctrl))) + return rc; + + keyword = line; + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + if (*line) + *line++ = 0; + while (spacep (line)) + line++; + nbytes = percent_plus_unescape (line); + + rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes); + + return map_to_assuan_status (rc); +} + +/* GENKEY [--force] <no> + + Generate a key on-card identified by NO, which is application + specific. Return values are application specific. For OpenPGP + cards 2 status lines are returned: + + S KEY-FPR <hexstring> + S KEY-CREATED-AT <seconds_since_epoch> + S KEY-DATA [p|n] <hexdata> + + + --force is required to overwriet an already existing key. The + KEY-CREATED-AT is required for further processing because it is + part of the hashed key material for the fingerprint. + + The public part of the key can also later be retrieved using the + READKEY command. + + */ +static int +cmd_genkey (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *keyno; + int force = has_option (line, "--force"); + + /* Skip over options. */ + while ( *line == '-' && line[1] == '-' ) + { + while (!spacep (line)) + line++; + while (spacep (line)) + line++; + } + if (!*line) + return set_error (Parameter_Error, "no key number given"); + keyno = line; + while (!spacep (line)) + line++; + *line = 0; + + if ((rc = open_card (ctrl))) + return rc; + + if (!ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx); + + return map_to_assuan_status (rc); +} + + +/* RANDOM <nbytes> + + Get NBYTES of random from the card and send them back as data. +*/ +static int +cmd_random (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + size_t nbytes; + unsigned char *buffer; + + if (!*line) + return set_error (Parameter_Error, "number of requested bytes missing"); + nbytes = strtoul (line, NULL, 0); + + if ((rc = open_card (ctrl))) + return rc; + + if (!ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + buffer = xtrymalloc (nbytes); + if (!buffer) + return ASSUAN_Out_Of_Core; + + rc = app_get_challenge (ctrl->app_ctx, nbytes, buffer); + if (!rc) + { + rc = assuan_send_data (ctx, buffer, nbytes); + xfree (buffer); + return rc; /* that is already an assuan error code */ + } + xfree (buffer); + + return map_to_assuan_status (rc); +} + + +/* PASSWD [--reset] <chvno> + + Change the PIN or reset thye retry counter of the card holder + verfication vector CHVNO. */ +static int +cmd_passwd (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *chvnostr; + int reset_mode = has_option (line, "--reset"); + + /* Skip over options. */ + while (*line == '-' && line[1] == '-') + { + while (!spacep (line)) + line++; + while (spacep (line)) + line++; + } + if (!*line) + return set_error (Parameter_Error, "no CHV number given"); + chvnostr = line; + while (!spacep (line)) + line++; + *line = 0; + + if ((rc = open_card (ctrl))) + return rc; + + if (!ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx +); + if (rc) + log_error ("command passwd failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + + + +/* Tell the assuan library about our commands */ +static int +register_commands (ASSUAN_CONTEXT ctx) +{ + static struct { + const char *name; + int (*handler)(ASSUAN_CONTEXT, char *line); + } table[] = { + { "SERIALNO", cmd_serialno }, + { "LEARN", cmd_learn }, + { "READCERT", cmd_readcert }, + { "READKEY", cmd_readkey }, + { "SETDATA", cmd_setdata }, + { "PKSIGN", cmd_pksign }, + { "PKAUTH", cmd_pkauth }, + { "PKDECRYPT", cmd_pkdecrypt }, + { "INPUT", NULL }, + { "OUTPUT", NULL }, + { "SETATTR", cmd_setattr }, + { "GENKEY", cmd_genkey }, + { "RANDOM", cmd_random }, + { "PASSWD", cmd_passwd }, + { NULL } + }; + int i, rc; + + for (i=0; table[i].name; i++) + { + rc = assuan_register_command (ctx, table[i].name, table[i].handler); + if (rc) + return rc; + } + assuan_set_hello_line (ctx, "GNU Privacy Guard's Smartcard server ready"); + + assuan_register_reset_notify (ctx, reset_notify); + assuan_register_option_handler (ctx, option_handler); + return 0; +} + + +/* Startup the server. If LISTEN_FD is given as -1, this is simple + piper server, otherwise it is a regular server */ +void +scd_command_handler (int listen_fd) +{ + int rc; + ASSUAN_CONTEXT ctx; + struct server_control_s ctrl; + + memset (&ctrl, 0, sizeof ctrl); + scd_init_default_ctrl (&ctrl); + + if (listen_fd == -1) + { + int filedes[2]; + + filedes[0] = 0; + filedes[1] = 1; + rc = assuan_init_pipe_server (&ctx, filedes); + } + else + { + rc = assuan_init_socket_server (&ctx, listen_fd); + } + if (rc) + { + log_error ("failed to initialize the server: %s\n", + assuan_strerror(rc)); + scd_exit (2); + } + rc = register_commands (ctx); + if (rc) + { + log_error ("failed to register commands with Assuan: %s\n", + assuan_strerror(rc)); + scd_exit (2); + } + assuan_set_pointer (ctx, &ctrl); + ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); + ctrl.server_local->assuan_ctx = ctx; + + if (DBG_ASSUAN) + assuan_set_log_stream (ctx, log_get_stream ()); + + for (;;) + { + rc = assuan_accept (ctx); + if (rc == -1) + { + break; + } + else if (rc) + { + log_info ("Assuan accept problem: %s\n", assuan_strerror (rc)); + break; + } + + rc = assuan_process (ctx); + if (rc) + { + log_info ("Assuan processing failed: %s\n", assuan_strerror (rc)); + continue; + } + } + reset_notify (ctx); /* used for cleanup */ + + assuan_deinit_server (ctx); +} + + +/* Send a line with status information via assuan and escape all given + buffers. The variable elements are pairs of (char *, size_t), + terminated with a (NULL, 0). */ +void +send_status_info (CTRL ctrl, const char *keyword, ...) +{ + va_list arg_ptr; + const unsigned char *value; + size_t valuelen; + char buf[950], *p; + size_t n; + ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx; + + va_start (arg_ptr, keyword); + + p = buf; + n = 0; + while ( (value = va_arg (arg_ptr, const unsigned char *)) ) + { + valuelen = va_arg (arg_ptr, size_t); + if (!valuelen) + continue; /* empty buffer */ + if (n) + { + *p++ = ' '; + n++; + } + for ( ; valuelen && n < DIM (buf)-2; n++, valuelen--, value++) + { + if (*value < ' ' || *value == '+') + { + sprintf (p, "%%%02X", *value); + p += 3; + } + else if (*value == ' ') + *p++ = '+'; + else + *p++ = *value; + } + } + *p = 0; + assuan_write_status (ctx, keyword, buf); + + va_end (arg_ptr); +} + diff --git a/scd/iso7816.c b/scd/iso7816.c new file mode 100644 index 000000000..8903d8a5c --- /dev/null +++ b/scd/iso7816.c @@ -0,0 +1,371 @@ +/* iso7816.c - ISO 7816 commands + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +#include "scdaemon.h" +#include "iso7816.h" +#include "apdu.h" + +#define CMD_SELECT_FILE 0xA4 +#define CMD_VERIFY 0x20 +#define CMD_CHANGE_REFERENCE_DATA 0x24 +#define CMD_RESET_RETRY_COUNTER 0x2C +#define CMD_GET_DATA 0xCA +#define CMD_PUT_DATA 0xDA +#define CMD_PSO 0x2A +#define CMD_INTERNAL_AUTHENTICATE 0x88 +#define CMD_GENERATE_KEYPAIR 0x47 +#define CMD_GET_CHALLENGE 0x84 + +static gpg_error_t +map_sw (int sw) +{ + gpg_err_code_t ec; + + switch (sw) + { + case SW_EEPROM_FAILURE: ec = GPG_ERR_HARDWARE; break; + case SW_WRONG_LENGTH: ec = GPG_ERR_INV_VALUE; break; + case SW_CHV_WRONG: ec = GPG_ERR_BAD_PIN; break; + case SW_CHV_BLOCKED: ec = GPG_ERR_PIN_BLOCKED; break; + case SW_USE_CONDITIONS: ec = GPG_ERR_USE_CONDITIONS; break; + case SW_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break; + case SW_BAD_PARAMETER: ec = GPG_ERR_INV_VALUE; break; + case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; break; + case SW_BAD_P0_P1: ec = GPG_ERR_INV_VALUE; break; + case SW_INS_NOT_SUP: ec = GPG_ERR_CARD; break; + case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break; + case SW_SUCCESS: ec = 0; break; + + case SW_HOST_OUT_OF_CORE: ec = GPG_ERR_ENOMEM; break; + case SW_HOST_INV_VALUE: ec = GPG_ERR_INV_VALUE; break; + case SW_HOST_INCOMPLETE_CARD_RESPONSE: ec = GPG_ERR_CARD; break; + default: + if ((sw & 0x010000)) + ec = GPG_ERR_GENERAL; /* Should not happen. */ + else if ((sw & 0xff00) == SW_MORE_DATA) + ec = 0; /* This should actually never been seen here. */ + else + ec = GPG_ERR_CARD; + } + return gpg_error (ec); +} + +/* This function is specialized version of the SELECT FILE command. + SLOT is the card and reader as created for example by + apdu_open_reader (), AID is a buffer of size AIDLEN holding the + requested application ID. The function can't be used to enumerate + AIDs and won't return the AID on success. The return value is 0 + for okay or GNUPG error code. Note that ISO error codes are + internally mapped. */ +gpg_error_t +iso7816_select_application (int slot, const char *aid, size_t aidlen) +{ + int sw; + + sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid); + return map_sw (sw); +} + + +/* Perform a VERIFY command on SLOT using the card holder verification + vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */ +gpg_error_t +iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen) +{ + int sw; + + sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv); + return map_sw (sw); +} + +/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder + verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN + 0), a "change reference data" is done, otherwise an "exchange + reference data". The new reference data is expected in NEWCHV of + length NEWCHVLEN. */ +gpg_error_t +iso7816_change_reference_data (int slot, int chvno, + const char *oldchv, size_t oldchvlen, + const char *newchv, size_t newchvlen) +{ + int sw; + char *buf; + + if ((!oldchv && oldchvlen) + || (oldchv && !oldchvlen) + || !newchv || !newchvlen ) + return gpg_error (GPG_ERR_INV_VALUE); + + buf = xtrymalloc (oldchvlen + newchvlen); + if (!buf) + return out_of_core (); + if (oldchvlen) + memcpy (buf, oldchv, oldchvlen); + memcpy (buf+oldchvlen, newchv, newchvlen); + + sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, + oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf); + xfree (buf); + return map_sw (sw); + +} + +gpg_error_t +iso7816_reset_retry_counter (int slot, int chvno, + const char *newchv, size_t newchvlen) +{ + int sw; + + if (!newchv || !newchvlen ) + return gpg_error (GPG_ERR_INV_VALUE); + + sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER, + 2, chvno, newchvlen, newchv); + return map_sw (sw); +} + + +/* Perform a GET DATA command requesting TAG and storing the result in + a newly allocated buffer at the address passed by RESULT. Return + the length of this data at the address of RESULTLEN. */ +gpg_error_t +iso7816_get_data (int slot, int tag, + unsigned char **result, size_t *resultlen) +{ + int sw; + + if (!result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + sw = apdu_send (slot, 0x00, CMD_GET_DATA, + ((tag >> 8) & 0xff), (tag & 0xff), -1, NULL, + result, resultlen); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + + return 0; +} + + +/* Perform a PUT DATA command on card in SLOT. Write DATA of length + DATALEN to TAG. */ +gpg_error_t +iso7816_put_data (int slot, int tag, + const unsigned char *data, size_t datalen) +{ + int sw; + + sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA, + ((tag >> 8) & 0xff), (tag & 0xff), + datalen, data); + return map_sw (sw); +} + + +/* Perform the security operation COMPUTE DIGITAL SIGANTURE. On + success 0 is returned and the data is availavle in a newly + allocated buffer stored at RESULT with its length stored at + RESULTLEN. */ +gpg_error_t +iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen) +{ + int sw; + + if (!data || !datalen || !result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, data, + result, resultlen); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + + return 0; +} + + +/* Perform the security operation DECIPHER. On + success 0 is returned and the plaintext is available in a newly + allocated buffer stored at RESULT with its length stored at + RESULTLEN. */ +gpg_error_t +iso7816_decipher (int slot, const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen) +{ + int sw; + unsigned char *buf; + + if (!data || !datalen || !result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + /* We need to prepend the padding indicator. */ + buf = xtrymalloc (datalen + 1); + if (!buf) + return out_of_core (); + *buf = 0; /* Padding indicator. */ + memcpy (buf+1, data, datalen); + sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf, + result, resultlen); + xfree (buf); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + + return 0; +} + + +gpg_error_t +iso7816_internal_authenticate (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen) +{ + int sw; + + if (!data || !datalen || !result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, + datalen, data, result, resultlen); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + + return 0; +} + + +static gpg_error_t +generate_keypair (int slot, int readonly, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen) +{ + int sw; + + if (!data || !datalen || !result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0, + datalen, data, result, resultlen); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + + return 0; +} + + +gpg_error_t +iso7816_generate_keypair (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen) +{ + return generate_keypair (slot, 0, data, datalen, result, resultlen); +} + + +gpg_error_t +iso7816_read_public_key (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen) +{ + return generate_keypair (slot, 1, data, datalen, result, resultlen); +} + + + +gpg_error_t +iso7816_get_challenge (int slot, int length, unsigned char *buffer) +{ + int sw; + unsigned char *result; + size_t resultlen, n; + + if (!buffer || length < 1) + return gpg_error (GPG_ERR_INV_VALUE); + + do + { + result = NULL; + n = length > 254? 254 : length; + sw = apdu_send_le (slot, 0x00, CMD_GET_CHALLENGE, 0, 0, -1, NULL, + n, + &result, &resultlen); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (result); + return map_sw (sw); + } + if (resultlen > n) + resultlen = n; + memcpy (buffer, result, resultlen); + buffer += resultlen; + length -= resultlen; + xfree (result); + } + while (length > 0); + + return 0; +} diff --git a/scd/iso7816.h b/scd/iso7816.h new file mode 100644 index 000000000..d7e77a101 --- /dev/null +++ b/scd/iso7816.h @@ -0,0 +1,56 @@ +/* iso7816.h - ISO 7816 commands + * 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 ISO7816_H +#define ISO7816_H + +gpg_error_t iso7816_select_application (int slot, + const char *aid, size_t aidlen); +gpg_error_t iso7816_verify (int slot, + int chvno, const char *chv, size_t chvlen); +gpg_error_t iso7816_change_reference_data (int slot, int chvno, + const char *oldchv, size_t oldchvlen, + const char *newchv, size_t newchvlen); +gpg_error_t iso7816_reset_retry_counter (int slot, int chvno, + const char *newchv, size_t newchvlen); +gpg_error_t iso7816_get_data (int slot, int tag, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_put_data (int slot, int tag, + const unsigned char *data, size_t datalen); +gpg_error_t iso7816_compute_ds (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_decipher (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_internal_authenticate (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_generate_keypair (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_read_public_key (int slot, + const unsigned char *data, size_t datalen, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_get_challenge (int slot, + int length, unsigned char *buffer); + + +#endif /*ISO7816_H*/ diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c new file mode 100644 index 000000000..9caf39a8a --- /dev/null +++ b/scd/sc-copykeys.c @@ -0,0 +1,731 @@ +/* sc-copykeys.c - A tool to store keys on a smartcard. + * 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 <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define JNLIB_NEED_LOG_LOGV +#include "scdaemon.h" +#include <gcrypt.h> + +#include "../common/ttyio.h" +#include "../common/simple-pwquery.h" +#include "apdu.h" /* for open_reader */ +#include "atr.h" +#include "app-common.h" + +#define _(a) (a) + + +enum cmd_and_opt_values +{ oVerbose = 'v', + oReaderPort = 500, + oDebug, + oDebugAll, + +aTest }; + + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, "@Options:\n " }, + + { oVerbose, "verbose", 0, "verbose" }, + { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"}, + { oDebug, "debug" ,4|16, "set debugging flags"}, + { oDebugAll, "debug-all" ,0, "enable full debugging"}, + {0} +}; + + +static void copykeys (APP app, const char *fname); + + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "sc-copykeys (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: sc-copykeys [options] (-h for help)\n"); + break; + case 41: p = _("Syntax: sc-copykeys [options] " + "file-with-key\n" + "Copy keys to a smartcards\n"); + break; + + default: p = NULL; + } + return p; +} + +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* translate the log levels */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; + } + log_logv (level, fmt, arg_ptr); +} + + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + int slot, rc; + int reader_port = 32768; /* First USB reader. */ + struct app_ctx_s appbuf; + + memset (&appbuf, 0, sizeof appbuf); + + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + log_set_prefix ("sc-copykeys", 1); + + /* check that the libraries are suitable. Do it here because + the option parsing may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + gcry_set_log_handler (my_gcry_logger, NULL); + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); /* FIXME - we want to use it */ + /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/ + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + while (arg_parse (&pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: opt.verbose++; break; + case oDebug: opt.debug |= pargs.r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit(2); + + if (argc != 1) + usage (1); + + slot = apdu_open_reader (reader_port); + if (slot == -1) + exit (1); + + /* FIXME: Use select_application. */ + appbuf.slot = slot; + rc = app_select_openpgp (&appbuf, &appbuf.serialno, &appbuf.serialnolen); + if (rc) + { + log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + exit (1); + } + appbuf.initialized = 1; + log_info ("openpgp application selected\n"); + + copykeys (&appbuf, *argv); + + + return 0; +} + + + +void +send_status_info (CTRL ctrl, const char *keyword, ...) +{ + /* DUMMY */ +} + + + +static char * +read_file (const char *fname, size_t *r_length) +{ + FILE *fp; + struct stat st; + char *buf; + size_t buflen; + + fp = fname? fopen (fname, "rb") : stdin; + if (!fp) + { + log_error ("can't open `%s': %s\n", + fname? fname: "[stdin]", strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + log_error ("can't stat `%s': %s\n", + fname? fname: "[stdin]", strerror (errno)); + if (fname) + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + log_error ("error reading `%s': %s\n", + fname? fname: "[stdin]", strerror (errno)); + if (fname) + fclose (fp); + xfree (buf); + return NULL; + } + if (fname) + fclose (fp); + + *r_length = buflen; + return buf; +} + + +static gcry_sexp_t +read_key (const char *fname) +{ + char *buf; + size_t buflen; + gcry_sexp_t private; + int rc; + + buf = read_file (fname, &buflen); + if (!buf) + return NULL; + + rc = gcry_sexp_new (&private, buf, buflen, 1); + if (rc) + { + log_error ("gcry_sexp_new failed: %s\n", gpg_strerror (rc)); + return NULL; + } + xfree (buf); + + return private; +} + + + +static gcry_mpi_t * +sexp_to_kparms (gcry_sexp_t sexp, unsigned long *created) +{ + gcry_sexp_t list, l2; + const char *name; + const char *s; + size_t n; + int i, idx; + const char *elems; + gcry_mpi_t *array; + + *created = 0; + list = gcry_sexp_find_token (sexp, "private-key", 0 ); + if(!list) + return NULL; + + /* quick hack to get the creation time. */ + l2 = gcry_sexp_find_token (list, "created", 0); + if (l2 && (name = gcry_sexp_nth_data (l2, 1, &n))) + { + char *tmp = xmalloc (n+1); + memcpy (tmp, name, n); + tmp[n] = 0; + *created = strtoul (tmp, NULL, 10); + xfree (tmp); + } + gcry_sexp_release (l2); + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + name = gcry_sexp_nth_data (list, 0, &n); + if(!name || n != 3 || memcmp (name, "rsa", 3)) + { + gcry_sexp_release (list); + return NULL; + } + + /* Parameter names used with RSA. */ + elems = "nedpqu"; + array = xcalloc (strlen(elems) + 1, sizeof *array); + for (idx=0, s=elems; *s; s++, idx++ ) + { + l2 = gcry_sexp_find_token (list, s, 1); + if (!l2) + { + for (i=0; i<idx; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (list); + return NULL; /* required parameter not found */ + } + array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + if (!array[idx]) + { + for (i=0; i<idx; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (list); + return NULL; /* required parameter is invalid */ + } + } + + gcry_sexp_release (list); + return array; +} + + +/* 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); +} + + +static void +show_sha1_fpr (const unsigned char *fpr) +{ + int i; + + if (fpr) + { + for (i=0; i < 20 ; i+=2, fpr += 2 ) + { + if (i == 10 ) + tty_printf (" "); + tty_printf (" %02X%02X", *fpr, fpr[1]); + } + } + else + tty_printf (" [none]"); + tty_printf ("\n"); +} + +/* Query the card, show a list of already stored keys and ask the user + where to store the key. Returns the key number or 0 for cancel + operation. */ +static int +query_card (APP app) +{ + int keyno = 0; + char *serialno, *disp_name, *pubkey_url; + unsigned char *fpr1, *fpr2, *fpr3; + + + if (app_openpgp_cardinfo (app, + &serialno, + &disp_name, + &pubkey_url, + &fpr1, &fpr2, &fpr3)) + return 0; + + + for (;;) + { + char *answer; + + tty_printf ("\n"); + + tty_printf ("Serial number ....: %s\n", + serialno? serialno : "[none]"); + tty_printf ("Name of cardholder: %s\n", + disp_name && *disp_name? disp_name : "[not set]"); + tty_printf ("URL of public key : %s\n", + pubkey_url && *pubkey_url? pubkey_url : "[not set]"); + tty_printf ("Signature key ....:"); + show_sha1_fpr (fpr1); + tty_printf ("Encryption key....:"); + show_sha1_fpr (fpr2); + tty_printf ("Authentication key:"); + show_sha1_fpr (fpr3); + + tty_printf ("\n" + "1 - store as signature key and reset usage counter\n" + "2 - store as encryption key\n" + "3 - store as authentication key\n" + "Q - quit\n" + "\n"); + + answer = tty_get("Your selection? "); + tty_kill_prompt(); + if (strlen (answer) != 1) + ; + else if ( *answer == '1' ) + { + if ( (fpr1 && !fpr_is_zero (fpr1)) ) + { + tty_printf ("\n"); + log_error ("WARNING: signature key does already exists!\n"); + tty_printf ("\n"); + if ( tty_get_answer_is_yes ("Replace existing key? ") ) + { + keyno = 1; + break; + } + } + else + { + keyno = 1; + break; + } + } + else if ( *answer == '2' ) + { + if ( (fpr2 && !fpr_is_zero (fpr2)) ) + { + tty_printf ("\n"); + log_error ("WARNING: encryption key does already exists!\n"); + tty_printf ("\n"); + if ( tty_get_answer_is_yes ("Replace existing key? ") ) + { + keyno = 2; + break; + } + } + else + { + keyno = 2; + break; + } + } + else if ( *answer == '3' ) + { + if ( (fpr3 && !fpr_is_zero (fpr3)) ) + { + tty_printf ("\n"); + log_error ("WARNING: authentication key does already exists!\n"); + tty_printf ("\n"); + if ( tty_get_answer_is_yes ("Replace existing key? ") ) + { + keyno = 3; + break; + } + } + else + { + keyno = 3; + break; + } + } + else if ( *answer == 'q' || *answer == 'Q') + { + keyno = 0; + break; + } + } + + xfree (serialno); + xfree (disp_name); + xfree (pubkey_url); + xfree (fpr1); + xfree (fpr2); + xfree (fpr3); + + return keyno; +} + + +/* Callback function to ask for a PIN. */ +static int +pincb (void *arg, const char *prompt, char **pinvalue) +{ + char *pin = xstrdup ("12345678"); + +/* pin = simple_pwquery (NULL, NULL, prompt, */ +/* "We need the admin's PIN to store the key on the card", */ +/* NULL); */ +/* if (!pin) */ +/* return gpg_error (GPG_ERR_CANCELED); */ + + + + *pinvalue = pin; + return 0; +} + + +/* This function expects a file (or NULL for stdin) with the secret + and public key parameters. This file should consist of an + S-expression as used by gpg-agent. Only the unprotected format is + supported. Example: + + (private-key + (rsa + (n #00e0ce9..[some bytes not shown]..51#) + (e #010001#) + (d #046129F..[some bytes not shown]..81#) + (p #00e861b..[some bytes not shown]..f1#) + (q #00f7a7c..[some bytes not shown]..61#) + (u #304559a..[some bytes not shown]..9b#)) + (uri http://foo.bar x-foo:whatever_you_want)) + +*/ +static void +copykeys (APP app, const char *fname) +{ + int rc; + gcry_sexp_t private; + gcry_mpi_t *mpis, rsa_n, rsa_e, rsa_p, rsa_q; + unsigned int nbits; + size_t n; + unsigned char *template, *tp; + unsigned char m[128], e[4]; + size_t mlen, elen; + unsigned long creation_date; + time_t created_at; + int keyno; + + if (!strcmp (fname, "-")) + fname = NULL; + + private = read_key (fname); + if (!private) + exit (1); + + mpis = sexp_to_kparms (private, &creation_date); + if (!creation_date) + { + log_info ("no creation date found - assuming current date\n"); + created_at = time (NULL); + } + else + created_at = creation_date; + gcry_sexp_release (private); + if (!mpis) + { + log_error ("invalid structure of key file or not RSA\n"); + exit (1); + } + /* MPIS is now an array with the key parameters as defined by OpenPGP. */ + rsa_n = mpis[0]; + rsa_e = mpis[1]; + gcry_mpi_release (mpis[2]); + rsa_p = mpis[3]; + rsa_q = mpis[4]; + gcry_mpi_release (mpis[5]); + xfree (mpis); + + nbits = gcry_mpi_get_nbits (rsa_e); + if (nbits < 2 || nbits > 32) + { + log_error ("public exponent too large (more than 32 bits)\n"); + goto failure; + } + nbits = gcry_mpi_get_nbits (rsa_p); + if (nbits != 512) + { + log_error ("length of first RSA prime is not 512\n"); + goto failure; + } + nbits = gcry_mpi_get_nbits (rsa_q); + if (nbits != 512) + { + log_error ("length of second RSA prime is not 512\n"); + goto failure; + } + + nbits = gcry_mpi_get_nbits (rsa_n); + if (nbits != 1024) + { + log_error ("length of RSA modulus is not 1024\n"); + goto failure; + } + + keyno = query_card (app); + if (!keyno) + goto failure; + + /* Build the private key template as described in section 4.3.3.6 of + the specs. + 0xC0 <length> public exponent + 0xC1 <length> prime p + 0xC2 <length> prime q */ + template = tp = xmalloc (1+2 + 1+1+4 + 1+1+64 + 1+1+64); + *tp++ = 0xC0; + *tp++ = 4; + rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 4, &n, rsa_e); + if (rc) + { + log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); + goto failure; + } + assert (n <= 4); + memcpy (e, tp, n); + elen = n; + if (n != 4) + { + memmove (tp+4-n, tp, 4-n); + memset (tp, 0, 4-n); + } + tp += 4; + + *tp++ = 0xC1; + *tp++ = 64; + rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_p); + if (rc) + { + log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); + goto failure; + } + assert (n == 64); + tp += 64; + + *tp++ = 0xC2; + *tp++ = 64; + rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_q); + if (rc) + { + log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); + goto failure; + } + assert (n == 64); + tp += 64; + assert (tp - template == 138); + + /* (we need the modulus to calculate the fingerprint) */ + rc = gcry_mpi_print (GCRYMPI_FMT_USG, m, 128, &n, rsa_n); + if (rc) + { + log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); + goto failure; + } + assert (n == 128); + mlen = 128; + + + rc = app_openpgp_storekey (app, keyno, + template, tp - template, + created_at, + m, mlen, + e, elen, + pincb, NULL); + + if (rc) + { + log_error ("error storing key: %s\n", gpg_strerror (rc)); + goto failure; + } + log_info ("key successfully stored\n"); + { + unsigned char *mm, *ee; + size_t mmlen, eelen; + int i; + + rc = app_openpgp_readkey (app, keyno, &mm, &mmlen, &ee, &eelen); + if (rc) + { + log_error ("error reading key back: %s\n", gpg_strerror (rc)); + goto failure; + } + + /* Strip leading zeroes. */ + for (i=0; i < mmlen && !mm[i]; i++) + ; + mmlen -= i; + memmove (mm, mm+i, mmlen); + for (i=0; i < eelen && !ee[i]; i++) + ; + eelen -= i; + memmove (ee, ee+i, eelen); + + if (eelen != elen || mmlen != mlen) + { + log_error ("key parameter length mismatch (n=%u/%u, e=%u/%u)\n", + (unsigned int)mlen, (unsigned int)mmlen, + (unsigned int)elen, (unsigned int)eelen); + xfree (mm); + xfree (ee); + goto failure; + } + + if (memcmp (m, mm, mlen)) + { + log_error ("key parameter n mismatch\n"); + log_printhex ("original n: ", m, mlen); + log_printhex (" copied n: ", mm, mlen); + xfree (mm); + xfree (ee); + goto failure; + } + if (memcmp (e, ee, elen)) + { + log_error ("key parameter e mismatch\n"); + log_printhex ("original e: ", e, elen); + log_printhex (" copied e: ", ee, elen); + xfree (mm); + xfree (ee); + goto failure; + } + xfree (mm); + xfree (ee); + } + + + gcry_mpi_release (rsa_e); + gcry_mpi_release (rsa_p); + gcry_mpi_release (rsa_q); + gcry_mpi_release (rsa_n); + return; + + failure: + gcry_mpi_release (rsa_e); + gcry_mpi_release (rsa_p); + gcry_mpi_release (rsa_q); + gcry_mpi_release (rsa_n); + exit (1); +} + + diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c new file mode 100644 index 000000000..e8f0eb83c --- /dev/null +++ b/scd/sc-investigate.c @@ -0,0 +1,209 @@ +/* sc-investigate.c - A tool to look around on smartcards. + * 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> + +#define JNLIB_NEED_LOG_LOGV +#include "scdaemon.h" +#include <gcrypt.h> + +#include "apdu.h" /* for open_reader */ +#include "atr.h" +#include "app-common.h" + +#define _(a) (a) + + +enum cmd_and_opt_values +{ oVerbose = 'v', + oReaderPort = 500, + oDebug, + oDebugAll, + + oGenRandom, + +aTest }; + + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, "@Options:\n " }, + + { oVerbose, "verbose", 0, "verbose" }, + { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"}, + { oDebug, "debug" ,4|16, "set debugging flags"}, + { oDebugAll, "debug-all" ,0, "enable full debugging"}, + { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"}, + {0} +}; + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "sc-investigate (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: sc-investigate [options] (-h for help)\n"); + break; + case 41: p = _("Syntax: sc-investigate [options] [args]]\n" + "Have a look at smartcards\n"); + break; + + default: p = NULL; + } + return p; +} + +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* translate the log levels */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; + } + log_logv (level, fmt, arg_ptr); +} + + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + int slot, rc; + int reader_port = 32768; /* First USB reader. */ + struct app_ctx_s appbuf; + unsigned long gen_random = 0; + + memset (&appbuf, 0, sizeof appbuf); + + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + log_set_prefix ("sc-investigate", 1); + + /* check that the libraries are suitable. Do it here because + the option parsing may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + gcry_set_log_handler (my_gcry_logger, NULL); + /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/ + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + while (arg_parse (&pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: opt.verbose++; break; + case oDebug: opt.debug |= pargs.r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + case oGenRandom: gen_random = pargs.r.ret_ulong; break; + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit(2); + + if (opt.verbose < 2) + opt.verbose = 2; /* hack to let select_openpgp print some info. */ + + if (argc) + usage (1); + + slot = apdu_open_reader (reader_port); + if (slot == -1) + exit (1); + + if (!gen_random) + { + rc = atr_dump (slot, stdout); + if (rc) + log_error ("can't dump ATR: %s\n", gpg_strerror (rc)); + } + + appbuf.slot = slot; + rc = app_select_openpgp (&appbuf, NULL, NULL); + if (rc) + log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + else + { + appbuf.initialized = 1; + log_info ("openpgp application selected\n"); + + if (gen_random) + { + size_t nbytes; + unsigned char *buffer; + + buffer = xmalloc (4096); + do + { + nbytes = gen_random > 4096? 4096 : gen_random; + rc = app_get_challenge (&appbuf, nbytes, buffer); + if (rc) + log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc)); + else + { + if (fwrite (buffer, nbytes, 1, stdout) != 1) + log_error ("writing to stdout failed: %s\n", + strerror (errno)); + gen_random -= nbytes; + } + } + while (gen_random && !log_get_errorcount (0)); + xfree (buffer); + } + } + + return log_get_errorcount (0)? 2:0; +} + + + +void +send_status_info (CTRL ctrl, const char *keyword, ...) +{ + /* DUMMY */ +} diff --git a/scd/scdaemon.c b/scd/scdaemon.c new file mode 100644 index 000000000..8e0ef37c9 --- /dev/null +++ b/scd/scdaemon.c @@ -0,0 +1,638 @@ +/* scdaemon.c - The GnuPG Smartcard Daemon + * 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 <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <time.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <signal.h> + +#define JNLIB_NEED_LOG_LOGV +#include "scdaemon.h" +#include <ksba.h> +#include <gcrypt.h> + +#include <assuan.h> /* malloc hooks */ + +#include "i18n.h" +#include "sysutils.h" + + + +enum cmd_and_opt_values +{ aNull = 0, + oCsh = 'c', + oQuiet = 'q', + oSh = 's', + oVerbose = 'v', + + oNoVerbose = 500, + oOptions, + oDebug, + oDebugAll, + oDebugWait, + oDebugSC, + oNoGreeting, + oNoOptions, + oHomedir, + oNoDetach, + oNoGrab, + oLogFile, + oServer, + oDaemon, + oBatch, + oReaderPort, + +aTest }; + + + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oServer, "server", 0, N_("run in server mode (foreground)") }, + { oDaemon, "daemon", 0, N_("run in daemon mode (background)") }, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oSh, "sh", 0, N_("sh-style command output") }, + { oCsh, "csh", 0, N_("csh-style command output") }, + { oOptions, "options" , 2, N_("read options from file")}, + { oDebug, "debug" ,4|16, N_("set debugging flags")}, + { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, + { oDebugWait,"debug-wait",1, "@"}, + { oDebugSC, "debug-sc", 1, N_("|N|set OpenSC debug level to N")}, + { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, + { oLogFile, "log-file" ,2, N_("use a log file for the server")}, + { oReaderPort, "reader-port", 1, N_("|N|connect to reader at port N")}, + + {0} +}; + + +static volatile int caught_fatal_sig = 0; + +/* It is possible that we are currently running under setuid permissions */ +static int maybe_setuid = 1; + +/* Name of the communication socket */ +static char socket_name[128]; + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "scdaemon (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: scdaemon [options] (-h for help)"); + break; + case 41: p = _("Syntax: scdaemon [options] [command [args]]\n" + "Smartcard daemon for GnuPG\n"); + break; + + default: p = NULL; + } + return p; +} + + + +static void +i18n_init (void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE ); +#else +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif +#endif +} + + + +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* translate the log levels */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; + } + log_logv (level, fmt, arg_ptr); +} + + +static void +cleanup (void) +{ + if (*socket_name) + { + char *p; + + remove (socket_name); + p = strrchr (socket_name, '/'); + if (p) + { + *p = 0; + rmdir (socket_name); + *p = '/'; + } + *socket_name = 0; + } +} + + +static RETSIGTYPE +cleanup_sh (int sig) +{ + if (caught_fatal_sig) + raise (sig); + caught_fatal_sig = 1; + + /* gcry_control( GCRYCTL_TERM_SECMEM );*/ + cleanup (); + +#ifndef HAVE_DOSISH_SYSTEM + { /* reset action to default action and raise signal again */ + struct sigaction nact; + nact.sa_handler = SIG_DFL; + sigemptyset( &nact.sa_mask ); + nact.sa_flags = 0; + sigaction( sig, &nact, NULL); + } +#endif + raise( sig ); +} + +int +main (int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + int orig_argc; + int may_coredump; + char **orig_argv; + FILE *configfp = NULL; + char *configname = NULL; + const char *shell; + unsigned configlineno; + int parse_debug = 0; + int default_config =1; + int greeting = 0; + int nogreeting = 0; + int pipe_server = 0; + int is_daemon = 0; + int nodetach = 0; + int csh_style = 0; + char *logfile = NULL; + int debug_wait = 0; + int reader_port = 32768; /* First USB reader. */ + + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + /* Please note that we may running SUID(ROOT), so be very CAREFUL + when adding any stuff between here and the call to INIT_SECMEM() + somewhere after the option parsing */ + log_set_prefix ("scdaemon", 1|4); + i18n_init (); + + /* check that the libraries are suitable. Do it here because + the option parsing may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + gcry_set_log_handler (my_gcry_logger, NULL); + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + + may_coredump = disable_core_dumps (); + + shell = getenv ("SHELL"); + if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) + csh_style = 1; + + /* FIXME: Using this homedir option does only make sense when not + running as a system service. We might want to check for this by + looking at the uid or ebtter use an explict option for this */ + opt.homedir = getenv("GNUPGHOME"); + if (!opt.homedir || !*opt.homedir) + opt.homedir = GNUPG_DEFAULT_HOMEDIR; + + /* check whether we have a config file on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ + while (arg_parse( &pargs, opts)) + { + if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) + parse_debug++; + else if (pargs.r_opt == oOptions) + { /* yes there is one, so we do not try the default one, but + read the option file when it is encountered at the + commandline */ + default_config = 0; + } + else if (pargs.r_opt == oNoOptions) + default_config = 0; /* --no-options */ + else if (pargs.r_opt == oHomedir) + opt.homedir = pargs.r.ret_str; + } + + /* initialize the secure memory. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + maybe_setuid = 0; + + /* + Now we are working under our real uid + */ + + + if (default_config) + configname = make_filename (opt.homedir, "scdaemon.conf", NULL ); + + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + next_pass: + if (configname) + { + configlineno = 0; + configfp = fopen (configname, "r"); + if (!configfp) + { + if (default_config) + { + if( parse_debug ) + log_info (_("NOTE: no default option file `%s'\n"), + configname ); + } + else + { + log_error (_("option file `%s': %s\n"), + configname, strerror(errno) ); + exit(2); + } + xfree (configname); + configname = NULL; + } + if (parse_debug && configname ) + log_info (_("reading options from `%s'\n"), configname ); + default_config = 0; + } + + while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) + { + switch (pargs.r_opt) + { + case oQuiet: opt.quiet = 1; break; + case oVerbose: opt.verbose++; break; + case oBatch: opt.batch=1; break; + + case oDebug: opt.debug |= pargs.r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + case oDebugWait: debug_wait = pargs.r.ret_int; break; + case oDebugSC: opt.debug_sc = pargs.r.ret_int; break; + + case oOptions: + /* config files may not be nested (silently ignore them) */ + if (!configfp) + { + xfree(configname); + configname = xstrdup(pargs.r.ret_str); + goto next_pass; + } + break; + case oNoGreeting: nogreeting = 1; break; + case oNoVerbose: opt.verbose = 0; break; + case oNoOptions: break; /* no-options */ + case oHomedir: opt.homedir = pargs.r.ret_str; break; + case oNoDetach: nodetach = 1; break; + case oLogFile: logfile = pargs.r.ret_str; break; + case oCsh: csh_style = 1; break; + case oSh: csh_style = 0; break; + case oServer: pipe_server = 1; break; + case oDaemon: is_daemon = 1; break; + + case oReaderPort: reader_port = pargs.r.ret_int; break; + + default : pargs.err = configfp? 1:2; break; + } + } + if (configfp) + { + fclose( configfp ); + configfp = NULL; + xfree(configname); + configname = NULL; + goto next_pass; + } + xfree (configname); + configname = NULL; + if (log_get_errorcount(0)) + exit(2); + if (nogreeting ) + greeting = 0; + + if (greeting) + { + fprintf (stderr, "%s %s; %s\n", + strusage(11), strusage(13), strusage(14) ); + fprintf (stderr, "%s\n", strusage(15) ); + } +#ifdef IS_DEVELOPMENT_VERSION + log_info ("NOTE: this is a development version!\n"); +#endif + + + if (atexit (cleanup)) + { + log_error ("atexit failed\n"); + cleanup (); + exit (1); + } + + + if (debug_wait && pipe_server) + { + log_debug ("waiting for debugger - my pid is %u .....\n", + (unsigned int)getpid()); + sleep (debug_wait); + log_debug ("... okay\n"); + } + + /* now start with logging to a file if this is desired */ + if (logfile) + { + log_set_file (logfile); + log_set_prefix (NULL, 1|2|4); + } + + + if (pipe_server) + { /* this is the simple pipe based server */ + scd_command_handler (-1); + } + else if (!is_daemon) + { + log_info (_("please use the option `--daemon'" + " to run the program in the background\n")); + } + else + { /* regular server mode */ + int fd; + pid_t pid; + int i; + int len; + struct sockaddr_un serv_addr; + char *p; + + /* fixme: if there is already a running gpg-agent we should + share the same directory - and vice versa */ + *socket_name = 0; + snprintf (socket_name, DIM(socket_name)-1, + "/tmp/gpg-XXXXXX/S.scdaemon"); + socket_name[DIM(socket_name)-1] = 0; + p = strrchr (socket_name, '/'); + if (!p) + BUG (); + *p = 0;; + if (!mkdtemp(socket_name)) + { + log_error ("can't create directory `%s': %s\n", + socket_name, strerror(errno) ); + exit (1); + } + *p = '/'; + + if (strchr (socket_name, ':') ) + { + log_error ("colons are not allowed in the socket name\n"); + exit (1); + } + if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) + { + log_error ("name of socket to long\n"); + exit (1); + } + + + fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + { + log_error ("can't create socket: %s\n", strerror(errno) ); + exit (1); + } + + memset (&serv_addr, 0, sizeof serv_addr); + serv_addr.sun_family = AF_UNIX; + strcpy (serv_addr.sun_path, socket_name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen(serv_addr.sun_path) + 1); + + if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1) + { + log_error ("error binding socket to `%s': %s\n", + serv_addr.sun_path, strerror (errno) ); + close (fd); + exit (1); + } + + if (listen (fd, 5 ) == -1) + { + log_error ("listen() failed: %s\n", strerror (errno)); + close (fd); + exit (1); + } + + if (opt.verbose) + log_info ("listening on socket `%s'\n", socket_name ); + + + fflush (NULL); + pid = fork (); + if (pid == (pid_t)-1) + { + log_fatal ("fork failed: %s\n", strerror (errno) ); + exit (1); + } + else if (pid) + { /* we are the parent */ + char *infostr; + + close (fd); + + /* create the info string: <name>:<pid>:<protocol_version> */ + if (asprintf (&infostr, "SCDAEMON_INFO=%s:%lu:1", + socket_name, (ulong)pid ) < 0) + { + log_error ("out of core\n"); + kill (pid, SIGTERM); + exit (1); + } + *socket_name = 0; /* don't let cleanup() remove the socket - + the child should do this from now on */ + if (argc) + { /* run the program given on the commandline */ + if (putenv (infostr)) + { + log_error ("failed to set environment: %s\n", + strerror (errno) ); + kill (pid, SIGTERM ); + exit (1); + } + execvp (argv[0], argv); + log_error ("failed to run the command: %s\n", strerror (errno)); + kill (pid, SIGTERM); + exit (1); + } + else + { + /* print the environment string, so that the caller can use + shell's eval to set it */ + if (csh_style) + { + *strchr (infostr, '=') = ' '; + printf ( "setenv %s\n", infostr); + } + else + { + printf ( "%s; export SCDAEMON_INFO;\n", infostr); + } + free (infostr); + exit (0); + } + /* NOTREACHED */ + } /* end parent */ + + /* this is the child */ + + /* detach from tty and put process into a new session */ + if (!nodetach ) + { /* close stdin, stdout and stderr unless it is the log stream */ + for (i=0; i <= 2; i++) + { + if ( log_get_fd () != i) + close (i); + } + if (setsid() == -1) + { + log_error ("setsid() failed: %s\n", strerror(errno) ); + cleanup (); + exit (1); + } + } + + /* setup signals */ + { + struct sigaction oact, nact; + + nact.sa_handler = cleanup_sh; + sigemptyset (&nact.sa_mask); + nact.sa_flags = 0; + + sigaction (SIGHUP, NULL, &oact); + if (oact.sa_handler != SIG_IGN) + sigaction (SIGHUP, &nact, NULL); + sigaction( SIGTERM, NULL, &oact ); + if (oact.sa_handler != SIG_IGN) + sigaction (SIGTERM, &nact, NULL); + nact.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &nact, NULL); + sigaction (SIGINT, &nact, NULL); + } + + if (chdir("/")) + { + log_error ("chdir to / failed: %s\n", strerror (errno)); + exit (1); + } + + scd_command_handler (fd); + + close (fd); + } + + return 0; +} + +void +scd_exit (int rc) +{ + #if 0 +#warning no update_random_seed_file + update_random_seed_file(); + #endif +#if 0 + /* at this time a bit annoying */ + if (opt.debug & DBG_MEMSTAT_VALUE) + { + gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); + gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + } + if (opt.debug) + gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); +#endif + gcry_control (GCRYCTL_TERM_SECMEM ); + rc = rc? rc : log_get_errorcount(0)? 2 : 0; + exit (rc); +} + + +void +scd_init_default_ctrl (CTRL ctrl) +{ + +} + diff --git a/scd/scdaemon.h b/scd/scdaemon.h new file mode 100644 index 000000000..b21e19f8c --- /dev/null +++ b/scd/scdaemon.h @@ -0,0 +1,127 @@ +/* scdaemon.h - Global definitions for the SCdaemon + * 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 SCDAEMON_H +#define SCDAEMON_H + +#ifdef GPG_ERR_SOURCE_DEFAULT +#error GPG_ERR_SOURCE_DEFAULT already defined +#endif +#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_SCD +#include <gpg-error.h> +#include <errno.h> + +#include <time.h> +#include <gcrypt.h> +#include "../common/util.h" +#include "../common/errors.h" + +/* Convenience funcion to be used instead of returning the old + GNUPG_Out_Of_Core. */ +static __inline__ gpg_error_t +out_of_core (void) +{ + return gpg_error (gpg_err_code_from_errno (errno)); +} + + +#define MAX_DIGEST_LEN 24 + +/* A large struct name "opt" to keep global flags */ +struct { + unsigned int debug; /* debug flags (DBG_foo_VALUE) */ + int debug_sc; /* OpenSC debug level */ + int verbose; /* verbosity level */ + int quiet; /* be as quiet as possible */ + int dry_run; /* don't change any persistent data */ + int batch; /* batch mode */ + const char *homedir; /* configuration directory name */ +} opt; + + +#define DBG_COMMAND_VALUE 1 /* debug commands i/o */ +#define DBG_MPI_VALUE 2 /* debug mpi details */ +#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ +#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ +#define DBG_CACHE_VALUE 64 /* debug the caching */ +#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ +#define DBG_HASHING_VALUE 512 /* debug hashing operations */ +#define DBG_ASSUAN_VALUE 1024 +#define DBG_CARD_IO_VALUE 2048 + +#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE) +#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) +#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) +#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) +#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) +#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) +#define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE) + +struct server_local_s; +struct card_ctx_s; +struct app_ctx_s; + +struct server_control_s { + struct server_local_s *server_local; + struct card_ctx_s *card_ctx; + struct app_ctx_s *app_ctx; + struct { + unsigned char *value; + int valuelen; + } in_data; /* helper to store the value we are going to sign */ + +}; + +typedef struct server_control_s *CTRL; +typedef struct card_ctx_s *CARD; +typedef struct app_ctx_s *APP; + +/*-- scdaemon.c --*/ +void scd_exit (int rc); +void scd_init_default_ctrl (CTRL ctrl); + +/*-- command.c --*/ +void scd_command_handler (int); +void send_status_info (CTRL ctrl, const char *keyword, ...); + +/*-- card.c --*/ +int card_open (CARD *rcard); +void card_close (CARD card); +int card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp); +int card_enum_keypairs (CARD card, int idx, + unsigned char *keygrip, + char **keyid); +int card_enum_certs (CARD card, int idx, char **certid, int *certtype); +int card_read_cert (CARD card, const char *certidstr, + unsigned char **cert, size_t *ncert); +int card_sign (CARD card, + const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); +int card_decipher (CARD card, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen); + + +#endif /*SCDAEMON_H*/ diff --git a/sm/ChangeLog b/sm/ChangeLog new file mode 100644 index 000000000..59a6b3271 --- /dev/null +++ b/sm/ChangeLog @@ -0,0 +1,816 @@ +2003-07-31 Werner Koch <wk@gnupg.org> + + * Makefile.am (gpgsm_LDADD): Added INTLLIBS. + +2003-07-29 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Add secmem features and set the random seed file. + (gpgsm_exit): Update the random seed file and enable debug output. + +2003-07-27 Werner Koch <wk@gnupg.org> + + Adjusted for gcry_mpi_print and gcry_mpi_scan API change. + +2003-06-24 Werner Koch <wk@gnupg.org> + + * server.c (gpgsm_status_with_err_code): New. + * verify.c (gpgsm_verify): Use it here instead of the old + tokenizing version. + + * verify.c (strtimestamp): Renamed to strtimestamp_r + + Adjusted for changes in the libgcrypt API. Some more fixes for the + libgpg-error stuff. + +2003-06-04 Werner Koch <wk@gnupg.org> + + * call-agent.c (init_membuf,put_membuf,get_membuf): Removed. + Include new membuf header and changed used type. + + Renamed error codes from INVALID to INV and removed _ERROR suffixes. + +2003-06-03 Werner Koch <wk@gnupg.org> + + Changed all error codes in all files to the new libgpg-error scheme. + + * gpgsm.h: Include gpg-error.h . + * Makefile.am: Link with libgpg-error. + +2003-04-29 Werner Koch <wk@gnupg.org> + + * Makefile.am: Use libassuan. Don't override LDFLAGS anymore. + * server.c (register_commands): Adjust for new Assuan semantics. + +2002-12-03 Werner Koch <wk@gnupg.org> + + * call-agent.c (gpgsm_agent_passwd): New. + * gpgsm.c (main): New command --passwd and --call-protect-tool + (run_protect_tool): New. + +2002-11-25 Werner Koch <wk@gnupg.org> + + * verify.c (gpgsm_verify): Handle content-type attribute. + +2002-11-13 Werner Koch <wk@gnupg.org> + + * call-agent.c (start_agent): Try to use $GPG_TTY instead of + ttyname. Changed ttyname to test stdin becuase it can be assumed + that output redirection is more common that input redirection. + +2002-11-12 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New command --call-dirmngr. + * call-dirmngr.c (gpgsm_dirmngr_run_command) + (run_command_inq_cb,run_command_cb) + (run_command_status_cb): New. + +2002-11-11 Werner Koch <wk@gnupg.org> + + * certcheck.c (gpgsm_check_cms_signature): Don't double free + s_sig but free s_pkey at leave. + +2002-11-10 Werner Koch <wk@gnupg.org> + + * gpgsm.c: Removed duplicate --list-secret-key entry. + +2002-09-19 Werner Koch <wk@gnupg.org> + + * certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging. + + * certchain.c (find_up): Print info when the cert was not found + by the autorithyKeyIdentifier. + +2002-09-03 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Disable the internal libgcrypt locking. + +2002-08-21 Werner Koch <wk@gnupg.org> + + * import.c (print_imported_summary): Cleaned up. Print new + not_imported value. + (check_and_store): Update non_imported counter. + (print_import_problem): New. + (check_and_store): Print error status message. + * server.c (get_status_string): Added STATUS_IMPORT_PROBLEM. + +2002-08-20 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Use the log file only in server mode. + + * import.c (print_imported_summary): New. + (check_and_store): Update the counters, take new argument. + (import_one): Factored out core of gpgsm_import. + (gpgsm_import): Print counters. + (gpgsm_import_files): New. + * gpgsm.c (main): Use the new function for import. + +2002-08-19 Werner Koch <wk@gnupg.org> + + * decrypt.c (gpgsm_decrypt): Return a better error status token. + * verify.c (gpgsm_verify): Don't error on messages with no signing + time or no message digest. This is only the case for messages + without any signed attributes. + +2002-08-16 Werner Koch <wk@gnupg.org> + + * certpath.c: Renamed to .. + * certchain.c: this. Renamed all all other usages of "path" in the + context of certificates to "chain". + + * call-agent.c (learn_cb): Special treatment when the issuer + certificate is missing. + +2002-08-10 Werner Koch <wk@gnupg.org> + + * Makefile.am (INCLUDES): Add definition for localedir. + + * keylist.c (list_cert_colon): Print the short fingerprint in the + key ID field. + * fingerprint.c (gpgsm_get_short_fingerprint): New. + * verify.c (gpgsm_verify): Print more verbose info for a good + signature. + +2002-08-09 Werner Koch <wk@gnupg.org> + + * decrypt.c (prepare_decryption): Hack to detected already + unpkcsedone keys. + + * gpgsm.c (emergency_cleanup): New. + (main): Initialize the signal handler. + + * sign.c (gpgsm_sign): Reset the hash context for subsequent + signers and release it at the end. + +2002-08-05 Werner Koch <wk@gnupg.org> + + * server.c (cmd_signer): New command "SIGNER" + (register_commands): Register it. + (cmd_sign): Pass the signer list to gpgsm_sign. + * certlist.c (gpgsm_add_to_certlist): Add SECRET argument, check + for secret key if set and changed all callers. + * sign.c (gpgsm_sign): New argument SIGNERLIST and implemt + multiple signers. + * gpgsm.c (main): Support more than one -u. + + * server.c (cmd_recipient): Return reason code 1 for No_Public_Key + which is actually what gets returned from add_to_certlist. + +2002-07-26 Werner Koch <wk@gnupg.org> + + * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup. + (gpgsm_check_cms_signature): Ditto. + +2002-07-22 Werner Koch <wk@gnupg.org> + + * keydb.c (keydb_add_resource): Register a lock file. + (lock_all, unlock_all): Implemented. + + * delete.c: New. + * gpgsm.c: Made --delete-key work. + * server.c (cmd_delkeys): New. + (register_commands): New command DELKEYS. + + * decrypt.c (gpgsm_decrypt): Print a convenience note when RC2 is + used and a STATUS_ERROR with the algorithm oid. + +2002-07-03 Werner Koch <wk@gnupg.org> + + * server.c (gpgsm_status2): Insert a blank between all optional + arguments when using assuan. + * server.c (cmd_recipient): No more need for extra blank in constants. + * import.c (print_imported_status): Ditto. + * gpgsm.c (main): Ditto. + +2002-07-02 Werner Koch <wk@gnupg.org> + + * verify.c (gpgsm_verify): Extend the STATUS_BADSIG line with + the fingerprint. + + * certpath.c (check_cert_policy): Don't use log_error to print a + warning. + + * keydb.c (keydb_store_cert): Add optional ar EXISTED and changed + all callers. + * call-agent.c (learn_cb): Print info message only for real imports. + + * import.c (gpgsm_import): Moved duplicated code to ... + (check_and_store): new function. Added magic to import the entire + chain. Print status only for real imports and moved printing code + to .. + (print_imported_status): New. + + * call-dirmngr.c (gpgsm_dirmngr_isvalid): print status of dirmngr + call in very verbose mode. + + * gpgsm.c (main): Use the same error codes for STATUS_INV_RECP as + with the server mode. + +2002-06-29 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New option --auto-issuer-key-retrieve. + * certpath.c (find_up): Try to retrieve an issuer key from an + external source and from the ephemeral key DB. + (find_up_store_certs_cb): New. + + * keydb.c (keydb_set_ephemeral): Does now return the old + state. Call the backend only when required. + + * call-dirmngr.c (start_dirmngr): Use GNUPG_DEFAULT_DIRMNGR. + (lookup_status_cb): Issue status only when CTRL is not NULL. + (gpgsm_dirmngr_lookup): Document that CTRL is optional. + + * call-agent.c (start_agent): Use GNUPG_DEFAULT_AGENT. + +2002-06-28 Werner Koch <wk@gnupg.org> + + * server.c (cmd_recipient): Add more reason codes. + +2002-06-27 Werner Koch <wk@gnupg.org> + + * certpath.c (gpgsm_basic_cert_check): Use + --debug-no-path-validation to also bypass this basic check. + + * gpgsm.c (main): Use GNUPG_DEFAULT_HOMEDIR constant. + + * call-agent.c (start_agent): Create and pass the list of FD to + keep in the child to assuan. + * call-dirmngr.c (start_dirmngr): Ditto. + +2002-06-26 Werner Koch <wk@gnupg.org> + + * import.c (gpgsm_import): Print an STATUS_IMPORTED. + + * gpgsm.c: --debug-no-path-validation does not take an argument. + +2002-06-25 Werner Koch <wk@gnupg.org> + + * certdump.c (print_dn_part): Always print a leading slash, + removed NEED_DELIM arg and changed caller. + + * export.c (gpgsm_export): Print LFs to FP and not stdout. + (print_short_info): Ditto. Make use of gpgsm_print_name. + + * server.c (cmd_export): Use output-fd instead of data lines; this + was actually the specified way. + +2002-06-24 Werner Koch <wk@gnupg.org> + + * gpgsm.c: Removed duped help entry for --list-keys. + + * gpgsm.c, gpgsm.h: New option --debug-no-path-validation. + + * certpath.c (gpgsm_validate_path): Use it here instead of the + debug flag hack. + + * certpath.c (check_cert_policy): Return No_Policy_Match if the + policy file could not be opened. + +2002-06-20 Werner Koch <wk@gnupg.org> + + * certlist.c (gpgsm_add_to_certlist): Fixed locating of a + certificate with the required key usage. + + * gpgsm.c (main): Fixed a segv when using --outfile without an + argument. + + * keylist.c (print_capabilities): Also check for non-repudiation + and data encipherment. + * certlist.c (cert_usage_p): Test for signing and encryption was + swapped. Add a case for certification usage, handle + non-repudiation and data encipherment. + (gpgsm_cert_use_cert_p): New. + (gpgsm_add_to_certlist): Added a CTRL argument and changed all + callers to pass it. + * certpath.c (gpgsm_validate_path): Use it here to print a status + message. Added a CTRL argument and changed all callers to pass it. + * decrypt.c (gpgsm_decrypt): Print a status message for wrong key + usage. + * verify.c (gpgsm_verify): Ditto. + * keydb.c (classify_user_id): Allow a colon delimited fingerprint. + +2002-06-19 Werner Koch <wk@gnupg.org> + + * call-agent.c (learn_cb): Use log_info instead of log_error on + successful import. + + * keydb.c (keydb_set_ephemeral): New. + (keydb_store_cert): New are ephemeral, changed all callers. + * keylist.c (list_external_cb): Store cert as ephemeral. + * export.c (gpgsm_export): Kludge to export epehmeral certificates. + + * gpgsm.c (main): New command --list-external-keys. + +2002-06-17 Werner Koch <wk@gnupg.org> + + * certreqgen.c (read_parameters): Improved error handling. + (gpgsm_genkey): Print error message. + +2002-06-13 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): New option --log-file. + +2002-06-12 Werner Koch <wk@gnupg.org> + + * call-dirmngr.c (lookup_status_cb): New. + (gpgsm_dirmngr_lookup): Use the status CB. Add new arg CTRL and + changed caller to pass it. + + * gpgsm.c (open_fwrite): New. + (main): Allow --output for --verify. + + * sign.c (hash_and_copy_data): New. + (gpgsm_sign): Implemented normal (non-detached) signatures. + * gpgsm.c (main): Ditto. + + * certpath.c (gpgsm_validate_path): Special error handling for + no policy match. + +2002-06-10 Werner Koch <wk@gnupg.org> + + * server.c (get_status_string): Add STATUS_ERROR. + + * certpath.c (gpgsm_validate_path): Tweaked the error checking to + return error codes in a more sensitive way. + * verify.c (gpgsm_verify): Send status TRUST_NEVER also for a bad + CA certificate and when the certificate has been revoked. Issue + TRUST_FULLY even when the cert has expired. Append an error token + to these status lines. Issue the new generic error status when a + cert was not found and when leaving the function. + +2002-06-04 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): New command --list-sigs + * keylist.c (list_cert_std): New. Use it whenever colon mode is + not used. + (list_cert_chain): New. + +2002-05-31 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Don't print the "go ahead" message for an + invalid command. + +2002-05-23 Werner Koch <wk@gnupg.org> + + * import.c (gpgsm_import): Add error messages. + +2002-05-21 Werner Koch <wk@gnupg.org> + + * keylist.c (list_internal_keys): Renamed from gpgsm_list_keys. + (list_external_keys): New. + (gpgsm_list_keys): Dispatcher for above. + * call-dirmngr.c (lookup_cb,pattern_from_strlist) + (gpgsm_dirmngr_lookup): New. + * server.c (option_handler): Handle new option --list-mode. + (do_listkeys): Handle options and actually use the mode argument. + (get_status_string): New code TRUNCATED. + + * import.c (gpgsm_import): Try to identify the type of input and + handle certs-only messages. + +2002-05-14 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New option --faked-system-time + * sign.c (gpgsm_sign): And use it here. + * certpath.c (gpgsm_validate_path): Ditto. + +2002-05-03 Werner Koch <wk@gnupg.org> + + * certpath.c (gpgsm_validate_path): Added EXPTIME arg and changed + all callers. + * verify.c (gpgsm_verify): Tweaked usage of log_debug and + log_error. Return EXPSIG status and add expiretime to VALIDSIG. + +2002-04-26 Werner Koch <wk@gnupg.org> + + * gpgsm.h (DBG_AGENT,DBG_AGENT_VALUE): Replaced by DBG_ASSUAN_*. + Changed all users. + + * call-agent.c (start_agent): Be more silent without -v. + * call-dirmngr.c (start_dirmngr): Ditto. + +2002-04-25 Werner Koch <wk@gnupg.org> + + * call-agent.c (start_agent): Make copies of old locales and check + for setlocale. + +2002-04-25 Marcus Brinkmann <marcus@g10code.de> + + * call-agent.c (start_agent): Fix error handling logic so the + locale is always correctly reset. + +2002-04-25 Marcus Brinkmann <marcus@g10code.de> + + * server.c (option_handler): Accept display, ttyname, ttytype, + lc_ctype and lc_messages options. + * gpgsm.c (main): Allocate memory for these options. + * gpgsm.h (struct opt): Make corresponding members non-const. + +2002-04-24 Marcus Brinkmann <marcus@g10code.de> + + * gpgsm.h (struct opt): New members display, ttyname, ttytype, + lc_ctype, lc_messages. + * gpgsm.c (enum cmd_and_opt_values): New members oDisplay, + oTTYname, oTTYtype, oLCctype, oLCmessages. + (opts): New entries for these options. + (main): Handle these new options. + * call-agent.c (start_agent): Set the various display and tty + parameter after resetting. + +2002-04-18 Werner Koch <wk@gnupg.org> + + * certreqgen.c (gpgsm_genkey): Write status output on success. + +2002-04-15 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Check ksba version. + + * certpath.c (find_up): New to use the authorithKeyIdentifier. + Use it in all other functions to locate the signing cert.. + +2002-04-11 Werner Koch <wk@gnupg.org> + + * certlist.c (cert_usable_p): New. + (gpgsm_cert_use_sign_p,gpgsm_cert_use_encrypt_p): New. + (gpgsm_cert_use_verify_p,gpgsm_cert_use_decrypt_p): New. + (gpgsm_add_to_certlist): Check the key usage. + * sign.c (gpgsm_sign): Ditto. + * verify.c (gpgsm_verify): Print a message wehn an unsuitable + certificate was used. + * decrypt.c (gpgsm_decrypt): Ditto + * keylist.c (print_capabilities): Determine values from the cert. + +2002-03-28 Werner Koch <wk@gnupg.org> + + * keylist.c (list_cert_colon): Fixed listing of crt record; the + issuer is not at the right place. Print a chainingID. + * certpath.c (gpgsm_walk_cert_chain): Be a bit more silent on + common errors. + +2002-03-21 Werner Koch <wk@gnupg.org> + + * export.c: New. + * gpgsm.c: Add command --export. + * server.c (cmd_export): New. + +2002-03-13 Werner Koch <wk@gnupg.org> + + * decrypt.c (gpgsm_decrypt): Allow multiple recipients. + +2002-03-12 Werner Koch <wk@gnupg.org> + + * certpath.c (check_cert_policy): Print the policy list. + + * verify.c (gpgsm_verify): Detect certs-only message. + +2002-03-11 Werner Koch <wk@gnupg.org> + + * import.c (gpgsm_import): Print a notice about imported certificates + when in verbose mode. + + * gpgsm.c (main): Print INV_RECP status. + * server.c (cmd_recipient): Ditto. + + * server.c (gpgsm_status2): New. Allows for a list of strings. + (gpgsm_status): Divert to gpgsm_status2. + + * encrypt.c (gpgsm_encrypt): Don't use a default key when no + recipients are given. Print a NO_RECP status. + +2002-03-06 Werner Koch <wk@gnupg.org> + + * server.c (cmd_listkeys, cmd_listsecretkeys): Divert to + (do_listkeys): new. Add pattern parsing. + + * keylist.c (gpgsm_list_keys): Handle selection pattern. + + * gpgsm.c: New command --learn-card + * call-agent.c (learn_cb,gpgsm_agent_learn): New. + + * gpgsm.c (main): Print error messages for non-implemented commands. + + * base64.c (base64_reader_cb): Use case insensitive compare of the + Content-Type string to detect plain base-64. + +2002-03-05 Werner Koch <wk@gnupg.org> + + * gpgsm.c, gpgsm.h: Add local_user. + * sign.c (gpgsm_get_default_cert): New. + (get_default_signer): Use the new function if local_user is not + set otherwise used that value. + * encrypt.c (get_default_recipient): Removed. + (gpgsm_encrypt): Use gpgsm_get_default_cert. + + * verify.c (gpgsm_verify): Better error text for a bad signature + found by comparing the hashs. + +2002-02-27 Werner Koch <wk@gnupg.org> + + * call-dirmngr.c, call-agent.c: Add 2 more arguments to all uses + of assuan_transact. + +2002-02-25 Werner Koch <wk@gnupg.org> + + * server.c (option_handler): Allow to use -2 for "send all certs + except the root cert". + * sign.c (add_certificate_list): Implement it here. + * certpath.c (gpgsm_is_root_cert): New. + +2002-02-19 Werner Koch <wk@gnupg.org> + + * certpath.c (check_cert_policy): New. + (gpgsm_validate_path): And call it from here. + * gpgsm.c (main): New options --policy-file, + --disable-policy-checks and --enable-policy-checks. + * gpgsm.h (opt): Added policy_file, no_policy_checks. + +2002-02-18 Werner Koch <wk@gnupg.org> + + * certpath.c (gpgsm_validate_path): Ask the agent to add the + certificate into the trusted list. + * call-agent.c (gpgsm_agent_marktrusted): New. + +2002-02-07 Werner Koch <wk@gnupg.org> + + * certlist.c (gpgsm_add_to_certlist): Check that the specified + name identifies a certificate unambiguously. + (gpgsm_find_cert): Ditto. + + * server.c (cmd_listkeys): Check that the data stream is available. + (cmd_listsecretkeys): Ditto. + (has_option): New. + (cmd_sign): Fix ambiguousity in option recognition. + + * gpgsm.c (main): Enable --logger-fd. + + * encrypt.c (gpgsm_encrypt): Increased buffer size for better + performance. + + * call-agent.c (gpgsm_agent_pksign): Check the S-Exp received from + the agent. + + * keylist.c (list_cert_colon): Filter out control characters. + +2002-02-06 Werner Koch <wk@gnupg.org> + + * decrypt.c (gpgsm_decrypt): Bail out after an decryption error. + + * server.c (reset_notify): Close input and output FDs. + (cmd_encrypt,cmd_decrypt,cmd_verify,cmd_sign.cmd_import) + (cmd_genkey): Close the FDs and release the recipient list even in + the error case. + +2002-02-01 Marcus Brinkmann <marcus@g10code.de> + + * sign.c (gpgsm_sign): Do not release certificate twice. + +2002-01-29 Werner Koch <wk@gnupg.org> + + * call-agent.c (gpgsm_agent_havekey): New. + * keylist.c (list_cert_colon): New arg HAVE_SECRET, print "crs" + when we know that the secret key is available. + (gpgsm_list_keys): New arg MODE, check whether a secret key is + available. Changed all callers. + * gpgsm.c (main): New command --list-secret-keys. + * server.c (cmd_listsecretkeys): New. + (cmd_listkeys): Return secret keys with "crs" record. + +2002-01-28 Werner Koch <wk@gnupg.org> + + * certreqgen.c (create_request): Store the email address in the req. + +2002-01-25 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Disable core dumps. + + * sign.c (add_certificate_list): New. + (gpgsm_sign): Add the certificates to the CMS object. + * certpath.c (gpgsm_walk_cert_chain): New. + * gpgsm.h (server_control_s): Add included_certs. + * gpgsm.c: Add option --include-certs. + (gpgsm_init_default_ctrl): New. + (main): Call it. + * server.c (gpgsm_server): Ditto. + (option_handler): Support --include-certs. + +2002-01-23 Werner Koch <wk@gnupg.org> + + * certpath.c (gpgsm_validate_path): Print the DN of a missing issuer. + * certdump.c (gpgsm_dump_string): New. + (print_dn): Replaced by above. + +2002-01-22 Werner Koch <wk@gnupg.org> + + * certpath.c (unknown_criticals): New. + (allowed_ca): New. + (gpgsm_validate_path): Check validity, CA attribute, path length + and unknown critical extensions. + +2002-01-21 Werner Koch <wk@gnupg.org> + + * gpgsm.c: Add option --enable-crl-checks. + + * call-agent.c (start_agent): Implemented socket based access. + * call-dirmngr.c (start_dirmngr): Ditto. + +2002-01-20 Werner Koch <wk@gnupg.org> + + * server.c (option_handler): New. + (gpgsm_server): Register it with assuan. + +2002-01-19 Werner Koch <wk@gnupg.org> + + * server.c (gpgsm_server): Use assuan_deinit_server and setup + assuan logging if enabled. + * call-agent.c (inq_ciphertext_cb): Don't show the session key in + an Assuan log file. + + * gpgsm.c (my_strusage): Take bugreport address from configure.ac + +2002-01-15 Werner Koch <wk@gnupg.org> + + * import.c (gpgsm_import): Just do a basic cert check before + storing it. + * certpath.c (gpgsm_basic_cert_check): New. + + * keydb.c (keydb_store_cert): New. + * import.c (store_cert): Removed and change all caller to use + the new function. + * verify.c (store_cert): Ditto. + + * certlist.c (gpgsm_add_to_certlist): Validate the path + + * certpath.c (gpgsm_validate_path): Check the trust list. + * call-agent.c (gpgsm_agent_istrusted): New. + +2002-01-14 Werner Koch <wk@gnupg.org> + + * call-dirmngr.c (inq_certificate): Changed for new interface semantic. + * certlist.c (gpgsm_find_cert): New. + +2002-01-13 Werner Koch <wk@gnupg.org> + + * fingerprint.c (gpgsm_get_certid): Print the serial and not the + hash after the dot. + +2002-01-11 Werner Koch <wk@gnupg.org> + + * call-dirmngr.c: New. + * certpath.c (gpgsm_validate_path): Check the CRL here. + * fingerprint.c (gpgsm_get_certid): New. + * gpgsm.c: New options --dirmngr-program and --disable-crl-checks. + +2002-01-10 Werner Koch <wk@gnupg.org> + + * base64.c (gpgsm_create_writer): Allow to set the object name + +2002-01-08 Werner Koch <wk@gnupg.org> + + * keydb.c (spacep): Removed because it is now in util.c + + * server.c (cmd_genkey): New. + * certreqgen.c: New. The parameter handling code has been taken + from gnupg/g10/keygen.c version 1.0.6. + * call-agent.c (gpgsm_agent_genkey): New. + +2002-01-02 Werner Koch <wk@gnupg.org> + + * server.c (rc_to_assuan_status): Removed and changed all callers + to use map_to_assuan_status. + +2001-12-20 Werner Koch <wk@gnupg.org> + + * verify.c (gpgsm_verify): Implemented non-detached signature + verification. Add OUT_FP arg, initialize a writer and changed all + callers. + * server.c (cmd_verify): Pass an out_fp if one has been set. + + * base64.c (base64_reader_cb): Try to detect an S/MIME body part. + + * certdump.c (print_sexp): Renamed to gpgsm_dump_serial, made + global. + (print_time): Renamed to gpgsm_dump_time, made global. + (gpgsm_dump_serial): Take a real S-Expression as argument and + print the first item. + * keylist.c (list_cert_colon): Ditto. + * keydb.c (keydb_search_issuer_sn): Ditto. + * decrypt.c (print_integer_sexp): Removed and made callers + use gpgsm_dump_serial. + * verify.c (print_time): Removed, made callers use gpgsm_dump_time. + +2001-12-19 Marcus Brinkmann <marcus@g10code.de> + + * call-agent.c (start_agent): Add new argument to assuan_pipe_connect. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * verify.c (print_integer_sexp): Renamed from print_integer and + print the serial number according to the S-Exp rules. + * decrypt.c (print_integer_sexp): Ditto. + +2001-12-17 Werner Koch <wk@gnupg.org> + + * keylist.c (list_cert_colon): Changed for new return value of + get_serial. + * keydb.c (keydb_search_issuer_sn): Ditto. + * certcheck.c (gpgsm_check_cert_sig): Likewise for other S-Exp + returingin functions. + * fingerprint.c (gpgsm_get_keygrip): Ditto. + * encrypt.c (encrypt_dek): Ditto + * certcheck.c (gpgsm_check_cms_signature): Ditto + * decrypt.c (prepare_decryption): Ditto. + * call-agent.c (gpgsm_agent_pkdecrypt): Removed arg ciphertextlen, + use KsbaSexp type and calculate the length. + + * certdump.c (print_sexp): Remaned from print_integer, changed caller. + + * Makefile.am: Use the LIBGCRYPT and LIBKSBA variables. + + * fingerprint.c (gpgsm_get_keygrip): Use the new + gcry_pk_get_keygrip to calculate the grip - note the algorithm and + therefore the grip values changed. + +2001-12-15 Werner Koch <wk@gnupg.org> + + * certcheck.c (gpgsm_check_cms_signature): Removed the faked-key + kludge. + (gpgsm_create_cms_signature): Removed the commented fake key + code. This makes the function pretty simple. + + * gpgsm.c (main): Renamed the default key database to "keyring.kbx". + + * decrypt.c (gpgsm_decrypt): Write STATUS_DECRYPTION_*. + * sign.c (gpgsm_sign): Write a STATUS_SIG_CREATED. + +2001-12-14 Werner Koch <wk@gnupg.org> + + * keylist.c (list_cert_colon): Kludge to show an email address + encoded in the subject's DN. + + * verify.c (gpgsm_verify): Add hash debug helpers + * sign.c (gpgsm_sign): Ditto. + + * base64.c (base64_reader_cb): Reset the linelen when we need to + skip the line and adjusted test; I somehow forgot about DeMorgan. + + * server.c (cmd_encrypt,cmd_decrypt,cmd_sign,cmd_verify) + (cmd_import): Close the FDs on success. + (close_message_fd): New. + (input_notify): Setting autodetect_encoding to 0 after initializing + it to 0 is pretty pointless. Easy to fix. + + * gpgsm.c (main): New option --debug-wait n, so that it is + possible to attach gdb when used in server mode. + + * sign.c (get_default_signer): Use keydb_classify_name here. + +2001-12-14 Marcus Brinkmann <marcus@g10code.de> + + * call-agent.c (LINELENGTH): Removed. + (gpgsm_agent_pksign): Use ASSUAN_LINELENGTH, not LINELENGTH. + (gpgsm_agent_pkdecrypt): Likewise. + +2001-12-13 Werner Koch <wk@gnupg.org> + + * keylist.c (list_cert_colon): Print alternative names of subject + and a few other values. + +2001-12-12 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): New options --assume-{armor,base64,binary}. + * base64.c (base64_reader_cb): Fixed non-autodetection mode. + +2001-12-04 Werner Koch <wk@gnupg.org> + + * call-agent.c (read_from_agent): Check for inquire responses. + (request_reply): Handle them using a new callback arg, changed all + callers. + (gpgsm_agent_pkdecrypt): New. + +2001-11-27 Werner Koch <wk@gnupg.org> + + * base64.c: New. Changed all other functions to use this instead + of direct creation of ksba_reader/writer. + * gpgsm.c (main): Set ctrl.auto_encoding unless --no-armor is used. + +2001-11-26 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New option --agent-program + * call-agent.c (start_agent): Allow to override the default path + to the agent. + + * keydb.c (keydb_add_resource): Create keybox + + * keylist.c (gpgsm_list_keys): Fixed non-server keylisting. + + * server.c (rc_to_assuan_status): New. Use it for all commands. + + + Copyright 2001, 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. diff --git a/sm/Makefile.am b/sm/Makefile.am new file mode 100644 index 000000000..6345573e5 --- /dev/null +++ b/sm/Makefile.am @@ -0,0 +1,55 @@ +# 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 + +## Process this file with automake to produce Makefile.in + +localedir = $(datadir)/locale +INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" + +bin_PROGRAMS = gpgsm + +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \ + $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) + +gpgsm_SOURCES = \ + gpgsm.c gpgsm.h \ + misc.c \ + keydb.c keydb.h \ + server.c \ + call-agent.c \ + call-dirmngr.c \ + fingerprint.c \ + base64.c \ + certlist.c \ + certdump.c \ + certcheck.c \ + certchain.c \ + keylist.c \ + verify.c \ + sign.c \ + encrypt.c \ + decrypt.c \ + import.c \ + export.c \ + delete.c \ + certreqgen.c + + +gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(KSBA_LIBS) -lgpg-error \ + @INTLLIBS@ diff --git a/sm/call-agent.c b/sm/call-agent.c new file mode 100644 index 000000000..4d26e3450 --- /dev/null +++ b/sm/call-agent.c @@ -0,0 +1,713 @@ +/* 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 + */ + +#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 "gpgsm.h" +#include <gcrypt.h> +#include <assuan.h> +#include "i18n.h" +#include "keydb.h" /* fixme: Move this to import.c */ +#include "../common/membuf.h" + + +static ASSUAN_CONTEXT agent_ctx = NULL; +static int force_pipe_server = 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; +}; + +struct learn_parm_s { + int error; + ASSUAN_CONTEXT ctx; + membuf_t *data; +}; + + + +/* 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 (which is suitable given that + the agent is not MT */ + + infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO"); + if (!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 (gpg_err_code_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 OUT_OF_CORE (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 OUT_OF_CORE (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 OUT_OF_CORE (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 OUT_OF_CORE (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 = OUT_OF_CORE (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 OUT_OF_CORE (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 = OUT_OF_CORE (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; +} + + +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; +} + + + + +/* Call the agent to do a sign operation using the key identified by + the hex string KEYGRIP. */ +int +gpgsm_agent_pksign (const char *keygrip, + unsigned char *digest, size_t digestlen, int digestalgo, + 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; + + if (digestlen*2 + 50 > DIM(line)) + return gpg_error (GPG_ERR_GENERAL); + + rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip); + line[DIM(line)-1] = 0; + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + sprintf (line, "SETHASH %d ", digestalgo); + p = line + strlen (line); + for (i=0; i < digestlen ; i++, p += 2 ) + sprintf (p, "%02X", digest[i]); + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + init_membuf (&data, 1024); + rc = assuan_transact (agent_ctx, "PKSIGN", + 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 (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL)) + { + xfree (*r_buf); *r_buf = NULL; + return gpg_error (GPG_ERR_INV_VALUE); + } + + return *r_buf? 0 : OUT_OF_CORE (errno); +} + + + + +/* Handle a CIPHERTEXT inquiry. Note, we only send the data, + assuan_transact talkes care of flushing and writing the end */ +static AssuanError +inq_ciphertext_cb (void *opaque, const char *keyword) +{ + struct cipher_parm_s *parm = opaque; + AssuanError rc; + + assuan_begin_confidential (parm->ctx); + rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen); + assuan_end_confidential (parm->ctx); + return rc; +} + + +/* Call the agent to do a decrypt operation using the key identified by + the hex string KEYGRIP. */ +int +gpgsm_agent_pkdecrypt (const char *keygrip, + KsbaConstSexp ciphertext, + char **r_buf, size_t *r_buflen ) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + membuf_t data; + struct cipher_parm_s cipher_parm; + size_t n, len; + char *buf, *endp; + size_t ciphertextlen; + + if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen) + return gpg_error (GPG_ERR_INV_VALUE); + *r_buf = NULL; + + ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL); + if (!ciphertextlen) + return gpg_error (GPG_ERR_INV_VALUE); + + 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); + + assert ( DIM(line) >= 50 ); + snprintf (line, DIM(line)-1, "SETKEY %s", keygrip); + line[DIM(line)-1] = 0; + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + init_membuf (&data, 1024); + cipher_parm.ctx = agent_ctx; + cipher_parm.ciphertext = ciphertext; + cipher_parm.ciphertextlen = ciphertextlen; + rc = assuan_transact (agent_ctx, "PKDECRYPT", + membuf_data_cb, &data, + inq_ciphertext_cb, &cipher_parm, NULL, NULL); + if (rc) + { + xfree (get_membuf (&data, &len)); + return map_assuan_err (rc); + } + + put_membuf (&data, "", 1); /* make sure it is 0 terminated */ + buf = get_membuf (&data, &len); + if (!buf) + return gpg_error (GPG_ERR_ENOMEM); + /* FIXME: We would better a return a full S-exp and not just a part */ + assert (len); + len--; /* remove the terminating 0 */ + n = strtoul (buf, &endp, 10); + if (!n || *endp != ':') + return gpg_error (GPG_ERR_INV_SEXP); + endp++; + if (endp-buf+n > len) + return gpg_error (GPG_ERR_INV_SEXP); /* oops len does not + match internal len*/ + memmove (buf, endp, n); + *r_buflen = n; + *r_buf = buf; + return 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 newkey */ +int +gpgsm_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; +} + + +/* Ask the agent whether the certificate is in the list of trusted + keys */ +int +gpgsm_agent_istrusted (KsbaCert cert) +{ + int rc; + char *fpr; + char line[ASSUAN_LINELENGTH]; + + rc = start_agent (); + if (rc) + return rc; + + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + if (!fpr) + { + log_error ("error getting the fingerprint\n"); + return gpg_error (GPG_ERR_GENERAL); + } + + snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr); + line[DIM(line)-1] = 0; + xfree (fpr); + + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + return map_assuan_err (rc); +} + +/* Ask the agent to mark CERT as a trusted Root-CA one */ +int +gpgsm_agent_marktrusted (KsbaCert cert) +{ + int rc; + char *fpr, *dn; + char line[ASSUAN_LINELENGTH]; + + rc = start_agent (); + if (rc) + return rc; + + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + if (!fpr) + { + log_error ("error getting the fingerprint\n"); + return gpg_error (GPG_ERR_GENERAL); + } + + dn = ksba_cert_get_issuer (cert, 0); + if (!dn) + { + xfree (fpr); + return gpg_error (GPG_ERR_GENERAL); + } + snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn); + line[DIM(line)-1] = 0; + ksba_free (dn); + xfree (fpr); + + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + return map_assuan_err (rc); +} + + + +/* Ask the agent whether the a corresponding secret key is available + for the given keygrip */ +int +gpgsm_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); +} + + +static AssuanError +learn_cb (void *opaque, const void *buffer, size_t length) +{ + struct learn_parm_s *parm = opaque; + size_t len; + char *buf; + KsbaCert cert; + int rc; + + if (parm->error) + return 0; + + if (buffer) + { + put_membuf (parm->data, buffer, length); + return 0; + } + /* END encountered - process what we have */ + buf = get_membuf (parm->data, &len); + if (!buf) + { + parm->error = gpg_error (GPG_ERR_ENOMEM); + return 0; + } + + + /* FIXME: this should go into import.c */ + cert = ksba_cert_new (); + if (!cert) + { + parm->error = gpg_error (GPG_ERR_ENOMEM); + return 0; + } + rc = ksba_cert_init_from_mem (cert, buf, len); + if (rc) + { + log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); + ksba_cert_release (cert); + parm->error = map_ksba_err (rc); + return 0; + } + + rc = gpgsm_basic_cert_check (cert); + if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT) + { /* For later use we store it in the ephemeral database. */ + log_info ("issuer certificate missing - storing as ephemeral\n"); + keydb_store_cert (cert, 1, NULL); + } + else if (rc) + log_error ("invalid certificate: %s\n", gpg_strerror (rc)); + else + { + int existed; + + if (!keydb_store_cert (cert, 0, &existed)) + { + if (opt.verbose > 1 && existed) + log_info ("certificate already in DB\n"); + else if (opt.verbose && !existed) + log_info ("certificate imported\n"); + } + } + + ksba_cert_release (cert); + init_membuf (parm->data, 4096); + return 0; +} + +/* Call the agent to learn about a smartcard */ +int +gpgsm_agent_learn () +{ + int rc; + struct learn_parm_s learn_parm; + membuf_t data; + size_t len; + + rc = start_agent (); + if (rc) + return rc; + + init_membuf (&data, 4096); + learn_parm.error = 0; + learn_parm.ctx = agent_ctx; + learn_parm.data = &data; + rc = assuan_transact (agent_ctx, "LEARN --send", + learn_cb, &learn_parm, + NULL, NULL, NULL, NULL); + xfree (get_membuf (&data, &len)); + if (rc) + return map_assuan_err (rc); + return learn_parm.error; +} + + +/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */ +int +gpgsm_agent_passwd (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, "PASSWD %s", hexkeygrip); + line[DIM(line)-1] = 0; + + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + return map_assuan_err (rc); +} + diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c new file mode 100644 index 000000000..b182b246c --- /dev/null +++ b/sm/call-dirmngr.c @@ -0,0 +1,632 @@ +/* call-dirmngr.c - communication with the dromngr + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> +#include <ctype.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <assuan.h> + +#include "i18n.h" + +struct membuf { + size_t len; + size_t size; + char *buf; + int out_of_core; +}; + + + +static ASSUAN_CONTEXT dirmngr_ctx = NULL; +static int force_pipe_server = 0; + +struct inq_certificate_parm_s { + ASSUAN_CONTEXT ctx; + KsbaCert cert; +}; + +struct lookup_parm_s { + CTRL ctrl; + ASSUAN_CONTEXT ctx; + void (*cb)(void *, KsbaCert); + void *cb_value; + struct membuf data; + int error; +}; + +struct run_command_parm_s { + ASSUAN_CONTEXT ctx; +}; + + +/* 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. */ + +static void +init_membuf (struct membuf *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 = 1; +} + +static void +put_membuf (struct membuf *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 = 1; + return; + } + mb->buf = p; + } + memcpy (mb->buf + mb->len, buf, len); + mb->len += len; +} + +static void * +get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ + return p; +} + + + + + +/* 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_dirmngr (void) +{ + int rc; + char *infostr, *p; + ASSUAN_CONTEXT ctx; + + if (dirmngr_ctx) + return 0; /* fixme: We need a context for each thread or serialize + the access to the dirmngr */ + + infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); + if (!infostr) + { + const char *pgmname; + const char *argv[3]; + int no_close_list[3]; + int i; + + if (opt.verbose) + log_info (_("no running dirmngr - starting one\n")); + + if (fflush (NULL)) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error flushing pending output: %s\n", strerror (errno)); + return tmperr; + } + + if (!opt.dirmngr_program || !*opt.dirmngr_program) + opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR; + if ( !(pgmname = strrchr (opt.dirmngr_program, '/'))) + pgmname = opt.dirmngr_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.dirmngr_program, (char**)argv, + no_close_list); + } + else + { + int prot; + int pid; + + infostr = xstrdup (infostr); + if ( !(p = strchr (infostr, ':')) || p == infostr) + { + log_error (_("malformed DIRMNGR_INFO environment variable\n")); + xfree (infostr); + force_pipe_server = 1; + return start_dirmngr (); + } + *p++ = 0; + pid = atoi (p); + while (*p && *p != ':') + p++; + prot = *p? atoi (p+1) : 0; + if (prot != 1) + { + log_error (_("dirmngr protocol version %d is not supported\n"), + prot); + xfree (infostr); + force_pipe_server = 1; + return start_dirmngr (); + } + + rc = assuan_socket_connect (&ctx, infostr, pid); + xfree (infostr); + if (rc == ASSUAN_Connect_Failed) + { + log_error (_("can't connect to the dirmngr - trying fall back\n")); + force_pipe_server = 1; + return start_dirmngr (); + } + } + + if (rc) + { + log_error ("can't connect to the dirmngr: %s\n", assuan_strerror (rc)); + return gpg_error (GPG_ERR_NO_DIRMNGR); + } + dirmngr_ctx = ctx; + + if (DBG_ASSUAN) + log_debug ("connection to dirmngr established\n"); + return 0; +} + + + +/* Handle a SENDCERT inquiry. */ +static AssuanError +inq_certificate (void *opaque, const char *line) +{ + struct inq_certificate_parm_s *parm = opaque; + AssuanError rc; + const unsigned char *der; + size_t derlen; + + if (!(!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))) + { + log_error ("unsupported inquiry `%s'\n", line); + return ASSUAN_Inquire_Unknown; + } + line += 8; + + if (!*line) + { /* send the current certificate */ + der = ksba_cert_get_image (parm->cert, &derlen); + if (!der) + rc = ASSUAN_Inquire_Error; + else + rc = assuan_send_data (parm->ctx, der, derlen); + } + else + { /* send the given certificate */ + int err; + KsbaCert cert; + + err = gpgsm_find_cert (line, &cert); + if (err) + { + log_error ("certificate not found: %s\n", gpg_strerror (err)); + rc = ASSUAN_Inquire_Error; + } + else + { + der = ksba_cert_get_image (cert, &derlen); + if (!der) + rc = ASSUAN_Inquire_Error; + else + rc = assuan_send_data (parm->ctx, der, derlen); + ksba_cert_release (cert); + } + } + + return rc; +} + + + +/* Call the directory manager to check whether the certificate is valid + Returns 0 for valid or usually one of the errors: + + GPG_ERR_CERTIFICATE_REVOKED + GPG_ERR_NO_CRL_KNOWN + GPG_ERR_CRL_TOO_OLD + */ +int +gpgsm_dirmngr_isvalid (KsbaCert cert) +{ + int rc; + char *certid; + char line[ASSUAN_LINELENGTH]; + struct inq_certificate_parm_s parm; + + rc = start_dirmngr (); + if (rc) + return rc; + + certid = gpgsm_get_certid (cert); + if (!certid) + { + log_error ("error getting the certificate ID\n"); + return gpg_error (GPG_ERR_GENERAL); + } + + if (opt.verbose > 1) + { + char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1); + log_info ("asking dirmngr about %s\n", fpr); + xfree (fpr); + } + + parm.ctx = dirmngr_ctx; + parm.cert = cert; + + snprintf (line, DIM(line)-1, "ISVALID %s", certid); + line[DIM(line)-1] = 0; + xfree (certid); + + rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, + inq_certificate, &parm, NULL, NULL); + if (opt.verbose > 1) + log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); + return map_assuan_err (rc); +} + + + +/* Lookup helpers*/ +static AssuanError +lookup_cb (void *opaque, const void *buffer, size_t length) +{ + struct lookup_parm_s *parm = opaque; + size_t len; + char *buf; + KsbaCert cert; + int rc; + + if (parm->error) + return 0; + + if (buffer) + { + put_membuf (&parm->data, buffer, length); + return 0; + } + /* END encountered - process what we have */ + buf = get_membuf (&parm->data, &len); + if (!buf) + { + parm->error = gpg_error (GPG_ERR_ENOMEM); + return 0; + } + + cert = ksba_cert_new (); + if (!cert) + { + parm->error = gpg_error (GPG_ERR_ENOMEM); + return 0; + } + rc = ksba_cert_init_from_mem (cert, buf, len); + if (rc) + { + log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); + } + else + { + parm->cb (parm->cb_value, cert); + } + + ksba_cert_release (cert); + init_membuf (&parm->data, 4096); + return 0; +} + +/* Return a properly escaped pattern from NAMES. The only error + return is NULL to indicate a malloc failure. */ +static char * +pattern_from_strlist (STRLIST names) +{ + STRLIST sl; + int n; + const char *s; + char *pattern, *p; + + for (n=0, sl=names; sl; sl = sl->next) + { + for (s=sl->d; *s; s++, n++) + { + if (*s == '%' || *s == ' ' || *s == '+') + n += 2; + } + n++; + } + + p = pattern = xtrymalloc (n+1); + if (!pattern) + return NULL; + + for (n=0, sl=names; sl; sl = sl->next) + { + for (s=sl->d; *s; s++) + { + switch (*s) + { + case '%': + *p++ = '%'; + *p++ = '2'; + *p++ = '5'; + break; + case ' ': + *p++ = '%'; + *p++ = '2'; + *p++ = '0'; + break; + case '+': + *p++ = '%'; + *p++ = '2'; + *p++ = 'B'; + break; + default: + *p++ = *s; + break; + } + } + *p++ = ' '; + } + if (p == pattern) + *pattern = 0; /* is empty */ + else + p[-1] = '\0'; /* remove trailing blank */ + + return pattern; +} + +static AssuanError +lookup_status_cb (void *opaque, const char *line) +{ + struct lookup_parm_s *parm = opaque; + + if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) + { + if (parm->ctrl) + { + for (line +=9; *line == ' '; line++) + ; + gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line); + } + } + return 0; +} + + +/* Run the Directroy Managers lookup command using the pattern + compiled from the strings given in NAMES. The caller must provide + the callback CB which will be passed cert by cert. Note that CTRL + is optional. */ +int +gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, + void (*cb)(void*, KsbaCert), void *cb_value) +{ + int rc; + char *pattern; + char line[ASSUAN_LINELENGTH]; + struct lookup_parm_s parm; + size_t len; + + rc = start_dirmngr (); + if (rc) + return rc; + + pattern = pattern_from_strlist (names); + if (!pattern) + return OUT_OF_CORE (errno); + snprintf (line, DIM(line)-1, "LOOKUP %s", pattern); + line[DIM(line)-1] = 0; + xfree (pattern); + + parm.ctrl = ctrl; + parm.ctx = dirmngr_ctx; + parm.cb = cb; + parm.cb_value = cb_value; + parm.error = 0; + init_membuf (&parm.data, 4096); + + rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm, + NULL, NULL, lookup_status_cb, &parm); + xfree (get_membuf (&parm.data, &len)); + if (rc) + return map_assuan_err (rc); + return parm.error; +} + + + +/* Run Command helpers*/ + +/* Fairly simple callback to write all output of dirmngr to stdout. */ +static AssuanError +run_command_cb (void *opaque, const void *buffer, size_t length) +{ + if (buffer) + { + if ( fwrite (buffer, length, 1, stdout) != 1 ) + log_error ("error writing to stdout: %s\n", strerror (errno)); + } + return 0; +} + +/* Handle inquiries from the dirmngr COMMAND. */ +static AssuanError +run_command_inq_cb (void *opaque, const char *line) +{ + struct run_command_parm_s *parm = opaque; + AssuanError rc = 0; + + if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) ) + { /* send the given certificate */ + int err; + KsbaCert cert; + const unsigned char *der; + size_t derlen; + + line += 8; + if (!*line) + return ASSUAN_Inquire_Error; + + err = gpgsm_find_cert (line, &cert); + if (err) + { + log_error ("certificate not found: %s\n", gpg_strerror (err)); + rc = ASSUAN_Inquire_Error; + } + else + { + der = ksba_cert_get_image (cert, &derlen); + if (!der) + rc = ASSUAN_Inquire_Error; + else + rc = assuan_send_data (parm->ctx, der, derlen); + ksba_cert_release (cert); + } + } + else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) ) + { /* Simply show the message given in the argument. */ + line += 9; + log_info ("dirmngr: %s\n", line); + } + else + { + log_error ("unsupported inquiry `%s'\n", line); + rc = ASSUAN_Inquire_Unknown; + } + + return rc; +} + +static AssuanError +run_command_status_cb (void *opaque, const char *line) +{ + if (opt.verbose) + { + log_info ("dirmngr status: %s\n", line); + } + return 0; +} + + + +/* Pass COMMAND to dirmngr and print all output generated by Dirmngr + to stdout. A couple of inquiries are defined (see above). ARGC + arguments in ARGV are given to the Dirmngr. Spaces, plus and + percent characters within the argument strings are percent escaped + so that blanks can act as delimiters. */ +int +gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, + int argc, char **argv) +{ + int rc; + int i; + const char *s; + char *line, *p; + size_t len; + struct run_command_parm_s parm; + + rc = start_dirmngr (); + if (rc) + return rc; + + parm.ctx = dirmngr_ctx; + + len = strlen (command) + 1; + for (i=0; i < argc; i++) + len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */ + line = xtrymalloc (len); + if (!line) + return OUT_OF_CORE (errno); + + p = stpcpy (line, command); + for (i=0; i < argc; i++) + { + *p++ = ' '; + for (s=argv[i]; *s; s++) + { + if (!isascii (*s)) + *p++ = *s; + else if (*s == ' ') + *p++ = '+'; + else if (!isprint (*s) || *s == '+') + { + sprintf (p, "%%%02X", *s); + p += 3; + } + else + *p++ = *s; + } + } + *p = 0; + + rc = assuan_transact (dirmngr_ctx, line, + run_command_cb, NULL, + run_command_inq_cb, &parm, + run_command_status_cb, NULL); + xfree (line); + log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); + return map_assuan_err (rc); +} diff --git a/sm/certchain.c b/sm/certchain.c new file mode 100644 index 000000000..6323c725e --- /dev/null +++ b/sm/certchain.c @@ -0,0 +1,793 @@ +/* certchain.c - certificate chain validation + * 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 <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +static int +unknown_criticals (KsbaCert cert) +{ + static const char *known[] = { + "2.5.29.15", /* keyUsage */ + "2.5.29.19", /* basic Constraints */ + "2.5.29.32", /* certificatePolicies */ + NULL + }; + int rc = 0, i, idx, crit; + const char *oid; + KsbaError err; + + for (idx=0; !(err=ksba_cert_get_extension (cert, idx, + &oid, &crit, NULL, NULL));idx++) + { + if (!crit) + continue; + for (i=0; known[i] && strcmp (known[i],oid); i++) + ; + if (!known[i]) + { + log_error (_("critical certificate extension %s is not supported\n"), + oid); + rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT); + } + } + if (err && err != -1) + rc = map_ksba_err (err); + + return rc; +} + +static int +allowed_ca (KsbaCert cert, int *chainlen) +{ + KsbaError err; + int flag; + + err = ksba_cert_is_ca (cert, &flag, chainlen); + if (err) + return map_ksba_err (err); + if (!flag) + { + log_error (_("issuer certificate is not marked as a CA\n")); + return gpg_error (GPG_ERR_BAD_CA_CERT); + } + return 0; +} + + +static int +check_cert_policy (KsbaCert cert) +{ + KsbaError err; + char *policies; + FILE *fp; + int any_critical; + + err = ksba_cert_get_cert_policies (cert, &policies); + if (err == KSBA_No_Data) + return 0; /* no policy given */ + if (err) + return map_ksba_err (err); + + /* STRING is a line delimited list of certifiate policies as stored + in the certificate. The line itself is colon delimited where the + first field is the OID of the policy and the second field either + N or C for normal or critical extension */ + + if (opt.verbose > 1) + log_info ("certificate's policy list: %s\n", policies); + + /* The check is very minimal but won't give false positives */ + any_critical = !!strstr (policies, ":C"); + + if (!opt.policy_file) + { + xfree (policies); + if (any_critical) + { + log_error ("critical marked policy without configured policies\n"); + return gpg_error (GPG_ERR_NO_POLICY_MATCH); + } + return 0; + } + + fp = fopen (opt.policy_file, "r"); + if (!fp) + { + log_error ("failed to open `%s': %s\n", + opt.policy_file, strerror (errno)); + xfree (policies); + return gpg_error (GPG_ERR_NO_POLICY_MATCH); + } + + for (;;) + { + int c; + char *p, line[256]; + char *haystack, *allowed; + + /* read line */ + do + { + if (!fgets (line, DIM(line)-1, fp) ) + { + gpg_error_t tmperr; + + xfree (policies); + if (feof (fp)) + { + fclose (fp); + /* with no critical policies this is only a warning */ + if (!any_critical) + { + log_info (_("note: certificate policy not allowed\n")); + return 0; + } + log_error (_("certificate policy not allowed\n")); + return gpg_error (GPG_ERR_NO_POLICY_MATCH); + } + tmperr = gpg_error (gpg_err_code_from_errno (errno)); + fclose (fp); + return tmperr; + } + + if (!*line || line[strlen(line)-1] != '\n') + { + /* eat until end of line */ + while ( (c=getc (fp)) != EOF && c != '\n') + ; + fclose (fp); + xfree (policies); + return gpg_error (*line? GPG_ERR_LINE_TOO_LONG + : GPG_ERR_INCOMPLETE_LINE); + } + + /* Allow for empty lines and spaces */ + for (p=line; spacep (p); p++) + ; + } + while (!*p || *p == '\n' || *p == '#'); + + /* parse line */ + for (allowed=line; spacep (allowed); allowed++) + ; + p = strpbrk (allowed, " :\n"); + if (!*p || p == allowed) + { + fclose (fp); + xfree (policies); + return gpg_error (GPG_ERR_CONFIGURATION); + } + *p = 0; /* strip the rest of the line */ + /* See whether we find ALLOWED (which is an OID) in POLICIES */ + for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1) + { + if ( !(p == policies || p[-1] == '\n') ) + continue; /* does not match the begin of a line */ + if (p[strlen (allowed)] != ':') + continue; /* the length does not match */ + /* Yep - it does match so return okay */ + fclose (fp); + xfree (policies); + return 0; + } + } +} + + +static void +find_up_store_certs_cb (void *cb_value, KsbaCert cert) +{ + if (keydb_store_cert (cert, 1, NULL)) + log_error ("error storing issuer certificate as ephemeral\n"); + ++*(int*)cb_value; +} + + +static int +find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer) +{ + KsbaName authid; + KsbaSexp authidno; + int rc = -1; + + if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno)) + { + const char *s = ksba_name_enum (authid, 0); + if (s && *authidno) + { + rc = keydb_search_issuer_sn (kh, s, authidno); + if (rc) + keydb_search_reset (kh); + if (rc == -1) + { /* And try the ephemeral DB. */ + int old = keydb_set_ephemeral (kh, 1); + if (!old) + { + rc = keydb_search_issuer_sn (kh, s, authidno); + if (rc) + keydb_search_reset (kh); + } + keydb_set_ephemeral (kh, old); + } + } + /* print a note so that the user does not feel too helpless when + an issuer certificate was found and gpgsm prints BAD + signature becuase it is not the correct one. */ + if (rc == -1) + { + log_info ("issuer certificate (#"); + gpgsm_dump_serial (authidno); + log_printf ("/"); + gpgsm_dump_string (s); + log_printf (") not found\n"); + } + else if (rc) + log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc); + ksba_name_release (authid); + xfree (authidno); + /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */ + } + + if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */ + rc = keydb_search_subject (kh, issuer); + if (rc == -1) + { + /* Not found, lets see whether we have one in the ephemeral key DB. */ + int old = keydb_set_ephemeral (kh, 1); + if (!old) + { + keydb_search_reset (kh); + rc = keydb_search_subject (kh, issuer); + } + keydb_set_ephemeral (kh, old); + } + + if (rc == -1 && opt.auto_issuer_key_retrieve) + { + STRLIST names = NULL; + int count = 0; + char *pattern; + const char *s; + + if (opt.verbose) + log_info (_("looking up issuer at external location\n")); + /* dirmngr is confused about unknown attributes so has a quick + and ugly hack we locate the CN and use this and the + following. Fixme: we should have far better parsing in the + dirmngr. */ + s = strstr (issuer, "CN="); + if (!s || s == issuer || s[-1] != ',') + s = issuer; + + pattern = xtrymalloc (strlen (s)+2); + if (!pattern) + return OUT_OF_CORE (errno); + strcpy (stpcpy (pattern, "/"), s); + add_to_strlist (&names, pattern); + xfree (pattern); + rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count); + free_strlist (names); + if (opt.verbose) + log_info (_("number of issuers matching: %d\n"), count); + if (rc) + { + log_error ("external key lookup failed: %s\n", gpg_strerror (rc)); + rc = -1; + } + else if (!count) + rc = -1; + else + { + int old; + /* The issuers are currently stored in the ephemeral key + DB, so we temporary switch to ephemeral mode. */ + old = keydb_set_ephemeral (kh, 1); + keydb_search_reset (kh); + rc = keydb_search_subject (kh, issuer); + keydb_set_ephemeral (kh, old); + } + } + return rc; +} + + +/* Return the next certificate up in the chain starting at START. + Returns -1 when there are no more certificates. */ +int +gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next) +{ + int rc = 0; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + + *r_next = NULL; + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + issuer = ksba_cert_get_issuer (start, 0); + subject = ksba_cert_get_subject (start, 0); + if (!issuer) + { + log_error ("no issuer found in certificate\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + if (!subject) + { + log_error ("no subject found in certificate\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + + if (!strcmp (issuer, subject)) + { + rc = -1; /* we are at the root */ + goto leave; + } + + rc = find_up (kh, start, issuer); + if (rc) + { + /* it is quite common not to have a certificate, so better don't + print an error here */ + if (rc != -1 && opt.verbose > 1) + log_error ("failed to find issuer's certificate: rc=%d\n", rc); + rc = gpg_error (GPG_ERR_MISSING_CERT); + goto leave; + } + + rc = keydb_get_cert (kh, r_next); + if (rc) + { + log_error ("failed to get cert: rc=%d\n", rc); + rc = gpg_error (GPG_ERR_GENERAL); + } + + leave: + xfree (issuer); + xfree (subject); + keydb_release (kh); + return rc; +} + + +/* Check whether the CERT is a root certificate. Returns True if this + is the case. */ +int +gpgsm_is_root_cert (KsbaCert cert) +{ + char *issuer; + char *subject; + int yes; + + issuer = ksba_cert_get_issuer (cert, 0); + subject = ksba_cert_get_subject (cert, 0); + yes = (issuer && subject && !strcmp (issuer, subject)); + xfree (issuer); + xfree (subject); + return yes; +} + + +/* Validate a chain and optionally return the nearest expiration time + in R_EXPTIME */ +int +gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) +{ + int rc = 0, depth = 0, maxdepth; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + KsbaCert subject_cert = NULL, issuer_cert = NULL; + time_t current_time = gnupg_get_time (); + time_t exptime = 0; + int any_expired = 0; + int any_revoked = 0; + int any_no_crl = 0; + int any_crl_too_old = 0; + int any_no_policy_match = 0; + + if (r_exptime) + *r_exptime = 0; + + if (opt.no_chain_validation) + { + log_info ("WARNING: bypassing certificate chain validation\n"); + return 0; + } + + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + if (DBG_X509) + gpgsm_dump_cert ("subject", cert); + + subject_cert = cert; + maxdepth = 50; + + for (;;) + { + xfree (issuer); + xfree (subject); + issuer = ksba_cert_get_issuer (subject_cert, 0); + subject = ksba_cert_get_subject (subject_cert, 0); + + if (!issuer) + { + log_error ("no issuer found in certificate\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + + { + time_t not_before, not_after; + + not_before = ksba_cert_get_validity (subject_cert, 0); + not_after = ksba_cert_get_validity (subject_cert, 1); + if (not_before == (time_t)(-1) || not_after == (time_t)(-1)) + { + log_error ("certificate with invalid validity\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + + if (not_after) + { + if (!exptime) + exptime = not_after; + else if (not_after < exptime) + exptime = not_after; + } + + if (not_before && current_time < not_before) + { + log_error ("certificate too young; valid from "); + gpgsm_dump_time (not_before); + log_printf ("\n"); + rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG); + goto leave; + } + if (not_after && current_time > not_after) + { + log_error ("certificate has expired at "); + gpgsm_dump_time (not_after); + log_printf ("\n"); + any_expired = 1; + } + } + + rc = unknown_criticals (subject_cert); + if (rc) + goto leave; + + if (!opt.no_policy_check) + { + rc = check_cert_policy (subject_cert); + if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH) + { + any_no_policy_match = 1; + rc = 1; + } + else if (rc) + goto leave; + } + + if (!opt.no_crl_check) + { + rc = gpgsm_dirmngr_isvalid (subject_cert); + if (rc) + { + switch (rc) + { + case GPG_ERR_CERT_REVOKED: + log_error (_("the certificate has been revoked\n")); + any_revoked = 1; + break; + case GPG_ERR_NO_CRL_KNOWN: + log_error (_("no CRL found for certificate\n")); + any_no_crl = 1; + break; + case GPG_ERR_CRL_TOO_OLD: + log_error (_("the available CRL is too old\n")); + log_info (_("please make sure that the " + "\"dirmngr\" is properly installed\n")); + any_crl_too_old = 1; + break; + default: + log_error (_("checking the CRL failed: %s\n"), + gpg_strerror (rc)); + goto leave; + } + rc = 0; + } + } + + if (subject && !strcmp (issuer, subject)) + { + if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) + { + log_error ("selfsigned certificate has a BAD signatures\n"); + rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN + : GPG_ERR_BAD_CERT); + goto leave; + } + rc = allowed_ca (subject_cert, NULL); + if (rc) + goto leave; + + rc = gpgsm_agent_istrusted (subject_cert); + if (!rc) + ; + else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) + { + int rc2; + + char *fpr = gpgsm_get_fingerprint_string (subject_cert, + GCRY_MD_SHA1); + log_info (_("root certificate is not marked trusted\n")); + log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); + xfree (fpr); + rc2 = gpgsm_agent_marktrusted (subject_cert); + if (!rc2) + { + log_info (_("root certificate has now" + " been marked as trusted\n")); + rc = 0; + } + else + { + gpgsm_dump_cert ("issuer", subject_cert); + log_info ("after checking the fingerprint, you may want " + "to enter it manually into " + "\"~/.gnupg-test/trustlist.txt\"\n"); + } + } + else + { + log_error (_("checking the trust list failed: %s\n"), + gpg_strerror (rc)); + } + + break; /* okay, a self-signed certicate is an end-point */ + } + + depth++; + if (depth > maxdepth) + { + log_error (_("certificate chain too long\n")); + rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN); + goto leave; + } + + /* find the next cert up the tree */ + keydb_search_reset (kh); + rc = find_up (kh, subject_cert, issuer); + if (rc) + { + if (rc == -1) + { + log_info ("issuer certificate (#/"); + gpgsm_dump_string (issuer); + log_printf (") not found\n"); + } + else + log_error ("failed to find issuer's certificate: rc=%d\n", rc); + rc = gpg_error (GPG_ERR_MISSING_CERT); + goto leave; + } + + ksba_cert_release (issuer_cert); issuer_cert = NULL; + rc = keydb_get_cert (kh, &issuer_cert); + if (rc) + { + log_error ("failed to get cert: rc=%d\n", rc); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + if (DBG_X509) + { + log_debug ("got issuer's certificate:\n"); + gpgsm_dump_cert ("issuer", issuer_cert); + } + + if (gpgsm_check_cert_sig (issuer_cert, subject_cert) ) + { + log_error ("certificate has a BAD signatures\n"); + rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN); + goto leave; + } + + { + int chainlen; + rc = allowed_ca (issuer_cert, &chainlen); + if (rc) + goto leave; + if (chainlen >= 0 && (depth - 1) > chainlen) + { + log_error (_("certificate chain longer than allowed by CA (%d)\n"), + chainlen); + rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN); + goto leave; + } + } + + rc = gpgsm_cert_use_cert_p (issuer_cert); + if (rc) + { + char numbuf[50]; + sprintf (numbuf, "%d", rc); + gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", + numbuf, NULL); + rc = 0; + } + + if (opt.verbose) + log_info ("certificate is good\n"); + + keydb_search_reset (kh); + subject_cert = issuer_cert; + issuer_cert = NULL; + } + + if (opt.no_policy_check) + log_info ("policies not checked due to --disable-policy-checks option\n"); + if (opt.no_crl_check) + log_info ("CRLs not checked due to --disable-crl-checks option\n"); + + if (!rc) + { /* If we encountered an error somewhere during the checks, set + the error code to the most critical one */ + if (any_revoked) + rc = gpg_error (GPG_ERR_CERT_REVOKED); + else if (any_no_crl) + rc = gpg_error (GPG_ERR_NO_CRL_KNOWN); + else if (any_crl_too_old) + rc = gpg_error (GPG_ERR_CRL_TOO_OLD); + else if (any_no_policy_match) + rc = gpg_error (GPG_ERR_NO_POLICY_MATCH); + else if (any_expired) + rc = gpg_error (GPG_ERR_CERT_EXPIRED); + } + + leave: + if (r_exptime) + *r_exptime = exptime; + xfree (issuer); + keydb_release (kh); + ksba_cert_release (issuer_cert); + if (subject_cert != cert) + ksba_cert_release (subject_cert); + return rc; +} + + +/* Check that the given certificate is valid but DO NOT check any + constraints. We assume that the issuers certificate is already in + the DB and that this one is valid; which it should be because it + has been checked using this function. */ +int +gpgsm_basic_cert_check (KsbaCert cert) +{ + int rc = 0; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + KsbaCert issuer_cert = NULL; + + if (opt.no_chain_validation) + { + log_info ("WARNING: bypassing basic certificate checks\n"); + return 0; + } + + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + issuer = ksba_cert_get_issuer (cert, 0); + subject = ksba_cert_get_subject (cert, 0); + if (!issuer) + { + log_error ("no issuer found in certificate\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + + if (subject && !strcmp (issuer, subject)) + { + if (gpgsm_check_cert_sig (cert, cert) ) + { + log_error ("selfsigned certificate has a BAD signatures\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + } + else + { + /* find the next cert up the tree */ + keydb_search_reset (kh); + rc = find_up (kh, cert, issuer); + if (rc) + { + if (rc == -1) + { + log_info ("issuer certificate (#/"); + gpgsm_dump_string (issuer); + log_printf (") not found\n"); + } + else + log_error ("failed to find issuer's certificate: rc=%d\n", rc); + rc = gpg_error (GPG_ERR_MISSING_CERT); + goto leave; + } + + ksba_cert_release (issuer_cert); issuer_cert = NULL; + rc = keydb_get_cert (kh, &issuer_cert); + if (rc) + { + log_error ("failed to get cert: rc=%d\n", rc); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + if (gpgsm_check_cert_sig (issuer_cert, cert) ) + { + log_error ("certificate has a BAD signatures\n"); + rc = gpg_error (GPG_ERR_BAD_CERT); + goto leave; + } + if (opt.verbose) + log_info ("certificate is good\n"); + } + + leave: + xfree (issuer); + keydb_release (kh); + ksba_cert_release (issuer_cert); + return rc; +} + diff --git a/sm/certcheck.c b/sm/certcheck.c new file mode 100644 index 000000000..35509c67e --- /dev/null +++ b/sm/certcheck.c @@ -0,0 +1,300 @@ +/* certcheck.c - check one certificate + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + + +static int +do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, + gcry_mpi_t *r_val) +{ + int nframe = (nbits+7) / 8; + byte *frame; + int i, n; + byte asn[100]; + size_t asnlen; + size_t len; + + asnlen = DIM(asn); + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + log_error ("No object identifier for algo %d\n", algo); + return gpg_error (GPG_ERR_INTERNAL); + } + + len = gcry_md_get_algo_dlen (algo); + + if ( len + asnlen + 4 > nframe ) + { + log_error ("can't encode a %d bit MD into a %d bits frame\n", + (int)(len*8), (int)nbits); + return gpg_error (GPG_ERR_INTERNAL); + } + + /* We encode the MD in this way: + * + * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) + * + * PAD consists of FF bytes. + */ + frame = xtrymalloc (nframe); + if (!frame) + return OUT_OF_CORE (errno); + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - len - asnlen -3 ; + assert ( i > 1 ); + memset ( frame+n, 0xff, i ); n += i; + frame[n++] = 0; + memcpy ( frame+n, asn, asnlen ); n += asnlen; + memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; + assert ( n == nframe ); + if (DBG_X509) + { + int j; + log_debug ("encoded hash:"); + for (j=0; j < nframe; j++) + log_printf (" %02X", frame[j]); + log_printf ("\n"); + } + + gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe); + xfree (frame); + return 0; +} + + +/* + Check the signature on CERT using the ISSUER-CERT. This function + does only test the cryptographic signature and nothing else. It is + assumed that the ISSUER_CERT is valid. */ +int +gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert) +{ + const char *algoid; + gcry_md_hd_t md; + int rc, algo; + gcry_mpi_t frame; + KsbaSexp p; + size_t n; + gcry_sexp_t s_sig, s_hash, s_pkey; + + algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert))); + if (!algo) + { + log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); + return gpg_error (GPG_ERR_GENERAL); + } + rc = gcry_md_open (&md, algo, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + return rc; + } + if (DBG_HASHING) + gcry_md_start_debug (md, "hash.cert"); + + rc = ksba_cert_hash (cert, 1, HASH_FNC, md); + if (rc) + { + log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); + gcry_md_close (md); + return map_ksba_err (rc); + } + gcry_md_final (md); + + p = ksba_cert_get_sig_val (cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + log_error ("libksba did not return a proper S-Exp\n"); + gcry_md_close (md); + ksba_free (p); + return gpg_error (GPG_ERR_BUG); + } + if (DBG_X509) + { + int j; + log_debug ("signature value:"); + for (j=0; j < n; j++) + log_printf (" %02X", p[j]); + log_printf ("\n"); + } + + rc = gcry_sexp_sscan ( &s_sig, NULL, p, n); + ksba_free (p); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + gcry_md_close (md); + return rc; + } + + p = ksba_cert_get_public_key (issuer_cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + log_error ("libksba did not return a proper S-Exp\n"); + gcry_md_close (md); + ksba_free (p); + gcry_sexp_release (s_sig); + return gpg_error (GPG_ERR_BUG); + } + rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + ksba_free (p); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + gcry_md_close (md); + gcry_sexp_release (s_sig); + return rc; + } + + rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); + if (rc) + { + gcry_md_close (md); + gcry_sexp_release (s_sig); + gcry_sexp_release (s_pkey); + return rc; + } + + /* put hash into the S-Exp s_hash */ + if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) + BUG (); + gcry_mpi_release (frame); + + + rc = gcry_pk_verify (s_sig, s_hash, s_pkey); + if (DBG_CRYPTO) + log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); + gcry_md_close (md); + gcry_sexp_release (s_sig); + gcry_sexp_release (s_hash); + gcry_sexp_release (s_pkey); + return rc; +} + + + +int +gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, + gcry_md_hd_t md, int algo) +{ + int rc; + KsbaSexp p; + gcry_mpi_t frame; + gcry_sexp_t s_sig, s_hash, s_pkey; + size_t n; + + n = gcry_sexp_canon_len (sigval, 0, NULL, NULL); + if (!n) + { + log_error ("libksba did not return a proper S-Exp\n"); + return gpg_error (GPG_ERR_BUG); + } + rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + return rc; + } + + p = ksba_cert_get_public_key (cert); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + log_error ("libksba did not return a proper S-Exp\n"); + ksba_free (p); + gcry_sexp_release (s_sig); + return gpg_error (GPG_ERR_BUG); + } + if (DBG_X509) + log_printhex ("public key: ", p, n); + + rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + ksba_free (p); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + gcry_sexp_release (s_sig); + return rc; + } + + + rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); + if (rc) + { + gcry_sexp_release (s_sig); + gcry_sexp_release (s_pkey); + return rc; + } + /* put hash into the S-Exp s_hash */ + if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) + BUG (); + gcry_mpi_release (frame); + + rc = gcry_pk_verify (s_sig, s_hash, s_pkey); + if (DBG_CRYPTO) + log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); + gcry_sexp_release (s_sig); + gcry_sexp_release (s_hash); + gcry_sexp_release (s_pkey); + return rc; +} + + + +int +gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo, + char **r_sigval) +{ + int rc; + char *grip; + size_t siglen; + + grip = gpgsm_get_keygrip_hexstring (cert); + if (!grip) + return gpg_error (GPG_ERR_BAD_CERT); + + rc = gpgsm_agent_pksign (grip, gcry_md_read(md, mdalgo), + gcry_md_get_algo_dlen (mdalgo), mdalgo, + r_sigval, &siglen); + xfree (grip); + return rc; +} + + + diff --git a/sm/certdump.c b/sm/certdump.c new file mode 100644 index 000000000..703e07186 --- /dev/null +++ b/sm/certdump.c @@ -0,0 +1,457 @@ +/* certdump.c - Dump a certificate for debugging + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +struct dn_array_s { + char *key; + char *value; +}; + + +/* print the first element of an S-Expression */ +void +gpgsm_print_serial (FILE *fp, KsbaConstSexp p) +{ + unsigned long n; + KsbaConstSexp endp; + + if (!p) + fputs (_("none"), fp); + else if (*p != '(') + fputs ("[Internal error - not an S-expression]", fp); + else + { + p++; + n = strtoul (p, (char**)&endp, 10); + p = endp; + if (*p!=':') + fputs ("[Internal Error - invalid S-expression]", fp); + else + { + for (p++; n; n--, p++) + fprintf (fp, "%02X", *p); + } + } +} + + +void +gpgsm_dump_serial (KsbaConstSexp p) +{ + unsigned long n; + KsbaConstSexp endp; + + if (!p) + log_printf ("none"); + else if (*p != '(') + log_printf ("ERROR - not an S-expression"); + else + { + p++; + n = strtoul (p, (char**)&endp, 10); + p = endp; + if (*p!=':') + log_printf ("ERROR - invalid S-expression"); + else + { + for (p++; n; n--, p++) + log_printf ("%02X", *p); + } + } +} + +void +gpgsm_print_time (FILE *fp, time_t t) +{ + if (!t) + fputs (_("none"), fp); + else if ( t == (time_t)(-1) ) + fputs ("[Error - Invalid time]", fp); + else + { + struct tm *tp; + + tp = gmtime (&t); + fprintf (fp, "%04d-%02d-%02d %02d:%02d:%02d Z", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + assert (!tp->tm_isdst); + } +} + +void +gpgsm_dump_time (time_t t) +{ + + if (!t) + log_printf (_("[none]")); + else if ( t == (time_t)(-1) ) + log_printf (_("[error]")); + else + { + struct tm *tp; + + tp = gmtime (&t); + log_printf ("%04d-%02d-%02d %02d:%02d:%02d", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + assert (!tp->tm_isdst); + } +} + + + + +void +gpgsm_dump_string (const char *string) +{ + + if (!string) + log_printf ("[error]"); + else + { + const unsigned char *s; + + for (s=string; *s; s++) + { + if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0)) + break; + } + if (!*s && *string != '[') + log_printf ("%s", string); + else + { + log_printf ( "[ "); + log_printhex (NULL, string, strlen (string)); + log_printf ( " ]"); + } + } +} + + +void +gpgsm_dump_cert (const char *text, KsbaCert cert) +{ + KsbaSexp sexp; + unsigned char *p; + char *dn; + time_t t; + + log_debug ("BEGIN Certificate `%s':\n", text? text:""); + if (cert) + { + sexp = ksba_cert_get_serial (cert); + log_debug (" serial: "); + gpgsm_dump_serial (sexp); + ksba_free (sexp); + log_printf ("\n"); + + t = ksba_cert_get_validity (cert, 0); + log_debug (" notBefore: "); + gpgsm_dump_time (t); + log_printf ("\n"); + t = ksba_cert_get_validity (cert, 1); + log_debug (" notAfter: "); + gpgsm_dump_time (t); + log_printf ("\n"); + + dn = ksba_cert_get_issuer (cert, 0); + log_debug (" issuer: "); + gpgsm_dump_string (dn); + ksba_free (dn); + log_printf ("\n"); + + dn = ksba_cert_get_subject (cert, 0); + log_debug (" subject: "); + gpgsm_dump_string (dn); + ksba_free (dn); + log_printf ("\n"); + + log_debug (" hash algo: %s\n", ksba_cert_get_digest_algo (cert)); + + p = gpgsm_get_fingerprint_string (cert, 0); + log_debug (" SHA1 Fingerprint: %s\n", p); + xfree (p); + } + log_debug ("END Certificate\n"); +} + + + +/* helper for the rfc2253 string parser */ +static const unsigned char * +parse_dn_part (struct dn_array_s *array, const unsigned char *string) +{ + const unsigned char *s, *s1; + size_t n; + unsigned char *p; + + /* parse attributeType */ + for (s = string+1; *s && *s != '='; s++) + ; + if (!*s) + return NULL; /* error */ + n = s - string; + if (!n) + return NULL; /* empty key */ + array->key = p = xtrymalloc (n+1); + if (!array->key) + return NULL; + memcpy (p, string, n); + p[n] = 0; + trim_trailing_spaces (p); + if ( !strcmp (p, "1.2.840.113549.1.9.1") ) + strcpy (p, "EMail"); + string = s + 1; + + if (*string == '#') + { /* hexstring */ + string++; + for (s=string; hexdigitp (s); s++) + s++; + n = s - string; + if (!n || (n & 1)) + return NULL; /* empty or odd number of digits */ + n /= 2; + array->value = p = xtrymalloc (n+1); + if (!p) + return NULL; + for (s1=string; n; s1 += 2, n--) + *p++ = xtoi_2 (s1); + *p = 0; + } + else + { /* regular v3 quoted string */ + for (n=0, s=string; *s; s++) + { + if (*s == '\\') + { /* pair */ + s++; + if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' + || *s == '\\' || *s == '\"' || *s == ' ') + n++; + else if (hexdigitp (s) && hexdigitp (s+1)) + { + s++; + n++; + } + else + return NULL; /* invalid escape sequence */ + } + else if (*s == '\"') + return NULL; /* invalid encoding */ + else if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' ) + break; + else + n++; + } + + array->value = p = xtrymalloc (n+1); + if (!p) + return NULL; + for (s=string; n; s++, n--) + { + if (*s == '\\') + { + s++; + if (hexdigitp (s)) + { + *p++ = xtoi_2 (s); + s++; + } + else + *p++ = *s; + } + else + *p++ = *s; + } + *p = 0; + } + return s; +} + + +/* Parse a DN and return an array-ized one. This is not a validating + parser and it does not support any old-stylish syntax; KSBA is + expected to return only rfc2253 compatible strings. */ +static struct dn_array_s * +parse_dn (const unsigned char *string) +{ + struct dn_array_s *array; + size_t arrayidx, arraysize; + int i; + + arraysize = 7; /* C,ST,L,O,OU,CN,email */ + arrayidx = 0; + array = xtrymalloc ((arraysize+1) * sizeof *array); + if (!array) + return NULL; + while (*string) + { + while (*string == ' ') + string++; + if (!*string) + break; /* ready */ + if (arrayidx >= arraysize) + { + struct dn_array_s *a2; + + arraysize += 5; + a2 = xtryrealloc (array, (arraysize+1) * sizeof *array); + if (!a2) + goto failure; + array = a2; + } + array[arrayidx].key = NULL; + array[arrayidx].value = NULL; + string = parse_dn_part (array+arrayidx, string); + arrayidx++; + if (!string) + goto failure; + while (*string == ' ') + string++; + if (*string && *string != ',' && *string != ';' && *string != '+') + goto failure; /* invalid delimiter */ + if (*string) + string++; + } + array[arrayidx].key = NULL; + array[arrayidx].value = NULL; + return array; + + failure: + for (i=0; i < arrayidx; i++) + { + xfree (array[i].key); + xfree (array[i].value); + } + xfree (array); + return NULL; +} + + +static void +print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) +{ + int any = 0; + + for (; dn->key; dn++) + { + if (!strcmp (dn->key, key) && dn->value && *dn->value) + { + putc ('/', fp); + if (any) + fputs (" + ", fp); + else + fprintf (fp, "%s=", key); + print_sanitized_utf8_string (fp, dn->value, '/'); + any = 1; + } + } +} + +/* Print all parts of a DN in a "standard" sequence. We first print + all the known parts, followed by the uncommon ones */ +static void +print_dn_parts (FILE *fp, struct dn_array_s *dn) +{ + const char *stdpart[] = { + "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL + }; + int i; + + for (i=0; stdpart[i]; i++) + print_dn_part (fp, dn, stdpart[i]); + + /* now print the rest without any specific ordering */ + for (; dn->key; dn++) + { + for (i=0; stdpart[i]; i++) + { + if (!strcmp (dn->key, stdpart[i])) + break; + } + if (!stdpart[i]) + print_dn_part (fp, dn, dn->key); + } +} + + + +void +gpgsm_print_name (FILE *fp, const char *name) +{ + const unsigned char *s; + int i; + + s = name; + if (!s) + { + fputs (_("[Error - No name]"), fp); + } + else if (*s == '<') + { + const unsigned char *s2 = strchr (s+1, '>'); + if (s2) + print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0); + } + else if (*s == '(') + fputs (_("[Error - unknown encoding]"), fp); + else if (!((*s >= '0' && *s < '9') + || (*s >= 'A' && *s <= 'Z') + || (*s >= 'a' && *s <= 'z'))) + fputs (_("[Error - invalid encoding]"), fp); + else + { + struct dn_array_s *dn = parse_dn (s); + if (!dn) + fputs (_("[Error - invalid DN]"), fp); + else + { + print_dn_parts (fp, dn); + for (i=0; dn[i].key; i++) + { + xfree (dn[i].key); + xfree (dn[i].value); + } + xfree (dn); + } + } +} + + + diff --git a/sm/certlist.c b/sm/certlist.c new file mode 100644 index 000000000..eedc99025 --- /dev/null +++ b/sm/certlist.c @@ -0,0 +1,315 @@ +/* certlist.c - build list of certificates + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +/* Return 0 if the cert is usable for encryption. A MODE of 0 checks + for signing a MODE of 1 checks for encryption, a MODE of 2 checks + for verification and a MODE of 3 for decryption (just for + debugging) */ +static int +cert_usage_p (KsbaCert cert, int mode) +{ + KsbaError err; + unsigned int use; + + err = ksba_cert_get_key_usage (cert, &use); + if (err == KSBA_No_Data) + { + if (opt.verbose && mode < 2) + log_info (mode? + _("no key usage specified - accepted for encryption\n"): + _("no key usage specified - accepted for signing\n")); + return 0; + } + if (err) + { + log_error (_("error getting key usage information: %s\n"), + ksba_strerror (err)); + return map_ksba_err (err); + } + + if (mode == 4) + { + if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN))) + return 0; + log_info ( _("certificate should have not been used certification\n")); + return gpg_error (GPG_ERR_WRONG_KEY_USAGE); + } + + if ((use & ((mode&1)? + (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT): + (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) + ) + return 0; + log_info (mode==3? _("certificate should have not been used for encryption\n"): + mode==2? _("certificate should have not been used for signing\n"): + mode==1? _("certificate is not usable for encryption\n"): + _("certificate is not usable for signing\n")); + return gpg_error (GPG_ERR_WRONG_KEY_USAGE); +} + + +/* Return 0 if the cert is usable for signing */ +int +gpgsm_cert_use_sign_p (KsbaCert cert) +{ + return cert_usage_p (cert, 0); +} + + +/* Return 0 if the cert is usable for encryption */ +int +gpgsm_cert_use_encrypt_p (KsbaCert cert) +{ + return cert_usage_p (cert, 1); +} + +int +gpgsm_cert_use_verify_p (KsbaCert cert) +{ + return cert_usage_p (cert, 2); +} + +int +gpgsm_cert_use_decrypt_p (KsbaCert cert) +{ + return cert_usage_p (cert, 3); +} + +int +gpgsm_cert_use_cert_p (KsbaCert cert) +{ + return cert_usage_p (cert, 4); +} + + +static int +same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert) +{ + char *subject2 = ksba_cert_get_subject (cert, 0); + char *issuer2 = ksba_cert_get_subject (cert, 0); + int tmp; + + tmp = (subject && subject2 + && !strcmp (subject, subject2) + && issuer && issuer2 + && !strcmp (issuer, issuer2)); + xfree (subject2); + xfree (issuer2); + return tmp; +} + + + +/* Add a certificate to a list of certificate and make sure that it is + a valid certificate. With SECRET set to true a secret key must be + avaibale for the certificate. */ +int +gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, + CERTLIST *listaddr) +{ + int rc; + KEYDB_SEARCH_DESC desc; + KEYDB_HANDLE kh = NULL; + KsbaCert cert = NULL; + + rc = keydb_classify_name (name, &desc); + if (!rc) + { + kh = keydb_new (0); + if (!kh) + rc = gpg_error (GPG_ERR_ENOMEM); + else + { + int wrong_usage = 0; + char *subject = NULL; + char *issuer = NULL; + + get_next: + rc = keydb_search (kh, &desc, 1); + if (!rc) + rc = keydb_get_cert (kh, &cert); + if (!rc) + { + rc = secret? gpgsm_cert_use_sign_p (cert) + : gpgsm_cert_use_encrypt_p (cert); + if (gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE) + { + /* There might be another certificate with the + correct usage, so we try again */ + if (!wrong_usage) + { /* save the first match */ + wrong_usage = rc; + subject = ksba_cert_get_subject (cert, 0); + issuer = ksba_cert_get_subject (cert, 0); + ksba_cert_release (cert); + cert = NULL; + goto get_next; + } + else if (same_subject_issuer (subject, issuer, cert)) + { + wrong_usage = rc; + ksba_cert_release (cert); + cert = NULL; + goto get_next; + } + else + wrong_usage = rc; + + } + } + /* we want the error code from the first match in this case */ + if (rc && wrong_usage) + rc = wrong_usage; + + if (!rc) + { + next_ambigious: + rc = keydb_search (kh, &desc, 1); + if (rc == -1) + rc = 0; + else if (!rc) + { + KsbaCert cert2 = NULL; + + /* We have to ignore ambigious names as long as + there only fault is a bad key usage */ + if (!keydb_get_cert (kh, &cert2)) + { + int tmp = (same_subject_issuer (subject, issuer, cert2) + && ((gpg_err_code ( + secret? gpgsm_cert_use_sign_p (cert2) + : gpgsm_cert_use_encrypt_p (cert2) + ) + ) == GPG_ERR_WRONG_KEY_USAGE)); + ksba_cert_release (cert2); + if (tmp) + goto next_ambigious; + } + rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + } + } + xfree (subject); + xfree (issuer); + + if (!rc && secret) + { + char *p; + + rc = gpg_error (GPG_ERR_NO_SECKEY); + p = gpgsm_get_keygrip_hexstring (cert); + if (p) + { + if (!gpgsm_agent_havekey (p)) + rc = 0; + xfree (p); + } + } + if (!rc) + rc = gpgsm_validate_chain (ctrl, cert, NULL); + if (!rc) + { + CERTLIST cl = xtrycalloc (1, sizeof *cl); + if (!cl) + rc = OUT_OF_CORE (errno); + else + { + cl->cert = cert; cert = NULL; + cl->next = *listaddr; + *listaddr = cl; + } + } + } + } + + keydb_release (kh); + ksba_cert_release (cert); + return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc; +} + +void +gpgsm_release_certlist (CERTLIST list) +{ + while (list) + { + CERTLIST cl = list->next; + ksba_cert_release (list->cert); + xfree (list); + list = cl; + } +} + + +/* Like gpgsm_add_to_certlist, but look only for one certificate. No + chain validation is done */ +int +gpgsm_find_cert (const char *name, KsbaCert *r_cert) +{ + int rc; + KEYDB_SEARCH_DESC desc; + KEYDB_HANDLE kh = NULL; + + *r_cert = NULL; + rc = keydb_classify_name (name, &desc); + if (!rc) + { + kh = keydb_new (0); + if (!kh) + rc = gpg_error (GPG_ERR_ENOMEM); + else + { + rc = keydb_search (kh, &desc, 1); + if (!rc) + rc = keydb_get_cert (kh, r_cert); + if (!rc) + { + rc = keydb_search (kh, &desc, 1); + if (rc == -1) + rc = 0; + else + { + if (!rc) + rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + ksba_cert_release (*r_cert); + *r_cert = NULL; + } + } + } + } + + keydb_release (kh); + return rc == -1? gpg_error (GPG_ERR_NO_PUBKEY): rc; +} + diff --git a/sm/certreqgen.c b/sm/certreqgen.c new file mode 100644 index 000000000..0dd4fdde9 --- /dev/null +++ b/sm/certreqgen.c @@ -0,0 +1,699 @@ +/* certreqgen.c - Generate a key and a certification request + * 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 + */ + +/* +The format of the native parameter file is follows: + o Text only, line length is limited to about 1000 chars. + o You must use UTF-8 encoding to specify non-ascii characters. + o Empty lines are ignored. + o Leading and trailing spaces are ignored. + o A hash sign as the first non white space character is a comment line. + o Control statements are indicated by a leading percent sign, the + arguments are separated by white space from the keyword. + o Parameters are specified by a keyword, followed by a colon. Arguments + are separated by white space. + o The first parameter must be "Key-Type", control statements + may be placed anywhere. + o Key generation takes place when either the end of the parameter file + is reached, the next "Key-Type" parameter is encountered or at the + controlstatement "%commit" + o Control statements: + %echo <text> + Print <text>. + %dry-run + Suppress actual key generation (useful for syntax checking). + %commit + Perform the key generation. Note that an implicit commit is done + at the next "Key-Type" parameter. + %certfile <filename> + Do not write the certificate to the keyDB but to <filename>. + This must be given before the first + commit to take place, duplicate specification of the same filename + is ignored, the last filename before a commit is used. + The filename is used until a new filename is used (at commit points) + and all keys are written to that file. If a new filename is given, + this file is created (and overwrites an existing one). + Both control statements must be given. + o The order of the parameters does not matter except for "Key-Type" + which must be the first parameter. The parameters are only for the + generated keyblock and parameters from previous key generations are not + used. Some syntactically checks may be performed. + The currently defined parameters are: + Key-Type: <algo> + Starts a new parameter block by giving the type of the + primary key. The algorithm must be capable of signing. + This is a required parameter. For now the only supported + algorithm is "rsa". + Key-Length: <length-in-bits> + Length of the key in bits. Default is 1024. + Key-Usage: <usage-list> + Space or comma delimited list of key usage, allowed values are + "encrypt" and "sign". This is used to generate the KeyUsage extension. + Please make sure that the algorithm is capable of this usage. Default + is to allow encrypt and sign. + Name-DN: subject name + This is the DN name of the subject in rfc2253 format. + Name-Email: <string> + The ist the email address + +Here is an example: +$ cat >foo <<EOF +%echo Generating a standard key +Key-Type: RSA +Key-Length: 1024 +Name-DN: CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE +Name-Email: joe@foo.bar +# Do a commit here, so that we can later print "done" :-) +%commit +%echo done +EOF +*/ + + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + + +enum para_name { + pKEYTYPE, + pKEYLENGTH, + pKEYUSAGE, + pNAMEDN, + pNAMEEMAIL +}; + +struct para_data_s { + struct para_data_s *next; + int lnr; + enum para_name key; + union { + unsigned int usage; + char value[1]; + } u; +}; + +struct reqgen_ctrl_s { + int lnr; + int dryrun; + KsbaWriter writer; +}; + + +static int proc_parameters (struct para_data_s *para, + struct reqgen_ctrl_s *outctrl); +static int create_request (struct para_data_s *para, + KsbaConstSexp public, + struct reqgen_ctrl_s *outctrl); + + + +static void +release_parameter_list (struct para_data_s *r) +{ + struct para_data_s *r2; + + for (; r ; r = r2) + { + r2 = r->next; + xfree(r); + } +} + +static struct para_data_s * +get_parameter (struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r; + + for (r = para; r && r->key != key; r = r->next) + ; + return r; +} + +static const char * +get_parameter_value (struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r = get_parameter (para, key); + return (r && *r->u.value)? r->u.value : NULL; +} + +static int +get_parameter_algo (struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r = get_parameter (para, key); + if (!r) + return -1; + if (digitp (r->u.value)) + return atoi( r->u.value ); + return gcry_pk_map_name (r->u.value); +} + +/* parse the usage parameter. Returns 0 on success. Note that we + only care about sign and encrypt and don't (yet) allow all the + other X.509 usage to be specified; instead we will use a fixed + mapping to the X.509 usage flags */ +static int +parse_parameter_usage (struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r = get_parameter (para, key); + char *p, *pn; + unsigned int use; + + if (!r) + return 0; /* none (this is an optional parameter)*/ + + use = 0; + pn = r->u.value; + while ( (p = strsep (&pn, " \t,")) ) + { + if (!*p) + ; + else if ( !ascii_strcasecmp (p, "sign") ) + use |= GCRY_PK_USAGE_SIGN; + else if ( !ascii_strcasecmp (p, "encrypt") ) + use |= GCRY_PK_USAGE_ENCR; + else + { + log_error ("line %d: invalid usage list\n", r->lnr); + return -1; /* error */ + } + } + r->u.usage = use; + return 0; +} + + +static unsigned int +get_parameter_uint (struct para_data_s *para, enum para_name key) +{ + struct para_data_s *r = get_parameter (para, key); + + if (!r) + return 0; + + return (unsigned int)strtoul (r->u.value, NULL, 10); +} + + + +/* Read the certificate generation parameters from FP and generate + (all) certificate requests. */ +static int +read_parameters (FILE *fp, KsbaWriter writer) +{ + static struct { + const char *name; + enum para_name key; + } keywords[] = { + { "Key-Type", pKEYTYPE}, + { "Key-Length", pKEYLENGTH }, + { "Key-Usage", pKEYUSAGE }, + { "Name-DN", pNAMEDN }, + { "Name-Email", pNAMEEMAIL }, + { NULL, 0 } + }; + char line[1024], *p; + const char *err = NULL; + struct para_data_s *para, *r; + int i, rc = 0, any = 0; + struct reqgen_ctrl_s outctrl; + + memset (&outctrl, 0, sizeof (outctrl)); + outctrl.writer = writer; + + err = NULL; + para = NULL; + while (fgets (line, DIM(line)-1, fp) ) + { + char *keyword, *value; + + outctrl.lnr++; + if (*line && line[strlen(line)-1] != '\n') + { + err = "line too long"; + break; + } + for (p=line; spacep (p); p++) + ; + if (!*p || *p == '#') + continue; + + keyword = p; + if (*keyword == '%') + { + for (; !spacep (p); p++) + ; + if (*p) + *p++ = 0; + for (; spacep (p); p++) + ; + value = p; + trim_trailing_spaces (value); + + if (!ascii_strcasecmp (keyword, "%echo")) + log_info ("%s\n", value); + else if (!ascii_strcasecmp (keyword, "%dry-run")) + outctrl.dryrun = 1; + else if (!ascii_strcasecmp( keyword, "%commit")) + { + rc = proc_parameters (para, &outctrl); + if (rc) + goto leave; + any = 1; + release_parameter_list (para); + para = NULL; + } + else + log_info ("skipping control `%s' (%s)\n", keyword, value); + + continue; + } + + + if (!(p = strchr (p, ':')) || p == keyword) + { + err = "missing colon"; + break; + } + if (*p) + *p++ = 0; + for (; spacep (p); p++) + ; + if (!*p) + { + err = "missing argument"; + break; + } + value = p; + trim_trailing_spaces (value); + + for (i=0; (keywords[i].name + && ascii_strcasecmp (keywords[i].name, keyword)); i++) + ; + if (!keywords[i].name) + { + err = "unknown keyword"; + break; + } + if (keywords[i].key != pKEYTYPE && !para) + { + err = "parameter block does not start with \"Key-Type\""; + break; + } + + if (keywords[i].key == pKEYTYPE && para) + { + rc = proc_parameters (para, &outctrl); + if (rc) + goto leave; + any = 1; + release_parameter_list (para); + para = NULL; + } + else + { + for (r = para; r && r->key != keywords[i].key; r = r->next) + ; + if (r) + { + err = "duplicate keyword"; + break; + } + } + + r = xtrycalloc (1, sizeof *r + strlen( value )); + if (!r) + { + err = "out of core"; + break; + } + r->lnr = outctrl.lnr; + r->key = keywords[i].key; + strcpy (r->u.value, value); + r->next = para; + para = r; + } + + if (err) + { + log_error ("line %d: %s\n", outctrl.lnr, err); + rc = gpg_error (GPG_ERR_GENERAL); + } + else if (ferror(fp)) + { + log_error ("line %d: read error: %s\n", outctrl.lnr, strerror(errno) ); + rc = gpg_error (GPG_ERR_GENERAL); + } + else if (para) + { + rc = proc_parameters (para, &outctrl); + if (rc) + goto leave; + any = 1; + } + + if (!rc && !any) + rc = gpg_error (GPG_ERR_NO_DATA); + + leave: + release_parameter_list (para); + return rc; +} + +/* check whether there are invalid characters in the email address S */ +static int +has_invalid_email_chars (const char *s) +{ + int at_seen=0; + static char valid_chars[] = "01234567890_-." + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + for (; *s; s++) + { + if (*s & 0x80) + return 1; + if (*s == '@') + at_seen++; + else if (!at_seen && !( !!strchr (valid_chars, *s) || *s == '+')) + return 1; + else if (at_seen && !strchr (valid_chars, *s)) + return 1; + } + return at_seen != 1; +} + + +/* Check that all required parameters are given and perform the action */ +static int +proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) +{ + struct para_data_s *r; + const char *s; + int i; + unsigned int nbits; + char numbuf[20]; + unsigned char keyparms[100]; + int rc; + KsbaSexp public; + + /* check that we have all required parameters */ + assert (get_parameter (para, pKEYTYPE)); + + /* We can only use RSA for now. There is a with pkcs-10 on how to + use ElGamal becuase it is expected that a PK algorithm can always + be used for signing. */ + i = get_parameter_algo (para, pKEYTYPE); + if (i < 1 || i != GCRY_PK_RSA ) + { + r = get_parameter (para, pKEYTYPE); + log_error ("line %d: invalid algorithm\n", r->lnr); + return gpg_error (GPG_ERR_INV_PARAMETER); + } + + /* check the keylength */ + if (!get_parameter (para, pKEYLENGTH)) + nbits = 1024; + else + nbits = get_parameter_uint (para, pKEYLENGTH); + if (nbits < 512 || nbits > 4096) + { + r = get_parameter (para, pKEYTYPE); + log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n", + r->lnr, nbits); + return gpg_error (GPG_ERR_INV_PARAMETER); + } + + /* check the usage */ + if (parse_parameter_usage (para, pKEYUSAGE)) + return gpg_error (GPG_ERR_INV_PARAMETER); + + /* check that there is a subject name and that this DN fits our + requirements */ + if (!(s=get_parameter_value (para, pNAMEDN))) + { + r = get_parameter (para, pKEYTYPE); + log_error ("line %d: no subject name given\n", r->lnr); + return gpg_error (GPG_ERR_INV_PARAMETER); + } + /* fixme check s */ + + /* check that the optional email address is okay */ + if ((s=get_parameter_value (para, pNAMEEMAIL))) + { + if (has_invalid_email_chars (s) + || *s == '@' + || s[strlen(s)-1] == '@' + || s[strlen(s)-1] == '.' + || strstr(s, "..")) + { + r = get_parameter (para, pKEYTYPE); + log_error ("line %d: not a valid email address\n", r->lnr); + return gpg_error (GPG_ERR_INV_PARAMETER); + } + } + + sprintf (numbuf, "%u", nbits); + snprintf (keyparms, DIM (keyparms)-1, + "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf); + rc = gpgsm_agent_genkey (keyparms, &public); + if (rc) + { + r = get_parameter (para, pKEYTYPE); + log_error ("line %d: key generation failed: %s\n", + r->lnr, gpg_strerror (rc)); + return rc; + } + + rc = create_request (para, public, outctrl); + xfree (public); + + return rc; +} + + +/* Parameters are checked, the key pair has been created. Now + generate the request and write it out */ +static int +create_request (struct para_data_s *para, KsbaConstSexp public, + struct reqgen_ctrl_s *outctrl) +{ + KsbaCertreq cr; + KsbaError err; + gcry_md_hd_t md; + KsbaStopReason stopreason; + int rc = 0; + const char *s; + + cr = ksba_certreq_new (); + if (!cr) + return gpg_error (GPG_ERR_ENOMEM); + + rc = gcry_md_open (&md, GCRY_MD_SHA1, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + goto leave; + } + if (DBG_HASHING) + gcry_md_start_debug (md, "cr.cri"); + + ksba_certreq_set_hash_function (cr, HASH_FNC, md); + ksba_certreq_set_writer (cr, outctrl->writer); + + err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN)); + if (err) + { + log_error ("error setting the subject's name: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + s = get_parameter_value (para, pNAMEEMAIL); + if (s) + { + char *buf; + + buf = xtrymalloc (strlen (s) + 3); + if (!buf) + { + rc = OUT_OF_CORE (errno); + goto leave; + } + *buf = '<'; + strcpy (buf+1, s); + strcat (buf+1, ">"); + err = ksba_certreq_add_subject (cr, buf); + xfree (buf); + if (err) + { + log_error ("error setting the subject's alternate name: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + + + err = ksba_certreq_set_public_key (cr, public); + if (err) + { + log_error ("error setting the public key: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + do + { + err = ksba_certreq_build (cr, &stopreason); + if (err) + { + log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + if (stopreason == KSBA_SR_NEED_SIG) + { + gcry_sexp_t s_pkey; + size_t n; + unsigned char grip[20], hexgrip[41]; + char *sigval; + size_t siglen; + + n = gcry_sexp_canon_len (public, 0, NULL, NULL); + if (!n) + { + log_error ("libksba did not return a proper S-Exp\n"); + err = gpg_error (GPG_ERR_BUG); + goto leave; + } + rc = gcry_sexp_sscan (&s_pkey, NULL, public, n); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + goto leave; + } + if ( !gcry_pk_get_keygrip (s_pkey, grip) ) + { + rc = gpg_error (GPG_ERR_GENERAL); + log_error ("can't figure out the keygrip\n"); + gcry_sexp_release (s_pkey); + goto leave; + } + gcry_sexp_release (s_pkey); + for (n=0; n < 20; n++) + sprintf (hexgrip+n*2, "%02X", grip[n]); + + rc = gpgsm_agent_pksign (hexgrip, + gcry_md_read(md, GCRY_MD_SHA1), + gcry_md_get_algo_dlen (GCRY_MD_SHA1), + GCRY_MD_SHA1, + &sigval, &siglen); + if (rc) + { + log_error ("signing failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + err = ksba_certreq_set_sig_val (cr, sigval); + xfree (sigval); + if (err) + { + log_error ("failed to store the sig_val: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + } + while (stopreason != KSBA_SR_READY); + + + leave: + gcry_md_close (md); + ksba_certreq_release (cr); + return rc; +} + + + +/* Create a new key by reading the parameters from in_fd. Multiple + keys may be created */ +int +gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp) +{ + int rc; + FILE *in_fp; + Base64Context b64writer = NULL; + KsbaWriter writer; + + in_fp = fdopen (dup (in_fd), "rb"); + if (!in_fp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("fdopen() failed: %s\n", strerror (errno)); + return tmperr; + } + + ctrl->pem_name = "NEW CERTIFICATE REQUEST"; + rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + + rc = read_parameters (in_fp, writer); + if (rc) + { + log_error ("error creating certificate request: %s\n", + gpg_strerror (rc)); + goto leave; + } + + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + gpgsm_status (ctrl, STATUS_KEY_CREATED, "P"); + log_info ("certificate request created\n"); + + leave: + gpgsm_destroy_writer (b64writer); + fclose (in_fp); + return rc; +} + diff --git a/sm/decrypt.c b/sm/decrypt.c new file mode 100644 index 000000000..17483aa49 --- /dev/null +++ b/sm/decrypt.c @@ -0,0 +1,506 @@ +/* decrypt.c - Decrypt a message + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +struct decrypt_filter_parm_s { + int algo; + int mode; + int blklen; + gcry_cipher_hd_t hd; + char iv[16]; + size_t ivlen; + int any_data; /* dod we push anything through the filter at all? */ + unsigned char lastblock[16]; /* to strip the padding we have to + keep this one */ + char helpblock[16]; /* needed because there is no block buffering in + libgcrypt (yet) */ + int helpblocklen; +}; + + + +/* decrypt the session key and fill in the parm structure. The + algo and the IV is expected to be already in PARM. */ +static int +prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val, + struct decrypt_filter_parm_s *parm) +{ + char *seskey = NULL; + size_t n, seskeylen; + int rc; + + rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val, + &seskey, &seskeylen); + if (rc) + { + log_error ("error decrypting session key: %s\n", gpg_strerror (rc)); + goto leave; + } + + if (DBG_CRYPTO) + log_printhex ("pkcs1 encoded session key:", seskey, seskeylen); + + n=0; + if (seskeylen == 24) + { + /* Smells like a 3-des key. This might happen because a SC has + already done the unpacking. fixme! */ + } + else + { + if (n + 7 > seskeylen ) + { + rc = gpg_error (GPG_ERR_INV_SESSION_KEY); + goto leave; + } + + /* FIXME: Actually the leading zero is required but due to the way + we encode the output in libgcrypt as an MPI we are not able to + encode that leading zero. However, when using a Smartcard we are + doing it the rightway and therefore we have to skip the zero. This + should be fixed in gpg-agent of course. */ + if (!seskey[n]) + n++; + + if (seskey[n] != 2 ) /* wrong block type version */ + { + rc = gpg_error (GPG_ERR_INV_SESSION_KEY); + goto leave; + } + + for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */ + ; + n++; /* and the zero byte */ + if (n >= seskeylen ) + { + rc = gpg_error (GPG_ERR_INV_SESSION_KEY); + goto leave; + } + } + + if (DBG_CRYPTO) + log_printhex ("session key:", seskey+n, seskeylen-n); + + rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0); + if (rc) + { + log_error ("error creating decryptor: %s\n", gpg_strerror (rc)); + goto leave; + } + + rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n); + if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY) + { + log_info (_("WARNING: message was encrypted with " + "a weak key in the symmetric cipher.\n")); + rc = 0; + } + if (rc) + { + log_error("key setup failed: %s\n", gpg_strerror(rc) ); + goto leave; + } + + gcry_cipher_setiv (parm->hd, parm->iv, parm->ivlen); + + leave: + xfree (seskey); + return rc; +} + + +/* This function is called by the KSBA writer just before the actual + write is done. The function must take INLEN bytes from INBUF, + decrypt it and store it inoutbuf which has a maximum size of + maxoutlen. The valid bytes in outbuf should be return in outlen. + Due to different buffer sizes or different length of input and + output, it may happen that fewer bytes are process or fewer bytes + are written. */ +static KsbaError +decrypt_filter (void *arg, + const void *inbuf, size_t inlen, size_t *inused, + void *outbuf, size_t maxoutlen, size_t *outlen) +{ + struct decrypt_filter_parm_s *parm = arg; + int blklen = parm->blklen; + size_t orig_inlen = inlen; + + /* fixme: Should we issue an error when we have not seen one full block? */ + if (!inlen) + return KSBA_Bug; + + if (maxoutlen < 2*parm->blklen) + return KSBA_Bug; + /* make some space becuase we will later need an extra block at the end */ + maxoutlen -= blklen; + + if (parm->helpblocklen) + { + int i, j; + + for (i=parm->helpblocklen,j=0; i < blklen && j < inlen; i++, j++) + parm->helpblock[i] = ((const char*)inbuf)[j]; + inlen -= j; + if (blklen > maxoutlen) + return KSBA_Bug; + if (i < blklen) + { + parm->helpblocklen = i; + *outlen = 0; + } + else + { + parm->helpblocklen = 0; + if (parm->any_data) + { + memcpy (outbuf, parm->lastblock, blklen); + *outlen =blklen; + } + else + *outlen = 0; + gcry_cipher_decrypt (parm->hd, parm->lastblock, blklen, + parm->helpblock, blklen); + parm->any_data = 1; + } + *inused = orig_inlen - inlen; + return 0; + } + + + if (inlen > maxoutlen) + inlen = maxoutlen; + if (inlen % blklen) + { /* store the remainder away */ + parm->helpblocklen = inlen%blklen; + inlen = inlen/blklen*blklen; + memcpy (parm->helpblock, (const char*)inbuf+inlen, parm->helpblocklen); + } + + *inused = inlen + parm->helpblocklen; + if (inlen) + { + assert (inlen >= blklen); + if (parm->any_data) + { + gcry_cipher_decrypt (parm->hd, (char*)outbuf+blklen, inlen, + inbuf, inlen); + memcpy (outbuf, parm->lastblock, blklen); + memcpy (parm->lastblock,(char*)outbuf+inlen, blklen); + *outlen = inlen; + } + else + { + gcry_cipher_decrypt (parm->hd, outbuf, inlen, inbuf, inlen); + memcpy (parm->lastblock, (char*)outbuf+inlen-blklen, blklen); + *outlen = inlen - blklen; + parm->any_data = 1; + } + } + else + *outlen = 0; + return 0; +} + + + +/* Perform a decrypt operation. */ +int +gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) +{ + int rc; + KsbaError err; + Base64Context b64reader = NULL; + Base64Context b64writer = NULL; + KsbaReader reader; + KsbaWriter writer; + KsbaCMS cms = NULL; + KsbaStopReason stopreason; + KEYDB_HANDLE kh; + int recp; + FILE *in_fp = NULL; + struct decrypt_filter_parm_s dfparm; + + memset (&dfparm, 0, sizeof dfparm); + + kh = keydb_new (0); + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + + in_fp = fdopen ( dup (in_fd), "rb"); + if (!in_fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("fdopen() failed: %s\n", strerror (errno)); + goto leave; + } + + rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader); + if (rc) + { + log_error ("can't create reader: %s\n", gpg_strerror (rc)); + goto leave; + } + + rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + + cms = ksba_cms_new (); + if (!cms) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + err = ksba_cms_set_reader_writer (cms, reader, writer); + if (err) + { + log_debug ("ksba_cms_set_reader_writer failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + /* parser loop */ + do + { + err = ksba_cms_parse (cms, &stopreason); + if (err) + { + log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + if (stopreason == KSBA_SR_BEGIN_DATA + || stopreason == KSBA_SR_DETACHED_DATA) + { + int algo, mode; + const char *algoid; + int any_key = 0; + + algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/); + algo = gcry_cipher_map_name (algoid); + mode = gcry_cipher_mode_from_oid (algoid); + if (!algo || !mode) + { + rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?"); + if (algoid && !strcmp (algoid, "1.2.840.113549.3.2")) + log_info (_("(this is the RC2 algorithm)\n")); + else if (!algoid) + log_info (_("(this does not seem to be an encrypted" + " message)\n")); + { + char numbuf[50]; + sprintf (numbuf, "%d", rc); + gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm", + numbuf, algoid?algoid:"?", NULL); + } + + goto leave; + } + dfparm.algo = algo; + dfparm.mode = mode; + dfparm.blklen = gcry_cipher_get_algo_blklen (algo); + if (dfparm.blklen > sizeof (dfparm.helpblock)) + return gpg_error (GPG_ERR_BUG); + + rc = ksba_cms_get_content_enc_iv (cms, + dfparm.iv, + sizeof (dfparm.iv), + &dfparm.ivlen); + if (rc) + { + log_error ("error getting IV: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + for (recp=0; !any_key; recp++) + { + char *issuer; + KsbaSexp serial; + KsbaSexp enc_val; + char *hexkeygrip = NULL; + + err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); + if (err == -1 && recp) + break; /* no more recipients */ + if (err) + log_error ("recp %d - error getting info: %s\n", + recp, ksba_strerror (err)); + else + { + KsbaCert cert = NULL; + + log_debug ("recp %d - issuer: `%s'\n", + recp, issuer? issuer:"[NONE]"); + log_debug ("recp %d - serial: ", recp); + gpgsm_dump_serial (serial); + log_printf ("\n"); + + keydb_search_reset (kh); + rc = keydb_search_issuer_sn (kh, issuer, serial); + if (rc) + { + log_error ("failed to find the certificate: %s\n", + gpg_strerror(rc)); + goto oops; + } + + rc = keydb_get_cert (kh, &cert); + if (rc) + { + log_error ("failed to get cert: %s\n", gpg_strerror (rc)); + goto oops; + } + /* Just in case there is a problem with the own + certificate we print this message - should never + happen of course */ + rc = gpgsm_cert_use_decrypt_p (cert); + if (rc) + { + char numbuf[50]; + sprintf (numbuf, "%d", rc); + gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage", + numbuf, NULL); + rc = 0; + } + + hexkeygrip = gpgsm_get_keygrip_hexstring (cert); + + oops: + xfree (issuer); + xfree (serial); + ksba_cert_release (cert); + } + + if (!hexkeygrip) + ; + else if (!(enc_val = ksba_cms_get_enc_val (cms, recp))) + log_error ("recp %d - error getting encrypted session key\n", + recp); + else + { + rc = prepare_decryption (hexkeygrip, enc_val, &dfparm); + xfree (enc_val); + if (rc) + { + log_debug ("decrypting session key failed: %s\n", + gpg_strerror (rc)); + } + else + { /* setup the bulk decrypter */ + any_key = 1; + ksba_writer_set_filter (writer, + decrypt_filter, + &dfparm); + } + } + } + if (!any_key) + { + rc = gpg_error (GPG_ERR_NO_SECKEY); + goto leave; + } + } + else if (stopreason == KSBA_SR_END_DATA) + { + ksba_writer_set_filter (writer, NULL, NULL); + if (dfparm.any_data) + { /* write the last block with padding removed */ + int i, npadding = dfparm.lastblock[dfparm.blklen-1]; + if (!npadding || npadding > dfparm.blklen) + { + log_error ("invalid padding with value %d\n", npadding); + rc = gpg_error (GPG_ERR_INV_DATA); + goto leave; + } + rc = ksba_writer_write (writer, + dfparm.lastblock, + dfparm.blklen - npadding); + if (rc) + { + rc = map_ksba_err (rc); + goto leave; + } + for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++) + { + if (dfparm.lastblock[i] != npadding) + { + log_error ("inconsistent padding\n"); + rc = gpg_error (GPG_ERR_INV_DATA); + goto leave; + } + } + } + } + + } + while (stopreason != KSBA_SR_READY); + + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL); + + + leave: + if (rc) + gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); + ksba_cms_release (cms); + gpgsm_destroy_reader (b64reader); + gpgsm_destroy_writer (b64writer); + keydb_release (kh); + if (in_fp) + fclose (in_fp); + if (dfparm.hd) + gcry_cipher_close (dfparm.hd); + return rc; +} + + diff --git a/sm/delete.c b/sm/delete.c new file mode 100644 index 000000000..53eff864c --- /dev/null +++ b/sm/delete.c @@ -0,0 +1,165 @@ +/* delete.c + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + + +/* Delete a certificate or an secret key from a key database. */ +static int +delete_one (CTRL ctrl, const char *username) +{ + int rc = 0; + KEYDB_SEARCH_DESC desc; + KEYDB_HANDLE kh = NULL; + KsbaCert cert = NULL; + int duplicates = 0; + + rc = keydb_classify_name (username, &desc); + if (rc) + { + log_error (_("certificate `%s' not found: %s\n"), + username, gpg_strerror (rc)); + gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "1", NULL); + goto leave; + } + + kh = keydb_new (0); + if (!kh) + { + log_error ("keydb_new failed\n"); + goto leave; + } + + + rc = keydb_search (kh, &desc, 1); + if (!rc) + rc = keydb_get_cert (kh, &cert); + if (!rc) + { + char fpr[20]; + + gpgsm_get_fingerprint (cert, 0, fpr, NULL); + + next_ambigious: + rc = keydb_search (kh, &desc, 1); + if (rc == -1) + rc = 0; + else if (!rc) + { + KsbaCert cert2 = NULL; + char fpr2[20]; + + /* We ignore all duplicated certificates which might have + been inserted due to program bugs. */ + if (!keydb_get_cert (kh, &cert2)) + { + gpgsm_get_fingerprint (cert2, 0, fpr2, NULL); + ksba_cert_release (cert2); + if (!memcmp (fpr, fpr2, 20)) + { + duplicates++; + goto next_ambigious; + } + } + rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + } + } + if (rc) + { + if (rc == -1) + rc = gpg_error (GPG_ERR_NO_PUBKEY); + log_error (_("certificate `%s' not found: %s\n"), + username, gpg_strerror (rc)); + gpgsm_status2 (ctrl, STATUS_DELETE_PROBLEM, "3", NULL); + goto leave; + } + + /* we need to search again to get back to the right position. */ + do + { + keydb_search_reset (kh); + rc = keydb_search (kh, &desc, 1); + if (rc) + { + log_error ("problem re-searching certificate: %s\n", + gpg_strerror (rc)); + goto leave; + } + + rc = keydb_delete (kh); + if (rc) + goto leave; + if (opt.verbose) + { + if (duplicates) + log_info (_("duplicated certificate `%s' deleted\n"), username); + else + log_info (_("certificate `%s' deleted\n"), username); + } + } + while (duplicates--); + + leave: + keydb_release (kh); + ksba_cert_release (cert); + return rc; +} + + + +/* Delete the certificates specified by NAMES. */ +int +gpgsm_delete (CTRL ctrl, STRLIST names) +{ + int rc; + + if (!names) + { + log_error ("nothing to delete\n"); + return gpg_error (GPG_ERR_NO_DATA); + } + + for (; names; names=names->next ) + { + rc = delete_one (ctrl, names->d); + if (rc) + { + log_error (_("deleting certificate \"%s\" failed: %s\n"), + names->d, gpg_strerror (rc) ); + return rc; + } + } + + return 0; +} diff --git a/sm/encrypt.c b/sm/encrypt.c new file mode 100644 index 000000000..725a81b70 --- /dev/null +++ b/sm/encrypt.c @@ -0,0 +1,550 @@ +/* encrypt.c - Encrypt a message + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + + +struct dek_s { + const char *algoid; + int algo; + gcry_cipher_hd_t chd; + char key[32]; + int keylen; + char iv[32]; + int ivlen; +}; +typedef struct dek_s *DEK; + +struct encrypt_cb_parm_s { + FILE *fp; + DEK dek; + int eof_seen; + int ready; + int readerror; + int bufsize; + unsigned char *buffer; + int buflen; +}; + + + + + +/* initialize the data encryptionkey (session key) */ +static int +init_dek (DEK dek) +{ + int rc=0, mode, i; + + dek->algo = gcry_cipher_map_name (dek->algoid); + mode = gcry_cipher_mode_from_oid (dek->algoid); + if (!dek->algo || !mode) + { + log_error ("unsupported algorithm `%s'\n", dek->algoid); + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + } + + dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); + if (!dek->keylen || dek->keylen > sizeof (dek->key)) + return gpg_error (GPG_ERR_BUG); + + dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo); + if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) + return gpg_error (GPG_ERR_BUG); + + if (dek->keylen < 100/8) + { /* make sure we don't use weak keys */ + log_error ("key length of `%s' too small\n", dek->algoid); + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + } + + rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE); + if (rc) + { + log_error ("failed to create cipher context: %s\n", gpg_strerror (rc)); + return rc; + } + + for (i=0; i < 8; i++) + { + gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); + rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen); + if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) + break; + log_info(_("weak key created - retrying\n") ); + } + if (rc) + { + log_error ("failed to set the key: %s\n", gpg_strerror (rc)); + gcry_cipher_close (dek->chd); + dek->chd = NULL; + return rc; + } + + gcry_randomize (dek->iv, dek->ivlen, GCRY_STRONG_RANDOM); + rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); + if (rc) + { + log_error ("failed to set the IV: %s\n", gpg_strerror (rc)); + gcry_cipher_close (dek->chd); + dek->chd = NULL; + return rc; + } + + return 0; +} + + +/* Encode the session key. NBITS is the number of bits which should be + used for packing the session key. returns: An mpi with the session + key (caller must free) */ +static gcry_mpi_t +encode_session_key (DEK dek, unsigned int nbits) +{ + int nframe = (nbits+7) / 8; + byte *p; + byte *frame; + int i,n; + gcry_mpi_t a; + + if (dek->keylen + 7 > nframe || !nframe) + log_bug ("can't encode a %d bit key in a %d bits frame\n", + dek->keylen*8, nbits ); + + /* We encode the session key in this way: + * + * 0 2 RND(n bytes) 0 KEY(k bytes) + * + * (But how can we store the leading 0 - the external representaion + * of MPIs doesn't allow leading zeroes =:-) + * + * RND are non-zero random bytes. + * KEY is the encryption key (session key) + */ + + frame = gcry_xmalloc_secure (nframe); + n = 0; + frame[n++] = 0; + frame[n++] = 2; + i = nframe - 3 - dek->keylen; + assert (i > 0); + p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); + /* replace zero bytes by new values */ + for (;;) + { + int j, k; + byte *pp; + + /* count the zero bytes */ + for(j=k=0; j < i; j++ ) + { + if( !p[j] ) + k++; + } + if( !k ) + break; /* okay: no zero bytes */ + + k += k/128; /* better get some more */ + pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); + for (j=0; j < i && k; j++) + { + if( !p[j] ) + p[j] = pp[--k]; + } + xfree (pp); + } + memcpy (frame+n, p, i); + xfree (p); + + n += i; + frame[n++] = 0; + memcpy (frame+n, dek->key, dek->keylen); + n += dek->keylen; + assert (n == nframe); + if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, n, &nframe) ) + BUG (); + gcry_free(frame); + + return a; +} + + + +/* encrypt the DEK under the key contained in CERT and return it as a + canonical S-Exp in encval */ +static int +encrypt_dek (const DEK dek, KsbaCert cert, char **encval) +{ + gcry_sexp_t s_ciph, s_data, s_pkey; + int rc; + KsbaSexp buf; + size_t len; + + *encval = NULL; + + /* get the key from the cert */ + buf = ksba_cert_get_public_key (cert); + if (!buf) + { + log_error ("no public key for recipient\n"); + return gpg_error (GPG_ERR_NO_PUBKEY); + } + len = gcry_sexp_canon_len (buf, 0, NULL, NULL); + if (!len) + { + log_error ("libksba did not return a proper S-Exp\n"); + return gpg_error (GPG_ERR_BUG); + } + rc = gcry_sexp_sscan (&s_pkey, NULL, buf, len); + xfree (buf); buf = NULL; + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + return rc; + } + + /* put the encoded cleartext into a simple list */ + { + /* fixme: actually the pkcs-1 encoding should go into libgcrypt */ + gcry_mpi_t data = encode_session_key (dek, gcry_pk_get_nbits (s_pkey)); + if (!data) + { + gcry_mpi_release (data); + return gpg_error (GPG_ERR_GENERAL); + } + if (gcry_sexp_build (&s_data, NULL, "%m", data)) + BUG (); + gcry_mpi_release (data); + } + + /* pass it to libgcrypt */ + rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); + gcry_sexp_release (s_data); + gcry_sexp_release (s_pkey); + + /* reformat it */ + len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xtrymalloc (len); + if (!buf) + { + gpg_error_t tmperr = OUT_OF_CORE (errno); + gcry_sexp_release (s_ciph); + return tmperr; + } + len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + + *encval = buf; + return 0; +} + + + +/* do the actual encryption */ +static int +encrypt_cb (void *cb_value, char *buffer, size_t count, size_t *nread) +{ + struct encrypt_cb_parm_s *parm = cb_value; + int blklen = parm->dek->ivlen; + unsigned char *p; + size_t n; + + *nread = 0; + if (!buffer) + return -1; /* not supported */ + + if (parm->ready) + return -1; + + if (count < blklen) + BUG (); + + if (!parm->eof_seen) + { /* fillup the buffer */ + p = parm->buffer; + for (n=parm->buflen; n < parm->bufsize; n++) + { + int c = getc (parm->fp); + if (c == EOF) + { + if (ferror (parm->fp)) + { + parm->readerror = errno; + return -1; + } + parm->eof_seen = 1; + break; + } + p[n] = c; + } + parm->buflen = n; + } + + n = parm->buflen < count? parm->buflen : count; + n = n/blklen * blklen; + if (n) + { /* encrypt the stuff */ + gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n); + *nread = n; + /* Who cares about cycles, take the easy way and shift the buffer */ + parm->buflen -= n; + memmove (parm->buffer, parm->buffer+n, parm->buflen); + } + else if (parm->eof_seen) + { /* no complete block but eof: add padding */ + /* fixme: we should try to do this also in the above code path */ + int i, npad = blklen - (parm->buflen % blklen); + p = parm->buffer; + for (n=parm->buflen, i=0; n < parm->bufsize && i < npad; n++, i++) + p[n] = npad; + gcry_cipher_encrypt (parm->dek->chd, buffer, n, parm->buffer, n); + *nread = n; + parm->ready = 1; + } + + return 0; +} + + + + +/* Perform an encrypt operation. + + Encrypt the data received on DATA-FD and write it to OUT_FP. The + recipients are take from the certificate given in recplist; if this + is NULL it will be encrypted for a default recipient */ +int +gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) +{ + int rc = 0; + Base64Context b64writer = NULL; + KsbaError err; + KsbaWriter writer; + KsbaReader reader = NULL; + KsbaCMS cms = NULL; + KsbaStopReason stopreason; + KEYDB_HANDLE kh = NULL; + struct encrypt_cb_parm_s encparm; + DEK dek = NULL; + int recpno; + FILE *data_fp = NULL; + CERTLIST cl; + + memset (&encparm, 0, sizeof encparm); + + if (!recplist) + { + log_error(_("no valid recipients given\n")); + gpgsm_status (ctrl, STATUS_NO_RECP, "0"); + rc = gpg_error (GPG_ERR_NO_PUBKEY); + goto leave; + } + + kh = keydb_new (0); + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + data_fp = fdopen ( dup (data_fd), "rb"); + if (!data_fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("fdopen() failed: %s\n", strerror (errno)); + goto leave; + } + + reader = ksba_reader_new (); + if (!reader) + rc = KSBA_Out_Of_Core; + if (!rc) + rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm); + if (rc) + { + rc = map_ksba_err (rc); + goto leave; + } + encparm.fp = data_fp; + + ctrl->pem_name = "ENCRYPTED MESSAGE"; + rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + + cms = ksba_cms_new (); + if (!cms) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + err = ksba_cms_set_reader_writer (cms, reader, writer); + if (err) + { + log_debug ("ksba_cms_set_reader_writer failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + /* We are going to create enveloped data with uninterpreted data as + inner content */ + err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA); + if (!err) + err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA); + if (err) + { + log_debug ("ksba_cms_set_content_type failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + /* create a session key */ + dek = xtrycalloc (1, sizeof *dek); /* hmmm: should we put it into secmem?*/ + if (!dek) + rc = OUT_OF_CORE (errno); + else + { + dek->algoid = opt.def_cipher_algoid; + rc = init_dek (dek); + } + if (rc) + { + log_error ("failed to create the session key: %s\n", + gpg_strerror (rc)); + goto leave; + } + + err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen); + if (err) + { + log_error ("ksba_cms_set_content_enc_algo failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + encparm.dek = dek; + /* Use a ~8k (AES) or ~4k (3DES) buffer */ + encparm.bufsize = 500 * dek->ivlen; + encparm.buffer = xtrymalloc (encparm.bufsize); + if (!encparm.buffer) + { + rc = OUT_OF_CORE (errno); + goto leave; + } + + /* gather certificates of recipients, encrypt the session key for + each and store them in the CMS object */ + for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next) + { + char *encval; + + rc = encrypt_dek (dek, cl->cert, &encval); + if (rc) + { + log_error ("encryption failed for recipient no. %d: %s\n", + recpno, gpg_strerror (rc)); + goto leave; + } + + err = ksba_cms_add_recipient (cms, cl->cert); + if (err) + { + log_error ("ksba_cms_add_recipient failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + xfree (encval); + goto leave; + } + + err = ksba_cms_set_enc_val (cms, recpno, encval); + xfree (encval); + if (err) + { + log_error ("ksba_cms_set_enc_val failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + + /* main control loop for encryption */ + recpno = 0; + do + { + err = ksba_cms_build (cms, &stopreason); + if (err) + { + log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + while (stopreason != KSBA_SR_READY); + + if (encparm.readerror) + { + log_error ("error reading input: %s\n", strerror (encparm.readerror)); + rc = gpg_error (gpg_err_code_from_errno (encparm.readerror)); + goto leave; + } + + + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + log_info ("encrypted data created\n"); + + leave: + ksba_cms_release (cms); + gpgsm_destroy_writer (b64writer); + ksba_reader_release (reader); + keydb_release (kh); + xfree (dek); + if (data_fp) + fclose (data_fp); + xfree (encparm.buffer); + return rc; +} diff --git a/sm/export.c b/sm/export.c new file mode 100644 index 000000000..93a55debc --- /dev/null +++ b/sm/export.c @@ -0,0 +1,249 @@ +/* export.c + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" + +static void print_short_info (KsbaCert cert, FILE *fp); + + + +/* Export all certificates or just those given in NAMES. */ +void +gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) +{ + KEYDB_HANDLE hd; + KEYDB_SEARCH_DESC *desc = NULL; + int ndesc; + Base64Context b64writer = NULL; + KsbaWriter writer; + STRLIST sl; + KsbaCert cert = NULL; + int rc=0; + int count = 0; + int i; + + hd = keydb_new (0); + if (!hd) + { + log_error ("keydb_new failed\n"); + goto leave; + } + + if (!names) + ndesc = 1; + else + { + for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) + ; + } + + desc = xtrycalloc (ndesc, sizeof *desc); + if (!ndesc) + { + log_error ("allocating memory for export failed: %s\n", + gpg_strerror (OUT_OF_CORE (errno))); + goto leave; + } + + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + else + { + for (ndesc=0, sl=names; sl; sl = sl->next) + { + rc = keydb_classify_name (sl->d, desc+ndesc); + if (rc) + { + log_error ("key `%s' not found: %s\n", + sl->d, gpg_strerror (rc)); + rc = 0; + } + else + ndesc++; + } + } + + /* If all specifications are done by fingerprint, we switch to + ephemeral mode so that _all_ currently available and matching + certificates are exported. + + fixme: we should in this case keep a list of certificates to + avoid accidential export of duplicate certificates. */ + if (names && ndesc) + { + for (i=0; (i < ndesc + && (desc[i].mode == KEYDB_SEARCH_MODE_FPR + || desc[i].mode == KEYDB_SEARCH_MODE_FPR20 + || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++) + ; + if (i == ndesc) + keydb_set_ephemeral (hd, 1); + } + + while (!(rc = keydb_search (hd, desc, ndesc))) + { + const unsigned char *image; + size_t imagelen; + + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + + rc = keydb_get_cert (hd, &cert); + if (rc) + { + log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + image = ksba_cert_get_image (cert, &imagelen); + if (!image) + { + log_error ("ksba_cert_get_image failed\n"); + goto leave; + } + + if (ctrl->create_pem) + { + if (count) + putc ('\n', fp); + print_short_info (cert, fp); + putc ('\n', fp); + } + count++; + + if (!b64writer) + { + ctrl->pem_name = "CERTIFICATE"; + rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + } + + rc = ksba_writer_write (writer, image, imagelen); + if (rc) + { + log_error ("write error: %s\n", ksba_strerror (rc)); + goto leave; + } + + if (ctrl->create_pem) + { + /* We want one certificate per PEM block */ + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + gpgsm_destroy_writer (b64writer); + b64writer = NULL; + } + + ksba_cert_release (cert); + cert = NULL; + } + if (rc && rc != -1) + log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); + else if (b64writer) + { + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + } + + leave: + gpgsm_destroy_writer (b64writer); + ksba_cert_release (cert); + xfree (desc); + keydb_release (hd); +} + + +/* Print some info about the certifciate CERT to FP */ +static void +print_short_info (KsbaCert cert, FILE *fp) +{ + char *p; + KsbaSexp sexp; + int idx; + + for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++) + { + fputs (!idx? "Issuer ...: " + : "\n aka ...: ", fp); + gpgsm_print_name (fp, p); + xfree (p); + } + putc ('\n', fp); + + fputs ("Serial ...: ", fp); + sexp = ksba_cert_get_serial (cert); + if (sexp) + { + int len; + const unsigned char *s = sexp; + + if (*s == '(') + { + s++; + for (len=0; *s && *s != ':' && digitp (s); s++) + len = len*10 + atoi_1 (s); + if (*s == ':') + for (s++; len; len--, s++) + fprintf (fp, "%02X", *s); + } + xfree (sexp); + } + putc ('\n', fp); + + for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++) + { + fputs (!idx? "Subject ..: " + : "\n aka ..: ", fp); + gpgsm_print_name (fp, p); + xfree (p); + } + putc ('\n', fp); +} + + + + + + diff --git a/sm/fingerprint.c b/sm/fingerprint.c new file mode 100644 index 000000000..028c08aab --- /dev/null +++ b/sm/fingerprint.c @@ -0,0 +1,271 @@ +/* fingerprint.c - Get the fingerprint + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +/* Return the fingerprint of the certificate (we can't put this into + libksba because we need libgcrypt support). The caller must + provide an array of sufficient length or NULL so that the function + allocates the array. If r_len is not NULL, the length of the + digest is returned; well, this can also be done by using + gcry_md_get_algo_dlen(). If algo is 0, a SHA-1 will be used. + + If there is a problem , the function does never return NULL but a + digest of all 0xff. + */ +char * +gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len) +{ + gcry_md_hd_t md; + int rc, len; + + if (!algo) + algo = GCRY_MD_SHA1; + + len = gcry_md_get_algo_dlen (algo); + assert (len); + if (!array) + array = xmalloc (len); + + if (r_len) + *r_len = len; + + rc = gcry_md_open (&md, algo, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + memset (array, 0xff, len); /* better return an invalid fpr than NULL */ + return array; + } + + rc = ksba_cert_hash (cert, 0, HASH_FNC, md); + if (rc) + { + log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); + gcry_md_close (md); + memset (array, 0xff, len); /* better return an invalid fpr than NULL */ + return array; + } + gcry_md_final (md); + memcpy (array, gcry_md_read(md, algo), len ); + return array; +} + + +/* Return an allocated buffer with the formatted fingerprint */ +char * +gpgsm_get_fingerprint_string (KsbaCert cert, int algo) +{ + unsigned char digest[MAX_DIGEST_LEN]; + char *buf; + int len, i; + + if (!algo) + algo = GCRY_MD_SHA1; + + len = gcry_md_get_algo_dlen (algo); + assert (len <= MAX_DIGEST_LEN ); + gpgsm_get_fingerprint (cert, algo, digest, NULL); + buf = xmalloc (len*3+1); + *buf = 0; + for (i=0; i < len; i++ ) + sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]); + return buf; +} + +/* Return an allocated buffer with the formatted fingerprint as one + large hexnumber */ +char * +gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo) +{ + unsigned char digest[MAX_DIGEST_LEN]; + char *buf; + int len, i; + + if (!algo) + algo = GCRY_MD_SHA1; + + len = gcry_md_get_algo_dlen (algo); + assert (len <= MAX_DIGEST_LEN ); + gpgsm_get_fingerprint (cert, algo, digest, NULL); + buf = xmalloc (len*3+1); + *buf = 0; + for (i=0; i < len; i++ ) + sprintf (buf+strlen(buf), "%02X", digest[i]); + return buf; +} + +/* Return a certificate ID. These are the last 4 bytes of the SHA-1 + fingerprint. */ +unsigned long +gpgsm_get_short_fingerprint (KsbaCert cert) +{ + unsigned char digest[20]; + + gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); + return ((digest[16]<<24)|(digest[17]<<16)|(digest[18]<< 8)|digest[19]); +} + + +/* Return the so called KEYGRIP which is the SHA-1 hash of the public + key parameters expressed as an canoncial encoded S-Exp. array must + be 20 bytes long. returns the array or a newly allocated one if the + passed one was NULL */ +char * +gpgsm_get_keygrip (KsbaCert cert, char *array) +{ + gcry_sexp_t s_pkey; + int rc; + KsbaSexp p; + size_t n; + + p = ksba_cert_get_public_key (cert); + if (!p) + return NULL; /* oops */ + + if (DBG_X509) + log_debug ("get_keygrip for public key: %s\n", p); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + log_error ("libksba did not return a proper S-Exp\n"); + return NULL; + } + rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + xfree (p); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); + return NULL; + } + array = gcry_pk_get_keygrip (s_pkey, array); + gcry_sexp_release (s_pkey); + if (!array) + { + rc = gpg_error (GPG_ERR_GENERAL); + log_error ("can't calculate keygrip\n"); + return NULL; + } + if (DBG_X509) + log_printhex ("keygrip=", array, 20); + + return array; +} + +/* Return an allocated buffer with the keygrip of CERT in from of an + hexstring. NULL is returned in case of error */ +char * +gpgsm_get_keygrip_hexstring (KsbaCert cert) +{ + unsigned char grip[20]; + char *buf, *p; + int i; + + gpgsm_get_keygrip (cert, grip); + buf = p = xmalloc (20*2+1); + for (i=0; i < 20; i++, p += 2 ) + sprintf (p, "%02X", grip[i]); + return buf; +} + + + +/* For certain purposes we need a certificate id which has an upper + limit of the size. We use the hash of the issuer name and the + serial number for this. In most cases the serial number is not + that large and the resulting string can be passed on an assuan + command line. Everything is hexencoded with the serialnumber + delimted from the has by a dot. + + The caller must free the string. +*/ +char * +gpgsm_get_certid (KsbaCert cert) +{ + KsbaSexp serial; + unsigned char *p; + char *endp; + unsigned char hash[20]; + unsigned long n; + char *certid; + int i; + + p = ksba_cert_get_issuer (cert, 0); + if (!p) + return NULL; /* Ooops: No issuer */ + gcry_md_hash_buffer (GCRY_MD_SHA1, hash, p, strlen (p)); + xfree (p); + + serial = ksba_cert_get_serial (cert); + if (!serial) + return NULL; /* oops: no serial number */ + p = serial; + if (*p != '(') + { + log_error ("Ooops: invalid serial number\n"); + xfree (serial); + return NULL; + } + p++; + n = strtoul (p, &endp, 10); + p = endp; + if (*p != ':') + { + log_error ("Ooops: invalid serial number (no colon)\n"); + xfree (serial); + return NULL; + } + p++; + + certid = xtrymalloc ( 40 + 1 + n*2 + 1); + if (!certid) + { + xfree (serial); + return NULL; /* out of core */ + } + + for (i=0, endp = certid; i < 20; i++, endp += 2 ) + sprintf (endp, "%02X", hash[i]); + *endp++ = '.'; + for (i=0; i < n; i++, endp += 2) + sprintf (endp, "%02X", p[i]); + *endp = 0; + + xfree (serial); + return certid; +} + + + + + + diff --git a/sm/gpgsm.c b/sm/gpgsm.c new file mode 100644 index 000000000..c392886ba --- /dev/null +++ b/sm/gpgsm.c @@ -0,0 +1,1458 @@ +/* gpgsm.c - GnuPG for S/MIME + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <fcntl.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <assuan.h> /* malloc hooks */ + +#include "../kbx/keybox.h" /* malloc hooks */ +#include "i18n.h" +#include "keydb.h" +#include "sysutils.h" + +enum cmd_and_opt_values { + aNull = 0, + oArmor = 'a', + aDetachedSign = 'b', + aSym = 'c', + aDecrypt = 'd', + aEncr = 'e', + oInteractive = 'i', + oKOption = 'k', + oDryRun = 'n', + oOutput = 'o', + oQuiet = 'q', + oRecipient = 'r', + aSign = 's', + oTextmodeShort= 't', + oUser = 'u', + oVerbose = 'v', + oCompress = 'z', + oNotation = 'N', + oBatch = 500, + aClearsign, + aStore, + aKeygen, + aSignEncr, + aSignKey, + aLSignKey, + aListPackets, + aEditKey, + aDeleteKey, + aImport, + aVerify, + aVerifyFiles, + aListKeys, + aListExternalKeys, + aListSigs, + aListSecretKeys, + aSendKeys, + aRecvKeys, + aExport, + aCheckKeys, /* nyi */ + aServer, + aLearnCard, + aCallDirmngr, + aCallProtectTool, + aPasswd, + + oOptions, + oDebug, + oDebugAll, + oDebugWait, + oDebugNoChainValidation, + oLogFile, + + oEnableSpecialFilenames, + + oAgentProgram, + oDisplay, + oTTYname, + oTTYtype, + oLCctype, + oLCmessages, + + oDirmngrProgram, + oFakedSystemTime, + + + oAssumeArmor, + oAssumeBase64, + oAssumeBinary, + + oBase64, + oNoArmor, + + oDisableCRLChecks, + oEnableCRLChecks, + + oIncludeCerts, + oPolicyFile, + oDisablePolicyChecks, + oEnablePolicyChecks, + oAutoIssuerKeyRetrieve, + + + oTextmode, + oFingerprint, + oWithFingerprint, + oAnswerYes, + oAnswerNo, + oKeyring, + oSecretKeyring, + oDefaultKey, + oDefRecipient, + oDefRecipientSelf, + oNoDefRecipient, + oStatusFD, + oNoComment, + oNoVersion, + oEmitVersion, + oCompletesNeeded, + oMarginalsNeeded, + oMaxCertDepth, + oLoadExtension, + oRFC1991, + oOpenPGP, + oCipherAlgo, + oDigestAlgo, + oCompressAlgo, + oCommandFD, + oNoVerbose, + oTrustDBName, + oNoSecmemWarn, + oNoDefKeyring, + oNoGreeting, + oNoTTY, + oNoOptions, + oNoBatch, + oHomedir, + oWithColons, + oWithKeyData, + oSkipVerify, + oCompressKeys, + oCompressSigs, + oAlwaysTrust, + oRunAsShmCP, + oSetFilename, + oSetPolicyURL, + oUseEmbeddedFilename, + oComment, + oDefaultComment, + oThrowKeyid, + oForceV3Sigs, + oForceMDC, + oS2KMode, + oS2KDigest, + oS2KCipher, + oCharset, + oNotDashEscaped, + oEscapeFrom, + oLockOnce, + oLockMultiple, + oLockNever, + oKeyServer, + oEncryptTo, + oNoEncryptTo, + oLoggerFD, + oUtf8Strings, + oNoUtf8Strings, + oDisableCipherAlgo, + oDisablePubkeyAlgo, + oAllowNonSelfsignedUID, + oAllowFreeformUID, + oNoLiteral, + oSetFilesize, + oHonorHttpProxy, + oFastListMode, + oListOnly, + oIgnoreTimeConflict, + oNoRandomSeedFile, + oNoAutoKeyRetrieve, + oUseAgent, + oMergeOnly, + oTryAllSecrets, + oTrustedKey, + oEmuMDEncodeBug, + aDummy + }; + + +static ARGPARSE_OPTS opts[] = { + + { 300, NULL, 0, N_("@Commands:\n ") }, + + { aSign, "sign", 256, N_("|[file]|make a signature")}, + { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, + { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, + { aEncr, "encrypt", 256, N_("encrypt data")}, + { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, + { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, + { aVerify, "verify" , 256, N_("verify a signature")}, + { aVerifyFiles, "verify-files" , 256, "@" }, + { aListKeys, "list-keys", 256, N_("list keys")}, + { aListExternalKeys, "list-external-keys", 256, N_("list external keys")}, + { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, + { aListSigs, "list-sigs", 256, N_("list certificate chain")}, + { aListSigs, "check-sigs",256, "@"}, + { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, + { aKeygen, "gen-key", 256, N_("generate a new key pair")}, + { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")}, + { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, + { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, + { aImport, "import", 256 , N_("import certificates")}, + { aExport, "export", 256 , N_("export certificates")}, + { aLearnCard, "learn-card", 256 ,N_("register a smartcard")}, + { aServer, "server", 256, N_("run in server mode")}, + { aCallDirmngr, "call-dirmngr", 256, N_("pass a command to the dirmngr")}, + { aCallProtectTool, "call-protect-tool", 256, + N_("invoke gpg-protect-tool")}, + { aPasswd, "passwd", 256, N_("change a passphrase")}, + + { 301, NULL, 0, N_("@\nOptions:\n ") }, + + { oArmor, "armor", 0, N_("create ascii armored output")}, + { oArmor, "armour", 0, "@" }, + { oBase64, "base64", 0, N_("create base-64 encoded output")}, + + { oAssumeArmor, "assume-armor", 0, N_("assume input is in PEM format")}, + { oAssumeBase64, "assume-base64", 0, + N_("assume input is in base-64 format")}, + { oAssumeBinary, "assume-binary", 0, + N_("assume input is in binary format")}, + + { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, + + + { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, + { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, + + { oIncludeCerts, "include-certs", 1, + N_("|N|number of certificates to include") }, + + { oPolicyFile, "policy-file", 2, + N_("|FILE|take policy information from FILE") }, + + { oDisablePolicyChecks, "disable-policy-checks", 0, + N_("do not check certificate policies")}, + { oEnablePolicyChecks, "enable-policy-checks", 0, "@"}, + + { oAutoIssuerKeyRetrieve, "auto-issuer-key-retrieve", 0, + N_("fetch missing issuer certificates")}, + +#if 0 + { oDefRecipient, "default-recipient" ,2, + N_("|NAME|use NAME as default recipient")}, + { oDefRecipientSelf, "default-recipient-self" ,0, + N_("use the default key as default recipient")}, + { oNoDefRecipient, "no-default-recipient", 0, "@" }, + { oEncryptTo, "encrypt-to", 2, "@" }, + { oNoEncryptTo, "no-encrypt-to", 0, "@" }, + +#endif + { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, + +#if 0 + { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, + { oTextmodeShort, NULL, 0, "@"}, + { oTextmode, "textmode", 0, N_("use canonical text mode")}, +#endif + + { oOutput, "output", 2, N_("use as output file")}, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, + { oLogFile, "log-file" ,2, N_("use a log file for the server")}, +#if 0 + { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, + { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, +#endif + { oDryRun, "dry-run", 0, N_("do not make any changes") }, + /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */ + /*{ oUseAgent, "use-agent",0, N_("use the gpg-agent")},*/ + { oBatch, "batch", 0, N_("batch mode: never ask")}, + { oAnswerYes, "yes", 0, N_("assume yes on most questions")}, + { oAnswerNo, "no", 0, N_("assume no on most questions")}, + + { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, + { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, + { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, + { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, + { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, + { oOptions, "options" , 2, N_("read options from file")}, + + { oDebug, "debug" ,4|16, "@"}, + { oDebugAll, "debug-all" ,0, "@"}, + { oDebugWait, "debug-wait" ,1, "@"}, + { oDebugNoChainValidation, "debug-no-chain-validation" ,0, "@"}, + { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, + { aDummy, "no-comment", 0, "@"}, + { aDummy, "completes-needed", 1, "@"}, + { aDummy, "marginals-needed", 1, "@"}, + { oMaxCertDepth, "max-cert-depth", 1, "@" }, + { aDummy, "trusted-key", 2, "@"}, + { oLoadExtension, "load-extension" ,2, + N_("|FILE|load extension module FILE")}, + { aDummy, "rfc1991", 0, "@"}, + { aDummy, "openpgp", 0, "@"}, + { aDummy, "s2k-mode", 1, "@"}, + { aDummy, "s2k-digest-algo",2, "@"}, + { aDummy, "s2k-cipher-algo",2, "@"}, + { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, + { oDigestAlgo, "digest-algo", 2 , + N_("|NAME|use message digest algorithm NAME")}, +#if 0 + { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")}, +#endif + { aDummy, "throw-keyid", 0, "@"}, + { aDummy, "notation-data", 2, "@"}, + + { 302, NULL, 0, N_( + "@\n(See the man page for a complete listing of all commands and options)\n" + )}, + + { 303, NULL, 0, N_("@\nExamples:\n\n" + " -se -r Bob [file] sign and encrypt for user Bob\n" + " --clearsign [file] make a clear text signature\n" + " --detach-sign [file] make a detached signature\n" + " --list-keys [names] show keys\n" + " --fingerprint [names] show fingerprints\n" ) }, + + /* hidden options */ + { oNoVerbose, "no-verbose", 0, "@"}, + + { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" }, + + + { oTrustDBName, "trustdb-name", 2, "@" }, + { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, + { oNoArmor, "no-armor", 0, "@"}, + { oNoArmor, "no-armour", 0, "@"}, + { oNoDefKeyring, "no-default-keyring", 0, "@" }, + { oNoGreeting, "no-greeting", 0, "@" }, + { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */ + { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ + { oAgentProgram, "agent-program", 2 , "@" }, + { oDisplay, "display", 2, "@" }, + { oTTYname, "ttyname", 2, "@" }, + { oTTYtype, "ttytype", 2, "@" }, + { oLCctype, "lc-ctype", 2, "@" }, + { oLCmessages, "lc-messages", 2, "@" }, + { oDirmngrProgram, "dirmngr-program", 2 , "@" }, + { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */ + + + { oNoBatch, "no-batch", 0, "@" }, + { oWithColons, "with-colons", 0, "@"}, + { oWithKeyData,"with-key-data", 0, "@"}, + { aListKeys, "list-key", 0, "@" }, /* alias */ + { aListSigs, "list-sig", 0, "@" }, /* alias */ + { aListSigs, "check-sig",0, "@" }, /* alias */ + { oSkipVerify, "skip-verify",0, "@" }, + { oCompressKeys, "compress-keys",0, "@"}, + { oCompressSigs, "compress-sigs",0, "@"}, + { oAlwaysTrust, "always-trust", 0, "@"}, + { oNoVersion, "no-version", 0, "@"}, + { oLockOnce, "lock-once", 0, "@" }, + { oLockMultiple, "lock-multiple", 0, "@" }, + { oLockNever, "lock-never", 0, "@" }, + { oLoggerFD, "logger-fd",1, "@" }, + { oWithFingerprint, "with-fingerprint", 0, "@" }, + { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, + { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, + { oHonorHttpProxy,"honor-http-proxy", 0, "@" }, + { oListOnly, "list-only", 0, "@"}, + { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, + { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, +{0} }; + + + +int gpgsm_errors_seen = 0; + +/* It is possible that we are currentlu running under setuid permissions */ +static int maybe_setuid = 1; + +/* Option --enable-special-filenames */ +static int allow_special_filenames; + + +static char *build_list (const char *text, + const char *(*mapf)(int), int (*chkf)(int)); +static void set_cmd (enum cmd_and_opt_values *ret_cmd, + enum cmd_and_opt_values new_cmd ); + +static void emergency_cleanup (void); +static int check_special_filename (const char *fname); +static int open_read (const char *filename); +static FILE *open_fwrite (const char *filename); +static void run_protect_tool (int argc, char **argv); + + +static int +our_pk_test_algo (int algo) +{ + return 1; +} + +static int +our_cipher_test_algo (int algo) +{ + return 1; +} + +static int +our_md_test_algo (int algo) +{ + return 1; +} + +static const char * +my_strusage( int level ) +{ + static char *digests, *pubkeys, *ciphers; + const char *p; + + switch (level) + { + case 11: p = "gpgsm (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: gpgsm [options] [files] (-h for help)"); + break; + case 41: + p = _("Syntax: gpgsm [options] [files]\n" + "sign, check, encrypt or decrypt using the S/MIME protocol\n" + "default operation depends on the input data\n"); + break; + + case 31: p = "\nHome: "; break; + case 32: p = opt.homedir; break; + case 33: p = _("\nSupported algorithms:\n"); break; + case 34: + if (!ciphers) + ciphers = build_list ("Cipher: ", gcry_cipher_algo_name, + our_cipher_test_algo ); + p = ciphers; + break; + case 35: + if (!pubkeys) + pubkeys = build_list ("Pubkey: ", gcry_pk_algo_name, + our_pk_test_algo ); + p = pubkeys; + break; + case 36: + if (!digests) + digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo ); + p = digests; + break; + + default: p = NULL; break; + } + return p; +} + + +static char * +build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int)) +{ + int i; + size_t n=strlen(text)+2; + char *list, *p; + + if (maybe_setuid) { + gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */ + } + + for (i=1; i < 110; i++ ) + if (!chkf(i)) + n += strlen(mapf(i)) + 2; + list = xmalloc (21 + n); + *list = 0; + for (p=NULL, i=1; i < 110; i++) + { + if (!chkf(i)) + { + if( !p ) + p = stpcpy (list, text ); + else + p = stpcpy (p, ", "); + p = stpcpy (p, mapf(i) ); + } + } + if (p) + p = stpcpy(p, "\n" ); + return list; +} + + +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file (PACKAGE); +#else +# ifdef ENABLE_NLS +# ifdef HAVE_LC_MESSAGES + setlocale (LC_TIME, ""); + setlocale (LC_MESSAGES, ""); +# else + setlocale (LC_ALL, "" ); +# endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +# endif +#endif +} + + +static void +wrong_args (const char *text) +{ + fputs (_("usage: gpgsm [options] "), stderr); + fputs (text, stderr); + putc ('\n', stderr); + gpgsm_exit (2); +} + + +static void +set_debug(void) +{ + if (opt.debug & DBG_MPI_VALUE) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); + if (opt.debug & DBG_CRYPTO_VALUE ) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); +} + + +static void +set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd) +{ + enum cmd_and_opt_values cmd = *ret_cmd; + + if (!cmd || cmd == new_cmd) + cmd = new_cmd; + else if ( cmd == aSign && new_cmd == aEncr ) + cmd = aSignEncr; + else if ( cmd == aEncr && new_cmd == aSign ) + cmd = aSignEncr; + else if ( (cmd == aSign && new_cmd == aClearsign) + || (cmd == aClearsign && new_cmd == aSign) ) + cmd = aClearsign; + else + { + log_error(_("conflicting commands\n")); + gpgsm_exit(2); + } + + *ret_cmd = cmd; +} + + +int +main ( int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + int orig_argc; + char **orig_argv; + const char *fname; + /* char *username;*/ + int may_coredump; + STRLIST sl, remusr= NULL, locusr=NULL; + STRLIST nrings=NULL; + int detached_sig = 0; + FILE *configfp = NULL; + char *configname = NULL; + unsigned configlineno; + int parse_debug = 0; + int no_more_options = 0; + int default_config =1; + int default_keyring = 1; + char *logfile = NULL; + int greeting = 0; + int nogreeting = 0; + int debug_wait = 0; + int use_random_seed = 1; + int with_fpr = 0; + char *def_digest_string = NULL; + enum cmd_and_opt_values cmd = 0; + struct server_control_s ctrl; + CERTLIST recplist = NULL; + CERTLIST signerlist = NULL; + + /* trap_unaligned ();*/ + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + /* We don't need any locking in libgcrypt unless we use any kind of + threading. */ + gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING); + + /* Please note that we may running SUID(ROOT), so be very CAREFUL + when adding any stuff between here and the call to secmem_init() + somewhere after the option parsing */ + log_set_prefix ("gpgsm", 1); + /* check that the libraries are suitable. Do it here because the + option parse may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + if (!ksba_check_version (NEED_KSBA_VERSION) ) + { + log_fatal( _("libksba is too old (need %s, have %s)\n"), + NEED_KSBA_VERSION, ksba_check_version (NULL) ); + } + + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + + may_coredump = disable_core_dumps (); + + gnupg_init_signals (0, emergency_cleanup); + + create_dotlock (NULL); /* register locking cleanup */ + i18n_init(); + + opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/ +#ifdef __MINGW32__ + 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; + + /* first check whether we have a config file on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ + while (arg_parse( &pargs, opts)) + { + if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) + parse_debug++; + else if (pargs.r_opt == oOptions) + { /* yes there is one, so we do not try the default one but + read the config file when it is encountered at the + commandline */ + default_config = 0; + } + else if (pargs.r_opt == oNoOptions) + default_config = 0; /* --no-options */ + else if (pargs.r_opt == oHomedir) + opt.homedir = pargs.r.ret_str; + else if (pargs.r_opt == aCallProtectTool) + break; /* This break makes sure that --version and --help are + passed to the protect-tool. */ + } + + + /* initialize the secure memory. */ + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + maybe_setuid = 0; + + /* + Now we are now working under our real uid + */ + + ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + + /* Setup a default control structure for command line mode */ + memset (&ctrl, 0, sizeof ctrl); + gpgsm_init_default_ctrl (&ctrl); + ctrl.no_server = 1; + ctrl.status_fd = -1; /* not status output */ + ctrl.autodetect_encoding = 1; + + /* set the default option file */ + if (default_config ) + configname = make_filename (opt.homedir, "gpgsm.conf", NULL); + /* cet the default policy file */ + opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL); + + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags = 1; /* do not remove the args */ + + next_pass: + if (configname) { + configlineno = 0; + configfp = fopen (configname, "r"); + if (!configfp) + { + if (default_config) + { + if (parse_debug) + log_info (_("NOTE: no default option file `%s'\n"), configname); + } + else + { + log_error (_("option file `%s': %s\n"), configname, strerror(errno)); + gpgsm_exit(2); + } + xfree(configname); + configname = NULL; + } + if (parse_debug && configname) + log_info (_("reading options from `%s'\n"), configname); + default_config = 0; + } + + while (!no_more_options + && optfile_parse (configfp, configname, &configlineno, &pargs, opts)) + { + switch (pargs.r_opt) + { + case aServer: + opt.batch = 1; + set_cmd (&cmd, aServer); + break; + case aCallDirmngr: + opt.batch = 1; + set_cmd (&cmd, aCallDirmngr); + break; + + case aCallProtectTool: + opt.batch = 1; + set_cmd (&cmd, aCallProtectTool); + no_more_options = 1; /* Stop parsing. */ + break; + + case aCheckKeys: set_cmd (&cmd, aCheckKeys); break; + case aImport: set_cmd (&cmd, aImport); break; + case aSendKeys: set_cmd (&cmd, aSendKeys); break; + case aRecvKeys: set_cmd (&cmd, aRecvKeys); break; + case aExport: set_cmd (&cmd, aExport); break; + case aListKeys: set_cmd (&cmd, aListKeys); break; + case aListExternalKeys: set_cmd (&cmd, aListExternalKeys); break; + case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break; + case aListSigs: set_cmd (&cmd, aListSigs); break; + + case aLearnCard: set_cmd (&cmd, aLearnCard); break; + + case aPasswd: set_cmd (&cmd, aPasswd); break; + + case aDeleteKey: + set_cmd (&cmd, aDeleteKey); + /*greeting=1;*/ + break; + + case aDetachedSign: + detached_sig = 1; + set_cmd (&cmd, aSign ); + break; + + case aSym: set_cmd (&cmd, aSym); break; + case aDecrypt: set_cmd (&cmd, aDecrypt); break; + case aEncr: set_cmd (&cmd, aEncr); break; + case aSign: set_cmd (&cmd, aSign ); break; + case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break; + case aClearsign: set_cmd (&cmd, aClearsign); break; + case aVerify: set_cmd (&cmd, aVerify); break; + + + /* output encoding selection */ + case oArmor: + ctrl.create_pem = 1; + break; + case oBase64: + ctrl.create_pem = 0; + ctrl.create_base64 = 1; + break; + case oNoArmor: + ctrl.create_pem = 0; + ctrl.create_base64 = 0; + break; + + /* Input encoding selection */ + case oAssumeArmor: + ctrl.autodetect_encoding = 0; + ctrl.is_pem = 1; + ctrl.is_base64 = 0; + break; + case oAssumeBase64: + ctrl.autodetect_encoding = 0; + ctrl.is_pem = 0; + ctrl.is_base64 = 1; + break; + case oAssumeBinary: + ctrl.autodetect_encoding = 0; + ctrl.is_pem = 0; + ctrl.is_base64 = 0; + break; + + case oDisableCRLChecks: + opt.no_crl_check = 1; + break; + case oEnableCRLChecks: + opt.no_crl_check = 0; + break; + + case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break; + + case oPolicyFile: + xfree (opt.policy_file); + if (*pargs.r.ret_str) + opt.policy_file = xstrdup (pargs.r.ret_str); + else + opt.policy_file = NULL; + break; + + case oDisablePolicyChecks: + opt.no_policy_check = 1; + break; + case oEnablePolicyChecks: + opt.no_policy_check = 0; + break; + + case oAutoIssuerKeyRetrieve: + opt.auto_issuer_key_retrieve = 1; + break; + + case oOutput: opt.outfile = pargs.r.ret_str; break; + + + case oQuiet: opt.quiet = 1; break; + case oNoTTY: /* fixme:tty_no_terminal(1);*/ break; + case oDryRun: opt.dry_run = 1; break; + + case oVerbose: + opt.verbose++; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); + break; + case oNoVerbose: + opt.verbose = 0; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); + break; + + case oLogFile: logfile = pargs.r.ret_str; break; + + case oBatch: + opt.batch = 1; + greeting = 0; + break; + case oNoBatch: opt.batch = 0; break; + + case oAnswerYes: opt.answer_yes = 1; break; + case oAnswerNo: opt.answer_no = 1; break; + + case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break; + + case oDebug: opt.debug |= pargs.r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + case oDebugWait: debug_wait = pargs.r.ret_int; break; + case oDebugNoChainValidation: opt.no_chain_validation = 1; break; + + case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; + case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; + case oWithFingerprint: + with_fpr=1; /*fall thru*/ + case oFingerprint: + opt.fingerprint++; + break; + + case oOptions: + /* config files may not be nested (silently ignore them) */ + if (!configfp) + { + xfree(configname); + configname = xstrdup (pargs.r.ret_str); + goto next_pass; + } + break; + case oNoOptions: break; /* no-options */ + case oHomedir: opt.homedir = pargs.r.ret_str; break; + case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; + case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break; + case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break; + case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break; + case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break; + case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break; + case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; + + case oFakedSystemTime: + gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0); + break; + + case oNoDefKeyring: default_keyring = 0; break; + case oNoGreeting: nogreeting = 1; break; + + case oDefaultKey: + /* fixme:opt.def_secret_key = pargs.r.ret_str;*/ + break; + case oDefRecipient: + if (*pargs.r.ret_str) + opt.def_recipient = xstrdup (pargs.r.ret_str); + break; + case oDefRecipientSelf: + xfree (opt.def_recipient); + opt.def_recipient = NULL; + opt.def_recipient_self = 1; + break; + case oNoDefRecipient: + xfree (opt.def_recipient); + opt.def_recipient = NULL; + opt.def_recipient_self = 0; + break; + + case oWithKeyData: opt.with_key_data=1; /* fall thru */ + case oWithColons: ctrl.with_colons = 1; break; + + case oSkipVerify: opt.skip_verify=1; break; + + case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break; + case oEncryptTo: /* store the recipient in the second list */ + sl = add_to_strlist (&remusr, pargs.r.ret_str); + sl->flags = 1; + break; + + case oRecipient: /* store the recipient */ + add_to_strlist ( &remusr, pargs.r.ret_str); + break; + + case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break; + case oTextmode: /*fixme:opt.textmode=1;*/ break; + + case oUser: /* store the local users, the first one is the default */ + if (!opt.local_user) + opt.local_user = pargs.r.ret_str; + add_to_strlist (&locusr, pargs.r.ret_str); + break; + + case oNoSecmemWarn: + gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); + break; + + case oCipherAlgo: + opt.def_cipher_algoid = pargs.r.ret_str; + break; + + case oDisableCipherAlgo: + { + int algo = gcry_cipher_map_name (pargs.r.ret_str); + gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); + } + break; + case oDisablePubkeyAlgo: + { + int algo = gcry_pk_map_name (pargs.r.ret_str); + gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo ); + } + break; + + case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; + case oNoRandomSeedFile: use_random_seed = 0; break; + + case oEnableSpecialFilenames: allow_special_filenames =1; break; + + + case aDummy: + break; + default: + pargs.err = configfp? 1:2; + break; + } + } + + if (configfp) + { + fclose (configfp); + configfp = NULL; + xfree (configname); + configname = NULL; + goto next_pass; + } + + xfree (configname); + configname = NULL; + + if (log_get_errorcount(0)) + gpgsm_exit(2); + + if (nogreeting) + greeting = 0; + + if (greeting) + { + fprintf(stderr, "%s %s; %s\n", + strusage(11), strusage(13), strusage(14) ); + fprintf(stderr, "%s\n", strusage(15) ); + } +# ifdef IS_DEVELOPMENT_VERSION + if (!opt.batch) + { + log_info ("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); + log_info ("It is only intended for test purposes and should NOT be\n"); + log_info ("used in a production environment or with production keys!\n"); + } +# endif + + if (may_coredump && !opt.quiet) + log_info (_("WARNING: program may create a core file!\n")); + + if (logfile && cmd == aServer) + { + log_set_file (logfile); + log_set_prefix (NULL, 1|2|4); + } + + if (gnupg_faked_time_p ()) + { + log_info (_("WARNING: running with faked system time: ")); + gpgsm_dump_time (gnupg_get_time ()); + log_printf ("\n"); + } + +/*FIXME if (opt.batch) */ +/* tty_batchmode (1); */ + + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); + + set_debug (); + + /* FIXME: should set filenames of libgcrypt explicitly + * gpg_opt_homedir = opt.homedir; */ + + /* must do this after dropping setuid, because the mapping functions + may try to load an module and we may have disabled an algorithm */ + if ( !gcry_cipher_map_name (opt.def_cipher_algoid) + || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid)) + log_error (_("selected cipher algorithm is invalid\n")); + + if (def_digest_string) + { + opt.def_digest_algo = gcry_md_map_name (def_digest_string); + xfree (def_digest_string); + def_digest_string = NULL; + if (our_md_test_algo(opt.def_digest_algo) ) + log_error (_("selected digest algorithm is invalid\n")); + } + + if (log_get_errorcount(0)) + gpgsm_exit(2); + + /* set the random seed file */ + if (use_random_seed) { + char *p = make_filename (opt.homedir, "random_seed", NULL); + gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); + xfree(p); + } + + + if (!cmd && opt.fingerprint && !with_fpr) + set_cmd (&cmd, aListKeys); + + if (!nrings && default_keyring) /* add default keybox */ + keydb_add_resource ("pubring.kbx", 0, 0); + for (sl = nrings; sl; sl = sl->next) + keydb_add_resource (sl->d, 0, 0); + FREE_STRLIST(nrings); + + + for (sl = locusr; sl; sl = sl->next) + { + int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist); + if (rc) + { + log_error (_("can't sign using `%s': %s\n"), + sl->d, gpg_strerror (rc)); + gpgsm_status2 (&ctrl, STATUS_INV_RECP, + gpg_err_code (rc) == -1? "1": + gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1": + gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2": + gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3": + gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4": + gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5": + gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6": + gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7": + gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8": + gpg_err_code (rc) == GPG_ERR_NO_SECKEY? "9": + "0", + sl->d, NULL); + } + } + for (sl = remusr; sl; sl = sl->next) + { + int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist); + if (rc) + { + log_error (_("can't encrypt to `%s': %s\n"), + sl->d, gpg_strerror (rc)); + gpgsm_status2 (&ctrl, STATUS_INV_RECP, + gpg_err_code (rc) == -1? "1": + gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1": + gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2": + gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3": + gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4": + gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5": + gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6": + gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7": + gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8": + "0", + sl->d, NULL); + } + } + if (log_get_errorcount(0)) + gpgsm_exit(1); /* must stop for invalid recipients */ + + + + fname = argc? *argv : NULL; + + switch (cmd) + { + case aServer: + if (debug_wait) + { + log_debug ("waiting for debugger - my pid is %u .....\n", + (unsigned int)getpid()); + sleep (debug_wait); + log_debug ("... okay\n"); + } + gpgsm_server (); + break; + + case aCallDirmngr: + if (!argc) + wrong_args (_("--call-dirmngr <command> {args}")); + else + if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1)) + gpgsm_exit (1); + break; + + case aCallProtectTool: + run_protect_tool (argc, argv); + break; + + case aEncr: /* encrypt the given file */ + if (!argc) + gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */ + else if (argc == 1) + gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */ + else + wrong_args (_("--encrypt [datafile]")); + break; + + case aSign: /* sign the given file */ + /* FIXME: We don't handle --output yet. We should also allow + to concatenate multiple files for signing because that is + what gpg does.*/ + if (!argc) + gpgsm_sign (&ctrl, signerlist, + 0, detached_sig, stdout); /* create from stdin */ + else if (argc == 1) + gpgsm_sign (&ctrl, signerlist, + open_read (*argv), detached_sig, stdout); /* from file */ + else + wrong_args (_("--sign [datafile]")); + break; + + case aSignEncr: /* sign and encrypt the given file */ + log_error ("this command has not yet been implemented\n"); + break; + + case aClearsign: /* make a clearsig */ + log_error ("this command has not yet been implemented\n"); + break; + + case aVerify: + { + FILE *fp = NULL; + + if (argc == 2 && opt.outfile) + log_info ("option --output ignored for a detached signature\n"); + else if (opt.outfile) + fp = open_fwrite (opt.outfile); + + if (!argc) + gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */ + else if (argc == 1) + gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */ + else if (argc == 2) /* detached signature (sig, detached) */ + gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL); + else + wrong_args (_("--verify [signature [detached_data]]")); + + if (fp && fp != stdout) + fclose (fp); + } + break; + + case aVerifyFiles: + log_error ("this command has not yet been implemented\n"); + break; + + case aDecrypt: + if (!argc) + gpgsm_decrypt (&ctrl, 0, stdout); /* from stdin */ + else if (argc == 1) + gpgsm_decrypt (&ctrl, open_read (*argv), stdout); /* from file */ + else + wrong_args (_("--decrypt [filename]")); + break; + + case aDeleteKey: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_delete (&ctrl, sl); + free_strlist(sl); + break; + + case aListSigs: + ctrl.with_chain = 1; + case aListKeys: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<6))); + free_strlist(sl); + break; + + case aListExternalKeys: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<7))); + free_strlist(sl); + break; + + case aListSecretKeys: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6))); + free_strlist(sl); + break; + + case aKeygen: /* generate a key */ + log_error ("this function is not yet available from the commandline\n"); + break; + + case aImport: + gpgsm_import_files (&ctrl, argc, argv, open_read); + break; + + case aExport: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_export (&ctrl, sl, stdout); + free_strlist(sl); + break; + + + case aSendKeys: + case aRecvKeys: + log_error ("this command has not yet been implemented\n"); + break; + + + case aLearnCard: + if (argc) + wrong_args ("--learn-card"); + else + { + int rc = gpgsm_agent_learn (); + if (rc) + log_error ("error learning card: %s\n", gpg_strerror (rc)); + } + break; + + case aPasswd: + if (argc != 1) + wrong_args ("--passwd <key-Id>"); + else + { + int rc; + KsbaCert cert = NULL; + char *grip = NULL; + + rc = gpgsm_find_cert (*argv, &cert); + if (rc) + ; + else if (!(grip = gpgsm_get_keygrip_hexstring (cert))) + rc = gpg_error (GPG_ERR_BUG); + else + rc = gpgsm_agent_passwd (grip); + if (rc) + log_error ("error changing passphrase: %s\n", gpg_strerror (rc)); + xfree (grip); + ksba_cert_release (cert); + } + break; + + default: + log_error ("invalid command (there is no implicit command)\n"); + break; + } + + /* cleanup */ + gpgsm_release_certlist (recplist); + gpgsm_release_certlist (signerlist); + FREE_STRLIST(remusr); + FREE_STRLIST(locusr); + gpgsm_exit(0); + return 8; /*NEVER REACHED*/ +} + +/* Note: This function is used by signal handlers!. */ +static void +emergency_cleanup (void) +{ + gcry_control (GCRYCTL_TERM_SECMEM ); +} + + +void +gpgsm_exit (int rc) +{ + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); + if (opt.debug & DBG_MEMSTAT_VALUE) + { + gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); + gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + } + if (opt.debug) + gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); + emergency_cleanup (); + rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0; + exit (rc); +} + + +void +gpgsm_init_default_ctrl (struct server_control_s *ctrl) +{ + ctrl->include_certs = 1; /* only include the signer's cert */ +} + + + +/* Check whether the filename has the form "-&nnnn", where n is a + non-zero number. Returns this number or -1 if it is not the case. */ +static int +check_special_filename (const char *fname) +{ + if (allow_special_filenames + && fname && *fname == '-' && fname[1] == '&' ) { + int i; + + fname += 2; + for (i=0; isdigit (fname[i]); i++ ) + ; + if ( !fname[i] ) + return atoi (fname); + } + return -1; +} + + + +/* Open the FILENAME for read and return the filedescriptor. Stop + with an error message in case of problems. "-" denotes stdin and + if special filenames are allowed the given fd is opened instead. */ +static int +open_read (const char *filename) +{ + int fd; + + if (filename[0] == '-' && !filename[1]) + return 0; /* stdin */ + fd = check_special_filename (filename); + if (fd != -1) + return fd; + fd = open (filename, O_RDONLY); + if (fd == -1) + { + log_error (_("can't open `%s': %s\n"), filename, strerror (errno)); + gpgsm_exit (2); + } + return fd; +} + +/* Open FILENAME for fwrite and return the stream. Stop with an error + message in case of problems. "-" denotes stdout and if special + filenames are allowed the given fd is opened instead. Caller must + close the returned stream unless it is stdout. */ +static FILE * +open_fwrite (const char *filename) +{ + int fd; + FILE *fp; + + if (filename[0] == '-' && !filename[1]) + return stdout; + + fd = check_special_filename (filename); + if (fd != -1) + { + fp = fdopen (dup (fd), "wb"); + if (!fp) + { + log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); + gpgsm_exit (2); + } + return fp; + } + fp = fopen (filename, "wb"); + if (!fp) + { + log_error (_("can't open `%s': %s\n"), filename, strerror (errno)); + gpgsm_exit (2); + } + return fp; +} + + +static void +run_protect_tool (int argc, char **argv) +{ + char *pgm = GNUPG_PROTECT_TOOL; + char **av; + int i; + + av = xcalloc (argc+2, sizeof *av); + av[0] = strrchr (pgm, '/'); + if (!av[0]) + av[0] = pgm; + for (i=1; argc; i++, argc--, argv++) + av[i] = *argv; + av[i] = NULL; + execv (pgm, av); + log_error ("error executing `%s': %s\n", pgm, strerror (errno)); + gpgsm_exit (2); +} + diff --git a/sm/gpgsm.h b/sm/gpgsm.h new file mode 100644 index 000000000..f996d578c --- /dev/null +++ b/sm/gpgsm.h @@ -0,0 +1,274 @@ +/* gpgsm.h - Global definitions for GpgSM + * 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 GPGSM_H +#define GPGSM_H + +#ifdef GPG_ERR_SOURCE_DEFAULT +#error GPG_ERR_SOURCE_DEFAULT already defined +#endif +#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGSM +#include <gpg-error.h> + +#include <ksba.h> +#include "../common/util.h" +#include "../common/errors.h" + +#define OUT_OF_CORE(a) (gpg_error (gpg_err_code_from_errno ((a)))) + +#define MAX_DIGEST_LEN 24 + +/* A large struct name "opt" to keep global flags */ +struct { + unsigned int debug; /* debug flags (DBG_foo_VALUE) */ + int verbose; /* verbosity level */ + int quiet; /* be as quiet as possible */ + int batch; /* run in batch mode, i.e w/o any user interaction */ + int answer_yes; /* assume yes on most questions */ + int answer_no; /* assume no on most questions */ + int dry_run; /* don't change any persistent data */ + + const char *homedir; /* configuration directory name */ + const char *agent_program; + char *display; + char *ttyname; + char *ttytype; + char *lc_ctype; + char *lc_messages; + + const char *dirmngr_program; + char *outfile; /* name of output file */ + + int with_key_data;/* include raw key in the column delimted output */ + + int fingerprint; /* list fingerprints in all key listings */ + + int armor; /* force base64 armoring (see also ctrl.with_base64) */ + int no_armor; /* don't try to figure out whether data is base64 armored*/ + + const char *def_cipher_algoid; /* cipher algorithm to use if + nothing else is specified */ + + int def_digest_algo; /* Ditto for hash algorithm */ + int def_compress_algo; /* Ditto for compress algorithm */ + + char *def_recipient; /* userID of the default recipient */ + int def_recipient_self; /* The default recipient is the default key */ + + char *local_user; /* NULL or argument to -u */ + + int always_trust; /* Trust the given keys even if there is no + valid certification chain */ + int skip_verify; /* do not check signatures on data */ + + int lock_once; /* Keep lock once they are set */ + + int ignore_time_conflict; /* Ignore certain time conflicts */ + + int no_crl_check; /* Don't do a CRL check */ + + char *policy_file; /* full pathname of policy file */ + int no_policy_check; /* ignore certificate policies */ + int no_chain_validation; /* Bypass all cert chain validity tests */ + + int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ +} opt; + + +#define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */ +#define DBG_MPI_VALUE 2 /* debug mpi details */ +#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ +#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ +#define DBG_CACHE_VALUE 64 /* debug the caching */ +#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ +#define DBG_HASHING_VALUE 512 /* debug hashing operations */ +#define DBG_ASSUAN_VALUE 1024 /* debug assuan communication */ + +#define DBG_X509 (opt.debug & DBG_X509_VALUE) +#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) +#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) +#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) +#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) +#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) + +struct server_local_s; + +/* Note that the default values for this are set by + gpgsm_init_default_ctrl() */ +struct server_control_s { + int no_server; /* we are not running under server control */ + int status_fd; /* only for non-server mode */ + struct server_local_s *server_local; + int with_colons; /* use column delimited output format */ + int with_chain; /* include the certifying certs in a listing */ + + int autodetect_encoding; /* try to detect the input encoding */ + int is_pem; /* Is in PEM format */ + int is_base64; /* is in plain base-64 format */ + + int create_base64; /* Create base64 encoded output */ + int create_pem; /* create PEM output */ + const char *pem_name; /* PEM name to use */ + + int include_certs; /* -1 to send all certificates in the chain + along with a signature or the number of + certificates up the chain (0 = none, 1 = only + signer) */ +}; +typedef struct server_control_s *CTRL; + +/* data structure used in base64.c */ +typedef struct base64_context_s *Base64Context; + + +struct certlist_s { + struct certlist_s *next; + KsbaCert cert; +}; +typedef struct certlist_s *CERTLIST; + +/*-- gpgsm.c --*/ +void gpgsm_exit (int rc); +void gpgsm_init_default_ctrl (struct server_control_s *ctrl); + +/*-- server.c --*/ +void gpgsm_server (void); +void gpgsm_status (CTRL ctrl, int no, const char *text); +void gpgsm_status2 (CTRL ctrl, int no, ...); +void gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text, + gpg_err_code_t ec); + +/*-- fingerprint --*/ +char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len); +char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo); +char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo); +unsigned long gpgsm_get_short_fingerprint (KsbaCert cert); +char *gpgsm_get_keygrip (KsbaCert cert, char *array); +char *gpgsm_get_keygrip_hexstring (KsbaCert cert); +char *gpgsm_get_certid (KsbaCert cert); + + +/*-- base64.c --*/ +int gpgsm_create_reader (Base64Context *ctx, + CTRL ctrl, FILE *fp, KsbaReader *r_reader); +void gpgsm_destroy_reader (Base64Context ctx); +int gpgsm_create_writer (Base64Context *ctx, + CTRL ctrl, FILE *fp, KsbaWriter *r_writer); +int gpgsm_finish_writer (Base64Context ctx); +void gpgsm_destroy_writer (Base64Context ctx); + + +/*-- certdump.c --*/ +void gpgsm_print_serial (FILE *fp, KsbaConstSexp p); +void gpgsm_print_time (FILE *fp, time_t t); +void gpgsm_print_name (FILE *fp, const char *string); + +void gpgsm_dump_cert (const char *text, KsbaCert cert); +void gpgsm_dump_serial (KsbaConstSexp p); +void gpgsm_dump_time (time_t t); +void gpgsm_dump_string (const char *string); + + + +/*-- certcheck.c --*/ +int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert); +int gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, + gcry_md_hd_t md, int hash_algo); +/* fixme: move create functions to another file */ +int gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo, + char **r_sigval); + + +/*-- certchain.c --*/ +int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next); +int gpgsm_is_root_cert (KsbaCert cert); +int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime); +int gpgsm_basic_cert_check (KsbaCert cert); + +/*-- certlist.c --*/ +int gpgsm_cert_use_sign_p (KsbaCert cert); +int gpgsm_cert_use_encrypt_p (KsbaCert cert); +int gpgsm_cert_use_verify_p (KsbaCert cert); +int gpgsm_cert_use_decrypt_p (KsbaCert cert); +int gpgsm_cert_use_cert_p (KsbaCert cert); +int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, + CERTLIST *listaddr); +void gpgsm_release_certlist (CERTLIST list); +int gpgsm_find_cert (const char *name, KsbaCert *r_cert); + +/*-- keylist.c --*/ +void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode); + +/*-- import.c --*/ +int gpgsm_import (CTRL ctrl, int in_fd); +int gpgsm_import_files (CTRL ctrl, int nfiles, char **files, + int (*of)(const char *fname)); + +/*-- export.c --*/ +void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp); + +/*-- delete.c --*/ +int gpgsm_delete (CTRL ctrl, STRLIST names); + +/*-- verify.c --*/ +int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp); + +/*-- sign.c --*/ +int gpgsm_get_default_cert (KsbaCert *r_cert); +int gpgsm_sign (CTRL ctrl, CERTLIST signerlist, + int data_fd, int detached, FILE *out_fp); + +/*-- encrypt.c --*/ +int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp); + +/*-- decrypt.c --*/ +int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp); + +/*-- certreqgen.c --*/ +int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp); + +/*-- call-agent.c --*/ +int gpgsm_agent_pksign (const char *keygrip, + unsigned char *digest, + size_t digestlen, + int digestalgo, + char **r_buf, size_t *r_buflen); +int gpgsm_agent_pkdecrypt (const char *keygrip, + KsbaConstSexp ciphertext, + char **r_buf, size_t *r_buflen); +int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey); +int gpgsm_agent_istrusted (KsbaCert cert); +int gpgsm_agent_havekey (const char *hexkeygrip); +int gpgsm_agent_marktrusted (KsbaCert cert); +int gpgsm_agent_learn (void); +int gpgsm_agent_passwd (const char *hexkeygrip); + +/*-- call-dirmngr.c --*/ +int gpgsm_dirmngr_isvalid (KsbaCert cert); +int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, + void (*cb)(void*, KsbaCert), void *cb_value); +int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, + int argc, char **argv); + + + + + +#endif /*GPGSM_H*/ diff --git a/sm/import.c b/sm/import.c new file mode 100644 index 000000000..17dc3d66c --- /dev/null +++ b/sm/import.c @@ -0,0 +1,349 @@ +/* import.c - Import certificates + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +struct stats_s { + unsigned long count; + unsigned long imported; + unsigned long unchanged; + unsigned long not_imported; +}; + + + +static void +print_imported_status (CTRL ctrl, KsbaCert cert) +{ + char *fpr; + + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL); + xfree (fpr); +} + + +/* Print an IMPORT_PROBLEM status. REASON is one of: + 0 := "No specific reason given". + 1 := "Invalid Certificate". + 2 := "Issuer Certificate missing". + 3 := "Certificate Chain too long". + 4 := "Error storing certificate". +*/ +static void +print_import_problem (CTRL ctrl, KsbaCert cert, int reason) +{ + char *fpr = NULL; + char buf[25]; + int i; + + sprintf (buf, "%d", reason); + if (cert) + { + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + /* detetect an error (all high) value */ + for (i=0; fpr[i] == 'F'; i++) + ; + if (!fpr[i]) + { + xfree (fpr); + fpr = NULL; + } + } + gpgsm_status2 (ctrl, STATUS_IMPORT_PROBLEM, buf, fpr, NULL); + xfree (fpr); +} + + +void +print_imported_summary (CTRL ctrl, struct stats_s *stats) +{ + char buf[14*25]; + + if (!opt.quiet) + { + log_info (_("total number processed: %lu\n"), stats->count); + if (stats->imported) + { + log_info (_(" imported: %lu"), stats->imported ); + log_printf ("\n"); + } + if (stats->unchanged) + log_info (_(" unchanged: %lu\n"), stats->unchanged); + if (stats->not_imported) + log_info (_(" not imported: %lu\n"), stats->not_imported); + } + + sprintf (buf, "%lu 0 %lu 0 %lu 0 0 0 0 0 0 0 0 %lu", + stats->count, + stats->imported, + stats->unchanged, + stats->not_imported + ); + gpgsm_status (ctrl, STATUS_IMPORT_RES, buf); +} + + + +static void +check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth) +{ + int rc; + + stats->count++; + if ( depth >= 50 ) + { + log_error (_("certificate chain too long\n")); + stats->not_imported++; + print_import_problem (ctrl, cert, 3); + return; + } + + rc = gpgsm_basic_cert_check (cert); + if (!rc) + { + int existed; + + if (!keydb_store_cert (cert, 0, &existed)) + { + KsbaCert next = NULL; + + if (!existed) + { + print_imported_status (ctrl, cert); + stats->imported++; + } + else + stats->unchanged++; + + if (opt.verbose > 1 && existed) + { + if (depth) + log_info ("issuer certificate already in DB\n"); + else + log_info ("certificate already in DB\n"); + } + else if (opt.verbose && !existed) + { + if (depth) + log_info ("issuer certificate imported\n"); + else + log_info ("certificate imported\n"); + } + /* Now lets walk up the chain and import all certificates up + the chain.*/ + else if (!gpgsm_walk_cert_chain (cert, &next)) + { + check_and_store (ctrl, stats, next, depth+1); + ksba_cert_release (next); + } + } + else + { + log_error (_("error storing certificate\n")); + stats->not_imported++; + print_import_problem (ctrl, cert, 4); + } + } + else + { + log_error (_("basic certificate checks failed - not imported\n")); + stats->not_imported++; + print_import_problem (ctrl, cert, + gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 : + gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0); + } +} + + + + +static int +import_one (CTRL ctrl, struct stats_s *stats, int in_fd) +{ + int rc; + Base64Context b64reader = NULL; + KsbaReader reader; + KsbaCert cert = NULL; + KsbaCMS cms = NULL; + FILE *fp = NULL; + KsbaContentType ct; + + fp = fdopen ( dup (in_fd), "rb"); + if (!fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("fdopen() failed: %s\n", strerror (errno)); + goto leave; + } + + rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); + if (rc) + { + log_error ("can't create reader: %s\n", gpg_strerror (rc)); + goto leave; + } + + ct = ksba_cms_identify (reader); + if (ct == KSBA_CT_SIGNED_DATA) + { /* This is probably a signed-only message - import the certs */ + KsbaStopReason stopreason; + int i; + + cms = ksba_cms_new (); + if (!cms) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + rc = ksba_cms_set_reader_writer (cms, reader, NULL); + if (rc) + { + log_error ("ksba_cms_set_reader_writer failed: %s\n", + ksba_strerror (rc)); + rc = map_ksba_err (rc); + goto leave; + } + + + do + { + rc = ksba_cms_parse (cms, &stopreason); + if (rc) + { + log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (rc)); + rc = map_ksba_err (rc); + goto leave; + } + + if (stopreason == KSBA_SR_BEGIN_DATA) + log_info ("not a certs-only message\n"); + } + while (stopreason != KSBA_SR_READY); + + for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) + { + check_and_store (ctrl, stats, cert, 0); + ksba_cert_release (cert); + cert = NULL; + } + if (!i) + log_error ("no certificate found\n"); + } + else if (ct == KSBA_CT_NONE) + { /* Failed to identify this message - assume a certificate */ + + cert = ksba_cert_new (); + if (!cert) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + rc = ksba_cert_read_der (cert, reader); + if (rc) + { + rc = map_ksba_err (rc); + goto leave; + } + + check_and_store (ctrl, stats, cert, 0); + } + else + { + log_error ("can't extract certificates from input\n"); + rc = gpg_error (GPG_ERR_NO_DATA); + } + + leave: + ksba_cms_release (cms); + ksba_cert_release (cert); + gpgsm_destroy_reader (b64reader); + if (fp) + fclose (fp); + return rc; +} + + +int +gpgsm_import (CTRL ctrl, int in_fd) +{ + int rc; + struct stats_s stats; + + memset (&stats, 0, sizeof stats); + rc = import_one (ctrl, &stats, in_fd); + print_imported_summary (ctrl, &stats); + /* If we never printed an error message do it now so that a command + line invocation will return with an error (log_error keeps a + global errorcount) */ + if (rc && !log_get_errorcount (0)) + log_error (_("error importing certificate: %s\n"), gpg_strerror (rc)); + return rc; +} + + +int +gpgsm_import_files (CTRL ctrl, int nfiles, char **files, + int (*of)(const char *fname)) +{ + int rc = 0; + struct stats_s stats; + + memset (&stats, 0, sizeof stats); + + if (!nfiles) + rc = import_one (ctrl, &stats, 0); + else + { + for (; nfiles && !rc ; nfiles--, files++) + { + int fd = of (*files); + rc = import_one (ctrl, &stats, fd); + close (fd); + if (rc == -1) + rc = 0; + } + } + print_imported_summary (ctrl, &stats); + /* If we never printed an error message do it now so that a command + line invocation will return with an error (log_error keeps a + global errorcount) */ + if (rc && !log_get_errorcount (0)) + log_error (_("error importing certificate: %s\n"), gpg_strerror (rc)); + return rc; +} + + diff --git a/sm/keydb.c b/sm/keydb.c new file mode 100644 index 000000000..fe6556549 --- /dev/null +++ b/sm/keydb.c @@ -0,0 +1,1282 @@ +/* keydb.c - key database dispatcher + * 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 <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 "gpgsm.h" +#include "../kbx/keybox.h" +#include "keydb.h" +#include "i18n.h" + +#define DIRSEP_C '/' + +static int active_handles; + +typedef enum { + KEYDB_RESOURCE_TYPE_NONE = 0, + KEYDB_RESOURCE_TYPE_KEYBOX +} KeydbResourceType; +#define MAX_KEYDB_RESOURCES 20 + +struct resource_item { + KeydbResourceType type; + union { + KEYBOX_HANDLE kr; + } u; + void *token; + int secret; + DOTLOCK lockhandle; +}; + +static struct resource_item all_resources[MAX_KEYDB_RESOURCES]; +static int used_resources; + +struct keydb_handle { + int locked; + int found; + int current; + int is_ephemeral; + 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 keybox file). + * The first keybox which is added by this function is + * created if it does not exist. + * Note: this function may be called before secure memory is + * available. + */ +int +keydb_add_resource (const char *url, int force, int secret) +{ + static int any_secret, any_public; + const char *resname = url; + char *filename = NULL; + int rc = 0; + FILE *fp; + KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; + const char *created_fname = NULL; + + /* Do we have an URL? + gnupg-kbx:filename := this is a plain keybox + filename := See what is is, but create as plain keybox. + */ + if (strlen (resname) > 10) + { + if (!strncmp (resname, "gnupg-kbx:", 10) ) + { + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + resname += 10; + } +#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) + else if (strchr (resname, ':')) + { + log_error ("invalid key resource URL `%s'\n", url ); + rc = gpg_error (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 *fp2 = fopen( filename, "rb" ); + + if (fp2) { + u32 magic; + + /* FIXME: check for the keybox magic */ + if (fread( &magic, 4, 1, fp2) == 1 ) + { + if (magic == 0x13579ace || magic == 0xce9a5713) + ; /* GDBM magic - no more support */ + else + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + } + else /* maybe empty: assume ring */ + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + fclose (fp2); + } + else /* no file yet: create ring */ + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + } + + switch (rt) + { + case KEYDB_RESOURCE_TYPE_NONE: + log_error ("unknown type of key resource `%s'\n", url ); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + + case KEYDB_RESOURCE_TYPE_KEYBOX: + fp = fopen (filename, "rb"); + if (!fp && !force) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } + + if (!fp) + { /* no file */ +#if 0 /* no autocreate of the homedirectory yet */ + { + char *last_slash_in_filename; + + 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 in this case the process will be + terminated, so that on the next invocation can + read the options file in on startup */ + try_make_homedir (filename); + rc = gpg_error (GPG_ERR_FILE_OPEN_ERROR); + *last_slash_in_filename = DIRSEP_C; + goto leave; + } + *last_slash_in_filename = DIRSEP_C; + } +#endif + fp = fopen (filename, "w"); + if (!fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + log_error (_("error creating keybox `%s': %s\n"), + filename, strerror(errno)); + goto leave; + } + + if (!opt.quiet) + log_info (_("keybox `%s' created\n"), filename); + created_fname = filename; + } + fclose (fp); + fp = NULL; + /* now register the file */ + { + + void *token = keybox_register_file (filename, secret); + if (!token) + ; /* already registered - ignore it */ + else if (used_resources >= MAX_KEYDB_RESOURCES) + rc = gpg_error (GPG_ERR_RESOURCE_LIMIT); + else + { + 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; + + all_resources[used_resources].lockhandle + = create_dotlock (filename); + if (!all_resources[used_resources].lockhandle) + log_fatal ( _("can't create lock for `%s'\n"), filename); + + used_resources++; + } + } + break; + default: + log_error ("resource type of `%s' not supported\n", url); + rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + 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_KEYBOX: + 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].lockhandle = all_resources[i].lockhandle; + hd->active[j].u.kr = keybox_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_KEYBOX: + keybox_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_KEYBOX: + s = keybox_get_resource_name (hd->active[idx].u.kr); + break; + } + + return s? s: ""; +} + +/* Switch the handle into ephemeral mode and return the orginal value. */ +int +keydb_set_ephemeral (KEYDB_HANDLE hd, int yes) +{ + int i; + + if (!hd) + return 0; + + yes = !!yes; + if (hd->is_ephemeral != yes) + { + for (i=0; i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + keybox_set_ephemeral (hd->active[i].u.kr, yes); + break; + } + } + } + + i = hd->is_ephemeral; + hd->is_ephemeral = yes; + return i; +} + + + +static int +lock_all (KEYDB_HANDLE hd) +{ + int i, rc = 0; + + /* Fixme: This locking scheme may lead to deadlock if the resources + are not added in the same sequence by all processes. We are + cuurently only allowing one resource so it is not a problem. */ + for (i=0; i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + if (hd->active[i].lockhandle) + rc = make_dotlock (hd->active[i].lockhandle, -1); + break; + } + if (rc) + 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_KEYBOX: + if (hd->active[i].lockhandle) + release_dotlock (hd->active[i].lockhandle); + 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_KEYBOX: + if (hd->active[i].lockhandle) + release_dotlock (hd->active[i].lockhandle); + break; + } + } + hd->locked = 0; +} + + +#if 0 +/* + * Return the last found keybox. 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 G10ERR_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 = G10ERR_GENERAL; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_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 G10ERR_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 = G10ERR_GENERAL; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_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 G10ERR_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 G10ERR_GENERAL; + + rc = lock_all (hd); + if (rc) + return rc; + + switch (hd->active[idx].type) { + case KEYDB_RESOURCE_TYPE_NONE: + rc = G10ERR_GENERAL; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_insert_keyblock (hd->active[idx].u.kr, kb); + break; + } + + unlock_all (hd); + return rc; +} + +#endif /*disabled code*/ + + + +/* + Return the last found keybox. 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_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) +{ + int rc = 0; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + 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_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert); + break; + } + + return rc; +} + +/* + * Insert a new Certificate into one of the resources. + */ +int +keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) +{ + int rc = -1; + int idx; + char digest[20]; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + 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_error (GPG_ERR_GENERAL); + + rc = lock_all (hd); + if (rc) + return rc; + + gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ + + switch (hd->active[idx].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = gpg_error (GPG_ERR_GENERAL); + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest); + break; + } + + unlock_all (hd); + return rc; +} + + + +/* update the current keyblock with KB */ +int +keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert) +{ + int rc = 0; + char digest[20]; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + 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; + + gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = gpg_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest); + break; + } + + unlock_all (hd); + return rc; +} + + +/* + * The current keyblock or cert will be deleted. + */ +int +keydb_delete (KEYDB_HANDLE hd) +{ + int rc = -1; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + 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_error (GPG_ERR_GENERAL); + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_delete (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_error (GPG_ERR_INV_VALUE); + + 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_KEYBOX: + if (keybox_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; + + 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_KEYBOX: +/* rc = keybox_rebuild_cache (all_resources[i].token); */ +/* if (rc) */ +/* log_error (_("failed to rebuild keybox cache: %s\n"), */ +/* g10_errstr (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_error (GPG_ERR_INV_VALUE); + + 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_KEYBOX: + rc = keybox_search_reset (hd->active[i].u.kr); + break; + } + } + return rc; /* fixme: we need to map error codes or share them with + all modules*/ +} + +/* + * 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_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) +{ + int rc = -1; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + 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_KEYBOX: + rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); + 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, 20); + return keydb_search (hd, &desc, 1); +} + +int +keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer) +{ + KEYDB_SEARCH_DESC desc; + int rc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_ISSUER; + desc.u.name = issuer; + rc = keydb_search (hd, &desc, 1); + return rc; +} + +int +keydb_search_issuer_sn (KEYDB_HANDLE hd, + const char *issuer, KsbaConstSexp serial) +{ + KEYDB_SEARCH_DESC desc; + int rc; + const unsigned char *s; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN; + s = serial; + if (*s !='(') + return gpg_error (GPG_ERR_INV_VALUE); + s++; + for (desc.snlen = 0; digitp (s); s++) + desc.snlen = 10*desc.snlen + atoi_1 (s); + if (*s !=':') + return gpg_error (GPG_ERR_INV_VALUE); + desc.sn = s+1; + desc.u.name = issuer; + rc = keydb_search (hd, &desc, 1); + return rc; +} + +int +keydb_search_subject (KEYDB_HANDLE hd, const char *name) +{ + KEYDB_SEARCH_DESC desc; + int rc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_SUBJECT; + desc.u.name = name; + rc = keydb_search (hd, &desc, 1); + return rc; +} + + +static int +hextobyte (const unsigned char *s) +{ + int c; + + if( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if ( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if ( *s >= 'a' && *s <= 'f' ) + c = 16 * (10 + *s - 'a'); + else + return -1; + s++; + if ( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if ( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if ( *s >= 'a' && *s <= 'f' ) + c += 10 + *s - 'a'; + else + return -1; + return c; +} + + +static int +classify_user_id (const char *name, + KEYDB_SEARCH_DESC *desc, + int *force_exact ) +{ + const char *s; + int hexprefix = 0; + int hexlength; + int mode = 0; + + /* clear the structure so that the mode field is set to zero unless + * we set it to the correct value right at the end of this function */ + memset (desc, 0, sizeof *desc); + *force_exact = 0; + /* skip leading spaces. Fixme: what about trailing white space? */ + for(s = name; *s && spacep (s); s++ ) + ; + + switch (*s) + { + case 0: /* empty string is an error */ + return 0; + + case '.': /* an email address, compare from end */ + mode = KEYDB_SEARCH_MODE_MAILEND; + s++; + desc->u.name = s; + break; + + case '<': /* an email address */ + mode = KEYDB_SEARCH_MODE_MAIL; + s++; + desc->u.name = s; + break; + + case '@': /* part of an email address */ + mode = KEYDB_SEARCH_MODE_MAILSUB; + s++; + desc->u.name = s; + break; + + case '=': /* exact compare */ + mode = KEYDB_SEARCH_MODE_EXACT; + s++; + desc->u.name = s; + break; + + case '*': /* case insensitive substring search */ + mode = KEYDB_SEARCH_MODE_SUBSTR; + s++; + desc->u.name = s; + break; + + case '+': /* compare individual words */ + mode = KEYDB_SEARCH_MODE_WORDS; + s++; + desc->u.name = s; + break; + + case '/': /* subject's DN */ + s++; + if (!*s || spacep (s)) + return 0; /* no DN or prefixed with a space */ + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_SUBJECT; + break; + + case '#': + { + const char *si; + + s++; + if ( *s == '/') + { /* "#/" indicates an issuer's DN */ + s++; + if (!*s || spacep (s)) + return 0; /* no DN or prefixed with a space */ + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_ISSUER; + } + else + { /* serialnumber + optional issuer ID */ + for (si=s; *si && *si != '/'; si++) + { + if (!strchr("01234567890abcdefABCDEF", *si)) + return 0; /* invalid digit in serial number*/ + } + desc->sn = s; + desc->snlen = -1; + if (!*si) + mode = KEYDB_SEARCH_MODE_SN; + else + { + s = si+1; + if (!*s || spacep (s)) + return 0; /* no DN or prefixed with a space */ + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_ISSUER_SN; + } + } + } + break; + + case ':': /*Unified fingerprint */ + { + const char *se, *si; + int i; + + se = strchr (++s,':'); + if (!se) + return 0; + for (i=0,si=s; si < se; si++, i++ ) + { + if (!strchr("01234567890abcdefABCDEF", *si)) + return 0; /* invalid digit */ + } + if (i != 32 && i != 40) + return 0; /* invalid length of fpr*/ + for (i=0,si=s; si < se; i++, si +=2) + desc->u.fpr[i] = hextobyte(si); + for (; i < 20; i++) + desc->u.fpr[i]= 0; + s = se + 1; + mode = KEYDB_SEARCH_MODE_FPR; + } + break; + + default: + if (s[0] == '0' && s[1] == 'x') + { + hexprefix = 1; + s += 2; + } + + hexlength = strspn(s, "0123456789abcdefABCDEF"); + if (hexlength >= 8 && s[hexlength] =='!') + { + *force_exact = 1; + hexlength++; /* just for the following check */ + } + + /* check if a hexadecimal number is terminated by EOS or blank */ + if (hexlength && s[hexlength] && !spacep (s+hexlength)) + { + if (hexprefix) /* a "0x" prefix without correct */ + return 0; /* termination is an error */ + /* The first chars looked like a hex number, but really is + not */ + hexlength = 0; + } + + if (*force_exact) + hexlength--; /* remove the bang */ + + if (hexlength == 8 + || (!hexprefix && hexlength == 9 && *s == '0')) + { /* short keyid */ + unsigned long kid; + if (hexlength == 9) + s++; + kid = strtoul( s, NULL, 16 ); + desc->u.kid[4] = kid >> 24; + desc->u.kid[5] = kid >> 16; + desc->u.kid[6] = kid >> 8; + desc->u.kid[7] = kid; + mode = KEYDB_SEARCH_MODE_SHORT_KID; + } + else if (hexlength == 16 + || (!hexprefix && hexlength == 17 && *s == '0')) + { /* complete keyid */ + unsigned long kid0, kid1; + char buf[9]; + if (hexlength == 17) + s++; + mem2str(buf, s, 9 ); + kid0 = strtoul (buf, NULL, 16); + kid1 = strtoul (s+8, NULL, 16); + desc->u.kid[0] = kid0 >> 24; + desc->u.kid[1] = kid0 >> 16; + desc->u.kid[2] = kid0 >> 8; + desc->u.kid[3] = kid0; + desc->u.kid[4] = kid1 >> 24; + desc->u.kid[5] = kid1 >> 16; + desc->u.kid[6] = kid1 >> 8; + desc->u.kid[7] = kid1; + mode = KEYDB_SEARCH_MODE_LONG_KID; + } + else if (hexlength == 32 + || (!hexprefix && hexlength == 33 && *s == '0')) + { /* md5 fingerprint */ + int i; + if (hexlength == 33) + s++; + memset(desc->u.fpr+16, 0, 4); + for (i=0; i < 16; i++, s+=2) + { + int c = hextobyte(s); + if (c == -1) + return 0; + desc->u.fpr[i] = c; + } + mode = KEYDB_SEARCH_MODE_FPR16; + } + else if (hexlength == 40 + || (!hexprefix && hexlength == 41 && *s == '0')) + { /* sha1/rmd160 fingerprint */ + int i; + if (hexlength == 41) + s++; + for (i=0; i < 20; i++, s+=2) + { + int c = hextobyte(s); + if (c == -1) + return 0; + desc->u.fpr[i] = c; + } + mode = KEYDB_SEARCH_MODE_FPR20; + } + else if (!hexprefix) + { + /* The fingerprint in an X.509 listing is often delimited by + colons, so we try to single this case out. */ + mode = 0; + hexlength = strspn (s, ":0123456789abcdefABCDEF"); + if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength))) + { + int i; + + for (i=0; i < 20; i++, s += 3) + { + int c = hextobyte(s); + if (c == -1 || (i < 19 && s[2] != ':')) + break; + desc->u.fpr[i] = c; + } + if (i == 20) + mode = KEYDB_SEARCH_MODE_FPR20; + } + if (!mode) /* default is substring search */ + { + *force_exact = 0; + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_SUBSTR; + } + } + else + { /* hex number with a prefix but a wrong length */ + return 0; + } + } + + desc->mode = mode; + return mode; +} + + +int +keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc) +{ + int dummy; + KEYDB_SEARCH_DESC dummy_desc; + + if (!desc) + desc = &dummy_desc; + + if (!classify_user_id (name, desc, &dummy)) + return gpg_error (GPG_ERR_INV_NAME); + return 0; +} + + +/* Store the certificate in the key DB but make sure that it does not + already exists. We do this simply by comparing the fingerprint. + If EXISTED is not NULL it will be set to true if the certificate + was already in the DB. */ +int +keydb_store_cert (KsbaCert cert, int ephemeral, int *existed) +{ + KEYDB_HANDLE kh; + int rc; + unsigned char fpr[20]; + + if (existed) + *existed = 0; + + if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL)) + { + log_error (_("failed to get the fingerprint\n")); + return gpg_error (GPG_ERR_GENERAL); + } + + kh = keydb_new (0); + if (!kh) + { + log_error (_("failed to allocate keyDB handle\n")); + return gpg_error (GPG_ERR_ENOMEM);; + } + + if (ephemeral) + keydb_set_ephemeral (kh, 1); + + rc = keydb_search_fpr (kh, fpr); + if (rc != -1) + { + keydb_release (kh); + if (!rc) + { + if (existed) + *existed = 1; + return 0; /* okay */ + } + log_error (_("problem looking for existing certificate: %s\n"), + gpg_strerror (rc)); + return rc; + } + + rc = keydb_locate_writable (kh, 0); + if (rc) + { + log_error (_("error finding writable keyDB: %s\n"), gpg_strerror (rc)); + keydb_release (kh); + return rc; + } + + rc = keydb_insert_cert (kh, cert); + if (rc) + { + log_error (_("error storing certificate: %s\n"), gpg_strerror (rc)); + keydb_release (kh); + return rc; + } + keydb_release (kh); + return 0; +} + + + diff --git a/sm/keylist.c b/sm/keylist.c new file mode 100644 index 000000000..634bda292 --- /dev/null +++ b/sm/keylist.c @@ -0,0 +1,617 @@ +/* keylist.c + * 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 <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" + +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +struct list_external_parm_s { + FILE *fp; + int print_header; + int with_colons; + int with_chain; +}; + + + +static void +print_key_data (KsbaCert cert, FILE *fp) +{ +#if 0 + int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; + int i; + + for(i=0; i < n; i++ ) + { + fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) ); + mpi_print(stdout, pk->pkey[i], 1 ); + putchar(':'); + putchar('\n'); + } +#endif +} + +static void +print_capabilities (KsbaCert cert, FILE *fp) +{ + KsbaError err; + unsigned int use; + + err = ksba_cert_get_key_usage (cert, &use); + if (err == KSBA_No_Data) + { + putc ('e', fp); + putc ('s', fp); + putc ('c', fp); + putc ('E', fp); + putc ('S', fp); + putc ('C', fp); + return; + } + if (err) + { + log_error (_("error getting key usage information: %s\n"), + ksba_strerror (err)); + return; + } + + if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT))) + putc ('e', fp); + if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) + putc ('s', fp); + if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN)) + putc ('c', fp); + if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT))) + putc ('E', fp); + if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) + putc ('S', fp); + if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN)) + putc ('C', fp); +} + + +static void +print_time (time_t t, FILE *fp) +{ + if (!t) + ; + else if ( t == (time_t)(-1) ) + putc ('?', fp); + else + fprintf (fp, "%lu", (unsigned long)t); +} + + +/* return an allocated string with the email address extracted from a + DN */ +static char * +email_kludge (const char *name) +{ + const unsigned char *p; + unsigned char *buf; + int n; + + if (strncmp (name, "1.2.840.113549.1.9.1=#", 22)) + return NULL; + /* This looks pretty much like an email address in the subject's DN + we use this to add an additional user ID entry. This way, + openSSL generated keys get a nicer and usable listing */ + name += 22; + for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++) + ; + if (*p != '#' || !n) + return NULL; + buf = xtrymalloc (n+3); + if (!buf) + return NULL; /* oops, out of core */ + *buf = '<'; + for (n=1, p=name; *p != '#'; p +=2, n++) + buf[n] = xtoi_2 (p); + buf[n++] = '>'; + buf[n] = 0; + return buf; +} + + + + +/* List one certificate in colon mode */ +static void +list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) +{ + int idx, trustletter = 0; + char *p; + KsbaSexp sexp; + char *fpr; + + fputs (have_secret? "crs:":"crt:", fp); + trustletter = 0; +#if 0 + if (is_not_valid (cert)) + putc ('i', fp); + else if ( is_revoked (cert) ) + putc ('r', fp); + else if ( has_expired (cert)) + putcr ('e', fp); + else +#endif + { + trustletter = '?'; /*get_validity_info ( pk, NULL );*/ + putc (trustletter, fp); + } + + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + fprintf (fp, ":%u:%d:%s:", + /*keylen_of_cert (cert)*/1024, + /* pubkey_algo_of_cert (cert)*/1, + fpr+24); + + /* we assume --fixed-list-mode for gpgsm */ + print_time ( ksba_cert_get_validity (cert, 0), fp); + putc (':', fp); + print_time ( ksba_cert_get_validity (cert, 1), fp); + putc (':', fp); + /* field 8, serial number: */ + if ((sexp = ksba_cert_get_serial (cert))) + { + int len; + const unsigned char *s = sexp; + + if (*s == '(') + { + s++; + for (len=0; *s && *s != ':' && digitp (s); s++) + len = len*10 + atoi_1 (s); + if (*s == ':') + for (s++; len; len--, s++) + fprintf (fp,"%02X", *s); + } + xfree (sexp); + } + putc (':', fp); + /* field 9, ownertrust - not used here */ + putc (':', fp); + /* field 10, old user ID - we use it here for the issuer DN */ + if ((p = ksba_cert_get_issuer (cert,0))) + { + print_sanitized_string (fp, p, ':'); + xfree (p); + } + putc (':', fp); + /* field 11, signature class - not used */ + putc (':', fp); + /* field 12, capabilities: */ + print_capabilities (cert, fp); + putc (':', fp); + putc ('\n', fp); + + /* FPR record */ + fprintf (fp, "fpr:::::::::%s:::", fpr); + xfree (fpr); fpr = NULL; + /* print chaining ID (field 13)*/ + { + KsbaCert next; + + if (!gpgsm_walk_cert_chain (cert, &next)) + { + p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); + fputs (p, fp); + xfree (p); + ksba_cert_release (next); + } + } + putc (':', fp); + putc ('\n', fp); + + + if (opt.with_key_data) + { + if ( (p = gpgsm_get_keygrip_hexstring (cert))) + { + fprintf (fp, "grp:::::::::%s:\n", p); + xfree (p); + } + print_key_data (cert, fp); + } + + for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++) + { + fprintf (fp, "uid:%c::::::::", trustletter); + print_sanitized_string (fp, p, ':'); + putc (':', fp); + putc (':', fp); + putc ('\n', fp); + if (!idx) + { + /* It would be better to get the faked email address from + the keydb. But as long as we don't have a way to pass + the meta data back, we just check it the same way as the + code used to create the keybox meta data does */ + char *pp = email_kludge (p); + if (pp) + { + fprintf (fp, "uid:%c::::::::", trustletter); + print_sanitized_string (fp, pp, ':'); + putc (':', fp); + putc (':', fp); + putc ('\n', fp); + xfree (pp); + } + } + xfree (p); + } +} + + +/* List one certificate in standard mode */ +static void +list_cert_std (KsbaCert cert, FILE *fp, int have_secret) +{ + KsbaError kerr; + KsbaSexp sexp; + char *dn; + time_t t; + int idx; + int is_ca, chainlen; + unsigned int kusage; + char *string, *p; + + sexp = ksba_cert_get_serial (cert); + fputs ("Serial number: ", fp); + gpgsm_print_serial (fp, sexp); + ksba_free (sexp); + putc ('\n', fp); + + dn = ksba_cert_get_issuer (cert, 0); + fputs (" Issuer: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++) + { + fputs (" aka: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + } + + dn = ksba_cert_get_subject (cert, 0); + fputs (" Subject: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++) + { + fputs (" aka: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + } + + t = ksba_cert_get_validity (cert, 0); + fputs (" validity: ", fp); + gpgsm_print_time (fp, t); + fputs (" through ", fp); + t = ksba_cert_get_validity (cert, 1); + gpgsm_print_time (fp, t); + putc ('\n', fp); + + kerr = ksba_cert_get_key_usage (cert, &kusage); + if (kerr != KSBA_No_Data) + { + fputs (" key usage:", fp); + if (kerr) + fprintf (fp, " [error: %s]", ksba_strerror (kerr)); + else + { + if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE)) + fputs (" digitalSignature", fp); + if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION)) + fputs (" nonRepudiation", fp); + if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) + fputs (" keyEncipherment", fp); + if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT)) + fputs (" dataEncipherment", fp); + if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT)) + fputs (" keyAgreement", fp); + if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN)) + fputs (" certSign", fp); + if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN)) + fputs (" crlSign", fp); + if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY)) + fputs (" encipherOnly", fp); + if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY)) + fputs (" decipherOnly", fp); + } + putc ('\n', fp); + } + + kerr = ksba_cert_get_cert_policies (cert, &string); + if (kerr != KSBA_No_Data) + { + fputs (" policies: ", fp); + if (kerr) + fprintf (fp, "[error: %s]", ksba_strerror (kerr)); + else + { + for (p=string; *p; p++) + { + if (*p == '\n') + *p = ','; + } + print_sanitized_string (fp, string, 0); + xfree (string); + } + putc ('\n', fp); + } + + kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen); + if (kerr || is_ca) + { + fputs (" chain length: ", fp); + if (kerr) + fprintf (fp, "[error: %s]", ksba_strerror (kerr)); + else if (chainlen == -1) + fputs ("unlimited", fp); + else + fprintf (fp, "%d", chainlen); + putc ('\n', fp); + } + + + dn = gpgsm_get_fingerprint_string (cert, 0); + fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); + xfree (dn); +} + +/* Same as standard mode mode list all certifying certts too */ +static void +list_cert_chain (KsbaCert cert, FILE *fp) +{ + KsbaCert next = NULL; + + list_cert_std (cert, fp, 0); + ksba_cert_ref (cert); + while (!gpgsm_walk_cert_chain (cert, &next)) + { + ksba_cert_release (cert); + fputs ("Certified by\n", fp); + list_cert_std (next, fp, 0); + cert = next; + } + ksba_cert_release (cert); + putc ('\n', fp); +} + + + +/* List all internal keys or just the key given as NAMES. + */ +static void +list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) +{ + KEYDB_HANDLE hd; + KEYDB_SEARCH_DESC *desc = NULL; + STRLIST sl; + int ndesc; + KsbaCert cert = NULL; + int rc=0; + const char *lastresname, *resname; + int have_secret; + + hd = keydb_new (0); + if (!hd) + { + log_error ("keydb_new failed\n"); + goto leave; + } + + if (!names) + ndesc = 1; + else + { + for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) + ; + } + + desc = xtrycalloc (ndesc, sizeof *desc); + if (!ndesc) + { + log_error ("out of core\n"); + goto leave; + } + + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + else + { + for (ndesc=0, sl=names; sl; sl = sl->next) + { + rc = keydb_classify_name (sl->d, desc+ndesc); + if (rc) + { + log_error ("key `%s' not found: %s\n", + sl->d, gpg_strerror (rc)); + rc = 0; + } + else + ndesc++; + } + + } + + /* 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 */ + + lastresname = NULL; + while (!(rc = keydb_search (hd, desc, ndesc))) + { + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + + rc = keydb_get_cert (hd, &cert); + if (rc) + { + log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + resname = keydb_get_resource_name (hd); + + if (lastresname != resname ) + { + int i; + + if (ctrl->no_server) + { + fprintf (fp, "%s\n", resname ); + for (i=strlen(resname); i; i-- ) + putchar('-'); + putc ('\n', fp); + lastresname = resname; + } + } + + have_secret = 0; + if (mode) + { + char *p = gpgsm_get_keygrip_hexstring (cert); + if (p) + { + if (!gpgsm_agent_havekey (p)) + have_secret = 1; + xfree (p); + } + } + + if (!mode + || ((mode & 1) && !have_secret) + || ((mode & 2) && have_secret) ) + { + if (ctrl->with_colons) + list_cert_colon (cert, fp, have_secret); + else if (ctrl->with_chain) + list_cert_chain (cert, fp); + else + { + list_cert_std (cert, fp, have_secret); + putc ('\n', fp); + } + } + ksba_cert_release (cert); + cert = NULL; + } + if (rc && rc != -1) + log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); + + leave: + ksba_cert_release (cert); + xfree (desc); + keydb_release (hd); +} + + + +static void +list_external_cb (void *cb_value, KsbaCert cert) +{ + struct list_external_parm_s *parm = cb_value; + + if (keydb_store_cert (cert, 1, NULL)) + log_error ("error storing certificate as ephemeral\n"); + + if (parm->print_header) + { + const char *resname = "[external keys]"; + int i; + + fprintf (parm->fp, "%s\n", resname ); + for (i=strlen(resname); i; i-- ) + putchar('-'); + putc ('\n', parm->fp); + parm->print_header = 0; + } + + if (parm->with_colons) + list_cert_colon (cert, parm->fp, 0); + else if (parm->with_chain) + list_cert_chain (cert, parm->fp); + else + { + list_cert_std (cert, parm->fp, 0); + putc ('\n', parm->fp); + } +} + + +/* List external keys similar to internal one. Note: mode does not + make sense here because it would be unwise to list external secret + keys */ +static void +list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) +{ + int rc; + struct list_external_parm_s parm; + + parm.fp = fp; + parm.print_header = ctrl->no_server; + parm.with_colons = ctrl->with_colons; + parm.with_chain = ctrl->with_chain; + + rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm); + if (rc) + log_error ("listing external keys failed: %s\n", gpg_strerror (rc)); +} + +/* List all keys or just the key given as NAMES. + MODE controls the operation mode: + Bit 0-2: + 0 = list all public keys but don't flag secret ones + 1 = list only public keys + 2 = list only secret keys + 3 = list secret and public keys + Bit 6: list internal keys + Bit 7: list external keys + */ +void +gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) +{ + if ((mode & (1<<6))) + list_internal_keys (ctrl, names, fp, (mode & 3)); + if ((mode & (1<<7))) + list_external_keys (ctrl, names, fp); +} diff --git a/sm/server.c b/sm/server.c new file mode 100644 index 000000000..dda150964 --- /dev/null +++ b/sm/server.c @@ -0,0 +1,1070 @@ +/* server.c - Server mode and main entry point + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <unistd.h> + +#include <assuan.h> + +#include "gpgsm.h" + +#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) + + +/* The filepointer for status message used in non-server mode */ +static FILE *statusfp; + +/* Data used to assuciate an Assuan context with local server data */ +struct server_local_s { + ASSUAN_CONTEXT assuan_ctx; + int message_fd; + int list_internal; + int list_external; + CERTLIST recplist; + CERTLIST signerlist; +}; + + + +/* note, that it is sufficient to allocate the target string D as + long as the source string S, i.e.: strlen(s)+1; */ +static void +strcpy_escaped_plus (char *d, const unsigned char *s) +{ + while (*s) + { + if (*s == '%' && s[1] && s[2]) + { + s++; + *d++ = xtoi_2 ( s); + s += 2; + } + else if (*s == '+') + *d++ = ' ', s++; + else + *d++ = *s++; + } + *d = 0; +} + + + + +/* Check whether the option NAME appears in LINE */ +static int +has_option (const char *line, const char *name) +{ + const char *s; + int n = strlen (name); + + s = strstr (line, name); + return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); +} + + +static void +close_message_fd (CTRL ctrl) +{ + if (ctrl->server_local->message_fd != -1) + { + close (ctrl->server_local->message_fd); + ctrl->server_local->message_fd = -1; + } +} + + +static int +option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + if (!strcmp (key, "include-certs")) + { + int i = *value? atoi (value) : -1; + if (ctrl->include_certs < -2) + return ASSUAN_Parameter_Error; + ctrl->include_certs = i; + } + else if (!strcmp (key, "display")) + { + if (opt.display) + free (opt.display); + opt.display = strdup (value); + if (!opt.display) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "ttyname")) + { + if (opt.ttyname) + free (opt.ttyname); + opt.ttyname = strdup (value); + if (!opt.ttyname) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "ttytype")) + { + if (opt.ttytype) + free (opt.ttytype); + opt.ttytype = strdup (value); + if (!opt.ttytype) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "lc-ctype")) + { + if (opt.lc_ctype) + free (opt.lc_ctype); + opt.lc_ctype = strdup (value); + if (!opt.lc_ctype) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "lc-messages")) + { + if (opt.lc_messages) + free (opt.lc_messages); + opt.lc_messages = strdup (value); + if (!opt.lc_messages) + return ASSUAN_Out_Of_Core; + } + else if (!strcmp (key, "list-mode")) + { + int i = *value? atoi (value) : 0; + if (!i || i == 1) /* default and mode 1 */ + { + ctrl->server_local->list_internal = 1; + ctrl->server_local->list_external = 0; + } + else if (i == 2) + { + ctrl->server_local->list_internal = 0; + ctrl->server_local->list_external = 1; + } + else if (i == 3) + { + ctrl->server_local->list_internal = 1; + ctrl->server_local->list_external = 1; + } + else + return ASSUAN_Parameter_Error; + } + else + return ASSUAN_Invalid_Option; + + return 0; +} + + + + +static void +reset_notify (ASSUAN_CONTEXT ctx) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + gpgsm_release_certlist (ctrl->server_local->recplist); + gpgsm_release_certlist (ctrl->server_local->signerlist); + ctrl->server_local->recplist = NULL; + ctrl->server_local->signerlist = NULL; + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); +} + + +static void +input_notify (ASSUAN_CONTEXT ctx, const char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + ctrl->autodetect_encoding = 0; + ctrl->is_pem = 0; + ctrl->is_base64 = 0; + if (strstr (line, "--armor")) + ctrl->is_pem = 1; + else if (strstr (line, "--base64")) + ctrl->is_base64 = 1; + else if (strstr (line, "--binary")) + ; + else + ctrl->autodetect_encoding = 1; +} + +static void +output_notify (ASSUAN_CONTEXT ctx, const char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + ctrl->create_pem = 0; + ctrl->create_base64 = 0; + if (strstr (line, "--armor")) + ctrl->create_pem = 1; + else if (strstr (line, "--base64")) + ctrl->create_base64 = 1; /* just the raw output */ +} + + + +/* RECIPIENT <userID> + + Set the recipient for the encryption. <userID> should be the + internal representation of the key; the server may accept any other + way of specification [we will support this]. 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 RECIPIENT commands are + cumulative until a RESET or an successful ENCRYPT command. */ +static int +cmd_recipient (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + + rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist); + if (rc) + { + gpg_err_code_t r = gpg_err_code (rc); + gpgsm_status2 (ctrl, STATUS_INV_RECP, + r == -1? "1": + r == GPG_ERR_NO_PUBKEY? "1": + r == GPG_ERR_AMBIGUOUS_NAME? "2": + r == GPG_ERR_WRONG_KEY_USAGE? "3": + r == GPG_ERR_CERT_REVOKED? "4": + r == GPG_ERR_CERT_EXPIRED? "5": + r == GPG_ERR_NO_CRL_KNOWN? "6": + r == GPG_ERR_CRL_TOO_OLD? "7": + r == GPG_ERR_NO_POLICY_MATCH? "8": + "0", + line, NULL); + } + + return map_to_assuan_status (rc); +} + +/* SIGNER <userID> + + Set the signer's keys for the signature creation. <userID> should + be the internal representation of the key; the server may accept any + other way of specification [we will support this]. If this is a + valid and usable signing key the server does respond with OK, + otherwise it returns an ERR with the reason why the key can't be + used, the signing will then not be done for this key. If the policy + is not to sign at all if not all signer keys are valid, the client + has to take care of this. All SIGNER commands are cumulative until + a RESET but they are *not* reset by an SIGN command becuase it can + be expected that set of signers are used for more than one sign + operation. + + Note that this command returns an INV_RECP status which is a bit + strange, but they are very similar. */ +static int +cmd_signer (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + + rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist); + if (rc) + { + gpg_err_code_t r = gpg_err_code (rc); + gpgsm_status2 (ctrl, STATUS_INV_RECP, + r == -1? "1": + r == GPG_ERR_NO_PUBKEY? "1": + r == GPG_ERR_AMBIGUOUS_NAME? "2": + r == GPG_ERR_WRONG_KEY_USAGE? "3": + r == GPG_ERR_CERT_REVOKED? "4": + r == GPG_ERR_CERT_EXPIRED? "5": + r == GPG_ERR_NO_CRL_KNOWN? "6": + r == GPG_ERR_CRL_TOO_OLD? "7": + r == GPG_ERR_NO_POLICY_MATCH? "8": + r == GPG_ERR_NO_SECKEY? "9": + "0", + line, NULL); + } + return map_to_assuan_status (rc); +} + + +/* ENCRYPT + + Do the actual encryption process. Takes the plaintext from the INPUT + command, writes to the ciphertext to the file descriptor set with + the OUTPUT command, take the recipients form 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. */ +static int +cmd_encrypt (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int inp_fd, out_fd; + FILE *out_fp; + int rc; + + inp_fd = assuan_get_input_fd (ctx); + if (inp_fd == -1) + return set_error (No_Input, NULL); + out_fd = assuan_get_output_fd (ctx); + if (out_fd == -1) + return set_error (No_Output, NULL); + + out_fp = fdopen ( dup(out_fd), "w"); + if (!out_fp) + return set_error (General_Error, "fdopen() failed"); + rc = gpgsm_encrypt (assuan_get_pointer (ctx), + ctrl->server_local->recplist, + inp_fd, out_fp); + fclose (out_fp); + + gpgsm_release_certlist (ctrl->server_local->recplist); + ctrl->server_local->recplist = NULL; + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + return map_to_assuan_status (rc); +} + +/* DECRYPT + + This performs the decrypt operation after doing some check on the + internal state. (e.g. that only 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 + does take care of this by requesting this from the user. */ +static int +cmd_decrypt (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int inp_fd, out_fd; + FILE *out_fp; + int rc; + + inp_fd = assuan_get_input_fd (ctx); + if (inp_fd == -1) + return set_error (No_Input, NULL); + out_fd = assuan_get_output_fd (ctx); + if (out_fd == -1) + return set_error (No_Output, NULL); + + out_fp = fdopen ( dup(out_fd), "w"); + if (!out_fp) + return set_error (General_Error, "fdopen() failed"); + rc = gpgsm_decrypt (ctrl, inp_fd, out_fp); + fclose (out_fp); + + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + + return map_to_assuan_status (rc); +} + + +/* VERIFY + + This 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. + */ +static int +cmd_verify (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + CTRL ctrl = assuan_get_pointer (ctx); + int fd = assuan_get_input_fd (ctx); + int out_fd = assuan_get_output_fd (ctx); + FILE *out_fp = NULL; + + if (fd == -1) + return set_error (No_Input, NULL); + + if (out_fd != -1) + { + out_fp = fdopen ( dup(out_fd), "w"); + if (!out_fp) + return set_error (General_Error, "fdopen() failed"); + } + + rc = gpgsm_verify (assuan_get_pointer (ctx), fd, + ctrl->server_local->message_fd, out_fp); + if (out_fp) + fclose (out_fp); + + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + + return map_to_assuan_status (rc); +} + + +/* SIGN [--detached] + + Sign the data set with the INPUT command and write it to the sink + set by OUTPUT. With "--detached" specified, a detached signature is + created (surprise). */ +static int +cmd_sign (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int inp_fd, out_fd; + FILE *out_fp; + int detached; + int rc; + + inp_fd = assuan_get_input_fd (ctx); + if (inp_fd == -1) + return set_error (No_Input, NULL); + out_fd = assuan_get_output_fd (ctx); + if (out_fd == -1) + return set_error (No_Output, NULL); + + detached = has_option (line, "--detached"); + + out_fp = fdopen ( dup(out_fd), "w"); + if (!out_fp) + return set_error (General_Error, "fdopen() failed"); + + rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist, + inp_fd, detached, out_fp); + fclose (out_fp); + + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + + return map_to_assuan_status (rc); +} + + +/* IMPORT + + Import the certificates read form the input-fd, return status + message for each imported one. The import checks the validity of + the certificate but not of the entire chain. It is possible to + import expired certificates. */ +static int +cmd_import (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + int fd = assuan_get_input_fd (ctx); + + if (fd == -1) + return set_error (No_Input, NULL); + + rc = gpgsm_import (assuan_get_pointer (ctx), fd); + + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + + return map_to_assuan_status (rc); +} + + +static int +cmd_export (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int fd = assuan_get_output_fd (ctx); + FILE *out_fp; + char *p; + STRLIST list, sl; + + if (fd == -1) + return set_error (No_Output, NULL); + + /* break the line down into an STRLIST */ + list = NULL; + for (p=line; *p; line = p) + { + while (*p && *p != ' ') + p++; + if (*p) + *p++ = 0; + if (*line) + { + sl = xtrymalloc (sizeof *sl + strlen (line)); + if (!sl) + { + free_strlist (list); + return ASSUAN_Out_Of_Core; + } + sl->flags = 0; + strcpy_escaped_plus (sl->d, line); + sl->next = list; + list = sl; + } + } + + out_fp = fdopen ( dup(fd), "w"); + if (!out_fp) + { + free_strlist (list); + return set_error (General_Error, "fdopen() failed"); + } + + gpgsm_export (ctrl, list, out_fp); + fclose (out_fp); + free_strlist (list); + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + return 0; +} + + +static int +cmd_delkeys (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + char *p; + STRLIST list, sl; + int rc; + + /* break the line down into an STRLIST */ + list = NULL; + for (p=line; *p; line = p) + { + while (*p && *p != ' ') + p++; + if (*p) + *p++ = 0; + if (*line) + { + sl = xtrymalloc (sizeof *sl + strlen (line)); + if (!sl) + { + free_strlist (list); + return ASSUAN_Out_Of_Core; + } + sl->flags = 0; + strcpy_escaped_plus (sl->d, line); + sl->next = list; + list = sl; + } + } + + rc = gpgsm_delete (ctrl, list); + free_strlist (list); + + /* close and reset the fd */ + close_message_fd (ctrl); + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + + return map_to_assuan_status (rc); +} + + + +/* MESSAGE FD=<n> + + Set the file descriptor to read a message which is used with + detached signatures */ +static int +cmd_message (ASSUAN_CONTEXT ctx, char *line) +{ + char *endp; + int fd; + CTRL ctrl = assuan_get_pointer (ctx); + + if (strncmp (line, "FD=", 3)) + return set_error (Syntax_Error, "FD=<n> expected"); + line += 3; + if (!digitp (line)) + return set_error (Syntax_Error, "number required"); + fd = strtoul (line, &endp, 10); + if (*endp) + return set_error (Syntax_Error, "garbage found"); + if (fd == -1) + return set_error (No_Input, NULL); + + ctrl->server_local->message_fd = fd; + return 0; +} + + +static int +do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode) +{ + CTRL ctrl = assuan_get_pointer (ctx); + FILE *fp = assuan_get_data_fp (ctx); + char *p; + STRLIST list, sl; + unsigned int listmode; + + if (!fp) + return set_error (General_Error, "no data stream"); + + /* break the line down into an STRLIST */ + list = NULL; + for (p=line; *p; line = p) + { + while (*p && *p != ' ') + p++; + if (*p) + *p++ = 0; + if (*line) + { + sl = xtrymalloc (sizeof *sl + strlen (line)); + if (!sl) + { + free_strlist (list); + return ASSUAN_Out_Of_Core; + } + sl->flags = 0; + strcpy_escaped_plus (sl->d, line); + sl->next = list; + list = sl; + } + } + + ctrl->with_colons = 1; + listmode = mode; + if (ctrl->server_local->list_internal) + listmode |= (1<<6); + if (ctrl->server_local->list_external) + listmode |= (1<<7); + gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode); + free_strlist (list); + return 0; +} + +static int +cmd_listkeys (ASSUAN_CONTEXT ctx, char *line) +{ + return do_listkeys (ctx, line, 3); +} + +static int +cmd_listsecretkeys (ASSUAN_CONTEXT ctx, char *line) +{ + return do_listkeys (ctx, line, 2); +} + + +/* GENKEY + + Read the parameters in native format from the input fd and write a + certificate request to the output. + */ +static int +cmd_genkey (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int inp_fd, out_fd; + FILE *out_fp; + int rc; + + inp_fd = assuan_get_input_fd (ctx); + if (inp_fd == -1) + return set_error (No_Input, NULL); + out_fd = assuan_get_output_fd (ctx); + if (out_fd == -1) + return set_error (No_Output, NULL); + + out_fp = fdopen ( dup(out_fd), "w"); + if (!out_fp) + return set_error (General_Error, "fdopen() failed"); + rc = gpgsm_genkey (ctrl, inp_fd, out_fp); + fclose (out_fp); + + /* close and reset the fds */ + assuan_close_input_fd (ctx); + assuan_close_output_fd (ctx); + + return map_to_assuan_status (rc); +} + + + + + +/* Tell the assuan library about our commands */ +static int +register_commands (ASSUAN_CONTEXT ctx) +{ + static struct { + const char *name; + int (*handler)(ASSUAN_CONTEXT, char *line); + } table[] = { + { "RECIPIENT", cmd_recipient }, + { "SIGNER", cmd_signer }, + { "ENCRYPT", cmd_encrypt }, + { "DECRYPT", cmd_decrypt }, + { "VERIFY", cmd_verify }, + { "SIGN", cmd_sign }, + { "IMPORT", cmd_import }, + { "EXPORT", cmd_export }, + { "INPUT", NULL }, + { "OUTPUT", NULL }, + { "MESSAGE", cmd_message }, + { "LISTKEYS", cmd_listkeys }, + { "LISTSECRETKEYS",cmd_listsecretkeys }, + { "GENKEY", cmd_genkey }, + { "DELKEYS", cmd_delkeys }, + { NULL } + }; + int i, rc; + + for (i=0; table[i].name; i++) + { + rc = assuan_register_command (ctx, table[i].name, table[i].handler); + if (rc) + return rc; + } + return 0; +} + +/* Startup the server */ +void +gpgsm_server (void) +{ + int rc; + int filedes[2]; + ASSUAN_CONTEXT ctx; + struct server_control_s ctrl; + + memset (&ctrl, 0, sizeof ctrl); + gpgsm_init_default_ctrl (&ctrl); + + /* For now we use a simple pipe based server so that we can work + from scripts. We will later add options to run as a daemon and + wait for requests on a Unix domain socket */ + filedes[0] = 0; + filedes[1] = 1; + rc = assuan_init_pipe_server (&ctx, filedes); + if (rc) + { + log_error ("failed to initialize the server: %s\n", + assuan_strerror(rc)); + gpgsm_exit (2); + } + rc = register_commands (ctx); + if (rc) + { + log_error ("failed to the register commands with Assuan: %s\n", + assuan_strerror(rc)); + gpgsm_exit (2); + } + assuan_set_hello_line (ctx, "GNU Privacy Guard's S/M server ready"); + + assuan_register_reset_notify (ctx, reset_notify); + assuan_register_input_notify (ctx, input_notify); + assuan_register_output_notify (ctx, output_notify); + assuan_register_option_handler (ctx, option_handler); + + assuan_set_pointer (ctx, &ctrl); + ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); + ctrl.server_local->assuan_ctx = ctx; + ctrl.server_local->message_fd = -1; + ctrl.server_local->list_internal = 1; + ctrl.server_local->list_external = 0; + + if (DBG_ASSUAN) + assuan_set_log_stream (ctx, log_get_stream ()); + + for (;;) + { + rc = assuan_accept (ctx); + if (rc == -1) + { + break; + } + else if (rc) + { + log_info ("Assuan accept problem: %s\n", assuan_strerror (rc)); + break; + } + + rc = assuan_process (ctx); + if (rc) + { + log_info ("Assuan processing failed: %s\n", assuan_strerror (rc)); + continue; + } + } + + gpgsm_release_certlist (ctrl.server_local->recplist); + ctrl.server_local->recplist = NULL; + gpgsm_release_certlist (ctrl.server_local->signerlist); + ctrl.server_local->signerlist = NULL; + + assuan_deinit_server (ctx); +} + + +static const char * +get_status_string ( int no ) +{ + const char *s; + + switch (no) + { + case STATUS_ENTER : s = "ENTER"; break; + case STATUS_LEAVE : s = "LEAVE"; break; + case STATUS_ABORT : s = "ABORT"; break; + case STATUS_GOODSIG: s = "GOODSIG"; break; + case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break; + case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; + case STATUS_BADSIG : s = "BADSIG"; break; + case STATUS_ERRSIG : s = "ERRSIG"; break; + case STATUS_BADARMOR : s = "BADARMOR"; break; + case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; + case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; + case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; + case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; + case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; + case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; + case STATUS_GET_BOOL : s = "GET_BOOL"; break; + case STATUS_GET_LINE : s = "GET_LINE"; break; + case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break; + case STATUS_GOT_IT : s = "GOT_IT"; break; + case STATUS_SHM_INFO : s = "SHM_INFO"; break; + case STATUS_SHM_GET : s = "SHM_GET"; break; + case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; + case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; + case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; + case STATUS_VALIDSIG : s = "VALIDSIG"; break; + case STATUS_SIG_ID : s = "SIG_ID"; break; + case STATUS_ENC_TO : s = "ENC_TO"; break; + case STATUS_NODATA : s = "NODATA"; break; + case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; + case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; + case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; + case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; + case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; + case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; + case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; + case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; + case STATUS_GOODMDC : s = "GOODMDC"; break; + case STATUS_BADMDC : s = "BADMDC"; break; + case STATUS_ERRMDC : s = "ERRMDC"; break; + case STATUS_IMPORTED : s = "IMPORTED"; break; + case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; + case STATUS_FILE_START : s = "FILE_START"; break; + case STATUS_FILE_DONE : s = "FILE_DONE"; break; + case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; + case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break; + case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break; + case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break; + case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break; + case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break; + case STATUS_PROGRESS : s = "PROGRESS"; break; + case STATUS_SIG_CREATED : s = "SIG_CREATED"; break; + case STATUS_SESSION_KEY : s = "SESSION_KEY"; break; + case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break; + case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break; + case STATUS_POLICY_URL : s = "POLICY_URL" ; break; + case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break; + case STATUS_END_STREAM : s = "END_STREAM"; break; + case STATUS_KEY_CREATED : s = "KEY_CREATED"; break; + case STATUS_UNEXPECTED : s = "UNEXPECTED"; break; + case STATUS_INV_RECP : s = "INV_RECP"; break; + case STATUS_NO_RECP : s = "NO_RECP"; break; + case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break; + case STATUS_EXPSIG : s = "EXPSIG"; break; + case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; + case STATUS_TRUNCATED : s = "TRUNCATED"; break; + case STATUS_ERROR : s = "ERROR"; break; + case STATUS_IMPORT_PROBLEM : s = "IMPORT_PROBLEM"; break; + default: s = "?"; break; + } + return s; +} + + +void +gpgsm_status2 (CTRL ctrl, int no, ...) +{ + va_list arg_ptr; + const char *text; + + va_start (arg_ptr, no); + + if (ctrl->no_server) + { + if (ctrl->status_fd == -1) + return; /* no status wanted */ + if (!statusfp) + { + if (ctrl->status_fd == 1) + statusfp = stdout; + else if (ctrl->status_fd == 2) + statusfp = stderr; + else + statusfp = fdopen (ctrl->status_fd, "w"); + + if (!statusfp) + { + log_fatal ("can't open fd %d for status output: %s\n", + ctrl->status_fd, strerror(errno)); + } + } + + fputs ("[GNUPG:] ", statusfp); + fputs (get_status_string (no), statusfp); + + while ( (text = va_arg (arg_ptr, const char*) )) + { + putc ( ' ', statusfp ); + for (; *text; text++) + { + if (*text == '\n') + fputs ( "\\n", statusfp ); + else if (*text == '\r') + fputs ( "\\r", statusfp ); + else + putc ( *(const byte *)text, statusfp ); + } + } + putc ('\n', statusfp); + fflush (statusfp); + } + else + { + ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx; + char buf[950], *p; + size_t n; + + p = buf; + n = 0; + while ( (text = va_arg (arg_ptr, const char *)) ) + { + if (n) + { + *p++ = ' '; + n++; + } + for ( ; *text && n < DIM (buf)-2; n++) + *p++ = *text++; + } + *p = 0; + assuan_write_status (ctx, get_status_string (no), buf); + } + + va_end (arg_ptr); +} + +void +gpgsm_status (CTRL ctrl, int no, const char *text) +{ + gpgsm_status2 (ctrl, no, text, NULL); +} + +void +gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text, + gpg_err_code_t ec) +{ + char buf[30]; + + sprintf (buf, "%u", (unsigned int)ec); + if (text) + gpgsm_status2 (ctrl, no, text, buf, NULL); + else + gpgsm_status2 (ctrl, no, buf, NULL); +} + +#if 0 +/* + * Write a status line with a buffer using %XX escapes. If WRAP is > + * 0 wrap the line after this length. If STRING is not NULL it will + * be prepended to the buffer, no escaping is done for string. + * A wrap of -1 forces spaces not to be encoded as %20. + */ +void +write_status_text_and_buffer ( int no, const char *string, + const char *buffer, size_t len, int wrap ) +{ + const char *s, *text; + int esc, first; + int lower_limit = ' '; + size_t n, count, dowrap; + + if( !statusfp ) + return; /* not enabled */ + + if (wrap == -1) { + lower_limit--; + wrap = 0; + } + + text = get_status_string (no); + count = dowrap = first = 1; + do { + if (dowrap) { + fprintf (statusfp, "[GNUPG:] %s ", text ); + count = dowrap = 0; + if (first && string) { + fputs (string, statusfp); + count += strlen (string); + } + first = 0; + } + for (esc=0, s=buffer, n=len; n && !esc; s++, n-- ) { + if ( *s == '%' || *(const byte*)s <= lower_limit + || *(const byte*)s == 127 ) + esc = 1; + if ( wrap && ++count > wrap ) { + dowrap=1; + break; + } + } + if (esc) { + s--; n++; + } + if (s != buffer) + fwrite (buffer, s-buffer, 1, statusfp ); + if ( esc ) { + fprintf (statusfp, "%%%02X", *(const byte*)s ); + s++; n--; + } + buffer = s; + len = n; + if ( dowrap && len ) + putc ( '\n', statusfp ); + } while ( len ); + + putc ('\n',statusfp); + fflush (statusfp); +} +#endif diff --git a/sm/sign.c b/sm/sign.c new file mode 100644 index 000000000..0afb52b62 --- /dev/null +++ b/sm/sign.c @@ -0,0 +1,621 @@ +/* sign.c - Sign a message + * 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 <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + + +static void +hash_data (int fd, gcry_md_hd_t md) +{ + FILE *fp; + char buffer[4096]; + int nread; + + fp = fdopen ( dup (fd), "rb"); + if (!fp) + { + log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); + return; + } + + do + { + nread = fread (buffer, 1, DIM(buffer), fp); + gcry_md_write (md, buffer, nread); + } + while (nread); + if (ferror (fp)) + log_error ("read error on fd %d: %s\n", fd, strerror (errno)); + fclose (fp); +} + +static int +hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer) +{ + KsbaError err; + FILE *fp; + char buffer[4096]; + int nread; + int rc = 0; + int any = 0; + + fp = fdopen ( dup (fd), "rb"); + if (!fp) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); + return tmperr; + } + + do + { + nread = fread (buffer, 1, DIM(buffer), fp); + if (nread) + { + any = 1; + gcry_md_write (md, buffer, nread); + err = ksba_writer_write_octet_string (writer, buffer, nread, 0); + if (err) + { + log_error ("write failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + } + } + } + while (nread && !rc); + if (ferror (fp)) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("read error on fd %d: %s\n", fd, strerror (errno)); + } + fclose (fp); + if (!any) + { + /* We can't allow to sign an empty message because it does not + make much sense and more seriously, ksba-cms_build has + already written the tag for data and now expects an octet + string but an octet string of zeize 0 is illegal. */ + log_error ("cannot sign an empty message\n"); + rc = gpg_error (GPG_ERR_NO_DATA); + } + if (!rc) + { + err = ksba_writer_write_octet_string (writer, NULL, 0, 1); + if (err) + { + log_error ("write failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + } + } + + return rc; +} + + +/* Get the default certificate which is defined as the first one our + keyDB retruns and has a secret key available */ +int +gpgsm_get_default_cert (KsbaCert *r_cert) +{ + KEYDB_HANDLE hd; + KsbaCert cert = NULL; + int rc; + char *p; + + hd = keydb_new (0); + if (!hd) + return gpg_error (GPG_ERR_GENERAL); + rc = keydb_search_first (hd); + if (rc) + { + keydb_release (hd); + return rc; + } + + do + { + rc = keydb_get_cert (hd, &cert); + if (rc) + { + log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc)); + keydb_release (hd); + return rc; + } + + p = gpgsm_get_keygrip_hexstring (cert); + if (p) + { + if (!gpgsm_agent_havekey (p)) + { + xfree (p); + keydb_release (hd); + *r_cert = cert; + return 0; /* got it */ + } + xfree (p); + } + + ksba_cert_release (cert); + cert = NULL; + } + while (!(rc = keydb_search_next (hd))); + if (rc && rc != -1) + log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); + + ksba_cert_release (cert); + keydb_release (hd); + return rc; +} + + +static KsbaCert +get_default_signer (void) +{ + KEYDB_SEARCH_DESC desc; + KsbaCert cert = NULL; + KEYDB_HANDLE kh = NULL; + int rc; + + if (!opt.local_user) + { + rc = gpgsm_get_default_cert (&cert); + if (rc) + { + if (rc != -1) + log_debug ("failed to find default certificate: %s\n", + gpg_strerror (rc)); + return NULL; + } + return cert; + } + + rc = keydb_classify_name (opt.local_user, &desc); + if (rc) + { + log_error ("failed to find default signer: %s\n", gpg_strerror (rc)); + return NULL; + } + + kh = keydb_new (0); + if (!kh) + return NULL; + + rc = keydb_search (kh, &desc, 1); + if (rc) + { + log_debug ("failed to find default certificate: rc=%d\n", rc); + } + else + { + rc = keydb_get_cert (kh, &cert); + if (rc) + { + log_debug ("failed to get cert: rc=%d\n", rc); + } + } + + keydb_release (kh); + return cert; +} + +/* Depending on the options in CTRL add the certificate CERT as well as + other certificate up in the chain to the Root-CA to the CMS + object. */ +static int +add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert) +{ + KsbaError err; + int rc = 0; + KsbaCert next = NULL; + int n; + int not_root = 0; + + ksba_cert_ref (cert); + + n = ctrl->include_certs; + if (n == -2) + { + not_root = 1; + n = -1; + } + if (n < 0 || n > 50) + n = 50; /* We better apply an upper bound */ + + if (n) + { + if (not_root && gpgsm_is_root_cert (cert)) + err = 0; + else + err = ksba_cms_add_cert (cms, cert); + if (err) + goto ksba_failure; + } + while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) ) + { + if (not_root && gpgsm_is_root_cert (next)) + err = 0; + else + err = ksba_cms_add_cert (cms, next); + ksba_cert_release (cert); + cert = next; next = NULL; + if (err) + goto ksba_failure; + } + ksba_cert_release (cert); + + return rc == -1? 0: rc; + + ksba_failure: + ksba_cert_release (cert); + log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err)); + return map_ksba_err (err); +} + + + + +/* Perform a sign operation. + + Sign the data received on DATA-FD in embedded mode or in detached + mode when DETACHED is true. Write the signature to OUT_FP. The + keys used to sign are taken from SIGNERLIST or the default one will + be used if the value of this argument is NULL. */ +int +gpgsm_sign (CTRL ctrl, CERTLIST signerlist, + int data_fd, int detached, FILE *out_fp) +{ + int i, rc; + KsbaError err; + Base64Context b64writer = NULL; + KsbaWriter writer; + KsbaCMS cms = NULL; + KsbaStopReason stopreason; + KEYDB_HANDLE kh = NULL; + gcry_md_hd_t data_md = NULL; + int signer; + const char *algoid; + int algo; + time_t signed_at; + CERTLIST cl; + int release_signerlist = 0; + + kh = keydb_new (0); + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + ctrl->pem_name = "SIGNED MESSAGE"; + rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + + cms = ksba_cms_new (); + if (!cms) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + err = ksba_cms_set_reader_writer (cms, NULL, writer); + if (err) + { + log_debug ("ksba_cms_set_reader_writer failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + /* We are going to create signed data with data as encap. content */ + err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA); + if (!err) + err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA); + if (err) + { + log_debug ("ksba_cms_set_content_type failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + /* If no list of signers is given, use a default one. */ + if (!signerlist) + { + KsbaCert cert = get_default_signer (); + if (!cert) + { + log_error ("no default signer found\n"); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + signerlist = xtrycalloc (1, sizeof *signerlist); + if (!signerlist) + { + rc = OUT_OF_CORE (errno); + ksba_cert_release (cert); + goto leave; + } + signerlist->cert = cert; + release_signerlist = 1; + } + + + /* Gather certificates of signers and store them in the CMS object. */ + for (cl=signerlist; cl; cl = cl->next) + { + rc = gpgsm_cert_use_sign_p (cl->cert); + if (rc) + goto leave; + + err = ksba_cms_add_signer (cms, cl->cert); + if (err) + { + log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + rc = add_certificate_list (ctrl, cms, cl->cert); + if (rc) + { + log_error ("failed to store list of certificates: %s\n", + gpg_strerror(rc)); + goto leave; + } + /* Set the hash algorithm we are going to use */ + err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/); + if (err) + { + log_debug ("ksba_cms_add_digest_algo failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + + /* Prepare hashing (actually we are figuring out what we have set above)*/ + rc = gcry_md_open (&data_md, 0, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + goto leave; + } + if (DBG_HASHING) + gcry_md_start_debug (data_md, "sign.data"); + + for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) + { + algo = gcry_md_map_name (algoid); + if (!algo) + { + log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); + rc = gpg_error (GPG_ERR_BUG); + goto leave; + } + gcry_md_enable (data_md, algo); + } + + if (detached) + { /* we hash the data right now so that we can store the message + digest. ksba_cms_build() takes this as an flag that detached + data is expected. */ + unsigned char *digest; + size_t digest_len; + /* Fixme do this for all signers and get the algo to use from + the signer's certificate - does not make mich sense, bu we + should do this consistent as we have already done it above */ + algo = GCRY_MD_SHA1; + hash_data (data_fd, data_md); + digest = gcry_md_read (data_md, algo); + digest_len = gcry_md_get_algo_dlen (algo); + if ( !digest || !digest_len) + { + log_error ("problem getting the hash of the data\n"); + rc = gpg_error (GPG_ERR_BUG); + goto leave; + } + for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) + { + err = ksba_cms_set_message_digest (cms, signer, digest, digest_len); + if (err) + { + log_error ("ksba_cms_set_message_digest failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + } + + signed_at = gnupg_get_time (); + for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) + { + err = ksba_cms_set_signing_time (cms, signer, signed_at); + if (err) + { + log_error ("ksba_cms_set_signing_time failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + + do + { + err = ksba_cms_build (cms, &stopreason); + if (err) + { + log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + if (stopreason == KSBA_SR_BEGIN_DATA) + { /* hash the data and store the message digest */ + unsigned char *digest; + size_t digest_len; + + assert (!detached); + /* Fixme: get the algo to use from the signer's certificate + - does not make much sense, but we should do this + consistent as we have already done it above. Code is + mostly duplicated above. */ + + algo = GCRY_MD_SHA1; + rc = hash_and_copy_data (data_fd, data_md, writer); + if (rc) + goto leave; + digest = gcry_md_read (data_md, algo); + digest_len = gcry_md_get_algo_dlen (algo); + if ( !digest || !digest_len) + { + log_error ("problem getting the hash of the data\n"); + rc = gpg_error (GPG_ERR_BUG); + goto leave; + } + for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) + { + err = ksba_cms_set_message_digest (cms, signer, + digest, digest_len); + if (err) + { + log_error ("ksba_cms_set_message_digest failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + } + } + else if (stopreason == KSBA_SR_NEED_SIG) + { /* calculate the signature for all signers */ + gcry_md_hd_t md; + + algo = GCRY_MD_SHA1; + rc = gcry_md_open (&md, algo, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + goto leave; + } + if (DBG_HASHING) + gcry_md_start_debug (md, "sign.attr"); + ksba_cms_set_hash_function (cms, HASH_FNC, md); + for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) + { + char *sigval = NULL; + char *buf, *fpr; + + if (signer) + gcry_md_reset (md); + rc = ksba_cms_hash_signed_attrs (cms, signer); + if (rc) + { + log_debug ("hashing signed attrs failed: %s\n", + ksba_strerror (rc)); + gcry_md_close (md); + goto leave; + } + + rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval); + if (rc) + { + gcry_md_close (md); + goto leave; + } + + err = ksba_cms_set_sig_val (cms, signer, sigval); + xfree (sigval); + if (err) + { + log_error ("failed to store the signature: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + gcry_md_close (md); + goto leave; + } + + /* write a status message */ + fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1); + if (!fpr) + { + rc = gpg_error (GPG_ERR_ENOMEM); + gcry_md_close (md); + goto leave; + } + rc = asprintf (&buf, "%c %d %d 00 %lu %s", + detached? 'D':'S', + GCRY_PK_RSA, /* FIXME: get pk algo from cert */ + algo, + (ulong)signed_at, + fpr); + xfree (fpr); + if (rc < 0) + { + rc = gpg_error (GPG_ERR_ENOMEM); + gcry_md_close (md); + goto leave; + } + rc = 0; + gpgsm_status (ctrl, STATUS_SIG_CREATED, buf); + free (buf); /* yes, we must use the regular free() here */ + } + gcry_md_close (md); + + } + } + while (stopreason != KSBA_SR_READY); + + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + log_info ("signature created\n"); + + + leave: + if (release_signerlist) + gpgsm_release_certlist (signerlist); + ksba_cms_release (cms); + gpgsm_destroy_writer (b64writer); + keydb_release (kh); + gcry_md_close (data_md); + return rc; +} diff --git a/sm/verify.c b/sm/verify.c new file mode 100644 index 000000000..6dd4f4e5b --- /dev/null +++ b/sm/verify.c @@ -0,0 +1,550 @@ +/* verify.c - Verify a messages signature + * 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 <unistd.h> +#include <time.h> +#include <assert.h> + +#include "gpgsm.h" +#include <gcrypt.h> +#include <ksba.h> + +#include "keydb.h" +#include "i18n.h" + +static char * +strtimestamp_r (time_t atime) +{ + char *buffer = xmalloc (15); + + if (atime < 0) + strcpy (buffer, "????" "-??" "-??"); + else if (!atime) + strcpy (buffer, "none"); + else + { + struct tm *tp; + + tp = gmtime( &atime ); + sprintf (buffer, "%04d-%02d-%02d", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday); + } + return buffer; +} + + + +/* Hash the data for a detached signature */ +static void +hash_data (int fd, gcry_md_hd_t md) +{ + FILE *fp; + char buffer[4096]; + int nread; + + fp = fdopen ( dup (fd), "rb"); + if (!fp) + { + log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); + return; + } + + do + { + nread = fread (buffer, 1, DIM(buffer), fp); + gcry_md_write (md, buffer, nread); + } + while (nread); + if (ferror (fp)) + log_error ("read error on fd %d: %s\n", fd, strerror (errno)); + fclose (fp); +} + + + + +/* Perform a verify operation. To verify detached signatures, data_fd + must be different than -1. With OUT_FP given and a non-detached + signature, the signed material is written to that stream. */ +int +gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) +{ + int i, rc; + Base64Context b64reader = NULL; + Base64Context b64writer = NULL; + KsbaError err; + KsbaReader reader; + KsbaWriter writer = NULL; + KsbaCMS cms = NULL; + KsbaStopReason stopreason; + KsbaCert cert; + KEYDB_HANDLE kh; + gcry_md_hd_t data_md = NULL; + int signer; + const char *algoid; + int algo; + int is_detached; + FILE *fp = NULL; + char *p; + + kh = keydb_new (0); + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + + fp = fdopen ( dup (in_fd), "rb"); + if (!fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("fdopen() failed: %s\n", strerror (errno)); + goto leave; + } + + rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); + if (rc) + { + log_error ("can't create reader: %s\n", gpg_strerror (rc)); + goto leave; + } + + if (out_fp) + { + rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + } + + cms = ksba_cms_new (); + if (!cms) + { + rc = gpg_error (GPG_ERR_ENOMEM); + goto leave; + } + + err = ksba_cms_set_reader_writer (cms, reader, writer); + if (err) + { + log_error ("ksba_cms_set_reader_writer failed: %s\n", + ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + rc = gcry_md_open (&data_md, 0, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + goto leave; + } + if (DBG_HASHING) + gcry_md_start_debug (data_md, "vrfy.data"); + + is_detached = 0; + do + { + err = ksba_cms_parse (cms, &stopreason); + if (err) + { + log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); + rc = map_ksba_err (err); + goto leave; + } + + if (stopreason == KSBA_SR_NEED_HASH) + { + is_detached = 1; + if (opt.verbose) + log_info ("detached signature\n"); + } + + if (stopreason == KSBA_SR_NEED_HASH + || stopreason == KSBA_SR_BEGIN_DATA) + { /* We are now able to enable the hash algorithms */ + for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) + { + algo = gcry_md_map_name (algoid); + if (!algo) + log_error ("unknown hash algorithm `%s'\n", + algoid? algoid:"?"); + else + gcry_md_enable (data_md, algo); + } + if (is_detached) + { + if (data_fd == -1) + log_info ("detached signature w/o data " + "- assuming certs-only\n"); + else + hash_data (data_fd, data_md); + } + else + { + ksba_cms_set_hash_function (cms, HASH_FNC, data_md); + } + } + else if (stopreason == KSBA_SR_END_DATA) + { /* The data bas been hashed */ + + } + } + while (stopreason != KSBA_SR_READY); + + if (b64writer) + { + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + } + + if (data_fd != -1 && !is_detached) + { + log_error ("data given for a non-detached signature\n"); + rc = gpg_error (GPG_ERR_CONFLICT); + goto leave; + } + + for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) + { + /* Fixme: it might be better to check the validity of the + certificate first before entering it into the DB. This way + we would avoid cluttering the DB with invalid + certificates. */ + keydb_store_cert (cert, 0, NULL); + ksba_cert_release (cert); + } + + cert = NULL; + err = 0; + for (signer=0; ; signer++) + { + char *issuer = NULL; + KsbaSexp sigval = NULL; + time_t sigtime, keyexptime; + KsbaSexp serial; + char *msgdigest = NULL; + size_t msgdigestlen; + char *ctattr; + + err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); + if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached) + { + log_info ("certs-only message accepted\n"); + err = 0; + break; + } + if (err) + { + if (signer && err == -1) + err = 0; + break; + } + if (DBG_X509) + { + log_debug ("signer %d - issuer: `%s'\n", + signer, issuer? issuer:"[NONE]"); + log_debug ("signer %d - serial: ", signer); + gpgsm_dump_serial (serial); + log_printf ("\n"); + } + + err = ksba_cms_get_signing_time (cms, signer, &sigtime); + if (err == KSBA_No_Data) + sigtime = 0; + else if (err) + { + log_error ("error getting signing time: %s\n", ksba_strerror (err)); + sigtime = (time_t)-1; + } + + err = ksba_cms_get_message_digest (cms, signer, + &msgdigest, &msgdigestlen); + if (!err) + { + algoid = ksba_cms_get_digest_algo (cms, signer); + algo = gcry_md_map_name (algoid); + if (DBG_X509) + log_debug ("signer %d - digest algo: %d\n", signer, algo); + if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) ) + { + log_error ("digest algo %d has not been enabled\n", algo); + goto next_signer; + } + } + else if (err == KSBA_No_Data) + { + assert (!msgdigest); + err = 0; + algoid = NULL; + algo = 0; + } + else /* real error */ + break; + + err = ksba_cms_get_sigattr_oids (cms, signer, + "1.2.840.113549.1.9.3",&ctattr); + if (!err) + { + const char *s; + + if (DBG_X509) + log_debug ("signer %d - content-type attribute: %s", signer, ctattr); + s = ksba_cms_get_content_oid (cms, 1); + if (!s || strcmp (ctattr, s)) + { + log_error ("content-type attribute does not match " + "actual content-type\n"); + ksba_free (ctattr); + ctattr = NULL; + goto next_signer; + } + ksba_free (ctattr); + ctattr = NULL; + } + else if (err != -1) + { + log_error ("error getting content-type attribute: %s\n", + ksba_strerror (err)); + goto next_signer; + } + err = 0; + + + sigval = ksba_cms_get_sig_val (cms, signer); + if (!sigval) + { + log_error ("no signature value available\n"); + goto next_signer; + } + if (DBG_X509) + log_debug ("signer %d - signature available", signer); + + /* Find the certificate of the signer */ + keydb_search_reset (kh); + rc = keydb_search_issuer_sn (kh, issuer, serial); + if (rc) + { + if (rc == -1) + { + log_error ("certificate not found\n"); + rc = gpg_error (GPG_ERR_NO_PUBKEY); + } + else + log_error ("failed to find the certificate: %s\n", + gpg_strerror(rc)); + { + char numbuf[50]; + sprintf (numbuf, "%d", rc); + + gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey", + numbuf, NULL); + } + /* fixme: we might want to append the issuer and serial + using our standard notation */ + goto next_signer; + } + + rc = keydb_get_cert (kh, &cert); + if (rc) + { + log_error ("failed to get cert: %s\n", gpg_strerror (rc)); + goto next_signer; + } + + log_info (_("Signature made ")); + if (sigtime) + gpgsm_dump_time (sigtime); + else + log_printf (_("[date not given]")); + log_printf (_(" using certificate ID %08lX\n"), + gpgsm_get_short_fingerprint (cert)); + + + if (msgdigest) + { /* Signed attributes are available. */ + gcry_md_hd_t md; + unsigned char *s; + + /* check that the message digest in the signed attributes + matches the one we calculated on the data */ + s = gcry_md_read (data_md, algo); + if ( !s || !msgdigestlen + || gcry_md_get_algo_dlen (algo) != msgdigestlen + || !s || memcmp (s, msgdigest, msgdigestlen) ) + { + char *fpr; + + log_error ("invalid signature: message digest attribute " + "does not match calculated one\n"); + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + gpgsm_status (ctrl, STATUS_BADSIG, fpr); + xfree (fpr); + goto next_signer; + } + + rc = gcry_md_open (&md, algo, 0); + if (rc) + { + log_error ("md_open failed: %s\n", gpg_strerror (rc)); + goto next_signer; + } + if (DBG_HASHING) + gcry_md_start_debug (md, "vrfy.attr"); + + ksba_cms_set_hash_function (cms, HASH_FNC, md); + rc = ksba_cms_hash_signed_attrs (cms, signer); + if (rc) + { + log_error ("hashing signed attrs failed: %s\n", + ksba_strerror (rc)); + gcry_md_close (md); + goto next_signer; + } + rc = gpgsm_check_cms_signature (cert, sigval, md, algo); + gcry_md_close (md); + } + else + { + rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo); + } + + if (rc) + { + char *fpr; + + log_error ("invalid signature: %s\n", gpg_strerror (rc)); + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + gpgsm_status (ctrl, STATUS_BADSIG, fpr); + xfree (fpr); + goto next_signer; + } + rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/ + if (rc) + { + gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage", + gpg_err_code (rc)); + rc = 0; + } + + if (DBG_X509) + log_debug ("signature okay - checking certs\n"); + rc = gpgsm_validate_chain (ctrl, cert, &keyexptime); + if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) + { + gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); + rc = 0; + } + else + gpgsm_status (ctrl, STATUS_GOODSIG, NULL); + + { + char *buf, *fpr, *tstr; + + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + tstr = strtimestamp_r (sigtime); + buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120); + sprintf (buf, "%s %s %lu %lu", fpr, tstr, + (unsigned long)sigtime, (unsigned long)keyexptime ); + xfree (tstr); + xfree (fpr); + gpgsm_status (ctrl, STATUS_VALIDSIG, buf); + xfree (buf); + } + + if (rc) /* of validate_chain */ + { + log_error ("invalid certification chain: %s\n", gpg_strerror (rc)); + if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN + || gpg_err_code (rc) == GPG_ERR_BAD_CERT + || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT + || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED) + gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL, + gpg_err_code (rc)); + else + gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, + gpg_err_code (rc)); + goto next_signer; + } + + for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) + { + log_info (!i? _("Good signature from") + : _(" aka")); + log_printf (" \""); + gpgsm_print_name (log_get_stream (), p); + log_printf ("\"\n"); + ksba_free (p); + } + + gpgsm_status (ctrl, STATUS_TRUST_FULLY, NULL); + + + next_signer: + rc = 0; + xfree (issuer); + xfree (serial); + xfree (sigval); + xfree (msgdigest); + ksba_cert_release (cert); + cert = NULL; + } + rc = 0; + if (err) + { + log_error ("ksba error: %s\n", ksba_strerror (err)); + rc = map_ksba_err (rc); + } + + + + leave: + ksba_cms_release (cms); + gpgsm_destroy_reader (b64reader); + gpgsm_destroy_writer (b64writer); + keydb_release (kh); + gcry_md_close (data_md); + if (fp) + fclose (fp); + + if (rc) + { + char numbuf[50]; + sprintf (numbuf, "%d", rc ); + gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave", + numbuf, NULL); + } + + return rc; +} + -- cgit v1.2.3 From 1bcf8ef9dea1a9b171c27ef48cadb79df6201e33 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 5 Aug 2003 17:11:04 +0000 Subject: Cleanups, fixes and PC/SC support --- ChangeLog | 4 + NEWS | 10 ++ README | 38 ++++- TODO | 3 + configure.ac | 4 +- doc/scdaemon.texi | 4 + g10/ChangeLog | 20 +++ g10/Makefile.am | 17 +- g10/g10.c | 107 ++----------- g10/pkglue.c | 37 ++++- g10/pkglue.h | 1 + g10/seckey-cert.c | 15 +- g10/status.c | 226 +-------------------------- g10/status.h | 4 - scd/ChangeLog | 22 +++ scd/apdu.c | 426 +++++++++++++++++++++++++++++++++++++++++++-------- scd/apdu.h | 3 +- scd/app-common.h | 1 + scd/app-openpgp.c | 135 ++++------------ scd/app.c | 13 +- scd/sc-copykeys.c | 8 +- scd/sc-investigate.c | 8 +- scd/scdaemon.c | 12 +- scd/scdaemon.h | 1 + 24 files changed, 600 insertions(+), 519 deletions(-) diff --git a/ChangeLog b/ChangeLog index b846f27a7..83e9cba0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2003-08-05 Werner Koch <wk@gnupg.org> + + * configure.ac (GNUPG_DEFAULT_HONMEDIR): Changed back to ~/.gnupg. + 2003-07-31 Werner Koch <wk@gnupg.org> * Makefile.am (DISTCLEANFILES): Add g10defs.h diff --git a/NEWS b/NEWS index 794ad11f1..9e6b9f1af 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,16 @@ Noteworthy changes in version 1.9.0 (unreleased) ------------------------------------------------ + * gpg has been renamed to gpg2 and gpgv to gpgv2. This is a + temporary solution to allow co-existing with stable gpg versions. + + * The default config file is ~/.gnupg/gpg.conf-1.9.0 if it exists. + + * 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. diff --git a/README b/README index 7aea069b3..8dea9dbb9 100644 --- a/README +++ b/README @@ -34,6 +34,21 @@ gpgsm: 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. + + + OPTIONS ======= @@ -139,6 +154,22 @@ gpg-agent: 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). @@ -174,10 +205,15 @@ 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. emptry lines + object identifiers of the policies line by line. Empty lines and lines startung with a hash mark are ignored. ++++++++++ diff --git a/TODO b/TODO index 431f2a2ea..c9b2d18ff 100644 --- a/TODO +++ b/TODO @@ -55,5 +55,8 @@ might want to have an agent context for each service request * sm/export.c ** Return an error code or a status info per user ID. +* scd/apdu.c +** We need close_reader functionality + * ALL ** Return IMPORT_OK status. diff --git a/configure.ac b/configure.ac index 9d8aef9ee..060f31d97 100644 --- a/configure.ac +++ b/configure.ac @@ -224,7 +224,7 @@ AH_BOTTOM([ #ifdef HAVE_DRIVE_LETTERS #define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" #else -#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg2" +#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" #endif #define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" @@ -966,7 +966,7 @@ cat >g10defs.tmp <<G10EOF #ifdef __VMS #define GNUPG_HOMEDIR "/SYS\$LOGIN/gnupg" #else -#define GNUPG_HOMEDIR "~/.gnupg2" +#define GNUPG_HOMEDIR "~/.gnupg" #endif #endif /* those are here to be redefined by handcrafted g10defs.h. diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 7b776c750..36274e601 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -142,6 +142,10 @@ 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}. + @end table All the long options may also be given in the configuration file after diff --git a/g10/ChangeLog b/g10/ChangeLog index 335f28fdf..f878be64d 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,23 @@ +2003-08-05 Werner Koch <wk@gnupg.org> + + * Makefile.am (install-data-local): Dropped check for the ancient + gpgm tool. + (bin_PROGRAMS): Renamed gpg to gpg2 and gpgv to gpgv2. This is so + that it won't conflict with the current stable version of gpg. + + * pkglue.c (pk_check_secret_key): New. + * seckey-cert.c (do_check): Reenable this test here again. + + * g10.c (main): Add command -K as an alias for + --list-secret-keys. Command "-k" is now an alias to --list-keys. + Remove special treatment of -kv and -kvv. + (set_cmd): Ditto. + (main): Strip a "-cvs" suffix when testing for a version specific + config file. + + * status.h, status.c, g10.c [USE_SHM_COPROCESSING]: Removed. This + is not any longer available. + 2003-07-29 Werner Koch <wk@gnupg.org> * g10.c (main): Add secmem features and set the random seed file. diff --git a/g10/Makefile.am b/g10/Makefile.am index d6984941e..59213d04b 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -31,8 +31,7 @@ AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" endif needed_libs = ../common/libcommon.a ../jnlib/libjnlib.a -#noinst_PROGRAMS = gpgd -bin_PROGRAMS = gpg gpgv +bin_PROGRAMS = gpg2 gpgv2 common_source = \ global.h gpg.h \ @@ -65,7 +64,7 @@ common_source = \ keylist.c \ pkglue.c pkglue.h -gpg_SOURCES = g10.c \ +gpg2_SOURCES = g10.c \ $(common_source) \ pkclist.c \ skclist.c \ @@ -99,7 +98,7 @@ gpg_SOURCES = g10.c \ card-util.c \ exec.c exec.h -gpgv_SOURCES = gpgv.c \ +gpgv2_SOURCES = gpgv.c \ $(common_source) \ verify.c @@ -111,8 +110,8 @@ gpgv_SOURCES = gpgv.c \ # $(common_source) LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ -gpg_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error -gpgv_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error +gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error +gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error $(PROGRAMS): $(needed_libs) @@ -120,8 +119,4 @@ install-data-local: $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) $(INSTALL_DATA) $(srcdir)/options.skel \ $(DESTDIR)$(pkgdatadir)/options.skel - @set -e;\ - if test -f $(DESTDIR)$(bindir)/gpgm ; then \ - echo "removing obsolete gpgm binary" ; \ - rm $(DESTDIR)$(bindir)/gpgm ; \ - fi + diff --git a/g10/g10.c b/g10/g10.c index f89556184..aef76992b 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -61,7 +61,8 @@ enum cmd_and_opt_values { aNull = 0, aEncr = 'e', aEncrFiles, oInteractive = 'i', - oKOption = 'k', + aListKeys = 'k', + aListSecretKeys = 'K', oDryRun = 'n', oOutput = 'o', oQuiet = 'q', @@ -93,15 +94,11 @@ enum cmd_and_opt_values { aNull = 0, aDeleteKeys, aDeleteSecretKeys, aDeleteSecretAndPublicKeys, - aKMode, - aKModeC, aImport, aFastImport, aVerify, aVerifyFiles, - aListKeys, aListSigs, - aListSecretKeys, aSendKeys, aRecvKeys, aSearchKeys, @@ -213,7 +210,6 @@ enum cmd_and_opt_values { aNull = 0, oTrustModel, oForceOwnertrust, oEmuChecksumBug, - oRunAsShmCP, oSetFilename, oForYourEyesOnly, oNoForYourEyesOnly, @@ -514,7 +510,6 @@ static ARGPARSE_OPTS opts[] = { /* Not yet used */ /* { aListTrustPath, "list-trust-path",0, "@"}, */ { aPipeMode, "pipemode", 0, "@" }, - { oKOption, NULL, 0, "@"}, { oPasswdFD, "passphrase-fd",1, "@" }, #ifdef __riscos__ { oPasswdFile, "passphrase-file",2, "@" }, @@ -549,7 +544,6 @@ static ARGPARSE_OPTS opts[] = { { oTrustModel, "trust-model", 2, "@"}, { oForceOwnertrust, "force-ownertrust", 2, "@"}, { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"}, - { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" }, { oSetFilename, "set-filename", 2, "@" }, { oForYourEyesOnly, "for-your-eyes-only", 0, "@" }, { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" }, @@ -879,8 +873,6 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) cmd = aSignSym; else if( cmd == aSym && new_cmd == aSign ) cmd = aSignSym; - else if( cmd == aKMode && new_cmd == aSym ) - cmd = aKModeC; else if( ( cmd == aSign && new_cmd == aClearsign ) || ( cmd == aClearsign && new_cmd == aSign ) ) cmd = aClearsign; @@ -1167,9 +1159,6 @@ main( int argc, char **argv ) int pwfd = -1; int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; -#ifdef USE_SHM_COPROCESSING - ulong requested_shm_size=0; -#endif #ifdef __riscos__ riscos_global_defaults(); @@ -1276,19 +1265,6 @@ main( int argc, char **argv ) opt.strict=0; log_set_strict(0); } -#ifdef USE_SHM_COPROCESSING - else if( pargs.r_opt == oRunAsShmCP ) { - /* does not make sense in a options file, we do it here, - * so that we are the able to drop setuid as soon as possible */ - opt.shm_coprocess = 1; - requested_shm_size = pargs.r.ret_ulong; - } - else if ( pargs.r_opt == oStatusFD ) { - /* this is needed to ensure that the status-fd filedescriptor is - * initialized when init_shm_coprocessing() is called */ - set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); - } -#endif } #ifdef HAVE_DOSISH_SYSTEM @@ -1301,11 +1277,7 @@ main( int argc, char **argv ) set_homedir (buf); } #endif -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) { - init_shm_coprocessing(requested_shm_size, 1 ); - } -#endif + /* Initialize the secure memory. */ gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); maybe_setuid = 0; @@ -1318,9 +1290,14 @@ main( int argc, char **argv ) if( default_config ) { - /* Try for a version specific config file first */ + /* Try for a version specific config file first but strip our + usual cvs suffix. That suffix indicates that it is not yet + the given version but we already want this config file. */ configname = make_filename(opt.homedir, "gpg" EXTSEP_S "conf-" SAFE_VERSION, NULL ); + if (!strcmp (configname + strlen (configname) - 4, "-cvs")) + configname[strlen (configname)-4] = 0; + if(access(configname,R_OK)) { xfree (configname); @@ -1458,7 +1435,6 @@ main( int argc, char **argv ) case oInteractive: opt.interactive = 1; break; case oVerbose: g10_opt_verbose++; opt.verbose++; opt.list_sigs=1; break; - case oKOption: set_cmd( &cmd, aKMode ); break; case oBatch: opt.batch = 1; nogreeting = 1; break; case oUseAgent: @@ -1631,17 +1607,6 @@ main( int argc, char **argv ) case oGnuPG: opt.compliance = CO_GNUPG; break; case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; case oCompressSigs: opt.compress_sigs = 1; break; - case oRunAsShmCP: -#ifndef __riscos__ -# ifndef USE_SHM_COPROCESSING - /* not possible in the option file, - * but we print the warning here anyway */ - log_error("shared memory coprocessing is not available\n"); -# endif -#else /* __riscos__ */ - riscos_not_implemented("run-as-shm-coprocess"); -#endif /* __riscos__ */ - break; case oSetFilename: opt.set_filename = pargs.r.ret_str; break; case oForYourEyesOnly: eyes_only = 1; break; case oNoForYourEyesOnly: eyes_only = 0; break; @@ -2276,21 +2241,6 @@ main( int argc, char **argv ) set_cmd( &cmd, aListKeys); } - if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */ - if( cmd == aKModeC ) { - opt.fingerprint = 1; - cmd = aKMode; - } - opt.list_sigs = 0; - if( opt.verbose > 2 ) - opt.check_sigs++; - if( opt.verbose > 1 ) - opt.list_sigs++; - - opt.verbose = opt.verbose > 1; - g10_opt_verbose = opt.verbose; - } - /* Compression algorithm 0 means no compression at all */ if( opt.def_compress_algo == 0) opt.compress = 0; @@ -2302,12 +2252,11 @@ main( int argc, char **argv ) if( opt.verbose > 1 ) set_packet_list_mode(1); - /* Add the keyrings, but not for some special commands and not in - case of "-kvv userid keyring". Also avoid adding the secret - keyring for a couple of commands to avoid unneeded access in - case the secrings are stored on a floppy */ - if( cmd != aDeArmor && cmd != aEnArmor - && !(cmd == aKMode && argc == 2 ) ) + /* Add the keyrings, but not for some special commands. Also + avoid adding the secret keyring for a couple of commands to + avoid unneeded access in case the secrings are stored on a + floppy */ + if( cmd != aDeArmor && cmd != aEnArmor ) { if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys && cmd != aVerify && cmd != aVerifyFiles @@ -2544,34 +2493,6 @@ main( int argc, char **argv ) free_strlist(sl); break; - case aKMode: /* list keyring -- NOTE: This will be removed soon */ - if( argc < 2 ) { /* -kv [userid] */ - sl = NULL; - if (argc && **argv) - add_to_strlist2( &sl, *argv, utf8_strings ); - public_key_list( sl ); - free_strlist(sl); - } - else if( argc == 2 ) { /* -kv userid keyring */ - if( access( argv[1], R_OK ) ) { - log_error(_("can't open %s: %s\n"), - print_fname_stdin(argv[1]), strerror(errno)); - } - else { - /* add keyring (default keyrings are not registered in this - * special case */ - keydb_add_resource( argv[1], 0, 0 ); - sl = NULL; - if (**argv) - add_to_strlist2( &sl, *argv, utf8_strings ); - public_key_list( sl ); - free_strlist(sl); - } - } - else - wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") ); - break; - case aKeygen: /* generate a key */ if( opt.batch ) { if( argc > 1 ) diff --git a/g10/pkglue.c b/g10/pkglue.c index 7920a5223..015aaf9ff 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -287,8 +287,39 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, } +/* Check whether SKEY is a suitable secret key. */ +int +pk_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_sexp_t s_skey; + int rc; + if (algo == GCRY_PK_DSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4]); + } + else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3]); + } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4], + skey[5]); + } + else + return GPG_ERR_PUBKEY_ALGO; - - - + if (!rc) + { + rc = gcry_pk_testkey (s_skey); + gcry_sexp_release (s_skey); + } + return rc; +} diff --git a/g10/pkglue.h b/g10/pkglue.h index 3065d66aa..43b82785b 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -29,6 +29,7 @@ int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey); int pk_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey); +int pk_check_secret_key (int algo, gcry_mpi_t *skey); #endif /*GNUPG_G10_PKGLUE_H*/ diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 5a7db4c97..5b0238240 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -215,14 +215,13 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, return gpg_error (GPG_ERR_BAD_PASSPHRASE); } /* the checksum may fail, so we also check the key itself */ -#warning fixme - we need to reenable this -/* res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey ); */ -/* if( res ) { */ -/* copy_secret_key( sk, save_sk ); */ -/* passphrase_clear_cache ( keyid, sk->pubkey_algo ); */ -/* free_secret_key( save_sk ); */ -/* return gpg_error (GPG_ERR_BAD_PASSPHRASE); */ -/* } */ + res = pk_check_secret_key (sk->pubkey_algo, sk->skey); + if (res) { + copy_secret_key( sk, save_sk ); + passphrase_clear_cache ( keyid, sk->pubkey_algo ); + free_secret_key( save_sk ); + return gpg_error (GPG_ERR_BAD_PASSPHRASE); + } free_secret_key( save_sk ); sk->is_protected = 0; } diff --git a/g10/status.c b/g10/status.c index 432ec575c..4414b33e9 100644 --- a/g10/status.c +++ b/g10/status.c @@ -1,5 +1,6 @@ /* status.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,21 +26,6 @@ #include <errno.h> #include <unistd.h> #include <signal.h> -#ifdef USE_SHM_COPROCESSING -#ifdef USE_CAPABILITIES -#include <sys/capability.h> -#endif -#ifdef HAVE_SYS_IPC_H -#include <sys/types.h> -#include <sys/ipc.h> -#endif -#ifdef HAVE_SYS_SHM_H -#include <sys/shm.h> -#endif -#if defined(HAVE_MLOCK) -#include <sys/mman.h> -#endif -#endif #include "gpg.h" #include "util.h" @@ -56,13 +42,6 @@ static FILE *statusfp; -#ifdef USE_SHM_COPROCESSING - static int shm_id = -1; - static volatile char *shm_area; - static size_t shm_size; - static int shm_is_locked; -#endif /*USE_SHM_COPROCESSING*/ - static void progress_cb (void *ctx, const char *what, int printchar, int current, int total) @@ -291,179 +270,6 @@ write_status_buffer ( int no, const char *buffer, size_t len, int wrap ) -#ifdef USE_SHM_COPROCESSING - -#ifndef IPC_RMID_DEFERRED_RELEASE -static void -remove_shmid( void ) -{ - if( shm_id != -1 ) { - shmctl ( shm_id, IPC_RMID, 0); - shm_id = -1; - } -} -#endif - -void -init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ) -{ - char buf[100]; - struct shmid_ds shmds; - -#ifndef IPC_RMID_DEFERRED_RELEASE - atexit( remove_shmid ); -#endif - requested_shm_size = (requested_shm_size + 4095) & ~4095; - if ( requested_shm_size > 2 * 4096 ) - log_fatal("too much shared memory requested; only 8k are allowed\n"); - shm_size = 4096 /* one page for us */ + requested_shm_size; - - shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 ); - if ( shm_id == -1 ) - log_fatal("can't get %uk of shared memory: %s\n", - (unsigned)shm_size/1024, strerror(errno)); - -#if !defined(IPC_HAVE_SHM_LOCK) \ - && defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK) - /* part of the old code which uses mlock */ - shm_area = shmat( shm_id, 0, 0 ); - if ( shm_area == (char*)-1 ) - log_fatal("can't attach %uk shared memory: %s\n", - (unsigned)shm_size/1024, strerror(errno)); - log_debug("mapped %uk shared memory at %p, id=%d\n", - (unsigned)shm_size/1024, shm_area, shm_id ); - if( lock_mem ) { -#ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); -#endif - /* (need the cast for Solaris with Sun's workshop compilers) */ - if ( mlock ( (char*)shm_area, shm_size) ) - log_info("locking shared memory %d failed: %s\n", - shm_id, strerror(errno)); - else - shm_is_locked = 1; -#ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+p") ); -#endif - } - -#ifdef IPC_RMID_DEFERRED_RELEASE - if( shmctl( shm_id, IPC_RMID, 0) ) - log_fatal("shmctl IPC_RMDID of %d failed: %s\n", - shm_id, strerror(errno)); -#endif - - if( shmctl( shm_id, IPC_STAT, &shmds ) ) - log_fatal("shmctl IPC_STAT of %d failed: %s\n", - shm_id, strerror(errno)); - if( shmds.shm_perm.uid != getuid() ) { - shmds.shm_perm.uid = getuid(); - if( shmctl( shm_id, IPC_SET, &shmds ) ) - log_fatal("shmctl IPC_SET of %d failed: %s\n", - shm_id, strerror(errno)); - } - -#else /* this is the new code which handles the changes in the SHM - * semantics introduced with Linux 2.4. The changes is that we - * now change the permissions and then attach to the memory. - */ - - if( lock_mem ) { -#ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); -#endif -#ifdef IPC_HAVE_SHM_LOCK - if ( shmctl (shm_id, SHM_LOCK, 0) ) - log_info("locking shared memory %d failed: %s\n", - shm_id, strerror(errno)); - else - shm_is_locked = 1; -#else - log_info("Locking shared memory %d failed: No way to do it\n", shm_id ); -#endif -#ifdef USE_CAPABILITIES - cap_set_proc( cap_from_text("cap_ipc_lock+p") ); -#endif - } - - if( shmctl( shm_id, IPC_STAT, &shmds ) ) - log_fatal("shmctl IPC_STAT of %d failed: %s\n", - shm_id, strerror(errno)); - if( shmds.shm_perm.uid != getuid() ) { - shmds.shm_perm.uid = getuid(); - if( shmctl( shm_id, IPC_SET, &shmds ) ) - log_fatal("shmctl IPC_SET of %d failed: %s\n", - shm_id, strerror(errno)); - } - - shm_area = shmat( shm_id, 0, 0 ); - if ( shm_area == (char*)-1 ) - log_fatal("can't attach %uk shared memory: %s\n", - (unsigned)shm_size/1024, strerror(errno)); - log_debug("mapped %uk shared memory at %p, id=%d\n", - (unsigned)shm_size/1024, shm_area, shm_id ); - -#ifdef IPC_RMID_DEFERRED_RELEASE - if( shmctl( shm_id, IPC_RMID, 0) ) - log_fatal("shmctl IPC_RMDID of %d failed: %s\n", - shm_id, strerror(errno)); -#endif - -#endif - /* write info; Protocol version, id, size, locked size */ - sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(), - shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 ); - write_status_text( STATUS_SHM_INFO, buf ); -} - -/**************** - * Request a string from client - * If bool, returns static string on true (do not free) or NULL for false - */ -static char * -do_shm_get( const char *keyword, int hidden, int bool ) -{ - size_t n; - byte *p; - char *string; - - if( !shm_area ) - BUG(); - - shm_area[0] = 0; /* msb of length of control block */ - shm_area[1] = 32; /* and lsb */ - shm_area[2] = 1; /* indicate that we are waiting on a reply */ - shm_area[3] = 0; /* clear data available flag */ - - write_status_text( bool? STATUS_SHM_GET_BOOL : - hidden? STATUS_SHM_GET_HIDDEN : STATUS_SHM_GET, keyword ); - - do { - pause_on_sigusr(1); - if( shm_area[0] || shm_area[1] != 32 || shm_area[2] != 1 ) - log_fatal("client modified shm control block - abort\n"); - } while( !shm_area[3] ); - shm_area[2] = 0; /* reset request flag */ - p = (byte*)shm_area+32; - n = p[0] << 8 | p[1]; - p += 2; - if( n+32+2+1 > 4095 ) - log_fatal("client returns too large data (%u bytes)\n", (unsigned)n ); - - if( bool ) - return p[0]? "" : NULL; - - string = hidden? xmalloc_secure ( n+1 ) : xmalloc ( n+1 ); - memcpy(string, p, n ); - string[n] = 0; /* make sure it is a string */ - if( hidden ) /* invalidate the memory */ - memset( p, 0, n ); - - return string; -} - -#endif /* USE_SHM_COPROCESSING */ - static int myread(int fd, void *buf, size_t count) { @@ -541,10 +347,6 @@ cpr_enabled() { if( opt.command_fd != -1 ) return 1; -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return 1; -#endif return 0; } @@ -555,10 +357,6 @@ cpr_get_no_help( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return do_get_from_fd ( keyword, 0, 0 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return do_shm_get( keyword, 0, 0 ); -#endif for(;;) { p = tty_get( prompt ); return p; @@ -572,10 +370,6 @@ cpr_get( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return do_get_from_fd ( keyword, 0, 0 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return do_shm_get( keyword, 0, 0 ); -#endif for(;;) { p = tty_get( prompt ); if( *p=='?' && !p[1] && !(keyword && !*keyword)) { @@ -608,10 +402,6 @@ cpr_get_hidden( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return do_get_from_fd ( keyword, 1, 0 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return do_shm_get( keyword, 1, 0 ); -#endif for(;;) { p = tty_get_hidden( prompt ); if( *p == '?' && !p[1] ) { @@ -628,10 +418,6 @@ cpr_kill_prompt(void) { if( opt.command_fd != -1 ) return; -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return; -#endif tty_kill_prompt(); return; } @@ -644,10 +430,6 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return !!do_get_from_fd ( keyword, 0, 1 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return !!do_shm_get( keyword, 0, 1 ); -#endif for(;;) { p = tty_get( prompt ); trim_spaces(p); /* it is okay to do this here */ @@ -672,10 +454,6 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return !!do_get_from_fd ( keyword, 0, 1 ); -#ifdef USE_SHM_COPROCESSING - if( opt.shm_coprocess ) - return !!do_shm_get( keyword, 0, 1 ); -#endif for(;;) { p = tty_get( prompt ); trim_spaces(p); /* it is okay to do this here */ diff --git a/g10/status.h b/g10/status.h index 44a7d6d32..4a0bcd45b 100644 --- a/g10/status.h +++ b/g10/status.h @@ -110,10 +110,6 @@ void write_status_buffer ( int no, void write_status_text_and_buffer ( int no, const char *text, const char *buffer, size_t len, int wrap ); -#ifdef USE_SHM_COPROCESSING - void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem ); -#endif /*USE_SHM_COPROCESSING*/ - int cpr_enabled(void); char *cpr_get( const char *keyword, const char *prompt ); char *cpr_get_no_help( const char *keyword, const char *prompt ); diff --git a/scd/ChangeLog b/scd/ChangeLog index ad4b0518c..ae2e6ce6e 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,25 @@ +2003-08-05 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (dump_all_do): Don't analyze constructed DOs after + an error. + +2003-08-04 Werner Koch <wk@gnupg.org> + + * app.c (app_set_default_reader_port): New. + (select_application): Use it here. + * scdaemon.c (main): and here. + * sc-copykeys.c: --reader-port does now take a string. + * sc-investigate.c, scdaemon.c: Ditto. + * apdu.c (apdu_open_reader): Ditto. Load pcsclite if no ctapi + driver is configured. Always include code for ctapi. + (new_reader_slot): Don't test for already used ports and remove + port arg. + (open_pcsc_reader, pcsc_send_apdu, pcsc_error_string): New. + (apdu_send_le): Changed RC to long to cope with PC/SC. + + * scdaemon.c, scdaemon.h: New option --ctapi-driver. + * sc-investigate.c, sc-copykeys.c: Ditto. + 2003-07-31 Werner Koch <wk@gnupg.org> * Makefile.am (scdaemon_LDADD): Added INTLLIBS. diff --git a/scd/apdu.c b/scd/apdu.c index 6fec584b9..60de5b953 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -29,8 +29,6 @@ #include "scdaemon.h" #include "apdu.h" -#define HAVE_CTAPI 1 - #define MAX_READER 4 /* Number of readers we support concurrently. */ #define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for insertion of the card (1 = don't wait). */ @@ -40,7 +38,13 @@ /* A global table to keep track of active readers. */ static struct { int used; /* True if slot is used. */ - unsigned short port; /* port number0 = unused, 1 - dev/tty */ + unsigned short port; /* Port number: 0 = unused, 1 - dev/tty */ + int is_ctapi; /* This is a ctAPI driver. */ + struct { + unsigned long context; + unsigned long card; + unsigned long protocol; + } pcsc; int status; unsigned char atr[33]; size_t atrlen; @@ -55,6 +59,61 @@ static char (*CT_data) (unsigned short ctn, unsigned char *dad, unsigned char *rsp); static char (*CT_close) (unsigned short ctn); +/* PC/SC constants and function pointer. */ +#define PCSC_SCOPE_USER 0 +#define PCSC_SCOPE_TERMINAL 1 +#define PCSC_SCOPE_SYSTEM 2 +#define PCSC_SCOPE_GLOBAL 3 + +#define PCSC_PROTOCOL_T0 1 +#define PCSC_PROTOCOL_T1 2 +#define PCSC_PROTOCOL_RAW 4 + +#define PCSC_SHARE_EXCLUSIVE 1 +#define PCSC_SHARE_SHARED 2 +#define PCSC_SHARE_DIRECT 3 + +#define PCSC_LEAVE_CARD 0 +#define PCSC_RESET_CARD 1 +#define PCSC_UNPOWER_CARD 2 +#define PCSC_EJECT_CARD 3 + +struct pcsc_io_request_s { + unsigned long protocol; + unsigned long pci_len; +}; + +typedef struct pcsc_io_request_s *pcsc_io_request_t; + +long (*pcsc_establish_context) (unsigned long scope, + const void *reserved1, + const void *reserved2, + unsigned long *r_context); +long (*pcsc_release_context) (unsigned long context); +long (*pcsc_list_readers) (unsigned long context, const char *groups, + char *readers, unsigned long *readerslen); +long (*pcsc_connect) (unsigned long context, + const char *reader, + unsigned long share_mode, + unsigned long preferred_protocols, + unsigned long *r_card, + unsigned long *r_active_protocol); +long (*pcsc_disconnect) (unsigned long card, unsigned long disposition); +long (*pcsc_status) (unsigned long card, + char *reader, unsigned long *readerlen, + unsigned long *r_state, unsigned long *r_protocol, + unsigned char *atr, unsigned long *atrlen); +long (*pcsc_begin_transaction) (unsigned long card); +long (*pcsc_end_transaction) (unsigned long card); +long (*pcsc_transmit) (unsigned long card, + const pcsc_io_request_t send_pci, + const unsigned char *send_buffer, + unsigned long send_len, + pcsc_io_request_t recv_pci, + unsigned char *recv_buffer, + unsigned long *recv_len); +long (*pcsc_set_timeout) (unsigned long context, unsigned long timeout); + @@ -64,28 +123,16 @@ static char (*CT_close) (unsigned short ctn); */ -/* Find an unused reader slot for PORT and put it into the reader +/* Find an unused reader slot for PORTSTR and put it into the reader table. Return -1 on error or the index into the reader table. */ static int -new_reader_slot (int port) +new_reader_slot (void) { int i, reader = -1; - if (port < 0 || port > 0xffff) - { - log_error ("new_reader_slot: invalid port %d requested\n", port); - return -1; - } - for (i=0; i < MAX_READER; i++) { - if (reader_table[i].used && reader_table[i].port == port) - { - log_error ("new_reader_slot: requested port %d already in use\n", - reader); - return -1; - } - else if (!reader_table[i].used && reader == -1) + if (!reader_table[i].used && reader == -1) reader = i; } if (reader == -1) @@ -94,7 +141,7 @@ new_reader_slot (int port) return -1; } reader_table[reader].used = 1; - reader_table[reader].port = port; + reader_table[reader].is_ctapi = 0; return reader; } @@ -102,11 +149,25 @@ new_reader_slot (int port) static void dump_reader_status (int reader) { - log_info ("reader %d: %s\n", reader, - reader_table[reader].status == 1? "Processor ICC present" : - reader_table[reader].status == 0? "Memory ICC present" : - "ICC not present" ); - + if (reader_table[reader].is_ctapi) + { + log_info ("reader slot %d: %s\n", reader, + reader_table[reader].status == 1? "Processor ICC present" : + reader_table[reader].status == 0? "Memory ICC present" : + "ICC not present" ); + } + else + { + log_info ("reader slot %d: active protocol:", reader); + if ((reader_table[reader].pcsc.protocol & PCSC_PROTOCOL_T0)) + log_printf (" T0"); + else if ((reader_table[reader].pcsc.protocol & PCSC_PROTOCOL_T1)) + log_printf (" T1"); + else if ((reader_table[reader].pcsc.protocol & PCSC_PROTOCOL_RAW)) + log_printf (" raw"); + log_printf ("\n"); + } + if (reader_table[reader].status != -1) { log_info ("reader %d: ATR=", reader); @@ -117,13 +178,12 @@ dump_reader_status (int reader) -#ifdef HAVE_CTAPI /* ct API Interface */ static const char * -ct_error_string (int err) +ct_error_string (long err) { switch (err) { @@ -150,7 +210,7 @@ ct_activate_card (int reader) unsigned short buflen; if (count) - sleep (1); /* FIXME: we should use a more reliable timer. */ + ; /* FIXME: we should use a more reliable timer than sleep. */ /* Check whether card has been inserted. */ dad[0] = 1; /* Destination address: CT. */ @@ -221,9 +281,15 @@ open_ct_reader (int port) { int rc, reader; - reader = new_reader_slot (port); + if (port < 0 || port > 0xffff) + { + log_error ("open_ct_reader: invalid port %d requested\n", port); + return -1; + } + reader = new_reader_slot (); if (reader == -1) return reader; + reader_table[reader].port = port; rc = CT_init (reader, (unsigned short)port); if (rc) @@ -241,6 +307,7 @@ open_ct_reader (int port) return -1; } + reader_table[reader].is_ctapi = 1; dump_reader_status (reader); return reader; } @@ -271,16 +338,205 @@ ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, } -#endif /*HAVE_CTAPI*/ - -#ifdef HAVE_PCSC +static const char * +pcsc_error_string (long err) +{ + const char *s; + + if (!err) + return "okay"; + if ((err & 0x80100000) != 0x80100000) + return "invalid PC/SC error code"; + err &= 0xffff; + switch (err) + { + case 0x0002: s = "cancelled"; break; + case 0x000e: s = "can't dispose"; break; + case 0x0008: s = "insufficient buffer"; break; + case 0x0015: s = "invalid ATR"; break; + case 0x0003: s = "invalid handle"; break; + case 0x0004: s = "invalid parameter"; break; + case 0x0005: s = "invalid target"; break; + case 0x0011: s = "invalid value"; break; + case 0x0006: s = "no memory"; break; + case 0x0013: s = "comm error"; break; + case 0x0001: s = "internal error"; break; + case 0x0014: s = "unknown error"; break; + case 0x0007: s = "waited too long"; break; + case 0x0009: s = "unknown reader"; break; + case 0x000a: s = "timeout"; break; + case 0x000b: s = "sharing violation"; break; + case 0x000c: s = "no smartcard"; break; + case 0x000d: s = "unknown card"; break; + case 0x000f: s = "proto mismatch"; break; + case 0x0010: s = "not ready"; break; + case 0x0012: s = "system cancelled"; break; + case 0x0016: s = "not transacted"; break; + case 0x0017: s = "reader unavailable"; break; + case 0x0065: s = "unsupported card"; break; + case 0x0066: s = "unresponsive card"; break; + case 0x0067: s = "unpowered card"; break; + case 0x0068: s = "reset card"; break; + case 0x0069: s = "removed card"; break; + case 0x006a: s = "inserted card"; break; + case 0x001f: s = "unsupported feature"; break; + case 0x0019: s = "PCI too small"; break; + case 0x001a: s = "reader unsupported"; break; + case 0x001b: s = "duplicate reader"; break; + case 0x001c: s = "card unsupported"; break; + case 0x001d: s = "no service"; break; + case 0x001e: s = "service stopped"; break; + default: s = "unknown PC/SC error code"; break; + } + return s; +} + /* PC/SC Interface */ +static int +open_pcsc_reader (const char *portstr) +{ + long err; + int slot; + char *list = NULL; + unsigned long nreader, listlen, atrlen; + char *p; + unsigned long card_state, card_protocol; + + slot = new_reader_slot (); + if (slot == -1) + return -1; + + err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL, + &reader_table[slot].pcsc.context); + if (err) + { + log_error ("pcsc_establish_context failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + reader_table[slot].used = 0; + return -1; + } + + err = pcsc_list_readers (reader_table[slot].pcsc.context, + NULL, NULL, &nreader); + if (!err) + { + list = xtrymalloc (nreader+1); /* Better add 1 for safety reasons. */ + if (!list) + { + log_error ("error allocating memory for reader list\n"); + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; + return -1; + } + err = pcsc_list_readers (reader_table[slot].pcsc.context, + NULL, list, &nreader); + } + if (err) + { + log_error ("pcsc_list_readers failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; + xfree (list); + return -1; + } + + listlen = nreader; + p = list; + while (nreader) + { + if (!*p && !p[1]) + break; + log_info ("detected reader `%s'\n", p); + if (nreader < (strlen (p)+1)) + { + log_error ("invalid response from pcsc_list_readers\n"); + break; + } + nreader -= strlen (p)+1; + p += strlen (p) + 1; + } + + err = pcsc_connect (reader_table[slot].pcsc.context, + portstr? portstr : list, + PCSC_SHARE_EXCLUSIVE, + PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, + &reader_table[slot].pcsc.card, + &reader_table[slot].pcsc.protocol); + if (err) + { + log_error ("pcsc_connect failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; + xfree (list); + return -1; + } + + atrlen = 32; + /* (We need to pass a dummy buffer. We use LIST because it ought to + be large enough.) */ + err = pcsc_status (reader_table[slot].pcsc.card, + list, &listlen, + &card_state, &card_protocol, + reader_table[slot].atr, &atrlen); + xfree (list); + if (err) + { + log_error ("pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; + return -1; + } + if (atrlen >= DIM (reader_table[0].atr)) + log_bug ("ATR returned by pcsc_status is too large\n"); + reader_table[slot].atrlen = atrlen; +/* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */ +/* log_debug ("protocol from pcsc_status: 0x%lx\n", card_protocol); */ + + dump_reader_status (slot); + return slot; +} + + +/* Actually send the APDU of length APDULEN to SLOT and return a + maximum of *BUFLEN data in BUFFER, the actual returned size will be + set to BUFLEN. Returns: CT API error code. */ +static int +pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) +{ + long err; + struct pcsc_io_request_s send_pci; + unsigned long recv_len; + + if (DBG_CARD_IO) + log_printhex (" CT_data:", apdu, apdulen); + + if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T1)) + send_pci.protocol = PCSC_PROTOCOL_T1; + else + send_pci.protocol = PCSC_PROTOCOL_T0; + send_pci.pci_len = sizeof send_pci; + recv_len = *buflen; + err = pcsc_transmit (reader_table[slot].pcsc.card, + &send_pci, apdu, apdulen, + NULL, buffer, &recv_len); + *buflen = recv_len; + if (err) + log_error ("pcsc_transmit failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + + return err? -1:0; +} + + -#endif /*HAVE_PCSC*/ /* @@ -288,35 +544,86 @@ ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, */ /* Open the reader and return an internal slot number or -1 on - error. */ + error. If PORTSTR is NULL we default to a suitable port (for ctAPI: + the first USB reader. For PCSC/ the first listed reader. */ int -apdu_open_reader (int port) +apdu_open_reader (const char *portstr) { - static int ct_api_loaded; + static int pcsc_api_loaded, ct_api_loaded; + + if (opt.ctapi_driver && *opt.ctapi_driver) + { + int port = portstr? atoi (portstr) : 32768; + + if (!ct_api_loaded) + { + void *handle; + + handle = dlopen (opt.ctapi_driver, RTLD_LAZY); + if (!handle) + { + log_error ("apdu_open_reader: failed to open driver: %s", + dlerror ()); + return -1; + } + CT_init = dlsym (handle, "CT_init"); + CT_data = dlsym (handle, "CT_data"); + CT_close = dlsym (handle, "CT_close"); + if (!CT_init || !CT_data || !CT_close) + { + log_error ("apdu_open_reader: invalid ctAPI driver\n"); + dlclose (handle); + return -1; + } + ct_api_loaded = 1; + } + return open_ct_reader (port); + } - if (!ct_api_loaded) + + /* No ctAPI configured, so lets try the PC/SC API */ + if (!pcsc_api_loaded) { void *handle; - handle = dlopen ("libtowitoko.so", RTLD_LAZY); + handle = dlopen ("libpcsclite.so", RTLD_LAZY); if (!handle) { log_error ("apdu_open_reader: failed to open driver: %s", dlerror ()); return -1; } - CT_init = dlsym (handle, "CT_init"); - CT_data = dlsym (handle, "CT_data"); - CT_close = dlsym (handle, "CT_close"); - if (!CT_init || !CT_data || !CT_close) + + pcsc_establish_context = dlsym (handle, "SCardEstablishContext"); + pcsc_release_context = dlsym (handle, "SCardReleaseContext"); + pcsc_list_readers = dlsym (handle, "SCardListReaders"); + pcsc_connect = dlsym (handle, "SCardConnect"); + pcsc_disconnect = dlsym (handle, "SCardDisconnect"); + pcsc_status = dlsym (handle, "SCardStatus"); + pcsc_begin_transaction = dlsym (handle, "SCardBeginTransaction"); + pcsc_end_transaction = dlsym (handle, "SCardEndTransaction"); + pcsc_transmit = dlsym (handle, "SCardTransmit"); + pcsc_set_timeout = dlsym (handle, "SCardSetTimeout"); + + if (!pcsc_establish_context + || !pcsc_release_context + || !pcsc_list_readers + || !pcsc_connect + || !pcsc_disconnect + || !pcsc_status + || !pcsc_begin_transaction + || !pcsc_end_transaction + || !pcsc_transmit + || !pcsc_set_timeout) { - log_error ("apdu_open_reader: invalid driver\n"); + log_error ("apdu_open_reader: invalid PC/SC driver\n"); dlclose (handle); return -1; } - ct_api_loaded = 1; + pcsc_api_loaded = 1; } - return open_ct_reader (port); + + return open_pcsc_reader (portstr); } @@ -338,15 +645,14 @@ apdu_get_atr (int slot, size_t *atrlen) static const char * -error_string (int slot, int rc) +error_string (int slot, long rc) { -#ifdef HAVE_CTAPI - return ct_error_string (rc); -#elif defined(HAVE_PCSC) - return "?"; -#else - return "?"; -#endif + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return "[invalid slot]"; + if (reader_table[slot].is_ctapi) + return ct_error_string (rc); + else + return pcsc_error_string (rc); } @@ -355,13 +661,12 @@ static int send_apdu (int slot, unsigned char *apdu, size_t apdulen, unsigned char *buffer, size_t *buflen) { -#ifdef HAVE_CTAPI - return ct_send_apdu (slot, apdu, apdulen, buffer, buflen); -#elif defined(HAVE_PCSC) - return SW_HOST_NO_DRIVER; -#else - return SW_HOST_NO_DRIVER; -#endif + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + if (reader_table[slot].is_ctapi) + return ct_send_apdu (slot, apdu, apdulen, buffer, buflen); + else + return pcsc_send_apdu (slot, apdu, apdulen, buffer, buflen); } /* Send an APDU to the card in SLOT. The APDU is created from all @@ -382,7 +687,8 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, size_t resultlen = 256; unsigned char apdu[5+256+1]; size_t apdulen; - int rc, sw; + int sw; + long rc; /* we need a long here due to PC/SC. */ if (DBG_CARD_IO) log_debug ("send apdu: c=%02X i=%02X p0=%02X p1=%02X lc=%d le=%d\n", diff --git a/scd/apdu.h b/scd/apdu.h index 44166a3fe..6e4244ba0 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -47,12 +47,13 @@ enum { between errnos on a failed malloc. */ SW_HOST_INV_VALUE = 0x10002, SW_HOST_INCOMPLETE_CARD_RESPONSE = 0x10003, + SW_HOST_NO_DRIVER = 0x10004 }; /* Note , that apdu_open_reader returns no status word but -1 on error. */ -int apdu_open_reader (int port); +int apdu_open_reader (const char *portstr); unsigned char *apdu_get_atr (int slot, size_t *atrlen); diff --git a/scd/app-common.h b/scd/app-common.h index 282f82715..1243ca3ec 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -69,6 +69,7 @@ struct app_ctx_s { }; /*-- app.c --*/ +void app_set_default_reader_port (const char *portstr); APP select_application (void); int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); int app_write_learn_status (APP app, CTRL ctrl); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 09a19699d..7f6114292 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -214,71 +214,6 @@ get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes) return NULL; } -#if 0 /* not used */ -static void -dump_one_do (int slot, int tag) -{ - int rc, i; - unsigned char *buffer; - size_t buflen; - const char *desc; - int binary; - const unsigned char *value; - size_t valuelen; - - for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++) - ; - desc = data_objects[i].tag? data_objects[i].desc : "?"; - binary = data_objects[i].tag? data_objects[i].binary : 1; - - value = NULL; - rc = -1; - if (data_objects[i].tag && data_objects[i].get_from) - { - rc = iso7816_get_data (slot, data_objects[i].get_from, - &buffer, &buflen); - if (!rc) - { - value = find_tlv (buffer, buflen, tag, &valuelen, 0); - if (!value) - ; /* not found */ - else if (valuelen > buflen - (value - buffer)) - { - log_error ("warning: constructed DO too short\n"); - value = NULL; - xfree (buffer); buffer = NULL; - } - } - } - - if (!value) /* Not in a constructed DO, try simple. */ - { - rc = iso7816_get_data (slot, tag, &buffer, &buflen); - if (!rc) - { - value = buffer; - valuelen = buflen; - } - } - if (rc == 0x6a88) - log_info ("DO `%s' not available\n", desc); - else if (rc) - log_info ("DO `%s' not available (rc=%04X)\n", desc, rc); - else - { - if (binary) - { - log_info ("DO `%s': ", desc); - log_printhex ("", value, valuelen); - } - else - log_info ("DO `%s': `%.*s'\n", - desc, (int)valuelen, value); /* FIXME: sanitize */ - xfree (buffer); - } -} -#endif /*not used*/ - static void dump_all_do (int slot) @@ -293,11 +228,11 @@ dump_all_do (int slot) continue; rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen); - if (rc == 0x6a88) + if (gpg_error (rc) == GPG_ERR_NO_OBJ) ; else if (rc) - log_info ("DO `%s' not available (rc=%04X)\n", - data_objects[i].desc, rc); + log_info ("DO `%s' not available: %s\n", + data_objects[i].desc, gpg_strerror (rc)); else { if (data_objects[i].binary) @@ -309,34 +244,34 @@ dump_all_do (int slot) log_info ("DO `%s': `%.*s'\n", data_objects[i].desc, (int)buflen, buffer); /* FIXME: sanitize */ - } - if (data_objects[i].constructed) - { - for (j=0; data_objects[j].tag; j++) + if (data_objects[i].constructed) { - const unsigned char *value; - size_t valuelen; - - if (j==i || data_objects[i].tag != data_objects[j].get_from) - continue; - value = find_tlv (buffer, buflen, - data_objects[j].tag, &valuelen, 0); - if (!value) - ; /* not found */ - else if (valuelen > buflen - (value - buffer)) - log_error ("warning: constructed DO too short\n"); - else + for (j=0; data_objects[j].tag; j++) { - if (data_objects[j].binary) + const unsigned char *value; + size_t valuelen; + + if (j==i || data_objects[i].tag != data_objects[j].get_from) + continue; + value = find_tlv (buffer, buflen, + data_objects[j].tag, &valuelen, 0); + if (!value) + ; /* not found */ + else if (valuelen > buflen - (value - buffer)) + log_error ("warning: constructed DO too short\n"); + else { - log_info ("DO `%s': ", data_objects[j].desc); - log_printhex ("", value, valuelen); + if (data_objects[j].binary) + { + log_info ("DO `%s': ", data_objects[j].desc); + log_printhex ("", value, valuelen); + } + else + log_info ("DO `%s': `%.*s'\n", + data_objects[j].desc, + (int)valuelen, value); /* FIXME: sanitize */ } - else - log_info ("DO `%s': `%.*s'\n", - data_objects[j].desc, - (int)valuelen, value); /* FIXME: sanitize */ } } } @@ -410,7 +345,7 @@ store_fpr (int slot, int keynumber, u32 timestamp, rc = iso7816_put_data (slot, (card_version > 0x0007? 0xC7 : 0xC6) + keynumber, fpr, 20); if (rc) - log_error ("failed to store the fingerprint: rc=%04X\n", rc); + log_error ("failed to store the fingerprint: %s\n",gpg_strerror (rc)); return rc; } @@ -582,7 +517,7 @@ do_setattr (APP app, const char *name, xfree (pinvalue); if (rc) { - log_error ("verify CHV3 failed\n"); + log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); rc = gpg_error (GPG_ERR_GENERAL); return rc; } @@ -626,7 +561,7 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, xfree (pinvalue); if (rc) { - log_error ("verify CHV3 failed: rc=%04X\n", rc); + log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); goto leave; } } @@ -642,7 +577,7 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, xfree (pinvalue); if (rc) { - log_error ("verify CHV1 failed: rc=%04X\n", rc); + log_error ("verify CHV1 failed: rc=%s\n", gpg_strerror (rc)); goto leave; } } @@ -658,7 +593,7 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, xfree (pinvalue); if (rc) { - log_error ("verify CHV2 failed: rc=%04X\n", rc); + log_error ("verify CHV2 failed: rc=%s\n", gpg_strerror (rc)); goto leave; } } @@ -757,7 +692,7 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, } if (rc) { - log_error ("verify CHV3 failed: rc=%04X\n", rc); + log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); goto leave; } @@ -1224,8 +1159,6 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) rc = iso7816_select_application (slot, aid, sizeof aid); if (!rc) { - /* fixme: get the full AID and check that the version is okay - with us. */ rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); if (rc) goto leave; @@ -1386,7 +1319,7 @@ app_openpgp_storekey (APP app, int keyno, } if (rc) { - log_error ("verify CHV3 failed: rc=%04X\n", rc); + log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); goto leave; } @@ -1395,7 +1328,7 @@ app_openpgp_storekey (APP app, int keyno, template, template_len); if (rc) { - log_error ("failed to store the key: rc=%04X\n", rc); + log_error ("failed to store the key: rc=%s\n", gpg_strerror (rc)); rc = gpg_error (GPG_ERR_CARD); goto leave; } diff --git a/scd/app.c b/scd/app.c index 7a85df336..04b421b55 100644 --- a/scd/app.c +++ b/scd/app.c @@ -30,17 +30,26 @@ #include "apdu.h" #include "iso7816.h" +static char *default_reader_port; + +void +app_set_default_reader_port (const char *portstr) +{ + xfree (default_reader_port); + default_reader_port = portstr? xstrdup (portstr): NULL; +} + + /* The select the best fitting application and return a context. Returns NULL if no application was found or no card is present. */ APP select_application (void) { - int reader_port = 32768; /* First USB reader. */ int slot; int rc; APP app; - slot = apdu_open_reader (reader_port); + slot = apdu_open_reader (default_reader_port); if (slot == -1) { log_error ("card reader not available\n"); diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c index 9caf39a8a..b56b88590 100644 --- a/scd/sc-copykeys.c +++ b/scd/sc-copykeys.c @@ -44,6 +44,7 @@ enum cmd_and_opt_values { oVerbose = 'v', oReaderPort = 500, + octapiDriver, oDebug, oDebugAll, @@ -55,7 +56,8 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, "@Options:\n " }, { oVerbose, "verbose", 0, "verbose" }, - { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"}, + { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"}, + { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"}, { oDebug, "debug" ,4|16, "set debugging flags"}, { oDebugAll, "debug-all" ,0, "enable full debugging"}, {0} @@ -115,7 +117,7 @@ main (int argc, char **argv ) { ARGPARSE_ARGS pargs; int slot, rc; - int reader_port = 32768; /* First USB reader. */ + const char *reader_port = NULL; struct app_ctx_s appbuf; memset (&appbuf, 0, sizeof appbuf); @@ -146,6 +148,8 @@ main (int argc, char **argv ) case oVerbose: opt.verbose++; break; case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; + case oReaderPort: reader_port = pargs.r.ret_str; break; + case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; default : pargs.err = 2; break; } } diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index e8f0eb83c..ecd385690 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -39,6 +39,7 @@ enum cmd_and_opt_values { oVerbose = 'v', oReaderPort = 500, + octapiDriver, oDebug, oDebugAll, @@ -52,7 +53,8 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, "@Options:\n " }, { oVerbose, "verbose", 0, "verbose" }, - { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"}, + { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"}, + { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"}, { oDebug, "debug" ,4|16, "set debugging flags"}, { oDebugAll, "debug-all" ,0, "enable full debugging"}, { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"}, @@ -108,7 +110,7 @@ main (int argc, char **argv ) { ARGPARSE_ARGS pargs; int slot, rc; - int reader_port = 32768; /* First USB reader. */ + const char *reader_port = NULL; struct app_ctx_s appbuf; unsigned long gen_random = 0; @@ -139,6 +141,8 @@ main (int argc, char **argv ) case oVerbose: opt.verbose++; break; case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; + case oReaderPort: reader_port = pargs.r.ret_str; break; + case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; case oGenRandom: gen_random = pargs.r.ret_ulong; break; default : pargs.err = 2; break; } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 8e0ef37c9..11952615d 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -43,7 +43,7 @@ #include "i18n.h" #include "sysutils.h" - +#include "app-common.h" enum cmd_and_opt_values @@ -69,6 +69,7 @@ enum cmd_and_opt_values oDaemon, oBatch, oReaderPort, + octapiDriver, aTest }; @@ -91,8 +92,8 @@ static ARGPARSE_OPTS opts[] = { { oDebugSC, "debug-sc", 1, N_("|N|set OpenSC debug level to N")}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - { oReaderPort, "reader-port", 1, N_("|N|connect to reader at port N")}, - + { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, + { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ctAPI driver")}, {0} }; @@ -230,7 +231,6 @@ main (int argc, char **argv ) int csh_style = 0; char *logfile = NULL; int debug_wait = 0; - int reader_port = 32768; /* First USB reader. */ set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -299,6 +299,7 @@ main (int argc, char **argv ) if (default_config) configname = make_filename (opt.homedir, "scdaemon.conf", NULL ); + argc = orig_argc; argv = orig_argv; @@ -365,7 +366,8 @@ main (int argc, char **argv ) case oServer: pipe_server = 1; break; case oDaemon: is_daemon = 1; break; - case oReaderPort: reader_port = pargs.r.ret_int; break; + case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break; + case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; default : pargs.err = configfp? 1:2; break; } diff --git a/scd/scdaemon.h b/scd/scdaemon.h index b21e19f8c..bdc4c21b3 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -53,6 +53,7 @@ struct { int dry_run; /* don't change any persistent data */ int batch; /* batch mode */ const char *homedir; /* configuration directory name */ + const char *ctapi_driver; /* Library to access the ctAPI. */ } opt; -- cgit v1.2.3 From c9c41927635b55500f4b0d2f3cc04f9bc2b024cd Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 5 Aug 2003 17:20:18 +0000 Subject: About to release the first 1.9 version. --- ChangeLog | 4 +++- Makefile.am | 2 +- NEWS | 9 ++++++--- configure.ac | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 83e9cba0c..00acca1c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,9 @@ 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 diff --git a/Makefile.am b/Makefile.am index be749a5c1..d5c639042 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,7 @@ ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = scripts/config.rpath autogen.sh +EXTRA_DIST = scripts/config.rpath autogen.sh README-alpha DISTCLEANFILES = g10defs.h if BUILD_GPG diff --git a/NEWS b/NEWS index 9e6b9f1af..8165e07b7 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,13 @@ -Noteworthy changes in version 1.9.0 (unreleased) +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 solution to allow co-existing with stable gpg versions. + temporary change to allow co-existing with stable gpg versions. - * The default config file is ~/.gnupg/gpg.conf-1.9.0 if it exists. + * ~/.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. diff --git a/configure.ac b/configure.ac index 060f31d97..3bfcbe026 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.0-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.0, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 4140c3d44780bec48256a47b8a9cfdd9056e53f3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 5 Aug 2003 18:55:40 +0000 Subject: Bumbed version number --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8165e07b7..d275fddfc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.1 (unreleased) +------------------------------------------------ + + Noteworthy changes in version 1.9.0 (2003-08-05) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 3bfcbe026..0d12770a9 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.0, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.1-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From dbb7f4c89c774e160e981d6456b1c5bb868ffaef Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 7 Aug 2003 07:05:38 +0000 Subject: (pk_sign): Fix last change. (pk_verify): Check for valid DATA array so that we don't segv in Libgcrypt. (pk_verify): Ditto. --- g10/ChangeLog | 11 +++++++++++ g10/pkglue.c | 46 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f878be64d..33d38cf13 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,14 @@ +2003-08-07 Werner Koch <wk@gnupg.org> + + * pkglue.c (pk_sign): Fix last change. + (pk_verify): Check for valid DATA array so that we don't segv in + Libgcrypt. + (pk_verify): Ditto. + +2003-08-06 Werner Koch <wk@gnupg.org> + + * pkglue.c (pk_sign): Allow signing using RSA. + 2003-08-05 Werner Koch <wk@gnupg.org> * Makefile.am (install-data-local): Dropped check for the ancient diff --git a/g10/pkglue.c b/g10/pkglue.c index 015aaf9ff..abec77d9d 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -48,6 +48,13 @@ pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", skey[0], skey[1], skey[2], skey[3], skey[4]); } + else if (algo == GCRY_PK_RSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4], + skey[5]); + } else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) { rc = gcry_sexp_build (&s_skey, NULL, @@ -70,6 +77,14 @@ pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) if (rc) ; + else if (algo == GCRY_PK_RSA) + { + list = gcry_sexp_find_token (s_sig, "s", 0); + assert (list); + data[0] = gcry_sexp_nth_mpi (list, 1, 0); + assert (data[0]); + gcry_sexp_release (list); + } else { list = gcry_sexp_find_token (s_sig, "r", 0); @@ -131,17 +146,26 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) /* put data into a S-Exp s_sig */ if (algo == GCRY_PK_DSA) { - rc = gcry_sexp_build (&s_sig, NULL, - "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); + if (!data[0] || !data[1]) + rc = gpg_error (GPG_ERR_BAD_MPI); + else + rc = gcry_sexp_build (&s_sig, NULL, + "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); } else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) { - rc = gcry_sexp_build (&s_sig, NULL, - "(sig-val(elg(r%m)(s%m)))", data[0], data[1]); + if (!data[0] || !data[1]) + rc = gpg_error (GPG_ERR_BAD_MPI); + else + rc = gcry_sexp_build (&s_sig, NULL, + "(sig-val(elg(r%m)(s%m)))", data[0], data[1]); } else if (algo == GCRY_PK_RSA) { - rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]); + if (!data[0]) + rc = gpg_error (GPG_ERR_BAD_MPI); + else + rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]); } else BUG (); @@ -259,12 +283,18 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, /* put data into a S-Exp s_data */ if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) { - rc = gcry_sexp_build (&s_data, NULL, - "(enc-val(elg(a%m)(b%m)))", data[0], data[1]); + if (!data[0] || !data[1]) + rc = gpg_error (GPG_ERR_BAD_MPI); + else + rc = gcry_sexp_build (&s_data, NULL, + "(enc-val(elg(a%m)(b%m)))", data[0], data[1]); } else if (algo == GCRY_PK_RSA) { - rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]); + if (!data[0]) + rc = gpg_error (GPG_ERR_BAD_MPI); + else + rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]); } else BUG (); -- cgit v1.2.3 From 2bf665e188bb0d56d233309e2343fdf03ceda108 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 12:06:43 +0000 Subject: 2003-08-14 Timo Schulz <twoaday@freakmail.de> * dlfcn.h. New. W32 wrapper around the dynload mechanism. --- common/ChangeLog | 4 ++++ common/dlfcn.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 common/dlfcn.h diff --git a/common/ChangeLog b/common/ChangeLog index 4870a4a5d..67f53f50b 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2003-08-14 Timo Schulz <twoaday@freakmail.de> + + * dlfcn.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. diff --git a/common/dlfcn.h b/common/dlfcn.h new file mode 100644 index 000000000..c88bf3be9 --- /dev/null +++ b/common/dlfcn.h @@ -0,0 +1,71 @@ +/* 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 __MINGW32__ +#include <dlfcn.h> /* include the actual header file */ +#else +#ifndef W32_DLFCN_H +#define W32_DLFCN_H + +#include <windows.h> + +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 /*W32_DLFCN_H*/ +#endif -- cgit v1.2.3 From f099ed75b84dcafb02c8dbebe885ea3e76e26cb7 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 12:16:58 +0000 Subject: *** empty log message *** --- common/ChangeLog | 2 +- common/dlfcn.h | 71 -------------------------------------------------------- common/dynload.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 72 deletions(-) delete mode 100644 common/dlfcn.h create mode 100644 common/dynload.h diff --git a/common/ChangeLog b/common/ChangeLog index 67f53f50b..6666b5941 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,6 +1,6 @@ 2003-08-14 Timo Schulz <twoaday@freakmail.de> - * dlfcn.h. New. W32 wrapper around the dynload mechanism. + * dynload.h. New. W32 wrapper around the dynload mechanism. 2003-07-15 Werner Koch <wk@gnupg.org> diff --git a/common/dlfcn.h b/common/dlfcn.h deleted file mode 100644 index c88bf3be9..000000000 --- a/common/dlfcn.h +++ /dev/null @@ -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 __MINGW32__ -#include <dlfcn.h> /* include the actual header file */ -#else -#ifndef W32_DLFCN_H -#define W32_DLFCN_H - -#include <windows.h> - -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 /*W32_DLFCN_H*/ -#endif diff --git a/common/dynload.h b/common/dynload.h new file mode 100644 index 000000000..d2df5f017 --- /dev/null +++ b/common/dynload.h @@ -0,0 +1,69 @@ +/* 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> + +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*/ -- cgit v1.2.3 From abbb66e037ff7565d2f4b196cf4d14fddbad02b2 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 12:20:08 +0000 Subject: * Always use 'dynload.h' instead of 'dlfcn.h'. --- scd/ChangeLog | 6 ++++++ scd/apdu.c | 55 ++++++++++++++++++++++++++----------------------------- scd/app.c | 3 ++- scd/atr.c | 2 +- scd/iso7816.c | 2 +- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index ae2e6ce6e..d78c4aa16 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2003-08-14 Timo Schulz <twoaday@freakmail.de> + + * apdu.c (ct_activate_card): Change the code a little to avoid + problems with other readers. + * Always use 'dynload.h' instead of 'dlfcn.h'. + 2003-08-05 Werner Koch <wk@gnupg.org> * app-openpgp.c (dump_all_do): Don't analyze constructed DOs after diff --git a/scd/apdu.c b/scd/apdu.c index 60de5b953..6afcd6711 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -23,11 +23,11 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <dlfcn.h> #include <assert.h> #include "scdaemon.h" #include "apdu.h" +#include "dynload.h" #define MAX_READER 4 /* Number of readers we support concurrently. */ #define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for @@ -232,40 +232,37 @@ ct_activate_card (int reader) return -1; } - if (buf[0] == 0x05) - { /* Connected, now activate the card. */ - dad[0] = 1; /* Destination address: CT. */ - sad[0] = 2; /* Source address: Host. */ + /* Connected, now activate the card. */ + dad[0] = 1; /* Destination address: CT. */ + sad[0] = 2; /* Source address: Host. */ - cmd[0] = 0x20; /* Class byte. */ - cmd[1] = 0x12; /* Request ICC. */ - cmd[2] = 0x01; /* From first interface. */ - cmd[3] = 0x01; /* Return card's ATR. */ - cmd[4] = 0x00; - - buflen = DIM(buf); + cmd[0] = 0x20; /* Class byte. */ + cmd[1] = 0x12; /* Request ICC. */ + cmd[2] = 0x01; /* From first interface. */ + cmd[3] = 0x01; /* Return card's ATR. */ + cmd[4] = 0x00; - rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf); - if (rc || buflen < 2 || buf[buflen-2] != 0x90) - { - log_error ("ct_activate_card(%d): activation failed: %s\n", - reader, ct_error_string (rc)); - return -1; - } + buflen = DIM(buf); - /* Store the type and the ATR. */ - if (buflen - 2 > DIM (reader_table[0].atr)) - { - log_error ("ct_activate_card(%d): ATR too long\n", reader); - return -1; - } + rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf); + if (rc || buflen < 2 || buf[buflen-2] != 0x90) + { + log_error ("ct_activate_card(%d): activation failed: %s\n", + reader, ct_error_string (rc)); + return -1; + } - reader_table[reader].status = buf[buflen - 1]; - memcpy (reader_table[reader].atr, buf, buflen - 2); - reader_table[reader].atrlen = buflen - 2; - return 0; + /* Store the type and the ATR. */ + if (buflen - 2 > DIM (reader_table[0].atr)) + { + log_error ("ct_activate_card(%d): ATR too long\n", reader); + return -1; } + reader_table[reader].status = buf[buflen - 1]; + memcpy (reader_table[reader].atr, buf, buflen - 2); + reader_table[reader].atrlen = buflen - 2; + return 0; } log_info ("ct_activate_card(%d): timeout waiting for card\n", reader); diff --git a/scd/app.c b/scd/app.c index 04b421b55..fa5df8a72 100644 --- a/scd/app.c +++ b/scd/app.c @@ -23,12 +23,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <dlfcn.h> + #include "scdaemon.h" #include "app-common.h" #include "apdu.h" #include "iso7816.h" +#include "dynload.h" static char *default_reader_port; diff --git a/scd/atr.c b/scd/atr.c index 4e15aad50..6475e83f8 100644 --- a/scd/atr.c +++ b/scd/atr.c @@ -23,12 +23,12 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <dlfcn.h> #include <assert.h> #include "scdaemon.h" #include "apdu.h" #include "atr.h" +#include "dynload.h" static int const fi_table[16] = { 0, 372, 558, 744, 1116,1488, 1860, -1, -1, 512, 768, 1024, 1536, 2048, -1, -1 }; diff --git a/scd/iso7816.c b/scd/iso7816.c index 8903d8a5c..2b06103ef 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -23,11 +23,11 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <dlfcn.h> #include "scdaemon.h" #include "iso7816.h" #include "apdu.h" +#include "dynload.h" #define CMD_SELECT_FILE 0xA4 #define CMD_VERIFY 0x20 -- cgit v1.2.3 From 7abac1ad8e7dfd494f9c8cb03d40eb42d96558a5 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 19:06:46 +0000 Subject: 2003-08-14 Timo Schulz <twoaday@freakmail.de> * pksign.c: do_encode_md: Due to the fact pkcs#1 padding is now in Libgcrypt, use the new interface. --- agent/ChangeLog | 5 +++++ agent/pksign.c | 69 ++++++++++++++++++--------------------------------------- 2 files changed, 27 insertions(+), 47 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 10f4d45fa..0c7857811 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2003-08-14 Timo Schulz <twoaday@freakmail.de> + + * pksign.c: do_encode_md: Due to the fact pkcs#1 padding + is now in Libgcrypt, use the new interface. + 2003-07-31 Werner Koch <wk@gnupg.org> * Makefile.am (gpg_agent_LDADD): Added INTLLIBS. diff --git a/agent/pksign.c b/agent/pksign.c index fba2c652c..37c85cad8 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -32,54 +32,32 @@ static int -do_encode_md (const unsigned char *digest, size_t digestlen, int algo, - unsigned int nbits, gcry_mpi_t *r_val) +do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) { - int nframe = (nbits+7) / 8; - byte *frame; - int i, n; - byte asn[100]; - size_t asnlen; - - asnlen = DIM(asn); - if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + gcry_sexp_t hash; + const char * s; + char * p, tmp[16]; + int i, rc; + + p = xmalloc (64+mdlen); + s = gcry_md_algo_name (algo); + if (s && strlen (s) < 16) { - log_error ("no object identifier for algo %d\n", algo); - return gpg_error (GPG_ERR_INTERNAL); + for (i=0; i < strlen (s); i++) + tmp[i] = tolower (s[i]); + tmp[i] = '\0'; } - - if (digestlen + asnlen + 4 > nframe ) + sprintf (p, "(data\n (flags pkcs1)\n (hash %s #", tmp); + for (i=0; i < mdlen; i++) { - log_error ("can't encode a %d bit MD into a %d bits frame\n", - (int)(digestlen*8), (int)nbits); - return gpg_error (GPG_ERR_INTERNAL); + sprintf (tmp, "%02x", md[i]); + strcat (p, tmp); } - - /* We encode the MD in this way: - * - * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = xtrymalloc (nframe); - if (!frame) - return out_of_core (); - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - digestlen - asnlen -3 ; - assert ( i > 1 ); - memset ( frame+n, 0xff, i ); n += i; - frame[n++] = 0; - memcpy ( frame+n, asn, asnlen ); n += asnlen; - memcpy ( frame+n, digest, digestlen ); n += digestlen; - assert ( n == nframe ); - if (DBG_CRYPTO) - log_printhex ("encoded hash:", frame, nframe); - - gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe); - xfree (frame); - return 0; + strcat (p, "#))\n"); + rc = gcry_sexp_sscan (&hash, NULL, p, strlen (p)); + xfree (p); + *r_hash = hash; + return rc; } @@ -132,12 +110,9 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) rc = do_encode_md (ctrl->digest.value, ctrl->digest.valuelen, ctrl->digest.algo, - gcry_pk_get_nbits (s_skey), - &frame); + &s_hash); if (rc) goto leave; - if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) - BUG (); if (DBG_CRYPTO) { -- cgit v1.2.3 From aa6e3f7d2872295ed3c3cc735d721c95dcb0f563 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 19:10:12 +0000 Subject: Forgot to remove the unsued variable. --- agent/pksign.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/agent/pksign.c b/agent/pksign.c index 37c85cad8..3022e79a7 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -67,7 +67,6 @@ int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) { gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL; - gcry_mpi_t frame = NULL; unsigned char *shadow_info = NULL; int rc; char *buf = NULL; @@ -151,7 +150,6 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) gcry_sexp_release (s_skey); gcry_sexp_release (s_hash); gcry_sexp_release (s_sig); - gcry_mpi_release (frame); xfree (buf); xfree (shadow_info); return rc; -- cgit v1.2.3 From 81a0683e219ef3d1d702f88127084c03d8066308 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 19:39:30 +0000 Subject: 2003-08-14 Timo Schulz <twoaday@freakmail.de> * encrypt.c (encode_session_key): Use new Libgcrypt interface. --- sm/ChangeLog | 4 +++ sm/encrypt.c | 97 ++++++++++++------------------------------------------------ 2 files changed, 23 insertions(+), 78 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 59a6b3271..87874ca7f 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2003-08-14 Timo Schulz <twoaday@freakmail.de> + + * encrypt.c (encode_session_key): Use new Libgcrypt interface. + 2003-07-31 Werner Koch <wk@gnupg.org> * Makefile.am (gpgsm_LDADD): Added INTLLIBS. diff --git a/sm/encrypt.c b/sm/encrypt.c index 725a81b70..b6770a4b5 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -126,81 +126,29 @@ init_dek (DEK dek) } -/* Encode the session key. NBITS is the number of bits which should be - used for packing the session key. returns: An mpi with the session - key (caller must free) */ -static gcry_mpi_t -encode_session_key (DEK dek, unsigned int nbits) +static int +encode_session_key (DEK dek, gcry_sexp_t * r_data) { - int nframe = (nbits+7) / 8; - byte *p; - byte *frame; - int i,n; - gcry_mpi_t a; - - if (dek->keylen + 7 > nframe || !nframe) - log_bug ("can't encode a %d bit key in a %d bits frame\n", - dek->keylen*8, nbits ); - - /* We encode the session key in this way: - * - * 0 2 RND(n bytes) 0 KEY(k bytes) - * - * (But how can we store the leading 0 - the external representaion - * of MPIs doesn't allow leading zeroes =:-) - * - * RND are non-zero random bytes. - * KEY is the encryption key (session key) - */ - - frame = gcry_xmalloc_secure (nframe); - n = 0; - frame[n++] = 0; - frame[n++] = 2; - i = nframe - 3 - dek->keylen; - assert (i > 0); - p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); - /* replace zero bytes by new values */ - for (;;) - { - int j, k; - byte *pp; - - /* count the zero bytes */ - for(j=k=0; j < i; j++ ) - { - if( !p[j] ) - k++; - } - if( !k ) - break; /* okay: no zero bytes */ + gcry_sexp_t data; + char * p, tmp[3]; + int i; + int rc; - k += k/128; /* better get some more */ - pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); - for (j=0; j < i && k; j++) - { - if( !p[j] ) - p[j] = pp[--k]; - } - xfree (pp); + p = xmalloc (64+dek->keylen); + strcpy (p, "(data\n (flags pkcs1)\n (value #"); + for (i=0; i < dek->keylen; i++) + { + sprintf (tmp, "%02x", dek->key[i]); + strcat (p, tmp); } - memcpy (frame+n, p, i); + strcat (p, "#))\n"); + rc = gcry_sexp_sscan (&data, NULL, p, strlen (p)); xfree (p); - - n += i; - frame[n++] = 0; - memcpy (frame+n, dek->key, dek->keylen); - n += dek->keylen; - assert (n == nframe); - if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, n, &nframe) ) - BUG (); - gcry_free(frame); - - return a; + *r_data = data; + return rc; } - /* encrypt the DEK under the key contained in CERT and return it as a canonical S-Exp in encval */ static int @@ -235,17 +183,10 @@ encrypt_dek (const DEK dek, KsbaCert cert, char **encval) } /* put the encoded cleartext into a simple list */ + rc = encode_session_key (dek, &s_data); { - /* fixme: actually the pkcs-1 encoding should go into libgcrypt */ - gcry_mpi_t data = encode_session_key (dek, gcry_pk_get_nbits (s_pkey)); - if (!data) - { - gcry_mpi_release (data); - return gpg_error (GPG_ERR_GENERAL); - } - if (gcry_sexp_build (&s_data, NULL, "%m", data)) - BUG (); - gcry_mpi_release (data); + log_error ("encode_session_key failed: %s\n", gpg_strerror (rc)); + return rc; } /* pass it to libgcrypt */ -- cgit v1.2.3 From 6bdd855d1120afd6f83885ca6ea7a3a4a366b3fe Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Thu, 14 Aug 2003 19:58:03 +0000 Subject: Add 'dynload.h' to Makefile.am. --- common/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/Makefile.am b/common/Makefile.am index 2b99a19eb..3fd1c9454 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -38,7 +38,8 @@ libcommon_a_SOURCES = \ membuf.c membuf.h \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ - signal.c + signal.c \ + dynload.h libcommon_a_LIBADD = @LIBOBJS@ -- cgit v1.2.3 From 0506e4ebec8db4f4b2f5ecdb3122abca8f70b670 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 18 Aug 2003 17:34:28 +0000 Subject: * Makefile.am: Add OPENSC_LIBS to all programs. * scdaemon.c, scdaemon.h: New option --disable-opensc. * card.c (card_open): Implement it. * apdu.c (open_osc_reader, osc_send_apdu): New. (apdu_open_reader) [HAVE_OPENSC]: Use the opensc driver if not disabled. (error_string) [HAVE_OPENSC]: Use sc_strerror. (send_apdu) [HAVE_OPENSC]: Call osc_apdu_send. --- ChangeLog | 6 ++ NEWS | 4 + acinclude.m4 | 56 +++++++++++++ configure.ac | 114 +++++++++++++++++---------- scd/ChangeLog | 17 +++- scd/Makefile.am | 4 +- scd/apdu.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- scd/scdaemon.c | 12 +++ scd/scdaemon.h | 1 + 9 files changed, 401 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 00acca1c4..7e172242e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/NEWS b/NEWS index d275fddfc..14722fbd9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.9.1 (unreleased) ------------------------------------------------ + * Support for OpenSC is back. scdaemon support a --disable-opensc to + disable OpenSC use at runtime, so that PC/SC or ct-API can still be + used directly. + Noteworthy changes in version 1.9.0 (2003-08-05) ------------------------------------------------ diff --git a/acinclude.m4 b/acinclude.m4 index 42377380b..023563422 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -636,3 +636,59 @@ AC_DEFUN(AM_PATH_OPENSC, ]) +dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS +dnl +AC_DEFUN(AM_PATH_GPG_ERROR, +[ AC_ARG_WITH(gpg-error-prefix, + AC_HELP_STRING([--with-gpg-error-prefix=PFX], + [prefix where GPG Error is installed (optional)]), + gpg_error_config_prefix="$withval", gpg_error_config_prefix="") + if test x$gpg_error_config_prefix != x ; then + gpg_error_config_args="$gpg_error_config_args --prefix=$gpg_error_config_prefix" + if test x${GPG_ERROR_CONFIG+set} != xset ; then + GPG_ERROR_CONFIG=$gpg_error_config_prefix/bin/gpg-error-config + fi + fi + + AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) + min_gpg_error_version=ifelse([$1], ,0.0,$1) + AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) + ok=no + if test "$GPG_ERROR_CONFIG" != "no" ; then + req_major=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` + major=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -ge "$req_minor"; then + ok=yes + fi + fi + fi + fi + if test $ok = yes; then + GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` + GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPG_ERROR_CFLAGS="" + GPG_ERROR_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPG_ERROR_CFLAGS) + AC_SUBST(GPG_ERROR_LIBS) +]) + + diff --git a/configure.ac b/configure.ac index 0d12770a9..0bf39ba75 100644 --- a/configure.ac +++ b/configure.ac @@ -27,8 +27,9 @@ AC_INIT(gnupg, 1.9.1-cvs, gnupg-devel@gnupg.org) # feel that the default check for a development version is not # sufficient. development_version=yes +NEED_GPG_ERROR_VERSION=0.2 NEED_LIBGCRYPT_VERSION=1.1.42 -NEED_LIBASSUAN_VERSION=0.0.1 +NEED_LIBASSUAN_VERSION=0.6.0 NEED_KSBA_VERSION=0.4.6 NEED_OPENSC_VERSION=0.7.0 @@ -47,7 +48,9 @@ AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AC_GNU_SOURCE # Some status variables to give feedback at the end of a configure run -habe_libassuan=no +have_gpg_error=no +have_libgcrypt=no +have_libassuan=no have_ksba=no have_opensc=no have_pth=no @@ -346,59 +349,32 @@ AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) # Checks for libraries. # +# +# libgpg-error is a library with error codes shared between GnuPG +# related projects. +# +AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION" + have_gpg_error=yes,have_gpg_error=no) + + # # Libgcrypt is our generic crypto library # -#AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config) -#if test -n "$LIBGCRYPT_CONFIG"; then -# LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` -# LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` -#else -# AC_MSG_ERROR([[ -#*** -#*** You need libgcrypt to build this program. -#*** It should be available at the same place you -#*** got this software. -#***]]) -#fi -#AC_SUBST(LIBGCRYPT_CFLAGS) -#AC_SUBST(LIBGCRYPT_LIBS) -AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_VERSION",, - AC_MSG_ERROR([[ -*** -*** libgcrypt was not found. You may want to get it from -*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libgcrypt/ -*** -]])) +AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_VERSION", + have_libgcrypt=yes,have_libgcrypt=no) # # libassuan is used for IPC # AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION", - have_libasssuan=yes,have_libasssun=no) -if test "$have_libassuan" = "no"; then - AC_MSG_ERROR([[ -*** -*** You need libassuan to build this program.. -*** It should be available at the same place you -*** got this software. -***]]) -fi + have_libassuan=yes,have_libassuan=no) # # libksba is our X.509 support library # AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) -if test "$have_ksba" = "no"; then - AC_MSG_ERROR([[ -*** -*** You need libksba to build this program.. -*** It should be available at the same place you -*** got this software. -***]]) -fi # @@ -910,6 +886,64 @@ AC_SUBST(NETLIBS) AC_DEFINE(HAVE_JNLIB_LOGGING, 1, [Defined if jnlib style logging fucntions are available]) + + + +# +# Print errors here so that they are visible all +# together and the user can acquire them all together. +# +die=no +if test "$have_gpg_error" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** You need libgpg-error to build this program. +** This library is for example available at +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libgpg-error +*** (at least version $NEED_GPG_ERROR_VERSION is required.) +***]]) +fi +if test "$have_libgcrypt" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** You need libgcrypt to build this program. +** This library is for example available at +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libgcrypt/ +*** (at least version $NEED_LIBGCRYPT_VERSION is required.) +***]]) +fi +if test "$have_libassuan" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** You need libassuan to build this program. +*** This library is for example available at +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libassuan/ +*** (at least version $NEED_LIBASSUAN_VERSION is required). +***]]) +fi +if test "$have_ksba" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** You need libksba to build this program. +*** This library is for example available at +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/aegypten/ +*** (at least version $NEED_KSBA_VERSION is required). +***]]) +fi + +if test "$die" = "yes"; then + AC_MSG_ERROR([[ +*** +*** Required libraries not found. Please consult the above messages +*** and install them before running configure again. +***]]) +fi + + # # Decide what to build # diff --git a/scd/ChangeLog b/scd/ChangeLog index d78c4aa16..a1cb11e0b 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,9 +1,24 @@ +2003-08-18 Werner Koch <wk@gnupg.org> + + * Makefile.am: Add OPENSC_LIBS to all programs. + + * scdaemon.c, scdaemon.h: New option --disable-opensc. + * card.c (card_open): Implement it. + * apdu.c (open_osc_reader, osc_send_apdu): New. + (apdu_open_reader) [HAVE_OPENSC]: Use the opensc driver if not + disabled. + (error_string) [HAVE_OPENSC]: Use sc_strerror. + (send_apdu) [HAVE_OPENSC]: Call osc_apdu_send. + + * card-p15.c (p15_enum_keypairs, p15_prepare_key): Adjusted for + libgpg-error. + 2003-08-14 Timo Schulz <twoaday@freakmail.de> * apdu.c (ct_activate_card): Change the code a little to avoid problems with other readers. * Always use 'dynload.h' instead of 'dlfcn.h'. - + 2003-08-05 Werner Koch <wk@gnupg.org> * app-openpgp.c (dump_all_do): Don't analyze constructed DOs after diff --git a/scd/Makefile.am b/scd/Makefile.am index 0771beb60..5ecadd2e8 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -50,7 +50,7 @@ sc_investigate_SOURCES = \ sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ - $(LIBGCRYPT_LIBS) @INTLLIBS@ -lgpg-error -ldl + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) @INTLLIBS@ -lgpg-error -ldl sc_copykeys_SOURCES = \ @@ -64,7 +64,7 @@ sc_copykeys_SOURCES = \ sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ -ldl + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ -ldl diff --git a/scd/apdu.c b/scd/apdu.c index 6afcd6711..978d9ae3d 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -24,6 +24,9 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#ifdef HAVE_OPENSC +# include <opensc/opensc.h> +#endif #include "scdaemon.h" #include "apdu.h" @@ -34,9 +37,9 @@ insertion of the card (1 = don't wait). */ - -/* A global table to keep track of active readers. */ -static struct { +/* A structure to collect information pertaining to one reader + slot. */ +struct reader_table_s { int used; /* True if slot is used. */ unsigned short port; /* Port number: 0 = unused, 1 - dev/tty */ int is_ctapi; /* This is a ctAPI driver. */ @@ -45,10 +48,21 @@ static struct { unsigned long card; unsigned long protocol; } pcsc; +#ifdef HAVE_OPENSC + int is_osc; /* We are using the OpenSC driver layer. */ + struct { + struct sc_context *ctx; + struct sc_card *scard; + } osc; +#endif /*HAVE_OPENSC*/ int status; unsigned char atr[33]; size_t atrlen; -} reader_table[MAX_READER]; +}; +typedef struct reader_table_s *reader_table_t; + +/* A global table to keep track of active readers. */ +static struct reader_table_s reader_table[MAX_READER]; /* ct API function pointer. */ @@ -142,6 +156,7 @@ new_reader_slot (void) } reader_table[reader].used = 1; reader_table[reader].is_ctapi = 0; + reader_table[reader].is_osc = 0; return reader; } @@ -513,7 +528,7 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, unsigned long recv_len; if (DBG_CARD_IO) - log_printhex (" CT_data:", apdu, apdulen); + log_printhex (" PCSC_data:", apdu, apdulen); if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T1)) send_pci.protocol = PCSC_PROTOCOL_T1; @@ -529,10 +544,199 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, log_error ("pcsc_transmit failed: %s (0x%lx)\n", pcsc_error_string (err), err); - return err? -1:0; + return err? -1:0; /* FIXME: Return appropriate error code. */ +} + + +#ifdef HAVE_OPENSC +/* + OpenSC Interface. + + This uses the OpenSC primitives to send APDUs. We need this + because we can't mix OpenSC and native (i.e. ctAPI or PC/SC) + access to a card for resource conflict reasons. + */ + +static int +open_osc_reader (int portno) +{ + int err; + int slot; + reader_table_t slotp; + + slot = new_reader_slot (); + if (slot == -1) + return -1; + slotp = reader_table + slot; + + err = sc_establish_context (&slotp->osc.ctx, "scdaemon"); + if (err) + { + log_error ("failed to establish SC context: %s\n", sc_strerror (err)); + slotp->used = 0; + return -1; + } + if (portno < 0 || portno >= slotp->osc.ctx->reader_count) + { + log_error ("no card reader available\n"); + sc_release_context (slotp->osc.ctx); + slotp->used = 0; + return -1; + } + + /* Redirect to our logging facility. */ + slotp->osc.ctx->error_file = log_get_stream (); + slotp->osc.ctx->debug = opt.debug_sc; + slotp->osc.ctx->debug_file = log_get_stream (); + + if (sc_detect_card_presence (slotp->osc.ctx->reader[portno], 0) != 1) + { + log_error ("no card present\n"); + sc_release_context (slotp->osc.ctx); + slotp->used = 0; + return -1; + } + + /* We want the standard ISO driver. */ + /*FIXME: OpenSC does not like "iso7816", so we use EMV for now. */ + err = sc_set_card_driver(slotp->osc.ctx, "emv"); + if (err) + { + log_error ("failed to select the iso7816 driver: %s\n", + sc_strerror (err)); + sc_release_context (slotp->osc.ctx); + slotp->used = 0; + return -1; + } + + /* Now connect the card and hope that OpenSC won't try to be too + smart. */ + err = sc_connect_card (slotp->osc.ctx->reader[portno], 0, + &slotp->osc.scard); + if (err) + { + log_error ("failed to connect card in reader %d: %s\n", + portno, sc_strerror (err)); + sc_release_context (slotp->osc.ctx); + slotp->used = 0; + return -1; + } + if (opt.verbose) + log_info ("connected to card in opensc reader %d using driver `%s'\n", + portno, slotp->osc.scard->driver->name); + + err = sc_lock (slotp->osc.scard); + if (err) + { + log_error ("can't lock card in reader %d: %s\n", + portno, sc_strerror (err)); + sc_disconnect_card (slotp->osc.scard, 0); + sc_release_context (slotp->osc.ctx); + slotp->used = 0; + return -1; + } + + if (slotp->osc.scard->atr_len >= DIM (slotp->atr)) + log_bug ("ATR returned by opensc is too large\n"); + slotp->atrlen = slotp->osc.scard->atr_len; + memcpy (slotp->atr, slotp->osc.scard->atr, slotp->atrlen); + + slotp->is_osc = 1; + + dump_reader_status (slot); + return slot; } +/* Actually send the APDU of length APDULEN to SLOT and return a + maximum of *BUFLEN data in BUFFER, the actual returned size will be + set to BUFLEN. Returns: OpenSC error code. */ +static int +osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) +{ + long err; + struct sc_apdu a; + unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; + unsigned char result[SC_MAX_APDU_BUFFER_SIZE]; + + if (DBG_CARD_IO) + log_printhex (" APDU_data:", apdu, apdulen); + + if (apdulen < 4) + { + log_error ("osc_send_apdu: APDU is too short\n"); + return SC_ERROR_CMD_TOO_SHORT; + } + + memset(&a, 0, sizeof a); + a.cla = *apdu++; + a.ins = *apdu++; + a.p1 = *apdu++; + a.p2 = *apdu++; + apdulen -= 4; + + if (!apdulen) + a.cse = SC_APDU_CASE_1; + else if (apdulen == 1) + { + a.le = *apdu? *apdu : 256; + apdu++; apdulen--; + a.cse = SC_APDU_CASE_2_SHORT; + } + else + { + a.lc = *apdu++; apdulen--; + if (apdulen < a.lc) + { + log_error ("osc_send_apdu: APDU shorter than specified in Lc\n"); + return SC_ERROR_CMD_TOO_SHORT; + + } + memcpy(data, apdu, a.lc); + apdu += a.lc; apdulen -= a.lc; + + a.data = data; + a.datalen = a.lc; + + if (!apdulen) + a.cse = SC_APDU_CASE_3_SHORT; + else + { + a.le = *apdu? *apdu : 256; + apdu++; apdulen--; + if (apdulen) + { + log_error ("osc_send_apdu: APDU larger than specified\n"); + return SC_ERROR_CMD_TOO_LONG; + } + a.cse = SC_APDU_CASE_4_SHORT; + } + } + + a.resp = result; + a.resplen = DIM(result); + + err = sc_transmit_apdu (reader_table[slot].osc.scard, &a); + if (err) + { + log_error ("sc_apdu_transmit failed: %s\n", sc_strerror (err)); + return err; + } + + if (*buflen < 2 || a.resplen > *buflen - 2) + { + log_error ("osc_send_apdu: provided buffer too short to store result\n"); + return SC_ERROR_BUFFER_TOO_SMALL; + } + memcpy (buffer, a.resp, a.resplen); + buffer[a.resplen] = a.sw1; + buffer[a.resplen+1] = a.sw2; + *buflen = a.resplen + 2; + return 0; +} + +#endif /* HAVE_OPENSC */ @@ -542,12 +746,23 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, /* Open the reader and return an internal slot number or -1 on error. If PORTSTR is NULL we default to a suitable port (for ctAPI: - the first USB reader. For PCSC/ the first listed reader. */ + the first USB reader. For PC/SC the first listed reader). IF + OpenSC support is cmpiled in, we first try to use OpenSC. */ int apdu_open_reader (const char *portstr) { static int pcsc_api_loaded, ct_api_loaded; +#ifdef HAVE_OPENSC + if (!opt.disable_opensc) + { + int port = portstr? atoi (portstr) : 0; + + return open_osc_reader (port); + } +#endif /* HAVE_OPENSC */ + + if (opt.ctapi_driver && *opt.ctapi_driver) { int port = portstr? atoi (portstr) : 32768; @@ -648,6 +863,10 @@ error_string (int slot, long rc) return "[invalid slot]"; if (reader_table[slot].is_ctapi) return ct_error_string (rc); +#ifdef HAVE_OPENSC + else if (reader_table[slot].is_osc) + return sc_strerror (rc); +#endif else return pcsc_error_string (rc); } @@ -662,6 +881,10 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen, return SW_HOST_NO_DRIVER; if (reader_table[slot].is_ctapi) return ct_send_apdu (slot, apdu, apdulen, buffer, buflen); +#ifdef HAVE_OPENSC + else if (reader_table[slot].is_osc) + return osc_send_apdu (slot, apdu, apdulen, buffer, buflen); +#endif else return pcsc_send_apdu (slot, apdu, apdulen, buffer, buflen); } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 11952615d..af813b57d 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -70,6 +70,7 @@ enum cmd_and_opt_values oBatch, oReaderPort, octapiDriver, + oDisableOpenSC, aTest }; @@ -94,6 +95,16 @@ static ARGPARSE_OPTS opts[] = { { oLogFile, "log-file" ,2, N_("use a log file for the server")}, { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ctAPI driver")}, + { oDisableOpenSC, "disable-opensc", 0, +#ifdef HAVE_OPENSC + N_("Do not use the OpenSC layer") +#else + "@" +#endif + /* end --disable-opensc */}, + + + {0} }; @@ -368,6 +379,7 @@ main (int argc, char **argv ) case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break; case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; + case oDisableOpenSC: opt.disable_opensc = 1; break; default : pargs.err = configfp? 1:2; break; } diff --git a/scd/scdaemon.h b/scd/scdaemon.h index bdc4c21b3..20e2fa768 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -54,6 +54,7 @@ struct { int batch; /* batch mode */ const char *homedir; /* configuration directory name */ const char *ctapi_driver; /* Library to access the ctAPI. */ + int disable_opensc; /* Disable the sue of the OpenSC framework. */ } opt; -- cgit v1.2.3 From 4eb5165019c100435b139825edae8a4c03d89e21 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 18 Aug 2003 17:34:51 +0000 Subject: * scdaemon.c, scdaemon.h: New option --disable-opensc. * card.c (card_open): Implement it. * apdu.c (open_osc_reader, osc_send_apdu): New. (apdu_open_reader) [HAVE_OPENSC]: Use the opensc driver if not disabled. (error_string) [HAVE_OPENSC]: Use sc_strerror. (send_apdu) [HAVE_OPENSC]: Call osc_apdu_send. * card-p15.c (p15_enum_keypairs, p15_prepare_key): Adjusted for libgpg-error. --- scd/card-p15.c | 6 +++--- scd/card.c | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/scd/card-p15.c b/scd/card-p15.c index 3cf4ba519..dfb05c03f 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -136,7 +136,7 @@ p15_enum_keypairs (CARD card, int idx, log_info ("certificate for private key %d not found: %s\n", idx, sc_strerror (rc)); /* note, that we return the ID anyway */ - rc = gpg_error (GPG_ERR_MISSING_CERTIFICATE); + rc = gpg_error (GPG_ERR_MISSING_CERT); goto return_keyid; } certinfo = tmpobj->data; @@ -339,7 +339,7 @@ p15_prepare_key (CARD card, const char *keyidstr, if (rc < 0) { log_error ("private key not found: %s\n", sc_strerror(rc)); - return gpg_error (GPG_ERR_NO_SECRET_KEY); + return gpg_error (GPG_ERR_NO_SECKEY); } rc = sc_pkcs15_find_pin_by_auth_id (card->p15card, @@ -357,7 +357,7 @@ p15_prepare_key (CARD card, const char *keyidstr, rc = pincb (pincb_arg, pinobj->label, &pinvalue); if (rc) { - log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc)); + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); return rc; } diff --git a/scd/card.c b/scd/card.c index 02b7bfdbf..0a71fb2df 100644 --- a/scd/card.c +++ b/scd/card.c @@ -88,7 +88,7 @@ card_help_get_keygrip (KsbaCert cert, unsigned char *array) /* Create a new context for the card and figures out some basic - information of the card. Detects whgether a PKCS_15 application is + information of the card. Detects whether a PKCS_15 application is stored. Common errors: GPG_ERR_CARD_NOT_PRESENT */ @@ -99,6 +99,9 @@ card_open (CARD *rcard) CARD card; int rc; + if (opt.disable_opensc) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + card = xtrycalloc (1, sizeof *card); if (!card) return out_of_core (); -- cgit v1.2.3 From 73b5da4c7da14e40671e09842ea4cb6e8382fab4 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Mon, 18 Aug 2003 21:25:03 +0000 Subject: 2003-08-18 Timo Schulz <twoaday@freakmail.de> * encode.c (encode_sesskey): Checked the code and removed the warning since all compatibility checks with PGP succeeded. * mainproc.c (symkey_decrypt_sesskey): Better check for the algorithm and check the return values of some functions. --- g10/ChangeLog | 7 +++++++ g10/encode.c | 51 ++++++++++++++++++++++++++------------------------ g10/mainproc.c | 59 +++++++++++++++++++++++++++++++--------------------------- 3 files changed, 66 insertions(+), 51 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 33d38cf13..2810ada23 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +2003-08-18 Timo Schulz <twoaday@freakmail.de> + + * encode.c (encode_sesskey): Checked the code and removed + the warning since all compatibility checks with PGP succeeded. + * mainproc.c (symkey_decrypt_sesskey): Better check for the + algorithm and check the return values of some functions. + 2003-08-07 Werner Koch <wk@gnupg.org> * pkglue.c (pk_sign): Fix last change. diff --git a/g10/encode.c b/g10/encode.c index ba40c0aef..59daa7474 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -78,34 +78,37 @@ encode_store( const char *filename ) } static void -encode_sesskey( DEK *dek, DEK **ret_dek, byte *enckey ) +encode_sesskey (DEK * dek, DEK ** ret_dek, byte * enckey) { -#warning This functions needs a review. - CIPHER_HANDLE hd; - DEK *c; - byte buf[33]; + CIPHER_HANDLE hd; + DEK * c; + byte buf[33]; - assert ( dek->keylen < 32 ); + 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 );*/ - - buf[0] = c->algo; - memcpy( buf + 1, c->key, c->keylen ); + 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); - - gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1 ); - gcry_cipher_setkey( hd, dek->key, dek->keylen ); - 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; + /* 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 */ diff --git a/g10/mainproc.c b/g10/mainproc.c index 969c65066..3689525ef 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -239,37 +239,42 @@ add_signature( CTX c, PACKET *pkt ) } static void -symkey_decrypt_sesskey( DEK *dek, byte *sesskey, size_t slen ) +symkey_decrypt_sesskey (DEK * dek, byte *sesskey, size_t slen) { - CIPHER_HANDLE hd; - int n; + CIPHER_HANDLE hd; + int n; - if ( slen < 17 || slen > 33 ) { - log_error ( _("weird size for an encrypted session key (%d)\n"), - (int)slen); - return; + if (slen < 17 || slen > 33) + { + log_error ( _("weird size for an encrypted session key (%d)\n"), + (int)slen); + return; } - gcry_cipher_open ( &hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1 ); - gcry_cipher_setkey( hd, dek->key, dek->keylen ); - gcry_cipher_setiv( hd, NULL, 0 ); - gcry_cipher_decrypt( hd, sesskey, slen, NULL, 0); - gcry_cipher_close( hd ); - /* check first byte (the cipher algo) */ - if ( sesskey[0] > 10 ) { - log_error ( _("invalid symkey algorithm detected (%d)\n"), - sesskey[0] ); - return; + /* we checked the DEK values before, so consider all errors 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_decrypt (hd, sesskey, slen, NULL, 0); + gcry_cipher_close (hd); + /* check first byte (the cipher algo) */ + if (openpgp_cipher_test_algo (sesskey[0])) + { + log_error (_("invalid symkey algorithm detected (%d)\n"), + sesskey[0]); + return; } - n = gcry_cipher_get_algo_keylen (sesskey[0]); - if (n > DIM(dek->key)) - BUG (); - /* now we replace the dek components with the real session key - to decrypt the contents of the sequencing packet. */ - dek->keylen = gcry_cipher_get_algo_keylen (sesskey[0]); - dek->algo = sesskey[0]; - memcpy (dek->key, sesskey + 1, dek->keylen); - /*log_hexdump( "thekey", dek->key, dek->keylen );*/ -} + n = gcry_cipher_get_algo_keylen (sesskey[0]); + if (n > DIM(dek->key)) + BUG (); + /* now we replace the dek components with the real session key + to decrypt the contents of the sequencing packet. */ + dek->keylen = n; + dek->algo = sesskey[0]; + memcpy (dek->key, sesskey + 1, dek->keylen); + /*log_hexdump ("thekey", dek->key, dek->keylen);*/ +} static void proc_symkey_enc( CTX c, PACKET *pkt ) -- cgit v1.2.3 From f9867edfb874a4badf40b1b1ac38ccaa9f36e740 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Mon, 18 Aug 2003 21:32:19 +0000 Subject: * mdc.c (use_mdc): Simplified. --- g10/ChangeLog | 1 + g10/encode.c | 41 +++++++++++++++++++---------------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 2810ada23..2f8a81d87 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -4,6 +4,7 @@ the warning since all compatibility checks with PGP succeeded. * mainproc.c (symkey_decrypt_sesskey): Better check for the algorithm and check the return values of some functions. + * mdc.c (use_mdc): Simplified. 2003-08-07 Werner Koch <wk@gnupg.org> diff --git a/g10/encode.c b/g10/encode.c index 59daa7474..9fc00183f 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -113,18 +113,26 @@ encode_sesskey (DEK * dek, DEK ** ret_dek, byte * enckey) /* We try very hard to use a MDC */ static int -use_mdc(PK_LIST pk_list,int algo) +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; + /* --force-mdc overrides --disable-mdc */ - if(opt.force_mdc) + if (opt.force_mdc) return 1; - if(opt.disable_mdc) + if (opt.disable_mdc) return 0; /* Do the keys really support MDC? */ - if(select_mdc_from_pklist(pk_list)) + 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 @@ -132,26 +140,15 @@ use_mdc(PK_LIST pk_list,int algo) 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. */ - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_AES,NULL)==CIPHER_ALGO_AES) - return 1; - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_AES192,NULL)==CIPHER_ALGO_AES192) - return 1; - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_AES256,NULL)==CIPHER_ALGO_AES256) - return 1; - - if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, - CIPHER_ALGO_TWOFISH,NULL)==CIPHER_ALGO_TWOFISH) - return 1; + 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) + if (gcry_cipher_get_algo_blklen (algo) != 8) return 1; return 0; /* No MDC */ -- cgit v1.2.3 From 5e380eb635ace848b2ccbf6c067086c4adaa45ef Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 19 Aug 2003 02:25:25 +0000 Subject: 2003-08-19 Marcus Brinkmann <marcus@g10code.de> * configure.ac (AM_PATH_GPG_ERROR): Add missing comma in invocation. --- ChangeLog | 5 +++++ configure.ac | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7e172242e..45be0a5a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/configure.ac b/configure.ac index 0bf39ba75..7a7570eae 100644 --- a/configure.ac +++ b/configure.ac @@ -353,7 +353,7 @@ AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) # libgpg-error is a library with error codes shared between GnuPG # related projects. # -AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION" +AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION", have_gpg_error=yes,have_gpg_error=no) -- cgit v1.2.3 From e3cdba838618c83e87910150d6f292d06ba65b9b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 19 Aug 2003 09:36:48 +0000 Subject: * scdaemon.c, scdaemon.h: New option --pcsc-driver. * apdu.c (apdu_open_reader): Use that option here instead of a hardcoded one. --- scd/ChangeLog | 6 ++++++ scd/apdu.c | 6 ++++++ scd/scdaemon.c | 10 +++++++++- scd/scdaemon.h | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index a1cb11e0b..821b074a2 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2003-08-19 Werner Koch <wk@gnupg.org> + + * scdaemon.c, scdaemon.h: New option --pcsc-driver. + * apdu.c (apdu_open_reader): Use that option here instead of a + hardcoded one. + 2003-08-18 Werner Koch <wk@gnupg.org> * Makefile.am: Add OPENSC_LIBS to all programs. diff --git a/scd/apdu.c b/scd/apdu.c index 978d9ae3d..0d6ad9a85 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -798,6 +798,12 @@ apdu_open_reader (const char *portstr) { void *handle; + if (!opt.pcsc_driver || !*opt.pcsc_driver) + { + log_error ("no PC/SC driver has been specified\n"); + return -1; + } + handle = dlopen ("libpcsclite.so", RTLD_LAZY); if (!handle) { diff --git a/scd/scdaemon.c b/scd/scdaemon.c index af813b57d..49036e045 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -70,6 +70,7 @@ enum cmd_and_opt_values oBatch, oReaderPort, octapiDriver, + opcscDriver, oDisableOpenSC, aTest }; @@ -94,7 +95,8 @@ static ARGPARSE_OPTS opts[] = { { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, - { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ctAPI driver")}, + { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ct-API driver")}, + { opcscDriver, "pcsc-driver", 2, N_("NAME|use NAME as PC/SC driver")}, { oDisableOpenSC, "disable-opensc", 0, #ifdef HAVE_OPENSC N_("Do not use the OpenSC layer") @@ -266,6 +268,11 @@ main (int argc, char **argv ) may_coredump = disable_core_dumps (); + /* Set default options. */ + opt.pcsc_driver = NULL; /* We can't use libpcsclite due to license + conflicts. */ + + shell = getenv ("SHELL"); if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) csh_style = 1; @@ -379,6 +386,7 @@ main (int argc, char **argv ) case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break; case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; + case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break; case oDisableOpenSC: opt.disable_opensc = 1; break; default : pargs.err = configfp? 1:2; break; diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 20e2fa768..3671c7394 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -54,6 +54,7 @@ struct { int batch; /* batch mode */ const char *homedir; /* configuration directory name */ const char *ctapi_driver; /* Library to access the ctAPI. */ + const char *pcsc_driver; /* Library to access the PC/SC system. */ int disable_opensc; /* Disable the sue of the OpenSC framework. */ } opt; -- cgit v1.2.3 From e8cf79c977f81a53487e37d4b284f6f4796617c8 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 20 Aug 2003 16:53:40 +0000 Subject: 2003-08-20 Marcus Brinkmann <marcus@g10code.de> * encrypt.c (encode_session_key): Allocate enough space. Cast key byte to unsigned char to prevent sign extension. (encrypt_dek): Check return value before error. --- sm/ChangeLog | 6 ++++++ sm/encrypt.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 87874ca7f..fbdf15f6c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2003-08-20 Marcus Brinkmann <marcus@g10code.de> + + * encrypt.c (encode_session_key): Allocate enough space. Cast key + byte to unsigned char to prevent sign extension. + (encrypt_dek): Check return value before error. + 2003-08-14 Timo Schulz <twoaday@freakmail.de> * encrypt.c (encode_session_key): Use new Libgcrypt interface. diff --git a/sm/encrypt.c b/sm/encrypt.c index b6770a4b5..4eef20c73 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -134,11 +134,11 @@ encode_session_key (DEK dek, gcry_sexp_t * r_data) int i; int rc; - p = xmalloc (64+dek->keylen); + p = xmalloc (64 + 2 * dek->keylen); strcpy (p, "(data\n (flags pkcs1)\n (value #"); for (i=0; i < dek->keylen; i++) { - sprintf (tmp, "%02x", dek->key[i]); + sprintf (tmp, "%02x", (unsigned char) dek->key[i]); strcat (p, tmp); } strcat (p, "#))\n"); @@ -184,6 +184,7 @@ encrypt_dek (const DEK dek, KsbaCert cert, char **encval) /* put the encoded cleartext into a simple list */ rc = encode_session_key (dek, &s_data); + if (rc) { log_error ("encode_session_key failed: %s\n", gpg_strerror (rc)); return rc; -- cgit v1.2.3 From 238a1b26b85542ab776aa801ee92964da471b1b9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 20 Aug 2003 17:23:23 +0000 Subject: 2003-08-20 Marcus Brinkmann <marcus@g10code.de> * maperror.c (map_ksba_err): Map -1. Use gpg_err_make to set the error source. --- common/ChangeLog | 5 +++++ common/maperror.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 6666b5941..ee363f83e 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/common/maperror.c b/common/maperror.c index 13657bece..f52a5995a 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -39,10 +39,10 @@ map_ksba_err (int err) { switch (err) { - case -1: case 0: break; + case -1: err = GPG_ERR_EOF; break; case KSBA_Out_Of_Core: err = GPG_ERR_ENOMEM; break; case KSBA_Invalid_Value: err = GPG_ERR_INV_VALUE; break; case KSBA_Not_Implemented: err = GPG_ERR_NOT_IMPLEMENTED; break; @@ -60,7 +60,7 @@ map_ksba_err (int err) err = GPG_ERR_GENERAL; break; } - return err; + return gpg_err_make (GPG_ERR_SOURCE_GPGSM, err); } -- cgit v1.2.3 From 4498a55dfb2d8e294f72571e339c889b5bf5f664 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Wed, 20 Aug 2003 20:20:59 +0000 Subject: 2003-08-20 Timo Schulz <twoaday@freakmail.de> * pksign.c (do_encode_md): Allocate enough space. Cast md byte to unsigned char to prevent sign extension. --- agent/ChangeLog | 7 ++++++- agent/pksign.c | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 0c7857811..39e93f818 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,6 +1,11 @@ +2003-08-20 Timo Schulz <twoaday@freakmail.de> + + * pksign.c (do_encode_md): Allocate enough space. Cast md + byte to unsigned char to prevent sign extension. + 2003-08-14 Timo Schulz <twoaday@freakmail.de> - * pksign.c: do_encode_md: Due to the fact pkcs#1 padding + * pksign.c (do_encode_md): Due to the fact pkcs#1 padding is now in Libgcrypt, use the new interface. 2003-07-31 Werner Koch <wk@gnupg.org> diff --git a/agent/pksign.c b/agent/pksign.c index 3022e79a7..200b6a2cc 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -39,7 +39,7 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) char * p, tmp[16]; int i, rc; - p = xmalloc (64+mdlen); + p = xmalloc (64 + 2 * mdlen); s = gcry_md_algo_name (algo); if (s && strlen (s) < 16) { @@ -50,7 +50,7 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) sprintf (p, "(data\n (flags pkcs1)\n (hash %s #", tmp); for (i=0; i < mdlen; i++) { - sprintf (tmp, "%02x", md[i]); + sprintf (tmp, "%02x", (byte)md[i]); strcat (p, tmp); } strcat (p, "#))\n"); -- cgit v1.2.3 From ab0f32351d5c2ecd4f0143e10a7cbd25bd349992 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 25 Aug 2003 09:58:02 +0000 Subject: (cmd_setattr): Use a copy of LINE. (cmd_genkey): Use a copy of KEYNO. (cmd_passwd): Use a copy of CHVNOSTR. (cmd_pksign, cmd_pkauth, cmd_pkdecrypt): s/strdup/xtrystrdup/. --- scd/ChangeLog | 7 +++++++ scd/command.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 821b074a2..609b5082f 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2003-08-25 Werner Koch <wk@gnupg.org> + + * command.c (cmd_setattr): Use a copy of LINE. + (cmd_genkey): Use a copy of KEYNO. + (cmd_passwd): Use a copy of CHVNOSTR. + (cmd_pksign, cmd_pkauth, cmd_pkdecrypt): s/strdup/xtrystrdup/. + 2003-08-19 Werner Koch <wk@gnupg.org> * scdaemon.c, scdaemon.h: New option --pcsc-driver. diff --git a/scd/command.c b/scd/command.c index c53af84f9..9f242bfab 100644 --- a/scd/command.c +++ b/scd/command.c @@ -577,7 +577,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) /* We have to use a copy of the key ID because the function may use the pin_cb which in turn uses the assuan line buffer and thus overwriting the original line with the keyid */ - keyidstr = strdup (line); + keyidstr = xtrystrdup (line); if (!keyidstr) return ASSUAN_Out_Of_Core; @@ -593,7 +593,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) pin_cb, ctx, ctrl->in_data.value, ctrl->in_data.valuelen, &outdata, &outdatalen); - free (keyidstr); + xfree (keyidstr); if (rc) { log_error ("card_sign failed: %s\n", gpg_strerror (rc)); @@ -630,7 +630,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) /* We have to use a copy of the key ID because the function may use the pin_cb which in turn uses the assuan line buffer and thus overwriting the original line with the keyid */ - keyidstr = strdup (line); + keyidstr = xtrystrdup (line); if (!keyidstr) return ASSUAN_Out_Of_Core; @@ -639,7 +639,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) pin_cb, ctx, ctrl->in_data.value, ctrl->in_data.valuelen, &outdata, &outdatalen); - free (keyidstr); + xfree (keyidstr); if (rc) { log_error ("app_auth_sign failed: %s\n", gpg_strerror (rc)); @@ -670,7 +670,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) if ((rc = open_card (ctrl))) return rc; - keyidstr = strdup (line); + keyidstr = xtrystrdup (line); if (!keyidstr) return ASSUAN_Out_Of_Core; if (ctrl->app_ctx) @@ -685,7 +685,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) pin_cb, ctx, ctrl->in_data.value, ctrl->in_data.valuelen, &outdata, &outdatalen); - free (keyidstr); + xfree (keyidstr); if (rc) { log_error ("card_create_signature failed: %s\n", gpg_strerror (rc)); @@ -715,17 +715,24 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) setattr function of the actually used application (app-*.c) for details. */ static int -cmd_setattr (ASSUAN_CONTEXT ctx, char *line) +cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; char *keyword; int keywordlen; size_t nbytes; + char *line, *linebuf; if ((rc = open_card (ctrl))) return rc; + /* We need to use a copy of LINE, because PIN_CB uses the same + context and thus reuses the Assuan provided LINE. */ + line = linebuf = xtrystrdup (orig_line); + if (!line) + return ASSUAN_Out_Of_Core; + keyword = line; for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) ; @@ -736,6 +743,7 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *line) nbytes = percent_plus_unescape (line); rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes); + xfree (linebuf); return map_to_assuan_status (rc); } @@ -788,8 +796,11 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) if (!ctrl->app_ctx) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + keyno = xtrystrdup (keyno); + if (!keyno) + return ASSUAN_Out_Of_Core; rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx); - + xfree (keyno); return map_to_assuan_status (rc); } @@ -865,11 +876,14 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) if (!ctrl->app_ctx) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - - rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx -); + + chvnostr = xtrystrdup (chvnostr); + if (!chvnostr) + return ASSUAN_Out_Of_Core; + rc = app_change_pin (ctrl->app_ctx, ctrl, chvnostr, reset_mode, pin_cb, ctx); if (rc) log_error ("command passwd failed: %s\n", gpg_strerror (rc)); + xfree (chvnostr); return map_to_assuan_status (rc); } -- cgit v1.2.3 From 93ddaf9accd431968c9c3151a88df391bc7ac3ad Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Mon, 25 Aug 2003 21:12:43 +0000 Subject: 2003-08-25 Timo Schulz <twoaday@freakmail.de> * pkglue.c (mpi_from_sexp): New. Used to factor out some common code. --- g10/ChangeLog | 5 +++++ g10/pkglue.c | 53 ++++++++++++++++++++--------------------------------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 2f8a81d87..8eca012af 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2003-08-25 Timo Schulz <twoaday@freakmail.de> + + * pkglue.c (mpi_from_sexp): New. Used to factor out + some common code. + 2003-08-18 Timo Schulz <twoaday@freakmail.de> * encode.c (encode_sesskey): Checked the code and removed diff --git a/g10/pkglue.c b/g10/pkglue.c index abec77d9d..f062d8366 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -30,6 +30,20 @@ #include "pkglue.h" +static gcry_mpi_t +mpi_from_sexp (gcry_sexp_t sexp, const char * item) +{ + gcry_sexp_t list; + gcry_mpi_t data; + + list = gcry_sexp_find_token (sexp, item, 0); + assert (list); + data = gcry_sexp_nth_mpi (list, 1, 0); + assert (data); + gcry_sexp_release (list); + return data; +} + /**************** * Emulate our old PK interface here - sometime in the future we might @@ -38,7 +52,7 @@ int pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) { - gcry_sexp_t s_sig, s_hash, s_skey, list; + gcry_sexp_t s_sig, s_hash, s_skey; int rc; /* make a sexp from skey */ @@ -78,29 +92,13 @@ pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) if (rc) ; else if (algo == GCRY_PK_RSA) - { - list = gcry_sexp_find_token (s_sig, "s", 0); - assert (list); - data[0] = gcry_sexp_nth_mpi (list, 1, 0); - assert (data[0]); - gcry_sexp_release (list); - } + data[0] = mpi_from_sexp (s_sig, "s"); else { - list = gcry_sexp_find_token (s_sig, "r", 0); - assert (list); - data[0] = gcry_sexp_nth_mpi (list, 1, 0); - assert (data[0]); - gcry_sexp_release (list); - - list = gcry_sexp_find_token (s_sig, "s", 0); - assert (list); - data[1] = gcry_sexp_nth_mpi (list, 1, 0); - assert (data[1]); - gcry_sexp_release (list); + data[0] = mpi_from_sexp (s_sig, "r"); + data[1] = mpi_from_sexp (s_sig, "s"); } - gcry_sexp_release (s_sig); return rc; } @@ -226,20 +224,9 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) ; else { /* add better error handling or make gnupg use S-Exp directly */ - gcry_sexp_t list = gcry_sexp_find_token (s_ciph, "a", 0); - assert (list); - resarr[0] = gcry_sexp_nth_mpi (list, 1, 0); - assert (resarr[0]); - gcry_sexp_release (list); - + resarr[0] = mpi_from_sexp (s_ciph, "a"); if (algo != GCRY_PK_RSA) - { - list = gcry_sexp_find_token (s_ciph, "b", 0); - assert (list); - resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); - assert (resarr[1]); - gcry_sexp_release (list); - } + resarr[1] = mpi_from_sexp (s_ciph, "b"); } gcry_sexp_release (s_ciph); -- cgit v1.2.3 From 93c76df907839925909f754983cb479174e3d3f1 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Tue, 26 Aug 2003 09:01:18 +0000 Subject: 2003-08-26 Timo Schulz <twoaday@freakmail.de> * apdu.c (new_reader_slot): Only set 'is_osc' when OpenSC is used. --- scd/ChangeLog | 5 +++++ scd/apdu.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/scd/ChangeLog b/scd/ChangeLog index 609b5082f..ff407f8ec 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2003-08-26 Timo Schulz <twoaday@freakmail.de> + + * apdu.c (new_reader_slot): Only set 'is_osc' when OpenSC + is used. + 2003-08-25 Werner Koch <wk@gnupg.org> * command.c (cmd_setattr): Use a copy of LINE. diff --git a/scd/apdu.c b/scd/apdu.c index 0d6ad9a85..3809ef3ec 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -156,7 +156,9 @@ new_reader_slot (void) } reader_table[reader].used = 1; reader_table[reader].is_ctapi = 0; +#ifdef HAVE_OPENSC reader_table[reader].is_osc = 0; +#endif return reader; } -- cgit v1.2.3 From 936250aac9d87f464e8e4c5958d54e9ac405c878 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 2 Sep 2003 19:06:34 +0000 Subject: * configure.ac (HAVE_LIBUSB): Added a simple test for libusb. * scdaemon.c, scdaemon.h: New option --pcsc-ccid. * ccid-driver.c, ccid-driver.h: New but far from being useful. * Makefile.am: Add above. * apdu.c: Add support for that ccid driver. --- ChangeLog | 4 + TODO | 3 + agent/pksign.c | 4 + configure.ac | 13 ++ g10/ChangeLog | 4 + g10/keygen.c | 9 + scd/ChangeLog | 7 + scd/Makefile.am | 11 +- scd/apdu.c | 96 ++++++++- scd/ccid-driver.c | 627 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ scd/ccid-driver.h | 40 ++++ scd/scdaemon.c | 13 +- scd/scdaemon.h | 3 +- 13 files changed, 827 insertions(+), 7 deletions(-) create mode 100644 scd/ccid-driver.c create mode 100644 scd/ccid-driver.h diff --git a/ChangeLog b/ChangeLog index 45be0a5a0..6ac146eec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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 diff --git a/TODO b/TODO index c9b2d18ff..fe81d0241 100644 --- a/TODO +++ b/TODO @@ -20,6 +20,9 @@ might want to have an agent context for each service request ** 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. +** Try all available root certs in case we have several of them in our keybox. + For example TC TrustCenter Class 1 CA certs are ambiguous becuase + user certs don't come with a authorityKeyIdentifier. * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution diff --git a/agent/pksign.c b/agent/pksign.c index 200b6a2cc..342582177 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -39,6 +39,10 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) char * p, tmp[16]; int i, rc; +#warning I do do like that stuff - libgcrypt provides easier interfaces. -wk + /* FIXME: Either use the build function or create canonical encoded + S-expressions. */ + p = xmalloc (64 + 2 * mdlen); s = gcry_md_algo_name (algo); if (s && strlen (s) < 16) diff --git a/configure.ac b/configure.ac index 7a7570eae..591d5df53 100644 --- a/configure.ac +++ b/configure.ac @@ -376,6 +376,19 @@ AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION", # AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) +# +# libusb allows us to use the integrated CCID smartcard reader driver. + +# Note, that we need the CVS version. FIXME: libusb should have a +# regular check as the other libraries do. + +AC_CHECK_LIB(usb, usb_find_device, + [ LIBUSB_LIBS="$LIBUSB_LIBS -lusb" + AC_DEFINE(HAVE_LIBUSB,1, + [defined if libusb is available]) + ]) +AC_SUBST(LIBUSB_LIBS) + # # OpenSC is needed by the SCdaemon - if it is not availbale we can only diff --git a/g10/ChangeLog b/g10/ChangeLog index 8eca012af..274637283 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -3,6 +3,10 @@ * pkglue.c (mpi_from_sexp): New. Used to factor out some common code. +2003-08-24 Werner Koch <wk@gnupg.org> + + * keygen.c (do_generate_keypair): Print a reminder to use --gen-revoke. + 2003-08-18 Timo Schulz <twoaday@freakmail.de> * encode.c (encode_sesskey): Checked the code and removed diff --git a/g10/keygen.c b/g10/keygen.c index 210bbc897..1840a58c7 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2655,6 +2655,15 @@ do_generate_keypair (struct para_data_s *para, "the command \"--edit-key\" to generate a " "secondary key for this purpose.\n")); } + + if (!opt.batch && card) + { + tty_printf(_( +"Please create a revocation certificate now, so that you are able\n" +"to revoke the key if it ever happens that you lose your card or\n" +"the card gets damaged. Use the command \"--gen-revoke\".\n" + )); + } } } diff --git a/scd/ChangeLog b/scd/ChangeLog index ff407f8ec..28dc4a73a 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2003-09-02 Werner Koch <wk@gnupg.org> + + * scdaemon.c, scdaemon.h: New option --pcsc-ccid. + * ccid-driver.c, ccid-driver.h: New but far from being useful. + * Makefile.am: Add above. + * apdu.c: Add support for that ccid driver. + 2003-08-26 Timo Schulz <twoaday@freakmail.de> * apdu.c (new_reader_slot): Only set 'is_osc' when OpenSC diff --git a/scd/Makefile.am b/scd/Makefile.am index 5ecadd2e8..a2ecd3a81 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -32,17 +32,19 @@ scdaemon_SOURCES = \ card-common.h \ card-p15.c card-dinsig.c \ apdu.c apdu.h \ + ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ app.c app-common.h \ app-openpgp.c scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - -lgpg-error @INTLLIBS@ -ldl + $(LIBUSB_LIBS) -lgpg-error @INTLLIBS@ -ldl sc_investigate_SOURCES = \ sc-investigate.c scdaemon.h \ apdu.c apdu.h \ + ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ app.c app-common.h \ app-openpgp.c \ @@ -50,12 +52,14 @@ sc_investigate_SOURCES = \ sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) @INTLLIBS@ -lgpg-error -ldl + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) @INTLLIBS@ \ + -lgpg-error -ldl sc_copykeys_SOURCES = \ sc-copykeys.c scdaemon.h \ apdu.c apdu.h \ + ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ app.c app-common.h \ app-openpgp.c \ @@ -64,7 +68,8 @@ sc_copykeys_SOURCES = \ sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ -ldl + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) \ + -lgpg-error @INTLLIBS@ -ldl diff --git a/scd/apdu.c b/scd/apdu.c index 3809ef3ec..4867f10ff 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -31,6 +31,7 @@ #include "scdaemon.h" #include "apdu.h" #include "dynload.h" +#include "ccid-driver.h" #define MAX_READER 4 /* Number of readers we support concurrently. */ #define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for @@ -42,6 +43,10 @@ struct reader_table_s { int used; /* True if slot is used. */ unsigned short port; /* Port number: 0 = unused, 1 - dev/tty */ + int is_ccid; /* Uses the internal CCID driver. */ + struct { + ccid_driver_t handle; + } ccid; int is_ctapi; /* This is a ctAPI driver. */ struct { unsigned long context; @@ -155,6 +160,7 @@ new_reader_slot (void) return -1; } reader_table[reader].used = 1; + reader_table[reader].is_ccid = 0; reader_table[reader].is_ctapi = 0; #ifdef HAVE_OPENSC reader_table[reader].is_osc = 0; @@ -166,7 +172,9 @@ new_reader_slot (void) static void dump_reader_status (int reader) { - if (reader_table[reader].is_ctapi) + if (reader_table[reader].is_ccid) + log_info ("reader slot %d: using ccid driver\n", reader); + else if (reader_table[reader].is_ctapi) { log_info ("reader slot %d: %s\n", reader, reader_table[reader].status == 1? "Processor ICC present" : @@ -549,7 +557,74 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, return err? -1:0; /* FIXME: Return appropriate error code. */ } + +#ifdef HAVE_LIBUSB +/* + Internal CCID driver interface. + */ + +static int +open_ccid_reader (void) +{ + int err; + int slot; + reader_table_t slotp; + + slot = new_reader_slot (); + if (slot == -1) + return -1; + slotp = reader_table + slot; + + err = ccid_open_reader (&slotp->ccid.handle, 0); + if (err) + { + slotp->used = 0; + return -1; + } + + err = ccid_get_atr (slotp->ccid.handle, + slotp->atr, sizeof slotp->atr, &slotp->atrlen); + if (err) + { + slotp->used = 0; + return -1; + } + + slotp->is_ccid = 1; + + dump_reader_status (slot); + return slot; +} + + +/* Actually send the APDU of length APDULEN to SLOT and return a + maximum of *BUFLEN data in BUFFER, the actual returned size will be + set to BUFLEN. Returns: Internal CCID driver error code. */ +static int +send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) +{ + long err; + size_t maxbuflen; + + if (DBG_CARD_IO) + log_printhex (" APDU_data:", apdu, apdulen); + + maxbuflen = *buflen; + err = ccid_transceive (reader_table[slot].ccid.handle, + apdu, apdulen, + buffer, maxbuflen, buflen); + if (err) + log_error ("ccid_transceive failed: (0x%lx)\n", + err); + + return err? -1:0; /* FIXME: Return appropriate error code. */ +} + +#endif /* HAVE_LIBUSB */ + + #ifdef HAVE_OPENSC /* OpenSC Interface. @@ -755,6 +830,17 @@ apdu_open_reader (const char *portstr) { static int pcsc_api_loaded, ct_api_loaded; +#ifdef HAVE_LIBUSB + if (!opt.disable_ccid) + { + int slot; + + slot = open_ccid_reader (); + if (slot != -1) + return slot; /* got one */ + } +#endif + #ifdef HAVE_OPENSC if (!opt.disable_opensc) { @@ -871,6 +957,10 @@ error_string (int slot, long rc) return "[invalid slot]"; if (reader_table[slot].is_ctapi) return ct_error_string (rc); +#ifdef HAVE_LIBUSB + else if (reader_table[slot].is_ccid) + return "no CCID driver error strings yet"; +#endif #ifdef HAVE_OPENSC else if (reader_table[slot].is_osc) return sc_strerror (rc); @@ -889,6 +979,10 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen, return SW_HOST_NO_DRIVER; if (reader_table[slot].is_ctapi) return ct_send_apdu (slot, apdu, apdulen, buffer, buflen); +#ifdef HAVE_LIBUSB + else if (reader_table[slot].is_ccid) + return send_apdu_ccid (slot, apdu, apdulen, buffer, buflen); +#endif #ifdef HAVE_OPENSC else if (reader_table[slot].is_osc) return osc_send_apdu (slot, apdu, apdulen, buffer, buflen); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c new file mode 100644 index 000000000..03c9bcb95 --- /dev/null +++ b/scd/ccid-driver.c @@ -0,0 +1,627 @@ +/* ccid-driver.c - USB ChipCardInterfaceDevices driver + * 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 + */ + + +/* CCID (ChipCardInterfaceDevices) is a specification for accessing + smartcard via a reader connected to the USB. + + This is a limited driver allowing to use some CCID drivers directly + without any other specila drivers. This is a fallback driver to be + used when nothing else works or the system should be kept minimal + for security reasons. It makes use of the libusb library to gain + portable access to USB. + + This driver has been tested with the SCM SCR335 smartcard reader + and requires that reader implements the TPDU level exchange and + does fully automatic initialization. +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(HAVE_LIBUSB) || defined(TEST) +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include <usb.h> + + +#include "ccid-driver.h" + +enum { + RDR_to_PC_NotifySlotChange= 0x50, + RDR_to_PC_HardwareError = 0x51, + + PC_to_RDR_SetParameters = 0x61, + PC_to_RDR_IccPowerOn = 0x62, + PC_to_RDR_IccPowerOff = 0x63, + PC_to_RDR_GetSlotStatus = 0x65, + PC_to_RDR_Secure = 0x69, + PC_to_RDR_T0APDU = 0x6a, + PC_to_RDR_Escape = 0x6b, + PC_to_RDR_GetParameters = 0x6c, + PC_to_RDR_ResetParameters = 0x6d, + PC_to_RDR_IccClock = 0x6e, + PC_to_RDR_XfrBlock = 0x6f, + PC_to_RDR_Mechanical = 0x71, + PC_to_RDR_Abort = 0x72, + PC_to_RDR_SetDataRate = 0x73, + + RDR_to_PC_DataBlock = 0x80, + RDR_to_PC_SlotStatus = 0x81, + RDR_to_PC_Parameters = 0x82, + RDR_to_PC_Escape = 0x83, + RDR_to_PC_DataRate = 0x84 +}; + + +/* Store information on the driver's state. A pointer to such a + structure is used as handle for most functions. */ +struct ccid_driver_s { + usb_dev_handle *idev; + int seqno; + unsigned char t1_seqno; +}; + + + + +/* Open the reader with the internal number READERNO and return a a + pointer to be used as handle in HANDLE. Returns 0 on success. */ +int +ccid_open_reader (ccid_driver_t *handle, int readerno) +{ + static int initialized; + + int rc; + usb_match_handle *match = NULL; + struct usb_device *dev = NULL; + usb_dev_handle *idev = NULL; + + *handle = NULL; + if (!initialized) + { + usb_init (); + initialized = 1; + } + + rc = usb_create_match (&match, -1, -1, 11, -1, -1); + if (rc) + { + fprintf (stderr, "ccid-driver: usb_create_match failed: %d\n", rc); + return -1; + } + + while (usb_find_device(match, dev, &dev) >= 0) + { + fprintf(stderr, "ccid-driver: %-40s %04X/%04X\n", dev->filename, + dev->descriptor->idVendor, dev->descriptor->idProduct); + if (!readerno) + { + rc = usb_open (dev, &idev); + if (rc) + { + fprintf (stderr, "ccid-driver: usb_open failed: %d\n", rc); + goto leave; + } + + rc = usb_claim_interface (idev, 0); + if (rc) + { + fprintf (stderr, "ccid-driver: usb_claim_interface failed: %d\n", + rc); + goto leave; + } + + *handle = calloc (1, sizeof **handle); + if (!*handle) + { + fprintf (stderr, "ccid-driver: out of memory\n"); + rc = -1; + goto leave; + } + (*handle)->idev = idev; + idev = NULL; + break; + } + readerno--; + } + + + leave: + if (idev) + usb_close (idev); + /* fixme: Do we need to release dev or is it supposed to be a + shallow copy of the list created internally by usb_init ? */ + usb_free_match (match); + + return rc; +} + + +/* Return False if a card is present and powered. */ +int +ccid_check_card_presence (ccid_driver_t handle) +{ + + return -1; +} + + +static void +set_msg_len (unsigned char *msg, unsigned int length) +{ + msg[1] = length; + msg[2] = length >> 8; + msg[3] = length >> 16; + msg[4] = length >> 24; +} + + +/* Write a MSG of length MSGLEN to the designated bulk out endpoint. + Returns 0 on success. */ +static int +bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) +{ + int rc; + + rc = usb_bulk_write (handle->idev, + 1, /*endpoint */ + msg, msglen, + 1000 /* ms timeout */); + if (rc == msglen) + return 0; + + if (rc == -1) + fprintf (stderr, "ccid-driver: usb_bulk_write error: %s\n", + strerror (errno)); + else + fprintf (stderr, "ccid-driver: usb_bulk_write failed: %d\n", rc); + return -1; +} + + +/* Read a maximum of LENGTH bytes from the bulk in endpoint into + BUFFER and return the actual read number if bytes in NREAD. + Returns 0 on success. */ +static int +bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, + size_t *nread) +{ + int rc; + + rc = usb_bulk_read (handle->idev, + 0x82, + buffer, length, + 1000 /* ms timeout */ ); + if (rc < 0) + { + fprintf (stderr, "ccid-driver: usb_bulk_read error: %s\n", + strerror (errno)); + return -1; + } + + *nread = rc; + return 0; +} + + +/* experimental */ +int +ccid_poll (ccid_driver_t handle) +{ + int rc; + unsigned char msg[10]; + size_t msglen; + int i, j; + + rc = usb_bulk_read (handle->idev, + 0x83, + msg, sizeof msg, + 0 /* ms timeout */ ); + if (rc < 0 && errno == ETIMEDOUT) + return 0; + + if (rc < 0) + { + fprintf (stderr, "ccid-driver: usb_intr_read error: %s\n", + strerror (errno)); + return -1; + } + + msglen = rc; + rc = 0; + + if (msglen < 1) + { + fprintf (stderr, "ccid-driver: intr-in msg too short\n"); + return -1; + } + + if (msg[0] == RDR_to_PC_NotifySlotChange) + { + fprintf (stderr, "ccid-driver: notify slot change:"); + for (i=1; i < msglen; i++) + for (j=0; j < 4; j++) + fprintf (stderr, " %d:%c%c", + (i-1)*4+j, + (msg[i] & (1<<(j*2)))? 'p':'-', + (msg[i] & (2<<(j*2)))? '*':' '); + putc ('\n', stderr); + } + else if (msg[0] == RDR_to_PC_HardwareError) + { + fprintf (stderr, "ccid-driver: hardware error occured\n"); + } + else + { + fprintf (stderr, "ccid-driver: unknown intr-in msg of type %02X\n", + msg[0]); + } + + return 0; +} + + + +int +ccid_slot_status (ccid_driver_t handle) +{ + int rc; + unsigned char msg[100]; + size_t msglen; + unsigned char seqno; + + msg[0] = PC_to_RDR_GetSlotStatus; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* RFU */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, 0); + + rc = bulk_out (handle, msg, 10); + if (rc) + return rc; + rc = bulk_in (handle, msg, sizeof msg, &msglen); + if (rc) + return rc; + if (msglen < 10) + { + fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n", + (unsigned int)msglen); + return -1; + } + if (msg[0] != RDR_to_PC_SlotStatus) + { + fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n", + msg[0]); + return -1; + } + if (msg[5] != 0) + { + fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n", + msg[5]); + return -1; + } + if (msg[6] != seqno) + { + fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n", + seqno, msg[6]); + return -1; + } + + fprintf (stderr, + "ccid-driver: status: %02X error: %02X clock-status: %02X\n", + msg[7], msg[8], msg[9] ); + + return 0; +} + + +int +ccid_get_atr (ccid_driver_t handle, + unsigned char *atr, size_t maxatrlen, size_t *atrlen) +{ + int rc; + unsigned char msg[100]; + size_t msglen; + unsigned char seqno; + int i; + + msg[0] = PC_to_RDR_IccPowerOn; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* power select (0=auto, 1=5V, 2=3V, 3=1.8V) */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, 0); + msglen = 10; + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + rc = bulk_in (handle, msg, sizeof msg, &msglen); + if (rc) + return rc; + if (msglen < 10) + { + fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n", + (unsigned int)msglen); + return -1; + } + if (msg[0] != RDR_to_PC_DataBlock) + { + fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n", + msg[0]); + return -1; + } + if (msg[5] != 0) + { + fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n", + msg[5]); + return -1; + } + if (msg[6] != seqno) + { + fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n", + seqno, msg[6]); + return -1; + } + + fprintf (stderr, + "ccid-driver: status: %02X error: %02X clock-status: %02X\n" + " data:", msg[7], msg[8], msg[9] ); + for (i=10; i < msglen; i++) + fprintf (stderr, " %02X", msg[i]); + putc ('\n', stderr); + + if (atr) + { + size_t n = msglen - 10; + + if (n > maxatrlen) + n = maxatrlen; + memcpy (atr, msg+10, n); + *atrlen = n; + } + + return 0; +} + + + +/* + Protocol T=1 overview + + Block Structure: + Prologue Field: + 1 byte Node Address (NAD) + 1 byte Protocol Control Byte (PCB) + 1 byte Length (LEN) + Information Field: + 0-254 byte APDU or Control Information (INF) + Epilogue Field: + 1 byte Error Detection Code (EDC) + + NAD: + bit 7 unused + bit 4..6 Destination Node Address (DAD) + bit 3 unused + bit 2..0 Source Node Address (SAD) + + If node adresses are not used, SAD and DAD should be set to 0 on + the first block sent to the card. If they are used they should + have different values (0 for one is okay); that first block sets up + the addresses of the node. + + PCB: + Information Block (I-Block): + bit 7 0 + bit 6 Sequence number (yep, that is modulo 2) + bit 5 Chaining flag + bit 4..0 reserved + Received-Ready Block (R-Block): + bit 7 1 + bit 6 0 + bit 5 0 + bit 4 Sequence number + bit 3..0 0 = no error + 1 = EDC or parity error + 2 = other error + other values are reserved + Supervisory Block (S-Block): + bit 7 1 + bit 6 1 + bit 5 clear=request,set=response + bit 4..0 0 = resyncronisation request + 1 = information field size request + 2 = abort request + 3 = extension of BWT request + 4 = VPP error + other values are reserved + +*/ + +int +ccid_transceive (ccid_driver_t handle, + const unsigned char *apdu, size_t apdulen, + unsigned char *resp, size_t maxresplen, size_t *nresp) +{ + int rc; + unsigned char msg[10+258], *tpdu, *p; + size_t msglen; + unsigned char seqno; + int i; + unsigned char crc; + + + /* Construct an I-Block. */ + if (apdulen > 254) + return -1; /* Invalid length. */ + + tpdu = msg+10; + tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + tpdu[1] = ((handle->t1_seqno & 1) << 6); /* I-block */ + tpdu[2] = apdulen; + memcpy (tpdu+3, apdu, apdulen); + crc = 0; + for (i=0,p=tpdu; i < apdulen+3; i++) + crc ^= *p++; + tpdu[3+apdulen] = crc; + + handle->t1_seqno ^= 1; + + msg[0] = PC_to_RDR_XfrBlock; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 4; /* bBWI */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, apdulen+4); + msglen = 10 + apdulen + 4; + + fprintf (stderr, "ccid-driver: sending"); + for (i=0; i < msglen; i++) + fprintf (stderr, " %02X", msg[i]); + putc ('\n', stderr); + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + rc = bulk_in (handle, msg, sizeof msg, &msglen); + if (rc) + return rc; + if (msglen < 10) + { + fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n", + (unsigned int)msglen); + return -1; + } + if (msg[0] != RDR_to_PC_DataBlock) + { + fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n", + msg[0]); + return -1; + } + if (msg[5] != 0) + { + fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n", + msg[5]); + return -1; + } + if (msg[6] != seqno) + { + fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n", + seqno, msg[6]); + return -1; + } + + fprintf (stderr, + "ccid-driver: status: %02X error: %02X clock-status: %02X\n" + " data:", msg[7], msg[8], msg[9] ); + for (i=10; i < msglen; i++) + fprintf (stderr, " %02X", msg[i]); + putc ('\n', stderr); + + if (resp) + { + size_t n = msglen - 10; + + if (n < 4) + n = 0; /* fixme: this is an empty I-block or some other block + - we ignore it for now until we have implemented the + T=1 machinery. */ + else + { + p = msg + 10 + 3; /* Skip ccid header and prologue field. */ + n -= 3; + n--; /* Strip the epilogue field. */ + if (n > maxresplen) + n = maxresplen; /* fixme: return an error instead of truncating. */ + memcpy (resp, p, n); + } + *nresp = n; + } + + return 0; +} + + + + +#ifdef TEST +int +main (int argc, char **argv) +{ + int rc; + ccid_driver_t ccid; + + rc = ccid_open_reader (&ccid, 0); + if (rc) + return 1; + + ccid_poll (ccid); + fputs ("getting ATR ...\n", stderr); + rc = ccid_get_atr (ccid, NULL, 0, NULL); + if (rc) + return 1; + + ccid_poll (ccid); + fputs ("getting slot status ...\n", stderr); + rc = ccid_slot_status (ccid); + if (rc) + return 1; + + ccid_poll (ccid); + + { + static unsigned char apdu[] = { + 0, 0xA4, 4, 0, 6, 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01}; + rc = ccid_transceive (ccid, + apdu, sizeof apdu, + NULL, 0, NULL); + } + ccid_poll (ccid); + + { + static unsigned char apdu[] = { + 0, 0xCA, 0, 0x65, 254 }; + rc = ccid_transceive (ccid, + apdu, sizeof apdu, + NULL, 0, NULL); + } + ccid_poll (ccid); + + + return 0; +} + +/* + * Local Variables: + * compile-command: "gcc -DTEST -Wall -I/usr/local/include -lusb -g ccid-driver.c" + * End: + */ +#endif /*TEST*/ +#endif /*HAVE_LIBUSB*/ diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h new file mode 100644 index 000000000..8c2d1fe5a --- /dev/null +++ b/scd/ccid-driver.h @@ -0,0 +1,40 @@ +/* ccid-driver.c - USB ChipCardInterfaceDevices driver + * 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 CCID_DRIVER_H +#define CCID_DRIVER_H + + +struct ccid_driver_s; +typedef struct ccid_driver_s *ccid_driver_t; + +int ccid_open_reader (ccid_driver_t *handle, int readerno); +int ccid_get_atr (ccid_driver_t handle, + unsigned char *atr, size_t maxatrlen, size_t *atrlen); +int ccid_transceive (ccid_driver_t handle, + const unsigned char *apdu, size_t apdulen, + unsigned char *resp, size_t maxresplen, size_t *nresp); + + + +#endif /*CCID_DRIVER_H*/ + + + diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 49036e045..fda0bed6f 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -71,6 +71,7 @@ enum cmd_and_opt_values oReaderPort, octapiDriver, opcscDriver, + oDisableCCID, oDisableOpenSC, aTest }; @@ -97,11 +98,18 @@ static ARGPARSE_OPTS opts[] = { { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ct-API driver")}, { opcscDriver, "pcsc-driver", 2, N_("NAME|use NAME as PC/SC driver")}, + { oDisableCCID, "disable-ccidc", 0, +#ifdef HAVE_LIBUSB + N_("do not use the internal CCID driver") +#else + "@" +#endif + /* end --disable-ccid */}, { oDisableOpenSC, "disable-opensc", 0, #ifdef HAVE_OPENSC - N_("Do not use the OpenSC layer") + N_("do not use the OpenSC layer") #else - "@" + "@" #endif /* end --disable-opensc */}, @@ -387,6 +395,7 @@ main (int argc, char **argv ) case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break; case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break; + case oDisableCCID: opt.disable_ccid = 1; break; case oDisableOpenSC: opt.disable_opensc = 1; break; default : pargs.err = configfp? 1:2; break; diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 3671c7394..43c3189b3 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -55,7 +55,8 @@ struct { const char *homedir; /* configuration directory name */ const char *ctapi_driver; /* Library to access the ctAPI. */ const char *pcsc_driver; /* Library to access the PC/SC system. */ - int disable_opensc; /* Disable the sue of the OpenSC framework. */ + int disable_opensc; /* Disable the use of the OpenSC framework. */ + int disable_ccid; /* Disable the use of the internal CCID driver. */ } opt; -- cgit v1.2.3 From 3598504854fd5f2709c35ea5075184a0a253ef50 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 5 Sep 2003 07:40:18 +0000 Subject: * keygen.c (do_add_key_flags, parse_parameter_usage) (do_generate_keypair): Add support the proposed AUTH key flag. * getkey.c (fixup_uidnode, merge_selfsigs_main) (merge_selfsigs_subkey, premerge_public_with_secret): Ditto. * keylist.c (print_capabilities): Ditto. --- g10/ChangeLog | 8 ++++++++ g10/getkey.c | 21 ++++++++++++++------- g10/keygen.c | 9 ++++++--- g10/keylist.c | 23 ++++++++++++++++------- include/ChangeLog | 4 ++++ include/cipher.h | 1 + 6 files changed, 49 insertions(+), 17 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 274637283..afc16cb94 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,11 @@ +2003-09-04 Werner Koch <wk@gnupg.org> + + * keygen.c (do_add_key_flags, parse_parameter_usage) + (do_generate_keypair): Add support the proposed AUTH key flag. + * getkey.c (fixup_uidnode, merge_selfsigs_main) + (merge_selfsigs_subkey, premerge_public_with_secret): Ditto. + * keylist.c (print_capabilities): Ditto. + 2003-08-25 Timo Schulz <twoaday@freakmail.de> * pkglue.c (mpi_from_sexp): New. Used to factor out diff --git a/g10/getkey.c b/g10/getkey.c index c13d96dfb..7eda9384c 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1255,12 +1255,14 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); if ( p && n ) { /* first octet of the keyflags */ - if ( (*p & 3) ) + if ( (*p & 0x03) ) uid->help_key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 12) ) + if ( (*p & 0x0c) ) uid->help_key_usage |= PUBKEY_USAGE_ENC; /* Note: we do not set the CERT flag here because it can be assumed * that thre is no real policy to set it. */ + if ( (*p & 0x20) ) + uid->help_key_usage |= PUBKEY_USAGE_AUTH; } /* ditto or the key expiration */ @@ -1468,10 +1470,12 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); if ( p && n ) { /* first octet of the keyflags */ - if ( (*p & 3) ) + if ( (*p & 0x03) ) key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 12) ) + if ( (*p & 0x0c) ) key_usage |= PUBKEY_USAGE_ENC; + if ( (*p & 0x20) ) + key_usage |= PUBKEY_USAGE_AUTH; } p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); @@ -1858,10 +1862,12 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); if ( p && n ) { /* first octet of the keyflags */ - if ( (*p & 3) ) + if ( (*p & 0x03) ) key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 12) ) + if ( (*p & 0x0c) ) key_usage |= PUBKEY_USAGE_ENC; + if ( (*p & 0x20) ) + key_usage |= PUBKEY_USAGE_AUTH; } if ( !key_usage ) { /* no key flags at all: get it from the algo */ key_usage = openpgp_pk_algo_usage ( subpk->pubkey_algo ); @@ -2059,7 +2065,8 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) /* The secret parts are not available so we can't use that key for signing etc. Fix the pubkey usage */ - pk->pubkey_usage &= ~PUBKEY_USAGE_SIG; + pk->pubkey_usage &= ~(PUBKEY_USAGE_SIG + |PUBKEY_USAGE_AUTH); } /* transfer flag bits 0 and 1 to the pubblock */ pub->flag |= (sec->flag &3); diff --git a/g10/keygen.c b/g10/keygen.c index 1840a58c7..84857ae62 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -150,6 +150,8 @@ do_add_key_flags (PKT_signature *sig, unsigned int use) buf[0] |= 0x01 | 0x02; if (use & PUBKEY_USAGE_ENC) buf[0] |= 0x04 | 0x08; + if (use & PUBKEY_USAGE_AUTH) + buf[0] |= 0x20; build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1); } @@ -1784,6 +1786,8 @@ parse_parameter_usage (const char *fname, use |= PUBKEY_USAGE_SIG; else if ( !ascii_strcasecmp (p, "encrypt") ) use |= PUBKEY_USAGE_ENC; + else if ( !ascii_strcasecmp (p, "auth") ) + use |= PUBKEY_USAGE_AUTH; else { log_error("%s:%d: invalid usage list\n", fname, r->lnr ); return -1; /* error */ @@ -2552,11 +2556,10 @@ do_generate_keypair (struct para_data_s *para, rc = gen_card_key (PUBKEY_ALGO_RSA, 3, pub_root, sec_root, get_parameter_u32 (para, pKEYEXPIRE), para); - /* FIXME: Change the usage to AUTH. */ if (!rc) - rc = write_keybinding (pub_root, pub_root, sk, PUBKEY_USAGE_SIG); + rc = write_keybinding (pub_root, pub_root, sk, PUBKEY_USAGE_AUTH); if (!rc) - rc = write_keybinding (sec_root, pub_root, sk, PUBKEY_USAGE_SIG); + rc = write_keybinding (sec_root, pub_root, sk, PUBKEY_USAGE_AUTH); } diff --git a/g10/keylist.c b/g10/keylist.c index b5549fb47..081782785 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -405,20 +405,23 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) { unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage; - if ( use & PUBKEY_USAGE_ENC ) + if ( (use & PUBKEY_USAGE_ENC) ) putchar ('e'); - if ( use & PUBKEY_USAGE_SIG ) + if ( (use & PUBKEY_USAGE_SIG) ) { putchar ('s'); if( pk? pk->is_primary : sk->is_primary ) putchar ('c'); } + + if ( (use & PUBKEY_USAGE_AUTH) ) + putchar ('a'); } if ( keyblock ) { /* figure out the usable capabilities */ KBNODE k; - int enc=0, sign=0, cert=0, disabled=0; + int enc=0, sign=0, cert=0, auth=0, disabled=0; for (k=keyblock; k; k = k->next ) { if ( k->pkt->pkttype == PKT_PUBLIC_KEY @@ -429,14 +432,16 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) disabled=pk_is_disabled(pk); if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) { - if ( pk->pubkey_usage & PUBKEY_USAGE_ENC ) + if ( (pk->pubkey_usage & PUBKEY_USAGE_ENC) ) enc = 1; - if ( pk->pubkey_usage & PUBKEY_USAGE_SIG ) + if ( (pk->pubkey_usage & PUBKEY_USAGE_SIG) ) { sign = 1; if(pk->is_primary) cert = 1; } + if ( (pk->pubkey_usage & PUBKEY_USAGE_AUTH) ) + auth = 1; } } else if ( k->pkt->pkttype == PKT_SECRET_KEY @@ -444,14 +449,16 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) sk = k->pkt->pkt.secret_key; if ( sk->is_valid && !sk->is_revoked && !sk->has_expired && sk->protect.s2k.mode!=1001 ) { - if ( sk->pubkey_usage & PUBKEY_USAGE_ENC ) + if ( (sk->pubkey_usage & PUBKEY_USAGE_ENC) ) enc = 1; - if ( sk->pubkey_usage & PUBKEY_USAGE_SIG ) + if ( (sk->pubkey_usage & PUBKEY_USAGE_SIG) ) { sign = 1; if(sk->is_primary) cert = 1; } + if ( (sk->pubkey_usage & PUBKEY_USAGE_AUTH) ) + auth = 1; } } } @@ -461,6 +468,8 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) putchar ('S'); if (cert) putchar ('C'); + if (auth) + putchar ('A'); if (disabled) putchar ('D'); } diff --git a/include/ChangeLog b/include/ChangeLog index 7d8191a2d..380d63b45 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2003-09-04 Werner Koch <wk@gnupg.org> + + * cipher.h (PUBKEY_USAGE_AUTH): Added. + 2003-07-03 Werner Koch <wk@gnupg.org> * cipher.h (DBG_CIPHER,g10c_debug_mode): Removed. diff --git a/include/cipher.h b/include/cipher.h index 56a1b2000..90cedb051 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -48,6 +48,7 @@ #define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN #define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR #define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/ +#define PUBKEY_USAGE_AUTH 8 #define DIGEST_ALGO_MD5 GCRY_MD_MD5 #define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 -- cgit v1.2.3 From 25430119e832a89cd141fb7c1a0edbfab237c243 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 5 Sep 2003 07:40:41 +0000 Subject: * ccid-driver.c: More work, data can now actually be retrieved. * ccid-driver.c, ccid-driver.h: Alternativley allow use under BSD conditions. --- scd/ChangeLog | 6 + scd/ccid-driver.c | 444 ++++++++++++++++++++++++++++++++++-------------------- scd/ccid-driver.h | 34 +++++ 3 files changed, 320 insertions(+), 164 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 28dc4a73a..5ffad3440 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2003-09-05 Werner Koch <wk@gnupg.org> + + * ccid-driver.c: More work, data can now actually be retrieved. + * ccid-driver.c, ccid-driver.h: Alternativley allow use under BSD + conditions. + 2003-09-02 Werner Koch <wk@gnupg.org> * scdaemon.c, scdaemon.h: New option --pcsc-ccid. diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 03c9bcb95..b18b055b0 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1,5 +1,6 @@ /* ccid-driver.c - USB ChipCardInterfaceDevices driver * Copyright (C) 2003 Free Software Foundation, Inc. + * Written by Werner Koch. * * This file is part of GnuPG. * @@ -16,6 +17,40 @@ * 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 + * + * ALTERNATIVELY, this file may be distributed under the terms of the + * following license, in which case the provisions of this license are + * required INSTEAD OF the GNU General Public License. If you wish to + * allow use of your version of this file only under the terms of the + * GNU General Public License, and not to allow others to use your + * version of this file under the terms of the following license, + * indicate your decision by deleting this paragraph and the license + * below. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -38,6 +73,7 @@ #endif #if defined(HAVE_LIBUSB) || defined(TEST) + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -46,9 +82,43 @@ #include <usb.h> - #include "ccid-driver.h" +#define DRVNAME "ccid-driver: " + + +#ifdef GNUPG_DEFAULT_SCDAEMON /* This source is used within the + gnupg>=1.9 source tree. */ +# include "scdaemon.h" + +# define DEBUGOUT(t) do { if (DBG_CARD_IO) \ + log_debug (DRVNAME t); } while (0) +# define DEBUGOUT_1(t,a) do { if (DBG_CARD_IO) \ + log_debug (DRVNAME t,(a)); } while (0) +# define DEBUGOUT_2(t,a,b) do { if (DBG_CARD_IO) \ + log_debug (DRVNAME t,(a),(b)); } while (0) +# define DEBUGOUT_3(t,a,b,c) do { if (DBG_CARD_IO) \ + log_debug (DRVNAME t,(a),(b),(c));} while (0) +# define DEBUGOUT_CONT_1(t,a) do { if (DBG_CARD_IO) \ + log_printf (t,(a)); } while (0) +# define DEBUGOUT_CONT_3(t,a,b,c) do { if (DBG_CARD_IO) \ + log_printf (t,(a),(b),(c)); } while (0) +# define DEBUGOUT_LF() do { if (DBG_CARD_IO) \ + log_printf ("\n"); } while (0) + +#else /* Other usage of this source - don't use gnupg specifics. */ + +# define DEBUGOUT(t) fprintf (stderr, DRVNAME t) +# define DEBUGOUT_1(t,a) fprintf (stderr, DRVNAME t, (a)) +# define DEBUGOUT_2(t,a,b) fprintf (stderr, DRVNAME t, (a), (b)) +# define DEBUGOUT_3(t,a,b,c) fprintf (stderr, DRVNAME t, (a), (b), (c)) +# define DEBUGOUT_CONT_1(t,a) fprintf (stderr, t, (a)) +# define DEBUGOUT_CONT_3(t,a,b,c) fprintf (stderr, t, (a), (b), (c)) +# define DEBUGOUT_LF() putc ('\n', stderr) + +#endif /* This source not used by scdaemon. */ + + enum { RDR_to_PC_NotifySlotChange= 0x50, RDR_to_PC_HardwareError = 0x51, @@ -81,7 +151,8 @@ enum { struct ccid_driver_s { usb_dev_handle *idev; int seqno; - unsigned char t1_seqno; + unsigned char t1_ns; + unsigned char t1_nr; }; @@ -109,35 +180,34 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) rc = usb_create_match (&match, -1, -1, 11, -1, -1); if (rc) { - fprintf (stderr, "ccid-driver: usb_create_match failed: %d\n", rc); + DEBUGOUT_1 ("usb_create_match failed: %d\n", rc); return -1; } while (usb_find_device(match, dev, &dev) >= 0) { - fprintf(stderr, "ccid-driver: %-40s %04X/%04X\n", dev->filename, - dev->descriptor->idVendor, dev->descriptor->idProduct); + DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, + dev->descriptor->idVendor, dev->descriptor->idProduct); if (!readerno) { rc = usb_open (dev, &idev); if (rc) { - fprintf (stderr, "ccid-driver: usb_open failed: %d\n", rc); + DEBUGOUT_1 ("usb_open failed: %d\n", rc); goto leave; } rc = usb_claim_interface (idev, 0); if (rc) { - fprintf (stderr, "ccid-driver: usb_claim_interface failed: %d\n", - rc); + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); goto leave; } *handle = calloc (1, sizeof **handle); if (!*handle) { - fprintf (stderr, "ccid-driver: out of memory\n"); + DEBUGOUT ("out of memory\n"); rc = -1; goto leave; } @@ -194,22 +264,24 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) return 0; if (rc == -1) - fprintf (stderr, "ccid-driver: usb_bulk_write error: %s\n", - strerror (errno)); + DEBUGOUT_1 ("usb_bulk_write error: %s\n", strerror (errno)); else - fprintf (stderr, "ccid-driver: usb_bulk_write failed: %d\n", rc); + DEBUGOUT_1 ("usb_bulk_write failed: %d\n", rc); return -1; } /* Read a maximum of LENGTH bytes from the bulk in endpoint into - BUFFER and return the actual read number if bytes in NREAD. - Returns 0 on success. */ + BUFFER and return the actual read number if bytes in NREAD. SEQNO + is the sequence number used to send the request and EXPECTED_TYPE + the type of message we expect. Does checks on the ccid + header. Returns 0 on success. */ static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, - size_t *nread) + size_t *nread, int expected_type, int seqno) { - int rc; + int i, rc; + size_t msglen; rc = usb_bulk_read (handle->idev, 0x82, @@ -217,12 +289,40 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, 1000 /* ms timeout */ ); if (rc < 0) { - fprintf (stderr, "ccid-driver: usb_bulk_read error: %s\n", - strerror (errno)); + DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno)); + return -1; + } + + *nread = msglen = rc; + + if (msglen < 10) + { + DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen); + return -1; + } + if (buffer[0] != expected_type) + { + DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]); + return -1; + } + if (buffer[5] != 0) + { + DEBUGOUT_1 ("unexpected bulk-in slot (%d)\n", buffer[5]); + return -1; + } + if (buffer[6] != seqno) + { + DEBUGOUT_2 ("bulk-in seqno does not match (%d/%d)\n", + seqno, buffer[6]); return -1; } - *nread = rc; + DEBUGOUT_3 ("status: %02X error: %02X clock-status: %02X\n" + " data:", buffer[7], buffer[8], buffer[9] ); + for (i=10; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", buffer[i]); + DEBUGOUT_LF (); + return 0; } @@ -245,8 +345,7 @@ ccid_poll (ccid_driver_t handle) if (rc < 0) { - fprintf (stderr, "ccid-driver: usb_intr_read error: %s\n", - strerror (errno)); + DEBUGOUT_1 ("usb_intr_read error: %s\n", strerror (errno)); return -1; } @@ -255,29 +354,28 @@ ccid_poll (ccid_driver_t handle) if (msglen < 1) { - fprintf (stderr, "ccid-driver: intr-in msg too short\n"); + DEBUGOUT ("intr-in msg too short\n"); return -1; } if (msg[0] == RDR_to_PC_NotifySlotChange) { - fprintf (stderr, "ccid-driver: notify slot change:"); + DEBUGOUT ("notify slot change:"); for (i=1; i < msglen; i++) for (j=0; j < 4; j++) - fprintf (stderr, " %d:%c%c", - (i-1)*4+j, - (msg[i] & (1<<(j*2)))? 'p':'-', - (msg[i] & (2<<(j*2)))? '*':' '); - putc ('\n', stderr); + DEBUGOUT_CONT_3 (" %d:%c%c", + (i-1)*4+j, + (msg[i] & (1<<(j*2)))? 'p':'-', + (msg[i] & (2<<(j*2)))? '*':' '); + DEBUGOUT_LF (); } else if (msg[0] == RDR_to_PC_HardwareError) { - fprintf (stderr, "ccid-driver: hardware error occured\n"); + DEBUGOUT ("hardware error occured\n"); } else { - fprintf (stderr, "ccid-driver: unknown intr-in msg of type %02X\n", - msg[0]); + DEBUGOUT_1 ("unknown intr-in msg of type %02X\n", msg[0]); } return 0; @@ -304,37 +402,9 @@ ccid_slot_status (ccid_driver_t handle) rc = bulk_out (handle, msg, 10); if (rc) return rc; - rc = bulk_in (handle, msg, sizeof msg, &msglen); + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno); if (rc) return rc; - if (msglen < 10) - { - fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n", - (unsigned int)msglen); - return -1; - } - if (msg[0] != RDR_to_PC_SlotStatus) - { - fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n", - msg[0]); - return -1; - } - if (msg[5] != 0) - { - fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n", - msg[5]); - return -1; - } - if (msg[6] != seqno) - { - fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n", - seqno, msg[6]); - return -1; - } - - fprintf (stderr, - "ccid-driver: status: %02X error: %02X clock-status: %02X\n", - msg[7], msg[8], msg[9] ); return 0; } @@ -348,7 +418,6 @@ ccid_get_atr (ccid_driver_t handle, unsigned char msg[100]; size_t msglen; unsigned char seqno; - int i; msg[0] = PC_to_RDR_IccPowerOn; msg[5] = 0; /* slot */ @@ -362,40 +431,9 @@ ccid_get_atr (ccid_driver_t handle, rc = bulk_out (handle, msg, msglen); if (rc) return rc; - rc = bulk_in (handle, msg, sizeof msg, &msglen); + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno); if (rc) return rc; - if (msglen < 10) - { - fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n", - (unsigned int)msglen); - return -1; - } - if (msg[0] != RDR_to_PC_DataBlock) - { - fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n", - msg[0]); - return -1; - } - if (msg[5] != 0) - { - fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n", - msg[5]); - return -1; - } - if (msg[6] != seqno) - { - fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n", - seqno, msg[6]); - return -1; - } - - fprintf (stderr, - "ccid-driver: status: %02X error: %02X clock-status: %02X\n" - " data:", msg[7], msg[8], msg[9] ); - for (i=10; i < msglen; i++) - fprintf (stderr, " %02X", msg[i]); - putc ('\n', stderr); if (atr) { @@ -434,7 +472,7 @@ ccid_get_atr (ccid_driver_t handle, If node adresses are not used, SAD and DAD should be set to 0 on the first block sent to the card. If they are used they should have different values (0 for one is okay); that first block sets up - the addresses of the node. + the addresses of the nodes. PCB: Information Block (I-Block): @@ -470,20 +508,29 @@ ccid_transceive (ccid_driver_t handle, unsigned char *resp, size_t maxresplen, size_t *nresp) { int rc; - unsigned char msg[10+258], *tpdu, *p; - size_t msglen; + unsigned char send_buffer[10+258], recv_buffer[10+258]; + unsigned char *msg, *tpdu, *p; + size_t msglen, tpdulen, n; unsigned char seqno; int i; unsigned char crc; + size_t dummy_nresp; + int sending = 1; + + if (!nresp) + nresp = &dummy_nresp; + *nresp = 0; /* Construct an I-Block. */ if (apdulen > 254) return -1; /* Invalid length. */ + msg = send_buffer; + tpdu = msg+10; tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ - tpdu[1] = ((handle->t1_seqno & 1) << 6); /* I-block */ + tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */ tpdu[2] = apdulen; memcpy (tpdu+3, apdu, apdulen); crc = 0; @@ -491,79 +538,148 @@ ccid_transceive (ccid_driver_t handle, crc ^= *p++; tpdu[3+apdulen] = crc; - handle->t1_seqno ^= 1; + tpdulen = apdulen + 4; - msg[0] = PC_to_RDR_XfrBlock; - msg[5] = 0; /* slot */ - msg[6] = seqno = handle->seqno++; - msg[7] = 4; /* bBWI */ - msg[8] = 0; /* RFU */ - msg[9] = 0; /* RFU */ - set_msg_len (msg, apdulen+4); - msglen = 10 + apdulen + 4; + for (;;) + { + msg[0] = PC_to_RDR_XfrBlock; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 4; /* bBWI */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, tpdulen); + msglen = 10 + tpdulen; + + DEBUGOUT ("sending"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + + fprintf (stderr, "T1: put %c-block seq=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + + msg = recv_buffer; + rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, + RDR_to_PC_DataBlock, seqno); + if (rc) + return rc; + + tpdu = msg + 10; + tpdulen = msglen - 10; + + if (tpdulen < 4) + { + DEBUGOUT ("cannot yet handle short block!!\n"); + return -1; + } - fprintf (stderr, "ccid-driver: sending"); - for (i=0; i < msglen; i++) - fprintf (stderr, " %02X", msg[i]); - putc ('\n', stderr); + fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 + ); + + if (!(tpdu[1] & 0x80)) + { /* This is an I-block. */ + + if (sending) + { /* last block sent was successful. */ + handle->t1_ns ^= 1; + sending = 0; + } - rc = bulk_out (handle, msg, msglen); - if (rc) - return rc; - rc = bulk_in (handle, msg, sizeof msg, &msglen); - if (rc) - return rc; - if (msglen < 10) - { - fprintf (stderr, "ccid-driver: bulk-in msg too short (%u)\n", - (unsigned int)msglen); - return -1; - } - if (msg[0] != RDR_to_PC_DataBlock) - { - fprintf (stderr, "ccid-driver: unexpected bulk-in msg type (%02x)\n", - msg[0]); - return -1; - } - if (msg[5] != 0) - { - fprintf (stderr, "ccid-driver: unexpected bulk-in slot (%d)\n", - msg[5]); - return -1; - } - if (msg[6] != seqno) - { - fprintf (stderr, "ccid-driver: bulk-in seqno does not match (%d/%d)\n", - seqno, msg[6]); - return -1; - } + if (!!(tpdu[1] & 0x40) != handle->t1_nr) + { /* Reponse does not match our sequence number. */ + msg = send_buffer; + tpdu = msg+10; + tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + tpdu[1] = (0x80 | (handle->t1_nr & 1) << 4 | 2); /* R-block */ + tpdu[2] = 0; + tpdulen = 3; + for (crc=0,i=0,p=tpdu; i < tpdulen; i++) + crc ^= *p++; + tpdu[tpdulen++] = crc; + + continue; + } - fprintf (stderr, - "ccid-driver: status: %02X error: %02X clock-status: %02X\n" - " data:", msg[7], msg[8], msg[9] ); - for (i=10; i < msglen; i++) - fprintf (stderr, " %02X", msg[i]); - putc ('\n', stderr); + handle->t1_nr ^= 1; - if (resp) - { - size_t n = msglen - 10; - - if (n < 4) - n = 0; /* fixme: this is an empty I-block or some other block - - we ignore it for now until we have implemented the - T=1 machinery. */ - else - { - p = msg + 10 + 3; /* Skip ccid header and prologue field. */ - n -= 3; - n--; /* Strip the epilogue field. */ - if (n > maxresplen) - n = maxresplen; /* fixme: return an error instead of truncating. */ - memcpy (resp, p, n); + p = tpdu + 3; /* Skip the prologue field. */ + n = tpdulen - 3 - 1; /* Strip the epilogue field. */ + /* fixme: verify the checksum. */ + if (resp) + { + if (n > maxresplen) + { + DEBUGOUT ("provided buffer too short for received data\n"); + return -1; + } + + memcpy (resp, p, n); + resp += n; + *nresp += n; + maxresplen -= n; + } + + if (!(tpdu[1] & 0x20)) + return 0; /* No chaining requested - ready. */ + + msg = send_buffer; + tpdu = msg+10; + tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + tpdu[1] = (0x80 | (handle->t1_nr & 1) << 4); /* R-block */ + tpdu[2] = 0; + tpdulen = 3; + for (crc=0,i=0,p=tpdu; i < tpdulen; i++) + crc ^= *p++; + tpdu[tpdulen++] = crc; + } - *nresp = n; - } + else if ((tpdu[1] & 0xc0) == 0x80) + { /* This is a R-block. */ + if ( (tpdu[1] & 0x0f)) + { /* Error: repeat last block */ + msg = send_buffer; + } + else + { + DEBUGOUT ("unxpectec ACK R-block received\n"); + return -1; + } + } + else + { /* This is a S-block. */ + DEBUGOUT_2 ("T1 S-block %s received cmd=%d\n", + (tpdu[1] & 0x20)? "response": "request", + (tpdu[1] & 0x1f)); + if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 3 && tpdu[2]) + { /* Wait time extension request. */ + unsigned char bwi = tpdu[3]; + msg = send_buffer; + tpdu = msg+10; + tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + tpdu[1] = (0xc0 | 0x20 | 3); /* S-block response */ + tpdu[2] = 1; + tpdu[3] = bwi; + tpdulen = 4; + for (crc=0,i=0,p=tpdu; i < tpdulen; i++) + crc ^= *p++; + tpdu[tpdulen++] = crc; + DEBUGOUT_1 ("T1 waittime extension of bwi=%d\n", bwi); + } + else + return -1; + } + } /* end T=1 protocol loop. */ return 0; } diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 8c2d1fe5a..4d12d88c2 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -16,6 +16,40 @@ * 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 + * + * ALTERNATIVELY, this file may be distributed under the terms of the + * following license, in which case the provisions of this license are + * required INSTEAD OF the GNU General Public License. If you wish to + * allow use of your version of this file only under the terms of the + * GNU General Public License, and not to allow others to use your + * version of this file under the terms of the following license, + * indicate your decision by deleting this paragraph and the license + * below. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CCID_DRIVER_H -- cgit v1.2.3 From be034cf34c3c5bc7787d9b2f8d4c7b6b948d4e2f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 6 Sep 2003 13:23:48 +0000 Subject: * configure.ac: Required newer versions of some libraries. * misc.c (openpgp_pk_algo_usage): Allow AUTH where SIGN is allowed. * keygen.c (ask_passphrase): No need to allocated S2K in secure memory. * scdaemon.c (main): --pcsc-driver again defaults to pcsclite. David Corcoran was so kind to remove the GPL incompatible advertisng clause from pcsclite. * apdu.c (apdu_open_reader): Actually make pcsc-driver option work. --- ChangeLog | 6 ++++++ NEWS | 9 +++++++-- configure.ac | 12 ++++++------ g10/ChangeLog | 7 +++++++ g10/keygen.c | 2 +- g10/misc.c | 6 +++--- scd/ChangeLog | 7 +++++++ scd/apdu.c | 18 ++++++------------ scd/ccid-driver.c | 26 ++++++++++++++------------ scd/scdaemon.c | 3 +-- 10 files changed, 58 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6ac146eec..6d11d8ca6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2003-09-06 Werner Koch <wk@gnupg.org> + + Released 1.9.1. + + * configure.ac: Required newer versions of some libraries. + 2003-09-02 Werner Koch <wk@gnupg.org> * configure.ac (HAVE_LIBUSB): Added a simple test for libusb. diff --git a/NEWS b/NEWS index 14722fbd9..9dc066a9f 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,15 @@ -Noteworthy changes in version 1.9.1 (unreleased) +Noteworthy changes in version 1.9.1 (2003-09-06) ------------------------------------------------ - * Support for OpenSC is back. scdaemon support a --disable-opensc to + * 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) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 591d5df53..4d651d380 100644 --- a/configure.ac +++ b/configure.ac @@ -22,16 +22,16 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.1-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.1, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. development_version=yes -NEED_GPG_ERROR_VERSION=0.2 -NEED_LIBGCRYPT_VERSION=1.1.42 +NEED_GPG_ERROR_VERSION=0.4 +NEED_LIBGCRYPT_VERSION=1.1.43 NEED_LIBASSUAN_VERSION=0.6.0 NEED_KSBA_VERSION=0.4.6 -NEED_OPENSC_VERSION=0.7.0 +NEED_OPENSC_VERSION=0.8.0 PACKAGE=$PACKAGE_NAME @@ -378,10 +378,10 @@ AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) # # libusb allows us to use the integrated CCID smartcard reader driver. - +# # Note, that we need the CVS version. FIXME: libusb should have a # regular check as the other libraries do. - +# AC_CHECK_LIB(usb, usb_find_device, [ LIBUSB_LIBS="$LIBUSB_LIBS -lusb" AC_DEFINE(HAVE_LIBUSB,1, diff --git a/g10/ChangeLog b/g10/ChangeLog index afc16cb94..ae602ebdc 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +2003-09-06 Werner Koch <wk@gnupg.org> + + * misc.c (openpgp_pk_algo_usage): Allow AUTH where SIGN is allowed. + + * keygen.c (ask_passphrase): No need to allocated S2K in secure + memory. + 2003-09-04 Werner Koch <wk@gnupg.org> * keygen.c (do_add_key_flags, parse_parameter_usage) diff --git a/g10/keygen.c b/g10/keygen.c index 84857ae62..3dbd9b402 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1629,7 +1629,7 @@ ask_passphrase( STRING2KEY **ret_s2k ) tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); - s2k = xmalloc_secure ( sizeof *s2k ); + s2k = xmalloc ( sizeof *s2k ); for(;;) { s2k->mode = opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; diff --git a/g10/misc.c b/g10/misc.c index ad04ce76f..4abe75661 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -260,7 +260,7 @@ openpgp_pk_algo_usage ( int algo ) /* they are hardwired in gpg 1.0 */ switch ( algo ) { case PUBKEY_ALGO_RSA: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; + use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH; break; case PUBKEY_ALGO_RSA_E: use = PUBKEY_USAGE_ENC; @@ -272,10 +272,10 @@ openpgp_pk_algo_usage ( int algo ) use = PUBKEY_USAGE_ENC; break; case PUBKEY_ALGO_DSA: - use = PUBKEY_USAGE_SIG; + use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; break; case PUBKEY_ALGO_ELGAMAL: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; + use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH; break; default: break; diff --git a/scd/ChangeLog b/scd/ChangeLog index 5ffad3440..1c785b215 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2003-09-06 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main): --pcsc-driver again defaults to pcsclite. + David Corcoran was so kind to remove the GPL incompatible + advertisng clause from pcsclite. + * apdu.c (apdu_open_reader): Actually make pcsc-driver option work. + 2003-09-05 Werner Koch <wk@gnupg.org> * ccid-driver.c: More work, data can now actually be retrieved. diff --git a/scd/apdu.c b/scd/apdu.c index 4867f10ff..d5f64c6d8 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -823,8 +823,8 @@ osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, /* Open the reader and return an internal slot number or -1 on error. If PORTSTR is NULL we default to a suitable port (for ctAPI: - the first USB reader. For PC/SC the first listed reader). IF - OpenSC support is cmpiled in, we first try to use OpenSC. */ + the first USB reader. For PC/SC the first listed reader). If + OpenSC support is compiled in, we first try to use OpenSC. */ int apdu_open_reader (const char *portstr) { @@ -839,7 +839,7 @@ apdu_open_reader (const char *portstr) if (slot != -1) return slot; /* got one */ } -#endif +#endif /* HAVE_LIBUSB */ #ifdef HAVE_OPENSC if (!opt.disable_opensc) @@ -886,17 +886,11 @@ apdu_open_reader (const char *portstr) { void *handle; - if (!opt.pcsc_driver || !*opt.pcsc_driver) - { - log_error ("no PC/SC driver has been specified\n"); - return -1; - } - - handle = dlopen ("libpcsclite.so", RTLD_LAZY); + handle = dlopen (opt.pcsc_driver, RTLD_LAZY); if (!handle) { - log_error ("apdu_open_reader: failed to open driver: %s", - dlerror ()); + log_error ("apdu_open_reader: failed to open driver `%s': %s", + opt.pcsc_driver, dlerror ()); return -1; } diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index b18b055b0..6f469de6a 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -286,7 +286,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, rc = usb_bulk_read (handle->idev, 0x82, buffer, length, - 1000 /* ms timeout */ ); + 10000 /* ms timeout */ ); + /* Fixme: instead of using a 10 second timeout we should better + handle the timeout here and retry if appropriate. */ if (rc < 0) { DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno)); @@ -556,10 +558,10 @@ ccid_transceive (ccid_driver_t handle, DEBUGOUT_CONT_1 (" %02X", msg[i]); DEBUGOUT_LF (); - fprintf (stderr, "T1: put %c-block seq=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); +/* fprintf (stderr, "T1: put %c-block seq=%d\n", */ +/* ((msg[11] & 0xc0) == 0x80)? 'R' : */ +/* (msg[11] & 0x80)? 'S' : 'I', */ +/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); */ rc = bulk_out (handle, msg, msglen); if (rc) @@ -576,16 +578,16 @@ ccid_transceive (ccid_driver_t handle, if (tpdulen < 4) { - DEBUGOUT ("cannot yet handle short block!!\n"); + DEBUGOUT ("cannot yet handle short blocks!\n"); return -1; } - fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), - ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 - ); +/* fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", */ +/* ((msg[11] & 0xc0) == 0x80)? 'R' : */ +/* (msg[11] & 0x80)? 'S' : 'I', */ +/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), */ +/* ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 */ +/* ); */ if (!(tpdu[1] & 0x80)) { /* This is an I-block. */ diff --git a/scd/scdaemon.c b/scd/scdaemon.c index fda0bed6f..89be04ab5 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -277,8 +277,7 @@ main (int argc, char **argv ) may_coredump = disable_core_dumps (); /* Set default options. */ - opt.pcsc_driver = NULL; /* We can't use libpcsclite due to license - conflicts. */ + opt.pcsc_driver = "libpcsclite.so"; shell = getenv ("SHELL"); -- cgit v1.2.3 From 657f9d4e5c4a50967c0ce5c0fb46cd1156806dc4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 6 Sep 2003 13:44:17 +0000 Subject: Post release version number update --- ChangeLog | 2 +- NEWS | 5 +++++ configure.ac | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6d11d8ca6..172dd0fe4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,7 @@ Released 1.9.1. - * configure.ac: Required newer versions of some libraries. + * configure.ac: Require newer versions of some libraries. 2003-09-02 Werner Koch <wk@gnupg.org> diff --git a/NEWS b/NEWS index 9dc066a9f..558a5e8ac 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Noteworthy changes in version 1.9.2 (unreleased) +------------------------------------------------ + + + Noteworthy changes in version 1.9.1 (2003-09-06) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 4d651d380..4ee1898b5 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.1, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.2-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 210b7257483b4cbed1eccce8afb50a142f085f52 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 18 Sep 2003 15:51:01 +0000 Subject: (tty_fprintf): New. (tty_print_string, tty_print_utf8_string2) (tty_print_utf8_string): Made P argument const byte*. --- common/ChangeLog | 6 ++++++ common/ttyio.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- common/ttyio.h | 12 ++++++++---- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index ee363f83e..66e935b28 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +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 diff --git a/common/ttyio.c b/common/ttyio.c index fd748009e..c77b4a85a 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -219,11 +219,58 @@ tty_printf( const char *fmt, ... ) } +/* 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 __MINGW32__ + { + 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( byte *p, size_t n ) +tty_print_string ( const byte *p, size_t n ) { if (no_terminal) return; @@ -261,7 +308,7 @@ tty_print_string( byte *p, size_t n ) } void -tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) +tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) { size_t i; char *buf; @@ -292,7 +339,7 @@ tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) } void -tty_print_utf8_string( byte *p, size_t n ) +tty_print_utf8_string( const byte *p, size_t n ) { tty_print_utf8_string2( p, n, 0 ); } diff --git a/common/ttyio.h b/common/ttyio.h index b3ca7dcaf..6fa7400a9 100644 --- a/common/ttyio.h +++ b/common/ttyio.h @@ -23,13 +23,17 @@ 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_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 (unsigned char *p, size_t n); -void tty_print_utf8_string (unsigned char *p, size_t n); -void tty_print_utf8_string2 (unsigned char *p, size_t n, size_t max_n); +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); -- cgit v1.2.3 From 918eee71958cec2af31542e44f8c83152c5c256f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 18 Sep 2003 15:51:18 +0000 Subject: * g10.c: New command --card-edit. * card-util.c (card_status): Use tty_fprintf for all output. (print_sha1_fpr, print_isoname): Ditto. (get_one_name,change_name, change_url, change_login,change_lang) (change_sex): New; taken from keygen.c. * keygen.c (smartcard_get_one_name, smartcard_change_name) (smartcard_change_url, smartcard_change_login_data) (smartcard_change_lang, smartcard_change_sex): Removed. (check_smartcard): Removed most menu items. --- g10/ChangeLog | 12 ++ g10/card-util.c | 424 +++++++++++++++++++++++++++++++++++++++++++++++++++----- g10/g10.c | 17 +++ g10/gpgv.c | 6 +- g10/keygen.c | 210 +--------------------------- g10/main.h | 2 +- 6 files changed, 420 insertions(+), 251 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index ae602ebdc..6f53430c3 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,15 @@ +2003-09-18 Werner Koch <wk@gnupg.org> + + * g10.c: New command --card-edit. + * card-util.c (card_status): Use tty_fprintf for all output. + (print_sha1_fpr, print_isoname): Ditto. + (get_one_name,change_name, change_url, change_login,change_lang) + (change_sex): New; taken from keygen.c. + * keygen.c (smartcard_get_one_name, smartcard_change_name) + (smartcard_change_url, smartcard_change_login_data) + (smartcard_change_lang, smartcard_change_sex): Removed. + (check_smartcard): Removed most menu items. + 2003-09-06 Werner Koch <wk@gnupg.org> * misc.c (openpgp_pk_algo_usage): Allow AUTH where SIGN is allowed. diff --git a/g10/card-util.c b/g10/card-util.c index 9f665cc74..b0754dcd2 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -34,6 +34,8 @@ #include "main.h" #include "call-agent.h" +#define CONTROL_D ('D' - 'A' + 1) + /* Change the PIN of a an OpenPGP card. This is an interactive function. */ @@ -135,32 +137,40 @@ print_sha1_fpr (FILE *fp, const unsigned char *fpr) for (i=0; i < 20 ; i+=2, fpr += 2 ) { if (i == 10 ) - putc (' ', fp); - fprintf (fp, " %02X%02X", *fpr, fpr[1]); + tty_fprintf (fp, " "); + tty_fprintf (fp, " %02X%02X", *fpr, fpr[1]); } } else - fputs (" [none]", fp); - putc ('\n', fp); + tty_fprintf (fp, " [none]"); + tty_fprintf (fp, "\n"); } static void print_name (FILE *fp, const char *text, const char *name) { - fputs (text, fp); + tty_fprintf (fp, text); + + /* FIXME: tty_printf_utf8_string2 east everything after and + including an @ - e.g. when printing an url. */ if (name && *name) - print_utf8_string2 (fp, name, strlen (name), '\n'); + { + if (fp) + print_utf8_string2 (fp, name, strlen (name), '\n'); + else + tty_print_utf8_string2 (name, strlen (name), '\n'); + } else - fputs (_("[not set]"), fp); - putc ('\n', fp); + tty_fprintf (fp, _("[not set]")); + tty_fprintf (fp, "\n"); } static void print_isoname (FILE *fp, const char *text, const char *name) { - fputs (text, fp); + tty_fprintf (fp, text); if (name && *name) { @@ -174,16 +184,22 @@ print_isoname (FILE *fp, const char *text, const char *name) { *given = 0; given += 2; - print_utf8_string2 (fp, given, strlen (given), '\n'); + if (fp) + print_utf8_string2 (fp, given, strlen (given), '\n'); + else + tty_print_utf8_string2 (given, strlen (given), '\n'); if (*buf) - putc (' ', fp); + tty_fprintf (fp, " "); } - print_utf8_string2 (fp, buf, strlen (buf), '\n'); + if (fp) + print_utf8_string2 (fp, buf, strlen (buf), '\n'); + else + tty_print_utf8_string2 (buf, strlen (buf), '\n'); xfree (buf); } else - fputs (_("[not set]"), fp); - putc ('\n', fp); + tty_fprintf (fp, _("[not set]")); + tty_fprintf (fp, "\n"); } @@ -203,59 +219,391 @@ card_status (FILE *fp) return; } - fprintf (fp, "Application ID ...: %s\n", - info.serialno? info.serialno : "[none]"); + tty_fprintf (fp, "Application ID ...: %s\n", + info.serialno? info.serialno : "[none]"); if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) || strlen (info.serialno) != 32 ) { log_info ("not an OpenPGP card\n"); agent_release_card_info (&info); } - 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]); - fprintf (fp, "Manufacturer .....: %s\n", - get_manufacturer (xtoi_2(info.serialno+16)*256 - + xtoi_2 (info.serialno+18))); - fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20); + 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: ", info.disp_name); print_name (fp, "Language prefs ...: ", info.disp_lang); - fprintf (fp, "Sex ..............: %s\n", info.disp_sex == 1? _("male"): - info.disp_sex == 2? _("female") : _("unspecified")); + 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); - fprintf (fp, "Signature PIN ....: %s\n", - info.chv1_cached? _("cached"): _("not cached")); - fprintf (fp, "Max. PIN lengths .: %d %d %d\n", - info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); - fprintf (fp, "PIN retry counter : %d %d %d\n", - info.chvretry[0], info.chvretry[1], info.chvretry[2]); - fputs ("Signature key ....:", fp); + tty_fprintf (fp, "Signature PIN ....: %s\n", + info.chv1_cached? _("cached"): _("not cached")); + 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 key ....:"); print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL); - fputs ("Encryption key....:", fp); + tty_fprintf (fp, "Encryption key....:"); print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL); - fputs ("Authentication key:", fp); + tty_fprintf (fp, "Authentication key:"); print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL); - fputs ("General key info..: ", fp); + tty_fprintf (fp, "General key info..: "); if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) print_pubkey_info (fp, pk); else fputs ("[none]\n", fp); - fprintf (fp, "Signature counter : %lu\n", info.sig_counter); + tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter); 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 = '<'; + + 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 (); + + 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 (); + + 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; +} +/* 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, + + 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") }, + { NULL, cmdNOP } + }; + + enum cmdids cmd = cmdNOP; + int have_commands = !!commands; + int redisplay = 1; + char *answer = NULL;; + + 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 ) + { + card_status (NULL); + 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 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); +} diff --git a/g10/g10.c b/g10/g10.c index aef76992b..619832372 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -127,6 +127,7 @@ enum cmd_and_opt_values { aNull = 0, aRebuildKeydbCaches, aRefreshKeys, aCardStatus, + aCardEdit, aChangePIN, oTextmode, @@ -362,6 +363,7 @@ static ARGPARSE_OPTS opts[] = { { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, { aCardStatus, "card-status", 256, N_("print the card status")}, + { aCardEdit, "card-edit", 256, N_("change data on a card")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, @@ -1425,6 +1427,7 @@ main( int argc, char **argv ) case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; case aCardStatus: set_cmd (&cmd, aCardStatus); break; + case aCardEdit: set_cmd (&cmd, aCardEdit); break; case aChangePIN: set_cmd (&cmd, aChangePIN); break; case oArmor: opt.armor = 1; opt.no_armor=0; break; @@ -2290,6 +2293,7 @@ main( int argc, char **argv ) case aEnArmor: case aFixTrustDB: case aCardStatus: + case aCardEdit: case aChangePIN: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; @@ -2789,6 +2793,19 @@ main( int argc, char **argv ) card_status (stdout); break; + case aCardEdit: + if (argc) + { + sl = NULL; + for (argc--, argv++ ; argc; argc--, argv++) + append_to_strlist (&sl, *argv); + card_edit (sl); + free_strlist (sl); + } + else + card_edit (NULL); + break; + case aChangePIN: if (!argc) change_pin (0); diff --git a/g10/gpgv.c b/g10/gpgv.c index da108d225..fb96fad5c 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -363,9 +363,9 @@ 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( byte *p, size_t n ) { } -void tty_print_utf8_string( byte *p, size_t n ) {} -void tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) {} +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) {} diff --git a/g10/keygen.c b/g10/keygen.c index 3dbd9b402..bc98cee17 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2860,184 +2860,6 @@ show_smartcard (struct agent_card_info_s *info) free_public_key( pk ); } - -static char * -smartcard_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 -smartcard_change_name (const char *current_name) -{ - char *surname = NULL, *givenname = NULL; - char *isoname, *p; - int rc; - - surname = smartcard_get_one_name ("keygen.smartcard.surname", - _("Cardholder's surname: ")); - givenname = smartcard_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 = '<'; - - 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 -smartcard_change_url (const char *current_url) -{ - char *url; - int rc; - - url = cpr_get ("keygen.smartcard.url", _("URL to retrieve public key: ")); - if (!url) - return -1; - trim_spaces (url); - cpr_kill_prompt (); - - 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 -smartcard_change_login_data (void) -{ - char *data; - int rc; - - data = cpr_get ("keygen.smartcard.login_data", - _("Login data (account name): ")); - if (!data) - return -1; - trim_spaces (data); - cpr_kill_prompt (); - - 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 -smartcard_change_lang (void) -{ - char *data, *p; - int rc; - - data = cpr_get ("keygen.smartcard.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 -smartcard_change_sex (void) -{ - char *data; - const char *str; - int rc; - - data = cpr_get ("keygen.smartcard.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; -} - - /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */ static int fpr_is_zero (const char *fpr) @@ -3083,11 +2905,6 @@ check_smartcard (char **r_serialno) show_smartcard (&info); tty_printf ("\n" - "N - change cardholder name\n" - "U - change public key URL\n" - "D - change login data\n" - "L - change language preferences\n" - "S - change sex\n" "K - generate all keys\n" "Q - quit\n" "\n"); @@ -3098,32 +2915,7 @@ check_smartcard (char **r_serialno) continue; rc = 0; - if ( *answer == 'N' || *answer == 'n') - { - if (!smartcard_change_name (info.disp_name)) - reread = 1; - } - else if ( *answer == 'U' || *answer == 'u') - { - if (!smartcard_change_url (info.pubkey_url)) - reread = 1; - } - else if ( *answer == 'D' || *answer == 'd') - { - if (!smartcard_change_login_data ()) - reread = 1; - } - else if ( *answer == 'L' || *answer == 'l') - { - if (!smartcard_change_lang ()) - reread = 1; - } - else if ( *answer == 'S' || *answer == 's') - { - if (!smartcard_change_sex ()) - reread = 1; - } - else if ( *answer == 'K' || *answer == 'k') + if ( *answer == 'K' || *answer == 'k') { if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) || (info.fpr2valid && !fpr_is_zero (info.fpr2)) diff --git a/g10/main.h b/g10/main.h index 2e1377ea4..320a543de 100644 --- a/g10/main.h +++ b/g10/main.h @@ -258,7 +258,7 @@ void run_in_pipemode (void); /*-- card-util.c --*/ void change_pin (int no); void card_status (FILE *fp); - +void card_edit (STRLIST commands); /*-- signal.c --*/ void init_signals(void); -- cgit v1.2.3 From 43c5c29bc1ec33be42e0078b082186706519f8f2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 19 Sep 2003 11:17:11 +0000 Subject: (parse_ccid_descriptor): New. (read_device_info): New. (ccid_open_reader): Check that the device has all required features. --- g10/card-util.c | 4 +- scd/ChangeLog | 6 ++ scd/ccid-driver.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+), 2 deletions(-) diff --git a/g10/card-util.c b/g10/card-util.c index b0754dcd2..5ee9d03ab 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -477,13 +477,13 @@ card_edit (STRLIST commands) { 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") }, - { NULL, cmdNOP } + { NULL, cmdINVCMD } }; enum cmdids cmd = cmdNOP; int have_commands = !!commands; int redisplay = 1; - char *answer = NULL;; + char *answer = NULL; if (opt.command_fd != -1) ; diff --git a/scd/ChangeLog b/scd/ChangeLog index 1c785b215..e8c4cc88b 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2003-09-19 Werner Koch <wk@gnupg.org> + + * ccid-driver.c (parse_ccid_descriptor): New. + (read_device_info): New. + (ccid_open_reader): Check that the device has all required features. + 2003-09-06 Werner Koch <wk@gnupg.org> * scdaemon.c (main): --pcsc-driver again defaults to pcsclite. diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 6f469de6a..e0b48f880 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -99,8 +99,12 @@ log_debug (DRVNAME t,(a),(b)); } while (0) # define DEBUGOUT_3(t,a,b,c) do { if (DBG_CARD_IO) \ log_debug (DRVNAME t,(a),(b),(c));} while (0) +# define DEBUGOUT_CONT(t) do { if (DBG_CARD_IO) \ + log_printf (t); } while (0) # define DEBUGOUT_CONT_1(t,a) do { if (DBG_CARD_IO) \ log_printf (t,(a)); } while (0) +# define DEBUGOUT_CONT_2(t,a,b) do { if (DBG_CARD_IO) \ + log_printf (t,(a),(b)); } while (0) # define DEBUGOUT_CONT_3(t,a,b,c) do { if (DBG_CARD_IO) \ log_printf (t,(a),(b),(c)); } while (0) # define DEBUGOUT_LF() do { if (DBG_CARD_IO) \ @@ -112,7 +116,9 @@ # define DEBUGOUT_1(t,a) fprintf (stderr, DRVNAME t, (a)) # define DEBUGOUT_2(t,a,b) fprintf (stderr, DRVNAME t, (a), (b)) # define DEBUGOUT_3(t,a,b,c) fprintf (stderr, DRVNAME t, (a), (b), (c)) +# define DEBUGOUT_CONT(t) fprintf (stderr, t) # define DEBUGOUT_CONT_1(t,a) fprintf (stderr, t, (a)) +# define DEBUGOUT_CONT_2(t,a,b) fprintf (stderr, t, (a), (b)) # define DEBUGOUT_CONT_3(t,a,b,c) fprintf (stderr, t, (a), (b), (c)) # define DEBUGOUT_LF() putc ('\n', stderr) @@ -156,6 +162,227 @@ struct ccid_driver_s { }; +/* Convert a little endian stored 4 byte value into an unsigned + integer. */ +static unsigned int +convert_le_u32 (const unsigned char *buf) +{ + return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); +} + + + +/* Parse a CCID descriptor, optionally print all available features + and test whether this reader is usable by this driver. Returns 0 + if it is usable. + + Note, that this code is based on the one in lsusb.c of the + usb-utils package, I wrote on 2003-09-01. -wk. */ +static int +parse_ccid_descriptor (const unsigned char *buf, size_t buflen) +{ + unsigned int i; + unsigned int us; + int have_t1 = 0, have_tpdu=0, have_auto_conf = 0; + + + if (buflen < 54 || buf[0] < 54) + { + DEBUGOUT ("CCID device descriptor is too short\n"); + return -1; + } + + DEBUGOUT ("ChipCard Interface Descriptor:\n"); + DEBUGOUT_1 (" bLength %5u\n", buf[0]); + DEBUGOUT_1 (" bDescriptorType %5u\n", buf[1]); + DEBUGOUT_2 (" bcdCCID %2x.%02x", buf[3], buf[2]); + if (buf[3] != 1 || buf[2] != 0) + DEBUGOUT_CONT(" (Warning: Only accurate for version 1.0)"); + DEBUGOUT_LF (); + + DEBUGOUT_1 (" nMaxSlotIndex %5u\n", buf[4]); + DEBUGOUT_2 (" bVoltageSupport %5u %s\n", + buf[5], (buf[5] == 1? "5.0V" : buf[5] == 2? "3.0V" + : buf[5] == 3? "1.8V":"?")); + + us = convert_le_u32 (buf+6); + DEBUGOUT_1 (" dwProtocols %5u ", us); + if ((us & 1)) + DEBUGOUT_CONT (" T=0"); + if ((us & 2)) + { + DEBUGOUT_CONT (" T=1"); + have_t1 = 1; + } + if ((us & ~3)) + DEBUGOUT_CONT (" (Invalid values detected)"); + DEBUGOUT_LF (); + + us = convert_le_u32(buf+10); + DEBUGOUT_1 (" dwDefaultClock %5u\n", us); + us = convert_le_u32(buf+14); + DEBUGOUT_1 (" dwMaxiumumClock %5u\n", us); + DEBUGOUT_1 (" bNumClockSupported %5u\n", buf[18]); + us = convert_le_u32(buf+19); + DEBUGOUT_1 (" dwDataRate %7u bps\n", us); + us = convert_le_u32(buf+23); + DEBUGOUT_1 (" dwMaxDataRate %7u bps\n", us); + DEBUGOUT_1 (" bNumDataRatesSupp. %5u\n", buf[27]); + + us = convert_le_u32(buf+28); + DEBUGOUT_1 (" dwMaxIFSD %5u\n", us); + + us = convert_le_u32(buf+32); + DEBUGOUT_1 (" dwSyncProtocols %08X ", us); + if ((us&1)) + DEBUGOUT_CONT ( " 2-wire"); + if ((us&2)) + DEBUGOUT_CONT ( " 3-wire"); + if ((us&4)) + DEBUGOUT_CONT ( " I2C"); + DEBUGOUT_LF (); + + us = convert_le_u32(buf+36); + DEBUGOUT_1 (" dwMechanical %08X ", us); + if ((us & 1)) + DEBUGOUT_CONT (" accept"); + if ((us & 2)) + DEBUGOUT_CONT (" eject"); + if ((us & 4)) + DEBUGOUT_CONT (" capture"); + if ((us & 8)) + DEBUGOUT_CONT (" lock"); + DEBUGOUT_LF (); + + us = convert_le_u32(buf+40); + DEBUGOUT_1 (" dwFeatures %08X\n", us); + if ((us & 0x0002)) + { + DEBUGOUT (" Auto configuration based on ATR\n"); + have_auto_conf = 1; + } + if ((us & 0x0004)) + DEBUGOUT (" Auto activation on insert\n"); + if ((us & 0x0008)) + DEBUGOUT (" Auto voltage selection\n"); + if ((us & 0x0010)) + DEBUGOUT (" Auto clock change\n"); + if ((us & 0x0020)) + DEBUGOUT (" Auto baud rate change\n"); + if ((us & 0x0040)) + DEBUGOUT (" Auto parameter negotation made by CCID\n"); + else if ((us & 0x0080)) + DEBUGOUT (" Auto PPS made by CCID\n"); + else if ((us & (0x0040 | 0x0080))) + DEBUGOUT (" WARNING: conflicting negotation features\n"); + + if ((us & 0x0100)) + DEBUGOUT (" CCID can set ICC in clock stop mode\n"); + if ((us & 0x0200)) + DEBUGOUT (" NAD value other than 0x00 accpeted\n"); + if ((us & 0x0400)) + DEBUGOUT (" Auto IFSD exchange\n"); + + if ((us & 0x00010000)) + { + DEBUGOUT (" TPDU level exchange\n"); + have_tpdu = 1; + } + else if ((us & 0x00020000)) + DEBUGOUT (" Short APDU level exchange\n"); + else if ((us & 0x00040000)) + DEBUGOUT (" Short and extended APDU level exchange\n"); + else if ((us & 0x00070000)) + DEBUGOUT (" WARNING: conflicting exchange levels\n"); + + us = convert_le_u32(buf+44); + DEBUGOUT_1 (" dwMaxCCIDMsgLen %5u\n", us); + + DEBUGOUT ( " bClassGetResponse "); + if (buf[48] == 0xff) + DEBUGOUT_CONT ("echo\n"); + else + DEBUGOUT_CONT_1 (" %02X\n", buf[48]); + + DEBUGOUT ( " bClassEnvelope "); + if (buf[49] == 0xff) + DEBUGOUT_CONT ("echo\n"); + else + DEBUGOUT_1 (" %02X\n", buf[48]); + + DEBUGOUT ( " wlcdLayout "); + if (!buf[50] && !buf[51]) + DEBUGOUT_CONT ("none\n"); + else + DEBUGOUT_CONT_2 ("%u cols %u lines\n", buf[50], buf[51]); + + DEBUGOUT_1 (" bPINSupport %5u ", buf[52]); + if ((buf[52] & 1)) + DEBUGOUT_CONT ( " verification"); + if ((buf[52] & 2)) + DEBUGOUT_CONT ( " modification"); + DEBUGOUT_LF (); + + DEBUGOUT_1 (" bMaxCCIDBusySlots %5u\n", buf[53]); + + if (buf[0] > 54) { + DEBUGOUT (" junk "); + for (i=54; i < buf[0]-54; i++) + DEBUGOUT_CONT_1 (" %02X", buf[i]); + DEBUGOUT_LF (); + } + + if (!have_t1 || !have_tpdu || !have_auto_conf) + { + DEBUGOUT ("this drivers requires that the reader supports T=1, " + "TPDU level exchange and auto configuration - " + "this is not available\n"); + return -1; + } + else + return 0; +} + + +/* Read the device information, return all required data and check + that the device is usable for us. Returns 0 on success or an error + code. */ +static int +read_device_info (struct usb_device *dev) +{ + int cfg_no; + + for (cfg_no=0; cfg_no < dev->descriptor->bNumConfigurations; cfg_no++) + { + struct usb_config_descriptor *config = dev->config + cfg_no; + int ifc_no; + + for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++) + { + struct usb_interface *interface = config->interface + ifc_no; + int set_no; + + for (set_no=0; set_no < interface->num_altsetting; set_no++) + { + struct usb_interface_descriptor *ifcdesc + = interface->altsetting + set_no; + + if (ifcdesc->bInterfaceClass == 11 + && ifcdesc->bInterfaceSubClass == 0 + && ifcdesc->bInterfaceProtocol == 0) + { + if (ifcdesc->extra) + { + if (!parse_ccid_descriptor (ifcdesc->extra, + ifcdesc->extralen)) + return 0; /* okay. we can use it. */ + } + } + } + } + } + return -1; /* No suitable device found. */ +} /* Open the reader with the internal number READERNO and return a a @@ -190,6 +417,13 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) dev->descriptor->idVendor, dev->descriptor->idProduct); if (!readerno) { + rc = read_device_info (dev); + if (rc) + { + DEBUGOUT ("device not supported\n"); + goto leave; + } + rc = usb_open (dev, &idev); if (rc) { @@ -197,6 +431,9 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) goto leave; } + + /* fixme: Do we need to claim and set the interface as + determined by read_device_info ()? */ rc = usb_claim_interface (idev, 0); if (rc) { @@ -213,6 +450,9 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) } (*handle)->idev = idev; idev = NULL; + /* FIXME: Do we need to get the endpoint addresses from the + structure and store them with the handle? */ + break; } readerno--; -- cgit v1.2.3 From 47959a306e07127cd87227861b0552a0c639cab1 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Mon, 22 Sep 2003 20:43:25 +0000 Subject: 2003-09-22 Timo Schulz <twoaday@freakmail.de> * card-util.c (card_status): Free pk in case of an error and return if the card is no OpenPGP card. --- g10/ChangeLog | 5 +++++ g10/card-util.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/g10/ChangeLog b/g10/ChangeLog index 6f53430c3..221961c4e 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2003-09-22 Timo Schulz <twoaday@freakmail.de> + + * card-util.c (card_status): Free pk in case of an error + and return if the card is no OpenPGP card. + 2003-09-18 Werner Koch <wk@gnupg.org> * g10.c: New command --card-edit. diff --git a/g10/card-util.c b/g10/card-util.c index 5ee9d03ab..99b40e9df 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -216,6 +216,7 @@ card_status (FILE *fp) { log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (rc)); + xfree (pk); return; } @@ -226,6 +227,8 @@ card_status (FILE *fp) { log_info ("not an OpenPGP card\n"); agent_release_card_info (&info); + xfree (pk); + return; } tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n", info.serialno[12] == '0'?"":info.serialno+12, -- cgit v1.2.3 From 4c66e94ff91d680eaf1d9c48a62d66d1951f90ef Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Sep 2003 17:48:33 +0000 Subject: Merged most of David Shaw's changes in 1.3 since 2003-06-03. --- ChangeLog | 14 +++ TODO | 2 + common/ChangeLog | 8 ++ common/iobuf.c | 20 ++-- common/ttyio.c | 16 +-- common/util.h | 4 + configure.ac | 36 +++--- g10/ChangeLog | 264 ++++++++++++++++++++++++++++++++++++++++++++ g10/Makefile.am | 2 +- g10/armor.c | 39 +++---- g10/build-packet.c | 4 + g10/encode.c | 4 + g10/exec.c | 10 +- g10/g10.c | 313 +++++++++++++++++++++++++++++++++-------------------- g10/getkey.c | 8 +- g10/gpgv.c | 16 ++- g10/import.c | 232 +++++++++++++++++++++------------------ g10/keyedit.c | 226 ++++++++++++++++++++++++++++++++++---- g10/keygen.c | 52 +++++++-- g10/keylist.c | 147 ++++++++++++++++++++++--- g10/keyring.c | 7 ++ g10/keyserver.c | 9 +- g10/main.h | 5 +- g10/mainproc.c | 131 ++++++++++++++++------ g10/misc.c | 29 ++++- g10/options.h | 27 +++-- g10/options.skel | 18 +-- g10/packet.h | 9 +- g10/parse-packet.c | 65 +++++++---- g10/passphrase.c | 22 ++-- g10/photoid.c | 4 +- g10/pkclist.c | 4 - g10/revoke.c | 2 +- g10/sig-check.c | 81 ++++++++------ g10/sign.c | 65 ++++++++--- g10/signal.c | 27 +++-- g10/status.c | 1 + g10/status.h | 1 + g10/tdbdump.c | 2 +- g10/tdbio.c | 5 + g10/trustdb.c | 42 +++++-- g10/trustdb.h | 3 + include/ChangeLog | 11 ++ include/cipher.h | 1 - include/types.h | 10 +- 45 files changed, 1489 insertions(+), 509 deletions(-) diff --git a/ChangeLog b/ChangeLog index 172dd0fe4..ce3d76967 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +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. diff --git a/TODO b/TODO index fe81d0241..da337f247 100644 --- a/TODO +++ b/TODO @@ -63,3 +63,5 @@ might want to have an agent context for each service request * ALL ** Return IMPORT_OK status. + +* Where is http.c, regcomp.c, srv.c, w32reg.c ? diff --git a/common/ChangeLog b/common/ChangeLog index 66e935b28..caabdd4cf 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,11 @@ +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. diff --git a/common/iobuf.c b/common/iobuf.c index 773e2993b..4d735397e 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -101,7 +101,7 @@ typedef struct close_cache_s *CLOSE_CACHE; static CLOSE_CACHE close_cache; #endif -#ifdef __MINGW32__ +#ifdef _WIN32 typedef struct { int sock; @@ -112,7 +112,7 @@ typedef struct char fname[1]; /* name of the file */ } sock_filter_ctx_t; -#endif /*__MINGW32__*/ +#endif /*_WIN32*/ /* The first partial length header block must be of size 512 * to make it easier (and efficienter) we use a min. block size of 512 @@ -580,7 +580,7 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf, return rc; } -#ifdef __MINGW32__ +#ifdef _WIN32 /* Becuase sockets are an special object under Lose32 we have to * use a special filter */ static int @@ -667,7 +667,7 @@ sock_filter (void *opaque, int control, iobuf_t chain, byte * buf, } return rc; } -#endif /*__MINGW32__*/ +#endif /*_WIN32*/ /**************** * This is used to implement the block write mode. @@ -1171,7 +1171,7 @@ check_special_filename (const char *fname) int i; fname += 2; - for (i = 0; isdigit (fname[i]); i++) + for (i = 0; digitp (fname+i); i++) ; if (!fname[i]) return atoi (fname); @@ -1262,7 +1262,7 @@ iobuf_t iobuf_sockopen (int fd, const char *mode) { iobuf_t a; -#ifdef __MINGW32__ +#ifdef _WIN32 sock_filter_ctx_t *scx; size_t len; @@ -1405,7 +1405,7 @@ iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval) b->keep_open = intval; return 0; } -#ifdef __MINGW32__ +#ifdef _WIN32 else if (!a->chain && a->filter == sock_filter) { sock_filter_ctx_t *b = a->filter_ov; @@ -1440,7 +1440,7 @@ iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval) b->no_cache = intval; return 0; } -#ifdef __MINGW32__ +#ifdef _WIN32 else if (!a->chain && a->filter == sock_filter) { sock_filter_ctx_t *b = a->filter_ov; @@ -2363,7 +2363,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, int iobuf_translate_file_handle (int fd, int for_write) { -#ifdef __MINGW32__ +#ifdef _WIN32 { int x; @@ -2387,7 +2387,7 @@ iobuf_translate_file_handle (int fd, int for_write) static int translate_file_handle (int fd, int for_write) { -#ifdef __MINGW32__ +#ifdef _WIN32 #ifdef FILE_FILTER_USES_STDIO fd = iobuf_translate_file_handle (fd, for_write); #else diff --git a/common/ttyio.c b/common/ttyio.c index c77b4a85a..eab805e20 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -37,7 +37,7 @@ #define HAVE_TCGETATTR #endif #endif -#ifdef __MINGW32__ /* use the odd Win32 functions */ +#ifdef _WIN32 /* use the odd Win32 functions */ #include <windows.h> #ifdef HAVE_TCGETATTR #error mingw32 and termios @@ -51,7 +51,7 @@ #define CONTROL_D ('D' - 'A' + 1) -#ifdef __MINGW32__ /* use the odd Win32 functions */ +#ifdef _WIN32 /* use the odd Win32 functions */ static struct { HANDLE in, out; } con; @@ -124,7 +124,7 @@ init_ttyfp(void) if( initialized ) return; -#if defined(__MINGW32__) +#if defined(_WIN32) { SECURITY_ATTRIBUTES sa; @@ -194,7 +194,7 @@ tty_printf( const char *fmt, ... ) init_ttyfp(); va_start( arg_ptr, fmt ) ; -#ifdef __MINGW32__ +#ifdef _WIN32 { char *buf = NULL; int n; @@ -241,7 +241,7 @@ tty_fprintf (FILE *fp, const char *fmt, ... ) init_ttyfp(); va_start( arg_ptr, fmt ) ; -#ifdef __MINGW32__ +#ifdef _WIN32 { char *buf = NULL; int n; @@ -278,7 +278,7 @@ tty_print_string ( const byte *p, size_t n ) if( !initialized ) init_ttyfp(); -#ifdef __MINGW32__ +#ifdef _WIN32 /* not so effective, change it if you want */ for( ; n; n--, p++ ) if( iscntrl( *p ) ) { @@ -372,7 +372,7 @@ do_get( const char *prompt, int hidden ) buf = xmalloc((n=50)); i = 0; -#ifdef __MINGW32__ /* windoze version */ +#ifdef _WIN32 /* windoze version */ if( hidden ) SetConsoleMode(con.in, HID_INPMODE ); @@ -527,7 +527,7 @@ tty_kill_prompt() last_prompt_len = 0; if( !last_prompt_len ) return; -#ifdef __MINGW32__ +#ifdef _WIN32 tty_printf("\r%*s\r", last_prompt_len, ""); #else { diff --git a/common/util.h b/common/util.h index 045851481..78aa2f890 100644 --- a/common/util.h +++ b/common/util.h @@ -107,6 +107,10 @@ int asprintf (char **result, const char *format, ...); #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)) diff --git a/configure.ac b/configure.ac index 4ee1898b5..23baee44a 100644 --- a/configure.ac +++ b/configure.ac @@ -647,7 +647,17 @@ AC_CHECK_SIZEOF(unsigned short) AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long long) -AC_CHECK_SIZEOF(uint64_t) +# Ensure that we have UINT64_C before we bother to check for uint64_t +# fixme: really needed in gnupg? I think it is only useful in libcgrypt. +AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works], + AC_COMPILE_IFELSE(AC_LANG_PROGRAM([#include <inttypes.h> +uint64_t foo=UINT64_C(42);]),gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no)) +if test "$gnupg_cv_uint64_c_works" = "yes" ; then + AC_CHECK_SIZEOF(uint64_t) +fi + + + if test "$ac_cv_sizeof_unsigned_short" = "0" \ || test "$ac_cv_sizeof_unsigned_int" = "0" \ @@ -660,19 +670,8 @@ if test "$ac_cv_sizeof_unsigned_int" != "8" \ && test "$ac_cv_sizeof_unsigned_long" != "8" \ && test "$ac_cv_sizeof_unsigned_long_long" != "8" \ && test "$ac_cv_sizeof_uint64_t" != "8"; then - AC_MSG_WARN([No 64-bit types. Disabling TIGER/192, SHA-384, and SHA-512]) + AC_MSG_WARN([No 64-bit types. Disabling SHA-384, and SHA-512]) else - if test x"$use_tiger192" = xyes ; then - AC_SUBST(TIGER_O,tiger.o) - AC_DEFINE(USE_TIGER192,1,[Define to include the TIGER/192 digest]) - fi - - if test "$use_old_tiger192" = yes ; then - AC_SUBST(TIGER_O,tiger.o) - AC_DEFINE(USE_TIGER192,1,[Define to include the TIGER/192 digest]) - AC_DEFINE(USE_OLD_TIGER,1,[Define to use the old fake OID for TIGER/192 digest support]) - fi - if test x"$use_sha512" = xyes ; then AC_SUBST(SHA512_O,sha512.o) AC_DEFINE(USE_SHA512,1,[Define to include the SHA-384 and SHA-512 digests]) @@ -689,9 +688,11 @@ AC_CHECK_FUNCS(strerror stpcpy strsep strlwr tcgetattr strtoul mmap) AC_CHECK_FUNCS(strcasecmp strncasecmp ctermid times) AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) -AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat) +AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat getaddrinfo) + +AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>]) -# These are needed by libjnlib - fixme: we should have a macros for them +# These are needed by libjnlib - fixme: we should have macros for them AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) AC_CHECK_FUNCS(flockfile funlockfile) @@ -703,6 +704,8 @@ AC_REPLACE_FUNCS(fseeko ftello) AC_REPLACE_FUNCS(isascii) AC_REPLACE_FUNCS(putc_unlocked) + + # # check for gethrtime and run a testprogram to see whether # it is broken. It has been reported that some Solaris and HP UX systems @@ -877,7 +880,7 @@ GNUPG_CHECK_GNUMAKE # mysterious reasons - the final link step should bail out. case "${target}" in *-*-mingw32*) - LIBS="$LIBS -lwsock32" + W32LIBS="-lwsock32" ;; *) ;; @@ -893,6 +896,7 @@ if test "$GCC" = yes; then fi AC_SUBST(NETLIBS) +AC_SUBST(W32LIBS) # We use jnlib, so tell other modules about it diff --git a/g10/ChangeLog b/g10/ChangeLog index 221961c4e..ac7a69468 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,267 @@ +2003-09-23 Werner Koch <wk@gnupg.org> + + Merged most of David Shaw's changes in 1.3 since 2003-06-03. + + * Makefile.am: Include W32LIBS where appropriate. + + * armor.c (parse_hash_header,armor_filter): Drop TIGER/192 support. + * g10.c (print_hex,print_mds): Ditto. + * pkclist.c (algo_available): Ditto. + + * armor.c (armor_filter): Allow using --comment multiple times to + get multiple Comment header lines. --no-comments resets list. + * options.h, g10.c (main): Ditto. Deprecate --default-comment in + favor of --no-comments. + + * g10.c (main): Trim --help to commonly used options. Remove -f. + + * g10.c (main): Add --multifile as an alias to turn --encrypt into + --encrypt-files (plus --verify-files, --decrypt-files). Error out + if --multifile is used with the commands that don't support it yet. + + * encode.c (use_mdc), g10.c (main): Use RFC1991 and RFC2440 + directly to check for MDC usability. Do not set the force_mdc or + disable_mdc flags since there is no point any longer. + + * g10.c (main): Use "keyserver-url" instead of + "preferred-keyserver" for the sake of short and simple commands. + (add_keyserver_url): Clarify a few strings. It's a + "preferred keyserver URL". + * keyedit.c (keyedit_menu): Ditto. + * sign.c (mk_notation_policy_etc): Ditto. + + * main.h, keygen.c (keygen_add_keyserver_url): Signature callback + for adding a keyserver URL. + * keyedit.c (keyedit_menu, menu_set_keyserver_url): New command to + set preferred keyserver to specified (or all) user IDs. + * build-packet.c (build_sig_subpkt): Set preferred keyserver flag + while building a preferred keyserver subpacket. + + * keylist.c (show_policy_url, show_keyserver_url): URLs might be + UTF8. + + * keyedit.c (menu_addrevoker): Fix leaking a few bytes. + + * keyedit.c (show_key_with_all_names): Use list-option + show-long-keyid in main --edit-key display. + + * keyedit.c (print_and_check_one_sig): Use list-option + show-long-keyid in --edit-key "check" function. + + * passphrase.c (agent_send_all_options): Make use of $GPG_TTY. + + * g10.c (main): Disable use-agent if passphrase-fd is given + later. Suggested by Kurt Garloff. + + * exec.c, g10.c, gpgv.c, passphrase.c, photoid.c: + s/__MINGW32__/_WIN32/ to help building on native Windows + compilers. Requested by Brian Gladman. From Werner on stable + branch. + + * options.h, g10.c (main): Add list-option + list-preferred-keyserver. + + * keyedit.c (change_passphrase): When responding 'no' to the blank + passphrase question, re-prompt for a new passphrase. This is bug + #202. + + * mainproc.c (check_sig_and_print): Use two different preferred + keyserver displays - one if the key is not present (to tell the + user where to get the key), the other if it is present (to tell + the user where the key can be refreshed). + + * packet.h, parse-packet.c (parse_signature): Set flag if a + preferred keyserver is present. + + * keylist.c (list_keyblock_print): Show keyserver url in listings + with list-option show-keyserver-url. + + * mainproc.c (check_sig_and_print): Get the uid validity before + printing any sig results to avoid munging the output with trustdb + warnings. + + * g10.c (main): Don't include --show-keyring in --help as it is + deprecated. + + * options.skel: Note that keyserver.pgp.com isn't synchronized, + and explain the roundrobin a bit better. + + * sig-check.c (check_key_signature2), import.c (import_one, + import_revoke_cert, chk_self_sigs, delete_inv_parts, + collapse_uids, merge_blocks): Make much quieter during import of + slightly munged, but recoverable, keys. Use log_error for + unrecoverable import failures. + + * keyring.c (keyring_rebuild_cache): Comment. + + * sign.c (mk_notation_and_policy): Making a v3 signature with + notations or policy urls is an error, not an info (i.e. increment + the errorcount). Don't print the notation or policy url to stdout + since it can be mixed into the output stream when piping and munge + the stream. + + * packet.h, sig-check.c (signature_check2, do_check, + do_check_messages): Provide a signing-key-is-revoked flag. Change + all callers. + + * status.h, status.c (get_status_string): New REVKEYSIG status tag + for a good signature from a revoked key. + + * mainproc.c (do_check_sig, check_sig_and_print): Use it here. + + * import.c (import_revoke_cert, merge_blocks, merge_sigs): Compare + actual signatures on import rather than using keyid or class + matching. This does not change actual behavior with a key, but + does mean that all sigs are imported whether they will be used or + not. + + * parse-packet.c (parse_signature): Don't give "signature packet + without xxxx" warnings for experimental pk algorithms. An + experimental algorithm may not have a notion of (for example) a + keyid (i.e. PGP's x.509 stuff). + + * options.h, g10.c (main), keylist.c (list_keyblock_print), + keyedit.c (print_and_check_one_sig): New "show-sig-expire" + list-option to show signature expiration dates (if any). + + * options.h, g10.c (main, add_keyserver_url): Add + --sig-preferred-keyserver to implant a "where to get my key" + subpacket into a signature. + + * sign.c (mk_notation_and_policy): Rename to + mk_notation_policy_etc and add preferred keyserver support for + signatures. + + * keygen.c (do_add_key_flags): Don't set the certify flag for + subkeys. + (ask_algo): Provide key flags for DSA, Elgamal_e, and Elgamal + subkeys. + (generate_keypair): Provide key flags for the default DSA/Elgamal + keys. + + * sig-check.c (signature_check, signature_check2, + check_key_signature, check_key_signature2): Allow passing NULLs + for unused parameters in the x2 form of each function to avoid the + need for dummy variables. getkey.c, mainproc.c: Change all + callers. + + * trustdb.h, trustdb.c (read_trust_options): New. Returns items + from the trustdb version record. + * keylist.c (public_key_list): Use it here for the new "tru" + record. + * gpgv.c (read_trust_options): Stub. + + * keyedit.c (show_key_with_all_names): Use list-option + show-validity in --edit-key interface as well. + + * options.h, g10.c (main), mainproc.c (check_sig_and_print): Add + verify-options "show-validity" and "show-long-keyid" to show + trustdb validity and long keyids during (file) signature + verification. + + * packet.h, main.h, sig-check.c (signature_check2) + (check_key_signature2, do_check): If ret_pk is set, fill in the pk + used to verify the signature. Change all callers in getkey.c, + mainproc.c, and sig-check.c. + + * keylist.c (list_keyblock_colon): Use the ret_pk from above to + put the fingerprint of the signing key in "sig" records during a + --with-colons --check-sigs. This requires --no-sig-cache as well + since we don't cache fingerprints. + + * parse-packet.c (parse_signature): No need to reserve 8 bytes for + the unhashed signature cache any longer. + + * misc.c (pct_expando): Add two new expandos - signer's + fingerprint (%g), and signer's primary fingerprint (%p). + + * g10.c (main): Add --rfc2440 alias for --openpgp since in a few + months, they won't be the same thing. + + * keyserver.c (parse_keyserver_uri): Accept "http" as an alias for + "hkp", since it is occasionally written that way. + (keyserver_spawn): Use ascii_isspace to avoid locale issues. + + * keygen.c (ask_user_id): Make --allow-freeform-uid apply to the + email field as well as the name field, and allow mixing fields + when it is set. + + * trustdb.c (validate_one_keyblock): Certifications on revoked or + expired uids do not count in the web of trust. + + * signal.c (init_one_signal, pause_on_sigusr, do_block): Only use + sigprocmask() if we have sigset_t, and only use sigaction() if we + have struct sigaction. This is for Forte c89 on Solaris which + seems to define only the function call half of the two pairs by + default. + (pause_on_sigusr): Typo. + (do_block): If we can't use sigprocmask() and sigset_t, try to get + the number of signals from NSIG as well as MAXSIG, and if we + can't, fail with an explanation. + + * signal.c, tdbio.c: Comment out the transaction code. It was not + used in this version, and was causing some build problems on + quasi-posix platforms (Solaris and Forte c89). + + * keylist.c (list_keyblock_colon): Don't include validity values + when listing secret keys since they can be incorrect and/or + misleading. This is a temporary kludge, and will be handled + properly in 1.9/2.0. + + * mainproc.c (check_sig_and_print): Only show the "key available + from" preferred keyserver line if the key is not currently + present. + + * keyedit.c (sign_uids): Do not sign expired uids without --expert + (same behavior as revoked uids). Do not allow signing a user ID + without a self-signature. --expert overrides. Add additional + prompt to the signature level question. + (menu_expire): When changing expiration dates, don't replace + selfsigs on revoked uids since this would effectively unrevoke + them. There is also no point in replacing expired selfsigs. This + is bug #181 + + * g10.c (add_notation_data): Make sure that only ascii is passed + to iscntrl. Noted by Christian Biere. + * getkey.c (classify_user_id2): Replaced isspace by spacep + * keygen.c (ask_user_id): Ditto. + (get_parameter_algo): Ditto. + * keyedit.c (keyedit_menu): Ditto. + * tdbdump.c (import_ownertrust): Ditto. s/isxdigit/hexdigitp/. + * revoke.c (ask_revocation_reason): + * keyserver.c (keyserver_spawn): Dito. + + * parse-packet.c (parse): Disallow old style partial length for + all key material packets to avoid possible corruption of keyrings. + + * import.c (import_keys_internal): Invalidate the cache so that + the file descriptor gets closed. Fixes bug reported by Juan + F. Codagnone. + + * options.h, g10.c (main), main.h, keylist.c (show_keyserver_url), + mainproc.c (check_sig_and_print), parse-packet.c (dump_sig_subpkt, + parse_one_sig_subpkt, can_handle_critical): Add read-only support + for preferred keyserver subpackets. They're basically policy URLs + with a different name. Add a verify-option + "show-preferred-keyserver" to turn them on and off (on by default, + as per stable branch). + + * g10.c (main): Add "--set-notation" as alias to "--notation-data" + this is to make things consistent with --set-policy-url meaning + both sigs and certs. + + * options.h, g10.c (main), keylist.c (list_keyblock_print): Add + "show-validity" and "show-long-keyid" list-options. + + * gpgv.c (get_validity, trust_value_to_string): Stubs. + + * g10.c (main): Use SAFE_VERSION instead of VERSION in the + version-specific gpg.conf file so it can be overridden on RISCOS. + + * keyedit.c (show_key_with_all_names): Fix assertion failure when + using toggle to see a secret key. Reported by Maxim Britov. + + 2003-09-22 Timo Schulz <twoaday@freakmail.de> * card-util.c (card_status): Free pk in case of an error diff --git a/g10/Makefile.am b/g10/Makefile.am index 59213d04b..ef2b0c3a8 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -109,7 +109,7 @@ gpgv2_SOURCES = gpgv.c \ # ks-db.h \ # $(common_source) -LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ +LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ @W32LIBS@ gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error diff --git a/g10/armor.c b/g10/armor.c index c6930e22a..121ec3a09 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -249,16 +249,12 @@ parse_hash_header( const char *line ) found |= 2; else if( !strncmp( s, "MD5", s2-s ) ) found |= 4; - else if( !strncmp( s, "TIGER192", s2-s ) ) - found |= 8; - else if( !strncmp( s, "TIGER", s2-s ) ) /* used by old versions */ - found |= 8; else if( !strncmp( s, "SHA256", s2-s ) ) - found |= 16; + found |= 8; else if( !strncmp( s, "SHA384", s2-s ) ) - found |= 32; + found |= 16; else if( !strncmp( s, "SHA512", s2-s ) ) - found |= 64; + found |= 32; else return 0; for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) @@ -899,12 +895,10 @@ armor_filter( void *opaque, int control, if( hashes & 4 ) buf[n++] = DIGEST_ALGO_MD5; if( hashes & 8 ) - buf[n++] = DIGEST_ALGO_TIGER; - if( hashes & 16 ) buf[n++] = DIGEST_ALGO_SHA256; - if( hashes & 32 ) + if( hashes & 16 ) buf[n++] = DIGEST_ALGO_SHA384; - if( hashes & 64 ) + if( hashes & 32 ) buf[n++] = DIGEST_ALGO_SHA512; buf[1] = n - 2; @@ -932,6 +926,7 @@ armor_filter( void *opaque, int control, else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) { if( !afx->status ) { /* write the header line */ const char *s; + STRLIST comment = opt.comments; if( afx->what >= DIM(head_strings) ) log_bug("afx->what=%d", afx->what); @@ -942,22 +937,24 @@ armor_filter( void *opaque, int control, iobuf_writestr(a, "Version: GnuPG v" VERSION " (" PRINTABLE_OS_NAME ")" LF ); - /* write the comment string or a default one */ - s = opt.comment_string; - if( s && *s ) { + /* Write the comment string. */ + for(s=comment? comment->d:NULL; comment; + comment=comment->next,s=comment->d) + { iobuf_writestr(a, "Comment: " ); - for( ; *s; s++ ) { + for ( ; *s; s++ ) + { if( *s == '\n' ) - iobuf_writestr(a, "\\n" ); + iobuf_writestr(a, "\\n" ); else if( *s == '\r' ) - iobuf_writestr(a, "\\r" ); + iobuf_writestr(a, "\\r" ); else if( *s == '\v' ) - iobuf_writestr(a, "\\v" ); + iobuf_writestr(a, "\\v" ); else - iobuf_put(a, *s ); - } + iobuf_put(a, *s ); + } iobuf_writestr(a, LF ); - } + } if ( afx->hdrlines ) { for ( s = afx->hdrlines; *s; s++ ) { diff --git a/g10/build-packet.c b/g10/build-packet.c index a24bdfcc6..d2c538477 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -756,6 +756,10 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, sig->flags.policy_url=1; break; + case SIGSUBPKT_PREF_KS: + sig->flags.pref_ks=1; + break; + case SIGSUBPKT_EXPORTABLE: if(buffer[0]) sig->flags.exportable=1; diff --git a/g10/encode.c b/g10/encode.c index 9fc00183f..7794bdb7c 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -122,6 +122,10 @@ use_mdc (PK_LIST pk_list,int algo) 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) diff --git a/g10/exec.c b/g10/exec.c index f3b58aa3c..a49fe15d2 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -1,5 +1,5 @@ /* exec.c - generic call-a-program code - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -59,7 +59,7 @@ int set_exec_path(const char *path,int method) { return GPG_ERR_GENERAL; } char *mkdtemp(char *template); #endif -#if defined (__MINGW32__) +#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. */ @@ -139,7 +139,7 @@ static int make_tempdir(struct exec_info *info) if(tmp==NULL) { -#if defined (__MINGW32__) +#if defined (_WIN32) tmp=xmalloc (256); if(GetTempPath(256,tmp)==0) strcpy(tmp,"c:\\windows\\temp"); @@ -176,7 +176,7 @@ static int make_tempdir(struct exec_info *info) sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); -#if defined (__MINGW32__) +#if defined (_WIN32) xfree (tmp); #endif @@ -502,7 +502,7 @@ int exec_read(struct exec_info *info) if(DBG_EXTPROG) log_debug("system() command is %s\n",info->command); -#if defined (__MINGW32__) +#if defined (_WIN32) info->progreturn=win_system(info->command); #else info->progreturn=system(info->command); diff --git a/g10/g10.c b/g10/g10.c index 619832372..cdd10d845 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -59,7 +59,6 @@ enum cmd_and_opt_values { aNull = 0, aSym = 'c', aDecrypt = 'd', aEncr = 'e', - aEncrFiles, oInteractive = 'i', aListKeys = 'k', aListSecretKeys = 'K', @@ -73,12 +72,13 @@ enum cmd_and_opt_values { aNull = 0, oUser = 'u', oVerbose = 'v', oCompress = 'z', - oNotation = 'N', + oSetNotation = 'N', oBatch = 500, oSigNotation, oCertNotation, oShowNotation, oNoShowNotation, + aEncrFiles, aDecryptFiles, aClearsign, aStore, @@ -172,6 +172,7 @@ enum cmd_and_opt_values { aNull = 0, oLoadExtension, oGnuPG, oRFC1991, + oRFC2440, oOpenPGP, oPGP2, oPGP6, @@ -219,9 +220,11 @@ enum cmd_and_opt_values { aNull = 0, oCertPolicyURL, oShowPolicyURL, oNoShowPolicyURL, + oSigKeyserverURL, oUseEmbeddedFilename, oComment, oDefaultComment, + oNoComments, oThrowKeyid, oNoThrowKeyid, oShowPhotos, @@ -315,6 +318,7 @@ enum cmd_and_opt_values { aNull = 0, oMangleDosFilenames, oNoMangleDosFilenames, oEnableProgressFilter, + oMultifile, aTest }; @@ -326,17 +330,17 @@ static ARGPARSE_OPTS opts[] = { { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, { aEncr, "encrypt", 256, N_("encrypt data")}, - { aEncrFiles, "encrypt-files", 256, N_("|[files]|encrypt files")}, + { aEncrFiles, "encrypt-files", 256, "@"}, { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, - { aStore, "store", 256, N_("store only")}, + { aStore, "store", 256, "@"}, { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, - { aDecryptFiles, "decrypt-files", 256, N_("|[files]|decrypt files")}, + { aDecryptFiles, "decrypt-files", 256, "@"}, { aVerify, "verify" , 256, N_("verify a signature")}, { aVerifyFiles, "verify-files" , 256, "@" }, { aListKeys, "list-keys", 256, N_("list keys")}, { aListKeys, "list-public-keys", 256, "@" }, { aListSigs, "list-sigs", 256, N_("list keys and signatures")}, - { aCheckKeys, "check-sigs",256, N_("check key signatures")}, + { aCheckKeys, "check-sigs",256, N_("list and check key signatures")}, { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, { aKeygen, "gen-key", 256, N_("generate a new key pair")}, @@ -345,8 +349,8 @@ static ARGPARSE_OPTS opts[] = { N_("remove keys from the secret keyring")}, { aSignKey, "sign-key" ,256, N_("sign a key")}, { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, - { aNRSignKey, "nrsign-key" ,256, N_("sign a key non-revocably")}, - { aNRLSignKey, "nrlsign-key" ,256, N_("sign a key locally and non-revocably")}, + { aNRSignKey, "nrsign-key" ,256, "@"}, + { aNRLSignKey, "nrlsign-key" ,256, "@"}, { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, { aDesigRevoke, "desig-revoke",256, "@" }, @@ -366,19 +370,15 @@ static ARGPARSE_OPTS opts[] = { { aCardEdit, "card-edit", 256, N_("change data on a card")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, - { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, - { aExportOwnerTrust, - "export-ownertrust", 256, N_("export the ownertrust values")}, - { aImportOwnerTrust, - "import-ownertrust", 256, N_("import ownertrust values")}, - { aUpdateTrustDB, - "update-trustdb",0 , N_("update the trust database")}, - { aCheckTrustDB, - "check-trustdb",0 , N_("unattended trust database update")}, + { aListPackets, "list-packets",256, "@"}, + { aExportOwnerTrust, "export-ownertrust", 256, "@"}, + { aImportOwnerTrust, "import-ownertrust", 256, "@"}, + { aUpdateTrustDB, "update-trustdb",0 , N_("update the trust database")}, + { aCheckTrustDB, "check-trustdb",0 , "@"}, { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, - { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") }, + { aDeArmor, "dearmor", 256, "@" }, { aDeArmor, "dearmour", 256, "@" }, - { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") }, + { aEnArmor, "enarmor", 256, "@" }, { aEnArmor, "enarmour", 256, "@" }, { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, { aPrimegen, "gen-prime" , 256, "@" }, @@ -391,10 +391,8 @@ static ARGPARSE_OPTS opts[] = { { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, { oHiddenRecipient, "hidden-recipient", 2, "@" }, { oRecipient, "remote-user", 2, "@"}, /* old option name */ - { oDefRecipient, "default-recipient" ,2, - N_("|NAME|use NAME as default recipient")}, - { oDefRecipientSelf, "default-recipient-self" ,0, - N_("use the default key as default recipient")}, + { oDefRecipient, "default-recipient" ,2, "@" }, + { oDefRecipientSelf, "default-recipient-self" ,0, "@" }, { oNoDefRecipient, "no-default-recipient", 0, "@" }, { oTempDir, "temp-directory", 2, "@" }, { oExecPath, "exec-path", 2, "@" }, @@ -414,82 +412,82 @@ static ARGPARSE_OPTS opts[] = { { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, { oOutput, "output", 2, N_("use as output file")}, { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, - { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, - { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, - { oNoForceV3Sigs, "no-force-v3-sigs", 0, N_("do not force v3 signatures") }, - { oForceV4Certs, "force-v4-certs", 0, N_("force v4 key signatures") }, - { oNoForceV4Certs, "no-force-v4-certs", 0, N_("do not force v4 key signatures") }, - { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, + { oQuiet, "quiet", 0, "@" }, + { oNoTTY, "no-tty", 0, "@" }, + { oForceV3Sigs, "force-v3-sigs", 0, "@" }, + { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@" }, + { oForceV4Certs, "force-v4-certs", 0, "@" }, + { oNoForceV4Certs, "no-force-v4-certs", 0, "@" }, + { oForceMDC, "force-mdc", 0, "@" }, { oNoForceMDC, "no-force-mdc", 0, "@" }, - { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") }, + { oDisableMDC, "disable-mdc", 0, "@" }, { oNoDisableMDC, "no-disable-mdc", 0, "@" }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, { oInteractive, "interactive", 0, N_("prompt before overwriting") }, - { oUseAgent, "use-agent",0, N_("use the gpg-agent")}, + { oUseAgent, "use-agent",0, "@"}, { oNoUseAgent, "no-use-agent",0, "@"}, { oGpgAgentInfo, "gpg-agent-info",2, "@"}, - { oBatch, "batch", 0, N_("batch mode: never ask")}, - { oAnswerYes, "yes", 0, N_("assume yes on most questions")}, - { oAnswerNo, "no", 0, N_("assume no on most questions")}, - { oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")}, + { oBatch, "batch", 0, "@"}, + { oAnswerYes, "yes", 0, "@"}, + { oAnswerNo, "no", 0, "@"}, + { oKeyring, "keyring" , 2, "@"}, { oPrimaryKeyring, "primary-keyring",2, "@" }, - { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, - { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")}, - { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, - { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, + { oSecretKeyring, "secret-keyring" ,2, "@"}, + { oShowKeyring, "show-keyring", 0, "@"}, + { oDefaultKey, "default-key" , 2, "@"}, + { oKeyServer, "keyserver", 2, "@"}, { oKeyServerOptions, "keyserver-options",2,"@"}, { oImportOptions, "import-options",2,"@"}, { oExportOptions, "export-options",2,"@"}, { oListOptions, "list-options",2,"@"}, - { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, - { oOptions, "options" , 2, N_("read options from file")}, + { oVerifyOptions, "verify-options",2,"@"}, + { oCharset, "charset" , 2, "@" }, + { oOptions, "options" , 2, "@"}, { oDebug, "debug" ,4|16, "@"}, { oDebugAll, "debug-all" ,0, "@"}, - { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, + { oStatusFD, "status-fd" ,1, "@" }, #ifdef __riscos__ - { oStatusFile, "status-file" ,2, N_("|[file]|write status info to file") }, + { oStatusFile, "status-file" ,2, "@" }, #endif /* __riscos__ */ { oAttributeFD, "attribute-fd" ,1, "@" }, #ifdef __riscos__ { oAttributeFile, "attribute-file" ,2, "@" }, #endif /* __riscos__ */ - { oNoSKComments, "no-comment", 0, "@"}, { oNoSKComments, "no-sk-comments", 0, "@"}, { oSKComments, "sk-comments", 0, "@"}, { oCompletesNeeded, "completes-needed", 1, "@"}, { oMarginalsNeeded, "marginals-needed", 1, "@"}, { oMaxCertDepth, "max-cert-depth", 1, "@" }, - { oTrustedKey, "trusted-key", 2, N_("|KEYID|ultimately trust this key")}, - { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")}, + { oTrustedKey, "trusted-key", 2, "@"}, + { oLoadExtension, "load-extension" ,2, "@"}, { oGnuPG, "gnupg", 0, "@"}, { oGnuPG, "no-pgp2", 0, "@"}, { oGnuPG, "no-pgp6", 0, "@"}, { oGnuPG, "no-pgp7", 0, "@"}, { oGnuPG, "no-pgp8", 0, "@"}, - { oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")}, - { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")}, - { oPGP2, "pgp2", 0, N_("set all packet, cipher and digest options to PGP 2.x behavior")}, + { oRFC1991, "rfc1991", 0, "@"}, + { oRFC2440, "rfc2440", 0, "@"}, + { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, + { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, { oPGP6, "pgp6", 0, "@"}, { oPGP7, "pgp7", 0, "@"}, { oPGP8, "pgp8", 0, "@"}, - { oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")}, - { oS2KDigest, "s2k-digest-algo",2, - N_("|NAME|use message digest algorithm NAME for passphrases")}, - { oS2KCipher, "s2k-cipher-algo",2, - N_("|NAME|use cipher algorithm NAME for passphrases")}, + { oS2KMode, "s2k-mode", 1, "@"}, + { oS2KDigest, "s2k-digest-algo",2, "@"}, + { oS2KCipher, "s2k-cipher-algo",2, "@"}, { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, - { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")}, - { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")}, + { oCipherAlgo, "cipher-algo", 2 , "@"}, + { oDigestAlgo, "digest-algo", 2 , "@"}, { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, - { oCompressAlgo,"compress-algo",2,N_("|NAME|use compression algorithm NAME")}, - { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")}, + { oCompressAlgo,"compress-algo",2, "@"}, + { oThrowKeyid, "throw-keyid", 0, "@"}, { oNoThrowKeyid, "no-throw-keyid", 0, "@" }, { oShowPhotos, "show-photos", 0, "@" }, { oNoShowPhotos, "no-show-photos", 0, "@" }, { oPhotoViewer, "photo-viewer", 2, "@" }, - { oNotation, "notation-data", 2, "@" }, + { oSetNotation, "set-notation", 2, "@" }, + { oSetNotation, "notation-data", 2, "@" }, /* Alias */ { oSigNotation, "sig-notation", 2, "@" }, { oCertNotation, "cert-notation", 2, "@" }, @@ -556,8 +554,10 @@ static ARGPARSE_OPTS opts[] = { { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, { oShowNotation, "show-notation", 0, "@" }, { oNoShowNotation, "no-show-notation", 0, "@" }, + { oSigKeyserverURL, "sig-keyserver-url", 2, "@" }, { oComment, "comment", 2, "@" }, { oDefaultComment, "default-comment", 0, "@" }, + { oNoComments, "no-comments", 0, "@" }, { oEmitVersion, "emit-version", 0, "@"}, { oNoEmitVersion, "no-emit-version", 0, "@"}, { oNoEmitVersion, "no-version", 0, "@"}, /* alias */ @@ -625,6 +625,7 @@ static ARGPARSE_OPTS opts[] = { { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" }, { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" }, { oEnableProgressFilter, "enable-progress-filter", 0, "@" }, + { oMultifile, "multifile", 0, "@" }, {0} }; @@ -641,6 +642,7 @@ static void set_cmd( enum cmd_and_opt_values *ret_cmd, static void print_mds( const char *fname, int algo ); static void add_notation_data( const char *string, int which ); static void add_policy_url( const char *string, int which ); +static void add_keyserver_url( const char *string, int which ); static void emergency_cleanup (void); #ifdef __riscos__ @@ -1158,6 +1160,7 @@ main( int argc, char **argv ) char *pers_digest_list = NULL; char *pers_compress_list = NULL; int eyes_only=0; + int multifile=0; int pwfd = -1; int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; @@ -1222,12 +1225,13 @@ main( int argc, char **argv ) opt.keyserver_options.include_subkeys=1; opt.keyserver_options.include_revoked=1; opt.keyserver_options.try_dns_srv=1; - opt.verify_options=VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION; + opt.verify_options= + VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION|VERIFY_SHOW_KEYSERVER; opt.trust_model=TM_AUTO; opt.mangle_dos_filenames = 1; opt.use_agent = 1; -#if defined (__MINGW32__) +#if defined (_WIN32) set_homedir ( read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" )); #else @@ -1389,11 +1393,15 @@ main( int argc, char **argv ) case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; case aSym: set_cmd( &cmd, aSym); break; + case aDecryptFiles: multifile=1; /* fall through */ case aDecrypt: set_cmd( &cmd, aDecrypt); break; - case aDecryptFiles: set_cmd( &cmd, aDecryptFiles); break; + case aEncrFiles: multifile=1; /* fall through */ case aEncr: set_cmd( &cmd, aEncr); break; - case aEncrFiles: set_cmd( &cmd, aEncrFiles ); break; + + case aVerifyFiles: multifile=1; /* fall through */ + case aVerify: set_cmd( &cmd, aVerify); break; + case aSign: set_cmd( &cmd, aSign ); break; case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; case aSignKey: set_cmd( &cmd, aSignKey); break; @@ -1405,8 +1413,7 @@ main( int argc, char **argv ) case aClearsign: set_cmd( &cmd, aClearsign); break; case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; - case aVerify: set_cmd( &cmd, aVerify); break; - case aVerifyFiles: set_cmd( &cmd, aVerifyFiles); break; + case aPrimegen: set_cmd( &cmd, aPrimegen); break; case aGenRandom: set_cmd( &cmd, aGenRandom); break; case aPrintMD: set_cmd( &cmd, aPrintMD); break; @@ -1564,7 +1571,7 @@ main( int argc, char **argv ) break; case oLoadExtension: #ifndef __riscos__ -#if defined(USE_DYNAMIC_LINKING) || defined(__MINGW32__) +#if defined(USE_DYNAMIC_LINKING) || defined(_WIN32) if(check_permissions(pargs.r.ret_str,2)) log_info(_("cipher extension \"%s\" not loaded due to " "unsafe permissions\n"),pargs.r.ret_str); @@ -1579,14 +1586,13 @@ main( int argc, char **argv ) case oRFC1991: opt.compliance = CO_RFC1991; opt.force_v4_certs = 0; - opt.disable_mdc = 1; opt.escape_from = 1; break; + case oRFC2440: case oOpenPGP: /* TODO: When 2440bis becomes a RFC, these may need changing. */ opt.compliance = CO_RFC2440; - opt.disable_mdc = 1; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; @@ -1627,9 +1633,19 @@ main( int argc, char **argv ) opt.list_options&=~LIST_SHOW_POLICY; opt.verify_options&=~VERIFY_SHOW_POLICY; break; + case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; - case oComment: opt.comment_string = pargs.r.ret_str; break; - case oDefaultComment: opt.comment_string = NULL; break; + + case oComment: add_to_strlist(&opt.comments,pargs.r.ret_str); break; + case oDefaultComment: + deprecated_warning(configname,configlineno, + "--default-comment","--no-comments",""); + /* fall through */ + case oNoComments: + free_strlist(opt.comments); + opt.comments=NULL; + break; + case oThrowKeyid: opt.throw_keyid = 1; break; case oNoThrowKeyid: opt.throw_keyid = 0; break; case oShowPhotos: @@ -1686,6 +1702,7 @@ main( int argc, char **argv ) case oCompress: opt.compress = pargs.r.ret_int; break; case oPasswdFD: pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); + opt.use_agent = 0; break; #ifdef __riscos__ case oPasswdFile: @@ -1784,9 +1801,11 @@ main( int argc, char **argv ) {"show-photos",LIST_SHOW_PHOTOS}, {"show-policy-url",LIST_SHOW_POLICY}, {"show-notation",LIST_SHOW_NOTATION}, - {"show-keyring",LIST_SHOW_KEYRING}, + {"show-keyserver-url",LIST_SHOW_KEYSERVER}, {"show-validity",LIST_SHOW_VALIDITY}, {"show-long-keyid",LIST_SHOW_LONG_KEYID}, + {"show-keyring",LIST_SHOW_KEYRING}, + {"show-sig-expire",LIST_SHOW_SIG_EXPIRE}, {NULL,0} }; @@ -1807,6 +1826,9 @@ main( int argc, char **argv ) {"show-photos",VERIFY_SHOW_PHOTOS}, {"show-policy-url",VERIFY_SHOW_POLICY}, {"show-notation",VERIFY_SHOW_NOTATION}, + {"show-keyserver-url",VERIFY_SHOW_KEYSERVER}, + {"show-validity",VERIFY_SHOW_VALIDITY}, + {"show-long-keyid",VERIFY_SHOW_LONG_KEYID}, {NULL,0} }; @@ -1827,7 +1849,7 @@ main( int argc, char **argv ) else opt.exec_path_set=1; break; - case oNotation: + case oSetNotation: add_notation_data( pargs.r.ret_str, 0 ); add_notation_data( pargs.r.ret_str, 1 ); break; @@ -1931,6 +1953,7 @@ main( int argc, char **argv ) case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; case oEnableProgressFilter: opt.enable_progress_filter = 1; break; + case oMultifile: multifile=1; break; default : pargs.err = configfp? 1:2; break; } @@ -2053,8 +2076,6 @@ main( int argc, char **argv ) compliance_failure(); else { - opt.force_mdc = 0; - opt.disable_mdc = 1; opt.force_v4_certs = 0; opt.sk_comments = 0; opt.escape_from = 1; @@ -2073,8 +2094,6 @@ main( int argc, char **argv ) opt.escape_from=1; opt.force_v3_sigs=1; opt.ask_sig_expire=0; - opt.force_mdc=0; - opt.disable_mdc=1; } else if(PGP7) { @@ -2170,6 +2189,37 @@ main( int argc, char **argv ) keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) log_error(_("invalid personal compress preferences\n")); + /* We don't support all possible commands with multifile yet */ + if(multifile) + { + char *cmdname; + + switch(cmd) + { + case aSign: + cmdname="--sign"; + break; + case aClearsign: + cmdname="--clearsign"; + break; + case aDetachedSign: + cmdname="--detach-sign"; + break; + case aSym: + cmdname="--symmetric"; + break; + case aStore: + cmdname="--store"; + break; + default: + cmdname=NULL; + break; + } + + if(cmdname) + log_error(_("%s does not yet work with %s\n"),cmdname,"--multifile"); + } + if( log_get_errorcount(0) ) g10_exit(2); @@ -2262,8 +2312,7 @@ main( int argc, char **argv ) if( cmd != aDeArmor && cmd != aEnArmor ) { if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys - && cmd != aVerify && cmd != aVerifyFiles - && cmd != aSym) + && cmd != aVerify && cmd != aSym) { if (!sec_nrings || default_keyring) /* add default secret rings */ keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); @@ -2335,17 +2384,18 @@ main( int argc, char **argv ) break; case aEncr: /* encrypt the given file */ - if( argc > 1 ) - wrong_args(_("--encrypt [filename]")); - if( (rc = encode_crypt(fname,remusr)) ) - log_error("%s: encryption failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); + if(multifile) + encode_crypt_files(argc, argv, remusr); + else + { + if( argc > 1 ) + wrong_args(_("--encrypt [filename]")); + if( (rc = encode_crypt(fname,remusr)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + } break; - case aEncrFiles: /* encrypt the given files */ - encode_crypt_files(argc, argv, remusr); - break; - case aSign: /* sign the given file */ sl = NULL; if( detached_sig ) { /* sign all files */ @@ -2397,26 +2447,30 @@ main( int argc, char **argv ) break; case aVerify: - if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); - break; - - case aVerifyFiles: - if( (rc = verify_files( argc, argv ) )) - log_error("verify files failed: %s\n", gpg_strerror (rc) ); + if(multifile) + { + if( (rc = verify_files( argc, argv ) )) + log_error("verify files failed: %s\n", gpg_strerror (rc) ); + } + else + { + if( (rc = verify_signatures( argc, argv ) )) + log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); + } break; case aDecrypt: - if( argc > 1 ) - wrong_args(_("--decrypt [filename]")); - if( (rc = decrypt_message( fname ) )) - log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); + if(multifile) + decrypt_messages(argc, argv); + else + { + if( argc > 1 ) + wrong_args(_("--decrypt [filename]")); + if( (rc = decrypt_message( fname ) )) + log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); + } break; - case aDecryptFiles: - decrypt_messages(argc, argv); - break; - case aSignKey: /* sign the key given as argument */ if( argc != 1 ) wrong_args(_("--sign-key user-id")); @@ -2900,8 +2954,6 @@ print_hex( MD_HANDLE md, int algo, const char *fname ) if(algo==DIGEST_ALGO_RMD160) indent+=printf("RMD160 = "); - else if(algo==DIGEST_ALGO_TIGER) - indent+=printf(" TIGER = "); else if(algo>0) indent+=printf("%6s = ", gcry_md_algo_name (algo)); else @@ -3018,9 +3070,6 @@ print_mds( const char *fname, int algo ) gcry_md_enable (md, GCRY_MD_MD5 ); gcry_md_enable (md, GCRY_MD_SHA1 ); gcry_md_enable (md, GCRY_MD_RMD160 ); -#ifdef USE_TIGER192 - gcry_md_enable (md, GCRY_MD_TIGER ); -#endif #ifdef USE_SHA256 gcry_md_enable (md, GCRY_MD_SHA256 ); #endif @@ -3043,9 +3092,6 @@ print_mds( const char *fname, int algo ) print_hashline( md, GCRY_MD_MD5, fname ); print_hashline( md, GCRY_MD_SHA1, fname ); print_hashline( md, GCRY_MD_RMD160, fname ); -#ifdef USE_TIGER192 - print_hashline( md, GCRY_MD_TIGER, fname ); -#endif #ifdef USE_SHA256 print_hashline( md, GCRY_MD_SHA256, fname ); #endif @@ -3062,9 +3108,6 @@ print_mds( const char *fname, int algo ) print_hex( md, GCRY_MD_MD5, fname ); print_hex( md, GCRY_MD_SHA1, fname ); print_hex( md, GCRY_MD_RMD160, fname ); -#ifdef USE_TIGER192 - print_hex( md, GCRY_MD_TIGER, fname ); -#endif #ifdef USE_SHA256 print_hex( md, GCRY_MD_SHA256, fname ); #endif @@ -3132,13 +3175,13 @@ add_notation_data( const char *string, int which ) /* we only support printable text - therefore we enforce the use * of only printable characters (an empty value is valid) */ for( s++; *s ; s++ ) { - if( iscntrl(*s) ) { + if( *s & 0x80 ) + highbit = 1; + else if( iscntrl(*s) ) { log_error(_("a notation value must not use " "any control characters\n") ); return; } - else if( *s & 0x80 ) - highbit = 1; } if( highbit ) /* must use UTF8 encoding */ @@ -3183,3 +3226,39 @@ add_policy_url( const char *string, int which ) if(critical) sl->flags |= 1; } + + +static void +add_keyserver_url( const char *string, int which ) +{ + int i,critical=0; + STRLIST sl; + + if(*string=='!') + { + string++; + critical=1; + } + + for(i=0;i<strlen(string);i++) + if(string[i]&0x80 || iscntrl(string[i])) + break; + + if(i==0 || i<strlen(string)) + { + if(which) + BUG(); + else + log_error(_("the given signature preferred" + " keyserver URL is invalid\n")); + } + + if(which) + BUG(); + else + sl=add_to_strlist( &opt.sig_keyserver_url, string ); + + if(critical) + sl->flags |= 1; +} + diff --git a/g10/getkey.c b/g10/getkey.c index 7eda9384c..f51b8f2df 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -572,7 +572,7 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) memset (desc, 0, sizeof *desc); /* skip leading spaces. Fixme: what is with trailing spaces? */ - for(s = name; *s && isspace(*s); s++ ) + for(s = name; *s && spacep (s); s++ ) ; switch (*s) { @@ -653,7 +653,7 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) } /* check if a hexadecimal number is terminated by EOS or blank */ - if (hexlength && s[hexlength] && !isspace(s[hexlength])) { + if (hexlength && s[hexlength] && !spacep (s+hexlength)) { if (hexprefix) /* a "0x" prefix without correct */ return 0; /* termination is an error */ else /* The first chars looked like */ @@ -1593,8 +1593,6 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) else if ( k->pkt->pkttype == PKT_SIGNATURE && uidnode ) { PKT_signature *sig = k->pkt->pkt.signature; - u32 dummy; - int dum2; if(sig->keyid[0] != kid[0] || sig->keyid[1]!=kid[1]) { @@ -1610,7 +1608,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) ultimate trust flag. */ if(get_pubkey_fast(ultimate_pk,sig->keyid)==0 && check_key_signature2(keyblock,k,ultimate_pk, - NULL,&dummy,&dum2)==0 + NULL, NULL, NULL, NULL)==0 && get_ownertrust(ultimate_pk)==TRUST_ULTIMATE) { free_public_key(ultimate_pk); diff --git a/g10/gpgv.c b/g10/gpgv.c index fb96fad5c..596b09fcb 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -1,5 +1,6 @@ /* gpgv.c - The GnuPG signature verify utility - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -155,8 +156,9 @@ main( int argc, char **argv ) opt.trust_model = TM_ALWAYS; opt.batch = 1; -#if defined (__MINGW32__) - opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); +#if defined (_WIN32) + opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", + "HomeDir" ); #else opt.homedir = getenv("GNUPGHOME"); #endif @@ -221,6 +223,14 @@ g10_exit( int 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 diff --git a/g10/import.c b/g10/import.c index 84d60a1b3..9c323243a 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1,5 +1,6 @@ -/* import.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* import.c - Import OpenPGP key material + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -168,6 +169,8 @@ import_keys_internal( iobuf_t inp, char **fnames, int nnames, else { rc = import( inp2, fname, stats, options ); iobuf_close(inp2); + /* Must invalidate that ugly cache to actually close it. */ + iobuf_ioctl (NULL, 2, 0, (char*)fname); if( rc ) log_error("import from `%s' failed: %s\n", fname, gpg_strerror (rc) ); @@ -589,7 +592,8 @@ import_one( const char *fname, KBNODE keyblock, clear_kbnode_flags( keyblock ); - if((options&IMPORT_REPAIR_PKS_SUBKEY_BUG) && fix_pks_corruption(keyblock)) + if((options&IMPORT_REPAIR_PKS_SUBKEY_BUG) && fix_pks_corruption(keyblock) + && opt.verbose) log_info(_("key %08lX: PKS subkey corruption repaired\n"), (ulong)keyid[1]); @@ -611,11 +615,9 @@ import_one( const char *fname, KBNODE keyblock, } if( !delete_inv_parts( fname, keyblock, keyid, options ) ) { - if( !opt.quiet ) { - log_info( _("key %08lX: no valid user IDs\n"), - (ulong)keyid[1]); + log_error ( _("key %08lX: no valid user IDs\n"), (ulong)keyid[1]); + if( !opt.quiet ) log_info(_("this may be caused by a missing self-signature\n")); - } stats->no_user_id++; return 0; } @@ -979,8 +981,8 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) pk = xcalloc (1, sizeof *pk ); rc = get_pubkey( pk, keyid ); if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY ) { - log_info( _("key %08lX: no public key - " - "can't apply revocation certificate\n"), (ulong)keyid[1]); + log_error ( _("key %08lX: no public key - " + "can't apply revocation certificate\n"), (ulong)keyid[1]); rc = 0; goto leave; } @@ -1030,12 +1032,12 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) if( onode->pkt->pkttype == PKT_USER_ID ) break; else if( onode->pkt->pkttype == PKT_SIGNATURE - && onode->pkt->pkt.signature->sig_class == 0x20 - && keyid[0] == onode->pkt->pkt.signature->keyid[0] - && keyid[1] == onode->pkt->pkt.signature->keyid[1] ) { - rc = 0; - goto leave; /* yes, we already know about it */ - } + && !cmp_signatures(node->pkt->pkt.signature, + onode->pkt->pkt.signature)) + { + rc = 0; + goto leave; /* yes, we already know about it */ + } } @@ -1125,17 +1127,20 @@ chk_self_sigs( const char *fname, KBNODE keyblock, rc = check_key_signature( keyblock, n, NULL); if( rc ) { - char *p=utf8_to_native(unode->pkt->pkt.user_id->name, - strlen(unode->pkt->pkt.user_id->name),0); - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key " - "algorithm on user id \"%s\"\n"): - _("key %08lX: invalid self-signature " - "on user id \"%s\"\n"), - (ulong)keyid[1],p); - xfree (p); - } - else + if (opt.verbose) + { + char *p=utf8_to_native(unode->pkt->pkt.user_id->name, + strlen(unode->pkt->pkt.user_id->name),0); + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key " + "algorithm on user id \"%s\"\n"): + _("key %08lX: invalid self-signature " + "on user id \"%s\"\n"), + (ulong)keyid[1],p); + xfree (p); + } + } + else unode->flag |= 1; /* mark that signature checked */ } } @@ -1144,39 +1149,49 @@ chk_self_sigs( const char *fname, KBNODE keyblock, like the rest of gpg. If the standard gets revocation targets, this may need to be revised. */ - if( !knode ) { - log_info( _("key %08lX: no subkey for subkey " - "binding signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ - } - else { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) { - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key algorithm\n"): + if( !knode ) + { + if (opt.verbose) + log_info( _("key %08lX: no subkey for subkey " + "binding signature\n"),(ulong)keyid[1]); + n->flag |= 4; /* delete this */ + } + else + { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) + { + if (opt.verbose) + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? + _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey binding\n"), - (ulong)keyid[1]); - n->flag|=4; - } - else { - /* It's valid, so is it newer? */ - if(sig->timestamp>=bsdate) { - knode->flag |= 1; /* the subkey is valid */ - if(bsnode) { - bsnode->flag|=4; /* Delete the last binding - sig since this one is - newer */ - log_info(_("key %08lX: removed multiple subkey " - "binding\n"),(ulong)keyid[1]); - } - - bsnode=n; - bsdate=sig->timestamp; - } - else - n->flag|=4; /* older */ - } - } + (ulong)keyid[1]); + n->flag|=4; + } + else + { + /* It's valid, so is it newer? */ + if(sig->timestamp>=bsdate) + { + knode->flag |= 1; /* the subkey is valid */ + if(bsnode) + { + bsnode->flag|=4; /* Delete the last binding + sig since this one is + newer */ + if (opt.verbose) + log_info(_("key %08lX: removed multiple " + "subkey binding\n"), + (ulong)keyid[1]); + } + + bsnode=n; + bsdate=sig->timestamp; + } + else + n->flag|=4; /* older */ + } + } } else if( sig->sig_class == 0x28 ) { /* We don't actually mark the subkey as revoked right @@ -1186,14 +1201,16 @@ chk_self_sigs( const char *fname, KBNODE keyblock, See the comment in getkey.c:merge_selfsigs_subkey for more */ if( !knode ) { + if (opt.verbose) log_info( _("key %08lX: no subkey for subkey " "revocation signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ + n->flag |= 4; /* delete this */ } else { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? + if (opt.verbose) + log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? _("key %08lX: unsupported public key algorithm\n"): _("key %08lX: invalid subkey revocation\n"), (ulong)keyid[1]); @@ -1206,8 +1223,10 @@ chk_self_sigs( const char *fname, KBNODE keyblock, rsnode->flag|=4; /* Delete the last revocation sig since this one is newer */ - log_info(_("key %08lX: removed multiple subkey " - "revocation signatures\n"),(ulong)keyid[1]); + if (opt.verbose) + log_info(_("key %08lX: removed multiple subkey " + "revocation signatures\n"), + (ulong)keyid[1]); } rsnode=n; @@ -1291,23 +1310,25 @@ delete_inv_parts( const char *fname, KBNODE keyblock, !node->pkt->pkt.signature->flags.exportable && !(options&IMPORT_ALLOW_LOCAL_SIGS) && seckey_available( node->pkt->pkt.signature->keyid ) ) { - /* here we violate the rfc a bit by still allowing + /* Here we violate the rfc a bit by still allowing * to import non-exportable signature when we have the * the secret key used to create this signature - it - * seems that this makes sense */ + * seems that this makes sense. */ + if (opt.verbose) log_info( _("key %08lX: non exportable signature " "(class %02x) - skipped\n"), - (ulong)keyid[1], + (ulong)keyid[1], node->pkt->pkt.signature->sig_class ); - delete_kbnode( node ); + delete_kbnode( node ); } else if( node->pkt->pkttype == PKT_SIGNATURE && node->pkt->pkt.signature->sig_class == 0x20 ) { if( uid_seen ) { + if (opt.verbose) log_error( _("key %08lX: revocation certificate " - "at wrong place - skipped\n"), + "at wrong place - skipped\n"), (ulong)keyid[1]); - delete_kbnode( node ); + delete_kbnode( node ); } else { /* If the revocation cert is from a different key than @@ -1321,9 +1342,10 @@ delete_inv_parts( const char *fname, KBNODE keyblock, int rc = check_key_signature( keyblock, node, NULL); if( rc ) { - log_error( _("key %08lX: invalid revocation " - "certificate: %s - skipped\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if (opt.verbose) + log_info ( _("key %08lX: invalid revocation " + "certificate: %s - skipped\n"), + (ulong)keyid[1], gpg_strerror (rc)); delete_kbnode( node ); } } @@ -1333,17 +1355,19 @@ delete_inv_parts( const char *fname, KBNODE keyblock, (node->pkt->pkt.signature->sig_class == 0x18 || node->pkt->pkt.signature->sig_class == 0x28) && !subkey_seen ) { - log_error( _("key %08lX: subkey signature " + if (opt.verbose) + log_info ( _("key %08lX: subkey signature " "in wrong place - skipped\n"), (ulong)keyid[1]); - delete_kbnode( node ); + delete_kbnode( node ); } else if( node->pkt->pkttype == PKT_SIGNATURE && !IS_CERT(node->pkt->pkt.signature)) { - log_error(_("key %08lX: unexpected signature class (0x%02X) -" - " skipped\n"),(ulong)keyid[1], - node->pkt->pkt.signature->sig_class); + if (opt.verbose) + log_info (_("key %08lX: unexpected signature class (0x%02X) -" + " skipped\n"),(ulong)keyid[1], + node->pkt->pkt.signature->sig_class); delete_kbnode(node); } else if( (node->flag & 4) ) /* marked for deletion */ @@ -1439,8 +1463,9 @@ collapse_uids( KBNODE *keyblock ) kid1 = keyid_from_sk( n->pkt->pkt.secret_key, NULL ); else kid1 = 0; - log_info(_("key %08lX: duplicated user ID detected - merged\n"), - (ulong)kid1); + if (!opt.quiet) + log_info (_("key %08lX: duplicated user ID detected - merged\n"), + (ulong)kid1); return 1; } @@ -1557,23 +1582,27 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, break; else if( onode->pkt->pkttype == PKT_SIGNATURE && onode->pkt->pkt.signature->sig_class == 0x20 - && node->pkt->pkt.signature->keyid[0] - == onode->pkt->pkt.signature->keyid[0] - && node->pkt->pkt.signature->keyid[1] - == onode->pkt->pkt.signature->keyid[1] ) { - found = 1; - break; - } + && !cmp_signatures(onode->pkt->pkt.signature, + node->pkt->pkt.signature)) + { + found = 1; + break; + } } if( !found ) { - char *p=get_user_id_printable (keyid); KBNODE n2 = clone_kbnode(node); insert_kbnode( keyblock_orig, n2, 0 ); n2->flag |= 1; ++*n_sigs; - log_info(_("key %08lX: \"%s\" revocation certificate added\n"), - (ulong)keyid[1],p); - xfree (p); + + if (!opt.quiet) + { + char *p=get_user_id_printable (keyid); + log_info(_("key %08lX: \"%s\" " + "revocation certificate added\n"), + (ulong)keyid[1],p); + xfree (p); + } } } } @@ -1602,8 +1631,9 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, insert_kbnode( keyblock_orig, n2, 0 ); n2->flag |= 1; ++*n_sigs; - log_info( _("key %08lX: direct key signature added\n"), - (ulong)keyid[1]); + if (!opt.quiet) + log_info( _("key %08lX: direct key signature added\n"), + (ulong)keyid[1]); } } } @@ -1771,20 +1801,12 @@ merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, || n->pkt->pkt.signature->sig_class == 0x28 ) continue; /* skip signatures which are only valid on subkeys */ found = 0; - for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next){ - if( n2->pkt->pkttype == PKT_SIGNATURE - && n->pkt->pkt.signature->keyid[0] - == n2->pkt->pkt.signature->keyid[0] - && n->pkt->pkt.signature->keyid[1] - == n2->pkt->pkt.signature->keyid[1] - && n->pkt->pkt.signature->timestamp - <= n2->pkt->pkt.signature->timestamp - && n->pkt->pkt.signature->sig_class - == n2->pkt->pkt.signature->sig_class ) { - found++; - break; - } - } + for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next) + if(!cmp_signatures(n->pkt->pkt.signature,n2->pkt->pkt.signature)) + { + found++; + break; + } if( !found ) { /* This signature is new or newer, append N to DST. * We add a clone to the original keyblock, because this diff --git a/g10/keyedit.c b/g10/keyedit.c index 85f2b92e9..bd41772fd 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -56,6 +56,7 @@ static int menu_addrevoker( KBNODE pub_keyblock, static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_select_uid( KBNODE keyblock, int idx ); static int menu_select_key( KBNODE keyblock, int idx ); static int count_uids( KBNODE keyblock ); @@ -135,7 +136,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, break; } if( sigrc != '?' || print_without_key ) { - tty_printf("%s%c%c %c%c%c%c%c%c %08lX %s ", + tty_printf("%s%c%c %c%c%c%c%c%c ", is_rev? "rev":"sig",sigrc, (sig->sig_class-0x10>0 && sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', @@ -145,8 +146,15 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, sig->flags.notation?'N':' ', sig->flags.expired?'X':' ', (sig->trust_depth>9)?'T': - (sig->trust_depth>0)?'0'+sig->trust_depth:' ', - (ulong)sig->keyid[1], datestr_from_sig(sig)); + (sig->trust_depth>0)?'0'+sig->trust_depth:' '); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + tty_printf("%08lX%08lX",(ulong)sig->keyid[0],(ulong)sig->keyid[1]); + else + tty_printf("%08lX",(ulong)sig->keyid[1]); + tty_printf(" %s", datestr_from_sig(sig)); + if(opt.list_options&LIST_SHOW_SIG_EXPIRE) + tty_printf(" %s",expirestr_from_sig(sig)); + tty_printf(" "); if( sigrc == '%' ) tty_printf("[%s] ", gpg_strerror (rc) ); else if( sigrc == '?' ) @@ -168,6 +176,9 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) show_notation(sig,3,0); + + if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + show_keyserver_url(sig,3,0); } return (sigrc == '!'); @@ -500,12 +511,47 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, tty_printf(_(" Unable to sign.\n")); } } - else if(!uidnode->pkt->pkt.user_id->created) + else if(uidnode->pkt->pkt.user_id->is_expired) { - tty_printf(_("WARNING: user ID \"%s\" is not " - "self-signed.\n"),user); + tty_printf(_("User ID \"%s\" is expired."),user); + + if(opt.expert) + { + tty_printf("\n"); + /* No, so remove the mark and continue */ + if(!cpr_get_answer_is_yes("sign_uid.expire_okay", + _("Are you sure you " + "still want to sign " + "it? (y/N) "))) + uidnode->flag &= ~NODFLG_MARK_A; + } + else + { + uidnode->flag &= ~NODFLG_MARK_A; + tty_printf(_(" Unable to sign.\n")); + } } + else if(!uidnode->pkt->pkt.user_id->created && !selfsig) + { + tty_printf(_("User ID \"%s\" is not self-signed."), + user); + if(opt.expert) + { + tty_printf("\n"); + /* No, so remove the mark and continue */ + if(!cpr_get_answer_is_yes("sign_uid.nosig_okay", + _("Are you sure you " + "still want to sign " + "it? (y/N) "))) + uidnode->flag &= ~NODFLG_MARK_A; + } + else + { + uidnode->flag &= ~NODFLG_MARK_A; + tty_printf(_(" Unable to sign.\n")); + } + } xfree (user); } } @@ -739,7 +785,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, while(class==0) { - answer = cpr_get("sign_uid.class",_("Your selection? ")); + answer = cpr_get("sign_uid.class",_("Your selection? " + "(enter '?' for more information): ")); if(answer[0]=='\0') class=0x10+opt.def_cert_check_level; /* Default */ @@ -970,8 +1017,10 @@ change_passphrase( KBNODE keyblock ) " this is probably a *bad* idea!\n\n")); if( cpr_get_answer_is_yes("change_passwd.empty.okay", _("Do you really want to do this? "))) + { changed++; - break; + break; + } } else { /* okay */ rc = 0; @@ -1067,7 +1116,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, - cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP }; + cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, + cmdNOP }; static struct { const char *name; enum cmdids id; int need_sk; @@ -1108,10 +1158,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret " "and public key listing") }, { N_("t" ) , cmdTOGGLE , 1,0,0, NULL }, - { N_("pref") , cmdPREF , 0,1,0, N_("list preferences (expert)") }, - { N_("showpref"), cmdSHOWPREF , 0,1,0, N_("list preferences (verbose)") }, + { N_("pref") , cmdPREF , 0,1,0, + N_("list preferences (expert)")}, + { N_("showpref"), cmdSHOWPREF , 0,1,0, + N_("list preferences (verbose)")}, { N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") }, { N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") }, + { N_("keyserver"),cmdPREFKS , 1,1,0, + N_("set preferred keyserver URL")}, { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") }, { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") }, { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") }, @@ -1238,7 +1292,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, cmd = cmdLIST; else if( *answer == CONTROL_D ) cmd = cmdQUIT; - else if( isdigit( *answer ) ) { + else if( digitp( answer ) ) { cmd = cmdSELUID; arg_number = atoi(answer); } @@ -1565,6 +1619,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } break; + case cmdPREFKS: + if( menu_set_keyserver_url ( keyblock, sec_keyblock ) ) { + merge_keys_and_selfsig( keyblock ); + modified = 1; + redisplay = 1; + } + break; + case cmdNOP: break; @@ -1950,6 +2012,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, int i, rc; int do_warn = 0; byte pk_version=0; + PKT_public_key *primary=NULL; if (opt.with_colons) { @@ -1979,7 +2042,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, do_warn = 1; } - pk_version=pk->version; + pk_version = pk->version; + primary = pk; } if(with_revoker) { @@ -2006,19 +2070,27 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, } } - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", - (node->flag & NODFLG_SELKEY)? '*':' ', - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk), - expirestr_from_pk(pk) ); + keyid_from_pk(pk,NULL); + tty_printf("%s%c %4u%c/", + node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", + (node->flag & NODFLG_SELKEY)? '*':' ', + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo )); + + if(opt.list_options&LIST_SHOW_LONG_KEYID) + tty_printf("%08lX",(ulong)pk->keyid[0]); + + tty_printf("%08lX ",(ulong)pk->keyid[1]); + tty_printf(_("created: %s expires: %s"), + datestr_from_pk(pk), + expirestr_from_pk(pk) ); tty_printf("\n"); if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { tty_printf(" "); + if(opt.list_options&LIST_SHOW_LONG_KEYID) + tty_printf(" "); tty_printf(_("trust: %-13s"), otrust); tty_printf(_("validity: %s"), trust ); tty_printf("\n"); @@ -2072,6 +2144,9 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, PKT_user_id *uid = node->pkt->pkt.user_id; ++i; if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){ + if(opt.list_options&LIST_SHOW_VALIDITY && primary) + tty_printf("[%8.8s] ", + trust_value_to_string(get_validity(primary,uid))); if( only_marked ) tty_printf(" "); else if( node->flag & NODFLG_SELUID ) @@ -2599,16 +2674,23 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) answer=cpr_get_utf8("keyedit.add_revoker", _("Enter the user ID of the designated revoker: ")); if(answer[0]=='\0' || answer[0]=='\004') - goto fail; - + { + xfree(answer); answer = NULL; + goto fail; + } + rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); if(rc) { log_error (_("key `%s' not found: %s\n"),answer,gpg_strerror (rc)); + xfree (answer); answer = NULL; continue; } + xfree (answer); answer = NULL; + + fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen); if(fprlen!=20) { @@ -2788,7 +2870,8 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) && ( mainkey || sub_pk ) ) { PKT_signature *sig = node->pkt->pkt.signature; if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && ( (mainkey && uid && (sig->sig_class&~3) == 0x10) + && ( (mainkey && uid + && uid->created && (sig->sig_class&~3) == 0x10) || (!mainkey && sig->sig_class == 0x18) ) ) { /* this is a selfsignature which is to be replaced */ PKT_signature *newsig; @@ -3084,6 +3167,101 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) } + +static int +menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected, select_all; + int modified = 0; + char *answer; + + no_primary_warning(pub_keyblock,1); + + answer=cpr_get_utf8("keyedit.add_keyserver", + _("Enter your preferred keyserver URL: ")); + if(answer[0]=='\0' || answer[0]=='\004') + { + xfree(answer); + return 0; + } + + select_all = !count_selected_uids (pub_keyblock); + + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + for ( node=pub_keyblock; node; node = node->next ) { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + } + else if ( node->pkt->pkttype == PKT_USER_ID ) { + uid = node->pkt->pkt.user_id; + selected = select_all || (node->flag & NODFLG_SELUID); + } + else if ( main_pk && uid && selected + && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) ) { + if( sig->version < 4 ) { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + + log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + user); + xfree(user); + } + else { + /* This is a selfsignature which is to be replaced + * We have to ignore v3 signatures because they are + * not able to carry the preferences */ + PKT_signature *newsig; + PACKET *newpkt; + int rc; + + rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + keygen_add_keyserver_url, + answer ); + if( rc ) { + log_error ("update_keysig_packet failed: %s\n", + gpg_strerror (rc)); + xfree(answer); + free_secret_key( sk ); + return 0; + } + /* replace the packet */ + newpkt = xcalloc (1, sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + xfree (node->pkt); + node->pkt = newpkt; + modified = 1; + } + } + } + } + + xfree(answer); + free_secret_key( sk ); + return modified; +} + + /**************** * Select one user id or remove all selection if index is 0. * Returns: True if the selection changed; diff --git a/g10/keygen.c b/g10/keygen.c index bc98cee17..38e9115b3 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -147,7 +147,12 @@ do_add_key_flags (PKT_signature *sig, unsigned int use) buf[0] = 0; if (use & PUBKEY_USAGE_SIG) - buf[0] |= 0x01 | 0x02; + { + if(sig->sig_class==0x18) + buf[0] |= 0x02; /* Don't set the certify flag for subkeys */ + else + buf[0] |= 0x01 | 0x02; + } if (use & PUBKEY_USAGE_ENC) buf[0] |= 0x04 | 0x08; if (use & PUBKEY_USAGE_AUTH) @@ -587,6 +592,18 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque ) return 0; } + +int +keygen_add_keyserver_url(PKT_signature *sig, void *opaque) +{ + const char *url=opaque; + + build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url)); + + return 0; +} + + int keygen_add_revkey(PKT_signature *sig, void *opaque) { @@ -1138,10 +1155,10 @@ gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, static int check_valid_days( const char *s ) { - if( !isdigit(*s) ) + if( !digitp(s) ) return 0; for( s++; *s; s++) - if( !isdigit(*s) ) + if( !digitp(s) ) break; if( !*s ) return 1; @@ -1219,15 +1236,18 @@ ask_algo (int addmode, unsigned int *r_usage) _("Create anyway? "))) { algo = PUBKEY_ALGO_ELGAMAL; + *r_usage = PUBKEY_USAGE_ENC | PUBKEY_USAGE_SIG; break; } } else if( algo == 3 && addmode ) { algo = PUBKEY_ALGO_ELGAMAL_E; + *r_usage = PUBKEY_USAGE_ENC; break; } else if( algo == 2 ) { algo = PUBKEY_ALGO_DSA; + *r_usage = PUBKEY_USAGE_SIG; break; } else @@ -1489,7 +1509,7 @@ ask_user_id( int mode ) if( strpbrk( aname, "<>" ) ) tty_printf(_("Invalid character in name\n")); - else if( isdigit(*aname) ) + else if( digitp(aname) ) tty_printf(_("Name may not start with a digit\n")); else if( strlen(aname) < 5 ) tty_printf(_("Name must be at least 5 characters long\n")); @@ -1503,7 +1523,7 @@ ask_user_id( int mode ) amail = cpr_get("keygen.email",_("Email address: ")); trim_spaces(amail); cpr_kill_prompt(); - if( !*amail ) + if( !*amail || opt.allow_freeform_uid ) break; /* no email address is okay */ else if( has_invalid_email_chars(amail) || count_chr(amail,'@') != 1 @@ -1551,7 +1571,8 @@ ask_user_id( int mode ) tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid); /* fixme: add a warning if this user-id already exists */ - if( !*amail && (strchr( aname, '@' ) || strchr( acomment, '@'))) { + if( !*amail && !opt.allow_freeform_uid + && (strchr( aname, '@' ) || strchr( acomment, '@'))) { fail = 1; tty_printf(_("Please don't put the email address " "into the real name or the comment\n") ); @@ -1608,7 +1629,7 @@ ask_user_id( int mode ) } xfree (answer); if( !amail && !acomment && !amail ) - break; + break; xfree (uid); uid = NULL; } if( uid ) { @@ -1754,7 +1775,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key ) struct para_data_s *r = get_parameter( para, key ); if( !r ) return -1; - if( isdigit( *r->u.value ) ) + if( digitp( r->u.value ) ) i = atoi( r->u.value ); else i = openpgp_pk_map_name ( r->u.value ); @@ -2295,6 +2316,11 @@ generate_keypair( const char *fname ) strcpy( r->u.value, "1024" ); r->next = para; para = r; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pKEYUSAGE; + strcpy( r->u.value, "sign" ); + r->next = para; + para = r; algo = PUBKEY_ALGO_ELGAMAL_E; r = xcalloc (1, sizeof *r + 20 ); @@ -2302,6 +2328,12 @@ generate_keypair( const char *fname ) sprintf( r->u.value, "%d", algo ); r->next = para; para = r; + r = xcalloc (1, sizeof *r + 20 ); + r->key = pSUBKEYUSAGE; + strcpy( r->u.value, "encrypt" ); + r->next = para; + r->next = para; + para = r; } else { diff --git a/g10/keylist.c b/g10/keylist.c index 081782785..f4344f204 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1,6 +1,6 @@ -/* keylist.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. +/* keylist.c - List all or selected keys + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -58,10 +58,46 @@ static FILE *attrib_fp=NULL; void public_key_list( STRLIST list ) { - if( !list ) - list_all(0); - else - list_one( list, 0 ); + if(opt.with_colons) + { + byte trust_model,marginals,completes,cert_depth; + ulong created,nextcheck; + + read_trust_options(&trust_model,&created,&nextcheck, + &marginals,&completes,&cert_depth); + + printf("tru:"); + + if(nextcheck && nextcheck <= make_timestamp()) + printf("o"); + if(trust_model!=opt.trust_model) + printf("t"); + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + { + if(marginals!=opt.marginals_needed) + printf("m"); + if(completes!=opt.completes_needed) + printf("c"); + if(cert_depth!=opt.max_cert_depth) + printf("d"); + } + + printf(":%d:%lu:%lu",trust_model,created,nextcheck); + + /* Only show marginals, completes, and cert_depth in the classic + or PGP trust models since they are not meaningful + otherwise. */ + + if(trust_model==TM_PGP || trust_model==TM_CLASSIC) + printf(":%d:%d:%d",marginals,completes,cert_depth); + + printf("\n"); + } + + if( !list ) + list_all(0); + else + list_one( list, 0 ); } void @@ -152,7 +188,6 @@ show_policy_url(PKT_signature *sig,int indent,int mode) for(i=0;i<indent;i++) putchar(' '); - /* This isn't UTF8 as it is a URL(?) */ if(crit) str=_("Critical signature policy: "); else @@ -161,7 +196,7 @@ show_policy_url(PKT_signature *sig,int indent,int mode) log_info("%s",str); else printf("%s",str); - print_string(fp,p,len,0); + print_utf8_string(fp,p,len); fprintf(fp,"\n"); } @@ -170,6 +205,48 @@ show_policy_url(PKT_signature *sig,int indent,int mode) } } + +/* + mode=0 for stdout. + mode=1 for log_info + status messages + mode=2 for status messages only +*/ +/* TODO: use this */ +void +show_keyserver_url(PKT_signature *sig,int indent,int mode) +{ + const byte *p; + size_t len; + int seq=0,crit; + FILE *fp=mode?log_get_stream():stdout; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&len,&seq,&crit))) + { + if(mode!=2) + { + int i; + char *str; + + for(i=0;i<indent;i++) + putchar(' '); + + if(crit) + str=_("Critical preferred keyserver: "); + else + str=_("Preferred keyserver: "); + if(mode) + log_info("%s",str); + else + printf("%s",str); + print_utf8_string(fp,p,len); + fprintf(fp,"\n"); + } + + /* TODO: put in a status-fd tag for preferred keyservers */ + } +} + + /* mode=0 for stdout. mode=1 for log_info + status messages @@ -788,6 +865,9 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) show_notation(sig,3,0); + if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + show_keyserver_url(sig,3,0); + /* fixme: check or list other sigs here */ } } @@ -820,7 +900,7 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) pk = NULL; sk = node->pkt->pkt.secret_key; keyid_from_sk( sk, keyid ); - printf("sec:u:%u:%d:%08lX%08lX:%s:%s:::", + printf("sec::%u:%d:%08lX%08lX:%s:%s:::", nbits_from_sk( sk ), sk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], @@ -886,13 +966,17 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) if( any ) { int i; char *str=uid->attrib_data?"uat":"uid"; - if ( uid->is_revoked ) + /* If we're listing a secret key, leave out the + validity values for now. FIXME: This should be + handled better in 1.9. */ + if ( sk ) + printf("%s:::::",str); + else if ( uid->is_revoked ) printf("%s:r::::",str); else if ( uid->is_expired ) printf("%s:e::::",str); - else if ( opt.no_expensive_trust_checks ) { + else if ( opt.no_expensive_trust_checks ) printf("%s:::::",str); - } else { int uid_validity; @@ -1010,8 +1094,10 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) } else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; - int sigrc; + int sigrc, fprokay=0; char *sigstr; + size_t fplen; + byte fparray[MAX_FINGERPRINT_LEN]; if( !any ) { /* no user id, (maybe a revocation follows)*/ if( sig->sig_class == 0x20 ) @@ -1045,8 +1131,14 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) continue; } if( opt.check_sigs ) { + PKT_public_key *signer_pk=NULL; + fflush(stdout); - rc = check_key_signature( keyblock, node, NULL ); + if(opt.no_sig_cache) + signer_pk = xcalloc (1, sizeof(PKT_public_key)); + + rc = check_key_signature2( keyblock, node, NULL, signer_pk, + NULL, NULL, NULL ); switch( gpg_err_code (rc) ) { case 0: sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; @@ -1054,6 +1146,16 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; default: sigrc = '%'; break; } + + if(opt.no_sig_cache) + { + if(!rc) + { + fingerprint_from_pk (signer_pk, fparray, &fplen); + fprokay=1; + } + free_public_key(signer_pk); + } } else { rc = 0; @@ -1087,7 +1189,20 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) print_string( stdout, p, n, ':' ); xfree (p); } - printf(":%02x%c:\n", sig->sig_class,sig->flags.exportable?'x':'l'); + printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l'); + if(opt.no_sig_cache && opt.check_sigs && fprokay) + { + size_t i; + + printf(":"); + + for (i=0; i < fplen ; i++ ) + printf ("%02X", fparray[i] ); + + printf(":"); + } + + printf("\n"); /* fixme: check or list other sigs here */ } } diff --git a/g10/keyring.c b/g10/keyring.c index 4639e9462..03a22667c 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -1382,6 +1382,13 @@ keyring_rebuild_cache (void *token) { if (node->pkt->pkttype == PKT_SIGNATURE) { + /* Note that this doesn't cache the result of a + revocation issued by a designated revoker. This is + because the pk in question does not carry the revkeys + as we haven't merged the key and selfsigs. It is + questionable whether this matters very much since + there are very very few designated revoker revocation + packets out there. */ check_key_signature (keyblock, node, NULL); sigcount++; } diff --git a/g10/keyserver.c b/g10/keyserver.c index e4f56ca3b..445c07620 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -170,7 +170,8 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) opt.keyserver_scheme="hkp"; opt.keyserver_options.broken_http_proxy=1; } - else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0) + else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0 + || ascii_strcasecmp(opt.keyserver_scheme,"http")==0) { /* Canonicalize this to "hkp" so it works with both the internal and external keyserver interface. */ @@ -203,7 +204,7 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) ch=opt.keyserver_port; while(*ch!='\0') { - if(!isdigit(*ch)) + if(!digitp(ch)) return GPG_ERR_BAD_URI; ch++; @@ -340,7 +341,7 @@ parse_keyrec(char *keystring) /* Remove trailing whitespace */ for(i=strlen(keystring);i>0;i--) - if(isspace(keystring[i-1])) + if(ascii_isspace(keystring[i-1])) keystring[i-1]='\0'; else break; @@ -978,7 +979,7 @@ keyserver_spawn(int action,STRLIST list, /* remove trailing whitespace */ plen=strlen(ptr); - while(plen>0 && isspace(ptr[plen-1])) + while(plen>0 && ascii_isspace(ptr[plen-1])) plen--; plen[ptr]='\0'; diff --git a/g10/main.h b/g10/main.h index 320a543de..76562fa91 100644 --- a/g10/main.h +++ b/g10/main.h @@ -151,7 +151,8 @@ int sign_symencrypt_file (const char *fname, STRLIST locusr); int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig); int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, - int *is_selfsig, u32 *r_expiredate, int *r_expired ); + PKT_public_key *ret_pk, int *is_selfsig, + u32 *r_expiredate, int *r_expired ); /*-- delkey.c --*/ int delete_keys( STRLIST names, int secret, int allow_both ); @@ -170,6 +171,7 @@ PKT_user_id *keygen_get_std_prefs (void); int keygen_add_key_expire( PKT_signature *sig, void *opaque ); int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); +int keygen_add_keyserver_url(PKT_signature *sig, void *opaque); int keygen_add_revkey(PKT_signature *sig, void *opaque); int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); @@ -232,6 +234,7 @@ void reorder_keyblock (KBNODE keyblock); void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); void show_policy_url(PKT_signature *sig,int indent,int mode); +void show_keyserver_url(PKT_signature *sig,int indent,int mode); void show_notation(PKT_signature *sig,int indent,int mode); void dump_attribs(const PKT_user_id *uid, PKT_public_key *pk,PKT_secret_key *sk); diff --git a/g10/mainproc.c b/g10/mainproc.c index 3689525ef..40b9bd20a 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -668,15 +668,12 @@ proc_compressed( CTX c, PACKET *pkt ) * Returns: 0 = valid signature or an error code */ static int -do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) +do_check_sig( CTX c, KBNODE node, int *is_selfsig, + int *is_expkey, int *is_revkey ) { PKT_signature *sig; MD_HANDLE md = NULL, md2 = NULL; - int algo, rc, dum2; - u32 dummy; - - if(!is_expkey) - is_expkey=&dum2; + int algo, rc; assert( node->pkt->pkttype == PKT_SIGNATURE ); if( is_selfsig ) @@ -732,9 +729,9 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, int *is_expkey ) } else return GPG_ERR_SIG_CLASS; - rc = signature_check2( sig, md, &dummy, is_expkey ); + rc = signature_check2( sig, md, NULL, is_expkey, is_revkey, NULL ); if( gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2 ) - rc = signature_check2( sig, md2, &dummy, is_expkey ); + rc = signature_check2( sig, md2, NULL, is_expkey, is_revkey, NULL ); gcry_md_close (md); gcry_md_close (md2); @@ -958,7 +955,8 @@ list_node( CTX c, KBNODE node ) if( opt.check_sigs ) { fflush(stdout); switch( gpg_err_code (rc2=do_check_sig( c, node, - &is_selfsig, NULL )) ) { + &is_selfsig, + NULL, NULL )) ) { case 0: sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: @@ -1217,7 +1215,7 @@ check_sig_and_print( CTX c, KBNODE node ) { PKT_signature *sig = node->pkt->pkt.signature; const char *astr, *tstr; - int rc, is_expkey=0; + int rc, is_expkey=0, is_revkey=0; if( opt.skip_verify ) { log_info(_("signature verification suppressed\n")); @@ -1281,19 +1279,51 @@ check_sig_and_print( CTX c, KBNODE node ) tstr = asctimestamp(sig->timestamp); astr = gcry_pk_algo_name (sig->pubkey_algo); - log_info(_("Signature made %.*s using %s key ID %08lX\n"), - (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); + if(opt.verify_options&VERIFY_SHOW_LONG_KEYID) + { + log_info(_("Signature made %.*s\n"),(int)strlen(tstr), tstr); + log_info(_(" using %s key %08lX%08lX\n"), + astr? astr: "?",(ulong)sig->keyid[0],(ulong)sig->keyid[1] ); + } + else + log_info(_("Signature made %.*s using %s key ID %08lX\n"), + (int)strlen(tstr), tstr, astr? astr: "?", + (ulong)sig->keyid[1] ); - rc = do_check_sig(c, node, NULL, &is_expkey ); + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { if( keyserver_import_keyid ( sig->keyid )==0 ) - rc = do_check_sig(c, node, NULL, &is_expkey ); + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); } + + + /* If the key still isn't found, try to inform the user where it + can be found. */ + if(gpg_err_code (rc)==GPG_ERR_NO_PUBKEY && sig->flags.pref_ks) + { + const byte *p; + int seq=0; + size_t n; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL))) + { + /* According to my favorite copy editor, in English + grammar, you say "at" if the key is located on a web + page, but "from" if it is located on a keyserver. I'm + not going to even try to make two strings here :) */ + log_info(_("Key available at: ") ); + print_string( log_get_stream(), p, n, 0 ); + putc( '\n', log_get_stream() ); + } + } + + if( !rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) { KBNODE un, keyblock; int count=0, statno; char keyid_str[50]; + PKT_public_key *pk=NULL; if(rc) statno=STATUS_BADSIG; @@ -1301,6 +1331,8 @@ check_sig_and_print( CTX c, KBNODE node ) statno=STATUS_EXPSIG; else if(is_expkey) statno=STATUS_EXPKEYSIG; + else if(is_revkey) + statno=STATUS_REVKEYSIG; else statno=STATUS_GOODSIG; @@ -1311,6 +1343,13 @@ check_sig_and_print( CTX c, KBNODE node ) /* find and print the primary user ID */ for( un=keyblock; un; un = un->next ) { + int valid; + + if(un->pkt->pkttype==PKT_PUBLIC_KEY) + { + pk=un->pkt->pkt.public_key; + continue; + } if( un->pkt->pkttype != PKT_USER_ID ) continue; if ( !un->pkt->pkt.user_id->created ) @@ -1325,6 +1364,13 @@ check_sig_and_print( CTX c, KBNODE node ) if ( un->pkt->pkt.user_id->attrib_data ) continue; + assert(pk); + + /* Get it before we print anything to avoid interrupting + the output with the "please do a --check-trustdb" + line. */ + valid=get_validity(pk,un->pkt->pkt.user_id); + keyid_str[17] = 0; /* cut off the "[uncertain]" part */ write_status_text_and_buffer (statno, keyid_str, un->pkt->pkt.user_id->name, @@ -1336,7 +1382,11 @@ check_sig_and_print( CTX c, KBNODE node ) : _("Good signature from \"")); print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len ); - fputs("\"\n", log_get_stream() ); + if(opt.verify_options&VERIFY_SHOW_VALIDITY) + fprintf (log_get_stream(), + "\" [%s]\n",trust_value_to_string(valid)); + else + fputs("\"\n", log_get_stream() ); count++; } if( !count ) { /* just in case that we have no valid textual @@ -1380,10 +1430,7 @@ check_sig_and_print( CTX c, KBNODE node ) /* If we have a good signature and already printed * the primary user ID, print all the other user IDs */ if ( count && !rc ) { - PKT_public_key *pk=NULL; for( un=keyblock; un; un = un->next ) { - if(un->pkt->pkttype==PKT_PUBLIC_KEY) - pk=un->pkt->pkt.public_key; if( un->pkt->pkttype != PKT_USER_ID ) continue; if ( un->pkt->pkt.user_id->is_revoked ) @@ -1407,28 +1454,46 @@ check_sig_and_print( CTX c, KBNODE node ) log_info( _(" aka \"")); print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len ); - fputs("\"\n", log_get_stream() ); + if(opt.verify_options&VERIFY_SHOW_VALIDITY) + fprintf (log_get_stream(), "\" [%s]\n", + trust_value_to_string(get_validity(pk, + un->pkt-> + pkt.user_id))); + else + fputs("\"\n", log_get_stream() ); } } release_kbnode( keyblock ); if( !rc ) { - show_notation(sig,0,1); - show_policy_url(sig,0,1); - } + if(opt.verify_options&VERIFY_SHOW_POLICY) + show_policy_url(sig,0,1); + else + show_policy_url(sig,0,2); + + if(opt.verify_options&VERIFY_SHOW_KEYSERVER) + show_keyserver_url(sig,0,1); + else + show_keyserver_url(sig,0,2); + + if(opt.verify_options&VERIFY_SHOW_NOTATION) + show_notation(sig,0,1); + else + show_notation(sig,0,2); + } if( !rc && is_status_enabled() ) { /* print a status response with the fingerprint */ - PKT_public_key *pk = xcalloc (1, sizeof *pk ); + PKT_public_key *vpk = xcalloc (1, sizeof *vpk ); - if( !get_pubkey( pk, sig->keyid ) ) { + if( !get_pubkey( vpk, sig->keyid ) ) { byte array[MAX_FINGERPRINT_LEN], *p; char buf[MAX_FINGERPRINT_LEN*4+90], *bufp; size_t i, n; bufp = buf; - fingerprint_from_pk( pk, array, &n ); + fingerprint_from_pk( vpk, array, &n ); p = array; for(i=0; i < n ; i++, p++, bufp += 2) sprintf(bufp, "%02X", *p ); @@ -1442,27 +1507,27 @@ check_sig_and_print( CTX c, KBNODE node ) sig->version,sig->pubkey_algo,sig->digest_algo, sig->sig_class); bufp = bufp + strlen (bufp); - if (!pk->is_primary) { + if (!vpk->is_primary) { u32 akid[2]; - akid[0] = pk->main_keyid[0]; - akid[1] = pk->main_keyid[1]; - free_public_key (pk); - pk = xcalloc (1, sizeof *pk ); - if (get_pubkey (pk, akid)) { + akid[0] = vpk->main_keyid[0]; + akid[1] = vpk->main_keyid[1]; + free_public_key (vpk); + vpk = xcalloc (1, sizeof *vpk ); + if (get_pubkey (vpk, akid)) { /* impossible error, we simply return a zeroed out fpr */ n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; memset (array, 0, n); } else - fingerprint_from_pk( pk, array, &n ); + fingerprint_from_pk( vpk, array, &n ); } p = array; for(i=0; i < n ; i++, p++, bufp += 2) sprintf(bufp, "%02X", *p ); write_status_text( STATUS_VALIDSIG, buf ); } - free_public_key( pk ); + free_public_key( vpk ); } if( !rc ) diff --git a/g10/misc.c b/g10/misc.c index 4abe75661..e122f0c5c 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -369,6 +369,8 @@ pct_expando(const char *string,struct expando_args *args) if(args->sk) keyid_from_sk(args->sk,sk_keyid); + /* This is used so that %k works in photoid command strings in + --list-secret-keys (which of course has a sk, but no pk). */ if(!args->pk && args->sk) keyid_from_sk(args->sk,pk_keyid); @@ -430,16 +432,37 @@ pct_expando(const char *string,struct expando_args *args) } break; - case 'f': /* fingerprint */ + case 'p': /* primary pk fingerprint of a sk */ + case 'f': /* pk fingerprint */ + case 'g': /* sk fingerprint */ { byte array[MAX_FINGERPRINT_LEN]; size_t len; int i; - if(args->pk) + if( ch[1]=='p' && args->sk) + { + if(args->sk->is_primary) + fingerprint_from_sk(args->sk,array,&len); + else if(args->sk->main_keyid[0] || args->sk->main_keyid[1]) + { + PKT_public_key *pk= xcalloc(1, sizeof(PKT_public_key)); + + if(get_pubkey_fast(pk,args->sk->main_keyid)==0) + fingerprint_from_pk(pk,array,&len); + else + memset(array,0,(len=MAX_FINGERPRINT_LEN)); + free_public_key(pk); + } + else + memset(array,0,(len=MAX_FINGERPRINT_LEN)); + } + else if( ch[1]=='f' && args->pk) fingerprint_from_pk(args->pk,array,&len); + else if( ch[1]=='g' && args->sk) + fingerprint_from_sk(args->sk,array,&len); else - memset(array,0, (len=MAX_FINGERPRINT_LEN)); + memset(array, 0, (len=MAX_FINGERPRINT_LEN)); if(idx+(len*2)<maxlen) { diff --git a/g10/options.h b/g10/options.h index 9eda2e252..a4cbc3834 100644 --- a/g10/options.h +++ b/g10/options.h @@ -101,7 +101,7 @@ struct { unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ int shm_coprocess; const char *set_filename; - const char *comment_string; + STRLIST comments; int throw_keyid; const char *photo_viewer; int s2k_mode; @@ -153,6 +153,7 @@ struct { STRLIST cert_notation_data; STRLIST sig_policy_url; STRLIST cert_policy_url; + STRLIST sig_keyserver_url; int use_embedded_filename; int allow_non_selfsigned_uid; int allow_freeform_uid; @@ -230,16 +231,22 @@ struct { #define EXPORT_SEXP_FORMAT 16 -#define LIST_SHOW_PHOTOS 1 -#define LIST_SHOW_POLICY 2 -#define LIST_SHOW_NOTATION 4 -#define LIST_SHOW_KEYRING 8 -#define LIST_SHOW_VALIDITY 16 -#define LIST_SHOW_LONG_KEYID 32 +#define LIST_SHOW_PHOTOS 1 +#define LIST_SHOW_POLICY 2 +#define LIST_SHOW_NOTATION 4 +#define LIST_SHOW_KEYSERVER 8 +#define LIST_SHOW_VALIDITY 16 +#define LIST_SHOW_LONG_KEYID 32 +#define LIST_SHOW_KEYRING 64 +#define LIST_SHOW_SIG_EXPIRE 128 -#define VERIFY_SHOW_PHOTOS 1 -#define VERIFY_SHOW_POLICY 2 -#define VERIFY_SHOW_NOTATION 4 + +#define VERIFY_SHOW_PHOTOS 1 +#define VERIFY_SHOW_POLICY 2 +#define VERIFY_SHOW_NOTATION 4 +#define VERIFY_SHOW_KEYSERVER 8 +#define VERIFY_SHOW_VALIDITY 16 +#define VERIFY_SHOW_LONG_KEYID 32 #endif /*G10_OPTIONS_H*/ diff --git a/g10/options.skel b/g10/options.skel index e50f66ffe..3d15f811c 100644 --- a/g10/options.skel +++ b/g10/options.skel @@ -90,10 +90,10 @@ # support). # # Example HKP keyserver: -# x-hkp://pgp.mit.edu +# hkp://subkeys.pgp.net # # Example email keyserver: -# mailto:pgp-public-keys@keys.nl.pgp.net +# mailto:pgp-public-keys@keys.pgp.net # # Example LDAP keyservers: # ldap://pgp.surfnet.nl:11370 @@ -101,7 +101,7 @@ # # Regular URL syntax applies, and you can set an alternate port # through the usual method: -# x-hkp://keyserver.example.net:22742 +# hkp://keyserver.example.net:22742 # # If you have problems connecting to a HKP server through a buggy http # proxy, you can use keyserver option broken-http-proxy (see below), @@ -109,10 +109,14 @@ # regarding proxies (keyserver option honor-http-proxy) # # Most users just set the name and type of their preferred keyserver. -# Most servers do synchronize with each other and DNS round-robin may -# give you a quasi-random server each time. - -#keyserver x-hkp://pgp.mit.edu +# Note that most servers (with the notable exception of +# ldap://keyserver.pgp.com) synchronize changes with each other. Note +# also that a single server name may actually point to multiple +# servers via DNS round-robin. hkp://subkeys.pgp.net is an example of +# such a "server", which spreads the load over a number of physical +# servers. + +keyserver hkp://subkeys.pgp.net #keyserver mailto:pgp-public-keys@keys.nl.pgp.net #keyserver ldap://pgp.surfnet.nl:11370 #keyserver ldap://keyserver.pgp.com diff --git a/g10/packet.h b/g10/packet.h index dc5b1583a..2d87c9c7d 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -132,8 +132,9 @@ typedef struct { unsigned unknown_critical:1; unsigned exportable:1; unsigned revocable:1; - unsigned policy_url:1; /* Policy URL is present */ - unsigned notation:1; /* At least one notation is present */ + unsigned policy_url:1; /* At least one policy URL is present */ + unsigned notation:1; /* At least one notation is present */ + unsigned pref_ks:1; /* At least one preferred keyserver is present */ unsigned expired:1; } flags; u32 keyid[2]; /* 64 bit keyid */ @@ -463,8 +464,8 @@ int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); /*-- sig-check.c --*/ int signature_check( PKT_signature *sig, MD_HANDLE digest ); -int signature_check2( PKT_signature *sig, MD_HANDLE digest, - u32 *r_expiredate, int *r_expired ); +int signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, + int *r_expired, int *r_revoked, PKT_public_key *ret_pk ); /*-- seckey-cert.c --*/ int is_secret_key_protected( PKT_secret_key *sk ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index f70cc3f69..c922eb5d9 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -367,9 +367,29 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); if( !lenbytes ) { pktlen = 0; /* don't know the value */ - if( pkttype != PKT_COMPRESSED ) - iobuf_set_block_mode(inp, 1); - } + switch (pkttype) { + case PKT_ENCRYPTED: + case PKT_PLAINTEXT: + /* These partial length encodings are from an very + early GnuPG release and deprecated. However we + still support them read-wise. Note, that we should + not allow them for any key related packets, because + this might render a keyring unusable if an errenous + packet indicated this mode but not complying to it + gets imported. */ + iobuf_set_block_mode(inp, 1); + break; + + case PKT_COMPRESSED: + break; /* the orginal pgp 2 way. */ + + default: + log_error ("%s: old style partial length " + "for invalid packet type\n", iobuf_where(inp) ); + rc = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + } else { for( ; lenbytes; lenbytes-- ) { pktlen <<= 8; @@ -860,7 +880,8 @@ dump_sig_subpkt( int hashed, int type, int critical, printf(" %02X", buffer[i]); break; case SIGSUBPKT_PREF_KS: - p = "preferred key server"; + fputs("preferred key server: ", stdout ); + print_string( stdout, buffer, length, ')' ); break; case SIGSUBPKT_PRIMARY_UID: p = "primary user ID"; @@ -936,6 +957,7 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_POLICY: + case SIGSUBPKT_PREF_KS: case SIGSUBPKT_FEATURES: case SIGSUBPKT_REGEXP: return 0; @@ -992,9 +1014,11 @@ can_handle_critical( const byte *buffer, size_t n, int type ) case SIGSUBPKT_KEY_FLAGS: case SIGSUBPKT_PRIMARY_UID: case SIGSUBPKT_FEATURES: - case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */ case SIGSUBPKT_TRUST: case SIGSUBPKT_REGEXP: + /* Is it enough to show the policy or keyserver? */ + case SIGSUBPKT_POLICY: + case SIGSUBPKT_PREF_KS: return 1; default: @@ -1220,11 +1244,8 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, goto leave; } if( n ) { - /* we add 8 extra bytes so that we have space for the signature - * status cache. Well we are wasting this if there is a cache - * packet already, but in the other case it avoids an realloc */ - sig->unhashed = xmalloc (sizeof(*sig->unhashed) + n + 8 - 1 ); - sig->unhashed->size = n + 8; + sig->unhashed = xmalloc (sizeof(*sig->unhashed) + n - 1 ); + sig->unhashed->size = n; sig->unhashed->len = n; if( iobuf_read(inp, sig->unhashed->data, n ) != n ) { log_error("premature eof while reading " @@ -1259,17 +1280,19 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, } p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL ); - if( !p ) - log_error("signature packet without timestamp\n"); - else - sig->timestamp = buffer_to_u32(p); + if(p) + sig->timestamp = buffer_to_u32(p); + else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)) + log_error("signature packet without timestamp\n"); + p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); - if( !p ) - log_error("signature packet without keyid\n"); - else { - sig->keyid[0] = buffer_to_u32(p); - sig->keyid[1] = buffer_to_u32(p+4); + if( p ) + { + sig->keyid[0] = buffer_to_u32(p); + sig->keyid[1] = buffer_to_u32(p+4); } + else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)) + log_error("signature packet without keyid\n"); p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL); if(p) @@ -1281,6 +1304,10 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, if(p) sig->flags.policy_url=1; + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,NULL); + if(p) + sig->flags.pref_ks=1; + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL); if(p) sig->flags.notation=1; diff --git a/g10/passphrase.c b/g10/passphrase.c index d00340109..ac7e71591 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -29,7 +29,7 @@ #include <sys/socket.h> #include <sys/un.h> #endif -#if defined (__MINGW32__) || defined (__CYGWIN32__) +#if defined (_WIN32) || defined (__CYGWIN32__) # include <windows.h> #endif #include <errno.h> @@ -101,7 +101,7 @@ static char *fd_passwd = NULL; static char *next_pw = NULL; static char *last_pw = NULL; -#if defined (__MINGW32__) +#if defined (_WIN32) static int read_fd = 0; static int write_fd = 0; #endif @@ -191,7 +191,7 @@ read_passphrase_from_fd( int fd ) static int writen ( int fd, const void *buf, size_t nbytes ) { -#if defined (__MINGW32__) +#if defined (_WIN32) DWORD nwritten, nleft = nbytes; while (nleft > 0) { @@ -234,7 +234,7 @@ writen ( int fd, const void *buf, size_t nbytes ) static int readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) { -#if defined (__MINGW32__) +#if defined (_WIN32) DWORD nread, nleft = buflen; while (nleft > 0) { @@ -328,7 +328,7 @@ readline (int fd, char *buf, size_t buflen) #if !defined (__riscos__) -#if !defined (__MINGW32__) +#if !defined (_WIN32) /* For the new Assuan protocol we may have to send options */ static int agent_send_option (int fd, const char *name, const char *value) @@ -376,7 +376,11 @@ agent_send_all_options (int fd) } if (!opt.ttyname) - dft_ttyname = tty_get_ttyname (); + { + dft_ttyname = getenv ("GPG_TTY"); + if ((!dft_ttyname || !*dft_ttyname) && tty_get_ttyname ()) + dft_ttyname = tty_get_ttyname (); + } if (opt.ttyname || dft_ttyname) { if (agent_send_option (fd, "ttyname", @@ -433,7 +437,7 @@ agent_send_all_options (int fd) #endif return rc; } -#endif /*!__MINGW32__*/ +#endif /*!_WIN32*/ /* @@ -444,7 +448,7 @@ agent_send_all_options (int fd) static int agent_open (int *ret_prot) { -#if defined (__MINGW32__) +#if defined (_WIN32) int fd; char *infostr, *p; HANDLE h; @@ -589,7 +593,7 @@ agent_open (int *ret_prot) static void agent_close ( int fd ) { -#if defined (__MINGW32__) +#if defined (_WIN32) HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); ResetEvent(h); #else diff --git a/g10/photoid.c b/g10/photoid.c index 1dd6edeca..00cc7a273 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -22,7 +22,7 @@ #include <errno.h> #include <stdio.h> #include <string.h> -#ifdef __MINGW32__ +#ifdef _WIN32 # include <windows.h> # ifndef VER_PLATFORM_WIN32_WINDOWS # define VER_PLATFORM_WIN32_WINDOWS 1 @@ -223,7 +223,7 @@ char *image_type_to_string(byte type,int style) #if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER) static const char *get_default_photo_command(void) { -#if defined(__MINGW32__) +#if defined(_WIN32) OSVERSIONINFO osvi; memset(&osvi,0,sizeof(osvi)); diff --git a/g10/pkclist.c b/g10/pkclist.c index 5a4aa250f..71e6492e8 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1164,10 +1164,6 @@ algo_available( preftype_t preftype, int algo, void *hint ) && algo != DIGEST_ALGO_SHA256)) return 0; - /* TIGER is not allowed any longer according to 2440bis. */ - if( RFC2440 && algo == DIGEST_ALGO_TIGER ) - return 0; - return algo && !gcry_md_test_algo( algo ); } else if( preftype == PREFTYPE_ZIP ) diff --git a/g10/revoke.c b/g10/revoke.c index cf1bfe17a..161bd2b82 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -608,7 +608,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) return NULL; /* cancel */ if( hint && !*answer ) n = hint; - else if(!isdigit( *answer ) ) + else if(!digitp( answer ) ) n = -1; else n = atoi(answer); diff --git a/g10/sig-check.c b/g10/sig-check.c index 4547c6e12..b0c89cba3 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -43,8 +43,9 @@ struct cmp_help_context_s { MD_HANDLE md; }; -static int do_check( PKT_public_key *pk, PKT_signature *sig, - MD_HANDLE digest, int *r_expired ); + +static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, + int *r_expired, int *r_revoked, PKT_public_key *ret_pk); /**************** * Check the signature which is contained in SIG. @@ -54,20 +55,16 @@ static int do_check( PKT_public_key *pk, PKT_signature *sig, int signature_check( PKT_signature *sig, MD_HANDLE digest ) { - u32 dummy; - int dum2; - return signature_check2( sig, digest, &dummy, &dum2 ); + return signature_check2( sig, digest, NULL, NULL, NULL, NULL ); } int -signature_check2( PKT_signature *sig, MD_HANDLE digest, - u32 *r_expiredate, int *r_expired ) +signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, + int *r_expired, int *r_revoked, PKT_public_key *ret_pk ) { PKT_public_key *pk = xcalloc (1, sizeof *pk ); int rc=0; - *r_expiredate = 0; - /* Sanity check that the md has a context for the hash that the sig is expecting. This can happen if a onepass sig header does not match the actual sig, and also if the clearsign "Hash:" @@ -83,8 +80,9 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, rc=GPG_ERR_BAD_PUBKEY; /* you cannot have a good sig from an invalid subkey */ else { - *r_expiredate = pk->expiredate; - rc = do_check( pk, sig, digest, r_expired ); + if (r_expiredate) + *r_expiredate = pk->expiredate; + rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk ); } free_public_key( pk ); @@ -135,11 +133,15 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, static int -do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) +do_check_messages( PKT_public_key *pk, PKT_signature *sig, + int *r_expired, int *r_revoked ) { u32 cur_time; - *r_expired = 0; + if (r_expired) + *r_expired = 0; + if (r_revoked) + *r_revoked = 0; if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { log_info(_("key %08lX: this is a PGP generated " "ElGamal key which is NOT secure for signatures!\n"), @@ -182,22 +184,26 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, int *r_expired ) sprintf(buf,"%lu",(ulong)pk->expiredate); write_status_text(STATUS_KEYEXPIRED,buf); write_status(STATUS_SIGEXPIRED); - *r_expired = 1; + if (r_expired) + *r_expired = 1; } + if(pk->is_revoked && r_revoked) + *r_revoked=1; + return 0; } static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, - int *r_expired ) + int *r_expired, int *r_revoked, PKT_public_key *ret_pk ) { gcry_mpi_t result = NULL; int rc=0; struct cmp_help_context_s ctx; - if( (rc=do_check_messages(pk,sig,r_expired)) ) + if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) ) return rc; if( (rc=gcry_md_test_algo(sig->digest_algo)) ) return rc; @@ -280,6 +286,9 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, rc = gpg_error (GPG_ERR_BAD_SIGNATURE); } + if(!rc && ret_pk) + copy_public_key(ret_pk,pk); + return rc; } @@ -406,16 +415,19 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) { - u32 dummy; - int dum2; - return check_key_signature2(root, node, NULL, is_selfsig, &dummy, &dum2 ); + return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL); } /* If check_pk is set, then use it to check the signature in node - rather than getting it from root or the keydb. */ + rather than getting it from root or the keydb. If ret_pk is set, + fill in the public key that was used to verify the signature. + ret_pk is only meaningful when the verification was successful. */ +/* TODO: add r_revoked here as well. It has the same problems as + r_expiredate and r_expired and the cache. */ int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, - int *is_selfsig, u32 *r_expiredate, int *r_expired ) + PKT_public_key *ret_pk, int *is_selfsig, + u32 *r_expiredate, int *r_expired ) { MD_HANDLE md; PKT_public_key *pk; @@ -425,8 +437,10 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( is_selfsig ) *is_selfsig = 0; - *r_expiredate = 0; - *r_expired = 0; + if( r_expiredate ) + *r_expiredate = 0; + if( r_expired ) + *r_expired = 0; assert( node->pkt->pkttype == PKT_SIGNATURE ); assert( root->pkt->pkttype == PKT_PUBLIC_KEY ); @@ -444,7 +458,9 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) *is_selfsig = 1; } - if((rc=do_check_messages(pk,sig,r_expired))) + /* BUG: This is wrong for non-self-sigs. Needs to be the + actual pk */ + if((rc=do_check_messages(pk,sig,r_expired,NULL))) return rc; return sig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE); } @@ -464,7 +480,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, { gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } @@ -476,12 +492,12 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } else { - if (!opt.quiet) + if (opt.verbose) log_info (_("key %08lX: no subkey for subkey " "revocation signature\n"), (ulong)keyid_from_pk (pk, NULL)); @@ -502,7 +518,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } @@ -517,7 +533,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, else if( sig->sig_class == 0x1f ) { /* direct key signature */ gcry_md_open (&md, algo, 0 ); hash_public_key( md, pk ); - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } @@ -535,12 +551,13 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, { if( is_selfsig ) *is_selfsig = 1; - rc = do_check( pk, sig, md, r_expired ); + rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); } else if (check_pk) - rc=do_check(check_pk,sig,md,r_expired); + rc=do_check(check_pk,sig,md,r_expired, NULL, ret_pk); else - rc = signature_check2( sig, md, r_expiredate, r_expired ); + rc = signature_check2( sig, md, r_expiredate, r_expired, + NULL, ret_pk); cache_sig_result ( sig, rc ); gcry_md_close(md); diff --git a/g10/sign.c b/g10/sign.c index 493bfb4d9..640e36fe0 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -55,12 +55,12 @@ void __stdcall Sleep(ulong); static int recipient_digest_algo=0; /**************** - * Create a notation. It is assumed that the stings in STRLIST - * are already checked to contain only printable data and have a valid - * NAME=VALUE format. + * Create a notation. We assume thIt is assumed that the strings in + * the STRLISTs of the opt struct are already checked to contain only + * printable data and have a valid NAME=VALUE format. */ static void -mk_notation_and_policy( PKT_signature *sig, +mk_notation_policy_etc( PKT_signature *sig, PKT_public_key *pk, PKT_secret_key *sk ) { const char *string; @@ -74,18 +74,25 @@ mk_notation_and_policy( PKT_signature *sig, args.pk=pk; args.sk=sk; + /* It is actually impossible to get here when making a v3 key + signature since keyedit.c:sign_uids will automatically bump a + signature with a notation or policy url up to v4, but it is + good to do these checks anyway. */ + /* notation data */ if(IS_SIG(sig) && opt.sig_notation_data) { if(sig->version<4) - log_info("can't put notation data into v3 signatures\n"); + log_error(_("can't put notation data into v3 (PGP 2.x style) " + "signatures\n")); else nd=opt.sig_notation_data; } else if( IS_CERT(sig) && opt.cert_notation_data ) { if(sig->version<4) - log_info("can't put notation data into v3 key signatures\n"); + log_error(_("can't put notation data into v3 (PGP 2.x style) " + "key signatures\n")); else nd=opt.cert_notation_data; } @@ -125,21 +132,20 @@ mk_notation_and_policy( PKT_signature *sig, xfree (buf); } - if(opt.list_options&LIST_SHOW_NOTATION) - show_notation(sig,0,0); - /* set policy URL */ if( IS_SIG(sig) && opt.sig_policy_url ) { if(sig->version<4) - log_info("can't put a policy URL into v3 signatures\n"); + log_error(_("can't put a policy URL into v3 (PGP 2.x style) " + "signatures\n")); else pu=opt.sig_policy_url; } else if( IS_CERT(sig) && opt.cert_policy_url ) { if(sig->version<4) - log_info("can't put a policy URL into v3 key signatures\n"); + log_error(_("can't put a policy URL into v3 key (PGP 2.x style) " + "signatures\n")); else pu=opt.cert_policy_url; } @@ -163,8 +169,34 @@ mk_notation_and_policy( PKT_signature *sig, xfree (s); } - if(opt.list_options&LIST_SHOW_POLICY) - show_policy_url(sig,0,0); + /* preferred keyserver URL */ + if( IS_SIG(sig) && opt.sig_keyserver_url ) + { + if(sig->version<4) + log_info (_("can't put a preferred keyserver URL " + "into v3 signatures\n")); + else + pu=opt.sig_keyserver_url; + } + + for(;pu;pu=pu->next) + { + string = pu->d; + + s=pct_expando(string,&args); + if(!s) + { + log_error(_("WARNING: unable to %%-expand preferred keyserver URL" + " (too large). Using unexpanded.\n")); + s=xstrdup(string); + } + + build_sig_subpkt(sig,SIGSUBPKT_PREF_KS| + ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0), + s,strlen(s)); + + xfree(s); + } } @@ -621,7 +653,8 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, sig = xcalloc (1,sizeof *sig); if(opt.force_v3_sigs || RFC1991) sig->version=3; - else if(duration || opt.sig_policy_url || opt.sig_notation_data) + else if(duration || opt.sig_policy_url + || opt.sig_notation_data || opt.sig_keyserver_url) sig->version=4; else sig->version=sk->version; @@ -640,7 +673,7 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, if (sig->version >= 4) build_sig_subpkt_from_sig (sig); - mk_notation_and_policy (sig, NULL, sk); + mk_notation_policy_etc (sig, NULL, sk); hash_sigversion_to_magic (md, sig); gcry_md_final (md); @@ -1308,7 +1341,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, sig->sig_class = sigclass; if( sig->version >= 4 ) build_sig_subpkt_from_sig( sig ); - mk_notation_and_policy( sig, pk, sk ); + mk_notation_policy_etc ( sig, pk, sk ); /* Crucial that the call to mksubpkt comes LAST before the calls to finalize the sig as that makes it possible for the mksubpkt diff --git a/g10/signal.c b/g10/signal.c index 90c0841d8..9f50fbe3a 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -1,5 +1,5 @@ /* signal.c - signal handling - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -42,7 +42,7 @@ static void init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign ) { #ifndef HAVE_DOSISH_SYSTEM -#ifdef HAVE_SIGACTION +#if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION) struct sigaction oact, nact; if (check_ign) { @@ -132,7 +132,7 @@ void pause_on_sigusr( int which ) { #ifndef HAVE_DOSISH_SYSTEM -#ifdef HAVE_SIGPROCMASK +#if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) sigset_t mask, oldmask; assert( which == 1 ); @@ -150,8 +150,8 @@ pause_on_sigusr( int which ) while (!caught_sigusr1) sigpause(SIGUSR1); caught_sigusr1 = 0; - sigrelse(SIGUSR1); ???? -#endif /*!HAVE_SIGPROCMASK*/ + sigrelse(SIGUSR1); +#endif /*!HAVE_SIGPROCMASK && HAVE_SISET_T*/ #endif } @@ -161,7 +161,7 @@ do_block( int block ) { #ifndef HAVE_DOSISH_SYSTEM static int is_blocked; -#ifdef HAVE_SIGPROCMASK +#if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) static sigset_t oldmask; if( block ) { @@ -180,13 +180,22 @@ do_block( int block ) is_blocked = 0; } #else /*!HAVE_SIGPROCMASK*/ - static void (*disposition[MAXSIG])(); + +#if defined(NSIG) +# define SIGSMAX (NSIG) +#elif defined(MAXSIG) +# define SIGSMAX (MAXSIG+1) +#else +# error "define SIGSMAX to the number of signals on your platform plus one" +#endif + + static void (*disposition[SIGSMAX])(int); int sig; if( block ) { if( is_blocked ) log_bug("signals are already blocked\n"); - for (sig=1; sig < MAXSIG; sig++) { + for (sig=1; sig < SIGSMAX; sig++) { disposition[sig] = sigset (sig, SIG_HOLD); } is_blocked = 1; @@ -194,7 +203,7 @@ do_block( int block ) else { if( !is_blocked ) log_bug("signals are not blocked\n"); - for (sig=1; sig < MAXSIG; sig++) { + for (sig=1; sig < SIGSMAX; sig++) { sigset (sig, disposition[sig]); } is_blocked = 0; diff --git a/g10/status.c b/g10/status.c index 4414b33e9..aa55020be 100644 --- a/g10/status.c +++ b/g10/status.c @@ -129,6 +129,7 @@ get_status_string ( int no ) case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; case STATUS_EXPSIG : s = "EXPSIG"; break; case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; + case STATUS_REVKEYSIG : s = "REVKEYSIG"; break; case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; default: s = "?"; break; } diff --git a/g10/status.h b/g10/status.h index 4a0bcd45b..d8de81080 100644 --- a/g10/status.h +++ b/g10/status.h @@ -99,6 +99,7 @@ #define STATUS_ATTRIBUTE 67 #define STATUS_IMPORT_OK 68 #define STATUS_IMPORT_CHECK 69 +#define STATUS_REVKEYSIG 70 /*-- status.c --*/ void set_status_fd ( int fd ); diff --git a/g10/tdbdump.c b/g10/tdbdump.c index 3f9e8b388..5eb482959 100644 --- a/g10/tdbdump.c +++ b/g10/tdbdump.c @@ -154,7 +154,7 @@ import_ownertrust( const char *fname ) break; /* can't continue */ } for(p = line; *p && *p != ':' ; p++ ) - if( !isxdigit(*p) ) + if( !hexdigitp (p) ) break; if( *p != ':' ) { log_error (_("\b%s: error: missing colon\n"), fname ); diff --git a/g10/tdbio.c b/g10/tdbio.c index 39239be20..d1b5ed32a 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -337,6 +337,9 @@ tdbio_sync() } +#if 0 +/* The transaction code is disabled in the 1.2.x branch, as it is not + yet used. It will be enabled in 1.3.x. */ /**************** * Simple transactions system: @@ -408,6 +411,8 @@ tdbio_cancel_transaction() return 0; } +#endif /* transaction code */ + /******************************************************** diff --git a/g10/trustdb.c b/g10/trustdb.c index 16bd96e49..864334f4f 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -591,6 +591,31 @@ trustdb_pending_check(void) return pending_check_trustdb; } +void +read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, + byte *marginals,byte *completes,byte *cert_depth) +{ + TRUSTREC opts; + + init_trustdb(); + + read_record(0,&opts,RECTYPE_VER); + + if(trust_model) + *trust_model=opts.r.ver.trust_model; + if(created) + *created=opts.r.ver.created; + if(nextcheck) + *nextcheck=opts.r.ver.nextcheck; + if(marginals) + *marginals=opts.r.ver.marginals; + if(completes) + *completes=opts.r.ver.completes; + if(cert_depth) + *cert_depth=opts.r.ver.cert_depth; +} + + /*********************************************** *********** Ownertrust et al. **************** @@ -1573,10 +1598,14 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist, signed (but not self-signed) uid does carry trust, of a sort, even if it is a statement being made by people other than the key owner "through" the uids on the key owner's key. I'm - going with the latter. -dshaw */ + going with the latter. However, if the user ID was + explicitly revoked, or passively allowed to expire, that + should stop validity through the user ID until it is + resigned. -dshaw */ - /* && node->pkt->pkt.user_id->created) */ - if (node->pkt->pkttype == PKT_USER_ID) + if (node->pkt->pkttype == PKT_USER_ID + && !node->pkt->pkt.user_id->is_revoked + && !node->pkt->pkt.user_id->is_expired) { if (uidnode && issigned) { @@ -1590,12 +1619,11 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist, } uidnode = node; uid=uidnode->pkt->pkt.user_id; -#if 0 - /* If the selfsig is going to expire... This is disabled as - we do count un-self-signed uids in the web of trust. */ + + /* If the selfsig is going to expire... */ if(uid->expiredate && uid->expiredate<*next_expire) *next_expire = uid->expiredate; -#endif + issigned = 0; get_validity_counts(pk,uid); mark_usable_uid_certs (kb, uidnode, main_kid, klist, diff --git a/g10/trustdb.h b/g10/trustdb.h index 720385a06..414c37702 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -64,6 +64,9 @@ int enum_cert_paths( void **context, ulong *lid, void enum_cert_paths_print( void **context, FILE *fp, int refresh, ulong selected_lid ); +void read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, + byte *marginals,byte *completes,byte *cert_depth); + unsigned int get_ownertrust (PKT_public_key *pk); unsigned int get_min_ownertrust (PKT_public_key *pk); int get_ownertrust_info (PKT_public_key *pk); diff --git a/include/ChangeLog b/include/ChangeLog index 380d63b45..5b343f5a0 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,14 @@ +2003-09-04 David Shaw <dshaw@jabberwocky.com> + + * cipher.h: Drop TIGER/192 support. + + * types.h: Prefer using uint64_t when creating a 64-bit unsigned + type. This avoids a warning on compilers that support but complain + about unsigned long long. + + * util.h: Make sure that only ascii is passed to isfoo + functions. (From Werner on stable branch). + 2003-09-04 Werner Koch <wk@gnupg.org> * cipher.h (PUBKEY_USAGE_AUTH): Added. diff --git a/include/cipher.h b/include/cipher.h index 90cedb051..e7e36c6d5 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -53,7 +53,6 @@ #define DIGEST_ALGO_MD5 GCRY_MD_MD5 #define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 #define DIGEST_ALGO_RMD160 GCRY_MD_RMD160 -#define DIGEST_ALGO_TIGER GCRY_MD_TIGER #define DIGEST_ALGO_SHA256 GCRY_MD_SHA256 #define DIGEST_ALGO_SHA384 GCRY_MD_SHA384 #define DIGEST_ALGO_SHA512 GCRY_MD_SHA512 diff --git a/include/types.h b/include/types.h index 838897aa5..dff512061 100644 --- a/include/types.h +++ b/include/types.h @@ -101,7 +101,11 @@ typedef unsigned long u32; */ #ifndef HAVE_U64_TYPEDEF #undef u64 /* maybe there is a macro with this name */ -#if SIZEOF_UNSIGNED_INT == 8 +#if SIZEOF_UINT64_T == 8 +typedef uint64_t u64; +#define U64_C(c) (UINT64_C(c)) +#define HAVE_U64_TYPEDEF +#elif SIZEOF_UNSIGNED_INT == 8 typedef unsigned int u64; #define U64_C(c) (c ## U) #define HAVE_U64_TYPEDEF @@ -113,10 +117,6 @@ typedef unsigned long u64; typedef unsigned long long u64; #define U64_C(c) (c ## ULL) #define HAVE_U64_TYPEDEF -#elif SIZEOF_UINT64_T == 8 -typedef uint64_t u64; -#define U64_C(c) (UINT64_C(c)) -#define HAVE_U64_TYPEDEF #endif #endif -- cgit v1.2.3 From 791e69e3e9f64eedc42c87e90fb4f04ce47a53bf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 24 Sep 2003 08:31:16 +0000 Subject: (print_isoname,card_status): Handle opt.with_colons. (print_sha1_fpr_colon): New. --- g10/ChangeLog | 5 ++ g10/card-util.c | 198 ++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 154 insertions(+), 49 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index ac7a69468..4d7d26d30 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2003-09-24 Werner Koch <wk@gnupg.org> + + * card-util.c (print_isoname,card_status): Handle opt.with_colons. + (print_sha1_fpr_colon): New. + 2003-09-23 Werner Koch <wk@gnupg.org> Merged most of David Shaw's changes in 1.3 since 2003-06-03. diff --git a/g10/card-util.c b/g10/card-util.c index 99b40e9df..9b82e99ea 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -117,6 +117,7 @@ change_pin (int chvno) 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: @@ -147,13 +148,27 @@ print_sha1_fpr (FILE *fp, const unsigned char *fpr) } +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, text); - /* FIXME: tty_printf_utf8_string2 east everything after and + /* FIXME: tty_printf_utf8_string2 eats everything after and including an @ - e.g. when printing an url. */ if (name && *name) { @@ -168,9 +183,12 @@ print_name (FILE *fp, const char *text, const char *name) } static void -print_isoname (FILE *fp, const char *text, const char *name) +print_isoname (FILE *fp, const char *text, const char *tag, const char *name) { - tty_fprintf (fp, text); + if (opt.with_colons) + fprintf (fp, "%s:", tag); + else + tty_fprintf (fp, text); if (name && *name) { @@ -184,22 +202,39 @@ print_isoname (FILE *fp, const char *text, const char *name) { *given = 0; given += 2; - if (fp) + 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), '\n'); - if (*buf) + + if (opt.with_colons) + putc (':', fp); + else if (*buf) tty_fprintf (fp, " "); } - if (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), '\n'); xfree (buf); } else - tty_fprintf (fp, _("[not set]")); - tty_fprintf (fp, "\n"); + { + if (opt.with_colons) + putc (':', fp); + else + tty_fprintf (fp, _("[not set]")); + } + + if (opt.with_colons) + fputs (":\n", fp); + else + tty_fprintf (fp, "\n"); } @@ -210,62 +245,119 @@ card_status (FILE *fp) struct agent_card_info_s info; PKT_public_key *pk = xcalloc (1, sizeof *pk); int rc; + unsigned int uval; 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; } - - tty_fprintf (fp, "Application ID ...: %s\n", - info.serialno? info.serialno : "[none]"); + + 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; } - 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: ", 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? _("cached"): _("not cached")); - 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 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 - fputs ("[none]\n", fp); - tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter); - + + 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? _("cached"): _("not cached")); + 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 + fputs ("[none]\n", fp); + } + free_public_key (pk); agent_release_card_info (&info); } @@ -506,8 +598,16 @@ card_edit (STRLIST commands) tty_printf("\n"); if (redisplay ) { - card_status (NULL); - tty_printf("\n"); + if (opt.with_colons) + { + card_status (stdout); + fflush (stdout); + } + else + { + card_status (NULL); + tty_printf("\n"); + } redisplay = 0; } -- cgit v1.2.3 From acd7f7c70d2d482ae175d4b25b2ad066ffac0822 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Fri, 26 Sep 2003 11:03:08 +0000 Subject: 2003-09-26 Timo Schulz <twoaday@freakmail.de> * card_status (card_status): Do not use fputs since the fp parameter can be NULL. This fixes a segv. --- g10/ChangeLog | 5 +++++ g10/card-util.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 4d7d26d30..f91bc6bcc 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2003-09-26 Timo Schulz <twoaday@freakmail.de> + + * card_status (card_status): Do not use fputs since the fp + parameter can be NULL. This fixes a segv. + 2003-09-24 Werner Koch <wk@gnupg.org> * card-util.c (print_isoname,card_status): Handle opt.with_colons. diff --git a/g10/card-util.c b/g10/card-util.c index 9b82e99ea..f42efde61 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -355,7 +355,7 @@ card_status (FILE *fp) if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) print_pubkey_info (fp, pk); else - fputs ("[none]\n", fp); + tty_fprintf (fp, "[none]\n"); } free_public_key (pk); -- cgit v1.2.3 From 5cf6152b4ce7a36e5d49e49ecb8ab642ff7d2509 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 30 Sep 2003 13:16:33 +0000 Subject: *** empty log message *** --- TODO | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO b/TODO index da337f247..11b887b9e 100644 --- a/TODO +++ b/TODO @@ -65,3 +65,8 @@ might want to have an agent context for each service request ** Return IMPORT_OK status. * Where is http.c, regcomp.c, srv.c, w32reg.c ? + +* scd/sc-investigate +** Enhance with card compatibility check + + -- cgit v1.2.3 From 3af881581faf505df3b40d5c8bff6bc0aaa125c5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 30 Sep 2003 13:22:33 +0000 Subject: Minor fixes --- g10/ChangeLog | 4 ++++ g10/sign.c | 38 +------------------------------------- scd/ChangeLog | 4 ++++ scd/app-openpgp.c | 2 +- 4 files changed, 10 insertions(+), 38 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f91bc6bcc..f8120230f 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2003-09-27 Werner Koch <wk@gnupg.org> + + * sign.c (do_sign): Removed disabled testcode. + 2003-09-26 Timo Schulz <twoaday@freakmail.de> * card_status (card_status): Do not use fputs since the fp diff --git a/g10/sign.c b/g10/sign.c index 640e36fe0..cd7615c00 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -307,43 +307,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, sig->digest_algo = digest_algo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; -#if 0 - if (sk->is_protected && sk->protect.s2k.mode == 1002 && !sk->is_primary) - { /* Temporary hack to test tey auth command. */ - char *rbuf; - size_t rbuflen; - char *snbuf; - char *tmpbuf; - size_t tmp_n; - - frame = encode_md_value( sk->pubkey_algo, md, - digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); - if (!frame) - return GPG_ERR_GENERAL; - - if (gcry_mpi_aprint (GCRYMPI_FMT_USG, (void **)&tmpbuf, &tmp_n, frame )) - BUG (); - for (; tmp_n && *tmpbuf; tmp_n--, tmpbuf++) - ; - assert (tmp_n); - tmp_n--; - tmpbuf++; - - snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); - rc = agent_scd_pksign (snbuf, 0, - tmpbuf, tmp_n, - &rbuf, &rbuflen); - xfree (snbuf); - if (!rc) - { - if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, - rbuf, rbuflen, NULL )) - BUG (); - } - } - else -#endif - if (sk->is_protected && sk->protect.s2k.mode == 1002) + if (sk->is_protected && sk->protect.s2k.mode == 1002) { /* FIXME: Note that we do only support RSA for now. */ char *rbuf; size_t rbuflen; diff --git a/scd/ChangeLog b/scd/ChangeLog index e8c4cc88b..a55707ad2 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2003-09-28 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (dump_all_do): Use gpg_err_code and not gpg_error. + 2003-09-19 Werner Koch <wk@gnupg.org> * ccid-driver.c (parse_ccid_descriptor): New. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 7f6114292..7a49edfe5 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -228,7 +228,7 @@ dump_all_do (int slot) continue; rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen); - if (gpg_error (rc) == GPG_ERR_NO_OBJ) + if (gpg_err_code (rc) == GPG_ERR_NO_OBJ) ; else if (rc) log_info ("DO `%s' not available: %s\n", -- cgit v1.2.3 From 316dc2fd60875bc102bd459a4b3d4a5a59086b02 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 30 Sep 2003 17:34:38 +0000 Subject: * keylist.c (print_card_serialno): New. (list_keyblock_print): Use it here. * card-util.c (toggle_forcesig): New. (card_edit): New command "forcesig". * card-util.c (print_name, print_isoname): Use 0 and not LF fro the max_n arg of tty_print_utf8_string2. * call-agent.c (agent_scd_getattr): New. (learn_status_cb): Release values before assignment so that it can be used by getattr to update the structure. * card-util.c (change_pin): Simplified. We now have only a PIN and an Admin PIN. --- g10/ChangeLog | 18 +++++++++++++ g10/call-agent.c | 42 +++++++++++++++++++++++++---- g10/call-agent.h | 3 +++ g10/card-util.c | 81 +++++++++++++++++++++++++++++++++++++------------------- g10/keylist.c | 41 ++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+), 32 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f8120230f..0e0e715fc 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,21 @@ +2003-09-30 Werner Koch <wk@gnupg.org> + + * keylist.c (print_card_serialno): New. + (list_keyblock_print): Use it here. + + * card-util.c (toggle_forcesig): New. + (card_edit): New command "forcesig". + + * card-util.c (print_name, print_isoname): Use 0 and not LF fro + the max_n arg of tty_print_utf8_string2. + + * call-agent.c (agent_scd_getattr): New. + (learn_status_cb): Release values before assignment so that it can + be used by getattr to update the structure. + + * card-util.c (change_pin): Simplified. We now have only a PIN + and an Admin PIN. + 2003-09-27 Werner Koch <wk@gnupg.org> * sign.c (do_sign): Removed disabled testcode. diff --git a/g10/call-agent.c b/g10/call-agent.c index 00d124f0b..f07c01f2a 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -479,14 +479,17 @@ learn_status_cb (void *opaque, const char *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)) @@ -495,10 +498,12 @@ learn_status_cb (void *opaque, const char *line) } 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)) @@ -574,6 +579,34 @@ agent_learn (struct agent_card_info_s *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; + + memset (info, 0, sizeof *info); + 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 @@ -809,12 +842,11 @@ agent_scd_pkdecrypt (const char *serialno, /* Change the PIN of an OpenPGP card or reset the retry counter. - CHVNO 1: Change the digital signature PIN - 2: Change the decryption and authentication PIN + CHVNO 1: Change the PIN + 2: Same as 1 3: Change the admin PIN - 101: Set a new digital signature PIN and reset the retry counter - 102: Set a decryption and authentication PIN - and reset the retry counter + 101: Set a new PIN and reset the retry counter + 102: Same as 101 */ int agent_scd_change_pin (int chvno) diff --git a/g10/call-agent.h b/g10/call-agent.h index e8abfbc7b..101db9574 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -58,6 +58,9 @@ 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); diff --git a/g10/card-util.c b/g10/card-util.c index f42efde61..1028cd373 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -44,7 +44,6 @@ change_pin (int chvno) { struct agent_card_info_s info; int rc; - int reset_mode = 0; rc = agent_learn (&info); if (rc) @@ -70,17 +69,11 @@ change_pin (int chvno) char *answer; tty_printf ("\n"); - tty_printf ("1 - change signature PIN\n" - "2 - change decryption and authentication PIN\n" - "3 - change Admin's PIN\n" - "R - toggle reset retry counter mode\n" + tty_printf ("1 - change PIN\n" + "2 - unblock PIN\n" + "3 - change Admin PIN\n" "Q - quit\n"); tty_printf ("\n"); - if (reset_mode) - { - tty_printf ("Reset Retry Counter mode active\n"); - tty_printf ("\n"); - } answer = cpr_get("cardutil.change_pin.menu",_("Your selection? ")); cpr_kill_prompt(); @@ -88,30 +81,35 @@ change_pin (int chvno) continue; rc = 0; - if (reset_mode && *answer == '3') + if (*answer == '1') { - tty_printf ("Sorry, reset of the Admin PIN's retry counter " - "is not possible.\n"); + 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 == '1' || *answer == '2' || *answer == '3') + else if (*answer == '2') { - rc = agent_scd_change_pin (*answer - '0' + (reset_mode?100:0)); + rc = agent_scd_change_pin (101); if (rc) - tty_printf ("Error changing/resetting the PIN: %s\n", - gpg_strerror (rc)); + tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("New PIN successfully set.\n"); + tty_printf ("PIN unblocked and new PIN set.\n"); } - else if (*answer == 'r' || *answer == 'R') + else if (*answer == '3') { - reset_mode = !reset_mode; + 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 * @@ -175,7 +173,7 @@ print_name (FILE *fp, const char *text, const char *name) if (fp) print_utf8_string2 (fp, name, strlen (name), '\n'); else - tty_print_utf8_string2 (name, strlen (name), '\n'); + tty_print_utf8_string2 (name, strlen (name), 0); } else tty_fprintf (fp, _("[not set]")); @@ -207,7 +205,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) else if (fp) print_utf8_string2 (fp, given, strlen (given), '\n'); else - tty_print_utf8_string2 (given, strlen (given), '\n'); + tty_print_utf8_string2 (given, strlen (given), 0); if (opt.with_colons) putc (':', fp); @@ -220,7 +218,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) else if (fp) print_utf8_string2 (fp, buf, strlen (buf), '\n'); else - tty_print_utf8_string2 (buf, strlen (buf), '\n'); + tty_print_utf8_string2 (buf, strlen (buf), 0); xfree (buf); } else @@ -339,7 +337,7 @@ card_status (FILE *fp) 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? _("cached"): _("not cached")); + 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", @@ -542,6 +540,30 @@ change_sex (void) } +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)); +} + + + /* Menu to edit all user changeable values on an OpenPGP card. Only Key creation is not handled here. */ void @@ -551,7 +573,7 @@ card_edit (STRLIST commands) cmdNOP = 0, cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, - + cmdFORCESIG, cmdINVCMD }; @@ -572,9 +594,10 @@ card_edit (STRLIST commands) { 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") }, { NULL, cmdINVCMD } }; - + enum cmdids cmd = cmdNOP; int have_commands = !!commands; int redisplay = 1; @@ -692,6 +715,10 @@ card_edit (STRLIST commands) change_sex (); break; + case cmdFORCESIG: + toggle_forcesig (); + break; + case cmdQUIT: goto leave; diff --git a/g10/keylist.c b/g10/keylist.c index f4344f204..50850de71 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -41,6 +41,7 @@ static void list_all(int); static void list_one( STRLIST names, int secret); +static void print_card_serialno (PKT_secret_key *sk); struct sig_stats { @@ -710,6 +711,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) if( !any ) { if( fpr ) print_fingerprint( pk, sk, 0 ); + print_card_serialno (sk); if( opt.with_key_data ) print_key_data( pk, keyid ); any = 1; @@ -755,6 +757,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) putchar('\n'); if( fpr ) print_fingerprint( pk, sk, 0 ); /* of the main key */ + print_card_serialno (sk); any = 1; } @@ -770,7 +773,10 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) printf(_(" [expires: %s]"), expirestr_from_sk( sk2 ) ); putchar('\n'); if( fpr > 1 ) + { print_fingerprint( NULL, sk2, 0 ); + print_card_serialno (sk); + } } else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; @@ -813,6 +819,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) putchar('\n'); if( fpr ) print_fingerprint( pk, sk, 0 ); + print_card_serialno (sk); any=1; } @@ -1398,6 +1405,40 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) tty_printf ("\n"); } + +/* Print the serial number of an OpenPGP card if available. */ +static void +print_card_serialno (PKT_secret_key *sk) +{ + int i; + + if (!sk) + return; + if (!sk->is_protected || sk->protect.s2k.mode != 1002) + return; /* Not a card. */ + if (opt.with_colons) + return; /* Format not yet defined. */ + + fputs (_(" Card serial no. ="), stdout); + putchar (' '); + if (sk->protect.ivlen == 16 + && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6) ) + { /* This is an OpenPGP card. Just print the relevant part. */ + for (i=8; i < 14; i++) + { + if (i == 10) + putchar (' '); + printf ("%02X", sk->protect.iv[i]); + } + } + else + { /* Something is wrong: Print all. */ + for (i=0; i < sk->protect.ivlen; i++) + printf ("%02X", sk->protect.iv[i]); + } + putchar ('\n'); +} + void set_attrib_fd(int fd) { static int last_fd=-1; -- cgit v1.2.3 From 59a61b3c93f6a109f1e1bfe94fd0ab4a28169a9e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 30 Sep 2003 17:35:05 +0000 Subject: * command.c (cmd_getattr): New command GETATTR. * app.c (app_setattr): New. (do_getattr): New. (do_learn_status): Reimplemented in terms of do_getattr. * app-openpgp.c (do_change_pin): Make sure CVH1 and CHV2 are always synced. (verify_chv2, verify_chv3): New. Factored out common code. (do_setattr, do_sign, do_auth, do_decipher): Change the names of the prompts to match that we have only 2 different PINs. (app_select_openpgp): Check whether the card enforced CHV1. (convert_sig_counter_value): New. Factor out code from get_sig_counter. --- scd/ChangeLog | 16 ++ scd/app-common.h | 3 + scd/app-openpgp.c | 483 ++++++++++++++++++++++++++++-------------------------- scd/app.c | 13 ++ scd/command.c | 36 ++++ 5 files changed, 321 insertions(+), 230 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index a55707ad2..4363888c6 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,19 @@ +2003-09-30 Werner Koch <wk@gnupg.org> + + * command.c (cmd_getattr): New command GETATTR. + * app.c (app_setattr): New. + (do_getattr): New. + (do_learn_status): Reimplemented in terms of do_getattr. + + * app-openpgp.c (do_change_pin): Make sure CVH1 and CHV2 are + always synced. + (verify_chv2, verify_chv3): New. Factored out common code. + (do_setattr, do_sign, do_auth, do_decipher): Change the names of + the prompts to match that we have only 2 different PINs. + (app_select_openpgp): Check whether the card enforced CHV1. + (convert_sig_counter_value): New. Factor out code from + get_sig_counter. + 2003-09-28 Werner Koch <wk@gnupg.org> * app-openpgp.c (dump_all_do): Use gpg_err_code and not gpg_error. diff --git a/scd/app-common.h b/scd/app-common.h index 1243ca3ec..e4b9d2f6c 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -31,10 +31,12 @@ struct app_ctx_s { size_t serialnolen; /* Length in octets of serialnumber. */ unsigned int card_version; int did_chv1; + int force_chv1; /* True if the card does not cache CHV1. */ int did_chv2; int did_chv3; struct { int (*learn_status) (APP app, CTRL ctrl); + int (*getattr) (APP app, CTRL ctrl, const char *name); int (*setattr) (APP app, const char *name, int (*pincb)(void*, const char *, char **), void *pincb_arg, @@ -73,6 +75,7 @@ void app_set_default_reader_port (const char *portstr); APP select_application (void); int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); int app_write_learn_status (APP app, CTRL ctrl); +int app_getattr (APP app, CTRL ctrl, const char *name); int app_setattr (APP app, const char *name, int (*pincb)(void*, const char *, char **), void *pincb_arg, diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 7a49edfe5..3a312696b 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -61,6 +61,8 @@ static struct { }; +static unsigned long convert_sig_counter_value (const unsigned char *value, + size_t valuelen); static unsigned long get_sig_counter (APP app); @@ -390,80 +392,165 @@ send_key_data (CTRL ctrl, const char *name, xfree (buf); } - - -static int -do_learn_status (APP app, CTRL ctrl) +/* Implement the GETATTR command. This is similar to the LEARN + command but returns just one value via the status interface. */ +static int +do_getattr (APP app, CTRL ctrl, const char *name) { + static struct { + const char *name; + int tag; + int special; + } table[] = { + { "DISP-NAME", 0x005B }, + { "LOGIN-DATA", 0x005E }, + { "DISP-LANG", 0x5F2D }, + { "DISP-SEX", 0x5F35 }, + { "PUBKEY-URL", 0x5F50 }, + { "KEY-FPR", 0x00C5, 3 }, + { "CA-FPR", 0x00C6, 3 }, + { "CHV-STATUS", 0x00C4, 1 }, + { "SIG-COUNTER", 0x0093, 2 }, + { NULL, 0 } + }; + int idx, i; void *relptr; unsigned char *value; size_t valuelen; - int i; - relptr = get_one_do (app->slot, 0x005B, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "DISP-NAME", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x5F2D, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "DISP-LANG", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x5F35, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "DISP-SEX", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "PUBKEY-URL", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x005E, &value, &valuelen); + for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++) + ; + if (!table[idx].name) + return gpg_error (GPG_ERR_INV_NAME); + + relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen); if (relptr) { - send_status_info (ctrl, "LOGIN-DATA", value, valuelen, NULL, 0); + if (table[idx].special == 1) + { + char numbuf[7*23]; + + for (i=0,*numbuf=0; i < valuelen && i < 7; i++) + sprintf (numbuf+strlen (numbuf), " %d", value[i]); + send_status_info (ctrl, table[idx].name, + numbuf, strlen (numbuf), NULL, 0); + } + else if (table[idx].special == 2) + { + char numbuf[50]; + + sprintf (numbuf, "%lu", convert_sig_counter_value (value, valuelen)); + send_status_info (ctrl, table[idx].name, + numbuf, strlen (numbuf), NULL, 0); + } + else if (table[idx].special == 3) + { + if (valuelen >= 60) + for (i=0; i < 3; i++) + send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20); + } + else + send_status_info (ctrl, table[idx].name, value, valuelen, NULL, 0); + xfree (relptr); } + return 0; +} - relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen); - if (relptr && valuelen >= 60) - { - for (i=0; i < 3; i++) - send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20); - } - xfree (relptr); - relptr = get_one_do (app->slot, 0x00C6, &value, &valuelen); - if (relptr && valuelen >= 60) - { - for (i=0; i < 3; i++) - send_fpr_if_not_null (ctrl, "CA-FPR", i+1, value+i*20); - } - xfree (relptr); - relptr = get_one_do (app->slot, 0x00C4, &value, &valuelen); - if (relptr) + +static int +do_learn_status (APP app, CTRL ctrl) +{ + do_getattr (app, ctrl, "DISP-NAME"); + do_getattr (app, ctrl, "DISP-LANG"); + do_getattr (app, ctrl, "DISP-SEX"); + do_getattr (app, ctrl, "PUBKEY-URL"); + do_getattr (app, ctrl, "LOGIN-DATA"); + do_getattr (app, ctrl, "KEY-FPR"); + do_getattr (app, ctrl, "CA-FPR"); + do_getattr (app, ctrl, "CHV-STATUS"); + do_getattr (app, ctrl, "SIG-COUNTER"); + + return 0; +} + + +/* Verify CHV2 if required. Depending on the configuration of the + card CHV1 will also be verified. */ +static int +verify_chv2 (APP app, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc = 0; + + if (!app->did_chv2) { - char numbuf[7*23]; + char *pinvalue; - for (i=0,*numbuf=0; i < valuelen && i < 7; i++) - sprintf (numbuf+strlen (numbuf), " %d", value[i]); - send_status_info (ctrl, "CHV-STATUS", numbuf, strlen (numbuf), NULL, 0); - xfree (relptr); + rc = pincb (pincb_arg, "PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + if (rc) + { + log_error ("verify CHV2 failed: %s\n", gpg_strerror (rc)); + xfree (pinvalue); + return rc; + } + app->did_chv2 = 1; + + if (!app->did_chv1 && !app->force_chv1) + { + rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); + if (gpg_err_code (rc) == GPG_ERR_BAD_PIN) + rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); + if (rc) + { + log_error ("verify CHV1 failed: %s\n", gpg_strerror (rc)); + xfree (pinvalue); + return rc; + } + app->did_chv1 = 1; + } + xfree (pinvalue); } + return rc; +} - { - unsigned long ul = get_sig_counter (app); - char numbuf[23]; +/* Verify CHV3 if required. */ +static int +verify_chv3 (APP app, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc = 0; - sprintf (numbuf, "%lu", ul); - send_status_info (ctrl, "SIG-COUNTER", numbuf, strlen (numbuf), NULL, 0); - } - return 0; + if (!app->did_chv3) + { + char *pinvalue; + + rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); + return rc; + } + app->did_chv3 = 1; + } + return rc; } @@ -499,41 +586,18 @@ do_setattr (APP app, const char *name, if (!table[idx].name) return gpg_error (GPG_ERR_INV_NAME); - if (!app->did_chv3) - { - char *pinvalue; - - rc = pincb (pincb_arg, "Admin PIN (CHV3)", - &pinvalue); -/* pinvalue = xstrdup ("12345678"); */ -/* rc = 0; */ - if (rc) - { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); - return rc; - } - - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); - rc = gpg_error (GPG_ERR_GENERAL); - return rc; - } - app->did_chv3 = 1; - } + rc = verify_chv3 (app, pincb, pincb_arg); + if (rc) + return rc; rc = iso7816_put_data (app->slot, table[idx].tag, value, valuelen); if (rc) log_error ("failed to set `%s': %s\n", table[idx].name, gpg_strerror (rc)); - /* FIXME: If this fails we should *once* try again after - doing a verify command, so that in case of a problem with - tracking the verify operation we have a fallback. */ return rc; } + /* Handle the PASSWD command. */ static int do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, @@ -551,51 +615,25 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, } else if (reset_mode || chvno == 3) { - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); - if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - goto leave; - } - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } - } - else if (chvno == 1) - { - rc = pincb (pincb_arg, "Signature PIN", &pinvalue); + /* we always require that the PIN is entered. */ + app->did_chv3 = 0; + rc = verify_chv3 (app, pincb, pincb_arg); if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - goto leave; - } - rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV1 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; } - else if (chvno == 2) + else if (chvno == 1 || chvno == 2) { - rc = pincb (pincb_arg, "Decryption PIN", &pinvalue); + /* CHV1 and CVH2 should always have the same value, thus we + enforce it here. */ + int save_force = app->force_chv1; + + app->force_chv1 = 0; + app->did_chv1 = 0; + app->did_chv2 = 0; + rc = verify_chv2 (app, pincb, pincb_arg); + app->force_chv1 = save_force; if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - goto leave; - } - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV2 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; } else { @@ -603,10 +641,12 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, goto leave; } - - rc = pincb (pincb_arg, chvno == 1? "New Signature PIN" : - chvno == 2? "New Decryption PIN" : - chvno == 3? "New Admin PIN" : "?", &pinvalue); + if (chvno == 3) + app->did_chv3 = 0; + else + app->did_chv1 = app->did_chv2 = 0; + + rc = pincb (pincb_arg, chvno == 3? "New Admin PIN" : "New PIN", &pinvalue); if (rc) { log_error ("error getting new PIN: %s\n", gpg_strerror (rc)); @@ -614,12 +654,27 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, } if (reset_mode) - rc = iso7816_reset_retry_counter (app->slot, 0x80 + chvno, - pinvalue, strlen (pinvalue)); - else - rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, - NULL, 0, + { + rc = iso7816_reset_retry_counter (app->slot, 0x81, pinvalue, strlen (pinvalue)); + if (!rc) + rc = iso7816_reset_retry_counter (app->slot, 0x82, + pinvalue, strlen (pinvalue)); + } + else + { + if (chvno == 1 || chvno == 2) + { + rc = iso7816_change_reference_data (app->slot, 0x81, NULL, 0, + pinvalue, strlen (pinvalue)); + if (!rc) + rc = iso7816_change_reference_data (app->slot, 0x82, NULL, 0, + pinvalue, strlen (pinvalue)); + } + else + rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, NULL, 0, + pinvalue, strlen (pinvalue)); + } xfree (pinvalue); @@ -679,22 +734,10 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, else log_info ("generating new key\n"); - { - char *pinvalue; - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); - if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - return rc; - } - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - } + + rc = verify_chv3 (app, pincb, pincb_arg); if (rc) - { - log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; xfree (buffer); buffer = NULL; #if 1 @@ -765,16 +808,10 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, static unsigned long -get_sig_counter (APP app) +convert_sig_counter_value (const unsigned char *value, size_t valuelen) { - void *relptr; - unsigned char *value; - size_t valuelen; unsigned long ul; - relptr = get_one_do (app->slot, 0x0093, &value, &valuelen); - if (!relptr) - return 0; if (valuelen == 3 ) ul = (value[0] << 16) | (value[1] << 8) | value[2]; else @@ -782,6 +819,21 @@ get_sig_counter (APP app) log_error ("invalid structure of OpenPGP card (DO 0x93)\n"); ul = 0; } + return ul; +} + +static unsigned long +get_sig_counter (APP app) +{ + void *relptr; + unsigned char *value; + size_t valuelen; + unsigned long ul; + + relptr = get_one_do (app->slot, 0x0093, &value, &valuelen); + if (!relptr) + return 0; + ul = convert_sig_counter_value (value, valuelen); xfree (relptr); return ul; } @@ -914,21 +966,17 @@ do_sign (APP app, const char *keyidstr, int hashalgo, sigcount = get_sig_counter (app); log_info ("signatures created so far: %lu\n", sigcount); - /* FIXME: Check whether we are really required to enter the PIN for - each signature. There is a DO for this. */ - if (!app->did_chv1 || 1) + if (!app->did_chv1 || app->force_chv1 ) { char *pinvalue; { char *prompt; - if (asprintf (&prompt, "Signature PIN [sigs done: %lu]", sigcount) < 0) + if (asprintf (&prompt, "PIN [sigs done: %lu]", sigcount) < 0) return gpg_error_from_errno (errno); rc = pincb (pincb_arg, prompt, &pinvalue); free (prompt); } -/* pinvalue = xstrdup ("123456"); */ -/* rc = 0; */ if (rc) { log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); @@ -936,14 +984,28 @@ do_sign (APP app, const char *keyidstr, int hashalgo, } rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); - xfree (pinvalue); if (rc) { log_error ("verify CHV1 failed\n"); - rc = gpg_error (GPG_ERR_GENERAL); + xfree (pinvalue); return rc; } app->did_chv1 = 1; + if (!app->did_chv2) + { + /* We should also verify CHV2. */ + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + if (gpg_err_code (rc) == GPG_ERR_BAD_PIN) + rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); + if (rc) + { + log_error ("verify CHV2 failed\n"); + xfree (pinvalue); + return rc; + } + app->did_chv2 = 1; + } + xfree (pinvalue); } rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); @@ -1024,30 +1086,10 @@ do_auth (APP app, const char *keyidstr, return rc; } - if (!app->did_chv2) - { - char *pinvalue; - - rc = pincb (pincb_arg, "Authentication/Decryption PIN", &pinvalue); - if (rc) - { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); - return rc; - } - - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV2 failed\n"); - rc = gpg_error (GPG_ERR_GENERAL); - return rc; - } - app->did_chv2 = 1; - } - - rc = iso7816_internal_authenticate (app->slot, indata, indatalen, - outdata, outdatalen); + rc = verify_chv2 (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_internal_authenticate (app->slot, indata, indatalen, + outdata, outdatalen); return rc; } @@ -1114,31 +1156,9 @@ do_decipher (APP app, const char *keyidstr, return rc; } - if (!app->did_chv2) - { - char *pinvalue; - - rc = pincb (pincb_arg, "Decryption PIN", &pinvalue); -/* pinvalue = xstrdup ("123456"); */ -/* rc = 0; */ - if (rc) - { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); - return rc; - } - - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV2 failed\n"); - rc = gpg_error (GPG_ERR_GENERAL); - return rc; - } - app->did_chv2 = 1; - } - - rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen); + rc = verify_chv2 (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen); return rc; } @@ -1155,10 +1175,15 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) int rc; unsigned char *buffer; size_t buflen; + void *relptr; rc = iso7816_select_application (slot, aid, sizeof aid); if (!rc) { + app->did_chv1 = 0; + app->did_chv2 = 0; + app->did_chv3 = 0; + rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); if (rc) goto leave; @@ -1178,10 +1203,20 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) else xfree (buffer); + relptr = get_one_do (app->slot, 0x00C4, &buffer, &buflen); + if (!relptr) + { + log_error ("can't access CHV Status Bytes - invalid OpenPGP card?\n"); + goto leave; + } + app->force_chv1 = (buflen && *buffer == 0); + xfree (relptr); + if (opt.verbose > 1) dump_all_do (slot); app->fnc.learn_status = do_learn_status; + app->fnc.getattr = do_getattr; app->fnc.setattr = do_setattr; app->fnc.genkey = do_genkey; app->fnc.sign = do_sign; @@ -1306,22 +1341,10 @@ app_openpgp_storekey (APP app, int keyno, return gpg_error (GPG_ERR_INV_ID); keyno--; - { - char *pinvalue; - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); - if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - return rc; - } - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - } + rc = verify_chv3 (app, pincb, pincb_arg); if (rc) - { - log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; + rc = iso7816_put_data (app->slot, (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, diff --git a/scd/app.c b/scd/app.c index fa5df8a72..5b0340b89 100644 --- a/scd/app.c +++ b/scd/app.c @@ -125,6 +125,19 @@ app_write_learn_status (APP app, CTRL ctrl) } +/* Perform a GETATTR operation. */ +int +app_getattr (APP app, CTRL ctrl, const char *name) +{ + if (!app || !name || !*name) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.getattr) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + return app->fnc.getattr (app, ctrl, name); +} + /* Perform a SETATTR operation. */ int app_setattr (APP app, const char *name, diff --git a/scd/command.c b/scd/command.c index 9f242bfab..fc5efa708 100644 --- a/scd/command.c +++ b/scd/command.c @@ -702,6 +702,41 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) } +/* GETATTR <name> + + This command is used to retrieve data from a smartcard. The + allowed names depend on the currently selected smartcard + application. NAME must be percent and '+' escaped. The value is + returned through status message, see the LESRN command for details. + + However, the current implementation assumes that Name is not escaped; + this works as long as noone uses arbitrary escaping. + +*/ +static int +cmd_getattr (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *keyword; + + if ((rc = open_card (ctrl))) + return rc; + + keyword = line; + for (; *line && !spacep (line); line++) + ; + if (*line) + *line++ = 0; + + /* (We ignore any garbage for now.) */ + + rc = app_getattr (ctrl->app_ctx, ctrl, keyword); + + return map_to_assuan_status (rc); +} + + /* SETATTR <name> <value> This command is used to store data on a a smartcard. The allowed @@ -908,6 +943,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "PKDECRYPT", cmd_pkdecrypt }, { "INPUT", NULL }, { "OUTPUT", NULL }, + { "GETATTR", cmd_getattr }, { "SETATTR", cmd_setattr }, { "GENKEY", cmd_genkey }, { "RANDOM", cmd_random }, -- cgit v1.2.3 From f194ebc782424053896734699c2fc70b5ff0f14a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 2 Oct 2003 10:27:34 +0000 Subject: Fixes to make inclusion of card raleted source files into 1.3 easier. --- ChangeLog | 4 ++++ configure.ac | 5 +++++ g10/ChangeLog | 6 +++++- g10/card-util.c | 6 ++++++ scd/ChangeLog | 11 +++++++++++ scd/apdu.c | 13 +++++++++++++ scd/app-common.h | 6 ++++++ scd/app-openpgp.c | 18 ++++++++++++++++-- scd/ccid-driver.c | 13 ++++++++++--- scd/iso7816.c | 20 ++++++++++++++++---- scd/iso7816.h | 4 ++++ 11 files changed, 96 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index ce3d76967..d2e219c90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/configure.ac b/configure.ac index 23baee44a..12ff0d703 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,11 @@ AH_BOTTOM([ /* Tell libgcrypt not to use its own libgpg-error implementation. */ #define USE_LIBGPG_ERROR 1 +/* This is the major version number of GnuPG so that + source included files can test for this. Note, that\ + we use 2 here even for GnuPG 1.9.x. */ +#define GNUPG_MAJOR_VERSION 2 + #include "g10defs.h" ]) diff --git a/g10/ChangeLog b/g10/ChangeLog index 0e0e715fc..563c71eee 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2003-10-01 Werner Koch <wk@gnupg.org> + + * card-util.c: Tweaked to use this source also under 1.3. + 2003-09-30 Werner Koch <wk@gnupg.org> * keylist.c (print_card_serialno): New. @@ -407,7 +411,7 @@ * card-util.c (card_status): New. * call-agent.c (learn_status_cb): Parse more information. - * keylist.c (print_pubkey_info): Add FP arg for optinal printing + * keylist.c (print_pubkey_info): Add FP arg for optional printing to a stream. Changed all callers. 2003-07-23 Werner Koch <wk@gnupg.org> diff --git a/g10/card-util.c b/g10/card-util.c index 1028cd373..70518e9ce 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -25,14 +25,20 @@ #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) diff --git a/scd/ChangeLog b/scd/ChangeLog index 4363888c6..f090e34c0 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,14 @@ +2003-10-01 Werner Koch <wk@gnupg.org> + + * ccid-driver.c: Detect GnuPG 1.3 and include appropriate files. + * apdu.c: Ditto. + * app-openpgp.c: Ditto. + * iso7816.c: Ditto. + (generate_keypair): Renamed to .. + (do_generate_keypair): .. this. + * app-common.h [GNUPG_MAJOR_VERSION]: New. + * iso7816.h [GNUPG_MAJOR_VERSION]: Include cardglue.h + 2003-09-30 Werner Koch <wk@gnupg.org> * command.c (cmd_getattr): New command GETATTR. diff --git a/scd/apdu.c b/scd/apdu.c index d5f64c6d8..d5b93de6e 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -28,7 +28,20 @@ # include <opensc/opensc.h> #endif +#if GNUPG_MAJOR_VERSION == 1 +/* This is used with GnuPG version < 1.9. The code has been source + copied from the current GnuPG >= 1.9 and is maintained over + there. */ +#include "options.h" +#include "errors.h" +#include "memory.h" +#include "util.h" +#include "i18n.h" +#include "cardglue.h" +#else /* GNUPG_MAJOR_VERSION != 1 */ #include "scdaemon.h" +#endif /* GNUPG_MAJOR_VERSION != 1 */ + #include "apdu.h" #include "dynload.h" #include "ccid-driver.h" diff --git a/scd/app-common.h b/scd/app-common.h index e4b9d2f6c..33f23127b 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -70,6 +70,10 @@ struct app_ctx_s { }; +#if GNUPG_MAJOR_VERSION == 1 +int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen); +int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); +#else /*-- app.c --*/ void app_set_default_reader_port (const char *portstr); APP select_application (void); @@ -124,6 +128,8 @@ int app_openpgp_storekey (APP app, int keyno, int app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, unsigned char **e, size_t *elen); +#endif + #endif /*GNUPG_SCD_APP_COMMON_H*/ diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 3a312696b..e8fe19ea1 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -24,10 +24,24 @@ #include <stdlib.h> #include <string.h> #include <assert.h> - +#include <time.h> + +#if GNUPG_MAJOR_VERSION == 1 +/* This is used with GnuPG version < 1.9. The code has been source + copied from the current GnuPG >= 1.9 and is maintained over + there. */ +#include "options.h" +#include "errors.h" +#include "memory.h" +#include "util.h" +#include "i18n.h" +#include "cardglue.h" +#else /* GNUPG_MAJOR_VERSION != 1 */ #include "scdaemon.h" -#include "app-common.h" +#endif /* GNUPG_MAJOR_VERSION != 1 */ + #include "iso7816.h" +#include "app-common.h" diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index e0b48f880..b4fbc0b21 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -87,9 +87,16 @@ #define DRVNAME "ccid-driver: " -#ifdef GNUPG_DEFAULT_SCDAEMON /* This source is used within the - gnupg>=1.9 source tree. */ -# include "scdaemon.h" +#ifdef GNUPG_MAJOR_VERSION /* This source is used within GnuPG. */ + +# if GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */ +# include "options.h" +# include "util.h" +# include "memory.h" +# include "cardglue.h" +# else /* This is the modularized GnuPG 1.9 or later. */ +# include "scdaemon.h" +# endif # define DEBUGOUT(t) do { if (DBG_CARD_IO) \ log_debug (DRVNAME t); } while (0) diff --git a/scd/iso7816.c b/scd/iso7816.c index 2b06103ef..f4aa18c6f 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -24,10 +24,22 @@ #include <stdlib.h> #include <string.h> +#if GNUPG_MAJOR_VERSION == 1 +/* This is used with GnuPG version < 1.9. The code has been source + copied from the current GnuPG >= 1.9 and is maintained over + there. */ +#include "options.h" +#include "errors.h" +#include "memory.h" +#include "util.h" +#include "i18n.h" +#else /* GNUPG_MAJOR_VERSION != 1 */ #include "scdaemon.h" +#endif /* GNUPG_MAJOR_VERSION != 1 */ + #include "iso7816.h" #include "apdu.h" -#include "dynload.h" + #define CMD_SELECT_FILE 0xA4 #define CMD_VERIFY 0x20 @@ -290,7 +302,7 @@ iso7816_internal_authenticate (int slot, static gpg_error_t -generate_keypair (int slot, int readonly, +do_generate_keypair (int slot, int readonly, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen) { @@ -321,7 +333,7 @@ iso7816_generate_keypair (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen) { - return generate_keypair (slot, 0, data, datalen, result, resultlen); + return do_generate_keypair (slot, 0, data, datalen, result, resultlen); } @@ -330,7 +342,7 @@ iso7816_read_public_key (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen) { - return generate_keypair (slot, 1, data, datalen, result, resultlen); + return do_generate_keypair (slot, 1, data, datalen, result, resultlen); } diff --git a/scd/iso7816.h b/scd/iso7816.h index d7e77a101..26b8d6aba 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -21,6 +21,10 @@ #ifndef ISO7816_H #define ISO7816_H +#if GNUPG_MAJOR_VERSION == 1 +#include "cardglue.h" +#endif + gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen); gpg_error_t iso7816_verify (int slot, -- cgit v1.2.3 From 30342b06efcc779b9222513d8dbfb85436ab624c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 8 Oct 2003 10:46:58 +0000 Subject: * call-agent.c (agent_scd_getattr): Don't clear the passed info structure, so that it can indeed be updated. * card-util.c (fpr_is_zero): New. (generate_card_keys): New. (card_edit): New command "generate". * keygen.c (generate_keypair): New arg CARD_SERIALNO, removed call to check_smartcard. (check_smartcard,show_smartcard): Removed. (show_sha1_fpr,fpr_is_zero): Removed. * app-openpgp.c (do_getattr): Support SERIALNO and AID. --- NEWS | 5 ++ README | 4 ++ TODO | 1 + g10/ChangeLog | 13 ++++ g10/call-agent.c | 1 - g10/card-util.c | 88 ++++++++++++++++++++++++- g10/g10.c | 4 +- g10/keygen.c | 192 +++++------------------------------------------------- g10/main.h | 2 +- scd/ChangeLog | 4 ++ scd/app-openpgp.c | 25 +++++++ 11 files changed, 158 insertions(+), 181 deletions(-) diff --git a/NEWS b/NEWS index 558a5e8ac..b708d44cf 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ Noteworthy changes in version 1.9.2 (unreleased) ------------------------------------------------ + * 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. Noteworthy changes in version 1.9.1 (2003-09-06) diff --git a/README b/README index 8dea9dbb9..60b613362 100644 --- a/README +++ b/README @@ -47,6 +47,10 @@ gpg2: 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 diff --git a/TODO b/TODO index 11b887b9e..e8aa872a1 100644 --- a/TODO +++ b/TODO @@ -33,6 +33,7 @@ might want to have an agent context for each service request * sm/gpgsm.c ** Support --output ** mark all unimplemented commands and options. +** Print a hint when of MD2 is the cause for a problem. * sm/keydb.c ** Check file permissions diff --git a/g10/ChangeLog b/g10/ChangeLog index 563c71eee..cb5a8ad64 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,16 @@ +2003-10-08 Werner Koch <wk@gnupg.org> + + * call-agent.c (agent_scd_getattr): Don't clear the passed info + structure, so that it can indeed be updated. + + * card-util.c (fpr_is_zero): New. + (generate_card_keys): New. + (card_edit): New command "generate". + * keygen.c (generate_keypair): New arg CARD_SERIALNO, removed call + to check_smartcard. + (check_smartcard,show_smartcard): Removed. + (show_sha1_fpr,fpr_is_zero): Removed. + 2003-10-01 Werner Koch <wk@gnupg.org> * card-util.c: Tweaked to use this source also under 1.3. diff --git a/g10/call-agent.c b/g10/call-agent.c index f07c01f2a..c6c8faaec 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -600,7 +600,6 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info) if (rc) return rc; - memset (info, 0, sizeof *info); rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, learn_status_cb, info); diff --git a/g10/card-util.c b/g10/card-util.c index 70518e9ce..669927707 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -241,6 +241,17 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) 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 @@ -569,6 +580,76 @@ toggle_forcesig (void) } +static void +generate_card_keys (void) +{ + 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; + } + } + 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. */ @@ -579,7 +660,7 @@ card_edit (STRLIST commands) cmdNOP = 0, cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, - cmdFORCESIG, + cmdFORCESIG, cmdGENERATE, cmdINVCMD }; @@ -601,6 +682,7 @@ card_edit (STRLIST commands) { 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") }, { NULL, cmdINVCMD } }; @@ -725,6 +807,10 @@ card_edit (STRLIST commands) toggle_forcesig (); break; + case cmdGENERATE: + generate_card_keys (); + break; + case cmdQUIT: goto leave; diff --git a/g10/g10.c b/g10/g10.c index cdd10d845..984e50d9c 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -2555,12 +2555,12 @@ main( int argc, char **argv ) if( opt.batch ) { if( argc > 1 ) wrong_args("--gen-key [parameterfile]"); - generate_keypair( argc? *argv : NULL ); + generate_keypair( argc? *argv : NULL, NULL ); } else { if( argc ) wrong_args("--gen-key"); - generate_keypair(NULL); + generate_keypair(NULL, NULL); } break; diff --git a/g10/keygen.c b/g10/keygen.c index 38e9115b3..935cff330 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -117,7 +117,6 @@ static int mdc_available,ks_modify; static void do_generate_keypair( struct para_data_s *para, struct output_control_s *outctrl, int card); static int write_keyblock( iobuf_t out, KBNODE node ); -static int check_smartcard (char **); static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, u32 expireval, struct para_data_s *para); @@ -2219,11 +2218,12 @@ read_parameter_file( const char *fname ) /**************** - * Generate a keypair - * (fname is only used in batch mode) + * Generate a keypair (fname is only used in batch mode) If + * CARD_SERIALNO is not NULL the fucntion will create the keys on an + * OpenPGP Card. */ void -generate_keypair( const char *fname ) +generate_keypair( const char *fname, const char *card_serialno ) { unsigned int nbits; char *uid = NULL; @@ -2232,42 +2232,34 @@ generate_keypair( const char *fname ) int algo; unsigned int use; int both = 0; - int card = 0; u32 expire; struct para_data_s *para = NULL; struct para_data_s *r; struct output_control_s outctrl; - char *serialno = NULL; memset (&outctrl, 0, sizeof (outctrl)); - if (opt.batch) + if (opt.batch && card_serialno) { - read_parameter_file( fname ); + /* We don't yet support unattended key generation. */ + log_error (_("sorry, can't do this in batch mode\n")); return; } - do + if (opt.batch) { - xfree (serialno); serialno = NULL; - card = check_smartcard (&serialno); - if (card < 0) - return; + read_parameter_file( fname ); + return; } - while (card > 1); - if (serialno) + if (card_serialno) { - r = xcalloc (1, sizeof *r + strlen (serialno) ); + r = xcalloc (1, sizeof *r + strlen (card_serialno) ); r->key = pSERIALNO; - strcpy( r->u.value, serialno); + strcpy( r->u.value, card_serialno); r->next = para; para = r; - xfree (serialno); serialno = NULL; - } - if (card) - { algo = PUBKEY_ALGO_RSA; r = xcalloc (1, sizeof *r + 20 ); @@ -2388,7 +2380,7 @@ generate_keypair( const char *fname ) r->next = para; para = r; - dek = card? NULL : ask_passphrase( &s2k ); + dek = card_serialno? NULL : ask_passphrase( &s2k ); if (dek) { r = xcalloc (1, sizeof *r ); @@ -2403,7 +2395,7 @@ generate_keypair( const char *fname ) para = r; } - proc_parameter_file (para, "[internal]", &outctrl, card); + proc_parameter_file (para, "[internal]", &outctrl, !!card_serialno); release_parameter_list (para); } @@ -2719,7 +2711,7 @@ do_generate_keypair (struct para_data_s *para, release_kbnode (pub_root); release_kbnode (sec_root); if (sk && !card) /* The unprotected secret key unless we have */ - free_secret_key (sk); /* shallow copy in card mode. */ + free_secret_key (sk); /* a shallow copy in card mode. */ } @@ -2848,158 +2840,6 @@ write_keyblock( iobuf_t out, KBNODE node ) } -static void -show_sha1_fpr (const unsigned char *fpr) -{ - int i; - - if (fpr) - { - for (i=0; i < 20 ; i+=2, fpr += 2 ) - { - if (i == 10 ) - tty_printf (" "); - tty_printf (" %02X%02X", *fpr, fpr[1]); - } - } - else - tty_printf (" [none]"); - tty_printf ("\n"); -} - -static void -show_smartcard (struct agent_card_info_s *info) -{ - PKT_public_key *pk = xcalloc (1, sizeof *pk); - - /* FIXME: Sanitize what we show. */ - tty_printf ("Name of cardholder: %s\n", - info->disp_name && *info->disp_name? info->disp_name - : "[not set]"); - tty_printf ("URL of public key : %s\n", - info->pubkey_url && *info->pubkey_url? info->pubkey_url - : "[not set]"); - tty_printf ("Signature key ....:"); - show_sha1_fpr (info->fpr1valid? info->fpr1:NULL); - tty_printf ("Encryption key....:"); - show_sha1_fpr (info->fpr2valid? info->fpr2:NULL); - tty_printf ("Authentication key:"); - show_sha1_fpr (info->fpr3valid? info->fpr3:NULL); - - if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20)) - print_pubkey_info (NULL, pk); - - free_public_key( pk ); -} - -/* 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); -} - -/* Check whether a smartcatrd is available and alow to select it as - the target for key generation. - - Return values: -1 = Quit generation - 0 = No smartcard - 1 = Generate keypair -*/ -static int -check_smartcard (char **r_serialno) -{ - struct agent_card_info_s info; - int rc; - - rc = agent_learn (&info); - if (rc) - { - tty_printf (_("OpenPGP card not available: %s\n"), - gpg_strerror (rc)); - return 0; - } - - tty_printf (_("OpenPGP card no. %s detected\n"), - info.serialno? info.serialno : "[none]"); - - - for (;;) - { - char *answer; - int reread = 0; - - tty_printf ("\n"); - show_smartcard (&info); - - tty_printf ("\n" - "K - generate all keys\n" - "Q - quit\n" - "\n"); - - answer = cpr_get("keygen.smartcard.menu",_("Your selection? ")); - cpr_kill_prompt(); - if (strlen (answer) != 1) - continue; - - rc = 0; - if ( *answer == 'K' || *answer == 'k') - { - 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_error ("WARNING: key does already exists!\n"); - tty_printf ("\n"); - if ( cpr_get_answer_is_yes( "keygen.card.replace_key", - _("Replace existing key? "))) - { - rc = 1; - break; - } - } - else - { - rc = 1; - break; - } - } - else if ( *answer == 'q' || *answer == 'Q') - { - rc = -1; - break; - } - - if (reread) - { - agent_release_card_info (&info); - rc = agent_learn (&info); - if (rc) - { - tty_printf (_("OpenPGP card not anymore available: %s\n"), - gpg_strerror (rc)); - g10_exit (1); - } - reread = 0; - } - } - - if (r_serialno && rc > 0) - { - *r_serialno = info.serialno; - info.serialno = NULL; - } - agent_release_card_info (&info); - - return rc; -} - - static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, diff --git a/g10/main.h b/g10/main.h index 76562fa91..d00044c9f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -165,7 +165,7 @@ void show_basic_key_info (KBNODE keyblock); /*-- keygen.c --*/ u32 ask_expire_interval(int object); u32 ask_expiredate(void); -void generate_keypair( const char *fname ); +void generate_keypair( const char *fname, const char *card_serialno ); int keygen_set_std_prefs (const char *string,int personal); PKT_user_id *keygen_get_std_prefs (void); int keygen_add_key_expire( PKT_signature *sig, void *opaque ); diff --git a/scd/ChangeLog b/scd/ChangeLog index f090e34c0..86068b245 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2003-10-08 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (do_getattr): Support SERIALNO and AID. + 2003-10-01 Werner Koch <wk@gnupg.org> * ccid-driver.c: Detect GnuPG 1.3 and include appropriate files. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index e8fe19ea1..174d2e974 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -425,6 +425,8 @@ do_getattr (APP app, CTRL ctrl, const char *name) { "CA-FPR", 0x00C6, 3 }, { "CHV-STATUS", 0x00C4, 1 }, { "SIG-COUNTER", 0x0093, 2 }, + { "SERIALNO", 0x004F, -1 }, + { "AID", 0x004F }, { NULL, 0 } }; int idx, i; @@ -437,6 +439,29 @@ do_getattr (APP app, CTRL ctrl, const char *name) if (!table[idx].name) return gpg_error (GPG_ERR_INV_NAME); + if (table[idx].special == -1) + { + /* The serial number is very special. We could have used the + AID DO to retrieve it, but we have it already in the app + context and the stanmp argument is required anyway which we + can't by other means. The AID DO is available anyway but not + hex formatted. */ + char *serial; + time_t stamp; + char tmp[50]; + + if (!app_get_serial_and_stamp (app, &serial, &stamp)) + { + sprintf (tmp, "%lu", (unsigned long)stamp); + send_status_info (ctrl, "SERIALNO", + serial, strlen (serial), + tmp, strlen (tmp), + NULL, 0); + xfree (serial); + } + return 0; + } + relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen); if (relptr) { -- cgit v1.2.3 From 1bc1427e723810536c63d62b114428dde99fc210 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Oct 2003 15:18:08 +0000 Subject: * ccid-driver.c (ccid_transceive): Add T=1 chaining for sending. --- scd/ChangeLog | 4 +++ scd/ccid-driver.c | 102 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 74 insertions(+), 32 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 86068b245..f8ce674b8 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2003-10-09 Werner Koch <wk@gnupg.org> + + * ccid-driver.c (ccid_transceive): Add T=1 chaining for sending. + 2003-10-08 Werner Koch <wk@gnupg.org> * app-openpgp.c (do_getattr): Support SERIALNO and AID. diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index b4fbc0b21..35f0329db 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -132,6 +132,11 @@ #endif /* This source not used by scdaemon. */ +/* Define to print information pertaining the T=1 protocol. */ +#undef DEBUG_T1 1 + + + enum { RDR_to_PC_NotifySlotChange= 0x50, RDR_to_PC_HardwareError = 0x51, @@ -566,7 +571,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, return -1; } - DEBUGOUT_3 ("status: %02X error: %02X clock-status: %02X\n" + DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n" " data:", buffer[7], buffer[8], buffer[9] ); for (i=10; i < msglen; i++) DEBUGOUT_CONT_1 (" %02X", buffer[i]); @@ -753,44 +758,62 @@ ccid_get_atr (ccid_driver_t handle, int ccid_transceive (ccid_driver_t handle, - const unsigned char *apdu, size_t apdulen, + const unsigned char *apdu_buf, size_t apdu_buflen, unsigned char *resp, size_t maxresplen, size_t *nresp) { int rc; unsigned char send_buffer[10+258], recv_buffer[10+258]; + const unsigned char *apdu; + size_t apdulen; unsigned char *msg, *tpdu, *p; size_t msglen, tpdulen, n; unsigned char seqno; int i; unsigned char crc; size_t dummy_nresp; + int next_chunk = 1; int sending = 1; if (!nresp) nresp = &dummy_nresp; - *nresp = 0; - - /* Construct an I-Block. */ - if (apdulen > 254) - return -1; /* Invalid length. */ + tpdulen = 0; /* Avoid compiler warning about no initialization. */ msg = send_buffer; + for (;;) + { + if (next_chunk) + { + next_chunk = 0; - tpdu = msg+10; - tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ - tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */ - tpdu[2] = apdulen; - memcpy (tpdu+3, apdu, apdulen); - crc = 0; - for (i=0,p=tpdu; i < apdulen+3; i++) - crc ^= *p++; - tpdu[3+apdulen] = crc; + apdu = apdu_buf; + apdulen = apdu_buflen; + assert (apdulen); - tpdulen = apdulen + 4; + /* Construct an I-Block. */ + if (apdulen > 254) + return -1; /* Invalid length. */ + + tpdu = msg+10; + tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */ + if (apdulen > 128 /* fixme: replace by ifsc */) + { + apdulen = 128; + apdu_buf += 128; + apdu_buflen -= 128; + tpdu[1] |= (1 << 5); /* Set more bit. */ + } + tpdu[2] = apdulen; + memcpy (tpdu+3, apdu, apdulen); + crc = 0; + for (i=0,p=tpdu; i < apdulen+3; i++) + crc ^= *p++; + tpdu[3+apdulen] = crc; + + tpdulen = apdulen + 4; + } - for (;;) - { msg[0] = PC_to_RDR_XfrBlock; msg[5] = 0; /* slot */ msg[6] = seqno = handle->seqno++; @@ -804,12 +827,14 @@ ccid_transceive (ccid_driver_t handle, for (i=0; i < msglen; i++) DEBUGOUT_CONT_1 (" %02X", msg[i]); DEBUGOUT_LF (); - -/* fprintf (stderr, "T1: put %c-block seq=%d\n", */ -/* ((msg[11] & 0xc0) == 0x80)? 'R' : */ -/* (msg[11] & 0x80)? 'S' : 'I', */ -/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); */ - + +#ifdef DEBUG_T1 + fprintf (stderr, "T1: put %c-block seq=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); +#endif + rc = bulk_out (handle, msg, msglen); if (rc) return rc; @@ -829,12 +854,14 @@ ccid_transceive (ccid_driver_t handle, return -1; } -/* fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", */ -/* ((msg[11] & 0xc0) == 0x80)? 'R' : */ -/* (msg[11] & 0x80)? 'S' : 'I', */ -/* ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), */ -/* ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 */ -/* ); */ +#ifdef DEBUG_T1 + fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 + ); +#endif if (!(tpdu[1] & 0x80)) { /* This is an I-block. */ @@ -899,9 +926,20 @@ ccid_transceive (ccid_driver_t handle, { /* Error: repeat last block */ msg = send_buffer; } + else if (sending && !!(tpdu[1] & 0x40) == handle->t1_ns) + { /* Reponse does not match our sequence number. */ + DEBUGOUT ("R-block with wrong seqno received on more bit\n"); + return -1; + } + else if (sending) + { /* Send next chunk. */ + msg = send_buffer; + next_chunk = 1; + handle->t1_ns ^= 1; + } else { - DEBUGOUT ("unxpectec ACK R-block received\n"); + DEBUGOUT ("unexpected ACK R-block received\n"); return -1; } } -- cgit v1.2.3 From cf2c58e686ef452b185e399011bfad5e60262641 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Oct 2003 17:11:32 +0000 Subject: (PRINTABLE_OS_NAME): Remove special case for The Hurd; Robert Millan reported that the uname test is now sufficient. --- ChangeLog | 6 ++++++ configure.ac | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2e219c90..cb7861164 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/configure.ac b/configure.ac index 12ff0d703..8cd6196c6 100644 --- a/configure.ac +++ b/configure.ac @@ -600,10 +600,6 @@ case "${target}" in *-linux*) PRINTABLE_OS_NAME="GNU/Linux" ;; -dnl let that after linux to avoid gnu-linux problems - *-gnu*) - PRINTABLE_OS_NAME="GNU/Hurd" - ;; *) PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` ;; -- cgit v1.2.3 From 99277d21c190965d1b7c95b895324f467413f0f1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Oct 2003 17:12:21 +0000 Subject: * card-util.c (card_edit): New command "passwd". Add logic to check the PIN in advance. (card_status): Add new args to return the serial number. Changed all callers. * call-agent.c (agent_scd_checkpin): New. --- doc/scdaemon.texi | 40 ++++++++++++++++++++++++++++++ g10/ChangeLog | 8 ++++++ g10/call-agent.c | 22 +++++++++++++++++ g10/call-agent.h | 4 +++ g10/card-util.c | 74 +++++++++++++++++++++++++++++++++++++++++-------------- g10/g10.c | 2 +- g10/main.h | 2 +- 7 files changed, 131 insertions(+), 21 deletions(-) diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 36274e601..3bd8caaa8 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -191,6 +191,12 @@ syncronizing access to a token between sessions. * 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 @@ -309,3 +315,37 @@ hex notation. The actual decryption is then done using the command 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. + + diff --git a/g10/ChangeLog b/g10/ChangeLog index cb5a8ad64..80216ced3 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,11 @@ +2003-10-20 Werner Koch <wk@gnupg.org> + + * card-util.c (card_edit): New command "passwd". Add logic to + check the PIN in advance. + (card_status): Add new args to return the serial number. Changed + all callers. + * call-agent.c (agent_scd_checkpin): New. + 2003-10-08 Werner Koch <wk@gnupg.org> * call-agent.c (agent_scd_getattr): Don't clear the passed info diff --git a/g10/call-agent.c b/g10/call-agent.c index c6c8faaec..9ca127c3c 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -869,3 +869,25 @@ agent_scd_change_pin (int chvno) return map_assuan_err (rc); } + +/* Perform a CHECKPIN operation. SERIALNO should be the seriial + 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); +} + + diff --git a/g10/call-agent.h b/g10/call-agent.h index 101db9574..875110118 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -85,6 +85,10 @@ int agent_scd_pkdecrypt (const char *serialno, /* 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*/ diff --git a/g10/card-util.c b/g10/card-util.c index 669927707..de445b796 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -255,13 +255,16 @@ fpr_is_zero (const char *fpr) /* Print all available information about the current card. */ void -card_status (FILE *fp) +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) { @@ -289,6 +292,13 @@ card_status (FILE *fp) 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); @@ -660,29 +670,33 @@ card_edit (STRLIST commands) cmdNOP = 0, cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, - cmdFORCESIG, cmdGENERATE, + cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdINVCMD }; static struct { const char *name; enum cmdids id; + int requires_pin; 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_("quit") , cmdQUIT , 0, N_("quit this menu") }, + { N_("q") , cmdQUIT , 0, NULL }, + { N_("help") , cmdHELP , 0, N_("show this help") }, + { "?" , cmdHELP , 0, NULL }, + { N_("list") , cmdLIST , 0, N_("list all available data") }, + { N_("l") , cmdLIST , 0, NULL }, + { N_("debug") , cmdDEBUG , 0, NULL }, + { N_("name") , cmdNAME , 1, N_("change card holder's name") }, + { N_("url") , cmdURL , 1, N_("change URL to retrieve key") }, + { N_("login") , cmdLOGIN , 1, N_("change the login name") }, + { N_("lang") , cmdLANG , 1, N_("change the language preferences") }, + { N_("sex") , cmdSEX , 1, N_("change card holder's sex") }, + { N_("forcesig"), + cmdFORCESIG, 1, N_("toggle the signature force PIN flag") }, + { N_("generate"), + cmdGENERATE, 1, N_("generate new keys") }, + { N_("passwd"), cmdPASSWD, 0, N_("menu to change or unblock the PIN") }, { NULL, cmdINVCMD } }; @@ -690,6 +704,9 @@ card_edit (STRLIST commands) int have_commands = !!commands; int redisplay = 1; char *answer = NULL; + int did_checkpin = 0; + char serialnobuf[50]; + if (opt.command_fd != -1) ; @@ -705,18 +722,19 @@ card_edit (STRLIST commands) const char *arg_string = ""; char *p; int i; - + int requires_pin; + tty_printf("\n"); if (redisplay ) { if (opt.with_colons) { - card_status (stdout); + card_status (stdout, serialnobuf, DIM (serialnobuf)); fflush (stdout); } else { - card_status (NULL); + card_status (NULL, serialnobuf, DIM (serialnobuf)); tty_printf("\n"); } redisplay = 0; @@ -750,6 +768,7 @@ card_edit (STRLIST commands) while( *answer == '#' ); arg_number = 0; /* Yes, here is the init which egcc complains about */ + requires_pin = 0; if (!*answer) cmd = cmdLIST; /* Default to the list command */ else if (*answer == CONTROL_D) @@ -769,7 +788,19 @@ card_edit (STRLIST commands) break; cmd = cmds[i].id; + requires_pin = cmds[i].requires_pin; } + + if (requires_pin && !did_checkpin) + { + int rc = agent_scd_checkpin (serialnobuf); + if (rc) + { + log_error ("error checking the PIN: %s\n", gpg_strerror (rc)); + continue; + } + did_checkpin = 1; + } switch (cmd) { @@ -811,6 +842,11 @@ card_edit (STRLIST commands) generate_card_keys (); break; + case cmdPASSWD: + change_pin (0); + did_checkpin = 0; /* Need to reset it of course. */ + break; + case cmdQUIT: goto leave; diff --git a/g10/g10.c b/g10/g10.c index 984e50d9c..77e6f6cf9 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -2844,7 +2844,7 @@ main( int argc, char **argv ) case aCardStatus: if (argc) wrong_args ("--card-status"); - card_status (stdout); + card_status (stdout, NULL, 0); break; case aCardEdit: diff --git a/g10/main.h b/g10/main.h index d00044c9f..52bfa7659 100644 --- a/g10/main.h +++ b/g10/main.h @@ -260,7 +260,7 @@ void run_in_pipemode (void); /*-- card-util.c --*/ void change_pin (int no); -void card_status (FILE *fp); +void card_status (FILE *fp, char *serialnobuf, size_t serialnobuflen); void card_edit (STRLIST commands); /*-- signal.c --*/ -- cgit v1.2.3 From 21be16dba911a3ebe530e37f3479690798cc8a01 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Oct 2003 17:12:50 +0000 Subject: * command.c (cmd_checkpin): New. (register_commands): Add command CHECKPIN. * app.c (app_check_pin): New. * app-openpgp.c (check_against_given_fingerprint): New. Factored out that code elsewhere. (do_check_pin): New. --- scd/ChangeLog | 17 +++++++ scd/apdu.c | 137 ++++++++++++++++++++++++++++++++++++++++-------------- scd/apdu.h | 1 + scd/app-common.h | 6 +++ scd/app-openpgp.c | 137 ++++++++++++++++++++++++++++++++++-------------------- scd/app.c | 23 +++++++++ scd/ccid-driver.c | 61 ++++++++++++++++++++---- scd/ccid-driver.h | 1 + scd/command.c | 36 ++++++++++++++ 9 files changed, 324 insertions(+), 95 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index f8ce674b8..40a928895 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,20 @@ +2003-10-20 Werner Koch <wk@gnupg.org> + + * command.c (cmd_checkpin): New. + (register_commands): Add command CHECKPIN. + * app.c (app_check_pin): New. + * app-openpgp.c (check_against_given_fingerprint): New. Factored + out that code elsewhere. + (do_check_pin): New. + +2003-10-10 Werner Koch <wk@gnupg.org> + + * ccid-driver.c (ccid_close_reader): New. + + * apdu.c (close_ccid_reader, close_ct_reader, close_csc_reader) + (close_osc_reader, apdu_close_reader): New. Not all are properly + implemented yet. + 2003-10-09 Werner Koch <wk@gnupg.org> * ccid-driver.c (ccid_transceive): Add T=1 chaining for sending. diff --git a/scd/apdu.c b/scd/apdu.c index d5b93de6e..2b17ef53b 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -51,6 +51,13 @@ insertion of the card (1 = don't wait). */ +#ifdef _WIN32 +#define DLSTDCALL __stdcall +#else +#define DLSTDCALL +#endif + + /* A structure to collect information pertaining to one reader slot. */ struct reader_table_s { @@ -84,12 +91,12 @@ static struct reader_table_s reader_table[MAX_READER]; /* ct API function pointer. */ -static char (*CT_init) (unsigned short ctn, unsigned short Pn); -static char (*CT_data) (unsigned short ctn, unsigned char *dad, - unsigned char *sad, unsigned short lc, - unsigned char *cmd, unsigned short *lr, - unsigned char *rsp); -static char (*CT_close) (unsigned short ctn); +static char (* DLSTDCALL CT_init) (unsigned short ctn, unsigned short Pn); +static char (* DLSTDCALL CT_data) (unsigned short ctn, unsigned char *dad, + unsigned char *sad, unsigned short lc, + unsigned char *cmd, unsigned short *lr, + unsigned char *rsp); +static char (* DLSTDCALL CT_close) (unsigned short ctn); /* PC/SC constants and function pointer. */ #define PCSC_SCOPE_USER 0 @@ -117,34 +124,38 @@ struct pcsc_io_request_s { typedef struct pcsc_io_request_s *pcsc_io_request_t; -long (*pcsc_establish_context) (unsigned long scope, - const void *reserved1, - const void *reserved2, - unsigned long *r_context); -long (*pcsc_release_context) (unsigned long context); -long (*pcsc_list_readers) (unsigned long context, const char *groups, - char *readers, unsigned long *readerslen); -long (*pcsc_connect) (unsigned long context, - const char *reader, - unsigned long share_mode, - unsigned long preferred_protocols, - unsigned long *r_card, - unsigned long *r_active_protocol); -long (*pcsc_disconnect) (unsigned long card, unsigned long disposition); -long (*pcsc_status) (unsigned long card, - char *reader, unsigned long *readerlen, - unsigned long *r_state, unsigned long *r_protocol, - unsigned char *atr, unsigned long *atrlen); -long (*pcsc_begin_transaction) (unsigned long card); -long (*pcsc_end_transaction) (unsigned long card); -long (*pcsc_transmit) (unsigned long card, - const pcsc_io_request_t send_pci, - const unsigned char *send_buffer, - unsigned long send_len, - pcsc_io_request_t recv_pci, - unsigned char *recv_buffer, - unsigned long *recv_len); -long (*pcsc_set_timeout) (unsigned long context, unsigned long timeout); +long (* DLSTDCALL pcsc_establish_context) (unsigned long scope, + const void *reserved1, + const void *reserved2, + unsigned long *r_context); +long (* DLSTDCALL pcsc_release_context) (unsigned long context); +long (* DLSTDCALL pcsc_list_readers) (unsigned long context, + const char *groups, + char *readers, unsigned long*readerslen); +long (* DLSTDCALL pcsc_connect) (unsigned long context, + const char *reader, + unsigned long share_mode, + unsigned long preferred_protocols, + unsigned long *r_card, + unsigned long *r_active_protocol); +long (* DLSTDCALL pcsc_disconnect) (unsigned long card, + unsigned long disposition); +long (* DLSTDCALL pcsc_status) (unsigned long card, + char *reader, unsigned long *readerlen, + unsigned long *r_state, + unsigned long *r_protocol, + unsigned char *atr, unsigned long *atrlen); +long (* DLSTDCALL pcsc_begin_transaction) (unsigned long card); +long (* DLSTDCALL pcsc_end_transaction) (unsigned long card); +long (* DLSTDCALL pcsc_transmit) (unsigned long card, + const pcsc_io_request_t send_pci, + const unsigned char *send_buffer, + unsigned long send_len, + pcsc_io_request_t recv_pci, + unsigned char *recv_buffer, + unsigned long *recv_len); +long (* DLSTDCALL pcsc_set_timeout) (unsigned long context, + unsigned long timeout); @@ -347,6 +358,14 @@ open_ct_reader (int port) return reader; } +static int +close_ct_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual retruned size will be @@ -570,6 +589,17 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, return err? -1:0; /* FIXME: Return appropriate error code. */ } +static int +close_pcsc_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + + + + #ifdef HAVE_LIBUSB /* @@ -609,6 +639,15 @@ open_ccid_reader (void) return slot; } +static int +close_ccid_reader (int slot) +{ + ccid_close_reader (reader_table[slot].ccid.handle); + reader_table[slot].used = 0; + return 0; +} + + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be @@ -738,6 +777,16 @@ open_osc_reader (int portno) } +static int +close_osc_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + + + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be set to BUFLEN. Returns: OpenSC error code. */ @@ -940,6 +989,26 @@ apdu_open_reader (const char *portstr) } +int +apdu_close_reader (int slot) +{ + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + if (reader_table[slot].is_ctapi) + return close_ct_reader (slot); +#ifdef HAVE_LIBUSB + else if (reader_table[slot].is_ccid) + return close_ccid_reader (slot); +#endif +#ifdef HAVE_OPENSC + else if (reader_table[slot].is_osc) + return close_osc_reader (slot); +#endif + else + return close_pcsc_reader (slot); +} + + unsigned char * apdu_get_atr (int slot, size_t *atrlen) { diff --git a/scd/apdu.h b/scd/apdu.h index 6e4244ba0..21e2b9840 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -54,6 +54,7 @@ enum { /* Note , that apdu_open_reader returns no status word but -1 on error. */ int apdu_open_reader (const char *portstr); +int apdu_close_reader (int slot); unsigned char *apdu_get_atr (int slot, size_t *atrlen); diff --git a/scd/app-common.h b/scd/app-common.h index 33f23127b..de1e02cac 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -65,6 +65,9 @@ struct app_ctx_s { const char *chvnostr, int reset_mode, int (*pincb)(void*, const char *, char **), void *pincb_arg); + int (*check_pin) (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg); } fnc; @@ -106,6 +109,9 @@ int app_get_challenge (APP app, size_t nbytes, unsigned char *buffer); int app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, int (*pincb)(void*, const char *, char **), void *pincb_arg); +int app_check_pin (APP app, const char *keyidstr, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); /*-- app-openpgp.c --*/ diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 174d2e974..07abf9bfb 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -912,6 +912,33 @@ compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr) } + /* If a fingerprint has been specified check it against the one on + the card. This is allows for a meaningful error message in case + the key on the card has been replaced but the shadow information + known to gpg was not updated. If there is no fingerprint we + assume that this is okay. */ +static int +check_against_given_fingerprint (APP app, const char *fpr, int keyno) +{ + unsigned char tmp[20]; + const char *s; + int n; + + for (s=fpr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 40) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* okay */ + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=fpr, n=0; n < 20; s += 2, n++) + tmp[n] = xtoi_2 (s); + return compare_fingerprint (app, keyno, tmp); +} + + /* Compute a digital signature on INDATA which is expected to be the raw message digest. For this application the KEYIDSTR consists of @@ -976,23 +1003,9 @@ do_sign (APP app, const char *keyidstr, int hashalgo, known to gpg was not updated. If there is no fingerprint, gpg will detect a bogus signature anyway due to the verify-after-signing feature. */ - if (fpr) - { - for (s=fpr, n=0; hexdigitp (s); s++, n++) - ; - if (n != 40) - return gpg_error (GPG_ERR_INV_ID); - else if (!*s) - ; /* okay */ - else - return gpg_error (GPG_ERR_INV_ID); - - for (s=fpr, n=0; n < 20; s += 2, n++) - tmp_sn[n] = xtoi_2 (s); - rc = compare_fingerprint (app, 1, tmp_sn); - if (rc) - return rc; - } + rc = fpr? check_against_given_fingerprint (app, fpr, 1) : 0; + if (rc) + return rc; if (hashalgo == GCRY_MD_SHA1) memcpy (data, sha1_prefix, 15); @@ -1107,23 +1120,9 @@ do_auth (APP app, const char *keyidstr, known to gpg was not updated. If there is no fingerprint, gpg will detect a bogus signature anyway due to the verify-after-signing feature. */ - if (fpr) - { - for (s=fpr, n=0; hexdigitp (s); s++, n++) - ; - if (n != 40) - return gpg_error (GPG_ERR_INV_ID); - else if (!*s) - ; /* okay */ - else - return gpg_error (GPG_ERR_INV_ID); - - for (s=fpr, n=0; n < 20; s += 2, n++) - tmp_sn[n] = xtoi_2 (s); - rc = compare_fingerprint (app, 3, tmp_sn); - if (rc) - return rc; - } + rc = fpr? check_against_given_fingerprint (app, fpr, 3) : 0; + if (rc) + return rc; rc = verify_chv2 (app, pincb, pincb_arg); if (!rc) @@ -1177,23 +1176,9 @@ do_decipher (APP app, const char *keyidstr, the key on the card has been replaced but the shadow information known to gpg was not updated. If there is no fingerprint, the decryption will won't produce the right plaintext anyway. */ - if (fpr) - { - for (s=fpr, n=0; hexdigitp (s); s++, n++) - ; - if (n != 40) - return gpg_error (GPG_ERR_INV_ID); - else if (!*s) - ; /* okay */ - else - return gpg_error (GPG_ERR_INV_ID); - - for (s=fpr, n=0; n < 20; s += 2, n++) - tmp_sn[n] = xtoi_2 (s); - rc = compare_fingerprint (app, 2, tmp_sn); - if (rc) - return rc; - } + rc = fpr? check_against_given_fingerprint (app, fpr, 2) : 0; + if (rc) + return rc; rc = verify_chv2 (app, pincb, pincb_arg); if (!rc) @@ -1202,6 +1187,55 @@ do_decipher (APP app, const char *keyidstr, } +/* Perform a simple verify operation for CHV1 and CHV2, so that + further operations won't ask for CHV2 and it is possible to do a + cheap check on the PIN: If there is something wrong with the PIN + entry system, only the regular CHV will get blocked and not the + dangerous CHV3. KEYIDSTR is the usual card's serial number; an + optional fingerprint part will be ignored. */ +static int +do_check_pin (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg) +{ + unsigned char tmp_sn[20]; + const char *s; + int n; + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check whether an OpenPGP card of any version has been requested. */ + if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 32) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* No fingerprint given: we allow this for now. */ + else if (*s == '/') + ; /* We ignore a fingerprint. */ + else + return gpg_error (GPG_ERR_INV_ID); + + for (s=keyidstr, n=0; n < 16; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + + if (app->serialnolen != 16) + return gpg_error (GPG_ERR_INV_CARD); + if (memcmp (app->serialno, tmp_sn, 16)) + return gpg_error (GPG_ERR_WRONG_CARD); + /* Yes, there is a race conditions: The user might pull the card + right here and we won't notice that. However this is not a + problem and the check above is merely for a graceful failure + between operations. */ + + return verify_chv2 (app, pincb, pincb_arg); +} + + /* Select the OpenPGP application on the card in SLOT. This function @@ -1262,6 +1296,7 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) app->fnc.auth = do_auth; app->fnc.decipher = do_decipher; app->fnc.change_pin = do_change_pin; + app->fnc.check_pin = do_check_pin; } leave: diff --git a/scd/app.c b/scd/app.c index 5b0340b89..1f142ea32 100644 --- a/scd/app.c +++ b/scd/app.c @@ -295,6 +295,29 @@ app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, } +/* Perform a VERIFY operation without doing anything lese. This may + be used to initialze a the PION cache for long lasting other + operations. Its use is highly application dependent. */ +int +app_check_pin (APP app, const char *keyidstr, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc; + + if (!app || !keyidstr || !*keyidstr || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.check_pin) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + rc = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg); + if (opt.verbose) + log_info ("operation check_pin result: %s\n", gpg_strerror (rc)); + return rc; +} + + diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 35f0329db..f14600cc2 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -174,6 +174,12 @@ struct ccid_driver_s { }; +static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen); +static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, + size_t *nread, int expected_type, int seqno); + + + /* Convert a little endian stored 4 byte value into an unsigned integer. */ static unsigned int @@ -182,6 +188,16 @@ convert_le_u32 (const unsigned char *buf) return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } +static void +set_msg_len (unsigned char *msg, unsigned int length) +{ + msg[1] = length; + msg[2] = length >> 8; + msg[3] = length >> 16; + msg[4] = length >> 24; +} + + /* Parse a CCID descriptor, optionally print all available features @@ -482,22 +498,47 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) } -/* Return False if a card is present and powered. */ -int -ccid_check_card_presence (ccid_driver_t handle) +/* Close the reader HANDLE. */ +int +ccid_close_reader (ccid_driver_t handle) { + if (!handle || !handle->idev) + return 0; - return -1; + { + int rc; + unsigned char msg[100]; + size_t msglen; + unsigned char seqno; + + msg[0] = PC_to_RDR_IccPowerOff; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* RFU */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, 0); + msglen = 10; + + rc = bulk_out (handle, msg, msglen); + if (!rc) + bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno); + } + + usb_release_interface (handle->idev, 0); + usb_close (handle->idev); + handle->idev = NULL; + free (handle); + return 0; } -static void -set_msg_len (unsigned char *msg, unsigned int length) +/* Return False if a card is present and powered. */ +int +ccid_check_card_presence (ccid_driver_t handle) { - msg[1] = length; - msg[2] = length >> 8; - msg[3] = length >> 16; - msg[4] = length >> 24; + + return -1; } diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 4d12d88c2..e33be55d9 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -60,6 +60,7 @@ struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; int ccid_open_reader (ccid_driver_t *handle, int readerno); +int ccid_close_reader (ccid_driver_t handle); int ccid_get_atr (ccid_driver_t handle, unsigned char *atr, size_t maxatrlen, size_t *atrlen); int ccid_transceive (ccid_driver_t handle, diff --git a/scd/command.c b/scd/command.c index fc5efa708..8808b10e9 100644 --- a/scd/command.c +++ b/scd/command.c @@ -923,6 +923,41 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) } +/* CHECKPIN <hexified_id> + + */ +static int +cmd_checkpin (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *keyidstr; + + if ((rc = open_card (ctrl))) + return rc; + + if (!ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + /* We have to use a copy of the key ID because the function may use + the pin_cb which in turn uses the assuan line buffer and thus + overwriting the original line with the keyid. */ + keyidstr = xtrystrdup (line); + if (!keyidstr) + return ASSUAN_Out_Of_Core; + + rc = app_check_pin (ctrl->app_ctx, + keyidstr, + pin_cb, ctx); + xfree (keyidstr); + if (rc) + log_error ("app_check_pin failed: %s\n", gpg_strerror (rc)); + + return map_to_assuan_status (rc); +} + + + /* Tell the assuan library about our commands */ @@ -948,6 +983,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "GENKEY", cmd_genkey }, { "RANDOM", cmd_random }, { "PASSWD", cmd_passwd }, + { "CHECKPIN", cmd_checkpin }, { NULL } }; int i, rc; -- cgit v1.2.3 From f936866734f9d8bd16a41d43bd7cc4edad6fe728 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 25 Oct 2003 14:22:08 +0000 Subject: (learn_status_cb, scd_genkey_cb): Fixed faulty use of !spacep(). --- g10/ChangeLog | 5 +++++ g10/call-agent.c | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 80216ced3..c6dfa1db7 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2003-10-25 Werner Koch <wk@gnupg.org> + + * call-agent.c (learn_status_cb, scd_genkey_cb): Fixed faulty use + of !spacep(). + 2003-10-20 Werner Koch <wk@gnupg.org> * card-util.c (card_edit): New command "passwd". Add logic to diff --git a/g10/call-agent.c b/g10/call-agent.c index 9ca127c3c..b981b7f22 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -520,14 +520,14 @@ learn_status_cb (void *opaque, const char *line) while (spacep (p)) p++; parm->chv1_cached = atoi (p); - while (!spacep (p)) + while (*p && !spacep (p)) p++; while (spacep (p)) p++; for (i=0; *p && i < 3; i++) { parm->chvmaxlen[i] = atoi (p); - while (!spacep (p)) + while (*p && !spacep (p)) p++; while (spacep (p)) p++; @@ -535,7 +535,7 @@ learn_status_cb (void *opaque, const char *line) for (i=0; *p && i < 3; i++) { parm->chvretry[i] = atoi (p); - while (!spacep (p)) + while (*p && !spacep (p)) p++; while (spacep (p)) p++; @@ -546,7 +546,7 @@ learn_status_cb (void *opaque, const char *line) else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) { int no = atoi (line); - while (!spacep (line)) + while (*line && !spacep (line)) line++; while (spacep (line)) line++; @@ -674,7 +674,7 @@ scd_genkey_cb (void *opaque, const char *line) gcry_mpi_t a; const char *name = line; - while (!spacep (line)) + while (*line && !spacep (line)) line++; while (spacep (line)) line++; -- cgit v1.2.3 From 5ee820978d09fea7aa660201f395434a16950dbb Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 25 Oct 2003 14:22:42 +0000 Subject: * command.c (cmd_genkey, cmd_passwd): Fixed faulty use of !spacep(). * apdu.c (apdu_open_reader): Hacks for PC/SC under Windows. --- scd/ChangeLog | 7 +++++++ scd/apdu.c | 33 ++++++++++++++++++++++++++++++--- scd/ccid-driver.c | 4 ++++ scd/command.c | 8 ++++---- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 40a928895..0b683d506 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2003-10-25 Werner Koch <wk@gnupg.org> + + * command.c (cmd_genkey, cmd_passwd): Fixed faulty use of + !spacep(). + + * apdu.c (apdu_open_reader): Hacks for PC/SC under Windows. + 2003-10-20 Werner Koch <wk@gnupg.org> * command.c (cmd_checkpin): New. diff --git a/scd/apdu.c b/scd/apdu.c index 2b17ef53b..9f5d36e09 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -298,6 +298,8 @@ ct_activate_card (int reader) { log_error ("ct_activate_card(%d): activation failed: %s\n", reader, ct_error_string (rc)); + if (!rc) + log_printhex (" received data:", buf, buflen); return -1; } @@ -933,7 +935,7 @@ apdu_open_reader (const char *portstr) CT_close = dlsym (handle, "CT_close"); if (!CT_init || !CT_data || !CT_close) { - log_error ("apdu_open_reader: invalid ctAPI driver\n"); + log_error ("apdu_open_reader: invalid CT-API driver\n"); dlclose (handle); return -1; } @@ -959,9 +961,21 @@ apdu_open_reader (const char *portstr) pcsc_establish_context = dlsym (handle, "SCardEstablishContext"); pcsc_release_context = dlsym (handle, "SCardReleaseContext"); pcsc_list_readers = dlsym (handle, "SCardListReaders"); +#ifdef _WIN32 + if (!pcsc_list_readers) + pcsc_list_readers = dlsym (handle, "SCardListReadersA"); +#endif pcsc_connect = dlsym (handle, "SCardConnect"); +#ifdef _WIN32 + if (!pcsc_connect) + pcsc_connect = dlsym (handle, "SCardConnectA"); +#endif pcsc_disconnect = dlsym (handle, "SCardDisconnect"); pcsc_status = dlsym (handle, "SCardStatus"); +#ifdef _WIN32 + if (pcsc_status) + pcsc_status = dlsym (handle, "SCardStatusA"); +#endif pcsc_begin_transaction = dlsym (handle, "SCardBeginTransaction"); pcsc_end_transaction = dlsym (handle, "SCardEndTransaction"); pcsc_transmit = dlsym (handle, "SCardTransmit"); @@ -976,9 +990,22 @@ apdu_open_reader (const char *portstr) || !pcsc_begin_transaction || !pcsc_end_transaction || !pcsc_transmit - || !pcsc_set_timeout) + /* || !pcsc_set_timeout */) { - log_error ("apdu_open_reader: invalid PC/SC driver\n"); + /* Note that set_timeout is currently not used and also not + available under Windows. */ + log_error ("apdu_open_reader: invalid PC/SC driver " + "(%d%d%d%d%d%d%d%d%d%d)\n", + !!pcsc_establish_context, + !!pcsc_release_context, + !!pcsc_list_readers, + !!pcsc_connect, + !!pcsc_disconnect, + !!pcsc_status, + !!pcsc_begin_transaction, + !!pcsc_end_transaction, + !!pcsc_transmit, + !!pcsc_set_timeout ); dlclose (handle); return -1; } diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index f14600cc2..8868a2cfc 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -880,6 +880,10 @@ ccid_transceive (ccid_driver_t handle, if (rc) return rc; + /* Fixme: The next line for the current Valgrid without support + for USB IOCTLs. */ + memset (recv_buffer, 0, sizeof recv_buffer); + msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, RDR_to_PC_DataBlock, seqno); diff --git a/scd/command.c b/scd/command.c index 8808b10e9..363b46480 100644 --- a/scd/command.c +++ b/scd/command.c @@ -813,7 +813,7 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) /* Skip over options. */ while ( *line == '-' && line[1] == '-' ) { - while (!spacep (line)) + while (*line && !spacep (line)) line++; while (spacep (line)) line++; @@ -821,7 +821,7 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) if (!*line) return set_error (Parameter_Error, "no key number given"); keyno = line; - while (!spacep (line)) + while (*line && !spacep (line)) line++; *line = 0; @@ -894,7 +894,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) /* Skip over options. */ while (*line == '-' && line[1] == '-') { - while (!spacep (line)) + while (*line && !spacep (line)) line++; while (spacep (line)) line++; @@ -902,7 +902,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) if (!*line) return set_error (Parameter_Error, "no CHV number given"); chvnostr = line; - while (!spacep (line)) + while (*line && !spacep (line)) line++; *line = 0; -- cgit v1.2.3 From 1ab791ed69edb437b658e220d965ee65a6e1e246 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 25 Oct 2003 14:23:11 +0000 Subject: (read_parameters): Fixed faulty of !spacep(). --- sm/ChangeLog | 4 ++++ sm/certreqgen.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index fbdf15f6c..4a2825efe 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2003-10-25 Werner Koch <wk@gnupg.org> + + * certreqgen.c (read_parameters): Fixed faulty of !spacep(). + 2003-08-20 Marcus Brinkmann <marcus@g10code.de> * encrypt.c (encode_session_key): Allocate enough space. Cast key diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 0dd4fdde9..efb3e8c1a 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -270,7 +270,7 @@ read_parameters (FILE *fp, KsbaWriter writer) keyword = p; if (*keyword == '%') { - for (; !spacep (p); p++) + for (; *p && !spacep (p); p++) ; if (*p) *p++ = 0; -- cgit v1.2.3 From ecb473800b4b38cc1965b4b19370517732dead79 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:11:33 +0000 Subject: (NEED_KSBA_VERSION): Set to 0.9.0 due the changed time interface. --- ChangeLog | 5 +++++ configure.ac | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index cb7861164..2a830143a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/configure.ac b/configure.ac index 8cd6196c6..1c6269f49 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,7 @@ development_version=yes NEED_GPG_ERROR_VERSION=0.4 NEED_LIBGCRYPT_VERSION=1.1.43 NEED_LIBASSUAN_VERSION=0.6.0 -NEED_KSBA_VERSION=0.4.6 +NEED_KSBA_VERSION=0.9.0 NEED_OPENSC_VERSION=0.8.0 @@ -686,7 +686,7 @@ AC_FUNC_FSEEKO AC_FUNC_VPRINTF AC_FUNC_FORK AC_CHECK_FUNCS(strerror stpcpy strsep strlwr tcgetattr strtoul mmap) -AC_CHECK_FUNCS(strcasecmp strncasecmp ctermid times) +AC_CHECK_FUNCS(strcasecmp strncasecmp ctermid times gmtime_r) AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat getaddrinfo) -- cgit v1.2.3 From 71d265a684da4ef4f1c2b6b73fb9ba3a27a6fa03 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:11:48 +0000 Subject: * command.c (cmd_get_confirmation): New command. --- agent/ChangeLog | 4 ++++ agent/command.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/agent/ChangeLog b/agent/ChangeLog index 39e93f818..005912dff 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2003-10-27 Werner Koch <wk@gnupg.org> + + * command.c (cmd_get_confirmation): New command. + 2003-08-20 Timo Schulz <twoaday@freakmail.de> * pksign.c (do_encode_md): Allocate enough space. Cast md diff --git a/agent/command.c b/agent/command.c index ed4ea6b02..f7a042ba9 100644 --- a/agent/command.c +++ b/agent/command.c @@ -522,6 +522,55 @@ cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line) return 0; } + +/* GET_CONFIRMATION <description> + + This command may be used to ask for a simple confirmation. + DESCRIPTION is displayed along with a Okay and Cancel button. This + command uses a syntax which helps clients to use the agent with + minimum effort. The agent either returns with an error or with a + OK. Note, that the length of DESCRIPTION is implicitly limited by + the maximum length of a command. DESCRIPTION should not conmtain + ant spaces, those must be encoded either percent escaped or simply + as '+'. +*/ + +static int +cmd_get_confirmation (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + char *desc = NULL; + char *p; + + /* parse the stuff */ + for (p=line; *p == ' '; p++) + ; + desc = p; + p = strchr (desc, ' '); + if (p) + *p = 0; /* We ignore any garbage -may be later used for other args. */ + + if (!desc || !*desc) + return set_error (Parameter_Error, "no description given"); + + if (!strcmp (desc, "X")) + desc = NULL; + + /* Note, that we only need to replace the + characters and should + leave the other escaping in place because the escaped string is + send verbatim to the pinentry which does the unescaping (but not + the + replacing) */ + if (desc) + plus_to_blank (desc); + + rc = agent_get_confirmation (ctrl, desc, NULL, NULL); + if (rc) + log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + /* LEARN [--send] @@ -671,6 +720,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "GENKEY", cmd_genkey }, { "GET_PASSPHRASE", cmd_get_passphrase }, { "CLEAR_PASSPHRASE", cmd_clear_passphrase }, + { "GET_CONFIRMATION", cmd_get_confirmation }, { "LISTTRUSTED", cmd_listtrusted }, { "MARKTRUSTED", cmd_marktrusted }, { "LEARN", cmd_learn }, -- cgit v1.2.3 From f21638c9e3b614bc0be6903b1fb75543f9619a7b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:11:57 +0000 Subject: * util.h (gnupg_isotime_t): New. (gnupg_copy_time): New. * gettime.c (gnupg_get_isotime): New. --- common/ChangeLog | 7 +++++++ common/gettime.c | 26 ++++++++++++++++++++++++++ common/util.h | 19 +++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/common/ChangeLog b/common/ChangeLog index caabdd4cf..7dc3c03eb 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,10 @@ +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 diff --git a/common/gettime.c b/common/gettime.c index a7914d348..ed1d0c819 100644 --- a/common/gettime.c +++ b/common/gettime.c @@ -46,6 +46,32 @@ gnupg_get_time () 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 diff --git a/common/util.h b/common/util.h index 78aa2f890..fb2c6e839 100644 --- a/common/util.h +++ b/common/util.h @@ -51,6 +51,12 @@ #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_ksba_err (int err); int map_gcry_err (int err); @@ -60,6 +66,7 @@ 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); @@ -69,6 +76,18 @@ 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); -- cgit v1.2.3 From 3344618b2e51834b3cd94d0a2a9ebad9768e05ce Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:12:17 +0000 Subject: new command --- doc/ChangeLog | 4 ++++ doc/gpg-agent.texi | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index d15420cfc..1c335280c 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 61484485f..793d093a1 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -354,6 +354,7 @@ secret keys. * 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 @@ -700,6 +701,27 @@ 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 -- cgit v1.2.3 From c8fb3836fb5c296d771457ed2dfb1c837a17bc08 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:12:36 +0000 Subject: * apdu.c (close_ct_reader, close_pcsc_reader): Implemented. (get_ccid_error_string): New. Not very useful messages, though. --- scd/ChangeLog | 8 ++++++++ scd/apdu.c | 17 +++++++++++++---- scd/ccid-driver.c | 3 +++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 0b683d506..d3282b38a 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,13 @@ +2003-10-30 Werner Koch <wk@gnupg.org> + + * apdu.c (close_ct_reader, close_pcsc_reader): Implemented. + (get_ccid_error_string): New. Not very useful messages, though. + 2003-10-25 Werner Koch <wk@gnupg.org> + * ccid-driver.c (ccid_open_reader): Return an error if no USB + devices are found. + * command.c (cmd_genkey, cmd_passwd): Fixed faulty use of !spacep(). diff --git a/scd/apdu.c b/scd/apdu.c index 9f5d36e09..27304c8b5 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -363,7 +363,7 @@ open_ct_reader (int port) static int close_ct_reader (int slot) { - /* FIXME: Implement. */ + CT_close (slot); reader_table[slot].used = 0; return 0; } @@ -594,7 +594,7 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, static int close_pcsc_reader (int slot) { - /* FIXME: Implement. */ + pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; return 0; } @@ -608,6 +608,15 @@ close_pcsc_reader (int slot) Internal CCID driver interface. */ +static const char * +get_ccid_error_string (long err) +{ + if (!err) + return "okay"; + else + return "unknown CCID error"; +} + static int open_ccid_reader (void) { @@ -973,7 +982,7 @@ apdu_open_reader (const char *portstr) pcsc_disconnect = dlsym (handle, "SCardDisconnect"); pcsc_status = dlsym (handle, "SCardStatus"); #ifdef _WIN32 - if (pcsc_status) + if (!pcsc_status) pcsc_status = dlsym (handle, "SCardStatusA"); #endif pcsc_begin_transaction = dlsym (handle, "SCardBeginTransaction"); @@ -1062,7 +1071,7 @@ error_string (int slot, long rc) return ct_error_string (rc); #ifdef HAVE_LIBUSB else if (reader_table[slot].is_ccid) - return "no CCID driver error strings yet"; + return get_ccid_error_string (rc); #endif #ifdef HAVE_OPENSC else if (reader_table[slot].is_osc) diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 8868a2cfc..099dae240 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -494,6 +494,9 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) shallow copy of the list created internally by usb_init ? */ usb_free_match (match); + if (!rc && !*handle) + rc = -1; /* In case we didn't enter the while lool at all. */ + return rc; } -- cgit v1.2.3 From dd808fa15bd93656bae7a70a463da0bdddace254 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:12:47 +0000 Subject: * verify.c (strtimestamp_r, gpgsm_verify): * sign.c (gpgsm_sign): * keylist.c (print_time, list_cert_std, list_cert_colon): * certdump.c (gpgsm_print_time, gpgsm_dump_time, gpgsm_dump_cert): * certchain.c (gpgsm_validate_chain): Changed to use ksba_isotime_t. --- sm/ChangeLog | 13 +++++++++++++ sm/certchain.c | 37 +++++++++++++++++++++---------------- sm/certdump.c | 40 ++++++++++------------------------------ sm/gpgsm.c | 5 ++++- sm/gpgsm.h | 6 +++--- sm/keylist.c | 23 ++++++++++++----------- sm/sign.c | 8 ++++---- sm/verify.c | 31 ++++++++++++------------------- 8 files changed, 79 insertions(+), 84 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 4a2825efe..a8dfc0896 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,16 @@ +2003-10-31 Werner Koch <wk@gnupg.org> + + + * verify.c (strtimestamp_r, gpgsm_verify): + + * sign.c (gpgsm_sign): + + * keylist.c (print_time, list_cert_std, list_cert_colon): + + * certdump.c (gpgsm_print_time, gpgsm_dump_time, gpgsm_dump_cert): + + * certchain.c (gpgsm_validate_chain): Changed to use ksba_isotime_t. + 2003-10-25 Werner Koch <wk@gnupg.org> * certreqgen.c (read_parameters): Fixed faulty of !spacep(). diff --git a/sm/certchain.c b/sm/certchain.c index 6323c725e..216b72e0e 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -408,23 +408,26 @@ gpgsm_is_root_cert (KsbaCert cert) /* Validate a chain and optionally return the nearest expiration time in R_EXPTIME */ int -gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) +gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) { int rc = 0, depth = 0, maxdepth; char *issuer = NULL; char *subject = NULL; KEYDB_HANDLE kh = keydb_new (0); KsbaCert subject_cert = NULL, issuer_cert = NULL; - time_t current_time = gnupg_get_time (); - time_t exptime = 0; + ksba_isotime_t current_time; + ksba_isotime_t exptime; int any_expired = 0; int any_revoked = 0; int any_no_crl = 0; int any_crl_too_old = 0; int any_no_policy_match = 0; + + gnupg_get_isotime (current_time); if (r_exptime) *r_exptime = 0; + *exptime = 0; if (opt.no_chain_validation) { @@ -460,26 +463,28 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) } { - time_t not_before, not_after; + ksba_isotime_t not_before, not_after; - not_before = ksba_cert_get_validity (subject_cert, 0); - not_after = ksba_cert_get_validity (subject_cert, 1); - if (not_before == (time_t)(-1) || not_after == (time_t)(-1)) + rc = ksba_cert_get_validity (subject_cert, 0, not_before); + if (!rc) + rc = ksba_cert_get_validity (subject_cert, 1, not_after); + if (rc) { - log_error ("certificate with invalid validity\n"); + log_error (_("certificate with invalid validity: %s\n"), + ksba_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } - if (not_after) + if (*not_after) { - if (!exptime) - exptime = not_after; - else if (not_after < exptime) - exptime = not_after; + if (!*exptime) + gnupg_copy_time (exptime, not_after); + else if (strcmp (not_after, exptime) < 0 ) + gnupg_copy_time (exptime, not_after); } - if (not_before && current_time < not_before) + if (*not_before && strcmp (current_time, not_before) < 0 ) { log_error ("certificate too young; valid from "); gpgsm_dump_time (not_before); @@ -487,7 +492,7 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG); goto leave; } - if (not_after && current_time > not_after) + if (not_after && strcmp (current_time, not_after) > 0 ) { log_error ("certificate has expired at "); gpgsm_dump_time (not_after); @@ -692,7 +697,7 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime) leave: if (r_exptime) - *r_exptime = exptime; + gnupg_copy_time (r_exptime, exptime); xfree (issuer); keydb_release (kh); ksba_cert_release (issuer_cert); diff --git a/sm/certdump.c b/sm/certdump.c index 703e07186..f06cc5832 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -93,42 +93,22 @@ gpgsm_dump_serial (KsbaConstSexp p) } void -gpgsm_print_time (FILE *fp, time_t t) +gpgsm_print_time (FILE *fp, ksba_isotime_t t) { - if (!t) + if (!t || !*t) fputs (_("none"), fp); - else if ( t == (time_t)(-1) ) - fputs ("[Error - Invalid time]", fp); else - { - struct tm *tp; - - tp = gmtime (&t); - fprintf (fp, "%04d-%02d-%02d %02d:%02d:%02d Z", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } + fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s", t, t+4, t+6, t+9, t+11, t+13); } void -gpgsm_dump_time (time_t t) +gpgsm_dump_time (ksba_isotime_t t) { - - if (!t) + if (!t || !*t) log_printf (_("[none]")); - else if ( t == (time_t)(-1) ) - log_printf (_("[error]")); else - { - struct tm *tp; - - tp = gmtime (&t); - log_printf ("%04d-%02d-%02d %02d:%02d:%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } + log_printf ("%.4s-%.2s-%.2s %.2s:%.2s:%s", + t, t+4, t+6, t+9, t+11, t+13); } @@ -167,7 +147,7 @@ gpgsm_dump_cert (const char *text, KsbaCert cert) KsbaSexp sexp; unsigned char *p; char *dn; - time_t t; + ksba_isotime_t t; log_debug ("BEGIN Certificate `%s':\n", text? text:""); if (cert) @@ -178,11 +158,11 @@ gpgsm_dump_cert (const char *text, KsbaCert cert) ksba_free (sexp); log_printf ("\n"); - t = ksba_cert_get_validity (cert, 0); + ksba_cert_get_validity (cert, 0, t); log_debug (" notBefore: "); gpgsm_dump_time (t); log_printf ("\n"); - t = ksba_cert_get_validity (cert, 1); + ksba_cert_get_validity (cert, 1, t); log_debug (" notAfter: "); gpgsm_dump_time (t); log_printf ("\n"); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index c392886ba..3fab49731 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1035,8 +1035,11 @@ main ( int argc, char **argv) if (gnupg_faked_time_p ()) { + gnupg_isotime_t tbuf; + log_info (_("WARNING: running with faked system time: ")); - gpgsm_dump_time (gnupg_get_time ()); + gnupg_get_isotime (tbuf); + gpgsm_dump_time (tbuf); log_printf ("\n"); } diff --git a/sm/gpgsm.h b/sm/gpgsm.h index f996d578c..f0b10c8dc 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -177,12 +177,12 @@ void gpgsm_destroy_writer (Base64Context ctx); /*-- certdump.c --*/ void gpgsm_print_serial (FILE *fp, KsbaConstSexp p); -void gpgsm_print_time (FILE *fp, time_t t); +void gpgsm_print_time (FILE *fp, ksba_isotime_t t); void gpgsm_print_name (FILE *fp, const char *string); void gpgsm_dump_cert (const char *text, KsbaCert cert); void gpgsm_dump_serial (KsbaConstSexp p); -void gpgsm_dump_time (time_t t); +void gpgsm_dump_time (ksba_isotime_t t); void gpgsm_dump_string (const char *string); @@ -199,7 +199,7 @@ int gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo, /*-- certchain.c --*/ int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next); int gpgsm_is_root_cert (KsbaCert cert); -int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, time_t *r_exptime); +int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime); int gpgsm_basic_cert_check (KsbaCert cert); /*-- certlist.c --*/ diff --git a/sm/keylist.c b/sm/keylist.c index 634bda292..548f2a452 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -101,14 +101,12 @@ print_capabilities (KsbaCert cert, FILE *fp) static void -print_time (time_t t, FILE *fp) +print_time (gnupg_isotime_t t, FILE *fp) { - if (!t) + if (!t || !*t) ; - else if ( t == (time_t)(-1) ) - putc ('?', fp); - else - fprintf (fp, "%lu", (unsigned long)t); + else + fputs (t, fp); } @@ -153,6 +151,7 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) char *p; KsbaSexp sexp; char *fpr; + ksba_isotime_t t; fputs (have_secret? "crs:":"crt:", fp); trustletter = 0; @@ -177,9 +176,11 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) fpr+24); /* we assume --fixed-list-mode for gpgsm */ - print_time ( ksba_cert_get_validity (cert, 0), fp); + ksba_cert_get_validity (cert, 0, t); + print_time (t, fp); putc (':', fp); - print_time ( ksba_cert_get_validity (cert, 1), fp); + ksba_cert_get_validity (cert, 1, t); + print_time ( t, fp); putc (':', fp); /* field 8, serial number: */ if ((sexp = ksba_cert_get_serial (cert))) @@ -280,7 +281,7 @@ list_cert_std (KsbaCert cert, FILE *fp, int have_secret) KsbaError kerr; KsbaSexp sexp; char *dn; - time_t t; + ksba_isotime_t t; int idx; int is_ca, chainlen; unsigned int kusage; @@ -318,11 +319,11 @@ list_cert_std (KsbaCert cert, FILE *fp, int have_secret) putc ('\n', fp); } - t = ksba_cert_get_validity (cert, 0); + ksba_cert_get_validity (cert, 0, t); fputs (" validity: ", fp); gpgsm_print_time (fp, t); fputs (" through ", fp); - t = ksba_cert_get_validity (cert, 1); + ksba_cert_get_validity (cert, 1, t); gpgsm_print_time (fp, t); putc ('\n', fp); diff --git a/sm/sign.c b/sm/sign.c index 0afb52b62..8e7431312 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -306,7 +306,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, int signer; const char *algoid; int algo; - time_t signed_at; + ksba_isotime_t signed_at; CERTLIST cl; int release_signerlist = 0; @@ -462,7 +462,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, } } - signed_at = gnupg_get_time (); + gnupg_get_isotime (signed_at); for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) { err = ksba_cms_set_signing_time (cms, signer, signed_at); @@ -577,11 +577,11 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, gcry_md_close (md); goto leave; } - rc = asprintf (&buf, "%c %d %d 00 %lu %s", + rc = asprintf (&buf, "%c %d %d 00 %s %s", detached? 'D':'S', GCRY_PK_RSA, /* FIXME: get pk algo from cert */ algo, - (ulong)signed_at, + signed_at, fpr); xfree (fpr); if (rc < 0) diff --git a/sm/verify.c b/sm/verify.c index 6dd4f4e5b..3c333129b 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -35,22 +35,14 @@ #include "i18n.h" static char * -strtimestamp_r (time_t atime) +strtimestamp_r (ksba_isotime_t atime) { char *buffer = xmalloc (15); - if (atime < 0) - strcpy (buffer, "????" "-??" "-??"); - else if (!atime) + if (!atime || !*atime) strcpy (buffer, "none"); else - { - struct tm *tp; - - tp = gmtime( &atime ); - sprintf (buffer, "%04d-%02d-%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday); - } + sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6); return buffer; } @@ -251,7 +243,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) { char *issuer = NULL; KsbaSexp sigval = NULL; - time_t sigtime, keyexptime; + ksba_isotime_t sigtime, keyexptime; KsbaSexp serial; char *msgdigest = NULL; size_t msgdigestlen; @@ -279,13 +271,14 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) log_printf ("\n"); } - err = ksba_cms_get_signing_time (cms, signer, &sigtime); + err = ksba_cms_get_signing_time (cms, signer, sigtime); if (err == KSBA_No_Data) - sigtime = 0; + *sigtime = 0; else if (err) { log_error ("error getting signing time: %s\n", ksba_strerror (err)); - sigtime = (time_t)-1; + *sigtime = 0; /* FIXME: we can't encode an error in the time + string. */ } err = ksba_cms_get_message_digest (cms, signer, @@ -383,7 +376,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) } log_info (_("Signature made ")); - if (sigtime) + if (*sigtime) gpgsm_dump_time (sigtime); else log_printf (_("[date not given]")); @@ -459,7 +452,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) if (DBG_X509) log_debug ("signature okay - checking certs\n"); - rc = gpgsm_validate_chain (ctrl, cert, &keyexptime); + rc = gpgsm_validate_chain (ctrl, cert, keyexptime); if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) { gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); @@ -474,8 +467,8 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); tstr = strtimestamp_r (sigtime); buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120); - sprintf (buf, "%s %s %lu %lu", fpr, tstr, - (unsigned long)sigtime, (unsigned long)keyexptime ); + sprintf (buf, "%s %s %s %s", fpr, tstr, + sigtime, keyexptime ); xfree (tstr); xfree (fpr); gpgsm_status (ctrl, STATUS_VALIDSIG, buf); -- cgit v1.2.3 From c64d5a769e48b7bef1a42503efbf4592d51803d3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 31 Oct 2003 12:14:14 +0000 Subject: The Changelog was not yet ready, so again: * certchain.c (gpgsm_validate_chain): Changed to use ksba_isotime_t. * verify.c (strtimestamp_r, gpgsm_verify): Ditto. * sign.c (gpgsm_sign): Ditto. * keylist.c (print_time, list_cert_std, list_cert_colon): Ditto. * certdump.c (gpgsm_print_time, gpgsm_dump_time, gpgsm_dump_cert): Ditto. --- sm/ChangeLog | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index a8dfc0896..fa618539c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,15 +1,11 @@ 2003-10-31 Werner Koch <wk@gnupg.org> - - * verify.c (strtimestamp_r, gpgsm_verify): - - * sign.c (gpgsm_sign): - - * keylist.c (print_time, list_cert_std, list_cert_colon): - - * certdump.c (gpgsm_print_time, gpgsm_dump_time, gpgsm_dump_cert): - * certchain.c (gpgsm_validate_chain): Changed to use ksba_isotime_t. + * verify.c (strtimestamp_r, gpgsm_verify): Ditto. + * sign.c (gpgsm_sign): Ditto. + * keylist.c (print_time, list_cert_std, list_cert_colon): Ditto. + * certdump.c (gpgsm_print_time, gpgsm_dump_time, gpgsm_dump_cert): + Ditto. 2003-10-25 Werner Koch <wk@gnupg.org> -- cgit v1.2.3 From f794da4ad4bed3f46648b6dd38eb3f58c6ea2d0d Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Mon, 10 Nov 2003 10:42:43 +0000 Subject: 2003-11-10 Moritz Schulte <mo@g10code.com> * Makefile.am (INCLUDES): Added: @LIBGCRYPT_CFLAGS@. --- g10/ChangeLog | 4 ++++ g10/Makefile.am | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index c6dfa1db7..d15c54a09 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2003-11-10 Moritz Schulte <mo@g10code.com> + + * Makefile.am (INCLUDES): Added: @LIBGCRYPT_CFLAGS@. + 2003-10-25 Werner Koch <wk@gnupg.org> * call-agent.c (learn_status_cb, scd_genkey_cb): Fixed faulty use diff --git a/g10/Makefile.am b/g10/Makefile.am index ef2b0c3a8..00a49df1e 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -20,7 +20,7 @@ ## Process this file with automake to produce Makefile.in localedir = $(datadir)/locale -INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/include -I$(top_srcdir)/intl -DLOCALEDIR=\"$(localedir)\" +INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/include -I$(top_srcdir)/intl -DLOCALEDIR=\"$(localedir)\" @LIBGCRYPT_CFLAGS@ EXTRA_DIST = options.skel # it seems that we can't use this with automake 1.5 -- cgit v1.2.3 From dba40e5e45e80896dc8864c2ae97f026069e2906 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 12 Nov 2003 15:17:44 +0000 Subject: Mainly changes to adjust for the changed KSBA API. --- agent/command.c | 4 ++-- agent/genkey.c | 2 +- agent/pkdecrypt.c | 1 - agent/pksign.c | 5 +++-- common/ChangeLog | 4 ++++ common/maperror.c | 43 ---------------------------------------- common/util.h | 2 -- g10/misc.c | 2 ++ jnlib/ChangeLog | 4 ++++ jnlib/strlist.h | 23 +++++++++++++--------- kbx/ChangeLog | 6 ++++++ kbx/keybox-blob.c | 1 + kbx/keybox-defs.h | 7 ++++--- kbx/keybox-search.c | 12 ++++++------ scd/ChangeLog | 4 ++++ scd/card-dinsig.c | 13 ++++++------- scd/card-p15.c | 13 ++++++------- scd/card.c | 3 ++- scd/command.c | 12 +++++------- sm/ChangeLog | 4 ++++ sm/base64.c | 21 ++++++++++---------- sm/call-agent.c | 10 +++++----- sm/call-dirmngr.c | 8 ++++---- sm/certchain.c | 12 ++++++------ sm/certcheck.c | 4 ++-- sm/certlist.c | 6 +++--- sm/certreqgen.c | 26 ++++++++++++------------- sm/decrypt.c | 30 ++++++++++++++-------------- sm/encrypt.c | 40 ++++++++++++++++++-------------------- sm/export.c | 2 +- sm/fingerprint.c | 4 ++-- sm/import.c | 29 +++++++++------------------ sm/keylist.c | 14 +++++++------- sm/misc.c | 3 ++- sm/sign.c | 56 ++++++++++++++++++++++++++--------------------------- sm/verify.c | 31 +++++++++++++++-------------- 36 files changed, 216 insertions(+), 245 deletions(-) diff --git a/agent/command.c b/agent/command.c index f7a042ba9..a3e1c514a 100644 --- a/agent/command.c +++ b/agent/command.c @@ -329,7 +329,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) { int rc; CTRL ctrl = assuan_get_pointer (ctx); - char *value; + unsigned char *value; size_t valuelen; /* First inquire the data to decrypt */ @@ -365,7 +365,7 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; - char *value; + unsigned char *value; size_t valuelen; /* First inquire the parameters */ diff --git a/agent/genkey.c b/agent/genkey.c index 0a0577f17..1417abb02 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -137,7 +137,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, { log_error ("key generation failed: %s\n", gpg_strerror (rc)); xfree (pi); - return map_gcry_err (rc); + return rc; } /* break out the parts */ diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 543a82737..d17c688a0 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -105,7 +105,6 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, if (rc) { log_error ("decryption failed: %s\n", gpg_strerror (rc)); - rc = map_gcry_err (rc); goto leave; } diff --git a/agent/pksign.c b/agent/pksign.c index 342582177..d5fe17bb7 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -39,7 +39,9 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) char * p, tmp[16]; int i, rc; -#warning I do do like that stuff - libgcrypt provides easier interfaces. -wk +#ifdef __GNUC__ +#warning I do not like that stuff - libgcrypt provides easier interfaces. -wk +#endif /* FIXME: Either use the build function or create canonical encoded S-expressions. */ @@ -128,7 +130,6 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) if (rc) { log_error ("signing failed: %s\n", gpg_strerror (rc)); - rc = map_gcry_err (rc); goto leave; } diff --git a/common/ChangeLog b/common/ChangeLog index 7dc3c03eb..2eaa954b9 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/maperror.c b/common/maperror.c index f52a5995a..361166388 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -32,49 +32,6 @@ #include "util.h" #include "errors.h" -/* Note: we might want to wrap this in a macro to get our hands on - the line and file where the error occured */ -int -map_ksba_err (int err) -{ - switch (err) - { - case 0: - break; - - case -1: err = GPG_ERR_EOF; break; - case KSBA_Out_Of_Core: err = GPG_ERR_ENOMEM; break; - case KSBA_Invalid_Value: err = GPG_ERR_INV_VALUE; break; - case KSBA_Not_Implemented: err = GPG_ERR_NOT_IMPLEMENTED; break; - case KSBA_Conflict: err = GPG_ERR_CONFLICT; break; - case KSBA_Read_Error: err = GPG_ERR_EIO; break; - case KSBA_Write_Error: err = GPG_ERR_EIO; break; - case KSBA_No_Data: err = GPG_ERR_NO_DATA; break; - case KSBA_Bug: err = GPG_ERR_BUG; break; - case KSBA_Unsupported_Algorithm: err = GPG_ERR_UNSUPPORTED_ALGORITHM; break; - case KSBA_Invalid_Index: err = GPG_ERR_INV_INDEX; break; - case KSBA_Invalid_Sexp: err = GPG_ERR_INV_SEXP; break; - case KSBA_Unknown_Sexp: err = GPG_ERR_UNKNOWN_SEXP; break; - - default: - err = GPG_ERR_GENERAL; - break; - } - return gpg_err_make (GPG_ERR_SOURCE_GPGSM, err); -} - - -int -map_gcry_err (int err) -{ - return err; -} - -int -map_kbx_err (int err) -{ - return err; -} /* Map Assuan error code ERR to an GPG_ERR_ code. We need to distinguish between genuine (and legacy) Assuan error codes and diff --git a/common/util.h b/common/util.h index fb2c6e839..987c8dfe8 100644 --- a/common/util.h +++ b/common/util.h @@ -58,8 +58,6 @@ typedef char gnupg_isotime_t[16]; /*-- maperror.c --*/ -int map_ksba_err (int err); -int map_gcry_err (int err); int map_kbx_err (int err); gpg_error_t map_assuan_err (int err); int map_to_assuan_status (int rc); diff --git a/g10/misc.c b/g10/misc.c index e122f0c5c..7012a8a25 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -246,7 +246,9 @@ openpgp_pk_test_algo( int algo, unsigned int usage_flags ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; +#ifdef __GNUC__ #warning need to handle the usage here? +#endif if (algo < 0 || algo > 110) return GPG_ERR_PUBKEY_ALGO; return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &value); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 594eb340b..7888ff18d 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2003-11-06 Werner Koch <wk@gnupg.org> + + * strlist.h (strlist_t): New. STRLIST is now deprecated. + 2003-06-18 Werner Koch <wk@gnupg.org> * strlist.c (strlist_pop): New. diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 443408f16..ea459d006 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -26,17 +26,22 @@ struct string_list { unsigned int flags; char d[1]; }; -typedef struct string_list *STRLIST; +typedef struct string_list *STRLIST; /* Deprecated. */ +typedef struct string_list *strlist_t; +void free_strlist (strlist_t sl); +strlist_t add_to_strlist (strlist_t *list, const char *string); -void free_strlist( STRLIST sl ); -STRLIST add_to_strlist( STRLIST *list, const char *string ); -/*STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 );*/ -STRLIST append_to_strlist( STRLIST *list, const char *string ); -/*STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 );*/ -STRLIST strlist_prev( STRLIST head, STRLIST node ); -STRLIST strlist_last( STRLIST node ); -char * strlist_pop (STRLIST *list); +/*strlist_t add_to_strlist2( strlist_t *list, + const char *string, int is_utf8);*/ + +strlist_t append_to_strlist (strlist_t *list, const char *string); + +/*strlist_t append_to_strlist2( strlist_t *list, const char *string, + int is_utf8);*/ +strlist_t strlist_prev (strlist_t head, strlist_t node); +strlist_t strlist_last (strlist_t node); +char * strlist_pop (strlist_t *list); #define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index af6e6b016..07a198200 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,9 @@ +2003-11-12 Werner Koch <wk@gnupg.org> + + Adjusted for API changes in Libksba. + + * keybox-blob.c: Include time.h + 2003-06-03 Werner Koch <wk@gnupg.org> Changed all error codes in all files to the new libgpg-error scheme. diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 5ad1d2610..ca36d6264 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -110,6 +110,7 @@ X.509 specific are noted like [X.509: xxx] #include <string.h> #include <errno.h> #include <assert.h> +#include <time.h> #include "keybox-defs.h" #include <gcrypt.h> diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index e4578d76b..fcae64c25 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -21,14 +21,15 @@ #ifndef KEYBOX_DEFS_H #define KEYBOX_DEFS_H 1 -#include <sys/types.h> /* off_t */ -#include "keybox.h" - #ifdef GPG_ERR_SOURCE_DEFAULT #error GPG_ERR_SOURCE_DEFAULT already defined #endif #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_KEYBOX + #include <gpg-error.h> +#include <sys/types.h> /* off_t */ +#include "keybox.h" + #ifndef HAVE_BYTE_TYPEDEF diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index 231a32d42..ff95815a2 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -778,9 +778,9 @@ keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert) if (cert_off+cert_len > length) return gpg_error (GPG_ERR_TOO_SHORT); - reader = ksba_reader_new (); - if (!reader) - return gpg_error (GPG_ERR_ENOMEM); + rc = ksba_reader_new (&reader); + if (rc) + return rc; rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len); if (rc) { @@ -789,11 +789,11 @@ keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert) return gpg_error (GPG_ERR_GENERAL); } - cert = ksba_cert_new (); - if (!cert) + rc = ksba_cert_new (&cert); + if (rc) { ksba_reader_release (reader); - return gpg_error (GPG_ERR_ENOMEM); + return rc; } rc = ksba_cert_read_der (cert, reader); diff --git a/scd/ChangeLog b/scd/ChangeLog index d3282b38a..cccd3b669 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2003-11-12 Werner Koch <wk@gnupg.org> + + Adjusted for API changes in Libksba. + 2003-10-30 Werner Koch <wk@gnupg.org> * apdu.c (close_ct_reader, close_pcsc_reader): Implemented. diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c index 391a51da8..18a67abb6 100644 --- a/scd/card-dinsig.c +++ b/scd/card-dinsig.c @@ -79,9 +79,9 @@ #ifdef HAVE_OPENSC #include <opensc/pkcs15.h> +#include "scdaemon.h" #include <ksba.h> -#include "scdaemon.h" #include "card-common.h" static int dinsig_read_cert (CARD card, const char *certidstr, @@ -113,12 +113,11 @@ dinsig_enum_keypairs (CARD card, int idx, if (rc) return rc; - cert = ksba_cert_new (); - if (!cert) + rc = ksba_cert_new (&cert); + if (rc) { - gpg_error_t tmperr = out_of_core (); xfree (buf); - return tmperr; + return rc; } krc = ksba_cert_init_from_mem (cert, buf, buflen); @@ -126,9 +125,9 @@ dinsig_enum_keypairs (CARD card, int idx, if (krc) { log_error ("failed to parse the certificate at idx %d: %s\n", - idx, ksba_strerror (krc)); + idx, gpg_strerror (krc)); ksba_cert_release (cert); - return gpg_error (GPG_ERR_CARD); + return krc; } if (card_help_get_keygrip (cert, keygrip)) { diff --git a/scd/card-p15.c b/scd/card-p15.c index dfb05c03f..33c58e2c8 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -27,9 +27,9 @@ #ifdef HAVE_OPENSC #include <opensc/pkcs15.h> -#include <ksba.h> #include "scdaemon.h" +#include <ksba.h> #include "card-common.h" @@ -148,21 +148,20 @@ p15_enum_keypairs (CARD card, int idx, return gpg_error (GPG_ERR_CARD); } - cert = ksba_cert_new (); - if (!cert) + rc = ksba_cert_new (&cert); + if (rc) { - gpg_error_t tmperr = out_of_core (); sc_pkcs15_free_certificate (certder); - return tmperr; + return rc; } krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len); sc_pkcs15_free_certificate (certder); if (krc) { log_error ("failed to parse the certificate for private key %d: %s\n", - idx, ksba_strerror (krc)); + idx, gpg_strerror (krc)); ksba_cert_release (cert); - return gpg_error (GPG_ERR_CARD); + return krc; } if (card_help_get_keygrip (cert, keygrip)) { diff --git a/scd/card.c b/scd/card.c index 0a71fb2df..042613294 100644 --- a/scd/card.c +++ b/scd/card.c @@ -28,9 +28,10 @@ #ifdef HAVE_OPENSC #include <opensc/pkcs15.h> #endif -#include <ksba.h> #include "scdaemon.h" +#include <ksba.h> + #include "card-common.h" /* Map the SC error codes to the GNUPG ones */ diff --git a/scd/command.c b/scd/command.c index 363b46480..122a2f3c1 100644 --- a/scd/command.c +++ b/scd/command.c @@ -25,11 +25,11 @@ #include <string.h> #include <ctype.h> #include <unistd.h> -#include <ksba.h> #include <assuan.h> #include "scdaemon.h" +#include <ksba.h> #include "app-common.h" /* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */ @@ -453,18 +453,16 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line) goto leave; } - kc = ksba_cert_new (); - if (!kc) + rc = ksba_cert_new (&kc); + if (rc) { - rc = out_of_core (); xfree (cert); goto leave; } rc = ksba_cert_init_from_mem (kc, cert, ncert); if (rc) { - log_error ("failed to parse the certificate: %s\n", ksba_strerror (rc)); - rc = map_ksba_err (rc); + log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc)); goto leave; } @@ -531,7 +529,7 @@ pin_cb (void *opaque, const char *info, char **retstr) ASSUAN_CONTEXT ctx = opaque; char *command; int rc; - char *value; + unsigned char *value; size_t valuelen; *retstr = NULL; diff --git a/sm/ChangeLog b/sm/ChangeLog index fa618539c..24f71fba6 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2003-11-12 Werner Koch <wk@gnupg.org> + + Adjusted for API changes in Libksba. + 2003-10-31 Werner Koch <wk@gnupg.org> * certchain.c (gpgsm_validate_chain): Changed to use ksba_isotime_t. diff --git a/sm/base64.c b/sm/base64.c index 07f546e85..aef287250 100644 --- a/sm/base64.c +++ b/sm/base64.c @@ -27,9 +27,10 @@ #include <time.h> #include <assert.h> +#include "gpgsm.h" + #include <ksba.h> -#include "gpgsm.h" #include "i18n.h" #ifdef HAVE_DOSISH_SYSTEM @@ -427,7 +428,7 @@ base64_writer_cb (void *cb_value, const void *buffer, size_t count) parm->base64.idx = idx; parm->base64.quad_count = quad_count; - return ferror (fp) ? KSBA_Write_Error:0; + return ferror (fp) ? gpg_error_from_errno (errno) : 0; } static int @@ -506,11 +507,11 @@ gpgsm_create_reader (Base64Context *ctx, if (!*ctx) return OUT_OF_CORE (errno); - r = ksba_reader_new (); - if (!r) + rc = ksba_reader_new (&r); + if (rc) { xfree (*ctx); *ctx = NULL; - return gpg_error (GPG_ERR_ENOMEM); + return rc; } (*ctx)->u.rparm.fp = fp; @@ -537,7 +538,7 @@ gpgsm_create_reader (Base64Context *ctx, { ksba_reader_release (r); xfree (*ctx); *ctx = NULL; - return map_ksba_err (rc); + return rc; } *r_reader = r; @@ -571,11 +572,11 @@ gpgsm_create_writer (Base64Context *ctx, if (!*ctx) return OUT_OF_CORE (errno); - w = ksba_writer_new (); - if (!w) + rc = ksba_writer_new (&w); + if (rc) { xfree (*ctx); *ctx = NULL; - return gpg_error (GPG_ERR_ENOMEM); + return rc; } if (ctrl->create_pem || ctrl->create_base64) @@ -593,7 +594,7 @@ gpgsm_create_writer (Base64Context *ctx, { ksba_writer_release (w); xfree (*ctx); *ctx = NULL; - return map_ksba_err (rc); + return rc; } *r_writer = w; diff --git a/sm/call-agent.c b/sm/call-agent.c index 4d26e3450..acb4ac190 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -622,18 +622,18 @@ learn_cb (void *opaque, const void *buffer, size_t length) /* FIXME: this should go into import.c */ - cert = ksba_cert_new (); - if (!cert) + rc = ksba_cert_new (&cert); + if (rc) { - parm->error = gpg_error (GPG_ERR_ENOMEM); + parm->error = rc; return 0; } rc = ksba_cert_init_from_mem (cert, buf, len); if (rc) { - log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); + log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc)); ksba_cert_release (cert); - parm->error = map_ksba_err (rc); + parm->error = rc; return 0; } diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index b182b246c..fa7f34f8b 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -357,16 +357,16 @@ lookup_cb (void *opaque, const void *buffer, size_t length) return 0; } - cert = ksba_cert_new (); - if (!cert) + rc = ksba_cert_new (&cert); + if (rc) { - parm->error = gpg_error (GPG_ERR_ENOMEM); + parm->error = rc; return 0; } rc = ksba_cert_init_from_mem (cert, buf, len); if (rc) { - log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc)); + log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc)); } else { diff --git a/sm/certchain.c b/sm/certchain.c index 216b72e0e..a25e08219 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -62,7 +62,7 @@ unknown_criticals (KsbaCert cert) } } if (err && err != -1) - rc = map_ksba_err (err); + rc = err; return rc; } @@ -75,7 +75,7 @@ allowed_ca (KsbaCert cert, int *chainlen) err = ksba_cert_is_ca (cert, &flag, chainlen); if (err) - return map_ksba_err (err); + return err; if (!flag) { log_error (_("issuer certificate is not marked as a CA\n")); @@ -94,10 +94,10 @@ check_cert_policy (KsbaCert cert) int any_critical; err = ksba_cert_get_cert_policies (cert, &policies); - if (err == KSBA_No_Data) + if (gpg_err_code (err) == GPG_ERR_NO_DATA) return 0; /* no policy given */ if (err) - return map_ksba_err (err); + return err; /* STRING is a line delimited list of certifiate policies as stored in the certificate. The line itself is colon delimited where the @@ -471,7 +471,7 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) if (rc) { log_error (_("certificate with invalid validity: %s\n"), - ksba_strerror (rc)); + gpg_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } @@ -522,7 +522,7 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) rc = gpgsm_dirmngr_isvalid (subject_cert); if (rc) { - switch (rc) + switch (gpg_err_code (rc)) { case GPG_ERR_CERT_REVOKED: log_error (_("the certificate has been revoked\n")); diff --git a/sm/certcheck.c b/sm/certcheck.c index 35509c67e..852c75e3a 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -129,9 +129,9 @@ gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert) rc = ksba_cert_hash (cert, 1, HASH_FNC, md); if (rc) { - log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); + log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); - return map_ksba_err (rc); + return rc; } gcry_md_final (md); diff --git a/sm/certlist.c b/sm/certlist.c index eedc99025..0dfe50e04 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -45,7 +45,7 @@ cert_usage_p (KsbaCert cert, int mode) unsigned int use; err = ksba_cert_get_key_usage (cert, &use); - if (err == KSBA_No_Data) + if (gpg_err_code (err) == GPG_ERR_NO_DATA) { if (opt.verbose && mode < 2) log_info (mode? @@ -56,8 +56,8 @@ cert_usage_p (KsbaCert cert, int mode) if (err) { log_error (_("error getting key usage information: %s\n"), - ksba_strerror (err)); - return map_ksba_err (err); + gpg_strerror (err)); + return err; } if (mode == 4) diff --git a/sm/certreqgen.c b/sm/certreqgen.c index efb3e8c1a..06a788ad9 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -513,9 +513,9 @@ create_request (struct para_data_s *para, KsbaConstSexp public, int rc = 0; const char *s; - cr = ksba_certreq_new (); - if (!cr) - return gpg_error (GPG_ERR_ENOMEM); + err = ksba_certreq_new (&cr); + if (err) + return err; rc = gcry_md_open (&md, GCRY_MD_SHA1, 0); if (rc) @@ -533,8 +533,8 @@ create_request (struct para_data_s *para, KsbaConstSexp public, if (err) { log_error ("error setting the subject's name: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -557,8 +557,8 @@ create_request (struct para_data_s *para, KsbaConstSexp public, if (err) { log_error ("error setting the subject's alternate name: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } @@ -568,8 +568,8 @@ create_request (struct para_data_s *para, KsbaConstSexp public, if (err) { log_error ("error setting the public key: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -578,8 +578,8 @@ create_request (struct para_data_s *para, KsbaConstSexp public, err = ksba_certreq_build (cr, &stopreason); if (err) { - log_error ("ksba_certreq_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_error ("ksba_certreq_build failed: %s\n", gpg_strerror (err)); + rc = err; goto leave; } if (stopreason == KSBA_SR_NEED_SIG) @@ -630,8 +630,8 @@ create_request (struct para_data_s *para, KsbaConstSexp public, if (err) { log_error ("failed to store the sig_val: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } diff --git a/sm/decrypt.c b/sm/decrypt.c index 17483aa49..23858efa8 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -159,10 +159,10 @@ decrypt_filter (void *arg, /* fixme: Should we issue an error when we have not seen one full block? */ if (!inlen) - return KSBA_Bug; + return gpg_error (GPG_ERR_BUG); if (maxoutlen < 2*parm->blklen) - return KSBA_Bug; + return gpg_error (GPG_ERR_BUG); /* make some space becuase we will later need an extra block at the end */ maxoutlen -= blklen; @@ -174,7 +174,7 @@ decrypt_filter (void *arg, parm->helpblock[i] = ((const char*)inbuf)[j]; inlen -= j; if (blklen > maxoutlen) - return KSBA_Bug; + return gpg_error (GPG_ERR_BUG); if (i < blklen) { parm->helpblocklen = i; @@ -285,10 +285,10 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) goto leave; } - cms = ksba_cms_new (); - if (!cms) + err = ksba_cms_new (&cms); + if (err) { - rc = gpg_error (GPG_ERR_ENOMEM); + rc = err; goto leave; } @@ -296,8 +296,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) if (err) { log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -307,8 +307,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) err = ksba_cms_parse (cms, &stopreason); if (err) { - log_debug ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (err)); + rc = err; goto leave; } @@ -352,8 +352,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) &dfparm.ivlen); if (rc) { - log_error ("error getting IV: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_error ("error getting IV: %s\n", gpg_strerror (err)); + rc = err; goto leave; } @@ -369,7 +369,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) break; /* no more recipients */ if (err) log_error ("recp %d - error getting info: %s\n", - recp, ksba_strerror (err)); + recp, gpg_strerror (err)); else { KsbaCert cert = NULL; @@ -461,10 +461,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) dfparm.lastblock, dfparm.blklen - npadding); if (rc) - { - rc = map_ksba_err (rc); goto leave; - } + for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++) { if (dfparm.lastblock[i] != npadding) diff --git a/sm/encrypt.c b/sm/encrypt.c index 4eef20c73..616949bf4 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -330,16 +330,14 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) goto leave; } - reader = ksba_reader_new (); - if (!reader) - rc = KSBA_Out_Of_Core; + err = ksba_reader_new (&reader); + if (err) + rc = err; if (!rc) rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm); if (rc) - { - rc = map_ksba_err (rc); goto leave; - } + encparm.fp = data_fp; ctrl->pem_name = "ENCRYPTED MESSAGE"; @@ -350,10 +348,10 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) goto leave; } - cms = ksba_cms_new (); - if (!cms) + err = ksba_cms_new (&cms); + if (err) { - rc = gpg_error (GPG_ERR_ENOMEM); + rc = err; goto leave; } @@ -361,8 +359,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) if (err) { log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -374,8 +372,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) if (err) { log_debug ("ksba_cms_set_content_type failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -399,8 +397,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) if (err) { log_error ("ksba_cms_set_content_enc_algo failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -432,8 +430,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) if (err) { log_error ("ksba_cms_add_recipient failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; xfree (encval); goto leave; } @@ -443,8 +441,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) if (err) { log_error ("ksba_cms_set_enc_val failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } @@ -456,8 +454,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) err = ksba_cms_build (cms, &stopreason); if (err) { - log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err)); + rc = err; goto leave; } } diff --git a/sm/export.c b/sm/export.c index 93a55debc..73c119fb0 100644 --- a/sm/export.c +++ b/sm/export.c @@ -155,7 +155,7 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) rc = ksba_writer_write (writer, image, imagelen); if (rc) { - log_error ("write error: %s\n", ksba_strerror (rc)); + log_error ("write error: %s\n", gpg_strerror (rc)); goto leave; } diff --git a/sm/fingerprint.c b/sm/fingerprint.c index 028c08aab..ec1ed91f2 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -70,7 +70,7 @@ gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len) rc = ksba_cert_hash (cert, 0, HASH_FNC, md); if (rc) { - log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); + log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); memset (array, 0xff, len); /* better return an invalid fpr than NULL */ return array; @@ -204,7 +204,7 @@ gpgsm_get_keygrip_hexstring (KsbaCert cert) serial number for this. In most cases the serial number is not that large and the resulting string can be passed on an assuan command line. Everything is hexencoded with the serialnumber - delimted from the has by a dot. + delimited from the hash by a dot. The caller must free the string. */ diff --git a/sm/import.c b/sm/import.c index 17dc3d66c..758cd3208 100644 --- a/sm/import.c +++ b/sm/import.c @@ -221,19 +221,15 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) KsbaStopReason stopreason; int i; - cms = ksba_cms_new (); - if (!cms) - { - rc = gpg_error (GPG_ERR_ENOMEM); - goto leave; - } + rc = ksba_cms_new (&cms); + if (rc) + goto leave; rc = ksba_cms_set_reader_writer (cms, reader, NULL); if (rc) { log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (rc)); - rc = map_ksba_err (rc); + gpg_strerror (rc)); goto leave; } @@ -243,8 +239,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) rc = ksba_cms_parse (cms, &stopreason); if (rc) { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (rc)); - rc = map_ksba_err (rc); + log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } @@ -265,19 +260,13 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) else if (ct == KSBA_CT_NONE) { /* Failed to identify this message - assume a certificate */ - cert = ksba_cert_new (); - if (!cert) - { - rc = gpg_error (GPG_ERR_ENOMEM); - goto leave; - } + rc = ksba_cert_new (&cert); + if (rc) + goto leave; rc = ksba_cert_read_der (cert, reader); if (rc) - { - rc = map_ksba_err (rc); - goto leave; - } + goto leave; check_and_store (ctrl, stats, cert, 0); } diff --git a/sm/keylist.c b/sm/keylist.c index 548f2a452..7b7402fab 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -68,7 +68,7 @@ print_capabilities (KsbaCert cert, FILE *fp) unsigned int use; err = ksba_cert_get_key_usage (cert, &use); - if (err == KSBA_No_Data) + if (gpg_err_code (err) == GPG_ERR_NO_DATA) { putc ('e', fp); putc ('s', fp); @@ -81,7 +81,7 @@ print_capabilities (KsbaCert cert, FILE *fp) if (err) { log_error (_("error getting key usage information: %s\n"), - ksba_strerror (err)); + gpg_strerror (err)); return; } @@ -328,11 +328,11 @@ list_cert_std (KsbaCert cert, FILE *fp, int have_secret) putc ('\n', fp); kerr = ksba_cert_get_key_usage (cert, &kusage); - if (kerr != KSBA_No_Data) + if (gpg_err_code (kerr) != GPG_ERR_NO_DATA) { fputs (" key usage:", fp); if (kerr) - fprintf (fp, " [error: %s]", ksba_strerror (kerr)); + fprintf (fp, " [error: %s]", gpg_strerror (kerr)); else { if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE)) @@ -358,11 +358,11 @@ list_cert_std (KsbaCert cert, FILE *fp, int have_secret) } kerr = ksba_cert_get_cert_policies (cert, &string); - if (kerr != KSBA_No_Data) + if (gpg_err_code (kerr) != GPG_ERR_NO_DATA) { fputs (" policies: ", fp); if (kerr) - fprintf (fp, "[error: %s]", ksba_strerror (kerr)); + fprintf (fp, "[error: %s]", gpg_strerror (kerr)); else { for (p=string; *p; p++) @@ -381,7 +381,7 @@ list_cert_std (KsbaCert cert, FILE *fp, int have_secret) { fputs (" chain length: ", fp); if (kerr) - fprintf (fp, "[error: %s]", ksba_strerror (kerr)); + fprintf (fp, "[error: %s]", gpg_strerror (kerr)); else if (chainlen == -1) fputs ("unlimited", fp); else diff --git a/sm/misc.c b/sm/misc.c index 3260b90b2..4ffa7153e 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -26,7 +26,8 @@ #include <ctype.h> #include <unistd.h> +#include "gpgsm.h" + #include <ksba.h> -#include "gpgsm.h" diff --git a/sm/sign.c b/sm/sign.c index 8e7431312..95ce8d5dd 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -88,8 +88,8 @@ hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer) err = ksba_writer_write_octet_string (writer, buffer, nread, 0); if (err) { - log_error ("write failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_error ("write failed: %s\n", gpg_strerror (err)); + rc = err; } } } @@ -114,8 +114,8 @@ hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer) err = ksba_writer_write_octet_string (writer, NULL, 0, 1); if (err) { - log_error ("write failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_error ("write failed: %s\n", gpg_strerror (err)); + rc = err; } } @@ -278,8 +278,8 @@ add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert) ksba_failure: ksba_cert_release (cert); - log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err)); - return map_ksba_err (err); + log_error ("ksba_cms_add_cert failed: %s\n", gpg_strerror (err)); + return err; } @@ -326,10 +326,10 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, goto leave; } - cms = ksba_cms_new (); - if (!cms) + err = ksba_cms_new (&cms); + if (err) { - rc = gpg_error (GPG_ERR_ENOMEM); + rc = err; goto leave; } @@ -337,8 +337,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_debug ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -349,8 +349,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_debug ("ksba_cms_set_content_type failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -386,8 +386,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, err = ksba_cms_add_signer (cms, cl->cert); if (err) { - log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_error ("ksba_cms_add_signer failed: %s\n", gpg_strerror (err)); + rc = err; goto leave; } rc = add_certificate_list (ctrl, cms, cl->cert); @@ -402,8 +402,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_debug ("ksba_cms_add_digest_algo failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } @@ -455,8 +455,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_error ("ksba_cms_set_message_digest failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } @@ -469,8 +469,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_error ("ksba_cms_set_signing_time failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } @@ -480,8 +480,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, err = ksba_cms_build (cms, &stopreason); if (err) { - log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err)); + rc = err; goto leave; } @@ -515,8 +515,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_error ("ksba_cms_set_message_digest failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } } @@ -546,7 +546,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (rc) { log_debug ("hashing signed attrs failed: %s\n", - ksba_strerror (rc)); + gpg_strerror (rc)); gcry_md_close (md); goto leave; } @@ -563,8 +563,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (err) { log_error ("failed to store the signature: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; gcry_md_close (md); goto leave; } diff --git a/sm/verify.c b/sm/verify.c index 3c333129b..201fc7b55 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -135,8 +135,8 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) } } - cms = ksba_cms_new (); - if (!cms) + err = ksba_cms_new (&cms); + if (err) { rc = gpg_error (GPG_ERR_ENOMEM); goto leave; @@ -146,8 +146,8 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) if (err) { log_error ("ksba_cms_set_reader_writer failed: %s\n", - ksba_strerror (err)); - rc = map_ksba_err (err); + gpg_strerror (err)); + rc = err; goto leave; } @@ -166,8 +166,8 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) err = ksba_cms_parse (cms, &stopreason); if (err) { - log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (err)); - rc = map_ksba_err (err); + log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (err)); + rc = err; goto leave; } @@ -250,7 +250,8 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) char *ctattr; err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); - if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached) + if (!signer && gpg_err_code (err) == GPG_ERR_NO_DATA + && data_fd == -1 && is_detached) { log_info ("certs-only message accepted\n"); err = 0; @@ -272,11 +273,11 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) } err = ksba_cms_get_signing_time (cms, signer, sigtime); - if (err == KSBA_No_Data) + if (gpg_err_code (err) == GPG_ERR_NO_DATA) *sigtime = 0; else if (err) { - log_error ("error getting signing time: %s\n", ksba_strerror (err)); + log_error ("error getting signing time: %s\n", gpg_strerror (err)); *sigtime = 0; /* FIXME: we can't encode an error in the time string. */ } @@ -295,7 +296,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) goto next_signer; } } - else if (err == KSBA_No_Data) + else if (gpg_err_code (err) == GPG_ERR_NO_DATA) { assert (!msgdigest); err = 0; @@ -328,7 +329,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) else if (err != -1) { log_error ("error getting content-type attribute: %s\n", - ksba_strerror (err)); + gpg_strerror (err)); goto next_signer; } err = 0; @@ -420,7 +421,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) if (rc) { log_error ("hashing signed attrs failed: %s\n", - ksba_strerror (rc)); + gpg_strerror (rc)); gcry_md_close (md); goto next_signer; } @@ -514,9 +515,9 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) } rc = 0; if (err) - { - log_error ("ksba error: %s\n", ksba_strerror (err)); - rc = map_ksba_err (rc); + { /* FIXME: still needed? */ + log_error ("ksba error: %s\n", gpg_strerror (err)); + rc = err; } -- cgit v1.2.3 From 53272a25fc0ae7098a2cd1e7eab550ce080438a7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 13 Nov 2003 07:37:18 +0000 Subject: (vasprintf): ARGS should not be a pointer. Fixed segv on Solaris. Reported by Andrew J. Schorr. --- THANKS | 2 ++ common/ChangeLog | 5 +++++ common/vasprintf.c | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/THANKS b/THANKS index 9047c1c18..e6cac5b9c 100644 --- a/THANKS +++ b/THANKS @@ -1,3 +1,5 @@ Richard Lefebvre rick@CERCA.UMontreal.CA +Andrew J. Schorr aschorr@telemetry-investments.com + diff --git a/common/ChangeLog b/common/ChangeLog index 2eaa954b9..1c63b5248 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2003-11-13 Werner Koch <wk@gnupg.org> + + * 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. diff --git a/common/vasprintf.c b/common/vasprintf.c index 2af2d3a20..9efea33f2 100644 --- a/common/vasprintf.c +++ b/common/vasprintf.c @@ -31,7 +31,7 @@ int global_total_width; #endif int -vasprintf (char **result, const char *format, va_list *args) +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 @@ -120,7 +120,7 @@ vasprintf (char **result, const char *format, va_list *args) #endif *result = malloc (total_width); if (*result != NULL) - return vsprintf (*result, format, *args); + return vsprintf (*result, format, args); else return 0; } -- cgit v1.2.3 From 9b32497c7e78d362e2be2a9c0dff1a589c725594 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 13 Nov 2003 19:15:38 +0000 Subject: (vasprintf): Also fixed the prototype. --- common/ChangeLog | 2 ++ common/util.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index 1c63b5248..afc48367c 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,7 @@ 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. diff --git a/common/util.h b/common/util.h index 987c8dfe8..e38ced337 100644 --- a/common/util.h +++ b/common/util.h @@ -112,7 +112,7 @@ 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 vasprintf (char **result, const char *format, va_list args); int asprintf (char **result, const char *format, ...); #endif -- cgit v1.2.3 From ecba8bf1f5268f7a3b44e45c5648ff73e3e3c8da Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 14 Nov 2003 11:36:04 +0000 Subject: Removed. --- common/ChangeLog | 4 ++++ common/Makefile.am | 1 - common/cryptmiss.c | 39 --------------------------------------- 3 files changed, 4 insertions(+), 40 deletions(-) delete mode 100644 common/cryptmiss.c diff --git a/common/ChangeLog b/common/ChangeLog index afc48367c..da80507f2 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2003-11-14 Werner Koch <wk@gnupg.org> + + * cryptmiss.c: Removed. + 2003-11-13 Werner Koch <wk@gnupg.org> * util.h (vasprintf): Also fixed the prototype. diff --git a/common/Makefile.am b/common/Makefile.am index 3fd1c9454..79dedca34 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -31,7 +31,6 @@ libcommon_a_SOURCES = \ errors.h \ maperror.c \ sysutils.c sysutils.h \ - cryptmiss.c \ gettime.c \ yesno.c \ miscellaneous.c \ diff --git a/common/cryptmiss.c b/common/cryptmiss.c deleted file mode 100644 index ae639db1d..000000000 --- a/common/cryptmiss.c +++ /dev/null @@ -1,39 +0,0 @@ -/* cryptmiss.c - Missing functions in libgcrypt - * 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 - */ - -#include <config.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#include "util.h" - -char * -gcry_strdup (const char *string) -{ - char *p; - - p = gcry_malloc (strlen (string)+1); - if (p) - strcpy (p, string); - return p; -} -- cgit v1.2.3 From 19d65e2b4b0c85f6d6b8789e3fe82ab9905cc2a0 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sun, 16 Nov 2003 15:29:07 +0000 Subject: 2003-11-16 Moritz Schulte <mo@g10code.com> * signal.c: Removed unused file. --- g10/ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/g10/ChangeLog b/g10/ChangeLog index d15c54a09..897836191 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2003-11-16 Moritz Schulte <mo@g10code.com> + + * signal.c: Removed unused file. + 2003-11-10 Moritz Schulte <mo@g10code.com> * Makefile.am (INCLUDES): Added: @LIBGCRYPT_CFLAGS@. -- cgit v1.2.3 From fbb2d9de15df27c26a1c17fbd714c54597e92677 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 17 Nov 2003 12:20:11 +0000 Subject: Preparing for 1.9.2 release. --- ChangeLog | 6 ++++++ NEWS | 4 +++- TODO | 9 +++++++- common/ChangeLog | 2 ++ common/mkdtemp.c | 7 ++---- configure.ac | 10 ++++----- jnlib/ChangeLog | 6 ++++++ jnlib/dotlock.c | 16 ++++++++++++++ jnlib/strlist.c | 65 +++++++++++++++++++++++++++++++++++++------------------- jnlib/strlist.h | 2 ++ 10 files changed, 93 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a830143a..f998dd1b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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 diff --git a/NEWS b/NEWS index b708d44cf..1f8ee3387 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.2 (unreleased) +Noteworthy changes in version 1.9.2 (2003-11-17) ------------------------------------------------ * On card key generation is no longer done using the --gen-key @@ -7,6 +7,8 @@ Noteworthy changes in version 1.9.2 (unreleased) * 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) ------------------------------------------------ diff --git a/TODO b/TODO index e8aa872a1..eb8e2da66 100644 --- a/TODO +++ b/TODO @@ -70,4 +70,11 @@ might want to have an agent context for each service request * scd/sc-investigate ** Enhance with card compatibility check - +* scd/app-openpgp + Do a pre-check to make sure that the minimum length condition of the + PINs are satisied - this avoid useless retry counter decrements in + case the PIN dialog is accidently hit. + + Must check that the fingerprint used is not the one of the + authentication key. Old GnuPG versions seem to encode the wrong + keyID. \ No newline at end of file diff --git a/common/ChangeLog b/common/ChangeLog index da80507f2..2344868a7 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,7 @@ 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> diff --git a/common/mkdtemp.c b/common/mkdtemp.c index 5347b9cb4..abe731e0a 100644 --- a/common/mkdtemp.c +++ b/common/mkdtemp.c @@ -66,11 +66,8 @@ char *mkdtemp(char *template) idx=0; - /* Using really random bits is probably overkill here. The - worst thing that can happen with a directory name collision - is that the function will return an error. */ - - randombits = gcry_random_bytes (4*remaining, GCRY_WEAK_RANDOM); + randombits = gcry_xmalloc (4*remaining); + gcry_create_nonce (randombits, 4*remaining); while(remaining>1) { diff --git a/configure.ac b/configure.ac index 1c6269f49..8886d5075 100644 --- a/configure.ac +++ b/configure.ac @@ -22,14 +22,14 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.2-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.2, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. development_version=yes -NEED_GPG_ERROR_VERSION=0.4 -NEED_LIBGCRYPT_VERSION=1.1.43 -NEED_LIBASSUAN_VERSION=0.6.0 +NEED_GPG_ERROR_VERSION=0.6 +NEED_LIBGCRYPT_VERSION=1.1.90 +NEED_LIBASSUAN_VERSION=0.6.1 NEED_KSBA_VERSION=0.9.0 NEED_OPENSC_VERSION=0.8.0 @@ -948,7 +948,7 @@ if test "$have_ksba" = "no"; then *** *** You need libksba to build this program. *** This library is for example available at -*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/aegypten/ +*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libksba/ *** (at least version $NEED_KSBA_VERSION is required). ***]]) fi diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 7888ff18d..e12dd8e00 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,9 @@ +2003-11-13 Werner Koch <wk@gnupg.org> + + * strlist.c (strlist_copy): New. + + * dotlock.c: Define DIRSEP_C et al. if not defined. + 2003-11-06 Werner Koch <wk@gnupg.org> * strlist.h (strlist_t): New. STRLIST is now deprecated. diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index 7240fafeb..a50a0ee99 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -37,6 +37,22 @@ #include "libjnlib-config.h" #include "dotlock.h" +#if !defined(DIRSEP_C) && !defined(EXTSEP_C) \ + && !defined(DIRSEP_S) && !defined(EXTSEP_S) +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\' +#define EXTSEP_C '.' +#define DIRSEP_S "\\" +#define EXTSEP_S "." +#else +#define DIRSEP_C '/' +#define EXTSEP_C '.' +#define DIRSEP_S "/" +#define EXTSEP_S "." +#endif +#endif + + struct dotlock_handle { struct dotlock_handle *next; char *tname; /* name of lockfile template */ diff --git a/jnlib/strlist.c b/jnlib/strlist.c index 063c89c7e..49b510666 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -29,9 +29,9 @@ void -free_strlist( STRLIST sl ) +free_strlist( strlist_t sl ) { - STRLIST sl2; + strlist_t sl2; for(; sl; sl = sl2 ) { sl2 = sl->next; @@ -40,10 +40,10 @@ free_strlist( STRLIST sl ) } -STRLIST -add_to_strlist( STRLIST *list, const char *string ) +strlist_t +add_to_strlist( strlist_t *list, const char *string ) { - STRLIST sl; + strlist_t sl; sl = jnlib_xmalloc( sizeof *sl + strlen(string)); sl->flags = 0; @@ -58,10 +58,10 @@ add_to_strlist( STRLIST *list, const char *string ) * same as add_to_strlist() but if is_utf8 is *not* set a conversion * to UTF8 is done */ -STRLIST -add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +strlist_t +add_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) { - STRLIST sl; + strlist_t sl; if( is_utf8 ) sl = add_to_strlist( list, string ); @@ -74,10 +74,10 @@ add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) } #endif -STRLIST -append_to_strlist( STRLIST *list, const char *string ) +strlist_t +append_to_strlist( strlist_t *list, const char *string ) { - STRLIST r, sl; + strlist_t r, sl; sl = jnlib_xmalloc( sizeof *sl + strlen(string)); sl->flags = 0; @@ -94,10 +94,10 @@ append_to_strlist( STRLIST *list, const char *string ) } #if 0 -STRLIST -append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) +strlist_t +append_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) { - STRLIST sl; + strlist_t sl; if( is_utf8 ) sl = append_to_strlist( list, string ); @@ -110,18 +110,40 @@ append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) } #endif -STRLIST -strlist_prev( STRLIST head, STRLIST node ) + +/* Return a copy of LIST. */ +strlist_t +strlist_copy (strlist_t list) +{ + strlist_t newlist = NULL, sl, *last; + + last = &newlist; + for (; list; list = list->next) + { + sl = jnlib_xmalloc (sizeof *sl + strlen (list->d)); + sl->flags = list->flags; + strcpy(sl->d, list->d); + sl->next = NULL; + *last = sl; + last = &sl; + } + return newlist; +} + + + +strlist_t +strlist_prev( strlist_t head, strlist_t node ) { - STRLIST n; + strlist_t n; for(n=NULL; head && head != node; head = head->next ) n = head; return n; } -STRLIST -strlist_last( STRLIST node ) +strlist_t +strlist_last( strlist_t node ) { if( node ) for( ; node->next ; node = node->next ) @@ -131,10 +153,10 @@ strlist_last( STRLIST node ) char * -strlist_pop (STRLIST *list) +strlist_pop (strlist_t *list) { char *str=NULL; - STRLIST sl=*list; + strlist_t sl=*list; if(sl) { @@ -148,4 +170,3 @@ strlist_pop (STRLIST *list) return str; } - diff --git a/jnlib/strlist.h b/jnlib/strlist.h index ea459d006..72da241bc 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -37,6 +37,8 @@ strlist_t add_to_strlist (strlist_t *list, const char *string); strlist_t append_to_strlist (strlist_t *list, const char *string); +strlist_t strlist_copy (strlist_t list); + /*strlist_t append_to_strlist2( strlist_t *list, const char *string, int is_utf8);*/ strlist_t strlist_prev (strlist_t head, strlist_t node); -- cgit v1.2.3 From 2f3d309750b0d669ab09b2d4edd9e8b0471d7dd0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 17 Nov 2003 12:56:43 +0000 Subject: *** empty log message *** --- NEWS | 3 +++ configure.ac | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 1f8ee3387..7a047750e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +Noteworthy changes in version 1.9.3 (unreleased) +------------------------------------------------ + Noteworthy changes in version 1.9.2 (2003-11-17) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 8886d5075..7eed5f393 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.52) # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.2, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.3-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 2f2eb1d202d6486476b0a2be4a639627ae3c20a3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 18 Nov 2003 17:29:51 +0000 Subject: * verify.c (gpgsm_verify): Fixed for changes API of gcry_md_info. * certchain.c (unknown_criticals): Fixed an error code test. --- sm/ChangeLog | 6 ++++++ sm/certchain.c | 2 +- sm/verify.c | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 24f71fba6..4b6e579b6 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2003-11-18 Werner Koch <wk@gnupg.org> + + * verify.c (gpgsm_verify): Fixed for changes API of gcry_md_info. + + * certchain.c (unknown_criticals): Fixed an error code test. + 2003-11-12 Werner Koch <wk@gnupg.org> Adjusted for API changes in Libksba. diff --git a/sm/certchain.c b/sm/certchain.c index a25e08219..50e910240 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -61,7 +61,7 @@ unknown_criticals (KsbaCert cert) rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT); } } - if (err && err != -1) + if (err && gpg_err_code (err) != GPG_ERR_EOF) rc = err; return rc; diff --git a/sm/verify.c b/sm/verify.c index 201fc7b55..e6e08c06c 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -286,11 +286,16 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) &msgdigest, &msgdigestlen); if (!err) { + size_t is_enabled; + algoid = ksba_cms_get_digest_algo (cms, signer); algo = gcry_md_map_name (algoid); if (DBG_X509) log_debug ("signer %d - digest algo: %d\n", signer, algo); - if ( !gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, NULL) ) + is_enabled = sizeof algo; + if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, + &algo, &is_enabled) + || !is_enabled) { log_error ("digest algo %d has not been enabled\n", algo); goto next_signer; -- cgit v1.2.3 From fbd0f91c824a48b4b9ae09829226f00ecaebf0d8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Dec 2003 10:53:26 +0000 Subject: * sexp-parse.h (snext): Don't use atoi_1 and digitp macros, so that this file is useful by other applications too. --- agent/ChangeLog | 5 +++++ agent/sexp-parse.h | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 005912dff..24b22b7b1 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2003-11-20 Werner Koch <wk@gnupg.org> + + * sexp-parse.h (snext): Don't use atoi_1 and digitp macros, so + that this file is useful by other applications too. + 2003-10-27 Werner Koch <wk@gnupg.org> * command.c (cmd_get_confirmation): New command. diff --git a/agent/sexp-parse.h b/agent/sexp-parse.h index 338321f48..89aa7210f 100644 --- a/agent/sexp-parse.h +++ b/agent/sexp-parse.h @@ -1,5 +1,5 @@ /* sexp-parse.h - S-Exp helper functions - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -21,10 +21,10 @@ #ifndef SEXP_PARSE_H #define SEXP_PARSE_H -#include "../common/util.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 return on error */ + the first data byte. 0 is returned on error */ static inline size_t snext (unsigned char const **buf) { @@ -32,8 +32,8 @@ snext (unsigned char const **buf) int n; s = *buf; - for (n=0; *s && *s != ':' && digitp (s); s++) - n = n*10 + atoi_1 (s); + 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; @@ -46,7 +46,7 @@ snext (unsigned char const **buf) 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 int +static inline gpg_error_t sskip (unsigned char const **buf, int *depth) { const unsigned char *s = *buf; @@ -83,7 +83,8 @@ sskip (unsigned char const **buf, int *depth) /* 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. */ + 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) { -- cgit v1.2.3 From 6b7af47bccea369de9215eaa7fc6396b7a5222c7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Dec 2003 10:53:40 +0000 Subject: (Certificate Options): Add --{enable,disable}-ocsp. --- NEWS | 4 ++++ doc/ChangeLog | 9 +++++++++ doc/gpgsm.texi | 9 +++++++++ doc/scdaemon.texi | 11 +++++++++++ 4 files changed, 33 insertions(+) diff --git a/NEWS b/NEWS index 7a047750e..8aff1add1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.9.3 (unreleased) ------------------------------------------------ + * New options --{enable,disable}-ocsp to validate keys using OCSP + This requires at least DirMngr 0.5.1 to work. Default is disabled. + + Noteworthy changes in version 1.9.2 (2003-11-17) ------------------------------------------------ diff --git a/doc/ChangeLog b/doc/ChangeLog index 1c335280c..583415cab 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,12 @@ +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. diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 4d91bda5b..6695eef67 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -250,6 +250,15 @@ 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 --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 diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 3bd8caaa8..e62146837 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -146,6 +146,17 @@ default is 32768 (first USB device). 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 -- cgit v1.2.3 From 7134af9fdb194ae8291775fed78cd1a82eaaa41b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Dec 2003 10:54:09 +0000 Subject: * scdaemon.c, scdaemon.h: New options --allow-admin and --deny-admin. * app-openpgp.c (verify_chv3): Check it here. --- scd/ChangeLog | 5 +++++ scd/app-openpgp.c | 6 ++++++ scd/scdaemon.c | 9 +++++++-- scd/scdaemon.h | 2 ++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index cccd3b669..873691f63 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2003-11-17 Werner Koch <wk@gnupg.org> + + * scdaemon.c, scdaemon.h: New options --allow-admin and --deny-admin. + * app-openpgp.c (verify_chv3): Check it here. + 2003-11-12 Werner Koch <wk@gnupg.org> Adjusted for API changes in Libksba. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 07abf9bfb..6b4a2f7ef 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -569,6 +569,12 @@ verify_chv3 (APP app, { int rc = 0; + if (!opt.allow_admin) + { + log_info ("access to admin commands is not configured\n"); + return gpg_error (GPG_ERR_EACCES); + } + if (!app->did_chv3) { char *pinvalue; diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 89be04ab5..a3100988b 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -73,6 +73,8 @@ enum cmd_and_opt_values opcscDriver, oDisableCCID, oDisableOpenSC, + oAllowAdmin, + oDenyAdmin, aTest }; @@ -112,8 +114,8 @@ static ARGPARSE_OPTS opts[] = { "@" #endif /* end --disable-opensc */}, - - + { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")}, + { oDenyAdmin, "deny-admin", 0, "@" }, {0} }; @@ -397,6 +399,9 @@ main (int argc, char **argv ) case oDisableCCID: opt.disable_ccid = 1; break; case oDisableOpenSC: opt.disable_opensc = 1; break; + case oAllowAdmin: opt.allow_admin = 1; break; + case oDenyAdmin: opt.allow_admin = 0; break; + default : pargs.err = configfp? 1:2; break; } } diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 43c3189b3..e13377af7 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -57,6 +57,8 @@ struct { const char *pcsc_driver; /* Library to access the PC/SC system. */ int disable_opensc; /* Disable the use of the OpenSC framework. */ int disable_ccid; /* Disable the use of the internal CCID driver. */ + int allow_admin; /* Allow the use of admin commands for certain + cards. */ } opt; -- cgit v1.2.3 From c68eaa4b6b7fdbdcb2b03ca8ecd7194ddae4dab8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Dec 2003 10:54:30 +0000 Subject: * gpgsm.c, gpgsm.h: New options --{enable,disable}-ocsp. (gpgsm_init_default_ctrl): Set USE_OCSP to the default value. * certchain.c (gpgsm_validate_chain): Handle USE_OCSP. * call-dirmngr.c (gpgsm_dirmngr_isvalid): Add arg USE_OCSP and proceed accordingly. --- sm/ChangeLog | 13 +++++++++++++ sm/call-dirmngr.c | 27 +++++++++++++++++++++------ sm/certchain.c | 8 +++++--- sm/gpgsm.c | 14 ++++++++++++++ sm/gpgsm.h | 6 ++++-- sm/verify.c | 3 ++- 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 4b6e579b6..fc4fcd07a 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,16 @@ +2003-12-01 Werner Koch <wk@gnupg.org> + + * gpgsm.c, gpgsm.h: New options --{enable,disable}-ocsp. + (gpgsm_init_default_ctrl): Set USE_OCSP to the default value. + * certchain.c (gpgsm_validate_chain): Handle USE_OCSP. + * call-dirmngr.c (gpgsm_dirmngr_isvalid): Add arg USE_OCSP and + proceed accordingly. + +2003-11-19 Werner Koch <wk@gnupg.org> + + * verify.c (gpgsm_verify): Use "0" instead of an empty string for + the VALIDSIG status. + 2003-11-18 Werner Koch <wk@gnupg.org> * verify.c (gpgsm_verify): Fixed for changes API of gcry_md_info. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index fa7f34f8b..8700145e3 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -288,9 +288,12 @@ inq_certificate (void *opaque, const char *line) GPG_ERR_CERTIFICATE_REVOKED GPG_ERR_NO_CRL_KNOWN GPG_ERR_CRL_TOO_OLD + + With USE_OCSP set to true, the dirmngr is asked to do an OCSP + request first. */ int -gpgsm_dirmngr_isvalid (KsbaCert cert) +gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp) { int rc; char *certid; @@ -301,23 +304,35 @@ gpgsm_dirmngr_isvalid (KsbaCert cert) if (rc) return rc; - certid = gpgsm_get_certid (cert); - if (!certid) + if (use_ocsp) { - log_error ("error getting the certificate ID\n"); - return gpg_error (GPG_ERR_GENERAL); + certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + } + else + { + certid = gpgsm_get_certid (cert); + if (!certid) + { + log_error ("error getting the certificate ID\n"); + return gpg_error (GPG_ERR_GENERAL); + } } if (opt.verbose > 1) { char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1); - log_info ("asking dirmngr about %s\n", fpr); + log_info ("asking dirmngr about %s%s\n", fpr, + use_ocsp? " (using OCSP)":""); xfree (fpr); } parm.ctx = dirmngr_ctx; parm.cert = cert; + /* FIXME: If --disable-crl-checks has been set, we should pass an + option to dirmngr, so that no fallback CRL check is done after an + ocsp check. */ + snprintf (line, DIM(line)-1, "ISVALID %s", certid); line[DIM(line)-1] = 0; xfree (certid); diff --git a/sm/certchain.c b/sm/certchain.c index 50e910240..28b098bf4 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -517,11 +517,13 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) goto leave; } - if (!opt.no_crl_check) + if (!opt.no_crl_check || ctrl->use_ocsp) { - rc = gpgsm_dirmngr_isvalid (subject_cert); + rc = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp); if (rc) { + /* Fixme: We should change the wording because we may + have used OCSP. */ switch (gpg_err_code (rc)) { case GPG_ERR_CERT_REVOKED: @@ -677,7 +679,7 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) if (opt.no_policy_check) log_info ("policies not checked due to --disable-policy-checks option\n"); - if (opt.no_crl_check) + if (opt.no_crl_check && !ctrl->use_ocsp) log_info ("CRLs not checked due to --disable-crl-checks option\n"); if (!rc) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 3fab49731..161d185b1 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -111,6 +111,9 @@ enum cmd_and_opt_values { oDisableCRLChecks, oEnableCRLChecks, + oDisableOCSP, + oEnableOCSP, + oIncludeCerts, oPolicyFile, @@ -253,6 +256,9 @@ static ARGPARSE_OPTS opts[] = { { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, + { oDisableOCSP, "disable-ocsp", 0, "@" }, + { oEnableOCSP, "enable-ocsp", 0, N_("check validity using OCSP")}, + { oIncludeCerts, "include-certs", 1, N_("|N|number of certificates to include") }, @@ -825,6 +831,13 @@ main ( int argc, char **argv) opt.no_crl_check = 0; break; + case oDisableOCSP: + opt.enable_ocsp = 0; + break; + case oEnableOCSP: + opt.enable_ocsp = 1; + break; + case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break; case oPolicyFile: @@ -1360,6 +1373,7 @@ void gpgsm_init_default_ctrl (struct server_control_s *ctrl) { ctrl->include_certs = 1; /* only include the signer's cert */ + ctrl->use_ocsp = opt.enable_ocsp; } diff --git a/sm/gpgsm.h b/sm/gpgsm.h index f0b10c8dc..680ba9503 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -35,7 +35,7 @@ #define MAX_DIGEST_LEN 24 -/* A large struct name "opt" to keep global flags */ +/* A large struct named "opt" to keep global flags */ struct { unsigned int debug; /* debug flags (DBG_foo_VALUE) */ int verbose; /* verbosity level */ @@ -83,6 +83,7 @@ struct { int ignore_time_conflict; /* Ignore certain time conflicts */ int no_crl_check; /* Don't do a CRL check */ + int enable_ocsp; /* Default to use OCSP checks. */ char *policy_file; /* full pathname of policy file */ int no_policy_check; /* ignore certificate policies */ @@ -131,6 +132,7 @@ struct server_control_s { along with a signature or the number of certificates up the chain (0 = none, 1 = only signer) */ + int use_ocsp; /* Set to true if OCSP should be used. */ }; typedef struct server_control_s *CTRL; @@ -261,7 +263,7 @@ int gpgsm_agent_learn (void); int gpgsm_agent_passwd (const char *hexkeygrip); /*-- call-dirmngr.c --*/ -int gpgsm_dirmngr_isvalid (KsbaCert cert); +int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp); int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, void (*cb)(void*, KsbaCert), void *cb_value); int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, diff --git a/sm/verify.c b/sm/verify.c index e6e08c06c..c58dd895e 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -474,7 +474,8 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) tstr = strtimestamp_r (sigtime); buf = xmalloc ( strlen(fpr) + strlen (tstr) + 120); sprintf (buf, "%s %s %s %s", fpr, tstr, - sigtime, keyexptime ); + *sigtime? sigtime : "0", + *keyexptime? keyexptime : "0" ); xfree (tstr); xfree (fpr); gpgsm_status (ctrl, STATUS_VALIDSIG, buf); -- cgit v1.2.3 From d0f704991ca748039acd43ddf4370634e2facf12 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Dec 2003 10:54:59 +0000 Subject: Added a very simple tool. --- tools/der-to-pem | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 tools/der-to-pem diff --git a/tools/der-to-pem b/tools/der-to-pem new file mode 100755 index 000000000..183996654 --- /dev/null +++ b/tools/der-to-pem @@ -0,0 +1,27 @@ +#!/bin/sh +# Convert A BER or DER encoding to PEM format. +# +# Copyright 20032 Free Software Foundation, Inc. +# +# This program 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. + +PGM="der-to-pem" +if [ $# == 0 ]; then + input="" +elif [ $# == 1 ]; then + input="$1" +else + echo "usage: $PGM [<inputfile>]" >&2 + exit 1 +fi + +echo "-----BEGIN CERTIFICATE-----" +mimencode $input +echo "-----END CERTIFICATE-----" + -- cgit v1.2.3 From f39b03d03da39c8a318fa0d30cf26aca09f37b14 Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Tue, 9 Dec 2003 09:07:09 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- ABOUT-NLS | 625 +++++++++++++++++ doc/gpg.texi | 1806 ++++++++++++++++++++++++++++++++++++++++++++++++ intl/ChangeLog | 4 + intl/Makefile.in | 479 +++++++++++++ intl/VERSION | 1 + intl/bindtextdom.c | 374 ++++++++++ intl/config.charset | 467 +++++++++++++ intl/dcgettext.c | 59 ++ intl/dcigettext.c | 1238 +++++++++++++++++++++++++++++++++ intl/dcngettext.c | 60 ++ intl/dgettext.c | 59 ++ intl/dngettext.c | 61 ++ intl/eval-plural.h | 114 +++ intl/finddomain.c | 195 ++++++ intl/gettext.c | 64 ++ intl/gettextP.h | 224 ++++++ intl/gmo.h | 148 ++++ intl/hash-string.h | 59 ++ intl/intl-compat.c | 151 ++++ intl/l10nflist.c | 453 ++++++++++++ intl/libgnuintl.h.in | 309 +++++++++ intl/loadinfo.h | 156 +++++ intl/loadmsgcat.c | 1322 +++++++++++++++++++++++++++++++++++ intl/localcharset.c | 398 +++++++++++ intl/localcharset.h | 42 ++ intl/localealias.c | 419 +++++++++++ intl/localename.c | 772 +++++++++++++++++++++ intl/log.c | 104 +++ intl/ngettext.c | 68 ++ intl/os2compat.c | 98 +++ intl/os2compat.h | 46 ++ intl/osdep.c | 24 + intl/plural-exp.c | 156 +++++ intl/plural-exp.h | 126 ++++ intl/plural.c | 1518 ++++++++++++++++++++++++++++++++++++++++ intl/plural.y | 409 +++++++++++ intl/relocatable.c | 439 ++++++++++++ intl/relocatable.h | 67 ++ intl/textdomain.c | 142 ++++ m4/codeset.m4 | 23 + m4/gettext.m4 | 415 +++++++++++ m4/glibc21.m4 | 32 + m4/iconv.m4 | 103 +++ m4/intdiv0.m4 | 72 ++ m4/inttypes-pri.m4 | 32 + m4/inttypes.m4 | 27 + m4/inttypes_h.m4 | 28 + m4/isc-posix.m4 | 26 + m4/lcmessage.m4 | 32 + m4/lib-ld.m4 | 110 +++ m4/lib-link.m4 | 551 +++++++++++++++ m4/lib-prefix.m4 | 155 +++++ m4/nls.m4 | 49 ++ m4/po.m4 | 197 ++++++ m4/progtest.m4 | 91 +++ m4/stdint_h.m4 | 28 + m4/uintmax_t.m4 | 32 + m4/ulonglong.m4 | 23 + po/LINGUAS | 18 + po/Makefile.in.in | 353 ++++++++++ po/Rules-quot | 42 ++ po/boldquot.sed | 10 + po/en@boldquot.header | 25 + po/en@quot.header | 22 + po/insert-header.sin | 23 + po/quot.sed | 6 + po/remove-potcdate.sed | 11 + po/remove-potcdate.sin | 19 + scripts/config.rpath | 548 +++++++++++++++ scripts/mkinstalldirs | 111 +++ tools/ChangeLog | 155 +++++ tools/Makefile.am | 33 + 72 files changed, 16658 insertions(+) create mode 100644 ABOUT-NLS create mode 100644 doc/gpg.texi create mode 100644 intl/ChangeLog create mode 100644 intl/Makefile.in create mode 100644 intl/VERSION create mode 100644 intl/bindtextdom.c create mode 100755 intl/config.charset create mode 100644 intl/dcgettext.c create mode 100644 intl/dcigettext.c create mode 100644 intl/dcngettext.c create mode 100644 intl/dgettext.c create mode 100644 intl/dngettext.c create mode 100644 intl/eval-plural.h create mode 100644 intl/finddomain.c create mode 100644 intl/gettext.c create mode 100644 intl/gettextP.h create mode 100644 intl/gmo.h create mode 100644 intl/hash-string.h create mode 100644 intl/intl-compat.c create mode 100644 intl/l10nflist.c create mode 100644 intl/libgnuintl.h.in create mode 100644 intl/loadinfo.h create mode 100644 intl/loadmsgcat.c create mode 100644 intl/localcharset.c create mode 100644 intl/localcharset.h create mode 100644 intl/localealias.c create mode 100644 intl/localename.c create mode 100644 intl/log.c create mode 100644 intl/ngettext.c create mode 100644 intl/os2compat.c create mode 100644 intl/os2compat.h create mode 100644 intl/osdep.c create mode 100644 intl/plural-exp.c create mode 100644 intl/plural-exp.h create mode 100644 intl/plural.c create mode 100644 intl/plural.y create mode 100644 intl/relocatable.c create mode 100644 intl/relocatable.h create mode 100644 intl/textdomain.c create mode 100644 m4/codeset.m4 create mode 100644 m4/gettext.m4 create mode 100644 m4/glibc21.m4 create mode 100644 m4/iconv.m4 create mode 100644 m4/intdiv0.m4 create mode 100644 m4/inttypes-pri.m4 create mode 100644 m4/inttypes.m4 create mode 100644 m4/inttypes_h.m4 create mode 100644 m4/isc-posix.m4 create mode 100644 m4/lcmessage.m4 create mode 100644 m4/lib-ld.m4 create mode 100644 m4/lib-link.m4 create mode 100644 m4/lib-prefix.m4 create mode 100644 m4/nls.m4 create mode 100644 m4/po.m4 create mode 100644 m4/progtest.m4 create mode 100644 m4/stdint_h.m4 create mode 100644 m4/uintmax_t.m4 create mode 100644 m4/ulonglong.m4 create mode 100644 po/LINGUAS create mode 100644 po/Makefile.in.in create mode 100644 po/Rules-quot create mode 100644 po/boldquot.sed create mode 100644 po/en@boldquot.header create mode 100644 po/en@quot.header create mode 100644 po/insert-header.sin create mode 100644 po/quot.sed create mode 100644 po/remove-potcdate.sed create mode 100644 po/remove-potcdate.sin create mode 100755 scripts/config.rpath create mode 100755 scripts/mkinstalldirs create mode 100644 tools/ChangeLog create mode 100644 tools/Makefile.am diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 000000000..47d5e39f0 --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,625 @@ +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. + diff --git a/doc/gpg.texi b/doc/gpg.texi new file mode 100644 index 000000000..4ed4f1f76 --- /dev/null +++ b/doc/gpg.texi @@ -0,0 +1,1806 @@ +\input texinfo +@c This Texinfo document has been automatically generated by +@c docbook2texi from a DocBook documentation. The tool used +@c can be found at: +@c <URL:http://shell.ipoline.com/~elmert/hacks/docbook2X/> +@c Please send any bug reports, improvements, comments, +@c patches, etc. to Steve Cheng <steve@ggi-project.org>. + +@setfilename gpg.info +@dircategory GnuPG +@direntry +* gpg: (gpg). GnuPG encryption and signing tool. +@end direntry + +@node top +@top gpg +@menu +@end menu + +@majorheading Name +gpg ---- encryption and signing tool</> + +@majorheading Synopsis + +@majorheading DESCRIPTION +@code{gpg} is the main program for the GnuPG system. + +This man page only lists the commands and options available. +For more verbose documentation get the GNU Privacy Handbook (GPH) or +one of the other documents at http://www.gnupg.org/docs.html . + +Please remember that option parsing stops as soon as a non option is +encountered, you can explicitly stop option parsing by using the +special option "---". + +@majorheading COMMANDS +@code{gpg} recognizes these commands: + +@table @asis +@item -s, ---sign +Make a signature. This command may be combined +with ---encrypt. + +@item ---clearsign +Make a clear text signature. + +@item -b, ---detach-sign +Make a detached signature. + +@item -e, ---encrypt +Encrypt data. This option may be combined with ---sign. + +@item -c, ---symmetric +Encrypt with a symmetric cipher using a passphrase. The default +symmetric cipher used is CAST5, but may be chosen with the +---cipher-algo option. + +@item ---store +Store only (make a simple RFC1991 packet). + +@item ---decrypt @code{file} +Decrypt @code{file} (or stdin if no file is specified) and +write it to stdout (or the file specified with +---output). If the decrypted file is signed, the +signature is also verified. 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. + +@item ---verify @code{sigfile} @code{signed-files} +Assume that @code{sigfile} is a signature and verify it +without generating any output. With no arguments, +the signature packet is read from stdin. If +only a sigfile is given, it may be a complete +signature or a detached signature, in which case +the signed stuff is expected in a file without the +".sig" or ".asc" extension. +With more than +1 argument, the first should be a detached signature +and the remaining files are the signed stuff. To read the signed +stuff from stdin, use @samp{-} as the second filename. +For security reasons a detached signature cannot read the signed +material from stdin without denoting it in the above way. + +@item ---verify-files @code{files} +This is a special version of the ---verify command which does not work with +detached signatures. The command expects the files to be verified either +on the command line or reads the filenames from stdin; each name must be on +separate line. The command is intended for quick checking of many files. + +@item ---encrypt-files @code{files} +This is a special version of the ---encrypt command. The command expects +the files to be encrypted either on the command line or reads the filenames +from stdin; each name must be on separate line. The command is intended +for a quick encryption of multiple files. + +@item ---decrypt-files @code{files} +The same as ---encrypt-files with the difference that files will be +decrypted. The syntax or the filenames is the same. + +@item ---list-keys @code{names} +@itemx ---list-public-keys @code{names} +List all keys from the public keyrings, or just the ones given on the +command line. + +Avoid using the output of this command in scripts or other programs as +it is likely to change as GnuPG changes. See ---with-colons for a +machine-parseable key listing command that is appropriate for use in +scripts and other programs. + +@item ---list-secret-keys @code{names} +List all keys from the secret keyrings, or just the ones given on the +command line. A '#' after the letters 'sec' means that the secret key +is not usable (for example, if it was created via +---export-secret-subkeys). + +@item ---list-sigs @code{names} +Same as ---list-keys, but the signatures are listed too. + +For each signature listed, there are several flags in between the +"sig" tag and keyid. These flags give additional information about +each signature. From left to right, they are the numbers 1-3 for +certificate check level (see ---default-cert-check-level), "L" for a +local or non-exportable signature (see ---lsign-key), "R" for a +nonRevocable signature (see ---nrsign-key), "P" for a signature that +contains a policy URL (see ---cert-policy-url), "N" for a signature +that contains a notation (see ---cert-notation), "X" for an eXpired +signature (see ---ask-cert-expire), and the numbers 1-9 or "T" for 10 +and above to indicate trust signature levels (see the ---edit-key +command "tsign"). + +@item ---check-sigs @code{names} +Same as ---list-sigs, but the signatures are verified. + +@item ---fingerprint @code{names} +List all keys with their fingerprints. This is the +same output as ---list-keys but with the additional output +of a line with the fingerprint. May also be combined +with ---list-sigs or --check-sigs. +If this command is given twice, the fingerprints of all +secondary keys are listed too. + +@item ---list-packets +List only the sequence of packets. This is mainly +useful for debugging. + +@item ---gen-key +Generate a new key pair. This command is normally only used +interactively. + +There is an experimental feature which allows you to create keys +in batch mode. See the file @file{doc/DETAILS} +in the source distribution on how to use this. + +@item ---edit-key @code{name} +Present a menu which enables you to do all key +related tasks: + +@table @asis +@item sign +Make a signature on key of user @code{name} +If the key is not yet signed by the default +user (or the users given with -u), the +program displays the information of the key +again, together with its fingerprint and +asks whether it should be signed. This +question is repeated for all users specified +with -u. + +@item lsign +Same as ---sign but the signature is marked as +non-exportable and will therefore never be used +by others. This may be used to make keys valid +only in the local environment. + +@item nrsign +Same as ---sign but the signature is marked as non-revocable and can +therefore never be revoked. + +@item nrlsign +Combines the functionality of nrsign and lsign to make a signature +that is both non-revocable and +non-exportable. + +@item tsign +Make a trust signature. This is a signature that combines the notions +of certification (like a regular signature), and trust (like the +"trust" command). It is generally only useful in distinct communities +or groups. + +@item revsig +Revoke a signature. For every signature which has been generated by +one of the secret keys, GnuPG asks whether a revocation certificate +should be generated. + +@item trust +Change the owner trust value. This updates the +trust-db immediately and no save is required. + +@item disable +@itemx enable +Disable or enable an entire key. A disabled key can not normally be +used for encryption. + +@item adduid +Create an alternate user id. + +@item addphoto +Create a photographic user id. This will prompt for a JPEG file that +will be embedded into the user ID. A very large JPEG will make for a +very large key. + +@item deluid +Delete a user id. + +@item revuid +Revoke a user id. + +@item addkey +Add a subkey to this key. + +@item delkey +Remove a subkey. + +@item addrevoker +Add a designated revoker. This takes one optional argument: +"sensitive". If a designated revoker is marked as sensitive, it will +not be exported by default (see +export-options). + +@item revkey +Revoke a subkey. + +@item expire +Change the key expiration time. If a subkey is selected, the +expiration time of this subkey will be changed. With no selection, +the key expiration of the primary key is changed. + +@item passwd +Change the passphrase of the secret key. + +@item primary +Flag the current user id as the primary one, removes the primary user +id flag from all other user ids and sets the timestamp of all affected +self-signatures one second ahead. Note that setting a photo user ID +as primary makes it primary over other photo user IDs, and setting a +regular user ID as primary makes it primary over other regular user +IDs. + +@item uid @code{n} +Toggle selection of user id with index @code{n}. +Use 0 to deselect all. + +@item key @code{n} +Toggle selection of subkey with index @code{n}. +Use 0 to deselect all. + +@item check +Check all selected user ids. + +@item showphoto +Display the selected photographic user +id. + +@item pref +List preferences from the selected user ID. This shows the actual +preferences, without including any implied preferences. + +@item showpref +More verbose preferences listing for the selected user ID. This shows +the preferences in effect by including the implied preferences of +3DES (cipher), SHA-1 (digest), and Uncompressed (compression) if they +are not already included in the preference list. + +@item setpref @code{string} +Set the list of user ID preferences to @code{string}, this should be a +string similar to the one printed by "pref". Using an empty string +will set the default preference string, using "none" will set the +preferences to nil. Use "gpg ---version" to get a list of available +algorithms. This command just initializes an internal list and does +not change anything unless another command (such as "updpref") which +changes the self-signatures is used. + +@item updpref +Change the preferences of all user IDs (or just of the selected ones +to the current list of preferences. The timestamp of all affected +self-signatures will be advanced by one second. Note that while you +can change the preferences on an attribute user ID (aka "photo ID"), +GnuPG does not select keys via attribute user IDs so these preferences +will not be used by GnuPG. + +@item toggle +Toggle between public and secret key listing. + +@item save +Save all changes to the key rings and quit. + +@item quit +Quit the program without updating the +key rings. + +@end table + +The listing shows you the key with its secondary +keys and all user ids. Selected keys or user ids +are indicated by an asterisk. The trust value is +displayed with the primary key: the first is the +assigned owner trust and the second is the calculated +trust value. Letters are used for the values: + +@table @asis +@item - +No ownertrust assigned / not yet calculated. + +@item e +Trust +calculation has failed; probably due to an expired key. + +@item q +Not enough information for calculation. + +@item n +Never trust this key. + +@item m +Marginally trusted. + +@item f +Fully trusted. + +@item u +Ultimately trusted. + +@end table + +@item ---sign-key @code{name} +Signs a public key with your secret key. This is a shortcut version of +the subcommand "sign" from ---edit. + +@item ---lsign-key @code{name} +Signs a public key with your secret key but marks it as +non-exportable. This is a shortcut version of the subcommand "lsign" +from ---edit. + +@item ---nrsign-key @code{name} +Signs a public key with your secret key but marks it as non-revocable. +This is a shortcut version of the subcommand "nrsign" from ---edit. + +@item ---delete-key @code{name} +Remove key from the public keyring. In batch mode either ---yes is +required or the key must be specified by fingerprint. This is a +safeguard against accidental deletion of multiple keys. + +@item ---delete-secret-key @code{name} +Remove key from the secret and public keyring. In batch mode the key +must be specified by fingerprint. + +@item ---delete-secret-and-public-key @code{name} +Same as ---delete-key, but if a secret key exists, it will be removed +first. In batch mode the key must be specified by fingerprint. + +@item ---gen-revoke +Generate a revocation certificate for the complete key. To revoke +a subkey or a signature, use the ---edit command. + +@item ---desig-revoke +Generate a designated revocation certificate for a key. This allows a +user (with the permission of the keyholder) to revoke someone else's +key. + +@item ---export @code{names} +Either export all keys from all keyrings (default +keyrings and those registered via option ---keyring), +or if at least one name is given, those of the given +name. The new keyring is written to stdout or to +the file given with option "output". Use together +with ---armor to mail those keys. + +@item ---send-keys @code{names} +Same as ---export but sends the keys to a keyserver. +Option ---keyserver must be used to give the name +of this keyserver. Don't send your complete keyring +to a keyserver - select only those keys which are new +or changed by you. + +@item ---export-all @code{names} +Same as ---export, but also exports keys which +are not compatible with OpenPGP. + +@item ---export-secret-keys @code{names} +@itemx ---export-secret-subkeys @code{names} +Same as ---export, but exports the secret keys instead. +This is normally not very useful and a security risk. +The second form of the command has the special property to +render the secret part of the primary key useless; this is +a GNU extension to OpenPGP and other implementations can +not be expected to successfully import such a key. +See the option ---simple-sk-checksum if you want to import such an +exported key with an older OpenPGP implementation. + +@item ---import @code{files} +@itemx ---fast-import @code{files} +Import/merge keys. This adds the given keys to the +keyring. The fast version is currently just a synonym. + +There are a few other options which control how this command works. +Most notable here is the ---merge-only option which does not insert new keys +but does only the merging of new signatures, user-IDs and subkeys. + +@item ---recv-keys @code{key IDs} +Import the keys with the given key IDs from a keyserver. Option +---keyserver must be used to give the name of this keyserver. + +@item ---refresh-keys @code{key IDs} +Request updates from a keyserver for keys that already exist on the +local keyring. This is useful for updating a key with the latest +signatures, user IDs, etc. Option ---keyserver must be used to give +the name of this keyserver. + +@item ---search-keys @code{names} +Search the keyserver for the given names. Multiple names given here +will be joined together to create the search string for the keyserver. +Option ---keyserver must be used to give the name of this keyserver. + +@item ---update-trustdb +Do trust database maintenance. This command iterates over all keys +and builds the Web-of-Trust. This is an interactive command because it +may have to ask for the "ownertrust" values for keys. The user has to +give an estimation of how far she trusts the owner of the displayed +key to correctly certify (sign) other keys. GnuPG only asks for the +ownertrust value if it has not yet been assigned to a key. Using the +---edit-key menu, the assigned value can be changed at any time. + +@item ---check-trustdb +Do trust database maintenance without user interaction. From time to +time the trust database must be updated so that expired keys or +signatures and the resulting changes in the Web-of-Trust can be +tracked. Normally, GnuPG will calculate when this is required and do +it automatically unless ---no-auto-check-trustdb is set. This command +can be used to force a trust database check at any time. The +processing is identical to that of ---update-trustdb but it skips keys +with a not yet defined "ownertrust". + +For use with cron jobs, this command can be used together with ---batch +in which case the trust database check is done only if a check is +needed. To force a run even in batch mode add the option ---yes. + +@item ---export-ownertrust +Send the ownertrust values to stdout. This is useful for backup +purposes as these values are the only ones which can't be re-created +from a corrupted trust DB. + +@item ---import-ownertrust @code{files} +Update the trustdb with the ownertrust values stored +in @code{files} (or stdin if not given); existing +values will be overwritten. + +@item ---rebuild-keydb-caches +When updating from version 1.0.6 to 1.0.7 this command should be used +to create signature caches in the keyring. It might be handy in other +situations too. + +@item ---print-md @code{algo} @code{files} +@itemx ---print-mds @code{files} +Print message digest of algorithm ALGO for all given files or stdin. +With the second form (or a deprecated "*" as algo) digests for all +available algorithms are printed. + +@item ---gen-random @code{0|1|2} @code{count} +Emit COUNT random bytes of the given quality level. If count is not given +or zero, an endless sequence of random bytes will be emitted. +PLEASE, don't use this command unless you know what you are doing; it may +remove precious entropy from the system! + +@item ---gen-prime @code{mode} @code{bits} @code{qbits} +Use the source, Luke :-). The output format is still subject to change. + +@item ---version +Print version information along with a list +of supported algorithms. + +@item ---warranty +Print warranty information. + +@item -h, ---help +Print usage information. This is a really long list even though it +doesn't list all options. For every option, consult this manual. + +@end table + +@majorheading OPTIONS +Long options can be put in an options file (default +"~/.gnupg/gpg.conf"). Short option names will not work - for example, +"armor" is a valid option for the options file, while "a" is not. Do +not write the 2 dashes, but simply the name of the option and any +required arguments. Lines with a hash ('#') as the first +non-white-space character are ignored. Commands may be put in this +file too, but that is not generally useful as the command will execute +automatically with every execution of gpg. + +@code{gpg} recognizes these options: + +@table @asis +@item -a, ---armor +Create ASCII armored output. + +@item -o, ---output @code{file} +Write output to @code{file}. + +@item ---mangle-dos-filenames +@itemx ---no-mangle-dos-filenames +Older version of Windows cannot handle filenames with more than one +dot. ---mangle-dos-filenames causes GnuPG to replace (rather than add +to) the extension of an output filename to avoid this problem. This +option is off by default and has no effect on non-Windows platforms. + +@item -u, ---local-user @code{name} +Use @code{name} as the user ID to sign. +This option is silently ignored for the list commands, +so that it can be used in an options file. + +@item ---default-key @code{name} +Use @code{name} as default user ID for signatures. If this +is not used the default user ID is the first user ID +found in the secret keyring. + +@item -r, ---recipient @code{name} +@itemx +Encrypt for user id @code{name}. If this option or ---hidden-recipient +is not specified, GnuPG asks for the user-id unless +---default-recipient is given. + +@item -R, ---hidden-recipient @code{name} +@itemx +Encrypt for user id @code{name}, but hide the keyid of the key. This +option hides the receiver of the message and is a countermeasure +against traffic analysis. If this option or ---recipient is not +specified, GnuPG asks for the user-id unless ---default-recipient is +given. + +@item ---default-recipient @code{name} +Use @code{name} as default recipient if option ---recipient is not used and +don't ask if this is a valid one. @code{name} must be non-empty. + +@item ---default-recipient-self +Use the default key as default recipient if option ---recipient is not used and +don't ask if this is a valid one. The default key is the first one from the +secret keyring or the one set with ---default-key. + +@item ---no-default-recipient +Reset ---default-recipient and --default-recipient-self. + +@item ---encrypt-to @code{name} +Same as ---recipient but this one is intended for use +in the options file and may be used with +your own user-id as an "encrypt-to-self". These keys +are only used when there are other recipients given +either by use of ---recipient or by the asked user id. +No trust checking is performed for these user ids and +even disabled keys can be used. + +@item ---hidden-encrypt-to @code{name} +Same as ---hidden-recipient but this one is intended for use in the +options file and may be used with your own user-id as a hidden +"encrypt-to-self". These keys are only used when there are other +recipients given either by use of ---recipient or by the asked user id. +No trust checking is performed for these user ids and even disabled +keys can be used. + +@item ---no-encrypt-to +Disable the use of all ---encrypt-to and --hidden-encrypt-to keys. + +@item -v, ---verbose +Give more information during processing. If used +twice, the input data is listed in detail. + +@item -q, ---quiet +Try to be as quiet as possible. + +@item -z @code{n}, ---compress @code{n} +Set compression level to @code{n}. A value of 0 for @code{n} +disables compression. Default is to use the default +compression level of zlib (normally 6). + +@item -t, ---textmode +@itemx ---no-textmode +Use canonical text mode. ---no-textmode disables this option. If -t +(but not ---textmode) is used together with armoring and signing, this +enables clearsigned messages. This kludge is needed for command-line +compatibility with command-line versions of PGP; normally you would +use ---sign or --clearsign to select the type of the signature. + +@item -n, ---dry-run +Don't make any changes (this is not completely implemented). + +@item -i, ---interactive +Prompt before overwriting any files. + +@item ---batch +@itemx ---no-batch +Use batch mode. Never ask, do not allow interactive commands. +---no-batch disables this option. + +@item ---no-tty +Make sure that the TTY (terminal) is never used for any output. +This option is needed in some cases because GnuPG sometimes prints +warnings to the TTY if ---batch is used. + +@item ---yes +Assume "yes" on most questions. + +@item ---no +Assume "no" on most questions. + +@item ---default-cert-check-level @code{n} +The default to use for the check level when signing a key. + +0 means you make no particular claim as to how carefully you verified +the key. + +1 means you believe the key is owned by the person who claims to own +it but you could not, or did not verify the key at all. This is +useful for a "persona" verification, where you sign the key of a +pseudonymous user. + +2 means you did casual verification of the key. For example, this +could mean that you verified that the key fingerprint and checked the +user ID on the key against a photo ID. + +3 means you did extensive verification of the key. For example, this +could mean that you verified the key fingerprint with the owner of the +key in person, and that you checked, by means of a hard to forge +document with a photo ID (such as a passport) that the name of the key +owner matches the name in the user ID on the key, and finally that you +verified (by exchange of email) that the email address on the key +belongs to the key owner. + +Note that the examples given above for levels 2 and 3 are just that: +examples. In the end, it is up to you to decide just what "casual" +and "extensive" mean to you. + +This option defaults to 0. + +@item ---trusted-key @code{long key ID} +Assume that the specified key (which must be given +as a full 8 byte key ID) is as trustworthy as one of +your own secret keys. This option is useful if you +don't want to keep your secret keys (or one of them) +online but still want to be able to check the validity of a given +recipient's or signator's key. + +@item ---trust-model @code{pgp|classic|always} +Set what trust model GnuPG should follow. The models are: + +@table @asis +@item pgp +This is the web-of-trust combined with trust signatures as used in PGP +5.x and later. This is the default trust model. + +@item classic +This is the standard web-of-trust as used in PGP 2.x and earlier. + +@item always +Skip key validation and assume that used keys are always fully +trusted. You won't use this unless you have installed some external +validation scheme. This option also suppresses the "[uncertain]" tag +printed with signature checks when there is no evidence that the user +ID is bound to the key. + +@end table + +@item ---always-trust +Identical to `---trust-model always' + +@item ---keyserver @code{name} +Use @code{name} as your keyserver. This is the server that ---recv-keys, +---send-keys, and --search-keys will communicate with to receive keys +from, send keys to, and search for keys on. The format of the +@code{name} is a URI: `scheme:[//]keyservername[:port]' The scheme is +the type of keyserver: "hkp" for the Horowitz (or compatible) +keyservers, "ldap" for the NAI LDAP keyserver, or "mailto" for the +Horowitz email keyserver. Note that your particular installation of +GnuPG may have other keyserver types available as well. Keyserver +schemes are case-insensitive. + +Most keyservers synchronize with each other, so there is generally no +need to send keys to more than one server. Using the command "host -l +pgp.net | grep wwwkeys" gives you a list of HKP keyservers. When +using one of the wwwkeys servers, due to load balancing using +round-robin DNS you may notice that you get a different key server +each time. + +@item ---keyserver-options @code{parameters} +This is a space or comma delimited string that gives options for the +keyserver. Options can be prepended with a `no-' to give the opposite +meaning. Valid import-options or export-options may be used here as +well to apply to importing (---recv-key) or exporting (--send-key) a +key from a keyserver. While not all options are available for all +keyserver types, some common options are: + +@table @asis +@item include-revoked +When searching for a key with ---search-keys, include keys that are +marked on the keyserver as revoked. Note that this option is always +set when using the NAI HKP keyserver, as this keyserver does not +differentiate between revoked and unrevoked keys. + +@item include-disabled +When searching for a key with ---search-keys, include keys that are +marked on the keyserver as disabled. Note that this option is not +used with HKP keyservers. + +@item include-subkeys +When receiving a key, include subkeys as potential targets. Note that +this option is not used with HKP keyservers, as they do not support +retrieving keys by subkey id. + +@item use-temp-files +On most Unix-like platforms, GnuPG communicates with the keyserver +helper program via pipes, which is the most efficient method. This +option forces GnuPG to use temporary files to communicate. On some +platforms (such as Win32 and RISC OS), this option is always enabled. + +@item keep-temp-files +If using `use-temp-files', do not delete the temp files after using +them. This option is useful to learn the keyserver communication +protocol by reading the temporary files. + +@item verbose +Tell the keyserver helper program to be more verbose. This option can +be repeated multiple times to increase the verbosity level. + +@item honor-http-proxy +For keyserver schemes that use HTTP (such as HKP), try to access the +keyserver over the proxy set with the environment variable +"http_proxy". + +@item auto-key-retrieve +This option enables the automatic retrieving of keys from a keyserver +when verifying signatures made by keys that are not on the local +keyring. + +Note that this option makes a "web bug" like behavior possible. +Keyserver operators can see which keys you request, so by sending you +a message signed by a brand new key (which you naturally will not have +on your local keyring), the operator can tell both your IP address and +the time when you verified the signature. + +@end table + +@item ---import-options @code{parameters} +This is a space or comma delimited string that gives options for +importing keys. Options can be prepended with a `no-' to give the +opposite meaning. The options are: + +@table @asis +@item allow-local-sigs +Allow importing key signatures marked as "local". This is not +generally useful unless a shared keyring scheme is being used. +Defaults to no. + +@item repair-pks-subkey-bug +During import, attempt to repair the damage caused by the PKS +keyserver bug (pre version 0.9.6) that mangles keys with multiple +subkeys. Note that this cannot completely repair the damaged key as +some crucial data is removed by the keyserver, but it does at least +give you back one subkey. Defaults to no for regular ---import and to +yes for keyserver ---recv-keys. + +@end table + +@item ---export-options @code{parameters} +This is a space or comma delimited string that gives options for +exporting keys. Options can be prepended with a `no-' to give the +opposite meaning. The options are: + +@table @asis +@item include-non-rfc +Include non-RFC compliant keys in the export. Defaults to yes. + +@item include-local-sigs +Allow exporting key signatures marked as "local". This is not +generally useful unless a shared keyring scheme is being used. +Defaults to no. + +@item include-attributes +Include attribute user IDs (photo IDs) while exporting. This is +useful to export keys if they are going to be used by an OpenPGP +program that does not accept attribute user IDs. Defaults to yes. + +@item include-sensitive-revkeys +Include designated revoker information that was marked as +"sensitive". Defaults to no. + +@end table + +@item ---list-options @code{parameters} +This is a space or comma delimited string that gives options used when +listing keys and signatures (that is, ---list-keys, --list-sigs, +---list-public-keys, --list-secret-keys, and the --edit-key functions). +Options can be prepended with a `no-' to give the opposite meaning. +The options are: + +@table @asis +@item show-photos +Causes ---list-keys, --list-sigs, --list-public-keys, and +---list-secret-keys to display any photo IDs attached to the key. +Defaults to no. See also ---photo-viewer. + +@item show-policy-url +Show policy URLs in the ---list-sigs or --check-sigs listings. +Defaults to no. + +@item show-notation +Show signature notations in the ---list-sigs or --check-sigs listings. +Defaults to no. + +@item show-keyserver-url +Show any preferred keyserver URL in the ---list-sigs or --check-sigs +listings. Defaults to no. + +@item show-validity +Display the calculated validity of keys and user IDs during key +listings. Defaults to no. + +@item show-long-keyid +Display all 64 bits (16 digits) of key IDs during key listings, rather +than the more common 32 bit (8 digit) IDs. Defaults to no. + +@item show-unusable-uids +Show revoked and expired user IDs in key listings. Defaults to no. + +@item show-keyring +Display the keyring name at the head of key listings to show which +keyring a given key resides on. Defaults to no. + +@item show-sig-expire +Show signature expiration dates (if any) during ---list-sigs or +---check-sigs listings. Defaults to no. + +@end table + +@item ---verify-options @code{parameters} +This is a space or comma delimited string that gives options used when +verifying signatures. Options can be prepended with a `no-' to give +the opposite meaning. The options are: + +@table @asis +@item show-photos +Display any photo IDs present on the key that issued the signature. +Defaults to no. See also ---photo-viewer. + +@item show-policy-url +Show policy URLs in the signature being verified. Defaults to no. + +@item show-notation +Show signature notations in the signature being verified. Defaults to +no. + +@item show-keyserver-url +Show any preferred keyserver URL in the signature being verified. +Defaults to no. + +@item show-validity +Display the calculated validity of the user IDs on the key that issued +the signature. Defaults to no. + +@item show-long-keyid +Display all 64 bits (16 digits) of key IDs during signature +verification, rather than the more common 32 bit (8 digit) IDs. +Defaults to no. + +@item show-unusable-uids +Show revoked and expired user IDs during signature verification. +Defaults to no. + +@end table + +@item ---show-photos +@itemx ---no-show-photos +Causes ---list-keys, --list-sigs, --list-public-keys, +---list-secret-keys, and verifying a signature to also display the +photo ID attached to the key, if any. See also ---photo-viewer. These +options are deprecated. Use `---list-options [no-]show-photos' and/or +`---verify-options [no-]show-photos' instead. + +@item ---photo-viewer @code{string} +This is the command line that should be run to view a photo ID. "%i" +will be expanded to a filename containing the photo. "%I" does the +same, except the file will not be deleted once the viewer exits. +Other flags are "%k" for the key ID, "%K" for the long key ID, "%f" +for the key fingerprint, "%t" for the extension of the image type +(e.g. "jpg"), "%T" for the MIME type of the image (e.g. "image/jpeg"), +and "%%" for an actual percent sign. If neither %i or %I are present, +then the photo will be supplied to the viewer on standard input. + +The default viewer is "xloadimage -fork -quiet -title 'KeyID 0x%k' +stdin". Note that if your image viewer program is not secure, then +executing it from GnuPG does not make it secure. + +@item ---exec-path @code{string} +Sets a list of directories to search for photo viewers and keyserver +helpers. If not provided, keyserver helpers use the compiled-in +default directory, and photo viewers use the $PATH environment +variable. + +@item ---show-keyring +Display the keyring name at the head of key listings to show which +keyring a given key resides on. This option is deprecated: use +`---list-options [no-]show-keyring' instead. + +@item ---keyring @code{file} +Add @code{file} to the list of keyrings. If @code{file} begins with a +tilde and a slash, these are replaced by the HOME directory. If the +filename does not contain a slash, it is assumed to be in the GnuPG +home directory ("~/.gnupg" if ---homedir is not used). The filename +may be prefixed with a scheme: + +"gnupg-ring:" is the default one. + +It might make sense to use it together with ---no-default-keyring. + +@item ---secret-keyring @code{file} +Same as ---keyring but for the secret keyrings. + +@item ---primary-keyring @code{file} +Designate @code{file} as the primary public keyring. This means that +newly imported keys (via ---import or keyserver --recv-from) will go to +this keyring. + +@item ---trustdb-name @code{file} +Use @code{file} instead of the default trustdb. If @code{file} begins +with a tilde and a slash, these are replaced by the HOME directory. If +the filename does not contain a slash, it is assumed to be in the +GnuPG home directory ("~/.gnupg" if ---homedir is not used). + +@item ---homedir @code{directory} +Set the name of the home directory to @code{directory} If this +option is not used it defaults to "~/.gnupg". It does +not make sense to use this in a options file. This +also overrides the environment variable "GNUPGHOME". + +@item ---charset @code{name} +Set the name of the native character set. This is used +to convert some strings to proper UTF-8 encoding. If this option is not used, the default character set is determined +from the current locale. A verbosity level of 3 shows the used one. +Valid values for @code{name} are: + +@table @asis +@item iso-8859-1 +This is the Latin 1 set. + +@item iso-8859-2 +The Latin 2 set. + +@item iso-8859-15 +This is currently an alias for +the Latin 1 set. + +@item koi8-r +The usual Russian set (rfc1489). + +@item utf-8 +Bypass all translations and assume +that the OS uses native UTF-8 encoding. + +@end table + +@item ---utf8-strings +@itemx ---no-utf8-strings +Assume that the arguments are already given as UTF8 strings. The default +(---no-utf8-strings) +is to assume that arguments are encoded in the character set as specified +by ---charset. These options affect all following arguments. Both options may +be used multiple times. + +@item ---options @code{file} +Read options from @code{file} and do not try to read +them from the default options file in the homedir +(see ---homedir). This option is ignored if used +in an options file. + +@item ---no-options +Shortcut for "---options /dev/null". This option is +detected before an attempt to open an option file. +Using this option will also prevent the creation of a +"~./gnupg" homedir. + +@item ---load-extension @code{name} +Load an extension module. If @code{name} does not contain a slash it is +searched for in the directory configured when GnuPG was built +(generally "/usr/local/lib/gnupg"). Extensions are not generally +useful anymore, and the use of this option is deprecated. + +@item ---debug @code{flags} +Set debugging flags. All flags are or-ed and @code{flags} may +be given in C syntax (e.g. 0x0042). + +@item ---debug-all +Set all useful debugging flags. + +@item ---enable-progress-filter +Enable certain PROGRESS status outputs. This option allows frontends +to display a progress indicator while gpg is processing larger files. +There is a slight performance overhead using it. + +@item ---status-fd @code{n} +Write special status strings to the file descriptor @code{n}. +See the file DETAILS in the documentation for a listing of them. + +@item ---logger-fd @code{n} +Write log output to file descriptor @code{n} and not to stderr. + +@item ---attribute-fd @code{n} +Write attribute subpackets to the file descriptor @code{n}. This is +most useful for use with ---status-fd, since the status messages are +needed to separate out the various subpackets from the stream +delivered to the file descriptor. + +@item ---sk-comments +@itemx ---no-sk-comments +Include secret key comment packets when exporting secret keys. This +is a GnuPG extension to the OpenPGP standard, and is off by default. +Please note that this has nothing to do with the comments in clear +text signatures or armor headers. ---no-sk-comments disables this +option. + +@item ---comment @code{string} +@itemx ---no-comments +Use @code{string} as a comment string in clear text signatures and +ASCII armored messages or keys (see ---armor). The default behavior is +not to use a comment string. ---comment may be repeated multiple times +to get multiple comment strings. ---no-comments removes all comments. + +@item ---emit-version +@itemx ---no-emit-version +Force inclusion of the version string in ASCII armored output. +---no-emit-version disables this option. + +@item ---sig-notation @code{name=value} +@itemx ---cert-notation @code{name=value} +@itemx -N, ---set-notation @code{name=value} +Put the name value pair into the signature as notation data. +@code{name} must consist only of printable characters or spaces, and +must contain a '@@' character. This is to help prevent pollution of +the IETF reserved notation namespace. The ---expert flag overrides the +'@@' check. @code{value} may be any printable string; it will be +encoded in UTF8, so you should check that your ---charset is set +correctly. If you prefix @code{name} with an exclamation mark, the +notation data will be flagged as critical (rfc2440:5.2.3.15). +---sig-notation sets a notation for data signatures. --cert-notation +sets a notation for key signatures (certifications). ---set-notation +sets both. + +There are special codes that may be used in notation names. "%k" will +be expanded into the key ID of the key being signed, "%K" into the +long key ID of the key being signed, "%f" into the fingerprint of the +key being signed, "%s" into the key ID of the key making the +signature, "%S" into the long key ID of the key making the signature, +"%g" into the fingerprint of the key making the signature (which might +be a subkey), "%p" into the fingerprint of the primary key of the key +making the signature, and "%%" results in a single "%". %k, %K, and +%f are only meaningful when making a key signature (certification). + +@item ---show-notation +@itemx ---no-show-notation +Show signature notations in the ---list-sigs or --check-sigs listings +as well as when verifying a signature with a notation in it. These +options are deprecated. Use `---list-options [no-]show-notation' +and/or `---verify-options [no-]show-notation' instead. + +@item ---sig-policy-url @code{string} +@itemx ---cert-policy-url @code{string} +@itemx ---set-policy-url @code{string} +Use @code{string} as a Policy URL for signatures (rfc2440:5.2.3.19). +If you prefix it with an exclamation mark, the policy URL packet will +be flagged as critical. ---sig-policy-url sets a a policy url for data +signatures. ---cert-policy-url sets a policy url for key signatures +(certifications). ---set-policy-url sets both. + +The same %-expandos used for notation data are available here as well. + +@item ---show-policy-url +@itemx ---no-show-policy-url +Show policy URLs in the ---list-sigs or --check-sigs listings as well +as when verifying a signature with a policy URL in it. These options +are deprecated. Use `---list-options [no-]show-policy-url' and/or +`---verify-options [no-]show-policy-url' instead. + +@item ---sig-keyserver-url @code{string} +Use @code{string} as a preferred keyserver URL for data signatures. If +you prefix it with an exclamation mark, the keyserver URL packet will +be flagged as critical. + +The same %-expandos used for notation data are available here as well. + +@item ---set-filename @code{string} +Use @code{string} as the filename which is stored inside messages. +This overrides the default, which is to use the actual filename of the +file being encrypted. + +@item ---for-your-eyes-only +@itemx ---no-for-your-eyes-only +Set the `for your eyes only' flag in the message. This causes GnuPG +to refuse to save the file unless the ---output option is given, and +PGP to use the "secure viewer" with a Tempest-resistant font to +display the message. This option overrides ---set-filename. +---no-for-your-eyes-only disables this option. + +@item ---use-embedded-filename +Try to create a file with a name as embedded in the data. +This can be a dangerous option as it allows to overwrite files. + +@item ---completes-needed @code{n} +Number of completely trusted users to introduce a new +key signer (defaults to 1). + +@item ---marginals-needed @code{n} +Number of marginally trusted users to introduce a new +key signer (defaults to 3) + +@item ---max-cert-depth @code{n} +Maximum depth of a certification chain (default is 5). + +@item ---cipher-algo @code{name} +Use @code{name} as cipher algorithm. Running the program +with the command ---version yields a list of supported +algorithms. If this is not used the cipher algorithm is +selected from the preferences stored with the key. + +@item ---digest-algo @code{name} +Use @code{name} as the message digest algorithm. Running the program +with the command ---version yields a list of supported algorithms. + +@item ---compress-algo @code{name} +Use compression algorithm @code{name}. "zlib" is RFC1950 ZLIB +compression. "zip" is RFC-1951 ZIP compression which is used by PGP. +"uncompressed" or "none" disables compression. If this option is not +used, the default behavior is to examine the recipient key preferences +to see which algorithms the recipient supports. If all else fails, +ZIP is used for maximum compatibility. Note, however, that ZLIB may +give better compression results if that is more important, as the +compression window size is not limited to 8k. + +@item ---cert-digest-algo @code{name} +Use @code{name} as the message digest algorithm used when signing a +key. Running the program with the command ---version yields a list of +supported algorithms. Be aware that if you choose an algorithm that +GnuPG supports but other OpenPGP implementations do not, then some +users will not be able to use the key signatures you make, or quite +possibly your entire key. + +@item ---s2k-cipher-algo @code{name} +Use @code{name} as the cipher algorithm used to protect secret keys. +The default cipher is CAST5. This cipher is also used for +conventional encryption if ---personal-cipher-preferences and +---cipher-algo is not given. + +@item ---s2k-digest-algo @code{name} +Use @code{name} as the digest algorithm used to mangle the passphrases. +The default algorithm is SHA-1. + +@item ---s2k-mode @code{n} +Selects how passphrases are mangled. If @code{n} is 0 a plain +passphrase (which is not recommended) will be used, a 1 adds a salt to +the passphrase and a 3 (the default) iterates the whole process a +couple of times. Unless ---rfc1991 is used, this mode is also used for +conventional encryption. + +@item ---simple-sk-checksum +Secret keys are integrity protected by using a SHA-1 checksum. This +method will be part of an enhanced OpenPGP specification but GnuPG +already uses it as a countermeasure against certain attacks. Old +applications don't understand this new format, so this option may be +used to switch back to the old behaviour. Using this this option +bears a security risk. Note that using this option only takes effect +when the secret key is encrypted - the simplest way to make this +happen is to change the passphrase on the key (even changing it to the +same value is acceptable). + +@item ---disable-cipher-algo @code{name} +Never allow the use of @code{name} as cipher algorithm. +The given name will not be checked so that a later loaded algorithm +will still get disabled. + +@item ---disable-pubkey-algo @code{name} +Never allow the use of @code{name} as public key algorithm. +The given name will not be checked so that a later loaded algorithm +will still get disabled. + +@item ---no-sig-cache +Do not cache the verification status of key signatures. +Caching gives a much better performance in key listings. However, if +you suspect that your public keyring is not save against write +modifications, you can use this option to disable the caching. It +probably does not make sense to disable it because all kind of damage +can be done if someone else has write access to your public keyring. + +@item ---no-sig-create-check +GnuPG normally verifies each signature right after creation to protect +against bugs and hardware malfunctions which could leak out bits from +the secret key. This extra verification needs some time (about 115% +for DSA keys), and so this option can be used to disable it. +However, due to the fact that the signature creation needs manual +interaction, this performance penalty does not matter in most settings. + +@item ---auto-check-trustdb +@itemx ---no-auto-check-trustdb +If GnuPG feels that its information about the Web-of-Trust has to be +updated, it automatically runs the ---check-trustdb command internally. +This may be a time consuming process. ---no-auto-check-trustdb +disables this option. + +@item ---throw-keyid +Do not put the keyids into encrypted packets. This option hides the +receiver of the message and is a countermeasure against traffic +analysis. It may slow down the decryption process because all +available secret keys are tried. + +@item ---no-throw-keyid +Resets the ---throw-keyid option. + +@item ---not-dash-escaped +This option changes the behavior of cleartext signatures +so that they can be used for patch files. You should not +send such an armored file via email because all spaces +and line endings are hashed too. You can not use this +option for data which has 5 dashes at the beginning of a +line, patch files don't have this. A special armor header +line tells GnuPG about this cleartext signature option. + +@item ---escape-from-lines +@itemx ---no-escape-from-lines +Because some mailers change lines starting with "From " to ">From +" it is good to handle such lines in a special way when creating +cleartext signatures to prevent the mail system from breaking the +signature. Note that all other PGP versions do it this way too. +Enabled by default. ---no-escape-from-lines disables this option. + +@item ---passphrase-fd @code{n} +Read the passphrase from file descriptor @code{n}. If you use +0 for @code{n}, the passphrase will be read from stdin. This +can only be used if only one passphrase is supplied. +Don't use this option if you can avoid it. + +@item ---command-fd @code{n} +This is a replacement for the deprecated shared-memory IPC mode. +If this option is enabled, user input on questions is not expected +from the TTY but from the given file descriptor. It should be used +together with ---status-fd. See the file doc/DETAILS in the source +distribution for details on how to use it. + +@item ---use-agent +@itemx ---no-use-agent +Try to use the GnuPG-Agent. Please note that this agent is still under +development. With this option, GnuPG first tries to connect to the +agent before it asks for a passphrase. ---no-use-agent disables this +option. + +@item ---gpg-agent-info +Override the value of the environment variable +@samp{GPG_AGENT_INFO}. This is only used when ---use-agent has been given + +@item Compliance options +These options control what GnuPG is compliant to. Only one of these +options may be active at a time. Note that the default setting of +this is nearly always the correct one. See the INTEROPERABILITY WITH +OTHER OPENPGP PROGRAMS section below before using one of these +options. + +@table @asis +@item ---gnupg +Use standard GnuPG behavior. This is essentially OpenPGP behavior +(see ---openpgp), but with some additional workarounds for common +compatibility problems in different versions of PGP. This is the +default option, so it is not generally needed, but it may be useful to +override a different compliance option in the gpg.conf file. + +@item ---openpgp +Reset all packet, cipher and digest options to strict OpenPGP +behavior. Use this option to reset all previous options like +---rfc1991, --force-v3-sigs, --s2k-*, --cipher-algo, --digest-algo and +---compress-algo to OpenPGP compliant values. All PGP workarounds are +disabled. + +@item ---rfc2440 +Reset all packet, cipher and digest options to strict RFC-2440 +behavior. Note that this is currently the same thing as ---openpgp. + +@item ---rfc1991 +Try to be more RFC-1991 (PGP 2.x) compliant. + +@item ---pgp2 +Set up all options to be as PGP 2.x compliant as possible, and warn if +an action is taken (e.g. encrypting to a non-RSA key) that will create +a message that PGP 2.x will not be able to handle. Note that `PGP +2.x' here means `MIT PGP 2.6.2'. There are other versions of PGP 2.x +available, but the MIT release is a good common baseline. + +This option implies `---rfc1991 --disable-mdc --no-force-v4-certs +---no-sk-comment --escape-from-lines --force-v3-sigs +---no-ask-sig-expire --no-ask-cert-expire --cipher-algo IDEA +---digest-algo MD5 --compress-algo 1'. It also disables --textmode +when encrypting. + +@item ---pgp6 +Set up all options to be as PGP 6 compliant as possible. This +restricts you to the ciphers IDEA (if the IDEA plugin is installed), +3DES, and CAST5, the hashes MD5, SHA1 and RIPEMD160, and the +compression algorithms none and ZIP. This also disables +---throw-keyid, and making signatures with signing subkeys as PGP 6 +does not understand signatures made by signing subkeys. + +This option implies `---disable-mdc --no-sk-comment --escape-from-lines +---force-v3-sigs --no-ask-sig-expire' + +@item ---pgp7 +Set up all options to be as PGP 7 compliant as possible. This is +identical to ---pgp6 except that MDCs are not disabled, and the list of +allowable ciphers is expanded to add AES128, AES192, AES256, and +TWOFISH. + +@item ---pgp8 +Set up all options to be as PGP 8 compliant as possible. PGP 8 is a +lot closer to the OpenPGP standard than previous versions of PGP, so +all this does is disable ---throw-keyid and set --escape-from-lines. +The allowed algorithms list is the same as ---pgp7 with the addition of +the SHA-256 digest algorithm. + +@end table + +@item ---force-v3-sigs +@itemx ---no-force-v3-sigs +OpenPGP states that an implementation should generate v4 signatures +but PGP versions 5 and higher only recognize v4 signatures on key +material. This option forces v3 signatures for signatures on data. +Note that this option overrides ---ask-sig-expire, as v3 signatures +cannot have expiration dates. ---no-force-v3-sigs disables this +option. + +@item ---force-v4-certs +@itemx ---no-force-v4-certs +Always use v4 key signatures even on v3 keys. This option also +changes the default hash algorithm for v3 RSA keys from MD5 to SHA-1. +---no-force-v4-certs disables this option. + +@item ---force-mdc +Force the use of encryption with a modification detection code. This +is always used with the newer ciphers (those with a blocksize greater +than 64 bits), or if all of the recipient keys indicate MDC support in +their feature flags. + +@item ---disable-mdc +Disable the use of the modification detection code. Note that by +using this option, the encrypted message becomes vulnerable to a +message modification attack. + +@item ---allow-non-selfsigned-uid +@itemx ---no-allow-non-selfsigned-uid +Allow the import and use of keys with user IDs which are not +self-signed. This is not recommended, as a non self-signed user ID is +trivial to forge. ---no-allow-non-selfsigned-uid disables. + +@item ---allow-freeform-uid +Disable all checks on the form of the user ID while generating a new +one. This option should only be used in very special environments as +it does not ensure the de-facto standard format of user IDs. + +@item ---ignore-time-conflict +GnuPG normally checks that the timestamps associated with keys and +signatures have plausible values. However, sometimes a signature +seems to be older than the key due to clock problems. This option +makes these checks just a warning. See also ---ignore-valid-from for +timestamp issues on subkeys. + +@item ---ignore-valid-from +GnuPG normally does not select and use subkeys created in the future. +This option allows the use of such keys and thus exhibits the +pre-1.0.7 behaviour. You should not use this option unless you there +is some clock problem. See also ---ignore-time-conflict for timestamp +issues with signatures. + +@item ---ignore-crc-error +The ASCII armor used by OpenPGP is protected by a CRC checksum against +transmission errors. Sometimes it happens that the CRC gets mangled +somewhere on the transmission channel but the actual content (which is +protected by the OpenPGP protocol anyway) is still okay. This option +will let gpg ignore CRC errors. + +@item ---ignore-mdc-error +This option changes a MDC integrity protection failure into a warning. +This can be useful if a message is partially corrupt, but it is +necessary to get as much data as possible out of the corrupt message. +However, be aware that a MDC protection failure may also mean that the +message was tampered with intentionally by an attacker. + +@item ---lock-once +Lock the databases the first time a lock is requested +and do not release the lock until the process +terminates. + +@item ---lock-multiple +Release the locks every time a lock is no longer +needed. Use this to override a previous ---lock-once +from a config file. + +@item ---lock-never +Disable locking entirely. This option should be used only in very +special environments, where it can be assured that only one process +is accessing those files. A bootable floppy with a stand-alone +encryption system will probably use this. Improper usage of this +option may lead to data and key corruption. + +@item ---no-random-seed-file +GnuPG uses a file to store its internal random pool over invocations. +This makes random generation faster; however sometimes write operations +are not desired. This option can be used to achieve that with the cost of +slower random generation. + +@item ---no-verbose +Reset verbose level to 0. + +@item ---no-greeting +Suppress the initial copyright message. + +@item ---no-secmem-warning +Suppress the warning about "using insecure memory". + +@item ---no-permission-warning +Suppress the warning about unsafe file and home directory (---homedir) +permissions. Note that the permission checks that GnuPG performs are +not intended to be authoritative, but rather they simply warn about +certain common permission problems. Do not assume that the lack of a +warning means that your system is secure. + +Note that the warning for unsafe ---homedir permissions cannot be +supressed in the gpg.conf file, as this would allow an attacker to +place an unsafe gpg.conf file in place, and use this file to supress +warnings about itself. The ---homedir permissions warning may only be +supressed on the command line. + +@item ---no-mdc-warning +Suppress the warning about missing MDC integrity protection. + +@item ---no-armor +Assume the input data is not in ASCII armored format. + +@item ---no-default-keyring +Do not add the default keyrings to the list of +keyrings. + +@item ---skip-verify +Skip the signature verification step. This may be +used to make the decryption faster if the signature +verification is not needed. + +@item ---with-colons +Print key listings delimited by colons. Note that the output will be +encoded in UTF-8 regardless of any ---charset setting. This format is +useful when GnuPG is called from scripts and other programs as it is +easily machine parsed. The details of this format are documented in +the file doc/DETAILS, which is included in the GnuPG source +distribution. + +@item ---with-key-data +Print key listings delimited by colons (like ---with-colons) and print the public key data. + +@item ---with-fingerprint +Same as the command ---fingerprint but changes only the format of the output +and may be used together with another command. + +@item ---fast-list-mode +Changes the output of the list commands to work faster; this is achieved +by leaving some parts empty. Some applications don't need the user ID and +the trust information given in the listings. By using this options they +can get a faster listing. The exact behaviour of this option may change +in future versions. + +@item ---fixed-list-mode +Do not merge primary user ID and primary key in ---with-colon listing +mode and print all timestamps as seconds since 1970-01-01. + +@item ---list-only +Changes the behaviour of some commands. This is like ---dry-run but +different in some cases. The semantic of this command may be extended in +the future. Currently it only skips the actual decryption pass and +therefore enables a fast listing of the encryption keys. + +@item ---no-literal +This is not for normal use. Use the source to see for what it might be useful. + +@item ---set-filesize +This is not for normal use. Use the source to see for what it might be useful. + +@item ---emulate-md-encode-bug +GnuPG versions prior to 1.0.2 had a bug in the way a signature was encoded. +This options enables a workaround by checking faulty signatures again with +the encoding used in old versions. This may only happen for ElGamal signatures +which are not widely used. + +@item ---show-session-key +Display the session key used for one message. See ---override-session-key +for the counterpart of this option. + +We think that Key-Escrow is a Bad Thing; however the user should +have the freedom to decide whether to go to prison or to reveal the content of +one specific message without compromising all messages ever encrypted for one +secret key. DON'T USE IT UNLESS YOU ARE REALLY FORCED TO DO SO. + +@item ---override-session-key @code{string} +Don't use the public key but the session key @code{string}. The format of this +string is the same as the one printed by ---show-session-key. This option +is normally not used but comes handy in case someone forces you to reveal the +content of an encrypted message; using this option you can do this without +handing out the secret key. + +@item ---ask-sig-expire +@itemx ---no-ask-sig-expire +When making a data signature, prompt for an expiration time. If this +option is not specified, the expiration time is "never". +---no-ask-sig-expire disables this option. + +@item ---ask-cert-expire +@itemx ---no-ask-cert-expire +When making a key signature, prompt for an expiration time. If this +option is not specified, the expiration time is "never". +---no-ask-cert-expire disables this option. + +@item ---expert +@itemx ---no-expert +Allow the user to do certain nonsensical or "silly" things like +signing an expired or revoked key, or certain potentially incompatible +things like generating deprecated key types. This also disables +certain warning messages about potentially incompatible actions. As +the name implies, this option is for experts only. If you don't fully +understand the implications of what it allows you to do, leave this +off. ---no-expert disables this option. + +@item ---merge-only +Don't insert new keys into the keyrings while doing an import. + +@item ---allow-secret-key-import +This is an obsolete option and is not used anywhere. + +@item ---try-all-secrets +Don't look at the key ID as stored in the message but try all secret keys in +turn to find the right decryption key. This option forces the behaviour as +used by anonymous recipients (created by using ---throw-keyid) and might come +handy in case where an encrypted message contains a bogus key ID. + +@item ---enable-special-filenames +This options enables a mode in which filenames of the form +@file{-&n}, where n is a non-negative decimal number, +refer to the file descriptor n and not to a file with that name. + +@item ---no-expensive-trust-checks +Experimental use only. + +@item ---group @code{name=value1 value2 value3 ...} +Sets up a named group, which is similar to aliases in email programs. +Any time the group name is a recipient (-r or ---recipient), it will +be expanded to the values specified. + +The values are @code{key IDs} or fingerprints, but any key description +is accepted. Note that a value with spaces in it will be treated as +two different values. Note also there is only one level of expansion +- you cannot make an group that points to another group. When used +from the command line, it may be necessary to quote the argument to +this option to prevent the shell from treating it as multiple +arguments. + +@item ---no-groups +Clear the ---group list. + +@item ---preserve-permissions +Don't change the permissions of a secret keyring back to user +read/write only. Use this option only if you really know what you are doing. + +@item ---personal-cipher-preferences @code{string} +Set the list of personal cipher preferences to @code{string}, this list +should be a string similar to the one printed by the command "pref" in +the edit menu. This allows the user to factor in their own preferred +algorithms when algorithms are chosen via recipient key preferences. +The most highly ranked cipher in this list is also used for the +---symmetric encryption command. + +@item ---personal-digest-preferences @code{string} +Set the list of personal digest preferences to @code{string}, this list +should be a string similar to the one printed by the command "pref" in +the edit menu. This allows the user to factor in their own preferred +algorithms when algorithms are chosen via recipient key preferences. +The most highly ranked digest algorithm in this list is algo used when +signing without encryption (e.g. ---clearsign or --sign). The default +value is SHA-1. + +@item ---personal-compress-preferences @code{string} +Set the list of personal compression preferences to @code{string}, this +list should be a string similar to the one printed by the command +"pref" in the edit menu. This allows the user to factor in their own +preferred algorithms when algorithms are chosen via recipient key +preferences. The most highly ranked algorithm in this list is also +used when there are no recipient keys to consider (e.g. ---symmetric). + +@item ---default-preference-list @code{string} +Set the list of default preferences to @code{string}, this list should +be a string similar to the one printed by the command "pref" in the +edit menu. This affects both key generation and "updpref" in the edit +menu. + +@end table + +@majorheading How to specify a user ID +There are different ways to specify a user ID to GnuPG; here are some +examples: + +@table @asis +@item +@item 234567C4 +@itemx 0F34E556E +@itemx 01347A56A +@itemx 0xAB123456 +Here the key ID is given in the usual short form. + +@item 234AABBCC34567C4 +@itemx 0F323456784E56EAB +@itemx 01AB3FED1347A5612 +@itemx 0x234AABBCC34567C4 +Here the key ID is given in the long form as used by OpenPGP +(you can get the long key ID using the option ---with-colons). + +@item 1234343434343434C434343434343434 +@itemx 123434343434343C3434343434343734349A3434 +@itemx 0E12343434343434343434EAB3484343434343434 +@itemx 0xE12343434343434343434EAB3484343434343434 +The best way to specify a key ID is by using the fingerprint of +the key. This avoids any ambiguities in case that there are duplicated +key IDs (which are really rare for the long key IDs). + +@item =Heinrich Heine <heinrichh@@uni-duesseldorf.de> +Using an exact to match string. The equal sign indicates this. + +@item <heinrichh@@uni-duesseldorf.de> +Using the email address part which must match exactly. The left angle bracket +indicates this email address mode. + +@item +Heinrich Heine duesseldorf +All words must match exactly (not case sensitive) but can appear in +any order in the user ID. Words are any sequences of letters, +digits, the underscore and all characters with bit 7 set. + +@item Heine +@itemx *Heine +By case insensitive substring matching. This is the default mode but +applications may want to explicitly indicate this by putting the asterisk +in front. + +@end table + +Note that you can append an exclamation mark to key IDs or +fingerprints. This flag tells GnuPG to use exactly the given primary +or secondary key and not to try to figure out which secondary or +primary key to use. + +@majorheading RETURN VALUE +The program returns 0 if everything was fine, 1 if at least +a signature was bad, and other error codes for fatal errors. + +@majorheading EXAMPLES +@table @asis +@item gpg -se -r @code{Bob} @code{file} +sign and encrypt for user Bob + +@item gpg ---clearsign @code{file} +make a clear text signature + +@item gpg -sb @code{file} +make a detached signature + +@item gpg ---list-keys @code{user_ID} +show keys + +@item gpg ---fingerprint @code{user_ID} +show fingerprint + +@item gpg ---verify @code{pgpfile} +@itemx gpg ---verify @code{sigfile} @code{files} +Verify the signature of the file but do not output the data. The second form +is used for detached signatures, where @code{sigfile} is the detached +signature (either ASCII armored of binary) and @code{files} are the signed +data; if this is not given the name of the file holding the signed data is +constructed by cutting off the extension (".asc" or ".sig") of +@code{sigfile} or by asking the user for the filename. + +@end table + +@majorheading ENVIRONMENT +@table @asis +@item HOME +Used to locate the default home directory. + +@item GNUPGHOME +If set directory used instead of "~/.gnupg". + +@item GPG_AGENT_INFO +Used to locate the gpg-agent; only honored when +---use-agent is set. The value consists of 3 colon delimited fields: +The first is the path to the Unix Domain Socket, the second the PID of +the gpg-agent and the protocol version which should be set to 1. When +starting the gpg-agent as described in its documentation, this +variable is set to the correct value. The option ---gpg-agent-info can +be used to override it. + +@item http_proxy +Only honored when the keyserver-option +honor-http-proxy is set. + +@end table + +@majorheading FILES +@table @asis +@item ~/.gnupg/secring.gpg +The secret keyring + +@item ~/.gnupg/secring.gpg.lock +and the lock file + +@item ~/.gnupg/pubring.gpg +The public keyring + +@item ~/.gnupg/pubring.gpg.lock +and the lock file + +@item ~/.gnupg/trustdb.gpg +The trust database + +@item ~/.gnupg/trustdb.gpg.lock +and the lock file + +@item ~/.gnupg/random_seed +used to preserve the internal random pool + +@item ~/.gnupg/gpg.conf +Default configuration file + +@item ~/.gnupg/options +Old style configuration file; only used when gpg.conf +is not found + +@item /usr[/local]/share/gnupg/options.skel +Skeleton options file + +@item /usr[/local]/lib/gnupg/ +Default location for extensions + +@end table + +@majorheading WARNINGS +Use a *good* password for your user account and a *good* passphrase +to protect your secret key. This passphrase is the weakest part of the +whole system. Programs to do dictionary attacks on your secret keyring +are very easy to write and so you should protect your "~/.gnupg/" +directory very well. + +Keep in mind that, if this program is used over a network (telnet), it +is *very* easy to spy out your passphrase! + +If you are going to verify detached signatures, make sure that the +program knows about it; either be giving both filenames on the +command line or using @samp{-} to specify stdin. + +@majorheading INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS +GnuPG tries to be a very flexible implementation of the OpenPGP +standard. In particular, GnuPG implements many of the "optional" +parts of the standard, such as the RIPEMD/160 hash, and the ZLIB +compression algorithms. It is important to be aware that not all +OpenPGP programs implement these optional algorithms and that by +forcing their use via the ---cipher-algo, --digest-algo, +---cert-digest-algo, or --compress-algo options in GnuPG, it is +possible to create a perfectly valid OpenPGP message, but one that +cannot be read by the intended recipient. + +For example, as of this writing, no version of official PGP supports +the BLOWFISH cipher algorithm. If you use it, no PGP user will be +able to decrypt your message. The same thing applies to the ZLIB +compression algorithm. By default, GnuPG uses the OpenPGP preferences +system that will always do the right thing and create messages that +are usable by all recipients, regardless of which OpenPGP program they +use. Only override this safe default if you know what you are doing. + +If you absolutely must override the safe default, or if the +preferences on a given key are invalid for some reason, you are far +better off using the ---pgp2, --pgp6, --pgp7, or --pgp8 options. These +options are safe as they do not force any particular algorithms in +violation of OpenPGP, but rather reduce the available algorithms to a +"PGP-safe" list. + +@majorheading BUGS +On many systems this program should be installed as setuid(root). This +is necessary to lock memory pages. Locking memory pages prevents the +operating system from writing memory pages to disk. If you get no +warning message about insecure memory your operating system supports +locking without being root. The program drops root privileges as soon +as locked memory is allocated. + +@bye diff --git a/intl/ChangeLog b/intl/ChangeLog new file mode 100644 index 000000000..eed2d21a4 --- /dev/null +++ b/intl/ChangeLog @@ -0,0 +1,4 @@ +2003-05-22 GNU <bug-gnu-gettext@gnu.org> + + * Version 0.12.1 released. + diff --git a/intl/Makefile.in b/intl/Makefile.in new file mode 100644 index 000000000..882396481 --- /dev/null +++ b/intl/Makefile.in @@ -0,0 +1,479 @@ +# Makefile for directory with message catalog handling library of GNU gettext +# Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc. +# +# This program 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, 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library 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. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = .. +VPATH = $(srcdir) + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +transform = @program_transform_name@ +libdir = @libdir@ +includedir = @includedir@ +datadir = @datadir@ +localedir = $(datadir)/locale +gettextsrcdir = $(datadir)/gettext/intl +aliaspath = $(localedir) +subdir = intl + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +mkinstalldirs = $(SHELL) $(MKINSTALLDIRS) + +l = @INTL_LIBTOOL_SUFFIX_PREFIX@ + +AR = ar +CC = @CC@ +LIBTOOL = @LIBTOOL@ +RANLIB = @RANLIB@ +YACC = @INTLBISON@ -y -d +YFLAGS = --name-prefix=__gettext + +DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \ +-DLIBDIR=\"$(libdir)\" -DIN_LIBINTL \ +-DENABLE_RELOCATABLE=1 -DIN_LIBRARY -DINSTALLDIR=\"$(libdir)\" -DNO_XMALLOC \ +-Dset_relocation_prefix=libintl_set_relocation_prefix \ +-Drelocate=libintl_relocate \ +-DDEPENDS_ON_LIBICONV=1 @DEFS@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +HEADERS = \ + gmo.h \ + gettextP.h \ + hash-string.h \ + loadinfo.h \ + plural-exp.h \ + eval-plural.h \ + localcharset.h \ + relocatable.h \ + os2compat.h \ + libgnuintl.h.in +SOURCES = \ + bindtextdom.c \ + dcgettext.c \ + dgettext.c \ + gettext.c \ + finddomain.c \ + loadmsgcat.c \ + localealias.c \ + textdomain.c \ + l10nflist.c \ + explodename.c \ + dcigettext.c \ + dcngettext.c \ + dngettext.c \ + ngettext.c \ + plural.y \ + plural-exp.c \ + localcharset.c \ + relocatable.c \ + localename.c \ + log.c \ + osdep.c \ + os2compat.c \ + intl-compat.c +OBJECTS = \ + bindtextdom.$lo \ + dcgettext.$lo \ + dgettext.$lo \ + gettext.$lo \ + finddomain.$lo \ + loadmsgcat.$lo \ + localealias.$lo \ + textdomain.$lo \ + l10nflist.$lo \ + explodename.$lo \ + dcigettext.$lo \ + dcngettext.$lo \ + dngettext.$lo \ + ngettext.$lo \ + plural.$lo \ + plural-exp.$lo \ + localcharset.$lo \ + relocatable.$lo \ + localename.$lo \ + log.$lo \ + osdep.$lo \ + intl-compat.$lo +DISTFILES.common = Makefile.in \ +config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) +DISTFILES.generated = plural.c +DISTFILES.normal = VERSION +DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc \ +Makefile.vms libgnuintl.h.msvc-shared README.woe32 Makefile.msvc +DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \ +COPYING.LIB-2 gettext.h libgettext.h plural-eval.c libgnuintl.h + +all: all-@USE_INCLUDED_LIBINTL@ +all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed +all-no: all-no-@BUILD_INCLUDED_LIBINTL@ +all-no-yes: libgnuintl.$la +all-no-no: + +libintl.a libgnuintl.a: $(OBJECTS) + rm -f $@ + $(AR) cru $@ $(OBJECTS) + $(RANLIB) $@ + +libintl.la libgnuintl.la: $(OBJECTS) + $(LIBTOOL) --mode=link \ + $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \ + $(OBJECTS) @LTLIBICONV@ $(LIBS) -lc \ + -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \ + -rpath $(libdir) \ + -no-undefined + +# Libtool's library version information for libintl. +# Before making a gettext release, the gettext maintainer must change this +# according to the libtool documentation, section "Library interface versions". +# Maintainers of other packages that include the intl directory must *not* +# change these values. +LTV_CURRENT=5 +LTV_REVISION=0 +LTV_AGE=3 + +.SUFFIXES: +.SUFFIXES: .c .y .o .lo .sin .sed + +.c.o: + $(COMPILE) $< + +.y.c: + $(YACC) $(YFLAGS) --output $@ $< + rm -f $*.h + +bindtextdom.lo: $(srcdir)/bindtextdom.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/bindtextdom.c +dcgettext.lo: $(srcdir)/dcgettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcgettext.c +dgettext.lo: $(srcdir)/dgettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dgettext.c +gettext.lo: $(srcdir)/gettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/gettext.c +finddomain.lo: $(srcdir)/finddomain.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/finddomain.c +loadmsgcat.lo: $(srcdir)/loadmsgcat.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/loadmsgcat.c +localealias.lo: $(srcdir)/localealias.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localealias.c +textdomain.lo: $(srcdir)/textdomain.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/textdomain.c +l10nflist.lo: $(srcdir)/l10nflist.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/l10nflist.c +explodename.lo: $(srcdir)/explodename.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/explodename.c +dcigettext.lo: $(srcdir)/dcigettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcigettext.c +dcngettext.lo: $(srcdir)/dcngettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcngettext.c +dngettext.lo: $(srcdir)/dngettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dngettext.c +ngettext.lo: $(srcdir)/ngettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/ngettext.c +plural.lo: $(srcdir)/plural.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural.c +plural-exp.lo: $(srcdir)/plural-exp.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural-exp.c +localcharset.lo: $(srcdir)/localcharset.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localcharset.c +relocatable.lo: $(srcdir)/relocatable.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/relocatable.c +localename.lo: $(srcdir)/localename.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c +log.lo: $(srcdir)/log.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c +osdep.lo: $(srcdir)/osdep.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c +intl-compat.lo: $(srcdir)/intl-compat.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/intl-compat.c + +ref-add.sed: $(srcdir)/ref-add.sin + sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-add.sin > t-ref-add.sed + mv t-ref-add.sed ref-add.sed +ref-del.sed: $(srcdir)/ref-del.sin + sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-del.sin > t-ref-del.sed + mv t-ref-del.sed ref-del.sed + +INCLUDES = -I. -I$(srcdir) -I.. + +libgnuintl.h: $(srcdir)/libgnuintl.h.in + cp $(srcdir)/libgnuintl.h.in libgnuintl.h + +libintl.h: libgnuintl.h + cp libgnuintl.h libintl.h + +charset.alias: $(srcdir)/config.charset + $(SHELL) $(srcdir)/config.charset '@host@' > t-$@ + mv t-$@ $@ + +check: all + +# We must not install the libintl.h/libintl.a files if we are on a +# system which has the GNU gettext() function in its C library or in a +# separate library. +# If you want to use the one which comes with this version of the +# package, you have to use `configure --with-included-gettext'. +install: install-exec install-data +install-exec: all + if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \ + && test '@USE_INCLUDED_LIBINTL@' = yes; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ + $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \ + $(LIBTOOL) --mode=install \ + $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \ + if test "@RELOCATABLE@" = yes; then \ + dependencies=`sed -n -e 's,^dependency_libs=\(.*\),\1,p' < $(DESTDIR)$(libdir)/libintl.la | sed -e "s,^',," -e "s,'\$$,,"`; \ + if test -n "$dependencies"; then \ + rm -f $(DESTDIR)$(libdir)/libintl.la; \ + fi; \ + fi; \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools" \ + && test '@USE_INCLUDED_LIBINTL@' = no; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir); \ + $(LIBTOOL) --mode=install \ + $(INSTALL_DATA) libgnuintl.$la $(DESTDIR)$(libdir)/libgnuintl.$la; \ + rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \ + $(INSTALL_DATA) $(DESTDIR)$(libdir)/libgnuintl.so $(DESTDIR)$(libdir)/preloadable_libintl.so; \ + $(LIBTOOL) --mode=uninstall \ + rm -f $(DESTDIR)$(libdir)/libgnuintl.$la; \ + else \ + : ; \ + fi + if test '@USE_INCLUDED_LIBINTL@' = yes; then \ + test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ + temp=$(DESTDIR)$(libdir)/t-charset.alias; \ + dest=$(DESTDIR)$(libdir)/charset.alias; \ + if test -f $(DESTDIR)$(libdir)/charset.alias; then \ + orig=$(DESTDIR)$(libdir)/charset.alias; \ + sed -f ref-add.sed $$orig > $$temp; \ + $(INSTALL_DATA) $$temp $$dest; \ + rm -f $$temp; \ + else \ + if test @GLIBC21@ = no; then \ + orig=charset.alias; \ + sed -f ref-add.sed $$orig > $$temp; \ + $(INSTALL_DATA) $$temp $$dest; \ + rm -f $$temp; \ + fi; \ + fi; \ + $(mkinstalldirs) $(DESTDIR)$(localedir); \ + test -f $(DESTDIR)$(localedir)/locale.alias \ + && orig=$(DESTDIR)$(localedir)/locale.alias \ + || orig=$(srcdir)/locale.alias; \ + temp=$(DESTDIR)$(localedir)/t-locale.alias; \ + dest=$(DESTDIR)$(localedir)/locale.alias; \ + sed -f ref-add.sed $$orig > $$temp; \ + $(INSTALL_DATA) $$temp $$dest; \ + rm -f $$temp; \ + else \ + : ; \ + fi +install-data: all + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ + $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \ + $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \ + dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \ + for file in $$dists; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \ + dists="$(DISTFILES.generated)"; \ + for file in $$dists; do \ + if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ + $(INSTALL_DATA) $$dir/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + dists="$(DISTFILES.obsolete)"; \ + for file in $$dists; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi + +install-strip: install + +installdirs: + if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \ + && test '@USE_INCLUDED_LIBINTL@' = yes; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools" \ + && test '@USE_INCLUDED_LIBINTL@' = no; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir); \ + else \ + : ; \ + fi + if test '@USE_INCLUDED_LIBINTL@' = yes; then \ + test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ + $(mkinstalldirs) $(DESTDIR)$(localedir); \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \ + && test '@USE_INCLUDED_LIBINTL@' = yes; then \ + rm -f $(DESTDIR)$(includedir)/libintl.h; \ + $(LIBTOOL) --mode=uninstall \ + rm -f $(DESTDIR)$(libdir)/libintl.$la; \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools" \ + && test '@USE_INCLUDED_LIBINTL@' = no; then \ + rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \ + else \ + : ; \ + fi + if test '@USE_INCLUDED_LIBINTL@' = yes; then \ + if test -f $(DESTDIR)$(libdir)/charset.alias; then \ + temp=$(DESTDIR)$(libdir)/t-charset.alias; \ + dest=$(DESTDIR)$(libdir)/charset.alias; \ + sed -f ref-del.sed $$dest > $$temp; \ + if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ + rm -f $$dest; \ + else \ + $(INSTALL_DATA) $$temp $$dest; \ + fi; \ + rm -f $$temp; \ + fi; \ + if test -f $(DESTDIR)$(localedir)/locale.alias; then \ + temp=$(DESTDIR)$(localedir)/t-locale.alias; \ + dest=$(DESTDIR)$(localedir)/locale.alias; \ + sed -f ref-del.sed $$dest > $$temp; \ + if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ + rm -f $$dest; \ + else \ + $(INSTALL_DATA) $$temp $$dest; \ + fi; \ + rm -f $$temp; \ + fi; \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi + +info dvi ps pdf html: + +$(OBJECTS): ../config.h libgnuintl.h +bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo textdomain.$lo: $(srcdir)/gettextP.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h +dcigettext.$lo loadmsgcat.$lo: $(srcdir)/hash-string.h +explodename.$lo l10nflist.$lo: $(srcdir)/loadinfo.h +dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.h +dcigettext.$lo: $(srcdir)/eval-plural.h +localcharset.$lo: $(srcdir)/localcharset.h +localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h + +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) + +ctags: CTAGS + +CTAGS: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && ctags -o $$here/CTAGS $(HEADERS) $(SOURCES) + +id: ID + +ID: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) + + +mostlyclean: + rm -f *.a *.la *.o *.obj *.lo core core.* + rm -f libgnuintl.h libintl.h charset.alias ref-add.sed ref-del.sed + rm -f -r .libs _libs + +clean: mostlyclean + +distclean: clean + rm -f Makefile ID TAGS + if test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; then \ + rm -f ChangeLog.inst $(DISTFILES.normal); \ + else \ + : ; \ + fi + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + + +# GNU gettext needs not contain the file `VERSION' but contains some +# other files which should not be distributed in other packages. +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: Makefile + if test "$(PACKAGE)" = "gettext-tools"; then \ + : ; \ + else \ + if test "$(PACKAGE)" = "gettext-runtime"; then \ + additional="$(DISTFILES.gettext)"; \ + else \ + additional="$(DISTFILES.normal)"; \ + fi; \ + $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \ + for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \ + if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ + cp -p $$dir/$$file $(distdir); \ + done; \ + fi + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status +# This would be more efficient, but doesn't work any more with autoconf-2.57, +# when AC_CONFIG_FILES([intl/Makefile:somedir/Makefile.in]) is used. +# cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/intl/VERSION b/intl/VERSION new file mode 100644 index 000000000..130318357 --- /dev/null +++ b/intl/VERSION @@ -0,0 +1 @@ +GNU gettext library from gettext-0.12.1 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c new file mode 100644 index 000000000..250f5e863 --- /dev/null +++ b/intl/bindtextdom.c @@ -0,0 +1,374 @@ +/* Implementation of the bindtextdomain(3) function + Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <stddef.h> +#include <stdlib.h> +#include <string.h> + +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif +#include "gettextP.h" + +#ifdef _LIBC +/* We have to handle multi-threaded applications. */ +# include <bits/libc-lock.h> +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_rwlock_define(CLASS, NAME) +# define __libc_rwlock_wrlock(NAME) +# define __libc_rwlock_unlock(NAME) +#endif + +/* The internal variables in the standalone libintl.a must have different + names than the internal variables in GNU libc, otherwise programs + using libintl.a cannot be linked statically. */ +#if !defined _LIBC +# define _nl_default_dirname libintl_nl_default_dirname +# define _nl_domain_bindings libintl_nl_domain_bindings +#endif + +/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ +#ifndef offsetof +# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) +#endif + +/* @@ end of prolog @@ */ + +/* Contains the default location of the message catalogs. */ +extern const char _nl_default_dirname[]; +#ifdef _LIBC +extern const char _nl_default_dirname_internal[] attribute_hidden; +#else +# define INTUSE(name) name +#endif + +/* List with bindings of specific domains. */ +extern struct binding *_nl_domain_bindings; + +/* Lock variable to protect the global data in the gettext implementation. */ +__libc_rwlock_define (extern, _nl_state_lock attribute_hidden) + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define BINDTEXTDOMAIN __bindtextdomain +# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset +# ifndef strdup +# define strdup(str) __strdup (str) +# endif +#else +# define BINDTEXTDOMAIN libintl_bindtextdomain +# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset +#endif + +/* Prototypes for local functions. */ +static void set_binding_values PARAMS ((const char *domainname, + const char **dirnamep, + const char **codesetp)); + +/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP + to be used for the DOMAINNAME message catalog. + If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not + modified, only the current value is returned. + If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither + modified nor returned. */ +static void +set_binding_values (domainname, dirnamep, codesetp) + const char *domainname; + const char **dirnamep; + const char **codesetp; +{ + struct binding *binding; + int modified; + + /* Some sanity checks. */ + if (domainname == NULL || domainname[0] == '\0') + { + if (dirnamep) + *dirnamep = NULL; + if (codesetp) + *codesetp = NULL; + return; + } + + __libc_rwlock_wrlock (_nl_state_lock); + + modified = 0; + + for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) + { + int compare = strcmp (domainname, binding->domainname); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It is not in the list. */ + binding = NULL; + break; + } + } + + if (binding != NULL) + { + if (dirnamep) + { + const char *dirname = *dirnamep; + + if (dirname == NULL) + /* The current binding has be to returned. */ + *dirnamep = binding->dirname; + else + { + /* The domain is already bound. If the new value and the old + one are equal we simply do nothing. Otherwise replace the + old binding. */ + char *result = binding->dirname; + if (strcmp (dirname, result) != 0) + { + if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0) + result = (char *) INTUSE(_nl_default_dirname); + else + { +#if defined _LIBC || defined HAVE_STRDUP + result = strdup (dirname); +#else + size_t len = strlen (dirname) + 1; + result = (char *) malloc (len); + if (__builtin_expect (result != NULL, 1)) + memcpy (result, dirname, len); +#endif + } + + if (__builtin_expect (result != NULL, 1)) + { + if (binding->dirname != INTUSE(_nl_default_dirname)) + free (binding->dirname); + + binding->dirname = result; + modified = 1; + } + } + *dirnamep = result; + } + } + + if (codesetp) + { + const char *codeset = *codesetp; + + if (codeset == NULL) + /* The current binding has be to returned. */ + *codesetp = binding->codeset; + else + { + /* The domain is already bound. If the new value and the old + one are equal we simply do nothing. Otherwise replace the + old binding. */ + char *result = binding->codeset; + if (result == NULL || strcmp (codeset, result) != 0) + { +#if defined _LIBC || defined HAVE_STRDUP + result = strdup (codeset); +#else + size_t len = strlen (codeset) + 1; + result = (char *) malloc (len); + if (__builtin_expect (result != NULL, 1)) + memcpy (result, codeset, len); +#endif + + if (__builtin_expect (result != NULL, 1)) + { + if (binding->codeset != NULL) + free (binding->codeset); + + binding->codeset = result; + binding->codeset_cntr++; + modified = 1; + } + } + *codesetp = result; + } + } + } + else if ((dirnamep == NULL || *dirnamep == NULL) + && (codesetp == NULL || *codesetp == NULL)) + { + /* Simply return the default values. */ + if (dirnamep) + *dirnamep = INTUSE(_nl_default_dirname); + if (codesetp) + *codesetp = NULL; + } + else + { + /* We have to create a new binding. */ + size_t len = strlen (domainname) + 1; + struct binding *new_binding = + (struct binding *) malloc (offsetof (struct binding, domainname) + len); + + if (__builtin_expect (new_binding == NULL, 0)) + goto failed; + + memcpy (new_binding->domainname, domainname, len); + + if (dirnamep) + { + const char *dirname = *dirnamep; + + if (dirname == NULL) + /* The default value. */ + dirname = INTUSE(_nl_default_dirname); + else + { + if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0) + dirname = INTUSE(_nl_default_dirname); + else + { + char *result; +#if defined _LIBC || defined HAVE_STRDUP + result = strdup (dirname); + if (__builtin_expect (result == NULL, 0)) + goto failed_dirname; +#else + size_t len = strlen (dirname) + 1; + result = (char *) malloc (len); + if (__builtin_expect (result == NULL, 0)) + goto failed_dirname; + memcpy (result, dirname, len); +#endif + dirname = result; + } + } + *dirnamep = dirname; + new_binding->dirname = (char *) dirname; + } + else + /* The default value. */ + new_binding->dirname = (char *) INTUSE(_nl_default_dirname); + + new_binding->codeset_cntr = 0; + + if (codesetp) + { + const char *codeset = *codesetp; + + if (codeset != NULL) + { + char *result; + +#if defined _LIBC || defined HAVE_STRDUP + result = strdup (codeset); + if (__builtin_expect (result == NULL, 0)) + goto failed_codeset; +#else + size_t len = strlen (codeset) + 1; + result = (char *) malloc (len); + if (__builtin_expect (result == NULL, 0)) + goto failed_codeset; + memcpy (result, codeset, len); +#endif + codeset = result; + new_binding->codeset_cntr++; + } + *codesetp = codeset; + new_binding->codeset = (char *) codeset; + } + else + new_binding->codeset = NULL; + + /* Now enqueue it. */ + if (_nl_domain_bindings == NULL + || strcmp (domainname, _nl_domain_bindings->domainname) < 0) + { + new_binding->next = _nl_domain_bindings; + _nl_domain_bindings = new_binding; + } + else + { + binding = _nl_domain_bindings; + while (binding->next != NULL + && strcmp (domainname, binding->next->domainname) > 0) + binding = binding->next; + + new_binding->next = binding->next; + binding->next = new_binding; + } + + modified = 1; + + /* Here we deal with memory allocation failures. */ + if (0) + { + failed_codeset: + if (new_binding->dirname != INTUSE(_nl_default_dirname)) + free (new_binding->dirname); + failed_dirname: + free (new_binding); + failed: + if (dirnamep) + *dirnamep = NULL; + if (codesetp) + *codesetp = NULL; + } + } + + /* If we modified any binding, we flush the caches. */ + if (modified) + ++_nl_msg_cat_cntr; + + __libc_rwlock_unlock (_nl_state_lock); +} + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +char * +BINDTEXTDOMAIN (domainname, dirname) + const char *domainname; + const char *dirname; +{ + set_binding_values (domainname, &dirname, NULL); + return (char *) dirname; +} + +/* Specify the character encoding in which the messages from the + DOMAINNAME message catalog will be returned. */ +char * +BIND_TEXTDOMAIN_CODESET (domainname, codeset) + const char *domainname; + const char *codeset; +{ + set_binding_values (domainname, NULL, &codeset); + return (char *) codeset; +} + +#ifdef _LIBC +/* Aliases for function names in GNU C Library. */ +weak_alias (__bindtextdomain, bindtextdomain); +weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset); +#endif diff --git a/intl/config.charset b/intl/config.charset new file mode 100755 index 000000000..32becece9 --- /dev/null +++ b/intl/config.charset @@ -0,0 +1,467 @@ +#! /bin/sh +# Output a system dependent table of character encoding aliases. +# +# Copyright (C) 2000-2003 Free Software Foundation, Inc. +# +# This program 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, 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library 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. +# +# The table consists of lines of the form +# ALIAS CANONICAL +# +# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". +# ALIAS is compared in a case sensitive way. +# +# CANONICAL is the GNU canonical name for this character encoding. +# It must be an encoding supported by libiconv. Support by GNU libc is +# also desirable. CANONICAL is case insensitive. Usually an upper case +# MIME charset name is preferred. +# The current list of GNU canonical charset names is as follows. +# +# name used by which systems a MIME name? +# ASCII, ANSI_X3.4-1968 glibc solaris freebsd +# ISO-8859-1 glibc aix hpux irix osf solaris freebsd yes +# ISO-8859-2 glibc aix hpux irix osf solaris freebsd yes +# ISO-8859-3 glibc solaris yes +# ISO-8859-4 osf solaris freebsd yes +# ISO-8859-5 glibc aix hpux irix osf solaris freebsd yes +# ISO-8859-6 glibc aix hpux solaris yes +# ISO-8859-7 glibc aix hpux irix osf solaris yes +# ISO-8859-8 glibc aix hpux osf solaris yes +# ISO-8859-9 glibc aix hpux irix osf solaris yes +# ISO-8859-13 glibc +# ISO-8859-14 glibc +# ISO-8859-15 glibc aix osf solaris freebsd +# KOI8-R glibc solaris freebsd yes +# KOI8-U glibc freebsd yes +# KOI8-T glibc +# CP437 dos +# CP775 dos +# CP850 aix osf dos +# CP852 dos +# CP855 dos +# CP856 aix +# CP857 dos +# CP861 dos +# CP862 dos +# CP864 dos +# CP865 dos +# CP866 freebsd dos +# CP869 dos +# CP874 woe32 dos +# CP922 aix +# CP932 aix woe32 dos +# CP943 aix +# CP949 osf woe32 dos +# CP950 woe32 dos +# CP1046 aix +# CP1124 aix +# CP1125 dos +# CP1129 aix +# CP1250 woe32 +# CP1251 glibc solaris woe32 +# CP1252 aix woe32 +# CP1253 woe32 +# CP1254 woe32 +# CP1255 glibc woe32 +# CP1256 woe32 +# CP1257 woe32 +# GB2312 glibc aix hpux irix solaris freebsd yes +# EUC-JP glibc aix hpux irix osf solaris freebsd yes +# EUC-KR glibc aix hpux irix osf solaris freebsd yes +# EUC-TW glibc aix hpux irix osf solaris +# BIG5 glibc aix hpux osf solaris freebsd yes +# BIG5-HKSCS glibc solaris +# GBK glibc aix osf solaris woe32 dos +# GB18030 glibc solaris +# SHIFT_JIS hpux osf solaris freebsd yes +# JOHAB glibc solaris woe32 +# TIS-620 glibc aix hpux osf solaris +# VISCII glibc yes +# TCVN5712-1 glibc +# GEORGIAN-PS glibc +# HP-ROMAN8 hpux +# HP-ARABIC8 hpux +# HP-GREEK8 hpux +# HP-HEBREW8 hpux +# HP-TURKISH8 hpux +# HP-KANA8 hpux +# DEC-KANJI osf +# DEC-HANYU osf +# UTF-8 glibc aix hpux osf solaris yes +# +# Note: Names which are not marked as being a MIME name should not be used in +# Internet protocols for information interchange (mail, news, etc.). +# +# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications +# must understand both names and treat them as equivalent. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM + +host="$1" +os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` +echo "# This file contains a table of character encoding aliases," +echo "# suitable for operating system '${os}'." +echo "# It was automatically generated from config.charset." +# List of references, updated during installation: +echo "# Packages using this file: " +case "$os" in + linux* | *-gnu*) + # With glibc-2.1 or newer, we don't need any canonicalization, + # because glibc has iconv and both glibc and libiconv support all + # GNU canonical names directly. Therefore, the Makefile does not + # need to install the alias file at all. + # The following applies only to glibc-2.0.x and older libcs. + echo "ISO_646.IRV:1983 ASCII" + ;; + aix*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-6 ISO-8859-6" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "IBM-850 CP850" + echo "IBM-856 CP856" + echo "IBM-921 ISO-8859-13" + echo "IBM-922 CP922" + echo "IBM-932 CP932" + echo "IBM-943 CP943" + echo "IBM-1046 CP1046" + echo "IBM-1124 CP1124" + echo "IBM-1129 CP1129" + echo "IBM-1252 CP1252" + echo "IBM-eucCN GB2312" + echo "IBM-eucJP EUC-JP" + echo "IBM-eucKR EUC-KR" + echo "IBM-eucTW EUC-TW" + echo "big5 BIG5" + echo "GBK GBK" + echo "TIS-620 TIS-620" + echo "UTF-8 UTF-8" + ;; + hpux*) + echo "iso88591 ISO-8859-1" + echo "iso88592 ISO-8859-2" + echo "iso88595 ISO-8859-5" + echo "iso88596 ISO-8859-6" + echo "iso88597 ISO-8859-7" + echo "iso88598 ISO-8859-8" + echo "iso88599 ISO-8859-9" + echo "iso885915 ISO-8859-15" + echo "roman8 HP-ROMAN8" + echo "arabic8 HP-ARABIC8" + echo "greek8 HP-GREEK8" + echo "hebrew8 HP-HEBREW8" + echo "turkish8 HP-TURKISH8" + echo "kana8 HP-KANA8" + echo "tis620 TIS-620" + echo "big5 BIG5" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "hp15CN GB2312" + #echo "ccdc ?" # what is this? + echo "SJIS SHIFT_JIS" + echo "utf8 UTF-8" + ;; + irix*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-9 ISO-8859-9" + echo "eucCN GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + ;; + osf*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "cp850 CP850" + echo "big5 BIG5" + echo "dechanyu DEC-HANYU" + echo "dechanzi GB2312" + echo "deckanji DEC-KANJI" + echo "deckorean EUC-KR" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "GBK GBK" + echo "KSC5601 CP949" + echo "sdeckanji EUC-JP" + echo "SJIS SHIFT_JIS" + echo "TACTIS TIS-620" + echo "UTF-8 UTF-8" + ;; + solaris*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-3 ISO-8859-3" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-6 ISO-8859-6" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "koi8-r KOI8-R" + echo "ansi-1251 CP1251" + echo "BIG5 BIG5" + echo "Big5-HKSCS BIG5-HKSCS" + echo "gb2312 GB2312" + echo "GBK GBK" + echo "GB18030 GB18030" + echo "cns11643 EUC-TW" + echo "5601 EUC-KR" + echo "ko_KR.johap92 JOHAB" + echo "eucJP EUC-JP" + echo "PCK SHIFT_JIS" + echo "TIS620.2533 TIS-620" + #echo "sun_eu_greek ?" # what is this? + echo "UTF-8 UTF-8" + ;; + freebsd* | os2*) + # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just + # reuse FreeBSD's locale data for OS/2. + echo "C ASCII" + echo "US-ASCII ASCII" + for l in la_LN lt_LN; do + echo "$l.ASCII ASCII" + done + for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ + fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ + lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do + echo "$l.ISO_8859-1 ISO-8859-1" + echo "$l.DIS_8859-15 ISO-8859-15" + done + for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do + echo "$l.ISO_8859-2 ISO-8859-2" + done + for l in la_LN lt_LT; do + echo "$l.ISO_8859-4 ISO-8859-4" + done + for l in ru_RU ru_SU; do + echo "$l.KOI8-R KOI8-R" + echo "$l.ISO_8859-5 ISO-8859-5" + echo "$l.CP866 CP866" + done + echo "uk_UA.KOI8-U KOI8-U" + echo "zh_TW.BIG5 BIG5" + echo "zh_TW.Big5 BIG5" + echo "zh_CN.EUC GB2312" + echo "ja_JP.EUC EUC-JP" + echo "ja_JP.SJIS SHIFT_JIS" + echo "ja_JP.Shift_JIS SHIFT_JIS" + echo "ko_KR.EUC EUC-KR" + ;; + netbsd*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-15 ISO-8859-15" + echo "eucCN GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "BIG5 BIG5" + echo "SJIS SHIFT_JIS" + ;; + beos*) + # BeOS has a single locale, and it has UTF-8 encoding. + echo "* UTF-8" + ;; + msdosdjgpp*) + # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "#" + echo "# The encodings given here may not all be correct." + echo "# If you find that the encoding given for your language and" + echo "# country is not the one your DOS machine actually uses, just" + echo "# correct it in this file, and send a mail to" + echo "# Juan Manuel Guerrero <st001906@hrz1.hrz.tu-darmstadt.de>" + echo "# and Bruno Haible <bruno@clisp.org>." + echo "#" + echo "C ASCII" + # ISO-8859-1 languages + echo "ca CP850" + echo "ca_ES CP850" + echo "da CP865" # not CP850 ?? + echo "da_DK CP865" # not CP850 ?? + echo "de CP850" + echo "de_AT CP850" + echo "de_CH CP850" + echo "de_DE CP850" + echo "en CP850" + echo "en_AU CP850" # not CP437 ?? + echo "en_CA CP850" + echo "en_GB CP850" + echo "en_NZ CP437" + echo "en_US CP437" + echo "en_ZA CP850" # not CP437 ?? + echo "es CP850" + echo "es_AR CP850" + echo "es_BO CP850" + echo "es_CL CP850" + echo "es_CO CP850" + echo "es_CR CP850" + echo "es_CU CP850" + echo "es_DO CP850" + echo "es_EC CP850" + echo "es_ES CP850" + echo "es_GT CP850" + echo "es_HN CP850" + echo "es_MX CP850" + echo "es_NI CP850" + echo "es_PA CP850" + echo "es_PY CP850" + echo "es_PE CP850" + echo "es_SV CP850" + echo "es_UY CP850" + echo "es_VE CP850" + echo "et CP850" + echo "et_EE CP850" + echo "eu CP850" + echo "eu_ES CP850" + echo "fi CP850" + echo "fi_FI CP850" + echo "fr CP850" + echo "fr_BE CP850" + echo "fr_CA CP850" + echo "fr_CH CP850" + echo "fr_FR CP850" + echo "ga CP850" + echo "ga_IE CP850" + echo "gd CP850" + echo "gd_GB CP850" + echo "gl CP850" + echo "gl_ES CP850" + echo "id CP850" # not CP437 ?? + echo "id_ID CP850" # not CP437 ?? + echo "is CP861" # not CP850 ?? + echo "is_IS CP861" # not CP850 ?? + echo "it CP850" + echo "it_CH CP850" + echo "it_IT CP850" + echo "lt CP775" + echo "lt_LT CP775" + echo "lv CP775" + echo "lv_LV CP775" + echo "nb CP865" # not CP850 ?? + echo "nb_NO CP865" # not CP850 ?? + echo "nl CP850" + echo "nl_BE CP850" + echo "nl_NL CP850" + echo "nn CP865" # not CP850 ?? + echo "nn_NO CP865" # not CP850 ?? + echo "no CP865" # not CP850 ?? + echo "no_NO CP865" # not CP850 ?? + echo "pt CP850" + echo "pt_BR CP850" + echo "pt_PT CP850" + echo "sv CP850" + echo "sv_SE CP850" + # ISO-8859-2 languages + echo "cs CP852" + echo "cs_CZ CP852" + echo "hr CP852" + echo "hr_HR CP852" + echo "hu CP852" + echo "hu_HU CP852" + echo "pl CP852" + echo "pl_PL CP852" + echo "ro CP852" + echo "ro_RO CP852" + echo "sk CP852" + echo "sk_SK CP852" + echo "sl CP852" + echo "sl_SI CP852" + echo "sq CP852" + echo "sq_AL CP852" + echo "sr CP852" # CP852 or CP866 or CP855 ?? + echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? + # ISO-8859-3 languages + echo "mt CP850" + echo "mt_MT CP850" + # ISO-8859-5 languages + echo "be CP866" + echo "be_BE CP866" + echo "bg CP866" # not CP855 ?? + echo "bg_BG CP866" # not CP855 ?? + echo "mk CP866" # not CP855 ?? + echo "mk_MK CP866" # not CP855 ?? + echo "ru CP866" + echo "ru_RU CP866" + echo "uk CP1125" + echo "uk_UA CP1125" + # ISO-8859-6 languages + echo "ar CP864" + echo "ar_AE CP864" + echo "ar_DZ CP864" + echo "ar_EG CP864" + echo "ar_IQ CP864" + echo "ar_IR CP864" + echo "ar_JO CP864" + echo "ar_KW CP864" + echo "ar_MA CP864" + echo "ar_OM CP864" + echo "ar_QA CP864" + echo "ar_SA CP864" + echo "ar_SY CP864" + # ISO-8859-7 languages + echo "el CP869" + echo "el_GR CP869" + # ISO-8859-8 languages + echo "he CP862" + echo "he_IL CP862" + # ISO-8859-9 languages + echo "tr CP857" + echo "tr_TR CP857" + # Japanese + echo "ja CP932" + echo "ja_JP CP932" + # Chinese + echo "zh_CN GBK" + echo "zh_TW CP950" # not CP938 ?? + # Korean + echo "kr CP949" # not CP934 ?? + echo "kr_KR CP949" # not CP934 ?? + # Thai + echo "th CP874" + echo "th_TH CP874" + # Other + echo "eo CP850" + echo "eo_EO CP850" + ;; +esac diff --git a/intl/dcgettext.c b/intl/dcgettext.c new file mode 100644 index 000000000..ca6a1c82d --- /dev/null +++ b/intl/dcgettext.c @@ -0,0 +1,59 @@ +/* Implementation of the dcgettext(3) function. + Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DCGETTEXT __dcgettext +# define DCIGETTEXT __dcigettext +#else +# define DCGETTEXT libintl_dcgettext +# define DCIGETTEXT libintl_dcigettext +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +char * +DCGETTEXT (domainname, msgid, category) + const char *domainname; + const char *msgid; + int category; +{ + return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +INTDEF(__dcgettext) +weak_alias (__dcgettext, dcgettext); +#endif diff --git a/intl/dcigettext.c b/intl/dcigettext.c new file mode 100644 index 000000000..f6edb95c0 --- /dev/null +++ b/intl/dcigettext.c @@ -0,0 +1,1238 @@ +/* Implementation of the internal dcigettext function. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Tell glibc's <string.h> to provide a prototype for mempcpy(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> + +#ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include <errno.h> +#ifndef errno +extern int errno; +#endif +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#if defined HAVE_UNISTD_H || defined _LIBC +# include <unistd.h> +#endif + +#include <locale.h> + +#ifdef _LIBC + /* Guess whether integer division by zero raises signal SIGFPE. + Set to 1 only if you know for sure. In case of doubt, set to 0. */ +# if defined __alpha__ || defined __arm__ || defined __i386__ \ + || defined __m68k__ || defined __s390__ +# define INTDIV0_RAISES_SIGFPE 1 +# else +# define INTDIV0_RAISES_SIGFPE 0 +# endif +#endif +#if !INTDIV0_RAISES_SIGFPE +# include <signal.h> +#endif + +#if defined HAVE_SYS_PARAM_H || defined _LIBC +# include <sys/param.h> +#endif + +#include "gettextP.h" +#include "plural-exp.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif +#include "hash-string.h" + +/* Thread safetyness. */ +#ifdef _LIBC +# include <bits/libc-lock.h> +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_lock_define_initialized(CLASS, NAME) +# define __libc_lock_lock(NAME) +# define __libc_lock_unlock(NAME) +# define __libc_rwlock_define_initialized(CLASS, NAME) +# define __libc_rwlock_rdlock(NAME) +# define __libc_rwlock_unlock(NAME) +#endif + +/* Alignment of types. */ +#if defined __GNUC__ && __GNUC__ >= 2 +# define alignof(TYPE) __alignof__ (TYPE) +#else +# define alignof(TYPE) \ + ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) +#endif + +/* The internal variables in the standalone libintl.a must have different + names than the internal variables in GNU libc, otherwise programs + using libintl.a cannot be linked statically. */ +#if !defined _LIBC +# define _nl_default_default_domain libintl_nl_default_default_domain +# define _nl_current_default_domain libintl_nl_current_default_domain +# define _nl_default_dirname libintl_nl_default_dirname +# define _nl_domain_bindings libintl_nl_domain_bindings +#endif + +/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ +#ifndef offsetof +# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) +#endif + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# define getcwd __getcwd +# ifndef stpcpy +# define stpcpy __stpcpy +# endif +# define tfind __tfind +#else +# if !defined HAVE_GETCWD +char *getwd (); +# define getcwd(buf, max) getwd (buf) +# else +char *getcwd (); +# endif +# ifndef HAVE_STPCPY +static char *stpcpy PARAMS ((char *dest, const char *src)); +# endif +# ifndef HAVE_MEMPCPY +static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); +# endif +#endif + +/* Amount to increase buffer size by in each try. */ +#define PATH_INCR 32 + +/* The following is from pathmax.h. */ +/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define + PATH_MAX but might cause redefinition warnings when sys/param.h is + later included (as on MORE/BSD 4.3). */ +#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) +# include <limits.h> +#endif + +#ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 255 +#endif + +#if !defined PATH_MAX && defined _PC_PATH_MAX +# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) +#endif + +/* Don't include sys/param.h if it already has been. */ +#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN +# include <sys/param.h> +#endif + +#if !defined PATH_MAX && defined MAXPATHLEN +# define PATH_MAX MAXPATHLEN +#endif + +#ifndef PATH_MAX +# define PATH_MAX _POSIX_PATH_MAX +#endif + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, + it may be concatenated to a directory pathname. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +#endif + +/* This is the type used for the search tree where known translations + are stored. */ +struct known_translation_t +{ + /* Domain in which to search. */ + char *domainname; + + /* The category. */ + int category; + + /* State of the catalog counter at the point the string was found. */ + int counter; + + /* Catalog where the string was found. */ + struct loaded_l10nfile *domain; + + /* And finally the translation. */ + const char *translation; + size_t translation_length; + + /* Pointer to the string in question. */ + char msgid[ZERO]; +}; + +/* Root of the search tree with known translations. We can use this + only if the system provides the `tsearch' function family. */ +#if defined HAVE_TSEARCH || defined _LIBC +# include <search.h> + +static void *root; + +# ifdef _LIBC +# define tsearch __tsearch +# endif + +/* Function to compare two entries in the table of known translations. */ +static int transcmp PARAMS ((const void *p1, const void *p2)); +static int +transcmp (p1, p2) + const void *p1; + const void *p2; +{ + const struct known_translation_t *s1; + const struct known_translation_t *s2; + int result; + + s1 = (const struct known_translation_t *) p1; + s2 = (const struct known_translation_t *) p2; + + result = strcmp (s1->msgid, s2->msgid); + if (result == 0) + { + result = strcmp (s1->domainname, s2->domainname); + if (result == 0) + /* We compare the category last (though this is the cheapest + operation) since it is hopefully always the same (namely + LC_MESSAGES). */ + result = s1->category - s2->category; + } + + return result; +} +#endif + +#ifndef INTVARDEF +# define INTVARDEF(name) +#endif +#ifndef INTUSE +# define INTUSE(name) name +#endif + +/* Name of the default domain used for gettext(3) prior any call to + textdomain(3). The default value for this is "messages". */ +const char _nl_default_default_domain[] attribute_hidden = "messages"; + +/* Value used as the default domain for gettext(3). */ +const char *_nl_current_default_domain attribute_hidden + = _nl_default_default_domain; + +/* Contains the default location of the message catalogs. */ +#if defined __EMX__ +extern const char _nl_default_dirname[]; +#else +const char _nl_default_dirname[] = LOCALEDIR; +INTVARDEF (_nl_default_dirname) +#endif + +/* List with bindings of specific domains created by bindtextdomain() + calls. */ +struct binding *_nl_domain_bindings; + +/* Prototypes for local functions. */ +static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, + unsigned long int n, + const char *translation, + size_t translation_len)) + internal_function; +static const char *guess_category_value PARAMS ((int category, + const char *categoryname)) + internal_function; +#ifdef _LIBC +# include "../locale/localeinfo.h" +# define category_to_name(category) _nl_category_names[category] +#else +static const char *category_to_name PARAMS ((int category)) internal_function; +#endif + + +/* For those loosing systems which don't have `alloca' we have to add + some additional code emulating it. */ +#ifdef HAVE_ALLOCA +/* Nothing has to be done. */ +# define freea(p) /* nothing */ +# define ADD_BLOCK(list, address) /* nothing */ +# define FREE_BLOCKS(list) /* nothing */ +#else +struct block_list +{ + void *address; + struct block_list *next; +}; +# define ADD_BLOCK(list, addr) \ + do { \ + struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ + /* If we cannot get a free block we cannot add the new element to \ + the list. */ \ + if (newp != NULL) { \ + newp->address = (addr); \ + newp->next = (list); \ + (list) = newp; \ + } \ + } while (0) +# define FREE_BLOCKS(list) \ + do { \ + while (list != NULL) { \ + struct block_list *old = list; \ + list = list->next; \ + free (old->address); \ + free (old); \ + } \ + } while (0) +# undef alloca +# define alloca(size) (malloc (size)) +# define freea(p) free (p) +#endif /* have alloca */ + + +#ifdef _LIBC +/* List of blocks allocated for translations. */ +typedef struct transmem_list +{ + struct transmem_list *next; + char data[ZERO]; +} transmem_block_t; +static struct transmem_list *transmem_list; +#else +typedef unsigned char transmem_block_t; +#endif + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DCIGETTEXT __dcigettext +#else +# define DCIGETTEXT libintl_dcigettext +#endif + +/* Lock variable to protect the global data in the gettext implementation. */ +#ifdef _LIBC +__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden) +#endif + +/* Checking whether the binaries runs SUID must be done and glibc provides + easier methods therefore we make a difference here. */ +#ifdef _LIBC +# define ENABLE_SECURE __libc_enable_secure +# define DETERMINE_SECURE +#else +# ifndef HAVE_GETUID +# define getuid() 0 +# endif +# ifndef HAVE_GETGID +# define getgid() 0 +# endif +# ifndef HAVE_GETEUID +# define geteuid() getuid() +# endif +# ifndef HAVE_GETEGID +# define getegid() getgid() +# endif +static int enable_secure; +# define ENABLE_SECURE (enable_secure == 1) +# define DETERMINE_SECURE \ + if (enable_secure == 0) \ + { \ + if (getuid () != geteuid () || getgid () != getegid ()) \ + enable_secure = 1; \ + else \ + enable_secure = -1; \ + } +#endif + +/* Get the function to evaluate the plural expression. */ +#include "eval-plural.h" + +/* Look up MSGID in the DOMAINNAME message catalog for the current + CATEGORY locale and, if PLURAL is nonzero, search over string + depending on the plural form determined by N. */ +char * +DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) + const char *domainname; + const char *msgid1; + const char *msgid2; + int plural; + unsigned long int n; + int category; +{ +#ifndef HAVE_ALLOCA + struct block_list *block_list = NULL; +#endif + struct loaded_l10nfile *domain; + struct binding *binding; + const char *categoryname; + const char *categoryvalue; + char *dirname, *xdomainname; + char *single_locale; + char *retval; + size_t retlen; + int saved_errno; +#if defined HAVE_TSEARCH || defined _LIBC + struct known_translation_t *search; + struct known_translation_t **foundp = NULL; + size_t msgid_len; +#endif + size_t domainname_len; + + /* If no real MSGID is given return NULL. */ + if (msgid1 == NULL) + return NULL; + +#ifdef _LIBC + if (category < 0 || category >= __LC_LAST || category == LC_ALL) + /* Bogus. */ + return (plural == 0 + ? (char *) msgid1 + /* Use the Germanic plural rule. */ + : n == 1 ? (char *) msgid1 : (char *) msgid2); +#endif + + __libc_rwlock_rdlock (_nl_state_lock); + + /* If DOMAINNAME is NULL, we are interested in the default domain. If + CATEGORY is not LC_MESSAGES this might not make much sense but the + definition left this undefined. */ + if (domainname == NULL) + domainname = _nl_current_default_domain; + + /* OS/2 specific: backward compatibility with older libintl versions */ +#ifdef LC_MESSAGES_COMPAT + if (category == LC_MESSAGES_COMPAT) + category = LC_MESSAGES; +#endif + +#if defined HAVE_TSEARCH || defined _LIBC + msgid_len = strlen (msgid1) + 1; + + /* Try to find the translation among those which we found at + some time. */ + search = (struct known_translation_t *) + alloca (offsetof (struct known_translation_t, msgid) + msgid_len); + memcpy (search->msgid, msgid1, msgid_len); + search->domainname = (char *) domainname; + search->category = category; + + foundp = (struct known_translation_t **) tfind (search, &root, transcmp); + freea (search); + if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) + { + /* Now deal with plural. */ + if (plural) + retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, + (*foundp)->translation_length); + else + retval = (char *) (*foundp)->translation; + + __libc_rwlock_unlock (_nl_state_lock); + return retval; + } +#endif + + /* Preserve the `errno' value. */ + saved_errno = errno; + + /* See whether this is a SUID binary or not. */ + DETERMINE_SECURE; + + /* First find matching binding. */ + for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) + { + int compare = strcmp (domainname, binding->domainname); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It is not in the list. */ + binding = NULL; + break; + } + } + + if (binding == NULL) + dirname = (char *) INTUSE(_nl_default_dirname); + else if (IS_ABSOLUTE_PATH (binding->dirname)) + dirname = binding->dirname; + else + { + /* We have a relative path. Make it absolute now. */ + size_t dirname_len = strlen (binding->dirname) + 1; + size_t path_max; + char *ret; + + path_max = (unsigned int) PATH_MAX; + path_max += 2; /* The getcwd docs say to do this. */ + + for (;;) + { + dirname = (char *) alloca (path_max + dirname_len); + ADD_BLOCK (block_list, dirname); + + __set_errno (0); + ret = getcwd (dirname, path_max); + if (ret != NULL || errno != ERANGE) + break; + + path_max += path_max / 2; + path_max += PATH_INCR; + } + + if (ret == NULL) + /* We cannot get the current working directory. Don't signal an + error but simply return the default string. */ + goto return_untranslated; + + stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); + } + + /* Now determine the symbolic name of CATEGORY and its value. */ + categoryname = category_to_name (category); + categoryvalue = guess_category_value (category, categoryname); + + domainname_len = strlen (domainname); + xdomainname = (char *) alloca (strlen (categoryname) + + domainname_len + 5); + ADD_BLOCK (block_list, xdomainname); + + stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), + domainname, domainname_len), + ".mo"); + + /* Creating working area. */ + single_locale = (char *) alloca (strlen (categoryvalue) + 1); + ADD_BLOCK (block_list, single_locale); + + + /* Search for the given string. This is a loop because we perhaps + got an ordered list of languages to consider for the translation. */ + while (1) + { + /* Make CATEGORYVALUE point to the next element of the list. */ + while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') + ++categoryvalue; + if (categoryvalue[0] == '\0') + { + /* The whole contents of CATEGORYVALUE has been searched but + no valid entry has been found. We solve this situation + by implicitly appending a "C" entry, i.e. no translation + will take place. */ + single_locale[0] = 'C'; + single_locale[1] = '\0'; + } + else + { + char *cp = single_locale; + while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') + *cp++ = *categoryvalue++; + *cp = '\0'; + + /* When this is a SUID binary we must not allow accessing files + outside the dedicated directories. */ + if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) + /* Ingore this entry. */ + continue; + } + + /* If the current locale value is C (or POSIX) we don't load a + domain. Return the MSGID. */ + if (strcmp (single_locale, "C") == 0 + || strcmp (single_locale, "POSIX") == 0) + break; + + /* Find structure describing the message catalog matching the + DOMAINNAME and CATEGORY. */ + domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); + + if (domain != NULL) + { + retval = _nl_find_msg (domain, binding, msgid1, &retlen); + + if (retval == NULL) + { + int cnt; + + for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) + { + retval = _nl_find_msg (domain->successor[cnt], binding, + msgid1, &retlen); + + if (retval != NULL) + { + domain = domain->successor[cnt]; + break; + } + } + } + + if (retval != NULL) + { + /* Found the translation of MSGID1 in domain DOMAIN: + starting at RETVAL, RETLEN bytes. */ + FREE_BLOCKS (block_list); +#if defined HAVE_TSEARCH || defined _LIBC + if (foundp == NULL) + { + /* Create a new entry and add it to the search tree. */ + struct known_translation_t *newp; + + newp = (struct known_translation_t *) + malloc (offsetof (struct known_translation_t, msgid) + + msgid_len + domainname_len + 1); + if (newp != NULL) + { + newp->domainname = + mempcpy (newp->msgid, msgid1, msgid_len); + memcpy (newp->domainname, domainname, domainname_len + 1); + newp->category = category; + newp->counter = _nl_msg_cat_cntr; + newp->domain = domain; + newp->translation = retval; + newp->translation_length = retlen; + + /* Insert the entry in the search tree. */ + foundp = (struct known_translation_t **) + tsearch (newp, &root, transcmp); + if (foundp == NULL + || __builtin_expect (*foundp != newp, 0)) + /* The insert failed. */ + free (newp); + } + } + else + { + /* We can update the existing entry. */ + (*foundp)->counter = _nl_msg_cat_cntr; + (*foundp)->domain = domain; + (*foundp)->translation = retval; + (*foundp)->translation_length = retlen; + } +#endif + __set_errno (saved_errno); + + /* Now deal with plural. */ + if (plural) + retval = plural_lookup (domain, n, retval, retlen); + + __libc_rwlock_unlock (_nl_state_lock); + return retval; + } + } + } + + return_untranslated: + /* Return the untranslated MSGID. */ + FREE_BLOCKS (block_list); + __libc_rwlock_unlock (_nl_state_lock); +#ifndef _LIBC + if (!ENABLE_SECURE) + { + extern void _nl_log_untranslated PARAMS ((const char *logfilename, + const char *domainname, + const char *msgid1, + const char *msgid2, + int plural)); + const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED"); + + if (logfilename != NULL && logfilename[0] != '\0') + _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural); + } +#endif + __set_errno (saved_errno); + return (plural == 0 + ? (char *) msgid1 + /* Use the Germanic plural rule. */ + : n == 1 ? (char *) msgid1 : (char *) msgid2); +} + + +char * +internal_function +_nl_find_msg (domain_file, domainbinding, msgid, lengthp) + struct loaded_l10nfile *domain_file; + struct binding *domainbinding; + const char *msgid; + size_t *lengthp; +{ + struct loaded_domain *domain; + nls_uint32 nstrings; + size_t act; + char *result; + size_t resultlen; + + if (domain_file->decided == 0) + _nl_load_domain (domain_file, domainbinding); + + if (domain_file->data == NULL) + return NULL; + + domain = (struct loaded_domain *) domain_file->data; + + nstrings = domain->nstrings; + + /* Locate the MSGID and its translation. */ + if (domain->hash_tab != NULL) + { + /* Use the hashing table. */ + nls_uint32 len = strlen (msgid); + nls_uint32 hash_val = hash_string (msgid); + nls_uint32 idx = hash_val % domain->hash_size; + nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); + + while (1) + { + nls_uint32 nstr = + W (domain->must_swap_hash_tab, domain->hash_tab[idx]); + + if (nstr == 0) + /* Hash table entry is empty. */ + return NULL; + + nstr--; + + /* Compare msgid with the original string at index nstr. + We compare the lengths with >=, not ==, because plural entries + are represented by strings with an embedded NUL. */ + if (nstr < nstrings + ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len + && (strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr].offset)) + == 0) + : domain->orig_sysdep_tab[nstr - nstrings].length > len + && (strcmp (msgid, + domain->orig_sysdep_tab[nstr - nstrings].pointer) + == 0)) + { + act = nstr; + goto found; + } + + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + } + /* NOTREACHED */ + } + else + { + /* Try the default method: binary search in the sorted array of + messages. */ + size_t top, bottom; + + bottom = 0; + top = nstrings; + while (bottom < top) + { + int cmp_val; + + act = (bottom + top) / 2; + cmp_val = strcmp (msgid, (domain->data + + W (domain->must_swap, + domain->orig_tab[act].offset))); + if (cmp_val < 0) + top = act; + else if (cmp_val > 0) + bottom = act + 1; + else + goto found; + } + /* No translation was found. */ + return NULL; + } + + found: + /* The translation was found at index ACT. If we have to convert the + string to use a different character set, this is the time. */ + if (act < nstrings) + { + result = (char *) + (domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); + resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; + } + else + { + result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer; + resultlen = domain->trans_sysdep_tab[act - nstrings].length; + } + +#if defined _LIBC || HAVE_ICONV + if (domain->codeset_cntr + != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) + { + /* The domain's codeset has changed through bind_textdomain_codeset() + since the message catalog was initialized or last accessed. We + have to reinitialize the converter. */ + _nl_free_domain_conv (domain); + _nl_init_domain_conv (domain_file, domain, domainbinding); + } + + if ( +# ifdef _LIBC + domain->conv != (__gconv_t) -1 +# else +# if HAVE_ICONV + domain->conv != (iconv_t) -1 +# endif +# endif + ) + { + /* We are supposed to do a conversion. First allocate an + appropriate table with the same structure as the table + of translations in the file, where we can put the pointers + to the converted strings in. + There is a slight complication with plural entries. They + are represented by consecutive NUL terminated strings. We + handle this case by converting RESULTLEN bytes, including + NULs. */ + + if (domain->conv_tab == NULL + && ((domain->conv_tab = + (char **) calloc (nstrings + domain->n_sysdep_strings, + sizeof (char *))) + == NULL)) + /* Mark that we didn't succeed allocating a table. */ + domain->conv_tab = (char **) -1; + + if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) + /* Nothing we can do, no more memory. */ + goto converted; + + if (domain->conv_tab[act] == NULL) + { + /* We haven't used this string so far, so it is not + translated yet. Do this now. */ + /* We use a bit more efficient memory handling. + We allocate always larger blocks which get used over + time. This is faster than many small allocations. */ + __libc_lock_define_initialized (static, lock) +# define INITIAL_BLOCK_SIZE 4080 + static unsigned char *freemem; + static size_t freemem_size; + + const unsigned char *inbuf; + unsigned char *outbuf; + int malloc_count; +# ifndef _LIBC + transmem_block_t *transmem_list = NULL; +# endif + + __libc_lock_lock (lock); + + inbuf = (const unsigned char *) result; + outbuf = freemem + sizeof (size_t); + + malloc_count = 0; + while (1) + { + transmem_block_t *newmem; +# ifdef _LIBC + size_t non_reversible; + int res; + + if (freemem_size < sizeof (size_t)) + goto resize_freemem; + + res = __gconv (domain->conv, + &inbuf, inbuf + resultlen, + &outbuf, + outbuf + freemem_size - sizeof (size_t), + &non_reversible); + + if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) + break; + + if (res != __GCONV_FULL_OUTPUT) + { + __libc_lock_unlock (lock); + goto converted; + } + + inbuf = result; +# else +# if HAVE_ICONV + const char *inptr = (const char *) inbuf; + size_t inleft = resultlen; + char *outptr = (char *) outbuf; + size_t outleft; + + if (freemem_size < sizeof (size_t)) + goto resize_freemem; + + outleft = freemem_size - sizeof (size_t); + if (iconv (domain->conv, + (ICONV_CONST char **) &inptr, &inleft, + &outptr, &outleft) + != (size_t) (-1)) + { + outbuf = (unsigned char *) outptr; + break; + } + if (errno != E2BIG) + { + __libc_lock_unlock (lock); + goto converted; + } +# endif +# endif + + resize_freemem: + /* We must allocate a new buffer or resize the old one. */ + if (malloc_count > 0) + { + ++malloc_count; + freemem_size = malloc_count * INITIAL_BLOCK_SIZE; + newmem = (transmem_block_t *) realloc (transmem_list, + freemem_size); +# ifdef _LIBC + if (newmem != NULL) + transmem_list = transmem_list->next; + else + { + struct transmem_list *old = transmem_list; + + transmem_list = transmem_list->next; + free (old); + } +# endif + } + else + { + malloc_count = 1; + freemem_size = INITIAL_BLOCK_SIZE; + newmem = (transmem_block_t *) malloc (freemem_size); + } + if (__builtin_expect (newmem == NULL, 0)) + { + freemem = NULL; + freemem_size = 0; + __libc_lock_unlock (lock); + goto converted; + } + +# ifdef _LIBC + /* Add the block to the list of blocks we have to free + at some point. */ + newmem->next = transmem_list; + transmem_list = newmem; + + freemem = newmem->data; + freemem_size -= offsetof (struct transmem_list, data); +# else + transmem_list = newmem; + freemem = newmem; +# endif + + outbuf = freemem + sizeof (size_t); + } + + /* We have now in our buffer a converted string. Put this + into the table of conversions. */ + *(size_t *) freemem = outbuf - freemem - sizeof (size_t); + domain->conv_tab[act] = (char *) freemem; + /* Shrink freemem, but keep it aligned. */ + freemem_size -= outbuf - freemem; + freemem = outbuf; + freemem += freemem_size & (alignof (size_t) - 1); + freemem_size = freemem_size & ~ (alignof (size_t) - 1); + + __libc_lock_unlock (lock); + } + + /* Now domain->conv_tab[act] contains the translation of all + the plural variants. */ + result = domain->conv_tab[act] + sizeof (size_t); + resultlen = *(size_t *) domain->conv_tab[act]; + } + + converted: + /* The result string is converted. */ + +#endif /* _LIBC || HAVE_ICONV */ + + *lengthp = resultlen; + return result; +} + + +/* Look up a plural variant. */ +static char * +internal_function +plural_lookup (domain, n, translation, translation_len) + struct loaded_l10nfile *domain; + unsigned long int n; + const char *translation; + size_t translation_len; +{ + struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; + unsigned long int index; + const char *p; + + index = plural_eval (domaindata->plural, n); + if (index >= domaindata->nplurals) + /* This should never happen. It means the plural expression and the + given maximum value do not match. */ + index = 0; + + /* Skip INDEX strings at TRANSLATION. */ + p = translation; + while (index-- > 0) + { +#ifdef _LIBC + p = __rawmemchr (p, '\0'); +#else + p = strchr (p, '\0'); +#endif + /* And skip over the NUL byte. */ + p++; + + if (p >= translation + translation_len) + /* This should never happen. It means the plural expression + evaluated to a value larger than the number of variants + available for MSGID1. */ + return (char *) translation; + } + return (char *) p; +} + +#ifndef _LIBC +/* Return string representation of locale CATEGORY. */ +static const char * +internal_function +category_to_name (category) + int category; +{ + const char *retval; + + switch (category) + { +#ifdef LC_COLLATE + case LC_COLLATE: + retval = "LC_COLLATE"; + break; +#endif +#ifdef LC_CTYPE + case LC_CTYPE: + retval = "LC_CTYPE"; + break; +#endif +#ifdef LC_MONETARY + case LC_MONETARY: + retval = "LC_MONETARY"; + break; +#endif +#ifdef LC_NUMERIC + case LC_NUMERIC: + retval = "LC_NUMERIC"; + break; +#endif +#ifdef LC_TIME + case LC_TIME: + retval = "LC_TIME"; + break; +#endif +#ifdef LC_MESSAGES + case LC_MESSAGES: + retval = "LC_MESSAGES"; + break; +#endif +#ifdef LC_RESPONSE + case LC_RESPONSE: + retval = "LC_RESPONSE"; + break; +#endif +#ifdef LC_ALL + case LC_ALL: + /* This might not make sense but is perhaps better than any other + value. */ + retval = "LC_ALL"; + break; +#endif + default: + /* If you have a better idea for a default value let me know. */ + retval = "LC_XXX"; + } + + return retval; +} +#endif + +/* Guess value of current locale from value of the environment variables. */ +static const char * +internal_function +guess_category_value (category, categoryname) + int category; + const char *categoryname; +{ + const char *language; + const char *retval; + + /* The highest priority value is the `LANGUAGE' environment + variable. But we don't use the value if the currently selected + locale is the C locale. This is a GNU extension. */ + language = getenv ("LANGUAGE"); + if (language != NULL && language[0] == '\0') + language = NULL; + + /* We have to proceed with the POSIX methods of looking to `LC_ALL', + `LC_xxx', and `LANG'. On some systems this can be done by the + `setlocale' function itself. */ +#ifdef _LIBC + retval = __current_locale_name (category); +#else + retval = _nl_locale_name (category, categoryname); +#endif + + /* Ignore LANGUAGE if the locale is set to "C" because + 1. "C" locale usually uses the ASCII encoding, and most international + messages use non-ASCII characters. These characters get displayed + as question marks (if using glibc's iconv()) or as invalid 8-bit + characters (because other iconv()s refuse to convert most non-ASCII + characters to ASCII). In any case, the output is ugly. + 2. The precise output of some programs in the "C" locale is specified + by POSIX and should not depend on environment variables like + "LANGUAGE". We allow such programs to use gettext(). */ + return language != NULL && strcmp (retval, "C") != 0 ? language : retval; +} + +/* @@ begin of epilog @@ */ + +/* We don't want libintl.a to depend on any other library. So we + avoid the non-standard function stpcpy. In GNU C Library this + function is available, though. Also allow the symbol HAVE_STPCPY + to be defined. */ +#if !_LIBC && !HAVE_STPCPY +static char * +stpcpy (dest, src) + char *dest; + const char *src; +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif + +#if !_LIBC && !HAVE_MEMPCPY +static void * +mempcpy (dest, src, n) + void *dest; + const void *src; + size_t n; +{ + return (void *) ((char *) memcpy (dest, src, n) + n); +} +#endif + + +#ifdef _LIBC +/* If we want to free all resources we have to do some work at + program's end. */ +libc_freeres_fn (free_mem) +{ + void *old; + + while (_nl_domain_bindings != NULL) + { + struct binding *oldp = _nl_domain_bindings; + _nl_domain_bindings = _nl_domain_bindings->next; + if (oldp->dirname != INTUSE(_nl_default_dirname)) + /* Yes, this is a pointer comparison. */ + free (oldp->dirname); + free (oldp->codeset); + free (oldp); + } + + if (_nl_current_default_domain != _nl_default_default_domain) + /* Yes, again a pointer comparison. */ + free ((char *) _nl_current_default_domain); + + /* Remove the search tree with the known translations. */ + __tdestroy (root, free); + root = NULL; + + while (transmem_list != NULL) + { + old = transmem_list; + transmem_list = transmem_list->next; + free (old); + } +} +#endif diff --git a/intl/dcngettext.c b/intl/dcngettext.c new file mode 100644 index 000000000..3a3404e2c --- /dev/null +++ b/intl/dcngettext.c @@ -0,0 +1,60 @@ +/* Implementation of the dcngettext(3) function. + Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DCNGETTEXT __dcngettext +# define DCIGETTEXT __dcigettext +#else +# define DCNGETTEXT libintl_dcngettext +# define DCIGETTEXT libintl_dcigettext +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +char * +DCNGETTEXT (domainname, msgid1, msgid2, n, category) + const char *domainname; + const char *msgid1; + const char *msgid2; + unsigned long int n; + int category; +{ + return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__dcngettext, dcngettext); +#endif diff --git a/intl/dgettext.c b/intl/dgettext.c new file mode 100644 index 000000000..cf5b4037f --- /dev/null +++ b/intl/dgettext.c @@ -0,0 +1,59 @@ +/* Implementation of the dgettext(3) function. + Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <locale.h> + +#include "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DGETTEXT __dgettext +# define DCGETTEXT INTUSE(__dcgettext) +#else +# define DGETTEXT libintl_dgettext +# define DCGETTEXT libintl_dcgettext +#endif + +/* Look up MSGID in the DOMAINNAME message catalog of the current + LC_MESSAGES locale. */ +char * +DGETTEXT (domainname, msgid) + const char *domainname; + const char *msgid; +{ + return DCGETTEXT (domainname, msgid, LC_MESSAGES); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__dgettext, dgettext); +#endif diff --git a/intl/dngettext.c b/intl/dngettext.c new file mode 100644 index 000000000..67fd030f2 --- /dev/null +++ b/intl/dngettext.c @@ -0,0 +1,61 @@ +/* Implementation of the dngettext(3) function. + Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <locale.h> + +#include "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DNGETTEXT __dngettext +# define DCNGETTEXT __dcngettext +#else +# define DNGETTEXT libintl_dngettext +# define DCNGETTEXT libintl_dcngettext +#endif + +/* Look up MSGID in the DOMAINNAME message catalog of the current + LC_MESSAGES locale and skip message according to the plural form. */ +char * +DNGETTEXT (domainname, msgid1, msgid2, n) + const char *domainname; + const char *msgid1; + const char *msgid2; + unsigned long int n; +{ + return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__dngettext, dngettext); +#endif diff --git a/intl/eval-plural.h b/intl/eval-plural.h new file mode 100644 index 000000000..19c7ca6ae --- /dev/null +++ b/intl/eval-plural.h @@ -0,0 +1,114 @@ +/* Plural expression evaluation. + Copyright (C) 2000-2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 STATIC +#define STATIC static +#endif + +/* Evaluate the plural expression and return an index value. */ +STATIC unsigned long int plural_eval PARAMS ((struct expression *pexp, + unsigned long int n)) + internal_function; + +STATIC +unsigned long int +internal_function +plural_eval (pexp, n) + struct expression *pexp; + unsigned long int n; +{ + switch (pexp->nargs) + { + case 0: + switch (pexp->operation) + { + case var: + return n; + case num: + return pexp->val.num; + default: + break; + } + /* NOTREACHED */ + break; + case 1: + { + /* pexp->operation must be lnot. */ + unsigned long int arg = plural_eval (pexp->val.args[0], n); + return ! arg; + } + case 2: + { + unsigned long int leftarg = plural_eval (pexp->val.args[0], n); + if (pexp->operation == lor) + return leftarg || plural_eval (pexp->val.args[1], n); + else if (pexp->operation == land) + return leftarg && plural_eval (pexp->val.args[1], n); + else + { + unsigned long int rightarg = plural_eval (pexp->val.args[1], n); + + switch (pexp->operation) + { + case mult: + return leftarg * rightarg; + case divide: +#if !INTDIV0_RAISES_SIGFPE + if (rightarg == 0) + raise (SIGFPE); +#endif + return leftarg / rightarg; + case module: +#if !INTDIV0_RAISES_SIGFPE + if (rightarg == 0) + raise (SIGFPE); +#endif + return leftarg % rightarg; + case plus: + return leftarg + rightarg; + case minus: + return leftarg - rightarg; + case less_than: + return leftarg < rightarg; + case greater_than: + return leftarg > rightarg; + case less_or_equal: + return leftarg <= rightarg; + case greater_or_equal: + return leftarg >= rightarg; + case equal: + return leftarg == rightarg; + case not_equal: + return leftarg != rightarg; + default: + break; + } + } + /* NOTREACHED */ + break; + } + case 3: + { + /* pexp->operation must be qmop. */ + unsigned long int boolarg = plural_eval (pexp->val.args[0], n); + return plural_eval (pexp->val.args[boolarg ? 1 : 2], n); + } + } + /* NOTREACHED */ + return 0; +} diff --git a/intl/finddomain.c b/intl/finddomain.c new file mode 100644 index 000000000..d24276442 --- /dev/null +++ b/intl/finddomain.c @@ -0,0 +1,195 @@ +/* Handle list of needed message catalogs + Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. + Written by Ulrich Drepper <drepper@gnu.org>, 1995. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> + +#if defined HAVE_UNISTD_H || defined _LIBC +# include <unistd.h> +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +/* @@ end of prolog @@ */ +/* List of already loaded domains. */ +static struct loaded_l10nfile *_nl_loaded_domains; + + +/* Return a data structure describing the message catalog described by + the DOMAINNAME and CATEGORY parameters with respect to the currently + established bindings. */ +struct loaded_l10nfile * +internal_function +_nl_find_domain (dirname, locale, domainname, domainbinding) + const char *dirname; + char *locale; + const char *domainname; + struct binding *domainbinding; +{ + struct loaded_l10nfile *retval; + const char *language; + const char *modifier; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *special; + const char *sponsor; + const char *revision; + const char *alias_value; + int mask; + + /* LOCALE can consist of up to four recognized parts for the XPG syntax: + + language[_territory[.codeset]][@modifier] + + and six parts for the CEN syntax: + + language[_territory][+audience][+special][,[sponsor][_revision]] + + Beside the first part all of them are allowed to be missing. If + the full specified locale is not found, the less specific one are + looked for. The various parts will be stripped off according to + the following order: + (1) revision + (2) sponsor + (3) special + (4) codeset + (5) normalized codeset + (6) territory + (7) audience/modifier + */ + + /* If we have already tested for this locale entry there has to + be one data set in the list of loaded domains. */ + retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, + strlen (dirname) + 1, 0, locale, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, domainname, 0); + if (retval != NULL) + { + /* We know something about this locale. */ + int cnt; + + if (retval->decided == 0) + _nl_load_domain (retval, domainbinding); + + if (retval->data != NULL) + return retval; + + for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) + { + if (retval->successor[cnt]->decided == 0) + _nl_load_domain (retval->successor[cnt], domainbinding); + + if (retval->successor[cnt]->data != NULL) + break; + } + return cnt >= 0 ? retval : NULL; + /* NOTREACHED */ + } + + /* See whether the locale value is an alias. If yes its value + *overwrites* the alias name. No test for the original value is + done. */ + alias_value = _nl_expand_alias (locale); + if (alias_value != NULL) + { +#if defined _LIBC || defined HAVE_STRDUP + locale = strdup (alias_value); + if (locale == NULL) + return NULL; +#else + size_t len = strlen (alias_value) + 1; + locale = (char *) malloc (len); + if (locale == NULL) + return NULL; + + memcpy (locale, alias_value, len); +#endif + } + + /* Now we determine the single parts of the locale name. First + look for the language. Termination symbols are `_' and `@' if + we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ + mask = _nl_explode_name (locale, &language, &modifier, &territory, + &codeset, &normalized_codeset, &special, + &sponsor, &revision); + + /* Create all possible locale entries which might be interested in + generalization. */ + retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, + strlen (dirname) + 1, mask, language, territory, + codeset, normalized_codeset, modifier, special, + sponsor, revision, domainname, 1); + if (retval == NULL) + /* This means we are out of core. */ + return NULL; + + if (retval->decided == 0) + _nl_load_domain (retval, domainbinding); + if (retval->data == NULL) + { + int cnt; + for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) + { + if (retval->successor[cnt]->decided == 0) + _nl_load_domain (retval->successor[cnt], domainbinding); + if (retval->successor[cnt]->data != NULL) + break; + } + } + + /* The room for an alias was dynamically allocated. Free it now. */ + if (alias_value != NULL) + free (locale); + + /* The space for normalized_codeset is dynamically allocated. Free it. */ + if (mask & XPG_NORM_CODESET) + free ((void *) normalized_codeset); + + return retval; +} + + +#ifdef _LIBC +libc_freeres_fn (free_mem) +{ + struct loaded_l10nfile *runp = _nl_loaded_domains; + + while (runp != NULL) + { + struct loaded_l10nfile *here = runp; + if (runp->data != NULL) + _nl_unload_domain ((struct loaded_domain *) runp->data); + runp = runp->next; + free ((char *) here->filename); + free (here); + } +} +#endif diff --git a/intl/gettext.c b/intl/gettext.c new file mode 100644 index 000000000..43d689f55 --- /dev/null +++ b/intl/gettext.c @@ -0,0 +1,64 @@ +/* Implementation of gettext(3) function. + Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 + +#ifdef _LIBC +# define __need_NULL +# include <stddef.h> +#else +# include <stdlib.h> /* Just for NULL. */ +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define GETTEXT __gettext +# define DCGETTEXT INTUSE(__dcgettext) +#else +# define GETTEXT libintl_gettext +# define DCGETTEXT libintl_dcgettext +#endif + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +char * +GETTEXT (msgid) + const char *msgid; +{ + return DCGETTEXT (NULL, msgid, LC_MESSAGES); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__gettext, gettext); +#endif diff --git a/intl/gettextP.h b/intl/gettextP.h new file mode 100644 index 000000000..f1748a356 --- /dev/null +++ b/intl/gettextP.h @@ -0,0 +1,224 @@ +/* Header describing internals of libintl library. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. + Written by Ulrich Drepper <drepper@cygnus.com>, 1995. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _GETTEXTP_H +#define _GETTEXTP_H + +#include <stddef.h> /* Get size_t. */ + +#ifdef _LIBC +# include "../iconv/gconv_int.h" +#else +# if HAVE_ICONV +# include <iconv.h> +# endif +#endif + +#include "loadinfo.h" + +#include "gmo.h" /* Get nls_uint32. */ + +/* @@ end of prolog @@ */ + +#ifndef PARAMS +# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +#endif + +#ifndef internal_function +# define internal_function +#endif + +#ifndef attribute_hidden +# define attribute_hidden +#endif + +/* Tell the compiler when a conditional or integer expression is + almost always true or almost always false. */ +#ifndef HAVE_BUILTIN_EXPECT +# define __builtin_expect(expr, val) (expr) +#endif + +#ifndef W +# define W(flag, data) ((flag) ? SWAP (data) : (data)) +#endif + + +#ifdef _LIBC +# include <byteswap.h> +# define SWAP(i) bswap_32 (i) +#else +static inline nls_uint32 +SWAP (i) + nls_uint32 i; +{ + return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); +} +#endif + + +/* In-memory representation of system dependent string. */ +struct sysdep_string_desc +{ + /* Length of addressed string, including the trailing NUL. */ + size_t length; + /* Pointer to addressed string. */ + const char *pointer; +}; + +/* The representation of an opened message catalog. */ +struct loaded_domain +{ + /* Pointer to memory containing the .mo file. */ + const char *data; + /* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed. */ + int use_mmap; + /* Size of mmap()ed memory. */ + size_t mmap_size; + /* 1 if the .mo file uses a different endianness than this machine. */ + int must_swap; + /* Pointer to additional malloc()ed memory. */ + void *malloced; + + /* Number of static strings pairs. */ + nls_uint32 nstrings; + /* Pointer to descriptors of original strings in the file. */ + const struct string_desc *orig_tab; + /* Pointer to descriptors of translated strings in the file. */ + const struct string_desc *trans_tab; + + /* Number of system dependent strings pairs. */ + nls_uint32 n_sysdep_strings; + /* Pointer to descriptors of original sysdep strings. */ + const struct sysdep_string_desc *orig_sysdep_tab; + /* Pointer to descriptors of translated sysdep strings. */ + const struct sysdep_string_desc *trans_sysdep_tab; + + /* Size of hash table. */ + nls_uint32 hash_size; + /* Pointer to hash table. */ + const nls_uint32 *hash_tab; + /* 1 if the hash table uses a different endianness than this machine. */ + int must_swap_hash_tab; + + int codeset_cntr; +#ifdef _LIBC + __gconv_t conv; +#else +# if HAVE_ICONV + iconv_t conv; +# endif +#endif + char **conv_tab; + + struct expression *plural; + unsigned long int nplurals; +}; + +/* We want to allocate a string at the end of the struct. But ISO C + doesn't allow zero sized arrays. */ +#ifdef __GNUC__ +# define ZERO 0 +#else +# define ZERO 1 +#endif + +/* A set of settings bound to a message domain. Used to store settings + from bindtextdomain() and bind_textdomain_codeset(). */ +struct binding +{ + struct binding *next; + char *dirname; + int codeset_cntr; /* Incremented each time codeset changes. */ + char *codeset; + char domainname[ZERO]; +}; + +/* A counter which is incremented each time some previous translations + become invalid. + This variable is part of the external ABI of the GNU libintl. */ +extern int _nl_msg_cat_cntr; + +#ifndef _LIBC +const char *_nl_locale_name PARAMS ((int category, const char *categoryname)); +#endif + +struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, + char *__locale, + const char *__domainname, + struct binding *__domainbinding)) + internal_function; +void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain, + struct binding *__domainbinding)) + internal_function; +void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) + internal_function; +const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file, + struct loaded_domain *__domain, + struct binding *__domainbinding)) + internal_function; +void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain)) + internal_function; + +char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file, + struct binding *domainbinding, + const char *msgid, size_t *lengthp)) + internal_function; + +#ifdef _LIBC +extern char *__gettext PARAMS ((const char *__msgid)); +extern char *__dgettext PARAMS ((const char *__domainname, + const char *__msgid)); +extern char *__dcgettext PARAMS ((const char *__domainname, + const char *__msgid, int __category)); +extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2, + unsigned long int __n)); +extern char *__dngettext PARAMS ((const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int n)); +extern char *__dcngettext PARAMS ((const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category)); +extern char *__dcigettext PARAMS ((const char *__domainname, + const char *__msgid1, const char *__msgid2, + int __plural, unsigned long int __n, + int __category)); +extern char *__textdomain PARAMS ((const char *__domainname)); +extern char *__bindtextdomain PARAMS ((const char *__domainname, + const char *__dirname)); +extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname, + const char *__codeset)); +#else +/* Declare the exported libintl_* functions, in a way that allows us to + call them under their real name. */ +# define _INTL_REDIRECT_MACROS +# include "libgnuintl.h" +extern char *libintl_dcigettext PARAMS ((const char *__domainname, + const char *__msgid1, + const char *__msgid2, + int __plural, unsigned long int __n, + int __category)); +#endif + +/* @@ begin of epilog @@ */ + +#endif /* gettextP.h */ diff --git a/intl/gmo.h b/intl/gmo.h new file mode 100644 index 000000000..d1fe4d6b8 --- /dev/null +++ b/intl/gmo.h @@ -0,0 +1,148 @@ +/* Description of GNU message catalog format: general file layout. + Copyright (C) 1995, 1997, 2000-2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _GETTEXT_H +#define _GETTEXT_H 1 + +#include <limits.h> + +/* @@ end of prolog @@ */ + +/* The magic number of the GNU message catalog format. */ +#define _MAGIC 0x950412de +#define _MAGIC_SWAPPED 0xde120495 + +/* Revision number of the currently used .mo (binary) file format. */ +#define MO_REVISION_NUMBER 0 + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work + when cross-compiling. */ + +#if __STDC__ +# define UINT_MAX_32_BITS 4294967295U +#else +# define UINT_MAX_32_BITS 0xFFFFFFFF +#endif + +/* If UINT_MAX isn't defined, assume it's a 32-bit type. + This should be valid for all systems GNU cares about because + that doesn't include 16-bit systems, and only modern systems + (that certainly have <limits.h>) have 64+-bit integral types. */ + +#ifndef UINT_MAX +# define UINT_MAX UINT_MAX_32_BITS +#endif + +#if UINT_MAX == UINT_MAX_32_BITS +typedef unsigned nls_uint32; +#else +# if USHRT_MAX == UINT_MAX_32_BITS +typedef unsigned short nls_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS +typedef unsigned long nls_uint32; +# else + /* The following line is intended to throw an error. Using #error is + not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +#endif + + +/* Header for binary .mo file format. */ +struct mo_file_header +{ + /* The magic number. */ + nls_uint32 magic; + /* The revision number of the file format. */ + nls_uint32 revision; + + /* The following are only used in .mo files with major revision 0. */ + + /* The number of strings pairs. */ + nls_uint32 nstrings; + /* Offset of table with start offsets of original strings. */ + nls_uint32 orig_tab_offset; + /* Offset of table with start offsets of translated strings. */ + nls_uint32 trans_tab_offset; + /* Size of hash table. */ + nls_uint32 hash_tab_size; + /* Offset of first hash table entry. */ + nls_uint32 hash_tab_offset; + + /* The following are only used in .mo files with minor revision >= 1. */ + + /* The number of system dependent segments. */ + nls_uint32 n_sysdep_segments; + /* Offset of table describing system dependent segments. */ + nls_uint32 sysdep_segments_offset; + /* The number of system dependent strings pairs. */ + nls_uint32 n_sysdep_strings; + /* Offset of table with start offsets of original sysdep strings. */ + nls_uint32 orig_sysdep_tab_offset; + /* Offset of table with start offsets of translated sysdep strings. */ + nls_uint32 trans_sysdep_tab_offset; +}; + +/* Descriptor for static string contained in the binary .mo file. */ +struct string_desc +{ + /* Length of addressed string, not including the trailing NUL. */ + nls_uint32 length; + /* Offset of string in file. */ + nls_uint32 offset; +}; + +/* The following are only used in .mo files with minor revision >= 1. */ + +/* Descriptor for system dependent string segment. */ +struct sysdep_segment +{ + /* Length of addressed string, including the trailing NUL. */ + nls_uint32 length; + /* Offset of string in file. */ + nls_uint32 offset; +}; + +/* Descriptor for system dependent string. */ +struct sysdep_string +{ + /* Offset of static string segments in file. */ + nls_uint32 offset; + /* Alternating sequence of static and system dependent segments. + The last segment is a static segment, including the trailing NUL. */ + struct segment_pair + { + /* Size of static segment. */ + nls_uint32 segsize; + /* Reference to system dependent string segment, or ~0 at the end. */ + nls_uint32 sysdepref; + } segments[1]; +}; + +/* Marker for the end of the segments[] array. This has the value 0xFFFFFFFF, + regardless whether 'int' is 16 bit, 32 bit, or 64 bit. */ +#define SEGMENTS_END ((nls_uint32) ~0) + +/* @@ begin of epilog @@ */ + +#endif /* gettext.h */ diff --git a/intl/hash-string.h b/intl/hash-string.h new file mode 100644 index 000000000..b267a8778 --- /dev/null +++ b/intl/hash-string.h @@ -0,0 +1,59 @@ +/* Description of GNU message catalog format: string hashing function. + Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 of prolog @@ */ + +#ifndef PARAMS +# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +#endif + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + + +/* Defines the so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ +static unsigned long int hash_string PARAMS ((const char *__str_param)); + +static inline unsigned long int +hash_string (str_param) + const char *str_param; +{ + unsigned long int hval, g; + const char *str = str_param; + + /* Compute the hash value for the given string. */ + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} diff --git a/intl/intl-compat.c b/intl/intl-compat.c new file mode 100644 index 000000000..36b7af0f8 --- /dev/null +++ b/intl/intl-compat.c @@ -0,0 +1,151 @@ +/* intl-compat.c - Stub functions to call gettext functions from GNU gettext + Library. + Copyright (C) 1995, 2000-2003 Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 "gettextP.h" + +/* @@ end of prolog @@ */ + +/* This file redirects the gettext functions (without prefix) to those + defined in the included GNU libintl library (with "libintl_" prefix). + It is compiled into libintl in order to make the AM_GNU_GETTEXT test + of gettext <= 0.11.2 work with the libintl library >= 0.11.3 which + has the redirections primarily in the <libintl.h> include file. + It is also compiled into libgnuintl so that libgnuintl.so can be used + as LD_PRELOADable library on glibc systems, to provide the extra + features that the functions in the libc don't have (namely, logging). */ + + +#undef gettext +#undef dgettext +#undef dcgettext +#undef ngettext +#undef dngettext +#undef dcngettext +#undef textdomain +#undef bindtextdomain +#undef bind_textdomain_codeset + + +/* When building a DLL, we must export some functions. Note that because + the functions are only defined for binary backward compatibility, we + don't need to use __declspec(dllimport) in any case. */ +#if defined _MSC_VER && BUILDING_DLL +# define DLL_EXPORTED __declspec(dllexport) +#else +# define DLL_EXPORTED +#endif + + +DLL_EXPORTED +char * +gettext (msgid) + const char *msgid; +{ + return libintl_gettext (msgid); +} + + +DLL_EXPORTED +char * +dgettext (domainname, msgid) + const char *domainname; + const char *msgid; +{ + return libintl_dgettext (domainname, msgid); +} + + +DLL_EXPORTED +char * +dcgettext (domainname, msgid, category) + const char *domainname; + const char *msgid; + int category; +{ + return libintl_dcgettext (domainname, msgid, category); +} + + +DLL_EXPORTED +char * +ngettext (msgid1, msgid2, n) + const char *msgid1; + const char *msgid2; + unsigned long int n; +{ + return libintl_ngettext (msgid1, msgid2, n); +} + + +DLL_EXPORTED +char * +dngettext (domainname, msgid1, msgid2, n) + const char *domainname; + const char *msgid1; + const char *msgid2; + unsigned long int n; +{ + return libintl_dngettext (domainname, msgid1, msgid2, n); +} + + +DLL_EXPORTED +char * +dcngettext (domainname, msgid1, msgid2, n, category) + const char *domainname; + const char *msgid1; + const char *msgid2; + unsigned long int n; + int category; +{ + return libintl_dcngettext (domainname, msgid1, msgid2, n, category); +} + + +DLL_EXPORTED +char * +textdomain (domainname) + const char *domainname; +{ + return libintl_textdomain (domainname); +} + + +DLL_EXPORTED +char * +bindtextdomain (domainname, dirname) + const char *domainname; + const char *dirname; +{ + return libintl_bindtextdomain (domainname, dirname); +} + + +DLL_EXPORTED +char * +bind_textdomain_codeset (domainname, codeset) + const char *domainname; + const char *codeset; +{ + return libintl_bind_textdomain_codeset (domainname, codeset); +} diff --git a/intl/l10nflist.c b/intl/l10nflist.c new file mode 100644 index 000000000..ec8713f8e --- /dev/null +++ b/intl/l10nflist.c @@ -0,0 +1,453 @@ +/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Tell glibc's <string.h> to provide a prototype for stpcpy(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> + +#if defined _LIBC || defined HAVE_ARGZ_H +# include <argz.h> +#endif +#include <ctype.h> +#include <sys/types.h> +#include <stdlib.h> + +#include "loadinfo.h" + +/* On some strange systems still no definition of NULL is found. Sigh! */ +#ifndef NULL +# if defined __STDC__ && __STDC__ +# define NULL ((void *) 0) +# else +# define NULL 0 +# endif +#endif + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# ifndef stpcpy +# define stpcpy(dest, src) __stpcpy(dest, src) +# endif +#else +# ifndef HAVE_STPCPY +static char *stpcpy PARAMS ((char *dest, const char *src)); +# endif +#endif + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, + it may be concatenated to a directory pathname. + */ +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) +#endif + +/* Define function which are usually not available. */ + +#if !defined _LIBC && !defined HAVE___ARGZ_COUNT +/* Returns the number of strings in ARGZ. */ +static size_t argz_count__ PARAMS ((const char *argz, size_t len)); + +static size_t +argz_count__ (argz, len) + const char *argz; + size_t len; +{ + size_t count = 0; + while (len > 0) + { + size_t part_len = strlen (argz); + argz += part_len + 1; + len -= part_len + 1; + count++; + } + return count; +} +# undef __argz_count +# define __argz_count(argz, len) argz_count__ (argz, len) +#else +# ifdef _LIBC +# define __argz_count(argz, len) INTUSE(__argz_count) (argz, len) +# endif +#endif /* !_LIBC && !HAVE___ARGZ_COUNT */ + +#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY +/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's + except the last into the character SEP. */ +static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); + +static void +argz_stringify__ (argz, len, sep) + char *argz; + size_t len; + int sep; +{ + while (len > 0) + { + size_t part_len = strlen (argz); + argz += part_len; + len -= part_len + 1; + if (len > 0) + *argz++ = sep; + } +} +# undef __argz_stringify +# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep) +#else +# ifdef _LIBC +# define __argz_stringify(argz, len, sep) \ + INTUSE(__argz_stringify) (argz, len, sep) +# endif +#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ + +#if !defined _LIBC && !defined HAVE___ARGZ_NEXT +static char *argz_next__ PARAMS ((char *argz, size_t argz_len, + const char *entry)); + +static char * +argz_next__ (argz, argz_len, entry) + char *argz; + size_t argz_len; + const char *entry; +{ + if (entry) + { + if (entry < argz + argz_len) + entry = strchr (entry, '\0') + 1; + + return entry >= argz + argz_len ? NULL : (char *) entry; + } + else + if (argz_len > 0) + return argz; + else + return 0; +} +# undef __argz_next +# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry) +#endif /* !_LIBC && !HAVE___ARGZ_NEXT */ + + +/* Return number of bits set in X. */ +static int pop PARAMS ((int x)); + +static inline int +pop (x) + int x; +{ + /* We assume that no more than 16 bits are used. */ + x = ((x & ~0x5555) >> 1) + (x & 0x5555); + x = ((x & ~0x3333) >> 2) + (x & 0x3333); + x = ((x >> 4) + x) & 0x0f0f; + x = ((x >> 8) + x) & 0xff; + + return x; +} + + +struct loaded_l10nfile * +_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, + territory, codeset, normalized_codeset, modifier, special, + sponsor, revision, filename, do_allocate) + struct loaded_l10nfile **l10nfile_list; + const char *dirlist; + size_t dirlist_len; + int mask; + const char *language; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *modifier; + const char *special; + const char *sponsor; + const char *revision; + const char *filename; + int do_allocate; +{ + char *abs_filename; + struct loaded_l10nfile **lastp; + struct loaded_l10nfile *retval; + char *cp; + size_t dirlist_count; + size_t entries; + int cnt; + + /* If LANGUAGE contains an absolute directory specification, we ignore + DIRLIST. */ + if (IS_ABSOLUTE_PATH (language)) + dirlist_len = 0; + + /* Allocate room for the full file name. */ + abs_filename = (char *) malloc (dirlist_len + + strlen (language) + + ((mask & TERRITORY) != 0 + ? strlen (territory) + 1 : 0) + + ((mask & XPG_CODESET) != 0 + ? strlen (codeset) + 1 : 0) + + ((mask & XPG_NORM_CODESET) != 0 + ? strlen (normalized_codeset) + 1 : 0) + + (((mask & XPG_MODIFIER) != 0 + || (mask & CEN_AUDIENCE) != 0) + ? strlen (modifier) + 1 : 0) + + ((mask & CEN_SPECIAL) != 0 + ? strlen (special) + 1 : 0) + + (((mask & CEN_SPONSOR) != 0 + || (mask & CEN_REVISION) != 0) + ? (1 + ((mask & CEN_SPONSOR) != 0 + ? strlen (sponsor) : 0) + + ((mask & CEN_REVISION) != 0 + ? strlen (revision) + 1 : 0)) : 0) + + 1 + strlen (filename) + 1); + + if (abs_filename == NULL) + return NULL; + + /* Construct file name. */ + cp = abs_filename; + if (dirlist_len > 0) + { + memcpy (cp, dirlist, dirlist_len); + __argz_stringify (cp, dirlist_len, PATH_SEPARATOR); + cp += dirlist_len; + cp[-1] = '/'; + } + + cp = stpcpy (cp, language); + + if ((mask & TERRITORY) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, territory); + } + if ((mask & XPG_CODESET) != 0) + { + *cp++ = '.'; + cp = stpcpy (cp, codeset); + } + if ((mask & XPG_NORM_CODESET) != 0) + { + *cp++ = '.'; + cp = stpcpy (cp, normalized_codeset); + } + if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) + { + /* This component can be part of both syntaces but has different + leading characters. For CEN we use `+', else `@'. */ + *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; + cp = stpcpy (cp, modifier); + } + if ((mask & CEN_SPECIAL) != 0) + { + *cp++ = '+'; + cp = stpcpy (cp, special); + } + if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) + { + *cp++ = ','; + if ((mask & CEN_SPONSOR) != 0) + cp = stpcpy (cp, sponsor); + if ((mask & CEN_REVISION) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, revision); + } + } + + *cp++ = '/'; + stpcpy (cp, filename); + + /* Look in list of already loaded domains whether it is already + available. */ + lastp = l10nfile_list; + for (retval = *l10nfile_list; retval != NULL; retval = retval->next) + if (retval->filename != NULL) + { + int compare = strcmp (retval->filename, abs_filename); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It's not in the list. */ + retval = NULL; + break; + } + + lastp = &retval->next; + } + + if (retval != NULL || do_allocate == 0) + { + free (abs_filename); + return retval; + } + + dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1); + + /* Allocate a new loaded_l10nfile. */ + retval = + (struct loaded_l10nfile *) + malloc (sizeof (*retval) + + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0)) + * sizeof (struct loaded_l10nfile *))); + if (retval == NULL) + return NULL; + + retval->filename = abs_filename; + + /* We set retval->data to NULL here; it is filled in later. + Setting retval->decided to 1 here means that retval does not + correspond to a real file (dirlist_count > 1) or is not worth + looking up (if an unnormalized codeset was specified). */ + retval->decided = (dirlist_count > 1 + || ((mask & XPG_CODESET) != 0 + && (mask & XPG_NORM_CODESET) != 0)); + retval->data = NULL; + + retval->next = *lastp; + *lastp = retval; + + entries = 0; + /* Recurse to fill the inheritance list of RETVAL. + If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL + entry does not correspond to a real file; retval->filename contains + colons. In this case we loop across all elements of DIRLIST and + across all bit patterns dominated by MASK. + If the DIRLIST is a single directory or entirely redundant (i.e. + DIRLIST_COUNT == 1), we loop across all bit patterns dominated by + MASK, excluding MASK itself. + In either case, we loop down from MASK to 0. This has the effect + that the extra bits in the locale name are dropped in this order: + first the modifier, then the territory, then the codeset, then the + normalized_codeset. */ + for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt) + if ((cnt & ~mask) == 0 + && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) + && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) + { + if (dirlist_count > 1) + { + /* Iterate over all elements of the DIRLIST. */ + char *dir = NULL; + + while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) + != NULL) + retval->successor[entries++] + = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, + cnt, language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, filename, 1); + } + else + retval->successor[entries++] + = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, + cnt, language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, filename, 1); + } + retval->successor[entries] = NULL; + + return retval; +} + +/* Normalize codeset name. There is no standard for the codeset + names. Normalization allows the user to use any of the common + names. The return value is dynamically allocated and has to be + freed by the caller. */ +const char * +_nl_normalize_codeset (codeset, name_len) + const char *codeset; + size_t name_len; +{ + int len = 0; + int only_digit = 1; + char *retval; + char *wp; + size_t cnt; + + for (cnt = 0; cnt < name_len; ++cnt) + if (isalnum ((unsigned char) codeset[cnt])) + { + ++len; + + if (isalpha ((unsigned char) codeset[cnt])) + only_digit = 0; + } + + retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); + + if (retval != NULL) + { + if (only_digit) + wp = stpcpy (retval, "iso"); + else + wp = retval; + + for (cnt = 0; cnt < name_len; ++cnt) + if (isalpha ((unsigned char) codeset[cnt])) + *wp++ = tolower ((unsigned char) codeset[cnt]); + else if (isdigit ((unsigned char) codeset[cnt])) + *wp++ = codeset[cnt]; + + *wp = '\0'; + } + + return (const char *) retval; +} + + +/* @@ begin of epilog @@ */ + +/* We don't want libintl.a to depend on any other library. So we + avoid the non-standard function stpcpy. In GNU C Library this + function is available, though. Also allow the symbol HAVE_STPCPY + to be defined. */ +#if !_LIBC && !HAVE_STPCPY +static char * +stpcpy (dest, src) + char *dest; + const char *src; +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif diff --git a/intl/libgnuintl.h.in b/intl/libgnuintl.h.in new file mode 100644 index 000000000..f596cfcb2 --- /dev/null +++ b/intl/libgnuintl.h.in @@ -0,0 +1,309 @@ +/* Message catalogs for internationalization. + Copyright (C) 1995-1997, 2000-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _LIBINTL_H +#define _LIBINTL_H 1 + +#include <locale.h> + +/* The LC_MESSAGES locale category is the category used by the functions + gettext() and dgettext(). It is specified in POSIX, but not in ANSI C. + On systems that don't define it, use an arbitrary value instead. + On Solaris, <locale.h> defines __LOCALE_H (or _LOCALE_H in Solaris 2.5) + then includes <libintl.h> (i.e. this file!) and then only defines + LC_MESSAGES. To avoid a redefinition warning, don't define LC_MESSAGES + in this case. */ +#if !defined LC_MESSAGES && !(defined __LOCALE_H || (defined _LOCALE_H && defined __sun)) +# define LC_MESSAGES 1729 +#endif + +/* We define an additional symbol to signal that we use the GNU + implementation of gettext. */ +#define __USE_GNU_GETTEXT 1 + +/* Provide information about the supported file formats. Returns the + maximum minor revision number supported for a given major revision. */ +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \ + ((major) == 0 ? 1 : -1) + +/* Resolve a platform specific conflict on DJGPP. GNU gettext takes + precedence over _conio_gettext. */ +#ifdef __DJGPP__ +# undef gettext +#endif + +/* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers + used by programs. Similarly, test __PROTOTYPES, not PROTOTYPES. */ +#ifndef _INTL_PARAMS +# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES +# define _INTL_PARAMS(args) args +# else +# define _INTL_PARAMS(args) () +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* We redirect the functions to those prefixed with "libintl_". This is + necessary, because some systems define gettext/textdomain/... in the C + library (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer). + If we used the unprefixed names, there would be cases where the + definition in the C library would override the one in the libintl.so + shared library. Recall that on ELF systems, the symbols are looked + up in the following order: + 1. in the executable, + 2. in the shared libraries specified on the link command line, in order, + 3. in the dependencies of the shared libraries specified on the link + command line, + 4. in the dlopen()ed shared libraries, in the order in which they were + dlopen()ed. + The definition in the C library would override the one in libintl.so if + either + * -lc is given on the link command line and -lintl isn't, or + * -lc is given on the link command line before -lintl, or + * libintl.so is a dependency of a dlopen()ed shared library but not + linked to the executable at link time. + Since Solaris gettext() behaves differently than GNU gettext(), this + would be unacceptable. + + The redirection happens by default through macros in C, so that &gettext + is independent of the compilation unit, but through inline functions in + C++, in order not to interfere with the name mangling of class fields or + class methods called 'gettext'. */ + +/* The user can define _INTL_REDIRECT_INLINE or _INTL_REDIRECT_MACROS. + If he doesn't, we choose the method. A third possible method is + _INTL_REDIRECT_ASM, supported only by GCC. */ +#if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS) +# if __GNUC__ >= 2 && !defined __APPLE_CC__ && (defined __STDC__ || defined __cplusplus) +# define _INTL_REDIRECT_ASM +# else +# ifdef __cplusplus +# define _INTL_REDIRECT_INLINE +# else +# define _INTL_REDIRECT_MACROS +# endif +# endif +#endif +/* Auxiliary macros. */ +#ifdef _INTL_REDIRECT_ASM +# define _INTL_ASM(cname) __asm__ (_INTL_ASMNAME (__USER_LABEL_PREFIX__, #cname)) +# define _INTL_ASMNAME(prefix,cnamestring) _INTL_STRINGIFY (prefix) cnamestring +# define _INTL_STRINGIFY(prefix) #prefix +#else +# define _INTL_ASM(cname) +#endif + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_gettext (const char *__msgid); +static inline char *gettext (const char *__msgid) +{ + return libintl_gettext (__msgid); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define gettext libintl_gettext +#endif +extern char *gettext _INTL_PARAMS ((const char *__msgid)) + _INTL_ASM (libintl_gettext); +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current + LC_MESSAGES locale. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dgettext (const char *__domainname, const char *__msgid); +static inline char *dgettext (const char *__domainname, const char *__msgid) +{ + return libintl_dgettext (__domainname, __msgid); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dgettext libintl_dgettext +#endif +extern char *dgettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid)) + _INTL_ASM (libintl_dgettext); +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dcgettext (const char *__domainname, const char *__msgid, + int __category); +static inline char *dcgettext (const char *__domainname, const char *__msgid, + int __category) +{ + return libintl_dcgettext (__domainname, __msgid, __category); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dcgettext libintl_dcgettext +#endif +extern char *dcgettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid, + int __category)) + _INTL_ASM (libintl_dcgettext); +#endif + + +/* Similar to `gettext' but select the plural form corresponding to the + number N. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_ngettext (const char *__msgid1, const char *__msgid2, + unsigned long int __n); +static inline char *ngettext (const char *__msgid1, const char *__msgid2, + unsigned long int __n) +{ + return libintl_ngettext (__msgid1, __msgid2, __n); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define ngettext libintl_ngettext +#endif +extern char *ngettext _INTL_PARAMS ((const char *__msgid1, + const char *__msgid2, + unsigned long int __n)) + _INTL_ASM (libintl_ngettext); +#endif + +/* Similar to `dgettext' but select the plural form corresponding to the + number N. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dngettext (const char *__domainname, const char *__msgid1, + const char *__msgid2, unsigned long int __n); +static inline char *dngettext (const char *__domainname, const char *__msgid1, + const char *__msgid2, unsigned long int __n) +{ + return libintl_dngettext (__domainname, __msgid1, __msgid2, __n); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dngettext libintl_dngettext +#endif +extern char *dngettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid1, + const char *__msgid2, + unsigned long int __n)) + _INTL_ASM (libintl_dngettext); +#endif + +/* Similar to `dcgettext' but select the plural form corresponding to the + number N. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dcngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category); +static inline char *dcngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category) +{ + return libintl_dcngettext (__domainname, __msgid1, __msgid2, __n, __category); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dcngettext libintl_dcngettext +#endif +extern char *dcngettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid1, + const char *__msgid2, + unsigned long int __n, + int __category)) + _INTL_ASM (libintl_dcngettext); +#endif + + +/* Set the current default message catalog to DOMAINNAME. + If DOMAINNAME is null, return the current default. + If DOMAINNAME is "", reset to the default of "messages". */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_textdomain (const char *__domainname); +static inline char *textdomain (const char *__domainname) +{ + return libintl_textdomain (__domainname); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define textdomain libintl_textdomain +#endif +extern char *textdomain _INTL_PARAMS ((const char *__domainname)) + _INTL_ASM (libintl_textdomain); +#endif + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_bindtextdomain (const char *__domainname, + const char *__dirname); +static inline char *bindtextdomain (const char *__domainname, + const char *__dirname) +{ + return libintl_bindtextdomain (__domainname, __dirname); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define bindtextdomain libintl_bindtextdomain +#endif +extern char *bindtextdomain _INTL_PARAMS ((const char *__domainname, + const char *__dirname)) + _INTL_ASM (libintl_bindtextdomain); +#endif + +/* Specify the character encoding in which the messages from the + DOMAINNAME message catalog will be returned. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_bind_textdomain_codeset (const char *__domainname, + const char *__codeset); +static inline char *bind_textdomain_codeset (const char *__domainname, + const char *__codeset) +{ + return libintl_bind_textdomain_codeset (__domainname, __codeset); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define bind_textdomain_codeset libintl_bind_textdomain_codeset +#endif +extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname, + const char *__codeset)) + _INTL_ASM (libintl_bind_textdomain_codeset); +#endif + + +/* Support for relocatable packages. */ + +/* Sets the original and the current installation prefix of the package. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +#define libintl_set_relocation_prefix libintl_set_relocation_prefix +extern void + libintl_set_relocation_prefix _INTL_PARAMS ((const char *orig_prefix, + const char *curr_prefix)); + + +#ifdef __cplusplus +} +#endif + +#endif /* libintl.h */ diff --git a/intl/loadinfo.h b/intl/loadinfo.h new file mode 100644 index 000000000..1d3ba6162 --- /dev/null +++ b/intl/loadinfo.h @@ -0,0 +1,156 @@ +/* Copyright (C) 1996-1999, 2000-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _LOADINFO_H +#define _LOADINFO_H 1 + +/* Declarations of locale dependent catalog lookup functions. + Implemented in + + localealias.c Possibly replace a locale name by another. + explodename.c Split a locale name into its various fields. + l10nflist.c Generate a list of filenames of possible message catalogs. + finddomain.c Find and open the relevant message catalogs. + + The main function _nl_find_domain() in finddomain.c is declared + in gettextP.h. + */ + +#ifndef PARAMS +# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +#endif + +#ifndef internal_function +# define internal_function +#endif + +/* Tell the compiler when a conditional or integer expression is + almost always true or almost always false. */ +#ifndef HAVE_BUILTIN_EXPECT +# define __builtin_expect(expr, val) (expr) +#endif + +/* Separator in PATH like lists of pathnames. */ +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define PATH_SEPARATOR ';' +#else + /* Unix */ +# define PATH_SEPARATOR ':' +#endif + +/* Encoding of locale name parts. */ +#define CEN_REVISION 1 +#define CEN_SPONSOR 2 +#define CEN_SPECIAL 4 +#define XPG_NORM_CODESET 8 +#define XPG_CODESET 16 +#define TERRITORY 32 +#define CEN_AUDIENCE 64 +#define XPG_MODIFIER 128 + +#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) +#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) + + +struct loaded_l10nfile +{ + const char *filename; + int decided; + + const void *data; + + struct loaded_l10nfile *next; + struct loaded_l10nfile *successor[1]; +}; + + +/* Normalize codeset name. There is no standard for the codeset + names. Normalization allows the user to use any of the common + names. The return value is dynamically allocated and has to be + freed by the caller. */ +extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, + size_t name_len)); + +/* Lookup a locale dependent file. + *L10NFILE_LIST denotes a pool of lookup results of locale dependent + files of the same kind, sorted in decreasing order of ->filename. + DIRLIST and DIRLIST_LEN are an argz list of directories in which to + look, containing at least one directory (i.e. DIRLIST_LEN > 0). + MASK, LANGUAGE, TERRITORY, CODESET, NORMALIZED_CODESET, MODIFIER, + SPECIAL, SPONSOR, REVISION are the pieces of the locale name, as + produced by _nl_explode_name(). FILENAME is the filename suffix. + The return value is the lookup result, either found in *L10NFILE_LIST, + or - if DO_ALLOCATE is nonzero - freshly allocated, or possibly NULL. + If the return value is non-NULL, it is added to *L10NFILE_LIST, and + its ->next field denotes the chaining inside *L10NFILE_LIST, and + furthermore its ->successor[] field contains a list of other lookup + results from which this lookup result inherits. */ +extern struct loaded_l10nfile * +_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, + const char *dirlist, size_t dirlist_len, int mask, + const char *language, const char *territory, + const char *codeset, + const char *normalized_codeset, + const char *modifier, const char *special, + const char *sponsor, const char *revision, + const char *filename, int do_allocate)); + +/* Lookup the real locale name for a locale alias NAME, or NULL if + NAME is not a locale alias (but possibly a real locale name). + The return value is statically allocated and must not be freed. */ +extern const char *_nl_expand_alias PARAMS ((const char *name)); + +/* Split a locale name NAME into its pieces: language, modifier, + territory, codeset, special, sponsor, revision. + NAME gets destructively modified: NUL bytes are inserted here and + there. *LANGUAGE gets assigned NAME. Each of *MODIFIER, *TERRITORY, + *CODESET, *SPECIAL, *SPONSOR, *REVISION gets assigned either a + pointer into the old NAME string, or NULL. *NORMALIZED_CODESET + gets assigned the expanded *CODESET, if it is different from *CODESET; + this one is dynamically allocated and has to be freed by the caller. + The return value is a bitmask, where each bit corresponds to one + filled-in value: + XPG_MODIFIER, CEN_AUDIENCE for *MODIFIER, + TERRITORY for *TERRITORY, + XPG_CODESET for *CODESET, + XPG_NORM_CODESET for *NORMALIZED_CODESET, + CEN_SPECIAL for *SPECIAL, + CEN_SPONSOR for *SPONSOR, + CEN_REVISION for *REVISION. + */ +extern int _nl_explode_name PARAMS ((char *name, const char **language, + const char **modifier, + const char **territory, + const char **codeset, + const char **normalized_codeset, + const char **special, + const char **sponsor, + const char **revision)); + +/* Split a locale name NAME into a leading language part and all the + rest. Return a pointer to the first character after the language, + i.e. to the first byte of the rest. */ +extern char *_nl_find_language PARAMS ((const char *name)); + +#endif /* loadinfo.h */ diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c new file mode 100644 index 000000000..8509bd345 --- /dev/null +++ b/intl/loadmsgcat.c @@ -0,0 +1,1322 @@ +/* Load needed message catalogs. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Tell glibc's <string.h> to provide a prototype for mempcpy(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include <stdlib.h> +#include <string.h> + +#if defined HAVE_UNISTD_H || defined _LIBC +# include <unistd.h> +#endif + +#ifdef _LIBC +# include <langinfo.h> +# include <locale.h> +#endif + +#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ + || (defined _LIBC && defined _POSIX_MAPPED_FILES) +# include <sys/mman.h> +# undef HAVE_MMAP +# define HAVE_MMAP 1 +#else +# undef HAVE_MMAP +#endif + +#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC +# include <stdint.h> +#endif +#if defined HAVE_INTTYPES_H || defined _LIBC +# include <inttypes.h> +#endif + +#include "gmo.h" +#include "gettextP.h" +#include "hash-string.h" +#include "plural-exp.h" + +#ifdef _LIBC +# include "../locale/localeinfo.h" +#endif + +/* Provide fallback values for macros that ought to be defined in <inttypes.h>. + Note that our fallback values need not be literal strings, because we don't + use them with preprocessor string concatenation. */ +#if !defined PRId8 || PRI_MACROS_BROKEN +# undef PRId8 +# define PRId8 "d" +#endif +#if !defined PRIi8 || PRI_MACROS_BROKEN +# undef PRIi8 +# define PRIi8 "i" +#endif +#if !defined PRIo8 || PRI_MACROS_BROKEN +# undef PRIo8 +# define PRIo8 "o" +#endif +#if !defined PRIu8 || PRI_MACROS_BROKEN +# undef PRIu8 +# define PRIu8 "u" +#endif +#if !defined PRIx8 || PRI_MACROS_BROKEN +# undef PRIx8 +# define PRIx8 "x" +#endif +#if !defined PRIX8 || PRI_MACROS_BROKEN +# undef PRIX8 +# define PRIX8 "X" +#endif +#if !defined PRId16 || PRI_MACROS_BROKEN +# undef PRId16 +# define PRId16 "d" +#endif +#if !defined PRIi16 || PRI_MACROS_BROKEN +# undef PRIi16 +# define PRIi16 "i" +#endif +#if !defined PRIo16 || PRI_MACROS_BROKEN +# undef PRIo16 +# define PRIo16 "o" +#endif +#if !defined PRIu16 || PRI_MACROS_BROKEN +# undef PRIu16 +# define PRIu16 "u" +#endif +#if !defined PRIx16 || PRI_MACROS_BROKEN +# undef PRIx16 +# define PRIx16 "x" +#endif +#if !defined PRIX16 || PRI_MACROS_BROKEN +# undef PRIX16 +# define PRIX16 "X" +#endif +#if !defined PRId32 || PRI_MACROS_BROKEN +# undef PRId32 +# define PRId32 "d" +#endif +#if !defined PRIi32 || PRI_MACROS_BROKEN +# undef PRIi32 +# define PRIi32 "i" +#endif +#if !defined PRIo32 || PRI_MACROS_BROKEN +# undef PRIo32 +# define PRIo32 "o" +#endif +#if !defined PRIu32 || PRI_MACROS_BROKEN +# undef PRIu32 +# define PRIu32 "u" +#endif +#if !defined PRIx32 || PRI_MACROS_BROKEN +# undef PRIx32 +# define PRIx32 "x" +#endif +#if !defined PRIX32 || PRI_MACROS_BROKEN +# undef PRIX32 +# define PRIX32 "X" +#endif +#if !defined PRId64 || PRI_MACROS_BROKEN +# undef PRId64 +# define PRId64 (sizeof (long) == 8 ? "ld" : "lld") +#endif +#if !defined PRIi64 || PRI_MACROS_BROKEN +# undef PRIi64 +# define PRIi64 (sizeof (long) == 8 ? "li" : "lli") +#endif +#if !defined PRIo64 || PRI_MACROS_BROKEN +# undef PRIo64 +# define PRIo64 (sizeof (long) == 8 ? "lo" : "llo") +#endif +#if !defined PRIu64 || PRI_MACROS_BROKEN +# undef PRIu64 +# define PRIu64 (sizeof (long) == 8 ? "lu" : "llu") +#endif +#if !defined PRIx64 || PRI_MACROS_BROKEN +# undef PRIx64 +# define PRIx64 (sizeof (long) == 8 ? "lx" : "llx") +#endif +#if !defined PRIX64 || PRI_MACROS_BROKEN +# undef PRIX64 +# define PRIX64 (sizeof (long) == 8 ? "lX" : "llX") +#endif +#if !defined PRIdLEAST8 || PRI_MACROS_BROKEN +# undef PRIdLEAST8 +# define PRIdLEAST8 "d" +#endif +#if !defined PRIiLEAST8 || PRI_MACROS_BROKEN +# undef PRIiLEAST8 +# define PRIiLEAST8 "i" +#endif +#if !defined PRIoLEAST8 || PRI_MACROS_BROKEN +# undef PRIoLEAST8 +# define PRIoLEAST8 "o" +#endif +#if !defined PRIuLEAST8 || PRI_MACROS_BROKEN +# undef PRIuLEAST8 +# define PRIuLEAST8 "u" +#endif +#if !defined PRIxLEAST8 || PRI_MACROS_BROKEN +# undef PRIxLEAST8 +# define PRIxLEAST8 "x" +#endif +#if !defined PRIXLEAST8 || PRI_MACROS_BROKEN +# undef PRIXLEAST8 +# define PRIXLEAST8 "X" +#endif +#if !defined PRIdLEAST16 || PRI_MACROS_BROKEN +# undef PRIdLEAST16 +# define PRIdLEAST16 "d" +#endif +#if !defined PRIiLEAST16 || PRI_MACROS_BROKEN +# undef PRIiLEAST16 +# define PRIiLEAST16 "i" +#endif +#if !defined PRIoLEAST16 || PRI_MACROS_BROKEN +# undef PRIoLEAST16 +# define PRIoLEAST16 "o" +#endif +#if !defined PRIuLEAST16 || PRI_MACROS_BROKEN +# undef PRIuLEAST16 +# define PRIuLEAST16 "u" +#endif +#if !defined PRIxLEAST16 || PRI_MACROS_BROKEN +# undef PRIxLEAST16 +# define PRIxLEAST16 "x" +#endif +#if !defined PRIXLEAST16 || PRI_MACROS_BROKEN +# undef PRIXLEAST16 +# define PRIXLEAST16 "X" +#endif +#if !defined PRIdLEAST32 || PRI_MACROS_BROKEN +# undef PRIdLEAST32 +# define PRIdLEAST32 "d" +#endif +#if !defined PRIiLEAST32 || PRI_MACROS_BROKEN +# undef PRIiLEAST32 +# define PRIiLEAST32 "i" +#endif +#if !defined PRIoLEAST32 || PRI_MACROS_BROKEN +# undef PRIoLEAST32 +# define PRIoLEAST32 "o" +#endif +#if !defined PRIuLEAST32 || PRI_MACROS_BROKEN +# undef PRIuLEAST32 +# define PRIuLEAST32 "u" +#endif +#if !defined PRIxLEAST32 || PRI_MACROS_BROKEN +# undef PRIxLEAST32 +# define PRIxLEAST32 "x" +#endif +#if !defined PRIXLEAST32 || PRI_MACROS_BROKEN +# undef PRIXLEAST32 +# define PRIXLEAST32 "X" +#endif +#if !defined PRIdLEAST64 || PRI_MACROS_BROKEN +# undef PRIdLEAST64 +# define PRIdLEAST64 PRId64 +#endif +#if !defined PRIiLEAST64 || PRI_MACROS_BROKEN +# undef PRIiLEAST64 +# define PRIiLEAST64 PRIi64 +#endif +#if !defined PRIoLEAST64 || PRI_MACROS_BROKEN +# undef PRIoLEAST64 +# define PRIoLEAST64 PRIo64 +#endif +#if !defined PRIuLEAST64 || PRI_MACROS_BROKEN +# undef PRIuLEAST64 +# define PRIuLEAST64 PRIu64 +#endif +#if !defined PRIxLEAST64 || PRI_MACROS_BROKEN +# undef PRIxLEAST64 +# define PRIxLEAST64 PRIx64 +#endif +#if !defined PRIXLEAST64 || PRI_MACROS_BROKEN +# undef PRIXLEAST64 +# define PRIXLEAST64 PRIX64 +#endif +#if !defined PRIdFAST8 || PRI_MACROS_BROKEN +# undef PRIdFAST8 +# define PRIdFAST8 "d" +#endif +#if !defined PRIiFAST8 || PRI_MACROS_BROKEN +# undef PRIiFAST8 +# define PRIiFAST8 "i" +#endif +#if !defined PRIoFAST8 || PRI_MACROS_BROKEN +# undef PRIoFAST8 +# define PRIoFAST8 "o" +#endif +#if !defined PRIuFAST8 || PRI_MACROS_BROKEN +# undef PRIuFAST8 +# define PRIuFAST8 "u" +#endif +#if !defined PRIxFAST8 || PRI_MACROS_BROKEN +# undef PRIxFAST8 +# define PRIxFAST8 "x" +#endif +#if !defined PRIXFAST8 || PRI_MACROS_BROKEN +# undef PRIXFAST8 +# define PRIXFAST8 "X" +#endif +#if !defined PRIdFAST16 || PRI_MACROS_BROKEN +# undef PRIdFAST16 +# define PRIdFAST16 "d" +#endif +#if !defined PRIiFAST16 || PRI_MACROS_BROKEN +# undef PRIiFAST16 +# define PRIiFAST16 "i" +#endif +#if !defined PRIoFAST16 || PRI_MACROS_BROKEN +# undef PRIoFAST16 +# define PRIoFAST16 "o" +#endif +#if !defined PRIuFAST16 || PRI_MACROS_BROKEN +# undef PRIuFAST16 +# define PRIuFAST16 "u" +#endif +#if !defined PRIxFAST16 || PRI_MACROS_BROKEN +# undef PRIxFAST16 +# define PRIxFAST16 "x" +#endif +#if !defined PRIXFAST16 || PRI_MACROS_BROKEN +# undef PRIXFAST16 +# define PRIXFAST16 "X" +#endif +#if !defined PRIdFAST32 || PRI_MACROS_BROKEN +# undef PRIdFAST32 +# define PRIdFAST32 "d" +#endif +#if !defined PRIiFAST32 || PRI_MACROS_BROKEN +# undef PRIiFAST32 +# define PRIiFAST32 "i" +#endif +#if !defined PRIoFAST32 || PRI_MACROS_BROKEN +# undef PRIoFAST32 +# define PRIoFAST32 "o" +#endif +#if !defined PRIuFAST32 || PRI_MACROS_BROKEN +# undef PRIuFAST32 +# define PRIuFAST32 "u" +#endif +#if !defined PRIxFAST32 || PRI_MACROS_BROKEN +# undef PRIxFAST32 +# define PRIxFAST32 "x" +#endif +#if !defined PRIXFAST32 || PRI_MACROS_BROKEN +# undef PRIXFAST32 +# define PRIXFAST32 "X" +#endif +#if !defined PRIdFAST64 || PRI_MACROS_BROKEN +# undef PRIdFAST64 +# define PRIdFAST64 PRId64 +#endif +#if !defined PRIiFAST64 || PRI_MACROS_BROKEN +# undef PRIiFAST64 +# define PRIiFAST64 PRIi64 +#endif +#if !defined PRIoFAST64 || PRI_MACROS_BROKEN +# undef PRIoFAST64 +# define PRIoFAST64 PRIo64 +#endif +#if !defined PRIuFAST64 || PRI_MACROS_BROKEN +# undef PRIuFAST64 +# define PRIuFAST64 PRIu64 +#endif +#if !defined PRIxFAST64 || PRI_MACROS_BROKEN +# undef PRIxFAST64 +# define PRIxFAST64 PRIx64 +#endif +#if !defined PRIXFAST64 || PRI_MACROS_BROKEN +# undef PRIXFAST64 +# define PRIXFAST64 PRIX64 +#endif +#if !defined PRIdMAX || PRI_MACROS_BROKEN +# undef PRIdMAX +# define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld") +#endif +#if !defined PRIiMAX || PRI_MACROS_BROKEN +# undef PRIiMAX +# define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli") +#endif +#if !defined PRIoMAX || PRI_MACROS_BROKEN +# undef PRIoMAX +# define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo") +#endif +#if !defined PRIuMAX || PRI_MACROS_BROKEN +# undef PRIuMAX +# define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu") +#endif +#if !defined PRIxMAX || PRI_MACROS_BROKEN +# undef PRIxMAX +# define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx") +#endif +#if !defined PRIXMAX || PRI_MACROS_BROKEN +# undef PRIXMAX +# define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX") +#endif +#if !defined PRIdPTR || PRI_MACROS_BROKEN +# undef PRIdPTR +# define PRIdPTR \ + (sizeof (void *) == sizeof (long) ? "ld" : \ + sizeof (void *) == sizeof (int) ? "d" : \ + "lld") +#endif +#if !defined PRIiPTR || PRI_MACROS_BROKEN +# undef PRIiPTR +# define PRIiPTR \ + (sizeof (void *) == sizeof (long) ? "li" : \ + sizeof (void *) == sizeof (int) ? "i" : \ + "lli") +#endif +#if !defined PRIoPTR || PRI_MACROS_BROKEN +# undef PRIoPTR +# define PRIoPTR \ + (sizeof (void *) == sizeof (long) ? "lo" : \ + sizeof (void *) == sizeof (int) ? "o" : \ + "llo") +#endif +#if !defined PRIuPTR || PRI_MACROS_BROKEN +# undef PRIuPTR +# define PRIuPTR \ + (sizeof (void *) == sizeof (long) ? "lu" : \ + sizeof (void *) == sizeof (int) ? "u" : \ + "llu") +#endif +#if !defined PRIxPTR || PRI_MACROS_BROKEN +# undef PRIxPTR +# define PRIxPTR \ + (sizeof (void *) == sizeof (long) ? "lx" : \ + sizeof (void *) == sizeof (int) ? "x" : \ + "llx") +#endif +#if !defined PRIXPTR || PRI_MACROS_BROKEN +# undef PRIXPTR +# define PRIXPTR \ + (sizeof (void *) == sizeof (long) ? "lX" : \ + sizeof (void *) == sizeof (int) ? "X" : \ + "llX") +#endif + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ISO C functions. This is required by the standard + because some ISO C functions will require linking with this object + file and the name space must not be polluted. */ +# define open __open +# define close __close +# define read __read +# define mmap __mmap +# define munmap __munmap +#endif + +/* For those losing systems which don't have `alloca' we have to add + some additional code emulating it. */ +#ifdef HAVE_ALLOCA +# define freea(p) /* nothing */ +#else +# define alloca(n) malloc (n) +# define freea(p) free (p) +#endif + +/* For systems that distinguish between text and binary I/O. + O_BINARY is usually declared in <fcntl.h>. */ +#if !defined O_BINARY && defined _O_BINARY + /* For MSC-compatible compilers. */ +# define O_BINARY _O_BINARY +# define O_TEXT _O_TEXT +#endif +#ifdef __BEOS__ + /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ +# undef O_BINARY +# undef O_TEXT +#endif +/* On reasonable systems, binary I/O is the default. */ +#ifndef O_BINARY +# define O_BINARY 0 +#endif + + +/* Prototypes for local functions. Needed to ensure compiler checking of + function argument counts despite of K&R C function definition syntax. */ +static const char *get_sysdep_segment_value PARAMS ((const char *name)); + + +/* We need a sign, whether a new catalog was loaded, which can be associated + with all translations. This is important if the translations are + cached by one of GCC's features. */ +int _nl_msg_cat_cntr; + + +/* Expand a system dependent string segment. Return NULL if unsupported. */ +static const char * +get_sysdep_segment_value (name) + const char *name; +{ + /* Test for an ISO C 99 section 7.8.1 format string directive. + Syntax: + P R I { d | i | o | u | x | X } + { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */ + /* We don't use a table of 14 times 6 'const char *' strings here, because + data relocations cost startup time. */ + if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I') + { + if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u' + || name[3] == 'x' || name[3] == 'X') + { + if (name[4] == '8' && name[5] == '\0') + { + if (name[3] == 'd') + return PRId8; + if (name[3] == 'i') + return PRIi8; + if (name[3] == 'o') + return PRIo8; + if (name[3] == 'u') + return PRIu8; + if (name[3] == 'x') + return PRIx8; + if (name[3] == 'X') + return PRIX8; + abort (); + } + if (name[4] == '1' && name[5] == '6' && name[6] == '\0') + { + if (name[3] == 'd') + return PRId16; + if (name[3] == 'i') + return PRIi16; + if (name[3] == 'o') + return PRIo16; + if (name[3] == 'u') + return PRIu16; + if (name[3] == 'x') + return PRIx16; + if (name[3] == 'X') + return PRIX16; + abort (); + } + if (name[4] == '3' && name[5] == '2' && name[6] == '\0') + { + if (name[3] == 'd') + return PRId32; + if (name[3] == 'i') + return PRIi32; + if (name[3] == 'o') + return PRIo32; + if (name[3] == 'u') + return PRIu32; + if (name[3] == 'x') + return PRIx32; + if (name[3] == 'X') + return PRIX32; + abort (); + } + if (name[4] == '6' && name[5] == '4' && name[6] == '\0') + { + if (name[3] == 'd') + return PRId64; + if (name[3] == 'i') + return PRIi64; + if (name[3] == 'o') + return PRIo64; + if (name[3] == 'u') + return PRIu64; + if (name[3] == 'x') + return PRIx64; + if (name[3] == 'X') + return PRIX64; + abort (); + } + if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A' + && name[7] == 'S' && name[8] == 'T') + { + if (name[9] == '8' && name[10] == '\0') + { + if (name[3] == 'd') + return PRIdLEAST8; + if (name[3] == 'i') + return PRIiLEAST8; + if (name[3] == 'o') + return PRIoLEAST8; + if (name[3] == 'u') + return PRIuLEAST8; + if (name[3] == 'x') + return PRIxLEAST8; + if (name[3] == 'X') + return PRIXLEAST8; + abort (); + } + if (name[9] == '1' && name[10] == '6' && name[11] == '\0') + { + if (name[3] == 'd') + return PRIdLEAST16; + if (name[3] == 'i') + return PRIiLEAST16; + if (name[3] == 'o') + return PRIoLEAST16; + if (name[3] == 'u') + return PRIuLEAST16; + if (name[3] == 'x') + return PRIxLEAST16; + if (name[3] == 'X') + return PRIXLEAST16; + abort (); + } + if (name[9] == '3' && name[10] == '2' && name[11] == '\0') + { + if (name[3] == 'd') + return PRIdLEAST32; + if (name[3] == 'i') + return PRIiLEAST32; + if (name[3] == 'o') + return PRIoLEAST32; + if (name[3] == 'u') + return PRIuLEAST32; + if (name[3] == 'x') + return PRIxLEAST32; + if (name[3] == 'X') + return PRIXLEAST32; + abort (); + } + if (name[9] == '6' && name[10] == '4' && name[11] == '\0') + { + if (name[3] == 'd') + return PRIdLEAST64; + if (name[3] == 'i') + return PRIiLEAST64; + if (name[3] == 'o') + return PRIoLEAST64; + if (name[3] == 'u') + return PRIuLEAST64; + if (name[3] == 'x') + return PRIxLEAST64; + if (name[3] == 'X') + return PRIXLEAST64; + abort (); + } + } + if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S' + && name[7] == 'T') + { + if (name[8] == '8' && name[9] == '\0') + { + if (name[3] == 'd') + return PRIdFAST8; + if (name[3] == 'i') + return PRIiFAST8; + if (name[3] == 'o') + return PRIoFAST8; + if (name[3] == 'u') + return PRIuFAST8; + if (name[3] == 'x') + return PRIxFAST8; + if (name[3] == 'X') + return PRIXFAST8; + abort (); + } + if (name[8] == '1' && name[9] == '6' && name[10] == '\0') + { + if (name[3] == 'd') + return PRIdFAST16; + if (name[3] == 'i') + return PRIiFAST16; + if (name[3] == 'o') + return PRIoFAST16; + if (name[3] == 'u') + return PRIuFAST16; + if (name[3] == 'x') + return PRIxFAST16; + if (name[3] == 'X') + return PRIXFAST16; + abort (); + } + if (name[8] == '3' && name[9] == '2' && name[10] == '\0') + { + if (name[3] == 'd') + return PRIdFAST32; + if (name[3] == 'i') + return PRIiFAST32; + if (name[3] == 'o') + return PRIoFAST32; + if (name[3] == 'u') + return PRIuFAST32; + if (name[3] == 'x') + return PRIxFAST32; + if (name[3] == 'X') + return PRIXFAST32; + abort (); + } + if (name[8] == '6' && name[9] == '4' && name[10] == '\0') + { + if (name[3] == 'd') + return PRIdFAST64; + if (name[3] == 'i') + return PRIiFAST64; + if (name[3] == 'o') + return PRIoFAST64; + if (name[3] == 'u') + return PRIuFAST64; + if (name[3] == 'x') + return PRIxFAST64; + if (name[3] == 'X') + return PRIXFAST64; + abort (); + } + } + if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X' + && name[7] == '\0') + { + if (name[3] == 'd') + return PRIdMAX; + if (name[3] == 'i') + return PRIiMAX; + if (name[3] == 'o') + return PRIoMAX; + if (name[3] == 'u') + return PRIuMAX; + if (name[3] == 'x') + return PRIxMAX; + if (name[3] == 'X') + return PRIXMAX; + abort (); + } + if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R' + && name[7] == '\0') + { + if (name[3] == 'd') + return PRIdPTR; + if (name[3] == 'i') + return PRIiPTR; + if (name[3] == 'o') + return PRIoPTR; + if (name[3] == 'u') + return PRIuPTR; + if (name[3] == 'x') + return PRIxPTR; + if (name[3] == 'X') + return PRIXPTR; + abort (); + } + } + } + /* Other system dependent strings are not valid. */ + return NULL; +} + +/* Initialize the codeset dependent parts of an opened message catalog. + Return the header entry. */ +const char * +internal_function +_nl_init_domain_conv (domain_file, domain, domainbinding) + struct loaded_l10nfile *domain_file; + struct loaded_domain *domain; + struct binding *domainbinding; +{ + /* Find out about the character set the file is encoded with. + This can be found (in textual form) in the entry "". If this + entry does not exist or if this does not contain the `charset=' + information, we will assume the charset matches the one the + current locale and we don't have to perform any conversion. */ + char *nullentry; + size_t nullentrylen; + + /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ + domain->codeset_cntr = + (domainbinding != NULL ? domainbinding->codeset_cntr : 0); +#ifdef _LIBC + domain->conv = (__gconv_t) -1; +#else +# if HAVE_ICONV + domain->conv = (iconv_t) -1; +# endif +#endif + domain->conv_tab = NULL; + + /* Get the header entry. */ + nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); + + if (nullentry != NULL) + { +#if defined _LIBC || HAVE_ICONV + const char *charsetstr; + + charsetstr = strstr (nullentry, "charset="); + if (charsetstr != NULL) + { + size_t len; + char *charset; + const char *outcharset; + + charsetstr += strlen ("charset="); + len = strcspn (charsetstr, " \t\n"); + + charset = (char *) alloca (len + 1); +# if defined _LIBC || HAVE_MEMPCPY + *((char *) mempcpy (charset, charsetstr, len)) = '\0'; +# else + memcpy (charset, charsetstr, len); + charset[len] = '\0'; +# endif + + /* The output charset should normally be determined by the + locale. But sometimes the locale is not used or not correctly + set up, so we provide a possibility for the user to override + this. Moreover, the value specified through + bind_textdomain_codeset overrides both. */ + if (domainbinding != NULL && domainbinding->codeset != NULL) + outcharset = domainbinding->codeset; + else + { + outcharset = getenv ("OUTPUT_CHARSET"); + if (outcharset == NULL || outcharset[0] == '\0') + { +# ifdef _LIBC + outcharset = _NL_CURRENT (LC_CTYPE, CODESET); +# else +# if HAVE_ICONV + extern const char *locale_charset PARAMS ((void)); + outcharset = locale_charset (); +# endif +# endif + } + } + +# ifdef _LIBC + /* We always want to use transliteration. */ + outcharset = norm_add_slashes (outcharset, "TRANSLIT"); + charset = norm_add_slashes (charset, NULL); + if (__gconv_open (outcharset, charset, &domain->conv, + GCONV_AVOID_NOCONV) + != __GCONV_OK) + domain->conv = (__gconv_t) -1; +# else +# if HAVE_ICONV + /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, + we want to use transliteration. */ +# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ + || _LIBICONV_VERSION >= 0x0105 + if (strchr (outcharset, '/') == NULL) + { + char *tmp; + + len = strlen (outcharset); + tmp = (char *) alloca (len + 10 + 1); + memcpy (tmp, outcharset, len); + memcpy (tmp + len, "//TRANSLIT", 10 + 1); + outcharset = tmp; + + domain->conv = iconv_open (outcharset, charset); + + freea (outcharset); + } + else +# endif + domain->conv = iconv_open (outcharset, charset); +# endif +# endif + + freea (charset); + } +#endif /* _LIBC || HAVE_ICONV */ + } + + return nullentry; +} + +/* Frees the codeset dependent parts of an opened message catalog. */ +void +internal_function +_nl_free_domain_conv (domain) + struct loaded_domain *domain; +{ + if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) + free (domain->conv_tab); + +#ifdef _LIBC + if (domain->conv != (__gconv_t) -1) + __gconv_close (domain->conv); +#else +# if HAVE_ICONV + if (domain->conv != (iconv_t) -1) + iconv_close (domain->conv); +# endif +#endif +} + +/* Load the message catalogs specified by FILENAME. If it is no valid + message catalog do nothing. */ +void +internal_function +_nl_load_domain (domain_file, domainbinding) + struct loaded_l10nfile *domain_file; + struct binding *domainbinding; +{ + int fd; + size_t size; +#ifdef _LIBC + struct stat64 st; +#else + struct stat st; +#endif + struct mo_file_header *data = (struct mo_file_header *) -1; + int use_mmap = 0; + struct loaded_domain *domain; + int revision; + const char *nullentry; + + domain_file->decided = 1; + domain_file->data = NULL; + + /* Note that it would be useless to store domainbinding in domain_file + because domainbinding might be == NULL now but != NULL later (after + a call to bind_textdomain_codeset). */ + + /* If the record does not represent a valid locale the FILENAME + might be NULL. This can happen when according to the given + specification the locale file name is different for XPG and CEN + syntax. */ + if (domain_file->filename == NULL) + return; + + /* Try to open the addressed file. */ + fd = open (domain_file->filename, O_RDONLY | O_BINARY); + if (fd == -1) + return; + + /* We must know about the size of the file. */ + if ( +#ifdef _LIBC + __builtin_expect (fstat64 (fd, &st) != 0, 0) +#else + __builtin_expect (fstat (fd, &st) != 0, 0) +#endif + || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0) + || __builtin_expect (size < sizeof (struct mo_file_header), 0)) + { + /* Something went wrong. */ + close (fd); + return; + } + +#ifdef HAVE_MMAP + /* Now we are ready to load the file. If mmap() is available we try + this first. If not available or it failed we try to load it. */ + data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, + MAP_PRIVATE, fd, 0); + + if (__builtin_expect (data != (struct mo_file_header *) -1, 1)) + { + /* mmap() call was successful. */ + close (fd); + use_mmap = 1; + } +#endif + + /* If the data is not yet available (i.e. mmap'ed) we try to load + it manually. */ + if (data == (struct mo_file_header *) -1) + { + size_t to_read; + char *read_ptr; + + data = (struct mo_file_header *) malloc (size); + if (data == NULL) + return; + + to_read = size; + read_ptr = (char *) data; + do + { + long int nb = (long int) read (fd, read_ptr, to_read); + if (nb <= 0) + { +#ifdef EINTR + if (nb == -1 && errno == EINTR) + continue; +#endif + close (fd); + return; + } + read_ptr += nb; + to_read -= nb; + } + while (to_read > 0); + + close (fd); + } + + /* Using the magic number we can test whether it really is a message + catalog file. */ + if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED, + 0)) + { + /* The magic number is wrong: not a message catalog file. */ +#ifdef HAVE_MMAP + if (use_mmap) + munmap ((caddr_t) data, size); + else +#endif + free (data); + return; + } + + domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); + if (domain == NULL) + return; + domain_file->data = domain; + + domain->data = (char *) data; + domain->use_mmap = use_mmap; + domain->mmap_size = size; + domain->must_swap = data->magic != _MAGIC; + domain->malloced = NULL; + + /* Fill in the information about the available tables. */ + revision = W (domain->must_swap, data->revision); + /* We support only the major revision 0. */ + switch (revision >> 16) + { + case 0: + domain->nstrings = W (domain->must_swap, data->nstrings); + domain->orig_tab = (const struct string_desc *) + ((char *) data + W (domain->must_swap, data->orig_tab_offset)); + domain->trans_tab = (const struct string_desc *) + ((char *) data + W (domain->must_swap, data->trans_tab_offset)); + domain->hash_size = W (domain->must_swap, data->hash_tab_size); + domain->hash_tab = + (domain->hash_size > 2 + ? (const nls_uint32 *) + ((char *) data + W (domain->must_swap, data->hash_tab_offset)) + : NULL); + domain->must_swap_hash_tab = domain->must_swap; + + /* Now dispatch on the minor revision. */ + switch (revision & 0xffff) + { + case 0: + domain->n_sysdep_strings = 0; + domain->orig_sysdep_tab = NULL; + domain->trans_sysdep_tab = NULL; + break; + case 1: + default: + { + nls_uint32 n_sysdep_strings; + + if (domain->hash_tab == NULL) + /* This is invalid. These minor revisions need a hash table. */ + goto invalid; + + n_sysdep_strings = + W (domain->must_swap, data->n_sysdep_strings); + if (n_sysdep_strings > 0) + { + nls_uint32 n_sysdep_segments; + const struct sysdep_segment *sysdep_segments; + const char **sysdep_segment_values; + const nls_uint32 *orig_sysdep_tab; + const nls_uint32 *trans_sysdep_tab; + size_t memneed; + char *mem; + struct sysdep_string_desc *inmem_orig_sysdep_tab; + struct sysdep_string_desc *inmem_trans_sysdep_tab; + nls_uint32 *inmem_hash_tab; + unsigned int i; + + /* Get the values of the system dependent segments. */ + n_sysdep_segments = + W (domain->must_swap, data->n_sysdep_segments); + sysdep_segments = (const struct sysdep_segment *) + ((char *) data + + W (domain->must_swap, data->sysdep_segments_offset)); + sysdep_segment_values = + alloca (n_sysdep_segments * sizeof (const char *)); + for (i = 0; i < n_sysdep_segments; i++) + { + const char *name = + (char *) data + + W (domain->must_swap, sysdep_segments[i].offset); + nls_uint32 namelen = + W (domain->must_swap, sysdep_segments[i].length); + + if (!(namelen > 0 && name[namelen - 1] == '\0')) + { + freea (sysdep_segment_values); + goto invalid; + } + + sysdep_segment_values[i] = get_sysdep_segment_value (name); + } + + orig_sysdep_tab = (const nls_uint32 *) + ((char *) data + + W (domain->must_swap, data->orig_sysdep_tab_offset)); + trans_sysdep_tab = (const nls_uint32 *) + ((char *) data + + W (domain->must_swap, data->trans_sysdep_tab_offset)); + + /* Compute the amount of additional memory needed for the + system dependent strings and the augmented hash table. */ + memneed = 2 * n_sysdep_strings + * sizeof (struct sysdep_string_desc) + + domain->hash_size * sizeof (nls_uint32); + for (i = 0; i < 2 * n_sysdep_strings; i++) + { + const struct sysdep_string *sysdep_string = + (const struct sysdep_string *) + ((char *) data + + W (domain->must_swap, + i < n_sysdep_strings + ? orig_sysdep_tab[i] + : trans_sysdep_tab[i - n_sysdep_strings])); + size_t need = 0; + const struct segment_pair *p = sysdep_string->segments; + + if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) + for (p = sysdep_string->segments;; p++) + { + nls_uint32 sysdepref; + + need += W (domain->must_swap, p->segsize); + + sysdepref = W (domain->must_swap, p->sysdepref); + if (sysdepref == SEGMENTS_END) + break; + + if (sysdepref >= n_sysdep_segments) + { + /* Invalid. */ + freea (sysdep_segment_values); + goto invalid; + } + + need += strlen (sysdep_segment_values[sysdepref]); + } + + memneed += need; + } + + /* Allocate additional memory. */ + mem = (char *) malloc (memneed); + if (mem == NULL) + goto invalid; + + domain->malloced = mem; + inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem; + mem += n_sysdep_strings * sizeof (struct sysdep_string_desc); + inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem; + mem += n_sysdep_strings * sizeof (struct sysdep_string_desc); + inmem_hash_tab = (nls_uint32 *) mem; + mem += domain->hash_size * sizeof (nls_uint32); + + /* Compute the system dependent strings. */ + for (i = 0; i < 2 * n_sysdep_strings; i++) + { + const struct sysdep_string *sysdep_string = + (const struct sysdep_string *) + ((char *) data + + W (domain->must_swap, + i < n_sysdep_strings + ? orig_sysdep_tab[i] + : trans_sysdep_tab[i - n_sysdep_strings])); + const char *static_segments = + (char *) data + + W (domain->must_swap, sysdep_string->offset); + const struct segment_pair *p = sysdep_string->segments; + + /* Concatenate the segments, and fill + inmem_orig_sysdep_tab[i] (for i < n_sysdep_strings) and + inmem_trans_sysdep_tab[i-n_sysdep_strings] (for + i >= n_sysdep_strings). */ + + if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END) + { + /* Only one static segment. */ + inmem_orig_sysdep_tab[i].length = + W (domain->must_swap, p->segsize); + inmem_orig_sysdep_tab[i].pointer = static_segments; + } + else + { + inmem_orig_sysdep_tab[i].pointer = mem; + + for (p = sysdep_string->segments;; p++) + { + nls_uint32 segsize = + W (domain->must_swap, p->segsize); + nls_uint32 sysdepref = + W (domain->must_swap, p->sysdepref); + size_t n; + + if (segsize > 0) + { + memcpy (mem, static_segments, segsize); + mem += segsize; + static_segments += segsize; + } + + if (sysdepref == SEGMENTS_END) + break; + + n = strlen (sysdep_segment_values[sysdepref]); + memcpy (mem, sysdep_segment_values[sysdepref], n); + mem += n; + } + + inmem_orig_sysdep_tab[i].length = + mem - inmem_orig_sysdep_tab[i].pointer; + } + } + + /* Compute the augmented hash table. */ + for (i = 0; i < domain->hash_size; i++) + inmem_hash_tab[i] = + W (domain->must_swap_hash_tab, domain->hash_tab[i]); + for (i = 0; i < n_sysdep_strings; i++) + { + const char *msgid = inmem_orig_sysdep_tab[i].pointer; + nls_uint32 hash_val = hash_string (msgid); + nls_uint32 idx = hash_val % domain->hash_size; + nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); + + for (;;) + { + if (inmem_hash_tab[idx] == 0) + { + /* Hash table entry is empty. Use it. */ + inmem_hash_tab[idx] = 1 + domain->nstrings + i; + break; + } + + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + } + } + + freea (sysdep_segment_values); + + domain->n_sysdep_strings = n_sysdep_strings; + domain->orig_sysdep_tab = inmem_orig_sysdep_tab; + domain->trans_sysdep_tab = inmem_trans_sysdep_tab; + + domain->hash_tab = inmem_hash_tab; + domain->must_swap_hash_tab = 0; + } + else + { + domain->n_sysdep_strings = 0; + domain->orig_sysdep_tab = NULL; + domain->trans_sysdep_tab = NULL; + } + } + break; + } + break; + default: + /* This is an invalid revision. */ + invalid: + /* This is an invalid .mo file. */ + if (domain->malloced) + free (domain->malloced); +#ifdef HAVE_MMAP + if (use_mmap) + munmap ((caddr_t) data, size); + else +#endif + free (data); + free (domain); + domain_file->data = NULL; + return; + } + + /* Now initialize the character set converter from the character set + the file is encoded with (found in the header entry) to the domain's + specified character set or the locale's character set. */ + nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); + + /* Also look for a plural specification. */ + EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); +} + + +#ifdef _LIBC +void +internal_function +_nl_unload_domain (domain) + struct loaded_domain *domain; +{ + if (domain->plural != &__gettext_germanic_plural) + __gettext_free_exp (domain->plural); + + _nl_free_domain_conv (domain); + + if (domain->malloced) + free (domain->malloced); + +# ifdef _POSIX_MAPPED_FILES + if (domain->use_mmap) + munmap ((caddr_t) domain->data, domain->mmap_size); + else +# endif /* _POSIX_MAPPED_FILES */ + free ((void *) domain->data); + + free (domain); +} +#endif diff --git a/intl/localcharset.c b/intl/localcharset.c new file mode 100644 index 000000000..d04d05368 --- /dev/null +++ b/intl/localcharset.c @@ -0,0 +1,398 @@ +/* Determine a canonical name for the current locale's character encoding. + + Copyright (C) 2000-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Written by Bruno Haible <bruno@clisp.org>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include "localcharset.h" + +#if HAVE_STDDEF_H +# include <stddef.h> +#endif + +#include <stdio.h> +#if HAVE_STRING_H +# include <string.h> +#else +# include <strings.h> +#endif +#if HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#if defined _WIN32 || defined __WIN32__ +# undef WIN32 /* avoid warning on mingw32 */ +# define WIN32 +#endif + +#if defined __EMX__ +/* Assume EMX program runs on OS/2, even if compiled under DOS. */ +# define OS2 +#endif + +#if !defined WIN32 +# if HAVE_LANGINFO_CODESET +# include <langinfo.h> +# else +# if HAVE_SETLOCALE +# include <locale.h> +# endif +# endif +#elif defined WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif +#if defined OS2 +# define INCL_DOS +# include <os2.h> +#endif + +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#endif + +#ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +#endif + +#ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +#endif + +#ifdef HAVE_GETC_UNLOCKED +# undef getc +# define getc getc_unlocked +#endif + +/* The following static variable is declared 'volatile' to avoid a + possible multithread problem in the function get_charset_aliases. If we + are running in a threaded environment, and if two threads initialize + 'charset_aliases' simultaneously, both will produce the same value, + and everything will be ok if the two assignments to 'charset_aliases' + are atomic. But I don't know what will happen if the two assignments mix. */ +#if __STDC__ != 1 +# define volatile /* empty */ +#endif +/* Pointer to the contents of the charset.alias file, if it has already been + read, else NULL. Its format is: + ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ +static const char * volatile charset_aliases; + +/* Return a pointer to the contents of the charset.alias file. */ +static const char * +get_charset_aliases () +{ + const char *cp; + + cp = charset_aliases; + if (cp == NULL) + { +#if !(defined VMS || defined WIN32) + FILE *fp; + const char *dir = relocate (LIBDIR); + const char *base = "charset.alias"; + char *file_name; + + /* Concatenate dir and base into freshly allocated file_name. */ + { + size_t dir_len = strlen (dir); + size_t base_len = strlen (base); + int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); + file_name = (char *) malloc (dir_len + add_slash + base_len + 1); + if (file_name != NULL) + { + memcpy (file_name, dir, dir_len); + if (add_slash) + file_name[dir_len] = DIRECTORY_SEPARATOR; + memcpy (file_name + dir_len + add_slash, base, base_len + 1); + } + } + + if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) + /* Out of memory or file not found, treat it as empty. */ + cp = ""; + else + { + /* Parse the file's contents. */ + int c; + char buf1[50+1]; + char buf2[50+1]; + char *res_ptr = NULL; + size_t res_size = 0; + size_t l1, l2; + + for (;;) + { + c = getc (fp); + if (c == EOF) + break; + if (c == '\n' || c == ' ' || c == '\t') + continue; + if (c == '#') + { + /* Skip comment, to end of line. */ + do + c = getc (fp); + while (!(c == EOF || c == '\n')); + if (c == EOF) + break; + continue; + } + ungetc (c, fp); + if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) + break; + l1 = strlen (buf1); + l2 = strlen (buf2); + if (res_size == 0) + { + res_size = l1 + 1 + l2 + 1; + res_ptr = (char *) malloc (res_size + 1); + } + else + { + res_size += l1 + 1 + l2 + 1; + res_ptr = (char *) realloc (res_ptr, res_size + 1); + } + if (res_ptr == NULL) + { + /* Out of memory. */ + res_size = 0; + break; + } + strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); + strcpy (res_ptr + res_size - (l2 + 1), buf2); + } + fclose (fp); + if (res_size == 0) + cp = ""; + else + { + *(res_ptr + res_size) = '\0'; + cp = res_ptr; + } + } + + if (file_name != NULL) + free (file_name); + +#else + +# if defined VMS + /* To avoid the troubles of an extra file charset.alias_vms in the + sources of many GNU packages, simply inline the aliases here. */ + /* The list of encodings is taken from the OpenVMS 7.3-1 documentation + "Compaq C Run-Time Library Reference Manual for OpenVMS systems" + section 10.7 "Handling Different Character Sets". */ + cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" + "ISO8859-2" "\0" "ISO-8859-2" "\0" + "ISO8859-5" "\0" "ISO-8859-5" "\0" + "ISO8859-7" "\0" "ISO-8859-7" "\0" + "ISO8859-8" "\0" "ISO-8859-8" "\0" + "ISO8859-9" "\0" "ISO-8859-9" "\0" + /* Japanese */ + "eucJP" "\0" "EUC-JP" "\0" + "SJIS" "\0" "SHIFT_JIS" "\0" + "DECKANJI" "\0" "DEC-KANJI" "\0" + "SDECKANJI" "\0" "EUC-JP" "\0" + /* Chinese */ + "eucTW" "\0" "EUC-TW" "\0" + "DECHANYU" "\0" "DEC-HANYU" "\0" + "DECHANZI" "\0" "GB2312" "\0" + /* Korean */ + "DECKOREAN" "\0" "EUC-KR" "\0"; +# endif + +# if defined WIN32 + /* To avoid the troubles of installing a separate file in the same + directory as the DLL and of retrieving the DLL's directory at + runtime, simply inline the aliases here. */ + + cp = "CP936" "\0" "GBK" "\0" + "CP1361" "\0" "JOHAB" "\0" + "CP20127" "\0" "ASCII" "\0" + "CP20866" "\0" "KOI8-R" "\0" + "CP21866" "\0" "KOI8-RU" "\0" + "CP28591" "\0" "ISO-8859-1" "\0" + "CP28592" "\0" "ISO-8859-2" "\0" + "CP28593" "\0" "ISO-8859-3" "\0" + "CP28594" "\0" "ISO-8859-4" "\0" + "CP28595" "\0" "ISO-8859-5" "\0" + "CP28596" "\0" "ISO-8859-6" "\0" + "CP28597" "\0" "ISO-8859-7" "\0" + "CP28598" "\0" "ISO-8859-8" "\0" + "CP28599" "\0" "ISO-8859-9" "\0" + "CP28605" "\0" "ISO-8859-15" "\0"; +# endif +#endif + + charset_aliases = cp; + } + + return cp; +} + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in config.charset. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ + +#ifdef STATIC +STATIC +#endif +const char * +locale_charset () +{ + const char *codeset; + const char *aliases; + +#if !(defined WIN32 || defined OS2) + +# if HAVE_LANGINFO_CODESET + + /* Most systems support nl_langinfo (CODESET) nowadays. */ + codeset = nl_langinfo (CODESET); + +# else + + /* On old systems which lack it, use setlocale or getenv. */ + const char *locale = NULL; + + /* But most old systems don't have a complete set of locales. Some + (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't + use setlocale here; it would return "C" when it doesn't support the + locale name the user has set. */ +# if HAVE_SETLOCALE && 0 + locale = setlocale (LC_CTYPE, NULL); +# endif + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + } + + /* On some old systems, one used to set locale = "iso8859_1". On others, + you set it to "language_COUNTRY.charset". In any case, we resolve it + through the charset.alias file. */ + codeset = locale; + +# endif + +#elif defined WIN32 + + static char buf[2 + 10 + 1]; + + /* Woe32 has a function returning the locale's codepage as a number. */ + sprintf (buf, "CP%u", GetACP ()); + codeset = buf; + +#elif defined OS2 + + const char *locale; + static char buf[2 + 10 + 1]; + ULONG cp[3]; + ULONG cplen; + + /* Allow user to override the codeset, as set in the operating system, + with standard language environment variables. */ + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + + /* Resolve through the charset.alias file. */ + codeset = locale; + } + else + { + /* OS/2 has a function returning the locale's codepage as a number. */ + if (DosQueryCp (sizeof (cp), cp, &cplen)) + codeset = ""; + else + { + sprintf (buf, "CP%u", cp[0]); + codeset = buf; + } + } + +#endif + + if (codeset == NULL) + /* The canonical name cannot be determined. */ + codeset = ""; + + /* Resolve alias. */ + for (aliases = get_charset_aliases (); + *aliases != '\0'; + aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) + if (strcmp (codeset, aliases) == 0 + || (aliases[0] == '*' && aliases[1] == '\0')) + { + codeset = aliases + strlen (aliases) + 1; + break; + } + + /* Don't return an empty string. GNU libc and GNU libiconv interpret + the empty string as denoting "the locale's character encoding", + thus GNU libiconv would call this function a second time. */ + if (codeset[0] == '\0') + codeset = "ASCII"; + + return codeset; +} diff --git a/intl/localcharset.h b/intl/localcharset.h new file mode 100644 index 000000000..3b137e73c --- /dev/null +++ b/intl/localcharset.h @@ -0,0 +1,42 @@ +/* Determine a canonical name for the current locale's character encoding. + Copyright (C) 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU CHARSET Library. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _LOCALCHARSET_H +#define _LOCALCHARSET_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in config.charset. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ +extern const char * locale_charset (void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _LOCALCHARSET_H */ diff --git a/intl/localealias.c b/intl/localealias.c new file mode 100644 index 000000000..7c4ce58f2 --- /dev/null +++ b/intl/localealias.c @@ -0,0 +1,419 @@ +/* Handle aliases for locale names. + Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Tell glibc's <string.h> to provide a prototype for mempcpy(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <ctype.h> +#include <stdio.h> +#if defined _LIBC || defined HAVE___FSETLOCKING +# include <stdio_ext.h> +#endif +#include <sys/types.h> + +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include <stdlib.h> +#include <string.h> + +#include "gettextP.h" + +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# define strcasecmp __strcasecmp + +# ifndef mempcpy +# define mempcpy __mempcpy +# endif +# define HAVE_MEMPCPY 1 +# define HAVE___FSETLOCKING 1 + +/* We need locking here since we can be called from different places. */ +# include <bits/libc-lock.h> + +__libc_lock_define_initialized (static, lock); +#endif + +#ifndef internal_function +# define internal_function +#endif + +/* Some optimizations for glibc. */ +#ifdef _LIBC +# define FEOF(fp) feof_unlocked (fp) +# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp) +#else +# define FEOF(fp) feof (fp) +# define FGETS(buf, n, fp) fgets (buf, n, fp) +#endif + +/* For those losing systems which don't have `alloca' we have to add + some additional code emulating it. */ +#ifdef HAVE_ALLOCA +# define freea(p) /* nothing */ +#else +# define alloca(n) malloc (n) +# define freea(p) free (p) +#endif + +#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED +# undef fgets +# define fgets(buf, len, s) fgets_unlocked (buf, len, s) +#endif +#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED +# undef feof +# define feof(s) feof_unlocked (s) +#endif + + +struct alias_map +{ + const char *alias; + const char *value; +}; + + +#ifndef _LIBC +# define libc_freeres_ptr(decl) decl +#endif + +libc_freeres_ptr (static char *string_space); +static size_t string_space_act; +static size_t string_space_max; +libc_freeres_ptr (static struct alias_map *map); +static size_t nmap; +static size_t maxmap; + + +/* Prototypes for local functions. */ +static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) + internal_function; +static int extend_alias_table PARAMS ((void)); +static int alias_compare PARAMS ((const struct alias_map *map1, + const struct alias_map *map2)); + + +const char * +_nl_expand_alias (name) + const char *name; +{ + static const char *locale_alias_path; + struct alias_map *retval; + const char *result = NULL; + size_t added; + +#ifdef _LIBC + __libc_lock_lock (lock); +#endif + + if (locale_alias_path == NULL) + locale_alias_path = LOCALE_ALIAS_PATH; + + do + { + struct alias_map item; + + item.alias = name; + + if (nmap > 0) + retval = (struct alias_map *) bsearch (&item, map, nmap, + sizeof (struct alias_map), + (int (*) PARAMS ((const void *, + const void *)) + ) alias_compare); + else + retval = NULL; + + /* We really found an alias. Return the value. */ + if (retval != NULL) + { + result = retval->value; + break; + } + + /* Perhaps we can find another alias file. */ + added = 0; + while (added == 0 && locale_alias_path[0] != '\0') + { + const char *start; + + while (locale_alias_path[0] == PATH_SEPARATOR) + ++locale_alias_path; + start = locale_alias_path; + + while (locale_alias_path[0] != '\0' + && locale_alias_path[0] != PATH_SEPARATOR) + ++locale_alias_path; + + if (start < locale_alias_path) + added = read_alias_file (start, locale_alias_path - start); + } + } + while (added != 0); + +#ifdef _LIBC + __libc_lock_unlock (lock); +#endif + + return result; +} + + +static size_t +internal_function +read_alias_file (fname, fname_len) + const char *fname; + int fname_len; +{ + FILE *fp; + char *full_fname; + size_t added; + static const char aliasfile[] = "/locale.alias"; + + full_fname = (char *) alloca (fname_len + sizeof aliasfile); +#ifdef HAVE_MEMPCPY + mempcpy (mempcpy (full_fname, fname, fname_len), + aliasfile, sizeof aliasfile); +#else + memcpy (full_fname, fname, fname_len); + memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); +#endif + + fp = fopen (relocate (full_fname), "r"); + freea (full_fname); + if (fp == NULL) + return 0; + +#ifdef HAVE___FSETLOCKING + /* No threads present. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); +#endif + + added = 0; + while (!FEOF (fp)) + { + /* It is a reasonable approach to use a fix buffer here because + a) we are only interested in the first two fields + b) these fields must be usable as file names and so must not + be that long + We avoid a multi-kilobyte buffer here since this would use up + stack space which we might not have if the program ran out of + memory. */ + char buf[400]; + char *alias; + char *value; + char *cp; + + if (FGETS (buf, sizeof buf, fp) == NULL) + /* EOF reached. */ + break; + + cp = buf; + /* Ignore leading white space. */ + while (isspace ((unsigned char) cp[0])) + ++cp; + + /* A leading '#' signals a comment line. */ + if (cp[0] != '\0' && cp[0] != '#') + { + alias = cp++; + while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) + ++cp; + /* Terminate alias name. */ + if (cp[0] != '\0') + *cp++ = '\0'; + + /* Now look for the beginning of the value. */ + while (isspace ((unsigned char) cp[0])) + ++cp; + + if (cp[0] != '\0') + { + size_t alias_len; + size_t value_len; + + value = cp++; + while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) + ++cp; + /* Terminate value. */ + if (cp[0] == '\n') + { + /* This has to be done to make the following test + for the end of line possible. We are looking for + the terminating '\n' which do not overwrite here. */ + *cp++ = '\0'; + *cp = '\n'; + } + else if (cp[0] != '\0') + *cp++ = '\0'; + + if (nmap >= maxmap) + if (__builtin_expect (extend_alias_table (), 0)) + return added; + + alias_len = strlen (alias) + 1; + value_len = strlen (value) + 1; + + if (string_space_act + alias_len + value_len > string_space_max) + { + /* Increase size of memory pool. */ + size_t new_size = (string_space_max + + (alias_len + value_len > 1024 + ? alias_len + value_len : 1024)); + char *new_pool = (char *) realloc (string_space, new_size); + if (new_pool == NULL) + return added; + + if (__builtin_expect (string_space != new_pool, 0)) + { + size_t i; + + for (i = 0; i < nmap; i++) + { + map[i].alias += new_pool - string_space; + map[i].value += new_pool - string_space; + } + } + + string_space = new_pool; + string_space_max = new_size; + } + + map[nmap].alias = memcpy (&string_space[string_space_act], + alias, alias_len); + string_space_act += alias_len; + + map[nmap].value = memcpy (&string_space[string_space_act], + value, value_len); + string_space_act += value_len; + + ++nmap; + ++added; + } + } + + /* Possibly not the whole line fits into the buffer. Ignore + the rest of the line. */ + while (strchr (buf, '\n') == NULL) + if (FGETS (buf, sizeof buf, fp) == NULL) + /* Make sure the inner loop will be left. The outer loop + will exit at the `feof' test. */ + break; + } + + /* Should we test for ferror()? I think we have to silently ignore + errors. --drepper */ + fclose (fp); + + if (added > 0) + qsort (map, nmap, sizeof (struct alias_map), + (int (*) PARAMS ((const void *, const void *))) alias_compare); + + return added; +} + + +static int +extend_alias_table () +{ + size_t new_size; + struct alias_map *new_map; + + new_size = maxmap == 0 ? 100 : 2 * maxmap; + new_map = (struct alias_map *) realloc (map, (new_size + * sizeof (struct alias_map))); + if (new_map == NULL) + /* Simply don't extend: we don't have any more core. */ + return -1; + + map = new_map; + maxmap = new_size; + return 0; +} + + +static int +alias_compare (map1, map2) + const struct alias_map *map1; + const struct alias_map *map2; +{ +#if defined _LIBC || defined HAVE_STRCASECMP + return strcasecmp (map1->alias, map2->alias); +#else + const unsigned char *p1 = (const unsigned char *) map1->alias; + const unsigned char *p2 = (const unsigned char *) map2->alias; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + /* I know this seems to be odd but the tolower() function in + some systems libc cannot handle nonalpha characters. */ + c1 = isupper (*p1) ? tolower (*p1) : *p1; + c2 = isupper (*p2) ? tolower (*p2) : *p2; + if (c1 == '\0') + break; + ++p1; + ++p2; + } + while (c1 == c2); + + return c1 - c2; +#endif +} diff --git a/intl/localename.c b/intl/localename.c new file mode 100644 index 000000000..faacecd50 --- /dev/null +++ b/intl/localename.c @@ -0,0 +1,772 @@ +/* Determine the current selected locale. + Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */ +/* Win32 code written by Tor Lillqvist <tml@iki.fi>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <locale.h> + +#if defined _WIN32 || defined __WIN32__ +# undef WIN32 /* avoid warning on mingw32 */ +# define WIN32 +#endif + +#ifdef WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +/* Mingw headers don't have latest language and sublanguage codes. */ +# ifndef LANG_AFRIKAANS +# define LANG_AFRIKAANS 0x36 +# endif +# ifndef LANG_ALBANIAN +# define LANG_ALBANIAN 0x1c +# endif +# ifndef LANG_ARABIC +# define LANG_ARABIC 0x01 +# endif +# ifndef LANG_ARMENIAN +# define LANG_ARMENIAN 0x2b +# endif +# ifndef LANG_ASSAMESE +# define LANG_ASSAMESE 0x4d +# endif +# ifndef LANG_AZERI +# define LANG_AZERI 0x2c +# endif +# ifndef LANG_BASQUE +# define LANG_BASQUE 0x2d +# endif +# ifndef LANG_BELARUSIAN +# define LANG_BELARUSIAN 0x23 +# endif +# ifndef LANG_BENGALI +# define LANG_BENGALI 0x45 +# endif +# ifndef LANG_CATALAN +# define LANG_CATALAN 0x03 +# endif +# ifndef LANG_DIVEHI +# define LANG_DIVEHI 0x65 +# endif +# ifndef LANG_ESTONIAN +# define LANG_ESTONIAN 0x25 +# endif +# ifndef LANG_FAEROESE +# define LANG_FAEROESE 0x38 +# endif +# ifndef LANG_FARSI +# define LANG_FARSI 0x29 +# endif +# ifndef LANG_GALICIAN +# define LANG_GALICIAN 0x56 +# endif +# ifndef LANG_GEORGIAN +# define LANG_GEORGIAN 0x37 +# endif +# ifndef LANG_GUJARATI +# define LANG_GUJARATI 0x47 +# endif +# ifndef LANG_HEBREW +# define LANG_HEBREW 0x0d +# endif +# ifndef LANG_HINDI +# define LANG_HINDI 0x39 +# endif +# ifndef LANG_INDONESIAN +# define LANG_INDONESIAN 0x21 +# endif +# ifndef LANG_KANNADA +# define LANG_KANNADA 0x4b +# endif +# ifndef LANG_KASHMIRI +# define LANG_KASHMIRI 0x60 +# endif +# ifndef LANG_KAZAK +# define LANG_KAZAK 0x3f +# endif +# ifndef LANG_KONKANI +# define LANG_KONKANI 0x57 +# endif +# ifndef LANG_KYRGYZ +# define LANG_KYRGYZ 0x40 +# endif +# ifndef LANG_LATVIAN +# define LANG_LATVIAN 0x26 +# endif +# ifndef LANG_LITHUANIAN +# define LANG_LITHUANIAN 0x27 +# endif +# ifndef LANG_MACEDONIAN +# define LANG_MACEDONIAN 0x2f +# endif +# ifndef LANG_MALAY +# define LANG_MALAY 0x3e +# endif +# ifndef LANG_MALAYALAM +# define LANG_MALAYALAM 0x4c +# endif +# ifndef LANG_MANIPURI +# define LANG_MANIPURI 0x58 +# endif +# ifndef LANG_MARATHI +# define LANG_MARATHI 0x4e +# endif +# ifndef LANG_MONGOLIAN +# define LANG_MONGOLIAN 0x50 +# endif +# ifndef LANG_NEPALI +# define LANG_NEPALI 0x61 +# endif +# ifndef LANG_ORIYA +# define LANG_ORIYA 0x48 +# endif +# ifndef LANG_PUNJABI +# define LANG_PUNJABI 0x46 +# endif +# ifndef LANG_SANSKRIT +# define LANG_SANSKRIT 0x4f +# endif +# ifndef LANG_SERBIAN +# define LANG_SERBIAN 0x1a +# endif +# ifndef LANG_SINDHI +# define LANG_SINDHI 0x59 +# endif +# ifndef LANG_SLOVAK +# define LANG_SLOVAK 0x1b +# endif +# ifndef LANG_SORBIAN +# define LANG_SORBIAN 0x2e +# endif +# ifndef LANG_SWAHILI +# define LANG_SWAHILI 0x41 +# endif +# ifndef LANG_SYRIAC +# define LANG_SYRIAC 0x5a +# endif +# ifndef LANG_TAMIL +# define LANG_TAMIL 0x49 +# endif +# ifndef LANG_TATAR +# define LANG_TATAR 0x44 +# endif +# ifndef LANG_TELUGU +# define LANG_TELUGU 0x4a +# endif +# ifndef LANG_THAI +# define LANG_THAI 0x1e +# endif +# ifndef LANG_UKRAINIAN +# define LANG_UKRAINIAN 0x22 +# endif +# ifndef LANG_URDU +# define LANG_URDU 0x20 +# endif +# ifndef LANG_UZBEK +# define LANG_UZBEK 0x43 +# endif +# ifndef LANG_VIETNAMESE +# define LANG_VIETNAMESE 0x2a +# endif +# ifndef SUBLANG_ARABIC_SAUDI_ARABIA +# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 +# endif +# ifndef SUBLANG_ARABIC_IRAQ +# define SUBLANG_ARABIC_IRAQ 0x02 +# endif +# ifndef SUBLANG_ARABIC_EGYPT +# define SUBLANG_ARABIC_EGYPT 0x03 +# endif +# ifndef SUBLANG_ARABIC_LIBYA +# define SUBLANG_ARABIC_LIBYA 0x04 +# endif +# ifndef SUBLANG_ARABIC_ALGERIA +# define SUBLANG_ARABIC_ALGERIA 0x05 +# endif +# ifndef SUBLANG_ARABIC_MOROCCO +# define SUBLANG_ARABIC_MOROCCO 0x06 +# endif +# ifndef SUBLANG_ARABIC_TUNISIA +# define SUBLANG_ARABIC_TUNISIA 0x07 +# endif +# ifndef SUBLANG_ARABIC_OMAN +# define SUBLANG_ARABIC_OMAN 0x08 +# endif +# ifndef SUBLANG_ARABIC_YEMEN +# define SUBLANG_ARABIC_YEMEN 0x09 +# endif +# ifndef SUBLANG_ARABIC_SYRIA +# define SUBLANG_ARABIC_SYRIA 0x0a +# endif +# ifndef SUBLANG_ARABIC_JORDAN +# define SUBLANG_ARABIC_JORDAN 0x0b +# endif +# ifndef SUBLANG_ARABIC_LEBANON +# define SUBLANG_ARABIC_LEBANON 0x0c +# endif +# ifndef SUBLANG_ARABIC_KUWAIT +# define SUBLANG_ARABIC_KUWAIT 0x0d +# endif +# ifndef SUBLANG_ARABIC_UAE +# define SUBLANG_ARABIC_UAE 0x0e +# endif +# ifndef SUBLANG_ARABIC_BAHRAIN +# define SUBLANG_ARABIC_BAHRAIN 0x0f +# endif +# ifndef SUBLANG_ARABIC_QATAR +# define SUBLANG_ARABIC_QATAR 0x10 +# endif +# ifndef SUBLANG_AZERI_LATIN +# define SUBLANG_AZERI_LATIN 0x01 +# endif +# ifndef SUBLANG_AZERI_CYRILLIC +# define SUBLANG_AZERI_CYRILLIC 0x02 +# endif +# ifndef SUBLANG_CHINESE_MACAU +# define SUBLANG_CHINESE_MACAU 0x05 +# endif +# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA +# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 +# endif +# ifndef SUBLANG_ENGLISH_JAMAICA +# define SUBLANG_ENGLISH_JAMAICA 0x08 +# endif +# ifndef SUBLANG_ENGLISH_CARIBBEAN +# define SUBLANG_ENGLISH_CARIBBEAN 0x09 +# endif +# ifndef SUBLANG_ENGLISH_BELIZE +# define SUBLANG_ENGLISH_BELIZE 0x0a +# endif +# ifndef SUBLANG_ENGLISH_TRINIDAD +# define SUBLANG_ENGLISH_TRINIDAD 0x0b +# endif +# ifndef SUBLANG_ENGLISH_ZIMBABWE +# define SUBLANG_ENGLISH_ZIMBABWE 0x0c +# endif +# ifndef SUBLANG_ENGLISH_PHILIPPINES +# define SUBLANG_ENGLISH_PHILIPPINES 0x0d +# endif +# ifndef SUBLANG_FRENCH_LUXEMBOURG +# define SUBLANG_FRENCH_LUXEMBOURG 0x05 +# endif +# ifndef SUBLANG_FRENCH_MONACO +# define SUBLANG_FRENCH_MONACO 0x06 +# endif +# ifndef SUBLANG_GERMAN_LUXEMBOURG +# define SUBLANG_GERMAN_LUXEMBOURG 0x04 +# endif +# ifndef SUBLANG_GERMAN_LIECHTENSTEIN +# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +# endif +# ifndef SUBLANG_KASHMIRI_INDIA +# define SUBLANG_KASHMIRI_INDIA 0x02 +# endif +# ifndef SUBLANG_MALAY_MALAYSIA +# define SUBLANG_MALAY_MALAYSIA 0x01 +# endif +# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM +# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +# endif +# ifndef SUBLANG_NEPALI_INDIA +# define SUBLANG_NEPALI_INDIA 0x02 +# endif +# ifndef SUBLANG_SERBIAN_LATIN +# define SUBLANG_SERBIAN_LATIN 0x02 +# endif +# ifndef SUBLANG_SERBIAN_CYRILLIC +# define SUBLANG_SERBIAN_CYRILLIC 0x03 +# endif +# ifndef SUBLANG_SPANISH_GUATEMALA +# define SUBLANG_SPANISH_GUATEMALA 0x04 +# endif +# ifndef SUBLANG_SPANISH_COSTA_RICA +# define SUBLANG_SPANISH_COSTA_RICA 0x05 +# endif +# ifndef SUBLANG_SPANISH_PANAMA +# define SUBLANG_SPANISH_PANAMA 0x06 +# endif +# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC +# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +# endif +# ifndef SUBLANG_SPANISH_VENEZUELA +# define SUBLANG_SPANISH_VENEZUELA 0x08 +# endif +# ifndef SUBLANG_SPANISH_COLOMBIA +# define SUBLANG_SPANISH_COLOMBIA 0x09 +# endif +# ifndef SUBLANG_SPANISH_PERU +# define SUBLANG_SPANISH_PERU 0x0a +# endif +# ifndef SUBLANG_SPANISH_ARGENTINA +# define SUBLANG_SPANISH_ARGENTINA 0x0b +# endif +# ifndef SUBLANG_SPANISH_ECUADOR +# define SUBLANG_SPANISH_ECUADOR 0x0c +# endif +# ifndef SUBLANG_SPANISH_CHILE +# define SUBLANG_SPANISH_CHILE 0x0d +# endif +# ifndef SUBLANG_SPANISH_URUGUAY +# define SUBLANG_SPANISH_URUGUAY 0x0e +# endif +# ifndef SUBLANG_SPANISH_PARAGUAY +# define SUBLANG_SPANISH_PARAGUAY 0x0f +# endif +# ifndef SUBLANG_SPANISH_BOLIVIA +# define SUBLANG_SPANISH_BOLIVIA 0x10 +# endif +# ifndef SUBLANG_SPANISH_EL_SALVADOR +# define SUBLANG_SPANISH_EL_SALVADOR 0x11 +# endif +# ifndef SUBLANG_SPANISH_HONDURAS +# define SUBLANG_SPANISH_HONDURAS 0x12 +# endif +# ifndef SUBLANG_SPANISH_NICARAGUA +# define SUBLANG_SPANISH_NICARAGUA 0x13 +# endif +# ifndef SUBLANG_SPANISH_PUERTO_RICO +# define SUBLANG_SPANISH_PUERTO_RICO 0x14 +# endif +# ifndef SUBLANG_SWEDISH_FINLAND +# define SUBLANG_SWEDISH_FINLAND 0x02 +# endif +# ifndef SUBLANG_URDU_PAKISTAN +# define SUBLANG_URDU_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_URDU_INDIA +# define SUBLANG_URDU_INDIA 0x02 +# endif +# ifndef SUBLANG_UZBEK_LATIN +# define SUBLANG_UZBEK_LATIN 0x01 +# endif +# ifndef SUBLANG_UZBEK_CYRILLIC +# define SUBLANG_UZBEK_CYRILLIC 0x02 +# endif +#endif + +/* XPG3 defines the result of 'setlocale (category, NULL)' as: + "Directs 'setlocale()' to query 'category' and return the current + setting of 'local'." + However it does not specify the exact format. Neither do SUSV2 and + ISO C 99. So we can use this feature only on selected systems (e.g. + those using GNU C Library). */ +#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2) +# define HAVE_LOCALE_NULL +#endif + +/* Determine the current locale's name, and canonicalize it into XPG syntax + language[_territory[.codeset]][@modifier] + The codeset part in the result is not reliable; the locale_charset() + should be used for codeset information instead. + The result must not be freed; it is statically allocated. */ + +const char * +_nl_locale_name (category, categoryname) + int category; + const char *categoryname; +{ + const char *retval; + +#ifndef WIN32 + + /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. + On some systems this can be done by the 'setlocale' function itself. */ +# if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL + retval = setlocale (category, NULL); +# else + /* Setting of LC_ALL overwrites all other. */ + retval = getenv ("LC_ALL"); + if (retval == NULL || retval[0] == '\0') + { + /* Next comes the name of the desired category. */ + retval = getenv (categoryname); + if (retval == NULL || retval[0] == '\0') + { + /* Last possibility is the LANG environment variable. */ + retval = getenv ("LANG"); + if (retval == NULL || retval[0] == '\0') + /* We use C as the default domain. POSIX says this is + implementation defined. */ + retval = "C"; + } + } +# endif + + return retval; + +#else /* WIN32 */ + + /* Return an XPG style locale name language[_territory][@modifier]. + Don't even bother determining the codeset; it's not useful in this + context, because message catalogs are not specific to a single + codeset. */ + + LCID lcid; + LANGID langid; + int primary, sub; + + /* Let the user override the system settings through environment + variables, as on POSIX systems. */ + retval = getenv ("LC_ALL"); + if (retval != NULL && retval[0] != '\0') + return retval; + retval = getenv (categoryname); + if (retval != NULL && retval[0] != '\0') + return retval; + retval = getenv ("LANG"); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* Use native Win32 API locale ID. */ + lcid = GetThreadLocale (); + + /* Strip off the sorting rules, keep only the language part. */ + langid = LANGIDFROMLCID (lcid); + + /* Split into language and territory part. */ + primary = PRIMARYLANGID (langid); + sub = SUBLANGID (langid); + + /* Dispatch on language. + See also http://www.unicode.org/unicode/onlinedat/languages.html . + For details about languages, see http://www.ethnologue.com/ . */ + switch (primary) + { + case LANG_AFRIKAANS: return "af_ZA"; + case LANG_ALBANIAN: return "sq_AL"; + case 0x5e: /* AMHARIC */ return "am_ET"; + case LANG_ARABIC: + switch (sub) + { + case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA"; + case SUBLANG_ARABIC_IRAQ: return "ar_IQ"; + case SUBLANG_ARABIC_EGYPT: return "ar_EG"; + case SUBLANG_ARABIC_LIBYA: return "ar_LY"; + case SUBLANG_ARABIC_ALGERIA: return "ar_DZ"; + case SUBLANG_ARABIC_MOROCCO: return "ar_MA"; + case SUBLANG_ARABIC_TUNISIA: return "ar_TN"; + case SUBLANG_ARABIC_OMAN: return "ar_OM"; + case SUBLANG_ARABIC_YEMEN: return "ar_YE"; + case SUBLANG_ARABIC_SYRIA: return "ar_SY"; + case SUBLANG_ARABIC_JORDAN: return "ar_JO"; + case SUBLANG_ARABIC_LEBANON: return "ar_LB"; + case SUBLANG_ARABIC_KUWAIT: return "ar_KW"; + case SUBLANG_ARABIC_UAE: return "ar_AE"; + case SUBLANG_ARABIC_BAHRAIN: return "ar_BH"; + case SUBLANG_ARABIC_QATAR: return "ar_QA"; + } + return "ar"; + case LANG_ARMENIAN: return "hy_AM"; + case LANG_ASSAMESE: return "as_IN"; + case LANG_AZERI: + switch (sub) + { + /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ + case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; + case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; + } + return "az"; + case LANG_BASQUE: + return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ + case LANG_BELARUSIAN: return "be_BY"; + case LANG_BENGALI: return "bn_IN"; + case LANG_BULGARIAN: return "bg_BG"; + case 0x55: /* BURMESE */ return "my_MM"; + case 0x53: /* CAMBODIAN */ return "km_KH"; + case LANG_CATALAN: return "ca_ES"; + case 0x5c: /* CHEROKEE */ return "chr_US"; + case LANG_CHINESE: + switch (sub) + { + case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW"; + case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN"; + case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; + case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; + case SUBLANG_CHINESE_MACAU: return "zh_MO"; + } + return "zh"; + case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN + * What used to be called Serbo-Croatian + * should really now be two separate + * languages because of political reasons. + * (Says tml, who knows nothing about Serbian + * or Croatian.) + * (I can feel those flames coming already.) + */ + switch (sub) + { + case SUBLANG_DEFAULT: return "hr_HR"; + case SUBLANG_SERBIAN_LATIN: return "sr_YU"; + case SUBLANG_SERBIAN_CYRILLIC: return "sr_YU@cyrillic"; + } + return "hr"; + case LANG_CZECH: return "cs_CZ"; + case LANG_DANISH: return "da_DK"; + case LANG_DIVEHI: return "div_MV"; + case LANG_DUTCH: + switch (sub) + { + case SUBLANG_DUTCH: return "nl_NL"; + case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; + } + return "nl"; + case 0x66: /* EDO */ return "bin_NG"; + case LANG_ENGLISH: + switch (sub) + { + /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought + * English was the language spoken in England. + * Oh well. + */ + case SUBLANG_ENGLISH_US: return "en_US"; + case SUBLANG_ENGLISH_UK: return "en_GB"; + case SUBLANG_ENGLISH_AUS: return "en_AU"; + case SUBLANG_ENGLISH_CAN: return "en_CA"; + case SUBLANG_ENGLISH_NZ: return "en_NZ"; + case SUBLANG_ENGLISH_EIRE: return "en_IE"; + case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA"; + case SUBLANG_ENGLISH_JAMAICA: return "en_JM"; + case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */ + case SUBLANG_ENGLISH_BELIZE: return "en_BZ"; + case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; + case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; + case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; + } + return "en"; + case LANG_ESTONIAN: return "et_EE"; + case LANG_FAEROESE: return "fo_FO"; + case LANG_FARSI: return "fa_IR"; + case LANG_FINNISH: return "fi_FI"; + case LANG_FRENCH: + switch (sub) + { + case SUBLANG_FRENCH: return "fr_FR"; + case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE"; + case SUBLANG_FRENCH_CANADIAN: return "fr_CA"; + case SUBLANG_FRENCH_SWISS: return "fr_CH"; + case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; + case SUBLANG_FRENCH_MONACO: return "fr_MC"; + } + return "fr"; + case 0x62: /* FRISIAN */ return "fy_NL"; + case 0x67: /* FULFULDE */ return "ful_NG"; + case 0x3c: /* GAELIC */ + switch (sub) + { + case 0x01: /* SCOTTISH */ return "gd_GB"; + case 0x02: /* IRISH */ return "ga_IE"; + } + return "C"; + case LANG_GALICIAN: return "gl_ES"; + case LANG_GEORGIAN: return "ka_GE"; + case LANG_GERMAN: + switch (sub) + { + case SUBLANG_GERMAN: return "de_DE"; + case SUBLANG_GERMAN_SWISS: return "de_CH"; + case SUBLANG_GERMAN_AUSTRIAN: return "de_AT"; + case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU"; + case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI"; + } + return "de"; + case LANG_GREEK: return "el_GR"; + case 0x74: /* GUARANI */ return "gn_PY"; + case LANG_GUJARATI: return "gu_IN"; + case 0x68: /* HAUSA */ return "ha_NG"; + case 0x75: /* HAWAIIAN */ + /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) + or Hawaii Creole English ("cpe_US", 600000 speakers)? */ + return "cpe_US"; + case LANG_HEBREW: return "he_IL"; + case LANG_HINDI: return "hi_IN"; + case LANG_HUNGARIAN: return "hu_HU"; + case 0x69: /* IBIBIO */ return "nic_NG"; + case LANG_ICELANDIC: return "is_IS"; + case 0x70: /* IGBO */ return "ibo_NG"; + case LANG_INDONESIAN: return "id_ID"; + case 0x5d: /* INUKTITUT */ return "iu_CA"; + case LANG_ITALIAN: + switch (sub) + { + case SUBLANG_ITALIAN: return "it_IT"; + case SUBLANG_ITALIAN_SWISS: return "it_CH"; + } + return "it"; + case LANG_JAPANESE: return "ja_JP"; + case LANG_KANNADA: return "kn_IN"; + case 0x71: /* KANURI */ return "kau_NG"; + case LANG_KASHMIRI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ks_PK"; + case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; + } + return "ks"; + case LANG_KAZAK: return "kk_KZ"; + case LANG_KONKANI: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "kok_IN"; + case LANG_KOREAN: return "ko_KR"; + case LANG_KYRGYZ: return "ky_KG"; + case 0x54: /* LAO */ return "lo_LA"; + case 0x76: /* LATIN */ return "la_VA"; + case LANG_LATVIAN: return "lv_LV"; + case LANG_LITHUANIAN: return "lt_LT"; + case LANG_MACEDONIAN: return "mk_MK"; + case LANG_MALAY: + switch (sub) + { + case SUBLANG_MALAY_MALAYSIA: return "ms_MY"; + case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN"; + } + return "ms"; + case LANG_MALAYALAM: return "ml_IN"; + case 0x3a: /* MALTESE */ return "mt_MT"; + case LANG_MANIPURI: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "mni_IN"; + case LANG_MARATHI: return "mr_IN"; + case LANG_MONGOLIAN: + return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */ + case LANG_NEPALI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ne_NP"; + case SUBLANG_NEPALI_INDIA: return "ne_IN"; + } + return "ne"; + case LANG_NORWEGIAN: + switch (sub) + { + case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO"; + case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; + } + return "no"; + case LANG_ORIYA: return "or_IN"; + case 0x72: /* OROMO */ return "om_ET"; + case 0x79: /* PAPIAMENTU */ return "pap_AN"; + case 0x63: /* PASHTO */ + return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ + case LANG_POLISH: return "pl_PL"; + case LANG_PORTUGUESE: + switch (sub) + { + case SUBLANG_PORTUGUESE: return "pt_PT"; + /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. + Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ + case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; + } + return "pt"; + case LANG_PUNJABI: return "pa_IN"; + case 0x17: /* RHAETO-ROMANCE */ return "rm_CH"; + case LANG_ROMANIAN: return "ro_RO"; + case LANG_RUSSIAN: + return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA". */ + case 0x3b: /* SAMI */ return "se_NO"; + case LANG_SANSKRIT: return "sa_IN"; + case LANG_SINDHI: return "sd"; + case 0x5b: /* SINHALESE */ return "si_LK"; + case LANG_SLOVAK: return "sk_SK"; + case LANG_SLOVENIAN: return "sl_SI"; + case 0x77: /* SOMALI */ return "so_SO"; + case LANG_SORBIAN: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "wen_DE"; + case LANG_SPANISH: + switch (sub) + { + case SUBLANG_SPANISH: return "es_ES"; + case SUBLANG_SPANISH_MEXICAN: return "es_MX"; + case SUBLANG_SPANISH_MODERN: + return "es_ES@modern"; /* not seen on Unix */ + case SUBLANG_SPANISH_GUATEMALA: return "es_GT"; + case SUBLANG_SPANISH_COSTA_RICA: return "es_CR"; + case SUBLANG_SPANISH_PANAMA: return "es_PA"; + case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO"; + case SUBLANG_SPANISH_VENEZUELA: return "es_VE"; + case SUBLANG_SPANISH_COLOMBIA: return "es_CO"; + case SUBLANG_SPANISH_PERU: return "es_PE"; + case SUBLANG_SPANISH_ARGENTINA: return "es_AR"; + case SUBLANG_SPANISH_ECUADOR: return "es_EC"; + case SUBLANG_SPANISH_CHILE: return "es_CL"; + case SUBLANG_SPANISH_URUGUAY: return "es_UY"; + case SUBLANG_SPANISH_PARAGUAY: return "es_PY"; + case SUBLANG_SPANISH_BOLIVIA: return "es_BO"; + case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV"; + case SUBLANG_SPANISH_HONDURAS: return "es_HN"; + case SUBLANG_SPANISH_NICARAGUA: return "es_NI"; + case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; + } + return "es"; + case 0x30: /* SUTU */ return "bnt_TZ"; + case LANG_SWAHILI: return "sw_KE"; + case LANG_SWEDISH: + switch (sub) + { + case SUBLANG_DEFAULT: return "sv_SE"; + case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; + } + return "sv"; + case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */ + case 0x64: /* TAGALOG */ return "tl_PH"; + case 0x28: /* TAJIK */ return "tg_TJ"; + case 0x5f: /* TAMAZIGHT */ return "ber_MA"; + case LANG_TAMIL: + return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ + case LANG_TATAR: return "tt_RU"; + case LANG_TELUGU: return "te_IN"; + case LANG_THAI: return "th_TH"; + case 0x51: /* TIBETAN */ return "bo_CN"; + case 0x73: /* TIGRINYA */ return "ti_ET"; + case 0x31: /* TSONGA */ return "ts_ZA"; + case LANG_TURKISH: return "tr_TR"; + case 0x42: /* TURKMEN */ return "tk_TM"; + case LANG_UKRAINIAN: return "uk_UA"; + case LANG_URDU: + switch (sub) + { + case SUBLANG_URDU_PAKISTAN: return "ur_PK"; + case SUBLANG_URDU_INDIA: return "ur_IN"; + } + return "ur"; + case LANG_UZBEK: + switch (sub) + { + /* FIXME: Adjust this when Uzbek locales appear on Unix. */ + case SUBLANG_UZBEK_LATIN: return "uz_UZ@latin"; + case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; + } + return "uz"; + case 0x33: /* VENDA */ return "ven_ZA"; + case LANG_VIETNAMESE: return "vi_VN"; + case 0x52: /* WELSH */ return "cy_GB"; + case 0x34: /* XHOSA */ return "xh_ZA"; + case 0x78: /* YI */ return "sit_CN"; + case 0x3d: /* YIDDISH */ return "yi_IL"; + case 0x6a: /* YORUBA */ return "yo_NG"; + case 0x35: /* ZULU */ return "zu_ZA"; + default: return "C"; + } + +#endif +} diff --git a/intl/log.c b/intl/log.c new file mode 100644 index 000000000..9c84791b9 --- /dev/null +++ b/intl/log.c @@ -0,0 +1,104 @@ +/* Log file output. + Copyright (C) 2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Written by Bruno Haible <bruno@clisp.org>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Print an ASCII string with quotes and escape sequences where needed. */ +static void +print_escaped (stream, str) + FILE *stream; + const char *str; +{ + putc ('"', stream); + for (; *str != '\0'; str++) + if (*str == '\n') + { + fputs ("\\n\"", stream); + if (str[1] == '\0') + return; + fputs ("\n\"", stream); + } + else + { + if (*str == '"' || *str == '\\') + putc ('\\', stream); + putc (*str, stream); + } + putc ('"', stream); +} + +/* Add to the log file an entry denoting a failed translation. */ +void +_nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural) + const char *logfilename; + const char *domainname; + const char *msgid1; + const char *msgid2; + int plural; +{ + static char *last_logfilename = NULL; + static FILE *last_logfile = NULL; + FILE *logfile; + + /* Can we reuse the last opened logfile? */ + if (last_logfilename == NULL || strcmp (logfilename, last_logfilename) != 0) + { + /* Close the last used logfile. */ + if (last_logfilename != NULL) + { + if (last_logfile != NULL) + { + fclose (last_logfile); + last_logfile = NULL; + } + free (last_logfilename); + last_logfilename = NULL; + } + /* Open the logfile. */ + last_logfilename = (char *) malloc (strlen (logfilename) + 1); + if (last_logfilename == NULL) + return; + strcpy (last_logfilename, logfilename); + last_logfile = fopen (logfilename, "a"); + if (last_logfile == NULL) + return; + } + logfile = last_logfile; + + fprintf (logfile, "domain "); + print_escaped (logfile, domainname); + fprintf (logfile, "\nmsgid "); + print_escaped (logfile, msgid1); + if (plural) + { + fprintf (logfile, "\nmsgid_plural "); + print_escaped (logfile, msgid2); + fprintf (logfile, "\nmsgstr[0] \"\"\n"); + } + else + fprintf (logfile, "\nmsgstr \"\"\n"); + putc ('\n', logfile); +} diff --git a/intl/ngettext.c b/intl/ngettext.c new file mode 100644 index 000000000..17a27f4aa --- /dev/null +++ b/intl/ngettext.c @@ -0,0 +1,68 @@ +/* Implementation of ngettext(3) function. + Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 + +#ifdef _LIBC +# define __need_NULL +# include <stddef.h> +#else +# include <stdlib.h> /* Just for NULL. */ +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif + +#include <locale.h> + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define NGETTEXT __ngettext +# define DCNGETTEXT __dcngettext +#else +# define NGETTEXT libintl_ngettext +# define DCNGETTEXT libintl_dcngettext +#endif + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +char * +NGETTEXT (msgid1, msgid2, n) + const char *msgid1; + const char *msgid2; + unsigned long int n; +{ + return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__ngettext, ngettext); +#endif diff --git a/intl/os2compat.c b/intl/os2compat.c new file mode 100644 index 000000000..c8dc33e7c --- /dev/null +++ b/intl/os2compat.c @@ -0,0 +1,98 @@ +/* OS/2 compatibility functions. + Copyright (C) 2001-2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +#define OS2_AWARE +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> + +/* A version of getenv() that works from DLLs */ +extern unsigned long DosScanEnv (const unsigned char *pszName, unsigned char **ppszValue); + +char * +_nl_getenv (const char *name) +{ + unsigned char *value; + if (DosScanEnv (name, &value)) + return NULL; + else + return value; +} + +/* A fixed size buffer. */ +char libintl_nl_default_dirname[MAXPATHLEN+1]; + +char *_nlos2_libdir = NULL; +char *_nlos2_localealiaspath = NULL; +char *_nlos2_localedir = NULL; + +static __attribute__((constructor)) void +nlos2_initialize () +{ + char *root = getenv ("UNIXROOT"); + char *gnulocaledir = getenv ("GNULOCALEDIR"); + + _nlos2_libdir = gnulocaledir; + if (!_nlos2_libdir) + { + if (root) + { + size_t sl = strlen (root); + _nlos2_libdir = (char *) malloc (sl + strlen (LIBDIR) + 1); + memcpy (_nlos2_libdir, root, sl); + memcpy (_nlos2_libdir + sl, LIBDIR, strlen (LIBDIR) + 1); + } + else + _nlos2_libdir = LIBDIR; + } + + _nlos2_localealiaspath = gnulocaledir; + if (!_nlos2_localealiaspath) + { + if (root) + { + size_t sl = strlen (root); + _nlos2_localealiaspath = (char *) malloc (sl + strlen (LOCALE_ALIAS_PATH) + 1); + memcpy (_nlos2_localealiaspath, root, sl); + memcpy (_nlos2_localealiaspath + sl, LOCALE_ALIAS_PATH, strlen (LOCALE_ALIAS_PATH) + 1); + } + else + _nlos2_localealiaspath = LOCALE_ALIAS_PATH; + } + + _nlos2_localedir = gnulocaledir; + if (!_nlos2_localedir) + { + if (root) + { + size_t sl = strlen (root); + _nlos2_localedir = (char *) malloc (sl + strlen (LOCALEDIR) + 1); + memcpy (_nlos2_localedir, root, sl); + memcpy (_nlos2_localedir + sl, LOCALEDIR, strlen (LOCALEDIR) + 1); + } + else + _nlos2_localedir = LOCALEDIR; + } + + if (strlen (_nlos2_localedir) <= MAXPATHLEN) + strcpy (libintl_nl_default_dirname, _nlos2_localedir); +} diff --git a/intl/os2compat.h b/intl/os2compat.h new file mode 100644 index 000000000..4f74e8c03 --- /dev/null +++ b/intl/os2compat.h @@ -0,0 +1,46 @@ +/* OS/2 compatibility defines. + This file is intended to be included from config.h + Copyright (C) 2001-2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* When included from os2compat.h we need all the original definitions */ +#ifndef OS2_AWARE + +#undef LIBDIR +#define LIBDIR _nlos2_libdir +extern char *_nlos2_libdir; + +#undef LOCALEDIR +#define LOCALEDIR _nlos2_localedir +extern char *_nlos2_localedir; + +#undef LOCALE_ALIAS_PATH +#define LOCALE_ALIAS_PATH _nlos2_localealiaspath +extern char *_nlos2_localealiaspath; + +#endif + +#undef HAVE_STRCASECMP +#define HAVE_STRCASECMP 1 +#define strcasecmp stricmp +#define strncasecmp strnicmp + +/* We have our own getenv() which works even if library is compiled as DLL */ +#define getenv _nl_getenv + +/* Older versions of gettext used -1 as the value of LC_MESSAGES */ +#define LC_MESSAGES_COMPAT (-1) diff --git a/intl/osdep.c b/intl/osdep.c new file mode 100644 index 000000000..b37259838 --- /dev/null +++ b/intl/osdep.c @@ -0,0 +1,24 @@ +/* OS dependent parts of libintl. + Copyright (C) 2001-2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 defined __EMX__ +# include "os2compat.c" +#else +/* Avoid AIX compiler warning. */ +typedef int dummy; +#endif diff --git a/intl/plural-exp.c b/intl/plural-exp.c new file mode 100644 index 000000000..c937c011a --- /dev/null +++ b/intl/plural-exp.c @@ -0,0 +1,156 @@ +/* Expression parsing for plural form selection. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Written by Ulrich Drepper <drepper@cygnus.com>, 2000. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "plural-exp.h" + +#if (defined __GNUC__ && !defined __APPLE_CC__) \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) + +/* These structs are the constant expression for the germanic plural + form determination. It represents the expression "n != 1". */ +static const struct expression plvar = +{ + .nargs = 0, + .operation = var, +}; +static const struct expression plone = +{ + .nargs = 0, + .operation = num, + .val = + { + .num = 1 + } +}; +struct expression GERMANIC_PLURAL = +{ + .nargs = 2, + .operation = not_equal, + .val = + { + .args = + { + [0] = (struct expression *) &plvar, + [1] = (struct expression *) &plone + } + } +}; + +# define INIT_GERMANIC_PLURAL() + +#else + +/* For compilers without support for ISO C 99 struct/union initializers: + Initialization at run-time. */ + +static struct expression plvar; +static struct expression plone; +struct expression GERMANIC_PLURAL; + +static void +init_germanic_plural () +{ + if (plone.val.num == 0) + { + plvar.nargs = 0; + plvar.operation = var; + + plone.nargs = 0; + plone.operation = num; + plone.val.num = 1; + + GERMANIC_PLURAL.nargs = 2; + GERMANIC_PLURAL.operation = not_equal; + GERMANIC_PLURAL.val.args[0] = &plvar; + GERMANIC_PLURAL.val.args[1] = &plone; + } +} + +# define INIT_GERMANIC_PLURAL() init_germanic_plural () + +#endif + +void +internal_function +EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp) + const char *nullentry; + struct expression **pluralp; + unsigned long int *npluralsp; +{ + if (nullentry != NULL) + { + const char *plural; + const char *nplurals; + + plural = strstr (nullentry, "plural="); + nplurals = strstr (nullentry, "nplurals="); + if (plural == NULL || nplurals == NULL) + goto no_plural; + else + { + char *endp; + unsigned long int n; + struct parse_args args; + + /* First get the number. */ + nplurals += 9; + while (*nplurals != '\0' && isspace ((unsigned char) *nplurals)) + ++nplurals; + if (!(*nplurals >= '0' && *nplurals <= '9')) + goto no_plural; +#if defined HAVE_STRTOUL || defined _LIBC + n = strtoul (nplurals, &endp, 10); +#else + for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++) + n = n * 10 + (*endp - '0'); +#endif + if (nplurals == endp) + goto no_plural; + *npluralsp = n; + + /* Due to the restrictions bison imposes onto the interface of the + scanner function we have to put the input string and the result + passed up from the parser into the same structure which address + is passed down to the parser. */ + plural += 7; + args.cp = plural; + if (PLURAL_PARSE (&args) != 0) + goto no_plural; + *pluralp = args.res; + } + } + else + { + /* By default we are using the Germanic form: singular form only + for `one', the plural form otherwise. Yes, this is also what + English is using since English is a Germanic language. */ + no_plural: + INIT_GERMANIC_PLURAL (); + *pluralp = &GERMANIC_PLURAL; + *npluralsp = 2; + } +} diff --git a/intl/plural-exp.h b/intl/plural-exp.h new file mode 100644 index 000000000..9e5d16583 --- /dev/null +++ b/intl/plural-exp.h @@ -0,0 +1,126 @@ +/* Expression parsing and evaluation for plural form selection. + Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + Written by Ulrich Drepper <drepper@cygnus.com>, 2000. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _PLURAL_EXP_H +#define _PLURAL_EXP_H + +#ifndef PARAMS +# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +#endif + +#ifndef internal_function +# define internal_function +#endif + +#ifndef attribute_hidden +# define attribute_hidden +#endif + + +/* This is the representation of the expressions to determine the + plural form. */ +struct expression +{ + int nargs; /* Number of arguments. */ + enum operator + { + /* Without arguments: */ + var, /* The variable "n". */ + num, /* Decimal number. */ + /* Unary operators: */ + lnot, /* Logical NOT. */ + /* Binary operators: */ + mult, /* Multiplication. */ + divide, /* Division. */ + module, /* Modulo operation. */ + plus, /* Addition. */ + minus, /* Subtraction. */ + less_than, /* Comparison. */ + greater_than, /* Comparison. */ + less_or_equal, /* Comparison. */ + greater_or_equal, /* Comparison. */ + equal, /* Comparison for equality. */ + not_equal, /* Comparison for inequality. */ + land, /* Logical AND. */ + lor, /* Logical OR. */ + /* Ternary operators: */ + qmop /* Question mark operator. */ + } operation; + union + { + unsigned long int num; /* Number value for `num'. */ + struct expression *args[3]; /* Up to three arguments. */ + } val; +}; + +/* This is the data structure to pass information to the parser and get + the result in a thread-safe way. */ +struct parse_args +{ + const char *cp; + struct expression *res; +}; + + +/* Names for the libintl functions are a problem. This source code is used + 1. in the GNU C Library library, + 2. in the GNU libintl library, + 3. in the GNU gettext tools. + The function names in each situation must be different, to allow for + binary incompatible changes in 'struct expression'. Furthermore, + 1. in the GNU C Library library, the names have a __ prefix, + 2.+3. in the GNU libintl library and in the GNU gettext tools, the names + must follow ANSI C and not start with __. + So we have to distinguish the three cases. */ +#ifdef _LIBC +# define FREE_EXPRESSION __gettext_free_exp +# define PLURAL_PARSE __gettextparse +# define GERMANIC_PLURAL __gettext_germanic_plural +# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural +#elif defined (IN_LIBINTL) +# define FREE_EXPRESSION libintl_gettext_free_exp +# define PLURAL_PARSE libintl_gettextparse +# define GERMANIC_PLURAL libintl_gettext_germanic_plural +# define EXTRACT_PLURAL_EXPRESSION libintl_gettext_extract_plural +#else +# define FREE_EXPRESSION free_plural_expression +# define PLURAL_PARSE parse_plural_expression +# define GERMANIC_PLURAL germanic_plural +# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression +#endif + +extern void FREE_EXPRESSION PARAMS ((struct expression *exp)) + internal_function; +extern int PLURAL_PARSE PARAMS ((void *arg)); +extern struct expression GERMANIC_PLURAL attribute_hidden; +extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry, + struct expression **pluralp, + unsigned long int *npluralsp)) + internal_function; + +#if !defined (_LIBC) && !defined (IN_LIBINTL) +extern unsigned long int plural_eval PARAMS ((struct expression *pexp, + unsigned long int n)); +#endif + +#endif /* _PLURAL_EXP_H */ diff --git a/intl/plural.c b/intl/plural.c new file mode 100644 index 000000000..3a4fa20ca --- /dev/null +++ b/intl/plural.c @@ -0,0 +1,1518 @@ +/* A Bison parser, made from plural.y + by GNU bison 1.35. */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define yyparse __gettextparse +#define yylex __gettextlex +#define yyerror __gettexterror +#define yylval __gettextlval +#define yychar __gettextchar +#define yydebug __gettextdebug +#define yynerrs __gettextnerrs +# define EQUOP2 257 +# define CMPOP2 258 +# define ADDOP2 259 +# define MULOP2 260 +# define NUMBER 261 + +#line 1 "plural.y" + +/* Expression parsing for plural form selection. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Written by Ulrich Drepper <drepper@cygnus.com>, 2000. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* The bison generated parser uses alloca. AIX 3 forces us to put this + declaration at the beginning of the file. The declaration in bison's + skeleton file comes too late. This must come before <config.h> + because <config.h> may include arbitrary system headers. */ +#if defined _AIX && !defined __GNUC__ + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stddef.h> +#include <stdlib.h> +#include "plural-exp.h" + +/* The main function generated by the parser is called __gettextparse, + but we want it to be called PLURAL_PARSE. */ +#ifndef _LIBC +# define __gettextparse PLURAL_PARSE +#endif + +#define YYLEX_PARAM &((struct parse_args *) arg)->cp +#define YYPARSE_PARAM arg + +#line 49 "plural.y" +#ifndef YYSTYPE +typedef union { + unsigned long int num; + enum operator op; + struct expression *exp; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +#line 55 "plural.y" + +/* Prototypes for local functions. */ +static struct expression *new_exp PARAMS ((int nargs, enum operator op, + struct expression * const *args)); +static inline struct expression *new_exp_0 PARAMS ((enum operator op)); +static inline struct expression *new_exp_1 PARAMS ((enum operator op, + struct expression *right)); +static struct expression *new_exp_2 PARAMS ((enum operator op, + struct expression *left, + struct expression *right)); +static inline struct expression *new_exp_3 PARAMS ((enum operator op, + struct expression *bexp, + struct expression *tbranch, + struct expression *fbranch)); +static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); +static void yyerror PARAMS ((const char *str)); + +/* Allocation of expressions. */ + +static struct expression * +new_exp (nargs, op, args) + int nargs; + enum operator op; + struct expression * const *args; +{ + int i; + struct expression *newp; + + /* If any of the argument could not be malloc'ed, just return NULL. */ + for (i = nargs - 1; i >= 0; i--) + if (args[i] == NULL) + goto fail; + + /* Allocate a new expression. */ + newp = (struct expression *) malloc (sizeof (*newp)); + if (newp != NULL) + { + newp->nargs = nargs; + newp->operation = op; + for (i = nargs - 1; i >= 0; i--) + newp->val.args[i] = args[i]; + return newp; + } + + fail: + for (i = nargs - 1; i >= 0; i--) + FREE_EXPRESSION (args[i]); + + return NULL; +} + +static inline struct expression * +new_exp_0 (op) + enum operator op; +{ + return new_exp (0, op, NULL); +} + +static inline struct expression * +new_exp_1 (op, right) + enum operator op; + struct expression *right; +{ + struct expression *args[1]; + + args[0] = right; + return new_exp (1, op, args); +} + +static struct expression * +new_exp_2 (op, left, right) + enum operator op; + struct expression *left; + struct expression *right; +{ + struct expression *args[2]; + + args[0] = left; + args[1] = right; + return new_exp (2, op, args); +} + +static inline struct expression * +new_exp_3 (op, bexp, tbranch, fbranch) + enum operator op; + struct expression *bexp; + struct expression *tbranch; + struct expression *fbranch; +{ + struct expression *args[3]; + + args[0] = bexp; + args[1] = tbranch; + args[2] = fbranch; + return new_exp (3, op, args); +} + +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + + + +#define YYFINAL 27 +#define YYFLAG -32768 +#define YYNTBASE 16 + +/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ +#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18) + +/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ +static const char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 10, 2, 2, 2, 2, 5, 2, + 14, 15, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, + 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 13, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 6, 7, 8, + 9, 11 +}; + +#if YYDEBUG +static const short yyprhs[] = +{ + 0, 0, 2, 8, 12, 16, 20, 24, 28, 32, + 35, 37, 39 +}; +static const short yyrhs[] = +{ + 17, 0, 17, 3, 17, 12, 17, 0, 17, 4, + 17, 0, 17, 5, 17, 0, 17, 6, 17, 0, + 17, 7, 17, 0, 17, 8, 17, 0, 17, 9, + 17, 0, 10, 17, 0, 13, 0, 11, 0, 14, + 17, 15, 0 +}; + +#endif + +#if YYDEBUG +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const short yyrline[] = +{ + 0, 174, 182, 186, 190, 194, 198, 202, 206, 210, + 214, 218, 223 +}; +#endif + + +#if (YYDEBUG) || defined YYERROR_VERBOSE + +/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ +static const char *const yytname[] = +{ + "$", "error", "$undefined.", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2", + "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'", + "start", "exp", 0 +}; +#endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const short yyr1[] = +{ + 0, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const short yyr2[] = +{ + 0, 1, 5, 3, 3, 3, 3, 3, 3, 2, + 1, 1, 3 +}; + +/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE + doesn't specify something else to do. Zero means the default is an + error. */ +static const short yydefact[] = +{ + 0, 0, 11, 10, 0, 1, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 12, 0, 3, 4, 5, + 6, 7, 8, 0, 2, 0, 0, 0 +}; + +static const short yydefgoto[] = +{ + 25, 5 +}; + +static const short yypact[] = +{ + -9, -9,-32768,-32768, -9, 34,-32768, 11, -9, -9, + -9, -9, -9, -9, -9,-32768, 24, 39, 43, 16, + 26, -3,-32768, -9, 34, 21, 53,-32768 +}; + +static const short yypgoto[] = +{ + -32768, -1 +}; + + +#define YYLAST 53 + + +static const short yytable[] = +{ + 6, 1, 2, 7, 3, 4, 14, 16, 17, 18, + 19, 20, 21, 22, 8, 9, 10, 11, 12, 13, + 14, 26, 24, 12, 13, 14, 15, 8, 9, 10, + 11, 12, 13, 14, 13, 14, 23, 8, 9, 10, + 11, 12, 13, 14, 10, 11, 12, 13, 14, 11, + 12, 13, 14, 27 +}; + +static const short yycheck[] = +{ + 1, 10, 11, 4, 13, 14, 9, 8, 9, 10, + 11, 12, 13, 14, 3, 4, 5, 6, 7, 8, + 9, 0, 23, 7, 8, 9, 15, 3, 4, 5, + 6, 7, 8, 9, 8, 9, 12, 3, 4, 5, + 6, 7, 8, 9, 5, 6, 7, 8, 9, 6, + 7, 8, 9, 0 +}; +#define YYPURE 1 + +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/local/share/bison/bison.simple" + +/* Skeleton output parser for bison, + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software + Foundation, Inc. + + 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, 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. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser when + the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; +# if YYLSP_NEEDED + YYLTYPE yyls; +# endif +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# if YYLSP_NEEDED +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAX) +# else +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) +# endif + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). + + When YYLLOC_DEFAULT is run, CURRENT is set the location of the + first token. By default, to implement support for ranges, extend + its range to the last symbol. */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#if YYPURE +# if YYLSP_NEEDED +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval, &yylloc) +# endif +# else /* !YYLSP_NEEDED */ +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval) +# endif +# endif /* !YYLSP_NEEDED */ +#else /* !YYPURE */ +# define YYLEX yylex () +#endif /* !YYPURE */ + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +#ifdef YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif +#endif + +#line 315 "/usr/local/share/bison/bison.simple" + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + +/* YY_DECL_VARIABLES -- depending whether we use a pure parser, + variables are global, or local to YYPARSE. */ + +#define YY_DECL_NON_LSP_VARIABLES \ +/* The lookahead symbol. */ \ +int yychar; \ + \ +/* The semantic value of the lookahead symbol. */ \ +YYSTYPE yylval; \ + \ +/* Number of parse errors so far. */ \ +int yynerrs; + +#if YYLSP_NEEDED +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES \ + \ +/* Location data for the lookahead symbol. */ \ +YYLTYPE yylloc; +#else +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES +#endif + + +/* If nonreentrant, generate the variables here. */ + +#if !YYPURE +YY_DECL_VARIABLES +#endif /* !YYPURE */ + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + /* If reentrant, generate the variables here. */ +#if YYPURE + YY_DECL_VARIABLES +#endif /* !YYPURE */ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + +#if YYLSP_NEEDED + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; +#endif + +#if YYLSP_NEEDED +# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +# define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + YYSIZE_T yystacksize = YYINITDEPTH; + + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; +#if YYLSP_NEEDED + YYLTYPE yyloc; +#endif + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; +#if YYLSP_NEEDED + yylsp = yyls; +#endif + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. */ +# if YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; +# else + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); +# endif + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); +# if YYLSP_NEEDED + YYSTACK_RELOCATE (yyls); +# endif +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; +#if YYLSP_NEEDED + yylsp = yyls + yysize - 1; +#endif + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + YYFPRINTF (stderr, "Next token is %d (%s", + yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise + meaning of a token, for further debugging info. */ +# ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +# endif + YYFPRINTF (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to the semantic value of + the lookahead token. This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + +#if YYLSP_NEEDED + /* Similarly for the default location. Let the user run additional + commands if for instance locations are ranges. */ + yyloc = yylsp[1-yylen]; + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +#endif + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + switch (yyn) { + +case 1: +#line 175 "plural.y" +{ + if (yyvsp[0].exp == NULL) + YYABORT; + ((struct parse_args *) arg)->res = yyvsp[0].exp; + } + break; +case 2: +#line 183 "plural.y" +{ + yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 3: +#line 187 "plural.y" +{ + yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 4: +#line 191 "plural.y" +{ + yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 5: +#line 195 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 6: +#line 199 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 7: +#line 203 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 8: +#line 207 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 9: +#line 211 "plural.y" +{ + yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); + } + break; +case 10: +#line 215 "plural.y" +{ + yyval.exp = new_exp_0 (var); + } + break; +case 11: +#line 219 "plural.y" +{ + if ((yyval.exp = new_exp_0 (num)) != NULL) + yyval.exp->val.num = yyvsp[0].num; + } + break; +case 12: +#line 224 "plural.y" +{ + yyval.exp = yyvsp[-1].exp; + } + break; +} + +#line 705 "/usr/local/share/bison/bison.simple" + + + yyvsp -= yylen; + yyssp -= yylen; +#if YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; +#if YYLSP_NEEDED + *++yylsp = yyloc; +#endif + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* defined (YYERROR_VERBOSE) */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*--------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action | +`--------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + + +/*-------------------------------------------------------------------. +| yyerrdefault -- current state does not do anything special for the | +| error token. | +`-------------------------------------------------------------------*/ +yyerrdefault: +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + + /* If its default is to accept any token, ok. Otherwise pop it. */ + yyn = yydefact[yystate]; + if (yyn) + goto yydefault; +#endif + + +/*---------------------------------------------------------------. +| yyerrpop -- pop the current state because it cannot handle the | +| error token | +`---------------------------------------------------------------*/ +yyerrpop: + if (yyssp == yyss) + YYABORT; + yyvsp--; + yystate = *--yyssp; +#if YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + +/*--------------. +| yyerrhandle. | +`--------------*/ +yyerrhandle: + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +/*---------------------------------------------. +| yyoverflowab -- parser overflow comes here. | +`---------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} +#line 229 "plural.y" + + +void +internal_function +FREE_EXPRESSION (exp) + struct expression *exp; +{ + if (exp == NULL) + return; + + /* Handle the recursive case. */ + switch (exp->nargs) + { + case 3: + FREE_EXPRESSION (exp->val.args[2]); + /* FALLTHROUGH */ + case 2: + FREE_EXPRESSION (exp->val.args[1]); + /* FALLTHROUGH */ + case 1: + FREE_EXPRESSION (exp->val.args[0]); + /* FALLTHROUGH */ + default: + break; + } + + free (exp); +} + + +static int +yylex (lval, pexp) + YYSTYPE *lval; + const char **pexp; +{ + const char *exp = *pexp; + int result; + + while (1) + { + if (exp[0] == '\0') + { + *pexp = exp; + return YYEOF; + } + + if (exp[0] != ' ' && exp[0] != '\t') + break; + + ++exp; + } + + result = *exp++; + switch (result) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + unsigned long int n = result - '0'; + while (exp[0] >= '0' && exp[0] <= '9') + { + n *= 10; + n += exp[0] - '0'; + ++exp; + } + lval->num = n; + result = NUMBER; + } + break; + + case '=': + if (exp[0] == '=') + { + ++exp; + lval->op = equal; + result = EQUOP2; + } + else + result = YYERRCODE; + break; + + case '!': + if (exp[0] == '=') + { + ++exp; + lval->op = not_equal; + result = EQUOP2; + } + break; + + case '&': + case '|': + if (exp[0] == result) + ++exp; + else + result = YYERRCODE; + break; + + case '<': + if (exp[0] == '=') + { + ++exp; + lval->op = less_or_equal; + } + else + lval->op = less_than; + result = CMPOP2; + break; + + case '>': + if (exp[0] == '=') + { + ++exp; + lval->op = greater_or_equal; + } + else + lval->op = greater_than; + result = CMPOP2; + break; + + case '*': + lval->op = mult; + result = MULOP2; + break; + + case '/': + lval->op = divide; + result = MULOP2; + break; + + case '%': + lval->op = module; + result = MULOP2; + break; + + case '+': + lval->op = plus; + result = ADDOP2; + break; + + case '-': + lval->op = minus; + result = ADDOP2; + break; + + case 'n': + case '?': + case ':': + case '(': + case ')': + /* Nothing, just return the character. */ + break; + + case ';': + case '\n': + case '\0': + /* Be safe and let the user call this function again. */ + --exp; + result = YYEOF; + break; + + default: + result = YYERRCODE; +#if YYDEBUG != 0 + --exp; +#endif + break; + } + + *pexp = exp; + + return result; +} + + +static void +yyerror (str) + const char *str; +{ + /* Do nothing. We don't print error messages here. */ +} diff --git a/intl/plural.y b/intl/plural.y new file mode 100644 index 000000000..616b7c11a --- /dev/null +++ b/intl/plural.y @@ -0,0 +1,409 @@ +%{ +/* Expression parsing for plural form selection. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Written by Ulrich Drepper <drepper@cygnus.com>, 2000. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* The bison generated parser uses alloca. AIX 3 forces us to put this + declaration at the beginning of the file. The declaration in bison's + skeleton file comes too late. This must come before <config.h> + because <config.h> may include arbitrary system headers. */ +#if defined _AIX && !defined __GNUC__ + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stddef.h> +#include <stdlib.h> +#include "plural-exp.h" + +/* The main function generated by the parser is called __gettextparse, + but we want it to be called PLURAL_PARSE. */ +#ifndef _LIBC +# define __gettextparse PLURAL_PARSE +#endif + +#define YYLEX_PARAM &((struct parse_args *) arg)->cp +#define YYPARSE_PARAM arg +%} +%pure_parser +%expect 7 + +%union { + unsigned long int num; + enum operator op; + struct expression *exp; +} + +%{ +/* Prototypes for local functions. */ +static struct expression *new_exp PARAMS ((int nargs, enum operator op, + struct expression * const *args)); +static inline struct expression *new_exp_0 PARAMS ((enum operator op)); +static inline struct expression *new_exp_1 PARAMS ((enum operator op, + struct expression *right)); +static struct expression *new_exp_2 PARAMS ((enum operator op, + struct expression *left, + struct expression *right)); +static inline struct expression *new_exp_3 PARAMS ((enum operator op, + struct expression *bexp, + struct expression *tbranch, + struct expression *fbranch)); +static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); +static void yyerror PARAMS ((const char *str)); + +/* Allocation of expressions. */ + +static struct expression * +new_exp (nargs, op, args) + int nargs; + enum operator op; + struct expression * const *args; +{ + int i; + struct expression *newp; + + /* If any of the argument could not be malloc'ed, just return NULL. */ + for (i = nargs - 1; i >= 0; i--) + if (args[i] == NULL) + goto fail; + + /* Allocate a new expression. */ + newp = (struct expression *) malloc (sizeof (*newp)); + if (newp != NULL) + { + newp->nargs = nargs; + newp->operation = op; + for (i = nargs - 1; i >= 0; i--) + newp->val.args[i] = args[i]; + return newp; + } + + fail: + for (i = nargs - 1; i >= 0; i--) + FREE_EXPRESSION (args[i]); + + return NULL; +} + +static inline struct expression * +new_exp_0 (op) + enum operator op; +{ + return new_exp (0, op, NULL); +} + +static inline struct expression * +new_exp_1 (op, right) + enum operator op; + struct expression *right; +{ + struct expression *args[1]; + + args[0] = right; + return new_exp (1, op, args); +} + +static struct expression * +new_exp_2 (op, left, right) + enum operator op; + struct expression *left; + struct expression *right; +{ + struct expression *args[2]; + + args[0] = left; + args[1] = right; + return new_exp (2, op, args); +} + +static inline struct expression * +new_exp_3 (op, bexp, tbranch, fbranch) + enum operator op; + struct expression *bexp; + struct expression *tbranch; + struct expression *fbranch; +{ + struct expression *args[3]; + + args[0] = bexp; + args[1] = tbranch; + args[2] = fbranch; + return new_exp (3, op, args); +} + +%} + +/* This declares that all operators have the same associativity and the + precedence order as in C. See [Harbison, Steele: C, A Reference Manual]. + There is no unary minus and no bitwise operators. + Operators with the same syntactic behaviour have been merged into a single + token, to save space in the array generated by bison. */ +%right '?' /* ? */ +%left '|' /* || */ +%left '&' /* && */ +%left EQUOP2 /* == != */ +%left CMPOP2 /* < > <= >= */ +%left ADDOP2 /* + - */ +%left MULOP2 /* * / % */ +%right '!' /* ! */ + +%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2 +%token <num> NUMBER +%type <exp> exp + +%% + +start: exp + { + if ($1 == NULL) + YYABORT; + ((struct parse_args *) arg)->res = $1; + } + ; + +exp: exp '?' exp ':' exp + { + $$ = new_exp_3 (qmop, $1, $3, $5); + } + | exp '|' exp + { + $$ = new_exp_2 (lor, $1, $3); + } + | exp '&' exp + { + $$ = new_exp_2 (land, $1, $3); + } + | exp EQUOP2 exp + { + $$ = new_exp_2 ($2, $1, $3); + } + | exp CMPOP2 exp + { + $$ = new_exp_2 ($2, $1, $3); + } + | exp ADDOP2 exp + { + $$ = new_exp_2 ($2, $1, $3); + } + | exp MULOP2 exp + { + $$ = new_exp_2 ($2, $1, $3); + } + | '!' exp + { + $$ = new_exp_1 (lnot, $2); + } + | 'n' + { + $$ = new_exp_0 (var); + } + | NUMBER + { + if (($$ = new_exp_0 (num)) != NULL) + $$->val.num = $1; + } + | '(' exp ')' + { + $$ = $2; + } + ; + +%% + +void +internal_function +FREE_EXPRESSION (exp) + struct expression *exp; +{ + if (exp == NULL) + return; + + /* Handle the recursive case. */ + switch (exp->nargs) + { + case 3: + FREE_EXPRESSION (exp->val.args[2]); + /* FALLTHROUGH */ + case 2: + FREE_EXPRESSION (exp->val.args[1]); + /* FALLTHROUGH */ + case 1: + FREE_EXPRESSION (exp->val.args[0]); + /* FALLTHROUGH */ + default: + break; + } + + free (exp); +} + + +static int +yylex (lval, pexp) + YYSTYPE *lval; + const char **pexp; +{ + const char *exp = *pexp; + int result; + + while (1) + { + if (exp[0] == '\0') + { + *pexp = exp; + return YYEOF; + } + + if (exp[0] != ' ' && exp[0] != '\t') + break; + + ++exp; + } + + result = *exp++; + switch (result) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + unsigned long int n = result - '0'; + while (exp[0] >= '0' && exp[0] <= '9') + { + n *= 10; + n += exp[0] - '0'; + ++exp; + } + lval->num = n; + result = NUMBER; + } + break; + + case '=': + if (exp[0] == '=') + { + ++exp; + lval->op = equal; + result = EQUOP2; + } + else + result = YYERRCODE; + break; + + case '!': + if (exp[0] == '=') + { + ++exp; + lval->op = not_equal; + result = EQUOP2; + } + break; + + case '&': + case '|': + if (exp[0] == result) + ++exp; + else + result = YYERRCODE; + break; + + case '<': + if (exp[0] == '=') + { + ++exp; + lval->op = less_or_equal; + } + else + lval->op = less_than; + result = CMPOP2; + break; + + case '>': + if (exp[0] == '=') + { + ++exp; + lval->op = greater_or_equal; + } + else + lval->op = greater_than; + result = CMPOP2; + break; + + case '*': + lval->op = mult; + result = MULOP2; + break; + + case '/': + lval->op = divide; + result = MULOP2; + break; + + case '%': + lval->op = module; + result = MULOP2; + break; + + case '+': + lval->op = plus; + result = ADDOP2; + break; + + case '-': + lval->op = minus; + result = ADDOP2; + break; + + case 'n': + case '?': + case ':': + case '(': + case ')': + /* Nothing, just return the character. */ + break; + + case ';': + case '\n': + case '\0': + /* Be safe and let the user call this function again. */ + --exp; + result = YYEOF; + break; + + default: + result = YYERRCODE; +#if YYDEBUG != 0 + --exp; +#endif + break; + } + + *pexp = exp; + + return result; +} + + +static void +yyerror (str) + const char *str; +{ + /* Do nothing. We don't print error messages here. */ +} diff --git a/intl/relocatable.c b/intl/relocatable.c new file mode 100644 index 000000000..16f79a528 --- /dev/null +++ b/intl/relocatable.c @@ -0,0 +1,439 @@ +/* Provide relocatable packages. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + + +/* Tell glibc's <stdio.h> to provide a prototype for getline(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "relocatable.h" + +#if ENABLE_RELOCATABLE + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef NO_XMALLOC +# define xmalloc malloc +#else +# include "xmalloc.h" +#endif + +#if DEPENDS_ON_LIBCHARSET +# include <libcharset.h> +#endif +#if DEPENDS_ON_LIBICONV && HAVE_ICONV +# include <iconv.h> +#endif +#if DEPENDS_ON_LIBINTL && ENABLE_NLS +# include <libintl.h> +#endif + +/* Faked cheap 'bool'. */ +#undef bool +#undef false +#undef true +#define bool int +#define false 0 +#define true 1 + +/* Pathname support. + ISSLASH(C) tests whether C is a directory separator character. + IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. + */ +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +# define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ + && (P)[1] == ':') +# define IS_PATH_WITH_DIR(P) \ + (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) +# define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILESYSTEM_PREFIX_LEN(P) 0 +#endif + +/* Original installation prefix. */ +static char *orig_prefix; +static size_t orig_prefix_len; +/* Current installation prefix. */ +static char *curr_prefix; +static size_t curr_prefix_len; +/* These prefixes do not end in a slash. Anything that will be concatenated + to them must start with a slash. */ + +/* Sets the original and the current installation prefix of this module. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +static void +set_this_relocation_prefix (const char *orig_prefix_arg, + const char *curr_prefix_arg) +{ + if (orig_prefix_arg != NULL && curr_prefix_arg != NULL + /* Optimization: if orig_prefix and curr_prefix are equal, the + relocation is a nop. */ + && strcmp (orig_prefix_arg, curr_prefix_arg) != 0) + { + /* Duplicate the argument strings. */ + char *memory; + + orig_prefix_len = strlen (orig_prefix_arg); + curr_prefix_len = strlen (curr_prefix_arg); + memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1); +#ifdef NO_XMALLOC + if (memory != NULL) +#endif + { + memcpy (memory, orig_prefix_arg, orig_prefix_len + 1); + orig_prefix = memory; + memory += orig_prefix_len + 1; + memcpy (memory, curr_prefix_arg, curr_prefix_len + 1); + curr_prefix = memory; + return; + } + } + orig_prefix = NULL; + curr_prefix = NULL; + /* Don't worry about wasted memory here - this function is usually only + called once. */ +} + +/* Sets the original and the current installation prefix of the package. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +void +set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg) +{ + set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg); + + /* Now notify all dependent libraries. */ +#if DEPENDS_ON_LIBCHARSET + libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg); +#endif +#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109 + libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg); +#endif +#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix + libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg); +#endif +} + +/* Convenience function: + Computes the current installation prefix, based on the original + installation prefix, the original installation directory of a particular + file, and the current pathname of this file. Returns NULL upon failure. */ +#ifdef IN_LIBRARY +#define compute_curr_prefix local_compute_curr_prefix +static +#endif +const char * +compute_curr_prefix (const char *orig_installprefix, + const char *orig_installdir, + const char *curr_pathname) +{ + const char *curr_installdir; + const char *rel_installdir; + + if (curr_pathname == NULL) + return NULL; + + /* Determine the relative installation directory, relative to the prefix. + This is simply the difference between orig_installprefix and + orig_installdir. */ + if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix)) + != 0) + /* Shouldn't happen - nothing should be installed outside $(prefix). */ + return NULL; + rel_installdir = orig_installdir + strlen (orig_installprefix); + + /* Determine the current installation directory. */ + { + const char *p_base = curr_pathname + FILESYSTEM_PREFIX_LEN (curr_pathname); + const char *p = curr_pathname + strlen (curr_pathname); + char *q; + + while (p > p_base) + { + p--; + if (ISSLASH (*p)) + break; + } + + q = (char *) xmalloc (p - curr_pathname + 1); +#ifdef NO_XMALLOC + if (q == NULL) + return NULL; +#endif + memcpy (q, curr_pathname, p - curr_pathname); + q[p - curr_pathname] = '\0'; + curr_installdir = q; + } + + /* Compute the current installation prefix by removing the trailing + rel_installdir from it. */ + { + const char *rp = rel_installdir + strlen (rel_installdir); + const char *cp = curr_installdir + strlen (curr_installdir); + const char *cp_base = + curr_installdir + FILESYSTEM_PREFIX_LEN (curr_installdir); + + while (rp > rel_installdir && cp > cp_base) + { + bool same = false; + const char *rpi = rp; + const char *cpi = cp; + + while (rpi > rel_installdir && cpi > cp_base) + { + rpi--; + cpi--; + if (ISSLASH (*rpi) || ISSLASH (*cpi)) + { + if (ISSLASH (*rpi) && ISSLASH (*cpi)) + same = true; + break; + } +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS - case insignificant filesystem */ + if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi) + != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi)) + break; +#else + if (*rpi != *cpi) + break; +#endif + } + if (!same) + break; + /* The last pathname component was the same. opi and cpi now point + to the slash before it. */ + rp = rpi; + cp = cpi; + } + + if (rp > rel_installdir) + /* Unexpected: The curr_installdir does not end with rel_installdir. */ + return NULL; + + { + size_t curr_prefix_len = cp - curr_installdir; + char *curr_prefix; + + curr_prefix = (char *) xmalloc (curr_prefix_len + 1); +#ifdef NO_XMALLOC + if (curr_prefix == NULL) + return NULL; +#endif + memcpy (curr_prefix, curr_installdir, curr_prefix_len); + curr_prefix[curr_prefix_len] = '\0'; + + return curr_prefix; + } + } +} + +#if defined PIC && defined INSTALLDIR + +/* Full pathname of shared library, or NULL. */ +static char *shared_library_fullname; + +#if defined _WIN32 || defined __WIN32__ + +/* Determine the full pathname of the shared library when it is loaded. */ + +BOOL WINAPI +DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved) +{ + (void) reserved; + + if (event == DLL_PROCESS_ATTACH) + { + /* The DLL is being loaded into an application's address range. */ + static char location[MAX_PATH]; + + if (!GetModuleFileName (module_handle, location, sizeof (location))) + /* Shouldn't happen. */ + return FALSE; + + if (!IS_PATH_WITH_DIR (location)) + /* Shouldn't happen. */ + return FALSE; + + shared_library_fullname = strdup (location); + } + + return TRUE; +} + +#else /* Unix */ + +static void +find_shared_library_fullname () +{ +#ifdef __linux__ + FILE *fp; + + /* Open the current process' maps file. It describes one VMA per line. */ + fp = fopen ("/proc/self/maps", "r"); + if (fp) + { + unsigned long address = (unsigned long) &find_shared_library_fullname; + for (;;) + { + unsigned long start, end; + int c; + + if (fscanf (fp, "%lx-%lx", &start, &end) != 2) + break; + if (address >= start && address <= end - 1) + { + /* Found it. Now see if this line contains a filename. */ + while (c = getc (fp), c != EOF && c != '\n' && c != '/') + continue; + if (c == '/') + { + size_t size; + int len; + + ungetc (c, fp); + shared_library_fullname = NULL; size = 0; + len = getline (&shared_library_fullname, &size, fp); + if (len >= 0) + { + /* Success: filled shared_library_fullname. */ + if (len > 0 && shared_library_fullname[len - 1] == '\n') + shared_library_fullname[len - 1] = '\0'; + } + } + break; + } + while (c = getc (fp), c != EOF && c != '\n') + continue; + } + fclose (fp); + } +#endif +} + +#endif /* WIN32 / Unix */ + +/* Return the full pathname of the current shared library. + Return NULL if unknown. + Guaranteed to work only on Linux and Woe32. */ +static char * +get_shared_library_fullname () +{ +#if !(defined _WIN32 || defined __WIN32__) + static bool tried_find_shared_library_fullname; + if (!tried_find_shared_library_fullname) + { + find_shared_library_fullname (); + tried_find_shared_library_fullname = true; + } +#endif + return shared_library_fullname; +} + +#endif /* PIC */ + +/* Returns the pathname, relocated according to the current installation + directory. */ +const char * +relocate (const char *pathname) +{ +#if defined PIC && defined INSTALLDIR + static int initialized; + + /* Initialization code for a shared library. */ + if (!initialized) + { + /* At this point, orig_prefix and curr_prefix likely have already been + set through the main program's set_program_name_and_installdir + function. This is sufficient in the case that the library has + initially been installed in the same orig_prefix. But we can do + better, to also cover the cases that 1. it has been installed + in a different prefix before being moved to orig_prefix and (later) + to curr_prefix, 2. unlike the program, it has not moved away from + orig_prefix. */ + const char *orig_installprefix = INSTALLPREFIX; + const char *orig_installdir = INSTALLDIR; + const char *curr_prefix_better; + + curr_prefix_better = + compute_curr_prefix (orig_installprefix, orig_installdir, + get_shared_library_fullname ()); + if (curr_prefix_better == NULL) + curr_prefix_better = curr_prefix; + + set_relocation_prefix (orig_installprefix, curr_prefix_better); + + initialized = 1; + } +#endif + + /* Note: It is not necessary to perform case insensitive comparison here, + even for DOS-like filesystems, because the pathname argument was + typically created from the same Makefile variable as orig_prefix came + from. */ + if (orig_prefix != NULL && curr_prefix != NULL + && strncmp (pathname, orig_prefix, orig_prefix_len) == 0) + { + if (pathname[orig_prefix_len] == '\0') + /* pathname equals orig_prefix. */ + return curr_prefix; + if (ISSLASH (pathname[orig_prefix_len])) + { + /* pathname starts with orig_prefix. */ + const char *pathname_tail = &pathname[orig_prefix_len]; + char *result = + (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1); + +#ifdef NO_XMALLOC + if (result != NULL) +#endif + { + memcpy (result, curr_prefix, curr_prefix_len); + strcpy (result + curr_prefix_len, pathname_tail); + return result; + } + } + } + /* Nothing to relocate. */ + return pathname; +} + +#endif diff --git a/intl/relocatable.h b/intl/relocatable.h new file mode 100644 index 000000000..d141200a6 --- /dev/null +++ b/intl/relocatable.h @@ -0,0 +1,67 @@ +/* Provide relocatable packages. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _RELOCATABLE_H +#define _RELOCATABLE_H + +/* This can be enabled through the configure --enable-relocatable option. */ +#if ENABLE_RELOCATABLE + +/* When building a DLL, we must export some functions. Note that because + this is a private .h file, we don't need to use __declspec(dllimport) + in any case. */ +#if defined _MSC_VER && BUILDING_DLL +# define RELOCATABLE_DLL_EXPORTED __declspec(dllexport) +#else +# define RELOCATABLE_DLL_EXPORTED +#endif + +/* Sets the original and the current installation prefix of the package. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +extern RELOCATABLE_DLL_EXPORTED void + set_relocation_prefix (const char *orig_prefix, + const char *curr_prefix); + +/* Returns the pathname, relocated according to the current installation + directory. */ +extern const char * relocate (const char *pathname); + +/* Memory management: relocate() leaks memory, because it has to construct + a fresh pathname. If this is a problem because your program calls + relocate() frequently, think about caching the result. */ + +/* Convenience function: + Computes the current installation prefix, based on the original + installation prefix, the original installation directory of a particular + file, and the current pathname of this file. Returns NULL upon failure. */ +extern const char * compute_curr_prefix (const char *orig_installprefix, + const char *orig_installdir, + const char *curr_pathname); + +#else + +/* By default, we use the hardwired pathnames. */ +#define relocate(pathname) (pathname) + +#endif + +#endif /* _RELOCATABLE_H */ diff --git a/intl/textdomain.c b/intl/textdomain.c new file mode 100644 index 000000000..f259c696d --- /dev/null +++ b/intl/textdomain.c @@ -0,0 +1,142 @@ +/* Implementation of the textdomain(3) function. + Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <stdlib.h> +#include <string.h> + +#ifdef _LIBC +# include <libintl.h> +#else +# include "libgnuintl.h" +#endif +#include "gettextP.h" + +#ifdef _LIBC +/* We have to handle multi-threaded applications. */ +# include <bits/libc-lock.h> +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_rwlock_define(CLASS, NAME) +# define __libc_rwlock_wrlock(NAME) +# define __libc_rwlock_unlock(NAME) +#endif + +/* The internal variables in the standalone libintl.a must have different + names than the internal variables in GNU libc, otherwise programs + using libintl.a cannot be linked statically. */ +#if !defined _LIBC +# define _nl_default_default_domain libintl_nl_default_default_domain +# define _nl_current_default_domain libintl_nl_current_default_domain +#endif + +/* @@ end of prolog @@ */ + +/* Name of the default text domain. */ +extern const char _nl_default_default_domain[] attribute_hidden; + +/* Default text domain in which entries for gettext(3) are to be found. */ +extern const char *_nl_current_default_domain attribute_hidden; + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define TEXTDOMAIN __textdomain +# ifndef strdup +# define strdup(str) __strdup (str) +# endif +#else +# define TEXTDOMAIN libintl_textdomain +#endif + +/* Lock variable to protect the global data in the gettext implementation. */ +__libc_rwlock_define (extern, _nl_state_lock attribute_hidden) + +/* Set the current default message catalog to DOMAINNAME. + If DOMAINNAME is null, return the current default. + If DOMAINNAME is "", reset to the default of "messages". */ +char * +TEXTDOMAIN (domainname) + const char *domainname; +{ + char *new_domain; + char *old_domain; + + /* A NULL pointer requests the current setting. */ + if (domainname == NULL) + return (char *) _nl_current_default_domain; + + __libc_rwlock_wrlock (_nl_state_lock); + + old_domain = (char *) _nl_current_default_domain; + + /* If domain name is the null string set to default domain "messages". */ + if (domainname[0] == '\0' + || strcmp (domainname, _nl_default_default_domain) == 0) + { + _nl_current_default_domain = _nl_default_default_domain; + new_domain = (char *) _nl_current_default_domain; + } + else if (strcmp (domainname, old_domain) == 0) + /* This can happen and people will use it to signal that some + environment variable changed. */ + new_domain = old_domain; + else + { + /* If the following malloc fails `_nl_current_default_domain' + will be NULL. This value will be returned and so signals we + are out of core. */ +#if defined _LIBC || defined HAVE_STRDUP + new_domain = strdup (domainname); +#else + size_t len = strlen (domainname) + 1; + new_domain = (char *) malloc (len); + if (new_domain != NULL) + memcpy (new_domain, domainname, len); +#endif + + if (new_domain != NULL) + _nl_current_default_domain = new_domain; + } + + /* We use this possibility to signal a change of the loaded catalogs + since this is most likely the case and there is no other easy we + to do it. Do it only when the call was successful. */ + if (new_domain != NULL) + { + ++_nl_msg_cat_cntr; + + if (old_domain != new_domain && old_domain != _nl_default_default_domain) + free (old_domain); + } + + __libc_rwlock_unlock (_nl_state_lock); + + return new_domain; +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__textdomain, textdomain); +#endif diff --git a/m4/codeset.m4 b/m4/codeset.m4 new file mode 100644 index 000000000..59535ebcf --- /dev/null +++ b/m4/codeset.m4 @@ -0,0 +1,23 @@ +# codeset.m4 serial AM1 (gettext-0.10.40) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, + [AC_TRY_LINK([#include <langinfo.h>], + [char* cs = nl_langinfo(CODESET);], + am_cv_langinfo_codeset=yes, + am_cv_langinfo_codeset=no) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE(HAVE_LANGINFO_CODESET, 1, + [Define if you have <langinfo.h> and nl_langinfo(CODESET).]) + fi +]) diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 000000000..16070b40a --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,415 @@ +# gettext.m4 serial 20 (gettext-0.12) +dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 <inttypes.h> formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value `$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define(gt_included_intl, ifelse([$1], [external], [no], [yes])) + define(gt_libtool_suffix_prefix, ifelse([$1], [use-libtool], [l], [])) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if test "$gt_cv_func_gnugettext_libc" != "yes"; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Set USE_NLS. + AM_NLS + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + dnl Add a version number to the cache macros. + define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1))) + define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) + define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) + + AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, + [AC_TRY_LINK([#include <libintl.h> +]ifelse([$2], [need-formatstring-macros], +[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +], [])[extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings;], + [bindtextdomain ("", ""); +return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings], + gt_cv_func_gnugettext_libc=yes, + gt_cv_func_gnugettext_libc=no)]) + + if test "$gt_cv_func_gnugettext_libc" != "yes"; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + gt_cv_func_gnugettext_libintl, + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_TRY_LINK([#include <libintl.h> +]ifelse([$2], [need-formatstring-macros], +[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +], [])[extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias ();], + [bindtextdomain ("", ""); +return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)], + gt_cv_func_gnugettext_libintl=yes, + gt_cv_func_gnugettext_libintl=no) + dnl Now see whether libintl exists and depends on libiconv. + if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include <libintl.h> +]ifelse([$2], [need-formatstring-macros], +[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +], [])[extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias ();], + [bindtextdomain ("", ""); +return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + gt_cv_func_gnugettext_libintl=yes + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if test "$gt_cv_func_gnugettext_libc" = "yes" \ + || { test "$gt_cv_func_gnugettext_libintl" = "yes" \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE(ENABLE_NLS, 1, + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if test "$gt_cv_func_gnugettext_libintl" = "yes"; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if test "$gt_cv_func_gnugettext_libintl" = "yes"; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE(HAVE_GETTEXT, 1, + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE(HAVE_DCGETTEXT, 1, + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST(BUILD_INCLUDED_LIBINTL) + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATOBJEXT) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST(DATADIRNAME) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST(INSTOBJEXT) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST(GENCAT) + + dnl For backward compatibility. Some Makefiles may be using this. + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST(INTLOBJS) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST(INTLLIBS) + + dnl Make all documented variables known to autoconf. + AC_SUBST(LIBINTL) + AC_SUBST(LTLIBINTL) + AC_SUBST(POSUB) +]) + + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_MKINSTALLDIRS])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([jm_GLIBC21])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ +stdlib.h string.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \ +geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \ +strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next \ +__fsetlocking]) + + AM_ICONV + AM_LANGINFO_CODESET + if test $ac_cv_header_locale_h = yes; then + AM_LC_MESSAGES + fi + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/m4/glibc21.m4 b/m4/glibc21.m4 new file mode 100644 index 000000000..9c9f3db30 --- /dev/null +++ b/m4/glibc21.m4 @@ -0,0 +1,32 @@ +# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([jm_GLIBC21], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, + ac_cv_gnu_library_2_1, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include <features.h> +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2_1=yes, + ac_cv_gnu_library_2_1=no) + ] + ) + AC_SUBST(GLIBC21) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 000000000..c5f357982 --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,103 @@ +# iconv.m4 serial AM4 (gettext-0.11.3) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_TRY_LINK([#include <stdlib.h> +#include <iconv.h>], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_func_iconv=yes) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include <stdlib.h> +#include <iconv.h>], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_lib_iconv=yes + am_cv_func_iconv=yes) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST(LIBICONV) + AC_SUBST(LTLIBICONV) +]) + +AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL(am_cv_proto_iconv, [ + AC_TRY_COMPILE([ +#include <stdlib.h> +#include <iconv.h> +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif +], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([$]{ac_t:- + }[$]am_cv_proto_iconv) + AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, + [Define as const if the declaration of iconv() needs const.]) + fi +]) diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4 new file mode 100644 index 000000000..55dddcf1c --- /dev/null +++ b/m4/intdiv0.m4 @@ -0,0 +1,72 @@ +# intdiv0.m4 serial 1 (gettext-0.11.3) +dnl Copyright (C) 2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + AC_TRY_RUN([ +#include <stdlib.h> +#include <signal.h> + +static void +#ifdef __cplusplus +sigfpe_handler (int sig) +#else +sigfpe_handler (sig) int sig; +#endif +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, + [ + # Guess based on the CPU. + case "$host_cpu" in + alpha* | i[34567]86 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac + ]) + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4 new file mode 100644 index 000000000..fd007c312 --- /dev/null +++ b/m4/inttypes-pri.m4 @@ -0,0 +1,32 @@ +# inttypes-pri.m4 serial 1 (gettext-0.11.4) +dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_REQUIRE([gt_HEADER_INTTYPES_H]) + if test $gt_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + gt_cv_inttypes_pri_broken, + [ + AC_TRY_COMPILE([#include <inttypes.h> +#ifdef PRId32 +char *p = PRId32; +#endif +], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, + [Define if <inttypes.h> exists and defines unusable PRI* macros.]) + fi +]) diff --git a/m4/inttypes.m4 b/m4/inttypes.m4 new file mode 100644 index 000000000..ab370ffe0 --- /dev/null +++ b/m4/inttypes.m4 @@ -0,0 +1,27 @@ +# inttypes.m4 serial 1 (gettext-0.11.4) +dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H if <inttypes.h> exists and doesn't clash with +# <sys/types.h>. + +AC_DEFUN([gt_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h, + [ + AC_TRY_COMPILE( + [#include <sys/types.h> +#include <inttypes.h>], + [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no) + ]) + if test $gt_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, + [Define if <inttypes.h> exists and doesn't clash with <sys/types.h>.]) + fi +]) diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4 new file mode 100644 index 000000000..f342eba39 --- /dev/null +++ b/m4/inttypes_h.m4 @@ -0,0 +1,28 @@ +# inttypes_h.m4 serial 5 (gettext-0.12) +dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists, +# doesn't clash with <sys/types.h>, and declares uintmax_t. + +AC_DEFUN([jm_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h, + [AC_TRY_COMPILE( + [#include <sys/types.h> +#include <inttypes.h>], + [uintmax_t i = (uintmax_t) -1;], + jm_ac_cv_header_inttypes_h=yes, + jm_ac_cv_header_inttypes_h=no)]) + if test $jm_ac_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, + [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, + and declares uintmax_t. ]) + fi +]) diff --git a/m4/isc-posix.m4 b/m4/isc-posix.m4 new file mode 100644 index 000000000..1319dd1c7 --- /dev/null +++ b/m4/isc-posix.m4 @@ -0,0 +1,26 @@ +# isc-posix.m4 serial 2 (gettext-0.11.2) +dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# This file is not needed with autoconf-2.53 and newer. Remove it in 2005. + +# This test replaces the one in autoconf. +# Currently this macro should have the same name as the autoconf macro +# because gettext's gettext.m4 (distributed in the automake package) +# still uses it. Otherwise, the use in gettext.m4 makes autoheader +# give these diagnostics: +# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX +# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX + +undefine([AC_ISC_POSIX]) + +AC_DEFUN([AC_ISC_POSIX], + [ + dnl This test replaces the obsolescent AC_ISC_POSIX kludge. + AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) + ] +) diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 000000000..ffd4008b8 --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,32 @@ +# lcmessage.m4 serial 3 (gettext-0.11.3) +dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995. + +# Check whether LC_MESSAGES is available in <locale.h>. + +AC_DEFUN([AM_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your <locale.h> file defines LC_MESSAGES.]) + fi +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 000000000..11d0ce773 --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,110 @@ +# lib-ld.m4 serial 2 (gettext-0.12) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + acl_cv_prog_gnu_ld=yes +else + acl_cv_prog_gnu_ld=no +fi]) +with_gnu_ld=$acl_cv_prog_gnu_ld +]) + +dnl From libtool-1.4. Sets the variable LD. +AC_DEFUN([AC_LIB_PROG_LD], +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(acl_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) diff --git a/m4/lib-link.m4 b/m4/lib-link.m4 new file mode 100644 index 000000000..eeb200d26 --- /dev/null +++ b/m4/lib-link.m4 @@ -0,0 +1,551 @@ +# lib-link.m4 serial 4 (gettext-0.12) +dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + undefine([Name]) + undefine([NAME]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. If found, it +dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and +dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIB[]NAME" + AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + undefine([Name]) + undefine([NAME]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, +dnl hardcode_direct, hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + libext="$acl_cv_libext" + shlibext="$acl_cv_shlibext" + hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + hardcode_direct="$acl_cv_hardcode_direct" + hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE(rpath, + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib$1-prefix], +[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib + --without-lib$1-prefix don't search for lib$1 in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/lib" + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 000000000..26874b267 --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,155 @@ +# lib-prefix.m4 serial 3 (gettext-0.12.2) +dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/lib" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/lib"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 000000000..36bc49317 --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,49 @@ +# nls.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003. + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) +]) + +AC_DEFUN([AM_MKINSTALLDIRS], +[ + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but $(top_srcdir). + dnl Try to locate it. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + case "$ac_aux_dir" in + /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; + *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; + esac + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 000000000..861e3dec3 --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,197 @@ +# po.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003. + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_MKINSTALLDIRS])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1], :) + + dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. + dnl Test whether we really found GNU msgfmt. + if test "$GMSGFMT" != ":"; then + dnl If it is no GNU msgfmt we define it as : so that the + dnl Makefiles still can work. + if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && + (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + : ; + else + GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` + AC_MSG_RESULT( + [found $GMSGFMT program is not GNU msgfmt; ignore it]) + GMSGFMT=":" + fi + fi + + dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && + (if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + fi + + AC_OUTPUT_COMMANDS([ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + GMOFILES= + UPDATEPOFILES= + DUMMYPOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it + # from automake. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) diff --git a/m4/progtest.m4 b/m4/progtest.m4 new file mode 100644 index 000000000..8fe527cec --- /dev/null +++ b/m4/progtest.m4 @@ -0,0 +1,91 @@ +# progtest.m4 serial 3 (gettext-0.12) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1996. + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4 new file mode 100644 index 000000000..32ba7ae77 --- /dev/null +++ b/m4/stdint_h.m4 @@ -0,0 +1,28 @@ +# stdint_h.m4 serial 3 (gettext-0.12) +dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists, +# doesn't clash with <sys/types.h>, and declares uintmax_t. + +AC_DEFUN([jm_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], jm_ac_cv_header_stdint_h, + [AC_TRY_COMPILE( + [#include <sys/types.h> +#include <stdint.h>], + [uintmax_t i = (uintmax_t) -1;], + jm_ac_cv_header_stdint_h=yes, + jm_ac_cv_header_stdint_h=no)]) + if test $jm_ac_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, + [Define if <stdint.h> exists, doesn't clash with <sys/types.h>, + and declares uintmax_t. ]) + fi +]) diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4 new file mode 100644 index 000000000..b5f28d440 --- /dev/null +++ b/m4/uintmax_t.m4 @@ -0,0 +1,32 @@ +# uintmax_t.m4 serial 7 (gettext-0.12) +dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +AC_PREREQ(2.13) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in <stdint.h> or <inttypes.h>. + +AC_DEFUN([jm_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([jm_AC_HEADER_STDINT_H]) + if test $jm_ac_cv_header_inttypes_h = no && test $jm_ac_cv_header_stdint_h = no; then + AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG]) + test $ac_cv_type_unsigned_long_long = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, + [Define to unsigned long or unsigned long long + if <stdint.h> and <inttypes.h> don't define.]) + else + AC_DEFINE(HAVE_UINTMAX_T, 1, + [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.]) + fi +]) diff --git a/m4/ulonglong.m4 b/m4/ulonglong.m4 new file mode 100644 index 000000000..c375e474c --- /dev/null +++ b/m4/ulonglong.m4 @@ -0,0 +1,23 @@ +# ulonglong.m4 serial 2 (fileutils-4.0.32, gettext-0.10.40) +dnl Copyright (C) 1999-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +AC_DEFUN([jm_AC_TYPE_UNSIGNED_LONG_LONG], +[ + AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, + [AC_TRY_LINK([unsigned long long ull = 1; int i = 63;], + [unsigned long long ullmax = (unsigned long long) -1; + return ull << i | ull >> i | ullmax / ull | ullmax % ull;], + ac_cv_type_unsigned_long_long=yes, + ac_cv_type_unsigned_long_long=no)]) + if test $ac_cv_type_unsigned_long_long = yes; then + AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, + [Define if you have the unsigned long long type.]) + fi +]) diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 000000000..b418cf26d --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,18 @@ +# Set of available languages. +# we have disabled most of them for now. +en@quot en@boldquot +#ca cs +#da +de +#eo el es et +#fi fr +#gl +#hu +#id it +#ja +#nl +#pl +#pt_BR pt +#sk sv +#tr +#zh_TW" diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 000000000..27b721aa8 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,353 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2003 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = @datadir@ +localedir = $(datadir)/locale +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +mkinstalldirs = $(SHELL) $(MKINSTALLDIRS) + +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in $(DOMAIN).pot stamp-po \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + test -z "$(CATALOGS)" || $(MAKE) $(CATALOGS) + @echo "touch stamp-po" + @echo timestamp > stamp-poT + @mv stamp-poT stamp-po + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address='$(MSGID_BUGS_ADDRESS)' + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + $(mkinstalldirs) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkinstalldirs) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + $(mkinstalldirs) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkinstalldirs) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + $(MAKE) update-po + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir); \ + else \ + cp -p $(srcdir)/$$file $(distdir); \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +Makefile: Makefile.in.in $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 000000000..5f46d237d --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,42 @@ +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 000000000..4b937aa51 --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 000000000..fedb6a06d --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 000000000..a9647fc35 --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 000000000..b26de01f6 --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 000000000..0122c4631 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sed b/po/remove-potcdate.sed new file mode 100644 index 000000000..edb38d704 --- /dev/null +++ b/po/remove-potcdate.sed @@ -0,0 +1,11 @@ +/^"POT-Creation-Date: .*"$/{ +x +s/P/P/ +ta +g +d +bb +:a +x +:b +} diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 000000000..2436c49e7 --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/scripts/config.rpath b/scripts/config.rpath new file mode 100755 index 000000000..fa24bfc2d --- /dev/null +++ b/scripts/config.rpath @@ -0,0 +1,548 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2003 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | pw32* | os2*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + newsos6) + ;; + linux*) + case $CC in + icc|ecc) + wl='-Wl,' + ;; + ccc) + wl='-Wl,' + ;; + esac + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + sco3.2v5*) + ;; + solaris*) + wl='-Wl,' + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + case "$host_os" in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris* | sysv5*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = yes; then + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + bsdi4*) + ;; + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + hardcode_direct=no + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd1*) + ld_shlibs=no + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10* | hpux11*) + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=no + ;; + ia64*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + *) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + openbsd*) + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + sco3.2v5*) + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4.2uw2*) + hardcode_direct=yes + hardcode_minus_L=no + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + ;; + sysv5*) + hardcode_libdir_flag_spec= + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. +libname_spec='lib$name' +case "$host_os" in + aix3*) + ;; + aix4* | aix5*) + ;; + amigaos*) + ;; + beos*) + ;; + bsdi4*) + ;; + cygwin* | mingw* | pw32*) + shrext=.dll + ;; + darwin* | rhapsody*) + shrext=.dylib + ;; + dgux*) + ;; + freebsd1*) + ;; + freebsd*) + ;; + gnu*) + ;; + hpux9* | hpux10* | hpux11*) + case "$host_cpu" in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux*) + ;; + netbsd*) + ;; + newsos6) + ;; + nto-qnx) + ;; + openbsd*) + ;; + os2*) + libname_spec='$name' + shrext=.dll + ;; + osf3* | osf4* | osf5*) + ;; + sco3.2v5*) + ;; + solaris*) + ;; + sunos4*) + ;; + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + ;; + sysv4*MP*) + ;; + uts4*) + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF + +# How to pass a linker flag through the compiler. +wl="$escaped_wl" + +# Static library suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally "so"). +shlibext="$shlibext" + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct="$hardcode_direct" + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L="$hardcode_minus_L" + +EOF diff --git a/scripts/mkinstalldirs b/scripts/mkinstalldirs new file mode 100755 index 000000000..d2d5f21b6 --- /dev/null +++ b/scripts/mkinstalldirs @@ -0,0 +1,111 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" 1>&2 + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +case $dirmode in + '') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi + ;; + *) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# End: +# mkinstalldirs ends here diff --git a/tools/ChangeLog b/tools/ChangeLog new file mode 100644 index 000000000..d34913df0 --- /dev/null +++ b/tools/ChangeLog @@ -0,0 +1,155 @@ +2003-12-06 David Shaw <dshaw@jabberwocky.com> + + * gpgsplit.c (write_part): Split off decompression code. + (handle_zlib): Move it here. + (handle_bzip2): Add this to handle BZIP2 compressed messages. + +2003-10-25 Werner Koch <wk@gnupg.org> + + * Makefile.am: Replaced INTLLIBS by LIBINTL. + +2003-08-24 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Use NETLIBS instead of EGDLIBS. + +2003-07-10 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Use W32LIBS where appropriate. + +2003-05-30 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Some cleanup, and use DLLIBS for -ldl. + +2003-05-24 David Shaw <dshaw@jabberwocky.com> + + * bftest.c, crlf.c, mk-tdata.c, mpicalc.c, shmtest.c: Edit all + preprocessor instructions to remove whitespace before the + '#'. This is not required by C89, but there are some compilers out + there that don't like it. + +2003-03-11 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Use @CAPLIBS@ to link in -lcap if we are using + capabilities. + +2003-02-22 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Distribute convert-from-106. + + * convert-from-106: Script to automate the 1.0.6->later + conversion. It marks all secret keys as ultimately trusted, adds + the signature caches, and checks the trustdb. Moved from the + scripts directory. + +2002-10-31 Stefan Bellon <sbellon@sbellon.de> + + * gpgsplit.c (write_part) [__riscos__]: Use riscos_load_module() + to load ZLib module. + +2002-10-23 Werner Koch <wk@gnupg.org> + + * gpgsplit.c: New options --secret-to-public and --no-split. + GNUified the indentation style. + +2002-09-25 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Link bftest with EGDLIBS (i.e. NETLIBS) as EGD uses + sockets. + +2002-05-07 Stefan Bellon <sbellon@sbellon.de> + + * gpgsplit.c (create_filename): Use EXTSEP_S instead of ".". + +2002-04-23 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Do not list libraries in -lxxx format in a + dependency line. + +2002-01-02 Stefan Bellon <sbellon@sbellon.de> + + * gpgsplit.c [__riscos__]: Added RISC OS specific file name + code. + + * gpgsplit.c (write_part): Introduced two explicit casts. + +2001-12-21 David Shaw <dshaw@jabberwocky.com> + + * gpgsplit.c (pkttype_to_string): PKT_PHOTO_ID -> PKT_ATTRIBUTE + +2001-10-23 Werner Koch <wk@gnupg.org> + + * Makefile.am (gpgsplit_LDADD): Add ZLIBS. + +2001-09-18 Werner Koch <wk@gnupg.org> + + * gpgsplit.c: New option --uncompress. + (write_part): Handle old style uncompressing. + +2001-06-20 Werner Koch <wk@gnupg.org> + + * gpgsplit.c: New. + * Makefile.am (bin_PROGRAMS): Install gpgsplit. + +2001-03-27 Werner Koch <wk@gnupg.org> + + * mail-signed-keys: Add option --dry-run. + +2001-03-21 Werner Koch <wk@gnupg.org> + + * shmtest.c: Add sys/types.h + +Fri Sep 15 18:40:36 CEST 2000 Werner Koch <wk@openit.de> + + * ring-a-party: An array start at offset 1 no 0. Many thanks to Mike + for finding this bug. + +Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> + + * ring-a-party: Flush the last key. + +Wed Jul 5 13:28:45 CEST 2000 Werner Koch <wk@> + + * mail-signed-keys: New. + +Tue May 23 09:19:00 CEST 2000 Werner Koch <wk@openit.de> + + * ring-a-party: New. + +Thu Jul 8 16:21:27 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * lspgpot: New + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Support for libtool. + +Tue Jun 8 13:36:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpicalc.c (main): hex digits may now be lowercase + (do_mulm): new. + +Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * mpicalc.c (main): Moved initialization out of definition. + +Mon May 18 15:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mk-tdata.c: New. + +Tue Apr 7 19:50:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * bftest.c: Now supports all availabe ciphers. + + + + Copyright 1998, 1999, 2000, 2001 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. + + diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 000000000..e52d49d36 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,33 @@ +# 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 + +## Process this file with automake to produce Makefile.in + +EXTRA_DIST = lspgpot ring-a-party mail-signed-keys convert-from-106 +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl +needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a + +bin_PROGRAMS = gpgsplit +noinst_PROGRAMS = mpicalc bftest clean-sat mk-tdata shmtest + +gpgsplit_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @ZLIBS@ +mpicalc_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @W32LIBS@ +bftest_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @W32LIBS@ @DLLIBS@ @NETLIBS@ +shmtest_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ + +gpgsplit mpicalc bftest shmtest: $(needed_libs) -- cgit v1.2.3 From be294cbb14337f928cffdf0d40e27206e26fd30e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 9 Dec 2003 09:07:09 +0000 Subject: Added files we better keep in the CVS --- m4/lib-prefix.m4 | 4 +- scripts/config.guess | 119 +- scripts/config.sub | 122 +- scripts/depcomp | 264 +- scripts/install-sh | 151 +- scripts/mdate-sh | 133 + scripts/missing | 10 +- scripts/texinfo.tex | 6773 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 7244 insertions(+), 332 deletions(-) create mode 100755 scripts/mdate-sh create mode 100644 scripts/texinfo.tex diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 index 26874b267..c719bc809 100644 --- a/m4/lib-prefix.m4 +++ b/m4/lib-prefix.m4 @@ -1,4 +1,4 @@ -# lib-prefix.m4 serial 3 (gettext-0.12.2) +# lib-prefix.m4 serial 2 (gettext-0.12) dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General @@ -13,7 +13,7 @@ dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], -[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that diff --git a/scripts/config.guess b/scripts/config.guess index 27d87fa73..ed2e03b7f 100755 --- a/scripts/config.guess +++ b/scripts/config.guess @@ -3,7 +3,7 @@ # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. -timestamp='2002-11-08' +timestamp='2002-03-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -88,40 +88,30 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 +# CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -# This shell variable is my proudest work .. or something. --bje - -set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; -(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) - || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; -dummy=$tmpdir/dummy ; -files="$dummy.c $dummy.o $dummy.rel $dummy" ; -trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; +set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; + if test $? = 0 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $files ; + rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; -unset files' +esac' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -152,7 +142,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; @@ -231,7 +220,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - eval $set_cc_for_build cat <<EOF >$dummy.s .data \$Lformat: @@ -257,9 +245,10 @@ main: jsr \$26,exit .end main EOF - $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null + eval $set_cc_for_build + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then - case `$dummy` in + case `./$dummy` in 0-0) UNAME_MACHINE="alpha" ;; @@ -281,12 +270,9 @@ EOF 2-1307) UNAME_MACHINE="alphaev68" ;; - 3-1307) - UNAME_MACHINE="alphaev7" - ;; esac fi - rm -f $dummy.s $dummy && rmdir $tmpdir + rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) @@ -327,10 +313,6 @@ EOF NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; - DRS?6000:UNIX_SV:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7 && exit 0 ;; - esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; @@ -437,21 +419,15 @@ EOF exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c \ - && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 - rm -f $dummy.c $dummy && rmdir $tmpdir + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit 0 ;; - Night_Hawk:*:*:PowerMAX_OS) - echo powerpc-harris-powermax - exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; @@ -524,8 +500,8 @@ EOF exit(0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 - rm -f $dummy.c $dummy && rmdir $tmpdir + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 @@ -623,9 +599,9 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy && rmdir $tmpdir + rm -f $dummy.c $dummy fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -661,8 +637,8 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 - rm -f $dummy.c $dummy && rmdir $tmpdir + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) @@ -745,19 +721,7 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) - # Determine whether the default compiler uses glibc. - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include <features.h> - #if __GLIBC__ >= 2 - LIBC=gnu - #else - LIBC= - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c && rmdir $tmpdir - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin @@ -818,7 +782,7 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - rm -f $dummy.c && rmdir $tmpdir + rm -f $dummy.c test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) @@ -881,7 +845,7 @@ EOF ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; + exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; @@ -914,7 +878,7 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c && rmdir $tmpdir + rm -f $dummy.c test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; @@ -953,13 +917,13 @@ EOF UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else @@ -992,15 +956,9 @@ EOF # "miniframe" echo m68010-convergent-sysv exit 0 ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit 0 ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` @@ -1091,9 +1049,6 @@ EOF SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; @@ -1114,7 +1069,7 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; - NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) @@ -1286,8 +1241,8 @@ main () } EOF -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 -rm -f $dummy.c $dummy && rmdir $tmpdir +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy # Apollos put the system type in the environment. diff --git a/scripts/config.sub b/scripts/config.sub index c4f0b2f52..f3657978c 100755 --- a/scripts/config.sub +++ b/scripts/config.sub @@ -3,7 +3,7 @@ # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. -timestamp='2002-11-08' +timestamp='2002-03-07' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -118,7 +118,7 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -229,34 +229,24 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ - | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mipsisa32 | mipsisa32el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ + | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 | mipsisa64 \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ + | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ @@ -291,45 +281,34 @@ case $basic_machine in | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | arm-* | armbe-* | armle-* | armv*-* \ | avr-* \ | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ | clipper-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ + | d10v-* | d30v-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39 | mipstx39el \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ @@ -749,13 +728,13 @@ case $basic_machine in pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) + pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) @@ -776,22 +755,22 @@ case $basic_machine in power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown - ;; + ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown - ;; + ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown - ;; + ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; @@ -822,12 +801,6 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; sequent) basic_machine=i386-sequent ;; @@ -893,7 +866,7 @@ case $basic_machine in sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; - sv1) + sv1) basic_machine=sv1-cray os=-unicos ;; @@ -913,10 +886,6 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic4x | c4x*) - basic_machine=tic4x-unknown - os=-coff - ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff @@ -955,8 +924,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -981,7 +950,7 @@ case $basic_machine in basic_machine=i386-pc os=-windows32-msvcrt ;; - xps | xps100) + xps | xps100) basic_machine=xps100-honeywell ;; ymp) @@ -1027,7 +996,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + sh3 | sh4 | sh3eb | sh4eb) basic_machine=sh-unknown ;; sh64) @@ -1036,7 +1005,7 @@ case $basic_machine in sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -1051,6 +1020,10 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -1117,8 +1090,7 @@ case $os in | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix*) + | -morphos* | -superux* | -rtmk* | -rtmk-nova*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1183,7 +1155,7 @@ case $os in os=-rtmk-nova ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1222,8 +1194,8 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint ;; -none) ;; @@ -1260,7 +1232,7 @@ case $basic_machine in pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1353,19 +1325,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1437,7 +1409,7 @@ case $basic_machine in -ptx*) vendor=sequent ;; - -vxsim* | -vxworks* | -windiss*) + -vxsim* | -vxworks*) vendor=wrs ;; -aux*) diff --git a/scripts/depcomp b/scripts/depcomp index 3480ce4e9..aea3d0078 100755 --- a/scripts/depcomp +++ b/scripts/depcomp @@ -206,19 +206,61 @@ aix) rm -f "$tmpdepfile" ;; +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - base=`echo "$object" | sed -e 's/\.o$//' -e 's/\.lo$//'` - tmpdepfile1="$base.o.d" - tmpdepfile2="$base.d" if test "$libtool" = yes; then + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir.libs/$base.d" "$@" -Wc,-MD else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" "$@" -MD fi @@ -250,34 +292,42 @@ tru64) dashmstdout) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - test -z "$dashmflag" && dashmflag=-M - ( IFS=" " - case " $* " in - *" --mode=compile "*) # this is libtool, let us make it quiet - for arg - do # cycle over the arguments - case "$arg" in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done + # always write the proprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg ;; esac - "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' @@ -295,33 +345,37 @@ dashXmstdout) ;; makedepend) - # X makedepend - ( - shift - cleared=no - for arg in "$@"; do - case $cleared in no) - set ""; shift - cleared=yes - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift;; - -*) - ;; - *) - set fnord "$@" "$arg"; shift;; - esac + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' @@ -334,35 +388,39 @@ makedepend) cpp) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - ( IFS=" " - case " $* " in - *" --mode=compile "*) - for arg - do # cycle over the arguments - case $arg in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done + # always write the proprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg ;; esac - "$@" -E | + done + + "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" @@ -374,47 +432,25 @@ msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. - ( IFS=" " - case " $* " in - *" --mode=compile "*) - for arg - do # cycle over the arguments - case $arg in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done - ;; - esac - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; - *) + *) set fnord "$@" "$arg" shift shift ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" diff --git a/scripts/install-sh b/scripts/install-sh index 398a88e14..6ce63b9f7 100755 --- a/scripts/install-sh +++ b/scripts/install-sh @@ -1,19 +1,37 @@ #!/bin/sh # # install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). # -# Copyright 1991 by the Massachusetts Institute of Technology +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. # -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it @@ -56,7 +74,7 @@ dir_arg="" while [ x"$1" != x ]; do case $1 in - -c) instcmd="$cpprog" + -c) instcmd=$cpprog shift continue;; @@ -79,7 +97,7 @@ while [ x"$1" != x ]; do shift continue;; - -s) stripcmd="$stripprog" + -s) stripcmd=$stripprog shift continue;; @@ -106,7 +124,7 @@ done if [ x"$src" = x ] then - echo "install: no input file specified" + echo "$0: no input file specified" >&2 exit 1 else : @@ -115,8 +133,8 @@ fi if [ x"$dir_arg" != x ]; then dst=$src src="" - - if [ -d $dst ]; then + + if [ -d "$dst" ]; then instcmd=: chmodcmd="" else @@ -125,20 +143,20 @@ if [ x"$dir_arg" != x ]; then else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad +# might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. - if [ -f $src -o -d $src ] + if [ -f "$src" ] || [ -d "$src" ] then : else - echo "install: $src does not exist" + echo "$0: $src does not exist" >&2 exit 1 fi - + if [ x"$dst" = x ] then - echo "install: no destination specified" + echo "$0: no destination specified" >&2 exit 1 else : @@ -147,16 +165,16 @@ else # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic - if [ -d $dst ] + if [ -d "$dst" ] then - dst="$dst"/`basename $src` + dst=$dst/`basename "$src"` else : fi fi ## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` +dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script @@ -165,69 +183,73 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` if [ ! -d "$dstdir" ]; then defaultIFS=' ' -IFS="${IFS-${defaultIFS}}" +IFS="${IFS-$defaultIFS}" -oIFS="${IFS}" +oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" +set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS=$oIFS pathcomp='' while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" + pathcomp=$pathcomp$1 shift - if [ ! -d "${pathcomp}" ] ; + if [ ! -d "$pathcomp" ] ; then - $mkdirprog "${pathcomp}" + $mkdirprog "$pathcomp" else : fi - pathcomp="${pathcomp}/" + pathcomp=$pathcomp/ done fi if [ x"$dir_arg" != x ] then - $doit $instcmd $dst && + $doit $instcmd "$dst" && - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi else # If we're going to rename the final executable, determine the name now. - if [ x"$transformarg" = x ] + if [ x"$transformarg" = x ] then - dstfile=`basename $dst` + dstfile=`basename "$dst"` else - dstfile=`basename $dst $transformbasename | + dstfile=`basename "$dst" $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename - if [ x"$dstfile" = x ] + if [ x"$dstfile" = x ] then - dstfile=`basename $dst` + dstfile=`basename "$dst"` else : fi -# Make a temp file name in the proper directory. +# Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/#inst.$$# + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ -# Move or copy the file name to the temp name +# Trap to clean up temp files at exit. - $doit $instcmd $src $dsttmp && + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 - trap "rm -f ${dsttmp}" 0 && +# Move or copy the file name to the temp name + + $doit $instcmd "$src" "$dsttmp" && # and set any options; do chmod last to preserve setuid bits @@ -235,17 +257,38 @@ else # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && + +# Now remove or move aside any old file at destination location. We try this +# two ways since rm can't unlink itself on some systems and the destination +# file might be busy for other reasons. In this case, the final cleanup +# might fail but the new file should still install successfully. + +{ + if [ -f "$dstdir/$dstfile" ] + then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || + $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || + { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi +} && # Now rename the file to the real destination. - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" fi && +# The final little trick to "correctly" pass the exit status to the exit trap. -exit 0 +{ + (exit 0); exit +} diff --git a/scripts/mdate-sh b/scripts/mdate-sh new file mode 100755 index 000000000..b610b47a6 --- /dev/null +++ b/scripts/mdate-sh @@ -0,0 +1,133 @@ +#!/bin/sh +# Get modification time of a file or directory and pretty-print it. +# Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. +# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995 +# +# 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, 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Prevent date giving response in another language. +LANG=C +export LANG +LC_ALL=C +export LC_ALL +LC_TIME=C +export LC_TIME + +save_arg1="$1" + +# Find out how to get the extended ls output of a file or directory. +if ls -L /dev/null 1>/dev/null 2>&1; then + ls_command='ls -L -l -d' +else + ls_command='ls -l -d' +fi + +# A `ls -l' line looks as follows on OS/2. +# drwxrwx--- 0 Aug 11 2001 foo +# This differs from Unix, which adds ownership information. +# drwxrwx--- 2 root root 4096 Aug 11 2001 foo +# +# To find the date, we split the line on spaces and iterate on words +# until we find a month. This cannot work with files whose owner is a +# user named `Jan', or `Feb', etc. However, it's unlikely that `/' +# will be owned by a user whose name is a month. So we first look at +# the extended ls output of the root directory to decide how many +# words should be skipped to get the date. + +# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. +set - x`$ls_command /` + +# Find which argument is the month. +month= +command= +until test $month +do + shift + # Add another shift to the command. + command="$command shift;" + case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; + esac +done + +# Get the extended ls output of the file or directory. +set - x`eval "$ls_command \"\$save_arg1\""` + +# Remove all preceding arguments +eval $command + +# Get the month. Next argument is day, followed by the year or time. +case $1 in + Jan) month=January; nummonth=1;; + Feb) month=February; nummonth=2;; + Mar) month=March; nummonth=3;; + Apr) month=April; nummonth=4;; + May) month=May; nummonth=5;; + Jun) month=June; nummonth=6;; + Jul) month=July; nummonth=7;; + Aug) month=August; nummonth=8;; + Sep) month=September; nummonth=9;; + Oct) month=October; nummonth=10;; + Nov) month=November; nummonth=11;; + Dec) month=December; nummonth=12;; +esac + +day=$2 + +# Here we have to deal with the problem that the ls output gives either +# the time of day or the year. +case $3 in + *:*) set `date`; eval year=\$$# + case $2 in + Jan) nummonthtod=1;; + Feb) nummonthtod=2;; + Mar) nummonthtod=3;; + Apr) nummonthtod=4;; + May) nummonthtod=5;; + Jun) nummonthtod=6;; + Jul) nummonthtod=7;; + Aug) nummonthtod=8;; + Sep) nummonthtod=9;; + Oct) nummonthtod=10;; + Nov) nummonthtod=11;; + Dec) nummonthtod=12;; + esac + # For the first six month of the year the time notation can also + # be used for files modified in the last year. + if (expr $nummonth \> $nummonthtod) > /dev/null; + then + year=`expr $year - 1` + fi;; + *) year=$3;; +esac + +# The result. +echo $day $month $year diff --git a/scripts/missing b/scripts/missing index dd583709f..6a37006e8 100755 --- a/scripts/missing +++ b/scripts/missing @@ -1,6 +1,6 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. # Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. # This program is free software; you can redistribute it and/or modify @@ -293,23 +293,23 @@ WARNING: \`$1' is missing on your system. You should only need it if # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then - gnutar ${1+"$@"} && exit 0 + gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then - gtar ${1+"$@"} && exit 0 + gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" ${1+"$@"} && exit 0 + tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" ${1+"$@"} && exit 0 + tar "$firstarg" "$@" && exit 0 ;; esac fi diff --git a/scripts/texinfo.tex b/scripts/texinfo.tex new file mode 100644 index 000000000..e9293f3b9 --- /dev/null +++ b/scripts/texinfo.tex @@ -0,0 +1,6773 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2003-05-04.08} +% +% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +% +% This texinfo.tex file 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, or (at +% your option) any later version. +% +% This texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% In other words, you are welcome to use, share and improve this program. +% You are forbidden to forbid anyone else to use, share and improve +% what you give them. Help stamp out software-hoarding! +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% ftp://ftp.gnu.org/gnu/texinfo/texinfo.tex +% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html) +% ftp://tug.org/tex/texinfo.tex +% (and all CTAN mirrors, see http://www.ctan.org), +% and /home/gd/gnu/doc/texinfo.tex on the GNU machines. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. +% +% The texinfo.tex in any given Texinfo distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +\message{Basics,} +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexindent=\indent +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexplus=+ +\let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexstar=\* +\let\ptext=\t + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi +\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi + +% In some macros, we cannot use the `\? notation---the left quote is +% in some cases the escape char. +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dotChar = `\. +\chardef\equalChar = `\= +\chardef\exclamChar= `\! +\chardef\questChar = `\? +\chardef\semiChar = `\; +\chardef\spaceChar = `\ % +\chardef\underChar = `\_ + +% Ignore a token. +% +\def\gobble#1{} + +% True if #1 is the empty string, i.e., called like `\ifempty{}'. +% +\def\ifempty#1{\ifemptyx #1\emptymarkA\emptymarkB}% +\def\ifemptyx#1#2\emptymarkB{\ifx #1\emptymarkA}% + +% Hyphenation fixes. +\hyphenation{ap-pen-dix} +\hyphenation{eshell} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{time-stamp} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\undefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines\maxdimen +}% + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \escapechar = `\\ % use backslash in output files. + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfmkdest{\the\pageno} \fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \normalturnoffactive + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment; press RETURN to continue} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Press RETURN to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux file. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \copy\groupbox + \endgroup % End the \group. + }% + % + \setbox\groupbox = \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{% + \leavevmode + \hbox to 1.5em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \leavevmode + \hbox to 2em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% + \spacefactor=3000 +} + +% @page forces the start of a new page. +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \let\value=\expandablevalue + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\def\center{\parsearg\docenter} +\def\docenter#1{{% + \ifhmode \hfil\break \fi + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{\hfil \ignorespaces#1\unskip \hfil}% + \ifhmode \break \fi +}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\def\paragraphindent{\parsearg\doparagraphindent} +\def\doparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\def\exampleindent{\parsearg\doexampleindent} +\def\doexampleindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indentat such +% paragraphs. +% +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. We +% switch the definition of this back and forth according to WORD. By +% default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\newdimen\currentparindent +% +\def\insertword{insert} +% +\def\firstparagraphindent{\parsearg\dofirstparagraphindent} +\def\dofirstparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi +} + +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. +% +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent{% + \global\let\indent=\ptexindent + \global\everypar = {}% + }% + \global\everypar = {% + \kern-\parindent + \global\let\indent=\ptexindent + \global\everypar = {}% + }% +}% + + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% We don't use $'s directly in the definition of \math because we need +% to set catcodes according to plain TeX first, to allow for subscripts, +% superscripts, special math chars, etc. +% +\let\implicitmath = $%$ font-lock fix +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ within @math be active (mathcode "8000), and distinguish by seeing +% if the current family is \slfam, which is what @var uses. +% +{\catcode\underChar = \active +\gdef\mathunderscore{% + \catcode\underChar=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% +}} +% +% Another complication: we want \\ (and @\) to output a \ character. +% FYI, plain.tex uses \\ as a temporary control sequence (why?), but +% this is not advertised and we don't care. Texinfo does not +% otherwise define @\. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathcode`\_="8000 \mathunderscore + \let\\ = \mathbackslash + \mathactive + \implicitmath\finishmath} +\def\finishmath#1{#1\implicitmath\Etex} + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an +% argument to a command which set the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + } +} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \iflinks + \readauxfile + \fi % \openindices needs to do some work in any case. + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + % Just to be on the safe side, close the input stream before the \input. + \openin 1 texinfo.cnf + \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi + \closein1 + \temp + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +\ifx\pdfoutput\undefined + \pdffalse + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\else + \pdftrue + \pdfoutput = 1 + \input pdfcolor + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}% + \def\imageheight{#3}% + % without \immediate, pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifx\empty\imagewidth\else width \imagewidth \fi + \ifx\empty\imageheight\else height \imageheight \fi + \ifnum\pdftexversion<13 + #1.pdf% + \else + {#1.pdf}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + \def\pdfmkdest#1{{\normalturnoffactive \pdfdest name{#1} xyz}} + \def\pdfmkpgn#1{#1} + \let\linkcolor = \Blue % was Cyan, but that seems light? + \def\endlink{\Black\pdfendlink} + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + \def\pdfmakeoutlines{{% + \openin 1 \jobname.toc + \ifeof 1\else\begingroup + \closein 1 + % Thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + \def\chapentry ##1##2##3{} + \def\secentry ##1##2##3##4{\advancenumber{chap##2}} + \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}} + \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}} + \let\appendixentry = \chapentry + \let\unnumbchapentry = \chapentry + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + \input \jobname.toc + \def\chapentry ##1##2##3{% + \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}} + \def\secentry ##1##2##3##4{% + \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}} + \def\subsecentry ##1##2##3##4##5{% + \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}} + \def\subsubsecentry ##1##2##3##4##5##6{% + \pdfoutline goto name{\pdfmkpgn{##6}}{##1}} + \let\appendixentry = \chapentry + \let\unnumbchapentry = \chapentry + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + % + % Make special characters normal for writing to the pdf file. + % + \indexnofonts + \let\tt=\relax + \turnoffactive + \input \jobname.toc + \endgroup\fi + }} + \def\makelinks #1,{% + \def\params{#1}\def\E{END}% + \ifx\params\E + \let\nextmakelinks=\relax + \else + \let\nextmakelinks=\makelinks + \ifnum\lnkcount>0,\fi + \picknum{#1}% + \startlink attr{/Border [0 0 0]} + goto name{\pdfmkpgn{\the\pgn}}% + \linkcolor #1% + \advance\lnkcount by 1% + \endlink + \fi + \nextmakelinks + } + \def\picknum#1{\expandafter\pn#1} + \def\pn#1{% + \def\p{#1}% + \ifx\p\lbrace + \let\nextpn=\ppn + \else + \let\nextpn=\ppnn + \def\first{#1} + \fi + \nextpn + } + \def\ppn#1{\pgn=#1\gobble} + \def\ppnn{\pgn=\first} + \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + \def\pdfurl#1{% + \begingroup + \normalturnoffactive\def\@{@}% + \let\value=\expandablevalue + \leavevmode\Red + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + % #1 + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS| + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \linkcolor #1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\fi % \ifx\pdfoutput + + +\message{fonts,} +% Font-change commands. + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Default leading. +\newdimen\textleading \textleading = 13.2pt + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\newcount\mainmagstep +\ifx\bigger\relax + % not really supported. + \mainmagstep=\magstep1 + \setfont\textrm\rmshape{12}{1000} + \setfont\texttt\ttshape{12}{1000} +\else + \mainmagstep=\magstephalf + \setfont\textrm\rmshape{10}{\mainmagstep} + \setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you may want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10 +% (in Bob's opinion). +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for small examples (8pt). +\setfont\smallerrm\rmshape{8}{1000} +\setfont\smallertt\ttshape{8}{1000} +\setfont\smallerbf\bfshape{10}{800} +\setfont\smallerit\itshape{8}{1000} +\setfont\smallersl\slshape{8}{1000} +\setfont\smallersf\sfshape{8}{1000} +\setfont\smallersc\scshape{10}{800} +\setfont\smallerttsl\ttslshape{10}{800} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} + +% Chapter (and unnumbered) fonts (17.28pt). +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% Subsection fonts (13.15pt). +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \resetmathfonts \setleading{9.5pt}} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \smallerfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% +% I wish we used A4 paper on this side of the Atlantic. +% +% --karl, 24jan03. + + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} +\setfont\shortconttt\ttshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else + \ptexslash\fi\fi\fi} +\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic +\let\cite=\smartslanted + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\frenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + } +\catcode`@=\other + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \let-\codedash + \catcode`\_=\active \let_\codeunder + \codex + } + % + % If we end up with any active - characters when handling the index, + % just treat them as a normal -. + \global\def\indexbreaks{\catcode`\-=\active \let-\realdash} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} +\def\codex #1{\tclose{#1}\endgroup} + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\def\kbdinputstyle{\parsearg\kbdinputstylexxx} +\def\kbdinputstylexxx#1{% + \def\arg{#1}% + \ifx\arg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle option `\arg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct.' +\kbdinputstyle distinct + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @url, @env, @command quotes seem unnecessary, so use \code. +\let\url=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym downcases the argument and prints in smallcaps. +\def\acronym#1{{\smallcaps \lowercase{#1}}} + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + +% @registeredsymbol - R in a circle. For now, only works in text size; +% we'd have to redo the font mechanism to change the \scriptstyle and +% \scriptscriptstyle font sizes to make it look right in headings. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{$\scriptstyle\rm R$}\hfil\crcr\Orb}}% + }$% +} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefonts\rm ##1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\undefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. (Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue.) However, if what follows is an environment + % such as @example, there will be no \parskip glue; then + % the negative vskip we just would cause the example and the item to + % crash together. So we use this bizarre value of 10001 as a signal + % to \aboveenvbreak to insert \parskip glue after all. + % (Possibly there are other commands that could be followed by + % @example which need the same treatment, but not section titles; or + % maybe section titles are the only special case and they should be + % penalty 10001...) + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +% Contains a kludge to get @end[description] to work. +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +% @table, @ftable, @vtable. +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey#1#2{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + \def#2{\endgraf\afterenvbreak\endgroup}% + \def\itemcontents{#1}% + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + \let\item=\itemizeitem +} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{In hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multitable or @end multitable do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the part of the @columnfraction before the decimal point, which +% is presumably either 0 or the empty string (but we don't check, we +% just throw it away). #2 is the decimal part, which we use as the +% percent of \hsize for this column. +\def\pickupwholefraction#1.#2 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% @multitable ... @end multitable definitions: +% +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item=\crcrwithfootnotes + % A \tab used to include \hskip1sp. But then the space in a template + % line is not enough. That is bad. So let's go back to just & until + % we encounter the problem it was intended to solve again. --karl, + % nathan@acm.org, 20apr99. + \let\tab=&% + \let\startfootins=\startsavedfootnote + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{% + \global\setpercentfalse + \crcrwithfootnotes\crcr + \egroup\egroup + }% + % + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. + \everycr{\noalign{% + % + % \filbreak%% keeps underfull box messages off when table breaks over pages. + % Maybe so, but it also creates really weird page breaks when the table + % breaks over pages. Wouldn't \vfil be better? Wait until the problem + % manifests itself, so it can be fixed for real --karl. + \global\colcount=0\relax}}% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup&\global\advance\colcount by 1\relax + \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively marking + % characters. + \noindent\ignorespaces##\unskip\multistrut}\cr +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\let\multistrut = \strut +\else +%% FIXME: what is \box0 supposed to be? +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + +% In case a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is +% finished. Otherwise, the insertion is lost, it never migrates to the +% main vertical list. --kasal, 22jan03. +% +\newbox\savedfootnotes +% +% \dotable \let's \startfootins to this, so that \dofootnote will call +% it instead of starting the insertion right away. +\def\startsavedfootnote{% + \global\setbox\savedfootnotes = \vbox\bgroup + \unvbox\savedfootnotes +} +\def\crcrwithfootnotes{% + \crcr + \ifvoid\savedfootnotes \else + \noalign{\insert\footins{\box\savedfootnotes}}% + \fi +} + +\message{conditionals,} +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% + \let\chapter=\relax + \let\unnumbered=\relax + \let\top=\relax + \let\unnumberedsec=\relax + \let\unnumberedsection=\relax + \let\unnumberedsubsec=\relax + \let\unnumberedsubsection=\relax + \let\unnumberedsubsubsec=\relax + \let\unnumberedsubsubsection=\relax + \let\section=\relax + \let\subsec=\relax + \let\subsubsec=\relax + \let\subsection=\relax + \let\subsubsection=\relax + \let\appendix=\relax + \let\appendixsec=\relax + \let\appendixsection=\relax + \let\appendixsubsec=\relax + \let\appendixsubsection=\relax + \let\appendixsubsubsec=\relax + \let\appendixsubsubsection=\relax + \let\contents=\relax + \let\smallbook=\relax + \let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +% We use \empty instead of \relax for the @def... commands, so that \end +% doesn't throw an error. For instance: +% @ignore +% @deffn ... +% @end deffn +% @end ignore +% +% The @end deffn is going to get expanded, because we're trying to allow +% nested conditionals. But we don't want to expand the actual @deffn, +% since it might be syntactically correct and intended to be ignored. +% Since \end checks for \relax, using \empty does not cause an error. +% +\def\ignoremorecommands{% + \let\defcodeindex = \relax + \let\defcv = \empty + \let\defcvx = \empty + \let\Edefcv = \empty + \let\deffn = \empty + \let\deffnx = \empty + \let\Edeffn = \empty + \let\defindex = \relax + \let\defivar = \empty + \let\defivarx = \empty + \let\Edefivar = \empty + \let\defmac = \empty + \let\defmacx = \empty + \let\Edefmac = \empty + \let\defmethod = \empty + \let\defmethodx = \empty + \let\Edefmethod = \empty + \let\defop = \empty + \let\defopx = \empty + \let\Edefop = \empty + \let\defopt = \empty + \let\defoptx = \empty + \let\Edefopt = \empty + \let\defspec = \empty + \let\defspecx = \empty + \let\Edefspec = \empty + \let\deftp = \empty + \let\deftpx = \empty + \let\Edeftp = \empty + \let\deftypefn = \empty + \let\deftypefnx = \empty + \let\Edeftypefn = \empty + \let\deftypefun = \empty + \let\deftypefunx = \empty + \let\Edeftypefun = \empty + \let\deftypeivar = \empty + \let\deftypeivarx = \empty + \let\Edeftypeivar = \empty + \let\deftypemethod = \empty + \let\deftypemethodx = \empty + \let\Edeftypemethod = \empty + \let\deftypeop = \empty + \let\deftypeopx = \empty + \let\Edeftypeop = \empty + \let\deftypevar = \empty + \let\deftypevarx = \empty + \let\Edeftypevar = \empty + \let\deftypevr = \empty + \let\deftypevrx = \empty + \let\Edeftypevr = \empty + \let\defun = \empty + \let\defunx = \empty + \let\Edefun = \empty + \let\defvar = \empty + \let\defvarx = \empty + \let\Edefvar = \empty + \let\defvr = \empty + \let\defvrx = \empty + \let\Edefvr = \empty + \let\clear = \relax + \let\down = \relax + \let\evenfooting = \relax + \let\evenheading = \relax + \let\everyfooting = \relax + \let\everyheading = \relax + \let\headings = \relax + \let\include = \relax + \let\item = \relax + \let\lowersections = \relax + \let\oddfooting = \relax + \let\oddheading = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\raisesections = \relax + \let\ref = \relax + \let\set = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\settitle = \relax + \let\up = \relax + \let\verbatiminclude = \relax + \let\xref = \relax +} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescriptionword{documentdescription} +\def\documentdescription{\doignore{documentdescription}} +\def\html{\doignore{html}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory = \comment + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + % This @ is a catcode 12 token (that is the normal catcode of @ in + % this texinfo.tex file). We change the catcode of @ below to match. + \long\def\doignoretext##1@end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode\spaceChar = 10 + % + % Ignore braces, too, so mismatched braces don't cause trouble. + \catcode`\{ = 9 + \catcode`\} = 9 + % + % We must not have @c interpreted as a control sequence. + \catcode`\@ = 12 + % + \def\ignoreword{#1}% + \ifx\ignoreword\documentdescriptionword + % The c kludge breaks documentdescription, since + % `documentdescription' contains a `c'. Means not everything will + % be ignored inside @documentdescription, but oh well... + \else + % Make the letter c a comment character so that the rest of the line + % will be ignored. This way, the document can have (for example) + % @c @end ifinfo + % and the @end ifinfo will be properly ignored. + % (We've just changed @ to catcode 12.) + \catcode`\c = 14 + \fi + % + % And now expand the command defined above. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{WARNING: for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{ (See ftp://ftp.gnu.org/non-gnu/TeX.README.)} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the chance of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because some sites + % might not have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm=\nullfont \let\tenit=\nullfont \let\tensl=\nullfont + \let\tenbf=\nullfont \let\tentt=\nullfont \let\smallcaps=\nullfont + \let\tensf=\nullfont + % Similarly for index fonts. + \let\smallrm=\nullfont \let\smallit=\nullfont \let\smallsl=\nullfont + \let\smallbf=\nullfont \let\smalltt=\nullfont \let\smallsc=\nullfont + \let\smallsf=\nullfont + % Similarly for smallexample fonts. + \let\smallerrm=\nullfont \let\smallerit=\nullfont \let\smallersl=\nullfont + \let\smallerbf=\nullfont \let\smallertt=\nullfont \let\smallersc=\nullfont + \let\smallersf=\nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex. + \def\tex{\doignore{tex}}% + % Do not execute macro definitions. + % `c' is a comment character, so the word `macro' will get cut off. + \def\macro{\doignore{ma}}% +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +{ + \catcode`\_ = \active + % + % We might end up with active _ or - characters in the argument if + % we're called from @code, as @code{@value{foo-bar_}}. So \let any + % such active characters to their normal equivalents. + \gdef\value{\begingroup + \catcode`\-=\other \catcode`\_=\other + \indexbreaks \let_\normalunderscore + \valuexxx} +} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we \let\value to this in \indexdummies). Ones +% whose names contain - or _ still won't work, but we can't do anything +% about that. The command has to be fully expandable (if the variable +% is set), since the result winds up in the index file. This means that +% if the variable's value contains other Texinfo commands, it's almost +% certain it will fail (although perhaps we could fix that with +% sufficient work to do a one-level expansion on the result, instead of +% complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\doifset} +\def\doifset#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \let\next=\ifsetfail + \else + \let\next=\ifsetsucceed + \fi + \next +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\doifclear} +\def\doifclear#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \let\next=\ifclearsucceed + \else + \let\next=\ifclearfail + \fi + \next +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex, @ifnothtml, @ifnotinfo, @ifnotplaintext always succeed; we +% read the text following, through the first @end iftex (etc.). Make +% `@end iftex' (etc.) valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\def\ifnothtml{\conditionalsucceed{ifnothtml}} +\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} +\def\ifnotplaintext{\conditionalsucceed{ifnotplaintext}} +\defineunmatchedend{iftex} +\defineunmatchedend{ifnothtml} +\defineunmatchedend{ifnotinfo} +\defineunmatchedend{ifnotplaintext} + +% True conditional. Since \set globally defines its variables, we can +% just start and end a group (to keep the @end definition undefined at +% the outer level). +% +\def\conditionalsucceed#1{\begingroup + \expandafter\def\csname E#1\endcsname{\endgroup}% +} + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \undefined + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname\donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % Need these in case \tex is in effect and \{ is a \delimiter again. + % But can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. + \let\{ = \mylbrace + \let\} = \myrbrace + % + % \definedummyword defines \#1 as \realbackslash #1\space, thus + % effectively preventing its expansion. This is used only for control + % words, not control letters, because the \space would be incorrect + % for control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword##1{% + \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}% + }% + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% + }% + % + % Do the redefinitions. + \commondummies +} + +% For the aux file, @ is the escape character. So we want to redefine +% everything using @ instead of \realbackslash. When everything uses +% @, this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % (See comments in \indexdummies.) + \def\definedummyword##1{% + \expandafter\def\csname ##1\endcsname{@##1\space}% + }% + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{@##1}% + }% + % + % Do the redefinitions. + \commondummies +} + +% Called from \indexdummies and \atdummies. \definedummyword and +% \definedummyletter must be defined first. +% +\def\commondummies{% + % + \normalturnoffactive + % + % Control letters and accents. + \definedummyletter{_}% + \definedummyletter{,}% + \definedummyletter{"}% + \definedummyletter{`}% + \definedummyletter{'}% + \definedummyletter{^}% + \definedummyletter{~}% + \definedummyletter{=}% + \definedummyword{u}% + \definedummyword{v}% + \definedummyword{H}% + \definedummyword{dotaccent}% + \definedummyword{ringaccent}% + \definedummyword{tieaccent}% + \definedummyword{ubaraccent}% + \definedummyword{udotaccent}% + \definedummyword{dotless}% + % + % Other non-English letters. + \definedummyword{AA}% + \definedummyword{AE}% + \definedummyword{L}% + \definedummyword{OE}% + \definedummyword{O}% + \definedummyword{aa}% + \definedummyword{ae}% + \definedummyword{l}% + \definedummyword{oe}% + \definedummyword{o}% + \definedummyword{ss}% + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword{bf}% + \definedummyword{gtr}% + \definedummyword{hat}% + \definedummyword{less}% + \definedummyword{sf}% + \definedummyword{sl}% + \definedummyword{tclose}% + \definedummyword{tt}% + % + % Texinfo font commands. + \definedummyword{b}% + \definedummyword{i}% + \definedummyword{r}% + \definedummyword{sc}% + \definedummyword{t}% + % + \definedummyword{TeX}% + \definedummyword{acronym}% + \definedummyword{cite}% + \definedummyword{code}% + \definedummyword{command}% + \definedummyword{dfn}% + \definedummyword{dots}% + \definedummyword{emph}% + \definedummyword{env}% + \definedummyword{file}% + \definedummyword{kbd}% + \definedummyword{key}% + \definedummyword{math}% + \definedummyword{option}% + \definedummyword{samp}% + \definedummyword{strong}% + \definedummyword{uref}% + \definedummyword{url}% + \definedummyword{var}% + \definedummyword{w}% + % + % Assorted special characters. + \definedummyword{bullet}% + \definedummyword{copyright}% + \definedummyword{dots}% + \definedummyword{enddots}% + \definedummyword{equiv}% + \definedummyword{error}% + \definedummyword{expansion}% + \definedummyword{minus}% + \definedummyword{pounds}% + \definedummyword{point}% + \definedummyword{print}% + \definedummyword{result}% + % + % Handle some cases of @value -- where the variable name does not + % contain - or _, and the value does not contain any + % (non-fully-expandable) commands. + \let\value = \expandablevalue + % + % Normal spaces, not active ones. + \unsepspaces + % + % No macro expansion. + \turnoffmacros +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexdummytex{TeX} +\def\indexdummydots{...} +% +\def\indexnofonts{% + \def\ { }% + \def\@{@}% + % how to handle braces? + \def\_{\normalunderscore}% + % + \let\,=\asis + \let\"=\asis + \let\`=\asis + \let\'=\asis + \let\^=\asis + \let\~=\asis + \let\==\asis + \let\u=\asis + \let\v=\asis + \let\H=\asis + \let\dotaccent=\asis + \let\ringaccent=\asis + \let\tieaccent=\asis + \let\ubaraccent=\asis + \let\udotaccent=\asis + \let\dotless=\asis + % + % Other non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\aa{aa}% + \def\ae{ae}% + \def\l{l}% + \def\oe{oe}% + \def\o{o}% + \def\ss{ss}% + \def\exclamdown{!}% + \def\questiondown{?}% + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + % Texinfo font commands. + \let\b=\asis + \let\i=\asis + \let\r=\asis + \let\sc=\asis + \let\t=\asis + % + \let\TeX=\indexdummytex + \let\acronym=\asis + \let\cite=\asis + \let\code=\asis + \let\command=\asis + \let\dfn=\asis + \let\dots=\indexdummydots + \let\emph=\asis + \let\env=\asis + \let\file=\asis + \let\kbd=\asis + \let\key=\asis + \let\math=\asis + \let\option=\asis + \let\samp=\asis + \let\strong=\asis + \let\uref=\asis + \let\url=\asis + \let\var=\asis + \let\w=\asis +} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% For \ifx comparisons. +\def\emptymacro{\empty} + +% Most index entries go through here, but \dosubind is the general case. +% +\def\doind#1#2{\dosubind{#1}{#2}\empty} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% \empty if called from \doind, as we usually are. The main exception +% is with defuns, which call us directly. +% +\def\dosubind#1#2#3{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \fi + {% + \count255=\lastpenalty + {% + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + {% + \let\folio = 0% We will expand all macros now EXCEPT \folio. + \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % The main index entry text. + \toks0 = {#2}% + % + % If third arg is present, precede it with space in sort key. + \def\thirdarg{#3}% + \ifx\thirdarg\emptymacro \else + % If the third (subentry) arg is present, add it to the index + % line to write. + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\csname#1indfile\endcsname{% + \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% + }% + % + % If a skip is the last thing on the list now, preserve it + % by backing up by \lastskip, doing the \write, then inserting + % the skip again. Otherwise, the whatsit generated by the + % \write will make \lastskip zero. The result is that sequences + % like this: + % @end defun + % @tindex whatever + % @defun ... + % will have extra space inserted, because the \medbreak in the + % start of the @defun won't see the skip inserted by the @end of + % the previous defun. + % + % But don't do any of this if we're not in vertical mode. We + % don't want to do a \vskip and prematurely end a paragraph. + % + % Avoid page breaks due to these extra skips, too. + % + \iflinks + \ifvmode + \skip0 = \lastskip + \ifdim\lastskip = 0pt \else \nobreak\vskip-\skip0 \fi + \fi + % + \temp % do the write + % + \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi + \fi + }% + }% + \penalty\count255 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\def\printindex{\parsearg\doprintindex} +\def\doprintindex#1{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + \indexbreaks + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\rawbackslashxx}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \penalty -300 + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + \vskip .33\baselineskip plus .1\baselineskip + % + % Do our best not to break after the initial. + \nobreak +}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry#1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing columns. + \vskip 0pt plus1pt + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + \ #2% The page number ends the paragraph. + \fi + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% \def\appendixletter{\char\the\appendixno} +% We do the following for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +\suppressfirstparagraphindent +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +\suppressfirstparagraphindent +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +\suppressfirstparagraphindent +} + +% @chapter, @appendix, @unnumbered. +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + \global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}% + \chapmacro {#1}{\the\chapno}% + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + % We don't substitute the actual chapter name into \thischapter + % because we don't want its macros evaluated now. + \xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% + \writetocentry{chap}{#1}{{\the\chapno}} + \donoderef + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +% we use \chapno to avoid indenting back +\def\appendixbox#1{% + \setbox0 = \hbox{\putwordAppendix{} \the\chapno}% + \hbox to \wd0{#1\hss}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + \global\advance \appendixno by 1 + \message{\putwordAppendix\space \appendixletter}% + \chapmacro {#1}{\appendixbox{\putwordAppendix{} \appendixletter}}% + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + \xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% + \writetocentry{appendix}{#1}{{\appendixletter}} + \appendixnoderef + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +% @top is like @unnumbered. +\outer\def\top{\parsearg\unnumberedyyy} + +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the<toks register> to achieve this: TeX expands \the<toks> only once, + % simply yielding the contents of <toks register>. (We also do this for + % the toc entries.) + \toks0 = {#1}\message{(\the\toks0)}% + % + \unnumbchapmacro {#1}% + \gdef\thischapter{#1}\gdef\thissection{#1}% + \writetocentry{unnumbchap}{#1}{{\the\chapno}} + \unnumbnoderef + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% Sections. +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{% + \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % + \gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% + \writetocentry{sec}{#1}{{\the\chapno}{\the\secno}} + \donoderef + \nobreak +} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{% + \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % + \gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% + \writetocentry{sec}{#1}{{\appendixletter}{\the\secno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{% + \plainsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsec}{#1}{{\the\chapno}{\the\secno}} + \unnumbnoderef + \nobreak +} + +% Subsections. +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{% + \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % + \subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% + \writetocentry{subsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}} + \donoderef + \nobreak +} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{% + \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % + \subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% + \writetocentry{subsec}{#1}{{\appendixletter}{\the\secno}{\the\subsecno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{% + \plainsubsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}} + \unnumbnoderef + \nobreak +} + +% Subsubsections. +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{% + \gdef\thissection{#1}\global\advance \subsubsecno by 1 % + \subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% + \writetocentry{subsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \donoderef + \nobreak +} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{% + \gdef\thissection{#1}\global\advance \subsubsecno by 1 % + \subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% + \writetocentry{subsubsec}{#1}{{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{% + \plainsubsubsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsubsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \unnumbnoderef + \nobreak +} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% + {\advance\chapheadingskip by 10pt \chapbreak }% + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +% Plain chapter opening. +% #1 is the text, #2 the chapter number or empty if unnumbered. +\def\chfplain#1#2{% + \pchapsepmacro + {% + \chapfonts \rm + \def\chapnum{#2}% + \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% Plain opening for unnumbered. +\def\unnchfplain#1{\chfplain{#1}{}} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerchfplain#1{{% + \def\centerparametersmaybe{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt + }% + \chfplain{#1}{}% +}} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + + +% Section titles. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% Subsection titles. +\newskip \subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} +\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} +\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} + +% Subsubsection titles. +\let\subsubsecheadingskip = \subsecheadingskip +\let\subsubsecheadingbreak = \subsecheadingbreak +\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} +\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} + + +% Print any size section title. +% +% #1 is the section type (sec/subsec/subsubsec), #2 is the section +% number (maybe empty), #3 the text. +\def\sectionheading#1#2#3{% + {% + \expandafter\advance\csname #1headingskip\endcsname by \parskip + \csname #1headingbreak\endcsname + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\endcsname \rm + % + % Only insert the separating space if we have a section number. + \def\secnum{#2}% + \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + % Add extra space after the heading -- either a line space or a + % paragraph space, whichever is more. (Some people like to set + % \parskip to large values for some reason.) Don't allow stretch, though. + \nobreak + \ifdim\parskip>\normalbaselineskip + \kern\parskip + \else + \kern\normalbaselineskip + \fi + \nobreak +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. We supply {\folio} at the end of the +% argument, which will end up as the last argument to the \...entry macro. +% +% Usage: \writetocentry{chap}{The Name of The Game}{{\the\chapno}} +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% +\newif\iftocfileopened +\def\writetocentry#1#2#3{% + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + \toks0 = {#2}% + \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}#3{\folio}}}% + \temp + \fi + % + % Tell \shipout to create a page destination if we're doing pdf, which + % will be the target of the links in the table of contents. We can't + % just do it on every page because the title pages are numbered 1 and + % 2 (the page numbers aren't printed), and so are the first two pages + % of the document. Thus, we'd have two destinations named `1', and + % two named `2'. + \ifpdf \pdfmakepagedesttrue \fi +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Finish up the main text and prepare to read what we've written +% to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund <tege@matematik.su.se> + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + % We can't do this, because then an actual ^ in a section + % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. + %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \pdfmakeoutlines + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\chapentry = \shortchapentry + \let\appendixentry = \shortappendixentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\subsecentry ##1##2##3##4##5{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +\ifpdf + \pdfcatalog{/PageMode /UseOutlines}% +\fi + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapters, in the main contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#3\egroup}% +} + +% Appendices, in the main contents. +\def\appendixentry#1#2#3{% + \dochapentry{\appendixbox{\putwordAppendix{} #2}\labelspace#1}{#3}} +% +% Appendices, in the short toc. +\let\shortappendixentry = \shortchapentry + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +% +\newdimen\shortappendixwidth +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + \dimen0 = 1em + \hbox to \dimen0{#1\hss}% +} + +% Unnumbered chapters. +\def\unnumbchapentry#1#2#3{\dochapentry{#1}{#3}} +\def\shortunnumberedentry#1#2#3{\tocentry{#1}{\doshortpageno\bgroup#3\egroup}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2#3#4#5{\dosubsecentry{#1}{#5}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2#3#4#5#6{\dosubsubsecentry{#1}{#6}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +\def\tocentry#1#2{\begingroup + \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks + % Do not use \turnoffactive in these arguments. Since the toc is + % typeset in cmr, characters such as _ would come out wrong; we + % have to do the usual translation tricks. + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} +% @foo ... @end foo. + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} +% +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\==\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\indent=\ptexindent + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @end lisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty>10000 \else \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\def\cartouche{% +\par % can't be in the midst of a paragraph. +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% Define the \E... control sequence only if we are inside the particular +% environment, so the error checking in \end will work. +% +% To end an @example-like environment, we first end the paragraph (via +% \afterenvbreak's vertical glue), and then the group. That way we keep +% the zero \parskip that the environments set -- \parskip glue will be +% inserted at the beginning of the next paragraph in the document, after +% the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup} + +% @lisp: indented, narrowed, typewriter font. +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} + +% @example: Same as @lisp. +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +\def\smalllisp{\begingroup + \def\Esmalllisp{\nonfillfinish\endgroup}% + \def\Esmallexample{\nonfillfinish\endgroup}% + \smallexamplefonts + \lisp +} +\let\smallexample = \smalllisp + + +% @display: same as @lisp except keep current font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} +% +% @smalldisplay: @display plus smaller fonts. +% +\def\smalldisplay{\begingroup + \def\Esmalldisplay{\nonfillfinish\endgroup}% + \smallexamplefonts \rm + \display +} + +% @format: same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} +% +% @smallformat: @format plus smaller fonts. +% +\def\smallformat{\begingroup + \def\Esmallformat{\nonfillfinish\endgroup}% + \smallexamplefonts \rm + \format +} + +% @flushleft (same as @format). +% +\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} + +% @flushright. +% +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble +} + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + + +% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>} +% If we want to allow any <char> as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=12}\dospecials} +% +% [Knuth] pp. 380,381,391 +% Disable Spanish ligatures ?` and !` of \tt font +\begingroup + \catcode`\`=\active\gdef`{\relax\lq} +\endgroup +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \catcode`\`=\active + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +\def\starttabbox{\setbox0=\hbox\bgroup} +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen0=\wd0 % the width so far, or since the previous tab + \divide\dimen0 by\tabw + \multiply\dimen0 by\tabw % compute previous multiple of \tabw + \advance\dimen0 by\tabw % advance to next multiple of \tabw + \wd0=\dimen0 \box0 \starttabbox + }% + } +\endgroup +\def\setupverbatim{% + % Easiest (and conventionally used) font for verbatim + \tt + \def\par{\leavevmode\egroup\box0\endgraf}% + \catcode`\`=\active + \tabexpand + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'<char>#1<char>'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=12\catcode`\}=12 + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +%% Include LaTeX hack for completeness -- never know +%% \begingroup +%% \catcode`|=0 \catcode`[=1 +%% \catcode`]=2\catcode`\{=12\catcode`\}=12\catcode`\ =\active +%% \catcode`\\=12|gdef|doverbatim#1@end verbatim[ +%% #1|endgroup|def|Everbatim[]|end[verbatim]] +%% |endgroup +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \gdef\doverbatim#1^^M#2@end verbatim{#2\end{verbatim}}% +\endgroup +% +\def\verbatim{% + \def\Everbatim{\nonfillfinish\endgroup}% + \begingroup + \nonfillstart + \advance\leftskip by -\defbodyindent + \begingroup\setupverbatim\doverbatim +} + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +% Allow normal characters that we make active in the argument (a file name). +\def\verbatiminclude{% + \begingroup + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \parsearg\doverbatiminclude +} +\def\setupverbatiminclude{% + \begingroup + \nonfillstart + \advance\leftskip by -\defbodyindent + \begingroup\setupverbatim +} +% +\def\doverbatiminclude#1{% + % Restore active chars for included file. + \endgroup + \begingroup + \let\value=\expandablevalue + \def\thisfile{#1}% + \expandafter\expandafter\setupverbatiminclude\input\thisfile + \endgroup + \nonfillfinish + \endgroup +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. Many commands won't be +% allowed in this context, but that's ok. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\begingroup + % Define a command to swallow text until we reach `@end copying'. + % \ is the escape char in this texinfo.tex file, so it is the + % delimiter for the command; @ will be the escape char when we read + % it, but that doesn't matter. + \long\def\docopying##1\end copying{\gdef\copyingtext{##1}\enddocopying}% + % + % We must preserve ^^M's in the input file; see \insertcopying below. + \catcode`\^^M = \active + \docopying +} + +% What we do to finish off the copying text. +% +\def\enddocopying{\endgroup\ignorespaces} + +% @insertcopying. Here we must play games with ^^M's. On the one hand, +% we need them to delimit commands such as `@end quotation', so they +% must be active. On the other hand, we certainly don't want every +% end-of-line to be a \par, as would happen with the normal active +% definition of ^^M. On the third hand, two ^^M's in a row should still +% generate a \par. +% +% Our approach is to make ^^M insert a space and a penalty1 normally; +% then it can also check if \lastpenalty=1. If it does, then manually +% do \par. +% +% This messes up the normal definitions of @c[omment], so we redefine +% it. Similarly for @ignore. (These commands are used in the gcc +% manual for man page generation.) +% +% Seems pretty fragile, most line-oriented commands will presumably +% fail, but for the limited use of getting the copying text (which +% should be quite simple) inserted, we can hope it's ok. +% +{\catcode`\^^M=\active % +\gdef\insertcopying{\begingroup % + \parindent = 0pt % looks wrong on title page + \def^^M{% + \ifnum \lastpenalty=1 % + \par % + \else % + \space \penalty 1 % + \fi % + }% + % + % Fix @c[omment] for catcode 13 ^^M's. + \def\c##1^^M{\ignorespaces}% + \let\comment = \c % + % + % Don't bother jumping through all the hoops that \doignore does, it + % would be very hard since the catcodes are already set. + \long\def\ignore##1\end ignore{\ignorespaces}% + % + \copyingtext % +\endgroup}% +} + +\message{defuns,} +% @defun etc. + +% Allow user to change definition object font (\df) internally +\def\setdeffont#1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\&=\active + \catcode`\[=\active \catcode`\]=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested + \global\advance\parencount by 1 +} +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. + % also in that case restore the outer-level definition of (. + \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi + \global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } +\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } +\let\ampnr = \& +\def\lbrb{{\bf\char`\[}} +\def\rbrb{{\bf\char`\]}} + +% Active &'s sneak into the index arguments, so make sure it's defined. +{ + \catcode`& = \active + \global\let& = \ampnr +} + +% \defname, which formats the name of the @def (not the args). +% #1 is the function name. +% #2 is the type of definition, such as "Function". +% +\def\defname#1#2{% + % How we'll output the type name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \ifempty{#2}% + \def\defnametype{}% + \else + \def\defnametype{[\rm #2]}% + \fi + % + % Get the values of \leftskip and \rightskip as they were outside the @def... + \dimen2=\leftskip + \advance\dimen2 by -\defbodyindent + % + % Figure out values for the paragraph shape. + \setbox0=\hbox{\hskip \deflastargmargin{\defnametype}}% + \dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line + \dimen1=\hsize \advance \dimen1 by -\defargsindent % size for continuations + \parshape 2 0in \dimen0 \defargsindent \dimen1 + % + % Output arg 2 ("Function" or some such) but stuck inside a box of + % width 0 so it does not interfere with linebreaking. + \noindent + % + {% Adjust \hsize to exclude the ambient margins, + % so that \rightline will obey them. + \advance \hsize by -\dimen2 + \dimen3 = 0pt % was -1.25pc + \rlap{\rightline{\defnametype\kern\dimen3}}% + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \advance\leftskip by -\defbodyindent + \exdentamount=\defbodyindent + {\df #1}\enskip % output function name + % \defunargs will be called next to output the arguments, if any. +} + +% Common pieces to start any @def... +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence (which our caller defines). +% #3 is the control sequence to process the header, such as \defunheader. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we want to allow a + % break after all. Check for penalty 10002 (inserted by + % \defargscommonending) instead of 10000, since the sectioning + % commands insert a \penalty10000, and we don't want to allow a break + % between a section heading and a defun. + \ifnum\lastpenalty=10002 \penalty0 \fi + \medbreak + % + % Define the \E... end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +% Common part of the \...x definitions. +% +\def\defxbodycommon{% + % As with \parsebodycommon above, allow line break if we have multiple + % x headers in a row. It's not a great place, though. + \ifnum\lastpenalty=10000 \penalty1000 \fi + % + \begingroup\obeylines +} + +% Process body of @defun, @deffn, @defmac, etc. +% +\def\defparsebody#1#2#3{% + \parsebodycommon{#1}{#2}{#3}% + \def#2{\defxbodycommon \activeparens \spacesplit#3}% + \catcode\equalChar=\active + \begingroup\obeylines\activeparens + \spacesplit#3% +} + +% #1, #2, #3 are the common arguments (see \parsebodycommon above). +% #4, delimited by the space, is the class name. +% +\def\defmethparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \activeparens \spacesplit{#3{##1}}}% + \begingroup\obeylines\activeparens + % The \empty here prevents misinterpretation of a construct such as + % @deffn {whatever} {Enharmonic comma} + % See comments at \deftpparsebody, although in our case we don't have + % to remove the \empty afterwards, since it is empty. + \spacesplit{#3{#4}}\empty +} + +% Used for @deftypemethod and @deftypeivar. +% #1, #2, #3 are the common arguments (see \defparsebody). +% #4, delimited by a space, is the class name. +% #5 is the method's return type. +% +\def\deftypemethparsebody#1#2#3#4 #5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\defxbodycommon \activeparens \spacesplit{#3{##1}{##2}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#4}{#5}}% +} + +% Used for @deftypeop. The change from \deftypemethparsebody is an +% extra argument at the beginning which is the `category', instead of it +% being the hardwired string `Method' or `Instance Variable'. We have +% to account for this both in the \...x definition and in parsing the +% input at hand. Thus also need a control sequence (passed as #5) for +% the \E... definition to assign the category name to. +% +\def\deftypeopparsebody#1#2#3#4#5 #6 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 ##3 {\def#4{##1}% + \defxbodycommon \activeparens \spacesplit{#3{##2}{##3}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#5}{#6}}% +} + +% For @defop. +\def\defopparsebody #1#2#3#4#5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\def#4{##1}% + \defxbodycommon \activeparens \spacesplit{#3{##2}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#5}}% +} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. +% +\def\defvarparsebody #1#2#3{% + \parsebodycommon{#1}{#2}{#3}% + \def#2{\defxbodycommon \spacesplit#3}% + \catcode\equalChar=\active + \begingroup\obeylines + \spacesplit#3% +} + +% @defopvar. +\def\defopvarparsebody #1#2#3#4#5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\def#4{##1}% + \defxbodycommon \spacesplit{#3{##2}}}% + \begingroup\obeylines + \spacesplit{#3{#5}}% +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% + \begingroup\obeylines + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% + \begingroup\obeylines + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does. +% +\def\removeemptybraces\empty#1\relax{#1} + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + #1{\removeemptybraces#2\relax}{#3}% +}% + +% Split up #2 (the rest of the input line) at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. +% +{\obeylines % + \gdef\spacesplit#1#2^^M{\endgroup\spacesplitx{#1}#2 \relax\spacesplitx}% + \long\gdef\spacesplitx#1#2 #3#4\spacesplitx{% + \ifx\relax #3% + #1{#2}{}% + \else % + #1{#2}{#3#4}% + \fi}% +} + +% Define @defun. + +% This is called to end the arguments processing for all the @def... commands. +% +\def\defargscommonending{% + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty 10002 % signal to \parsebodycommon. +} + +% This expands the args and terminates the paragraph they comprise. +% +\def\defunargs#1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Set the font temporarily and use \font in case \setfont made \tensl a macro. +{\tensl\hyphenchar\font=0}% +#1% +{\tensl\hyphenchar\font=45}% +\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% + \defargscommonending +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars + \defargscommonending +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDeffunc}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypefun}% +\deftypefunargs {#3}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$.$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$.${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$.$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefmac}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefspec}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defop CATEGORY CLASS OPERATION ARG... +% +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} +% +\def\defopheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% function index entry + \begingroup + \defname{#2}{\defoptype\ \putwordon\ #1}% + \defunargs{#3}% + \endgroup +} + +% @deftypeop CATEGORY CLASS TYPE OPERATION ARG... +% +\def\deftypeop #1 {\def\deftypeopcategory{#1}% + \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader + \deftypeopcategory} +% +% #1 is the class name, #2 the data type, #3 the operation name, #4 the args. +\def\deftypeopheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3} + {\deftypeopcategory\ \putwordon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypemethod CLASS TYPE METHOD ARG... +% +\def\deftypemethod{% + \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% +% #1 is the class name, #2 the data type, #3 the method name, #4 the args. +\def\deftypemethodheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3}{\putwordMethodon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypeivar CLASS TYPE VARNAME +% +\def\deftypeivar{% + \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader} +% +% #1 is the class name, #2 the data type, #3 the variable name. +\def\deftypeivarheader#1#2#3{% + \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3} + {\putwordInstanceVariableof\ \code{#1}}% + \defvarargs{#3}% + \endgroup +} + +% @defmethod == @defop Method +% +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} +% +% #1 is the class name, #2 the method name, #3 the args. +\def\defmethodheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{#2}{\putwordMethodon\ \code{#1}}% + \defunargs{#3}% + \endgroup +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% + \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% variable index entry + \begingroup + \defname{#2}{\defcvtype\ \putwordof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME +% +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} +% +\def\defivarheader#1#2#3{% + \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% entry in var index + \begingroup + \defname{#2}{\putwordInstanceVariableof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defvar +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% + \defargscommonending +} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefvar}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefopt}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name, perhaps followed by text that +% is actually part of the data type, which should not be put into the index. +\def\deftypevarheader #1#2{% +\dovarind#2 \relax% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypevar}% + \defargscommonending +\endgroup} +\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\dovarind#3 \relax% +\begingroup\defname {\defheaderxcond#2\relax$.$#3}{#1} + \defargscommonending +\endgroup} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% These definitions are used if you use @defunx (etc.) +% anywhere other than immediately after a @defun or @defunx. +% +\def\defcvx#1 {\errmessage{@defcvx in invalid context}} +\def\deffnx#1 {\errmessage{@deffnx in invalid context}} +\def\defivarx#1 {\errmessage{@defivarx in invalid context}} +\def\defmacx#1 {\errmessage{@defmacx in invalid context}} +\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\defopx#1 {\errmessage{@defopx in invalid context}} +\def\defspecx#1 {\errmessage{@defspecx in invalid context}} +\def\deftpx#1 {\errmessage{@deftpx in invalid context}} +\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}} +\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}} +\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}} +\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}} +\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}} +\def\defunx#1 {\errmessage{@defunx in invalid context}} +\def\defvarx#1 {\errmessage{@defvarx in invalid context}} +\def\defvrx#1 {\errmessage{@defvrx in invalid context}} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scanmacro#1{% + \begingroup \newlinechar`\^^M + % Undo catcode changes of \startcontents and \doprintindex + \catcode`\@=0 \catcode`\\=\other \escapechar=`\@ + % Append \endinput to make sure that TeX does not see the ending newline. + \toks0={#1\endinput}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \let\xeatspaces\eatspaces + \input \jobname.tmp + \endgroup +} +\else +\def\scanmacro#1{% +\begingroup \newlinechar`\^^M +% Undo catcode changes of \startcontents and \doprintindex +\catcode`\@=0 \catcode`\\=\other \escapechar=`\@ +\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup} +\fi + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? +\def\macrolist{} % List of all defined macros in the form + % \do\macro1\do\macro2... + +% Utility routines. +% Thisdoes \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter +\expandafter\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\macrobodyctxt{% + \catcode`\~=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\+=\other + \catcode`\{=\other + \catcode`\}=\other + \catcode`\@=\other + \catcode`\^^M=\other + \usembodybackslash} + +\def\macroargctxt{% + \catcode`\~=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\+=\other + \catcode`\@=\other + \catcode`\\=\other} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + % Add the macroname to \macrolist + \toks0 = \expandafter{\macrolist\do}% + \xdef\macrolist{\the\toks0 + \expandafter\noexpand\csname\the\macname\endcsname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\def\unmacro{\parsearg\dounmacro} +\def\dounmacro#1{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\do\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx#1\relax + % remove this + \else + \noexpand\do \noexpand #1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% <parameter list> is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + +% We mant to disable all macros during \shipout so that they are not +% expanded by \write. +\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% + \edef\next{\macrolist}\expandafter\endgroup\next} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\begingroup\obeyspaces\parsearg\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{\ignoreactivespaces +\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=% + \expandafter\noexpand\csname#2\endcsname}% +\expandafter\endgroup\next} + + +\message{cross references,} +% @xref etc. + +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's job is to define \lastnode. +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx #1,\finishnodeparse} +\def\nodexxx#1,#2\finishnodeparse{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +% The sectioning commands (@chapter, etc.) call these. +\def\donoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Ysectionnumberandtype}% + \global\let\lastnode=\relax + \fi +} +\def\unnumbnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}% + \global\let\lastnode=\relax + \fi +} +\def\appendixnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Yappendixletterandtype}% + \global\let\lastnode=\relax + \fi +} + + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), namely NAME-title (the corresponding @chapter/etc. name), +% NAME-pg (the page number), and NAME-snt (section number and type). +% Called from \foonoderef. +% +% We have to set \indexdummies so commands such as @code in a section +% title aren't expanded. It would be nicer not to expand the titles in +% the first place, but there's so many layers that that is hard to do. +% +% Likewise, use \turnoffactive so that punctuation chars such as underscore +% and backslash work in node names. +% +\def\setref#1#2{{% + \atdummies + \pdfmkdest{#1}% + % + \turnoffactive + \dosetq{#1-title}{Ytitle}% + \dosetq{#1-pg}{Ypagenumber}% + \dosetq{#1-snt}{#2}% +}} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifpdf + \leavevmode + \getfilename{#4}% + {\turnoffactive \otherbackslash + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{#1}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{#1}% + \fi + }% + \linkcolor + \fi + % + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive \otherbackslash + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % output the `[mynode]' via a macro. + \xrefprintnodename\printednodename + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% + \fi + \endlink +\endgroup} + +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since not square brackets don't work in some documents. Particularly +% one that Bob is working on :). +% +\def\xrefprintnodename#1{[#1]} + +% \dosetq is called from \setref to do the actual \write (\iflinks). +% +\def\dosetq#1#2{% + {\let\folio=0% + \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% + \iflinks \next \fi + }% +} + +% \internalsetq{foo}{page} expands into +% CHARACTERS @xrdef{foo}{...expansion of \page...} +\def\internalsetq#1#2{@xrdef{#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq. +% +\def\Ypagenumber{\folio} +\def\Ytitle{\thissection} +\def\Ynothing{} +\def\Ysectionnumberandtype{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +\def\Yappendixletterandtype{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname X#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. +% +\def\xrdef#1{\expandafter\gdef\csname X#1\endcsname} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % Make the characters 128-255 be printing characters + {% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% + }% + % + % Turn off \ as an escape so we do not lose on + % entries which were dumped with control sequences in their names. + % For example, @xrdef{$\leq $-fun}{page ...} made by @defun ^^ + % Reference to such entries still does not work the way one would wish, + % but at least they do not bomb out when the aux file is read in. + \catcode`\\=\other + % + % @ is our escape character in .aux files. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 + % + \openin 1 \jobname.aux + \ifeof 1 \else + \closein 1 + \input \jobname.aux + \global\havexrefstrue + \global\warnedobstrue + \fi + % Open the new aux file. TeX will close it automatically at exit. + \openout\auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \let\indent=\ptexindent + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset and anything else that uses +% \parseargline fail inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +% The start of the footnote looks usually like this: +\gdef\startfootins{\insert\footins\bgroup} +% +% ... but this macro is redefined inside @multitable. +% +\gdef\dofootnote{% + \startfootins + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + \closein 1 + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing this stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \line\bgroup\hss + \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode \hss \egroup \bigbreak \fi % space after the image +\endgroup} + + +\message{localization,} +% and i18n. + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\def\documentlanguage{\parsearg\dodocumentlanguage} +\def\dodocumentlanguage#1{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \let\temp = \relax + \else + \def\temp{\input txi-#1.tex }% + \fi + \temp + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; +% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8) +% physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}% + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.5 (or so) format. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {\voffset}{.25in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{51\baselineskip}{160mm} + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\def\pagesizes{\parsearg\pagesizesxxx} +\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1 + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$}%$ font-lock fix + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\rawbackslashxx=`\\ + +% \rawbackslash defines an active \ to do \rawbackslashxx. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +{\catcode`\\=\active + @gdef@rawbackslash{@let\=@rawbackslashxx} + @gdef@otherbackslash{@let\=@realbackslash} +} + +% \realbackslash is an actual character `\' with catcode other. +{\catcode`\\=\other @gdef@realbackslash{\}} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{% + @let"=@normaldoublequote + @let\=@realbackslash + @let~=@normaltilde + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let<=@normalless + @let>=@normalgreater + @let+=@normalplus + @let$=@normaldollar %$ font-lock fix +} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. (Thus, \ is not expandable when this is in +% effect.) +% +@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + +@c Set initial fonts. +@textfonts +@rm + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: -- cgit v1.2.3 From 1c1069f70b66209f4b1feb1c277a97aa81517fe5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 9 Dec 2003 09:12:43 +0000 Subject: * configure.ac: Add a min_automake_version. * README.CVS: New. * autogen.sh: Revamped except for the --build-w32 hack. * Makefile.am: Add README.CVS --- ChangeLog | 7 +++ Makefile.am | 4 +- autogen.sh | 175 +++++++++++++++++++++++++++++------------------------------ configure.ac | 6 +- 4 files changed, 99 insertions(+), 93 deletions(-) diff --git a/ChangeLog b/ChangeLog index f998dd1b0..f270cad13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +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. diff --git a/Makefile.am b/Makefile.am index d5c639042..dd75d14b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,7 @@ ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = scripts/config.rpath autogen.sh README-alpha +EXTRA_DIST = scripts/config.rpath autogen.sh README-alpha README.CVS DISTCLEANFILES = g10defs.h if BUILD_GPG @@ -45,7 +45,7 @@ else scd = endif -SUBDIRS = m4 intl jnlib common kbx \ +SUBDIRS = m4 intl jnlib common kbx \ ${gpg} ${sm} ${agent} ${scd} po doc #tests diff --git a/autogen.sh b/autogen.sh index bf958dbcb..a317f0b20 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,60 +1,46 @@ -#!/bin/sh -# Run this to generate all the initial makefiles, etc. -# It is only needed for the CVS version. - -# have_version(prog, list of executables, required version) +#! /bin/sh +# Run this to generate all the initial makefiles, etc. +# +# Copyright (C) 2003 g10 Code GmbH # -# Returns true and sets $prog to the first executable with the -# required minimum major.minor. -have_version () -{ - found=0 - - for prog in $2 : - do - ver=$($prog --version \ - | gawk '{ if (match($0, /[0-9]+\.[0-9]+/)) - { - print substr($0, RSTART, RLENGTH); ok=1; exit 0; - } - } - - END { - if (! ok) - exit 1; - }') - - if test $? = 0 - then - if expr 0$ver '>=' 0$3 >/dev/null 2>&1 - then - echo Using $prog - found=1 - export $1="$prog" - break - fi +# 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` >= $2 )) == 1 ]; then + return 0 fi - done - - if test 0$found = 01 - then - true - else - echo "*** Error. Could not find an appropriate executable for $1 with " - echo "at least version $3." - false - 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 } -PGM=NEWPG -lib_config_files="" -autoconf_vers=2.52 -automake_vers=1.5 -aclocal_vers=1.5 -#libtool_vers=1.3 +# 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 test "$1" = "--build-w32"; then + +if [ "$1" = "--build-w32" ]; then shift target=i386--mingw32 if [ ! -f ./config.guess ]; then @@ -113,51 +99,62 @@ if test "$1" = "--build-w32"; then exit $? fi -if ! have_version autoconf "$autoconf autoconf" $autoconf_vers -then - DIE="yes" -fi -if have_version automake "$automake automake automake-1.6" $automake_vers + +# 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 - if ! have_version aclocal "$aclocal aclocal aclocal-1.6" $aclocal_vers - then - DIE='yes' - fi -else - DIE='yes' + echo "**Error**: version information not found in "\`${configure_ac}\'"." >&2 + exit 1 fi -#if (libtool --version) < /dev/null > /dev/null 2>&1 ; then -# if (libtool --version | awk 'NR==1 { if( $4 >= '$libtool_vers') \ -# exit 1; exit 0; }'); -# then -# echo "**Error**: "\`libtool\'" is too old." -# echo ' (version ' $libtool_vers ' or newer is required)' -# DIE="yes" -# fi -#else -# echo -# echo "**Error**: You must have "\`libtool\'" installed to compile $PGM." -# echo ' (version ' $libtool_vers ' or newer is required)' -# DIE="yes" -#fi -if test "$DIE" = "yes"; then - exit 1 +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 -#echo "Running libtoolize... Ignore non-fatal messages." -#echo "no" | libtoolize +if test "$DIE" = "yes"; then + cat <<EOF -echo "Running autopoint" -autopoint +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 -I m4 +echo "Running aclocal -I m4 ..." +$ACLOCAL -I m4 echo "Running autoheader..." -autoheader -echo "Running $automake --gnu -a" -$automake --gnu -a -echo "Running $autoconf" -$autoconf +$AUTOHEADER +echo "Running automake --gnu ..." +$AUTOMAKE --gnu; +echo "Running autoconf..." +$AUTOCONF + +echo "You may now run \"./configure --enable-maintainer-mode && make\"." diff --git a/configure.ac b/configure.ac index 7eed5f393..7bca11986 100644 --- a/configure.ac +++ b/configure.ac @@ -20,6 +20,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) +min_automake_version="1.7.6" + # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. AC_INIT(gnupg, 1.9.3-cvs, gnupg-devel@gnupg.org) @@ -37,8 +39,6 @@ NEED_OPENSC_VERSION=0.8.0 PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION -AM_GNU_GETTEXT_VERSION(0.11.5) - AC_CONFIG_AUX_DIR(scripts) AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) @@ -354,6 +354,7 @@ AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) # Checks for libraries. # + # # libgpg-error is a library with error codes shared between GnuPG # related projects. @@ -608,6 +609,7 @@ AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", [A human readable text with the name of the OS]) +AM_GNU_GETTEXT_VERSION(0.12.1) if test "$try_gettext" = yes; then AM_GNU_GETTEXT(,[need-ngettext]) -- cgit v1.2.3 From 07d31ceeb1fba1dae9c676f1b8098206fc0e3b96 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 9 Dec 2003 09:13:29 +0000 Subject: (MSGID_BUGS_ADDRESS): New. --- po/ChangeLog | 4 ++++ po/Makevars | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/po/ChangeLog b/po/ChangeLog index 94547f3ea..682f086f3 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2003-12-09 Werner Koch <wk@gnupg.org> + + * Makevars (MSGID_BUGS_ADDRESS): New. + 2003-04-29 Werner Koch <wk@gnupg.org> * LINUGAS: NEW. diff --git a/po/Makevars b/po/Makevars index 8b09f53b0..20a50fc7d 100644 --- a/po/Makevars +++ b/po/Makevars @@ -20,6 +20,22 @@ XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # their copyright. COPYRIGHT_HOLDER = Free Software Foundation, Inc. +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = translations@gnupg.org + # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = -- cgit v1.2.3 From d4143cdd92a5234317ad28af5a71540c65cf6093 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 9 Dec 2003 09:20:26 +0000 Subject: Readded file --- README-alpha | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 README-alpha diff --git a/README-alpha b/README-alpha new file mode 100644 index 000000000..b844eabce --- /dev/null +++ b/README-alpha @@ -0,0 +1,16 @@ + ====== THIS IS WORK IN PROGESS ====== + + DO NOT USE IN A PRODUCTION ENVIRONMENT! + + THERE MIGHT BE SECURITY PROBLEMS! + +The source may change quite often and may have serious problems; it +may even not compile on some machines. + +It will probably needs GCC and GLIBC to build due to some debugging +code. Please don't complain if it does not work on other machines. +We will make it work again later. + +The specification for the OpenPGP smartcard application will be +released soon and we will try to make cards easily available. + -- cgit v1.2.3 From 6c88a1f5c0ede89c6bb0d711c030aa149328c09a Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Tue, 9 Dec 2003 09:21:06 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- INSTALL | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.CVS | 51 ++++++++++++++ 2 files changed, 280 insertions(+) create mode 100644 INSTALL create mode 100644 README.CVS diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..54caf7c19 --- /dev/null +++ b/INSTALL @@ -0,0 +1,229 @@ +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. + diff --git a/README.CVS b/README.CVS new file mode 100644 index 000000000..ae17923bd --- /dev/null +++ b/README.CVS @@ -0,0 +1,51 @@ +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. + + + + -- cgit v1.2.3 -- cgit v1.2.3 -- cgit v1.2.3 From 56530d2c397ab10faa29dce68dd87b78626e7c5b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 9 Dec 2003 09:28:27 +0000 Subject: Keep those files in CVS too. --- intl/libgnuintl.h | 258 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 213 insertions(+), 45 deletions(-) diff --git a/intl/libgnuintl.h b/intl/libgnuintl.h index f891deb96..ed25fe9f5 100644 --- a/intl/libgnuintl.h +++ b/intl/libgnuintl.h @@ -1,5 +1,5 @@ /* Message catalogs for internationalization. - Copyright (C) 1995-1997, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 2000-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -24,10 +24,11 @@ /* The LC_MESSAGES locale category is the category used by the functions gettext() and dgettext(). It is specified in POSIX, but not in ANSI C. On systems that don't define it, use an arbitrary value instead. - On Solaris, <locale.h> defines __LOCALE_H then includes <libintl.h> (i.e. - this file!) and then only defines LC_MESSAGES. To avoid a redefinition - warning, don't define LC_MESSAGES in this case. */ -#if !defined LC_MESSAGES && !defined __LOCALE_H + On Solaris, <locale.h> defines __LOCALE_H (or _LOCALE_H in Solaris 2.5) + then includes <libintl.h> (i.e. this file!) and then only defines + LC_MESSAGES. To avoid a redefinition warning, don't define LC_MESSAGES + in this case. */ +#if !defined LC_MESSAGES && !(defined __LOCALE_H || (defined _LOCALE_H && defined __sun)) # define LC_MESSAGES 1729 #endif @@ -35,18 +36,24 @@ implementation of gettext. */ #define __USE_GNU_GETTEXT 1 +/* Provide information about the supported file formats. Returns the + maximum minor revision number supported for a given major revision. */ +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \ + ((major) == 0 ? 1 : -1) + /* Resolve a platform specific conflict on DJGPP. GNU gettext takes precedence over _conio_gettext. */ #ifdef __DJGPP__ # undef gettext -# define gettext gettext #endif -#ifndef PARAMS -# if __STDC__ || defined __cplusplus -# define PARAMS(args) args +/* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers + used by programs. Similarly, test __PROTOTYPES, not PROTOTYPES. */ +#ifndef _INTL_PARAMS +# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES +# define _INTL_PARAMS(args) args # else -# define PARAMS(args) () +# define _INTL_PARAMS(args) () # endif #endif @@ -54,71 +61,232 @@ extern "C" { #endif + +/* We redirect the functions to those prefixed with "libintl_". This is + necessary, because some systems define gettext/textdomain/... in the C + library (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer). + If we used the unprefixed names, there would be cases where the + definition in the C library would override the one in the libintl.so + shared library. Recall that on ELF systems, the symbols are looked + up in the following order: + 1. in the executable, + 2. in the shared libraries specified on the link command line, in order, + 3. in the dependencies of the shared libraries specified on the link + command line, + 4. in the dlopen()ed shared libraries, in the order in which they were + dlopen()ed. + The definition in the C library would override the one in libintl.so if + either + * -lc is given on the link command line and -lintl isn't, or + * -lc is given on the link command line before -lintl, or + * libintl.so is a dependency of a dlopen()ed shared library but not + linked to the executable at link time. + Since Solaris gettext() behaves differently than GNU gettext(), this + would be unacceptable. + + The redirection happens by default through macros in C, so that &gettext + is independent of the compilation unit, but through inline functions in + C++, in order not to interfere with the name mangling of class fields or + class methods called 'gettext'. */ + +/* The user can define _INTL_REDIRECT_INLINE or _INTL_REDIRECT_MACROS. + If he doesn't, we choose the method. A third possible method is + _INTL_REDIRECT_ASM, supported only by GCC. */ +#if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS) +# if __GNUC__ >= 2 && (defined __STDC__ || defined __cplusplus) +# define _INTL_REDIRECT_ASM +# else +# ifdef __cplusplus +# define _INTL_REDIRECT_INLINE +# else +# define _INTL_REDIRECT_MACROS +# endif +# endif +#endif +/* Auxiliary macros. */ +#ifdef _INTL_REDIRECT_ASM +# define _INTL_ASM(cname) __asm__ (_INTL_ASMNAME (__USER_LABEL_PREFIX__, #cname)) +# define _INTL_ASMNAME(prefix,cnamestring) _INTL_STRINGIFY (prefix) cnamestring +# define _INTL_STRINGIFY(prefix) #prefix +#else +# define _INTL_ASM(cname) +#endif + /* Look up MSGID in the current default message catalog for the current LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ -extern char *gettext PARAMS ((const char *__msgid)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_gettext (const char *__msgid); +static inline char *gettext (const char *__msgid) +{ + return libintl_gettext (__msgid); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define gettext libintl_gettext +#endif +extern char *gettext _INTL_PARAMS ((const char *__msgid)) + _INTL_ASM (libintl_gettext); +#endif /* Look up MSGID in the DOMAINNAME message catalog for the current LC_MESSAGES locale. */ -extern char *dgettext PARAMS ((const char *__domainname, const char *__msgid)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dgettext (const char *__domainname, const char *__msgid); +static inline char *dgettext (const char *__domainname, const char *__msgid) +{ + return libintl_dgettext (__domainname, __msgid); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dgettext libintl_dgettext +#endif +extern char *dgettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid)) + _INTL_ASM (libintl_dgettext); +#endif /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale. */ -extern char *dcgettext PARAMS ((const char *__domainname, const char *__msgid, - int __category)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dcgettext (const char *__domainname, const char *__msgid, + int __category); +static inline char *dcgettext (const char *__domainname, const char *__msgid, + int __category) +{ + return libintl_dcgettext (__domainname, __msgid, __category); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dcgettext libintl_dcgettext +#endif +extern char *dcgettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid, + int __category)) + _INTL_ASM (libintl_dcgettext); +#endif /* Similar to `gettext' but select the plural form corresponding to the number N. */ -extern char *ngettext PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_ngettext (const char *__msgid1, const char *__msgid2, + unsigned long int __n); +static inline char *ngettext (const char *__msgid1, const char *__msgid2, + unsigned long int __n) +{ + return libintl_ngettext (__msgid1, __msgid2, __n); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define ngettext libintl_ngettext +#endif +extern char *ngettext _INTL_PARAMS ((const char *__msgid1, + const char *__msgid2, + unsigned long int __n)) + _INTL_ASM (libintl_ngettext); +#endif /* Similar to `dgettext' but select the plural form corresponding to the number N. */ -extern char *dngettext PARAMS ((const char *__domainname, const char *__msgid1, - const char *__msgid2, unsigned long int __n)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dngettext (const char *__domainname, const char *__msgid1, + const char *__msgid2, unsigned long int __n); +static inline char *dngettext (const char *__domainname, const char *__msgid1, + const char *__msgid2, unsigned long int __n) +{ + return libintl_dngettext (__domainname, __msgid1, __msgid2, __n); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dngettext libintl_dngettext +#endif +extern char *dngettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid1, + const char *__msgid2, + unsigned long int __n)) + _INTL_ASM (libintl_dngettext); +#endif /* Similar to `dcgettext' but select the plural form corresponding to the number N. */ -extern char *dcngettext PARAMS ((const char *__domainname, const char *__msgid1, - const char *__msgid2, unsigned long int __n, - int __category)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_dcngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category); +static inline char *dcngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category) +{ + return libintl_dcngettext (__domainname, __msgid1, __msgid2, __n, __category); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define dcngettext libintl_dcngettext +#endif +extern char *dcngettext _INTL_PARAMS ((const char *__domainname, + const char *__msgid1, + const char *__msgid2, + unsigned long int __n, + int __category)) + _INTL_ASM (libintl_dcngettext); +#endif /* Set the current default message catalog to DOMAINNAME. If DOMAINNAME is null, return the current default. If DOMAINNAME is "", reset to the default of "messages". */ -extern char *textdomain PARAMS ((const char *__domainname)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_textdomain (const char *__domainname); +static inline char *textdomain (const char *__domainname) +{ + return libintl_textdomain (__domainname); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define textdomain libintl_textdomain +#endif +extern char *textdomain _INTL_PARAMS ((const char *__domainname)) + _INTL_ASM (libintl_textdomain); +#endif /* Specify that the DOMAINNAME message catalog will be found in DIRNAME rather than in the system locale data base. */ -extern char *bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_bindtextdomain (const char *__domainname, + const char *__dirname); +static inline char *bindtextdomain (const char *__domainname, + const char *__dirname) +{ + return libintl_bindtextdomain (__domainname, __dirname); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define bindtextdomain libintl_bindtextdomain +#endif +extern char *bindtextdomain _INTL_PARAMS ((const char *__domainname, + const char *__dirname)) + _INTL_ASM (libintl_bindtextdomain); +#endif /* Specify the character encoding in which the messages from the DOMAINNAME message catalog will be returned. */ -extern char *bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); - - -/* Optimized version of the functions above. */ -#if defined __OPTIMIZED -/* These are macros, but could also be inline functions. */ - -# define gettext(msgid) \ - dgettext (NULL, msgid) - -# define dgettext(domainname, msgid) \ - dcgettext (domainname, msgid, LC_MESSAGES) - -# define ngettext(msgid1, msgid2, n) \ - dngettext (NULL, msgid1, msgid2, n) - -# define dngettext(domainname, msgid1, msgid2, n) \ - dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES) - -#endif /* Optimizing. */ +#ifdef _INTL_REDIRECT_INLINE +extern char *libintl_bind_textdomain_codeset (const char *__domainname, + const char *__codeset); +static inline char *bind_textdomain_codeset (const char *__domainname, + const char *__codeset) +{ + return libintl_bind_textdomain_codeset (__domainname, __codeset); +} +#else +#ifdef _INTL_REDIRECT_MACROS +# define bind_textdomain_codeset libintl_bind_textdomain_codeset +#endif +extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname, + const char *__codeset)) + _INTL_ASM (libintl_bind_textdomain_codeset); +#endif #ifdef __cplusplus -- cgit v1.2.3 From dba63c0a0ceb473909528ec51b5851ec28731218 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 11:30:16 +0000 Subject: * configure.ac: Check for funopen and fopencookie as part of the jnlib checks. * logging.c (writen, fun_writer, fun_closer): New. (log_set_file): Add feature to log to a socket. --- ChangeLog | 5 ++ NEWS | 8 ++- configure.ac | 3 +- jnlib/ChangeLog | 5 ++ jnlib/logging.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 187 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index f270cad13..2a08051f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/NEWS b/NEWS index 8aff1add1..ebc65a27d 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,13 @@ Noteworthy changes in version 1.9.3 (unreleased) ------------------------------------------------ * New options --{enable,disable}-ocsp to validate keys using OCSP - This requires at least DirMngr 0.5.1 to work. Default is disabled. + This requires a not yet released DirMngr 0.5.1. Default is + disabled. + + * The --log-file 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. Noteworthy changes in version 1.9.2 (2003-11-17) diff --git a/configure.ac b/configure.ac index 7bca11986..a0cf391a4 100644 --- a/configure.ac +++ b/configure.ac @@ -698,7 +698,7 @@ AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>]) # These are needed by libjnlib - fixme: we should have macros for them AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) -AC_CHECK_FUNCS(flockfile funlockfile) +AC_CHECK_FUNCS(flockfile funlockfile fopencookie funopen) AC_REPLACE_FUNCS(vasprintf) AC_REPLACE_FUNCS(fopencookie) @@ -709,6 +709,7 @@ AC_REPLACE_FUNCS(putc_unlocked) + # # check for gethrtime and run a testprogram to see whether # it is broken. It has been reported that some Solaris and HP UX systems diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index e12dd8e00..e6b7dc3fb 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2003-12-16 Werner Koch <wk@gnupg.org> + + * logging.c (writen, fun_writer, fun_closer): New. + (log_set_file): Add feature to log to a socket. + 2003-11-13 Werner Koch <wk@gnupg.org> * strlist.c (strlist_copy): New. diff --git a/jnlib/logging.c b/jnlib/logging.c index 913d01b6f..b019fb76c 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -29,12 +29,15 @@ #include <stdio.h> #include <string.h> #include <stdarg.h> +#include <stddef.h> #include <errno.h> #include <time.h> #include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> #include <unistd.h> #ifdef __MINGW32__ - #include <io.h> +# include <io.h> #endif #define JNLIB_NEED_LOG_LOGV 1 @@ -84,22 +87,173 @@ log_inc_errorcount (void) errorcount++; } -void -log_set_file( const char *name ) + +/* The follwing 3 functions are used by funopen to write logs to a + socket. */ +#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) +struct fun_cookie_s { + int fd; + int quiet; + char name[1]; +}; + +/* Write NBYTES of BUF to file descriptor FD. */ +static int +writen (int fd, const unsigned char *buf, size_t nbytes) { - FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr; - if( !fp ) { - fprintf(stderr, "failed to open log file `%s': %s\n", - name, strerror(errno)); - return; + size_t nleft = nbytes; + int nwritten; + + while (nleft > 0) + { + nwritten = write (fd, buf, nleft); + if (nwritten < 0 && errno == EINTR) + continue; + if (nwritten < 0) + return -1; + nleft -= nwritten; + buf = buf + nwritten; } - setvbuf( fp, NULL, _IOLBF, 0 ); + + return 0; +} + + +static int +fun_writer (void *cookie_arg, const char *buffer, size_t size) +{ + struct fun_cookie_s *cookie = cookie_arg; + + /* Note that we always try to reconnect to the socket but print error + messages only the first time an error occured. */ + if (cookie->fd == -1 ) + { + /* Note yet open or meanwhile closed due to an error. */ + struct sockaddr_un addr; + size_t addrlen; + + cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); + if (cookie->fd == -1) + { + if (!cookie->quiet) + fprintf (stderr, "failed to create socket for logging: %s\n", + strerror(errno)); + goto failure; + } + + memset (&addr, 0, sizeof addr); + addr.sun_family = PF_LOCAL; + strncpy (addr.sun_path, cookie->name, sizeof (addr.sun_path)-1); + addr.sun_path[sizeof (addr.sun_path)-1] = 0; + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (addr.sun_path) + 1); + + if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) + { + if (!cookie->quiet) + fprintf (stderr, "can't connect to `%s': %s\n", + cookie->name, strerror(errno)); + close (cookie->fd); + cookie->fd = -1; + goto failure; + } + /* Connection established. */ + cookie->quiet = 0; + } + + if (!writen (cookie->fd, buffer, size)) + return size; /* Okay. */ + + fprintf (stderr, "error writing to `%s': %s\n", + cookie->name, strerror(errno)); + close (cookie->fd); + cookie->fd = -1; + + failure: + if (!cookie->quiet) + { + fputs ("switching logging to stderr\n", stderr); + cookie->quiet = 1; + } + + fwrite (buffer, size, 1, stderr); + return size; +} - if (logstream && logstream != stderr && logstream != stdout) - fclose( logstream ); - logstream = fp; - missing_lf = 0; +static int +fun_closer (void *cookie_arg) +{ + struct fun_cookie_s *cookie = cookie_arg; + + if (cookie->fd != -1) + close (cookie->fd); + jnlib_free (cookie); + return 0; } +#endif /* HAVE_FOPENCOOKIE || HAVE_FUNOPEN */ + + + + +/* Set the file to write log to. The sepcial names NULL and "_" may + be used to select stderr and names formatted like + "socket:///home/foo/mylogs" may be used to write the logging to the + socket "/home/foo/mylogs". If the connection to the socket fails + or a write error is detected, the function writes to stderr and + tries the next time again to connect the socket. + */ +void +log_set_file (const char *name) +{ + FILE *fp; + + if (name && !strncmp (name, "socket://", 9) && name[9]) + { +#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN) + struct fun_cookie_s *cookie; + + cookie = jnlib_xmalloc (sizeof *cookie + strlen (name+9)); + cookie->fd = -1; + cookie->quiet = 0; + strcpy (cookie->name, name+9); + +#ifdef HAVE_FOPENCOOKIE + { + cookie_io_functions_t io = { NULL }; + io.write = fun_writer; + io.close = fun_closer; + + fp = fopencookie (cookie, "w", io); + } +#else /*!HAVE_FOPENCOOKIE*/ + { + fp = funopen (cookie, NULL, fun_writer, NULL, fun_closer); + } +#endif /*!HAVE_FOPENCOOKIE*/ +#else /* Neither fopencookie nor funopen. */ + { + fprintf (stderr, "system does not support logging to a socket - " + "using stderr\n"); + fp = stderr; + } +#endif /* Neither fopencookie nor funopen. */ + } + else + fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr; + if (!fp) + { + fprintf (stderr, "failed to open log file `%s': %s\n", + name? name:"[stderr]", strerror(errno)); + return; + } + setvbuf (fp, NULL, _IOLBF, 0); + + if (logstream && logstream != stderr && logstream != stdout) + fclose (logstream); + logstream = fp; + missing_lf = 0; +} + void log_set_fd (int fd) @@ -221,6 +375,7 @@ do_logv( int level, const char *fmt, va_list arg_ptr ) default: fprintf(logstream,"[Unknown log level %d]: ", level ); break; } + if (fmt) { vfprintf(logstream,fmt,arg_ptr) ; -- cgit v1.2.3 From d06cba69849c3d2fb6ecdc9733885fc44b3efdb7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 11:30:38 +0000 Subject: * protect.c (do_encryption): Use gcry_create_nonce instad of the obsolete WEAK_RANDOM. --- agent/ChangeLog | 5 +++++ agent/protect.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 24b22b7b1..c4a37f5e8 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2003-12-15 Werner Koch <wk@gnupg.org> + + * protect.c (do_encryption): Use gcry_create_nonce instad of the + obsolete WEAK_RANDOM. + 2003-11-20 Werner Koch <wk@gnupg.org> * sexp-parse.h (snext): Don't use atoi_1 and digitp macros, so diff --git a/agent/protect.c b/agent/protect.c index e438d53b4..df8a9bfe7 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -168,12 +168,12 @@ do_encryption (const char *protbegin, size_t protlen, rc = out_of_core (); if (!rc) { - /* allocate random bytes to be used as IV, padding and s2k salt*/ - iv = gcry_random_bytes (blklen*2+8, GCRY_WEAK_RANDOM); + /* Allocate random bytes to be used as IV, padding and s2k salt. */ + iv = xtrymalloc (blklen*2+8); if (!iv) rc = gpg_error (GPG_ERR_ENOMEM); - else - rc = gcry_cipher_setiv (hd, iv, blklen); + gcry_create_nonce (iv, blklen*2+8); + rc = gcry_cipher_setiv (hd, iv, blklen); } if (!rc) { -- cgit v1.2.3 From f18d0e557ce7644af8ccf3feae789afc4915daa5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 11:30:57 +0000 Subject: * seckey-cert.c (protect_secret_key): Use gry_create_nonce for the IV; there is not need for real strong random here and it even better protect the random bits used for the key. --- g10/ChangeLog | 6 ++++++ g10/seckey-cert.c | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 897836191..849e6931a 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,9 @@ +2003-12-15 Werner Koch <wk@gnupg.org> + + * seckey-cert.c (protect_secret_key): Use gry_create_nonce for the + IV; there is not need for real strong random here and it even + better protect the random bits used for the key. + 2003-11-16 Moritz Schulte <mo@g10code.com> * signal.c: Removed unused file. diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 5b0238240..7356cb224 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -346,8 +346,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) assert( sk->protect.ivlen <= DIM(sk->protect.iv) ); if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 ) BUG(); /* yes, we are very careful */ - gcry_randomize (sk->protect.iv, sk->protect.ivlen, - GCRY_STRONG_RANDOM); + gcry_create_nonce (sk->protect.iv, sk->protect.ivlen); gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); if( sk->version >= 4 ) { unsigned char *bufarr[PUBKEY_MAX_NSKEY]; -- cgit v1.2.3 From d0fbe288b2c50d4b5a5bdf2271e964a5328a56a4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 11:31:46 +0000 Subject: * encrypt.c (init_dek): Use gry_create_nonce for the IV; there is not need for real strong random here and it even better protect the random bits used for the key. --- sm/ChangeLog | 6 ++++++ sm/decrypt.c | 2 +- sm/encrypt.c | 4 ++-- sm/gpgsm.c | 4 ++-- sm/server.c | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index fc4fcd07a..2363eb91b 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2003-12-15 Werner Koch <wk@gnupg.org> + + * encrypt.c (init_dek): Use gry_create_nonce for the IV; there is + not need for real strong random here and it even better protect + the random bits used for the key. + 2003-12-01 Werner Koch <wk@gnupg.org> * gpgsm.c, gpgsm.h: New options --{enable,disable}-ocsp. diff --git a/sm/decrypt.c b/sm/decrypt.c index 23858efa8..671b4aa5e 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -51,7 +51,7 @@ struct decrypt_filter_parm_s { -/* decrypt the session key and fill in the parm structure. The +/* Decrypt the session key and fill in the parm structure. The algo and the IV is expected to be already in PARM. */ static int prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val, diff --git a/sm/encrypt.c b/sm/encrypt.c index 616949bf4..60752fa07 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -61,7 +61,7 @@ struct encrypt_cb_parm_s { -/* initialize the data encryptionkey (session key) */ +/* Initialize the data encryption key (session key). */ static int init_dek (DEK dek) { @@ -112,7 +112,7 @@ init_dek (DEK dek) return rc; } - gcry_randomize (dek->iv, dek->ivlen, GCRY_STRONG_RANDOM); + gcry_create_nonce (dek->iv, dek->ivlen); rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); if (rc) { diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 161d185b1..d3180adee 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -211,8 +211,8 @@ static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("@Commands:\n ") }, - { aSign, "sign", 256, N_("|[file]|make a signature")}, - { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, + { aSign, "sign", 256, N_("|[FILE]|make a signature")}, + { aClearsign, "clearsign", 256, N_("|[FILE]|make a clear text signature") }, { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, { aEncr, "encrypt", 256, N_("encrypt data")}, { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, diff --git a/sm/server.c b/sm/server.c index dda150964..20ba51301 100644 --- a/sm/server.c +++ b/sm/server.c @@ -49,7 +49,7 @@ struct server_local_s { -/* note, that it is sufficient to allocate the target string D as +/* Note that it is sufficient to allocate the target string D as long as the source string S, i.e.: strlen(s)+1; */ static void strcpy_escaped_plus (char *d, const unsigned char *s) -- cgit v1.2.3 From 9f8cb453b7f7b5b3c40570d4da70b173ec252f19 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 11:32:52 +0000 Subject: Add simple tool to watch the log output of gnupg and related modules. --- tools/watchgnupg.c | 337 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 tools/watchgnupg.c diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c new file mode 100644 index 000000000..d6ed36415 --- /dev/null +++ b/tools/watchgnupg.c @@ -0,0 +1,337 @@ +/* watchgnupg.c - Socket server for GnuPG logs + * 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 <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <assert.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> + + +#define PGM "watchgnupg" + +static int verbose; +static int debug; + + +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); + + exit (1); +} + + +/* static void */ +/* err (const char *format, ...) */ +/* { */ +/* va_list arg_ptr; */ + +/* fflush (stdout); */ +/* fprintf (stderr, "%s: ", PGM); */ + +/* va_start (arg_ptr, format); */ +/* vfprintf (stderr, format, arg_ptr); */ +/* va_end (arg_ptr); */ +/* putc ('\n', stderr); */ +/* } */ + +static void * +xmalloc (size_t n) +{ + void *p = malloc (n); + if (!p) + die ("out of core"); + return p; +} + +static void * +xcalloc (size_t n, size_t m) +{ + void *p = calloc (n, m); + if (!p) + die ("out of core"); + return p; +} + +static void * +xrealloc (void *old, size_t n) +{ + void *p = realloc (old, n); + if (!p) + die ("out of core"); + return p; +} + + +struct client_s { + struct client_s *next; + int fd; + size_t size; /* Allocated size of buffer. */ + size_t len; /* Current length of buffer. */ + unsigned char *buffer; /* Buffer to with data already read. */ + +}; +typedef struct client_s *client_t; + + + +/* Print LINE for the client identified by C. Calling this function + witgh LINE set to NULL, will flush the internal buffer. */ +static void +print_line (client_t c, const char *line) +{ + const char *s; + size_t n; + + if (!line) + { + if (c->buffer && c->len) + { + printf ("%3d - ", c->fd); + fwrite (c->buffer, c->len, 1, stdout); + putc ('\n', stdout); + c->len = 0; + } + return; + } + + while ((s = strchr (line, '\n'))) + { + printf ("%3d - ", c->fd); + if (c->buffer && c->len) + { + fwrite (c->buffer, c->len, 1, stdout); + c->len = 0; + } + fwrite (line, s - line + 1, 1, stdout); + line = s + 1; + } + n = strlen (line); + if (!c->buffer) + { + c->size = 256 - (n + 256) % 256; + c->buffer = xmalloc (c->size); + memcpy (c->buffer, line, n); + c->len = n; + } + else + { + if (c->len + n > c->size) + { + c->size += 256 - (n + 256) % 256; + c->buffer = xrealloc (c->buffer, c->size); + } + memcpy (c->buffer + c->len, line, n); + c->len += n; + } +} + + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + int force = 0; + + struct sockaddr_un srvr_addr; + int addrlen; + int server; + client_t client_list = NULL; + + if (argc) + { + argc--; argv++; + } + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--help")) + { + puts ( + "usage: " PGM " [options] socketname\n" + "\n" + " Options are --verbose, --debug and --force"); + exit (0); + } + if (!strcmp (*argv, "--verbose")) + { + verbose = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose = debug = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--force")) + { + force = 1; + argc--; argv++; + } + } + + if (argc != 1) + { + die ("usage: " PGM " socketname\n"); + } + + + if (verbose) + fprintf (stderr, "opening socket `%s'\n", *argv); + + setvbuf (stdout, NULL, _IOLBF, 0); + + server = socket (PF_LOCAL, SOCK_STREAM, 0); + if (server == -1) + die ("socket() failed: %s\n", strerror (errno)); + + memset (&srvr_addr, 0, sizeof srvr_addr); + srvr_addr.sun_family = AF_LOCAL; + strncpy (srvr_addr.sun_path, *argv, sizeof (srvr_addr.sun_path) - 1); + srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0; + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (srvr_addr.sun_path) + 1); + + + again: + if (bind (server, (struct sockaddr *) &srvr_addr, addrlen)) + { + if (errno == EADDRINUSE && force) + { + force = 0; + remove (srvr_addr.sun_path); + goto again; + } + die ("bind to `%s' failed: %s\n", *argv, strerror (errno)); + } + + if (listen (server, 5)) + die ("listen failed: %s\n", strerror (errno)); + + for (;;) + { + fd_set rfds; + int max_fd; + client_t client; + + /* Usually we don't have that many connections, thus it is okay + to set them al the time from scratch and don't maintain an + active fd_set. */ + FD_ZERO (&rfds); + FD_SET (server, &rfds); + max_fd = server; + for (client = client_list; client; client = client->next) + if (client->fd != -1) + { + FD_SET (client->fd, &rfds); + if (client->fd > max_fd) + max_fd = client->fd; + } + + if (select (max_fd + 1, &rfds, NULL, NULL, NULL) <= 0) + continue; /* Ignore any errors. */ + + if (FD_ISSET (server, &rfds)) /* New connection. */ + { + struct sockaddr_un clnt_addr; + int fd; + + addrlen = sizeof clnt_addr; + fd = accept (server, (struct sockaddr *) &clnt_addr, &addrlen); + if (fd == -1) + { + printf ("accepting connection failed: %s\n", strerror (errno)); + } + else if (fd >= FD_SETSIZE) + { + close (fd); + printf ("[connection request denied: too many connections\n"); + } + else + { + for (client = client_list; client && client->fd != -1; + client = client->next) + ; + if (!client) + { + client = xcalloc (1, sizeof *client); + client->next = client_list; + client_list = client; + } + client->fd = fd; + printf ("[client at fd %d connected]\n", client->fd); + } + } + for (client = client_list; client; client = client->next) + if (client->fd != -1) + { + char line[256]; + int n; + + n = read (client->fd, line, sizeof line - 1); + if (n == 1) + { + int save_errno = errno; + print_line (client, NULL); /* flush */ + printf ("[client at fd %d read error: %s]\n", + client->fd, strerror (save_errno)); + close (client->fd); + client->fd = -1; + } + else if (!n) + { + print_line (client, NULL); /* flush */ + close (client->fd); + printf ("[client at fd %d disconnected]\n", client->fd); + client->fd = -1; + } + else + { + line[n] = 0; + print_line (client, line); + } + } + } + + return 0; +} + + +/* +Local Variables: +compile-command: "gcc -Wall -g -o watchgnupg watchgnupg.c" +End: +*/ -- cgit v1.2.3 From 082e84c273052e7aebc04bb30529de7cc10bd297 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 14:20:45 +0000 Subject: Fixed blatant allocation bug. --- tools/watchgnupg.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index d6ed36415..d74119a1a 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -139,19 +139,14 @@ print_line (client_t c, const char *line) line = s + 1; } n = strlen (line); - if (!c->buffer) + if (n) { - c->size = 256 - (n + 256) % 256; - c->buffer = xmalloc (c->size); - memcpy (c->buffer, line, n); - c->len = n; - } - else - { - if (c->len + n > c->size) + if (c->len + n >= c->size) { - c->size += 256 - (n + 256) % 256; - c->buffer = xrealloc (c->buffer, c->size); + c->size += ((n + 255) & ~255); + c->buffer = (c->buffer + ? xrealloc (c->buffer, c->size) + : xmalloc (c->size)); } memcpy (c->buffer + c->len, line, n); c->len += n; -- cgit v1.2.3 From bba0f774225b6e5281101253f6bd627e9421f3f8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 16:30:48 +0000 Subject: (writen, fun_writer, fun_closer): New. (log_set_file): Add feature to log to a socket. (log_set_file, do_logv): Force printing with prefix and pid. --- jnlib/ChangeLog | 1 + jnlib/logging.c | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index e6b7dc3fb..a6ff01d71 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -2,6 +2,7 @@ * logging.c (writen, fun_writer, fun_closer): New. (log_set_file): Add feature to log to a socket. + (log_set_file, do_logv): Force printing with prefix and pid. 2003-11-13 Werner Koch <wk@gnupg.org> diff --git a/jnlib/logging.c b/jnlib/logging.c index b019fb76c..6a12d8771 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -50,6 +50,7 @@ static char prefix_buffer[80]; static int with_time; static int with_prefix; static int with_pid; +static int force_prefixes; static int missing_lf; static int errorcount; @@ -207,6 +208,7 @@ log_set_file (const char *name) { FILE *fp; + force_prefixes = 0; if (name && !strncmp (name, "socket://", 9) && name[9]) { #if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN) @@ -237,6 +239,10 @@ log_set_file (const char *name) fp = stderr; } #endif /* Neither fopencookie nor funopen. */ + + /* We always need to print the prefix and the pid, so that the + server reading the socket can do something meanigful. */ + force_prefixes = 1; } else fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr; @@ -259,7 +265,8 @@ void log_set_fd (int fd) { FILE *fp; - + + force_prefixes = 0; if (fd == 1) fp = stdout; else if (fd == 2) @@ -338,7 +345,7 @@ do_logv( int level, const char *fmt, va_list arg_ptr ) if (level != JNLIB_LOG_CONT) { /* Note this does not work for multiple line logging as we would * need to print to a buffer first */ - if (with_time) + if (with_time && !force_prefixes) { struct tm *tp; time_t atime = time (NULL); @@ -348,14 +355,14 @@ do_logv( int level, const char *fmt, va_list arg_ptr ) 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec ); } - if (with_prefix) + if (with_prefix || force_prefixes) fputs (prefix_buffer, logstream); - if (with_pid) + if (with_pid || force_prefixes) fprintf (logstream, "[%u]", (unsigned int)getpid ()); - if (!with_time) + if (!with_time || force_prefixes) putc (':', logstream); /* A leading backspace suppresses the extra space so that we can - correclty output, programname, filename and linenumber. */ + correctly output, programname, filename and linenumber. */ if (fmt && *fmt == '\b') fmt++; else -- cgit v1.2.3 From f438224daea48f5658a8703a4d6d6c7060f026ae Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 16:30:55 +0000 Subject: (main): Set the prefixes for assuan logging. --- agent/ChangeLog | 4 ++++ agent/gpg-agent.c | 2 ++ scd/ChangeLog | 4 ++++ scd/scdaemon.c | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/agent/ChangeLog b/agent/ChangeLog index c4a37f5e8..0e165e31b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2003-12-16 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): Set the prefixes for assuan logging. + 2003-12-15 Werner Koch <wk@gnupg.org> * protect.c (do_encryption): Use gcry_create_nonce instad of the diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 675f2be3f..47420117e 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -355,6 +355,8 @@ main (int argc, char **argv ) } assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + assuan_set_assuan_log_stream (log_get_stream ()); + assuan_set_assuan_log_prefix (log_get_prefix (NULL)); gcry_set_log_handler (my_gcry_logger, NULL); gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); diff --git a/scd/ChangeLog b/scd/ChangeLog index 873691f63..6b9654f58 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2003-12-16 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main): Set the prefixes for assuan logging. + 2003-11-17 Werner Koch <wk@gnupg.org> * scdaemon.c, scdaemon.h: New options --allow-admin and --deny-admin. diff --git a/scd/scdaemon.c b/scd/scdaemon.c index a3100988b..91ac93227 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -272,7 +272,11 @@ main (int argc, char **argv ) } ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + assuan_set_assuan_log_stream (log_get_stream ()); + assuan_set_assuan_log_prefix (log_get_prefix (NULL)); + gcry_set_log_handler (my_gcry_logger, NULL); gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); -- cgit v1.2.3 From a41d45af627c7d9cc66d581ea18521a73fc2660e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 16:31:16 +0000 Subject: * gpgsm.c (main): Set the prefixes for assuan logging. * sign.c (gpgsm_sign): Add validation checks for the default certificate. * gpgsm.c: Add -k as alias for --list-keys and -K for --list-secret-keys. --- sm/ChangeLog | 10 ++++++++++ sm/certlist.c | 4 ++-- sm/gpgsm.c | 9 ++++++--- sm/sign.c | 13 ++++++++++++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 2363eb91b..d19e5761d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2003-12-16 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Set the prefixes for assuan logging. + + * sign.c (gpgsm_sign): Add validation checks for the default + certificate. + + * gpgsm.c: Add -k as alias for --list-keys and -K for + --list-secret-keys. + 2003-12-15 Werner Koch <wk@gnupg.org> * encrypt.c (init_dek): Use gry_create_nonce for the IV; there is diff --git a/sm/certlist.c b/sm/certlist.c index 0dfe50e04..9eb3e7cfa 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -135,7 +135,7 @@ same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert) /* Add a certificate to a list of certificate and make sure that it is a valid certificate. With SECRET set to true a secret key must be - avaibale for the certificate. */ + available for the certificate. */ int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, CERTLIST *listaddr) @@ -190,7 +190,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, } } - /* we want the error code from the first match in this case */ + /* We want the error code from the first match in this case. */ if (rc && wrong_usage) rc = wrong_usage; diff --git a/sm/gpgsm.c b/sm/gpgsm.c index d3180adee..95f61132d 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -44,7 +44,8 @@ enum cmd_and_opt_values { aDecrypt = 'd', aEncr = 'e', oInteractive = 'i', - oKOption = 'k', + aListKeys = 'k', + aListSecretKeys = 'K', oDryRun = 'n', oOutput = 'o', oQuiet = 'q', @@ -68,10 +69,8 @@ enum cmd_and_opt_values { aImport, aVerify, aVerifyFiles, - aListKeys, aListExternalKeys, aListSigs, - aListSecretKeys, aSendKeys, aRecvKeys, aExport, @@ -695,7 +694,11 @@ main ( int argc, char **argv) */ ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + assuan_set_assuan_log_stream (log_get_stream ()); + assuan_set_assuan_log_prefix (log_get_prefix (NULL)); + keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); /* Setup a default control structure for command line mode */ diff --git a/sm/sign.c b/sm/sign.c index 95ce8d5dd..38d8ca9ed 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -124,7 +124,7 @@ hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer) /* Get the default certificate which is defined as the first one our - keyDB retruns and has a secret key available */ + keyDB returns and has a secret key available. */ int gpgsm_get_default_cert (KsbaCert *r_cert) { @@ -364,6 +364,17 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, rc = gpg_error (GPG_ERR_GENERAL); goto leave; } + + /* Although we don't check for ambigious specification we will + check that the signer's certificate is is usable and + valid. */ + rc = gpgsm_cert_use_sign_p (cert); + if (!rc) + rc = gpgsm_validate_chain (ctrl, cert, NULL); + if (rc) + goto leave; + + /* That one is fine - create signerlist. */ signerlist = xtrycalloc (1, sizeof *signerlist); if (!signerlist) { -- cgit v1.2.3 From d27fc828d7beca6dad0ccc83a06824e987bd4018 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 16:31:42 +0000 Subject: print the time. --- tools/watchgnupg.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index d74119a1a..63daab11e 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -28,7 +28,7 @@ #include <unistd.h> #include <sys/socket.h> #include <sys/un.h> - +#include <time.h> #define PGM "watchgnupg" @@ -107,6 +107,20 @@ typedef struct client_s *client_t; +static void +print_fd_and_time (int fd) +{ + struct tm *tp; + time_t atime = time (NULL); + + tp = localtime (&atime); + printf ("%3d - %04d-%02d-%02d %02d:%02d:%02d ", + fd, + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec ); +} + + /* Print LINE for the client identified by C. Calling this function witgh LINE set to NULL, will flush the internal buffer. */ static void @@ -119,7 +133,7 @@ print_line (client_t c, const char *line) { if (c->buffer && c->len) { - printf ("%3d - ", c->fd); + print_fd_and_time (c->fd); fwrite (c->buffer, c->len, 1, stdout); putc ('\n', stdout); c->len = 0; @@ -129,7 +143,7 @@ print_line (client_t c, const char *line) while ((s = strchr (line, '\n'))) { - printf ("%3d - ", c->fd); + print_fd_and_time (c->fd); if (c->buffer && c->len) { fwrite (c->buffer, c->len, 1, stdout); -- cgit v1.2.3 From 1114bc64308582c2435cbbdf6698d35931c0c46f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Dec 2003 16:32:02 +0000 Subject: Updated. --- NEWS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index ebc65a27d..ce966b751 100644 --- a/NEWS +++ b/NEWS @@ -5,10 +5,10 @@ Noteworthy changes in version 1.9.3 (unreleased) This requires a not yet released DirMngr 0.5.1. Default is disabled. - * The --log-file 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 --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. Noteworthy changes in version 1.9.2 (2003-11-17) -- cgit v1.2.3 From 911daed647eeb8617bf3b21e1f6e987e5e7e97f2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:25:09 +0000 Subject: (initialize): Replaced use of non-literal forma args. Suggested by Florian Weimer. --- jnlib/ChangeLog | 5 +++++ jnlib/argparse.c | 32 +++++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index a6ff01d71..89a3ccca4 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2003-12-17 Werner Koch <wk@gnupg.org> + + * argparse.c (initialize): Replaced use of non-literal forma + args. Suggested by Florian Weimer. + 2003-12-16 Werner Koch <wk@gnupg.org> * logging.c (writen, fun_writer, fun_closer): New. diff --git a/jnlib/argparse.c b/jnlib/argparse.c index 0eb99d452..148934637 100644 --- a/jnlib/argparse.c +++ b/jnlib/argparse.c @@ -165,35 +165,37 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) if( filename ) { if( arg->r_opt == -6 ) - s = "%s:%u: argument not expected\n"; + s = "argument not expected\n"; else if( arg->r_opt == -5 ) - s = "%s:%u: read error\n"; + s = "read error\n"; else if( arg->r_opt == -4 ) - s = "%s:%u: keyword too long\n"; + s = "keyword too long\n"; else if( arg->r_opt == -3 ) - s = "%s:%u: missing argument\n"; + s = "missing argument\n"; else if( arg->r_opt == -7 ) - s = "%s:%u: invalid command\n"; + s = "invalid command\n"; else if( arg->r_opt == -10 ) - s = "%s:%u: invalid alias definition\n"; + s = "invalid alias definition\n"; else - s = "%s:%u: invalid option\n"; - jnlib_log_error(s, filename, *lineno ); + s = "invalid option\n"; + jnlib_log_error("%s:%u: %s\n", filename, *lineno, s); } else { + s = arg->internal.last? arg->internal.last:"[??]"; + if( arg->r_opt == -3 ) - s = "Missing argument for option \"%.50s\"\n"; + jnlib_log_error ("Missing argument for option \"%.50s\"\n", s); else if( arg->r_opt == -6 ) - s = "Option \"%.50s\" does not expect an argument\n"; + jnlib_log_error ("Option \"%.50s\" does not expect an argument\n", + s ); else if( arg->r_opt == -7 ) - s = "Invalid command \"%.50s\"\n"; + jnlib_log_error ("Invalid command \"%.50s\"\n", s); else if( arg->r_opt == -8 ) - s = "Option \"%.50s\" is ambiguous\n"; + jnlib_log_error ("Option \"%.50s\" is ambiguous\n", s); else if( arg->r_opt == -9 ) - s = "Command \"%.50s\" is ambiguous\n"; + jnlib_log_error ("Command \"%.50s\" is ambiguous\n",s ); else - s = "Invalid option \"%.50s\"\n"; - jnlib_log_error(s, arg->internal.last? arg->internal.last:"[??]" ); + jnlib_log_error ("Invalid option \"%.50s\"\n", s); } if( arg->err != 1 ) exit(2); -- cgit v1.2.3 From 8ab35a7d26707dfa0032b3b0dbde6a984a9683cb Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:26:38 +0000 Subject: * 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. --- common/ChangeLog | 9 +++++++++ common/gettime.c | 6 ++++-- common/miscellaneous.c | 20 ++++++++++++++++++++ common/util.h | 8 +++++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 2344868a7..e69df733f 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,12 @@ +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. diff --git a/common/gettime.c b/common/gettime.c index ed1d0c819..93e4ba113 100644 --- a/common/gettime.c +++ b/common/gettime.c @@ -246,9 +246,11 @@ asctimestamp( u32 stamp ) mem2str( fmt, nl_langinfo(D_T_FMT), DIM(fmt)-3 ); if( strstr( fmt, "%Z" ) == NULL ) strcat( fmt, " %Z"); - strftime( buffer, DIM(buffer)-1, fmt, tp ); + /* 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" + /* 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 */ diff --git a/common/miscellaneous.c b/common/miscellaneous.c index bdb12c574..4937bd7ce 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -25,6 +25,26 @@ #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; +} + + + /* Decide whether the filename is stdout or a real filename and return * an appropriate string. */ const char * diff --git a/common/util.h b/common/util.h index e38ced337..80a1d01a6 100644 --- a/common/util.h +++ b/common/util.h @@ -99,6 +99,12 @@ int answer_is_yes_no_quit (const char *s); /*-- 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); @@ -113,7 +119,7 @@ int is_file_compressed (const char *s, int *ret_rc); #if !HAVE_VASPRINTF #include <stdarg.h> int vasprintf (char **result, const char *format, va_list args); -int asprintf (char **result, const char *format, ...); +int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3); #endif -- cgit v1.2.3 From 23fa5c97929a1206aaa662e2833eaec629d95c57 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:26:56 +0000 Subject: * card-util.c (print_name): Fixed bad format string usage. (print_isoname): Ditto. * trustdb.c (check_regexp): s/exp/expr/. * keyedit.c (trustsig_prompt): Removed a "> 255" term; it is always false due to the data type. * passphrase.c (agent_get_passphrase): Use xasprintf and avoid non-literal format strings. * tdbio.c (upd_hashtable, drop_from_hashtable, lookup_hashtable): Fixed log_error format string bugs. Kudos to the now working gcc-3.3 -Wformat-nonliteral and Florian Weimer's investigations in gnupg 1.2.3. --- g10/ChangeLog | 18 ++++++++++++++++++ g10/card-util.c | 5 ++--- g10/keyedit.c | 4 ++-- g10/passphrase.c | 18 ++++++------------ g10/tdbio.c | 31 +++++++++++++++++-------------- g10/trustdb.c | 8 ++++---- 6 files changed, 49 insertions(+), 35 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 849e6931a..f3399b510 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,21 @@ +2003-12-17 Werner Koch <wk@gnupg.org> + + * card-util.c (print_name): Fixed bad format string usage. + (print_isoname): Ditto. + + * trustdb.c (check_regexp): s/exp/expr/. + + * keyedit.c (trustsig_prompt): Removed a "> 255" term; it is + always false due to the data type. + + * passphrase.c (agent_get_passphrase): Use xasprintf and avoid + non-literal format strings. + + * tdbio.c (upd_hashtable, drop_from_hashtable, lookup_hashtable): + Fixed log_error format string bugs. Kudos to the now working + gcc-3.3 -Wformat-nonliteral and Florian Weimer's investigations in + gnupg 1.2.3. + 2003-12-15 Werner Koch <wk@gnupg.org> * seckey-cert.c (protect_secret_key): Use gry_create_nonce for the diff --git a/g10/card-util.c b/g10/card-util.c index de445b796..c40cfd84d 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -169,8 +169,7 @@ print_sha1_fpr_colon (FILE *fp, const unsigned char *fpr) static void print_name (FILE *fp, const char *text, const char *name) { - tty_fprintf (fp, text); - + tty_fprintf (fp, "%s", text); /* FIXME: tty_printf_utf8_string2 eats everything after and including an @ - e.g. when printing an url. */ @@ -192,7 +191,7 @@ 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, text); + tty_fprintf (fp, "%s", text); if (name && *name) { diff --git a/g10/keyedit.c b/g10/keyedit.c index bd41772fd..4da174e3c 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -298,7 +298,7 @@ sign_mk_attrib( PKT_signature *sig, void *opaque ) } static void -trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) +trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) { char *p; @@ -344,7 +344,7 @@ trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) cpr_kill_prompt(); *trust_depth=atoi(p); xfree (p); - if(*trust_depth<1 || *trust_depth>255) + if(*trust_depth < 1 ) *trust_depth=0; } diff --git a/g10/passphrase.c b/g10/passphrase.c index ac7e71591..0db9404b9 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -673,32 +673,26 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, const char *algo_name = gcry_pk_algo_name ( pk->pubkey_algo ); const char *timestr; char *maink; - const char *fmtstr; if ( !algo_name ) algo_name = "?"; - fmtstr = _(" (main key ID %08lX)"); - maink = xmalloc ( strlen (fmtstr) + 20 ); if( keyid[2] && keyid[3] && keyid[0] != keyid[2] && keyid[1] != keyid[3] ) - sprintf( maink, fmtstr, (ulong)keyid[3] ); + maink = xasprintf ( _(" (main key ID %08lX)"), (ulong)keyid[3] ); else - *maink = 0; + maink = NULL; uid = get_user_id ( keyid, &uidlen ); timestr = strtimestamp (pk->timestamp); - fmtstr = _("You need a passphrase to unlock the" + atext = xasprintf ( + _("You need a passphrase to unlock the" " secret key for user:\n" "\"%.*s\"\n" - "%u-bit %s key, ID %08lX, created %s%s\n" ); - atext = xmalloc ( 100 + strlen (fmtstr) - + uidlen + 15 + strlen(algo_name) + 8 - + strlen (timestr) + strlen (maink) ); - sprintf (atext, fmtstr, + "%u-bit %s key, ID %08lX, created %s%s\n" ), uidlen, uid, nbits_from_pk (pk), algo_name, (ulong)keyid[1], timestr, - maink ); + maink?maink:"" ); xfree (uid); xfree (maink); diff --git a/g10/tdbio.c b/g10/tdbio.c index d1b5ed32a..75687a3b0 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -782,9 +782,9 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { - log_error( db_name, "upd_hashtable: read failed: %s\n", - gpg_strerror (rc) ); - return rc; + log_error ("upd_hashtable in `%s': read failed: %s\n", db_name, + gpg_strerror (rc) ); + return rc; } item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; @@ -792,8 +792,8 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum; rc = tdbio_write_record( &rec ); if( rc ) { - log_error( db_name, "upd_hashtable: write htbl failed: %s\n", - gpg_strerror (rc) ); + log_error ("upd_hashtable in `%s': write htbl failed: %s\n", + db_name, gpg_strerror (rc) ); return rc; } } @@ -931,8 +931,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { - log_error( db_name, "drop_from_hashtable: read failed: %s\n", - gpg_strerror (rc) ); + log_error ("drop_from_hashtable `%s': read failed: %s\n", + db_name, gpg_strerror (rc) ); return rc; } @@ -944,8 +944,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0; rc = tdbio_write_record( &rec ); if( rc ) - log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - gpg_strerror (rc) ); + log_error ("drop_from_hashtable `%s': write htbl failed: %s\n", + db_name, gpg_strerror (rc) ); return rc; } @@ -973,8 +973,9 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rec.r.hlst.rnum[i] = 0; /* drop */ rc = tdbio_write_record( &rec ); if( rc ) - log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n", - gpg_strerror (rc) ); + log_error ("drop_from_hashtable `%s': " + "write htbl failed: %s\n", + db_name, gpg_strerror (rc) ); return rc; } } @@ -1020,7 +1021,8 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL ); if( rc ) { - log_error( db_name, "lookup_hashtable failed: %s\n", gpg_strerror (rc) ); + log_error ("lookup_hashtable in `%s' failed: %s\n", + db_name, gpg_strerror (rc) ); return rc; } @@ -1030,14 +1032,15 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( item, rec, 0 ); if( rc ) { - log_error( db_name, "hashtable read failed: %s\n", gpg_strerror (rc) ); + log_error ("hashtable `%s' read failed: %s\n", + db_name, gpg_strerror (rc) ); return rc; } if( rec->rectype == RECTYPE_HTBL ) { hashrec = item; level++; if( level >= keylen ) { - log_error( db_name, "hashtable has invalid indirections\n"); + log_error ("hashtable `%s' has invalid indirections\n", db_name); return GPG_ERR_TRUSTDB; } goto next_level; diff --git a/g10/trustdb.c b/g10/trustdb.c index 864334f4f..b3a2b369e 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1539,19 +1539,19 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, signature. Returns 1 for match, and 0 for no match or regex error. */ static int -check_regexp(const char *exp,const char *string) +check_regexp(const char *expr,const char *string) { #ifdef DISABLE_REGEX /* When DISABLE_REGEX is defined, assume all regexps do not match. */ return 0; #elif defined(__riscos__) - return riscos_check_regexp(exp, string, DBG_TRUST); + return riscos_check_regexp(expr, string, DBG_TRUST); #else int ret; regex_t pat; - if(regcomp(&pat,exp,REG_ICASE|REG_NOSUB|REG_EXTENDED)!=0) + if(regcomp(&pat,expr,REG_ICASE|REG_NOSUB|REG_EXTENDED)!=0) return 0; ret=regexec(&pat,string,0,NULL,0); @@ -1559,7 +1559,7 @@ check_regexp(const char *exp,const char *string) regfree(&pat); if(DBG_TRUST) - log_debug("regexp \"%s\" on \"%s\": %s\n",exp,string,ret==0?"YES":"NO"); + log_debug("regexp \"%s\" on \"%s\": %s\n",expr,string,ret==0?"YES":"NO"); return (ret==0); #endif -- cgit v1.2.3 From e4cea09fe116d875163baae3b7895101755388d4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:27:21 +0000 Subject: Replaced deprecated type names --- kbx/keybox-blob.c | 4 ++-- kbx/keybox-defs.h | 2 +- kbx/keybox-search.c | 6 +++--- kbx/keybox-update.c | 4 ++-- kbx/keybox.h | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index ca36d6264..defddad69 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -479,7 +479,7 @@ pgp_create_blob_keyblock (KEYBOXBLOB blob, KBNODE keyblock) /* Write the raw certificate out */ static int -x509_create_blob_cert (KEYBOXBLOB blob, KsbaCert cert) +x509_create_blob_cert (KEYBOXBLOB blob, ksba_cert_t cert) { struct membuf *a = blob->buf; const unsigned char *image; @@ -808,7 +808,7 @@ x509_email_kludge (const char *name) /* Note: We should move calculation of the digest into libksba and remove that parameter */ int -_keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert, +_keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, unsigned char *sha1_digest, int as_ephemeral) { int i, rc = 0; diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index fcae64c25..fa145f7e5 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -102,7 +102,7 @@ struct keybox_handle { /* fixme */ #endif /*KEYBOX_WITH_OPENPGP*/ #ifdef KEYBOX_WITH_X509 -int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, KsbaCert cert, +int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, unsigned char *sha1_digest, int as_ephemeral); #endif /*KEYBOX_WITH_X509*/ diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index ff95815a2..e834cd2bf 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -753,13 +753,13 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) Return the last found cert. Caller must free it. */ int -keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *r_cert) +keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert) { const unsigned char *buffer; size_t length; size_t cert_off, cert_len; - KsbaReader reader = NULL; - KsbaCert cert = NULL; + ksba_reader_t reader = NULL; + ksba_cert_t cert = NULL; int rc; if (!hd) diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index 52ad258b0..ed9ca2bf7 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -337,7 +337,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, #ifdef KEYBOX_WITH_X509 int -keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, +keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, unsigned char *sha1_digest) { int rc; @@ -375,7 +375,7 @@ keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, } int -keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert, +keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, unsigned char *sha1_digest) { return -1; diff --git a/kbx/keybox.h b/kbx/keybox.h index 5fe5516d4..5a5ad2933 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -59,7 +59,7 @@ int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes); /*-- keybox-search.c --*/ #ifdef KEYBOX_WITH_X509 -int keybox_get_cert (KEYBOX_HANDLE hd, KsbaCert *ret_cert); +int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert); #endif /*KEYBOX_WITH_X509*/ int keybox_search_reset (KEYBOX_HANDLE hd); @@ -68,9 +68,9 @@ int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc); /*-- keybox-update.c --*/ #ifdef KEYBOX_WITH_X509 -int keybox_insert_cert (KEYBOX_HANDLE hd, KsbaCert cert, +int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, unsigned char *sha1_digest); -int keybox_update_cert (KEYBOX_HANDLE hd, KsbaCert cert, +int keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, unsigned char *sha1_digest); #endif /*KEYBOX_WITH_X509*/ -- cgit v1.2.3 From c4182e3e24546c248f932d9acd46b79105841f38 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:27:51 +0000 Subject: Replaced deprecated type names. * card-p15.c (p15_enum_keypairs): Replaced KRC by RC. * card-dinsig.c (dinsig_enum_keypairs): Ditto. --- scd/ChangeLog | 5 +++++ scd/card-common.h | 2 +- scd/card-dinsig.c | 11 +++++------ scd/card-p15.c | 11 +++++------ scd/card.c | 4 ++-- scd/ccid-driver.c | 2 +- scd/command.c | 4 ++-- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 6b9654f58..60b5f8eb9 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2003-12-17 Werner Koch <wk@gnupg.org> + + * card-p15.c (p15_enum_keypairs): Replaced KRC by RC. + * card-dinsig.c (dinsig_enum_keypairs): Ditto. + 2003-12-16 Werner Koch <wk@gnupg.org> * scdaemon.c (main): Set the prefixes for assuan logging. diff --git a/scd/card-common.h b/scd/card-common.h index 31f0dfe8f..cefaf120f 100644 --- a/scd/card-common.h +++ b/scd/card-common.h @@ -60,7 +60,7 @@ struct card_ctx_s { /*-- card.c --*/ gpg_error_t map_sc_err (int rc); -int card_help_get_keygrip (KsbaCert cert, unsigned char *array); +int card_help_get_keygrip (ksba_cert_t cert, unsigned char *array); /*-- card-15.c --*/ void p15_release_private_data (CARD card); diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c index 18a67abb6..bb070d5f0 100644 --- a/scd/card-dinsig.c +++ b/scd/card-dinsig.c @@ -99,8 +99,7 @@ dinsig_enum_keypairs (CARD card, int idx, int rc; unsigned char *buf; size_t buflen; - KsbaError krc; - KsbaCert cert; + ksba_cert_t cert; /* fixme: We should locate the application via the EF(DIR) and not assume a Netkey card */ @@ -120,14 +119,14 @@ dinsig_enum_keypairs (CARD card, int idx, return rc; } - krc = ksba_cert_init_from_mem (cert, buf, buflen); + rc = ksba_cert_init_from_mem (cert, buf, buflen); xfree (buf); - if (krc) + if (rc) { log_error ("failed to parse the certificate at idx %d: %s\n", - idx, gpg_strerror (krc)); + idx, gpg_strerror (rc)); ksba_cert_release (cert); - return krc; + return rc; } if (card_help_get_keygrip (cert, keygrip)) { diff --git a/scd/card-p15.c b/scd/card-p15.c index 33c58e2c8..239e75045 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -109,14 +109,13 @@ p15_enum_keypairs (CARD card, int idx, unsigned char *keygrip, char **keyid) { int rc; - KsbaError krc; struct p15private_s *priv; struct sc_pkcs15_object *tmpobj; int nobjs; struct sc_pkcs15_prkey_info *pinfo; struct sc_pkcs15_cert_info *certinfo; struct sc_pkcs15_cert *certder; - KsbaCert cert; + ksba_cert_t cert; rc = init_private_data (card); if (rc) @@ -154,14 +153,14 @@ p15_enum_keypairs (CARD card, int idx, sc_pkcs15_free_certificate (certder); return rc; } - krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len); + rc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len); sc_pkcs15_free_certificate (certder); - if (krc) + if (rc) { log_error ("failed to parse the certificate for private key %d: %s\n", - idx, gpg_strerror (krc)); + idx, gpg_strerror (rc)); ksba_cert_release (cert); - return krc; + return rc; } if (card_help_get_keygrip (cert, keygrip)) { diff --git a/scd/card.c b/scd/card.c index 042613294..95149074d 100644 --- a/scd/card.c +++ b/scd/card.c @@ -58,11 +58,11 @@ map_sc_err (int rc) /* Get the keygrip from CERT, return 0 on success */ int -card_help_get_keygrip (KsbaCert cert, unsigned char *array) +card_help_get_keygrip (ksba_cert_t cert, unsigned char *array) { gcry_sexp_t s_pkey; int rc; - KsbaSexp p; + ksba_sexp_t p; size_t n; p = ksba_cert_get_public_key (cert); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 099dae240..936672cc6 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -133,7 +133,7 @@ /* Define to print information pertaining the T=1 protocol. */ -#undef DEBUG_T1 1 +#undef DEBUG_T1 diff --git a/scd/command.c b/scd/command.c index 122a2f3c1..bc3132a0b 100644 --- a/scd/command.c +++ b/scd/command.c @@ -437,8 +437,8 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line) int rc; unsigned char *cert = NULL; size_t ncert, n; - KsbaCert kc = NULL; - KsbaSexp p; + ksba_cert_t kc = NULL; + ksba_sexp_t p; if ((rc = open_card (ctrl))) return rc; -- cgit v1.2.3 From cbd57643a796acd3de6819183e751b251e748c32 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:28:24 +0000 Subject: Replaced deprecated type names. * certdump.c (gpgsm_print_serial): Cleaned up cast use in strtoul. (gpgsm_dump_serial): Ditto. * decrypt.c (gpgsm_decrypt): Replaced ERR by RC. --- sm/ChangeLog | 7 ++++++ sm/base64.c | 8 +++---- sm/call-agent.c | 10 ++++----- sm/call-dirmngr.c | 12 +++++------ sm/certchain.c | 32 ++++++++++++++-------------- sm/certcheck.c | 10 ++++----- sm/certdump.c | 16 +++++++------- sm/certlist.c | 22 +++++++++---------- sm/certreqgen.c | 18 ++++++++-------- sm/decrypt.c | 53 ++++++++++++++++++++------------------------- sm/delete.c | 4 ++-- sm/encrypt.c | 14 ++++++------ sm/export.c | 10 ++++----- sm/fingerprint.c | 18 ++++++++-------- sm/gpgsm.c | 2 +- sm/gpgsm.h | 64 +++++++++++++++++++++++++++---------------------------- sm/import.c | 18 ++++++++-------- sm/keydb.c | 10 ++++----- sm/keydb.h | 8 +++---- sm/keylist.c | 26 +++++++++++----------- sm/sign.c | 28 ++++++++++++------------ sm/verify.c | 16 +++++++------- 22 files changed, 203 insertions(+), 203 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index d19e5761d..62505fee9 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2003-12-17 Werner Koch <wk@gnupg.org> + + * certdump.c (gpgsm_print_serial): Cleaned up cast use in strtoul. + (gpgsm_dump_serial): Ditto. + + * decrypt.c (gpgsm_decrypt): Replaced ERR by RC. + 2003-12-16 Werner Koch <wk@gnupg.org> * gpgsm.c (main): Set the prefixes for assuan logging. diff --git a/sm/base64.c b/sm/base64.c index aef287250..11237dcc1 100644 --- a/sm/base64.c +++ b/sm/base64.c @@ -497,10 +497,10 @@ base64_finish_write (struct writer_cb_parm_s *parm) ksba_reader_release function on. */ int gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaReader *r_reader) + CTRL ctrl, FILE *fp, ksba_reader_t *r_reader) { int rc; - KsbaReader r; + ksba_reader_t r; *r_reader = NULL; *ctx = xtrycalloc (1, sizeof **ctx); @@ -562,10 +562,10 @@ gpgsm_destroy_reader (Base64Context ctx) function on. */ int gpgsm_create_writer (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaWriter *r_writer) + CTRL ctrl, FILE *fp, ksba_writer_t *r_writer) { int rc; - KsbaWriter w; + ksba_writer_t w; *r_writer = NULL; *ctx = xtrycalloc (1, sizeof **ctx); diff --git a/sm/call-agent.c b/sm/call-agent.c index acb4ac190..fe740964b 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -377,7 +377,7 @@ inq_ciphertext_cb (void *opaque, const char *keyword) the hex string KEYGRIP. */ int gpgsm_agent_pkdecrypt (const char *keygrip, - KsbaConstSexp ciphertext, + ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen ) { int rc; @@ -464,7 +464,7 @@ inq_genkey_parms (void *opaque, const char *keyword) /* Call the agent to generate a newkey */ int -gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey) +gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey) { int rc; struct genkey_parm_s gk_parm; @@ -511,7 +511,7 @@ gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey) /* Ask the agent whether the certificate is in the list of trusted keys */ int -gpgsm_agent_istrusted (KsbaCert cert) +gpgsm_agent_istrusted (ksba_cert_t cert) { int rc; char *fpr; @@ -538,7 +538,7 @@ gpgsm_agent_istrusted (KsbaCert cert) /* Ask the agent to mark CERT as a trusted Root-CA one */ int -gpgsm_agent_marktrusted (KsbaCert cert) +gpgsm_agent_marktrusted (ksba_cert_t cert) { int rc; char *fpr, *dn; @@ -601,7 +601,7 @@ learn_cb (void *opaque, const void *buffer, size_t length) struct learn_parm_s *parm = opaque; size_t len; char *buf; - KsbaCert cert; + ksba_cert_t cert; int rc; if (parm->error) diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 8700145e3..05f7bd10d 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -48,13 +48,13 @@ static int force_pipe_server = 0; struct inq_certificate_parm_s { ASSUAN_CONTEXT ctx; - KsbaCert cert; + ksba_cert_t cert; }; struct lookup_parm_s { CTRL ctrl; ASSUAN_CONTEXT ctx; - void (*cb)(void *, KsbaCert); + void (*cb)(void *, ksba_cert_t); void *cb_value; struct membuf data; int error; @@ -258,7 +258,7 @@ inq_certificate (void *opaque, const char *line) else { /* send the given certificate */ int err; - KsbaCert cert; + ksba_cert_t cert; err = gpgsm_find_cert (line, &cert); if (err) @@ -353,7 +353,7 @@ lookup_cb (void *opaque, const void *buffer, size_t length) struct lookup_parm_s *parm = opaque; size_t len; char *buf; - KsbaCert cert; + ksba_cert_t cert; int rc; if (parm->error) @@ -477,7 +477,7 @@ lookup_status_cb (void *opaque, const char *line) is optional. */ int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, - void (*cb)(void*, KsbaCert), void *cb_value) + void (*cb)(void*, ksba_cert_t), void *cb_value) { int rc; char *pattern; @@ -537,7 +537,7 @@ run_command_inq_cb (void *opaque, const char *line) if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) ) { /* send the given certificate */ int err; - KsbaCert cert; + ksba_cert_t cert; const unsigned char *der; size_t derlen; diff --git a/sm/certchain.c b/sm/certchain.c index 28b098bf4..59577f6a5 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -35,7 +35,7 @@ #include "i18n.h" static int -unknown_criticals (KsbaCert cert) +unknown_criticals (ksba_cert_t cert) { static const char *known[] = { "2.5.29.15", /* keyUsage */ @@ -45,7 +45,7 @@ unknown_criticals (KsbaCert cert) }; int rc = 0, i, idx, crit; const char *oid; - KsbaError err; + gpg_error_t err; for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit, NULL, NULL));idx++) @@ -68,9 +68,9 @@ unknown_criticals (KsbaCert cert) } static int -allowed_ca (KsbaCert cert, int *chainlen) +allowed_ca (ksba_cert_t cert, int *chainlen) { - KsbaError err; + gpg_error_t err; int flag; err = ksba_cert_is_ca (cert, &flag, chainlen); @@ -86,9 +86,9 @@ allowed_ca (KsbaCert cert, int *chainlen) static int -check_cert_policy (KsbaCert cert) +check_cert_policy (ksba_cert_t cert) { - KsbaError err; + gpg_error_t err; char *policies; FILE *fp; int any_critical; @@ -206,7 +206,7 @@ check_cert_policy (KsbaCert cert) static void -find_up_store_certs_cb (void *cb_value, KsbaCert cert) +find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) { if (keydb_store_cert (cert, 1, NULL)) log_error ("error storing issuer certificate as ephemeral\n"); @@ -215,10 +215,10 @@ find_up_store_certs_cb (void *cb_value, KsbaCert cert) static int -find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer) +find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer) { - KsbaName authid; - KsbaSexp authidno; + ksba_name_t authid; + ksba_sexp_t authidno; int rc = -1; if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno)) @@ -325,7 +325,7 @@ find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer) /* Return the next certificate up in the chain starting at START. Returns -1 when there are no more certificates. */ int -gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next) +gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next) { int rc = 0; char *issuer = NULL; @@ -390,7 +390,7 @@ gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next) /* Check whether the CERT is a root certificate. Returns True if this is the case. */ int -gpgsm_is_root_cert (KsbaCert cert) +gpgsm_is_root_cert (ksba_cert_t cert) { char *issuer; char *subject; @@ -408,13 +408,13 @@ gpgsm_is_root_cert (KsbaCert cert) /* Validate a chain and optionally return the nearest expiration time in R_EXPTIME */ int -gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) +gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) { int rc = 0, depth = 0, maxdepth; char *issuer = NULL; char *subject = NULL; KEYDB_HANDLE kh = keydb_new (0); - KsbaCert subject_cert = NULL, issuer_cert = NULL; + ksba_cert_t subject_cert = NULL, issuer_cert = NULL; ksba_isotime_t current_time; ksba_isotime_t exptime; int any_expired = 0; @@ -714,13 +714,13 @@ gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime) the DB and that this one is valid; which it should be because it has been checked using this function. */ int -gpgsm_basic_cert_check (KsbaCert cert) +gpgsm_basic_cert_check (ksba_cert_t cert) { int rc = 0; char *issuer = NULL; char *subject = NULL; KEYDB_HANDLE kh = keydb_new (0); - KsbaCert issuer_cert = NULL; + ksba_cert_t issuer_cert = NULL; if (opt.no_chain_validation) { diff --git a/sm/certcheck.c b/sm/certcheck.c index 852c75e3a..47cae13c0 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -101,13 +101,13 @@ do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, does only test the cryptographic signature and nothing else. It is assumed that the ISSUER_CERT is valid. */ int -gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert) +gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) { const char *algoid; gcry_md_hd_t md; int rc, algo; gcry_mpi_t frame; - KsbaSexp p; + ksba_sexp_t p; size_t n; gcry_sexp_t s_sig, s_hash, s_pkey; @@ -210,11 +210,11 @@ gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert) int -gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, +gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, gcry_md_hd_t md, int algo) { int rc; - KsbaSexp p; + ksba_sexp_t p; gcry_mpi_t frame; gcry_sexp_t s_sig, s_hash, s_pkey; size_t n; @@ -278,7 +278,7 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, int -gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo, +gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, char **r_sigval) { int rc; diff --git a/sm/certdump.c b/sm/certdump.c index f06cc5832..f64e985d3 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -42,10 +42,10 @@ struct dn_array_s { /* print the first element of an S-Expression */ void -gpgsm_print_serial (FILE *fp, KsbaConstSexp p) +gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p) { unsigned long n; - KsbaConstSexp endp; + char *endp; if (!p) fputs (_("none"), fp); @@ -54,7 +54,7 @@ gpgsm_print_serial (FILE *fp, KsbaConstSexp p) else { p++; - n = strtoul (p, (char**)&endp, 10); + n = strtoul (p, &endp, 10); p = endp; if (*p!=':') fputs ("[Internal Error - invalid S-expression]", fp); @@ -68,10 +68,10 @@ gpgsm_print_serial (FILE *fp, KsbaConstSexp p) void -gpgsm_dump_serial (KsbaConstSexp p) +gpgsm_dump_serial (ksba_const_sexp_t p) { unsigned long n; - KsbaConstSexp endp; + char *endp; if (!p) log_printf ("none"); @@ -80,7 +80,7 @@ gpgsm_dump_serial (KsbaConstSexp p) else { p++; - n = strtoul (p, (char**)&endp, 10); + n = strtoul (p, &endp, 10); p = endp; if (*p!=':') log_printf ("ERROR - invalid S-expression"); @@ -142,9 +142,9 @@ gpgsm_dump_string (const char *string) void -gpgsm_dump_cert (const char *text, KsbaCert cert) +gpgsm_dump_cert (const char *text, ksba_cert_t cert) { - KsbaSexp sexp; + ksba_sexp_t sexp; unsigned char *p; char *dn; ksba_isotime_t t; diff --git a/sm/certlist.c b/sm/certlist.c index 9eb3e7cfa..fe2830909 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -39,9 +39,9 @@ for verification and a MODE of 3 for decryption (just for debugging) */ static int -cert_usage_p (KsbaCert cert, int mode) +cert_usage_p (ksba_cert_t cert, int mode) { - KsbaError err; + gpg_error_t err; unsigned int use; err = ksba_cert_get_key_usage (cert, &use); @@ -83,7 +83,7 @@ cert_usage_p (KsbaCert cert, int mode) /* Return 0 if the cert is usable for signing */ int -gpgsm_cert_use_sign_p (KsbaCert cert) +gpgsm_cert_use_sign_p (ksba_cert_t cert) { return cert_usage_p (cert, 0); } @@ -91,32 +91,32 @@ gpgsm_cert_use_sign_p (KsbaCert cert) /* Return 0 if the cert is usable for encryption */ int -gpgsm_cert_use_encrypt_p (KsbaCert cert) +gpgsm_cert_use_encrypt_p (ksba_cert_t cert) { return cert_usage_p (cert, 1); } int -gpgsm_cert_use_verify_p (KsbaCert cert) +gpgsm_cert_use_verify_p (ksba_cert_t cert) { return cert_usage_p (cert, 2); } int -gpgsm_cert_use_decrypt_p (KsbaCert cert) +gpgsm_cert_use_decrypt_p (ksba_cert_t cert) { return cert_usage_p (cert, 3); } int -gpgsm_cert_use_cert_p (KsbaCert cert) +gpgsm_cert_use_cert_p (ksba_cert_t cert) { return cert_usage_p (cert, 4); } static int -same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert) +same_subject_issuer (const char *subject, const char *issuer, ksba_cert_t cert) { char *subject2 = ksba_cert_get_subject (cert, 0); char *issuer2 = ksba_cert_get_subject (cert, 0); @@ -143,7 +143,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, int rc; KEYDB_SEARCH_DESC desc; KEYDB_HANDLE kh = NULL; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; rc = keydb_classify_name (name, &desc); if (!rc) @@ -202,7 +202,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, rc = 0; else if (!rc) { - KsbaCert cert2 = NULL; + ksba_cert_t cert2 = NULL; /* We have to ignore ambigious names as long as there only fault is a bad key usage */ @@ -275,7 +275,7 @@ gpgsm_release_certlist (CERTLIST list) /* Like gpgsm_add_to_certlist, but look only for one certificate. No chain validation is done */ int -gpgsm_find_cert (const char *name, KsbaCert *r_cert) +gpgsm_find_cert (const char *name, ksba_cert_t *r_cert) { int rc; KEYDB_SEARCH_DESC desc; diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 06a788ad9..cffa564bd 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -125,14 +125,14 @@ struct para_data_s { struct reqgen_ctrl_s { int lnr; int dryrun; - KsbaWriter writer; + ksba_writer_t writer; }; static int proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl); static int create_request (struct para_data_s *para, - KsbaConstSexp public, + ksba_const_sexp_t public, struct reqgen_ctrl_s *outctrl); @@ -228,7 +228,7 @@ get_parameter_uint (struct para_data_s *para, enum para_name key) /* Read the certificate generation parameters from FP and generate (all) certificate requests. */ static int -read_parameters (FILE *fp, KsbaWriter writer) +read_parameters (FILE *fp, ksba_writer_t writer) { static struct { const char *name; @@ -423,7 +423,7 @@ proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) char numbuf[20]; unsigned char keyparms[100]; int rc; - KsbaSexp public; + ksba_sexp_t public; /* check that we have all required parameters */ assert (get_parameter (para, pKEYTYPE)); @@ -503,13 +503,13 @@ proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) /* Parameters are checked, the key pair has been created. Now generate the request and write it out */ static int -create_request (struct para_data_s *para, KsbaConstSexp public, +create_request (struct para_data_s *para, ksba_const_sexp_t public, struct reqgen_ctrl_s *outctrl) { - KsbaCertreq cr; - KsbaError err; + ksba_certreq_t cr; + gpg_error_t err; gcry_md_hd_t md; - KsbaStopReason stopreason; + ksba_stop_reason_t stopreason; int rc = 0; const char *s; @@ -655,7 +655,7 @@ gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp) int rc; FILE *in_fp; Base64Context b64writer = NULL; - KsbaWriter writer; + ksba_writer_t writer; in_fp = fdopen (dup (in_fd), "rb"); if (!in_fp) diff --git a/sm/decrypt.c b/sm/decrypt.c index 671b4aa5e..9b02392d6 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -54,7 +54,7 @@ struct decrypt_filter_parm_s { /* Decrypt the session key and fill in the parm structure. The algo and the IV is expected to be already in PARM. */ static int -prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val, +prepare_decryption (const char *hexkeygrip, ksba_const_sexp_t enc_val, struct decrypt_filter_parm_s *parm) { char *seskey = NULL; @@ -148,7 +148,7 @@ prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val, Due to different buffer sizes or different length of input and output, it may happen that fewer bytes are process or fewer bytes are written. */ -static KsbaError +static gpg_error_t decrypt_filter (void *arg, const void *inbuf, size_t inlen, size_t *inused, void *outbuf, size_t maxoutlen, size_t *outlen) @@ -240,13 +240,12 @@ int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) { int rc; - KsbaError err; Base64Context b64reader = NULL; Base64Context b64writer = NULL; - KsbaReader reader; - KsbaWriter writer; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; + ksba_reader_t reader; + ksba_writer_t writer; + ksba_cms_t cms = NULL; + ksba_stop_reason_t stopreason; KEYDB_HANDLE kh; int recp; FILE *in_fp = NULL; @@ -285,30 +284,25 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) goto leave; } - err = ksba_cms_new (&cms); - if (err) - { - rc = err; - goto leave; - } + rc = ksba_cms_new (&cms); + if (rc) + goto leave; - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) + rc = ksba_cms_set_reader_writer (cms, reader, writer); + if (rc) { log_debug ("ksba_cms_set_reader_writer failed: %s\n", - gpg_strerror (err)); - rc = err; + gpg_strerror (rc)); goto leave; } /* parser loop */ do { - err = ksba_cms_parse (cms, &stopreason); - if (err) + rc = ksba_cms_parse (cms, &stopreason); + if (rc) { - log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (err)); - rc = err; + log_debug ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } @@ -352,27 +346,26 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) &dfparm.ivlen); if (rc) { - log_error ("error getting IV: %s\n", gpg_strerror (err)); - rc = err; + log_error ("error getting IV: %s\n", gpg_strerror (rc)); goto leave; } for (recp=0; !any_key; recp++) { char *issuer; - KsbaSexp serial; - KsbaSexp enc_val; + ksba_sexp_t serial; + ksba_sexp_t enc_val; char *hexkeygrip = NULL; - err = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); - if (err == -1 && recp) + rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); + if (rc == -1 && recp) break; /* no more recipients */ - if (err) + if (rc) log_error ("recp %d - error getting info: %s\n", - recp, gpg_strerror (err)); + recp, gpg_strerror (rc)); else { - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; log_debug ("recp %d - issuer: `%s'\n", recp, issuer? issuer:"[NONE]"); diff --git a/sm/delete.c b/sm/delete.c index 53eff864c..8b04bc426 100644 --- a/sm/delete.c +++ b/sm/delete.c @@ -42,7 +42,7 @@ delete_one (CTRL ctrl, const char *username) int rc = 0; KEYDB_SEARCH_DESC desc; KEYDB_HANDLE kh = NULL; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; int duplicates = 0; rc = keydb_classify_name (username, &desc); @@ -77,7 +77,7 @@ delete_one (CTRL ctrl, const char *username) rc = 0; else if (!rc) { - KsbaCert cert2 = NULL; + ksba_cert_t cert2 = NULL; char fpr2[20]; /* We ignore all duplicated certificates which might have diff --git a/sm/encrypt.c b/sm/encrypt.c index 60752fa07..f31391e7c 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -152,11 +152,11 @@ encode_session_key (DEK dek, gcry_sexp_t * r_data) /* encrypt the DEK under the key contained in CERT and return it as a canonical S-Exp in encval */ static int -encrypt_dek (const DEK dek, KsbaCert cert, char **encval) +encrypt_dek (const DEK dek, ksba_cert_t cert, char **encval) { gcry_sexp_t s_ciph, s_data, s_pkey; int rc; - KsbaSexp buf; + ksba_sexp_t buf; size_t len; *encval = NULL; @@ -292,11 +292,11 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) { int rc = 0; Base64Context b64writer = NULL; - KsbaError err; - KsbaWriter writer; - KsbaReader reader = NULL; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; + gpg_error_t err; + ksba_writer_t writer; + ksba_reader_t reader = NULL; + ksba_cms_t cms = NULL; + ksba_stop_reason_t stopreason; KEYDB_HANDLE kh = NULL; struct encrypt_cb_parm_s encparm; DEK dek = NULL; diff --git a/sm/export.c b/sm/export.c index 73c119fb0..524576628 100644 --- a/sm/export.c +++ b/sm/export.c @@ -33,7 +33,7 @@ #include "keydb.h" -static void print_short_info (KsbaCert cert, FILE *fp); +static void print_short_info (ksba_cert_t cert, FILE *fp); @@ -45,9 +45,9 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) KEYDB_SEARCH_DESC *desc = NULL; int ndesc; Base64Context b64writer = NULL; - KsbaWriter writer; + ksba_writer_t writer; STRLIST sl; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; int rc=0; int count = 0; int i; @@ -197,10 +197,10 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) /* Print some info about the certifciate CERT to FP */ static void -print_short_info (KsbaCert cert, FILE *fp) +print_short_info (ksba_cert_t cert, FILE *fp) { char *p; - KsbaSexp sexp; + ksba_sexp_t sexp; int idx; for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++) diff --git a/sm/fingerprint.c b/sm/fingerprint.c index ec1ed91f2..26d147f41 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -43,7 +43,7 @@ digest of all 0xff. */ char * -gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len) +gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len) { gcry_md_hd_t md; int rc, len; @@ -83,7 +83,7 @@ gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len) /* Return an allocated buffer with the formatted fingerprint */ char * -gpgsm_get_fingerprint_string (KsbaCert cert, int algo) +gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo) { unsigned char digest[MAX_DIGEST_LEN]; char *buf; @@ -105,7 +105,7 @@ gpgsm_get_fingerprint_string (KsbaCert cert, int algo) /* Return an allocated buffer with the formatted fingerprint as one large hexnumber */ char * -gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo) +gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo) { unsigned char digest[MAX_DIGEST_LEN]; char *buf; @@ -127,7 +127,7 @@ gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo) /* Return a certificate ID. These are the last 4 bytes of the SHA-1 fingerprint. */ unsigned long -gpgsm_get_short_fingerprint (KsbaCert cert) +gpgsm_get_short_fingerprint (ksba_cert_t cert) { unsigned char digest[20]; @@ -141,11 +141,11 @@ gpgsm_get_short_fingerprint (KsbaCert cert) be 20 bytes long. returns the array or a newly allocated one if the passed one was NULL */ char * -gpgsm_get_keygrip (KsbaCert cert, char *array) +gpgsm_get_keygrip (ksba_cert_t cert, char *array) { gcry_sexp_t s_pkey; int rc; - KsbaSexp p; + ksba_sexp_t p; size_t n; p = ksba_cert_get_public_key (cert); @@ -184,7 +184,7 @@ gpgsm_get_keygrip (KsbaCert cert, char *array) /* Return an allocated buffer with the keygrip of CERT in from of an hexstring. NULL is returned in case of error */ char * -gpgsm_get_keygrip_hexstring (KsbaCert cert) +gpgsm_get_keygrip_hexstring (ksba_cert_t cert) { unsigned char grip[20]; char *buf, *p; @@ -209,9 +209,9 @@ gpgsm_get_keygrip_hexstring (KsbaCert cert) The caller must free the string. */ char * -gpgsm_get_certid (KsbaCert cert) +gpgsm_get_certid (ksba_cert_t cert) { - KsbaSexp serial; + ksba_sexp_t serial; unsigned char *p; char *endp; unsigned char hash[20]; diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 95f61132d..497df048d 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1316,7 +1316,7 @@ main ( int argc, char **argv) else { int rc; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; char *grip = NULL; rc = gpgsm_find_cert (*argv, &cert); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 680ba9503..8c71c3479 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -142,7 +142,7 @@ typedef struct base64_context_s *Base64Context; struct certlist_s { struct certlist_s *next; - KsbaCert cert; + ksba_cert_t cert; }; typedef struct certlist_s *CERTLIST; @@ -158,62 +158,62 @@ void gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text, gpg_err_code_t ec); /*-- fingerprint --*/ -char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len); -char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo); -char *gpgsm_get_fingerprint_hexstring (KsbaCert cert, int algo); -unsigned long gpgsm_get_short_fingerprint (KsbaCert cert); -char *gpgsm_get_keygrip (KsbaCert cert, char *array); -char *gpgsm_get_keygrip_hexstring (KsbaCert cert); -char *gpgsm_get_certid (KsbaCert cert); +char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len); +char *gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo); +char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo); +unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert); +char *gpgsm_get_keygrip (ksba_cert_t cert, char *array); +char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert); +char *gpgsm_get_certid (ksba_cert_t cert); /*-- base64.c --*/ int gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaReader *r_reader); + CTRL ctrl, FILE *fp, ksba_reader_t *r_reader); void gpgsm_destroy_reader (Base64Context ctx); int gpgsm_create_writer (Base64Context *ctx, - CTRL ctrl, FILE *fp, KsbaWriter *r_writer); + CTRL ctrl, FILE *fp, ksba_writer_t *r_writer); int gpgsm_finish_writer (Base64Context ctx); void gpgsm_destroy_writer (Base64Context ctx); /*-- certdump.c --*/ -void gpgsm_print_serial (FILE *fp, KsbaConstSexp p); +void gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p); void gpgsm_print_time (FILE *fp, ksba_isotime_t t); void gpgsm_print_name (FILE *fp, const char *string); -void gpgsm_dump_cert (const char *text, KsbaCert cert); -void gpgsm_dump_serial (KsbaConstSexp p); +void gpgsm_dump_cert (const char *text, ksba_cert_t cert); +void gpgsm_dump_serial (ksba_const_sexp_t p); void gpgsm_dump_time (ksba_isotime_t t); void gpgsm_dump_string (const char *string); /*-- certcheck.c --*/ -int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert); -int gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval, +int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert); +int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, gcry_md_hd_t md, int hash_algo); /* fixme: move create functions to another file */ -int gpgsm_create_cms_signature (KsbaCert cert, gcry_md_hd_t md, int mdalgo, +int gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, char **r_sigval); /*-- certchain.c --*/ -int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next); -int gpgsm_is_root_cert (KsbaCert cert); -int gpgsm_validate_chain (CTRL ctrl, KsbaCert cert, ksba_isotime_t r_exptime); -int gpgsm_basic_cert_check (KsbaCert cert); +int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next); +int gpgsm_is_root_cert (ksba_cert_t cert); +int gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime); +int gpgsm_basic_cert_check (ksba_cert_t cert); /*-- certlist.c --*/ -int gpgsm_cert_use_sign_p (KsbaCert cert); -int gpgsm_cert_use_encrypt_p (KsbaCert cert); -int gpgsm_cert_use_verify_p (KsbaCert cert); -int gpgsm_cert_use_decrypt_p (KsbaCert cert); -int gpgsm_cert_use_cert_p (KsbaCert cert); +int gpgsm_cert_use_sign_p (ksba_cert_t cert); +int gpgsm_cert_use_encrypt_p (ksba_cert_t cert); +int gpgsm_cert_use_verify_p (ksba_cert_t cert); +int gpgsm_cert_use_decrypt_p (ksba_cert_t cert); +int gpgsm_cert_use_cert_p (ksba_cert_t cert); int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, CERTLIST *listaddr); void gpgsm_release_certlist (CERTLIST list); -int gpgsm_find_cert (const char *name, KsbaCert *r_cert); +int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert); /*-- keylist.c --*/ void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode); @@ -233,7 +233,7 @@ int gpgsm_delete (CTRL ctrl, STRLIST names); int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp); /*-- sign.c --*/ -int gpgsm_get_default_cert (KsbaCert *r_cert); +int gpgsm_get_default_cert (ksba_cert_t *r_cert); int gpgsm_sign (CTRL ctrl, CERTLIST signerlist, int data_fd, int detached, FILE *out_fp); @@ -253,19 +253,19 @@ int gpgsm_agent_pksign (const char *keygrip, int digestalgo, char **r_buf, size_t *r_buflen); int gpgsm_agent_pkdecrypt (const char *keygrip, - KsbaConstSexp ciphertext, + ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen); -int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey); -int gpgsm_agent_istrusted (KsbaCert cert); +int gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); +int gpgsm_agent_istrusted (ksba_cert_t cert); int gpgsm_agent_havekey (const char *hexkeygrip); -int gpgsm_agent_marktrusted (KsbaCert cert); +int gpgsm_agent_marktrusted (ksba_cert_t cert); int gpgsm_agent_learn (void); int gpgsm_agent_passwd (const char *hexkeygrip); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp); int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, - void (*cb)(void*, KsbaCert), void *cb_value); + void (*cb)(void*, ksba_cert_t), void *cb_value); int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, int argc, char **argv); diff --git a/sm/import.c b/sm/import.c index 758cd3208..2bc6e694f 100644 --- a/sm/import.c +++ b/sm/import.c @@ -44,7 +44,7 @@ struct stats_s { static void -print_imported_status (CTRL ctrl, KsbaCert cert) +print_imported_status (CTRL ctrl, ksba_cert_t cert) { char *fpr; @@ -62,7 +62,7 @@ print_imported_status (CTRL ctrl, KsbaCert cert) 4 := "Error storing certificate". */ static void -print_import_problem (CTRL ctrl, KsbaCert cert, int reason) +print_import_problem (CTRL ctrl, ksba_cert_t cert, int reason) { char *fpr = NULL; char buf[25]; @@ -117,7 +117,7 @@ print_imported_summary (CTRL ctrl, struct stats_s *stats) static void -check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth) +check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) { int rc; @@ -137,7 +137,7 @@ check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth) if (!keydb_store_cert (cert, 0, &existed)) { - KsbaCert next = NULL; + ksba_cert_t next = NULL; if (!existed) { @@ -194,11 +194,11 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) { int rc; Base64Context b64reader = NULL; - KsbaReader reader; - KsbaCert cert = NULL; - KsbaCMS cms = NULL; + ksba_reader_t reader; + ksba_cert_t cert = NULL; + ksba_cms_t cms = NULL; FILE *fp = NULL; - KsbaContentType ct; + ksba_content_type_t ct; fp = fdopen ( dup (in_fd), "rb"); if (!fp) @@ -218,7 +218,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) ct = ksba_cms_identify (reader); if (ct == KSBA_CT_SIGNED_DATA) { /* This is probably a signed-only message - import the certs */ - KsbaStopReason stopreason; + ksba_stop_reason_t stopreason; int i; rc = ksba_cms_new (&cms); diff --git a/sm/keydb.c b/sm/keydb.c index fe6556549..62e3ab2f3 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -557,7 +557,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) key used to locate the keyblock or flag bit 1 set for the user ID node. */ int -keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) +keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert) { int rc = 0; @@ -584,7 +584,7 @@ keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) * Insert a new Certificate into one of the resources. */ int -keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) +keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert) { int rc = -1; int idx; @@ -627,7 +627,7 @@ keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) /* update the current keyblock with KB */ int -keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert) +keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert) { int rc = 0; char digest[20]; @@ -881,7 +881,7 @@ keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer) int keydb_search_issuer_sn (KEYDB_HANDLE hd, - const char *issuer, KsbaConstSexp serial) + const char *issuer, ksba_const_sexp_t serial) { KEYDB_SEARCH_DESC desc; int rc; @@ -1219,7 +1219,7 @@ keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc) If EXISTED is not NULL it will be set to true if the certificate was already in the DB. */ int -keydb_store_cert (KsbaCert cert, int ephemeral, int *existed) +keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed) { KEYDB_HANDLE kh; int rc; diff --git a/sm/keydb.h b/sm/keydb.h index ad7eaf51d..0133d0ccd 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -41,9 +41,9 @@ int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb); int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb); #endif -int keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert); -int keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert); -int keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert); +int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert); +int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert); +int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert); int keydb_delete (KEYDB_HANDLE hd); @@ -63,7 +63,7 @@ int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer); int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc); -int keydb_store_cert (KsbaCert cert, int ephemeral, int *existed); +int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed); #endif /*GNUPG_KEYDB_H*/ diff --git a/sm/keylist.c b/sm/keylist.c index 7b7402fab..007400729 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -45,7 +45,7 @@ struct list_external_parm_s { static void -print_key_data (KsbaCert cert, FILE *fp) +print_key_data (ksba_cert_t cert, FILE *fp) { #if 0 int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; @@ -62,9 +62,9 @@ print_key_data (KsbaCert cert, FILE *fp) } static void -print_capabilities (KsbaCert cert, FILE *fp) +print_capabilities (ksba_cert_t cert, FILE *fp) { - KsbaError err; + gpg_error_t err; unsigned int use; err = ksba_cert_get_key_usage (cert, &use); @@ -145,11 +145,11 @@ email_kludge (const char *name) /* List one certificate in colon mode */ static void -list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) +list_cert_colon (ksba_cert_t cert, FILE *fp, int have_secret) { int idx, trustletter = 0; char *p; - KsbaSexp sexp; + ksba_sexp_t sexp; char *fpr; ksba_isotime_t t; @@ -221,7 +221,7 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) xfree (fpr); fpr = NULL; /* print chaining ID (field 13)*/ { - KsbaCert next; + ksba_cert_t next; if (!gpgsm_walk_cert_chain (cert, &next)) { @@ -276,10 +276,10 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) /* List one certificate in standard mode */ static void -list_cert_std (KsbaCert cert, FILE *fp, int have_secret) +list_cert_std (ksba_cert_t cert, FILE *fp, int have_secret) { - KsbaError kerr; - KsbaSexp sexp; + gpg_error_t kerr; + ksba_sexp_t sexp; char *dn; ksba_isotime_t t; int idx; @@ -397,9 +397,9 @@ list_cert_std (KsbaCert cert, FILE *fp, int have_secret) /* Same as standard mode mode list all certifying certts too */ static void -list_cert_chain (KsbaCert cert, FILE *fp) +list_cert_chain (ksba_cert_t cert, FILE *fp) { - KsbaCert next = NULL; + ksba_cert_t next = NULL; list_cert_std (cert, fp, 0); ksba_cert_ref (cert); @@ -425,7 +425,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) KEYDB_SEARCH_DESC *desc = NULL; STRLIST sl; int ndesc; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; int rc=0; const char *lastresname, *resname; int have_secret; @@ -548,7 +548,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) static void -list_external_cb (void *cb_value, KsbaCert cert) +list_external_cb (void *cb_value, ksba_cert_t cert) { struct list_external_parm_s *parm = cb_value; diff --git a/sm/sign.c b/sm/sign.c index 38d8ca9ed..5afbc6cdd 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -61,9 +61,9 @@ hash_data (int fd, gcry_md_hd_t md) } static int -hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer) +hash_and_copy_data (int fd, gcry_md_hd_t md, ksba_writer_t writer) { - KsbaError err; + gpg_error_t err; FILE *fp; char buffer[4096]; int nread; @@ -126,10 +126,10 @@ hash_and_copy_data (int fd, gcry_md_hd_t md, KsbaWriter writer) /* Get the default certificate which is defined as the first one our keyDB returns and has a secret key available. */ int -gpgsm_get_default_cert (KsbaCert *r_cert) +gpgsm_get_default_cert (ksba_cert_t *r_cert) { KEYDB_HANDLE hd; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; int rc; char *p; @@ -179,11 +179,11 @@ gpgsm_get_default_cert (KsbaCert *r_cert) } -static KsbaCert +static ksba_cert_t get_default_signer (void) { KEYDB_SEARCH_DESC desc; - KsbaCert cert = NULL; + ksba_cert_t cert = NULL; KEYDB_HANDLE kh = NULL; int rc; @@ -233,11 +233,11 @@ get_default_signer (void) other certificate up in the chain to the Root-CA to the CMS object. */ static int -add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert) +add_certificate_list (CTRL ctrl, ksba_cms_t cms, ksba_cert_t cert) { - KsbaError err; + gpg_error_t err; int rc = 0; - KsbaCert next = NULL; + ksba_cert_t next = NULL; int n; int not_root = 0; @@ -296,11 +296,11 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, int data_fd, int detached, FILE *out_fp) { int i, rc; - KsbaError err; + gpg_error_t err; Base64Context b64writer = NULL; - KsbaWriter writer; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; + ksba_writer_t writer; + ksba_cms_t cms = NULL; + ksba_stop_reason_t stopreason; KEYDB_HANDLE kh = NULL; gcry_md_hd_t data_md = NULL; int signer; @@ -357,7 +357,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, /* If no list of signers is given, use a default one. */ if (!signerlist) { - KsbaCert cert = get_default_signer (); + ksba_cert_t cert = get_default_signer (); if (!cert) { log_error ("no default signer found\n"); diff --git a/sm/verify.c b/sm/verify.c index c58dd895e..a10aff92c 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -86,12 +86,12 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) int i, rc; Base64Context b64reader = NULL; Base64Context b64writer = NULL; - KsbaError err; - KsbaReader reader; - KsbaWriter writer = NULL; - KsbaCMS cms = NULL; - KsbaStopReason stopreason; - KsbaCert cert; + gpg_error_t err; + ksba_reader_t reader; + ksba_writer_t writer = NULL; + ksba_cms_t cms = NULL; + ksba_stop_reason_t stopreason; + ksba_cert_t cert; KEYDB_HANDLE kh; gcry_md_hd_t data_md = NULL; int signer; @@ -242,9 +242,9 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) for (signer=0; ; signer++) { char *issuer = NULL; - KsbaSexp sigval = NULL; + ksba_sexp_t sigval = NULL; ksba_isotime_t sigtime, keyexptime; - KsbaSexp serial; + ksba_sexp_t serial; char *msgdigest = NULL; size_t msgdigestlen; char *ctattr; -- cgit v1.2.3 From a1bd2fa625962a2a8e2864d6f4704b0a65ca7a7f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 12:28:54 +0000 Subject: (CFLAGS): Add --Wformat-noliteral in gcc mode. --- ChangeLog | 4 ++++ configure.ac | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2a08051f0..1f99181f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2003-12-17 Werner Koch <wk@gnupg.org> + + * configure.ac (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 diff --git a/configure.ac b/configure.ac index a0cf391a4..72df23915 100644 --- a/configure.ac +++ b/configure.ac @@ -894,6 +894,7 @@ esac if test "$GCC" = yes; then if test "$USE_MAINTAINER_MODE" = "yes"; then CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" + CFLAGS="$CFLAGS -Wformat-nonliteral" else CFLAGS="$CFLAGS -Wall" fi -- cgit v1.2.3 From aac9cea6daaabe8179a1efb8c7fb1d76f73273c9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 13:03:59 +0000 Subject: Requires now libassuan 0.6.2. (CFLAGS): Add --Wformat-noliteral in gcc mode. --- ChangeLog | 4 +++- configure.ac | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1f99181f0..8a9e054f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ 2003-12-17 Werner Koch <wk@gnupg.org> - * configure.ac (CFLAGS): Add --Wformat-noliteral in gcc mode. + * configure.ac: Requires now libassuan 0.6.2. + (CFLAGS): Add --Wformat-noliteral in gcc mode. + 2003-12-16 Werner Koch <wk@gnupg.org> diff --git a/configure.ac b/configure.ac index 72df23915..06fad2864 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ AC_INIT(gnupg, 1.9.3-cvs, gnupg-devel@gnupg.org) development_version=yes NEED_GPG_ERROR_VERSION=0.6 NEED_LIBGCRYPT_VERSION=1.1.90 -NEED_LIBASSUAN_VERSION=0.6.1 +NEED_LIBASSUAN_VERSION=0.6.2 NEED_KSBA_VERSION=0.9.0 NEED_OPENSC_VERSION=0.8.0 -- cgit v1.2.3 From 711c4853d63a9eb4bacac3f540dfcbb71fba2a51 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Dec 2003 17:12:14 +0000 Subject: * server.c (gpgsm_server): Add arg DEFAULT_RECPLIST. (cmd_encrypt): Add all enrypt-to marked certs to the list. * encrypt.c (gpgsm_encrypt): Check that real recipients are available. * gpgsm.c (main): Make the --encrypt-to and --no-encrypt-to options work. Pass the list of recients to gpgsm_server. * gpgsm.h (certlist_s): Add field IS_ENCRYPT_TO. (opt): Add NO_ENCRYPT_TO. * certlist.c (gpgsm_add_to_certlist): New arg IS_ENCRYPT_TO. Changed all callers and ignore duplicate entries. (is_cert_in_certlist): New. (gpgsm_add_cert_to_certlist): New. --- NEWS | 9 ++++-- sm/ChangeLog | 13 +++++++++ sm/certlist.c | 90 ++++++++++++++++++++++++++++++++++++++++++++--------------- sm/encrypt.c | 12 ++++++-- sm/gpgsm.c | 68 ++++++++++++++++++++++++++++---------------- sm/gpgsm.h | 56 ++++++++++++++++++++++--------------- sm/server.c | 42 ++++++++++++++++++++-------- 7 files changed, 203 insertions(+), 87 deletions(-) diff --git a/NEWS b/NEWS index ce966b751..8a381ead2 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,8 @@ Noteworthy changes in version 1.9.3 (unreleased) ------------------------------------------------ - * New options --{enable,disable}-ocsp to validate keys using OCSP - This requires a not yet released DirMngr 0.5.1. Default is + * New gpgsm options --{enable,disable}-ocsp to validate keys using + OCSP. This requires a not yet released DirMngr 0.5.1. Default is disabled. * The --log-file option may now be used to print logs to a socket. @@ -10,6 +10,11 @@ Noteworthy changes in version 1.9.3 (unreleased) 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) ------------------------------------------------ diff --git a/sm/ChangeLog b/sm/ChangeLog index 62505fee9..e3329b669 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,18 @@ 2003-12-17 Werner Koch <wk@gnupg.org> + * server.c (gpgsm_server): Add arg DEFAULT_RECPLIST. + (cmd_encrypt): Add all enrypt-to marked certs to the list. + * encrypt.c (gpgsm_encrypt): Check that real recipients are + available. + * gpgsm.c (main): Make the --encrypt-to and --no-encrypt-to + options work. Pass the list of recients to gpgsm_server. + * gpgsm.h (certlist_s): Add field IS_ENCRYPT_TO. + (opt): Add NO_ENCRYPT_TO. + * certlist.c (gpgsm_add_to_certlist): New arg IS_ENCRYPT_TO. + Changed all callers and ignore duplicate entries. + (is_cert_in_certlist): New. + (gpgsm_add_cert_to_certlist): New. + * certdump.c (gpgsm_print_serial): Cleaned up cast use in strtoul. (gpgsm_dump_serial): Ditto. diff --git a/sm/certlist.c b/sm/certlist.c index fe2830909..b61f0f663 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -131,14 +131,54 @@ same_subject_issuer (const char *subject, const char *issuer, ksba_cert_t cert) return tmp; } +/* Return true if CERT is already contained in CERTLIST. */ +static int +is_cert_in_certlist (ksba_cert_t cert, certlist_t certlist) +{ + const unsigned char *img_a, *img_b; + size_t len_a, len_b; + + img_a = ksba_cert_get_image (cert, &len_a); + if (img_a) + { + for ( ; certlist; certlist = certlist->next) + { + img_b = ksba_cert_get_image (certlist->cert, &len_b); + if (img_b && len_a == len_b && !memcmp (img_a, img_b, len_a)) + return 1; /* Already contained. */ + } + } + return 0; +} +/* Add CERT to the list of certificates at CERTADDR but avoid + duplicates. */ +int +gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, + certlist_t *listaddr, int is_encrypt_to) +{ + if (!is_cert_in_certlist (cert, *listaddr)) + { + certlist_t cl = xtrycalloc (1, sizeof *cl); + if (!cl) + return OUT_OF_CORE (errno); + cl->cert = cert; + ksba_cert_ref (cert); + cl->next = *listaddr; + cl->is_encrypt_to = is_encrypt_to; + *listaddr = cl; + } + return 0; +} + /* Add a certificate to a list of certificate and make sure that it is a valid certificate. With SECRET set to true a secret key must be - available for the certificate. */ + available for the certificate. IS_ENCRYPT_TO sets the corresponding + flag in the new create LISTADDR item. */ int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, - CERTLIST *listaddr) + CERTLIST *listaddr, int is_encrypt_to) { int rc; KEYDB_SEARCH_DESC desc; @@ -224,31 +264,35 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, xfree (subject); xfree (issuer); - if (!rc && secret) + if (!rc && !is_cert_in_certlist (cert, *listaddr)) { - char *p; - - rc = gpg_error (GPG_ERR_NO_SECKEY); - p = gpgsm_get_keygrip_hexstring (cert); - if (p) + if (!rc && secret) { - if (!gpgsm_agent_havekey (p)) - rc = 0; - xfree (p); + char *p; + + rc = gpg_error (GPG_ERR_NO_SECKEY); + p = gpgsm_get_keygrip_hexstring (cert); + if (p) + { + if (!gpgsm_agent_havekey (p)) + rc = 0; + xfree (p); + } } - } - if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL); - if (!rc) - { - CERTLIST cl = xtrycalloc (1, sizeof *cl); - if (!cl) - rc = OUT_OF_CORE (errno); - else + if (!rc) + rc = gpgsm_validate_chain (ctrl, cert, NULL); + if (!rc) { - cl->cert = cert; cert = NULL; - cl->next = *listaddr; - *listaddr = cl; + CERTLIST cl = xtrycalloc (1, sizeof *cl); + if (!cl) + rc = OUT_OF_CORE (errno); + else + { + cl->cert = cert; cert = NULL; + cl->next = *listaddr; + cl->is_encrypt_to = is_encrypt_to; + *listaddr = cl; + } } } } diff --git a/sm/encrypt.c b/sm/encrypt.c index f31391e7c..8f2c26b45 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -306,7 +306,13 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) memset (&encparm, 0, sizeof encparm); - if (!recplist) + /* Check that the certificate list is not empty and that at least + one certificate is not flagged as encrypt_to; i.e. is a real + recipient. */ + for (cl = recplist; cl; cl = cl->next) + if (!cl->is_encrypt_to) + break; + if (!cl) { log_error(_("no valid recipients given\n")); gpgsm_status (ctrl, STATUS_NO_RECP, "0"); @@ -412,7 +418,7 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) goto leave; } - /* gather certificates of recipients, encrypt the session key for + /* Gather certificates of recipients, encrypt the session key for each and store them in the CMS object */ for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next) { @@ -447,7 +453,7 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) } } - /* main control loop for encryption */ + /* Main control loop for encryption. */ recpno = 0; do { diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 497df048d..c8d76afa9 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -277,10 +277,10 @@ static ARGPARSE_OPTS opts[] = { { oDefRecipientSelf, "default-recipient-self" ,0, N_("use the default key as default recipient")}, { oNoDefRecipient, "no-default-recipient", 0, "@" }, +#endif { oEncryptTo, "encrypt-to", 2, "@" }, { oNoEncryptTo, "no-encrypt-to", 0, "@" }, -#endif { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, #if 0 @@ -585,6 +585,31 @@ set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd) } +/* Helper to add recipients to a list. */ +static void +do_add_recipient (ctrl_t ctrl, const char *name, + certlist_t *recplist, int is_encrypt_to) +{ + int rc = gpgsm_add_to_certlist (ctrl, name, 0, recplist, is_encrypt_to); + if (rc) + { + log_error (_("can't encrypt to `%s': %s\n"), name, gpg_strerror (rc)); + gpgsm_status2 (ctrl, STATUS_INV_RECP, + gpg_err_code (rc) == -1? "1": + gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1": + gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2": + gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3": + gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4": + gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5": + gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6": + gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7": + gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8": + "0", + name, NULL); + } +} + + int main ( int argc, char **argv) { @@ -953,8 +978,8 @@ main ( int argc, char **argv) case oSkipVerify: opt.skip_verify=1; break; - case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break; - case oEncryptTo: /* store the recipient in the second list */ + case oNoEncryptTo: opt.no_encrypt_to = 1; break; + case oEncryptTo: /* Store the recipient in the second list */ sl = add_to_strlist (&remusr, pargs.r.ret_str); sl->flags = 1; break; @@ -1107,7 +1132,7 @@ main ( int argc, char **argv) for (sl = locusr; sl; sl = sl->next) { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist); + int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0); if (rc) { log_error (_("can't sign using `%s': %s\n"), @@ -1127,27 +1152,22 @@ main ( int argc, char **argv) sl->d, NULL); } } + + /* Build the recipient list. We first add the regular ones and then + the encrypt-to ones because the underlying function will silenty + ignore duplicates and we can't allow to keep a duplicate which is + flagged as encrypt-to as the actually encrypt function would then + complain about no (regular) recipients. */ for (sl = remusr; sl; sl = sl->next) + if (!(sl->flags & 1)) + do_add_recipient (&ctrl, sl->d, &recplist, 0); + if (!opt.no_encrypt_to) { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist); - if (rc) - { - log_error (_("can't encrypt to `%s': %s\n"), - sl->d, gpg_strerror (rc)); - gpgsm_status2 (&ctrl, STATUS_INV_RECP, - gpg_err_code (rc) == -1? "1": - gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1": - gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2": - gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3": - gpg_err_code (rc) == GPG_ERR_CERT_REVOKED? "4": - gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED? "5": - gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN? "6": - gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD? "7": - gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8": - "0", - sl->d, NULL); - } - } + for (sl = remusr; sl; sl = sl->next) + if ((sl->flags & 1)) + do_add_recipient (&ctrl, sl->d, &recplist, 1); + } + if (log_get_errorcount(0)) gpgsm_exit(1); /* must stop for invalid recipients */ @@ -1165,7 +1185,7 @@ main ( int argc, char **argv) sleep (debug_wait); log_debug ("... okay\n"); } - gpgsm_server (); + gpgsm_server (recplist); break; case aCallDirmngr: diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 8c71c3479..e8cdd93df 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -72,6 +72,8 @@ struct { char *def_recipient; /* userID of the default recipient */ int def_recipient_self; /* The default recipient is the default key */ + int no_encrypt_to; /* Ignore all as encrypt to marked recipients. */ + char *local_user; /* NULL or argument to -u */ int always_trust; /* Trust the given keys even if there is no @@ -135,6 +137,7 @@ struct server_control_s { int use_ocsp; /* Set to true if OCSP should be used. */ }; typedef struct server_control_s *CTRL; +typedef struct server_control_s *ctrl_t; /* data structure used in base64.c */ typedef struct base64_context_s *Base64Context; @@ -143,22 +146,26 @@ typedef struct base64_context_s *Base64Context; struct certlist_s { struct certlist_s *next; ksba_cert_t cert; + int is_encrypt_to; /* True if the certificate has been set through + the --encrypto-to option. */ }; typedef struct certlist_s *CERTLIST; +typedef struct certlist_s *certlist_t; /*-- gpgsm.c --*/ void gpgsm_exit (int rc); void gpgsm_init_default_ctrl (struct server_control_s *ctrl); /*-- server.c --*/ -void gpgsm_server (void); -void gpgsm_status (CTRL ctrl, int no, const char *text); -void gpgsm_status2 (CTRL ctrl, int no, ...); -void gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text, +void gpgsm_server (certlist_t default_recplist); +void gpgsm_status (ctrl_t ctrl, int no, const char *text); +void gpgsm_status2 (ctrl_t ctrl, int no, ...); +void gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text, gpg_err_code_t ec); /*-- fingerprint --*/ -char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len); +char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, + char *array, int *r_len); char *gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo); char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo); unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert); @@ -169,10 +176,10 @@ char *gpgsm_get_certid (ksba_cert_t cert); /*-- base64.c --*/ int gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, ksba_reader_t *r_reader); + ctrl_t ctrl, FILE *fp, ksba_reader_t *r_reader); void gpgsm_destroy_reader (Base64Context ctx); int gpgsm_create_writer (Base64Context *ctx, - CTRL ctrl, FILE *fp, ksba_writer_t *r_writer); + ctrl_t ctrl, FILE *fp, ksba_writer_t *r_writer); int gpgsm_finish_writer (Base64Context ctx); void gpgsm_destroy_writer (Base64Context ctx); @@ -201,7 +208,8 @@ int gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, /*-- certchain.c --*/ int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next); int gpgsm_is_root_cert (ksba_cert_t cert); -int gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime); +int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, + ksba_isotime_t r_exptime); int gpgsm_basic_cert_check (ksba_cert_t cert); /*-- certlist.c --*/ @@ -210,41 +218,43 @@ int gpgsm_cert_use_encrypt_p (ksba_cert_t cert); int gpgsm_cert_use_verify_p (ksba_cert_t cert); int gpgsm_cert_use_decrypt_p (ksba_cert_t cert); int gpgsm_cert_use_cert_p (ksba_cert_t cert); -int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, - CERTLIST *listaddr); -void gpgsm_release_certlist (CERTLIST list); +int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, + certlist_t *listaddr, int is_encrypt_to); +int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, + certlist_t *listaddr, int is_encrypt_to); +void gpgsm_release_certlist (certlist_t list); int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert); /*-- keylist.c --*/ -void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode); +void gpgsm_list_keys (ctrl_t ctrl, STRLIST names, FILE *fp, unsigned int mode); /*-- import.c --*/ -int gpgsm_import (CTRL ctrl, int in_fd); -int gpgsm_import_files (CTRL ctrl, int nfiles, char **files, +int gpgsm_import (ctrl_t ctrl, int in_fd); +int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files, int (*of)(const char *fname)); /*-- export.c --*/ -void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp); +void gpgsm_export (ctrl_t ctrl, STRLIST names, FILE *fp); /*-- delete.c --*/ -int gpgsm_delete (CTRL ctrl, STRLIST names); +int gpgsm_delete (ctrl_t ctrl, STRLIST names); /*-- verify.c --*/ -int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp); +int gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp); /*-- sign.c --*/ int gpgsm_get_default_cert (ksba_cert_t *r_cert); -int gpgsm_sign (CTRL ctrl, CERTLIST signerlist, +int gpgsm_sign (ctrl_t ctrl, CERTLIST signerlist, int data_fd, int detached, FILE *out_fp); /*-- encrypt.c --*/ -int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp); +int gpgsm_encrypt (ctrl_t ctrl, CERTLIST recplist, int in_fd, FILE *out_fp); /*-- decrypt.c --*/ -int gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp); +int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- certreqgen.c --*/ -int gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp); +int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- call-agent.c --*/ int gpgsm_agent_pksign (const char *keygrip, @@ -264,9 +274,9 @@ int gpgsm_agent_passwd (const char *hexkeygrip); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp); -int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, +int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names, void (*cb)(void*, ksba_cert_t), void *cb_value); -int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, +int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command, int argc, char **argv); diff --git a/sm/server.c b/sm/server.c index 20ba51301..549c35350 100644 --- a/sm/server.c +++ b/sm/server.c @@ -39,12 +39,13 @@ static FILE *statusfp; /* Data used to assuciate an Assuan context with local server data */ struct server_local_s { - ASSUAN_CONTEXT assuan_ctx; + assuan_context_t assuan_ctx; int message_fd; int list_internal; int list_external; - CERTLIST recplist; - CERTLIST signerlist; + certlist_t recplist; + certlist_t signerlist; + certlist_t default_recplist; /* As set by main() - don't release. */ }; @@ -233,7 +234,7 @@ output_notify (ASSUAN_CONTEXT ctx, const char *line) way of specification [we will support this]. 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 + 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 RECIPIENT commands are cumulative until a RESET or an successful ENCRYPT command. */ @@ -243,7 +244,7 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line) CTRL ctrl = assuan_get_pointer (ctx); int rc; - rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist); + rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist, 0); if (rc) { gpg_err_code_t r = gpg_err_code (rc); @@ -286,7 +287,8 @@ cmd_signer (ASSUAN_CONTEXT ctx, char *line) CTRL ctrl = assuan_get_pointer (ctx); int rc; - rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist); + rc = gpgsm_add_to_certlist (ctrl, line, 1, + &ctrl->server_local->signerlist, 0); if (rc) { gpg_err_code_t r = gpg_err_code (rc); @@ -325,6 +327,7 @@ static int cmd_encrypt (ASSUAN_CONTEXT ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); + certlist_t cl; int inp_fd, out_fd; FILE *out_fp; int rc; @@ -339,14 +342,26 @@ cmd_encrypt (ASSUAN_CONTEXT ctx, char *line) out_fp = fdopen ( dup(out_fd), "w"); if (!out_fp) return set_error (General_Error, "fdopen() failed"); - rc = gpgsm_encrypt (assuan_get_pointer (ctx), - ctrl->server_local->recplist, - inp_fd, out_fp); + + /* Now add all encrypt-to marked recipients from the default + list. */ + rc = 0; + if (!opt.no_encrypt_to) + { + for (cl=ctrl->server_local->recplist; !rc && cl; cl = cl->next) + if (cl->is_encrypt_to) + rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert, + &ctrl->server_local->recplist, 1); + } + if (!rc) + rc = gpgsm_encrypt (assuan_get_pointer (ctx), + ctrl->server_local->recplist, + inp_fd, out_fp); fclose (out_fp); gpgsm_release_certlist (ctrl->server_local->recplist); ctrl->server_local->recplist = NULL; - /* close and reset the fd */ + /* Close and reset the fd */ close_message_fd (ctrl); assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); @@ -755,9 +770,11 @@ register_commands (ASSUAN_CONTEXT ctx) return 0; } -/* Startup the server */ +/* Startup the server. DEFAULT_RECPLIST is the list of recipients as + set from the command line or config file. We only require those + marked as encrypt-to. */ void -gpgsm_server (void) +gpgsm_server (certlist_t default_recplist) { int rc; int filedes[2]; @@ -799,6 +816,7 @@ gpgsm_server (void) ctrl.server_local->message_fd = -1; ctrl.server_local->list_internal = 1; ctrl.server_local->list_external = 0; + ctrl.server_local->default_recplist = default_recplist; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); -- cgit v1.2.3 From 02f20a7506263c95767f15ea69f81ede70c64627 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Dec 2003 10:23:16 +0000 Subject: Enable the tests directory. --- ChangeLog | 9 +++++++++ Makefile.am | 6 +----- NEWS | 4 ++-- TODO | 18 ++++++++++++------ configure.ac | 6 +++--- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8a9e054f3..2d3eb566e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2003-12-23 Werner Koch <wk@gnupg.org> + + * configure.ac, Makefile.am: Enable the tests directory. + +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. diff --git a/Makefile.am b/Makefile.am index dd75d14b5..732d9e417 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,11 +46,7 @@ scd = endif SUBDIRS = m4 intl jnlib common kbx \ - ${gpg} ${sm} ${agent} ${scd} po doc - -#tests - - + ${gpg} ${sm} ${agent} ${scd} po doc tests dist-hook: @set -e; \ diff --git a/NEWS b/NEWS index 8a381ead2..ea7960cc2 100644 --- a/NEWS +++ b/NEWS @@ -2,8 +2,8 @@ Noteworthy changes in version 1.9.3 (unreleased) ------------------------------------------------ * New gpgsm options --{enable,disable}-ocsp to validate keys using - OCSP. This requires a not yet released DirMngr 0.5.1. Default is - disabled. + 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 diff --git a/TODO b/TODO index eb8e2da66..f1355c03c 100644 --- a/TODO +++ b/TODO @@ -33,7 +33,7 @@ might want to have an agent context for each service request * sm/gpgsm.c ** Support --output ** mark all unimplemented commands and options. -** Print a hint when of MD2 is the cause for a problem. +** Print a hint when MD2 is the cause for a problem. * sm/keydb.c ** Check file permissions @@ -71,10 +71,16 @@ might want to have an agent context for each service request ** Enhance with card compatibility check * scd/app-openpgp - Do a pre-check to make sure that the minimum length condition of the - PINs are satisied - this avoid useless retry counter decrements in - case the PIN dialog is accidently hit. - Must check that the fingerprint used is not the one of the authentication key. Old GnuPG versions seem to encode the wrong - keyID. \ No newline at end of file + keyID. + +* Store the revocation status directly in the Keybox + +* 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. + + diff --git a/configure.ac b/configure.ac index 06fad2864..fd0c99570 100644 --- a/configure.ac +++ b/configure.ac @@ -30,9 +30,9 @@ AC_INIT(gnupg, 1.9.3-cvs, gnupg-devel@gnupg.org) # sufficient. development_version=yes NEED_GPG_ERROR_VERSION=0.6 -NEED_LIBGCRYPT_VERSION=1.1.90 +NEED_LIBGCRYPT_VERSION=1.1.91 NEED_LIBASSUAN_VERSION=0.6.2 -NEED_KSBA_VERSION=0.9.0 +NEED_KSBA_VERSION=0.9.1 NEED_OPENSC_VERSION=0.8.0 @@ -1074,9 +1074,9 @@ sm/Makefile agent/Makefile scd/Makefile doc/Makefile +tests/Makefile ]) AC_OUTPUT -#tests/Makefile echo " -- cgit v1.2.3 From 6103066b175874cdb9c8425b29bf1520f8742b36 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Dec 2003 10:24:49 +0000 Subject: (map_assuan_err): Prepared for a new error code. --- common/ChangeLog | 4 ++++ common/maperror.c | 15 ++++----------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index e69df733f..1b454fa13 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/maperror.c b/common/maperror.c index 361166388..b04ec0bb3 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -72,6 +72,10 @@ map_assuan_err (int err) case ASSUAN_Not_Confirmed: ec = GPG_ERR_NOT_CONFIRMED; break; case ASSUAN_Invalid_Id: ec = GPG_ERR_INV_ID; break; +#if 0 /* FIXME: Enable this after releasing libgpg error 0.7 */ + case ASSUAN_Locale_Problem: ec = GPG_ERR_LOCALE_PROBLEM; break; +#endif + default: ec = err < 100? GPG_ERR_ASSUAN_SERVER_FAULT : GPG_ERR_ASSUAN; break; @@ -101,14 +105,3 @@ map_to_assuan_status (int rc) return gpg_err_make (es, ec); } - - - - - - - - - - - -- cgit v1.2.3 From 28db0fabb4edf65ad1c5bec061c19c9922be9b23 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Dec 2003 10:25:24 +0000 Subject: * apdu.c (apdu_send_le): Send a get_response with the indicated length and not the 64 bytes we used for testing. * app-openpgp.c (verify_chv2, verify_chv3, do_sign): Check the minimum length of the passphrase, so that we don't need to decrement the retry counter. --- scd/ChangeLog | 9 +++++++++ scd/apdu.c | 2 +- scd/app-openpgp.c | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 60b5f8eb9..0862d356b 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2003-12-19 Werner Koch <wk@gnupg.org> + + * apdu.c (apdu_send_le): Send a get_response with the indicated + length and not the 64 bytes we used for testing. + + * app-openpgp.c (verify_chv2, verify_chv3, do_sign): Check the + minimum length of the passphrase, so that we don't need to + decrement the retry counter. + 2003-12-17 Werner Koch <wk@gnupg.org> * card-p15.c (p15_enum_keypairs): Replaced KRC by RC. diff --git a/scd/apdu.c b/scd/apdu.c index 27304c8b5..02038b65c 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1207,7 +1207,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, apdu[apdulen++] = 0xC0; apdu[apdulen++] = 0; apdu[apdulen++] = 0; - apdu[apdulen++] = 64; /* that is 256 bytes for Le */ + apdu[apdulen++] = len; memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); rc = send_apdu (slot, apdu, apdulen, result, &resultlen); if (rc || resultlen < 2) diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 6b4a2f7ef..8f9a303fe 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -534,6 +534,13 @@ verify_chv2 (APP app, return rc; } + if (strlen (pinvalue) < 6) + { + log_error ("prassphrase (CHV2) is too short; minimum length is 6\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); if (rc) { @@ -586,6 +593,13 @@ verify_chv3 (APP app, return rc; } + if (strlen (pinvalue) < 6) + { + log_error ("prassphrase (CHV3) is too short; minimum length is 6\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); xfree (pinvalue); if (rc) @@ -1041,6 +1055,13 @@ do_sign (APP app, const char *keyidstr, int hashalgo, return rc; } + if (strlen (pinvalue) < 6) + { + log_error ("prassphrase (CHV1) is too short; minimum length is 6\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); if (rc) { -- cgit v1.2.3 From e11529f290556057446283850d5f60a8e353ce6e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Dec 2003 11:05:00 +0000 Subject: * Makefile.am: New. * watchgnupg.c: New. --- tools/ChangeLog | 148 ++---------------------------------------------------- tools/Makefile.am | 23 ++------- 2 files changed, 9 insertions(+), 162 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index d34913df0..af8225bc1 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,148 +1,10 @@ -2003-12-06 David Shaw <dshaw@jabberwocky.com> +2003-12-23 Werner Koch <wk@gnupg.org> - * gpgsplit.c (write_part): Split off decompression code. - (handle_zlib): Move it here. - (handle_bzip2): Add this to handle BZIP2 compressed messages. + * Makefile.am: New. + * watchgnupg.c: New. -2003-10-25 Werner Koch <wk@gnupg.org> - * Makefile.am: Replaced INTLLIBS by LIBINTL. - -2003-08-24 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Use NETLIBS instead of EGDLIBS. - -2003-07-10 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Use W32LIBS where appropriate. - -2003-05-30 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Some cleanup, and use DLLIBS for -ldl. - -2003-05-24 David Shaw <dshaw@jabberwocky.com> - - * bftest.c, crlf.c, mk-tdata.c, mpicalc.c, shmtest.c: Edit all - preprocessor instructions to remove whitespace before the - '#'. This is not required by C89, but there are some compilers out - there that don't like it. - -2003-03-11 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Use @CAPLIBS@ to link in -lcap if we are using - capabilities. - -2003-02-22 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Distribute convert-from-106. - - * convert-from-106: Script to automate the 1.0.6->later - conversion. It marks all secret keys as ultimately trusted, adds - the signature caches, and checks the trustdb. Moved from the - scripts directory. - -2002-10-31 Stefan Bellon <sbellon@sbellon.de> - - * gpgsplit.c (write_part) [__riscos__]: Use riscos_load_module() - to load ZLib module. - -2002-10-23 Werner Koch <wk@gnupg.org> - - * gpgsplit.c: New options --secret-to-public and --no-split. - GNUified the indentation style. - -2002-09-25 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Link bftest with EGDLIBS (i.e. NETLIBS) as EGD uses - sockets. - -2002-05-07 Stefan Bellon <sbellon@sbellon.de> - - * gpgsplit.c (create_filename): Use EXTSEP_S instead of ".". - -2002-04-23 David Shaw <dshaw@jabberwocky.com> - - * Makefile.am: Do not list libraries in -lxxx format in a - dependency line. - -2002-01-02 Stefan Bellon <sbellon@sbellon.de> - - * gpgsplit.c [__riscos__]: Added RISC OS specific file name - code. - - * gpgsplit.c (write_part): Introduced two explicit casts. - -2001-12-21 David Shaw <dshaw@jabberwocky.com> - - * gpgsplit.c (pkttype_to_string): PKT_PHOTO_ID -> PKT_ATTRIBUTE - -2001-10-23 Werner Koch <wk@gnupg.org> - - * Makefile.am (gpgsplit_LDADD): Add ZLIBS. - -2001-09-18 Werner Koch <wk@gnupg.org> - - * gpgsplit.c: New option --uncompress. - (write_part): Handle old style uncompressing. - -2001-06-20 Werner Koch <wk@gnupg.org> - - * gpgsplit.c: New. - * Makefile.am (bin_PROGRAMS): Install gpgsplit. - -2001-03-27 Werner Koch <wk@gnupg.org> - - * mail-signed-keys: Add option --dry-run. - -2001-03-21 Werner Koch <wk@gnupg.org> - - * shmtest.c: Add sys/types.h - -Fri Sep 15 18:40:36 CEST 2000 Werner Koch <wk@openit.de> - - * ring-a-party: An array start at offset 1 no 0. Many thanks to Mike - for finding this bug. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> - - * ring-a-party: Flush the last key. - -Wed Jul 5 13:28:45 CEST 2000 Werner Koch <wk@> - - * mail-signed-keys: New. - -Tue May 23 09:19:00 CEST 2000 Werner Koch <wk@openit.de> - - * ring-a-party: New. - -Thu Jul 8 16:21:27 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * lspgpot: New - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * Makefile.am: Support for libtool. - -Tue Jun 8 13:36:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * mpicalc.c (main): hex digits may now be lowercase - (do_mulm): new. - -Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * mpicalc.c (main): Moved initialization out of definition. - -Mon May 18 15:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mk-tdata.c: New. - -Tue Apr 7 19:50:41 1998 Werner Koch (wk@isil.d.shuttle.de) - - * bftest.c: Now supports all availabe ciphers. - - - - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 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 @@ -151,5 +13,3 @@ Tue Apr 7 19:50:41 1998 Werner Koch (wk@isil.d.shuttle.de) 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. - - diff --git a/tools/Makefile.am b/tools/Makefile.am index e52d49d36..c22fb8f36 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,7 +1,8 @@ -# Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. -# +# Makefile.am - Tools directory +# 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 @@ -16,18 +17,4 @@ # 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 = lspgpot ring-a-party mail-signed-keys convert-from-106 -INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a - -bin_PROGRAMS = gpgsplit -noinst_PROGRAMS = mpicalc bftest clean-sat mk-tdata shmtest - -gpgsplit_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @ZLIBS@ -mpicalc_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @W32LIBS@ -bftest_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @W32LIBS@ @DLLIBS@ @NETLIBS@ -shmtest_LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ - -gpgsplit mpicalc bftest shmtest: $(needed_libs) +EXTRA_DIST = watchgnupg.c -- cgit v1.2.3 From c25ac44a7e2d9bb5702bc7445e4dcb7fd7360ef7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Dec 2003 11:05:19 +0000 Subject: * README-alpha: Removed. * configure.ac, Makefile.am: Add the tests and tools directories. --- ChangeLog | 6 ++++-- Makefile.am | 4 ++-- NEWS | 2 +- README | 22 ++++++++++++---------- README-alpha | 16 ---------------- configure.ac | 3 ++- 6 files changed, 21 insertions(+), 32 deletions(-) delete mode 100644 README-alpha diff --git a/ChangeLog b/ChangeLog index 2d3eb566e..0752eec64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 2003-12-23 Werner Koch <wk@gnupg.org> - * configure.ac, Makefile.am: Enable the tests directory. + 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> @@ -11,7 +14,6 @@ * configure.ac: Requires now libassuan 0.6.2. (CFLAGS): Add --Wformat-noliteral in gcc mode. - 2003-12-16 Werner Koch <wk@gnupg.org> diff --git a/Makefile.am b/Makefile.am index 732d9e417..8f7d1771c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,7 @@ ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = scripts/config.rpath autogen.sh README-alpha README.CVS +EXTRA_DIST = scripts/config.rpath autogen.sh README.CVS DISTCLEANFILES = g10defs.h if BUILD_GPG @@ -46,7 +46,7 @@ scd = endif SUBDIRS = m4 intl jnlib common kbx \ - ${gpg} ${sm} ${agent} ${scd} po doc tests + ${gpg} ${sm} ${agent} ${scd} tools po doc tests dist-hook: @set -e; \ diff --git a/NEWS b/NEWS index ea7960cc2..efa85b162 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.3 (unreleased) +Noteworthy changes in version 1.9.3 (2003-12-23) ------------------------------------------------ * New gpgsm options --{enable,disable}-ocsp to validate keys using diff --git a/README b/README index 60b613362..42099d6f6 100644 --- a/README +++ b/README @@ -1,12 +1,15 @@ -GnuPG 1.9 is a temporary protect to work on GnuPG extensions. It will -eventually lead to a GnuPG 2.0 release. +GnuPG 1.9 is a temporary project to work on GnuPG extensions; it is a +merke fo gnupg 1.3 and the old newpg package. It will eventually lead +to a GnuPG 2.0 release. 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 + You need the libgpg-error package. Libassuan, Libksba and Libgcrypt are also required to build it. @@ -24,14 +27,14 @@ gpgsm: --learn-card - Read tinformation about the private keys from the smartcard and + Read information about the private keys from the smartcard and import the certificates from there. --export - Export all certificates storein the Keybox or those specified on - the commandline. When using --armor a few informational lines are - prepended before each block. + 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: @@ -94,7 +97,7 @@ gpgsm: 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 envrionment varaibale DIRMNGR_INFO is not set or a running + the environment varaibale DIRMNGR_INFO is not set or a running dirmngr can't be connected. --no-secmem-warning @@ -148,12 +151,11 @@ gpg-agent: --pinentry-program <path_to_pinentry_program> Specify the PINentry program. The default value is - "../../pinentry/kpinentry/kpinentry" so you most likely want to - specify it. + "<prefix>/bin/pinentry" so you most likely want to specify it. --no-grab - Tel the pinentry not to grab keybourd and mouse. You most likely + 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. diff --git a/README-alpha b/README-alpha deleted file mode 100644 index b844eabce..000000000 --- a/README-alpha +++ /dev/null @@ -1,16 +0,0 @@ - ====== THIS IS WORK IN PROGESS ====== - - DO NOT USE IN A PRODUCTION ENVIRONMENT! - - THERE MIGHT BE SECURITY PROBLEMS! - -The source may change quite often and may have serious problems; it -may even not compile on some machines. - -It will probably needs GCC and GLIBC to build due to some debugging -code. Please don't complain if it does not work on other machines. -We will make it work again later. - -The specification for the OpenPGP smartcard application will be -released soon and we will try to make cards easily available. - diff --git a/configure.ac b/configure.ac index fd0c99570..1f3a6b0ff 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.3-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.3, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -1073,6 +1073,7 @@ g10/Makefile sm/Makefile agent/Makefile scd/Makefile +tools/Makefile doc/Makefile tests/Makefile ]) -- cgit v1.2.3 From 4ad92cecbcf4d586b886fa41041fde67eccfc58a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Dec 2003 11:27:13 +0000 Subject: Post release version number bump. --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index efa85b162..aff9d5468 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.4 (unreleased) +------------------------------------------------ + + Noteworthy changes in version 1.9.3 (2003-12-23) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 1f3a6b0ff..b0c8f2379 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.3, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.4-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From f332166e51ea753ed17e80c0a74fd8acc5b211fb Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 5 Jan 2004 09:28:27 +0000 Subject: * Manifest: New. * gpgconf.c, gpgconf.h, gpgconf-list.c: New. A skeleton for now. * no-libgcrypt.c: New. * Makefile.am: Add above. --- tools/ChangeLog | 7 +++ tools/Makefile.am | 13 +++- tools/Manifest | 6 ++ tools/gpgconf-list.c | 60 ++++++++++++++++++ tools/gpgconf.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/gpgconf.h | 41 ++++++++++++ tools/no-libgcrypt.c | 83 ++++++++++++++++++++++++ 7 files changed, 384 insertions(+), 1 deletion(-) create mode 100644 tools/Manifest create mode 100644 tools/gpgconf-list.c create mode 100644 tools/gpgconf.c create mode 100644 tools/gpgconf.h create mode 100644 tools/no-libgcrypt.c diff --git a/tools/ChangeLog b/tools/ChangeLog index af8225bc1..46f4a07cf 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2004-01-05 Werner Koch <wk@gnupg.org> + + * Manifest: New. + * gpgconf.c, gpgconf.h, gpgconf-list.c: New. A skeleton for now. + * no-libgcrypt.c: New. + * Makefile.am: Add above. + 2003-12-23 Werner Koch <wk@gnupg.org> * Makefile.am: New. diff --git a/tools/Makefile.am b/tools/Makefile.am index c22fb8f36..f5fc114a7 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -17,4 +17,15 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -EXTRA_DIST = watchgnupg.c +EXTRA_DIST = Manifest watchgnupg.c + +localedir = $(datadir)/locale +INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl + +bin_PROGRAMS = gpgconf + +gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-list.c no-libgcrypt.c + +gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @INTLLIBS@ + diff --git a/tools/Manifest b/tools/Manifest new file mode 100644 index 000000000..96423352d --- /dev/null +++ b/tools/Manifest @@ -0,0 +1,6 @@ +Makefile.am +watchgnupg.c +gpgconf.c +gpgconf.h +gpgconf-list.c +$names$ diff --git a/tools/gpgconf-list.c b/tools/gpgconf-list.c new file mode 100644 index 000000000..e774d2bf4 --- /dev/null +++ b/tools/gpgconf-list.c @@ -0,0 +1,60 @@ +/* gpgconf-list.c - Print list of options. + * 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 "gpgconf.h" +#include "i18n.h" + +/* Format of the colon delimited listing is: + + Area: gpg, gpgsm, gpg-agent, scdaemon, dirmngr, "G" or empty for unspecified. + Option name: Name of the option + Expert level: Expertnesslevel of option: 0 - basic + Immediately Change: "1" is the option is immediatley changeable + (e.g. through SIGHUP) + Option index: Instance number of the option value to build lists. + Option value: Current value of the option + +*/ + + +/* List global options, i.er. those which are commonly required and + may affect more than one program. */ +static void +list_global_options (void) +{ + + +} + + + +void +gpgconf_list_standard_options (void) +{ + + list_global_options (); + + +} diff --git a/tools/gpgconf.c b/tools/gpgconf.c new file mode 100644 index 000000000..6f4c1fbbb --- /dev/null +++ b/tools/gpgconf.c @@ -0,0 +1,175 @@ +/* gpgconf.c - Configuration utility for GnuPG + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "gpgconf.h" +#include "i18n.h" + +/* Constants to identify the commands and options. */ +enum cmd_and_opt_values + { + aNull = 0, + oDryRun = 'n', + oOutput = 'o', + oQuiet = 'q', + oVerbose = 'v', + oNoVerbose = 500, + oHomedir, + + aDummy + }; + + +/* The list of commands and options. */ +static ARGPARSE_OPTS opts[] = + { + { 300, NULL, 0, N_("@Commands:\n ") }, + + { 301, NULL, 0, N_("@\nOptions:\n ") }, + + { oOutput, "output", 2, N_("use as output file")}, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oDryRun, "dry-run", 0, N_("do not make any changes") }, + + /* hidden options */ + { oNoVerbose, "no-verbose", 0, "@"}, + { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ + {0} + }; + + +/* Print usage information and and provide strings for help. */ +static const char * +my_strusage( int level ) +{ + const char *p; + + switch (level) + { + case 11: p = "gpgconf (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: gpgconf [options] (-h for help)"); + break; + case 41: + p = _("Syntax: gpgconf [options]\n" + "Manage configuration options for tools of the GnuPG system\n"); + break; + + default: p = NULL; break; + } + return p; +} + + +/* Initialize the gettext system. */ +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file (PACKAGE); +#else +# ifdef ENABLE_NLS +# ifdef HAVE_LC_MESSAGES + setlocale (LC_TIME, ""); + setlocale (LC_MESSAGES, ""); +# else + setlocale (LC_ALL, "" ); +# endif + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +# endif +#endif +} + + +/* gpgconf main. */ +int +main (int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + const char *fname; + int no_more_options = 0; + enum cmd_and_opt_values cmd = 0; + + set_strusage (my_strusage); + log_set_prefix ("gpgconf", 1); + + i18n_init(); + + /* Setup the default homedir. */ +#ifdef __MINGW32__ + 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; + + /* Patrse the command line. */ + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags = 1; /* do not remove the args */ + while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts)) + { + switch (pargs.r_opt) + { + case oOutput: opt.outfile = pargs.r.ret_str; break; + + case oQuiet: opt.quiet = 1; break; + case oDryRun: opt.dry_run = 1; break; + case oVerbose: opt.verbose++; break; + case oNoVerbose: opt.verbose = 0; break; + case oHomedir: opt.homedir = pargs.r.ret_str; break; + + case aDummy: break; + default: pargs.err = 2; break; + } + } + + if (log_get_errorcount (0)) + exit (2); + + fname = argc? *argv : NULL; + + switch (cmd) + { + default: + /* List all standard options. */ + gpgconf_list_standard_options (); + break; + } + + return 0; +} + + + diff --git a/tools/gpgconf.h b/tools/gpgconf.h new file mode 100644 index 000000000..dd0ec2cc2 --- /dev/null +++ b/tools/gpgconf.h @@ -0,0 +1,41 @@ +/* gpgconf.h - Global definitions for gpgconf + * 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 GPGCONF_H +#define GPGCONF_H + +#include "../common/util.h" + +/* We keep all global options in the structure OPT. */ +struct { + int verbose; /* Verbosity level. */ + int quiet; /* Be as quiet as possible. */ + int dry_run; /* Don't change any persistent data. */ + const char *homedir; /* Configuration directory name. */ + char *outfile; /* Name of output file. */ +} opt; + + + +/*-- gpgconf-list.c --*/ +void gpgconf_list_standard_options (void); + + +#endif /*GPGCONF_H*/ diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c new file mode 100644 index 000000000..b5342732d --- /dev/null +++ b/tools/no-libgcrypt.c @@ -0,0 +1,83 @@ +/* no-libgcrypt.c - Replacement functions for libgcrypt. + * 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 "../common/util.h" +#include "i18n.h" + + +/* Replace libgcrypt's malloc functions which are used by + ../jnlib/libjnlib.a . ../common/util.h defines macros to map them + to xmalloc etc. */ +static void +out_of_core (void) +{ + log_fatal (_("error allocating enough memory: %s\n"), strerror (errno)); +} + + +void * +gcry_xmalloc (size_t n) +{ + void *p = malloc (n); + if (!p) + out_of_core (); + return p; +} + +void * +gcry_xrealloc (void *a, size_t n) +{ + void *p = realloc (a, n); + if (!p) + out_of_core (); + return p; +} + +void * +gcry_xcalloc (size_t n, size_t m) +{ + void *p = calloc (n, m); + if (!p) + out_of_core (); + return p; +} + +char * +gcry_xstrdup (const char *string) +{ + void *p = malloc (strlen (string)+1); + if (!p) + out_of_core (); + strcpy( p, string ); + return p; +} + +void +gcry_free (void *a) +{ + if (a) + free (a); +} -- cgit v1.2.3 From 1e53ff3608dc56181f0517ffaef9228ae27fa051 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 10 Jan 2004 11:50:48 +0000 Subject: Use GPG_ERROR_CFLAGS --- tools/ChangeLog | 4 ++++ tools/Makefile.am | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 46f4a07cf..aa380120e 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-01-10 Werner Koch <wk@gnupg.org> + + * Makefile.am: Use GPG_ERROR_CFLAGS + 2004-01-05 Werner Koch <wk@gnupg.org> * Manifest: New. diff --git a/tools/Makefile.am b/tools/Makefile.am index f5fc114a7..fb2d929bf 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -21,7 +21,10 @@ EXTRA_DIST = Manifest watchgnupg.c localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl + +# Note, that we require GPG_ERROR_CFLAGS only because some share header files +# require that file. It is not actually used in gpgconf. +AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl @GPG_ERROR_CFLAGS@ bin_PROGRAMS = gpgconf -- cgit v1.2.3 From 671f696e55256b7a1788ef379a10edf273baa98b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jan 2004 17:39:58 +0000 Subject: * findkey.c (agent_key_from_file): Now return an error code so that we have more detailed error messages in the upper layers. This fixes the handling pinentry's cancel button. * pksign.c (agent_pksign): Changed accordingly. * pkdecrypt.c (agent_pkdecrypt): Ditto. * command.c (cmd_passwd): Ditto. --- TODO | 3 ++- agent/ChangeLog | 9 +++++++++ agent/agent.h | 4 ++-- agent/command.c | 6 +++--- agent/findkey.c | 48 ++++++++++++++++++++++++++++-------------------- agent/pkdecrypt.c | 5 ++--- agent/pksign.c | 7 +++---- 7 files changed, 49 insertions(+), 33 deletions(-) diff --git a/TODO b/TODO index f1355c03c..12fd998aa 100644 --- a/TODO +++ b/TODO @@ -31,9 +31,10 @@ might want to have an agent context for each service request ** Don't hardcode the use of RSA. * sm/gpgsm.c -** Support --output +** 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 * sm/keydb.c ** Check file permissions diff --git a/agent/ChangeLog b/agent/ChangeLog index 0e165e31b..263259f6a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2004-01-16 Werner Koch <wk@gnupg.org> + + * findkey.c (agent_key_from_file): Now return an error code so + that we have more detailed error messages in the upper layers. + This fixes the handling pinentry's cancel button. + * pksign.c (agent_pksign): Changed accordingly. + * pkdecrypt.c (agent_pkdecrypt): Ditto. + * command.c (cmd_passwd): Ditto. + 2003-12-16 Werner Koch <wk@gnupg.org> * gpg-agent.c (main): Set the prefixes for assuan logging. diff --git a/agent/agent.h b/agent/agent.h index eb4f4e32d..95b0ba4cd 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -130,9 +130,9 @@ void start_command_handler (int, int); /*-- findkey.c --*/ int agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); -gcry_sexp_t agent_key_from_file (CTRL ctrl, const unsigned char *grip, +gpg_error_t agent_key_from_file (CTRL ctrl, const unsigned char *grip, unsigned char **shadow_info, - int ignore_cache); + int ignore_cache, gcry_sexp_t *result); int agent_key_available (const unsigned char *grip); /*-- query.c --*/ diff --git a/agent/command.c b/agent/command.c index a3e1c514a..0406ea439 100644 --- a/agent/command.c +++ b/agent/command.c @@ -606,9 +606,9 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) return rc; /* we can't jump to leave because this is already an Assuan error code. */ - s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1); - if (!s_skey && !shadow_info) - rc = gpg_error (GPG_ERR_NO_SECKEY); + rc = agent_key_from_file (ctrl, grip, &shadow_info, 1, &s_skey); + if (rc) + ; else if (!s_skey) { log_error ("changing a smartcard PIN is not yet supported\n"); diff --git a/agent/findkey.c b/agent/findkey.c index db36cb1b9..a9566a2c7 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -198,16 +198,16 @@ unprotect (CTRL ctrl, -/* Return the secret key as an S-Exp after locating it using the grip. - Returns NULL if key is not available or the operation should be - diverted to a token. In the latter case shadow_info will point to - an allocated S-Expression with the shadow_info part from the file. - With IGNORE_CACHE passed as true the passphrase is not taken from - the cache.*/ -gcry_sexp_t +/* Return the secret key as an S-Exp in RESULT after locating it using + the grip. Returns NULL in RESULT if the operation should be + diverted to a token; SHADOW_INFO will point then to an allocated + S-Expression with the shadow_info part from the file. With + IGNORE_CACHE passed as true the passphrase is not taken from the + cache.*/ +gpg_error_t agent_key_from_file (CTRL ctrl, const unsigned char *grip, unsigned char **shadow_info, - int ignore_cache) + int ignore_cache, gcry_sexp_t *result) { int i, rc; char *fname; @@ -217,7 +217,9 @@ agent_key_from_file (CTRL ctrl, size_t len, buflen, erroff; gcry_sexp_t s_skey; char hexgrip[40+4+1]; + int got_shadow_info = 0; + *result = NULL; if (shadow_info) *shadow_info = NULL; @@ -229,28 +231,31 @@ agent_key_from_file (CTRL ctrl, fp = fopen (fname, "rb"); if (!fp) { + rc = gpg_error_from_errno (errno); log_error ("can't open `%s': %s\n", fname, strerror (errno)); xfree (fname); - return NULL; + return rc; } if (fstat (fileno(fp), &st)) { + rc = gpg_error_from_errno (errno); log_error ("can't stat `%s': %s\n", fname, strerror (errno)); xfree (fname); fclose (fp); - return NULL; + return rc; } buflen = st.st_size; buf = xmalloc (buflen+1); if (fread (buf, buflen, 1, fp) != 1) { + rc = gpg_error_from_errno (errno); log_error ("error reading `%s': %s\n", fname, strerror (errno)); xfree (fname); fclose (fp); xfree (buf); - return NULL; + return rc; } rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); @@ -261,15 +266,16 @@ agent_key_from_file (CTRL ctrl, { log_error ("failed to build S-Exp (off=%u): %s\n", (unsigned int)erroff, gpg_strerror (rc)); - return NULL; + return rc; } len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0); assert (len); buf = xtrymalloc (len); if (!buf) { + rc = out_of_core (); gcry_sexp_release (s_skey); - return NULL; + return rc; } len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len); assert (len); @@ -303,26 +309,27 @@ agent_key_from_file (CTRL ctrl, { memcpy (*shadow_info, s, n); rc = 0; + got_shadow_info = 1; } } if (rc) log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc)); } - rc = -1; /* ugly interface: we return an error but keep a value - in shadow_info. */ + else + rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY); break; default: log_error ("invalid private key format\n"); rc = gpg_error (GPG_ERR_BAD_SECKEY); break; } - if (rc) + if (rc || got_shadow_info) { xfree (buf); - return NULL; + return rc; } - /* arggg FIXME: does scan support secure memory? */ + /* Arggg FIXME: does scan support secure memory? */ rc = gcry_sexp_sscan (&s_skey, &erroff, buf, gcry_sexp_canon_len (buf, 0, NULL, NULL)); xfree (buf); @@ -330,10 +337,11 @@ agent_key_from_file (CTRL ctrl, { log_error ("failed to build S-Exp (off=%u): %s\n", (unsigned int)erroff, gpg_strerror (rc)); - return NULL; + return rc; } - return s_skey; + *result = s_skey; + return 0; } /* Return the secret key as an S-Exp after locating it using the grip. diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index d17c688a0..cc3a2f33f 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -64,11 +64,10 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, log_printhex ("keygrip:", ctrl->keygrip, 20); log_printhex ("cipher: ", ciphertext, ciphertextlen); } - s_skey = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0); - if (!s_skey && !shadow_info) + rc = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0, &s_skey); + if (rc) { log_error ("failed to read the secret key\n"); - rc = gpg_error (GPG_ERR_NO_SECKEY); goto leave; } diff --git a/agent/pksign.c b/agent/pksign.c index d5fe17bb7..34381365e 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -81,12 +81,11 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) if (!ctrl->have_keygrip) return gpg_error (GPG_ERR_NO_SECKEY); - s_skey = agent_key_from_file (ctrl, - ctrl->keygrip, &shadow_info, ignore_cache); - if (!s_skey && !shadow_info) + rc = agent_key_from_file (ctrl, ctrl->keygrip, + &shadow_info, ignore_cache, &s_skey); + if (rc) { log_error ("failed to read the secret key\n"); - rc = gpg_error (GPG_ERR_NO_SECKEY); goto leave; } -- cgit v1.2.3 From 52f55537597a5587aa1b9cc872f9bf07f69c84ea Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jan 2004 17:40:50 +0000 Subject: * argparse.c (strusage): Changed default copyright year to 2004. --- jnlib/ChangeLog | 6 +++++- jnlib/argparse.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 89a3ccca4..9d5564c85 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,6 +1,10 @@ +2004-01-05 Werner Koch <wk@gnupg.org> + + * argparse.c (strusage): Changed default copyright year to 2004. + 2003-12-17 Werner Koch <wk@gnupg.org> - * argparse.c (initialize): Replaced use of non-literal forma + * argparse.c (initialize): Replaced use of non-literal format args. Suggested by Florian Weimer. 2003-12-16 Werner Koch <wk@gnupg.org> diff --git a/jnlib/argparse.c b/jnlib/argparse.c index 148934637..de828e8ce 100644 --- a/jnlib/argparse.c +++ b/jnlib/argparse.c @@ -904,7 +904,7 @@ strusage( int level ) switch( level ) { case 11: p = "foo"; break; case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2002 Free Software Foundation, Inc."; break; + case 14: p = "Copyright (C) 2004 Free Software Foundation, Inc."; break; case 15: p = "This program comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" -- cgit v1.2.3 From 30948e5ecd227771771c4a2e1263e4392296b8af Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jan 2004 17:42:08 +0000 Subject: comment typo fixes. --- kbx/keybox-blob.c | 4 ++-- kbx/keybox-search.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index defddad69..3d815321f 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -72,7 +72,7 @@ X.509 specific are noted like [X.509: xxx] bit 0 = byte validity byte reserved - [For X509, the first user ID is the ISsuer, the second the subject + [For X509, the first user ID is the Issuer, the second the Subject and the others are subjectAltNames] u16 number of signatures u16 size of signature information (4) @@ -195,7 +195,7 @@ struct keyboxblob { -/* A simple implemnation of a dynamic buffer. Use init_membuf() to +/* A simple implemention 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 diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index e834cd2bf..b8add5abe 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -566,7 +566,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) /* kludge: we need to convert an SN given as hexstring to it's binary representation - in some cases we are not able to store it - in the search descriptor, because due to its usgae it is not + in the search descriptor, because due to its usage it is not possible to free allocated memory */ if (sn_array) { -- cgit v1.2.3 From 4dc78204ae8b3632de311addbb215cdadf14acda Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jan 2004 17:42:36 +0000 Subject: * sign.c (gpgsm_sign): Print an error message on all failures. * decrypt.c (gpgsm_decrypt): Ditto. --- sm/ChangeLog | 5 +++++ sm/decrypt.c | 5 ++++- sm/sign.c | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index e3329b669..788c71f4d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-01-16 Werner Koch <wk@gnupg.org> + + * sign.c (gpgsm_sign): Print an error message on all failures. + * decrypt.c (gpgsm_decrypt): Ditto. + 2003-12-17 Werner Koch <wk@gnupg.org> * server.c (gpgsm_server): Add arg DEFAULT_RECPLIST. diff --git a/sm/decrypt.c b/sm/decrypt.c index 9b02392d6..c6eb8ab4b 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -482,7 +482,10 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) leave: if (rc) - gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); + { + gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); + log_error ("message decryption failed: %s\n", gpg_strerror (rc)); + } ksba_cms_release (cms); gpgsm_destroy_reader (b64reader); gpgsm_destroy_writer (b64writer); diff --git a/sm/sign.c b/sm/sign.c index 5afbc6cdd..b3e3b5646 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -622,6 +622,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, leave: + if (rc) + log_error ("error creating signature: %s\n", gpg_strerror (rc)); if (release_signerlist) gpgsm_release_certlist (signerlist); ksba_cms_release (cms); -- cgit v1.2.3 From e5b228fc67cb6a5fb73b1a9fd20b557539d7442d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jan 2004 22:38:58 +0000 Subject: (main): Need to use FD_ISSET for the client descriptors too; aiiih. Set the listening socket to non-blocking. --- tools/ChangeLog | 5 +++++ tools/watchgnupg.c | 22 +++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index aa380120e..33ed0fc8b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-01-16 Werner Koch <wk@gnupg.org> + + * watchgnupg.c (main): Need to use FD_ISSET for the client + descriptors too; aiiih. Set the listening socket to non-blocking. + 2004-01-10 Werner Koch <wk@gnupg.org> * Makefile.am: Use GPG_ERROR_CFLAGS diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index 63daab11e..dfb11f2de 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -28,6 +28,7 @@ #include <unistd.h> #include <sys/socket.h> #include <sys/un.h> +#include <fcntl.h> #include <time.h> #define PGM "watchgnupg" @@ -178,6 +179,7 @@ main (int argc, char **argv) struct sockaddr_un srvr_addr; int addrlen; int server; + int flags; client_t client_list = NULL; if (argc) @@ -227,6 +229,16 @@ main (int argc, char **argv) if (server == -1) die ("socket() failed: %s\n", strerror (errno)); + /* We better set the listening socket to non-blocking so that we + don't get bitten by race conditions in accept. The should not + happen for Unix Domain sockets but well, shit happens. */ + flags = fcntl (server, F_GETFL, 0); + if (flags == -1) + die ("fcntl (F_GETFL) failed: %s\n", strerror (errno)); + if ( fcntl (server, F_SETFL, (flags | O_NONBLOCK)) == -1) + die ("fcntl (F_SETFL) failed: %s\n", strerror (errno)); + + memset (&srvr_addr, 0, sizeof srvr_addr); srvr_addr.sun_family = AF_LOCAL; strncpy (srvr_addr.sun_path, *argv, sizeof (srvr_addr.sun_path) - 1); @@ -257,8 +269,8 @@ main (int argc, char **argv) client_t client; /* Usually we don't have that many connections, thus it is okay - to set them al the time from scratch and don't maintain an - active fd_set. */ + to set them allways from scratch and don't maintain an active + fd_set. */ FD_ZERO (&rfds); FD_SET (server, &rfds); max_fd = server; @@ -282,12 +294,12 @@ main (int argc, char **argv) fd = accept (server, (struct sockaddr *) &clnt_addr, &addrlen); if (fd == -1) { - printf ("accepting connection failed: %s\n", strerror (errno)); + printf ("[accepting connection failed: %s]\n", strerror (errno)); } else if (fd >= FD_SETSIZE) { close (fd); - printf ("[connection request denied: too many connections\n"); + printf ("[connection request denied: too many connections]\n"); } else { @@ -305,7 +317,7 @@ main (int argc, char **argv) } } for (client = client_list; client; client = client->next) - if (client->fd != -1) + if (client->fd != -1 && FD_ISSET (client->fd, &rfds)) { char line[256]; int n; -- cgit v1.2.3 From 36cbfed6fcdaaeda951120d6a596d9b9a665c850 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sun, 18 Jan 2004 22:48:49 +0000 Subject: 2004-01-18 Moritz Schulte <mo@g10code.com> * keygen.c (do_generate_keypair): Print member fname, instead of newfname. --- g10/ChangeLog | 5 +++++ g10/keygen.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f3399b510..f4fb088ca 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2004-01-18 Moritz Schulte <mo@g10code.com> + + * keygen.c (do_generate_keypair): Print member fname, instead of + newfname. + 2003-12-17 Werner Koch <wk@gnupg.org> * card-util.c (print_name): Fixed bad format string usage. diff --git a/g10/keygen.c b/g10/keygen.c index 935cff330..309a6ea85 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -2452,7 +2452,7 @@ do_generate_keypair (struct para_data_s *para, outctrl->pub.stream = iobuf_create (outctrl->pub.fname); if (!outctrl->pub.stream) { - log_error ("can't create `%s': %s\n", outctrl->pub.newfname, + log_error ("can't create `%s': %s\n", outctrl->pub.fname, strerror (errno)); return; } -- cgit v1.2.3 From 7739d9580408f77c85b88f2dee64ec24c3cbfe14 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Mon, 19 Jan 2004 01:07:46 +0000 Subject: 2004-01-19 Moritz Schulte <mo@g10code.com> * keygen.c (do_generate_keypair): Print member fname, instead of newfname, again. --- g10/ChangeLog | 5 +++++ g10/keygen.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index f4fb088ca..3316f1ca6 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2004-01-19 Moritz Schulte <mo@g10code.com> + + * keygen.c (do_generate_keypair): Print member fname, instead of + newfname, again. + 2004-01-18 Moritz Schulte <mo@g10code.com> * keygen.c (do_generate_keypair): Print member fname, instead of diff --git a/g10/keygen.c b/g10/keygen.c index 309a6ea85..a13ea155c 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2474,7 +2474,7 @@ do_generate_keypair (struct para_data_s *para, outctrl->sec.stream = iobuf_create (outctrl->sec.fname); if (!outctrl->sec.stream) { - log_error ("can't create `%s': %s\n", outctrl->sec.newfname, + log_error ("can't create `%s': %s\n", outctrl->sec.fname, strerror (errno)); return; } -- cgit v1.2.3 From af41684669b470d22eb95a09bc714abd799960ae Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Mon, 19 Jan 2004 01:48:17 +0000 Subject: 2004-01-19 Moritz Schulte <mo@g10code.com> * keygen.c (do_generate_keypair): Don't try to execute certain pieces of code in case an error occured. (gen_card_key): Don't print out a message, which is already printed by do_generate_keypair(). --- g10/ChangeLog | 4 ++++ g10/keygen.c | 10 ++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 3316f1ca6..cc4509433 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -2,6 +2,10 @@ * keygen.c (do_generate_keypair): Print member fname, instead of newfname, again. + (do_generate_keypair): Don't try to execute certain pieces of code + in case an error occured. + (gen_card_key): Don't print out a message, which is already + printed by do_generate_keypair(). 2004-01-18 Moritz Schulte <mo@g10code.com> diff --git a/g10/keygen.c b/g10/keygen.c index a13ea155c..72c5e1e8a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2549,7 +2549,7 @@ do_generate_keypair (struct para_data_s *para, get_parameter_uint (para, pKEYUSAGE)); } - if (get_parameter (para, pSUBKEYTYPE)) + if ((! rc) && get_parameter (para, pSUBKEYTYPE)) { if (!card) { @@ -2575,7 +2575,7 @@ do_generate_keypair (struct para_data_s *para, did_sub = 1; } - if (card && get_parameter (para, pAUTHKEYTYPE)) + if ((! rc) && card && get_parameter (para, pAUTHKEYTYPE)) { rc = gen_card_key (PUBKEY_ALGO_RSA, 3, pub_root, sec_root, get_parameter_u32 (para, pKEYEXPIRE), para); @@ -2866,10 +2866,8 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, /* } */ if (rc) - { - log_error ("key generation failed: %s\n", gpg_strerror (rc)); - return rc; - } + return rc; + if ( !info.n || !info.e ) { log_error ("communication error with SCD\n"); -- cgit v1.2.3 From 203e1cc272325046388387ef17b10e9d25a2524b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 24 Jan 2004 20:50:49 +0000 Subject: * call-scd.c (atfork_cb): New. (start_scd): Make sure secmem gets cleared. * query.c (atfork_cb): New. (start_pinentry): Make sure secmem gets cleared. --- agent/ChangeLog | 7 +++++++ agent/call-scd.c | 16 +++++++++++++--- agent/query.c | 17 ++++++++++++++--- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 263259f6a..bd009ecbe 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,10 @@ +2004-01-24 Werner Koch <wk@gnupg.org> + + * call-scd.c (atfork_cb): New. + (start_scd): Make sure secmem gets cleared. + * query.c (atfork_cb): New. + (start_pinentry): Make sure secmem gets cleared. + 2004-01-16 Werner Koch <wk@gnupg.org> * findkey.c (agent_key_from_file): Now return an error code so diff --git a/agent/call-scd.c b/agent/call-scd.c index 14487f1e3..f205fb074 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -152,6 +152,16 @@ unlock_scd (int rc) return rc; } +/* To make sure we leave no secrets in our image after forking of the + scdaemon, we use this callback. */ +static void +atfork_cb (void *opaque, int where) +{ + if (!where) + gcry_control (GCRYCTL_TERM_SECMEM); +} + + /* Fork off the SCdaemon if this has not already been done */ static int start_scd (void) @@ -206,9 +216,9 @@ start_scd (void) } no_close_list[i] = -1; - /* connect to the pinentry and perform initial handshaking */ - rc = assuan_pipe_connect (&ctx, opt.scdaemon_program, (char**)argv, - no_close_list); + /* Connect to the pinentry and perform initial handshaking */ + rc = assuan_pipe_connect2 (&ctx, opt.scdaemon_program, (char**)argv, + no_close_list, atfork_cb, NULL); if (rc) { log_error ("can't connect to the SCdaemon: %s\n", diff --git a/agent/query.c b/agent/query.c index 4a051965d..a3a773380 100644 --- a/agent/query.c +++ b/agent/query.c @@ -78,6 +78,17 @@ unlock_pinentry (int rc) return rc; } + +/* To make sure we leave no secrets in our image after forking of the + pinentry, we use this callback. */ +static void +atfork_cb (void *opaque, int where) +{ + if (!where) + gcry_control (GCRYCTL_TERM_SECMEM); +} + + /* Fork off the pin entry if this has not already been done. Note, that this function must always be used to aquire the lock for the pinentry - we will serialize _all_ pinentry calls. @@ -139,9 +150,9 @@ start_pinentry (CTRL ctrl) } no_close_list[i] = -1; - /* connect to the pinentry and perform initial handshaking */ - rc = assuan_pipe_connect (&ctx, opt.pinentry_program, (char**)argv, - no_close_list); + /* Connect to the pinentry and perform initial handshaking */ + rc = assuan_pipe_connect2 (&ctx, opt.pinentry_program, (char**)argv, + no_close_list, atfork_cb, NULL); if (rc) { log_error ("can't connect to the PIN entry module: %s\n", -- cgit v1.2.3 From eb24d8b751750cf96cb200f80b45ed3806648883 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 27 Jan 2004 16:40:42 +0000 Subject: Some minor bug fixes, new test utilities and started support for other smartcard applications. --- ChangeLog | 4 + README | 4 +- TODO | 1 + agent/ChangeLog | 6 +- agent/Makefile.am | 3 +- agent/sexp-parse.h | 99 ---- common/ChangeLog | 6 + common/Makefile.am | 1 + common/sexp-parse.h | 99 ++++ common/util.h | 3 +- configure.ac | 2 +- scd/ChangeLog | 65 +++ scd/Makefile.am | 24 +- scd/apdu.c | 2 +- scd/apdu.h | 5 +- scd/app-common.h | 70 +-- scd/app-dinsig.c | 129 ++++++ scd/app-nks.c | 388 ++++++++++++++++ scd/app-openpgp.c | 139 ++---- scd/app.c | 131 ++++-- scd/card.c | 6 +- scd/ccid-driver.c | 9 +- scd/command.c | 127 ++++-- scd/iso7816.c | 192 +++++++- scd/iso7816.h | 8 + scd/sc-copykeys.c | 2 +- scd/sc-investigate.c | 480 ++++++++++++++++++-- scd/scdaemon.c | 4 +- scd/scdaemon.h | 3 + scd/tlv.c | 219 +++++++++ scd/tlv.h | 84 ++++ tools/gpgparsemail.c | 705 ++++++++++++++++++++++++++++ tools/rfc822parse.c | 1235 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools/rfc822parse.h | 79 ++++ 34 files changed, 3959 insertions(+), 375 deletions(-) delete mode 100644 agent/sexp-parse.h create mode 100644 common/sexp-parse.h create mode 100644 scd/app-dinsig.c create mode 100644 scd/app-nks.c create mode 100644 scd/tlv.c create mode 100644 scd/tlv.h create mode 100644 tools/gpgparsemail.c create mode 100644 tools/rfc822parse.c create mode 100644 tools/rfc822parse.h diff --git a/ChangeLog b/ChangeLog index 0752eec64..84abc4dee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/README b/README index 42099d6f6..84fc8967b 100644 --- a/README +++ b/README @@ -138,8 +138,8 @@ gpgsm: --with-key-data - Displays extra information with the --list-keys commands. Especiall - a line tagged "grp" si printed which tells you the keygrip of a + 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. diff --git a/TODO b/TODO index 12fd998aa..621b278ba 100644 --- a/TODO +++ b/TODO @@ -52,6 +52,7 @@ might want to have an agent context for each service request * agent/protect-tool.c ** Export and import certificates along with the secret key. ** Make it more comfortable; i.e. copy files to the correct place. +** BUG? --p12-export seems to work only with unprotected keys * Move pkcs-1 encoding into libgcrypt. diff --git a/agent/ChangeLog b/agent/ChangeLog index bd009ecbe..57f9214f6 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-01-27 Werner Koch <wk@gnupg.org> + + * sexp-parse.h: Moved to ../common. + 2004-01-24 Werner Koch <wk@gnupg.org> * call-scd.c (atfork_cb): New. @@ -437,7 +441,7 @@ * protect.c (agent_get_shadow_info): New. * protect.c (snext,sskip,smatch): Moved to - * sexp-parse.h: new file. + * sexp-parse.h: New file. * divert-scd.c: New. 2002-02-27 Werner Koch <wk@gnupg.org> diff --git a/agent/Makefile.am b/agent/Makefile.am index 400aa2fd2..65af03368 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -41,8 +41,7 @@ gpg_agent_SOURCES = \ trustlist.c \ divert-scd.c \ call-scd.c \ - learncard.c \ - sexp-parse.h + learncard.c gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ diff --git a/agent/sexp-parse.h b/agent/sexp-parse.h deleted file mode 100644 index 89aa7210f..000000000 --- a/agent/sexp-parse.h +++ /dev/null @@ -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*/ diff --git a/common/ChangeLog b/common/ChangeLog index 1b454fa13..8e5c615d9 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/common/Makefile.am b/common/Makefile.am index 79dedca34..770ed12d6 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -29,6 +29,7 @@ AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) libcommon_a_SOURCES = \ util.h i18n.h \ errors.h \ + sexp-parse.h \ maperror.c \ sysutils.c sysutils.h \ gettime.c \ diff --git a/common/sexp-parse.h b/common/sexp-parse.h new file mode 100644 index 000000000..89aa7210f --- /dev/null +++ b/common/sexp-parse.h @@ -0,0 +1,99 @@ +/* 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*/ diff --git a/common/util.h b/common/util.h index 80a1d01a6..7e134e846 100644 --- a/common/util.h +++ b/common/util.h @@ -134,13 +134,14 @@ int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3); \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 */ +/* 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)) diff --git a/configure.ac b/configure.ac index b0c8f2379..cd0486f4b 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ AC_INIT(gnupg, 1.9.4-cvs, gnupg-devel@gnupg.org) development_version=yes NEED_GPG_ERROR_VERSION=0.6 NEED_LIBGCRYPT_VERSION=1.1.91 -NEED_LIBASSUAN_VERSION=0.6.2 +NEED_LIBASSUAN_VERSION=0.6.3 NEED_KSBA_VERSION=0.9.1 NEED_OPENSC_VERSION=0.8.0 diff --git a/scd/ChangeLog b/scd/ChangeLog index 0862d356b..3a6a6aea4 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,68 @@ +2004-01-27 Werner Koch <wk@gnupg.org> + + * command.c (cmd_readcert, cmd_readkey): Work on a copy of LINE. + + * app-common.h (app_ctx_s): Added readcert field. + * app.c (app_readcert): New. + * tlv.c (parse_ber_header): Added; taken from libksba. + +2004-01-26 Werner Koch <wk@gnupg.org> + + * card.c (map_sc_err): Use SCD as the error source. + + * command.c (open_card): ADD arg NAME to allow requesting a + specific application. Changed all callers. + (cmd_serialno): Allow optional argument to select the desired + application. + + * app-nks.c: New. + + * scdaemon.h (opt): Add READER_PORT. + * scdaemon.c (main): Set it here. + * app.c (app_set_default_reader_port): Removed. + (select_application): Add NAME arg and figure out a + default serial number from the GDO. Add SLOT arg and remove all + reader management. + (release_application): New. + (app_write_learn_status): Output an APPTYPE status line. + * command.c (open_card): Adapt for select_application change. + * app-openpgp.c (app_select_openpgp): Removed SN and SNLEN args + and set it directly. Changed all callers. + +2004-01-25 Werner Koch <wk@gnupg.org> + + * iso7816.c (iso7816_select_application): P1 kludge for OpenPGP + card. + * app-openpgp.c (find_tlv): Factor out this function to .. + * tlv.c, tlv.h: .. new. + + * scdaemon.h: Introduced app_t and ctrl_t as the new types for APP + and CTRL. + +2004-01-21 Werner Koch <wk@gnupg.org> + + * apdu.c (apdu_send_le): Treat SW_EOF_REACHED as a warning. + +2004-01-20 Werner Koch <wk@gnupg.org> + + * iso7816.c (iso7816_read_binary): New. + (iso7816_select_file): New. + (iso7816_list_directory): New. + + * sc-investigate.c: Add option -i. + (select_app, read_line, interactive_shell): New. + +2004-01-16 Werner Koch <wk@gnupg.org> + + * apdu.h: Add SW_FILE_NOT_FOUND. + * iso7816.c (map_sw): Map it to GPG_ERR_ENOENT. + * iso7816.c (iso7816_select_file): New. + + * app-dinsig.c: New file w/o any real code yet. + * Makefile.am (scdaemon_SOURCES,sc_investigate_SOURCES): Add file. + + * sc-investigate.c: Add option --disable-ccid. + 2003-12-19 Werner Koch <wk@gnupg.org> * apdu.c (apdu_send_le): Send a get_response with the indicated diff --git a/scd/Makefile.am b/scd/Makefile.am index a2ecd3a81..c8bf3d0de 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -26,6 +26,8 @@ bin_PROGRAMS = scdaemon sc-investigate sc-copykeys AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) +card_apps = app-openpgp.c app-nks.c app-dinsig.c + scdaemon_SOURCES = \ scdaemon.c scdaemon.h \ command.c card.c \ @@ -34,8 +36,9 @@ scdaemon_SOURCES = \ apdu.c apdu.h \ ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ - app.c app-common.h \ - app-openpgp.c + tlv.c tlv.h \ + app.c app-common.h $(card_apps) + scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ @@ -46,9 +49,9 @@ sc_investigate_SOURCES = \ apdu.c apdu.h \ ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ - app.c app-common.h \ - app-openpgp.c \ - atr.c atr.h + tlv.c tlv.h \ + atr.c atr.h \ + app.c app-common.h $(card_apps) sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ @@ -61,17 +64,12 @@ sc_copykeys_SOURCES = \ apdu.c apdu.h \ ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ - app.c app-common.h \ - app-openpgp.c \ - atr.c atr.h + tlv.c tlv.h \ + atr.c atr.h \ + app.c app-common.h $(card_apps) sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) \ -lgpg-error @INTLLIBS@ -ldl - - - - - diff --git a/scd/apdu.c b/scd/apdu.c index 02038b65c..e5295f566 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1168,7 +1168,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, log_printhex (" dump: ", result, resultlen); } - if (sw == SW_SUCCESS) + if (sw == SW_SUCCESS || sw == SW_EOF_REACHED) { if (retbuf) { diff --git a/scd/apdu.h b/scd/apdu.h index 21e2b9840..fd7634f13 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -27,13 +27,16 @@ enum { SW_MORE_DATA = 0x6100, /* Note: that the low byte must be masked of.*/ + SW_EOF_REACHED = 0x6282, SW_EEPROM_FAILURE = 0x6581, SW_WRONG_LENGTH = 0x6700, SW_CHV_WRONG = 0x6982, SW_CHV_BLOCKED = 0x6983, SW_USE_CONDITIONS = 0x6985, - SW_NOT_SUPPORTED = 0x6a81, SW_BAD_PARAMETER = 0x6a80, /* (in the data field) */ + SW_NOT_SUPPORTED = 0x6a81, + SW_FILE_NOT_FOUND = 0x6a82, + SW_RECORD_NOT_FOUND = 0x6a83, SW_REF_NOT_FOUND = 0x6a88, SW_BAD_P0_P1 = 0x6b00, SW_INS_NOT_SUP = 0x6d00, diff --git a/scd/app-common.h b/scd/app-common.h index de1e02cac..cda17700f 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -29,43 +29,46 @@ struct app_ctx_s { int slot; /* Used reader. */ unsigned char *serialno; /* Serialnumber in raw form, allocated. */ size_t serialnolen; /* Length in octets of serialnumber. */ + const char *apptype; unsigned int card_version; int did_chv1; int force_chv1; /* True if the card does not cache CHV1. */ int did_chv2; int did_chv3; struct { - int (*learn_status) (APP app, CTRL ctrl); - int (*getattr) (APP app, CTRL ctrl, const char *name); - int (*setattr) (APP app, const char *name, + int (*learn_status) (app_t app, ctrl_t ctrl); + int (*readcert) (app_t app, const char *certid, + unsigned char **cert, size_t *certlen); + int (*getattr) (app_t app, ctrl_t ctrl, const char *name); + int (*setattr) (app_t app, const char *name, int (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen); - int (*sign) (APP app, + int (*sign) (app_t app, const char *keyidstr, int hashalgo, int (pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); - int (*auth) (APP app, const char *keyidstr, + int (*auth) (app_t app, const char *keyidstr, int (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); - int (*decipher) (APP app, const char *keyidstr, + int (*decipher) (app_t app, const char *keyidstr, int (pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); - int (*genkey) (APP app, CTRL ctrl, + int (*genkey) (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, int (*pincb)(void*, const char *, char **), void *pincb_arg); - int (*change_pin) (APP app, CTRL ctrl, + int (*change_pin) (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, int (*pincb)(void*, const char *, char **), void *pincb_arg); - int (*check_pin) (APP app, const char *keyidstr, + int (*check_pin) (app_t app, const char *keyidstr, int (pincb)(void*, const char *, char **), void *pincb_arg); } fnc; @@ -74,66 +77,77 @@ struct app_ctx_s { }; #if GNUPG_MAJOR_VERSION == 1 -int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen); -int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); +int app_select_openpgp (app_t app); +int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); #else /*-- app.c --*/ -void app_set_default_reader_port (const char *portstr); -APP select_application (void); -int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); -int app_write_learn_status (APP app, CTRL ctrl); -int app_getattr (APP app, CTRL ctrl, const char *name); -int app_setattr (APP app, const char *name, +app_t select_application (ctrl_t ctrl, int slot, const char *name); +void release_application (app_t app); +int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); +int app_write_learn_status (app_t app, ctrl_t ctrl); +int app_readcert (app_t app, const char *certid, + unsigned char **cert, size_t *certlen); +int app_getattr (app_t app, ctrl_t ctrl, const char *name); +int app_setattr (app_t app, const char *name, int (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen); -int app_sign (APP app, const char *keyidstr, int hashalgo, +int app_sign (app_t app, const char *keyidstr, int hashalgo, int (pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); -int app_auth (APP app, const char *keyidstr, +int app_auth (app_t app, const char *keyidstr, int (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); -int app_decipher (APP app, const char *keyidstr, +int app_decipher (app_t app, const char *keyidstr, int (pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); -int app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, +int app_genkey (app_t app, ctrl_t ctrl, + const char *keynostr, unsigned int flags, int (*pincb)(void*, const char *, char **), void *pincb_arg); -int app_get_challenge (APP app, size_t nbytes, unsigned char *buffer); -int app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, +int app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer); +int app_change_pin (app_t app, ctrl_t ctrl, + const char *chvnostr, int reset_mode, int (*pincb)(void*, const char *, char **), void *pincb_arg); -int app_check_pin (APP app, const char *keyidstr, +int app_check_pin (app_t app, const char *keyidstr, int (*pincb)(void*, const char *, char **), void *pincb_arg); /*-- app-openpgp.c --*/ -int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen); +int app_select_openpgp (app_t app); -int app_openpgp_cardinfo (APP app, +int app_openpgp_cardinfo (app_t app, char **serialno, char **disp_name, char **pubkey_url, unsigned char **fpr1, unsigned char **fpr2, unsigned char **fpr3); -int app_openpgp_storekey (APP app, int keyno, +int app_openpgp_storekey (app_t app, int keyno, unsigned char *template, size_t template_len, time_t created_at, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, int (*pincb)(void*, const char *, char **), void *pincb_arg); -int app_openpgp_readkey (APP app, int keyno, +int app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen, unsigned char **e, size_t *elen); +/*-- app-nks.c --*/ +int app_select_nks (app_t app); + +/*-- app-dinsig.c --*/ +int app_select_dinsig (app_t app); + + #endif diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c new file mode 100644 index 000000000..4b5b517eb --- /dev/null +++ b/scd/app-dinsig.c @@ -0,0 +1,129 @@ +/* app-dinsig.c - The DINSIG (DIN V 66291-1) card application. + * 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 + */ + + +/* The German signature law and its bylaw (SigG and SigV) is currently + used with an interface specification described in DIN V 66291-1. + The AID to be used is: 'D27600006601'. + + The file IDs for certificates utilize the generic format: + Cxyz + C being the hex digit 'C' (12). + x being the service indicator: + '0' := SigG conform digital signature. + '1' := entity authentication. + '2' := key encipherment. + '3' := data encipherment. + '4' := key agreement. + other values are reserved for future use. + y being the security environment number using '0' for cards + not supporting a SE number. + z being the certificate type: + '0' := C.CH (base certificate of card holder) or C.ICC. + '1' .. '7' := C.CH (business or professional certificate + of card holder. + '8' .. 'D' := C.CA (certificate of a CA issue by the Root-CA). + 'E' := C.RCA (self certified certificate of the Root-CA). + 'F' := reserved. + + The file IDs used by default are: + '1F00' EF.SSD (security service descriptor). [o,o] + '2F02' EF.GDO (global data objects) [m,m] + 'A000' EF.PROT (signature log). Cyclic file with 20 records of 53 byte. + Read and update after user authentication. [o,o] + 'B000' EF.PK.RCA.DS (public keys of Root-CA). Size is 512b or size + of keys. [m (unless a 'C00E' is present),m] + 'B001' EF.PK.CA.DS (public keys of CAs). Size is 512b or size + of keys. [o,o] + 'C00n' EF.C.CH.DS (digital signature certificate of card holder) + with n := 0 .. 7. Size is 2k or size of cert. Read and + update allowed after user authentication. [m,m] + 'C00m' EF.C.CA.DS (digital signature certificate of CA) + with m := 8 .. E. Size is 1k or size of cert. Read always + allowed, update after user authentication. [o,o] + 'C100' EF.C.ICC.AUT (AUT certificate of ICC) [o,m] + 'C108' EF.C.CA.AUT (AUT certificate of CA) [o,m] + 'D000' EF.DM (display message) [-,m] + + The letters in brackets indicate optional or mandatory files: The + first for card terminals under full control and the second for + "business" card terminals. + + FIXME: Needs a lot more explanation. + +*/ + + + + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> + +#include "scdaemon.h" + +#include "iso7816.h" +#include "app-common.h" + + + +static int +do_learn_status (APP app, CTRL ctrl) +{ + return 0; +} + + + + + +/* Select the DINSIG application on the card in SLOT. This function + must be used before any other DINSIG application functions. */ +int +app_select_dinsig (APP app) +{ + static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 }; + int slot = app->slot; + int rc; + + rc = iso7816_select_application (slot, aid, sizeof aid); + if (!rc) + { + app->apptype = "DINSIG"; + + app->fnc.learn_status = do_learn_status; + app->fnc.getattr = NULL; + app->fnc.setattr = NULL; + app->fnc.genkey = NULL; + app->fnc.sign = NULL; + app->fnc.auth = NULL; + app->fnc.decipher = NULL; + app->fnc.change_pin = NULL; + app->fnc.check_pin = NULL; + } + + return rc; +} + + diff --git a/scd/app-nks.c b/scd/app-nks.c new file mode 100644 index 000000000..0a04f7511 --- /dev/null +++ b/scd/app-nks.c @@ -0,0 +1,388 @@ +/* app-nks.c - The Telesec NKS 2.0 card application. + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> + +#include "scdaemon.h" + +#include "iso7816.h" +#include "app-common.h" +#include "tlv.h" + +static struct { + int fid; /* File ID. */ + int certtype; /* Type of certificate or 0 if it is not a certificate. */ + int iskeypair; /* If true has the FID of the correspoding certificate. */ +} filelist[] = { + { 0x4531, 0, 0xC000 }, + { 0xC000, 101 }, + { 0x4331, 100 }, + { 0x4332, 100 }, + { 0xB000, 110 }, + { 0x45B1, 0, 0xC200 }, + { 0xC200, 101 }, + { 0x43B1, 100 }, + { 0x43B2, 100 }, + { 0, 0 } +}; + + + +/* Given the slot and the File Id FID, return the length of the + certificate contained in that file. Returns 0 if the file does not + exists or does not contain a certificate. */ +static size_t +get_length_of_cert (int slot, int fid) +{ + gpg_error_t err; + unsigned char *buffer; + const unsigned char *p; + size_t buflen, n; + int class, tag, constructed, ndef; + size_t objlen, hdrlen; + + err = iso7816_select_file (slot, fid, 0, NULL, NULL); + if (err) + { + log_info ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err)); + return 0; + } + + err = iso7816_read_binary (slot, 0, 32, &buffer, &buflen); + if (err) + { + log_info ("error reading certificate from FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + return 0; + } + + if (!buflen || *buffer == 0xff) + { + log_info ("no certificate contained in FID 0x%04X\n", fid); + xfree (buffer); + return 0; + } + + p = buffer; + n = buflen; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + { + log_info ("error parsing certificate in FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + xfree (buffer); + return 0; + } + + /* All certificates should commence with a SEQUENCE expect fro the + special ROOT CA which are enclosed in a SET. */ + if ( !(class == CLASS_UNIVERSAL && constructed + && (tag == TAG_SEQUENCE || tag == TAG_SET))) + { + log_info ("contents of FID 0x%04X does not look like a certificate\n", + fid); + return 0; + } + + return objlen + hdrlen; +} + + + +/* Read the file with FID, assume it contains a public key and return + its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */ +static gpg_error_t +keygripstr_from_pk_file (int slot, int fid, char *r_gripstr) +{ + gpg_error_t err; + unsigned char grip[20]; + unsigned char *buffer[2]; + size_t buflen[2]; + gcry_sexp_t sexp; + int i; + + err = iso7816_select_file (slot, fid, 0, NULL, NULL); + if (err) + return err; + err = iso7816_read_record (slot, 1, 1, &buffer[0], &buflen[0]); + if (err) + return err; + err = iso7816_read_record (slot, 2, 1, &buffer[1], &buflen[1]); + if (err) + { + xfree (buffer[0]); + return err; + } + + for (i=0; i < 2; i++) + { + /* Check that the value appears like an integer encoded as + Simple-TLV. We don't check the tag because the tests cards I + have use 1 for both, the modulus and the exponent - the + example in the documentation gives 2 for the exponent. */ + if (buflen[i] < 3) + err = gpg_error (GPG_ERR_TOO_SHORT); + else if (buffer[i][1] != buflen[i]-2 ) + err = gpg_error (GPG_ERR_INV_OBJ); + } + + if (!err) + err = gcry_sexp_build (&sexp, NULL, + "(public-key (rsa (n %b) (e %b)))", + (int)buflen[0]-2, buffer[0]+2, + (int)buflen[1]-2, buffer[1]+2); + + xfree (buffer[0]); + xfree (buffer[1]); + if (err) + return err; + + if (!gcry_pk_get_keygrip (sexp, grip)) + { + err = gpg_error (GPG_ERR_INTERNAL); /* i.e. RSA not supported by + libgcrypt. */ + } + else + { + for (i=0; i < 20; i++) + sprintf (r_gripstr+i*2, "%02X", grip[i]); + } + gcry_sexp_release (sexp); + return err; +} + + + +static int +do_learn_status (APP app, CTRL ctrl) +{ + gpg_error_t err; + char ct_buf[100], id_buf[100]; + int i; + + /* Output information about all useful objects. */ + for (i=0; filelist[i].fid; i++) + { + if (filelist[i].certtype) + { + size_t len = get_length_of_cert (app->slot, filelist[i].fid); + + if (len) + { + /* FIXME: We should store the length in the application's + context so that a following readcert does only need to + read that many bytes. */ + sprintf (ct_buf, "%d", filelist[i].certtype); + sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid); + send_status_info (ctrl, "CERTINFO", + ct_buf, strlen (ct_buf), + id_buf, strlen (id_buf), + NULL, (size_t)0); + } + } + else if (filelist[i].iskeypair) + { + char gripstr[40+1]; + + err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr); + if (err) + log_error ("can't get keygrip from FID 0x%04X: %s\n", + filelist[i].fid, gpg_strerror (err)); + else + { + sprintf (id_buf, "NKS-DF01.%04X", filelist[i].fid); + send_status_info (ctrl, "KEYPAIRINFO", + gripstr, 40, + id_buf, strlen (id_buf), + NULL, (size_t)0); + } + } + } + + return 0; +} + + + + +/* Read the certificate with id CERTID (as returned by learn_status in + the CERTINFO status lines) and return it in the freshly allocated + buffer put into CERT and the length of the certificate put into + CERTLEN. */ +static int +do_readcert (app_t app, const char *certid, + unsigned char **cert, size_t *certlen) +{ + int i, fid; + gpg_error_t err; + unsigned char *buffer; + const unsigned char *p; + size_t buflen, n; + int class, tag, constructed, ndef; + size_t totobjlen, objlen, hdrlen; + int rootca = 0; + + *cert = NULL; + *certlen = 0; + if (strncmp (certid, "NKS-DF01.", 9) ) + return gpg_error (GPG_ERR_INV_ID); + certid += 9; + if (!hexdigitp (certid) || !hexdigitp (certid+1) + || !hexdigitp (certid+2) || !hexdigitp (certid+3) + || certid[4]) + return gpg_error (GPG_ERR_INV_ID); + fid = xtoi_4 (certid); + for (i=0; filelist[i].fid; i++) + if ((filelist[i].certtype || filelist[i].iskeypair) + && filelist[i].fid == fid) + break; + if (!filelist[i].fid) + return gpg_error (GPG_ERR_NOT_FOUND); + + /* If the requested objects is a plain public key, redirect it to + the corresponding certificate. The whole system is a bit messy + becuase we sometime use the key directly or let the caller + retrieve the key from the certificate. The valid point behind + that is to support not-yet stored certificates. */ + if (filelist[i].iskeypair) + fid = filelist[i].iskeypair; + + + /* Read the entire file. fixme: This could be optimized by first + reading the header to figure out how long the certificate + actually is. */ + err = iso7816_select_file (app->slot, fid, 0, NULL, NULL); + if (err) + { + log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err)); + return err; + } + + err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen); + if (err) + { + log_error ("error reading certificate from FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + return err; + } + + if (!buflen || *buffer == 0xff) + { + log_info ("no certificate contained in FID 0x%04X\n", fid); + err = gpg_error (GPG_ERR_NOT_FOUND); + goto leave; + } + + /* Now figure something out about the object. */ + p = buffer; + n = buflen; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed ) + ; + else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed ) + rootca = 1; + else + return gpg_error (GPG_ERR_INV_OBJ); + totobjlen = objlen + hdrlen; + assert (totobjlen <= buflen); + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + + if (rootca) + ; + else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed) + { + const unsigned char *save_p; + + /* The certificate seems to be contained in a userCertificate + container. Skip this and assume the following sequence is + the certificate. */ + if (n < objlen) + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto leave; + } + p += objlen; + n -= objlen; + save_p = p; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) ) + return gpg_error (GPG_ERR_INV_OBJ); + totobjlen = objlen + hdrlen; + assert (save_p + totobjlen <= buffer + buflen); + memmove (buffer, save_p, totobjlen); + } + + *cert = buffer; + buffer = NULL; + *certlen = totobjlen; + + leave: + xfree (buffer); + return err; +} + + + +/* Select the NKS 2.0 application on the card in SLOT. */ +int +app_select_nks (APP app) +{ + static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 }; + int slot = app->slot; + int rc; + + rc = iso7816_select_application (slot, aid, sizeof aid); + if (!rc) + { + app->apptype = "NKS"; + + app->fnc.learn_status = do_learn_status; + app->fnc.readcert = do_readcert; + app->fnc.getattr = NULL; + app->fnc.setattr = NULL; + app->fnc.genkey = NULL; + app->fnc.sign = NULL; + app->fnc.auth = NULL; + app->fnc.decipher = NULL; + app->fnc.change_pin = NULL; + app->fnc.check_pin = NULL; + } + + return rc; +} + + diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 8f9a303fe..75e3e299e 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1,5 +1,5 @@ /* app-openpgp.c - The OpenPGP card application. - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -42,7 +42,7 @@ #include "iso7816.h" #include "app-common.h" - +#include "tlv.h" static struct { @@ -80,94 +80,6 @@ static unsigned long convert_sig_counter_value (const unsigned char *value, static unsigned long get_sig_counter (APP app); -/* Locate a TLV encoded data object in BUFFER of LENGTH and - return a pointer to value as well as its length in NBYTES. Return - NULL if it was not found. Note, that the function does not check - whether the value fits into the provided buffer. - - FIXME: Move this to an extra file, it is mostly duplicated from card.c. -*/ -static const unsigned char * -find_tlv (const unsigned char *buffer, size_t length, - int tag, size_t *nbytes, int nestlevel) -{ - const unsigned char *s = buffer; - size_t n = length; - size_t len; - int this_tag; - int composite; - - for (;;) - { - buffer = s; - if (n < 2) - return NULL; /* buffer definitely too short for tag and length. */ - if (!*s || *s == 0xff) - { /* Skip optional filler between TLV objects. */ - s++; - n--; - continue; - } - composite = !!(*s & 0x20); - if ((*s & 0x1f) == 0x1f) - { /* more tag bytes to follow */ - s++; - n--; - if (n < 2) - return NULL; /* buffer definitely too short for tag and length. */ - if ((*s & 0x1f) == 0x1f) - return NULL; /* We support only up to 2 bytes. */ - this_tag = (s[-1] << 8) | (s[0] & 0x7f); - } - else - this_tag = s[0]; - len = s[1]; - s += 2; n -= 2; - if (len < 0x80) - ; - else if (len == 0x81) - { /* One byte length follows. */ - if (!n) - return NULL; /* we expected 1 more bytes with the length. */ - len = s[0]; - s++; n--; - } - else if (len == 0x82) - { /* Two byte length follows. */ - if (n < 2) - return NULL; /* we expected 2 more bytes with the length. */ - len = (s[0] << 8) | s[1]; - s += 2; n -= 2; - } - else - return NULL; /* APDU limit is 65535, thus it does not make - sense to assume longer length fields. */ - - if (composite && nestlevel < 100) - { /* Dive into this composite DO after checking for too deep - nesting. */ - const unsigned char *tmp_s; - size_t tmp_len; - - tmp_s = find_tlv (s, len, tag, &tmp_len, nestlevel+1); - if (tmp_s) - { - *nbytes = tmp_len; - return tmp_s; - } - } - - if (this_tag == tag) - { - *nbytes = len; - return s; - } - if (len > n) - return NULL; /* buffer too short to skip to the next tag. */ - s += len; n -= len; - } -} - /* Get the DO identified by TAG from the card in SLOT and return a buffer with its content in RESULT and NBYTES. The return value is @@ -197,7 +109,7 @@ get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes) { const unsigned char *s; - s = find_tlv (buffer, buflen, tag, &valuelen, 0); + s = find_tlv (buffer, buflen, tag, &valuelen); if (!s) value = NULL; /* not found */ else if (valuelen > buflen - (s - buffer)) @@ -271,7 +183,7 @@ dump_all_do (int slot) if (j==i || data_objects[i].tag != data_objects[j].get_from) continue; value = find_tlv (buffer, buflen, - data_objects[j].tag, &valuelen, 0); + data_objects[j].tag, &valuelen); if (!value) ; /* not found */ else if (valuelen > buflen - (value - buffer)) @@ -443,7 +355,7 @@ do_getattr (APP app, CTRL ctrl, const char *name) { /* The serial number is very special. We could have used the AID DO to retrieve it, but we have it already in the app - context and the stanmp argument is required anyway which we + context and the stamp argument is required anyway which we can't by other means. The AID DO is available anyway but not hex formatted. */ char *serial; @@ -772,7 +684,7 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, log_error ("error reading application data\n"); return gpg_error (GPG_ERR_GENERAL); } - fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0); + fpr = find_tlv (buffer, buflen, 0x00C5, &n); if (!fpr || n != 60) { rc = gpg_error (GPG_ERR_GENERAL); @@ -820,7 +732,7 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, } log_info ("key generation completed (%d seconds)\n", (int)(time (NULL) - start_at)); - keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0); + keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen); if (!keydata) { rc = gpg_error (GPG_ERR_CARD); @@ -828,7 +740,7 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, goto leave; } - m = find_tlv (keydata, keydatalen, 0x0081, &mlen, 0); + m = find_tlv (keydata, keydatalen, 0x0081, &mlen); if (!m) { rc = gpg_error (GPG_ERR_CARD); @@ -838,7 +750,7 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, /* log_printhex ("RSA n:", m, mlen); */ send_key_data (ctrl, "n", m, mlen); - e = find_tlv (keydata, keydatalen, 0x0082, &elen, 0); + e = find_tlv (keydata, keydatalen, 0x0082, &elen); if (!e) { rc = gpg_error (GPG_ERR_CARD); @@ -913,7 +825,7 @@ compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr) log_error ("error reading application data\n"); return gpg_error (GPG_ERR_GENERAL); } - fpr = find_tlv (buffer, buflen, 0x00C5, &n, 0); + fpr = find_tlv (buffer, buflen, 0x00C5, &n); if (!fpr || n != 60) { xfree (buffer); @@ -1268,7 +1180,7 @@ do_check_pin (APP app, const char *keyidstr, /* Select the OpenPGP application on the card in SLOT. This function must be used before any other OpenPGP application functions. */ int -app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) +app_select_openpgp (APP app) { static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 }; int slot = app->slot; @@ -1280,10 +1192,17 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) rc = iso7816_select_application (slot, aid, sizeof aid); if (!rc) { + app->apptype = "OPENPGP"; + app->did_chv1 = 0; app->did_chv2 = 0; app->did_chv3 = 0; + /* The OpenPGP card returns the serial number as part of the + AID; because we prefer to use OpenPGP serial numbers, we + repalce a possibly already set one from a EF.GDO with this + one. Note, that for current OpenPGP cards, no EF.GDO exists + and thus it won't matter at all. */ rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); if (rc) goto leave; @@ -1293,15 +1212,12 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) log_printhex ("", buffer, buflen); } - if (sn) - { - *sn = buffer; - *snlen = buflen; - app->card_version = buffer[6] << 8; - app->card_version |= buffer[7]; - } - else - xfree (buffer); + app->card_version = buffer[6] << 8; + app->card_version |= buffer[7]; + xfree (app->serialno); + app->serialno = buffer; + app->serialnolen = buflen; + buffer = NULL; relptr = get_one_do (app->slot, 0x00C4, &buffer, &buflen); if (!relptr) @@ -1316,6 +1232,7 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) dump_all_do (slot); app->fnc.learn_status = do_learn_status; + app->fnc.readcert = NULL; app->fnc.getattr = do_getattr; app->fnc.setattr = do_setattr; app->fnc.genkey = do_genkey; @@ -1498,7 +1415,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, goto leave; } - keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen, 0); + keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen); if (!keydata) { log_error ("response does not contain the public key data\n"); @@ -1506,7 +1423,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, goto leave; } - a = find_tlv (keydata, keydatalen, 0x0081, &alen, 0); + a = find_tlv (keydata, keydatalen, 0x0081, &alen); if (!a) { log_error ("response does not contain the RSA modulus\n"); @@ -1517,7 +1434,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, *m = xmalloc (alen); memcpy (*m, a, alen); - a = find_tlv (keydata, keydatalen, 0x0082, &alen, 0); + a = find_tlv (keydata, keydatalen, 0x0082, &alen); if (!e) { log_error ("response does not contain the RSA public exponent\n"); diff --git a/scd/app.c b/scd/app.c index 1f142ea32..6ac18272b 100644 --- a/scd/app.c +++ b/scd/app.c @@ -29,49 +29,78 @@ #include "app-common.h" #include "apdu.h" #include "iso7816.h" -#include "dynload.h" +#include "tlv.h" -static char *default_reader_port; -void -app_set_default_reader_port (const char *portstr) -{ - xfree (default_reader_port); - default_reader_port = portstr? xstrdup (portstr): NULL; -} - - -/* The select the best fitting application and return a context. - Returns NULL if no application was found or no card is present. */ +/* If called with NAME as NULL, select the best fitting application + and return a context; otherwise select the application with NAME + and return a context. SLOT identifies the reader device. Returns + NULL if no application was found or no card is present. */ APP -select_application (void) +select_application (ctrl_t ctrl, int slot, const char *name) { - int slot; int rc; APP app; - - slot = apdu_open_reader (default_reader_port); - if (slot == -1) - { - log_error ("card reader not available\n"); - return NULL; - } + unsigned char *result = NULL; + size_t resultlen; app = xtrycalloc (1, sizeof *app); if (!app) { rc = out_of_core (); log_info ("error allocating context: %s\n", gpg_strerror (rc)); - /*apdu_close_reader (slot);*/ return NULL; } - app->slot = slot; - rc = app_select_openpgp (app, &app->serialno, &app->serialnolen); + + /* Fixme: We should now first check whether a card is at all + present. */ + + /* Try to read the GDO file first to get a default serial number. */ + rc = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL); + if (!rc) + rc = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL); + if (!rc) + rc = iso7816_read_binary (slot, 0, 0, &result, &resultlen); + if (!rc) + { + size_t n; + const unsigned char *p; + + p = find_tlv (result, resultlen, 0x5A, &n); + if (p && n && n >= (resultlen - (p - result))) + { + /* The GDO file is pretty short, thus we simply reuse it for + storing the serial number. */ + memmove (result, p, n); + app->serialno = result; + app->serialnolen = n; + } + else + xfree (result); + result = NULL; + } + + + rc = gpg_error (GPG_ERR_NOT_FOUND); + + if (!name || !strcmp (name, "openpgp")) + rc = app_select_openpgp (app); + if (rc && (!name || !strcmp (name, "nks"))) + rc = app_select_nks (app); + if (rc && (!name || !strcmp (name, "dinsig"))) + rc = app_select_dinsig (app); + if (rc && name) + rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + if (rc) { -/* apdu_close_reader (slot); */ - log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + if (name) + log_info ("can't select application `%s': %s\n", + name, gpg_strerror (rc)); + else + log_info ("no supported card application found: %s\n", + gpg_strerror (rc)); xfree (app); return NULL; } @@ -81,23 +110,36 @@ select_application (void) } +void +release_application (app_t app) +{ + if (!app) + return; + + xfree (app->serialno); + xfree (app); +} + + /* Retrieve the serial number and the time of the last update of the card. The serial number is returned as a malloced string (hex encoded) in SERIAL and the time of update is returned in STAMP. If no update time is available the returned value is 0. Caller must - free SERIAL unless the function returns an error. */ + free SERIAL unless the function returns an error. If STAMP is not + of interest, NULL may be passed. */ int -app_get_serial_and_stamp (APP app, char **serial, time_t *stamp) +app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp) { unsigned char *buf, *p; int i; - if (!app || !serial || !stamp) + if (!app || !serial) return gpg_error (GPG_ERR_INV_VALUE); *serial = NULL; - *stamp = 0; /* not available */ + if (stamp) + *stamp = 0; /* not available */ buf = xtrymalloc (app->serialnolen * 2 + 1); if (!buf) @@ -121,10 +163,34 @@ app_write_learn_status (APP app, CTRL ctrl) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.learn_status) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + if (app->apptype) + send_status_info (ctrl, "APPTYPE", + app->apptype, strlen (app->apptype), NULL, 0); + return app->fnc.learn_status (app, ctrl); } +/* Read the certificate with id CERTID (as returned by learn_status in + the CERTINFO status lines) and return it in the freshly allocated + buffer put into CERT and the length of the certificate put into + CERTLEN. */ +int +app_readcert (app_t app, const char *certid, + unsigned char **cert, size_t *certlen) +{ + if (!app) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.readcert) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + return app->fnc.readcert (app, certid, cert, certlen); +} + + /* Perform a GETATTR operation. */ int app_getattr (APP app, CTRL ctrl, const char *name) @@ -317,8 +383,3 @@ app_check_pin (APP app, const char *keyidstr, return rc; } - - - - - diff --git a/scd/card.c b/scd/card.c index 95149074d..53c89f3a4 100644 --- a/scd/card.c +++ b/scd/card.c @@ -53,7 +53,10 @@ map_sc_err (int rc) #endif default: e = GPG_ERR_CARD; break; } - return gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, e); + /* It does not make much sense to further distingusih the error + source between OpenSC and SCD. Thus we use SCD as source + here. */ + return gpg_err_make (GPG_ERR_SOURCE_SCD, e); } /* Get the keygrip from CERT, return 0 on success */ @@ -462,6 +465,7 @@ card_enum_keypairs (CARD card, int idx, 100 := Regular X.509 cert 101 := Trusted X.509 cert 102 := Useful X.509 cert + 110 := Root CA cert (DINSIG) */ int card_enum_certs (CARD card, int idx, char **certid, int *certtype) diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 936672cc6..f910722eb 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -98,6 +98,11 @@ # include "scdaemon.h" # endif +/* Disable all debgging output for now. */ +#undef DBG_CARD_IO +#define DBG_CARD_IO 0 + + # define DEBUGOUT(t) do { if (DBG_CARD_IO) \ log_debug (DRVNAME t); } while (0) # define DEBUGOUT_1(t,a) do { if (DBG_CARD_IO) \ @@ -944,7 +949,9 @@ ccid_transceive (ccid_driver_t handle, { if (n > maxresplen) { - DEBUGOUT ("provided buffer too short for received data\n"); + DEBUGOUT_2 ("provided buffer too short for received data " + "(%u/%u)\n", + (unsigned int)n, (unsigned int)maxresplen); return -1; } diff --git a/scd/command.c b/scd/command.c index bc3132a0b..9e571f228 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1,5 +1,5 @@ /* command.c - SCdaemon command handler - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -31,6 +31,7 @@ #include "scdaemon.h" #include <ksba.h> #include "app-common.h" +#include "apdu.h" /* Required for apdu_*_reader (). */ /* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */ #define MAXLEN_PIN 100 @@ -90,17 +91,34 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) function returns an Assuan error, so don't map the error a second time */ static AssuanError -open_card (CTRL ctrl) +open_card (CTRL ctrl, const char *apptype) { + int slot; + if (ctrl->app_ctx) return 0; /* Already initialized for one specific application. */ if (ctrl->card_ctx) return 0; /* Already initialized using a card context. */ - ctrl->app_ctx = select_application (); + slot = apdu_open_reader (opt.reader_port); + if (slot != -1) + { + ctrl->app_ctx = select_application (ctrl, slot, apptype); + if (!ctrl->app_ctx) + apdu_close_reader (slot); + } if (!ctrl->app_ctx) { /* No application found - fall back to old mode. */ - int rc = card_open (&ctrl->card_ctx); + /* Note that we should rework the old code to use the + application paradigma too. */ + int rc; + + /* If an APPTYPE was requested and it is not pkcs#15, we return + an error here. */ + if (apptype && !(!strcmp (apptype, "P15") || !strcmp (apptype, "p15"))) + rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + else + rc = card_open (&ctrl->card_ctx); if (rc) return map_to_assuan_status (rc); } @@ -143,11 +161,17 @@ percent_plus_unescape (unsigned char *string) -/* SERIALNO +/* SERIALNO [APPTYPE] Return the serial number of the card using a status reponse. This functon should be used to check for the presence of a card. + If APPTYPE is given, an application of that type is selected and an + error is returned if the application is not supported or available. + The default is to auto-select the application using a hardwired + preference system. Note, that a future extension to this function + may allow to specify a list and order of applications to try. + This function is special in that it can be used to reset the card. Most other functions will return an error when a card change has been detected and the use of this function is therefore required. @@ -165,7 +189,7 @@ cmd_serialno (ASSUAN_CONTEXT ctx, char *line) char *serial; time_t stamp; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, *line? line:NULL))) return rc; if (ctrl->app_ctx) @@ -223,6 +247,7 @@ cmd_serialno (ASSUAN_CONTEXT ctx, char *line) 100 := Regular X.509 cert 101 := Trusted X.509 cert 102 := Useful X.509 cert + 110 := Root CA cert (DINSIG) For certain cards, more information will be returned: @@ -240,7 +265,7 @@ cmd_serialno (ASSUAN_CONTEXT ctx, char *line) S DISP-NAME <name_of_card_holder> The name of the card holder as stored on the card; percent - aescaping takes place, spaces are encoded as '+' + escaping takes place, spaces are encoded as '+' S PUBKEY-URL <url> @@ -254,7 +279,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) int rc = 0; int idx; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; /* Unless the force option is used we try a shortcut by identifying @@ -305,10 +330,15 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) free (serial_and_stamp); } - /* Return information about the certificates. */ - if (ctrl->app_ctx) - rc = -1; /* This information is not yet available for applications. */ - for (idx=0; !rc; idx++) + /* If we are using the modern application paradigma, let the + application print out its collection of useful status + information. */ + if (!rc && ctrl->app_ctx) + rc = app_write_learn_status (ctrl->app_ctx, ctrl); + + /* Return information about the certificates. FIXME: Move this into + an app-p15.c*/ + for (idx=0; !rc && !ctrl->app_ctx; idx++) { char *certid; int certtype; @@ -333,11 +363,9 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) if (rc == -1) rc = 0; - - /* Return information about the keys. */ - if (ctrl->app_ctx) - rc = -1; /* This information is not yet available for applications. */ - for (idx=0; !rc; idx++) + /* Return information about the keys. FIXME: Move this into an + app-p15.c */ + for (idx=0; !rc && !ctrl->app_ctx; idx++) { unsigned char keygrip[20]; char *keyid; @@ -346,7 +374,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid); if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid) { - /* this does happen with an incomplete personalized + /* This does happen with an incomplete personalized card; i.e. during the time we have stored the key on the card but not stored the certificate; probably becuase it has not yet been received back from the CA. Note that we @@ -383,10 +411,6 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) if (rc == -1) rc = 0; - if (!rc && ctrl->app_ctx) - rc = app_write_learn_status (ctrl->app_ctx, ctrl); - - return map_to_assuan_status (rc); } @@ -403,17 +427,24 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line) unsigned char *cert; size_t ncert; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; + line = xstrdup (line); /* Need a copy of the line. */ if (ctrl->app_ctx) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - - rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); - if (rc) { - log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); + rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); + if (rc) + log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); + } + else + { + rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); + if (rc) + log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); } + xfree (line); + line = NULL; if (!rc) { rc = assuan_send_data (ctx, cert, ncert); @@ -440,18 +471,26 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line) ksba_cert_t kc = NULL; ksba_sexp_t p; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; + line = xstrdup (line); /* Need a copy of the line. */ if (ctrl->app_ctx) - return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - - rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); - if (rc) { - log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); - goto leave; + rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); + if (rc) + log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); + } + else + { + rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); + if (rc) + log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); } + xfree (line); + line = NULL; + if (rc) + goto leave; rc = ksba_cert_new (&kc); if (rc) @@ -569,7 +608,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) size_t outdatalen; char *keyidstr; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; /* We have to use a copy of the key ID because the function may use @@ -619,7 +658,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) size_t outdatalen; char *keyidstr; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; if (!ctrl->app_ctx) @@ -665,7 +704,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) size_t outdatalen; char *keyidstr; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; keyidstr = xtrystrdup (line); @@ -718,7 +757,7 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line) int rc; char *keyword; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; keyword = line; @@ -757,7 +796,7 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line) size_t nbytes; char *line, *linebuf; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; /* We need to use a copy of LINE, because PIN_CB uses the same @@ -823,7 +862,7 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) line++; *line = 0; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; if (!ctrl->app_ctx) @@ -854,7 +893,7 @@ cmd_random (ASSUAN_CONTEXT ctx, char *line) return set_error (Parameter_Error, "number of requested bytes missing"); nbytes = strtoul (line, NULL, 0); - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; if (!ctrl->app_ctx) @@ -904,7 +943,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) line++; *line = 0; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; if (!ctrl->app_ctx) @@ -931,7 +970,7 @@ cmd_checkpin (ASSUAN_CONTEXT ctx, char *line) int rc; char *keyidstr; - if ((rc = open_card (ctrl))) + if ((rc = open_card (ctrl, NULL))) return rc; if (!ctrl->app_ctx) diff --git a/scd/iso7816.c b/scd/iso7816.c index f4aa18c6f..9a15ce953 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -51,6 +51,8 @@ #define CMD_INTERNAL_AUTHENTICATE 0x88 #define CMD_GENERATE_KEYPAIR 0x47 #define CMD_GET_CHALLENGE 0x84 +#define CMD_READ_BINARY 0xB0 +#define CMD_READ_RECORD 0xB2 static gpg_error_t map_sw (int sw) @@ -66,6 +68,8 @@ map_sw (int sw) case SW_USE_CONDITIONS: ec = GPG_ERR_USE_CONDITIONS; break; case SW_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break; case SW_BAD_PARAMETER: ec = GPG_ERR_INV_VALUE; break; + case SW_FILE_NOT_FOUND: ec = GPG_ERR_ENOENT; break; + case SW_RECORD_NOT_FOUND:ec= GPG_ERR_NOT_FOUND; break; case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; break; case SW_BAD_P0_P1: ec = GPG_ERR_INV_VALUE; break; case SW_INS_NOT_SUP: ec = GPG_ERR_CARD; break; @@ -91,18 +95,79 @@ map_sw (int sw) apdu_open_reader (), AID is a buffer of size AIDLEN holding the requested application ID. The function can't be used to enumerate AIDs and won't return the AID on success. The return value is 0 - for okay or GNUPG error code. Note that ISO error codes are + for okay or a GPG error code. Note that ISO error codes are internally mapped. */ gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen) { + static char const openpgp_aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 }; int sw; + int p1 = 0x0C; /* No FCI to be returned. */ + + if (aidlen == sizeof openpgp_aid + && !memcmp (aid, openpgp_aid, sizeof openpgp_aid)) + p1 = 0; /* The current openpgp cards don't allow 0x0c. */ - sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid); + sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, p1, aidlen, aid); return map_sw (sw); } +gpg_error_t +iso7816_select_file (int slot, int tag, int is_dir, + unsigned char **result, size_t *resultlen) +{ + int sw, p0, p1; + unsigned char tagbuf[2]; + + tagbuf[0] = (tag >> 8) & 0xff; + tagbuf[1] = tag & 0xff; + + if (result || resultlen) + { + *result = NULL; + *resultlen = 0; + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + else + { + p0 = (tag == 0x3F00)? 0: is_dir? 1:2; + p1 = 0x0c; /* No FC return. */ + sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, + p0, p1, 2, tagbuf ); + return map_sw (sw); + } + + return 0; +} + + +/* This is a private command currently only working for TCOS cards. */ +gpg_error_t +iso7816_list_directory (int slot, int list_dirs, + unsigned char **result, size_t *resultlen) +{ + int sw; + + if (!result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + sw = apdu_send (slot, 0x80, 0xAA, list_dirs? 1:2, 0, -1, NULL, + result, resultlen); + if (sw != SW_SUCCESS) + { + /* Make sure that pending buffers are released. */ + xfree (*result); + *result = NULL; + *resultlen = 0; + } + return map_sw (sw); +} + + + /* Perform a VERIFY command on SLOT using the card holder verification vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */ gpg_error_t @@ -381,3 +446,126 @@ iso7816_get_challenge (int slot, int length, unsigned char *buffer) return 0; } + +/* Perform a READ BINARY command requesting a maximum of NMAX bytes + from OFFSET. With NMAX = 0 the entire file is read. The result is + stored in a newly allocated buffer at the address passed by RESULT. + Returns the length of this data at the address of RESULTLEN. */ +gpg_error_t +iso7816_read_binary (int slot, size_t offset, size_t nmax, + unsigned char **result, size_t *resultlen) +{ + int sw; + unsigned char *buffer; + size_t bufferlen; + + if (!result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus + we check for this limit. */ + if (offset > 32767 || nmax > 254) + return gpg_error (GPG_ERR_INV_VALUE); + + do + { + buffer = NULL; + bufferlen = 0; + /* Fixme: Either the ccid driver of the TCOS cards have problems + with an Le of 0. */ + sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, + ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, + nmax? nmax : 254, &buffer, &bufferlen); + + if (sw != SW_SUCCESS && sw != SW_EOF_REACHED) + { + /* Make sure that pending buffers are released. */ + xfree (buffer); + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + if (*result) /* Need to extend the buffer. */ + { + unsigned char *p = xtryrealloc (*result, *resultlen + bufferlen); + if (!p) + { + gpg_error_t err = gpg_error_from_errno (errno); + xfree (buffer); + xfree (*result); + *result = NULL; + *resultlen = 0; + return err; + } + *result = p; + memcpy (*result + *resultlen, buffer, bufferlen); + *resultlen += bufferlen; + xfree (buffer); + buffer = NULL; + } + else /* Transfer the buffer into our result. */ + { + *result = buffer; + *resultlen = bufferlen; + } + offset += bufferlen; + if (offset > 32767) + break; /* We simply truncate the result for too large + files. */ + } + while (!nmax && sw != SW_EOF_REACHED); + + return 0; +} + +/* Perform a READ RECORD command. RECNO gives the record number to + read with 0 indicating the current record. RECCOUNT must be 1 (not + all cards support reading of more than one record). The result is + stored in a newly allocated buffer at the address passed by RESULT. + Returns the length of this data at the address of RESULTLEN. */ +gpg_error_t +iso7816_read_record (int slot, int recno, int reccount, + unsigned char **result, size_t *resultlen) +{ + int sw; + unsigned char *buffer; + size_t bufferlen; + + if (!result || !resultlen) + return gpg_error (GPG_ERR_INV_VALUE); + *result = NULL; + *resultlen = 0; + + /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus + we check for this limit. */ + if (recno < 0 || recno > 255 || reccount != 1) + return gpg_error (GPG_ERR_INV_VALUE); + + buffer = NULL; + bufferlen = 0; + /* Fixme: Either the ccid driver of the TCOS cards have problems + with an Le of 0. */ + sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD, + recno, + 0x04, + -1, NULL, + 254, &buffer, &bufferlen); + + if (sw != SW_SUCCESS && sw != SW_EOF_REACHED) + { + /* Make sure that pending buffers are released. */ + xfree (buffer); + xfree (*result); + *result = NULL; + *resultlen = 0; + return map_sw (sw); + } + *result = buffer; + *resultlen = bufferlen; + + return 0; +} + diff --git a/scd/iso7816.h b/scd/iso7816.h index 26b8d6aba..98e688693 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -27,6 +27,10 @@ gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen); +gpg_error_t iso7816_select_file (int slot, int tag, int is_dir, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_list_directory (int slot, int list_dirs, + unsigned char **result, size_t *resultlen); gpg_error_t iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen); gpg_error_t iso7816_change_reference_data (int slot, int chvno, @@ -56,5 +60,9 @@ gpg_error_t iso7816_read_public_key (int slot, gpg_error_t iso7816_get_challenge (int slot, int length, unsigned char *buffer); +gpg_error_t iso7816_read_binary (int slot, size_t offset, size_t nmax, + unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_read_record (int slot, int recno, int reccount, + unsigned char **result, size_t *resultlen); #endif /*ISO7816_H*/ diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c index b56b88590..78cb2acc8 100644 --- a/scd/sc-copykeys.c +++ b/scd/sc-copykeys.c @@ -165,7 +165,7 @@ main (int argc, char **argv ) /* FIXME: Use select_application. */ appbuf.slot = slot; - rc = app_select_openpgp (&appbuf, &appbuf.serialno, &appbuf.serialnolen); + rc = app_select_openpgp (&appbuf); if (rc) { log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc)); diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index ecd385690..acef86ead 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -24,6 +24,13 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <ctype.h> +#include <unistd.h> + +#ifdef HAVE_READLINE_READLINE_H +#include <readline/readline.h> +#include <readline/history.h> +#endif #define JNLIB_NEED_LOG_LOGV #include "scdaemon.h" @@ -32,17 +39,25 @@ #include "apdu.h" /* for open_reader */ #include "atr.h" #include "app-common.h" +#include "iso7816.h" #define _(a) (a) +#define CONTROL_D ('D' - 'A' + 1) + enum cmd_and_opt_values -{ oVerbose = 'v', +{ + oInteractive = 'i', + oVerbose = 'v', oReaderPort = 500, octapiDriver, oDebug, oDebugAll, + oDisableCCID, + + oGenRandom, aTest }; @@ -52,15 +67,27 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, "@Options:\n " }, + { oInteractive, "interactive", 0, "start in interactive explorer mode"}, { oVerbose, "verbose", 0, "verbose" }, { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"}, { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"}, + { oDisableCCID, "disable-ccid", 0, +#ifdef HAVE_LIBUSB + "do not use the internal CCID driver" +#else + "@" +#endif + }, { oDebug, "debug" ,4|16, "set debugging flags"}, { oDebugAll, "debug-all" ,0, "enable full debugging"}, { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"}, {0} }; + +static void interactive_shell (int slot); + + static const char * my_strusage (int level) { @@ -111,10 +138,8 @@ main (int argc, char **argv ) ARGPARSE_ARGS pargs; int slot, rc; const char *reader_port = NULL; - struct app_ctx_s appbuf; unsigned long gen_random = 0; - - memset (&appbuf, 0, sizeof appbuf); + int interactive = 0; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -143,7 +168,9 @@ main (int argc, char **argv ) case oDebugAll: opt.debug = ~0; break; case oReaderPort: reader_port = pargs.r.ret_str; break; case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; + case oDisableCCID: opt.disable_ccid = 1; break; case oGenRandom: gen_random = pargs.r.ret_ulong; break; + case oInteractive: interactive = 1; break; default : pargs.err = 2; break; } } @@ -151,7 +178,7 @@ main (int argc, char **argv ) exit(2); if (opt.verbose < 2) - opt.verbose = 2; /* hack to let select_openpgp print some info. */ + opt.verbose = 2; /* Hack to let select_openpgp print some info. */ if (argc) usage (1); @@ -167,40 +194,61 @@ main (int argc, char **argv ) log_error ("can't dump ATR: %s\n", gpg_strerror (rc)); } - appbuf.slot = slot; - rc = app_select_openpgp (&appbuf, NULL, NULL); - if (rc) - log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + if (interactive) + interactive_shell (slot); else { - appbuf.initialized = 1; - log_info ("openpgp application selected\n"); + struct app_ctx_s appbuf; - if (gen_random) + /* Fixme: We better use app.c directly. */ + memset (&appbuf, 0, sizeof appbuf); + appbuf.slot = slot; + rc = app_select_openpgp (&appbuf); + if (rc) { - size_t nbytes; - unsigned char *buffer; - - buffer = xmalloc (4096); - do + log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + memset (&appbuf, 0, sizeof appbuf); + appbuf.slot = slot; + rc = app_select_dinsig (&appbuf); + if (rc) + log_info ("selecting dinsig failed: %s\n", gpg_strerror (rc)); + else { - nbytes = gen_random > 4096? 4096 : gen_random; - rc = app_get_challenge (&appbuf, nbytes, buffer); - if (rc) - log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc)); - else + appbuf.initialized = 1; + log_info ("dinsig application selected\n"); + } + } + else + { + appbuf.initialized = 1; + log_info ("openpgp application selected\n"); + + if (gen_random) + { + size_t nbytes; + unsigned char *buffer; + + buffer = xmalloc (4096); + do { - if (fwrite (buffer, nbytes, 1, stdout) != 1) - log_error ("writing to stdout failed: %s\n", - strerror (errno)); - gen_random -= nbytes; + nbytes = gen_random > 4096? 4096 : gen_random; + rc = app_get_challenge (&appbuf, nbytes, buffer); + if (rc) + log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc)); + else + { + if (fwrite (buffer, nbytes, 1, stdout) != 1) + log_error ("writing to stdout failed: %s\n", + strerror (errno)); + gen_random -= nbytes; + } } + while (gen_random && !log_get_errorcount (0)); + xfree (buffer); } - while (gen_random && !log_get_errorcount (0)); - xfree (buffer); } } - + return log_get_errorcount (0)? 2:0; } @@ -211,3 +259,377 @@ send_status_info (CTRL ctrl, const char *keyword, ...) { /* DUMMY */ } + + + +/* Dump BUFFER of length NBYTES in a nicely human readable format. */ +static void +dump_buffer (const unsigned char *buffer, size_t nbytes) +{ + int i; + + while (nbytes) + { + for (i=0; i < 16 && i < nbytes; i++) + printf ("%02X%s ", buffer[i], i==8? " ":""); + for (; i < 16; i++) + printf (" %s ", i==8? " ":""); + putchar (' '); + putchar (' '); + for (i=0; i < 16 && i < nbytes; i++) + if (isprint (buffer[i])) + putchar (buffer[i]); + else + putchar ('.'); + nbytes -= i; + buffer += i; + for (; i < 16; i++) + putchar (' '); + putchar ('\n'); + } +} + + +static void +dump_or_store_buffer (const char *arg, + const unsigned char *buffer, size_t nbytes) +{ + const char *s = strchr (arg, '>'); + int append; + FILE *fp; + + if (!s) + { + dump_buffer (buffer, nbytes); + return; + } + if ((append = (*++s == '>'))) + s++; + fp = fopen (s, append? "ab":"wb"); + if (!fp) + { + log_error ("failed to create `%s': %s\n", s, strerror (errno)); + return; + } + if (nbytes && fwrite (buffer, nbytes, 1, fp) != 1) + log_error ("failed to write to `%s': %s\n", s, strerror (errno)); + if (fclose (fp)) + log_error ("failed to close `%s': %s\n", s, strerror (errno)); +} + + +/* Convert STRING into a a newly allocated buffer and return the + length of the buffer in R_LENGTH. Detect xx:xx:xx... sequence and + unhexify that one. */ +static unsigned char * +pin_to_buffer (const char *string, size_t *r_length) +{ + unsigned char *buffer = xmalloc (strlen (string)+1); + const char *s; + size_t n; + + for (s=string, n=0; *s; s += 3) + { + if (hexdigitp (s) && hexdigitp (s+1) && (s[2]==':'||!s[2])) + { + buffer[n++] = xtoi_2 (s); + if (!s[2]) + break; + } + else + { + memcpy (buffer, string, strlen (string)); + *r_length = strlen (string); + return buffer; + } + } + *r_length = n; + return buffer; +} + + +static char * +read_line (int use_readline, char *prompt) +{ + static char buf[256]; + +#ifdef HAVE_READLINE + if (use_readline) + { + char *line = readline (prompt); + if (line) + trim_spaces (line); + if (line && strlen (line) > 2 ) + add_history (line); + return line; + } +#endif + /* Either we don't have readline or we are not running + interactively */ +#ifndef HAVE_READLINE + printf ("%s", prompt ); +#endif + fflush(stdout); + if (!fgets(buf, sizeof(buf), stdin)) + return NULL; + if (!strlen(buf)) + return NULL; + if (buf[strlen (buf)-1] == '\n') + buf[strlen (buf)-1] = 0; + trim_spaces (buf); + return buf; +} + +/* Run a shell for interactive exploration of the card. */ +static void +interactive_shell (int slot) +{ + enum cmdids + { + cmdNOP = 0, + cmdQUIT, cmdHELP, + cmdSELECT, + cmdCHDIR, + cmdLS, + cmdAPP, + cmdREAD, + cmdREADREC, + cmdDEBUG, + cmdVERIFY, + cmdCHANGEREF, + + cmdINVCMD + }; + static struct + { + const char *name; + enum cmdids id; + const char *desc; + } cmds[] = { + { "quit" , cmdQUIT , "quit this menu" }, + { "q" , cmdQUIT , NULL }, + { "help" , cmdHELP , "show this help" }, + { "?" , cmdHELP , NULL }, + { "debug" , cmdDEBUG, "set debugging flags" }, + { "select" , cmdSELECT, "select file (EF)" }, + { "s" , cmdSELECT, NULL }, + { "chdir" , cmdCHDIR, "change directory (select DF)"}, + { "cd" , cmdCHDIR, NULL }, + { "ls" , cmdLS, "list directory (some cards only)"}, + { "app" , cmdAPP, "select application"}, + { "read" , cmdREAD, "read binary" }, + { "rb" , cmdREAD, NULL }, + { "readrec", cmdREADREC, "read record(s)" }, + { "rr" , cmdREADREC, NULL }, + { "verify" , cmdVERIFY, "verify CHVNO PIN" }, + { "ver" , cmdVERIFY, NULL }, + { "changeref", cmdCHANGEREF, "change reference data" }, + { NULL, cmdINVCMD } + }; + enum cmdids cmd = cmdNOP; + int use_readline = isatty (fileno(stdin)); + char *line; + gpg_error_t err = 0; + unsigned char *result = NULL; + size_t resultlen; + +#ifdef HAVE_READLINE + if (use_readline) + using_history (); +#endif + + for (;;) + { + int arg_number; + const char *arg_string = ""; + const char *arg_next = ""; + char *p; + int i; + + if (err) + printf ("command failed: %s\n", gpg_strerror (err)); + err = 0; + xfree (result); + result = NULL; + + printf ("\n"); + do + { + line = read_line (use_readline, "cmd> "); + } + while ( line && *line == '#' ); + + arg_number = 0; + if (!line || *line == CONTROL_D) + cmd = cmdQUIT; + else if (!*line) + cmd = cmdNOP; + else { + if ((p=strchr (line,' '))) + { + char *endp; + + *p++ = 0; + trim_spaces (line); + trim_spaces (p); + arg_number = strtol (p, &endp, 0); + arg_string = p; + if (endp != p) + { + arg_next = endp; + while ( spacep (arg_next) ) + arg_next++; + } + } + + for (i=0; cmds[i].name; i++ ) + if (!ascii_strcasecmp (line, cmds[i].name )) + break; + + cmd = cmds[i].id; + } + + switch (cmd) + { + case cmdHELP: + for (i=0; cmds[i].name; i++ ) + if (cmds[i].desc) + printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); + break; + + case cmdQUIT: + goto leave; + + case cmdNOP: + break; + + case cmdDEBUG: + if (!*arg_string) + opt.debug = opt.debug? 0 : 2048; + else + opt.debug = arg_number; + break; + + case cmdSELECT: + err = iso7816_select_file (slot, arg_number, 0, NULL, NULL); + break; + + case cmdCHDIR: + err = iso7816_select_file (slot, arg_number, 1, NULL, NULL); + break; + + case cmdLS: + err = iso7816_list_directory (slot, 1, &result, &resultlen); + if (!err || gpg_err_code (err) == GPG_ERR_ENOENT) + err = iso7816_list_directory (slot, 0, &result, &resultlen); + /* FIXME: Do something with RESULT. */ + break; + + case cmdAPP: + { + app_t app; + + app = select_application (NULL, slot, *arg_string? arg_string:NULL); + if (app) + { + char *sn; + + app_get_serial_and_stamp (app, &sn, NULL); + log_info ("application `%s' ready; sn=%s\n", + app->apptype?app->apptype:"?", sn? sn:"[none]"); + release_application (app); + } + } + break; + + case cmdREAD: + err = iso7816_read_binary (slot, 0, 0, &result, &resultlen); + if (!err) + dump_or_store_buffer (arg_string, result, resultlen); + break; + + case cmdREADREC: + if (*arg_string == '*' && (!arg_string[1] || arg_string[1] == ' ')) + { + /* Fixme: Can't write to a file yet. */ + for (i=1, err=0; !err; i++) + { + xfree (result); result = NULL; + err = iso7816_read_record (slot, i, 1, &result, &resultlen); + if (!err) + dump_buffer (result, resultlen); + } + if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) + err = 0; + } + else + { + err = iso7816_read_record (slot, arg_number, 1, + &result, &resultlen); + if (!err) + dump_or_store_buffer (arg_string, result, resultlen); + } + break; + + case cmdVERIFY: + if (arg_number < 0 || arg_number > 255 || (arg_number & 127) > 31) + printf ("error: invalid CHVNO\n"); + else + { + unsigned char *pin; + size_t pinlen; + + pin = pin_to_buffer (arg_next, &pinlen); + err = iso7816_verify (slot, arg_number, pin, pinlen); + xfree (pin); + } + break; + + case cmdCHANGEREF: + { + const char *newpin = arg_next; + + while ( *newpin && !spacep (newpin) ) + newpin++; + while ( spacep (newpin) ) + newpin++; + + if (arg_number < 0 || arg_number > 255 || (arg_number & 127) > 31) + printf ("error: invalid CHVNO\n"); + else if (!*arg_next || !*newpin || newpin == arg_next) + printf ("usage: changeref CHVNO OLDPIN NEWPIN\n"); + else + { + char *oldpin = xstrdup (arg_next); + unsigned char *oldpin_buf, *newpin_buf; + size_t oldpin_len, newpin_len; + + for (p=oldpin; *p && !spacep (p); p++ ) + ; + *p = 0; + oldpin_buf = pin_to_buffer (oldpin, &oldpin_len); + newpin_buf = pin_to_buffer (newpin, &newpin_len); + + err = iso7816_change_reference_data (slot, arg_number, + oldpin_buf, oldpin_len, + newpin_buf, newpin_len); + + xfree (newpin_buf); + xfree (oldpin_buf); + xfree (oldpin); + } + } + break; + + case cmdINVCMD: + default: + printf ("\n"); + printf ("Invalid command (try \"help\")\n"); + break; + } /* End command switch. */ + } /* End of main menu loop. */ + + leave: + ; +} + diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 91ac93227..c6652c8dc 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -100,7 +100,7 @@ static ARGPARSE_OPTS opts[] = { { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ct-API driver")}, { opcscDriver, "pcsc-driver", 2, N_("NAME|use NAME as PC/SC driver")}, - { oDisableCCID, "disable-ccidc", 0, + { oDisableCCID, "disable-ccid", 0, #ifdef HAVE_LIBUSB N_("do not use the internal CCID driver") #else @@ -397,7 +397,7 @@ main (int argc, char **argv ) case oServer: pipe_server = 1; break; case oDaemon: is_daemon = 1; break; - case oReaderPort: app_set_default_reader_port (pargs.r.ret_str); break; + case oReaderPort: opt.reader_port = pargs.r.ret_str; break; case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break; case oDisableCCID: opt.disable_ccid = 1; break; diff --git a/scd/scdaemon.h b/scd/scdaemon.h index e13377af7..2bbf271da 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -55,6 +55,7 @@ struct { const char *homedir; /* configuration directory name */ const char *ctapi_driver; /* Library to access the ctAPI. */ const char *pcsc_driver; /* Library to access the PC/SC system. */ + const char *reader_port; /* NULL or reder port to use. */ int disable_opensc; /* Disable the use of the OpenSC framework. */ int disable_ccid; /* Disable the use of the internal CCID driver. */ int allow_admin; /* Allow the use of admin commands for certain @@ -96,8 +97,10 @@ struct server_control_s { }; typedef struct server_control_s *CTRL; +typedef struct server_control_s *ctrl_t; typedef struct card_ctx_s *CARD; typedef struct app_ctx_s *APP; +typedef struct app_ctx_s *app_t; /*-- scdaemon.c --*/ void scd_exit (int rc); diff --git a/scd/tlv.c b/scd/tlv.c new file mode 100644 index 000000000..dbcd24546 --- /dev/null +++ b/scd/tlv.c @@ -0,0 +1,219 @@ +/* tlv.c - Tag-Length-Value Utilities + * Copyright (C) 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include <gpg-error.h> + +#include "tlv.h" + +static const unsigned char * +do_find_tlv (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes, int nestlevel) +{ + const unsigned char *s = buffer; + size_t n = length; + size_t len; + int this_tag; + int composite; + + for (;;) + { + buffer = s; + if (n < 2) + return NULL; /* Buffer definitely too short for tag and length. */ + if (!*s || *s == 0xff) + { /* Skip optional filler between TLV objects. */ + s++; + n--; + continue; + } + composite = !!(*s & 0x20); + if ((*s & 0x1f) == 0x1f) + { /* more tag bytes to follow */ + s++; + n--; + if (n < 2) + return NULL; /* buffer definitely too short for tag and length. */ + if ((*s & 0x1f) == 0x1f) + return NULL; /* We support only up to 2 bytes. */ + this_tag = (s[-1] << 8) | (s[0] & 0x7f); + } + else + this_tag = s[0]; + len = s[1]; + s += 2; n -= 2; + if (len < 0x80) + ; + else if (len == 0x81) + { /* One byte length follows. */ + if (!n) + return NULL; /* we expected 1 more bytes with the length. */ + len = s[0]; + s++; n--; + } + else if (len == 0x82) + { /* Two byte length follows. */ + if (n < 2) + return NULL; /* We expected 2 more bytes with the length. */ + len = (s[0] << 8) | s[1]; + s += 2; n -= 2; + } + else + return NULL; /* APDU limit is 65535, thus it does not make + sense to assume longer length fields. */ + + if (composite && nestlevel < 100) + { /* Dive into this composite DO after checking for a too deep + nesting. */ + const unsigned char *tmp_s; + size_t tmp_len; + + tmp_s = do_find_tlv (s, len, tag, &tmp_len, nestlevel+1); + if (tmp_s) + { + *nbytes = tmp_len; + return tmp_s; + } + } + + if (this_tag == tag) + { + *nbytes = len; + return s; + } + if (len > n) + return NULL; /* Buffer too short to skip to the next tag. */ + s += len; n -= len; + } +} + + +/* Locate a TLV encoded data object in BUFFER of LENGTH and + return a pointer to value as well as its length in NBYTES. Return + NULL if it was not found. Note, that the function does not check + whether the value fits into the provided buffer. */ +const unsigned char * +find_tlv (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes) +{ + return do_find_tlv (buffer, length, tag, nbytes, 0); +} + + + + +/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag + and the length part from the TLV triplet. Update BUFFER and SIZE + on success. */ +gpg_error_t +parse_ber_header (unsigned char const **buffer, size_t *size, + int *r_class, int *r_tag, + int *r_constructed, int *r_ndef, + size_t *r_length, size_t *r_nhdr) +{ + int c; + unsigned long tag; + const unsigned char *buf = *buffer; + size_t length = *size; + + *r_ndef = 0; + *r_length = 0; + *r_nhdr = 0; + + /* Get the tag. */ + if (!length) + return gpg_error (GPG_ERR_EOF); + c = *buf++; length--; ++*r_nhdr; + + *r_class = (c & 0xc0) >> 6; + *r_constructed = !!(c & 0x20); + tag = c & 0x1f; + + if (tag == 0x1f) + { + tag = 0; + do + { + /* Simple check against overflow. We limit our maximim tag + value more than needed but that should not be a problem + because I have nver encountered such large value. We + assume at least 32 bit integers. */ + if (tag > (1 << 24)) + return gpg_error (GPG_ERR_TOO_LARGE); + tag <<= 7; + if (!length) + return gpg_error (GPG_ERR_EOF); + c = *buf++; length--; ++*r_nhdr; + tag |= c & 0x7f; + + } + while (c & 0x80); + } + *r_tag = tag; + + /* Get the length. */ + if (!length) + return gpg_error (GPG_ERR_EOF); + c = *buf++; length--; ++*r_nhdr; + + if ( !(c & 0x80) ) + *r_length = c; + else if (c == 0x80) + *r_ndef = 1; + else if (c == 0xff) + return gpg_error (GPG_ERR_BAD_BER); + else + { + unsigned long len = 0; + int count = c & 0x7f; + + for (; count; count--) + { + /* Simple check against overflow. We limit our maximim + length more than needed but that should not be a problem + because I have never encountered such large value and + well they are managed in memory and thus we would run + into memory problems anyway. We assume at least 32 bit + integers. */ + if (len > (1 << 24)) + return gpg_error (GPG_ERR_TOO_LARGE); + len <<= 8; + if (!length) + return gpg_error (GPG_ERR_EOF); + c = *buf++; length--; ++*r_nhdr; + len |= c & 0xff; + } + *r_length = len; + } + + /* Without this kludge some example certs can't be parsed. */ + if (*r_class == CLASS_UNIVERSAL && !*r_tag) + *r_length = 0; + + *buffer = buf; + *size = length; + return 0; +} diff --git a/scd/tlv.h b/scd/tlv.h new file mode 100644 index 000000000..26a9905f7 --- /dev/null +++ b/scd/tlv.h @@ -0,0 +1,84 @@ +/* tlv.h - Tag-Length-Value Utilities + * 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 SCD_TLV_H +#define SCD_TLV_H 1 + + +enum tlv_tag_class { + CLASS_UNIVERSAL = 0, + CLASS_APPLICATION = 1, + CLASS_CONTEXT = 2, + CLASS_PRIVATE =3 +}; + +enum tlv_tag_type { + TAG_NONE = 0, + TAG_BOOLEAN = 1, + TAG_INTEGER = 2, + TAG_BIT_STRING = 3, + TAG_OCTET_STRING = 4, + TAG_NULL = 5, + TAG_OBJECT_ID = 6, + TAG_OBJECT_DESCRIPTOR = 7, + TAG_EXTERNAL = 8, + TAG_REAL = 9, + TAG_ENUMERATED = 10, + TAG_EMBEDDED_PDV = 11, + TAG_UTF8_STRING = 12, + TAG_REALTIVE_OID = 13, + TAG_SEQUENCE = 16, + TAG_SET = 17, + TAG_NUMERIC_STRING = 18, + TAG_PRINTABLE_STRING = 19, + TAG_TELETEX_STRING = 20, + TAG_VIDEOTEX_STRING = 21, + TAG_IA5_STRING = 22, + TAG_UTC_TIME = 23, + TAG_GENERALIZED_TIME = 24, + TAG_GRAPHIC_STRING = 25, + TAG_VISIBLE_STRING = 26, + TAG_GENERAL_STRING = 27, + TAG_UNIVERSAL_STRING = 28, + TAG_CHARACTER_STRING = 29, + TAG_BMP_STRING = 30 +}; + + + +/* Locate a TLV encoded data object in BUFFER of LENGTH and return a + pointer to value as well as its length in NBYTES. Return NULL if + it was not found. Note, that the function does not check whether + the value fits into the provided buffer.*/ +const unsigned char *find_tlv (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes); + + +/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag + and the length part from the TLV triplet. Update BUFFER and SIZE + on success. */ +gpg_error_t parse_ber_header (unsigned char const **buffer, size_t *size, + int *r_class, int *r_tag, + int *r_constructed, + int *r_ndef, size_t *r_length, size_t *r_nhdr); + + + +#endif /* SCD_TLV_H */ diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c new file mode 100644 index 000000000..956cf18d9 --- /dev/null +++ b/tools/gpgparsemail.c @@ -0,0 +1,705 @@ +/* gpgparsemail.c - Standalone crypto mail parser + * 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 + */ + + +/* This utility prints an RFC8222, possible MIME structured, message + in an annotated format with the first column having an indicator + for the content of the line.. Several options are available to + scrutinize the message. S/MIME and OpenPGP suuport is included. */ + + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <assert.h> +#include <time.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/wait.h> + +#include "rfc822parse.h" + + +#define PGM "gpgparsemail" + +/* Option flags. */ +static int verbose; +static int debug; +static int opt_crypto; /* Decrypt or verify messages. */ +static int opt_no_header; /* Don't output the header lines. */ + +/* Structure used to communicate with the parser callback. */ +struct parse_info_s { + int show_header; /* Show the header lines. */ + int show_data; /* Show the data lines. */ + unsigned int skip_show; /* Temporary disable above for these + number of lines. */ + int show_data_as_note; /* The next data line should be shown + as a note. */ + int show_boundary; + int nesting_level; + + int gpgsm_mime; /* gpgsm shall be used from S/MIME. */ + char *signing_protocol; + int hashing_level; /* The nesting level we are hashing. */ + int hashing; + FILE *hash_file; + FILE *sig_file; + int verify_now; /* Falg set when all signature data is + available. */ +}; + + +/* Print diagnostic message and exit with failure. */ +static void +die (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); + + exit (1); +} + + +/* Print diagnostic message. */ +static void +err (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + putc ('\n', stderr); +} + +static void * +xmalloc (size_t n) +{ + void *p = malloc (n); + if (!p) + die ("out of core: %s", strerror (errno)); + return p; +} + +/* static void * */ +/* xcalloc (size_t n, size_t m) */ +/* { */ +/* void *p = calloc (n, m); */ +/* if (!p) */ +/* die ("out of core: %s", strerror (errno)); */ +/* return p; */ +/* } */ + +/* static void * */ +/* xrealloc (void *old, size_t n) */ +/* { */ +/* void *p = realloc (old, n); */ +/* if (!p) */ +/* die ("out of core: %s", strerror (errno)); */ +/* return p; */ +/* } */ + +static char * +xstrdup (const char *string) +{ + void *p = malloc (strlen (string)+1); + if (!p) + die ("out of core: %s", strerror (errno)); + strcpy (p, string); + return p; +} + +static char * +stpcpy (char *a,const char *b) +{ + while (*b) + *a++ = *b++; + *a = 0; + + return (char*)a; +} + + +static int +run_gnupg (int smime, int sig_fd, int data_fd, int *close_list) +{ + int rp[2]; + pid_t pid; + int i, c, is_status; + unsigned int pos; + char status_buf[10]; + const char *cmd = smime? "gpgsm":"gpg"; + FILE *fp; + + if (pipe (rp) == -1) + die ("error creating a pipe: %s", strerror (errno)); + + pid = fork (); + if (pid == -1) + die ("error forking process: %s", strerror (errno)); + + if (!pid) + { /* Child. */ + char data_fd_buf[50]; + int fd; + + /* Connect our signature fd to stdin. */ + if (sig_fd != 0) + { + if (dup2 (sig_fd, 0) == -1) + die ("dup2 stdin failed: %s", strerror (errno)); + } + + /* Keep our data fd and format it for gpg/gpgsm use. */ + sprintf (data_fd_buf, "-&%d", data_fd); + + /* Send stdout to the bit bucket. */ + fd = open ("/dev/null", O_WRONLY); + if (fd == -1) + die ("can't open `/dev/null': %s", strerror (errno)); + if (fd != 1) + { + if (dup2 (fd, 1) == -1) + die ("dup2 stderr failed: %s", strerror (errno)); + } + + /* Connect stderr to our pipe. */ + if (rp[1] != 2) + { + if (dup2 (rp[1], 2) == -1) + die ("dup2 stderr failed: %s", strerror (errno)); + } + + /* Close other files. */ + for (i=0; (fd=close_list[i]) != -1; i++) + if (fd > 2 && fd != data_fd) + close (fd); + errno = 0; + + execlp (cmd, cmd, + "--enable-special-filenames", + "--status-fd", "2", + "--assume-base64", + "--verify", + "--", + "-", data_fd_buf, + NULL); + + die ("failed to exec the crypto command: %s", strerror (errno)); + } + + /* Parent. */ + close (rp[1]); + + fp = fdopen (rp[0], "r"); + if (!fp) + die ("can't fdopen pipe for reading: %s", strerror (errno)); + + pos = 0; + is_status = 0; + assert (sizeof status_buf > 9); + while ((c=getc (fp)) != EOF) + { + if (pos < 9) + status_buf[pos] = c; + else + { + if (pos == 9) + { + is_status = !memcmp (status_buf, "[GNUPG:] ", 9); + if (is_status) + fputs ( "c ", stdout); + else if (verbose) + fputs ( "# ", stdout); + fwrite (status_buf, 9, 1, stdout); + } + putchar (c); + } + if (c == '\n') + { + if (verbose && pos < 9) + { + fputs ( "# ", stdout); + fwrite (status_buf, pos+1, 1, stdout); + } + pos = 0; + } + else + pos++; + } + if (pos) + { + if (verbose && pos < 9) + { + fputs ( "# ", stdout); + fwrite (status_buf, pos+1, 1, stdout); + } + putchar ('\n'); + } + fclose (fp); + + while ( (i=waitpid (pid, NULL, 0)) == -1 && errno == EINTR) + ; + if (i == -1) + die ("waiting for child failed: %s", strerror (errno)); + + return 0; +} + + + + +/* Verify the signature in the current temp files. */ +static void +verify_signature (struct parse_info_s *info) +{ + int close_list[10]; + + assert (info->hash_file); + assert (info->sig_file); + rewind (info->hash_file); + rewind (info->sig_file); + +/* printf ("# Begin hashed data\n"); */ +/* while ( (c=getc (info->hash_file)) != EOF) */ +/* putchar (c); */ +/* printf ("# End hashed data signature\n"); */ +/* printf ("# Begin signature\n"); */ +/* while ( (c=getc (info->sig_file)) != EOF) */ +/* putchar (c); */ +/* printf ("# End signature\n"); */ +/* rewind (info->hash_file); */ +/* rewind (info->sig_file); */ + + close_list[0] = -1; + run_gnupg (1, fileno (info->sig_file), fileno (info->hash_file), close_list); +} + + + + + +/* Prepare for a multipart/signed. + FIELD_CTX is the parsed context of the content-type header.*/ +static void +mime_signed_begin (struct parse_info_s *info, rfc822parse_t msg, + rfc822parse_field_t field_ctx) +{ + const char *s; + s = rfc822parse_query_parameter (field_ctx, "protocol", 1); + if (s) + { + printf ("h signed.protocol: %s\n", s); + if (!strcmp (s, "application/pkcs7-signature") + || !strcmp (s, "application/x-pkcs7-signature")) + { + if (info->gpgsm_mime) + err ("note: ignoring nested pkcs7-signature"); + else + { + info->gpgsm_mime = 1; + free (info->signing_protocol); + info->signing_protocol = xstrdup (s); + } + } + else if (verbose) + printf ("# this protocol is not supported\n"); + } +} + + +/* Prepare for a multipart/encrypted. + FIELD_CTX is the parsed context of the content-type header.*/ +static void +mime_encrypted_begin (struct parse_info_s *info, rfc822parse_t msg, + rfc822parse_field_t field_ctx) +{ + const char *s; + s = rfc822parse_query_parameter (field_ctx, "protocol", 0); + if (s) + printf ("h encrypted.protocol: %s\n", s); +} + + + +/* Print the event received by the parser for debugging as comment + line. */ +static void +show_event (rfc822parse_event_t event) +{ + const char *s; + + switch (event) + { + case RFC822PARSE_OPEN: s= "Open"; break; + case RFC822PARSE_CLOSE: s= "Close"; break; + case RFC822PARSE_CANCEL: s= "Cancel"; break; + case RFC822PARSE_T2BODY: s= "T2Body"; break; + case RFC822PARSE_FINISH: s= "Finish"; break; + case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break; + case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break; + case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break; + case RFC822PARSE_BOUNDARY: s= "Boundary"; break; + case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break; + case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break; + case RFC822PARSE_PREAMBLE: s= "Preamble"; break; + case RFC822PARSE_EPILOGUE: s= "Epilogue"; break; + default: s= "[unknown event]"; break; + } + printf ("# *** got RFC822 event %s\n", s); +} + +/* This function is called by the parser to communicate events. This + callback comminucates with the main program using a structure + passed in OPAQUE. Should retrun 0 or set errno and return -1. */ +static int +message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg) +{ + struct parse_info_s *info = opaque; + + if (debug) + show_event (event); + if (event == RFC822PARSE_OPEN) + { + /* Initialize for a new message. */ + info->show_header = 1; + } + else if (event == RFC822PARSE_T2BODY) + { + rfc822parse_field_t ctx; + + ctx = rfc822parse_parse_field (msg, "Content-Type", -1); + if (ctx) + { + const char *s1, *s2; + s1 = rfc822parse_query_media_type (ctx, &s2); + if (s1) + { + printf ("h media: %*s%s %s\n", + info->nesting_level*2, "", s1, s2); + if (info->gpgsm_mime == 3) + { + char *buf = xmalloc (strlen (s1) + strlen (s2) + 2); + strcpy (stpcpy (stpcpy (buf, s1), "/"), s2); + assert (info->signing_protocol); + if (strcmp (buf, info->signing_protocol)) + err ("invalid S/MIME structure; expected `%s', found `%s'", + info->signing_protocol, buf); + else + { + printf ("c begin_signature\n"); + info->gpgsm_mime++; + if (opt_crypto) + { + assert (!info->sig_file); + info->sig_file = tmpfile (); + if (!info->sig_file) + die ("error creating temp file: %s", + strerror (errno)); + } + } + free (buf); + } + else if (!strcmp (s1, "multipart")) + { + if (!strcmp (s2, "signed")) + mime_signed_begin (info, msg, ctx); + else if (!strcmp (s2, "encrypted")) + mime_encrypted_begin (info, msg, ctx); + } + } + else + printf ("h media: %*s none\n", info->nesting_level*2, ""); + + rfc822parse_release_field (ctx); + } + else + printf ("h media: %*stext plain [assumed]\n", + info->nesting_level*2, ""); + info->show_header = 0; + info->show_data = 1; + info->skip_show = 1; + } + else if (event == RFC822PARSE_PREAMBLE) + info->show_data_as_note = 1; + else if (event == RFC822PARSE_LEVEL_DOWN) + { + printf ("b down\n"); + info->nesting_level++; + } + else if (event == RFC822PARSE_LEVEL_UP) + { + printf ("b up\n"); + if (info->nesting_level) + info->nesting_level--; + else + err ("invalid structure (bad nesting level)"); + } + else if (event == RFC822PARSE_BOUNDARY || event == RFC822PARSE_LAST_BOUNDARY) + { + info->show_data = 0; + info->show_boundary = 1; + if (event == RFC822PARSE_BOUNDARY) + { + info->show_header = 1; + info->skip_show = 1; + printf ("b part\n"); + } + else + printf ("b last\n"); + + if (info->gpgsm_mime == 2 && info->nesting_level == info->hashing_level) + { + printf ("c end_hash\n"); + info->gpgsm_mime++; + info->hashing = 0; + } + else if (info->gpgsm_mime == 4) + { + printf ("c end_signature\n"); + info->verify_now = 1; + } + } + else if (event == RFC822PARSE_BEGIN_HEADER) + { + if (info->gpgsm_mime == 1) + { + printf ("c begin_hash\n"); + info->hashing = 1; + info->hashing_level = info->nesting_level; + info->gpgsm_mime++; + + if (opt_crypto) + { + assert (!info->hash_file); + info->hash_file = tmpfile (); + if (!info->hash_file) + die ("failed to create temporary file: %s", strerror (errno)); + } + } + } + + return 0; +} + + +/* Read a message from FP and process it according to the global + options. */ +static void +parse_message (FILE *fp) +{ + char line[5000]; + size_t length; + rfc822parse_t msg; + unsigned int lineno = 0; + int no_cr_reported = 0; + struct parse_info_s info; + + memset (&info, 0, sizeof info); + + msg = rfc822parse_open (message_cb, &info); + if (!msg) + die ("can't open parser: %s", strerror (errno)); + + /* Fixme: We should not use fgets becuase it can't cope with + embedded nul characters. */ + while (fgets (line, sizeof (line), fp)) + { + lineno++; + if (lineno == 1 && !strncmp (line, "From ", 5)) + continue; /* We better ignore a leading From line. */ + + length = strlen (line); + if (length && line[length - 1] == '\n') + line[--length] = 0; + else + err ("line number %u too long or last line not terminated", lineno); + if (length && line[length - 1] == '\r') + line[--length] = 0; + else if (verbose && !no_cr_reported) + { + err ("non canonical ended line detected (line %u)", lineno); + no_cr_reported = 1; + } + + + if (rfc822parse_insert (msg, line, length)) + die ("parser failed: %s", strerror (errno)); + + if (info.hashing) + { + /* Delay hashing of the CR/LF because the last line ending + belongs to the next boundary. */ + if (debug) + printf ("# hashing %s`%s'\n", info.hashing==2?"CR,LF+":"", line); + if (opt_crypto) + { + if (info.hashing == 2) + fputs ("\r\n", info.hash_file); + fputs (line, info.hash_file); + if (ferror (info.hash_file)) + die ("error writing to temporary file: %s", strerror (errno)); + } + + info.hashing = 2; + } + + if (info.sig_file && opt_crypto) + { + if (info.verify_now) + { + verify_signature (&info); + fclose (info.hash_file); + info.hash_file = NULL; + fclose (info.sig_file); + info.sig_file = NULL; + info.gpgsm_mime = 0; + } + else + { + fputs (line, info.sig_file); + fputs ("\r\n", info.sig_file); + if (ferror (info.sig_file)) + die ("error writing to temporary file: %s", strerror (errno)); + } + } + + if (info.show_boundary) + { + if (!opt_no_header) + printf (":%s\n", line); + info.show_boundary = 0; + } + + if (info.skip_show) + info.skip_show--; + else if (info.show_data) + { + if (info.show_data_as_note) + { + if (verbose) + printf ("# DATA: %s\n", line); + info.show_data_as_note = 0; + } + else + printf (" %s\n", line); + } + else if (info.show_header && !opt_no_header) + printf (".%s\n", line); + + } + + rfc822parse_close (msg); +} + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + + if (argc) + { + argc--; argv++; + } + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + puts ( + "Usage: " PGM " [OPTION] [FILE]\n" + "Parse a mail message into an annotated format.\n\n" + " --crypto decrypt or verify messages\n" + " --no-header don't output the header lines\n" + " --verbose enable extra informational output\n" + " --debug enable additional debug output\n" + " --help display this help and exit\n\n" + "With no FILE, or when FILE is -, read standard input.\n\n" + "Report bugs to <bug-gnupg@gnu.org>."); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose = debug = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--crypto")) + { + opt_crypto = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--no-header")) + { + opt_no_header = 1; + argc--; argv++; + } + } + + if (argc > 1) + die ("usage: " PGM " [OPTION] [FILE] (try --help for more information)\n"); + + signal (SIGPIPE, SIG_IGN); + + if (argc && strcmp (*argv, "-")) + { + FILE *fp = fopen (*argv, "rb"); + if (!fp) + die ("can't open `%s': %s", *argv, strerror (errno)); + parse_message (fp); + fclose (fp); + } + else + parse_message (stdin); + + return 0; +} + + +/* +Local Variables: +compile-command: "gcc -Wall -g -o gpgparsemail rfc822parse.c gpgparsemail.c" +End: +*/ diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c new file mode 100644 index 000000000..be1cf4a47 --- /dev/null +++ b/tools/rfc822parse.c @@ -0,0 +1,1235 @@ +/* rfc822parse.c - Simple mail and MIME parser + * Copyright (C) 1999, 2000 Werner Koch, Duesseldorf + * Copyright (C) 2003, g10 Code GmbH + * + * 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 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 + */ + + +/* According to RFC822 binary 0 are allowed at many places. We + * do not handle this correct especially in the field parsing code. It + * should be easy to fix and the API provides a interfcaes which returns + * the length but in addition makes sure that returned strings are always + * ended by a \0. + * + * Furthermore, the case of field names is changed and thus it is not + * always a good idea to use these modified header + * lines (e.g. signatures may break). + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <assert.h> + +#include "rfc822parse.h" + +enum token_type +{ + tSPACE, + tATOM, + tQUOTED, + tDOMAINLIT, + tSPECIAL +}; + +/* For now we directly use our TOKEN as the parse context */ +typedef struct rfc822parse_field_context *TOKEN; +struct rfc822parse_field_context +{ + TOKEN next; + enum token_type type; + struct { + unsigned int cont:1; + unsigned int lowered:1; + } flags; + /*TOKEN owner_pantry; */ + char data[1]; +}; + +struct hdr_line +{ + struct hdr_line *next; + int cont; /* This is a continuation of the previous line. */ + unsigned char line[1]; +}; + +typedef struct hdr_line *HDR_LINE; + + +struct part +{ + struct part *right; /* The next part. */ + struct part *down; /* A contained part. */ + HDR_LINE hdr_lines; /* Header lines os that part. */ + HDR_LINE *hdr_lines_tail; /* Helper for adding lines. */ + char *boundary; /* Only used in the first part. */ +}; +typedef struct part *part_t; + +struct rfc822parse_context +{ + rfc822parse_cb_t callback; + void *callback_value; + int callback_error; + int in_body; + int in_preamble; /* Wether we are before the first boundary. */ + part_t parts; /* The tree of parts. */ + part_t current_part; /* Whom we are processing (points into parts). */ + const char *boundary; /* Current boundary. */ +}; + +static HDR_LINE find_header (rfc822parse_t msg, const char *name, + int which, HDR_LINE * rprev); + + +static size_t +length_sans_trailing_ws (const unsigned char *line, size_t len) +{ + const unsigned char *p, *mark; + size_t n; + + for (mark=NULL, p=line, n=0; n < len; n++, p++) + { + if (strchr (" \t\r\n", *p )) + { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if (mark) + return mark - line; + return len; +} + + +static void +lowercase_string (unsigned char *string) +{ + for (; *string; string++) + if (*string >= 'A' && *string <= 'Z') + *string = *string - 'A' + 'a'; +} + +/* Transform a header name into a standard capitalized format; i.e + "Content-Type". Conversion stops at the colon. As usual we don't + use the localized versions of ctype.h. + */ +static void +capitalize_header_name (unsigned char *name) +{ + int first = 1; + + for (; *name && *name != ':'; name++) + if (*name == '-') + first = 1; + else if (first) + { + if (*name >= 'a' && *name <= 'z') + *name = *name - 'a' + 'A'; + first = 0; + } + else if (*name >= 'A' && *name <= 'Z') + *name = *name - 'A' + 'a'; +} + + +static char * +stpcpy (char *a,const char *b) +{ + while (*b) + *a++ = *b++; + *a = 0; + + return (char*)a; +} + + +/* If a callback has been registerd, call it for the event of type + EVENT. */ +static int +do_callback (rfc822parse_t msg, rfc822parse_event_t event) +{ + int rc; + + if (!msg->callback || msg->callback_error) + return 0; + rc = msg->callback (msg->callback_value, event, msg); + if (rc) + msg->callback_error = rc; + return rc; +} + +static part_t +new_part (void) +{ + part_t part; + + part = calloc (1, sizeof *part); + if (part) + { + part->hdr_lines_tail = &part->hdr_lines; + } + return part; +} + + +static void +release_part (part_t part) +{ + part_t tmp; + HDR_LINE hdr, hdr2; + + for (; part; part = tmp) + { + tmp = part->right; + if (part->down) + release_part (part->down); + for (hdr = part->hdr_lines; hdr; hdr = hdr2) + { + hdr2 = hdr->next; + free (hdr); + } + free (part->boundary); + free (part); + } +} + + +static void +release_handle_data (rfc822parse_t msg) +{ + release_part (msg->parts); + msg->parts = NULL; + msg->current_part = NULL; + msg->boundary = NULL; +} + + +/* Create a new parsing context for an entire rfc822 message and + return it. CB and CB_VALUE may be given to callback for certain + events. NULL is returned on error with errno set appropriately. */ +rfc822parse_t +rfc822parse_open (rfc822parse_cb_t cb, void *cb_value) +{ + rfc822parse_t msg = calloc (1, sizeof *msg); + if (msg) + { + msg->parts = msg->current_part = new_part (); + if (!msg->parts) + { + free (msg); + msg = NULL; + } + else + { + msg->callback = cb; + msg->callback_value = cb_value; + if (do_callback (msg, RFC822PARSE_OPEN)) + { + release_handle_data (msg); + free (msg); + msg = NULL; + } + } + } + return msg; +} + + +void +rfc822parse_cancel (rfc822parse_t msg) +{ + if (msg) + { + do_callback (msg, RFC822PARSE_CANCEL); + release_handle_data (msg); + free (msg); + } +} + + +void +rfc822parse_close (rfc822parse_t msg) +{ + if (msg) + { + do_callback (msg, RFC822PARSE_CLOSE); + release_handle_data (msg); + free (msg); + } +} + +static part_t +find_parent (part_t tree, part_t target) +{ + part_t part; + + for (part = tree->down; part; part = part->right) + { + if (part == target) + return tree; /* Found. */ + if (part->down) + { + part_t tmp = find_parent (part, target); + if (tmp) + return tmp; + } + } + return NULL; +} + +static void +set_current_part_to_parent (rfc822parse_t msg) +{ + part_t parent; + + assert (msg->current_part); + parent = find_parent (msg->parts, msg->current_part); + if (!parent) + return; /* Already at the top. */ + +#ifndef NDEBUG + { + part_t part; + for (part = parent->down; part; part = part->right) + if (part == msg->current_part) + break; + assert (part); + } +#endif + msg->current_part = parent; + + parent = find_parent (msg->parts, parent); + msg->boundary = parent? parent->boundary: NULL; +} + + + +/**************** + * We have read in all header lines and are about to receive the body + * part. The delimiter line has already been processed. + * + * FIXME: we's better return an error in case of memory failures. + */ +static int +transition_to_body (rfc822parse_t msg) +{ + rfc822parse_field_t ctx; + int rc; + + rc = do_callback (msg, RFC822PARSE_T2BODY); + if (!rc) + { + /* Store the boundary if we have multipart type. */ + ctx = rfc822parse_parse_field (msg, "Content-Type", -1); + if (ctx) + { + const char *s; + + s = rfc822parse_query_media_type (ctx, NULL); + if (s && !strcmp (s,"multipart")) + { + s = rfc822parse_query_parameter (ctx, "boundary", 0); + if (s) + { + assert (!msg->current_part->boundary); + msg->current_part->boundary = malloc (strlen (s) + 1); + if (msg->current_part->boundary) + { + part_t part; + + strcpy (msg->current_part->boundary, s); + msg->boundary = msg->current_part->boundary; + part = new_part (); + if (!part) + { + int save_errno = errno; + rfc822parse_release_field (ctx); + errno = save_errno; + return -1; + } + rc = do_callback (msg, RFC822PARSE_LEVEL_DOWN); + assert (!msg->current_part->down); + msg->current_part->down = part; + msg->current_part = part; + msg->in_preamble = 1; + } + } + } + rfc822parse_release_field (ctx); + } + } + + return rc; +} + +/* We have just passed a MIME boundary and need to prepare for new part. + headers. */ +static int +transition_to_header (rfc822parse_t msg) +{ + part_t part; + + assert (msg->current_part); + assert (!msg->current_part->right); + + part = new_part (); + if (!part) + return -1; + + msg->current_part->right = part; + msg->current_part = part; + return 0; +} + + +static int +insert_header (rfc822parse_t msg, const unsigned char *line, size_t length) +{ + HDR_LINE hdr; + + assert (msg->current_part); + if (!length) + { + msg->in_body = 1; + return transition_to_body (msg); + } + + if (!msg->current_part->hdr_lines) + do_callback (msg, RFC822PARSE_BEGIN_HEADER); + + length = length_sans_trailing_ws (line, length); + hdr = malloc (sizeof (*hdr) + length); + if (!hdr) + return -1; + hdr->next = NULL; + hdr->cont = (*line == ' ' || *line == '\t'); + memcpy (hdr->line, line, length); + hdr->line[length] = 0; /* Make it a string. */ + + /* Transform a field name into canonical format. */ + if (!hdr->cont && strchr (line, ':')) + capitalize_header_name (hdr->line); + + *msg->current_part->hdr_lines_tail = hdr; + msg->current_part->hdr_lines_tail = &hdr->next; + + /* Lets help the caller to prevent mail loops and issue an event for + * every Received header. */ + if (length >= 9 && !memcmp (line, "Received:", 9)) + do_callback (msg, RFC822PARSE_RCVD_SEEN); + return 0; +} + + +/**************** + * Note: We handle the body transparent to allow binary zeroes in it. + */ +static int +insert_body (rfc822parse_t msg, const unsigned char *line, size_t length) +{ + int rc = 0; + + if (length > 2 && *line == '-' && line[1] == '-' && msg->boundary) + { + size_t blen = strlen (msg->boundary); + + if (length == blen + 2 + && !memcmp (line+2, msg->boundary, blen)) + { + rc = do_callback (msg, RFC822PARSE_BOUNDARY); + msg->in_body = 0; + if (!rc && !msg->in_preamble) + rc = transition_to_header (msg); + msg->in_preamble = 0; + } + else if (length == blen + 4 + && line[length-2] =='-' && line[length-1] == '-' + && !memcmp (line+2, msg->boundary, blen)) + { + rc = do_callback (msg, RFC822PARSE_LAST_BOUNDARY); + msg->boundary = NULL; /* No current boundary anymore. */ + set_current_part_to_parent (msg); + + /* Fixme: The next should acctually be sent right before the + next boundary, so that we can mark the epilogue. */ + if (!rc) + rc = do_callback (msg, RFC822PARSE_LEVEL_UP); + } + } + if (msg->in_preamble && !rc) + rc = do_callback (msg, RFC822PARSE_PREAMBLE); + + return rc; +} + +/* Insert the next line into the parser. Return 0 on success or true + on error with errno set appropriately. */ +int +rfc822parse_insert (rfc822parse_t msg, const unsigned char *line, size_t length) +{ + return (msg->in_body + ? insert_body (msg, line, length) + : insert_header (msg, line, length)); +} + + +/* Tell the parser that we have finished the message. */ +int +rfc822parse_finish (rfc822parse_t msg) +{ + return do_callback (msg, RFC822PARSE_FINISH); +} + + + +/**************** + * Get a copy of a header line. The line is returned as one long + * string with LF to separate the continuation line. Caller must free + * the return buffer. which may be used to enumerate over all lines. + * Wildcards are allowed. This function works on the current headers; + * i.e. the regular mail headers or the MIME headers of the current + * part. + * + * WHICH gives the mode: + * -1 := Take the last occurence + * n := Take the n-th one. + * + * Returns a newly allocated buffer or NULL on error. errno is set in + * case of a memory failure or set to 0 if the requested field is not + * available. + */ +char * +rfc822parse_get_field (rfc822parse_t msg, const char *name, int which) +{ + HDR_LINE h, h2; + char *buf, *p; + size_t n; + + h = find_header (msg, name, which, NULL); + if (!h) + { + errno = 0; + return NULL; /* no such field */ + } + + n = strlen (h->line) + 1; + for (h2 = h->next; h2 && h2->cont; h2 = h2->next) + n += strlen (h2->line) + 1; + + buf = p = malloc (n); + if (buf) + { + p = stpcpy (p, h->line); + *p++ = '\n'; + for (h2 = h->next; h2 && h2->cont; h2 = h2->next) + { + p = stpcpy (p, h2->line); + *p++ = '\n'; + } + p[-1] = 0; + } + return buf; +} + + +/**************** + * Enumerate all header. Caller has to provide the address of a pointer + * which has to be initialzed to NULL, the caller should then never change this + * pointer until he has closed the enumeration by passing again the address + * of the pointer but with msg set to NULL. + * The function returns pointers to all the header lines or NULL when + * all lines have been enumerated or no headers are available. + */ +const char * +rfc822parse_enum_header_lines (rfc822parse_t msg, void **context) +{ + HDR_LINE l; + + if (!msg) /* Close. */ + return NULL; + + if (*context == msg || !msg->current_part) + return NULL; + + l = *context ? (HDR_LINE) *context : msg->current_part->hdr_lines; + + if (l) + { + *context = l->next ? (void *) (l->next) : (void *) msg; + return l->line; + } + *context = msg; /* Mark end of list. */ + return NULL; +} + + + +/**************** + * Find a header field. If the Name does end in an asterisk this is meant + * to be a wildcard. + * + * which -1 : Retrieve the last field + * >0 : Retrieve the n-th field + + * RPREV may be used to return the predecessor of the returned field; + * which may be NULL for the very first one. It has to be initialzed + * to either NULL in which case the search start at the first header line, + * or it may point to a headerline, where the search should start + */ +static HDR_LINE +find_header (rfc822parse_t msg, const char *name, int which, HDR_LINE *rprev) +{ + HDR_LINE hdr, prev = NULL, mark = NULL; + unsigned char *p; + size_t namelen, n; + int found = 0; + int glob = 0; + + if (!msg->current_part) + return NULL; + + namelen = strlen (name); + if (namelen && name[namelen - 1] == '*') + { + namelen--; + glob = 1; + } + + hdr = msg->current_part->hdr_lines; + if (rprev && *rprev) + { + /* spool forward to the requested starting place. + * we cannot simply set this as we have to return + * the previous list element too */ + for (; hdr && hdr != *rprev; prev = hdr, hdr = hdr->next) + ; + } + + for (; hdr; prev = hdr, hdr = hdr->next) + { + if (hdr->cont) + continue; + if (!(p = strchr (hdr->line, ':'))) + continue; /* invalid header, just skip it. */ + n = p - hdr->line; + if (!n) + continue; /* invalid name */ + if ((glob ? (namelen <= n) : (namelen == n)) + && !memcmp (hdr->line, name, namelen)) + { + found++; + if (which == -1) + mark = hdr; + else if (found == which) + { + if (rprev) + *rprev = prev; + return hdr; + } + } + } + if (mark && rprev) + *rprev = prev; + return mark; +} + + + +static const char * +skip_ws (const char *s) +{ + while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') + s++; + return s; +} + + +static void +release_token_list (TOKEN t) +{ + while (t) + { + TOKEN t2 = t->next; + /* fixme: If we have owner_pantry, put the token back to + * this pantry so that it can be reused later */ + free (t); + t = t2; + } +} + + +static TOKEN +new_token (enum token_type type, const char *buf, size_t length) +{ + TOKEN t; + + /* fixme: look through our pantries to find a suitable + * token for reuse */ + t = malloc (sizeof *t + length); + if (t) + { + t->next = NULL; + t->type = type; + memset (&t->flags, 0, sizeof (t->flags)); + t->data[0] = 0; + if (buf) + { + memcpy (t->data, buf, length); + t->data[length] = 0; /* Make sure it is a C string. */ + } + else + t->data[0] = 0; + } + return t; +} + +static TOKEN +append_to_token (TOKEN old, const char *buf, size_t length) +{ + size_t n = strlen (old->data); + TOKEN t; + + t = malloc (sizeof *t + n + length); + if (t) + { + t->next = old->next; + t->type = old->type; + t->flags = old->flags; + memcpy (t->data, old->data, n); + memcpy (t->data + n, buf, length); + t->data[n + length] = 0; + old->next = NULL; + release_token_list (old); + } + return t; +} + + + +/* + Parse a field into tokens as defined by rfc822. + */ +static TOKEN +parse_field (HDR_LINE hdr) +{ + static const char specials[] = "<>@.,;:\\[]\"()"; + static const char specials2[] = "<>@.,;:"; + static const char tspecials[] = "/?=<>@,;:\\[]\"()"; + static const char tspecials2[] = "/?=<>@.,;:"; + static struct + { + const unsigned char *name; + size_t namelen; + } tspecial_header[] = { + { "Content-Type", 12}, + { "Content-Transfer-Encoding", 25}, + { NULL, 0} + }; + const char *delimiters; + const char *delimiters2; + const unsigned char *line, *s, *s2; + size_t n; + int i, invalid = 0; + TOKEN t, tok, *tok_tail; + + errno = 0; + if (!hdr) + return NULL; + + tok = NULL; + tok_tail = &tok; + + line = hdr->line; + if (!(s = strchr (line, ':'))) + return NULL; /* oops */ + + n = s - line; + if (!n) + return NULL; /* oops: invalid name */ + + delimiters = specials; + delimiters2 = specials2; + for (i = 0; tspecial_header[i].name; i++) + { + if (n == tspecial_header[i].namelen + && !memcmp (line, tspecial_header[i].name, n)) + { + delimiters = tspecials; + delimiters2 = tspecials2; + break; + } + } + + s++; /* Move over the colon. */ + for (;;) + { + if (!*s) + { + if (!hdr->next || !hdr->next->cont) + break; + hdr = hdr->next; + s = hdr->line; + } + + if (*s == '(') + { + int level = 1; + int in_quote = 0; + + invalid = 0; + for (s++;; s++) + { + if (!*s) + { + if (!hdr->next || !hdr->next->cont) + break; + hdr = hdr->next; + s = hdr->line; + } + + if (in_quote) + { + if (*s == '\"') + in_quote = 0; + else if (*s == '\\' && s[1]) /* what about continuation? */ + s++; + } + else if (*s == ')') + { + if (!--level) + break; + } + else if (*s == '(') + level++; + else if (*s == '\"') + in_quote = 1; + } + if (!*s) + ; /* Actually this is an error, but we don't care about it. */ + else + s++; + } + else if (*s == '\"' || *s == '[') + { + /* We do not check for non-allowed nesting of domainliterals */ + int term = *s == '\"' ? '\"' : ']'; + invalid = 0; + s++; + t = NULL; + + for (;;) + { + for (s2 = s; *s2; s2++) + { + if (*s2 == term) + break; + else if (*s2 == '\\' && s2[1]) /* what about continuation? */ + s2++; + } + + t = (t + ? append_to_token (t, s, s2 - s) + : new_token (term == '\"'? tQUOTED : tDOMAINLIT, s, s2 - s)); + if (!t) + goto failure; + + if (*s2 || !hdr->next || !hdr->next->cont) + break; + hdr = hdr->next; + s = hdr->line; + } + *tok_tail = t; + tok_tail = &t->next; + s = s2; + if (*s) + s++; /* skip the delimiter */ + } + else if ((s2 = strchr (delimiters2, *s))) + { /* Special characters which are not handled above. */ + invalid = 0; + t = new_token (tSPECIAL, s, 1); + if (!t) + goto failure; + *tok_tail = t; + tok_tail = &t->next; + s++; + } + else if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') + { + invalid = 0; + s = skip_ws (s + 1); + } + else if (*s > 0x20 && !(*s & 128)) + { /* Atom. */ + invalid = 0; + for (s2 = s + 1; *s2 > 0x20 + && !(*s2 & 128) && !strchr (delimiters, *s2); s2++) + ; + t = new_token (tATOM, s, s2 - s); + if (!t) + goto failure; + *tok_tail = t; + tok_tail = &t->next; + s = s2; + } + else + { /* Invalid character. */ + if (!invalid) + { /* For parsing we assume only one space. */ + t = new_token (tSPACE, NULL, 0); + if (!t) + goto failure; + *tok_tail = t; + tok_tail = &t->next; + invalid = 1; + } + s++; + } + } + + return tok; + + failure: + { + int save = errno; + release_token_list (tok); + errno = save; + } + return NULL; +} + + + + +/**************** + * Find and parse a header field. + * WHICH indicates what to do if there are multiple instance of the same + * field (like "Received"); the following value are defined: + * -1 := Take the last occurence + * 0 := Reserved + * n := Take the n-th one. + * Returns a handle for further operations on the parse context of the field + * or NULL if the field was not found. + */ +rfc822parse_field_t +rfc822parse_parse_field (rfc822parse_t msg, const char *name, int which) +{ + HDR_LINE hdr; + + if (!which) + return NULL; + + hdr = find_header (msg, name, which, NULL); + if (!hdr) + return NULL; + return parse_field (hdr); +} + +void +rfc822parse_release_field (rfc822parse_field_t ctx) +{ + if (ctx) + release_token_list (ctx); +} + + + +/**************** + * Check whether T points to a parameter. + * A parameter starts with a semicolon and it is assumed that t + * points to exactly this one. + */ +static int +is_parameter (TOKEN t) +{ + t = t->next; + if (!t || t->type != tATOM) + return 0; + t = t->next; + if (!t || !(t->type == tSPECIAL && t->data[0] == '=')) + return 0; + t = t->next; + if (!t) + return 1; /* We assume that an non existing value is an empty one. */ + return t->type == tQUOTED || t->type == tATOM; +} + +/* + Some header (Content-type) have a special syntax where attribute=value + pairs are used after a leading semicolon. The parse_field code + knows about these fields and changes the parsing to the one defined + in RFC2045. + Returns a pointer to the value which is valid as long as the + parse context is valid; NULL is returned in case that attr is not + defined in the header, a missing value is reppresented by an empty string. + + With LOWER_VALUE set to true, a matching field valuebe be + lowercased. + + Note, that ATTR should be lowercase. + */ +const char * +rfc822parse_query_parameter (rfc822parse_field_t ctx, const char *attr, + int lower_value) +{ + TOKEN t, a; + + for (t = ctx; t; t = t->next) + { + /* skip to the next semicolon */ + for (; t && !(t->type == tSPECIAL && t->data[0] == ';'); t = t->next) + ; + if (!t) + return NULL; + if (is_parameter (t)) + { /* Look closer. */ + a = t->next; /* We know that this is an atom */ + if ( !a->flags.lowered ) + { + lowercase_string (a->data); + a->flags.lowered = 1; + } + if (!strcmp (a->data, attr)) + { /* found */ + t = a->next->next; + /* Either T is now an atom, a quoted string or NULL in + * which case we return an empty string. */ + + if ( lower_value && t && !t->flags.lowered ) + { + lowercase_string (t->data); + t->flags.lowered = 1; + } + return t ? t->data : ""; + } + } + } + return NULL; +} + +/**************** + * This function may be used for the Content-Type header to figure out + * the media type and subtype. Note, that the returned strings are + * guaranteed to be lowercase as required by MIME. + * + * Returns: a pointer to the media type and if subtype is not NULL, + * a pointer to the subtype. + */ +const char * +rfc822parse_query_media_type (rfc822parse_field_t ctx, const char **subtype) +{ + TOKEN t = ctx; + const char *type; + + if (t->type != tATOM) + return NULL; + if (!t->flags.lowered) + { + lowercase_string (t->data); + t->flags.lowered = 1; + } + type = t->data; + t = t->next; + if (!t || t->type != tSPECIAL || t->data[0] != '/') + return NULL; + t = t->next; + if (!t || t->type != tATOM) + return NULL; + + if (subtype) + { + if (!t->flags.lowered) + { + lowercase_string (t->data); + t->flags.lowered = 1; + } + *subtype = t->data; + } + return type; +} + + + + + +#ifdef TESTING + +/* Internal debug function to print the structure of the message. */ +static void +dump_structure (rfc822parse_t msg, part_t part, int indent) +{ + if (!part) + { + printf ("*** Structure of this message:\n"); + part = msg->parts; + } + + for (; part; part = part->right) + { + rfc822parse_field_t ctx; + part_t save_part; /* ugly hack - we should have a function to + get part inforation. */ + const char *s; + + save_part = msg->current_part; + msg->current_part = part; + ctx = rfc822parse_parse_field (msg, "Content-Type", -1); + msg->current_part = save_part; + if (ctx) + { + const char *s1, *s2; + s1 = rfc822parse_query_media_type (ctx, &s2); + if (s1) + printf ("*** %*s %s/%s", indent*2, "", s1, s2); + else + printf ("*** %*s [not found]", indent*2, ""); + + s = rfc822parse_query_parameter (ctx, "boundary", 0); + if (s) + printf (" (boundary=\"%s\")", s); + rfc822parse_release_field (ctx); + } + else + printf ("*** %*s text/plain [assumed]", indent*2, ""); + putchar('\n'); + + if (part->down) + dump_structure (msg, part->down, indent + 1); + } + +} + + + +static void +show_param (rfc822parse_field_t ctx, const char *name) +{ + const char *s; + + if (!ctx) + return; + s = rfc822parse_query_parameter (ctx, name, 0); + if (s) + printf ("*** %s: `%s'\n", name, s); +} + + + +static void +show_event (rfc822parse_event_t event) +{ + const char *s; + + switch (event) + { + case RFC822PARSE_OPEN: s= "Open"; break; + case RFC822PARSE_CLOSE: s= "Close"; break; + case RFC822PARSE_CANCEL: s= "Cancel"; break; + case RFC822PARSE_T2BODY: s= "T2Body"; break; + case RFC822PARSE_FINISH: s= "Finish"; break; + case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break; + case RFC822PARSE_BOUNDARY: s= "Boundary"; break; + case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break; + default: s= "***invalid event***"; break; + } + printf ("*** got RFC822 event %s\n", s); +} + +static int +msg_cb (void *dummy_arg, rfc822parse_event_t event, rfc822parse_t msg) +{ + show_event (event); + if (event == RFC822PARSE_T2BODY) + { + rfc822parse_field_t ctx; + void *ectx; + const char *line; + + for (ectx=NULL; (line = rfc822parse_enum_header_lines (msg, &ectx)); ) + { + printf ("*** HDR: %s\n", line); + } + rfc822parse_enum_header_lines (NULL, &ectx); /* Close enumerator. */ + + ctx = rfc822parse_parse_field (msg, "Content-Type", -1); + if (ctx) + { + const char *s1, *s2; + s1 = rfc822parse_query_media_type (ctx, &s2); + if (s1) + printf ("*** media: `%s/%s'\n", s1, s2); + else + printf ("*** media: [not found]\n"); + show_param (ctx, "boundary"); + show_param (ctx, "protocol"); + rfc822parse_release_field (ctx); + } + else + printf ("*** media: text/plain [assumed]\n"); + + } + + + return 0; +} + + + +int +main (int argc, char **argv) +{ + char line[5000]; + size_t length; + rfc822parse_t msg; + + msg = rfc822parse_open (msg_cb, NULL); + if (!msg) + abort (); + + while (fgets (line, sizeof (line), stdin)) + { + length = strlen (line); + if (length && line[length - 1] == '\n') + line[--length] = 0; + if (length && line[length - 1] == '\r') + line[--length] = 0; + if (rfc822parse_insert (msg, line, length)) + abort (); + } + + dump_structure (msg, NULL, 0); + + rfc822parse_close (msg); + return 0; +} +#endif + +/* +Local Variables: +compile-command: "gcc -Wall -g -DTESTING -o rfc822parse rfc822parse.c" +End: +*/ diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h new file mode 100644 index 000000000..1293117ac --- /dev/null +++ b/tools/rfc822parse.h @@ -0,0 +1,79 @@ +/* rfc822parse.h - Simple mail and MIME parser + * Copyright (C) 1999 Werner Koch, Duesseldorf + * Copyright (C) 2003, g10 Code GmbH + * + * 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 + */ + +#ifndef RFC822PARSE_H +#define RFC822PARSE_H + +struct rfc822parse_context; +typedef struct rfc822parse_context *rfc822parse_t; + +typedef enum + { + RFC822PARSE_OPEN = 1, + RFC822PARSE_CLOSE, + RFC822PARSE_CANCEL, + RFC822PARSE_T2BODY, + RFC822PARSE_FINISH, + RFC822PARSE_RCVD_SEEN, + RFC822PARSE_LEVEL_DOWN, + RFC822PARSE_LEVEL_UP, + RFC822PARSE_BOUNDARY, + RFC822PARSE_LAST_BOUNDARY, + RFC822PARSE_BEGIN_HEADER, + RFC822PARSE_PREAMBLE, + RFC822PARSE_EPILOGUE + } +rfc822parse_event_t; + +struct rfc822parse_field_context; +typedef struct rfc822parse_field_context *rfc822parse_field_t; + + +typedef int (*rfc822parse_cb_t) (void *opaque, + rfc822parse_event_t event, + rfc822parse_t msg); + + +rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value); + +void rfc822parse_close (rfc822parse_t msg); + +void rfc822parse_cancel (rfc822parse_t msg); +int rfc822parse_finish (rfc822parse_t msg); + +int rfc822parse_insert (rfc822parse_t msg, + const unsigned char *line, size_t length); + +char *rfc822parse_get_field (rfc822parse_t msg, const char *name, int which); + +const char *rfc822parse_enum_header_lines (rfc822parse_t msg, void **context); + +rfc822parse_field_t rfc822parse_parse_field (rfc822parse_t msg, + const char *name, + int which); + +void rfc822parse_release_field (rfc822parse_field_t field); + +const char *rfc822parse_query_parameter (rfc822parse_field_t ctx, + const char *attr, int lower_value); + +const char *rfc822parse_query_media_type (rfc822parse_field_t ctx, + const char **subtype); + +#endif /*RFC822PARSE_H */ -- cgit v1.2.3 From 4453659c9a18179f37e7f4ec051f496545cf59e2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 27 Jan 2004 19:10:38 +0000 Subject: (parse_dn_part): Pretty print the nameDistinguisher OID. (print_dn_part): Do not delimit multiple RDNs by " + ". Handle multi-valued RDNs in a special way, i.e. in the order specified by the certificate. (print_dn_parts): Simplified. --- sm/ChangeLog | 8 ++++++++ sm/certdump.c | 55 +++++++++++++++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 788c71f4d..c3b0e88b0 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2004-01-27 Werner Koch <wk@gnupg.org> + + * certdump.c (parse_dn_part): Pretty print the nameDistinguisher OID. + (print_dn_part): Do not delimit multiple RDN by " + ". Handle + multi-valued RDNs in a special way, i.e. in the order specified by + the certificate. + (print_dn_parts): Simplified. + 2004-01-16 Werner Koch <wk@gnupg.org> * sign.c (gpgsm_sign): Print an error message on all failures. diff --git a/sm/certdump.c b/sm/certdump.c index f64e985d3..505693973 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -37,6 +37,8 @@ struct dn_array_s { char *key; char *value; + int multivalued; + int done; }; @@ -213,7 +215,10 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) p[n] = 0; trim_trailing_spaces (p); if ( !strcmp (p, "1.2.840.113549.1.9.1") ) - strcpy (p, "EMail"); + strcpy (p, "EMail"); + else if ( !strcmp (p, "0.2.262.1.10.7.20") ) + strcpy (p, "NameDistinguisher"); + string = s + 1; if (*string == '#') @@ -319,11 +324,13 @@ parse_dn (const unsigned char *string) array[arrayidx].key = NULL; array[arrayidx].value = NULL; string = parse_dn_part (array+arrayidx, string); - arrayidx++; if (!string) goto failure; while (*string == ' ') string++; + array[arrayidx].multivalued = (*string == '+'); + array[arrayidx].done = 0; + arrayidx++; if (*string && *string != ',' && *string != ';' && *string != '+') goto failure; /* invalid delimiter */ if (*string) @@ -347,19 +354,31 @@ parse_dn (const unsigned char *string) static void print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) { - int any = 0; + struct dn_array_s *first_dn = dn; for (; dn->key; dn++) { - if (!strcmp (dn->key, key) && dn->value && *dn->value) + if (!dn->done && !strcmp (dn->key, key)) { - putc ('/', fp); - if (any) - fputs (" + ", fp); - else - fprintf (fp, "%s=", key); - print_sanitized_utf8_string (fp, dn->value, '/'); - any = 1; + /* Forward to the last multi-valued RDN, so that we can + print them all in reverse in the correct order. Note + that this overrides the the standard sequence but that + seems to a reasonable thing to do with multi-valued + RDNs. */ + while (dn->multivalued && dn[1].key) + dn++; + next: + if (!dn->done && dn->value && *dn->value) + { + fprintf (fp, "/%s=", dn->key); + print_sanitized_utf8_string (fp, dn->value, '/'); + } + dn->done = 1; + if (dn > first_dn && dn[-1].multivalued) + { + dn--; + goto next; + } } } } @@ -375,19 +394,11 @@ print_dn_parts (FILE *fp, struct dn_array_s *dn) int i; for (i=0; stdpart[i]; i++) - print_dn_part (fp, dn, stdpart[i]); + print_dn_part (fp, dn, stdpart[i]); - /* now print the rest without any specific ordering */ + /* Now print the rest without any specific ordering */ for (; dn->key; dn++) - { - for (i=0; stdpart[i]; i++) - { - if (!strcmp (dn->key, stdpart[i])) - break; - } - if (!stdpart[i]) - print_dn_part (fp, dn, dn->key); - } + print_dn_part (fp, dn, dn->key); } -- cgit v1.2.3 From fa5d1513a29708ce51496b4e248bcd91a81c17fe Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Jan 2004 16:19:46 +0000 Subject: (agent_marktrusted): Check whether the trustlist is writable. --- agent/ChangeLog | 5 +++++ agent/divert-scd.c | 2 +- agent/learncard.c | 1 + agent/trustlist.c | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 57f9214f6..73b9c4596 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-01-28 Werner Koch <wk@gnupg.org> + + * trustlist.c (agent_marktrusted): Check whether the trustlist is + writable. + 2004-01-27 Werner Koch <wk@gnupg.org> * sexp-parse.h: Moved to ../common. diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 69f184474..283150ad3 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -134,7 +134,7 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) } -/* Put the DIGEST into an DER encoded comtainer and return it in R_VAL. */ +/* Put the DIGEST into an DER encoded container and return it in R_VAL. */ static int encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo, unsigned char **r_val, size_t *r_len) diff --git a/agent/learncard.c b/agent/learncard.c index 28a74f972..a76f2652a 100644 --- a/agent/learncard.c +++ b/agent/learncard.c @@ -303,6 +303,7 @@ agent_handle_learn (void *assuan_context) 101, /* trusted */ 102, /* useful */ 100, /* regular */ + /* We don't include 110 here because gpgsm can't handle it. */ -1 /* end of list */ }; diff --git a/agent/trustlist.c b/agent/trustlist.c index 8575aedb0..5c3271ac0 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -236,6 +236,22 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) static char key[41]; int keyflag; char *desc; + char *fname; + + /* Check whether we are at all allowed to modify the trustlist. + This is useful so that the trustlist may be a symlink to a global + trustlist with only admin priviliges to modify it. Of course + this is not a secure way of denying access, but it avoids the + usual clicking on an Okay buttun thing most users are used to. */ + fname = make_filename (opt.homedir, "trustlist.txt", NULL); + rc = access (fname, W_OK); + if (rc && errno != ENOENT) + { + xfree (fname); + return gpg_error (GPG_ERR_EPERM); + } + xfree (fname); + if (trustfp) rewind (trustfp); -- cgit v1.2.3 From a0cb56fe7fa88c3c63be1d683e0da48488babe1d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Jan 2004 16:20:17 +0000 Subject: (gpgsm_validate_chain): Changed the message printed for an untrusted root certificate. --- sm/ChangeLog | 5 +++++ sm/certchain.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index c3b0e88b0..8d39133ad 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-01-28 Werner Koch <wk@gnupg.org> + + * certchain.c (gpgsm_validate_chain): Changed the message printed + for an untrusted root certificate. + 2004-01-27 Werner Koch <wk@gnupg.org> * certdump.c (parse_dn_part): Pretty print the nameDistinguisher OID. diff --git a/sm/certchain.c b/sm/certchain.c index 59577f6a5..64be1aed8 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -585,8 +585,8 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) { gpgsm_dump_cert ("issuer", subject_cert); log_info ("after checking the fingerprint, you may want " - "to enter it manually into " - "\"~/.gnupg-test/trustlist.txt\"\n"); + "to add it manually to the list of trusted " + "certificates.\n"); } } else -- cgit v1.2.3 From 97958029f67eee3f87ad6da48afc3ac73cbbe27f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Jan 2004 16:21:57 +0000 Subject: (iso7816_manage_security_env): New. (iso7816_decipher): Add PADIND argument. ** app-nks.c is now functional ** --- scd/ChangeLog | 5 ++ scd/app-nks.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- scd/app-openpgp.c | 3 +- scd/iso7816.c | 57 ++++++++++++---- scd/iso7816.h | 4 ++ 5 files changed, 246 insertions(+), 22 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 3a6a6aea4..66f48d467 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-01-28 Werner Koch <wk@gnupg.org> + + * iso7816.c (iso7816_manage_security_env): New. + (iso7816_decipher): Add PADIND argument. + 2004-01-27 Werner Koch <wk@gnupg.org> * command.c (cmd_readcert, cmd_readkey): Work on a copy of LINE. diff --git a/scd/app-nks.c b/scd/app-nks.c index 0a04f7511..2ceb537a2 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -33,16 +33,18 @@ #include "tlv.h" static struct { - int fid; /* File ID. */ - int certtype; /* Type of certificate or 0 if it is not a certificate. */ + int fid; /* File ID. */ + int certtype; /* Type of certificate or 0 if it is not a certificate. */ int iskeypair; /* If true has the FID of the correspoding certificate. */ + int issignkey; /* True if file is a key usable for signing. */ + int isenckey; /* True if file is a key usable for decryption. */ } filelist[] = { - { 0x4531, 0, 0xC000 }, + { 0x4531, 0, 0xC000, 1, 0 }, { 0xC000, 101 }, { 0x4331, 100 }, { 0x4332, 100 }, { 0xB000, 110 }, - { 0x45B1, 0, 0xC200 }, + { 0x45B1, 0, 0xC200, 0, 1 }, { 0xC200, 101 }, { 0x43B1, 100 }, { 0x43B2, 100 }, @@ -356,6 +358,191 @@ do_readcert (app_t app, const char *certid, } +/* Verify the PIN if required. */ +static int +verify_pin (app_t app, + int (pincb)(void*, const char *, char **), + void *pincb_arg) +{ + /* Note that force_chv1 is never set but we do it here anyway so + that other applications may euse this function. For example it + makes sense to set force_chv1 for German signature law cards. + NKS is very similar to the DINSIG draft standard. */ + if (!app->did_chv1 || app->force_chv1 ) + { + char *pinvalue; + int rc; + + rc = pincb (pincb_arg, "PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + /* The follwoing limits are due to TCOS but also defined in the + NKS specs. */ + if (strlen (pinvalue) < 6) + { + log_error ("PIN is too short; minimum length is 6\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + else if (strlen (pinvalue) > 16) + { + log_error ("PIN is too large; maximum length is 16\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + + /* Also it is possible to use a local PIN, we use the gloabl + PIN for this application. */ + rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue)); + if (rc) + { + log_error ("verify PIN failed\n"); + xfree (pinvalue); + return rc; + } + app->did_chv1 = 1; + xfree (pinvalue); + } + + return 0; +} + + + +/* Create the signature and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; + that callback should return the PIN in an allocated buffer and + store that in the 3rd argument. */ +static int +do_sign (app_t app, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + int rc, i; + int fid; + unsigned char data[35]; /* Must be large enough for a SHA-1 digest + + the largest OID _prefix above. */ + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + if (indatalen != 20 && indatalen != 16 && indatalen != 35) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check that the provided ID is vaid. This is not really needed + but we do it to to enforce correct usage by the caller. */ + if (strncmp (keyidstr, "NKS-DF01.", 9) ) + return gpg_error (GPG_ERR_INV_ID); + keyidstr += 9; + if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) + || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) + || keyidstr[4]) + return gpg_error (GPG_ERR_INV_ID); + fid = xtoi_4 (keyidstr); + for (i=0; filelist[i].fid; i++) + if (filelist[i].iskeypair && filelist[i].fid == fid) + break; + if (!filelist[i].fid) + return gpg_error (GPG_ERR_NOT_FOUND); + if (!filelist[i].issignkey) + return gpg_error (GPG_ERR_INV_ID); + + /* Prepare the DER object from INDATA. */ + if (indatalen == 35) + { + /* Alright, the caller was so kind to send us an already + prepared DER object. Check that it is waht we want and that + it matches the hash algorithm. */ + if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15)) + ; + else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15)) + ; + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data, indata, indatalen); + } + else + { + if (hashalgo == GCRY_MD_SHA1) + memcpy (data, sha1_prefix, 15); + else if (hashalgo == GCRY_MD_RMD160) + memcpy (data, rmd160_prefix, 15); + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data+15, indata, indatalen); + } + + rc = verify_pin (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + return rc; +} + + + + +/* Decrypt the data in INDATA and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; it + should return the PIN in an allocated buffer and put it into PIN. */ +static int +do_decipher (app_t app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + static const unsigned char mse_parm[] = { + 0x80, 1, 0x10, /* Select algorithm RSA. */ + 0x84, 1, 0x81 /* Select locak secret key 1 for descryption. */ + }; + int rc, i; + int fid; + + if (!keyidstr || !*keyidstr || !indatalen) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check that the provided ID is vaid. This is not really needed + but we do it to to enforce correct usage by the caller. */ + if (strncmp (keyidstr, "NKS-DF01.", 9) ) + return gpg_error (GPG_ERR_INV_ID); + keyidstr += 9; + if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) + || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) + || keyidstr[4]) + return gpg_error (GPG_ERR_INV_ID); + fid = xtoi_4 (keyidstr); + for (i=0; filelist[i].fid; i++) + if (filelist[i].iskeypair && filelist[i].fid == fid) + break; + if (!filelist[i].fid) + return gpg_error (GPG_ERR_NOT_FOUND); + if (!filelist[i].isenckey) + return gpg_error (GPG_ERR_INV_ID); + + /* Do the TCOS specific MSE. */ + rc = iso7816_manage_security_env (app->slot, + 0xC1, 0xB8, + mse_parm, sizeof mse_parm); + if (!rc) + rc = verify_pin (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_decipher (app->slot, indata, indatalen, 0x81, + outdata, outdatalen); + return rc; +} + + /* Select the NKS 2.0 application on the card in SLOT. */ int @@ -375,9 +562,9 @@ app_select_nks (APP app) app->fnc.getattr = NULL; app->fnc.setattr = NULL; app->fnc.genkey = NULL; - app->fnc.sign = NULL; + app->fnc.sign = do_sign; app->fnc.auth = NULL; - app->fnc.decipher = NULL; + app->fnc.decipher = do_decipher; app->fnc.change_pin = NULL; app->fnc.check_pin = NULL; } diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 75e3e299e..021d6a52c 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1121,7 +1121,8 @@ do_decipher (APP app, const char *keyidstr, rc = verify_chv2 (app, pincb, pincb_arg); if (!rc) - rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen); + rc = iso7816_decipher (app->slot, indata, indatalen, 0, + outdata, outdatalen); return rc; } diff --git a/scd/iso7816.c b/scd/iso7816.c index 9a15ce953..1ee9b55e7 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -1,5 +1,5 @@ /* iso7816.c - ISO 7816 commands - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -47,6 +47,7 @@ #define CMD_RESET_RETRY_COUNTER 0x2C #define CMD_GET_DATA 0xCA #define CMD_PUT_DATA 0xDA +#define CMD_MSE 0x22 #define CMD_PSO 0x2A #define CMD_INTERNAL_AUTHENTICATE 0x88 #define CMD_GENERATE_KEYPAIR 0x47 @@ -270,6 +271,23 @@ iso7816_put_data (int slot, int tag, return map_sw (sw); } +/* Manage Security Environment. This is a weird operation and there + is no easy abstraction for it. Furthermore, some card seem to have + a different interpreation of 7816-8 and thus we resort to let the + caller decide what to do. */ +gpg_error_t +iso7816_manage_security_env (int slot, int p1, int p2, + const unsigned char *data, size_t datalen) +{ + int sw; + + if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 || !data || !datalen) + return gpg_error (GPG_ERR_INV_VALUE); + + sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, datalen, data); + return map_sw (sw); +} + /* Perform the security operation COMPUTE DIGITAL SIGANTURE. On success 0 is returned and the data is availavle in a newly @@ -301,13 +319,14 @@ iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, } -/* Perform the security operation DECIPHER. On - success 0 is returned and the plaintext is available in a newly - allocated buffer stored at RESULT with its length stored at - RESULTLEN. */ +/* Perform the security operation DECIPHER. PADIND is the padding + indicator to be used. It should be 0 if no padding is required, a + value of -1 suppresses the padding byte. On success 0 is returned + and the plaintext is available in a newly allocated buffer stored + at RESULT with its length stored at RESULTLEN. */ gpg_error_t iso7816_decipher (int slot, const unsigned char *data, size_t datalen, - unsigned char **result, size_t *resultlen) + int padind, unsigned char **result, size_t *resultlen) { int sw; unsigned char *buf; @@ -317,15 +336,23 @@ iso7816_decipher (int slot, const unsigned char *data, size_t datalen, *result = NULL; *resultlen = 0; - /* We need to prepend the padding indicator. */ - buf = xtrymalloc (datalen + 1); - if (!buf) - return out_of_core (); - *buf = 0; /* Padding indicator. */ - memcpy (buf+1, data, datalen); - sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf, - result, resultlen); - xfree (buf); + if (padind >= 0) + { + /* We need to prepend the padding indicator. */ + buf = xtrymalloc (datalen + 1); + if (!buf) + return out_of_core (); + *buf = padind; /* Padding indicator. */ + memcpy (buf+1, data, datalen); + sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf, + result, resultlen); + xfree (buf); + } + else + { + sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen, data, + result, resultlen); + } if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ diff --git a/scd/iso7816.h b/scd/iso7816.h index 98e688693..937326b6d 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -42,11 +42,15 @@ gpg_error_t iso7816_get_data (int slot, int tag, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_put_data (int slot, int tag, const unsigned char *data, size_t datalen); +gpg_error_t iso7816_manage_security_env (int slot, int p1, int p2, + const unsigned char *data, + size_t datalen); gpg_error_t iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_decipher (int slot, const unsigned char *data, size_t datalen, + int padind, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_internal_authenticate (int slot, const unsigned char *data, size_t datalen, -- cgit v1.2.3 From d6fe40e8d523acb99f13573ba78a8bb47f8c65e0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Jan 2004 16:22:25 +0000 Subject: add a few notes. --- TODO | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/TODO b/TODO index 621b278ba..ce1f6a7da 100644 --- a/TODO +++ b/TODO @@ -11,6 +11,7 @@ We should always use valid S-Exp and not just parts. ** When we allow concurrent service request in gpgsm, we might want to have an agent context for each service request (i.e. Assuan context). +** There is no error report if GPG_AGENT_INFO has been set but the agent is not anymore running. * sm/certreqgen.c ** Improve error reporting @@ -23,6 +24,11 @@ might want to have an agent context for each service request ** Try all available root certs in case we have several of them in our keybox. For example TC TrustCenter Class 1 CA certs are ambiguous becuase user certs don't come with a authorityKeyIdentifier. +** Support extKeyUsage + The only value which makes sense for us is emailProtection (I have + not yet found a test cetificate with that). We might want to allow + other usages depending on special options (e.g. an option used for code + signing). * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution @@ -43,6 +49,10 @@ might want to have an agent context for each service request ** 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. + * agent/command.c ** Make sure that secure memory is used where appropriate -- cgit v1.2.3 From 42ab09e82131c628f6675ad2b306e6acf60a265c Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 28 Jan 2004 23:58:18 +0000 Subject: 2004-01-29 Marcus Brinkmann <marcus@g10code.de> * gpgconf-list.c: File removed. * README.gpgconf: New file. * gpgconf-comp.c: New file. * Makefile.am (gpgconf_SOURCES): Remove gpgconf-list.c, add gpgconf-comp.c. --- tools/ChangeLog | 8 + tools/Makefile.am | 2 +- tools/README.gpgconf | 322 ++++++++++++ tools/gpgconf-comp.c | 1321 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools/gpgconf-list.c | 60 --- tools/gpgconf.c | 74 ++- tools/gpgconf.h | 23 +- 7 files changed, 1721 insertions(+), 89 deletions(-) create mode 100644 tools/README.gpgconf create mode 100644 tools/gpgconf-comp.c delete mode 100644 tools/gpgconf-list.c diff --git a/tools/ChangeLog b/tools/ChangeLog index 33ed0fc8b..a382d05a5 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,11 @@ +2004-01-29 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-list.c: File removed. + * README.gpgconf: New file. + * gpgconf-comp.c: New file. + * Makefile.am (gpgconf_SOURCES): Remove gpgconf-list.c, add + gpgconf-comp.c. + 2004-01-16 Werner Koch <wk@gnupg.org> * watchgnupg.c (main): Need to use FD_ISSET for the client diff --git a/tools/Makefile.am b/tools/Makefile.am index fb2d929bf..09ba633f4 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -28,7 +28,7 @@ AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl @GPG_ERROR_CFLAGS@ bin_PROGRAMS = gpgconf -gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-list.c no-libgcrypt.c +gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @INTLLIBS@ diff --git a/tools/README.gpgconf b/tools/README.gpgconf new file mode 100644 index 000000000..c0e5511c1 --- /dev/null +++ b/tools/README.gpgconf @@ -0,0 +1,322 @@ +============ + GPG Conf +============ + +CONCEPT +======= + +gpgconf provides access to the configuration of one or more components +of the GnuPG system. These components correspond more or less to the +programs that exist in the GnuPG framework, like GnuPG, GPGSM, +DirMngr, etc. But this is not a strict one-to-one relationship. Not +all configuration options are available through GPGConf. GPGConf +provides a generic and abstract method to access the most important +configuration options that can feasibly be controlled via such a +mechanism. + +GPGConf can be used to gather and change the options available in each +component, and can also provide their default values. GPGConf will +give detailed type information that can be used to restrict the user's +input without making an attempt to commit the changes. + +GPGConf provides the backend of a configuration editor. The +configuration editor would usually be a graphical user interface +program, that allows to display the current options, their default +values, and allows the user to make changes to the options. These +changes can then be made active with GPGConf again. Such a program +that uses GPGConf in this way will be called 'GUI' throughout this +document. + + +Format Conventions +================== + +Some lines in the output of GPGConf contain a list of colon-separated +fields. The following conventions apply: + +The GUI program is required to strip off trailing newline and/or carriage +return characters from the output. + +GPGConf will never leave out fields. If a certain version documents a +certain field, this field will always be present in all GPGConf +versions from that time on. + +Future versions of GPGConf might append fields to the list. New +fields will always be separated from the previously last field by a +colon separator. The GUI should be prepared to parse the last field +it knows about up until a colon or end of line. + +Not all fields are defined under all conditions. You are required to +ignore the content of undefined fields. + +Some fields contain strings that are not escaped in any way. Such +fields are described to be used "verbatim". These fields will never +contain a colon character (for obvious reasons). No de-escaping or +other formatting is required to use the field content. This is for +easy parsing of the output, when it is known that the content can +never contain any special characters. + +Some fields contain strings that are described to be +"percent-escaped". Such strings need to be de-escaped before their +content can be presented to the user. A percent-escaped string is +de-escaped by replacing all occurences of %XY by the byte that has the +hexadecimal value XY. X and Y are from the set { '0'..'9', 'a'..'f' }. + +Some fields contain strings that are described to be "localised". Such +strings are translated to the active language and formatted in the +active character set. + +Some fields contain an unsigned number. This number will always fit +into a 32-bit unsigned integer variable. The number may be followed +by a space, followed by a human readable description of that value. +You should ignore everything in the field that follows the number. + +Some fields contain a signed number. This number will always fit into +a 32-bit signed integer variable. The number may be followed by a +space, followed by a human readable description of that value. You +should ignore everything in the field that follows the number. + +Some fields contain an option argument. The format of an option +argument depends on the type of the option and on some flags: + +The simplest case is that the option does not take an argument at all +(TYPE is 0). Then the option argument is either empty if the option +is not set, or an unsigned number that specifies how often the option +occurs. If the LIST flag is not set, then the only valid number is 1. + +If the option takes a number argument (ALT-TYPE is 2 or 3), and it can +only occur once (LIST flag is not set), then the option argument is +either empty if the option is not set, or it is a number. A number is +a string that begins with an optional minus character, followed by one +or more digits. The number must fit into an integer variable +(unsigned or signed, depending on ALT-TYPE). + +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of numbers as described above. + +If the option takes a string argument (ALT-TYPE is 1), and it can only +occur once (LIST flag is not set) then the option argument is either +empty if the option is not set, or it starts with a double quote +character (") followed by a percent-escaped string that is the +argument value. Note that there is only a leading double quote +character, no trailing one. The double quote character is only needed +to be able to differentiate between no value and the empty string as +value. + +If the option takes a string argument and it can occur more than once, +then the option argument is either empty or it starts with a double +quote character (") followed by a comma-separated list of +percent-escaped strings. Obviously any commas in the individual +strings must be percent-escaped. + + +FIXME: Document the active language and active character set. Allow +to change it via the command line? + + +Components +========== + +A component is a set of configuration options that semantically belong +together. Furthermore, several changes to a component can be made in +an atomic way with a single operation. The GUI could for example +provide a menu with one entry for each component, or a window with one +tabulator sheet per component. + +The following interface is provided to list the available components: + +Command --list-components +------------------------- + +Outputs a list of all components available, one per line. The format +of each line is: + +NAME:DESCRIPTION + +NAME + +This field contains a name tag of the component. The name tag is used +to specify the component in all communication with GPGConf. The name +tag is to be used verbatim. It is not in any escaped format. + +DESCRIPTION + +The string in this field contains a human-readable description of the +component. It can be displayed to the user of the GUI for +informational purposes. It is percent-escaped and localized. + +Example: +$ gpgconf --list-components +gpg-agent:GPG Agent +dirmngr:CRL Manager + + +OPTIONS +======= + +Every component contains one or more options. Options may belong to a +group. The following command lists all options and the groups they +belong to: + +Command --list-options COMPONENT +-------------------------------- + +Lists all options (and the groups they belong to) in the component +COMPONENT. COMPONENT is the string in the field NAME in the +output of the --list-components command. + +There is one line for each option and each group. First come all +options that are not in any group. Then comes a line describing a +group. Then come all options that belong into each group. Then comes +the next group and so on. + +The format of each line is: + +NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:VALUE + +NAME + +This field contains a name tag for the group or option. The name tag +is used to specify the group or option in all communication with +GPGConf. The name tag is to be used verbatim. It is not in any +escaped format. + +FLAGS + +The flags field contains an unsigned number. Its value is the +OR-wise combination of the following flag values: + + 1 group If this flag is set, this is a line describing + a group and not an option. + O 2 optional arg If this flag is set, the argument is optional. + O 4 list If this flag is set, the option can be given + multiple times. + O 8 runtime If this flag is set, the option can be changed + at runtime. + +Flags marked with a 'O' are only defined for options (ie, if the GROUP +flag is not set). + +LEVEL + +This field is defined for options and for groups. It contains an +unsigned number that specifies the expert level under which this group +or option should be displayed. The following expert levels are +defined for options (they have analogous meaning for groups): + + 0 basic This option should always be offered to the user. + 1 advanced This option may be offered to advanced users. + 2 expert This option should only be offered to expert users. + 3 invisible This option should normally never be displayed, + not even to expert users. + 4 internal This option is for internal use only. Ignore it. + +The level of a group will always be the lowest level of all options it +contains. + +DESCRIPTION + +This field is defined for options and groups. The string in this +field contains a human-readable description of the option or group. +It can be displayed to the user of the GUI for informational purposes. +It is percent-escaped and localized. + +TYPE + +This field is only defined for options. It contains an unsigned +number that specifies the type of the option's argument, if any. +The following types are defined: + + 0 none No argument allowed. + 1 string An unformatted string. + 2 int32 A signed integer number. + 3 uint32 An unsigned integer number. + 4 pathname A string that describes the pathname of a file. + The file does not necessarily need to exist. + 5 ldap server A string that describes an LDAP server in the format + HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. + +More types will be added in the future. Please see the ALT-TYPE field +for information on how to cope with unknown types. + +ALT-TYPE + +This field is identical to TYPE, except that only the types 0 to 3 are +allowed. The GUI is expected to present the user the option in the +format specified by TYPE. But if the argument type TYPE is not +supported by the GUI, it can still display the option in the more +generic basic type ALT-TYPE. The GUI must support the basic types 0 +to 3 to be able to display all options. + +ARGNAME + +This field is only defined for options with an argument type TYPE that +is not 0. In this case it may contain a percent-escaped and localised +string that gives a short name for the argument. The field may also +be empty, though, in which case a short name is not known. + +DEFAULT + +This field is defined only for options. Its format is that of an +option argument (see section Format Conventions for details). If the +default value is empty, then no default is known. Otherwise, the +value specifies the default value for this option. Note that this +field is also meaningful if the option itself does not take a real +argument. + +VALUE + +This field is defined only for options. Its format is that of an +option argument. If it is empty, then the option is not explicitely +set in the current configuration, and the default applies (if any). +Otherwise, it contains the current value of the option. Note that +this field is also meaningful if the option itself does not take a +real argument. + + +CHANGING OPTIONS +================ + +To change the options for a component, you must provide them in the +following format: + +NAME:NEW-VALUE + +NAME + +This is the name of the option to change. + +NEW-VALUE + +The new value for the option. The format is that of an option +argument. If it is empty (or the field is omitted), the option will +be deleted, so that the default value is used. Otherwise, the option +will be set to the specified value. + +Option --runtime +---------------- + +If this option is set, the changes will take effect at run-time, as +far as this is possible. Otherwise, they will take effect at the next +start of the respective backend programs. + + +BACKENDS +======== + +Backends should support the following commands: + +Command --gpgconf-list +---------------------- + +List the location of the configuration file, and all default values of +all options. The location of the configuration file must be an +absolute pathname. + +Example: +$ dirmngr --gpgconf-list +gpgconf-config-file:/mnt/marcus/.gnupg/dirmngr.conf +ldapservers-file:/mnt/marcus/.gnupg/dirmngr_ldapservers.conf +add-servers: +max-replies:10 diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c new file mode 100644 index 000000000..0e0ae5d7c --- /dev/null +++ b/tools/gpgconf-comp.c @@ -0,0 +1,1321 @@ +/* gpgconf-comp.c - Configuration utility for GnuPG. + Copyright (C) 2003 g10 Code GmbH + + 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 GnuPG; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +/* FIXME use gettext.h */ +#include <libintl.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <assert.h> +#include <errno.h> +#include <time.h> + +#include <error.h> + +#include "gpgconf.h" + + +/* TODO: + Portability - Add gnulib replacements for getline, error, etc. + Backend: File backend must be able to write out changes !!! + Components: Add more components and their options. + Robustness: Do more validation. Call programs to do validation for us. +*/ + + +/* Backend configuration. Backends are used to decide how the default + and current value of an option can be determined, and how the + option can be changed. To every option in every component belongs + exactly one backend that controls and determines the option. Some + backends are programs from the GPG system. Others might be + implemented by GPGConf itself. If you change this enum, don't + forget to update GC_BACKEND below. */ +typedef enum + { + /* Any backend, used for find_option (). */ + GC_BACKEND_ANY, + + /* The Gnu Privacy Guard. */ + GC_BACKEND_GPG, + + /* The Gnu Privacy Guard for S/MIME. */ + GC_BACKEND_GPGSM, + + /* The GPG Agent. */ + GC_BACKEND_GPG_AGENT, + + /* The Aegypten directory manager. */ + GC_BACKEND_DIRMNGR, + + /* The LDAP server list file for the Aegypten director manager. */ + GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST, + + /* The number of the above entries. */ + GC_BACKEND_NR + } gc_backend_t; + + +/* To be able to implement generic algorithms for the various + backends, we collect all information about them in this struct. */ +static struct +{ + /* The name of the backend. */ + const char *name; + + /* The name of the program that acts as the backend. Some backends + don't have an associated program, but are implemented directly by + GPGConf. In this case, PROGRAM is NULL. */ + char *program; + + /* The option name for the configuration filename of this backend. + This must be an absolute pathname. It can be an option from a + different backend (but then ordering of the options might + matter). */ + const char *option_config_filename; + + /* If this is a file backend rather than a program backend, then + this is the name of the option associated with the file. */ + const char *option_name; +} gc_backend[GC_BACKEND_NR] = + { + { NULL, NULL, NULL }, /* GC_BACKEND_ANY dummy entry. */ + { "GnuPG", "gpg", "gpgconf-config-file" }, + { "GPGSM", "gpgsm", "gpgconf-config-file" }, + { "GPG Agent", "gpg-agent", "gpgconf-config-file" }, + { "DirMngr", "dirmngr", "gpgconf-config-file" }, + { "DirMngr LDAP Server List", NULL, "ldapserverlist-file", "LDAP Server" }, + }; + + +/* Option configuration. */ + +/* An option might take an argument, or not. Argument types can be + basic or complex. Basic types are generic and easy to validate. + Complex types provide more specific information about the intended + use, but can be difficult to validate. If you add to this enum, + don't forget to update GC_ARG_TYPE below. YOU MUST NOT CHANGE THE + NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL + INTERFACE. */ +typedef enum + { + /* Basic argument types. */ + + /* No argument. */ + GC_ARG_TYPE_NONE = 0, + + /* A String argument. */ + GC_ARG_TYPE_STRING = 1, + + /* A signed integer argument. */ + GC_ARG_TYPE_INT32 = 2, + + /* An unsigned integer argument. */ + GC_ARG_TYPE_UINT32 = 3, + + + /* Complex argument types. */ + + /* A complete pathname. */ + GC_ARG_TYPE_PATHNAME = 4, + + /* An LDAP server in the format + HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. */ + GC_ARG_TYPE_LDAP_SERVER = 5, + + /* A 40 character fingerprint. */ + GC_ARG_TYPE_KEY_FPR = 6, + + /* ADD NEW ENTRIES HERE. */ + + /* The number of the above entries. */ + GC_ARG_TYPE_NR + } gc_arg_type_t; + + +/* For every argument, we record some information about it in the + following struct. */ +static struct +{ + /* For every argument type exists a basic argument type that can be + used as a fallback for input and validation purposes. */ + gc_arg_type_t fallback; + + /* Human-readable name of the type. */ + const char *name; +} gc_arg_type[GC_ARG_TYPE_NR] = + { + /* The basic argument types have their own types as fallback. */ + { GC_ARG_TYPE_NONE, "none" }, + { GC_ARG_TYPE_STRING, "string" }, + { GC_ARG_TYPE_INT32, "int32" }, + { GC_ARG_TYPE_UINT32, "uint32" }, + + /* The complex argument types have a basic type as fallback. */ + { GC_ARG_TYPE_STRING, "pathname" }, + { GC_ARG_TYPE_STRING, "ldap server" }, + { GC_ARG_TYPE_STRING, "key fpr" }, + }; + + +/* Every option has an associated expert level, than can be used to + hide advanced and expert options from beginners. If you add to + this list, don't forget to update GC_LEVEL below. YOU MUST NOT + CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE + EXTERNAL INTERFACE. */ +typedef enum + { + /* The basic options should always be displayed. */ + GC_LEVEL_BASIC, + + /* The advanced options may be hidden from beginners. */ + GC_LEVEL_ADVANCED, + + /* The expert options should only be displayed to experts. */ + GC_LEVEL_EXPERT, + + /* The invisible options should normally never be displayed. */ + GC_LEVEL_INVISIBLE, + + /* The internal options are never exported, they mark options that + are recorded for internal use only. */ + GC_LEVEL_INTERNAL, + + /* ADD NEW ENTRIES HERE. */ + + /* The number of the above entries. */ + GC_LEVEL_NR + } gc_expert_level_t; + +/* A description for each expert level. */ +static struct +{ + const char *name; +} gc_level[] = + { + { "basic" }, + { "advanced" }, + { "expert" }, + { "invisible" }, + { "internal" } + }; + + +/* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING + FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ +#define GC_OPT_FLAG_NONE 0 +/* Some entries in the option list are not options, but mark the + beginning of a new group of options. These entries have the GROUP + flag set. */ +#define GC_OPT_FLAG_GROUP (1 << 0) +/* The ARG_OPT flag for an option indicates that the argument is + optional. */ +#define GC_OPT_FLAG_ARG_OPT (1 << 1) +/* The LIST flag for an option indicates that the option can occur + several times. A comma separated list of arguments is used as the + argument value. */ +#define GC_OPT_FLAG_LIST (1 << 2) +/* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1 << 3) + +/* A human-readable description for each flag. */ +static struct +{ + const char *name; +} gc_flag[] = + { + { "group" }, + { "optional arg" }, + { "list" }, + { "runtime" } + }; + + +/* To each option, or group marker, the information in the GC_OPTION + struct is provided. If you change this, don't forget to update the + option list of each component. */ +struct gc_option +{ + /* If this is NULL, then this is a terminator in an array of unknown + length. Otherwise, if this entry is a group marker (see FLAGS), + then this is the name of the group described by this entry. + Otherwise it is the name of the option described by this + entry. The name must not contain a colon. */ + const char *name; + + /* The option flags. If the GROUP flag is set, then this entry is a + group marker, not an option, and only the fields LEVEL, + DESC_DOMAIN and DESC are valid. In all other cases, this entry + describes a new option and all fields are valid. */ + unsigned int flags; + + /* The expert level. This field is valid for options and groups. A + group has the expert level of the lowest-level option in the + group. */ + gc_expert_level_t level; + + /* A gettext domain in which the following description can be found. + If this is NULL, then DESC is not translated. Valid for groups + and options. */ + const char *desc_domain; + + /* A gettext description for this group or option. If it starts + with a '|', then the string up to the next '|' describes the + argument, and the description follows the second '|'. */ + const char *desc; + + /* The following fields are only valid for options. */ + + /* The type of the option argument. */ + gc_arg_type_t arg_type; + + /* The backend that implements this option. */ + gc_backend_t backend; + + /* The following fields are set to NULL at startup (because all + option's are declared as static variables). They are at the end + of the list so that they can be omitted from the option + declarations. */ + + /* The default value for this option. This is NULL if the option is + not present in the backend, the empty string if no default is + available, and otherwise a quoted string. */ + char *default_value; + + /* The current value of this option. */ + char *value; + + /* The new value of this option. */ + char *new_value; +}; +typedef struct gc_option gc_option_t; + +/* Use this macro to terminate an option list. */ +#define GC_OPTION_NULL { NULL } + + +/* The options of the GC_COMPONENT_GPG_AGENT component. */ +static gc_option_t gc_options_gpg_agent[] = + { + GC_OPTION_NULL + }; + + +/* The options of the GC_COMPONENT_DIRMNGR component. */ +static gc_option_t gc_options_dirmngr[] = + { + /* The configuration file to which we write the changes. */ + { "gpgconf-config-file", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, + + { "Monitor", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the diagnostic output" }, + { "verbose", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "verbose", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "be somewhat more quiet", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + + { "Format", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the format of the output" }, + { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "sh-style command output", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "csh-style command output", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + + { "Configuration", + GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, + NULL, "Options controlling the configuration" }, + { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "dirmngr", "|FILE|read options from FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, + + { "Debug", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "dirmngr", "Options useful for debugging" }, + { "debug", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + "dirmngr", "|FLAGS|set the debugging FLAGS", + GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, + { "debug-all", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "set all debugging flags", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "do not detach from the console", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "|FILE|write logs to FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, + { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, + { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, + + { "Enforcement", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the interactivity and enforcement" }, + { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "run without asking a user", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "force loading of outdated CRLs", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + + { "LDAP", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Configuration of LDAP servers to use" }, + { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "add new servers discovered in CRL distribution points" + " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "|N|set LDAP timeout to N seconds", + GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, + /* The following entry must not be removed, as it is required for + the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST. */ + { "ldapserverlist-file", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + "dirmngr", "|FILE|read LDAP server list from FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, + /* This entry must come after at least one entry for + GC_BACKEND_DIRMNGR in this component, so that the entry for + "ldapserverlist-file will be initialized before this one. */ + { "LDAP Server", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + NULL, "LDAP server list", + GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST }, + + { "CRL", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Configuration of the CRL" }, + { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "|N|do not return more than N items in one query", + GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, + + GC_OPTION_NULL + }; + + +/* Component system. Each component is a set of options that can be + configured at the same time. If you change this, don't forget to + update GC_COMPONENT below. */ +typedef enum + { + /* The GPG Agent. */ + GC_COMPONENT_GPG_AGENT, + + /* The LDAP Directory Manager for CRLs. */ + GC_COMPONENT_DIRMNGR, + + /* The number of components. */ + GC_COMPONENT_NR + } gc_component_t; + + +/* The information associated with each component. */ +static struct +{ + /* The name of this component. Must not contain a colon (':') + character. */ + const char *name; + + /* The gettext domain for the description DESC. If this is NULL, + then the description is not translated. */ + const char *desc_domain; + + /* The description for this domain. */ + const char *desc; + + /* The list of options for this component, terminated by + GC_OPTION_NULL. */ + gc_option_t *options; +} gc_component[] = + { + { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, + { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr } + }; + + +/* Robust version of dgettext. */ +static const char * +my_dgettext (const char *domain, const char *msgid) +{ + if (domain) + { + char *text = dgettext (domain, msgid); + return text ? text : msgid; + } + else + return msgid; +} + + +/* Percent-Escape special characters. The string is valid until the + next invocation of the function. */ +static char * +percent_escape (const char *src) +{ + static char *esc_str; + static int esc_str_len; + int new_len = 3 * strlen (src) + 1; + char *dst; + + if (esc_str_len < new_len) + { + char *new_esc_str = realloc (esc_str, new_len); + if (!new_esc_str) + error (1, 1, "Can not escape string"); + esc_str = new_esc_str; + esc_str_len = new_len; + } + + dst = esc_str; + while (*src) + { + if (*src == '%') + { + *(dst++) = '%'; + *(dst++) = '2'; + *(dst++) = '5'; + } + else if (*src == ':') + { + /* The colon is used as field separator. */ + *(dst++) = '%'; + *(dst++) = '3'; + *(dst++) = 'a'; + } + else if (*src == ',') + { + /* The comma is used as list separator. */ + *(dst++) = '%'; + *(dst++) = '2'; + *(dst++) = 'c'; + } + else + *(dst++) = *(src); + src++; + } + *dst = '\0'; + return esc_str; +} + + + +/* List all components that are available. */ +void +gc_component_list_components (FILE *out) +{ + gc_component_t idx; + + for (idx = 0; idx < GC_COMPONENT_NR; idx++) + { + const char *desc = gc_component[idx].desc; + desc = my_dgettext (gc_component[idx].desc_domain, desc); + fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc)); + } +} + + +/* Find the component with the name NAME. Returns -1 if not + found. */ +int +gc_component_find (const char *name) +{ + gc_component_t idx; + + for (idx = 0; idx < GC_COMPONENT_NR; idx++) + { + if (!strcmp (name, gc_component[idx].name)) + return idx; + } + return -1; +} + + +/* List all options of the component COMPONENT. */ +void +gc_component_list_options (int component, FILE *out) +{ + const gc_option_t *option = gc_component[component].options; + + while (option->name) + { + const char *desc = NULL; + char *arg_name = NULL; + + /* Do not output unknown or internal options. */ + if (!option->default_value || option->level == GC_LEVEL_INTERNAL) + { + option++; + continue; + } + + if (option->desc) + { + desc = my_dgettext (option->desc_domain, option->desc); + + if (*desc == '|') + { + const char *arg_tail = strchr (&desc[1], '|'); + + if (arg_tail) + { + int arg_len = arg_tail - &desc[1]; + arg_name = malloc (arg_len + 1); + if (!arg_name) + error (1, 1, "Can not build argument name"); + memcpy (arg_name, &desc[1], arg_len); + arg_name[arg_len] = '\0'; + desc = arg_tail + 1; + } + } + } + + /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR + ORDER IS PART OF THE EXTERNAL INTERFACE. YOU MUST NOT REMOVE + ANY FIELDS. */ + + /* The name field. */ + fprintf (out, "%s", option->name); + + /* The flags field. */ + fprintf (out, ":%u", option->flags); + if (opt.verbose) + { + putc (' ', out); + + if (!option->flags) + fprintf (out, "none"); + else + { + unsigned int flags = option->flags; + unsigned int flag = 0; + unsigned int first = 1; + + while (flags) + { + if (flags & 1) + { + if (first) + first = 0; + else + putc (',', out); + fprintf (out, "%s", gc_flag[flag].name); + } + flags >>= 1; + flag++; + } + } + } + + /* The level field. */ + fprintf (out, ":%u", option->level); + if (opt.verbose) + fprintf (out, " %s", gc_level[option->level].name); + + /* The description field. */ + fprintf (out, ":%s", desc ? percent_escape (desc) : ""); + + /* The type field. */ + fprintf (out, ":%u", option->arg_type); + if (opt.verbose) + fprintf (out, " %s", gc_arg_type[option->arg_type].name); + + /* The alternate type field. */ + fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback); + if (opt.verbose) + fprintf (out, " %s", + gc_arg_type[gc_arg_type[option->arg_type].fallback].name); + + /* The argument name field. */ + fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : ""); + if (arg_name) + free (arg_name); + + /* The default value field. */ + fprintf (out, ":%s", option->default_value ? option->default_value : ""); + + /* The value field. */ + fprintf (out, ":%s", option->value ? option->value : ""); + + /* ADD NEW FIELDS HERE. */ + + putc ('\n', out); + option++; + } +} + + +/* Find the option NAME in component COMPONENT, for the backend + BACKEND. If BACKEND is GC_BACKEND_ANY, any backend will match. */ +static gc_option_t * +find_option (gc_component_t component, const char *name, + gc_backend_t backend) +{ + gc_option_t *option = gc_component[component].options; + while (option->name) + { + if (!(option->flags & GC_OPT_FLAG_GROUP) + && !strcmp (option->name, name) + && (backend == GC_BACKEND_ANY || option->backend == backend)) + break; + option++; + } + return option->name ? option : NULL; +} + + +/* Determine the configuration pathname for the component COMPONENT + and backend BACKEND. */ +static char * +get_config_pathname (gc_component_t component, gc_backend_t backend) +{ + char *pathname; + gc_option_t *option = find_option + (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY); + assert (option); + + if (!option->default_value) + error (1, 0, "Option %s, needed by backend %s, was not initialized", + gc_backend[backend].option_config_filename, + gc_backend[backend].name); + if (*option->value) + pathname = option->value; + else + pathname = option->default_value; + + if (*pathname != '/') + error (1, 0, "Option %s, needed by backend %s, is not absolute", + gc_backend[backend].option_config_filename, + gc_backend[backend].name); + + return pathname; +} + + +/* Retrieve the options for the component COMPONENT from backend + BACKEND, which we already know is a program-type backend. */ +static void +retrieve_options_from_program (gc_component_t component, gc_backend_t backend) +{ + char *cmd_line; + char *line = NULL; + size_t line_len = 0; + ssize_t length; + FILE *output; + + asprintf (&cmd_line, "%s --gpgconf-list", gc_backend[backend].program); + if (!cmd_line) + error (1, 1, "Can not construct command line"); + + output = popen (cmd_line, "r"); + if (!output) + error (1, 1, "Could not gather active options from %s", cmd_line); + + while ((length = getline (&line, &line_len, output)) > 0) + { + gc_option_t *option; + char *default_value; + char *value; + + /* Strip newline and carriage return, if present. */ + while (length > 0 + && (line[length - 1] == '\n' || line[length - 1] == '\r')) + line[--length] = '\0'; + + /* Extract default value and value, if present. Default to + empty if not. */ + default_value = strchr (line, ':'); + if (!default_value) + { + default_value = ""; + value = ""; + } + else + { + *(default_value++) = '\0'; + value = strchr (default_value, ':'); + if (!value) + value = ""; + else + { + char *end; + + *(value++) = '\0'; + end = strchr (value, ':'); + if (end) + *end = '\0'; + } + } + + /* Look up the option in the component and install the + configuration data. */ + option = find_option (component, line, backend); + if (option) + { + if (option->default_value) + error (1, 1, "Option %s returned twice from %s", + line, cmd_line); + option->default_value = strdup (default_value); + option->value = strdup (value); + if (!option->default_value || !option->value) + error (1, 1, "Could not store options"); + } + } + if (ferror (output)) + error (1, 1, "Error reading from %s", cmd_line); + if (fclose (output) && ferror (output)) + error (1, 1, "Error closing %s", cmd_line); + free (cmd_line); +} + + +/* Retrieve the options for the component COMPONENT from backend + BACKEND, which we already know is of type file list. */ +static void +retrieve_options_from_file (gc_component_t component, gc_backend_t backend) +{ + gc_option_t *list_option; + char *list_pathname; + FILE *list_file; + char *line = NULL; + size_t line_len = 0; + ssize_t length; + char *list; + + list_option = find_option (component, + gc_backend[backend].option_name, GC_BACKEND_ANY); + assert (list_option); + + list_pathname = get_config_pathname (component, backend); + + list_file = fopen (list_pathname, "r"); + if (ferror (list_file)) + error (1, 1, "Can not open list file %s", list_pathname); + + list = strdup ("\""); + if (!list) + error (1, 1, "Can not allocate initial list string"); + + while ((length = getline (&line, &line_len, list_file)) > 0) + { + char *start; + char *end; + char *new_list; + + start = line; + while (*start == ' ' || *start == '\t') + start++; + if (!*start || *start == '#' || *start == '\r' || *start == '\n') + continue; + + end = start; + while (*end && *end != '#' && *end != '\r' && *end != '\n') + end++; + /* Walk back to skip trailing white spaces. Looks evil, but + works because of the conditions on START and END imposed + at this point (END is at least START + 1, and START is + not a whitespace character). */ + while (*(end - 1) == ' ' || *(end - 1) == '\t') + end--; + *end = '\0'; + /* FIXME: Oh, no! This is so lame! Use realloc and really + append. */ + if (list) + { + asprintf (&new_list, "%s,%s", list, percent_escape (start)); + free (list); + list = new_list; + } + if (!list) + error (1, 1, "Can not construct list"); + } + if (ferror (list_file)) + error (1, 1, "Can not read list file %s", list_pathname); + list_option->default_value = ""; + list_option->value = list; +} + + +/* Retrieve the currently active options and their defaults from all + involved backends for this component. */ +void +gc_component_retrieve_options (int component) +{ + int backend_seen[GC_BACKEND_NR]; + gc_backend_t backend; + gc_option_t *option = gc_component[component].options; + + for (backend = 0; backend < GC_BACKEND_NR; backend++) + backend_seen[backend] = 0; + + while (option->name) + { + if (!(option->flags & GC_OPT_FLAG_GROUP)) + { + backend = option->backend; + + if (backend_seen[backend]) + { + option++; + continue; + } + backend_seen[backend] = 1; + + assert (backend != GC_BACKEND_ANY); + + if (gc_backend[backend].program) + retrieve_options_from_program (component, backend); + else + retrieve_options_from_file (component, backend); + } + option++; + } +} + + +/* Perform a simple validity check based on the type. */ +static void +option_check_validity (gc_option_t *option, const char *new_value) +{ + if (option->new_value) + error (1, 0, "Option %s already changed", option->name); + + if (!*new_value) + return; + + /* FIXME. Verify that lists are lists, numbers are numbers, strings + are strings, etc. */ +} + + +/* Create and verify the new configuration file for the specified + backend and component. Returns 0 on success and -1 on error. */ +static int +change_options_file (gc_component_t component, gc_backend_t backend, + char **src_filenamep, char **dest_filenamep, + char **orig_filenamep) +{ + /* FIXME. */ + assert (!"Not implemented."); + return -1; +} + + +/* Create and verify the new configuration file for the specified + backend and component. Returns 0 on success and -1 on error. */ +static int +change_options_program (gc_component_t component, gc_backend_t backend, + char **src_filenamep, char **dest_filenamep, + char **orig_filenamep) +{ + static const char marker[] = "###+++--- GPGConf ---+++###"; + /* True if we are within the marker in the config file. */ + int in_marker = 0; + gc_option_t *option; +#define LINE_LEN 4096 + char line[LINE_LEN]; + int res; + int fd; + FILE *src_file = NULL; + FILE *dest_file = NULL; + char *src_filename; + char *dest_filename; + char *orig_filename; + + /* FIXME. Throughout the function, do better error reporting. */ + dest_filename = strdup (get_config_pathname (component, backend)); + if (!dest_filename) + return -1; + asprintf (&src_filename, "%s.gpgconf.%i.new", dest_filename, getpid ()); + if (!src_filename) + return -1; + asprintf (&orig_filename, "%s.gpgconf.%i.bak", dest_filename, getpid ()); + if (!orig_filename) + return -1; + + res = link (dest_filename, orig_filename); + if (res < 0 && errno != ENOENT) + return -1; + if (res < 0) + { + free (orig_filename); + orig_filename = NULL; + } + /* We now initialize the return strings, so the caller can do the + cleanup for us. */ + *src_filenamep = src_filename; + *dest_filenamep = dest_filename; + *orig_filenamep = orig_filename; + + /* Use open() so that we can use O_EXCL. */ + fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd < 0) + return -1; + src_file = fdopen (fd, "w"); + res = errno; + if (!src_file) + { + errno = res; + return -1; + } + + /* Only if ORIG_FILENAME is not NULL did the configuration file + exist already. In this case, we will copy its content into the + new configuration file, changing it to our liking in the + process. */ + if (orig_filename) + { + dest_file = fopen (dest_filename, "r"); + if (!dest_file) + goto change_one_err; + + while (fgets (line, LINE_LEN, dest_file)) + { + int length; + int disable = 0; + char *start; + char *end; + + line[LINE_LEN - 1] = '\0'; + length = strlen (line); + if (length == LINE_LEN - 1) + { + /* FIXME */ + errno = ENAMETOOLONG; + goto change_one_err; + } + + if (!strncmp (marker, line, sizeof (marker) - 1)) + { + if (!in_marker) + in_marker = 1; + else + break; + } + + start = line; + while (*start == ' ' || *start == '\t') + start++; + if (*start && *start != '\r' && *start != '\n' && *start != '#') + { + char saved_end; + + end = start; + while (*end && *end != ' ' && *end != '\t' + && *end != '\r' && *end != '\n' && *end != '#') + end++; + saved_end = *end; + *end = '\0'; + + option = find_option (component, start, backend); + *end = saved_end; + if (option && option->new_value) + disable = 1; + } + if (disable) + { + if (!in_marker) + { + fprintf (src_file, + "# GPGConf disabled this option here at FIXME\n"); + if (ferror (src_file)) + goto change_one_err; + fprintf (src_file, "# %s", line); + if (ferror (src_file)) + goto change_one_err; + } + } + else + { + fprintf (src_file, "%s", line); + if (ferror (src_file)) + goto change_one_err; + } + } + if (ferror (dest_file)) + goto change_one_err; + } + + if (!in_marker) + { + /* There was no marker. This is the first time we edit the + file. We add our own marker at the end of the file and + proceed. Note that we first write a newline, this guards us + against files which lack the newline at the end of the last + line, while it doesn't hurt us in all other cases. */ + fprintf (src_file, "\n%s\n", marker); + if (ferror (src_file)) + goto change_one_err; + } + /* At this point, we have copied everything up to the end marker + into the new file, except for the options we are going to change. + Now, dump the changed options (except for those we are going to + revert to their default), and write the end marker, possibly + followed by the rest of the original file. */ + option = gc_component[component].options; + while (option->name) + { + if (!(option->flags & GC_OPT_FLAG_GROUP) + && option->backend == backend + && option->new_value + && *option->new_value) + { + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) + fprintf (src_file, "%s %s\n", option->name, &option->new_value[1]); + else if (option->arg_type == GC_ARG_TYPE_NONE) + fprintf (src_file, "%s\n", option->name); + else + fprintf (src_file, "%s %s\n", option->name, option->new_value); + if (ferror (src_file)) + goto change_one_err; + } + option++; + } + { + time_t cur_time = time (NULL); + + /* asctime() returns a string that ends with a newline + character! */ + fprintf (src_file, "%s %s", marker, asctime (localtime (&cur_time))); + if (ferror (src_file)) + goto change_one_err; + } + if (!in_marker) + { + fprintf (src_file, "# GPGConf edited this configuration file.\n"); + if (ferror (src_file)) + goto change_one_err; + fprintf (src_file, "# It will disable options before this marked " + "block, but it will\n"); + if (ferror (src_file)) + goto change_one_err; + fprintf (src_file, "# never change anything below these lines.\n"); + if (ferror (src_file)) + goto change_one_err; + } + if (dest_file) + { + while (fgets (line, LINE_LEN, dest_file)) + { + int length; + + line[LINE_LEN - 1] = '\0'; + length = strlen (line); + if (length == LINE_LEN - 1) + { + /* FIXME */ + errno = ENAMETOOLONG; + goto change_one_err; + } + fprintf (src_file, "%s", line); + if (ferror (src_file)) + goto change_one_err; + } + if (ferror (dest_file)) + goto change_one_err; + } + res = fclose (src_file); + if (res) + { + res = errno; + close (fd); + if (dest_file) + fclose (dest_file); + errno = res; + return -1; + } + close (fd); + if (dest_file) + { + res = fclose (dest_file); + if (res) + return -1; + } + return 0; + + change_one_err: + res = errno; + if (src_file) + { + fclose (src_file); + close (fd); + } + if (dest_file) + fclose (dest_file); + errno = res; + return -1; +} + +/* Read the modifications from IN and apply them. */ +void +gc_component_change_options (int component, FILE *in) +{ + int err = 0; + char *src_pathname[GC_BACKEND_NR]; + char *dest_pathname[GC_BACKEND_NR]; + char *orig_pathname[GC_BACKEND_NR]; + gc_backend_t backend; + gc_option_t *option; + char *line = NULL; + size_t line_len = 0; + ssize_t length; + + for (backend = 0; backend < GC_BACKEND_NR; backend++) + { + src_pathname[backend] = NULL; + dest_pathname[backend] = NULL; + orig_pathname[backend] = NULL; + } + + while ((length = getline (&line, &line_len, in)) > 0) + { + char *value; + + /* Strip newline and carriage return, if present. */ + while (length > 0 + && (line[length - 1] == '\n' || line[length - 1] == '\r')) + line[--length] = '\0'; + + value = strchr (line, ':'); + if (!value) + value = ""; + else + { + char *end; + + *(value++) = '\0'; + end = strchr (value, ':'); + if (end) + *end = '\0'; + } + + option = find_option (component, line, GC_BACKEND_ANY); + if (!option) + error (1, 0, "Unknown option %s", line); + + option_check_validity (option, value); + option->new_value = strdup (value); + } + + /* Now that we have collected and locally verified the changes, + write them out to new configuration files, verify them + externally, and then commit them. */ + option = gc_component[component].options; + while (option->name) + { + /* Go on if we have already seen this backend, or if there is + nothing to do. */ + if (src_pathname[option->backend] || !option->new_value) + { + option++; + continue; + } + + if (gc_backend[option->backend].program) + err = change_options_program (component, option->backend, + &src_pathname[component], + &dest_pathname[component], + &orig_pathname[component]); + else + err = change_options_file (component, option->backend, + &src_pathname[component], + &dest_pathname[component], + &orig_pathname[component]); + + if (err) + break; + + option++; + } + if (!err) + { + int i; + + for (i = 0; i < GC_COMPONENT_NR; i++) + { + if (src_pathname[i]) + { + /* FIXME: Make a verification here. */ + + assert (dest_pathname[i]); + + if (orig_pathname[i]) + err = rename (src_pathname[i], dest_pathname[i]); + else + { + /* This is a bit safer than rename() because we + expect DEST_PATHNAME not to be there. If it + happens to be there, this will fail. */ + err = link (src_pathname[i], dest_pathname[i]); + if (!err) + unlink (src_pathname[i]); + } + if (err) + break; + src_pathname[i] = NULL; + } + } + } + + if (err) + { + int i; + int res = errno; + + /* An error occured. */ + for (i = 0; i < GC_COMPONENT_NR; i++) + { + if (src_pathname[i]) + { + /* The change was not yet committed. */ + unlink (src_pathname[i]); + if (orig_pathname[i]) + unlink (orig_pathname[i]); + } + else + { + /* The changes were already committed. FIXME: This is a + tad dangerous, as we don't know if we don't overwrite + a version of the file that is even newer than the one + we just installed. */ + if (orig_pathname[i]) + rename (orig_pathname[i], dest_pathname[i]); + else + unlink (dest_pathname[i]); + } + } + errno = res; + error (1, 1, "Could not commit changes"); + } +} diff --git a/tools/gpgconf-list.c b/tools/gpgconf-list.c deleted file mode 100644 index e774d2bf4..000000000 --- a/tools/gpgconf-list.c +++ /dev/null @@ -1,60 +0,0 @@ -/* gpgconf-list.c - Print list of options. - * 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 "gpgconf.h" -#include "i18n.h" - -/* Format of the colon delimited listing is: - - Area: gpg, gpgsm, gpg-agent, scdaemon, dirmngr, "G" or empty for unspecified. - Option name: Name of the option - Expert level: Expertnesslevel of option: 0 - basic - Immediately Change: "1" is the option is immediatley changeable - (e.g. through SIGHUP) - Option index: Instance number of the option value to build lists. - Option value: Current value of the option - -*/ - - -/* List global options, i.er. those which are commonly required and - may affect more than one program. */ -static void -list_global_options (void) -{ - - -} - - - -void -gpgconf_list_standard_options (void) -{ - - list_global_options (); - - -} diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 6f4c1fbbb..f261a2c0a 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -33,12 +33,16 @@ enum cmd_and_opt_values aNull = 0, oDryRun = 'n', oOutput = 'o', - oQuiet = 'q', + oQuiet = 'q', oVerbose = 'v', + oComponent = 'c', oNoVerbose = 500, oHomedir, - - aDummy + + aListComponents, + aListOptions, + aChangeOptions, + }; @@ -47,16 +51,19 @@ static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("@Commands:\n ") }, + { aListComponents, "list-components", 256, N_("list all components") }, + { aListOptions, "list-options", 256, N_("|COMPONENT|list options") }, + { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") }, + { 301, NULL, 0, N_("@\nOptions:\n ") }, - { oOutput, "output", 2, N_("use as output file")}, + { oOutput, "output", 2, N_("use as output file") }, { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, + { oQuiet, "quiet", 0, N_("quiet") }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, - + /* hidden options */ { oNoVerbose, "no-verbose", 0, "@"}, - { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ {0} }; @@ -124,16 +131,6 @@ main (int argc, char **argv) i18n_init(); - /* Setup the default homedir. */ -#ifdef __MINGW32__ - 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; - /* Patrse the command line. */ pargs.argc = &argc; pargs.argv = &argv; @@ -143,14 +140,17 @@ main (int argc, char **argv) switch (pargs.r_opt) { case oOutput: opt.outfile = pargs.r.ret_str; break; - - case oQuiet: opt.quiet = 1; break; + case oQuiet: opt.quiet = 1; break; case oDryRun: opt.dry_run = 1; break; case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; - case oHomedir: opt.homedir = pargs.r.ret_str; break; - case aDummy: break; + case aListComponents: + case aListOptions: + case aChangeOptions: + cmd = pargs.r_opt; + break; + default: pargs.err = 2; break; } } @@ -158,14 +158,40 @@ main (int argc, char **argv) if (log_get_errorcount (0)) exit (2); - fname = argc? *argv : NULL; + fname = argc ? *argv : NULL; switch (cmd) { + case aListComponents: default: - /* List all standard options. */ - gpgconf_list_standard_options (); + /* List all components. */ + gc_component_list_components (stdout); break; + + case aListOptions: + case aChangeOptions: + if (!fname) + { + fputs (N_("usage: gpgconf [options] "), stderr); + fputs (N_("Need one component argument"), stderr); + putc ('\n',stderr); + exit (2); + } + else + { + int idx = gc_component_find (fname); + if (idx < 0) + { + fputs (N_("Component not found"), stderr); + putc ('\n', stderr); + exit (1); + } + gc_component_retrieve_options (idx); + if (cmd == aListOptions) + gc_component_list_options (idx, stdout); + else + gc_component_change_options (idx, stdin); + } } return 0; diff --git a/tools/gpgconf.h b/tools/gpgconf.h index dd0ec2cc2..6ccc0d1dd 100644 --- a/tools/gpgconf.h +++ b/tools/gpgconf.h @@ -26,16 +26,31 @@ /* We keep all global options in the structure OPT. */ struct { int verbose; /* Verbosity level. */ - int quiet; /* Be as quiet as possible. */ + int quiet; /* Be extra quiet. */ int dry_run; /* Don't change any persistent data. */ - const char *homedir; /* Configuration directory name. */ char *outfile; /* Name of output file. */ + + int component; /* The active component. */ } opt; -/*-- gpgconf-list.c --*/ -void gpgconf_list_standard_options (void); +/*-- gpgconf-comp.c --*/ +/* List all components that are available. */ +void gc_component_list_components (FILE *out); + +/* Find the component with the name NAME. Returns -1 if not + found. */ +int gc_component_find (const char *name); + +/* Retrieve the currently active options and their defaults from all + involved backends for this component. */ +void gc_component_retrieve_options (int component); + +/* List all options of the component COMPONENT. */ +void gc_component_list_options (int component, FILE *out); +/* Read the modifications from IN and apply them. */ +void gc_component_change_options (int component, FILE *in); #endif /*GPGCONF_H*/ -- cgit v1.2.3 From b001af10acb7e263c7e575c359891c86062aecb6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Jan 2004 07:41:55 +0000 Subject: (parse_dn_part): Map common OIDs to human readable labels. Make sure that a value won't get truncated if it includes a Nul. --- README | 12 ++++++++---- sm/ChangeLog | 6 ++++++ sm/certdump.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/README b/README index 84fc8967b..d56ea71a3 100644 --- a/README +++ b/README @@ -339,17 +339,21 @@ modes for gpgsm, here is the entire list of ways to specify a key: * [NEW] Exact match by subject's DN This is indicated by a leading slash, directly followed by the - rfc2253 encoded DN of the subject. + 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=Henrich Heine,O=Poets,L=Paris,C=FR + /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 + issuer. This should return the Root cert of the issuer. See note + above. Example: @@ -359,7 +363,7 @@ modes for gpgsm, here is the entire list of ways to specify a key: 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. + the RFC2253 encoded DN of the issuer. See note above. Example: diff --git a/sm/ChangeLog b/sm/ChangeLog index 8d39133ad..cdb613b1a 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-01-29 Werner Koch <wk@gnupg.org> + + * certdump.c (parse_dn_part): Map common OIDs to human readable + labels. Make sure that a value won't get truncated if it includes + a Nul. + 2004-01-28 Werner Koch <wk@gnupg.org> * certchain.c (gpgsm_validate_chain): Changed the message printed diff --git a/sm/certdump.c b/sm/certdump.c index 505693973..26f3f7e2c 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -196,11 +196,31 @@ gpgsm_dump_cert (const char *text, ksba_cert_t cert) static const unsigned char * parse_dn_part (struct dn_array_s *array, const unsigned char *string) { + static struct { + const char *label; + const char *oid; + } label_map[] = { + /* Warning: When adding new labels, make sure that the buffer + below we be allocated large enough. */ + {"EMail", "1.2.840.113549.1.9.1" }, + {"T", "2.5.4.12" }, + {"GN", "2.5.4.42" }, + {"SN", "2.5.4.4" }, + {"NameDistinguisher", "0.2.262.1.10.7.20"}, + {"ADDR", "2.5.4.16" }, + {"BC", "2.5.4.15" }, + {"D", "2.5.4.13" }, + {"PostalCode", "2.5.4.17" }, + {"Pseudo", "2.5.4.65" }, + {"SerialNumber", "2.5.4.5" }, + {NULL, NULL} + }; const unsigned char *s, *s1; size_t n; unsigned char *p; + int i; - /* parse attributeType */ + /* Parse attributeType */ for (s = string+1; *s && *s != '='; s++) ; if (!*s) @@ -208,17 +228,25 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) n = s - string; if (!n) return NULL; /* empty key */ - array->key = p = xtrymalloc (n+1); + + /* We need to allocate a few bytes more due to the possible mapping + from the shorter OID to the longer label. */ + array->key = p = xtrymalloc (n+10); if (!array->key) return NULL; memcpy (p, string, n); p[n] = 0; trim_trailing_spaces (p); - if ( !strcmp (p, "1.2.840.113549.1.9.1") ) - strcpy (p, "EMail"); - else if ( !strcmp (p, "0.2.262.1.10.7.20") ) - strcpy (p, "NameDistinguisher"); + if (digitp (p)) + { + for (i=0; label_map[i].label; i++ ) + if ( !strcmp (p, label_map[i].oid) ) + { + strcpy (p, label_map[i].label); + break; + } + } string = s + 1; if (*string == '#') @@ -228,13 +256,18 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) s++; n = s - string; if (!n || (n & 1)) - return NULL; /* empty or odd number of digits */ + return NULL; /* Empty or odd number of digits. */ n /= 2; array->value = p = xtrymalloc (n+1); if (!p) return NULL; - for (s1=string; n; s1 += 2, n--) - *p++ = xtoi_2 (s1); + for (s1=string; n; s1 += 2, n--, p++) + { + *p = xtoi_2 (s1); + if (!*p) + *p = 0x01; /* Better print a wrong value than truncating + the string. */ + } *p = 0; } else -- cgit v1.2.3 From e4587ba874f5052a7d1aa9731e118107d7f0b189 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Jan 2004 20:16:59 +0000 Subject: * README: Updated. --- ChangeLog | 6 +++ NEWS | 4 ++ README | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- TODO | 3 ++ configure.ac | 2 +- 5 files changed, 128 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 84abc4dee..23b805c87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/NEWS b/NEWS index aff9d5468..47e72b41d 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.9.4 (unreleased) ------------------------------------------------ + * Added support for the Telesec NKS 2.0 card application. + + * Various minor bug fixes and cleanups; mainly gpgsm and gpg-agent + related. Noteworthy changes in version 1.9.3 (2003-12-23) ------------------------------------------------ diff --git a/README b/README index d56ea71a3..3eb745da7 100644 --- a/README +++ b/README @@ -1,22 +1,56 @@ -GnuPG 1.9 is a temporary project to work on GnuPG extensions; it is a -merke fo gnupg 1.3 and the old newpg package. It will eventually lead -to a GnuPG 2.0 release. + The GNU Privacy Guard 2 + ========================= + Version 1.9.x -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 +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 -You need the libgpg-error package. Libassuan, Libksba and Libgcrypt -are also required to build it. + ./configure + make + make install -Keybox is designed to be source include-able. +(Before doing install you might need to become root.) -A texinfo manual `gnupg.info' will get installed. Some commands and -options given below. +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 @@ -177,6 +211,12 @@ scdaemon: 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 @@ -261,7 +301,22 @@ private-keys-v1.d/ about. -How to specify a user ID +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 @@ -394,7 +449,7 @@ data. Some of the search modes are not yet implemented ;-) -How to import a private key +HOW TO IMPORT A PRIVATE KEY =========================== There is some limited support to import a private key from a PKCS-12 file. Note, that this does only import the private key and not any @@ -408,7 +463,7 @@ however this is in general not a good idea. If that key already exists, the protect-tool refuses to store it unless you use the option "--force". -How to export a private key +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. @@ -416,3 +471,45 @@ 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 implementation supports the OpenPGP smartcard +(surprise!); see http://g10code.com/p-card.html. + +[Fixme: We need to explain this further] + + +GPGSM, the CMS (S/MIME) implementation 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] + + + + + diff --git a/TODO b/TODO index ce1f6a7da..911841514 100644 --- a/TODO +++ b/TODO @@ -59,6 +59,9 @@ might want to have an agent context for each service request * agent/pkdecrypt.c, agent/pksign.c ** Don't use stdio to return results. +* agent/divert-scd.c + Remove the agent_reset_scd kludge. + * agent/protect-tool.c ** Export and import certificates along with the secret key. ** Make it more comfortable; i.e. copy files to the correct place. diff --git a/configure.ac b/configure.ac index cd0486f4b..f47ef1f8b 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ development_version=yes NEED_GPG_ERROR_VERSION=0.6 NEED_LIBGCRYPT_VERSION=1.1.91 NEED_LIBASSUAN_VERSION=0.6.3 -NEED_KSBA_VERSION=0.9.1 +NEED_KSBA_VERSION=0.9.2 NEED_OPENSC_VERSION=0.8.0 -- cgit v1.2.3 From b11106ebf0e34caae45a68b87fb81f63faf2004f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Jan 2004 20:17:27 +0000 Subject: * agent.h (server_control_s): Add connection_fd field. * command.c (start_command_handler): Init it here. * gpg-agent.c (agent_init_default_ctrl): and here. * call-scd.c: Add the CTRL arg to all functions calling start_scd and pass it to start_scd. Changed all callers (start_scd): Keep track of the current active connection. (agent_reset_scd): New. * command.c (start_command_handler): Call it here. * learncard.c (agent_handle_learn): Add arg CTRL; changed caller. (send_cert_back): Ditto. --- agent/ChangeLog | 15 +++++++- agent/agent.h | 23 ++++++++---- agent/call-scd.c | 107 +++++++++++++++++++++++++++++++++++++++++------------ agent/command.c | 6 ++- agent/divert-scd.c | 15 ++++++-- agent/gpg-agent.c | 2 + agent/learncard.c | 16 ++++---- 7 files changed, 138 insertions(+), 46 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 73b9c4596..4cdaadef6 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,16 @@ +2004-01-29 Werner Koch <wk@gnupg.org> + + * agent.h (server_control_s): Add connection_fd field. + * command.c (start_command_handler): Init it here. + * gpg-agent.c (agent_init_default_ctrl): and here. + * call-scd.c: Add the CTRL arg to all functions calling start_scd + and pass it to start_scd. Changed all callers + (start_scd): Keep track of the current active connection. + (agent_reset_scd): New. + * command.c (start_command_handler): Call it here. + * learncard.c (agent_handle_learn): Add arg CTRL; changed caller. + (send_cert_back): Ditto. + 2004-01-28 Werner Koch <wk@gnupg.org> * trustlist.c (agent_marktrusted): Check whether the trustlist is @@ -18,7 +31,7 @@ * findkey.c (agent_key_from_file): Now return an error code so that we have more detailed error messages in the upper layers. - This fixes the handling pinentry's cancel button. + This fixes the handling of pinentry's cancel button. * pksign.c (agent_pksign): Changed accordingly. * pkdecrypt.c (agent_pkdecrypt): Ditto. * command.c (cmd_passwd): Ditto. diff --git a/agent/agent.h b/agent/agent.h index 95b0ba4cd..b70a4ae2d 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -83,6 +83,7 @@ struct server_local_s; struct server_control_s { struct server_local_s *server_local; + int connection_fd; /* -1 or an identifier for the current connection. */ char *display; char *ttyname; char *ttytype; @@ -98,6 +99,7 @@ struct server_control_s { }; typedef struct server_control_s *CTRL; +typedef struct server_control_s *ctrl_t; struct pin_entry_info_s { @@ -194,33 +196,38 @@ int divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context); /*-- call-scd.c --*/ -int agent_card_learn (void (*kpinfo_cb)(void*, const char *), +int agent_reset_scd (ctrl_t ctrl); +int agent_card_learn (ctrl_t ctrl, + void (*kpinfo_cb)(void*, const char *), void *kpinfo_cb_arg, void (*certinfo_cb)(void*, const char *), void *certinfo_cb_arg, void (*sinfo_cb)(void*, const char *, size_t, const char *), void *sinfo_cb_arg); -int agent_card_serialno (char **r_serialno); -int agent_card_pksign (const char *keyid, +int agent_card_serialno (ctrl_t ctrl, char **r_serialno); +int agent_card_pksign (ctrl_t ctrl, + const char *keyid, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, const unsigned char *indata, size_t indatalen, char **r_buf, size_t *r_buflen); -int agent_card_pkdecrypt (const char *keyid, +int agent_card_pkdecrypt (ctrl_t ctrl, + const char *keyid, int (*getpin_cb)(void *, const char *, char*,size_t), void *getpin_cb_arg, const unsigned char *indata, size_t indatalen, char **r_buf, size_t *r_buflen); -int agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen); -int agent_card_readkey (const char *id, unsigned char **r_buf); -int agent_card_scd (const char *cmdline, +int agent_card_readcert (ctrl_t ctrl, + const char *id, char **r_buf, size_t *r_buflen); +int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf); +int agent_card_scd (ctrl_t ctrl, const char *cmdline, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, void *assuan_context); /*-- learncard.c --*/ -int agent_handle_learn (void *assuan_context); +int agent_handle_learn (ctrl_t ctrl, void *assuan_context); #endif /*AGENT_H*/ diff --git a/agent/call-scd.c b/agent/call-scd.c index f205fb074..0bb365ced 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -50,6 +50,17 @@ static ASSUAN_CONTEXT scd_ctx = NULL; #ifdef USE_GNU_PTH static pth_mutex_t scd_lock = PTH_MUTEX_INIT; #endif +/* We need to keep track of the connection currently using the SCD. + For a pipe server this is all a NOP becuase the connection will + always have the conenction indicator -1. agent_reset_scd releases + the active connection; i.e. sets it back to -1, so that a new + connection can start using the SCD. If we eventually allow + multiple SCD session we will either make scdaemon multi-threaded or + fork of a new scdaemon and let it see how it can get access to a + reader. +*/ +static int active_connection_fd = -1; +static int active_connection = 0; /* callback parameter for learn card */ struct learn_parm_s { @@ -162,9 +173,10 @@ atfork_cb (void *opaque, int where) } -/* Fork off the SCdaemon if this has not already been done */ +/* Fork off the SCdaemon if this has not already been done. Note that + this fucntion alos locks the daemon. */ static int -start_scd (void) +start_scd (ctrl_t ctrl) { int rc; const char *pgmname; @@ -182,9 +194,20 @@ start_scd (void) #endif if (scd_ctx) - return 0; /* No need to serialize things because the agent is - expected to tun as a single-thread (or may be in - future using libpth) */ + { + /* If we are not the connection currently using the SCD, return + an error. */ + if (!active_connection) + { + active_connection_fd = ctrl->connection_fd; + active_connection = 1; + } + else if (ctrl->connection_fd != active_connection_fd) + return unlock_scd (gpg_error (GPG_ERR_CONFLICT)); + + /* Okay, we scdaemon already started and used by us. */ + return 0; + } if (opt.verbose) log_info ("no running SCdaemon - starting it\n"); @@ -226,13 +249,45 @@ start_scd (void) return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON)); } scd_ctx = ctx; - + active_connection_fd = ctrl->connection_fd; + active_connection = 1; + if (DBG_ASSUAN) log_debug ("connection to SCdaemon established\n"); + return 0; } + +/* Reset the SCD if it has been used. */ +int +agent_reset_scd (ctrl_t ctrl) +{ + int rc = 0; + +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&scd_lock, 0, NULL)) + { + log_error ("failed to acquire the SCD lock for reset\n"); + return gpg_error (GPG_ERR_INTERNAL); + } +#endif + if (active_connection && active_connection_fd == ctrl->connection_fd) + { + if (scd_ctx) + rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, + NULL, NULL, NULL, NULL); + active_connection_fd = -1; + active_connection = 0; + } + + return unlock_scd (map_assuan_err (rc)); +} + + + + static AssuanError learn_status_cb (void *opaque, const char *line) @@ -264,7 +319,8 @@ learn_status_cb (void *opaque, const char *line) /* Perform the learn command and return a list of all private keys stored on the card. */ int -agent_card_learn (void (*kpinfo_cb)(void*, const char *), +agent_card_learn (ctrl_t ctrl, + void (*kpinfo_cb)(void*, const char *), void *kpinfo_cb_arg, void (*certinfo_cb)(void*, const char *), void *certinfo_cb_arg, @@ -274,7 +330,7 @@ agent_card_learn (void (*kpinfo_cb)(void*, const char *), int rc; struct learn_parm_s parm; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; @@ -330,12 +386,12 @@ get_serialno_cb (void *opaque, const char *line) /* Return the serial number of the card or an appropriate error. The serial number is returned as a hexstring. */ int -agent_card_serialno (char **r_serialno) +agent_card_serialno (ctrl_t ctrl, char **r_serialno) { int rc; char *serialno = NULL; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; @@ -405,7 +461,8 @@ inq_needpin (void *opaque, const char *line) /* Create a signature using the current card */ int -agent_card_pksign (const char *keyid, +agent_card_pksign (ctrl_t ctrl, + const char *keyid, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, const unsigned char *indata, size_t indatalen, @@ -420,7 +477,7 @@ agent_card_pksign (const char *keyid, size_t sigbuflen; *r_buf = NULL; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; @@ -476,11 +533,12 @@ agent_card_pksign (const char *keyid, /* Decipher INDATA using the current card. Note that the returned value is */ int -agent_card_pkdecrypt (const char *keyid, - int (*getpin_cb)(void *, const char *, char*, size_t), - void *getpin_cb_arg, - const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen) +agent_card_pkdecrypt (ctrl_t ctrl, + const char *keyid, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen) { int rc, i; char *p, line[ASSUAN_LINELENGTH]; @@ -489,7 +547,7 @@ agent_card_pkdecrypt (const char *keyid, size_t len; *r_buf = NULL; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; @@ -531,7 +589,8 @@ agent_card_pkdecrypt (const char *keyid, /* Read a certificate with ID into R_BUF and R_BUFLEN. */ int -agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen) +agent_card_readcert (ctrl_t ctrl, + const char *id, char **r_buf, size_t *r_buflen) { int rc; char line[ASSUAN_LINELENGTH]; @@ -539,7 +598,7 @@ agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen) size_t len; *r_buf = NULL; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; @@ -567,7 +626,7 @@ agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen) /* Read a key with ID and return it in an allocate buffer pointed to by r_BUF as a valid S-expression. */ int -agent_card_readkey (const char *id, unsigned char **r_buf) +agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf) { int rc; char line[ASSUAN_LINELENGTH]; @@ -575,7 +634,7 @@ agent_card_readkey (const char *id, unsigned char **r_buf) size_t len, buflen; *r_buf = NULL; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; @@ -642,14 +701,14 @@ pass_data_thru (void *opaque, const void *buffer, size_t length) mechanism to pass everything verbatim to SCDAEMOPN. The PIN inquirey is handled inside gpg-agent. */ int -agent_card_scd (const char *cmdline, +agent_card_scd (ctrl_t ctrl, const char *cmdline, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, void *assuan_context) { int rc; struct inq_needpin_s inqparm; - rc = start_scd (); + rc = start_scd (ctrl); if (rc) return rc; diff --git a/agent/command.c b/agent/command.c index 0406ea439..aec48e194 100644 --- a/agent/command.c +++ b/agent/command.c @@ -579,9 +579,10 @@ cmd_get_confirmation (ASSUAN_CONTEXT ctx, char *line) static int cmd_learn (ASSUAN_CONTEXT ctx, char *line) { + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; - rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL); + rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL); if (rc) log_error ("command learn failed: %s\n", gpg_strerror (rc)); return map_to_assuan_status (rc); @@ -771,6 +772,7 @@ start_command_handler (int listen_fd, int fd) else { rc = assuan_init_connected_socket_server (&ctx, fd); + ctrl.connection_fd = fd; } if (rc) { @@ -816,6 +818,8 @@ start_command_handler (int listen_fd, int fd) } } + /* Reset the SCD if needed. */ + agent_reset_scd (&ctrl); assuan_deinit_server (ctx); if (ctrl.display) diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 283150ad3..455d23068 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -81,7 +81,7 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) for (;;) { - rc = agent_card_serialno (&serialno); + rc = agent_card_serialno (ctrl, &serialno); if (!rc) { log_debug ("detected card with S/N %s\n", serialno); @@ -108,6 +108,13 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) if (!rc) { + /* We better reset the SCD now. This is kludge requred + because the scdaemon is currently not always able to + detect the presence of a card. With a fully working + scdaemon this would not be required; i.e. the pkcs#15 + support does not require it becuase OpenSC correclty + detects a present card. */ + agent_reset_scd (ctrl); if (asprintf (&desc, "%s:%%0A%%0A" " \"%.*s\"", @@ -230,7 +237,7 @@ divert_pksign (CTRL ctrl, if (rc) return rc; - rc = agent_card_pksign (kid, getpin_cb, ctrl, + rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, data, ndata, &sigval, &siglen); if (!rc) *r_sig = sigval; @@ -294,7 +301,7 @@ divert_pkdecrypt (CTRL ctrl, if (rc) return rc; - rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl, + rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl, ciphertext, ciphertextlen, &plaintext, &plaintextlen); if (!rc) @@ -310,7 +317,7 @@ divert_pkdecrypt (CTRL ctrl, int divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context) { - return agent_card_scd (cmdline, getpin_cb, ctrl, assuan_context); + return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context); } diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 47420117e..22537aa3b 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -784,6 +784,8 @@ agent_exit (int rc) void agent_init_default_ctrl (struct server_control_s *ctrl) { + ctrl->connection_fd = -1; + /* Note we ignore malloc errors because we can't do much about it and the request will fail anyway shortly after this initialization. */ diff --git a/agent/learncard.c b/agent/learncard.c index a76f2652a..76e8986f8 100644 --- a/agent/learncard.c +++ b/agent/learncard.c @@ -255,13 +255,13 @@ make_shadow_info (const char *serialno, const char *idstring) } static int -send_cert_back (const char *id, void *assuan_context) +send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context) { int rc; char *derbuf; size_t derbuflen; - rc = agent_card_readcert (id, &derbuf, &derbuflen); + rc = agent_card_readcert (ctrl, id, &derbuf, &derbuflen); if (rc) { log_error ("error reading certificate: %s\n", @@ -287,7 +287,7 @@ send_cert_back (const char *id, void *assuan_context) /* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new certificates are send via Assuan */ int -agent_handle_learn (void *assuan_context) +agent_handle_learn (ctrl_t ctrl, void *assuan_context) { int rc; struct kpinfo_cb_parm_s parm; @@ -313,12 +313,12 @@ agent_handle_learn (void *assuan_context) memset (&sparm, 0, sizeof sparm); /* Check whether a card is present and get the serial number */ - rc = agent_card_serialno (&serialno); + rc = agent_card_serialno (ctrl, &serialno); if (rc) goto leave; /* now gather all the available info */ - rc = agent_card_learn (kpinfo_cb, &parm, certinfo_cb, &cparm, + rc = agent_card_learn (ctrl, kpinfo_cb, &parm, certinfo_cb, &cparm, sinfo_cb, &sparm); if (!rc && (parm.error || cparm.error || sparm.error)) rc = parm.error? parm.error : cparm.error? cparm.error : sparm.error; @@ -354,7 +354,7 @@ agent_handle_learn (void *assuan_context) if (assuan_context) { - rc = send_cert_back (citem->id, assuan_context); + rc = send_cert_back (ctrl, citem->id, assuan_context); if (rc) goto leave; citem->done = 1; @@ -380,7 +380,7 @@ agent_handle_learn (void *assuan_context) continue; /* unknown - store it */ - rc = agent_card_readkey (item->id, &pubkey); + rc = agent_card_readkey (ctrl, item->id, &pubkey); if (rc) { log_debug ("agent_card_readkey failed: %s\n", gpg_strerror (rc)); @@ -430,7 +430,7 @@ agent_handle_learn (void *assuan_context) } if (!citem) { - rc = send_cert_back (item->id, assuan_context); + rc = send_cert_back (ctrl, item->id, assuan_context); if (rc) goto leave; } -- cgit v1.2.3 From 94c03c860e7b0262d22662bf41e9ccbb558101ff Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Jan 2004 20:17:51 +0000 Subject: (reset_notify): Release the application context and close the reader. --- scd/ChangeLog | 5 +++++ scd/command.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 66f48d467..f6fc67423 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-01-29 Werner Koch <wk@gnupg.org> + + * command.c (reset_notify): Release the application context and + close the reader. + 2004-01-28 Werner Koch <wk@gnupg.org> * iso7816.c (iso7816_manage_security_env): New. diff --git a/scd/command.c b/scd/command.c index 9e571f228..d449eee52 100644 --- a/scd/command.c +++ b/scd/command.c @@ -73,9 +73,10 @@ reset_notify (ASSUAN_CONTEXT ctx) } if (ctrl->app_ctx) { - /* FIXME: close the application. */ - xfree (ctrl->app_ctx); + int slot = ctrl->app_ctx->slot; + release_application (ctrl->app_ctx); ctrl->app_ctx = NULL; + apdu_close_reader (slot); } } -- cgit v1.2.3 From a7840b96439352fe14b62c202725837e788285f0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Jan 2004 20:20:10 +0000 Subject: New. --- tools/ChangeLog | 4 +++ tools/Makefile.am | 2 +- tools/addgnupghome | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100755 tools/addgnupghome diff --git a/tools/ChangeLog b/tools/ChangeLog index a382d05a5..215317967 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-01-29 Werner Koch <wk@gnupg.org> + + * addgnupghome: New. + 2004-01-29 Marcus Brinkmann <marcus@g10code.de> * gpgconf-list.c: File removed. diff --git a/tools/Makefile.am b/tools/Makefile.am index 09ba633f4..c24e4c7a3 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -EXTRA_DIST = Manifest watchgnupg.c +EXTRA_DIST = Manifest watchgnupg.c addgnupghome localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" diff --git a/tools/addgnupghome b/tools/addgnupghome new file mode 100755 index 000000000..20436b637 --- /dev/null +++ b/tools/addgnupghome @@ -0,0 +1,95 @@ +# !/bin/sh -*- sh -*- +# Add a new .gnupg home directory for a list of users +# +# Copyright 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. + +PGM=addgnupghome +any_error=0 + +error () { + echo "$PGM: $*" >&2 + any_error=1 +} + +info () { + echo "$PGM: $*" >&2 +} + +# Do it for one user +one_user () { + user="$1" + home=$(awk -F: -v n="$user" '$1 == n {print $6}' /etc/passwd ) + if [ -z "$home" ]; then + if awk -F: -v n="$user" '$1 == n {exit 1}' /etc/passwd; then + error "no such user \`$user'" + else + error "no home directory for user \`$user'" + fi + return + fi + if [ ! -d "$home" ]; then + error "home directory \`$home' of user \`$user' does not exist" + return + fi + if [ -d "$home/.gnupg" ]; then + info "skipping user \`$user': \`.gnupg' already exists" + return + fi + info "creating home directory \`$home/.gnupg' for \`$user'" + if ! mkdir "$home/.gnupg" ; then + error "error creating \`$home/.gnupg'" + return + fi + if ! chown $user "$home/.gnupg" ; then + error "error changing ownership of \`$home/.gnupg'" + return + fi + + if ! cd "$home/.gnupg" ; then + error "error cd-ing to \`$home/.gnupg'" + return + fi + for f in $filelist; do + if [ -d /etc/skel/.gnupg/$f ]; then + mkdir $f + else + cp /etc/skel/.gnupg/$f $f + fi + chown $user $f + done + + +} + +if [ -z "$1" ]; then + echo "usage: $PGM userids" + exit 1 +fi + +if [ ! -d /etc/skel/.gnupg ]; then + error "skeleton directory \`/etc/skel/.gnupg' does not exist" + exit 1 +fi +cd "/etc/skel/.gnupg" || (error "error cd-ing to \`/etc/skel/.gnupg'"; exit 1) +filelist=$(find . \( -type f -or -type d \) -not -name '*~' -not -name . -print) + + + +if ! umask 0077 ; then + error "error setting umask" + exit 1 +fi + +for name in $*; do + one_user $name +done + +exit $any_error -- cgit v1.2.3 From fec4dc4c99e1a1eb12b99a5bbc9d995a93bd5227 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Jan 2004 09:12:36 +0000 Subject: * configure.ac: Require libksba 0.9.3 due to another bug fix there. * sign.c (add_certificate_list): Decrement N for the first cert. * Makefile.am (sbin_SCRIPTS): New, to install addgnupghome. (EXTRA_DIST): Added rfc822parse.c rfc822parse.h gpgparsemail.c which might be useful for debugging. --- ChangeLog | 6 ++++++ NEWS | 6 +++++- configure.ac | 4 ++-- sm/ChangeLog | 4 ++++ sm/sign.c | 8 ++++++++ tools/ChangeLog | 8 +++++++- tools/Makefile.am | 6 +++++- tools/gpgparsemail.c | 2 +- 8 files changed, 38 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 23b805c87..9b729bf9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/NEWS b/NEWS index 47e72b41d..bf83f678d 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,15 @@ -Noteworthy changes in version 1.9.4 (unreleased) +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) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index f47ef1f8b..716a2f610 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.4-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.4, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -32,7 +32,7 @@ development_version=yes NEED_GPG_ERROR_VERSION=0.6 NEED_LIBGCRYPT_VERSION=1.1.91 NEED_LIBASSUAN_VERSION=0.6.3 -NEED_KSBA_VERSION=0.9.2 +NEED_KSBA_VERSION=0.9.3 NEED_OPENSC_VERSION=0.8.0 diff --git a/sm/ChangeLog b/sm/ChangeLog index cdb613b1a..a94da4eb9 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-01-30 Werner Koch <wk@gnupg.org> + + * sign.c (add_certificate_list): Decrement N for the first cert. + 2004-01-29 Werner Koch <wk@gnupg.org> * certdump.c (parse_dn_part): Map common OIDs to human readable diff --git a/sm/sign.c b/sm/sign.c index b3e3b5646..3f64c2e5e 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -244,6 +244,7 @@ add_certificate_list (CTRL ctrl, ksba_cms_t cms, ksba_cert_t cert) ksba_cert_ref (cert); n = ctrl->include_certs; + log_debug ("adding certificates at level %d\n", n); if (n == -2) { not_root = 1; @@ -252,6 +253,8 @@ add_certificate_list (CTRL ctrl, ksba_cms_t cms, ksba_cert_t cert) if (n < 0 || n > 50) n = 50; /* We better apply an upper bound */ + /* First add my own certificate unless we don't want any certificate + included at all. */ if (n) { if (not_root && gpgsm_is_root_cert (cert)) @@ -260,7 +263,12 @@ add_certificate_list (CTRL ctrl, ksba_cms_t cms, ksba_cert_t cert) err = ksba_cms_add_cert (cms, cert); if (err) goto ksba_failure; + if (n>0) + n--; } + /* Walk the chain to include all other certificates. Note that a -1 + used for N makes sure that there is no limit and all certs get + included. */ while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) ) { if (not_root && gpgsm_is_root_cert (next)) diff --git a/tools/ChangeLog b/tools/ChangeLog index 215317967..4d7511713 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2004-01-30 Werner Koch <wk@gnupg.org> + + * Makefile.am (sbin_SCRIPTS): New, to install addgnupghome. + (EXTRA_DIST): Added rfc822parse.c rfc822parse.h gpgparsemail.c + which might be useful for debugging. + 2004-01-29 Werner Koch <wk@gnupg.org> * addgnupghome: New. @@ -32,7 +38,7 @@ * watchgnupg.c: New. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 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 diff --git a/tools/Makefile.am b/tools/Makefile.am index c24e4c7a3..32dd709fa 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -17,7 +17,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -EXTRA_DIST = Manifest watchgnupg.c addgnupghome +EXTRA_DIST = Manifest watchgnupg.c \ + rfc822parse.c rfc822parse.h gpgparsemail.c \ + addgnupghome localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" @@ -26,6 +28,8 @@ INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" # require that file. It is not actually used in gpgconf. AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl @GPG_ERROR_CFLAGS@ +sbin_SCRIPTS = addgnupghome + bin_PROGRAMS = gpgconf gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c index 956cf18d9..fa848c8f6 100644 --- a/tools/gpgparsemail.c +++ b/tools/gpgparsemail.c @@ -1,5 +1,5 @@ /* gpgparsemail.c - Standalone crypto mail parser - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * -- cgit v1.2.3 From 6fe61392895b27bc42b19d940d4d8b2b48b8c07c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Jan 2004 09:47:28 +0000 Subject: (check_cert_policy): Fixed read error checking. (check_cert_policy): With no critical policies issue only a warning if the policy file does not exists. --- sm/ChangeLog | 4 ++++ sm/certchain.c | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index a94da4eb9..2a584e079 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,9 @@ 2004-01-30 Werner Koch <wk@gnupg.org> + * certchain.c (check_cert_policy): Fixed read error checking. + (check_cert_policy): With no critical policies issue only a + warning if the policy file does not exists. + * sign.c (add_certificate_list): Decrement N for the first cert. 2004-01-29 Werner Koch <wk@gnupg.org> diff --git a/sm/certchain.c b/sm/certchain.c index 64be1aed8..a48dbd737 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -127,6 +127,13 @@ check_cert_policy (ksba_cert_t cert) log_error ("failed to open `%s': %s\n", opt.policy_file, strerror (errno)); xfree (policies); + /* With no critical policies this is only a warning */ + if (!any_critical) + { + log_info (_("note: certificate policy not allowed\n")); + return 0; + } + log_error (_("certificate policy not allowed\n")); return gpg_error (GPG_ERR_NO_POLICY_MATCH); } @@ -141,13 +148,13 @@ check_cert_policy (ksba_cert_t cert) { if (!fgets (line, DIM(line)-1, fp) ) { - gpg_error_t tmperr; + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); xfree (policies); if (feof (fp)) { fclose (fp); - /* with no critical policies this is only a warning */ + /* With no critical policies this is only a warning */ if (!any_critical) { log_info (_("note: certificate policy not allowed\n")); @@ -156,7 +163,6 @@ check_cert_policy (ksba_cert_t cert) log_error (_("certificate policy not allowed\n")); return gpg_error (GPG_ERR_NO_POLICY_MATCH); } - tmperr = gpg_error (gpg_err_code_from_errno (errno)); fclose (fp); return tmperr; } @@ -193,10 +199,10 @@ check_cert_policy (ksba_cert_t cert) for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1) { if ( !(p == policies || p[-1] == '\n') ) - continue; /* does not match the begin of a line */ + continue; /* Does not match the begin of a line. */ if (p[strlen (allowed)] != ':') - continue; /* the length does not match */ - /* Yep - it does match so return okay */ + continue; /* The length does not match. */ + /* Yep - it does match so return okay. */ fclose (fp); xfree (policies); return 0; -- cgit v1.2.3 From 82097af523e854af014b0948de6df1b4a4e5a3ae Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Jan 2004 10:13:51 +0000 Subject: Post release updated --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index bf83f678d..f5d2a551c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.5 +------------------------------------------------ + + Noteworthy changes in version 1.9.4 (2004-01-30) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 716a2f610..ffb6bd788 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.4, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.5-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 0329746dce6800fd3bd5926ae4971f0e63edd6ae Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 30 Jan 2004 10:38:07 +0000 Subject: 2004-01-30 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c: Use xmalloc, libcommon's asctimestamp and gnupg_get_time, fix error() invocation and use getline() consistently. --- tools/ChangeLog | 6 ++++ tools/gpgconf-comp.c | 84 ++++++++++++++++++++-------------------------------- 2 files changed, 38 insertions(+), 52 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 4d7511713..a9254bd99 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2004-01-30 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c: Use xmalloc, libcommon's asctimestamp and + gnupg_get_time, fix error() invocation and use getline() + consistently. + 2004-01-30 Werner Koch <wk@gnupg.org> * Makefile.am (sbin_SCRIPTS): New, to install addgnupghome. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 0e0ae5d7c..5a1629fb8 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -34,6 +34,9 @@ #include <error.h> +/* For asctimestamp(), gnupg_get_time (). */ +#include "util.h" + #include "gpgconf.h" @@ -42,6 +45,8 @@ Backend: File backend must be able to write out changes !!! Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. + Don't use popen, as this will not tell us if the program had a + non-zero exit code. */ @@ -493,7 +498,7 @@ percent_escape (const char *src) { char *new_esc_str = realloc (esc_str, new_len); if (!new_esc_str) - error (1, 1, "Can not escape string"); + error (1, errno, "can not escape string"); esc_str = new_esc_str; esc_str_len = new_len; } @@ -591,9 +596,7 @@ gc_component_list_options (int component, FILE *out) if (arg_tail) { int arg_len = arg_tail - &desc[1]; - arg_name = malloc (arg_len + 1); - if (!arg_name) - error (1, 1, "Can not build argument name"); + arg_name = xmalloc (arg_len + 1); memcpy (arg_name, &desc[1], arg_len); arg_name[arg_len] = '\0'; desc = arg_tail + 1; @@ -660,7 +663,7 @@ gc_component_list_options (int component, FILE *out) /* The argument name field. */ fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : ""); if (arg_name) - free (arg_name); + xfree (arg_name); /* The default value field. */ fprintf (out, ":%s", option->default_value ? option->default_value : ""); @@ -706,7 +709,7 @@ get_config_pathname (gc_component_t component, gc_backend_t backend) assert (option); if (!option->default_value) - error (1, 0, "Option %s, needed by backend %s, was not initialized", + error (1, 0, "option %s, needed by backend %s, was not initialized", gc_backend[backend].option_config_filename, gc_backend[backend].name); if (*option->value) @@ -715,7 +718,7 @@ get_config_pathname (gc_component_t component, gc_backend_t backend) pathname = option->default_value; if (*pathname != '/') - error (1, 0, "Option %s, needed by backend %s, is not absolute", + error (1, 0, "option %s, needed by backend %s, is not absolute", gc_backend[backend].option_config_filename, gc_backend[backend].name); @@ -736,11 +739,11 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) asprintf (&cmd_line, "%s --gpgconf-list", gc_backend[backend].program); if (!cmd_line) - error (1, 1, "Can not construct command line"); + error (1, errno, "can not construct command line"); output = popen (cmd_line, "r"); if (!output) - error (1, 1, "Could not gather active options from %s", cmd_line); + error (1, errno, "could not gather active options from %s", cmd_line); while ((length = getline (&line, &line_len, output)) > 0) { @@ -784,18 +787,18 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) if (option) { if (option->default_value) - error (1, 1, "Option %s returned twice from %s", + error (1, errno, "option %s returned twice from %s", line, cmd_line); option->default_value = strdup (default_value); option->value = strdup (value); if (!option->default_value || !option->value) - error (1, 1, "Could not store options"); + error (1, errno, "could not store options"); } } if (ferror (output)) - error (1, 1, "Error reading from %s", cmd_line); + error (1, errno, "error reading from %s", cmd_line); if (fclose (output) && ferror (output)) - error (1, 1, "Error closing %s", cmd_line); + error (1, errno, "error closing %s", cmd_line); free (cmd_line); } @@ -821,11 +824,11 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) list_file = fopen (list_pathname, "r"); if (ferror (list_file)) - error (1, 1, "Can not open list file %s", list_pathname); + error (1, errno, "can not open list file %s", list_pathname); list = strdup ("\""); if (!list) - error (1, 1, "Can not allocate initial list string"); + error (1, errno, "can not allocate initial list string"); while ((length = getline (&line, &line_len, list_file)) > 0) { @@ -858,10 +861,10 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) list = new_list; } if (!list) - error (1, 1, "Can not construct list"); + error (1, errno, "can not construct list"); } if (ferror (list_file)) - error (1, 1, "Can not read list file %s", list_pathname); + error (1, errno, "can not read list file %s", list_pathname); list_option->default_value = ""; list_option->value = list; } @@ -909,7 +912,7 @@ static void option_check_validity (gc_option_t *option, const char *new_value) { if (option->new_value) - error (1, 0, "Option %s already changed", option->name); + error (1, 0, "option %s already changed", option->name); if (!*new_value) return; @@ -943,8 +946,9 @@ change_options_program (gc_component_t component, gc_backend_t backend, /* True if we are within the marker in the config file. */ int in_marker = 0; gc_option_t *option; -#define LINE_LEN 4096 - char line[LINE_LEN]; + char *line; + size_t line_len; + ssize_t length; int res; int fd; FILE *src_file = NULL; @@ -1000,22 +1004,12 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (!dest_file) goto change_one_err; - while (fgets (line, LINE_LEN, dest_file)) + while ((length = getline (&line, &line_len, dest_file)) > 0) { - int length; int disable = 0; char *start; char *end; - line[LINE_LEN - 1] = '\0'; - length = strlen (line); - if (length == LINE_LEN - 1) - { - /* FIXME */ - errno = ENAMETOOLONG; - goto change_one_err; - } - if (!strncmp (marker, line, sizeof (marker) - 1)) { if (!in_marker) @@ -1048,7 +1042,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (!in_marker) { fprintf (src_file, - "# GPGConf disabled this option here at FIXME\n"); + "# GPGConf disabled this option here at %s\n", + asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_one_err; fprintf (src_file, "# %s", line); @@ -1103,11 +1098,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, option++; } { - time_t cur_time = time (NULL); - - /* asctime() returns a string that ends with a newline - character! */ - fprintf (src_file, "%s %s", marker, asctime (localtime (&cur_time))); + fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_one_err; } @@ -1126,18 +1117,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, } if (dest_file) { - while (fgets (line, LINE_LEN, dest_file)) + while ((length = getline (&line, &line_len, dest_file)) > 0) { - int length; - - line[LINE_LEN - 1] = '\0'; - length = strlen (line); - if (length == LINE_LEN - 1) - { - /* FIXME */ - errno = ENAMETOOLONG; - goto change_one_err; - } fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_one_err; @@ -1222,7 +1203,7 @@ gc_component_change_options (int component, FILE *in) option = find_option (component, line, GC_BACKEND_ANY); if (!option) - error (1, 0, "Unknown option %s", line); + error (1, 0, "unknown option %s", line); option_check_validity (option, value); option->new_value = strdup (value); @@ -1291,7 +1272,7 @@ gc_component_change_options (int component, FILE *in) if (err) { int i; - int res = errno; + int saved_errno = errno; /* An error occured. */ for (i = 0; i < GC_COMPONENT_NR; i++) @@ -1315,7 +1296,6 @@ gc_component_change_options (int component, FILE *in) unlink (dest_pathname[i]); } } - errno = res; - error (1, 1, "Could not commit changes"); + error (1, saved_errno, "could not commit changes"); } } -- cgit v1.2.3 From 74a20c31e3c15d81c3258dc66ca235034e575cfa Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 30 Jan 2004 12:15:53 +0000 Subject: 2004-01-30 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_error): New function, use it instead of error() throughout. --- tools/ChangeLog | 3 ++ tools/gpgconf-comp.c | 87 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index a9254bd99..a91f4fe68 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,8 @@ 2004-01-30 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (gc_error): New function, use it instead of + error() throughout. + * gpgconf-comp.c: Use xmalloc, libcommon's asctimestamp and gnupg_get_time, fix error() invocation and use getline() consistently. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 5a1629fb8..a6bda075d 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -31,24 +31,61 @@ #include <assert.h> #include <errno.h> #include <time.h> +#include <stdarg.h> -#include <error.h> - -/* For asctimestamp(), gnupg_get_time (). */ +/* For log_logv(), asctimestamp(), gnupg_get_time (). */ +#define JNLIB_NEED_LOG_LOGV #include "util.h" #include "gpgconf.h" /* TODO: - Portability - Add gnulib replacements for getline, error, etc. + Portability - Add gnulib replacements for getline, etc. Backend: File backend must be able to write out changes !!! Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. Don't use popen, as this will not tell us if the program had a non-zero exit code. + Add options to change backend binary path. + Extract binary path for some backends from gpgsm/gpg config. */ + +#if defined (__riscos__) \ + || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) +void gc_error (int status, int errnum, const char *fmt, ...) \ + __attribute__ ((format (printf, 3, 4))); +#endif + +/* Output a diagnostic message. If ERRNUM is not 0, then the output + is followed by a colon, a white space, and the error string for the + error number ERRNUM. In any case the output is finished by a + newline. The message is prepended by the program name, a colon, + and a whitespace. The output may be further formatted or + redirected by the jnlib logging facility. */ +void +gc_error (int status, int errnum, const char *fmt, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, fmt); + log_logv (JNLIB_LOG_ERROR, fmt, arg_ptr); + va_end (arg_ptr); + + if (errnum) + log_printf (": %s\n", strerror (errnum)); + else + log_printf ("\n"); + + if (status) + { + log_printf (NULL); + log_printf ("fatal error (exit status %i)\n", status); + exit (status); + } +} + /* Backend configuration. Backends are used to decide how the default and current value of an option can be determined, and how the @@ -498,7 +535,7 @@ percent_escape (const char *src) { char *new_esc_str = realloc (esc_str, new_len); if (!new_esc_str) - error (1, errno, "can not escape string"); + gc_error (1, errno, "can not escape string"); esc_str = new_esc_str; esc_str_len = new_len; } @@ -709,18 +746,18 @@ get_config_pathname (gc_component_t component, gc_backend_t backend) assert (option); if (!option->default_value) - error (1, 0, "option %s, needed by backend %s, was not initialized", - gc_backend[backend].option_config_filename, - gc_backend[backend].name); + gc_error (1, 0, "option %s, needed by backend %s, was not initialized", + gc_backend[backend].option_config_filename, + gc_backend[backend].name); if (*option->value) pathname = option->value; else pathname = option->default_value; if (*pathname != '/') - error (1, 0, "option %s, needed by backend %s, is not absolute", - gc_backend[backend].option_config_filename, - gc_backend[backend].name); + gc_error (1, 0, "option %s, needed by backend %s, is not absolute", + gc_backend[backend].option_config_filename, + gc_backend[backend].name); return pathname; } @@ -739,11 +776,11 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) asprintf (&cmd_line, "%s --gpgconf-list", gc_backend[backend].program); if (!cmd_line) - error (1, errno, "can not construct command line"); + gc_error (1, errno, "can not construct command line"); output = popen (cmd_line, "r"); if (!output) - error (1, errno, "could not gather active options from %s", cmd_line); + gc_error (1, errno, "could not gather active options from %s", cmd_line); while ((length = getline (&line, &line_len, output)) > 0) { @@ -787,18 +824,18 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) if (option) { if (option->default_value) - error (1, errno, "option %s returned twice from %s", - line, cmd_line); + gc_error (1, errno, "option %s returned twice from %s", + line, cmd_line); option->default_value = strdup (default_value); option->value = strdup (value); if (!option->default_value || !option->value) - error (1, errno, "could not store options"); + gc_error (1, errno, "could not store options"); } } if (ferror (output)) - error (1, errno, "error reading from %s", cmd_line); + gc_error (1, errno, "error reading from %s", cmd_line); if (fclose (output) && ferror (output)) - error (1, errno, "error closing %s", cmd_line); + gc_error (1, errno, "error closing %s", cmd_line); free (cmd_line); } @@ -824,11 +861,11 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) list_file = fopen (list_pathname, "r"); if (ferror (list_file)) - error (1, errno, "can not open list file %s", list_pathname); + gc_error (1, errno, "can not open list file %s", list_pathname); list = strdup ("\""); if (!list) - error (1, errno, "can not allocate initial list string"); + gc_error (1, errno, "can not allocate initial list string"); while ((length = getline (&line, &line_len, list_file)) > 0) { @@ -861,10 +898,10 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) list = new_list; } if (!list) - error (1, errno, "can not construct list"); + gc_error (1, errno, "can not construct list"); } if (ferror (list_file)) - error (1, errno, "can not read list file %s", list_pathname); + gc_error (1, errno, "can not read list file %s", list_pathname); list_option->default_value = ""; list_option->value = list; } @@ -912,7 +949,7 @@ static void option_check_validity (gc_option_t *option, const char *new_value) { if (option->new_value) - error (1, 0, "option %s already changed", option->name); + gc_error (1, 0, "option %s already changed", option->name); if (!*new_value) return; @@ -1203,7 +1240,7 @@ gc_component_change_options (int component, FILE *in) option = find_option (component, line, GC_BACKEND_ANY); if (!option) - error (1, 0, "unknown option %s", line); + gc_error (1, 0, "unknown option %s", line); option_check_validity (option, value); option->new_value = strdup (value); @@ -1296,6 +1333,6 @@ gc_component_change_options (int component, FILE *in) unlink (dest_pathname[i]); } } - error (1, saved_errno, "could not commit changes"); + gc_error (1, saved_errno, "could not commit changes"); } } -- cgit v1.2.3 From 0f7a19f3b0e91861dc962780c4738453764247ce Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 30 Jan 2004 12:37:09 +0000 Subject: 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. --- common/ChangeLog | 7 +++++++ common/Makefile.am | 1 + common/miscellaneous.c | 19 ------------------- common/xasprintf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 common/xasprintf.c diff --git a/common/ChangeLog b/common/ChangeLog index 8e5c615d9..1266a88c5 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,10 @@ +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. diff --git a/common/Makefile.am b/common/Makefile.am index 770ed12d6..640051be4 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -35,6 +35,7 @@ libcommon_a_SOURCES = \ gettime.c \ yesno.c \ miscellaneous.c \ + xasprintf.c \ membuf.c membuf.h \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ diff --git a/common/miscellaneous.c b/common/miscellaneous.c index 4937bd7ce..86b0fcb3a 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -25,25 +25,6 @@ #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; -} - - /* Decide whether the filename is stdout or a real filename and return * an appropriate string. */ diff --git a/common/xasprintf.c b/common/xasprintf.c new file mode 100644 index 000000000..2c8fafc06 --- /dev/null +++ b/common/xasprintf.c @@ -0,0 +1,44 @@ +/* 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; +} -- cgit v1.2.3 From a9eaa96f836b06644bdab472e1c438c177aa8bec Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Jan 2004 17:57:16 +0000 Subject: *** empty log message *** --- tools/ChangeLog | 4 ++++ tools/addgnupghome | 23 +++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index a91f4fe68..1d2181227 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -7,6 +7,10 @@ gnupg_get_time, fix error() invocation and use getline() consistently. +2004-01-30 Werner Koch <wk@gnupg.org> + + * addgnupghome: Also set the group of copied files. + 2004-01-30 Werner Koch <wk@gnupg.org> * Makefile.am (sbin_SCRIPTS): New, to install addgnupghome. diff --git a/tools/addgnupghome b/tools/addgnupghome index 20436b637..d237a0b42 100755 --- a/tools/addgnupghome +++ b/tools/addgnupghome @@ -48,11 +48,22 @@ one_user () { error "error creating \`$home/.gnupg'" return fi + if ! chown $user "$home/.gnupg" ; then error "error changing ownership of \`$home/.gnupg'" return fi + group=$(id -g "$user") + [ -z "$group" ] && group="0" + + if [ "$group" -gt 0 ]; then + if ! chgrp $group "$home/.gnupg" ; then + error "error changing group of \`$home/.gnupg'" + return + fi + fi + if ! cd "$home/.gnupg" ; then error "error cd-ing to \`$home/.gnupg'" return @@ -63,10 +74,18 @@ one_user () { else cp /etc/skel/.gnupg/$f $f fi - chown $user $f + if ! chown $user $f ; then + error "error changing ownership of \`$f'" + return + fi + if [ "$group" -gt 0 ]; then + if ! chgrp $group "$f" ; then + error "error changing group of \`$f'" + return + fi + fi done - } if [ -z "$1" ]; then -- cgit v1.2.3 From cff3f7686269b994ec47ee9e1400c84a7893fd1f Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sat, 31 Jan 2004 13:58:27 +0000 Subject: 2004-01-31 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c: Some bug fixes, parse only defaults from the program, and read the current values from the configuration file directly. --- tools/ChangeLog | 6 + tools/gpgconf-comp.c | 308 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 210 insertions(+), 104 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 1d2181227..110a434d7 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2004-01-31 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c: Some bug fixes, parse only defaults from the + program, and read the current values from the configuration file + directly. + 2004-01-30 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_error): New function, use it instead of diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index a6bda075d..fc3d4edcf 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1,5 +1,5 @@ /* gpgconf-comp.c - Configuration utility for GnuPG. - Copyright (C) 2003 g10 Code GmbH + Copyright (C) 2004 g10 Code GmbH This file is part of GnuPG. @@ -143,10 +143,10 @@ static struct } gc_backend[GC_BACKEND_NR] = { { NULL, NULL, NULL }, /* GC_BACKEND_ANY dummy entry. */ - { "GnuPG", "gpg", "gpgconf-config-file" }, - { "GPGSM", "gpgsm", "gpgconf-config-file" }, - { "GPG Agent", "gpg-agent", "gpgconf-config-file" }, - { "DirMngr", "dirmngr", "gpgconf-config-file" }, + { "GnuPG", "gpg", "gpgconf-gpg.conf" }, + { "GPGSM", "gpgsm", "gpgconf-gpgsm.conf" }, + { "GPG Agent", "gpg-agent", "gpgconf-gpg-agent.conf" }, + { "DirMngr", "dirmngr", "gpgconf-dirmngr.conf" }, { "DirMngr LDAP Server List", NULL, "ldapserverlist-file", "LDAP Server" }, }; @@ -341,6 +341,10 @@ struct gc_option of the list so that they can be omitted from the option declarations. */ + /* This is true if the option is supported by this version of the + backend. */ + int active; + /* The default value for this option. This is NULL if the option is not present in the backend, the empty string if no default is available, and otherwise a quoted string. */ @@ -369,13 +373,13 @@ static gc_option_t gc_options_gpg_agent[] = static gc_option_t gc_options_dirmngr[] = { /* The configuration file to which we write the changes. */ - { "gpgconf-config-file", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, NULL, "Options controlling the diagnostic output" }, - { "verbose", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "dirmngr", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, @@ -616,7 +620,7 @@ gc_component_list_options (int component, FILE *out) char *arg_name = NULL; /* Do not output unknown or internal options. */ - if (!option->default_value || option->level == GC_LEVEL_INTERNAL) + if (!option->active || option->level == GC_LEVEL_INTERNAL) { option++; continue; @@ -740,26 +744,29 @@ find_option (gc_component_t component, const char *name, static char * get_config_pathname (gc_component_t component, gc_backend_t backend) { - char *pathname; + char *pathname = NULL; gc_option_t *option = find_option (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY); assert (option); + assert (option->arg_type == GC_ARG_TYPE_PATHNAME); + assert (!(option->flags & GC_OPT_FLAG_LIST)); - if (!option->default_value) - gc_error (1, 0, "option %s, needed by backend %s, was not initialized", + if (!option->active || !option->default_value) + gc_error (1, 0, "Option %s, needed by backend %s, was not initialized", gc_backend[backend].option_config_filename, gc_backend[backend].name); - if (*option->value) + + if (option->value && *option->value) pathname = option->value; else pathname = option->default_value; - if (*pathname != '/') - gc_error (1, 0, "option %s, needed by backend %s, is not absolute", + if (pathname[1] != '/') + gc_error (1, 0, "Option %s, needed by backend %s, is not absolute", gc_backend[backend].option_config_filename, gc_backend[backend].name); - return pathname; + return &pathname[1]; } @@ -772,20 +779,18 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) char *line = NULL; size_t line_len = 0; ssize_t length; - FILE *output; + FILE *config; + char *config_pathname; - asprintf (&cmd_line, "%s --gpgconf-list", gc_backend[backend].program); - if (!cmd_line) - gc_error (1, errno, "can not construct command line"); + cmd_line = xasprintf ("%s --gpgconf-list", gc_backend[backend].program); - output = popen (cmd_line, "r"); - if (!output) + config = popen (cmd_line, "r"); + if (!config) gc_error (1, errno, "could not gather active options from %s", cmd_line); - while ((length = getline (&line, &line_len, output)) > 0) + while ((length = getline (&line, &line_len, config)) > 0) { gc_option_t *option; - char *default_value; char *value; /* Strip newline and carriage return, if present. */ @@ -793,29 +798,19 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; - /* Extract default value and value, if present. Default to - empty if not. */ - default_value = strchr (line, ':'); - if (!default_value) - { - default_value = ""; - value = ""; - } + /* Extract default value, if present. Default to empty if + not. */ + value = strchr (line, ':'); + if (!value) + value = ""; else { - *(default_value++) = '\0'; - value = strchr (default_value, ':'); - if (!value) - value = ""; - else - { - char *end; + char *end; - *(value++) = '\0'; - end = strchr (value, ':'); - if (end) - *end = '\0'; - } + *(value++) = '\0'; + end = strchr (value, ':'); + if (end) + *end = '\0'; } /* Look up the option in the component and install the @@ -823,20 +818,122 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) option = find_option (component, line, backend); if (option) { - if (option->default_value) + if (option->active) gc_error (1, errno, "option %s returned twice from %s", line, cmd_line); - option->default_value = strdup (default_value); - option->value = strdup (value); - if (!option->default_value || !option->value) - gc_error (1, errno, "could not store options"); + option->active = 1; + if (*value) + option->default_value = xstrdup (value); } } - if (ferror (output)) + if (ferror (config)) gc_error (1, errno, "error reading from %s", cmd_line); - if (fclose (output) && ferror (output)) + if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", cmd_line); - free (cmd_line); + xfree (cmd_line); + + /* At this point, we can parse the configuration file. */ + config_pathname = get_config_pathname (component, backend); + + config = fopen (config_pathname, "r"); + if (!config) + gc_error (0, errno, "warning: can not open config file %s", + config_pathname); + else + { + while ((length = getline (&line, &line_len, config)) > 0) + { + char *name; + char *value; + gc_option_t *option; + + name = line; + while (*name == ' ' || *name == '\t') + name++; + if (!*name || *name == '#' || *name == '\r' || *name == '\n') + continue; + + value = name; + while (*value && *value != ' ' && *value != '\t' + && *value != '#' && *value != '\r' && *value != '\n') + value++; + if (*value == ' ' || *value == '\t') + { + char *end; + + *(value++) = '\0'; + while (*value == ' ' || *value == '\t') + value++; + + end = value; + while (*end && *end != '#' && *end != '\r' && *end != '\n') + end++; + while (end > value && (end[-1] == ' ' || end[-1] == '\t')) + end--; + *end = '\0'; + } + else + *value = '\0'; + + /* Look up the option in the component and install the + configuration data. */ + option = find_option (component, line, backend); + if (option) + { + char *opt_value; + + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) + { + if (*value) + gc_error (0, 0, + "warning: ignoring argument %s for option %s", + value, name); + opt_value = xstrdup ("Y"); + } + else if (gc_arg_type[option->arg_type].fallback + == GC_ARG_TYPE_STRING) + opt_value = xasprintf ("\"%s", percent_escape (value)); + else + { + /* FIXME: Verify that the number is sane. */ + opt_value = xstrdup (value); + } + + /* Now enter the option into the table. */ + if (!(option->flags & GC_OPT_FLAG_LIST)) + { + if (option->value) + free (option->value); + option->value = opt_value; + } + else + { + if (!option->value) + option->value = opt_value; + else + { + char *opt_val = opt_value; + + if (gc_arg_type[option->arg_type].fallback + == GC_ARG_TYPE_STRING) + opt_val++; + + option->value = xasprintf ("%s,%s", option->value, + opt_val); + xfree (opt_value); + } + } + } + } + + if (ferror (config)) + gc_error (1, errno, "error reading from %s", config_pathname); + if (fclose (config) && ferror (config)) + gc_error (1, errno, "error closing %s", config_pathname); + } + + if (line) + free (line); } @@ -851,59 +948,62 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) char *line = NULL; size_t line_len = 0; ssize_t length; - char *list; + char *list = NULL; list_option = find_option (component, gc_backend[backend].option_name, GC_BACKEND_ANY); assert (list_option); + assert (!list_option->active); list_pathname = get_config_pathname (component, backend); - list_file = fopen (list_pathname, "r"); - if (ferror (list_file)) - gc_error (1, errno, "can not open list file %s", list_pathname); - - list = strdup ("\""); - if (!list) - gc_error (1, errno, "can not allocate initial list string"); - - while ((length = getline (&line, &line_len, list_file)) > 0) + if (!list_file) + gc_error (0, errno, "warning: can not open list file %s", list_pathname); + else { - char *start; - char *end; - char *new_list; - - start = line; - while (*start == ' ' || *start == '\t') - start++; - if (!*start || *start == '#' || *start == '\r' || *start == '\n') - continue; - - end = start; - while (*end && *end != '#' && *end != '\r' && *end != '\n') - end++; - /* Walk back to skip trailing white spaces. Looks evil, but - works because of the conditions on START and END imposed - at this point (END is at least START + 1, and START is - not a whitespace character). */ - while (*(end - 1) == ' ' || *(end - 1) == '\t') - end--; - *end = '\0'; - /* FIXME: Oh, no! This is so lame! Use realloc and really - append. */ - if (list) + + while ((length = getline (&line, &line_len, list_file)) > 0) { - asprintf (&new_list, "%s,%s", list, percent_escape (start)); - free (list); - list = new_list; + char *start; + char *end; + char *new_list; + + start = line; + while (*start == ' ' || *start == '\t') + start++; + if (!*start || *start == '#' || *start == '\r' || *start == '\n') + continue; + + end = start; + while (*end && *end != '#' && *end != '\r' && *end != '\n') + end++; + /* Walk back to skip trailing white spaces. Looks evil, but + works because of the conditions on START and END imposed + at this point (END is at least START + 1, and START is + not a whitespace character). */ + while (*(end - 1) == ' ' || *(end - 1) == '\t') + end--; + *end = '\0'; + /* FIXME: Oh, no! This is so lame! Use realloc and really + append. */ + if (list) + { + new_list = xasprintf ("%s,%s", list, percent_escape (start)); + xfree (list); + list = new_list; + } + else + list = xasprintf ("\"%s", percent_escape (start)); } - if (!list) - gc_error (1, errno, "can not construct list"); + if (ferror (list_file)) + gc_error (1, errno, "can not read list file %s", list_pathname); } - if (ferror (list_file)) - gc_error (1, errno, "can not read list file %s", list_pathname); - list_option->default_value = ""; + + list_option->active = 1; list_option->value = list; + + if (line) + free (line); } @@ -983,7 +1083,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, /* True if we are within the marker in the config file. */ int in_marker = 0; gc_option_t *option; - char *line; + char *line = NULL; size_t line_len; ssize_t length; int res; @@ -995,22 +1095,16 @@ change_options_program (gc_component_t component, gc_backend_t backend, char *orig_filename; /* FIXME. Throughout the function, do better error reporting. */ - dest_filename = strdup (get_config_pathname (component, backend)); - if (!dest_filename) - return -1; - asprintf (&src_filename, "%s.gpgconf.%i.new", dest_filename, getpid ()); - if (!src_filename) - return -1; - asprintf (&orig_filename, "%s.gpgconf.%i.bak", dest_filename, getpid ()); - if (!orig_filename) - return -1; + dest_filename = xstrdup (get_config_pathname (component, backend)); + src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ()); + orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ()); res = link (dest_filename, orig_filename); if (res < 0 && errno != ENOENT) return -1; if (res < 0) { - free (orig_filename); + xfree (orig_filename); orig_filename = NULL; } /* We now initialize the return strings, so the caller can do the @@ -1163,6 +1257,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (ferror (dest_file)) goto change_one_err; } + if (line) + free (line); res = fclose (src_file); if (res) { @@ -1183,6 +1279,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, return 0; change_one_err: + if (line) + free (line); res = errno; if (src_file) { @@ -1243,7 +1341,7 @@ gc_component_change_options (int component, FILE *in) gc_error (1, 0, "unknown option %s", line); option_check_validity (option, value); - option->new_value = strdup (value); + option->new_value = xstrdup (value); } /* Now that we have collected and locally verified the changes, @@ -1335,4 +1433,6 @@ gc_component_change_options (int component, FILE *in) } gc_error (1, saved_errno, "could not commit changes"); } + if (line) + free (line); } -- cgit v1.2.3 From bdae155c7b22e0fbe36a5f5e6ca13c298475c37e Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sun, 1 Feb 2004 15:30:50 +0000 Subject: Fix copyright line. --- tools/gpgconf-comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index fc3d4edcf..efe2bf5a8 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1,5 +1,5 @@ /* gpgconf-comp.c - Configuration utility for GnuPG. - Copyright (C) 2004 g10 Code GmbH + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GnuPG. -- cgit v1.2.3 From 5bda9a8e74753da5d7ee912c32a0137ebce2abd8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 2 Feb 2004 17:09:35 +0000 Subject: * keybox.h (keybox_flag_t): New. * keybox-search.c (get_flag_from_image, keybox_get_flags): New. (_keybox_get_flag_location): New. * certchain.c (gpgsm_validate_chain): Mark revoked certs in the keybox. * keylist.c (list_cert_colon): New arg VALIDITY; use it to print a revoked flag. (list_internal_keys): Retrieve validity flag. (list_external_cb): Pass 0 as validity flag. * keydb.c (keydb_get_flags, keydb_set_flags): New. (keydb_set_cert_flags): New. (lock_all): Return a proper error code. (keydb_lock): New. (keydb_delete): Don't lock but check that it has been locked. (keydb_update_keyblock): Ditto. * delete.c (delete_one): Take a lock. --- kbx/ChangeLog | 6 ++ kbx/keybox-blob.c | 11 ++-- kbx/keybox-defs.h | 6 ++ kbx/keybox-search.c | 116 ++++++++++++++++++++++++++++++++++++- kbx/keybox-update.c | 82 +++++++++++++++++++++++++++ kbx/keybox.h | 14 ++++- sm/ChangeLog | 17 ++++++ sm/certchain.c | 6 ++ sm/delete.c | 9 ++- sm/keydb.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++---- sm/keydb.h | 10 ++++ sm/keylist.c | 30 ++++++---- 12 files changed, 438 insertions(+), 29 deletions(-) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 07a198200..a866e04f0 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,9 @@ +2004-02-02 Werner Koch <wk@gnupg.org> + + * keybox.h (keybox_flag_t): New. + * keybox-search.c (get_flag_from_image, keybox_get_flags): New. + (_keybox_get_flag_location): New. + 2003-11-12 Werner Koch <wk@gnupg.org> Adjusted for API changes in Libksba. diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 3d815321f..96595436c 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -39,7 +39,7 @@ The first record of a plain KBX file has a special format: byte pgp_completes ditto. byte pgp_cert_depth ditto. -The OpenPGP and X.509 blob are verry similiar, things which are +The OpenPGP and X.509 blob are very similiar, things which are X.509 specific are noted like [X.509: xxx] u32 length of this blob (including these 4 bytes) @@ -57,7 +57,7 @@ X.509 specific are noted like [X.509: xxx] b20 The keys fingerprint (fingerprints are always 20 bytes, MD5 left padded with zeroes) u32 offset to the n-th key's keyID (a keyID is always 8 byte) - or 0 if not known which is the case opnly for X509. + or 0 if not known which is the case only for X509. u16 special key flags bit 0 = u16 reserved @@ -82,8 +82,11 @@ X.509 specific are noted like [X.509: xxx] 0x00000002 = bad signature 0x10000000 = valid and expires at some date in 1978. 0xffffffff = valid and does not expire - u8 assigned ownertrust [X509: no used] - u8 all_validity [X509: no used] + u8 assigned ownertrust [X509: not used] + u8 all_validity + OpenPGP: see ../g10/trustdb/TRUST_* [not yet used] + X509: Bit 4 set := key has been revoked. nOte that this value + matches TRUST_FLAG_REVOKED u16 reserved u32 recheck_after u32 Newest timestamp in the keyblock (useful for KS syncronsiation?) diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index fa145f7e5..17431502f 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -116,6 +116,12 @@ off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp); +/*-- keybox-search.c --*/ +gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer, + size_t length, + int what, + size_t *flag_off, size_t *flag_size); + /*-- keybox-dump.c --*/ int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); int _keybox_dump_file (const char *filename, FILE *outfp); diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index b8add5abe..f23bfdada 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -1,5 +1,5 @@ /* keybox-search.c - Search operations - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -26,12 +26,15 @@ #include <errno.h> #include "../jnlib/stringhelp.h" /* ascii_xxxx() */ + #include "keybox-defs.h" + #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)) + struct sn_array_s { int snlen; unsigned char *sn; @@ -88,6 +91,97 @@ blob_get_blob_flags (KEYBOXBLOB blob) } +/* Return information on the flag WHAT within the blob BUFFER,LENGTH. + Return the offset and the length (in bytes) of the flag in + FLAGOFF,FLAG_SIZE. */ +gpg_err_code_t +_keybox_get_flag_location (const unsigned char *buffer, size_t length, + int what, size_t *flag_off, size_t *flag_size) +{ + size_t pos; + size_t nkeys, keyinfolen; + size_t nuids, uidinfolen; + size_t nserial; + size_t nsigs, siginfolen; + + switch (what) + { + case KEYBOX_FLAG_BLOB: + if (length < 8) + return GPG_ERR_INV_OBJ; + *flag_off = 6; + *flag_size = 2; + break; + + case KEYBOX_FLAG_VALIDITY: + case KEYBOX_FLAG_OWNERTRUST: + if (length < 20) + return GPG_ERR_INV_OBJ; + /* Key info. */ + nkeys = get16 (buffer + 16); + keyinfolen = get16 (buffer + 18 ); + if (keyinfolen < 28) + return GPG_ERR_INV_OBJ; + pos = 20 + keyinfolen*nkeys; + if (pos+2 > length) + return GPG_ERR_INV_OBJ; /* Out of bounds. */ + /* Serial number. */ + nserial = get16 (buffer+pos); + pos += 2 + nserial; + if (pos+4 > length) + return GPG_ERR_INV_OBJ; /* Out of bounds. */ + /* User IDs. */ + nuids = get16 (buffer + pos); pos += 2; + uidinfolen = get16 (buffer + pos); pos += 2; + if (uidinfolen < 12 ) + return GPG_ERR_INV_OBJ; + pos += uidinfolen*nuids; + if (pos+4 > length) + return GPG_ERR_INV_OBJ ; /* Out of bounds. */ + /* Signature info. */ + nsigs = get16 (buffer + pos); pos += 2; + siginfolen = get16 (buffer + pos); pos += 2; + if (siginfolen < 4 ) + return GPG_ERR_INV_OBJ; + pos += siginfolen*nsigs; + if (pos+1+1+2+4+4+4+4 > length) + return GPG_ERR_INV_OBJ ; /* Out of bounds. */ + *flag_size = 1; + *flag_off = pos; + if (what == KEYBOX_FLAG_VALIDITY) + ++*flag_off; + break; + + default: + return GPG_ERR_INV_FLAG; + } + return 0; +} + +/* Return one of the flags WHAT in VALUE from teh blob BUFFER of + LENGTH bytes. Return 0 on success or an raw error code. */ +static gpg_err_code_t +get_flag_from_image (const unsigned char *buffer, size_t length, + int what, unsigned int *value) +{ + gpg_err_code_t ec; + size_t pos, size; + + *value = 0; + ec = _keybox_get_flag_location (buffer, length, what, &pos, &size); + if (!ec) + switch (size) + { + case 1: *value = buffer[pos]; break; + case 2: *value = get16 (buffer + pos); break; + case 4: *value = get32 (buffer + pos); break; + default: ec = GPG_ERR_BUG; break; + } + + return ec; +} + + static int blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) { @@ -811,3 +905,23 @@ keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert) } #endif /*KEYBOX_WITH_X509*/ + +/* Return the flags named WHAT iat the address of VALUE. IDX is used + only for certain flags and should be 0 if not required. */ +int +keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value) +{ + const unsigned char *buffer; + size_t length; + gpg_err_code_t ec; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + if (!hd->found.blob) + return gpg_error (GPG_ERR_NOTHING_FOUND); + + buffer = _keybox_get_blob_image (hd->found.blob, &length); + ec = get_flag_from_image (buffer, length, what, value); + return ec? gpg_error (ec):0; +} + diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index ed9ca2bf7..47e53966a 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -384,6 +384,88 @@ keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, #endif /*KEYBOX_WITH_X509*/ +/* Note: We assume that the keybox has been locked before the current + search was executed. This is needed so that we can depend on the + offset information of the flags. */ +int +keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value) +{ + off_t off; + const char *fname; + FILE *fp; + gpg_err_code_t ec; + size_t flag_pos, flag_size; + const unsigned char *buffer; + size_t length; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + if (!hd->found.blob) + return gpg_error (GPG_ERR_NOTHING_FOUND); + if (!hd->kb) + return gpg_error (GPG_ERR_INV_HANDLE); + if (!hd->found.blob) + return gpg_error (GPG_ERR_NOTHING_FOUND); + fname = hd->kb->fname; + if (!fname) + return gpg_error (GPG_ERR_INV_HANDLE); + + off = _keybox_get_blob_fileoffset (hd->found.blob); + if (off == (off_t)-1) + return gpg_error (GPG_ERR_GENERAL); + + buffer = _keybox_get_blob_image (hd->found.blob, &length); + ec = _keybox_get_flag_location (buffer, length, what, &flag_pos, &flag_size); + if (ec) + return gpg_error (ec); + + off += flag_pos; + + if (hd->fp) + { + fclose (hd->fp); + hd->fp = NULL; + } + fp = fopen (hd->kb->fname, "r+b"); + if (!fp) + return gpg_error (gpg_err_code_from_errno (errno)); + + ec = 0; + if (fseeko (fp, off, SEEK_SET)) + ec = gpg_error (gpg_err_code_from_errno (errno)); + else + { + unsigned char tmp[4]; + + tmp[0] = value >> 24; + tmp[1] = value >> 16; + tmp[2] = value >> 8; + tmp[3] = value; + + switch (flag_size) + { + case 1: + case 2: + case 4: + if (fwrite (tmp+4-flag_size, flag_size, 1, fp) != 1) + ec = gpg_err_code_from_errno (errno); + break; + default: + ec = GPG_ERR_BUG; + break; + } + } + + if (fclose (fp)) + { + if (!ec) + ec = gpg_err_code_from_errno (errno); + } + + return gpg_error (ec); +} + + int keybox_delete (KEYBOX_HANDLE hd) diff --git a/kbx/keybox.h b/kbx/keybox.h index 5a5ad2933..e4dc9d642 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -42,9 +42,19 @@ extern "C" { # include <ksba.h> #endif +typedef struct keybox_handle *KEYBOX_HANDLE; -typedef struct keybox_handle *KEYBOX_HANDLE; +typedef enum + { + KEYBOX_FLAG_BLOB, /* The blob flags. */ + KEYBOX_FLAG_VALIDITY, /* The validity of the entire key. */ + KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */ + KEYBOX_FLAG_KEY, /* The key flags; requires a key index. */ + KEYBOX_FLAG_UID, /* The user ID flags; requires an uid index. */ + KEYBOX_FLAG_UID_VALIDITY/* The validity of a specific uid, requires + an uid index. */ + } keyxox_flag_t; /*-- keybox-init.c --*/ @@ -61,6 +71,7 @@ int keybox_set_ephemeral (KEYBOX_HANDLE hd, int yes); #ifdef KEYBOX_WITH_X509 int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert); #endif /*KEYBOX_WITH_X509*/ +int keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value); int keybox_search_reset (KEYBOX_HANDLE hd); int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc); @@ -73,6 +84,7 @@ int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, int keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, unsigned char *sha1_digest); #endif /*KEYBOX_WITH_X509*/ +int keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value); int keybox_delete (KEYBOX_HANDLE hd); diff --git a/sm/ChangeLog b/sm/ChangeLog index 2a584e079..cde6e8439 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,20 @@ +2004-02-02 Werner Koch <wk@gnupg.org> + + * certchain.c (gpgsm_validate_chain): Mark revoked certs in the + keybox. + + * keylist.c (list_cert_colon): New arg VALIDITY; use it to print a + revoked flag. + (list_internal_keys): Retrieve validity flag. + (list_external_cb): Pass 0 as validity flag. + * keydb.c (keydb_get_flags, keydb_set_flags): New. + (keydb_set_cert_flags): New. + (lock_all): Return a proper error code. + (keydb_lock): New. + (keydb_delete): Don't lock but check that it has been locked. + (keydb_update_keyblock): Ditto. + * delete.c (delete_one): Take a lock. + 2004-01-30 Werner Koch <wk@gnupg.org> * certchain.c (check_cert_policy): Fixed read error checking. diff --git a/sm/certchain.c b/sm/certchain.c index a48dbd737..bcc66660a 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -32,6 +32,7 @@ #include <ksba.h> #include "keydb.h" +#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */ #include "i18n.h" static int @@ -535,6 +536,11 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) case GPG_ERR_CERT_REVOKED: log_error (_("the certificate has been revoked\n")); any_revoked = 1; + /* Store that in the keybox so that key listings are + able to return the revoked flag. We don't care + about error, though. */ + keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0, + VALIDITY_REVOKED); break; case GPG_ERR_NO_CRL_KNOWN: log_error (_("no CRL found for certificate\n")); diff --git a/sm/delete.c b/sm/delete.c index 8b04bc426..11a0a5476 100644 --- a/sm/delete.c +++ b/sm/delete.c @@ -105,7 +105,14 @@ delete_one (CTRL ctrl, const char *username) goto leave; } - /* we need to search again to get back to the right position. */ + /* We need to search again to get back to the right position. */ + rc = keydb_lock (kh); + if (rc) + { + log_error (_("error locking keybox: %s\n"), gpg_strerror (rc)); + goto leave; + } + do { keydb_search_reset (kh); diff --git a/sm/keydb.c b/sm/keydb.c index 62e3ab2f3..f770135c1 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -1,5 +1,5 @@ /* keydb.c - key database dispatcher - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -373,6 +373,21 @@ keydb_set_ephemeral (KEYDB_HANDLE hd, int yes) } +/* If the keyring has not yet been locked, lock it now. This + operation is required before any update opeations; it is optionaly + for an insert operation. The lock is released with + keydb_released. */ +gpg_error_t +keydb_lock (KEYDB_HANDLE hd) +{ + if (!hd) + return gpg_error (GPG_ERR_INV_HANDLE); + if (hd->locked) + return 0; /* Already locked. */ + return lock_all (hd); +} + + static int lock_all (KEYDB_HANDLE hd) @@ -380,8 +395,8 @@ lock_all (KEYDB_HANDLE hd) int i, rc = 0; /* Fixme: This locking scheme may lead to deadlock if the resources - are not added in the same sequence by all processes. We are - cuurently only allowing one resource so it is not a problem. */ + are not added in the same order all processes. We are + currently only allowing one resource so it is not a problem. */ for (i=0; i < hd->used; i++) { switch (hd->active[i].type) @@ -416,7 +431,10 @@ lock_all (KEYDB_HANDLE hd) else hd->locked = 1; - return rc; + /* make_dotlock () does not yet guarantee that errno is set, thus + we can't rely on the error reason and will simply use + EACCES. */ + return rc? gpg_error (GPG_ERR_EACCES) : 0; } static void @@ -490,9 +508,8 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) if( opt.dry_run ) return 0; - rc = lock_all (hd); - if (rc) - return rc; + if (!hd->locked) + return gpg_error (GPG_ERR_CONFLICT); switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: @@ -552,7 +569,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) /* - Return the last found keybox. Caller must free it. The returned + Return the last found object. 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. */ @@ -580,6 +597,67 @@ keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert) return rc; } +/* Return a flag of the last found object. WHICH is the flag requested; + it should be one of the KEYBOX_FLAG_ values. If the operation is + successful, the flag value will be stored at the address given by + VALUE. Return 0 on success or an error code. */ +gpg_error_t +keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value) +{ + int err = 0; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + if ( hd->found < 0 || hd->found >= hd->used) + return gpg_error (GPG_ERR_NOTHING_FOUND); + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + err = gpg_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + err = keybox_get_flags (hd->active[hd->found].u.kr, which, idx, value); + break; + } + + return err; +} + +/* Set a flag of the last found object. WHICH is the flag to be set; it + should be one of the KEYBOX_FLAG_ values. If the operation is + successful, the flag value will be stored in the keybox. Note, + that some flag values can't be updated and thus may retrun an + error, some other flag values may be masked out before an update. + Returns 0 on success or an error code. */ +gpg_error_t +keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value) +{ + int err = 0; + + if (!hd) + return gpg_error (GPG_ERR_INV_VALUE); + + if ( hd->found < 0 || hd->found >= hd->used) + return gpg_error (GPG_ERR_NOTHING_FOUND); + + if (!hd->locked) + return gpg_error (GPG_ERR_CONFLICT); + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + err = gpg_error (GPG_ERR_GENERAL); /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + err = keybox_set_flags (hd->active[hd->found].u.kr, which, idx, value); + break; + } + + return err; +} + /* * Insert a new Certificate into one of the resources. */ @@ -679,9 +757,8 @@ keydb_delete (KEYDB_HANDLE hd) if( opt.dry_run ) return 0; - rc = lock_all (hd); - if (rc) - return rc; + if (!hd->locked) + return gpg_error (GPG_ERR_CONFLICT); /* ...NOT_LOCKED would be better. */ switch (hd->active[hd->found].type) { @@ -1279,4 +1356,65 @@ keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed) } +/* This is basically keydb_set_flags but it implements a complete + transaction by locating teh certificate in the DB and updating the + flags. */ +gpg_error_t +keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value) +{ + KEYDB_HANDLE kh; + gpg_error_t err; + unsigned char fpr[20]; + unsigned int old_value; + + if (!gpgsm_get_fingerprint (cert, 0, fpr, NULL)) + { + log_error (_("failed to get the fingerprint\n")); + return gpg_error (GPG_ERR_GENERAL); + } + + kh = keydb_new (0); + if (!kh) + { + log_error (_("failed to allocate keyDB handle\n")); + return gpg_error (GPG_ERR_ENOMEM);; + } + + err = keydb_lock (kh); + if (err) + { + log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); + keydb_release (kh); + return err; + } + + err = keydb_search_fpr (kh, fpr); + if (err) + { + log_error (_("problem re-searching certificate: %s\n"), + gpg_strerror (err)); + keydb_release (kh); + return err; + } + + err = keydb_get_flags (kh, which, idx, &old_value); + if (err) + { + log_error (_("error getting stored flags: %s\n"), gpg_strerror (err)); + keydb_release (kh); + return err; + } + if (value != old_value) + { + err = keydb_set_flags (kh, which, idx, value); + if (err) + { + log_error (_("error storing flags: %s\n"), gpg_strerror (err)); + keydb_release (kh); + return err; + } + } + keydb_release (kh); + return 0; +} diff --git a/sm/keydb.h b/sm/keydb.h index 0133d0ccd..2e9ed1573 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -27,6 +27,9 @@ typedef struct keydb_handle *KEYDB_HANDLE; +/* Flag value used with KEYBOX_FLAG_VALIDITY. */ +#define VALIDITY_REVOKED (1<<5) + /*-- keydb.c --*/ int keydb_add_resource (const char *url, int force, int secret); @@ -34,6 +37,7 @@ KEYDB_HANDLE keydb_new (int secret); void keydb_release (KEYDB_HANDLE hd); int keydb_set_ephemeral (KEYDB_HANDLE hd, int yes); const char *keydb_get_resource_name (KEYDB_HANDLE hd); +gpg_error_t keydb_lock (KEYDB_HANDLE hd); #if 0 /* pgp stuff */ int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); @@ -41,6 +45,10 @@ int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb); int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb); #endif +gpg_error_t keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, + unsigned int *value); +gpg_error_t keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, + unsigned int value); int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert); int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert); int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert); @@ -64,6 +72,8 @@ int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer); int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc); int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed); +gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, + unsigned int value); #endif /*GNUPG_KEYDB_H*/ diff --git a/sm/keylist.c b/sm/keylist.c index 007400729..40fa6b043 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -33,6 +33,7 @@ #include <ksba.h> #include "keydb.h" +#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */ #include "i18n.h" struct list_external_parm_s { @@ -145,7 +146,8 @@ email_kludge (const char *name) /* List one certificate in colon mode */ static void -list_cert_colon (ksba_cert_t cert, FILE *fp, int have_secret) +list_cert_colon (ksba_cert_t cert, unsigned int validity, + FILE *fp, int have_secret) { int idx, trustletter = 0; char *p; @@ -155,19 +157,17 @@ list_cert_colon (ksba_cert_t cert, FILE *fp, int have_secret) fputs (have_secret? "crs:":"crt:", fp); trustletter = 0; + if ((validity & VALIDITY_REVOKED)) + trustletter = 'r'; #if 0 - if (is_not_valid (cert)) + else if (is_not_valid (cert)) putc ('i', fp); - else if ( is_revoked (cert) ) - putc ('r', fp); else if ( has_expired (cert)) putcr ('e', fp); - else #endif - { - trustletter = '?'; /*get_validity_info ( pk, NULL );*/ - putc (trustletter, fp); - } + else + trustletter = '?'; + putc (trustletter, fp); fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); fprintf (fp, ":%u:%d:%s:", @@ -481,9 +481,17 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) lastresname = NULL; while (!(rc = keydb_search (hd, desc, ndesc))) { + unsigned int validity; + if (!names) desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity); + if (rc) + { + log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc)); + goto leave; + } rc = keydb_get_cert (hd, &cert); if (rc) { @@ -524,7 +532,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) || ((mode & 2) && have_secret) ) { if (ctrl->with_colons) - list_cert_colon (cert, fp, have_secret); + list_cert_colon (cert, validity, fp, have_secret); else if (ctrl->with_chain) list_cert_chain (cert, fp); else @@ -568,7 +576,7 @@ list_external_cb (void *cb_value, ksba_cert_t cert) } if (parm->with_colons) - list_cert_colon (cert, parm->fp, 0); + list_cert_colon (cert, 0, parm->fp, 0); else if (parm->with_chain) list_cert_chain (cert, parm->fp); else -- cgit v1.2.3 From 31de2267ec849cd8f269cd8bf25b8590f2d93e1d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 3 Feb 2004 16:24:37 +0000 Subject: * findkey.c (agent_key_from_file): Extra paranoid wipe. * protect.c (agent_unprotect): Ditto. (merge_lists): Ditto. Add arg RESULTLEN. * pkdecrypt.c (agent_pkdecrypt): Don't show the secret key even in debug mode. * protect.c: Add DSA and Elgamal description. --- agent/ChangeLog | 10 ++++++++++ agent/findkey.c | 8 ++++---- agent/pkdecrypt.c | 12 ++++++------ agent/protect.c | 26 +++++++++++++++++++------- agent/query.c | 2 +- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 4cdaadef6..01a3c90f5 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,13 @@ +2004-02-03 Werner Koch <wk@gnupg.org> + + * findkey.c (agent_key_from_file): Extra paranoid wipe. + * protect.c (agent_unprotect): Ditto. + (merge_lists): Ditto. Add arg RESULTLEN. + * pkdecrypt.c (agent_pkdecrypt): Don't show the secret key even in + debug mode. + + * protect.c: Add DSA and Elgamal description. + 2004-01-29 Werner Koch <wk@gnupg.org> * agent.h (server_control_s): Add connection_fd field. diff --git a/agent/findkey.c b/agent/findkey.c index a9566a2c7..f145daef1 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -154,7 +154,7 @@ unprotect (CTRL ctrl, sprintf (hexgrip+2*i, "%02X", grip[i]); hexgrip[40] = 0; - /* first try to get it from the cache - if there is none or we can't + /* First try to get it from the cache - if there is none or we can't unprotect it, we fall back to ask the user */ if (!ignore_cache) { @@ -329,9 +329,9 @@ agent_key_from_file (CTRL ctrl, return rc; } - /* Arggg FIXME: does scan support secure memory? */ - rc = gcry_sexp_sscan (&s_skey, &erroff, - buf, gcry_sexp_canon_len (buf, 0, NULL, NULL)); + buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL); + rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); + wipememory (buf, buflen); xfree (buf); if (rc) { diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index cc3a2f33f..72f81778e 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -93,12 +93,12 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, putc (0, outfp); } else - { /* no smartcard, but a private key */ - if (DBG_CRYPTO) - { - log_debug ("skey: "); - gcry_sexp_dump (s_skey); - } + { /* No smartcard, but a private key */ +/* if (DBG_CRYPTO ) */ +/* { */ +/* log_debug ("skey: "); */ +/* gcry_sexp_dump (s_skey); */ +/* } */ rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey); if (rc) diff --git a/agent/protect.c b/agent/protect.c index df8a9bfe7..2de5e97c5 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -46,6 +46,8 @@ static struct { int prot_from, prot_to; } protect_info[] = { { "rsa", "nedpqu", 2, 5 }, + { "dsa", "pqgyx", 4, 4 }, + { "elg", "pgyx", 3, 3 }, { NULL } }; @@ -432,13 +434,13 @@ do_decryption (const unsigned char *protected, size_t protectedlen, xfree (outbuf); return rc; } - /* do a quick check first */ + /* Do a quick check first. */ if (*outbuf != '(' && outbuf[1] != '(') { xfree (outbuf); return gpg_error (GPG_ERR_BAD_PASSPHRASE); } - /* check that we have a consistent S-Exp */ + /* Check that we have a consistent S-Exp. */ reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL); if (!reallen || (reallen + blklen < protectedlen) ) { @@ -458,7 +460,8 @@ static int merge_lists (const unsigned char *protectedkey, size_t replacepos, const unsigned char *cleartext, - unsigned char *sha1hash, unsigned char **result) + unsigned char *sha1hash, + unsigned char **result, size_t *resultlen) { size_t n, newlistlen; unsigned char *newlist, *p; @@ -559,13 +562,16 @@ merge_lists (const unsigned char *protectedkey, /* ready */ *result = newlist; + *resultlen = newlistlen; return 0; failure: + wipememory (newlist, newlistlen); xfree (newlist); return rc; invalid_sexp: + wipememory (newlist, newlistlen); xfree (newlist); return gpg_error (GPG_ERR_INV_SEXP); } @@ -589,6 +595,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, const unsigned char *prot_begin; unsigned char *cleartext; unsigned char *final; + size_t finallen; s = protectedkey; if (*s != '(') @@ -612,7 +619,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, if (!protect_info[infidx].algo) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); - /* now find the list with the protected information. Here is an + /* Now find the list with the protected information. Here is an example for such a list: (protected openpgp-s2k3-sha1-aes-cbc ((sha1 <salt> <count>) <Initialization_Vector>) @@ -669,7 +676,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, s++; /* skip list end */ n = snext (&s); - if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */ + if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */ return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); iv = s; s += n; @@ -688,7 +695,11 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, return rc; rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext, - sha1hash, &final); + sha1hash, &final, &finallen); + /* Albeit cleartext has been allocated in secure memory and thus + xfree will wipe it out, we do an extra wipe just in case + somethings goes badly wrong. */ + wipememory (cleartext, prot_begin-protectedkey); xfree (cleartext); if (rc) return rc; @@ -698,6 +709,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION); if (rc) { + wipememory (final, finallen); xfree (final); return rc; } @@ -954,7 +966,7 @@ agent_get_shadow_info (const unsigned char *shadowkey, depth--; s++; } - /* found the shadowed list, s points to the protocol */ + /* Found the shadowed list, S points to the protocol */ n = snext (&s); if (!n) return gpg_error (GPG_ERR_INV_SEXP); diff --git a/agent/query.c b/agent/query.c index a3a773380..28873775a 100644 --- a/agent/query.c +++ b/agent/query.c @@ -1,5 +1,5 @@ /* query.c - fork of the pinentry to query stuff from the user - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * -- cgit v1.2.3 From 336e415f5b09819255c4d52d701575282b6ab5ce Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 3 Feb 2004 16:27:51 +0000 Subject: * import.c (check_and_store): Import certificates even with missing issuer's cert. Fixed an "depending on the verbose setting" bug. --- sm/ChangeLog | 4 ++++ sm/import.c | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index cde6e8439..7c4483335 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,9 @@ 2004-02-02 Werner Koch <wk@gnupg.org> + * import.c (check_and_store): Import certificates even with + missing issuer's cert. Fixed an "depending on the verbose + setting" bug. + * certchain.c (gpgsm_validate_chain): Mark revoked certs in the keybox. diff --git a/sm/import.c b/sm/import.c index 2bc6e694f..20413b92c 100644 --- a/sm/import.c +++ b/sm/import.c @@ -130,8 +130,15 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) return; } + /* Some basic checks, but don't care about missing certificates; + this is so that we are able to import entire certificate chains + w/o requirening a special order (i.e. root-CA first). This used + to be different but becuase gpgsm_verify even imports + certificates without any checks, it doesn't matter much and the + code gets much cleaner. A housekeeping function to remove + certificates w/o an anchor would be nice, though. */ rc = gpgsm_basic_cert_check (cert); - if (!rc) + if (!rc || gpg_err_code (rc) == GPG_ERR_MISSING_CERT) { int existed; @@ -161,9 +168,11 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) else log_info ("certificate imported\n"); } + /* Now lets walk up the chain and import all certificates up - the chain.*/ - else if (!gpgsm_walk_cert_chain (cert, &next)) + the chain. This is required in case we already stored + parent certificates in the ephemeral keybox. */ + if (!gpgsm_walk_cert_chain (cert, &next)) { check_and_store (ctrl, stats, next, depth+1); ksba_cert_release (next); @@ -205,7 +214,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) { rc = gpg_error (gpg_err_code_from_errno (errno)); log_error ("fdopen() failed: %s\n", strerror (errno)); - goto leave; + q goto leave; } rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); -- cgit v1.2.3 From 6788ede345957d93cff7827936a98a53dc7f74cc Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 3 Feb 2004 16:38:07 +0000 Subject: Try to use getent, so that it also works for NIS setups. --- tools/ChangeLog | 5 +++++ tools/addgnupghome | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 110a434d7..e764d7b6a 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-02-03 Werner Koch <wk@gnupg.org> + + * addgnupghome: Try to use getent, so that it also works for NIS + setups. + 2004-01-31 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c: Some bug fixes, parse only defaults from the diff --git a/tools/addgnupghome b/tools/addgnupghome index d237a0b42..37a427bf2 100755 --- a/tools/addgnupghome +++ b/tools/addgnupghome @@ -14,6 +14,7 @@ PGM=addgnupghome any_error=0 + error () { echo "$PGM: $*" >&2 any_error=1 @@ -26,9 +27,9 @@ info () { # Do it for one user one_user () { user="$1" - home=$(awk -F: -v n="$user" '$1 == n {print $6}' /etc/passwd ) + home=$(${cat_passwd} | awk -F: -v n="$user" '$1 == n {print $6}') if [ -z "$home" ]; then - if awk -F: -v n="$user" '$1 == n {exit 1}' /etc/passwd; then + if ${cat_passwd} | awk -F: -v n="$user" '$1 == n {exit 1}'; then error "no such user \`$user'" else error "no home directory for user \`$user'" @@ -93,6 +94,14 @@ if [ -z "$1" ]; then exit 1 fi +# Check whether we can use getent +if getent --help </dev/null >/dev/null 2>&1 ; then + cat_passwd='getent passwd' +else + cat_passwd='cat /etc/passwd' + info "please note that only users from /etc/passwd are checked" +fi + if [ ! -d /etc/skel/.gnupg ]; then error "skeleton directory \`/etc/skel/.gnupg' does not exist" exit 1 @@ -101,7 +110,6 @@ cd "/etc/skel/.gnupg" || (error "error cd-ing to \`/etc/skel/.gnupg'"; exit 1) filelist=$(find . \( -type f -or -type d \) -not -name '*~' -not -name . -print) - if ! umask 0077 ; then error "error setting umask" exit 1 -- cgit v1.2.3 From cfb33014ae643381cc0a407ddca50e244c26811c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 4 Feb 2004 19:13:16 +0000 Subject: Fixed a build bug (straw letter in sm/import.c) and updated the documentation. --- TODO | 1 + agent/minip12.c | 63 ++++++++++++++++++++++++++++++++++--- agent/protect-tool.c | 2 +- doc/ChangeLog | 6 ++++ doc/assuan.texi | 2 +- doc/contrib.texi | 89 +++++++++++++++++++++++++++++++++++++++++++--------- doc/gnupg.texi | 2 +- doc/gpg-agent.texi | 15 +++++---- doc/gpgsm.texi | 23 ++++++++------ doc/scdaemon.texi | 4 ++- sm/import.c | 2 +- 11 files changed, 170 insertions(+), 39 deletions(-) diff --git a/TODO b/TODO index 911841514..b45d74737 100644 --- a/TODO +++ b/TODO @@ -48,6 +48,7 @@ might want to have an agent context for each service request ** Check that all error code mapping is done. ** Remove the inter-module dependencies between gpgsm and keybox ** Add an source_of_key field +** We need an error code GPG_ERR_NOT_LOCKED * agent/gpg-agent.c ** A SIGHUP should also restart the scdaemon diff --git a/agent/minip12.c b/agent/minip12.c index 255fef096..753b5022f 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -91,8 +91,12 @@ static unsigned char const oid_encryptedData[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 }; +static unsigned char const oid_pkcs_12_CertBag[11] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x03 }; static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 }; +static unsigned char const oid_pbeWithSHAAnd40BitRC2_CBC[10] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06 }; static unsigned char const oid_rsaEncryption[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; @@ -402,11 +406,62 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, p += DIM(oid_data); n -= DIM(oid_data); - /* fixme: continue parsing */ +#if 0 + where = "bag.encryptedData.keyinfo" + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (!ti.class && ti.tag == TAG_OBJECT_ID + && ti.length == DIM(oid_pbeWithSHAAnd40BitRC2_CBC) + && memcmp (p, oid_pbeWithSHAAnd40BitRC2_CBC, + DIM(oid_pbeWithSHAAnd40BitRC2_CBC))) + { + p += DIM(oid_pbeWithSHAAnd40BitRC2_CBC); + n -= DIM(oid_pbeWithSHAAnd40BitRC2_CBC); + } + else + goto bailout; + + where = "rc2-params"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 ) + goto bailout; + memcpy (salt, p, 8); + p += 8; + n -= 8; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_INTEGER || !ti.length ) + goto bailout; + for (iter=0; ti.length; ti.length--) + { + iter <<= 8; + iter |= (*p++) & 0xff; + n--; + } + + where = "rc2-ciphertext"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length ) + goto bailout; + + log_info ("%lu bytes of RC2 encrypted text\n", ti.length); +#endif + + return 0; bailout: - log_error ("encrptedData error at \"%s\", offset %u\n", + log_error ("encryptedData error at \"%s\", offset %u\n", where, (p - buffer)+startoffset); return -1; } @@ -615,8 +670,8 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, /* Parse a PKCS12 object and return an array of MPI representing the - secret key parameters. This is a very limited inplementation in - that it is only able to look for 3DES encoded enctyptedData and + secret key parameters. This is a very limited implementation in + that it is only able to look for 3DES encoded encryptedData and tries to extract the first private key object it finds. In case of an error NULL is returned. */ gcry_mpi_t * diff --git a/agent/protect-tool.c b/agent/protect-tool.c index e518c5672..d4f945a94 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -648,7 +648,7 @@ import_p12_file (const char *fname) log_printf ("%02X", grip[i]); log_printf ("\n"); - /* convert to canonical encoding */ + /* Convert to canonical encoding. */ buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, NULL, 0); assert (buflen); key = gcry_xmalloc_secure (buflen); diff --git a/doc/ChangeLog b/doc/ChangeLog index 583415cab..39d98b963 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/doc/assuan.texi b/doc/assuan.texi index fbf513ad8..2e2219263 100644 --- a/doc/assuan.texi +++ b/doc/assuan.texi @@ -5,7 +5,7 @@ @node Assuan @chapter Description of the Assuan protocol. -The architecture of the modula GnuPG system is based on a couple of +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. diff --git a/doc/contrib.texi b/doc/contrib.texi index 0b250eecc..035b6c251 100644 --- a/doc/contrib.texi +++ b/doc/contrib.texi @@ -40,23 +40,84 @@ underspecified interfaces. Thomas Koester did extensive testing and tracked down a lot of bugs @item -Werner Koch desgned the system and wrote most of the original code. +Werner Koch designed the system and wrote most of the original code. @end itemize -FIXME: We need to copy a lot of credits from GnupG 1.0 to here. - - -We'd also like to thank the folks who have contributed time and energy in -testing GnuPG: - -@itemize @bullet -@item -Joe R. Hacker - -@item -And many others -@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, Rmi Guyomarch, Stefan Bellon, Timo Schulz and Werner +Koch wrote the code. Birger Langkjer, Daniel Resare, Dokianakis +Theofanis, Edmund GRIMLEY EVANS, Gal Quri, Gregory Steuck, Nagy +Ferenc Lszl, 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, Gal +Quri, 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 Teveen, Jrg 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 Jskelinen, 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, Rmi 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 Mller, 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 diff --git a/doc/gnupg.texi b/doc/gnupg.texi index de243a8f7..d85b81ff9 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -112,7 +112,7 @@ Boston, MA 02111-1307 USA @cindex introduction This manual documents how to use the GNU Privay Guard system as well as -the administartion and the architecture. +the administration and the architecture. @c * Gpg:: Using the OpenPGP protocol. @menu diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 793d093a1..fbab7a17e 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -118,7 +118,9 @@ $ eval `gpg-agent --daemon` @item --options @var{file} @opindex options Reads configuration from @var{file} instead of from the default -per-user configuration file. +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 @@ -224,15 +226,16 @@ control this behaviour but this command line option takes precedence. Set the time a cache entry is valid to @var{n} seconds. The default are 600 seconds. -@item --pinentry-program @var{path} +@item --pinentry-program @var{filename} @opindex pinentry-program -Use program @var{path} as the PIN entry. The default is installation +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{path} +@item --scdaemon-program @var{filename} @opindex scdaemon-program -Use program @var{path} as the Smartcard daemon. The default is installation -dependend and can be shown with the @code{--version} command. +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} diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 6695eef67..1c8b3071b 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -98,11 +98,12 @@ Run in server mode and wait for commands on the @code{stdin}. @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 filenames given as arguments should have an -absulte path 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. +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 @@ -193,7 +194,9 @@ in the option file. @item --options @var{file} @opindex options Reads configuration from @var{file} instead of from the default -per-user configuration file. +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 @@ -299,7 +302,7 @@ secret key found in the database. @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 filename of the +key. This string is for example used as the file name of the secret key. @end table @@ -360,10 +363,10 @@ usual C-Syntax. The currently defined bits are: @opindex debug-all Same as @code{--debug=0xffffffff} -@item --debug-no-path-validation -@opindex debug-no-path-validation +@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 path validation checks. +lets gpgsm bypass all certificate chain validation checks. @end table diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index e62146837..5a5a1af6a 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -76,7 +76,9 @@ This is mainly a debugging command, used to print the ATR @item --options @var{file} @opindex options Reads configuration from @var{file} instead of from the default -per-user configuration file. +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 diff --git a/sm/import.c b/sm/import.c index 20413b92c..132b7403e 100644 --- a/sm/import.c +++ b/sm/import.c @@ -214,7 +214,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) { rc = gpg_error (gpg_err_code_from_errno (errno)); log_error ("fdopen() failed: %s\n", strerror (errno)); - q goto leave; + goto leave; } rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); -- cgit v1.2.3 From a1dd1cc223e2da077cbbe2716c12a67d00c6947e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 10 Feb 2004 19:26:55 +0000 Subject: * minip12.c (parse_bag_encrypted_data): Finished implementation. (p12_parse): Add callback args. * protect-tool.c (import_p12_cert_cb): New. (import_p12_file): Use it. --- agent/ChangeLog | 12 ++++ agent/minip12.c | 199 ++++++++++++++++++++++++++++++++++++++++++--------- agent/minip12.h | 4 +- agent/protect-tool.c | 22 +++++- 4 files changed, 199 insertions(+), 38 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 01a3c90f5..1589d4f9a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,15 @@ +2004-02-10 Werner Koch <wk@gnupg.org> + + * minip12.c (parse_bag_encrypted_data): Finished implementation. + (p12_parse): Add callback args. + * protect-tool.c (import_p12_cert_cb): New. + (import_p12_file): Use it. + +2004-02-06 Werner Koch <wk@gnupg.org> + + * minip12.c (crypt_block): Add arg CIPHER_ALGO; changed all callers. + (set_key_iv): Add arg KEYBYTES; changed caller. + 2004-02-03 Werner Koch <wk@gnupg.org> * findkey.c (agent_key_from_file): Extra paranoid wipe. diff --git a/agent/minip12.c b/agent/minip12.c index 753b5022f..af39ae0fd 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -1,5 +1,5 @@ /* minip12.c - A minimal pkcs-12 implementation. - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -27,7 +27,12 @@ #include <assert.h> #include <gcrypt.h> -#undef TEST +#ifdef __GCC__ +#warning Remove this kludge and set the libgcrypt required version higher. +#endif +#ifndef GCRY_CIPHER_RFC2268_40 +#define GCRY_CIPHER_RFC2268_40 307 +#endif #ifdef TEST #include <sys/stat.h> @@ -97,6 +102,9 @@ static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 }; static unsigned char const oid_pbeWithSHAAnd40BitRC2_CBC[10] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06 }; +static unsigned char const oid_x509Certificate_for_pkcs_12[10] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01 }; + static unsigned char const oid_rsaEncryption[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; @@ -303,14 +311,16 @@ string_to_key (int id, char *salt, int iter, const char *pw, static int -set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw) +set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw, + int keybytes) { unsigned char keybuf[24]; int rc; - if (string_to_key (1, salt, iter, pw, 24, keybuf)) + assert (keybytes == 5 || keybytes == 24); + if (string_to_key (1, salt, iter, pw, keybytes, keybuf)) return -1; - rc = gcry_cipher_setkey (chd, keybuf, 24); + rc = gcry_cipher_setkey (chd, keybuf, keybytes); if (rc) { log_error ( "gcry_cipher_setkey failed: %s\n", gpg_strerror (rc)); @@ -331,18 +341,19 @@ set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw) static void crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, - const char *pw, int encrypt) + const char *pw, int cipher_algo, int encrypt) { gcry_cipher_hd_t chd; int rc; - rc = gcry_cipher_open (&chd, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); + rc = gcry_cipher_open (&chd, cipher_algo, GCRY_CIPHER_MODE_CBC, 0); if (rc) { - log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(-1)); + log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(rc)); return; } - if (set_key_iv (chd, salt, iter, pw)) + if (set_key_iv (chd, salt, iter, pw, + cipher_algo == GCRY_CIPHER_RFC2268_40? 5:24)) goto leave; rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0) @@ -354,12 +365,6 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, goto leave; } -/* { */ -/* FILE *fp = fopen("inner.der", "wb"); */ -/* fwrite (buffer, 1, length, fp); */ -/* fclose (fp); */ -/* } */ - leave: gcry_cipher_close (chd); } @@ -369,12 +374,18 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, static int parse_bag_encrypted_data (const unsigned char *buffer, size_t length, - int startoffset) + int startoffset, const char *pw, + void (*certcb)(void*, const unsigned char*, size_t), + void *certcbarg) { struct tag_info ti; const unsigned char *p = buffer; size_t n = length; const char *where; + char salt[8]; + unsigned int iter; + unsigned char *plain = NULL; + where = "start"; if (parse_tag (&p, &n, &ti)) @@ -406,18 +417,17 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, p += DIM(oid_data); n -= DIM(oid_data); -#if 0 - where = "bag.encryptedData.keyinfo" + where = "bag.encryptedData.keyinfo"; if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class || ti.tag != TAG_SEQUENCE) goto bailout; if (parse_tag (&p, &n, &ti)) goto bailout; - if (!ti.class && ti.tag == TAG_OBJECT_ID + if (!ti.class && ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_pbeWithSHAAnd40BitRC2_CBC) - && memcmp (p, oid_pbeWithSHAAnd40BitRC2_CBC, - DIM(oid_pbeWithSHAAnd40BitRC2_CBC))) + && !memcmp (p, oid_pbeWithSHAAnd40BitRC2_CBC, + DIM(oid_pbeWithSHAAnd40BitRC2_CBC))) { p += DIM(oid_pbeWithSHAAnd40BitRC2_CBC); n -= DIM(oid_pbeWithSHAAnd40BitRC2_CBC); @@ -451,16 +461,118 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, where = "rc2-ciphertext"; if (parse_tag (&p, &n, &ti)) goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length ) + if (ti.class != CONTEXT || ti.tag != 0 || !ti.length ) goto bailout; log_info ("%lu bytes of RC2 encrypted text\n", ti.length); -#endif + plain = gcry_malloc_secure (ti.length); + if (!plain) + { + log_error ("error allocating decryption buffer\n"); + goto bailout; + } + memcpy (plain, p, ti.length); + crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_RFC2268_40, 0); + n = ti.length; + startoffset = 0; + buffer = p = plain; + + where = "outer.outer.seq"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + + if (parse_tag (&p, &n, &ti)) + goto bailout; + + /* Loop over all certificates inside the bab. */ + while (n) + { + where = "certbag.nextcert"; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + where = "certbag.objectidentifier"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_pkcs_12_CertBag) + || memcmp (p, oid_pkcs_12_CertBag, + DIM(oid_pkcs_12_CertBag))) + goto bailout; + p += DIM(oid_pkcs_12_CertBag); + n -= DIM(oid_pkcs_12_CertBag); + + where = "certbag.before.certheader"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_x509Certificate_for_pkcs_12) + || memcmp (p, oid_x509Certificate_for_pkcs_12, + DIM(oid_x509Certificate_for_pkcs_12))) + goto bailout; + p += DIM(oid_x509Certificate_for_pkcs_12); + n -= DIM(oid_x509Certificate_for_pkcs_12); + + where = "certbag.before.octetstring"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING || ti.ndef) + goto bailout; + + /* Return the certificate. */ + if (certcb) + certcb (certcbarg, p, ti.length); + + p += ti.length; + n -= ti.length; + + /* Ugly hack to cope with the padding: Forget about a rest of + sie les than the cipher's block length. */ + if (n < 8) + n = 0; + + /* Skip the optional SET with the pkcs12 cert attributes. */ + if (n) + { + where = "certbag.attributes"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (!ti.class && ti.tag == TAG_SEQUENCE) + ; /* No attributes. */ + else if (!ti.class && ti.tag == TAG_SET && !ti.ndef) + { /* The optional SET. */ + p += ti.length; + n -= ti.length; + if (n < 8) + n = 0; + if (n && parse_tag (&p, &n, &ti)) + goto bailout; + } + else + goto bailout; + } + } + + gcry_free (plain); return 0; bailout: + gcry_free (plain); log_error ("encryptedData error at \"%s\", offset %u\n", where, (p - buffer)+startoffset); return -1; @@ -574,7 +686,7 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, goto bailout; } memcpy (plain, p, ti.length); - crypt_block (plain, ti.length, salt, iter, pw, 0); + crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_3DES, 0); n = ti.length; startoffset = 0; buffer = p = plain; @@ -673,9 +785,12 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, secret key parameters. This is a very limited implementation in that it is only able to look for 3DES encoded encryptedData and tries to extract the first private key object it finds. In case of - an error NULL is returned. */ + an error NULL is returned. CERTCB and CERRTCBARG are used to pass + X.509 certificates back to the caller. */ gcry_mpi_t * -p12_parse (const unsigned char *buffer, size_t length, const char *pw) +p12_parse (const unsigned char *buffer, size_t length, const char *pw, + void (*certcb)(void*, const unsigned char*, size_t), + void *certcbarg) { struct tag_info ti; const unsigned char *p = buffer; @@ -751,7 +866,8 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw) n -= DIM(oid_encryptedData); len -= DIM(oid_encryptedData); where = "bag.encryptedData"; - if (parse_bag_encrypted_data (p, n, (p - buffer))) + if (parse_bag_encrypted_data (p, n, (p - buffer), pw, + certcb, certcbarg)) goto bailout; } else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data) @@ -1034,7 +1150,7 @@ p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length) /* Encrypt it and prepend a lot of stupid things. */ gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); - crypt_block (plain, plainlen, salt, 1024, pw, 1); + crypt_block (plain, plainlen, salt, 1024, pw, GCRY_CIPHER_3DES, 1); /* the data goes into an octet string. */ needed = compute_tag_length (plainlen); needed += plainlen; @@ -1128,14 +1244,21 @@ p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length) #ifdef TEST + +static void +cert_cb (void *opaque, const unsigned char *cert, size_t certlen) +{ + printf ("got a certificate of %u bytes length\n", certlen); +} + int main (int argc, char **argv) { FILE *fp; struct stat st; - char *buf; + unsigned char *buf; size_t buflen; - GcryMPI *result; + gcry_mpi_t *result; if (argc != 3) { @@ -1168,23 +1291,23 @@ main (int argc, char **argv) } fclose (fp); - result = p12_parse (buf, buflen, argv[2]); + result = p12_parse (buf, buflen, argv[2], cert_cb, NULL); if (result) { int i, rc; - char *buf; + unsigned char *tmpbuf; for (i=0; result[i]; i++) { - rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, + rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &tmpbuf, NULL, result[i]); if (rc) printf ("%d: [error printing number: %s]\n", i, gpg_strerror (rc)); else { - printf ("%d: %s\n", i, buf); - gcry_free (buf); + printf ("%d: %s\n", i, tmpbuf); + gcry_free (tmpbuf); } } } @@ -1192,4 +1315,10 @@ main (int argc, char **argv) return 0; } + +/* +Local Variables: +compile-command: "gcc -Wall -O -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error" +End: +*/ #endif /* TEST */ diff --git a/agent/minip12.h b/agent/minip12.h index 122215549..61a597926 100644 --- a/agent/minip12.h +++ b/agent/minip12.h @@ -24,7 +24,9 @@ #include <gcrypt.h> gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length, - const char *pw); + const char *pw, + void (*certcb)(void*, const unsigned char*, size_t), + void *certcbarg); unsigned char *p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length); diff --git a/agent/protect-tool.c b/agent/protect-tool.c index d4f945a94..2d1df4d7c 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -563,6 +563,23 @@ rsa_key_check (struct rsa_secret_key_s *skey) } +/* A callback used by p12_parse to return a certificate. */ +static void +import_p12_cert_cb (void *opaque, const unsigned char *cert, size_t certlen) +{ + struct b64state state; + gpg_error_t err, err2; + + err = b64enc_start (&state, stdout, "CERTIFICATE"); + if (!err) + err = b64enc_write (&state, cert, certlen); + err2 = b64enc_finish (&state); + if (!err) + err = err2; + if (err) + log_error ("error writing armored certificate: %s\n", gpg_strerror (err)); +} + static void import_p12_file (const char *fname) { @@ -583,11 +600,12 @@ import_p12_file (const char *fname) if (!buf) return; - kparms = p12_parse (buf, buflen, get_passphrase ()); + kparms = p12_parse (buf, buflen, get_passphrase (), + import_p12_cert_cb, NULL); xfree (buf); if (!kparms) { - log_error ("error parsing or decrypting the PKCS-1 file\n"); + log_error ("error parsing or decrypting the PKCS-12 file\n"); return; } for (i=0; kparms[i]; i++) -- cgit v1.2.3 From f0d63ef75d2f03d41260e2c6a9f277cbcd71987a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 10 Feb 2004 19:27:54 +0000 Subject: New. Based on code from ../sm/base64.c. --- common/ChangeLog | 4 + common/Makefile.am | 1 + common/b64enc.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/util.h | 20 ++++- 4 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 common/b64enc.c diff --git a/common/ChangeLog b/common/ChangeLog index 1266a88c5..6355f350a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/Makefile.am b/common/Makefile.am index 640051be4..393e48435 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -34,6 +34,7 @@ libcommon_a_SOURCES = \ sysutils.c sysutils.h \ gettime.c \ yesno.c \ + b64enc.c \ miscellaneous.c \ xasprintf.c \ membuf.c membuf.h \ diff --git a/common/b64enc.c b/common/b64enc.c new file mode 100644 index 000000000..edcf6e3ad --- /dev/null +++ b/common/b64enc.c @@ -0,0 +1,211 @@ +/* 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; +} + diff --git a/common/util.h b/common/util.h index 7e134e846..ca7266627 100644 --- a/common/util.h +++ b/common/util.h @@ -1,5 +1,5 @@ -/* util.h - Utility functions for Gnupg - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +/* util.h - Utility functions for GnuPG + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -98,6 +98,22 @@ int answer_is_yes_no_default (const char *s, int def_answer); int answer_is_yes_no_quit (const char *s); +/*-- 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 -- cgit v1.2.3 From 53d11566822393b91d8ca238a6bc98c7291440fe Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:25:30 +0000 Subject: * am/cmacros.am: New. * 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. --- ChangeLog | 13 ++++ NEWS | 3 + acinclude.m4 | 2 +- autogen.sh | 4 +- configure.ac | 220 ++++++++++++++++++++++++++++------------------------------- 5 files changed, 124 insertions(+), 118 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b729bf9e..30916e04e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-02-12 Werner Koch <wk@gnupg.org> + + * 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. diff --git a/NEWS b/NEWS index f5d2a551c..82f7e575e 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ Noteworthy changes in version 1.9.5 ------------------------------------------------ + * 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. Noteworthy changes in version 1.9.4 (2004-01-30) ------------------------------------------------ diff --git a/acinclude.m4 b/acinclude.m4 index 023563422..6855cbee7 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -596,7 +596,7 @@ AC_DEFUN(AM_PATH_OPENSC, 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` + 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 | \ diff --git a/autogen.sh b/autogen.sh index a317f0b20..4fbcdca6f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -18,7 +18,7 @@ cvtver () { } check_version () { - if [ $(( `("$1" --version || echo "0") | cvtver` >= $2 )) == 1 ]; then + if [ `("$1" --version || echo "0") | cvtver` -ge "$2" ]; then return 0 fi echo "**Error**: "\`$1\'" not installed or too old." >&2 @@ -148,6 +148,8 @@ EOF exit 1 fi +exit 0 + echo "Running aclocal -I m4 ..." $ACLOCAL -I m4 echo "Running autoheader..." diff --git a/configure.ac b/configure.ac index ffb6bd788..6b8c1994d 100644 --- a/configure.ac +++ b/configure.ac @@ -74,63 +74,58 @@ AC_DEFINE_UNQUOTED(NEED_KSBA_VERSION, "$NEED_KSBA_VERSION", - -# I know that it is in general not a good idea to evaluate bindir in -# the configuration but we want to hard code the defaults into some of -# the programs and doing this during a make install is not a good -# idea. We also have the problem that 2 of the programs are included -# in the package but the others are distributed in other packages. -eval my_default_bindir=${exec_prefix} -test "x${my_default_bindir}" = xNONE && my_default_bindir=${ac_default_prefix} -my_default_bindir=${my_default_bindir}/bin - -# Same goes for the pkglibdir which is used to call the gpg-protect-tool. -eval my_default_pkglibdir=${exec_prefix} -test "x${my_default_pkglibdir}" = xNONE && my_default_pkglibdir=${ac_default_prefix} -my_default_pkglibdir=${my_default_pkglibdir}/lib/${PACKAGE_NAME} - +# The default is to use the modules from this package and the few +# other packages in a standard place; i.e where this package gets +# installed. With these options it is possible to override these +# ${prefix} depended values with fixed paths, which can't be replaced +# at make time. See also am/cmacros.am and the defaults in AH_BOTTOM. AC_ARG_WITH(agent-pgm, - [ --with-agent-pgm=PATH Use PATH as the default for the gpg-agent)], - gnupg_agent_pgm="$withval", - gnupg_agent_pgm="${my_default_bindir}/gpg-agent" ) -AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_AGENT, "$gnupg_agent_pgm", - [Default location of the gpg-agent program]) + [ --with-agent-pgm=PATH Use PATH as the default for the agent)], + GNUPG_AGENT_PGM="$withval", GNUPG_AGENT_PGM="" ) +AC_SUBST(GNUPG_AGENT_PGM) +AM_CONDITIONAL(GNUPG_AGENT_PGM, test -n "$GNUPG_AGENT_PGM") +show_gnupg_agent_pgm="(default)" +test -n "$GNUPG_AGENT_PGM" && show_gnupg_agent_pgm="$GNUPG_AGENT_PGM" + AC_ARG_WITH(pinentry-pgm, [ --with-pinentry-pgm=PATH Use PATH as the default for the pinentry)], - gnupg_pinentry_pgm="$withval", gnupg_pinentry_pgm="" ) -if test -z "$gnupg_pinentry_pgm"; then - gnupg_pinentry_pgm=${my_default_bindir}/pinentry -fi -AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_PINENTRY, "$gnupg_pinentry_pgm", - [Default location of the pinentry program]) + GNUPG_PINENTRY_PGM="$withval", GNUPG_PINENTRY_PGM="" ) +AC_SUBST(GNUPG_PINENTRY_PGM) +AM_CONDITIONAL(GNUPG_PINENTRY_PGM, test -n "$GNUPG_PINENTRY_PGM") +show_gnupg_pinentry_pgm="(default)" +test -n "$GNUPG_PINENTRY_PGM" && show_gnupg_pinentry_pgm="$GNUPG_PINENTRY_PGM" + + AC_ARG_WITH(scdaemon-pgm, [ --with-scdaemon-pgm=PATH Use PATH as the default for the scdaemon)], - gnupg_scdaemon_pgm="$withval", gnupg_scdaemon_pgm="" ) -if test -z "$gnupg_scdaemon_pgm"; then - gnupg_scdaemon_pgm=${my_default_bindir}/scdaemon -fi -AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_SCDAEMON, "$gnupg_scdaemon_pgm", - [Default location of the scdaemon program]) + GNUPG_SCDAEMON_PGM="$withval", GNUPG_SCDAEMON_PGM="" ) +AC_SUBST(GNUPG_SCDAEMON_PGM) +AM_CONDITIONAL(GNUPG_SCDAEMON_PGM, test -n "$GNUPG_SCDAEMON_PGM") +show_gnupg_scdaemon_pgm="(default)" +test -n "$GNUPG_SCDAEMON_PGM" && show_gnupg_scdaemon_pgm="$GNUPG_SCDAEMON_PGM" + + AC_ARG_WITH(dirmngr-pgm, [ --with-dirmngr-pgm=PATH Use PATH as the default for the dirmngr)], - gnupg_dirmngr_pgm="$withval", gnupg_dirmngr_pgm="" ) -if test -z "$gnupg_dirmngr_pgm"; then - gnupg_dirmngr_pgm=${my_default_bindir}/dirmngr -fi -AC_DEFINE_UNQUOTED(GNUPG_DEFAULT_DIRMNGR, "$gnupg_dirmngr_pgm", - [Default location of the dirmngr program]) - -AC_ARG_WITH(protect-tool, - [ --with-protect-tool=PATH Use PATH as the protect-tool)], - gnupg_protect_tool="$withval", gnupg_protect_tool="" ) -if test -z "$gnupg_protect_tool"; then - gnupg_protect_tool=${my_default_pkglibdir}/gpg-protect-tool -fi -AC_DEFINE_UNQUOTED(GNUPG_PROTECT_TOOL, "$gnupg_protect_tool", - [Name of the protect tool program]) + GNUPG_DIRMNGR_PGM="$withval", GNUPG_DIRMNGR_PGM="" ) +AC_SUBST(GNUPG_DIRMNGR_PGM) +AM_CONDITIONAL(GNUPG_DIRMNGR_PGM, test -n "$GNUPG_DIRMNGR_PGM") +show_gnupg_dirmngr_pgm="(default)" +test -n "$GNUPG_DIRMNGR_PGM" && show_gnupg_dirmngr_pgm="$GNUPG_DIRMNGR_PGM" +AC_ARG_WITH(protect-tool-pgm, + [ --with-protect-tool-pgm=PATH Use PATH as the default for the protect-tool)], + GNUPG_PROTECT_TOOL_PGM="$withval", GNUPG_PROTECT_TOOL_PGM="" ) +AC_SUBST(GNUPG_PROTECT_TOOL_PGM) +AM_CONDITIONAL(GNUPG_PROTECT_TOOL_PGM, test -n "$GNUPG_PROTECT_TOOL_PGM") +show_gnupg_protect_tool_pgm="(default)" +test -n "$GNUPG_PROTECT_TOOL_PGM" \ + && show_gnupg_protect_tool_pgm="$GNUPG_PROTECT_TOOL_PGM" + +# Configure option to allow ot disallow execution of external +# programs, like a photo viewer. AC_MSG_CHECKING([whether to enable external program execution]) AC_ARG_ENABLE(exec, AC_HELP_STRING([--disable-exec],[disable all external program execution]), @@ -226,15 +221,13 @@ AH_BOTTOM([ /* Some global constants. */ #ifdef HAVE_DRIVE_LETTERS #define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" +#elif defined(__VMS) +#define GNUPG_DEFAULT_HOMEDIR "/SYS\$LOGIN/gnupg" #else #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" #endif #define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" -#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) -#define EXEC_TEMPFILE_ONLY -#endif - /* Tell libgcrypt not to use its own libgpg-error implementation. */ #define USE_LIBGPG_ERROR 1 @@ -243,7 +236,59 @@ AH_BOTTOM([ we use 2 here even for GnuPG 1.9.x. */ #define GNUPG_MAJOR_VERSION 2 -#include "g10defs.h" +/* Now to separate file name parts. + Please note that the string version must not contain more + than one character because the code assumes strlen()==1 */ +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\' +#define EXTSEP_C '.' +#define DIRSEP_S "\\" +#define EXTSEP_S "." +#else +#define DIRSEP_C '/' +#define EXTSEP_C '.' +#define DIRSEP_S "/" +#define EXTSEP_S "." +#endif + +/* This is the same as VERSION, but should be overridden if the + platform cannot handle things like dots '.' in filenames. */ +#define SAFE_VERSION VERSION + +/* For some systems (DOS currently), we hardcode the path here. For + POSIX systems the values are constructed by the Makefiles, so that + the values may be overridden by the make invocations; this is to + comply with the GNU coding standards. */ +#ifdef HAVE_DRIVE_LETTERS +#define GNUPG_BINDIR "c:\\gnupg" +#define GNUPG_LIBEXECDIR "c:\\lib\\gnupg" +#define GNUPG_LIBDIR "c:\\lib\\gnupg" +#define GNUPG_DATADIR "c:\\lib\\gnupg" +#endif + +/* Setup the hardwired names of modules. */ +#ifndef GNUPG_DEFAULT_AGENT +#define GNUPG_DEFAULT_AGENT ( GNUPG_BINDIR DIRSEP_S "gpg-agent" ) +#endif +#ifndef GNUPG_DEFAULT_PINENTRY +#define GNUPG_DEFAULT_PINENTRY ( GNUPG_BINDIR DIRSEP_S "pinentry" ) +#endif +#ifndef GNUPG_DEFAULT_SCDAEMON +#define GNUPG_DEFAULT_SCDAEMON ( GNUPG_BINDIR DIRSEP_S "scdaemon" ) +#endif +#ifndef GNUPG_DEFAULT_DIRMNGR +#define GNUPG_DEFAULT_DIRMNGR ( GNUPG_BINDIR DIRSEP_S "dirmngr" ) +#endif +#ifndef GNUPG_DEFAULT_PROTECT_TOOL +#define GNUPG_DEFAULT_PROTECT_TOOL \ + ( GNUPG_LIBEXECDIR DIRSEP_S "gpg-protect-tool" ) +#endif + + +/* Derive some other constants. */ +#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) +#define EXEC_TEMPFILE_ONLY +#endif ]) @@ -406,7 +451,6 @@ if test $have_opensc = yes; then [defined if the OpenSC library is available]) fi - # # Check whether the (highly desirable) GNU Pth library is available # @@ -1004,64 +1048,6 @@ AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") -AC_CONFIG_COMMANDS(g10defs.h,[[ -cat >g10defs.tmp <<G10EOF -/* Generated automatically by configure */ -/* FIXME: Shouldn't we replace GNUPG_HOMEDIR by GNUPG_DEFAULT_HOMEDIR - and we propably can get rid of g10defs.h */ -#ifdef HAVE_DRIVE_LETTERS -/*#define G10_LOCALEDIR "c:\\\\lib\\\\gnupg\\\\locale"*/ -#define GNUPG_LIBDIR "c:\\\\lib\\\\gnupg" -#define GNUPG_LIBEXECDIR "c:\\\\lib\\\\gnupg" -#define GNUPG_DATADIR "c:\\\\lib\\\\gnupg" -#define GNUPG_HOMEDIR "c:\\\\gnupg" -#else -/*#define G10_LOCALEDIR "${datadir}/locale"*/ -#define GNUPG_LIBDIR "${libdir}/gnupg" -#define GNUPG_DATADIR "${datadir}/gnupg" -#ifdef __VMS -#define GNUPG_HOMEDIR "/SYS\$LOGIN/gnupg" -#else -#define GNUPG_HOMEDIR "~/.gnupg" -#endif -#endif -/* those are here to be redefined by handcrafted g10defs.h. - Please note that the string version must not contain more - than one character because the using code assumes strlen()==1 */ -#ifdef HAVE_DOSISH_SYSTEM -#define DIRSEP_C '\\\\' -#define EXTSEP_C '.' -#define DIRSEP_S "\\\\" -#define EXTSEP_S "." -#else -#define DIRSEP_C '/' -#define EXTSEP_C '.' -#define DIRSEP_S "/" -#define EXTSEP_S "." -#endif -/* This is the same as VERSION, but should be overridden if the - platform cannot handle things like dots '.' in filenames. */ -#define SAFE_VERSION VERSION -G10EOF -## Do we really need the following? It defines BYTES_PER-MPI_LIMB -## cat mpi/mpi-asm-defs.h >>g10defs.tmp -if cmp -s g10defs.h g10defs.tmp 2>/dev/null; then - echo "g10defs.h is unchanged" - rm -f g10defs.tmp -else - rm -f g10defs.h - mv g10defs.tmp g10defs.h - echo "g10defs.h created" -fi -]],[[ -prefix=$prefix -exec_prefix=$exec_prefix -libdir=$libdir -libexecdir=$libexecdir -datadir=$datadir -DATADIRNAME=$DATADIRNAME -]]) - AC_CONFIG_FILES([ m4/Makefile Makefile po/Makefile.in @@ -1080,6 +1066,8 @@ tests/Makefile AC_OUTPUT + + echo " GnuPG v${VERSION} has been configured as follows: @@ -1090,10 +1078,10 @@ echo " Agent: $build_agent $build_agent_threaded Smartcard: $build_scdaemon $build_scdaemon_extra - Protect tool: $gnupg_protect_tool - Default agent: $gnupg_agent_pgm - Default pinentry: $gnupg_pinentry_pgm - Default scdaemon: $gnupg_scdaemon_pgm - Default dirmngr: $gnupg_dirmngr_pgm + Protect tool: $show_gnupg_protect_tool_pgm + Default agent: $show_gnupg_agent_pgm + Default pinentry: $show_gnupg_pinentry_pgm + Default scdaemon: $show_gnupg_scdaemon_pgm + Default dirmngr: $show_gnupg_dirmngr_pgm " -- cgit v1.2.3 From f5c3d2712b7745ca6ad8ad9fe2c0d30f50a6adb5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:27:36 +0000 Subject: Include cmacros.am for common flags. (libexec_PROGRAMS): Put gpg-protect-tool there. --- agent/ChangeLog | 5 +++ agent/Makefile.am | 14 +++---- agent/minip12.c | 107 +++++++++++++++++++++++++++++++++++------------------- 3 files changed, 81 insertions(+), 45 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 1589d4f9a..d9e4049ff 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-02-12 Werner Koch <wk@gnupg.org> + + * Makefile.am: Include cmacros.am for common flags. + (libexec_PROGRAMS): Put gpg-protect-tool there. + 2004-02-10 Werner Koch <wk@gnupg.org> * minip12.c (parse_bag_encrypted_data): Finished implementation. diff --git a/agent/Makefile.am b/agent/Makefile.am index 65af03368..6f7097749 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2001, 2003 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -18,14 +18,14 @@ ## Process this file with automake to produce Makefile.in -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - bin_PROGRAMS = gpg-agent -pkglib_PROGRAMS = gpg-protect-tool +libexec_PROGRAMS = gpg-protect-tool + +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl + +include $(top_srcdir)/am/cmacros.am -AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS) \ - $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) gpg_agent_SOURCES = \ gpg-agent.c agent.h \ diff --git a/agent/minip12.c b/agent/minip12.c index af39ae0fd..1e86bc251 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -98,6 +98,9 @@ static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 }; static unsigned char const oid_pkcs_12_CertBag[11] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x03 }; +static unsigned char const oid_pkcs_12_CrlBag[11] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x04 }; + static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 }; static unsigned char const oid_pbeWithSHAAnd40BitRC2_CBC[10] = { @@ -490,6 +493,8 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, /* Loop over all certificates inside the bab. */ while (n) { + int isbag = 0; + where = "certbag.nextcert"; if (ti.class || ti.tag != TAG_SEQUENCE) goto bailout; @@ -497,59 +502,78 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, where = "certbag.objectidentifier"; if (parse_tag (&p, &n, &ti)) goto bailout; - if (ti.class || ti.tag != TAG_OBJECT_ID - || ti.length != DIM(oid_pkcs_12_CertBag) - || memcmp (p, oid_pkcs_12_CertBag, - DIM(oid_pkcs_12_CertBag))) - goto bailout; - p += DIM(oid_pkcs_12_CertBag); - n -= DIM(oid_pkcs_12_CertBag); - - where = "certbag.before.certheader"; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class != CONTEXT || ti.tag) - goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; - if (parse_tag (&p, &n, &ti)) + if (ti.class || ti.tag != TAG_OBJECT_ID) goto bailout; - if (ti.class || ti.tag != TAG_OBJECT_ID - || ti.length != DIM(oid_x509Certificate_for_pkcs_12) - || memcmp (p, oid_x509Certificate_for_pkcs_12, - DIM(oid_x509Certificate_for_pkcs_12))) + if ( ti.length == DIM(oid_pkcs_12_CertBag) + && !memcmp (p, oid_pkcs_12_CertBag, DIM(oid_pkcs_12_CertBag))) + { + p += DIM(oid_pkcs_12_CertBag); + n -= DIM(oid_pkcs_12_CertBag); + } + else if ( ti.length == DIM(oid_pkcs_12_CrlBag) + && !memcmp (p, oid_pkcs_12_CrlBag, DIM(oid_pkcs_12_CrlBag))) + { + p += DIM(oid_pkcs_12_CrlBag); + n -= DIM(oid_pkcs_12_CrlBag); + isbag = 1; + } + else goto bailout; - p += DIM(oid_x509Certificate_for_pkcs_12); - n -= DIM(oid_x509Certificate_for_pkcs_12); - where = "certbag.before.octetstring"; + where = "certbag.before.certheader"; if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class != CONTEXT || ti.tag) goto bailout; - if (parse_tag (&p, &n, &ti)) - goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING || ti.ndef) - goto bailout; - - /* Return the certificate. */ - if (certcb) - certcb (certcbarg, p, ti.length); + if (isbag) + { + log_info ("skipping unsupported crlBag\n"); + p += ti.length; + n -= ti.length; + } + else + { + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_x509Certificate_for_pkcs_12) + || memcmp (p, oid_x509Certificate_for_pkcs_12, + DIM(oid_x509Certificate_for_pkcs_12))) + goto bailout; + p += DIM(oid_x509Certificate_for_pkcs_12); + n -= DIM(oid_x509Certificate_for_pkcs_12); + + where = "certbag.before.octetstring"; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class != CONTEXT || ti.tag) + goto bailout; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (ti.class || ti.tag != TAG_OCTET_STRING || ti.ndef) + goto bailout; + + /* Return the certificate. */ + if (certcb) + certcb (certcbarg, p, ti.length); - p += ti.length; - n -= ti.length; + p += ti.length; + n -= ti.length; + } - /* Ugly hack to cope with the padding: Forget about a rest of - sie les than the cipher's block length. */ + /* Ugly hack to cope with the padding: Forget about the rest if + that it is less than the cipher's block length. */ if (n < 8) n = 0; /* Skip the optional SET with the pkcs12 cert attributes. */ if (n) { - where = "certbag.attributes"; + where = "bag.attributes"; if (parse_tag (&p, &n, &ti)) goto bailout; if (!ti.class && ti.tag == TAG_SEQUENCE) @@ -691,6 +715,13 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, startoffset = 0; buffer = p = plain; + { + FILE *fp = fopen ("tmp-3des-plain.der", "wb"); + if (!fp || fwrite (p, n, 1, fp) != 1) + exit (2); + fclose (fp); + } + where = "decrypted-text"; if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) goto bailout; -- cgit v1.2.3 From 0bcd5e329b8c25a21b6d41ef66e7a7478b0fa5e7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:27:58 +0000 Subject: New --- am/cmacros.am | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 am/cmacros.am diff --git a/am/cmacros.am b/am/cmacros.am new file mode 100644 index 000000000..0f7a09fe0 --- /dev/null +++ b/am/cmacros.am @@ -0,0 +1,45 @@ +# 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 -- cgit v1.2.3 From 584784ba6d6db6f24d3310f2d458cae50380792b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:28:32 +0000 Subject: minor cleanups --- common/Makefile.am | 3 +-- common/sysutils.c | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/Makefile.am b/common/Makefile.am index 393e48435..a5d2a4e5d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -20,11 +20,10 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = mkerrors mkerrtok -#INCLUDES = noinst_LIBRARIES = libcommon.a libsimple-pwquery.a -AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) libcommon_a_SOURCES = \ util.h i18n.h \ diff --git a/common/sysutils.c b/common/sysutils.c index 6eb40b125..4948af57f 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -117,7 +117,8 @@ get_session_marker( size_t *rlen ) } -#if 0 /* not yet needed */ +#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) { -- cgit v1.2.3 From e99475d59e214954ca76d07577a1c3e972d4aeac Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:28:52 +0000 Subject: * gpgv.c: Removed g10defs.h. * Makefile.am: Include cmacros.am for common flags. --- g10/ChangeLog | 12 ++++++++++++ g10/Makefile.am | 17 ++++++++--------- g10/g10.c | 2 +- g10/gpgv.c | 3 +-- g10/openfile.c | 2 +- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index cc4509433..d45fa74ad 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,15 @@ +2004-02-12 Werner Koch <wk@gnupg.org> + + * gpgv.c: Removed g10defs.h. + + * Makefile.am: Include cmacros.am for common flags. + +2004-02-11 Werner Koch <wk@gnupg.org> + + * openfile.c (try_make_homedir): Use GNUPG_DEFAULT_HOMEDIR. + * gpgv.c (main): Ditto. + * g10.c (main): Ditto. + 2004-01-19 Moritz Schulte <mo@g10code.com> * keygen.c (do_generate_keypair): Print member fname, instead of diff --git a/g10/Makefile.am b/g10/Makefile.am index 00a49df1e..fc33acf73 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -19,16 +19,15 @@ ## Process this file with automake to produce Makefile.in -localedir = $(datadir)/locale -INCLUDES = -I$(top_srcdir)/common -I$(top_srcdir)/include -I$(top_srcdir)/intl -DLOCALEDIR=\"$(localedir)\" @LIBGCRYPT_CFLAGS@ - EXTRA_DIST = options.skel -# it seems that we can't use this with automake 1.5 -#OMIT_DEPENDENCIES = zlib.h zconf.h -libexecdir = @libexecdir@/@PACKAGE@ -if ! HAVE_DOSISH_SYSTEM -AM_CFLAGS = -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" -endif + +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 diff --git a/g10/g10.c b/g10/g10.c index 77e6f6cf9..e3c621453 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1238,7 +1238,7 @@ main( int argc, char **argv ) set_homedir ( getenv("GNUPGHOME") ); #endif if( !*opt.homedir ) - set_homedir ( GNUPG_HOMEDIR ); + set_homedir ( GNUPG_DEFAULT_HOMEDIR ); /* check whether we have a config file on the commandline */ orig_argc = argc; diff --git a/g10/gpgv.c b/g10/gpgv.c index 596b09fcb..d020bda62 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -46,7 +46,6 @@ #include "ttyio.h" #include "i18n.h" #include "status.h" -#include "g10defs.h" enum cmd_and_opt_values { aNull = 0, @@ -163,7 +162,7 @@ main( int argc, char **argv ) opt.homedir = getenv("GNUPGHOME"); #endif if( !opt.homedir || !*opt.homedir ) { - opt.homedir = GNUPG_HOMEDIR; + opt.homedir = GNUPG_DEFAULT_HOMEDIR; } tty_no_terminal(1); tty_batchmode(1); diff --git a/g10/openfile.c b/g10/openfile.c index b36e0d8e0..7dbbf7d6a 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -360,7 +360,7 @@ copy_options_file( const char *destdir ) void try_make_homedir( const char *fname ) { - const char *defhome = GNUPG_HOMEDIR; + const char *defhome = GNUPG_DEFAULT_HOMEDIR; /* Create the directory only if the supplied directory name * is the same as the default one. This way we avoid to create -- cgit v1.2.3 From 70631cf0df8784eaa157dd5bf00abaebfe384031 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:29:00 +0000 Subject: Replaced INCLUDES by AM_CPPFLAGS. --- jnlib/ChangeLog | 4 ++++ jnlib/Makefile.am | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 9d5564c85..d6361153c 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2004-02-12 Werner Koch <wk@gnupg.org> + + * Makefile.am: Replaced INCLUDES by AM_CPPFLAGS. + 2004-01-05 Werner Koch <wk@gnupg.org> * argparse.c (strusage): Changed default copyright year to 2004. diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index ae1cf6be2..bad3c5a71 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 1999, 2000, 2001 Feee Software Soundation, Inc. +# Copyright (C) 1999, 2000, 2001, 2004 Feee Software Soundation, Inc. # # This file is part of GnuPG # @@ -20,8 +20,10 @@ EXTRA_DIST = README -# We need libgcrypt becuase libjnlib-confilig includes gcrypt.h -INCLUDES = -I$(top_srcdir)/intl $(LIBGCRYPT_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/intl + +# We need libgcrypt because libjnlib-config includes gcrypt.h +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) noinst_LIBRARIES = libjnlib.a -- cgit v1.2.3 From 82b26c59659a47250a1a70348321efec265b7c70 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:29:14 +0000 Subject: Include cmacros.am for common flags. --- scd/ChangeLog | 4 ++++ scd/Makefile.am | 10 ++++++---- scd/ccid-driver.c | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index f6fc67423..002ad1efc 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-02-12 Werner Koch <wk@gnupg.org> + + * Makefile.am: Include cmacros.am for common flags. + 2004-01-29 Werner Koch <wk@gnupg.org> * command.c (reset_notify): Release the application context and diff --git a/scd/Makefile.am b/scd/Makefile.am index c8bf3d0de..89ebf4e05 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -18,14 +18,16 @@ ## Process this file with automake to produce Makefile.in -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" - bin_PROGRAMS = scdaemon sc-investigate sc-copykeys -AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ +AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common + +include $(top_srcdir)/am/cmacros.am + +AM_CFLAGS = $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) + card_apps = app-openpgp.c app-nks.c app-dinsig.c scdaemon_SOURCES = \ diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index f910722eb..ca5620176 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -98,7 +98,7 @@ # include "scdaemon.h" # endif -/* Disable all debgging output for now. */ +/* Disable all debugging output for now. */ #undef DBG_CARD_IO #define DBG_CARD_IO 0 -- cgit v1.2.3 From 76b14453902fd27def7d588d1516426caa9a75fb Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:29:42 +0000 Subject: * Makefile.am (AM_CPPFLAGS): Pass directory constants via -D; this will allow to override directory names at make time. --- sm/ChangeLog | 5 +++++ sm/Makefile.am | 11 ++++++----- sm/gpgsm.c | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 7c4483335..77807d065 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-02-11 Werner Koch <wk@gnupg.org> + + * Makefile.am (AM_CPPFLAGS): Pass directory constants via -D; this + will allow to override directory names at make time. + 2004-02-02 Werner Koch <wk@gnupg.org> * import.c (check_and_store): Import certificates even with diff --git a/sm/Makefile.am b/sm/Makefile.am index 6345573e5..1ac7cbe84 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -18,13 +18,14 @@ ## Process this file with automake to produce Makefile.in -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" bin_PROGRAMS = gpgsm -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \ - $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) + +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl +include $(top_srcdir)/am/cmacros.am + gpgsm_SOURCES = \ gpgsm.c gpgsm.h \ @@ -52,4 +53,4 @@ gpgsm_SOURCES = \ gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(KSBA_LIBS) -lgpg-error \ - @INTLLIBS@ + $(INTLLIBS) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index c8d76afa9..d1da02c59 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1480,7 +1480,7 @@ open_fwrite (const char *filename) static void run_protect_tool (int argc, char **argv) { - char *pgm = GNUPG_PROTECT_TOOL; + char *pgm = GNUPG_DEFAULT_PROTECT_TOOL; char **av; int i; -- cgit v1.2.3 From 270576cf172de5defe854bb74fe4d51f01ae8e7d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 09:30:37 +0000 Subject: More stuff for testing --- tests/extrasamples/README | 5 +++++ tests/extrasamples/dod-test9.p12 | Bin 0 -> 3934 bytes tests/samplekeys/README | 12 ++++++++++++ tests/samplekeys/cryptlib-key.p12 | Bin 0 -> 1559 bytes tests/samplekeys/opensc-test.p12 | Bin 0 -> 2397 bytes tests/samplekeys/ov-server.p12 | Bin 0 -> 2133 bytes tests/samplekeys/ov-user.p12 | Bin 0 -> 2141 bytes 7 files changed, 17 insertions(+) create mode 100644 tests/extrasamples/README create mode 100644 tests/extrasamples/dod-test9.p12 create mode 100644 tests/samplekeys/README create mode 100644 tests/samplekeys/cryptlib-key.p12 create mode 100644 tests/samplekeys/opensc-test.p12 create mode 100644 tests/samplekeys/ov-server.p12 create mode 100644 tests/samplekeys/ov-user.p12 diff --git a/tests/extrasamples/README b/tests/extrasamples/README new file mode 100644 index 000000000..3102eac15 --- /dev/null +++ b/tests/extrasamples/README @@ -0,0 +1,5 @@ +Extra test data where it is not clear whether we may distribute them. This +we only keep them in the CVS. + +dod-test9.p12 A file from the DoD X.509 tests suite, September 2001. + Passphrase is "password". diff --git a/tests/extrasamples/dod-test9.p12 b/tests/extrasamples/dod-test9.p12 new file mode 100644 index 000000000..a109b1aa9 Binary files /dev/null and b/tests/extrasamples/dod-test9.p12 differ diff --git a/tests/samplekeys/README b/tests/samplekeys/README new file mode 100644 index 000000000..d2ff84c72 --- /dev/null +++ b/tests/samplekeys/README @@ -0,0 +1,12 @@ +This is a collection of keys we use with the regression tests. + +opensc-tests.p12 PKCS#12 key and certificates taken from OpenSC. + Passphrase is "password" + +ov-user.p12 Private tests keys from www.openvalidation.org. +ov-server.p12 Passphrase for both is "start" + + + + + diff --git a/tests/samplekeys/cryptlib-key.p12 b/tests/samplekeys/cryptlib-key.p12 new file mode 100644 index 000000000..5c23e95a7 Binary files /dev/null and b/tests/samplekeys/cryptlib-key.p12 differ diff --git a/tests/samplekeys/opensc-test.p12 b/tests/samplekeys/opensc-test.p12 new file mode 100644 index 000000000..990b1279a Binary files /dev/null and b/tests/samplekeys/opensc-test.p12 differ diff --git a/tests/samplekeys/ov-server.p12 b/tests/samplekeys/ov-server.p12 new file mode 100644 index 000000000..52f2d558d Binary files /dev/null and b/tests/samplekeys/ov-server.p12 differ diff --git a/tests/samplekeys/ov-user.p12 b/tests/samplekeys/ov-user.p12 new file mode 100644 index 000000000..bb53a3d1a Binary files /dev/null and b/tests/samplekeys/ov-user.p12 differ -- cgit v1.2.3 From 7080c6553fbebbf058999c5f5a50960257a693a4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 10:02:22 +0000 Subject: * watchgnupg.c (main): Implement option "--". (print_version): New. * Makefile.am: Include cmacros.am for common flags. --- tools/ChangeLog | 7 +++++++ tools/Makefile.am | 9 ++++---- tools/watchgnupg.c | 61 ++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index e764d7b6a..bd99271d6 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2004-02-12 Werner Koch <wk@gnupg.org> + + * watchgnupg.c (main): Implement option "--". + (print_version): New. + + * Makefile.am: Include cmacros.am for common flags. + 2004-02-03 Werner Koch <wk@gnupg.org> * addgnupghome: Try to use getent, so that it also works for NIS diff --git a/tools/Makefile.am b/tools/Makefile.am index 32dd709fa..71a77356f 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -21,18 +21,19 @@ EXTRA_DIST = Manifest watchgnupg.c \ rfc822parse.c rfc822parse.h gpgparsemail.c \ addgnupghome -localedir = $(datadir)/locale -INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" +AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common +include $(top_srcdir)/am/cmacros.am # Note, that we require GPG_ERROR_CFLAGS only because some share header files # require that file. It is not actually used in gpgconf. -AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl @GPG_ERROR_CFLAGS@ +AM_CFLAGS = @GPG_ERROR_CFLAGS@ sbin_SCRIPTS = addgnupghome -bin_PROGRAMS = gpgconf +bin_PROGRAMS = gpgconf watchgnupg gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @INTLLIBS@ +watchgnupg_SOURCES = watchgnupg.c diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index dfb11f2de..7f79f2f18 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -1,5 +1,5 @@ /* watchgnupg.c - Socket server for GnuPG logs - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -18,6 +18,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <stdio.h> #include <stdlib.h> #include <stddef.h> @@ -33,8 +36,16 @@ #define PGM "watchgnupg" +/* Allow for a standalone build. */ +#ifdef VERSION +#define MYVERSION_LINE PGM " (GnuPG) " VERSION +#define BUGREPORT_LINE "\nReport bugs to <bug-gnupg@gnu.org>.\n" +#else +#define MYVERSION_LINE PGM +#define BUGREPORT_LINE "" +#endif + static int verbose; -static int debug; static void @@ -169,6 +180,29 @@ print_line (client_t c, const char *line) } +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2004 Free Software Foundation, Inc.\n" + "This program comes with ABSOLUTELY NO WARRANTY.\n" + "This is free software, and you are welcome to redistribute it\n" + "under certain conditions. See the file COPYING for details.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] SOCKETNAME\n" + "Open the local socket SOCKETNAME and display log messages\n" + "\n" + " --force delete an already existing socket file\n" + " --verbose enable extra informational output\n" + " --version print version of the program and exit\n" + " --help display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} int main (int argc, char **argv) @@ -189,22 +223,18 @@ main (int argc, char **argv) while (argc && last_argc != argc ) { last_argc = argc; - if (!strcmp (*argv, "--help")) + if (!strcmp (*argv, "--")) { - puts ( - "usage: " PGM " [options] socketname\n" - "\n" - " Options are --verbose, --debug and --force"); - exit (0); - } - if (!strcmp (*argv, "--verbose")) - { - verbose = 1; argc--; argv++; + break; } - else if (!strcmp (*argv, "--debug")) + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--verbose")) { - verbose = debug = 1; + verbose = 1; argc--; argv++; } else if (!strcmp (*argv, "--force")) @@ -216,7 +246,8 @@ main (int argc, char **argv) if (argc != 1) { - die ("usage: " PGM " socketname\n"); + fprintf (stderr, "usage: " PGM " socketname\n"); + exit (1); } -- cgit v1.2.3 From 8197b20e24bbb5b006a1f1e0c49dac8c5cd6d5ad Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 12 Feb 2004 10:05:47 +0000 Subject: Removed cruft from debugging. --- ChangeLog | 2 ++ autogen.sh | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 30916e04e..764573e50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 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> diff --git a/autogen.sh b/autogen.sh index 4fbcdca6f..ad335b972 100755 --- a/autogen.sh +++ b/autogen.sh @@ -148,7 +148,6 @@ EOF exit 1 fi -exit 0 echo "Running aclocal -I m4 ..." $ACLOCAL -I m4 -- cgit v1.2.3 From b01d9899256f36b725212b68b7fcc47c9557e74e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 Feb 2004 12:37:54 +0000 Subject: (main): New options --no-fail-on-exist, --homedir. (store_private_key): Use them here. --- agent/ChangeLog | 7 +++ agent/divert-scd.c | 2 +- agent/minip12.c | 7 --- agent/protect-tool.c | 128 ++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 99 insertions(+), 45 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index d9e4049ff..b3c5d73d6 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,12 @@ +2004-02-13 Werner Koch <wk@gnupg.org> + + * protect-tool.c (main): New options --no-fail-on-exist, --homedir. + (store_private_key): Use them here. + 2004-02-12 Werner Koch <wk@gnupg.org> + * protect-tool.c (read_file, main): Allow reading from stdin. + * Makefile.am: Include cmacros.am for common flags. (libexec_PROGRAMS): Put gpg-protect-tool there. diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 455d23068..9c512bdcf 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -108,7 +108,7 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) if (!rc) { - /* We better reset the SCD now. This is kludge requred + /* We better reset the SCD now. This is kludge required because the scdaemon is currently not always able to detect the presence of a card. With a fully working scdaemon this would not be required; i.e. the pkcs#15 diff --git a/agent/minip12.c b/agent/minip12.c index 1e86bc251..e065a6d20 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -27,13 +27,6 @@ #include <assert.h> #include <gcrypt.h> -#ifdef __GCC__ -#warning Remove this kludge and set the libgcrypt required version higher. -#endif -#ifndef GCRY_CIPHER_RFC2268_40 -#define GCRY_CIPHER_RFC2268_40 307 -#endif - #ifdef TEST #include <sys/stat.h> #include <unistd.h> diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 2d1df4d7c..0bb344424 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -54,6 +54,8 @@ enum cmd_and_opt_values oP12Export, oStore, oForce, + oNoFailOnExist, + oHomedir, aTest }; @@ -68,9 +70,11 @@ struct rsa_secret_key_s }; +static char *opt_homedir; static int opt_armor; static int opt_store; static int opt_force; +static int opt_no_fail_on_exist; static const char *passphrase; static const char *get_passphrase (void); @@ -95,6 +99,8 @@ static ARGPARSE_OPTS opts[] = { { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"}, { oStore, "store", 0, "store the created key in the appropriate place"}, { oForce, "force", 0, "force overwriting"}, + { oNoFailOnExist, "no-fail-on-exist", 0, "@" }, + { oHomedir, "homedir", 2, "@" }, {0} }; @@ -231,34 +237,67 @@ static char * read_file (const char *fname, size_t *r_length) { FILE *fp; - struct stat st; char *buf; size_t buflen; - fp = fopen (fname, "rb"); - if (!fp) + if (!strcmp (fname, "-")) { - log_error ("can't open `%s': %s\n", fname, strerror (errno)); - return NULL; + size_t nread, bufsize = 0; + + fp = stdin; + buf = NULL; + buflen = 0; +#define NCHUNK 8192 + do + { + bufsize += NCHUNK; + if (!buf) + buf = xmalloc (bufsize); + else + buf = xrealloc (buf, bufsize); + + nread = fread (buf+buflen, 1, NCHUNK, fp); + if (nread < NCHUNK && ferror (fp)) + { + log_error ("error reading `[stdin]': %s\n", strerror (errno)); + xfree (buf); + return NULL; + } + buflen += nread; + } + while (nread == NCHUNK); +#undef NCHUNK + } - - if (fstat (fileno(fp), &st)) + else { - log_error ("can't stat `%s': %s\n", fname, strerror (errno)); - fclose (fp); - return NULL; - } + struct stat st; - buflen = st.st_size; - buf = xmalloc (buflen+1); - if (fread (buf, buflen, 1, fp) != 1) - { - log_error ("error reading `%s': %s\n", fname, strerror (errno)); + fp = fopen (fname, "rb"); + if (!fp) + { + log_error ("can't open `%s': %s\n", fname, strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + log_error ("can't stat `%s': %s\n", fname, strerror (errno)); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xmalloc (buflen+1); + if (fread (buf, buflen, 1, fp) != 1) + { + log_error ("error reading `%s': %s\n", fname, strerror (errno)); + fclose (fp); + xfree (buf); + return NULL; + } fclose (fp); - xfree (buf); - return NULL; } - fclose (fp); *r_length = buflen; return buf; @@ -821,12 +860,14 @@ export_p12_file (const char *fname) xfree (key); } + int main (int argc, char **argv ) { ARGPARSE_ARGS pargs; int cmd = 0; + const char *fname; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -843,15 +884,26 @@ main (int argc, char **argv ) gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); +#ifdef __MINGW32__ + 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; + + pargs.argc = &argc; pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ + pargs.flags= 1; /* (do not remove the args) */ while (arg_parse (&pargs, opts) ) { switch (pargs.r_opt) { case oVerbose: opt.verbose++; break; case oArmor: opt_armor=1; break; + case oHomedir: opt_homedir = pargs.r.ret_str; break; case oProtect: cmd = oProtect; break; case oUnprotect: cmd = oUnprotect; break; @@ -864,6 +916,7 @@ main (int argc, char **argv ) case oPassphrase: passphrase = pargs.r.ret_str; break; case oStore: opt_store = 1; break; case oForce: opt_force = 1; break; + case oNoFailOnExist: opt_no_fail_on_exist = 1; break; default : pargs.err = 2; break; } @@ -871,25 +924,28 @@ main (int argc, char **argv ) if (log_get_errorcount(0)) exit(2); - if (argc != 1) + fname = "-"; + if (argc == 1) + fname = *argv; + else if (argc > 1) usage (1); if (cmd == oProtect) - read_and_protect (*argv); + read_and_protect (fname); else if (cmd == oUnprotect) - read_and_unprotect (*argv); + read_and_unprotect (fname); else if (cmd == oShadow) - read_and_shadow (*argv); + read_and_shadow (fname); else if (cmd == oShowShadowInfo) - show_shadow_info (*argv); + show_shadow_info (fname); else if (cmd == oShowKeygrip) - show_keygrip (*argv); + show_keygrip (fname); else if (cmd == oP12Import) - import_p12_file (*argv); + import_p12_file (fname); else if (cmd == oP12Export) - export_p12_file (*argv); + export_p12_file (fname); else - show_file (*argv); + show_file (fname); agent_exit (0); return 8; /*NOTREACHED*/ @@ -937,7 +993,6 @@ store_private_key (const unsigned char *grip, const void *buffer, size_t length, int force) { int i; - const char *homedir; char *fname; FILE *fp; char hexgrip[40+4+1]; @@ -946,20 +1001,19 @@ store_private_key (const unsigned char *grip, sprintf (hexgrip+2*i, "%02X", grip[i]); strcpy (hexgrip+40, ".key"); - homedir = getenv("GNUPGHOME"); - if (!homedir || !*homedir) - homedir = GNUPG_DEFAULT_HOMEDIR; - - fname = make_filename (homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); + fname = make_filename (opt_homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); if (force) fp = fopen (fname, "wb"); else { if (!access (fname, F_OK)) { - log_error ("secret key file `%s' already exists\n", fname); + if (opt_no_fail_on_exist) + log_info ("secret key file `%s' already exists\n", fname); + else + log_error ("secret key file `%s' already exists\n", fname); xfree (fname); - return -1; + return opt_no_fail_on_exist? 0 : -1; } fp = fopen (fname, "wbx"); /* FIXME: the x is a GNU extension - let configure check whether this actually -- cgit v1.2.3 From 8b49254b97ceacd1f7b22ac68475baf9fe2b72de Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 Feb 2004 12:39:49 +0000 Subject: Removed debugging cruft. --- agent/minip12.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/agent/minip12.c b/agent/minip12.c index e065a6d20..13b6aa3eb 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -708,12 +708,12 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, startoffset = 0; buffer = p = plain; - { - FILE *fp = fopen ("tmp-3des-plain.der", "wb"); - if (!fp || fwrite (p, n, 1, fp) != 1) - exit (2); - fclose (fp); - } +/* { */ +/* FILE *fp = fopen ("tmp-3des-plain.der", "wb"); */ +/* if (!fp || fwrite (p, n, 1, fp) != 1) */ +/* exit (2); */ +/* fclose (fp); */ +/* } */ where = "decrypted-text"; if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) @@ -1165,11 +1165,11 @@ p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length) for (;(plainlen % 8); plainlen++) *p++ = n; - { - FILE *fp = fopen("inner-out.der", "wb"); - fwrite (plain, 1, plainlen, fp); - fclose (fp); - } +/* { */ +/* FILE *fp = fopen("inner-out.der", "wb"); */ +/* fwrite (plain, 1, plainlen, fp); */ +/* fclose (fp); */ +/* } */ /* Encrypt it and prepend a lot of stupid things. */ -- cgit v1.2.3 From 1a159fd8e383f69ad73e83491c396b1395385563 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 Feb 2004 12:40:23 +0000 Subject: * encrypt.c (init_dek): Check for too weak algorithms. * import.c (parse_p12, popen_protect_tool): New. * base64.c (gpgsm_create_reader): New arg ALLOW_MULTI_PEM. Changed all callers. (base64_reader_cb): Handle it here. (gpgsm_reader_eof_seen): New. (base64_reader_cb): Set a flag for EOF. (simple_reader_cb): Ditto. --- sm/ChangeLog | 18 +++ sm/base64.c | 42 +++++- sm/decrypt.c | 2 +- sm/encrypt.c | 19 ++- sm/gpgsm.c | 15 ++- sm/gpgsm.h | 7 +- sm/import.c | 420 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- sm/verify.c | 2 +- 8 files changed, 457 insertions(+), 68 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 77807d065..2e78d1f41 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,21 @@ +2004-02-13 Werner Koch <wk@gnupg.org> + + * encrypt.c (init_dek): Check for too weak algorithms. + + * import.c (parse_p12, popen_protect_tool): New. + + * base64.c (gpgsm_create_reader): New arg ALLOW_MULTI_PEM. + Changed all callers. + (base64_reader_cb): Handle it here. + (gpgsm_reader_eof_seen): New. + (base64_reader_cb): Set a flag for EOF. + (simple_reader_cb): Ditto. + +2004-02-12 Werner Koch <wk@gnupg.org> + + * gpgsm.h, gpgsm.c: New option --protect-tool-program. + * gpgsm.c (run_protect_tool): Use it. + 2004-02-11 Werner Koch <wk@gnupg.org> * Makefile.am (AM_CPPFLAGS): Pass directory constants via -D; this diff --git a/sm/base64.c b/sm/base64.c index 11237dcc1..4cc6ffa27 100644 --- a/sm/base64.c +++ b/sm/base64.c @@ -48,9 +48,10 @@ struct reader_cb_parm_s { int have_lf; unsigned long line_counter; - int autodetect; /* try to detect the input encoding */ - int assume_pem; /* assume input encoding is PEM */ - int assume_base64; /* assume input is base64 encoded */ + int allow_multi_pem; /* Allow processing of multiple PEM objects. */ + int autodetect; /* Try to detect the input encoding. */ + int assume_pem; /* Assume input encoding is PEM. */ + int assume_base64; /* Assume input is base64 encoded. */ int identified; int is_pem; @@ -58,6 +59,8 @@ struct reader_cb_parm_s { int stop_seen; int might_be_smime; + int eof_seen; + struct { int idx; unsigned char val; @@ -171,6 +174,7 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) c = getc (parm->fp); if (c == EOF) { + parm->eof_seen = 1; if (ferror (parm->fp)) return -1; break; @@ -268,7 +272,22 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) { parm->identified = 0; parm->linelen = parm->readpos = 0; - /* let us return 0 */ + + /* If the caller want to read multiple PEM objects from one + file, we have to reset our internal state and return a + EOF immediately. The caller is the expected to use + ksba_reader_clear to clear the EOF condition and continue + to read. If we don't want to do that we just return 0 + bytes which will force the ksba_reader to skip until + EOF. */ + if (parm->allow_multi_pem) + { + parm->identified = 0; + parm->autodetect = 0; + parm->assume_pem = 1; + parm->stop_seen = 0; + return -1; /* Send EOF now. */ + } } else if (parm->stop_seen) { /* skip the rest of the line */ @@ -356,6 +375,7 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) c = getc (parm->fp); if (c == EOF) { + parm->eof_seen = 1; if ( ferror (parm->fp) ) return -1; if (n) @@ -494,10 +514,13 @@ base64_finish_write (struct writer_cb_parm_s *parm) The function returns a Base64Context object which must be passed to the gpgme_destroy_reader function. The created KsbaReader object is also returned, but the caller must not call the - ksba_reader_release function on. */ + ksba_reader_release function on. If ALLOW_MULTI_PEM is true, the + reader expects that the caller uses ksba_reader_clear after EOF + until no more objects were found. */ int gpgsm_create_reader (Base64Context *ctx, - CTRL ctrl, FILE *fp, ksba_reader_t *r_reader) + CTRL ctrl, FILE *fp, int allow_multi_pem, + ksba_reader_t *r_reader) { int rc; ksba_reader_t r; @@ -506,6 +529,7 @@ gpgsm_create_reader (Base64Context *ctx, *ctx = xtrycalloc (1, sizeof **ctx); if (!*ctx) return OUT_OF_CORE (errno); + (*ctx)->u.rparm.allow_multi_pem = allow_multi_pem; rc = ksba_reader_new (&r); if (rc) @@ -546,6 +570,12 @@ gpgsm_create_reader (Base64Context *ctx, } +int +gpgsm_reader_eof_seen (Base64Context ctx) +{ + return ctx && ctx->u.rparm.eof_seen; +} + void gpgsm_destroy_reader (Base64Context ctx) { diff --git a/sm/decrypt.c b/sm/decrypt.c index c6eb8ab4b..427466a49 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -270,7 +270,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) goto leave; } - rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader); + rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, 0, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); diff --git a/sm/encrypt.c b/sm/encrypt.c index 8f2c26b45..8cc9a8828 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -1,5 +1,5 @@ /* encrypt.c - Encrypt a message - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -74,6 +74,20 @@ init_dek (DEK dek) log_error ("unsupported algorithm `%s'\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } + + /* Extra check for algorithms we considere to be to weak for + encryption, qlthough we suppor them fro decryption. Note that + there is another check below discriminating on the key length. */ + switch (dek->algo) + { + case GCRY_CIPHER_DES: + case GCRY_CIPHER_RFC2268_40: + log_error ("cipher algorithm `%s' not allowed: too weak\n", + gcry_cipher_algo_name (dek->algo)); + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + default: + break; + } dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); if (!dek->keylen || dek->keylen > sizeof (dek->key)) @@ -83,8 +97,9 @@ init_dek (DEK dek) if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) return gpg_error (GPG_ERR_BUG); + /* Make sure we don't use weak keys. */ if (dek->keylen < 100/8) - { /* make sure we don't use weak keys */ + { log_error ("key length of `%s' too small\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } diff --git a/sm/gpgsm.c b/sm/gpgsm.c index d1da02c59..fa3e1b203 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -98,6 +98,7 @@ enum cmd_and_opt_values { oLCmessages, oDirmngrProgram, + oProtectToolProgram, oFakedSystemTime, @@ -370,6 +371,7 @@ static ARGPARSE_OPTS opts[] = { { oLCctype, "lc-ctype", 2, "@" }, { oLCmessages, "lc-messages", 2, "@" }, { oDirmngrProgram, "dirmngr-program", 2 , "@" }, + { oProtectToolProgram, "protect-tool-program", 2 , "@" }, { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */ @@ -947,6 +949,9 @@ main ( int argc, char **argv) case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break; case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break; case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; + case oProtectToolProgram: + opt.protect_tool_program = pargs.r.ret_str; + break; case oFakedSystemTime: gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0); @@ -1480,14 +1485,19 @@ open_fwrite (const char *filename) static void run_protect_tool (int argc, char **argv) { - char *pgm = GNUPG_DEFAULT_PROTECT_TOOL; + const char *pgm; char **av; int i; + if (!opt.protect_tool_program || !*opt.protect_tool_program) + pgm = GNUPG_DEFAULT_PROTECT_TOOL; + else + pgm = opt.protect_tool_program; + av = xcalloc (argc+2, sizeof *av); av[0] = strrchr (pgm, '/'); if (!av[0]) - av[0] = pgm; + av[0] = xstrdup (pgm); for (i=1; argc; i++, argc--, argv++) av[i] = *argv; av[i] = NULL; @@ -1495,4 +1505,3 @@ run_protect_tool (int argc, char **argv) log_error ("error executing `%s': %s\n", pgm, strerror (errno)); gpgsm_exit (2); } - diff --git a/sm/gpgsm.h b/sm/gpgsm.h index e8cdd93df..2132c564e 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -1,5 +1,5 @@ /* gpgsm.h - Global definitions for GpgSM - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -54,6 +54,7 @@ struct { char *lc_messages; const char *dirmngr_program; + const char *protect_tool_program; char *outfile; /* name of output file */ int with_key_data;/* include raw key in the column delimted output */ @@ -176,7 +177,9 @@ char *gpgsm_get_certid (ksba_cert_t cert); /*-- base64.c --*/ int gpgsm_create_reader (Base64Context *ctx, - ctrl_t ctrl, FILE *fp, ksba_reader_t *r_reader); + ctrl_t ctrl, FILE *fp, int allow_multi_pem, + ksba_reader_t *r_reader); +int gpgsm_reader_eof_seen (Base64Context ctx); void gpgsm_destroy_reader (Base64Context ctx); int gpgsm_create_writer (Base64Context *ctx, ctrl_t ctrl, FILE *fp, ksba_writer_t *r_writer); diff --git a/sm/import.c b/sm/import.c index 132b7403e..b11cd75b6 100644 --- a/sm/import.c +++ b/sm/import.c @@ -1,5 +1,5 @@ /* import.c - Import certificates - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -26,6 +26,9 @@ #include <unistd.h> #include <time.h> #include <assert.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/wait.h> #include "gpgsm.h" #include <gcrypt.h> @@ -34,6 +37,13 @@ #include "keydb.h" #include "i18n.h" +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + + struct stats_s { unsigned long count; unsigned long imported; @@ -42,6 +52,9 @@ struct stats_s { }; +static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp); + + static void print_imported_status (CTRL ctrl, ksba_cert_t cert) @@ -208,6 +221,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) ksba_cms_t cms = NULL; FILE *fp = NULL; ksba_content_type_t ct; + int any = 0; fp = fdopen ( dup (in_fd), "rb"); if (!fp) @@ -217,75 +231,138 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) goto leave; } - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); + rc = gpgsm_create_reader (&b64reader, ctrl, fp, 1, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); goto leave; } - - ct = ksba_cms_identify (reader); - if (ct == KSBA_CT_SIGNED_DATA) - { /* This is probably a signed-only message - import the certs */ - ksba_stop_reason_t stopreason; - int i; - - rc = ksba_cms_new (&cms); - if (rc) - goto leave; - - rc = ksba_cms_set_reader_writer (cms, reader, NULL); - if (rc) - { - log_error ("ksba_cms_set_reader_writer failed: %s\n", - gpg_strerror (rc)); - goto leave; - } - - - do - { - rc = ksba_cms_parse (cms, &stopreason); + + + /* We need to loop here to handle multiple PEM objects in one + file. */ + do + { + ksba_cms_release (cms); cms = NULL; + ksba_cert_release (cert); cert = NULL; + + ct = ksba_cms_identify (reader); + if (ct == KSBA_CT_SIGNED_DATA) + { /* This is probably a signed-only message - import the certs */ + ksba_stop_reason_t stopreason; + int i; + + rc = ksba_cms_new (&cms); + if (rc) + goto leave; + + rc = ksba_cms_set_reader_writer (cms, reader, NULL); if (rc) { - log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); + log_error ("ksba_cms_set_reader_writer failed: %s\n", + gpg_strerror (rc)); goto leave; } - if (stopreason == KSBA_SR_BEGIN_DATA) - log_info ("not a certs-only message\n"); - } - while (stopreason != KSBA_SR_READY); + do + { + rc = ksba_cms_parse (cms, &stopreason); + if (rc) + { + log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + if (stopreason == KSBA_SR_BEGIN_DATA) + log_info ("not a certs-only message\n"); + } + while (stopreason != KSBA_SR_READY); - for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) - { - check_and_store (ctrl, stats, cert, 0); - ksba_cert_release (cert); - cert = NULL; + for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) + { + check_and_store (ctrl, stats, cert, 0); + ksba_cert_release (cert); + cert = NULL; + } + if (!i) + log_error ("no certificate found\n"); + else + any = 1; } - if (!i) - log_error ("no certificate found\n"); - } - else if (ct == KSBA_CT_NONE) - { /* Failed to identify this message - assume a certificate */ + else if (ct == KSBA_CT_PKCS12) + { /* This seems to be a pkcs12 message. We use an external + tool to parse the message and to store the private keys. + We need to use a another reader here to parse the + certificate we included in the p12 file; then we continue + to look for other pkcs12 files (works only if they are in + PEM format. */ + FILE *certfp; + Base64Context b64p12rdr; + ksba_reader_t p12rdr; + + rc = parse_p12 (reader, &certfp); + if (!rc) + { + any = 1; + + rewind (certfp); + rc = gpgsm_create_reader (&b64p12rdr, ctrl, certfp, 1, &p12rdr); + if (rc) + { + log_error ("can't create reader: %s\n", gpg_strerror (rc)); + fclose (certfp); + goto leave; + } + + do + { + ksba_cert_release (cert); cert = NULL; + rc = ksba_cert_new (&cert); + if (!rc) + { + rc = ksba_cert_read_der (cert, p12rdr); + if (!rc) + check_and_store (ctrl, stats, cert, 0); + } + ksba_reader_clear (p12rdr, NULL, NULL); + } + while (!rc && !gpgsm_reader_eof_seen (b64p12rdr)); + + if (gpg_err_code (rc) == GPG_ERR_EOF) + rc = 0; + gpgsm_destroy_reader (b64p12rdr); + fclose (certfp); + if (rc) + goto leave; + } + } + else if (ct == KSBA_CT_NONE) + { /* Failed to identify this message - assume a certificate */ - rc = ksba_cert_new (&cert); - if (rc) - goto leave; + rc = ksba_cert_new (&cert); + if (rc) + goto leave; - rc = ksba_cert_read_der (cert, reader); - if (rc) - goto leave; + rc = ksba_cert_read_der (cert, reader); + if (rc) + goto leave; - check_and_store (ctrl, stats, cert, 0); - } - else - { - log_error ("can't extract certificates from input\n"); - rc = gpg_error (GPG_ERR_NO_DATA); + check_and_store (ctrl, stats, cert, 0); + any = 1; + } + else + { + log_error ("can't extract certificates from input\n"); + rc = gpg_error (GPG_ERR_NO_DATA); + } + + ksba_reader_clear (reader, NULL, NULL); } - + while (!gpgsm_reader_eof_seen (b64reader)); + leave: + if (any && gpg_err_code (rc) == GPG_ERR_EOF) + rc = 0; ksba_cms_release (cms); ksba_cert_release (cert); gpgsm_destroy_reader (b64reader); @@ -345,3 +422,240 @@ gpgsm_import_files (CTRL ctrl, int nfiles, char **files, } +/* Fork and exec the protecttool, connect the file descriptor of + INFILE to stdin, return a new stream in STATUSFILE, write the + output to OUTFILE and the pid of the process in PID. Returns 0 on + success or an error code. */ +static gpg_error_t +popen_protect_tool (const char *pgmname, + FILE *infile, FILE *outfile, FILE **statusfile, pid_t *pid) +{ + gpg_error_t err; + int fd, fdout, rp[2]; + int n, i; + + fflush (infile); + rewind (infile); + fd = fileno (infile); + fdout = fileno (outfile); + if (fd == -1 || fdout == -1) + log_fatal ("no file descriptor for temporary file: %s\n", + strerror (errno)); + + /* Now start the protect-tool. */ + if (pipe (rp) == -1) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating a pipe: %s\n"), strerror (errno)); + return err; + } + + *pid = fork (); + if (*pid == -1) + { + err = gpg_error_from_errno (errno); + log_error (_("error forking process: %s\n"), strerror (errno)); + close (rp[0]); + close (rp[1]); + return err; + } + + if (!*pid) + { /* Child. */ + const char *arg0; + + arg0 = strrchr (pgmname, '/'); + if (arg0) + arg0++; + else + arg0 = pgmname; + + /* Connect the infile to stdin. */ + if (fd != 0 && dup2 (fd, 0) == -1) + log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); + + /* Connect the outfile to stdout. */ + if (fdout != 1 && dup2 (fdout, 1) == -1) + log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); + + /* Connect stderr to our pipe. */ + if (rp[1] != 2 && dup2 (rp[1], 2) == -1) + log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); + + /* Close all other files. */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=3; i < n; i++) + close(i); + errno = 0; + + execlp (pgmname, arg0, + "--homedir", opt.homedir, + "--p12-import", + "--store", + "--no-fail-on-exist", + "--", + NULL); + /* No way to print anything, as we have closed all streams. */ + _exit (31); + } + + /* Parent. */ + close (rp[1]); + *statusfile = fdopen (rp[0], "r"); + if (!*statusfile) + { + err = gpg_error_from_errno (errno); + log_error ("can't fdopen pipe for reading: %s", strerror (errno)); + kill (*pid, SIGTERM); + return err; + } + + return 0; +} + + +/* Assume that the reader is at a pkcs#12 message and try to import + certificates from that stupid format. We will alos store secret + keys. All of the pkcs#12 parsing and key storing is handled by the + gpg-protect-tool, we merely have to take care of receiving the + certificates. On success RETFP returns a temporary file with + certificates. */ +static gpg_error_t +parse_p12 (ksba_reader_t reader, FILE **retfp) +{ + const char *pgmname; + gpg_error_t err = 0, child_err = 0; + int i, c, cont_line; + unsigned int pos; + FILE *tmpfp, *certfp = NULL, *fp = NULL; + char buffer[1024]; + size_t nread; + pid_t pid = -1; + + if (!opt.protect_tool_program || !*opt.protect_tool_program) + pgmname = GNUPG_DEFAULT_PROTECT_TOOL; + else + pgmname = opt.protect_tool_program; + + *retfp = NULL; + + /* To avoid an extra feeder process or doing selects and because + gpg-protect-tool will anyway parse the entire pkcs#12 message in + memory, we simply use tempfiles here and pass them to + the gpg-protect-tool. */ + tmpfp = tmpfile (); + if (!tmpfp) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating temporary file: %s\n"), strerror (errno)); + goto cleanup; + } + while (!(err = ksba_reader_read (reader, buffer, sizeof buffer, &nread))) + { + if (fwrite (buffer, nread, 1, tmpfp) != 1) + { + err = gpg_error_from_errno (errno); + log_error (_("error writing to temporary file: %s\n"), + strerror (errno)); + goto cleanup; + } + } + if (gpg_err_code (err) == GPG_ERR_EOF) + err = 0; + if (err) + { + log_error (_("error reading input: %s\n"), gpg_strerror (err)); + goto cleanup; + } + + certfp = tmpfile (); + if (!certfp) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating temporary file: %s\n"), strerror (errno)); + goto cleanup; + } + + err = popen_protect_tool (pgmname, tmpfp, certfp, &fp, &pid); + if (err) + { + pid = -1; + goto cleanup; + } + fclose (tmpfp); + tmpfp = NULL; + + /* Read stderr of the protect tool. */ + pos = 0; + cont_line = 0; + while ((c=getc (fp)) != EOF) + { + /* fixme: We could here grep for status information of the + protect tool to figure out better error codes for + CHILD_ERR. */ + buffer[pos++] = c; + if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n') + { + buffer[pos - (c == '\n')] = 0; + if (cont_line) + log_printf ("%s", buffer); + else + log_info ("%s", buffer); + pos = 0; + cont_line = (c != '\n'); + } + } + + if (pos) + { + buffer[pos] = 0; + if (cont_line) + log_printf ("%s\n", buffer); + else + log_info ("%s\n", buffer); + } + + /* If we found no error in the output of the cild, setup a suitable + error code, which will later be reset if the exit status of the + child is 0. */ + if (!child_err) + child_err = gpg_error (GPG_ERR_DECRYPT_FAILED); + + + cleanup: + if (tmpfp) + fclose (tmpfp); + if (fp) + fclose (fp); + if (pid != -1) + { + int status; + + while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) + ; + if (i == -1) + log_error (_("waiting for protect-tools to terminate failed: %s\n"), + strerror (errno)); + else if (WIFEXITED (status) && WEXITSTATUS (status) == 31) + log_error (_("error running `%s': probably not installed\n"), pgmname); + else if (WIFEXITED (status) && WEXITSTATUS (status)) + log_error (_("error running `%s': exit status %d\n"), pgmname, + WEXITSTATUS (status)); + else if (!WIFEXITED (status)) + log_error (_("error running `%s': terminated\n"), pgmname); + else + child_err = 0; + } + if (!err) + err = child_err; + if (err) + { + if (certfp) + fclose (certfp); + } + else + *retfp = certfp; + return err; +} diff --git a/sm/verify.c b/sm/verify.c index a10aff92c..2a95c81e7 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -118,7 +118,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) goto leave; } - rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader); + rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); -- cgit v1.2.3 From e98b7a9b21bcc33a35a0e17df722a8773fc670aa Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 Feb 2004 12:40:54 +0000 Subject: Require libksba 0.9.4 and libgcrypt 1.1.92. --- ChangeLog | 4 ++++ NEWS | 4 ++++ README | 16 ++++++---------- TODO | 3 +-- configure.ac | 4 ++-- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 764573e50..10d115c75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/NEWS b/NEWS index 82f7e575e..41edd66af 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ Noteworthy changes in version 1.9.5 Cleaned up the build system to better comply with the coding standards. + * The --import command is now able to autodetect pkcs#12 files and + import secret and private keys from this file format. + + Noteworthy changes in version 1.9.4 (2004-01-30) ------------------------------------------------ diff --git a/README b/README index 3eb745da7..5b4a69027 100644 --- a/README +++ b/README @@ -452,16 +452,12 @@ 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. Note, that this does only import the private key and not any -certificates available in that file. +file. - gpgsm --call-protect-tool --p12-import --store foo.p12 + gpgsm --import foo.p12 + +This require that the gpg-agent is running. -This require that the gpg-agent is running, alternative you may give -the passphrase on the commandline using the option "-P <passphrase>" - -however this is in general not a good idea. If that key already -exists, the protect-tool refuses to store it unless you use the option -"--force". HOW TO EXPORT A PRIVATE KEY =========================== @@ -474,13 +470,13 @@ format. However the certificate is not stored and there is no MAC applied. SMARTCARD INTRO =============== -GPG, the OpenPGP implementation supports the OpenPGP smartcard +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) implementation supports two kinds of +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 diff --git a/TODO b/TODO index b45d74737..7f06e546b 100644 --- a/TODO +++ b/TODO @@ -64,8 +64,7 @@ might want to have an agent context for each service request Remove the agent_reset_scd kludge. * agent/protect-tool.c -** Export and import certificates along with the secret key. -** Make it more comfortable; i.e. copy files to the correct place. +** Export certificates along with the secret key. ** BUG? --p12-export seems to work only with unprotected keys * Move pkcs-1 encoding into libgcrypt. diff --git a/configure.ac b/configure.ac index 6b8c1994d..1faf753c0 100644 --- a/configure.ac +++ b/configure.ac @@ -30,9 +30,9 @@ AC_INIT(gnupg, 1.9.5-cvs, gnupg-devel@gnupg.org) # sufficient. development_version=yes NEED_GPG_ERROR_VERSION=0.6 -NEED_LIBGCRYPT_VERSION=1.1.91 +NEED_LIBGCRYPT_VERSION=1.1.92 NEED_LIBASSUAN_VERSION=0.6.3 -NEED_KSBA_VERSION=0.9.3 +NEED_KSBA_VERSION=0.9.4 NEED_OPENSC_VERSION=0.8.0 -- cgit v1.2.3 From cbff0b05e54d7aa022c88e76dddd8d5106cc3536 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 Feb 2004 17:06:34 +0000 Subject: * command.c (cmd_setkeydesc): New. (register_commands): Add command SETKEYDESC. (cmd_pksign, cmd_pkdecrypt): Use the key description. (reset_notify): Reset the description. * findkey.c (unprotect): Add arg DESC_TEXT. (agent_key_from_file): Ditto. * pksign.c (agent_pksign): Ditto. * pkdecrypt.c (agent_pkdecrypt): Ditto. Made CIPHERTEXT an unsigned char*. --- NEWS | 7 +++- agent/ChangeLog | 10 +++++ agent/agent.h | 30 ++++++++------ agent/command.c | 114 ++++++++++++++++++++++++++++++++++++++++-------------- agent/findkey.c | 16 ++++---- agent/pkdecrypt.c | 6 ++- agent/pksign.c | 4 +- 7 files changed, 134 insertions(+), 53 deletions(-) diff --git a/NEWS b/NEWS index 41edd66af..07216f555 100644 --- a/NEWS +++ b/NEWS @@ -5,8 +5,11 @@ Noteworthy changes in version 1.9.5 Cleaned up the build system to better comply with the coding standards. - * The --import command is now able to autodetect pkcs#12 files and - import secret and private keys from this file format. + * [gpgsm] The --import command is now able to autodetect pkcs#12 + files and import secret and private keys from this file format. + + * [gpgsm] The pinentry will no present a description of the key for + whom the passphrase is requests. Noteworthy changes in version 1.9.4 (2004-01-30) diff --git a/agent/ChangeLog b/agent/ChangeLog index b3c5d73d6..f064bc17c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,15 @@ 2004-02-13 Werner Koch <wk@gnupg.org> + * command.c (cmd_setkeydesc): New. + (register_commands): Add command SETKEYDESC. + (cmd_pksign, cmd_pkdecrypt): Use the key description. + (reset_notify): Reset the description. + * findkey.c (unprotect): Add arg DESC_TEXT. + (agent_key_from_file): Ditto. + * pksign.c (agent_pksign): Ditto. + * pkdecrypt.c (agent_pkdecrypt): Ditto. Made CIPHERTEXT an + unsigned char*. + * protect-tool.c (main): New options --no-fail-on-exist, --homedir. (store_private_key): Use them here. diff --git a/agent/agent.h b/agent/agent.h index b70a4ae2d..a849e873f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -132,18 +132,20 @@ void start_command_handler (int, int); /*-- findkey.c --*/ int agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); -gpg_error_t agent_key_from_file (CTRL ctrl, const unsigned char *grip, +gpg_error_t agent_key_from_file (ctrl_t ctrl, + const char *desc_text, + const unsigned char *grip, unsigned char **shadow_info, int ignore_cache, gcry_sexp_t *result); int agent_key_available (const unsigned char *grip); /*-- query.c --*/ -int agent_askpin (CTRL ctrl, +int agent_askpin (ctrl_t ctrl, const char *desc_text, struct pin_entry_info_s *pininfo); -int agent_get_passphrase (CTRL ctrl, char **retpass, +int agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *desc, const char *prompt, const char *errtext); -int agent_get_confirmation (CTRL ctrl, const char *desc, const char *ok, +int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok, const char *cancel); /*-- cache.c --*/ @@ -154,16 +156,18 @@ void agent_unlock_cache_entry (void **cache_id); /*-- pksign.c --*/ -int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache); +int agent_pksign (ctrl_t ctrl, const char *desc_text, + FILE *outfp, int ignore_cache); /*-- pkdecrypt.c --*/ -int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, +int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, + const unsigned char *ciphertext, size_t ciphertextlen, FILE *outfp); /*-- genkey.c --*/ -int agent_genkey (CTRL ctrl, +int agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparmlen, FILE *outfp); -int agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey); +int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey); /*-- protect.c --*/ int agent_protect (const unsigned char *plainkey, const char *passphrase, @@ -181,18 +185,20 @@ int agent_get_shadow_info (const unsigned char *shadowkey, /*-- trustlist.c --*/ int agent_istrusted (const char *fpr); int agent_listtrusted (void *assuan_context); -int agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag); +int agent_marktrusted (ctrl_t ctrl, const char *name, + const char *fpr, int flag); /*-- divert-scd.c --*/ -int divert_pksign (CTRL ctrl, +int divert_pksign (ctrl_t ctrl, const unsigned char *digest, size_t digestlen, int algo, const unsigned char *shadow_info, unsigned char **r_sig); -int divert_pkdecrypt (CTRL ctrl, +int divert_pkdecrypt (ctrl_t ctrl, const unsigned char *cipher, const unsigned char *shadow_info, char **r_buf, size_t *r_len); -int divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context); +int divert_generic_cmd (ctrl_t ctrl, + const char *cmdline, void *assuan_context); /*-- call-scd.c --*/ diff --git a/agent/command.c b/agent/command.c index aec48e194..2fa182f63 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1,5 +1,5 @@ /* command.c - gpg-agent command handler - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -50,6 +50,8 @@ struct server_local_s { ASSUAN_CONTEXT assuan_ctx; int message_fd; int use_cache_for_signing; + char *keydesc; /* Allocated description fro the next key + operation. */ }; @@ -59,11 +61,14 @@ struct server_local_s { static void reset_notify (ASSUAN_CONTEXT ctx) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); memset (ctrl->keygrip, 0, 20); ctrl->have_keygrip = 0; ctrl->digest.valuelen = 0; + + xfree (ctrl->server_local->keydesc); + ctrl->server_local->keydesc = NULL; } @@ -78,6 +83,18 @@ has_option (const char *line, const char *name) return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); } +/* Replace all '+' by a blank. */ +static void +plus_to_blank (char *s) +{ + for (; *s; s++) + { + if (*s == '+') + *s = ' '; + } +} + + /* Parse a hex string. Return an Assuan error code or 0 on success and the length of the parsed string in LEN. */ static int @@ -179,7 +196,7 @@ cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line) static int cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc, n, i; char *p; char fpr[41]; @@ -245,7 +262,7 @@ static int cmd_sigkey (ASSUAN_CONTEXT ctx, char *line) { int rc; - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); rc = parse_keygrip (ctx, line, ctrl->keygrip); if (rc) @@ -255,6 +272,50 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line) } +/* SETKEYDESC plus_percent_escaped_string: + + Set a description to be used for the next PKSIGN or PKDECRYPT + operation if this operation requires the entry of a passphrase. If + this command is not used a default text will be used. Note, that + this description implictly selects the label used for the entry + box; if the string contains the string PIN (which in general will + not be translated), "PIN" is used, other wiese the translation of + 'passphrase" is used. The description string should not contain + blanks unless they are percent or '+' escaped. + + The descrition is only valid for the next PKSIGN or PKDECRYPT + operation. +*/ +static int +cmd_setkeydesc (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + char *desc, *p; + + for (p=line; *p == ' '; p++) + ; + desc = p; + p = strchr (desc, ' '); + if (p) + *p = 0; /* We ignore any garbage; we might late use it for other args. */ + + if (!desc || !*desc) + return set_error (Parameter_Error, "no description given"); + + /* Note, that we only need to replace the + characters and should + leave the other escaping in place because the escaped string is + send verbatim to the pinentry which does the unescaping (but not + the + replacing) */ + plus_to_blank (desc); + + xfree (ctrl->server_local->keydesc); + ctrl->server_local->keydesc = xtrystrdup (desc); + if (!ctrl->server_local->keydesc) + return map_to_assuan_status (gpg_error_from_errno (errno)); + return 0; +} + + /* SETHASH <algonumber> <hexstring> The client can use this command to tell the server about the data @@ -265,7 +326,7 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line) int rc; size_t n; char *p; - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); unsigned char *buf; char *endp; int algo; @@ -307,16 +368,19 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) { int rc; int ignore_cache = 0; - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); if (opt.ignore_cache_for_signing) ignore_cache = 1; else if (!ctrl->server_local->use_cache_for_signing) ignore_cache = 1; - rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache); + rc = agent_pksign (ctrl, ctrl->server_local->keydesc, + assuan_get_data_fp (ctx), ignore_cache); if (rc) log_error ("command pksign failed: %s\n", gpg_strerror (rc)); + xfree (ctrl->server_local->keydesc); + ctrl->server_local->keydesc = NULL; return map_to_assuan_status (rc); } @@ -328,7 +392,7 @@ static int cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) { int rc; - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); unsigned char *value; size_t valuelen; @@ -338,10 +402,13 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) if (rc) return rc; - rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx)); + rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc, + value, valuelen, assuan_get_data_fp (ctx)); xfree (value); if (rc) log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc)); + xfree (ctrl->server_local->keydesc); + ctrl->server_local->keydesc = NULL; return map_to_assuan_status (rc); } @@ -363,7 +430,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) static int cmd_genkey (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char *value; size_t valuelen; @@ -381,16 +448,6 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) } -static void -plus_to_blank (char *s) -{ - for (; *s; s++) - { - if (*s == '+') - *s = ' '; - } -} - /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>] This function is usually used to ask for a passphrase to be used @@ -405,7 +462,7 @@ plus_to_blank (char *s) static int cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; const char *pw; char *response; @@ -530,15 +587,15 @@ cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line) command uses a syntax which helps clients to use the agent with minimum effort. The agent either returns with an error or with a OK. Note, that the length of DESCRIPTION is implicitly limited by - the maximum length of a command. DESCRIPTION should not conmtain - ant spaces, those must be encoded either percent escaped or simply + the maximum length of a command. DESCRIPTION should not contain + any spaces, those must be encoded either percent escaped or simply as '+'. */ static int cmd_get_confirmation (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; char *desc = NULL; char *p; @@ -596,7 +653,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) static int cmd_passwd (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char grip[20]; gcry_sexp_t s_skey = NULL; @@ -607,7 +664,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) return rc; /* we can't jump to leave because this is already an Assuan error code. */ - rc = agent_key_from_file (ctrl, grip, &shadow_info, 1, &s_skey); + rc = agent_key_from_file (ctrl, NULL, grip, &shadow_info, 1, &s_skey); if (rc) ; else if (!s_skey) @@ -633,7 +690,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) static int cmd_scd (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; rc = divert_generic_cmd (ctrl, line, ctx); @@ -646,7 +703,7 @@ cmd_scd (ASSUAN_CONTEXT ctx, char *line) static int option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); if (!strcmp (key, "display")) { @@ -715,6 +772,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "HAVEKEY", cmd_havekey }, { "SIGKEY", cmd_sigkey }, { "SETKEY", cmd_sigkey }, + { "SETKEYDESC", cmd_setkeydesc }, { "SETHASH", cmd_sethash }, { "PKSIGN", cmd_pksign }, { "PKDECRYPT", cmd_pkdecrypt }, diff --git a/agent/findkey.c b/agent/findkey.c index f145daef1..14ca38448 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -1,5 +1,5 @@ /* findkey.c - locate the secret key - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -138,9 +138,10 @@ try_unprotect_cb (struct pin_entry_info_s *pi) /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP should be the hex encoded keygrip of that key to be used with the - caching mechanism. */ + caching mechanism. DESC_TEXT may be set to override the default + description used for the pinentry. */ static int -unprotect (CTRL ctrl, +unprotect (CTRL ctrl, const char *desc_text, unsigned char **keybuf, const unsigned char *grip, int ignore_cache) { struct pin_entry_info_s *pi; @@ -184,7 +185,7 @@ unprotect (CTRL ctrl, arg.unprotected_key = NULL; pi->check_cb_arg = &arg; - rc = agent_askpin (ctrl, NULL, pi); + rc = agent_askpin (ctrl, desc_text, pi); if (!rc) { assert (arg.unprotected_key); @@ -203,9 +204,10 @@ unprotect (CTRL ctrl, diverted to a token; SHADOW_INFO will point then to an allocated S-Expression with the shadow_info part from the file. With IGNORE_CACHE passed as true the passphrase is not taken from the - cache.*/ + cache. DESC_TEXT may be set to present a custom description for the + pinentry. */ gpg_error_t -agent_key_from_file (CTRL ctrl, +agent_key_from_file (CTRL ctrl, const char *desc_text, const unsigned char *grip, unsigned char **shadow_info, int ignore_cache, gcry_sexp_t *result) { @@ -286,7 +288,7 @@ agent_key_from_file (CTRL ctrl, case PRIVATE_KEY_CLEAR: break; /* no unprotection needed */ case PRIVATE_KEY_PROTECTED: - rc = unprotect (ctrl, &buf, grip, ignore_cache); + rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache); if (rc) log_error ("failed to unprotect the secret key: %s\n", gpg_strerror (rc)); diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 72f81778e..eaa2b2254 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -35,7 +35,8 @@ Try to get the key from CTRL and write the decoded stuff back to OUTFP. */ int -agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, +agent_pkdecrypt (CTRL ctrl, const char *desc_text, + const unsigned char *ciphertext, size_t ciphertextlen, FILE *outfp) { gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL; @@ -64,7 +65,8 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, log_printhex ("keygrip:", ctrl->keygrip, 20); log_printhex ("cipher: ", ciphertext, ciphertextlen); } - rc = agent_key_from_file (ctrl, ctrl->keygrip, &shadow_info, 0, &s_skey); + rc = agent_key_from_file (ctrl, desc_text, + ctrl->keygrip, &shadow_info, 0, &s_skey); if (rc) { log_error ("failed to read the secret key\n"); diff --git a/agent/pksign.c b/agent/pksign.c index 34381365e..8bec33c0b 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -70,7 +70,7 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) /* SIGN whatever information we have accumulated in CTRL and write it back to OUTFP. */ int -agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) +agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) { gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL; unsigned char *shadow_info = NULL; @@ -81,7 +81,7 @@ agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) if (!ctrl->have_keygrip) return gpg_error (GPG_ERR_NO_SECKEY); - rc = agent_key_from_file (ctrl, ctrl->keygrip, + rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip, &shadow_info, ignore_cache, &s_skey); if (rc) { -- cgit v1.2.3 From 01486117e893f1a57460297937e6f6ff03fe6359 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 Feb 2004 17:06:50 +0000 Subject: * certcheck.c (gpgsm_create_cms_signature): Format a description for use by the pinentry. * decrypt.c (gpgsm_decrypt): Ditto. Free HEXKEYGRIP. * certdump.c (format_name_cookie, format_name_writer) (gpgsm_format_name): New. (gpgsm_format_serial): New. (gpgsm_format_keydesc): New. * call-agent.c (gpgsm_agent_pksign): New arg DESC. (gpgsm_agent_pkdecrypt): Ditto. --- sm/ChangeLog | 10 ++++ sm/call-agent.c | 24 +++++++- sm/certcheck.c | 7 ++- sm/certdump.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- sm/certreqgen.c | 2 +- sm/decrypt.c | 15 +++-- sm/gpgsm.h | 8 ++- 7 files changed, 236 insertions(+), 13 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 2e78d1f41..4af2437d3 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,15 @@ 2004-02-13 Werner Koch <wk@gnupg.org> + * certcheck.c (gpgsm_create_cms_signature): Format a description + for use by the pinentry. + * decrypt.c (gpgsm_decrypt): Ditto. Free HEXKEYGRIP. + * certdump.c (format_name_cookie, format_name_writer) + (gpgsm_format_name): New. + (gpgsm_format_serial): New. + (gpgsm_format_keydesc): New. + * call-agent.c (gpgsm_agent_pksign): New arg DESC. + (gpgsm_agent_pkdecrypt): Ditto. + * encrypt.c (init_dek): Check for too weak algorithms. * import.c (parse_p12, popen_protect_tool): New. diff --git a/sm/call-agent.c b/sm/call-agent.c index fe740964b..30a1b6480 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -301,7 +301,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length) /* Call the agent to do a sign operation using the key identified by the hex string KEYGRIP. */ int -gpgsm_agent_pksign (const char *keygrip, +gpgsm_agent_pksign (const char *keygrip, const char *desc, unsigned char *digest, size_t digestlen, int digestalgo, char **r_buf, size_t *r_buflen ) { @@ -328,6 +328,16 @@ gpgsm_agent_pksign (const char *keygrip, if (rc) return map_assuan_err (rc); + if (desc) + { + snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); + line[DIM(line)-1] = 0; + rc = assuan_transact (agent_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + } + sprintf (line, "SETHASH %d ", digestalgo); p = line + strlen (line); for (i=0; i < digestlen ; i++, p += 2 ) @@ -376,7 +386,7 @@ inq_ciphertext_cb (void *opaque, const char *keyword) /* Call the agent to do a decrypt operation using the key identified by the hex string KEYGRIP. */ int -gpgsm_agent_pkdecrypt (const char *keygrip, +gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc, ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen ) { @@ -411,6 +421,16 @@ gpgsm_agent_pkdecrypt (const char *keygrip, if (rc) return map_assuan_err (rc); + if (desc) + { + snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); + line[DIM(line)-1] = 0; + rc = assuan_transact (agent_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + } + init_membuf (&data, 1024); cipher_parm.ctx = agent_ctx; cipher_parm.ciphertext = ciphertext; diff --git a/sm/certcheck.c b/sm/certcheck.c index 47cae13c0..dbd0ff1ba 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -282,16 +282,19 @@ gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, char **r_sigval) { int rc; - char *grip; + char *grip, *desc; size_t siglen; grip = gpgsm_get_keygrip_hexstring (cert); if (!grip) return gpg_error (GPG_ERR_BAD_CERT); - rc = gpgsm_agent_pksign (grip, gcry_md_read(md, mdalgo), + desc = gpgsm_format_keydesc (cert); + + rc = gpgsm_agent_pksign (grip, desc, gcry_md_read(md, mdalgo), gcry_md_get_algo_dlen (mdalgo), mdalgo, r_sigval, &siglen); + xfree (desc); xfree (grip); return rc; } diff --git a/sm/certdump.c b/sm/certdump.c index 26f3f7e2c..598ce7448 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -1,5 +1,5 @@ /* certdump.c - Dump a certificate for debugging - * Copyright (C) 2001 Free Software Foundation, Inc. + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -94,6 +94,41 @@ gpgsm_dump_serial (ksba_const_sexp_t p) } } + +char * +gpgsm_format_serial (ksba_const_sexp_t p) +{ + unsigned long n; + char *endp; + char *buffer; + int i; + + if (!p) + return NULL; + + if (*p != '(') + BUG (); /* Not a valid S-expression. */ + + p++; + n = strtoul (p, &endp, 10); + p = endp; + if (*p!=':') + BUG (); /* Not a valid S-expression. */ + p++; + + buffer = xtrymalloc (n*2+1); + if (buffer) + { + for (i=0; n; n--, p++, i+=2) + sprintf (buffer+i, "%02X", *(unsigned char *)p); + buffer[i] = 0; + } + return buffer; +} + + + + void gpgsm_print_time (FILE *fp, ksba_isotime_t t) { @@ -479,3 +514,149 @@ gpgsm_print_name (FILE *fp, const char *name) +/* A cookie structure used for the memory stream. */ +struct format_name_cookie +{ + char *buffer; /* Malloced buffer with the data to deliver. */ + size_t size; /* Allocated size of this buffer. */ + size_t len; /* strlen (buffer). */ + int error; /* system error code if any. */ +}; + +/* The writer function for the memory stream. */ +static int +format_name_writer (void *cookie, const char *buffer, size_t size) +{ + struct format_name_cookie *c = cookie; + char *p; + + if (c->buffer) + p = xtryrealloc (c->buffer, c->size + size + 1); + else + p = xtrymalloc (size + 1); + if (!p) + { + c->error = errno; + xfree (c->buffer); + errno = c->error; + return -1; + } + c->buffer = p; + memcpy (p + c->len, buffer, size); + c->len += size; + p[c->len] = 0; /* Terminate string. */ + + return size; +} + +/* Format NAME which is expected to be in rfc2253 format into a better + human readable format. Caller must free the returned string. NULL + is returned in case of an error. */ +char * +gpgsm_format_name (const char *name) +{ +#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN) + FILE *fp; + struct format_name_cookie cookie; + + memset (&cookie, 0, sizeof cookie); + +#ifdef HAVE_FOPENCOOKIE + { + cookie_io_functions_t io = { NULL }; + io.write = format_name_writer; + + fp = fopencookie (&cookie, "w", io); + } +#else /*!HAVE_FOPENCOOKIE*/ + { + fp = funopen (&cookie, NULL, format_name_writer, NULL, NULL); + } +#endif /*!HAVE_FOPENCOOKIE*/ + if (!fp) + { + int save_errno = errno; + log_error ("error creating memory stream: %s\n", strerror (errno)); + errno = save_errno; + return NULL; + } + gpgsm_print_name (fp, name); + fclose (fp); + if (cookie.error || !cookie.buffer) + { + xfree (cookie.buffer); + errno = cookie.error; + return NULL; + } + return cookie.buffer; +#else /* No fun - use the name verbatim. */ + return xtrystrdup (name); +#endif /* No fun. */ +} + + +/* Create a key description for the CERT, this may be passed to the + pinentry. The caller must free the returned string. NULL may be + returned on error. */ +char * +gpgsm_format_keydesc (ksba_cert_t cert) +{ + char *name, *subject, *buffer, *p; + const char *s; + ksba_isotime_t t; + char created[20]; + char *sn; + ksba_sexp_t sexp; + + name = ksba_cert_get_subject (cert, 0); + subject = name? gpgsm_format_name (name) : NULL; + ksba_free (name); name = NULL; + + sexp = ksba_cert_get_serial (cert); + sn = sexp? gpgsm_format_serial (sexp) : NULL; + ksba_free (sexp); + + ksba_cert_get_validity (cert, 0, t); + if (t && *t) + sprintf (created, "%.4s-%.2s-%.2s", t, t+4, t+6); + else + *created = 0; + + if ( asprintf (&name, + _("Please enter the passphrase to unlock the" + " secret key for:\n" + "\"%s\"\n" + "S/N %s, ID %08lX, created %s" ), + subject? subject:"?", + sn? sn: "?", + gpgsm_get_short_fingerprint (cert), + created) < 0) + { + int save_errno = errno; + xfree (subject); + xfree (sn); + errno = save_errno; + return NULL; + } + + xfree (subject); + xfree (sn); + + buffer = p = xtrymalloc (strlen (name) * 3 + 1); + for (s=name; *s; s++) + { + if (*s < ' ' || *s == '+') + { + sprintf (p, "%%%02X", *(unsigned char *)s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p = 0; + free (name); + + return buffer; +} diff --git a/sm/certreqgen.c b/sm/certreqgen.c index cffa564bd..a0addd2b4 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -614,7 +614,7 @@ create_request (struct para_data_s *para, ksba_const_sexp_t public, for (n=0; n < 20; n++) sprintf (hexgrip+n*2, "%02X", grip[n]); - rc = gpgsm_agent_pksign (hexgrip, + rc = gpgsm_agent_pksign (hexgrip, NULL, gcry_md_read(md, GCRY_MD_SHA1), gcry_md_get_algo_dlen (GCRY_MD_SHA1), GCRY_MD_SHA1, diff --git a/sm/decrypt.c b/sm/decrypt.c index 427466a49..76524b51f 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -54,14 +54,15 @@ struct decrypt_filter_parm_s { /* Decrypt the session key and fill in the parm structure. The algo and the IV is expected to be already in PARM. */ static int -prepare_decryption (const char *hexkeygrip, ksba_const_sexp_t enc_val, +prepare_decryption (const char *hexkeygrip, const char *desc, + ksba_const_sexp_t enc_val, struct decrypt_filter_parm_s *parm) { char *seskey = NULL; size_t n, seskeylen; int rc; - rc = gpgsm_agent_pkdecrypt (hexkeygrip, enc_val, + rc = gpgsm_agent_pkdecrypt (hexkeygrip, desc, enc_val, &seskey, &seskeylen); if (rc) { @@ -356,6 +357,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) ksba_sexp_t serial; ksba_sexp_t enc_val; char *hexkeygrip = NULL; + char *desc = NULL; rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial); if (rc == -1 && recp) @@ -402,6 +404,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) } hexkeygrip = gpgsm_get_keygrip_hexstring (cert); + desc = gpgsm_format_keydesc (cert); oops: xfree (issuer); @@ -416,12 +419,12 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) recp); else { - rc = prepare_decryption (hexkeygrip, enc_val, &dfparm); + rc = prepare_decryption (hexkeygrip, desc, enc_val, &dfparm); xfree (enc_val); if (rc) { - log_debug ("decrypting session key failed: %s\n", - gpg_strerror (rc)); + log_info ("decrypting session key failed: %s\n", + gpg_strerror (rc)); } else { /* setup the bulk decrypter */ @@ -431,6 +434,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) &dfparm); } } + xfree (hexkeygrip); + xfree (desc); } if (!any_key) { diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 2132c564e..eb40b1c49 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -197,6 +197,10 @@ void gpgsm_dump_serial (ksba_const_sexp_t p); void gpgsm_dump_time (ksba_isotime_t t); void gpgsm_dump_string (const char *string); +char *gpgsm_format_serial (ksba_const_sexp_t p); +char *gpgsm_format_name (const char *name); + +char *gpgsm_format_keydesc (ksba_cert_t cert); /*-- certcheck.c --*/ @@ -260,12 +264,12 @@ int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp); int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- call-agent.c --*/ -int gpgsm_agent_pksign (const char *keygrip, +int gpgsm_agent_pksign (const char *keygrip, const char *desc, unsigned char *digest, size_t digestlen, int digestalgo, char **r_buf, size_t *r_buflen); -int gpgsm_agent_pkdecrypt (const char *keygrip, +int gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc, ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen); int gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); -- cgit v1.2.3 From ef5546a48b9af8de5cc9f96a7f7dfa123f312fed Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Feb 2004 15:04:28 +0000 Subject: Added STATUS_IMPORT_OK. --- common/ChangeLog | 4 ++++ common/errors.h | 1 + 2 files changed, 5 insertions(+) diff --git a/common/ChangeLog b/common/ChangeLog index 6355f350a..7fc6bb60f 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-02-17 Werner Koch <wk@gnupg.org> + + * errors.h: Added STATUS_IMPORT_OK. + 2004-02-10 Werner Koch <wk@gnupg.org> * b64enc.c: New. Based on code from ../sm/base64.c. diff --git a/common/errors.h b/common/errors.h index a5643f08a..881a2fa51 100644 --- a/common/errors.h +++ b/common/errors.h @@ -63,6 +63,7 @@ enum { STATUS_BADMDC, STATUS_ERRMDC, STATUS_IMPORTED, + STATUS_IMPORT_OK, STATUS_IMPORT_PROBLEM, STATUS_IMPORT_RES, STATUS_FILE_START, -- cgit v1.2.3 From a5fc1f40c36778dd24472b42bfd8b43e7c63f64f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Feb 2004 15:04:49 +0000 Subject: Added new options --- doc/gpgsm.texi | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 1c8b3071b..bf0e071b8 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -305,6 +305,16 @@ 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 @@ -730,7 +740,10 @@ To import certificates into the internal key database, the command @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. +@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 -- cgit v1.2.3 From 45a817bf4a6f7624d49cd61247b7efeb3b7ad726 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Feb 2004 15:05:04 +0000 Subject: * gpgsm.c: New option --with-md5-fingerprint. * keylist.c (list_cert_std): Print MD5 fpr. * gpgsm.c: New options --with-validation. * server.c (option_handler): New option "with-validation". * keylist.c (list_cert_std, list_internal_keys): New args CTRL and WITH_VALIDATION. Changed callers to set it. (list_external_cb, list_external_keys): Pass CTRL to the callback. (list_cert_colon): Add arg CTRL. Check validation if requested. * certchain.c (unknown_criticals, allowed_ca, check_cert_policy) (gpgsm_validate_chain): New args LISTMODE and FP. (do_list): New helper for info output. (find_up): New arg FIND_NEXT. (gpgsm_validate_chain): After a bad signature try again with other CA certificates. * import.c (print_imported_status): New arg NEW_CERT. Print additional STATUS_IMPORT_OK becuase that is what gpgme expects. (check_and_store): Always call above function after import. * server.c (get_status_string): Added STATUS_IMPORT_OK. --- sm/ChangeLog | 23 +++++ sm/certchain.c | 269 +++++++++++++++++++++++++++++++++++++-------------------- sm/certcheck.c | 2 +- sm/certlist.c | 2 +- sm/gpgsm.c | 12 ++- sm/gpgsm.h | 19 ++-- sm/import.c | 20 +++-- sm/keylist.c | 112 +++++++++++++++--------- sm/server.c | 5 ++ sm/sign.c | 2 +- sm/verify.c | 2 +- 11 files changed, 315 insertions(+), 153 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 4af2437d3..aa6e46bc2 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,26 @@ +2004-02-17 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New option --with-md5-fingerprint. + * keylist.c (list_cert_std): Print MD5 fpr. + + * gpgsm.c: New options --with-validation. + * server.c (option_handler): New option "with-validation". + * keylist.c (list_cert_std, list_internal_keys): New args CTRL and + WITH_VALIDATION. Changed callers to set it. + (list_external_cb, list_external_keys): Pass CTRL to the callback. + (list_cert_colon): Add arg CTRL. Check validation if requested. + * certchain.c (unknown_criticals, allowed_ca, check_cert_policy) + (gpgsm_validate_chain): New args LISTMODE and FP. + (do_list): New helper for info output. + (find_up): New arg FIND_NEXT. + (gpgsm_validate_chain): After a bad signature try again with other + CA certificates. + + * import.c (print_imported_status): New arg NEW_CERT. Print + additional STATUS_IMPORT_OK becuase that is what gpgme expects. + (check_and_store): Always call above function after import. + * server.c (get_status_string): Added STATUS_IMPORT_OK. + 2004-02-13 Werner Koch <wk@gnupg.org> * certcheck.c (gpgsm_create_cms_signature): Format a description diff --git a/sm/certchain.c b/sm/certchain.c index bcc66660a..bf5582503 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1,5 +1,5 @@ /* certchain.c - certificate chain validation - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,8 +25,11 @@ #include <errno.h> #include <unistd.h> #include <time.h> +#include <stdarg.h> #include <assert.h> +#define JNLIB_NEED_LOG_LOGV /* We need log_logv. */ + #include "gpgsm.h" #include <gcrypt.h> #include <ksba.h> @@ -35,8 +38,37 @@ #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */ #include "i18n.h" + +/* If LISTMODE is true, print FORMAT in liting mode to FP. If + LISTMODE is false, use the string to print an log_info or, if + IS_ERROR is true, an log_error. */ +static void +do_list (int is_error, int listmode, FILE *fp, const char *format, ...) +{ + va_list arg_ptr; + + va_start (arg_ptr, format) ; + if (listmode) + { + if (fp) + { + fputs (" [", fp); + vfprintf (fp, format, arg_ptr); + fputs ("]\n", fp); + } + } + else + { + log_logv (is_error? JNLIB_LOG_ERROR: JNLIB_LOG_INFO, format, arg_ptr); + log_printf ("\n"); + } + va_end (arg_ptr); +} + + + static int -unknown_criticals (ksba_cert_t cert) +unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp) { static const char *known[] = { "2.5.29.15", /* keyUsage */ @@ -57,8 +89,9 @@ unknown_criticals (ksba_cert_t cert) ; if (!known[i]) { - log_error (_("critical certificate extension %s is not supported\n"), - oid); + do_list (1, listmode, fp, + _("critical certificate extension %s is not supported"), + oid); rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT); } } @@ -69,7 +102,7 @@ unknown_criticals (ksba_cert_t cert) } static int -allowed_ca (ksba_cert_t cert, int *chainlen) +allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp) { gpg_error_t err; int flag; @@ -79,7 +112,7 @@ allowed_ca (ksba_cert_t cert, int *chainlen) return err; if (!flag) { - log_error (_("issuer certificate is not marked as a CA\n")); + do_list (1, listmode, fp,_("issuer certificate is not marked as a CA")); return gpg_error (GPG_ERR_BAD_CA_CERT); } return 0; @@ -87,7 +120,7 @@ allowed_ca (ksba_cert_t cert, int *chainlen) static int -check_cert_policy (ksba_cert_t cert) +check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist) { gpg_error_t err; char *policies; @@ -105,7 +138,7 @@ check_cert_policy (ksba_cert_t cert) first field is the OID of the policy and the second field either N or C for normal or critical extension */ - if (opt.verbose > 1) + if (opt.verbose > 1 && !listmode) log_info ("certificate's policy list: %s\n", policies); /* The check is very minimal but won't give false positives */ @@ -116,7 +149,8 @@ check_cert_policy (ksba_cert_t cert) xfree (policies); if (any_critical) { - log_error ("critical marked policy without configured policies\n"); + do_list (1, listmode, fplist, + _("critical marked policy without configured policies")); return gpg_error (GPG_ERR_NO_POLICY_MATCH); } return 0; @@ -131,10 +165,12 @@ check_cert_policy (ksba_cert_t cert) /* With no critical policies this is only a warning */ if (!any_critical) { - log_info (_("note: certificate policy not allowed\n")); + do_list (0, listmode, fplist, + _("note: non-critical certificate policy not allowed")); return 0; } - log_error (_("certificate policy not allowed\n")); + do_list (1, listmode, fplist, + _("certificate policy not allowed")); return gpg_error (GPG_ERR_NO_POLICY_MATCH); } @@ -158,10 +194,12 @@ check_cert_policy (ksba_cert_t cert) /* With no critical policies this is only a warning */ if (!any_critical) { - log_info (_("note: certificate policy not allowed\n")); + do_list (0, listmode, fplist, + _("note: non-critical certificate policy not allowed")); return 0; } - log_error (_("certificate policy not allowed\n")); + do_list (1, listmode, fplist, + _("certificate policy not allowed")); return gpg_error (GPG_ERR_NO_POLICY_MATCH); } fclose (fp); @@ -222,7 +260,7 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) static int -find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer) +find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) { ksba_name_t authid; ksba_sexp_t authidno; @@ -236,8 +274,12 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer) rc = keydb_search_issuer_sn (kh, s, authidno); if (rc) keydb_search_reset (kh); - if (rc == -1) - { /* And try the ephemeral DB. */ + + /* In case of an error try the ephemeral DB. We can't do + that in find-netx mode because we can't keep the search + state then. */ + if (rc == -1 && !find_next) + { int old = keydb_set_ephemeral (kh, 1); if (!old) { @@ -248,9 +290,9 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer) keydb_set_ephemeral (kh, old); } } - /* print a note so that the user does not feel too helpless when + /* Print a note so that the user does not feel too helpless when an issuer certificate was found and gpgsm prints BAD - signature becuase it is not the correct one. */ + signature because it is not the correct one. */ if (rc == -1) { log_info ("issuer certificate (#"); @@ -267,8 +309,8 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer) } if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */ - rc = keydb_search_subject (kh, issuer); - if (rc == -1) + rc = keydb_search_subject (kh, issuer); + if (rc == -1 && !find_next) { /* Not found, lets see whether we have one in the ephemeral key DB. */ int old = keydb_set_ephemeral (kh, 1); @@ -280,7 +322,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer) keydb_set_ephemeral (kh, old); } - if (rc == -1 && opt.auto_issuer_key_retrieve) + if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) { STRLIST names = NULL; int count = 0; @@ -368,7 +410,7 @@ gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next) goto leave; } - rc = find_up (kh, start, issuer); + rc = find_up (kh, start, issuer, 0); if (rc) { /* it is quite common not to have a certificate, so better don't @@ -413,9 +455,12 @@ gpgsm_is_root_cert (ksba_cert_t cert) /* Validate a chain and optionally return the nearest expiration time - in R_EXPTIME */ + in R_EXPTIME. With LISTMODE set to 1 a special listmode is + activated where only information about the certificate is printed + to FP and no outputis send to the usual log stream. */ int -gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) +gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, + int listmode, FILE *fp) { int rc = 0, depth = 0, maxdepth; char *issuer = NULL; @@ -429,14 +474,14 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) int any_no_crl = 0; int any_crl_too_old = 0; int any_no_policy_match = 0; - + int lm = listmode; gnupg_get_isotime (current_time); if (r_exptime) *r_exptime = 0; *exptime = 0; - if (opt.no_chain_validation) + if (opt.no_chain_validation && !listmode) { log_info ("WARNING: bypassing certificate chain validation\n"); return 0; @@ -449,7 +494,7 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) goto leave; } - if (DBG_X509) + if (DBG_X509 && !listmode) gpgsm_dump_cert ("subject", cert); subject_cert = cert; @@ -464,7 +509,7 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) if (!issuer) { - log_error ("no issuer found in certificate\n"); + do_list (1, lm, fp, _("no issuer found in certificate")); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } @@ -477,8 +522,8 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) rc = ksba_cert_get_validity (subject_cert, 1, not_after); if (rc) { - log_error (_("certificate with invalid validity: %s\n"), - gpg_strerror (rc)); + do_list (1, lm, fp, _("certificate with invalid validity: %s"), + gpg_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } @@ -493,28 +538,36 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) if (*not_before && strcmp (current_time, not_before) < 0 ) { - log_error ("certificate too young; valid from "); - gpgsm_dump_time (not_before); - log_printf ("\n"); + do_list (1, lm, fp, _("certificate not yet valid")); + if (!lm) + { + log_info ("(valid from "); + gpgsm_dump_time (not_before); + log_printf (")\n"); + } rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG); goto leave; } if (not_after && strcmp (current_time, not_after) > 0 ) { - log_error ("certificate has expired at "); - gpgsm_dump_time (not_after); - log_printf ("\n"); + do_list (1, lm, fp, _("certificate has expired")); + if (!lm) + { + log_error ("(expired at "); + gpgsm_dump_time (not_after); + log_printf (")\n"); + } any_expired = 1; } } - rc = unknown_criticals (subject_cert); + rc = unknown_criticals (subject_cert, listmode, fp); if (rc) goto leave; if (!opt.no_policy_check) { - rc = check_cert_policy (subject_cert); + rc = check_cert_policy (subject_cert, listmode, fp); if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH) { any_no_policy_match = 1; @@ -534,7 +587,7 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) switch (gpg_err_code (rc)) { case GPG_ERR_CERT_REVOKED: - log_error (_("the certificate has been revoked\n")); + do_list (1, lm, fp, _("certificate has been revoked")); any_revoked = 1; /* Store that in the keybox so that key listings are able to return the revoked flag. We don't care @@ -543,18 +596,19 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) VALIDITY_REVOKED); break; case GPG_ERR_NO_CRL_KNOWN: - log_error (_("no CRL found for certificate\n")); + do_list (1, lm, fp, _("no CRL found for certificate")); any_no_crl = 1; break; case GPG_ERR_CRL_TOO_OLD: - log_error (_("the available CRL is too old\n")); - log_info (_("please make sure that the " - "\"dirmngr\" is properly installed\n")); + do_list (1, lm, fp, _("the available CRL is too old")); + if (!lm) + log_info (_("please make sure that the " + "\"dirmngr\" is properly installed\n")); any_crl_too_old = 1; break; default: - log_error (_("checking the CRL failed: %s\n"), - gpg_strerror (rc)); + do_list (1, lm, fp, _("checking the CRL failed: %s"), + gpg_strerror (rc)); goto leave; } rc = 0; @@ -565,12 +619,13 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) { if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) { - log_error ("selfsigned certificate has a BAD signatures\n"); + do_list (1, lm, fp, + _("selfsigned certificate has a BAD signature")); rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN : GPG_ERR_BAD_CERT); goto leave; } - rc = allowed_ca (subject_cert, NULL); + rc = allowed_ca (subject_cert, NULL, listmode, fp); if (rc) goto leave; @@ -579,26 +634,28 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) ; else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) { - int rc2; - - char *fpr = gpgsm_get_fingerprint_string (subject_cert, - GCRY_MD_SHA1); - log_info (_("root certificate is not marked trusted\n")); - log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); - xfree (fpr); - rc2 = gpgsm_agent_marktrusted (subject_cert); - if (!rc2) - { - log_info (_("root certificate has now" - " been marked as trusted\n")); - rc = 0; - } - else + do_list (0, lm, fp, _("root certificate is not marked trusted")); + if (!lm) { - gpgsm_dump_cert ("issuer", subject_cert); - log_info ("after checking the fingerprint, you may want " - "to add it manually to the list of trusted " - "certificates.\n"); + int rc2; + char *fpr = gpgsm_get_fingerprint_string (subject_cert, + GCRY_MD_SHA1); + log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); + xfree (fpr); + rc2 = gpgsm_agent_marktrusted (subject_cert); + if (!rc2) + { + log_info (_("root certificate has now" + " been marked as trusted\n")); + rc = 0; + } + else + { + gpgsm_dump_cert ("issuer", subject_cert); + log_info ("after checking the fingerprint, you may want " + "to add it manually to the list of trusted " + "certificates.\n"); + } } } else @@ -613,21 +670,25 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) depth++; if (depth > maxdepth) { - log_error (_("certificate chain too long\n")); + do_list (1, lm, fp, _("certificate chain too long\n")); rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN); goto leave; } /* find the next cert up the tree */ keydb_search_reset (kh); - rc = find_up (kh, subject_cert, issuer); + rc = find_up (kh, subject_cert, issuer, 0); if (rc) { if (rc == -1) { - log_info ("issuer certificate (#/"); - gpgsm_dump_string (issuer); - log_printf (") not found\n"); + do_list (0, lm, fp, _("issuer certificate not found")); + if (!lm) + { + log_info ("issuer certificate: #/"); + gpgsm_dump_string (issuer); + log_printf ("\n"); + } } else log_error ("failed to find issuer's certificate: rc=%d\n", rc); @@ -635,6 +696,7 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) goto leave; } + try_another_cert: ksba_cert_release (issuer_cert); issuer_cert = NULL; rc = keydb_get_cert (kh, &issuer_cert); if (rc) @@ -650,38 +712,56 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) gpgsm_dump_cert ("issuer", issuer_cert); } - if (gpgsm_check_cert_sig (issuer_cert, subject_cert) ) + rc = gpgsm_check_cert_sig (issuer_cert, subject_cert); + if (rc) { - log_error ("certificate has a BAD signatures\n"); + do_list (0, lm, fp, _("certificate has a BAD signature")); + if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE) + { + rc = find_up (kh, subject_cert, issuer, 1); + if (!rc) + { + do_list (0, lm, fp, _("found another possible matching " + "CA certificate - trying again")); + goto try_another_cert; + } + } + + /* We give a more descriptive error code than the one + returned from the signature checking. */ rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN); goto leave; } { int chainlen; - rc = allowed_ca (issuer_cert, &chainlen); + rc = allowed_ca (issuer_cert, &chainlen, listmode, fp); if (rc) goto leave; if (chainlen >= 0 && (depth - 1) > chainlen) { - log_error (_("certificate chain longer than allowed by CA (%d)\n"), - chainlen); + do_list (1, lm, fp, + _("certificate chain longer than allowed by CA (%d)"), + chainlen); rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN); goto leave; } } - rc = gpgsm_cert_use_cert_p (issuer_cert); - if (rc) + if (!listmode) { - char numbuf[50]; - sprintf (numbuf, "%d", rc); - gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", - numbuf, NULL); - rc = 0; + rc = gpgsm_cert_use_cert_p (issuer_cert); + if (rc) + { + char numbuf[50]; + sprintf (numbuf, "%d", rc); + gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", + numbuf, NULL); + rc = 0; + } } - if (opt.verbose) + if (opt.verbose && !listmode) log_info ("certificate is good\n"); keydb_search_reset (kh); @@ -689,10 +769,15 @@ gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime) issuer_cert = NULL; } - if (opt.no_policy_check) - log_info ("policies not checked due to --disable-policy-checks option\n"); - if (opt.no_crl_check && !ctrl->use_ocsp) - log_info ("CRLs not checked due to --disable-crl-checks option\n"); + if (!listmode) + { + if (opt.no_policy_check) + log_info ("policies not checked due to %s option\n", + "--disable-policy-checks"); + if (opt.no_crl_check && !ctrl->use_ocsp) + log_info ("CRLs not checked due to %s option\n", + "--disable-crl-checks"); + } if (!rc) { /* If we encountered an error somewhere during the checks, set @@ -733,7 +818,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) char *subject = NULL; KEYDB_HANDLE kh = keydb_new (0); ksba_cert_t issuer_cert = NULL; - + if (opt.no_chain_validation) { log_info ("WARNING: bypassing basic certificate checks\n"); @@ -760,7 +845,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) { if (gpgsm_check_cert_sig (cert, cert) ) { - log_error ("selfsigned certificate has a BAD signatures\n"); + log_error ("selfsigned certificate has a BAD signature\n"); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } @@ -769,7 +854,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) { /* find the next cert up the tree */ keydb_search_reset (kh); - rc = find_up (kh, cert, issuer); + rc = find_up (kh, cert, issuer, 0); if (rc) { if (rc == -1) @@ -795,7 +880,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) if (gpgsm_check_cert_sig (issuer_cert, cert) ) { - log_error ("certificate has a BAD signatures\n"); + log_error ("certificate has a BAD signature\n"); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } diff --git a/sm/certcheck.c b/sm/certcheck.c index dbd0ff1ba..271557ae7 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -49,7 +49,7 @@ do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, asnlen = DIM(asn); if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) { - log_error ("No object identifier for algo %d\n", algo); + log_error ("no object identifier for algo %d\n", algo); return gpg_error (GPG_ERR_INTERNAL); } diff --git a/sm/certlist.c b/sm/certlist.c index b61f0f663..66fb46326 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -280,7 +280,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, } } if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL); + rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL); if (!rc) { CERTLIST cl = xtrycalloc (1, sizeof *cl); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index fa3e1b203..0734c0644 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1,5 +1,5 @@ /* gpgsm.c - GnuPG for S/MIME - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -125,6 +125,7 @@ enum cmd_and_opt_values { oTextmode, oFingerprint, oWithFingerprint, + oWithMD5Fingerprint, oAnswerYes, oAnswerNo, oKeyring, @@ -158,6 +159,7 @@ enum cmd_and_opt_values { oHomedir, oWithColons, oWithKeyData, + oWithValidation, oSkipVerify, oCompressKeys, oCompressSigs, @@ -378,6 +380,8 @@ static ARGPARSE_OPTS opts[] = { { oNoBatch, "no-batch", 0, "@" }, { oWithColons, "with-colons", 0, "@"}, { oWithKeyData,"with-key-data", 0, "@"}, + { oWithValidation, "with-validation", 0, "@"}, + { oWithMD5Fingerprint, "with-md5-fingerprint", 0, "@"}, { aListKeys, "list-key", 0, "@" }, /* alias */ { aListSigs, "list-sig", 0, "@" }, /* alias */ { aListSigs, "check-sig",0, "@" }, /* alias */ @@ -925,6 +929,8 @@ main ( int argc, char **argv) case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; + case oWithMD5Fingerprint: + opt.with_md5_fingerprint=1; /*fall thru*/ case oWithFingerprint: with_fpr=1; /*fall thru*/ case oFingerprint: @@ -980,6 +986,7 @@ main ( int argc, char **argv) case oWithKeyData: opt.with_key_data=1; /* fall thru */ case oWithColons: ctrl.with_colons = 1; break; + case oWithValidation: ctrl.with_validation=1; break; case oSkipVerify: opt.skip_verify=1; break; @@ -1291,7 +1298,8 @@ main ( int argc, char **argv) case aListExternalKeys: for (sl=NULL; argc; argc--, argv++) add_to_strlist (&sl, *argv); - gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<7))); + gpgsm_list_keys (&ctrl, sl, stdout, + (0 | (1<<7))); free_strlist(sl); break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index eb40b1c49..49a73186d 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -58,9 +58,12 @@ struct { char *outfile; /* name of output file */ int with_key_data;/* include raw key in the column delimted output */ - + int fingerprint; /* list fingerprints in all key listings */ + int with_md5_fingerprint; /* Also print an MD5 fingerprint for + standard key listings. */ + int armor; /* force base64 armoring (see also ctrl.with_base64) */ int no_armor; /* don't try to figure out whether data is base64 armored*/ @@ -117,13 +120,14 @@ struct server_local_s; /* Note that the default values for this are set by gpgsm_init_default_ctrl() */ struct server_control_s { - int no_server; /* we are not running under server control */ - int status_fd; /* only for non-server mode */ + int no_server; /* We are not running under server control */ + int status_fd; /* Only for non-server mode */ struct server_local_s *server_local; - int with_colons; /* use column delimited output format */ - int with_chain; /* include the certifying certs in a listing */ + int with_colons; /* Use column delimited output format */ + int with_chain; /* Include the certifying certs in a listing */ + int with_validation;/* Validate each key while listing. */ - int autodetect_encoding; /* try to detect the input encoding */ + int autodetect_encoding; /* Try to detect the input encoding */ int is_pem; /* Is in PEM format */ int is_base64; /* is in plain base-64 format */ @@ -216,7 +220,8 @@ int gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next); int gpgsm_is_root_cert (ksba_cert_t cert); int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, - ksba_isotime_t r_exptime); + ksba_isotime_t r_exptime, + int listmode, FILE *listfp); int gpgsm_basic_cert_check (ksba_cert_t cert); /*-- certlist.c --*/ diff --git a/sm/import.c b/sm/import.c index b11cd75b6..47f062790 100644 --- a/sm/import.c +++ b/sm/import.c @@ -57,12 +57,17 @@ static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp); static void -print_imported_status (CTRL ctrl, ksba_cert_t cert) +print_imported_status (CTRL ctrl, ksba_cert_t cert, int new_cert) { char *fpr; - + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL); + if (new_cert) + gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL); + + gpgsm_status2 (ctrl, STATUS_IMPORT_OK, + new_cert? "1":"0", fpr, NULL); + xfree (fpr); } @@ -146,7 +151,7 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) /* Some basic checks, but don't care about missing certificates; this is so that we are able to import entire certificate chains w/o requirening a special order (i.e. root-CA first). This used - to be different but becuase gpgsm_verify even imports + to be different but because gpgsm_verify even imports certificates without any checks, it doesn't matter much and the code gets much cleaner. A housekeeping function to remove certificates w/o an anchor would be nice, though. */ @@ -161,11 +166,14 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) if (!existed) { - print_imported_status (ctrl, cert); + print_imported_status (ctrl, cert, 1); stats->imported++; } else - stats->unchanged++; + { + print_imported_status (ctrl, cert, 0); + stats->unchanged++; + } if (opt.verbose > 1 && existed) { diff --git a/sm/keylist.c b/sm/keylist.c index 40fa6b043..e6daec681 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1,5 +1,6 @@ /* keylist.c - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -37,6 +38,7 @@ #include "i18n.h" struct list_external_parm_s { + ctrl_t ctrl; FILE *fp; int print_header; int with_colons; @@ -146,28 +148,35 @@ email_kludge (const char *name) /* List one certificate in colon mode */ static void -list_cert_colon (ksba_cert_t cert, unsigned int validity, +list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, FILE *fp, int have_secret) { - int idx, trustletter = 0; + int idx; + char truststring[2]; char *p; ksba_sexp_t sexp; char *fpr; ksba_isotime_t t; + gpg_error_t valerr; - fputs (have_secret? "crs:":"crt:", fp); - trustletter = 0; - if ((validity & VALIDITY_REVOKED)) - trustletter = 'r'; -#if 0 - else if (is_not_valid (cert)) - putc ('i', fp); - else if ( has_expired (cert)) - putcr ('e', fp); -#endif + if (ctrl->with_validation) + valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL); else - trustletter = '?'; - putc (trustletter, fp); + valerr = 0; + + fputs (have_secret? "crs:":"crt:", fp); + truststring[0] = 0; + truststring[1] = 0; + if ((validity & VALIDITY_REVOKED) + || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED) + *truststring = 'r'; + else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED) + *truststring = 'e'; + else if (valerr) + *truststring = 'i'; + + if (*truststring) + fputs (truststring, fp); fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); fprintf (fp, ":%u:%d:%s:", @@ -247,7 +256,7 @@ list_cert_colon (ksba_cert_t cert, unsigned int validity, for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++) { - fprintf (fp, "uid:%c::::::::", trustletter); + fprintf (fp, "uid:%s::::::::", truststring); print_sanitized_string (fp, p, ':'); putc (':', fp); putc (':', fp); @@ -261,7 +270,7 @@ list_cert_colon (ksba_cert_t cert, unsigned int validity, char *pp = email_kludge (p); if (pp) { - fprintf (fp, "uid:%c::::::::", trustletter); + fprintf (fp, "uid:%s::::::::", truststring); print_sanitized_string (fp, pp, ':'); putc (':', fp); putc (':', fp); @@ -276,9 +285,10 @@ list_cert_colon (ksba_cert_t cert, unsigned int validity, /* List one certificate in standard mode */ static void -list_cert_std (ksba_cert_t cert, FILE *fp, int have_secret) +list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, + int with_validation) { - gpg_error_t kerr; + gpg_error_t err; ksba_sexp_t sexp; char *dn; ksba_isotime_t t; @@ -327,12 +337,12 @@ list_cert_std (ksba_cert_t cert, FILE *fp, int have_secret) gpgsm_print_time (fp, t); putc ('\n', fp); - kerr = ksba_cert_get_key_usage (cert, &kusage); - if (gpg_err_code (kerr) != GPG_ERR_NO_DATA) + err = ksba_cert_get_key_usage (cert, &kusage); + if (gpg_err_code (err) != GPG_ERR_NO_DATA) { fputs (" key usage:", fp); - if (kerr) - fprintf (fp, " [error: %s]", gpg_strerror (kerr)); + if (err) + fprintf (fp, " [error: %s]", gpg_strerror (err)); else { if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE)) @@ -357,12 +367,12 @@ list_cert_std (ksba_cert_t cert, FILE *fp, int have_secret) putc ('\n', fp); } - kerr = ksba_cert_get_cert_policies (cert, &string); - if (gpg_err_code (kerr) != GPG_ERR_NO_DATA) + err = ksba_cert_get_cert_policies (cert, &string); + if (gpg_err_code (err) != GPG_ERR_NO_DATA) { fputs (" policies: ", fp); - if (kerr) - fprintf (fp, "[error: %s]", gpg_strerror (kerr)); + if (err) + fprintf (fp, "[error: %s]", gpg_strerror (err)); else { for (p=string; *p; p++) @@ -376,12 +386,12 @@ list_cert_std (ksba_cert_t cert, FILE *fp, int have_secret) putc ('\n', fp); } - kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen); - if (kerr || is_ca) + err = ksba_cert_is_ca (cert, &is_ca, &chainlen); + if (err || is_ca) { fputs (" chain length: ", fp); - if (kerr) - fprintf (fp, "[error: %s]", gpg_strerror (kerr)); + if (err) + fprintf (fp, "[error: %s]", gpg_strerror (err)); else if (chainlen == -1) fputs ("unlimited", fp); else @@ -389,25 +399,41 @@ list_cert_std (ksba_cert_t cert, FILE *fp, int have_secret) putc ('\n', fp); } + if (opt.with_md5_fingerprint) + { + dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5); + fprintf (fp, " md5 fpr: %s\n", dn?dn:"error"); + xfree (dn); + } dn = gpgsm_get_fingerprint_string (cert, 0); fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); xfree (dn); + + if (with_validation) + { + err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp); + if (!err) + fprintf (fp, " [certificate is good]\n"); + else + fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err)); + } } -/* Same as standard mode mode list all certifying certts too */ + +/* Same as standard mode mode list all certifying certs too. */ static void -list_cert_chain (ksba_cert_t cert, FILE *fp) +list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation) { ksba_cert_t next = NULL; - list_cert_std (cert, fp, 0); + list_cert_std (ctrl, cert, fp, 0, with_validation); ksba_cert_ref (cert); while (!gpgsm_walk_cert_chain (cert, &next)) { ksba_cert_release (cert); fputs ("Certified by\n", fp); - list_cert_std (next, fp, 0); + list_cert_std (ctrl, next, fp, 0, with_validation); cert = next; } ksba_cert_release (cert); @@ -471,7 +497,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) } - /* it would be nice to see which of the given users did actually + /* 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 - @@ -532,12 +558,13 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) || ((mode & 2) && have_secret) ) { if (ctrl->with_colons) - list_cert_colon (cert, validity, fp, have_secret); + list_cert_colon (ctrl, cert, validity, fp, have_secret); else if (ctrl->with_chain) - list_cert_chain (cert, fp); + list_cert_chain (ctrl, cert, fp, ctrl->with_validation); else { - list_cert_std (cert, fp, have_secret); + list_cert_std (ctrl, cert, fp, have_secret, + ctrl->with_validation); putc ('\n', fp); } } @@ -576,12 +603,12 @@ list_external_cb (void *cb_value, ksba_cert_t cert) } if (parm->with_colons) - list_cert_colon (cert, 0, parm->fp, 0); + list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0); else if (parm->with_chain) - list_cert_chain (cert, parm->fp); + list_cert_chain (parm->ctrl, cert, parm->fp, 0); else { - list_cert_std (cert, parm->fp, 0); + list_cert_std (parm->ctrl, cert, parm->fp, 0, 0); putc ('\n', parm->fp); } } @@ -597,6 +624,7 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) struct list_external_parm_s parm; parm.fp = fp; + parm.ctrl = ctrl, parm.print_header = ctrl->no_server; parm.with_colons = ctrl->with_colons; parm.with_chain = ctrl->with_chain; diff --git a/sm/server.c b/sm/server.c index 549c35350..54b220d14 100644 --- a/sm/server.c +++ b/sm/server.c @@ -170,6 +170,10 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) else return ASSUAN_Parameter_Error; } + else if (!strcmp (key, "with-validation")) + { + ctrl->with_validation = !!*value; + } else return ASSUAN_Invalid_Option; @@ -898,6 +902,7 @@ get_status_string ( int no ) case STATUS_BADMDC : s = "BADMDC"; break; case STATUS_ERRMDC : s = "ERRMDC"; break; case STATUS_IMPORTED : s = "IMPORTED"; break; + case STATUS_IMPORT_OK : s = "IMPORT_OK"; break; case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; case STATUS_FILE_START : s = "FILE_START"; break; case STATUS_FILE_DONE : s = "FILE_DONE"; break; diff --git a/sm/sign.c b/sm/sign.c index 3f64c2e5e..1d3b01cb3 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -378,7 +378,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, valid. */ rc = gpgsm_cert_use_sign_p (cert); if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL); + rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL); if (rc) goto leave; diff --git a/sm/verify.c b/sm/verify.c index 2a95c81e7..bd334908e 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -458,7 +458,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) if (DBG_X509) log_debug ("signature okay - checking certs\n"); - rc = gpgsm_validate_chain (ctrl, cert, keyexptime); + rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL); if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) { gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); -- cgit v1.2.3 From d68674a77a4fc92b4311244d760ef070d06d363b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Feb 2004 15:07:27 +0000 Subject: More samples --- tests/samplekeys/README | 5 ++++ tests/samplekeys/ossl-rentec-user.pem | 44 ++++++++++++++++++++++++++++ tests/samplekeys/webdeca.der | Bin 0 -> 1857 bytes tests/samplekeys/webderoot.der | Bin 0 -> 2009 bytes tests/samplemsgs/webde-buenemann-signed.cms | Bin 0 -> 3368 bytes 5 files changed, 49 insertions(+) create mode 100644 tests/samplekeys/ossl-rentec-user.pem create mode 100644 tests/samplekeys/webdeca.der create mode 100644 tests/samplekeys/webderoot.der create mode 100644 tests/samplemsgs/webde-buenemann-signed.cms diff --git a/tests/samplekeys/README b/tests/samplekeys/README index d2ff84c72..0e8877907 100644 --- a/tests/samplekeys/README +++ b/tests/samplekeys/README @@ -6,6 +6,11 @@ opensc-tests.p12 PKCS#12 key and certificates taken from OpenSC. ov-user.p12 Private tests keys from www.openvalidation.org. ov-server.p12 Passphrase for both is "start" +ossl-rentec-user.pem An OpenSSL generated user certificate using a + bunch of attributes and DC RDNs. + +webderoot.der trust.web.de Root CA certificate [2004-02-17] +webdeca.der trust.web.de CA certificate [2004-02-17] diff --git a/tests/samplekeys/ossl-rentec-user.pem b/tests/samplekeys/ossl-rentec-user.pem new file mode 100644 index 000000000..290b0ef0d --- /dev/null +++ b/tests/samplekeys/ossl-rentec-user.pem @@ -0,0 +1,44 @@ +-----BEGIN CERTIFICATE----- +MIIHnTCCBYWgAwIBAgIBATANBgkqhkiG9w0BAQQFADBGMRMwEQYKCZImiZPyLGQB +GRYDY29tMRYwFAYKCZImiZPyLGQBGRYGcmVudGVjMRcwFQYDVQQDDA5SZW5haXNz +YW5jZSBDQTAeFw0wNDAxMTAwNDE1NDZaFw0wNjAxMDkwNDE1NDZaMFcxEzARBgoJ +kiaJk/IsZAEZFgNjb20xFjAUBgoJkiaJk/IsZAEZFgZyZW50ZWMxDzANBgNVBAsM +BlBlb3BsZTEXMBUGA1UEAwwOS2Fyc3RlbiBLw7xubmUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDBoZHGO+Ikq/Uhb9a4nUBuKayowUVga0wPQCiWhoLV +u2tDVWf7U9uzFrz/6JMIIBT3MIe5hBgQrYWq80/na3WO+H7vd4nR3gUfPBrfDPCm +HPm9nRMV1BsnFeg+2O0N+mfci2e/PLu7Ph9Arrr4+C0IVKQWxdNiqYj/gA0mSYvw +aThuBe8px3PZPAosZ9oGuhKmT+J9JtGe3qcyGPoW6yPEVpAUff0EFBGFI+wvaRV/ +vlK2omekQ2GkirzMqywTYiBPMuQ0abIjWZJn6ThR4FspIFLDAFnppwbZHMozrBYm +vS7pkoTK+DGVzk6kdbRxugWr61q0CQfL8b6VdfB6SGqxAgMBAAGjggODMIIDfzAJ +BgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAOBgNVHQ8BAf8EBAMCBeAwHQYD +VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMFAGCWCGSAGG+EIBDQRDFkFPcGVu +U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZSwgaXNzdWVkIGJ5IFJlbmFpc3NhbmNl +IFRlY2huLiBDb3JwLjAdBgNVHQ4EFgQUh6HtcbLmbeEAQSpU73jYI7Ap0HUwbgYD +VR0jBGcwZYAUXqKKaiAqs5Gz38Yq0UGucAGbLd+hSqRIMEYxEzARBgoJkiaJk/Is +ZAEZFgNjb20xFjAUBgoJkiaJk/IsZAEZFgZyZW50ZWMxFzAVBgNVBAMMDlJlbmFp +c3NhbmNlIENBggEAMDgGA1UdEgQxMC+BDWNhQHJlbnRlYy5jb22GHmh0dHBzOi8v +d3d3LnJlbnRlYy5jb206ODQ0NC9jYTA9BgNVHR8ENjA0MDKgMKAuhixodHRwczov +L3d3dy5yZW50ZWMuY29tOjg0NDQvY2EvcmVudGVjX2NhLmNybDA6BggrBgEFBQcB +AQQuMCwwKgYIKwYBBQUHMAGGHmh0dHA6Ly9jb3VnYXIucmVudGVjLmNvbTo4MDgy +LzAuBglghkgBhvhCAQIEIRYfaHR0cHM6Ly93d3cucmVudGVjLmNvbTo4NDQ0L2Nh +LzAcBglghkgBhvhCAQgEDxYNY2Fwb2xpY3kuaHRtbDAlBglghkgBhvhCAQMEGBYW +Y2dpLWJpbi9jaGVjay1yZXYuY2dpPzCCAQUGA1UdIASB/TCB+jCB9wYKKwYBBAHD +SAMBATCB6DA4BggrBgEFBQcCARYsaHR0cHM6Ly93d3cucmVudGVjLmNvbTo4NDQ0 +L2NhL2NhcG9saWN5Lmh0bWwwgasGCCsGAQUFBwICMIGeGoGbT3BlblNTTCBHZW5l +cmF0ZWQgQ2VydGlmaWNhdGUsIGlzc3VlZCBieSBSZW5haXNzYW5jZSBUZWNobi4g +Q29ycC4sIFRoaXMgY2VydGlmaWNhdGUgaXMgdmFsaWQgb25seSBmb3IgU1NMIENs +aWVudCBBdXRoZW50aWNhdGlvbiBhbmQgU2VjdXJlIEUtTWFpbCAoUy9NSU1FKS4w +HAYDVR0RBBUwE4ERa3Vlbm5lQHJlbnRlYy5jb20wDQYJKoZIhvcNAQEEBQADggIB +AGgYIKrR5nQKICNuXl1OwWFwk+CgnbDrVIrIoFiwRlSqaNsedXMXIDYHdyE/LYwR +VaiHFimV5WywIPeoBKiws67ZcWVfGGvxF2CZuCcnuQpAyKn+J0PDAaTi3z/uoi4n +YPUVMpfU/7TPXVo4pjFfUmm9XJ6dduC6SlAN+1/xDRR1dy2WqNLcN1dpyoUTtEWp +Xvp7I66oLfWahKs0d4fOXIrZmyLqKN3H8CLrZPz8b4Skw+wWxEUIqJEkRKez5adK +Ry1VK21nIwUUWHfLvrqw4CgZvpMQVEZRhsiOPqlHEH+epDV4hD5/OCG5oK+8RoKA +Yw1xjs3gOCCf6GDVrftBBLsYQufL7E4BOD4RKDYQCo6HD7cHXfy+RttdIcKzlq4u +6QbzFgIkc3KF0/U5FpvKxQHyfQwoD8AORWF6myjGtM13ij8yXg4Mx1sgKOY9IK1/ +muLauYAamNdCSkD5+0ecmYJ98G7022zUTBE8LR6FFHAG+3F8mzP+oI2eOwJYzMFW +Zw3MNUCarArIyxts/+izpOEIfkf0ztx1TckCTGd/F7WAkQcDHZHsf8Vb+eaLTltk +rEM6mnpov+YCO8qb/vmr2018fNS5haTJvECjLbYRy6RV2v6wRPNbYRHN3og87h/8 +2HUYfYCVebbJdzSwkQGApPty9mx2wr3EwB7KTT+IjXkp +-----END CERTIFICATE----- + diff --git a/tests/samplekeys/webdeca.der b/tests/samplekeys/webdeca.der new file mode 100644 index 000000000..9532e3fa5 Binary files /dev/null and b/tests/samplekeys/webdeca.der differ diff --git a/tests/samplekeys/webderoot.der b/tests/samplekeys/webderoot.der new file mode 100644 index 000000000..3fedd9cd0 Binary files /dev/null and b/tests/samplekeys/webderoot.der differ diff --git a/tests/samplemsgs/webde-buenemann-signed.cms b/tests/samplemsgs/webde-buenemann-signed.cms new file mode 100644 index 000000000..9ed2dc1c4 Binary files /dev/null and b/tests/samplemsgs/webde-buenemann-signed.cms differ -- cgit v1.2.3 From 81edc1e40ecb73c83d983fbf63b012559d063ad9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Feb 2004 17:21:07 +0000 Subject: * gpgsm.c: Fixed value parsing for --with-validation. * call-agent.c (start_agent): Ignore an empty GPG_AGENT_INFO. * call-dirmngr.c (start_dirmngr): Likewise for DIRMNGR_INFO. --- sm/ChangeLog | 4 ++++ sm/call-agent.c | 4 ++-- sm/call-dirmngr.c | 2 +- sm/server.c | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index aa6e46bc2..2f46e1e4d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,9 @@ 2004-02-17 Werner Koch <wk@gnupg.org> + * gpgsm.c: Fixed value parsing for --with-validation. + * call-agent.c (start_agent): Ignore an empty GPG_AGENT_INFO. + * call-dirmngr.c (start_dirmngr): Likewise for DIRMNGR_INFO. + * gpgsm.c: New option --with-md5-fingerprint. * keylist.c (list_cert_std): Print MD5 fpr. diff --git a/sm/call-agent.c b/sm/call-agent.c index 30a1b6480..a0a1da5c3 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -78,10 +78,10 @@ start_agent (void) if (agent_ctx) return 0; /* fixme: We need a context for each thread or serialize the access to the agent (which is suitable given that - the agent is not MT */ + the agent is not MT. */ infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO"); - if (!infostr) + if (!infostr || !*infostr) { const char *pgmname; const char *argv[3]; diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 05f7bd10d..ba96df499 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -142,7 +142,7 @@ start_dirmngr (void) the access to the dirmngr */ infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); - if (!infostr) + if (!infostr || !*infostr) { const char *pgmname; const char *argv[3]; diff --git a/sm/server.c b/sm/server.c index 54b220d14..8cc1b900e 100644 --- a/sm/server.c +++ b/sm/server.c @@ -172,7 +172,8 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) } else if (!strcmp (key, "with-validation")) { - ctrl->with_validation = !!*value; + int i = *value? atoi (value) : 0; + ctrl->with_validation = i; } else return ASSUAN_Invalid_Option; -- cgit v1.2.3 From bda3467067cb93de9a86b8cad17e20c3f0558d0c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 16:57:38 +0000 Subject: * protect-tool.c (main): Setup the used character set. * gpg-agent.c (main): Ditto. * gpg-agent.c (set_debug): New. New option --debug-level. (main): New option --gpgconf-list. --- NEWS | 8 +- agent/ChangeLog | 15 ++ agent/Makefile.am | 1 - agent/gpg-agent.c | 80 +++++++- agent/pksign.c | 28 +-- agent/protect-tool.c | 5 + agent/simple-pwquery.c | 486 ------------------------------------------------- agent/simple-pwquery.h | 69 ------- 8 files changed, 112 insertions(+), 580 deletions(-) delete mode 100644 agent/simple-pwquery.c delete mode 100644 agent/simple-pwquery.h diff --git a/NEWS b/NEWS index 07216f555..c0a8d6026 100644 --- a/NEWS +++ b/NEWS @@ -8,9 +8,15 @@ Noteworthy changes in version 1.9.5 * [gpgsm] The --import command is now able to autodetect pkcs#12 files and import secret and private keys from this file format. - * [gpgsm] The pinentry will no present a description of the key for + * [gpgsm] The pinentry will now present a description of the key for whom the passphrase is requests. + * [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) ------------------------------------------------ diff --git a/agent/ChangeLog b/agent/ChangeLog index f064bc17c..ffd48f59e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,18 @@ +2004-02-18 Werner Koch <wk@gnupg.org> + + * protect-tool.c (main): Setup the used character set. + * gpg-agent.c (main): Ditto. + + * gpg-agent.c (set_debug): New. New option --debug-level. + (main): New option --gpgconf-list. + +2004-02-17 Werner Koch <wk@gnupg.org> + + * pksign.c (do_encode_md): Cleaned up by using gcry_sexp_build. + + * Makefile.am (gpg_protect_tool_SOURCES): Removed + simple-pwquery.[ch], as we once moved it to ../common. + 2004-02-13 Werner Koch <wk@gnupg.org> * command.c (cmd_setkeydesc): New. diff --git a/agent/Makefile.am b/agent/Makefile.am index 6f7097749..e83311fb4 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -51,7 +51,6 @@ gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ gpg_protect_tool_SOURCES = \ protect-tool.c \ protect.c \ - simple-pwquery.c simple-pwquery.h \ minip12.c minip12.h gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \ diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 22537aa3b..83a1041f8 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -51,11 +51,13 @@ enum cmd_and_opt_values oQuiet = 'q', oSh = 's', oVerbose = 'v', - + oNoVerbose = 500, + aGPGConfList, oOptions, oDebug, oDebugAll, + oDebugLevel, oDebugWait, oNoGreeting, oNoOptions, @@ -86,6 +88,8 @@ aTest }; static ARGPARSE_OPTS opts[] = { + + { aGPGConfList, "gpgconf-list", 256, "@" }, { 301, NULL, 0, N_("@Options:\n ") }, @@ -96,8 +100,9 @@ static ARGPARSE_OPTS opts[] = { { oSh, "sh", 0, N_("sh-style command output") }, { oCsh, "csh", 0, N_("csh-style command output") }, { oOptions, "options" , 2, N_("read options from file")}, - { oDebug, "debug" ,4|16, N_("set debugging flags")}, - { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, + { oDebug, "debug" ,4|16, "@"}, + { oDebugAll, "debug-all" ,0, "@"}, + { oDebugLevel, "debug-level" ,2, "@"}, { oDebugWait,"debug-wait",1, "@"}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")}, @@ -145,6 +150,8 @@ static char *default_lc_messages; /* Name of a config file, which will be reread on a HUP if it is not NULL. */ static char *config_filename; +/* Helper to implement --debug-level */ +static const char *debug_level; /* Local prototypes. */ static void create_directories (void); @@ -216,6 +223,48 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) } +/* Setup the debugging. With a LEVEL of NULL only the active debug + flags are propagated to the subsystems. With LEVEL set, a specific + set of debug flags is set; thus overriding all flags already + set. Note that we don't fail here, because it is important to keep + gpg-agent running even after re-reading the options due to a + SIGHUP. */ +static void +set_debug (void) +{ + if (!debug_level) + ; + else if (!strcmp (debug_level, "none")) + opt.debug = 0; + else if (!strcmp (debug_level, "basic")) + opt.debug = DBG_ASSUAN_VALUE; + else if (!strcmp (debug_level, "advanced")) + opt.debug = DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE; + else if (!strcmp (debug_level, "expert")) + opt.debug = (DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE + |DBG_CACHE_VALUE); + else if (!strcmp (debug_level, "guru")) + opt.debug = ~0; + else + { + log_error (_("invalid debug-level `%s' given\n"), debug_level); + opt.debug = 0; /* Reset debugging, so that prior debug + statements won't have an undesired effect. */ + } + + if (opt.debug && !opt.verbose) + opt.verbose = 1; + if (opt.debug && opt.quiet) + opt.quiet = 0; + + if (opt.debug & DBG_MPI_VALUE) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); + if (opt.debug & DBG_CRYPTO_VALUE ) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); +} + + static void cleanup (void) { @@ -286,6 +335,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs) case oDebug: opt.debug |= pargs->r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; + case oDebugLevel: debug_level = pargs->r.ret_str; break; case oNoGrab: opt.no_grab = 1; break; @@ -325,6 +375,7 @@ main (int argc, char **argv ) char *logfile = NULL; int debug_wait = 0; int disable_pth = 0; + int gpgconf_list = 0; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -332,6 +383,10 @@ main (int argc, char **argv ) when adding any stuff between here and the call to INIT_SECMEM() somewhere after the option parsing */ log_set_prefix ("gpg-agent", 1|4); + + /* Try to auto set the character set. */ + set_native_charset (NULL); + i18n_init (); /* We need to initialize Pth before libgcrypt, because the libgcrypt @@ -446,6 +501,7 @@ main (int argc, char **argv ) continue; /* Already handled */ switch (pargs.r_opt) { + case aGPGConfList: gpgconf_list = 1; break; case oBatch: opt.batch=1; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; @@ -509,6 +565,7 @@ main (int argc, char **argv ) log_info ("NOTE: this is a development version!\n"); #endif + set_debug (); if (atexit (cleanup)) { @@ -526,6 +583,22 @@ main (int argc, char **argv ) sleep (debug_wait); log_debug ("... okay\n"); } + + if (gpgconf_list) + { /* List options and default values in the GPG Conf format. */ + + printf ("gpgconf-gpg-agent.conf:\"%s\n", config_filename); + + printf ("verbose:\n" + "quiet:\n" + "debug-level:none\n" + "log-file:\n" + "force:\n" + "faked-system-time:\n" + "no-greeting:\n"); + + agent_exit (0); + } if (!pipe_server && !is_daemon) log_info (_("please use the option `--daemon'" @@ -853,6 +926,7 @@ reread_configuration (void) parse_rereadable_options (&pargs); } fclose (fp); + set_debug (); } diff --git a/agent/pksign.c b/agent/pksign.c index 8bec33c0b..acde66029 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -1,5 +1,5 @@ -/* pksign.c - public key signing (well, acually using a secret key) - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. +/* pksign.c - public key signing (well, actually using a secret key) + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -35,17 +35,10 @@ static int do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) { gcry_sexp_t hash; - const char * s; - char * p, tmp[16]; + const char *s; + char tmp[16+1]; int i, rc; -#ifdef __GNUC__ -#warning I do not like that stuff - libgcrypt provides easier interfaces. -wk -#endif - /* FIXME: Either use the build function or create canonical encoded - S-expressions. */ - - p = xmalloc (64 + 2 * mdlen); s = gcry_md_algo_name (algo); if (s && strlen (s) < 16) { @@ -53,15 +46,10 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) tmp[i] = tolower (s[i]); tmp[i] = '\0'; } - sprintf (p, "(data\n (flags pkcs1)\n (hash %s #", tmp); - for (i=0; i < mdlen; i++) - { - sprintf (tmp, "%02x", (byte)md[i]); - strcat (p, tmp); - } - strcat (p, "#))\n"); - rc = gcry_sexp_sscan (&hash, NULL, p, strlen (p)); - xfree (p); + rc = gcry_sexp_build (&hash, NULL, + "(data (flags pkcs1) (hash %s %b))", + tmp, + mdlen, md); *r_hash = hash; return rc; } diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 0bb344424..59f6c6711 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -872,6 +872,10 @@ main (int argc, char **argv ) set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); log_set_prefix ("gpg-protect-tool", 1); + + /* Try to auto set the character set. */ + set_native_charset (NULL); + i18n_init (); if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) @@ -884,6 +888,7 @@ main (int argc, char **argv ) gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + #ifdef __MINGW32__ opt_homedir = read_w32_registry_string ( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); diff --git a/agent/simple-pwquery.c b/agent/simple-pwquery.c deleted file mode 100644 index e870122cb..000000000 --- a/agent/simple-pwquery.c +++ /dev/null @@ -1,486 +0,0 @@ -/* simple-pwquery.c - A simple password query client 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 ) - { -#ifdef SPWQ_USE_LOGGING - log_error (_("gpg-agent is not available in this session\n")); -#endif - return SPWQ_NO_AGENT; - } - - 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 poiinter 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; - char *p = buffer; - - for (i=0; text[i]; i++) - { - if (text[i] < ' ' || text[i] == '+') - { - sprintf (p, "%%%02X", text[i]); - p += 3; - } - else if (text[i] == ' ') - *p++ = '+'; - else - *p++ = text[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; -} diff --git a/agent/simple-pwquery.h b/agent/simple-pwquery.h deleted file mode 100644 index a1b276ff6..000000000 --- a/agent/simple-pwquery.h +++ /dev/null @@ -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; 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); - - -#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*/ -- cgit v1.2.3 From 103a442be9da91bf2ddb22f416347ce1505e109f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 16:58:00 +0000 Subject: * simple-pwquery.c (agent_open): Ignore an empty GPG_AGENT_INFO. --- common/ChangeLog | 2 ++ common/simple-pwquery.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index 7fc6bb60f..28395053c 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,7 @@ 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> diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index afdc4e2a4..5ceddc613 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -266,7 +266,7 @@ agent_open (int *rfd) *rfd = -1; infostr = getenv ( "GPG_AGENT_INFO" ); - if ( !infostr ) + if ( !infostr || !*infostr ) { #ifdef SPWQ_USE_LOGGING log_error (_("gpg-agent is not available in this session\n")); -- cgit v1.2.3 From 6c9c5accd1ad3d838b6cb6bc4112ec6fdf248e3b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 16:58:29 +0000 Subject: Described new options --- doc/gpg-agent.texi | 23 +++++++++++++++++++++++ doc/gpgsm.texi | 35 ++++++++++++++++++++++++++++++----- doc/scdaemon.texi | 23 +++++++++++++++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index fbab7a17e..92975fd11 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -146,11 +146,34 @@ 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 diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index bf0e071b8..10d487f82 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -343,11 +343,35 @@ 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: +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 @@ -365,10 +389,11 @@ usual C-Syntax. The currently defined bits are: write hashed data to files named @code{dbgmd-000*} @item 10 (1024) trace Assuan protocol - @item 12 (4096) - bypass all certificate validation @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} diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 5a5a1af6a..51ec4b34c 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -88,11 +88,34 @@ 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 -- cgit v1.2.3 From 16f3d8396e1e6954b02cd86ec6344ad60396a0e8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 16:59:03 +0000 Subject: * call-agent.c (start_agent): Ignore an empty GPG_AGENT_INFO. * passphrase.c (agent_open): Ditto. --- g10/ChangeLog | 5 +++++ g10/call-agent.c | 2 +- g10/passphrase.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index d45fa74ad..c6715c635 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2004-02-17 Werner Koch <wk@gnupg.org> + + * call-agent.c (start_agent): Ignore an empty GPG_AGENT_INFO. + * passphrase.c (agent_open): Ditto. + 2004-02-12 Werner Koch <wk@gnupg.org> * gpgv.c: Removed g10defs.h. diff --git a/g10/call-agent.c b/g10/call-agent.c index b981b7f22..e1eabc9f0 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -82,7 +82,7 @@ start_agent (void) the access to the agent. */ infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO"); - if (!infostr) + if (!infostr || !*infostr) { const char *pgmname; const char *argv[3]; diff --git a/g10/passphrase.c b/g10/passphrase.c index 0db9404b9..27ffcad97 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -504,7 +504,7 @@ agent_open (int *ret_prot) else { infostr = getenv ( "GPG_AGENT_INFO" ); - if ( !infostr ) { + if ( !infostr || !*infostr ) { log_error (_("gpg-agent is not available in this session\n")); opt.use_agent = 0; return -1; -- cgit v1.2.3 From 9702e85d5d3c7d1e3ea8ccac7852fa8d1523d4a3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 16:59:19 +0000 Subject: (print_sanitized_buffer): Don't care about non-ASCII characaters. (sanitize_buffer): Ditto. --- jnlib/ChangeLog | 6 ++++++ jnlib/stringhelp.c | 8 +++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index d6361153c..6867b4fb9 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,9 @@ +2004-02-18 Werner Koch <wk@gnupg.org> + + * stringhelp.c (print_sanitized_buffer): Don't care about + non-ASCII characaters. + (sanitize_buffer): Ditto. + 2004-02-12 Werner Koch <wk@gnupg.org> * Makefile.am: Replaced INCLUDES by AM_CPPFLAGS. diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index e2744a5ac..4c8ab314b 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -327,7 +327,7 @@ print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, for (; length; length--, p++, count++) { - if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim) + if (*p < 0x20 || *p == 0x7f || *p == delim) { putc ('\\', fp); count++; @@ -408,8 +408,7 @@ sanitize_buffer (const unsigned char *p, size_t n, int delim) /* first count length */ for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) { - if ( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim - || (delim && *p=='\\')) + if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) { if ( *p=='\n' || *p=='\r' || *p=='\f' || *p=='\v' || *p=='\b' || !*p ) @@ -426,8 +425,7 @@ sanitize_buffer (const unsigned char *p, size_t n, int delim) d = buffer = jnlib_xmalloc( buflen ); for ( ; n; n--, p++ ) { - if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim - ||(delim && *p=='\\')) { + if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) { *d++ = '\\'; if( *p == '\n' ) *d++ = 'n'; -- cgit v1.2.3 From ef7e99c4271a0a4f8324a72fc15f86657df3ebda Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 16:59:53 +0000 Subject: Adjusted for moved file. --- po/POTFILES.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 7cb83ded6..3bf6300b5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,12 +2,12 @@ agent/gpg-agent.c agent/protect-tool.c -agent/simple-pwquery.c agent/divert-scd.c agent/genkey.c agent/query.c common/sysutils.c +common/simple-pwquery.c jnlib/argparse.c jnlib/logging.c -- cgit v1.2.3 From de43297298225f2a2846b2b9d379a14921941cec Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 17:00:11 +0000 Subject: * sc-investigate.c (main): Setup the used character set. * scdaemon.c (main): Ditto. * scdaemon.c (set_debug): New. Add option --debug-level. (main): Add option --gpgconf-list. --- scd/ChangeLog | 8 +++++ scd/sc-investigate.c | 4 +++ scd/scdaemon.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 002ad1efc..66ceebd22 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,11 @@ +2004-02-18 Werner Koch <wk@gnupg.org> + + * sc-investigate.c (main): Setup the used character set. + * scdaemon.c (main): Ditto. + + * scdaemon.c (set_debug): New. Add option --debug-level. + (main): Add option --gpgconf-list. + 2004-02-12 Werner Koch <wk@gnupg.org> * Makefile.am: Include cmacros.am for common flags. diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index acef86ead..6f8b330b1 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -145,6 +145,9 @@ main (int argc, char **argv ) gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); log_set_prefix ("sc-investigate", 1); + /* Try to auto set the character set. */ + set_native_charset (NULL); + /* check that the libraries are suitable. Do it here because the option parsing may need services of the library */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) @@ -153,6 +156,7 @@ main (int argc, char **argv ) NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); } + gcry_set_log_handler (my_gcry_logger, NULL); /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/ diff --git a/scd/scdaemon.c b/scd/scdaemon.c index c6652c8dc..5665237ca 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -1,5 +1,5 @@ /* scdaemon.c - The GnuPG Smartcard Daemon - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -54,9 +54,11 @@ enum cmd_and_opt_values oVerbose = 'v', oNoVerbose = 500, + aGPGConfList, oOptions, oDebug, oDebugAll, + oDebugLevel, oDebugWait, oDebugSC, oNoGreeting, @@ -81,6 +83,8 @@ aTest }; static ARGPARSE_OPTS opts[] = { + + { aGPGConfList, "gpgconf-list", 256, "@" }, { 301, NULL, 0, N_("@Options:\n ") }, @@ -91,8 +95,9 @@ static ARGPARSE_OPTS opts[] = { { oSh, "sh", 0, N_("sh-style command output") }, { oCsh, "csh", 0, N_("csh-style command output") }, { oOptions, "options" , 2, N_("read options from file")}, - { oDebug, "debug" ,4|16, N_("set debugging flags")}, - { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, + { oDebug, "debug" ,4|16, "@"}, + { oDebugAll, "debug-all" ,0, "@"}, + { oDebugLevel, "debug-level" ,2, "@"}, { oDebugWait,"debug-wait",1, "@"}, { oDebugSC, "debug-sc", 1, N_("|N|set OpenSC debug level to N")}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, @@ -191,6 +196,47 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) } +/* Setup the debugging. With a LEVEL of NULL only the active debug + flags are propagated to the subsystems. With LEVEL set, a specific + set of debug flags is set; thus overriding all flags already + set. */ +static void +set_debug (const char *level) +{ + if (!level) + ; + else if (!strcmp (level, "none")) + opt.debug = 0; + else if (!strcmp (level, "basic")) + opt.debug = DBG_ASSUAN_VALUE; + else if (!strcmp (level, "advanced")) + opt.debug = DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE; + else if (!strcmp (level, "expert")) + opt.debug = (DBG_ASSUAN_VALUE|DBG_COMMAND_VALUE + |DBG_CACHE_VALUE|DBG_CARD_IO_VALUE); + else if (!strcmp (level, "guru")) + opt.debug = ~0; + else + { + log_error (_("invalid debug-level `%s' given\n"), level); + scd_exit(2); + } + + + if (opt.debug && !opt.verbose) + opt.verbose = 1; + if (opt.debug && opt.quiet) + opt.quiet = 0; + + if (opt.debug & DBG_MPI_VALUE) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); + if (opt.debug & DBG_CRYPTO_VALUE ) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); +} + + + static void cleanup (void) { @@ -245,6 +291,7 @@ main (int argc, char **argv ) const char *shell; unsigned configlineno; int parse_debug = 0; + const char *debug_level = NULL; int default_config =1; int greeting = 0; int nogreeting = 0; @@ -254,6 +301,7 @@ main (int argc, char **argv ) int csh_style = 0; char *logfile = NULL; int debug_wait = 0; + int gpgconf_list = 0; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -261,6 +309,9 @@ main (int argc, char **argv ) when adding any stuff between here and the call to INIT_SECMEM() somewhere after the option parsing */ log_set_prefix ("scdaemon", 1|4); + /* Try to auto set the character set. */ + set_native_charset (NULL); + i18n_init (); /* check that the libraries are suitable. Do it here because @@ -368,12 +419,14 @@ main (int argc, char **argv ) { switch (pargs.r_opt) { + case aGPGConfList: gpgconf_list = 1; break; case oQuiet: opt.quiet = 1; break; case oVerbose: opt.verbose++; break; case oBatch: opt.batch=1; break; case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; + case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugSC: opt.debug_sc = pargs.r.ret_int; break; @@ -434,7 +487,7 @@ main (int argc, char **argv ) log_info ("NOTE: this is a development version!\n"); #endif - + if (atexit (cleanup)) { log_error ("atexit failed\n"); @@ -442,7 +495,8 @@ main (int argc, char **argv ) exit (1); } - + set_debug (debug_level); + if (debug_wait && pipe_server) { log_debug ("waiting for debugger - my pid is %u .....\n", @@ -451,6 +505,25 @@ main (int argc, char **argv ) log_debug ("... okay\n"); } + if (gpgconf_list) + { /* List options and default values in the GPG Conf format. */ + char *filename; + + filename = make_filename (opt.homedir, "scdaemon.conf", NULL); + printf ("gpgconf-scdaemon.conf:\"%s\n", filename); + xfree (filename); + + printf ("verbose:\n" + "quiet:\n" + "debug-level:none\n" + "log-file:\n" + "force:\n" + "faked-system-time:\n" + "no-greeting:\n"); + + scd_exit (0); + } + /* now start with logging to a file if this is desired */ if (logfile) { @@ -649,10 +722,10 @@ main (int argc, char **argv ) void scd_exit (int rc) { - #if 0 +#if 0 #warning no update_random_seed_file update_random_seed_file(); - #endif +#endif #if 0 /* at this time a bit annoying */ if (opt.debug & DBG_MEMSTAT_VALUE) -- cgit v1.2.3 From 1a709b341c23758de4b146a9702ef9d96898d188 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 17:00:21 +0000 Subject: * gpgsm.c (set_debug): Set the new --debug-level flags. (main): New option --gpgconf-list. (main): Do not setup -u and -r keys when not required. (main): Setup the used character set. * keydb.c (keydb_add_resource): Print a hint to start the gpg-agent. --- sm/ChangeLog | 10 ++++ sm/certdump.c | 2 +- sm/gpgsm.c | 179 ++++++++++++++++++++++++++++++++++++++++++---------------- sm/keydb.c | 2 + 4 files changed, 143 insertions(+), 50 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 2f46e1e4d..4fcc2517e 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2004-02-18 Werner Koch <wk@gnupg.org> + + * gpgsm.c (set_debug): Set the new --debug-level flags. + (main): New option --gpgconf-list. + (main): Do not setup -u and -r keys when not required. + (main): Setup the used character set. + + * keydb.c (keydb_add_resource): Print a hint to start the + gpg-agent. + 2004-02-17 Werner Koch <wk@gnupg.org> * gpgsm.c: Fixed value parsing for --with-validation. diff --git a/sm/certdump.c b/sm/certdump.c index 598ce7448..f2c21f7fa 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -555,7 +555,7 @@ format_name_writer (void *cookie, const char *buffer, size_t size) char * gpgsm_format_name (const char *name) { -#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN) +#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) FILE *fp; struct format_name_cookie cookie; diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 0734c0644..de265c128 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -80,9 +80,11 @@ enum cmd_and_opt_values { aCallDirmngr, aCallProtectTool, aPasswd, + aGPGConfList, oOptions, oDebug, + oDebugLevel, oDebugAll, oDebugWait, oDebugNoChainValidation, @@ -239,6 +241,7 @@ static ARGPARSE_OPTS opts[] = { { aCallProtectTool, "call-protect-tool", 256, N_("invoke gpg-protect-tool")}, { aPasswd, "passwd", 256, N_("change a passphrase")}, + { aGPGConfList, "gpgconf-list", 256, "@" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -316,6 +319,7 @@ static ARGPARSE_OPTS opts[] = { { oOptions, "options" , 2, N_("read options from file")}, { oDebug, "debug" ,4|16, "@"}, + { oDebugLevel, "debug-level" ,2, "@"}, { oDebugAll, "debug-all" ,0, "@"}, { oDebugWait, "debug-wait" ,1, "@"}, { oDebugNoChainValidation, "debug-no-chain-validation" ,0, "@"}, @@ -557,14 +561,47 @@ wrong_args (const char *text) } +/* Setup the debugging. With a LEVEL of NULL only the active debug + flags are propagated to the subsystems. With LEVEL set, a specific + set of debug flags is set; thus overriding all flags already + set. */ static void -set_debug(void) +set_debug (const char *level) { + if (!level) + ; + else if (!strcmp (level, "none")) + opt.debug = 0; + else if (!strcmp (level, "basic")) + opt.debug = DBG_ASSUAN_VALUE; + else if (!strcmp (level, "advanced")) + opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE; + else if (!strcmp (level, "expert")) + opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE + |DBG_CACHE_VALUE|DBG_CRYPTO_VALUE); + else if (!strcmp (level, "guru")) + opt.debug = ~0; + else + { + log_error (_("invalid debug-level `%s' given\n"), level); + gpgsm_exit(2); + } + + + if (opt.debug && !opt.verbose) + { + opt.verbose = 1; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); + } + if (opt.debug && opt.quiet) + opt.quiet = 0; + if (opt.debug & DBG_MPI_VALUE) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); if (opt.debug & DBG_CRYPTO_VALUE ) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); } + static void @@ -639,6 +676,7 @@ main ( int argc, char **argv) int greeting = 0; int nogreeting = 0; int debug_wait = 0; + const char *debug_level = NULL; int use_random_seed = 1; int with_fpr = 0; char *def_digest_string = NULL; @@ -646,6 +684,7 @@ main ( int argc, char **argv) struct server_control_s ctrl; CERTLIST recplist = NULL; CERTLIST signerlist = NULL; + int do_not_setup_keys = 0; /* trap_unaligned ();*/ set_strusage (my_strusage); @@ -658,7 +697,11 @@ main ( int argc, char **argv) when adding any stuff between here and the call to secmem_init() somewhere after the option parsing */ log_set_prefix ("gpgsm", 1); - /* check that the libraries are suitable. Do it here because the + + /* Try to auto set the character set. */ + set_native_charset (NULL); + + /* Check that the libraries are suitable. Do it here because the option parse may need services of the library */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) { @@ -780,53 +823,70 @@ main ( int argc, char **argv) { switch (pargs.r_opt) { + case aGPGConfList: + set_cmd (&cmd, pargs.r_opt); + do_not_setup_keys = 1; + nogreeting = 1; + break; + case aServer: opt.batch = 1; set_cmd (&cmd, aServer); break; + case aCallDirmngr: opt.batch = 1; set_cmd (&cmd, aCallDirmngr); + do_not_setup_keys = 1; break; case aCallProtectTool: opt.batch = 1; set_cmd (&cmd, aCallProtectTool); no_more_options = 1; /* Stop parsing. */ + do_not_setup_keys = 1; break; - case aCheckKeys: set_cmd (&cmd, aCheckKeys); break; - case aImport: set_cmd (&cmd, aImport); break; - case aSendKeys: set_cmd (&cmd, aSendKeys); break; - case aRecvKeys: set_cmd (&cmd, aRecvKeys); break; - case aExport: set_cmd (&cmd, aExport); break; - case aListKeys: set_cmd (&cmd, aListKeys); break; - case aListExternalKeys: set_cmd (&cmd, aListExternalKeys); break; - case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break; - case aListSigs: set_cmd (&cmd, aListSigs); break; - - case aLearnCard: set_cmd (&cmd, aLearnCard); break; - - case aPasswd: set_cmd (&cmd, aPasswd); break; - case aDeleteKey: set_cmd (&cmd, aDeleteKey); /*greeting=1;*/ + do_not_setup_keys = 1; break; case aDetachedSign: detached_sig = 1; set_cmd (&cmd, aSign ); break; - - case aSym: set_cmd (&cmd, aSym); break; - case aDecrypt: set_cmd (&cmd, aDecrypt); break; - case aEncr: set_cmd (&cmd, aEncr); break; - case aSign: set_cmd (&cmd, aSign ); break; - case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break; - case aClearsign: set_cmd (&cmd, aClearsign); break; - case aVerify: set_cmd (&cmd, aVerify); break; + case aKeygen: + set_cmd (&cmd, aKeygen); + greeting=1; + do_not_setup_keys = 1; + break; + + case aCheckKeys: + case aImport: + case aSendKeys: + case aRecvKeys: + case aExport: + case aListKeys: + case aListExternalKeys: + case aListSecretKeys: + case aListSigs: + case aLearnCard: + case aPasswd: + do_not_setup_keys = 1; + set_cmd (&cmd, pargs.r_opt); + break; + + case aSym: + case aDecrypt: + case aEncr: + case aSign: + case aClearsign: + case aVerify: + set_cmd (&cmd, pargs.r_opt); + break; /* output encoding selection */ case oArmor: @@ -924,6 +984,7 @@ main ( int argc, char **argv) case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; + case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugNoChainValidation: opt.no_chain_validation = 1; break; @@ -1101,7 +1162,7 @@ main ( int argc, char **argv) gcry_control (GCRYCTL_RESUME_SECMEM_WARN); - set_debug (); + set_debug (debug_level); /* FIXME: should set filenames of libgcrypt explicitly * gpg_opt_homedir = opt.homedir; */ @@ -1141,15 +1202,16 @@ main ( int argc, char **argv) keydb_add_resource (sl->d, 0, 0); FREE_STRLIST(nrings); - - for (sl = locusr; sl; sl = sl->next) + if (!do_not_setup_keys) { - int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0); - if (rc) + for (sl = locusr; sl ; sl = sl->next) { - log_error (_("can't sign using `%s': %s\n"), - sl->d, gpg_strerror (rc)); - gpgsm_status2 (&ctrl, STATUS_INV_RECP, + int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0); + if (rc) + { + log_error (_("can't sign using `%s': %s\n"), + sl->d, gpg_strerror (rc)); + gpgsm_status2 (&ctrl, STATUS_INV_RECP, gpg_err_code (rc) == -1? "1": gpg_err_code (rc) == GPG_ERR_NO_PUBKEY? "1": gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME? "2": @@ -1162,33 +1224,52 @@ main ( int argc, char **argv) gpg_err_code (rc) == GPG_ERR_NO_SECKEY? "9": "0", sl->d, NULL); + } } - } - - /* Build the recipient list. We first add the regular ones and then - the encrypt-to ones because the underlying function will silenty - ignore duplicates and we can't allow to keep a duplicate which is - flagged as encrypt-to as the actually encrypt function would then - complain about no (regular) recipients. */ - for (sl = remusr; sl; sl = sl->next) - if (!(sl->flags & 1)) - do_add_recipient (&ctrl, sl->d, &recplist, 0); - if (!opt.no_encrypt_to) - { + + /* Build the recipient list. We first add the regular ones and then + the encrypt-to ones because the underlying function will silenty + ignore duplicates and we can't allow to keep a duplicate which is + flagged as encrypt-to as the actually encrypt function would then + complain about no (regular) recipients. */ for (sl = remusr; sl; sl = sl->next) - if ((sl->flags & 1)) - do_add_recipient (&ctrl, sl->d, &recplist, 1); + if (!(sl->flags & 1)) + do_add_recipient (&ctrl, sl->d, &recplist, 0); + if (!opt.no_encrypt_to) + { + for (sl = remusr; sl; sl = sl->next) + if ((sl->flags & 1)) + do_add_recipient (&ctrl, sl->d, &recplist, 1); + } } - + if (log_get_errorcount(0)) gpgsm_exit(1); /* must stop for invalid recipients */ - - fname = argc? *argv : NULL; switch (cmd) { + case aGPGConfList: + { /* List options and default values in the GPG Conf format. */ + char *filename; + + /* First the default configuration file. This is not an + option, but it is vital information for GPG Conf. */ + filename = make_filename (opt.homedir, "gpgsm.conf", NULL); + printf ("gpgconf-gpgsm.conf:\"%s\n", filename); + xfree (filename); + + printf ("verbose:\n" + "quiet:\n" + "debug-level:none\n" + "log-file:\n" + "force:\n" + "faked-system-time:\n" + "no-greeting:\n"); + } + break; + case aServer: if (debug_wait) { diff --git a/sm/keydb.c b/sm/keydb.c index f770135c1..ab30ba15d 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -188,6 +188,8 @@ keydb_add_resource (const char *url, int force, int secret) rc = gpg_error (gpg_err_code_from_errno (errno)); log_error (_("error creating keybox `%s': %s\n"), filename, strerror(errno)); + if (errno == ENOENT) + log_info (_("you may want to start the gpg-agent first\n")); goto leave; } -- cgit v1.2.3 From e588e13d7c85388db70b75c18273ba79715ecd3d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 17:00:56 +0000 Subject: Added empty components for gpgsm and scdaemon. --- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index bd99271d6..7796acbed 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-02-18 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c: Added empty components for gpgsm and scdaemon. + 2004-02-12 Werner Koch <wk@gnupg.org> * watchgnupg.c (main): Implement option "--". diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index efe2bf5a8..857ba0840 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -369,6 +369,20 @@ static gc_option_t gc_options_gpg_agent[] = }; +/* The options of the GC_COMPONENT_SCDAEMON component. */ +static gc_option_t gc_options_scdaemon[] = + { + GC_OPTION_NULL + }; + + +/* The options of the GC_COMPONENT_GPGSM component. */ +static gc_option_t gc_options_gpgsm[] = + { + GC_OPTION_NULL + }; + + /* The options of the GC_COMPONENT_DIRMNGR component. */ static gc_option_t gc_options_dirmngr[] = { @@ -479,6 +493,12 @@ typedef enum /* The GPG Agent. */ GC_COMPONENT_GPG_AGENT, + /* The Smardcard Daemon. */ + GC_COMPONENT_SCDAEMON, + + /* GPG for S/MIME. */ + GC_COMPONENT_GPGSM, + /* The LDAP Directory Manager for CRLs. */ GC_COMPONENT_DIRMNGR, @@ -507,6 +527,8 @@ static struct } gc_component[] = { { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, + { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon }, + { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm }, { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr } }; -- cgit v1.2.3 From 50ad027c9af9327699a5826db02c2d71cc01cff7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Feb 2004 18:38:50 +0000 Subject: * acinclude.m4: Removed macros to detect gpg-error, libgcrypt, libassuan and ksba as they are now distributed in m4/. * gpg-error.m4, libgcrypt.m4, libassuan.m4, ksba.m4: New. * Makefile.am: Distribute them --- ChangeLog | 5 ++ acinclude.m4 | 258 -------------------------------------------------------- m4/ChangeLog | 5 ++ m4/Makefile.am | 2 + m4/gpg-error.m4 | 56 ++++++++++++ m4/ksba.m4 | 76 +++++++++++++++++ m4/libassuan.m4 | 76 +++++++++++++++++ m4/libgcrypt.m4 | 75 ++++++++++++++++ 8 files changed, 295 insertions(+), 258 deletions(-) create mode 100644 m4/gpg-error.m4 create mode 100644 m4/ksba.m4 create mode 100644 m4/libassuan.m4 create mode 100644 m4/libgcrypt.m4 diff --git a/ChangeLog b/ChangeLog index 10d115c75..4ce7da6c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/acinclude.m4 b/acinclude.m4 index 6855cbee7..f6bbae78e 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -367,208 +367,6 @@ fi -dnl [copied from libgcrypt] -dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, -dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for liblibgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS -dnl -AC_DEFUN(AM_PATH_LIBGCRYPT, -[ AC_ARG_WITH(libgcrypt-prefix, - AC_HELP_STRING([--with-libgcrypt-prefix=PFX], - [prefix where LIBGCRYPT is installed (optional)]), - libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") - if test x$libgcrypt_config_prefix != x ; then - libgcrypt_config_args="$libgcrypt_config_args --prefix=$libgcrypt_config_prefix" - if test x${LIBGCRYPT_CONFIG+set} != xset ; then - LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config - fi - fi - - AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) - min_libgcrypt_version=ifelse([$1], ,0.4.4,$1) - AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) - ok=no - if test "$LIBGCRYPT_CONFIG" != "no" ; then - req_major=`echo $min_libgcrypt_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` - req_minor=`echo $min_libgcrypt_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` - req_micro=`echo $min_libgcrypt_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --version` - major=`echo $libgcrypt_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` - minor=`echo $libgcrypt_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` - micro=`echo $libgcrypt_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 - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs` - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - LIBGCRYPT_CFLAGS="" - LIBGCRYPT_LIBS="" - AC_MSG_RESULT(no) - ifelse([$3], , :, [$3]) - fi - AC_SUBST(LIBGCRYPT_CFLAGS) - AC_SUBST(LIBGCRYPT_LIBS) -]) - -dnl [copied from libassuan 0.0.1] -dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION, -dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS -dnl -AC_DEFUN(AM_PATH_LIBASSUAN, -[ AC_ARG_WITH(libassuan-prefix, - AC_HELP_STRING([--with-libassuan-prefix=PFX], - [prefix where LIBASSUAN is installed (optional)]), - libassuan_config_prefix="$withval", libassuan_config_prefix="") - if test x$libassuan_config_prefix != x ; then - libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix" - if test x${LIBASSUAN_CONFIG+set} != xset ; then - LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config - fi - fi - - AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no) - min_libassuan_version=ifelse([$1], ,0.0.1,$1) - AC_MSG_CHECKING(for LIBASSUAN - version >= $min_libassuan_version) - ok=no - if test "$LIBASSUAN_CONFIG" != "no" ; then - req_major=`echo $min_libassuan_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` - req_minor=`echo $min_libassuan_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` - req_micro=`echo $min_libassuan_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - libassuan_config_version=`$LIBASSUAN_CONFIG $libassuan_config_args --version` - major=`echo $libassuan_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` - minor=`echo $libassuan_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` - micro=`echo $libassuan_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 - LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags` - LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs` - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - LIBASSUAN_CFLAGS="" - LIBASSUAN_LIBS="" - AC_MSG_RESULT(no) - ifelse([$3], , :, [$3]) - fi - AC_SUBST(LIBASSUAN_CFLAGS) - AC_SUBST(LIBASSUAN_LIBS) -]) - - - -dnl [Copied from libksba] -dnl AM_PATH_KSBA([MINIMUM-VERSION, -dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for libksba and define KSBA_CFLAGS and KSBA_LIBS -dnl -AC_DEFUN(AM_PATH_KSBA, -[ AC_ARG_WITH(ksba-prefix, - AC_HELP_STRING([--with-ksba-prefix=PFX], - [prefix where KSBA is installed (optional)]), - ksba_config_prefix="$withval", ksba_config_prefix="") - if test x$ksba_config_prefix != x ; then - ksba_config_args="$ksba_config_args --prefix=$ksba_config_prefix" - if test x${KSBA_CONFIG+set} != xset ; then - KSBA_CONFIG=$ksba_config_prefix/bin/ksba-config - fi - fi - - AC_PATH_PROG(KSBA_CONFIG, ksba-config, no) - min_ksba_version=ifelse([$1], ,0.4.4,$1) - AC_MSG_CHECKING(for KSBA - version >= $min_ksba_version) - ok=no - if test "$KSBA_CONFIG" != "no" ; then - req_major=`echo $min_ksba_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` - req_minor=`echo $min_ksba_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` - req_micro=`echo $min_ksba_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - ksba_config_version=`$KSBA_CONFIG $ksba_config_args --version` - major=`echo $ksba_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` - minor=`echo $ksba_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` - micro=`echo $ksba_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 - KSBA_CFLAGS=`$KSBA_CONFIG $ksba_config_args --cflags` - KSBA_LIBS=`$KSBA_CONFIG $ksba_config_args --libs` - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - KSBA_CFLAGS="" - KSBA_LIBS="" - AC_MSG_RESULT(no) - ifelse([$3], , :, [$3]) - fi - AC_SUBST(KSBA_CFLAGS) - AC_SUBST(KSBA_LIBS) -]) - - - 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 @@ -636,59 +434,3 @@ AC_DEFUN(AM_PATH_OPENSC, ]) -dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, -dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS -dnl -AC_DEFUN(AM_PATH_GPG_ERROR, -[ AC_ARG_WITH(gpg-error-prefix, - AC_HELP_STRING([--with-gpg-error-prefix=PFX], - [prefix where GPG Error is installed (optional)]), - gpg_error_config_prefix="$withval", gpg_error_config_prefix="") - if test x$gpg_error_config_prefix != x ; then - gpg_error_config_args="$gpg_error_config_args --prefix=$gpg_error_config_prefix" - if test x${GPG_ERROR_CONFIG+set} != xset ; then - GPG_ERROR_CONFIG=$gpg_error_config_prefix/bin/gpg-error-config - fi - fi - - AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) - min_gpg_error_version=ifelse([$1], ,0.0,$1) - AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) - ok=no - if test "$GPG_ERROR_CONFIG" != "no" ; then - req_major=`echo $min_gpg_error_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` - req_minor=`echo $min_gpg_error_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` - gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` - major=`echo $gpg_error_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` - minor=`echo $gpg_error_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` - if test "$major" -gt "$req_major"; then - ok=yes - else - if test "$major" -eq "$req_major"; then - if test "$minor" -ge "$req_minor"; then - ok=yes - fi - fi - fi - fi - if test $ok = yes; then - GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` - GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - GPG_ERROR_CFLAGS="" - GPG_ERROR_LIBS="" - AC_MSG_RESULT(no) - ifelse([$3], , :, [$3]) - fi - AC_SUBST(GPG_ERROR_CFLAGS) - AC_SUBST(GPG_ERROR_LIBS) -]) - - diff --git a/m4/ChangeLog b/m4/ChangeLog index 84a288341..d6ac513e5 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,8 @@ +2004-02-18 Werner Koch <wk@gnupg.org> + + * gpg-error.m4, libgcrypt.m4, libassuan.m4, ksba.m4: New. + * Makefile.am: Distribute them + 2003-04-29 gettextize <bug-gnu-gettext@gnu.org> * codeset.m4: New file, from gettext-0.11.5. diff --git a/m4/Makefile.am b/m4/Makefile.am index 42126ac73..0eb02f694 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -1 +1,3 @@ EXTRA_DIST = codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 + +EXTRA_DIST += gpg-error.m4 libgcrypt.m4 libassuan.m4 ksba.m4 diff --git a/m4/gpg-error.m4 b/m4/gpg-error.m4 new file mode 100644 index 000000000..931630b14 --- /dev/null +++ b/m4/gpg-error.m4 @@ -0,0 +1,56 @@ +dnl Autoconf macros for libgpg-error + +dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS +dnl +AC_DEFUN(AM_PATH_GPG_ERROR, +[ AC_ARG_WITH(gpg-error-prefix, + AC_HELP_STRING([--with-gpg-error-prefix=PFX], + [prefix where GPG Error is installed (optional)]), + gpg_error_config_prefix="$withval", gpg_error_config_prefix="") + if test x$gpg_error_config_prefix != x ; then + if test x${GPG_ERROR_CONFIG+set} != xset ; then + GPG_ERROR_CONFIG=$gpg_error_config_prefix/bin/gpg-error-config + fi + fi + + AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) + min_gpg_error_version=ifelse([$1], ,0.0,$1) + AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) + ok=no + if test "$GPG_ERROR_CONFIG" != "no" ; then + req_major=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` + major=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -ge "$req_minor"; then + ok=yes + fi + fi + fi + fi + if test $ok = yes; then + GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` + GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPG_ERROR_CFLAGS="" + GPG_ERROR_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPG_ERROR_CFLAGS) + AC_SUBST(GPG_ERROR_LIBS) +]) + diff --git a/m4/ksba.m4 b/m4/ksba.m4 new file mode 100644 index 000000000..c59ac8024 --- /dev/null +++ b/m4/ksba.m4 @@ -0,0 +1,76 @@ +# ksba.m4 - autoconf macro to detect ksba +# Copyright (C) 2002 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 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. + + +dnl AM_PATH_KSBA([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libksba and define KSBA_CFLAGS and KSBA_LIBS +dnl +AC_DEFUN(AM_PATH_KSBA, +[ AC_ARG_WITH(ksba-prefix, + AC_HELP_STRING([--with-ksba-prefix=PFX], + [prefix where KSBA is installed (optional)]), + ksba_config_prefix="$withval", ksba_config_prefix="") + if test x$ksba_config_prefix != x ; then + ksba_config_args="$ksba_config_args --prefix=$ksba_config_prefix" + if test x${KSBA_CONFIG+set} != xset ; then + KSBA_CONFIG=$ksba_config_prefix/bin/ksba-config + fi + fi + + AC_PATH_PROG(KSBA_CONFIG, ksba-config, no) + min_ksba_version=ifelse([$1], ,0.4.4,$1) + AC_MSG_CHECKING(for KSBA - version >= $min_ksba_version) + ok=no + if test "$KSBA_CONFIG" != "no" ; then + req_major=`echo $min_ksba_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_ksba_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_ksba_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + ksba_config_version=`$KSBA_CONFIG $ksba_config_args --version` + major=`echo $ksba_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $ksba_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $ksba_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 + KSBA_CFLAGS=`$KSBA_CONFIG $ksba_config_args --cflags` + KSBA_LIBS=`$KSBA_CONFIG $ksba_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + KSBA_CFLAGS="" + KSBA_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(KSBA_CFLAGS) + AC_SUBST(KSBA_LIBS) +]) diff --git a/m4/libassuan.m4 b/m4/libassuan.m4 new file mode 100644 index 000000000..2afc69737 --- /dev/null +++ b/m4/libassuan.m4 @@ -0,0 +1,76 @@ +dnl Autoconf macros for libassuan +dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc. +dnl +dnl This file is free software; as a special exception the author gives +dnl unlimited permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl +dnl This file is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS +dnl +AC_DEFUN(AM_PATH_LIBASSUAN, +[ AC_ARG_WITH(libassuan-prefix, + AC_HELP_STRING([--with-libassuan-prefix=PFX], + [prefix where LIBASSUAN is installed (optional)]), + libassuan_config_prefix="$withval", libassuan_config_prefix="") + if test x$libassuan_config_prefix != x ; then + libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix" + if test x${LIBASSUAN_CONFIG+set} != xset ; then + LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config + fi + fi + + AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no) + min_libassuan_version=ifelse([$1], ,0.0.1,$1) + AC_MSG_CHECKING(for LIBASSUAN - version >= $min_libassuan_version) + ok=no + if test "$LIBASSUAN_CONFIG" != "no" ; then + req_major=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + libassuan_config_version=`$LIBASSUAN_CONFIG $libassuan_config_args --version` + major=`echo $libassuan_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $libassuan_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $libassuan_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 + LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags` + LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + LIBASSUAN_CFLAGS="" + LIBASSUAN_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBASSUAN_CFLAGS) + AC_SUBST(LIBASSUAN_LIBS) +]) diff --git a/m4/libgcrypt.m4 b/m4/libgcrypt.m4 new file mode 100644 index 000000000..0e8ab5803 --- /dev/null +++ b/m4/libgcrypt.m4 @@ -0,0 +1,75 @@ +dnl Autoconf macros for libgcrypt +dnl Copyright (C) 2002 Free Software Foundation, Inc. +dnl +dnl This file is free software; as a special exception the author gives +dnl unlimited permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl +dnl This file is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for liblibgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS +dnl +AC_DEFUN(AM_PATH_LIBGCRYPT, +[ AC_ARG_WITH(libgcrypt-prefix, + AC_HELP_STRING([--with-libgcrypt-prefix=PFX], + [prefix where LIBGCRYPT is installed (optional)]), + libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") + if test x$libgcrypt_config_prefix != x ; then + if test x${LIBGCRYPT_CONFIG+set} != xset ; then + LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config + fi + fi + + AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) + min_libgcrypt_version=ifelse([$1], ,0.4.4,$1) + AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) + ok=no + if test "$LIBGCRYPT_CONFIG" != "no" ; then + req_major=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libgcrypt_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --version` + major=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $libgcrypt_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + micro=`echo $libgcrypt_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 + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + LIBGCRYPT_CFLAGS="" + LIBGCRYPT_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBGCRYPT_CFLAGS) + AC_SUBST(LIBGCRYPT_LIBS) +]) -- cgit v1.2.3 From a1b487a17a084b3d8d652d4feabb7de2d67ad292 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 19 Feb 2004 16:26:32 +0000 Subject: * protect-tool.c: New options --have-cert and --prompt. (export_p12_file): Read a certificate from STDIN and pass it to p12_build. Detect a keygrip and construct the filename in that case. Unprotcet a key if needed. Print error messages for key formats we can't handle. (release_passphrase): New. (get_passphrase): New arg PROMPTNO. Return the allocated string. Changed all callers. * minip12.c: Revamped the build part. (p12_build): New args CERT and CERTLEN. * simple-pwquery.c (agent_open): Don't mangle INFOSTR. * export.c (export_p12, popen_protect_tool) (gpgsm_p12_export): New. * gpgsm.c (main): New command --export-secret-key-p12. --- NEWS | 2 + agent/ChangeLog | 14 ++ agent/minip12.c | 559 ++++++++++++++++++++++++++++++++++++++---------- agent/minip12.h | 5 +- agent/protect-tool.c | 218 +++++++++++++++++-- common/ChangeLog | 4 + common/simple-pwquery.c | 7 +- doc/gpgsm.texi | 8 + scd/command.c | 2 +- sm/ChangeLog | 6 + sm/export.c | 371 +++++++++++++++++++++++++++++++- sm/gpgsm.c | 10 + sm/gpgsm.h | 1 + sm/import.c | 2 +- 14 files changed, 1062 insertions(+), 147 deletions(-) diff --git a/NEWS b/NEWS index c0a8d6026..3d6837d2f 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ Noteworthy changes in version 1.9.5 * [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 requests. diff --git a/agent/ChangeLog b/agent/ChangeLog index ffd48f59e..241a60964 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,17 @@ +2004-02-19 Werner Koch <wk@gnupg.org> + + * protect-tool.c: New options --have-cert and --prompt. + (export_p12_file): Read a certificate from STDIN and pass it to + p12_build. Detect a keygrip and construct the filename in that + case. Unprotcet a key if needed. Print error messages for key + formats we can't handle. + (release_passphrase): New. + (get_passphrase): New arg PROMPTNO. Return the allocated + string. Changed all callers. + + * minip12.c: Revamped the build part. + (p12_build): New args CERT and CERTLEN. + 2004-02-18 Werner Koch <wk@gnupg.org> * protect-tool.c (main): Setup the used character set. diff --git a/agent/minip12.c b/agent/minip12.c index 13b6aa3eb..e32a40de2 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -106,12 +106,19 @@ static unsigned char const oid_rsaEncryption[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; -static unsigned char const data_3desiter1024[30] = { +static unsigned char const data_3desiter2048[30] = { 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E, 0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x02, 0x02, 0x04, 0x00 }; -#define DATA_3DESITER1024_SALT_OFF 18 + 0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 }; +#define DATA_3DESITER2048_SALT_OFF 18 + +static unsigned char const data_rc2iter2048[30] = { + 0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06, 0x30, 0x0E, + 0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 }; +#define DATA_RC2ITER2048_SALT_OFF 18 struct buffer_s @@ -346,17 +353,22 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, if (rc) { log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(rc)); + wipememory (buffer, length); return; } if (set_key_iv (chd, salt, iter, pw, cipher_algo == GCRY_CIPHER_RFC2268_40? 5:24)) - goto leave; + { + wipememory (buffer, length); + goto leave; + } rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0) : gcry_cipher_decrypt (chd, buffer, length, NULL, 0); if (rc) { + wipememory (buffer, length); log_error ( "en/de-crytion failed: %s\n", gpg_strerror (rc)); goto leave; } @@ -474,6 +486,13 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, startoffset = 0; buffer = p = plain; +/* { */ +/* FILE *fp = fopen ("tmp-rc2-plain.der", "wb"); */ +/* if (!fp || fwrite (p, n, 1, fp) != 1) */ +/* exit (2); */ +/* fclose (fp); */ +/* } */ + where = "outer.outer.seq"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -708,13 +727,6 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, startoffset = 0; buffer = p = plain; -/* { */ -/* FILE *fp = fopen ("tmp-3des-plain.der", "wb"); */ -/* if (!fp || fwrite (p, n, 1, fp) != 1) */ -/* exit (2); */ -/* fclose (fp); */ -/* } */ - where = "decrypted-text"; if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) goto bailout; @@ -970,37 +982,48 @@ create_final (struct buffer_s *sequences, size_t *r_length) { int i; size_t needed = 0; - size_t n, outseqlen, notsooutseqlen, out0taglen, octstrlen, inseqlen; + size_t len[8], n; unsigned char *result, *p; size_t resultlen; + /* 8 steps to create the pkcs#12 Krampf. */ + + /* 7. All the buffers. */ for (i=0; sequences[i].buffer; i++) needed += sequences[i].length; - /* This goes into a sequences. */ - inseqlen = needed; + + /* 6. This goes into a sequences. */ + len[6] = needed; n = compute_tag_length (needed); needed += n; - /* And encapsulate all in an octet string. */ - octstrlen = needed; + + /* 5. Encapsulate all in an octet string. */ + len[5] = needed; n = compute_tag_length (needed); needed += n; - /* And tag it with [0]. */ - out0taglen = needed; + + /* 4. And tag it with [0]. */ + len[4] = needed; n = compute_tag_length (needed); needed += n; - /* Prepend an data OID. */ + + /* 3. Prepend an data OID. */ needed += 2 + DIM (oid_data); - /* This all into a sequences. */ - notsooutseqlen = needed; + + /* 2. Put all into a sequences. */ + len[2] = needed; n = compute_tag_length (needed); needed += n; - /* Prepend the version integer 3. */ + + /* 1. Prepend the version integer 3. */ needed += 3; - /* And the final sequence. */ - outseqlen = needed; + + /* 0. And the final outer sequence. */ + len[0] = needed; n = compute_tag_length (needed); needed += n; + /* Allocate a buffer. */ result = gcry_malloc (needed); if (!result) { @@ -1009,25 +1032,32 @@ create_final (struct buffer_s *sequences, size_t *r_length) } p = result; - /* Store the very outer sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, outseqlen); - /* Store the version integer 3. */ + /* 0. Store the very outer sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[0]); + + /* 1. Store the version integer 3. */ *p++ = TAG_INTEGER; *p++ = 1; - *p++ = 3; - /* Store another sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, notsooutseqlen); - /* Store the data OID. */ + *p++ = 3; + + /* 2. Store another sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[2]); + + /* 3. Store the data OID. */ p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); memcpy (p, oid_data, DIM (oid_data)); p += DIM (oid_data); - /* Next comes a context tag. */ - p = store_tag_length (p, 0xa0, out0taglen); - /* And an octet string. */ - p = store_tag_length (p, TAG_OCTET_STRING, octstrlen); - /* And the inner sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, inseqlen); - /* And append all the buffers. */ + + /* 4. Next comes a context tag. */ + p = store_tag_length (p, 0xa0, len[4]); + + /* 5. And an octet string. */ + p = store_tag_length (p, TAG_OCTET_STRING, len[5]); + + /* 6. And the inner sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[6]); + + /* 7. Append all the buffers. */ for (i=0; sequences[i].buffer; i++) { memcpy (p, sequences[i].buffer, sequences[i].length); @@ -1044,20 +1074,38 @@ create_final (struct buffer_s *sequences, size_t *r_length) } -/* Expect the RSA key parameters in KPARMS and a password in - PW. Create a PKCS structure from it and return it as well as the - length in R_LENGTH; return NULL in case of an error. */ -unsigned char * -p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length) +/* Build a DER encoded SEQUENCE with the key: + + SEQUENCE { + INTEGER 0 + SEQUENCE { + OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) + NULL + } + OCTET STRING, encapsulates { + SEQUENCE { + INTEGER 0 + INTEGER + INTEGER + INTEGER + INTEGER + INTEGER + INTEGER + INTEGER + INTEGER + } + } + } +*/ + +static unsigned char * +build_key_sequence (gcry_mpi_t *kparms, size_t *r_length) { int rc, i; size_t needed, n; - unsigned char *plain, *p, *cipher; - size_t plainlen, cipherlen; + unsigned char *plain, *p; + size_t plainlen; size_t outseqlen, oidseqlen, octstrlen, inseqlen; - size_t out0taglen, in0taglen, outoctstrlen; - size_t aseq1len, aseq2len, aseq3len; - char salt[8]; needed = 3; /* The version(?) integer of value 0. */ for (i=0; kparms[i]; i++) @@ -1165,105 +1213,380 @@ p12_build (gcry_mpi_t *kparms, const char *pw, size_t *r_length) for (;(plainlen % 8); plainlen++) *p++ = n; -/* { */ -/* FILE *fp = fopen("inner-out.der", "wb"); */ -/* fwrite (plain, 1, plainlen, fp); */ -/* fclose (fp); */ -/* } */ + *r_length = plainlen; + return plain; +} + + + +static unsigned char * +build_key_bag (unsigned char *buffer, size_t buflen, char *salt, + size_t *r_length) +{ + size_t len[11], needed; + unsigned char *p, *keybag; + size_t keybaglen; + + /* Walk 11 steps down to collect the info: */ + + /* 10. The data goes into an octet string. */ + needed = compute_tag_length (buflen); + needed += buflen; + /* 9. Prepend the algorithm identifier. */ + needed += DIM (data_3desiter2048); - /* Encrypt it and prepend a lot of stupid things. */ - gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); - crypt_block (plain, plainlen, salt, 1024, pw, GCRY_CIPHER_3DES, 1); - /* the data goes into an octet string. */ - needed = compute_tag_length (plainlen); - needed += plainlen; - /* we prepend the the algorithm identifier (we use a pre-encoded one)*/ - needed += DIM (data_3desiter1024); - /* we put a sequence around. */ - aseq3len = needed; + /* 8. Put a sequence around. */ + len[8] = needed; needed += compute_tag_length (needed); - /* Prepend it with a [0] tag. */ - in0taglen = needed; + + /* 7. Prepend a [0] tag. */ + len[7] = needed; needed += compute_tag_length (needed); - /* Prepend that shroudedKeyBag OID. */ + + /* 6. Prepend the shroudedKeyBag OID. */ needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); - /* Put it all into two sequence. */ - aseq2len = needed; + + /* 5+4. Put all into two sequences. */ + len[5] = needed; needed += compute_tag_length ( needed); - aseq1len = needed; + len[4] = needed; needed += compute_tag_length (needed); - /* This all goes into an octet string. */ - outoctstrlen = needed; + + /* 3. This all goes into an octet string. */ + len[3] = needed; needed += compute_tag_length (needed); - /* Prepend it with a [0] tag. */ - out0taglen = needed; + + /* 2. Prepend another [0] tag. */ + len[2] = needed; needed += compute_tag_length (needed); - /* Prepend the data OID. */ + + /* 1. Prepend the data OID. */ needed += 2 + DIM (oid_data); - /* And a sequence. */ - outseqlen = needed; + + /* 0. Prepend another sequence. */ + len[0] = needed; needed += compute_tag_length (needed); - cipher = gcry_malloc (needed); - if (!cipher) + /* Now that we have all length information, allocate a buffer. */ + p = keybag = gcry_malloc (needed); + if (!keybag) { log_error ("error allocating buffer\n"); - gcry_free (plain); return NULL; } - p = cipher; - /* Store the first sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, outseqlen); - /* Store the data OID. */ + + /* Walk 11 steps up to store the data. */ + + /* 0. Store the first sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[0]); + + /* 1. Store the data OID. */ p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); memcpy (p, oid_data, DIM (oid_data)); p += DIM (oid_data); - /* Next comes a context tag. */ - p = store_tag_length (p, 0xa0, out0taglen); - /* And an octet string. */ - p = store_tag_length (p, TAG_OCTET_STRING, outoctstrlen); - /* Two sequences. */ - p = store_tag_length (p, TAG_SEQUENCE, aseq1len); - p = store_tag_length (p, TAG_SEQUENCE, aseq2len); - /* Store the shroudedKeyBag OID. */ + + /* 2. Store a [0] tag. */ + p = store_tag_length (p, 0xa0, len[2]); + + /* 3. And an octet string. */ + p = store_tag_length (p, TAG_OCTET_STRING, len[3]); + + /* 4+5. Two sequences. */ + p = store_tag_length (p, TAG_SEQUENCE, len[4]); + p = store_tag_length (p, TAG_SEQUENCE, len[5]); + + /* 6. Store the shroudedKeyBag OID. */ p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag, DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); - /* Next comes a context tag. */ - p = store_tag_length (p, 0xa0, in0taglen); - /* And a sequence. */ - p = store_tag_length (p, TAG_SEQUENCE, aseq3len); - /* Now for the pre-encoded algorithm indentifier and the salt. */ - memcpy (p, data_3desiter1024, DIM (data_3desiter1024)); - memcpy (p + DATA_3DESITER1024_SALT_OFF, salt, 8); - p += DIM (data_3desiter1024); - /* And finally the octet string with the encrypted data. */ - p = store_tag_length (p, TAG_OCTET_STRING, plainlen); - memcpy (p, plain, plainlen); - p += plainlen; - cipherlen = p - cipher; + + /* 7. Store a [0] tag. */ + p = store_tag_length (p, 0xa0, len[7]); + + /* 8. Store a sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[8]); + + /* 9. Now for the pre-encoded algorithm identifier and the salt. */ + memcpy (p, data_3desiter2048, DIM (data_3desiter2048)); + memcpy (p + DATA_3DESITER2048_SALT_OFF, salt, 8); + p += DIM (data_3desiter2048); + + /* 10. And finally the octet string with the encrypted data. */ + p = store_tag_length (p, TAG_OCTET_STRING, buflen); + memcpy (p, buffer, buflen); + p += buflen; + keybaglen = p - keybag; - if (needed != cipherlen) - log_debug ("length mismatch: %u, %u\n", needed, cipherlen); - gcry_free (plain); + if (needed != keybaglen) + log_debug ("length mismatch: %u, %u\n", needed, keybaglen); + + *r_length = keybaglen; + return keybag; +} + + +static unsigned char * +build_cert_bag (unsigned char *buffer, size_t buflen, char *salt, + size_t *r_length) +{ + size_t len[9], needed; + unsigned char *p, *certbag; + size_t certbaglen; + + /* Walk 9 steps down to collect the info: */ + + /* 8. The data goes into an octet string. */ + needed = compute_tag_length (buflen); + needed += buflen; + + /* 7. The algorithm identifier. */ + needed += DIM (data_rc2iter2048); + + /* 6. The data OID. */ + needed += 2 + DIM (oid_data); + + /* 5. A sequence. */ + len[5] = needed; + needed += compute_tag_length ( needed); + + /* 4. An integer. */ + needed += 3; + + /* 3. A sequence. */ + len[3] = needed; + needed += compute_tag_length (needed); + + /* 2. A [0] tag. */ + len[2] = needed; + needed += compute_tag_length (needed); + + /* 1. The encryptedData OID. */ + needed += 2 + DIM (oid_encryptedData); + + /* 0. The first sequence. */ + len[0] = needed; + needed += compute_tag_length (needed); + + /* Now that we have all length information, allocate a buffer. */ + p = certbag = gcry_malloc (needed); + if (!certbag) + { + log_error ("error allocating buffer\n"); + return NULL; + } + + /* Walk 9 steps up to store the data. */ + + /* 0. Store the first sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[0]); + + /* 1. Store the encryptedData OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_encryptedData)); + memcpy (p, oid_encryptedData, DIM (oid_encryptedData)); + p += DIM (oid_encryptedData); + + /* 2. Store a [0] tag. */ + p = store_tag_length (p, 0xa0, len[2]); + + /* 3. Store a sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[3]); + + /* 4. Store the integer 0. */ + *p++ = TAG_INTEGER; + *p++ = 1; + *p++ = 0; + + /* 5. Store a sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[5]); + + /* 6. Store the data OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data)); + memcpy (p, oid_data, DIM (oid_data)); + p += DIM (oid_data); + + /* 7. Now for the pre-encoded algorithm identifier and the salt. */ + memcpy (p, data_rc2iter2048, DIM (data_rc2iter2048)); + memcpy (p + DATA_RC2ITER2048_SALT_OFF, salt, 8); + p += DIM (data_rc2iter2048); + + /* 8. And finally the [0] tag with the encrypted data. */ + p = store_tag_length (p, 0xa0, buflen); + memcpy (p, buffer, buflen); + p += buflen; + certbaglen = p - certbag; + + if (needed != certbaglen) + log_debug ("length mismatch: %u, %u\n", needed, certbaglen); + + *r_length = certbaglen; + return certbag; +} + + +static unsigned char * +build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) +{ + size_t len[8], needed, n; + unsigned char *p, *certseq; + size_t certseqlen; + + /* Walk 8 steps down to collect the info: */ + + /* 7. The data goes into an octet string. */ + needed = compute_tag_length (buflen); + needed += buflen; + + /* 6. A [0] tag. */ + len[6] = needed; + needed += compute_tag_length (needed); + + /* 5. An OID. */ + needed += 2 + DIM (oid_x509Certificate_for_pkcs_12); + + /* 4. A sequence. */ + len[4] = needed; + needed += compute_tag_length (needed); + + /* 3. A [0] tag. */ + len[3] = needed; + needed += compute_tag_length (needed); + + /* 2. An OID. */ + needed += 2 + DIM (oid_pkcs_12_CertBag); + + /* 1. A sequence. */ + len[1] = needed; + needed += compute_tag_length (needed); + + /* 0. The first sequence. */ + len[0] = needed; + needed += compute_tag_length (needed); + + /* Now that we have all length information, allocate a buffer. */ + p = certseq = gcry_malloc (needed + 8 /*(for padding)*/); + if (!certseq) + { + log_error ("error allocating buffer\n"); + return NULL; + } + + /* Walk 8 steps up to store the data. */ + + /* 0. Store the first sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[0]); + + /* 1. Store the second sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[1]); + + /* 2. Store the pkcs12-cert-bag OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_pkcs_12_CertBag)); + memcpy (p, oid_pkcs_12_CertBag, DIM (oid_pkcs_12_CertBag)); + p += DIM (oid_pkcs_12_CertBag); + + /* 3. Store a [0] tag. */ + p = store_tag_length (p, 0xa0, len[3]); + + /* 4. Store a sequence. */ + p = store_tag_length (p, TAG_SEQUENCE, len[4]); + + /* 5. Store the x509Certificate OID. */ + p = store_tag_length (p, TAG_OBJECT_ID, + DIM (oid_x509Certificate_for_pkcs_12)); + memcpy (p, oid_x509Certificate_for_pkcs_12, + DIM (oid_x509Certificate_for_pkcs_12)); + p += DIM (oid_x509Certificate_for_pkcs_12); + + /* 6. Store a [0] tag. */ + p = store_tag_length (p, 0xa0, len[6]); + + /* 7. And finally the octet string with the actual certificate. */ + p = store_tag_length (p, TAG_OCTET_STRING, buflen); + memcpy (p, buffer, buflen); + p += buflen; + certseqlen = p - certseq; + + if (needed != certseqlen) + log_debug ("length mismatch: %u, %u\n", needed, certseqlen); + + /* Append some pad characters; we already allocated extra space. */ + n = 8 - certseqlen % 8; + for (;(certseqlen % 8); certseqlen++) + *p++ = n; + + *r_length = certseqlen; + return certseq; +} + + +/* Expect the RSA key parameters in KPARMS and a password in + PW. Create a PKCS structure from it and return it as well as the + length in R_LENGTH; return NULL in case of an error. */ +unsigned char * +p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, + const char *pw, size_t *r_length) +{ + unsigned char *buffer; + size_t n, buflen; + char salt[8]; + struct buffer_s seqlist[2]; + int seqlistidx = 0; + + if (cert && certlen) + { + /* Encode the certificate. */ + buffer = build_cert_sequence (cert, certlen, &buflen); + if (!buffer) + goto failure; + + /* Encrypt it. */ + gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); + crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_RFC2268_40, 1); + + /* Encode the encrypted stuff into a bag. */ + seqlist[seqlistidx].buffer = build_cert_bag (buffer, buflen, salt, &n); + seqlist[seqlistidx].length = n; + gcry_free (buffer); + buffer = NULL; + if (!seqlist[seqlistidx].buffer) + goto failure; + seqlistidx++; + } + + if (kparms) + { + /* Encode the key. */ + buffer = build_key_sequence (kparms, &buflen); + if (!buffer) + goto failure; + + /* Encrypt it. */ + gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); + crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_3DES, 1); + + /* Encode the encrypted stuff into a bag. */ + seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, &n); + seqlist[seqlistidx].length = n; + gcry_free (buffer); + buffer = NULL; + if (!seqlist[seqlistidx].buffer) + goto failure; + seqlistidx++; + } - { - struct buffer_s seqlist[2]; + seqlist[seqlistidx].buffer = NULL; + seqlist[seqlistidx].length = 0; - seqlist[0].buffer = cipher; - seqlist[0].length = cipherlen; - seqlist[1].buffer = NULL; - seqlist[1].length = 0; + buffer = create_final (seqlist, &buflen); - cipher = create_final (seqlist, &cipherlen); - gcry_free (seqlist[0].buffer); - } + failure: + for ( ; seqlistidx; seqlistidx--) + gcry_free (seqlist[seqlistidx].buffer); - *r_length = cipherlen; - return cipher; + *r_length = buffer? buflen : 0; + return buffer; } diff --git a/agent/minip12.h b/agent/minip12.h index 61a597926..2fbb490d7 100644 --- a/agent/minip12.h +++ b/agent/minip12.h @@ -28,8 +28,9 @@ gcry_mpi_t *p12_parse (const unsigned char *buffer, size_t length, void (*certcb)(void*, const unsigned char*, size_t), void *certcbarg); -unsigned char *p12_build (gcry_mpi_t *kparms, const char *pw, - size_t *r_length); +unsigned char *p12_build (gcry_mpi_t *kparms, + unsigned char *cert, size_t certlen, + const char *pw, size_t *r_length); #endif /*MINIP12_H*/ diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 59f6c6711..1bc7144be 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -1,5 +1,5 @@ /* protect-tool.c - A tool to test the secret key protection - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -54,8 +54,10 @@ enum cmd_and_opt_values oP12Export, oStore, oForce, + oHaveCert, oNoFailOnExist, oHomedir, + oPrompt, aTest }; @@ -75,9 +77,12 @@ static int opt_armor; static int opt_store; static int opt_force; static int opt_no_fail_on_exist; -static const char *passphrase; +static int opt_have_cert; +static const char *opt_passphrase; +static char *opt_prompt; -static const char *get_passphrase (void); +static char *get_passphrase (int promptno); +static void release_passphrase (char *pw); static int store_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); @@ -97,10 +102,12 @@ static ARGPARSE_OPTS opts[] = { { oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"}, { oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"}, + { oHaveCert, "have-cert", 0, "certificate to export provided on STDIN"}, { oStore, "store", 0, "store the created key in the appropriate place"}, { oForce, "force", 0, "force overwriting"}, { oNoFailOnExist, "no-fail-on-exist", 0, "@" }, { oHomedir, "homedir", 2, "@" }, + { oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"}, {0} }; @@ -328,12 +335,15 @@ read_and_protect (const char *fname) unsigned char *key; unsigned char *result; size_t resultlen; + char *pw; key = read_key (fname); if (!key) return; - rc = agent_protect (key, get_passphrase (), &result, &resultlen); + pw = get_passphrase (1); + rc = agent_protect (key, pw, &result, &resultlen); + release_passphrase (pw); xfree (key); if (rc) { @@ -363,12 +373,14 @@ read_and_unprotect (const char *fname) unsigned char *key; unsigned char *result; size_t resultlen; + char *pw; key = read_key (fname); if (!key) return; - rc = agent_unprotect (key, get_passphrase (), &result, &resultlen); + rc = agent_unprotect (key, (pw=get_passphrase (1)), &result, &resultlen); + release_passphrase (pw); xfree (key); if (rc) { @@ -632,6 +644,7 @@ import_p12_file (const char *fname) gcry_sexp_t s_key; unsigned char *key; unsigned char grip[20]; + char *pw; /* fixme: we should release some stuff on error */ @@ -639,8 +652,9 @@ import_p12_file (const char *fname) if (!buf) return; - kparms = p12_parse (buf, buflen, get_passphrase (), + kparms = p12_parse (buf, buflen, (pw=get_passphrase (0)), import_p12_cert_cb, NULL); + release_passphrase (pw); xfree (buf); if (!kparms) { @@ -714,7 +728,8 @@ import_p12_file (const char *fname) gcry_sexp_release (s_key); - rc = agent_protect (key, get_passphrase (), &result, &resultlen); + rc = agent_protect (key, (pw=get_passphrase (0)), &result, &resultlen); + release_passphrase (pw); xfree (key); if (rc) { @@ -797,27 +812,113 @@ sexp_to_kparms (gcry_sexp_t sexp) } +/* Check whether STRING is a KEYGRIP, i.e has the correct length and + does only consist of uppercase hex characters. */ +static int +is_keygrip (const char *string) +{ + int i; + + for(i=0; string[i] && i < 41; i++) + if (!strchr("01234567890ABCDEF", string[i])) + return 0; + return i == 40; +} static void export_p12_file (const char *fname) { + int rc; gcry_mpi_t kparms[9], *kp; unsigned char *key; size_t keylen; gcry_sexp_t private; struct rsa_secret_key_s sk; int i; + unsigned char *cert = NULL; + size_t certlen = 0; + int keytype; + size_t keylen_for_wipe = 0; + char *pw; + + if ( is_keygrip (fname) ) + { + char hexgrip[40+4+1]; + char *p; - key = read_key (fname); + assert (strlen(fname) == 40); + strcpy (stpcpy (hexgrip, fname), ".key"); + + p = make_filename (opt_homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); + key = read_key (p); + xfree (p); + } + else + key = read_key (fname); + if (!key) return; + keytype = agent_private_key_type (key); + if (keytype == PRIVATE_KEY_PROTECTED) + { + unsigned char *tmpkey; + size_t tmplen; + + rc = agent_unprotect (key, (pw=get_passphrase (1)), &tmpkey, &tmplen); + release_passphrase (pw); + if (rc) + { + log_error ("unprotecting key `%s' failed: %s\n", + fname, gpg_strerror (rc)); + xfree (key); + return; + } + xfree (key); + key = tmpkey; + keylen_for_wipe = tmplen; + + keytype = agent_private_key_type (key); + } + + if (keytype == PRIVATE_KEY_SHADOWED) + { + log_error ("`%s' is a shadowed private key - can't export it\n", fname); + wipememory (key, keylen_for_wipe); + xfree (key); + return; + } + else if (keytype != PRIVATE_KEY_CLEAR) + { + log_error ("\%s' is not a private key\n", fname); + wipememory (key, keylen_for_wipe); + xfree (key); + return; + } + + + if (opt_have_cert) + { + cert = read_file ("-", &certlen); + if (!cert) + { + wipememory (key, keylen_for_wipe); + xfree (key); + return; + } + } + + if (gcry_sexp_new (&private, key, 0, 0)) { log_error ("gcry_sexp_new failed\n"); + wipememory (key, keylen_for_wipe); + xfree (key); + xfree (cert); return; } + wipememory (key, keylen_for_wipe); xfree (key); kp = sexp_to_kparms (private); @@ -825,6 +926,7 @@ export_p12_file (const char *fname) if (!kp) { log_error ("error converting key parameters\n"); + xfree (cert); return; } sk.n = kp[0]; @@ -850,7 +952,9 @@ export_p12_file (const char *fname) kparms[7] = sk.u; kparms[8] = NULL; - key = p12_build (kparms, get_passphrase (), &keylen); + key = p12_build (kparms, cert, certlen, (pw=get_passphrase (0)), &keylen); + release_passphrase (pw); + xfree (cert); for (i=0; i < 8; i++) gcry_mpi_release (kparms[i]); if (!key) @@ -861,6 +965,54 @@ export_p12_file (const char *fname) } + +/* Do the percent and plus/space unescaping in place and return the + length of the valid buffer. */ +static size_t +percent_plus_unescape (unsigned char *string) +{ + unsigned char *p = string; + size_t n = 0; + + while (*string) + { + if (*string == '%' && string[1] && string[2]) + { + string++; + *p++ = xtoi_2 (string); + n++; + string+= 2; + } + else if (*string == '+') + { + *p++ = ' '; + n++; + string++; + } + else + { + *p++ = *string++; + n++; + } + } + + return n; +} + +/* Remove percent and plus escaping and make sure that the reuslt is a + string. This is done in place. Returns STRING. */ +static char * +percent_plus_unescape_string (char *string) +{ + unsigned char *p = string; + size_t n; + + n = percent_plus_unescape (p); + p[n] = 0; + + return string; +} + int main (int argc, char **argv ) @@ -918,11 +1070,13 @@ main (int argc, char **argv ) case oP12Import: cmd = oP12Import; break; case oP12Export: cmd = oP12Export; break; - case oPassphrase: passphrase = pargs.r.ret_str; break; + case oPassphrase: opt_passphrase = pargs.r.ret_str; break; case oStore: opt_store = 1; break; case oForce: opt_force = 1; break; case oNoFailOnExist: opt_no_fail_on_exist = 1; break; - + case oHaveCert: opt_have_cert = 1; break; + case oPrompt: opt_prompt = pargs.r.ret_str; break; + default : pargs.err = 2; break; } } @@ -935,6 +1089,9 @@ main (int argc, char **argv ) else if (argc > 1) usage (1); + if (opt_prompt) + opt_prompt = percent_plus_unescape_string (xstrdup (opt_prompt)); + if (cmd == oProtect) read_and_protect (fname); else if (cmd == oUnprotect) @@ -965,21 +1122,27 @@ agent_exit (int rc) /* Return the passphrase string and ask the agent if it has not been - set from the command line. */ -static const char * -get_passphrase (void) + set from the command line PROMPTNO select the prompt to display: + 0 = default + 1 = taken from the option --prompt +*/ +static char * +get_passphrase (int promptno) { char *pw; int err; + const char *desc; + + if (opt_passphrase) + return xstrdup (opt_passphrase); - if (passphrase) - return passphrase; + if (promptno == 1 && opt_prompt) + desc = opt_prompt; + else + desc = _("Please enter the passphrase or the PIN\n" + "needed to complete this operation."); - pw = simple_pwquery (NULL,NULL, - _("Enter passphrase:"), - _("Please enter the passphrase or the PIN\n" - "needed to complete this operation."), - &err); + pw = simple_pwquery (NULL,NULL, _("Passphrase:"), desc, &err); if (!pw) { if (err) @@ -988,10 +1151,19 @@ get_passphrase (void) log_info ("cancelled\n"); agent_exit (0); } - passphrase = pw; - return passphrase; + + return pw; } +static void +release_passphrase (char *pw) +{ + if (pw) + { + wipememory (pw, strlen (pw)); + xfree (pw); + } +} static int store_private_key (const unsigned char *grip, diff --git a/common/ChangeLog b/common/ChangeLog index 28395053c..6f02303e6 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 5ceddc613..50dabc218 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -273,6 +273,11 @@ agent_open (int *rfd) #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 ) @@ -344,7 +349,7 @@ agent_open (int *rfd) } -/* Copy text to BUFFER and escape as required. Return a poiinter to +/* 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. */ diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 10d487f82..53624558d 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -152,6 +152,14 @@ 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 diff --git a/scd/command.c b/scd/command.c index d449eee52..d148ddb5a 100644 --- a/scd/command.c +++ b/scd/command.c @@ -127,7 +127,7 @@ open_card (CTRL ctrl, const char *apptype) } -/* Do the percent and plus/space unescaping in place and return tghe +/* Do the percent and plus/space unescaping in place and return the length of the valid buffer. */ static size_t percent_plus_unescape (unsigned char *string) diff --git a/sm/ChangeLog b/sm/ChangeLog index 4fcc2517e..922773ecb 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-02-19 Werner Koch <wk@gnupg.org> + + * export.c (export_p12, popen_protect_tool) + (gpgsm_p12_export): New. + * gpgsm.c (main): New command --export-secret-key-p12. + 2004-02-18 Werner Koch <wk@gnupg.org> * gpgsm.c (set_debug): Set the new --debug-level flags. diff --git a/sm/export.c b/sm/export.c index 524576628..ab175f160 100644 --- a/sm/export.c +++ b/sm/export.c @@ -1,5 +1,5 @@ /* export.c - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -26,14 +26,29 @@ #include <unistd.h> #include <time.h> #include <assert.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/wait.h> #include "gpgsm.h" #include <gcrypt.h> #include <ksba.h> #include "keydb.h" +#include "i18n.h" + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + + static void print_short_info (ksba_cert_t cert, FILE *fp); +static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen, + const char *prompt, const char *keygrip, + FILE **retfp); @@ -195,6 +210,147 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) } +/* Export a certificates and its private key. */ +void +gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp) +{ + KEYDB_HANDLE hd; + KEYDB_SEARCH_DESC *desc = NULL; + Base64Context b64writer = NULL; + ksba_writer_t writer; + ksba_cert_t cert = NULL; + int rc=0; + const unsigned char *image; + size_t imagelen; + char *keygrip = NULL; + char *prompt; + char buffer[1024]; + int nread; + FILE *datafp = NULL; + + hd = keydb_new (0); + if (!hd) + { + log_error ("keydb_new failed\n"); + goto leave; + } + + desc = xtrycalloc (1, sizeof *desc); + if (!desc) + { + log_error ("allocating memory for export failed: %s\n", + gpg_strerror (OUT_OF_CORE (errno))); + goto leave; + } + + rc = keydb_classify_name (name, desc); + if (rc) + { + log_error ("key `%s' not found: %s\n", + name, gpg_strerror (rc)); + goto leave; + } + + /* Lookup the certificate an make sure that it is unique. */ + rc = keydb_search (hd, desc, 1); + if (!rc) + { + rc = keydb_get_cert (hd, &cert); + if (rc) + { + log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc)); + goto leave; + } + + rc = keydb_search (hd, desc, 1); + if (!rc) + rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) + rc = 0; + if (rc) + { + log_error ("key `%s' not found: %s\n", + name, gpg_strerror (rc)); + goto leave; + } + } + + keygrip = gpgsm_get_keygrip_hexstring (cert); + if (!keygrip || gpgsm_agent_havekey (keygrip)) + { + /* Note, that the !keygrip case indicates a bad certificate. */ + rc = gpg_error (GPG_ERR_NO_SECKEY); + log_error ("can't export key `%s': %s\n", name, gpg_strerror (rc)); + goto leave; + } + + image = ksba_cert_get_image (cert, &imagelen); + if (!image) + { + log_error ("ksba_cert_get_image failed\n"); + goto leave; + } + + if (ctrl->create_pem) + { + print_short_info (cert, fp); + putc ('\n', fp); + } + + ctrl->pem_name = "PKCS12"; + rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + + + prompt = gpgsm_format_keydesc (cert); + rc = export_p12 (image, imagelen, prompt, keygrip, &datafp); + xfree (prompt); + if (rc) + goto leave; + rewind (datafp); + while ( (nread = fread (buffer, 1, sizeof buffer, datafp)) > 0 ) + if ((rc = ksba_writer_write (writer, buffer, nread))) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + if (ferror (datafp)) + { + rc = gpg_error_from_errno (rc); + log_error ("error reading temporary file: %s\n", gpg_strerror (rc)); + goto leave; + } + + if (ctrl->create_pem) + { + /* We want one certificate per PEM block */ + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + gpgsm_destroy_writer (b64writer); + b64writer = NULL; + } + + ksba_cert_release (cert); + cert = NULL; + + leave: + if (datafp) + fclose (datafp); + gpgsm_destroy_writer (b64writer); + ksba_cert_release (cert); + xfree (desc); + keydb_release (hd); +} + + /* Print some info about the certifciate CERT to FP */ static void print_short_info (ksba_cert_t cert, FILE *fp) @@ -243,7 +399,220 @@ print_short_info (ksba_cert_t cert, FILE *fp) } +static gpg_error_t +popen_protect_tool (const char *pgmname, + FILE *infile, FILE *outfile, FILE **statusfile, + const char *prompt, const char *keygrip, + pid_t *pid) +{ + gpg_error_t err; + int fd, fdout, rp[2]; + int n, i; + + fflush (infile); + rewind (infile); + fd = fileno (infile); + fdout = fileno (outfile); + if (fd == -1 || fdout == -1) + log_fatal ("no file descriptor for temporary file: %s\n", + strerror (errno)); + + /* Now start the protect-tool. */ + if (pipe (rp) == -1) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating a pipe: %s\n"), strerror (errno)); + return err; + } + + *pid = fork (); + if (*pid == -1) + { + err = gpg_error_from_errno (errno); + log_error (_("error forking process: %s\n"), strerror (errno)); + close (rp[0]); + close (rp[1]); + return err; + } + + if (!*pid) + { /* Child. */ + const char *arg0; + arg0 = strrchr (pgmname, '/'); + if (arg0) + arg0++; + else + arg0 = pgmname; + /* Connect the infile to stdin. */ + if (fd != 0 && dup2 (fd, 0) == -1) + log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); + /* Connect the outfile to stdout. */ + if (fdout != 1 && dup2 (fdout, 1) == -1) + log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); + + /* Connect stderr to our pipe. */ + if (rp[1] != 2 && dup2 (rp[1], 2) == -1) + log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); + + /* Close all other files. */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=3; i < n; i++) + close(i); + errno = 0; + + execlp (pgmname, arg0, + "--homedir", opt.homedir, + "--p12-export", + "--prompt", prompt?prompt:"", + "--", + keygrip, + NULL); + /* No way to print anything, as we have closed all streams. */ + _exit (31); + } + + /* Parent. */ + close (rp[1]); + *statusfile = fdopen (rp[0], "r"); + if (!*statusfile) + { + err = gpg_error_from_errno (errno); + log_error ("can't fdopen pipe for reading: %s", strerror (errno)); + kill (*pid, SIGTERM); + return err; + } + + return 0; +} + + +static gpg_error_t +export_p12 (const unsigned char *certimg, size_t certimglen, + const char *prompt, const char *keygrip, + FILE **retfp) +{ + const char *pgmname; + gpg_error_t err = 0, child_err = 0; + int i, c, cont_line; + unsigned int pos; + FILE *infp = NULL, *outfp = NULL, *fp = NULL; + char buffer[1024]; + pid_t pid = -1; + + if (!opt.protect_tool_program || !*opt.protect_tool_program) + pgmname = GNUPG_DEFAULT_PROTECT_TOOL; + else + pgmname = opt.protect_tool_program; + + infp = tmpfile (); + if (!infp) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating temporary file: %s\n"), strerror (errno)); + goto cleanup; + } + + if (fwrite (certimg, certimglen, 1, infp) != 1) + { + err = gpg_error_from_errno (errno); + log_error (_("error writing to temporary file: %s\n"), + strerror (errno)); + goto cleanup; + } + + outfp = tmpfile (); + if (!outfp) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating temporary file: %s\n"), strerror (errno)); + goto cleanup; + } + + err = popen_protect_tool (pgmname, infp, outfp, &fp, prompt, keygrip, &pid); + if (err) + { + pid = -1; + goto cleanup; + } + fclose (infp); + infp = NULL; + + /* Read stderr of the protect tool. */ + pos = 0; + cont_line = 0; + while ((c=getc (fp)) != EOF) + { + /* fixme: We could here grep for status information of the + protect tool to figure out better error codes for + CHILD_ERR. */ + buffer[pos++] = c; + if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n') + { + buffer[pos - (c == '\n')] = 0; + if (cont_line) + log_printf ("%s", buffer); + else + log_info ("%s", buffer); + pos = 0; + cont_line = (c != '\n'); + } + } + + if (pos) + { + buffer[pos] = 0; + if (cont_line) + log_printf ("%s\n", buffer); + else + log_info ("%s\n", buffer); + } + else if (cont_line) + log_printf ("\n"); + + /* If we found no error in the output of the child, setup a suitable + error code, which will later be reset if the exit status of the + child is 0. */ + if (!child_err) + child_err = gpg_error (GPG_ERR_DECRYPT_FAILED); + + cleanup: + if (infp) + fclose (infp); + if (fp) + fclose (fp); + if (pid != -1) + { + int status; + + while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) + ; + if (i == -1) + log_error (_("waiting for protect-tools to terminate failed: %s\n"), + strerror (errno)); + else if (WIFEXITED (status) && WEXITSTATUS (status) == 31) + log_error (_("error running `%s': probably not installed\n"), pgmname); + else if (WIFEXITED (status) && WEXITSTATUS (status)) + log_error (_("error running `%s': exit status %d\n"), pgmname, + WEXITSTATUS (status)); + else if (!WIFEXITED (status)) + log_error (_("error running `%s': terminated\n"), pgmname); + else + child_err = 0; + } + if (!err) + err = child_err; + if (err) + { + if (outfp) + fclose (outfp); + } + else + *retfp = outfp; + return err; +} diff --git a/sm/gpgsm.c b/sm/gpgsm.c index de265c128..ede432b1b 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -74,6 +74,7 @@ enum cmd_and_opt_values { aSendKeys, aRecvKeys, aExport, + aExportSecretKeyP12, aCheckKeys, /* nyi */ aServer, aLearnCard, @@ -344,6 +345,8 @@ static ARGPARSE_OPTS opts[] = { #endif { aDummy, "throw-keyid", 0, "@"}, { aDummy, "notation-data", 2, "@"}, + { aExportSecretKeyP12, "export-secret-key-p12", 256, "@"}, + { 302, NULL, 0, N_( "@\n(See the man page for a complete listing of all commands and options)\n" @@ -869,6 +872,7 @@ main ( int argc, char **argv) case aSendKeys: case aRecvKeys: case aExport: + case aExportSecretKeyP12: case aListKeys: case aListExternalKeys: case aListSecretKeys: @@ -1406,6 +1410,12 @@ main ( int argc, char **argv) free_strlist(sl); break; + case aExportSecretKeyP12: + if (argc == 1) + gpgsm_p12_export (&ctrl, *argv, stdout); + else + wrong_args (_("--export-secret-key-p12 KEY-ID")); + break; case aSendKeys: case aRecvKeys: diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 49a73186d..a1711a72e 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -247,6 +247,7 @@ int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files, /*-- export.c --*/ void gpgsm_export (ctrl_t ctrl, STRLIST names, FILE *fp); +void gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp); /*-- delete.c --*/ int gpgsm_delete (ctrl_t ctrl, STRLIST names); diff --git a/sm/import.c b/sm/import.c index 47f062790..02d2e629f 100644 --- a/sm/import.c +++ b/sm/import.c @@ -562,7 +562,7 @@ parse_p12 (ksba_reader_t reader, FILE **retfp) } while (!(err = ksba_reader_read (reader, buffer, sizeof buffer, &nread))) { - if (fwrite (buffer, nread, 1, tmpfp) != 1) + if (nread && fwrite (buffer, nread, 1, tmpfp) != 1) { err = gpg_error_from_errno (errno); log_error (_("error writing to temporary file: %s\n"), -- cgit v1.2.3 From aa0e38982a2d220ecafb6f82b169c1e4897f9e29 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 20 Feb 2004 13:46:21 +0000 Subject: * gpgsm.c (main): New option --debug-ignore-expiration. * certchain.c (gpgsm_validate_chain): Use it here. * certlist.c (cert_usage_p): Apply extKeyUsage. --- TODO | 24 +++-------------- doc/gpgsm.texi | 6 +++++ sm/ChangeLog | 7 +++++ sm/certchain.c | 14 ++++++---- sm/certlist.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ sm/gpgsm.c | 5 +++- sm/gpgsm.h | 1 + sm/keylist.c | 56 +++++++++++++++++++++++++++++++++++++-- 8 files changed, 159 insertions(+), 36 deletions(-) diff --git a/TODO b/TODO index 7f06e546b..496babfdc 100644 --- a/TODO +++ b/TODO @@ -21,14 +21,6 @@ might want to have an agent context for each service request ** 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. -** Try all available root certs in case we have several of them in our keybox. - For example TC TrustCenter Class 1 CA certs are ambiguous becuase - user certs don't come with a authorityKeyIdentifier. -** Support extKeyUsage - The only value which makes sense for us is emailProtection (I have - not yet found a test cetificate with that). We might want to allow - other usages depending on special options (e.g. an option used for code - signing). * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution @@ -49,10 +41,12 @@ might want to have an agent context for each service request ** Remove the inter-module dependencies between gpgsm and keybox ** Add an source_of_key field ** We need an error code GPG_ERR_NOT_LOCKED + It is already libgpg-error. * 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 @@ -63,10 +57,6 @@ might want to have an agent context for each service request * agent/divert-scd.c Remove the agent_reset_scd kludge. -* agent/protect-tool.c -** Export certificates along with the secret key. -** BUG? --p12-export seems to work only with unprotected keys - * Move pkcs-1 encoding into libgcrypt. * Use a MAC to protect some files. @@ -74,12 +64,6 @@ might want to have an agent context for each service request * sm/export.c ** Return an error code or a status info per user ID. -* scd/apdu.c -** We need close_reader functionality - -* ALL -** Return IMPORT_OK status. - * Where is http.c, regcomp.c, srv.c, w32reg.c ? * scd/sc-investigate @@ -90,12 +74,12 @@ might want to have an agent context for each service request authentication key. Old GnuPG versions seem to encode the wrong keyID. -* Store the revocation status directly in the Keybox - * 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. + diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 53624558d..24503a10b 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -411,6 +411,12 @@ Same as @code{--debug=0xffffffff} 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 diff --git a/sm/ChangeLog b/sm/ChangeLog index 922773ecb..a8a8f3f44 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-02-20 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): New option --debug-ignore-expiration. + * certchain.c (gpgsm_validate_chain): Use it here. + + * certlist.c (cert_usage_p): Apply extKeyUsage. + 2004-02-19 Werner Koch <wk@gnupg.org> * export.c (export_p12, popen_protect_tool) diff --git a/sm/certchain.c b/sm/certchain.c index bf5582503..2a59c559d 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -66,7 +66,6 @@ do_list (int is_error, int listmode, FILE *fp, const char *format, ...) } - static int unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp) { @@ -74,6 +73,7 @@ unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp) "2.5.29.15", /* keyUsage */ "2.5.29.19", /* basic Constraints */ "2.5.29.32", /* certificatePolicies */ + "2.5.29.37", /* extendedKeyUsage - handled by certlist.c */ NULL }; int rc = 0, i, idx, crit; @@ -548,16 +548,20 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG); goto leave; } - if (not_after && strcmp (current_time, not_after) > 0 ) + if (*not_after && strcmp (current_time, not_after) > 0 ) { - do_list (1, lm, fp, _("certificate has expired")); + do_list (opt.ignore_expiration?0:1, lm, fp, + _("certificate has expired")); if (!lm) { - log_error ("(expired at "); + log_info ("(expired at "); gpgsm_dump_time (not_after); log_printf (")\n"); } - any_expired = 1; + if (opt.ignore_expiration) + log_info ("WARNING: ignoring expiration\n"); + else + any_expired = 1; } } diff --git a/sm/certlist.c b/sm/certlist.c index 66fb46326..8ee3c2caf 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -1,5 +1,5 @@ /* certlist.c - build list of certificates - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -33,7 +33,14 @@ #include "keydb.h" #include "i18n.h" - + + +static const char oid_kp_serverAuth[] = "1.3.6.1.5.5.7.3.1"; +static const char oid_kp_clientAuth[] = "1.3.6.1.5.5.7.3.2"; +static const char oid_kp_codeSigning[] = "1.3.6.1.5.5.7.3.3"; +static const char oid_kp_emailProtection[]= "1.3.6.1.5.5.7.3.4"; +static const char oid_kp_timeStamping[] = "1.3.6.1.5.5.7.3.8"; + /* Return 0 if the cert is usable for encryption. A MODE of 0 checks for signing a MODE of 1 checks for encryption, a MODE of 2 checks for verification and a MODE of 3 for decryption (just for @@ -43,20 +50,78 @@ cert_usage_p (ksba_cert_t cert, int mode) { gpg_error_t err; unsigned int use; + char *extkeyusages; - err = ksba_cert_get_key_usage (cert, &use); + err = ksba_cert_get_ext_key_usages (cert, &extkeyusages); if (gpg_err_code (err) == GPG_ERR_NO_DATA) + err = 0; /* no policy given */ + if (!err) { - if (opt.verbose && mode < 2) - log_info (mode? - _("no key usage specified - accepted for encryption\n"): - _("no key usage specified - accepted for signing\n")); - return 0; + unsigned int extusemask = ~0; /* Allow all. */ + + if (extkeyusages) + { + char *p, *pend; + int any_critical = 0; + + extusemask = 0; + + p = extkeyusages; + while (p && (pend=strchr (p, ':'))) + { + *pend++ = 0; + /* Only care about critical flagged usages. */ + if ( *pend == 'C' ) + { + any_critical = 1; + if ( !strcmp (p, oid_kp_serverAuth)) + extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE + | KSBA_KEYUSAGE_KEY_ENCIPHERMENT + | KSBA_KEYUSAGE_KEY_AGREEMENT); + else if ( !strcmp (p, oid_kp_clientAuth)) + extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE + | KSBA_KEYUSAGE_KEY_AGREEMENT); + else if ( !strcmp (p, oid_kp_codeSigning)) + extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE); + else if ( !strcmp (p, oid_kp_emailProtection)) + extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE + | KSBA_KEYUSAGE_NON_REPUDIATION + | KSBA_KEYUSAGE_KEY_ENCIPHERMENT + | KSBA_KEYUSAGE_KEY_AGREEMENT); + else if ( !strcmp (p, oid_kp_timeStamping)) + extusemask |= (KSBA_KEYUSAGE_DIGITAL_SIGNATURE + | KSBA_KEYUSAGE_NON_REPUDIATION); + } + + if ((p = strchr (pend, '\n'))) + p++; + } + xfree (extkeyusages); + extkeyusages = NULL; + + if (!any_critical) + extusemask = ~0; /* Reset to the don't care mask. */ + } + + + err = ksba_cert_get_key_usage (cert, &use); + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + { + err = 0; + if (opt.verbose && mode < 2) + log_info (_("no key usage specified - assuming all usages\n")); + use = ~0; + } + + /* Apply extKeyUsage. */ + use &= extusemask; + } if (err) { log_error (_("error getting key usage information: %s\n"), gpg_strerror (err)); + xfree (extkeyusages); return err; } @@ -73,6 +138,7 @@ cert_usage_p (ksba_cert_t cert, int mode) (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) ) return 0; + log_info (mode==3? _("certificate should have not been used for encryption\n"): mode==2? _("certificate should have not been used for signing\n"): mode==1? _("certificate is not usable for encryption\n"): diff --git a/sm/gpgsm.c b/sm/gpgsm.c index ede432b1b..68214a6d8 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -89,6 +89,7 @@ enum cmd_and_opt_values { oDebugAll, oDebugWait, oDebugNoChainValidation, + oDebugIgnoreExpiration, oLogFile, oEnableSpecialFilenames, @@ -323,7 +324,8 @@ static ARGPARSE_OPTS opts[] = { { oDebugLevel, "debug-level" ,2, "@"}, { oDebugAll, "debug-all" ,0, "@"}, { oDebugWait, "debug-wait" ,1, "@"}, - { oDebugNoChainValidation, "debug-no-chain-validation" ,0, "@"}, + { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"}, + { oDebugIgnoreExpiration, "debug-ignore-expiration", 0, "@"}, { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, { aDummy, "no-comment", 0, "@"}, { aDummy, "completes-needed", 1, "@"}, @@ -991,6 +993,7 @@ main ( int argc, char **argv) case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugNoChainValidation: opt.no_chain_validation = 1; break; + case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break; case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index a1711a72e..6cf3ed094 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -94,6 +94,7 @@ struct { char *policy_file; /* full pathname of policy file */ int no_policy_check; /* ignore certificate policies */ int no_chain_validation; /* Bypass all cert chain validity tests */ + int ignore_expiration; /* Ignore the notAfter validity checks. */ int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ } opt; diff --git a/sm/keylist.c b/sm/keylist.c index e6daec681..a73d18e92 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -46,6 +46,28 @@ struct list_external_parm_s { }; +/* This table is to map Extended Key Usage OIDs to human readable + names. */ +struct { + const char *oid; + const char *name; +} key_purpose_map[] = { + { "1.3.6.1.5.5.7.3.1", "serverAuth" }, + { "1.3.6.1.5.5.7.3.2", "clientAuth" }, + { "1.3.6.1.5.5.7.3.3", "codeSigning" }, + { "1.3.6.1.5.5.7.3.4", "emailProtection" }, + { "1.3.6.1.5.5.7.3.5", "ipsecEndSystem" }, + { "1.3.6.1.5.5.7.3.6", "ipsecTunnel" }, + { "1.3.6.1.5.5.7.3.7", "ipsecUser" }, + { "1.3.6.1.5.5.7.3.8", "timeStamping" }, + { "1.3.6.1.5.5.7.3.9", "ocspSigning" }, + { "1.3.6.1.5.5.7.3.10", "dvcs" }, + { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" }, + { "1.3.6.1.5.5.7.3.13", "eapOverPPP" }, + { "1.3.6.1.5.5.7.3.14", "wlanSSID" }, + { NULL, NULL } +}; + static void print_key_data (ksba_cert_t cert, FILE *fp) @@ -292,10 +314,10 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, ksba_sexp_t sexp; char *dn; ksba_isotime_t t; - int idx; + int idx, i; int is_ca, chainlen; unsigned int kusage; - char *string, *p; + char *string, *p, *pend; sexp = ksba_cert_get_serial (cert); fputs ("Serial number: ", fp); @@ -367,6 +389,36 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, putc ('\n', fp); } + err = ksba_cert_get_ext_key_usages (cert, &string); + if (gpg_err_code (err) != GPG_ERR_NO_DATA) + { + fputs ("ext key usage: ", fp); + if (err) + fprintf (fp, "[error: %s]", gpg_strerror (err)); + else + { + p = string; + while (p && (pend=strchr (p, ':'))) + { + *pend++ = 0; + for (i=0; key_purpose_map[i].oid; i++) + if ( !strcmp (key_purpose_map[i].oid, p) ) + break; + fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp); + p = pend; + if (*p != 'C') + fputs (" (suggested)", fp); + if ((p = strchr (p, '\n'))) + { + p++; + fputs (", ", fp); + } + } + xfree (string); + } + putc ('\n', fp); + } + err = ksba_cert_get_cert_policies (cert, &string); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { -- cgit v1.2.3 From c4663004d9718954527dce20c278ae7528fea3e3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 20 Feb 2004 13:46:35 +0000 Subject: * Makefile.am: Reset GPG_AGENT_INFO here * runtest: and not anymore here. --- tests/ChangeLog | 5 +++++ tests/Makefile.am | 3 +-- tests/runtest | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/ChangeLog b/tests/ChangeLog index c6b3b9af1..68f9b4e21 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2004-02-20 Werner Koch <wk@gnupg.org> + + * Makefile.am: Reset GPG_AGENT_INFO here + * runtest: and not anymore here. + 2002-12-04 Werner Koch <wk@gnupg.org> * inittests (gpgsm.conf): Fake system time. diff --git a/tests/Makefile.am b/tests/Makefile.am index 622b5fe58..791829a07 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,8 +21,7 @@ GPGSM = ../sm/gpgsm -# We can't unset a variable here so we unset GPG_AGENT_INFO in runtest -TESTS_ENVIRONMENT = GNUPGHOME=`pwd` LC_ALL=C GPGSM=$(GPGSM) \ +TESTS_ENVIRONMENT = GNUPGHOME=`pwd` GPG_AGENT_INFO= LC_ALL=C GPGSM=$(GPGSM) \ LD_LIBRARY_PATH=$$(seen=0; \ for i in $(LDFLAGS) $(LIBGCRYPT_LIBS) $(PTH_LIBS); \ do \ diff --git a/tests/runtest b/tests/runtest index 71385fb46..8d5078647 100755 --- a/tests/runtest +++ b/tests/runtest @@ -1,5 +1,4 @@ #!/bin/sh -unset GPG_AGENT_INFO [ -x "$1" ] && exec $1 $2 exec ./asschk --no-echo -DGPGSM=${GPGSM} <"$1" -- cgit v1.2.3 From ffd5cd03689d95e44087fadf590ecd97fd9b493c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 20 Feb 2004 14:23:30 +0000 Subject: Fixed URLs in the notice messages. --- ChangeLog | 4 ++++ configure.ac | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4ce7da6c3..00b6a9c9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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, diff --git a/configure.ac b/configure.ac index 1faf753c0..14f97795a 100644 --- a/configure.ac +++ b/configure.ac @@ -966,7 +966,7 @@ if test "$have_gpg_error" = "no"; then *** *** You need libgpg-error to build this program. ** This library is for example available at -*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libgpg-error +*** ftp://ftp.gnupg.org/gcrypt/alpha/libgpg-error *** (at least version $NEED_GPG_ERROR_VERSION is required.) ***]]) fi @@ -976,7 +976,7 @@ if test "$have_libgcrypt" = "no"; then *** *** You need libgcrypt to build this program. ** This library is for example available at -*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libgcrypt/ +*** ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/ *** (at least version $NEED_LIBGCRYPT_VERSION is required.) ***]]) fi @@ -986,7 +986,7 @@ if test "$have_libassuan" = "no"; then *** *** You need libassuan to build this program. *** This library is for example available at -*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libassuan/ +*** ftp://ftp.gnupg.org/gcrypt/alpha/libassuan/ *** (at least version $NEED_LIBASSUAN_VERSION is required). ***]]) fi @@ -996,7 +996,7 @@ if test "$have_ksba" = "no"; then *** *** You need libksba to build this program. *** This library is for example available at -*** ftp://ftp.gnupg.org/pub/gcrypt/alpha/libksba/ +*** ftp://ftp.gnupg.org/gcrypt/alpha/libksba/ *** (at least version $NEED_KSBA_VERSION is required). ***]]) fi -- cgit v1.2.3 From a425334f4884a6cd5f95976cf1d0950305f40691 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 21 Feb 2004 13:05:22 +0000 Subject: * command.c (cmd_passwd): Take acount of a key description. * genkey.c (reenter_compare_cb): Do not set the error text. (agent_protect_and_store, agent_genkey): Force a re-enter after a non-matching passphrase. * query.c (agent_askpin): Add new arg INITIAL_ERRTEXT; changed all callers. --- agent/ChangeLog | 10 ++++++++++ agent/agent.h | 3 ++- agent/command.c | 5 ++++- agent/divert-scd.c | 2 +- agent/findkey.c | 2 +- agent/genkey.c | 32 ++++++++++++++++++++++++++------ agent/query.c | 17 +++++++++++++++-- 7 files changed, 59 insertions(+), 12 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 241a60964..f05685b0d 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,13 @@ +2004-02-21 Werner Koch <wk@gnupg.org> + + * command.c (cmd_passwd): Take acount of a key description. + + * genkey.c (reenter_compare_cb): Do not set the error text. + (agent_protect_and_store, agent_genkey): Force a re-enter after a + non-matching passphrase. + * query.c (agent_askpin): Add new arg INITIAL_ERRTEXT; changed + all callers. + 2004-02-19 Werner Koch <wk@gnupg.org> * protect-tool.c: New options --have-cert and --prompt. diff --git a/agent/agent.h b/agent/agent.h index a849e873f..a4312e081 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -141,7 +141,8 @@ int agent_key_available (const unsigned char *grip); /*-- query.c --*/ int agent_askpin (ctrl_t ctrl, - const char *desc_text, struct pin_entry_info_s *pininfo); + const char *desc_text, const char *inital_errtext, + struct pin_entry_info_s *pininfo); int agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *desc, const char *prompt, const char *errtext); diff --git a/agent/command.c b/agent/command.c index 2fa182f63..1d1ae9704 100644 --- a/agent/command.c +++ b/agent/command.c @@ -664,7 +664,8 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) return rc; /* we can't jump to leave because this is already an Assuan error code. */ - rc = agent_key_from_file (ctrl, NULL, grip, &shadow_info, 1, &s_skey); + rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc, + grip, &shadow_info, 1, &s_skey); if (rc) ; else if (!s_skey) @@ -675,6 +676,8 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) else rc = agent_protect_and_store (ctrl, s_skey); + xfree (ctrl->server_local->keydesc); + ctrl->server_local->keydesc = NULL; gcry_sexp_release (s_skey); xfree (shadow_info); if (rc) diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 9c512bdcf..72cf338fe 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -202,7 +202,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) info? info:"", info? "')":"") < 0) desc = NULL; - rc = agent_askpin (ctrl, desc?desc:info, pi); + rc = agent_askpin (ctrl, desc?desc:info, NULL, pi); free (desc); if (!rc) { diff --git a/agent/findkey.c b/agent/findkey.c index 14ca38448..9866b54b9 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -185,7 +185,7 @@ unprotect (CTRL ctrl, const char *desc_text, arg.unprotected_key = NULL; pi->check_cb_arg = &arg; - rc = agent_askpin (ctrl, desc_text, pi); + rc = agent_askpin (ctrl, desc_text, NULL, pi); if (!rc) { assert (arg.unprotected_key); diff --git a/agent/genkey.c b/agent/genkey.c index 1417abb02..3c56ba33e 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -1,5 +1,5 @@ /* pksign.c - Generate a keypair - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -79,7 +79,6 @@ reenter_compare_cb (struct pin_entry_info_s *pi) if (!strcmp (pin1, pi->pin)) return 0; /* okay */ - pi->cb_errtext = _("does not match - try again"); return -1; } @@ -109,6 +108,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, const char *text1 = _("Please enter the passphrase to%0A" "to protect your new key"); const char *text2 = _("Please re-enter this passphrase"); + const char *initial_errtext = NULL; pi = gcry_calloc_secure (2, sizeof (*pi) + 100); pi2 = pi + (sizeof *pi + 100); @@ -119,9 +119,19 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, pi2->check_cb = reenter_compare_cb; pi2->check_cb_arg = pi->pin; - rc = agent_askpin (ctrl, text1, pi); + next_try: + rc = agent_askpin (ctrl, text1, initial_errtext, pi); + initial_errtext = NULL; if (!rc) - rc = agent_askpin (ctrl, text2, pi2); + { + rc = agent_askpin (ctrl, text2, NULL, pi2); + if (rc == -1) + { /* The re-entered one did not match and the user did not + hit cancel. */ + initial_errtext = _("does not match - try again"); + goto next_try; + } + } if (rc) return rc; if (!*pi->pin) @@ -212,6 +222,7 @@ agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey) { const char *text1 = _("Please enter the new passphrase"); const char *text2 = _("Please re-enter this passphrase"); + const char *initial_errtext = NULL; pi = gcry_calloc_secure (2, sizeof (*pi) + 100); pi2 = pi + (sizeof *pi + 100); @@ -222,9 +233,18 @@ agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey) pi2->check_cb = reenter_compare_cb; pi2->check_cb_arg = pi->pin; - rc = agent_askpin (ctrl, text1, pi); + next_try: + rc = agent_askpin (ctrl, text1, initial_errtext, pi); if (!rc) - rc = agent_askpin (ctrl, text2, pi2); + { + rc = agent_askpin (ctrl, text2, NULL, pi2); + if (rc == -1) + { /* The re-entered one did not match and the user did not + hit cancel. */ + initial_errtext = _("does not match - try again"); + goto next_try; + } + } if (rc) return rc; if (!*pi->pin) diff --git a/agent/query.c b/agent/query.c index 28873775a..145aaca00 100644 --- a/agent/query.c +++ b/agent/query.c @@ -250,7 +250,8 @@ all_digitsp( const char *s) numbers. */ int agent_askpin (CTRL ctrl, - const char *desc_text, struct pin_entry_info_s *pininfo) + const char *desc_text, const char *initial_errtext, + struct pin_entry_info_s *pininfo) { int rc; char line[ASSUAN_LINELENGTH]; @@ -289,6 +290,17 @@ agent_askpin (CTRL ctrl, if (rc) return unlock_pinentry (map_assuan_err (rc)); + + if (initial_errtext) + { + snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++) { memset (&parm, 0, sizeof parm); @@ -301,7 +313,8 @@ agent_askpin (CTRL ctrl, snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)", errtext, pininfo->failed_tries+1, pininfo->max_tries); line[DIM(line)-1] = 0; - rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + rc = assuan_transact (entry_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return unlock_pinentry (map_assuan_err (rc)); errtext = NULL; -- cgit v1.2.3 From 0c224cadf3f8b5ae259d8936f7963b56f63a0c26 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 21 Feb 2004 13:05:52 +0000 Subject: * keylist.c (list_internal_keys): Return error codes. (list_external_keys, gpgsm_list_keys): Ditto. * server.c (do_listkeys): Ditto. * gpgsm.c (main): Display a key description for --passwd. * call-agent.c (gpgsm_agent_passwd): New arg DESC. --- sm/ChangeLog | 9 +++++++++ sm/call-agent.c | 16 ++++++++++++++-- sm/gpgsm.c | 6 +++++- sm/gpgsm.h | 5 +++-- sm/keylist.c | 31 ++++++++++++++++++++++--------- sm/server.c | 5 +++-- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index a8a8f3f44..e543bbcba 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,12 @@ +2004-02-21 Werner Koch <wk@gnupg.org> + + * keylist.c (list_internal_keys): Return error codes. + (list_external_keys, gpgsm_list_keys): Ditto. + * server.c (do_listkeys): Ditto. + + * gpgsm.c (main): Display a key description for --passwd. + * call-agent.c (gpgsm_agent_passwd): New arg DESC. + 2004-02-20 Werner Koch <wk@gnupg.org> * gpgsm.c (main): New option --debug-ignore-expiration. diff --git a/sm/call-agent.c b/sm/call-agent.c index a0a1da5c3..053959b2c 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -710,9 +710,11 @@ gpgsm_agent_learn () } -/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */ +/* Ask the agent to change the passphrase of the key identified by + HEXKEYGRIP. If DESC is not NULL, display instead of the default + description message. */ int -gpgsm_agent_passwd (const char *hexkeygrip) +gpgsm_agent_passwd (const char *hexkeygrip, const char *desc) { int rc; char line[ASSUAN_LINELENGTH]; @@ -724,6 +726,16 @@ gpgsm_agent_passwd (const char *hexkeygrip) if (!hexkeygrip || strlen (hexkeygrip) != 40) return gpg_error (GPG_ERR_INV_VALUE); + if (desc) + { + snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); + line[DIM(line)-1] = 0; + rc = assuan_transact (agent_ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + } + snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip); line[DIM(line)-1] = 0; diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 68214a6d8..6f3e62a33 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1452,7 +1452,11 @@ main ( int argc, char **argv) else if (!(grip = gpgsm_get_keygrip_hexstring (cert))) rc = gpg_error (GPG_ERR_BUG); else - rc = gpgsm_agent_passwd (grip); + { + char *desc = gpgsm_format_keydesc (cert); + rc = gpgsm_agent_passwd (grip, desc); + xfree (desc); + } if (rc) log_error ("error changing passphrase: %s\n", gpg_strerror (rc)); xfree (grip); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 6cf3ed094..c0434d79c 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -239,7 +239,8 @@ void gpgsm_release_certlist (certlist_t list); int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert); /*-- keylist.c --*/ -void gpgsm_list_keys (ctrl_t ctrl, STRLIST names, FILE *fp, unsigned int mode); +gpg_error_t gpgsm_list_keys (ctrl_t ctrl, STRLIST names, + FILE *fp, unsigned int mode); /*-- import.c --*/ int gpgsm_import (ctrl_t ctrl, int in_fd); @@ -284,7 +285,7 @@ int gpgsm_agent_istrusted (ksba_cert_t cert); int gpgsm_agent_havekey (const char *hexkeygrip); int gpgsm_agent_marktrusted (ksba_cert_t cert); int gpgsm_agent_learn (void); -int gpgsm_agent_passwd (const char *hexkeygrip); +int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp); diff --git a/sm/keylist.c b/sm/keylist.c index a73d18e92..3ebbe3ba3 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -496,7 +496,7 @@ list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation) /* List all internal keys or just the key given as NAMES. */ -static void +static gpg_error_t list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) { KEYDB_HANDLE hd; @@ -504,7 +504,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) STRLIST sl; int ndesc; ksba_cert_t cert = NULL; - int rc=0; + gpg_error_t rc = 0; const char *lastresname, *resname; int have_secret; @@ -512,6 +512,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) if (!hd) { log_error ("keydb_new failed\n"); + rc = gpg_error (GPG_ERR_GENERAL); goto leave; } @@ -526,6 +527,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) desc = xtrycalloc (ndesc, sizeof *desc); if (!ndesc) { + rc = gpg_error_from_errno (errno); log_error ("out of core\n"); goto leave; } @@ -599,8 +601,12 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) char *p = gpgsm_get_keygrip_hexstring (cert); if (p) { - if (!gpgsm_agent_havekey (p)) + rc = gpgsm_agent_havekey (p); + if (!rc) have_secret = 1; + else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY) + goto leave; + rc = 0; xfree (p); } } @@ -623,13 +629,16 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) ksba_cert_release (cert); cert = NULL; } - if (rc && rc != -1) + if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 ) + rc = 0; + if (rc) log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); leave: ksba_cert_release (cert); xfree (desc); keydb_release (hd); + return rc; } @@ -669,7 +678,7 @@ list_external_cb (void *cb_value, ksba_cert_t cert) /* List external keys similar to internal one. Note: mode does not make sense here because it would be unwise to list external secret keys */ -static void +static gpg_error_t list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) { int rc; @@ -684,6 +693,7 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm); if (rc) log_error ("listing external keys failed: %s\n", gpg_strerror (rc)); + return rc; } /* List all keys or just the key given as NAMES. @@ -696,11 +706,14 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) Bit 6: list internal keys Bit 7: list external keys */ -void +gpg_error_t gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) { + gpg_error_t err = 0; + if ((mode & (1<<6))) - list_internal_keys (ctrl, names, fp, (mode & 3)); - if ((mode & (1<<7))) - list_external_keys (ctrl, names, fp); + err = list_internal_keys (ctrl, names, fp, (mode & 3)); + if (!err && (mode & (1<<7))) + err = list_external_keys (ctrl, names, fp); + return err; } diff --git a/sm/server.c b/sm/server.c index 8cc1b900e..a132f9f2b 100644 --- a/sm/server.c +++ b/sm/server.c @@ -651,6 +651,7 @@ do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode) char *p; STRLIST list, sl; unsigned int listmode; + gpg_error_t err; if (!fp) return set_error (General_Error, "no data stream"); @@ -684,9 +685,9 @@ do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode) listmode |= (1<<6); if (ctrl->server_local->list_external) listmode |= (1<<7); - gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode); + err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode); free_strlist (list); - return 0; + return map_to_assuan_status (err); } static int -- cgit v1.2.3 From b67d7c40732e2deeed53b61d6a862687638b5f80 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 21 Feb 2004 13:13:35 +0000 Subject: About to release 1.9.5 --- ChangeLog | 4 ++++ NEWS | 4 ++-- configure.ac | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 00b6a9c9b..be4f47ef2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/NEWS b/NEWS index 3d6837d2f..d698f2096 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.5 +Noteworthy changes in version 1.9.5 (2004-02-21) ------------------------------------------------ * gpg-protect-tool gets now installed into libexec as it ought to be. @@ -11,7 +11,7 @@ Noteworthy changes in version 1.9.5 exporting of secret keys in PKCS\#12 format. * [gpgsm] The pinentry will now present a description of the key for - whom the passphrase is requests. + whom the passphrase is requested. * [gpgsm] New option --with-validation to check the validity of key while listing it. diff --git a/configure.ac b/configure.ac index 14f97795a..210c6e744 100644 --- a/configure.ac +++ b/configure.ac @@ -24,14 +24,14 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.5-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.5, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. development_version=yes NEED_GPG_ERROR_VERSION=0.6 NEED_LIBGCRYPT_VERSION=1.1.92 -NEED_LIBASSUAN_VERSION=0.6.3 +NEED_LIBASSUAN_VERSION=0.6.4 NEED_KSBA_VERSION=0.9.4 NEED_OPENSC_VERSION=0.8.0 -- cgit v1.2.3 From 48b0cdef7c6dad8cf14cd8d1838e9207363d654c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 21 Feb 2004 13:35:42 +0000 Subject: post release version bumb --- NEWS | 5 +++++ configure.ac | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d698f2096..905c5852a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Noteworthy changes in version 1.9.6 +------------------------------------------------ + + + Noteworthy changes in version 1.9.5 (2004-02-21) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 210c6e744..f9cfce22d 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.5, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.6-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From c38f60920601f859c4877d2fa532178b3c01084b Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 23 Feb 2004 19:37:04 +0000 Subject: 2004-02-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (hextobyte): New function. (percent_deescape): New function. (get_config_pathname): Percent deescape pathname if taken from option (default) value. Use default value only if it exists and is not empty. Use empty string otherwise. Don't include leading quote in pathname. (change_options_program): Percent deescape string before writing it out. --- tools/ChangeLog | 14 ++++++++ tools/gpgconf-comp.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 98 insertions(+), 11 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 7796acbed..4c55ed4fe 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,17 @@ +2004-02-23 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (hextobyte): New function. + (percent_deescape): New function. + (get_config_pathname): Percent deescape pathname if taken from + option (default) value. Use default value only if it exists and + is not empty. Use empty string otherwise. Don't include leading + quote in pathname. + (change_options_program): Percent deescape string before writing + it out. + + * gpgconf-comp.c (gc_component_list_options): Do not skip groups + on output. + 2004-02-18 Werner Koch <wk@gnupg.org> * gpgconf-comp.c: Added empty components for gpgsm and scdaemon. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 857ba0840..2065a6587 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -598,6 +598,74 @@ percent_escape (const char *src) } +/* Convert two hexadecimal digits from STR to the value they + represent. Returns -1 if one of the characters is not a + hexadecimal digit. */ +static int +hextobyte (const char *str) +{ + int val = 0; + int i; + +#define NROFHEXDIGITS 2 + for (i = 0; i < NROFHEXDIGITS; i++) + { + if (*str >= '0' && *str <= '9') + val += *str - '0'; + else if (*str >= 'A' && *str <= 'F') + val += 10 + *str - 'A'; + else if (*str >= 'a' && *str <= 'f') + val += 10 + *str - 'a'; + else + return -1; + if (i < NROFHEXDIGITS - 1) + val *= 16; + str++; + } + return val; +} + + + +/* Percent-Deescape special characters. The string is valid until the + next invocation of the function. */ +static char * +percent_deescape (const char *src) +{ + static char *str; + static int str_len; + int new_len = 3 * strlen (src) + 1; + char *dst; + + if (str_len < new_len) + { + char *new_str = realloc (str, new_len); + if (!new_str) + gc_error (1, errno, "can not deescape string"); + str = new_str; + str_len = new_len; + } + + dst = str; + while (*src) + { + if (*src == '%') + { + int val = hextobyte (src + 1); + + if (val < 0) + gc_error (1, 0, "malformed end of string %s", src); + + *(dst++) = (char) val; + src += 3; + } + else + *(dst++) = *(src++); + } + *dst = '\0'; + return str; +} + /* List all components that are available. */ void @@ -642,7 +710,8 @@ gc_component_list_options (int component, FILE *out) char *arg_name = NULL; /* Do not output unknown or internal options. */ - if (!option->active || option->level == GC_LEVEL_INTERNAL) + if (!(option->flags & GC_OPT_FLAG_GROUP) + && (!option->active || option->level == GC_LEVEL_INTERNAL)) { option++; continue; @@ -779,16 +848,18 @@ get_config_pathname (gc_component_t component, gc_backend_t backend) gc_backend[backend].name); if (option->value && *option->value) - pathname = option->value; + pathname = percent_deescape (&option->value[1]); + else if (option->default_value && *option->default_value) + pathname = percent_deescape (&option->default_value[1]); else - pathname = option->default_value; + pathname = ""; - if (pathname[1] != '/') + if (pathname[0] != '/') gc_error (1, 0, "Option %s, needed by backend %s, is not absolute", gc_backend[backend].option_config_filename, gc_backend[backend].name); - return &pathname[1]; + return pathname; } @@ -1234,13 +1305,15 @@ change_options_program (gc_component_t component, gc_backend_t backend, option = gc_component[component].options; while (option->name) { + /* FIXME: Add support for lists. */ if (!(option->flags & GC_OPT_FLAG_GROUP) && option->backend == backend && option->new_value && *option->new_value) { if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) - fprintf (src_file, "%s %s\n", option->name, &option->new_value[1]); + fprintf (src_file, "%s %s\n", option->name, + percent_deescape (&option->new_value[1])); else if (option->arg_type == GC_ARG_TYPE_NONE) fprintf (src_file, "%s\n", option->name); else @@ -1250,11 +1323,11 @@ change_options_program (gc_component_t component, gc_backend_t backend, } option++; } - { - fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ())); - if (ferror (src_file)) - goto change_one_err; - } + + fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ())); + if (ferror (src_file)) + goto change_one_err; + if (!in_marker) { fprintf (src_file, "# GPGConf edited this configuration file.\n"); -- cgit v1.2.3 From 5620ac56bf57cb2f42a78d6da236acf446b9b881 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 23 Feb 2004 20:31:35 +0000 Subject: 2004-02-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf.h (struct): Add member runtime. * gpgconf.c: Add new option oRuntime. (main): Same here. --- tools/ChangeLog | 4 ++++ tools/gpgconf.c | 13 ++++++++++--- tools/gpgconf.h | 14 ++++++++------ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 4c55ed4fe..b7c9ed0bb 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,9 @@ 2004-02-23 Marcus Brinkmann <marcus@g10code.de> + * gpgconf.h (struct): Add member runtime. + * gpgconf.c: Add new option oRuntime. + (main): Same here. + * gpgconf-comp.c (hextobyte): New function. (percent_deescape): New function. (get_config_pathname): Percent deescape pathname if taken from diff --git a/tools/gpgconf.c b/tools/gpgconf.c index f261a2c0a..476c57fc1 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -35,6 +35,7 @@ enum cmd_and_opt_values oOutput = 'o', oQuiet = 'q', oVerbose = 'v', + oRuntime = 'r', oComponent = 'c', oNoVerbose = 500, oHomedir, @@ -61,6 +62,7 @@ static ARGPARSE_OPTS opts[] = { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("quiet") }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, + { oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") }, /* hidden options */ { oNoVerbose, "no-verbose", 0, "@"}, @@ -131,10 +133,10 @@ main (int argc, char **argv) i18n_init(); - /* Patrse the command line. */ + /* Parse the command line. */ pargs.argc = &argc; pargs.argv = &argv; - pargs.flags = 1; /* do not remove the args */ + pargs.flags = 1; /* Do not remove the args. */ while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts)) { switch (pargs.r_opt) @@ -142,6 +144,11 @@ main (int argc, char **argv) case oOutput: opt.outfile = pargs.r.ret_str; break; case oQuiet: opt.quiet = 1; break; case oDryRun: opt.dry_run = 1; break; + case oRuntime: + opt.runtime = 1; + /* FIXME */ + fputs ("gpgconf: warning: option --runtime not supported yet\n", stderr); + break; case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; @@ -154,7 +161,7 @@ main (int argc, char **argv) default: pargs.err = 2; break; } } - + if (log_get_errorcount (0)) exit (2); diff --git a/tools/gpgconf.h b/tools/gpgconf.h index 6ccc0d1dd..138380b6d 100644 --- a/tools/gpgconf.h +++ b/tools/gpgconf.h @@ -23,12 +23,14 @@ #include "../common/util.h" -/* We keep all global options in the structure OPT. */ -struct { - int verbose; /* Verbosity level. */ - int quiet; /* Be extra quiet. */ - int dry_run; /* Don't change any persistent data. */ - char *outfile; /* Name of output file. */ +/* We keep all global options in the structure OPT. */ +struct +{ + int verbose; /* Verbosity level. */ + int quiet; /* Be extra quiet. */ + int dry_run; /* Don't change any persistent data. */ + int runtime; /* Make changes active at runtime. */ + char *outfile; /* Name of output file. */ int component; /* The active component. */ } opt; -- cgit v1.2.3 From cd3ccbf34d6f4206f86e9390cceec160135388f9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 23 Feb 2004 20:59:18 +0000 Subject: 2004-02-23 Marcus Brinkmann <marcus@g10code.de> * README.gpgconf: Change meaning of type 0 options value if it is the empty string or "0". --- tools/ChangeLog | 3 +++ tools/README.gpgconf | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index b7c9ed0bb..1871f8b15 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,8 @@ 2004-02-23 Marcus Brinkmann <marcus@g10code.de> + * README.gpgconf: Change meaning of type 0 options value if it is + the empty string or "0". + * gpgconf.h (struct): Add member runtime. * gpgconf.c: Add new option oRuntime. (main): Same here. diff --git a/tools/README.gpgconf b/tools/README.gpgconf index c0e5511c1..848e1c59f 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -82,7 +82,9 @@ argument depends on the type of the option and on some flags: The simplest case is that the option does not take an argument at all (TYPE is 0). Then the option argument is either empty if the option is not set, or an unsigned number that specifies how often the option -occurs. If the LIST flag is not set, then the only valid number is 1. +occurs. If the LIST flag is not set, then the only valid numbers are +0 and 1. 0 often has a special meaning in this context as it actually +negates setting the option one or more times. If the option takes a number argument (ALT-TYPE is 2 or 3), and it can only occur once (LIST flag is not set), then the option argument is @@ -318,5 +320,5 @@ Example: $ dirmngr --gpgconf-list gpgconf-config-file:/mnt/marcus/.gnupg/dirmngr.conf ldapservers-file:/mnt/marcus/.gnupg/dirmngr_ldapservers.conf -add-servers: +add-servers:0 max-replies:10 -- cgit v1.2.3 From 18a212f2c8a75596d6ef39c4d29c018383e6089a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 24 Feb 2004 14:15:43 +0000 Subject: (list_cert_colon): Print the fingerprint as the cert-id for root certificates. --- sm/ChangeLog | 5 +++++ sm/keylist.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index e543bbcba..30c3d53df 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-02-24 Werner Koch <wk@gnupg.org> + + * keylist.c (list_cert_colon): Print the fingerprint as the + cert-id for root certificates. + 2004-02-21 Werner Koch <wk@gnupg.org> * keylist.c (list_internal_keys): Return error codes. diff --git a/sm/keylist.c b/sm/keylist.c index 3ebbe3ba3..6d48068b0 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -249,21 +249,27 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, /* FPR record */ fprintf (fp, "fpr:::::::::%s:::", fpr); - xfree (fpr); fpr = NULL; /* print chaining ID (field 13)*/ { ksba_cert_t next; + int rc; - if (!gpgsm_walk_cert_chain (cert, &next)) + rc = gpgsm_walk_cert_chain (cert, &next); + if (!rc) /* We known the issuer's certificate. */ { p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); fputs (p, fp); xfree (p); ksba_cert_release (next); } + else if (rc == -1) /* We reached the root certificate. */ + { + fputs (fpr, fp); + } } putc (':', fp); putc ('\n', fp); + xfree (fpr); fpr = NULL; if (opt.with_key_data) -- cgit v1.2.3 From 54d5446797fc4c1e40e36a74fa7fa12c87ba5ab9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 24 Feb 2004 14:31:59 +0000 Subject: 2004-02-24 Marcus Brinkmann <marcus@g10code.de> * README.gpgconf: Revert last change. Add new flags "default", "default desc" and "no arg desc". Add new field ARGDEF. Add new field FLAG to backend interface. * gpgconf-comp.c (struct gc_option): Make flags of type unsigned long. (gc_component_list_options): Adjust type for flags. Add default argument field. (retrieve_options_from_program): Use "1" as value for non-option arguments, not "Y". (gc_component_change_options): Read in flags from input. --- tools/ChangeLog | 13 ++++ tools/README.gpgconf | 140 ++++++++++++++++++++++++++++++++++------- tools/gpgconf-comp.c | 173 ++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 266 insertions(+), 60 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 1871f8b15..efb3794b9 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,16 @@ +2004-02-24 Marcus Brinkmann <marcus@g10code.de> + + * README.gpgconf: Revert last change. Add new flags "default", + "default desc" and "no arg desc". Add new field ARGDEF. Add new + field FLAG to backend interface. + * gpgconf-comp.c (struct gc_option): Make flags of type unsigned + long. + (gc_component_list_options): Adjust type for flags. + Add default argument field. + (retrieve_options_from_program): Use "1" as value for non-option + arguments, not "Y". + (gc_component_change_options): Read in flags from input. + 2004-02-23 Marcus Brinkmann <marcus@g10code.de> * README.gpgconf: Change meaning of type 0 options value if it is diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 848e1c59f..84fed518b 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -82,9 +82,8 @@ argument depends on the type of the option and on some flags: The simplest case is that the option does not take an argument at all (TYPE is 0). Then the option argument is either empty if the option is not set, or an unsigned number that specifies how often the option -occurs. If the LIST flag is not set, then the only valid numbers are -0 and 1. 0 often has a special meaning in this context as it actually -negates setting the option one or more times. +occurs. If the LIST flag is not set, then the only valid number is 1. +Options that don't take an argument never have the "default" flag set. If the option takes a number argument (ALT-TYPE is 2 or 3), and it can only occur once (LIST flag is not set), then the option argument is @@ -175,7 +174,7 @@ the next group and so on. The format of each line is: -NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:VALUE +NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE NAME @@ -189,13 +188,19 @@ FLAGS The flags field contains an unsigned number. Its value is the OR-wise combination of the following flag values: - 1 group If this flag is set, this is a line describing + 1 group If this flag is set, this is a line describing a group and not an option. - O 2 optional arg If this flag is set, the argument is optional. - O 4 list If this flag is set, the option can be given + O 2 optional arg If this flag is set, the argument is optional. + O 4 list If this flag is set, the option can be given multiple times. - O 8 runtime If this flag is set, the option can be changed + O 8 runtime If this flag is set, the option can be changed at runtime. + O 16 default If this flag is set, a default value is available. + O 32 default desc If this flag is set, a (runtime) default is available. + This and the 'default' flag are mutually exclusive. + O 64 no arg desc If this flag is set, and the 'optional arg' flag + is set, then the option has a special meaning if no + argument is given. Flags marked with a 'O' are only defined for options (ie, if the GROUP flag is not set). @@ -230,13 +235,16 @@ This field is only defined for options. It contains an unsigned number that specifies the type of the option's argument, if any. The following types are defined: - 0 none No argument allowed. - 1 string An unformatted string. - 2 int32 A signed integer number. - 3 uint32 An unsigned integer number. - 4 pathname A string that describes the pathname of a file. + Basic types + 0 none No argument allowed. + 1 string An unformatted string. + 2 int32 A signed integer number. + 3 uint32 An unsigned integer number. + + Complex types + 32 pathname A string that describes the pathname of a file. The file does not necessarily need to exist. - 5 ldap server A string that describes an LDAP server in the format + 33 ldap server A string that describes an LDAP server in the format HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. More types will be added in the future. Please see the ALT-TYPE field @@ -244,12 +252,14 @@ for information on how to cope with unknown types. ALT-TYPE -This field is identical to TYPE, except that only the types 0 to 3 are -allowed. The GUI is expected to present the user the option in the -format specified by TYPE. But if the argument type TYPE is not +This field is identical to TYPE, except that only the types 0 to 31 +are allowed. The GUI is expected to present the user the option in +the format specified by TYPE. But if the argument type TYPE is not supported by the GUI, it can still display the option in the more -generic basic type ALT-TYPE. The GUI must support the basic types 0 -to 3 to be able to display all options. +generic basic type ALT-TYPE. The GUI must support all the defined +basic types to be able to display all options. More basic types may +be added in future versions. If the GUI encounters a basic type it +doesn't support, it should report an error and abort the operation. ARGNAME @@ -267,6 +277,18 @@ value specifies the default value for this option. Note that this field is also meaningful if the option itself does not take a real argument. +ARGDEF + +This field is defined only for options for which the "optional arg" +flag is set. If the "no arg desc" flag is not set, its format is that +of an option argument (see section Format Conventions for details). +If the default value is empty, then no default is known. Otherwise, +the value specifies the default value for this option. If the "no arg +desc" flag is set, the field is either empty or contains a description +of the effect of this option if no argument is given. Note that this +field is also meaningful if the option itself does not take a real +argument. + VALUE This field is defined only for options. Its format is that of an @@ -283,18 +305,35 @@ CHANGING OPTIONS To change the options for a component, you must provide them in the following format: -NAME:NEW-VALUE +NAME:FLAGS:NEW-VALUE NAME This is the name of the option to change. +FLAGS + +The flags field contains an unsigned number. Its value is the +OR-wise combination of the following flag values: + + 16 default If this flag is set, the option is deleted and the + default value is used instead (if applicable). + NEW-VALUE -The new value for the option. The format is that of an option -argument. If it is empty (or the field is omitted), the option will -be deleted, so that the default value is used. Otherwise, the option -will be set to the specified value. +The new value for the option. This field is only defined if the +"default" flag is not set. The format is that of an option argument. +If it is empty (or the field is omitted), the default argument is used +(only allowed if the argument is optional for this option). +Otherwise, the option will be set to the specified value. + + +Example: +To set the option force, which is of basic type 0 (none). +$ echo 'force:0:1' | gpgconf --change-options dirmngr +To delete the option force: +$ echo 'force:16:0' | gpgconf --change-options dirmngr + Option --runtime ---------------- @@ -316,9 +355,62 @@ List the location of the configuration file, and all default values of all options. The location of the configuration file must be an absolute pathname. +The format of each line is: + +NAME:FLAGS:DEFAULT:ARGDEF + +NAME + +This field contains a name tag for the group or option. The name tag +is used to specify the group or option in all communication with +GPGConf. The name tag is to be used verbatim. It is not in any +escaped format. + +FLAGS + +The flags field contains an unsigned number. Its value is the +OR-wise combination of the following flag values: + + 16 default If this flag is set, a default value is available. + 32 default desc If this flag is set, a (runtime) default is available. + This and the "default" flag are mutually exclusive. + 64 no arg desc If this flag is set, and the "optional arg" flag + is set, then the option has a special meaning if no + argument is given. + +DEFAULT + +This field is defined only for options. Its format is that of an +option argument (see section Format Conventions for details). If the +default value is empty, then no default is known. Otherwise, the +value specifies the default value for this option. Note that this +field is also meaningful if the option itself does not take a real +argument. + +ARGDEF + +This field is defined only for options for which the "optional arg" +flag is set. If the "no arg desc" flag is not set, its format is that +of an option argument (see section Format Conventions for details). +If the default value is empty, then no default is known. Otherwise, +the value specifies the default value for this option. If the "no arg +desc" flag is set, the field is either empty or contains a description +of the effect of this option if no argument is given. Note that this +field is also meaningful if the option itself does not take a real +argument. + + Example: $ dirmngr --gpgconf-list gpgconf-config-file:/mnt/marcus/.gnupg/dirmngr.conf ldapservers-file:/mnt/marcus/.gnupg/dirmngr_ldapservers.conf add-servers:0 max-replies:10 + + +TODO +---- + +* Extend the backend interface to include gettext domain and +description, if available, to avoid repeating this information in +gpgconf. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 2065a6587..4dc2fbbe8 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -176,20 +176,21 @@ typedef enum /* An unsigned integer argument. */ GC_ARG_TYPE_UINT32 = 3, + /* ADD NEW BASIC TYPE ENTRIES HERE. */ /* Complex argument types. */ /* A complete pathname. */ - GC_ARG_TYPE_PATHNAME = 4, + GC_ARG_TYPE_PATHNAME = 32, /* An LDAP server in the format HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. */ - GC_ARG_TYPE_LDAP_SERVER = 5, + GC_ARG_TYPE_LDAP_SERVER = 33, /* A 40 character fingerprint. */ - GC_ARG_TYPE_KEY_FPR = 6, + GC_ARG_TYPE_KEY_FPR = 34, - /* ADD NEW ENTRIES HERE. */ + /* ADD NEW COMPLEX TYPE ENTRIES HERE. */ /* The number of the above entries. */ GC_ARG_TYPE_NR @@ -214,6 +215,22 @@ static struct { GC_ARG_TYPE_INT32, "int32" }, { GC_ARG_TYPE_UINT32, "uint32" }, + /* Reserved basic type entries for future extension. */ + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL }, + /* The complex argument types have a basic type as fallback. */ { GC_ARG_TYPE_STRING, "pathname" }, { GC_ARG_TYPE_STRING, "ldap server" }, @@ -266,21 +283,32 @@ static struct /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0 +#define GC_OPT_FLAG_NONE 0UL /* Some entries in the option list are not options, but mark the beginning of a new group of options. These entries have the GROUP flag set. */ -#define GC_OPT_FLAG_GROUP (1 << 0) +#define GC_OPT_FLAG_GROUP (1UL << 0) /* The ARG_OPT flag for an option indicates that the argument is optional. */ -#define GC_OPT_FLAG_ARG_OPT (1 << 1) +#define GC_OPT_FLAG_ARG_OPT (1UL << 1) /* The LIST flag for an option indicates that the option can occur several times. A comma separated list of arguments is used as the argument value. */ -#define GC_OPT_FLAG_LIST (1 << 2) +#define GC_OPT_FLAG_LIST (1UL << 2) /* The RUNTIME flag for an option indicates that the option can be changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1 << 3) +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + +/* The following flags are incorporated from the backend. */ +/* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) +/* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) +/* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) /* A human-readable description for each flag. */ static struct @@ -311,7 +339,7 @@ struct gc_option group marker, not an option, and only the fields LEVEL, DESC_DOMAIN and DESC are valid. In all other cases, this entry describes a new option and all fields are valid. */ - unsigned int flags; + unsigned long flags; /* The expert level. This field is valid for options and groups. A group has the expert level of the lowest-level option in the @@ -350,6 +378,11 @@ struct gc_option available, and otherwise a quoted string. */ char *default_value; + /* The default argument is only valid if the "optional arg" flag is + set, and specifies the default argument (value) that is used if + the argument is omitted. */ + char *default_arg; + /* The current value of this option. */ char *value; @@ -744,7 +777,7 @@ gc_component_list_options (int component, FILE *out) fprintf (out, "%s", option->name); /* The flags field. */ - fprintf (out, ":%u", option->flags); + fprintf (out, ":%lu", option->flags); if (opt.verbose) { putc (' ', out); @@ -753,9 +786,9 @@ gc_component_list_options (int component, FILE *out) fprintf (out, "none"); else { - unsigned int flags = option->flags; - unsigned int flag = 0; - unsigned int first = 1; + unsigned long flags = option->flags; + unsigned long flag = 0; + unsigned long first = 1; while (flags) { @@ -800,6 +833,9 @@ gc_component_list_options (int component, FILE *out) /* The default value field. */ fprintf (out, ":%s", option->default_value ? option->default_value : ""); + /* The default argument field. */ + fprintf (out, ":%s", option->default_arg ? option->default_arg : ""); + /* The value field. */ fprintf (out, ":%s", option->value ? option->value : ""); @@ -884,26 +920,53 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) while ((length = getline (&line, &line_len, config)) > 0) { gc_option_t *option; - char *value; - + char *linep; + unsigned long flags = 0; + char *default_value = NULL; + /* Strip newline and carriage return, if present. */ while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; + linep = strchr (line, ':'); + if (linep) + *(linep++) = '\0'; + + /* Extract additional flags. Default to none. */ + if (linep) + { + char *end; + char *tail; + + end = strchr (linep, ':'); + if (end) + *(end++) = '\0'; + + errno = 0; + flags = strtoul (linep, &tail, 0); + if (errno) + gc_error (1, errno, "malformed flags in option %s from %s", line, cmd_line); + if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) + gc_error (1, 0, "garbage after flags in option %s from %s", line, cmd_line); + + linep = end; + } + /* Extract default value, if present. Default to empty if not. */ - value = strchr (line, ':'); - if (!value) - value = ""; - else + if (linep) { char *end; - *(value++) = '\0'; - end = strchr (value, ':'); + end = strchr (linep, ':'); if (end) - *end = '\0'; + *(end++) = '\0'; + + if (flags & GC_OPT_FLAG_DEFAULT) + default_value = linep; + + linep = end; } /* Look up the option in the component and install the @@ -915,8 +978,10 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) gc_error (1, errno, "option %s returned twice from %s", line, cmd_line); option->active = 1; - if (*value) - option->default_value = xstrdup (value); + + option->flags |= flags; + if (default_value && *default_value) + option->default_value = xstrdup (default_value); } } if (ferror (config)) @@ -981,7 +1046,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) gc_error (0, 0, "warning: ignoring argument %s for option %s", value, name); - opt_value = xstrdup ("Y"); + opt_value = xstrdup ("1"); } else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) @@ -1011,6 +1076,8 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) == GC_ARG_TYPE_STRING) opt_val++; + /* FIXME. For type none arguments, this is + wrong. */ option->value = xasprintf ("%s,%s", option->value, opt_val); xfree (opt_value); @@ -1411,32 +1478,66 @@ gc_component_change_options (int component, FILE *in) while ((length = getline (&line, &line_len, in)) > 0) { - char *value; + char *linep; + unsigned long flags = 0; + char *new_value = NULL; /* Strip newline and carriage return, if present. */ while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; - value = strchr (line, ':'); - if (!value) - value = ""; - else + linep = strchr (line, ':'); + if (linep) + *(linep++) = '\0'; + + /* Extract additional flags. Default to none. */ + if (linep) + { + char *end; + char *tail; + + end = strchr (linep, ':'); + if (end) + *(end++) = '\0'; + + errno = 0; + flags = strtoul (linep, &tail, 0); + if (errno) + gc_error (1, errno, "malformed flags in option %s", line); + if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) + gc_error (1, 0, "garbage after flags in option %s", line); + + linep = end; + } + + /* Extract default value, if present. Default to empty if + not. */ + if (linep) { char *end; - *(value++) = '\0'; - end = strchr (value, ':'); + end = strchr (linep, ':'); if (end) - *end = '\0'; + *(end++) = '\0'; + + if (!(flags & GC_OPT_FLAG_DEFAULT)) + new_value = linep; + + linep = end; } option = find_option (component, line, GC_BACKEND_ANY); if (!option) gc_error (1, 0, "unknown option %s", line); - option_check_validity (option, value); - option->new_value = xstrdup (value); + /* FIXME: This is not correct, as it ignores the optional arg + case. */ + if (flags & GC_OPT_FLAG_DEFAULT) + new_value = ""; + + option_check_validity (option, new_value); + option->new_value = xstrdup (new_value); } /* Now that we have collected and locally verified the changes, -- cgit v1.2.3 From 9d988d60683c5411754c9963e03ea4a37837567b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 25 Feb 2004 08:58:46 +0000 Subject: New option --disable-threads to inhibit unintentional builds without Pth. --- ChangeLog | 5 ++++ TODO | 5 ++++ configure.ac | 97 +++++++++++++++++++++++++++++++++++++----------------------- 3 files changed, 70 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index be4f47ef2..5fbf045d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/TODO b/TODO index 496babfdc..f3a66f08c 100644 --- a/TODO +++ b/TODO @@ -33,6 +33,11 @@ might want to have an agent context for each service request ** 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 diff --git a/configure.ac b/configure.ac index f9cfce22d..aed97fd8f 100644 --- a/configure.ac +++ b/configure.ac @@ -484,6 +484,11 @@ fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) +AC_ARG_ENABLE(threads, + AC_HELP_STRING([--disable-threads],[allow building without Pth support]); + +) + dnl Must check for network library requirements before doing link tests dnl for ldap, for example. If ldap libs are static (or dynamic and without @@ -954,6 +959,46 @@ AC_DEFINE(HAVE_JNLIB_LOGGING, 1, +# +# Decide what to build +# +missing_pth=no +if test $have_ksba = no; then + build_gpgsm=no + build_scdaemon=no +fi + +build_agent_threaded="" +if test "$build_agent" = "yes"; then + if test $have_pth = no; then + build_agent_threaded="(not multi-threaded)" + missing_pth=yes + fi +fi + +build_scdaemon_extra="" +if test "$build_scdaemon" = "yes"; then + tmp="" + if test $have_pth = no; then + build_scdaemon_extra="not multi-threaded" + tmp=", " + missing_pth=yes + fi + if test $have_opensc = no; then + build_scdaemon_extra="${build_scdaemon_extra}${tmp}no pkcs#15" + tmp=", " + fi + if test -n "$build_scdaemon_extra"; then + build_scdaemon_extra="(${build_scdaemon_extra})" + fi +fi + +AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") +AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") +AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") +AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") + + # # Print errors here so that they are visible all @@ -1000,6 +1045,21 @@ if test "$have_ksba" = "no"; then *** (at least version $NEED_KSBA_VERSION is required). ***]]) fi +if test "$missing_pth" = "yes"; then + AC_MSG_NOTICE([[ +*** +*** It is strongly suggested to build with support for the +*** GNU Portable Threads Library (Pth). Please install this +*** library first or use --disable-threads to allow building +*** anyway. The library is for example available at +*** ftp://ftp.gnu.org/gnu/pth/ +*** On a Debian GNU/Linux system you can install it using +*** apt-get install libpth-dev +***]]) + if test "$enable_threads" != "no"; then + die=yes + fi +fi if test "$die" = "yes"; then AC_MSG_ERROR([[ @@ -1010,43 +1070,6 @@ if test "$die" = "yes"; then fi -# -# Decide what to build -# -if test $have_ksba = no; then - build_gpgsm=no - build_scdaemon=no -fi - -build_agent_threaded="" -if test "$build_agent" = "yes"; then - if test $have_pth = no; then - build_agent_threaded="(not multi-threaded)" - fi -fi - -build_scdaemon_extra="" -if test "$build_scdaemon" = "yes"; then - tmp="" - if test $have_pth = no; then - build_scdaemon_extra="not multi-threaded" - tmp=", " - fi - if test $have_opensc = no; then - build_scdaemon_extra="${build_scdaemon_extra}${tmp}no pkcs#15" - tmp=", " - fi - if test -n "$build_scdaemon_extra"; then - build_scdaemon_extra="(${build_scdaemon_extra})" - fi -fi - - -AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") -AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") -AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") -AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") - AC_CONFIG_FILES([ m4/Makefile Makefile -- cgit v1.2.3 From 8f8c5c47dd9495d1d4236ee632cd4e8193cb8607 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 25 Feb 2004 19:35:36 +0000 Subject: 2004-02-25 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_list_options): Correct output for lists of arg type none. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index efb3794b9..b98e4c559 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-02-25 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (gc_component_list_options): Correct output for + lists of arg type none. + 2004-02-24 Marcus Brinkmann <marcus@g10code.de> * README.gpgconf: Revert last change. Add new flags "default", diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 4dc2fbbe8..8e143010f 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -837,7 +837,14 @@ gc_component_list_options (int component, FILE *out) fprintf (out, ":%s", option->default_arg ? option->default_arg : ""); /* The value field. */ - fprintf (out, ":%s", option->value ? option->value : ""); + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE + && (option->flags & GC_OPT_FLAG_LIST) + && option->value) + /* The special format "1,1,1,1,...,1" is converted to a number + here. */ + fprintf (out, ":%u", (strlen (option->value) + 1) / 2); + else + fprintf (out, ":%s", option->value ? option->value : ""); /* ADD NEW FIELDS HERE. */ -- cgit v1.2.3 From 8817c66900b5f23b568d0cd7642739c050aa127b Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 25 Feb 2004 20:24:53 +0000 Subject: 2004-02-25 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (struct gc_option): Add new member new_flags. (option_check_validity): Check OPTION->new_flags beside OPTION->new_value. Add new argument FLAGS. (gc_component_change_options): Support default flag correctly. (change_options_program): Likewise. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 35 +++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index b98e4c559..fab5cafec 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -2,6 +2,11 @@ * gpgconf-comp.c (gc_component_list_options): Correct output for lists of arg type none. + (struct gc_option): Add new member new_flags. + (option_check_validity): Check OPTION->new_flags beside + OPTION->new_value. Add new argument FLAGS. + (gc_component_change_options): Support default flag correctly. + (change_options_program): Likewise. 2004-02-24 Marcus Brinkmann <marcus@g10code.de> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 8e143010f..ee980c5da 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -386,6 +386,11 @@ struct gc_option /* The current value of this option. */ char *value; + /* The new flags for this option. The only defined flag is actually + GC_OPT_FLAG_DEFAULT, and it means that the option should be + deleted. In this case, NEW_VALUE is NULL. */ + unsigned long new_flags; + /* The new value of this option. */ char *new_value; }; @@ -1213,11 +1218,16 @@ gc_component_retrieve_options (int component) /* Perform a simple validity check based on the type. */ static void -option_check_validity (gc_option_t *option, const char *new_value) +option_check_validity (gc_option_t *option, unsigned long flags, + const char *new_value) { - if (option->new_value) + if (option->new_flags || option->new_value) gc_error (1, 0, "option %s already changed", option->name); + if ((flags & GC_OPT_FLAG_DEFAULT) && *new_value) + gc_error (1, 0, "value %s provided for deleted option %s", + new_value, option->name); + if (!*new_value) return; @@ -1332,7 +1342,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, option = find_option (component, start, backend); *end = saved_end; - if (option && option->new_value) + if (option && (option->new_flags & GC_OPT_FLAG_DEFAULT)) disable = 1; } if (disable) @@ -1379,7 +1389,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, option = gc_component[component].options; while (option->name) { - /* FIXME: Add support for lists. */ + /* FIXME: Add support for lists and default arg (new_value eq ""). */ if (!(option->flags & GC_OPT_FLAG_GROUP) && option->backend == backend && option->new_value @@ -1487,7 +1497,7 @@ gc_component_change_options (int component, FILE *in) { char *linep; unsigned long flags = 0; - char *new_value = NULL; + char *new_value = ""; /* Strip newline and carriage return, if present. */ while (length > 0 @@ -1528,8 +1538,7 @@ gc_component_change_options (int component, FILE *in) if (end) *(end++) = '\0'; - if (!(flags & GC_OPT_FLAG_DEFAULT)) - new_value = linep; + new_value = linep; linep = end; } @@ -1538,13 +1547,11 @@ gc_component_change_options (int component, FILE *in) if (!option) gc_error (1, 0, "unknown option %s", line); - /* FIXME: This is not correct, as it ignores the optional arg - case. */ - if (flags & GC_OPT_FLAG_DEFAULT) - new_value = ""; + option_check_validity (option, flags, new_value); - option_check_validity (option, new_value); - option->new_value = xstrdup (new_value); + option->new_flags = flags; + if (!(flags & GC_OPT_FLAG_DEFAULT)) + option->new_value = xstrdup (new_value); } /* Now that we have collected and locally verified the changes, @@ -1555,7 +1562,7 @@ gc_component_change_options (int component, FILE *in) { /* Go on if we have already seen this backend, or if there is nothing to do. */ - if (src_pathname[option->backend] || !option->new_value) + if (src_pathname[option->backend] || !(option->new_flags || option->new_value)) { option++; continue; -- cgit v1.2.3 From 7aa4fa9b095a70fb1c1049c9e61dbd6c9d96eeac Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 26 Feb 2004 16:28:27 +0000 Subject: 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * README.gpgconf (NAME): Add info about optional arg and arg type 0. * gpgconf-comp.c (gc_component_change_options): Parse list of arg type 0 options. (option_check_validity): Add new argument NEW_VALUE_NR. Perform rigorous validity checks. (change_options_program): Disable an option also if we have a new value for it. --- tools/ChangeLog | 10 ++++ tools/README.gpgconf | 1 + tools/gpgconf-comp.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 141 insertions(+), 13 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index fab5cafec..69af2eb99 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,13 @@ +2004-02-26 Marcus Brinkmann <marcus@g10code.de> + + * README.gpgconf (NAME): Add info about optional arg and arg type 0. + * gpgconf-comp.c (gc_component_change_options): Parse list of + arg type 0 options. + (option_check_validity): Add new argument NEW_VALUE_NR. Perform + rigorous validity checks. + (change_options_program): Disable an option also if we have a new + value for it. + 2004-02-25 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_list_options): Correct output for diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 84fed518b..2f6a2e073 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -191,6 +191,7 @@ OR-wise combination of the following flag values: 1 group If this flag is set, this is a line describing a group and not an option. O 2 optional arg If this flag is set, the argument is optional. + This is never set for arg type 0 (none) options. O 4 list If this flag is set, the option can be given multiple times. O 8 runtime If this flag is set, the option can be changed diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index ee980c5da..dc8de903c 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -289,7 +289,7 @@ static struct flag set. */ #define GC_OPT_FLAG_GROUP (1UL << 0) /* The ARG_OPT flag for an option indicates that the argument is - optional. */ + optional. This is never set for GC_ARG_TYPE_NONE options. */ #define GC_OPT_FLAG_ARG_OPT (1UL << 1) /* The LIST flag for an option indicates that the option can occur several times. A comma separated list of arguments is used as the @@ -1216,23 +1216,116 @@ gc_component_retrieve_options (int component) } -/* Perform a simple validity check based on the type. */ +/* Perform a simple validity check based on the type. Return in + NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of + type GC_ARG_TYPE_NONE. */ static void option_check_validity (gc_option_t *option, unsigned long flags, - const char *new_value) + char *new_value, unsigned long *new_value_nr) { if (option->new_flags || option->new_value) gc_error (1, 0, "option %s already changed", option->name); - if ((flags & GC_OPT_FLAG_DEFAULT) && *new_value) - gc_error (1, 0, "value %s provided for deleted option %s", - new_value, option->name); + if (flags & GC_OPT_FLAG_DEFAULT) + { + if (*new_value) + gc_error (1, 0, "argument %s provided for deleted option %s", + new_value, option->name); + } + else + { + /* This is even correct for GC_ARG_TYPE_NONE options, for which + GC_OPT_FLAG_ARG_OPT is never set. */ + if (!(option->flags & GC_OPT_FLAG_ARG_OPT) && (*new_value == '\0')) + gc_error (1, 0, "no argument for option %s", option->name); + + if (*new_value) + { + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) + { + char *tail; + + errno = 0; + *new_value_nr = strtoul (new_value, &tail, 0); + + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + if (*tail) + gc_error (1, 0, "garbage after argument for option %s", + option->name); + + if (!(option->flags & GC_OPT_FLAG_LIST)) + { + if (*new_value_nr != 1) + gc_error (1, 0, "argument for non-list option %s of type 0 " + "(none) must be 1", option->name); + } + else + { + if (*new_value_nr == 0) + gc_error (1, 0, "argument for option %s of type 0 (none) " + "must be positive", option->name); + } + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) + { + if (*new_value != '"') + gc_error (1, 0, "string argument for option %s must begin " + "with a quote (\") character", option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) + { + char *tail = new_value; + + while (*tail) + { + errno = 0; + (void) strtol (new_value, &tail, 0); - if (!*new_value) - return; + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + if (*tail == ',') + { + if (!(option->flags & GC_OPT_FLAG_LIST)) + gc_error (1, 0, "list found for non-list option %s", + option->name); + tail++; + } + else if (*tail) + gc_error (1, 0, "garbage after argument for option %s", + option->name); + } + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_UINT32) + { + char *tail = new_value; - /* FIXME. Verify that lists are lists, numbers are numbers, strings - are strings, etc. */ + while (*tail) + { + errno = 0; + (void) strtoul (new_value, &tail, 0); + + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + if (*tail == ',') + { + if (!(option->flags & GC_OPT_FLAG_LIST)) + gc_error (1, 0, "list found for non-list option %s", + option->name); + tail++; + } + else if (*tail) + gc_error (1, 0, "garbage after argument for option %s", + option->name); + } + } + else + assert (!"Unexpected argument type"); + } + } } @@ -1342,7 +1435,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, option = find_option (component, start, backend); *end = saved_end; - if (option && (option->new_flags & GC_OPT_FLAG_DEFAULT)) + if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT) + || option->new_value)) disable = 1; } if (disable) @@ -1472,6 +1566,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, return -1; } + /* Read the modifications from IN and apply them. */ void gc_component_change_options (int component, FILE *in) @@ -1498,6 +1593,7 @@ gc_component_change_options (int component, FILE *in) char *linep; unsigned long flags = 0; char *new_value = ""; + unsigned long new_value_nr; /* Strip newline and carriage return, if present. */ while (length > 0 @@ -1547,11 +1643,32 @@ gc_component_change_options (int component, FILE *in) if (!option) gc_error (1, 0, "unknown option %s", line); - option_check_validity (option, flags, new_value); + option_check_validity (option, flags, new_value, &new_value_nr); option->new_flags = flags; if (!(flags & GC_OPT_FLAG_DEFAULT)) - option->new_value = xstrdup (new_value); + { + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE + && (option->flags & GC_OPT_FLAG_LIST)) + { + char *str; + + /* We convert the number to a list of 1's for + convenient list handling. */ + assert (new_value_nr > 0); + option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1); + str = option->new_value; + *(str++) = '1'; + while (--new_value_nr > 0) + { + *(str++) = ','; + *(str++) = '1'; + } + *(str++) = '\0'; + } + else + option->new_value = xstrdup (new_value); + } } /* Now that we have collected and locally verified the changes, -- cgit v1.2.3 From 255d2cea0435ad834581726ef2a424b1626c9872 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 26 Feb 2004 18:22:02 +0000 Subject: 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * README.gpgconf: Fix description of arguments. * gpgconf-comp.c (option_check_validity): Rewritten to properly support optional arguments in lists. --- tools/ChangeLog | 6 +- tools/README.gpgconf | 31 +++++------ tools/gpgconf-comp.c | 155 ++++++++++++++++++++++++--------------------------- 3 files changed, 92 insertions(+), 100 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 69af2eb99..154ec55e8 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,6 +1,10 @@ 2004-02-26 Marcus Brinkmann <marcus@g10code.de> - * README.gpgconf (NAME): Add info about optional arg and arg type 0. + * README.gpgconf: Fix description of arguments. + * gpgconf-comp.c (option_check_validity): Rewritten to properly + support optional arguments in lists. + + * README.gpgconf: Add info about optional arg and arg type 0. * gpgconf-comp.c (gc_component_change_options): Parse list of arg type 0 options. (option_check_validity): Add new argument NEW_VALUE_NR. Perform diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 2f6a2e073..0973939d0 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -80,17 +80,17 @@ Some fields contain an option argument. The format of an option argument depends on the type of the option and on some flags: The simplest case is that the option does not take an argument at all -(TYPE is 0). Then the option argument is either empty if the option -is not set, or an unsigned number that specifies how often the option -occurs. If the LIST flag is not set, then the only valid number is 1. -Options that don't take an argument never have the "default" flag set. +(TYPE is 0). Then the option argument is an unsigned number that +specifies how often the option occurs. If the LIST flag is not set, +then the only valid number is 1. Options that don't take an argument +never have the "default" or "optional arg" flag set. If the option takes a number argument (ALT-TYPE is 2 or 3), and it can only occur once (LIST flag is not set), then the option argument is -either empty if the option is not set, or it is a number. A number is -a string that begins with an optional minus character, followed by one -or more digits. The number must fit into an integer variable -(unsigned or signed, depending on ALT-TYPE). +either empty (only allowed if the argument is optional), or it is a +number. A number is a string that begins with an optional minus +character, followed by one or more digits. The number must fit into +an integer variable (unsigned or signed, depending on ALT-TYPE). If the option takes a number argument and it can occur more than once, then the option argument is either empty, or it is a comma-separated @@ -98,19 +98,16 @@ list of numbers as described above. If the option takes a string argument (ALT-TYPE is 1), and it can only occur once (LIST flag is not set) then the option argument is either -empty if the option is not set, or it starts with a double quote -character (") followed by a percent-escaped string that is the -argument value. Note that there is only a leading double quote +empty (only allowed if the argument is optional), or it starts with a +double quote character (") followed by a percent-escaped string that +is the argument value. Note that there is only a leading double quote character, no trailing one. The double quote character is only needed to be able to differentiate between no value and the empty string as value. -If the option takes a string argument and it can occur more than once, -then the option argument is either empty or it starts with a double -quote character (") followed by a comma-separated list of -percent-escaped strings. Obviously any commas in the individual -strings must be percent-escaped. - +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of string arguments as described above. FIXME: Document the active language and active character set. Allow to change it via the command line? diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index dc8de903c..524f2170d 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1223,6 +1223,8 @@ static void option_check_validity (gc_option_t *option, unsigned long flags, char *new_value, unsigned long *new_value_nr) { + char *arg; + if (option->new_flags || option->new_value) gc_error (1, 0, "option %s already changed", option->name); @@ -1231,101 +1233,89 @@ option_check_validity (gc_option_t *option, unsigned long flags, if (*new_value) gc_error (1, 0, "argument %s provided for deleted option %s", new_value, option->name); + + return; } - else + + /* GC_ARG_TYPE_NONE options have special list treatment. */ + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) { - /* This is even correct for GC_ARG_TYPE_NONE options, for which - GC_OPT_FLAG_ARG_OPT is never set. */ - if (!(option->flags & GC_OPT_FLAG_ARG_OPT) && (*new_value == '\0')) - gc_error (1, 0, "no argument for option %s", option->name); + char *tail; - if (*new_value) + errno = 0; + *new_value_nr = strtoul (new_value, &tail, 0); + + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); + if (*tail) + gc_error (1, 0, "garbage after argument for option %s", + option->name); + + if (!(option->flags & GC_OPT_FLAG_LIST)) { - if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE) - { - char *tail; + if (*new_value_nr != 1) + gc_error (1, 0, "argument for non-list option %s of type 0 " + "(none) must be 1", option->name); + } + else + { + if (*new_value_nr == 0) + gc_error (1, 0, "argument for option %s of type 0 (none) " + "must be positive", option->name); + } - errno = 0; - *new_value_nr = strtoul (new_value, &tail, 0); + return; + } - if (errno) - gc_error (1, errno, "invalid argument for option %s", - option->name); - if (*tail) - gc_error (1, 0, "garbage after argument for option %s", - option->name); + arg = new_value; + do + { + if (*arg == '\0' || *arg == ',') + { + if (!(option->flags & GC_OPT_FLAG_ARG_OPT)) + gc_error (1, 0, "argument required for option %s", option->name); - if (!(option->flags & GC_OPT_FLAG_LIST)) - { - if (*new_value_nr != 1) - gc_error (1, 0, "argument for non-list option %s of type 0 " - "(none) must be 1", option->name); - } - else - { - if (*new_value_nr == 0) - gc_error (1, 0, "argument for option %s of type 0 (none) " - "must be positive", option->name); - } - } - else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) - { - if (*new_value != '"') - gc_error (1, 0, "string argument for option %s must begin " - "with a quote (\") character", option->name); - } - else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) - { - char *tail = new_value; + if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST)) + gc_error (1, 0, "list found for non-list option %s", option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) + { + if (*arg != '"') + gc_error (1, 0, "string argument for option %s must begin " + "with a quote (\") character", option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) + { + errno = 0; + (void) strtol (arg, &arg, 0); - while (*tail) - { - errno = 0; - (void) strtol (new_value, &tail, 0); + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); - if (errno) - gc_error (1, errno, "invalid argument for option %s", - option->name); - if (*tail == ',') - { - if (!(option->flags & GC_OPT_FLAG_LIST)) - gc_error (1, 0, "list found for non-list option %s", - option->name); - tail++; - } - else if (*tail) - gc_error (1, 0, "garbage after argument for option %s", - option->name); - } - } - else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_UINT32) - { - char *tail = new_value; + if (*arg != '\0' && *arg != ',') + gc_error (1, 0, "garbage after argument for option %s", + option->name); + } + else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32) + { + errno = 0; + (void) strtoul (arg, &arg, 0); - while (*tail) - { - errno = 0; - (void) strtoul (new_value, &tail, 0); + if (errno) + gc_error (1, errno, "invalid argument for option %s", + option->name); - if (errno) - gc_error (1, errno, "invalid argument for option %s", - option->name); - if (*tail == ',') - { - if (!(option->flags & GC_OPT_FLAG_LIST)) - gc_error (1, 0, "list found for non-list option %s", - option->name); - tail++; - } - else if (*tail) - gc_error (1, 0, "garbage after argument for option %s", - option->name); - } - } - else - assert (!"Unexpected argument type"); + if (*arg != '\0' && *arg != ',') + gc_error (1, 0, "garbage after argument for option %s", + option->name); } + arg = strchr (arg, ','); + if (arg) + arg++; } + while (arg && *arg); } @@ -1377,6 +1367,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, xfree (orig_filename); orig_filename = NULL; } + /* We now initialize the return strings, so the caller can do the cleanup for us. */ *src_filenamep = src_filename; -- cgit v1.2.3 From aa7a4c1aec98d5a730059ef956cd85867523a00d Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 26 Feb 2004 18:39:34 +0000 Subject: 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (change_options_program): Support all types of options, including list types. --- tools/ChangeLog | 5 +++- tools/README.gpgconf | 8 ++++++ tools/gpgconf-comp.c | 77 ++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 154ec55e8..57c52f437 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,9 +1,12 @@ 2004-02-26 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (change_options_program): Support all types of + options, including list types. + * README.gpgconf: Fix description of arguments. * gpgconf-comp.c (option_check_validity): Rewritten to properly support optional arguments in lists. - + * README.gpgconf: Add info about optional arg and arg type 0. * gpgconf-comp.c (gc_component_change_options): Parse list of arg type 0 options. diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 0973939d0..03fd9daa7 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -412,3 +412,11 @@ TODO * Extend the backend interface to include gettext domain and description, if available, to avoid repeating this information in gpgconf. + +* Left out string arguments (optional) are written out exactly as +empty string arguments. Should we do quoting? + +* More string argument trouble: Special characters like newlines etc +cause trouble. Again, should we do quoting? + + diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 524f2170d..3b9927f61 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1474,21 +1474,73 @@ change_options_program (gc_component_t component, gc_backend_t backend, option = gc_component[component].options; while (option->name) { - /* FIXME: Add support for lists and default arg (new_value eq ""). */ if (!(option->flags & GC_OPT_FLAG_GROUP) && option->backend == backend - && option->new_value - && *option->new_value) + && option->new_value) { - if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING) - fprintf (src_file, "%s %s\n", option->name, - percent_deescape (&option->new_value[1])); - else if (option->arg_type == GC_ARG_TYPE_NONE) - fprintf (src_file, "%s\n", option->name); - else - fprintf (src_file, "%s %s\n", option->name, option->new_value); - if (ferror (src_file)) - goto change_one_err; + char *arg = option->new_value; + + do + { + if (*arg == '\0' || *arg == ',') + { + fprintf (src_file, "%s\n", option->name); + if (ferror (src_file)) + goto change_one_err; + } + else if (gc_arg_type[option->arg_type].fallback + == GC_ARG_TYPE_NONE) + { + assert (*arg == '1'); + fprintf (src_file, "%s\n", option->name); + if (ferror (src_file)) + goto change_one_err; + + arg++; + } + else if (gc_arg_type[option->arg_type].fallback + == GC_ARG_TYPE_STRING) + { + char *end; + + assert (*arg == '"'); + arg++; + + end = strchr (arg, ','); + if (end) + *end = '\0'; + + fprintf (src_file, "%s %s\n", option->name, + percent_deescape (arg)); + if (ferror (src_file)) + goto change_one_err; + + if (end) + *end = ','; + arg = end; + } + else + { + char *end; + + end = strchr (arg, ','); + if (end) + *end = '\0'; + + fprintf (src_file, "%s %s\n", option->name, arg); + if (ferror (src_file)) + goto change_one_err; + + if (end) + *end = ','; + arg = end; + } + + assert (arg == NULL || *arg == '\0' || *arg == ','); + if (arg && *arg == ',') + arg++; + } + while (arg && *arg); } option++; } @@ -1692,6 +1744,7 @@ gc_component_change_options (int component, FILE *in) option++; } + if (!err) { int i; -- cgit v1.2.3 From bfd5ed026ce2fc344cbc4b550a118ce492811939 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 26 Feb 2004 18:54:46 +0000 Subject: 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (retrieve_options_from_program): Remove broken string handling. --- tools/ChangeLog | 3 +++ tools/gpgconf-comp.c | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 57c52f437..084028c15 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,8 @@ 2004-02-26 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (retrieve_options_from_program): Remove broken + string handling. + * gpgconf-comp.c (change_options_program): Support all types of options, including list types. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 3b9927f61..e56f9c49f 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1084,12 +1084,6 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) { char *opt_val = opt_value; - if (gc_arg_type[option->arg_type].fallback - == GC_ARG_TYPE_STRING) - opt_val++; - - /* FIXME. For type none arguments, this is - wrong. */ option->value = xasprintf ("%s,%s", option->value, opt_val); xfree (opt_value); -- cgit v1.2.3 From cd8531210b6cd768a0be29e0c8b6138c631172a7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 26 Feb 2004 22:08:58 +0000 Subject: (compare_certs): New. (gpgsm_validate_chain): Fixed infinite certificate checks after bad signatures. --- sm/ChangeLog | 6 ++++++ sm/certchain.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 30c3d53df..f6716b0a4 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-02-26 Werner Koch <wk@gnupg.org> + + * certchain.c (compare_certs): New. + (gpgsm_validate_chain): Fixed infinite certificate checks after + bad signatures. + 2004-02-24 Werner Koch <wk@gnupg.org> * keylist.c (list_cert_colon): Print the fingerprint as the diff --git a/sm/certchain.c b/sm/certchain.c index 2a59c559d..bb3fd0339 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -65,6 +65,22 @@ do_list (int is_error, int listmode, FILE *fp, const char *format, ...) va_end (arg_ptr); } +/* Return 0 if A and B are equal. */ +static int +compare_certs (ksba_cert_t a, ksba_cert_t b) +{ + const unsigned char *img_a, *img_b; + size_t len_a, len_b; + + img_a = ksba_cert_get_image (a, &len_a); + if (!img_a) + return 1; + img_b = ksba_cert_get_image (b, &len_b); + if (!img_b) + return 1; + return !(len_a == len_b && !memcmp (img_a, img_b, len_a)); +} + static int unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp) @@ -700,7 +716,6 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, goto leave; } - try_another_cert: ksba_cert_release (issuer_cert); issuer_cert = NULL; rc = keydb_get_cert (kh, &issuer_cert); if (rc) @@ -710,6 +725,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, goto leave; } + try_another_cert: if (DBG_X509) { log_debug ("got issuer's certificate:\n"); @@ -722,12 +738,32 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, do_list (0, lm, fp, _("certificate has a BAD signature")); if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE) { + /* We now try to find other issuer certificates which + might have been used. This is rquired because some + CAs are reusing the issuer and subject DN for new + root certificates. */ rc = find_up (kh, subject_cert, issuer, 1); if (!rc) { - do_list (0, lm, fp, _("found another possible matching " - "CA certificate - trying again")); - goto try_another_cert; + ksba_cert_t tmp_cert; + + rc = keydb_get_cert (kh, &tmp_cert); + if (rc || !compare_certs (issuer_cert, tmp_cert)) + { + /* The find next did not work or returned an + identical certificate. We better stop here + to avoid infinite checks. */ + rc = gpg_error (GPG_ERR_BAD_SIGNATURE); + ksba_cert_release (tmp_cert); + } + else + { + do_list (0, lm, fp, _("found another possible matching " + "CA certificate - trying again")); + ksba_cert_release (issuer_cert); + issuer_cert = tmp_cert; + goto try_another_cert; + } } } -- cgit v1.2.3 From 91a514f2a1b45fb4bd750bcd9ac44fdcf6ff78d7 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 26 Feb 2004 22:18:36 +0000 Subject: 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (option_check_validity): Check if option is active. (change_options_file): Implement. --- tools/ChangeLog | 4 + tools/gpgconf-comp.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 292 insertions(+), 3 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 084028c15..1821d8b93 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,9 @@ 2004-02-26 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (option_check_validity): Check if option is + active. + (change_options_file): Implement. + * gpgconf-comp.c (retrieve_options_from_program): Remove broken string handling. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e56f9c49f..bbf0649a9 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1219,6 +1219,9 @@ option_check_validity (gc_option_t *option, unsigned long flags, { char *arg; + if (!option->active) + gc_error (1, 0, "option %s not supported by backend", option->name); + if (option->new_flags || option->new_value) gc_error (1, 0, "option %s already changed", option->name); @@ -1320,8 +1323,290 @@ change_options_file (gc_component_t component, gc_backend_t backend, char **src_filenamep, char **dest_filenamep, char **orig_filenamep) { - /* FIXME. */ - assert (!"Not implemented."); + static const char marker[] = "###+++--- GPGConf ---+++###"; + /* True if we are within the marker in the config file. */ + int in_marker = 0; + gc_option_t *option; + char *line = NULL; + size_t line_len; + ssize_t length; + int res; + int fd; + FILE *src_file = NULL; + FILE *dest_file = NULL; + char *src_filename; + char *dest_filename; + char *orig_filename; + char *arg; + char *cur_arg = NULL; + + option = find_option (component, + gc_backend[backend].option_name, GC_BACKEND_ANY); + assert (option); + assert (option->active); + assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE); + assert (!(option->flags & GC_OPT_FLAG_ARG_OPT)); + + /* FIXME. Throughout the function, do better error reporting. */ + /* Note that get_config_pathname() calls percent_deescape(), so we + call this before processing the arguments. */ + dest_filename = xstrdup (get_config_pathname (component, backend)); + src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ()); + orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ()); + + arg = option->new_value; + if (arg) + { + char *end; + + arg++; + end = strchr (arg, ','); + if (end) + *end = '\0'; + + cur_arg = percent_deescape (arg); + if (end) + { + *end = ','; + arg = end + 1; + } + else + arg = NULL; + } + + res = link (dest_filename, orig_filename); + if (res < 0 && errno != ENOENT) + return -1; + if (res < 0) + { + xfree (orig_filename); + orig_filename = NULL; + } + + /* We now initialize the return strings, so the caller can do the + cleanup for us. */ + *src_filenamep = src_filename; + *dest_filenamep = dest_filename; + *orig_filenamep = orig_filename; + + /* Use open() so that we can use O_EXCL. */ + fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd < 0) + return -1; + src_file = fdopen (fd, "w"); + res = errno; + if (!src_file) + { + errno = res; + return -1; + } + + /* Only if ORIG_FILENAME is not NULL did the configuration file + exist already. In this case, we will copy its content into the + new configuration file, changing it to our liking in the + process. */ + if (orig_filename) + { + dest_file = fopen (dest_filename, "r"); + if (!dest_file) + goto change_file_one_err; + + while ((length = getline (&line, &line_len, dest_file)) > 0) + { + int disable = 0; + char *start; + + if (!strncmp (marker, line, sizeof (marker) - 1)) + { + if (!in_marker) + in_marker = 1; + else + break; + } + + start = line; + while (*start == ' ' || *start == '\t') + start++; + if (*start && *start != '\r' && *start != '\n' && *start != '#') + { + char *end; + char *endp; + char saved_end; + + endp = start; + end = endp; + + /* Search for the end of the line. */ + while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n') + { + endp++; + if (*endp && *endp != ' ' && *endp != '\t' + && *endp != '\r' && *endp != '\n' && *endp != '#') + end = endp + 1; + } + saved_end = *end; + *end = '\0'; + + if ((option->new_flags & GC_OPT_FLAG_DEFAULT) + || !cur_arg || strcmp (start, cur_arg)) + disable = 1; + else + { + /* Find next argument. */ + if (arg) + { + char *arg_end; + + arg++; + arg_end = strchr (arg, ','); + if (arg_end) + *arg_end = '\0'; + + cur_arg = percent_deescape (arg); + if (arg_end) + { + *arg_end = ','; + arg = arg_end + 1; + } + else + arg = NULL; + } + else + cur_arg = NULL; + } + + *end = saved_end; + } + + if (disable) + { + if (!in_marker) + { + fprintf (src_file, + "# GPGConf disabled this option here at %s\n", + asctimestamp (gnupg_get_time ())); + if (ferror (src_file)) + goto change_file_one_err; + fprintf (src_file, "# %s", line); + if (ferror (src_file)) + goto change_file_one_err; + } + } + else + { + fprintf (src_file, "%s", line); + if (ferror (src_file)) + goto change_file_one_err; + } + } + if (ferror (dest_file)) + goto change_file_one_err; + } + + if (!in_marker) + { + /* There was no marker. This is the first time we edit the + file. We add our own marker at the end of the file and + proceed. Note that we first write a newline, this guards us + against files which lack the newline at the end of the last + line, while it doesn't hurt us in all other cases. */ + fprintf (src_file, "\n%s\n", marker); + if (ferror (src_file)) + goto change_file_one_err; + } + + /* At this point, we have copied everything up to the end marker + into the new file, except for the arguments we are going to add. + Now, dump the new arguments and write the end marker, possibly + followed by the rest of the original file. */ + while (cur_arg) + { + fprintf (src_file, "%s\n", cur_arg); + + /* Find next argument. */ + if (arg) + { + char *end; + + arg++; + end = strchr (arg, ','); + if (end) + *end = '\0'; + + cur_arg = percent_deescape (arg); + if (end) + { + *end = ','; + arg = end + 1; + } + else + arg = NULL; + } + else + cur_arg = NULL; + } + + fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ())); + if (ferror (src_file)) + goto change_file_one_err; + + if (!in_marker) + { + fprintf (src_file, "# GPGConf edited this configuration file.\n"); + if (ferror (src_file)) + goto change_file_one_err; + fprintf (src_file, "# It will disable options before this marked " + "block, but it will\n"); + if (ferror (src_file)) + goto change_file_one_err; + fprintf (src_file, "# never change anything below these lines.\n"); + if (ferror (src_file)) + goto change_file_one_err; + } + if (dest_file) + { + while ((length = getline (&line, &line_len, dest_file)) > 0) + { + fprintf (src_file, "%s", line); + if (ferror (src_file)) + goto change_file_one_err; + } + if (ferror (dest_file)) + goto change_file_one_err; + } + if (line) + free (line); + res = fclose (src_file); + if (res) + { + res = errno; + close (fd); + if (dest_file) + fclose (dest_file); + errno = res; + return -1; + } + close (fd); + if (dest_file) + { + res = fclose (dest_file); + if (res) + return -1; + } + return 0; + + change_file_one_err: + if (line) + free (line); + res = errno; + if (src_file) + { + fclose (src_file); + close (fd); + } + if (dest_file) + fclose (dest_file); + errno = res; return -1; } @@ -1394,7 +1679,6 @@ change_options_program (gc_component_t component, gc_backend_t backend, { int disable = 0; char *start; - char *end; if (!strncmp (marker, line, sizeof (marker) - 1)) { @@ -1409,6 +1693,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, start++; if (*start && *start != '\r' && *start != '\n' && *start != '#') { + char *end; char saved_end; end = start; -- cgit v1.2.3 From 4a038d65afa8cfffda86437b6e02636e8325e582 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 26 Feb 2004 22:45:19 +0000 Subject: 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_list_options): Do not print empty groups. --- tools/ChangeLog | 3 + tools/gpgconf-comp.c | 214 ++++++++++++++++++++++++++++----------------------- 2 files changed, 121 insertions(+), 96 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 1821d8b93..ba5df4765 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,8 @@ 2004-02-26 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (gc_component_list_options): Do not print empty + groups. + * gpgconf-comp.c (option_check_validity): Check if option is active. (change_options_file): Implement. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index bbf0649a9..5dda4f306 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -736,124 +736,146 @@ gc_component_find (const char *name) } -/* List all options of the component COMPONENT. */ -void -gc_component_list_options (int component, FILE *out) -{ - const gc_option_t *option = gc_component[component].options; +/* List the option OPTION. */ +static void +list_one_option (const gc_option_t *option, FILE *out) +{ + const char *desc = NULL; + char *arg_name = NULL; - while (option->name) + if (option->desc) { - const char *desc = NULL; - char *arg_name = NULL; + desc = my_dgettext (option->desc_domain, option->desc); - /* Do not output unknown or internal options. */ - if (!(option->flags & GC_OPT_FLAG_GROUP) - && (!option->active || option->level == GC_LEVEL_INTERNAL)) + if (*desc == '|') { - option++; - continue; + const char *arg_tail = strchr (&desc[1], '|'); + + if (arg_tail) + { + int arg_len = arg_tail - &desc[1]; + arg_name = xmalloc (arg_len + 1); + memcpy (arg_name, &desc[1], arg_len); + arg_name[arg_len] = '\0'; + desc = arg_tail + 1; + } } + } + + + /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR ORDER IS + PART OF THE EXTERNAL INTERFACE. YOU MUST NOT REMOVE ANY + FIELDS. */ - if (option->desc) + /* The name field. */ + fprintf (out, "%s", option->name); + + /* The flags field. */ + fprintf (out, ":%lu", option->flags); + if (opt.verbose) + { + putc (' ', out); + + if (!option->flags) + fprintf (out, "none"); + else { - desc = my_dgettext (option->desc_domain, option->desc); + unsigned long flags = option->flags; + unsigned long flag = 0; + unsigned long first = 1; - if (*desc == '|') + while (flags) { - const char *arg_tail = strchr (&desc[1], '|'); - - if (arg_tail) + if (flags & 1) { - int arg_len = arg_tail - &desc[1]; - arg_name = xmalloc (arg_len + 1); - memcpy (arg_name, &desc[1], arg_len); - arg_name[arg_len] = '\0'; - desc = arg_tail + 1; + if (first) + first = 0; + else + putc (',', out); + fprintf (out, "%s", gc_flag[flag].name); } + flags >>= 1; + flag++; } } + } - /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR - ORDER IS PART OF THE EXTERNAL INTERFACE. YOU MUST NOT REMOVE - ANY FIELDS. */ + /* The level field. */ + fprintf (out, ":%u", option->level); + if (opt.verbose) + fprintf (out, " %s", gc_level[option->level].name); + + /* The description field. */ + fprintf (out, ":%s", desc ? percent_escape (desc) : ""); + + /* The type field. */ + fprintf (out, ":%u", option->arg_type); + if (opt.verbose) + fprintf (out, " %s", gc_arg_type[option->arg_type].name); + + /* The alternate type field. */ + fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback); + if (opt.verbose) + fprintf (out, " %s", + gc_arg_type[gc_arg_type[option->arg_type].fallback].name); + + /* The argument name field. */ + fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : ""); + if (arg_name) + xfree (arg_name); + + /* The default value field. */ + fprintf (out, ":%s", option->default_value ? option->default_value : ""); + + /* The default argument field. */ + fprintf (out, ":%s", option->default_arg ? option->default_arg : ""); + + /* The value field. */ + if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE + && (option->flags & GC_OPT_FLAG_LIST) + && option->value) + /* The special format "1,1,1,1,...,1" is converted to a number + here. */ + fprintf (out, ":%u", (strlen (option->value) + 1) / 2); + else + fprintf (out, ":%s", option->value ? option->value : ""); - /* The name field. */ - fprintf (out, "%s", option->name); + /* ADD NEW FIELDS HERE. */ - /* The flags field. */ - fprintf (out, ":%lu", option->flags); - if (opt.verbose) - { - putc (' ', out); - - if (!option->flags) - fprintf (out, "none"); - else - { - unsigned long flags = option->flags; - unsigned long flag = 0; - unsigned long first = 1; + putc ('\n', out); +} - while (flags) - { - if (flags & 1) - { - if (first) - first = 0; - else - putc (',', out); - fprintf (out, "%s", gc_flag[flag].name); - } - flags >>= 1; - flag++; - } - } + +/* List all options of the component COMPONENT. */ +void +gc_component_list_options (int component, FILE *out) +{ + const gc_option_t *option = gc_component[component].options; + const gc_option_t *group_option = NULL; + + while (option->name) + { + /* Do not output unknown or internal options. */ + if (!(option->flags & GC_OPT_FLAG_GROUP) + && (!option->active || option->level == GC_LEVEL_INTERNAL)) + { + option++; + continue; } - /* The level field. */ - fprintf (out, ":%u", option->level); - if (opt.verbose) - fprintf (out, " %s", gc_level[option->level].name); - - /* The description field. */ - fprintf (out, ":%s", desc ? percent_escape (desc) : ""); - - /* The type field. */ - fprintf (out, ":%u", option->arg_type); - if (opt.verbose) - fprintf (out, " %s", gc_arg_type[option->arg_type].name); - - /* The alternate type field. */ - fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback); - if (opt.verbose) - fprintf (out, " %s", - gc_arg_type[gc_arg_type[option->arg_type].fallback].name); - - /* The argument name field. */ - fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : ""); - if (arg_name) - xfree (arg_name); - - /* The default value field. */ - fprintf (out, ":%s", option->default_value ? option->default_value : ""); - - /* The default argument field. */ - fprintf (out, ":%s", option->default_arg ? option->default_arg : ""); - - /* The value field. */ - if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE - && (option->flags & GC_OPT_FLAG_LIST) - && option->value) - /* The special format "1,1,1,1,...,1" is converted to a number - here. */ - fprintf (out, ":%u", (strlen (option->value) + 1) / 2); + if (option->flags & GC_OPT_FLAG_GROUP) + group_option = option; else - fprintf (out, ":%s", option->value ? option->value : ""); + { + if (group_option) + { + list_one_option (group_option, out); + group_option = NULL; + } - /* ADD NEW FIELDS HERE. */ + list_one_option (option, out); + } - putc ('\n', out); option++; } } -- cgit v1.2.3 From 58a722938b4944f086b1b3bf34473b12570193ee Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 2 Mar 2004 08:02:47 +0000 Subject: (create_duptable, destroy_duptable) (insert_duptable): New. (gpgsm_export): Avoid duplicates. --- sm/ChangeLog | 6 ++ sm/export.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 149 insertions(+), 35 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index f6716b0a4..1cda33b14 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-03-02 Werner Koch <wk@gnupg.org> + + * export.c (create_duptable, destroy_duptable) + (insert_duptable): New. + (gpgsm_export): Avoid duplicates. + 2004-02-26 Werner Koch <wk@gnupg.org> * certchain.c (compare_certs): New. diff --git a/sm/export.c b/sm/export.c index ab175f160..fa56ec9e8 100644 --- a/sm/export.c +++ b/sm/export.c @@ -44,6 +44,25 @@ #endif +/* A table tem to store a fingerprint used in a duplicates table. We + don't need to hash here because a fingerprint is alrady a perfect + hash value. This we use the most significant bits to index the + table and then use a linked list for the overflow. Possible + enhancement for very large number of certictates: Add a second + level table and then resort to a linked list. */ +struct duptable_s +{ + struct duptable_s *next; + + /* Note that we only need to store 19 bytes because the first byte + is implictly given by the table index (we require at least 8 + bits). */ + unsigned char fpr[19]; +}; +typedef struct duptable_s *duptable_t; +#define DUPTABLE_BITS 12 +#define DUPTABLE_SIZE (1 << DUPTABLE_BITS) + static void print_short_info (ksba_cert_t cert, FILE *fp); static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen, @@ -51,12 +70,74 @@ static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen, FILE **retfp); +/* Create a table used to indetify duplicated certificates. */ +static duptable_t * +create_duptable (void) +{ + return xtrycalloc (DUPTABLE_SIZE, sizeof (duptable_t)); +} + +static void +destroy_duptable (duptable_t *table) +{ + int idx; + duptable_t t, t2; + + if (table) + { + for (idx=0; idx < DUPTABLE_SIZE; idx++) + for (t = table[idx]; t; t = t2) + { + t2 = t->next; + xfree (t); + } + xfree (table); + } +} + +/* Insert the 20 byte fingerprint FPR into TABLE. Sets EXITS to true + if the fingerprint already exists in the table. */ +static gpg_error_t +insert_duptable (duptable_t *table, unsigned char *fpr, int *exists) +{ + size_t idx; + duptable_t t; + + *exists = 0; + idx = fpr[0]; +#if DUPTABLE_BITS > 16 +#error cannot handle a table larger than 16 bits +#elif DUPTABLE_BITS > 8 + idx <<= (DUPTABLE_BITS - 8); + idx |= (fpr[1] & ~(~0 << 4)); +#endif + + for (t = table[idx]; t; t = t->next) + if (!memcmp (t->fpr, fpr+1, 19)) + break; + if (t) + { + *exists = 1; + return 0; + } + /* Insert that fingerprint. */ + t = xtrymalloc (sizeof *t); + if (!t) + return gpg_error_from_errno (errno); + memcpy (t->fpr, fpr+1, 19); + t->next = table[idx]; + table[idx] = t; + return 0; +} + + + /* Export all certificates or just those given in NAMES. */ void gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) { - KEYDB_HANDLE hd; + KEYDB_HANDLE hd = NULL; KEYDB_SEARCH_DESC *desc = NULL; int ndesc; Base64Context b64writer = NULL; @@ -66,6 +147,15 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) int rc=0; int count = 0; int i; + duptable_t *dtable; + + + dtable = create_duptable (); + if (!dtable) + { + log_error ("creating duplicates table failed: %s\n", strerror (errno)); + goto leave; + } hd = keydb_new (0); if (!hd) @@ -127,8 +217,8 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) while (!(rc = keydb_search (hd, desc, ndesc))) { - const unsigned char *image; - size_t imagelen; + unsigned char fpr[20]; + int exists; if (!names) desc[0].mode = KEYDB_SEARCH_MODE_NEXT; @@ -140,53 +230,69 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) goto leave; } - image = ksba_cert_get_image (cert, &imagelen); - if (!image) + gpgsm_get_fingerprint (cert, 0, fpr, NULL); + rc = insert_duptable (dtable, fpr, &exists); + if (rc) { - log_error ("ksba_cert_get_image failed\n"); + log_error ("inserting into duplicates table fauiled: %s\n", + gpg_strerror (rc)); goto leave; } - if (ctrl->create_pem) + if (!exists) { - if (count) - putc ('\n', fp); - print_short_info (cert, fp); - putc ('\n', fp); - } - count++; + const unsigned char *image; + size_t imagelen; - if (!b64writer) - { - ctrl->pem_name = "CERTIFICATE"; - rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer); - if (rc) + image = ksba_cert_get_image (cert, &imagelen); + if (!image) { - log_error ("can't create writer: %s\n", gpg_strerror (rc)); + log_error ("ksba_cert_get_image failed\n"); goto leave; } - } - rc = ksba_writer_write (writer, image, imagelen); - if (rc) - { - log_error ("write error: %s\n", gpg_strerror (rc)); - goto leave; - } - if (ctrl->create_pem) - { - /* We want one certificate per PEM block */ - rc = gpgsm_finish_writer (b64writer); - if (rc) + if (ctrl->create_pem) { - log_error ("write failed: %s\n", gpg_strerror (rc)); + if (count) + putc ('\n', fp); + print_short_info (cert, fp); + putc ('\n', fp); + } + count++; + + if (!b64writer) + { + ctrl->pem_name = "CERTIFICATE"; + rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer); + if (rc) + { + log_error ("can't create writer: %s\n", gpg_strerror (rc)); + goto leave; + } + } + + rc = ksba_writer_write (writer, image, imagelen); + if (rc) + { + log_error ("write error: %s\n", gpg_strerror (rc)); goto leave; } - gpgsm_destroy_writer (b64writer); - b64writer = NULL; + + if (ctrl->create_pem) + { + /* We want one certificate per PEM block */ + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gpg_strerror (rc)); + goto leave; + } + gpgsm_destroy_writer (b64writer); + b64writer = NULL; + } } - + ksba_cert_release (cert); cert = NULL; } @@ -207,6 +313,7 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) ksba_cert_release (cert); xfree (desc); keydb_release (hd); + destroy_duptable (dtable); } @@ -228,6 +335,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp) int nread; FILE *datafp = NULL; + hd = keydb_new (0); if (!hd) { -- cgit v1.2.3 From 9008835d8a4b96433cb5d43192e264cdd4948d7b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 3 Mar 2004 08:55:50 +0000 Subject: (gpgsm_export): Make sure that we don't export more than one certificate. --- sm/ChangeLog | 5 +++++ sm/export.c | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 1cda33b14..545f93d1a 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-03-03 Werner Koch <wk@gnupg.org> + + * export.c (gpgsm_export): Make sure that we don't export more + than one certificate. + 2004-03-02 Werner Koch <wk@gnupg.org> * export.c (create_duptable, destroy_duptable) diff --git a/sm/export.c b/sm/export.c index fa56ec9e8..66dd46d25 100644 --- a/sm/export.c +++ b/sm/export.c @@ -44,7 +44,7 @@ #endif -/* A table tem to store a fingerprint used in a duplicates table. We +/* A table to store a fingerprint as used in a duplicates table. We don't need to hash here because a fingerprint is alrady a perfect hash value. This we use the most significant bits to index the table and then use a linked list for the overflow. Possible @@ -105,8 +105,8 @@ insert_duptable (duptable_t *table, unsigned char *fpr, int *exists) *exists = 0; idx = fpr[0]; -#if DUPTABLE_BITS > 16 -#error cannot handle a table larger than 16 bits +#if DUPTABLE_BITS > 16 || DUPTABLE_BITS < 8 +#error cannot handle a table larger than 16 bits or smaller than 8 bits #elif DUPTABLE_BITS > 8 idx <<= (DUPTABLE_BITS - 8); idx |= (fpr[1] & ~(~0 << 4)); @@ -239,6 +239,14 @@ gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp) goto leave; } + if (!exists && count && !ctrl->create_pem) + { + log_info ("exporting more than one certificate " + "is not possible in binary mode\n"); + log_info ("ignoring other certificates\n"); + break; + } + if (!exists) { const unsigned char *image; -- cgit v1.2.3 From 884483282f0782f93cf1f171983f27e72eef252c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 6 Mar 2004 20:11:19 +0000 Subject: Preparing for a release --- ChangeLog | 6 ++ NEWS | 3 +- common/ChangeLog | 5 ++ common/Makefile.am | 3 +- common/asshelp.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/asshelp.h | 36 ++++++++++++ configure.ac | 14 +++-- m4/ChangeLog | 4 ++ m4/libgcrypt.m4 | 47 ++++++++++++--- sm/ChangeLog | 15 +++++ sm/call-agent.c | 123 ++------------------------------------- sm/call-dirmngr.c | 32 +++++++++-- sm/certchain.c | 109 ++++++++++++++++++++++------------- sm/certdump.c | 37 +++++++++++- sm/gpgsm.h | 3 +- 15 files changed, 423 insertions(+), 180 deletions(-) create mode 100644 common/asshelp.c create mode 100644 common/asshelp.h diff --git a/ChangeLog b/ChangeLog index 5fbf045d7..a70971759 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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 diff --git a/NEWS b/NEWS index 905c5852a..934bce740 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ -Noteworthy changes in version 1.9.6 +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) diff --git a/common/ChangeLog b/common/ChangeLog index 6f02303e6..4889db4ec 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/common/Makefile.am b/common/Makefile.am index a5d2a4e5d..4e7fd504c 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -39,6 +39,7 @@ libcommon_a_SOURCES = \ membuf.c membuf.h \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ + asshelp.c asshelp.h \ signal.c \ dynload.h @@ -46,7 +47,7 @@ libcommon_a_SOURCES = \ libcommon_a_LIBADD = @LIBOBJS@ libsimple_pwquery_a_SOURCES = \ - simple-pwquery.c simple-pwquery.h + simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h libsimple_pwquery_a_LIBADD = @LIBOBJS@ diff --git a/common/asshelp.c b/common/asshelp.c new file mode 100644 index 000000000..23feca507 --- /dev/null +++ b/common/asshelp.c @@ -0,0 +1,166 @@ +/* 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; +} + diff --git a/common/asshelp.h b/common/asshelp.h new file mode 100644 index 000000000..993594882 --- /dev/null +++ b/common/asshelp.h @@ -0,0 +1,36 @@ +/* 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*/ diff --git a/configure.ac b/configure.ac index aed97fd8f..a8e84dc39 100644 --- a/configure.ac +++ b/configure.ac @@ -24,18 +24,24 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.6-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.6, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. development_version=yes NEED_GPG_ERROR_VERSION=0.6 -NEED_LIBGCRYPT_VERSION=1.1.92 + +NEED_LIBGCRYPT_API=1 +NEED_LIBGCRYPT_VERSION=1.1.93 + NEED_LIBASSUAN_VERSION=0.6.4 + NEED_KSBA_VERSION=0.9.4 + NEED_OPENSC_VERSION=0.8.0 + PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION @@ -411,7 +417,7 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION", # # Libgcrypt is our generic crypto library # -AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_VERSION", +AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION", have_libgcrypt=yes,have_libgcrypt=no) @@ -1022,7 +1028,7 @@ if test "$have_libgcrypt" = "no"; then *** You need libgcrypt to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/ -*** (at least version $NEED_LIBGCRYPT_VERSION is required.) +*** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API) is required.) ***]]) fi if test "$have_libassuan" = "no"; then diff --git a/m4/ChangeLog b/m4/ChangeLog index d6ac513e5..efcded757 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,7 @@ +2004-03-06 Werner Koch <wk@gnupg.org> + + * libgcrypt.m4: Updated. + 2004-02-18 Werner Koch <wk@gnupg.org> * gpg-error.m4, libgcrypt.m4, libassuan.m4, ksba.m4: New. diff --git a/m4/libgcrypt.m4 b/m4/libgcrypt.m4 index 0e8ab5803..e5f2a43c0 100644 --- a/m4/libgcrypt.m4 +++ b/m4/libgcrypt.m4 @@ -1,5 +1,5 @@ dnl Autoconf macros for libgcrypt -dnl Copyright (C) 2002 Free Software Foundation, Inc. +dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc. dnl dnl This file is free software; as a special exception the author gives dnl unlimited permission to copy and/or distribute it, with or without @@ -12,7 +12,13 @@ dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for liblibgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS +dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. +dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed +dnl with the API version to also check the API compatibility. Example: +dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed +dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using +dnl this features allows to prevent build against newer versions of libgcrypt +dnl with a changed API. dnl AC_DEFUN(AM_PATH_LIBGCRYPT, [ AC_ARG_WITH(libgcrypt-prefix, @@ -26,7 +32,15 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, fi AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) - min_libgcrypt_version=ifelse([$1], ,0.4.4,$1) + tmp=ifelse([$1], ,1:1.2.0,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) ok=no if test "$LIBGCRYPT_CONFIG" != "no" ; then @@ -36,7 +50,7 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` req_micro=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --version` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` major=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` minor=`echo $libgcrypt_config_version | \ @@ -60,14 +74,33 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, fi fi if test $ok = yes; then - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs` AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + AC_MSG_CHECKING([LIBGCRYPT API version]) + if test "$req_libgcrypt_api" -eq "$tmp" ; then + AC_MSG_RESULT(okay) + else + ok=no + AC_MSG_RESULT([does not match (want=$req_libgcrypt_api got=$tmp)]) + fi + fi + fi + fi + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` ifelse([$2], , :, [$2]) else LIBGCRYPT_CFLAGS="" LIBGCRYPT_LIBS="" - AC_MSG_RESULT(no) ifelse([$3], , :, [$3]) fi AC_SUBST(LIBGCRYPT_CFLAGS) diff --git a/sm/ChangeLog b/sm/ChangeLog index 545f93d1a..eb1c608dc 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,20 @@ +2004-03-04 Werner Koch <wk@gnupg.org> + + * call-dirmngr.c (gpgsm_dirmngr_isvalid): New arg ISSUER_CERT. + + * certchain.c (is_cert_still_valid): New. Code moved from ... + (gpgsm_validate_chain): ... here because we now need to check at + two places and at a later stage, so that we can pass the issuer + cert down to the dirmngr. + 2004-03-03 Werner Koch <wk@gnupg.org> + * call-agent.c (start_agent): Replaced pinentry setup code by a + call to a new common function. + + * certdump.c (gpgsm_format_keydesc): Make sure the string is + returned as utf-8. + * export.c (gpgsm_export): Make sure that we don't export more than one certificate. diff --git a/sm/call-agent.c b/sm/call-agent.c index 053959b2c..15ae5eacc 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -34,6 +34,7 @@ #include <gcrypt.h> #include <assuan.h> #include "i18n.h" +#include "asshelp.h" #include "keydb.h" /* fixme: Move this to import.c */ #include "../common/membuf.h" @@ -68,12 +69,7 @@ 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; + assuan_context_t ctx; if (agent_ctx) return 0; /* fixme: We need a context for each thread or serialize @@ -170,118 +166,9 @@ start_agent (void) 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 OUT_OF_CORE (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 OUT_OF_CORE (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 OUT_OF_CORE (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 OUT_OF_CORE (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 = OUT_OF_CORE (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 OUT_OF_CORE (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 = OUT_OF_CORE (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 send_pinentry_environment (agent_ctx, + opt.display, opt.ttyname, opt.ttytype, + opt.lc_ctype, opt.lc_messages); } diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index ba96df499..4f07fec24 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -49,6 +49,7 @@ static int force_pipe_server = 0; struct inq_certificate_parm_s { ASSUAN_CONTEXT ctx; ksba_cert_t cert; + ksba_cert_t issuer_cert; }; struct lookup_parm_s { @@ -239,27 +240,45 @@ inq_certificate (void *opaque, const char *line) AssuanError rc; const unsigned char *der; size_t derlen; + int issuer_mode = 0; - if (!(!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))) + if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8])) + { + line += 8; + } + else if (!strncmp (line, "SENDISSUERCERT", 14) + && (line[14] == ' ' || !line[14])) + { + line += 14; + issuer_mode = 1; + } + else { log_error ("unsupported inquiry `%s'\n", line); return ASSUAN_Inquire_Unknown; } - line += 8; if (!*line) - { /* send the current certificate */ - der = ksba_cert_get_image (parm->cert, &derlen); + { /* Send the current certificate. */ + der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert, + &derlen); if (!der) rc = ASSUAN_Inquire_Error; else rc = assuan_send_data (parm->ctx, der, derlen); } + else if (issuer_mode) + { + log_error ("sending specific issuer certificate back " + "is not yet implemented\n"); + rc = ASSUAN_Inquire_Error; + } else - { /* send the given certificate */ + { /* Send the given certificate. */ int err; ksba_cert_t cert; + err = gpgsm_find_cert (line, &cert); if (err) { @@ -293,7 +312,7 @@ inq_certificate (void *opaque, const char *line) request first. */ int -gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp) +gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) { int rc; char *certid; @@ -328,6 +347,7 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp) parm.ctx = dirmngr_ctx; parm.cert = cert; + parm.issuer_cert = issuer_cert; /* FIXME: If --disable-crl-checks has been set, we should pass an option to dirmngr, so that no fallback CRL check is done after an diff --git a/sm/certchain.c b/sm/certchain.c index bb3fd0339..2904680ea 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -347,7 +347,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) if (opt.verbose) log_info (_("looking up issuer at external location\n")); - /* dirmngr is confused about unknown attributes so has a quick + /* dirmngr is confused about unknown attributes so as a quick and ugly hack we locate the CN and use this and the following. Fixme: we should have far better parsing in the dirmngr. */ @@ -469,6 +469,55 @@ gpgsm_is_root_cert (ksba_cert_t cert) return yes; } + +/* This is a helper for gpgsm_validate_chain. */ +static gpg_error_t +is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp, + ksba_cert_t subject_cert, ksba_cert_t issuer_cert, + int *any_revoked, int *any_no_crl, int *any_crl_too_old) +{ + if (!opt.no_crl_check || ctrl->use_ocsp) + { + gpg_error_t err; + + err = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp); + if (err) + { + /* Fixme: We should change the wording because we may + have used OCSP. */ + switch (gpg_err_code (err)) + { + case GPG_ERR_CERT_REVOKED: + do_list (1, lm, fp, _("certificate has been revoked")); + *any_revoked = 1; + /* Store that in the keybox so that key listings are + able to return the revoked flag. We don't care + about error, though. */ + keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0, + VALIDITY_REVOKED); + break; + case GPG_ERR_NO_CRL_KNOWN: + do_list (1, lm, fp, _("no CRL found for certificate")); + *any_no_crl = 1; + break; + case GPG_ERR_CRL_TOO_OLD: + do_list (1, lm, fp, _("the available CRL is too old")); + if (!lm) + log_info (_("please make sure that the " + "\"dirmngr\" is properly installed\n")); + *any_crl_too_old = 1; + break; + default: + do_list (1, lm, fp, _("checking the CRL failed: %s"), + gpg_strerror (rc)); + return err; + } + } + } + return 0; +} + + /* Validate a chain and optionally return the nearest expiration time in R_EXPTIME. With LISTMODE set to 1 a special listmode is @@ -597,46 +646,10 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, goto leave; } - if (!opt.no_crl_check || ctrl->use_ocsp) - { - rc = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp); - if (rc) - { - /* Fixme: We should change the wording because we may - have used OCSP. */ - switch (gpg_err_code (rc)) - { - case GPG_ERR_CERT_REVOKED: - do_list (1, lm, fp, _("certificate has been revoked")); - any_revoked = 1; - /* Store that in the keybox so that key listings are - able to return the revoked flag. We don't care - about error, though. */ - keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0, - VALIDITY_REVOKED); - break; - case GPG_ERR_NO_CRL_KNOWN: - do_list (1, lm, fp, _("no CRL found for certificate")); - any_no_crl = 1; - break; - case GPG_ERR_CRL_TOO_OLD: - do_list (1, lm, fp, _("the available CRL is too old")); - if (!lm) - log_info (_("please make sure that the " - "\"dirmngr\" is properly installed\n")); - any_crl_too_old = 1; - break; - default: - do_list (1, lm, fp, _("checking the CRL failed: %s"), - gpg_strerror (rc)); - goto leave; - } - rc = 0; - } - } + /* Is this a self-signed certificate? */ if (subject && !strcmp (issuer, subject)) - { + { /* Yes. */ if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) { do_list (1, lm, fp, @@ -684,7 +697,15 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, gpg_strerror (rc)); } - break; /* okay, a self-signed certicate is an end-point */ + /* Check for revocations etc. */ + rc = is_cert_still_valid (ctrl, lm, fp, + subject_cert, subject_cert, + &any_revoked, &any_no_crl, + &any_crl_too_old); + if (rc) + goto leave; + + break; /* Okay: a self-signed certicate is an end-point. */ } depth++; @@ -801,6 +822,14 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, } } + /* Check for revocations etc. */ + rc = is_cert_still_valid (ctrl, lm, fp, + subject_cert, issuer_cert, + &any_revoked, &any_no_crl, &any_crl_too_old); + if (rc) + goto leave; + + if (opt.verbose && !listmode) log_info ("certificate is good\n"); diff --git a/sm/certdump.c b/sm/certdump.c index f2c21f7fa..30cd0bd53 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -26,6 +26,12 @@ #include <unistd.h> #include <time.h> #include <assert.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif #include "gpgsm.h" #include <gcrypt.h> @@ -601,12 +607,14 @@ gpgsm_format_name (const char *name) char * gpgsm_format_keydesc (ksba_cert_t cert) { + int rc; char *name, *subject, *buffer, *p; const char *s; ksba_isotime_t t; char created[20]; char *sn; ksba_sexp_t sexp; + char *orig_codeset = NULL; name = ksba_cert_get_subject (cert, 0); subject = name? gpgsm_format_name (name) : NULL; @@ -622,7 +630,24 @@ gpgsm_format_keydesc (ksba_cert_t cert) else *created = 0; - if ( asprintf (&name, + +#ifdef ENABLE_NLS + /* The Assuan agent protol requires us to transmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset) + { /* We only switch when we are able to restore the codeset later. */ + orig_codeset = xstrdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE, "utf-8")) + orig_codeset = NULL; + } +#endif + + + rc = asprintf (&name, _("Please enter the passphrase to unlock the" " secret key for:\n" "\"%s\"\n" @@ -630,7 +655,15 @@ gpgsm_format_keydesc (ksba_cert_t cert) subject? subject:"?", sn? sn: "?", gpgsm_get_short_fingerprint (cert), - created) < 0) + created); + +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif + xfree (orig_codeset); + + if (rc < 0) { int save_errno = errno; xfree (subject); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index c0434d79c..62bc05354 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -288,7 +288,8 @@ int gpgsm_agent_learn (void); int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc); /*-- call-dirmngr.c --*/ -int gpgsm_dirmngr_isvalid (ksba_cert_t cert, int use_ocsp); +int gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, + int use_ocsp); int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names, void (*cb)(void*, ksba_cert_t), void *cb_value); int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command, -- cgit v1.2.3 From 15f1c42c85d7a407912a7b4d88c103246bdfa25b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 6 Mar 2004 20:15:17 +0000 Subject: still preparing for a release --- sm/certchain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sm/certchain.c b/sm/certchain.c index 2904680ea..5056139df 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -480,7 +480,7 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp, { gpg_error_t err; - err = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp); + err = gpgsm_dirmngr_isvalid (subject_cert, issuer_cert, ctrl->use_ocsp); if (err) { /* Fixme: We should change the wording because we may @@ -509,7 +509,7 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp, break; default: do_list (1, lm, fp, _("checking the CRL failed: %s"), - gpg_strerror (rc)); + gpg_strerror (err)); return err; } } -- cgit v1.2.3 From f3553d844d25db7829d627aa8b05f5b0bc087af5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 6 Mar 2004 20:42:14 +0000 Subject: post release development preparations --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 934bce740..c6bcf8d9e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.7 +------------------------------------------------ + + Noteworthy changes in version 1.9.6 (2004-03-06) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index a8e84dc39..563e082d2 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.6, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.7-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 5c457626a8151dfa1a642c7e3abdd7e0b6a86aa5 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 8 Mar 2004 14:28:54 +0000 Subject: Fix buglet. --- tools/README.gpgconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/README.gpgconf b/tools/README.gpgconf index 03fd9daa7..c0d3c7c61 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -330,7 +330,7 @@ Example: To set the option force, which is of basic type 0 (none). $ echo 'force:0:1' | gpgconf --change-options dirmngr To delete the option force: -$ echo 'force:16:0' | gpgconf --change-options dirmngr +$ echo 'force:16:' | gpgconf --change-options dirmngr Option --runtime -- cgit v1.2.3 From 8cf4e69141bb11d8fb956d31752293e7bfb5cbcf Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 8 Mar 2004 17:59:24 +0000 Subject: 2004-03-08 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (retrieve_options_from_file): Quote each string in the list, not only the first. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index ba5df4765..9acd30f48 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-03-08 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (retrieve_options_from_file): Quote each string + in the list, not only the first. + 2004-02-26 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_list_options): Do not print empty diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 5dda4f306..e483675f8 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1172,11 +1172,11 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) while (*(end - 1) == ' ' || *(end - 1) == '\t') end--; *end = '\0'; - /* FIXME: Oh, no! This is so lame! Use realloc and really - append. */ + /* FIXME: Oh, no! This is so lame! Should use realloc and + really append. */ if (list) { - new_list = xasprintf ("%s,%s", list, percent_escape (start)); + new_list = xasprintf ("%s,\"%s", list, percent_escape (start)); xfree (list); list = new_list; } -- cgit v1.2.3 From 7ad15ec24a29d76dadc33da8930a3fc7f566903a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 9 Mar 2004 14:34:12 +0000 Subject: Removed special code for RISC OS; we don't want to clutter our code with system dependent stuff. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 9acd30f48..ebdc94eaf 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-03-09 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c [_riscos_]: Removed special code for RISC OS; we + don't want to clutter our code with system dependent stuff. + 2004-03-08 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (retrieve_options_from_file): Quote each string diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e483675f8..791839a4d 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -42,6 +42,13 @@ /* TODO: Portability - Add gnulib replacements for getline, etc. + +XXX Marcus: Please use the read_line code from dirmngr/src/http.c - it +has been in use for may years and provides the ability to limit the +length of the line and thus thwart DoS (not a issue here but at many +other places). + + Backend: File backend must be able to write out changes !!! Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. @@ -52,8 +59,7 @@ */ -#if defined (__riscos__) \ - || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) +#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )) void gc_error (int status, int errnum, const char *fmt, ...) \ __attribute__ ((format (printf, 3, 4))); #endif -- cgit v1.2.3 From 8927b55c28eeab38498165bdea162621d7681523 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 12 Mar 2004 14:29:40 +0000 Subject: 2004-03-12 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_change_options): Set the filenames of the option's backend, not of the component. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 15 ++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index ebdc94eaf..077115a58 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-03-12 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (gc_component_change_options): Set the filenames + of the option's backend, not of the component. + 2004-03-09 Werner Koch <wk@gnupg.org> * gpgconf-comp.c [_riscos_]: Removed special code for RISC OS; we diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 791839a4d..d792d1d75 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -2029,7 +2029,8 @@ gc_component_change_options (int component, FILE *in) { /* Go on if we have already seen this backend, or if there is nothing to do. */ - if (src_pathname[option->backend] || !(option->new_flags || option->new_value)) + if (src_pathname[option->backend] + || !(option->new_flags || option->new_value)) { option++; continue; @@ -2037,14 +2038,14 @@ gc_component_change_options (int component, FILE *in) if (gc_backend[option->backend].program) err = change_options_program (component, option->backend, - &src_pathname[component], - &dest_pathname[component], - &orig_pathname[component]); + &src_pathname[option->backend], + &dest_pathname[option->backend], + &orig_pathname[option->backend]); else err = change_options_file (component, option->backend, - &src_pathname[component], - &dest_pathname[component], - &orig_pathname[component]); + &src_pathname[option->backend], + &dest_pathname[option->backend], + &orig_pathname[option->backend]); if (err) break; -- cgit v1.2.3 From 2bb4c53e7a99254e1a95810efbb2df0bf8f6bed7 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 12 Mar 2004 14:42:31 +0000 Subject: 2004-03-12 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_change_options): Set the filenames of the option's backend, not of the component. Also use GC_BACKEND_NR, not GC_COMPONENT_NR. --- tools/ChangeLog | 1 + tools/gpgconf-comp.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 077115a58..1489eb051 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -2,6 +2,7 @@ * gpgconf-comp.c (gc_component_change_options): Set the filenames of the option's backend, not of the component. + Also use GC_BACKEND_NR, not GC_COMPONENT_NR. 2004-03-09 Werner Koch <wk@gnupg.org> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index d792d1d75..a55883e55 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -2057,7 +2057,7 @@ gc_component_change_options (int component, FILE *in) { int i; - for (i = 0; i < GC_COMPONENT_NR; i++) + for (i = 0; i < GC_BACKEND_NR; i++) { if (src_pathname[i]) { @@ -2089,7 +2089,7 @@ gc_component_change_options (int component, FILE *in) int saved_errno = errno; /* An error occured. */ - for (i = 0; i < GC_COMPONENT_NR; i++) + for (i = 0; i < GC_BACKEND_NR; i++) { if (src_pathname[i]) { -- cgit v1.2.3 From 501267f88bae2119ba0cded96213868870cd9145 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 15 Mar 2004 08:39:48 +0000 Subject: (list_cert_colon): Hack to set the expired flag. --- sm/ChangeLog | 10 ++++++++++ sm/gpgsm.c | 4 ++-- sm/keydb.c | 4 ++-- sm/keylist.c | 25 +++++++++++++++++++------ 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index eb1c608dc..18431c11c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2004-03-15 Werner Koch <wk@gnupg.org> + + * keylist.c (list_cert_colon): Hack to set the expired flag. + +2004-03-09 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Correctly intitialze USE_OCSP flag. + + * keydb.c (keydb_delete): s/GPG_ERR_CONFLICT/GPG_ERR_NOT_LOCKED/ + 2004-03-04 Werner Koch <wk@gnupg.org> * call-dirmngr.c (gpgsm_dirmngr_isvalid): New arg ISSUER_CERT. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 6f3e62a33..ca7fbfcca 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -932,10 +932,10 @@ main ( int argc, char **argv) break; case oDisableOCSP: - opt.enable_ocsp = 0; + ctrl.use_ocsp = opt.enable_ocsp = 0; break; case oEnableOCSP: - opt.enable_ocsp = 1; + ctrl.use_ocsp = opt.enable_ocsp = 1; break; case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break; diff --git a/sm/keydb.c b/sm/keydb.c index ab30ba15d..858baf242 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -630,7 +630,7 @@ keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value) /* Set a flag of the last found object. WHICH is the flag to be set; it should be one of the KEYBOX_FLAG_ values. If the operation is successful, the flag value will be stored in the keybox. Note, - that some flag values can't be updated and thus may retrun an + that some flag values can't be updated and thus may return an error, some other flag values may be masked out before an update. Returns 0 on success or an error code. */ gpg_error_t @@ -760,7 +760,7 @@ keydb_delete (KEYDB_HANDLE hd) return 0; if (!hd->locked) - return gpg_error (GPG_ERR_CONFLICT); /* ...NOT_LOCKED would be better. */ + return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) { diff --git a/sm/keylist.c b/sm/keylist.c index 6d48068b0..80cc675db 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -196,6 +196,19 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, *truststring = 'e'; else if (valerr) *truststring = 'i'; + else + { + /* Lets also check whether the certificate under question + expired. This is merely a hack until we found a proper way + to store the expiration flag in the keybox. */ + ksba_isotime_t current_time, not_after; + + gnupg_get_isotime (current_time); + if (!opt.ignore_expiration + && !ksba_cert_get_validity (cert, 1, not_after) + && *not_after && strcmp (current_time, not_after) > 0 ) + *truststring = 'e'; + } if (*truststring) fputs (truststring, fp); @@ -206,14 +219,14 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, /* pubkey_algo_of_cert (cert)*/1, fpr+24); - /* we assume --fixed-list-mode for gpgsm */ + /* We assume --fixed-list-mode for gpgsm */ ksba_cert_get_validity (cert, 0, t); print_time (t, fp); putc (':', fp); ksba_cert_get_validity (cert, 1, t); print_time ( t, fp); putc (':', fp); - /* field 8, serial number: */ + /* Field 8, serial number: */ if ((sexp = ksba_cert_get_serial (cert))) { int len; @@ -231,7 +244,7 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, xfree (sexp); } putc (':', fp); - /* field 9, ownertrust - not used here */ + /* Field 9, ownertrust - not used here */ putc (':', fp); /* field 10, old user ID - we use it here for the issuer DN */ if ((p = ksba_cert_get_issuer (cert,0))) @@ -240,16 +253,16 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, xfree (p); } putc (':', fp); - /* field 11, signature class - not used */ + /* Field 11, signature class - not used */ putc (':', fp); - /* field 12, capabilities: */ + /* Field 12, capabilities: */ print_capabilities (cert, fp); putc (':', fp); putc ('\n', fp); /* FPR record */ fprintf (fp, "fpr:::::::::%s:::", fpr); - /* print chaining ID (field 13)*/ + /* Print chaining ID (field 13)*/ { ksba_cert_t next; int rc; -- cgit v1.2.3 From b541bbde6dd97ed71368443389566b16ef1f7f18 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 10:47:08 +0000 Subject: * dynload.h [__MINGW32__]: Define RTLD_LAZY. --- common/ChangeLog | 8 ++++++++ common/dynload.h | 2 ++ common/maperror.c | 2 -- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 4889db4ec..6d408ba4f 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,11 @@ +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. diff --git a/common/dynload.h b/common/dynload.h index d2df5f017..3c4652091 100644 --- a/common/dynload.h +++ b/common/dynload.h @@ -25,6 +25,8 @@ #else #include <windows.h> +#define RTLD_LAZY 0 + static __inline__ void * dlopen (const char * name, int flag) { diff --git a/common/maperror.c b/common/maperror.c index b04ec0bb3..2f6f1b159 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -72,9 +72,7 @@ map_assuan_err (int err) case ASSUAN_Not_Confirmed: ec = GPG_ERR_NOT_CONFIRMED; break; case ASSUAN_Invalid_Id: ec = GPG_ERR_INV_ID; break; -#if 0 /* FIXME: Enable this after releasing libgpg error 0.7 */ case ASSUAN_Locale_Problem: ec = GPG_ERR_LOCALE_PROBLEM; break; -#endif default: ec = err < 100? GPG_ERR_ASSUAN_SERVER_FAULT : GPG_ERR_ASSUAN; -- cgit v1.2.3 From a6768b8eca84fb52393393a2c03ca46d5bc28283 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 10:48:13 +0000 Subject: (gc_options_gpg_agent): Implemented. --- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 1489eb051..c8eca3137 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-03-16 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c (gc_options_gpg_agent): Implemented. + 2004-03-12 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_change_options): Set the filenames diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index a55883e55..4785eefb6 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -409,6 +409,57 @@ typedef struct gc_option gc_option_t; /* The options of the GC_COMPONENT_GPG_AGENT component. */ static gc_option_t gc_options_gpg_agent[] = { + /* The configuration file to which we write the changes. */ + { "gpgconf-gpg-agent.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, + + { "Monitor", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the diagnostic output" }, + { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + "gnupg", "verbose", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "be somewhat more quiet", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + + { "Configuration", + GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, + NULL, "Options controlling the configuration" }, + { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "|FILE|read options from FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, + + { "Debug", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "gnupg", "Options useful for debugging" }, + { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + "gnupg", "|LEVEL|set the debugging level to LEVEL", + GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT }, + { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "|FILE|write logs to FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, + { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, + + { "Security", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the security" }, + { "default-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, + "gnupg", "|N|expire cached PINs after N seconds", + GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, + { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, + "gnupg", "do not use the PIN cache when signing", + GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, + { "no-grab", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "do not grab keybourd and mouse", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + + GC_OPTION_NULL }; @@ -525,6 +576,14 @@ static gc_option_t gc_options_dirmngr[] = "dirmngr", "|N|do not return more than N items in one query", GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, + { "OCSP", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + NULL, "Configuration for OCSP" }, + { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "|URL|use OCSP responder URL", + GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, + + GC_OPTION_NULL }; -- cgit v1.2.3 From 3e8221e95522286fbc48ce0945f0b5ab533730d9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 10:48:42 +0000 Subject: (parse_rereadable_options): Use the new DEFAULT_CACHE_TTL macro. (main): Updated --gpgconf-list output. --- agent/ChangeLog | 6 ++++++ agent/gpg-agent.c | 61 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index f05685b0d..7516cddb8 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2004-03-16 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (parse_rereadable_options): Use the new + DEFAULT_CACHE_TTL macro. + (main): Updated --gpgconf-list output. + 2004-02-21 Werner Koch <wk@gnupg.org> * command.c (cmd_passwd): Take acount of a key description. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 83a1041f8..5b9e22465 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -99,7 +99,7 @@ static ARGPARSE_OPTS opts[] = { { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, { oSh, "sh", 0, N_("sh-style command output") }, { oCsh, "csh", 0, N_("csh-style command output") }, - { oOptions, "options" , 2, N_("read options from file")}, + { oOptions, "options" , 2, N_("|FILE|read options from FILE")}, { oDebug, "debug" ,4|16, "@"}, { oDebugAll, "debug-all" ,0, "@"}, { oDebugLevel, "debug-level" ,2, "@"}, @@ -128,6 +128,8 @@ static ARGPARSE_OPTS opts[] = { }; +#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ + static volatile int caught_fatal_sig = 0; /* flag to indicate that a shutdown was requested */ @@ -323,7 +325,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs) opt.no_grab = 0; opt.pinentry_program = NULL; opt.scdaemon_program = NULL; - opt.def_cache_ttl = 10*60; /* default to 10 minutes */ + opt.def_cache_ttl = DEFAULT_CACHE_TTL; opt.ignore_cache_for_signing = 0; return 1; } @@ -587,15 +589,40 @@ main (int argc, char **argv ) if (gpgconf_list) { /* List options and default values in the GPG Conf format. */ - printf ("gpgconf-gpg-agent.conf:\"%s\n", config_filename); + /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ + /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING + FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ +#define GC_OPT_FLAG_NONE 0UL + /* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + /* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + /* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) + /* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + + printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n", + GC_OPT_FLAG_DEFAULT, config_filename); - printf ("verbose:\n" - "quiet:\n" - "debug-level:none\n" - "log-file:\n" - "force:\n" - "faked-system-time:\n" - "no-greeting:\n"); + printf ("verbose:%lu:\n" + "quiet:%lu:\n" + "debug-level:%lu:\"none\":\n" + "log-file:%lu:\n", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, + GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, + GC_OPT_FLAG_NONE ); + printf ("default-cache-ttl:%lu:%d:\n", + GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, DEFAULT_CACHE_TTL ); + printf ("no-grab:%lu:\n", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); + printf ("ignore-cache-for-signing:%lu:\n", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); agent_exit (0); } @@ -605,13 +632,13 @@ main (int argc, char **argv ) " to run the program in the background\n")); #ifdef ENABLE_NLS - /* gpg-agent usdually does not ooutput any messages becuase it runs - in the background. For log files it is acceptable to have - messages always encoded in utf-8. We switch here to utf-8, so - that commands like --help still give native messages. It is far - easier to swicthnonly once instead of for every message and it - actually helps when more then one thread is active (avoids - required an extra copy step). */ + /* gpg-agent usually does not output any messages because it runs in + the background. For log files it is acceptable to have messages + always encoded in utf-8. We switch here to utf-8, so that + commands like --help still give native messages. It is far + easier to switch only once instead of for every message and it + actually helps when more then one thread is active (avoids an + extra copy step). */ bind_textdomain_codeset (PACKAGE, "UTF-8"); #endif -- cgit v1.2.3 From 1a389c1e1eaf8483d7bea0967a27b21d258cd222 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 10:49:00 +0000 Subject: * configure.ac (NEED_GPG_ERROR_VERSION): Set to 0.7. --- ChangeLog | 4 ++++ TODO | 2 -- configure.ac | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a70971759..0e9c72c68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/TODO b/TODO index f3a66f08c..1d12b7446 100644 --- a/TODO +++ b/TODO @@ -45,8 +45,6 @@ might want to have an agent context for each service request ** Check that all error code mapping is done. ** Remove the inter-module dependencies between gpgsm and keybox ** Add an source_of_key field -** We need an error code GPG_ERR_NOT_LOCKED - It is already libgpg-error. * agent/gpg-agent.c ** A SIGHUP should also restart the scdaemon diff --git a/configure.ac b/configure.ac index 563e082d2..6d6918a9c 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ AC_INIT(gnupg, 1.9.7-cvs, gnupg-devel@gnupg.org) # feel that the default check for a development version is not # sufficient. development_version=yes -NEED_GPG_ERROR_VERSION=0.6 +NEED_GPG_ERROR_VERSION=0.7 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.1.93 -- cgit v1.2.3 From f8d44bc637a4c897fd4448de804ee08ae065e194 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 10:49:37 +0000 Subject: *** empty log message *** --- scd/ChangeLog | 14 +++++ scd/apdu.c | 4 +- scd/app-nks.c | 4 +- scd/app-openpgp.c | 2 +- scd/app.c | 2 +- scd/card-dinsig.c | 4 +- scd/card-p15.c | 12 ++--- scd/card.c | 8 +-- scd/ccid-driver.c | 14 +++-- scd/command.c | 6 +-- scd/iso7816.c | 24 +++++---- scd/iso7816.h | 1 + scd/sc-investigate.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++--- scd/scdaemon.h | 8 --- 14 files changed, 200 insertions(+), 46 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 66ceebd22..a9296cbbb 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,17 @@ +2004-03-11 Werner Koch <wk@gnupg.org> + + * scdaemon.h (out_of_core): Removed. Replaced callers by standard + gpg_error function. + + * apdu.c, iso7816.c, ccid-driver.c [GNUPG_SCD_MAIN_HEADER]: Allow + to include a header defined by the compiler. This helps us to + reuse the source in other software. + +2004-03-10 Werner Koch <wk@gnupg.org> + + * iso7816.c (iso7816_read_record): New arg SHORT_EF. Changed all + callers. + 2004-02-18 Werner Koch <wk@gnupg.org> * sc-investigate.c (main): Setup the used character set. diff --git a/scd/apdu.c b/scd/apdu.c index e5295f566..7843fd566 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -28,7 +28,9 @@ # include <opensc/opensc.h> #endif -#if GNUPG_MAJOR_VERSION == 1 +#if defined(GNUPG_SCD_MAIN_HEADER) +#include GNUPG_SCD_MAIN_HEADER +#elif GNUPG_MAJOR_VERSION == 1 /* This is used with GnuPG version < 1.9. The code has been source copied from the current GnuPG >= 1.9 and is maintained over there. */ diff --git a/scd/app-nks.c b/scd/app-nks.c index 2ceb537a2..a4b6e3a15 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -130,10 +130,10 @@ keygripstr_from_pk_file (int slot, int fid, char *r_gripstr) err = iso7816_select_file (slot, fid, 0, NULL, NULL); if (err) return err; - err = iso7816_read_record (slot, 1, 1, &buffer[0], &buflen[0]); + err = iso7816_read_record (slot, 1, 1, 0, &buffer[0], &buflen[0]); if (err) return err; - err = iso7816_read_record (slot, 2, 1, &buffer[1], &buflen[1]); + err = iso7816_read_record (slot, 2, 1, 0, &buffer[1], &buflen[1]); if (err) { xfree (buffer[0]); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 021d6a52c..7782b8e1c 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -245,7 +245,7 @@ store_fpr (int slot, int keynumber, u32 timestamp, n = 6 + 2 + mlen + 2 + elen; p = buffer = xtrymalloc (3 + n); if (!buffer) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); *p++ = 0x99; /* ctb */ *p++ = n >> 8; /* 2 byte length header */ diff --git a/scd/app.c b/scd/app.c index 6ac18272b..d395fe559 100644 --- a/scd/app.c +++ b/scd/app.c @@ -47,7 +47,7 @@ select_application (ctrl_t ctrl, int slot, const char *name) app = xtrycalloc (1, sizeof *app); if (!app) { - rc = out_of_core (); + rc = gpg_error (gpg_err_code_from_errno (errno)); log_info ("error allocating context: %s\n", gpg_strerror (rc)); return NULL; } diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c index bb070d5f0..df09bfb57 100644 --- a/scd/card-dinsig.c +++ b/scd/card-dinsig.c @@ -141,7 +141,7 @@ dinsig_enum_keypairs (CARD card, int idx, { *keyid = xtrymalloc (17); if (!*keyid) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); if (!idx) strcpy (*keyid, "DINSIG-DF01.C000"); else @@ -193,7 +193,7 @@ dinsig_read_cert (CARD card, const char *certidstr, buf = xtrymalloc (file->size); if (!buf) { - gpg_error_t tmperr = out_of_core (); + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); sc_file_free (file); return tmperr; } diff --git a/scd/card-p15.c b/scd/card-p15.c index 239e75045..ae3ef148f 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -53,7 +53,7 @@ init_private_data (CARD card) priv = xtrycalloc (1, sizeof *priv); if (!priv) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); /* OpenSC (0.7.0) is a bit strange in that the get_objects functions tries to be a bit too clever and implicitly does an enumeration @@ -179,7 +179,7 @@ p15_enum_keypairs (CARD card, int idx, *keyid = p = xtrymalloc (9+pinfo->id.len*2+1); if (!*keyid) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); p = stpcpy (p, "P15-5015."); for (i=0; i < pinfo->id.len; i++, p += 2) sprintf (p, "%02X", pinfo->id.value[i]); @@ -217,7 +217,7 @@ p15_enum_certs (CARD card, int idx, char **certid, int *type) *certid = p = xtrymalloc (9+cinfo->id.len*2+1); if (!*certid) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); p = stpcpy (p, "P15-5015."); for (i=0; i < cinfo->id.len; i++, p += 2) sprintf (p, "%02X", cinfo->id.value[i]); @@ -304,7 +304,7 @@ p15_read_cert (CARD card, const char *certidstr, *cert = xtrymalloc (certder->data_len); if (!*cert) { - gpg_error_t tmperr = out_of_core (); + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); sc_pkcs15_free_certificate (certder); return tmperr; } @@ -400,7 +400,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo, outbuflen = 1024; outbuf = xtrymalloc (outbuflen); if (!outbuf) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); rc = sc_pkcs15_compute_signature (card->p15card, keyobj, cryptflags, @@ -462,7 +462,7 @@ p15_decipher (CARD card, const char *keyidstr, outbuflen = indatalen < 256? 256 : indatalen; outbuf = xtrymalloc (outbuflen); if (!outbuf) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); rc = sc_pkcs15_decipher (card->p15card, keyobj, 0, diff --git a/scd/card.c b/scd/card.c index 53c89f3a4..8366dcb1c 100644 --- a/scd/card.c +++ b/scd/card.c @@ -108,7 +108,7 @@ card_open (CARD *rcard) card = xtrycalloc (1, sizeof *card); if (!card) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); card->reader = 0; rc = sc_establish_context (&card->ctx, "scdaemon"); @@ -275,7 +275,7 @@ find_iccsn (const unsigned char *buffer, size_t length, char **serial) *serial = p = xtrymalloc (2*n+1); if (!*serial) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); for (; n; n--, p += 2, s++) sprintf (p, "%02X", *s); *p = 0; @@ -389,7 +389,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp) *serial = NULL; p = xtrymalloc (strlen (efser) + 7); if (!p) - rc = out_of_core (); + rc = gpg_error (gpg_err_code_from_errno (errno)); else { strcpy (p, "FF0100"); @@ -405,7 +405,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp) { xfree (*serial); *serial = NULL; - rc = out_of_core (); + rc = gpg_error (gpg_err_code_from_errno (errno)); } else { diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index ca5620176..b398e3ce3 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -87,16 +87,24 @@ #define DRVNAME "ccid-driver: " -#ifdef GNUPG_MAJOR_VERSION /* This source is used within GnuPG. */ +/* Depending on how this source is used we either define our error + output to go to stderr or to the jnlib based logging functions. We + use the latter when GNUPG_MAJOR_VERSION is defines or when both, + GNUPG_SCD_MAIN_HEADER and HAVE_JNLIB_LOGGING are defined. +*/ +#if defined(GNUPG_MAJOR_VERSION) \ + || (defined(GNUPG_SCD_MAIN_HEADER) && defined(HAVE_JNLIB_LOGGING)) -# if GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */ +#if defined(GNUPG_SCD_MAIN_HEADER) +# include GNUPG_SCD_MAIN_HEADER +#elif GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */ # include "options.h" # include "util.h" # include "memory.h" # include "cardglue.h" # else /* This is the modularized GnuPG 1.9 or later. */ # include "scdaemon.h" -# endif +#endif /* Disable all debugging output for now. */ #undef DBG_CARD_IO diff --git a/scd/command.c b/scd/command.c index d148ddb5a..4746e11b5 100644 --- a/scd/command.c +++ b/scd/command.c @@ -351,7 +351,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) buf = xtrymalloc (40 + 1 + strlen (certid) + 1); if (!buf) - rc = out_of_core (); + rc = gpg_error (gpg_err_code_from_errno (errno)); else { sprintf (buf, "%d %s", certtype, certid); @@ -389,7 +389,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1); if (!buf) - rc = out_of_core (); + rc = gpg_error (gpg_err_code_from_errno (errno)); else { int i; @@ -577,7 +577,7 @@ pin_cb (void *opaque, const char *info, char **retstr) rc = asprintf (&command, "NEEDPIN %s", info); if (rc < 0) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); /* FIXME: Write an inquire function which returns the result in secure memory */ diff --git a/scd/iso7816.c b/scd/iso7816.c index 1ee9b55e7..d7d3c126b 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -24,7 +24,9 @@ #include <stdlib.h> #include <string.h> -#if GNUPG_MAJOR_VERSION == 1 +#if defined(GNUPG_SCD_MAIN_HEADER) +#include GNUPG_SCD_MAIN_HEADER +#elif GNUPG_MAJOR_VERSION == 1 /* This is used with GnuPG version < 1.9. The code has been source copied from the current GnuPG >= 1.9 and is maintained over there. */ @@ -200,7 +202,7 @@ iso7816_change_reference_data (int slot, int chvno, buf = xtrymalloc (oldchvlen + newchvlen); if (!buf) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); if (oldchvlen) memcpy (buf, oldchv, oldchvlen); memcpy (buf+oldchvlen, newchv, newchvlen); @@ -341,7 +343,8 @@ iso7816_decipher (int slot, const unsigned char *data, size_t datalen, /* We need to prepend the padding indicator. */ buf = xtrymalloc (datalen + 1); if (!buf) - return out_of_core (); + return gpg_error (gpg_err_code_from_errno (errno)); + *buf = padind; /* Padding indicator. */ memcpy (buf+1, data, datalen); sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf, @@ -550,11 +553,13 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax, /* Perform a READ RECORD command. RECNO gives the record number to read with 0 indicating the current record. RECCOUNT must be 1 (not - all cards support reading of more than one record). The result is - stored in a newly allocated buffer at the address passed by RESULT. - Returns the length of this data at the address of RESULTLEN. */ + all cards support reading of more than one record). SHORT_EF + should be 0 to read the current EF or contain a short EF. The + result is stored in a newly allocated buffer at the address passed + by RESULT. Returns the length of this data at the address of + RESULTLEN. */ gpg_error_t -iso7816_read_record (int slot, int recno, int reccount, +iso7816_read_record (int slot, int recno, int reccount, int short_ef, unsigned char **result, size_t *resultlen) { int sw; @@ -568,7 +573,8 @@ iso7816_read_record (int slot, int recno, int reccount, /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus we check for this limit. */ - if (recno < 0 || recno > 255 || reccount != 1) + if (recno < 0 || recno > 255 || reccount != 1 + || short_ef < 0 || short_ef > 254 ) return gpg_error (GPG_ERR_INV_VALUE); buffer = NULL; @@ -577,7 +583,7 @@ iso7816_read_record (int slot, int recno, int reccount, with an Le of 0. */ sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD, recno, - 0x04, + short_ef? short_ef : 0x04, -1, NULL, 254, &buffer, &bufferlen); diff --git a/scd/iso7816.h b/scd/iso7816.h index 937326b6d..8f2b150e6 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -67,6 +67,7 @@ gpg_error_t iso7816_get_challenge (int slot, gpg_error_t iso7816_read_binary (int slot, size_t offset, size_t nmax, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_read_record (int slot, int recno, int reccount, + int short_ef, unsigned char **result, size_t *resultlen); #endif /*ISO7816_H*/ diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index 6f8b330b1..3882e1dfd 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -50,8 +50,10 @@ enum cmd_and_opt_values { oInteractive = 'i', oVerbose = 'v', + oQuiet = 'q', oReaderPort = 500, octapiDriver, + oDebug, oDebugAll, @@ -68,6 +70,7 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, "@Options:\n " }, { oInteractive, "interactive", 0, "start in interactive explorer mode"}, + { oQuiet, "quiet", 0, "quiet" }, { oVerbose, "verbose", 0, "verbose" }, { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"}, { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"}, @@ -86,7 +89,7 @@ static ARGPARSE_OPTS opts[] = { static void interactive_shell (int slot); - +static void dump_other_cards (int slot); static const char * my_strusage (int level) @@ -168,6 +171,7 @@ main (int argc, char **argv ) switch (pargs.r_opt) { case oVerbose: opt.verbose++; break; + case oQuiet: opt.quiet++; break; case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; case oReaderPort: reader_port = pargs.r.ret_str; break; @@ -191,7 +195,7 @@ main (int argc, char **argv ) if (slot == -1) exit (1); - if (!gen_random) + if (!gen_random && !opt.quiet) { rc = atr_dump (slot, stdout); if (rc) @@ -210,12 +214,17 @@ main (int argc, char **argv ) rc = app_select_openpgp (&appbuf); if (rc) { - log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); + if (!opt.quiet) + log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); memset (&appbuf, 0, sizeof appbuf); appbuf.slot = slot; rc = app_select_dinsig (&appbuf); if (rc) - log_info ("selecting dinsig failed: %s\n", gpg_strerror (rc)); + { + if (!opt.quiet) + log_info ("selecting dinsig failed: %s\n", gpg_strerror (rc)); + dump_other_cards (slot); + } else { appbuf.initialized = 1; @@ -398,6 +407,7 @@ interactive_shell (int slot) cmdAPP, cmdREAD, cmdREADREC, + cmdREADSHORTREC, cmdDEBUG, cmdVERIFY, cmdCHANGEREF, @@ -425,6 +435,7 @@ interactive_shell (int slot) { "rb" , cmdREAD, NULL }, { "readrec", cmdREADREC, "read record(s)" }, { "rr" , cmdREADREC, NULL }, + { "rsr" , cmdREADSHORTREC, "readshortrec RECNO SHORT_EF" }, { "verify" , cmdVERIFY, "verify CHVNO PIN" }, { "ver" , cmdVERIFY, NULL }, { "changeref", cmdCHANGEREF, "change reference data" }, @@ -559,7 +570,8 @@ interactive_shell (int slot) for (i=1, err=0; !err; i++) { xfree (result); result = NULL; - err = iso7816_read_record (slot, i, 1, &result, &resultlen); + err = iso7816_read_record (slot, i, 1, 0, + &result, &resultlen); if (!err) dump_buffer (result, resultlen); } @@ -568,13 +580,31 @@ interactive_shell (int slot) } else { - err = iso7816_read_record (slot, arg_number, 1, + err = iso7816_read_record (slot, arg_number, 1, 0, &result, &resultlen); if (!err) dump_or_store_buffer (arg_string, result, resultlen); } break; + case cmdREADSHORTREC: + { + int short_ef; + + short_ef = strtol (arg_next, NULL, 0); + + if (short_ef < 1 || short_ef > 254) + printf ("error: short EF must be between 1 and 254\n"); + else + { + err = iso7816_read_record (slot, arg_number, 1, short_ef, + &result, &resultlen); + if (!err) + dump_or_store_buffer (arg_string, result, resultlen); + } + } + break; + case cmdVERIFY: if (arg_number < 0 || arg_number > 255 || (arg_number & 127) > 31) printf ("error: invalid CHVNO\n"); @@ -637,3 +667,104 @@ interactive_shell (int slot) ; } + + +/* Figure out whether the current card is a German Geldkarte and print + what we know about it. */ +static int +dump_geldkarte (int slot) +{ + unsigned char *r = NULL; + size_t rlen; + const char *t; + + if (iso7816_read_record (slot, 1, 1, 0xbc, &r, &rlen)) + return -1; + /* We require that the record is at least 24 bytes, the first byte + is 0x67 and the filler byte is correct. */ + if (rlen < 24 || *r != 0x67 || r[22]) + return -1; + + /* The short Bankleitzahl consists of 3 bytes at offset 1. */ + switch (r[1]) + { + case 0x21: t = "Oeffentlich-rechtliche oder private Bank"; break; + case 0x22: t = "Privat- oder Geschftsbank"; break; + case 0x25: t = "Sparkasse"; break; + case 0x26: + case 0x29: t = "Genossenschaftsbank"; break; + default: + xfree (r); + return -1; /* Probably not a Geldkarte. */ + } + + printf ("KBLZ .....: %02X-%02X%02X (%s)\n", r[1], r[2], r[3], t); + printf ("Card-No ..: %02X%02X%02X%02X%02X\n", r[4], r[5], r[6], r[7], r[8]); + +/* Byte 10 enthlt im linken Halbbyte eine Prfziffer, die nach dem */ +/* Verfahren 'Luhn formula for computing modulus 10' ber die Ziffern der */ +/* ersten 9 Byte berechnet ist. */ + +/* Das rechte Halbbyte wird zu 'D' gesetzt. */ + +/* Fr die Berechnung der Luhn-Prfziffer sind die folgenden Schritte */ +/* durchzufhren: */ + +/* Schritt 1: Mit der rechtesten Ziffer beginnend ist einschlielich dieser */ +/* Ziffer jede bernchste Ziffer zu verdoppeln (mit 2 multiplizieren). */ + +/* Schritt 2: Die einzelnen Ziffern der Produkte aus Schritt 1 und die bei */ +/* diesen Multiplikationen unberhrt gebliebenen Ziffern sind zu addieren. */ + +/* Schritt 3: Das Ergebnis der Addition aus Schritt 2 ist von dem auf die */ +/* nchst hhere Zahl mit der Einerstelle 0 aufgerundeten Ergebnis der */ +/* Addition aus Schritt 2 abzuziehen. Wenn das Ergebnis der Addition aus */ +/* Schritt 2 bereits eine Zahl mit der Einerstelle 0 ergibt (z.B. 30, 40, */ +/* usw.), ist die Prfziffer 0. */ + +/* Beispiel: Kartennummer ohne Prfziffer: 992 839 871 */ + +/* 9 9 2 8 3 9 8 7 1 */ + +/* x 2 x 2 x 2 x 2 x 2 Schritt 1 */ + +/* 18 4 6 16 2 */ + +/* 1+8 +9 +4 +8 +6 +9 +1+6 +7 +2 = 61 Schritt 2 */ + +/* 70-61 = 9 Schritt 3 */ + +/* Prfziffer zu 992 839 871 = 9 */ + + + printf ("Expires at: %02X/%02X\n", r[11], r[10] ); + printf ("Valid from: %02X.%02X.%02X\n", r[14], r[13], r[12]); + printf ("Country ..: %02X%02X\n", r[15], r[16]); + printf ("Currency .: %c%c%c\n", isascii (r[17])? r[17]:' ', + isascii (r[18])? r[18]:' ', isascii (r[19])? r[19]:' '); + printf ("Cur.-Mult : %s\n", + r[20] == 0x01? "0.01": + r[20] == 0x02? "0.1": + r[20] == 0x04? "1": + r[20] == 0x08? "10": + r[20] == 0x10? "100": + r[20] == 0x20? "1000": "?"); + printf ("ZKA ChipID: %02X\n", r[21]); + printf ("OS version: %02X\n", r[23]); + + xfree (r); + return 0; +} + + + +/* Try to figure out the type of teh card and dump its contents. */ +static void +dump_other_cards (int slot) +{ + + if (!dump_geldkarte (slot)) + return; + +} + diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 2bbf271da..098738508 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -33,14 +33,6 @@ #include "../common/util.h" #include "../common/errors.h" -/* Convenience funcion to be used instead of returning the old - GNUPG_Out_Of_Core. */ -static __inline__ gpg_error_t -out_of_core (void) -{ - return gpg_error (gpg_err_code_from_errno (errno)); -} - #define MAX_DIGEST_LEN 24 -- cgit v1.2.3 From 050b96f79077b1514829f49a89ce2a1acda0a483 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 18:59:09 +0000 Subject: (main): Implemented --gpgconf-list. --- sm/ChangeLog | 4 ++++ sm/certlist.c | 1 + sm/gpgsm.c | 60 +++++++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 18431c11c..210448643 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-03-16 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Implemented --gpgconf-list. + 2004-03-15 Werner Koch <wk@gnupg.org> * keylist.c (list_cert_colon): Hack to set the expired flag. diff --git a/sm/certlist.c b/sm/certlist.c index 8ee3c2caf..6e694b781 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -40,6 +40,7 @@ static const char oid_kp_clientAuth[] = "1.3.6.1.5.5.7.3.2"; static const char oid_kp_codeSigning[] = "1.3.6.1.5.5.7.3.3"; static const char oid_kp_emailProtection[]= "1.3.6.1.5.5.7.3.4"; static const char oid_kp_timeStamping[] = "1.3.6.1.5.5.7.3.8"; +static const char oid_kp_ocspSigning[] = "1.3.6.1.5.6.7.3.9"; /* Return 0 if the cert is usable for encryption. A MODE of 0 checks for signing a MODE of 1 checks for encryption, a MODE of 2 checks diff --git a/sm/gpgsm.c b/sm/gpgsm.c index ca7fbfcca..6b8a2ea49 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -690,6 +690,7 @@ main ( int argc, char **argv) CERTLIST recplist = NULL; CERTLIST signerlist = NULL; int do_not_setup_keys = 0; + char *config_filename = NULL; /* trap_unaligned ();*/ set_strusage (my_strusage); @@ -1116,7 +1117,8 @@ main ( int argc, char **argv) { fclose (configfp); configfp = NULL; - xfree (configname); + /* Keep a copy of the config filename. */ + config_filename = configname; configname = NULL; goto next_pass; } @@ -1259,21 +1261,47 @@ main ( int argc, char **argv) { case aGPGConfList: { /* List options and default values in the GPG Conf format. */ - char *filename; - - /* First the default configuration file. This is not an - option, but it is vital information for GPG Conf. */ - filename = make_filename (opt.homedir, "gpgsm.conf", NULL); - printf ("gpgconf-gpgsm.conf:\"%s\n", filename); - xfree (filename); - - printf ("verbose:\n" - "quiet:\n" - "debug-level:none\n" - "log-file:\n" - "force:\n" - "faked-system-time:\n" - "no-greeting:\n"); + + /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ + /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING + FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ +#define GC_OPT_FLAG_NONE 0UL + /* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + /* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + /* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) + /* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + + printf ("gpgconf-gpgsm.conf:%lu:\"%s\"\n", + GC_OPT_FLAG_DEFAULT, + config_filename?config_filename:"/dev/null"); + + printf ("verbose:%lu:\n" + "quiet:%lu:\n" + "debug-level:%lu:\"none\":\n" + "log-file:%lu:\n", + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_DEFAULT, + GC_OPT_FLAG_NONE ); + printf ("disable-crl-checks:%lu:\n", + GC_OPT_FLAG_NONE ); + printf ("enable-ocsp:%lu:\n", + GC_OPT_FLAG_NONE ); + printf ("include-certs:%lu:1:\n", + GC_OPT_FLAG_DEFAULT ); + printf ("disable-policy-checks:%lu:\n", + GC_OPT_FLAG_NONE ); + printf ("auto-issuer-key-retrieve:%lu:\n", + GC_OPT_FLAG_NONE ); + } break; -- cgit v1.2.3 From e209ea3c39e7110d94e4420513f397d8656a75b7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 18:59:21 +0000 Subject: * app-dinsig.c: Implemented. Based on app-nks.c and card-dinsig.c * app-nks.c (get_length_of_cert): Removed. * app-help.c: New. (app_help_read_length_of_cert): New. Code taken from above. New optional arg R_CERTOFF. * card-dinsig.c: Removed. * card.c (card_get_serial_and_stamp): Do not bind to the old and never finsiged card-dinsig.c. * iso7816.c (iso7816_read_binary): Allow for an NMAX > 254. --- scd/ChangeLog | 14 +++ scd/Makefile.am | 14 +-- scd/app-common.h | 7 ++ scd/app-dinsig.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- scd/app-help.c | 157 +++++++++++++++++++++++++++ scd/app-nks.c | 66 +----------- scd/app-openpgp.c | 2 +- scd/card.c | 2 - scd/iso7816.c | 20 +++- scd/scdaemon.c | 67 +++++++++--- 10 files changed, 561 insertions(+), 102 deletions(-) create mode 100644 scd/app-help.c diff --git a/scd/ChangeLog b/scd/ChangeLog index a9296cbbb..679f867fe 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,17 @@ +2004-03-16 Werner Koch <wk@gnupg.org> + + * app-dinsig.c: Implemented. Based on app-nks.c and card-dinsig.c + * app-nks.c (get_length_of_cert): Removed. + * app-help.c: New. + (app_help_read_length_of_cert): New. Code taken from above. New + optional arg R_CERTOFF. + + * card-dinsig.c: Removed. + * card.c (card_get_serial_and_stamp): Do not bind to the old and + never finsiged card-dinsig.c. + + * iso7816.c (iso7816_read_binary): Allow for an NMAX > 254. + 2004-03-11 Werner Koch <wk@gnupg.org> * scdaemon.h (out_of_core): Removed. Replaced callers by standard diff --git a/scd/Makefile.am b/scd/Makefile.am index 89ebf4e05..da59a1997 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -34,12 +34,12 @@ scdaemon_SOURCES = \ scdaemon.c scdaemon.h \ command.c card.c \ card-common.h \ - card-p15.c card-dinsig.c \ + card-p15.c \ apdu.c apdu.h \ ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ tlv.c tlv.h \ - app.c app-common.h $(card_apps) + app.c app-common.h app-help.c $(card_apps) scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ @@ -53,12 +53,12 @@ sc_investigate_SOURCES = \ iso7816.c iso7816.h \ tlv.c tlv.h \ atr.c atr.h \ - app.c app-common.h $(card_apps) + app.c app-common.h app-help.c $(card_apps) sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) @INTLLIBS@ \ - -lgpg-error -ldl + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBUSB_LIBS) \ + @INTLLIBS@ -lgpg-error -ldl sc_copykeys_SOURCES = \ @@ -68,10 +68,10 @@ sc_copykeys_SOURCES = \ iso7816.c iso7816.h \ tlv.c tlv.h \ atr.c atr.h \ - app.c app-common.h $(card_apps) + app.c app-common.h app-help.c $(card_apps) sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBUSB_LIBS) \ + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBUSB_LIBS) \ -lgpg-error @INTLLIBS@ -ldl diff --git a/scd/app-common.h b/scd/app-common.h index cda17700f..c16a15719 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -21,6 +21,8 @@ #ifndef GNUPG_SCD_APP_COMMON_H #define GNUPG_SCD_APP_COMMON_H +#include <ksba.h> + struct app_ctx_s { int initialized; /* The application has been initialied and the function pointers may be used. Note that for @@ -80,6 +82,11 @@ struct app_ctx_s { int app_select_openpgp (app_t app); int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); #else +/*-- app-help.c --*/ +gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip); +size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); + + /*-- app.c --*/ app_t select_application (ctrl_t ctrl, int slot, const char *name); void release_application (app_t app); diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 4b5b517eb..38fbc79ee 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -1,5 +1,5 @@ /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application. - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -65,9 +65,6 @@ The letters in brackets indicate optional or mandatory files: The first for card terminals under full control and the second for "business" card terminals. - - FIXME: Needs a lot more explanation. - */ @@ -85,17 +82,317 @@ #include "iso7816.h" #include "app-common.h" +#include "tlv.h" + + +static int +do_learn_status (app_t app, ctrl_t ctrl) +{ + gpg_error_t err; + char ct_buf[100], id_buf[100]; + char hexkeygrip[41]; + size_t len, certoff; + unsigned char *der; + size_t derlen; + ksba_cert_t cert; + int fid; + + /* Return the certificate of the card holder. */ + fid = 0xC000; + len = app_help_read_length_of_cert (app->slot, fid, &certoff); + if (!len) + return 0; /* Card has not been personalized. */ + + sprintf (ct_buf, "%d", 101); + sprintf (id_buf, "DINSIG.%04X", fid); + send_status_info (ctrl, "CERTINFO", + ct_buf, strlen (ct_buf), + id_buf, strlen (id_buf), + NULL, (size_t)0); + + /* Now we need to read the certificate, so that we can get the + public key out of it. */ + err = iso7816_read_binary (app->slot, certoff, len-certoff, &der, &derlen); + if (err) + { + log_info ("error reading entire certificate from FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + return 0; + } + + err = ksba_cert_new (&cert); + if (err) + { + xfree (der); + return err; + } + err = ksba_cert_init_from_mem (cert, der, derlen); + xfree (der); der = NULL; + if (err) + { + log_error ("failed to parse the certificate at FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + ksba_cert_release (cert); + return err; + } + err = app_help_get_keygrip_string (cert, hexkeygrip); + if (err) + { + log_error ("failed to calculate the keygrip for FID 0x%04X\n", fid); + ksba_cert_release (cert); + return gpg_error (GPG_ERR_CARD); + } + ksba_cert_release (cert); + + sprintf (id_buf, "DINSIG.%04X", fid); + send_status_info (ctrl, "KEYPAIRINFO", + hexkeygrip, 40, + id_buf, strlen (id_buf), + NULL, (size_t)0); + return 0; +} + + +/* Read the certificate with id CERTID (as returned by learn_status in + the CERTINFO status lines) and return it in the freshly allocated + buffer put into CERT and the length of the certificate put into + CERTLEN. + FIXME: This needs some cleanups and caching with do_learn_status. +*/ static int -do_learn_status (APP app, CTRL ctrl) +do_readcert (app_t app, const char *certid, + unsigned char **cert, size_t *certlen) { + int fid; + gpg_error_t err; + unsigned char *buffer; + const unsigned char *p; + size_t buflen, n; + int class, tag, constructed, ndef; + size_t totobjlen, objlen, hdrlen; + int rootca = 0; + + *cert = NULL; + *certlen = 0; + if (strncmp (certid, "DINSIG.", 7) ) + return gpg_error (GPG_ERR_INV_ID); + certid += 7; + if (!hexdigitp (certid) || !hexdigitp (certid+1) + || !hexdigitp (certid+2) || !hexdigitp (certid+3) + || certid[4]) + return gpg_error (GPG_ERR_INV_ID); + fid = xtoi_4 (certid); + if (fid != 0xC000 ) + return gpg_error (GPG_ERR_NOT_FOUND); + + /* Read the entire file. fixme: This could be optimized by first + reading the header to figure out how long the certificate + actually is. */ + err = iso7816_select_file (app->slot, fid, 0, NULL, NULL); + if (err) + { + log_error ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err)); + return err; + } + + err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen); + if (err) + { + log_error ("error reading certificate from FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + return err; + } + + if (!buflen || *buffer == 0xff) + { + log_info ("no certificate contained in FID 0x%04X\n", fid); + err = gpg_error (GPG_ERR_NOT_FOUND); + goto leave; + } + + /* Now figure something out about the object. */ + p = buffer; + n = buflen; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + if ( class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed ) + ; + else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed ) + rootca = 1; + else + return gpg_error (GPG_ERR_INV_OBJ); + totobjlen = objlen + hdrlen; + assert (totobjlen <= buflen); + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + + if (rootca) + ; + else if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed) + { + const unsigned char *save_p; + + /* The certificate seems to be contained in a userCertificate + container. Skip this and assume the following sequence is + the certificate. */ + if (n < objlen) + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto leave; + } + p += objlen; + n -= objlen; + save_p = p; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) ) + return gpg_error (GPG_ERR_INV_OBJ); + totobjlen = objlen + hdrlen; + assert (save_p + totobjlen <= buffer + buflen); + memmove (buffer, save_p, totobjlen); + } + + *cert = buffer; + buffer = NULL; + *certlen = totobjlen; + + leave: + xfree (buffer); + return err; +} + + +/* Verify the PIN if required. */ +static int +verify_pin (app_t app, + int (pincb)(void*, const char *, char **), + void *pincb_arg) +{ + if (!app->did_chv1 || app->force_chv1 ) + { + char *pinvalue; + int rc; + + rc = pincb (pincb_arg, "PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + /* We require the PIN to be at least 6 and at max 8 bytes. + According to the specs, this should all be ASCII but we don't + check this. */ + if (strlen (pinvalue) < 6) + { + log_error ("PIN is too short; minimum length is 6\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + else if (strlen (pinvalue) > 8) + { + log_error ("PIN is too large; maximum length is 8\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + + rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); + if (rc) + { + log_error ("verify PIN failed\n"); + xfree (pinvalue); + return rc; + } + app->did_chv1 = 1; + xfree (pinvalue); + } + return 0; } +/* Create the signature and return the allocated result in OUTDATA. + If a PIN is required the PINCB will be used to ask for the PIN; + that callback should return the PIN in an allocated buffer and + store that in the 3rd argument. */ +static int +do_sign (app_t app, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + int rc; + int fid; + unsigned char data[35]; /* Must be large enough for a SHA-1 digest + + the largest OID _prefix above. */ + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + if (indatalen != 20 && indatalen != 16 && indatalen != 35) + return gpg_error (GPG_ERR_INV_VALUE); + + /* Check that the provided ID is vaid. This is not really needed + but we do it to to enforce correct usage by the caller. */ + if (strncmp (keyidstr, "DINSIG.", 7) ) + return gpg_error (GPG_ERR_INV_ID); + keyidstr += 7; + if (!hexdigitp (keyidstr) || !hexdigitp (keyidstr+1) + || !hexdigitp (keyidstr+2) || !hexdigitp (keyidstr+3) + || keyidstr[4]) + return gpg_error (GPG_ERR_INV_ID); + fid = xtoi_4 (keyidstr); + if (fid != 0xC000) + return gpg_error (GPG_ERR_NOT_FOUND); + + /* Prepare the DER object from INDATA. */ + if (indatalen == 35) + { + /* Alright, the caller was so kind to send us an already + prepared DER object. Check that it is what we want and that + it matches the hash algorithm. */ + if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15)) + ; + else if (hashalgo == GCRY_MD_RMD160 && !memcmp (indata, rmd160_prefix,15)) + ; + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data, indata, indatalen); + } + else + { + if (hashalgo == GCRY_MD_SHA1) + memcpy (data, sha1_prefix, 15); + else if (hashalgo == GCRY_MD_RMD160) + memcpy (data, rmd160_prefix, 15); + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data+15, indata, indatalen); + } + + rc = verify_pin (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + return rc; +} + /* Select the DINSIG application on the card in SLOT. This function @@ -113,17 +410,18 @@ app_select_dinsig (APP app) app->apptype = "DINSIG"; app->fnc.learn_status = do_learn_status; + app->fnc.readcert = do_readcert; app->fnc.getattr = NULL; app->fnc.setattr = NULL; app->fnc.genkey = NULL; - app->fnc.sign = NULL; + app->fnc.sign = do_sign; app->fnc.auth = NULL; app->fnc.decipher = NULL; app->fnc.change_pin = NULL; app->fnc.check_pin = NULL; + + app->force_chv1 = 1; } return rc; } - - diff --git a/scd/app-help.c b/scd/app-help.c new file mode 100644 index 000000000..c6695635f --- /dev/null +++ b/scd/app-help.c @@ -0,0 +1,157 @@ +/* app-help.c - Application helper functions + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "scdaemon.h" +#include "app-common.h" +#include "iso7816.h" +#include "tlv.h" + +/* Return the KEYGRIP for the certificate CERT as an hex encoded + string in the user provided buffer HEXKEYGRIP which must be of at + least 41 bytes. */ +gpg_error_t +app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip) +{ + gpg_error_t err; + gcry_sexp_t s_pkey; + ksba_sexp_t p; + size_t n; + unsigned char array[20]; + int i; + + p = ksba_cert_get_public_key (cert); + if (!p) + return gpg_error (GPG_ERR_BUG); + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + return gpg_error (GPG_ERR_INV_SEXP); + err = gcry_sexp_sscan (&s_pkey, NULL, p, n); + xfree (p); + if (err) + return err; /* Can't parse that S-expression. */ + if (!gcry_pk_get_keygrip (s_pkey, array)) + { + gcry_sexp_release (s_pkey); + return gpg_error (GPG_ERR_GENERAL); /* Failed to calculate the keygrip.*/ + } + gcry_sexp_release (s_pkey); + + for (i=0; i < 20; i++) + sprintf (hexkeygrip+i*2, "%02X", array[i]); + + return 0; +} + + + +/* Given the SLOT and the File ID FID, return the length of the + certificate contained in that file. Returns 0 if the file does not + exists or does not contain a certificate. If R_CERTOFF is not + NULL, the length the header will be stored at this address; thus to + parse the X.509 certificate a read should start at that offset. + + On success the file is still selected. +*/ +size_t +app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff) +{ + gpg_error_t err; + unsigned char *buffer; + const unsigned char *p; + size_t buflen, n; + int class, tag, constructed, ndef; + size_t resultlen, objlen, hdrlen; + + err = iso7816_select_file (slot, fid, 0, NULL, NULL); + if (err) + { + log_info ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err)); + return 0; + } + + err = iso7816_read_binary (slot, 0, 32, &buffer, &buflen); + if (err) + { + log_info ("error reading certificate from FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + return 0; + } + + if (!buflen || *buffer == 0xff) + { + log_info ("no certificate contained in FID 0x%04X\n", fid); + xfree (buffer); + return 0; + } + + p = buffer; + n = buflen; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + { + log_info ("error parsing certificate in FID 0x%04X: %s\n", + fid, gpg_strerror (err)); + xfree (buffer); + return 0; + } + + /* All certificates should commence with a SEQUENCE except for the + special ROOT CA which are enclosed in a SET. */ + if ( !(class == CLASS_UNIVERSAL && constructed + && (tag == TAG_SEQUENCE || tag == TAG_SET))) + { + log_info ("contents of FID 0x%04X does not look like a certificate\n", + fid); + return 0; + } + + resultlen = objlen + hdrlen; + if (r_certoff) + { + /* The callers want the offset to the actual certificate. */ + *r_certoff = hdrlen; + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + return 0; + + if (class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed) + { + /* The certificate seems to be contained in a + userCertificate container. Assume the following sequence + is the certificate. */ + *r_certoff += hdrlen + objlen; + if (*r_certoff > resultlen) + return 0; /* That should never happen. */ + } + } + + return resultlen; +} + + diff --git a/scd/app-nks.c b/scd/app-nks.c index a4b6e3a15..e69b59879 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -53,68 +53,6 @@ static struct { -/* Given the slot and the File Id FID, return the length of the - certificate contained in that file. Returns 0 if the file does not - exists or does not contain a certificate. */ -static size_t -get_length_of_cert (int slot, int fid) -{ - gpg_error_t err; - unsigned char *buffer; - const unsigned char *p; - size_t buflen, n; - int class, tag, constructed, ndef; - size_t objlen, hdrlen; - - err = iso7816_select_file (slot, fid, 0, NULL, NULL); - if (err) - { - log_info ("error selecting FID 0x%04X: %s\n", fid, gpg_strerror (err)); - return 0; - } - - err = iso7816_read_binary (slot, 0, 32, &buffer, &buflen); - if (err) - { - log_info ("error reading certificate from FID 0x%04X: %s\n", - fid, gpg_strerror (err)); - return 0; - } - - if (!buflen || *buffer == 0xff) - { - log_info ("no certificate contained in FID 0x%04X\n", fid); - xfree (buffer); - return 0; - } - - p = buffer; - n = buflen; - err = parse_ber_header (&p, &n, &class, &tag, &constructed, - &ndef, &objlen, &hdrlen); - if (err) - { - log_info ("error parsing certificate in FID 0x%04X: %s\n", - fid, gpg_strerror (err)); - xfree (buffer); - return 0; - } - - /* All certificates should commence with a SEQUENCE expect fro the - special ROOT CA which are enclosed in a SET. */ - if ( !(class == CLASS_UNIVERSAL && constructed - && (tag == TAG_SEQUENCE || tag == TAG_SET))) - { - log_info ("contents of FID 0x%04X does not look like a certificate\n", - fid); - return 0; - } - - return objlen + hdrlen; -} - - - /* Read the file with FID, assume it contains a public key and return its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */ static gpg_error_t @@ -191,8 +129,10 @@ do_learn_status (APP app, CTRL ctrl) { if (filelist[i].certtype) { - size_t len = get_length_of_cert (app->slot, filelist[i].fid); + size_t len; + len = app_help_read_length_of_cert (app->slot, + filelist[i].fid, NULL); if (len) { /* FIXME: We should store the length in the application's diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 7782b8e1c..af5f5a27f 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1201,7 +1201,7 @@ app_select_openpgp (APP app) /* The OpenPGP card returns the serial number as part of the AID; because we prefer to use OpenPGP serial numbers, we - repalce a possibly already set one from a EF.GDO with this + replace a possibly already set one from a EF.GDO with this one. Note, that for current OpenPGP cards, no EF.GDO exists and thus it won't matter at all. */ rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); diff --git a/scd/card.c b/scd/card.c index 8366dcb1c..9ec2a52c5 100644 --- a/scd/card.c +++ b/scd/card.c @@ -325,8 +325,6 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp) } if (card->p15card) card_p15_bind (card); - else - card_dinsig_bind (card); card->fnc.initialized = 1; } diff --git a/scd/iso7816.c b/scd/iso7816.c index d7d3c126b..24361d148 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -488,6 +488,8 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax, int sw; unsigned char *buffer; size_t bufferlen; + int read_all = !nmax; + size_t n; if (!result || !resultlen) return gpg_error (GPG_ERR_INV_VALUE); @@ -496,18 +498,22 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax, /* We can only encode 15 bits in p0,p1 to indicate an offset. Thus we check for this limit. */ - if (offset > 32767 || nmax > 254) + if (offset > 32767) return gpg_error (GPG_ERR_INV_VALUE); do { buffer = NULL; bufferlen = 0; - /* Fixme: Either the ccid driver of the TCOS cards have problems + /* Fixme: Either the ccid driver or the TCOS cards have problems with an Le of 0. */ + if (read_all || nmax > 254) + n = 254; + else + n = nmax; sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, - ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, - nmax? nmax : 254, &buffer, &bufferlen); + ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, + n, &buffer, &bufferlen); if (sw != SW_SUCCESS && sw != SW_EOF_REACHED) { @@ -545,8 +551,12 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax, if (offset > 32767) break; /* We simply truncate the result for too large files. */ + if (nmax > bufferlen) + nmax -= bufferlen; + else + nmax = 0; } - while (!nmax && sw != SW_EOF_REACHED); + while ((read_all && sw != SW_EOF_REACHED) || (!read_all && nmax)); return 0; } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 5665237ca..93746ec35 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -103,8 +103,8 @@ static ARGPARSE_OPTS opts[] = { { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, - { octapiDriver, "ctapi-driver", 2, N_("NAME|use NAME as ct-API driver")}, - { opcscDriver, "pcsc-driver", 2, N_("NAME|use NAME as PC/SC driver")}, + { octapiDriver, "ctapi-driver", 2, N_("|NAME|use NAME as ct-API driver")}, + { opcscDriver, "pcsc-driver", 2, N_("|NAME|use NAME as PC/SC driver")}, { oDisableCCID, "disable-ccid", 0, #ifdef HAVE_LIBUSB N_("do not use the internal CCID driver") @@ -126,6 +126,9 @@ static ARGPARSE_OPTS opts[] = { }; +#define DEFAULT_PCSC_DRIVER "libpcsclite.so" + + static volatile int caught_fatal_sig = 0; /* It is possible that we are currently running under setuid permissions */ @@ -302,6 +305,7 @@ main (int argc, char **argv ) char *logfile = NULL; int debug_wait = 0; int gpgconf_list = 0; + const char *config_filename = NULL; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -334,7 +338,7 @@ main (int argc, char **argv ) may_coredump = disable_core_dumps (); /* Set default options. */ - opt.pcsc_driver = "libpcsclite.so"; + opt.pcsc_driver = DEFAULT_PCSC_DRIVER; shell = getenv ("SHELL"); @@ -466,7 +470,8 @@ main (int argc, char **argv ) { fclose( configfp ); configfp = NULL; - xfree(configname); + /* Keep a copy of the config name for use by --gpgconf-list. */ + config_filename = configname; configname = NULL; goto next_pass; } @@ -507,19 +512,49 @@ main (int argc, char **argv ) if (gpgconf_list) { /* List options and default values in the GPG Conf format. */ - char *filename; - filename = make_filename (opt.homedir, "scdaemon.conf", NULL); - printf ("gpgconf-scdaemon.conf:\"%s\n", filename); - xfree (filename); - - printf ("verbose:\n" - "quiet:\n" - "debug-level:none\n" - "log-file:\n" - "force:\n" - "faked-system-time:\n" - "no-greeting:\n"); + /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ + /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING + FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ +#define GC_OPT_FLAG_NONE 0UL + /* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + /* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + /* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) + /* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + + printf ("gpgconf-scdaemon.conf:%lu:\"%s\"\n", + GC_OPT_FLAG_DEFAULT, + config_filename?config_filename:"/dev/null"); + + printf ("verbose:%lu:\n" + "quiet:%lu:\n" + "debug-level:%lu:\"none\":\n" + "log-file:%lu:\n", + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_DEFAULT, + GC_OPT_FLAG_NONE ); + + printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE ); + printf ("ctapi-driver:%lu:\n", GC_OPT_FLAG_NONE ); + printf ("pcsc-driver:%lu:\"%s\":\n", + GC_OPT_FLAG_DEFAULT, DEFAULT_PCSC_DRIVER ); +#ifdef HAVE_LIBUSB + printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE ); +#endif +#ifdef HAVE_LIBUSB + printf ("disable-opensc:%lu:\n", GC_OPT_FLAG_NONE ); +#endif + printf ("allow-admin:%lu:\n", GC_OPT_FLAG_NONE ); + scd_exit (0); } -- cgit v1.2.3 From a854459fc14e4a8b612f4d9ef23607c2867d2cb8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 18:59:35 +0000 Subject: (parse_rereadable_options): Use the new DEFAULT_CACHE_TTL macro. (main): Updated --gpgconf-list output. --- agent/gpg-agent.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 5b9e22465..12bdb85ea 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -607,8 +607,9 @@ main (int argc, char **argv ) #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, config_filename); - + GC_OPT_FLAG_DEFAULT, + config_filename?config_filename:"/dev/null"); + printf ("verbose:%lu:\n" "quiet:%lu:\n" "debug-level:%lu:\"none\":\n" -- cgit v1.2.3 From 1cd35d8551aa11defd282df9b512fdec3c47de0e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 19:00:00 +0000 Subject: *** empty log message *** --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index c6bcf8d9e..85d931fa1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.9.7 ------------------------------------------------ + * Instrumented the modules for gpgconf. + + * Added support for DINSIG card applications. + Noteworthy changes in version 1.9.6 (2004-03-06) ------------------------------------------------ -- cgit v1.2.3 From 6568059dd647b8d604d669b9ff600cf3b3c78cea Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Mar 2004 19:00:25 +0000 Subject: (gc_options_gpg_agent): Implemented. (gc_options_gpgsm, gc_options_scdaemon): Implemented. (gc_backend_t): Add GC_BACKEND_SCDAEMON. --- tools/ChangeLog | 2 + tools/gpgconf-comp.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 123 insertions(+), 6 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index c8eca3137..9debec445 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,6 +1,8 @@ 2004-03-16 Werner Koch <wk@gnupg.org> * gpgconf-comp.c (gc_options_gpg_agent): Implemented. + (gc_options_gpgsm, gc_options_scdaemon): Implemented. + (gc_backend_t): Add GC_BACKEND_SCDAEMON. 2004-03-12 Marcus Brinkmann <marcus@g10code.de> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 4785eefb6..2839b37cf 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -114,6 +114,9 @@ typedef enum /* The GPG Agent. */ GC_BACKEND_GPG_AGENT, + /* The GnuPG SCDaemon. */ + GC_BACKEND_SCDAEMON, + /* The Aegypten directory manager. */ GC_BACKEND_DIRMNGR, @@ -152,6 +155,7 @@ static struct { "GnuPG", "gpg", "gpgconf-gpg.conf" }, { "GPGSM", "gpgsm", "gpgconf-gpgsm.conf" }, { "GPG Agent", "gpg-agent", "gpgconf-gpg-agent.conf" }, + { "SCDaemon", "scdaemon", "gpgconf-scdaemon.conf" }, { "DirMngr", "dirmngr", "gpgconf-dirmngr.conf" }, { "DirMngr LDAP Server List", NULL, "ldapserverlist-file", "LDAP Server" }, }; @@ -467,6 +471,64 @@ static gc_option_t gc_options_gpg_agent[] = /* The options of the GC_COMPONENT_SCDAEMON component. */ static gc_option_t gc_options_scdaemon[] = { + /* The configuration file to which we write the changes. */ + { "gpgconf-scdaemon.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, + + { "Monitor", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the diagnostic output" }, + { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + "gnupg", "verbose", + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, + { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "be somewhat more quiet", + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, + { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, + + { "Configuration", + GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, + NULL, "Options controlling the configuration" }, + { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "|FILE|read options from FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, + { "reader-port", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "|N|connect to reader at port N", + GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, + { "ctapi-driver", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "|NAME|use NAME as ct-API driver", + GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, + { "pcsc-driver", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "|NAME|use NAME as PC/SC driver", + GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, + { "disable-opensc", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "do not use the OpenSC layer", + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, + { "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "do not use the internal CCID driver", + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, + + + { "Debug", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "gnupg", "Options useful for debugging" }, + { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + "gnupg", "|LEVEL|set the debugging level to LEVEL", + GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, + { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "|FILE|write logs to FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, + + { "Security", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the security" }, + { "allow-admin", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "allow the use of admin card commands", + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, + + GC_OPTION_NULL }; @@ -474,6 +536,62 @@ static gc_option_t gc_options_scdaemon[] = /* The options of the GC_COMPONENT_GPGSM component. */ static gc_option_t gc_options_gpgsm[] = { + /* The configuration file to which we write the changes. */ + { "gpgconf-gpgsm.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM }, + + { "Monitor", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the diagnostic output" }, + { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + "gnupg", "verbose", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "be somewhat more quiet", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + + { "Configuration", + GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, + NULL, "Options controlling the configuration" }, + { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "|FILE|read options from FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM }, + + { "Debug", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "gnupg", "Options useful for debugging" }, + { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + "gnupg", "|LEVEL|set the debugging level to LEVEL", + GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, + { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "|FILE|write logs to FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM }, + { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM }, + + { "Security", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the security" }, + { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "never consult a CRL", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "check validity using OCSP", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "|N|number of certificates to include", + GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM }, + { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "do not check certificate policies", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "fetch missing issuer certificates", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + GC_OPTION_NULL }; @@ -518,12 +636,9 @@ static gc_option_t gc_options_dirmngr[] = { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "dirmngr", "Options useful for debugging" }, - { "debug", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, - "dirmngr", "|FLAGS|set the debugging FLAGS", - GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, - { "debug-all", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, - "dirmngr", "set all debugging flags", - GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + "dirmngr", "|LEVEL|set the debugging level to LEVEL", + GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "do not detach from the console", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, -- cgit v1.2.3 From d714e81e58f835f7a85e04049d19981ceeb426fc Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 17 Mar 2004 13:01:16 +0000 Subject: * gpg-agent.c (main) <gpgconf>: Fixed default value quoting. * scdaemon.c (main) <gpgconf>: Fixed default value quoting. * gpgsm.c (main) <gpgconf>: Fixed default value quoting. --- agent/ChangeLog | 4 ++++ agent/gpg-agent.c | 2 +- scd/ChangeLog | 4 ++++ scd/scdaemon.c | 4 ++-- sm/ChangeLog | 4 ++++ sm/gpgsm.c | 4 ++-- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 7516cddb8..484a5ffd7 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-03-17 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main) <gpgconf>: Fixed default value quoting. + 2004-03-16 Werner Koch <wk@gnupg.org> * gpg-agent.c (parse_rereadable_options): Use the new diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 12bdb85ea..2051d9080 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -612,7 +612,7 @@ main (int argc, char **argv ) printf ("verbose:%lu:\n" "quiet:%lu:\n" - "debug-level:%lu:\"none\":\n" + "debug-level:%lu:\"none:\n" "log-file:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, diff --git a/scd/ChangeLog b/scd/ChangeLog index 679f867fe..9b2ddf79c 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-03-17 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main) <gpgconf>: Fixed default value quoting. + 2004-03-16 Werner Koch <wk@gnupg.org> * app-dinsig.c: Implemented. Based on app-nks.c and card-dinsig.c diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 93746ec35..9f1e409e4 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -530,13 +530,13 @@ main (int argc, char **argv ) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - printf ("gpgconf-scdaemon.conf:%lu:\"%s\"\n", + printf ("gpgconf-scdaemon.conf:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, config_filename?config_filename:"/dev/null"); printf ("verbose:%lu:\n" "quiet:%lu:\n" - "debug-level:%lu:\"none\":\n" + "debug-level:%lu:\"none:\n" "log-file:%lu:\n", GC_OPT_FLAG_NONE, GC_OPT_FLAG_NONE, diff --git a/sm/ChangeLog b/sm/ChangeLog index 210448643..08793b810 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-03-17 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main) <gpgconf>: Fixed default value quoting. + 2004-03-16 Werner Koch <wk@gnupg.org> * gpgsm.c (main): Implemented --gpgconf-list. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 6b8a2ea49..761aefcee 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1279,13 +1279,13 @@ main ( int argc, char **argv) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - printf ("gpgconf-gpgsm.conf:%lu:\"%s\"\n", + printf ("gpgconf-gpgsm.conf:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, config_filename?config_filename:"/dev/null"); printf ("verbose:%lu:\n" "quiet:%lu:\n" - "debug-level:%lu:\"none\":\n" + "debug-level:%lu:\"none:\n" "log-file:%lu:\n", GC_OPT_FLAG_NONE, GC_OPT_FLAG_NONE, -- cgit v1.2.3 From 6c80bd0b49efd56b56eb76f3ccbe8ced27d65e33 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 23 Mar 2004 12:21:29 +0000 Subject: 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpg-agent.c (main): For now, always print the default config file name for --gpgconf-list. --- agent/ChangeLog | 5 +++++ agent/gpg-agent.c | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 484a5ffd7..9ffd8131c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-03-23 Marcus Brinkmann <marcus@g10code.de> + + * gpg-agent.c (main): For now, always print the default config + file name for --gpgconf-list. + 2004-03-17 Werner Koch <wk@gnupg.org> * gpg-agent.c (main) <gpgconf>: Fixed default value quoting. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 2051d9080..010bbc53a 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -587,7 +587,10 @@ main (int argc, char **argv ) } if (gpgconf_list) - { /* List options and default values in the GPG Conf format. */ + { + char *filename; + + /* List options and default values in the GPG Conf format. */ /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING @@ -606,9 +609,10 @@ main (int argc, char **argv ) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + filename = make_filename (opt.homedir, "gpg-agent.conf", NULL ); printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, - config_filename?config_filename:"/dev/null"); + GC_OPT_FLAG_DEFAULT, filename); + xfree (filename); printf ("verbose:%lu:\n" "quiet:%lu:\n" -- cgit v1.2.3 From 3b2e2e7418b0e83ada626c9699def6085c5953e9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 23 Mar 2004 12:21:48 +0000 Subject: 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c: Include <signal.h>. (gc_backend): Add new member runtime_change. (gpg_agent_runtime_change): New function. (gc_component_change_options): New variable runtime. Initialize it. If an option is changed that has the GC_OPT_FLAG_RUNTIME bit set, also set the corresponding runtime variable. Finally, call the runtime_change callback of the backend if needed. --- tools/ChangeLog | 10 +++++++ tools/gpgconf-comp.c | 73 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 9debec445..688a22ef1 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,13 @@ +2004-03-23 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c: Include <signal.h>. + (gc_backend): Add new member runtime_change. + (gpg_agent_runtime_change): New function. + (gc_component_change_options): New variable runtime. Initialize + it. If an option is changed that has the GC_OPT_FLAG_RUNTIME bit + set, also set the corresponding runtime variable. Finally, call + the runtime_change callback of the backend if needed. + 2004-03-16 Werner Koch <wk@gnupg.org> * gpgconf-comp.c (gc_options_gpg_agent): Implemented. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 2839b37cf..b441572cf 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -32,6 +32,7 @@ #include <errno.h> #include <time.h> #include <stdarg.h> +#include <signal.h> /* For log_logv(), asctimestamp(), gnupg_get_time (). */ #define JNLIB_NEED_LOG_LOGV @@ -48,8 +49,6 @@ has been in use for may years and provides the ability to limit the length of the line and thus thwart DoS (not a issue here but at many other places). - - Backend: File backend must be able to write out changes !!! Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. Don't use popen, as this will not tell us if the program had a @@ -93,6 +92,9 @@ gc_error (int status, int errnum, const char *fmt, ...) } +/* Forward declaration. */ +void gpg_agent_runtime_change (void); + /* Backend configuration. Backends are used to decide how the default and current value of an option can be determined, and how the option can be changed. To every option in every component belongs @@ -140,6 +142,9 @@ static struct GPGConf. In this case, PROGRAM is NULL. */ char *program; + /* The runtime change callback. */ + void (*runtime_change) (void); + /* The option name for the configuration filename of this backend. This must be an absolute pathname. It can be an option from a different backend (but then ordering of the options might @@ -151,13 +156,15 @@ static struct const char *option_name; } gc_backend[GC_BACKEND_NR] = { - { NULL, NULL, NULL }, /* GC_BACKEND_ANY dummy entry. */ - { "GnuPG", "gpg", "gpgconf-gpg.conf" }, - { "GPGSM", "gpgsm", "gpgconf-gpgsm.conf" }, - { "GPG Agent", "gpg-agent", "gpgconf-gpg-agent.conf" }, - { "SCDaemon", "scdaemon", "gpgconf-scdaemon.conf" }, - { "DirMngr", "dirmngr", "gpgconf-dirmngr.conf" }, - { "DirMngr LDAP Server List", NULL, "ldapserverlist-file", "LDAP Server" }, + { NULL }, /* GC_BACKEND_ANY dummy entry. */ + { "GnuPG", "gpg", NULL, "gpgconf-gpg.conf" }, + { "GPGSM", "gpgsm", NULL, "gpgconf-gpgsm.conf" }, + { "GPG Agent", "gpg-agent", gpg_agent_runtime_change, + "gpgconf-gpg-agent.conf" }, + { "SCDaemon", "scdaemon", NULL, "gpgconf-scdaemon.conf" }, + { "DirMngr", "dirmngr", NULL, "gpgconf-dirmngr.conf" }, + { "DirMngr LDAP Server List", NULL, NULL, "ldapserverlist-file", + "LDAP Server" }, }; @@ -750,6 +757,40 @@ static struct { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr } }; + +/* Engine specific support. */ +void +gpg_agent_runtime_change (void) +{ + char *agent = getenv ("GPG_AGENT_INFO"); + char *pid_str; + unsigned long pid_long; + char *tail; + pid_t pid; + + if (!agent) + return; + + pid_str = strchr (agent, ':'); + if (!pid_str) + return; + + pid_str++; + errno = 0; + pid_long = strtoul (pid_str, &tail, 0); + if (errno || (*tail != ':' && *tail != '\0')) + return; + + pid = (pid_t) pid_long; + + /* Check for overflow. */ + if (pid_long != (unsigned long) pid) + return; + + /* Ignore any errors here. */ + kill (pid, SIGHUP); +} + /* Robust version of dgettext. */ static const char * @@ -2096,6 +2137,7 @@ void gc_component_change_options (int component, FILE *in) { int err = 0; + int runtime[GC_BACKEND_NR]; char *src_pathname[GC_BACKEND_NR]; char *dest_pathname[GC_BACKEND_NR]; char *orig_pathname[GC_BACKEND_NR]; @@ -2107,6 +2149,7 @@ gc_component_change_options (int component, FILE *in) for (backend = 0; backend < GC_BACKEND_NR; backend++) { + runtime[backend] = 0; src_pathname[backend] = NULL; dest_pathname[backend] = NULL; orig_pathname[backend] = NULL; @@ -2169,6 +2212,9 @@ gc_component_change_options (int component, FILE *in) option_check_validity (option, flags, new_value, &new_value_nr); + if (option->flags & GC_OPT_FLAG_RUNTIME) + runtime[option->backend] = 1; + option->new_flags = flags; if (!(flags & GC_OPT_FLAG_DEFAULT)) { @@ -2286,6 +2332,15 @@ gc_component_change_options (int component, FILE *in) } gc_error (1, saved_errno, "could not commit changes"); } + + /* If it all worked, notify the daemons of the changes. */ + if (opt.runtime) + for (backend = 0; backend < GC_BACKEND_NR; backend++) + { + if (runtime[backend] && gc_backend[backend].runtime_change) + (*gc_backend[backend].runtime_change) (); + } + if (line) free (line); } -- cgit v1.2.3 From 0c36e10633eb9dee9b44a2f773c8242c5cb1ea61 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Mar 2004 12:33:20 +0000 Subject: (main) <gpgconf_list>: Fixed output for pcsc_driver. --- scd/ChangeLog | 7 +++++++ scd/scdaemon.c | 2 +- scd/tlv.c | 17 +++-------------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 9b2ddf79c..895aae966 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,12 @@ +2004-03-23 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main) <gpgconf_list>: Fixed output for pcsc_driver. + 2004-03-17 Werner Koch <wk@gnupg.org> + * tlv.c (parse_ber_header): Do not check for tag overflow - it + does not make sense. Simplified the check for length overflow. + * scdaemon.c (main) <gpgconf>: Fixed default value quoting. 2004-03-16 Werner Koch <wk@gnupg.org> diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 9f1e409e4..955724b3f 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -545,7 +545,7 @@ main (int argc, char **argv ) printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE ); printf ("ctapi-driver:%lu:\n", GC_OPT_FLAG_NONE ); - printf ("pcsc-driver:%lu:\"%s\":\n", + printf ("pcsc-driver:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, DEFAULT_PCSC_DRIVER ); #ifdef HAVE_LIBUSB printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE ); diff --git a/scd/tlv.c b/scd/tlv.c index dbcd24546..5b9d0d6b9 100644 --- a/scd/tlv.c +++ b/scd/tlv.c @@ -157,12 +157,6 @@ parse_ber_header (unsigned char const **buffer, size_t *size, tag = 0; do { - /* Simple check against overflow. We limit our maximim tag - value more than needed but that should not be a problem - because I have nver encountered such large value. We - assume at least 32 bit integers. */ - if (tag > (1 << 24)) - return gpg_error (GPG_ERR_TOO_LARGE); tag <<= 7; if (!length) return gpg_error (GPG_ERR_EOF); @@ -190,16 +184,11 @@ parse_ber_header (unsigned char const **buffer, size_t *size, unsigned long len = 0; int count = c & 0x7f; + if (count > sizeof (len) || count > sizeof (size_t)) + return gpg_error (GPG_ERR_BAD_BER); + for (; count; count--) { - /* Simple check against overflow. We limit our maximim - length more than needed but that should not be a problem - because I have never encountered such large value and - well they are managed in memory and thus we would run - into memory problems anyway. We assume at least 32 bit - integers. */ - if (len > (1 << 24)) - return gpg_error (GPG_ERR_TOO_LARGE); len <<= 8; if (!length) return gpg_error (GPG_ERR_EOF); -- cgit v1.2.3 From fc584a063df98170b54252722b812c26bac4a3e9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 23 Mar 2004 12:33:59 +0000 Subject: 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_flag): Add missing flags. --- tools/ChangeLog | 4 +++- tools/gpgconf-comp.c | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 688a22ef1..1c4b3bdd2 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,12 +1,14 @@ 2004-03-23 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (gc_flag): Add missing flags. + * gpgconf-comp.c: Include <signal.h>. (gc_backend): Add new member runtime_change. (gpg_agent_runtime_change): New function. (gc_component_change_options): New variable runtime. Initialize it. If an option is changed that has the GC_OPT_FLAG_RUNTIME bit set, also set the corresponding runtime variable. Finally, call - the runtime_change callback of the backend if needed. + the runtime_change callback of the backend if needed. 2004-03-16 Werner Koch <wk@gnupg.org> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index b441572cf..8d6e223c9 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -336,7 +336,10 @@ static struct { "group" }, { "optional arg" }, { "list" }, - { "runtime" } + { "runtime" }, + { "default" }, + { "default desc" }, + { "no arg desc" } }; -- cgit v1.2.3 From a40cbf1c331d4e7023b6f1ef089b2f7a62c143a5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Mar 2004 13:03:09 +0000 Subject: * configure.ac: Define SAFE_VERSION_DASH and SAFE_VERSION_DOT> * g10.c: New options --gpgconf-list, --debug-level and --log-file (set_debug): Add arg DEBUG_LEVEL. (main): Look at less and less version specific config files. From gnupg 1.3. --- ChangeLog | 4 ++ configure.ac | 6 ++- g10/ChangeLog | 7 +++ g10/g10.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 133 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e9c72c68..45ad464d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/configure.ac b/configure.ac index 6d6918a9c..44dcbc7aa 100644 --- a/configure.ac +++ b/configure.ac @@ -258,8 +258,12 @@ AH_BOTTOM([ #endif /* This is the same as VERSION, but should be overridden if the - platform cannot handle things like dots '.' in filenames. */ + platform cannot handle things like dots '.' in filenames. Set + SAFE_VERSION_DOT and SAFE_VERSION_DASH to whatever SAFE_VERSION + uses for dots and dashes. */ #define SAFE_VERSION VERSION +#define SAFE_VERSION_DOT '.' +#define SAFE_VERSION_DASH '-' /* For some systems (DOS currently), we hardcode the path here. For POSIX systems the values are constructed by the Makefiles, so that diff --git a/g10/ChangeLog b/g10/ChangeLog index c6715c635..6cb971db5 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,10 @@ +2004-03-23 Werner Koch <wk@gnupg.org> + + * g10.c: New options --gpgconf-list, --debug-level and --log-file + (set_debug): Add arg DEBUG_LEVEL. + (main): Look at less and less version specific config files. From + gnupg 1.3. + 2004-02-17 Werner Koch <wk@gnupg.org> * call-agent.c (start_agent): Ignore an empty GPG_AGENT_INFO. diff --git a/g10/g10.c b/g10/g10.c index e3c621453..968163cce 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1,5 +1,6 @@ /* g10.c - The GnuPG utility (main for gpg) - * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + * Copyright (C) 1998,1999,2000,2001,2002,2003 + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -74,6 +75,7 @@ enum cmd_and_opt_values { aNull = 0, oCompress = 'z', oSetNotation = 'N', oBatch = 500, + aGPGConfList, oSigNotation, oCertNotation, oShowNotation, @@ -153,6 +155,7 @@ enum cmd_and_opt_values { aNull = 0, oNoDefRecipient, oOptions, oDebug, + oDebugLevel, oDebugAll, oStatusFD, #ifdef __riscos__ @@ -260,6 +263,7 @@ enum cmd_and_opt_values { aNull = 0, oEncryptTo, oHiddenEncryptTo, oNoEncryptTo, + oLogFile, oLoggerFD, #ifdef __riscos__ oLoggerFile, @@ -383,6 +387,7 @@ static ARGPARSE_OPTS opts[] = { { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, { aPrimegen, "gen-prime" , 256, "@" }, { aGenRandom, "gen-random" , 256, "@" }, + { aGPGConfList, "gpgconf-list", 256, "@" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -414,6 +419,7 @@ static ARGPARSE_OPTS opts[] = { { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, "@" }, { oNoTTY, "no-tty", 0, "@" }, + { oLogFile, "log-file" ,2, "@" }, { oForceV3Sigs, "force-v3-sigs", 0, "@" }, { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@" }, { oForceV4Certs, "force-v4-certs", 0, "@" }, @@ -445,6 +451,7 @@ static ARGPARSE_OPTS opts[] = { { oOptions, "options" , 2, "@"}, { oDebug, "debug" ,4|16, "@"}, + { oDebugLevel, "debug-level" ,2, "@"}, { oDebugAll, "debug-all" ,0, "@"}, { oStatusFD, "status-fd" ,1, "@" }, #ifdef __riscos__ @@ -835,9 +842,32 @@ add_to_strlist2 ( STRLIST *list, const char *string, int is_utf8) } +/* Setup the debugging. With a LEVEL of NULL only the active debug + flags are propagated to the subsystems. With LEVEL set, a specific + set of debug flags is set; thus overriding all flags already + set. */ static void -set_debug(void) +set_debug (const char *level) { + if (!level) + ; + else if (!strcmp (level, "none")) + opt.debug = 0; + else if (!strcmp (level, "basic")) + opt.debug = DBG_MEMSTAT_VALUE; + else if (!strcmp (level, "advanced")) + opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE; + else if (!strcmp (level, "expert")) + opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE + |DBG_CACHE_VALUE|DBG_FILTER_VALUE|DBG_PACKET_VALUE); + else if (!strcmp (level, "guru")) + opt.debug = ~0; + else + { + log_error (_("invalid debug-level `%s' given\n"), level); + g10_exit (2); + } + if (opt.debug & DBG_MEMORY_VALUE ) memory_debug_mode = 1; if (opt.debug & DBG_MEMSTAT_VALUE ) @@ -1141,14 +1171,17 @@ main( int argc, char **argv ) int detached_sig = 0; FILE *configfp = NULL; char *configname = NULL; + const char *config_filename = NULL; unsigned configlineno; int parse_debug = 0; int default_config = 1; int default_keyring = 1; int greeting = 0; int nogreeting = 0; + char *logfile = NULL; int use_random_seed = 1; enum cmd_and_opt_values cmd = 0; + const char *debug_level = NULL; const char *trustdb_name = NULL; char *def_cipher_string = NULL; char *def_digest_string = NULL; @@ -1294,22 +1327,34 @@ main( int argc, char **argv ) set_native_charset (NULL); /* Try to auto set the character set */ + /* Try for a version specific config file first */ if( default_config ) { - /* Try for a version specific config file first but strip our - usual cvs suffix. That suffix indicates that it is not yet - the given version but we already want this config file. */ - configname = make_filename(opt.homedir, - "gpg" EXTSEP_S "conf-" SAFE_VERSION, NULL ); - if (!strcmp (configname + strlen (configname) - 4, "-cvs")) - configname[strlen (configname)-4] = 0; - - if(access(configname,R_OK)) + char *name = xstrdup ("gpg" EXTSEP_S "conf-" SAFE_VERSION); + char *ver = name + strlen("gpg" EXTSEP_S "conf-"); + + do { - xfree (configname); - configname = make_filename(opt.homedir, - "gpg" EXTSEP_S "conf", NULL ); + if(configname) + { + char *tok; + + xfree (configname); + configname=NULL; + + if((tok=strrchr (ver,SAFE_VERSION_DASH))) + *tok='\0'; + else if((tok=strrchr (ver,SAFE_VERSION_DOT))) + *tok='\0'; + else + break; + } + + configname = make_filename (opt.homedir, name, NULL); } + while ( access(configname,R_OK) ); + xfree(name); + if (!access (configname, R_OK)) { /* Print a warning when both config files are present. */ char *p = make_filename(opt.homedir, "options", NULL ); @@ -1436,6 +1481,10 @@ main( int argc, char **argv ) case aCardStatus: set_cmd (&cmd, aCardStatus); break; case aCardEdit: set_cmd (&cmd, aCardEdit); break; case aChangePIN: set_cmd (&cmd, aChangePIN); break; + case aGPGConfList: + set_cmd (&cmd, aGPGConfList); + nogreeting = 1; + break; case oArmor: opt.armor = 1; opt.no_armor=0; break; case oOutput: opt.outfile = pargs.r.ret_str; break; @@ -1446,6 +1495,8 @@ main( int argc, char **argv ) case oVerbose: g10_opt_verbose++; opt.verbose++; opt.list_sigs=1; break; + case oLogFile: logfile = pargs.r.ret_str; break; + case oBatch: opt.batch = 1; nogreeting = 1; break; case oUseAgent: #ifndef __riscos__ @@ -1467,6 +1518,7 @@ main( int argc, char **argv ) case oShowKeyring: opt.list_options|=LIST_SHOW_KEYRING; break; case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; + case oDebugLevel: debug_level = pargs.r.ret_str; break; case oStatusFD: set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); break; @@ -1962,7 +2014,9 @@ main( int argc, char **argv ) if( configfp ) { fclose( configfp ); configfp = NULL; - xfree (configname); configname = NULL; + config_filename = configname; /* Keep a copy of the config + file name. */ + configname = NULL; goto next_pass; } xfree ( configname ); configname = NULL; @@ -1984,6 +2038,15 @@ main( int argc, char **argv ) } #endif + /* FIXME: We should use the lggging to a file only in server mode; + however we have not yet implemetyed that thus we try to get + away with --batch as indication for logging to file required. */ + if (logfile && opt.batch) + { + log_set_file (logfile); + log_set_prefix (NULL, 1|2|4); + } + if (opt.verbose > 2) log_info ("using character set `%s'\n", get_native_charset ()); @@ -2015,7 +2078,7 @@ main( int argc, char **argv ) tty_batchmode( 1 ); gcry_control (GCRYCTL_RESUME_SECMEM_WARN); - set_debug(); + set_debug (debug_level); /* Do these after the switch(), so they can override settings. */ if(PGP2) @@ -2309,7 +2372,7 @@ main( int argc, char **argv ) avoid adding the secret keyring for a couple of commands to avoid unneeded access in case the secrings are stored on a floppy */ - if( cmd != aDeArmor && cmd != aEnArmor ) + if( cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfList ) { if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys && cmd != aVerify && cmd != aSym) @@ -2344,6 +2407,7 @@ main( int argc, char **argv ) case aCardStatus: case aCardEdit: case aChangePIN: + case aGPGConfList: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; @@ -2869,6 +2933,42 @@ main( int argc, char **argv ) wrong_args ("--change-pin [no]"); break; + case aGPGConfList: + { /* List options and default values in the GPG Conf format. */ + + /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ + /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING + FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ +#define GC_OPT_FLAG_NONE 0UL + /* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + /* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + /* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) + /* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + + printf ("gpgconf-gpg.conf:%lu:\"%s\n", + GC_OPT_FLAG_DEFAULT, + config_filename?config_filename:"/dev/null"); + + printf ("verbose:%lu:\n" + "quiet:%lu:\n" + "debug-level:%lu:\"none:\n" + "log-file:%lu:\n", + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_DEFAULT, + GC_OPT_FLAG_NONE ); + + } + break; + case aListPackets: opt.list_packets=2; default: -- cgit v1.2.3 From d5579da4a3307c3f9e1168ffb9fec4be84989726 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Mar 2004 13:04:34 +0000 Subject: (gc_options_gpg): New. (gc_component_t, gc_component): Add GC_BACKEND_GPG. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 1c4b3bdd2..360efa847 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-03-23 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c (gc_options_gpg): New. + (gc_component_t, gc_component): Add GC_BACKEND_GPG. + 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_flag): Add missing flags. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 8d6e223c9..e3990f9c3 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -543,6 +543,52 @@ static gc_option_t gc_options_scdaemon[] = }; +/* The options of the GC_COMPONENT_GPG component. */ +static gc_option_t gc_options_gpg[] = + { + /* The configuration file to which we write the changes. */ + { "gpgconf-gpg.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG }, + + { "Monitor", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Options controlling the diagnostic output" }, + { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + "gnupg", "verbose", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, + { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "be somewhat more quiet", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, + { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, + NULL, NULL, + GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, + + { "Configuration", + GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, + NULL, "Options controlling the configuration" }, + { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", "|FILE|read options from FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG }, + + { "Debug", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "gnupg", "Options useful for debugging" }, + { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + "gnupg", "|LEVEL|set the debugging level to LEVEL", + GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, + { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "|FILE|write logs to FILE", + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG }, +/* { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */ +/* NULL, NULL, */ +/* GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */ + + + GC_OPTION_NULL + }; + + + /* The options of the GC_COMPONENT_GPGSM component. */ static gc_option_t gc_options_gpgsm[] = { @@ -724,6 +770,9 @@ typedef enum /* The Smardcard Daemon. */ GC_COMPONENT_SCDAEMON, + /* The classic GPG for OpenPGP. */ + GC_COMPONENT_GPG + /* GPG for S/MIME. */ GC_COMPONENT_GPGSM, @@ -756,6 +805,7 @@ static struct { { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon }, + { "gpg", NULL, "GPG for OpenPGP", gc_options_gpg }, { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm }, { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr } }; -- cgit v1.2.3 From 88844c4c41010c75f9d2a5d69bfd9d4970528c13 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Mar 2004 13:11:10 +0000 Subject: add missing comma --- tools/gpgconf-comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e3990f9c3..e449d48f2 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -771,7 +771,7 @@ typedef enum GC_COMPONENT_SCDAEMON, /* The classic GPG for OpenPGP. */ - GC_COMPONENT_GPG + GC_COMPONENT_GPG, /* GPG for S/MIME. */ GC_COMPONENT_GPGSM, -- cgit v1.2.3 From 333d1a107c587892d9e7583e6f2b97f82dc479ee Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Mar 2004 13:48:46 +0000 Subject: Make it work --- g10/g10.c | 1 + tools/gpgconf-comp.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/g10/g10.c b/g10/g10.c index 968163cce..2fbc7e625 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -2965,6 +2965,7 @@ main( int argc, char **argv ) GC_OPT_FLAG_NONE, GC_OPT_FLAG_DEFAULT, GC_OPT_FLAG_NONE ); + printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); } break; diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e449d48f2..fa96a42b7 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -583,6 +583,13 @@ static gc_option_t gc_options_gpg[] = /* NULL, NULL, */ /* GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */ + { "Keyserver", + GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, + NULL, "Configuration for Keyservers" }, + { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", "|URL|use keyserver at URL", + GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, + GC_OPTION_NULL }; @@ -764,15 +771,15 @@ static gc_option_t gc_options_dirmngr[] = update GC_COMPONENT below. */ typedef enum { + /* The classic GPG for OpenPGP. */ + GC_COMPONENT_GPG, + /* The GPG Agent. */ GC_COMPONENT_GPG_AGENT, /* The Smardcard Daemon. */ GC_COMPONENT_SCDAEMON, - /* The classic GPG for OpenPGP. */ - GC_COMPONENT_GPG, - /* GPG for S/MIME. */ GC_COMPONENT_GPGSM, @@ -803,9 +810,9 @@ static struct gc_option_t *options; } gc_component[] = { + { "gpg", NULL, "GPG for OpenPGP", gc_options_gpg }, { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon }, - { "gpg", NULL, "GPG for OpenPGP", gc_options_gpg }, { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm }, { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr } }; -- cgit v1.2.3 From fae48e4f76a30a8330f3896ae527d03420e8ccad Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 23 Mar 2004 15:40:54 +0000 Subject: 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf.c (main): Remove obsolete warning. --- tools/ChangeLog | 4 ++++ tools/gpgconf.c | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 360efa847..44bb2be58 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-03-23 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf.c (main): Remove obsolete warning. + 2004-03-23 Werner Koch <wk@gnupg.org> * gpgconf-comp.c (gc_options_gpg): New. diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 476c57fc1..aab1397c7 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -146,8 +146,6 @@ main (int argc, char **argv) case oDryRun: opt.dry_run = 1; break; case oRuntime: opt.runtime = 1; - /* FIXME */ - fputs ("gpgconf: warning: option --runtime not supported yet\n", stderr); break; case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; -- cgit v1.2.3 From 3b7262e41ebe0ab6e24d0395ec2256246c6e1a4c Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 23 Mar 2004 18:27:37 +0000 Subject: 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_options_dirmngr): Set GC_OPT_FLAG_ARG_OPT for "LDAP Server". (change_options_file): Remove assertion that tests that this flag is not present. Handle an empty string in OPTION->new_value. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 44bb2be58..ed42e5f73 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,10 @@ 2004-03-23 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (gc_options_dirmngr): Set GC_OPT_FLAG_ARG_OPT for + "LDAP Server". + (change_options_file): Remove assertion that tests that this flag + is not present. Handle an empty string in OPTION->new_value. + * gpgconf.c (main): Remove obsolete warning. 2004-03-23 Werner Koch <wk@gnupg.org> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index fa96a42b7..da4cfae92 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -743,7 +743,7 @@ static gc_option_t gc_options_dirmngr[] = /* This entry must come after at least one entry for GC_BACKEND_DIRMNGR in this component, so that the entry for "ldapserverlist-file will be initialized before this one. */ - { "LDAP Server", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, NULL, "LDAP server list", GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST }, @@ -1648,7 +1648,6 @@ change_options_file (gc_component_t component, gc_backend_t backend, assert (option); assert (option->active); assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE); - assert (!(option->flags & GC_OPT_FLAG_ARG_OPT)); /* FIXME. Throughout the function, do better error reporting. */ /* Note that get_config_pathname() calls percent_deescape(), so we @@ -1658,7 +1657,9 @@ change_options_file (gc_component_t component, gc_backend_t backend, orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ()); arg = option->new_value; - if (arg) + if (arg && arg[0] == '\0') + arg = NULL; + else if (arg) { char *end; -- cgit v1.2.3 From 2b1f8df9bdd0535e6c71fb6ed9e32c41364d49b4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Mar 2004 18:43:25 +0000 Subject: Add dirmngr:allow-ocsp --- tools/ChangeLog | 1 + tools/gpgconf-comp.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index ed42e5f73..a9bd5fba5 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -11,6 +11,7 @@ * gpgconf-comp.c (gc_options_gpg): New. (gc_component_t, gc_component): Add GC_BACKEND_GPG. + (gc_options_dirmngr): Add allow-ocsp. 2004-03-23 Marcus Brinkmann <marcus@g10code.de> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index da4cfae92..c010e7cfd 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -757,6 +757,9 @@ static gc_option_t gc_options_dirmngr[] = { "OCSP", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, NULL, "Configuration for OCSP" }, + { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "allow sending OCSP requests", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|use OCSP responder URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, -- cgit v1.2.3 From 496cf5aa7c7f92c8cd3b30f148801d1a4504f6ed Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 24 Mar 2004 14:28:18 +0000 Subject: (gpgsm_sign): Include a short list of capabilities. --- sm/ChangeLog | 4 ++++ sm/sign.c | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/sm/ChangeLog b/sm/ChangeLog index 08793b810..ecf1125c4 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-03-24 Werner Koch <wk@gnupg.org> + + * sign.c (gpgsm_sign): Include a short list of capabilities. + 2004-03-17 Werner Koch <wk@gnupg.org> * gpgsm.c (main) <gpgconf>: Fixed default value quoting. diff --git a/sm/sign.c b/sm/sign.c index 1d3b01cb3..3cc1444b7 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -494,6 +494,25 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, } } + /* We need to write at least a minimal list of our capabilities to + try to convince some MUAs to use 3DEs and not the crippled + RC2. Our list is: + + aes128-CBC + des-EDE3-CBC + */ + err = ksba_cms_add_smime_capability (cms, "2.16.840.1.101.3.4.1.2", NULL, 0); + if (!err) + err = ksba_cms_add_smime_capability (cms, "1.2.840.113549.3.7", NULL, 0); + if (err) + { + log_error ("ksba_cms_add_smime_capability failed: %s\n", + gpg_strerror (err)); + goto leave; + } + + + /* Main building loop. */ do { err = ksba_cms_build (cms, &stopreason); -- cgit v1.2.3 From d3411b3277222805054678ebcafc75456802cf7a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 5 Apr 2004 17:24:27 +0000 Subject: (STATUS_NEWSIG): New. --- common/ChangeLog | 4 ++++ common/errors.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index 6d408ba4f..e82e5b774 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/errors.h b/common/errors.h index 881a2fa51..f34f3ba79 100644 --- a/common/errors.h +++ b/common/errors.h @@ -99,7 +99,8 @@ enum { STATUS_EXPKEYSIG, STATUS_TRUNCATED, - STATUS_ERROR + STATUS_ERROR, + STATUS_NEWSIG }; -- cgit v1.2.3 From da89d93c77f695df5f7c1adf9f83bd8a8080cecf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 5 Apr 2004 17:25:21 +0000 Subject: * verify.c (gpgsm_verify): Print STATUS_NEWSIG for each signature. * certchain.c (gpgsm_validate_chain) <gpgsm_cert_use_cer_p>: Do not just warn if a cert is not suitable; bail out immediately. * call-dirmngr.c (isvalid_status_cb): New. (unhexify_fpr): New. Taken from ../g10/call-agent.c (gpgsm_dirmngr_isvalid): Add new arg CTRL, changed caller to pass it thru. Detect need to check the respondert cert and do that. * certchain.c (gpgsm_validate_chain): Add new arg FLAGS. Changed all callers. --- sm/ChangeLog | 16 ++++++++ sm/call-dirmngr.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- sm/certchain.c | 32 ++++++++++------ sm/certlist.c | 5 ++- sm/gpgsm.h | 6 ++- sm/keylist.c | 4 +- sm/sign.c | 2 +- sm/verify.c | 5 ++- 8 files changed, 159 insertions(+), 22 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index ecf1125c4..c1ca076dd 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,19 @@ +2004-04-05 Werner Koch <wk@gnupg.org> + + * verify.c (gpgsm_verify): Print STATUS_NEWSIG for each signature. + + * certchain.c (gpgsm_validate_chain) <gpgsm_cert_use_cer_p>: Do + not just warn if a cert is not suitable; bail out immediately. + +2004-04-01 Werner Koch <wk@gnupg.org> + + * call-dirmngr.c (isvalid_status_cb): New. + (unhexify_fpr): New. Taken from ../g10/call-agent.c + (gpgsm_dirmngr_isvalid): Add new arg CTRL, changed caller to pass + it thru. Detect need to check the respondert cert and do that. + * certchain.c (gpgsm_validate_chain): Add new arg FLAGS. Changed + all callers. + 2004-03-24 Werner Koch <wk@gnupg.org> * sign.c (gpgsm_sign): Include a short list of capabilities. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 4f07fec24..0e8f67f28 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -33,6 +33,8 @@ #include <assuan.h> #include "i18n.h" +#include "keydb.h" + struct membuf { size_t len; @@ -52,6 +54,12 @@ struct inq_certificate_parm_s { ksba_cert_t issuer_cert; }; +struct isvalid_status_parm_s { + int seen; + unsigned char fpr[20]; +}; + + struct lookup_parm_s { CTRL ctrl; ASSUAN_CONTEXT ctx; @@ -300,6 +308,42 @@ inq_certificate (void *opaque, const char *line) } +/* 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 */ +} + + +static assuan_error_t +isvalid_status_cb (void *opaque, const char *line) +{ + struct isvalid_status_parm_s *parm = opaque; + + if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24) + && (line[24]==' ' || !line[24])) + { + parm->seen++; + if (!line[24] || !unhexify_fpr (line+25, parm->fpr)) + parm->seen++; /* Bumb it to indicate an error. */ + } + return 0; +} + + + /* Call the directory manager to check whether the certificate is valid Returns 0 for valid or usually one of the errors: @@ -312,12 +356,14 @@ inq_certificate (void *opaque, const char *line) request first. */ int -gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) +gpgsm_dirmngr_isvalid (ctrl_t ctrl, + ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) { int rc; char *certid; char line[ASSUAN_LINELENGTH]; struct inq_certificate_parm_s parm; + struct isvalid_status_parm_s stparm; rc = start_dirmngr (); if (rc) @@ -349,6 +395,9 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) parm.cert = cert; parm.issuer_cert = issuer_cert; + stparm.seen = 0; + memset (stparm.fpr, 0, 20); + /* FIXME: If --disable-crl-checks has been set, we should pass an option to dirmngr, so that no fallback CRL check is done after an ocsp check. */ @@ -358,10 +407,66 @@ gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) xfree (certid); rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, - inq_certificate, &parm, NULL, NULL); + inq_certificate, &parm, + isvalid_status_cb, &stparm); if (opt.verbose > 1) log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); - return map_assuan_err (rc); + rc = map_assuan_err (rc); + + if (!rc && stparm.seen) + { + /* Need to also check the certificate validity. */ + if (stparm.seen != 1) + { + log_error ("communication problem with dirmngr detected\n"); + rc = gpg_error (GPG_ERR_INV_CRL); + } + else + { + KEYDB_HANDLE kh; + ksba_cert_t rspcert = NULL; + + /* Fixme: First try to get the certificate from the + dirmngr's cache - it should be there. */ + kh = keydb_new (0); + if (!kh) + rc = gpg_error (GPG_ERR_ENOMEM); + if (!rc) + rc = keydb_search_fpr (kh, stparm.fpr); + if (!rc) + rc = keydb_get_cert (kh, &rspcert); + if (rc) + { + log_error ("unable to find the certificate used " + "by the dirmngr: %s\n", gpg_strerror (rc)); + rc = gpg_error (GPG_ERR_INV_CRL); + } + keydb_release (kh); + + if (!rc) + { + /* fixme: We should refine the check to check for + certificates allowed for CRL/OCPS. */ + rc = gpgsm_cert_use_verify_p (rspcert); + if (rc) + rc = gpg_error (GPG_ERR_INV_CRL); + else + { + /* Note, the flag = 1: This avoids checking this + certificate over and over again. */ + rc = gpgsm_validate_chain (ctrl, rspcert, NULL, 0, NULL, 1); + if (rc) + { + log_error ("invalid certificate used for CRL/OCSP: %s\n", + gpg_strerror (rc)); + rc = gpg_error (GPG_ERR_INV_CRL); + } + } + } + ksba_cert_release (rspcert); + } + } + return rc; } diff --git a/sm/certchain.c b/sm/certchain.c index 5056139df..3bdba2a9d 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -480,7 +480,8 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp, { gpg_error_t err; - err = gpgsm_dirmngr_isvalid (subject_cert, issuer_cert, ctrl->use_ocsp); + err = gpgsm_dirmngr_isvalid (ctrl, + subject_cert, issuer_cert, ctrl->use_ocsp); if (err) { /* Fixme: We should change the wording because we may @@ -522,10 +523,13 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp, /* Validate a chain and optionally return the nearest expiration time in R_EXPTIME. With LISTMODE set to 1 a special listmode is activated where only information about the certificate is printed - to FP and no outputis send to the usual log stream. */ + to FP and no output is send to the usual log stream. + + Defined flag bits: 0 - do not do any dirmngr isvalid checks. +*/ int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, - int listmode, FILE *fp) + int listmode, FILE *fp, unsigned int flags) { int rc = 0, depth = 0, maxdepth; char *issuer = NULL; @@ -698,10 +702,13 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, } /* Check for revocations etc. */ - rc = is_cert_still_valid (ctrl, lm, fp, - subject_cert, subject_cert, - &any_revoked, &any_no_crl, - &any_crl_too_old); + if ((flags & 1)) + rc = 0; + else + rc = is_cert_still_valid (ctrl, lm, fp, + subject_cert, subject_cert, + &any_revoked, &any_no_crl, + &any_crl_too_old); if (rc) goto leave; @@ -818,14 +825,17 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, sprintf (numbuf, "%d", rc); gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage", numbuf, NULL); - rc = 0; + goto leave; } } /* Check for revocations etc. */ - rc = is_cert_still_valid (ctrl, lm, fp, - subject_cert, issuer_cert, - &any_revoked, &any_no_crl, &any_crl_too_old); + if ((flags & 1)) + rc = 0; + else + rc = is_cert_still_valid (ctrl, lm, fp, + subject_cert, issuer_cert, + &any_revoked, &any_no_crl, &any_crl_too_old); if (rc) goto leave; diff --git a/sm/certlist.c b/sm/certlist.c index 6e694b781..0394a584f 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -130,7 +130,8 @@ cert_usage_p (ksba_cert_t cert, int mode) { if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN))) return 0; - log_info ( _("certificate should have not been used certification\n")); + log_info (_("certificate should have not " + "been used for certification\n")); return gpg_error (GPG_ERR_WRONG_KEY_USAGE); } @@ -347,7 +348,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, } } if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL); + rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0); if (!rc) { CERTLIST cl = xtrycalloc (1, sizeof *cl); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 62bc05354..93487f002 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -222,7 +222,8 @@ int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next); int gpgsm_is_root_cert (ksba_cert_t cert); int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, - int listmode, FILE *listfp); + int listmode, FILE *listfp, + unsigned int flags); int gpgsm_basic_cert_check (ksba_cert_t cert); /*-- certlist.c --*/ @@ -288,7 +289,8 @@ int gpgsm_agent_learn (void); int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc); /*-- call-dirmngr.c --*/ -int gpgsm_dirmngr_isvalid (ksba_cert_t cert, ksba_cert_t issuer_cert, +int gpgsm_dirmngr_isvalid (ctrl_t ctrl, + ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp); int gpgsm_dirmngr_lookup (ctrl_t ctrl, STRLIST names, void (*cb)(void*, ksba_cert_t), void *cb_value); diff --git a/sm/keylist.c b/sm/keylist.c index 80cc675db..4e6f28db8 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -182,7 +182,7 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, gpg_error_t valerr; if (ctrl->with_validation) - valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL); + valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0); else valerr = 0; @@ -483,7 +483,7 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, if (with_validation) { - err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp); + err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0); if (!err) fprintf (fp, " [certificate is good]\n"); else diff --git a/sm/sign.c b/sm/sign.c index 3cc1444b7..473cf93a2 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -378,7 +378,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, valid. */ rc = gpgsm_cert_use_sign_p (cert); if (!rc) - rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL); + rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0); if (rc) goto leave; diff --git a/sm/verify.c b/sm/verify.c index bd334908e..4b43ed064 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -263,6 +263,9 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) err = 0; break; } + + gpgsm_status (ctrl, STATUS_NEWSIG, NULL); + if (DBG_X509) { log_debug ("signer %d - issuer: `%s'\n", @@ -458,7 +461,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) if (DBG_X509) log_debug ("signature okay - checking certs\n"); - rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL); + rc = gpgsm_validate_chain (ctrl, cert, keyexptime, 0, NULL, 0); if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) { gpgsm_status (ctrl, STATUS_EXPKEYSIG, NULL); -- cgit v1.2.3 From 51e2ffaa0ade03e5278fbf9c8d62050083528b12 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 5 Apr 2004 17:25:43 +0000 Subject: Typo fix --- tools/gpgconf-comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index c010e7cfd..fa755afe0 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -470,7 +470,7 @@ static gc_option_t gc_options_gpg_agent[] = "gnupg", "do not use the PIN cache when signing", GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "no-grab", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, - "gnupg", "do not grab keybourd and mouse", + "gnupg", "do not grab keyboard and mouse", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, -- cgit v1.2.3 From 8c03a61f945f9791d8e7e959e56145c3f24046ff Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Apr 2004 07:36:25 +0000 Subject: Require libgcrypt 1.1.94. --- ChangeLog | 6 +++++- NEWS | 2 ++ configure.ac | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45ad464d1..8686c54ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ +2004-04-06 Werner Koch <wk@gnupg.org> + + * configure.ac: Require libgcrypt 1.1.94. + 2004-03-23 Werner Koch <wk@gnupg.org> - * configure.ac: Define SAFE_VERSION_DASH and SAFE_VERSION_DOT> + * configure.ac: Define SAFE_VERSION_DASH and SAFE_VERSION_DOT. 2004-03-09 Werner Koch <wk@gnupg.org> diff --git a/NEWS b/NEWS index 85d931fa1..b118f9c8b 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ Noteworthy changes in version 1.9.7 * Added support for DINSIG card applications. + * Include the smimeCapabilities attribute with signed messages. + Noteworthy changes in version 1.9.6 (2004-03-06) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 44dcbc7aa..bd64976be 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ development_version=yes NEED_GPG_ERROR_VERSION=0.7 NEED_LIBGCRYPT_API=1 -NEED_LIBGCRYPT_VERSION=1.1.93 +NEED_LIBGCRYPT_VERSION=1.1.94 NEED_LIBASSUAN_VERSION=0.6.4 -- cgit v1.2.3 From cd3e11add8e963111bd5b92de91ce6006d00a6e0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Apr 2004 07:36:44 +0000 Subject: (main): Use new libgcrypt thread library register scheme. --- agent/ChangeLog | 5 +++++ agent/gpg-agent.c | 27 ++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 9ffd8131c..b20ee42e0 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-04-06 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): Use new libgcrypt thread library register + scheme. + 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpg-agent.c (main): For now, always print the default config diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 010bbc53a..dd35bfcdf 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -159,7 +159,11 @@ static const char *debug_level; static void create_directories (void); #ifdef USE_GNU_PTH static void handle_connections (int listen_fd); -#endif + +/* Pth wrapper function definitions. */ +GCRY_THREAD_OPTION_PTH_IMPL; + +#endif /*USE_GNU_PTH*/ @@ -378,6 +382,7 @@ main (int argc, char **argv ) int debug_wait = 0; int disable_pth = 0; int gpgconf_list = 0; + gpg_error_t err; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -391,20 +396,19 @@ main (int argc, char **argv ) i18n_init (); - /* We need to initialize Pth before libgcrypt, because the libgcrypt - initialization done by gcry_check_version internally sets up its - mutex system. Note that one must not link against pth if - USE_GNU_PTH is not defined. */ + /* Libgcrypt requires us to register the threading model first. + Note that this will also do the pth_init. */ #ifdef USE_GNU_PTH - if (!pth_init ()) + err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + if (err) { - log_error ("failed to initialize the Pth library\n"); - exit (1); + log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", + gpg_strerror (err)); } #endif /*USE_GNU_PTH*/ - /* check that the libraries are suitable. Do it here because - the option parsing may need services of the library */ + /* Check that the libraries are suitable. Do it here because + the option parsing may need services of the library. */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) { log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), @@ -533,7 +537,8 @@ main (int argc, char **argv ) case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break; case oTTYtype: default_ttytype = xstrdup (pargs.r.ret_str); break; case oLCctype: default_lc_ctype = xstrdup (pargs.r.ret_str); break; - case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break; + case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); + break; case oKeepTTY: opt.keep_tty = 1; break; case oKeepDISPLAY: opt.keep_display = 1; break; -- cgit v1.2.3 From c58c97e61f9571579980eca93f5601ba80ea4007 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Apr 2004 07:37:52 +0000 Subject: Add STATUS_NEWSIG --- sm/ChangeLog | 1 + sm/server.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sm/ChangeLog b/sm/ChangeLog index c1ca076dd..25f72915f 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,6 @@ 2004-04-05 Werner Koch <wk@gnupg.org> + * server.c (get_status_string): Add STATUS_NEWSIG. * verify.c (gpgsm_verify): Print STATUS_NEWSIG for each signature. * certchain.c (gpgsm_validate_chain) <gpgsm_cert_use_cer_p>: Do diff --git a/sm/server.c b/sm/server.c index a132f9f2b..e73efe418 100644 --- a/sm/server.c +++ b/sm/server.c @@ -867,6 +867,7 @@ get_status_string ( int no ) case STATUS_ENTER : s = "ENTER"; break; case STATUS_LEAVE : s = "LEAVE"; break; case STATUS_ABORT : s = "ABORT"; break; + case STATUS_NEWSIG : s = "NEWSIG"; break; case STATUS_GOODSIG: s = "GOODSIG"; break; case STATUS_SIGEXPIRED: s = "SIGEXPIRED"; break; case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; -- cgit v1.2.3 From d84d632583c1c61180d40ce9b91f185160ab02d6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Apr 2004 10:01:04 +0000 Subject: * configure.ac: Require libgcrypt 1.1.94. Introduce PACKAGE_GT and set it to gnupg2. * gpg-agent.c (main): Use new libgcrypt thread library register scheme. * Makevars (DOMAIN): Init from PACKAGE_GT --- ChangeLog | 3 +- NEWS | 3 + agent/gpg-agent.c | 8 +- agent/protect-tool.c | 6 +- configure.ac | 6 +- g10/g10.c | 6 +- g10/gpgv.c | 6 +- g10/passphrase.c | 12 +- kbx/kbxutil.c | 16 +- po/ChangeLog | 4 + po/LINGUAS | 19 +- po/LINUGAS | 4 - po/Makevars | 2 +- po/POTFILES.in | 3 + po/de.po | 878 +++++++++++++++++++++++++++++++-------------------- scd/scdaemon.c | 6 +- sm/certdump.c | 6 +- sm/gpgsm.c | 20 +- sm/import.c | 2 +- tools/gpgconf.c | 6 +- 20 files changed, 609 insertions(+), 407 deletions(-) delete mode 100644 po/LINUGAS diff --git a/ChangeLog b/ChangeLog index 8686c54ea..11c4093a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ 2004-04-06 Werner Koch <wk@gnupg.org> * configure.ac: Require libgcrypt 1.1.94. + Introduce PACKAGE_GT and set it to gnupg2. 2004-03-23 Werner Koch <wk@gnupg.org> @@ -414,7 +415,7 @@ * configure.ac (HAVE_JNLIB_LOGGING): always define it. - Copyright 2001, 2002 Free Software Foundation, Inc. + 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 diff --git a/NEWS b/NEWS index b118f9c8b..a4c909fa3 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ Noteworthy changes in version 1.9.7 * 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) ------------------------------------------------ diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index dd35bfcdf..0fc1bb8bf 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -197,12 +197,12 @@ static void i18n_init (void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); #endif #endif } @@ -649,7 +649,7 @@ main (int argc, char **argv ) easier to switch only once instead of for every message and it actually helps when more then one thread is active (avoids an extra copy step). */ - bind_textdomain_codeset (PACKAGE, "UTF-8"); + bind_textdomain_codeset (PACKAGE_GT, "UTF-8"); #endif /* now start with logging to a file if this is desired */ diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 1bc7144be..c62c649ad 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -141,12 +141,12 @@ static void i18n_init (void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); #endif #endif } diff --git a/configure.ac b/configure.ac index bd64976be..8c167f9e2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac - for GnuPG 1.9 # Copyright (C) 1998, 1999, 2000, 2001, 2002, -# 2003 Free Software Foundation, Inc. +# 2003, 2004 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -43,6 +43,7 @@ NEED_OPENSC_VERSION=0.8.0 PACKAGE=$PACKAGE_NAME +PACKAGE_GT=${PACKAGE_NAME}2 VERSION=$PACKAGE_VERSION AC_CONFIG_AUX_DIR(scripts) @@ -68,8 +69,11 @@ GNUPG_BUILD_PROGRAM(scdaemon, yes) AC_SUBST(PACKAGE) +AC_SUBST(PACKAGE_GT) AC_SUBST(VERSION) AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) +AC_DEFINE_UNQUOTED(PACKAGE_GT, "$PACKAGE_GT", + [Name of this package for gettext]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT, "$PACKAGE_BUGREPORT", [Bug report address]) diff --git a/g10/g10.c b/g10/g10.c index 2fbc7e625..006e88ad2 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -783,12 +783,12 @@ static void i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS setlocale( LC_ALL, "" ); - bindtextdomain( PACKAGE, LOCALEDIR ); - textdomain( PACKAGE ); + bindtextdomain( PACKAGE_GT, LOCALEDIR ); + textdomain( PACKAGE_GT ); #endif #endif } diff --git a/g10/gpgv.c b/g10/gpgv.c index d020bda62..9bd954c6f 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -116,7 +116,7 @@ static void i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS #ifdef HAVE_LC_MESSAGES @@ -125,8 +125,8 @@ i18n_init(void) #else setlocale( LC_ALL, "" ); #endif - bindtextdomain( PACKAGE, LOCALEDIR ); - textdomain( PACKAGE ); + bindtextdomain( PACKAGE_GT, LOCALEDIR ); + textdomain( PACKAGE_GT ); #endif #endif } diff --git a/g10/passphrase.c b/g10/passphrase.c index 27ffcad97..986070a16 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -649,8 +649,8 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, } #ifdef ENABLE_NLS - /* The Assuan agent protol requires us to trasnmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE, NULL); + /* The Assuan agent protocol requires us to transmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); #ifdef HAVE_LANGINFO_CODESET if (!orig_codeset) orig_codeset = nl_langinfo (CODESET); @@ -658,7 +658,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, if (orig_codeset) { /* We only switch when we are able to restore the codeset later. */ orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE, "utf-8")) + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) orig_codeset = NULL; } #endif @@ -765,7 +765,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, free_public_key( pk ); #ifdef ENABLE_NLS if (orig_codeset) - bind_textdomain_codeset (PACKAGE, orig_codeset); + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); #endif xfree (orig_codeset); return pw; @@ -857,7 +857,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, free_public_key( pk ); #ifdef ENABLE_NLS if (orig_codeset) - bind_textdomain_codeset (PACKAGE, orig_codeset); + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); #endif xfree (orig_codeset); return pw; @@ -880,7 +880,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, failure: #ifdef ENABLE_NLS if (orig_codeset) - bind_textdomain_codeset (PACKAGE, orig_codeset); + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); #endif xfree (atext); if ( fd != -1 ) diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index abca4faa9..76678619c 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -117,20 +117,20 @@ my_strusage( int level ) static void i18n_init(void) { - #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); - #else - #ifdef ENABLE_NLS +#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, LOCALEDIR ); - textdomain( PACKAGE ); - #endif - #endif + bindtextdomain( PACKAGE_GT, LOCALEDIR ); + textdomain( PACKAGE_GT ); +#endif +#endif } diff --git a/po/ChangeLog b/po/ChangeLog index 682f086f3..97e68c730 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2004-04-06 Werner Koch <wk@gnupg.org> + + * Makevars (DOMAIN): Init from PACKAGE_GT + 2003-12-09 Werner Koch <wk@gnupg.org> * Makevars (MSGID_BUGS_ADDRESS): New. diff --git a/po/LINGUAS b/po/LINGUAS index b418cf26d..2d1cafec8 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1,18 +1,5 @@ # Set of available languages. -# we have disabled most of them for now. -en@quot en@boldquot -#ca cs -#da de -#eo el es et -#fi fr -#gl -#hu -#id it -#ja -#nl -#pl -#pt_BR pt -#sk sv -#tr -#zh_TW" + + + diff --git a/po/LINUGAS b/po/LINUGAS deleted file mode 100644 index eaa0fea22..000000000 --- a/po/LINUGAS +++ /dev/null @@ -1,4 +0,0 @@ -# Set of available languages. -de - - diff --git a/po/Makevars b/po/Makevars index 20a50fc7d..b99cd466c 100644 --- a/po/Makevars +++ b/po/Makevars @@ -1,7 +1,7 @@ # Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. -DOMAIN = $(PACKAGE) +DOMAIN = gnupg2 # These two variables depend on the location of this directory. subdir = po diff --git a/po/POTFILES.in b/po/POTFILES.in index 3bf6300b5..ae54716ac 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -31,3 +31,6 @@ sm/keydb.c sm/keylist.c sm/sign.c sm/verify.c + +tools/gpgconf.c +tools/gpgconf-comp.c diff --git a/po/de.po b/po/de.po index a7febc6c3..dafe41232 100644 --- a/po/de.po +++ b/po/de.po @@ -1,19 +1,24 @@ -# German translationn for NewPG which will soon be merged with GnuPG. -# Copyright (C) 2002 Free Software Foundation, Inc. +# German translation for GnuPG 1.9.x +# Copyright (C) 2002, 2004 Free Software Foundation, Inc. # Werner Koch <wk@gnupg.org>, 2002. # +# +# Note that we use "gnupg2" as the domain to avoid conflicts with +# already installed domains "gnupg" from GnuPG < 1.9. +# msgid "" msgstr "" -"Project-Id-Version: NewPG 0.9.3\n" -"POT-Creation-Date: 2003-04-29 12:08+0200\n" -"PO-Revision-Date: 2002-08-21 13:13+0200\n" +"Project-Id-Version: gnupg2 1.9.7\n" +"Report-Msgid-Bugs-To: translations@gnupg.org\n" +"POT-Creation-Date: 2004-04-06 12:06+0200\n" +"PO-Revision-Date: 2004-04-06 11:47+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:92 agent/protect-tool.c:85 scd/scdaemon.c:78 +#: agent/gpg-agent.c:94 agent/protect-tool.c:92 scd/scdaemon.c:89 msgid "" "@Options:\n" " " @@ -21,81 +26,74 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:94 scd/scdaemon.c:80 +#: agent/gpg-agent.c:96 scd/scdaemon.c:91 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:95 scd/scdaemon.c:81 +#: agent/gpg-agent.c:97 scd/scdaemon.c:92 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:96 kbx/kbxutil.c:72 scd/scdaemon.c:82 sm/gpgsm.c:287 +#: agent/gpg-agent.c:98 kbx/kbxutil.c:73 scd/scdaemon.c:93 sm/gpgsm.c:301 +#: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:97 kbx/kbxutil.c:73 scd/scdaemon.c:83 sm/gpgsm.c:288 +#: agent/gpg-agent.c:99 kbx/kbxutil.c:74 scd/scdaemon.c:94 sm/gpgsm.c:302 msgid "be somewhat more quiet" msgstr "etwas weniger Aussageb erzeugen" -#: agent/gpg-agent.c:98 scd/scdaemon.c:84 +#: agent/gpg-agent.c:100 scd/scdaemon.c:95 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:99 scd/scdaemon.c:85 +#: agent/gpg-agent.c:101 scd/scdaemon.c:96 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" -#: agent/gpg-agent.c:100 scd/scdaemon.c:86 sm/gpgsm.c:307 -msgid "read options from file" -msgstr "Konfigurationsoptionen aus Datei lesen" - -#: agent/gpg-agent.c:101 kbx/kbxutil.c:76 scd/scdaemon.c:87 -msgid "set debugging flags" -msgstr "Debug Flags setzen" - -#: agent/gpg-agent.c:102 kbx/kbxutil.c:77 scd/scdaemon.c:88 -msgid "enable full debugging" -msgstr "Alle Debug Flags setzen" +#: agent/gpg-agent.c:102 +msgid "|FILE|read options from FILE" +msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:104 scd/scdaemon.c:91 +#: agent/gpg-agent.c:107 scd/scdaemon.c:103 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:105 +#: agent/gpg-agent.c:108 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:106 scd/scdaemon.c:92 sm/gpgsm.c:290 +#: agent/gpg-agent.c:109 scd/scdaemon.c:104 sm/gpgsm.c:304 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:107 +#: agent/gpg-agent.c:110 msgid "do not allow multiple connections" msgstr "Nicht mehr als eine Verbindung erlauben" -#: agent/gpg-agent.c:121 +#: agent/gpg-agent.c:124 msgid "ignore requests to change the TTY" -msgstr "" +msgstr "Ignoriere Anfragen, das TTY zu wechseln" -#: agent/gpg-agent.c:123 +#: agent/gpg-agent.c:126 msgid "ignore requests to change the X display" -msgstr "" +msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:169 agent/protect-tool.c:113 scd/scdaemon.c:117 -#: sm/gpgsm.c:447 +#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:150 +#: sm/gpgsm.c:468 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:169 agent/protect-tool.c:113 scd/scdaemon.c:117 -#: sm/gpgsm.c:447 +#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:150 +#: sm/gpgsm.c:468 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:172 +#: agent/gpg-agent.c:183 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: agent/gpg-agent.c:174 +#: agent/gpg-agent.c:185 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -103,50 +101,55 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:343 agent/protect-tool.c:822 kbx/kbxutil.c:229 -#: scd/scdaemon.c:245 sm/gpgsm.c:628 +#: agent/gpg-agent.c:256 scd/scdaemon.c:224 sm/gpgsm.c:591 +#, c-format +msgid "invalid debug-level `%s' given\n" +msgstr "ungltige Debugebene `%s' angegeben\n" + +#: agent/gpg-agent.c:414 agent/protect-tool.c:1035 kbx/kbxutil.c:230 +#: scd/scdaemon.c:325 sm/gpgsm.c:714 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:414 scd/scdaemon.c:316 sm/gpgsm.c:722 +#: agent/gpg-agent.c:487 scd/scdaemon.c:405 sm/gpgsm.c:812 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:419 agent/gpg-agent.c:829 scd/scdaemon.c:321 -#: sm/gpgsm.c:726 +#: agent/gpg-agent.c:492 agent/gpg-agent.c:947 scd/scdaemon.c:410 +#: sm/gpgsm.c:816 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:427 scd/scdaemon.c:329 sm/gpgsm.c:733 +#: agent/gpg-agent.c:500 scd/scdaemon.c:418 sm/gpgsm.c:823 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:519 scd/scdaemon.c:424 +#: agent/gpg-agent.c:641 scd/scdaemon.c:576 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" -#: agent/gpg-agent.c:861 agent/gpg-agent.c:895 +#: agent/gpg-agent.c:980 agent/gpg-agent.c:1014 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: agent/gpg-agent.c:864 agent/gpg-agent.c:900 +#: agent/gpg-agent.c:983 agent/gpg-agent.c:1019 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/protect-tool.c:116 +#: agent/protect-tool.c:127 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" -#: agent/protect-tool.c:118 +#: agent/protect-tool.c:129 msgid "" "Syntax: gpg-protect-tool [options] [args]]\n" "Secret key maintenance tool\n" @@ -154,11 +157,7 @@ msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" "Werkzeug zum Bearbeiten von geheimen Schlsseln\n" -#: agent/protect-tool.c:902 -msgid "Enter passphrase:" -msgstr "Bitte das Mantra (Passphrase) eingeben:" - -#: agent/protect-tool.c:903 +#: agent/protect-tool.c:1142 msgid "" "Please enter the passphrase or the PIN\n" "needed to complete this operation." @@ -166,64 +165,34 @@ msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" "wird bentigt um diese Aktion auszufhren." -#: agent/simple-pwquery.c:272 -msgid "gpg-agent is not available in this session\n" -msgstr "Der gpg-agent ist nicht verfgbar\n" - -#: agent/simple-pwquery.c:281 sm/call-agent.c:195 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" - -#: agent/simple-pwquery.c:293 sm/call-agent.c:207 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" +#: agent/protect-tool.c:1145 +msgid "Passphrase:" +msgstr "Passphrase:" -#: agent/simple-pwquery.c:315 -#, c-format -msgid "can't connect to `%s': %s\n" -msgstr "Verbindung zu `%s' kann nicht aufgebaut werden: %s\n" - -#: agent/simple-pwquery.c:326 -msgid "communication problem with gpg-agent\n" -msgstr "Kommunikationsproblem mit gpg-agent\n" - -#: agent/simple-pwquery.c:336 -msgid "problem setting the gpg-agent options\n" -msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" - -#: agent/simple-pwquery.c:466 -msgid "canceled by user\n" -msgstr "Vom Benutzer abgebrochen\n" - -#: agent/simple-pwquery.c:473 -msgid "problem with the agent\n" -msgstr "Problem mit dem Agenten\n" - -#: agent/divert-scd.c:192 +#: agent/divert-scd.c:200 #, c-format msgid "Please enter the PIN%s%s%s to unlock the card" msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" -#: agent/genkey.c:82 -msgid "does not match - try again" -msgstr "Keine bereinstimmung - bitte nochmal versuchen" - -#: agent/genkey.c:109 +#: agent/genkey.c:108 #, c-format msgid "Please enter the passphrase to%0Ato protect your new key" msgstr "" "Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlssel zu schtzen" -#: agent/genkey.c:111 agent/genkey.c:212 +#: agent/genkey.c:110 agent/genkey.c:224 msgid "Please re-enter this passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" -#: agent/genkey.c:211 +#: agent/genkey.c:131 agent/genkey.c:244 +msgid "does not match - try again" +msgstr "Keine bereinstimmung - bitte nochmal versuchen" + +#: agent/genkey.c:223 msgid "Please enter the new passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: agent/query.c:255 +#: agent/query.c:268 msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" @@ -231,7 +200,7 @@ msgstr "" "Bitte geben Sie Ihre PIN ein, so da der geheime Schlssel benutzt werden " "kann" -#: agent/query.c:258 +#: agent/query.c:271 msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" @@ -239,31 +208,31 @@ msgstr "" "Bitte geben Sie Ihr Mantra (Passphrase) ein, so da der geheime Schlssel " "benutzt werden kann" -#: agent/query.c:301 agent/query.c:313 +#: agent/query.c:326 agent/query.c:338 msgid "PIN too long" msgstr "Die PIN ist zu lang" -#: agent/query.c:302 +#: agent/query.c:327 msgid "Passphrase too long" msgstr "Das Matra (Passphrase) ist zu lang" -#: agent/query.c:310 +#: agent/query.c:335 msgid "Invalid characters in PIN" msgstr "Ungltige Zeichen in der PIN" -#: agent/query.c:315 +#: agent/query.c:340 msgid "PIN too short" msgstr "Die PIN ist zu kurz" -#: agent/query.c:326 +#: agent/query.c:352 msgid "Bad PIN" msgstr "Falsche PIN" -#: agent/query.c:327 +#: agent/query.c:353 msgid "Bad Passphrase" msgstr "Falsches Mantra (Passphrase)" -#: agent/query.c:366 +#: agent/query.c:392 msgid "Passphrase" msgstr "Mantra" @@ -274,22 +243,56 @@ msgstr "" "Das Erstellen eines Speicherabzugs (core-dump) kann nicht verhindert werden: " "%s\n" -#: common/sysutils.c:158 +#: common/sysutils.c:159 #, c-format msgid "Warning: unsafe ownership on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Besitzrechte fr %s \"%s\"\n" -#: common/sysutils.c:190 +#: common/sysutils.c:191 #, c-format msgid "Warning: unsafe permissions on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" -#: jnlib/logging.c:343 +#: common/simple-pwquery.c:272 +msgid "gpg-agent is not available in this session\n" +msgstr "Der gpg-agent ist nicht verfgbar\n" + +#: common/simple-pwquery.c:286 sm/call-agent.c:126 +msgid "malformed GPG_AGENT_INFO environment variable\n" +msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" + +#: common/simple-pwquery.c:298 sm/call-agent.c:138 +#, c-format +msgid "gpg-agent protocol version %d is not supported\n" +msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" + +#: common/simple-pwquery.c:320 +#, c-format +msgid "can't connect to `%s': %s\n" +msgstr "Verbindung zu `%s' kann nicht aufgebaut werden: %s\n" + +#: common/simple-pwquery.c:331 +msgid "communication problem with gpg-agent\n" +msgstr "Kommunikationsproblem mit gpg-agent\n" + +#: common/simple-pwquery.c:341 +msgid "problem setting the gpg-agent options\n" +msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" + +#: common/simple-pwquery.c:471 +msgid "canceled by user\n" +msgstr "Vom Benutzer abgebrochen\n" + +#: common/simple-pwquery.c:478 +msgid "problem with the agent\n" +msgstr "Problem mit dem Agenten\n" + +#: jnlib/logging.c:516 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:61 sm/gpgsm.c:208 +#: kbx/kbxutil.c:62 sm/gpgsm.c:218 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -297,7 +300,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:67 sm/gpgsm.c:237 +#: kbx/kbxutil.c:68 sm/gpgsm.c:248 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -307,31 +310,39 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:69 sm/gpgsm.c:239 +#: kbx/kbxutil.c:70 sm/gpgsm.c:250 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: kbx/kbxutil.c:71 sm/gpgsm.c:286 +#: kbx/kbxutil.c:72 sm/gpgsm.c:300 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: kbx/kbxutil.c:74 sm/gpgsm.c:295 +#: kbx/kbxutil.c:75 sm/gpgsm.c:309 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" -#: kbx/kbxutil.c:98 +#: kbx/kbxutil.c:77 +msgid "set debugging flags" +msgstr "Debug Flags setzen" + +#: kbx/kbxutil.c:78 +msgid "enable full debugging" +msgstr "Alle Debug Flags setzen" + +#: kbx/kbxutil.c:99 msgid "Please report bugs to " msgstr "Bite richten sie Berichte ber Bugs (Softwarefehler) an " -#: kbx/kbxutil.c:98 +#: kbx/kbxutil.c:99 msgid ".\n" msgstr ".\n" -#: kbx/kbxutil.c:102 +#: kbx/kbxutil.c:103 msgid "Usage: kbxutil [options] [files] (-h for help)" msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h fr Hilfe)" -#: kbx/kbxutil.c:105 +#: kbx/kbxutil.c:106 msgid "" "Syntax: kbxutil [options] [files]\n" "list, export, import Keybox data\n" @@ -339,15 +350,43 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:90 +#: scd/scdaemon.c:97 sm/gpgsm.c:321 +msgid "read options from file" +msgstr "Konfigurationsoptionen aus Datei lesen" + +#: scd/scdaemon.c:102 msgid "|N|set OpenSC debug level to N" msgstr "|N|Den OpenSC Debugstufe auf N setzen" -#: scd/scdaemon.c:120 +#: scd/scdaemon.c:105 +msgid "|N|connect to reader at port N" +msgstr "|N|Verbinde mit dem Leser auf Port N" + +#: scd/scdaemon.c:106 +msgid "|NAME|use NAME as ct-API driver" +msgstr "|NAME|Benutze NAME als CT-API Treiber" + +#: scd/scdaemon.c:107 +msgid "|NAME|use NAME as PC/SC driver" +msgstr "|NAME|Benutze NAME als PC/SC Treiber" + +#: scd/scdaemon.c:110 +msgid "do not use the internal CCID driver" +msgstr "Den internen CCID Treiber nicht benutzen" + +#: scd/scdaemon.c:117 +msgid "do not use the OpenSC layer" +msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" + +#: scd/scdaemon.c:122 +msgid "allow the use of admin card commands" +msgstr "Erlaube die Benuztung von \"Admin\" Kommandos" + +#: scd/scdaemon.c:153 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" -#: scd/scdaemon.c:122 +#: scd/scdaemon.c:155 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" @@ -355,194 +394,236 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon fr GnuPG\n" -#: sm/base64.c:295 +#: sm/base64.c:315 #, c-format msgid "invalid radix64 character %02x skipped\n" msgstr "Ungltiges Basis-64 Zeichen %02X wurde bergangen\n" -#: sm/call-agent.c:158 +#: sm/call-agent.c:88 msgid "no running gpg-agent - starting one\n" msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" -#: sm/call-agent.c:218 +#: sm/call-agent.c:149 msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" -#: sm/call-dirmngr.c:153 +#: sm/call-dirmngr.c:162 msgid "no running dirmngr - starting one\n" msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" -#: sm/call-dirmngr.c:190 +#: sm/call-dirmngr.c:200 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" -#: sm/call-dirmngr.c:202 +#: sm/call-dirmngr.c:212 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "Die Dirmngr Protokollversion %d wird nicht untersttzt\n" -#: sm/call-dirmngr.c:213 +#: sm/call-dirmngr.c:223 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " "versucht\n" -#: sm/certdump.c:51 sm/certdump.c:99 +#: sm/certdump.c:59 sm/certdump.c:142 msgid "none" msgstr "keine" -#: sm/certdump.c:119 +#: sm/certdump.c:151 msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:121 -msgid "[error]" -msgstr "[Fehler]" - -#: sm/certdump.c:424 +#: sm/certdump.c:489 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:433 +#: sm/certdump.c:498 msgid "[Error - unknown encoding]" msgstr "[Fehler - Unbekannte Kodierung]" -#: sm/certdump.c:437 +#: sm/certdump.c:502 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungltige Kodierung]" -#: sm/certdump.c:442 +#: sm/certdump.c:507 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungltiger DN]" -#: sm/certlist.c:52 -msgid "no key usage specified - accepted for encryption\n" +#: sm/certdump.c:651 +#, c-format +msgid "" +"Please enter the passphrase to unlock the secret key for:\n" +"\"%s\"\n" +"S/N %s, ID %08lX, created %s" msgstr "" -"Schlsselverwendungszweck nicht vorhanden - wird zum Verschlsseln " -"akzeptiert\n" - -#: sm/certlist.c:53 -msgid "no key usage specified - accepted for signing\n" +"Bitte geben Sie die Passphrase an, um den \n" +"geheimen Schlssels von\n" +"\"%s\"\n" +"S/N %s, ID %08lX, erzeugt %s\n" +"zu entsperren" + +#: sm/certlist.c:113 +msgid "no key usage specified - assuming all usages\n" msgstr "" -"Schlsselverwendungszweck nicht vorhanden - wird zum Signieren akzeptiert\n" +"Schlsselverwendungszweck nicht vorhanden - fr alle Zwecke akzeptiert\n" -#: sm/certlist.c:58 sm/keylist.c:82 +#: sm/certlist.c:123 sm/keylist.c:108 #, c-format msgid "error getting key usage information: %s\n" msgstr "Fehler beim holen der Schlsselbenutzungsinformationen: %s\n" -#: sm/certlist.c:67 -msgid "certificate should have not been used certification\n" -msgstr "Das Zertifikat hatte nicht zum Zertifizieren benutzt werden sollen\n" +#: sm/certlist.c:133 +msgid "certificate should have not been used for certification\n" +msgstr "Das Zertifikat htte nicht zum Zertifizieren benutzt werden sollen\n" -#: sm/certlist.c:76 +#: sm/certlist.c:144 msgid "certificate should have not been used for encryption\n" msgstr "Das Zertifikat hatte nicht zum Verschlsseln benutzt werden sollen\n" -#: sm/certlist.c:77 +#: sm/certlist.c:145 msgid "certificate should have not been used for signing\n" msgstr "Das Zertifikat hatte nicht zum Signieren benutzt werden sollen\n" -#: sm/certlist.c:78 +#: sm/certlist.c:146 msgid "certificate is not usable for encryption\n" msgstr "Das Zertifikat kann nicht zum Verschlsseln benutzt werden\n" -#: sm/certlist.c:79 +#: sm/certlist.c:147 msgid "certificate is not usable for signing\n" msgstr "Das Zertifikat kann nicht zum Signieren benutzt werden\n" -#: sm/certchain.c:59 +#: sm/certchain.c:109 #, c-format -msgid "critical certificate extension %s is not supported\n" -msgstr "Die kritische Zertifikaterweiterung %s wird nicht untersttzt\n" +msgid "critical certificate extension %s is not supported" +msgstr "Die kritische Zertifikaterweiterung %s wird nicht untersttzt" -#: sm/certchain.c:81 -msgid "issuer certificate is not marked as a CA\n" -msgstr "Das Herausgeberzertifikat ist fr eine CA nicht zulssig\n" +#: sm/certchain.c:131 +msgid "issuer certificate is not marked as a CA" +msgstr "Das Herausgeberzertifikat ist nicht fr eine CA gekennzeichnet" -#: sm/certchain.c:151 -msgid "note: certificate policy not allowed\n" -msgstr "Notiz: Die Zertifikatrichtilinie ist nicht erlaubt\n" +#: sm/certchain.c:169 +msgid "critical marked policy without configured policies" +msgstr "kritische Richtlinie ohne konfigurierte Richtlinien" -#: sm/certchain.c:154 -msgid "certificate policy not allowed\n" -msgstr "Die Zertifikatrichtilinie ist nicht erlaubt\n" +#: sm/certchain.c:185 sm/certchain.c:214 +msgid "note: non-critical certificate policy not allowed" +msgstr "Notiz: Die unkritische Zertifikatrichtlinie ist nicht erlaubt" -#: sm/certchain.c:280 +#: sm/certchain.c:189 sm/certchain.c:218 +msgid "certificate policy not allowed" +msgstr "Die Zertifikatrichtlinie ist nicht erlaubt" + +#: sm/certchain.c:349 msgid "looking up issuer at external location\n" msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" -#: sm/certchain.c:298 +#: sm/certchain.c:367 #, c-format msgid "number of issuers matching: %d\n" msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:334 sm/certchain.c:433 sm/certchain.c:719 sm/decrypt.c:263 -#: sm/encrypt.c:377 sm/sign.c:315 sm/verify.c:116 +#: sm/certchain.c:403 sm/certchain.c:561 sm/certchain.c:909 sm/decrypt.c:260 +#: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:107 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" -#: sm/certchain.c:519 -msgid "the certificate has been revoked\n" -msgstr "Das Zertifikat wurde widerrufen\n" +#: sm/certchain.c:492 +msgid "certificate has been revoked" +msgstr "Das Zertifikat wurde widerrufen" -#: sm/certchain.c:523 -msgid "no CRL found for certificate\n" -msgstr "Keine CRL fr das Zertifikat vorhanden\n" +#: sm/certchain.c:501 +msgid "no CRL found for certificate" +msgstr "Keine CRL fr das Zertifikat gefunden" -#: sm/certchain.c:527 -msgid "the available CRL is too old\n" -msgstr "Die vorhandene CRL ist zu alt\n" +#: sm/certchain.c:505 +msgid "the available CRL is too old" +msgstr "Die vorhandene CRL ist zu alt" -#: sm/certchain.c:528 +#: sm/certchain.c:507 msgid "please make sure that the \"dirmngr\" is properly installed\n" msgstr "" "Bite vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" -#: sm/certchain.c:533 +#: sm/certchain.c:512 #, c-format -msgid "checking the CRL failed: %s\n" -msgstr "Die CRL konnte nicht geprft werden: %s\n" +msgid "checking the CRL failed: %s" +msgstr "Die CRL konnte nicht geprft werden: %s" -#: sm/certchain.c:562 -msgid "root certificate is not marked trusted\n" -msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert\n" +#: sm/certchain.c:581 +msgid "no issuer found in certificate" +msgstr "Im Zertifikat ist kein Herausgeber enthalten" -#: sm/certchain.c:563 +#: sm/certchain.c:594 +#, c-format +msgid "certificate with invalid validity: %s" +msgstr "Zertifikat mit unzulssiger Gltigkeit: %s" + +#: sm/certchain.c:610 +msgid "certificate not yet valid" +msgstr "Das Zertifikat ist noch nicht gltig" + +#: sm/certchain.c:623 +msgid "certificate has expired" +msgstr "Das Zertifikat ist abgelaufen" + +#: sm/certchain.c:660 +msgid "selfsigned certificate has a BAD signature" +msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" + +#: sm/certchain.c:674 +msgid "root certificate is not marked trusted" +msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert" + +#: sm/certchain.c:680 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:568 +#: sm/certchain.c:685 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" -#: sm/certchain.c:582 +#: sm/certchain.c:700 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:592 sm/import.c:127 +#: sm/certchain.c:721 sm/import.c:145 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:643 +#: sm/certchain.c:733 +msgid "issuer certificate not found" +msgstr "Herausgeberzertifikat nicht gefunden" + +#: sm/certchain.c:766 +msgid "certificate has a BAD signature" +msgstr "Das Zertifikat hat eine FALSCHE Signatur" + +#: sm/certchain.c:789 +msgid "found another possible matching CA certificate - trying again" +msgstr "" +"Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " +"nochmal" + +#: sm/certchain.c:812 #, c-format -msgid "certificate chain longer than allowed by CA (%d)\n" -msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)\n" +msgid "certificate chain longer than allowed by CA (%d)" +msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" -#: sm/decrypt.c:128 +#: sm/decrypt.c:127 msgid "" "WARNING: message was encrypted with a weak key in the symmetric cipher.\n" msgstr "" "WARNUNG: Die Nachricht wurde mich einem schwachen Schlssel (Weak Key) " "erzeugt\n" -#: sm/decrypt.c:333 +#: sm/decrypt.c:325 msgid "(this is the RC2 algorithm)\n" msgstr "(Dies ist der RC-2 Algorithmus)\n" -#: sm/decrypt.c:335 +#: sm/decrypt.c:327 msgid "(this does not seem to be an encrypted message)\n" msgstr "(dies is wahrscheinlich keine verschlsselte Nachricht)\n" @@ -551,246 +632,255 @@ msgstr "(dies is wahrscheinlich keine verschl msgid "certificate `%s' not found: %s\n" msgstr "Zertifikat `%s' nicht gefunden: %s\n" -#: sm/delete.c:126 +#: sm/delete.c:112 sm/keydb.c:1388 +#, c-format +msgid "error locking keybox: %s\n" +msgstr "Fehler beim Sperren der Keybox: %s\n" + +#: sm/delete.c:133 #, c-format msgid "duplicated certificate `%s' deleted\n" msgstr "Doppeltes Zertifikat `%s' gelscht\n" -#: sm/delete.c:128 +#: sm/delete.c:135 #, c-format msgid "certificate `%s' deleted\n" msgstr "Zertifikat `%s' gelscht\n" -#: sm/delete.c:158 +#: sm/delete.c:165 #, c-format msgid "deleting certificate \"%s\" failed: %s\n" msgstr "Fehler beim Lschen des Zertifikats \"%s\": %s\n" -#: sm/encrypt.c:105 +#: sm/encrypt.c:120 msgid "weak key created - retrying\n" msgstr "Schwacher Schlssel - es wird erneut versucht\n" -#: sm/encrypt.c:368 +#: sm/encrypt.c:332 msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:210 -msgid "|[file]|make a signature" -msgstr "|DATEI|Erzeufe eine Signatur" +#: sm/gpgsm.c:220 +msgid "|[FILE]|make a signature" +msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:211 -msgid "|[file]|make a clear text signature" -msgstr "|DATEI|Erzeuge eine Klartextsignatur" +#: sm/gpgsm.c:221 +msgid "|[FILE]|make a clear text signature" +msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:212 +#: sm/gpgsm.c:222 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:213 +#: sm/gpgsm.c:223 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:214 +#: sm/gpgsm.c:224 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:215 +#: sm/gpgsm.c:225 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:216 +#: sm/gpgsm.c:226 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:218 +#: sm/gpgsm.c:228 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:219 +#: sm/gpgsm.c:229 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:220 +#: sm/gpgsm.c:230 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:221 +#: sm/gpgsm.c:231 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:223 +#: sm/gpgsm.c:233 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:224 +#: sm/gpgsm.c:234 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:225 +#: sm/gpgsm.c:235 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:226 +#: sm/gpgsm.c:236 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:227 +#: sm/gpgsm.c:237 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:228 +#: sm/gpgsm.c:238 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:229 +#: sm/gpgsm.c:239 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:230 +#: sm/gpgsm.c:240 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:231 +#: sm/gpgsm.c:241 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:232 +#: sm/gpgsm.c:242 msgid "pass a command to the dirmngr" -msgstr "" +msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:234 +#: sm/gpgsm.c:244 msgid "invoke gpg-protect-tool" -msgstr "" +msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:235 +#: sm/gpgsm.c:245 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:252 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:254 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:256 msgid "assume input is in base-64 format" msgstr "Eingabedaten sin im Basis-64 Format" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:258 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:249 +#: sm/gpgsm.c:260 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:252 +#: sm/gpgsm.c:263 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:256 +#: sm/gpgsm.c:267 +msgid "check validity using OCSP" +msgstr "Die Gltigkeit mittels OCSP prfen" + +#: sm/gpgsm.c:270 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:259 +#: sm/gpgsm.c:273 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:262 +#: sm/gpgsm.c:276 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:266 +#: sm/gpgsm.c:280 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:270 +#: sm/gpgsm.c:284 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:272 +#: sm/gpgsm.c:286 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:278 +#: sm/gpgsm.c:292 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:281 +#: sm/gpgsm.c:295 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:283 +#: sm/gpgsm.c:297 msgid "use canonical text mode" -msgstr "" +msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:289 +#: sm/gpgsm.c:303 msgid "don't use the terminal at all" -msgstr "" +msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:292 +#: sm/gpgsm.c:306 msgid "force v3 signatures" -msgstr "" +msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:293 +#: sm/gpgsm.c:307 msgid "always use a MDC for encryption" -msgstr "" +msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:298 +#: sm/gpgsm.c:312 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:299 +#: sm/gpgsm.c:313 msgid "assume yes on most questions" -msgstr "" +msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:300 +#: sm/gpgsm.c:314 msgid "assume no on most questions" -msgstr "" +msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:302 +#: sm/gpgsm.c:316 msgid "add this keyring to the list of keyrings" -msgstr "" +msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:303 +#: sm/gpgsm.c:317 msgid "add this secret keyring to the list" -msgstr "" +msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:304 +#: sm/gpgsm.c:318 msgid "|NAME|use NAME as default secret key" -msgstr "" +msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:305 +#: sm/gpgsm.c:319 msgid "|HOST|use this keyserver to lookup keys" -msgstr "" +msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:306 +#: sm/gpgsm.c:320 msgid "|NAME|set terminal charset to NAME" -msgstr "" +msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:313 +#: sm/gpgsm.c:329 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:320 +#: sm/gpgsm.c:336 msgid "|FILE|load extension module FILE" -msgstr "" +msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:326 +#: sm/gpgsm.c:342 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verhsclsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:328 +#: sm/gpgsm.c:344 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:330 +#: sm/gpgsm.c:346 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:336 +#: sm/gpgsm.c:354 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -798,7 +888,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:339 +#: sm/gpgsm.c:357 msgid "" "@\n" "Examples:\n" @@ -809,12 +899,20 @@ msgid "" " --list-keys [names] show keys\n" " --fingerprint [names] show fingerprints\n" msgstr "" +"@\n" +"Beispiele:\n" +"\n" +" -se -r Bob [Datei] Signieren und verschlsseln fr Benutzer Bob\\n\n" +" --clearsign [Datei] Eine Klartextsignatur erzeugen\\n\n" +" --detach-sign [Datei] Eine abgetrennte Signatur erzeugen\\n\n" +" --list-keys [Namen] Schlssel anzeigenn\n" +" --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:450 +#: sm/gpgsm.c:471 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:453 +#: sm/gpgsm.c:474 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -823,167 +921,273 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:460 +#: sm/gpgsm.c:481 msgid "" "\n" "Supported algorithms:\n" msgstr "" +"\n" +"Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:541 +#: sm/gpgsm.c:562 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:574 +#: sm/gpgsm.c:628 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:633 +#: sm/gpgsm.c:644 +#, c-format +msgid "can't encrypt to `%s': %s\n" +msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" + +#: sm/gpgsm.c:719 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1027 +#: sm/gpgsm.c:1151 msgid "WARNING: program may create a core file!\n" -msgstr "" +msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1037 +#: sm/gpgsm.c:1163 msgid "WARNING: running with faked system time: " -msgstr "" +msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1056 +#: sm/gpgsm.c:1183 msgid "selected cipher algorithm is invalid\n" -msgstr "" +msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1064 +#: sm/gpgsm.c:1191 msgid "selected digest algorithm is invalid\n" -msgstr "" +msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1096 +#: sm/gpgsm.c:1221 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1118 -#, c-format -msgid "can't encrypt to `%s': %s\n" -msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" - -#: sm/gpgsm.c:1156 -msgid "--call-dirmngr <command> {args}" -msgstr "" - -#: sm/gpgsm.c:1172 -msgid "--encrypt [datafile]" -msgstr "" - -#: sm/gpgsm.c:1186 -msgid "--sign [datafile]" -msgstr "" +#: sm/gpgsm.c:1386 +msgid "this command has not yet been implemented\n" +msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1213 -msgid "--verify [signature [detached_data]]" -msgstr "" - -#: sm/gpgsm.c:1230 -msgid "--decrypt [filename]" -msgstr "" - -#: sm/gpgsm.c:1408 sm/gpgsm.c:1441 +#: sm/gpgsm.c:1579 sm/gpgsm.c:1612 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" -#: sm/import.c:96 +#: sm/import.c:114 #, c-format msgid "total number processed: %lu\n" msgstr "gesamte verarbeitete Anzahl: %lu\n" -#: sm/import.c:99 +#: sm/import.c:117 #, c-format msgid " imported: %lu" msgstr " importiert: %lu" -#: sm/import.c:103 +#: sm/import.c:121 #, c-format msgid " unchanged: %lu\n" msgstr " nicht gendert: %lu\n" -#: sm/import.c:105 +#: sm/import.c:123 #, c-format msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: sm/import.c:174 +#: sm/import.c:204 msgid "error storing certificate\n" msgstr "Fehler beim speichern des Zertifikats\n" -#: sm/import.c:181 +#: sm/import.c:211 msgid "basic certificate checks failed - not imported\n" msgstr "Grundlegende Zertifikatprfungen fehlgeschlagen - nicht importiert\n" -#: sm/import.c:313 sm/import.c:345 +#: sm/import.c:396 sm/import.c:428 #, c-format msgid "error importing certificate: %s\n" msgstr "Fehler beim Importieren des Zertifikats: %s\n" -#: sm/keydb.c:188 +#: sm/import.c:457 +#, c-format +msgid "error creating a pipe: %s\n" +msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" + +#: sm/import.c:465 +#, c-format +msgid "error forking process: %s\n" +msgstr "Fehler beim \"Forken\" des Prozess: %s\n" + +#: sm/import.c:560 sm/import.c:585 +#, c-format +msgid "error creating temporary file: %s\n" +msgstr "Fehler beim Erstellen einer temporren Datei: %s\n" + +#: sm/import.c:568 +#, c-format +msgid "error writing to temporary file: %s\n" +msgstr "Fehler beim Schreiben auf eine temporre Datei: %s\n" + +#: sm/import.c:577 +#, c-format +msgid "error reading input: %s\n" +msgstr "Fehler beim Lesen der Eingabe: %s\n" + +#: sm/import.c:647 +#, c-format +msgid "waiting for protect-tool to terminate failed: %s\n" +msgstr "" +"Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" + +#: sm/import.c:650 +#, c-format +msgid "error running `%s': probably not installed\n" +msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" + +#: sm/import.c:652 +#, c-format +msgid "error running `%s': exit status %d\n" +msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" + +#: sm/import.c:655 +#, c-format +msgid "error running `%s': terminated\n" +msgstr "Fehler beim Ausfhren von `%s': beendet\n" + +#: sm/keydb.c:189 #, c-format msgid "error creating keybox `%s': %s\n" msgstr "Die \"Keybox\" `%s' konnte nicht erstellt werden: %s\n" -#: sm/keydb.c:195 +#: sm/keydb.c:192 +msgid "you may want to start the gpg-agent first\n" +msgstr "Sie sollten zuerst den gpg-agent starten\n" + +#: sm/keydb.c:197 #, c-format msgid "keybox `%s' created\n" msgstr "Die \"Keybox\" `%s' wurde erstellt\n" -#: sm/keydb.c:218 +#: sm/keydb.c:220 #, c-format msgid "can't create lock for `%s'\n" msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: sm/keydb.c:1233 +#: sm/keydb.c:1312 sm/keydb.c:1374 msgid "failed to get the fingerprint\n" -msgstr "" +msgstr "Kann den Fingerprint nicht ermitteln\n" -#: sm/keydb.c:1240 +#: sm/keydb.c:1319 sm/keydb.c:1381 msgid "failed to allocate keyDB handle\n" -msgstr "" +msgstr "Kann keinen KeyDB Handler bereitstellen\n" -#: sm/keydb.c:1257 +#: sm/keydb.c:1336 #, c-format msgid "problem looking for existing certificate: %s\n" -msgstr "" +msgstr "Problem bei der Suche nach vorhandenem Zertifikat: %s\n" -#: sm/keydb.c:1265 +#: sm/keydb.c:1344 #, c-format msgid "error finding writable keyDB: %s\n" -msgstr "" +msgstr "Fehler bei der Suche nach einer schreibbaren KeyDB: %s\n" -#: sm/keydb.c:1273 +#: sm/keydb.c:1352 #, c-format msgid "error storing certificate: %s\n" -msgstr "" +msgstr "Fehler beim Speichern des Zertifikats: %s\n" -#: sm/verify.c:382 +#: sm/keydb.c:1396 +#, c-format +msgid "problem re-searching certificate: %s\n" +msgstr "Problem bei Wiederfinden des Zertifikats: %s\n" + +#: sm/keydb.c:1405 +#, c-format +msgid "error getting stored flags: %s\n" +msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" + +#: sm/keydb.c:1414 +#, c-format +msgid "error storing flags: %s\n" +msgstr "Fehler beim Speichern der Flags: %s\n" + +#: sm/verify.c:387 msgid "Signature made " msgstr "Signatur erzeugt am " -#: sm/verify.c:386 +#: sm/verify.c:391 msgid "[date not given]" msgstr "[Datum nicht vorhanden]" -#: sm/verify.c:387 +#: sm/verify.c:392 #, c-format msgid " using certificate ID %08lX\n" msgstr "mittels Zertifikat ID %08lX\n" -#: sm/verify.c:497 +#: sm/verify.c:505 msgid "Good signature from" msgstr "Korrekte Signatur von" -#: sm/verify.c:498 +#: sm/verify.c:506 msgid " aka" msgstr " alias" +#: tools/gpgconf.c:55 +msgid "list all components" +msgstr "Liste aller Komponenten" + +#: tools/gpgconf.c:56 +msgid "|COMPONENT|list options" +msgstr "|KOMPONENTE|Zeige die Optionen an" + +#: tools/gpgconf.c:57 +msgid "|COMPONENT|change options" +msgstr "|KOMPONENTE|ndere die Optionen" + +#: tools/gpgconf.c:63 +msgid "quiet" +msgstr "Weniger Ausgaben" + +#: tools/gpgconf.c:65 +msgid "activate changes at runtime, if possible" +msgstr "Aktiviere nderungen zur Laufzeit; falls mglich" + +#: tools/gpgconf.c:88 +msgid "Usage: gpgconf [options] (-h for help)" +msgstr "Gebrauch: gpgconf [Optionen] (-h fr Hilfe)" + +#: tools/gpgconf.c:91 +msgid "" +"Syntax: gpgconf [options]\n" +"Manage configuration options for tools of the GnuPG system\n" +msgstr "" +"Syntax: gpgconf {Optionen]\n" +"Verwalte Konfigurationsoptionen fr Programme des GnuPG Systems\n" + +#: tools/gpgconf.c:180 +msgid "usage: gpgconf [options] " +msgstr "Gebrauch: gpgconf [Optionen] " + +#: tools/gpgconf.c:181 +msgid "Need one component argument" +msgstr "Bentige ein Komponenten Argument" + +#: tools/gpgconf.c:190 +msgid "Component not found" +msgstr "Komponente nicht gefunden" + +#~ msgid "Enter passphrase:" +#~ msgstr "Bitte das Mantra (Passphrase) eingeben:" + +#~ msgid "[error]" +#~ msgstr "[Fehler]" + +#~ msgid "no key usage specified - accepted for encryption\n" +#~ msgstr "" +#~ "Schlsselverwendungszweck nicht vorhanden - wird zum Verschlsseln " +#~ "akzeptiert\n" + #~ msgid " skipped new keys: %lu\n" #~ msgstr " bersprungene Schlssel: %lu\n" diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 955724b3f..bc9d90b72 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -167,12 +167,12 @@ static void i18n_init (void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE ); + set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); #endif #endif } diff --git a/sm/certdump.c b/sm/certdump.c index 30cd0bd53..aefaf27ef 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -633,7 +633,7 @@ gpgsm_format_keydesc (ksba_cert_t cert) #ifdef ENABLE_NLS /* The Assuan agent protol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE, NULL); + orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); #ifdef HAVE_LANGINFO_CODESET if (!orig_codeset) orig_codeset = nl_langinfo (CODESET); @@ -641,7 +641,7 @@ gpgsm_format_keydesc (ksba_cert_t cert) if (orig_codeset) { /* We only switch when we are able to restore the codeset later. */ orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE, "utf-8")) + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) orig_codeset = NULL; } #endif @@ -659,7 +659,7 @@ gpgsm_format_keydesc (ksba_cert_t cert) #ifdef ENABLE_NLS if (orig_codeset) - bind_textdomain_codeset (PACKAGE, orig_codeset); + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); #endif xfree (orig_codeset); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 761aefcee..047b356dd 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -540,7 +540,7 @@ static void i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file (PACKAGE); + set_gettext_file (PACKAGE_GT); #else # ifdef ENABLE_NLS # ifdef HAVE_LC_MESSAGES @@ -549,8 +549,8 @@ i18n_init(void) # else setlocale (LC_ALL, "" ); # endif - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); # endif #endif } @@ -1318,7 +1318,7 @@ main ( int argc, char **argv) case aCallDirmngr: if (!argc) - wrong_args (_("--call-dirmngr <command> {args}")); + wrong_args ("--call-dirmngr <command> {args}"); else if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1)) gpgsm_exit (1); @@ -1334,7 +1334,7 @@ main ( int argc, char **argv) else if (argc == 1) gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */ else - wrong_args (_("--encrypt [datafile]")); + wrong_args ("--encrypt [datafile]"); break; case aSign: /* sign the given file */ @@ -1348,7 +1348,7 @@ main ( int argc, char **argv) gpgsm_sign (&ctrl, signerlist, open_read (*argv), detached_sig, stdout); /* from file */ else - wrong_args (_("--sign [datafile]")); + wrong_args ("--sign [datafile]"); break; case aSignEncr: /* sign and encrypt the given file */ @@ -1375,7 +1375,7 @@ main ( int argc, char **argv) else if (argc == 2) /* detached signature (sig, detached) */ gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL); else - wrong_args (_("--verify [signature [detached_data]]")); + wrong_args ("--verify [signature [detached_data]]"); if (fp && fp != stdout) fclose (fp); @@ -1383,7 +1383,7 @@ main ( int argc, char **argv) break; case aVerifyFiles: - log_error ("this command has not yet been implemented\n"); + log_error (_("this command has not yet been implemented\n")); break; case aDecrypt: @@ -1392,7 +1392,7 @@ main ( int argc, char **argv) else if (argc == 1) gpgsm_decrypt (&ctrl, open_read (*argv), stdout); /* from file */ else - wrong_args (_("--decrypt [filename]")); + wrong_args ("--decrypt [filename]"); break; case aDeleteKey: @@ -1445,7 +1445,7 @@ main ( int argc, char **argv) if (argc == 1) gpgsm_p12_export (&ctrl, *argv, stdout); else - wrong_args (_("--export-secret-key-p12 KEY-ID")); + wrong_args ("--export-secret-key-p12 KEY-ID"); break; case aSendKeys: diff --git a/sm/import.c b/sm/import.c index 02d2e629f..c54579b7d 100644 --- a/sm/import.c +++ b/sm/import.c @@ -644,7 +644,7 @@ parse_p12 (ksba_reader_t reader, FILE **retfp) while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) ; if (i == -1) - log_error (_("waiting for protect-tools to terminate failed: %s\n"), + log_error (_("waiting for protect-tool to terminate failed: %s\n"), strerror (errno)); else if (WIFEXITED (status) && WEXITSTATUS (status) == 31) log_error (_("error running `%s': probably not installed\n"), pgmname); diff --git a/tools/gpgconf.c b/tools/gpgconf.c index aab1397c7..7aca335fa 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -103,7 +103,7 @@ static void i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file (PACKAGE); + set_gettext_file (PACKAGE_GT); #else # ifdef ENABLE_NLS # ifdef HAVE_LC_MESSAGES @@ -112,8 +112,8 @@ i18n_init(void) # else setlocale (LC_ALL, "" ); # endif - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); # endif #endif } -- cgit v1.2.3 From b361a6addc80ce618909dad898876208f0ba28a7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Apr 2004 11:40:28 +0000 Subject: About to release 1.9.7 --- ChangeLog | 2 ++ NEWS | 2 +- configure.ac | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11c4093a1..ff87bdd70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 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. diff --git a/NEWS b/NEWS index a4c909fa3..763b7707f 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.7 +Noteworthy changes in version 1.9.7 (2004-04-06) ------------------------------------------------ * Instrumented the modules for gpgconf. diff --git a/configure.ac b/configure.ac index 8c167f9e2..a3a4e3d0b 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.7-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.7, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From e9857ca1e3cf2009203a9ee7a3999bb6f03416c0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Apr 2004 14:15:47 +0000 Subject: post release re-versioning --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 763b7707f..dc1122846 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.8 +------------------------------------------------ + + Noteworthy changes in version 1.9.7 (2004-04-06) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index a3a4e3d0b..dc296af43 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.7, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.8-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 1194f42d5aca06edb8850a93c06b234090228449 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 7 Apr 2004 16:53:55 +0000 Subject: (my_dgettext): Switch the codeset once to utf-8. Allow building with out NLS. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index a9bd5fba5..0a4046cbd 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-04-07 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c (my_dgettext): Switch the codeset once to utf-8. + Allow building with out NLS. + 2004-03-23 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_options_dirmngr): Set GC_OPT_FLAG_ARG_OPT for diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index fa755afe0..0b56129c1 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -855,16 +855,31 @@ gpg_agent_runtime_change (void) } -/* Robust version of dgettext. */ +/* More or less Robust version of dgettext. It has the sidefeect of + switching the codeset to utf-8 becuase this is what we want to + output. In theory it is posible to keep the orginal code set and + switch back for regular disgnostic output (redefine "_(" for that) + but given the natur of this tool, being something invoked from + other pograms, it does not make much sense. */ static const char * my_dgettext (const char *domain, const char *msgid) { +#ifdef ENABLE_NLS if (domain) { - char *text = dgettext (domain, msgid); + static int switched_codeset; + char *text; + + if (!switched_codeset) + { + bind_textdomain_codeset (PACKAGE_GT, "utf-8"); + switched_codeset = 1; + } + text = dgettext (domain, msgid); return text ? text : msgid; } else +#endif return msgid; } -- cgit v1.2.3 From c61c77b1b2d68a91c409ca2a5a91368f4c84d220 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 7 Apr 2004 17:59:18 +0000 Subject: * gpgsm.c: New option --force-crl-refresh. * call-dirmngr.c (gpgsm_dirmngr_isvalid): Pass option to dirmngr. --- sm/ChangeLog | 5 +++++ sm/call-dirmngr.c | 13 +++++++++++++ sm/fingerprint.c | 2 +- sm/gpgsm.c | 7 ++++++- sm/gpgsm.h | 1 + 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 25f72915f..c2627d3d2 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-04-07 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New option --force-crl-refresh. + * call-dirmngr.c (gpgsm_dirmngr_isvalid): Pass option to dirmngr. + 2004-04-05 Werner Koch <wk@gnupg.org> * server.c (get_status_string): Add STATUS_NEWSIG. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 0e8f67f28..15160dc41 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -149,6 +149,8 @@ start_dirmngr (void) if (dirmngr_ctx) return 0; /* fixme: We need a context for each thread or serialize the access to the dirmngr */ + /* Note: if you change this to multiple connections, you also need + to take care of the implicit option sending caching. */ infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); if (!infostr || !*infostr) @@ -359,12 +361,14 @@ int gpgsm_dirmngr_isvalid (ctrl_t ctrl, ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) { + static int did_options; int rc; char *certid; char line[ASSUAN_LINELENGTH]; struct inq_certificate_parm_s parm; struct isvalid_status_parm_s stparm; + rc = start_dirmngr (); if (rc) return rc; @@ -402,6 +406,15 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, option to dirmngr, so that no fallback CRL check is done after an ocsp check. */ + /* It is sufficient to send the options only once because we have + one connection per process only. */ + if (!did_options) + { + if (opt.force_crl_refresh) + assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1", + NULL, NULL, NULL, NULL, NULL, NULL); + did_options = 1; + } snprintf (line, DIM(line)-1, "ISVALID %s", certid); line[DIM(line)-1] = 0; xfree (certid); diff --git a/sm/fingerprint.c b/sm/fingerprint.c index 26d147f41..6755f8eb7 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -153,7 +153,7 @@ gpgsm_get_keygrip (ksba_cert_t cert, char *array) return NULL; /* oops */ if (DBG_X509) - log_debug ("get_keygrip for public key: %s\n", p); + log_debug ("get_keygrip for public key\n"); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 047b356dd..7140e34ac 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -115,10 +115,11 @@ enum cmd_and_opt_values { oDisableCRLChecks, oEnableCRLChecks, + oForceCRLRefresh, + oDisableOCSP, oEnableOCSP, - oIncludeCerts, oPolicyFile, oDisablePolicyChecks, @@ -262,6 +263,7 @@ static ARGPARSE_OPTS opts[] = { { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, + { oForceCRLRefresh, "force-crl-refresh", 0, "@"}, { oDisableOCSP, "disable-ocsp", 0, "@" }, { oEnableOCSP, "enable-ocsp", 0, N_("check validity using OCSP")}, @@ -931,6 +933,9 @@ main ( int argc, char **argv) case oEnableCRLChecks: opt.no_crl_check = 0; break; + case oForceCRLRefresh: + opt.force_crl_refresh = 1; + break; case oDisableOCSP: ctrl.use_ocsp = opt.enable_ocsp = 0; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 93487f002..d3fbc03ef 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -89,6 +89,7 @@ struct { int ignore_time_conflict; /* Ignore certain time conflicts */ int no_crl_check; /* Don't do a CRL check */ + int force_crl_refresh; /* Force refreshing the CRL. */ int enable_ocsp; /* Default to use OCSP checks. */ char *policy_file; /* full pathname of policy file */ -- cgit v1.2.3 From bd2d99c4e750b0529f4ebbcd4e8981a08ce97999 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 7 Apr 2004 18:02:56 +0000 Subject: Documented --force-crl-refresh --- doc/gpgsm.texi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 24503a10b..977fe3c37 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -261,6 +261,16 @@ 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 -- cgit v1.2.3 From 389fa08de6077a0ef3499d841dee2d26ffa657d4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 8 Apr 2004 09:53:32 +0000 Subject: (gpgsm_decrypt): Return GPG_ERR_NO_DATA if it is not a encrypted message. --- sm/ChangeLog | 5 +++++ sm/decrypt.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/sm/ChangeLog b/sm/ChangeLog index c2627d3d2..eac744b08 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-04-08 Werner Koch <wk@gnupg.org> + + * decrypt.c (gpgsm_decrypt): Return GPG_ERR_NO_DATA if it is not a + encrypted message. + 2004-04-07 Werner Koch <wk@gnupg.org> * gpgsm.c: New option --force-crl-refresh. diff --git a/sm/decrypt.c b/sm/decrypt.c index 76524b51f..df0edc2ae 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -333,6 +333,11 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) numbuf, algoid?algoid:"?", NULL); } + /* If it seems that this is not an ecrypted message we + return a more sensible error code. */ + if (!algoid) + rc = gpg_error (GPG_ERR_NO_DATA); + goto leave; } dfparm.algo = algo; -- cgit v1.2.3 From 5b9023c6e7b55f66845821544514c7a11e687bb7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 13 Apr 2004 09:45:23 +0000 Subject: (copy_and_escape): Relaxed quoting. --- common/ChangeLog | 4 ++++ common/simple-pwquery.c | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index e82e5b774..8e81baa0c 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 50dabc218..36244b120 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -357,19 +357,21 @@ static char * copy_and_escape (char *buffer, const char *text) { int i; + const unsigned char *s = text; char *p = buffer; + - for (i=0; text[i]; i++) + for (i=0; s[i]; i++) { - if (text[i] < ' ' || text[i] == '+') + if (s[i] < ' ' || s[i] == '+') { - sprintf (p, "%%%02X", text[i]); + sprintf (p, "%%%02X", s[i]); p += 3; } - else if (text[i] == ' ') + else if (s[i] == ' ') *p++ = '+'; else - *p++ = text[i]; + *p++ = s[i]; } return p; } -- cgit v1.2.3 From aaac5dd2dca6dc1bcd2367a93e6d9713379121d7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 13 Apr 2004 09:45:35 +0000 Subject: * misc.c (setup_pinentry_env): New. * import.c (popen_protect_tool): Call it. * export.c (popen_protect_tool): Call it. --- sm/ChangeLog | 6 ++++++ sm/export.c | 2 ++ sm/gpgsm.h | 2 ++ sm/import.c | 2 ++ sm/misc.c | 36 ++++++++++++++++++++++++++++++++++-- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index eac744b08..02f627a4d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-04-13 Werner Koch <wk@gnupg.org> + + * misc.c (setup_pinentry_env): New. + * import.c (popen_protect_tool): Call it. + * export.c (popen_protect_tool): Call it. + 2004-04-08 Werner Koch <wk@gnupg.org> * decrypt.c (gpgsm_decrypt): Return GPG_ERR_NO_DATA if it is not a diff --git a/sm/export.c b/sm/export.c index 66dd46d25..8a89110de 100644 --- a/sm/export.c +++ b/sm/export.c @@ -581,6 +581,8 @@ popen_protect_tool (const char *pgmname, close(i); errno = 0; + setup_pinentry_env (); + execlp (pgmname, arg0, "--homedir", opt.homedir, "--p12-export", diff --git a/sm/gpgsm.h b/sm/gpgsm.h index d3fbc03ef..a06bfa482 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -299,6 +299,8 @@ int gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command, int argc, char **argv); +/*-- misc.c --*/ +void setup_pinentry_env (void); diff --git a/sm/import.c b/sm/import.c index c54579b7d..df080da9e 100644 --- a/sm/import.c +++ b/sm/import.c @@ -498,6 +498,8 @@ popen_protect_tool (const char *pgmname, close(i); errno = 0; + setup_pinentry_env (); + execlp (pgmname, arg0, "--homedir", opt.homedir, "--p12-import", diff --git a/sm/misc.c b/sm/misc.c index 4ffa7153e..281056177 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -1,5 +1,5 @@ /* misc.c - Miscellaneous fucntions - * Copyright (C) 2001 Free Software Foundation, Inc. + * Copyright (C) 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,9 +25,41 @@ #include <string.h> #include <ctype.h> #include <unistd.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif #include "gpgsm.h" -#include <ksba.h> +/* Setup the environment so that the pinentry is able to get all + required information. This is used prior to an exec of the + protect-tool. */ +void +setup_pinentry_env (void) +{ + char *lc; + + if (opt.display) + setenv ("DISPLAY", opt.display, 1); + if (opt.ttyname) + setenv ("GPG_TTY", opt.ttyname, 1); + if (opt.ttytype) + setenv ("TERM", opt.ttytype, 1); + + if (opt.lc_ctype) + setenv ("LC_CTYPE", opt.lc_ctype, 1); +#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) + else if ( (lc = setlocale (LC_CTYPE, "")) ) + setenv ("LC_CTYPE", lc, 1); +#endif + + if (opt.lc_messages) + setenv ("LC_MESSAGES", opt.lc_messages, 1); +#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) + else if ( (lc = setlocale (LC_MESSAGES, "")) ) + setenv ("LC_MESSAGES", lc, 1); +#endif + +} -- cgit v1.2.3 From e21bf7b9e059dc0ef97c6c8a866db3a266f3f647 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Apr 2004 09:46:54 +0000 Subject: * gpg-agent.c (main): Tell the logging code taht we are runnign detached. * logging.h (JNLIB_LOG_WITH_PREFIX): Add constants for the flag values. * logging.c (log_set_prefix): New flag DETACHED. (fun_writer): Take care of this flag. (log_test_fd): New. --- agent/ChangeLog | 5 ++++ agent/gpg-agent.c | 24 +++++++++++------ jnlib/ChangeLog | 10 +++++++- jnlib/logging.c | 77 ++++++++++++++++++++++++++++++++++++++----------------- jnlib/logging.h | 8 +++++- 5 files changed, 91 insertions(+), 33 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index b20ee42e0..43bdb7ab5 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-04-16 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (main): Tell the logging code taht we are runnign + detached. + 2004-04-06 Werner Koch <wk@gnupg.org> * gpg-agent.c (main): Use new libgcrypt thread library register diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 0fc1bb8bf..18a456f19 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -389,7 +389,7 @@ main (int argc, char **argv ) /* Please note that we may running SUID(ROOT), so be very CAREFUL when adding any stuff between here and the call to INIT_SECMEM() somewhere after the option parsing */ - log_set_prefix ("gpg-agent", 1|4); + log_set_prefix ("gpg-agent", JNLIB_LOG_WITH_PREFIX|JNLIB_LOG_WITH_PID); /* Try to auto set the character set. */ set_native_charset (NULL); @@ -652,11 +652,13 @@ main (int argc, char **argv ) bind_textdomain_codeset (PACKAGE_GT, "UTF-8"); #endif - /* now start with logging to a file if this is desired */ + /* Now start with logging to a file if this is desired. */ if (logfile) { log_set_file (logfile); - log_set_prefix (NULL, 1|2|4); + log_set_prefix (NULL, (JNLIB_LOG_WITH_PREFIX + |JNLIB_LOG_WITH_TIME + |JNLIB_LOG_WITH_PID)); } /* Make sure that we have a default ttyname. */ @@ -754,7 +756,7 @@ main (int argc, char **argv ) exit (1); } else if (pid) - { /* we are the parent */ + { /* We are the parent */ char *infostr; close (fd); @@ -803,17 +805,20 @@ main (int argc, char **argv ) } /* end parent */ - /* this is the child */ + /* + This is the child + */ - /* detach from tty and put process into a new session */ + /* Detach from tty and put process into a new session */ if (!nodetach ) { int i; + unsigned int oldflags; - /* close stdin, stdout and stderr unless it is the log stream */ + /* Close stdin, stdout and stderr unless it is the log stream */ for (i=0; i <= 2; i++) { - if ( log_get_fd () != i) + if (!log_test_fd (i) ) close (i); } if (setsid() == -1) @@ -822,6 +827,9 @@ main (int argc, char **argv ) cleanup (); exit (1); } + + log_get_prefix (&oldflags); + log_set_prefix (NULL, oldflags | JNLIB_LOG_RUN_DETACHED); opt.running_detached = 1; } diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 6867b4fb9..99c9177b5 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,11 @@ +2004-04-16 Werner Koch <wk@gnupg.org> + + * logging.h (JNLIB_LOG_WITH_PREFIX): Add constants for the flag + values. + * logging.c (log_set_prefix): New flag DETACHED. + (fun_writer): Take care of this flag. + (log_test_fd): New. + 2004-02-18 Werner Koch <wk@gnupg.org> * stringhelp.c (print_sanitized_buffer): Don't care about @@ -181,7 +189,7 @@ Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> * You may find it source-copied in other packages. * *********************************************************** - Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003, 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 diff --git a/jnlib/logging.c b/jnlib/logging.c index 6a12d8771..fdf2d7fcb 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -1,5 +1,6 @@ /* logging.c - useful logging functions - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -46,10 +47,12 @@ static FILE *logstream; +static int log_socket = -1; static char prefix_buffer[80]; static int with_time; static int with_prefix; static int with_pid; +static int running_detached; static int force_prefixes; static int missing_lf; @@ -125,9 +128,14 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) { struct fun_cookie_s *cookie = cookie_arg; - /* Note that we always try to reconnect to the socket but print error - messages only the first time an error occured. */ - if (cookie->fd == -1 ) + /* Note that we always try to reconnect to the socket but print + error messages only the first time an error occured. IF + RUNNING_DETACHED is set we don't fall back to stderr and even do + not print any error messages. This is needed becuase detached + processes often close stderr and my printing to fiel descriptor 2 + we might send the log message to a file not intended for logging + (e.g. a pipe or network connection). */ + if (cookie->fd == -1) { /* Note yet open or meanwhile closed due to an error. */ struct sockaddr_un addr; @@ -136,11 +144,12 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); if (cookie->fd == -1) { - if (!cookie->quiet) + if (!cookie->quiet && !running_detached) fprintf (stderr, "failed to create socket for logging: %s\n", strerror(errno)); goto failure; } + log_socket = cookie->fd; memset (&addr, 0, sizeof addr); addr.sun_family = PF_LOCAL; @@ -151,7 +160,8 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) { - if (!cookie->quiet) + log_socket = -1; + if (!cookie->quiet && !running_detached) fprintf (stderr, "can't connect to `%s': %s\n", cookie->name, strerror(errno)); close (cookie->fd); @@ -165,19 +175,24 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) if (!writen (cookie->fd, buffer, size)) return size; /* Okay. */ - fprintf (stderr, "error writing to `%s': %s\n", - cookie->name, strerror(errno)); + log_socket = -1; + if (!running_detached) + fprintf (stderr, "error writing to `%s': %s\n", + cookie->name, strerror(errno)); close (cookie->fd); cookie->fd = -1; failure: - if (!cookie->quiet) + if (!running_detached) { - fputs ("switching logging to stderr\n", stderr); - cookie->quiet = 1; + if (!cookie->quiet) + { + fputs ("switching logging to stderr\n", stderr); + cookie->quiet = 1; + } + + fwrite (buffer, size, 1, stderr); } - - fwrite (buffer, size, 1, stderr); return size; } @@ -297,9 +312,10 @@ log_set_prefix (const char *text, unsigned int flags) prefix_buffer[sizeof (prefix_buffer)-1] = 0; } - with_prefix = (flags & 1); - with_time = (flags & 2); - with_pid = (flags & 4); + with_prefix = (flags & JNLIB_LOG_WITH_PREFIX); + with_time = (flags & JNLIB_LOG_WITH_TIME); + with_pid = (flags & JNLIB_LOG_WITH_PID); + running_detached = (flags & JNLIB_LOG_RUN_DETACHED); } @@ -310,30 +326,45 @@ log_get_prefix (unsigned int *flags) { *flags = 0; if (with_prefix) - *flags |= 1; + *flags |= JNLIB_LOG_WITH_PREFIX; if (with_time) - *flags |= 2; + *flags |= JNLIB_LOG_WITH_TIME; if (with_pid) - *flags |=4; + *flags |= JNLIB_LOG_WITH_PID; + if (running_detached) + *flags |= JNLIB_LOG_RUN_DETACHED; } return prefix_buffer; } +/* This function returns true if the file descriptor FD is in use for + logging. This is preferable over a test using log_get_fd in that + it allows the logging code to use more then one file descriptor. */ +int +log_test_fd (int fd) +{ + if (fileno (logstream?logstream:stderr) == fd) + return 1; + if (log_socket == fd) + return 1; + return 0; +} + int -log_get_fd() +log_get_fd () { - return fileno(logstream?logstream:stderr); + return fileno(logstream?logstream:stderr); } FILE * log_get_stream () { - return logstream?logstream:stderr; + return logstream?logstream:stderr; } static void -do_logv( int level, const char *fmt, va_list arg_ptr ) +do_logv (int level, const char *fmt, va_list arg_ptr) { if (!logstream) logstream = stderr; diff --git a/jnlib/logging.h b/jnlib/logging.h index 78d2b020d..b5c0bd741 100644 --- a/jnlib/logging.h +++ b/jnlib/logging.h @@ -1,5 +1,5 @@ /* logging.h - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -24,6 +24,11 @@ #include <stdio.h> #include "mischelp.h" +/* Flag values for log_set_prefix. */ +#define JNLIB_LOG_WITH_PREFIX 1 +#define JNLIB_LOG_WITH_TIME 2 +#define JNLIB_LOG_WITH_PID 4 +#define JNLIB_LOG_RUN_DETACHED 256 int log_get_errorcount (int clear); void log_inc_errorcount (void); @@ -31,6 +36,7 @@ void log_set_file( const char *name ); void log_set_fd (int fd); void log_set_prefix (const char *text, unsigned int flags); const char *log_get_prefix (unsigned int *flags); +int log_test_fd (int fd); int log_get_fd(void); FILE *log_get_stream (void); -- cgit v1.2.3 From 56dced503df190cf4174e12e0aa398e2a04a75f2 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 19 Apr 2004 14:17:30 +0000 Subject: 2004-04-02 Thomas Schwinge <schwinge@nic-nac-project.de> * autogen.sh: Added ACLOCAL_FLAGS. --- ChangeLog | 4 ++++ autogen.sh | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index ff87bdd70..cce1f799b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/autogen.sh b/autogen.sh index ad335b972..a607d63da 100755 --- a/autogen.sh +++ b/autogen.sh @@ -149,8 +149,8 @@ EOF fi -echo "Running aclocal -I m4 ..." -$ACLOCAL -I m4 +echo "Running aclocal -I m4 ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..." +$ACLOCAL -I m4 $ACLOCAL_FLAGS echo "Running autoheader..." $AUTOHEADER echo "Running automake --gnu ..." -- cgit v1.2.3 From c1858725b24b5c19a94b2e4da224291f8e1403df Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Apr 2004 06:50:55 +0000 Subject: Removed this file from the CVS. --- common/fopencookie.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 common/fopencookie.c diff --git a/common/fopencookie.c b/common/fopencookie.c deleted file mode 100644 index 7862b9a0d..000000000 --- a/common/fopencookie.c +++ /dev/null @@ -1,37 +0,0 @@ -/* fopencookie.c - Dummy glibc replacement - * 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> -#include <errno.h> - -#include "util.h" - -FILE * -fopencookie (void *cookie, const char *opentype, - cookie_io_functions_t funclist) -{ - errno = ENOSYS; - return NULL; -} - - -- cgit v1.2.3 From 22795ca77fa88910483d94f1d2a7b8759783c3d6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Apr 2004 14:16:26 +0000 Subject: * configure.ac: Remove the fopencookie test. We don't need the dummy function because we conditionally use fopencookie, fpencookie or a replacement at place. --- ChangeLog | 6 ++++++ THANKS | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index cce1f799b..23f099ba3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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. diff --git a/THANKS b/THANKS index e6cac5b9c..3f56e29d3 100644 --- a/THANKS +++ b/THANKS @@ -1,5 +1,5 @@ -Richard Lefebvre rick@CERCA.UMontreal.CA -Andrew J. Schorr aschorr@telemetry-investments.com - +Richard Lefebvre rick at CERCA.UMontreal.CA +Andrew J. Schorr aschorr at telemetry-investments.com +Michael Nottebrock michaelnottebrock at gmx.net -- cgit v1.2.3 From 74b7ca69f946366ddf97df955904c7e7d7c724cf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Apr 2004 14:16:44 +0000 Subject: Remove the fopencookie test. We don't need the dummy function because we conditionally use fopencookie, fpencookie or a replacement at place. --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index dc296af43..1a3a450c7 100644 --- a/configure.ac +++ b/configure.ac @@ -764,7 +764,6 @@ AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) AC_CHECK_FUNCS(flockfile funlockfile fopencookie funopen) AC_REPLACE_FUNCS(vasprintf) -AC_REPLACE_FUNCS(fopencookie) AC_REPLACE_FUNCS(mkdtemp) AC_REPLACE_FUNCS(fseeko ftello) AC_REPLACE_FUNCS(isascii) -- cgit v1.2.3 From d70bc68c307a36d673fc911b9bea92e28cf7396f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Apr 2004 14:16:55 +0000 Subject: Include jnlib/types.h and remove our own definitions for byte.u16 and u32. --- kbx/ChangeLog | 5 +++++ kbx/keybox-defs.h | 17 ++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index a866e04f0..d6c75025e 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,8 @@ +2004-04-20 Werner Koch <wk@gnupg.org> + + * keybox-defs.h: Include jnlib/types.h and remove our own + definitions for byte.u16 and u32. + 2004-02-02 Werner Koch <wk@gnupg.org> * keybox.h (keybox_flag_t): New. diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 17431502f..d7e132d6b 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -1,5 +1,5 @@ /* keybox-defs.h - interal Keybox defintions - * Copyright (C) 2001 Free Software Foundation, Inc. + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -28,19 +28,14 @@ #include <gpg-error.h> #include <sys/types.h> /* off_t */ -#include "keybox.h" +/* We include the type defintions from jnlib instead of defining our + owns here. This will not allow us build KBX in a standalone way + but tehre is currently no need for it anyway. */ +#include "../jnlib/types.h" +#include "keybox.h" -#ifndef HAVE_BYTE_TYPEDEF -typedef unsigned char byte; /* fixme */ -#endif -#ifndef HAVE_U16_TYPEDEF -typedef unsigned short u16; /* fixme */ -#endif -#ifndef HAVE_U32_TYPEDEF -typedef unsigned int u32; /* fixme */ -#endif enum { BLOBTYPE_EMPTY = 0, -- cgit v1.2.3 From e950b01ff56c86d8e04b75a7bac4234afc939199 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Apr 2004 14:17:10 +0000 Subject: * pcsc-wrapper.c: New. * Makefile.am (pkglib_PROGRAMS): Install it here. * apdu.c (writen, readn): New. (open_pcsc_reader, pcsc_send_apdu, close_pcsc_reader): Use the pcsc-wrapper if we are using Pth. --- scd/ChangeLog | 54 +++++ scd/Makefile.am | 16 +- scd/apdu.c | 688 ++++++++++++++++++++++++++++++++++++++++++++++++++++- scd/apdu.h | 11 +- scd/ccid-driver.c | 276 +++++++++++++++++---- scd/ccid-driver.h | 1 + scd/command.c | 69 ++++-- scd/iso7816.c | 3 + scd/pcsc-wrapper.c | 631 ++++++++++++++++++++++++++++++++++++++++++++++++ scd/scdaemon.c | 154 +++++++++++- scd/scdaemon.h | 2 + 11 files changed, 1827 insertions(+), 78 deletions(-) create mode 100644 scd/pcsc-wrapper.c diff --git a/scd/ChangeLog b/scd/ChangeLog index 895aae966..9b04d5e78 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,57 @@ +2004-04-20 Werner Koch <wk@gnupg.org> + + * pcsc-wrapper.c: New. + * Makefile.am (pkglib_PROGRAMS): Install it here. + * apdu.c (writen, readn): New. + (open_pcsc_reader, pcsc_send_apdu, close_pcsc_reader): Use the + pcsc-wrapper if we are using Pth. + +2004-04-19 Werner Koch <wk@gnupg.org> + + * ccid-driver.c (parse_ccid_descriptor): Store some of the reader + features away. New arg HANDLE + (read_device_info): New arg HANDLE. Changed caller. + (bulk_in): Handle time extension requests. + (ccid_get_atr): Setup parameters and the IFSD. + (compute_edc): New. Factored out code. + (ccid_transceive): Use default NADs when required. + +2004-04-14 Werner Koch <wk@gnupg.org> + + * scdaemon.h (server_control_s): Add member READER_SLOT. + * scdaemon.c (scd_init_default_ctrl): Initialize READER_SLOT to -1. + * command.c (open_card): Reuse an open slot. + (reset_notify): Just reset the slot if supported by the reader. + (do_reset): Factored code from above out. + (scd_command_handler): Use it for cleanup. + + * apdu.h: New pseudo stati SW_HOST_NOT_SUPPORTED, + SW_HOST_LOCKING_FAILED and SW_HOST_BUSY. + * iso7816.c (map_sw): Map it. + + * ccid-driver.c (ccid_slot_status): Add arg STATUSBITS. + * apdu.c (apdu_get_status): New. + (ct_get_status, pcsc_get_status, ocsc_get_status): New stubs. + (get_status_ccid): New. + (apdu_reset): New. + (reset_ct_reader, reset_pcsc_reader, reset_osc_reader): New stubs. + (reset_ccid_reader): New. + (apdu_enum_reader): New. + + * apdu.c (lock_slot, trylock_slot, unlock_slot): New helpers. + (new_reader_slot) [USE_GNU_PTH]: Init mutex. + (apdu_reset, apdu_get_status, apdu_send_le): Run functions + in locked mode. + + * command.c (scd_update_reader_status_file): New. + * scdaemon.c (handle_tick): Call it. + +2004-04-13 Werner Koch <wk@gnupg.org> + + * scdaemon.c: Convert to a Pth application. + (handle_signal, ticker_thread, handle_tick): New. + (main): Fire up the ticker thread in server mode. + 2004-03-23 Werner Koch <wk@gnupg.org> * scdaemon.c (main) <gpgconf_list>: Fixed output for pcsc_driver. diff --git a/scd/Makefile.am b/scd/Makefile.am index da59a1997..c3c603d28 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -19,13 +19,14 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = scdaemon sc-investigate sc-copykeys +pkglib_PROGRAMS = pcsc-wrapper AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am AM_CFLAGS = $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ - $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) + $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) card_apps = app-openpgp.c app-nks.c app-dinsig.c @@ -43,7 +44,8 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(PTH_LIBS) \ + $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ $(LIBUSB_LIBS) -lgpg-error @INTLLIBS@ -ldl sc_investigate_SOURCES = \ @@ -57,7 +59,8 @@ sc_investigate_SOURCES = \ sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBUSB_LIBS) \ + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(PTH_LIBS) \ + $(KSBA_LIBS) $(LIBUSB_LIBS) \ @INTLLIBS@ -lgpg-error -ldl @@ -73,5 +76,10 @@ sc_copykeys_SOURCES = \ sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBUSB_LIBS) \ + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(PTH_LIBS) \ + $(KSBA_LIBS) $(LIBUSB_LIBS) \ -lgpg-error @INTLLIBS@ -ldl + +pcsc_wrapper_SOURCES = pcsc-wrapper.c +pcsc_wrapper_LDADD = -ldl +pcsc_wrapper_CFLAGS = \ No newline at end of file diff --git a/scd/apdu.c b/scd/apdu.c index 7843fd566..1b5ebc375 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1,5 +1,5 @@ /* apdu.c - ISO 7816 APDU functions and low level I/O - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -24,6 +24,11 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#ifdef USE_GNU_PTH +# include <pth.h> +# include <unistd.h> +# include <fcntl.h> +#endif #ifdef HAVE_OPENSC # include <opensc/opensc.h> #endif @@ -48,6 +53,11 @@ #include "dynload.h" #include "ccid-driver.h" +#ifdef USE_GNU_PTH +#define NEED_PCSC_WRAPPER 1 +#endif + + #define MAX_READER 4 /* Number of readers we support concurrently. */ #define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for insertion of the card (1 = don't wait). */ @@ -59,6 +69,12 @@ #define DLSTDCALL #endif +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + /* A structure to collect information pertaining to one reader slot. */ @@ -74,6 +90,11 @@ struct reader_table_s { unsigned long context; unsigned long card; unsigned long protocol; +#ifdef NEED_PCSC_WRAPPER + int req_fd; + int rsp_fd; + pid_t pid; +#endif /*NEED_PCSC_WRAPPER*/ } pcsc; #ifdef HAVE_OPENSC int is_osc; /* We are using the OpenSC driver layer. */ @@ -85,6 +106,11 @@ struct reader_table_s { int status; unsigned char atr[33]; size_t atrlen; + unsigned int change_counter; +#ifdef USE_GNU_PTH + int lock_initialized; + pth_mutex_t lock; +#endif }; typedef struct reader_table_s *reader_table_t; @@ -185,11 +211,27 @@ new_reader_slot (void) log_error ("new_reader_slot: out of slots\n"); return -1; } +#ifdef USE_GNU_PTH + if (!reader_table[reader].lock_initialized) + { + if (!pth_mutex_init (&reader_table[reader].lock)) + { + log_error ("error initializing mutex: %s\n", strerror (errno)); + return -1; + } + reader_table[reader].lock_initialized = 1; + } +#endif /*USE_GNU_PTH*/ reader_table[reader].used = 1; reader_table[reader].is_ccid = 0; reader_table[reader].is_ctapi = 0; #ifdef HAVE_OPENSC reader_table[reader].is_osc = 0; +#endif +#ifdef NEED_PCSC_WRAPPER + reader_table[reader].pcsc.req_fd = -1; + reader_table[reader].pcsc.rsp_fd = -1; + reader_table[reader].pcsc.pid = (pid_t)(-1); #endif return reader; } @@ -370,6 +412,18 @@ close_ct_reader (int slot) return 0; } +static int +reset_ct_reader (int slot) +{ + return SW_HOST_NOT_SUPPORTED; +} + + +static int +ct_get_status (int slot, unsigned int *status) +{ + return SW_HOST_NOT_SUPPORTED; +} /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual retruned size will be @@ -397,6 +451,66 @@ ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, +#ifdef NEED_PCSC_WRAPPER +static int +writen (int fd, const void *buf, size_t nbytes) +{ + size_t nleft = nbytes; + int nwritten; + +/* log_printhex (" writen:", buf, nbytes); */ + + while (nleft > 0) + { +#ifdef USE_GNU_PTH + nwritten = pth_write (fd, buf, nleft); +#else + nwritten = write (fd, buf, nleft); +#endif + if (nwritten < 0 && errno == EINTR) + continue; + if (nwritten < 0) + return -1; + nleft -= nwritten; + buf = (const char*)buf + nwritten; + } + return 0; +} + +/* Read up to BUFLEN bytes from FD and return the number of bytes + actually read in NREAD. Returns -1 on error or 0 on success. */ +static int +readn (int fd, void *buf, size_t buflen, size_t *nread) +{ + size_t nleft = buflen; + int n; +/* void *orig_buf = buf; */ + + while (nleft > 0) + { +#ifdef USE_GNU_PTH + n = pth_read (fd, buf, nleft); +#else + n = read (fd, buf, nleft); +#endif + if (n < 0 && errno == EINTR) + continue; + if (n < 0) + return -1; /* read error. */ + if (!n) + break; /* EOF */ + nleft -= n; + buf = (char*)buf + n; + } + if (nread) + *nread = buflen - nleft; + +/* log_printhex (" readn:", orig_buf, *nread); */ + + return 0; +} +#endif /*NEED_PCSC_WRAPPER*/ + static const char * pcsc_error_string (long err) { @@ -457,6 +571,172 @@ pcsc_error_string (long err) static int open_pcsc_reader (const char *portstr) { +#ifdef NEED_PCSC_WRAPPER +/* Open the PC/SC reader using the pcsc_wrapper program. This is + needed to cope with different thread models and other peculiarities + of libpcsclite. */ + int slot; + reader_table_t slotp; + int fd, rp[2], wp[2]; + int n, i; + pid_t pid; + size_t len; + unsigned char msgbuf[9]; + int err; + + slot = new_reader_slot (); + if (slot == -1) + return -1; + slotp = reader_table + slot; + + /* Fire up the pcsc wrapper. We don't use any fork/exec code from + the common directy but implement it direclty so that this file + may still be source copied. */ + + if (pipe (rp) == -1) + { + log_error ("error creating a pipe: %s\n", strerror (errno)); + slotp->used = 0; + return -1; + } + if (pipe (wp) == -1) + { + log_error ("error creating a pipe: %s\n", strerror (errno)); + close (rp[0]); + close (rp[1]); + slotp->used = 0; + return -1; + } + + pid = fork (); + if (pid == -1) + { + log_error ("error forking process: %s\n", strerror (errno)); + close (rp[0]); + close (rp[1]); + close (wp[0]); + close (wp[1]); + slotp->used = 0; + return -1; + } + slotp->pcsc.pid = pid; + + if (!pid) + { /* + === Child === + */ + + /* Double fork. */ + pid = fork (); + if (pid == -1) + _exit (31); + if (pid) + _exit (0); /* Immediate exit this parent, so that the child + gets cleaned up by the init process. */ + + /* Connect our pipes. */ + if (wp[0] != 0 && dup2 (wp[0], 0) == -1) + log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); + if (rp[1] != 1 && dup2 (rp[1], 1) == -1) + log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); + + /* Send stderr to the bit bucket. */ + fd = open ("/dev/null", O_WRONLY); + if (fd == -1) + log_fatal ("can't open `/dev/null': %s", strerror (errno)); + if (fd != 2 && dup2 (fd, 2) == -1) + log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); + + /* Close all other files. */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=3; i < n; i++) + close(i); + errno = 0; + + execl (GNUPG_LIBDIR "/pcsc-wrapper", + "pcsc-wrapper", + "--", + "1", /* API version */ + opt.pcsc_driver, /* Name of the PC/SC library. */ + NULL); + _exit (31); + } + + /* + === Parent === + */ + close (wp[0]); + close (rp[1]); + slotp->pcsc.req_fd = wp[1]; + slotp->pcsc.rsp_fd = rp[0]; + + /* Wait for the intermediate child to terminate. */ + while ( (i=pth_waitpid (pid, NULL, 0)) == -1 && errno == EINTR) + ; + + /* Now send the open request. */ + msgbuf[0] = 0x01; /* OPEN command. */ + len = portstr? strlen (portstr):0; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) + || (portstr && writen (slotp->pcsc.req_fd, portstr, len))) + { + log_error ("error sending PC/SC OPEN request: %s\n", + strerror (errno)); + goto command_failed; + } + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC OPEN response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + if (len > DIM (slotp->atr)) + { + log_error ("PC/SC returned a too large ATR (len=%x)\n", len); + goto command_failed; + } + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + { + log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err)); + goto command_failed; + } + n = len; + if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n) + { + log_error ("error receiving PC/SC OPEN response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + slotp->atrlen = len; + + dump_reader_status (slot); + return slot; + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return -1; +#else /*!NEED_PCSC_WRAPPER */ long err; int slot; char *list = NULL; @@ -559,9 +839,16 @@ open_pcsc_reader (const char *portstr) dump_reader_status (slot); return slot; +#endif /*!NEED_PCSC_WRAPPER */ } +static int +pcsc_get_status (int slot, unsigned int *status) +{ + return SW_HOST_NOT_SUPPORTED; +} + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be set to BUFLEN. Returns: CT API error code. */ @@ -569,6 +856,108 @@ static int pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, unsigned char *buffer, size_t *buflen) { +#ifdef NEED_PCSC_WRAPPER + long err; + reader_table_t slotp; + size_t len, full_len; + int i, n; + unsigned char msgbuf[9]; + + if (DBG_CARD_IO) + log_printhex (" PCSC_data:", apdu, apdulen); + + slotp = reader_table + slot; + + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 + || slotp->pcsc.pid == (pid_t)(-1) ) + { + log_error ("pcsc_send_apdu: pcsc-wrapper not running\n"); + return -1; + } + + msgbuf[0] = 0x03; /* TRANSMIT command. */ + len = apdulen; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) + || writen (slotp->pcsc.req_fd, apdu, len)) + { + log_error ("error sending PC/SC TRANSMIT request: %s\n", + strerror (errno)); + goto command_failed; + } + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + { + log_error ("pcsc_transmit failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return -1; + } + + full_len = len; + + n = *buflen < len ? *buflen : len; + if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) + { + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + *buflen = n; + full_len -= len; + if (full_len) + { + log_error ("pcsc_send_apdu: provided buffer too short - truncated\n"); + err = -1; + } + /* We need to read any rest of the response, to keep the + protocol runnng. */ + while (full_len) + { + unsigned char dummybuf[128]; + + n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf); + if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n) + { + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + full_len -= n; + } + + return err; + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return -1; + +#else /*!NEED_PCSC_WRAPPER*/ + long err; struct pcsc_io_request_s send_pci; unsigned long recv_len; @@ -591,14 +980,87 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, pcsc_error_string (err), err); return err? -1:0; /* FIXME: Return appropriate error code. */ +#endif /*!NEED_PCSC_WRAPPER*/ } + static int close_pcsc_reader (int slot) { +#ifdef NEED_PCSC_WRAPPER + long err; + reader_table_t slotp; + size_t len; + int i; + unsigned char msgbuf[9]; + + slotp = reader_table + slot; + + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 + || slotp->pcsc.pid == (pid_t)(-1) ) + { + log_error ("close_pcsc_reader: pcsc-wrapper not running\n"); + return 0; + } + + msgbuf[0] = 0x02; /* CLOSE command. */ + len = 0; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) ) + { + log_error ("error sending PC/SC CLOSE request: %s\n", + strerror (errno)); + goto command_failed; + } + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC CLOSE response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + log_error ("pcsc_close failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + + /* We will the wrapper in any case - errors are merely + informational. */ + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return 0; + +#else /*!NEED_PCSC_WRAPPER*/ + pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; return 0; +#endif /*!NEED_PCSC_WRAPPER*/ +} + +static int +reset_pcsc_reader (int slot) +{ + return SW_HOST_NOT_SUPPORTED; } @@ -661,6 +1123,46 @@ close_ccid_reader (int slot) } +static int +reset_ccid_reader (int slot) +{ + int err; + reader_table_t slotp = reader_table + slot; + unsigned char atr[33]; + size_t atrlen; + + err = ccid_get_atr (slotp->ccid.handle, atr, sizeof atr, &atrlen); + if (err) + return -1; + /* If the reset was successful, update the ATR. */ + assert (sizeof slotp->atr >= sizeof atr); + slotp->atrlen = atrlen; + memcpy (slotp->atr, atr, atrlen); + dump_reader_status (slot); + return 0; +} + + +static int +get_status_ccid (int slot, unsigned int *status) +{ + int rc; + int bits; + + rc = ccid_slot_status (reader_table[slot].ccid.handle, &bits); + if (rc) + return -1; + + if (bits == 0) + *status = 1|2|4; + else if (bits == 1) + *status = 2; + else + *status = 0; + + return 0; +} + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be @@ -798,6 +1300,18 @@ close_osc_reader (int slot) return 0; } +static int +reset_osc_reader (int slot) +{ + return SW_HOST_NOT_SUPPORTED; +} + + +static int +ocsc_get_status (int slot, unsigned int *status) +{ + return SW_HOST_NOT_SUPPORTED; +} /* Actually send the APDU of length APDULEN to SLOT and return a @@ -896,6 +1410,45 @@ osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, Driver Access */ + +static int +lock_slot (int slot) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&reader_table[slot].lock, 0, NULL)) + { + log_error ("failed to acquire apdu lock: %s\n", strerror (errno)); + return SW_HOST_LOCKING_FAILED; + } +#endif /*USE_GNU_PTH*/ + return 0; +} + +static int +trylock_slot (int slot) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_acquire (&reader_table[slot].lock, TRUE, NULL)) + { + if (errno == EBUSY) + return SW_HOST_BUSY; + log_error ("failed to acquire apdu lock: %s\n", strerror (errno)); + return SW_HOST_LOCKING_FAILED; + } +#endif /*USE_GNU_PTH*/ + return 0; +} + +static void +unlock_slot (int slot) +{ +#ifdef USE_GNU_PTH + if (!pth_mutex_release (&reader_table[slot].lock)) + log_error ("failed to release apdu lock: %s\n", strerror (errno)); +#endif /*USE_GNU_PTH*/ +} + + /* Open the reader and return an internal slot number or -1 on error. If PORTSTR is NULL we default to a suitable port (for ctAPI: the first USB reader. For PC/SC the first listed reader). If @@ -937,7 +1490,7 @@ apdu_open_reader (const char *portstr) handle = dlopen (opt.ctapi_driver, RTLD_LAZY); if (!handle) { - log_error ("apdu_open_reader: failed to open driver: %s", + log_error ("apdu_open_reader: failed to open driver: %s\n", dlerror ()); return -1; } @@ -959,12 +1512,13 @@ apdu_open_reader (const char *portstr) /* No ctAPI configured, so lets try the PC/SC API */ if (!pcsc_api_loaded) { +#ifndef NEED_PCSC_WRAPPER void *handle; handle = dlopen (opt.pcsc_driver, RTLD_LAZY); if (!handle) { - log_error ("apdu_open_reader: failed to open driver `%s': %s", + log_error ("apdu_open_reader: failed to open driver `%s': %s\n", opt.pcsc_driver, dlerror ()); return -1; } @@ -1020,9 +1574,10 @@ apdu_open_reader (const char *portstr) dlclose (handle); return -1; } +#endif /*!NEED_PCSC_WRAPPER*/ pcsc_api_loaded = 1; } - + return open_pcsc_reader (portstr); } @@ -1046,6 +1601,47 @@ apdu_close_reader (int slot) return close_pcsc_reader (slot); } +/* Enumerate all readers and return information on whether this reader + is in use. The caller should start with SLOT set to 0 and + increment it with each call until an error is returned. */ +int +apdu_enum_reader (int slot, int *used) +{ + if (slot < 0 || slot >= MAX_READER) + return SW_HOST_NO_DRIVER; + *used = reader_table[slot].used; + return 0; +} + +/* Do a reset for the card in reader at SLOT. */ +int +apdu_reset (int slot) +{ + int sw; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if ((sw = lock_slot (slot))) + return sw; + + if (reader_table[slot].is_ctapi) + sw = reset_ct_reader (slot); +#ifdef HAVE_LIBUSB + else if (reader_table[slot].is_ccid) + sw = reset_ccid_reader (slot); +#endif +#ifdef HAVE_OPENSC + else if (reader_table[slot].is_osc) + sw = reset_osc_reader (slot); +#endif + else + sw = reset_pcsc_reader (slot); + + unlock_slot (slot); + return sw; +} + unsigned char * apdu_get_atr (int slot, size_t *atrlen) @@ -1062,6 +1658,7 @@ apdu_get_atr (int slot, size_t *atrlen) *atrlen = reader_table[slot].atrlen; return buf; } + static const char * @@ -1084,7 +1681,62 @@ error_string (int slot, long rc) } -/* Dispatcher for the actual send_apdu fucntion. */ +/* Retrieve the status for SLOT. The function does obnly wait fot the + card to become available if HANG is set to true. On success the + bits in STATUS will be set to + + bit 0 = card present and usable + bit 1 = card present + bit 2 = card active + bit 3 = card access locked [not yet implemented] + + For must application, tetsing bit 0 is sufficient. + + CHANGED will receive the value of the counter tracking the number + of card insertions. This value may be used to detect a card + change. +*/ +int +apdu_get_status (int slot, int hang, + unsigned int *status, unsigned int *changed) +{ + int sw; + unsigned int s; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if ((sw = hang? lock_slot (slot) : trylock_slot (slot))) + return sw; + + if (reader_table[slot].is_ctapi) + sw = ct_get_status (slot, &s); +#ifdef HAVE_LIBUSB + else if (reader_table[slot].is_ccid) + sw = get_status_ccid (slot, &s); +#endif +#ifdef HAVE_OPENSC + else if (reader_table[slot].is_osc) + sw = osc_get_status (slot, &s); +#endif + else + sw = pcsc_get_status (slot, &s); + + unlock_slot (slot); + + if (sw) + return sw; + + if (status) + *status = s; + if (changed) + *changed = reader_table[slot].change_counter; + return 0; +} + + +/* Dispatcher for the actual send_apdu function. Note, that this + function should be called in locked state. */ static int send_apdu (int slot, unsigned char *apdu, size_t apdulen, unsigned char *buffer, size_t *buflen) @@ -1126,6 +1778,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, int sw; long rc; /* we need a long here due to PC/SC. */ + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + if (DBG_CARD_IO) log_debug ("send apdu: c=%02X i=%02X p0=%02X p1=%02X lc=%d le=%d\n", class, ins, p0, p1, lc, le); @@ -1137,6 +1792,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, if ((!data && lc != -1) || (data && lc == -1)) return SW_HOST_INV_VALUE; + if ((sw = lock_slot (slot))) + return sw; + apdulen = 0; apdu[apdulen++] = class; apdu[apdulen++] = ins; @@ -1158,6 +1816,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, { log_error ("apdu_send_simple(%d) failed: %s\n", slot, error_string (slot, rc)); + unlock_slot (slot); return SW_HOST_INCOMPLETE_CARD_RESPONSE; } sw = (result[resultlen-2] << 8) | result[resultlen-1]; @@ -1176,7 +1835,10 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, { *retbuf = xtrymalloc (resultlen? resultlen : 1); if (!*retbuf) - return SW_HOST_OUT_OF_CORE; + { + unlock_slot (slot); + return SW_HOST_OUT_OF_CORE; + } *retbuflen = resultlen; memcpy (*retbuf, result, resultlen); } @@ -1192,7 +1854,10 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, { *retbuf = p = xtrymalloc (bufsize); if (!*retbuf) - return SW_HOST_OUT_OF_CORE; + { + unlock_slot (slot); + return SW_HOST_OUT_OF_CORE; + } assert (resultlen < bufsize); memcpy (p, result, resultlen); p += resultlen; @@ -1216,6 +1881,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, { log_error ("apdu_send_simple(%d) for get response failed: %s\n", slot, error_string (slot, rc)); + unlock_slot (slot); return SW_HOST_INCOMPLETE_CARD_RESPONSE; } sw = (result[resultlen-2] << 8) | result[resultlen-1]; @@ -1236,7 +1902,10 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, bufsize += resultlen > 4096? resultlen: 4096; tmp = xtryrealloc (*retbuf, bufsize); if (!tmp) - return SW_HOST_OUT_OF_CORE; + { + unlock_slot (slot); + return SW_HOST_OUT_OF_CORE; + } p = tmp + (p - *retbuf); *retbuf = tmp; } @@ -1259,6 +1928,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, *retbuf = tmp; } } + + unlock_slot (slot); + if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS) log_printhex (" dump: ", *retbuf, *retbuflen); diff --git a/scd/apdu.h b/scd/apdu.h index fd7634f13..f74bab7fe 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -48,9 +48,12 @@ enum { those values can't be issued by a card. */ SW_HOST_OUT_OF_CORE = 0x10001, /* No way yet to differentiate between errnos on a failed malloc. */ - SW_HOST_INV_VALUE = 0x10002, + SW_HOST_INV_VALUE = 0x10002, SW_HOST_INCOMPLETE_CARD_RESPONSE = 0x10003, - SW_HOST_NO_DRIVER = 0x10004 + SW_HOST_NO_DRIVER = 0x10004, + SW_HOST_NOT_SUPPORTED = 0x10005, + SW_HOST_LOCKING_FAILED= 0x10006, + SW_HOST_BUSY = 0x10007 }; @@ -58,10 +61,14 @@ enum { /* Note , that apdu_open_reader returns no status word but -1 on error. */ int apdu_open_reader (const char *portstr); int apdu_close_reader (int slot); +int apdu_enum_reader (int slot, int *used); unsigned char *apdu_get_atr (int slot, size_t *atrlen); /* The apdu send functions do return status words. */ +int apdu_reset (int slot); +int apdu_get_status (int slot, int hang, + unsigned int *status, unsigned int *changed); int apdu_send_simple (int slot, int class, int ins, int p0, int p1, int lc, const char *data); int apdu_send (int slot, int class, int ins, int p0, int p1, diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index b398e3ce3..1c8167869 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1,5 +1,5 @@ /* ccid-driver.c - USB ChipCardInterfaceDevices driver - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * Written by Werner Koch. * * This file is part of GnuPG. @@ -108,7 +108,10 @@ /* Disable all debugging output for now. */ #undef DBG_CARD_IO -#define DBG_CARD_IO 0 +#define DBG_CARD_IO 1 + +/* Define to print information pertaining the T=1 protocol. */ +#undef DEBUG_T1 # define DEBUGOUT(t) do { if (DBG_CARD_IO) \ @@ -145,8 +148,6 @@ #endif /* This source not used by scdaemon. */ -/* Define to print information pertaining the T=1 protocol. */ -#undef DEBUG_T1 @@ -184,9 +185,15 @@ struct ccid_driver_s { int seqno; unsigned char t1_ns; unsigned char t1_nr; + int nonnull_nad; + int auto_ifsd; + int max_ifsd; + int ifsd; }; +static unsigned int compute_edc (const unsigned char *data, size_t datalen, + int use_crc); static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen); static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, size_t *nread, int expected_type, int seqno); @@ -220,13 +227,18 @@ set_msg_len (unsigned char *msg, unsigned int length) Note, that this code is based on the one in lsusb.c of the usb-utils package, I wrote on 2003-09-01. -wk. */ static int -parse_ccid_descriptor (const unsigned char *buf, size_t buflen) +parse_ccid_descriptor (ccid_driver_t handle, + const unsigned char *buf, size_t buflen) { unsigned int i; unsigned int us; int have_t1 = 0, have_tpdu=0, have_auto_conf = 0; + handle->nonnull_nad = 0; + handle->auto_ifsd = 0; + handle->max_ifsd = 32; + handle->ifsd = 0; if (buflen < 54 || buf[0] < 54) { DEBUGOUT ("CCID device descriptor is too short\n"); @@ -272,6 +284,7 @@ parse_ccid_descriptor (const unsigned char *buf, size_t buflen) us = convert_le_u32(buf+28); DEBUGOUT_1 (" dwMaxIFSD %5u\n", us); + handle->max_ifsd = us; us = convert_le_u32(buf+32); DEBUGOUT_1 (" dwSyncProtocols %08X ", us); @@ -320,9 +333,15 @@ parse_ccid_descriptor (const unsigned char *buf, size_t buflen) if ((us & 0x0100)) DEBUGOUT (" CCID can set ICC in clock stop mode\n"); if ((us & 0x0200)) - DEBUGOUT (" NAD value other than 0x00 accpeted\n"); + { + DEBUGOUT (" NAD value other than 0x00 accepted\n"); + handle->nonnull_nad = 1; + } if ((us & 0x0400)) - DEBUGOUT (" Auto IFSD exchange\n"); + { + DEBUGOUT (" Auto IFSD exchange\n"); + handle->auto_ifsd = 1; + } if ((us & 0x00010000)) { @@ -389,7 +408,7 @@ parse_ccid_descriptor (const unsigned char *buf, size_t buflen) that the device is usable for us. Returns 0 on success or an error code. */ static int -read_device_info (struct usb_device *dev) +read_device_info (ccid_driver_t handle, struct usb_device *dev) { int cfg_no; @@ -414,8 +433,9 @@ read_device_info (struct usb_device *dev) { if (ifcdesc->extra) { - if (!parse_ccid_descriptor (ifcdesc->extra, - ifcdesc->extralen)) + if (!parse_ccid_descriptor (handle, + ifcdesc->extra, + ifcdesc->extralen)) return 0; /* okay. we can use it. */ } } @@ -458,10 +478,22 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) dev->descriptor->idVendor, dev->descriptor->idProduct); if (!readerno) { - rc = read_device_info (dev); + *handle = calloc (1, sizeof **handle); + if (!*handle) + { + DEBUGOUT ("out of memory\n"); + rc = -1; + free (*handle); + *handle = NULL; + goto leave; + } + + rc = read_device_info (*handle, dev); if (rc) { DEBUGOUT ("device not supported\n"); + free (*handle); + *handle = NULL; goto leave; } @@ -469,6 +501,8 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) if (rc) { DEBUGOUT_1 ("usb_open failed: %d\n", rc); + free (*handle); + *handle = NULL; goto leave; } @@ -479,16 +513,11 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) if (rc) { DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + free (*handle); + *handle = NULL; goto leave; } - *handle = calloc (1, sizeof **handle); - if (!*handle) - { - DEBUGOUT ("out of memory\n"); - rc = -1; - goto leave; - } (*handle)->idev = idev; idev = NULL; /* FIXME: Do we need to get the endpoint addresses from the @@ -508,7 +537,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) usb_free_match (match); if (!rc && !*handle) - rc = -1; /* In case we didn't enter the while lool at all. */ + rc = -1; /* In case we didn't enter the while loop at all. */ return rc; } @@ -592,6 +621,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, int i, rc; size_t msglen; + retry: rc = usb_bulk_read (handle->idev, 0x82, buffer, length, @@ -628,6 +658,14 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, return -1; } + if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80) + { + /* Card present and active, time extension requested. */ + DEBUGOUT_2 ("time extension requested (%02X,%02X)\n", + buffer[7], buffer[8]); + goto retry; + } + DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n" " data:", buffer[7], buffer[8], buffer[9] ); for (i=10; i < msglen; i++) @@ -695,7 +733,7 @@ ccid_poll (ccid_driver_t handle) int -ccid_slot_status (ccid_driver_t handle) +ccid_slot_status (ccid_driver_t handle, int *statusbits) { int rc; unsigned char msg[100]; @@ -716,6 +754,7 @@ ccid_slot_status (ccid_driver_t handle) rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno); if (rc) return rc; + *statusbits = (msg[7] & 3); return 0; } @@ -727,8 +766,12 @@ ccid_get_atr (ccid_driver_t handle, { int rc; unsigned char msg[100]; - size_t msglen; + unsigned char *tpdu; + size_t msglen, tpdulen; unsigned char seqno; + int use_crc = 0; + unsigned int edc; + int i; msg[0] = PC_to_RDR_IccPowerOn; msg[5] = 0; /* slot */ @@ -756,11 +799,135 @@ ccid_get_atr (ccid_driver_t handle, *atrlen = n; } + /* Setup parameters to select T=1. */ + msg[0] = PC_to_RDR_SetParameters; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 1; /* Select T=1. */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + + /* FIXME: Get those values from the ATR. */ + msg[10]= 0x01; /* Fi/Di */ + msg[11]= 0x10; /* LRC, direct convention. */ + msg[12]= 0; /* Extra guardtime. */ + msg[13]= 0x41; /* BWI/CWI */ + msg[14]= 0; /* No clock stoppping. */ + msg[15]= 254; /* IFSC */ + msg[16]= 0; /* Does not support non default NAD values. */ + set_msg_len (msg, 7); + msglen = 10 + 7; + + DEBUGOUT ("sending"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + /* Note that we ignore the error code on purpose. */ + bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno); + + + /* Send an S-Block with our maximun IFSD to the CCID. */ + if (!handle->auto_ifsd) + { + tpdu = msg+10; + /* NAD: DAD=1, SAD=0 */ + tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; + tpdu[1] = (0xc0 | 0 | 1); /* S-block request: change IFSD */ + tpdu[2] = 1; + tpdu[3] = handle->max_ifsd? handle->max_ifsd : 32; + tpdulen = 4; + edc = compute_edc (tpdu, tpdulen, use_crc); + if (use_crc) + tpdu[tpdulen++] = (edc >> 8); + tpdu[tpdulen++] = edc; + + msg[0] = PC_to_RDR_XfrBlock; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, tpdulen); + msglen = 10 + tpdulen; + + DEBUGOUT ("sending"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + +#ifdef DEBUG_T1 + fprintf (stderr, "T1: put %c-block seq=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); +#endif + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + + /* Fixme: The next line for the current Valgrid without support + for USB IOCTLs. */ + memset (msg, 0, sizeof msg); + + rc = bulk_in (handle, msg, sizeof msg, &msglen, + RDR_to_PC_DataBlock, seqno); + if (rc) + return rc; + + tpdu = msg + 10; + tpdulen = msglen - 10; + + if (tpdulen < 4) + { + DEBUGOUT ("cannot yet handle short blocks!\n"); + return -1; + } + +#ifdef DEBUG_T1 + fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 + ); +#endif + if ((tpdu[1] & 0xe0) != 0xe0 || tpdu[2] != 1) + { + DEBUGOUT ("invalid response for S-block (Change-IFSD)\n"); + return -1; + } + DEBUGOUT_1 ("IFSD has been set to %d\n", tpdu[3]); + } + return 0; } + +static unsigned int +compute_edc (const unsigned char *data, size_t datalen, int use_crc) +{ + if (use_crc) + { + return 0x42; /* Not yet implemented. */ + } + else + { + unsigned char crc = 0; + + for (; datalen; datalen--) + crc ^= *data++; + return crc; + } +} + + /* Protocol T=1 overview @@ -819,17 +986,19 @@ ccid_transceive (ccid_driver_t handle, unsigned char *resp, size_t maxresplen, size_t *nresp) { int rc; - unsigned char send_buffer[10+258], recv_buffer[10+258]; + unsigned char send_buffer[10+259], recv_buffer[10+259]; const unsigned char *apdu; size_t apdulen; unsigned char *msg, *tpdu, *p; - size_t msglen, tpdulen, n; + size_t msglen, tpdulen, last_tpdulen, n; unsigned char seqno; int i; - unsigned char crc; + unsigned int edc; + int use_crc = 0; size_t dummy_nresp; int next_chunk = 1; int sending = 1; + int retries = 0; if (!nresp) nresp = &dummy_nresp; @@ -852,7 +1021,8 @@ ccid_transceive (ccid_driver_t handle, return -1; /* Invalid length. */ tpdu = msg+10; - tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + /* NAD: DAD=1, SAD=0 */ + tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; tpdu[1] = ((handle->t1_ns & 1) << 6); /* I-block */ if (apdulen > 128 /* fixme: replace by ifsc */) { @@ -863,12 +1033,11 @@ ccid_transceive (ccid_driver_t handle, } tpdu[2] = apdulen; memcpy (tpdu+3, apdu, apdulen); - crc = 0; - for (i=0,p=tpdu; i < apdulen+3; i++) - crc ^= *p++; - tpdu[3+apdulen] = crc; - - tpdulen = apdulen + 4; + tpdulen = 3 + apdulen; + edc = compute_edc (tpdu, tpdulen, use_crc); + if (use_crc) + tpdu[tpdulen++] = (edc >> 8); + tpdu[tpdulen++] = edc; } msg[0] = PC_to_RDR_XfrBlock; @@ -879,6 +1048,7 @@ ccid_transceive (ccid_driver_t handle, msg[9] = 0; /* RFU */ set_msg_len (msg, tpdulen); msglen = 10 + tpdulen; + last_tpdulen = tpdulen; DEBUGOUT ("sending"); for (i=0; i < msglen; i++) @@ -926,7 +1096,7 @@ ccid_transceive (ccid_driver_t handle, if (!(tpdu[1] & 0x80)) { /* This is an I-block. */ - + retries = 0; if (sending) { /* last block sent was successful. */ handle->t1_ns ^= 1; @@ -937,13 +1107,15 @@ ccid_transceive (ccid_driver_t handle, { /* Reponse does not match our sequence number. */ msg = send_buffer; tpdu = msg+10; - tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + /* NAD: DAD=1, SAD=0 */ + tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; tpdu[1] = (0x80 | (handle->t1_nr & 1) << 4 | 2); /* R-block */ tpdu[2] = 0; tpdulen = 3; - for (crc=0,i=0,p=tpdu; i < tpdulen; i++) - crc ^= *p++; - tpdu[tpdulen++] = crc; + edc = compute_edc (tpdu, tpdulen, use_crc); + if (use_crc) + tpdu[tpdulen++] = (edc >> 8); + tpdu[tpdulen++] = edc; continue; } @@ -974,20 +1146,27 @@ ccid_transceive (ccid_driver_t handle, msg = send_buffer; tpdu = msg+10; - tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + /* NAD: DAD=1, SAD=0 */ + tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; tpdu[1] = (0x80 | (handle->t1_nr & 1) << 4); /* R-block */ tpdu[2] = 0; tpdulen = 3; - for (crc=0,i=0,p=tpdu; i < tpdulen; i++) - crc ^= *p++; - tpdu[tpdulen++] = crc; - + edc = compute_edc (tpdu, tpdulen, use_crc); + if (use_crc) + tpdu[tpdulen++] = (edc >> 8); + tpdu[tpdulen++] = edc; } else if ((tpdu[1] & 0xc0) == 0x80) { /* This is a R-block. */ if ( (tpdu[1] & 0x0f)) { /* Error: repeat last block */ + if (++retries > 3) + { + DEBUGOUT ("3 failed retries\n"); + return -1; + } msg = send_buffer; + tpdulen = last_tpdulen; } else if (sending && !!(tpdu[1] & 0x40) == handle->t1_ns) { /* Reponse does not match our sequence number. */ @@ -996,6 +1175,7 @@ ccid_transceive (ccid_driver_t handle, } else if (sending) { /* Send next chunk. */ + retries = 0; msg = send_buffer; next_chunk = 1; handle->t1_ns ^= 1; @@ -1008,6 +1188,7 @@ ccid_transceive (ccid_driver_t handle, } else { /* This is a S-block. */ + retries = 0; DEBUGOUT_2 ("T1 S-block %s received cmd=%d\n", (tpdu[1] & 0x20)? "response": "request", (tpdu[1] & 0x1f)); @@ -1016,14 +1197,16 @@ ccid_transceive (ccid_driver_t handle, unsigned char bwi = tpdu[3]; msg = send_buffer; tpdu = msg+10; - tpdu[0] = ((1 << 4) | 0); /* NAD: DAD=1, SAD=0 */ + /* NAD: DAD=1, SAD=0 */ + tpdu[0] = handle->nonnull_nad? ((1 << 4) | 0): 0; tpdu[1] = (0xc0 | 0x20 | 3); /* S-block response */ tpdu[2] = 1; tpdu[3] = bwi; tpdulen = 4; - for (crc=0,i=0,p=tpdu; i < tpdulen; i++) - crc ^= *p++; - tpdu[tpdulen++] = crc; + edc = compute_edc (tpdu, tpdulen, use_crc); + if (use_crc) + tpdu[tpdulen++] = (edc >> 8); + tpdu[tpdulen++] = edc; DEBUGOUT_1 ("T1 waittime extension of bwi=%d\n", bwi); } else @@ -1043,6 +1226,7 @@ main (int argc, char **argv) { int rc; ccid_driver_t ccid; + unsigned int slotstat; rc = ccid_open_reader (&ccid, 0); if (rc) @@ -1056,7 +1240,7 @@ main (int argc, char **argv) ccid_poll (ccid); fputs ("getting slot status ...\n", stderr); - rc = ccid_slot_status (ccid); + rc = ccid_slot_status (ccid, &slotstat); if (rc) return 1; diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index e33be55d9..8b86eb1a5 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -63,6 +63,7 @@ int ccid_open_reader (ccid_driver_t *handle, int readerno); int ccid_close_reader (ccid_driver_t handle); int ccid_get_atr (ccid_driver_t handle, unsigned char *atr, size_t maxatrlen, size_t *atrlen); +int ccid_slot_status (ccid_driver_t handle, int *statusbits); int ccid_transceive (ccid_driver_t handle, const unsigned char *apdu, size_t apdulen, unsigned char *resp, size_t maxresplen, size_t *nresp); diff --git a/scd/command.c b/scd/command.c index 4746e11b5..06ff6d2e2 100644 --- a/scd/command.c +++ b/scd/command.c @@ -56,14 +56,11 @@ has_option (const char *line, const char *name) } - - -/* Note, that this reset_notify is also used for cleanup purposes. */ +/* Reset the card and free the application context. With DO_CLOSE set + to true, close the reader and don't do just a reset. */ static void -reset_notify (ASSUAN_CONTEXT ctx) +do_reset (ctrl_t ctrl, int do_close) { - CTRL ctrl = assuan_get_pointer (ctx); - if (ctrl->card_ctx) { card_close (ctrl->card_ctx); @@ -73,13 +70,28 @@ reset_notify (ASSUAN_CONTEXT ctx) } if (ctrl->app_ctx) { - int slot = ctrl->app_ctx->slot; release_application (ctrl->app_ctx); ctrl->app_ctx = NULL; - apdu_close_reader (slot); + } + if (ctrl->reader_slot != -1) + { + if (do_close || apdu_reset (ctrl->reader_slot)) + { + apdu_close_reader (ctrl->reader_slot); + ctrl->reader_slot = -1; + } } } + +static void +reset_notify (ASSUAN_CONTEXT ctx) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + do_reset (ctrl, 0); +} + static int option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) @@ -92,7 +104,7 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) function returns an Assuan error, so don't map the error a second time */ static AssuanError -open_card (CTRL ctrl, const char *apptype) +open_card (ctrl_t ctrl, const char *apptype) { int slot; @@ -101,13 +113,13 @@ open_card (CTRL ctrl, const char *apptype) if (ctrl->card_ctx) return 0; /* Already initialized using a card context. */ - slot = apdu_open_reader (opt.reader_port); + if (ctrl->reader_slot != -1) + slot = ctrl->reader_slot; + else + slot = apdu_open_reader (opt.reader_port); + ctrl->reader_slot = slot; if (slot != -1) - { - ctrl->app_ctx = select_application (ctrl, slot, apptype); - if (!ctrl->app_ctx) - apdu_close_reader (slot); - } + ctrl->app_ctx = select_application (ctrl, slot, apptype); if (!ctrl->app_ctx) { /* No application found - fall back to old mode. */ /* Note that we should rework the old code to use the @@ -1084,6 +1096,12 @@ scd_command_handler (int listen_fd) if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); + /* We open the reader right at startup so that the ticker is able to + update the status file. */ + if (ctrl.reader_slot == -1) + ctrl.reader_slot = apdu_open_reader (opt.reader_port); + + /* Command processing loop. */ for (;;) { rc = assuan_accept (ctx); @@ -1104,7 +1122,7 @@ scd_command_handler (int listen_fd) continue; } } - reset_notify (ctx); /* used for cleanup */ + do_reset (&ctrl, 1); /* Cleanup. */ assuan_deinit_server (ctx); } @@ -1156,3 +1174,22 @@ send_status_info (CTRL ctrl, const char *keyword, ...) va_end (arg_ptr); } + + +void +scd_update_reader_status_file (void) +{ + int slot; + int used; + unsigned int status, changed; + + /* Note, that we only try to get the status, becuase it does not + make sense to wait here for a operation to complete. If we are + so busy working with the card, delays in the status file updated + are should be acceptable. */ + for (slot=0; !apdu_enum_reader (slot, &used); slot++) + if (used && !apdu_get_status (slot, 0, &status, &changed)) + { + log_info ("status of slot %d is %u\n", slot, status); + } +} diff --git a/scd/iso7816.c b/scd/iso7816.c index 24361d148..fd3f0485c 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -82,6 +82,9 @@ map_sw (int sw) case SW_HOST_OUT_OF_CORE: ec = GPG_ERR_ENOMEM; break; case SW_HOST_INV_VALUE: ec = GPG_ERR_INV_VALUE; break; case SW_HOST_INCOMPLETE_CARD_RESPONSE: ec = GPG_ERR_CARD; break; + case SW_HOST_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break; + case SW_HOST_LOCKING_FAILED: ec = GPG_ERR_BUG; break; + case SW_HOST_BUSY: ec = GPG_ERR_EBUSY; break; default: if ((sw & 0x010000)) ec = GPG_ERR_GENERAL; /* Should not happen. */ diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c new file mode 100644 index 000000000..4f47ee95c --- /dev/null +++ b/scd/pcsc-wrapper.c @@ -0,0 +1,631 @@ +/* pcsc-wrapper.c - Wrapper for ccessing the PC/SC service + * Copyright (C) 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 + */ + +/* + This wrapper is required to handle problems with the libpscslite + library. That library assumes that pthreads are used and fails + badly if one tries to use it with a procerss using Pth. + + The operation model is pretty simple: It reads requests from stdin + and returns the answer on stdout. There is no direct mapping to the + pcsc interface but to a higher level one which resembles the code + used in scdaemon (apdu.c) when not using Pth or while running under + Windows. + + The interface is binary consisting of a command tag and the length + of the parameter list. The calling process needs to pass the + version number of the interface on the command line to make sure + that both agree on the same interface. For each port a separate + instance of this process needs to be started. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <assert.h> +#include <dlfcn.h> + + +#define PGM "pcsc-wrapper" + +/* Allow for a standalone build. */ +#ifdef VERSION +#define MYVERSION_LINE PGM " (GnuPG) " VERSION +#define BUGREPORT_LINE "\nReport bugs to <bug-gnupg@gnu.org>.\n" +#else +#define MYVERSION_LINE PGM +#define BUGREPORT_LINE "" +#endif + +#define DEFAULT_PCSC_DRIVER "libpcsclite.so" + + +static int verbose; + + +/* PC/SC constants and function pointer. */ +#define PCSC_SCOPE_USER 0 +#define PCSC_SCOPE_TERMINAL 1 +#define PCSC_SCOPE_SYSTEM 2 +#define PCSC_SCOPE_GLOBAL 3 + +#define PCSC_PROTOCOL_T0 1 +#define PCSC_PROTOCOL_T1 2 +#define PCSC_PROTOCOL_RAW 4 + +#define PCSC_SHARE_EXCLUSIVE 1 +#define PCSC_SHARE_SHARED 2 +#define PCSC_SHARE_DIRECT 3 + +#define PCSC_LEAVE_CARD 0 +#define PCSC_RESET_CARD 1 +#define PCSC_UNPOWER_CARD 2 +#define PCSC_EJECT_CARD 3 + +struct pcsc_io_request_s { + unsigned long protocol; + unsigned long pci_len; +}; + +typedef struct pcsc_io_request_s *pcsc_io_request_t; + + +static int driver_is_open; /* True if the PC/SC driver has been + initialzied and is ready for + operations. The follwoing variables + are then valid. */ +static unsigned long pcsc_context; /* The current PC/CS context. */ +static unsigned long pcsc_card; +static unsigned long pcsc_protocol; +static unsigned char current_atr[33]; +static size_t current_atrlen; + +long (* pcsc_establish_context) (unsigned long scope, + const void *reserved1, + const void *reserved2, + unsigned long *r_context); +long (* pcsc_release_context) (unsigned long context); +long (* pcsc_list_readers) (unsigned long context, + const char *groups, + char *readers, unsigned long*readerslen); +long (* pcsc_connect) (unsigned long context, + const char *reader, + unsigned long share_mode, + unsigned long preferred_protocols, + unsigned long *r_card, + unsigned long *r_active_protocol); +long (* pcsc_disconnect) (unsigned long card, + unsigned long disposition); +long (* pcsc_status) (unsigned long card, + char *reader, unsigned long *readerlen, + unsigned long *r_state, + unsigned long *r_protocol, + unsigned char *atr, unsigned long *atrlen); +long (* pcsc_begin_transaction) (unsigned long card); +long (* pcsc_end_transaction) (unsigned long card); +long (* pcsc_transmit) (unsigned long card, + const pcsc_io_request_t send_pci, + const unsigned char *send_buffer, + unsigned long send_len, + pcsc_io_request_t recv_pci, + unsigned char *recv_buffer, + unsigned long *recv_len); +long (* pcsc_set_timeout) (unsigned long context, + unsigned long timeout); + + + +static void +bad_request (const char *type) +{ + fprintf (stderr, PGM ": bad `%s' request\n", type); + exit (1); +} + +static void +request_failed (int err) +{ + if (!err) + err = -1; + + putchar (0x81); /* Simple error/success response. */ + + putchar (0); + putchar (0); + putchar (0); + putchar (4); + + putchar ((err >> 24) & 0xff); + putchar ((err >> 16) & 0xff); + putchar ((err >> 8) & 0xff); + putchar ((err ) & 0xff); + + fflush (stdout); +} + + +static void +request_succeeded (const void *buffer, size_t buflen) +{ + size_t len; + + putchar (0x81); /* Simple error/success response. */ + + len = 4 + buflen; + putchar ((len >> 24) & 0xff); + putchar ((len >> 16) & 0xff); + putchar ((len >> 8) & 0xff); + putchar ((len ) & 0xff); + + /* Error code. */ + putchar (0); + putchar (0); + putchar (0); + putchar (0); + + /* Optional reponse string. */ + if (buffer) + fwrite (buffer, buflen, 1, stdout); + + fflush (stdout); +} + + + +static unsigned long +read_32 (FILE *fp) +{ + int c1, c2, c3, c4; + + c1 = getc (stdin); + c2 = getc (stdin); + c3 = getc (stdin); + c4 = getc (stdin); + if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF) + { + fprintf (stderr, PGM ": premature EOF while parsing request\n"); + exit (1); + } + return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4; +} + + + +static const char * +pcsc_error_string (long err) +{ + const char *s; + + if (!err) + return "okay"; + if ((err & 0x80100000) != 0x80100000) + return "invalid PC/SC error code"; + err &= 0xffff; + switch (err) + { + case 0x0002: s = "cancelled"; break; + case 0x000e: s = "can't dispose"; break; + case 0x0008: s = "insufficient buffer"; break; + case 0x0015: s = "invalid ATR"; break; + case 0x0003: s = "invalid handle"; break; + case 0x0004: s = "invalid parameter"; break; + case 0x0005: s = "invalid target"; break; + case 0x0011: s = "invalid value"; break; + case 0x0006: s = "no memory"; break; + case 0x0013: s = "comm error"; break; + case 0x0001: s = "internal error"; break; + case 0x0014: s = "unknown error"; break; + case 0x0007: s = "waited too long"; break; + case 0x0009: s = "unknown reader"; break; + case 0x000a: s = "timeout"; break; + case 0x000b: s = "sharing violation"; break; + case 0x000c: s = "no smartcard"; break; + case 0x000d: s = "unknown card"; break; + case 0x000f: s = "proto mismatch"; break; + case 0x0010: s = "not ready"; break; + case 0x0012: s = "system cancelled"; break; + case 0x0016: s = "not transacted"; break; + case 0x0017: s = "reader unavailable"; break; + case 0x0065: s = "unsupported card"; break; + case 0x0066: s = "unresponsive card"; break; + case 0x0067: s = "unpowered card"; break; + case 0x0068: s = "reset card"; break; + case 0x0069: s = "removed card"; break; + case 0x006a: s = "inserted card"; break; + case 0x001f: s = "unsupported feature"; break; + case 0x0019: s = "PCI too small"; break; + case 0x001a: s = "reader unsupported"; break; + case 0x001b: s = "duplicate reader"; break; + case 0x001c: s = "card unsupported"; break; + case 0x001d: s = "no service"; break; + case 0x001e: s = "service stopped"; break; + default: s = "unknown PC/SC error code"; break; + } + return s; +} + +static void +load_pcsc_driver (const char *libname) +{ + void *handle; + + handle = dlopen (libname, RTLD_LAZY); + if (!handle) + { + fprintf (stderr, PGM ": failed to open driver `%s': %s", + libname, dlerror ()); + exit (1); + } + + pcsc_establish_context = dlsym (handle, "SCardEstablishContext"); + pcsc_release_context = dlsym (handle, "SCardReleaseContext"); + pcsc_list_readers = dlsym (handle, "SCardListReaders"); + pcsc_connect = dlsym (handle, "SCardConnect"); + pcsc_disconnect = dlsym (handle, "SCardDisconnect"); + pcsc_status = dlsym (handle, "SCardStatus"); + pcsc_begin_transaction = dlsym (handle, "SCardBeginTransaction"); + pcsc_end_transaction = dlsym (handle, "SCardEndTransaction"); + pcsc_transmit = dlsym (handle, "SCardTransmit"); + pcsc_set_timeout = dlsym (handle, "SCardSetTimeout"); + + if (!pcsc_establish_context + || !pcsc_release_context + || !pcsc_list_readers + || !pcsc_connect + || !pcsc_disconnect + || !pcsc_status + || !pcsc_begin_transaction + || !pcsc_end_transaction + || !pcsc_transmit + /* || !pcsc_set_timeout */) + { + /* Note that set_timeout is currently not used and also not + available under Windows. */ + fprintf (stderr, + "apdu_open_reader: invalid PC/SC driver " + "(%d%d%d%d%d%d%d%d%d%d)\n", + !!pcsc_establish_context, + !!pcsc_release_context, + !!pcsc_list_readers, + !!pcsc_connect, + !!pcsc_disconnect, + !!pcsc_status, + !!pcsc_begin_transaction, + !!pcsc_end_transaction, + !!pcsc_transmit, + !!pcsc_set_timeout ); + dlclose (handle); + exit (1); + } +} + + + + +/* Handle a open request. The argument is expected to be a string + with the port indentification. ARGBUF is always guaranteed to be + terminted by a 0 which is not counted in ARGLEN. We may modifiy + ARGBUF. */ +static void +handle_open (unsigned char *argbuf, size_t arglen) +{ + long err; + const char * portstr; + char *list = NULL; + unsigned long nreader, listlen, atrlen; + char *p; + unsigned long card_state, card_protocol; + unsigned char atr[33]; + + /* Make sure there is only the port string */ + if (arglen != strlen (argbuf)) + bad_request ("OPEN"); + portstr = argbuf; + + if (driver_is_open) + { + fprintf (stderr, PGM ": PC/SC has already been opened\n"); + request_failed (-1); + } + + err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL, &pcsc_context); + if (err) + { + fprintf (stderr, PGM": pcsc_establish_context failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + request_failed (err); + return; + } + + err = pcsc_list_readers (pcsc_context, NULL, NULL, &nreader); + if (!err) + { + list = malloc (nreader+1); /* Better add 1 for safety reasons. */ + if (!list) + { + fprintf (stderr, PGM": error allocating memory for reader list\n"); + exit (1); + } + err = pcsc_list_readers (pcsc_context, NULL, list, &nreader); + } + if (err) + { + fprintf (stderr, PGM": pcsc_list_readers failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (pcsc_context); + free (list); + request_failed (err); + return; + } + + listlen = nreader; + p = list; + while (nreader) + { + if (!*p && !p[1]) + break; + fprintf (stderr, PGM": detected reader `%s'\n", p); + if (nreader < (strlen (p)+1)) + { + fprintf (stderr, PGM": invalid response from pcsc_list_readers\n"); + break; + } + nreader -= strlen (p)+1; + p += strlen (p) + 1; + } + + err = pcsc_connect (pcsc_context, + portstr && *portstr? portstr : list, + PCSC_SHARE_EXCLUSIVE, + PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, + &pcsc_card, + &pcsc_protocol); + if (err) + { + fprintf (stderr, PGM": pcsc_connect failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (pcsc_context); + free (list); + request_failed (err); + return; + } + + atrlen = 32; + /* (We need to pass a dummy buffer. We use LIST because it ought to + be large enough.) */ + err = pcsc_status (pcsc_card, + list, &listlen, + &card_state, &card_protocol, + atr, &atrlen); + free (list); + if (err) + { + fprintf (stderr, PGM": pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (pcsc_context); + request_failed (err); + return; + } + if (atrlen >= sizeof atr || atrlen >= sizeof current_atr) + { + fprintf (stderr, PGM": ATR returned by pcsc_status is too large\n"); + exit (4); + } + memcpy (current_atr, atr, atrlen); + current_atrlen = atrlen; + driver_is_open = 1; + request_succeeded (current_atr, current_atrlen); +} + + + +/* Handle a close request. We expect no arguments. We may modifiy + ARGBUF. */ +static void +handle_close (unsigned char *argbuf, size_t arglen) +{ + if (!driver_is_open) + { + fprintf (stderr, PGM ": PC/SC has not yet been opened\n"); + request_failed (-1); + } + + pcsc_release_context (pcsc_context); + + request_succeeded (NULL, 0); +} + + + +/* Handle a transmit request. The argument is expected to be a bufer + with the APDU. We may modifiy ARGBUF. */ +static void +handle_transmit (unsigned char *argbuf, size_t arglen) +{ + long err; + struct pcsc_io_request_s send_pci; + unsigned long recv_len; + unsigned char buffer[1024]; + + /* The apdu should at least be one byte. */ + if (!arglen) + bad_request ("TRANSMIT"); + + if (!driver_is_open) + { + fprintf (stderr, PGM ": PC/SC has not yet been opened\n"); + request_failed (-1); + } + + if ((pcsc_protocol & PCSC_PROTOCOL_T1)) + send_pci.protocol = PCSC_PROTOCOL_T1; + else + send_pci.protocol = PCSC_PROTOCOL_T0; + send_pci.pci_len = sizeof send_pci; + recv_len = sizeof (buffer); + err = pcsc_transmit (pcsc_card, &send_pci, argbuf, arglen, + NULL, buffer, &recv_len); + if (err) + { + if (verbose) + fprintf (stderr, PGM": pcsc_transmit failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + request_failed (err); + return; + } + request_succeeded (buffer, recv_len); +} + + + + + + + + + + + + +static void +print_version (int with_help) +{ + fputs (MYVERSION_LINE "\n" + "Copyright (C) 2004 Free Software Foundation, Inc.\n" + "This program comes with ABSOLUTELY NO WARRANTY.\n" + "This is free software, and you are welcome to redistribute it\n" + "under certain conditions. See the file COPYING for details.\n", + stdout); + + if (with_help) + fputs ("\n" + "Usage: " PGM " [OPTIONS] API-NUMBER [LIBNAME]\n" + "Helper to connect scdaemon to the PC/SC library\n" + "\n" + " --verbose enable extra informational output\n" + " --version print version of the program and exit\n" + " --help display this help and exit\n" + BUGREPORT_LINE, stdout ); + + exit (0); +} + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + int api_number = 0; + int c; + + if (argc) + { + argc--; argv++; + } + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--version")) + print_version (0); + else if (!strcmp (*argv, "--help")) + print_version (1); + else if (!strcmp (*argv, "--verbose")) + { + verbose = 1; + argc--; argv++; + } + } + if (argc != 1 && argc != 2) + { + fprintf (stderr, "usage: " PGM " API-NUMBER [LIBNAME]\n"); + exit (1); + } + + api_number = atoi (*argv); + argv++; argc--; + if (api_number != 1) + { + fprintf (stderr, PGM ": api-number %d is not valid\n", api_number); + exit (1); + } + + load_pcsc_driver (argc? *argv : DEFAULT_PCSC_DRIVER); + + while ((c = getc (stdin)) != EOF) + { + size_t arglen; + unsigned char argbuffer[2048]; + + arglen = read_32 (stdin); + if (arglen >= sizeof argbuffer - 1) + { + fprintf (stderr, PGM ": request too long\n"); + exit (1); + } + if (arglen && fread (argbuffer, arglen, 1, stdin) != 1) + { + fprintf (stderr, PGM ": error reading request: %s\n", + strerror (errno)); + exit (1); + } + argbuffer[arglen] = 0; + switch (c) + { + case 1: + handle_open (argbuffer, arglen); + break; + + case 2: + handle_close (argbuffer, arglen); + exit (0); + break; + + case 3: + handle_transmit (argbuffer, arglen); + break; + + default: + fprintf (stderr, PGM ": invalid request 0x%02X\n", c); + exit (1); + } + free (argbuffer); + } + return 0; +} + + + +/* +Local Variables: +compile-command: "gcc -Wall -g -o pcsc-wrapper pcsc-wrapper.c -ldl" +End: +*/ diff --git a/scd/scdaemon.c b/scd/scdaemon.c index bc9d90b72..aabd38861 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -33,6 +33,9 @@ #include <sys/un.h> #include <unistd.h> #include <signal.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif #define JNLIB_NEED_LOG_LOGV #include "scdaemon.h" @@ -131,12 +134,24 @@ static ARGPARSE_OPTS opts[] = { static volatile int caught_fatal_sig = 0; +/* Flag to indicate that a shutdown was requested. */ +static int shutdown_pending; + /* It is possible that we are currently running under setuid permissions */ static int maybe_setuid = 1; /* Name of the communication socket */ static char socket_name[128]; + +#ifdef USE_GNU_PTH +/* Pth wrapper function definitions. */ +GCRY_THREAD_OPTION_PTH_IMPL; + +static void *ticker_thread (void *arg); +#endif /*USE_GNU_PTH*/ + + static const char * my_strusage (int level) { @@ -287,6 +302,7 @@ main (int argc, char **argv ) { ARGPARSE_ARGS pargs; int orig_argc; + gpg_error_t err; int may_coredump; char **orig_argv; FILE *configfp = NULL; @@ -318,7 +334,18 @@ main (int argc, char **argv ) i18n_init (); - /* check that the libraries are suitable. Do it here because + /* Libgcrypt requires us to register the threading model first. + Note that this will also do the pth_init. */ +#ifdef USE_GNU_PTH + err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + if (err) + { + log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", + gpg_strerror (err)); + } +#endif /*USE_GNU_PTH*/ + + /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) { @@ -568,7 +595,21 @@ main (int argc, char **argv ) if (pipe_server) - { /* this is the simple pipe based server */ + { /* This is the simple pipe based server */ +#ifdef USE_GNU_PTH + pth_attr_t tattr; + + tattr = pth_attr_new(); + pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024); + pth_attr_set (tattr, PTH_ATTR_NAME, "ticker"); + + if (!pth_spawn (tattr, ticker_thread, NULL)) + { + log_error ("error spawning ticker thread: %s\n", strerror (errno)); + scd_exit (2); + } +#endif /*USE_GNU_PTH*/ scd_command_handler (-1); } else if (!is_daemon) @@ -780,6 +821,115 @@ scd_exit (int rc) void scd_init_default_ctrl (CTRL ctrl) { + ctrl->reader_slot = -1; +} + + +#ifdef USE_GNU_PTH + +static void +handle_signal (int signo) +{ + switch (signo) + { + case SIGHUP: + log_info ("SIGHUP received - " + "re-reading configuration and resetting cards\n"); +/* reread_configuration (); */ + break; + + case SIGUSR1: + if (opt.verbose < 5) + opt.verbose++; + log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose); + break; + + case SIGUSR2: + if (opt.verbose) + opt.verbose--; + log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose ); + break; + + case SIGTERM: + if (!shutdown_pending) + log_info ("SIGTERM received - shutting down ...\n"); + else + log_info ("SIGTERM received - still %ld running threads\n", + pth_ctrl( PTH_CTRL_GETTHREADS )); + shutdown_pending++; + if (shutdown_pending > 2) + { + log_info ("shutdown forced\n"); + log_info ("%s %s stopped\n", strusage(11), strusage(13) ); + cleanup (); + scd_exit (0); + } + break; + + case SIGINT: + log_info ("SIGINT received - immediate shutdown\n"); + log_info( "%s %s stopped\n", strusage(11), strusage(13)); + cleanup (); + scd_exit (0); + break; + default: + log_info ("signal %d received - no action defined\n", signo); + } } +static void +handle_tick (void) +{ + scd_update_reader_status_file (); +} + +static void * +ticker_thread (void *dummy_arg) +{ + pth_event_t sigs_ev, time_ev = NULL; + sigset_t sigs; + int signo; + + sigemptyset (&sigs ); + sigaddset (&sigs, SIGHUP); + sigaddset (&sigs, SIGUSR1); + sigaddset (&sigs, SIGUSR2); + sigaddset (&sigs, SIGINT); + sigaddset (&sigs, SIGTERM); + sigs_ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); + + for (;;) + { + if (!time_ev) + { + time_ev = pth_event (PTH_EVENT_TIME, pth_timeout (2, 0)); + if (time_ev) + pth_event_concat (sigs_ev, time_ev, NULL); + } + + if (pth_wait (sigs_ev) < 1) + continue; + + if ( +#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ + pth_event_status (sigs_ev) == PTH_STATUS_OCCURRED +#else + pth_event_occurred (sigs_ev) +#endif + ) + handle_signal (signo); + + /* Always run the ticker. */ + if (!shutdown_pending) + { + pth_event_isolate (sigs_ev); + pth_event_free (time_ev, PTH_FREE_ALL); + time_ev = NULL; + handle_tick (); + } + } + + pth_event_free (sigs_ev, PTH_FREE_ALL); +} +#endif /*USE_GNU_PTH*/ diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 098738508..1dd32ae90 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -79,6 +79,7 @@ struct app_ctx_s; struct server_control_s { struct server_local_s *server_local; + int reader_slot; /* Slot of the open reader or -1 if not open. */ struct card_ctx_s *card_ctx; struct app_ctx_s *app_ctx; struct { @@ -101,6 +102,7 @@ void scd_init_default_ctrl (CTRL ctrl); /*-- command.c --*/ void scd_command_handler (int); void send_status_info (CTRL ctrl, const char *keyword, ...); +void scd_update_reader_status_file (void); /*-- card.c --*/ int card_open (CARD *rcard); -- cgit v1.2.3 From 2c9aac608b25072c823779af56411dcf14bf0ae8 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 20 Apr 2004 16:02:30 +0000 Subject: 2004-04-20 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_options_gpg_agent): Change type of ignore-cache-for-signing option to GC_ARG_TYPE_NONE. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 0a4046cbd..6da70fdda 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-04-20 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (gc_options_gpg_agent): Change type of + ignore-cache-for-signing option to GC_ARG_TYPE_NONE. + 2004-04-07 Werner Koch <wk@gnupg.org> * gpgconf-comp.c (my_dgettext): Switch the codeset once to utf-8. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 0b56129c1..8a5c96033 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -468,7 +468,7 @@ static gc_option_t gc_options_gpg_agent[] = GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing", - GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "no-grab", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "do not grab keyboard and mouse", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, -- cgit v1.2.3 From 78f797d11d9201b3561b921b69b6de50df7160e8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Apr 2004 16:42:55 +0000 Subject: * command.c (scd_update_reader_status_file): Write status files. * app-help.c (app_help_read_length_of_cert): Fixed calculation of R_CERTOFF. * pcsc-wrapper.c: New. * Makefile.am (pkglib_PROGRAMS): Install it here. * apdu.c (writen, readn): New. (open_pcsc_reader, pcsc_send_apdu, close_pcsc_reader): Use the pcsc-wrapper if we are using Pth. (apdu_send_le): Reinitialize RESULTLEN. Handle SW_EOF_REACHED like SW_SUCCESS. --- NEWS | 5 +++++ scd/ChangeLog | 7 +++++++ scd/apdu.c | 23 ++++++++++++++++------- scd/app-help.c | 7 ++++++- scd/ccid-driver.c | 2 +- scd/command.c | 35 +++++++++++++++++++++++++++++++++-- 6 files changed, 68 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index dc1122846..31f76b6c8 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ Noteworthy changes in version 1.9.8 ------------------------------------------------ + * [scdaemon] Overhauled the internal CCID driver. + + * [scdaemon] Status files named ~/.gnupg/reader_<n>.status are now + written when using the internal CCID driver. + Noteworthy changes in version 1.9.7 (2004-04-06) ------------------------------------------------ diff --git a/scd/ChangeLog b/scd/ChangeLog index 9b04d5e78..bf5c36cbc 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,10 +1,17 @@ 2004-04-20 Werner Koch <wk@gnupg.org> + * command.c (scd_update_reader_status_file): Write status files. + + * app-help.c (app_help_read_length_of_cert): Fixed calculation of + R_CERTOFF. + * pcsc-wrapper.c: New. * Makefile.am (pkglib_PROGRAMS): Install it here. * apdu.c (writen, readn): New. (open_pcsc_reader, pcsc_send_apdu, close_pcsc_reader): Use the pcsc-wrapper if we are using Pth. + (apdu_send_le): Reinitialize RESULTLEN. Handle SW_EOF_REACHED + like SW_SUCCESS. 2004-04-19 Werner Koch <wk@gnupg.org> diff --git a/scd/apdu.c b/scd/apdu.c index 1b5ebc375..42b337238 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -913,7 +913,7 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, } full_len = len; - + n = *buflen < len ? *buflen : len; if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) { @@ -922,6 +922,7 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, goto command_failed; } *buflen = n; + full_len -= len; if (full_len) { @@ -1771,8 +1772,10 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, int lc, const char *data, int le, unsigned char **retbuf, size_t *retbuflen) { - unsigned char result[256+10]; /* 10 extra in case of bugs in the driver. */ - size_t resultlen = 256; +#define RESULTLEN 256 + unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in + the driver. */ + size_t resultlen; unsigned char apdu[5+256+1]; size_t apdulen; int sw; @@ -1811,6 +1814,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, assert (sizeof (apdu) >= apdulen); /* As safeguard don't pass any garbage from the stack to the driver. */ memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen); if (rc || resultlen < 2) { @@ -1867,8 +1871,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, { int len = (sw & 0x00ff); - log_debug ("apdu_send_simple(%d): %d more bytes available\n", - slot, len); + if (DBG_CARD_IO) + log_debug ("apdu_send_simple(%d): %d more bytes available\n", + slot, len); apdulen = 0; apdu[apdulen++] = class; apdu[apdulen++] = 0xC0; @@ -1876,6 +1881,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, apdu[apdulen++] = 0; apdu[apdulen++] = len; memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen); if (rc || resultlen < 2) { @@ -1893,9 +1899,11 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, log_printhex (" dump: ", result, resultlen); } - if ((sw & 0xff00) == SW_MORE_DATA || sw == SW_SUCCESS) + if ((sw & 0xff00) == SW_MORE_DATA + || sw == SW_SUCCESS + || sw == SW_EOF_REACHED ) { - if (retbuf) + if (retbuf && resultlen) { if (p - *retbuf + resultlen > bufsize) { @@ -1935,6 +1943,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, log_printhex (" dump: ", *retbuf, *retbuflen); return sw; +#undef RESULTLEN } /* Send an APDU to the card in SLOT. The APDU is created from all diff --git a/scd/app-help.c b/scd/app-help.c index c6695635f..1c3c52b15 100644 --- a/scd/app-help.c +++ b/scd/app-help.c @@ -147,8 +147,13 @@ app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff) is the certificate. */ *r_certoff += hdrlen + objlen; if (*r_certoff > resultlen) - return 0; /* That should never happen. */ + { + *r_certoff = 0; + return 0; /* That should never happen. */ + } } + else + *r_certoff = 0; } return resultlen; diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 1c8167869..cd0bee6ef 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -108,7 +108,7 @@ /* Disable all debugging output for now. */ #undef DBG_CARD_IO -#define DBG_CARD_IO 1 +#define DBG_CARD_IO 0 /* Define to print information pertaining the T=1 protocol. */ #undef DEBUG_T1 diff --git a/scd/command.c b/scd/command.c index 06ff6d2e2..9e77cbe0f 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1179,6 +1179,11 @@ send_status_info (CTRL ctrl, const char *keyword, ...) void scd_update_reader_status_file (void) { + static struct { + int any; + unsigned int status; + unsigned int changed; + } last[10]; int slot; int used; unsigned int status, changed; @@ -1187,9 +1192,35 @@ scd_update_reader_status_file (void) make sense to wait here for a operation to complete. If we are so busy working with the card, delays in the status file updated are should be acceptable. */ - for (slot=0; !apdu_enum_reader (slot, &used); slot++) + for (slot=0; (slot < DIM(last) + &&!apdu_enum_reader (slot, &used)); slot++) if (used && !apdu_get_status (slot, 0, &status, &changed)) { - log_info ("status of slot %d is %u\n", slot, status); + if (!last[slot].any || last[slot].status != status + || last[slot].changed != changed ) + { + char *fname; + char templ[50]; + FILE *fp; + + last[slot].any = 1; + last[slot].status = status; + last[slot].changed = changed; + + log_info ("updating status of slot %d to 0x%04X\n", slot, status); + + sprintf (templ, "reader_%d.status", slot); + fname = make_filename (opt.homedir, templ, NULL ); + fp = fopen (fname, "w"); + if (fp) + { + fprintf (fp, "%s\n", + (status & 1)? "USABLE": + (status & 4)? "ACTIVE": + (status & 2)? "PRESENT": "NOCARD"); + fclose (fp); + } + xfree (fname); + } } } -- cgit v1.2.3 From 3d58329f67ba10a21ec0b2c9c8ede6e275a3607d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 21 Apr 2004 14:43:51 +0000 Subject: * call-scd.c (start_scd): Send event-signal option. Always check that the scdaemon is still running. * gpg-agent.c (handle_signal): Do not use SIGUSR{1,2} anymore for changing the verbosity. --- agent/ChangeLog | 8 ++++++++ agent/call-scd.c | 31 +++++++++++++++++++++++++++---- agent/gpg-agent.c | 10 +++------- doc/gpg-agent.texi | 16 +++++++--------- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 43bdb7ab5..f63ae88a1 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2004-04-21 Werner Koch <wk@gnupg.org> + + * call-scd.c (start_scd): Send event-signal option. Always check + that the scdaemon is still running. + + * gpg-agent.c (handle_signal): Do not use SIGUSR{1,2} anymore for + changing the verbosity. + 2004-04-16 Werner Koch <wk@gnupg.org> * gpg-agent.c (main): Tell the logging code taht we are runnign diff --git a/agent/call-scd.c b/agent/call-scd.c index 0bb365ced..3c2bf9e2a 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -33,6 +33,8 @@ #include <assert.h> #include <unistd.h> #include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> #ifdef USE_GNU_PTH # include <pth.h> #endif @@ -51,8 +53,8 @@ static ASSUAN_CONTEXT scd_ctx = NULL; static pth_mutex_t scd_lock = PTH_MUTEX_INIT; #endif /* We need to keep track of the connection currently using the SCD. - For a pipe server this is all a NOP becuase the connection will - always have the conenction indicator -1. agent_reset_scd releases + For a pipe server this is all a NOP because the connection will + always have the connection indicator -1. agent_reset_scd releases the active connection; i.e. sets it back to -1, so that a new connection can start using the SCD. If we eventually allow multiple SCD session we will either make scdaemon multi-threaded or @@ -195,6 +197,8 @@ start_scd (ctrl_t ctrl) if (scd_ctx) { + pid_t pid; + /* If we are not the connection currently using the SCD, return an error. */ if (!active_connection) @@ -205,8 +209,19 @@ start_scd (ctrl_t ctrl) else if (ctrl->connection_fd != active_connection_fd) return unlock_scd (gpg_error (GPG_ERR_CONFLICT)); - /* Okay, we scdaemon already started and used by us. */ - return 0; + /* Okay, we already started the scdaemon and it is used by us.*/ + + /* We better do a sanity check now to see whether it has + accidently died. */ + pid = assuan_get_pid (scd_ctx); + if (pid != (pid_t)(-1) && pid + && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) + { + assuan_disconnect (scd_ctx); + scd_ctx = NULL; + } + else + return 0; } if (opt.verbose) @@ -255,6 +270,14 @@ start_scd (ctrl_t ctrl) if (DBG_ASSUAN) log_debug ("connection to SCdaemon established\n"); + /* Tell the scdaemon that we want him to send us an event signal. */ + { + char buf[100]; + + sprintf (buf, "OPTION event-signal=%d", SIGUSR2); + assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); + } + return 0; } diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 18a456f19..9b8678823 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1059,15 +1059,11 @@ handle_signal (int signo) break; case SIGUSR1: - if (opt.verbose < 5) - opt.verbose++; - log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose); + log_info ("SIGUSR1 received - no action defined\n"); break; - + case SIGUSR2: - if (opt.verbose) - opt.verbose--; - log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose ); + log_info ("SIGUSR2 received - checking smartcard status\n"); break; case SIGTERM: diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 92975fd11..e199109a4 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -312,15 +312,6 @@ implementation, which calls the scdaemon only once, it is not of much use. -@item SIGUSR1 -@cpindex SIGUSR1 -This signal increases the verbosity of the logging by one up to a value -of 5. - -@item SIGUSR2 -@cpindex SIGUSR2 -This signal decreases the verbosity of the logging by one. - @item SIGTERM @cpindex SIGTERM Shuts down the process but waits until all current requests are @@ -331,6 +322,13 @@ are still pending, a shutdown is forced. @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 -- cgit v1.2.3 From 4624e9dfb3fd8260273706d43c6137f860abb89c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 21 Apr 2004 14:44:09 +0000 Subject: * command.c (scd_update_reader_status_file): Send a signal back to the client. (option_handler): Parse the new event-signal option. * scdaemon.c (handle_signal): Do not use SIGUSR{1,2} anymore for changing the verbosity. --- scd/ChangeLog | 9 +++++++++ scd/command.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- scd/scdaemon.c | 8 ++------ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index bf5c36cbc..037090863 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2004-04-21 Werner Koch <wk@gnupg.org> + + * command.c (scd_update_reader_status_file): Send a signal back to + the client. + (option_handler): Parse the new event-signal option. + + * scdaemon.c (handle_signal): Do not use SIGUSR{1,2} anymore for + changing the verbosity. + 2004-04-20 Werner Koch <wk@gnupg.org> * command.c (scd_update_reader_status_file): Write status files. diff --git a/scd/command.c b/scd/command.c index 9e77cbe0f..6fa100ff9 100644 --- a/scd/command.c +++ b/scd/command.c @@ -25,6 +25,7 @@ #include <string.h> #include <ctype.h> #include <unistd.h> +#include <signal.h> #include <assuan.h> @@ -33,14 +34,21 @@ #include "app-common.h" #include "apdu.h" /* Required for apdu_*_reader (). */ -/* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */ +/* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */ #define MAXLEN_PIN 100 + +/* We keep track of the primary client using scdaemon. This one will + for example receive signal on card change. */ +static ctrl_t primary_connection; + + #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) /* Data used to associate an Assuan context with local server data */ struct server_local_s { ASSUAN_CONTEXT assuan_ctx; + int event_signal; /* Or 0 if not used. */ }; @@ -96,7 +104,18 @@ reset_notify (ASSUAN_CONTEXT ctx) static int option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) { - return 0; + ctrl_t ctrl = assuan_get_pointer (ctx); + + if (!strcmp (key, "event-signal")) + { + /* A value of 0 is allowed to reset the event signal. */ + int i = *value? atoi (value) : -1; + if (i < 0) + return ASSUAN_Parameter_Error; + ctrl->server_local->event_signal = i; + } + + return 0; } @@ -1096,6 +1115,10 @@ scd_command_handler (int listen_fd) if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); + /* Store the primary connection's assuan context. */ + if (!primary_connection) + primary_connection = &ctrl; + /* We open the reader right at startup so that the ticker is able to update the status file. */ if (ctrl.reader_slot == -1) @@ -1122,6 +1145,12 @@ scd_command_handler (int listen_fd) continue; } } + + /* The next client will be the primary conenction if this one + terminates. */ + if (primary_connection == &ctrl) + primary_connection = NULL; + do_reset (&ctrl, 1); /* Cleanup. */ assuan_deinit_server (ctx); @@ -1221,6 +1250,19 @@ scd_update_reader_status_file (void) fclose (fp); } xfree (fname); + + /* Send a signal to the primary client, if any. */ + if (primary_connection && primary_connection->server_local + && primary_connection->server_local->assuan_ctx) + { + pid_t pid = assuan_get_pid (primary_connection + ->server_local->assuan_ctx); + int signo = primary_connection->server_local->event_signal; + + log_info ("client pid is %d, sending signal %d\n", pid, signo); + if (pid != (pid_t)(-1) && pid && signo > 0) + kill (pid, signo); + } } } } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index aabd38861..5066a373b 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -839,15 +839,11 @@ handle_signal (int signo) break; case SIGUSR1: - if (opt.verbose < 5) - opt.verbose++; - log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose); + log_info ("SIGUSR1 received - no action defined\n"); break; case SIGUSR2: - if (opt.verbose) - opt.verbose--; - log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose ); + log_info ("SIGUSR2 received - no action defined\n"); break; case SIGTERM: -- cgit v1.2.3 From 99e00351a33911426cd51ae2bbfcac054585130d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 22 Apr 2004 13:03:44 +0000 Subject: (main): New commands --dump-keys, --dump-external-keys, --dump-secret-keys. --- sm/ChangeLog | 5 ++ sm/certdump.c | 1 + sm/gpgsm.c | 32 +++++++++ sm/keylist.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 241 insertions(+), 13 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 02f627a4d..796098f9d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-04-22 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): New commands --dump-keys, --dump-external-keys, + --dump-secret-keys. + 2004-04-13 Werner Koch <wk@gnupg.org> * misc.c (setup_pinentry_env): New. diff --git a/sm/certdump.c b/sm/certdump.c index aefaf27ef..21581dca3 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -184,6 +184,7 @@ gpgsm_dump_string (const char *string) } +/* This simple dump function is mainly used for debugging purposes. */ void gpgsm_dump_cert (const char *text, ksba_cert_t cert) { diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 7140e34ac..322f893a4 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -82,6 +82,9 @@ enum cmd_and_opt_values { aCallProtectTool, aPasswd, aGPGConfList, + aDumpKeys, + aDumpSecretKeys, + aDumpExternalKeys, oOptions, oDebug, @@ -246,6 +249,10 @@ static ARGPARSE_OPTS opts[] = { { aPasswd, "passwd", 256, N_("change a passphrase")}, { aGPGConfList, "gpgconf-list", 256, "@" }, + { aDumpKeys, "dump-keys", 256, "@"}, + { aDumpExternalKeys, "dump-external-keys", 256, "@"}, + { aDumpSecretKeys, "dump-secret-keys", 256, "@"}, + { 301, NULL, 0, N_("@\nOptions:\n ") }, { oArmor, "armor", 0, N_("create ascii armored output")}, @@ -878,6 +885,9 @@ main ( int argc, char **argv) case aRecvKeys: case aExport: case aExportSecretKeyP12: + case aDumpKeys: + case aDumpExternalKeys: + case aDumpSecretKeys: case aListKeys: case aListExternalKeys: case aListSecretKeys: @@ -1416,6 +1426,13 @@ main ( int argc, char **argv) free_strlist(sl); break; + case aDumpKeys: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_list_keys (&ctrl, sl, stdout, (256 | (1<<6))); + free_strlist(sl); + break; + case aListExternalKeys: for (sl=NULL; argc; argc--, argv++) add_to_strlist (&sl, *argv); @@ -1424,6 +1441,14 @@ main ( int argc, char **argv) free_strlist(sl); break; + case aDumpExternalKeys: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_list_keys (&ctrl, sl, stdout, + (256 | (1<<7))); + free_strlist(sl); + break; + case aListSecretKeys: for (sl=NULL; argc; argc--, argv++) add_to_strlist (&sl, *argv); @@ -1431,6 +1456,13 @@ main ( int argc, char **argv) free_strlist(sl); break; + case aDumpSecretKeys: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + gpgsm_list_keys (&ctrl, sl, stdout, (256 | 2 | (1<<6))); + free_strlist(sl); + break; + case aKeygen: /* generate a key */ log_error ("this function is not yet available from the commandline\n"); break; diff --git a/sm/keylist.c b/sm/keylist.c index 4e6f28db8..74a5e623a 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -43,6 +43,7 @@ struct list_external_parm_s { int print_header; int with_colons; int with_chain; + int raw_mode; }; @@ -324,6 +325,175 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, } +/* List one certificate in raw mode useful to have a closer look at + the certificate. This one does not beautification and only minimal + output sanitation. It is mainly useful for debugging. */ +static void +list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, + int with_validation) +{ + gpg_error_t err; + ksba_sexp_t sexp; + char *dn; + ksba_isotime_t t; + int idx, i; + int is_ca, chainlen; + unsigned int kusage; + char *string, *p, *pend; + + sexp = ksba_cert_get_serial (cert); + fputs ("Serial number: ", fp); + gpgsm_print_serial (fp, sexp); + ksba_free (sexp); + putc ('\n', fp); + + dn = ksba_cert_get_issuer (cert, 0); + fputs (" Issuer: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++) + { + fputs (" aka: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + } + + dn = ksba_cert_get_subject (cert, 0); + fputs (" Subject: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++) + { + fputs (" aka: ", fp); + gpgsm_print_name (fp, dn); + ksba_free (dn); + putc ('\n', fp); + } + + ksba_cert_get_validity (cert, 0, t); + fputs (" validity: ", fp); + gpgsm_print_time (fp, t); + fputs (" through ", fp); + ksba_cert_get_validity (cert, 1, t); + gpgsm_print_time (fp, t); + putc ('\n', fp); + + err = ksba_cert_get_key_usage (cert, &kusage); + if (gpg_err_code (err) != GPG_ERR_NO_DATA) + { + fputs (" key usage:", fp); + if (err) + fprintf (fp, " [error: %s]", gpg_strerror (err)); + else + { + if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE)) + fputs (" digitalSignature", fp); + if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION)) + fputs (" nonRepudiation", fp); + if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) + fputs (" keyEncipherment", fp); + if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT)) + fputs (" dataEncipherment", fp); + if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT)) + fputs (" keyAgreement", fp); + if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN)) + fputs (" certSign", fp); + if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN)) + fputs (" crlSign", fp); + if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY)) + fputs (" encipherOnly", fp); + if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY)) + fputs (" decipherOnly", fp); + } + putc ('\n', fp); + } + + err = ksba_cert_get_ext_key_usages (cert, &string); + if (gpg_err_code (err) != GPG_ERR_NO_DATA) + { + fputs ("ext key usage: ", fp); + if (err) + fprintf (fp, "[error: %s]", gpg_strerror (err)); + else + { + p = string; + while (p && (pend=strchr (p, ':'))) + { + *pend++ = 0; + for (i=0; key_purpose_map[i].oid; i++) + if ( !strcmp (key_purpose_map[i].oid, p) ) + break; + fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp); + p = pend; + if (*p != 'C') + fputs (" (suggested)", fp); + if ((p = strchr (p, '\n'))) + { + p++; + fputs (", ", fp); + } + } + xfree (string); + } + putc ('\n', fp); + } + + err = ksba_cert_get_cert_policies (cert, &string); + if (gpg_err_code (err) != GPG_ERR_NO_DATA) + { + fputs (" policies: ", fp); + if (err) + fprintf (fp, "[error: %s]", gpg_strerror (err)); + else + { + for (p=string; *p; p++) + { + if (*p == '\n') + *p = ','; + } + print_sanitized_string (fp, string, 0); + xfree (string); + } + putc ('\n', fp); + } + + err = ksba_cert_is_ca (cert, &is_ca, &chainlen); + if (err || is_ca) + { + fputs (" chain length: ", fp); + if (err) + fprintf (fp, "[error: %s]", gpg_strerror (err)); + else if (chainlen == -1) + fputs ("unlimited", fp); + else + fprintf (fp, "%d", chainlen); + putc ('\n', fp); + } + + dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5); + fprintf (fp, " md5 fpr: %s\n", dn?dn:"error"); + xfree (dn); + + dn = gpgsm_get_fingerprint_string (cert, 0); + fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); + xfree (dn); + + if (with_validation) + { + err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0); + if (!err) + fprintf (fp, " [certificate is good]\n"); + else + fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err)); + } +} + + + + /* List one certificate in standard mode */ static void list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, @@ -494,17 +664,24 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, /* Same as standard mode mode list all certifying certs too. */ static void -list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation) +list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, int raw_mode, + FILE *fp, int with_validation) { ksba_cert_t next = NULL; - list_cert_std (ctrl, cert, fp, 0, with_validation); + if (raw_mode) + list_cert_raw (ctrl, cert, fp, 0, with_validation); + else + list_cert_std (ctrl, cert, fp, 0, with_validation); ksba_cert_ref (cert); while (!gpgsm_walk_cert_chain (cert, &next)) { ksba_cert_release (cert); fputs ("Certified by\n", fp); - list_cert_std (ctrl, next, fp, 0, with_validation); + if (raw_mode) + list_cert_raw (ctrl, next, fp, 0, with_validation); + else + list_cert_std (ctrl, next, fp, 0, with_validation); cert = next; } ksba_cert_release (cert); @@ -513,10 +690,14 @@ list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation) -/* List all internal keys or just the key given as NAMES. +/* List all internal keys or just the keys given as NAMES. MODE is a + bit vector to specify what keys are to be included; see + gpgsm_list_keys (below) for details. If RAW_MODE is true, the raw + output mode will be used intead of the standard beautified one. */ static gpg_error_t -list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) +list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, + unsigned int mode, int raw_mode) { KEYDB_HANDLE hd; KEYDB_SEARCH_DESC *desc = NULL; @@ -637,11 +818,15 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) if (ctrl->with_colons) list_cert_colon (ctrl, cert, validity, fp, have_secret); else if (ctrl->with_chain) - list_cert_chain (ctrl, cert, fp, ctrl->with_validation); + list_cert_chain (ctrl, cert, raw_mode, fp, ctrl->with_validation); else { - list_cert_std (ctrl, cert, fp, have_secret, - ctrl->with_validation); + if (raw_mode) + list_cert_raw (ctrl, cert, fp, have_secret, + ctrl->with_validation); + else + list_cert_std (ctrl, cert, fp, have_secret, + ctrl->with_validation); putc ('\n', fp); } } @@ -685,10 +870,13 @@ list_external_cb (void *cb_value, ksba_cert_t cert) if (parm->with_colons) list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0); else if (parm->with_chain) - list_cert_chain (parm->ctrl, cert, parm->fp, 0); + list_cert_chain (parm->ctrl, cert, parm->raw_mode, parm->fp, 0); else { - list_cert_std (parm->ctrl, cert, parm->fp, 0, 0); + if (parm->raw_mode) + list_cert_raw (parm->ctrl, cert, parm->fp, 0, 0); + else + list_cert_std (parm->ctrl, cert, parm->fp, 0, 0); putc ('\n', parm->fp); } } @@ -698,7 +886,7 @@ list_external_cb (void *cb_value, ksba_cert_t cert) make sense here because it would be unwise to list external secret keys */ static gpg_error_t -list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) +list_external_keys (CTRL ctrl, STRLIST names, FILE *fp, int raw_mode) { int rc; struct list_external_parm_s parm; @@ -708,6 +896,7 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) parm.print_header = ctrl->no_server; parm.with_colons = ctrl->with_colons; parm.with_chain = ctrl->with_chain; + parm.raw_mode = raw_mode; rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm); if (rc) @@ -724,6 +913,7 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp) 3 = list secret and public keys Bit 6: list internal keys Bit 7: list external keys + Bit 8: Do a raw format dump. */ gpg_error_t gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) @@ -731,8 +921,8 @@ gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) gpg_error_t err = 0; if ((mode & (1<<6))) - err = list_internal_keys (ctrl, names, fp, (mode & 3)); + err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256)); if (!err && (mode & (1<<7))) - err = list_external_keys (ctrl, names, fp); + err = list_external_keys (ctrl, names, fp, (mode&256)); return err; } -- cgit v1.2.3 From cbc5ce3ea43fd9dcaddcbef936c62bc4b7e788a0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 23 Apr 2004 10:34:25 +0000 Subject: (oidtranstbl): New. OIDs collected from several sources. (print_name_raw, print_names_raw, list_cert_raw): New. (gpgsm_list_keys): Check the dump mode and pass it down as necessary. --- sm/ChangeLog | 7 ++ sm/keylist.c | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 309 insertions(+), 21 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 796098f9d..28171b963 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-04-23 Werner Koch <wk@gnupg.org> + + * keylist.c (oidtranstbl): New. OIDs collected from several sources. + (print_name_raw, print_names_raw, list_cert_raw): New. + (gpgsm_list_keys): Check the dump mode and pass it down as + necessary. + 2004-04-22 Werner Koch <wk@gnupg.org> * gpgsm.c (main): New commands --dump-keys, --dump-external-keys, diff --git a/sm/keylist.c b/sm/keylist.c index 74a5e623a..2a365bc3a 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -70,6 +70,121 @@ struct { }; +/* A table mapping OIDs to a descriptive string. */ +static struct { + char *oid; + char *name; + unsigned int flag; +} oidtranstbl[] = { + + /* Algorithms. */ + { "1.2.840.10040.4.1", "dsa" }, + { "1.2.840.10040.4.3", "dsaWithSha1" }, + + { "1.2.840.113549.1.1.1", "rsaEncryption" }, + { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" }, + { "1.2.840.113549.1.1.3", "md4WithRSAEncryption" }, + { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" }, + { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" }, + { "1.2.840.113549.1.1.7", "rsaOAEP" }, + { "1.2.840.113549.1.1.8", "rsaOAEP-MGF" }, + { "1.2.840.113549.1.1.9", "rsaOAEP-pSpecified" }, + { "1.2.840.113549.1.1.10", "rsaPSS" }, + { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" }, + { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" }, + { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" }, + + { "1.3.14.3.2.26", "sha1" }, + { "1.3.14.3.2.29", "sha-1WithRSAEncryption" }, + { "1.3.36.3.3.1.2", "rsaSignatureWithripemd160" }, + + + /* Telesec extensions. */ + { "0.2.262.1.10.12.0", "certExtensionLiabilityLimitationExt" }, + { "0.2.262.1.10.12.1", "telesecCertIdExt" }, + { "0.2.262.1.10.12.2", "telesecPolicyIdentifier" }, + { "0.2.262.1.10.12.3", "telesecPolicyQualifierID" }, + { "0.2.262.1.10.12.4", "telesecCRLFilteredExt" }, + { "0.2.262.1.10.12.5", "telesecCRLFilterExt"}, + { "0.2.262.1.10.12.6", "telesecNamingAuthorityExt" }, + + /* PKIX private extensions. */ + { "1.3.6.1.5.5.7.1.1", "authorityInfoAccess" }, + { "1.3.6.1.5.5.7.1.2", "biometricInfo" }, + { "1.3.6.1.5.5.7.1.3", "qcStatements" }, + { "1.3.6.1.5.5.7.1.4", "acAuditIdentity" }, + { "1.3.6.1.5.5.7.1.5", "acTargeting" }, + { "1.3.6.1.5.5.7.1.6", "acAaControls" }, + { "1.3.6.1.5.5.7.1.7", "sbgp-ipAddrBlock" }, + { "1.3.6.1.5.5.7.1.8", "sbgp-autonomousSysNum" }, + { "1.3.6.1.5.5.7.1.9", "sbgp-routerIdentifier" }, + { "1.3.6.1.5.5.7.1.10", "acProxying" }, + { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" }, + + /* X.509 id-ce */ + { "2.5.29.14", "subjectKeyIdentifier"}, + { "2.5.29.15", "keyUsage", 1 }, + { "2.5.29.16", "privateKeyUsagePeriod" }, + { "2.5.29.17", "subjectAltName", 1 }, + { "2.5.29.18", "issuerAltName", 1 }, + { "2.5.29.19", "basicConstraints", 1}, + { "2.5.29.20", "cRLNumber" }, + { "2.5.29.21", "cRLReason" }, + { "2.5.29.22", "expirationDate" }, + { "2.5.29.23", "instructionCode" }, + { "2.5.29.24", "invalidityDate" }, + { "2.5.29.27", "deltaCRLIndicator" }, + { "2.5.29.28", "issuingDistributionPoint" }, + { "2.5.29.29", "certificateIssuer" }, + { "2.5.29.30", "nameConstraints" }, + { "2.5.29.31", "cRLDistributionPoints", 1 }, + { "2.5.29.32", "certificatePolicies", 1 }, + { "2.5.29.32.0", "anyPolicy" }, + { "2.5.29.33", "policyMappings" }, + { "2.5.29.35", "authorityKeyIdentifier", 1 }, + { "2.5.29.36", "policyConstraints" }, + { "2.5.29.37", "extKeyUsage", 1 }, + { "2.5.29.46", "freshestCRL" }, + { "2.5.29.54", "inhibitAnyPolicy" }, + + /* Netscape certificate extensions. */ + { "2.16.840.1.113730.1.1", "netscape-cert-type" }, + { "2.16.840.1.113730.1.2", "netscape-base-url" }, + { "2.16.840.1.113730.1.3", "netscape-revocation-url" }, + { "2.16.840.1.113730.1.4", "netscape-ca-revocation-url" }, + { "2.16.840.1.113730.1.7", "netscape-cert-renewal-url" }, + { "2.16.840.1.113730.1.8", "netscape-ca-policy-url" }, + { "2.16.840.1.113730.1.9", "netscape-homePage-url" }, + { "2.16.840.1.113730.1.10", "netscape-entitylogo" }, + { "2.16.840.1.113730.1.11", "netscape-userPicture" }, + { "2.16.840.1.113730.1.12", "netscape-ssl-server-name" }, + { "2.16.840.1.113730.1.13", "netscape-comment" }, + + { NULL } +}; + + +/* Return the description for OID; if no description is available + NULL is returned. */ +static const char * +get_oid_desc (const char *oid, unsigned int *flag) +{ + int i; + + if (oid) + for (i=0; oidtranstbl[i].oid; i++) + if (!strcmp (oidtranstbl[i].oid, oid)) + { + if (flag) + *flag = oidtranstbl[i].flag; + return oidtranstbl[i].name; + } + if (flag) + *flag = 0; + return NULL; +} + + static void print_key_data (ksba_cert_t cert, FILE *fp) { @@ -325,6 +440,40 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, } +static void +print_name_raw (FILE *fp, const char *string) +{ + if (!string) + fputs ("[error]", fp); + else + print_sanitized_string (fp, string, 0); +} + +static void +print_names_raw (FILE *fp, int indent, ksba_name_t name) +{ + int idx; + const char *s; + int indent_all; + + if ((indent_all = (indent < 0))) + indent = - indent; + + if (!name) + { + fputs ("none\n", fp); + return; + } + + for (idx=0; (s = ksba_name_enum (name, idx)); idx++) + { + char *p = ksba_name_get_uri (name, idx); + printf ("%*s%s\n", idx||indent_all?indent:0, "", p?p:s); + xfree (p); + } +} + + /* List one certificate in raw mode useful to have a closer look at the certificate. This one does not beautification and only minimal output sanitation. It is mainly useful for debugging. */ @@ -333,6 +482,7 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, int with_validation) { gpg_error_t err; + size_t off, len; ksba_sexp_t sexp; char *dn; ksba_isotime_t t; @@ -340,6 +490,9 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, int is_ca, chainlen; unsigned int kusage; char *string, *p, *pend; + const char *oid, *s; + ksba_name_t name, name2; + unsigned int reason; sexp = ksba_cert_get_serial (cert); fputs ("Serial number: ", fp); @@ -349,42 +502,74 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, dn = ksba_cert_get_issuer (cert, 0); fputs (" Issuer: ", fp); - gpgsm_print_name (fp, dn); + print_name_raw (fp, dn); ksba_free (dn); putc ('\n', fp); for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++) { fputs (" aka: ", fp); - gpgsm_print_name (fp, dn); + print_name_raw (fp, dn); ksba_free (dn); putc ('\n', fp); } dn = ksba_cert_get_subject (cert, 0); fputs (" Subject: ", fp); - gpgsm_print_name (fp, dn); + print_name_raw (fp, dn); ksba_free (dn); putc ('\n', fp); for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++) { fputs (" aka: ", fp); - gpgsm_print_name (fp, dn); + print_name_raw (fp, dn); ksba_free (dn); putc ('\n', fp); } + dn = gpgsm_get_fingerprint_string (cert, 0); + fprintf (fp, " sha1_fpr: %s\n", dn?dn:"error"); + xfree (dn); + + dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5); + fprintf (fp, " md5_fpr: %s\n", dn?dn:"error"); + xfree (dn); + ksba_cert_get_validity (cert, 0, t); - fputs (" validity: ", fp); + fputs (" notBefore: ", fp); gpgsm_print_time (fp, t); - fputs (" through ", fp); + putc ('\n', fp); + fputs (" notAfter: ", fp); ksba_cert_get_validity (cert, 1, t); gpgsm_print_time (fp, t); putc ('\n', fp); + oid = ksba_cert_get_digest_algo (cert); + s = get_oid_desc (oid, NULL); + fprintf (fp, " hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":""); + + /* authorityKeyIdentifier */ + fputs (" authKeyId: ", fp); + err = ksba_cert_get_auth_key_id (cert, NULL, &name, &sexp); + if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) + { + if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name) + fputs ("[none]\n", fp); + else + { + gpgsm_print_serial (fp, sexp); + ksba_free (sexp); + putc ('\n', fp); + print_names_raw (fp, -15, name); + ksba_name_release (name); + } + } + else + fputs ("[?]\n", fp); + + fputs (" keyUsage:", fp); err = ksba_cert_get_key_usage (cert, &kusage); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { - fputs (" key usage:", fp); if (err) fprintf (fp, " [error: %s]", gpg_strerror (err)); else @@ -410,11 +595,13 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, } putc ('\n', fp); } + else + fputs ("[none]\n", fp); + fputs (" extKeyUsage: ", fp); err = ksba_cert_get_ext_key_usages (cert, &string); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { - fputs ("ext key usage: ", fp); if (err) fprintf (fp, "[error: %s]", gpg_strerror (err)); else @@ -433,37 +620,53 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, if ((p = strchr (p, '\n'))) { p++; - fputs (", ", fp); + fputs ("\n ", fp); } } xfree (string); } putc ('\n', fp); } + else + fputs ("[none]\n", fp); + + fputs (" policies: ", fp); err = ksba_cert_get_cert_policies (cert, &string); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { - fputs (" policies: ", fp); if (err) fprintf (fp, "[error: %s]", gpg_strerror (err)); else { - for (p=string; *p; p++) + p = string; + while (p && (pend=strchr (p, ':'))) { - if (*p == '\n') - *p = ','; + *pend++ = 0; + for (i=0; key_purpose_map[i].oid; i++) + if ( !strcmp (key_purpose_map[i].oid, p) ) + break; + fputs (p, fp); + p = pend; + if (*p == 'C') + fputs (" (critical)", fp); + if ((p = strchr (p, '\n'))) + { + p++; + fputs ("\n ", fp); + } } - print_sanitized_string (fp, string, 0); xfree (string); } putc ('\n', fp); } + else + fputs ("[none]\n", fp); + fputs (" chainLength: ", fp); err = ksba_cert_is_ca (cert, &is_ca, &chainlen); if (err || is_ca) { - fputs (" chain length: ", fp); if (err) fprintf (fp, "[error: %s]", gpg_strerror (err)); else if (chainlen == -1) @@ -472,14 +675,92 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, fprintf (fp, "%d", chainlen); putc ('\n', fp); } + else + fputs ("not a CA\n", fp); - dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5); - fprintf (fp, " md5 fpr: %s\n", dn?dn:"error"); - xfree (dn); - dn = gpgsm_get_fingerprint_string (cert, 0); - fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); - xfree (dn); + /* CRL distribution point */ + for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2, + &reason)) ;idx++) + { + fputs (" crlDP: ", fp); + print_names_raw (fp, 15, name); + if (reason) + { + fputs (" reason: ", fp); + if ( (reason & KSBA_CRLREASON_UNSPECIFIED)) + fputs (" unused", stdout); + if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE)) + fputs (" keyCompromise", stdout); + if ( (reason & KSBA_CRLREASON_CA_COMPROMISE)) + fputs (" caCompromise", stdout); + if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED)) + fputs (" affiliationChanged", stdout); + if ( (reason & KSBA_CRLREASON_SUPERSEDED)) + fputs (" superseded", stdout); + if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION)) + fputs (" cessationOfOperation", stdout); + if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD)) + fputs (" certificateHold", stdout); + putchar ('\n'); + } + fputs (" issuer: ", fp); + print_names_raw (fp, 23, name2); + ksba_name_release (name); + ksba_name_release (name2); + } + if (err && gpg_err_code (err) != GPG_ERR_EOF) + fputs (" crlDP: [error]\n", fp); + else if (!idx) + fputs (" crlDP: [none]\n", fp); + + + /* authorityInfoAccess. */ + for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string, + &name)); idx++) + { + fputs (" authInfo: ", fp); + s = get_oid_desc (string, NULL); + fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":""); + print_names_raw (fp, -15, name); + ksba_name_release (name); + ksba_free (string); + } + if (err && gpg_err_code (err) != GPG_ERR_EOF) + fputs (" authInfo: [error]\n", fp); + else if (!idx) + fputs (" authInfo: [none]\n", fp); + + /* subjectInfoAccess. */ + for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string, + &name)); idx++) + { + fputs (" subjectInfo: ", fp); + s = get_oid_desc (string, NULL); + fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":""); + print_names_raw (fp, -15, name); + ksba_name_release (name); + ksba_free (string); + } + if (err && gpg_err_code (err) != GPG_ERR_EOF) + fputs (" subjInfo: [error]\n", fp); + else if (!idx) + fputs (" subjInfo: [none]\n", fp); + + + for (idx=0; !(err=ksba_cert_get_extension (cert, idx, + &oid, &i, &off, &len));idx++) + { + unsigned int flag; + + s = get_oid_desc (oid, &flag); + + if (!(flag & 1)) + fprintf (fp, " %s: %s%s%s%s [%d octets]\n", + i? "critExtn":" extn", + oid, s?" (":"", s?s:"", s?")":"", (int)len); + } + if (with_validation) { -- cgit v1.2.3 From 6aaceac7fec0b98b60ab1259bda5f97465817ce6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 26 Apr 2004 08:09:25 +0000 Subject: The keybox gets now compressed after 3 hours and ephemeral stored certificates are deleted after about a day. --- NEWS | 6 ++ TODO | 1 - doc/gpgsm.texi | 23 +++++- kbx/ChangeLog | 24 ++++++ kbx/Manifest | 8 ++ kbx/keybox-blob.c | 27 ++++++- kbx/keybox-defs.h | 3 + kbx/keybox-dump.c | 27 ++++++- kbx/keybox-file.c | 50 +++++++++++- kbx/keybox-search.c | 53 ++++++++----- kbx/keybox-update.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++------ kbx/keybox.h | 6 +- sm/ChangeLog | 2 + sm/keydb.c | 15 ++++ 14 files changed, 413 insertions(+), 57 deletions(-) create mode 100644 kbx/Manifest diff --git a/NEWS b/NEWS index 31f76b6c8..4e246f6d6 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,12 @@ Noteworthy changes in version 1.9.8 * [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. + Noteworthy changes in version 1.9.7 (2004-04-06) ------------------------------------------------ diff --git a/TODO b/TODO index 1d12b7446..21c44a925 100644 --- a/TODO +++ b/TODO @@ -41,7 +41,6 @@ might want to have an agent context for each service request * sm/keydb.c ** Check file permissions -** Write a keybox header and check for that magic value. ** Check that all error code mapping is done. ** Remove the inter-module dependencies between gpgsm and keybox ** Add an source_of_key field diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 977fe3c37..a0da96d56 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -130,17 +130,36 @@ use @samp{--help} to get a list of supported operations. 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 keys whenre a secret key is available. +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 -utilies the @code{dirmngr} service. +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 --delete-keys @var{pattern} @opindex delete-keys diff --git a/kbx/ChangeLog b/kbx/ChangeLog index d6c75025e..aa39df815 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,27 @@ +2004-04-23 Werner Koch <wk@gnupg.org> + + * keybox-blob.c (_keybox_update_header_blob): New. + * keybox-update.c (blob_filecopy): Handle header blob. + * keybox-file.c (_keybox_read_blob2): New. Moved code from + _keybox_read_blob to there. + * keybox-dump.c (dump_header_blob): Print header info. + +2004-04-21 Werner Koch <wk@gnupg.org> + + * keybox-search.c (_keybox_get_flag_location): Add flag + KEYBOX_FLAG_CREATED_AT. + * keybox-update.c (keybox_compress): New. + + * keybox-search.c (get32, get16, blob_get_type) + (blob_get_blob_flags, has_short_kid, has_long_kid) + (has_fingerprint, has_issuer, has_issuer_sn, has_sn, has_subject) + (has_subject_or_alt, has_mail): inline them. + + * keybox-update.c (blob_filecopy): Fixed an error/eof check + (s/if(fread)/if(nread)/). + + * keybox-dump.c (_keybox_dump_blob): Really print the timestamps. + 2004-04-20 Werner Koch <wk@gnupg.org> * keybox-defs.h: Include jnlib/types.h and remove our own diff --git a/kbx/Manifest b/kbx/Manifest new file mode 100644 index 000000000..95f48d73f --- /dev/null +++ b/kbx/Manifest @@ -0,0 +1,8 @@ + +keybox-update.c +keybox-file.c + + + + +$names$ diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 96595436c..48bce28e2 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -35,9 +35,11 @@ The first record of a plain KBX file has a special format: byte reserved byte reserved u32 magic 'KBXf' - byte pgp_marginals used for validity calculation of this file - byte pgp_completes ditto. - byte pgp_cert_depth ditto. + u32 reserved + u32 file_created_at + u32 last_maintenance_run + u32 reserved + u32 reserved The OpenPGP and X.509 blob are very similiar, things which are X.509 specific are noted like [X.509: xxx] @@ -85,7 +87,7 @@ X.509 specific are noted like [X.509: xxx] u8 assigned ownertrust [X509: not used] u8 all_validity OpenPGP: see ../g10/trustdb/TRUST_* [not yet used] - X509: Bit 4 set := key has been revoked. nOte that this value + X509: Bit 4 set := key has been revoked. Note that this value matches TRUST_FLAG_REVOKED u16 reserved u32 recheck_after @@ -978,6 +980,7 @@ _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off) return 0; } + void _keybox_release_blob (KEYBOXBLOB blob) { @@ -1010,3 +1013,19 @@ _keybox_get_blob_fileoffset (KEYBOXBLOB blob) return blob->fileoffset; } + + +void +_keybox_update_header_blob (KEYBOXBLOB blob) +{ + if (blob->bloblen >= 32 && blob->blob[4] == BLOBTYPE_HEADER) + { + u32 val = make_timestamp (); + + /* Update the last maintenance run times tamp. */ + blob->blob[20] = (val >> 24); + blob->blob[20+1] = (val >> 16); + blob->blob[20+2] = (val >> 8); + blob->blob[20+3] = (val ); + } +} diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index d7e132d6b..705762c41 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -106,10 +106,13 @@ int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, void _keybox_release_blob (KEYBOXBLOB blob); const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); +void _keybox_update_header_blob (KEYBOXBLOB blob); /*-- keybox-file.c --*/ int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); +int _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted); int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp); +int _keybox_write_header_blob (FILE *fp); /*-- keybox-search.c --*/ gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer, diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index 2177bedae..2fb0984c0 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -78,9 +78,22 @@ print_string (FILE *fp, const byte *p, size_t n, int delim) static int dump_header_blob (const byte *buffer, size_t length, FILE *fp) { + unsigned long n; + + if (length < 32) + { + fprintf (fp, "[blob too short]\n"); + return -1; + } fprintf (fp, "Version: %d\n", buffer[5]); if ( memcmp (buffer+8, "KBXf", 4)) fprintf (fp, "[Error: invalid magic number]\n"); + + n = get32 (buffer+16); + fprintf( fp, "created-at: %lu\n", n ); + n = get32 (buffer+20); + fprintf( fp, "last-maint: %lu\n", n ); + return 0; } @@ -101,7 +114,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) + if (length < 32) { fprintf (fp, "[blob too short]\n"); return -1; @@ -136,6 +149,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) return 0; } fprintf (fp, "Version: %d\n", buffer[5]); + + if (length < 40) + { + fprintf (fp, "[blob too short]\n"); + return -1; + } n = get16 (buffer + 6); fprintf( fp, "Blob-Flags: %04lX", n); @@ -290,11 +309,11 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) fprintf (fp, "All-Validity: %d\n", p[1] ); p += 4; n = get32 (p); p += 4; - fprintf (fp, "Recheck-After: %s\n", /*n? strtimestamp(n) :*/ "0" ); + fprintf (fp, "Recheck-After: %lu\n", n ); n = get32 (p ); p += 4; - fprintf( fp, "Latest-Timestamp: %s\n", "0"/*strtimestamp(n)*/ ); + fprintf( fp, "Latest-Timestamp: %lu\n", n ); n = get32 (p ); p += 4; - fprintf (fp, "Created-At: %s\n", "0"/*strtimestamp(n)*/ ); + fprintf (fp, "Created-At: %lu\n", n ); n = get32 (p ); p += 4; fprintf (fp, "Reserved-Space: %lu\n", n ); diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c index fc9321478..db3164fef 100644 --- a/kbx/keybox-file.c +++ b/kbx/keybox-file.c @@ -23,13 +23,14 @@ #include <stdio.h> #include <string.h> #include <errno.h> +#include <time.h> #include "keybox-defs.h" /* Read a block at the current postion and return it in r_blob. r_blob may be NULL to simply skip the current block */ int -_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) +_keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted) { char *image; size_t imagelen = 0; @@ -37,6 +38,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) int rc; off_t off; + *skipped_deleted = 0; again: *r_blob = NULL; off = ftello (fp); @@ -55,7 +57,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) } imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; - if (imagelen > 500000) /* sanity check */ + if (imagelen > 500000) /* Sanity check. */ return gpg_error (GPG_ERR_TOO_LARGE); if (imagelen < 5) @@ -63,9 +65,10 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) if (!type) { - /* special treatment for empty blobs. */ + /* Special treatment for empty blobs. */ if (fseek (fp, imagelen-5, SEEK_CUR)) return gpg_error (gpg_err_code_from_errno (errno)); + *skipped_deleted = 1; goto again; } @@ -87,6 +90,13 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) return rc; } +int +_keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) +{ + int dummy; + return _keybox_read_blob2 (r_blob, fp, &dummy); +} + /* Write the block to the current file position */ int @@ -100,3 +110,37 @@ _keybox_write_blob (KEYBOXBLOB blob, FILE *fp) return gpg_error (gpg_err_code_from_errno (errno)); return 0; } + + +/* Write a fresh header type blob. */ +int +_keybox_write_header_blob (FILE *fp) +{ + unsigned char image[32]; + u32 val; + + memset (image, 0, sizeof image); + /* Length of this blob. */ + image[3] = 32; + + image[4] = BLOBTYPE_HEADER; + image[5] = 1; /* Version */ + + memcpy (image+8, "KBXf", 4); + val = time (NULL); + /* created_at and last maintenance run. */ + image[16] = (val >> 24); + image[16+1] = (val >> 16); + image[16+2] = (val >> 8); + image[16+3] = (val ); + image[20] = (val >> 24); + image[20+1] = (val >> 16); + image[20+2] = (val >> 8); + image[20+3] = (val ); + + if (fwrite (image, 32, 1, fp) != 1) + return gpg_error (gpg_err_code_from_errno (errno)); + return 0; +} + + diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index f23bfdada..2ce3c1923 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -42,7 +42,7 @@ struct sn_array_s { -static ulong +static inline ulong get32 (const byte *buffer) { ulong a; @@ -53,7 +53,7 @@ get32 (const byte *buffer) return a; } -static ulong +static inline ulong get16 (const byte *buffer) { ulong a; @@ -64,20 +64,20 @@ get16 (const byte *buffer) -static int +static inline int blob_get_type (KEYBOXBLOB blob) { const unsigned char *buffer; size_t length; buffer = _keybox_get_blob_image (blob, &length); - if (length < 40) + if (length < 32) return -1; /* blob too short */ return buffer[4]; } -static unsigned int +static inline unsigned int blob_get_blob_flags (KEYBOXBLOB blob) { const unsigned char *buffer; @@ -113,8 +113,9 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length, *flag_size = 2; break; - case KEYBOX_FLAG_VALIDITY: case KEYBOX_FLAG_OWNERTRUST: + case KEYBOX_FLAG_VALIDITY: + case KEYBOX_FLAG_CREATED_AT: if (length < 20) return GPG_ERR_INV_OBJ; /* Key info. */ @@ -148,8 +149,18 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length, return GPG_ERR_INV_OBJ ; /* Out of bounds. */ *flag_size = 1; *flag_off = pos; - if (what == KEYBOX_FLAG_VALIDITY) - ++*flag_off; + switch (what) + { + case KEYBOX_FLAG_VALIDITY: + *flag_off += 1; + break; + case KEYBOX_FLAG_CREATED_AT: + *flag_size = 4; + *flag_off += 1+2+4+4+4; + break; + default: + break; + } break; default: @@ -158,6 +169,8 @@ _keybox_get_flag_location (const unsigned char *buffer, size_t length, return 0; } + + /* Return one of the flags WHAT in VALUE from teh blob BUFFER of LENGTH bytes. Return 0 on success or an raw error code. */ static gpg_err_code_t @@ -447,26 +460,26 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr) /* The has_foo functions are used as helpers for search */ -static int +static inline int has_short_kid (KEYBOXBLOB blob, const unsigned char *kid) { return blob_cmp_fpr_part (blob, kid+4, 16, 4); } -static int +static inline int has_long_kid (KEYBOXBLOB blob, const unsigned char *kid) { return blob_cmp_fpr_part (blob, kid, 12, 8); } -static int +static inline int has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr) { return blob_cmp_fpr (blob, fpr); } -static int +static inline int has_issuer (KEYBOXBLOB blob, const char *name) { size_t namelen; @@ -480,7 +493,7 @@ has_issuer (KEYBOXBLOB blob, const char *name) return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0); } -static int +static inline int has_issuer_sn (KEYBOXBLOB blob, const char *name, const unsigned char *sn, int snlen) { @@ -498,7 +511,7 @@ has_issuer_sn (KEYBOXBLOB blob, const char *name, && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0)); } -static int +static inline int has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) { return_val_if_fail (sn, 0); @@ -508,7 +521,7 @@ has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen) return blob_cmp_sn (blob, sn, snlen); } -static int +static inline int has_subject (KEYBOXBLOB blob, const char *name) { size_t namelen; @@ -522,7 +535,7 @@ has_subject (KEYBOXBLOB blob, const char *name) return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0); } -static int +static inline int has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr) { size_t namelen; @@ -538,7 +551,7 @@ has_subject_or_alt (KEYBOXBLOB blob, const char *name, int substr) } -static int +static inline int has_mail (KEYBOXBLOB blob, const char *name, int substr) { size_t namelen; @@ -728,6 +741,10 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) if (rc) break; + if (blob_get_type (blob) == BLOBTYPE_HEADER) + continue; + + blobflags = blob_get_blob_flags (blob); if (!hd->ephemeral && (blobflags & 2)) continue; /* not in ephemeral mode but blob is flagged ephemeral */ @@ -906,7 +923,7 @@ keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert) #endif /*KEYBOX_WITH_X509*/ -/* Return the flags named WHAT iat the address of VALUE. IDX is used +/* Return the flags named WHAT at the address of VALUE. IDX is used only for certain flags and should be 0 if not required. */ int keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value) diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index 47e53966a..16955502f 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -1,5 +1,5 @@ /* keybox-update.c - keybox update operations - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,6 +23,7 @@ #include <stdio.h> #include <string.h> #include <errno.h> +#include <time.h> #include <unistd.h> #include "keybox-defs.h" @@ -193,29 +194,30 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, fp = fopen (fname, "rb"); if (mode == 1 && !fp && errno == ENOENT) - { /* insert mode but file does not exist: create a new keybox file */ + { + /* Insert mode but file does not exist: + Create a new keybox file. */ newfp = fopen (fname, "wb"); if (!newfp ) - { - return gpg_error (gpg_err_code_from_errno (errno)); - } + return gpg_error (gpg_err_code_from_errno (errno)); + + rc = _keybox_write_header_blob (newfp); + if (rc) + return rc; rc = _keybox_write_blob (blob, newfp); if (rc) - { - return rc; - } + return rc; + if ( fclose (newfp) ) - { - return gpg_error (gpg_err_code_from_errno (errno)); - } + return gpg_error (gpg_err_code_from_errno (errno)); /* if (chmod( fname, S_IRUSR | S_IWUSR )) */ /* { */ /* log_debug ("%s: chmod failed: %s\n", fname, strerror(errno) ); */ /* return KEYBOX_File_Error; */ /* } */ - return 0; /* ready */ + return 0; /* Ready. */ } if (!fp) @@ -224,7 +226,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, goto leave; } - /* create the new file */ + /* Create the new file. */ rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); if (rc) { @@ -235,7 +237,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, /* prepare for insert */ if (mode == 1) { - /* copy everything to the new file */ + /* Copy everything to the new file. */ while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) { if (fwrite (buffer, nread, 1, newfp) != 1) @@ -251,19 +253,19 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, } } - /* prepare for delete or update */ + /* Prepare for delete or update. */ if ( mode == 2 || mode == 3 ) { off_t current = 0; - /* copy first part to the new file */ + /* Copy first part to the new file. */ while ( current < start_offset ) { nbytes = DIM(buffer); if (current + nbytes > start_offset) nbytes = start_offset - current; nread = fread (buffer, 1, nbytes, fp); - if (!fread) + if (!nread) break; current += nread; @@ -279,13 +281,13 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, goto leave; } - /* skip this blob */ + /* Skip this blob. */ rc = _keybox_read_blob (NULL, fp); if (rc) return rc; } - /* Do an insert or update */ + /* Do an insert or update. */ if ( mode == 1 || mode == 3 ) { rc = _keybox_write_blob (blob, newfp); @@ -293,7 +295,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, return rc; } - /* copy the rest of the packet for an delete or update */ + /* Copy the rest of the packet for an delete or update. */ if (mode == 2 || mode == 3) { while ( (nread = fread (buffer, 1, DIM(buffer), fp)) > 0 ) @@ -311,7 +313,7 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, } } - /* close both files */ + /* Close both files. */ if (fclose(fp)) { rc = gpg_error (gpg_err_code_from_errno (errno)); @@ -334,7 +336,6 @@ blob_filecopy (int mode, const char *fname, KEYBOXBLOB blob, - #ifdef KEYBOX_WITH_X509 int keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, @@ -352,7 +353,7 @@ keybox_insert_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, if (!fname) return gpg_error (GPG_ERR_INV_HANDLE); - /* close this one otherwise we will mess up the position for a next + /* Close this one otherwise we will mess up the position for a next search. Fixme: it would be better to adjust the position after the write opertions. */ if (hd->fp) @@ -517,3 +518,181 @@ keybox_delete (KEYBOX_HANDLE hd) } +/* Compress the keybox file. This should be run with the file + locked. */ +int +keybox_compress (KEYBOX_HANDLE hd) +{ + int read_rc, rc; + const char *fname; + FILE *fp, *newfp; + char *bakfname = NULL; + char *tmpfname = NULL; + int first_blob; + KEYBOXBLOB blob = NULL; + u32 cut_time; + int any_changes = 0; + int skipped_deleted; + + if (!hd) + return gpg_error (GPG_ERR_INV_HANDLE); + if (!hd->kb) + return gpg_error (GPG_ERR_INV_HANDLE); + if (hd->secret) + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + fname = hd->kb->fname; + if (!fname) + return gpg_error (GPG_ERR_INV_HANDLE); + + if (hd->fp) + { + fclose (hd->fp); + hd->fp = NULL; + } + + /* Open the source file. Because we do a rename, we have to check the + permissions of the file */ + if (access (fname, W_OK)) + return gpg_error (gpg_err_code_from_errno (errno)); + + fp = fopen (fname, "rb"); + if (!fp && errno == ENOENT) + return 0; /* Ready. File has been deleted right after the access above. */ + if (!fp) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + return rc; + } + + /* A quick test to see if we need to compress the file at all. We + schedule a compress run after 3 hours. */ + if ( !_keybox_read_blob (&blob, fp) ) + { + const unsigned char *buffer; + size_t length; + + buffer = _keybox_get_blob_image (blob, &length); + if (length > 4 && buffer[4] == BLOBTYPE_HEADER) + { + u32 last_maint = ((buffer[20] << 24) | (buffer[20+1] << 16) + | (buffer[20+2] << 8) | (buffer[20+3])); + + if ( (last_maint + 3*3600) > time (NULL) ) + { + fclose (fp); + _keybox_release_blob (blob); + return 0; /* Compress run not yet needed. */ + } + } + _keybox_release_blob (blob); + rewind (fp); + } + + /* Create the new file. */ + rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); + if (rc) + { + fclose(fp); + return rc;; + } + + + /* Processing loop. By reading using _keybox_read_blob we + automagically skip and blobs flagged as deleted. Thus what we + only have to do is to check all ephemeral flagged blocks whether + their time has come and write out all other blobs. */ + cut_time = time(NULL) - 86400; + first_blob = 1; + skipped_deleted = 0; + for (rc=0; !(read_rc = _keybox_read_blob2 (&blob, fp, &skipped_deleted)); + _keybox_release_blob (blob), blob = NULL ) + { + unsigned int blobflags; + const unsigned char *buffer; + size_t length, pos, size; + u32 created_at; + + if (skipped_deleted) + any_changes = 1; + buffer = _keybox_get_blob_image (blob, &length); + if (first_blob) + { + first_blob = 0; + if (length > 4 && buffer[4] == BLOBTYPE_HEADER) + { + /* Write out the blob with an updated maintenance time stamp. */ + _keybox_update_header_blob (blob); + rc = _keybox_write_blob (blob, newfp); + if (rc) + break; + continue; + } + + /* The header blob is missing. Insert it. */ + rc = _keybox_write_header_blob (newfp); + if (rc) + break; + any_changes = 1; + } + else if (length > 4 && buffer[4] == BLOBTYPE_HEADER) + { + /* Oops: There is another header record - remove it. */ + any_changes = 1; + continue; + } + + if (_keybox_get_flag_location (buffer, length, + KEYBOX_FLAG_BLOB, &pos, &size) + || size != 2) + { + rc = gpg_error (GPG_ERR_BUG); + break; + } + blobflags = ((buffer[pos] << 8) | (buffer[pos+1])); + if ((blobflags & 2)) + { + /* This is an ephemeral blob. */ + if (_keybox_get_flag_location (buffer, length, + KEYBOX_FLAG_CREATED_AT, &pos, &size) + || size != 4) + created_at = 0; /* oops. */ + else + created_at = ((buffer[pos] << 24) | (buffer[pos+1] << 16) + | (buffer[pos+2] << 8) | (buffer[pos+3])); + + if (created_at && created_at < cut_time) + { + any_changes = 1; + continue; /* Skip this blob. */ + } + } + + rc = _keybox_write_blob (blob, newfp); + if (rc) + break; + } + if (skipped_deleted) + any_changes = 1; + _keybox_release_blob (blob); blob = NULL; + if (!rc && read_rc == -1) + rc = 0; + else if (!rc) + rc = read_rc; + + /* Close both files. */ + if (fclose(fp) && !rc) + rc = gpg_error (gpg_err_code_from_errno (errno)); + if (fclose(newfp) && !rc) + rc = gpg_error (gpg_err_code_from_errno (errno)); + + /* Rename or remove the temporary file. */ + if (rc || !any_changes) + remove (tmpfname); + else + rc = rename_tmp_file (bakfname, tmpfname, fname, hd->secret); + + xfree(bakfname); + xfree(tmpfname); + return rc; +} + diff --git a/kbx/keybox.h b/kbx/keybox.h index e4dc9d642..af1fc4516 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -52,9 +52,10 @@ typedef enum KEYBOX_FLAG_OWNERTRUST, /* The assigned ownertrust. */ KEYBOX_FLAG_KEY, /* The key flags; requires a key index. */ KEYBOX_FLAG_UID, /* The user ID flags; requires an uid index. */ - KEYBOX_FLAG_UID_VALIDITY/* The validity of a specific uid, requires + KEYBOX_FLAG_UID_VALIDITY,/* The validity of a specific uid, requires an uid index. */ - } keyxox_flag_t; + KEYBOX_FLAG_CREATED_AT /* The date the block was created. */ + } keybox_flag_t; /*-- keybox-init.c --*/ @@ -87,6 +88,7 @@ int keybox_update_cert (KEYBOX_HANDLE hd, ksba_cert_t cert, int keybox_set_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int value); int keybox_delete (KEYBOX_HANDLE hd); +int keybox_compress (KEYBOX_HANDLE hd); /*-- --*/ diff --git a/sm/ChangeLog b/sm/ChangeLog index 28171b963..8c0297d28 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,7 @@ 2004-04-23 Werner Koch <wk@gnupg.org> + * keydb.c (keydb_add_resource): Try to compress the file on init. + * keylist.c (oidtranstbl): New. OIDs collected from several sources. (print_name_raw, print_names_raw, list_cert_raw): New. (gpgsm_list_keys): Check the dump mode and pass it down as diff --git a/sm/keydb.c b/sm/keydb.c index 858baf242..322307553 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -218,10 +218,25 @@ keydb_add_resource (const char *url, int force, int secret) = create_dotlock (filename); if (!all_resources[used_resources].lockhandle) log_fatal ( _("can't create lock for `%s'\n"), filename); + + /* Do a compress run if needed and the file is not locked. */ + if (!make_dotlock (all_resources[used_resources].lockhandle, 0)) + { + KEYBOX_HANDLE kbxhd = keybox_new (token, secret); + + if (kbxhd) + { + keybox_compress (kbxhd); + keybox_release (kbxhd); + } + release_dotlock (all_resources[used_resources].lockhandle); + } used_resources++; } } + + break; default: log_error ("resource type of `%s' not supported\n", url); -- cgit v1.2.3 From 1101deced5790f04bc7c5913616dfd4ba557055b Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 26 Apr 2004 13:07:08 +0000 Subject: 2004-04-26 Marcus Brinkmann <marcus@g10code.de> * scdaemon.c (main): For now, always print default filename for --gpgconf-list, and never /dev/null. --- scd/ChangeLog | 5 +++++ scd/scdaemon.c | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 037090863..eb2074bba 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-04-26 Marcus Brinkmann <marcus@g10code.de> + + * scdaemon.c (main): For now, always print default filename for + --gpgconf-list, and never /dev/null. + 2004-04-21 Werner Koch <wk@gnupg.org> * command.c (scd_update_reader_status_file): Send a signal back to diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 5066a373b..d0306aeb6 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -538,7 +538,10 @@ main (int argc, char **argv ) } if (gpgconf_list) - { /* List options and default values in the GPG Conf format. */ + { + char *filename; + + /* List options and default values in the GPG Conf format. */ /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING @@ -557,9 +560,10 @@ main (int argc, char **argv ) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + filename = make_filename (opt.homedir, "scdaemon.conf", NULL); printf ("gpgconf-scdaemon.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, - config_filename?config_filename:"/dev/null"); + GC_OPT_FLAG_DEFAULT, filename); + xfree (filename); printf ("verbose:%lu:\n" "quiet:%lu:\n" -- cgit v1.2.3 From 388218891b10daae07b07dee0ad0c10149413629 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 26 Apr 2004 13:29:09 +0000 Subject: * call-agent.c (gpgsm_agent_pksign, gpgsm_agent_pkdecrypt) (gpgsm_agent_genkey, gpgsm_agent_istrusted) (gpgsm_agent_marktrusted, gpgsm_agent_havekey) (gpgsm_agent_passwd): Add new arg CTRL and changed all callers. (start_agent): New arg CTRL. Send progress item when starting a new agent. * sign.c (gpgsm_get_default_cert, get_default_signer): New arg CTRL to be passed down to the agent function. * decrypt.c (prepare_decryption): Ditto. * certreqgen.c (proc_parameters, read_parameters): Ditto. * certcheck.c (gpgsm_create_cms_signature): Ditto. --- TODO | 1 - sm/ChangeLog | 14 ++++++++++++++ sm/call-agent.c | 43 +++++++++++++++++++++++-------------------- sm/certchain.c | 4 ++-- sm/certcheck.c | 6 +++--- sm/certlist.c | 4 ++-- sm/certreqgen.c | 30 +++++++++++++++++------------- sm/decrypt.c | 9 +++++---- sm/export.c | 2 +- sm/gpgsm.c | 4 ++-- sm/gpgsm.h | 22 ++++++++++++---------- sm/keylist.c | 4 ++-- sm/sign.c | 13 +++++++------ 13 files changed, 90 insertions(+), 66 deletions(-) diff --git a/TODO b/TODO index 21c44a925..80035b69b 100644 --- a/TODO +++ b/TODO @@ -11,7 +11,6 @@ We should always use valid S-Exp and not just parts. ** When we allow concurrent service request in gpgsm, we might want to have an agent context for each service request (i.e. Assuan context). -** There is no error report if GPG_AGENT_INFO has been set but the agent is not anymore running. * sm/certreqgen.c ** Improve error reporting diff --git a/sm/ChangeLog b/sm/ChangeLog index 8c0297d28..6c3ff32fb 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,17 @@ +2004-04-26 Werner Koch <wk@gnupg.org> + + * call-agent.c (gpgsm_agent_pksign, gpgsm_agent_pkdecrypt) + (gpgsm_agent_genkey, gpgsm_agent_istrusted) + (gpgsm_agent_marktrusted, gpgsm_agent_havekey) + (gpgsm_agent_passwd): Add new arg CTRL and changed all callers. + (start_agent): New arg CTRL. Send progress item when starting a + new agent. + * sign.c (gpgsm_get_default_cert, get_default_signer): New arg + CTRL to be passed down to the agent function. + * decrypt.c (prepare_decryption): Ditto. + * certreqgen.c (proc_parameters, read_parameters): Ditto. + * certcheck.c (gpgsm_create_cms_signature): Ditto. + 2004-04-23 Werner Koch <wk@gnupg.org> * keydb.c (keydb_add_resource): Try to compress the file on init. diff --git a/sm/call-agent.c b/sm/call-agent.c index 15ae5eacc..2e8c75496 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -65,7 +65,7 @@ struct learn_parm_s { /* 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) +start_agent (ctrl_t ctrl) { int rc = 0; char *infostr, *p; @@ -86,6 +86,8 @@ start_agent (void) if (opt.verbose) log_info (_("no running gpg-agent - starting one\n")); + + gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0"); if (fflush (NULL)) { @@ -126,7 +128,7 @@ start_agent (void) log_error (_("malformed GPG_AGENT_INFO environment variable\n")); xfree (infostr); force_pipe_server = 1; - return start_agent (); + return start_agent (ctrl); } *p++ = 0; pid = atoi (p); @@ -139,7 +141,7 @@ start_agent (void) prot); xfree (infostr); force_pipe_server = 1; - return start_agent (); + return start_agent (ctrl); } rc = assuan_socket_connect (&ctx, infostr, pid); @@ -148,7 +150,7 @@ start_agent (void) { log_error (_("can't connect to the agent - trying fall back\n")); force_pipe_server = 1; - return start_agent (); + return start_agent (ctrl); } } @@ -188,7 +190,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length) /* Call the agent to do a sign operation using the key identified by the hex string KEYGRIP. */ int -gpgsm_agent_pksign (const char *keygrip, const char *desc, +gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc, unsigned char *digest, size_t digestlen, int digestalgo, char **r_buf, size_t *r_buflen ) { @@ -198,7 +200,7 @@ gpgsm_agent_pksign (const char *keygrip, const char *desc, size_t len; *r_buf = NULL; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -273,7 +275,7 @@ inq_ciphertext_cb (void *opaque, const char *keyword) /* Call the agent to do a decrypt operation using the key identified by the hex string KEYGRIP. */ int -gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc, +gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen ) { @@ -293,7 +295,7 @@ gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc, if (!ciphertextlen) return gpg_error (GPG_ERR_INV_VALUE); - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -371,7 +373,8 @@ inq_genkey_parms (void *opaque, const char *keyword) /* Call the agent to generate a newkey */ int -gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey) +gpgsm_agent_genkey (ctrl_t ctrl, + ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey) { int rc; struct genkey_parm_s gk_parm; @@ -380,7 +383,7 @@ gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey) char *buf; *r_pubkey = NULL; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -418,13 +421,13 @@ gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey) /* Ask the agent whether the certificate is in the list of trusted keys */ int -gpgsm_agent_istrusted (ksba_cert_t cert) +gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert) { int rc; char *fpr; char line[ASSUAN_LINELENGTH]; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -445,13 +448,13 @@ gpgsm_agent_istrusted (ksba_cert_t cert) /* Ask the agent to mark CERT as a trusted Root-CA one */ int -gpgsm_agent_marktrusted (ksba_cert_t cert) +gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert) { int rc; char *fpr, *dn; char line[ASSUAN_LINELENGTH]; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -482,12 +485,12 @@ gpgsm_agent_marktrusted (ksba_cert_t cert) /* Ask the agent whether the a corresponding secret key is available for the given keygrip */ int -gpgsm_agent_havekey (const char *hexkeygrip) +gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip) { int rc; char line[ASSUAN_LINELENGTH]; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -572,14 +575,14 @@ learn_cb (void *opaque, const void *buffer, size_t length) /* Call the agent to learn about a smartcard */ int -gpgsm_agent_learn () +gpgsm_agent_learn (ctrl_t ctrl) { int rc; struct learn_parm_s learn_parm; membuf_t data; size_t len; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; @@ -601,12 +604,12 @@ gpgsm_agent_learn () HEXKEYGRIP. If DESC is not NULL, display instead of the default description message. */ int -gpgsm_agent_passwd (const char *hexkeygrip, const char *desc) +gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc) { int rc; char line[ASSUAN_LINELENGTH]; - rc = start_agent (); + rc = start_agent (ctrl); if (rc) return rc; diff --git a/sm/certchain.c b/sm/certchain.c index 3bdba2a9d..3009c21aa 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -666,7 +666,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, if (rc) goto leave; - rc = gpgsm_agent_istrusted (subject_cert); + rc = gpgsm_agent_istrusted (ctrl, subject_cert); if (!rc) ; else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) @@ -679,7 +679,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, GCRY_MD_SHA1); log_info (_("fingerprint=%s\n"), fpr? fpr : "?"); xfree (fpr); - rc2 = gpgsm_agent_marktrusted (subject_cert); + rc2 = gpgsm_agent_marktrusted (ctrl, subject_cert); if (!rc2) { log_info (_("root certificate has now" diff --git a/sm/certcheck.c b/sm/certcheck.c index 271557ae7..b5ed9914a 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -278,8 +278,8 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, int -gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, - char **r_sigval) +gpgsm_create_cms_signature (ctrl_t ctrl, ksba_cert_t cert, + gcry_md_hd_t md, int mdalgo, char **r_sigval) { int rc; char *grip, *desc; @@ -291,7 +291,7 @@ gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, desc = gpgsm_format_keydesc (cert); - rc = gpgsm_agent_pksign (grip, desc, gcry_md_read(md, mdalgo), + rc = gpgsm_agent_pksign (ctrl, grip, desc, gcry_md_read(md, mdalgo), gcry_md_get_algo_dlen (mdalgo), mdalgo, r_sigval, &siglen); xfree (desc); diff --git a/sm/certlist.c b/sm/certlist.c index 0394a584f..96acf90f7 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -245,7 +245,7 @@ gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, available for the certificate. IS_ENCRYPT_TO sets the corresponding flag in the new create LISTADDR item. */ int -gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, +gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, CERTLIST *listaddr, int is_encrypt_to) { int rc; @@ -342,7 +342,7 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret, p = gpgsm_get_keygrip_hexstring (cert); if (p) { - if (!gpgsm_agent_havekey (p)) + if (!gpgsm_agent_havekey (ctrl, p)) rc = 0; xfree (p); } diff --git a/sm/certreqgen.c b/sm/certreqgen.c index a0addd2b4..b93ba73b1 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -129,9 +129,11 @@ struct reqgen_ctrl_s { }; -static int proc_parameters (struct para_data_s *para, +static int proc_parameters (ctrl_t ctrl, + struct para_data_s *para, struct reqgen_ctrl_s *outctrl); -static int create_request (struct para_data_s *para, +static int create_request (ctrl_t ctrl, + struct para_data_s *para, ksba_const_sexp_t public, struct reqgen_ctrl_s *outctrl); @@ -228,7 +230,7 @@ get_parameter_uint (struct para_data_s *para, enum para_name key) /* Read the certificate generation parameters from FP and generate (all) certificate requests. */ static int -read_parameters (FILE *fp, ksba_writer_t writer) +read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer) { static struct { const char *name; @@ -285,7 +287,7 @@ read_parameters (FILE *fp, ksba_writer_t writer) outctrl.dryrun = 1; else if (!ascii_strcasecmp( keyword, "%commit")) { - rc = proc_parameters (para, &outctrl); + rc = proc_parameters (ctrl, para, &outctrl); if (rc) goto leave; any = 1; @@ -332,7 +334,7 @@ read_parameters (FILE *fp, ksba_writer_t writer) if (keywords[i].key == pKEYTYPE && para) { - rc = proc_parameters (para, &outctrl); + rc = proc_parameters (ctrl, para, &outctrl); if (rc) goto leave; any = 1; @@ -375,7 +377,7 @@ read_parameters (FILE *fp, ksba_writer_t writer) } else if (para) { - rc = proc_parameters (para, &outctrl); + rc = proc_parameters (ctrl, para, &outctrl); if (rc) goto leave; any = 1; @@ -414,7 +416,8 @@ has_invalid_email_chars (const char *s) /* Check that all required parameters are given and perform the action */ static int -proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) +proc_parameters (ctrl_t ctrl, + struct para_data_s *para, struct reqgen_ctrl_s *outctrl) { struct para_data_s *r; const char *s; @@ -484,7 +487,7 @@ proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) sprintf (numbuf, "%u", nbits); snprintf (keyparms, DIM (keyparms)-1, "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf); - rc = gpgsm_agent_genkey (keyparms, &public); + rc = gpgsm_agent_genkey (ctrl, keyparms, &public); if (rc) { r = get_parameter (para, pKEYTYPE); @@ -493,7 +496,7 @@ proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) return rc; } - rc = create_request (para, public, outctrl); + rc = create_request (ctrl, para, public, outctrl); xfree (public); return rc; @@ -503,7 +506,8 @@ proc_parameters (struct para_data_s *para, struct reqgen_ctrl_s *outctrl) /* Parameters are checked, the key pair has been created. Now generate the request and write it out */ static int -create_request (struct para_data_s *para, ksba_const_sexp_t public, +create_request (ctrl_t ctrl, + struct para_data_s *para, ksba_const_sexp_t public, struct reqgen_ctrl_s *outctrl) { ksba_certreq_t cr; @@ -614,7 +618,7 @@ create_request (struct para_data_s *para, ksba_const_sexp_t public, for (n=0; n < 20; n++) sprintf (hexgrip+n*2, "%02X", grip[n]); - rc = gpgsm_agent_pksign (hexgrip, NULL, + rc = gpgsm_agent_pksign (ctrl, hexgrip, NULL, gcry_md_read(md, GCRY_MD_SHA1), gcry_md_get_algo_dlen (GCRY_MD_SHA1), GCRY_MD_SHA1, @@ -650,7 +654,7 @@ create_request (struct para_data_s *para, ksba_const_sexp_t public, /* Create a new key by reading the parameters from in_fd. Multiple keys may be created */ int -gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp) +gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp) { int rc; FILE *in_fp; @@ -673,7 +677,7 @@ gpgsm_genkey (CTRL ctrl, int in_fd, FILE *out_fp) goto leave; } - rc = read_parameters (in_fp, writer); + rc = read_parameters (ctrl, in_fp, writer); if (rc) { log_error ("error creating certificate request: %s\n", diff --git a/sm/decrypt.c b/sm/decrypt.c index df0edc2ae..9a21cfb46 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -54,7 +54,7 @@ struct decrypt_filter_parm_s { /* Decrypt the session key and fill in the parm structure. The algo and the IV is expected to be already in PARM. */ static int -prepare_decryption (const char *hexkeygrip, const char *desc, +prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc, ksba_const_sexp_t enc_val, struct decrypt_filter_parm_s *parm) { @@ -62,7 +62,7 @@ prepare_decryption (const char *hexkeygrip, const char *desc, size_t n, seskeylen; int rc; - rc = gpgsm_agent_pkdecrypt (hexkeygrip, desc, enc_val, + rc = gpgsm_agent_pkdecrypt (ctrl, hexkeygrip, desc, enc_val, &seskey, &seskeylen); if (rc) { @@ -238,7 +238,7 @@ decrypt_filter (void *arg, /* Perform a decrypt operation. */ int -gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) +gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp) { int rc; Base64Context b64reader = NULL; @@ -424,7 +424,8 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp) recp); else { - rc = prepare_decryption (hexkeygrip, desc, enc_val, &dfparm); + rc = prepare_decryption (ctrl, + hexkeygrip, desc, enc_val, &dfparm); xfree (enc_val); if (rc) { diff --git a/sm/export.c b/sm/export.c index 8a89110de..2b675bdd7 100644 --- a/sm/export.c +++ b/sm/export.c @@ -392,7 +392,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp) } keygrip = gpgsm_get_keygrip_hexstring (cert); - if (!keygrip || gpgsm_agent_havekey (keygrip)) + if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip)) { /* Note, that the !keygrip case indicates a bad certificate. */ rc = gpg_error (GPG_ERR_NO_SECKEY); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 322f893a4..eff167367 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1496,7 +1496,7 @@ main ( int argc, char **argv) wrong_args ("--learn-card"); else { - int rc = gpgsm_agent_learn (); + int rc = gpgsm_agent_learn (&ctrl); if (rc) log_error ("error learning card: %s\n", gpg_strerror (rc)); } @@ -1519,7 +1519,7 @@ main ( int argc, char **argv) else { char *desc = gpgsm_format_keydesc (cert); - rc = gpgsm_agent_passwd (grip, desc); + rc = gpgsm_agent_passwd (&ctrl, grip, desc); xfree (desc); } if (rc) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index a06bfa482..c1a3c9964 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -214,7 +214,8 @@ int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert); int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, gcry_md_hd_t md, int hash_algo); /* fixme: move create functions to another file */ -int gpgsm_create_cms_signature (ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, +int gpgsm_create_cms_signature (ctrl_t ctrl, + ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, char **r_sigval); @@ -260,7 +261,7 @@ int gpgsm_delete (ctrl_t ctrl, STRLIST names); int gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp); /*-- sign.c --*/ -int gpgsm_get_default_cert (ksba_cert_t *r_cert); +int gpgsm_get_default_cert (ctrl_t ctrl, ksba_cert_t *r_cert); int gpgsm_sign (ctrl_t ctrl, CERTLIST signerlist, int data_fd, int detached, FILE *out_fp); @@ -274,20 +275,21 @@ int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp); int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- call-agent.c --*/ -int gpgsm_agent_pksign (const char *keygrip, const char *desc, +int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc, unsigned char *digest, size_t digestlen, int digestalgo, char **r_buf, size_t *r_buflen); -int gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc, +int gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen); -int gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); -int gpgsm_agent_istrusted (ksba_cert_t cert); -int gpgsm_agent_havekey (const char *hexkeygrip); -int gpgsm_agent_marktrusted (ksba_cert_t cert); -int gpgsm_agent_learn (void); -int gpgsm_agent_passwd (const char *hexkeygrip, const char *desc); +int gpgsm_agent_genkey (ctrl_t ctrl, + ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); +int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert); +int gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip); +int gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert); +int gpgsm_agent_learn (ctrl_t ctrl); +int gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (ctrl_t ctrl, diff --git a/sm/keylist.c b/sm/keylist.c index 2a365bc3a..07cddb3dc 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -977,7 +977,7 @@ list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, int raw_mode, output mode will be used intead of the standard beautified one. */ static gpg_error_t -list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, +list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp, unsigned int mode, int raw_mode) { KEYDB_HANDLE hd; @@ -1082,7 +1082,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, char *p = gpgsm_get_keygrip_hexstring (cert); if (p) { - rc = gpgsm_agent_havekey (p); + rc = gpgsm_agent_havekey (ctrl, p); if (!rc) have_secret = 1; else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY) diff --git a/sm/sign.c b/sm/sign.c index 473cf93a2..9d34ab221 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -126,7 +126,7 @@ hash_and_copy_data (int fd, gcry_md_hd_t md, ksba_writer_t writer) /* Get the default certificate which is defined as the first one our keyDB returns and has a secret key available. */ int -gpgsm_get_default_cert (ksba_cert_t *r_cert) +gpgsm_get_default_cert (ctrl_t ctrl, ksba_cert_t *r_cert) { KEYDB_HANDLE hd; ksba_cert_t cert = NULL; @@ -156,7 +156,7 @@ gpgsm_get_default_cert (ksba_cert_t *r_cert) p = gpgsm_get_keygrip_hexstring (cert); if (p) { - if (!gpgsm_agent_havekey (p)) + if (!gpgsm_agent_havekey (ctrl, p)) { xfree (p); keydb_release (hd); @@ -180,7 +180,7 @@ gpgsm_get_default_cert (ksba_cert_t *r_cert) static ksba_cert_t -get_default_signer (void) +get_default_signer (ctrl_t ctrl) { KEYDB_SEARCH_DESC desc; ksba_cert_t cert = NULL; @@ -189,7 +189,7 @@ get_default_signer (void) if (!opt.local_user) { - rc = gpgsm_get_default_cert (&cert); + rc = gpgsm_get_default_cert (ctrl, &cert); if (rc) { if (rc != -1) @@ -365,7 +365,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, /* If no list of signers is given, use a default one. */ if (!signerlist) { - ksba_cert_t cert = get_default_signer (); + ksba_cert_t cert = get_default_signer (ctrl); if (!cert) { log_error ("no default signer found\n"); @@ -589,7 +589,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, goto leave; } - rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval); + rc = gpgsm_create_cms_signature (ctrl, cl->cert, + md, algo, &sigval); if (rc) { gcry_md_close (md); -- cgit v1.2.3 From 5fa53f752458107ecfc49c4a58fb87123193fdfa Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 26 Apr 2004 13:46:36 +0000 Subject: * scdaemon.c (main): Do the last change the usual way. This is so that we can easily test for versioned config files above. * gpgsm.c (main) <gpgconf>: Do not use /dev/null as default config filename. --- scd/ChangeLog | 5 +++++ scd/scdaemon.c | 8 +++----- sm/ChangeLog | 3 +++ sm/gpgsm.c | 6 ++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index eb2074bba..3aea9f08d 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-04-26 Werner Koch <wk@gnupg.org> + + * scdaemon.c (main): Do the last change the usual way. This is so + that we can easily test for versioned config files above. + 2004-04-26 Marcus Brinkmann <marcus@g10code.de> * scdaemon.c (main): For now, always print default filename for diff --git a/scd/scdaemon.c b/scd/scdaemon.c index d0306aeb6..5e9737ae4 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -539,8 +539,6 @@ main (int argc, char **argv ) if (gpgconf_list) { - char *filename; - /* List options and default values in the GPG Conf format. */ /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ @@ -559,11 +557,11 @@ main (int argc, char **argv ) /* The NO_ARG_DESC flag for an option indicates that the argument has a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + if (!config_filename) + config_filename = make_filename (opt.homedir, "scdaemon.conf", NULL ); - filename = make_filename (opt.homedir, "scdaemon.conf", NULL); printf ("gpgconf-scdaemon.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, filename); - xfree (filename); + GC_OPT_FLAG_DEFAULT, config_filename); printf ("verbose:%lu:\n" "quiet:%lu:\n" diff --git a/sm/ChangeLog b/sm/ChangeLog index 6c3ff32fb..aaf5d9047 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,8 @@ 2004-04-26 Werner Koch <wk@gnupg.org> + * gpgsm.c (main) <gpgconf>: Do not use /dev/null as default config + filename. + * call-agent.c (gpgsm_agent_pksign, gpgsm_agent_pkdecrypt) (gpgsm_agent_genkey, gpgsm_agent_istrusted) (gpgsm_agent_marktrusted, gpgsm_agent_havekey) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index eff167367..33d8a2c48 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1294,9 +1294,11 @@ main ( int argc, char **argv) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + if (!config_filename) + config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL); + printf ("gpgconf-gpgsm.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, - config_filename?config_filename:"/dev/null"); + GC_OPT_FLAG_DEFAULT, config_filename); printf ("verbose:%lu:\n" "quiet:%lu:\n" -- cgit v1.2.3 From d74d2f5bc90dfeefae65bed9e4bad5a6dd3d9e44 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 26 Apr 2004 18:26:41 +0000 Subject: (start_scd): Do not register an event signal if we are running as a pipe server. --- agent/ChangeLog | 5 +++++ agent/call-scd.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index f63ae88a1..10674ad18 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-04-26 Werner Koch <wk@gnupg.org> + + * call-scd.c (start_scd): Do not register an event signal if we + are running as a pipe server. + 2004-04-21 Werner Koch <wk@gnupg.org> * call-scd.c (start_scd): Send event-signal option. Always check diff --git a/agent/call-scd.c b/agent/call-scd.c index 3c2bf9e2a..2427d8ca3 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -270,7 +270,10 @@ start_scd (ctrl_t ctrl) if (DBG_ASSUAN) log_debug ("connection to SCdaemon established\n"); - /* Tell the scdaemon that we want him to send us an event signal. */ + /* Tell the scdaemon that we want him to send us an event signal. + But only do this if we are running as a regular sever and not + simply as a pipe server. */ + if (ctrl->connection_fd != -1) { char buf[100]; -- cgit v1.2.3 From 6efe46d4ffcfe3360310bee2ad471b81c940cc97 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 26 Apr 2004 18:26:54 +0000 Subject: (change_name): Check that the NAME is not too long. (change_url): Likewise. (change_login): Likewise. --- g10/ChangeLog | 6 ++++++ g10/card-util.c | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/g10/ChangeLog b/g10/ChangeLog index 6cb971db5..dffa68a95 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,9 @@ +2004-04-26 Werner Koch <wk@gnupg.org> + + * card-util.c (change_name): Check that the NAME is not too long. + (change_url): Likewise. + (change_login): Likewise. + 2004-03-23 Werner Koch <wk@gnupg.org> * g10.c: New options --gpgconf-list, --debug-level and --log-file diff --git a/g10/card-util.c b/g10/card-util.c index c40cfd84d..c56ab24aa 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -445,6 +445,14 @@ change_name (void) 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) @@ -467,6 +475,14 @@ change_url (void) 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)); @@ -487,6 +503,14 @@ change_login (void) 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)); -- cgit v1.2.3 From 869a2bbad2f76153d953aeaaec5e3f0dd31d82f6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 26 Apr 2004 18:28:06 +0000 Subject: * app-common.h: New members FNC.DEINIT and APP_LOCAL. * app.c (release_application): Call new deconstructor. * app-openpgp.c (do_deinit): New. (get_cached_data, flush_cache_item, flush_cache_after_error) (flush_cache): New. (get_one_do): Replaced arg SLOT by APP. Make used of cached data. (verify_chv2, verify_chv3): Flush some cache item after error. (do_change_pin): Ditto. (do_sign): Ditto. (do_setattr): Flush cache item. (do_genkey): Flush the entire cache. (compare_fingerprint): Use cached data. --- scd/ChangeLog | 13 +++ scd/app-common.h | 5 +- scd/app-openpgp.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++------- scd/app.c | 6 ++ 4 files changed, 235 insertions(+), 33 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 3aea9f08d..1db7a8a62 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,18 @@ 2004-04-26 Werner Koch <wk@gnupg.org> + * app-common.h: New members FNC.DEINIT and APP_LOCAL. + * app.c (release_application): Call new deconstructor. + * app-openpgp.c (do_deinit): New. + (get_cached_data, flush_cache_item, flush_cache_after_error) + (flush_cache): New. + (get_one_do): Replaced arg SLOT by APP. Make used of cached data. + (verify_chv2, verify_chv3): Flush some cache item after error. + (do_change_pin): Ditto. + (do_sign): Ditto. + (do_setattr): Flush cache item. + (do_genkey): Flush the entire cache. + (compare_fingerprint): Use cached data. + * scdaemon.c (main): Do the last change the usual way. This is so that we can easily test for versioned config files above. diff --git a/scd/app-common.h b/scd/app-common.h index c16a15719..6e62bf99d 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -23,6 +23,8 @@ #include <ksba.h> +struct app_local_s; /* Defined by all app-*.c. */ + struct app_ctx_s { int initialized; /* The application has been initialied and the function pointers may be used. Note that for @@ -37,7 +39,9 @@ struct app_ctx_s { int force_chv1; /* True if the card does not cache CHV1. */ int did_chv2; int did_chv3; + struct app_local_s *app_local; /* Local to the application. */ struct { + void (*deinit) (app_t app); int (*learn_status) (app_t app, ctrl_t ctrl); int (*readcert) (app_t app, const char *certid, unsigned char **cert, size_t *certlen); @@ -75,7 +79,6 @@ struct app_ctx_s { void *pincb_arg); } fnc; - }; #if GNUPG_MAJOR_VERSION == 1 diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index af5f5a27f..7ecbc6a48 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -50,35 +50,199 @@ static struct { int constructed; int get_from; /* Constructed DO with this DO or 0 for direct access. */ int binary; + int dont_cache; + int flush_on_error; char *desc; } data_objects[] = { - { 0x005E, 0, 0, 1, "Login Data" }, - { 0x5F50, 0, 0, 0, "URL" }, - { 0x0065, 1, 0, 1, "Cardholder Related Data"}, - { 0x005B, 0, 0x65, 0, "Name" }, - { 0x5F2D, 0, 0x65, 0, "Language preferences" }, - { 0x5F35, 0, 0x65, 0, "Sex" }, - { 0x006E, 1, 0, 1, "Application Related Data" }, - { 0x004F, 0, 0x6E, 1, "AID" }, - { 0x0073, 1, 0, 1, "Discretionary Data Objects" }, - { 0x0047, 0, 0x6E, 1, "Card Capabilities" }, - { 0x00C0, 0, 0x6E, 1, "Extended Card Capabilities" }, - { 0x00C1, 0, 0x6E, 1, "Algorithm Attributes Signature" }, - { 0x00C2, 0, 0x6E, 1, "Algorithm Attributes Decryption" }, - { 0x00C3, 0, 0x6E, 1, "Algorithm Attributes Authentication" }, - { 0x00C4, 0, 0x6E, 1, "CHV Status Bytes" }, - { 0x00C5, 0, 0x6E, 1, "Fingerprints" }, - { 0x00C6, 0, 0x6E, 1, "CA Fingerprints" }, - { 0x007A, 1, 0, 1, "Security Support Template" }, - { 0x0093, 0, 0x7A, 1, "Digital Signature Counter" }, + { 0x005E, 0, 0, 1, 0, 0, "Login Data" }, + { 0x5F50, 0, 0, 0, 0, 0, "URL" }, + { 0x0065, 1, 0, 1, 0, 0, "Cardholder Related Data"}, + { 0x005B, 0, 0x65, 0, 0, 0, "Name" }, + { 0x5F2D, 0, 0x65, 0, 0, 0, "Language preferences" }, + { 0x5F35, 0, 0x65, 0, 0, 0, "Sex" }, + { 0x006E, 1, 0, 1, 0, 0, "Application Related Data" }, + { 0x004F, 0, 0x6E, 1, 0, 0, "AID" }, + { 0x0073, 1, 0, 1, 0, 0, "Discretionary Data Objects" }, + { 0x0047, 0, 0x6E, 1, 0, 0, "Card Capabilities" }, + { 0x00C0, 0, 0x6E, 1, 0, 0, "Extended Card Capabilities" }, + { 0x00C1, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Signature" }, + { 0x00C2, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Decryption" }, + { 0x00C3, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Authentication" }, + { 0x00C4, 0, 0x6E, 1, 0, 1, "CHV Status Bytes" }, + { 0x00C5, 0, 0x6E, 1, 0, 0, "Fingerprints" }, + { 0x00C6, 0, 0x6E, 1, 0, 0, "CA Fingerprints" }, + { 0x007A, 1, 0, 1, 0, 0, "Security Support Template" }, + { 0x0093, 0, 0x7A, 1, 1, 0, "Digital Signature Counter" }, { 0 } }; +struct cache_s { + struct cache_s *next; + int tag; + size_t length; + unsigned char data[1]; +}; + +struct app_local_s { + struct cache_s *cache; +}; + + static unsigned long convert_sig_counter_value (const unsigned char *value, size_t valuelen); static unsigned long get_sig_counter (APP app); +/* Deconstructor. */ +static void +do_deinit (app_t app) +{ + if (app && app->app_local) + { + struct cache_s *c, *c2; + + for (c = app->app_local->cache; c; c = c2) + { + c2 = c->next; + xfree (c); + } + xfree (app->app_local); + app->app_local = NULL; + } +} + + +/* Wrapper around iso7816_get_data which first tries to get the data + from the cache. */ +static gpg_error_t +get_cached_data (app_t app, int tag, + unsigned char **result, size_t *resultlen) +{ + gpg_error_t err; + int i; + unsigned char *p; + size_t len; + struct cache_s *c; + + + *result = NULL; + *resultlen = 0; + + if (app->app_local) + { + for (c=app->app_local->cache; c; c = c->next) + if (c->tag == tag) + { + p = xtrymalloc (c->length); + if (!p) + return gpg_error (gpg_err_code_from_errno (errno)); + memcpy (p, c->data, c->length); + *resultlen = c->length; + *result = p; + return 0; + } + } + + err = iso7816_get_data (app->slot, tag, &p, &len); + if (err) + return err; + *result = p; + *resultlen = len; + + /* Check whether we should cache this object. */ + for (i=0; data_objects[i].tag; i++) + if (data_objects[i].tag == tag) + { + if (data_objects[i].dont_cache) + return 0; + break; + } + + /* No, cache it. */ + if (!app->app_local) + app->app_local = xtrycalloc (1, sizeof *app->app_local); + + /* Note that we can safely ignore out of core errors. */ + if (app->app_local) + { + for (c=app->app_local->cache; c; c = c->next) + assert (c->tag != tag); + + c = xtrymalloc (sizeof *c + len); + if (c) + { + memcpy (c->data, p, len); + log_debug (" caching tag %04X\n", tag); + c->length = len; + c->tag = tag; + c->next = app->app_local->cache; + app->app_local->cache = c; + } + } + + return 0; +} + +/* Remove DO at TAG from the cache. */ +static void +flush_cache_item (app_t app, int tag) +{ + struct cache_s *c, *cprev; + int i; + + if (!app->app_local) + return; + + for (c=app->app_local->cache, cprev=NULL; c ; cprev=c, c = c->next) + if (c->tag == tag) + { + if (cprev) + cprev->next = c->next; + else + app->app_local->cache = c->next; + xfree (c); + + for (c=app->app_local->cache; c ; c = c->next) + assert (c->tag != tag); /* Oops: duplicated entry. */ + return; + } + + /* Try again if we have an outer tag. */ + for (i=0; data_objects[i].tag; i++) + if (data_objects[i].tag == tag && data_objects[i].get_from + && data_objects[i].get_from != tag) + flush_cache_item (app, data_objects[i].get_from); +} + +/* Flush all entries from the cache which might be out of sync after + an error. */ +static void +flush_cache_after_error (app_t app) +{ + int i; + + for (i=0; data_objects[i].tag; i++) + if (data_objects[i].flush_on_error) + flush_cache_item (app, data_objects[i].tag); +} + + +/* Flush the entire cache. */ +static void +flush_cache (app_t app) +{ + if (app && app->app_local) + { + struct cache_s *c, *c2; + + for (c = app->app_local->cache; c; c = c2) + { + c2 = c->next; + xfree (c); + } + app->app_local->cache = NULL; + } +} /* Get the DO identified by TAG from the card in SLOT and return a @@ -86,7 +250,7 @@ static unsigned long get_sig_counter (APP app); NULL if not found or a pointer which must be used to release the buffer holding value. */ static void * -get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes) +get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) { int rc, i; unsigned char *buffer; @@ -103,8 +267,8 @@ get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes) rc = -1; if (data_objects[i].tag && data_objects[i].get_from) { - rc = iso7816_get_data (slot, data_objects[i].get_from, - &buffer, &buflen); + rc = get_cached_data (app, data_objects[i].get_from, + &buffer, &buflen); if (!rc) { const unsigned char *s; @@ -125,7 +289,7 @@ get_one_do (int slot, int tag, unsigned char **result, size_t *nbytes) if (!value) /* Not in a constructed DO, try simple. */ { - rc = iso7816_get_data (slot, tag, &buffer, &buflen); + rc = get_cached_data (app, tag, &buffer, &buflen); if (!rc) { value = buffer; @@ -374,7 +538,7 @@ do_getattr (APP app, CTRL ctrl, const char *name) return 0; } - relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen); + relptr = get_one_do (app, table[idx].tag, &value, &valuelen); if (relptr) { if (table[idx].special == 1) @@ -429,7 +593,7 @@ do_learn_status (APP app, CTRL ctrl) /* Verify CHV2 if required. Depending on the configuration of the card CHV1 will also be verified. */ static int -verify_chv2 (APP app, +verify_chv2 (app_t app, int (*pincb)(void*, const char *, char **), void *pincb_arg) { @@ -458,6 +622,7 @@ verify_chv2 (APP app, { log_error ("verify CHV2 failed: %s\n", gpg_strerror (rc)); xfree (pinvalue); + flush_cache_after_error (app); return rc; } app->did_chv2 = 1; @@ -471,6 +636,7 @@ verify_chv2 (APP app, { log_error ("verify CHV1 failed: %s\n", gpg_strerror (rc)); xfree (pinvalue); + flush_cache_after_error (app); return rc; } app->did_chv1 = 1; @@ -517,6 +683,7 @@ verify_chv3 (APP app, if (rc) { log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); + flush_cache_after_error (app); return rc; } app->did_chv3 = 1; @@ -561,6 +728,10 @@ do_setattr (APP app, const char *name, if (rc) return rc; + /* Flush the cache before writing it, so that the next get operation + will reread the data from the card and thus get synced in case of + errors (e.g. data truncated by the card). */ + flush_cache_item (app, table[idx].tag); rc = iso7816_put_data (app->slot, table[idx].tag, value, valuelen); if (rc) log_error ("failed to set `%s': %s\n", table[idx].name, gpg_strerror (rc)); @@ -647,7 +818,8 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, pinvalue, strlen (pinvalue)); } xfree (pinvalue); - + if (rc) + flush_cache_after_error (app); leave: return rc; @@ -678,6 +850,10 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, return gpg_error (GPG_ERR_INV_ID); keyno--; + /* We flush the cache to increase the traffic before a key + generation. This _might_ help a card to gather more entropy. */ + flush_cache (app); + rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); if (rc) { @@ -711,6 +887,7 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, goto leave; xfree (buffer); buffer = NULL; + #if 1 log_info ("please wait while key is being generated ...\n"); start_at = time (NULL); @@ -801,7 +978,7 @@ get_sig_counter (APP app) size_t valuelen; unsigned long ul; - relptr = get_one_do (app->slot, 0x0093, &value, &valuelen); + relptr = get_one_do (app, 0x0093, &value, &valuelen); if (!relptr) return 0; ul = convert_sig_counter_value (value, valuelen); @@ -819,7 +996,7 @@ compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr) assert (keyno >= 1 && keyno <= 3); - rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); + rc = get_cached_data (app, 0x006E, &buffer, &buflen); if (rc) { log_error ("error reading application data\n"); @@ -979,6 +1156,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo, { log_error ("verify CHV1 failed\n"); xfree (pinvalue); + flush_cache_after_error (app); return rc; } app->did_chv1 = 1; @@ -992,6 +1170,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo, { log_error ("verify CHV2 failed\n"); xfree (pinvalue); + flush_cache_after_error (app); return rc; } app->did_chv2 = 1; @@ -1220,7 +1399,7 @@ app_select_openpgp (APP app) app->serialnolen = buflen; buffer = NULL; - relptr = get_one_do (app->slot, 0x00C4, &buffer, &buflen); + relptr = get_one_do (app, 0x00C4, &buffer, &buflen); if (!relptr) { log_error ("can't access CHV Status Bytes - invalid OpenPGP card?\n"); @@ -1232,6 +1411,7 @@ app_select_openpgp (APP app) if (opt.verbose > 1) dump_all_do (slot); + app->fnc.deinit = do_deinit; app->fnc.learn_status = do_learn_status; app->fnc.readcert = NULL; app->fnc.getattr = do_getattr; @@ -1285,7 +1465,7 @@ app_openpgp_cardinfo (APP app, if (disp_name) { *disp_name = NULL; - relptr = get_one_do (app->slot, 0x005B, &value, &valuelen); + relptr = get_one_do (app, 0x005B, &value, &valuelen); if (relptr) { *disp_name = make_printable_string (value, valuelen, 0); @@ -1296,7 +1476,7 @@ app_openpgp_cardinfo (APP app, if (pubkey_url) { *pubkey_url = NULL; - relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen); + relptr = get_one_do (app, 0x5F50, &value, &valuelen); if (relptr) { *pubkey_url = make_printable_string (value, valuelen, 0); @@ -1310,7 +1490,7 @@ app_openpgp_cardinfo (APP app, *fpr2 = NULL; if (fpr3) *fpr3 = NULL; - relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen); + relptr = get_one_do (app, 0x00C5, &value, &valuelen); if (relptr && valuelen >= 60) { if (fpr1) diff --git a/scd/app.c b/scd/app.c index d395fe559..a9a9243eb 100644 --- a/scd/app.c +++ b/scd/app.c @@ -116,6 +116,12 @@ release_application (app_t app) if (!app) return; + if (app->fnc.deinit) + { + app->fnc.deinit (app); + app->fnc.deinit = NULL; + } + xfree (app->serialno); xfree (app); } -- cgit v1.2.3 From 236d241aed4c21a89157add693cef23ad66405be Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Apr 2004 08:59:34 +0000 Subject: * gpgsm.c: New command --keydb-clear-some-cert-flags. * keydb.c (keydb_clear_some_cert_flags): New. (keydb_update_keyblock, keydb_set_flags): Change error code CONFLICT to NOT_LOCKED. --- doc/gpgsm.texi | 9 +++++ sm/ChangeLog | 7 ++++ sm/gpgsm.c | 11 +++++++ sm/keydb.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- sm/keydb.h | 2 ++ 5 files changed, 127 insertions(+), 3 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index a0da96d56..b5c87b77c 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -161,6 +161,15 @@ 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}. diff --git a/sm/ChangeLog b/sm/ChangeLog index aaf5d9047..105b84443 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-04-28 Werner Koch <wk@gnupg.org> + + * gpgsm.c: New command --keydb-clear-some-cert-flags. + * keydb.c (keydb_clear_some_cert_flags): New. + (keydb_update_keyblock, keydb_set_flags): Change error code + CONFLICT to NOT_LOCKED. + 2004-04-26 Werner Koch <wk@gnupg.org> * gpgsm.c (main) <gpgconf>: Do not use /dev/null as default config diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 33d8a2c48..61307701a 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -85,6 +85,7 @@ enum cmd_and_opt_values { aDumpKeys, aDumpSecretKeys, aDumpExternalKeys, + aKeydbClearSomeCertFlags, oOptions, oDebug, @@ -252,6 +253,7 @@ static ARGPARSE_OPTS opts[] = { { aDumpKeys, "dump-keys", 256, "@"}, { aDumpExternalKeys, "dump-external-keys", 256, "@"}, { aDumpSecretKeys, "dump-secret-keys", 256, "@"}, + { aKeydbClearSomeCertFlags, "keydb-clear-some-cert-flags", 256, "@"}, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -894,6 +896,7 @@ main ( int argc, char **argv) case aListSigs: case aLearnCard: case aPasswd: + case aKeydbClearSomeCertFlags: do_not_setup_keys = 1; set_cmd (&cmd, pargs.r_opt); break; @@ -1531,6 +1534,14 @@ main ( int argc, char **argv) } break; + case aKeydbClearSomeCertFlags: + for (sl=NULL; argc; argc--, argv++) + add_to_strlist (&sl, *argv); + keydb_clear_some_cert_flags (&ctrl, sl); + free_strlist(sl); + break; + + default: log_error ("invalid command (there is no implicit command)\n"); break; diff --git a/sm/keydb.c b/sm/keydb.c index 322307553..8832643b9 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -526,7 +526,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) return 0; if (!hd->locked) - return gpg_error (GPG_ERR_CONFLICT); + return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: @@ -660,7 +660,7 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value) return gpg_error (GPG_ERR_NOTHING_FOUND); if (!hd->locked) - return gpg_error (GPG_ERR_CONFLICT); + return gpg_error (GPG_ERR_NOT_LOCKED); switch (hd->active[hd->found].type) { @@ -1374,7 +1374,7 @@ keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed) /* This is basically keydb_set_flags but it implements a complete - transaction by locating teh certificate in the DB and updating the + transaction by locating the certificate in the DB and updating the flags. */ gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value) @@ -1435,3 +1435,98 @@ keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value) return 0; } + +/* Reset all the certificate flags we have stored with the certificates + for performance reasons. */ +void +keydb_clear_some_cert_flags (ctrl_t ctrl, STRLIST names) +{ + gpg_error_t err; + KEYDB_HANDLE hd = NULL; + KEYDB_SEARCH_DESC *desc = NULL; + int ndesc; + STRLIST sl; + int rc=0; + unsigned int old_value, value; + + hd = keydb_new (0); + if (!hd) + { + log_error ("keydb_new failed\n"); + goto leave; + } + + if (!names) + ndesc = 1; + else + { + for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) + ; + } + + desc = xtrycalloc (ndesc, sizeof *desc); + if (!ndesc) + { + log_error ("allocating memory failed: %s\n", + gpg_strerror (OUT_OF_CORE (errno))); + goto leave; + } + + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + else + { + for (ndesc=0, sl=names; sl; sl = sl->next) + { + rc = keydb_classify_name (sl->d, desc+ndesc); + if (rc) + { + log_error ("key `%s' not found: %s\n", + sl->d, gpg_strerror (rc)); + rc = 0; + } + else + ndesc++; + } + } + + err = keydb_lock (hd); + if (err) + { + log_error (_("error locking keybox: %s\n"), gpg_strerror (err)); + goto leave; + } + + while (!(rc = keydb_search (hd, desc, ndesc))) + { + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + + err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value); + if (err) + { + log_error (_("error getting stored flags: %s\n"), + gpg_strerror (err)); + goto leave; + } + + value = (old_value & ~VALIDITY_REVOKED); + if (value != old_value) + { + err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value); + if (err) + { + log_error (_("error storing flags: %s\n"), gpg_strerror (err)); + goto leave; + } + } + } + if (rc && rc != -1) + log_error ("keydb_search failed: %s\n", gpg_strerror (rc)); + + leave: + xfree (desc); + keydb_release (hd); +} + + diff --git a/sm/keydb.h b/sm/keydb.h index 2e9ed1573..924ad77c4 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -75,6 +75,8 @@ int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed); gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int which, int idx, unsigned int value); +void keydb_clear_some_cert_flags (ctrl_t ctrl, STRLIST names); + #endif /*GNUPG_KEYDB_H*/ -- cgit v1.2.3 From 4c96cb0683c4ff4e4b8d5ae9c61d555437ad51bd Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Apr 2004 09:00:05 +0000 Subject: * app-common.h: Do not include ksba.h for gnupg 1. --- scd/ChangeLog | 4 ++++ scd/app-common.h | 2 ++ scd/app-openpgp.c | 1 - 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 1db7a8a62..2233f223d 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-04-27 Werner Koch <wk@gnupg.org> + + * app-common.h: Do not include ksba.h for gnupg 1. + 2004-04-26 Werner Koch <wk@gnupg.org> * app-common.h: New members FNC.DEINIT and APP_LOCAL. diff --git a/scd/app-common.h b/scd/app-common.h index 6e62bf99d..c61bcca60 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -21,7 +21,9 @@ #ifndef GNUPG_SCD_APP_COMMON_H #define GNUPG_SCD_APP_COMMON_H +#if GNUPG_MAJOR_VERSION != 1 #include <ksba.h> +#endif struct app_local_s; /* Defined by all app-*.c. */ diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 7ecbc6a48..07420c697 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -172,7 +172,6 @@ get_cached_data (app_t app, int tag, if (c) { memcpy (c->data, p, len); - log_debug (" caching tag %04X\n", tag); c->length = len; c->tag = tag; c->next = app->app_local->cache; -- cgit v1.2.3 From 99a4774e344676f58a9b94caaa468459b54c22b6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Apr 2004 09:04:03 +0000 Subject: Add --ocsp-signer for the dirmngr backend. --- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 6da70fdda..5fe13021b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-04-28 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c: Add --ocsp-signer for the dirmngr backend. + 2004-04-20 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_options_gpg_agent): Change type of diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 8a5c96033..338c43119 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -763,6 +763,9 @@ static gc_option_t gc_options_dirmngr[] = { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|use OCSP responder URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, + { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "|FPR|OCSP response signed by FPR", + GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, GC_OPTION_NULL -- cgit v1.2.3 From b6018a1b0e2cc0b014737429b498b4bf01e9633d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 17:25:38 +0000 Subject: * card-util.c (card_edit): Remove PIN verification. (generate_card_keys): New arg SERIALNO. Do PIN verification here after resetting forced_chv1. --- g10/ChangeLog | 6 ++++++ g10/call-agent.c | 2 +- g10/card-util.c | 58 +++++++++++++++++++++++++------------------------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index dffa68a95..86c6c7957 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,9 @@ +2004-04-28 Werner Koch <wk@gnupg.org> + + * card-util.c (card_edit): Remove PIN verification. + (generate_card_keys): New arg SERIALNO. Do PIN verification here + after resetting forced_chv1. + 2004-04-26 Werner Koch <wk@gnupg.org> * card-util.c (change_name): Check that the NAME is not too long. diff --git a/g10/call-agent.c b/g10/call-agent.c index e1eabc9f0..de157d491 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -870,7 +870,7 @@ agent_scd_change_pin (int chvno) } -/* Perform a CHECKPIN operation. SERIALNO should be the seriial +/* 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 diff --git a/g10/card-util.c b/g10/card-util.c index c56ab24aa..c93d028bd 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -614,7 +614,7 @@ toggle_forcesig (void) static void -generate_card_keys (void) +generate_card_keys (const char *serialno) { struct agent_card_info_s info; int rc; @@ -670,7 +670,15 @@ generate_card_keys (void) return; } } - generate_keypair (NULL, info.serialno); + + /* 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. */ @@ -700,26 +708,25 @@ card_edit (STRLIST commands) static struct { const char *name; enum cmdids id; - int requires_pin; const char *desc; } cmds[] = { - { N_("quit") , cmdQUIT , 0, N_("quit this menu") }, - { N_("q") , cmdQUIT , 0, NULL }, - { N_("help") , cmdHELP , 0, N_("show this help") }, - { "?" , cmdHELP , 0, NULL }, - { N_("list") , cmdLIST , 0, N_("list all available data") }, - { N_("l") , cmdLIST , 0, NULL }, - { N_("debug") , cmdDEBUG , 0, NULL }, - { N_("name") , cmdNAME , 1, N_("change card holder's name") }, - { N_("url") , cmdURL , 1, N_("change URL to retrieve key") }, - { N_("login") , cmdLOGIN , 1, N_("change the login name") }, - { N_("lang") , cmdLANG , 1, N_("change the language preferences") }, - { N_("sex") , cmdSEX , 1, N_("change card holder's sex") }, + { 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, 1, N_("toggle the signature force PIN flag") }, + cmdFORCESIG, N_("toggle the signature force PIN flag") }, { N_("generate"), - cmdGENERATE, 1, N_("generate new keys") }, - { N_("passwd"), cmdPASSWD, 0, N_("menu to change or unblock the PIN") }, + cmdGENERATE, N_("generate new keys") }, + { N_("passwd"), cmdPASSWD, N_("menu to change or unblock the PIN") }, { NULL, cmdINVCMD } }; @@ -745,7 +752,6 @@ card_edit (STRLIST commands) const char *arg_string = ""; char *p; int i; - int requires_pin; tty_printf("\n"); if (redisplay ) @@ -791,7 +797,6 @@ card_edit (STRLIST commands) while( *answer == '#' ); arg_number = 0; /* Yes, here is the init which egcc complains about */ - requires_pin = 0; if (!*answer) cmd = cmdLIST; /* Default to the list command */ else if (*answer == CONTROL_D) @@ -811,19 +816,8 @@ card_edit (STRLIST commands) break; cmd = cmds[i].id; - requires_pin = cmds[i].requires_pin; } - if (requires_pin && !did_checkpin) - { - int rc = agent_scd_checkpin (serialnobuf); - if (rc) - { - log_error ("error checking the PIN: %s\n", gpg_strerror (rc)); - continue; - } - did_checkpin = 1; - } switch (cmd) { @@ -862,7 +856,7 @@ card_edit (STRLIST commands) break; case cmdGENERATE: - generate_card_keys (); + generate_card_keys (serialnobuf); break; case cmdPASSWD: -- cgit v1.2.3 From 7d486a0969c6efa46f53e76b8746c8c041f527ad Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 17:25:57 +0000 Subject: * app-openpgp.c (do_setattr): Sync FORCE_CHV1. --- scd/ChangeLog | 4 ++++ scd/app-openpgp.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 2233f223d..14dd9c3ff 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-04-28 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (do_setattr): Sync FORCE_CHV1. + 2004-04-27 Werner Koch <wk@gnupg.org> * app-common.h: Do not include ksba.h for gnupg 1. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 07420c697..f40951941 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -704,13 +704,14 @@ do_setattr (APP app, const char *name, static struct { const char *name; int tag; + int special; } table[] = { { "DISP-NAME", 0x005B }, { "LOGIN-DATA", 0x005E }, { "DISP-LANG", 0x5F2D }, { "DISP-SEX", 0x5F35 }, { "PUBKEY-URL", 0x5F50 }, - { "CHV-STATUS-1", 0x00C4 }, + { "CHV-STATUS-1", 0x00C4, 1 }, { "CA-FPR-1", 0x00CA }, { "CA-FPR-2", 0x00CB }, { "CA-FPR-3", 0x00CC }, @@ -735,6 +736,9 @@ do_setattr (APP app, const char *name, if (rc) log_error ("failed to set `%s': %s\n", table[idx].name, gpg_strerror (rc)); + if (table[idx].special == 1) + app->force_chv1 = (valuelen && *value == 0); + return rc; } -- cgit v1.2.3 From 18b6a60cb82ac36bc67eff9a9131b0df2819955e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 17:26:14 +0000 Subject: typo fix --- sm/certreqgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sm/certreqgen.c b/sm/certreqgen.c index b93ba73b1..b1adf2974 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -432,7 +432,7 @@ proc_parameters (ctrl_t ctrl, assert (get_parameter (para, pKEYTYPE)); /* We can only use RSA for now. There is a with pkcs-10 on how to - use ElGamal becuase it is expected that a PK algorithm can always + use ElGamal because it is expected that a PK algorithm can always be used for signing. */ i = get_parameter_algo (para, pKEYTYPE); if (i < 1 || i != GCRY_PK_RSA ) -- cgit v1.2.3 From 77c4506425b6694a0f21673debbf0896ac1dbf25 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 17:32:02 +0000 Subject: About to release 1.9.8 --- ChangeLog | 4 ++++ NEWS | 5 ++++- configure.ac | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 23f099ba3..ef33021cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,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 diff --git a/NEWS b/NEWS index 4e246f6d6..865f69f8b 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.8 +Noteworthy changes in version 1.9.8 (2004-04-29) ------------------------------------------------ * [scdaemon] Overhauled the internal CCID driver. @@ -12,6 +12,9 @@ Noteworthy changes in version 1.9.8 * 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) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 1a3a450c7..0c7bd927a 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.8-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.8, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -34,7 +34,7 @@ NEED_GPG_ERROR_VERSION=0.7 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.1.94 -NEED_LIBASSUAN_VERSION=0.6.4 +NEED_LIBASSUAN_VERSION=0.6.5 NEED_KSBA_VERSION=0.9.4 -- cgit v1.2.3 From fd1a0869d6ffa96fd96d41ce0244efebff6944a0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 17:35:47 +0000 Subject: Added --- scripts/compile | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100755 scripts/compile diff --git a/scripts/compile b/scripts/compile new file mode 100755 index 000000000..ac07cc541 --- /dev/null +++ b/scripts/compile @@ -0,0 +1,107 @@ +#! /bin/sh + +# Wrapper for compilers which do not understand `-c -o'. + +# Copyright 1999, 2000 Free Software Foundation, Inc. +# Written by Tom Tromey <tromey@cygnus.com>. +# +# 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, 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Usage: +# compile PROGRAM [ARGS]... +# `-o FOO.o' is removed from the args passed to the actual compile. + +# Usage statement added by Billy Biggs <vektor@dumbterm.net>. +if [ -z $1 ]; then + echo "Wrapper for compilers which do not understand '-c -o'." + echo "usage: compile PROGRAM [ARGS]..." + echo "'-o FOO.o' is removed from the args passed to the actual compile." + exit 1 +fi + +prog=$1 +shift + +ofile= +cfile= +args= +while test $# -gt 0; do + case "$1" in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we do something ugly here. + ofile=$2 + shift + case "$ofile" in + *.o | *.obj) + ;; + *) + args="$args -o $ofile" + ofile= + ;; + esac + ;; + *.c) + cfile=$1 + args="$args $1" + ;; + *) + args="$args $1" + ;; + esac + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$prog" $args +fi + +# Name of file we expect compiler to create. +cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d +while true; do + if mkdir $lockdir > /dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir $lockdir; exit 1" 1 2 15 + +# Run the compile. +"$prog" $args +status=$? + +if test -f "$cofile"; then + mv "$cofile" "$ofile" +fi + +rmdir $lockdir +exit $status -- cgit v1.2.3 From 64a6b54aa78debc25880cae6a9b66d82eba23bab Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 17:38:20 +0000 Subject: autoupdated --- po/de.po | 282 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 141 insertions(+), 141 deletions(-) diff --git a/po/de.po b/po/de.po index dafe41232..2cf41ddb0 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.7\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-04-06 12:06+0200\n" +"POT-Creation-Date: 2004-04-29 19:50+0200\n" "PO-Revision-Date: 2004-04-06 11:47+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:94 agent/protect-tool.c:92 scd/scdaemon.c:89 +#: agent/gpg-agent.c:94 agent/protect-tool.c:92 scd/scdaemon.c:92 msgid "" "@Options:\n" " " @@ -26,28 +26,28 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:96 scd/scdaemon.c:91 +#: agent/gpg-agent.c:96 scd/scdaemon.c:94 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:97 scd/scdaemon.c:92 +#: agent/gpg-agent.c:97 scd/scdaemon.c:95 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:98 kbx/kbxutil.c:73 scd/scdaemon.c:93 sm/gpgsm.c:301 +#: agent/gpg-agent.c:98 kbx/kbxutil.c:73 scd/scdaemon.c:96 sm/gpgsm.c:312 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:99 kbx/kbxutil.c:74 scd/scdaemon.c:94 sm/gpgsm.c:302 +#: agent/gpg-agent.c:99 kbx/kbxutil.c:74 scd/scdaemon.c:97 sm/gpgsm.c:313 msgid "be somewhat more quiet" msgstr "etwas weniger Aussageb erzeugen" -#: agent/gpg-agent.c:100 scd/scdaemon.c:95 +#: agent/gpg-agent.c:100 scd/scdaemon.c:98 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:101 scd/scdaemon.c:96 +#: agent/gpg-agent.c:101 scd/scdaemon.c:99 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" @@ -55,7 +55,7 @@ msgstr "Ausgabe f msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:107 scd/scdaemon.c:103 +#: agent/gpg-agent.c:107 scd/scdaemon.c:106 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" @@ -63,7 +63,7 @@ msgstr "Im Vordergrund laufen lassen" msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:109 scd/scdaemon.c:104 sm/gpgsm.c:304 +#: agent/gpg-agent.c:109 scd/scdaemon.c:107 sm/gpgsm.c:315 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" @@ -79,13 +79,13 @@ msgstr "Ignoriere Anfragen, das TTY zu wechseln" msgid "ignore requests to change the X display" msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:150 -#: sm/gpgsm.c:468 tools/gpgconf.c:85 +#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:165 +#: sm/gpgsm.c:479 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:150 -#: sm/gpgsm.c:468 tools/gpgconf.c:85 +#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:165 +#: sm/gpgsm.c:479 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -101,46 +101,46 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:256 scd/scdaemon.c:224 sm/gpgsm.c:591 +#: agent/gpg-agent.c:256 scd/scdaemon.c:239 sm/gpgsm.c:602 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:414 agent/protect-tool.c:1035 kbx/kbxutil.c:230 -#: scd/scdaemon.c:325 sm/gpgsm.c:714 +#: scd/scdaemon.c:352 sm/gpgsm.c:725 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:487 scd/scdaemon.c:405 sm/gpgsm.c:812 +#: agent/gpg-agent.c:487 scd/scdaemon.c:432 sm/gpgsm.c:823 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:492 agent/gpg-agent.c:947 scd/scdaemon.c:410 -#: sm/gpgsm.c:816 +#: agent/gpg-agent.c:492 agent/gpg-agent.c:955 scd/scdaemon.c:437 +#: sm/gpgsm.c:827 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:500 scd/scdaemon.c:418 sm/gpgsm.c:823 +#: agent/gpg-agent.c:500 scd/scdaemon.c:445 sm/gpgsm.c:834 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:641 scd/scdaemon.c:576 +#: agent/gpg-agent.c:641 scd/scdaemon.c:619 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" -#: agent/gpg-agent.c:980 agent/gpg-agent.c:1014 +#: agent/gpg-agent.c:988 agent/gpg-agent.c:1022 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: agent/gpg-agent.c:983 agent/gpg-agent.c:1019 +#: agent/gpg-agent.c:991 agent/gpg-agent.c:1027 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" @@ -257,11 +257,11 @@ msgstr "WARNUNG: Unsichere Zugriffsrechte f msgid "gpg-agent is not available in this session\n" msgstr "Der gpg-agent ist nicht verfgbar\n" -#: common/simple-pwquery.c:286 sm/call-agent.c:126 +#: common/simple-pwquery.c:286 sm/call-agent.c:128 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: common/simple-pwquery.c:298 sm/call-agent.c:138 +#: common/simple-pwquery.c:298 sm/call-agent.c:140 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" @@ -279,20 +279,20 @@ msgstr "Kommunikationsproblem mit gpg-agent\n" msgid "problem setting the gpg-agent options\n" msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: common/simple-pwquery.c:471 +#: common/simple-pwquery.c:473 msgid "canceled by user\n" msgstr "Vom Benutzer abgebrochen\n" -#: common/simple-pwquery.c:478 +#: common/simple-pwquery.c:480 msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:516 +#: jnlib/logging.c:547 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:62 sm/gpgsm.c:218 tools/gpgconf.c:53 +#: kbx/kbxutil.c:62 sm/gpgsm.c:223 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -300,7 +300,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:68 sm/gpgsm.c:248 tools/gpgconf.c:59 +#: kbx/kbxutil.c:68 sm/gpgsm.c:258 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -310,15 +310,15 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:70 sm/gpgsm.c:250 +#: kbx/kbxutil.c:70 sm/gpgsm.c:260 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: kbx/kbxutil.c:72 sm/gpgsm.c:300 tools/gpgconf.c:61 +#: kbx/kbxutil.c:72 sm/gpgsm.c:311 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: kbx/kbxutil.c:75 sm/gpgsm.c:309 tools/gpgconf.c:64 +#: kbx/kbxutil.c:75 sm/gpgsm.c:320 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" @@ -350,43 +350,43 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:97 sm/gpgsm.c:321 +#: scd/scdaemon.c:100 sm/gpgsm.c:332 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" -#: scd/scdaemon.c:102 +#: scd/scdaemon.c:105 msgid "|N|set OpenSC debug level to N" msgstr "|N|Den OpenSC Debugstufe auf N setzen" -#: scd/scdaemon.c:105 +#: scd/scdaemon.c:108 msgid "|N|connect to reader at port N" msgstr "|N|Verbinde mit dem Leser auf Port N" -#: scd/scdaemon.c:106 +#: scd/scdaemon.c:109 msgid "|NAME|use NAME as ct-API driver" msgstr "|NAME|Benutze NAME als CT-API Treiber" -#: scd/scdaemon.c:107 +#: scd/scdaemon.c:110 msgid "|NAME|use NAME as PC/SC driver" msgstr "|NAME|Benutze NAME als PC/SC Treiber" -#: scd/scdaemon.c:110 +#: scd/scdaemon.c:113 msgid "do not use the internal CCID driver" msgstr "Den internen CCID Treiber nicht benutzen" -#: scd/scdaemon.c:117 +#: scd/scdaemon.c:120 msgid "do not use the OpenSC layer" msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" -#: scd/scdaemon.c:122 +#: scd/scdaemon.c:125 msgid "allow the use of admin card commands" msgstr "Erlaube die Benuztung von \"Admin\" Kommandos" -#: scd/scdaemon.c:153 +#: scd/scdaemon.c:168 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" -#: scd/scdaemon.c:155 +#: scd/scdaemon.c:170 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" @@ -403,24 +403,24 @@ msgstr "Ung msgid "no running gpg-agent - starting one\n" msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" -#: sm/call-agent.c:149 +#: sm/call-agent.c:151 msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" -#: sm/call-dirmngr.c:162 +#: sm/call-dirmngr.c:164 msgid "no running dirmngr - starting one\n" msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" -#: sm/call-dirmngr.c:200 +#: sm/call-dirmngr.c:202 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" -#: sm/call-dirmngr.c:212 +#: sm/call-dirmngr.c:214 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "Die Dirmngr Protokollversion %d wird nicht untersttzt\n" -#: sm/call-dirmngr.c:223 +#: sm/call-dirmngr.c:225 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " @@ -434,23 +434,23 @@ msgstr "keine" msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:489 +#: sm/certdump.c:490 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:498 +#: sm/certdump.c:499 msgid "[Error - unknown encoding]" msgstr "[Fehler - Unbekannte Kodierung]" -#: sm/certdump.c:502 +#: sm/certdump.c:503 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungltige Kodierung]" -#: sm/certdump.c:507 +#: sm/certdump.c:508 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungltiger DN]" -#: sm/certdump.c:651 +#: sm/certdump.c:652 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -468,7 +468,7 @@ msgid "no key usage specified - assuming all usages\n" msgstr "" "Schlsselverwendungszweck nicht vorhanden - fr alle Zwecke akzeptiert\n" -#: sm/certlist.c:123 sm/keylist.c:108 +#: sm/certlist.c:123 sm/keylist.c:224 #, c-format msgid "error getting key usage information: %s\n" msgstr "Fehler beim holen der Schlsselbenutzungsinformationen: %s\n" @@ -632,7 +632,7 @@ msgstr "(dies is wahrscheinlich keine verschl msgid "certificate `%s' not found: %s\n" msgstr "Zertifikat `%s' nicht gefunden: %s\n" -#: sm/delete.c:112 sm/keydb.c:1388 +#: sm/delete.c:112 sm/keydb.c:1403 sm/keydb.c:1496 #, c-format msgid "error locking keybox: %s\n" msgstr "Fehler beim Sperren der Keybox: %s\n" @@ -660,227 +660,227 @@ msgstr "Schwacher Schl msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:220 +#: sm/gpgsm.c:225 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:221 +#: sm/gpgsm.c:226 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:222 +#: sm/gpgsm.c:227 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:223 +#: sm/gpgsm.c:228 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:224 +#: sm/gpgsm.c:229 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:225 +#: sm/gpgsm.c:230 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:226 +#: sm/gpgsm.c:231 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:228 +#: sm/gpgsm.c:233 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:229 +#: sm/gpgsm.c:234 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:230 +#: sm/gpgsm.c:235 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:231 +#: sm/gpgsm.c:236 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:233 +#: sm/gpgsm.c:238 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:234 +#: sm/gpgsm.c:239 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:235 +#: sm/gpgsm.c:240 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:236 +#: sm/gpgsm.c:241 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:237 +#: sm/gpgsm.c:242 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:238 +#: sm/gpgsm.c:243 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:244 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:240 +#: sm/gpgsm.c:245 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:246 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:247 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:249 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:250 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:252 +#: sm/gpgsm.c:262 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:254 +#: sm/gpgsm.c:264 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:256 +#: sm/gpgsm.c:266 msgid "assume input is in base-64 format" msgstr "Eingabedaten sin im Basis-64 Format" -#: sm/gpgsm.c:258 +#: sm/gpgsm.c:268 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:260 +#: sm/gpgsm.c:270 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:263 +#: sm/gpgsm.c:273 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:267 +#: sm/gpgsm.c:278 msgid "check validity using OCSP" msgstr "Die Gltigkeit mittels OCSP prfen" -#: sm/gpgsm.c:270 +#: sm/gpgsm.c:281 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:273 +#: sm/gpgsm.c:284 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:276 +#: sm/gpgsm.c:287 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:280 +#: sm/gpgsm.c:291 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:284 +#: sm/gpgsm.c:295 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:286 +#: sm/gpgsm.c:297 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:292 +#: sm/gpgsm.c:303 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:295 +#: sm/gpgsm.c:306 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:297 +#: sm/gpgsm.c:308 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:303 +#: sm/gpgsm.c:314 msgid "don't use the terminal at all" msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:306 +#: sm/gpgsm.c:317 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:307 +#: sm/gpgsm.c:318 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:312 +#: sm/gpgsm.c:323 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:313 +#: sm/gpgsm.c:324 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:314 +#: sm/gpgsm.c:325 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:316 +#: sm/gpgsm.c:327 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:317 +#: sm/gpgsm.c:328 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:318 +#: sm/gpgsm.c:329 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:319 +#: sm/gpgsm.c:330 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:320 +#: sm/gpgsm.c:331 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:329 +#: sm/gpgsm.c:340 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:336 +#: sm/gpgsm.c:347 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:342 +#: sm/gpgsm.c:353 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verhsclsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:344 +#: sm/gpgsm.c:355 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:346 +#: sm/gpgsm.c:357 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:354 +#: sm/gpgsm.c:365 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -888,7 +888,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:357 +#: sm/gpgsm.c:368 msgid "" "@\n" "Examples:\n" @@ -908,11 +908,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:471 +#: sm/gpgsm.c:482 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:474 +#: sm/gpgsm.c:485 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -921,7 +921,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:481 +#: sm/gpgsm.c:492 msgid "" "\n" "Supported algorithms:\n" @@ -929,50 +929,50 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:562 +#: sm/gpgsm.c:573 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:628 +#: sm/gpgsm.c:639 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:644 +#: sm/gpgsm.c:655 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:719 +#: sm/gpgsm.c:730 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1151 +#: sm/gpgsm.c:1169 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1163 +#: sm/gpgsm.c:1181 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1183 +#: sm/gpgsm.c:1201 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1191 +#: sm/gpgsm.c:1209 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1221 +#: sm/gpgsm.c:1239 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1386 +#: sm/gpgsm.c:1406 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1579 sm/gpgsm.c:1612 +#: sm/gpgsm.c:1629 sm/gpgsm.c:1662 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" @@ -1020,38 +1020,38 @@ msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" msgid "error forking process: %s\n" msgstr "Fehler beim \"Forken\" des Prozess: %s\n" -#: sm/import.c:560 sm/import.c:585 +#: sm/import.c:562 sm/import.c:587 #, c-format msgid "error creating temporary file: %s\n" msgstr "Fehler beim Erstellen einer temporren Datei: %s\n" -#: sm/import.c:568 +#: sm/import.c:570 #, c-format msgid "error writing to temporary file: %s\n" msgstr "Fehler beim Schreiben auf eine temporre Datei: %s\n" -#: sm/import.c:577 +#: sm/import.c:579 #, c-format msgid "error reading input: %s\n" msgstr "Fehler beim Lesen der Eingabe: %s\n" -#: sm/import.c:647 +#: sm/import.c:649 #, c-format msgid "waiting for protect-tool to terminate failed: %s\n" msgstr "" "Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" -#: sm/import.c:650 +#: sm/import.c:652 #, c-format msgid "error running `%s': probably not installed\n" msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" -#: sm/import.c:652 +#: sm/import.c:654 #, c-format msgid "error running `%s': exit status %d\n" msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" -#: sm/import.c:655 +#: sm/import.c:657 #, c-format msgid "error running `%s': terminated\n" msgstr "Fehler beim Ausfhren von `%s': beendet\n" @@ -1075,40 +1075,40 @@ msgstr "Die \"Keybox\" `%s' wurde erstellt\n" msgid "can't create lock for `%s'\n" msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: sm/keydb.c:1312 sm/keydb.c:1374 +#: sm/keydb.c:1327 sm/keydb.c:1389 msgid "failed to get the fingerprint\n" msgstr "Kann den Fingerprint nicht ermitteln\n" -#: sm/keydb.c:1319 sm/keydb.c:1381 +#: sm/keydb.c:1334 sm/keydb.c:1396 msgid "failed to allocate keyDB handle\n" msgstr "Kann keinen KeyDB Handler bereitstellen\n" -#: sm/keydb.c:1336 +#: sm/keydb.c:1351 #, c-format msgid "problem looking for existing certificate: %s\n" msgstr "Problem bei der Suche nach vorhandenem Zertifikat: %s\n" -#: sm/keydb.c:1344 +#: sm/keydb.c:1359 #, c-format msgid "error finding writable keyDB: %s\n" msgstr "Fehler bei der Suche nach einer schreibbaren KeyDB: %s\n" -#: sm/keydb.c:1352 +#: sm/keydb.c:1367 #, c-format msgid "error storing certificate: %s\n" msgstr "Fehler beim Speichern des Zertifikats: %s\n" -#: sm/keydb.c:1396 +#: sm/keydb.c:1411 #, c-format msgid "problem re-searching certificate: %s\n" msgstr "Problem bei Wiederfinden des Zertifikats: %s\n" -#: sm/keydb.c:1405 +#: sm/keydb.c:1420 sm/keydb.c:1508 #, c-format msgid "error getting stored flags: %s\n" msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" -#: sm/keydb.c:1414 +#: sm/keydb.c:1429 sm/keydb.c:1519 #, c-format msgid "error storing flags: %s\n" msgstr "Fehler beim Speichern der Flags: %s\n" -- cgit v1.2.3 From cb76c9bc779ebb75ecc241fa336c5844838b35b2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 29 Apr 2004 18:16:44 +0000 Subject: post release version bump --- NEWS | 5 +++++ configure.ac | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 865f69f8b..cd6c102a0 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Noteworthy changes in version 1.9.9 +------------------------------------------------ + + + Noteworthy changes in version 1.9.8 (2004-04-29) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 0c7bd927a..37341ed9d 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.8, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.9-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 8370e202cc74d1cba0166ab727d222c44d6b09c3 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 29 Apr 2004 19:00:37 +0000 Subject: 2004-04-29 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (change_options_program): Turn on utf8-strings in the gpgconf specific part of the config file for the GnuPG backend. --- tools/ChangeLog | 6 ++++++ tools/gpgconf-comp.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 5fe13021b..efc78ea9e 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2004-04-29 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (change_options_program): Turn on utf8-strings in + the gpgconf specific part of the config file for the GnuPG + backend. + 2004-04-28 Werner Koch <wk@gnupg.org> * gpgconf-comp.c: Add --ocsp-signer for the dirmngr backend. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 338c43119..089818fd4 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -2075,6 +2075,11 @@ change_options_program (gc_component_t component, gc_backend_t backend, Now, dump the changed options (except for those we are going to revert to their default), and write the end marker, possibly followed by the rest of the original file. */ + + /* We have to turn on UTF8 strings for GnuPG. */ + if (backend == GC_BACKEND_GPG) + fprintf (src_file, "utf8-strings\n"); + option = gc_component[component].options; while (option->name) { -- cgit v1.2.3 From 93e9f9aedde3ca294eb884edef81adf76e10eb22 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Apr 2004 03:03:34 +0000 Subject: Added more runtime flags for the gpg-agent backend. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index efc78ea9e..529892643 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-04-30 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c: Added more runtime flags for the gpg-agent + backend. + 2004-04-29 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (change_options_program): Turn on utf8-strings in diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 089818fd4..35ad9b38e 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -430,10 +430,10 @@ static gc_option_t gc_options_gpg_agent[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, NULL, "Options controlling the diagnostic output" }, - { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, + { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, - { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "be somewhat more quiet", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, @@ -450,7 +450,7 @@ static gc_option_t gc_options_gpg_agent[] = { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, "gnupg", "Options useful for debugging" }, - { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, + { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, @@ -469,7 +469,7 @@ static gc_option_t gc_options_gpg_agent[] = { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, - { "no-grab", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not grab keyboard and mouse", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, -- cgit v1.2.3 From 6d96ca16cfcd2c7ba3bdc45799875e2488b0f62d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Apr 2004 03:27:10 +0000 Subject: (check_and_store): Do not update the stats for hidden imports of issuer certs. --- sm/ChangeLog | 5 +++++ sm/import.c | 23 +++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 105b84443..08f0212d2 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-04-30 Werner Koch <wk@gnupg.org> + + * import.c (check_and_store): Do not update the stats for hidden + imports of issuer certs. + 2004-04-28 Werner Koch <wk@gnupg.org> * gpgsm.c: New command --keydb-clear-some-cert-flags. diff --git a/sm/import.c b/sm/import.c index df080da9e..bbaa83b86 100644 --- a/sm/import.c +++ b/sm/import.c @@ -139,11 +139,13 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) { int rc; - stats->count++; + if (stats) + stats->count++; if ( depth >= 50 ) { log_error (_("certificate chain too long\n")); - stats->not_imported++; + if (stats) + stats->not_imported++; print_import_problem (ctrl, cert, 3); return; } @@ -167,12 +169,14 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) if (!existed) { print_imported_status (ctrl, cert, 1); - stats->imported++; + if (stats) + stats->imported++; } else { print_imported_status (ctrl, cert, 0); - stats->unchanged++; + if (stats) + stats->unchanged++; } if (opt.verbose > 1 && existed) @@ -192,24 +196,27 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) /* Now lets walk up the chain and import all certificates up the chain. This is required in case we already stored - parent certificates in the ephemeral keybox. */ + parent certificates in the ephemeral keybox. Do not + update the statistics, though. */ if (!gpgsm_walk_cert_chain (cert, &next)) { - check_and_store (ctrl, stats, next, depth+1); + check_and_store (ctrl, NULL, next, depth+1); ksba_cert_release (next); } } else { log_error (_("error storing certificate\n")); - stats->not_imported++; + if (stats) + stats->not_imported++; print_import_problem (ctrl, cert, 4); } } else { log_error (_("basic certificate checks failed - not imported\n")); - stats->not_imported++; + if (stats) + stats->not_imported++; print_import_problem (ctrl, cert, gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 : gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0); -- cgit v1.2.3 From 623fad67a576532a82c065e98b955da43266dcf4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Apr 2004 03:58:21 +0000 Subject: * gpg-agent.c (parse_rereadable_options): New arg REREAD. Allow changing oLogFile. (current_logfile): New. * logging.c (log_set_file): Make sure the log stream will be closed even if the stderr fileno will be assigned to a new socket. --- agent/ChangeLog | 6 ++++++ agent/gpg-agent.c | 30 +++++++++++++++++++++++------- jnlib/ChangeLog | 5 +++++ jnlib/logging.c | 9 ++++++++- 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 10674ad18..a76199961 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2004-04-30 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (parse_rereadable_options): New arg REREAD. Allow + changing oLogFile. + (current_logfile): New. + 2004-04-26 Werner Koch <wk@gnupg.org> * call-scd.c (start_scd): Do not register an event signal if we diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 9b8678823..3bf62c26f 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -155,6 +155,10 @@ static char *config_filename; /* Helper to implement --debug-level */ static const char *debug_level; +/* Keep track of the current log file so that we can avoid updating + the log file afte a SIGHUP if id didn't changed. Malloced. */ +static char *current_logfile; + /* Local prototypes. */ static void create_directories (void); #ifdef USE_GNU_PTH @@ -317,9 +321,10 @@ cleanup_sh (int sig) /* Handle options which are allowed to be reset after program start. Return true when the current option in PARGS could be handled and false if not. As a special feature, passing a value of NULL for - PARGS, resets the options to the default. */ + PARGS, resets the options to the default. REREAD should be set + true if it is not the initial option parsing. */ static int -parse_rereadable_options (ARGPARSE_ARGS *pargs) +parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) { if (!pargs) { /* reset mode */ @@ -343,6 +348,16 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs) case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs->r.ret_str; break; + case oLogFile: + if (!current_logfile || !pargs->r.ret_str + || strcmp (current_logfile, pargs->r.ret_str)) + { + log_set_file (pargs->r.ret_str); + xfree (current_logfile); + current_logfile = xtrystrdup (pargs->r.ret_str); + } + break; + case oNoGrab: opt.no_grab = 1; break; case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break; @@ -424,7 +439,7 @@ main (int argc, char **argv ) may_coredump = disable_core_dumps (); - parse_rereadable_options (NULL); /* Reset them to default values. */ + parse_rereadable_options (NULL, 0); /* Reset them to default values. */ shell = getenv ("SHELL"); if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) @@ -503,7 +518,7 @@ main (int argc, char **argv ) while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) { - if (parse_rereadable_options (&pargs)) + if (parse_rereadable_options (&pargs, 0)) continue; /* Already handled */ switch (pargs.r_opt) { @@ -626,7 +641,7 @@ main (int argc, char **argv ) GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, - GC_OPT_FLAG_NONE ); + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME ); printf ("default-cache-ttl:%lu:%d:\n", GC_OPT_FLAG_DEFAULT|GC_OPT_FLAG_RUNTIME, DEFAULT_CACHE_TTL ); printf ("no-grab:%lu:\n", @@ -659,6 +674,7 @@ main (int argc, char **argv ) log_set_prefix (NULL, (JNLIB_LOG_WITH_PREFIX |JNLIB_LOG_WITH_TIME |JNLIB_LOG_WITH_PID)); + current_logfile = xstrdup (logfile); } /* Make sure that we have a default ttyname. */ @@ -957,7 +973,7 @@ reread_configuration (void) return; } - parse_rereadable_options (NULL); /* Start from the default values. */ + parse_rereadable_options (NULL, 1); /* Start from the default values. */ memset (&pargs, 0, sizeof pargs); dummy = 0; @@ -968,7 +984,7 @@ reread_configuration (void) if (pargs.r_opt < -1) pargs.err = 1; /* Print a warning. */ else /* Try to parse this option - ignore unchangeable ones. */ - parse_rereadable_options (&pargs); + parse_rereadable_options (&pargs, 1); } fclose (fp); set_debug (); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 99c9177b5..1527fb773 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2004-04-30 Werner Koch <wk@gnupg.org> + + * logging.c (log_set_file): Make sure the log stream will be + closed even if the stderr fileno will be assigned to a new socket. + 2004-04-16 Werner Koch <wk@gnupg.org> * logging.h (JNLIB_LOG_WITH_PREFIX): Add constants for the flag diff --git a/jnlib/logging.c b/jnlib/logging.c index fdf2d7fcb..7397ddd30 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -211,7 +211,7 @@ fun_closer (void *cookie_arg) -/* Set the file to write log to. The sepcial names NULL and "_" may +/* Set the file to write log to. The special names NULL and "-" may be used to select stderr and names formatted like "socket:///home/foo/mylogs" may be used to write the logging to the socket "/home/foo/mylogs". If the connection to the socket fails @@ -258,6 +258,13 @@ log_set_file (const char *name) /* We always need to print the prefix and the pid, so that the server reading the socket can do something meanigful. */ force_prefixes = 1; + /* On success close the old logstream right now, so that we are + really sure it has been closed. */ + if (fp) + { + fclose (logstream); + logstream = NULL; + } } else fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr; -- cgit v1.2.3 From f93e691d38143ba2b38a95638808e74b4b84ef74 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Apr 2004 03:58:43 +0000 Subject: Allow changing --log-file --- tools/gpgconf-comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 35ad9b38e..ce16ce7f4 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -453,7 +453,7 @@ static gc_option_t gc_options_gpg_agent[] = { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT }, - { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|FILE|write logs to FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, -- cgit v1.2.3 From 28f89ad24521ef663a84012f71859d07a3863618 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Apr 2004 15:24:33 +0000 Subject: * protect-tool.c: New option --enable-status-msg. (store_private_key): Print status messages for imported keys. (read_and_unprotect): Ditto for bad passphrase. * import.c (check_and_store): Do not update the stats for hidden imports of issuer certs. (popen_protect_tool): Request statusmessages from the protect-tool. (parse_p12): Detect status messages. Add new arg STATS and update them. (print_imported_summary): Include secret key stats. --- agent/ChangeLog | 4 +++ agent/protect-tool.c | 11 ++++++++ sm/ChangeLog | 3 +++ sm/import.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index a76199961..2f2b1e410 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,9 @@ 2004-04-30 Werner Koch <wk@gnupg.org> + * protect-tool.c: New option --enable-status-msg. + (store_private_key): Print status messages for imported keys. + (read_and_unprotect): Ditto for bad passphrase. + * gpg-agent.c (parse_rereadable_options): New arg REREAD. Allow changing oLogFile. (current_logfile): New. diff --git a/agent/protect-tool.c b/agent/protect-tool.c index c62c649ad..c33d21094 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -58,6 +58,7 @@ enum cmd_and_opt_values oNoFailOnExist, oHomedir, oPrompt, + oStatusMsg, aTest }; @@ -80,6 +81,7 @@ static int opt_no_fail_on_exist; static int opt_have_cert; static const char *opt_passphrase; static char *opt_prompt; +static int opt_status_msg; static char *get_passphrase (int promptno); static void release_passphrase (char *pw); @@ -108,6 +110,7 @@ static ARGPARSE_OPTS opts[] = { { oNoFailOnExist, "no-fail-on-exist", 0, "@" }, { oHomedir, "homedir", 2, "@" }, { oPrompt, "prompt", 2, "|ESCSTRING|use ESCSTRING as prompt in pinentry"}, + { oStatusMsg, "enable-status-msg", 0, "@"}, {0} }; @@ -384,6 +387,8 @@ read_and_unprotect (const char *fname) xfree (key); if (rc) { + if (opt_status_msg) + log_info ("[PROTECT-TOOL:] bad-passphrase\n"); log_error ("unprotecting the key failed: %s\n", gpg_strerror (rc)); return; } @@ -1076,6 +1081,7 @@ main (int argc, char **argv ) case oNoFailOnExist: opt_no_fail_on_exist = 1; break; case oHaveCert: opt_have_cert = 1; break; case oPrompt: opt_prompt = pargs.r.ret_str; break; + case oStatusMsg: opt_status_msg = 1; break; default : pargs.err = 2; break; } @@ -1185,6 +1191,8 @@ store_private_key (const unsigned char *grip, { if (!access (fname, F_OK)) { + if (opt_status_msg) + log_info ("[PROTECT-TOOL:] secretkey-exists\n"); if (opt_no_fail_on_exist) log_info ("secret key file `%s' already exists\n", fname); else @@ -1221,6 +1229,9 @@ store_private_key (const unsigned char *grip, } log_info ("secret key stored as `%s'\n", fname); + if (opt_status_msg) + log_info ("[PROTECT-TOOL:] secretkey-stored\n"); + xfree (fname); return 0; } diff --git a/sm/ChangeLog b/sm/ChangeLog index 08f0212d2..9e29d0c92 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -2,6 +2,9 @@ * import.c (check_and_store): Do not update the stats for hidden imports of issuer certs. + (popen_protect_tool): Request statusmessages from the protect-tool. + (parse_p12): Detect status messages. Add new arg STATS and update them. + (print_imported_summary): Include secret key stats. 2004-04-28 Werner Koch <wk@gnupg.org> diff --git a/sm/import.c b/sm/import.c index bbaa83b86..c5581eb64 100644 --- a/sm/import.c +++ b/sm/import.c @@ -49,10 +49,14 @@ struct stats_s { unsigned long imported; unsigned long unchanged; unsigned long not_imported; -}; + unsigned long secret_read; + unsigned long secret_imported; + unsigned long secret_dups; + }; -static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp); +static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp, + struct stats_s *stats); @@ -119,16 +123,32 @@ print_imported_summary (CTRL ctrl, struct stats_s *stats) } if (stats->unchanged) log_info (_(" unchanged: %lu\n"), stats->unchanged); + if (stats->secret_read) + log_info (_(" secret keys read: %lu\n"), stats->secret_read ); + if (stats->secret_imported) + log_info (_(" secret keys imported: %lu\n"), stats->secret_imported ); + if (stats->secret_dups) + log_info (_(" secret keys unchanged: %lu\n"), stats->secret_dups ); if (stats->not_imported) log_info (_(" not imported: %lu\n"), stats->not_imported); } - sprintf (buf, "%lu 0 %lu 0 %lu 0 0 0 0 0 0 0 0 %lu", - stats->count, - stats->imported, - stats->unchanged, - stats->not_imported - ); + sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + stats->count, + 0l /*stats->no_user_id*/, + stats->imported, + 0l /*stats->imported_rsa*/, + stats->unchanged, + 0l /*stats->n_uids*/, + 0l /*stats->n_subk*/, + 0l /*stats->n_sigs*/, + 0l /*stats->n_revoc*/, + stats->secret_read, + stats->secret_imported, + stats->secret_dups, + 0l /*stats->skipped_new_keys*/, + stats->not_imported + ); gpgsm_status (ctrl, STATUS_IMPORT_RES, buf); } @@ -315,7 +335,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) Base64Context b64p12rdr; ksba_reader_t p12rdr; - rc = parse_p12 (reader, &certfp); + rc = parse_p12 (reader, &certfp, stats); if (!rc) { any = 1; @@ -512,6 +532,7 @@ popen_protect_tool (const char *pgmname, "--p12-import", "--store", "--no-fail-on-exist", + "--enable-status-msg", "--", NULL); /* No way to print anything, as we have closed all streams. */ @@ -540,7 +561,7 @@ popen_protect_tool (const char *pgmname, certificates. On success RETFP returns a temporary file with certificates. */ static gpg_error_t -parse_p12 (ksba_reader_t reader, FILE **retfp) +parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) { const char *pgmname; gpg_error_t err = 0, child_err = 0; @@ -613,13 +634,39 @@ parse_p12 (ksba_reader_t reader, FILE **retfp) protect tool to figure out better error codes for CHILD_ERR. */ buffer[pos++] = c; - if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n') + if (pos >= sizeof buffer - 5 || c == '\n') { buffer[pos - (c == '\n')] = 0; if (cont_line) log_printf ("%s", buffer); else - log_info ("%s", buffer); + { + if (!strncmp (buffer, "gpg-protect-tool: [PROTECT-TOOL:] ",34)) + { + char *p, *pend; + + p = buffer + 34; + pend = strchr (p, ' '); + if (pend) + *pend = 0; + if ( !strcmp (p, "secretkey-stored")) + { + stats->count++; + stats->secret_read++; + stats->secret_imported++; + } + else if ( !strcmp (p, "secretkey-exists")) + { + stats->count++; + stats->secret_read++; + stats->secret_dups++; + } + else if ( !strcmp (p, "bad-passphrase")) + ; + } + else + log_info ("%s", buffer); + } pos = 0; cont_line = (c != '\n'); } -- cgit v1.2.3 From 339f0840e11b1421338966edd0d5dc97af24ad26 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Apr 2004 16:36:36 +0000 Subject: (main) <gpgconf>: Use gpg.conf and not /dev/null as default filename. --- g10/ChangeLog | 5 +++++ g10/g10.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 86c6c7957..0e87c2f46 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2004-04-30 Werner Koch <wk@gnupg.org> + + * g10.c (main) <gpgconf>: Use gpg.conf and not /dev/null as + default filename. + 2004-04-28 Werner Koch <wk@gnupg.org> * card-util.c (card_edit): Remove PIN verification. diff --git a/g10/g10.c b/g10/g10.c index 006e88ad2..915011026 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -2953,9 +2953,11 @@ main( int argc, char **argv ) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + if (!config_filename) + config_filename = make_filename (opt.homedir, "gpg.conf", NULL); + printf ("gpgconf-gpg.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, - config_filename?config_filename:"/dev/null"); + GC_OPT_FLAG_DEFAULT, config_filename); printf ("verbose:%lu:\n" "quiet:%lu:\n" -- cgit v1.2.3 From 30bbef1a285929422bd99d648592e146cd5418ae Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 3 May 2004 13:37:38 +0000 Subject: * gpg-agent.c: Remove help texts for options lile --lc-ctype. (main): New option --allow-mark-trusted. * trustlist.c (agent_marktrusted): Use it here. * gpg-agent.texi (Agent Options): Add --allow-mark-trusted. * gpgconf-comp.c: Add --allow-mark-trusted for the gpg-agent. --- agent/ChangeLog | 6 ++++++ agent/agent.h | 1 + agent/gpg-agent.c | 33 ++++++++++++++++++++++----------- agent/trustlist.c | 6 +++++- doc/ChangeLog | 4 ++++ doc/gpg-agent.texi | 6 ++++++ tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 3 +++ 8 files changed, 51 insertions(+), 12 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 2f2b1e410..cf4ae79bf 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2004-05-03 Werner Koch <wk@gnupg.org> + + * gpg-agent.c: Remove help texts for options lile --lc-ctype. + (main): New option --allow-mark-trusted. + * trustlist.c (agent_marktrusted): Use it here. + 2004-04-30 Werner Koch <wk@gnupg.org> * protect-tool.c: New option --enable-status-msg. diff --git a/agent/agent.h b/agent/agent.h index a4312e081..99fdc0547 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -58,6 +58,7 @@ struct { int running_detached; /* we are running detached from the tty. */ int ignore_cache_for_signing; + int allow_mark_trusted; int keep_tty; /* don't switch the TTY (for pinentry) on request */ int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ } opt; diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 3bf62c26f..ad6ef33ea 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -80,6 +80,7 @@ enum cmd_and_opt_values oDisablePth, oIgnoreCacheForSigning, + oAllowMarkTrusted, oKeepTTY, oKeepDISPLAY, @@ -109,21 +110,26 @@ static ARGPARSE_OPTS opts[] = { { oLogFile, "log-file" ,2, N_("use a log file for the server")}, { oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")}, - { oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" }, - { oDisplay, "display", 2, "set the display" }, - { oTTYname, "ttyname", 2, "set the tty terminal node name" }, - { oTTYtype, "ttytype", 2, "set the tty terminal type" }, - { oLCctype, "lc-ctype", 2, "set the tty LC_CTYPE value" }, - { oLCmessages, "lc-messages", 2, "set the tty LC_MESSAGES value" }, + { oPinentryProgram, "pinentry-program", 2 , + N_("|PGM|use PGM as the PIN-Entry program") }, + { oScdaemonProgram, "scdaemon-program", 2 , + N_("|PGM|use PGM as the SCdaemon program") }, - { oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" }, - { oDefCacheTTL, "default-cache-ttl", 4, - "|N|expire cached PINs after N seconds"}, - { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, - "do not use the PIN cache when signing"}, + { oDisplay, "display", 2, "@" }, + { oTTYname, "ttyname", 2, "@" }, + { oTTYtype, "ttytype", 2, "@" }, + { oLCctype, "lc-ctype", 2, "@" }, + { oLCmessages, "lc-messages", 2, "@" }, { oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")}, { oKeepDISPLAY, "keep-display", 0, N_("ignore requests to change the X display")}, + + { oDefCacheTTL, "default-cache-ttl", 4, + N_("|N|expire cached PINs after N seconds")}, + { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, + N_("do not use the PIN cache when signing")}, + { oAllowMarkTrusted, "allow-mark-trusted", 0, + N_("allow clients to mark keys as \"trusted\"")}, {0} }; @@ -336,6 +342,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.scdaemon_program = NULL; opt.def_cache_ttl = DEFAULT_CACHE_TTL; opt.ignore_cache_for_signing = 0; + opt.allow_mark_trusted = 0; return 1; } @@ -367,6 +374,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; + case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break; + default: return 0; /* not handled */ } @@ -648,6 +657,8 @@ main (int argc, char **argv ) GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("ignore-cache-for-signing:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); + printf ("allow-mark-trusted:%lu:\n", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); agent_exit (0); } diff --git a/agent/trustlist.c b/agent/trustlist.c index 5c3271ac0..19de0708d 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -224,7 +224,7 @@ agent_listtrusted (void *assuan_context) /* Insert the given fpr into our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'. - This function does first check whether that key has alreay ben put + This function does first check whether that key has alreay been put into the trustdb and returns success in this case. Before a FPR actually gets inserted, the user is asked by means of the pin-entry whether this is actual wants he want to do. @@ -265,6 +265,10 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) if (rc != -1) return rc; /* error in the trustdb */ + /* This feature must explicitly been enabled. */ + if (!opt.allow_mark_trusted) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + /* insert a new one */ if (asprintf (&desc, "Please verify that the certificate identified as:%%0A" diff --git a/doc/ChangeLog b/doc/ChangeLog index 39d98b963..a920022d0 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +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 diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index e199109a4..aad0fbb68 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -238,6 +238,12 @@ seeing what the agent actually does. 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 diff --git a/tools/ChangeLog b/tools/ChangeLog index 529892643..fa41aff0a 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-05-03 Werner Koch <wk@gnupg.org> + + * gpgconf-comp.c: Add --allow-mark-trusted for the gpg-agent. + 2004-04-30 Werner Koch <wk@gnupg.org> * gpgconf-comp.c: Added more runtime flags for the gpg-agent diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index ce16ce7f4..735e87c86 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -469,6 +469,9 @@ static gc_option_t gc_options_gpg_agent[] = { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, + { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, + "gnupg", "allow clients to mark keys as \"trusted\"", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", "do not grab keyboard and mouse", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, -- cgit v1.2.3 From edda971a15c98194bba283786d3e486e8f5839c5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 5 May 2004 19:33:56 +0000 Subject: (log_set_file): Oops, don't close if LOGSTREAM is NULL. --- jnlib/ChangeLog | 4 ++++ jnlib/logging.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 1527fb773..e9f643774 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2004-05-05 Werner Koch <wk@gnupg.org> + + * logging.c (log_set_file): Oops, don't close if LOGSTREAM is NULL. + 2004-04-30 Werner Koch <wk@gnupg.org> * logging.c (log_set_file): Make sure the log stream will be diff --git a/jnlib/logging.c b/jnlib/logging.c index 7397ddd30..c75efaf85 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -260,7 +260,7 @@ log_set_file (const char *name) force_prefixes = 1; /* On success close the old logstream right now, so that we are really sure it has been closed. */ - if (fp) + if (fp && logstream) { fclose (logstream); logstream = NULL; -- cgit v1.2.3 From d3184ce584f540d765da72988269e2d2a9f29e0f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 11 May 2004 09:15:56 +0000 Subject: * gpgsm.h (opt): Add member CONFIG_FILENAME. * gpgsm.c (main): Use it here instead of the local var. * server.c (gpgsm_server): Print some additional information with the hello in verbose mode. --- NEWS | 3 +++ TODO | 5 ----- configure.ac | 2 +- sm/ChangeLog | 7 +++++++ sm/gpgsm.c | 12 +++++------- sm/gpgsm.h | 3 ++- sm/server.c | 22 ++++++++++++++++++++-- 7 files changed, 38 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index cd6c102a0..e24af0476 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ Noteworthy changes in version 1.9.9 ------------------------------------------------ + * [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. Noteworthy changes in version 1.9.8 (2004-04-29) diff --git a/TODO b/TODO index 80035b69b..0ac96b85c 100644 --- a/TODO +++ b/TODO @@ -70,11 +70,6 @@ might want to have an agent context for each service request * scd/sc-investigate ** Enhance with card compatibility check -* scd/app-openpgp - Must check that the fingerprint used is not the one of the - authentication key. Old GnuPG versions seem to encode the wrong - keyID. - * tests ** Makefile.am We use printf(1) to setup the library path, this is not portable. diff --git a/configure.ac b/configure.ac index 37341ed9d..687805759 100644 --- a/configure.ac +++ b/configure.ac @@ -34,7 +34,7 @@ NEED_GPG_ERROR_VERSION=0.7 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.1.94 -NEED_LIBASSUAN_VERSION=0.6.5 +NEED_LIBASSUAN_VERSION=0.6.6 NEED_KSBA_VERSION=0.9.4 diff --git a/sm/ChangeLog b/sm/ChangeLog index 9e29d0c92..ee5f1a5a6 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-05-11 Werner Koch <wk@gnupg.org> + + * gpgsm.h (opt): Add member CONFIG_FILENAME. + * gpgsm.c (main): Use it here instead of the local var. + * server.c (gpgsm_server): Print some additional information with + the hello in verbose mode. + 2004-04-30 Werner Koch <wk@gnupg.org> * import.c (check_and_store): Do not update the stats for hidden diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 61307701a..adc04336e 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -701,7 +701,6 @@ main ( int argc, char **argv) CERTLIST recplist = NULL; CERTLIST signerlist = NULL; int do_not_setup_keys = 0; - char *config_filename = NULL; /* trap_unaligned ();*/ set_strusage (my_strusage); @@ -1136,14 +1135,16 @@ main ( int argc, char **argv) fclose (configfp); configfp = NULL; /* Keep a copy of the config filename. */ - config_filename = configname; + opt.config_filename = configname; configname = NULL; goto next_pass; } - xfree (configname); configname = NULL; + if (!opt.config_filename) + opt.config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL); + if (log_get_errorcount(0)) gpgsm_exit(2); @@ -1297,11 +1298,8 @@ main ( int argc, char **argv) a default, which is described by the value of the ARGDEF field. */ #define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - if (!config_filename) - config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL); - printf ("gpgconf-gpgsm.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, config_filename); + GC_OPT_FLAG_DEFAULT, opt.config_filename); printf ("verbose:%lu:\n" "quiet:%lu:\n" diff --git a/sm/gpgsm.h b/sm/gpgsm.h index c1a3c9964..3c3a1ba76 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -45,7 +45,8 @@ struct { int answer_no; /* assume no on most questions */ int dry_run; /* don't change any persistent data */ - const char *homedir; /* configuration directory name */ + const char *homedir; /* Configuration directory name */ + const char *config_filename; /* Name of the used config file. */ const char *agent_program; char *display; char *ttyname; diff --git a/sm/server.c b/sm/server.c index e73efe418..293857139 100644 --- a/sm/server.c +++ b/sm/server.c @@ -1,5 +1,5 @@ /* server.c - Server mode and main entry point - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -786,6 +786,8 @@ gpgsm_server (certlist_t default_recplist) int filedes[2]; ASSUAN_CONTEXT ctx; struct server_control_s ctrl; + static const char hello[] = ("GNU Privacy Guard's S/M server " + VERSION " ready"); memset (&ctrl, 0, sizeof ctrl); gpgsm_init_default_ctrl (&ctrl); @@ -809,7 +811,23 @@ gpgsm_server (certlist_t default_recplist) assuan_strerror(rc)); gpgsm_exit (2); } - assuan_set_hello_line (ctx, "GNU Privacy Guard's S/M server ready"); + if (opt.verbose) + { + char *tmp = NULL; + if (asprintf (&tmp, + "Home: %s\n" + "Config: %s\n" + "%s", + opt.homedir, + opt.config_filename, + hello) > 0) + { + assuan_set_hello_line (ctx, tmp); + free (tmp); + } + } + else + assuan_set_hello_line (ctx, hello); assuan_register_reset_notify (ctx, reset_notify); assuan_register_input_notify (ctx, input_notify); -- cgit v1.2.3 From 13b620506640a650f69e64bd4882f27df5d6a1d7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 11 May 2004 09:24:09 +0000 Subject: Also print agent and dirmngr info. --- sm/server.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sm/server.c b/sm/server.c index 293857139..d94485926 100644 --- a/sm/server.c +++ b/sm/server.c @@ -814,13 +814,20 @@ gpgsm_server (certlist_t default_recplist) if (opt.verbose) { char *tmp = NULL; + const char *s1 = getenv ("GPG_AGENT_INFO"); + const char *s2 = getenv ("DIRMNGR_INFO"); + if (asprintf (&tmp, - "Home: %s\n" - "Config: %s\n" - "%s", - opt.homedir, - opt.config_filename, - hello) > 0) + "Home: %s\n" + "Config: %s\n" + "AgentInfo: %s\n" + "DirmngrInfo: %s\n" + "%s", + opt.homedir, + opt.config_filename, + s1?s1:"[not set]", + s2?s2:"[not set]", + hello) > 0) { assuan_set_hello_line (ctx, tmp); free (tmp); -- cgit v1.2.3 From ac791c0a9a4bcd6ec1785d1689994b578a9edf82 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 11 May 2004 09:54:52 +0000 Subject: * sysutils.c (disable_core_dumps): Only set the current limit. (enable_core_dumps): New. * gpgsm.texi (Esoteric Options): Add --debug-allow-core-dump. * gpgsm.c: New option --debug-allow-core-dump. * gpgsm.h (opt): Add member CONFIG_FILENAME. * gpgsm.c (main): Use it here instead of the local var. * server.c (gpgsm_server): Print some additional information with the hello in verbose mode. --- common/ChangeLog | 5 +++++ common/sysutils.c | 37 ++++++++++++++++++++++++++++++------- common/sysutils.h | 1 + doc/ChangeLog | 4 ++++ doc/gpgsm.texi | 8 ++++++++ sm/ChangeLog | 3 +++ sm/gpgsm.c | 5 +++++ sm/server.c | 2 +- 8 files changed, 57 insertions(+), 8 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 8e81baa0c..a39f17aaa 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/common/sysutils.c b/common/sysutils.c index 4948af57f..97fa23d95 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -70,21 +70,44 @@ trap_unaligned(void) int disable_core_dumps (void) { - #ifdef HAVE_DOSISH_SYSTEM +#ifdef HAVE_DOSISH_SYSTEM return 0; - #else - #ifdef HAVE_SETRLIMIT +#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; - limit.rlim_max = 0; - if( !setrlimit( RLIMIT_CORE, &limit ) ) + if( !setrlimit (RLIMIT_CORE, &limit) ) return 0; if( errno != EINVAL && errno != ENOSYS ) log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) ); - #endif +#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 +#endif } diff --git a/common/sysutils.h b/common/sysutils.h index f2054d468..66f714acd 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -23,6 +23,7 @@ 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); diff --git a/doc/ChangeLog b/doc/ChangeLog index a920022d0..1676834f8 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index b5c87b77c..4bb688c44 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -444,6 +444,14 @@ Note, that all flags set using this option may get overriden by @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 diff --git a/sm/ChangeLog b/sm/ChangeLog index ee5f1a5a6..af7ddb1c6 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,7 +1,10 @@ 2004-05-11 Werner Koch <wk@gnupg.org> + * gpgsm.c: New option --debug-allow-core-dump. + * gpgsm.h (opt): Add member CONFIG_FILENAME. * gpgsm.c (main): Use it here instead of the local var. + * server.c (gpgsm_server): Print some additional information with the hello in verbose mode. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index adc04336e..e1751a7aa 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -92,6 +92,7 @@ enum cmd_and_opt_values { oDebugLevel, oDebugAll, oDebugWait, + oDebugAllowCoreDump, oDebugNoChainValidation, oDebugIgnoreExpiration, oLogFile, @@ -335,6 +336,7 @@ static ARGPARSE_OPTS opts[] = { { oDebugLevel, "debug-level" ,2, "@"}, { oDebugAll, "debug-all" ,0, "@"}, { oDebugWait, "debug-wait" ,1, "@"}, + { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" }, { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"}, { oDebugIgnoreExpiration, "debug-ignore-expiration", 0, "@"}, { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, @@ -1010,6 +1012,9 @@ main ( int argc, char **argv) case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; + case oDebugAllowCoreDump: + may_coredump = enable_core_dumps (); + break; case oDebugNoChainValidation: opt.no_chain_validation = 1; break; case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break; diff --git a/sm/server.c b/sm/server.c index d94485926..72bf74afa 100644 --- a/sm/server.c +++ b/sm/server.c @@ -811,7 +811,7 @@ gpgsm_server (certlist_t default_recplist) assuan_strerror(rc)); gpgsm_exit (2); } - if (opt.verbose) + if (opt.verbose || opt.debug) { char *tmp = NULL; const char *s1 = getenv ("GPG_AGENT_INFO"); -- cgit v1.2.3 From fdb1933917f9257b911c7e54ad046772c7ab4507 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 11 May 2004 15:36:48 +0000 Subject: * sign.c (gpgsm_sign): Include the error source in the final error message. * decrypt.c (gpgsm_decrypt): Ditto. * fingerprint.c (gpgsm_get_key_algo_info): New. * sign.c (gpgsm_sign): Don't assume RSA in the status line. * keylist.c (list_cert_colon): Really print the algorithm and key length. (list_cert_raw, list_cert_std): Ditto. * gpgsm.h (opt): Add member CONFIG_FILENAME. * gpgsm.c (main): Use it here instead of the local var. --- sm/ChangeLog | 10 ++++++++++ sm/decrypt.c | 3 ++- sm/fingerprint.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sm/gpgsm.h | 1 + sm/keylist.c | 26 ++++++++++++++++++++---- sm/sign.c | 18 ++++++++++------- 6 files changed, 106 insertions(+), 12 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index af7ddb1c6..a1997e27e 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,15 @@ 2004-05-11 Werner Koch <wk@gnupg.org> + * sign.c (gpgsm_sign): Include the error source in the final error + message. + * decrypt.c (gpgsm_decrypt): Ditto. + + * fingerprint.c (gpgsm_get_key_algo_info): New. + * sign.c (gpgsm_sign): Don't assume RSA in the status line. + * keylist.c (list_cert_colon): Really print the algorithm and key + length. + (list_cert_raw, list_cert_std): Ditto. + * gpgsm.c: New option --debug-allow-core-dump. * gpgsm.h (opt): Add member CONFIG_FILENAME. diff --git a/sm/decrypt.c b/sm/decrypt.c index 9a21cfb46..de53af9e7 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -495,7 +495,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp) if (rc) { gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL); - log_error ("message decryption failed: %s\n", gpg_strerror (rc)); + log_error ("message decryption failed: %s <%s>\n", + gpg_strerror (rc), gpg_strsource (rc)); } ksba_cms_release (cms); gpgsm_destroy_reader (b64reader); diff --git a/sm/fingerprint.c b/sm/fingerprint.c index 6755f8eb7..7fe619c18 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -198,6 +198,66 @@ gpgsm_get_keygrip_hexstring (ksba_cert_t cert) } +/* Return the PK algorithm used by CERT as well as the length in bits + of the public key at NBITS. */ +int +gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits) +{ + gcry_sexp_t s_pkey; + int rc; + ksba_sexp_t p; + size_t n; + gcry_sexp_t l1, l2; + const char *name; + char namebuf[128]; + + if (nbits) + *nbits = 0; + + p = ksba_cert_get_public_key (cert); + if (!p) + return 0; + n = gcry_sexp_canon_len (p, 0, NULL, NULL); + if (!n) + { + xfree (p); + return 0; + } + rc = gcry_sexp_sscan (&s_pkey, NULL, p, n); + xfree (p); + if (rc) + return 0; + + if (nbits) + *nbits = gcry_pk_get_nbits (s_pkey); + + /* Breaking the algorithm out of the S-exp is a bit of a challenge ... */ + l1 = gcry_sexp_find_token (s_pkey, "public-key", 0); + if (!l1) + { + gcry_sexp_release (s_pkey); + return 0; + } + l2 = gcry_sexp_cadr (l1); + gcry_sexp_release (l1); + l1 = l2; + name = gcry_sexp_nth_data (l1, 0, &n); + if (name) + { + if (n > sizeof namebuf -1) + n = sizeof namebuf -1; + memcpy (namebuf, name, n); + namebuf[n] = 0; + } + else + *namebuf = 0; + gcry_sexp_release (l1); + gcry_sexp_release (s_pkey); + return gcry_pk_map_name (namebuf); +} + + + /* For certain purposes we need a certificate id which has an upper limit of the size. We use the hash of the issuer name and the diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 3c3a1ba76..786a97353 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -179,6 +179,7 @@ char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo); unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert); char *gpgsm_get_keygrip (ksba_cert_t cert, char *array); char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert); +int gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits); char *gpgsm_get_certid (ksba_cert_t cert); diff --git a/sm/keylist.c b/sm/keylist.c index 07cddb3dc..e9056b6da 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -296,6 +296,8 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, char *fpr; ksba_isotime_t t; gpg_error_t valerr; + int algo; + unsigned int nbits; if (ctrl->with_validation) valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0); @@ -330,10 +332,8 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, fputs (truststring, fp); fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - fprintf (fp, ":%u:%d:%s:", - /*keylen_of_cert (cert)*/1024, - /* pubkey_algo_of_cert (cert)*/1, - fpr+24); + algo = gpgsm_get_key_algo_info (cert, &nbits); + fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24); /* We assume --fixed-list-mode for gpgsm */ ksba_cert_get_validity (cert, 0, t); @@ -547,6 +547,14 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, s = get_oid_desc (oid, NULL); fprintf (fp, " hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":""); + { + const char *algoname; + unsigned int nbits; + + algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits)); + fprintf (fp, " keyType: %u bit %s\n", nbits, algoname? algoname:"?"); + } + /* authorityKeyIdentifier */ fputs (" authKeyId: ", fp); err = ksba_cert_get_auth_key_id (cert, NULL, &name, &sexp); @@ -829,6 +837,16 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, gpgsm_print_time (fp, t); putc ('\n', fp); + + { + const char *algoname; + unsigned int nbits; + + algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits)); + fprintf (fp, " key type: %u bit %s\n", nbits, algoname? algoname:"?"); + } + + err = ksba_cert_get_key_usage (cert, &kusage); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { diff --git a/sm/sign.c b/sm/sign.c index 9d34ab221..3340f1066 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -616,12 +616,15 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, gcry_md_close (md); goto leave; } - rc = asprintf (&buf, "%c %d %d 00 %s %s", - detached? 'D':'S', - GCRY_PK_RSA, /* FIXME: get pk algo from cert */ - algo, - signed_at, - fpr); + { + int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL); + rc = asprintf (&buf, "%c %d %d 00 %s %s", + detached? 'D':'S', + pkalgo, + algo, + signed_at, + fpr); + } xfree (fpr); if (rc < 0) { @@ -651,7 +654,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, leave: if (rc) - log_error ("error creating signature: %s\n", gpg_strerror (rc)); + log_error ("error creating signature: %s <%s>\n", + gpg_strerror (rc), gpg_strsource (rc) ); if (release_signerlist) gpgsm_release_certlist (signerlist); ksba_cms_release (cms); -- cgit v1.2.3 From 2cce42c23f628383485d04a8c38a13c490b62257 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 11 May 2004 19:11:53 +0000 Subject: * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. (start_connection_thread): Hack to simulate a ticker. * trustlist.c (agent_trustlist_housekeeping) (agent_reload_trustlist): New. Protected all global functions here with a simple counter which is sufficient for Pth. * fingerprint.c (gpgsm_get_key_algo_info): New. * sign.c (gpgsm_sign): Don't assume RSA in the status line. * keylist.c (list_cert_colon): Really print the algorithm and key length. (list_cert_raw, list_cert_std): Ditto. (list_cert_colon): Reorganized to be able to tell whether a root certificate is trusted. --- agent/ChangeLog | 8 ++++ agent/agent.h | 2 + agent/gpg-agent.c | 7 ++++ agent/trustlist.c | 111 +++++++++++++++++++++++++++++++++++++++++++----------- sm/ChangeLog | 2 + sm/keylist.c | 65 ++++++++++++++++++++++---------- 6 files changed, 153 insertions(+), 42 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index cf4ae79bf..ae1dd884e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2004-05-11 Werner Koch <wk@gnupg.org> + + * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. + (start_connection_thread): Hack to simulate a ticker. + * trustlist.c (agent_trustlist_housekeeping) + (agent_reload_trustlist): New. Protected all global functions + here with a simple counter which is sufficient for Pth. + 2004-05-03 Werner Koch <wk@gnupg.org> * gpg-agent.c: Remove help texts for options lile --lc-ctype. diff --git a/agent/agent.h b/agent/agent.h index 99fdc0547..6b7821e30 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -189,6 +189,8 @@ int agent_istrusted (const char *fpr); int agent_listtrusted (void *assuan_context); int agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag); +void agent_trustlist_housekeeping (void); +void agent_reload_trustlist (void); /*-- divert-scd.c --*/ diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ad6ef33ea..8d21dc43c 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1083,6 +1083,7 @@ handle_signal (int signo) "re-reading configuration and flushing cache\n"); agent_flush_cache (); reread_configuration (); + agent_reload_trustlist (); break; case SIGUSR1: @@ -1129,6 +1130,12 @@ start_connection_thread (void *arg) if (opt.verbose) log_info ("handler for fd %d started\n", fd); + + /* FIXME: Move this housekeeping into a ticker function. Calling it + for each connection should work but won't work anymore if our + cleints start to keep connections. */ + agent_trustlist_housekeeping (); + start_command_handler (-1, fd); if (opt.verbose) log_info ("handler for fd %d terminated\n", fd); diff --git a/agent/trustlist.c b/agent/trustlist.c index 19de0708d..16b7dc34e 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -1,5 +1,5 @@ /* trustlist.c - Maintain the list of trusted keys - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -41,10 +41,13 @@ static const char headerblurb[] = "# with optional white spaces, followed by exactly 40 hex character,\n" "# optioanlly followed by a flag character which my either be 'P', 'S'\n" "# or '*'. Additional data delimited with by a white space is ignored.\n" +"# NOTE: You should give the gpg-agent a HUP after editing this file.\n" "\n"; static FILE *trustfp; +static int trustfp_used; /* Counter to track usage of TRUSTFP. */ +static int reload_trustlist_pending; static int @@ -164,7 +167,7 @@ read_list (char *key, int *keyflag) return 0; } -/* check whether the given fpr is in our trustdb. We expect FPR to be +/* Check whether the given fpr is in our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. */ int agent_istrusted (const char *fpr) @@ -173,25 +176,31 @@ agent_istrusted (const char *fpr) static char key[41]; int keyflag; + trustfp_used++; if (trustfp) rewind (trustfp); while (!(rc=read_list (key, &keyflag))) { if (!strcmp (key, fpr)) - return 0; + { + trustfp_used--; + return 0; + } } if (rc != -1) { - /* error in the trustdb - close it to give the user a chance for + /* Error in the trustdb - close it to give the user a chance for correction */ - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; } + trustfp_used--; return rc; } -/* write all trust entries to FP */ +/* Write all trust entries to FP. */ int agent_listtrusted (void *assuan_context) { @@ -199,6 +208,7 @@ agent_listtrusted (void *assuan_context) static char key[51]; int keyflag; + trustfp_used++; if (trustfp) rewind (trustfp); while (!(rc=read_list (key, &keyflag))) @@ -213,11 +223,13 @@ agent_listtrusted (void *assuan_context) rc = 0; if (rc) { - /* error in the trustdb - close it to give the user a chance for + /* Error in the trustdb - close it to give the user a chance for correction */ - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; } + trustfp_used--; return rc; } @@ -252,7 +264,7 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) } xfree (fname); - + trustfp_used++; if (trustfp) rewind (trustfp); while (!(rc=read_list (key, &keyflag))) @@ -260,14 +272,21 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) if (!strcmp (key, fpr)) return 0; } - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; if (rc != -1) - return rc; /* error in the trustdb */ + { + trustfp_used--; + return rc; /* Error in the trustlist. */ + } /* This feature must explicitly been enabled. */ if (!opt.allow_mark_trusted) - return gpg_error (GPG_ERR_NOT_SUPPORTED); + { + trustfp_used--; + return gpg_error (GPG_ERR_NOT_SUPPORTED); + } /* insert a new one */ if (asprintf (&desc, @@ -275,42 +294,62 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) " \"%s\"%%0A" "has the fingerprint:%%0A" " %s", name, fpr) < 0 ) - return out_of_core (); + { + trustfp_used--; + return out_of_core (); + } rc = agent_get_confirmation (ctrl, desc, "Correct", "No"); free (desc); if (rc) - return rc; + { + trustfp_used--; + return rc; + } if (asprintf (&desc, "Do you ultimately trust%%0A" " \"%s\"%%0A" "to correctly certify user certificates?", name) < 0 ) - return out_of_core (); + { + trustfp_used--; + return out_of_core (); + } rc = agent_get_confirmation (ctrl, desc, "Yes", "No"); free (desc); if (rc) - return rc; + { + trustfp_used--; + return rc; + } - /* now check again to avoid duplicates. Also open in append mode now */ + /* Now check again to avoid duplicates. Also open in append mode now. */ rc = open_list (1); if (rc) - return rc; + { + trustfp_used--; + return rc; + } rewind (trustfp); while (!(rc=read_list (key, &keyflag))) { if (!strcmp (key, fpr)) - return 0; + { + trustfp_used--; + return 0; + } } if (rc != -1) { - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; - return rc; /* error in the trustdb */ + trustfp_used--; + return rc; /* Error in the trustlist. */ } rc = 0; - /* append the key */ + /* Append the key. */ fflush (trustfp); fputs ("\n# ", trustfp); print_sanitized_string (trustfp, name, 0); @@ -322,5 +361,33 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) if (fclose (trustfp)) rc = gpg_error (gpg_err_code_from_errno (errno)); trustfp = NULL; + trustfp_used--; return rc; } + + +void +agent_trustlist_housekeeping (void) +{ + if (reload_trustlist_pending && !trustfp_used) + { + if (trustfp) + { + fclose (trustfp); + trustfp = NULL; + } + reload_trustlist_pending = 0; + } +} + + +/* Not all editors are editing files in place, thus a changes + trustlist.txt won't be recognozed if we keep the file descriptor + open. This function may be used to explicitly close that file + descriptor, which will force a reopen in turn. */ +void +agent_reload_trustlist (void) +{ + reload_trustlist_pending = 1; + agent_trustlist_housekeeping (); +} diff --git a/sm/ChangeLog b/sm/ChangeLog index a1997e27e..eed350b24 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -9,6 +9,8 @@ * keylist.c (list_cert_colon): Really print the algorithm and key length. (list_cert_raw, list_cert_std): Ditto. + (list_cert_colon): Reorganized to be able to tell whether a root + certificate is trusted. * gpgsm.c: New option --debug-allow-core-dump. diff --git a/sm/keylist.c b/sm/keylist.c index e9056b6da..27c67ded3 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -289,6 +289,7 @@ static void list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, FILE *fp, int have_secret) { + int rc; int idx; char truststring[2]; char *p; @@ -298,12 +299,39 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, gpg_error_t valerr; int algo; unsigned int nbits; + const char *chain_id; + char *chain_id_buffer = NULL; + int is_root = 0; if (ctrl->with_validation) valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0); else valerr = 0; + + /* We need to get the fingerprint and the chaining ID in advance. */ + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + { + ksba_cert_t next; + + rc = gpgsm_walk_cert_chain (cert, &next); + if (!rc) /* We known the issuer's certificate. */ + { + p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); + chain_id_buffer = p; + chain_id = chain_id_buffer; + ksba_cert_release (next); + } + else if (rc == -1) /* We have reached the root certificate. */ + { + chain_id = fpr; + is_root = 1; + } + else + chain_id = NULL; + } + + fputs (have_secret? "crs:":"crt:", fp); truststring[0] = 0; truststring[1] = 0; @@ -327,11 +355,23 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, && *not_after && strcmp (current_time, not_after) > 0 ) *truststring = 'e'; } + + /* Is we have no truststring yet (i.e. the certificate might be + good) and this is a root certificate, we ask the agent whether + this is a trusted root certificate. */ + if (!*truststring && is_root) + { + rc = gpgsm_agent_istrusted (ctrl, cert); + if (!rc) + *truststring = 'u'; /* Yes, we trust this one (ultimately). */ + else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) + *truststring = 'n'; /* No, we do not trust this one. */ + /* (in case of an error we can't tell anything.) */ + } if (*truststring) fputs (truststring, fp); - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); algo = gpgsm_get_key_algo_info (cert, &nbits); fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24); @@ -379,27 +419,12 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, /* FPR record */ fprintf (fp, "fpr:::::::::%s:::", fpr); /* Print chaining ID (field 13)*/ - { - ksba_cert_t next; - int rc; - - rc = gpgsm_walk_cert_chain (cert, &next); - if (!rc) /* We known the issuer's certificate. */ - { - p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); - fputs (p, fp); - xfree (p); - ksba_cert_release (next); - } - else if (rc == -1) /* We reached the root certificate. */ - { - fputs (fpr, fp); - } - } + if (chain_id) + fputs (chain_id, fp); putc (':', fp); putc ('\n', fp); - xfree (fpr); fpr = NULL; - + xfree (fpr); fpr = NULL; chain_id = NULL; + xfree (chain_id_buffer); chain_id_buffer = NULL; if (opt.with_key_data) { -- cgit v1.2.3 From fb84c86f64019279800e6d92fe85d74b1fd4cf37 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 21 May 2004 13:46:13 +0000 Subject: 2004-05-21 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_component_change_options): Move the per-process backup file into a standard location. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index fa41aff0a..61fc7e625 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-05-21 Marcus Brinkmann <marcus@g10code.de> + + * gpgconf-comp.c (gc_component_change_options): Move the + per-process backup file into a standard location. + 2004-05-03 Werner Koch <wk@gnupg.org> * gpgconf-comp.c: Add --allow-mark-trusted for the gpg-agent. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 735e87c86..c7bfb0d53 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -2431,6 +2431,18 @@ gc_component_change_options (int component, FILE *in) (*gc_backend[backend].runtime_change) (); } + /* Move the per-process backup file into its place. */ + for (backend = 0; backend < GC_BACKEND_NR; backend++) + if (orig_pathname[backend]) + { + char *backup_pathname; + + assert (dest_pathname[backend]); + + backup_pathname = xasprintf ("%s.gpgconf.bak", dest_pathname[backend]); + rename (orig_pathname[backend], backup_pathname); + } + if (line) free (line); } -- cgit v1.2.3 From d3c05ee44c2d57aaba501e85a61ef8d3e0b900e0 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 21 May 2004 13:55:43 +0000 Subject: 2004-05-21 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its only option "max-replies" into LDAP group. (gc_component): Change description of dirmngr to "Directory Manager". --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 6 +----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 61fc7e625..d8e293bc5 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,10 @@ 2004-05-21 Marcus Brinkmann <marcus@g10code.de> + * gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its + only option "max-replies" into LDAP group. + (gc_component): Change description of dirmngr to "Directory + Manager". + * gpgconf-comp.c (gc_component_change_options): Move the per-process backup file into a standard location. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index c7bfb0d53..f51be1762 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -749,10 +749,6 @@ static gc_option_t gc_options_dirmngr[] = { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, NULL, "LDAP server list", GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST }, - - { "CRL", - GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Configuration of the CRL" }, { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "|N|do not return more than N items in one query", GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR }, @@ -823,7 +819,7 @@ static struct { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent }, { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon }, { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm }, - { "dirmngr", NULL, "CRL Manager", gc_options_dirmngr } + { "dirmngr", NULL, "Directory Manager", gc_options_dirmngr } }; -- cgit v1.2.3 From 438ece068bdedcdd20e5bfb4bddfa94e216735d2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 6 Jun 2004 12:59:02 +0000 Subject: * util.h (xtrycalloc_secure,xtrymalloc_secure): New. --- common/ChangeLog | 4 ++++ common/util.h | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index a39f17aaa..2e523618b 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/util.h b/common/util.h index ca7266627..461e744ad 100644 --- a/common/util.h +++ b/common/util.h @@ -37,9 +37,11 @@ #include "../jnlib/dotlock.h" #include "../jnlib/utf8conv.h" -/* handy malloc macros - use only them */ +/* 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)) -- cgit v1.2.3 From f289f433b6d7f0b5ac76e03853ce628f23e3cdc2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 6 Jun 2004 13:00:59 +0000 Subject: * configure.ac: Require libksba 0.9.7. * certreqgen.c (get_parameter_uint, create_request): Create an extension for key usage when requested. * gpgsm.c (main): Install emergency_cleanup also as an atexit handler. * verify.c (gpgsm_verify): Removed the separate error code handling for KSBA. We use shared error codes anyway. * export.c (export_p12): Removed debugging code. * encrypt.c (gpgsm_encrypt): Put the session key in to secure memory. --- ChangeLog | 4 +++ NEWS | 2 ++ TODO | 3 --- configure.ac | 2 +- sm/ChangeLog | 17 ++++++++++++ sm/certreqgen.c | 40 ++++++++++++++++++++++++++-- sm/decrypt.c | 8 +++--- sm/encrypt.c | 4 +-- sm/export.c | 2 +- sm/gpgsm.c | 16 ++++++++---- sm/keydb.c | 4 +-- sm/sign.c | 4 +-- sm/verify.c | 81 ++++++++++++++++++++++++--------------------------------- 13 files changed, 118 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index ef33021cf..3a0512249 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/NEWS b/NEWS index e24af0476..24523229d 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ Noteworthy changes in version 1.9.9 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) ------------------------------------------------ diff --git a/TODO b/TODO index 0ac96b85c..f22a19b41 100644 --- a/TODO +++ b/TODO @@ -24,9 +24,6 @@ might want to have an agent context for each service request * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution -* sm/sign.c -** Don't hardcode the use of RSA. - * sm/gpgsm.c ** Support --output for all commands ** mark all unimplemented commands and options. diff --git a/configure.ac b/configure.ac index 687805759..4c719fe75 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ NEED_LIBGCRYPT_VERSION=1.1.94 NEED_LIBASSUAN_VERSION=0.6.6 -NEED_KSBA_VERSION=0.9.4 +NEED_KSBA_VERSION=0.9.7 NEED_OPENSC_VERSION=0.8.0 diff --git a/sm/ChangeLog b/sm/ChangeLog index eed350b24..c1a8f6411 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,20 @@ +2004-06-06 Werner Koch <wk@gnupg.org> + + * certreqgen.c (get_parameter_uint, create_request): Create + an extension for key usage when requested. + +2004-05-12 Werner Koch <wk@gnupg.org> + + * gpgsm.c (main): Install emergency_cleanup also as an atexit + handler. + + * verify.c (gpgsm_verify): Removed the separate error code + handling for KSBA. We use shared error codes anyway. + + * export.c (export_p12): Removed debugging code. + + * encrypt.c (gpgsm_encrypt): Put the session key in to secure memory. + 2004-05-11 Werner Koch <wk@gnupg.org> * sign.c (gpgsm_sign): Include the error source in the final error diff --git a/sm/certreqgen.c b/sm/certreqgen.c index b1adf2974..969ed14b0 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -129,6 +129,9 @@ struct reqgen_ctrl_s { }; +static const char oidstr_keyUsage[] = "2.5.29.15"; + + static int proc_parameters (ctrl_t ctrl, struct para_data_s *para, struct reqgen_ctrl_s *outctrl); @@ -179,10 +182,10 @@ get_parameter_algo (struct para_data_s *para, enum para_name key) return gcry_pk_map_name (r->u.value); } -/* parse the usage parameter. Returns 0 on success. Note that we +/* Parse the usage parameter. Returns 0 on success. Note that we only care about sign and encrypt and don't (yet) allow all the other X.509 usage to be specified; instead we will use a fixed - mapping to the X.509 usage flags */ + mapping to the X.509 usage flags. */ static int parse_parameter_usage (struct para_data_s *para, enum para_name key) { @@ -222,6 +225,9 @@ get_parameter_uint (struct para_data_s *para, enum para_name key) if (!r) return 0; + if (r->key == pKEYUSAGE) + return r->u.usage; + return (unsigned int)strtoul (r->u.value, NULL, 10); } @@ -516,6 +522,7 @@ create_request (ctrl_t ctrl, ksba_stop_reason_t stopreason; int rc = 0; const char *s; + unsigned int use; err = ksba_certreq_new (&cr); if (err) @@ -576,6 +583,35 @@ create_request (ctrl_t ctrl, rc = err; goto leave; } + + + use = get_parameter_uint (para, pKEYUSAGE); + if (use == GCRY_PK_USAGE_SIGN) + { + /* For signing only we encode the bits: + KSBA_KEYUSAGE_DIGITAL_SIGNATURE + KSBA_KEYUSAGE_NON_REPUDIATION */ + err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1, + "\x03\x02\x06\xC0", 4); + } + else if (use == GCRY_PK_USAGE_ENCR) + { + /* For encrypt only we encode the bits: + KSBA_KEYUSAGE_KEY_ENCIPHERMENT + KSBA_KEYUSAGE_DATA_ENCIPHERMENT */ + err = ksba_certreq_add_extension (cr, oidstr_keyUsage, 1, + "\x03\x02\x04\x30", 4); + } + else + err = 0; /* Both or none given: don't request one. */ + if (err) + { + log_error ("error setting the key usage: %s\n", + gpg_strerror (err)); + rc = err; + goto leave; + } + do { diff --git a/sm/decrypt.c b/sm/decrypt.c index de53af9e7..8ac2e23fe 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -77,7 +77,7 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc, if (seskeylen == 24) { /* Smells like a 3-des key. This might happen because a SC has - already done the unpacking. fixme! */ + already done the unpacking. */ } else { @@ -90,18 +90,18 @@ prepare_decryption (ctrl_t ctrl, const char *hexkeygrip, const char *desc, /* FIXME: Actually the leading zero is required but due to the way we encode the output in libgcrypt as an MPI we are not able to encode that leading zero. However, when using a Smartcard we are - doing it the rightway and therefore we have to skip the zero. This + doing it the right way and therefore we have to skip the zero. This should be fixed in gpg-agent of course. */ if (!seskey[n]) n++; - if (seskey[n] != 2 ) /* wrong block type version */ + if (seskey[n] != 2 ) /* Wrong block type version. */ { rc = gpg_error (GPG_ERR_INV_SESSION_KEY); goto leave; } - for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */ + for (n++; n < seskeylen && seskey[n]; n++) /* Skip the random bytes. */ ; n++; /* and the zero byte */ if (n >= seskeylen ) diff --git a/sm/encrypt.c b/sm/encrypt.c index 8cc9a8828..50da92c32 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -398,8 +398,8 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) goto leave; } - /* create a session key */ - dek = xtrycalloc (1, sizeof *dek); /* hmmm: should we put it into secmem?*/ + /* Create a session key */ + dek = xtrycalloc_secure (1, sizeof *dek); if (!dek) rc = OUT_OF_CORE (errno); else diff --git a/sm/export.c b/sm/export.c index 2b675bdd7..3f7457502 100644 --- a/sm/export.c +++ b/sm/export.c @@ -669,7 +669,7 @@ export_p12 (const unsigned char *certimg, size_t certimglen, protect tool to figure out better error codes for CHILD_ERR. */ buffer[pos++] = c; - if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n') + if (pos >= sizeof buffer - 5 || c == '\n') { buffer[pos - (c == '\n')] = 0; if (cont_line) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index e1751a7aa..bf053b7a5 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1197,11 +1197,17 @@ main ( int argc, char **argv) set_debug (debug_level); - /* FIXME: should set filenames of libgcrypt explicitly - * gpg_opt_homedir = opt.homedir; */ + /* Although we alwasy use gpgsm_exit, we better install a regualr + exit handler so that at least the secure memory gets wiped + out. */ + if (atexit (emergency_cleanup)) + { + log_error ("atexit failed\n"); + gpgsm_exit (2); + } - /* must do this after dropping setuid, because the mapping functions - may try to load an module and we may have disabled an algorithm */ + /* Must do this after dropping setuid, because the mapping functions + may try to load an module and we may have disabled an algorithm. */ if ( !gcry_cipher_map_name (opt.def_cipher_algoid) || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid)) log_error (_("selected cipher algorithm is invalid\n")); @@ -1218,7 +1224,7 @@ main ( int argc, char **argv) if (log_get_errorcount(0)) gpgsm_exit(2); - /* set the random seed file */ + /* Set the random seed file. */ if (use_random_seed) { char *p = make_filename (opt.homedir, "random_seed", NULL); gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); diff --git a/sm/keydb.c b/sm/keydb.c index 8832643b9..6c5c77364 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -412,7 +412,7 @@ lock_all (KEYDB_HANDLE hd) int i, rc = 0; /* Fixme: This locking scheme may lead to deadlock if the resources - are not added in the same order all processes. We are + are not added in the same order by all processes. We are currently only allowing one resource so it is not a problem. */ for (i=0; i < hd->used; i++) { @@ -1051,7 +1051,7 @@ classify_user_id (const char *name, * we set it to the correct value right at the end of this function */ memset (desc, 0, sizeof *desc); *force_exact = 0; - /* skip leading spaces. Fixme: what about trailing white space? */ + /* Skip leading spaces. Fixme: what about trailing white space? */ for(s = name; *s && spacep (s); s++ ) ; diff --git a/sm/sign.c b/sm/sign.c index 3340f1066..5deef6088 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -456,8 +456,8 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, unsigned char *digest; size_t digest_len; /* Fixme do this for all signers and get the algo to use from - the signer's certificate - does not make mich sense, bu we - should do this consistent as we have already done it above */ + the signer's certificate - does not make mich sense, but we + should do this consistent as we have already done it above. */ algo = GCRY_MD_SHA1; hash_data (data_fd, data_md); digest = gcry_md_read (data_md, algo); diff --git a/sm/verify.c b/sm/verify.c index 4b43ed064..410e86de7 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -86,7 +86,6 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) int i, rc; Base64Context b64reader = NULL; Base64Context b64writer = NULL; - gpg_error_t err; ksba_reader_t reader; ksba_writer_t writer = NULL; ksba_cms_t cms = NULL; @@ -135,19 +134,15 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) } } - err = ksba_cms_new (&cms); - if (err) - { - rc = gpg_error (GPG_ERR_ENOMEM); - goto leave; - } + rc = ksba_cms_new (&cms); + if (rc) + goto leave; - err = ksba_cms_set_reader_writer (cms, reader, writer); - if (err) + rc = ksba_cms_set_reader_writer (cms, reader, writer); + if (rc) { log_error ("ksba_cms_set_reader_writer failed: %s\n", - gpg_strerror (err)); - rc = err; + gpg_strerror (rc)); goto leave; } @@ -163,11 +158,10 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) is_detached = 0; do { - err = ksba_cms_parse (cms, &stopreason); - if (err) + rc = ksba_cms_parse (cms, &stopreason); + if (rc) { - log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (err)); - rc = err; + log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } @@ -238,7 +232,6 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) } cert = NULL; - err = 0; for (signer=0; ; signer++) { char *issuer = NULL; @@ -249,18 +242,18 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) size_t msgdigestlen; char *ctattr; - err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); - if (!signer && gpg_err_code (err) == GPG_ERR_NO_DATA + rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); + if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA && data_fd == -1 && is_detached) { log_info ("certs-only message accepted\n"); - err = 0; + rc = 0; break; } - if (err) + if (rc) { - if (signer && err == -1) - err = 0; + if (signer && rc == -1) + rc = 0; break; } @@ -275,19 +268,18 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) log_printf ("\n"); } - err = ksba_cms_get_signing_time (cms, signer, sigtime); - if (gpg_err_code (err) == GPG_ERR_NO_DATA) + rc = ksba_cms_get_signing_time (cms, signer, sigtime); + if (gpg_err_code (rc) == GPG_ERR_NO_DATA) *sigtime = 0; - else if (err) + else if (rc) { - log_error ("error getting signing time: %s\n", gpg_strerror (err)); - *sigtime = 0; /* FIXME: we can't encode an error in the time - string. */ + log_error ("error getting signing time: %s\n", gpg_strerror (rc)); + *sigtime = 0; /* (we can't encode an error in the time string.) */ } - err = ksba_cms_get_message_digest (cms, signer, - &msgdigest, &msgdigestlen); - if (!err) + rc = ksba_cms_get_message_digest (cms, signer, + &msgdigest, &msgdigestlen); + if (!rc) { size_t is_enabled; @@ -304,24 +296,26 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) goto next_signer; } } - else if (gpg_err_code (err) == GPG_ERR_NO_DATA) + else if (gpg_err_code (rc) == GPG_ERR_NO_DATA) { assert (!msgdigest); - err = 0; + rc = 0; algoid = NULL; algo = 0; } else /* real error */ break; - err = ksba_cms_get_sigattr_oids (cms, signer, - "1.2.840.113549.1.9.3",&ctattr); - if (!err) + rc = ksba_cms_get_sigattr_oids (cms, signer, + "1.2.840.113549.1.9.3", &ctattr); + if (!rc) { const char *s; if (DBG_X509) - log_debug ("signer %d - content-type attribute: %s", signer, ctattr); + log_debug ("signer %d - content-type attribute: %s", + signer, ctattr); + s = ksba_cms_get_content_oid (cms, 1); if (!s || strcmp (ctattr, s)) { @@ -334,13 +328,13 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) ksba_free (ctattr); ctattr = NULL; } - else if (err != -1) + else if (rc != -1) { log_error ("error getting content-type attribute: %s\n", - gpg_strerror (err)); + gpg_strerror (rc)); goto next_signer; } - err = 0; + rc = 0; sigval = ksba_cms_get_sig_val (cms, signer); @@ -523,13 +517,6 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) cert = NULL; } rc = 0; - if (err) - { /* FIXME: still needed? */ - log_error ("ksba error: %s\n", gpg_strerror (err)); - rc = err; - } - - leave: ksba_cms_release (cms); -- cgit v1.2.3 From 89da78cdf3ae31aba578f07650cdc0265b79c9b2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 8 Jun 2004 19:10:32 +0000 Subject: about to release 1.9.9 --- ChangeLog | 4 ++++ NEWS | 2 +- agent/ChangeLog | 2 +- configure.ac | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3a0512249..f71334c9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/NEWS b/NEWS index 24523229d..bc8eaac6c 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.9 +Noteworthy changes in version 1.9.9 (2004-06-08) ------------------------------------------------ * [gpg-agent] The new option --allow-mark-trusted is now required to diff --git a/agent/ChangeLog b/agent/ChangeLog index ae1dd884e..07ef30af7 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -37,7 +37,7 @@ 2004-04-16 Werner Koch <wk@gnupg.org> - * gpg-agent.c (main): Tell the logging code taht we are runnign + * gpg-agent.c (main): Tell the logging code that we are running detached. 2004-04-06 Werner Koch <wk@gnupg.org> diff --git a/configure.ac b/configure.ac index 4c719fe75..3a31433a5 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.9-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.9, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 5836ea925a7cc45e5a3dacd6624577b3ebc532e9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 8 Jun 2004 19:25:06 +0000 Subject: post release version bump --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index bc8eaac6c..3d9b4ca34 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.10 +------------------------------------------------ + + Noteworthy changes in version 1.9.9 (2004-06-08) ------------------------------------------------ diff --git a/configure.ac b/configure.ac index 3a31433a5..4e611651e 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.9, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.10-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From feb40e2c6ec1eb008960fbcbbb683c96110bf8aa Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 14 Jun 2004 08:32:07 +0000 Subject: * xreadline.c: New. Based on the iobuf_read_line function. * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New. * gpgconf-comp.c (retrieve_options_from_program) (retrieve_options_from_file, change_options_file) (change_options_program, gc_component_change_options): Replaced getline by read_line and test for allocation failure. --- common/ChangeLog | 4 ++ common/Makefile.am | 1 + common/util.h | 5 +++ common/xreadline.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/ChangeLog | 9 ++++ tools/gpgconf-comp.c | 62 ++++++++++++--------------- tools/no-libgcrypt.c | 22 ++++++++++ 7 files changed, 183 insertions(+), 36 deletions(-) create mode 100644 common/xreadline.c diff --git a/common/ChangeLog b/common/ChangeLog index 2e523618b..a848b8c78 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/common/Makefile.am b/common/Makefile.am index 4e7fd504c..64b565cd2 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -36,6 +36,7 @@ libcommon_a_SOURCES = \ b64enc.c \ miscellaneous.c \ xasprintf.c \ + xreadline.c \ membuf.c membuf.h \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ diff --git a/common/util.h b/common/util.h index 461e744ad..b9ffe6562 100644 --- a/common/util.h +++ b/common/util.h @@ -99,6 +99,11 @@ 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 diff --git a/common/xreadline.c b/common/xreadline.c new file mode 100644 index 000000000..85f0af02e --- /dev/null +++ b/common/xreadline.c @@ -0,0 +1,116 @@ +/* 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; +} diff --git a/tools/ChangeLog b/tools/ChangeLog index d8e293bc5..a81a2d301 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,12 @@ +2004-06-14 Werner Koch <wk@gnupg.org> + + * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New. + + * gpgconf-comp.c (retrieve_options_from_program) + (retrieve_options_from_file, change_options_file) + (change_options_program, gc_component_change_options): Replaced + getline by read_line and test for allocation failure. + 2004-05-21 Marcus Brinkmann <marcus@g10code.de> * gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index f51be1762..cc0751d0c 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -42,13 +42,6 @@ /* TODO: - Portability - Add gnulib replacements for getline, etc. - -XXX Marcus: Please use the read_line code from dirmngr/src/http.c - it -has been in use for may years and provides the ability to limit the -length of the line and thus thwart DoS (not a issue here but at many -other places). - Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. Don't use popen, as this will not tell us if the program had a @@ -1252,7 +1245,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) if (!config) gc_error (1, errno, "could not gather active options from %s", cmd_line); - while ((length = getline (&line, &line_len, config)) > 0) + while ((length = read_line (config, &line, &line_len, NULL)) > 0) { gc_option_t *option; char *linep; @@ -1319,7 +1312,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) option->default_value = xstrdup (default_value); } } - if (ferror (config)) + if (length < 0 || ferror (config)) gc_error (1, errno, "error reading from %s", cmd_line); if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", cmd_line); @@ -1334,7 +1327,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) config_pathname); else { - while ((length = getline (&line, &line_len, config)) > 0) + while ((length = read_line (config, &line, &line_len, NULL)) > 0) { char *name; char *value; @@ -1415,14 +1408,13 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend) } } - if (ferror (config)) + if (length < 0 || ferror (config)) gc_error (1, errno, "error reading from %s", config_pathname); if (fclose (config) && ferror (config)) gc_error (1, errno, "error closing %s", config_pathname); } - if (line) - free (line); + xfree (line); } @@ -1451,7 +1443,7 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) else { - while ((length = getline (&line, &line_len, list_file)) > 0) + while ((length = read_line (list_file, &line, &line_len, NULL)) > 0) { char *start; char *end; @@ -1484,15 +1476,14 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend) else list = xasprintf ("\"%s", percent_escape (start)); } - if (ferror (list_file)) + if (length < 0 || ferror (list_file)) gc_error (1, errno, "can not read list file %s", list_pathname); } list_option->active = 1; list_option->value = list; - if (line) - free (line); + xfree (line); } @@ -1735,7 +1726,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, if (!dest_file) goto change_file_one_err; - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { int disable = 0; char *start; @@ -1823,7 +1814,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, goto change_file_one_err; } } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_file_one_err; } @@ -1889,17 +1880,18 @@ change_options_file (gc_component_t component, gc_backend_t backend, } if (dest_file) { - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_file_one_err; } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_file_one_err; } - if (line) - free (line); + xfree (line); + line = NULL; + res = fclose (src_file); if (res) { @@ -1920,8 +1912,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, return 0; change_file_one_err: - if (line) - free (line); + xfree (line); res = errno; if (src_file) { @@ -1999,7 +1990,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (!dest_file) goto change_one_err; - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { int disable = 0; char *start; @@ -2054,7 +2045,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, goto change_one_err; } } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_one_err; } @@ -2172,17 +2163,18 @@ change_options_program (gc_component_t component, gc_backend_t backend, } if (dest_file) { - while ((length = getline (&line, &line_len, dest_file)) > 0) + while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0) { fprintf (src_file, "%s", line); if (ferror (src_file)) goto change_one_err; } - if (ferror (dest_file)) + if (length < 0 || ferror (dest_file)) goto change_one_err; } - if (line) - free (line); + xfree (line); + line = NULL; + res = fclose (src_file); if (res) { @@ -2203,8 +2195,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, return 0; change_one_err: - if (line) - free (line); + xfree (line); res = errno; if (src_file) { @@ -2241,7 +2232,7 @@ gc_component_change_options (int component, FILE *in) orig_pathname[backend] = NULL; } - while ((length = getline (&line, &line_len, in)) > 0) + while ((length = read_line (in, &line, &line_len, NULL)) > 0) { char *linep; unsigned long flags = 0; @@ -2439,6 +2430,5 @@ gc_component_change_options (int component, FILE *in) rename (orig_pathname[backend], backup_pathname); } - if (line) - free (line); + xfree (line); } diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c index b5342732d..0fabec90d 100644 --- a/tools/no-libgcrypt.c +++ b/tools/no-libgcrypt.c @@ -38,6 +38,12 @@ out_of_core (void) } +void * +gcry_malloc (size_t n) +{ + return malloc (n); +} + void * gcry_xmalloc (size_t n) { @@ -47,6 +53,13 @@ gcry_xmalloc (size_t n) return p; } + +void * +gcry_realloc (void *a, size_t n) +{ + return realloc (a, n); +} + void * gcry_xrealloc (void *a, size_t n) { @@ -56,6 +69,14 @@ gcry_xrealloc (void *a, size_t n) return p; } + + +void * +gcry_calloc (size_t n, size_t m) +{ + return calloc (n, m); +} + void * gcry_xcalloc (size_t n, size_t m) { @@ -65,6 +86,7 @@ gcry_xcalloc (size_t n, size_t m) return p; } + char * gcry_xstrdup (const char *string) { -- cgit v1.2.3 From a4ef559d6cf734a86231ea3e189f76d961f1c3fb Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 16 Jun 2004 12:38:01 +0000 Subject: (osc_get_status): Fixed type in function name. Noted by Axel Thimm. Yes, I didn't tested it with OpenSC :-(. --- scd/ChangeLog | 5 +++++ scd/apdu.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 14dd9c3ff..e04575c75 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-06-16 Werner Koch <wk@gnupg.org> + + * apdu.c (osc_get_status): Fixed type in function name. Noted by + Axel Thimm. Yes, I didn't tested it with OpenSC :-(. + 2004-04-28 Werner Koch <wk@gnupg.org> * app-openpgp.c (do_setattr): Sync FORCE_CHV1. diff --git a/scd/apdu.c b/scd/apdu.c index 42b337238..9742be760 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1309,7 +1309,7 @@ reset_osc_reader (int slot) static int -ocsc_get_status (int slot, unsigned int *status) +osc_get_status (int slot, unsigned int *status) { return SW_HOST_NOT_SUPPORTED; } -- cgit v1.2.3 From a1dfa88e521d0340c2c4afb8d3da5356daaea856 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 18 Jun 2004 09:53:56 +0000 Subject: * keybox-dump.c (_keybox_dump_file): New arg STATS_ONLY. (update_stats): New. * kbxutil.c (main): New command --stats. --- kbx/ChangeLog | 6 +++ kbx/kbxutil.c | 96 ++++++++++++++++++++++++----------------- kbx/keybox-defs.h | 2 +- kbx/keybox-dump.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 187 insertions(+), 44 deletions(-) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index aa39df815..1c3b9e3a1 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,9 @@ +2004-06-18 Werner Koch <wk@gnupg.org> + + * keybox-dump.c (_keybox_dump_file): New arg STATS_ONLY. + (update_stats): New. + * kbxutil.c (main): New command --stats. + 2004-04-23 Werner Koch <wk@gnupg.org> * keybox-blob.c (_keybox_update_header_blob): New. diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 76678619c..37c19130b 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -47,6 +47,7 @@ enum cmd_and_opt_values { aFindByFpr, aFindByKid, aFindByUid, + aStats, oDebug, oDebugAll, @@ -61,15 +62,16 @@ enum cmd_and_opt_values { static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("@Commands:\n ") }, - { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, - { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, - { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, +/* { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, */ +/* { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, */ +/* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */ + { aStats, "stats", 0, "show key statistics" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, - { oArmor, "armor", 0, N_("create ascii armored output")}, - { oArmor, "armour", 0, "@" }, - { oOutput, "output", 2, N_("use as output file")}, +/* { oArmor, "armor", 0, N_("create ascii armored output")}, */ +/* { oArmor, "armour", 0, "@" }, */ +/* { oOutput, "output", 2, N_("use as output file")}, */ { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, @@ -261,6 +263,7 @@ main( int argc, char **argv ) case aFindByFpr: case aFindByKid: case aFindByUid: + case aStats: cmd = pargs.r_opt; break; @@ -275,50 +278,65 @@ main( int argc, char **argv ) if (!cmd) { /* default is to list a KBX file */ if (!argc) - _keybox_dump_file (NULL, stdout); + _keybox_dump_file (NULL, 0, stdout); else { for (; argc; argc--, argv++) - _keybox_dump_file (*argv, stdout); + _keybox_dump_file (*argv, 0, stdout); + } + } + else if (cmd == aStats ) + { + if (!argc) + _keybox_dump_file (NULL, 1, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_file (*argv, 1, stdout); } } #if 0 - else if ( cmd == aFindByFpr ) { - char *fpr; - if ( argc != 2 ) - wrong_args ("kbxfile foingerprint"); - fpr = format_fingerprint ( argv[1] ); - if ( !fpr ) - log_error ("invalid formatted fingerprint\n"); - else { - kbxfile_search_by_fpr ( argv[0], fpr ); - gcry_free ( fpr ); - } + else if ( cmd == aFindByFpr ) + { + char *fpr; + if ( argc != 2 ) + wrong_args ("kbxfile foingerprint"); + fpr = format_fingerprint ( argv[1] ); + if ( !fpr ) + log_error ("invalid formatted fingerprint\n"); + else + { + kbxfile_search_by_fpr ( argv[0], fpr ); + gcry_free ( fpr ); + } } - else if ( cmd == aFindByKid ) { - u32 kid[2]; - int mode; - - if ( argc != 2 ) - wrong_args ("kbxfile short-or-long-keyid"); - mode = format_keyid ( argv[1], kid ); - if ( !mode ) - log_error ("invalid formatted keyID\n"); - else { - kbxfile_search_by_kid ( argv[0], kid, mode ); + else if ( cmd == aFindByKid ) + { + u32 kid[2]; + int mode; + + if ( argc != 2 ) + wrong_args ("kbxfile short-or-long-keyid"); + mode = format_keyid ( argv[1], kid ); + if ( !mode ) + log_error ("invalid formatted keyID\n"); + else + { + kbxfile_search_by_kid ( argv[0], kid, mode ); } } - else if ( cmd == aFindByUid ) { - if ( argc != 2 ) - wrong_args ("kbxfile userID"); - kbxfile_search_by_uid ( argv[0], argv[1] ); + else if ( cmd == aFindByUid ) + { + if ( argc != 2 ) + wrong_args ("kbxfile userID"); + kbxfile_search_by_uid ( argv[0], argv[1] ); } #endif - else - log_error ("unsupported action\n"); - - myexit(0); - return 8; /*NEVER REACHED*/ + else + log_error ("unsupported action\n"); + + myexit(0); + return 8; /*NEVER REACHED*/ } diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 705762c41..759289a0e 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -122,7 +122,7 @@ gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer, /*-- keybox-dump.c --*/ int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); -int _keybox_dump_file (const char *filename, FILE *outfp); +int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp); /*-- keybox-util.c --*/ diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index 2fb0984c0..495fb249e 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -323,14 +323,95 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) } +struct file_stats_s +{ + unsigned long too_short_blobs; + unsigned long too_large_blobs; + unsigned long total_blob_count; + unsigned long empty_blob_count; + unsigned long header_blob_count; + unsigned long pgp_blob_count; + unsigned long x509_blob_count; + unsigned long unknown_blob_count; + unsigned long non_flagged; + unsigned long secret_flagged; + unsigned long ephemeral_flagged; +}; + +static int +update_stats (KEYBOXBLOB blob, struct file_stats_s *s) +{ + const unsigned char *buffer; + size_t length; + int type; + unsigned long n; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 32) + { + s->too_short_blobs++; + return -1; + } + + n = get32( buffer ); + if (n > length) + s->too_large_blobs++; + else + length = n; /* ignore the rest */ + + s->total_blob_count++; + type = buffer[4]; + switch (type) + { + case BLOBTYPE_EMPTY: + s->empty_blob_count++; + return 0; + case BLOBTYPE_HEADER: + s->header_blob_count++; + return 0; + case BLOBTYPE_PGP: + s->pgp_blob_count++; + break; + case BLOBTYPE_X509: + s->x509_blob_count++; + break; + default: + s->unknown_blob_count++; + return 0; + } + + if (length < 40) + { + s->too_short_blobs++; + return -1; + } + + n = get16 (buffer + 6); + if (n) + { + if ((n & 1)) + s->secret_flagged++; + if ((n & 2)) + s->ephemeral_flagged++; + } + else + s->non_flagged++; + + return 0; +} + + int -_keybox_dump_file (const char *filename, FILE *outfp) +_keybox_dump_file (const char *filename, int stats_only, FILE *outfp) { FILE *fp; KEYBOXBLOB blob; int rc; unsigned long count = 0; + struct file_stats_s stats; + + memset (&stats, 0, sizeof stats); if (!filename) { @@ -348,10 +429,17 @@ _keybox_dump_file (const char *filename, FILE *outfp) while ( !(rc = _keybox_read_blob (&blob, fp)) ) { - fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); - _keybox_dump_blob (blob, outfp); + if (stats_only) + { + update_stats (blob, &stats); + } + else + { + fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); + _keybox_dump_blob (blob, outfp); + fprintf (outfp, "END-RECORD\n"); + } _keybox_release_blob (blob); - fprintf (outfp, "END-RECORD\n"); count++; } if (rc == -1) @@ -361,5 +449,36 @@ _keybox_dump_file (const char *filename, FILE *outfp) if (fp != stdin) fclose (fp); + + if (stats_only) + { + fprintf (outfp, + "Total number of blobs: %8lu\n" + " header: %8lu\n" + " empty: %8lu\n" + " openpgp: %8lu\n" + " x509: %8lu\n" + " non flagged: %8lu\n" + " secret flagged: %8lu\n" + " ephemeral flagged: %8lu\n", + stats.total_blob_count, + stats.header_blob_count, + stats.empty_blob_count, + stats.pgp_blob_count, + stats.x509_blob_count, + stats.non_flagged, + stats.secret_flagged, + stats.ephemeral_flagged); + if (stats.unknown_blob_count) + fprintf (outfp, " unknown blob types: %8lu\n", + stats.unknown_blob_count); + if (stats.too_short_blobs) + fprintf (outfp, " too short blobs: %8lu\n", + stats.too_short_blobs); + if (stats.too_large_blobs) + fprintf (outfp, " too large blobs: %8lu\n", + stats.too_large_blobs); + } + return rc; } -- cgit v1.2.3 From 8b810c8dc32bbb005b706bcf200eab4c086e32ff Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 18 Jun 2004 11:18:27 +0000 Subject: * debugging.texi: New. * gnupg.texi: Include it. --- doc/ChangeLog | 5 +++++ doc/Makefile.am | 2 +- doc/gnupg.texi | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 1676834f8..bcc288125 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/doc/Makefile.am b/doc/Makefile.am index 78ae80a2e..d1d72e834 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -22,7 +22,7 @@ info_TEXINFOS = gnupg.texi gnupg_TEXINFOS = \ gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi\ - contrib.texi gpl.texi fdl.texi + debugging.texi contrib.texi gpl.texi fdl.texi DISTCLEANFILES = gnupg.tmp gnupg.ops diff --git a/doc/gnupg.texi b/doc/gnupg.texi index d85b81ff9..58c995b38 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -126,6 +126,7 @@ Developer information 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. @@ -143,6 +144,8 @@ Indices @include assuan.texi +@include debugging.texi + @include gpl.texi @include fdl.texi -- cgit v1.2.3 From 17b9d06d7ce742210e206684e06fdd93de5035c0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 18 Jun 2004 12:29:30 +0000 Subject: * debugging.texi: New. * gnupg.texi: Include it. --- doc/debugging.texi | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 doc/debugging.texi diff --git a/doc/debugging.texi b/doc/debugging.texi new file mode 100644 index 000000000..e5e3e43fd --- /dev/null +++ b/doc/debugging.texi @@ -0,0 +1,82 @@ +@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}. + + + + + -- cgit v1.2.3 From 4b3427c6cecf4a7b657fea0e0cddb36eb3eece84 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sun, 20 Jun 2004 11:35:13 +0000 Subject: 2004-06-20 Moritz Schulte <moritz@g10code.com> * gpg-agent.c: Include <sys/stat.h> (build fix for BSD). --- agent/ChangeLog | 4 ++++ agent/gpg-agent.c | 1 + 2 files changed, 5 insertions(+) diff --git a/agent/ChangeLog b/agent/ChangeLog index 07ef30af7..929959d85 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-06-20 Moritz Schulte <moritz@g10code.com> + + * gpg-agent.c: Include <sys/stat.h> (build fix for BSD). + 2004-05-11 Werner Koch <wk@gnupg.org> * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 8d21dc43c..69a28e78b 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -30,6 +30,7 @@ #include <time.h> #include <fcntl.h> #include <sys/socket.h> +#include <sys/stat.h> #include <sys/un.h> #include <unistd.h> #include <signal.h> -- cgit v1.2.3 From 8b3cf19e24f19f544558f4b9374af1cda339e308 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 21 Jun 2004 06:53:30 +0000 Subject: * sc-investigate.c (my_read_line): Renamed from read_line. --- scd/ChangeLog | 4 ++++ scd/sc-investigate.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index e04575c75..b06c692f5 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-06-18 Werner Koch <wk@g10code.com> + + * sc-investigate.c (my_read_line): Renamed from read_line. + 2004-06-16 Werner Koch <wk@gnupg.org> * apdu.c (osc_get_status): Fixed type in function name. Noted by diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index 3882e1dfd..229def535 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -362,7 +362,7 @@ pin_to_buffer (const char *string, size_t *r_length) static char * -read_line (int use_readline, char *prompt) +my_read_line (int use_readline, char *prompt) { static char buf[256]; @@ -470,7 +470,7 @@ interactive_shell (int slot) printf ("\n"); do { - line = read_line (use_readline, "cmd> "); + line = my_read_line (use_readline, "cmd> "); } while ( line && *line == '#' ); -- cgit v1.2.3 From 3571968f04ac5bbbbc2702478d1478330d2e2973 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 21 Jun 2004 09:50:22 +0000 Subject: (log_set_file): Do not close an old logstream if it used to be stderr or stdout. --- jnlib/ChangeLog | 5 +++++ jnlib/logging.c | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index e9f643774..e4df12a7f 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2004-06-21 Werner Koch <wk@g10code.com> + + * logging.c (log_set_file): Do not close an old logstream if it + used to be stderr or stdout. + 2004-05-05 Werner Koch <wk@gnupg.org> * logging.c (log_set_file): Oops, don't close if LOGSTREAM is NULL. diff --git a/jnlib/logging.c b/jnlib/logging.c index c75efaf85..f91339687 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -129,15 +129,15 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) struct fun_cookie_s *cookie = cookie_arg; /* Note that we always try to reconnect to the socket but print - error messages only the first time an error occured. IF + error messages only the first time an error occured. If RUNNING_DETACHED is set we don't fall back to stderr and even do - not print any error messages. This is needed becuase detached - processes often close stderr and my printing to fiel descriptor 2 + not print any error messages. This is needed because detached + processes often close stderr and by writing to file descriptor 2 we might send the log message to a file not intended for logging (e.g. a pipe or network connection). */ if (cookie->fd == -1) { - /* Note yet open or meanwhile closed due to an error. */ + /* Not yet open or meanwhile closed due to an error. */ struct sockaddr_un addr; size_t addrlen; @@ -256,13 +256,14 @@ log_set_file (const char *name) #endif /* Neither fopencookie nor funopen. */ /* We always need to print the prefix and the pid, so that the - server reading the socket can do something meanigful. */ + server reading the socket can do something meaningful. */ force_prefixes = 1; /* On success close the old logstream right now, so that we are really sure it has been closed. */ if (fp && logstream) { - fclose (logstream); + if (logstream != stderr && logstream != stdout) + fclose (logstream); logstream = NULL; } } -- cgit v1.2.3 From 6e4f619b3c23a4bc206314a7239eba773a8ff91e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 28 Jun 2004 07:42:33 +0000 Subject: Added some doc stuff --- TODO | 8 ++++++++ doc/ChangeLog | 4 ++++ doc/Makefile.am | 2 +- doc/debugging.texi | 15 ++++++++++++++- doc/gnupg.texi | 3 +++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index f22a19b41..cb58f907b 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,13 @@ -*- outline -*- +* Keylisting +Add the keygrip to the dump output +Explain how to setup a root CA key as trusted +Look for new system-wide certificates +Explain how trustlist.txt might be managed. + + + * src/base64 ** Make parsing more robust Currently we don't cope with overlong lines in the best way. diff --git a/doc/ChangeLog b/doc/ChangeLog index bcc288125..1760695be 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2004-06-22 Werner Koch <wk@g10code.com> + + * glossary.texi: New. + 2004-06-18 Werner Koch <wk@gnupg.org> * debugging.texi: New. diff --git a/doc/Makefile.am b/doc/Makefile.am index d1d72e834..9dc917de4 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -22,7 +22,7 @@ info_TEXINFOS = gnupg.texi gnupg_TEXINFOS = \ gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi\ - debugging.texi contrib.texi gpl.texi fdl.texi + debugging.texi glossary.texi contrib.texi gpl.texi fdl.texi DISTCLEANFILES = gnupg.tmp gnupg.ops diff --git a/doc/debugging.texi b/doc/debugging.texi index e5e3e43fd..9406ba567 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -17,7 +17,7 @@ solve the problem at hand. @menu * Debugging Tools:: Description of some useful tools - +* Common Problems:: Commonly seen problems. @end menu @@ -80,3 +80,16 @@ in a standard way and directly available from @command{gpgsm}. +@node Common Problems +@section Commonly Seen Problems + + +@itemize @bullet +@item Error code @samp{Not supported} from Dirmngr + + Most likely the option @option{enable-ocsp} is active for gpgsm + but Dirmngr's OCSP feature has not been enabled using + @option{allow-ocsp} in @file{dirmngr.conf}. + +@end itemize + diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 58c995b38..0beb97e69 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -134,6 +134,7 @@ Miscellaneous Indices +* Glossary:: Short descrition of used terms. * Option Index:: Index to command line options. * Index:: Index of concepts and symbol names. @end menu @@ -155,6 +156,8 @@ Indices @c Indexes @c --------------------------------------------------------------------- +@include glossary.texi + @node Option Index @unnumbered Option Index -- cgit v1.2.3 From 7158c4db92f42799ae5df993431f0ebcdd80fe6c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 29 Jun 2004 07:16:40 +0000 Subject: Added glossary --- doc/glossary.texi | 24 ++++++++++++++++++++++++ doc/gpgsm.texi | 9 ++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 doc/glossary.texi diff --git a/doc/glossary.texi b/doc/glossary.texi new file mode 100644 index 000000000..7c1b7d5a0 --- /dev/null +++ b/doc/glossary.texi @@ -0,0 +1,24 @@ +@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 Glossary +@unnumbered Glossary + + +@table @samp +@item ARL + The @emph{Authority Revocation List} is technical identical to a +@acronym{CRL} but used for @acronym{CA}s and not for end user +certificates. + +@item CRL + The @emph{Certificate Revocation List} is a list containing +certificates revoked by the issuer. + +@item OCSP + The @emph{Online Certificate Status Protocol} is used as an +alternative to a @acronym{CRL}. It is described in @code{RFC 2560}. + + +@end table diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 4bb688c44..384a36593 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -296,7 +296,7 @@ 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 +along with the option @option{--with-validation} for a ke listing command. This option should not be used in a configuration file. @item --enable-ocsp @@ -305,8 +305,11 @@ command. This option should not be used in a configuration file. @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. +are also enabled, CRLs will be used as a fallback if for some reason an +OCSP request won't succeed. Note, that you have to allow OCSP +requests in Dirmngr's configuration too (option +@option{--allow-ocsp} and configure dirmngr properly. If you don't do +so you will get the error code @samp{Not supported}. @end table -- cgit v1.2.3 From bcaa520ad6fec10966d2b82e3c52756d69d8764e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 1 Jul 2004 17:41:33 +0000 Subject: (do_getattr): Fix for sending CA-FPR. --- scd/ChangeLog | 9 +++++++++ scd/app-openpgp.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index b06c692f5..1dfafbd5a 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2004-07-01 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (do_getattr): Fix for sending CA-FPR. + +2004-06-30 Werner Koch <wk@gnupg.org> + + * app-openpgp.c (app_openpgp_readkey): Fixed check for valid + exponent. + 2004-06-18 Werner Koch <wk@g10code.com> * sc-investigate.c (my_read_line): Renamed from read_line. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index f40951941..3dc015baa 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -561,7 +561,7 @@ do_getattr (APP app, CTRL ctrl, const char *name) { if (valuelen >= 60) for (i=0; i < 3; i++) - send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20); + send_fpr_if_not_null (ctrl, table[idx].name, i+1, value+i*20); } else send_status_info (ctrl, table[idx].name, value, valuelen, NULL, 0); @@ -1619,7 +1619,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, memcpy (*m, a, alen); a = find_tlv (keydata, keydatalen, 0x0082, &alen); - if (!e) + if (!a) { log_error ("response does not contain the RSA public exponent\n"); rc = gpg_error (GPG_ERR_CARD); -- cgit v1.2.3 From 8f81ba17dc1989fb617ef8a0d1319b8b231fab2b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 1 Jul 2004 17:42:09 +0000 Subject: * card-util.c (change_login): Kludge to allow reading data from a file. (card_edit): Pass ARG_STRING to change_login. (card_status): Print CA fingerprints. (change_cafpr): New. (card_edit): New command CAFPR. * call-agent.h: Add members for CA fingerprints. * call-agent.c (agent_release_card_info): Invalid them. (learn_status_cb): Store them. --- g10/ChangeLog | 13 ++++++ g10/call-agent.c | 15 +++++++ g10/call-agent.h | 6 +++ g10/card-util.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 146 insertions(+), 11 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 0e87c2f46..7a8ccd5c0 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,16 @@ +2004-07-01 Werner Koch <wk@gnupg.org> + + * card-util.c (change_login): Kludge to allow reading data from a + file. + (card_edit): Pass ARG_STRING to change_login. + (card_status): Print CA fingerprints. + (change_cafpr): New. + (card_edit): New command CAFPR. + + * call-agent.h: Add members for CA fingerprints. + * call-agent.c (agent_release_card_info): Invalid them. + (learn_status_cb): Store them. + 2004-04-30 Werner Koch <wk@gnupg.org> * g10.c (main) <gpgconf>: Use gpg.conf and not /dev/null as diff --git a/g10/call-agent.c b/g10/call-agent.c index de157d491..f93132fde 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -461,6 +461,7 @@ agent_release_card_info (struct agent_card_info_s *info) 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->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0; info->fpr1valid = info->fpr2valid = info->fpr3valid = 0; } @@ -557,6 +558,20 @@ learn_status_cb (void *opaque, const char *line) else if (no == 3) parm->fpr3valid = unhexify_fpr (line, parm->fpr3); } + else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen)) + { + int no = atoi (line); + while (*line && !spacep (line)) + line++; + while (spacep (line)) + line++; + if (no == 1) + parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1); + else if (no == 2) + parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2); + else if (no == 3) + parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3); + } return 0; } diff --git a/g10/call-agent.h b/g10/call-agent.h index 875110118..3d9f4f9bf 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -29,6 +29,12 @@ struct agent_card_info_s { int disp_sex; /* 0 = unspecified, 1 = male, 2 = female */ char *pubkey_url; /* malloced. */ char *login_data; /* malloced. */ + char cafpr1valid; + char cafpr2valid; + char cafpr3valid; + char cafpr1[20]; + char cafpr2[20]; + char cafpr3[20]; char fpr1valid; char fpr2valid; char fpr3valid; diff --git a/g10/card-util.c b/g10/card-util.c index c93d028bd..2d7f00800 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -336,6 +336,11 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) info.chvretry[0], info.chvretry[1], info.chvretry[2]); fprintf (fp, "sigcount:%lu:::\n", info.sig_counter); + fputs ("cafpr:", fp); + print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL); + print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL); + print_sha1_fpr_colon (fp, info.cafpr3valid? info.cafpr3:NULL); + putc ('\n', fp); fputs ("fpr:", fp); print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL); print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL); @@ -362,6 +367,21 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) info.disp_sex == 2? _("female") : _("unspecified")); print_name (fp, "URL of public key : ", info.pubkey_url); print_name (fp, "Login data .......: ", info.login_data); + if (info.cafpr1valid) + { + tty_fprintf (fp, "CA fingerprint %d .:", 1); + print_sha1_fpr (fp, info.cafpr1); + } + if (info.cafpr2valid) + { + tty_fprintf (fp, "CA fingerprint %d .:", 2); + print_sha1_fpr (fp, info.cafpr2); + } + if (info.cafpr3valid) + { + tty_fprintf (fp, "CA fingerprint %d .:", 3); + print_sha1_fpr (fp, info.cafpr3); + } tty_fprintf (fp, "Signature PIN ....: %s\n", info.chv1_cached? _("not forced"): _("forced")); tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", @@ -491,19 +511,46 @@ change_url (void) } static int -change_login (void) +change_login (const char *args) { char *data; + int n; int rc; - data = cpr_get ("cardedit.change_login", - _("Login data (account name): ")); - if (!data) - return -1; - trim_spaces (data); - cpr_kill_prompt (); + if (args && *args == '<') /* Read it from a file */ + { + FILE *fp; - if (strlen (data) > 254 ) + for (args++; spacep (args); args++) + ; + fp = fopen (args, "rb"); + if (!fp) + { + tty_printf ("can't open `%s': %s\n", args, strerror (errno)); + return -1; + } + data = xmalloc (254); + n = fread (data, 1, 254, fp); + fclose (fp); + if (n < 0) + { + tty_printf ("error reading `%s': %s\n", args, strerror (errno)); + xfree (data); + return -1; + } + } + else + { + data = cpr_get ("cardedit.change_login", + _("Login data (account name): ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + n = strlen (data); + } + + if (n > 254 ) { tty_printf (_("Error: Login data too long " "(limit is %d characters).\n"), 254); @@ -511,7 +558,7 @@ change_login (void) return -1; } - rc = agent_scd_setattr ("LOGIN-DATA", data, strlen (data) ); + rc = agent_scd_setattr ("LOGIN-DATA", data, n ); if (rc) log_error ("error setting login data: %s\n", gpg_strerror (rc)); xfree (data); @@ -590,6 +637,51 @@ change_sex (void) } +static int +change_cafpr (int fprno) +{ + char *data; + const char *s; + int i, c, rc; + unsigned char fpr[20]; + + data = cpr_get ("cardedit.change_cafpr", _("CA fingerprint: ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + for (i=0, s=data; i < 20 && *s; ) + { + while (spacep(s)) + s++; + if (*s == ':') + s++; + while (spacep(s)) + s++; + c = hextobyte (s); + if (c == -1) + break; + fpr[i++] = c; + s += 2; + } + xfree (data); + if (i != 20 || *s) + { + tty_printf (_("Error: invalid formatted fingerprint.\n")); + return -1; + } + + rc = agent_scd_setattr (fprno==1?"CA-FPR-1": + fprno==2?"CA-FPR-2": + fprno==3?"CA-FPR-3":"x", fpr, 20 ); + if (rc) + log_error ("error setting cafpr: %s\n", gpg_strerror (rc)); + return rc; +} + + + static void toggle_forcesig (void) { @@ -700,7 +792,7 @@ card_edit (STRLIST commands) enum cmdids { cmdNOP = 0, cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, - cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, + cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdINVCMD }; @@ -722,6 +814,7 @@ card_edit (STRLIST commands) { 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_("cafpr"), cmdCAFPR, N_("change a CA fingerprint") }, { N_("forcesig"), cmdFORCESIG, N_("toggle the signature force PIN flag") }, { N_("generate"), @@ -840,7 +933,7 @@ card_edit (STRLIST commands) break; case cmdLOGIN: - change_login (); + change_login (arg_string); break; case cmdLANG: @@ -851,6 +944,14 @@ card_edit (STRLIST commands) change_sex (); break; + case cmdCAFPR: + if ( arg_number < 1 || arg_number > 3 ) + tty_printf ("usage: cafpr N\n" + " 1 <= N <= 3\n"); + else + change_cafpr (arg_number); + break; + case cmdFORCESIG: toggle_forcesig (); break; -- cgit v1.2.3 From c4e52b1531816cc9bd39f4a326010eb8ee221f1f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 1 Jul 2004 18:09:25 +0000 Subject: Initialize Pth which is now required. (interactive_shell): New command "readpk". --- scd/ChangeLog | 3 +++ scd/sc-investigate.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 1dfafbd5a..f594fdd7f 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,8 @@ 2004-07-01 Werner Koch <wk@gnupg.org> + * sc-investigate.c: Initialize Pth which is now required. + (interactive_shell): New command "readpk". + * app-openpgp.c (do_getattr): Fix for sending CA-FPR. 2004-06-30 Werner Koch <wk@gnupg.org> diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index 229def535..be985533c 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -26,6 +26,9 @@ #include <errno.h> #include <ctype.h> #include <unistd.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif #ifdef HAVE_READLINE_READLINE_H #include <readline/readline.h> @@ -88,6 +91,12 @@ static ARGPARSE_OPTS opts[] = { }; +#ifdef USE_GNU_PTH +/* Pth wrapper function definitions. */ +GCRY_THREAD_OPTION_PTH_IMPL; +#endif /*USE_GNU_PTH*/ + + static void interactive_shell (int slot); static void dump_other_cards (int slot); @@ -151,7 +160,18 @@ main (int argc, char **argv ) /* Try to auto set the character set. */ set_native_charset (NULL); - /* check that the libraries are suitable. Do it here because + /* Libgcrypt requires us to register the threading model first. + Note that this will also do the pth_init. */ +#ifdef USE_GNU_PTH + rc = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + if (rc) + { + log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", + gpg_strerror (rc)); + } +#endif /*USE_GNU_PTH*/ + + /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) { @@ -411,6 +431,7 @@ interactive_shell (int slot) cmdDEBUG, cmdVERIFY, cmdCHANGEREF, + cmdREADPK, cmdINVCMD }; @@ -439,6 +460,7 @@ interactive_shell (int slot) { "verify" , cmdVERIFY, "verify CHVNO PIN" }, { "ver" , cmdVERIFY, NULL }, { "changeref", cmdCHANGEREF, "change reference data" }, + { "readpk", cmdREADPK, "read a public key" }, { NULL, cmdINVCMD } }; enum cmdids cmd = cmdNOP; @@ -655,6 +677,23 @@ interactive_shell (int slot) } break; + case cmdREADPK: + if (arg_number < 1 || arg_number > 255) + printf ("usage: readpk CRTBYTE1\n"); + else + { + unsigned char crt[2]; + + crt[0] = arg_number; + crt[1] = 0; + err = iso7816_read_public_key(slot, crt, 2, + &result, &resultlen); + if (!err) + dump_or_store_buffer (arg_string, result, resultlen); + } + break; + + case cmdINVCMD: default: printf ("\n"); -- cgit v1.2.3 From 8add759d64b3cca6881a78205dce6a129141d26f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jul 2004 15:45:25 +0000 Subject: (reader_table_s): Add function pointers for the backends. (apdu_close_reader, apdu_get_status, apdu_activate) (send_apdu): Make use of them. (new_reader_slot): Intialize them to NULL. (dump_ccid_reader_status, ct_dump_reader_status): New. (dump_pcsc_reader_status): New. (open_ct_reader, open_pcsc_reader, open_ccid_reader) (open_osc_reader, open_rapdu_reader): Intialize function pointers. (ct_activate_card, ct_send_apdu, pcsc_send_apdu, osc_send_apdu) (error_string): Removed. Replaced by apdu_strerror. (get_ccid_error_string): Removed. (ct_activate_card): Remove the unused loop. (reset_ct_reader): Implemented. (ct_send_apdu): Activate the card if not yet done. (pcsc_send_apdu): Ditto. --- scd/ChangeLog | 43 ++ scd/apdu.c | 1797 +++++++++++++++++++++++++++++++++++------------------ scd/apdu.h | 27 +- scd/ccid-driver.c | 53 +- scd/ccid-driver.h | 16 + scd/iso7816.c | 6 + 6 files changed, 1305 insertions(+), 637 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index f594fdd7f..1d3cff257 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,46 @@ +2004-07-16 Werner Koch <wk@gnupg.org> + + * apdu.c (reader_table_s): Add function pointers for the backends. + (apdu_close_reader, apdu_get_status, apdu_activate) + (send_apdu): Make use of them. + (new_reader_slot): Intialize them to NULL. + (dump_ccid_reader_status, ct_dump_reader_status): New. + (dump_pcsc_reader_status): New. + (open_ct_reader, open_pcsc_reader, open_ccid_reader) + (open_osc_reader, open_rapdu_reader): Intialize function pointers. + (ct_activate_card, ct_send_apdu, pcsc_send_apdu, osc_send_apdu) + (error_string): Removed. Replaced by apdu_strerror. + (get_ccid_error_string): Removed. + (ct_activate_card): Remove the unused loop. + (reset_ct_reader): Implemented. + (ct_send_apdu): Activate the card if not yet done. + (pcsc_send_apdu): Ditto. + +2004-07-15 Werner Koch <wk@gnupg.org> + + * ccid-driver.h: Add error codes. + * ccid-driver.c: Implement more or less proper error codes all + over the place. + + * apdu.c (apdu_send_direct): New. + (get_ccid_error_string): Add some error code mappings. + (send_apdu): Pass error codes along for drivers already supporting + them. + (host_sw_string): New. + (get_ccid_error_string): Use above. + (send_apdu_ccid): Reset the reader if it has not yet been done. + (open_ccid_reader): Don't care if the ATR can't be read. + (apdu_activate_card): New. + (apdu_strerror): New. + (dump_reader_status): Only enable it with opt.VERBOSE. + * iso7816.c (map_sw): Add mappings for the new error codes. + +2004-07-02 Werner Koch <wk@gnupg.org> + + * apdu.c (open_ct_reader, open_pcsc_reader, open_ccid_reader) + (reset_ccid_reader, open_osc_reader): Call dump_reader_status only + in verbose mode. + 2004-07-01 Werner Koch <wk@gnupg.org> * sc-investigate.c: Initialize Pth which is now required. diff --git a/scd/apdu.c b/scd/apdu.c index 9742be760..cc9b213fb 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -33,6 +33,12 @@ # include <opensc/opensc.h> #endif +/* If requested include the definitions for the remote APDU protocol + code. */ +#ifdef USE_G10CODE_RAPDU +#include "rapdu.h" +#endif /*USE_G10CODE_RAPDU*/ + #if defined(GNUPG_SCD_MAIN_HEADER) #include GNUPG_SCD_MAIN_HEADER #elif GNUPG_MAJOR_VERSION == 1 @@ -59,8 +65,6 @@ #define MAX_READER 4 /* Number of readers we support concurrently. */ -#define CARD_CONNECT_TIMEOUT 1 /* Number of seconds to wait for - insertion of the card (1 = don't wait). */ #ifdef _WIN32 @@ -81,11 +85,18 @@ struct reader_table_s { int used; /* True if slot is used. */ unsigned short port; /* Port number: 0 = unused, 1 - dev/tty */ - int is_ccid; /* Uses the internal CCID driver. */ + + /* Function pointers intialized to the various backends. */ + int (*close_reader)(int); + int (*reset_reader)(int); + int (*get_status_reader)(int, unsigned int *); + int (*send_apdu_reader)(int,unsigned char *,size_t, + unsigned char *, size_t *); + void (*dump_status_reader)(int); + struct { ccid_driver_t handle; } ccid; - int is_ctapi; /* This is a ctAPI driver. */ struct { unsigned long context; unsigned long card; @@ -97,15 +108,21 @@ struct reader_table_s { #endif /*NEED_PCSC_WRAPPER*/ } pcsc; #ifdef HAVE_OPENSC - int is_osc; /* We are using the OpenSC driver layer. */ struct { struct sc_context *ctx; struct sc_card *scard; } osc; #endif /*HAVE_OPENSC*/ +#ifdef USE_G10CODE_RAPDU + struct { + rapdu_t handle; + } rapdu; +#endif /*USE_G10CODE_RAPDU*/ int status; unsigned char atr[33]; - size_t atrlen; + size_t atrlen; /* A zero length indicates that the ATR has + not yet been read; i.e. the card is not + ready for use. */ unsigned int change_counter; #ifdef USE_GNU_PTH int lock_initialized; @@ -222,12 +239,13 @@ new_reader_slot (void) reader_table[reader].lock_initialized = 1; } #endif /*USE_GNU_PTH*/ + reader_table[reader].close_reader = NULL; + reader_table[reader].reset_reader = NULL; + reader_table[reader].get_status_reader = NULL; + reader_table[reader].send_apdu_reader = NULL; + reader_table[reader].dump_status_reader = NULL; + reader_table[reader].used = 1; - reader_table[reader].is_ccid = 0; - reader_table[reader].is_ctapi = 0; -#ifdef HAVE_OPENSC - reader_table[reader].is_osc = 0; -#endif #ifdef NEED_PCSC_WRAPPER reader_table[reader].pcsc.req_fd = -1; reader_table[reader].pcsc.rsp_fd = -1; @@ -238,34 +256,72 @@ new_reader_slot (void) static void -dump_reader_status (int reader) +dump_reader_status (int slot) { - if (reader_table[reader].is_ccid) - log_info ("reader slot %d: using ccid driver\n", reader); - else if (reader_table[reader].is_ctapi) + if (!opt.verbose) + return; + + if (reader_table[slot].dump_status_reader) + reader_table[slot].dump_status_reader (slot); + + if (reader_table[slot].status != -1 + && reader_table[slot].atrlen) { - log_info ("reader slot %d: %s\n", reader, - reader_table[reader].status == 1? "Processor ICC present" : - reader_table[reader].status == 0? "Memory ICC present" : - "ICC not present" ); + log_info ("slot %d: ATR=", slot); + log_printhex ("", reader_table[slot].atr, reader_table[slot].atrlen); } - else +} + + + +static const char * +host_sw_string (long err) +{ + switch (err) { - log_info ("reader slot %d: active protocol:", reader); - if ((reader_table[reader].pcsc.protocol & PCSC_PROTOCOL_T0)) - log_printf (" T0"); - else if ((reader_table[reader].pcsc.protocol & PCSC_PROTOCOL_T1)) - log_printf (" T1"); - else if ((reader_table[reader].pcsc.protocol & PCSC_PROTOCOL_RAW)) - log_printf (" raw"); - log_printf ("\n"); + case 0: return "okay"; + case SW_HOST_OUT_OF_CORE: return "out of core"; + case SW_HOST_INV_VALUE: return "invalid value"; + case SW_HOST_NO_DRIVER: return "no driver"; + case SW_HOST_NOT_SUPPORTED: return "not supported"; + case SW_HOST_LOCKING_FAILED: return "locking failed"; + case SW_HOST_BUSY: return "busy"; + case SW_HOST_NO_CARD: return "no card"; + case SW_HOST_CARD_INACTIVE: return "card inactive"; + case SW_HOST_CARD_IO_ERROR: return "card I/O error"; + case SW_HOST_GENERAL_ERROR: return "general error"; + case SW_HOST_NO_READER: return "no reader"; + default: return "unknown host status error"; } +} - if (reader_table[reader].status != -1) + +const char * +apdu_strerror (int rc) +{ + switch (rc) { - log_info ("reader %d: ATR=", reader); - log_printhex ("", reader_table[reader].atr, - reader_table[reader].atrlen); + case SW_EOF_REACHED : return "eof reached"; + case SW_EEPROM_FAILURE : return "eeprom failure"; + case SW_WRONG_LENGTH : return "wrong length"; + case SW_CHV_WRONG : return "CHV wrong"; + case SW_CHV_BLOCKED : return "CHV blocked"; + case SW_USE_CONDITIONS : return "use conditions not satisfied"; + case SW_BAD_PARAMETER : return "bad parameter"; + case SW_NOT_SUPPORTED : return "not supported"; + case SW_FILE_NOT_FOUND : return "file not found"; + case SW_RECORD_NOT_FOUND:return "record not found"; + case SW_REF_NOT_FOUND : return "reference not found"; + case SW_BAD_P0_P1 : return "bad P0 or P1"; + case SW_INS_NOT_SUP : return "instruction not supported"; + case SW_CLA_NOT_SUP : return "class not supported"; + case SW_SUCCESS : return "success"; + default: + if ((rc & ~0x00ff) == SW_MORE_DATA) + return "more data available"; + if ( (rc & 0x10000) ) + return host_sw_string (rc); + return "unknown status error"; } } @@ -290,120 +346,82 @@ ct_error_string (long err) } } -/* Wait for the card in READER and activate it. Return -1 on error or - 0 on success. */ -static int -ct_activate_card (int reader) -{ - int rc, count; - - for (count = 0; count < CARD_CONNECT_TIMEOUT; count++) - { - unsigned char dad[1], sad[1], cmd[11], buf[256]; - unsigned short buflen; - - if (count) - ; /* FIXME: we should use a more reliable timer than sleep. */ - - /* Check whether card has been inserted. */ - dad[0] = 1; /* Destination address: CT. */ - sad[0] = 2; /* Source address: Host. */ - - cmd[0] = 0x20; /* Class byte. */ - cmd[1] = 0x13; /* Request status. */ - cmd[2] = 0x00; /* From kernel. */ - cmd[3] = 0x80; /* Return card's DO. */ - cmd[4] = 0x00; - - buflen = DIM(buf); - - rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf); - if (rc || buflen < 2 || buf[buflen-2] != 0x90) - { - log_error ("ct_activate_card: can't get status of reader %d: %s\n", - reader, ct_error_string (rc)); - return -1; - } - /* Connected, now activate the card. */ - dad[0] = 1; /* Destination address: CT. */ - sad[0] = 2; /* Source address: Host. */ +static void +ct_dump_reader_status (int slot) +{ + log_info ("reader slot %d: %s\n", slot, + reader_table[slot].status == 1? "Processor ICC present" : + reader_table[slot].status == 0? "Memory ICC present" : + "ICC not present" ); +} - cmd[0] = 0x20; /* Class byte. */ - cmd[1] = 0x12; /* Request ICC. */ - cmd[2] = 0x01; /* From first interface. */ - cmd[3] = 0x01; /* Return card's ATR. */ - cmd[4] = 0x00; - buflen = DIM(buf); +/* Wait for the card in SLOT and activate it. Return a status word + error or 0 on success. */ +static int +ct_activate_card (int slot) +{ + int rc; + unsigned char dad[1], sad[1], cmd[11], buf[256]; + unsigned short buflen; + + /* Check whether card has been inserted. */ + dad[0] = 1; /* Destination address: CT. */ + sad[0] = 2; /* Source address: Host. */ - rc = CT_data (reader, dad, sad, 5, cmd, &buflen, buf); - if (rc || buflen < 2 || buf[buflen-2] != 0x90) - { - log_error ("ct_activate_card(%d): activation failed: %s\n", - reader, ct_error_string (rc)); - if (!rc) - log_printhex (" received data:", buf, buflen); - return -1; - } + cmd[0] = 0x20; /* Class byte. */ + cmd[1] = 0x13; /* Request status. */ + cmd[2] = 0x00; /* From kernel. */ + cmd[3] = 0x80; /* Return card's DO. */ + cmd[4] = 0x00; - /* Store the type and the ATR. */ - if (buflen - 2 > DIM (reader_table[0].atr)) - { - log_error ("ct_activate_card(%d): ATR too long\n", reader); - return -1; - } + buflen = DIM(buf); - reader_table[reader].status = buf[buflen - 1]; - memcpy (reader_table[reader].atr, buf, buflen - 2); - reader_table[reader].atrlen = buflen - 2; - return 0; + rc = CT_data (slot, dad, sad, 5, cmd, &buflen, buf); + if (rc || buflen < 2 || buf[buflen-2] != 0x90) + { + log_error ("ct_activate_card: can't get status of reader %d: %s\n", + slot, ct_error_string (rc)); + return SW_HOST_CARD_IO_ERROR; } - - log_info ("ct_activate_card(%d): timeout waiting for card\n", reader); - return -1; -} + /* Connected, now activate the card. */ + dad[0] = 1; /* Destination address: CT. */ + sad[0] = 2; /* Source address: Host. */ -/* Open a reader and return an internal handle for it. PORT is a - non-negative value with the port number of the reader. USB readers - do have port numbers starting at 32769. */ -static int -open_ct_reader (int port) -{ - int rc, reader; + cmd[0] = 0x20; /* Class byte. */ + cmd[1] = 0x12; /* Request ICC. */ + cmd[2] = 0x01; /* From first interface. */ + cmd[3] = 0x01; /* Return card's ATR. */ + cmd[4] = 0x00; - if (port < 0 || port > 0xffff) - { - log_error ("open_ct_reader: invalid port %d requested\n", port); - return -1; - } - reader = new_reader_slot (); - if (reader == -1) - return reader; - reader_table[reader].port = port; + buflen = DIM(buf); - rc = CT_init (reader, (unsigned short)port); - if (rc) + rc = CT_data (slot, dad, sad, 5, cmd, &buflen, buf); + if (rc || buflen < 2 || buf[buflen-2] != 0x90) { - log_error ("apdu_open_ct_reader failed on port %d: %s\n", - port, ct_error_string (rc)); - reader_table[reader].used = 0; - return -1; + log_error ("ct_activate_card(%d): activation failed: %s\n", + slot, ct_error_string (rc)); + if (!rc) + log_printhex (" received data:", buf, buflen); + return SW_HOST_CARD_IO_ERROR; } - rc = ct_activate_card (reader); - if (rc) + /* Store the type and the ATR. */ + if (buflen - 2 > DIM (reader_table[0].atr)) { - reader_table[reader].used = 0; - return -1; + log_error ("ct_activate_card(%d): ATR too long\n", slot); + return SW_HOST_CARD_IO_ERROR; } - reader_table[reader].is_ctapi = 1; - dump_reader_status (reader); - return reader; + reader_table[slot].status = buf[buflen - 1]; + memcpy (reader_table[slot].atr, buf, buflen - 2); + reader_table[slot].atrlen = buflen - 2; + return 0; } + static int close_ct_reader (int slot) { @@ -415,13 +433,17 @@ close_ct_reader (int slot) static int reset_ct_reader (int slot) { - return SW_HOST_NOT_SUPPORTED; + /* FIXME: Check is this is sufficient do do a reset. */ + return ct_activate_card (slot); } static int ct_get_status (int slot, unsigned int *status) { + *status = 1|2|4; /* FIXME */ + return 0; + return SW_HOST_NOT_SUPPORTED; } @@ -436,6 +458,11 @@ ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, unsigned char dad[1], sad[1]; unsigned short ctbuflen; + /* If we don't have an ATR, we need to reset the reader first. */ + if (!reader_table[slot].atrlen + && (rc = reset_ct_reader (slot))) + return rc; + dad[0] = 0; /* Destination address: Card. */ sad[0] = 2; /* Source address: Host. */ ctbuflen = *buflen; @@ -444,12 +471,56 @@ ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, rc = CT_data (slot, dad, sad, apdulen, apdu, &ctbuflen, buffer); *buflen = ctbuflen; - /* FIXME: map the errorcodes to GNUPG ones, so that they can be - shared between CTAPI and PCSC. */ - return rc; + return rc? SW_HOST_CARD_IO_ERROR: 0; } + +/* Open a reader and return an internal handle for it. PORT is a + non-negative value with the port number of the reader. USB readers + do have port numbers starting at 32769. */ +static int +open_ct_reader (int port) +{ + int rc, reader; + + if (port < 0 || port > 0xffff) + { + log_error ("open_ct_reader: invalid port %d requested\n", port); + return -1; + } + reader = new_reader_slot (); + if (reader == -1) + return reader; + reader_table[reader].port = port; + + rc = CT_init (reader, (unsigned short)port); + if (rc) + { + log_error ("apdu_open_ct_reader failed on port %d: %s\n", + port, ct_error_string (rc)); + reader_table[reader].used = 0; + return -1; + } + + /* Only try to activate the card. */ + rc = ct_activate_card (reader); + if (rc) + { + reader_table[reader].atrlen = 0; + rc = 0; + } + + reader_table[reader].close_reader = close_ct_reader; + reader_table[reader].reset_reader = reset_ct_reader; + reader_table[reader].get_status_reader = ct_get_status; + reader_table[reader].send_apdu_reader = ct_send_apdu; + reader_table[reader].dump_status_reader = ct_dump_reader_status; + + dump_reader_status (reader); + return reader; +} + #ifdef NEED_PCSC_WRAPPER static int @@ -568,76 +639,322 @@ pcsc_error_string (long err) PC/SC Interface */ +static void +dump_pcsc_reader_status (int slot) +{ + log_info ("reader slot %d: active protocol:", slot); + if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T0)) + log_printf (" T0"); + else if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T1)) + log_printf (" T1"); + else if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_RAW)) + log_printf (" raw"); + log_printf ("\n"); +} + + + static int -open_pcsc_reader (const char *portstr) +pcsc_get_status (int slot, unsigned int *status) +{ + *status = 1|2|4; /* FIXME!!!! */ + return 0; +} + +static int +reset_pcsc_reader (int slot) +{ + return SW_HOST_NOT_SUPPORTED; +} + + +/* Actually send the APDU of length APDULEN to SLOT and return a + maximum of *BUFLEN data in BUFFER, the actual returned size will be + set to BUFLEN. Returns: CT API error code. */ +static int +pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) { #ifdef NEED_PCSC_WRAPPER -/* Open the PC/SC reader using the pcsc_wrapper program. This is - needed to cope with different thread models and other peculiarities - of libpcsclite. */ - int slot; + long err; reader_table_t slotp; - int fd, rp[2], wp[2]; - int n, i; - pid_t pid; - size_t len; + size_t len, full_len; + int i, n; unsigned char msgbuf[9]; - int err; - slot = new_reader_slot (); - if (slot == -1) - return -1; + if (!reader_table[slot].atrlen + && (err = reset_pcsc_reader (slot))) + return err; + + if (DBG_CARD_IO) + log_printhex (" PCSC_data:", apdu, apdulen); + slotp = reader_table + slot; - /* Fire up the pcsc wrapper. We don't use any fork/exec code from - the common directy but implement it direclty so that this file - may still be source copied. */ - - if (pipe (rp) == -1) + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 + || slotp->pcsc.pid == (pid_t)(-1) ) { - log_error ("error creating a pipe: %s\n", strerror (errno)); - slotp->used = 0; - return -1; + log_error ("pcsc_send_apdu: pcsc-wrapper not running\n"); + return SW_HOST_CARD_IO_ERROR; } - if (pipe (wp) == -1) + + msgbuf[0] = 0x03; /* TRANSMIT command. */ + len = apdulen; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) + || writen (slotp->pcsc.req_fd, apdu, len)) { - log_error ("error creating a pipe: %s\n", strerror (errno)); - close (rp[0]); - close (rp[1]); - slotp->used = 0; - return -1; + log_error ("error sending PC/SC TRANSMIT request: %s\n", + strerror (errno)); + goto command_failed; } - - pid = fork (); - if (pid == -1) + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) { - log_error ("error forking process: %s\n", strerror (errno)); - close (rp[0]); - close (rp[1]); - close (wp[0]); - close (wp[1]); - slotp->used = 0; - return -1; + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + { + log_error ("pcsc_transmit failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return SW_HOST_CARD_IO_ERROR; } - slotp->pcsc.pid = pid; - - if (!pid) - { /* - === Child === - */ - /* Double fork. */ - pid = fork (); - if (pid == -1) - _exit (31); - if (pid) - _exit (0); /* Immediate exit this parent, so that the child - gets cleaned up by the init process. */ + full_len = len; + + n = *buflen < len ? *buflen : len; + if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) + { + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + *buflen = n; - /* Connect our pipes. */ - if (wp[0] != 0 && dup2 (wp[0], 0) == -1) - log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); - if (rp[1] != 1 && dup2 (rp[1], 1) == -1) + full_len -= len; + if (full_len) + { + log_error ("pcsc_send_apdu: provided buffer too short - truncated\n"); + err = SW_HOST_INV_VALUE; + } + /* We need to read any rest of the response, to keep the + protocol runnng. */ + while (full_len) + { + unsigned char dummybuf[128]; + + n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf); + if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n) + { + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + full_len -= n; + } + + return err; + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return -1; + +#else /*!NEED_PCSC_WRAPPER*/ + + long err; + struct pcsc_io_request_s send_pci; + unsigned long recv_len; + + if (!reader_table[slot].atrlen + && (err = reset_pcsc_reader (slot))) + return err; + + if (DBG_CARD_IO) + log_printhex (" PCSC_data:", apdu, apdulen); + + if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T1)) + send_pci.protocol = PCSC_PROTOCOL_T1; + else + send_pci.protocol = PCSC_PROTOCOL_T0; + send_pci.pci_len = sizeof send_pci; + recv_len = *buflen; + err = pcsc_transmit (reader_table[slot].pcsc.card, + &send_pci, apdu, apdulen, + NULL, buffer, &recv_len); + *buflen = recv_len; + if (err) + log_error ("pcsc_transmit failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + + return err? SW_HOST_CARD_IO_ERROR:0; +#endif /*!NEED_PCSC_WRAPPER*/ +} + + +static int +close_pcsc_reader (int slot) +{ +#ifdef NEED_PCSC_WRAPPER + long err; + reader_table_t slotp; + size_t len; + int i; + unsigned char msgbuf[9]; + + slotp = reader_table + slot; + + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 + || slotp->pcsc.pid == (pid_t)(-1) ) + { + log_error ("close_pcsc_reader: pcsc-wrapper not running\n"); + return 0; + } + + msgbuf[0] = 0x02; /* CLOSE command. */ + len = 0; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) ) + { + log_error ("error sending PC/SC CLOSE request: %s\n", + strerror (errno)); + goto command_failed; + } + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC CLOSE response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + log_error ("pcsc_close failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + + /* We will the wrapper in any case - errors are merely + informational. */ + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return 0; + +#else /*!NEED_PCSC_WRAPPER*/ + + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; + return 0; +#endif /*!NEED_PCSC_WRAPPER*/ +} + +static int +open_pcsc_reader (const char *portstr) +{ +#ifdef NEED_PCSC_WRAPPER +/* Open the PC/SC reader using the pcsc_wrapper program. This is + needed to cope with different thread models and other peculiarities + of libpcsclite. */ + int slot; + reader_table_t slotp; + int fd, rp[2], wp[2]; + int n, i; + pid_t pid; + size_t len; + unsigned char msgbuf[9]; + int err; + + slot = new_reader_slot (); + if (slot == -1) + return -1; + slotp = reader_table + slot; + + /* Fire up the pcsc wrapper. We don't use any fork/exec code from + the common directy but implement it direclty so that this file + may still be source copied. */ + + if (pipe (rp) == -1) + { + log_error ("error creating a pipe: %s\n", strerror (errno)); + slotp->used = 0; + return -1; + } + if (pipe (wp) == -1) + { + log_error ("error creating a pipe: %s\n", strerror (errno)); + close (rp[0]); + close (rp[1]); + slotp->used = 0; + return -1; + } + + pid = fork (); + if (pid == -1) + { + log_error ("error forking process: %s\n", strerror (errno)); + close (rp[0]); + close (rp[1]); + close (wp[0]); + close (wp[1]); + slotp->used = 0; + return -1; + } + slotp->pcsc.pid = pid; + + if (!pid) + { /* + === Child === + */ + + /* Double fork. */ + pid = fork (); + if (pid == -1) + _exit (31); + if (pid) + _exit (0); /* Immediate exit this parent, so that the child + gets cleaned up by the init process. */ + + /* Connect our pipes. */ + if (wp[0] != 0 && dup2 (wp[0], 0) == -1) + log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); + if (rp[1] != 1 && dup2 (rp[1], 1) == -1) log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); /* Send stderr to the bit bucket. */ @@ -724,6 +1041,12 @@ open_pcsc_reader (const char *portstr) } slotp->atrlen = len; + reader_table[slot].close_reader = close_pcsc_reader; + reader_table[slot].reset_reader = reset_pcsc_reader; + reader_table[slot].get_status_reader = pcsc_get_status; + reader_table[slot].send_apdu_reader = pcsc_send_apdu; + reader_table[slot].dump_status_reader = dump_pcsc_reader_status; + dump_reader_status (slot); return slot; @@ -819,300 +1142,49 @@ open_pcsc_reader (const char *portstr) /* (We need to pass a dummy buffer. We use LIST because it ought to be large enough.) */ err = pcsc_status (reader_table[slot].pcsc.card, - list, &listlen, - &card_state, &card_protocol, - reader_table[slot].atr, &atrlen); - xfree (list); - if (err) - { - log_error ("pcsc_status failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - pcsc_release_context (reader_table[slot].pcsc.context); - reader_table[slot].used = 0; - return -1; - } - if (atrlen >= DIM (reader_table[0].atr)) - log_bug ("ATR returned by pcsc_status is too large\n"); - reader_table[slot].atrlen = atrlen; -/* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */ -/* log_debug ("protocol from pcsc_status: 0x%lx\n", card_protocol); */ - - dump_reader_status (slot); - return slot; -#endif /*!NEED_PCSC_WRAPPER */ -} - - -static int -pcsc_get_status (int slot, unsigned int *status) -{ - return SW_HOST_NOT_SUPPORTED; -} - -/* Actually send the APDU of length APDULEN to SLOT and return a - maximum of *BUFLEN data in BUFFER, the actual returned size will be - set to BUFLEN. Returns: CT API error code. */ -static int -pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) -{ -#ifdef NEED_PCSC_WRAPPER - long err; - reader_table_t slotp; - size_t len, full_len; - int i, n; - unsigned char msgbuf[9]; - - if (DBG_CARD_IO) - log_printhex (" PCSC_data:", apdu, apdulen); - - slotp = reader_table + slot; - - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 - || slotp->pcsc.pid == (pid_t)(-1) ) - { - log_error ("pcsc_send_apdu: pcsc-wrapper not running\n"); - return -1; - } - - msgbuf[0] = 0x03; /* TRANSMIT command. */ - len = apdulen; - msgbuf[1] = (len >> 24); - msgbuf[2] = (len >> 16); - msgbuf[3] = (len >> 8); - msgbuf[4] = (len ); - if ( writen (slotp->pcsc.req_fd, msgbuf, 5) - || writen (slotp->pcsc.req_fd, apdu, len)) - { - log_error ("error sending PC/SC TRANSMIT request: %s\n", - strerror (errno)); - goto command_failed; - } - - /* Read the response. */ - if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) - { - log_error ("error receiving PC/SC TRANSMIT response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; - if (msgbuf[0] != 0x81 || len < 4) - { - log_error ("invalid response header from PC/SC received\n"); - goto command_failed; - } - len -= 4; /* Already read the error code. */ - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; - if (err) - { - log_error ("pcsc_transmit failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - return -1; - } - - full_len = len; - - n = *buflen < len ? *buflen : len; - if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) - { - log_error ("error receiving PC/SC TRANSMIT response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - *buflen = n; - - full_len -= len; - if (full_len) - { - log_error ("pcsc_send_apdu: provided buffer too short - truncated\n"); - err = -1; - } - /* We need to read any rest of the response, to keep the - protocol runnng. */ - while (full_len) - { - unsigned char dummybuf[128]; - - n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf); - if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n) - { - log_error ("error receiving PC/SC TRANSMIT response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - full_len -= n; - } - - return err; - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - return -1; - -#else /*!NEED_PCSC_WRAPPER*/ - - long err; - struct pcsc_io_request_s send_pci; - unsigned long recv_len; - - if (DBG_CARD_IO) - log_printhex (" PCSC_data:", apdu, apdulen); - - if ((reader_table[slot].pcsc.protocol & PCSC_PROTOCOL_T1)) - send_pci.protocol = PCSC_PROTOCOL_T1; - else - send_pci.protocol = PCSC_PROTOCOL_T0; - send_pci.pci_len = sizeof send_pci; - recv_len = *buflen; - err = pcsc_transmit (reader_table[slot].pcsc.card, - &send_pci, apdu, apdulen, - NULL, buffer, &recv_len); - *buflen = recv_len; - if (err) - log_error ("pcsc_transmit failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - - return err? -1:0; /* FIXME: Return appropriate error code. */ -#endif /*!NEED_PCSC_WRAPPER*/ -} - - -static int -close_pcsc_reader (int slot) -{ -#ifdef NEED_PCSC_WRAPPER - long err; - reader_table_t slotp; - size_t len; - int i; - unsigned char msgbuf[9]; - - slotp = reader_table + slot; - - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 - || slotp->pcsc.pid == (pid_t)(-1) ) - { - log_error ("close_pcsc_reader: pcsc-wrapper not running\n"); - return 0; - } - - msgbuf[0] = 0x02; /* CLOSE command. */ - len = 0; - msgbuf[1] = (len >> 24); - msgbuf[2] = (len >> 16); - msgbuf[3] = (len >> 8); - msgbuf[4] = (len ); - if ( writen (slotp->pcsc.req_fd, msgbuf, 5) ) - { - log_error ("error sending PC/SC CLOSE request: %s\n", - strerror (errno)); - goto command_failed; - } - - /* Read the response. */ - if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) - { - log_error ("error receiving PC/SC CLOSE response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; - } - len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; - if (msgbuf[0] != 0x81 || len < 4) - { - log_error ("invalid response header from PC/SC received\n"); - goto command_failed; - } - len -= 4; /* Already read the error code. */ - err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; - if (err) - log_error ("pcsc_close failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - - /* We will the wrapper in any case - errors are merely - informational. */ - - command_failed: - close (slotp->pcsc.req_fd); - close (slotp->pcsc.rsp_fd); - slotp->pcsc.req_fd = -1; - slotp->pcsc.rsp_fd = -1; - kill (slotp->pcsc.pid, SIGTERM); - slotp->pcsc.pid = (pid_t)(-1); - slotp->used = 0; - return 0; - -#else /*!NEED_PCSC_WRAPPER*/ - - pcsc_release_context (reader_table[slot].pcsc.context); - reader_table[slot].used = 0; - return 0; -#endif /*!NEED_PCSC_WRAPPER*/ -} - -static int -reset_pcsc_reader (int slot) -{ - return SW_HOST_NOT_SUPPORTED; -} - - - - - -#ifdef HAVE_LIBUSB -/* - Internal CCID driver interface. - */ - -static const char * -get_ccid_error_string (long err) -{ - if (!err) - return "okay"; - else - return "unknown CCID error"; -} - -static int -open_ccid_reader (void) -{ - int err; - int slot; - reader_table_t slotp; - - slot = new_reader_slot (); - if (slot == -1) - return -1; - slotp = reader_table + slot; - - err = ccid_open_reader (&slotp->ccid.handle, 0); - if (err) - { - slotp->used = 0; - return -1; - } - - err = ccid_get_atr (slotp->ccid.handle, - slotp->atr, sizeof slotp->atr, &slotp->atrlen); + list, &listlen, + &card_state, &card_protocol, + reader_table[slot].atr, &atrlen); + xfree (list); if (err) { - slotp->used = 0; + log_error ("pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; return -1; } + if (atrlen >= DIM (reader_table[0].atr)) + log_bug ("ATR returned by pcsc_status is too large\n"); + reader_table[slot].atrlen = atrlen; - slotp->is_ccid = 1; + reader_table[slot].close_reader = close_pcsc_reader; + reader_table[slot].reset_reader = reset_pcsc_reader; + reader_table[slot].get_status_reader = pcsc_get_status; + reader_table[slot].send_apdu_reader = pcsc_send_apdu; + reader_table[slot].dump_status_reader = dump_pcsc_reader_status; + +/* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */ +/* log_debug ("protocol from pcsc_status: 0x%lx\n", card_protocol); */ dump_reader_status (slot); return slot; +#endif /*!NEED_PCSC_WRAPPER */ +} + + + + +#ifdef HAVE_LIBUSB +/* + Internal CCID driver interface. + */ + + +static void +dump_ccid_reader_status (int slot) +{ + log_info ("reader slot %d: using ccid driver\n", slot); } static int @@ -1134,7 +1206,7 @@ reset_ccid_reader (int slot) err = ccid_get_atr (slotp->ccid.handle, atr, sizeof atr, &atrlen); if (err) - return -1; + return err; /* If the reset was successful, update the ATR. */ assert (sizeof slotp->atr >= sizeof atr); slotp->atrlen = atrlen; @@ -1175,6 +1247,11 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, long err; size_t maxbuflen; + /* If we don't have an ATR, we need to reset the reader first. */ + if (!reader_table[slot].atrlen + && (err = reset_ccid_reader (slot))) + return err; + if (DBG_CARD_IO) log_printhex (" APDU_data:", apdu, apdulen); @@ -1186,9 +1263,49 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, log_error ("ccid_transceive failed: (0x%lx)\n", err); - return err? -1:0; /* FIXME: Return appropriate error code. */ + return err; +} + +/* Open the reader and try to read an ATR. */ +static int +open_ccid_reader (void) +{ + int err; + int slot; + reader_table_t slotp; + + slot = new_reader_slot (); + if (slot == -1) + return -1; + slotp = reader_table + slot; + + err = ccid_open_reader (&slotp->ccid.handle, 0); + if (err) + { + slotp->used = 0; + return -1; + } + + err = ccid_get_atr (slotp->ccid.handle, + slotp->atr, sizeof slotp->atr, &slotp->atrlen); + if (err) + { + slotp->atrlen = 0; + err = 0; + } + + reader_table[slot].close_reader = close_ccid_reader; + reader_table[slot].reset_reader = reset_ccid_reader; + reader_table[slot].get_status_reader = get_status_ccid; + reader_table[slot].send_apdu_reader = send_apdu_ccid; + reader_table[slot].dump_status_reader = dump_ccid_reader_status; + + dump_reader_status (slot); + return slot; } + + #endif /* HAVE_LIBUSB */ @@ -1202,6 +1319,117 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, access to a card for resource conflict reasons. */ + +static int +close_osc_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + +static int +reset_osc_reader (int slot) +{ + return SW_HOST_NOT_SUPPORTED; +} + + +static int +osc_get_status (int slot, unsigned int *status) +{ + return SW_HOST_NOT_SUPPORTED; +} + + +/* Actually send the APDU of length APDULEN to SLOT and return a + maximum of *BUFLEN data in BUFFER, the actual returned size will be + set to BUFLEN. Returns: OpenSC error code. */ +static int +osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) +{ + long err; + struct sc_apdu a; + unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; + unsigned char result[SC_MAX_APDU_BUFFER_SIZE]; + + if (DBG_CARD_IO) + log_printhex (" APDU_data:", apdu, apdulen); + + if (apdulen < 4) + { + log_error ("osc_send_apdu: APDU is too short\n"); + return SW_HOST_INV_VALUE; + } + + memset(&a, 0, sizeof a); + a.cla = *apdu++; + a.ins = *apdu++; + a.p1 = *apdu++; + a.p2 = *apdu++; + apdulen -= 4; + + if (!apdulen) + a.cse = SC_APDU_CASE_1; + else if (apdulen == 1) + { + a.le = *apdu? *apdu : 256; + apdu++; apdulen--; + a.cse = SC_APDU_CASE_2_SHORT; + } + else + { + a.lc = *apdu++; apdulen--; + if (apdulen < a.lc) + { + log_error ("osc_send_apdu: APDU shorter than specified in Lc\n"); + return SW_HOST_INV_VALUE; + + } + memcpy(data, apdu, a.lc); + apdu += a.lc; apdulen -= a.lc; + + a.data = data; + a.datalen = a.lc; + + if (!apdulen) + a.cse = SC_APDU_CASE_3_SHORT; + else + { + a.le = *apdu? *apdu : 256; + apdu++; apdulen--; + if (apdulen) + { + log_error ("osc_send_apdu: APDU larger than specified\n"); + return SW_HOST_INV_VALUE; + } + a.cse = SC_APDU_CASE_4_SHORT; + } + } + + a.resp = result; + a.resplen = DIM(result); + + err = sc_transmit_apdu (reader_table[slot].osc.scard, &a); + if (err) + { + log_error ("sc_apdu_transmit failed: %s\n", sc_strerror (err)); + return SW_HOST_CARD_IO_ERROR; + } + + if (*buflen < 2 || a.resplen > *buflen - 2) + { + log_error ("osc_send_apdu: provided buffer too short to store result\n"); + return SW_HOST_INV_VALUE; + } + memcpy (buffer, a.resp, a.resplen); + buffer[a.resplen] = a.sw1; + buffer[a.resplen+1] = a.sw2; + *buflen = a.resplen + 2; + return 0; +} + static int open_osc_reader (int portno) { @@ -1286,30 +1514,119 @@ open_osc_reader (int portno) slotp->atrlen = slotp->osc.scard->atr_len; memcpy (slotp->atr, slotp->osc.scard->atr, slotp->atrlen); - slotp->is_osc = 1; + reader_table[slot].close_reader = close_osc_reader; + reader_table[slot].reset_reader = reset_osc_reader; + reader_table[slot].get_status_reader = osc_get_status; + reader_table[slot].send_apdu_reader = osc_send_apdu; + reader_table[slot].dump_status_reader = NULL; dump_reader_status (slot); return slot; } +#endif /* HAVE_OPENSC */ + + + +#ifdef USE_G10CODE_RAPDU +/* + The Remote APDU Interface. + + This uses the Remote APDU protocol to contact a reader. + + The port number is actually an index into the list of ports as + returned via the protocol. + */ + + +static int +rapdu_status_to_sw (int status) +{ + int rc; + + switch (status) + { + case RAPDU_STATUS_SUCCESS: rc = 0; break; + + case RAPDU_STATUS_INVCMD: + case RAPDU_STATUS_INVPROT: + case RAPDU_STATUS_INVSEQ: + case RAPDU_STATUS_INVCOOKIE: + case RAPDU_STATUS_INVREADER: rc = SW_HOST_INV_VALUE; break; + + case RAPDU_STATUS_TIMEOUT: rc = SW_HOST_CARD_IO_ERROR; break; + case RAPDU_STATUS_CARDIO: rc = SW_HOST_CARD_IO_ERROR; break; + case RAPDU_STATUS_NOCARD: rc = SW_HOST_NO_CARD; break; + case RAPDU_STATUS_CARDCHG: rc = SW_HOST_NO_CARD; break; + case RAPDU_STATUS_BUSY: rc = SW_HOST_BUSY; break; + case RAPDU_STATUS_NEEDRESET: rc = SW_HOST_CARD_INACTIVE; break; + + default: rc = SW_HOST_GENERAL_ERROR; break; + } + + return rc; +} + + static int -close_osc_reader (int slot) +close_rapdu_reader (int slot) { - /* FIXME: Implement. */ + rapdu_release (reader_table[slot].rapdu.handle); reader_table[slot].used = 0; return 0; } + static int -reset_osc_reader (int slot) +reset_rapdu_reader (int slot) { - return SW_HOST_NOT_SUPPORTED; + int err; + reader_table_t slotp; + rapdu_msg_t msg = NULL; + + slotp = reader_table + slot; + + err = rapdu_send_cmd (slotp->rapdu.handle, RAPDU_CMD_RESET); + if (err) + { + log_error ("sending rapdu command RESET failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + rapdu_msg_release (msg); + return rapdu_status_to_sw (err); + } + err = rapdu_read_msg (slotp->rapdu.handle, &msg); + if (err) + { + log_error ("receiving rapdu message failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + rapdu_msg_release (msg); + return rapdu_status_to_sw (err); + } + if (msg->cmd != RAPDU_STATUS_SUCCESS || !msg->datalen) + { + int sw = rapdu_status_to_sw (msg->cmd); + log_error ("rapdu command RESET failed: %s\n", + rapdu_strerror (msg->cmd)); + rapdu_msg_release (msg); + return sw; + } + if (msg->datalen >= DIM (slotp->atr)) + { + log_error ("ATR returned by the RAPDU layer is too large\n"); + rapdu_msg_release (msg); + return SW_HOST_INV_VALUE; + } + slotp->atrlen = msg->datalen; + memcpy (slotp->atr, msg->data, msg->datalen); + + rapdu_msg_release (msg); + return 0; } static int -osc_get_status (int slot, unsigned int *status) +my_rapdu_get_status (int slot, unsigned int *status) { return SW_HOST_NOT_SUPPORTED; } @@ -1319,91 +1636,151 @@ osc_get_status (int slot, unsigned int *status) maximum of *BUFLEN data in BUFFER, the actual returned size will be set to BUFLEN. Returns: OpenSC error code. */ static int -osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) +my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen, + unsigned char *buffer, size_t *buflen) { - long err; - struct sc_apdu a; - unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; - unsigned char result[SC_MAX_APDU_BUFFER_SIZE]; + int err; + reader_table_t slotp; + rapdu_msg_t msg = NULL; + size_t maxlen = *buflen; + + slotp = reader_table + slot; + *buflen = 0; if (DBG_CARD_IO) log_printhex (" APDU_data:", apdu, apdulen); if (apdulen < 4) { - log_error ("osc_send_apdu: APDU is too short\n"); - return SC_ERROR_CMD_TOO_SHORT; + log_error ("rapdu_send_apdu: APDU is too short\n"); + return SW_HOST_INV_VALUE; } - memset(&a, 0, sizeof a); - a.cla = *apdu++; - a.ins = *apdu++; - a.p1 = *apdu++; - a.p2 = *apdu++; - apdulen -= 4; - - if (!apdulen) - a.cse = SC_APDU_CASE_1; - else if (apdulen == 1) + err = rapdu_send_apdu (slotp->rapdu.handle, apdu, apdulen); + if (err) { - a.le = *apdu? *apdu : 256; - apdu++; apdulen--; - a.cse = SC_APDU_CASE_2_SHORT; + log_error ("sending rapdu command APDU failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + rapdu_msg_release (msg); + return rapdu_status_to_sw (err); } - else + err = rapdu_read_msg (slotp->rapdu.handle, &msg); + if (err) { - a.lc = *apdu++; apdulen--; - if (apdulen < a.lc) - { - log_error ("osc_send_apdu: APDU shorter than specified in Lc\n"); - return SC_ERROR_CMD_TOO_SHORT; + log_error ("receiving rapdu message failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + rapdu_msg_release (msg); + return rapdu_status_to_sw (err); + } + if (msg->cmd != RAPDU_STATUS_SUCCESS || !msg->datalen) + { + int sw = rapdu_status_to_sw (msg->cmd); + log_error ("rapdu command APDU failed: %s\n", + rapdu_strerror (msg->cmd)); + rapdu_msg_release (msg); + return sw; + } + + if (msg->datalen > maxlen) + { + log_error ("rapdu response apdu too large\n"); + rapdu_msg_release (msg); + return SW_HOST_INV_VALUE; + } + + *buflen = msg->datalen; + memcpy (buffer, msg->data, msg->datalen); + + rapdu_msg_release (msg); + return 0; +} + +static int +open_rapdu_reader (int portno, + const unsigned char *cookie, size_t length, + int (*readfnc) (void *opaque, + void *buffer, size_t size), + void *readfnc_value, + int (*writefnc) (void *opaque, + const void *buffer, size_t size), + void *writefnc_value, + void (*closefnc) (void *opaque), + void *closefnc_value) +{ + int err; + int slot; + reader_table_t slotp; + rapdu_msg_t msg = NULL; - } - memcpy(data, apdu, a.lc); - apdu += a.lc; apdulen -= a.lc; + slot = new_reader_slot (); + if (slot == -1) + return -1; + slotp = reader_table + slot; - a.data = data; - a.datalen = a.lc; - - if (!apdulen) - a.cse = SC_APDU_CASE_3_SHORT; - else - { - a.le = *apdu? *apdu : 256; - apdu++; apdulen--; - if (apdulen) - { - log_error ("osc_send_apdu: APDU larger than specified\n"); - return SC_ERROR_CMD_TOO_LONG; - } - a.cse = SC_APDU_CASE_4_SHORT; - } + slotp->rapdu.handle = rapdu_new (); + if (!slotp->rapdu.handle) + { + slotp->used = 0; + return -1; } - a.resp = result; - a.resplen = DIM(result); - err = sc_transmit_apdu (reader_table[slot].osc.scard, &a); + rapdu_set_iofunc (slotp->rapdu.handle, + readfnc, readfnc_value, + writefnc, writefnc_value, + closefnc, closefnc_value); + rapdu_set_cookie (slotp->rapdu.handle, cookie, length); + + /* First try to get the current ATR, but if the card is inactive + issue a reset instead. */ + err = rapdu_send_cmd (slotp->rapdu.handle, RAPDU_CMD_GET_ATR); + if (err == RAPDU_STATUS_NEEDRESET) + err = rapdu_send_cmd (slotp->rapdu.handle, RAPDU_CMD_RESET); if (err) { - log_error ("sc_apdu_transmit failed: %s\n", sc_strerror (err)); - return err; + log_info ("sending rapdu command GET_ATR/RESET failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + goto failure; } - - if (*buflen < 2 || a.resplen > *buflen - 2) + err = rapdu_read_msg (slotp->rapdu.handle, &msg); + if (err) { - log_error ("osc_send_apdu: provided buffer too short to store result\n"); - return SC_ERROR_BUFFER_TOO_SMALL; + log_info ("receiving rapdu message failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + goto failure; } - memcpy (buffer, a.resp, a.resplen); - buffer[a.resplen] = a.sw1; - buffer[a.resplen+1] = a.sw2; - *buflen = a.resplen + 2; - return 0; + if (msg->cmd != RAPDU_STATUS_SUCCESS || !msg->datalen) + { + log_info ("rapdu command GET ATR failed: %s\n", + rapdu_strerror (msg->cmd)); + goto failure; + } + if (msg->datalen >= DIM (slotp->atr)) + { + log_error ("ATR returned by the RAPDU layer is too large\n"); + goto failure; + } + slotp->atrlen = msg->datalen; + memcpy (slotp->atr, msg->data, msg->datalen); + + reader_table[slot].close_reader = close_rapdu_reader; + reader_table[slot].reset_reader = reset_rapdu_reader; + reader_table[slot].get_status_reader = my_rapdu_get_status; + reader_table[slot].send_apdu_reader = my_rapdu_send_apdu; + reader_table[slot].dump_status_reader = NULL; + + dump_reader_status (slot); + rapdu_msg_release (msg); + return slot; + + failure: + rapdu_msg_release (msg); + rapdu_release (slotp->rapdu.handle); + slotp->used = 0; + return -1; } -#endif /* HAVE_OPENSC */ +#endif /*USE_G10CODE_RAPDU*/ @@ -1583,23 +1960,46 @@ apdu_open_reader (const char *portstr) } +/* Open an remote reader and return an internal slot number or -1 on + error. This function is an alternative to apdu_open_reader and used + with remote readers only. Note that the supplied CLOSEFNC will + only be called once and the slot will not be valid afther this. + + If PORTSTR is NULL we default to the first availabe port. +*/ +int +apdu_open_remote_reader (const char *portstr, + const unsigned char *cookie, size_t length, + int (*readfnc) (void *opaque, + void *buffer, size_t size), + void *readfnc_value, + int (*writefnc) (void *opaque, + const void *buffer, size_t size), + void *writefnc_value, + void (*closefnc) (void *opaque), + void *closefnc_value) +{ +#ifdef USE_G10CODE_RAPDU + return open_rapdu_reader (portstr? atoi (portstr) : 0, + cookie, length, + readfnc, readfnc_value, + writefnc, writefnc_value, + closefnc, closefnc_value); +#else + errno = ENOSYS; + return -1; +#endif +} + + int apdu_close_reader (int slot) { if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; - if (reader_table[slot].is_ctapi) - return close_ct_reader (slot); -#ifdef HAVE_LIBUSB - else if (reader_table[slot].is_ccid) - return close_ccid_reader (slot); -#endif -#ifdef HAVE_OPENSC - else if (reader_table[slot].is_osc) - return close_osc_reader (slot); -#endif - else - return close_pcsc_reader (slot); + if (reader_table[slot].close_reader) + return reader_table[slot].close_reader (slot); + return SW_HOST_NOT_SUPPORTED; } /* Enumerate all readers and return information on whether this reader @@ -1626,23 +2026,52 @@ apdu_reset (int slot) if ((sw = lock_slot (slot))) return sw; - if (reader_table[slot].is_ctapi) - sw = reset_ct_reader (slot); -#ifdef HAVE_LIBUSB - else if (reader_table[slot].is_ccid) - sw = reset_ccid_reader (slot); -#endif -#ifdef HAVE_OPENSC - else if (reader_table[slot].is_osc) - sw = reset_osc_reader (slot); -#endif - else - sw = reset_pcsc_reader (slot); + if (reader_table[slot].reset_reader) + sw = reader_table[slot].reset_reader (slot); + + unlock_slot (slot); + return sw; +} + +/* Activate a card if it has not yet been done. This is a kind of + reset-if-required. It is useful to test for presence of a card + before issuing a bunch of apdu commands. It does not wait on a + locked card. */ +int +apdu_activate (int slot) +{ + int sw; + unsigned int s; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if ((sw = trylock_slot (slot))) + return sw; + + if (reader_table[slot].get_status_reader) + sw = reader_table[slot].get_status_reader (slot, &s); + + if (!sw) + { + if (!(s & 2)) /* Card not present. */ + sw = SW_HOST_NO_CARD; + else if ( ((s & 2) && !(s & 4)) + || !reader_table[slot].atrlen ) + { + /* We don't have an ATR or a card is present though inactive: + do a reset now. */ + if (reader_table[slot].reset_reader) + sw = reader_table[slot].reset_reader (slot); + } + } + unlock_slot (slot); return sw; } + unsigned char * apdu_get_atr (int slot, size_t *atrlen) @@ -1660,29 +2089,9 @@ apdu_get_atr (int slot, size_t *atrlen) return buf; } - - -static const char * -error_string (int slot, long rc) -{ - if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) - return "[invalid slot]"; - if (reader_table[slot].is_ctapi) - return ct_error_string (rc); -#ifdef HAVE_LIBUSB - else if (reader_table[slot].is_ccid) - return get_ccid_error_string (rc); -#endif -#ifdef HAVE_OPENSC - else if (reader_table[slot].is_osc) - return sc_strerror (rc); -#endif - else - return pcsc_error_string (rc); -} - -/* Retrieve the status for SLOT. The function does obnly wait fot the + +/* Retrieve the status for SLOT. The function does only wait for the card to become available if HANG is set to true. On success the bits in STATUS will be set to @@ -1691,7 +2100,7 @@ error_string (int slot, long rc) bit 2 = card active bit 3 = card access locked [not yet implemented] - For must application, tetsing bit 0 is sufficient. + For must application, testing bit 0 is sufficient. CHANGED will receive the value of the counter tracking the number of card insertions. This value may be used to detect a card @@ -1710,18 +2119,8 @@ apdu_get_status (int slot, int hang, if ((sw = hang? lock_slot (slot) : trylock_slot (slot))) return sw; - if (reader_table[slot].is_ctapi) - sw = ct_get_status (slot, &s); -#ifdef HAVE_LIBUSB - else if (reader_table[slot].is_ccid) - sw = get_status_ccid (slot, &s); -#endif -#ifdef HAVE_OPENSC - else if (reader_table[slot].is_osc) - sw = osc_get_status (slot, &s); -#endif - else - sw = pcsc_get_status (slot, &s); + if (reader_table[slot].get_status_reader) + sw = reader_table[slot].get_status_reader (slot, &s); unlock_slot (slot); @@ -1744,18 +2143,13 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen, { if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; - if (reader_table[slot].is_ctapi) - return ct_send_apdu (slot, apdu, apdulen, buffer, buflen); -#ifdef HAVE_LIBUSB - else if (reader_table[slot].is_ccid) - return send_apdu_ccid (slot, apdu, apdulen, buffer, buflen); -#endif -#ifdef HAVE_OPENSC - else if (reader_table[slot].is_osc) - return osc_send_apdu (slot, apdu, apdulen, buffer, buflen); -#endif + + if (reader_table[slot].send_apdu_reader) + return reader_table[slot].send_apdu_reader (slot, + apdu, apdulen, + buffer, buflen); else - return pcsc_send_apdu (slot, apdu, apdulen, buffer, buflen); + return SW_HOST_NOT_SUPPORTED; } /* Send an APDU to the card in SLOT. The APDU is created from all @@ -1819,9 +2213,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, if (rc || resultlen < 2) { log_error ("apdu_send_simple(%d) failed: %s\n", - slot, error_string (slot, rc)); + slot, apdu_strerror (rc)); unlock_slot (slot); - return SW_HOST_INCOMPLETE_CARD_RESPONSE; + return rc? rc : SW_HOST_INCOMPLETE_CARD_RESPONSE; } sw = (result[resultlen-2] << 8) | result[resultlen-1]; /* store away the returned data but strip the statusword. */ @@ -1886,9 +2280,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, if (rc || resultlen < 2) { log_error ("apdu_send_simple(%d) for get response failed: %s\n", - slot, error_string (slot, rc)); + slot, apdu_strerror (rc)); unlock_slot (slot); - return SW_HOST_INCOMPLETE_CARD_RESPONSE; + return rc? rc : SW_HOST_INCOMPLETE_CARD_RESPONSE; } sw = (result[resultlen-2] << 8) | result[resultlen-1]; resultlen -= 2; @@ -1977,5 +2371,180 @@ apdu_send_simple (int slot, int class, int ins, int p0, int p1, } +/* This is a more generic version of the apdu sending routine. It + takes an already formatted APDU in APDUDATA or length APDUDATALEN + and returns the with the APDU including the status word. With + HANDLE_MORE set to true this function will handle the MORE DATA + status and return all APDUs concatenated with one status word at + the end. The function does not return a regular status word but 0 + on success. If the slot is locked, the fucntion returns + immediately.*/ +int +apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, + int handle_more, + unsigned char **retbuf, size_t *retbuflen) +{ +#define RESULTLEN 256 + unsigned char apdu[5+256+1]; + size_t apdulen; + unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in + the driver. */ + size_t resultlen; + int sw; + long rc; /* we need a long here due to PC/SC. */ + int class; + + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if ((sw = trylock_slot (slot))) + return sw; + + /* We simply trucntate a too long APDU. */ + if (apdudatalen > sizeof apdu) + apdudatalen = sizeof apdu; + apdulen = apdudatalen; + memcpy (apdu, apdudata, apdudatalen); + class = apdulen? *apdu : 0; + + + rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + if (rc || resultlen < 2) + { + log_error ("apdu_send_direct(%d) failed: %s\n", + slot, apdu_strerror (rc)); + unlock_slot (slot); + return rc? rc : SW_HOST_INCOMPLETE_CARD_RESPONSE; + } + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + /* Store away the returned data but strip the statusword. */ + resultlen -= 2; + if (DBG_CARD_IO) + { + log_debug (" response: sw=%04X datalen=%d\n", sw, resultlen); + if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA)) + log_printhex (" dump: ", result, resultlen); + } + + if (handle_more && (sw & 0xff00) == SW_MORE_DATA) + { + unsigned char *p = NULL, *tmp; + size_t bufsize = 4096; + + /* It is likely that we need to return much more data, so we + start off with a large buffer. */ + if (retbuf) + { + *retbuf = p = xtrymalloc (bufsize + 2); + if (!*retbuf) + { + unlock_slot (slot); + return SW_HOST_OUT_OF_CORE; + } + assert (resultlen < bufsize); + memcpy (p, result, resultlen); + p += resultlen; + } + + do + { + int len = (sw & 0x00ff); + + if (DBG_CARD_IO) + log_debug ("apdu_send_direct(%d): %d more bytes available\n", + slot, len); + apdulen = 0; + apdu[apdulen++] = class; + apdu[apdulen++] = 0xC0; + apdu[apdulen++] = 0; + apdu[apdulen++] = 0; + apdu[apdulen++] = len; + memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); + resultlen = RESULTLEN; + rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + if (rc || resultlen < 2) + { + log_error ("apdu_send_direct(%d) for get response failed: %s\n", + slot, apdu_strerror (rc)); + unlock_slot (slot); + return rc ? rc : SW_HOST_INCOMPLETE_CARD_RESPONSE; + } + sw = (result[resultlen-2] << 8) | result[resultlen-1]; + resultlen -= 2; + if (DBG_CARD_IO) + { + log_debug (" more: sw=%04X datalen=%d\n", sw, resultlen); + if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA)) + log_printhex (" dump: ", result, resultlen); + } + + if ((sw & 0xff00) == SW_MORE_DATA + || sw == SW_SUCCESS + || sw == SW_EOF_REACHED ) + { + if (retbuf && resultlen) + { + if (p - *retbuf + resultlen > bufsize) + { + bufsize += resultlen > 4096? resultlen: 4096; + tmp = xtryrealloc (*retbuf, bufsize + 2); + if (!tmp) + { + unlock_slot (slot); + return SW_HOST_OUT_OF_CORE; + } + p = tmp + (p - *retbuf); + *retbuf = tmp; + } + memcpy (p, result, resultlen); + p += resultlen; + } + } + else + log_info ("apdu_send_sdirect(%d) " + "got unexpected status %04X from get response\n", + slot, sw); + } + while ((sw & 0xff00) == SW_MORE_DATA); + + if (retbuf) + { + *retbuflen = p - *retbuf; + tmp = xtryrealloc (*retbuf, *retbuflen + 2); + if (tmp) + *retbuf = tmp; + } + } + else + { + if (retbuf) + { + *retbuf = xtrymalloc ((resultlen? resultlen : 1)+2); + if (!*retbuf) + { + unlock_slot (slot); + return SW_HOST_OUT_OF_CORE; + } + *retbuflen = resultlen; + memcpy (*retbuf, result, resultlen); + } + } + + unlock_slot (slot); + + /* Append the status word - we reseved the two extra bytes while + allocating the buffer. */ + if (retbuf) + { + (*retbuf)[(*retbuflen)++] = (sw >> 8); + (*retbuf)[(*retbuflen)++] = sw; + } + + if (DBG_CARD_IO && retbuf) + log_printhex (" dump: ", *retbuf, *retbuflen); + + return 0; +#undef RESULTLEN +} diff --git a/scd/apdu.h b/scd/apdu.h index f74bab7fe..a2b781266 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -53,19 +53,38 @@ enum { SW_HOST_NO_DRIVER = 0x10004, SW_HOST_NOT_SUPPORTED = 0x10005, SW_HOST_LOCKING_FAILED= 0x10006, - SW_HOST_BUSY = 0x10007 + SW_HOST_BUSY = 0x10007, + SW_HOST_NO_CARD = 0x10008, + SW_HOST_CARD_INACTIVE = 0x10009, + SW_HOST_CARD_IO_ERROR = 0x1000a, + SW_HOST_GENERAL_ERROR = 0x1000b, + SW_HOST_NO_READER = 0x1000c }; /* Note , that apdu_open_reader returns no status word but -1 on error. */ int apdu_open_reader (const char *portstr); +int apdu_open_remote_reader (const char *portstr, + const unsigned char *cookie, size_t length, + int (*readfnc) (void *opaque, + void *buffer, size_t size), + void *readfnc_value, + int (*writefnc) (void *opaque, + const void *buffer, size_t size), + void *writefnc_value, + void (*closefnc) (void *opaque), + void *closefnc_value); int apdu_close_reader (int slot); int apdu_enum_reader (int slot, int *used); unsigned char *apdu_get_atr (int slot, size_t *atrlen); +const char *apdu_strerror (int rc); -/* The apdu send functions do return status words. */ + +/* These apdu functions do return status words. */ + +int apdu_activate (int slot); int apdu_reset (int slot); int apdu_get_status (int slot, int hang, unsigned int *status, unsigned int *changed); @@ -77,6 +96,10 @@ int apdu_send (int slot, int class, int ins, int p0, int p1, int apdu_send_le (int slot, int class, int ins, int p0, int p1, int lc, const char *data, int le, unsigned char **retbuf, size_t *retbuflen); +int apdu_send_direct (int slot, + const unsigned char *apdudata, size_t apdudatalen, + int handle_more, + unsigned char **retbuf, size_t *retbuflen); #endif /*APDU_H*/ diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index cd0bee6ef..4751b8cdb 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -442,11 +442,11 @@ read_device_info (ccid_driver_t handle, struct usb_device *dev) } } } - return -1; /* No suitable device found. */ + return CCID_DRIVER_ERR_NO_READER; /* No suitable device found. */ } -/* Open the reader with the internal number READERNO and return a a +/* Open the reader with the internal number READERNO and return a pointer to be used as handle in HANDLE. Returns 0 on success. */ int ccid_open_reader (ccid_driver_t *handle, int readerno) @@ -469,7 +469,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) if (rc) { DEBUGOUT_1 ("usb_create_match failed: %d\n", rc); - return -1; + return CCID_DRIVER_ERR_NO_READER; } while (usb_find_device(match, dev, &dev) >= 0) @@ -482,7 +482,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) if (!*handle) { DEBUGOUT ("out of memory\n"); - rc = -1; + rc = CCID_DRIVER_ERR_OUT_OF_CORE; free (*handle); *handle = NULL; goto leave; @@ -503,6 +503,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) DEBUGOUT_1 ("usb_open failed: %d\n", rc); free (*handle); *handle = NULL; + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; goto leave; } @@ -515,6 +516,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); free (*handle); *handle = NULL; + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; goto leave; } @@ -605,7 +607,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) DEBUGOUT_1 ("usb_bulk_write error: %s\n", strerror (errno)); else DEBUGOUT_1 ("usb_bulk_write failed: %d\n", rc); - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } @@ -631,7 +633,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, if (rc < 0) { DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno)); - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } *nread = msglen = rc; @@ -639,23 +641,23 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, if (msglen < 10) { DEBUGOUT_1 ("bulk-in msg too short (%u)\n", (unsigned int)msglen); - return -1; + return CCID_DRIVER_ERR_INV_VALUE; } if (buffer[0] != expected_type) { DEBUGOUT_1 ("unexpected bulk-in msg type (%02x)\n", buffer[0]); - return -1; + return CCID_DRIVER_ERR_INV_VALUE; } if (buffer[5] != 0) { DEBUGOUT_1 ("unexpected bulk-in slot (%d)\n", buffer[5]); - return -1; + return CCID_DRIVER_ERR_INV_VALUE; } if (buffer[6] != seqno) { DEBUGOUT_2 ("bulk-in seqno does not match (%d/%d)\n", seqno, buffer[6]); - return -1; + return CCID_DRIVER_ERR_INV_VALUE; } if ( !(buffer[7] & 0x03) && (buffer[7] & 0xC0) == 0x80) @@ -672,6 +674,13 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, DEBUGOUT_CONT_1 (" %02X", buffer[i]); DEBUGOUT_LF (); + switch ((buffer[7] & 0x03)) + { + case 0: /* no error */ break; + case 1: return CCID_DRIVER_ERR_CARD_INACTIVE; + case 2: return CCID_DRIVER_ERR_NO_CARD; + case 3: /* RFU */ break; + } return 0; } @@ -695,7 +704,7 @@ ccid_poll (ccid_driver_t handle) if (rc < 0) { DEBUGOUT_1 ("usb_intr_read error: %s\n", strerror (errno)); - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } msglen = rc; @@ -704,7 +713,7 @@ ccid_poll (ccid_driver_t handle) if (msglen < 1) { DEBUGOUT ("intr-in msg too short\n"); - return -1; + return CCID_DRIVER_ERR_INV_VALUE; } if (msg[0] == RDR_to_PC_NotifySlotChange) @@ -731,7 +740,8 @@ ccid_poll (ccid_driver_t handle) } - +/* Note that this fucntion won't return the error codes NO_CARD or + CARD_INACTIVE */ int ccid_slot_status (ccid_driver_t handle, int *statusbits) { @@ -752,7 +762,8 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) if (rc) return rc; rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno); - if (rc) + if (rc && rc != CCID_DRIVER_ERR_NO_CARD + && rc != CCID_DRIVER_ERR_CARD_INACTIVE) return rc; *statusbits = (msg[7] & 3); @@ -1018,7 +1029,7 @@ ccid_transceive (ccid_driver_t handle, /* Construct an I-Block. */ if (apdulen > 254) - return -1; /* Invalid length. */ + return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */ tpdu = msg+10; /* NAD: DAD=1, SAD=0 */ @@ -1082,7 +1093,7 @@ ccid_transceive (ccid_driver_t handle, if (tpdulen < 4) { DEBUGOUT ("cannot yet handle short blocks!\n"); - return -1; + return CCID_DRIVER_ERR_NOT_SUPPORTED; } #ifdef DEBUG_T1 @@ -1132,7 +1143,7 @@ ccid_transceive (ccid_driver_t handle, DEBUGOUT_2 ("provided buffer too short for received data " "(%u/%u)\n", (unsigned int)n, (unsigned int)maxresplen); - return -1; + return CCID_DRIVER_ERR_INV_VALUE; } memcpy (resp, p, n); @@ -1163,7 +1174,7 @@ ccid_transceive (ccid_driver_t handle, if (++retries > 3) { DEBUGOUT ("3 failed retries\n"); - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } msg = send_buffer; tpdulen = last_tpdulen; @@ -1171,7 +1182,7 @@ ccid_transceive (ccid_driver_t handle, else if (sending && !!(tpdu[1] & 0x40) == handle->t1_ns) { /* Reponse does not match our sequence number. */ DEBUGOUT ("R-block with wrong seqno received on more bit\n"); - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } else if (sending) { /* Send next chunk. */ @@ -1183,7 +1194,7 @@ ccid_transceive (ccid_driver_t handle, else { DEBUGOUT ("unexpected ACK R-block received\n"); - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } } else @@ -1210,7 +1221,7 @@ ccid_transceive (ccid_driver_t handle, DEBUGOUT_1 ("T1 waittime extension of bwi=%d\n", bwi); } else - return -1; + return CCID_DRIVER_ERR_CARD_IO_ERROR; } } /* end T=1 protocol loop. */ diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 8b86eb1a5..0b108f16d 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -55,6 +55,22 @@ #ifndef CCID_DRIVER_H #define CCID_DRIVER_H +/* The CID driver returns the same error codes as the statsu words + used by GnuPG's apdu.h. For ease of maintenance they should always + match. */ +#define CCID_DRIVER_ERR_OUT_OF_CORE 0x10001 +#define CCID_DRIVER_ERR_INV_VALUE 0x10002 +#define CCID_DRIVER_ERR_INCOMPLETE_CARD_RESPONSE = 0x10003 +#define CCID_DRIVER_ERR_NO_DRIVER 0x10004 +#define CCID_DRIVER_ERR_NOT_SUPPORTED 0x10005 +#define CCID_DRIVER_ERR_LOCKING_FAILED 0x10006 +#define CCID_DRIVER_ERR_BUSY 0x10007 +#define CCID_DRIVER_ERR_NO_CARD 0x10008 +#define CCID_DRIVER_ERR_CARD_INACTIVE 0x10009 +#define CCID_DRIVER_ERR_CARD_IO_ERROR 0x1000a +#define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b +#define CCID_DRIVER_ERR_NO_READER 0x1000c + struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; diff --git a/scd/iso7816.c b/scd/iso7816.c index fd3f0485c..d5db607f8 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -85,6 +85,12 @@ map_sw (int sw) case SW_HOST_NOT_SUPPORTED: ec = GPG_ERR_NOT_SUPPORTED; break; case SW_HOST_LOCKING_FAILED: ec = GPG_ERR_BUG; break; case SW_HOST_BUSY: ec = GPG_ERR_EBUSY; break; + case SW_HOST_NO_CARD: ec = GPG_ERR_CARD_NOT_PRESENT; break; + case SW_HOST_CARD_INACTIVE: ec = GPG_ERR_CARD_RESET; break; + case SW_HOST_CARD_IO_ERROR: ec = GPG_ERR_EIO; break; + case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break; + case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break; + default: if ((sw & 0x010000)) ec = GPG_ERR_GENERAL; /* Should not happen. */ -- cgit v1.2.3 From 08b98804e429e1282a8921f6261ec27c88c43827 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jul 2004 07:06:36 +0000 Subject: (gpgsm_validate_chain): The trust check didn't worked anymore, probably due to the changes at 2003-03-04. Fixed. --- sm/ChangeLog | 5 +++++ sm/certchain.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/sm/ChangeLog b/sm/ChangeLog index c1a8f6411..5571540be 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-07-20 Werner Koch <wk@gnupg.org> + + * certchain.c (gpgsm_validate_chain): The trust check didn't + worked anymore, probably due to the changes at 2003-03-04. Fixed. + 2004-06-06 Werner Koch <wk@gnupg.org> * certreqgen.c (get_parameter_uint, create_request): Create diff --git a/sm/certchain.c b/sm/certchain.c index 3009c21aa..8d54767f8 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -701,6 +701,9 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, gpg_strerror (rc)); } + if (rc) + goto leave; + /* Check for revocations etc. */ if ((flags & 1)) rc = 0; -- cgit v1.2.3 From 224da037849fd7dd30a221db9e1c6eba037c5689 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jul 2004 11:21:53 +0000 Subject: * rfc822parse.c (rfc822parse_get_field): Add arg VALUEOFF. --- tools/ChangeLog | 4 ++++ tools/rfc822parse.c | 25 ++++++++++++++++++++++--- tools/rfc822parse.h | 3 ++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index a81a2d301..e4862bc38 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-06-16 Werner Koch <wk@gnupg.org> + + * rfc822parse.c (rfc822parse_get_field): Add arg VALUEOFF. + 2004-06-14 Werner Koch <wk@gnupg.org> * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New. diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index be1cf4a47..3379886de 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -1,6 +1,6 @@ /* rfc822parse.c - Simple mail and MIME parser * Copyright (C) 1999, 2000 Werner Koch, Duesseldorf - * Copyright (C) 2003, g10 Code GmbH + * Copyright (C) 2003, 2004 g10 Code GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -509,7 +509,7 @@ rfc822parse_finish (rfc822parse_t msg) /**************** * Get a copy of a header line. The line is returned as one long * string with LF to separate the continuation line. Caller must free - * the return buffer. which may be used to enumerate over all lines. + * the return buffer. WHICH may be used to enumerate over all lines. * Wildcards are allowed. This function works on the current headers; * i.e. the regular mail headers or the MIME headers of the current * part. @@ -521,9 +521,13 @@ rfc822parse_finish (rfc822parse_t msg) * Returns a newly allocated buffer or NULL on error. errno is set in * case of a memory failure or set to 0 if the requested field is not * available. + * + * If VALUEOFF is not NULL it will receive the offset of the first non + * space character in th value of the line. */ char * -rfc822parse_get_field (rfc822parse_t msg, const char *name, int which) +rfc822parse_get_field (rfc822parse_t msg, const char *name, int which, + size_t *valueoff) { HDR_LINE h, h2; char *buf, *p; @@ -552,6 +556,21 @@ rfc822parse_get_field (rfc822parse_t msg, const char *name, int which) } p[-1] = 0; } + + if (valueoff) + { + p = strchr (buf, ':'); + if (!p) + *valueoff = 0; /* Oops: should never happen. */ + else + { + p++; + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + *valueoff = p - buf; + } + } + return buf; } diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h index 1293117ac..a7ed5b4ec 100644 --- a/tools/rfc822parse.h +++ b/tools/rfc822parse.h @@ -60,7 +60,8 @@ int rfc822parse_finish (rfc822parse_t msg); int rfc822parse_insert (rfc822parse_t msg, const unsigned char *line, size_t length); -char *rfc822parse_get_field (rfc822parse_t msg, const char *name, int which); +char *rfc822parse_get_field (rfc822parse_t msg, const char *name, int which, + size_t *valueoff); const char *rfc822parse_enum_header_lines (rfc822parse_t msg, void **context); -- cgit v1.2.3 From 3d471c15b8f9c0df81128150b730220a434fa11f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jul 2004 11:22:10 +0000 Subject: New option --enable-agent-only. --- ChangeLog | 4 ++++ configure.ac | 22 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f71334c9e..9fad1ba5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-07-20 Werner Koch <wk@gnupg.org> + + * configure.ac: New option --enable-agent-only. + 2004-06-08 Werner Koch <wk@gnupg.org> Released 1.9.9. diff --git a/configure.ac b/configure.ac index 4e611651e..e0f9b720e 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,13 @@ test -n "$GNUPG_PROTECT_TOOL_PGM" \ && show_gnupg_protect_tool_pgm="$GNUPG_PROTECT_TOOL_PGM" +# Some folks want to use only the agent form this packet. Make it +# easier for them by providing the configure option +# --enable-only-agent. +AC_ARG_ENABLE(agent-only, + AC_HELP_STRING([--enable-agent-only],[build only the gpg-agent]), + build_agent_only=$enableval) + # Configure option to allow ot disallow execution of external # programs, like a photo viewer. @@ -744,6 +751,7 @@ else fi fi +# fixme: do we really need this - it should be encapsulated in libassuan GNUPG_SYS_SO_PEERCRED # Checks for library functions. @@ -777,6 +785,8 @@ AC_REPLACE_FUNCS(putc_unlocked) # it is broken. It has been reported that some Solaris and HP UX systems # raise an SIGILL # +# fixme: Do we need this - iirc, this is only used by libgcrypt. +# AC_CACHE_CHECK([for gethrtime], [gnupg_cv_func_gethrtime], [AC_TRY_LINK([#include <sys/times.h>],[ @@ -815,6 +825,8 @@ GNUPG_FUNC_MKDIR_TAKES_ONE_ARG dnl dnl Check whether we can use Linux capabilities as requested dnl +# fixme: Still required? +# if test "$use_capabilities" = "yes" ; then use_capabilities=no AC_CHECK_HEADERS(sys/capability.h) @@ -968,7 +980,7 @@ AC_SUBST(W32LIBS) # We use jnlib, so tell other modules about it AC_DEFINE(HAVE_JNLIB_LOGGING, 1, - [Defined if jnlib style logging fucntions are available]) + [Defined if jnlib style logging functions are available]) @@ -1006,6 +1018,12 @@ if test "$build_scdaemon" = "yes"; then fi fi +if test "$build_agent_only" = "yes" ; then + build_gpg=no + build_gpgsm=no + build_scdaemon=no +fi + AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") @@ -1049,7 +1067,7 @@ if test "$have_libassuan" = "no"; then ***]]) fi if test "$have_ksba" = "no"; then - die=yes + die=no AC_MSG_NOTICE([[ *** *** You need libksba to build this program. -- cgit v1.2.3 From 2e10dbd6c8a7b8a80f90e9ff6e4285803c86dc48 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jul 2004 18:41:49 +0000 Subject: * Makefile.am (sm): Build kbx only if gpgsm is to be build. * maperror.c: Removed header ksba.h. Not required anymore. --- ChangeLog | 4 ++++ Makefile.am | 9 ++++++++- common/ChangeLog | 4 ++++ common/maperror.c | 1 - 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9fad1ba5b..dc43552dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-07-20 Werner Koch <wk@g10code.de> + + * Makefile.am (sm): Build kbx only if gpgsm is to be build. + 2004-07-20 Werner Koch <wk@gnupg.org> * configure.ac: New option --enable-agent-only. diff --git a/Makefile.am b/Makefile.am index 8f7d1771c..9be193353 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,6 +24,13 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = scripts/config.rpath autogen.sh README.CVS DISTCLEANFILES = g10defs.h +if BUILD_GPGSM +kbx = kbx +else +kbx = +endif + + if BUILD_GPG gpg = g10 else @@ -45,7 +52,7 @@ else scd = endif -SUBDIRS = m4 intl jnlib common kbx \ +SUBDIRS = m4 intl jnlib common ${kbx} \ ${gpg} ${sm} ${agent} ${scd} tools po doc tests dist-hook: diff --git a/common/ChangeLog b/common/ChangeLog index a848b8c78..a3a23bee1 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-07-20 Werner Koch <wk@g10code.de> + + * maperror.c: Removed header ksba.h. Not required anymore. + 2004-06-14 Werner Koch <wk@gnupg.org> * xreadline.c: New. Based on the iobuf_read_line function. diff --git a/common/maperror.c b/common/maperror.c index 2f6f1b159..89ecee987 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -26,7 +26,6 @@ #include <ctype.h> #include <unistd.h> -#include <ksba.h> #include <assuan.h> #include "util.h" -- cgit v1.2.3 From d9147773b4e5eda669ebd79454052d0a191cde55 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 22 Jul 2004 09:37:36 +0000 Subject: * trustlist.c (read_list): Allow colons in the fingerprint. (headerblurb): Rephrased. * gpg-agent.c (handle_connections): Increase the stack size ot 256k. * de.po: Updated. * scdaemon.c (main): Bumbed thread stack size up to 512k. * keylist.c (list_cert_raw): Print the keygrip. --- ChangeLog | 9 ++ NEWS | 11 +- README | 34 ++++-- TODO | 11 +- agent/ChangeLog | 7 ++ agent/gpg-agent.c | 2 +- agent/trustlist.c | 28 +++-- configure.ac | 3 +- po/ChangeLog | 4 + po/de.po | 350 +++++++++++++++++++++++++++++------------------------- scd/ChangeLog | 4 + scd/scdaemon.c | 2 +- sm/ChangeLog | 4 + sm/keylist.c | 6 +- 14 files changed, 275 insertions(+), 200 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc43552dd..42fe782af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-07-22 Werner Koch <wk@g10code.de> + + Released 1.9.10. + +2004-07-21 Werner Koch <wk@g10code.de> + + * configure.ac: Don't set DIE to no after it might has been set to + yes. + 2004-07-20 Werner Koch <wk@g10code.de> * Makefile.am (sm): Build kbx only if gpgsm is to be build. diff --git a/NEWS b/NEWS index 3d9b4ca34..74250b04a 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ -Noteworthy changes in version 1.9.10 ------------------------------------------------- +Noteworthy changes in version 1.9.10 (2004-07-22) +------------------------------------------------- + + * Fixed a serious bug in the checking of trusted root certificates. + + * New configure option --enable-agent-pnly allows to build and + install just the agent. + + * Fixed a problem with the log file handling. Noteworthy changes in version 1.9.9 (2004-06-08) diff --git a/README b/README index 5b4a69027..8027b6960 100644 --- a/README +++ b/README @@ -9,6 +9,10 @@ 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. +You should use this GnuPG version if you want to use the gpg-agent or +gpgsm (the S/MIME variant of gpg). Note that the gpg-agent is also +helpful when using the standard gpg versions (1.2.x or 1.3.x). + BUILD INSTRUCTIONS ================== @@ -20,7 +24,10 @@ GnuPG 1.9 depends on the following packages: 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 +If you use the configure option --enable-agent-only, libksba is not +required. + +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/ . @@ -28,7 +35,7 @@ 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 +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). @@ -42,9 +49,9 @@ As with all packages, you just have to do 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. +that this package won't confict with a GnuPG 1.2 or 1.3 +installation. gpg2 behaves just like gpg; it is however suggested to +keep using gpg 1.2.x or 1.3.x. 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. @@ -71,7 +78,7 @@ gpgsm: prepended before each block. -gpg2: +gpg2: (Note that these card commands are also available with gpg 1.3.x) ----- --card-status @@ -268,9 +275,10 @@ policies.txt 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. + A list of trusted certificates. The file will be created + automagically with some explaining comments. By using + gpg-agent's option --allow-mark-trusted, gpg-agent may add new + entries after user confirmation. random_seed @@ -436,7 +444,7 @@ modes for gpgsm, here is the entire list of ways to specify a key: *Heine -Please note that we have reused the hash mark indentifier which was +Please note that we have reused the hash mark identifier 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. @@ -456,7 +464,7 @@ file. gpgsm --import foo.p12 -This require that the gpg-agent is running. +This requires that the gpg-agent is running. HOW TO EXPORT A PRIVATE KEY @@ -482,8 +490,8 @@ 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. +The other cards we currently support are the Telesec NetKey card with +the NKS 2.0 card application and all generic DINSIG cards. 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 diff --git a/TODO b/TODO index cb58f907b..ce835d8ec 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,5 @@ -*- outline -*- -* Keylisting -Add the keygrip to the dump output -Explain how to setup a root CA key as trusted -Look for new system-wide certificates -Explain how trustlist.txt might be managed. - - * src/base64 ** Make parsing more robust @@ -83,4 +76,6 @@ might want to have an agent context for each service request ** Add a test to check the extkeyusage. - +* doc/ +** Explain how to setup a root CA key as trusted +** Explain how trustlist.txt might be managed. diff --git a/agent/ChangeLog b/agent/ChangeLog index 929959d85..d616b1544 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,10 @@ +2004-07-22 Werner Koch <wk@g10code.de> + + * trustlist.c (read_list): Allow colons in the fingerprint. + (headerblurb): Rephrased. + + * gpg-agent.c (handle_connections): Increase the stack size ot 256k. + 2004-06-20 Moritz Schulte <moritz@g10code.com> * gpg-agent.c: Include <sys/stat.h> (build fix for BSD). diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 69a28e78b..f7e701bbc 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1158,7 +1158,7 @@ handle_connections (int listen_fd) tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); - pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024); pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent"); sigemptyset (&sigs ); diff --git a/agent/trustlist.c b/agent/trustlist.c index 16b7dc34e..a0b6b9861 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -32,15 +32,16 @@ #include <assuan.h> /* fixme: need a way to avoid assuan calls here */ static const char headerblurb[] = -"# This is the list of trusted keys. Comments like this one and empty\n" -"# lines are allowed but keep in mind that the entire file is integrity\n" +"# This is the list of trusted keys. Comment lines, like this one, as\n" +"# well as empty lines are ignored. The entire file may be integrity\n" "# protected by the use of a MAC, so changing the file does not make\n" -"# much sense without the knowledge of the MAC key. Lines do have a\n" -"# length limit but this is not serious limitation as the format of the\n" +"# sense without the knowledge of the MAC key. Lines do have a length\n" +"# limit but this is not serious limitation as the format of the\n" "# entries is fixed and checked by gpg-agent: A non-comment line starts\n" -"# with optional white spaces, followed by exactly 40 hex character,\n" -"# optioanlly followed by a flag character which my either be 'P', 'S'\n" -"# or '*'. Additional data delimited with by a white space is ignored.\n" +"# with optional white spaces, followed by the SHA-1 fingerpint in hex,\n" +"# optionally followed by a flag character which my either be 'P', 'S'\n" +"# or '*'. Additional data, delimited by white space, is ignored.\n" +"#\n" "# NOTE: You should give the gpg-agent a HUP after editing this file.\n" "\n"; @@ -97,7 +98,7 @@ static int read_list (char *key, int *keyflag) { int rc; - int c, i; + int c, i, j; char *p, line[256]; if (!trustfp) @@ -125,16 +126,17 @@ read_list (char *key, int *keyflag) : GPG_ERR_INCOMPLETE_LINE); } - /* Allow for emty lines and spaces */ + /* Allow for empty lines and spaces */ for (p=line; spacep (p); p++) ; } while (!*p || *p == '\n' || *p == '#'); - for (i=0; hexdigitp (p+i) && i < 40; i++) - key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i]; - key[i] = 0; - if (i!=40 || !(spacep (p+i) || p[i] == '\n')) + for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++) + if ( p[i] != ':' ) + key[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i]; + key[j] = 0; + if (j!=40 || !(spacep (p+i) || p[i] == '\n')) { log_error ("invalid formatted fingerprint in trustlist\n"); return gpg_error (GPG_ERR_BAD_DATA); diff --git a/configure.ac b/configure.ac index e0f9b720e..87c015033 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.10-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.10, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -1067,7 +1067,6 @@ if test "$have_libassuan" = "no"; then ***]]) fi if test "$have_ksba" = "no"; then - die=no AC_MSG_NOTICE([[ *** *** You need libksba to build this program. diff --git a/po/ChangeLog b/po/ChangeLog index 97e68c730..c1bcd81e1 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2004-07-22 Werner Koch <wk@g10code.de> + + * de.po: Updated. + 2004-04-06 Werner Koch <wk@gnupg.org> * Makevars (DOMAIN): Init from PACKAGE_GT diff --git a/po/de.po b/po/de.po index 2cf41ddb0..4dbe66e8a 100644 --- a/po/de.po +++ b/po/de.po @@ -8,17 +8,17 @@ # msgid "" msgstr "" -"Project-Id-Version: gnupg2 1.9.7\n" +"Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-04-29 19:50+0200\n" -"PO-Revision-Date: 2004-04-06 11:47+0200\n" +"POT-Creation-Date: 2004-07-22 09:54+0200\n" +"PO-Revision-Date: 2004-07-22 10:05+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:94 agent/protect-tool.c:92 scd/scdaemon.c:92 +#: agent/gpg-agent.c:96 agent/protect-tool.c:94 scd/scdaemon.c:92 msgid "" "@Options:\n" " " @@ -26,51 +26,59 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:96 scd/scdaemon.c:94 +#: agent/gpg-agent.c:98 scd/scdaemon.c:94 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:97 scd/scdaemon.c:95 +#: agent/gpg-agent.c:99 scd/scdaemon.c:95 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:98 kbx/kbxutil.c:73 scd/scdaemon.c:96 sm/gpgsm.c:312 +#: agent/gpg-agent.c:100 kbx/kbxutil.c:75 scd/scdaemon.c:96 sm/gpgsm.c:313 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:99 kbx/kbxutil.c:74 scd/scdaemon.c:97 sm/gpgsm.c:313 +#: agent/gpg-agent.c:101 kbx/kbxutil.c:76 scd/scdaemon.c:97 sm/gpgsm.c:314 msgid "be somewhat more quiet" msgstr "etwas weniger Aussageb erzeugen" -#: agent/gpg-agent.c:100 scd/scdaemon.c:98 +#: agent/gpg-agent.c:102 scd/scdaemon.c:98 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:101 scd/scdaemon.c:99 +#: agent/gpg-agent.c:103 scd/scdaemon.c:99 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" -#: agent/gpg-agent.c:102 +#: agent/gpg-agent.c:104 msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:107 scd/scdaemon.c:106 +#: agent/gpg-agent.c:109 scd/scdaemon.c:106 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:108 +#: agent/gpg-agent.c:110 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:109 scd/scdaemon.c:107 sm/gpgsm.c:315 +#: agent/gpg-agent.c:111 scd/scdaemon.c:107 sm/gpgsm.c:316 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:110 +#: agent/gpg-agent.c:112 msgid "do not allow multiple connections" msgstr "Nicht mehr als eine Verbindung erlauben" +#: agent/gpg-agent.c:115 +msgid "|PGM|use PGM as the PIN-Entry program" +msgstr "|PGM|benutze PGM as PIN-Entry" + +#: agent/gpg-agent.c:117 +msgid "|PGM|use PGM as the SCdaemon program" +msgstr "|PGM|benutze PGM as SCdaemon" + #: agent/gpg-agent.c:124 msgid "ignore requests to change the TTY" msgstr "Ignoriere Anfragen, das TTY zu wechseln" @@ -79,21 +87,33 @@ msgstr "Ignoriere Anfragen, das TTY zu wechseln" msgid "ignore requests to change the X display" msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:165 -#: sm/gpgsm.c:479 tools/gpgconf.c:85 +#: agent/gpg-agent.c:129 +msgid "|N|expire cached PINs after N seconds" +msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" + +#: agent/gpg-agent.c:131 +msgid "do not use the PIN cache when signing" +msgstr "benutze PINs im Cache nicht bem Signieren" + +#: agent/gpg-agent.c:133 +msgid "allow clients to mark keys as \"trusted\"" +msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" + +#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:165 +#: sm/gpgsm.c:481 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:180 agent/protect-tool.c:124 scd/scdaemon.c:165 -#: sm/gpgsm.c:479 tools/gpgconf.c:85 +#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:165 +#: sm/gpgsm.c:481 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:183 +#: agent/gpg-agent.c:194 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: agent/gpg-agent.c:185 +#: agent/gpg-agent.c:196 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -101,55 +121,55 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:256 scd/scdaemon.c:239 sm/gpgsm.c:602 +#: agent/gpg-agent.c:267 scd/scdaemon.c:239 sm/gpgsm.c:604 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:414 agent/protect-tool.c:1035 kbx/kbxutil.c:230 -#: scd/scdaemon.c:352 sm/gpgsm.c:725 +#: agent/gpg-agent.c:439 agent/protect-tool.c:1040 kbx/kbxutil.c:232 +#: scd/scdaemon.c:352 sm/gpgsm.c:726 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:487 scd/scdaemon.c:432 sm/gpgsm.c:823 +#: agent/gpg-agent.c:512 scd/scdaemon.c:432 sm/gpgsm.c:824 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:492 agent/gpg-agent.c:955 scd/scdaemon.c:437 -#: sm/gpgsm.c:827 +#: agent/gpg-agent.c:517 agent/gpg-agent.c:983 scd/scdaemon.c:437 +#: sm/gpgsm.c:828 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:500 scd/scdaemon.c:445 sm/gpgsm.c:834 +#: agent/gpg-agent.c:525 scd/scdaemon.c:445 sm/gpgsm.c:835 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:641 scd/scdaemon.c:619 +#: agent/gpg-agent.c:668 scd/scdaemon.c:619 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" -#: agent/gpg-agent.c:988 agent/gpg-agent.c:1022 +#: agent/gpg-agent.c:1016 agent/gpg-agent.c:1050 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: agent/gpg-agent.c:991 agent/gpg-agent.c:1027 +#: agent/gpg-agent.c:1019 agent/gpg-agent.c:1055 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/protect-tool.c:127 +#: agent/protect-tool.c:130 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" -#: agent/protect-tool.c:129 +#: agent/protect-tool.c:132 msgid "" "Syntax: gpg-protect-tool [options] [args]]\n" "Secret key maintenance tool\n" @@ -157,7 +177,7 @@ msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" "Werkzeug zum Bearbeiten von geheimen Schlsseln\n" -#: agent/protect-tool.c:1142 +#: agent/protect-tool.c:1148 msgid "" "Please enter the passphrase or the PIN\n" "needed to complete this operation." @@ -165,7 +185,7 @@ msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" "wird bentigt um diese Aktion auszufhren." -#: agent/protect-tool.c:1145 +#: agent/protect-tool.c:1151 msgid "Passphrase:" msgstr "Passphrase:" @@ -236,19 +256,19 @@ msgstr "Falsches Mantra (Passphrase)" msgid "Passphrase" msgstr "Mantra" -#: common/sysutils.c:84 +#: common/sysutils.c:87 #, c-format msgid "can't disable core dumps: %s\n" msgstr "" "Das Erstellen eines Speicherabzugs (core-dump) kann nicht verhindert werden: " "%s\n" -#: common/sysutils.c:159 +#: common/sysutils.c:182 #, c-format msgid "Warning: unsafe ownership on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Besitzrechte fr %s \"%s\"\n" -#: common/sysutils.c:191 +#: common/sysutils.c:214 #, c-format msgid "Warning: unsafe permissions on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" @@ -287,12 +307,12 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:547 +#: jnlib/logging.c:555 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:62 sm/gpgsm.c:223 tools/gpgconf.c:53 +#: kbx/kbxutil.c:63 sm/gpgsm.c:224 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -300,7 +320,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:68 sm/gpgsm.c:258 tools/gpgconf.c:59 +#: kbx/kbxutil.c:70 sm/gpgsm.c:259 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -310,39 +330,31 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:70 sm/gpgsm.c:260 -msgid "create ascii armored output" -msgstr "Ausgabe mit ASCII Hlle wird erzeugt" - -#: kbx/kbxutil.c:72 sm/gpgsm.c:311 tools/gpgconf.c:61 -msgid "use as output file" -msgstr "als Ausgabedatei benutzen" - -#: kbx/kbxutil.c:75 sm/gpgsm.c:320 tools/gpgconf.c:64 +#: kbx/kbxutil.c:77 sm/gpgsm.c:321 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" -#: kbx/kbxutil.c:77 +#: kbx/kbxutil.c:79 msgid "set debugging flags" msgstr "Debug Flags setzen" -#: kbx/kbxutil.c:78 +#: kbx/kbxutil.c:80 msgid "enable full debugging" msgstr "Alle Debug Flags setzen" -#: kbx/kbxutil.c:99 +#: kbx/kbxutil.c:101 msgid "Please report bugs to " msgstr "Bite richten sie Berichte ber Bugs (Softwarefehler) an " -#: kbx/kbxutil.c:99 +#: kbx/kbxutil.c:101 msgid ".\n" msgstr ".\n" -#: kbx/kbxutil.c:103 +#: kbx/kbxutil.c:105 msgid "Usage: kbxutil [options] [files] (-h for help)" msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h fr Hilfe)" -#: kbx/kbxutil.c:106 +#: kbx/kbxutil.c:108 msgid "" "Syntax: kbxutil [options] [files]\n" "list, export, import Keybox data\n" @@ -350,7 +362,7 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:100 sm/gpgsm.c:332 +#: scd/scdaemon.c:100 sm/gpgsm.c:333 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" @@ -523,8 +535,8 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" msgid "number of issuers matching: %d\n" msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:403 sm/certchain.c:561 sm/certchain.c:909 sm/decrypt.c:260 -#: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:107 +#: sm/certchain.c:403 sm/certchain.c:561 sm/certchain.c:912 sm/decrypt.c:260 +#: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" @@ -589,25 +601,25 @@ msgstr "Das Wurzelzertifikat wurde nun als vertrauensw msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:721 sm/import.c:145 +#: sm/certchain.c:724 sm/import.c:166 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:733 +#: sm/certchain.c:736 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:766 +#: sm/certchain.c:769 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:789 +#: sm/certchain.c:792 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:812 +#: sm/certchain.c:815 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" @@ -660,227 +672,235 @@ msgstr "Schwacher Schl msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:225 +#: sm/gpgsm.c:226 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:226 +#: sm/gpgsm.c:227 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:227 +#: sm/gpgsm.c:228 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:228 +#: sm/gpgsm.c:229 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:229 +#: sm/gpgsm.c:230 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:230 +#: sm/gpgsm.c:231 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:231 +#: sm/gpgsm.c:232 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:233 +#: sm/gpgsm.c:234 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:234 +#: sm/gpgsm.c:235 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:235 +#: sm/gpgsm.c:236 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:236 +#: sm/gpgsm.c:237 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:238 +#: sm/gpgsm.c:239 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:240 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:240 +#: sm/gpgsm.c:241 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:242 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:243 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:244 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:245 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:246 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:246 +#: sm/gpgsm.c:247 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:248 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:249 +#: sm/gpgsm.c:250 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:251 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:262 +#: sm/gpgsm.c:261 +msgid "create ascii armored output" +msgstr "Ausgabe mit ASCII Hlle wird erzeugt" + +#: sm/gpgsm.c:263 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:264 +#: sm/gpgsm.c:265 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:266 +#: sm/gpgsm.c:267 msgid "assume input is in base-64 format" msgstr "Eingabedaten sin im Basis-64 Format" -#: sm/gpgsm.c:268 +#: sm/gpgsm.c:269 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:270 +#: sm/gpgsm.c:271 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:273 +#: sm/gpgsm.c:274 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:278 +#: sm/gpgsm.c:279 msgid "check validity using OCSP" msgstr "Die Gltigkeit mittels OCSP prfen" -#: sm/gpgsm.c:281 +#: sm/gpgsm.c:282 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:284 +#: sm/gpgsm.c:285 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:287 +#: sm/gpgsm.c:288 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:291 +#: sm/gpgsm.c:292 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:295 +#: sm/gpgsm.c:296 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:297 +#: sm/gpgsm.c:298 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:303 +#: sm/gpgsm.c:304 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:306 +#: sm/gpgsm.c:307 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:308 +#: sm/gpgsm.c:309 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:314 +#: sm/gpgsm.c:312 tools/gpgconf.c:61 +msgid "use as output file" +msgstr "als Ausgabedatei benutzen" + +#: sm/gpgsm.c:315 msgid "don't use the terminal at all" msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:317 +#: sm/gpgsm.c:318 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:318 +#: sm/gpgsm.c:319 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:323 +#: sm/gpgsm.c:324 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:324 +#: sm/gpgsm.c:325 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:325 +#: sm/gpgsm.c:326 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:327 +#: sm/gpgsm.c:328 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:328 +#: sm/gpgsm.c:329 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:329 +#: sm/gpgsm.c:330 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:330 +#: sm/gpgsm.c:331 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:331 +#: sm/gpgsm.c:332 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:340 +#: sm/gpgsm.c:342 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:347 +#: sm/gpgsm.c:349 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:353 +#: sm/gpgsm.c:355 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verhsclsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:355 +#: sm/gpgsm.c:357 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:357 +#: sm/gpgsm.c:359 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:365 +#: sm/gpgsm.c:367 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -888,7 +908,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:368 +#: sm/gpgsm.c:370 msgid "" "@\n" "Examples:\n" @@ -908,11 +928,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:482 +#: sm/gpgsm.c:484 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:485 +#: sm/gpgsm.c:487 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -921,7 +941,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:492 +#: sm/gpgsm.c:494 msgid "" "\n" "Supported algorithms:\n" @@ -929,129 +949,144 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:573 +#: sm/gpgsm.c:575 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:639 +#: sm/gpgsm.c:641 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:655 +#: sm/gpgsm.c:657 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:730 +#: sm/gpgsm.c:731 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1169 +#: sm/gpgsm.c:1175 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1181 +#: sm/gpgsm.c:1187 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1201 +#: sm/gpgsm.c:1213 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1209 +#: sm/gpgsm.c:1221 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1239 +#: sm/gpgsm.c:1251 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1406 +#: sm/gpgsm.c:1415 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1629 sm/gpgsm.c:1662 +#: sm/gpgsm.c:1638 sm/gpgsm.c:1671 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" -#: sm/import.c:114 +#: sm/import.c:118 #, c-format msgid "total number processed: %lu\n" msgstr "gesamte verarbeitete Anzahl: %lu\n" -#: sm/import.c:117 +#: sm/import.c:121 #, c-format msgid " imported: %lu" msgstr " importiert: %lu" -#: sm/import.c:121 +#: sm/import.c:125 #, c-format msgid " unchanged: %lu\n" msgstr " nicht gendert: %lu\n" -#: sm/import.c:123 +#: sm/import.c:127 +#, c-format +msgid " secret keys read: %lu\n" +msgstr " gelesene private Schlssel: %lu\n" + +#: sm/import.c:129 +#, c-format +msgid " secret keys imported: %lu\n" +msgstr "importierte priv. Schlssel: %lu\n" + +#: sm/import.c:131 +#, c-format +msgid " secret keys unchanged: %lu\n" +msgstr "ungenderte priv. Schlssel: %lu\n" + +#: sm/import.c:133 #, c-format msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: sm/import.c:204 +#: sm/import.c:229 msgid "error storing certificate\n" msgstr "Fehler beim speichern des Zertifikats\n" -#: sm/import.c:211 +#: sm/import.c:237 msgid "basic certificate checks failed - not imported\n" msgstr "Grundlegende Zertifikatprfungen fehlgeschlagen - nicht importiert\n" -#: sm/import.c:396 sm/import.c:428 +#: sm/import.c:423 sm/import.c:455 #, c-format msgid "error importing certificate: %s\n" msgstr "Fehler beim Importieren des Zertifikats: %s\n" -#: sm/import.c:457 +#: sm/import.c:484 #, c-format msgid "error creating a pipe: %s\n" msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" -#: sm/import.c:465 +#: sm/import.c:492 #, c-format msgid "error forking process: %s\n" msgstr "Fehler beim \"Forken\" des Prozess: %s\n" -#: sm/import.c:562 sm/import.c:587 +#: sm/import.c:590 sm/import.c:615 #, c-format msgid "error creating temporary file: %s\n" msgstr "Fehler beim Erstellen einer temporren Datei: %s\n" -#: sm/import.c:570 +#: sm/import.c:598 #, c-format msgid "error writing to temporary file: %s\n" msgstr "Fehler beim Schreiben auf eine temporre Datei: %s\n" -#: sm/import.c:579 +#: sm/import.c:607 #, c-format msgid "error reading input: %s\n" msgstr "Fehler beim Lesen der Eingabe: %s\n" -#: sm/import.c:649 +#: sm/import.c:703 #, c-format msgid "waiting for protect-tool to terminate failed: %s\n" msgstr "" "Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" -#: sm/import.c:652 +#: sm/import.c:706 #, c-format msgid "error running `%s': probably not installed\n" msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" -#: sm/import.c:654 +#: sm/import.c:708 #, c-format msgid "error running `%s': exit status %d\n" msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" -#: sm/import.c:657 +#: sm/import.c:711 #, c-format msgid "error running `%s': terminated\n" msgstr "Fehler beim Ausfhren von `%s': beendet\n" @@ -1113,24 +1148,24 @@ msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" msgid "error storing flags: %s\n" msgstr "Fehler beim Speichern der Flags: %s\n" -#: sm/verify.c:387 +#: sm/verify.c:381 msgid "Signature made " msgstr "Signatur erzeugt am " -#: sm/verify.c:391 +#: sm/verify.c:385 msgid "[date not given]" msgstr "[Datum nicht vorhanden]" -#: sm/verify.c:392 +#: sm/verify.c:386 #, c-format msgid " using certificate ID %08lX\n" msgstr "mittels Zertifikat ID %08lX\n" -#: sm/verify.c:505 +#: sm/verify.c:499 msgid "Good signature from" msgstr "Korrekte Signatur von" -#: sm/verify.c:506 +#: sm/verify.c:500 msgid " aka" msgstr " alias" @@ -1188,6 +1223,3 @@ msgstr "Komponente nicht gefunden" #~ msgstr "" #~ "Schlsselverwendungszweck nicht vorhanden - wird zum Verschlsseln " #~ "akzeptiert\n" - -#~ msgid " skipped new keys: %lu\n" -#~ msgstr " bersprungene Schlssel: %lu\n" diff --git a/scd/ChangeLog b/scd/ChangeLog index 1d3cff257..3a634b92b 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-07-22 Werner Koch <wk@g10code.de> + + * scdaemon.c (main): Bumbed thread stack size up to 512k. + 2004-07-16 Werner Koch <wk@gnupg.org> * apdu.c (reader_table_s): Add function pointers for the backends. diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 5e9737ae4..b0038de16 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -603,7 +603,7 @@ main (int argc, char **argv ) tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); - pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); pth_attr_set (tattr, PTH_ATTR_NAME, "ticker"); if (!pth_spawn (tattr, ticker_thread, NULL)) diff --git a/sm/ChangeLog b/sm/ChangeLog index 5571540be..b9780cc90 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-07-22 Werner Koch <wk@g10code.de> + + * keylist.c (list_cert_raw): Print the keygrip. + 2004-07-20 Werner Koch <wk@gnupg.org> * certchain.c (gpgsm_validate_chain): The trust check didn't diff --git a/sm/keylist.c b/sm/keylist.c index 27c67ded3..0fd06ca13 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -500,7 +500,7 @@ print_names_raw (FILE *fp, int indent, ksba_name_t name) /* List one certificate in raw mode useful to have a closer look at - the certificate. This one does not beautification and only minimal + the certificate. This one does no beautification and only minimal output sanitation. It is mainly useful for debugging. */ static void list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, @@ -559,6 +559,10 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, fprintf (fp, " md5_fpr: %s\n", dn?dn:"error"); xfree (dn); + dn = gpgsm_get_keygrip_hexstring (cert); + fprintf (fp, " keygrip: %s\n", dn?dn:"error"); + xfree (dn); + ksba_cert_get_validity (cert, 0, t); fputs (" notBefore: ", fp); gpgsm_print_time (fp, t); -- cgit v1.2.3 From 44bf2d0ae4adbcf5b6b404bfc6526c461ae6a92a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 22 Jul 2004 10:52:56 +0000 Subject: * configure.ac: Define AM conditional HAVE_OPENSC. * Makefile.am: Make OpenSC lib link after libgcrypt. Do not link to pth. * apdu.c: Don't use Pth if we use OpenSC. * sc-investigate.c, scdaemon.c: Disable use of pth if OpenSC is used. * scdaemon.c (main): Bumbed thread stack size up to 512k. --- ChangeLog | 2 ++ configure.ac | 1 + scd/ChangeLog | 5 +++++ scd/Makefile.am | 21 ++++++++++++++------- scd/apdu.c | 4 ++++ scd/sc-investigate.c | 11 +++++++---- scd/scdaemon.c | 9 ++++++++- 7 files changed, 41 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42fe782af..d83d94cde 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ Released 1.9.10. + * configure.ac: Define AM conditional HAVE_OPENSC. + 2004-07-21 Werner Koch <wk@g10code.de> * configure.ac: Don't set DIE to no after it might has been set to diff --git a/configure.ac b/configure.ac index 87c015033..94760f529 100644 --- a/configure.ac +++ b/configure.ac @@ -471,6 +471,7 @@ if test $have_opensc = yes; then AC_DEFINE(HAVE_OPENSC,1, [defined if the OpenSC library is available]) fi +AM_CONDITIONAL(HAVE_OPENSC, test "$have_opensc" = "yes") # # Check whether the (highly desirable) GNU Pth library is available diff --git a/scd/ChangeLog b/scd/ChangeLog index 3a634b92b..cb759c0b2 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,10 @@ 2004-07-22 Werner Koch <wk@g10code.de> + * Makefile.am: Make OpenSC lib link after libgcrypt. Do not link + to pth. + * apdu.c: Don't use Pth if we use OpenSC. + * sc-investigate.c, scdaemon.c: Disable use of pth if OpenSC is used. + * scdaemon.c (main): Bumbed thread stack size up to 512k. 2004-07-16 Werner Koch <wk@gnupg.org> diff --git a/scd/Makefile.am b/scd/Makefile.am index c3c603d28..e3dfbf0b6 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -25,6 +25,13 @@ AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am +# avoid linking against Pth if we are using OpenSC. +if HAVE_OPENSC +pth_libs = +else +pth_libs = $(PTH_LIBS) +endif + AM_CFLAGS = $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) @@ -44,9 +51,9 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(PTH_LIBS) \ + $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) -lgpg-error @INTLLIBS@ -ldl + $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @INTLLIBS@ -ldl sc_investigate_SOURCES = \ sc-investigate.c scdaemon.h \ @@ -59,8 +66,8 @@ sc_investigate_SOURCES = \ sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(PTH_LIBS) \ - $(KSBA_LIBS) $(LIBUSB_LIBS) \ + $(LIBGCRYPT_LIBS) $(pth_libs) \ + $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ @INTLLIBS@ -lgpg-error -ldl @@ -76,10 +83,10 @@ sc_copykeys_SOURCES = \ sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(PTH_LIBS) \ - $(KSBA_LIBS) $(LIBUSB_LIBS) \ + $(LIBGCRYPT_LIBS) $(pth_libs) \ + $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ -lgpg-error @INTLLIBS@ -ldl pcsc_wrapper_SOURCES = pcsc-wrapper.c pcsc_wrapper_LDADD = -ldl -pcsc_wrapper_CFLAGS = \ No newline at end of file +pcsc_wrapper_CFLAGS = diff --git a/scd/apdu.c b/scd/apdu.c index cc9b213fb..28d32ad2c 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -19,6 +19,7 @@ */ #include <config.h> + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -31,6 +32,9 @@ #endif #ifdef HAVE_OPENSC # include <opensc/opensc.h> +# ifdef USE_GNU_PTH +# undef USE_GNU_PTH +# endif #endif /* If requested include the definitions for the remote APDU protocol diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index be985533c..8d34ab77e 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -90,12 +90,12 @@ static ARGPARSE_OPTS opts[] = { {0} }; - +#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; #endif /*USE_GNU_PTH*/ - +#endif /*!HAVE_OPENSC*/ static void interactive_shell (int slot); static void dump_other_cards (int slot); @@ -160,8 +160,10 @@ main (int argc, char **argv ) /* Try to auto set the character set. */ set_native_charset (NULL); - /* Libgcrypt requires us to register the threading model first. - Note that this will also do the pth_init. */ + /* Libgcrypt requires us to register the threading model first. We + can't use pth at all if we are using OpenSC becuase OpenSC uses + ptreads. Note that this will also do the pth_init. */ +#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH rc = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (rc) @@ -170,6 +172,7 @@ main (int argc, char **argv ) gpg_strerror (rc)); } #endif /*USE_GNU_PTH*/ +#endif /*!HAVE_OPENSC*/ /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ diff --git a/scd/scdaemon.c b/scd/scdaemon.c index b0038de16..f647aecc2 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -144,13 +144,14 @@ static int maybe_setuid = 1; static char socket_name[128]; +#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; static void *ticker_thread (void *arg); #endif /*USE_GNU_PTH*/ - +#endif /*!HAVE_OPENSC*/ static const char * my_strusage (int level) @@ -336,6 +337,7 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ +#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) @@ -344,6 +346,7 @@ main (int argc, char **argv ) gpg_strerror (err)); } #endif /*USE_GNU_PTH*/ +#endif /*!HAVE_OPENSC*/ /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ @@ -598,6 +601,7 @@ main (int argc, char **argv ) if (pipe_server) { /* This is the simple pipe based server */ +#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH pth_attr_t tattr; @@ -612,6 +616,7 @@ main (int argc, char **argv ) scd_exit (2); } #endif /*USE_GNU_PTH*/ +#endif /*!HAVE_OPENSC*/ scd_command_handler (-1); } else if (!is_daemon) @@ -827,6 +832,7 @@ scd_init_default_ctrl (CTRL ctrl) } +#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH static void @@ -931,3 +937,4 @@ ticker_thread (void *dummy_arg) pth_event_free (sigs_ev, PTH_FREE_ALL); } #endif /*USE_GNU_PTH*/ +#endif /*!HAVE_OPENSC*/ -- cgit v1.2.3 From 8e237f5b09a035d65aa3ff33a055292a51ae57dc Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 22 Jul 2004 11:40:17 +0000 Subject: post-release version number bump --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 74250b04a..df35b570e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.11 +------------------------------------------------- + + Noteworthy changes in version 1.9.10 (2004-07-22) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 94760f529..bc9f9663d 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.10, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.11-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 97e9cb4e6087a9b0240be6df6c160f5e5bf02adf Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Tue, 27 Jul 2004 11:28:10 +0000 Subject: 2004-07-27 Moritz Schulte <moritz@g10code.com> * configure.ac: Check for dlopen in libc and libdl, substitute DL_LIBS accordingly. --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index bc9f9663d..ca6eaf14f 100644 --- a/configure.ac +++ b/configure.ac @@ -461,6 +461,13 @@ AC_CHECK_LIB(usb, usb_find_device, ]) AC_SUBST(LIBUSB_LIBS) +# +# Check wether it is necessary to link against libdl. +# +LIBS="" +AC_SEARCH_LIBS(dlopen, c dl,,,) +DL_LIBS=$LIBS +AC_SUBST(DL_LIBS) # # OpenSC is needed by the SCdaemon - if it is not availbale we can only -- cgit v1.2.3 From 9d36000e6fea8e91d54dd176a9b3eed9b3b811bc Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Tue, 27 Jul 2004 11:28:47 +0000 Subject: 2004-07-27 Moritz Schulte <moritz@g10code.com> * Makefile.am: Use @DL_LIBS@ instead of -ldl. --- scd/Makefile.am | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scd/Makefile.am b/scd/Makefile.am index e3dfbf0b6..5c49ee6f9 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -53,7 +53,8 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @INTLLIBS@ -ldl + $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @INTLLIBS@ \ + @DL_LIBS@ sc_investigate_SOURCES = \ sc-investigate.c scdaemon.h \ @@ -68,7 +69,7 @@ sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ - @INTLLIBS@ -lgpg-error -ldl + @INTLLIBS@ -lgpg-error @DL_LIBS@ sc_copykeys_SOURCES = \ @@ -85,8 +86,8 @@ sc_copykeys_LDADD = \ ../common/libsimple-pwquery.a \ $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ - -lgpg-error @INTLLIBS@ -ldl + -lgpg-error @INTLLIBS@ @DL_LIBS@ pcsc_wrapper_SOURCES = pcsc-wrapper.c -pcsc_wrapper_LDADD = -ldl +pcsc_wrapper_LDADD = @DL_LIBS@ pcsc_wrapper_CFLAGS = -- cgit v1.2.3 From 587222f48d0fc64d967ebb1ff3dece97a95181fe Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Tue, 27 Jul 2004 11:35:52 +0000 Subject: 2004-07-27 Moritz Schulte <moritz@g10code.com> * apdu.c: Include <signal.h>. --- scd/ChangeLog | 6 ++++++ scd/apdu.c | 1 + 2 files changed, 7 insertions(+) diff --git a/scd/ChangeLog b/scd/ChangeLog index cb759c0b2..b0f07dc82 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2004-07-27 Moritz Schulte <moritz@g10code.com> + + * apdu.c: Include <signal.h>. + + * Makefile.am: Use @DL_LIBS@ instead of -ldl. + 2004-07-22 Werner Koch <wk@g10code.de> * Makefile.am: Make OpenSC lib link after libgcrypt. Do not link diff --git a/scd/apdu.c b/scd/apdu.c index 28d32ad2c..7898452c4 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <signal.h> #ifdef USE_GNU_PTH # include <pth.h> # include <unistd.h> -- cgit v1.2.3 From 818e9bad581868f8455a62fb3548b4dcc9d4cbac Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 5 Aug 2004 09:24:36 +0000 Subject: * configure.ac: Changed tests for libusb to also suuport the stable version 0.1.x. * scdaemon.texi (Card applications): New section. * scdaemon.c (main): New option --disable-application. * app.c (is_app_allowed): New. (select_application): Use it to check for disabled applications. * ccid-driver.h (CCID_DRIVER_ERR_ABORTED): New. * ccid-driver.c (ccid_open_reader): Support the stable 0.1 version of libusb. (ccid_get_atr): Handle short messages. * apdu.c (my_rapdu_get_status): Implemented. --- ChangeLog | 5 +++ TODO | 22 +++++++++++ configure.ac | 6 +-- doc/ChangeLog | 4 ++ doc/scdaemon.texi | 57 ++++++++++++++++++++++++++- scd/ChangeLog | 13 +++++++ scd/apdu.c | 39 ++++++++++++++++++- scd/apdu.h | 3 +- scd/app.c | 19 +++++++-- scd/ccid-driver.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++------ scd/ccid-driver.h | 2 +- scd/iso7816.c | 1 + scd/scdaemon.c | 6 +++ scd/scdaemon.h | 2 + sm/ChangeLog | 5 +++ sm/certreqgen.c | 15 +++---- 16 files changed, 282 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index d83d94cde..7b14b7944 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-08-05 Werner Koch <wk@g10code.de> + + * configure.ac: Changed tests for libusb to also suuport the + stable version 0.1.x. + 2004-07-22 Werner Koch <wk@g10code.de> Released 1.9.10. diff --git a/TODO b/TODO index ce835d8ec..6e5c8cfb8 100644 --- a/TODO +++ b/TODO @@ -79,3 +79,25 @@ might want to have an agent context for each service request * doc/ ** Explain how to setup a root CA key as trusted ** Explain how trustlist.txt might be managed. + + +* Requirements by the BSI +** Support authorityKeyIdentifier.keyIdentifier + This needs support in libksba/src/cert.c as well as in sm/*.c. + Need test certs as well. Same goes for CRL authorityKeyIdentifier. + +** For pkcs#10 request header. + We use "NEW CERTIFICATE REQUEST" the specs say "CERTIFICATE + REQUEST" should be used. However it seems that their CA software + is also able to use our header. Binary pkcs#10 request are not + allowed. + +** Dirmngr: name subordination (nameRelativeToCRLIssuer) + is not yet supported by Dirmngr. + +** Dirmngr: CRL DP URI + The CRL DP shall use an URI for LDAP without a host name. The host + name shall be looked by using the DN in the URI. We don't implement + this yet. Solution is to have a mapping DN->host in our ldapservers + configuration file. + diff --git a/configure.ac b/configure.ac index ca6eaf14f..f34faf469 100644 --- a/configure.ac +++ b/configure.ac @@ -451,15 +451,13 @@ AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) # # libusb allows us to use the integrated CCID smartcard reader driver. # -# Note, that we need the CVS version. FIXME: libusb should have a -# regular check as the other libraries do. -# -AC_CHECK_LIB(usb, usb_find_device, +AC_CHECK_LIB(usb, usb_bulk_write, [ LIBUSB_LIBS="$LIBUSB_LIBS -lusb" AC_DEFINE(HAVE_LIBUSB,1, [defined if libusb is available]) ]) AC_SUBST(LIBUSB_LIBS) +AC_CHECK_FUNCS(usb_create_match) # # Check wether it is necessary to link against libdl. diff --git a/doc/ChangeLog b/doc/ChangeLog index 1760695be..79a8c9532 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2004-08-05 Werner Koch <wk@g10code.de> + + * scdaemon.texi (Card applications): New section. + 2004-06-22 Werner Koch <wk@g10code.com> * glossary.texi: New. diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 51ec4b34c..3e11a8930 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -10,7 +10,7 @@ @c man begin DESCRIPTION -The @sc{scdaeon} is a daemon to manage smartcards. It is usually +The @sc{scdaemon} is a daemon to manage smartcards. It is usually invoked by gpg-agent and in general not used directly. @c man end @@ -20,6 +20,7 @@ invoked by gpg-agent and in general not used directly. @menu * Scdaemon Commands:: List of all commands. * Scdaemon Options:: List of all options. +* Card applications:: Description of card applications. * Scdaemon Examples:: Some usage examples. * Scdaemon Protocol:: The protocol the daemon uses. @end menu @@ -176,18 +177,70 @@ is @code{libtowitoko.so}. @itemx --deny-admin @opindex allow-admin @opindex deny-admin -This enables the use of Admin class commands for card application +This enables the use of Admin class commands for card applications 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. +@item --disable-application @var{name} +@opindex disable-application +This option disables the use of the card application named +@var{name}. This is mainly useful for debugging or if a application +with lower priority should be used by default. + @end table All the long options may also be given in the configuration file after stripping off the two leading dashes. +@c man begin CARD APPLICATIONS + +@node Card applications +@section Description of card applications + +@sc{scdaemon} supports the card applications as described below. + +@menu +* OpenPGP Card:: The OpenPGP card application +* NKS Card:: The Telesec NetKey card application +* DINSIG Card:: The DINSIG card application +* PKCS#15 Card:: The PKCS#15 card application +@end menu + +@node OpenPGP Card +@subsection The OpenPGP card application ``openpgp'' + +This application is currently only used by @sc{gpg} but may in +future also be useful with @sc{gpgsm}. + +The specification for such a card is available at +@uref{http://g10code.com/docs/openpgp-card-1.0.pdf}. + +@node NKS Card +@subsection The Telesec NetKey card ``nks'' + +This is the main application of the Telesec cards as available in +Germany. It is a superset of the German DINSIG card. The card is +used by @sc{gpgsm}. + +@node DINSIG Card +@subsection The DINSIG card application ``dinsig'' + +This is an application as described in the German draft standard +@emph{DIN V 66291-1}. It is intended to be used by cards supporteing +the German signature law and its bylaws (SigG and SigV). + +@node PKCS#15 Card +@subsection The PKCS#15 card application ``p15'' + +This is common fraqmework for smart card applications; support is only +available if compiled with support for the OpenSC library. It is used +by @sc{gpgsm}. + + + @c @c Examples @c diff --git a/scd/ChangeLog b/scd/ChangeLog index b0f07dc82..80b244ef1 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,16 @@ +2004-08-05 Werner Koch <wk@g10code.de> + + * scdaemon.c (main): New option --disable-application. + * app.c (is_app_allowed): New. + (select_application): Use it to check for disabled applications. + + * ccid-driver.h (CCID_DRIVER_ERR_ABORTED): New. + * ccid-driver.c (ccid_open_reader): Support the stable 0.1 version + of libusb. + (ccid_get_atr): Handle short messages. + + * apdu.c (my_rapdu_get_status): Implemented. + 2004-07-27 Moritz Schulte <moritz@g10code.com> * apdu.c: Include <signal.h>. diff --git a/scd/apdu.c b/scd/apdu.c index 7898452c4..5f800c983 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -19,7 +19,6 @@ */ #include <config.h> - #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -296,6 +295,7 @@ host_sw_string (long err) case SW_HOST_CARD_IO_ERROR: return "card I/O error"; case SW_HOST_GENERAL_ERROR: return "general error"; case SW_HOST_NO_READER: return "no reader"; + case SW_HOST_ABORTED: return "aborted"; default: return "unknown host status error"; } } @@ -1633,7 +1633,42 @@ reset_rapdu_reader (int slot) static int my_rapdu_get_status (int slot, unsigned int *status) { - return SW_HOST_NOT_SUPPORTED; + int err; + reader_table_t slotp; + rapdu_msg_t msg = NULL; + int oldslot; + + slotp = reader_table + slot; + + oldslot = rapdu_set_reader (slotp->rapdu.handle, slot); + err = rapdu_send_cmd (slotp->rapdu.handle, RAPDU_CMD_GET_STATUS); + rapdu_set_reader (slotp->rapdu.handle, oldslot); + if (err) + { + log_error ("sending rapdu command GET_STATUS failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + return rapdu_status_to_sw (err); + } + err = rapdu_read_msg (slotp->rapdu.handle, &msg); + if (err) + { + log_error ("receiving rapdu message failed: %s\n", + err < 0 ? strerror (errno): rapdu_strerror (err)); + rapdu_msg_release (msg); + return rapdu_status_to_sw (err); + } + if (msg->cmd != RAPDU_STATUS_SUCCESS || !msg->datalen) + { + int sw = rapdu_status_to_sw (msg->cmd); + log_error ("rapdu command GET_STATUS failed: %s\n", + rapdu_strerror (msg->cmd)); + rapdu_msg_release (msg); + return sw; + } + *status = msg->data[0]; + + rapdu_msg_release (msg); + return 0; } diff --git a/scd/apdu.h b/scd/apdu.h index a2b781266..a0654a242 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -58,7 +58,8 @@ enum { SW_HOST_CARD_INACTIVE = 0x10009, SW_HOST_CARD_IO_ERROR = 0x1000a, SW_HOST_GENERAL_ERROR = 0x1000b, - SW_HOST_NO_READER = 0x1000c + SW_HOST_NO_READER = 0x1000c, + SW_HOST_ABORTED = 0x1000d }; diff --git a/scd/app.c b/scd/app.c index a9a9243eb..b3a13f19a 100644 --- a/scd/app.c +++ b/scd/app.c @@ -32,6 +32,19 @@ #include "tlv.h" +/* Check wether the application NAME is allowed. This does not mean + we have support for it though. */ +static int +is_app_allowed (const char *name) +{ + strlist_t l; + + for (l=opt.disabled_applications; l; l = l->next) + if (!strcmp (l->d, name)) + return 0; /* no */ + return 1; /* yes */ +} + /* If called with NAME as NULL, select the best fitting application and return a context; otherwise select the application with NAME and return a context. SLOT identifies the reader device. Returns @@ -84,11 +97,11 @@ select_application (ctrl_t ctrl, int slot, const char *name) rc = gpg_error (GPG_ERR_NOT_FOUND); - if (!name || !strcmp (name, "openpgp")) + if (rc && is_app_allowed ("openpgp") && (!name || !strcmp (name, "openpgp"))) rc = app_select_openpgp (app); - if (rc && (!name || !strcmp (name, "nks"))) + if (rc && is_app_allowed ("nks") && (!name || !strcmp (name, "nks"))) rc = app_select_nks (app); - if (rc && (!name || !strcmp (name, "dinsig"))) + if (rc && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) rc = app_select_dinsig (app); if (rc && name) rc = gpg_error (GPG_ERR_NOT_SUPPORTED); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 4751b8cdb..0fc168590 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -412,7 +412,13 @@ read_device_info (ccid_driver_t handle, struct usb_device *dev) { int cfg_no; - for (cfg_no=0; cfg_no < dev->descriptor->bNumConfigurations; cfg_no++) + for (cfg_no=0; cfg_no < +#ifdef HAVE_USB_CREATE_MATCH + dev->descriptor->bNumConfigurations +#else + dev->descriptor.bNumConfigurations +#endif + ; cfg_no++) { struct usb_config_descriptor *config = dev->config + cfg_no; int ifc_no; @@ -451,8 +457,9 @@ read_device_info (ccid_driver_t handle, struct usb_device *dev) int ccid_open_reader (ccid_driver_t *handle, int readerno) { +#ifdef HAVE_USB_CREATE_MATCH + /* This is the development version of libusb. */ static int initialized; - int rc; usb_match_handle *match = NULL; struct usb_device *dev = NULL; @@ -471,7 +478,7 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) DEBUGOUT_1 ("usb_create_match failed: %d\n", rc); return CCID_DRIVER_ERR_NO_READER; } - + while (usb_find_device(match, dev, &dev) >= 0) { DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, @@ -530,7 +537,6 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) readerno--; } - leave: if (idev) usb_close (idev); @@ -542,6 +548,96 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) rc = -1; /* In case we didn't enter the while loop at all. */ return rc; +#else /* Stable 0.1 version of libusb. */ + static int initialized; + int rc = 0; + struct usb_bus *busses, *bus; + struct usb_device *dev = NULL; + usb_dev_handle *idev = NULL; + + *handle = NULL; + if (!initialized) + { + usb_init (); + initialized = 1; + } + + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, + dev->descriptor.idVendor, dev->descriptor.idProduct); + + if (!readerno) + { + *handle = calloc (1, sizeof **handle); + if (!*handle) + { + DEBUGOUT ("out of memory\n"); + rc = CCID_DRIVER_ERR_OUT_OF_CORE; + free (*handle); + *handle = NULL; + goto leave; + } + + rc = read_device_info (*handle, dev); + if (rc) + { + DEBUGOUT ("device not supported\n"); + free (*handle); + *handle = NULL; + continue; + } + + idev = usb_open (dev); + if (!idev) + { + DEBUGOUT_1 ("usb_open failed: %s\n", strerror (errno)); + free (*handle); + *handle = NULL; + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } + + /* fixme: Do we need to claim and set the interface as + determined by read_device_info ()? */ + rc = usb_claim_interface (idev, 0); + if (rc) + { + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + free (*handle); + *handle = NULL; + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } + + (*handle)->idev = idev; + idev = NULL; + /* FIXME: Do we need to get the endpoint addresses from the + structure and store them with the handle? */ + + goto leave; /* ready. */ + } + readerno--; + } + } + + leave: + if (idev) + usb_close (idev); + /* fixme: Do we need to release dev or is it supposed to be a + shallow copy of the list created internally by usb_init ? */ + + if (!rc && !*handle) + rc = -1; /* In case we didn't enter the while loop at all. */ + + return rc; +#endif /* Stable version 0.1 of libusb. */ } @@ -894,10 +990,7 @@ ccid_get_atr (ccid_driver_t handle, tpdulen = msglen - 10; if (tpdulen < 4) - { - DEBUGOUT ("cannot yet handle short blocks!\n"); - return -1; - } + return CCID_DRIVER_ERR_ABORTED; #ifdef DEBUG_T1 fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", @@ -1092,10 +1185,9 @@ ccid_transceive (ccid_driver_t handle, if (tpdulen < 4) { - DEBUGOUT ("cannot yet handle short blocks!\n"); - return CCID_DRIVER_ERR_NOT_SUPPORTED; + usb_clear_halt (handle->idev, 0x82); + return CCID_DRIVER_ERR_ABORTED; } - #ifdef DEBUG_T1 fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", ((msg[11] & 0xc0) == 0x80)? 'R' : diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 0b108f16d..0cb52e1c3 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -70,7 +70,7 @@ #define CCID_DRIVER_ERR_CARD_IO_ERROR 0x1000a #define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b #define CCID_DRIVER_ERR_NO_READER 0x1000c - +#define CCID_DRIVER_ERR_ABORTED 0x1000d struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; diff --git a/scd/iso7816.c b/scd/iso7816.c index d5db607f8..cbb314eb2 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -90,6 +90,7 @@ map_sw (int sw) case SW_HOST_CARD_IO_ERROR: ec = GPG_ERR_EIO; break; case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break; case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break; + case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break; default: if ((sw & 0x010000)) diff --git a/scd/scdaemon.c b/scd/scdaemon.c index f647aecc2..b54a63816 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -80,6 +80,7 @@ enum cmd_and_opt_values oDisableOpenSC, oAllowAdmin, oDenyAdmin, + oDisableApplication, aTest }; @@ -124,6 +125,7 @@ static ARGPARSE_OPTS opts[] = { /* end --disable-opensc */}, { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")}, { oDenyAdmin, "deny-admin", 0, "@" }, + { oDisableApplication, "disable-application", 2, "@"}, {0} }; @@ -493,6 +495,10 @@ main (int argc, char **argv ) case oAllowAdmin: opt.allow_admin = 1; break; case oDenyAdmin: opt.allow_admin = 0; break; + case oDisableApplication: + add_to_strlist (&opt.disabled_applications, pargs.r.ret_str); + break; + default : pargs.err = configfp? 1:2; break; } } diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 1dd32ae90..c8d78c88b 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -52,6 +52,8 @@ struct { int disable_ccid; /* Disable the use of the internal CCID driver. */ int allow_admin; /* Allow the use of admin commands for certain cards. */ + strlist_t disabled_applications; /* card applications we do not + want to use. */ } opt; diff --git a/sm/ChangeLog b/sm/ChangeLog index b9780cc90..b21a5faff 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-07-23 Werner Koch <wk@g10code.de> + + * certreqgen.c (proc_parameters): Do not allow key length below + 1024. + 2004-07-22 Werner Koch <wk@g10code.de> * keylist.c (list_cert_raw): Print the keygrip. diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 969ed14b0..ab1f539de 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -444,7 +444,7 @@ proc_parameters (ctrl_t ctrl, if (i < 1 || i != GCRY_PK_RSA ) { r = get_parameter (para, pKEYTYPE); - log_error ("line %d: invalid algorithm\n", r->lnr); + log_error (_("line %d: invalid algorithm\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } @@ -453,11 +453,12 @@ proc_parameters (ctrl_t ctrl, nbits = 1024; else nbits = get_parameter_uint (para, pKEYLENGTH); - if (nbits < 512 || nbits > 4096) + if (nbits < 1024 || nbits > 4096) { + /* The BSI specs dated 2002-11-25 don't allow lengths below 1024. */ r = get_parameter (para, pKEYTYPE); - log_error ("line %d: invalid key length %u (valid are 512 to 4096)\n", - r->lnr, nbits); + log_error (_("line %d: invalid key length %u (valid are %d to %d)\n"), + r->lnr, nbits, 1024, 4096); return gpg_error (GPG_ERR_INV_PARAMETER); } @@ -470,7 +471,7 @@ proc_parameters (ctrl_t ctrl, if (!(s=get_parameter_value (para, pNAMEDN))) { r = get_parameter (para, pKEYTYPE); - log_error ("line %d: no subject name given\n", r->lnr); + log_error (_("line %d: no subject name given\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } /* fixme check s */ @@ -485,7 +486,7 @@ proc_parameters (ctrl_t ctrl, || strstr(s, "..")) { r = get_parameter (para, pKEYTYPE); - log_error ("line %d: not a valid email address\n", r->lnr); + log_error (_("line %d: not a valid email address\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } } @@ -497,7 +498,7 @@ proc_parameters (ctrl_t ctrl, if (rc) { r = get_parameter (para, pKEYTYPE); - log_error ("line %d: key generation failed: %s\n", + log_error (_("line %d: key generation failed: %s\n"), r->lnr, gpg_strerror (rc)); return rc; } -- cgit v1.2.3 From f96ad015d8ac7611213ff84227f97c7c6eb25fe7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 6 Aug 2004 16:14:10 +0000 Subject: * gpgsm.c: New option --with-ephemeral-keys. * keylist.c (list_internal_keys): Set it here. (list_cert_raw): And indicate those keys. Changed all our callers to pass the new arg HD through. --- doc/gpgsm.texi | 6 +++++- sm/ChangeLog | 7 +++++++ sm/gpgsm.c | 3 +++ sm/gpgsm.h | 3 +++ sm/keylist.c | 34 ++++++++++++++++++++++++++-------- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 384a36593..2f1033e3f 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -381,7 +381,7 @@ values include up to @var{n} certificates starting with the signer cert. @node Esoteric Options -@subsection Doing things one usually don't want todo. +@subsection Doing things one usually don't want to do. @table @gnupgtabopt @@ -392,6 +392,10 @@ 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 --with-ephemeral-keys +@opindex with-ephemeral-keys +Include ephemeral flagged keys in the output of key listings. + @item --debug-level @var{level} @opindex debug-level Select the debug level for investigating problems. @var{level} may be diff --git a/sm/ChangeLog b/sm/ChangeLog index b21a5faff..74b22b295 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-08-06 Werner Koch <wk@g10code.com> + + * gpgsm.c: New option --with-ephemeral-keys. + * keylist.c (list_internal_keys): Set it here. + (list_cert_raw): And indicate those keys. Changed all our callers + to pass the new arg HD through. + 2004-07-23 Werner Koch <wk@g10code.de> * certreqgen.c (proc_parameters): Do not allow key length below diff --git a/sm/gpgsm.c b/sm/gpgsm.c index bf053b7a5..5fb80a0de 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -170,6 +170,7 @@ enum cmd_and_opt_values { oWithColons, oWithKeyData, oWithValidation, + oWithEphemeralKeys, oSkipVerify, oCompressKeys, oCompressSigs, @@ -404,6 +405,7 @@ static ARGPARSE_OPTS opts[] = { { oWithKeyData,"with-key-data", 0, "@"}, { oWithValidation, "with-validation", 0, "@"}, { oWithMD5Fingerprint, "with-md5-fingerprint", 0, "@"}, + { oWithEphemeralKeys, "with-ephemeral-keys", 0, "@"}, { aListKeys, "list-key", 0, "@" }, /* alias */ { aListSigs, "list-sig", 0, "@" }, /* alias */ { aListSigs, "check-sig",0, "@" }, /* alias */ @@ -1078,6 +1080,7 @@ main ( int argc, char **argv) case oWithKeyData: opt.with_key_data=1; /* fall thru */ case oWithColons: ctrl.with_colons = 1; break; case oWithValidation: ctrl.with_validation=1; break; + case oWithEphemeralKeys: opt.with_ephemeral_keys=1; break; case oSkipVerify: opt.skip_verify=1; break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 786a97353..a1813462f 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -65,6 +65,9 @@ struct { int with_md5_fingerprint; /* Also print an MD5 fingerprint for standard key listings. */ + int with_ephemeral_keys; /* Include ephemeral flagged keys in the + keylisting. */ + int armor; /* force base64 armoring (see also ctrl.with_base64) */ int no_armor; /* don't try to figure out whether data is base64 armored*/ diff --git a/sm/keylist.c b/sm/keylist.c index 0fd06ca13..0c8ebd33e 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -503,7 +503,8 @@ print_names_raw (FILE *fp, int indent, ksba_name_t name) the certificate. This one does no beautification and only minimal output sanitation. It is mainly useful for debugging. */ static void -list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, +list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, + ksba_cert_t cert, FILE *fp, int have_secret, int with_validation) { gpg_error_t err; @@ -807,6 +808,18 @@ list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, else fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err)); } + + if (opt.with_ephemeral_keys && hd) + { + unsigned int blobflags; + + err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags); + if (err) + fprintf (fp, " [error getting keyflags: %s]\n", gpg_strerror (err)); + else if ((blobflags & 2)) + fprintf (fp, " [stored as ephemeral]\n"); + } + } @@ -992,13 +1005,14 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, /* Same as standard mode mode list all certifying certs too. */ static void -list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, int raw_mode, +list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd, + ksba_cert_t cert, int raw_mode, FILE *fp, int with_validation) { ksba_cert_t next = NULL; if (raw_mode) - list_cert_raw (ctrl, cert, fp, 0, with_validation); + list_cert_raw (ctrl, hd, cert, fp, 0, with_validation); else list_cert_std (ctrl, cert, fp, 0, with_validation); ksba_cert_ref (cert); @@ -1007,7 +1021,7 @@ list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, int raw_mode, ksba_cert_release (cert); fputs ("Certified by\n", fp); if (raw_mode) - list_cert_raw (ctrl, next, fp, 0, with_validation); + list_cert_raw (ctrl, hd, next, fp, 0, with_validation); else list_cert_std (ctrl, next, fp, 0, with_validation); cert = next; @@ -1079,6 +1093,9 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp, } + if (opt.with_ephemeral_keys) + keydb_set_ephemeral (hd, 1); + /* 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 @@ -1146,11 +1163,12 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp, if (ctrl->with_colons) list_cert_colon (ctrl, cert, validity, fp, have_secret); else if (ctrl->with_chain) - list_cert_chain (ctrl, cert, raw_mode, fp, ctrl->with_validation); + list_cert_chain (ctrl, hd, cert, + raw_mode, fp, ctrl->with_validation); else { if (raw_mode) - list_cert_raw (ctrl, cert, fp, have_secret, + list_cert_raw (ctrl, hd, cert, fp, have_secret, ctrl->with_validation); else list_cert_std (ctrl, cert, fp, have_secret, @@ -1198,11 +1216,11 @@ list_external_cb (void *cb_value, ksba_cert_t cert) if (parm->with_colons) list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0); else if (parm->with_chain) - list_cert_chain (parm->ctrl, cert, parm->raw_mode, parm->fp, 0); + list_cert_chain (parm->ctrl, NULL, cert, parm->raw_mode, parm->fp, 0); else { if (parm->raw_mode) - list_cert_raw (parm->ctrl, cert, parm->fp, 0, 0); + list_cert_raw (parm->ctrl, NULL, cert, parm->fp, 0, 0); else list_cert_std (parm->ctrl, cert, parm->fp, 0, 0); putc ('\n', parm->fp); -- cgit v1.2.3 From 93b7fb4a1742b1284d329b5768fa25044bfea055 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Mon, 9 Aug 2004 11:58:26 +0000 Subject: 2004-08-09 Moritz Schulte <moritz@g10code.com> * gpgsm-gencert.sh: New file. --- tools/ChangeLog | 4 ++ tools/gpgsm-gencert.sh | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100755 tools/gpgsm-gencert.sh diff --git a/tools/ChangeLog b/tools/ChangeLog index e4862bc38..841fb0c98 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-08-09 Moritz Schulte <moritz@g10code.com> + + * gpgsm-gencert.sh: New file. + 2004-06-16 Werner Koch <wk@gnupg.org> * rfc822parse.c (rfc822parse_get_field): Add arg VALUEOFF. diff --git a/tools/gpgsm-gencert.sh b/tools/gpgsm-gencert.sh new file mode 100755 index 000000000..3241efd94 --- /dev/null +++ b/tools/gpgsm-gencert.sh @@ -0,0 +1,115 @@ +#!/bin/sh + +# gpgsm-gencert.c - Generate X.509 certificates through GPGSM. +# Copyright (C) 2004 g10 Code GmbH +# +# 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. + +set -e + +ASSUAN_FP_IN=4 +ASSUAN_FP_OUT=5 + +ASSUAN_COMMANDS="\ +INPUT FD=$ASSUAN_FP_IN\n\ +OUTPUT FD=$ASSUAN_FP_OUT --armor\n\ +GENKEY\n\ +BYE" + +ANSWER="" + +query_user() +{ + message=$1; shift + + echo "$message" + echo -n "> " + read answer + + ANSWER=$answer; +} + +query_user_menu() +{ + message=$1; shift + i=0 + + echo "$message" + for choice in "$@"; do + i=$(expr $i + 1) + echo " [$i] $choice" + done + + while true; do + j=1 + echo -n "Your selection: " + read idx + + while [ $j -lt $i -o $j -eq $i ]; do + if [ "$idx" = $j ]; then + break + fi + j=$(expr $j + 1) + done + if [ $j -lt $i -o $j -eq $i ]; then + break + fi + done + + i=0 + for choice in "$@"; do + i=$(expr $i + 1) + if [ $i -eq $idx ]; then + ANSWER=$1 + break; + fi + shift + done + + echo "You selected: $ANSWER" +} + +query_user_menu "Key type" "RSA" +KEY_TYPE=$ANSWER + +query_user_menu "Key length" "1024" "2048" +KEY_LENGTH=$ANSWER + +query_user_menu "Key usage" "sign, encrypt" +KEY_USAGE=$ANSWER + +query_user "Name" +NAME=$ANSWER + +query_user "E-Mail address" +EMAIL_ADDRESS=$ANSWER + +file_parameter=$(mktemp "/tmp/gpgsm.XXXXXX") + +cat > "$file_parameter" <<EOF +Key-Type: $KEY_TYPE +Key-Length: $KEY_LENGTH +Key-Usage: $KEY_USAGE +Name-DN: $NAME +Name-Email: $EMAIL_ADDRESS +EOF + +echo -e "$ASSUAN_COMMANDS" | gpgsm --server 4< "$file_parameter" 5>&1 + +rm "$file_parameter" +exit 0 -- cgit v1.2.3 From f5799d0170229bcda77110bab643fd18a12023b8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 16 Aug 2004 11:15:55 +0000 Subject: (cmd_encrypt): Use DEFAULT_RECPLIST and not recplist for encrypt-to keys. --- sm/ChangeLog | 5 +++++ sm/server.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 74b22b295..51f46c335 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-08-16 Werner Koch <wk@g10code.de> + + * server.c (cmd_encrypt): Use DEFAULT_RECPLIST and not recplist + for encrypt-to keys. + 2004-08-06 Werner Koch <wk@g10code.com> * gpgsm.c: New option --with-ephemeral-keys. diff --git a/sm/server.c b/sm/server.c index 72bf74afa..e39c78a8d 100644 --- a/sm/server.c +++ b/sm/server.c @@ -353,7 +353,7 @@ cmd_encrypt (ASSUAN_CONTEXT ctx, char *line) rc = 0; if (!opt.no_encrypt_to) { - for (cl=ctrl->server_local->recplist; !rc && cl; cl = cl->next) + for (cl=ctrl->server_local->default_recplist; !rc && cl; cl = cl->next) if (cl->is_encrypt_to) rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert, &ctrl->server_local->recplist, 1); -- cgit v1.2.3 From 066352a6a555ec60d4a7e117ced0c87e2467fe7e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Aug 2004 15:26:22 +0000 Subject: * import.c (check_and_store): Do a full validation if --with-validation is set. * certchain.c (gpgsm_basic_cert_check): Print more detailed error messages. * certcheck.c (do_encode_md): Partly support DSA. Add new arg PKALGO. Changed all callers to pass it. (pk_algo_from_sexp): New. tests/pkits: New directory --- ChangeLog | 5 + NEWS | 3 + TODO | 7 +- configure.ac | 21 +- doc/gpgsm.texi | 14 +- po/de.po | 56 ++--- scd/sc-investigate.c | 2 +- sm/ChangeLog | 15 ++ sm/certchain.c | 16 +- sm/certcheck.c | 138 +++++++---- sm/gpgsm.c | 8 +- sm/gpgsm.h | 1 + sm/import.c | 39 ++- tests/ChangeLog | 4 + tests/pkits/ChangeLog | 18 ++ tests/pkits/Makefile.am | 69 ++++++ tests/pkits/PKITS_data.tar.bz2 | Bin 0 -> 1155744 bytes tests/pkits/README | 9 + tests/pkits/common.sh | 135 +++++++++++ tests/pkits/import-all-certs | 53 +++++ tests/pkits/import-all-certs.data | 490 ++++++++++++++++++++++++++++++++++++++ tests/pkits/inittests | 94 ++++++++ tests/pkits/runtest | 4 + tests/pkits/validate-all-certs | 55 +++++ 24 files changed, 1158 insertions(+), 98 deletions(-) create mode 100644 tests/pkits/ChangeLog create mode 100644 tests/pkits/Makefile.am create mode 100644 tests/pkits/PKITS_data.tar.bz2 create mode 100644 tests/pkits/README create mode 100644 tests/pkits/common.sh create mode 100755 tests/pkits/import-all-certs create mode 100644 tests/pkits/import-all-certs.data create mode 100755 tests/pkits/inittests create mode 100755 tests/pkits/runtest create mode 100755 tests/pkits/validate-all-certs diff --git a/ChangeLog b/ChangeLog index 7b14b7944..86bd01bff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-08-16 Werner Koch <wk@g10code.de> + + * configure.ac: Build Makefile for tests/pkits. New option + --with-pkits-tests. + 2004-08-05 Werner Koch <wk@g10code.de> * configure.ac: Changed tests for libusb to also suuport the diff --git a/NEWS b/NEWS index df35b570e..2fbf6475e 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ Noteworthy changes in version 1.9.11 ------------------------------------------------- + * When using --import along with --with-validation, the imported + certificates are validated and only imported if they are fully + valid. Noteworthy changes in version 1.9.10 (2004-07-22) ------------------------------------------------- diff --git a/TODO b/TODO index 6e5c8cfb8..ce0db37aa 100644 --- a/TODO +++ b/TODO @@ -35,6 +35,8 @@ might want to have an agent context for each service request 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. +** support the anyPolicy semantic +** Check that we are really following the verification procedures in rfc3280. * sm/keydb.c ** Check file permissions @@ -44,14 +46,15 @@ might want to have an agent context for each service request * 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. + 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. +** Support DSA * agent/divert-scd.c Remove the agent_reset_scd kludge. diff --git a/configure.ac b/configure.ac index f34faf469..d04475f6b 100644 --- a/configure.ac +++ b/configure.ac @@ -940,6 +940,14 @@ else fi AC_SUBST(ZLIBS) + +# See wether we want to run the long test suite. +AC_ARG_WITH(pkits-tests, + AC_HELP_STRING([--with-pkits-tests],[run the PKITS based tests]), + [run_pkits_tests=$withval], [run_pkits_tests=no]) +AM_CONDITIONAL(RUN_PKITS_TESTS, test "$run_pkits_tests" = "yes") + + # Allow users to append something to the version string without # flagging it as development version. The user version parts is # considered everything after a dash. @@ -1121,6 +1129,7 @@ scd/Makefile tools/Makefile doc/Makefile tests/Makefile +tests/pkits/Makefile ]) AC_OUTPUT @@ -1137,10 +1146,12 @@ echo " Agent: $build_agent $build_agent_threaded Smartcard: $build_scdaemon $build_scdaemon_extra - Protect tool: $show_gnupg_protect_tool_pgm - Default agent: $show_gnupg_agent_pgm - Default pinentry: $show_gnupg_pinentry_pgm - Default scdaemon: $show_gnupg_scdaemon_pgm - Default dirmngr: $show_gnupg_dirmngr_pgm + Protect tool: $show_gnupg_protect_tool_pgm + Default agent: $show_gnupg_agent_pgm + Default pinentry: $show_gnupg_pinentry_pgm + Default scdaemon: $show_gnupg_scdaemon_pgm + Default dirmngr: $show_gnupg_dirmngr_pgm + + PKITS based tests: $run_pkits_tests " diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 2f1033e3f..c79622342 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -358,7 +358,13 @@ secret key. @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. +requires a CRL lookup and other operations. + +When used along with --import, a validation of the certificate to +import is done and only imported if it succeeds the test. Note that +this does not affect an already available cwertificate in the DB. +This option is therefore useful to simply verify a certificate. + @item --with-md5-fingerprint For standard key listings, also print the MD5 fingerprint of the @@ -470,6 +476,12 @@ 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. +@item --fixed-passphrase @var{string} +@opindex fixed-passphrase +Supply the passphrase @var{string} to the gpg-protect-tool. This +option is only useful for the regression tests included with this +package and may be revised or removed at any time without notice. + @end table All the long options may also be given in the configuration file after diff --git a/po/de.po b/po/de.po index 4dbe66e8a..06ae4320e 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-07-22 09:54+0200\n" +"POT-Creation-Date: 2004-08-05 11:31+0200\n" "PO-Revision-Date: 2004-07-22 10:05+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:96 agent/protect-tool.c:94 scd/scdaemon.c:92 +#: agent/gpg-agent.c:96 agent/protect-tool.c:94 scd/scdaemon.c:93 msgid "" "@Options:\n" " " @@ -26,28 +26,28 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:98 scd/scdaemon.c:94 +#: agent/gpg-agent.c:98 scd/scdaemon.c:95 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:99 scd/scdaemon.c:95 +#: agent/gpg-agent.c:99 scd/scdaemon.c:96 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:100 kbx/kbxutil.c:75 scd/scdaemon.c:96 sm/gpgsm.c:313 +#: agent/gpg-agent.c:100 kbx/kbxutil.c:75 scd/scdaemon.c:97 sm/gpgsm.c:313 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:101 kbx/kbxutil.c:76 scd/scdaemon.c:97 sm/gpgsm.c:314 +#: agent/gpg-agent.c:101 kbx/kbxutil.c:76 scd/scdaemon.c:98 sm/gpgsm.c:314 msgid "be somewhat more quiet" msgstr "etwas weniger Aussageb erzeugen" -#: agent/gpg-agent.c:102 scd/scdaemon.c:98 +#: agent/gpg-agent.c:102 scd/scdaemon.c:99 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:103 scd/scdaemon.c:99 +#: agent/gpg-agent.c:103 scd/scdaemon.c:100 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" @@ -55,7 +55,7 @@ msgstr "Ausgabe f msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:109 scd/scdaemon.c:106 +#: agent/gpg-agent.c:109 scd/scdaemon.c:107 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" @@ -63,7 +63,7 @@ msgstr "Im Vordergrund laufen lassen" msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:111 scd/scdaemon.c:107 sm/gpgsm.c:316 +#: agent/gpg-agent.c:111 scd/scdaemon.c:108 sm/gpgsm.c:316 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" @@ -99,12 +99,12 @@ msgstr "benutze PINs im Cache nicht bem Signieren" msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" -#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:165 +#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:168 #: sm/gpgsm.c:481 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:165 +#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:168 #: sm/gpgsm.c:481 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -121,35 +121,35 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:267 scd/scdaemon.c:239 sm/gpgsm.c:604 +#: agent/gpg-agent.c:267 scd/scdaemon.c:242 sm/gpgsm.c:604 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:439 agent/protect-tool.c:1040 kbx/kbxutil.c:232 -#: scd/scdaemon.c:352 sm/gpgsm.c:726 +#: scd/scdaemon.c:357 sm/gpgsm.c:726 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:512 scd/scdaemon.c:432 sm/gpgsm.c:824 +#: agent/gpg-agent.c:512 scd/scdaemon.c:437 sm/gpgsm.c:824 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:517 agent/gpg-agent.c:983 scd/scdaemon.c:437 +#: agent/gpg-agent.c:517 agent/gpg-agent.c:983 scd/scdaemon.c:442 #: sm/gpgsm.c:828 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:525 scd/scdaemon.c:445 sm/gpgsm.c:835 +#: agent/gpg-agent.c:525 scd/scdaemon.c:450 sm/gpgsm.c:835 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:668 scd/scdaemon.c:619 +#: agent/gpg-agent.c:668 scd/scdaemon.c:630 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " @@ -362,43 +362,43 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:100 sm/gpgsm.c:333 +#: scd/scdaemon.c:101 sm/gpgsm.c:333 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" -#: scd/scdaemon.c:105 +#: scd/scdaemon.c:106 msgid "|N|set OpenSC debug level to N" msgstr "|N|Den OpenSC Debugstufe auf N setzen" -#: scd/scdaemon.c:108 +#: scd/scdaemon.c:109 msgid "|N|connect to reader at port N" msgstr "|N|Verbinde mit dem Leser auf Port N" -#: scd/scdaemon.c:109 +#: scd/scdaemon.c:110 msgid "|NAME|use NAME as ct-API driver" msgstr "|NAME|Benutze NAME als CT-API Treiber" -#: scd/scdaemon.c:110 +#: scd/scdaemon.c:111 msgid "|NAME|use NAME as PC/SC driver" msgstr "|NAME|Benutze NAME als PC/SC Treiber" -#: scd/scdaemon.c:113 +#: scd/scdaemon.c:114 msgid "do not use the internal CCID driver" msgstr "Den internen CCID Treiber nicht benutzen" -#: scd/scdaemon.c:120 +#: scd/scdaemon.c:121 msgid "do not use the OpenSC layer" msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" -#: scd/scdaemon.c:125 +#: scd/scdaemon.c:126 msgid "allow the use of admin card commands" msgstr "Erlaube die Benuztung von \"Admin\" Kommandos" -#: scd/scdaemon.c:168 +#: scd/scdaemon.c:171 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" -#: scd/scdaemon.c:170 +#: scd/scdaemon.c:173 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c index 8d34ab77e..1f1920650 100644 --- a/scd/sc-investigate.c +++ b/scd/sc-investigate.c @@ -76,7 +76,7 @@ static ARGPARSE_OPTS opts[] = { { oQuiet, "quiet", 0, "quiet" }, { oVerbose, "verbose", 0, "verbose" }, { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"}, - { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"}, + { octapiDriver, "ctapi-driver", 2, "|NAME|use NAME as ctAPI driver"}, { oDisableCCID, "disable-ccid", 0, #ifdef HAVE_LIBUSB "do not use the internal CCID driver" diff --git a/sm/ChangeLog b/sm/ChangeLog index 51f46c335..951c8db17 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,20 @@ +2004-08-17 Werner Koch <wk@g10code.de> + + * import.c (check_and_store): Do a full validation if + --with-validation is set. + + * certchain.c (gpgsm_basic_cert_check): Print more detailed error + messages. + + * certcheck.c (do_encode_md): Partly support DSA. Add new arg + PKALGO. Changed all callers to pass it. + (pk_algo_from_sexp): New. + 2004-08-16 Werner Koch <wk@g10code.de> + * gpgsm.c: New option --fixed-passphrase. + * import.c (popen_protect_tool): Pass it to the protect-tool. + * server.c (cmd_encrypt): Use DEFAULT_RECPLIST and not recplist for encrypt-to keys. diff --git a/sm/certchain.c b/sm/certchain.c index 8d54767f8..2ce247f65 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -39,9 +39,9 @@ #include "i18n.h" -/* If LISTMODE is true, print FORMAT in liting mode to FP. If +/* If LISTMODE is true, print FORMAT using LISTMODE to FP. If LISTMODE is false, use the string to print an log_info or, if - IS_ERROR is true, an log_error. */ + IS_ERROR is true, and log_error. */ static void do_list (int is_error, int listmode, FILE *fp, const char *format, ...) { @@ -925,9 +925,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert) if (subject && !strcmp (issuer, subject)) { - if (gpgsm_check_cert_sig (cert, cert) ) + rc = gpgsm_check_cert_sig (cert, cert); + if (rc) { - log_error ("selfsigned certificate has a BAD signature\n"); + log_error ("selfsigned certificate has a BAD signature: %s\n", + gpg_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } @@ -960,9 +962,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert) goto leave; } - if (gpgsm_check_cert_sig (issuer_cert, cert) ) + rc = gpgsm_check_cert_sig (issuer_cert, cert); + if (rc) { - log_error ("certificate has a BAD signature\n"); + log_error ("certificate has a BAD signature: %s\n", + gpg_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } diff --git a/sm/certcheck.c b/sm/certcheck.c index b5ed9914a..4f667cbbe 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -1,5 +1,5 @@ /* certcheck.c - check one certificate - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -36,51 +36,71 @@ static int -do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, +do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits, gcry_mpi_t *r_val) { - int nframe = (nbits+7) / 8; - byte *frame; - int i, n; - byte asn[100]; - size_t asnlen; - size_t len; - - asnlen = DIM(asn); - if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + int n, nframe; + unsigned char *frame; + + if (pkalgo == GCRY_PK_DSA) { - log_error ("no object identifier for algo %d\n", algo); - return gpg_error (GPG_ERR_INTERNAL); + nframe = gcry_md_get_algo_dlen (algo); + if (nframe != 20) + { + log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); + return gpg_error (GPG_ERR_INTERNAL); + } + frame = xtrymalloc (nframe); + if (!frame) + return OUT_OF_CORE (errno); + memcpy (frame, gcry_md_read (md, algo), nframe); + n = nframe; } - - len = gcry_md_get_algo_dlen (algo); - - if ( len + asnlen + 4 > nframe ) + else { - log_error ("can't encode a %d bit MD into a %d bits frame\n", - (int)(len*8), (int)nbits); - return gpg_error (GPG_ERR_INTERNAL); + int i; + unsigned char asn[100]; + size_t asnlen; + size_t len; + + nframe = (nbits+7) / 8; + + asnlen = DIM(asn); + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + log_error ("no object identifier for algo %d\n", algo); + return gpg_error (GPG_ERR_INTERNAL); + } + + len = gcry_md_get_algo_dlen (algo); + + if ( len + asnlen + 4 > nframe ) + { + log_error ("can't encode a %d bit MD into a %d bits frame\n", + (int)(len*8), (int)nbits); + return gpg_error (GPG_ERR_INTERNAL); + } + + /* We encode the MD in this way: + * + * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) + * + * PAD consists of FF bytes. + */ + frame = xtrymalloc (nframe); + if (!frame) + return OUT_OF_CORE (errno); + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - len - asnlen -3 ; + assert ( i > 1 ); + memset ( frame+n, 0xff, i ); n += i; + frame[n++] = 0; + memcpy ( frame+n, asn, asnlen ); n += asnlen; + memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; + assert ( n == nframe ); } - - /* We encode the MD in this way: - * - * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = xtrymalloc (nframe); - if (!frame) - return OUT_OF_CORE (errno); - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - len - asnlen -3 ; - assert ( i > 1 ); - memset ( frame+n, 0xff, i ); n += i; - frame[n++] = 0; - memcpy ( frame+n, asn, asnlen ); n += asnlen; - memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; - assert ( n == nframe ); if (DBG_X509) { int j; @@ -95,6 +115,38 @@ do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, return 0; } +/* Return the public key algorithm id from the S-expression PKEY. + FIXME: libgcrypt should provide such a function. Note that this + implementation uses the names as used by libksba. */ +static int +pk_algo_from_sexp (gcry_sexp_t pkey) +{ + gcry_sexp_t l1, l2; + const char *name; + size_t n; + int algo; + + l1 = gcry_sexp_find_token (pkey, "public-key", 0); + if (!l1) + return 0; /* Not found. */ + l2 = gcry_sexp_cadr (l1); + gcry_sexp_release (l1); + + name = gcry_sexp_nth_data (l2, 0, &n); + if (!name) + algo = 0; /* Not found. */ + else if (n==3 && !memcmp (name, "rsa", 3)) + algo = GCRY_PK_RSA; + else if (n==3 && !memcmp (name, "dsa", 3)) + algo = GCRY_PK_DSA; + else if (n==13 && !memcmp (name, "ambiguous-rsa", 13)) + algo = GCRY_PK_RSA; + else + algo = 0; + gcry_sexp_release (l2); + return algo; +} + /* Check the signature on CERT using the ISSUER-CERT. This function @@ -182,7 +234,8 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) return rc; } - rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); + rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey), + gcry_pk_get_nbits (s_pkey), &frame); if (rc) { gcry_md_close (md); @@ -254,7 +307,8 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, } - rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); + rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey), + gcry_pk_get_nbits (s_pkey), &frame); if (rc) { gcry_sexp_release (s_sig); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 5fb80a0de..3331537b1 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -95,6 +95,7 @@ enum cmd_and_opt_values { oDebugAllowCoreDump, oDebugNoChainValidation, oDebugIgnoreExpiration, + oFixedPassphrase, oLogFile, oEnableSpecialFilenames, @@ -340,6 +341,7 @@ static ARGPARSE_OPTS opts[] = { { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" }, { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"}, { oDebugIgnoreExpiration, "debug-ignore-expiration", 0, "@"}, + { oFixedPassphrase, "fixed-passphrase", 2, "@"}, { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, { aDummy, "no-comment", 0, "@"}, { aDummy, "completes-needed", 1, "@"}, @@ -706,6 +708,7 @@ main ( int argc, char **argv) CERTLIST signerlist = NULL; int do_not_setup_keys = 0; + /* trap_unaligned ();*/ set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -802,10 +805,10 @@ main ( int argc, char **argv) ctrl.status_fd = -1; /* not status output */ ctrl.autodetect_encoding = 1; - /* set the default option file */ + /* Set the default option file */ if (default_config ) configname = make_filename (opt.homedir, "gpgsm.conf", NULL); - /* cet the default policy file */ + /* Set the default policy file */ opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL); argc = orig_argc; @@ -1019,6 +1022,7 @@ main ( int argc, char **argv) break; case oDebugNoChainValidation: opt.no_chain_validation = 1; break; case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break; + case oFixedPassphrase: opt.fixed_passphrase = pargs.r.ret_str; break; case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index a1813462f..20a3c5ee9 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -100,6 +100,7 @@ struct { int no_policy_check; /* ignore certificate policies */ int no_chain_validation; /* Bypass all cert chain validity tests */ int ignore_expiration; /* Ignore the notAfter validity checks. */ + char *fixed_passphrase; /* Passphrase used by regression tests. */ int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ } opt; diff --git a/sm/import.c b/sm/import.c index c5581eb64..5d3484d92 100644 --- a/sm/import.c +++ b/sm/import.c @@ -172,13 +172,19 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) /* Some basic checks, but don't care about missing certificates; this is so that we are able to import entire certificate chains - w/o requirening a special order (i.e. root-CA first). This used + w/o requiring a special order (i.e. root-CA first). This used to be different but because gpgsm_verify even imports certificates without any checks, it doesn't matter much and the code gets much cleaner. A housekeeping function to remove - certificates w/o an anchor would be nice, though. */ + certificates w/o an anchor would be nice, though. + + Optionally we do a full validation in addition to the basic test. + */ rc = gpgsm_basic_cert_check (cert); - if (!rc || gpg_err_code (rc) == GPG_ERR_MISSING_CERT) + if (!rc && ctrl->with_validation) + rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0); + if (!rc || (!ctrl->with-validation + && gpg_err_code (rc) == GPG_ERR_MISSING_CERT) ) { int existed; @@ -527,14 +533,25 @@ popen_protect_tool (const char *pgmname, setup_pinentry_env (); - execlp (pgmname, arg0, - "--homedir", opt.homedir, - "--p12-import", - "--store", - "--no-fail-on-exist", - "--enable-status-msg", - "--", - NULL); + if (opt.fixed_passphrase) + execlp (pgmname, arg0, + "--homedir", opt.homedir, + "--p12-import", + "--store", + "--no-fail-on-exist", + "--enable-status-msg", + "--passphrase", opt.fixed_passphrase, + "--", + NULL); + else + execlp (pgmname, arg0, + "--homedir", opt.homedir, + "--p12-import", + "--store", + "--no-fail-on-exist", + "--enable-status-msg", + "--", + NULL); /* No way to print anything, as we have closed all streams. */ _exit (31); } diff --git a/tests/ChangeLog b/tests/ChangeLog index 68f9b4e21..c012c2346 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2004-08-16 Werner Koch <wk@g10code.de> + + * Makefile.am: Descend into the new pkits directory + 2004-02-20 Werner Koch <wk@gnupg.org> * Makefile.am: Reset GPG_AGENT_INFO here diff --git a/tests/pkits/ChangeLog b/tests/pkits/ChangeLog new file mode 100644 index 000000000..2f0b7ba0e --- /dev/null +++ b/tests/pkits/ChangeLog @@ -0,0 +1,18 @@ +2004-08-16 Werner Koch <wk@g10code.de> + + Started implementing PKITS based tests. + + + Copyright 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. + + + + diff --git a/tests/pkits/Makefile.am b/tests/pkits/Makefile.am new file mode 100644 index 000000000..41fdec497 --- /dev/null +++ b/tests/pkits/Makefile.am @@ -0,0 +1,69 @@ +# Makefile.am - tests using NIST's PKITS +# 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 + +## Process this file with automake to produce Makefile.in + +GPGSM = ../../sm/gpgsm + +TESTS_ENVIRONMENT = GNUPGHOME=`pwd` GPG_AGENT_INFO= LC_ALL=C GPGSM=$(GPGSM) \ + LD_LIBRARY_PATH=$$(seen=0; \ + for i in $(LDFLAGS) $(LIBGCRYPT_LIBS) $(PTH_LIBS); \ + do \ + if echo "$$i" | egrep '^-L' >/dev/null 2>&1; \ + then \ + if test $$seen = 0; \ + then \ + seen=1; \ + else \ + printf ":"; \ + fi; \ + printf "%s" "$${i}" | sed 's/^-L//'; \ + fi; \ + done; \ + if test $$seen != 0 \ + && test x$${LD_LIBRARY_PATH} != x; \ + then \ + printf ":"; \ + fi; \ + printf "%s" "$${LD_LIBRARY_PATH}") $(srcdir)/runtest + + + +testscripts = import-all-certs validate-all-certs + + + +EXTRA_DIST = PKITS_data.tar.bz2 inittests runtest $(testscripts) + import-all-certs.data + +TESTS = $(testscripts) + +CLEANFILES = inittests.stamp x y y z out err *.lock .\#lk* *.log + +DISTCLEANFILES = pubring.kbx~ random_seed + +all-local: inittests.stamp + +clean-local: + srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests --clean + +inittests.stamp: inittests + srcdir=$(srcdir) $(TESTS_ENVIRONMENT) $(srcdir)/inittests + echo timestamp >./inittests.stamp + diff --git a/tests/pkits/PKITS_data.tar.bz2 b/tests/pkits/PKITS_data.tar.bz2 new file mode 100644 index 000000000..0604f2286 Binary files /dev/null and b/tests/pkits/PKITS_data.tar.bz2 differ diff --git a/tests/pkits/README b/tests/pkits/README new file mode 100644 index 000000000..a4290fe1f --- /dev/null +++ b/tests/pkits/README @@ -0,0 +1,9 @@ +tests/pkits/README + +These are tests based on NIST's Public Key Interoperability Test Suite +(PKITS) as downloaded on 2004-08-16 from +http://csrc.nist.gov/pki/testing/x509paths.html . + +README - this file. +PKITS_data.tar.bz2 - the orginal ZIP file, repackaged as a tarball. +Makefile.am - Part of our build system. diff --git a/tests/pkits/common.sh b/tests/pkits/common.sh new file mode 100644 index 000000000..5e773ea5d --- /dev/null +++ b/tests/pkits/common.sh @@ -0,0 +1,135 @@ +#!/bin/sh +# common.sh - common defs for all tests -*- sh -*- +# 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 + +# reset some environment variables because we do not want to test locals +export LANG=C +export LANGUAGE=C +export LC_ALL=C + + +[ "$VERBOSE" = yes ] && set -x +[ -z "$srcdir" ] && srcdir="." +[ -z "$top_srcdir" ] && top_srcdir=".." +[ -z "$GPGSM" ] && GPGSM="../../sm/gpgsm" + + +if [ "$GNUPGHOME" != "`pwd`" ]; then + echo "inittests: please set GNUPGHOME to the tests/pkits directory" >&2 + exit 1 +fi + +if [ -n "$GPG_AGENT_INFO" ]; then + echo "inittests: please unset GPG_AGENT_INFO" >&2 + exit 1 +fi + + + +#-------------------------------- +#------ utility functions ------- +#-------------------------------- + +echo_n_init=no +echo_n () { + if test "$echo_n_init" = "no"; then + if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + echo_n_n= + echo_n_c=' +' + else + echo_n_n='-n' + echo_n_c= + fi + else + echo_n_n= + echo_n_c='\c' + fi + echo_n_init=yes + fi + echo $echo_n_n "${1}$echo_n_c" +} + +fatal () { + echo "$pgmname: fatal:" $* >&2 + exit 1; +} + +error () { + echo "$pgmname:" $* >&2 + exit 1 +} + +info () { + echo "$pgmname:" $* >&2 +} + +info_n () { + $echo_n "$pgmname:" $* >&2 +} + +pass () { + echo "PASS: " $* >&2 + pass_count=`expr ${pass_count} + 1` +} + +fail () { + echo "FAIL: " $* >&2 + fail_count=`expr ${fail_count} + 1` +} + +unresolved () { + echo "UNRESOLVED: " $* >&2 + unresolved_count=`expr ${unresolved_count} + 1` +} + +unsupported () { + echo "UNSUPPORTED: " $* >&2 + unsupported_count=`expr ${unsupported_count} + 1` +} + + +final_result () { + [ $pass_count = 0 ] || info "$pass_count tests passed" + [ $fail_count = 0 ] || info "$fail_count tests failed" + [ $unresolved_count = 0 ] || info "$unresolved_count tests unresolved" + [ $unsupported_count = 0 ] || info "$unsupported_count tests unsupported" + if [ $fail_count = 0 ]; then + info "all tests passed" + else + exit 1 + fi +} + +set -e + +pgmname=`basename $0` + +pass_count=0 +fail_count=0 +unresolved_count=0 +unsupported_count=0 + + +#trap cleanup SIGHUP SIGINT SIGQUIT +exec 2> ${pgmname}.log + +: +# end diff --git a/tests/pkits/import-all-certs b/tests/pkits/import-all-certs new file mode 100755 index 000000000..d1af5fb03 --- /dev/null +++ b/tests/pkits/import-all-certs @@ -0,0 +1,53 @@ +#!/bin/sh +# Copyright (C) 2004 Free Software Foundation, Inc. -*- sh -*- +# +# 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 + +. ${srcdir:-.}/common.sh || exit 2 + +while read flag dummy name; do + case $flag in \#*) continue;; esac + [ -z "$flag" ] && continue; + + if ${GPGSM} -q --import certs/$name ; then + if [ "$flag" = 'p' ]; then + pass "importing certificate \`$name' succeeded" + elif [ "$flag" = 'f' ]; then + fail "importing certificate \`$name' succeeded" + elif [ "$flag" = '?' ]; then + unresolved "importing certificate \`$name' succeeded" + elif [ "$flag" = 'u' ]; then + unsupported "importing certificate \`$name' succeeded" + else + info "importing certificate \`$name' succeeded - (flag=$flag)" + fi + else + if [ "$flag" = 'p' ]; then + fail "importing certificate \`$name' failed" + elif [ "$flag" = 'f' ]; then + pass "importing certificate \`$name' failed" + elif [ "$flag" = '?' ]; then + unresolved "importing certificate \`$name' failed" + elif [ "$flag" = 'u' ]; then + unsupported "importing certificate \`$name' failed" + else + info "importing certificate \`$name' failed - (flag=$flag)" + fi + fi +done < $srcdir/import-all-certs.data + +final_result diff --git a/tests/pkits/import-all-certs.data b/tests/pkits/import-all-certs.data new file mode 100644 index 000000000..18708aa61 --- /dev/null +++ b/tests/pkits/import-all-certs.data @@ -0,0 +1,490 @@ +# The first column is for the basic import test, the second for a +# validation test. + +# Make sure that the root certificate is imported first +p p TrustAnchorRootCertificate.crt + +p p AllCertificatesNoPoliciesTest2EE.crt +p p AllCertificatesSamePoliciesTest10EE.crt +p p AllCertificatesSamePoliciesTest13EE.crt +p p AllCertificatesanyPolicyTest11EE.crt +p p AnyPolicyTest14EE.crt +p p BadCRLIssuerNameCACert.crt +p p BadCRLSignatureCACert.crt +f f BadSignedCACert.crt +p f BadnotAfterDateCACert.crt + +# UTC: "470101120100Z" i.e. not before 2047-01-01 +p f BadnotBeforeDateCACert.crt + +p p BasicSelfIssuedCRLSigningKeyCACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? BasicSelfIssuedCRLSigningKeyCRLCert.crt + +p p BasicSelfIssuedNewKeyCACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? BasicSelfIssuedNewKeyOldWithNewCACert.crt + +p p BasicSelfIssuedOldKeyCACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? BasicSelfIssuedOldKeyNewWithOldCACert.crt + +p p CPSPointerQualifierTest20EE.crt + +u u DSACACert.crt +u u DSAParametersInheritedCACert.crt + +p p DifferentPoliciesTest12EE.crt +p p DifferentPoliciesTest3EE.crt +p p DifferentPoliciesTest4EE.crt +p p DifferentPoliciesTest5EE.crt +p p DifferentPoliciesTest7EE.crt +p p DifferentPoliciesTest8EE.crt +p p DifferentPoliciesTest9EE.crt +p p GeneralizedTimeCRLnextUpdateCACert.crt +p p GoodCACert.crt +p p GoodsubCACert.crt + +# gpgsm: critical certificate extension 2.5.29.33 (policyMappings) +# is not supported +p u GoodsubCAPanyPolicyMapping1to2CACert.crt + +# fixme: gpgme does not fail for it. +p f InvalidBadCRLIssuerNameTest5EE.crt + +p f InvalidBadCRLSignatureTest4EE.crt +p f InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt + +f f InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt + +p f InvalidBasicSelfIssuedNewWithOldTest5EE.crt + +f f InvalidBasicSelfIssuedOldWithNewTest2EE.crt + +p f InvalidCASignatureTest2EE.crt + +p f InvalidCAnotAfterDateTest5EE.crt +p f InvalidCAnotBeforeDateTest1EE.crt +p f InvalidDNSnameConstraintsTest31EE.crt +p f InvalidDNSnameConstraintsTest33EE.crt +p f InvalidDNSnameConstraintsTest38EE.crt +p f InvalidDNandRFC822nameConstraintsTest28EE.crt +p f InvalidDNandRFC822nameConstraintsTest29EE.crt +p f InvalidDNnameConstraintsTest10EE.crt +p f InvalidDNnameConstraintsTest12EE.crt +p f InvalidDNnameConstraintsTest13EE.crt +p f InvalidDNnameConstraintsTest15EE.crt +p f InvalidDNnameConstraintsTest16EE.crt +p f InvalidDNnameConstraintsTest17EE.crt + +f f InvalidDNnameConstraintsTest20EE.crt + +p f InvalidDNnameConstraintsTest2EE.crt +p f InvalidDNnameConstraintsTest3EE.crt +p f InvalidDNnameConstraintsTest7EE.crt +p f InvalidDNnameConstraintsTest8EE.crt +p f InvalidDNnameConstraintsTest9EE.crt + +u u InvalidDSASignatureTest6EE.crt + +f f InvalidEESignatureTest3EE.crt + +p f InvalidEEnotAfterDateTest6EE.crt +p f InvalidEEnotBeforeDateTest2EE.crt +p f InvalidIDPwithindirectCRLTest23EE.crt +p f InvalidIDPwithindirectCRLTest26EE.crt +p f InvalidLongSerialNumberTest18EE.crt +p f InvalidMappingFromanyPolicyTest7EE.crt +p f InvalidMappingToanyPolicyTest8EE.crt +p f InvalidMissingCRLTest1EE.crt +p f InvalidMissingbasicConstraintsTest1EE.crt +p f InvalidNameChainingOrderTest2EE.crt +p f InvalidNameChainingTest1EE.crt +p f InvalidNegativeSerialNumberTest15EE.crt +p f InvalidOldCRLnextUpdateTest11EE.crt +p f InvalidPolicyMappingTest10EE.crt +p f InvalidPolicyMappingTest2EE.crt +p f InvalidPolicyMappingTest4EE.crt +p f InvalidRFC822nameConstraintsTest22EE.crt +p f InvalidRFC822nameConstraintsTest24EE.crt +p f InvalidRFC822nameConstraintsTest26EE.crt +p f InvalidRevokedCATest2EE.crt +p f InvalidRevokedEETest3EE.crt + +f f InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt + +p f InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt +p f InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt +p f InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt +p f InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt +p f InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt +p f InvalidSelfIssuedpathLenConstraintTest16EE.crt +p f InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt +p f InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt + +f f InvalidSeparateCertificateandCRLKeysTest20EE.crt +f f InvalidSeparateCertificateandCRLKeysTest21EE.crt + +p f InvalidURInameConstraintsTest35EE.crt +p f InvalidURInameConstraintsTest37EE.crt +p f InvalidUnknownCRLEntryExtensionTest8EE.crt +p f InvalidUnknownCRLExtensionTest10EE.crt +p f InvalidUnknownCRLExtensionTest9EE.crt +p f InvalidUnknownCriticalCertificateExtensionTest2EE.crt +p f InvalidWrongCRLTest6EE.crt +p f InvalidcAFalseTest2EE.crt +p f InvalidcAFalseTest3EE.crt +p f InvalidcRLIssuerTest27EE.crt +p f InvalidcRLIssuerTest31EE.crt +p f InvalidcRLIssuerTest32EE.crt +p f InvalidcRLIssuerTest34EE.crt +p f InvalidcRLIssuerTest35EE.crt +p f InvaliddeltaCRLIndicatorNoBaseTest1EE.crt +p f InvaliddeltaCRLTest10EE.crt +p f InvaliddeltaCRLTest3EE.crt +p f InvaliddeltaCRLTest4EE.crt +p f InvaliddeltaCRLTest6EE.crt +p f InvaliddeltaCRLTest9EE.crt +p f InvaliddistributionPointTest2EE.crt +p f InvaliddistributionPointTest3EE.crt +p f InvaliddistributionPointTest6EE.crt +p f InvaliddistributionPointTest8EE.crt +p f InvaliddistributionPointTest9EE.crt +p f InvalidinhibitAnyPolicyTest1EE.crt +p f InvalidinhibitAnyPolicyTest4EE.crt +p f InvalidinhibitAnyPolicyTest5EE.crt +p f InvalidinhibitAnyPolicyTest6EE.crt +p f InvalidinhibitPolicyMappingTest1EE.crt +p f InvalidinhibitPolicyMappingTest3EE.crt +p f InvalidinhibitPolicyMappingTest5EE.crt +p f InvalidinhibitPolicyMappingTest6EE.crt +p f InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt +p f InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt +p f InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt +p f InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt +p f InvalidonlyContainsAttributeCertsTest14EE.crt +p f InvalidonlyContainsCACertsTest12EE.crt +p f InvalidonlyContainsUserCertsTest11EE.crt +p f InvalidonlySomeReasonsTest15EE.crt +p f InvalidonlySomeReasonsTest16EE.crt +p f InvalidonlySomeReasonsTest17EE.crt +p f InvalidonlySomeReasonsTest20EE.crt +p f InvalidonlySomeReasonsTest21EE.crt +p f InvalidpathLenConstraintTest10EE.crt +p f InvalidpathLenConstraintTest11EE.crt +p f InvalidpathLenConstraintTest12EE.crt +p f InvalidpathLenConstraintTest5EE.crt +p f InvalidpathLenConstraintTest6EE.crt +p f InvalidpathLenConstraintTest9EE.crt +p f Invalidpre2000CRLnextUpdateTest12EE.crt +p f Invalidpre2000UTCEEnotAfterDateTest7EE.crt +p f InvalidrequireExplicitPolicyTest3EE.crt +p f InvalidrequireExplicitPolicyTest5EE.crt +p p LongSerialNumberCACert.crt +p p Mapping1to2CACert.crt +p p MappingFromanyPolicyCACert.crt +p p MappingToanyPolicyCACert.crt +p p MissingbasicConstraintsCACert.crt +p p NameOrderingCACert.crt +p p NegativeSerialNumberCACert.crt +p p NoCRLCACert.crt +p p NoPoliciesCACert.crt +p p NoissuingDistributionPointCACert.crt +p p OldCRLnextUpdateCACert.crt +p p OverlappingPoliciesTest6EE.crt +p p P12Mapping1to3CACert.crt +p p P12Mapping1to3subCACert.crt +p p P12Mapping1to3subsubCACert.crt +p p P1Mapping1to234CACert.crt +p p P1Mapping1to234subCACert.crt +p p P1anyPolicyMapping1to2CACert.crt +p p PanyPolicyMapping1to2CACert.crt +p p PoliciesP1234CACert.crt +p p PoliciesP1234subCAP123Cert.crt +p p PoliciesP1234subsubCAP123P12Cert.crt +p p PoliciesP123CACert.crt +p p PoliciesP123subCAP12Cert.crt +p p PoliciesP123subsubCAP12P1Cert.crt +p p PoliciesP123subsubCAP12P2Cert.crt +p p PoliciesP123subsubsubCAP12P2P1Cert.crt +p p PoliciesP12CACert.crt +p p PoliciesP12subCAP1Cert.crt +p p PoliciesP12subsubCAP1P2Cert.crt +p p PoliciesP2subCA2Cert.crt +p p PoliciesP2subCACert.crt +p p PoliciesP3CACert.crt +p p RFC3280MandatoryAttributeTypesCACert.crt +p p RFC3280OptionalAttributeTypesCACert.crt +p p RevokedsubCACert.crt +p p RolloverfromPrintableStringtoUTF8StringCACert.crt +p p SeparateCertificateandCRLKeysCA2CRLSigningCert.crt +p p SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt +p p SeparateCertificateandCRLKeysCRLSigningCert.crt +p p SeparateCertificateandCRLKeysCertificateSigningCACert.crt +p p TwoCRLsCACert.crt +p p UIDCACert.crt +p p UTF8StringCaseInsensitiveMatchCACert.crt +p p UTF8StringEncodedNamesCACert.crt +p p UnknownCRLEntryExtensionCACert.crt +p p UnknownCRLExtensionCACert.crt +p p UserNoticeQualifierTest15EE.crt +p p UserNoticeQualifierTest16EE.crt +p p UserNoticeQualifierTest17EE.crt +p p UserNoticeQualifierTest18EE.crt +p p UserNoticeQualifierTest19EE.crt +p p ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? ValidBasicSelfIssuedNewWithOldTest3EE.crt + +p p ValidBasicSelfIssuedNewWithOldTest4EE.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? ValidBasicSelfIssuedOldWithNewTest1EE.crt + +p p ValidCertificatePathTest1EE.crt +p p ValidDNSnameConstraintsTest30EE.crt +p p ValidDNSnameConstraintsTest32EE.crt +p p ValidDNandRFC822nameConstraintsTest27EE.crt +p p ValidDNnameConstraintsTest11EE.crt + +# This certificate has an empty subject sequence. Our parser does not +# support this yet and it is unlikely that gpgsm will be able to cope +# with it at all. +u u ValidDNnameConstraintsTest14EE.crt + +p p ValidDNnameConstraintsTest18EE.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? ValidDNnameConstraintsTest19EE.crt + +p p ValidDNnameConstraintsTest1EE.crt +p p ValidDNnameConstraintsTest4EE.crt +p p ValidDNnameConstraintsTest5EE.crt +p p ValidDNnameConstraintsTest6EE.crt + +u p ValidDSAParameterInheritanceTest5EE.crt +u p ValidDSASignaturesTest4EE.crt + +p p ValidGeneralizedTimeCRLnextUpdateTest13EE.crt +p p ValidGeneralizedTimenotAfterDateTest8EE.crt +p p ValidGeneralizedTimenotBeforeDateTest4EE.crt +p p ValidIDPwithindirectCRLTest22EE.crt +p p ValidIDPwithindirectCRLTest24EE.crt +p p ValidIDPwithindirectCRLTest25EE.crt +p p ValidLongSerialNumberTest16EE.crt +p p ValidLongSerialNumberTest17EE.crt +p p ValidNameChainingCapitalizationTest5EE.crt +p p ValidNameChainingWhitespaceTest3EE.crt +p p ValidNameChainingWhitespaceTest4EE.crt +p p ValidNameUIDsTest6EE.crt +p p ValidNegativeSerialNumberTest14EE.crt +p p ValidNoissuingDistributionPointTest10EE.crt +p p ValidPolicyMappingTest11EE.crt +p p ValidPolicyMappingTest12EE.crt +p p ValidPolicyMappingTest13EE.crt +p p ValidPolicyMappingTest14EE.crt +p p ValidPolicyMappingTest1EE.crt +p p ValidPolicyMappingTest3EE.crt +p p ValidPolicyMappingTest5EE.crt +p p ValidPolicyMappingTest6EE.crt +p p ValidPolicyMappingTest9EE.crt +p p ValidRFC3280MandatoryAttributeTypesTest7EE.crt +p p ValidRFC3280OptionalAttributeTypesTest8EE.crt +p p ValidRFC822nameConstraintsTest21EE.crt +p p ValidRFC822nameConstraintsTest23EE.crt +p p ValidRFC822nameConstraintsTest25EE.crt +p p ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt +p p ValidSelfIssuedinhibitAnyPolicyTest7EE.crt +p p ValidSelfIssuedinhibitAnyPolicyTest9EE.crt +p p ValidSelfIssuedinhibitPolicyMappingTest7EE.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? ValidSelfIssuedpathLenConstraintTest15EE.crt + +p p ValidSelfIssuedpathLenConstraintTest17EE.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? ValidSelfIssuedrequireExplicitPolicyTest6EE.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? ValidSeparateCertificateandCRLKeysTest19EE.crt + +p p ValidTwoCRLsTest7EE.crt +p p ValidURInameConstraintsTest34EE.crt +p p ValidURInameConstraintsTest36EE.crt +p p ValidUTF8StringCaseInsensitiveMatchTest11EE.crt +p p ValidUTF8StringEncodedNamesTest9EE.crt +p p ValidUnknownNotCriticalCertificateExtensionTest1EE.crt +p p ValidbasicConstraintsNotCriticalTest4EE.crt +p p ValidcRLIssuerTest28EE.crt +p p ValidcRLIssuerTest29EE.crt +p p ValidcRLIssuerTest30EE.crt +p p ValidcRLIssuerTest33EE.crt +p p ValiddeltaCRLTest2EE.crt +p p ValiddeltaCRLTest5EE.crt +p p ValiddeltaCRLTest7EE.crt +p p ValiddeltaCRLTest8EE.crt +p p ValiddistributionPointTest1EE.crt +p p ValiddistributionPointTest4EE.crt +p p ValiddistributionPointTest5EE.crt +p p ValiddistributionPointTest7EE.crt +p p ValidinhibitAnyPolicyTest2EE.crt +p p ValidinhibitPolicyMappingTest2EE.crt +p p ValidinhibitPolicyMappingTest4EE.crt +p p ValidkeyUsageNotCriticalTest3EE.crt +p p ValidonlyContainsCACertsTest13EE.crt +p p ValidonlySomeReasonsTest18EE.crt +p p ValidonlySomeReasonsTest19EE.crt +p p ValidpathLenConstraintTest13EE.crt +p p ValidpathLenConstraintTest14EE.crt +p p ValidpathLenConstraintTest7EE.crt +p p ValidpathLenConstraintTest8EE.crt +p p Validpre2000UTCnotBeforeDateTest3EE.crt +p p ValidrequireExplicitPolicyTest1EE.crt +p p ValidrequireExplicitPolicyTest2EE.crt +p p ValidrequireExplicitPolicyTest4EE.crt +p p WrongCRLCACert.crt +p p anyPolicyCACert.crt +p p basicConstraintsCriticalcAFalseCACert.crt +p p basicConstraintsNotCriticalCACert.crt +p p basicConstraintsNotCriticalcAFalseCACert.crt +p p deltaCRLCA1Cert.crt +p p deltaCRLCA2Cert.crt +p p deltaCRLCA3Cert.crt +p p deltaCRLIndicatorNoBaseCACert.crt +p p distributionPoint1CACert.crt +p p distributionPoint2CACert.crt +p p indirectCRLCA1Cert.crt +p p indirectCRLCA2Cert.crt +p p indirectCRLCA3Cert.crt +p p indirectCRLCA3cRLIssuerCert.crt +p p indirectCRLCA4Cert.crt +p p indirectCRLCA4cRLIssuerCert.crt +p p indirectCRLCA5Cert.crt +p p indirectCRLCA6Cert.crt +p p inhibitAnyPolicy0CACert.crt +p p inhibitAnyPolicy1CACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? inhibitAnyPolicy1SelfIssuedCACert.crt +? ? inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt + +p p inhibitAnyPolicy1subCA1Cert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? inhibitAnyPolicy1subCA2Cert.crt + +p p inhibitAnyPolicy1subCAIAP5Cert.crt +p p inhibitAnyPolicy1subsubCA2Cert.crt +p p inhibitAnyPolicy5CACert.crt +p p inhibitAnyPolicy5subCACert.crt +p p inhibitAnyPolicy5subsubCACert.crt +p p inhibitAnyPolicyTest3EE.crt +p p inhibitPolicyMapping0CACert.crt +p p inhibitPolicyMapping0subCACert.crt +p p inhibitPolicyMapping1P12CACert.crt +p p inhibitPolicyMapping1P12subCACert.crt +p p inhibitPolicyMapping1P12subCAIPM5Cert.crt +p p inhibitPolicyMapping1P12subsubCACert.crt +p p inhibitPolicyMapping1P12subsubCAIPM5Cert.crt +p p inhibitPolicyMapping1P1CACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? inhibitPolicyMapping1P1SelfIssuedCACert.crt +? ? inhibitPolicyMapping1P1SelfIssuedsubCACert.crt +? ? inhibitPolicyMapping1P1subCACert.crt + +p p inhibitPolicyMapping1P1subsubCACert.crt +p p inhibitPolicyMapping5CACert.crt +p p inhibitPolicyMapping5subCACert.crt +p p inhibitPolicyMapping5subsubCACert.crt +p p inhibitPolicyMapping5subsubsubCACert.crt +p p keyUsageCriticalcRLSignFalseCACert.crt +p p keyUsageCriticalkeyCertSignFalseCACert.crt +p p keyUsageNotCriticalCACert.crt +p p keyUsageNotCriticalcRLSignFalseCACert.crt +p p keyUsageNotCriticalkeyCertSignFalseCACert.crt +p p nameConstraintsDN1CACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? nameConstraintsDN1SelfIssuedCACert.crt + +p p nameConstraintsDN1subCA1Cert.crt +p p nameConstraintsDN1subCA2Cert.crt +p p nameConstraintsDN1subCA3Cert.crt +p p nameConstraintsDN2CACert.crt +p p nameConstraintsDN3CACert.crt +p p nameConstraintsDN3subCA1Cert.crt +p p nameConstraintsDN3subCA2Cert.crt +p p nameConstraintsDN4CACert.crt +p p nameConstraintsDN5CACert.crt +p p nameConstraintsDNS1CACert.crt +p p nameConstraintsDNS2CACert.crt +p p nameConstraintsRFC822CA1Cert.crt +p p nameConstraintsRFC822CA2Cert.crt +p p nameConstraintsRFC822CA3Cert.crt +p p nameConstraintsURI1CACert.crt +p p nameConstraintsURI2CACert.crt +p p onlyContainsAttributeCertsCACert.crt +p p onlyContainsCACertsCACert.crt +p p onlyContainsUserCertsCACert.crt +p p onlySomeReasonsCA1Cert.crt +p p onlySomeReasonsCA2Cert.crt +p p onlySomeReasonsCA3Cert.crt +p p onlySomeReasonsCA4Cert.crt +p p pathLenConstraint0CACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? pathLenConstraint0SelfIssuedCACert.crt +? ? pathLenConstraint0subCA2Cert.crt + +p p pathLenConstraint0subCACert.crt +p p pathLenConstraint1CACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? pathLenConstraint1SelfIssuedCACert.crt +? ? pathLenConstraint1SelfIssuedsubCACert.crt +? ? pathLenConstraint1subCACert.crt + +p p pathLenConstraint6CACert.crt +p p pathLenConstraint6subCA0Cert.crt +p p pathLenConstraint6subCA1Cert.crt +p p pathLenConstraint6subCA4Cert.crt +p p pathLenConstraint6subsubCA00Cert.crt +p p pathLenConstraint6subsubCA11Cert.crt +p p pathLenConstraint6subsubCA41Cert.crt +p p pathLenConstraint6subsubsubCA11XCert.crt +p p pathLenConstraint6subsubsubCA41XCert.crt +p p pre2000CRLnextUpdateCACert.crt +p p requireExplicitPolicy0CACert.crt +p p requireExplicitPolicy0subCACert.crt +p p requireExplicitPolicy0subsubCACert.crt +p p requireExplicitPolicy0subsubsubCACert.crt +p p requireExplicitPolicy10CACert.crt +p p requireExplicitPolicy10subCACert.crt +p p requireExplicitPolicy10subsubCACert.crt +p p requireExplicitPolicy10subsubsubCACert.crt +p p requireExplicitPolicy2CACert.crt + +# For yet unknown reasons gpgsm claims a bad signature. +? ? requireExplicitPolicy2SelfIssuedCACert.crt +? ? requireExplicitPolicy2SelfIssuedsubCACert.crt +? ? requireExplicitPolicy2subCACert.crt + +p p requireExplicitPolicy4CACert.crt +p p requireExplicitPolicy4subCACert.crt +p p requireExplicitPolicy4subsubCACert.crt +p p requireExplicitPolicy4subsubsubCACert.crt +p p requireExplicitPolicy5CACert.crt +p p requireExplicitPolicy5subCACert.crt +p p requireExplicitPolicy5subsubCACert.crt +p p requireExplicitPolicy5subsubsubCACert.crt +p p requireExplicitPolicy7CACert.crt +p p requireExplicitPolicy7subCARE2Cert.crt +p p requireExplicitPolicy7subsubCARE2RE4Cert.crt +p p requireExplicitPolicy7subsubsubCARE2RE4Cert.crt + diff --git a/tests/pkits/inittests b/tests/pkits/inittests new file mode 100755 index 000000000..6af16de03 --- /dev/null +++ b/tests/pkits/inittests @@ -0,0 +1,94 @@ +#!/bin/sh +# Copyright (C) 2004 Free Software Foundation, Inc. -*- sh -*- +# +# 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. + +set -e + + +clean_files=' +ReadMe.txt pkits.ldif +gpgsm.conf gpg-agent.conf trustlist.txt policies.txt pubring.kbx +msg msg.sig msg.unsig +' + +[ -z "$srcdir" ] && srcdir=. +[ -z "$GPGSM" ] && GPGSM=../../sm/gpgsm + +if [ -f $srcdir/README ] \ + && grep tests/pkits/README README >/dev/null 2>&1; then + : +else + # During make distclean the Makefile has already been removed, + # so we need this extra test. + if ! grep gnupg-test-pkits-directory testdir.stamp >/dev/null 2>&1; then + echo "inittests: please cd to the tests/pkits directory first" >&2 + exit 1 + fi +fi + +if [ "$1" = "--clean" ]; then + if [ -d private-keys-v1.d ]; then + rm private-keys-v1.d/* 2>/dev/null || true + rmdir private-keys-v1.d + fi + rm ${clean_files} testdir.stamp 2>/dev/null || true + for i in certs certpairs crls pkcs12 smime; do + if [ -d $i ]; then + rm $i/* 2>/dev/null || true + rmdir $i + fi + done + exit 0 +fi + +if [ "$GNUPGHOME" != "`pwd`" ]; then + echo "inittests: please set GNUPGHOME to the tests/pkits directory" >&2 + exit 1 +fi + +if [ -n "$GPG_AGENT_INFO" ]; then + echo "inittests: please unset GPG_AGENT_INFO" >&2 + exit 1 +fi + +if ! bunzip2 -c PKITS_data.tar.bz2 | tar xf - ; then + echo "inittests: failed to untar the test data" >&2 + exit 1 +fi + + +# A stamp file used with --clean +echo gnupg-test-pkits-directory > testdir.stamp + + +# Create the configuration scripts +cat > gpgsm.conf <<EOF +no-secmem-warning +no-greeting +batch +disable-crl-checks +agent-program ../../agent/gpg-agent +EOF + +# Fixme: we need to write a dummy pinentry program +cat > gpg-agent.conf <<EOF +no-grab +EOF + +# Mark the root CA trusted +cat > trustlist.txt <<EOF +# /CN=Trust Anchor/O=Test Certificates/C=US +66:8A:47:56:A2:DC:88:FF:DA:B8:95:E1:3C:63:37:55:5F:0A:F7:BF S +EOF + +# Define the standard policies as NIST test-policy-1 +#cat >policies.txt <<EOF +#2.16.840.1.101.3.2.1.48.1 +#EOF diff --git a/tests/pkits/runtest b/tests/pkits/runtest new file mode 100755 index 000000000..f054a3498 --- /dev/null +++ b/tests/pkits/runtest @@ -0,0 +1,4 @@ +#!/bin/sh +[ -x "$1" ] && exec $1 $2 +exec sh $1 $2 + diff --git a/tests/pkits/validate-all-certs b/tests/pkits/validate-all-certs new file mode 100755 index 000000000..f482fdb51 --- /dev/null +++ b/tests/pkits/validate-all-certs @@ -0,0 +1,55 @@ +#!/bin/sh +# validate-all-certs -*- sh -*- +# 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 + +. ${srcdir:-.}/common.sh || exit 2 + +while read dummy flag name; do + case $dummy in \#*) continue;; esac + [ -z "$dummy" ] && continue; + + if ${GPGSM} -q --import --with-validation --disable-crl-checks \ + certs/$name ; then + if [ "$flag" = 'p' ]; then + pass "validating certificate \`$name' succeeded" + elif [ "$flag" = 'f' ]; then + fail "validating certificate \`$name' succeeded" + elif [ "$flag" = '?' ]; then + unresolved "validating certificate \`$name' succeeded" + elif [ "$flag" = 'u' ]; then + unsupported "validating certificate \`$name' succeeded" + else + info "validating certificate \`$name' succeeded - (flag=$flag)" + fi + else + if [ "$flag" = 'p' ]; then + fail "validating certificate \`$name' failed" + elif [ "$flag" = 'f' ]; then + pass "validating certificate \`$name' failed" + elif [ "$flag" = '?' ]; then + unresolved "validating certificate \`$name' failed" + elif [ "$flag" = 'u' ]; then + unsupported "validating certificate \`$name' failed" + else + info "validating certificate \`$name' failed - (flag=$flag)" + fi + fi +done < $srcdir/import-all-certs.data + +final_result -- cgit v1.2.3 From 53f7e372b94a500c3377a1c480fa2231d296f353 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 17 Aug 2004 15:32:56 +0000 Subject: tests/pkits: New directory --- tests/Makefile.am | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 791829a07..b44336bfb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,8 +19,19 @@ ## Process this file with automake to produce Makefile.in + +if RUN_PKITS_TESTS +pkits = pkits +else +pkits = +endif + +SUBDIRS = . ${pkits} + + GPGSM = ../sm/gpgsm + TESTS_ENVIRONMENT = GNUPGHOME=`pwd` GPG_AGENT_INFO= LC_ALL=C GPGSM=$(GPGSM) \ LD_LIBRARY_PATH=$$(seen=0; \ for i in $(LDFLAGS) $(LIBGCRYPT_LIBS) $(PTH_LIBS); \ @@ -56,7 +67,7 @@ EXTRA_DIST = runtest inittests $(testscripts) \ TESTS = $(testscripts) -CLEANFILES = inittests.stamp x y y z out err +CLEANFILES = inittests.stamp x y y z out err \ *.lock .\#lk* DISTCLEANFILES = pubring.kbx~ random_seed -- cgit v1.2.3 From e5a6d2b4560f23821503cb0d20a37288c057b0a1 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 17 Aug 2004 20:06:24 +0000 Subject: 2004-08-17 Marcus Brinkmann <marcus@g10code.de> * import.c: Fix typo in last change. --- sm/ChangeLog | 4 ++++ sm/import.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 951c8db17..0bc31c0bc 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-08-17 Marcus Brinkmann <marcus@g10code.de> + + * import.c: Fix typo in last change. + 2004-08-17 Werner Koch <wk@g10code.de> * import.c (check_and_store): Do a full validation if diff --git a/sm/import.c b/sm/import.c index 5d3484d92..836ac0877 100644 --- a/sm/import.c +++ b/sm/import.c @@ -183,7 +183,7 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) rc = gpgsm_basic_cert_check (cert); if (!rc && ctrl->with_validation) rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0); - if (!rc || (!ctrl->with-validation + if (!rc || (!ctrl->with_validation && gpg_err_code (rc) == GPG_ERR_MISSING_CERT) ) { int existed; -- cgit v1.2.3 From 9d864ebef7608faa69a314ad220c270bffd43834 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 18 Aug 2004 00:03:07 +0000 Subject: 2004-08-18 Marcus Brinkmann <marcus@g10code.de> * passphrase.c (agent_get_passphrase): --- g10/ChangeLog | 5 +++++ g10/passphrase.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 7a8ccd5c0..e472a626f 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2004-08-18 Marcus Brinkmann <marcus@g10code.de> + + * passphrase.c (agent_get_passphrase): Fix detection of gpg-agent + cancellation. + 2004-07-01 Werner Koch <wk@gnupg.org> * card-util.c (change_login): Kludge to allow reading data from a diff --git a/g10/passphrase.c b/g10/passphrase.c index 986070a16..30149908e 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -862,9 +862,11 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, xfree (orig_codeset); return pw; } - else if (nread > 7 && !memcmp (pw, "ERR 111", 7) - && (pw[7] == ' ' || pw[7] == '\n') ) - { + else if (nread > 4 && !memcmp (pw, "ERR ", 4) + && (0xffff & strtoul (&pw[4], NULL, 0)) == 99) + { + /* 99 is GPG_ERR_CANCELED. FIXME: Check tail and overflow, + and use gpg-error. */ log_info (_("cancelled by user\n") ); if (canceled) *canceled = 1; -- cgit v1.2.3 From aac85ca3141533d3dae12f82d2189a63ec981d1b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Aug 2004 12:47:33 +0000 Subject: (get_passphrase): Make sure that the default prompts passed to gpg-agent are utf-8 encoded. --- agent/ChangeLog | 5 +++++ agent/protect-tool.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/agent/ChangeLog b/agent/ChangeLog index d616b1544..8305ec4af 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-08-18 Werner Koch <wk@g10code.de> + + * protect-tool.c (get_passphrase): Make sure that the default + prompts passed to gpg-agent are utf-8 encoded. + 2004-07-22 Werner Koch <wk@g10code.de> * trustlist.c (read_list): Allow colons in the fingerprint. diff --git a/agent/protect-tool.c b/agent/protect-tool.c index c33d21094..d4c2accfc 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -29,6 +29,12 @@ #include <assert.h> #include <sys/stat.h> #include <unistd.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif #define JNLIB_NEED_LOG_LOGV #include "agent.h" @@ -1138,10 +1144,29 @@ get_passphrase (int promptno) char *pw; int err; const char *desc; + char *orig_codeset = NULL; if (opt_passphrase) return xstrdup (opt_passphrase); +#ifdef ENABLE_NLS + /* The Assuan agent protocol requires us to transmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset && !strcmp (orig_codeset, "UTF-8")) + orig_codeset = NULL; + if (orig_codeset) + { + /* We only switch when we are able to restore the codeset later. */ + orig_codeset = xstrdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) + orig_codeset = NULL; + } +#endif + if (promptno == 1 && opt_prompt) desc = opt_prompt; else @@ -1149,6 +1174,15 @@ get_passphrase (int promptno) "needed to complete this operation."); pw = simple_pwquery (NULL,NULL, _("Passphrase:"), desc, &err); + +#ifdef ENABLE_NLS + if (orig_codeset) + { + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); + xfree (orig_codeset); + } +#endif + if (!pw) { if (err) -- cgit v1.2.3 From 9c6da35ea2a722123140714c1769c5610c704225 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Aug 2004 13:21:56 +0000 Subject: (print_sanitized_utf8_string): Actually implement it. --- jnlib/ChangeLog | 5 +++++ jnlib/stringhelp.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index e4df12a7f..db9b68d0d 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2004-08-18 Werner Koch <wk@g10code.de> + + * stringhelp.c (print_sanitized_utf8_string): Actually implement + it. + 2004-06-21 Werner Koch <wk@g10code.com> * logging.c (log_set_file): Do not close an old logstream if it diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 4c8ab314b..568152fdd 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -392,8 +392,9 @@ print_sanitized_string (FILE *fp, const char *string, int delim) size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim) { - /* FIXME: convert to local characterset */ - return print_sanitized_string (fp, string, delim); + return string? print_sanitized_utf8_buffer (fp, + string, strlen (string), + delim) : 0; } /* Create a string from the buffer P of length N which is suitable for -- cgit v1.2.3 From 33310977ac6984a49085f12f0f5ff83c9a9f8d8a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Aug 2004 14:37:22 +0000 Subject: (simple_pwquery): Handle gpg-error style return code for canceled. --- TODO | 4 ++++ common/ChangeLog | 5 +++++ common/simple-pwquery.c | 10 ++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index ce0db37aa..dd69544e1 100644 --- a/TODO +++ b/TODO @@ -22,6 +22,10 @@ might want to have an agent context for each service request ** figure out how to auto retrieve a key by serialno+issuer. Dirmngr is currently not able to parse more than the CN. +* sm/certlist.c +** ocspSigning usage is not fully implemented + We should review the entire CRL and OCSP validation system. + * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution diff --git a/common/ChangeLog b/common/ChangeLog index a3a23bee1..f0e7bf67a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2004-08-18 Werner Koch <wk@g10code.de> + + * simple-pwquery.c (simple_pwquery): Handle gpg-error style return + code for canceled. + 2004-07-20 Werner Koch <wk@g10code.de> * maperror.c: Removed header ksba.h. Not required anymore. diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 36244b120..0bc8128e1 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -466,9 +466,15 @@ simple_pwquery (const char *cacheid, result = pw; pw = NULL; } - else if (nread > 7 && !memcmp (pw, "ERR 111", 7) - && (pw[7] == ' ' || pw[7] == '\n') ) + else if ((nread > 7 && !memcmp (pw, "ERR 111", 7) + && (pw[7] == ' ' || pw[7] == '\n') ) + || ((nread > 4 && !memcmp (pw, "ERR ", 4) + && (strtoul (pw+4, NULL, 0) & 0xffff) == 99)) ) { + /* 111 is the old Assuan code for canceled which might still + be in use by old installations. 99 is GPG_ERR_CANCELED as + used by modern gpg-agents; 0xffff is used to mask out the + error source. */ #ifdef SPWQ_USE_LOGGING log_info (_("canceled by user\n") ); #endif -- cgit v1.2.3 From fc07b029ea71cf46304aaaea453d794daf39c68e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Aug 2004 14:38:47 +0000 Subject: * certlist.c (gpgsm_cert_use_ocsp_p): New. (cert_usage_p): Support it here. * call-dirmngr.c (gpgsm_dirmngr_isvalid): Use it here. --- doc/gpgsm.texi | 4 +++- sm/ChangeLog | 6 ++++++ sm/call-dirmngr.c | 4 +--- sm/certlist.c | 29 ++++++++++++++++++++++++++++- sm/gpgsm.h | 1 + 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index c79622342..0f2167184 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -133,6 +133,8 @@ Generate a new key and a certificate request. @itemx -k @opindex list-keys List all available certificates stored in the local key database. +Note that the displayed data might be reformatted for better human +readability and illegal characters are replaced by safe substitutes. @item --list-secret-keys @itemx -K @@ -156,7 +158,7 @@ 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 +@opindex dump-external-keys List certificates matching @var{pattern} using an external server. This utilizes the @code{dirmngr} service. It uses a format useful mainly for debugging. diff --git a/sm/ChangeLog b/sm/ChangeLog index 0bc31c0bc..ab362e842 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-08-18 Werner Koch <wk@g10code.de> + + * certlist.c (gpgsm_cert_use_ocsp_p): New. + (cert_usage_p): Support it here. + * call-dirmngr.c (gpgsm_dirmngr_isvalid): Use it here. + 2004-08-17 Marcus Brinkmann <marcus@g10code.de> * import.c: Fix typo in last change. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 15160dc41..849b8a04c 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -458,9 +458,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, if (!rc) { - /* fixme: We should refine the check to check for - certificates allowed for CRL/OCPS. */ - rc = gpgsm_cert_use_verify_p (rspcert); + rc = gpgsm_cert_use_ocsp_p (rspcert); if (rc) rc = gpg_error (GPG_ERR_INV_CRL); else diff --git a/sm/certlist.c b/sm/certlist.c index 96acf90f7..983732317 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -45,13 +45,15 @@ static const char oid_kp_ocspSigning[] = "1.3.6.1.5.6.7.3.9"; /* Return 0 if the cert is usable for encryption. A MODE of 0 checks for signing a MODE of 1 checks for encryption, a MODE of 2 checks for verification and a MODE of 3 for decryption (just for - debugging) */ + debugging). MODE 4 is for certificate signing, MODE for COSP + response signing. */ static int cert_usage_p (ksba_cert_t cert, int mode) { gpg_error_t err; unsigned int use; char *extkeyusages; + int have_ocsp_signing = 0; err = ksba_cert_get_ext_key_usages (cert, &extkeyusages); if (gpg_err_code (err) == GPG_ERR_NO_DATA) @@ -94,6 +96,13 @@ cert_usage_p (ksba_cert_t cert, int mode) | KSBA_KEYUSAGE_NON_REPUDIATION); } + /* This is a hack to cope with OCSP. Note that we do + not yet fully comply with the requirements and that + the entire CRL/OCSP checking thing should undergo a + thorough review and probably redesign. */ + if ( !strcmp (p, oid_kp_ocspSigning)) + have_ocsp_signing = 1; + if ((p = strchr (pend, '\n'))) p++; } @@ -135,6 +144,18 @@ cert_usage_p (ksba_cert_t cert, int mode) return gpg_error (GPG_ERR_WRONG_KEY_USAGE); } + if (mode == 5) + { + if (use != ~0 + && (have_ocsp_signing + || (use & (KSBA_KEYUSAGE_KEY_CERT_SIGN + |KSBA_KEYUSAGE_CRL_SIGN)))) + return 0; + log_info (_("certificate should have not " + "been used for OCSP response signing\n")); + return gpg_error (GPG_ERR_WRONG_KEY_USAGE); + } + if ((use & ((mode&1)? (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT): (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION))) @@ -182,6 +203,12 @@ gpgsm_cert_use_cert_p (ksba_cert_t cert) return cert_usage_p (cert, 4); } +int +gpgsm_cert_use_ocsp_p (ksba_cert_t cert) +{ + return cert_usage_p (cert, 5); +} + static int same_subject_issuer (const char *subject, const char *issuer, ksba_cert_t cert) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 20a3c5ee9..72486aadb 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -240,6 +240,7 @@ int gpgsm_cert_use_encrypt_p (ksba_cert_t cert); int gpgsm_cert_use_verify_p (ksba_cert_t cert); int gpgsm_cert_use_decrypt_p (ksba_cert_t cert); int gpgsm_cert_use_cert_p (ksba_cert_t cert); +int gpgsm_cert_use_ocsp_p (ksba_cert_t cert); int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, certlist_t *listaddr, int is_encrypt_to); int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, -- cgit v1.2.3 From 6c3677c2967b77f068a3cadc742013e90338c8ad Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 Aug 2004 16:21:13 +0000 Subject: (get_passphrase): Make sure that the default prompts passed to gpg-agent are utf-8 encoded. Add new prompt values. (import_p12_file, import_p12_file, export_p12_file): Changed calls to get_passphrase so that better prompts are displayed. (get_new_passphrase): New. --- agent/ChangeLog | 5 +++- agent/protect-tool.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 8305ec4af..ae252474c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,7 +1,10 @@ 2004-08-18 Werner Koch <wk@g10code.de> * protect-tool.c (get_passphrase): Make sure that the default - prompts passed to gpg-agent are utf-8 encoded. + prompts passed to gpg-agent are utf-8 encoded. Add new prompt values. + (import_p12_file, import_p12_file, export_p12_file): Changed calls + to get_passphrase so that better prompts are displayed. + (get_new_passphrase): New. 2004-07-22 Werner Koch <wk@g10code.de> diff --git a/agent/protect-tool.c b/agent/protect-tool.c index d4c2accfc..7cfb760b8 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -90,6 +90,7 @@ static char *opt_prompt; static int opt_status_msg; static char *get_passphrase (int promptno); +static char *get_new_passphrase (int promptno); static void release_passphrase (char *pw); static int store_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); @@ -663,7 +664,7 @@ import_p12_file (const char *fname) if (!buf) return; - kparms = p12_parse (buf, buflen, (pw=get_passphrase (0)), + kparms = p12_parse (buf, buflen, (pw=get_passphrase (2)), import_p12_cert_cb, NULL); release_passphrase (pw); xfree (buf); @@ -739,7 +740,7 @@ import_p12_file (const char *fname) gcry_sexp_release (s_key); - rc = agent_protect (key, (pw=get_passphrase (0)), &result, &resultlen); + rc = agent_protect (key, (pw=get_new_passphrase (4)), &result, &resultlen); release_passphrase (pw); xfree (key); if (rc) @@ -963,7 +964,8 @@ export_p12_file (const char *fname) kparms[7] = sk.u; kparms[8] = NULL; - key = p12_build (kparms, cert, certlen, (pw=get_passphrase (0)), &keylen); + key = p12_build (kparms, cert, certlen, + (pw=get_new_passphrase (3)), &keylen); release_passphrase (pw); xfree (cert); for (i=0; i < 8; i++) @@ -1137,6 +1139,11 @@ agent_exit (int rc) set from the command line PROMPTNO select the prompt to display: 0 = default 1 = taken from the option --prompt + 2 = for unprotecting a pkcs#12 object + 3 = for protecting a new pkcs#12 object + 4 = for protecting an imported pkcs#12 in our system + 5 = reenter the passphrase + When adding 100 to the values, a "does not match - try again" errro message is shown. */ static char * get_passphrase (int promptno) @@ -1145,10 +1152,15 @@ get_passphrase (int promptno) int err; const char *desc; char *orig_codeset = NULL; + int error_msgno; + if (opt_passphrase) return xstrdup (opt_passphrase); + error_msgno = promptno / 100; + promptno %= 100; + #ifdef ENABLE_NLS /* The Assuan agent protocol requires us to transmit utf-8 strings */ orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); @@ -1169,11 +1181,24 @@ get_passphrase (int promptno) if (promptno == 1 && opt_prompt) desc = opt_prompt; + else if (promptno == 2) + desc = _("Please enter the passphrase to unprotect the " + "PKCS#12 object."); + else if (promptno == 3) + desc = _("Please enter the passphrase to protect the " + "new PKCS#12 object."); + else if (promptno == 4) + desc = _("Please enter the passphrase to protect the " + "imported object within the GnuPG system."); + else if (promptno == 5) + desc = _("Please re-enter this passphrase"); else desc = _("Please enter the passphrase or the PIN\n" "needed to complete this operation."); - pw = simple_pwquery (NULL,NULL, _("Passphrase:"), desc, &err); + pw = simple_pwquery (NULL, + error_msgno == 1? _("does not match - try again"):NULL, + _("Passphrase:"), desc, &err); #ifdef ENABLE_NLS if (orig_codeset) @@ -1195,6 +1220,44 @@ get_passphrase (int promptno) return pw; } + +/* Same as get_passphrase but requests it a second time and compares + it to the one entered the first time. */ +static char * +get_new_passphrase (int promptno) +{ + char *pw; + int i, secondpromptno; + + pw = get_passphrase (promptno); + if (!pw) + return NULL; /* Canceled. */ + if (!*pw) + return pw; /* Empty passphrase - no need to as for repeating it. */ + + secondpromptno = 5; + for (i=0; i < 3; i++) + { + char *pw2 = get_passphrase (secondpromptno); + if (!pw2) + { + xfree (pw); + return NULL; /* Canceled. */ + } + if (!strcmp (pw, pw2)) + { + xfree (pw2); + return pw; /* Okay. */ + } + secondpromptno = 105; + xfree (pw2); + } + xfree (pw); + return NULL; /* 3 times repeated wrong - cancel. */ +} + + + static void release_passphrase (char *pw) { -- cgit v1.2.3 From 0ded03123777db4a411c79746173bece0fdef99d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 20 Aug 2004 13:03:32 +0000 Subject: (start_pinentry): Use a timeout for the pinentry lock. --- agent/ChangeLog | 4 ++++ agent/query.c | 26 +++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index ae252474c..2fd201a8a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-08-20 Werner Koch <wk@g10code.de> + + * query.c (start_pinentry): Use a timeout for the pinentry lock. + 2004-08-18 Werner Koch <wk@g10code.de> * protect-tool.c (get_passphrase): Make sure that the default diff --git a/agent/query.c b/agent/query.c index 145aaca00..b514f6f5e 100644 --- a/agent/query.c +++ b/agent/query.c @@ -41,6 +41,14 @@ #define MAX_OPEN_FDS 20 #endif + +/* Because access to the pinentry must be serialized (it is and shall + be a global mutual dialog) we should better timeout further + requests after some time. 2 minutes seem to be a reasonable + time. */ +#define LOCK_TIMEOUT (1*60) + + static ASSUAN_CONTEXT entry_ctx = NULL; #ifdef USE_GNU_PTH static pth_mutex_t entry_lock = PTH_MUTEX_INIT; @@ -104,11 +112,23 @@ start_pinentry (CTRL ctrl) int i; #ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&entry_lock, 0, NULL)) + { + pth_event_t evt; + + evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0)); + if (!pth_mutex_acquire (&entry_lock, 0, evt)) { - log_error ("failed to acquire the entry lock\n"); - return gpg_error (GPG_ERR_INTERNAL); + if (pth_event_occurred (evt)) + rc = gpg_error (GPG_ERR_TIMEOUT); + else + rc = gpg_error (GPG_ERR_INTERNAL); + pth_event_free (evt, PTH_FREE_THIS); + log_error (_("failed to acquire the pinentry lock: %s\n"), + gpg_strerror (rc)); + return rc; } + pth_event_free (evt, PTH_FREE_THIS); + } #endif if (entry_ctx) -- cgit v1.2.3 From ebaba6bdab5cff7a7208106454cf9f0af45b69e1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 20 Aug 2004 13:43:14 +0000 Subject: * gpg-agent.c: New option --max-cache-ttl. Suggested by Alexander Belopolsky. * cache.c (housekeeping): Use it here instead of the hardwired default of 1 hour. --- agent/ChangeLog | 5 +++++ agent/agent.h | 1 + agent/cache.c | 5 +++-- agent/gpg-agent.c | 9 +++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 2fd201a8a..220eb21e4 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,10 @@ 2004-08-20 Werner Koch <wk@g10code.de> + * gpg-agent.c: New option --max-cache-ttl. Suggested by Alexander + Belopolsky. + * cache.c (housekeeping): Use it here instead of the hardwired + default of 1 hour. + * query.c (start_pinentry): Use a timeout for the pinentry lock. 2004-08-18 Werner Koch <wk@g10code.de> diff --git a/agent/agent.h b/agent/agent.h index 6b7821e30..89fc4285e 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -54,6 +54,7 @@ struct { const char *scdaemon_program; int no_grab; /* don't let the pinentry grab the keyboard */ unsigned long def_cache_ttl; + unsigned long max_cache_ttl; int running_detached; /* we are running detached from the tty. */ diff --git a/agent/cache.c b/agent/cache.c index b6ab55085..8017b1414 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -103,10 +103,11 @@ housekeeping (void) that the user has to enter it from time to time. We do this every hour */ for (r=thecache; r; r = r->next) { - if (!r->lockcount && r->pw && r->created + 60*60 < current) + if (!r->lockcount && r->pw && r->created + opt.max_cache_ttl < current) { if (DBG_CACHE) - log_debug (" expired `%s' (1h after creation)\n", r->key); + log_debug (" expired `%s' (%lus after creation)\n", + r->key, opt.max_cache_ttl); release_data (r->pw); r->pw = NULL; r->accessed = current; diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index f7e701bbc..6aa3e6d67 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -77,8 +77,9 @@ enum cmd_and_opt_values oLCctype, oLCmessages, oScdaemonProgram, - oDefCacheTTL, oDisablePth, + oDefCacheTTL, + oMaxCacheTTL, oIgnoreCacheForSigning, oAllowMarkTrusted, @@ -127,6 +128,7 @@ static ARGPARSE_OPTS opts[] = { { oDefCacheTTL, "default-cache-ttl", 4, N_("|N|expire cached PINs after N seconds")}, + { oMaxCacheTTL, "max-cache-ttl", 4, "@" }, { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, N_("do not use the PIN cache when signing")}, { oAllowMarkTrusted, "allow-mark-trusted", 0, @@ -135,7 +137,8 @@ static ARGPARSE_OPTS opts[] = { }; -#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ +#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ +#define MAX_CACHE_TTL (120*60) /* 2 hours */ static volatile int caught_fatal_sig = 0; @@ -342,6 +345,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.pinentry_program = NULL; opt.scdaemon_program = NULL; opt.def_cache_ttl = DEFAULT_CACHE_TTL; + opt.max_cache_ttl = MAX_CACHE_TTL; opt.ignore_cache_for_signing = 0; opt.allow_mark_trusted = 0; return 1; @@ -372,6 +376,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break; case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break; + case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; -- cgit v1.2.3 From d851bdf579077d66e1d8f552f6bd51d4ac1dc08d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 24 Aug 2004 18:13:15 +0000 Subject: Fixed typo in ocsp OID. --- sm/ChangeLog | 4 ++++ sm/certlist.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index ab362e842..a8139e2e0 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-08-24 Werner Koch <wk@g10code.de> + + * certlist.c: Fixed typo in ocsp OID. + 2004-08-18 Werner Koch <wk@g10code.de> * certlist.c (gpgsm_cert_use_ocsp_p): New. diff --git a/sm/certlist.c b/sm/certlist.c index 983732317..018ad47ff 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -40,7 +40,7 @@ static const char oid_kp_clientAuth[] = "1.3.6.1.5.5.7.3.2"; static const char oid_kp_codeSigning[] = "1.3.6.1.5.5.7.3.3"; static const char oid_kp_emailProtection[]= "1.3.6.1.5.5.7.3.4"; static const char oid_kp_timeStamping[] = "1.3.6.1.5.5.7.3.8"; -static const char oid_kp_ocspSigning[] = "1.3.6.1.5.6.7.3.9"; +static const char oid_kp_ocspSigning[] = "1.3.6.1.5.5.7.3.9"; /* Return 0 if the cert is usable for encryption. A MODE of 0 checks for signing a MODE of 1 checks for encryption, a MODE of 2 checks -- cgit v1.2.3 From 2a09a35ad07494747f55957286fdc5ad78871451 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 24 Aug 2004 19:55:47 +0000 Subject: * kbxutil.c: New command --import-openpgp. (main): Updated libgcrypt initialization stuff. (my_gcry_logger): New. (read_file): New. Taken from ../agent/protect-tool. (dump_fpr, dump_openpgp_key, import_openpgp): New. * keybox-openpgp.c: New. --- kbx/ChangeLog | 10 + kbx/Makefile.am | 1 + kbx/kbxutil.c | 269 ++++++++++++++++++++++++--- kbx/keybox-defs.h | 41 ++++ kbx/keybox-openpgp.c | 516 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 810 insertions(+), 27 deletions(-) create mode 100644 kbx/keybox-openpgp.c diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 1c3b9e3a1..f13434de8 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,13 @@ +2004-08-24 Werner Koch <wk@g10code.de> + + * kbxutil.c: New command --import-openpgp. + (main): Updated libgcrypt initialization stuff. + (my_gcry_logger): New. + (read_file): New. Taken from ../agent/protect-tool. + (dump_fpr, dump_openpgp_key, import_openpgp): New. + + * keybox-openpgp.c: New. + 2004-06-18 Werner Koch <wk@gnupg.org> * keybox-dump.c (_keybox_dump_file): New arg STATS_ONLY. diff --git a/kbx/Makefile.am b/kbx/Makefile.am index 4f0c40043..6b6a59b26 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -37,6 +37,7 @@ common_sources = \ keybox-file.c \ keybox-search.c \ keybox-update.c \ + keybox-openpgp.c \ keybox-dump.c diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 37c19130b..cd5da5f77 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -1,5 +1,5 @@ /* kbxutil.c - The Keybox utility - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -24,11 +24,15 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <sys/stat.h> #include <unistd.h> +#include <assert.h> +#define JNLIB_NEED_LOG_LOGV #include "../jnlib/logging.h" #include "../jnlib/argparse.h" #include "../jnlib/stringhelp.h" +#include "../jnlib/utf8conv.h" #include "../common/i18n.h" #include "keybox-defs.h" @@ -48,6 +52,7 @@ enum cmd_and_opt_values { aFindByKid, aFindByUid, aStats, + aImportOpenPGP, oDebug, oDebugAll, @@ -66,6 +71,7 @@ static ARGPARSE_OPTS opts[] = { /* { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, */ /* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */ { aStats, "stats", 0, "show key statistics" }, + { aImportOpenPGP, "import-openpgp", 0, "import OpenPGP keyblocks"}, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -135,6 +141,26 @@ i18n_init(void) #endif } +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* Map the log levels. */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; + } + log_logv (level, fmt, arg_ptr); +} + + /* static void */ /* wrong_args( const char *text ) */ @@ -215,6 +241,181 @@ format_keyid ( const char *s, u32 *kid ) } #endif +static char * +read_file (const char *fname, size_t *r_length) +{ + FILE *fp; + char *buf; + size_t buflen; + + if (!strcmp (fname, "-")) + { + size_t nread, bufsize = 0; + + fp = stdin; + buf = NULL; + buflen = 0; +#define NCHUNK 8192 + do + { + bufsize += NCHUNK; + if (!buf) + buf = xtrymalloc (bufsize); + else + buf = xtryrealloc (buf, bufsize); + if (!buf) + log_fatal ("can't allocate buffer: %s\n", strerror (errno)); + + nread = fread (buf+buflen, 1, NCHUNK, fp); + if (nread < NCHUNK && ferror (fp)) + { + log_error ("error reading `[stdin]': %s\n", strerror (errno)); + xfree (buf); + return NULL; + } + buflen += nread; + } + while (nread == NCHUNK); +#undef NCHUNK + + } + else + { + struct stat st; + + fp = fopen (fname, "rb"); + if (!fp) + { + log_error ("can't open `%s': %s\n", fname, strerror (errno)); + return NULL; + } + + if (fstat (fileno(fp), &st)) + { + log_error ("can't stat `%s': %s\n", fname, strerror (errno)); + fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = xtrymalloc (buflen+1); + if (!buf) + log_fatal ("can't allocate buffer: %s\n", strerror (errno)); + if (fread (buf, buflen, 1, fp) != 1) + { + log_error ("error reading `%s': %s\n", fname, strerror (errno)); + fclose (fp); + xfree (buf); + return NULL; + } + fclose (fp); + } + + *r_length = buflen; + return buf; +} + + +static void +dump_fpr (const unsigned char *buffer, size_t len) +{ + int i; + + for (i=0; i < len; i++, buffer++) + { + if (len == 20) + { + if (i == 10) + putchar (' '); + printf (" %02X%02X", buffer[0], buffer[1]); + i++; buffer++; + } + else + { + if (i && !(i % 8)) + putchar (' '); + printf (" %02X", buffer[0]); + } + } +} + + +static void +dump_openpgp_key (keybox_openpgp_info_t info, const unsigned char *image) +{ + printf ("pub %02X%02X%02X%02X", + info->primary.keyid[4], info->primary.keyid[5], + info->primary.keyid[6], info->primary.keyid[7] ); + dump_fpr (info->primary.fpr, info->primary.fprlen); + putchar ('\n'); + if (info->nsubkeys) + { + struct _keybox_openpgp_key_info *k; + + k = &info->subkeys; + do + { + printf ("sub %02X%02X%02X%02X", + k->keyid[4], k->keyid[5], + k->keyid[6], k->keyid[7] ); + dump_fpr (k->fpr, k->fprlen); + putchar ('\n'); + k = k->next; + } + while (k); + } + if (info->nuids) + { + struct _keybox_openpgp_uid_info *u; + + u = &info->uids; + do + { + printf ("uid\t\t%.*s\n", u->len, image + u->off); + u = u->next; + } + while (u); + } +} + + +static void +import_openpgp (const char *filename) +{ + gpg_error_t err; + char *buffer; + size_t buflen, nparsed; + unsigned char *p; + struct _keybox_openpgp_info info; + + buffer = read_file (filename, &buflen); + if (!buffer) + return; + p = buffer; + for (;;) + { + err = _keybox_parse_openpgp (p, buflen, &nparsed, &info); + assert (nparsed <= buflen); + if (err) + { + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + break; + log_info ("%s: failed to parse OpenPGP keyblock: %s\n", + filename, gpg_strerror (err)); + } + else + { + dump_openpgp_key (&info, p); + _keybox_destroy_openpgp_info (&info); + } + p += nparsed; + buflen -= nparsed; + } + xfree (buffer); +} + + + int main( int argc, char **argv ) @@ -223,19 +424,22 @@ main( int argc, char **argv ) enum cmd_and_opt_values cmd = 0; set_strusage( my_strusage ); - /*log_set_name("kbxutil"); fixme */ -#if 0 - /* check that the libraries are suitable. Do it here because - * the option parse may need services of the library */ - if ( !gcry_check_version ( "1.1.4" ) ) + gcry_control (GCRYCTL_DISABLE_SECMEM); + log_set_prefix ("kbxutil", 1); + set_native_charset (NULL); + i18n_init (); + + /* Check that the libraries are suitable. Do it here because + the option parsing may need services of the library. */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) { - log_fatal(_("libgcrypt is too old (need %s, have %s)\n"), - "1.1.4", gcry_check_version(NULL) ); + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); } -#endif + + gcry_set_log_handler (my_gcry_logger, NULL); /*create_dotlock(NULL); register locking cleanup */ - i18n_init(); /* We need to use the gcry malloc function because jnlib does use them */ keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); @@ -264,9 +468,10 @@ main( int argc, char **argv ) case aFindByKid: case aFindByUid: case aStats: + case aImportOpenPGP: cmd = pargs.r_opt; break; - + default: pargs.err = 2; break; @@ -276,24 +481,34 @@ main( int argc, char **argv ) myexit(2); if (!cmd) - { /* default is to list a KBX file */ - if (!argc) - _keybox_dump_file (NULL, 0, stdout); - else - { - for (; argc; argc--, argv++) - _keybox_dump_file (*argv, 0, stdout); - } - } + { /* Default is to list a KBX file */ + if (!argc) + _keybox_dump_file (NULL, 0, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_file (*argv, 0, stdout); + } + } else if (cmd == aStats ) { - if (!argc) - _keybox_dump_file (NULL, 1, stdout); - else - { - for (; argc; argc--, argv++) - _keybox_dump_file (*argv, 1, stdout); - } + if (!argc) + _keybox_dump_file (NULL, 1, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_file (*argv, 1, stdout); + } + } + else if (cmd == aImportOpenPGP) + { + if (!argc) + import_openpgp ("-"); + else + { + for (; argc; argc--, argv++) + import_openpgp (*argv); + } } #if 0 else if ( cmd == aFindByFpr ) diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 759289a0e..4906a386e 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -82,6 +82,40 @@ struct keybox_handle { }; +/* Openpgp helper structures. */ +struct _keybox_openpgp_key_info +{ + struct _keybox_openpgp_key_info *next; + unsigned char keyid[8]; + int fprlen; /* Either 16 or 20 */ + unsigned char fpr[20]; +}; + +struct _keybox_openpgp_uid_info +{ + struct _keybox_openpgp_uid_info *next; + size_t off; + size_t len; +}; + +struct _keybox_openpgp_info +{ + int is_secret; /* True if this is a secret key. */ + unsigned int nsubkeys;/* Total number of subkeys. */ + unsigned int nuids; /* Total number of user IDs in the keyblock. */ + unsigned int nsigs; /* Total number of signatures in the keyblock. */ + + /* Note, we use 2 structs here to better cope with the most common + use of having one primary and one subkey - this allows us to + statically allocate this structure and only malloc stuff for more + than one subkey. */ + struct _keybox_openpgp_key_info primary; + struct _keybox_openpgp_key_info subkeys; + struct _keybox_openpgp_uid_info uids; +}; +typedef struct _keybox_openpgp_info *keybox_openpgp_info_t; + + /* Don't know whether this is needed: */ /* static struct { */ /* const char *homedir; */ @@ -108,6 +142,13 @@ const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); void _keybox_update_header_blob (KEYBOXBLOB blob); +/*-- keybox-openpgp.c --*/ +gpg_error_t _keybox_parse_openpgp (const unsigned char *image, size_t imagelen, + size_t *nparsed, + keybox_openpgp_info_t info); +void _keybox_destroy_openpgp_info (keybox_openpgp_info_t info); + + /*-- keybox-file.c --*/ int _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp); int _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted); diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c new file mode 100644 index 000000000..7e6e0e412 --- /dev/null +++ b/kbx/keybox-openpgp.c @@ -0,0 +1,516 @@ +/* keybox-openpgp.c - OpenPGP key parsing + * 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 + */ + +/* This is a simple OpenPGP parser suitable for all OpenPGP key + material. It just provides the functionality required to build and + parse an KBX OpenPGP key blob. Thus it is not a complete parser. + However it is self-contained and optimized for fast in-memory + parsing. Note that we don't support old ElGamal v3 keys + anymore. */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "keybox-defs.h" + +#include <gcrypt.h> + + +enum packet_types + { + PKT_NONE =0, + PKT_PUBKEY_ENC =1, /* public key encrypted packet */ + PKT_SIGNATURE =2, /* secret key encrypted packet */ + PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/ + PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/ + PKT_SECRET_KEY =5, /* secret key */ + PKT_PUBLIC_KEY =6, /* public key */ + PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */ + PKT_COMPRESSED =8, /* compressed data packet */ + PKT_ENCRYPTED =9, /* conventional encrypted data */ + PKT_MARKER =10, /* marker packet (OpenPGP) */ + PKT_PLAINTEXT =11, /* plaintext data with filename and mode */ + PKT_RING_TRUST =12, /* keyring trust packet */ + PKT_USER_ID =13, /* user id packet */ + PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */ + PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */ + PKT_ATTRIBUTE =17, /* PGP's attribute packet */ + PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */ + PKT_MDC =19, /* manipulation detection code packet */ + PKT_COMMENT =61, /* new comment packet (private) */ + PKT_GPG_CONTROL =63 /* internal control packet */ + }; + + + +/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR + which is of amaximum length as stored at BUFLEN. Return the header + information of that packet and advance the pointer stored at BUFPTR + to the next packet; also adjust the length stored at BUFLEN to + match the remaining bytes. If there are no more packets, store NULL + at BUFPTR. Return an non-zero error code on failure or the + follwing data on success: + + R_DATAPKT = Pointer to the begin of the packet data. + R_DATALEN = Length of this data. This has already been checked to fit + into the buffer. + R_PKTTYPE = The packet type. + R_NTOTAL = The total number of bytes of this packet + + Note that these values are only updated on success. +*/ +static gpg_error_t +next_packet (unsigned char const **bufptr, size_t *buflen, + unsigned char const **r_data, size_t *r_datalen, int *r_pkttype, + size_t *r_ntotal) +{ + const unsigned char *buf = *bufptr; + size_t len = *buflen; + int c, ctb, pkttype; + unsigned long pktlen; + + if (!len) + return gpg_error (GPG_ERR_NO_DATA); + + ctb = *buf++; len--; + if ( !(ctb & 0x80) ) + return gpg_error (GPG_ERR_INV_PACKET); /* Invalid CTB. */ + + pktlen = 0; + if ((ctb & 0x40)) /* New style (OpenPGP) CTB. */ + { + pkttype = (ctb & 0x3f); + if (!len) + return gpg_error (GPG_ERR_INV_PACKET); /* No 1st length byte. */ + c = *buf++; len--; + if (pkttype == PKT_COMPRESSED) + return gpg_error (GPG_ERR_UNEXPECTED); /* ... packet in a keyblock. */ + if ( c < 192 ) + pktlen = c; + else if ( c < 224 ) + { + pktlen = (c - 192) * 256; + if (!len) + return gpg_error (GPG_ERR_INV_PACKET); /* No 2nd length byte. */ + c = *buf++; len--; + pktlen += c + 192; + } + else if (c == 255) + { + if (len <4 ) + return gpg_error (GPG_ERR_INV_PACKET); /* No length bytes. */ + pktlen = (*buf++) << 24; + pktlen |= (*buf++) << 16; + pktlen |= (*buf++) << 8; + pktlen |= (*buf++); + len -= 4; + } + else /* Partial length encoding is not allowed for key packets. */ + return gpg_error (GPG_ERR_UNEXPECTED); + } + else /* Old style CTB. */ + { + int lenbytes; + + pktlen = 0; + pkttype = (ctb>>2)&0xf; + lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); + if (!lenbytes) /* Not allowed in key packets. */ + return gpg_error (GPG_ERR_UNEXPECTED); + if (len < lenbytes) + return gpg_error (GPG_ERR_INV_PACKET); /* Not enough length bytes. */ + for (; lenbytes; lenbytes--) + { + pktlen <<= 8; + pktlen |= *buf++; len--; + } + } + + /* Do some basic sanity check. */ + switch (pkttype) + { + case PKT_SIGNATURE: + case PKT_SECRET_KEY: + case PKT_PUBLIC_KEY: + case PKT_SECRET_SUBKEY: + case PKT_MARKER: + case PKT_RING_TRUST: + case PKT_USER_ID: + case PKT_PUBLIC_SUBKEY: + case PKT_OLD_COMMENT: + case PKT_ATTRIBUTE: + case PKT_COMMENT: + case PKT_GPG_CONTROL: + break; /* Okay these are allowed packets. */ + default: + return gpg_error (GPG_ERR_UNEXPECTED); + } + + if (pktlen == 0xffffffff) + return gpg_error (GPG_ERR_INV_PACKET); + + if (pktlen > len) + return gpg_error (GPG_ERR_INV_PACKET); /* Packet length header too long. */ + + *r_data = buf; + *r_datalen = pktlen; + *r_pkttype = pkttype; + *r_ntotal = (buf - *bufptr) + pktlen; + + *bufptr = buf + pktlen; + *buflen = len - pktlen; + if (!*buflen) + *bufptr = NULL; + + return 0; +} + + +/* Parse a key packet and store the ionformation in KI. */ +static gpg_error_t +parse_key (const unsigned char *data, size_t datalen, + struct _keybox_openpgp_key_info *ki) +{ + gpg_error_t err; + const unsigned char *data_start = data; + int i, version, algorithm; + size_t n; + unsigned long timestamp, expiredate; + int npkey; + unsigned char hashbuffer[768]; + const unsigned char *mpi_n = NULL; + size_t mpi_n_len = 0, mpi_e_len = 0; + gcry_md_hd_t md; + + if (datalen < 5) + return gpg_error (GPG_ERR_INV_PACKET); + version = *data++; datalen--; + if (version < 2 || version > 4 ) + return gpg_error (GPG_ERR_INV_PACKET); /* Invalid version. */ + + timestamp = ((data[0]<<24)|(data[1]<<16)|(data[2]<<8)|(data[3])); + data +=4; datalen -=4; + + if (version < 4) + { + unsigned short ndays; + + if (datalen < 2) + return gpg_error (GPG_ERR_INV_PACKET); + ndays = ((data[0]<<8)|(data[1])); + data +=2; datalen -= 2; + if (ndays) + expiredate = ndays? (timestamp + ndays * 86400L) : 0; + } + else + expiredate = 0; /* This is stored in the self-signature. */ + + if (!datalen) + return gpg_error (GPG_ERR_INV_PACKET); + algorithm = *data++; datalen--; + + switch (algorithm) + { + case 1: + case 2: + case 3: /* RSA */ + npkey = 2; + break; + case 16: + case 20: /* Elgamal */ + npkey = 3; + break; + case 17: /* DSA */ + npkey = 4; + break; + default: /* Unknown algorithm. */ + return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); + } + + for (i=0; i < npkey; i++ ) + { + unsigned int nbits, nbytes; + + if (datalen < 2) + return gpg_error (GPG_ERR_INV_PACKET); + nbits = ((data[0]<<8)|(data[1])); + data += 2; datalen -=2; + nbytes = (nbits+7) / 8; + if (datalen < nbytes) + return gpg_error (GPG_ERR_INV_PACKET); + /* For use by v3 fingerprint calculation we need to know the RSA + modulus and exponent. */ + if (i==0) + { + mpi_n = data; + mpi_n_len = nbytes; + } + else if (i==1) + mpi_e_len = nbytes; + + data += nbytes; datalen -= nbytes; + } + n = data - data_start; + + if (version < 4) + { + /* We do not support any other algorithm than RSA in v3 + packets. */ + if (algorithm < 1 || algorithm > 3) + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + + err = gcry_md_open (&md, GCRY_MD_MD5, 0); + if (err) + return err; /* Oops */ + gcry_md_write (md, mpi_n, mpi_n_len); + gcry_md_write (md, mpi_n+mpi_n_len+2, mpi_e_len); + memcpy (ki->fpr, gcry_md_read (md, 0), 16); + gcry_md_close (md); + ki->fprlen = 16; + + if (mpi_n_len < 8) + { + /* Moduli less than 64 bit are out of the specs scope. Zero + them out becuase this is what gpg does too. */ + memset (ki->keyid, 0, 8); + } + else + memcpy (ki->keyid, mpi_n + mpi_n_len - 8, 8); + } + else + { + /* Its a pitty that we need to prefix the buffer with the tag + and a length header: We can't simply psss it to the fast + hashing fucntion for that reason. It might be a good idea to + have a scatter-gather enabled hash function. What we do here + is to use a static buffer if this one is large enough and + only use the regular hash fucntions if this buffer is not + large enough. */ + if ( 3 + n < sizeof hashbuffer ) + { + hashbuffer[0] = 0x99; /* CTB */ + hashbuffer[1] = (n >> 8); /* 2 byte length header. */ + hashbuffer[2] = n; + memcpy (hashbuffer + 3, data_start, n); + gcry_md_hash_buffer (GCRY_MD_SHA1, ki->fpr, hashbuffer, 3 + n); + } + else + { + err = gcry_md_open (&md, GCRY_MD_SHA1, 0); + if (err) + return err; /* Oops */ + gcry_md_putc (md, 0x99 ); /* CTB */ + gcry_md_putc (md, (n >> 8) ); /* 2 byte length header. */ + gcry_md_putc (md, n ); + gcry_md_write (md, data_start, n); + memcpy (ki->fpr, gcry_md_read (md, 0), 20); + gcry_md_close (md); + } + ki->fprlen = 20; + memcpy (ki->keyid, ki->fpr+12, 8); + } + + return 0; +} + + + +/* The caller must pass the address of an INFO structure which will + get filled on success with information pertaining to the OpenPGP + keyblock IMAGE of length IMAGELEN. Note that a caller does only + need to release this INFO structure when the function returns + success. If NPARSED is not NULL the actual number of bytes parsed + will be stored at this address. */ +gpg_error_t +_keybox_parse_openpgp (const unsigned char *image, size_t imagelen, + size_t *nparsed, + keybox_openpgp_info_t info) +{ + gpg_error_t err = 0; + const unsigned char *image_start, *data; + size_t n, datalen; + int pkttype; + int first = 1; + struct _keybox_openpgp_key_info *k, **ktail = NULL; + struct _keybox_openpgp_uid_info *u, **utail = NULL; + + memset (info, 0, sizeof *info); + if (nparsed) + *nparsed = 0; + + image_start = image; + while (image) + { + err = next_packet (&image, &imagelen, &data, &datalen, &pkttype, &n); + if (err) + break; + + if (first) + { + if (pkttype == PKT_PUBLIC_KEY) + ; + else if (pkttype == PKT_SECRET_KEY) + info->is_secret = 1; + else + { + err = gpg_error (GPG_ERR_UNEXPECTED); + break; + } + first = 0; + } + else if (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY) + break; /* Next keyblock encountered - ready. */ + + if (nparsed) + *nparsed += n; + + if (pkttype == PKT_SIGNATURE) + { + /* For now we only count the total number of signatures. */ + info->nsigs++; + } + else if (pkttype == PKT_USER_ID) + { + info->nuids++; + if (info->nuids == 1) + { + info->uids.off = data - image_start; + info->uids.len = datalen; + utail = &info->uids.next; + } + else + { + u = xtrycalloc (1, sizeof *u); + if (!u) + { + err = gpg_error_from_errno (errno); + break; + } + u->off = data - image_start; + u->len = datalen; + *utail = u; + utail = &u->next; + } + } + else if (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY) + { + err = parse_key (data, datalen, &info->primary); + if (err) + break; + } + else if( pkttype == PKT_PUBLIC_SUBKEY && datalen && *data == '#' ) + { + /* Early versions of GnuPG used old PGP comment packets; + * luckily all those comments are prefixed by a hash + * sign - ignore these packets. */ + } + else if (pkttype == PKT_PUBLIC_SUBKEY || pkttype == PKT_SECRET_SUBKEY) + { + info->nsubkeys++; + if (info->nsubkeys == 1) + { + err = parse_key (data, datalen, &info->subkeys); + if (err) + { + info->nsubkeys--; + if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM) + break; + /* We ignore subkeys with unknown algorithms. */ + } + else + ktail = &info->subkeys.next; + } + else + { + k = xtrycalloc (1, sizeof *k); + if (!k) + { + err = gpg_error_from_errno (errno); + break; + } + err = parse_key (data, datalen, k); + if (err) + { + xfree (k); + info->nsubkeys--; + if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM) + break; + /* We ignore subkeys with unknown algorithms. */ + } + else + { + *ktail = k; + ktail = &k->next; + } + } + } + } + + if (err) + { + _keybox_destroy_openpgp_info (info); + if (!first + && (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM + || gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM)) + { + /* We are able to skip to the end of this keyblock. */ + while (image) + { + if (next_packet (&image, &imagelen, + &data, &datalen, &pkttype, &n) ) + break; /* Another error - stop here. */ + + if (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY) + break; /* Next keyblock encountered - ready. */ + + if (nparsed) + *nparsed += n; + } + } + } + + return err; +} + + +/* Release any malloced data in INFO but not INFO itself! */ +void +_keybox_destroy_openpgp_info (keybox_openpgp_info_t info) +{ + struct _keybox_openpgp_key_info *k, *k2; + struct _keybox_openpgp_uid_info *u, *u2; + + assert (!info->primary.next); + for (k=info->subkeys.next; k; k = k2) + { + k2 = k->next; + xfree (k); + } + + for (u=info->uids.next; u; u = u2) + { + u2 = u->next; + xfree (u); + } +} -- cgit v1.2.3 From 452e415784b5bed128ed1ae517110361e5212c8c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 31 Aug 2004 07:57:33 +0000 Subject: * openfile.c (copy_options_file): Use gpg-conf.skel * Makefile.am: Install options.skel as gpg-conf.skel. --- g10/ChangeLog | 5 +++++ g10/Makefile.am | 2 +- g10/openfile.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index e472a626f..429ab368d 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2004-08-31 Werner Koch <wk@g10code.de> + + * openfile.c (copy_options_file): Use gpg-conf.skel + * Makefile.am: Install options.skel as gpg-conf.skel. + 2004-08-18 Marcus Brinkmann <marcus@g10code.de> * passphrase.c (agent_get_passphrase): Fix detection of gpg-agent diff --git a/g10/Makefile.am b/g10/Makefile.am index fc33acf73..53d748ee0 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -117,5 +117,5 @@ $(PROGRAMS): $(needed_libs) install-data-local: $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) $(INSTALL_DATA) $(srcdir)/options.skel \ - $(DESTDIR)$(pkgdatadir)/options.skel + $(DESTDIR)$(pkgdatadir)/gpg-conf.skel diff --git a/g10/openfile.c b/g10/openfile.c index 7dbbf7d6a..663c2c5d3 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -309,7 +309,7 @@ copy_options_file( const char *destdir ) return; fname = xmalloc ( strlen(datadir) + strlen(destdir) + 15 ); - strcpy(stpcpy(fname, datadir), DIRSEP_S "options" SKELEXT ); + strcpy(stpcpy(fname, datadir), DIRSEP_S "gpg-conf" SKELEXT ); src = fopen( fname, "r" ); if( !src ) { log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); -- cgit v1.2.3 From 45accef52a9e703bd204087abc2dc0a4e15d57ac Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 31 Aug 2004 09:00:58 +0000 Subject: Better take the length of SKELEXT into account --- g10/ChangeLog | 3 ++- g10/openfile.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 429ab368d..498d247b9 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,6 +1,7 @@ 2004-08-31 Werner Koch <wk@g10code.de> - * openfile.c (copy_options_file): Use gpg-conf.skel + * openfile.c (copy_options_file): Use gpg-conf.skel. Better take + the length of SKELEXT into account, someone might make it larger. * Makefile.am: Install options.skel as gpg-conf.skel. 2004-08-18 Marcus Brinkmann <marcus@g10code.de> diff --git a/g10/openfile.c b/g10/openfile.c index 663c2c5d3..dbf42db78 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -308,7 +308,8 @@ copy_options_file( const char *destdir ) if( opt.dry_run ) return; - fname = xmalloc ( strlen(datadir) + strlen(destdir) + 15 ); + fname = xmalloc ( strlen(datadir) + strlen(destdir) + strlen (SKELEXT) + 15 ); strcpy(stpcpy(fname, datadir), DIRSEP_S "gpg-conf" SKELEXT ); src = fopen( fname, "r" ); if( !src ) { -- cgit v1.2.3 From 0cb56ad4ac39b77f7d53ec91174583b5568e5155 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Sep 2004 07:27:57 +0000 Subject: (check_for_running_agent): New. (main): The default action is now to check for an already running agent. (parse_rereadable_options): Set logfile only on reread. (main): Do not print the "is development version" note. --- NEWS | 6 +++++ THANKS | 4 +-- agent/ChangeLog | 8 ++++++ agent/gpg-agent.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 2fbf6475e..a93c7ce80 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,12 @@ Noteworthy changes in version 1.9.11 certificates are validated and only imported if they are fully valid. + * [gpg-agent] New option --max-cache-ttl. + + * [gpg-agent] When used without --daemon or --server, gpg-agent now + check whether a agent is already running and usable. + + Noteworthy changes in version 1.9.10 (2004-07-22) ------------------------------------------------- diff --git a/THANKS b/THANKS index 3f56e29d3..d523474c7 100644 --- a/THANKS +++ b/THANKS @@ -1,5 +1,5 @@ - -Richard Lefebvre rick at CERCA.UMontreal.CA +Alexander Belopolsky belopolsky at mac.com +Richard Lefebvre rick at cerca.umontreal.ca Andrew J. Schorr aschorr at telemetry-investments.com Michael Nottebrock michaelnottebrock at gmx.net diff --git a/agent/ChangeLog b/agent/ChangeLog index 220eb21e4..470c70162 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2004-09-09 Werner Koch <wk@g10code.de> + + * gpg-agent.c (check_for_running_agent): New. + (main): The default action is now to check for an already running + agent. + (parse_rereadable_options): Set logfile only on reread. + (main): Do not print the "is development version" note. + 2004-08-20 Werner Koch <wk@g10code.de> * gpg-agent.c: New option --max-cache-ttl. Suggested by Alexander diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 6aa3e6d67..4e3f0b507 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -178,6 +178,7 @@ static void handle_connections (int listen_fd); GCRY_THREAD_OPTION_PTH_IMPL; #endif /*USE_GNU_PTH*/ +static void check_for_running_agent (void); @@ -361,8 +362,9 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oDebugLevel: debug_level = pargs->r.ret_str; break; case oLogFile: - if (!current_logfile || !pargs->r.ret_str - || strcmp (current_logfile, pargs->r.ret_str)) + if (reread + && (!current_logfile || !pargs->r.ret_str + || strcmp (current_logfile, pargs->r.ret_str))) { log_set_file (pargs->r.ret_str); xfree (current_logfile); @@ -599,7 +601,9 @@ main (int argc, char **argv ) fprintf (stderr, "%s\n", strusage(15) ); } #ifdef IS_DEVELOPMENT_VERSION - log_info ("NOTE: this is a development version!\n"); + /* We don't want to print it here because gpg-agent is useful of its + own and quite matured. */ + /*log_info ("NOTE: this is a development version!\n");*/ #endif set_debug (); @@ -669,9 +673,15 @@ main (int argc, char **argv ) agent_exit (0); } + /* If this has been called without any options, we merely check + whether an agent is already running. We do this here so that we + don't clobber a logfile but print it directly to stderr. */ if (!pipe_server && !is_daemon) - log_info (_("please use the option `--daemon'" - " to run the program in the background\n")); + { + log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX); + check_for_running_agent (); + agent_exit (0); + } #ifdef ENABLE_NLS /* gpg-agent usually does not output any messages because it runs in @@ -705,9 +715,9 @@ main (int argc, char **argv ) start_command_handler (-1, -1); } else if (!is_daemon) - ; + ; /* NOTREACHED */ else - { /* regular server mode */ + { /* Regular server mode */ int fd; pid_t pid; int len; @@ -1220,3 +1230,56 @@ handle_connections (int listen_fd) log_info ("%s %s stopped\n", strusage(11), strusage(13)); } #endif /*USE_GNU_PTH*/ + + +/* Figure out whether an agent is available and running. Prints an + error if not. */ +static void +check_for_running_agent () +{ + int rc; + char *infostr, *p; + assuan_context_t ctx; + int prot, pid; + + infostr = getenv ("GPG_AGENT_INFO"); + if (!infostr || !*infostr) + { + log_error (_("no gpg-agent running in this session\n")); + return; + } + + infostr = xstrdup (infostr); + if ( !(p = strchr (infostr, ':')) || p == infostr) + { + log_error (_("malformed GPG_AGENT_INFO environment variable\n")); + xfree (infostr); + return; + } + + *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); + return; + } + + rc = assuan_socket_connect (&ctx, infostr, pid); + xfree (infostr); + if (rc) + { + log_error ("can't connect to the agent: %s\n", assuan_strerror (rc)); + return; + } + + if (!opt.quiet) + log_info ("gpg-agent running and available\n"); + + assuan_disconnect (ctx); +} -- cgit v1.2.3 From 9d74d40da1e3b58a994dc3435e6feb07fb1fc420 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Sep 2004 07:28:47 +0000 Subject: * app.c (select_application): Fixed serial number extraction and added the BMI card workaround. (app_munge_serialno): New. * app-openpgp.c (app_select_openpgp): Try munging serialno. --- scd/ChangeLog | 7 +++++++ scd/app-common.h | 4 ++++ scd/app-openpgp.c | 7 +++++++ scd/app.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 80b244ef1..a527b5da5 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2004-08-20 Werner Koch <wk@g10code.de> + + * app.c (select_application): Fixed serial number extraction and + added the BMI card workaround. + (app_munge_serialno): New. + * app-openpgp.c (app_select_openpgp): Try munging serialno. + 2004-08-05 Werner Koch <wk@g10code.de> * scdaemon.c (main): New option --disable-application. diff --git a/scd/app-common.h b/scd/app-common.h index c61bcca60..c15f174bf 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -95,6 +95,7 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); /*-- app.c --*/ app_t select_application (ctrl_t ctrl, int slot, const char *name); void release_application (app_t app); +int app_munge_serialno (app_t app); int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); int app_write_learn_status (app_t app, ctrl_t ctrl); int app_readcert (app_t app, const char *certid, @@ -159,6 +160,9 @@ int app_select_nks (app_t app); /*-- app-dinsig.c --*/ int app_select_dinsig (app_t app); +/*-- app-p15.c --*/ +int app_select_p15 (app_t app); + #endif diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 3dc015baa..67bc336ec 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1394,6 +1394,13 @@ app_select_openpgp (APP app) log_info ("got AID: "); log_printhex ("", buffer, buflen); } +#if GNUPG_MAJOR_VERSION != 1 + /* A valid OpenPGP card should never need this but well the test + is cheap. */ + rc = app_number_serialno (app); + if (rc) + goto leave; +#endif app->card_version = buffer[6] << 8; app->card_version |= buffer[7]; diff --git a/scd/app.c b/scd/app.c index b3a13f19a..55fb5861e 100644 --- a/scd/app.c +++ b/scd/app.c @@ -1,5 +1,5 @@ /* app.c - Application selection. - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -45,6 +45,7 @@ is_app_allowed (const char *name) return 1; /* yes */ } + /* If called with NAME as NULL, select the best fitting application and return a context; otherwise select the application with NAME and return a context. SLOT identifies the reader device. Returns @@ -81,31 +82,50 @@ select_application (ctrl_t ctrl, int slot, const char *name) const unsigned char *p; p = find_tlv (result, resultlen, 0x5A, &n); - if (p && n && n >= (resultlen - (p - result))) + if (p) + resultlen -= (p-result); + if (p && n > resultlen && n == 0x0d && resultlen+1 == n) + { + /* The object it does not fit into the buffer. This is an + invalid encoding (or the buffer is too short. However, I + have some test cards with such an invalid encoding and + therefore I use this ugly workaround to return something + I can further experiment with. */ + log_debug ("enabling BMI testcard workaround\n"); + n--; + } + + if (p && n <= resultlen) { /* The GDO file is pretty short, thus we simply reuse it for storing the serial number. */ memmove (result, p, n); app->serialno = result; app->serialnolen = n; + rc = app_munge_serialno (app); + if (rc) + goto leave; } else xfree (result); result = NULL; } - + rc = gpg_error (GPG_ERR_NOT_FOUND); if (rc && is_app_allowed ("openpgp") && (!name || !strcmp (name, "openpgp"))) rc = app_select_openpgp (app); if (rc && is_app_allowed ("nks") && (!name || !strcmp (name, "nks"))) rc = app_select_nks (app); +/* if (rc && is_app_allowed ("p12") && (!name || !strcmp (name, "p12"))) */ +/* rc = app_select_p12 (app); */ if (rc && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) rc = app_select_dinsig (app); if (rc && name) rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + leave: if (rc) { if (name) @@ -141,6 +161,39 @@ release_application (app_t app) +/* The serial number may need some cosmetics. Do it here. This + function shall only be called once after a new serial number has + been put into APP->serialno. + + Prefixes we use: + + FF 00 00 = For serial numbers starting with an FF + FF 01 00 = Some german p15 cards return an empty serial number so the + serial number from the EF(TokeInfo is used instead. + + All other serial number not starting with FF are used as they are. +*/ +int +app_munge_serialno (app_t app) +{ + if (app->serialnolen && app->serialno[0] == 0xff) + { + /* The serial number starts with our special prefix. This + requires that we put our default prefix "FF0000" in front. */ + unsigned char *p = xtrymalloc (app->serialnolen + 3); + if (!p) + return gpg_error (gpg_err_code_from_errno (errno)); + memcpy (p, "\xff\0", 3); + memcpy (p+3, app->serialno, app->serialnolen); + app->serialnolen += 3; + xfree (app->serialno); + app->serialno = p; + } + return 0; +} + + + /* Retrieve the serial number and the time of the last update of the card. The serial number is returned as a malloced string (hex encoded) in SERIAL and the time of update is returned in STAMP. If -- cgit v1.2.3 From 609d9516be858663a8e560fa4561a5730e5061db Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Sep 2004 07:29:35 +0000 Subject: doc --max-cache-ttl --- doc/gpg-agent.texi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index aad0fbb68..460cca45a 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -255,6 +255,12 @@ control this behaviour but this command line option takes precedence. Set the time a cache entry is valid to @var{n} seconds. The default are 600 seconds. +@item --max-cache-ttl @var{n} +@opindex max-cache-ttl +Set the maximum time a cache entry is valid to @var{n} seconds. After +this time a cache entry will get expired even if it has been accessed +recently. The default are 2 hours (7200 seconds). + @item --pinentry-program @var{filename} @opindex pinentry-program Use program @var{filename} as the PIN entry. The default is installation -- cgit v1.2.3 From 305f910ed2da1cba6785d8158bd771da72e317cf Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sat, 11 Sep 2004 13:34:41 +0000 Subject: 2004-09-11 Moritz Schulte <moritz@g10code.com> * openfile.c (copy_options_file): Fixed last commit (added a `+'). --- g10/ChangeLog | 4 ++++ g10/openfile.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 498d247b9..d33dcdc36 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2004-09-11 Moritz Schulte <moritz@g10code.com> + + * openfile.c (copy_options_file): Fixed last commit (added a `+'). + 2004-08-31 Werner Koch <wk@g10code.de> * openfile.c (copy_options_file): Use gpg-conf.skel. Better take diff --git a/g10/openfile.c b/g10/openfile.c index dbf42db78..faf9a2cd6 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -309,7 +309,7 @@ copy_options_file( const char *destdir ) return; fname = xmalloc ( strlen(datadir) + strlen(destdir) - strlen (SKELEXT) + 15 ); + + strlen (SKELEXT) + 15 ); strcpy(stpcpy(fname, datadir), DIRSEP_S "gpg-conf" SKELEXT ); src = fopen( fname, "r" ); if( !src ) { -- cgit v1.2.3 From f103eeb9da5283bfd1997f8e061b95a05a83a1b6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 11 Sep 2004 14:32:37 +0000 Subject: Collection of artwork collected over the years --- artwork/README | 2 ++ artwork/ascii-key | 5 +++++ artwork/gnu-head-sm.jpg | Bin 0 -> 6006 bytes artwork/gnu1.jpg | Bin 0 -> 20302 bytes artwork/gnu5.png | Bin 0 -> 5378 bytes artwork/gnud.png | Bin 0 -> 5766 bytes artwork/gnue.png | Bin 0 -> 6294 bytes artwork/gnue2.png | Bin 0 -> 5970 bytes artwork/gnupg-1.0-available-now.png | Bin 0 -> 4480 bytes artwork/gnupg-1.0-ist-da.png | Bin 0 -> 4296 bytes artwork/gnupg-badge-openpgp.cdr.gz | Bin 0 -> 32969 bytes artwork/gnupg-badge-openpgp.eps.gz | Bin 0 -> 386093 bytes artwork/gnupg-badge-openpgp.jpg | Bin 0 -> 63450 bytes artwork/gnupg-logo-black.jpg | Bin 0 -> 38505 bytes artwork/gnupg-logo-cia.jpg | Bin 0 -> 23438 bytes artwork/gnupg-logo-cia2.jpg | Bin 0 -> 63450 bytes artwork/gnurieg.png | Bin 0 -> 1701 bytes artwork/gpglogo.eps.gz | Bin 0 -> 89069 bytes artwork/gpglogo.jpg | Bin 0 -> 3963 bytes artwork/tl-gnu1.jpg | Bin 0 -> 4942 bytes 20 files changed, 7 insertions(+) create mode 100644 artwork/README create mode 100644 artwork/ascii-key create mode 100644 artwork/gnu-head-sm.jpg create mode 100644 artwork/gnu1.jpg create mode 100644 artwork/gnu5.png create mode 100644 artwork/gnud.png create mode 100644 artwork/gnue.png create mode 100644 artwork/gnue2.png create mode 100644 artwork/gnupg-1.0-available-now.png create mode 100644 artwork/gnupg-1.0-ist-da.png create mode 100644 artwork/gnupg-badge-openpgp.cdr.gz create mode 100644 artwork/gnupg-badge-openpgp.eps.gz create mode 100644 artwork/gnupg-badge-openpgp.jpg create mode 100644 artwork/gnupg-logo-black.jpg create mode 100644 artwork/gnupg-logo-cia.jpg create mode 100644 artwork/gnupg-logo-cia2.jpg create mode 100644 artwork/gnurieg.png create mode 100644 artwork/gpglogo.eps.gz create mode 100644 artwork/gpglogo.jpg create mode 100644 artwork/tl-gnu1.jpg diff --git a/artwork/README b/artwork/README new file mode 100644 index 000000000..990fed62e --- /dev/null +++ b/artwork/README @@ -0,0 +1,2 @@ +These is a collection of graphics used in connection with GnuPG. It +is not part of GnuPG proper. [wk 2004-09-11] diff --git a/artwork/ascii-key b/artwork/ascii-key new file mode 100644 index 000000000..3540f7eec --- /dev/null +++ b/artwork/ascii-key @@ -0,0 +1,5 @@ + + .-. +( )====GnuPG + `-' + diff --git a/artwork/gnu-head-sm.jpg b/artwork/gnu-head-sm.jpg new file mode 100644 index 000000000..2a9746a25 Binary files /dev/null and b/artwork/gnu-head-sm.jpg differ diff --git a/artwork/gnu1.jpg b/artwork/gnu1.jpg new file mode 100644 index 000000000..5637bcc17 Binary files /dev/null and b/artwork/gnu1.jpg differ diff --git a/artwork/gnu5.png b/artwork/gnu5.png new file mode 100644 index 000000000..e1cd68f97 Binary files /dev/null and b/artwork/gnu5.png differ diff --git a/artwork/gnud.png b/artwork/gnud.png new file mode 100644 index 000000000..73a72bbcf Binary files /dev/null and b/artwork/gnud.png differ diff --git a/artwork/gnue.png b/artwork/gnue.png new file mode 100644 index 000000000..881889cfc Binary files /dev/null and b/artwork/gnue.png differ diff --git a/artwork/gnue2.png b/artwork/gnue2.png new file mode 100644 index 000000000..7cd20d690 Binary files /dev/null and b/artwork/gnue2.png differ diff --git a/artwork/gnupg-1.0-available-now.png b/artwork/gnupg-1.0-available-now.png new file mode 100644 index 000000000..f5adeb9fa Binary files /dev/null and b/artwork/gnupg-1.0-available-now.png differ diff --git a/artwork/gnupg-1.0-ist-da.png b/artwork/gnupg-1.0-ist-da.png new file mode 100644 index 000000000..2438cf74f Binary files /dev/null and b/artwork/gnupg-1.0-ist-da.png differ diff --git a/artwork/gnupg-badge-openpgp.cdr.gz b/artwork/gnupg-badge-openpgp.cdr.gz new file mode 100644 index 000000000..b50f28645 Binary files /dev/null and b/artwork/gnupg-badge-openpgp.cdr.gz differ diff --git a/artwork/gnupg-badge-openpgp.eps.gz b/artwork/gnupg-badge-openpgp.eps.gz new file mode 100644 index 000000000..aa76f193e Binary files /dev/null and b/artwork/gnupg-badge-openpgp.eps.gz differ diff --git a/artwork/gnupg-badge-openpgp.jpg b/artwork/gnupg-badge-openpgp.jpg new file mode 100644 index 000000000..fc4b2a8dd Binary files /dev/null and b/artwork/gnupg-badge-openpgp.jpg differ diff --git a/artwork/gnupg-logo-black.jpg b/artwork/gnupg-logo-black.jpg new file mode 100644 index 000000000..fb7173749 Binary files /dev/null and b/artwork/gnupg-logo-black.jpg differ diff --git a/artwork/gnupg-logo-cia.jpg b/artwork/gnupg-logo-cia.jpg new file mode 100644 index 000000000..9ced3c077 Binary files /dev/null and b/artwork/gnupg-logo-cia.jpg differ diff --git a/artwork/gnupg-logo-cia2.jpg b/artwork/gnupg-logo-cia2.jpg new file mode 100644 index 000000000..fc4b2a8dd Binary files /dev/null and b/artwork/gnupg-logo-cia2.jpg differ diff --git a/artwork/gnurieg.png b/artwork/gnurieg.png new file mode 100644 index 000000000..0de179a9d Binary files /dev/null and b/artwork/gnurieg.png differ diff --git a/artwork/gpglogo.eps.gz b/artwork/gpglogo.eps.gz new file mode 100644 index 000000000..6b8616bf9 Binary files /dev/null and b/artwork/gpglogo.eps.gz differ diff --git a/artwork/gpglogo.jpg b/artwork/gpglogo.jpg new file mode 100644 index 000000000..3fff990a1 Binary files /dev/null and b/artwork/gpglogo.jpg differ diff --git a/artwork/tl-gnu1.jpg b/artwork/tl-gnu1.jpg new file mode 100644 index 000000000..c3842ea87 Binary files /dev/null and b/artwork/tl-gnu1.jpg differ -- cgit v1.2.3 From 9ec1437772d84ccaf32fd1bdde170e7667bc54b7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 11 Sep 2004 14:50:35 +0000 Subject: Some more new files --- artwork/gpglogo.fig | 36 ++++++++ doc/Notes | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 artwork/gpglogo.fig create mode 100644 doc/Notes diff --git a/artwork/gpglogo.fig b/artwork/gpglogo.fig new file mode 100644 index 000000000..bed127833 --- /dev/null +++ b/artwork/gpglogo.fig @@ -0,0 +1,36 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +0 32 #414541 +0 33 #8e8e8e +0 34 #414541 +0 35 #8e8e8e +0 36 #8e8e8e +6 91 46 7785 7740 +1 3 0 2 0 7 100 0 -1 0.000 1 0.0000 3938 3893 3832 3832 3938 3893 7763 4118 +1 3 0 2 0 7 100 0 -1 0.000 1 0.0000 3938 3893 2959 2959 3938 3893 6863 4343 +2 5 0 1 0 -1 100 0 -1 0.000 0 0 -1 0 0 5 + 0 tmp/gnu1.jpg + 1628 2303 6248 2303 6248 5633 1628 5633 1628 2303 +4 0 0 100 0 30 40 0.0000 4 450 480 3713 743 N\001 +4 0 0 100 0 30 40 0.2618 4 450 465 2918 908 G\001 +4 0 0 100 0 30 40 6.0214 4 450 450 4527 791 U\001 +4 0 0 100 0 30 40 6.0214 4 330 330 3046 7398 c\001 +4 0 0 100 0 30 40 0.8727 4 330 285 6684 6299 r\001 +4 0 0 100 0 30 40 0.0000 4 465 390 3668 7493 y\001 +4 0 0 100 0 30 40 5.9341 4 330 345 2488 7193 a\001 +4 0 0 100 0 30 40 5.7596 4 330 390 1944 6889 v\001 +4 0 0 100 0 30 40 5.4978 4 465 195 1562 6609 i\001 +4 0 0 100 0 30 40 5.4105 4 330 285 1198 6206 r\001 +4 0 0 100 0 30 40 5.3233 4 450 375 826 5724 P\001 +4 0 0 100 0 30 40 0.5236 4 330 390 5681 7140 u\001 +4 0 0 100 0 30 40 0.6981 4 330 345 6247 6739 a\001 +4 0 0 100 0 30 40 1.0472 4 465 390 7039 5909 d\001 +4 0 0 100 0 30 40 0.3491 4 450 465 5031 7399 G\001 +-6 diff --git a/doc/Notes b/doc/Notes new file mode 100644 index 000000000..4a990776e --- /dev/null +++ b/doc/Notes @@ -0,0 +1,242 @@ +> * How to mark a CA certificate as trusted. + +There are two ways: + + 1. Let gpg-agent do this for you. Since version 1.9.9 you need to + add the option --allow-mark-trusted gpg-agent.conf or when + invoking gpg-agent. Everytime gpgsm notices an untrusted root + certificate gpg-agent will pop up a dialog to ask whether this + certificate should be trusted. This is similar to whatmost + browsers do. + + The disadvantage of this method and the reason why + --allow-mark-trusted is required is that the list of trusted root + certificates will grow, because almost all user will just hit + "yes, I trust" and "yes, I verified the fingerprint" without + understanding that this is a very serious decision. + + 2. Use your editor. Edit the file ~/.gnupg/trustlist.txt and add + the fingerprints of the trusted root certificates. There are + comments on the top explaining the simple format. The current + CVS version allows for colons in the fingerprint, so you can + easily cut and paste it from whereever you know that this is the + correct fingerprint. + +An example for an entry in the trustlist.txt is: + + # CN=PCA-1-Verwaltung,O=PKI-1-Verwaltung,C=de + 3EEE3D8BB7F0FE5C9F5804A3A7E51BCE98209DF9 S + +This is in fact one that probably made its way into the file using the +first method. As usual a # indicates a comment. The trailing S means +that this is to be used for (X.509). + +It is not possible to trust intermediate CA certificates; gpgsm always +checks the entire chain of certificates. + +> * How to import a key and bind it to some certificate already +> imported. Alternatively, import key and certificate together, from +> a pkcs12 blob, or pkcs8 + certificate blobs, or whatever. +> Alternatively, don't import the key at all, but specify location of +> key using a parameter when signing. + +You always need to import the key; there is something similar to a +keyring (here called a keybox: ~/.gnupg/pubring.kbx). + +Importing a key either from a binary or ascii armored (PEM) certificate +file or from a cert-only signature file is done using + + gpg --import FILE + +or + + gpg --import < FILE + +In general you should first import the root certificates and then down +to the end user certificate. You may put all into one file and gpgsm +will do the right thing in this case independend of the order. + +While verifying a signature, all included certificates are +automagically imported. + +To import from a pkcs#12 file you may use the same command; if a +private key is contained in that file, you will be asked for the +transport passphrases as well as for the new passphrase used to +protect it in gpg-agent's private key storage +(~/.gnupg/private-keys-v1.d/). Note that the pkcs#12 support is very +basic but sufficient for certificates exported from Mozilla, OpenSSL +and MS Outlook. + +Background info on private keys: + +If you want to look at the private key you first need to know the name +of the keyfile. Run the command "gpgsm -K --with-key-data [KEYID]" and +you get an output like: + + crs::1024:1:CF8[..]6D:20040105T184908:2006[...]:09::CN=ZS[....]::esES: + fpr:::::::::3B50BF2BDAF2[...]1AE6796D:::2812[...]508F21F065E65E44: + grp:::::::::C92DB9CFD588ADE846BE3AC4E7A2E1B11A4A2ADB: + uid:::::::::CN=Werner Koch,OU=test,O=g10 Code,C=de:: + uid:::::::::<wk@g10code.de>:: + +This should be familar to advanced gpg-users; see doc/DETAILS in gpg +1.3 (CVS HEAD) for a description of the records. The value in the +"grp" tagged record is the so called keygrip and you should find a +file ~/.gnupg/private-keys-v1.d/C92DB9CFD588ADE846BE3AC4E7A2E1B11A4A2ADB.key +with the private and public key in an S-expression like format. The +gpg-protect-tool may be used to display it in a human readable format: + + $ gpgsm --call-protect-tool ~/.gnupg/private-keys-v1.d/C9[...]B.key + (protected-private-key + (rsa + (n #00C16B6E807C47BB[...]10487#) + (e #010001#) + (protected openpgp-s2k3-sha1-aes-cbc + ( + (sha1 "Hvü9Qt^Ç" "96") + #2B17DC766AEA2568EE0C688E18F9757E#) + #65A4FF9F30750A1300[...]7#) + ) + ) + +The current CVS version of gpgsm has a command --dump-keys which lists +more details of a key including the keygrip so you don't need to use +the colon format if you want to manually debug things. + + $ gpgsm --dump-keys + Serial number: 01 + Issuer: CN=Trust Anchor,O=Test Certificates,C=US + Subject: CN=Trust Anchor,O=Test Certificates,C=US + sha1_fpr: 66:8A:47:56:A2:DC:88:FF:DA:B8:95:E1:3C:63:37:55:5F:0A:F7:BF + md5_fpr: 03:01:3B:BB:EC:6C:5D:48:88:4C:95:63:99:84:ED:C0 + keygrip: 6A082B3063F6DA6D68B2994AB11B4328FD6206D2 + notBefore: 2001-04-19 14:57:20 + notAfter: 2011-04-19 14:57:20 + hashAlgo: 1.2.840.113549.1.1.5 (sha1WithRSAEncryption) + keyType: 1024 bit RSA + authKeyId: [none] + keyUsage: certSign crlSign + extKeyUsage: [none] + policies: [none] + chainLength: unlimited + crlDP: [none] + authInfo: [none] + subjInfo: [none] + extn: 2.5.29.14 (subjectKeyIdentifier) [22 octets] + +> * How to import a CRL + +CRLs are managed by the dirmngr which is a separate package. The idea +is to eventaully turn it into a system daemon, so that on a multi-user +machine CRLs are handled more efficiently. As of now the dirmngr +needs service from gpgsm thus it is best to call it through gpgsm: + + gpgsm --call-dirmngr LOAD /absolute/filename/to/a/CRL/file + +See the dirmngr README and manual for further details. + +If you don't want to check CRLs, use the option --diable-crl-checks +with gpgsm. + +> I'm trying to replace the S/MIME support in OpenSSL with gpgsm for the +> MUA Gnus. + +Great; I'd love it. + +> Perhaps I shouldn't be using gpgsm directly? gpgme didn't seem to +> have a command line front end. + +For Gnus it makes sense to use gpgsm directly. Enhancing pgg to +support gpgsm should not be that hard. Things you need to take care +off are: Warn if GPG_AGENT_INFO has not been set, because this will +call gpg-agent for each operation and obviously does not cache the +passphrase them. If GPG_AGENT_INFO has been set, also disable the +passphrase code for gpg and pass --use-agent to gpg - this way gpg +benefits from the passphrase caching and the pinentry. + +You may want to look at gpgconf (tools/README.gpgconf) to provide a +customization interface for gpgsm, gpg-agent and dirmngr. + + +Module Overview +================ + +gpgsm + libgpg-error + libgcrypt + libksba + libassuan [statically linked] + [Standard system libraries] + +gpg-agent + libgpg-error + libgcrypt + libassuan [statically linked] + libpth [system library] + [Standard system libraries] + +scdaemon + libgpg-error + libgcrypt + libksba + libassuan [statically linked] + libusb [system library, optional] + libopensc [system library, optional] + [For reader access libpcsclite or a CT-API library may be + linked at runtime (controllable by scdaemon.conf)] + [Standard system libraries] + +gpg-protect-tool + libgpg-error + libgcrypt + [Standard system libraries] + +dirmngr + libgpg-error + libgcrypt + libksba + libassuan [statically linked] + libldap [system libary] + liblber [system libary] + libsasl [system libary, required by libldap] + libdb2 [system libary, required by libsasl] + libcrypt [system libary, required by libsasl - OOPS] + libpam [system libary, required by libsasl] + [Standard system libraries] + +pinentry-curses + libncurses + [Standard system libraries] + [Independent Assuan code is source included] + +pinentry-gtk + libncurses + [GTK+ and X libraries] + [Standard system libraries] + [Independent Assuan code is source included] + +pinentry-qt + libncurses + [QT and X libraries] + [Standard system libraries] + [Independent Assuan code is source included] + +gpgme + [Standard system libraries] + [gpgsm is required at runtime] + [Independent Assuan code is source included] + +libgpg-error + [none] + +libgcrypt + libgpg-error + +libksba + libgpg-error + +libassuan + [none] + + + -- cgit v1.2.3 From f10040147834bbc5cc75f02b7215f2b45642ecaf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 20 Sep 2004 18:47:11 +0000 Subject: (show_key_with_all_names): Print the card S/N. * app-openpgp.c (app_select_openpgp): Its app_munge_serialno and not app_number_serialno. --- g10/ChangeLog | 4 ++++ g10/keyedit.c | 21 +++++++++++++++++++++ scd/ChangeLog | 5 +++++ scd/app-openpgp.c | 2 +- sm/ChangeLog | 6 ++++++ sm/certchain.c | 15 ++++++++++++--- 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index d33dcdc36..b553c1c9f 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2004-09-20 Werner Koch <wk@g10code.com> + + * keyedit.c (show_key_with_all_names): Print the card S/N. + 2004-09-11 Moritz Schulte <moritz@g10code.com> * openfile.c (copy_options_file): Fixed last commit (added a `+'). diff --git a/g10/keyedit.c b/g10/keyedit.c index 4da174e3c..2f9fccbf5 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -2121,6 +2121,27 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, datestr_from_sk(sk), expirestr_from_sk(sk) ); tty_printf("\n"); + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { + tty_printf(" "); + tty_printf(_("card-no: ")); + if (sk->protect.ivlen == 16 + && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) + { /* This is an OpenPGP card. */ + for (i=8; i < 14; i++) + { + if (i == 10) + tty_printf (" "); + tty_printf ("%02X", sk->protect.iv[i]); + } + } + else + { /* Something is wrong: Print all. */ + for (i=0; i < sk->protect.ivlen; i++) + tty_printf ("%02X", sk->protect.iv[i]); + } + tty_printf ("\n"); + } } else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE && node->pkt->pkt.signature->sig_class == 0x28 ) { diff --git a/scd/ChangeLog b/scd/ChangeLog index a527b5da5..e6789fcb2 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-09-11 Werner Koch <wk@g10code.com> + + * app-openpgp.c (app_select_openpgp): Its app_munge_serialno and + not app_number_serialno. + 2004-08-20 Werner Koch <wk@g10code.de> * app.c (select_application): Fixed serial number extraction and diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 67bc336ec..1617ab888 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1397,7 +1397,7 @@ app_select_openpgp (APP app) #if GNUPG_MAJOR_VERSION != 1 /* A valid OpenPGP card should never need this but well the test is cheap. */ - rc = app_number_serialno (app); + rc = app_munge_serialno (app); if (rc) goto leave; #endif diff --git a/sm/ChangeLog b/sm/ChangeLog index a8139e2e0..d68759151 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-09-14 Werner Koch <wk@g10code.com> + + * certchain.c (gpgsm_validate_chain): Give expired certificates a + higher error precedence and don't bother to check any CRL in that + case. + 2004-08-24 Werner Koch <wk@g10code.de> * certlist.c: Fixed typo in ocsp OID. diff --git a/sm/certchain.c b/sm/certchain.c index 2ce247f65..ad30a36e1 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -672,7 +672,12 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) { do_list (0, lm, fp, _("root certificate is not marked trusted")); - if (!lm) + /* If we already figured out that the certificate is + expired it does not make much sense to ask the user + whether we wants to trust the root certificate. He + should do this only if the certificate under question + will then be usable. */ + if (!lm && !any_expired) { int rc2; char *fpr = gpgsm_get_fingerprint_string (subject_cert, @@ -707,6 +712,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Check for revocations etc. */ if ((flags & 1)) rc = 0; + else if (any_expired) + ; /* Don't bother to run the expensive CRL check then. */ else rc = is_cert_still_valid (ctrl, lm, fp, subject_cert, subject_cert, @@ -835,6 +842,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Check for revocations etc. */ if ((flags & 1)) rc = 0; + else if (any_expired) + ; /* Don't bother to run the expensive CRL check then. */ else rc = is_cert_still_valid (ctrl, lm, fp, subject_cert, issuer_cert, @@ -866,14 +875,14 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, the error code to the most critical one */ if (any_revoked) rc = gpg_error (GPG_ERR_CERT_REVOKED); + else if (any_expired) + rc = gpg_error (GPG_ERR_CERT_EXPIRED); else if (any_no_crl) rc = gpg_error (GPG_ERR_NO_CRL_KNOWN); else if (any_crl_too_old) rc = gpg_error (GPG_ERR_CRL_TOO_OLD); else if (any_no_policy_match) rc = gpg_error (GPG_ERR_NO_POLICY_MATCH); - else if (any_expired) - rc = gpg_error (GPG_ERR_CERT_EXPIRED); } leave: -- cgit v1.2.3 From 1db08a412cc349bc38786de78ed460cf71f8467f Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sun, 26 Sep 2004 21:48:13 +0000 Subject: 2004-09-25 Moritz Schulte <moritz@g10code.com> * agent.h: Declare: agent_pksign_do. (struct server_control_s): New member: raw_value. * pksign.c (do_encode_md): New argument: raw_value; support generation of raw (non-pkcs1) data objects; adjust callers. (agent_pksign_do): New function, based on code ripped out from agent_pksign. (agent_pksign): Use agent_pksign_do. * command.c (start_command_handler): Set ctrl.digest.raw_value. --- agent/ChangeLog | 13 ++++++ agent/agent.h | 3 ++ agent/command.c | 1 + agent/pksign.c | 136 +++++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 113 insertions(+), 40 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 470c70162..032308608 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,16 @@ +2004-09-25 Moritz Schulte <moritz@g10code.com> + + * agent.h: Declare: agent_pksign_do. + (struct server_control_s): New member: raw_value. + + * pksign.c (do_encode_md): New argument: raw_value; support + generation of raw (non-pkcs1) data objects; adjust callers. + (agent_pksign_do): New function, based on code ripped + out from agent_pksign. + (agent_pksign): Use agent_pksign_do. + + * command.c (start_command_handler): Set ctrl.digest.raw_value. + 2004-09-09 Werner Koch <wk@g10code.de> * gpg-agent.c (check_for_running_agent): New. diff --git a/agent/agent.h b/agent/agent.h index 89fc4285e..8112c258a 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -95,6 +95,7 @@ struct server_control_s { int algo; unsigned char value[MAX_DIGEST_LEN]; int valuelen; + int raw_value: 1; } digest; char keygrip[20]; int have_keygrip; @@ -159,6 +160,8 @@ void agent_unlock_cache_entry (void **cache_id); /*-- pksign.c --*/ +int agent_pksign_do (CTRL ctrl, const char *desc_text, + gcry_sexp_t *signature_sexp, int ignore_cache); int agent_pksign (ctrl_t ctrl, const char *desc_text, FILE *outfp, int ignore_cache); diff --git a/agent/command.c b/agent/command.c index 1d1ae9704..02bbf3429 100644 --- a/agent/command.c +++ b/agent/command.c @@ -854,6 +854,7 @@ start_command_handler (int listen_fd, int fd) ctrl.server_local->assuan_ctx = ctx; ctrl.server_local->message_fd = -1; ctrl.server_local->use_cache_for_signing = 1; + ctrl.digest.raw_value = 0; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); diff --git a/agent/pksign.c b/agent/pksign.c index acde66029..11e964837 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -32,41 +32,61 @@ static int -do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) +do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash, + int raw_value) { gcry_sexp_t hash; - const char *s; - char tmp[16+1]; - int i, rc; + int rc; - s = gcry_md_algo_name (algo); - if (s && strlen (s) < 16) + if (! raw_value) + { + const char *s; + char tmp[16+1]; + int i; + + s = gcry_md_algo_name (algo); + if (s && strlen (s) < 16) + { + for (i=0; i < strlen (s); i++) + tmp[i] = tolower (s[i]); + tmp[i] = '\0'; + } + + rc = gcry_sexp_build (&hash, NULL, + "(data (flags pkcs1) (hash %s %b))", + tmp, mdlen, md); + } + else { - for (i=0; i < strlen (s); i++) - tmp[i] = tolower (s[i]); - tmp[i] = '\0'; + gcry_mpi_t mpi; + + rc = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, md, mdlen, NULL); + if (! rc) + { + rc = gcry_sexp_build (&hash, NULL, + "(data (flags raw) (value %m))", + mpi); + gcry_mpi_release (mpi); + } + } - rc = gcry_sexp_build (&hash, NULL, - "(data (flags pkcs1) (hash %s %b))", - tmp, - mdlen, md); + *r_hash = hash; return rc; } -/* SIGN whatever information we have accumulated in CTRL and write it - back to OUTFP. */ +/* SIGN whatever information we have accumulated in CTRL and return + the signature S-Expression. */ int -agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) +agent_pksign_do (CTRL ctrl, const char *desc_text, + gcry_sexp_t *signature_sexp, int ignore_cache) { - gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL; + gcry_sexp_t s_skey = NULL, s_sig = NULL; unsigned char *shadow_info = NULL; - int rc; - char *buf = NULL; - size_t len; + unsigned int rc = 0; /* FIXME: gpg-error? */ - if (!ctrl->have_keygrip) + if (! ctrl->have_keygrip) return gpg_error (GPG_ERR_NO_SECKEY); rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip, @@ -77,32 +97,47 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) goto leave; } - if (!s_skey) - { /* divert operation to the smartcard */ - unsigned char *sigbuf; + if (! s_skey) + { + /* divert operation to the smartcard */ + + unsigned char *buf = NULL; + size_t len = 0; rc = divert_pksign (ctrl, ctrl->digest.value, ctrl->digest.valuelen, ctrl->digest.algo, - shadow_info, &sigbuf); + shadow_info, &buf); if (rc) { log_error ("smartcard signing failed: %s\n", gpg_strerror (rc)); goto leave; } - len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL); + len = gcry_sexp_canon_len (buf, 0, NULL, NULL); assert (len); - buf = sigbuf; + + rc = gcry_sexp_sscan (&s_sig, NULL, buf, len); + xfree (buf); + if (rc) + { + log_error ("failed to convert sigbuf returned by divert_pksign " + "into S-Exp: %s", gpg_strerror (rc)); + goto leave; + } } else - { /* no smartcard, but a private key */ + { + /* no smartcard, but a private key */ + + gcry_sexp_t s_hash = NULL; /* put the hash into a sexp */ rc = do_encode_md (ctrl->digest.value, ctrl->digest.valuelen, ctrl->digest.algo, - &s_hash); + &s_hash, + ctrl->digest.raw_value); if (rc) goto leave; @@ -114,6 +149,7 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) /* sign */ rc = gcry_pk_sign (&s_sig, s_hash, s_skey); + gcry_sexp_release (s_hash); if (rc) { log_error ("signing failed: %s\n", gpg_strerror (rc)); @@ -125,26 +161,46 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) log_debug ("result: "); gcry_sexp_dump (s_sig); } - - len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xmalloc (len); - len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len); - assert (len); } + leave: + + *signature_sexp = s_sig; + + gcry_sexp_release (s_skey); + xfree (shadow_info); + + return rc; +} + +/* SIGN whatever information we have accumulated in CTRL and write it + back to OUTFP. */ +int +agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) +{ + gcry_sexp_t s_sig = NULL; + char *buf = NULL; + size_t len = 0; + int rc = 0; + + rc = agent_pksign_do (ctrl, desc_text, &s_sig, ignore_cache); + if (rc) + goto leave; + + len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xmalloc (len); + len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + /* FIXME: we must make sure that no buffering takes place or we are in full control of the buffer memory (easy to do) - should go into assuan. */ fwrite (buf, 1, len, outfp); leave: - gcry_sexp_release (s_skey); - gcry_sexp_release (s_hash); gcry_sexp_release (s_sig); xfree (buf); - xfree (shadow_info); + return rc; } - - -- cgit v1.2.3 From 5e9f8cd329cfb131e59ae9d35693a38b6297dcbe Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 28 Sep 2004 14:12:10 +0000 Subject: (agent_unprotect): Fixed wiping of CLEARTEXT. Thanks to Moritz for pointing this out. --- agent/ChangeLog | 5 +++++ agent/protect.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 032308608..22846f3bd 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-09-28 Werner Koch <wk@g10code.com> + + * protect.c (agent_unprotect): Fixed wiping of CLEARTEXT. Thanks + to Moritz for pointing this out. + 2004-09-25 Moritz Schulte <moritz@g10code.com> * agent.h: Declare: agent_pksign_do. diff --git a/agent/protect.c b/agent/protect.c index 2de5e97c5..edcca36d9 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -699,7 +699,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, /* Albeit cleartext has been allocated in secure memory and thus xfree will wipe it out, we do an extra wipe just in case somethings goes badly wrong. */ - wipememory (cleartext, prot_begin-protectedkey); + wipememory (cleartext, n); xfree (cleartext); if (rc) return rc; -- cgit v1.2.3 From 4604ae8e99dfdc91d2af76d7336cd4a4d6da2722 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Sep 2004 11:04:30 +0000 Subject: Changed license of the manual stuff to GPL. * gnupg.texi (Top): New menu item Helper Tools. * tools.texi (Helper Tools): New. * Makefile.am (gnupg_TEXINFOS): Add tools.texi. --- doc/ChangeLog | 9 +++++++ doc/Makefile.am | 4 +-- doc/Notes | 3 +++ doc/gnupg.texi | 26 ++++++------------- doc/gpg-agent.texi | 2 +- doc/tools.texi | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 96 insertions(+), 22 deletions(-) create mode 100644 doc/tools.texi diff --git a/doc/ChangeLog b/doc/ChangeLog index 79a8c9532..d7015bd85 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,12 @@ +2004-09-29 Werner Koch <wk@g10code.com> + + Changed license of the manual stuff to GPL. + + * gnupg.texi (Top): New menu item Helper Tools. + + * tools.texi (Helper Tools): New. + * Makefile.am (gnupg_TEXINFOS): Add tools.texi. + 2004-08-05 Werner Koch <wk@g10code.de> * scdaemon.texi (Card applications): New section. diff --git a/doc/Makefile.am b/doc/Makefile.am index 9dc917de4..3ac312049 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -21,8 +21,8 @@ info_TEXINFOS = gnupg.texi gnupg_TEXINFOS = \ - gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi\ - debugging.texi glossary.texi contrib.texi gpl.texi fdl.texi + gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi tools.texi \ + debugging.texi glossary.texi contrib.texi gpl.texi DISTCLEANFILES = gnupg.tmp gnupg.ops diff --git a/doc/Notes b/doc/Notes index 4a990776e..3598bc7a7 100644 --- a/doc/Notes +++ b/doc/Notes @@ -1,3 +1,6 @@ + +Add an infor page for watchgnupg. + > * How to mark a CA certificate as trusted. There are two ways: diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 0beb97e69..ec82fe425 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -5,26 +5,14 @@ @include version.texi @macro copyrightnotice -Copyright @copyright{} 2002 Free Software Foundation, Inc. +Copyright @copyright{} 2002, 2004 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. +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. The text of the license can be found in the +section entitled ``Copying''. @end macro @@ -126,10 +114,10 @@ Developer information Miscellaneous +* Helper Tools:: Description of small helper tools * 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 @@ -145,10 +133,10 @@ Indices @include assuan.texi +@include tools.texi @include debugging.texi @include gpl.texi -@include fdl.texi @include contrib.texi diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 460cca45a..ab28eeb7d 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -282,7 +282,7 @@ command. @opindex ttyname @opindex ttytype @opindex lc-type -@opindex lc-messa +@opindex lc-messages These options are used with the server mode to pass localization information. diff --git a/doc/tools.texi b/doc/tools.texi new file mode 100644 index 000000000..d04b01277 --- /dev/null +++ b/doc/tools.texi @@ -0,0 +1,74 @@ +@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 Helper Tools +@chapter Helper Tools + +GnuPG comes with a couple of smaller tools: + +@menu +* watchgnupg:: Read logs from a socket. +* addgnupghome:: Create .gnupg home directories +@end menu + + +@node watchgnupg +@section Read logs from a socket + +Most of the main utilities are able to write there log files to a +Unix Domain socket if configured that way. watchgnupg is a simple +listener for such a socket. It ameliorates the output with a time +stamp and makes sure that long lines are not interspersed with log +output from other utilities. + +@noindent +watchgnupg is commonly invoked as + +@samp{watchgnupg --force ~/.gnupg/S.log} + +@noindent +This starts it on the current terminal for listening on the socket +@file{~/.gnupg/S.log}. + +@noindent +watchgnupg understands these options: + +@table @gnupgtabopt + +@item --force +@opindex force +Delete an already existing socket file. + +@item --verbose +@opindex verbose +Enable extra informational output. + +@item --version +@opindex version +print version of the program and exit + +@item --help +@opindex help +Display a brief help page and exit + +@end table + + + +@node addgnupghome +@section Create .gnupg home directories + +If GnuPG is installed on a system with existing user accounts, it is +sometimes required to populate the GnuPG home directory with existing +files. Especially a @file{trustlist.txt} and a keybox with some +initial certificates are often desired. This scripts help to do this +by copying all files from @file{/etc/skel/.gnupg} to the home +directories of the accounts given on the command line. It takes care +not to overwrite existing GnuPG home directories. + +@noindent +addgnupghome is invoked by root as: + +@samp{addgnupghome account1 account2 ... accountn} + -- cgit v1.2.3 From 530a0a91c4f5dc935278f64be26090f51acc9586 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Sep 2004 13:50:31 +0000 Subject: * minip12.c (parse_bag_encrypted_data): Print error if a bad passphrase has been given. * gpg-agent.texi (Invoking GPG-AGENT): Add a few words about the expected pinentry filename. * import.c (parse_p12): Write an error status line for bad passphrases. Add new arg CTRL and changed caller. * export.c (export_p12): Likewise. --- TODO | 3 ++- agent/ChangeLog | 5 +++++ agent/minip12.c | 27 +++++++++++++++++++++------ agent/protect-tool.c | 2 ++ doc/ChangeLog | 3 +++ doc/gpg-agent.texi | 8 ++++++++ sm/ChangeLog | 6 ++++++ sm/export.c | 33 +++++++++++++++++++++++++++++---- sm/import.c | 32 ++++++++++++++++++++++++++------ 9 files changed, 102 insertions(+), 17 deletions(-) diff --git a/TODO b/TODO index dd69544e1..89db14aad 100644 --- a/TODO +++ b/TODO @@ -86,7 +86,8 @@ might want to have an agent context for each service request * doc/ ** Explain how to setup a root CA key as trusted ** Explain how trustlist.txt might be managed. - +** Document watchgnupg +** Write a script to generate man pages from texi. * Requirements by the BSI ** Support authorityKeyIdentifier.keyIdentifier diff --git a/agent/ChangeLog b/agent/ChangeLog index 22846f3bd..f72bd50c9 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-09-29 Werner Koch <wk@g10code.com> + + * minip12.c (parse_bag_encrypted_data): Print error if a bad + passphrase has been given. + 2004-09-28 Werner Koch <wk@g10code.com> * protect.c (agent_unprotect): Fixed wiping of CLEARTEXT. Thanks diff --git a/agent/minip12.c b/agent/minip12.c index e32a40de2..fc9b26dd1 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -379,7 +379,6 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, - static int parse_bag_encrypted_data (const unsigned char *buffer, size_t length, int startoffset, const char *pw, @@ -393,8 +392,8 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, char salt[8]; unsigned int iter; unsigned char *plain = NULL; - - + int bad_pass = 0; + where = "start"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -495,12 +494,21 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, where = "outer.outer.seq"; if (parse_tag (&p, &n, &ti)) - goto bailout; + { + bad_pass = 1; + goto bailout; + } if (ti.class || ti.tag != TAG_SEQUENCE) - goto bailout; + { + bad_pass = 1; + goto bailout; + } if (parse_tag (&p, &n, &ti)) - goto bailout; + { + bad_pass = 1; + goto bailout; + } /* Loop over all certificates inside the bab. */ while (n) @@ -611,6 +619,13 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, gcry_free (plain); log_error ("encryptedData error at \"%s\", offset %u\n", where, (p - buffer)+startoffset); + if (bad_pass) + { + /* Note, that the following string might be used by other programs + to check for a bad passphrase; it should therefore not be + translated or changed. */ + log_error ("possibly bad passphrase given\n"); + } return -1; } diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 7cfb760b8..286adde54 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -882,6 +882,8 @@ export_p12_file (const char *fname) release_passphrase (pw); if (rc) { + if (opt_status_msg && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE ) + log_info ("[PROTECT-TOOL:] bad-passphrase\n"); log_error ("unprotecting key `%s' failed: %s\n", fname, gpg_strerror (rc)); xfree (key); diff --git a/doc/ChangeLog b/doc/ChangeLog index d7015bd85..6373b0339 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,8 @@ 2004-09-29 Werner Koch <wk@g10code.com> + * gpg-agent.texi (Invoking GPG-AGENT): Add a few words about the + expected pinentry filename. + Changed license of the manual stuff to GPL. * gnupg.texi (Top): New menu item Helper Tools. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index ab28eeb7d..2b45a41c1 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -52,9 +52,17 @@ GPG_TTY=`tty` export GPG_TTY @end smallexample +@noindent It is important that this environment variable always reflects the output of the @code{tty} command. +Please make sure that a proper pinentry program has been installed +under the default filename (which is system dependant) or use the +option @code{pinentry-pgm} to specify the full name of that program. +It is often useful to install a symbolic link from the actual used +pinentry (e.g. @file{/usr/bin/pinentry-gtk}) to the expected +one (e.g. @file{/usr/bin/pinentry}). + @c man end @noindent diff --git a/sm/ChangeLog b/sm/ChangeLog index d68759151..2391deb18 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-09-29 Werner Koch <wk@g10code.com> + + * import.c (parse_p12): Write an error status line for bad + passphrases. Add new arg CTRL and changed caller. + * export.c (export_p12): Likewise. + 2004-09-14 Werner Koch <wk@g10code.com> * certchain.c (gpgsm_validate_chain): Give expired certificates a diff --git a/sm/export.c b/sm/export.c index 3f7457502..15ad87b04 100644 --- a/sm/export.c +++ b/sm/export.c @@ -65,7 +65,8 @@ typedef struct duptable_s *duptable_t; static void print_short_info (ksba_cert_t cert, FILE *fp); -static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen, +static gpg_error_t export_p12 (ctrl_t ctrl, + const unsigned char *certimg, size_t certimglen, const char *prompt, const char *keygrip, FILE **retfp); @@ -423,7 +424,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp) prompt = gpgsm_format_keydesc (cert); - rc = export_p12 (image, imagelen, prompt, keygrip, &datafp); + rc = export_p12 (ctrl, image, imagelen, prompt, keygrip, &datafp); xfree (prompt); if (rc) goto leave; @@ -587,6 +588,7 @@ popen_protect_tool (const char *pgmname, "--homedir", opt.homedir, "--p12-export", "--prompt", prompt?prompt:"", + "--enable-status-msg", "--", keygrip, NULL); @@ -610,7 +612,7 @@ popen_protect_tool (const char *pgmname, static gpg_error_t -export_p12 (const unsigned char *certimg, size_t certimglen, +export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen, const char *prompt, const char *keygrip, FILE **retfp) { @@ -621,6 +623,7 @@ export_p12 (const unsigned char *certimg, size_t certimglen, FILE *infp = NULL, *outfp = NULL, *fp = NULL; char buffer[1024]; pid_t pid = -1; + int bad_pass = 0; if (!opt.protect_tool_program || !*opt.protect_tool_program) pgmname = GNUPG_DEFAULT_PROTECT_TOOL; @@ -675,7 +678,21 @@ export_p12 (const unsigned char *certimg, size_t certimglen, if (cont_line) log_printf ("%s", buffer); else - log_info ("%s", buffer); + { + if (!strncmp (buffer, "gpg-protect-tool: [PROTECT-TOOL:] ",34)) + { + char *p, *pend; + + p = buffer + 34; + pend = strchr (p, ' '); + if (pend) + *pend = 0; + if ( !strcmp (p, "bad-passphrase")) + bad_pass++; + } + else + log_info ("%s", buffer); + } pos = 0; cont_line = (c != '\n'); } @@ -731,6 +748,14 @@ export_p12 (const unsigned char *certimg, size_t certimglen, } else *retfp = outfp; + if (bad_pass) + { + /* During export this is the passphrase used to unprotect the + key and not the pkcs#12 thing as in export. Therefore we can + issue the regular passphrase status. FIXME: replace the all + zero keyid by a regular one. */ + gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000"); + } return err; } diff --git a/sm/import.c b/sm/import.c index 836ac0877..938bc17d0 100644 --- a/sm/import.c +++ b/sm/import.c @@ -55,7 +55,7 @@ struct stats_s { }; -static gpg_error_t parse_p12 (ksba_reader_t reader, FILE **retfp, +static gpg_error_t parse_p12 (ctrl_t ctrl, ksba_reader_t reader, FILE **retfp, struct stats_s *stats); @@ -341,7 +341,7 @@ import_one (CTRL ctrl, struct stats_s *stats, int in_fd) Base64Context b64p12rdr; ksba_reader_t p12rdr; - rc = parse_p12 (reader, &certfp, stats); + rc = parse_p12 (ctrl, reader, &certfp, stats); if (!rc) { any = 1; @@ -572,13 +572,14 @@ popen_protect_tool (const char *pgmname, /* Assume that the reader is at a pkcs#12 message and try to import - certificates from that stupid format. We will alos store secret + certificates from that stupid format. We will also store secret keys. All of the pkcs#12 parsing and key storing is handled by the gpg-protect-tool, we merely have to take care of receiving the certificates. On success RETFP returns a temporary file with certificates. */ static gpg_error_t -parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) +parse_p12 (ctrl_t ctrl, ksba_reader_t reader, + FILE **retfp, struct stats_s *stats) { const char *pgmname; gpg_error_t err = 0, child_err = 0; @@ -588,6 +589,7 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) char buffer[1024]; size_t nread; pid_t pid = -1; + int bad_pass = 0; if (!opt.protect_tool_program || !*opt.protect_tool_program) pgmname = GNUPG_DEFAULT_PROTECT_TOOL; @@ -681,8 +683,13 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) else if ( !strcmp (p, "bad-passphrase")) ; } - else - log_info ("%s", buffer); + else + { + log_info ("%s", buffer); + if (!strncmp (buffer, "gpg-protect-tool: " + "possibly bad passphrase given",46)) + bad_pass++; + } } pos = 0; cont_line = (c != '\n'); @@ -698,6 +705,7 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) log_info ("%s\n", buffer); } + /* If we found no error in the output of the cild, setup a suitable error code, which will later be reset if the exit status of the child is 0. */ @@ -738,5 +746,17 @@ parse_p12 (ksba_reader_t reader, FILE **retfp, struct stats_s *stats) } else *retfp = certfp; + + if (bad_pass) + { + /* We only write a plain error code and not direct + BAD_PASSPHRASE because the pkcs12 parser might issue this + message multiple times, BAd_PASSPHRASE in general requires a + keyID and parts of the import might actually succeed so that + IMPORT_PROBLEM is also not appropriate. */ + gpgsm_status_with_err_code (ctrl, STATUS_ERROR, + "import.parsep12", GPG_ERR_BAD_PASSPHRASE); + } + return err; } -- cgit v1.2.3 From e0a2769b6ebb2ba2459657bdb581d35fff2825c8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Sep 2004 14:28:15 +0000 Subject: Fuzzy fixes --- po/de.po | 401 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 214 insertions(+), 187 deletions(-) diff --git a/po/de.po b/po/de.po index 06ae4320e..11cd4912a 100644 --- a/po/de.po +++ b/po/de.po @@ -10,15 +10,15 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-08-05 11:31+0200\n" -"PO-Revision-Date: 2004-07-22 10:05+0200\n" +"POT-Creation-Date: 2004-09-29 16:21+0200\n" +"PO-Revision-Date: 2004-09-29 16:28+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:96 agent/protect-tool.c:94 scd/scdaemon.c:93 +#: agent/gpg-agent.c:97 agent/protect-tool.c:101 scd/scdaemon.c:93 msgid "" "@Options:\n" " " @@ -26,94 +26,94 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:98 scd/scdaemon.c:95 +#: agent/gpg-agent.c:99 scd/scdaemon.c:95 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:99 scd/scdaemon.c:96 +#: agent/gpg-agent.c:100 scd/scdaemon.c:96 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:100 kbx/kbxutil.c:75 scd/scdaemon.c:97 sm/gpgsm.c:313 +#: agent/gpg-agent.c:101 kbx/kbxutil.c:81 scd/scdaemon.c:97 sm/gpgsm.c:315 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:101 kbx/kbxutil.c:76 scd/scdaemon.c:98 sm/gpgsm.c:314 +#: agent/gpg-agent.c:102 kbx/kbxutil.c:82 scd/scdaemon.c:98 sm/gpgsm.c:316 msgid "be somewhat more quiet" msgstr "etwas weniger Aussageb erzeugen" -#: agent/gpg-agent.c:102 scd/scdaemon.c:99 +#: agent/gpg-agent.c:103 scd/scdaemon.c:99 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:103 scd/scdaemon.c:100 +#: agent/gpg-agent.c:104 scd/scdaemon.c:100 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" -#: agent/gpg-agent.c:104 +#: agent/gpg-agent.c:105 msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:109 scd/scdaemon.c:107 +#: agent/gpg-agent.c:110 scd/scdaemon.c:107 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:110 +#: agent/gpg-agent.c:111 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:111 scd/scdaemon.c:108 sm/gpgsm.c:316 +#: agent/gpg-agent.c:112 scd/scdaemon.c:108 sm/gpgsm.c:318 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:112 +#: agent/gpg-agent.c:113 msgid "do not allow multiple connections" msgstr "Nicht mehr als eine Verbindung erlauben" -#: agent/gpg-agent.c:115 +#: agent/gpg-agent.c:116 msgid "|PGM|use PGM as the PIN-Entry program" msgstr "|PGM|benutze PGM as PIN-Entry" -#: agent/gpg-agent.c:117 +#: agent/gpg-agent.c:118 msgid "|PGM|use PGM as the SCdaemon program" msgstr "|PGM|benutze PGM as SCdaemon" -#: agent/gpg-agent.c:124 +#: agent/gpg-agent.c:125 msgid "ignore requests to change the TTY" msgstr "Ignoriere Anfragen, das TTY zu wechseln" -#: agent/gpg-agent.c:126 +#: agent/gpg-agent.c:127 msgid "ignore requests to change the X display" msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:129 +#: agent/gpg-agent.c:130 msgid "|N|expire cached PINs after N seconds" msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" -#: agent/gpg-agent.c:131 +#: agent/gpg-agent.c:133 msgid "do not use the PIN cache when signing" msgstr "benutze PINs im Cache nicht bem Signieren" -#: agent/gpg-agent.c:133 +#: agent/gpg-agent.c:135 msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" -#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:168 -#: sm/gpgsm.c:481 tools/gpgconf.c:85 +#: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 +#: sm/gpgsm.c:485 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:191 agent/protect-tool.c:127 scd/scdaemon.c:168 -#: sm/gpgsm.c:481 tools/gpgconf.c:85 +#: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 +#: sm/gpgsm.c:485 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:194 +#: agent/gpg-agent.c:198 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: agent/gpg-agent.c:196 +#: agent/gpg-agent.c:200 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -121,55 +121,62 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:267 scd/scdaemon.c:242 sm/gpgsm.c:604 +#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:608 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:439 agent/protect-tool.c:1040 kbx/kbxutil.c:232 -#: scd/scdaemon.c:357 sm/gpgsm.c:726 +#: agent/gpg-agent.c:446 agent/protect-tool.c:1050 kbx/kbxutil.c:436 +#: scd/scdaemon.c:357 sm/gpgsm.c:731 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:512 scd/scdaemon.c:437 sm/gpgsm.c:824 +#: agent/gpg-agent.c:519 scd/scdaemon.c:437 sm/gpgsm.c:829 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:517 agent/gpg-agent.c:983 scd/scdaemon.c:442 -#: sm/gpgsm.c:828 +#: agent/gpg-agent.c:524 agent/gpg-agent.c:998 scd/scdaemon.c:442 +#: sm/gpgsm.c:833 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:525 scd/scdaemon.c:450 sm/gpgsm.c:835 +#: agent/gpg-agent.c:532 scd/scdaemon.c:450 sm/gpgsm.c:840 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:668 scd/scdaemon.c:630 -msgid "please use the option `--daemon' to run the program in the background\n" -msgstr "" -"Bitte die Option `--daemon' nutzen um das Programm im Hintergund " -"auszufhren\n" - -#: agent/gpg-agent.c:1016 agent/gpg-agent.c:1050 +#: agent/gpg-agent.c:1031 agent/gpg-agent.c:1065 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: agent/gpg-agent.c:1019 agent/gpg-agent.c:1055 +#: agent/gpg-agent.c:1034 agent/gpg-agent.c:1070 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/protect-tool.c:130 +#: agent/gpg-agent.c:1248 +msgid "no gpg-agent running in this session\n" +msgstr "Der gpg-agent läuft nicht für diese Session\n" + +#: agent/gpg-agent.c:1255 common/simple-pwquery.c:286 sm/call-agent.c:128 +msgid "malformed GPG_AGENT_INFO environment variable\n" +msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" + +#: agent/gpg-agent.c:1267 common/simple-pwquery.c:298 sm/call-agent.c:140 +#, c-format +msgid "gpg-agent protocol version %d is not supported\n" +msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" + +#: agent/protect-tool.c:137 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" -#: agent/protect-tool.c:132 +#: agent/protect-tool.c:139 msgid "" "Syntax: gpg-protect-tool [options] [args]]\n" "Secret key maintenance tool\n" @@ -177,7 +184,25 @@ msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" "Werkzeug zum Bearbeiten von geheimen Schlsseln\n" -#: agent/protect-tool.c:1148 +#: agent/protect-tool.c:1187 +msgid "Please enter the passphrase to unprotect the PKCS#12 object." +msgstr "Bitte geben Sie die Passphrase zum Entsperren des PKCS#12 Objekts ein" + +#: agent/protect-tool.c:1190 +msgid "Please enter the passphrase to protect the new PKCS#12 object." +msgstr "Bitte geben Sie die Passphrase zum Schützen des neuen PKCS#12 Objekts ein" + +#: agent/protect-tool.c:1193 +msgid "" +"Please enter the passphrase to protect the imported object within the GnuPG " +"system." +msgstr "Bitte geben Sie die Passphrase ein, um das importierte Objket im GnuPG System zu schützen." + +#: agent/protect-tool.c:1196 agent/genkey.c:110 agent/genkey.c:224 +msgid "Please re-enter this passphrase" +msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" + +#: agent/protect-tool.c:1198 msgid "" "Please enter the passphrase or the PIN\n" "needed to complete this operation." @@ -185,7 +210,11 @@ msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" "wird bentigt um diese Aktion auszufhren." -#: agent/protect-tool.c:1151 +#: agent/protect-tool.c:1202 agent/genkey.c:131 agent/genkey.c:244 +msgid "does not match - try again" +msgstr "Keine bereinstimmung - bitte nochmal versuchen" + +#: agent/protect-tool.c:1203 msgid "Passphrase:" msgstr "Passphrase:" @@ -200,19 +229,16 @@ msgid "Please enter the passphrase to%0Ato protect your new key" msgstr "" "Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlssel zu schtzen" -#: agent/genkey.c:110 agent/genkey.c:224 -msgid "Please re-enter this passphrase" -msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" - -#: agent/genkey.c:131 agent/genkey.c:244 -msgid "does not match - try again" -msgstr "Keine bereinstimmung - bitte nochmal versuchen" - #: agent/genkey.c:223 msgid "Please enter the new passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: agent/query.c:268 +#: agent/query.c:126 +#, c-format +msgid "failed to acquire the pinentry lock: %s\n" +msgstr "Die Sperre für das Pinentry kann nicht gesetzt werden: %s\n" + +#: agent/query.c:288 msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" @@ -220,7 +246,7 @@ msgstr "" "Bitte geben Sie Ihre PIN ein, so da der geheime Schlssel benutzt werden " "kann" -#: agent/query.c:271 +#: agent/query.c:291 msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" @@ -228,31 +254,31 @@ msgstr "" "Bitte geben Sie Ihr Mantra (Passphrase) ein, so da der geheime Schlssel " "benutzt werden kann" -#: agent/query.c:326 agent/query.c:338 +#: agent/query.c:346 agent/query.c:358 msgid "PIN too long" msgstr "Die PIN ist zu lang" -#: agent/query.c:327 +#: agent/query.c:347 msgid "Passphrase too long" msgstr "Das Matra (Passphrase) ist zu lang" -#: agent/query.c:335 +#: agent/query.c:355 msgid "Invalid characters in PIN" msgstr "Ungltige Zeichen in der PIN" -#: agent/query.c:340 +#: agent/query.c:360 msgid "PIN too short" msgstr "Die PIN ist zu kurz" -#: agent/query.c:352 +#: agent/query.c:372 msgid "Bad PIN" msgstr "Falsche PIN" -#: agent/query.c:353 +#: agent/query.c:373 msgid "Bad Passphrase" msgstr "Falsches Mantra (Passphrase)" -#: agent/query.c:392 +#: agent/query.c:412 msgid "Passphrase" msgstr "Mantra" @@ -277,15 +303,6 @@ msgstr "WARNUNG: Unsichere Zugriffsrechte f msgid "gpg-agent is not available in this session\n" msgstr "Der gpg-agent ist nicht verfgbar\n" -#: common/simple-pwquery.c:286 sm/call-agent.c:128 -msgid "malformed GPG_AGENT_INFO environment variable\n" -msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" - -#: common/simple-pwquery.c:298 sm/call-agent.c:140 -#, c-format -msgid "gpg-agent protocol version %d is not supported\n" -msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" - #: common/simple-pwquery.c:320 #, c-format msgid "can't connect to `%s': %s\n" @@ -299,11 +316,11 @@ msgstr "Kommunikationsproblem mit gpg-agent\n" msgid "problem setting the gpg-agent options\n" msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: common/simple-pwquery.c:473 +#: common/simple-pwquery.c:479 msgid "canceled by user\n" msgstr "Vom Benutzer abgebrochen\n" -#: common/simple-pwquery.c:480 +#: common/simple-pwquery.c:486 msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" @@ -312,7 +329,7 @@ msgstr "Problem mit dem Agenten\n" msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:63 sm/gpgsm.c:224 tools/gpgconf.c:53 +#: kbx/kbxutil.c:68 sm/gpgsm.c:226 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -320,7 +337,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:70 sm/gpgsm.c:259 tools/gpgconf.c:59 +#: kbx/kbxutil.c:76 sm/gpgsm.c:261 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -330,31 +347,31 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:77 sm/gpgsm.c:321 tools/gpgconf.c:64 +#: kbx/kbxutil.c:83 sm/gpgsm.c:323 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" -#: kbx/kbxutil.c:79 +#: kbx/kbxutil.c:85 msgid "set debugging flags" msgstr "Debug Flags setzen" -#: kbx/kbxutil.c:80 +#: kbx/kbxutil.c:86 msgid "enable full debugging" msgstr "Alle Debug Flags setzen" -#: kbx/kbxutil.c:101 +#: kbx/kbxutil.c:107 msgid "Please report bugs to " msgstr "Bite richten sie Berichte ber Bugs (Softwarefehler) an " -#: kbx/kbxutil.c:101 +#: kbx/kbxutil.c:107 msgid ".\n" msgstr ".\n" -#: kbx/kbxutil.c:105 +#: kbx/kbxutil.c:111 msgid "Usage: kbxutil [options] [files] (-h for help)" msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h fr Hilfe)" -#: kbx/kbxutil.c:108 +#: kbx/kbxutil.c:114 msgid "" "Syntax: kbxutil [options] [files]\n" "list, export, import Keybox data\n" @@ -362,7 +379,7 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:101 sm/gpgsm.c:333 +#: scd/scdaemon.c:101 sm/gpgsm.c:335 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" @@ -406,6 +423,12 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon fr GnuPG\n" +#: scd/scdaemon.c:630 +msgid "please use the option `--daemon' to run the program in the background\n" +msgstr "" +"Bitte die Option `--daemon' nutzen um das Programm im Hintergund " +"auszufhren\n" + #: sm/base64.c:315 #, c-format msgid "invalid radix64 character %02x skipped\n" @@ -475,33 +498,37 @@ msgstr "" "S/N %s, ID %08lX, erzeugt %s\n" "zu entsperren" -#: sm/certlist.c:113 +#: sm/certlist.c:122 msgid "no key usage specified - assuming all usages\n" msgstr "" "Schlsselverwendungszweck nicht vorhanden - fr alle Zwecke akzeptiert\n" -#: sm/certlist.c:123 sm/keylist.c:224 +#: sm/certlist.c:132 sm/keylist.c:224 #, c-format msgid "error getting key usage information: %s\n" msgstr "Fehler beim holen der Schlsselbenutzungsinformationen: %s\n" -#: sm/certlist.c:133 +#: sm/certlist.c:142 msgid "certificate should have not been used for certification\n" msgstr "Das Zertifikat htte nicht zum Zertifizieren benutzt werden sollen\n" -#: sm/certlist.c:144 +#: sm/certlist.c:154 +msgid "certificate should have not been used for OCSP response signing\n" +msgstr "Das Zertifikat hätte nicht zum Signieren von OCSP Antworten benutzt werden sollen\n" + +#: sm/certlist.c:165 msgid "certificate should have not been used for encryption\n" -msgstr "Das Zertifikat hatte nicht zum Verschlsseln benutzt werden sollen\n" +msgstr "Das Zertifikat hätte nicht zum Verschlsseln benutzt werden sollen\n" -#: sm/certlist.c:145 +#: sm/certlist.c:166 msgid "certificate should have not been used for signing\n" -msgstr "Das Zertifikat hatte nicht zum Signieren benutzt werden sollen\n" +msgstr "Das Zertifikat hätte nicht zum Signieren benutzt werden sollen\n" -#: sm/certlist.c:146 +#: sm/certlist.c:167 msgid "certificate is not usable for encryption\n" msgstr "Das Zertifikat kann nicht zum Verschlsseln benutzt werden\n" -#: sm/certlist.c:147 +#: sm/certlist.c:168 msgid "certificate is not usable for signing\n" msgstr "Das Zertifikat kann nicht zum Signieren benutzt werden\n" @@ -535,7 +562,7 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" msgid "number of issuers matching: %d\n" msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:403 sm/certchain.c:561 sm/certchain.c:912 sm/decrypt.c:260 +#: sm/certchain.c:403 sm/certchain.c:561 sm/certchain.c:921 sm/decrypt.c:260 #: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" @@ -587,39 +614,39 @@ msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert" -#: sm/certchain.c:680 +#: sm/certchain.c:685 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:685 +#: sm/certchain.c:690 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" -#: sm/certchain.c:700 +#: sm/certchain.c:705 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:724 sm/import.c:166 +#: sm/certchain.c:731 sm/import.c:166 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:736 +#: sm/certchain.c:743 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:769 +#: sm/certchain.c:776 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:792 +#: sm/certchain.c:799 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:815 +#: sm/certchain.c:822 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" @@ -672,235 +699,235 @@ msgstr "Schwacher Schl msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:226 +#: sm/gpgsm.c:228 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:227 +#: sm/gpgsm.c:229 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:228 +#: sm/gpgsm.c:230 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:229 +#: sm/gpgsm.c:231 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:230 +#: sm/gpgsm.c:232 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:231 +#: sm/gpgsm.c:233 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:232 +#: sm/gpgsm.c:234 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:234 +#: sm/gpgsm.c:236 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:235 +#: sm/gpgsm.c:237 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:236 +#: sm/gpgsm.c:238 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:237 +#: sm/gpgsm.c:239 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:241 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:240 +#: sm/gpgsm.c:242 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:243 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:244 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:245 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:246 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:247 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:246 +#: sm/gpgsm.c:248 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:249 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:248 +#: sm/gpgsm.c:250 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:252 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:251 +#: sm/gpgsm.c:253 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:261 +#: sm/gpgsm.c:263 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: sm/gpgsm.c:263 +#: sm/gpgsm.c:265 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:265 +#: sm/gpgsm.c:267 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:267 +#: sm/gpgsm.c:269 msgid "assume input is in base-64 format" msgstr "Eingabedaten sin im Basis-64 Format" -#: sm/gpgsm.c:269 +#: sm/gpgsm.c:271 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:271 +#: sm/gpgsm.c:273 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:274 +#: sm/gpgsm.c:276 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:279 +#: sm/gpgsm.c:281 msgid "check validity using OCSP" msgstr "Die Gltigkeit mittels OCSP prfen" -#: sm/gpgsm.c:282 +#: sm/gpgsm.c:284 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:285 +#: sm/gpgsm.c:287 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:288 +#: sm/gpgsm.c:290 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:292 +#: sm/gpgsm.c:294 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:296 +#: sm/gpgsm.c:298 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:298 +#: sm/gpgsm.c:300 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:304 +#: sm/gpgsm.c:306 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:307 +#: sm/gpgsm.c:309 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:309 +#: sm/gpgsm.c:311 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:312 tools/gpgconf.c:61 +#: sm/gpgsm.c:314 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: sm/gpgsm.c:315 +#: sm/gpgsm.c:317 msgid "don't use the terminal at all" msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:318 +#: sm/gpgsm.c:320 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:319 +#: sm/gpgsm.c:321 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:324 +#: sm/gpgsm.c:326 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:325 +#: sm/gpgsm.c:327 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:326 +#: sm/gpgsm.c:328 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:328 +#: sm/gpgsm.c:330 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:329 +#: sm/gpgsm.c:331 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:330 +#: sm/gpgsm.c:332 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:331 +#: sm/gpgsm.c:333 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:332 +#: sm/gpgsm.c:334 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:342 +#: sm/gpgsm.c:345 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:349 +#: sm/gpgsm.c:352 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:355 +#: sm/gpgsm.c:358 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verhsclsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:357 +#: sm/gpgsm.c:360 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:359 +#: sm/gpgsm.c:362 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:367 +#: sm/gpgsm.c:370 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -908,7 +935,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:370 +#: sm/gpgsm.c:373 msgid "" "@\n" "Examples:\n" @@ -928,11 +955,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:484 +#: sm/gpgsm.c:488 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:487 +#: sm/gpgsm.c:491 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -941,7 +968,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:494 +#: sm/gpgsm.c:498 msgid "" "\n" "Supported algorithms:\n" @@ -949,50 +976,50 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:575 +#: sm/gpgsm.c:579 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:641 +#: sm/gpgsm.c:645 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:657 +#: sm/gpgsm.c:661 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:731 +#: sm/gpgsm.c:736 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1175 +#: sm/gpgsm.c:1182 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1187 +#: sm/gpgsm.c:1194 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1213 +#: sm/gpgsm.c:1220 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1221 +#: sm/gpgsm.c:1228 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1251 +#: sm/gpgsm.c:1258 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1415 +#: sm/gpgsm.c:1422 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1638 sm/gpgsm.c:1671 +#: sm/gpgsm.c:1645 sm/gpgsm.c:1678 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" @@ -1032,61 +1059,61 @@ msgstr "unge msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: sm/import.c:229 +#: sm/import.c:235 msgid "error storing certificate\n" msgstr "Fehler beim speichern des Zertifikats\n" -#: sm/import.c:237 +#: sm/import.c:243 msgid "basic certificate checks failed - not imported\n" msgstr "Grundlegende Zertifikatprfungen fehlgeschlagen - nicht importiert\n" -#: sm/import.c:423 sm/import.c:455 +#: sm/import.c:429 sm/import.c:461 #, c-format msgid "error importing certificate: %s\n" msgstr "Fehler beim Importieren des Zertifikats: %s\n" -#: sm/import.c:484 +#: sm/import.c:490 #, c-format msgid "error creating a pipe: %s\n" msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" -#: sm/import.c:492 +#: sm/import.c:498 #, c-format msgid "error forking process: %s\n" msgstr "Fehler beim \"Forken\" des Prozess: %s\n" -#: sm/import.c:590 sm/import.c:615 +#: sm/import.c:609 sm/import.c:634 #, c-format msgid "error creating temporary file: %s\n" msgstr "Fehler beim Erstellen einer temporren Datei: %s\n" -#: sm/import.c:598 +#: sm/import.c:617 #, c-format msgid "error writing to temporary file: %s\n" msgstr "Fehler beim Schreiben auf eine temporre Datei: %s\n" -#: sm/import.c:607 +#: sm/import.c:626 #, c-format msgid "error reading input: %s\n" msgstr "Fehler beim Lesen der Eingabe: %s\n" -#: sm/import.c:703 +#: sm/import.c:728 #, c-format msgid "waiting for protect-tool to terminate failed: %s\n" msgstr "" "Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" -#: sm/import.c:706 +#: sm/import.c:731 #, c-format msgid "error running `%s': probably not installed\n" msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" -#: sm/import.c:708 +#: sm/import.c:733 #, c-format msgid "error running `%s': exit status %d\n" msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" -#: sm/import.c:711 +#: sm/import.c:736 #, c-format msgid "error running `%s': terminated\n" msgstr "Fehler beim Ausfhren von `%s': beendet\n" -- cgit v1.2.3 From c0fa36d40506687b09484ce9e42d37bcdf4baf22 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Sep 2004 16:16:02 +0000 Subject: Added a few strings. --- po/de.po | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/po/de.po b/po/de.po index 11cd4912a..a09f0024d 100644 --- a/po/de.po +++ b/po/de.po @@ -1,4 +1,4 @@ -# German translation for GnuPG 1.9.x +# German translation for GnuPG 1.9.x -*-coding: latin-1;-*- # Copyright (C) 2002, 2004 Free Software Foundation, Inc. # Werner Koch <wk@gnupg.org>, 2002. # @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-09-29 16:21+0200\n" -"PO-Revision-Date: 2004-09-29 16:28+0200\n" +"POT-Creation-Date: 2004-09-29 18:01+0200\n" +"PO-Revision-Date: 2004-09-29 18:10+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -190,13 +190,16 @@ msgstr "Bitte geben Sie die Passphrase zum Entsperren des PKCS#12 Objekts ein" #: agent/protect-tool.c:1190 msgid "Please enter the passphrase to protect the new PKCS#12 object." -msgstr "Bitte geben Sie die Passphrase zum Schützen des neuen PKCS#12 Objekts ein" +msgstr "" +"Bitte geben Sie die Passphrase zum Schützen des neuen PKCS#12 Objekts ein" #: agent/protect-tool.c:1193 msgid "" "Please enter the passphrase to protect the imported object within the GnuPG " "system." -msgstr "Bitte geben Sie die Passphrase ein, um das importierte Objket im GnuPG System zu schützen." +msgstr "" +"Bitte geben Sie die Passphrase ein, um das importierte Objket im GnuPG " +"System zu schützen." #: agent/protect-tool.c:1196 agent/genkey.c:110 agent/genkey.c:224 msgid "Please re-enter this passphrase" @@ -514,7 +517,9 @@ msgstr "Das Zertifikat h #: sm/certlist.c:154 msgid "certificate should have not been used for OCSP response signing\n" -msgstr "Das Zertifikat hätte nicht zum Signieren von OCSP Antworten benutzt werden sollen\n" +msgstr "" +"Das Zertifikat hätte nicht zum Signieren von OCSP Antworten benutzt werden " +"sollen\n" #: sm/certlist.c:165 msgid "certificate should have not been used for encryption\n" @@ -1240,6 +1245,45 @@ msgstr "Ben msgid "Component not found" msgstr "Komponente nicht gefunden" +#: tools/gpgconf-comp.c:432 tools/gpgconf-comp.c:493 tools/gpgconf-comp.c:558 +#: tools/gpgconf-comp.c:611 tools/gpgconf-comp.c:674 +msgid "Options controlling the diagnostic output" +msgstr "Optionen zur Einstellung Diagnoseausgaben" + +#: tools/gpgconf-comp.c:445 tools/gpgconf-comp.c:506 tools/gpgconf-comp.c:571 +#: tools/gpgconf-comp.c:624 tools/gpgconf-comp.c:697 +msgid "Options controlling the configuration" +msgstr "Optionen zur Einstellung der Konfiguration" + +#: tools/gpgconf-comp.c:452 tools/gpgconf-comp.c:529 tools/gpgconf-comp.c:578 +#: tools/gpgconf-comp.c:631 tools/gpgconf-comp.c:704 +msgid "Options useful for debugging" +msgstr "Nützliche Optionen zum Debuggen" + +#: tools/gpgconf-comp.c:465 tools/gpgconf-comp.c:539 tools/gpgconf-comp.c:644 +msgid "Options controlling the security" +msgstr "Optionen zur Einstellung der Sicherheit" + +#: tools/gpgconf-comp.c:591 +msgid "Configuration for Keyservers" +msgstr "Konfiguration der Schlüsselserver" + +#: tools/gpgconf-comp.c:687 +msgid "Options controlling the format of the output" +msgstr "Optionen zum Einstellen der Ausgabeformate" + +#: tools/gpgconf-comp.c:723 +msgid "Options controlling the interactivity and enforcement" +msgstr "Optionen zur Einstellung der Interaktivität und Geltendmachung" + +#: tools/gpgconf-comp.c:733 +msgid "Configuration of LDAP servers to use" +msgstr "Konfiguration der zu nutzenden LDAP-Server" + +#: tools/gpgconf-comp.c:758 +msgid "Configuration for OCSP" +msgstr "Konfiguration zu OCSP" + #~ msgid "Enter passphrase:" #~ msgstr "Bitte das Mantra (Passphrase) eingeben:" -- cgit v1.2.3 From e4ce12abd176106e41c37a7ffbdb26ebd3a5e884 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Sep 2004 16:16:47 +0000 Subject: * gpgsm.texi (Configuration Options): Add --log-file. * gpgconf-comp.c: Made the entries fro GROUPs translatable. Include i18n.h. (my_dgettext): Hack to use the gnupg2 domain. --- doc/ChangeLog | 2 ++ doc/gpgsm.texi | 4 ++- tools/ChangeLog | 6 +++++ tools/addgnupghome | 4 +-- tools/gpgconf-comp.c | 72 +++++++++++++++++++++++++++++++--------------------- 5 files changed, 56 insertions(+), 32 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 6373b0339..db72a2020 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,7 @@ 2004-09-29 Werner Koch <wk@g10code.com> + * gpgsm.texi (Configuration Options): Add --log-file. + * gpg-agent.texi (Invoking GPG-AGENT): Add a few words about the expected pinentry filename. diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 0f2167184..05c351cd8 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -266,7 +266,9 @@ a running dirmngr can't be connected. @opindex no-secmem-warning Don't print a warning when the so called "secure memory" can't be used. - +@item --log-file @var{file} +@opindex log-file +When running in server mode, append all logging output to @var{file}. @end table diff --git a/tools/ChangeLog b/tools/ChangeLog index 841fb0c98..befb1bf3c 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2004-09-29 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c: Made the entries fro GROUPs translatable. + Include i18n.h. + (my_dgettext): Hack to use the gnupg2 domain. + 2004-08-09 Moritz Schulte <moritz@g10code.com> * gpgsm-gencert.sh: New file. diff --git a/tools/addgnupghome b/tools/addgnupghome index 37a427bf2..fb032b674 100755 --- a/tools/addgnupghome +++ b/tools/addgnupghome @@ -1,5 +1,5 @@ -# !/bin/sh -*- sh -*- -# Add a new .gnupg home directory for a list of users +#!/bin/sh +# Add a new .gnupg home directory for a list of users -*- sh -*- # # Copyright 2004 Free Software Foundation, Inc. # diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index cc0751d0c..b140db76e 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -23,8 +23,6 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -/* FIXME use gettext.h */ -#include <libintl.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> @@ -37,9 +35,11 @@ /* For log_logv(), asctimestamp(), gnupg_get_time (). */ #define JNLIB_NEED_LOG_LOGV #include "util.h" +#include "i18n.h" #include "gpgconf.h" + /* TODO: Components: Add more components and their options. @@ -361,12 +361,19 @@ struct gc_option /* A gettext domain in which the following description can be found. If this is NULL, then DESC is not translated. Valid for groups - and options. */ + and options. + + Note that we try to keep the description of groups within the + gnupg domain. */ const char *desc_domain; /* A gettext description for this group or option. If it starts with a '|', then the string up to the next '|' describes the - argument, and the description follows the second '|'. */ + argument, and the description follows the second '|'. + + In general enclosing these description in N_() is not required + because the description should be identical to the one in the + help menu of the respective program. */ const char *desc; /* The following fields are only valid for options. */ @@ -422,7 +429,7 @@ static gc_option_t gc_options_gpg_agent[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the diagnostic output" }, + "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, @@ -435,14 +442,14 @@ static gc_option_t gc_options_gpg_agent[] = { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, - NULL, "Options controlling the configuration" }, + "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, - "gnupg", "Options useful for debugging" }, + "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT }, @@ -455,7 +462,7 @@ static gc_option_t gc_options_gpg_agent[] = { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the security" }, + "gnupg", N_("Options controlling the security") }, { "default-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, "gnupg", "|N|expire cached PINs after N seconds", GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT }, @@ -483,7 +490,7 @@ static gc_option_t gc_options_scdaemon[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the diagnostic output" }, + "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, @@ -496,7 +503,7 @@ static gc_option_t gc_options_scdaemon[] = { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, - NULL, "Options controlling the configuration" }, + "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, @@ -519,7 +526,7 @@ static gc_option_t gc_options_scdaemon[] = { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, - "gnupg", "Options useful for debugging" }, + "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, @@ -529,7 +536,7 @@ static gc_option_t gc_options_scdaemon[] = { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the security" }, + "gnupg", N_("Options controlling the security") }, { "allow-admin", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "allow the use of admin card commands", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, @@ -548,7 +555,7 @@ static gc_option_t gc_options_gpg[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the diagnostic output" }, + "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, @@ -561,14 +568,14 @@ static gc_option_t gc_options_gpg[] = { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, - NULL, "Options controlling the configuration" }, + "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, - "gnupg", "Options useful for debugging" }, + "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, @@ -581,7 +588,7 @@ static gc_option_t gc_options_gpg[] = { "Keyserver", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Configuration for Keyservers" }, + "gnupg", N_("Configuration for Keyservers") }, { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "|URL|use keyserver at URL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, @@ -601,7 +608,7 @@ static gc_option_t gc_options_gpgsm[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the diagnostic output" }, + "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "gnupg", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, @@ -614,14 +621,14 @@ static gc_option_t gc_options_gpgsm[] = { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, - NULL, "Options controlling the configuration" }, + "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, - "gnupg", "Options useful for debugging" }, + "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, @@ -634,7 +641,7 @@ static gc_option_t gc_options_gpgsm[] = { "Security", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the security" }, + "gnupg", N_("Options controlling the security") }, { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "never consult a CRL", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, @@ -664,7 +671,7 @@ static gc_option_t gc_options_dirmngr[] = { "Monitor", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the diagnostic output" }, + "gnupg", N_("Options controlling the diagnostic output") }, { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC, "dirmngr", "verbose", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, @@ -677,7 +684,7 @@ static gc_option_t gc_options_dirmngr[] = { "Format", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the format of the output" }, + "gnupg", N_("Options controlling the format of the output") }, { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "sh-style command output", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, @@ -687,14 +694,14 @@ static gc_option_t gc_options_dirmngr[] = { "Configuration", GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT, - NULL, "Options controlling the configuration" }, + "gnupg", N_("Options controlling the configuration") }, { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "dirmngr", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, - "dirmngr", "Options useful for debugging" }, + "gnupg", N_("Options useful for debugging") }, { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED, "dirmngr", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, @@ -713,7 +720,7 @@ static gc_option_t gc_options_dirmngr[] = { "Enforcement", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Options controlling the interactivity and enforcement" }, + "gnupg", N_("Options controlling the interactivity and enforcement") }, { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "run without asking a user", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, @@ -723,7 +730,7 @@ static gc_option_t gc_options_dirmngr[] = { "LDAP", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, - NULL, "Configuration of LDAP servers to use" }, + "gnupg", N_("Configuration of LDAP servers to use") }, { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "add new servers discovered in CRL distribution points" " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, @@ -748,7 +755,7 @@ static gc_option_t gc_options_dirmngr[] = { "OCSP", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, - NULL, "Configuration for OCSP" }, + "gnupg", N_("Configuration for OCSP") }, { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "allow sending OCSP requests", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, @@ -850,8 +857,8 @@ gpg_agent_runtime_change (void) } -/* More or less Robust version of dgettext. It has the sidefeect of - switching the codeset to utf-8 becuase this is what we want to +/* More or less Robust version of dgettext. It has the side effect of + switching the codeset to utf-8 because this is what we want to output. In theory it is posible to keep the orginal code set and switch back for regular disgnostic output (redefine "_(" for that) but given the natur of this tool, being something invoked from @@ -870,6 +877,13 @@ my_dgettext (const char *domain, const char *msgid) bind_textdomain_codeset (PACKAGE_GT, "utf-8"); switched_codeset = 1; } + + /* Note: This is a hack to actually use the gnupg2 domain as + long we are in a transition phase where gnupg 1.x and 1.9 may + coexist. */ + if (!strcmp (domain, "gnupg")) + domain = PACKAGE_GT; + text = dgettext (domain, msgid); return text ? text : msgid; } -- cgit v1.2.3 From 374971248465b5c02b92ede807e3fef6e5673fbd Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Sep 2004 17:15:42 +0000 Subject: Print warning when --default-key is used. --- sm/gpgsm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 3331537b1..5e3e0f2d9 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1065,6 +1065,7 @@ main ( int argc, char **argv) case oDefaultKey: /* fixme:opt.def_secret_key = pargs.r.ret_str;*/ + log_info ("WARNING: --default-key has not yet been implemented\n"); break; case oDefRecipient: if (*pargs.r.ret_str) -- cgit v1.2.3 From a8b5bc669fad63b66a6a49f1aa64750ae4f00afa Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 29 Sep 2004 23:05:37 +0000 Subject: 2004-09-30 Marcus Brinkmann <marcus@g10code.de> * contrib.texi (Contributors): Add two missing periods. --- doc/ChangeLog | 4 ++++ doc/contrib.texi | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index db72a2020..eabebbfd1 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2004-09-30 Marcus Brinkmann <marcus@g10code.de> + + * contrib.texi (Contributors): Add two missing periods. + 2004-09-29 Werner Koch <wk@g10code.com> * gpgsm.texi (Configuration Options): Add --log-file. diff --git a/doc/contrib.texi b/doc/contrib.texi index 035b6c251..73d722c23 100644 --- a/doc/contrib.texi +++ b/doc/contrib.texi @@ -15,7 +15,7 @@ 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 +Bernhard Herzog did extensive testing and tracked down a lot of bugs. @item Bernhard Reiter made sure that we met the specifications and the @@ -37,7 +37,7 @@ 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 +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. -- cgit v1.2.3 From 502be0ce06b747900628364ca0f560114b042b72 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 29 Sep 2004 23:06:02 +0000 Subject: 2004-09-30 Marcus Brinkmann <marcus@g10code.de> * tools.texi (Changing options): Add documentation for gpgconf. --- doc/ChangeLog | 2 + doc/tools.texi | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 500 insertions(+), 2 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index eabebbfd1..4c2eaf216 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,7 @@ 2004-09-30 Marcus Brinkmann <marcus@g10code.de> + * tools.texi (Changing options): Add documentation for gpgconf. + * contrib.texi (Contributors): Add two missing periods. 2004-09-29 Werner Koch <wk@g10code.com> diff --git a/doc/tools.texi b/doc/tools.texi index d04b01277..72707639c 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -9,7 +9,8 @@ GnuPG comes with a couple of smaller tools: @menu * watchgnupg:: Read logs from a socket. -* addgnupghome:: Create .gnupg home directories +* addgnupghome:: Create .gnupg home directories. +* gpgconf:: Modify .gnupg home directories. @end menu @@ -57,7 +58,7 @@ Display a brief help page and exit @node addgnupghome -@section Create .gnupg home directories +@section Create .gnupg home directories. If GnuPG is installed on a system with existing user accounts, it is sometimes required to populate the GnuPG home directory with existing @@ -72,3 +73,498 @@ addgnupghome is invoked by root as: @samp{addgnupghome account1 account2 ... accountn} + +@node gpgconf +@section Modify .gnupg home directories. + +The @command{gpgconf} is a utility to automatically and reasonable +safely query and modify configuration files in the @file{.gnupg} home +directory. It is designed not to be invoked manually by the user, but +automatically by graphical user interfaces (GUI).@footnote{Please note +that currently no locking is done, so concurrent access should be +avoided. There are some precautions to avoid corruption with +concurrent usage, but results may be inconsistent and some changes may +get lost. The stateless design makes it difficult to provide more +guarantees.} + +@command{gpgconf} provides access to the configuration of one or more +components of the GnuPG system. These components correspond more or +less to the programs that exist in the GnuPG framework, like GnuPG, +GPGSM, DirMngr, etc. But this is not a strict one-to-one +relationship. Not all configuration options are available through +@command{gpgconf}. @command{gpgconf} provides a generic and abstract +method to access the most important configuration options that can +feasibly be controlled via such a mechanism. + +@command{gpgconf} can be used to gather and change the options +available in each component, and can also provide their default +values. @command{gpgconf} will give detailed type information that +can be used to restrict the user's input without making an attempt to +commit the changes. + +@command{gpgconf} provides the backend of a configuration editor. The +configuration editor would usually be a graphical user interface +program, that allows to display the current options, their default +values, and allows the user to make changes to the options. These +changes can then be made active with @command{gpgconf} again. Such a +program that uses @command{gpgconf} in this way will be called GUI +throughout this section. + +@menu +* Invoking gpgconf:: List of all commands and options. +* Format conventions:: Formatting conventions relevant for all commands. +* Listing components:: List all gpgconf components. +* Listing options:: List all options of a component. +* Changing options:: Changing options of a component. +@end menu + + +@node Invoking gpgconf +@subsection Invoking gpgconf + +One of the following commands must be given: + +@table @gnupgtabopt +@item --list-components +List all components. This is the default command used if none is +specified. + +@item --list-options @var{component} +List all options of the component @var{component}. + +@item --change-options @var{component} +Change the options of the component @var{component}. +@end table + +The following options may be used: + +@table @gnupgtabopt +@c FIXME: Not yet supported. +@c @item -o @var{file} +@c @itemx --output @var{file} +@c Use @var{file} as output file. + +@item -v +@itemx --verbose +Outputs additional information while running. Specifically, this +extends numerical field values by human-readable descriptions. + +@c FIXME: Not yet supported. +@c @item -n +@c @itemx --dry-run +@c Do not actually change anything. Useful together with +@c @code{--change-options} for testing purposes. + +@item -r +@itemx --runtime +Only used together with @code{--change-options}. If one of the +modified options can be changed in a running daemon process, signal +the running daemon to ask it to reparse its configuration file after +changing. + +This means that the changes will take effect at run-time, as far as +this is possible. Otherwise, they will take effect at the next start +of the respective backend programs. +@end table + + +@node Format conventions +@subsection Format conventions + +Some lines in the output of @command{gpgconf} contain a list of +colon-separated fields. The following conventions apply: + +@itemize @bullet +@item +The GUI program is required to strip off trailing newline and/or +carriage return characters from the output. + +@item +@command{gpgconf} will never leave out fields. If a certain version +provides a certain field, this field will always be present in all +@command{gpgconf} versions from that time on. + +@item +Future versions of @command{gpgconf} might append fields to the list. +New fields will always be separated from the previously last field by +a colon separator. The GUI should be prepared to parse the last field +it knows about up until a colon or end of line. + +@item +Not all fields are defined under all conditions. You are required to +ignore the content of undefined fields. +@end itemize + +There are several standard types for the content of a field: + +@table @asis +@item verbatim +Some fields contain strings that are not escaped in any way. Such +fields are described to be used @emph{verbatim}. These fields will +never contain a colon character (for obvious reasons). No de-escaping +or other formatting is required to use the field content. This is for +easy parsing of the output, when it is known that the content can +never contain any special characters. + +@item percent-escaped +Some fields contain strings that are described to be +@emph{percent-escaped}. Such strings need to be de-escaped before +their content can be presented to the user. A percent-escaped string +is de-escaped by replacing all occurences of @code{%XY} by the byte +that has the hexadecimal value @code{XY}. @code{X} and @code{Y} are +from the set @code{0-9a-f}. + +@item localised +Some fields contain strings that are described to be @emph{localised}. +Such strings are translated to the active language and formatted in +the active character set. + +@item @w{unsigned number} +Some fields contain an @emph{unsigned number}. This number will +always fit into a 32-bit unsigned integer variable. The number may be +followed by a space, followed by a human readable description of that +value (if the verbose option is used). You should ignore everything +in the field that follows the number. + +@item @w{signed number} +Some fields contain a @emph{signed number}. This number will always +fit into a 32-bit signed integer variable. The number may be followed +by a space, followed by a human readable description of that value (if +the verbose option is used). You should ignore everything in the +field that follows the number. + +@item option +Some fields contain an @emph{option} argument. The format of an +option argument depends on the type of the option and on some flags: + +@table @asis +@item no argument +The simplest case is that the option does not take an argument at all +(@var{type} @code{0}). Then the option argument is an unsigned number +that specifies how often the option occurs. If the @code{list} flag +is not set, then the only valid number is @code{1}. Options that do +not take an argument never have the @code{default} or @code{optional +arg} flag set. + +@item number +If the option takes a number argument (@var{alt-type} is @code{2} or +@code{3}), and it can only occur once (@code{list} flag is not set), +then the option argument is either empty (only allowed if the argument +is optional), or it is a number. A number is a string that begins +with an optional minus character, followed by one or more digits. The +number must fit into an integer variable (unsigned or signed, +depending on @var{alt-type}). + +@item number list +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of numbers as described above. + +@item string +If the option takes a string argument (@var{alt-type} is 1), and it +can only occur once (@code{list} flag is not set) then the option +argument is either empty (only allowed if the argument is optional), +or it starts with a double quote character (@code{"}) followed by a +percent-escaped string that is the argument value. Note that there is +only a leading double quote character, no trailing one. The double +quote character is only needed to be able to differentiate between no +value and the empty string as value. + +@item string list +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of string arguments as described above. +@end table +@end table + +The active language and character set are currently determined from +the locale environment of the @command{gpgconf} program. + +@c FIXME: Document the active language and active character set. Allow +@c to change it via the command line? + + +@node Listing components +@subsection Listing components + +The command @code{--list-components} will list all components that can +be configured with @command{gpgconf}. Usually, one component will +correspond to one GnuPG-related program and contain the options of +that programs configuration file that can be modified using +@command{gpgconf}. However, this is not necessarily the case. A +component might also be a group of selected options from several +programs, or contain entirely virtual options that have a special +effect rather than changing exactly one option in one configuration +file. + +A component is a set of configuration options that semantically belong +together. Furthermore, several changes to a component can be made in +an atomic way with a single operation. The GUI could for example +provide a menu with one entry for each component, or a window with one +tabulator sheet per component. + +The command argument @code{--list-components} lists all available +components, one per line. The format of each line is: + +@code{@var{name}:@var{description}} + +@table @var +@item name +This field contains a name tag of the component. The name tag is used +to specify the component in all communication with @command{gpgconf}. +The name tag is to be used @emph{verbatim}. It is thus not in any +escaped format. + +@item description +The @emph{string} in this field contains a human-readable description +of the component. It can be displayed to the user of the GUI for +informational purposes. It is @emph{percent-escaped} and +@emph{localized}. +@end table + +Example: +@example +$ gpgconf --list-components +gpg:GPG for OpenPGP +gpg-agent:GPG Agent +scdaemon:Smartcard Daemon +gpgsm:GPG for S/MIME +dirmngr:Directory Manager +@end example + + +@node Listing options +@subsection Listing options + +Every component contains one or more options. Options may be gathered +into option groups to allow the GUI to give visual hints to the user +about which options are related. + +The command argument @code{@w{--list-options @var{component}}} lists +all options (and the groups they belong to) in the component +@var{component}, one per line. @var{component} must be the string in +the field @var{name} in the output of the @code{--list-components} +command. + +There is one line for each option and each group. First come all +options that are not in any group. Then comes a line describing a +group. Then come all options that belong into each group. Then comes +the next group and so on. There does not need to be any group (and in +this case the output will stop after the last non-grouped option). + +The format of each line is: + +@code{@var{name}:@var{flags}:@var{level}:@var{description}:@var{type}:@var{alt-type}:@var{argname}:@var{default}:@var{argdef}:@var{value}} + +@table @var +@item name +This field contains a name tag for the group or option. The name tag +is used to specify the group or option in all communication with +@command{gpgconf}. The name tag is to be used @emph{verbatim}. It is +thus not in any escaped format. + +@item flags +The flags field contains an @emph{unsigned number}. Its value is the +OR-wise combination of the following flag values: + +@table @code +@item group (1) +If this flag is set, this is a line describing a group and not an +option. +@end table + +The following flag values are only defined for options (that is, if +the @code{group} flag is not used). + +@table @code +@item optional arg (2) +If this flag is set, the argument is optional. This is never set for +@var{type} @code{0} (none) options. + +@item list (4) +If this flag is set, the option can be given multiple times. + +@item runtime (8) +If this flag is set, the option can be changed at runtime. + +@item default (16) +If this flag is set, a default value is available. + +@item default desc (32) +If this flag is set, a (runtime) default is available. This and the +@code{default} flag are mutually exclusive. + +@item no arg desc (64) +If this flag is set, and the @code{optional arg} flag is set, then the +option has a special meaning if no argument is given. +@end table + +@item level +This field is defined for options and for groups. It contains an +@emph{unsigned number} that specifies the expert level under which +this group or option should be displayed. The following expert levels +are defined for options (they have analogous meaning for groups): + +@table @code +@item basic (0) +This option should always be offered to the user. + +@item advanced (1) +This option may be offered to advanced users. + +@item expert (2) +This option should only be offered to expert users. + +@item invisible (3) +This option should normally never be displayed, not even to expert +users. + +@item internal (4) +This option is for internal use only. Ignore it. +@end table + +The level of a group will always be the lowest level of all options it +contains. + +@item description +This field is defined for options and groups. The @emph{string} in +this field contains a human-readable description of the option or +group. It can be displayed to the user of the GUI for informational +purposes. It is @emph{percent-escaped} and @emph{localized}. + +@item type +This field is only defined for options. It contains an @emph{unsigned +number} that specifies the type of the option's argument, if any. The +following types are defined: + +Basic types: + +@table @code +@item none (0) +No argument allowed. + +@item string (1) +An @emph{unformatted string}. + +@item int32 (2) +A @emph{signed number}. + +@item uint32 (3) +An @emph{unsigned number}. +@end table + +Complex types: + +@table @code +@item pathname (32) +A @emph{string} that describes the pathname of a file. The file does +not necessarily need to exist. + +@item ldap server (33) +A @emph{string} that describes an LDAP server in the format: + +@code{@var{hostname}:@var{port}:@var{username}:@var{password}:@var{base_dn}} +@end table + +More types will be added in the future. Please see the @var{alt-type} +field for information on how to cope with unknown types. + +@item alt-type +This field is identical to @var{type}, except that only the types +@code{0} to @code{31} are allowed. The GUI is expected to present the +user the option in the format specified by @var{type}. But if the +argument type @var{type} is not supported by the GUI, it can still +display the option in the more generic basic type @var{alt-type}. The +GUI must support all the defined basic types to be able to display all +options. More basic types may be added in future versions. If the +GUI encounters a basic type it doesn't support, it should report an +error and abort the operation. + +@item argname +This field is only defined for options with an argument type +@var{type} that is not @code{0}. In this case it may contain a +@emph{percent-escaped} and @emph{localised string} that gives a short +name for the argument. The field may also be empty, though, in which +case a short name is not known. + +@item default +This field is defined only for options. Its format is that of an +@emph{option argument} (@xref{Format conventions}, for details). If +the default value is empty, then no default is known. Otherwise, the +value specifies the default value for this option. Note that this +field is also meaningful if the option itself does not take a real +argument. + +@item argdef +This field is defined only for options for which the @code{optional +arg} flag is set. If the @code{no arg desc} flag is not set, its +format is that of an @emph{option argument} (@xref{Format +conventions}, for details). If the default value is empty, then no +default is known. Otherwise, the value specifies the default value +for this option. If the @code{no arg desc} flag is set, the field is +either empty or contains a description of the effect of this option if +no argument is given. Note that this field is also meaningful if the +option itself does not take a real argument. + +@item value +This field is defined only for options. Its format is that of an +@emph{option argument}. If it is empty, then the option is not +explicitely set in the current configuration, and the default applies +(if any). Otherwise, it contains the current value of the option. +Note that this field is also meaningful if the option itself does not +take a real argument. +@end table + + +@node Changing options +@subsection Changing options + +The command @w{@code{--change-options @var{component}}} will attempt +to change the options of the component @var{component} to the +specified values. @var{component} must be the string in the field +@var{name} in the output of the @code{--list-components} command. You +have to provide the options that shall be changed in the following +format on standard input: + +@code{@var{name}:@var{flags}:@var{new-value}} + +@table @var +@item name +This is the name of the option to change. @var{name} must be the +string in the field @var{name} in the output of the +@code{--list-options} command. + +@item flags +The flags field contains an @emph{unsigned number}. Its value is the +OR-wise combination of the following flag values: + +@table @code +@item default (16) +If this flag is set, the option is deleted and the default value is +used instead (if applicable). +@end table + +@item new-value +The new value for the option. This field is only defined if the +@code{default} flag is not set. The format is that of an @emph{option +argument}. If it is empty (or the field is omitted), the default +argument is used (only allowed if the argument is optional for this +option). Otherwise, the option will be set to the specified value. +@end table + +Examples: + +To set the force option, which is of basic type @code{none (0)}: + +@example +$ echo 'force:0:1' | gpgconf --change-options dirmngr +@end example + +To delete the force option: + +@example +$ echo 'force:16:' | gpgconf --change-options dirmngr +@end example + +The @code{--runtime} option can influence when the changes take +effect. -- cgit v1.2.3 From 5e41c3969cb0a5fa4c055133f5cc8e8451498b9e Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 29 Sep 2004 23:06:58 +0000 Subject: Remove what is now in the texi docs. --- tools/README.gpgconf | 349 +-------------------------------------------------- 1 file changed, 3 insertions(+), 346 deletions(-) diff --git a/tools/README.gpgconf b/tools/README.gpgconf index c0d3c7c61..084711441 100644 --- a/tools/README.gpgconf +++ b/tools/README.gpgconf @@ -2,344 +2,7 @@ GPG Conf ============ -CONCEPT -======= - -gpgconf provides access to the configuration of one or more components -of the GnuPG system. These components correspond more or less to the -programs that exist in the GnuPG framework, like GnuPG, GPGSM, -DirMngr, etc. But this is not a strict one-to-one relationship. Not -all configuration options are available through GPGConf. GPGConf -provides a generic and abstract method to access the most important -configuration options that can feasibly be controlled via such a -mechanism. - -GPGConf can be used to gather and change the options available in each -component, and can also provide their default values. GPGConf will -give detailed type information that can be used to restrict the user's -input without making an attempt to commit the changes. - -GPGConf provides the backend of a configuration editor. The -configuration editor would usually be a graphical user interface -program, that allows to display the current options, their default -values, and allows the user to make changes to the options. These -changes can then be made active with GPGConf again. Such a program -that uses GPGConf in this way will be called 'GUI' throughout this -document. - - -Format Conventions -================== - -Some lines in the output of GPGConf contain a list of colon-separated -fields. The following conventions apply: - -The GUI program is required to strip off trailing newline and/or carriage -return characters from the output. - -GPGConf will never leave out fields. If a certain version documents a -certain field, this field will always be present in all GPGConf -versions from that time on. - -Future versions of GPGConf might append fields to the list. New -fields will always be separated from the previously last field by a -colon separator. The GUI should be prepared to parse the last field -it knows about up until a colon or end of line. - -Not all fields are defined under all conditions. You are required to -ignore the content of undefined fields. - -Some fields contain strings that are not escaped in any way. Such -fields are described to be used "verbatim". These fields will never -contain a colon character (for obvious reasons). No de-escaping or -other formatting is required to use the field content. This is for -easy parsing of the output, when it is known that the content can -never contain any special characters. - -Some fields contain strings that are described to be -"percent-escaped". Such strings need to be de-escaped before their -content can be presented to the user. A percent-escaped string is -de-escaped by replacing all occurences of %XY by the byte that has the -hexadecimal value XY. X and Y are from the set { '0'..'9', 'a'..'f' }. - -Some fields contain strings that are described to be "localised". Such -strings are translated to the active language and formatted in the -active character set. - -Some fields contain an unsigned number. This number will always fit -into a 32-bit unsigned integer variable. The number may be followed -by a space, followed by a human readable description of that value. -You should ignore everything in the field that follows the number. - -Some fields contain a signed number. This number will always fit into -a 32-bit signed integer variable. The number may be followed by a -space, followed by a human readable description of that value. You -should ignore everything in the field that follows the number. - -Some fields contain an option argument. The format of an option -argument depends on the type of the option and on some flags: - -The simplest case is that the option does not take an argument at all -(TYPE is 0). Then the option argument is an unsigned number that -specifies how often the option occurs. If the LIST flag is not set, -then the only valid number is 1. Options that don't take an argument -never have the "default" or "optional arg" flag set. - -If the option takes a number argument (ALT-TYPE is 2 or 3), and it can -only occur once (LIST flag is not set), then the option argument is -either empty (only allowed if the argument is optional), or it is a -number. A number is a string that begins with an optional minus -character, followed by one or more digits. The number must fit into -an integer variable (unsigned or signed, depending on ALT-TYPE). - -If the option takes a number argument and it can occur more than once, -then the option argument is either empty, or it is a comma-separated -list of numbers as described above. - -If the option takes a string argument (ALT-TYPE is 1), and it can only -occur once (LIST flag is not set) then the option argument is either -empty (only allowed if the argument is optional), or it starts with a -double quote character (") followed by a percent-escaped string that -is the argument value. Note that there is only a leading double quote -character, no trailing one. The double quote character is only needed -to be able to differentiate between no value and the empty string as -value. - -If the option takes a number argument and it can occur more than once, -then the option argument is either empty, or it is a comma-separated -list of string arguments as described above. - -FIXME: Document the active language and active character set. Allow -to change it via the command line? - - -Components -========== - -A component is a set of configuration options that semantically belong -together. Furthermore, several changes to a component can be made in -an atomic way with a single operation. The GUI could for example -provide a menu with one entry for each component, or a window with one -tabulator sheet per component. - -The following interface is provided to list the available components: - -Command --list-components -------------------------- - -Outputs a list of all components available, one per line. The format -of each line is: - -NAME:DESCRIPTION - -NAME - -This field contains a name tag of the component. The name tag is used -to specify the component in all communication with GPGConf. The name -tag is to be used verbatim. It is not in any escaped format. - -DESCRIPTION - -The string in this field contains a human-readable description of the -component. It can be displayed to the user of the GUI for -informational purposes. It is percent-escaped and localized. - -Example: -$ gpgconf --list-components -gpg-agent:GPG Agent -dirmngr:CRL Manager - - -OPTIONS -======= - -Every component contains one or more options. Options may belong to a -group. The following command lists all options and the groups they -belong to: - -Command --list-options COMPONENT --------------------------------- - -Lists all options (and the groups they belong to) in the component -COMPONENT. COMPONENT is the string in the field NAME in the -output of the --list-components command. - -There is one line for each option and each group. First come all -options that are not in any group. Then comes a line describing a -group. Then come all options that belong into each group. Then comes -the next group and so on. - -The format of each line is: - -NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE - -NAME - -This field contains a name tag for the group or option. The name tag -is used to specify the group or option in all communication with -GPGConf. The name tag is to be used verbatim. It is not in any -escaped format. - -FLAGS - -The flags field contains an unsigned number. Its value is the -OR-wise combination of the following flag values: - - 1 group If this flag is set, this is a line describing - a group and not an option. - O 2 optional arg If this flag is set, the argument is optional. - This is never set for arg type 0 (none) options. - O 4 list If this flag is set, the option can be given - multiple times. - O 8 runtime If this flag is set, the option can be changed - at runtime. - O 16 default If this flag is set, a default value is available. - O 32 default desc If this flag is set, a (runtime) default is available. - This and the 'default' flag are mutually exclusive. - O 64 no arg desc If this flag is set, and the 'optional arg' flag - is set, then the option has a special meaning if no - argument is given. - -Flags marked with a 'O' are only defined for options (ie, if the GROUP -flag is not set). - -LEVEL - -This field is defined for options and for groups. It contains an -unsigned number that specifies the expert level under which this group -or option should be displayed. The following expert levels are -defined for options (they have analogous meaning for groups): - - 0 basic This option should always be offered to the user. - 1 advanced This option may be offered to advanced users. - 2 expert This option should only be offered to expert users. - 3 invisible This option should normally never be displayed, - not even to expert users. - 4 internal This option is for internal use only. Ignore it. - -The level of a group will always be the lowest level of all options it -contains. - -DESCRIPTION - -This field is defined for options and groups. The string in this -field contains a human-readable description of the option or group. -It can be displayed to the user of the GUI for informational purposes. -It is percent-escaped and localized. - -TYPE - -This field is only defined for options. It contains an unsigned -number that specifies the type of the option's argument, if any. -The following types are defined: - - Basic types - 0 none No argument allowed. - 1 string An unformatted string. - 2 int32 A signed integer number. - 3 uint32 An unsigned integer number. - - Complex types - 32 pathname A string that describes the pathname of a file. - The file does not necessarily need to exist. - 33 ldap server A string that describes an LDAP server in the format - HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. - -More types will be added in the future. Please see the ALT-TYPE field -for information on how to cope with unknown types. - -ALT-TYPE - -This field is identical to TYPE, except that only the types 0 to 31 -are allowed. The GUI is expected to present the user the option in -the format specified by TYPE. But if the argument type TYPE is not -supported by the GUI, it can still display the option in the more -generic basic type ALT-TYPE. The GUI must support all the defined -basic types to be able to display all options. More basic types may -be added in future versions. If the GUI encounters a basic type it -doesn't support, it should report an error and abort the operation. - -ARGNAME - -This field is only defined for options with an argument type TYPE that -is not 0. In this case it may contain a percent-escaped and localised -string that gives a short name for the argument. The field may also -be empty, though, in which case a short name is not known. - -DEFAULT - -This field is defined only for options. Its format is that of an -option argument (see section Format Conventions for details). If the -default value is empty, then no default is known. Otherwise, the -value specifies the default value for this option. Note that this -field is also meaningful if the option itself does not take a real -argument. - -ARGDEF - -This field is defined only for options for which the "optional arg" -flag is set. If the "no arg desc" flag is not set, its format is that -of an option argument (see section Format Conventions for details). -If the default value is empty, then no default is known. Otherwise, -the value specifies the default value for this option. If the "no arg -desc" flag is set, the field is either empty or contains a description -of the effect of this option if no argument is given. Note that this -field is also meaningful if the option itself does not take a real -argument. - -VALUE - -This field is defined only for options. Its format is that of an -option argument. If it is empty, then the option is not explicitely -set in the current configuration, and the default applies (if any). -Otherwise, it contains the current value of the option. Note that -this field is also meaningful if the option itself does not take a -real argument. - - -CHANGING OPTIONS -================ - -To change the options for a component, you must provide them in the -following format: - -NAME:FLAGS:NEW-VALUE - -NAME - -This is the name of the option to change. - -FLAGS - -The flags field contains an unsigned number. Its value is the -OR-wise combination of the following flag values: - - 16 default If this flag is set, the option is deleted and the - default value is used instead (if applicable). - -NEW-VALUE - -The new value for the option. This field is only defined if the -"default" flag is not set. The format is that of an option argument. -If it is empty (or the field is omitted), the default argument is used -(only allowed if the argument is optional for this option). -Otherwise, the option will be set to the specified value. - - -Example: -To set the option force, which is of basic type 0 (none). -$ echo 'force:0:1' | gpgconf --change-options dirmngr -To delete the option force: -$ echo 'force:16:' | gpgconf --change-options dirmngr - - -Option --runtime ----------------- - -If this option is set, the changes will take effect at run-time, as -far as this is possible. Otherwise, they will take effect at the next -start of the respective backend programs. - +Main documentation for this tool can be found in doc/tools.texi. BACKENDS ======== @@ -409,14 +72,8 @@ max-replies:10 TODO ---- +* Implement --dry-run and --quiet. + * Extend the backend interface to include gettext domain and description, if available, to avoid repeating this information in gpgconf. - -* Left out string arguments (optional) are written out exactly as -empty string arguments. Should we do quoting? - -* More string argument trouble: Special characters like newlines etc -cause trouble. Again, should we do quoting? - - -- cgit v1.2.3 From 63cdc7d132aef6d5face321f1c48c3427e0296c6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 30 Sep 2004 07:54:12 +0000 Subject: spelling fix --- sm/certdump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sm/certdump.c b/sm/certdump.c index 21581dca3..33052b186 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -640,7 +640,10 @@ gpgsm_format_keydesc (ksba_cert_t cert) orig_codeset = nl_langinfo (CODESET); #endif if (orig_codeset) - { /* We only switch when we are able to restore the codeset later. */ + { /* We only switch when we are able to restore the codeset later. + Note that bind_textdomain_codeset does only return on memory + errors but not if a codeset is not available. Thus we don't + bother printing a diagnostic here. */ orig_codeset = xstrdup (orig_codeset); if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) orig_codeset = NULL; -- cgit v1.2.3 From 5fe61f65dda1200e2b5e97bf75938ea30b776972 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 30 Sep 2004 08:38:32 +0000 Subject: * gpg.texi: New. * gnupg.texi: Include gpg.texi * tools.texi: Add a few @command markups. * gpgsm.texi: Ditto * gpg-agent.texi: Ditto. * scdaemon.texi: Ditto. --- doc/ChangeLog | 10 ++++++++++ doc/Makefile.am | 4 ++-- doc/gnupg.texi | 3 ++- doc/gpg-agent.texi | 25 ++++++++++++------------ doc/gpgsm.texi | 57 +++++++++++++++++++++++++++--------------------------- doc/scdaemon.texi | 21 ++++++++++---------- doc/tools.texi | 19 ++++++++++++------ 7 files changed, 80 insertions(+), 59 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 4c2eaf216..c8e955ef2 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,13 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * gpg.texi: New. + * gnupg.texi: Include gpg.texi + + * tools.texi: Add a few @command markups. + * gpgsm.texi: Ditto + * gpg-agent.texi: Ditto. + * scdaemon.texi: Ditto. + 2004-09-30 Marcus Brinkmann <marcus@g10code.de> * tools.texi (Changing options): Add documentation for gpgconf. diff --git a/doc/Makefile.am b/doc/Makefile.am index 3ac312049..d44765a2e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -21,8 +21,8 @@ info_TEXINFOS = gnupg.texi gnupg_TEXINFOS = \ - gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi tools.texi \ - debugging.texi glossary.texi contrib.texi gpl.texi + gpg.texi gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi \ + tools.texi debugging.texi glossary.texi contrib.texi gpl.texi DISTCLEANFILES = gnupg.tmp gnupg.ops diff --git a/doc/gnupg.texi b/doc/gnupg.texi index ec82fe425..478bb4395 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -102,8 +102,8 @@ Boston, MA 02111-1307 USA 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 GPG:: Using the OpenPGP protocol. * Invoking GPGSM:: Using the S/MIME protocol. * Invoking GPG-AGENT:: How to launch the secret key daemon. * Invoking SCDAEMON:: How to handle Smartcards. @@ -127,6 +127,7 @@ Indices * Index:: Index of concepts and symbol names. @end menu +@include gpg.texi @include gpgsm.texi @include gpg-agent.texi @include scdaemon.texi diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 2b45a41c1..26b5634cc 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -10,9 +10,10 @@ @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. +@command{gpg-agent} is a daemon to manage secret (private) keys +independelty from any protocol. It is used as a backend for +@command{gpg} and @command{gpgsm} as well as for a couple of other +utilities. @noindent The usual way to run the agent is from the @code{~/.xsession} file: @@ -24,8 +25,8 @@ eval `gpg-agent --daemon` @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 +to run multiple instance of the @command{gpg-agent}, so you should make sure that +only is running: @command{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: @@ -66,7 +67,7 @@ one (e.g. @file{/usr/bin/pinentry}). @c man end @noindent -@xref{Option Index}, for an index to GPG-AGENTS's commands and options. +@xref{Option Index}, for an index to @command{GPG-AGENT}'s commands and options. @menu * Agent Commands:: List of all commands. @@ -254,7 +255,7 @@ 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 +This option will let @command{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. @@ -372,13 +373,13 @@ $ eval `gpg-agent --daemon` @node Agent Protocol @section Agent's Assuan Protocol -The gpg-agent should be started by the login shell and set an +The @command{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 +usable. Because @command{gpg-agent} can only be used in background mode, no special command line option is required to activate the use of the protocol. @@ -416,7 +417,7 @@ appropriate secret key or to delegate it to a smartcard. @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 +not used, @command{gpg-agent} may try to figure out the key by trying to decrypt the message with each key available. @example @@ -528,8 +529,8 @@ The operation is affected by the option @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 +will lead @command{gpg-agent} to ignore the passphrase cache. Note, that there is +also a global command line option for @command{gpg-agent} to globally disable the caching. diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 05c351cd8..94e6936ad 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -10,15 +10,15 @@ @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. +@command{gpgsm} is a tool similar to @command{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. +@command{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. +@xref{Option Index}, for an index to @command{GPGSM}'s commands and options. @menu * GPGSM Commands:: List of all commands. @@ -26,7 +26,7 @@ rules defined for the German Sphinx project. * GPGSM Examples:: Some usage examples. Developer information: -* Unattended Usage:: Using @sc{gpgsm} from other programs. +* Unattended Usage:: Using @command{gpgsm} from other programs. * GPGSM Protocol:: The protocol the server mode uses. @end menu @@ -106,7 +106,7 @@ 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 +where a dirmngr must be able to call back to @command{gpgsm}. See the Dirmngr manual for details. @item --call-protect-tool @var{arguments} @@ -169,7 +169,7 @@ 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 +because @command{gpgsm} always make sure that the validity of a certificate is checked right before it is used. @item --delete-keys @var{pattern} @@ -208,7 +208,7 @@ smartcard is not yet supported. @node GPGSM Options @section Option Summary -GPGSM comes features a bunch ofoptions to control the exact behaviour +@command{GPGSM} comes features a bunch ofoptions to control the exact behaviour and to change the default configuration. @menu @@ -242,7 +242,7 @@ below the home directory of the user. @opindex verbose Outputs additional information while running. You can increase the verbosity by giving several -verbose commands to @sc{gpgsm}, such as @samp{-vv}. +verbose commands to @command{gpgsm}, such as @samp{-vv}. @item --policy-file @var{filename} @opindex policy-file @@ -463,7 +463,7 @@ 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 +Usually @command{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 @@ -472,12 +472,12 @@ 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. +lets @command{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 +lets @command{gpgsm} ignore all notAfter dates, this is used by the regresssion tests. @item --fixed-passphrase @var{string} @@ -515,7 +515,7 @@ $ gpgsm -er goo@@bar.net <plaintext >ciphertext @node Unattended Usage @section Unattended Usage -@sc{gpgsm} is often used as a backend engine by other software. To help +@command{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 @@ -541,7 +541,7 @@ 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 +should be displayed. Depending on the subcase @command{gpgsm} will issue these status codes: @table @asis @item signature valid and nothing did expire @@ -556,7 +556,7 @@ these status codes: @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: +@command{gpgsm} issues one of these status codes sequences: @table @code @item @code{BADSIG} @item @code{GOODSIG}, @code{VALIDSIG} @code{TRUST_NEVER} @@ -576,12 +576,13 @@ this is a missing certificate. @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). +Description of the protocol used to access @command{GPGSM}. +@command{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 +@command{gpgsm} as a server the command line the option +@code{--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. @@ -658,7 +659,7 @@ 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 +otherwise mark it as invalid. @command{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 @@ -671,7 +672,7 @@ closed. 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 +is no need to set recipients. @command{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. @@ -697,7 +698,7 @@ Signing is usually done with these commands: INPUT FD=@var{n} [--armor|--base64|--binary] @end example -This tells GPGSM to read the data to sign from file descriptor @var{n}. +This tells @command{GPGSM} to read the data to sign from file descriptor @var{n}. @example OUTPUT FD=@var{m} [--armor|--base64] @@ -755,14 +756,14 @@ client must provide it. 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 +token is used to store the key. Configuration options to @command{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 +@command{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: diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 3e11a8930..42dedb6b4 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -10,7 +10,7 @@ @c man begin DESCRIPTION -The @sc{scdaemon} is a daemon to manage smartcards. It is usually +The @command{scdaemon} is a daemon to manage smartcards. It is usually invoked by gpg-agent and in general not used directly. @c man end @@ -87,7 +87,7 @@ below the home directory of the user. @opindex verbose Outputs additional information while running. You can increase the verbosity by giving several -verbose commands to @sc{gpgsm}, such as @samp{-vv}. +verbose commands to @command{gpgsm}, such as @samp{-vv}. @item --debug-level @var{level} @opindex debug-level @@ -200,7 +200,7 @@ stripping off the two leading dashes. @node Card applications @section Description of card applications -@sc{scdaemon} supports the card applications as described below. +@command{scdaemon} supports the card applications as described below. @menu * OpenPGP Card:: The OpenPGP card application @@ -212,8 +212,8 @@ stripping off the two leading dashes. @node OpenPGP Card @subsection The OpenPGP card application ``openpgp'' -This application is currently only used by @sc{gpg} but may in -future also be useful with @sc{gpgsm}. +This application is currently only used by @command{gpg} but may in +future also be useful with @command{gpgsm}. The specification for such a card is available at @uref{http://g10code.com/docs/openpgp-card-1.0.pdf}. @@ -223,7 +223,7 @@ The specification for such a card is available at This is the main application of the Telesec cards as available in Germany. It is a superset of the German DINSIG card. The card is -used by @sc{gpgsm}. +used by @command{gpgsm}. @node DINSIG Card @subsection The DINSIG card application ``dinsig'' @@ -237,7 +237,7 @@ the German signature law and its bylaws (SigG and SigV). This is common fraqmework for smart card applications; support is only available if compiled with support for the OpenSC library. It is used -by @sc{gpgsm}. +by @command{gpgsm}. @@ -375,7 +375,7 @@ To sign some data the caller should use the command SETDATA @var{hexstring} @end example -to tell scdaemon about the data to be signed. The data must be given in +to tell @command{scdaemon} about the data to be signed. The data must be given in hex notation. The actual signing is done using the command @example @@ -395,8 +395,9 @@ To decrypt some data the caller should use the command 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 +to tell @command{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} diff --git a/doc/tools.texi b/doc/tools.texi index 72707639c..79ae85d90 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -13,18 +13,20 @@ GnuPG comes with a couple of smaller tools: * gpgconf:: Modify .gnupg home directories. @end menu - +@c +@c WATHCGNUPG +@c @node watchgnupg @section Read logs from a socket Most of the main utilities are able to write there log files to a -Unix Domain socket if configured that way. watchgnupg is a simple +Unix Domain socket if configured that way. @command{watchgnupg} is a simple listener for such a socket. It ameliorates the output with a time stamp and makes sure that long lines are not interspersed with log output from other utilities. @noindent -watchgnupg is commonly invoked as +@command{watchgnupg} is commonly invoked as @samp{watchgnupg --force ~/.gnupg/S.log} @@ -33,7 +35,7 @@ This starts it on the current terminal for listening on the socket @file{~/.gnupg/S.log}. @noindent -watchgnupg understands these options: +@command{watchgnupg} understands these options: @table @gnupgtabopt @@ -56,7 +58,9 @@ Display a brief help page and exit @end table - +@c +@c ADDGNUPGHOME +@c @node addgnupghome @section Create .gnupg home directories. @@ -69,11 +73,14 @@ directories of the accounts given on the command line. It takes care not to overwrite existing GnuPG home directories. @noindent -addgnupghome is invoked by root as: +@command{addgnupghome} is invoked by root as: @samp{addgnupghome account1 account2 ... accountn} +@c +@c GPGCONF +@c @node gpgconf @section Modify .gnupg home directories. -- cgit v1.2.3 From ce6a094cc094e6f57268001b289a249f08554e78 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 30 Sep 2004 08:39:08 +0000 Subject: * gpg.texi: New. --- doc/gpg.texi | 1821 +--------------------------------------------------------- 1 file changed, 21 insertions(+), 1800 deletions(-) diff --git a/doc/gpg.texi b/doc/gpg.texi index 4ed4f1f76..3254c94df 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -1,1806 +1,27 @@ -\input texinfo -@c This Texinfo document has been automatically generated by -@c docbook2texi from a DocBook documentation. The tool used -@c can be found at: -@c <URL:http://shell.ipoline.com/~elmert/hacks/docbook2X/> -@c Please send any bug reports, improvements, comments, -@c patches, etc. to Steve Cheng <steve@ggi-project.org>. +@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. -@setfilename gpg.info -@dircategory GnuPG -@direntry -* gpg: (gpg). GnuPG encryption and signing tool. -@end direntry +@node Invoking GPG +@chapter Invoking GPG +@cindex GPG command options +@cindex command options +@cindex options, GPG command -@node top -@top gpg -@menu -@end menu +@c man begin DESCRIPTION -@majorheading Name -gpg ---- encryption and signing tool</> +@command{gpg} is the OpenPGP part of GnuPG. The version included in +this package is not as matured as the standard versions (1.2.x or +1.4.x) and thus we strongly suggest to keep on using the one of the +standard versions. Both versions may be installed side by side and +should coexists without problems. To help for that, the @command{gpg} +from this package gets installed under the name @command{gpg2}. If you +really want to use this @command{gpg2} command you should name the +configuration file @file{gpg.conf-1.9} to keep it separate from the +one used with the standard @command{gpg}. -@majorheading Synopsis +Documentation for the old standard @command{gpg} is available in a +man page and at @inforef{Top,GnuPG 1,gpg}. -@majorheading DESCRIPTION -@code{gpg} is the main program for the GnuPG system. -This man page only lists the commands and options available. -For more verbose documentation get the GNU Privacy Handbook (GPH) or -one of the other documents at http://www.gnupg.org/docs.html . - -Please remember that option parsing stops as soon as a non option is -encountered, you can explicitly stop option parsing by using the -special option "---". - -@majorheading COMMANDS -@code{gpg} recognizes these commands: - -@table @asis -@item -s, ---sign -Make a signature. This command may be combined -with ---encrypt. - -@item ---clearsign -Make a clear text signature. - -@item -b, ---detach-sign -Make a detached signature. - -@item -e, ---encrypt -Encrypt data. This option may be combined with ---sign. - -@item -c, ---symmetric -Encrypt with a symmetric cipher using a passphrase. The default -symmetric cipher used is CAST5, but may be chosen with the ----cipher-algo option. - -@item ---store -Store only (make a simple RFC1991 packet). - -@item ---decrypt @code{file} -Decrypt @code{file} (or stdin if no file is specified) and -write it to stdout (or the file specified with ----output). If the decrypted file is signed, the -signature is also verified. 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. - -@item ---verify @code{sigfile} @code{signed-files} -Assume that @code{sigfile} is a signature and verify it -without generating any output. With no arguments, -the signature packet is read from stdin. If -only a sigfile is given, it may be a complete -signature or a detached signature, in which case -the signed stuff is expected in a file without the -".sig" or ".asc" extension. -With more than -1 argument, the first should be a detached signature -and the remaining files are the signed stuff. To read the signed -stuff from stdin, use @samp{-} as the second filename. -For security reasons a detached signature cannot read the signed -material from stdin without denoting it in the above way. - -@item ---verify-files @code{files} -This is a special version of the ---verify command which does not work with -detached signatures. The command expects the files to be verified either -on the command line or reads the filenames from stdin; each name must be on -separate line. The command is intended for quick checking of many files. - -@item ---encrypt-files @code{files} -This is a special version of the ---encrypt command. The command expects -the files to be encrypted either on the command line or reads the filenames -from stdin; each name must be on separate line. The command is intended -for a quick encryption of multiple files. - -@item ---decrypt-files @code{files} -The same as ---encrypt-files with the difference that files will be -decrypted. The syntax or the filenames is the same. - -@item ---list-keys @code{names} -@itemx ---list-public-keys @code{names} -List all keys from the public keyrings, or just the ones given on the -command line. - -Avoid using the output of this command in scripts or other programs as -it is likely to change as GnuPG changes. See ---with-colons for a -machine-parseable key listing command that is appropriate for use in -scripts and other programs. - -@item ---list-secret-keys @code{names} -List all keys from the secret keyrings, or just the ones given on the -command line. A '#' after the letters 'sec' means that the secret key -is not usable (for example, if it was created via ----export-secret-subkeys). - -@item ---list-sigs @code{names} -Same as ---list-keys, but the signatures are listed too. - -For each signature listed, there are several flags in between the -"sig" tag and keyid. These flags give additional information about -each signature. From left to right, they are the numbers 1-3 for -certificate check level (see ---default-cert-check-level), "L" for a -local or non-exportable signature (see ---lsign-key), "R" for a -nonRevocable signature (see ---nrsign-key), "P" for a signature that -contains a policy URL (see ---cert-policy-url), "N" for a signature -that contains a notation (see ---cert-notation), "X" for an eXpired -signature (see ---ask-cert-expire), and the numbers 1-9 or "T" for 10 -and above to indicate trust signature levels (see the ---edit-key -command "tsign"). - -@item ---check-sigs @code{names} -Same as ---list-sigs, but the signatures are verified. - -@item ---fingerprint @code{names} -List all keys with their fingerprints. This is the -same output as ---list-keys but with the additional output -of a line with the fingerprint. May also be combined -with ---list-sigs or --check-sigs. -If this command is given twice, the fingerprints of all -secondary keys are listed too. - -@item ---list-packets -List only the sequence of packets. This is mainly -useful for debugging. - -@item ---gen-key -Generate a new key pair. This command is normally only used -interactively. - -There is an experimental feature which allows you to create keys -in batch mode. See the file @file{doc/DETAILS} -in the source distribution on how to use this. - -@item ---edit-key @code{name} -Present a menu which enables you to do all key -related tasks: - -@table @asis -@item sign -Make a signature on key of user @code{name} -If the key is not yet signed by the default -user (or the users given with -u), the -program displays the information of the key -again, together with its fingerprint and -asks whether it should be signed. This -question is repeated for all users specified -with -u. - -@item lsign -Same as ---sign but the signature is marked as -non-exportable and will therefore never be used -by others. This may be used to make keys valid -only in the local environment. - -@item nrsign -Same as ---sign but the signature is marked as non-revocable and can -therefore never be revoked. - -@item nrlsign -Combines the functionality of nrsign and lsign to make a signature -that is both non-revocable and -non-exportable. - -@item tsign -Make a trust signature. This is a signature that combines the notions -of certification (like a regular signature), and trust (like the -"trust" command). It is generally only useful in distinct communities -or groups. - -@item revsig -Revoke a signature. For every signature which has been generated by -one of the secret keys, GnuPG asks whether a revocation certificate -should be generated. - -@item trust -Change the owner trust value. This updates the -trust-db immediately and no save is required. - -@item disable -@itemx enable -Disable or enable an entire key. A disabled key can not normally be -used for encryption. - -@item adduid -Create an alternate user id. - -@item addphoto -Create a photographic user id. This will prompt for a JPEG file that -will be embedded into the user ID. A very large JPEG will make for a -very large key. - -@item deluid -Delete a user id. - -@item revuid -Revoke a user id. - -@item addkey -Add a subkey to this key. - -@item delkey -Remove a subkey. - -@item addrevoker -Add a designated revoker. This takes one optional argument: -"sensitive". If a designated revoker is marked as sensitive, it will -not be exported by default (see -export-options). - -@item revkey -Revoke a subkey. - -@item expire -Change the key expiration time. If a subkey is selected, the -expiration time of this subkey will be changed. With no selection, -the key expiration of the primary key is changed. - -@item passwd -Change the passphrase of the secret key. - -@item primary -Flag the current user id as the primary one, removes the primary user -id flag from all other user ids and sets the timestamp of all affected -self-signatures one second ahead. Note that setting a photo user ID -as primary makes it primary over other photo user IDs, and setting a -regular user ID as primary makes it primary over other regular user -IDs. - -@item uid @code{n} -Toggle selection of user id with index @code{n}. -Use 0 to deselect all. - -@item key @code{n} -Toggle selection of subkey with index @code{n}. -Use 0 to deselect all. - -@item check -Check all selected user ids. - -@item showphoto -Display the selected photographic user -id. - -@item pref -List preferences from the selected user ID. This shows the actual -preferences, without including any implied preferences. - -@item showpref -More verbose preferences listing for the selected user ID. This shows -the preferences in effect by including the implied preferences of -3DES (cipher), SHA-1 (digest), and Uncompressed (compression) if they -are not already included in the preference list. - -@item setpref @code{string} -Set the list of user ID preferences to @code{string}, this should be a -string similar to the one printed by "pref". Using an empty string -will set the default preference string, using "none" will set the -preferences to nil. Use "gpg ---version" to get a list of available -algorithms. This command just initializes an internal list and does -not change anything unless another command (such as "updpref") which -changes the self-signatures is used. - -@item updpref -Change the preferences of all user IDs (or just of the selected ones -to the current list of preferences. The timestamp of all affected -self-signatures will be advanced by one second. Note that while you -can change the preferences on an attribute user ID (aka "photo ID"), -GnuPG does not select keys via attribute user IDs so these preferences -will not be used by GnuPG. - -@item toggle -Toggle between public and secret key listing. - -@item save -Save all changes to the key rings and quit. - -@item quit -Quit the program without updating the -key rings. - -@end table - -The listing shows you the key with its secondary -keys and all user ids. Selected keys or user ids -are indicated by an asterisk. The trust value is -displayed with the primary key: the first is the -assigned owner trust and the second is the calculated -trust value. Letters are used for the values: - -@table @asis -@item - -No ownertrust assigned / not yet calculated. - -@item e -Trust -calculation has failed; probably due to an expired key. - -@item q -Not enough information for calculation. - -@item n -Never trust this key. - -@item m -Marginally trusted. - -@item f -Fully trusted. - -@item u -Ultimately trusted. - -@end table - -@item ---sign-key @code{name} -Signs a public key with your secret key. This is a shortcut version of -the subcommand "sign" from ---edit. - -@item ---lsign-key @code{name} -Signs a public key with your secret key but marks it as -non-exportable. This is a shortcut version of the subcommand "lsign" -from ---edit. - -@item ---nrsign-key @code{name} -Signs a public key with your secret key but marks it as non-revocable. -This is a shortcut version of the subcommand "nrsign" from ---edit. - -@item ---delete-key @code{name} -Remove key from the public keyring. In batch mode either ---yes is -required or the key must be specified by fingerprint. This is a -safeguard against accidental deletion of multiple keys. - -@item ---delete-secret-key @code{name} -Remove key from the secret and public keyring. In batch mode the key -must be specified by fingerprint. - -@item ---delete-secret-and-public-key @code{name} -Same as ---delete-key, but if a secret key exists, it will be removed -first. In batch mode the key must be specified by fingerprint. - -@item ---gen-revoke -Generate a revocation certificate for the complete key. To revoke -a subkey or a signature, use the ---edit command. - -@item ---desig-revoke -Generate a designated revocation certificate for a key. This allows a -user (with the permission of the keyholder) to revoke someone else's -key. - -@item ---export @code{names} -Either export all keys from all keyrings (default -keyrings and those registered via option ---keyring), -or if at least one name is given, those of the given -name. The new keyring is written to stdout or to -the file given with option "output". Use together -with ---armor to mail those keys. - -@item ---send-keys @code{names} -Same as ---export but sends the keys to a keyserver. -Option ---keyserver must be used to give the name -of this keyserver. Don't send your complete keyring -to a keyserver - select only those keys which are new -or changed by you. - -@item ---export-all @code{names} -Same as ---export, but also exports keys which -are not compatible with OpenPGP. - -@item ---export-secret-keys @code{names} -@itemx ---export-secret-subkeys @code{names} -Same as ---export, but exports the secret keys instead. -This is normally not very useful and a security risk. -The second form of the command has the special property to -render the secret part of the primary key useless; this is -a GNU extension to OpenPGP and other implementations can -not be expected to successfully import such a key. -See the option ---simple-sk-checksum if you want to import such an -exported key with an older OpenPGP implementation. - -@item ---import @code{files} -@itemx ---fast-import @code{files} -Import/merge keys. This adds the given keys to the -keyring. The fast version is currently just a synonym. - -There are a few other options which control how this command works. -Most notable here is the ---merge-only option which does not insert new keys -but does only the merging of new signatures, user-IDs and subkeys. - -@item ---recv-keys @code{key IDs} -Import the keys with the given key IDs from a keyserver. Option ----keyserver must be used to give the name of this keyserver. - -@item ---refresh-keys @code{key IDs} -Request updates from a keyserver for keys that already exist on the -local keyring. This is useful for updating a key with the latest -signatures, user IDs, etc. Option ---keyserver must be used to give -the name of this keyserver. - -@item ---search-keys @code{names} -Search the keyserver for the given names. Multiple names given here -will be joined together to create the search string for the keyserver. -Option ---keyserver must be used to give the name of this keyserver. - -@item ---update-trustdb -Do trust database maintenance. This command iterates over all keys -and builds the Web-of-Trust. This is an interactive command because it -may have to ask for the "ownertrust" values for keys. The user has to -give an estimation of how far she trusts the owner of the displayed -key to correctly certify (sign) other keys. GnuPG only asks for the -ownertrust value if it has not yet been assigned to a key. Using the ----edit-key menu, the assigned value can be changed at any time. - -@item ---check-trustdb -Do trust database maintenance without user interaction. From time to -time the trust database must be updated so that expired keys or -signatures and the resulting changes in the Web-of-Trust can be -tracked. Normally, GnuPG will calculate when this is required and do -it automatically unless ---no-auto-check-trustdb is set. This command -can be used to force a trust database check at any time. The -processing is identical to that of ---update-trustdb but it skips keys -with a not yet defined "ownertrust". - -For use with cron jobs, this command can be used together with ---batch -in which case the trust database check is done only if a check is -needed. To force a run even in batch mode add the option ---yes. - -@item ---export-ownertrust -Send the ownertrust values to stdout. This is useful for backup -purposes as these values are the only ones which can't be re-created -from a corrupted trust DB. - -@item ---import-ownertrust @code{files} -Update the trustdb with the ownertrust values stored -in @code{files} (or stdin if not given); existing -values will be overwritten. - -@item ---rebuild-keydb-caches -When updating from version 1.0.6 to 1.0.7 this command should be used -to create signature caches in the keyring. It might be handy in other -situations too. - -@item ---print-md @code{algo} @code{files} -@itemx ---print-mds @code{files} -Print message digest of algorithm ALGO for all given files or stdin. -With the second form (or a deprecated "*" as algo) digests for all -available algorithms are printed. - -@item ---gen-random @code{0|1|2} @code{count} -Emit COUNT random bytes of the given quality level. If count is not given -or zero, an endless sequence of random bytes will be emitted. -PLEASE, don't use this command unless you know what you are doing; it may -remove precious entropy from the system! - -@item ---gen-prime @code{mode} @code{bits} @code{qbits} -Use the source, Luke :-). The output format is still subject to change. - -@item ---version -Print version information along with a list -of supported algorithms. - -@item ---warranty -Print warranty information. - -@item -h, ---help -Print usage information. This is a really long list even though it -doesn't list all options. For every option, consult this manual. - -@end table - -@majorheading OPTIONS -Long options can be put in an options file (default -"~/.gnupg/gpg.conf"). Short option names will not work - for example, -"armor" is a valid option for the options file, while "a" is not. Do -not write the 2 dashes, but simply the name of the option and any -required arguments. Lines with a hash ('#') as the first -non-white-space character are ignored. Commands may be put in this -file too, but that is not generally useful as the command will execute -automatically with every execution of gpg. - -@code{gpg} recognizes these options: - -@table @asis -@item -a, ---armor -Create ASCII armored output. - -@item -o, ---output @code{file} -Write output to @code{file}. - -@item ---mangle-dos-filenames -@itemx ---no-mangle-dos-filenames -Older version of Windows cannot handle filenames with more than one -dot. ---mangle-dos-filenames causes GnuPG to replace (rather than add -to) the extension of an output filename to avoid this problem. This -option is off by default and has no effect on non-Windows platforms. - -@item -u, ---local-user @code{name} -Use @code{name} as the user ID to sign. -This option is silently ignored for the list commands, -so that it can be used in an options file. - -@item ---default-key @code{name} -Use @code{name} as default user ID for signatures. If this -is not used the default user ID is the first user ID -found in the secret keyring. - -@item -r, ---recipient @code{name} -@itemx -Encrypt for user id @code{name}. If this option or ---hidden-recipient -is not specified, GnuPG asks for the user-id unless ----default-recipient is given. - -@item -R, ---hidden-recipient @code{name} -@itemx -Encrypt for user id @code{name}, but hide the keyid of the key. This -option hides the receiver of the message and is a countermeasure -against traffic analysis. If this option or ---recipient is not -specified, GnuPG asks for the user-id unless ---default-recipient is -given. - -@item ---default-recipient @code{name} -Use @code{name} as default recipient if option ---recipient is not used and -don't ask if this is a valid one. @code{name} must be non-empty. - -@item ---default-recipient-self -Use the default key as default recipient if option ---recipient is not used and -don't ask if this is a valid one. The default key is the first one from the -secret keyring or the one set with ---default-key. - -@item ---no-default-recipient -Reset ---default-recipient and --default-recipient-self. - -@item ---encrypt-to @code{name} -Same as ---recipient but this one is intended for use -in the options file and may be used with -your own user-id as an "encrypt-to-self". These keys -are only used when there are other recipients given -either by use of ---recipient or by the asked user id. -No trust checking is performed for these user ids and -even disabled keys can be used. - -@item ---hidden-encrypt-to @code{name} -Same as ---hidden-recipient but this one is intended for use in the -options file and may be used with your own user-id as a hidden -"encrypt-to-self". These keys are only used when there are other -recipients given either by use of ---recipient or by the asked user id. -No trust checking is performed for these user ids and even disabled -keys can be used. - -@item ---no-encrypt-to -Disable the use of all ---encrypt-to and --hidden-encrypt-to keys. - -@item -v, ---verbose -Give more information during processing. If used -twice, the input data is listed in detail. - -@item -q, ---quiet -Try to be as quiet as possible. - -@item -z @code{n}, ---compress @code{n} -Set compression level to @code{n}. A value of 0 for @code{n} -disables compression. Default is to use the default -compression level of zlib (normally 6). - -@item -t, ---textmode -@itemx ---no-textmode -Use canonical text mode. ---no-textmode disables this option. If -t -(but not ---textmode) is used together with armoring and signing, this -enables clearsigned messages. This kludge is needed for command-line -compatibility with command-line versions of PGP; normally you would -use ---sign or --clearsign to select the type of the signature. - -@item -n, ---dry-run -Don't make any changes (this is not completely implemented). - -@item -i, ---interactive -Prompt before overwriting any files. - -@item ---batch -@itemx ---no-batch -Use batch mode. Never ask, do not allow interactive commands. ----no-batch disables this option. - -@item ---no-tty -Make sure that the TTY (terminal) is never used for any output. -This option is needed in some cases because GnuPG sometimes prints -warnings to the TTY if ---batch is used. - -@item ---yes -Assume "yes" on most questions. - -@item ---no -Assume "no" on most questions. - -@item ---default-cert-check-level @code{n} -The default to use for the check level when signing a key. - -0 means you make no particular claim as to how carefully you verified -the key. - -1 means you believe the key is owned by the person who claims to own -it but you could not, or did not verify the key at all. This is -useful for a "persona" verification, where you sign the key of a -pseudonymous user. - -2 means you did casual verification of the key. For example, this -could mean that you verified that the key fingerprint and checked the -user ID on the key against a photo ID. - -3 means you did extensive verification of the key. For example, this -could mean that you verified the key fingerprint with the owner of the -key in person, and that you checked, by means of a hard to forge -document with a photo ID (such as a passport) that the name of the key -owner matches the name in the user ID on the key, and finally that you -verified (by exchange of email) that the email address on the key -belongs to the key owner. - -Note that the examples given above for levels 2 and 3 are just that: -examples. In the end, it is up to you to decide just what "casual" -and "extensive" mean to you. - -This option defaults to 0. - -@item ---trusted-key @code{long key ID} -Assume that the specified key (which must be given -as a full 8 byte key ID) is as trustworthy as one of -your own secret keys. This option is useful if you -don't want to keep your secret keys (or one of them) -online but still want to be able to check the validity of a given -recipient's or signator's key. - -@item ---trust-model @code{pgp|classic|always} -Set what trust model GnuPG should follow. The models are: - -@table @asis -@item pgp -This is the web-of-trust combined with trust signatures as used in PGP -5.x and later. This is the default trust model. - -@item classic -This is the standard web-of-trust as used in PGP 2.x and earlier. - -@item always -Skip key validation and assume that used keys are always fully -trusted. You won't use this unless you have installed some external -validation scheme. This option also suppresses the "[uncertain]" tag -printed with signature checks when there is no evidence that the user -ID is bound to the key. - -@end table - -@item ---always-trust -Identical to `---trust-model always' - -@item ---keyserver @code{name} -Use @code{name} as your keyserver. This is the server that ---recv-keys, ----send-keys, and --search-keys will communicate with to receive keys -from, send keys to, and search for keys on. The format of the -@code{name} is a URI: `scheme:[//]keyservername[:port]' The scheme is -the type of keyserver: "hkp" for the Horowitz (or compatible) -keyservers, "ldap" for the NAI LDAP keyserver, or "mailto" for the -Horowitz email keyserver. Note that your particular installation of -GnuPG may have other keyserver types available as well. Keyserver -schemes are case-insensitive. - -Most keyservers synchronize with each other, so there is generally no -need to send keys to more than one server. Using the command "host -l -pgp.net | grep wwwkeys" gives you a list of HKP keyservers. When -using one of the wwwkeys servers, due to load balancing using -round-robin DNS you may notice that you get a different key server -each time. - -@item ---keyserver-options @code{parameters} -This is a space or comma delimited string that gives options for the -keyserver. Options can be prepended with a `no-' to give the opposite -meaning. Valid import-options or export-options may be used here as -well to apply to importing (---recv-key) or exporting (--send-key) a -key from a keyserver. While not all options are available for all -keyserver types, some common options are: - -@table @asis -@item include-revoked -When searching for a key with ---search-keys, include keys that are -marked on the keyserver as revoked. Note that this option is always -set when using the NAI HKP keyserver, as this keyserver does not -differentiate between revoked and unrevoked keys. - -@item include-disabled -When searching for a key with ---search-keys, include keys that are -marked on the keyserver as disabled. Note that this option is not -used with HKP keyservers. - -@item include-subkeys -When receiving a key, include subkeys as potential targets. Note that -this option is not used with HKP keyservers, as they do not support -retrieving keys by subkey id. - -@item use-temp-files -On most Unix-like platforms, GnuPG communicates with the keyserver -helper program via pipes, which is the most efficient method. This -option forces GnuPG to use temporary files to communicate. On some -platforms (such as Win32 and RISC OS), this option is always enabled. - -@item keep-temp-files -If using `use-temp-files', do not delete the temp files after using -them. This option is useful to learn the keyserver communication -protocol by reading the temporary files. - -@item verbose -Tell the keyserver helper program to be more verbose. This option can -be repeated multiple times to increase the verbosity level. - -@item honor-http-proxy -For keyserver schemes that use HTTP (such as HKP), try to access the -keyserver over the proxy set with the environment variable -"http_proxy". - -@item auto-key-retrieve -This option enables the automatic retrieving of keys from a keyserver -when verifying signatures made by keys that are not on the local -keyring. - -Note that this option makes a "web bug" like behavior possible. -Keyserver operators can see which keys you request, so by sending you -a message signed by a brand new key (which you naturally will not have -on your local keyring), the operator can tell both your IP address and -the time when you verified the signature. - -@end table - -@item ---import-options @code{parameters} -This is a space or comma delimited string that gives options for -importing keys. Options can be prepended with a `no-' to give the -opposite meaning. The options are: - -@table @asis -@item allow-local-sigs -Allow importing key signatures marked as "local". This is not -generally useful unless a shared keyring scheme is being used. -Defaults to no. - -@item repair-pks-subkey-bug -During import, attempt to repair the damage caused by the PKS -keyserver bug (pre version 0.9.6) that mangles keys with multiple -subkeys. Note that this cannot completely repair the damaged key as -some crucial data is removed by the keyserver, but it does at least -give you back one subkey. Defaults to no for regular ---import and to -yes for keyserver ---recv-keys. - -@end table - -@item ---export-options @code{parameters} -This is a space or comma delimited string that gives options for -exporting keys. Options can be prepended with a `no-' to give the -opposite meaning. The options are: - -@table @asis -@item include-non-rfc -Include non-RFC compliant keys in the export. Defaults to yes. - -@item include-local-sigs -Allow exporting key signatures marked as "local". This is not -generally useful unless a shared keyring scheme is being used. -Defaults to no. - -@item include-attributes -Include attribute user IDs (photo IDs) while exporting. This is -useful to export keys if they are going to be used by an OpenPGP -program that does not accept attribute user IDs. Defaults to yes. - -@item include-sensitive-revkeys -Include designated revoker information that was marked as -"sensitive". Defaults to no. - -@end table - -@item ---list-options @code{parameters} -This is a space or comma delimited string that gives options used when -listing keys and signatures (that is, ---list-keys, --list-sigs, ----list-public-keys, --list-secret-keys, and the --edit-key functions). -Options can be prepended with a `no-' to give the opposite meaning. -The options are: - -@table @asis -@item show-photos -Causes ---list-keys, --list-sigs, --list-public-keys, and ----list-secret-keys to display any photo IDs attached to the key. -Defaults to no. See also ---photo-viewer. - -@item show-policy-url -Show policy URLs in the ---list-sigs or --check-sigs listings. -Defaults to no. - -@item show-notation -Show signature notations in the ---list-sigs or --check-sigs listings. -Defaults to no. - -@item show-keyserver-url -Show any preferred keyserver URL in the ---list-sigs or --check-sigs -listings. Defaults to no. - -@item show-validity -Display the calculated validity of keys and user IDs during key -listings. Defaults to no. - -@item show-long-keyid -Display all 64 bits (16 digits) of key IDs during key listings, rather -than the more common 32 bit (8 digit) IDs. Defaults to no. - -@item show-unusable-uids -Show revoked and expired user IDs in key listings. Defaults to no. - -@item show-keyring -Display the keyring name at the head of key listings to show which -keyring a given key resides on. Defaults to no. - -@item show-sig-expire -Show signature expiration dates (if any) during ---list-sigs or ----check-sigs listings. Defaults to no. - -@end table - -@item ---verify-options @code{parameters} -This is a space or comma delimited string that gives options used when -verifying signatures. Options can be prepended with a `no-' to give -the opposite meaning. The options are: - -@table @asis -@item show-photos -Display any photo IDs present on the key that issued the signature. -Defaults to no. See also ---photo-viewer. - -@item show-policy-url -Show policy URLs in the signature being verified. Defaults to no. - -@item show-notation -Show signature notations in the signature being verified. Defaults to -no. - -@item show-keyserver-url -Show any preferred keyserver URL in the signature being verified. -Defaults to no. - -@item show-validity -Display the calculated validity of the user IDs on the key that issued -the signature. Defaults to no. - -@item show-long-keyid -Display all 64 bits (16 digits) of key IDs during signature -verification, rather than the more common 32 bit (8 digit) IDs. -Defaults to no. - -@item show-unusable-uids -Show revoked and expired user IDs during signature verification. -Defaults to no. - -@end table - -@item ---show-photos -@itemx ---no-show-photos -Causes ---list-keys, --list-sigs, --list-public-keys, ----list-secret-keys, and verifying a signature to also display the -photo ID attached to the key, if any. See also ---photo-viewer. These -options are deprecated. Use `---list-options [no-]show-photos' and/or -`---verify-options [no-]show-photos' instead. - -@item ---photo-viewer @code{string} -This is the command line that should be run to view a photo ID. "%i" -will be expanded to a filename containing the photo. "%I" does the -same, except the file will not be deleted once the viewer exits. -Other flags are "%k" for the key ID, "%K" for the long key ID, "%f" -for the key fingerprint, "%t" for the extension of the image type -(e.g. "jpg"), "%T" for the MIME type of the image (e.g. "image/jpeg"), -and "%%" for an actual percent sign. If neither %i or %I are present, -then the photo will be supplied to the viewer on standard input. - -The default viewer is "xloadimage -fork -quiet -title 'KeyID 0x%k' -stdin". Note that if your image viewer program is not secure, then -executing it from GnuPG does not make it secure. - -@item ---exec-path @code{string} -Sets a list of directories to search for photo viewers and keyserver -helpers. If not provided, keyserver helpers use the compiled-in -default directory, and photo viewers use the $PATH environment -variable. - -@item ---show-keyring -Display the keyring name at the head of key listings to show which -keyring a given key resides on. This option is deprecated: use -`---list-options [no-]show-keyring' instead. - -@item ---keyring @code{file} -Add @code{file} to the list of keyrings. If @code{file} begins with a -tilde and a slash, these are replaced by the HOME directory. If the -filename does not contain a slash, it is assumed to be in the GnuPG -home directory ("~/.gnupg" if ---homedir is not used). The filename -may be prefixed with a scheme: - -"gnupg-ring:" is the default one. - -It might make sense to use it together with ---no-default-keyring. - -@item ---secret-keyring @code{file} -Same as ---keyring but for the secret keyrings. - -@item ---primary-keyring @code{file} -Designate @code{file} as the primary public keyring. This means that -newly imported keys (via ---import or keyserver --recv-from) will go to -this keyring. - -@item ---trustdb-name @code{file} -Use @code{file} instead of the default trustdb. If @code{file} begins -with a tilde and a slash, these are replaced by the HOME directory. If -the filename does not contain a slash, it is assumed to be in the -GnuPG home directory ("~/.gnupg" if ---homedir is not used). - -@item ---homedir @code{directory} -Set the name of the home directory to @code{directory} If this -option is not used it defaults to "~/.gnupg". It does -not make sense to use this in a options file. This -also overrides the environment variable "GNUPGHOME". - -@item ---charset @code{name} -Set the name of the native character set. This is used -to convert some strings to proper UTF-8 encoding. If this option is not used, the default character set is determined -from the current locale. A verbosity level of 3 shows the used one. -Valid values for @code{name} are: - -@table @asis -@item iso-8859-1 -This is the Latin 1 set. - -@item iso-8859-2 -The Latin 2 set. - -@item iso-8859-15 -This is currently an alias for -the Latin 1 set. - -@item koi8-r -The usual Russian set (rfc1489). - -@item utf-8 -Bypass all translations and assume -that the OS uses native UTF-8 encoding. - -@end table - -@item ---utf8-strings -@itemx ---no-utf8-strings -Assume that the arguments are already given as UTF8 strings. The default -(---no-utf8-strings) -is to assume that arguments are encoded in the character set as specified -by ---charset. These options affect all following arguments. Both options may -be used multiple times. - -@item ---options @code{file} -Read options from @code{file} and do not try to read -them from the default options file in the homedir -(see ---homedir). This option is ignored if used -in an options file. - -@item ---no-options -Shortcut for "---options /dev/null". This option is -detected before an attempt to open an option file. -Using this option will also prevent the creation of a -"~./gnupg" homedir. - -@item ---load-extension @code{name} -Load an extension module. If @code{name} does not contain a slash it is -searched for in the directory configured when GnuPG was built -(generally "/usr/local/lib/gnupg"). Extensions are not generally -useful anymore, and the use of this option is deprecated. - -@item ---debug @code{flags} -Set debugging flags. All flags are or-ed and @code{flags} may -be given in C syntax (e.g. 0x0042). - -@item ---debug-all -Set all useful debugging flags. - -@item ---enable-progress-filter -Enable certain PROGRESS status outputs. This option allows frontends -to display a progress indicator while gpg is processing larger files. -There is a slight performance overhead using it. - -@item ---status-fd @code{n} -Write special status strings to the file descriptor @code{n}. -See the file DETAILS in the documentation for a listing of them. - -@item ---logger-fd @code{n} -Write log output to file descriptor @code{n} and not to stderr. - -@item ---attribute-fd @code{n} -Write attribute subpackets to the file descriptor @code{n}. This is -most useful for use with ---status-fd, since the status messages are -needed to separate out the various subpackets from the stream -delivered to the file descriptor. - -@item ---sk-comments -@itemx ---no-sk-comments -Include secret key comment packets when exporting secret keys. This -is a GnuPG extension to the OpenPGP standard, and is off by default. -Please note that this has nothing to do with the comments in clear -text signatures or armor headers. ---no-sk-comments disables this -option. - -@item ---comment @code{string} -@itemx ---no-comments -Use @code{string} as a comment string in clear text signatures and -ASCII armored messages or keys (see ---armor). The default behavior is -not to use a comment string. ---comment may be repeated multiple times -to get multiple comment strings. ---no-comments removes all comments. - -@item ---emit-version -@itemx ---no-emit-version -Force inclusion of the version string in ASCII armored output. ----no-emit-version disables this option. - -@item ---sig-notation @code{name=value} -@itemx ---cert-notation @code{name=value} -@itemx -N, ---set-notation @code{name=value} -Put the name value pair into the signature as notation data. -@code{name} must consist only of printable characters or spaces, and -must contain a '@@' character. This is to help prevent pollution of -the IETF reserved notation namespace. The ---expert flag overrides the -'@@' check. @code{value} may be any printable string; it will be -encoded in UTF8, so you should check that your ---charset is set -correctly. If you prefix @code{name} with an exclamation mark, the -notation data will be flagged as critical (rfc2440:5.2.3.15). ----sig-notation sets a notation for data signatures. --cert-notation -sets a notation for key signatures (certifications). ---set-notation -sets both. - -There are special codes that may be used in notation names. "%k" will -be expanded into the key ID of the key being signed, "%K" into the -long key ID of the key being signed, "%f" into the fingerprint of the -key being signed, "%s" into the key ID of the key making the -signature, "%S" into the long key ID of the key making the signature, -"%g" into the fingerprint of the key making the signature (which might -be a subkey), "%p" into the fingerprint of the primary key of the key -making the signature, and "%%" results in a single "%". %k, %K, and -%f are only meaningful when making a key signature (certification). - -@item ---show-notation -@itemx ---no-show-notation -Show signature notations in the ---list-sigs or --check-sigs listings -as well as when verifying a signature with a notation in it. These -options are deprecated. Use `---list-options [no-]show-notation' -and/or `---verify-options [no-]show-notation' instead. - -@item ---sig-policy-url @code{string} -@itemx ---cert-policy-url @code{string} -@itemx ---set-policy-url @code{string} -Use @code{string} as a Policy URL for signatures (rfc2440:5.2.3.19). -If you prefix it with an exclamation mark, the policy URL packet will -be flagged as critical. ---sig-policy-url sets a a policy url for data -signatures. ---cert-policy-url sets a policy url for key signatures -(certifications). ---set-policy-url sets both. - -The same %-expandos used for notation data are available here as well. - -@item ---show-policy-url -@itemx ---no-show-policy-url -Show policy URLs in the ---list-sigs or --check-sigs listings as well -as when verifying a signature with a policy URL in it. These options -are deprecated. Use `---list-options [no-]show-policy-url' and/or -`---verify-options [no-]show-policy-url' instead. - -@item ---sig-keyserver-url @code{string} -Use @code{string} as a preferred keyserver URL for data signatures. If -you prefix it with an exclamation mark, the keyserver URL packet will -be flagged as critical. - -The same %-expandos used for notation data are available here as well. - -@item ---set-filename @code{string} -Use @code{string} as the filename which is stored inside messages. -This overrides the default, which is to use the actual filename of the -file being encrypted. - -@item ---for-your-eyes-only -@itemx ---no-for-your-eyes-only -Set the `for your eyes only' flag in the message. This causes GnuPG -to refuse to save the file unless the ---output option is given, and -PGP to use the "secure viewer" with a Tempest-resistant font to -display the message. This option overrides ---set-filename. ----no-for-your-eyes-only disables this option. - -@item ---use-embedded-filename -Try to create a file with a name as embedded in the data. -This can be a dangerous option as it allows to overwrite files. - -@item ---completes-needed @code{n} -Number of completely trusted users to introduce a new -key signer (defaults to 1). - -@item ---marginals-needed @code{n} -Number of marginally trusted users to introduce a new -key signer (defaults to 3) - -@item ---max-cert-depth @code{n} -Maximum depth of a certification chain (default is 5). - -@item ---cipher-algo @code{name} -Use @code{name} as cipher algorithm. Running the program -with the command ---version yields a list of supported -algorithms. If this is not used the cipher algorithm is -selected from the preferences stored with the key. - -@item ---digest-algo @code{name} -Use @code{name} as the message digest algorithm. Running the program -with the command ---version yields a list of supported algorithms. - -@item ---compress-algo @code{name} -Use compression algorithm @code{name}. "zlib" is RFC1950 ZLIB -compression. "zip" is RFC-1951 ZIP compression which is used by PGP. -"uncompressed" or "none" disables compression. If this option is not -used, the default behavior is to examine the recipient key preferences -to see which algorithms the recipient supports. If all else fails, -ZIP is used for maximum compatibility. Note, however, that ZLIB may -give better compression results if that is more important, as the -compression window size is not limited to 8k. - -@item ---cert-digest-algo @code{name} -Use @code{name} as the message digest algorithm used when signing a -key. Running the program with the command ---version yields a list of -supported algorithms. Be aware that if you choose an algorithm that -GnuPG supports but other OpenPGP implementations do not, then some -users will not be able to use the key signatures you make, or quite -possibly your entire key. - -@item ---s2k-cipher-algo @code{name} -Use @code{name} as the cipher algorithm used to protect secret keys. -The default cipher is CAST5. This cipher is also used for -conventional encryption if ---personal-cipher-preferences and ----cipher-algo is not given. - -@item ---s2k-digest-algo @code{name} -Use @code{name} as the digest algorithm used to mangle the passphrases. -The default algorithm is SHA-1. - -@item ---s2k-mode @code{n} -Selects how passphrases are mangled. If @code{n} is 0 a plain -passphrase (which is not recommended) will be used, a 1 adds a salt to -the passphrase and a 3 (the default) iterates the whole process a -couple of times. Unless ---rfc1991 is used, this mode is also used for -conventional encryption. - -@item ---simple-sk-checksum -Secret keys are integrity protected by using a SHA-1 checksum. This -method will be part of an enhanced OpenPGP specification but GnuPG -already uses it as a countermeasure against certain attacks. Old -applications don't understand this new format, so this option may be -used to switch back to the old behaviour. Using this this option -bears a security risk. Note that using this option only takes effect -when the secret key is encrypted - the simplest way to make this -happen is to change the passphrase on the key (even changing it to the -same value is acceptable). - -@item ---disable-cipher-algo @code{name} -Never allow the use of @code{name} as cipher algorithm. -The given name will not be checked so that a later loaded algorithm -will still get disabled. - -@item ---disable-pubkey-algo @code{name} -Never allow the use of @code{name} as public key algorithm. -The given name will not be checked so that a later loaded algorithm -will still get disabled. - -@item ---no-sig-cache -Do not cache the verification status of key signatures. -Caching gives a much better performance in key listings. However, if -you suspect that your public keyring is not save against write -modifications, you can use this option to disable the caching. It -probably does not make sense to disable it because all kind of damage -can be done if someone else has write access to your public keyring. - -@item ---no-sig-create-check -GnuPG normally verifies each signature right after creation to protect -against bugs and hardware malfunctions which could leak out bits from -the secret key. This extra verification needs some time (about 115% -for DSA keys), and so this option can be used to disable it. -However, due to the fact that the signature creation needs manual -interaction, this performance penalty does not matter in most settings. - -@item ---auto-check-trustdb -@itemx ---no-auto-check-trustdb -If GnuPG feels that its information about the Web-of-Trust has to be -updated, it automatically runs the ---check-trustdb command internally. -This may be a time consuming process. ---no-auto-check-trustdb -disables this option. - -@item ---throw-keyid -Do not put the keyids into encrypted packets. This option hides the -receiver of the message and is a countermeasure against traffic -analysis. It may slow down the decryption process because all -available secret keys are tried. - -@item ---no-throw-keyid -Resets the ---throw-keyid option. - -@item ---not-dash-escaped -This option changes the behavior of cleartext signatures -so that they can be used for patch files. You should not -send such an armored file via email because all spaces -and line endings are hashed too. You can not use this -option for data which has 5 dashes at the beginning of a -line, patch files don't have this. A special armor header -line tells GnuPG about this cleartext signature option. - -@item ---escape-from-lines -@itemx ---no-escape-from-lines -Because some mailers change lines starting with "From " to ">From -" it is good to handle such lines in a special way when creating -cleartext signatures to prevent the mail system from breaking the -signature. Note that all other PGP versions do it this way too. -Enabled by default. ---no-escape-from-lines disables this option. - -@item ---passphrase-fd @code{n} -Read the passphrase from file descriptor @code{n}. If you use -0 for @code{n}, the passphrase will be read from stdin. This -can only be used if only one passphrase is supplied. -Don't use this option if you can avoid it. - -@item ---command-fd @code{n} -This is a replacement for the deprecated shared-memory IPC mode. -If this option is enabled, user input on questions is not expected -from the TTY but from the given file descriptor. It should be used -together with ---status-fd. See the file doc/DETAILS in the source -distribution for details on how to use it. - -@item ---use-agent -@itemx ---no-use-agent -Try to use the GnuPG-Agent. Please note that this agent is still under -development. With this option, GnuPG first tries to connect to the -agent before it asks for a passphrase. ---no-use-agent disables this -option. - -@item ---gpg-agent-info -Override the value of the environment variable -@samp{GPG_AGENT_INFO}. This is only used when ---use-agent has been given - -@item Compliance options -These options control what GnuPG is compliant to. Only one of these -options may be active at a time. Note that the default setting of -this is nearly always the correct one. See the INTEROPERABILITY WITH -OTHER OPENPGP PROGRAMS section below before using one of these -options. - -@table @asis -@item ---gnupg -Use standard GnuPG behavior. This is essentially OpenPGP behavior -(see ---openpgp), but with some additional workarounds for common -compatibility problems in different versions of PGP. This is the -default option, so it is not generally needed, but it may be useful to -override a different compliance option in the gpg.conf file. - -@item ---openpgp -Reset all packet, cipher and digest options to strict OpenPGP -behavior. Use this option to reset all previous options like ----rfc1991, --force-v3-sigs, --s2k-*, --cipher-algo, --digest-algo and ----compress-algo to OpenPGP compliant values. All PGP workarounds are -disabled. - -@item ---rfc2440 -Reset all packet, cipher and digest options to strict RFC-2440 -behavior. Note that this is currently the same thing as ---openpgp. - -@item ---rfc1991 -Try to be more RFC-1991 (PGP 2.x) compliant. - -@item ---pgp2 -Set up all options to be as PGP 2.x compliant as possible, and warn if -an action is taken (e.g. encrypting to a non-RSA key) that will create -a message that PGP 2.x will not be able to handle. Note that `PGP -2.x' here means `MIT PGP 2.6.2'. There are other versions of PGP 2.x -available, but the MIT release is a good common baseline. - -This option implies `---rfc1991 --disable-mdc --no-force-v4-certs ----no-sk-comment --escape-from-lines --force-v3-sigs ----no-ask-sig-expire --no-ask-cert-expire --cipher-algo IDEA ----digest-algo MD5 --compress-algo 1'. It also disables --textmode -when encrypting. - -@item ---pgp6 -Set up all options to be as PGP 6 compliant as possible. This -restricts you to the ciphers IDEA (if the IDEA plugin is installed), -3DES, and CAST5, the hashes MD5, SHA1 and RIPEMD160, and the -compression algorithms none and ZIP. This also disables ----throw-keyid, and making signatures with signing subkeys as PGP 6 -does not understand signatures made by signing subkeys. - -This option implies `---disable-mdc --no-sk-comment --escape-from-lines ----force-v3-sigs --no-ask-sig-expire' - -@item ---pgp7 -Set up all options to be as PGP 7 compliant as possible. This is -identical to ---pgp6 except that MDCs are not disabled, and the list of -allowable ciphers is expanded to add AES128, AES192, AES256, and -TWOFISH. - -@item ---pgp8 -Set up all options to be as PGP 8 compliant as possible. PGP 8 is a -lot closer to the OpenPGP standard than previous versions of PGP, so -all this does is disable ---throw-keyid and set --escape-from-lines. -The allowed algorithms list is the same as ---pgp7 with the addition of -the SHA-256 digest algorithm. - -@end table - -@item ---force-v3-sigs -@itemx ---no-force-v3-sigs -OpenPGP states that an implementation should generate v4 signatures -but PGP versions 5 and higher only recognize v4 signatures on key -material. This option forces v3 signatures for signatures on data. -Note that this option overrides ---ask-sig-expire, as v3 signatures -cannot have expiration dates. ---no-force-v3-sigs disables this -option. - -@item ---force-v4-certs -@itemx ---no-force-v4-certs -Always use v4 key signatures even on v3 keys. This option also -changes the default hash algorithm for v3 RSA keys from MD5 to SHA-1. ----no-force-v4-certs disables this option. - -@item ---force-mdc -Force the use of encryption with a modification detection code. This -is always used with the newer ciphers (those with a blocksize greater -than 64 bits), or if all of the recipient keys indicate MDC support in -their feature flags. - -@item ---disable-mdc -Disable the use of the modification detection code. Note that by -using this option, the encrypted message becomes vulnerable to a -message modification attack. - -@item ---allow-non-selfsigned-uid -@itemx ---no-allow-non-selfsigned-uid -Allow the import and use of keys with user IDs which are not -self-signed. This is not recommended, as a non self-signed user ID is -trivial to forge. ---no-allow-non-selfsigned-uid disables. - -@item ---allow-freeform-uid -Disable all checks on the form of the user ID while generating a new -one. This option should only be used in very special environments as -it does not ensure the de-facto standard format of user IDs. - -@item ---ignore-time-conflict -GnuPG normally checks that the timestamps associated with keys and -signatures have plausible values. However, sometimes a signature -seems to be older than the key due to clock problems. This option -makes these checks just a warning. See also ---ignore-valid-from for -timestamp issues on subkeys. - -@item ---ignore-valid-from -GnuPG normally does not select and use subkeys created in the future. -This option allows the use of such keys and thus exhibits the -pre-1.0.7 behaviour. You should not use this option unless you there -is some clock problem. See also ---ignore-time-conflict for timestamp -issues with signatures. - -@item ---ignore-crc-error -The ASCII armor used by OpenPGP is protected by a CRC checksum against -transmission errors. Sometimes it happens that the CRC gets mangled -somewhere on the transmission channel but the actual content (which is -protected by the OpenPGP protocol anyway) is still okay. This option -will let gpg ignore CRC errors. - -@item ---ignore-mdc-error -This option changes a MDC integrity protection failure into a warning. -This can be useful if a message is partially corrupt, but it is -necessary to get as much data as possible out of the corrupt message. -However, be aware that a MDC protection failure may also mean that the -message was tampered with intentionally by an attacker. - -@item ---lock-once -Lock the databases the first time a lock is requested -and do not release the lock until the process -terminates. - -@item ---lock-multiple -Release the locks every time a lock is no longer -needed. Use this to override a previous ---lock-once -from a config file. - -@item ---lock-never -Disable locking entirely. This option should be used only in very -special environments, where it can be assured that only one process -is accessing those files. A bootable floppy with a stand-alone -encryption system will probably use this. Improper usage of this -option may lead to data and key corruption. - -@item ---no-random-seed-file -GnuPG uses a file to store its internal random pool over invocations. -This makes random generation faster; however sometimes write operations -are not desired. This option can be used to achieve that with the cost of -slower random generation. - -@item ---no-verbose -Reset verbose level to 0. - -@item ---no-greeting -Suppress the initial copyright message. - -@item ---no-secmem-warning -Suppress the warning about "using insecure memory". - -@item ---no-permission-warning -Suppress the warning about unsafe file and home directory (---homedir) -permissions. Note that the permission checks that GnuPG performs are -not intended to be authoritative, but rather they simply warn about -certain common permission problems. Do not assume that the lack of a -warning means that your system is secure. - -Note that the warning for unsafe ---homedir permissions cannot be -supressed in the gpg.conf file, as this would allow an attacker to -place an unsafe gpg.conf file in place, and use this file to supress -warnings about itself. The ---homedir permissions warning may only be -supressed on the command line. - -@item ---no-mdc-warning -Suppress the warning about missing MDC integrity protection. - -@item ---no-armor -Assume the input data is not in ASCII armored format. - -@item ---no-default-keyring -Do not add the default keyrings to the list of -keyrings. - -@item ---skip-verify -Skip the signature verification step. This may be -used to make the decryption faster if the signature -verification is not needed. - -@item ---with-colons -Print key listings delimited by colons. Note that the output will be -encoded in UTF-8 regardless of any ---charset setting. This format is -useful when GnuPG is called from scripts and other programs as it is -easily machine parsed. The details of this format are documented in -the file doc/DETAILS, which is included in the GnuPG source -distribution. - -@item ---with-key-data -Print key listings delimited by colons (like ---with-colons) and print the public key data. - -@item ---with-fingerprint -Same as the command ---fingerprint but changes only the format of the output -and may be used together with another command. - -@item ---fast-list-mode -Changes the output of the list commands to work faster; this is achieved -by leaving some parts empty. Some applications don't need the user ID and -the trust information given in the listings. By using this options they -can get a faster listing. The exact behaviour of this option may change -in future versions. - -@item ---fixed-list-mode -Do not merge primary user ID and primary key in ---with-colon listing -mode and print all timestamps as seconds since 1970-01-01. - -@item ---list-only -Changes the behaviour of some commands. This is like ---dry-run but -different in some cases. The semantic of this command may be extended in -the future. Currently it only skips the actual decryption pass and -therefore enables a fast listing of the encryption keys. - -@item ---no-literal -This is not for normal use. Use the source to see for what it might be useful. - -@item ---set-filesize -This is not for normal use. Use the source to see for what it might be useful. - -@item ---emulate-md-encode-bug -GnuPG versions prior to 1.0.2 had a bug in the way a signature was encoded. -This options enables a workaround by checking faulty signatures again with -the encoding used in old versions. This may only happen for ElGamal signatures -which are not widely used. - -@item ---show-session-key -Display the session key used for one message. See ---override-session-key -for the counterpart of this option. - -We think that Key-Escrow is a Bad Thing; however the user should -have the freedom to decide whether to go to prison or to reveal the content of -one specific message without compromising all messages ever encrypted for one -secret key. DON'T USE IT UNLESS YOU ARE REALLY FORCED TO DO SO. - -@item ---override-session-key @code{string} -Don't use the public key but the session key @code{string}. The format of this -string is the same as the one printed by ---show-session-key. This option -is normally not used but comes handy in case someone forces you to reveal the -content of an encrypted message; using this option you can do this without -handing out the secret key. - -@item ---ask-sig-expire -@itemx ---no-ask-sig-expire -When making a data signature, prompt for an expiration time. If this -option is not specified, the expiration time is "never". ----no-ask-sig-expire disables this option. - -@item ---ask-cert-expire -@itemx ---no-ask-cert-expire -When making a key signature, prompt for an expiration time. If this -option is not specified, the expiration time is "never". ----no-ask-cert-expire disables this option. - -@item ---expert -@itemx ---no-expert -Allow the user to do certain nonsensical or "silly" things like -signing an expired or revoked key, or certain potentially incompatible -things like generating deprecated key types. This also disables -certain warning messages about potentially incompatible actions. As -the name implies, this option is for experts only. If you don't fully -understand the implications of what it allows you to do, leave this -off. ---no-expert disables this option. - -@item ---merge-only -Don't insert new keys into the keyrings while doing an import. - -@item ---allow-secret-key-import -This is an obsolete option and is not used anywhere. - -@item ---try-all-secrets -Don't look at the key ID as stored in the message but try all secret keys in -turn to find the right decryption key. This option forces the behaviour as -used by anonymous recipients (created by using ---throw-keyid) and might come -handy in case where an encrypted message contains a bogus key ID. - -@item ---enable-special-filenames -This options enables a mode in which filenames of the form -@file{-&n}, where n is a non-negative decimal number, -refer to the file descriptor n and not to a file with that name. - -@item ---no-expensive-trust-checks -Experimental use only. - -@item ---group @code{name=value1 value2 value3 ...} -Sets up a named group, which is similar to aliases in email programs. -Any time the group name is a recipient (-r or ---recipient), it will -be expanded to the values specified. - -The values are @code{key IDs} or fingerprints, but any key description -is accepted. Note that a value with spaces in it will be treated as -two different values. Note also there is only one level of expansion -- you cannot make an group that points to another group. When used -from the command line, it may be necessary to quote the argument to -this option to prevent the shell from treating it as multiple -arguments. - -@item ---no-groups -Clear the ---group list. - -@item ---preserve-permissions -Don't change the permissions of a secret keyring back to user -read/write only. Use this option only if you really know what you are doing. - -@item ---personal-cipher-preferences @code{string} -Set the list of personal cipher preferences to @code{string}, this list -should be a string similar to the one printed by the command "pref" in -the edit menu. This allows the user to factor in their own preferred -algorithms when algorithms are chosen via recipient key preferences. -The most highly ranked cipher in this list is also used for the ----symmetric encryption command. - -@item ---personal-digest-preferences @code{string} -Set the list of personal digest preferences to @code{string}, this list -should be a string similar to the one printed by the command "pref" in -the edit menu. This allows the user to factor in their own preferred -algorithms when algorithms are chosen via recipient key preferences. -The most highly ranked digest algorithm in this list is algo used when -signing without encryption (e.g. ---clearsign or --sign). The default -value is SHA-1. - -@item ---personal-compress-preferences @code{string} -Set the list of personal compression preferences to @code{string}, this -list should be a string similar to the one printed by the command -"pref" in the edit menu. This allows the user to factor in their own -preferred algorithms when algorithms are chosen via recipient key -preferences. The most highly ranked algorithm in this list is also -used when there are no recipient keys to consider (e.g. ---symmetric). - -@item ---default-preference-list @code{string} -Set the list of default preferences to @code{string}, this list should -be a string similar to the one printed by the command "pref" in the -edit menu. This affects both key generation and "updpref" in the edit -menu. - -@end table - -@majorheading How to specify a user ID -There are different ways to specify a user ID to GnuPG; here are some -examples: - -@table @asis -@item -@item 234567C4 -@itemx 0F34E556E -@itemx 01347A56A -@itemx 0xAB123456 -Here the key ID is given in the usual short form. - -@item 234AABBCC34567C4 -@itemx 0F323456784E56EAB -@itemx 01AB3FED1347A5612 -@itemx 0x234AABBCC34567C4 -Here the key ID is given in the long form as used by OpenPGP -(you can get the long key ID using the option ---with-colons). - -@item 1234343434343434C434343434343434 -@itemx 123434343434343C3434343434343734349A3434 -@itemx 0E12343434343434343434EAB3484343434343434 -@itemx 0xE12343434343434343434EAB3484343434343434 -The best way to specify a key ID is by using the fingerprint of -the key. This avoids any ambiguities in case that there are duplicated -key IDs (which are really rare for the long key IDs). - -@item =Heinrich Heine <heinrichh@@uni-duesseldorf.de> -Using an exact to match string. The equal sign indicates this. - -@item <heinrichh@@uni-duesseldorf.de> -Using the email address part which must match exactly. The left angle bracket -indicates this email address mode. - -@item +Heinrich Heine duesseldorf -All words must match exactly (not case sensitive) but can appear in -any order in the user ID. Words are any sequences of letters, -digits, the underscore and all characters with bit 7 set. - -@item Heine -@itemx *Heine -By case insensitive substring matching. This is the default mode but -applications may want to explicitly indicate this by putting the asterisk -in front. - -@end table - -Note that you can append an exclamation mark to key IDs or -fingerprints. This flag tells GnuPG to use exactly the given primary -or secondary key and not to try to figure out which secondary or -primary key to use. - -@majorheading RETURN VALUE -The program returns 0 if everything was fine, 1 if at least -a signature was bad, and other error codes for fatal errors. - -@majorheading EXAMPLES -@table @asis -@item gpg -se -r @code{Bob} @code{file} -sign and encrypt for user Bob - -@item gpg ---clearsign @code{file} -make a clear text signature - -@item gpg -sb @code{file} -make a detached signature - -@item gpg ---list-keys @code{user_ID} -show keys - -@item gpg ---fingerprint @code{user_ID} -show fingerprint - -@item gpg ---verify @code{pgpfile} -@itemx gpg ---verify @code{sigfile} @code{files} -Verify the signature of the file but do not output the data. The second form -is used for detached signatures, where @code{sigfile} is the detached -signature (either ASCII armored of binary) and @code{files} are the signed -data; if this is not given the name of the file holding the signed data is -constructed by cutting off the extension (".asc" or ".sig") of -@code{sigfile} or by asking the user for the filename. - -@end table - -@majorheading ENVIRONMENT -@table @asis -@item HOME -Used to locate the default home directory. - -@item GNUPGHOME -If set directory used instead of "~/.gnupg". - -@item GPG_AGENT_INFO -Used to locate the gpg-agent; only honored when ----use-agent is set. The value consists of 3 colon delimited fields: -The first is the path to the Unix Domain Socket, the second the PID of -the gpg-agent and the protocol version which should be set to 1. When -starting the gpg-agent as described in its documentation, this -variable is set to the correct value. The option ---gpg-agent-info can -be used to override it. - -@item http_proxy -Only honored when the keyserver-option -honor-http-proxy is set. - -@end table - -@majorheading FILES -@table @asis -@item ~/.gnupg/secring.gpg -The secret keyring - -@item ~/.gnupg/secring.gpg.lock -and the lock file - -@item ~/.gnupg/pubring.gpg -The public keyring - -@item ~/.gnupg/pubring.gpg.lock -and the lock file - -@item ~/.gnupg/trustdb.gpg -The trust database - -@item ~/.gnupg/trustdb.gpg.lock -and the lock file - -@item ~/.gnupg/random_seed -used to preserve the internal random pool - -@item ~/.gnupg/gpg.conf -Default configuration file - -@item ~/.gnupg/options -Old style configuration file; only used when gpg.conf -is not found - -@item /usr[/local]/share/gnupg/options.skel -Skeleton options file - -@item /usr[/local]/lib/gnupg/ -Default location for extensions - -@end table - -@majorheading WARNINGS -Use a *good* password for your user account and a *good* passphrase -to protect your secret key. This passphrase is the weakest part of the -whole system. Programs to do dictionary attacks on your secret keyring -are very easy to write and so you should protect your "~/.gnupg/" -directory very well. - -Keep in mind that, if this program is used over a network (telnet), it -is *very* easy to spy out your passphrase! - -If you are going to verify detached signatures, make sure that the -program knows about it; either be giving both filenames on the -command line or using @samp{-} to specify stdin. - -@majorheading INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS -GnuPG tries to be a very flexible implementation of the OpenPGP -standard. In particular, GnuPG implements many of the "optional" -parts of the standard, such as the RIPEMD/160 hash, and the ZLIB -compression algorithms. It is important to be aware that not all -OpenPGP programs implement these optional algorithms and that by -forcing their use via the ---cipher-algo, --digest-algo, ----cert-digest-algo, or --compress-algo options in GnuPG, it is -possible to create a perfectly valid OpenPGP message, but one that -cannot be read by the intended recipient. - -For example, as of this writing, no version of official PGP supports -the BLOWFISH cipher algorithm. If you use it, no PGP user will be -able to decrypt your message. The same thing applies to the ZLIB -compression algorithm. By default, GnuPG uses the OpenPGP preferences -system that will always do the right thing and create messages that -are usable by all recipients, regardless of which OpenPGP program they -use. Only override this safe default if you know what you are doing. - -If you absolutely must override the safe default, or if the -preferences on a given key are invalid for some reason, you are far -better off using the ---pgp2, --pgp6, --pgp7, or --pgp8 options. These -options are safe as they do not force any particular algorithms in -violation of OpenPGP, but rather reduce the available algorithms to a -"PGP-safe" list. - -@majorheading BUGS -On many systems this program should be installed as setuid(root). This -is necessary to lock memory pages. Locking memory pages prevents the -operating system from writing memory pages to disk. If you get no -warning message about insecure memory your operating system supports -locking without being root. The program drops root privileges as soon -as locked memory is allocated. - -@bye +@c man end -- cgit v1.2.3 From f67c66e56f15b83ee8539ef2de563750c6908d9f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 30 Sep 2004 13:24:33 +0000 Subject: * de.po: Updated. * POTFILES.in: Add more files. * app-openpgp.c (do_sign): Add the error string to the verify failed messages. * keylist.c (list_cert_colon): Make sure that the expired flag has a higher precedence than the invalid flag. --- po/ChangeLog | 6 ++ po/POTFILES.in | 2 + po/de.po | 125 ++++++++++++++++++++++--- scd/ChangeLog | 71 ++++++++++++++ scd/app-openpgp.c | 276 ++++++++++++++++++++++++++++++++++++++---------------- sm/ChangeLog | 5 + sm/keylist.c | 7 +- 7 files changed, 396 insertions(+), 96 deletions(-) diff --git a/po/ChangeLog b/po/ChangeLog index c1bcd81e1..25d7d4595 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,9 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * de.po: Updated. + + * POTFILES.in: Add more files. + 2004-07-22 Werner Koch <wk@g10code.de> * de.po: Updated. diff --git a/po/POTFILES.in b/po/POTFILES.in index ae54716ac..eb4e36c85 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -15,6 +15,8 @@ jnlib/logging.c kbx/kbxutil.c scd/scdaemon.c +scd/sc-investigate.c +scd/app-openpgp.c sm/base64.c sm/call-agent.c diff --git a/po/de.po b/po/de.po index a09f0024d..3c4d90a44 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-09-29 18:01+0200\n" -"PO-Revision-Date: 2004-09-29 18:10+0200\n" +"POT-Creation-Date: 2004-09-30 15:22+0200\n" +"PO-Revision-Date: 2004-09-30 15:23+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -100,12 +100,12 @@ msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:485 tools/gpgconf.c:85 +#: scd/sc-investigate.c:113 sm/gpgsm.c:485 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:485 tools/gpgconf.c:85 +#: scd/sc-investigate.c:113 sm/gpgsm.c:485 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -127,7 +127,7 @@ msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:446 agent/protect-tool.c:1050 kbx/kbxutil.c:436 -#: scd/scdaemon.c:357 sm/gpgsm.c:731 +#: scd/scdaemon.c:357 scd/sc-investigate.c:181 sm/gpgsm.c:731 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" @@ -432,6 +432,103 @@ msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" +#: scd/sc-investigate.c:116 +msgid "Usage: sc-investigate [options] (-h for help)\n" +msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" + +#: scd/sc-investigate.c:118 +msgid "" +"Syntax: sc-investigate [options] [args]]\n" +"Have a look at smartcards\n" +msgstr "" +"Gebrauch: sc-investigate [Optionen] [Argumente]\n" +"Den Inhalt einer Smartcard inspizieren\n" + +#: scd/app-openpgp.c:458 +#, c-format +msgid "failed to store the fingerprint: %s\n" +msgstr "Der Fingerprint kann nicht gespeichert werden: %s\n" + +#: scd/app-openpgp.c:471 +#, c-format +msgid "failed to store the creation date: %s\n" +msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" + +#: scd/app-openpgp.c:656 scd/app-openpgp.c:745 +#, c-format +msgid "PIN callback returned error: %s\n" +msgstr "Fehler vom PIN \"callback\": %s\n" + +#: scd/app-openpgp.c:662 scd/app-openpgp.c:751 scd/app-openpgp.c:1236 +#, c-format +msgid "prassphrase (CHV%d) is too short; minimum length is %d\n" +msgstr "Die Passphrase (CHV%d) ist zu kurz; Mindestlnge ist %d\n" + +#: scd/app-openpgp.c:671 scd/app-openpgp.c:685 scd/app-openpgp.c:761 +#: scd/app-openpgp.c:1245 scd/app-openpgp.c:1259 +#, c-format +msgid "verify CHV%d failed: %s\n" +msgstr "Prfen von CHV%d fehlgeschlagen: %s\n" + +#: scd/app-openpgp.c:708 +msgid "access to admin commands is not configured\n" +msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" + +#: scd/app-openpgp.c:725 +msgid "error retrieving CHV status from card\n" +msgstr "Fehler beim Holen des CHV Status von der Karte\n" + +#: scd/app-openpgp.c:731 +msgid "card is permanently locked!\n" +msgstr "Die Karte ist dauerhaft gesperrt!\n" + +#: scd/app-openpgp.c:738 +#, c-format +msgid "%d Admin PIN attempts remaining before card is permanently locked\n" +msgstr "" +"Noch %d Admin PIN Versuche mglich bevor die Karte dauerhaft gesperrt wird\n" + +#: scd/app-openpgp.c:742 +msgid "Admin PIN" +msgstr "Admin PIN" + +#: scd/app-openpgp.c:1504 +msgid "can't access CHV Status Bytes - invalid OpenPGP card?\n" +msgstr "" +"Zugriff auf die CHV Status Bytes nicht mglich - ungltige OpenPGP Karte?\n" + +#: scd/app-openpgp.c:1514 +msgid "can't access Extended Capability Flags - invalid OpenPGP card?\n" +msgstr "" +"Zugriff auf die Extended Capability Flags nicht mglich - ungltige OpenPGP " +"Karte?\n" + +#: scd/app-openpgp.c:1584 +#, c-format +msgid "error getting serial number: %s\n" +msgstr "Fehler beim Holen der Seriennummer: %s\n" + +#: scd/app-openpgp.c:1679 +#, c-format +msgid "failed to store the key: %s\n" +msgstr "Fehler beim Speichern des Schlssels: %s\n" + +#: scd/app-openpgp.c:1721 +msgid "reading the key failed\n" +msgstr "Fehler beim Lesen des Schlssels: %s\n" + +#: scd/app-openpgp.c:1728 +msgid "response does not contain the public key data\n" +msgstr "Die Antwort enthlt keine Public Key Daten\n" + +#: scd/app-openpgp.c:1736 +msgid "response does not contain the RSA modulus\n" +msgstr "Die Antwort enthlt keinen RSA Modulus\n" + +#: scd/app-openpgp.c:1747 +msgid "response does not contain the RSA public exponent\n" +msgstr "Die Antwort enthlt keinen ffenlichen RSA Exponent\n" + #: sm/base64.c:315 #, c-format msgid "invalid radix64 character %02x skipped\n" @@ -488,7 +585,7 @@ msgstr "[Fehler - Ung msgid "[Error - invalid DN]" msgstr "[Fehler - Ungltiger DN]" -#: sm/certdump.c:652 +#: sm/certdump.c:655 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -496,7 +593,7 @@ msgid "" "S/N %s, ID %08lX, created %s" msgstr "" "Bitte geben Sie die Passphrase an, um den \n" -"geheimen Schlssels von\n" +"geheimen Schlssel von\n" "\"%s\"\n" "S/N %s, ID %08lX, erzeugt %s\n" "zu entsperren" @@ -999,32 +1096,32 @@ msgstr "Verschl msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1182 +#: sm/gpgsm.c:1183 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1194 +#: sm/gpgsm.c:1195 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1220 +#: sm/gpgsm.c:1221 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1228 +#: sm/gpgsm.c:1229 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1258 +#: sm/gpgsm.c:1259 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1422 +#: sm/gpgsm.c:1423 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1645 sm/gpgsm.c:1678 +#: sm/gpgsm.c:1646 sm/gpgsm.c:1679 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" diff --git a/scd/ChangeLog b/scd/ChangeLog index e6789fcb2..9640ef6b2 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,74 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_sign): Add the error string to the verify + failed messages. + +2004-09-27 Werner Koch <wk@g10code.com> + + From gnupg 1.3 + + * app-openpgp.c: Made all strings translatable. + (verify_chv3) [GNUPG_MAJOR_VERSION]: Make opt.allow_admin + available for use in gnupg 2. + (verify_chv3): Reimplemented countdown showing to use only + functions from this module. Flush the CVH status cache on a + successful read. + (get_one_do): Hack to bypass the cache for cards versions > 1.0. + (store_fpr): Store the creation date for card version > 1.0. + + * app-openpgp.c (app_openpgp_storekey): Call flush_cache. + (get_cached_data): Move local data initialization to .. + (app_select_openpgp): .. here. Read some flags for later use. + (do_getattr): New read-only attribute EXTCAP. + + * apdu.c (open_pcsc_reader): Do not print empty reader string. + + * ccid-driver.c (do_close_reader): Factored some code out from ... + (ccid_close_reader): ..here. + (ccid_shutdown_reader): New. + + * apdu.c (apdu_shutdown_reader): New. + (shutdown_ccid_reader): New. + + * apdu.c (open_ccid_reader): New arg PORTSTR. Pass it to + ccid_open_reader. + (apdu_open_reader): Pass portstr to open_ccid_reader. + (apdu_open_reader): No fallback if a full CCID reader id has been + given. + + * ccid-driver.c (ccid_get_reader_list): New. + (ccid_open_reader): Changed API to take a string for the reader. + Removed al the cruft for the libusb development vesion which seems + not to be maintained anymore and there are no packages anyway. + The stable library works just fine. + (struct ccid_reader_id_s): Deleted and replaced everywhere by a + simple string. + (usb_get_string_simple): Removed. + (bulk_in): Do valgrind hack here and not just everywhere. + + * ccid-driver.c (read_device_info): Removed. + (make_reader_id, scan_or_find_devices): New. + (ccid_open_reader): Simplified by make use of the new functions. + (ccid_set_debug_level): New. Changed the macros to make use of + it. It has turned out that it is often useful to enable debugging + at runtime so I added this option. + + From gnupg 1.3 - David Shaw <dshaw@jabberwocky.com> + + * app-openpgp.c (verify_chv3): Show a countdown of how many wrong + admin PINs can be entered before the card is locked. + + * app-openpgp.c (get_cached_data): Avoid mallocing zero since it + breaks us when using --enable-m-guard. + + * ccid-driver.c (usb_get_string_simple): Replacement function to + work with older libusb. + + * ccid-driver.c (read_device_info): Fix segfault when usb device + is not accessible. + (ccid_open_reader): Allow working with an even older version of + libusb (usb_busses global instead of usb_get_busses()). + 2004-09-11 Werner Koch <wk@g10code.com> * app-openpgp.c (app_select_openpgp): Its app_munge_serialno and diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 1617ab888..6f9837c90 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -34,12 +34,12 @@ #include "errors.h" #include "memory.h" #include "util.h" -#include "i18n.h" #include "cardglue.h" #else /* GNUPG_MAJOR_VERSION != 1 */ #include "scdaemon.h" #endif /* GNUPG_MAJOR_VERSION != 1 */ +#include "i18n.h" #include "iso7816.h" #include "app-common.h" #include "tlv.h" @@ -52,27 +52,33 @@ static struct { int binary; int dont_cache; int flush_on_error; + int get_immediate_in_v11; /* Enable a hack to bypass the cache of + this data object if it is used in 1.1 + and later versions of the card. This + does not work with composite DO and is + currently only useful for the CHV + status bytes. */ char *desc; } data_objects[] = { - { 0x005E, 0, 0, 1, 0, 0, "Login Data" }, - { 0x5F50, 0, 0, 0, 0, 0, "URL" }, - { 0x0065, 1, 0, 1, 0, 0, "Cardholder Related Data"}, - { 0x005B, 0, 0x65, 0, 0, 0, "Name" }, - { 0x5F2D, 0, 0x65, 0, 0, 0, "Language preferences" }, - { 0x5F35, 0, 0x65, 0, 0, 0, "Sex" }, - { 0x006E, 1, 0, 1, 0, 0, "Application Related Data" }, - { 0x004F, 0, 0x6E, 1, 0, 0, "AID" }, - { 0x0073, 1, 0, 1, 0, 0, "Discretionary Data Objects" }, - { 0x0047, 0, 0x6E, 1, 0, 0, "Card Capabilities" }, - { 0x00C0, 0, 0x6E, 1, 0, 0, "Extended Card Capabilities" }, - { 0x00C1, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Signature" }, - { 0x00C2, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Decryption" }, - { 0x00C3, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Authentication" }, - { 0x00C4, 0, 0x6E, 1, 0, 1, "CHV Status Bytes" }, - { 0x00C5, 0, 0x6E, 1, 0, 0, "Fingerprints" }, - { 0x00C6, 0, 0x6E, 1, 0, 0, "CA Fingerprints" }, - { 0x007A, 1, 0, 1, 0, 0, "Security Support Template" }, - { 0x0093, 0, 0x7A, 1, 1, 0, "Digital Signature Counter" }, + { 0x005E, 0, 0, 1, 0, 0, 0, "Login Data" }, + { 0x5F50, 0, 0, 0, 0, 0, 0, "URL" }, + { 0x0065, 1, 0, 1, 0, 0, 0, "Cardholder Related Data"}, + { 0x005B, 0, 0x65, 0, 0, 0, 0, "Name" }, + { 0x5F2D, 0, 0x65, 0, 0, 0, 0, "Language preferences" }, + { 0x5F35, 0, 0x65, 0, 0, 0, 0, "Sex" }, + { 0x006E, 1, 0, 1, 0, 0, 0, "Application Related Data" }, + { 0x004F, 0, 0x6E, 1, 0, 0, 0, "AID" }, + { 0x0073, 1, 0, 1, 0, 0, 0, "Discretionary Data Objects" }, + { 0x0047, 0, 0x6E, 1, 1, 0, 0, "Card Capabilities" }, + { 0x00C0, 0, 0x6E, 1, 1, 0, 0, "Extended Card Capabilities" }, + { 0x00C1, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Signature" }, + { 0x00C2, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Decryption" }, + { 0x00C3, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Authentication" }, + { 0x00C4, 0, 0x6E, 1, 0, 1, 1, "CHV Status Bytes" }, + { 0x00C5, 0, 0x6E, 1, 0, 0, 0, "Fingerprints" }, + { 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" }, + { 0x007A, 1, 0, 1, 0, 0, 0, "Security Support Template" }, + { 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" }, { 0 } }; @@ -86,6 +92,13 @@ struct cache_s { struct app_local_s { struct cache_s *cache; + struct + { + unsigned int get_challenge:1; + unsigned int key_import:1; + unsigned int change_force_chv:1; + unsigned int private_dos:1; + } extcap; }; @@ -124,24 +137,26 @@ get_cached_data (app_t app, int tag, size_t len; struct cache_s *c; - *result = NULL; *resultlen = 0; - if (app->app_local) - { - for (c=app->app_local->cache; c; c = c->next) - if (c->tag == tag) + for (c=app->app_local->cache; c; c = c->next) + if (c->tag == tag) + { + if(c->length) { - p = xtrymalloc (c->length); - if (!p) - return gpg_error (gpg_err_code_from_errno (errno)); - memcpy (p, c->data, c->length); - *resultlen = c->length; - *result = p; - return 0; + p = xtrymalloc (c->length); + if (!p) + return gpg_error (gpg_err_code_from_errno (errno)); + memcpy (p, c->data, c->length); + *result = p; } - } + + *resultlen = c->length; + + return 0; + } + err = iso7816_get_data (app->slot, tag, &p, &len); if (err) @@ -159,24 +174,18 @@ get_cached_data (app_t app, int tag, } /* No, cache it. */ - if (!app->app_local) - app->app_local = xtrycalloc (1, sizeof *app->app_local); - /* Note that we can safely ignore out of core errors. */ - if (app->app_local) + for (c=app->app_local->cache; c; c = c->next) + assert (c->tag != tag); + + c = xtrymalloc (sizeof *c + len); + if (c) { - for (c=app->app_local->cache; c; c = c->next) - assert (c->tag != tag); - - c = xtrymalloc (sizeof *c + len); - if (c) - { - memcpy (c->data, p, len); - c->length = len; - c->tag = tag; - c->next = app->app_local->cache; - app->app_local->cache = c; - } + memcpy (c->data, p, len); + c->length = len; + c->tag = tag; + c->next = app->app_local->cache; + app->app_local->cache = c; } return 0; @@ -202,7 +211,9 @@ flush_cache_item (app_t app, int tag) xfree (c); for (c=app->app_local->cache; c ; c = c->next) - assert (c->tag != tag); /* Oops: duplicated entry. */ + { + assert (c->tag != tag); /* Oops: duplicated entry. */ + } return; } @@ -262,6 +273,15 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++) ; + if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11) + { + if( iso7816_get_data (app->slot, tag, &buffer, &buflen)) + return NULL; + *result = buffer; + *nbytes = buflen; + return buffer; + } + value = NULL; rc = -1; if (data_objects[i].tag && data_objects[i].get_from) @@ -428,7 +448,6 @@ store_fpr (int slot, int keynumber, u32 timestamp, *p++ = nbits; memcpy (p, e, elen); p += elen; - log_printhex ("fprbuf:", buffer, n+3); gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3); xfree (buffer); @@ -436,7 +455,22 @@ store_fpr (int slot, int keynumber, u32 timestamp, rc = iso7816_put_data (slot, (card_version > 0x0007? 0xC7 : 0xC6) + keynumber, fpr, 20); if (rc) - log_error ("failed to store the fingerprint: %s\n",gpg_strerror (rc)); + log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc)); + + if (!rc && card_version > 0x0100) + { + unsigned char buf[4]; + + buf[0] = timestamp >> 24; + buf[1] = timestamp >> 16; + buf[2] = timestamp >> 8; + buf[3] = timestamp; + + rc = iso7816_put_data (slot, 0xCE + keynumber, buf, 4); + if (rc) + log_error (_("failed to store the creation date: %s\n"), + gpg_strerror (rc)); + } return rc; } @@ -502,6 +536,7 @@ do_getattr (APP app, CTRL ctrl, const char *name) { "SIG-COUNTER", 0x0093, 2 }, { "SERIALNO", 0x004F, -1 }, { "AID", 0x004F }, + { "EXTCAP", 0x0000, -2 }, { NULL, 0 } }; int idx, i; @@ -536,6 +571,18 @@ do_getattr (APP app, CTRL ctrl, const char *name) } return 0; } + if (table[idx].special == -2) + { + char tmp[50]; + + sprintf (tmp, "gc=%d ki=%d fc=%d pd=%d", + app->app_local->extcap.get_challenge, + app->app_local->extcap.key_import, + app->app_local->extcap.change_force_chv, + app->app_local->extcap.private_dos); + send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); + return 0; + } relptr = get_one_do (app, table[idx].tag, &value, &valuelen); if (relptr) @@ -575,6 +622,7 @@ do_getattr (APP app, CTRL ctrl, const char *name) static int do_learn_status (APP app, CTRL ctrl) { + do_getattr (app, ctrl, "EXTCAP"); do_getattr (app, ctrl, "DISP-NAME"); do_getattr (app, ctrl, "DISP-LANG"); do_getattr (app, ctrl, "DISP-SEX"); @@ -605,13 +653,14 @@ verify_chv2 (app_t app, rc = pincb (pincb_arg, "PIN", &pinvalue); if (rc) { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc)); return rc; } if (strlen (pinvalue) < 6) { - log_error ("prassphrase (CHV2) is too short; minimum length is 6\n"); + log_error (_("prassphrase (CHV%d) is too short;" + " minimum length is %d\n"), 2, 6); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); } @@ -619,7 +668,7 @@ verify_chv2 (app_t app, rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); if (rc) { - log_error ("verify CHV2 failed: %s\n", gpg_strerror (rc)); + log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc)); xfree (pinvalue); flush_cache_after_error (app); return rc; @@ -633,7 +682,7 @@ verify_chv2 (app_t app, rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); if (rc) { - log_error ("verify CHV1 failed: %s\n", gpg_strerror (rc)); + log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc)); xfree (pinvalue); flush_cache_after_error (app); return rc; @@ -653,26 +702,54 @@ verify_chv3 (APP app, { int rc = 0; +#if GNUPG_MAJOR_VERSION != 1 if (!opt.allow_admin) { - log_info ("access to admin commands is not configured\n"); + log_info (_("access to admin commands is not configured\n")); return gpg_error (GPG_ERR_EACCES); } +#endif if (!app->did_chv3) { char *pinvalue; + void *relptr; + unsigned char *value; + size_t valuelen; + int reread_chv_status; + - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + relptr = get_one_do (app, 0x00C4, &value, &valuelen); + if (!relptr || valuelen < 7) + { + log_error (_("error retrieving CHV status from card\n")); + xfree (relptr); + return gpg_error (GPG_ERR_CARD); + } + if (value[6] == 0) + { + log_info (_("card is permanently locked!\n")); + xfree (relptr); + return gpg_error (GPG_ERR_BAD_PIN); + } + + reread_chv_status = (value[6] < 3); + + log_info(_("%d Admin PIN attempts remaining before card" + " is permanently locked\n"), value[6]); + xfree (relptr); + + rc = pincb (pincb_arg, _("Admin PIN"), &pinvalue); if (rc) { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc)); return rc; } if (strlen (pinvalue) < 6) { - log_error ("prassphrase (CHV3) is too short; minimum length is 6\n"); + log_error (_("prassphrase (CHV%d) is too short;" + " minimum length is %d\n"), 3, 6); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); } @@ -681,11 +758,18 @@ verify_chv3 (APP app, xfree (pinvalue); if (rc) { - log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); + log_error (_("verify CHV%d failed: %s\n"), 3, gpg_strerror (rc)); flush_cache_after_error (app); return rc; } app->did_chv3 = 1; + /* If the PIN has been entered wrongly before, we need to flush + the cached value so that the next read correctly reflects the + resetted retry counter. Note that version 1.1 of the specs + allow direct reading of that DO, so that we could actually + flush it in all cases. */ + if (reread_chv_status) + flush_cache_item (app, 0x00C4); } return rc; } @@ -1149,7 +1233,8 @@ do_sign (APP app, const char *keyidstr, int hashalgo, if (strlen (pinvalue) < 6) { - log_error ("prassphrase (CHV1) is too short; minimum length is 6\n"); + log_error (_("prassphrase (CHV%d) is too short;" + " minimum length is %d\n"), 1, 6); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); } @@ -1157,7 +1242,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo, rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); if (rc) { - log_error ("verify CHV1 failed\n"); + log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc)); xfree (pinvalue); flush_cache_after_error (app); return rc; @@ -1171,7 +1256,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo, rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); if (rc) { - log_error ("verify CHV2 failed\n"); + log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc)); xfree (pinvalue); flush_cache_after_error (app); return rc; @@ -1375,11 +1460,14 @@ app_select_openpgp (APP app) rc = iso7816_select_application (slot, aid, sizeof aid); if (!rc) { + unsigned int manufacturer; + app->apptype = "OPENPGP"; app->did_chv1 = 0; app->did_chv2 = 0; app->did_chv3 = 0; + app->app_local = NULL; /* The OpenPGP card returns the serial number as part of the AID; because we prefer to use OpenPGP serial numbers, we @@ -1391,33 +1479,57 @@ app_select_openpgp (APP app) goto leave; if (opt.verbose) { - log_info ("got AID: "); + log_info ("AID: "); log_printhex ("", buffer, buflen); } -#if GNUPG_MAJOR_VERSION != 1 - /* A valid OpenPGP card should never need this but well the test - is cheap. */ - rc = app_munge_serialno (app); - if (rc) - goto leave; -#endif app->card_version = buffer[6] << 8; app->card_version |= buffer[7]; + manufacturer = (buffer[8]<<8 | buffer[9]); + xfree (app->serialno); app->serialno = buffer; app->serialnolen = buflen; buffer = NULL; + app->app_local = xtrycalloc (1, sizeof *app->app_local); + if (!app->app_local) + { + rc = gpg_error (gpg_err_code_from_errno (errno)); + goto leave; + } relptr = get_one_do (app, 0x00C4, &buffer, &buflen); if (!relptr) { - log_error ("can't access CHV Status Bytes - invalid OpenPGP card?\n"); + log_error (_("can't access CHV Status Bytes " + "- invalid OpenPGP card?\n")); goto leave; } app->force_chv1 = (buflen && *buffer == 0); xfree (relptr); - + + relptr = get_one_do (app, 0x00C0, &buffer, &buflen); + if (!relptr) + { + log_error (_("can't access Extended Capability Flags - " + "invalid OpenPGP card?\n")); + goto leave; + } + if (buflen) + { + app->app_local->extcap.get_challenge = !!(*buffer & 0x40); + app->app_local->extcap.key_import = !!(*buffer & 0x20); + app->app_local->extcap.change_force_chv = !!(*buffer & 0x10); + app->app_local->extcap.private_dos = !!(*buffer & 0x08); + } + xfree (relptr); + + /* Some of the first cards accidently don't set the + CHANGE_FORCE_CHV bit but allow it anyway. */ + if (app->card_version <= 0x0100 && manufacturer == 1) + app->app_local->extcap.change_force_chv = 1; + + if (opt.verbose > 1) dump_all_do (slot); @@ -1435,6 +1547,8 @@ app_select_openpgp (APP app) } leave: + if (rc) + do_deinit (app); return rc; } @@ -1467,7 +1581,8 @@ app_openpgp_cardinfo (APP app, rc = app_get_serial_and_stamp (app, serialno, &dummy); if (rc) { - log_error ("error getting serial number: %s\n", gpg_strerror (rc)); + log_error (_("error getting serial number: %s\n"), + gpg_strerror (rc)); return rc; } } @@ -1554,13 +1669,14 @@ app_openpgp_storekey (APP app, int keyno, if (rc) goto leave; + flush_cache (app); rc = iso7816_put_data (app->slot, (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, template, template_len); if (rc) { - log_error ("failed to store the key: rc=%s\n", gpg_strerror (rc)); + log_error (_("failed to store the key: %s\n"), gpg_strerror (rc)); rc = gpg_error (GPG_ERR_CARD); goto leave; } @@ -1602,14 +1718,14 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, if (rc) { rc = gpg_error (GPG_ERR_CARD); - log_error ("reading key failed\n"); + log_error (_("reading the key failed\n")); goto leave; } keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen); if (!keydata) { - log_error ("response does not contain the public key data\n"); + log_error (_("response does not contain the public key data\n")); rc = gpg_error (GPG_ERR_CARD); goto leave; } @@ -1617,7 +1733,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, a = find_tlv (keydata, keydatalen, 0x0081, &alen); if (!a) { - log_error ("response does not contain the RSA modulus\n"); + log_error (_("response does not contain the RSA modulus\n")); rc = gpg_error (GPG_ERR_CARD); goto leave; } @@ -1628,7 +1744,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, a = find_tlv (keydata, keydatalen, 0x0082, &alen); if (!a) { - log_error ("response does not contain the RSA public exponent\n"); + log_error (_("response does not contain the RSA public exponent\n")); rc = gpg_error (GPG_ERR_CARD); goto leave; } diff --git a/sm/ChangeLog b/sm/ChangeLog index 2391deb18..28a397182 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * keylist.c (list_cert_colon): Make sure that the expired flag has + a higher precedence than the invalid flag. + 2004-09-29 Werner Koch <wk@g10code.com> * import.c (parse_p12): Write an error status line for bad diff --git a/sm/keylist.c b/sm/keylist.c index 0c8ebd33e..e9985f3ec 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -333,6 +333,9 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, fputs (have_secret? "crs:":"crt:", fp); + + /* Note: We can't use multiple flags, like "ei", because the + validation check does only return one error. */ truststring[0] = 0; truststring[1] = 0; if ((validity & VALIDITY_REVOKED) @@ -340,8 +343,6 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, *truststring = 'r'; else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED) *truststring = 'e'; - else if (valerr) - *truststring = 'i'; else { /* Lets also check whether the certificate under question @@ -354,6 +355,8 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, && !ksba_cert_get_validity (cert, 1, not_after) && *not_after && strcmp (current_time, not_after) > 0 ) *truststring = 'e'; + else if (valerr) + *truststring = 'i'; } /* Is we have no truststring yet (i.e. the certificate might be -- cgit v1.2.3 From dd3b12f3b11e3f188d05ae4607f630bf07827a64 Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Thu, 30 Sep 2004 14:34:34 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- intl/printf-args.c | 119 +++++++ intl/printf-args.h | 137 ++++++++ intl/printf-parse.c | 537 +++++++++++++++++++++++++++++++ intl/printf-parse.h | 75 +++++ intl/printf.c | 371 +++++++++++++++++++++ intl/vasnprintf.c | 887 +++++++++++++++++++++++++++++++++++++++++++++++++++ intl/vasnprintf.h | 61 ++++ intl/vasnwprintf.h | 46 +++ intl/wprintf-parse.h | 75 +++++ intl/xsize.h | 109 +++++++ m4/intmax.m4 | 32 ++ m4/longdouble.m4 | 30 ++ m4/longlong.m4 | 25 ++ m4/printf-posix.m4 | 46 +++ m4/signed.m4 | 19 ++ m4/size_max.m4 | 61 ++++ m4/wchar_t.m4 | 22 ++ m4/wint_t.m4 | 22 ++ m4/xsize.m4 | 14 + scripts/ChangeLog | 377 ++++++++++++++++++++++ 20 files changed, 3065 insertions(+) create mode 100644 intl/printf-args.c create mode 100644 intl/printf-args.h create mode 100644 intl/printf-parse.c create mode 100644 intl/printf-parse.h create mode 100644 intl/printf.c create mode 100644 intl/vasnprintf.c create mode 100644 intl/vasnprintf.h create mode 100644 intl/vasnwprintf.h create mode 100644 intl/wprintf-parse.h create mode 100644 intl/xsize.h create mode 100644 m4/intmax.m4 create mode 100644 m4/longdouble.m4 create mode 100644 m4/longlong.m4 create mode 100644 m4/printf-posix.m4 create mode 100644 m4/signed.m4 create mode 100644 m4/size_max.m4 create mode 100644 m4/wchar_t.m4 create mode 100644 m4/wint_t.m4 create mode 100644 m4/xsize.m4 create mode 100644 scripts/ChangeLog diff --git a/intl/printf-args.c b/intl/printf-args.c new file mode 100644 index 000000000..f6f3219e7 --- /dev/null +++ b/intl/printf-args.c @@ -0,0 +1,119 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 + +/* Specification. */ +#include "printf-args.h" + +#ifdef STATIC +STATIC +#endif +int +printf_fetchargs (va_list args, arguments *a) +{ + size_t i; + argument *ap; + + for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) + switch (ap->type) + { + case TYPE_SCHAR: + ap->a.a_schar = va_arg (args, /*signed char*/ int); + break; + case TYPE_UCHAR: + ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); + break; + case TYPE_SHORT: + ap->a.a_short = va_arg (args, /*short*/ int); + break; + case TYPE_USHORT: + ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); + break; + case TYPE_INT: + ap->a.a_int = va_arg (args, int); + break; + case TYPE_UINT: + ap->a.a_uint = va_arg (args, unsigned int); + break; + case TYPE_LONGINT: + ap->a.a_longint = va_arg (args, long int); + break; + case TYPE_ULONGINT: + ap->a.a_ulongint = va_arg (args, unsigned long int); + break; +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + ap->a.a_longlongint = va_arg (args, long long int); + break; + case TYPE_ULONGLONGINT: + ap->a.a_ulonglongint = va_arg (args, unsigned long long int); + break; +#endif + case TYPE_DOUBLE: + ap->a.a_double = va_arg (args, double); + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + ap->a.a_longdouble = va_arg (args, long double); + break; +#endif + case TYPE_CHAR: + ap->a.a_char = va_arg (args, int); + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: + ap->a.a_wide_char = va_arg (args, wint_t); + break; +#endif + case TYPE_STRING: + ap->a.a_string = va_arg (args, const char *); + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + ap->a.a_wide_string = va_arg (args, const wchar_t *); + break; +#endif + case TYPE_POINTER: + ap->a.a_pointer = va_arg (args, void *); + break; + case TYPE_COUNT_SCHAR_POINTER: + ap->a.a_count_schar_pointer = va_arg (args, signed char *); + break; + case TYPE_COUNT_SHORT_POINTER: + ap->a.a_count_short_pointer = va_arg (args, short *); + break; + case TYPE_COUNT_INT_POINTER: + ap->a.a_count_int_pointer = va_arg (args, int *); + break; + case TYPE_COUNT_LONGINT_POINTER: + ap->a.a_count_longint_pointer = va_arg (args, long int *); + break; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); + break; +#endif + default: + /* Unknown type. */ + return -1; + } + return 0; +} diff --git a/intl/printf-args.h b/intl/printf-args.h new file mode 100644 index 000000000..f11e64c04 --- /dev/null +++ b/intl/printf-args.h @@ -0,0 +1,137 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _PRINTF_ARGS_H +#define _PRINTF_ARGS_H + +/* Get size_t. */ +#include <stddef.h> + +/* Get wchar_t. */ +#ifdef HAVE_WCHAR_T +# include <stddef.h> +#endif + +/* Get wint_t. */ +#ifdef HAVE_WINT_T +# include <wchar.h> +#endif + +/* Get va_list. */ +#include <stdarg.h> + + +/* Argument types */ +typedef enum +{ + TYPE_NONE, + TYPE_SCHAR, + TYPE_UCHAR, + TYPE_SHORT, + TYPE_USHORT, + TYPE_INT, + TYPE_UINT, + TYPE_LONGINT, + TYPE_ULONGINT, +#ifdef HAVE_LONG_LONG + TYPE_LONGLONGINT, + TYPE_ULONGLONGINT, +#endif + TYPE_DOUBLE, +#ifdef HAVE_LONG_DOUBLE + TYPE_LONGDOUBLE, +#endif + TYPE_CHAR, +#ifdef HAVE_WINT_T + TYPE_WIDE_CHAR, +#endif + TYPE_STRING, +#ifdef HAVE_WCHAR_T + TYPE_WIDE_STRING, +#endif + TYPE_POINTER, + TYPE_COUNT_SCHAR_POINTER, + TYPE_COUNT_SHORT_POINTER, + TYPE_COUNT_INT_POINTER, + TYPE_COUNT_LONGINT_POINTER +#ifdef HAVE_LONG_LONG +, TYPE_COUNT_LONGLONGINT_POINTER +#endif +} arg_type; + +/* Polymorphic argument */ +typedef struct +{ + arg_type type; + union + { + signed char a_schar; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long int a_longint; + unsigned long int a_ulongint; +#ifdef HAVE_LONG_LONG + long long int a_longlongint; + unsigned long long int a_ulonglongint; +#endif + float a_float; + double a_double; +#ifdef HAVE_LONG_DOUBLE + long double a_longdouble; +#endif + int a_char; +#ifdef HAVE_WINT_T + wint_t a_wide_char; +#endif + const char* a_string; +#ifdef HAVE_WCHAR_T + const wchar_t* a_wide_string; +#endif + void* a_pointer; + signed char * a_count_schar_pointer; + short * a_count_short_pointer; + int * a_count_int_pointer; + long int * a_count_longint_pointer; +#ifdef HAVE_LONG_LONG + long long int * a_count_longlongint_pointer; +#endif + } + a; +} +argument; + +typedef struct +{ + size_t count; + argument *arg; +} +arguments; + + +/* Fetch the arguments, putting them into a. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int printf_fetchargs (va_list args, arguments *a); + +#endif /* _PRINTF_ARGS_H */ diff --git a/intl/printf-parse.c b/intl/printf-parse.c new file mode 100644 index 000000000..d19f903d7 --- /dev/null +++ b/intl/printf-parse.c @@ -0,0 +1,537 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Get size_t, NULL. */ +#include <stddef.h> + +/* Get intmax_t. */ +#if HAVE_STDINT_H_WITH_UINTMAX +# include <stdint.h> +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +# include <inttypes.h> +#endif + +/* malloc(), realloc(), free(). */ +#include <stdlib.h> + +/* Checked size_t computations. */ +#include "xsize.h" + +#if WIDE_CHAR_VERSION +# define PRINTF_PARSE wprintf_parse +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +#else +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#endif + +#ifdef STATIC +STATIC +#endif +int +PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) +{ + const CHAR_T *cp = format; /* pointer into format */ + size_t arg_posn = 0; /* number of regular arguments consumed */ + size_t d_allocated; /* allocated elements of d->dir */ + size_t a_allocated; /* allocated elements of a->arg */ + size_t max_width_length = 0; + size_t max_precision_length = 0; + + d->count = 0; + d_allocated = 1; + d->dir = malloc (d_allocated * sizeof (DIRECTIVE)); + if (d->dir == NULL) + /* Out of memory. */ + return -1; + + a->count = 0; + a_allocated = 0; + a->arg = NULL; + +#define REGISTER_ARG(_index_,_type_) \ + { \ + size_t n = (_index_); \ + if (n >= a_allocated) \ + { \ + size_t memory_size; \ + argument *memory; \ + \ + a_allocated = xtimes (a_allocated, 2); \ + if (a_allocated <= n) \ + a_allocated = xsum (n, 1); \ + memory_size = xtimes (a_allocated, sizeof (argument)); \ + if (size_overflow_p (memory_size)) \ + /* Overflow, would lead to out of memory. */ \ + goto error; \ + memory = (a->arg \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ + if (memory == NULL) \ + /* Out of memory. */ \ + goto error; \ + a->arg = memory; \ + } \ + while (a->count <= n) \ + a->arg[a->count++].type = TYPE_NONE; \ + if (a->arg[n].type == TYPE_NONE) \ + a->arg[n].type = (_type_); \ + else if (a->arg[n].type != (_type_)) \ + /* Ambiguous type for positional argument. */ \ + goto error; \ + } + + while (*cp != '\0') + { + CHAR_T c = *cp++; + if (c == '%') + { + size_t arg_index = ARG_NONE; + DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ + + /* Initialize the next directive. */ + dp->dir_start = cp - 1; + dp->flags = 0; + dp->width_start = NULL; + dp->width_end = NULL; + dp->width_arg_index = ARG_NONE; + dp->precision_start = NULL; + dp->precision_end = NULL; + dp->precision_arg_index = ARG_NONE; + dp->arg_index = ARG_NONE; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + arg_index = n - 1; + cp = np + 1; + } + } + + /* Read the flags. */ + for (;;) + { + if (*cp == '\'') + { + dp->flags |= FLAG_GROUP; + cp++; + } + else if (*cp == '-') + { + dp->flags |= FLAG_LEFT; + cp++; + } + else if (*cp == '+') + { + dp->flags |= FLAG_SHOWSIGN; + cp++; + } + else if (*cp == ' ') + { + dp->flags |= FLAG_SPACE; + cp++; + } + else if (*cp == '#') + { + dp->flags |= FLAG_ALT; + cp++; + } + else if (*cp == '0') + { + dp->flags |= FLAG_ZERO; + cp++; + } + else + break; + } + + /* Parse the field width. */ + if (*cp == '*') + { + dp->width_start = cp; + cp++; + dp->width_end = cp; + if (max_width_length < 1) + max_width_length = 1; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + dp->width_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->width_arg_index == ARG_NONE) + { + dp->width_arg_index = arg_posn++; + if (dp->width_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->width_arg_index, TYPE_INT); + } + else if (*cp >= '0' && *cp <= '9') + { + size_t width_length; + + dp->width_start = cp; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->width_end = cp; + width_length = dp->width_end - dp->width_start; + if (max_width_length < width_length) + max_width_length = width_length; + } + + /* Parse the precision. */ + if (*cp == '.') + { + cp++; + if (*cp == '*') + { + dp->precision_start = cp - 1; + cp++; + dp->precision_end = cp; + if (max_precision_length < 2) + max_precision_length = 2; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory + later. */ + goto error; + dp->precision_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->precision_arg_index == ARG_NONE) + { + dp->precision_arg_index = arg_posn++; + if (dp->precision_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->precision_arg_index, TYPE_INT); + } + else + { + size_t precision_length; + + dp->precision_start = cp - 1; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->precision_end = cp; + precision_length = dp->precision_end - dp->precision_start; + if (max_precision_length < precision_length) + max_precision_length = precision_length; + } + } + + { + arg_type type; + + /* Parse argument type/size specifiers. */ + { + int flags = 0; + + for (;;) + { + if (*cp == 'h') + { + flags |= (1 << (flags & 1)); + cp++; + } + else if (*cp == 'L') + { + flags |= 4; + cp++; + } + else if (*cp == 'l') + { + flags += 8; + cp++; + } +#ifdef HAVE_INTMAX_T + else if (*cp == 'j') + { + if (sizeof (intmax_t) > sizeof (long)) + { + /* intmax_t = long long */ + flags += 16; + } + else if (sizeof (intmax_t) > sizeof (int)) + { + /* intmax_t = long */ + flags += 8; + } + cp++; + } +#endif + else if (*cp == 'z' || *cp == 'Z') + { + /* 'z' is standardized in ISO C 99, but glibc uses 'Z' + because the warning facility in gcc-2.95.2 understands + only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ + if (sizeof (size_t) > sizeof (long)) + { + /* size_t = long long */ + flags += 16; + } + else if (sizeof (size_t) > sizeof (int)) + { + /* size_t = long */ + flags += 8; + } + cp++; + } + else if (*cp == 't') + { + if (sizeof (ptrdiff_t) > sizeof (long)) + { + /* ptrdiff_t = long long */ + flags += 16; + } + else if (sizeof (ptrdiff_t) > sizeof (int)) + { + /* ptrdiff_t = long */ + flags += 8; + } + cp++; + } + else + break; + } + + /* Read the conversion character. */ + c = *cp++; + switch (c) + { + case 'd': case 'i': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGLONGINT; + else +#endif + if (flags >= 8) + type = TYPE_LONGINT; + else if (flags & 2) + type = TYPE_SCHAR; + else if (flags & 1) + type = TYPE_SHORT; + else + type = TYPE_INT; + break; + case 'o': case 'u': case 'x': case 'X': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_ULONGLONGINT; + else +#endif + if (flags >= 8) + type = TYPE_ULONGINT; + else if (flags & 2) + type = TYPE_UCHAR; + else if (flags & 1) + type = TYPE_USHORT; + else + type = TYPE_UINT; + break; + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': +#ifdef HAVE_LONG_DOUBLE + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGDOUBLE; + else +#endif + type = TYPE_DOUBLE; + break; + case 'c': + if (flags >= 8) +#ifdef HAVE_WINT_T + type = TYPE_WIDE_CHAR; +#else + goto error; +#endif + else + type = TYPE_CHAR; + break; +#ifdef HAVE_WINT_T + case 'C': + type = TYPE_WIDE_CHAR; + c = 'c'; + break; +#endif + case 's': + if (flags >= 8) +#ifdef HAVE_WCHAR_T + type = TYPE_WIDE_STRING; +#else + goto error; +#endif + else + type = TYPE_STRING; + break; +#ifdef HAVE_WCHAR_T + case 'S': + type = TYPE_WIDE_STRING; + c = 's'; + break; +#endif + case 'p': + type = TYPE_POINTER; + break; + case 'n': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_COUNT_LONGLONGINT_POINTER; + else +#endif + if (flags >= 8) + type = TYPE_COUNT_LONGINT_POINTER; + else if (flags & 2) + type = TYPE_COUNT_SCHAR_POINTER; + else if (flags & 1) + type = TYPE_COUNT_SHORT_POINTER; + else + type = TYPE_COUNT_INT_POINTER; + break; + case '%': + type = TYPE_NONE; + break; + default: + /* Unknown conversion character. */ + goto error; + } + } + + if (type != TYPE_NONE) + { + dp->arg_index = arg_index; + if (dp->arg_index == ARG_NONE) + { + dp->arg_index = arg_posn++; + if (dp->arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->arg_index, type); + } + dp->conversion = c; + dp->dir_end = cp; + } + + d->count++; + if (d->count >= d_allocated) + { + size_t memory_size; + DIRECTIVE *memory; + + d_allocated = xtimes (d_allocated, 2); + memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + goto error; + memory = realloc (d->dir, memory_size); + if (memory == NULL) + /* Out of memory. */ + goto error; + d->dir = memory; + } + } + } + d->dir[d->count].dir_start = cp; + + d->max_width_length = max_width_length; + d->max_precision_length = max_precision_length; + return 0; + +error: + if (a->arg) + free (a->arg); + if (d->dir) + free (d->dir); + return -1; +} + +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef PRINTF_PARSE diff --git a/intl/printf-parse.h b/intl/printf-parse.h new file mode 100644 index 000000000..8aec50e2a --- /dev/null +++ b/intl/printf-parse.h @@ -0,0 +1,75 @@ +/* Parse printf format string. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _PRINTF_PARSE_H +#define _PRINTF_PARSE_H + +#include "printf-args.h" + + +/* Flags */ +#define FLAG_GROUP 1 /* ' flag */ +#define FLAG_LEFT 2 /* - flag */ +#define FLAG_SHOWSIGN 4 /* + flag */ +#define FLAG_SPACE 8 /* space flag */ +#define FLAG_ALT 16 /* # flag */ +#define FLAG_ZERO 32 + +/* arg_index value indicating that no argument is consumed. */ +#define ARG_NONE (~(size_t)0) + +/* A parsed directive. */ +typedef struct +{ + const char* dir_start; + const char* dir_end; + int flags; + const char* width_start; + const char* width_end; + size_t width_arg_index; + const char* precision_start; + const char* precision_end; + size_t precision_arg_index; + char conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + size_t arg_index; +} +char_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + char_directive *dir; + size_t max_width_length; + size_t max_precision_length; +} +char_directives; + + +/* Parses the format string. Fills in the number N of directives, and fills + in directives[0], ..., directives[N-1], and sets directives[N].dir_start + to the end of the format string. Also fills in the arg_type fields of the + arguments and the needed count of arguments. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int printf_parse (const char *format, char_directives *d, arguments *a); + +#endif /* _PRINTF_PARSE_H */ diff --git a/intl/printf.c b/intl/printf.c new file mode 100644 index 000000000..878646c2d --- /dev/null +++ b/intl/printf.c @@ -0,0 +1,371 @@ +/* Formatted output to strings, using POSIX/XSI format strings with positions. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 + +#ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include <stdio.h> + +#if !HAVE_POSIX_PRINTF + +#include <stdlib.h> +#include <string.h> + +/* When building a DLL, we must export some functions. Note that because + the functions are only defined for binary backward compatibility, we + don't need to use __declspec(dllimport) in any case. */ +#if defined _MSC_VER && BUILDING_DLL +# define DLL_EXPORTED __declspec(dllexport) +#else +# define DLL_EXPORTED +#endif + +#define STATIC static + +/* Define auxiliary functions declared in "printf-args.h". */ +#include "printf-args.c" + +/* Define auxiliary functions declared in "printf-parse.h". */ +#include "printf-parse.c" + +/* Define functions declared in "vasnprintf.h". */ +#define vasnprintf libintl_vasnprintf +#include "vasnprintf.c" +#if 0 /* not needed */ +#define asnprintf libintl_asnprintf +#include "asnprintf.c" +#endif + +DLL_EXPORTED +int +libintl_vfprintf (FILE *stream, const char *format, va_list args) +{ + if (strchr (format, '$') == NULL) + return vfprintf (stream, format, args); + else + { + size_t length; + char *result = libintl_vasnprintf (NULL, &length, format, args); + int retval = -1; + if (result != NULL) + { + if (fwrite (result, 1, length, stream) == length) + retval = length; + free (result); + } + return retval; + } +} + +DLL_EXPORTED +int +libintl_fprintf (FILE *stream, const char *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vfprintf (stream, format, args); + va_end (args); + return retval; +} + +DLL_EXPORTED +int +libintl_vprintf (const char *format, va_list args) +{ + return libintl_vfprintf (stdout, format, args); +} + +DLL_EXPORTED +int +libintl_printf (const char *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vprintf (format, args); + va_end (args); + return retval; +} + +DLL_EXPORTED +int +libintl_vsprintf (char *resultbuf, const char *format, va_list args) +{ + if (strchr (format, '$') == NULL) + return vsprintf (resultbuf, format, args); + else + { + size_t length = (size_t) ~0 / (4 * sizeof (char)); + char *result = libintl_vasnprintf (resultbuf, &length, format, args); + if (result != resultbuf) + { + free (result); + return -1; + } + else + return length; + } +} + +DLL_EXPORTED +int +libintl_sprintf (char *resultbuf, const char *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vsprintf (resultbuf, format, args); + va_end (args); + return retval; +} + +#if HAVE_SNPRINTF + +# if HAVE_DECL__SNPRINTF + /* Windows. */ +# define system_vsnprintf _vsnprintf +# else + /* Unix. */ +# define system_vsnprintf vsnprintf +# endif + +DLL_EXPORTED +int +libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args) +{ + if (strchr (format, '$') == NULL) + return system_vsnprintf (resultbuf, length, format, args); + else + { + size_t maxlength = length; + char *result = libintl_vasnprintf (resultbuf, &length, format, args); + if (result != resultbuf) + { + if (maxlength > 0) + { + if (length < maxlength) + abort (); + memcpy (resultbuf, result, maxlength - 1); + resultbuf[maxlength - 1] = '\0'; + } + free (result); + return -1; + } + else + return length; + } +} + +DLL_EXPORTED +int +libintl_snprintf (char *resultbuf, size_t length, const char *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vsnprintf (resultbuf, length, format, args); + va_end (args); + return retval; +} + +#endif + +#if HAVE_ASPRINTF + +DLL_EXPORTED +int +libintl_vasprintf (char **resultp, const char *format, va_list args) +{ + size_t length; + char *result = libintl_vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + *resultp = result; + return length; +} + +DLL_EXPORTED +int +libintl_asprintf (char **resultp, const char *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vasprintf (resultp, format, args); + va_end (args); + return retval; +} + +#endif + +#if HAVE_FWPRINTF + +#include <wchar.h> + +#define WIDE_CHAR_VERSION 1 + +/* Define auxiliary functions declared in "wprintf-parse.h". */ +#include "printf-parse.c" + +/* Define functions declared in "vasnprintf.h". */ +#define vasnwprintf libintl_vasnwprintf +#include "vasnprintf.c" +#if 0 /* not needed */ +#define asnwprintf libintl_asnwprintf +#include "asnprintf.c" +#endif + +# if HAVE_DECL__SNWPRINTF + /* Windows. */ +# define system_vswprintf _vsnwprintf +# else + /* Unix. */ +# define system_vswprintf vswprintf +# endif + +DLL_EXPORTED +int +libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args) +{ + if (wcschr (format, '$') == NULL) + return vfwprintf (stream, format, args); + else + { + size_t length; + wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args); + int retval = -1; + if (result != NULL) + { + size_t i; + for (i = 0; i < length; i++) + if (fputwc (result[i], stream) == WEOF) + break; + if (i == length) + retval = length; + free (result); + } + return retval; + } +} + +DLL_EXPORTED +int +libintl_fwprintf (FILE *stream, const wchar_t *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vfwprintf (stream, format, args); + va_end (args); + return retval; +} + +DLL_EXPORTED +int +libintl_vwprintf (const wchar_t *format, va_list args) +{ + return libintl_vfwprintf (stdout, format, args); +} + +DLL_EXPORTED +int +libintl_wprintf (const wchar_t *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vwprintf (format, args); + va_end (args); + return retval; +} + +DLL_EXPORTED +int +libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args) +{ + if (wcschr (format, '$') == NULL) + return system_vswprintf (resultbuf, length, format, args); + else + { + size_t maxlength = length; + wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args); + if (result != resultbuf) + { + if (maxlength > 0) + { + if (length < maxlength) + abort (); + memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t)); + resultbuf[maxlength - 1] = 0; + } + free (result); + return -1; + } + else + return length; + } +} + +DLL_EXPORTED +int +libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...) +{ + va_list args; + int retval; + + va_start (args, format); + retval = libintl_vswprintf (resultbuf, length, format, args); + va_end (args); + return retval; +} + +#endif + +#endif diff --git a/intl/vasnprintf.c b/intl/vasnprintf.c new file mode 100644 index 000000000..8a62282d7 --- /dev/null +++ b/intl/vasnprintf.c @@ -0,0 +1,887 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Tell glibc's <stdio.h> to provide a prototype for snprintf(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#ifndef IN_LIBINTL +# include <alloca.h> +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +#else +# include "vasnprintf.h" +#endif + +#include <stdio.h> /* snprintf(), sprintf() */ +#include <stdlib.h> /* abort(), malloc(), realloc(), free() */ +#include <string.h> /* memcpy(), strlen() */ +#include <errno.h> /* errno */ +#include <limits.h> /* CHAR_BIT */ +#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Checked size_t computations. */ +#include "xsize.h" + +#ifdef HAVE_WCHAR_T +# ifdef HAVE_WCSLEN +# define local_wcslen wcslen +# else + /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 +static size_t +local_wcslen (const wchar_t *s) +{ + const wchar_t *ptr; + + for (ptr = s; *ptr != (wchar_t) 0; ptr++) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if WIDE_CHAR_VERSION +# define VASNPRINTF vasnwprintf +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +# define PRINTF_PARSE wprintf_parse +# define USE_SNPRINTF 1 +# if HAVE_DECL__SNWPRINTF + /* On Windows, the function swprintf() has a different signature than + on Unix; we use the _snwprintf() function instead. */ +# define SNPRINTF _snwprintf +# else + /* Unix. */ +# define SNPRINTF swprintf +# endif +#else +# define VASNPRINTF vasnprintf +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +# define PRINTF_PARSE printf_parse +# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) +# if HAVE_DECL__SNPRINTF + /* Windows. */ +# define SNPRINTF _snprintf +# else + /* Unix. */ +# define SNPRINTF snprintf +# endif +#endif + +CHAR_T * +VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) +{ + DIRECTIVES d; + arguments a; + + if (PRINTF_PARSE (format, &d, &a) < 0) + { + errno = EINVAL; + return NULL; + } + +#define CLEANUP() \ + free (d.dir); \ + if (a.arg) \ + free (a.arg); + + if (printf_fetchargs (args, &a) < 0) + { + CLEANUP (); + errno = EINVAL; + return NULL; + } + + { + size_t buf_neededlength; + CHAR_T *buf; + CHAR_T *buf_malloced; + const CHAR_T *cp; + size_t i; + DIRECTIVE *dp; + /* Output string accumulator. */ + CHAR_T *result; + size_t allocated; + size_t length; + + /* Allocate a small buffer that will hold a directive passed to + sprintf or snprintf. */ + buf_neededlength = + xsum4 (7, d.max_width_length, d.max_precision_length, 6); +#if HAVE_ALLOCA + if (buf_neededlength < 4000 / sizeof (CHAR_T)) + { + buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); + buf_malloced = NULL; + } + else +#endif + { + size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); + if (size_overflow_p (buf_memsize)) + goto out_of_memory_1; + buf = (CHAR_T *) malloc (buf_memsize); + if (buf == NULL) + goto out_of_memory_1; + buf_malloced = buf; + } + + if (resultbuf != NULL) + { + result = resultbuf; + allocated = *lengthp; + } + else + { + result = NULL; + allocated = 0; + } + length = 0; + /* Invariants: + result is either == resultbuf or == NULL or malloc-allocated. + If length > 0, then result != NULL. */ + + /* Ensures that allocated >= needed. Aborts through a jump to + out_of_memory if needed is SIZE_MAX or otherwise too big. */ +#define ENSURE_ALLOCATION(needed) \ + if ((needed) > allocated) \ + { \ + size_t memory_size; \ + CHAR_T *memory; \ + \ + allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ + if ((needed) > allocated) \ + allocated = (needed); \ + memory_size = xtimes (allocated, sizeof (CHAR_T)); \ + if (size_overflow_p (memory_size)) \ + goto out_of_memory; \ + if (result == resultbuf || result == NULL) \ + memory = (CHAR_T *) malloc (memory_size); \ + else \ + memory = (CHAR_T *) realloc (result, memory_size); \ + if (memory == NULL) \ + goto out_of_memory; \ + if (result == resultbuf && length > 0) \ + memcpy (memory, result, length * sizeof (CHAR_T)); \ + result = memory; \ + } + + for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) + { + if (cp != dp->dir_start) + { + size_t n = dp->dir_start - cp; + size_t augmented_length = xsum (length, n); + + ENSURE_ALLOCATION (augmented_length); + memcpy (result + length, cp, n * sizeof (CHAR_T)); + length = augmented_length; + } + if (i == d.count) + break; + + /* Execute a single directive. */ + if (dp->conversion == '%') + { + size_t augmented_length; + + if (!(dp->arg_index == ARG_NONE)) + abort (); + augmented_length = xsum (length, 1); + ENSURE_ALLOCATION (augmented_length); + result[length] = '%'; + length = augmented_length; + } + else + { + if (!(dp->arg_index != ARG_NONE)) + abort (); + + if (dp->conversion == 'n') + { + switch (a.arg[dp->arg_index].type) + { + case TYPE_COUNT_SCHAR_POINTER: + *a.arg[dp->arg_index].a.a_count_schar_pointer = length; + break; + case TYPE_COUNT_SHORT_POINTER: + *a.arg[dp->arg_index].a.a_count_short_pointer = length; + break; + case TYPE_COUNT_INT_POINTER: + *a.arg[dp->arg_index].a.a_count_int_pointer = length; + break; + case TYPE_COUNT_LONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longint_pointer = length; + break; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; + break; +#endif + default: + abort (); + } + } + else + { + arg_type type = a.arg[dp->arg_index].type; + CHAR_T *p; + unsigned int prefix_count; + int prefixes[2]; +#if !USE_SNPRINTF + size_t tmp_length; + CHAR_T tmpbuf[700]; + CHAR_T *tmp; + + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + { + size_t width; + size_t precision; + + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = (arg < 0 ? (unsigned int) (-arg) : arg); + } + else + { + const CHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + precision = 6; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + precision = (arg < 0 ? 0 : arg); + } + else + { + const CHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + do + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + while (digitp != dp->precision_end); + } + } + + switch (dp->conversion) + { + + case 'd': case 'i': case 'u': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'o': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'x': case 'X': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + break; + + case 'f': case 'F': +# ifdef HAVE_LONG_DOUBLE + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + else +# endif + tmp_length = + (unsigned int) (DBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': + tmp_length = + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'c': +# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# ifdef HAVE_WCHAR_T + if (type == TYPE_WIDE_STRING) + { + tmp_length = + local_wcslen (a.arg[dp->arg_index].a.a_wide_string); + +# if !WIDE_CHAR_VERSION + tmp_length = xtimes (tmp_length, MB_CUR_MAX); +# endif + } + else +# endif + tmp_length = strlen (a.arg[dp->arg_index].a.a_string); + break; + + case 'p': + tmp_length = + (unsigned int) (sizeof (void *) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading 0x */ + break; + + default: + abort (); + } + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + } + + if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (CHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } +#endif + + /* Construct the format string for calling snprintf or + sprintf. */ + p = buf; + *p++ = '%'; + if (dp->flags & FLAG_GROUP) + *p++ = '\''; + if (dp->flags & FLAG_LEFT) + *p++ = '-'; + if (dp->flags & FLAG_SHOWSIGN) + *p++ = '+'; + if (dp->flags & FLAG_SPACE) + *p++ = ' '; + if (dp->flags & FLAG_ALT) + *p++ = '#'; + if (dp->flags & FLAG_ZERO) + *p++ = '0'; + if (dp->width_start != dp->width_end) + { + size_t n = dp->width_end - dp->width_start; + memcpy (p, dp->width_start, n * sizeof (CHAR_T)); + p += n; + } + if (dp->precision_start != dp->precision_end) + { + size_t n = dp->precision_end - dp->precision_start; + memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); + p += n; + } + + switch (type) + { +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: + *p++ = 'l'; + /*FALLTHROUGH*/ +#endif + case TYPE_LONGINT: + case TYPE_ULONGINT: +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: +#endif +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: +#endif + *p++ = 'l'; + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + *p++ = 'L'; + break; +#endif + default: + break; + } + *p = dp->conversion; +#if USE_SNPRINTF + p[1] = '%'; + p[2] = 'n'; + p[3] = '\0'; +#else + p[1] = '\0'; +#endif + + /* Construct the arguments for calling snprintf or sprintf. */ + prefix_count = 0; + if (dp->width_arg_index != ARG_NONE) + { + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; + } + if (dp->precision_arg_index != ARG_NONE) + { + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; + } + +#if USE_SNPRINTF + /* Prepare checking whether snprintf returns the count + via %n. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; +#endif + + for (;;) + { + size_t maxlen; + int count; + int retcount; + + maxlen = allocated - length; + count = -1; + retcount = 0; + +#if USE_SNPRINTF +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + arg, &count); \ + break; \ + case 1: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + prefixes[0], arg, &count); \ + break; \ + case 2: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + prefixes[0], prefixes[1], arg, \ + &count); \ + break; \ + default: \ + abort (); \ + } +#else +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + count = sprintf (tmp, buf, arg); \ + break; \ + case 1: \ + count = sprintf (tmp, buf, prefixes[0], arg); \ + break; \ + case 2: \ + count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ + arg); \ + break; \ + default: \ + abort (); \ + } +#endif + + switch (type) + { + case TYPE_SCHAR: + { + int arg = a.arg[dp->arg_index].a.a_schar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UCHAR: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uchar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_SHORT: + { + int arg = a.arg[dp->arg_index].a.a_short; + SNPRINTF_BUF (arg); + } + break; + case TYPE_USHORT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_ushort; + SNPRINTF_BUF (arg); + } + break; + case TYPE_INT: + { + int arg = a.arg[dp->arg_index].a.a_int; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UINT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGINT: + { + long int arg = a.arg[dp->arg_index].a.a_longint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGINT: + { + unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + { + long long int arg = a.arg[dp->arg_index].a.a_longlongint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGLONGINT: + { + unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_DOUBLE: + { + double arg = a.arg[dp->arg_index].a.a_double; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_CHAR: + { + int arg = a.arg[dp->arg_index].a.a_char; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: + { + wint_t arg = a.arg[dp->arg_index].a.a_wide_char; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_STRING: + { + const char *arg = a.arg[dp->arg_index].a.a_string; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + { + const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_POINTER: + { + void *arg = a.arg[dp->arg_index].a.a_pointer; + SNPRINTF_BUF (arg); + } + break; + default: + abort (); + } + +#if USE_SNPRINTF + /* Portability: Not all implementations of snprintf() + are ISO C 99 compliant. Determine the number of + bytes that snprintf() has produced or would have + produced. */ + if (count >= 0) + { + /* Verify that snprintf() has NUL-terminated its + result. */ + if (count < maxlen && result[length + count] != '\0') + abort (); + /* Portability hack. */ + if (retcount > count) + count = retcount; + } + else + { + /* snprintf() doesn't understand the '%n' + directive. */ + if (p[1] != '\0') + { + /* Don't use the '%n' directive; instead, look + at the snprintf() return value. */ + p[1] = '\0'; + continue; + } + else + { + /* Look at the snprintf() return value. */ + if (retcount < 0) + { + /* HP-UX 10.20 snprintf() is doubly deficient: + It doesn't understand the '%n' directive, + *and* it returns -1 (rather than the length + that would have been required) when the + buffer is too small. */ + size_t bigger_need = + xsum (xtimes (allocated, 2), 12); + ENSURE_ALLOCATION (bigger_need); + continue; + } + else + count = retcount; + } + } +#endif + + /* Attempt to handle failure. */ + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EINVAL; + return NULL; + } + +#if !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#endif + + /* Make room for the result. */ + if (count >= maxlen) + { + /* Need at least count bytes. But allocate + proportionally, to avoid looping eternally if + snprintf() reports a too small count. */ + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); +#if USE_SNPRINTF + continue; +#endif + } + +#if USE_SNPRINTF + /* The snprintf() result did fit. */ +#else + /* Append the sprintf() result. */ + memcpy (result + length, tmp, count * sizeof (CHAR_T)); + if (tmp != tmpbuf) + free (tmp); +#endif + + length += count; + break; + } + } + } + } + + /* Add the final NUL. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; + + if (result != resultbuf && length + 1 < allocated) + { + /* Shrink the allocated memory if possible. */ + CHAR_T *memory; + + memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); + if (memory != NULL) + result = memory; + } + + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + *lengthp = length; + return result; + + out_of_memory: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + out_of_memory_1: + CLEANUP (); + errno = ENOMEM; + return NULL; + } +} + +#undef SNPRINTF +#undef USE_SNPRINTF +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef VASNPRINTF diff --git a/intl/vasnprintf.h b/intl/vasnprintf.h new file mode 100644 index 000000000..65f1bc13d --- /dev/null +++ b/intl/vasnprintf.h @@ -0,0 +1,61 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _VASNPRINTF_H +#define _VASNPRINTF_H + +/* Get va_list. */ +#include <stdarg.h> + +/* Get size_t. */ +#include <stddef.h> + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + You can pass a preallocated buffer for the result in RESULTBUF and its + size in *LENGTHP; otherwise you pass RESULTBUF = NULL. + If successful, return the address of the string (this may be = RESULTBUF + if no dynamic memory allocation was necessary) and set *LENGTHP to the + number of resulting bytes, excluding the trailing NUL. Upon error, set + errno and return NULL. */ +extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 3, 0))); + +#ifdef __cplusplus +} +#endif + +#endif /* _VASNPRINTF_H */ diff --git a/intl/vasnwprintf.h b/intl/vasnwprintf.h new file mode 100644 index 000000000..d3cef4cbc --- /dev/null +++ b/intl/vasnwprintf.h @@ -0,0 +1,46 @@ +/* vswprintf with automatic memory allocation. + Copyright (C) 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _VASNWPRINTF_H +#define _VASNWPRINTF_H + +/* Get va_list. */ +#include <stdarg.h> + +/* Get wchar_t, size_t. */ +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + You can pass a preallocated buffer for the result in RESULTBUF and its + size in *LENGTHP; otherwise you pass RESULTBUF = NULL. + If successful, return the address of the string (this may be = RESULTBUF + if no dynamic memory allocation was necessary) and set *LENGTHP to the + number of resulting bytes, excluding the trailing NUL. Upon error, set + errno and return NULL. */ +extern wchar_t * asnwprintf (wchar_t *resultbuf, size_t *lengthp, const wchar_t *format, ...); +extern wchar_t * vasnwprintf (wchar_t *resultbuf, size_t *lengthp, const wchar_t *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* _VASNWPRINTF_H */ diff --git a/intl/wprintf-parse.h b/intl/wprintf-parse.h new file mode 100644 index 000000000..24a2cfc28 --- /dev/null +++ b/intl/wprintf-parse.h @@ -0,0 +1,75 @@ +/* Parse printf format string. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _WPRINTF_PARSE_H +#define _WPRINTF_PARSE_H + +#include "printf-args.h" + + +/* Flags */ +#define FLAG_GROUP 1 /* ' flag */ +#define FLAG_LEFT 2 /* - flag */ +#define FLAG_SHOWSIGN 4 /* + flag */ +#define FLAG_SPACE 8 /* space flag */ +#define FLAG_ALT 16 /* # flag */ +#define FLAG_ZERO 32 + +/* arg_index value indicating that no argument is consumed. */ +#define ARG_NONE (~(size_t)0) + +/* A parsed directive. */ +typedef struct +{ + const wchar_t* dir_start; + const wchar_t* dir_end; + int flags; + const wchar_t* width_start; + const wchar_t* width_end; + size_t width_arg_index; + const wchar_t* precision_start; + const wchar_t* precision_end; + size_t precision_arg_index; + wchar_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + size_t arg_index; +} +wchar_t_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + wchar_t_directive *dir; + size_t max_width_length; + size_t max_precision_length; +} +wchar_t_directives; + + +/* Parses the format string. Fills in the number N of directives, and fills + in directives[0], ..., directives[N-1], and sets directives[N].dir_start + to the end of the format string. Also fills in the arg_type fields of the + arguments and the needed count of arguments. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int wprintf_parse (const wchar_t *format, wchar_t_directives *d, arguments *a); + +#endif /* _WPRINTF_PARSE_H */ diff --git a/intl/xsize.h b/intl/xsize.h new file mode 100644 index 000000000..362e24b72 --- /dev/null +++ b/intl/xsize.h @@ -0,0 +1,109 @@ +/* xsize.h -- Checked size_t computations. + + Copyright (C) 2003 Free Software Foundation, Inc. + + This program 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, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _XSIZE_H +#define _XSIZE_H + +/* Get size_t. */ +#include <stddef.h> + +/* Get SIZE_MAX. */ +#include <limits.h> +#if HAVE_STDINT_H +# include <stdint.h> +#endif + +/* The size of memory objects is often computed through expressions of + type size_t. Example: + void* p = malloc (header_size + n * element_size). + These computations can lead to overflow. When this happens, malloc() + returns a piece of memory that is way too small, and the program then + crashes while attempting to fill the memory. + To avoid this, the functions and macros in this file check for overflow. + The convention is that SIZE_MAX represents overflow. + malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc + implementation that uses mmap --, it's recommended to use size_overflow_p() + or size_in_bounds_p() before invoking malloc(). + The example thus becomes: + size_t size = xsum (header_size, xtimes (n, element_size)); + void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); +*/ + +/* Convert an arbitrary value >= 0 to type size_t. */ +#define xcast_size_t(N) \ + ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) + +/* Sum of two sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum (size_t size1, size_t size2) +{ + size_t sum = size1 + size2; + return (sum >= size1 ? sum : SIZE_MAX); +} + +/* Sum of three sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum3 (size_t size1, size_t size2, size_t size3) +{ + return xsum (xsum (size1, size2), size3); +} + +/* Sum of four sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) +{ + return xsum (xsum (xsum (size1, size2), size3), size4); +} + +/* Maximum of two sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xmax (size_t size1, size_t size2) +{ + /* No explicit check is needed here, because for any n: + max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ + return (size1 >= size2 ? size1 : size2); +} + +/* Multiplication of a count with an element size, with overflow check. + The count must be >= 0 and the element size must be > 0. + This is a macro, not an inline function, so that it works correctly even + when N is of a wider tupe and N > SIZE_MAX. */ +#define xtimes(N, ELSIZE) \ + ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) + +/* Check for overflow. */ +#define size_overflow_p(SIZE) \ + ((SIZE) == SIZE_MAX) +/* Check against overflow. */ +#define size_in_bounds_p(SIZE) \ + ((SIZE) != SIZE_MAX) + +#endif /* _XSIZE_H */ diff --git a/m4/intmax.m4 b/m4/intmax.m4 new file mode 100644 index 000000000..dfb08ccc9 --- /dev/null +++ b/m4/intmax.m4 @@ -0,0 +1,32 @@ +# intmax.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([jm_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, + [AC_TRY_COMPILE([ +#include <stddef.h> +#include <stdlib.h> +#if HAVE_STDINT_H_WITH_UINTMAX +#include <stdint.h> +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include <inttypes.h> +#endif +], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.]) + fi +]) diff --git a/m4/longdouble.m4 b/m4/longdouble.m4 new file mode 100644 index 000000000..1333d2f57 --- /dev/null +++ b/m4/longdouble.m4 @@ -0,0 +1,30 @@ +# longdouble.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. +dnl Test whether the compiler supports the 'long double' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_LONGDOUBLE], +[ + AC_CACHE_CHECK([for long double], gt_cv_c_long_double, + [if test "$GCC" = yes; then + gt_cv_c_long_double=yes + else + AC_TRY_COMPILE([ + /* The Stardent Vistra knows sizeof(long double), but does not support it. */ + long double foo = 0.0; + /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ + int array [2*(sizeof(long double) >= sizeof(double)) - 1]; + ], , + gt_cv_c_long_double=yes, gt_cv_c_long_double=no) + fi]) + if test $gt_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) + fi +]) diff --git a/m4/longlong.m4 b/m4/longlong.m4 new file mode 100644 index 000000000..d7d7350b3 --- /dev/null +++ b/m4/longlong.m4 @@ -0,0 +1,25 @@ +# longlong.m4 serial 4 +dnl Copyright (C) 1999-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG if 'long long' works. + +AC_DEFUN([jm_AC_TYPE_LONG_LONG], +[ + AC_CACHE_CHECK([for long long], ac_cv_type_long_long, + [AC_TRY_LINK([long long ll = 1LL; int i = 63;], + [long long llmax = (long long) -1; + return ll << i | ll >> i | llmax / ll | llmax % ll;], + ac_cv_type_long_long=yes, + ac_cv_type_long_long=no)]) + if test $ac_cv_type_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, + [Define if you have the 'long long' type.]) + fi +]) diff --git a/m4/printf-posix.m4 b/m4/printf-posix.m4 new file mode 100644 index 000000000..186ba6a6d --- /dev/null +++ b/m4/printf-posix.m4 @@ -0,0 +1,46 @@ +# printf-posix.m4 serial 2 (gettext-0.13.1) +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. +dnl Test whether the printf() function supports POSIX/XSI format strings with +dnl positions. + +AC_DEFUN([gt_PRINTF_POSIX], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings], + gt_cv_func_printf_posix, + [ + AC_TRY_RUN([ +#include <stdio.h> +#include <string.h> +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, + [ + AC_EGREP_CPP(notposix, [ +#if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], gt_cv_func_printf_posix="guessing no", + gt_cv_func_printf_posix="guessing yes") + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE(HAVE_POSIX_PRINTF, 1, + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/m4/signed.m4 b/m4/signed.m4 new file mode 100644 index 000000000..dc1f54f10 --- /dev/null +++ b/m4/signed.m4 @@ -0,0 +1,19 @@ +# signed.m4 serial 1 (gettext-0.10.40) +dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([bh_C_SIGNED], +[ + AC_CACHE_CHECK([for signed], bh_cv_c_signed, + [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) + if test $bh_cv_c_signed = no; then + AC_DEFINE(signed, , + [Define to empty if the C compiler doesn't support this keyword.]) + fi +]) diff --git a/m4/size_max.m4 b/m4/size_max.m4 new file mode 100644 index 000000000..5762fc333 --- /dev/null +++ b/m4/size_max.m4 @@ -0,0 +1,61 @@ +# size_max.m4 serial 2 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS(stdint.h) + dnl First test whether the system already has SIZE_MAX. + AC_MSG_CHECKING([for SIZE_MAX]) + result= + AC_EGREP_CPP([Found it], [ +#include <limits.h> +#if HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef SIZE_MAX +Found it +#endif +], result=yes) + if test -z "$result"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. + dnl The _AC_COMPUTE_INT macro works up to LONG_MAX, since it uses 'expr', + dnl which is guaranteed to work from LONG_MIN to LONG_MAX. + _AC_COMPUTE_INT([~(size_t)0 / 10], res_hi, + [#include <stddef.h>], result=?) + _AC_COMPUTE_INT([~(size_t)0 % 10], res_lo, + [#include <stddef.h>], result=?) + _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, + [#include <stddef.h>], result=?) + if test "$fits_in_uint" = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include <stddef.h> + extern size_t foo; + extern unsigned long foo; + ], [], fits_in_uint=0) + fi + if test -z "$result"; then + if test "$fits_in_uint" = 1; then + result="$res_hi$res_lo"U + else + result="$res_hi$res_lo"UL + fi + else + dnl Shouldn't happen, but who knows... + result='~(size_t)0' + fi + fi + AC_MSG_RESULT([$result]) + if test "$result" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$result], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi +]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 new file mode 100644 index 000000000..d8fd1ec5c --- /dev/null +++ b/m4/wchar_t.m4 @@ -0,0 +1,22 @@ +# wchar_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. +dnl Test whether <stddef.h> has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, + [AC_TRY_COMPILE([#include <stddef.h> + wchar_t foo = (wchar_t)'\0';], , + gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/m4/wint_t.m4 b/m4/wint_t.m4 new file mode 100644 index 000000000..3d8d21594 --- /dev/null +++ b/m4/wint_t.m4 @@ -0,0 +1,22 @@ +# wint_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. +dnl Test whether <wchar.h> has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, + [AC_TRY_COMPILE([#include <wchar.h> + wint_t foo = (wchar_t)'\0';], , + gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/m4/xsize.m4 b/m4/xsize.m4 new file mode 100644 index 000000000..9b7cf9b49 --- /dev/null +++ b/m4/xsize.m4 @@ -0,0 +1,14 @@ +# xsize.m4 serial 2 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_CHECK_HEADERS(stdint.h) +]) diff --git a/scripts/ChangeLog b/scripts/ChangeLog new file mode 100644 index 000000000..e485a905e --- /dev/null +++ b/scripts/ChangeLog @@ -0,0 +1,377 @@ +2004-07-27 Werner Koch <wk@g10code.de> + + * autogen.sh: Updated to the moder version, grepping the required + tool versions from configure.ac. + +2004-06-14 Werner Koch <wk@gnupg.org> + + * mk-w32-dist: Do not include the en@* po files. + + * autogen.sh <--build-w32>: Build keyserver helpers again. + +2004-04-02 Thomas Schwinge <schwinge@nic-nac-project.de> + + * autogen.sh: Added ACLOCAL_FLAGS. + +2003-12-28 Stefan Bellon <sbellon@sbellon.de> + + * build-riscos, conf-riscos/*: Updated to reflect latest changes. + +2003-10-25 Werner Koch <wk@gnupg.org> + + * autogen.sh: Updated required versions and add -I m4 to aclocal. + +2003-08-28 David Shaw <dshaw@jabberwocky.com> + + * autogen.sh: Touch po/all for --build-w32. From Werner on stable + branch. + +2003-08-25 David Shaw <dshaw@jabberwocky.com> + + * gnupg.spec.in: Rework much of the spec to use %-macros + throughout. Fix to work properly with RPM 4.1 (all files in + buildroot must be packaged). Package and install info files. Tweak + the English description. Do not install gpgv and gpgsplit setuid + root. Make sure that install-info is called in such a way that + doesn't bork the RPM install if it cannot complete (necessary for + some upgrade scenarios). + +2003-05-26 David Shaw <dshaw@jabberwocky.com> + + * mk-w32-dist: Don't iconv {hu,sk,zh_TW}.po. (From wk on stable + branch) + +2003-04-08 Werner Koch <wk@gnupg.org> + + * autogen.sh: Add options to build for coldfire and uClinux. + +2003-02-22 David Shaw <dshaw@jabberwocky.com> + + * distfiles, gnupg.spec.in: convert-from-106 is in the tools + directory now. + + * convert-from-106: Move to the tools directory. + +2002-12-01 David Shaw <dshaw@jabberwocky.com> + + * distfiles, gnupg.spec.in: Include convert-from-106. + + * convert-from-106: Script to automate the 1.0.6->later + conversion. It marks all secret keys as ultimately trusted, adds + the signature caches, and checks the trustdb. + +2002-11-13 David Shaw <dshaw@jabberwocky.com> + + * mk-w32-dist: Don't use iconv for pl.po. From Werner on stable + branch. + + * mk-w32-dist: Include gpgkeys_ldap and gpgkeys_hkp. + +2002-11-12 Werner Koch <wk@gnupg.org> + + * config.sub, config.guess: Updated from ftp.gnu.org/gnu/config + to version 2002-11-08. + +2002-10-31 David Shaw <dshaw@jabberwocky.com> + + * gnupg.spec.in: Update source ftp path. + +2002-10-31 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/Makefile: Updated to reflect latest changes. + +2002-10-28 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/include/config.h: Updated to reflect latest changes. + +2002-10-26 David Shaw <dshaw@jabberwocky.com> + + * gnupg.spec.in: Use new path for keyserver helpers, /usr/lib is + no longer used for cipher/hash plugins, and include gpgv, + gpgsplit, and the new gnupg.7 man page. + +2002-10-17 Werner Koch <wk@gnupg.org> + + * autogen.sh: Allow env variables to override the auto* tool + names. Suggested by Simon Josefsson. + +2002-09-11 Werner Koch <wk@gnupg.org> + + * distfiles: Include mk-w32-dist. + + * mk-w32-dist: Convert the character sets on a per language base. + +2002-09-02 Werner Koch <wk@gnupg.org> + + * mk-w32-dist: Include more man pages and gpg split. Changed name + of ZIP file to better indicate that this is a command line version. + +2002-08-23 Werner Koch <wk@gnupg.org> + + * autogen.sh : Don't run gettextize. + +2002-08-06 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/include/config.h: Changed #define FOO to + #define FOO 1. + * conf-riscos/include/g10defs.h: Likewise. + +2002-08-03 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/include/g10defs.h: Added GNUPG_LIBEXECDIR. + * conf-riscos/include/config.h: Changes due to dynload removal and + minor changes to avoid some warnings. + * conf-riscos/Makefile: Changes due to dynload removal. + * conf-riscos/cipher/*: Not needed anymore due to dynload removal. + +2002-07-25 David Shaw <dshaw@jabberwocky.com> + + * gnupgbug: "Warning" -> "WARNING" + +2002-07-01 Werner Koch <wk@gnupg.org> + + * mk-gpg-texi: New. + +2002-06-30 Werner Koch <wk@gnupg.org> + + * mk-w32-dist (bindir): Fixes vor VPATH builds in a subdir, + include gpgv. + +2002-06-21 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/Makefile: Changes due to moving around RISC OS + specific stuff in the code. + +2002-06-07 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/include/config.h [__riscos__]: Fixed macro bug. + +2002-05-10 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/include/config.h [__riscos__]: Changes for later + Norcroft compilers. + + * conf-riscos/Makefile [__riscos__]: Updated. + +2002-04-22 Stefan Bellon <sbellon@sbellon.de> + + * conf-riscos/include/config.h [__riscos__]: Development + versions automatically define DEBUG from now on. + + * conf-riscos/Makefile [__riscos__]: Updated for LDAP keyserver + code. + +2002-04-19 David Shaw <dshaw@jabberwocky.com> + + * gnupg.spec.in: Removed pubring.asc and OPTIONS. Added + samplekeys.asc. + +2002-03-31 David Shaw <dshaw@jabberwocky.com> + + * gnupg.spec.in: Added the gpgkeys_xxx keyserver helpers. Added a + * to catch variations on the basic gpg man page (gpg, gpgv). Mark + options.skel as a config file. Do not include the FAQ/faq.html + twice (in /doc/ and /share/). + +2002-01-02 Stefan Bellon <sbellon@sbellon.de> + + * build-riscos [__riscos__]: Set filetype of Makefile correctly. + + * conf-riscos/include/g10defs.h [__riscos__]: Added GNU GPL + header and exec code defines. + + * conf-riscos/include/config.h [__riscos__]: Moved parts to + include/util.h where they really belong to. + + * conf-riscos/Makefile [__riscos__]: Updated for new keyserver, + exec and photo id code. + +2001-12-22 Werner Koch <wk@gnupg.org> + + * autogen.sh: Fixed last change. + +2001-12-21 Werner Koch <wk@gnupg.org> + + * distfiles: Removed those files which which automake installs by + default. + + * autogen.sh: Replaced $() by backticks for system without a posix + shell. Removed gawk specific quoting. By David Champion. + +2001-10-22 Werner Koch <wk@gnupg.org> + + * autogen.sh (aclocal_vers): Require automalke 1.5. + +2001-08-21 Stefan Bellon <sbellon@sbellon.de> + + * build-riscos [__riscos__]: New. + * conf-riscos [__riscos__]: Ditto. + +2001-08-13 Werner Koch <wk@gnupg.org> + + * autogen.sh: Test on gettext 0.10.38. By Michael Engels. + +2001-08-07 Werner Koch <wk@gnupg.org> + + * autogen.sh: Adjusted --build-w32 for autoconf 2.52 + +2001-07-09 Werner Koch <wk@gnupg.org> + + * autogen.sh (autoconf_vers): Require autoconf 2.50 + +2001-05-06 Werner Koch <wk@gnupg.org> + + * config.guess, config.sub: Add updates from subversions.gnu.org. + +2001-04-19 Werner Koch <wk@gnupg.org> + + * autogen.sh: Add VPATH build support for option --build-w32. + +2001-03-12 Werner Koch <wk@gnupg.org> + + * config.guess, config.sub: Replaced with the current GNU CVS ones. + +2001-01-18 Werner Koch <wk@gnupg.org> + + * autogen.sh: New options --build-w32 + * build-w32: Does now call autogen.sh + +2000-11-24 Werner Koch <wk@gnupg.org> + + * build-w32: New script to build the W32 version. + * distfiles: And put it into the distribution + +Thu Sep 14 17:45:11 CEST 2000 Werner Koch <wk@openit.de> + + * gnupg.spec.in: Updated. + +Wed Sep 6 17:55:47 CEST 2000 Werner Koch <wk@openit.de> + + * config.guess, config.sub: Replaced with the latest version from the + CVS archive. Hope that does not break too much. + +Fri May 12 14:01:20 CEST 2000 Werner Koch <wk@openit.de> + + * gnupg.spec.in: New version from Fabio with some updated descriptions. + +Mon May 1 15:38:04 CEST 2000 Werner Koch <wk@openit.de> + + * gnupg.spec.in: New version from Fabio. + +Fri Mar 17 16:26:05 CET 2000 Werner Koch <wk@openit.de> + + * config.gues, config.sub: Support for s390-ibm-linux-gnu. Thanks + to Holger Smolinski. + +Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de> + + * config.guess: Add support for QNX. By Sam Roberts. + * config.sub: Ditto. + +Thu Sep 23 09:49:25 1999 Werner Koch (wk@gnupg.org) + + * commit: Remove leading and trailing empty lines when copying + Changes to Changelog + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * gnupg.spec: Add Portuguese description + +Thu Sep 2 16:40:55 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mkdiff: changed format of diff file name and made script more + general. + +Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.guess: Updated from gnu/common and applied my emx patch again. + * config.sub: Updated from gnu/common. + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * ltmain.sh, ltconfig.sh : Updated to libtool 1.3.3 + +Mon Jul 12 14:55:34 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * autogen.sh: Run libtoolize + +Sat May 22 22:47:26 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * autogen.sh: Fixed the error message for a missing libtool. + +Sat May 8 19:28:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mkinstalldirs, install-sh: New from GNU repository + * config.sub, config.guess: Merged with rep version. + +Sun Mar 14 19:34:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * autogen.sh: Add a check for libtool because some autoconf macros + are needed. + +Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * autogen.sh: Enhanced the version testing code (Philippe Laliberte) + + * mkwebpage: Edits the buglist. + +Sat Feb 13 12:04:43 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * autogen.sh: Now uses gettextize + +Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.sub, config.guess: Support i386-emx-os2 + +Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * autogen.sh: Now checks for installed gettext + +Sat Jan 16 09:27:30 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.guess (m68k-atari-mint): New. + * config.sub: Add support for atarist-MiNT + +Wed Jan 13 12:49:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * gnupg.spec.in: New + * gnupg.spec: Removed + +Wed Dec 23 13:18:14 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * gnupg.spec: Updated version by Fabio Coatti + +Thu Dec 17 18:31:15 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * gnupg.spec: New version by Reuben Sumner and did some more + changes. + +Fri Nov 27 12:39:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + + * commit: New + + +Fri Nov 20 12:01:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mkdiff: signs the patch file + +Sat Oct 17 16:10:16 1998 Werner Koch (wk@isil.d.shuttle.de) + + * autogen.sh: New. + +Wed Oct 14 09:55:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.guess (FreeBSD): Changes from Jun Kuriyama to support ELF + * config.sub: (freebsd): Add to maybe_os + + + Copyright 1998, 1999, 2000, 2001, 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. -- cgit v1.2.3 From 335b5e4ac4d1ab56bb9db5addc4f7ca6ce8987f6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 30 Sep 2004 14:34:34 +0000 Subject: Preparing a new release. Updated gettext --- ABOUT-NLS | 989 +++++++++++++++++++++++++++++---------------------- ChangeLog | 8 + README | 8 +- agent/ChangeLog | 4 + agent/Makefile.am | 4 +- configure.ac | 5 +- g10/ChangeLog | 4 + g10/Makefile.am | 2 +- intl/ChangeLog | 4 +- intl/Makefile.in | 24 +- intl/VERSION | 2 +- intl/bindtextdom.c | 21 +- intl/config.charset | 285 +++++++++++---- intl/dcgettext.c | 7 +- intl/dcigettext.c | 75 ++-- intl/dcngettext.c | 11 +- intl/dgettext.c | 9 +- intl/dngettext.c | 12 +- intl/eval-plural.h | 10 +- intl/explodename.c | 21 +- intl/finddomain.c | 9 +- intl/gettext.c | 5 +- intl/gettextP.h | 91 +++-- intl/gmo.h | 5 +- intl/hash-string.h | 17 +- intl/intl-compat.c | 44 +-- intl/l10nflist.c | 62 +--- intl/libgnuintl.h.in | 146 ++++++-- intl/loadinfo.h | 47 +-- intl/loadmsgcat.c | 386 ++++++++++++-------- intl/localcharset.c | 2 +- intl/locale.alias | 12 +- intl/localealias.c | 29 +- intl/localename.c | 478 ++++++++++++++++++++++--- intl/log.c | 12 +- intl/ngettext.c | 7 +- intl/plural-exp.c | 8 +- intl/plural-exp.h | 24 +- intl/plural.c | 82 ++--- intl/plural.y | 52 +-- intl/relocatable.c | 14 +- intl/relocatable.h | 10 + intl/textdomain.c | 5 +- kbx/ChangeLog | 4 + kbx/Makefile.am | 2 +- m4/ChangeLog | 22 ++ m4/Makefile.am | 2 +- m4/gettext.m4 | 80 ++++- m4/gpg-error.m4 | 2 +- m4/lib-ld.m4 | 24 +- m4/lib-prefix.m4 | 4 +- m4/libassuan.m4 | 2 +- m4/libgcrypt.m4 | 2 +- m4/po.m4 | 241 ++++++++++++- m4/ulonglong.m4 | 10 +- po/ChangeLog | 5 + po/Makefile.in.in | 25 +- po/Rules-quot | 5 + scd/ChangeLog | 2 + scd/Makefile.am | 6 +- scd/apdu.c | 44 ++- scd/apdu.h | 1 + scd/ccid-driver.c | 914 ++++++++++++++++++++++++++++++++++------------- scd/ccid-driver.h | 5 +- scripts/ChangeLog | 371 +------------------ scripts/config.guess | 370 ++++++++++++------- scripts/config.rpath | 8 +- scripts/config.sub | 259 ++++++++++---- sm/ChangeLog | 2 + sm/Makefile.am | 4 +- tests/ChangeLog | 5 + tests/Makefile.am | 14 +- tools/ChangeLog | 4 + tools/Makefile.am | 2 +- 74 files changed, 3419 insertions(+), 2074 deletions(-) diff --git a/ABOUT-NLS b/ABOUT-NLS index 47d5e39f0..2f50c6693 100644 --- a/ABOUT-NLS +++ b/ABOUT-NLS @@ -1,8 +1,8 @@ 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 +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. @@ -25,7 +25,7 @@ related to internationalization, you should tell about the version of Quick configuration advice ========================== - If you want to exploit the full power of internationalization, you +If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext @@ -48,10 +48,10 @@ 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'. +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 @@ -98,7 +98,7 @@ codes, stating which languages are allowed. Using This Package ================== - As a user, if your language has been installed for this package, you +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 @@ -131,6 +131,13 @@ 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'. + Special advice for Norwegian users: The language code for Norwegian +bokma*l changed from `no' to `nb' recently (in 2003). During the +transition period, while some message catalogs for this language are +installed under `nb' and some older ones under `no', it's recommended +for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and +older translations are used. + 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 @@ -140,7 +147,7 @@ to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' Translating Teams ================= - For the Free Translation Project to be a success, we need interested +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 @@ -170,423 +177,559 @@ 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 +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of January +2004. 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 + Ready PO files af am ar az be bg bs ca cs da de el en en_GB eo es + +----------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | () | + ant-phone | () | + anubis | | + ap-utils | | + aspell | [] | + bash | [] [] [] [] | + batchelor | | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] | + bluez-pin | [] [] [] | + clisp | | + clisp | [] [] [] | + console-tools | [] [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + darkstat | [] () [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] [] | + error | [] [] [] [] [] | + fetchmail | [] () [] [] [] [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] [] [] | + flex | [] [] [] [] | + fslint | | + gas | [] | + gawk | [] [] [] [] | + gbiff | [] | + gcal | [] | + gcc | [] [] | + gettext | [] [] [] [] [] | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] [] | + gimp-print | [] [] [] [] [] | + gliv | | + glunarclock | [] [] | + gnubiff | [] | + gnucash | [] () [] [] | + gnucash-glossary | [] () [] | + gnupg | [] () [] [] [] [] | + gpe-aerial | [] | + gpe-beam | [] [] | + gpe-calendar | [] [] | + gpe-clock | [] [] | + gpe-conf | [] [] | + gpe-contacts | [] [] | + gpe-edit | [] | + gpe-go | [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] | + gpe-taskmanager | [] [] | + gpe-timesheet | [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] | + gpsdrive | () () () | + gramadoir | [] | + grep | [] [] [] [] [] [] | + gretl | [] | + gtick | [] () | + hello | [] [] [] [] [] [] | + id-utils | [] [] | + indent | [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] | + iso_3166_1 | [] [] [] [] [] [] | + iso_3166_2 | | + iso_3166_3 | [] | + iso_4217 | [] [] [] [] | + iso_639 | | + jpilot | [] [] [] | + jtag | | + jwhois | [] | + kbd | [] [] [] [] [] | + latrine | () | + ld | [] [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] [] | + libiconv | [] [] [] [] [] | + lifelines | [] () | + lilypond | [] | + lingoteach | | + lingoteach_lessons | () () | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | [] [] | + make | [] [] [] | + man-db | [] () [] [] () | + minicom | [] [] [] | + mysecretdiary | [] [] [] | + nano | [] () [] [] [] | + nano_1_0 | [] () [] [] [] | + opcodes | [] | + parted | [] [] [] [] [] | + ptx | [] [] [] [] [] | + python | | + radius | [] | + recode | [] [] [] [] [] [] [] | + rpm | [] [] | + screem | | + scrollkeeper | [] [] [] [] [] [] | + sed | [] [] [] [] [] [] | + sh-utils | [] [] [] | + shared-mime-info | | + sharutils | [] [] [] [] [] [] | + silky | () | + skencil | [] () [] | + sketch | [] () [] | + soundtracker | [] [] [] | + sp | [] | + tar | [] [] [] [] | + texinfo | [] [] [] | + textutils | [] [] [] [] | + tin | () () | + tp-robot | | + tuxpaint | [] [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] [] [] | + vorbis-tools | [] [] [] [] | + wastesedge | () | + wdiff | [] [] [] [] | + wget | [] [] [] [] [] [] | + xchat | [] [] [] [] | + xfree86_xkb_xml | [] [] | + xpad | [] | + +----------------------------------------------------+ + af am ar az be bg bs ca cs da de el en en_GB eo es + 4 0 0 1 9 4 1 40 41 60 78 17 1 5 13 68 - 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 + et eu fa fi fr ga gl he hr hu id is it ja ko lg + +-------------------------------------------------+ + a2ps | [] [] [] () () | + aegis | | + ant-phone | [] | + anubis | [] | + ap-utils | [] | + aspell | [] [] | + bash | [] [] | + batchelor | [] [] | + bfd | [] | + binutils | [] [] | + bison | [] [] [] [] | + bluez-pin | [] [] [] [] [] | + clisp | | + clisp | [] | + console-tools | | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] [] | + darkstat | () [] [] [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | | + enscript | [] [] | + error | [] [] [] [] | + fetchmail | [] | + fileutils | [] [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] [] [] [] | + flex | [] [] [] | + fslint | [] | + gas | [] | + gawk | [] [] [] | + gbiff | [] | + gcal | [] | + gcc | [] | + gettext | [] [] [] | + gettext-examples | [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] [] | + gimp-print | [] [] | + gliv | () | + glunarclock | [] [] [] [] | + gnubiff | [] | + gnucash | () [] | + gnucash-glossary | [] | + gnupg | [] [] [] [] [] [] [] | + gpe-aerial | [] | + gpe-beam | [] | + gpe-calendar | [] [] [] | + gpe-clock | [] | + gpe-conf | [] | + gpe-contacts | [] [] | + gpe-edit | [] [] | + gpe-go | [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] | + gpe-sketchbook | [] | + gpe-su | [] | + gpe-taskmanager | [] | + gpe-timesheet | [] [] [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | [] [] [] | + gprof | [] [] | + gpsdrive | () () () | + gramadoir | [] [] | + grep | [] [] [] [] [] [] [] [] [] [] [] | + gretl | [] [] | + gtick | [] [] [] | + hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] [] | + indent | [] [] [] [] [] [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] | + iso_3166_1 | [] [] [] [] [] | + iso_3166_2 | | + iso_3166_3 | | + iso_4217 | [] [] [] [] [] [] | + iso_639 | | + jpilot | [] () | + jtag | [] | + jwhois | [] [] [] [] | + kbd | [] | + latrine | [] | + ld | [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] [] [] [] | + libiconv | [] [] [] [] [] [] [] [] [] | + lifelines | () | + lilypond | [] | + lingoteach | [] [] | + lingoteach_lessons | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | | + make | [] [] [] [] [] [] | + man-db | () () | + minicom | [] [] [] [] | + mysecretdiary | [] [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] | + opcodes | [] | + parted | [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + radius | [] | + recode | [] [] [] [] [] [] | + rpm | [] [] | + screem | | + scrollkeeper | [] | + sed | [] [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] [] [] [] | + shared-mime-info | [] [] [] | + sharutils | [] [] [] [] [] | + silky | () [] () () | + skencil | [] | + sketch | [] | + soundtracker | [] [] | + sp | [] () | + tar | [] [] [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] [] [] [] [] | + tin | [] () | + tp-robot | [] | + tuxpaint | [] [] [] [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux | [] [] [] [] () [] | + vorbis-tools | [] | + wastesedge | () | + wdiff | [] [] [] [] [] [] | + wget | [] [] [] [] [] [] [] | + xchat | [] [] [] | + xfree86_xkb_xml | [] [] | + xpad | [] [] | + +-------------------------------------------------+ + et eu fa fi fr ga gl he hr hu id is it ja ko lg + 22 2 1 26 106 28 24 8 10 41 33 1 26 33 12 0 - 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 + lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru + +-----------------------------------------------------+ + a2ps | [] [] () () [] [] [] | + aegis | () () () | + ant-phone | [] [] | + anubis | [] [] [] [] [] [] | + ap-utils | [] () [] | + aspell | [] | + bash | [] [] [] | + batchelor | [] | + bfd | [] | + binutils | [] | + bison | [] [] [] [] [] | + bluez-pin | [] [] [] | + clisp | | + clisp | [] | + console-tools | [] | + coreutils | [] [] | + cpio | [] [] [] [] [] | + darkstat | [] [] [] [] | + diffutils | [] [] [] [] [] [] | + e2fsprogs | [] | + enscript | [] [] [] [] | + error | [] [] [] | + fetchmail | [] [] () [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] | + fslint | [] [] | + gas | | + gawk | [] [] [] | + gbiff | [] [] | + gcal | | + gcc | | + gettext | [] [] [] | + gettext-examples | [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] [] | + gimp-print | [] | + gliv | [] [] [] | + glunarclock | [] [] [] [] | + gnubiff | [] | + gnucash | [] [] () [] | + gnucash-glossary | [] [] | + gnupg | [] | + gpe-aerial | [] [] [] [] | + gpe-beam | [] [] [] [] | + gpe-calendar | [] [] [] [] | + gpe-clock | [] [] [] [] | + gpe-conf | [] [] [] [] | + gpe-contacts | [] [] [] [] | + gpe-edit | [] [] [] [] | + gpe-go | [] [] [] | + gpe-login | [] [] [] [] | + gpe-ownerinfo | [] [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] | + gpe-taskmanager | [] [] [] [] | + gpe-timesheet | [] [] [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] [] [] | + gphoto2 | [] | + gprof | [] [] | + gpsdrive | () () [] | + gramadoir | () [] | + grep | [] [] [] [] [] | + gretl | | + gtick | [] [] [] | + hello | [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] [] | + indent | [] [] [] [] | + iso_3166 | [] [] [] | + iso_3166_1 | [] [] | + iso_3166_2 | | + iso_3166_3 | [] | + iso_4217 | [] [] [] [] [] [] [] [] | + iso_639 | [] | + jpilot | () () | + jtag | | + jwhois | [] [] [] [] () | + kbd | [] [] [] | + latrine | [] | + ld | | + libc | [] [] [] [] | + libgpewidget | [] [] [] | + libiconv | [] [] [] [] [] | + lifelines | | + lilypond | | + lingoteach | | + lingoteach_lessons | | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailutils | [] [] [] | + make | [] [] [] [] | + man-db | [] | + minicom | [] [] [] [] | + mysecretdiary | [] [] [] | + nano | [] [] [] [] [] | + nano_1_0 | [] [] [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] | + ptx | [] [] [] [] [] [] [] [] | + python | | + radius | [] [] | + recode | [] [] [] [] | + rpm | [] [] [] | + screem | | + scrollkeeper | [] [] [] [] [] | + sed | [] [] [] | + sh-utils | [] [] | + shared-mime-info | [] [] | + sharutils | [] [] | + silky | () | + skencil | [] [] | + sketch | [] [] | + soundtracker | | + sp | | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] | + tin | | + tp-robot | [] | + tuxpaint | [] [] [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] | + vorbis-tools | [] [] [] | + wastesedge | | + wdiff | [] [] [] [] [] | + wget | [] [] [] | + xchat | [] [] [] | + xfree86_xkb_xml | [] [] | + xpad | [] [] | + +-----------------------------------------------------+ + lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru + 1 2 0 3 12 0 10 69 6 7 1 40 26 36 76 63 - 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 + sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu + +-----------------------------------------------------+ + a2ps | [] [] [] [] | 16 + aegis | | 0 + ant-phone | | 3 + anubis | [] [] | 9 + ap-utils | () | 3 + aspell | | 4 + bash | | 9 + batchelor | | 3 + bfd | [] [] | 6 + binutils | [] [] [] | 8 + bison | [] [] | 14 + bluez-pin | [] [] [] | 14 + clisp | | 0 + clisp | | 5 + console-tools | | 3 + coreutils | [] [] [] [] | 16 + cpio | [] [] | 14 + darkstat | [] [] [] () () | 12 + diffutils | [] [] [] | 23 + e2fsprogs | [] [] | 6 + enscript | [] [] | 12 + error | [] [] [] | 15 + fetchmail | [] [] | 11 + fileutils | [] [] [] [] [] | 17 + findutils | [] [] [] [] [] [] | 29 + flex | [] [] | 13 + fslint | | 3 + gas | [] | 3 + gawk | [] [] | 12 + gbiff | | 4 + gcal | [] [] | 4 + gcc | [] | 4 + gettext | [] [] [] [] [] | 16 + gettext-examples | [] [] [] [] [] | 14 + gettext-runtime | [] [] [] [] [] [] [] [] | 22 + gettext-tools | [] [] [] [] [] [] | 14 + gimp-print | [] [] | 10 + gliv | | 3 + glunarclock | [] [] [] | 13 + gnubiff | | 3 + gnucash | [] [] | 9 + gnucash-glossary | [] [] [] | 8 + gnupg | [] [] [] [] | 17 + gpe-aerial | [] | 7 + gpe-beam | [] | 8 + gpe-calendar | [] [] [] [] | 13 + gpe-clock | [] [] [] | 10 + gpe-conf | [] [] | 9 + gpe-contacts | [] [] [] | 11 + gpe-edit | [] [] [] [] [] | 12 + gpe-go | | 5 + gpe-login | [] [] [] [] [] | 13 + gpe-ownerinfo | [] [] [] [] | 13 + gpe-sketchbook | [] [] | 9 + gpe-su | [] [] [] | 10 + gpe-taskmanager | [] [] [] | 10 + gpe-timesheet | [] [] [] [] | 12 + gpe-today | [] [] [] [] [] | 13 + gpe-todo | [] [] [] [] | 12 + gphoto2 | [] [] [] | 11 + gprof | [] [] | 9 + gpsdrive | [] [] | 3 + gramadoir | [] | 5 + grep | [] [] [] [] | 26 + gretl | | 3 + gtick | | 7 + hello | [] [] [] [] [] | 34 + id-utils | [] [] | 12 + indent | [] [] [] [] | 21 + iso_3166 | [] [] [] [] [] [] [] | 27 + iso_3166_1 | [] [] [] | 16 + iso_3166_2 | | 0 + iso_3166_3 | | 2 + iso_4217 | [] [] [] [] [] [] | 24 + iso_639 | | 1 + jpilot | [] [] [] [] [] | 9 + jtag | [] | 2 + jwhois | () [] [] | 11 + kbd | [] [] | 11 + latrine | | 2 + ld | [] [] | 5 + libc | [] [] [] [] | 20 + libgpewidget | [] [] [] [] | 13 + libiconv | [] [] [] [] [] [] [] [] | 27 + lifelines | [] | 2 + lilypond | [] | 3 + lingoteach | | 2 + lingoteach_lessons | () | 0 + lynx | [] [] [] | 14 + m4 | [] [] | 15 + mailutils | | 5 + make | [] [] [] | 16 + man-db | [] | 5 + minicom | | 11 + mysecretdiary | [] [] | 10 + nano | [] [] [] [] | 17 + nano_1_0 | [] [] [] | 17 + opcodes | [] [] | 6 + parted | [] [] [] | 15 + ptx | [] [] | 22 + python | | 0 + radius | | 4 + recode | [] [] [] | 20 + rpm | [] [] | 9 + screem | [] [] | 2 + scrollkeeper | [] [] [] | 15 + sed | [] [] [] [] [] [] | 24 + sh-utils | [] [] | 14 + shared-mime-info | [] [] | 7 + sharutils | [] [] [] [] | 17 + silky | () | 3 + skencil | [] | 6 + sketch | [] | 6 + soundtracker | [] [] | 7 + sp | [] | 3 + tar | [] [] [] [] [] | 24 + texinfo | [] [] [] | 14 + textutils | [] [] [] [] | 16 + tin | | 1 + tp-robot | | 2 + tuxpaint | [] [] [] [] [] | 29 + unicode-han-tra... | | 0 + unicode-transla... | | 2 + util-linux | [] [] | 15 + vorbis-tools | | 8 + wastesedge | | 0 + wdiff | [] [] [] | 18 + wget | [] [] [] [] [] [] [] [] | 24 + xchat | [] [] [] [] [] | 15 + xfree86_xkb_xml | [] [] [] [] [] | 11 + xpad | | 5 + +-----------------------------------------------------+ + 63 teams sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu + 131 domains 47 19 28 83 0 0 59 13 1 1 11 0 22 22 0 1373 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 @@ -599,7 +742,7 @@ 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 + If January 2004 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'. @@ -607,7 +750,7 @@ matrix with full percentage details can be found at Using `gettext' in new packages =============================== - If you are writing a freely available program and want to +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 diff --git a/ChangeLog b/ChangeLog index 86bd01bff..bb7379bf1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * README: Minor updates. + +2004-09-30 gettextize <bug-gnu-gettext@gnu.org> + + * configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.14.1. + 2004-08-16 Werner Koch <wk@g10code.de> * configure.ac: Build Makefile for tests/pkits. New option diff --git a/README b/README index 8027b6960..c08c16af1 100644 --- a/README +++ b/README @@ -19,8 +19,8 @@ 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/) + libgpg-error (ftp://ftp.gnupg.org/gcrypt/libgpg-error/) + libgcrypt (ftp://ftp.gnupg.org/gcrypt/libgcrypt/) libassuan (ftp://ftp.gnupg.org/gcrypt/alpha/libassuan/) libksba (ftp://ftp.gnupg.org/gcrypt/alpha/libksba/) @@ -470,9 +470,9 @@ This requires 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. +format. However there is no MAC applied. - gpgsm --call-protect-tool --p12-export foo.key >foo.p12 + gpgsm --export-secret-key-p12 userIDey >foo.p12 SMARTCARD INTRO diff --git a/agent/ChangeLog b/agent/ChangeLog index f72bd50c9..b65e7b1de 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * Makefile.am: Adjusted from gettext 1.14. + 2004-09-29 Werner Koch <wk@g10code.com> * minip12.c (parse_bag_encrypted_data): Print error if a bad diff --git a/agent/Makefile.am b/agent/Makefile.am index e83311fb4..6f3ea70d2 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -46,7 +46,7 @@ gpg_agent_SOURCES = \ gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ - -lgpg-error @INTLLIBS@ + -lgpg-error @LIBINTL@ gpg_protect_tool_SOURCES = \ protect-tool.c \ @@ -55,6 +55,6 @@ gpg_protect_tool_SOURCES = \ gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \ ../common/libcommon.a ../common/libsimple-pwquery.a \ - $(LIBGCRYPT_LIBS) -lgpg-error @INTLLIBS@ + $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ diff --git a/configure.ac b/configure.ac index d04475f6b..bce1555b0 100644 --- a/configure.ac +++ b/configure.ac @@ -685,7 +685,7 @@ AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", [A human readable text with the name of the OS]) -AM_GNU_GETTEXT_VERSION(0.12.1) +AM_GNU_GETTEXT_VERSION(0.14.1) if test "$try_gettext" = yes; then AM_GNU_GETTEXT(,[need-ngettext]) @@ -1129,10 +1129,11 @@ scd/Makefile tools/Makefile doc/Makefile tests/Makefile -tests/pkits/Makefile ]) AC_OUTPUT +#tests/pkits/Makefile + diff --git a/g10/ChangeLog b/g10/ChangeLog index b553c1c9f..187d8584b 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * Makefile.am (LDADD): Adjusted for gettext 0.14. + 2004-09-20 Werner Koch <wk@g10code.com> * keyedit.c (show_key_with_all_names): Print the card S/N. diff --git a/g10/Makefile.am b/g10/Makefile.am index 53d748ee0..aa7833fb9 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -108,7 +108,7 @@ gpgv2_SOURCES = gpgv.c \ # ks-db.h \ # $(common_source) -LDADD = $(needed_libs) @INTLLIBS@ @CAPLIBS@ @ZLIBS@ @W32LIBS@ +LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @ZLIBS@ @W32LIBS@ gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error diff --git a/intl/ChangeLog b/intl/ChangeLog index eed2d21a4..751291929 100644 --- a/intl/ChangeLog +++ b/intl/ChangeLog @@ -1,4 +1,4 @@ -2003-05-22 GNU <bug-gnu-gettext@gnu.org> +2004-01-29 GNU <bug-gnu-gettext@gnu.org> - * Version 0.12.1 released. + * Version 0.14.1 released. diff --git a/intl/Makefile.in b/intl/Makefile.in index 882396481..05f15329e 100644 --- a/intl/Makefile.in +++ b/intl/Makefile.in @@ -73,6 +73,10 @@ HEADERS = \ eval-plural.h \ localcharset.h \ relocatable.h \ + xsize.h \ + printf-args.h printf-args.c \ + printf-parse.h wprintf-parse.h printf-parse.c \ + vasnprintf.h vasnwprintf.h vasnprintf.c \ os2compat.h \ libgnuintl.h.in SOURCES = \ @@ -96,6 +100,7 @@ SOURCES = \ relocatable.c \ localename.c \ log.c \ + printf.c \ osdep.c \ os2compat.c \ intl-compat.c @@ -120,6 +125,7 @@ OBJECTS = \ relocatable.$lo \ localename.$lo \ log.$lo \ + printf.$lo \ osdep.$lo \ intl-compat.$lo DISTFILES.common = Makefile.in \ @@ -127,7 +133,8 @@ config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) DISTFILES.generated = plural.c DISTFILES.normal = VERSION DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc \ -Makefile.vms libgnuintl.h.msvc-shared README.woe32 Makefile.msvc +libgnuintl.h_vms Makefile.vms \ +libgnuintl.h.msvc-static libgnuintl.h.msvc-shared README.woe32 Makefile.msvc DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \ COPYING.LIB-2 gettext.h libgettext.h plural-eval.c libgnuintl.h @@ -155,9 +162,9 @@ libintl.la libgnuintl.la: $(OBJECTS) # according to the libtool documentation, section "Library interface versions". # Maintainers of other packages that include the intl directory must *not* # change these values. -LTV_CURRENT=5 +LTV_CURRENT=7 LTV_REVISION=0 -LTV_AGE=3 +LTV_AGE=4 .SUFFIXES: .SUFFIXES: .c .y .o .lo .sin .sed @@ -209,6 +216,8 @@ localename.lo: $(srcdir)/localename.c $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c log.lo: $(srcdir)/log.c $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c +printf.lo: $(srcdir)/printf.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/printf.c osdep.lo: $(srcdir)/osdep.c $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c intl-compat.lo: $(srcdir)/intl-compat.c @@ -224,7 +233,11 @@ ref-del.sed: $(srcdir)/ref-del.sin INCLUDES = -I. -I$(srcdir) -I.. libgnuintl.h: $(srcdir)/libgnuintl.h.in - cp $(srcdir)/libgnuintl.h.in libgnuintl.h + sed -e 's,@''HAVE_POSIX_PRINTF''@,@HAVE_POSIX_PRINTF@,g' \ + -e 's,@''HAVE_ASPRINTF''@,@HAVE_ASPRINTF@,g' \ + -e 's,@''HAVE_SNPRINTF''@,@HAVE_SNPRINTF@,g' \ + -e 's,@''HAVE_WPRINTF''@,@HAVE_WPRINTF@,g' \ + < $(srcdir)/libgnuintl.h.in > libgnuintl.h libintl.h: libgnuintl.h cp libgnuintl.h libintl.h @@ -250,7 +263,7 @@ install-exec: all $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \ if test "@RELOCATABLE@" = yes; then \ dependencies=`sed -n -e 's,^dependency_libs=\(.*\),\1,p' < $(DESTDIR)$(libdir)/libintl.la | sed -e "s,^',," -e "s,'\$$,,"`; \ - if test -n "$dependencies"; then \ + if test -n "$$dependencies"; then \ rm -f $(DESTDIR)$(libdir)/libintl.la; \ fi; \ fi; \ @@ -412,6 +425,7 @@ dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.h dcigettext.$lo: $(srcdir)/eval-plural.h localcharset.$lo: $(srcdir)/localcharset.h localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h +printf.$lo: $(srcdir)/printf-args.h $(srcdir)/printf-args.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/xsize.h $(srcdir)/printf-parse.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/vasnprintf.c tags: TAGS diff --git a/intl/VERSION b/intl/VERSION index 130318357..b4b846ca7 100644 --- a/intl/VERSION +++ b/intl/VERSION @@ -1 +1 @@ -GNU gettext library from gettext-0.12.1 +GNU gettext library from gettext-0.14.1 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c index 250f5e863..dcdc40085 100644 --- a/intl/bindtextdom.c +++ b/intl/bindtextdom.c @@ -1,5 +1,5 @@ /* Implementation of the bindtextdomain(3) function - Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -86,11 +86,6 @@ __libc_rwlock_define (extern, _nl_state_lock attribute_hidden) # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset #endif -/* Prototypes for local functions. */ -static void set_binding_values PARAMS ((const char *domainname, - const char **dirnamep, - const char **codesetp)); - /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP to be used for the DOMAINNAME message catalog. If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not @@ -98,10 +93,8 @@ static void set_binding_values PARAMS ((const char *domainname, If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither modified nor returned. */ static void -set_binding_values (domainname, dirnamep, codesetp) - const char *domainname; - const char **dirnamep; - const char **codesetp; +set_binding_values (const char *domainname, + const char **dirnamep, const char **codesetp) { struct binding *binding; int modified; @@ -348,9 +341,7 @@ set_binding_values (domainname, dirnamep, codesetp) /* Specify that the DOMAINNAME message catalog will be found in DIRNAME rather than in the system locale data base. */ char * -BINDTEXTDOMAIN (domainname, dirname) - const char *domainname; - const char *dirname; +BINDTEXTDOMAIN (const char *domainname, const char *dirname) { set_binding_values (domainname, &dirname, NULL); return (char *) dirname; @@ -359,9 +350,7 @@ BINDTEXTDOMAIN (domainname, dirname) /* Specify the character encoding in which the messages from the DOMAINNAME message catalog will be returned. */ char * -BIND_TEXTDOMAIN_CODESET (domainname, codeset) - const char *domainname; - const char *codeset; +BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset) { set_binding_values (domainname, NULL, &codeset); return (char *) codeset; diff --git a/intl/config.charset b/intl/config.charset index 32becece9..43d45fb75 100755 --- a/intl/config.charset +++ b/intl/config.charset @@ -1,7 +1,7 @@ #! /bin/sh # Output a system dependent table of character encoding aliases. # -# Copyright (C) 2000-2003 Free Software Foundation, Inc. +# Copyright (C) 2000-2004 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published @@ -30,77 +30,77 @@ # MIME charset name is preferred. # The current list of GNU canonical charset names is as follows. # -# name used by which systems a MIME name? -# ASCII, ANSI_X3.4-1968 glibc solaris freebsd -# ISO-8859-1 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-2 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-3 glibc solaris yes -# ISO-8859-4 osf solaris freebsd yes -# ISO-8859-5 glibc aix hpux irix osf solaris freebsd yes -# ISO-8859-6 glibc aix hpux solaris yes -# ISO-8859-7 glibc aix hpux irix osf solaris yes -# ISO-8859-8 glibc aix hpux osf solaris yes -# ISO-8859-9 glibc aix hpux irix osf solaris yes -# ISO-8859-13 glibc -# ISO-8859-14 glibc -# ISO-8859-15 glibc aix osf solaris freebsd -# KOI8-R glibc solaris freebsd yes -# KOI8-U glibc freebsd yes -# KOI8-T glibc -# CP437 dos -# CP775 dos -# CP850 aix osf dos -# CP852 dos -# CP855 dos -# CP856 aix -# CP857 dos -# CP861 dos -# CP862 dos -# CP864 dos -# CP865 dos -# CP866 freebsd dos -# CP869 dos -# CP874 woe32 dos -# CP922 aix -# CP932 aix woe32 dos -# CP943 aix -# CP949 osf woe32 dos -# CP950 woe32 dos -# CP1046 aix -# CP1124 aix -# CP1125 dos -# CP1129 aix -# CP1250 woe32 -# CP1251 glibc solaris woe32 -# CP1252 aix woe32 -# CP1253 woe32 -# CP1254 woe32 -# CP1255 glibc woe32 -# CP1256 woe32 -# CP1257 woe32 -# GB2312 glibc aix hpux irix solaris freebsd yes -# EUC-JP glibc aix hpux irix osf solaris freebsd yes -# EUC-KR glibc aix hpux irix osf solaris freebsd yes -# EUC-TW glibc aix hpux irix osf solaris -# BIG5 glibc aix hpux osf solaris freebsd yes -# BIG5-HKSCS glibc solaris -# GBK glibc aix osf solaris woe32 dos -# GB18030 glibc solaris -# SHIFT_JIS hpux osf solaris freebsd yes -# JOHAB glibc solaris woe32 -# TIS-620 glibc aix hpux osf solaris -# VISCII glibc yes -# TCVN5712-1 glibc -# GEORGIAN-PS glibc -# HP-ROMAN8 hpux -# HP-ARABIC8 hpux -# HP-GREEK8 hpux -# HP-HEBREW8 hpux -# HP-TURKISH8 hpux -# HP-KANA8 hpux -# DEC-KANJI osf -# DEC-HANYU osf -# UTF-8 glibc aix hpux osf solaris yes +# name MIME? used by which systems +# ASCII, ANSI_X3.4-1968 glibc solaris freebsd darwin +# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd darwin +# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd darwin +# ISO-8859-3 Y glibc solaris +# ISO-8859-4 Y osf solaris freebsd darwin +# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd darwin +# ISO-8859-6 Y glibc aix hpux solaris +# ISO-8859-7 Y glibc aix hpux irix osf solaris +# ISO-8859-8 Y glibc aix hpux osf solaris +# ISO-8859-9 Y glibc aix hpux irix osf solaris +# ISO-8859-13 glibc +# ISO-8859-14 glibc +# ISO-8859-15 glibc aix osf solaris freebsd +# KOI8-R Y glibc solaris freebsd darwin +# KOI8-U Y glibc freebsd darwin +# KOI8-T glibc +# CP437 dos +# CP775 dos +# CP850 aix osf dos +# CP852 dos +# CP855 dos +# CP856 aix +# CP857 dos +# CP861 dos +# CP862 dos +# CP864 dos +# CP865 dos +# CP866 freebsd darwin dos +# CP869 dos +# CP874 woe32 dos +# CP922 aix +# CP932 aix woe32 dos +# CP943 aix +# CP949 osf woe32 dos +# CP950 woe32 dos +# CP1046 aix +# CP1124 aix +# CP1125 dos +# CP1129 aix +# CP1250 woe32 +# CP1251 glibc solaris darwin woe32 +# CP1252 aix woe32 +# CP1253 woe32 +# CP1254 woe32 +# CP1255 glibc woe32 +# CP1256 woe32 +# CP1257 woe32 +# GB2312 Y glibc aix hpux irix solaris freebsd darwin +# EUC-JP Y glibc aix hpux irix osf solaris freebsd darwin +# EUC-KR Y glibc aix hpux irix osf solaris freebsd darwin +# EUC-TW glibc aix hpux irix osf solaris +# BIG5 Y glibc aix hpux osf solaris freebsd darwin +# BIG5-HKSCS glibc solaris +# GBK glibc aix osf solaris woe32 dos +# GB18030 glibc solaris +# SHIFT_JIS Y hpux osf solaris freebsd darwin +# JOHAB glibc solaris woe32 +# TIS-620 glibc aix hpux osf solaris +# VISCII Y glibc +# TCVN5712-1 glibc +# GEORGIAN-PS glibc +# HP-ROMAN8 hpux +# HP-ARABIC8 hpux +# HP-GREEK8 hpux +# HP-HEBREW8 hpux +# HP-TURKISH8 hpux +# HP-KANA8 hpux +# DEC-KANJI osf +# DEC-HANYU osf +# UTF-8 Y glibc aix hpux osf solaris # # Note: Names which are not marked as being a MIME name should not be used in # Internet protocols for information interchange (mail, news, etc.). @@ -121,6 +121,105 @@ echo "# It was automatically generated from config.charset." # List of references, updated during installation: echo "# Packages using this file: " case "$os" in + linux-gnulibc1*) + # Linux libc5 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "C ASCII" + echo "POSIX ASCII" + for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \ + en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \ + en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \ + es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \ + et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \ + fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \ + it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \ + sv_FI sv_SE; do + echo "$l ISO-8859-1" + echo "$l.iso-8859-1 ISO-8859-1" + echo "$l.iso-8859-15 ISO-8859-15" + echo "$l.iso-8859-15@euro ISO-8859-15" + echo "$l@euro ISO-8859-15" + echo "$l.cp-437 CP437" + echo "$l.cp-850 CP850" + echo "$l.cp-1252 CP1252" + echo "$l.cp-1252@euro CP1252" + #echo "$l.atari-st ATARI-ST" # not a commonly used encoding + echo "$l.utf-8 UTF-8" + echo "$l.utf-8@euro UTF-8" + done + for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \ + sl_SI sr sr_CS sr_YU; do + echo "$l ISO-8859-2" + echo "$l.iso-8859-2 ISO-8859-2" + echo "$l.cp-852 CP852" + echo "$l.cp-1250 CP1250" + echo "$l.utf-8 UTF-8" + done + for l in mk mk_MK ru ru_RU; do + echo "$l ISO-8859-5" + echo "$l.iso-8859-5 ISO-8859-5" + echo "$l.koi8-r KOI8-R" + echo "$l.cp-866 CP866" + echo "$l.cp-1251 CP1251" + echo "$l.utf-8 UTF-8" + done + for l in ar ar_SA; do + echo "$l ISO-8859-6" + echo "$l.iso-8859-6 ISO-8859-6" + echo "$l.cp-864 CP864" + #echo "$l.cp-868 CP868" # not a commonly used encoding + echo "$l.cp-1256 CP1256" + echo "$l.utf-8 UTF-8" + done + for l in el el_GR gr gr_GR; do + echo "$l ISO-8859-7" + echo "$l.iso-8859-7 ISO-8859-7" + echo "$l.cp-869 CP869" + echo "$l.cp-1253 CP1253" + echo "$l.cp-1253@euro CP1253" + echo "$l.utf-8 UTF-8" + echo "$l.utf-8@euro UTF-8" + done + for l in he he_IL iw iw_IL; do + echo "$l ISO-8859-8" + echo "$l.iso-8859-8 ISO-8859-8" + echo "$l.cp-862 CP862" + echo "$l.cp-1255 CP1255" + echo "$l.utf-8 UTF-8" + done + for l in tr tr_TR; do + echo "$l ISO-8859-9" + echo "$l.iso-8859-9 ISO-8859-9" + echo "$l.cp-857 CP857" + echo "$l.cp-1254 CP1254" + echo "$l.utf-8 UTF-8" + done + for l in lt lt_LT lv lv_LV; do + #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name + echo "$l ISO-8859-13" + done + for l in ru_UA uk uk_UA; do + echo "$l KOI8-U" + done + for l in zh zh_CN; do + #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name + echo "$l GB2312" + done + for l in ja ja_JP ja_JP.EUC; do + echo "$l EUC-JP" + done + for l in ko ko_KR; do + echo "$l EUC-KR" + done + for l in th th_TH; do + echo "$l TIS-620" + done + for l in fa fa_IR; do + #echo "$l ISIRI-3342" # a broken encoding + echo "$l.utf-8 UTF-8" + done + ;; linux* | *-gnu*) # With glibc-2.1 or newer, we don't need any canonicalization, # because glibc has iconv and both glibc and libiconv support all @@ -297,6 +396,47 @@ case "$os" in echo "BIG5 BIG5" echo "SJIS SHIFT_JIS" ;; + darwin*) + # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "C ASCII" + for l in en_AU en_CA en_GB en_US la_LN; do + echo "$l.US-ASCII ASCII" + done + for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ + fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \ + nl_NL no_NO pt_PT sv_SE; do + echo "$l ISO-8859-1" + echo "$l.ISO8859-1 ISO-8859-1" + echo "$l.ISO8859-15 ISO-8859-15" + done + for l in la_LN; do + echo "$l.ISO8859-1 ISO-8859-1" + echo "$l.ISO8859-15 ISO-8859-15" + done + for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do + echo "$l.ISO8859-2 ISO-8859-2" + done + for l in la_LN lt_LT; do + echo "$l.ISO8859-4 ISO-8859-4" + done + for l in ru_RU; do + echo "$l.KOI8-R KOI8-R" + echo "$l.ISO8859-5 ISO-8859-5" + echo "$l.CP866 CP866" + done + for l in bg_BG; do + echo "$l.CP1251 CP1251" + done + echo "uk_UA.KOI8-U KOI8-U" + echo "zh_TW.BIG5 BIG5" + echo "zh_TW.Big5 BIG5" + echo "zh_CN.EUC GB2312" + echo "ja_JP.EUC EUC-JP" + echo "ja_JP.SJIS SHIFT_JIS" + echo "ko_KR.EUC EUC-KR" + ;; beos*) # BeOS has a single locale, and it has UTF-8 encoding. echo "* UTF-8" @@ -410,6 +550,7 @@ case "$os" in echo "sq CP852" echo "sq_AL CP852" echo "sr CP852" # CP852 or CP866 or CP855 ?? + echo "sr_CS CP852" # CP852 or CP866 or CP855 ?? echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? # ISO-8859-3 languages echo "mt CP850" diff --git a/intl/dcgettext.c b/intl/dcgettext.c index ca6a1c82d..850acdee9 100644 --- a/intl/dcgettext.c +++ b/intl/dcgettext.c @@ -1,5 +1,5 @@ /* Implementation of the dcgettext(3) function. - Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -44,10 +44,7 @@ /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale. */ char * -DCGETTEXT (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; +DCGETTEXT (const char *domainname, const char *msgid, int category) { return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category); } diff --git a/intl/dcigettext.c b/intl/dcigettext.c index f6edb95c0..35238e2cb 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -148,13 +148,17 @@ extern int errno; char *getwd (); # define getcwd(buf, max) getwd (buf) # else +# if VMS +# define getcwd(buf, max) (getcwd) (buf, max, 0) +# else char *getcwd (); +# endif # endif # ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); +static char *stpcpy (char *dest, const char *src); # endif # ifndef HAVE_MEMPCPY -static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); +static void *mempcpy (void *dest, const void *src, size_t n); # endif #endif @@ -248,11 +252,8 @@ static void *root; # endif /* Function to compare two entries in the table of known translations. */ -static int transcmp PARAMS ((const void *p1, const void *p2)); static int -transcmp (p1, p2) - const void *p1; - const void *p2; +transcmp (const void *p1, const void *p2) { const struct known_translation_t *s1; const struct known_translation_t *s2; @@ -304,19 +305,18 @@ INTVARDEF (_nl_default_dirname) struct binding *_nl_domain_bindings; /* Prototypes for local functions. */ -static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, - unsigned long int n, - const char *translation, - size_t translation_len)) +static char *plural_lookup (struct loaded_l10nfile *domain, + unsigned long int n, + const char *translation, size_t translation_len) internal_function; -static const char *guess_category_value PARAMS ((int category, - const char *categoryname)) +static const char *guess_category_value (int category, + const char *categoryname) internal_function; #ifdef _LIBC # include "../locale/localeinfo.h" # define category_to_name(category) _nl_category_names[category] #else -static const char *category_to_name PARAMS ((int category)) internal_function; +static const char *category_to_name (int category) internal_function; #endif @@ -424,13 +424,8 @@ static int enable_secure; CATEGORY locale and, if PLURAL is nonzero, search over string depending on the plural form determined by N. */ char * -DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - int plural; - unsigned long int n; - int category; +DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + int plural, unsigned long int n, int category) { #ifndef HAVE_ALLOCA struct block_list *block_list = NULL; @@ -703,11 +698,10 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) #ifndef _LIBC if (!ENABLE_SECURE) { - extern void _nl_log_untranslated PARAMS ((const char *logfilename, - const char *domainname, - const char *msgid1, - const char *msgid2, - int plural)); + extern void _nl_log_untranslated (const char *logfilename, + const char *domainname, + const char *msgid1, const char *msgid2, + int plural); const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED"); if (logfilename != NULL && logfilename[0] != '\0') @@ -724,11 +718,9 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) char * internal_function -_nl_find_msg (domain_file, domainbinding, msgid, lengthp) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; - const char *msgid; - size_t *lengthp; +_nl_find_msg (struct loaded_l10nfile *domain_file, + struct binding *domainbinding, const char *msgid, + size_t *lengthp) { struct loaded_domain *domain; nls_uint32 nstrings; @@ -1035,11 +1027,8 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) /* Look up a plural variant. */ static char * internal_function -plural_lookup (domain, n, translation, translation_len) - struct loaded_l10nfile *domain; - unsigned long int n; - const char *translation; - size_t translation_len; +plural_lookup (struct loaded_l10nfile *domain, unsigned long int n, + const char *translation, size_t translation_len) { struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; unsigned long int index; @@ -1076,8 +1065,7 @@ plural_lookup (domain, n, translation, translation_len) /* Return string representation of locale CATEGORY. */ static const char * internal_function -category_to_name (category) - int category; +category_to_name (int category) { const char *retval; @@ -1137,9 +1125,7 @@ category_to_name (category) /* Guess value of current locale from value of the environment variables. */ static const char * internal_function -guess_category_value (category, categoryname) - int category; - const char *categoryname; +guess_category_value (int category, const char *categoryname) { const char *language; const char *retval; @@ -1180,9 +1166,7 @@ guess_category_value (category, categoryname) to be defined. */ #if !_LIBC && !HAVE_STPCPY static char * -stpcpy (dest, src) - char *dest; - const char *src; +stpcpy (char *dest, const char *src) { while ((*dest++ = *src++) != '\0') /* Do nothing. */ ; @@ -1192,10 +1176,7 @@ stpcpy (dest, src) #if !_LIBC && !HAVE_MEMPCPY static void * -mempcpy (dest, src, n) - void *dest; - const void *src; - size_t n; +mempcpy (void *dest, const void *src, size_t n) { return (void *) ((char *) memcpy (dest, src, n) + n); } diff --git a/intl/dcngettext.c b/intl/dcngettext.c index 3a3404e2c..48a3e09e0 100644 --- a/intl/dcngettext.c +++ b/intl/dcngettext.c @@ -1,5 +1,5 @@ /* Implementation of the dcngettext(3) function. - Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -44,12 +44,9 @@ /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale. */ char * -DCNGETTEXT (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; +DCNGETTEXT (const char *domainname, + const char *msgid1, const char *msgid2, unsigned long int n, + int category) { return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category); } diff --git a/intl/dgettext.c b/intl/dgettext.c index cf5b4037f..b64b0f5d3 100644 --- a/intl/dgettext.c +++ b/intl/dgettext.c @@ -1,5 +1,5 @@ /* Implementation of the dgettext(3) function. - Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -20,9 +20,10 @@ # include <config.h> #endif +#include "gettextP.h" + #include <locale.h> -#include "gettextP.h" #ifdef _LIBC # include <libintl.h> #else @@ -46,9 +47,7 @@ /* Look up MSGID in the DOMAINNAME message catalog of the current LC_MESSAGES locale. */ char * -DGETTEXT (domainname, msgid) - const char *domainname; - const char *msgid; +DGETTEXT (const char *domainname, const char *msgid) { return DCGETTEXT (domainname, msgid, LC_MESSAGES); } diff --git a/intl/dngettext.c b/intl/dngettext.c index 67fd030f2..7815637f0 100644 --- a/intl/dngettext.c +++ b/intl/dngettext.c @@ -1,5 +1,5 @@ /* Implementation of the dngettext(3) function. - Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -20,9 +20,10 @@ # include <config.h> #endif +#include "gettextP.h" + #include <locale.h> -#include "gettextP.h" #ifdef _LIBC # include <libintl.h> #else @@ -46,11 +47,8 @@ /* Look up MSGID in the DOMAINNAME message catalog of the current LC_MESSAGES locale and skip message according to the plural form. */ char * -DNGETTEXT (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; +DNGETTEXT (const char *domainname, + const char *msgid1, const char *msgid2, unsigned long int n) { return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES); } diff --git a/intl/eval-plural.h b/intl/eval-plural.h index 19c7ca6ae..01bd5af5f 100644 --- a/intl/eval-plural.h +++ b/intl/eval-plural.h @@ -1,5 +1,5 @@ /* Plural expression evaluation. - Copyright (C) 2000-2002 Free Software Foundation, Inc. + Copyright (C) 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -21,16 +21,10 @@ #endif /* Evaluate the plural expression and return an index value. */ -STATIC unsigned long int plural_eval PARAMS ((struct expression *pexp, - unsigned long int n)) - internal_function; - STATIC unsigned long int internal_function -plural_eval (pexp, n) - struct expression *pexp; - unsigned long int n; +plural_eval (struct expression *pexp, unsigned long int n) { switch (pexp->nargs) { diff --git a/intl/explodename.c b/intl/explodename.c index 2985064c9..52c25e727 100644 --- a/intl/explodename.c +++ b/intl/explodename.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1995-1998, 2000-2001, 2003 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. This program is free software; you can redistribute it and/or modify it @@ -38,8 +38,7 @@ /* @@ end of prolog @@ */ char * -_nl_find_language (name) - const char *name; +_nl_find_language (const char *name) { while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '+' && name[0] != ',') @@ -50,17 +49,11 @@ _nl_find_language (name) int -_nl_explode_name (name, language, modifier, territory, codeset, - normalized_codeset, special, sponsor, revision) - char *name; - const char **language; - const char **modifier; - const char **territory; - const char **codeset; - const char **normalized_codeset; - const char **special; - const char **sponsor; - const char **revision; +_nl_explode_name (char *name, + const char **language, const char **modifier, + const char **territory, const char **codeset, + const char **normalized_codeset, const char **special, + const char **sponsor, const char **revision) { enum { undecided, xpg, cen } syntax; char *cp; diff --git a/intl/finddomain.c b/intl/finddomain.c index d24276442..4992a8c9e 100644 --- a/intl/finddomain.c +++ b/intl/finddomain.c @@ -1,5 +1,5 @@ /* Handle list of needed message catalogs - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc. Written by Ulrich Drepper <drepper@gnu.org>, 1995. This program is free software; you can redistribute it and/or modify it @@ -47,11 +47,8 @@ static struct loaded_l10nfile *_nl_loaded_domains; established bindings. */ struct loaded_l10nfile * internal_function -_nl_find_domain (dirname, locale, domainname, domainbinding) - const char *dirname; - char *locale; - const char *domainname; - struct binding *domainbinding; +_nl_find_domain (const char *dirname, char *locale, + const char *domainname, struct binding *domainbinding) { struct loaded_l10nfile *retval; const char *language; diff --git a/intl/gettext.c b/intl/gettext.c index 43d689f55..92c42faa7 100644 --- a/intl/gettext.c +++ b/intl/gettext.c @@ -1,5 +1,5 @@ /* Implementation of gettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -52,8 +52,7 @@ LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ char * -GETTEXT (msgid) - const char *msgid; +GETTEXT (const char *msgid) { return DCGETTEXT (NULL, msgid, LC_MESSAGES); } diff --git a/intl/gettextP.h b/intl/gettextP.h index f1748a356..4d66c3de3 100644 --- a/intl/gettextP.h +++ b/intl/gettextP.h @@ -36,14 +36,6 @@ /* @@ end of prolog @@ */ -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - #ifndef internal_function # define internal_function #endif @@ -159,64 +151,63 @@ struct binding extern int _nl_msg_cat_cntr; #ifndef _LIBC -const char *_nl_locale_name PARAMS ((int category, const char *categoryname)); +const char *_nl_locale_name (int category, const char *categoryname); #endif -struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, - char *__locale, - const char *__domainname, - struct binding *__domainbinding)) +struct loaded_l10nfile *_nl_find_domain (const char *__dirname, char *__locale, + const char *__domainname, + struct binding *__domainbinding) internal_function; -void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain, - struct binding *__domainbinding)) +void _nl_load_domain (struct loaded_l10nfile *__domain, + struct binding *__domainbinding) internal_function; -void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) +void _nl_unload_domain (struct loaded_domain *__domain) internal_function; -const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file, - struct loaded_domain *__domain, - struct binding *__domainbinding)) +const char *_nl_init_domain_conv (struct loaded_l10nfile *__domain_file, + struct loaded_domain *__domain, + struct binding *__domainbinding) internal_function; -void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain)) +void _nl_free_domain_conv (struct loaded_domain *__domain) internal_function; -char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file, - struct binding *domainbinding, - const char *msgid, size_t *lengthp)) +char *_nl_find_msg (struct loaded_l10nfile *domain_file, + struct binding *domainbinding, const char *msgid, + size_t *lengthp) internal_function; #ifdef _LIBC -extern char *__gettext PARAMS ((const char *__msgid)); -extern char *__dgettext PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *__dcgettext PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *__dngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int n)); -extern char *__dcngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n, int __category)); -extern char *__dcigettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *__textdomain PARAMS ((const char *__domainname)); -extern char *__bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); +extern char *__gettext (const char *__msgid); +extern char *__dgettext (const char *__domainname, const char *__msgid); +extern char *__dcgettext (const char *__domainname, const char *__msgid, + int __category); +extern char *__ngettext (const char *__msgid1, const char *__msgid2, + unsigned long int __n); +extern char *__dngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int n); +extern char *__dcngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category); +extern char *__dcigettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + int __plural, unsigned long int __n, + int __category); +extern char *__textdomain (const char *__domainname); +extern char *__bindtextdomain (const char *__domainname, + const char *__dirname); +extern char *__bind_textdomain_codeset (const char *__domainname, + const char *__codeset); #else /* Declare the exported libintl_* functions, in a way that allows us to call them under their real name. */ +# undef _INTL_REDIRECT_INLINE +# undef _INTL_REDIRECT_MACROS # define _INTL_REDIRECT_MACROS # include "libgnuintl.h" -extern char *libintl_dcigettext PARAMS ((const char *__domainname, - const char *__msgid1, - const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); +extern char *libintl_dcigettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + int __plural, unsigned long int __n, + int __category); #endif /* @@ begin of epilog @@ */ diff --git a/intl/gmo.h b/intl/gmo.h index d1fe4d6b8..e7c9cc14b 100644 --- a/intl/gmo.h +++ b/intl/gmo.h @@ -1,5 +1,5 @@ /* Description of GNU message catalog format: general file layout. - Copyright (C) 1995, 1997, 2000-2002 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 2000-2002, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -29,6 +29,7 @@ /* Revision number of the currently used .mo (binary) file format. */ #define MO_REVISION_NUMBER 0 +#define MO_REVISION_NUMBER_WITH_SYSDEP_I 1 /* The following contortions are an attempt to use the C preprocessor to determine an unsigned integral type that is 32 bits wide. An @@ -76,7 +77,7 @@ struct mo_file_header /* The revision number of the file format. */ nls_uint32 revision; - /* The following are only used in .mo files with major revision 0. */ + /* The following are only used in .mo files with major revision 0 or 1. */ /* The number of strings pairs. */ nls_uint32 nstrings; diff --git a/intl/hash-string.h b/intl/hash-string.h index b267a8778..093e3b1c1 100644 --- a/intl/hash-string.h +++ b/intl/hash-string.h @@ -1,5 +1,5 @@ /* Description of GNU message catalog format: string hashing function. - Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995, 1997-1998, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -18,14 +18,6 @@ /* @@ end of prolog @@ */ -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif -#endif - /* We assume to have `unsigned long int' value with at least 32 bits. */ #define HASHWORDBITS 32 @@ -33,11 +25,8 @@ /* Defines the so called `hashpjw' function by P.J. Weinberger [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, 1986, 1987 Bell Telephone Laboratories, Inc.] */ -static unsigned long int hash_string PARAMS ((const char *__str_param)); - static inline unsigned long int -hash_string (str_param) - const char *str_param; +hash_string (const char *str_param) { unsigned long int hval, g; const char *str = str_param; @@ -47,7 +36,7 @@ hash_string (str_param) while (*str != '\0') { hval <<= 4; - hval += (unsigned long int) *str++; + hval += (unsigned char) *str++; g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); if (g != 0) { diff --git a/intl/intl-compat.c b/intl/intl-compat.c index 36b7af0f8..96f9d955d 100644 --- a/intl/intl-compat.c +++ b/intl/intl-compat.c @@ -58,8 +58,7 @@ DLL_EXPORTED char * -gettext (msgid) - const char *msgid; +gettext (const char *msgid) { return libintl_gettext (msgid); } @@ -67,9 +66,7 @@ gettext (msgid) DLL_EXPORTED char * -dgettext (domainname, msgid) - const char *domainname; - const char *msgid; +dgettext (const char *domainname, const char *msgid) { return libintl_dgettext (domainname, msgid); } @@ -77,10 +74,7 @@ dgettext (domainname, msgid) DLL_EXPORTED char * -dcgettext (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; +dcgettext (const char *domainname, const char *msgid, int category) { return libintl_dcgettext (domainname, msgid, category); } @@ -88,10 +82,7 @@ dcgettext (domainname, msgid, category) DLL_EXPORTED char * -ngettext (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; +ngettext (const char *msgid1, const char *msgid2, unsigned long int n) { return libintl_ngettext (msgid1, msgid2, n); } @@ -99,11 +90,8 @@ ngettext (msgid1, msgid2, n) DLL_EXPORTED char * -dngettext (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; +dngettext (const char *domainname, + const char *msgid1, const char *msgid2, unsigned long int n) { return libintl_dngettext (domainname, msgid1, msgid2, n); } @@ -111,12 +99,9 @@ dngettext (domainname, msgid1, msgid2, n) DLL_EXPORTED char * -dcngettext (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; +dcngettext (const char *domainname, + const char *msgid1, const char *msgid2, unsigned long int n, + int category) { return libintl_dcngettext (domainname, msgid1, msgid2, n, category); } @@ -124,8 +109,7 @@ dcngettext (domainname, msgid1, msgid2, n, category) DLL_EXPORTED char * -textdomain (domainname) - const char *domainname; +textdomain (const char *domainname) { return libintl_textdomain (domainname); } @@ -133,9 +117,7 @@ textdomain (domainname) DLL_EXPORTED char * -bindtextdomain (domainname, dirname) - const char *domainname; - const char *dirname; +bindtextdomain (const char *domainname, const char *dirname) { return libintl_bindtextdomain (domainname, dirname); } @@ -143,9 +125,7 @@ bindtextdomain (domainname, dirname) DLL_EXPORTED char * -bind_textdomain_codeset (domainname, codeset) - const char *domainname; - const char *codeset; +bind_textdomain_codeset (const char *domainname, const char *codeset) { return libintl_bind_textdomain_codeset (domainname, codeset); } diff --git a/intl/l10nflist.c b/intl/l10nflist.c index ec8713f8e..eb995aafa 100644 --- a/intl/l10nflist.c +++ b/intl/l10nflist.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. This program is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ # endif #else # ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); +static char *stpcpy (char *dest, const char *src); # endif #endif @@ -84,12 +84,8 @@ static char *stpcpy PARAMS ((char *dest, const char *src)); #if !defined _LIBC && !defined HAVE___ARGZ_COUNT /* Returns the number of strings in ARGZ. */ -static size_t argz_count__ PARAMS ((const char *argz, size_t len)); - static size_t -argz_count__ (argz, len) - const char *argz; - size_t len; +argz_count__ (const char *argz, size_t len) { size_t count = 0; while (len > 0) @@ -112,13 +108,8 @@ argz_count__ (argz, len) #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's except the last into the character SEP. */ -static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); - static void -argz_stringify__ (argz, len, sep) - char *argz; - size_t len; - int sep; +argz_stringify__ (char *argz, size_t len, int sep) { while (len > 0) { @@ -139,14 +130,8 @@ argz_stringify__ (argz, len, sep) #endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ #if !defined _LIBC && !defined HAVE___ARGZ_NEXT -static char *argz_next__ PARAMS ((char *argz, size_t argz_len, - const char *entry)); - static char * -argz_next__ (argz, argz_len, entry) - char *argz; - size_t argz_len; - const char *entry; +argz_next__ (char *argz, size_t argz_len, const char *entry) { if (entry) { @@ -167,11 +152,8 @@ argz_next__ (argz, argz_len, entry) /* Return number of bits set in X. */ -static int pop PARAMS ((int x)); - static inline int -pop (x) - int x; +pop (int x) { /* We assume that no more than 16 bits are used. */ x = ((x & ~0x5555) >> 1) + (x & 0x5555); @@ -184,23 +166,13 @@ pop (x) struct loaded_l10nfile * -_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, - territory, codeset, normalized_codeset, modifier, special, - sponsor, revision, filename, do_allocate) - struct loaded_l10nfile **l10nfile_list; - const char *dirlist; - size_t dirlist_len; - int mask; - const char *language; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *modifier; - const char *special; - const char *sponsor; - const char *revision; - const char *filename; - int do_allocate; +_nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list, + const char *dirlist, size_t dirlist_len, + int mask, const char *language, const char *territory, + const char *codeset, const char *normalized_codeset, + const char *modifier, const char *special, + const char *sponsor, const char *revision, + const char *filename, int do_allocate) { char *abs_filename; struct loaded_l10nfile **lastp; @@ -393,9 +365,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, names. The return value is dynamically allocated and has to be freed by the caller. */ const char * -_nl_normalize_codeset (codeset, name_len) - const char *codeset; - size_t name_len; +_nl_normalize_codeset (const char *codeset, size_t name_len) { int len = 0; int only_digit = 1; @@ -442,9 +412,7 @@ _nl_normalize_codeset (codeset, name_len) to be defined. */ #if !_LIBC && !HAVE_STPCPY static char * -stpcpy (dest, src) - char *dest; - const char *src; +stpcpy (char *dest, const char *src) { while ((*dest++ = *src++) != '\0') /* Do nothing. */ ; diff --git a/intl/libgnuintl.h.in b/intl/libgnuintl.h.in index f596cfcb2..3be7eb990 100644 --- a/intl/libgnuintl.h.in +++ b/intl/libgnuintl.h.in @@ -47,16 +47,6 @@ # undef gettext #endif -/* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers - used by programs. Similarly, test __PROTOTYPES, not PROTOTYPES. */ -#ifndef _INTL_PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define _INTL_PARAMS(args) args -# else -# define _INTL_PARAMS(args) () -# endif -#endif - #ifdef __cplusplus extern "C" { #endif @@ -93,7 +83,7 @@ extern "C" { If he doesn't, we choose the method. A third possible method is _INTL_REDIRECT_ASM, supported only by GCC. */ #if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS) -# if __GNUC__ >= 2 && !defined __APPLE_CC__ && (defined __STDC__ || defined __cplusplus) +# if __GNUC__ >= 2 && !defined __APPLE_CC__ && !defined __MINGW32__ && !(__GNUC__ == 2 && defined _AIX) && (defined __STDC__ || defined __cplusplus) # define _INTL_REDIRECT_ASM # else # ifdef __cplusplus @@ -125,7 +115,7 @@ static inline char *gettext (const char *__msgid) #ifdef _INTL_REDIRECT_MACROS # define gettext libintl_gettext #endif -extern char *gettext _INTL_PARAMS ((const char *__msgid)) +extern char *gettext (const char *__msgid) _INTL_ASM (libintl_gettext); #endif @@ -141,8 +131,7 @@ static inline char *dgettext (const char *__domainname, const char *__msgid) #ifdef _INTL_REDIRECT_MACROS # define dgettext libintl_dgettext #endif -extern char *dgettext _INTL_PARAMS ((const char *__domainname, - const char *__msgid)) +extern char *dgettext (const char *__domainname, const char *__msgid) _INTL_ASM (libintl_dgettext); #endif @@ -160,9 +149,8 @@ static inline char *dcgettext (const char *__domainname, const char *__msgid, #ifdef _INTL_REDIRECT_MACROS # define dcgettext libintl_dcgettext #endif -extern char *dcgettext _INTL_PARAMS ((const char *__domainname, - const char *__msgid, - int __category)) +extern char *dcgettext (const char *__domainname, const char *__msgid, + int __category) _INTL_ASM (libintl_dcgettext); #endif @@ -181,9 +169,8 @@ static inline char *ngettext (const char *__msgid1, const char *__msgid2, #ifdef _INTL_REDIRECT_MACROS # define ngettext libintl_ngettext #endif -extern char *ngettext _INTL_PARAMS ((const char *__msgid1, - const char *__msgid2, - unsigned long int __n)) +extern char *ngettext (const char *__msgid1, const char *__msgid2, + unsigned long int __n) _INTL_ASM (libintl_ngettext); #endif @@ -201,10 +188,9 @@ static inline char *dngettext (const char *__domainname, const char *__msgid1, #ifdef _INTL_REDIRECT_MACROS # define dngettext libintl_dngettext #endif -extern char *dngettext _INTL_PARAMS ((const char *__domainname, - const char *__msgid1, - const char *__msgid2, - unsigned long int __n)) +extern char *dngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n) _INTL_ASM (libintl_dngettext); #endif @@ -224,11 +210,9 @@ static inline char *dcngettext (const char *__domainname, #ifdef _INTL_REDIRECT_MACROS # define dcngettext libintl_dcngettext #endif -extern char *dcngettext _INTL_PARAMS ((const char *__domainname, - const char *__msgid1, - const char *__msgid2, - unsigned long int __n, - int __category)) +extern char *dcngettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + unsigned long int __n, int __category) _INTL_ASM (libintl_dcngettext); #endif @@ -246,7 +230,7 @@ static inline char *textdomain (const char *__domainname) #ifdef _INTL_REDIRECT_MACROS # define textdomain libintl_textdomain #endif -extern char *textdomain _INTL_PARAMS ((const char *__domainname)) +extern char *textdomain (const char *__domainname) _INTL_ASM (libintl_textdomain); #endif @@ -264,8 +248,7 @@ static inline char *bindtextdomain (const char *__domainname, #ifdef _INTL_REDIRECT_MACROS # define bindtextdomain libintl_bindtextdomain #endif -extern char *bindtextdomain _INTL_PARAMS ((const char *__domainname, - const char *__dirname)) +extern char *bindtextdomain (const char *__domainname, const char *__dirname) _INTL_ASM (libintl_bindtextdomain); #endif @@ -283,12 +266,103 @@ static inline char *bind_textdomain_codeset (const char *__domainname, #ifdef _INTL_REDIRECT_MACROS # define bind_textdomain_codeset libintl_bind_textdomain_codeset #endif -extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname, - const char *__codeset)) +extern char *bind_textdomain_codeset (const char *__domainname, + const char *__codeset) _INTL_ASM (libintl_bind_textdomain_codeset); #endif +/* Support for format strings with positions in *printf(), following the + POSIX/XSI specification. + Note: These replacements for the *printf() functions are visible only + in source files that #include <libintl.h> or #include "gettext.h". + Packages that use *printf() in source files that don't refer to _() + or gettext() but for which the format string could be the return value + of _() or gettext() need to add this #include. Oh well. */ + +#if !@HAVE_POSIX_PRINTF@ + +#include <stdio.h> +#include <stddef.h> + +/* Get va_list. */ +#if __STDC__ || defined __cplusplus || defined _MSC_VER +# include <stdarg.h> +#else +# include <varargs.h> +#endif + +#undef fprintf +#define fprintf libintl_fprintf +extern int fprintf (FILE *, const char *, ...); +#undef vfprintf +#define vfprintf libintl_vfprintf +extern int vfprintf (FILE *, const char *, va_list); + +#undef printf +#define printf libintl_printf +extern int printf (const char *, ...); +#undef vprintf +#define vprintf libintl_vprintf +extern int vprintf (const char *, va_list); + +#undef sprintf +#define sprintf libintl_sprintf +extern int sprintf (char *, const char *, ...); +#undef vsprintf +#define vsprintf libintl_vsprintf +extern int vsprintf (char *, const char *, va_list); + +#if @HAVE_SNPRINTF@ + +#undef snprintf +#define snprintf libintl_snprintf +extern int snprintf (char *, size_t, const char *, ...); +#undef vsnprintf +#define vsnprintf libintl_vsnprintf +extern int vsnprintf (char *, size_t, const char *, va_list); + +#endif + +#if @HAVE_ASPRINTF@ + +#undef asprintf +#define asprintf libintl_asprintf +extern int asprintf (char **, const char *, ...); +#undef vasprintf +#define vasprintf libintl_vasprintf +extern int vasprintf (char **, const char *, va_list); + +#endif + +#if @HAVE_WPRINTF@ + +#undef fwprintf +#define fwprintf libintl_fwprintf +extern int fwprintf (FILE *, const wchar_t *, ...); +#undef vfwprintf +#define vfwprintf libintl_vfwprintf +extern int vfwprintf (FILE *, const wchar_t *, va_list); + +#undef wprintf +#define wprintf libintl_wprintf +extern int wprintf (const wchar_t *, ...); +#undef vwprintf +#define vwprintf libintl_vwprintf +extern int vwprintf (const wchar_t *, va_list); + +#undef swprintf +#define swprintf libintl_swprintf +extern int swprintf (wchar_t *, size_t, const wchar_t *, ...); +#undef vswprintf +#define vswprintf libintl_vswprintf +extern int vswprintf (wchar_t *, size_t, const wchar_t *, va_list); + +#endif + +#endif + + /* Support for relocatable packages. */ /* Sets the original and the current installation prefix of the package. @@ -298,8 +372,8 @@ extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname, instead of "/"). */ #define libintl_set_relocation_prefix libintl_set_relocation_prefix extern void - libintl_set_relocation_prefix _INTL_PARAMS ((const char *orig_prefix, - const char *curr_prefix)); + libintl_set_relocation_prefix (const char *orig_prefix, + const char *curr_prefix); #ifdef __cplusplus diff --git a/intl/loadinfo.h b/intl/loadinfo.h index 1d3ba6162..65e5ebd1f 100644 --- a/intl/loadinfo.h +++ b/intl/loadinfo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-1999, 2000-2002 Free Software Foundation, Inc. +/* Copyright (C) 1996-1999, 2000-2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -32,14 +32,6 @@ in gettextP.h. */ -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - #ifndef internal_function # define internal_function #endif @@ -89,8 +81,8 @@ struct loaded_l10nfile names. Normalization allows the user to use any of the common names. The return value is dynamically allocated and has to be freed by the caller. */ -extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, - size_t name_len)); +extern const char *_nl_normalize_codeset (const char *codeset, + size_t name_len); /* Lookup a locale dependent file. *L10NFILE_LIST denotes a pool of lookup results of locale dependent @@ -107,19 +99,18 @@ extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, furthermore its ->successor[] field contains a list of other lookup results from which this lookup result inherits. */ extern struct loaded_l10nfile * -_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, - const char *dirlist, size_t dirlist_len, int mask, - const char *language, const char *territory, - const char *codeset, - const char *normalized_codeset, - const char *modifier, const char *special, - const char *sponsor, const char *revision, - const char *filename, int do_allocate)); +_nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list, + const char *dirlist, size_t dirlist_len, int mask, + const char *language, const char *territory, + const char *codeset, const char *normalized_codeset, + const char *modifier, const char *special, + const char *sponsor, const char *revision, + const char *filename, int do_allocate); /* Lookup the real locale name for a locale alias NAME, or NULL if NAME is not a locale alias (but possibly a real locale name). The return value is statically allocated and must not be freed. */ -extern const char *_nl_expand_alias PARAMS ((const char *name)); +extern const char *_nl_expand_alias (const char *name); /* Split a locale name NAME into its pieces: language, modifier, territory, codeset, special, sponsor, revision. @@ -139,18 +130,16 @@ extern const char *_nl_expand_alias PARAMS ((const char *name)); CEN_SPONSOR for *SPONSOR, CEN_REVISION for *REVISION. */ -extern int _nl_explode_name PARAMS ((char *name, const char **language, - const char **modifier, - const char **territory, - const char **codeset, - const char **normalized_codeset, - const char **special, - const char **sponsor, - const char **revision)); +extern int _nl_explode_name (char *name, const char **language, + const char **modifier, const char **territory, + const char **codeset, + const char **normalized_codeset, + const char **special, const char **sponsor, + const char **revision); /* Split a locale name NAME into a leading language part and all the rest. Return a pointer to the first character after the language, i.e. to the first byte of the rest. */ -extern char *_nl_find_language PARAMS ((const char *name)); +extern char *_nl_find_language (const char *name); #endif /* loadinfo.h */ diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c index 8509bd345..99c51b4c5 100644 --- a/intl/loadmsgcat.c +++ b/intl/loadmsgcat.c @@ -1,5 +1,5 @@ /* Load needed message catalogs. - Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000-2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -491,11 +491,6 @@ char *alloca (); #endif -/* Prototypes for local functions. Needed to ensure compiler checking of - function argument counts despite of K&R C function definition syntax. */ -static const char *get_sysdep_segment_value PARAMS ((const char *name)); - - /* We need a sign, whether a new catalog was loaded, which can be associated with all translations. This is important if the translations are cached by one of GCC's features. */ @@ -504,8 +499,7 @@ int _nl_msg_cat_cntr; /* Expand a system dependent string segment. Return NULL if unsupported. */ static const char * -get_sysdep_segment_value (name) - const char *name; +get_sysdep_segment_value (const char *name) { /* Test for an ISO C 99 section 7.8.1 format string directive. Syntax: @@ -754,6 +748,18 @@ get_sysdep_segment_value (name) } } } + /* Test for a glibc specific printf() format directive flag. */ + if (name[0] == 'I' && name[1] == '\0') + { +#if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) + /* The 'I' flag, in numeric format directives, replaces ASCII digits + with the 'outdigits' defined in the LC_CTYPE locale facet. This is + used for Farsi (Persian) and maybe Arabic. */ + return "I"; +#else + return ""; +#endif + } /* Other system dependent strings are not valid. */ return NULL; } @@ -762,10 +768,9 @@ get_sysdep_segment_value (name) Return the header entry. */ const char * internal_function -_nl_init_domain_conv (domain_file, domain, domainbinding) - struct loaded_l10nfile *domain_file; - struct loaded_domain *domain; - struct binding *domainbinding; +_nl_init_domain_conv (struct loaded_l10nfile *domain_file, + struct loaded_domain *domain, + struct binding *domainbinding) { /* Find out about the character set the file is encoded with. This can be found (in textual form) in the entry "". If this @@ -829,7 +834,7 @@ _nl_init_domain_conv (domain_file, domain, domainbinding) outcharset = _NL_CURRENT (LC_CTYPE, CODESET); # else # if HAVE_ICONV - extern const char *locale_charset PARAMS ((void)); + extern const char *locale_charset (void); outcharset = locale_charset (); # endif # endif @@ -881,8 +886,7 @@ _nl_init_domain_conv (domain_file, domain, domainbinding) /* Frees the codeset dependent parts of an opened message catalog. */ void internal_function -_nl_free_domain_conv (domain) - struct loaded_domain *domain; +_nl_free_domain_conv (struct loaded_domain *domain) { if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) free (domain->conv_tab); @@ -902,9 +906,8 @@ _nl_free_domain_conv (domain) message catalog do nothing. */ void internal_function -_nl_load_domain (domain_file, domainbinding) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; +_nl_load_domain (struct loaded_l10nfile *domain_file, + struct binding *domainbinding) { int fd; size_t size; @@ -1028,10 +1031,11 @@ _nl_load_domain (domain_file, domainbinding) /* Fill in the information about the available tables. */ revision = W (domain->must_swap, data->revision); - /* We support only the major revision 0. */ + /* We support only the major revisions 0 and 1. */ switch (revision >> 16) { case 0: + case 1: domain->nstrings = W (domain->must_swap, data->nstrings); domain->orig_tab = (const struct string_desc *) ((char *) data + W (domain->must_swap, data->orig_tab_offset)); @@ -1071,12 +1075,13 @@ _nl_load_domain (domain_file, domainbinding) const char **sysdep_segment_values; const nls_uint32 *orig_sysdep_tab; const nls_uint32 *trans_sysdep_tab; + nls_uint32 n_inmem_sysdep_strings; size_t memneed; char *mem; struct sysdep_string_desc *inmem_orig_sysdep_tab; struct sysdep_string_desc *inmem_trans_sysdep_tab; nls_uint32 *inmem_hash_tab; - unsigned int i; + unsigned int i, j; /* Get the values of the system dependent segments. */ n_sysdep_segments = @@ -1111,153 +1116,247 @@ _nl_load_domain (domain_file, domainbinding) + W (domain->must_swap, data->trans_sysdep_tab_offset)); /* Compute the amount of additional memory needed for the - system dependent strings and the augmented hash table. */ - memneed = 2 * n_sysdep_strings - * sizeof (struct sysdep_string_desc) - + domain->hash_size * sizeof (nls_uint32); - for (i = 0; i < 2 * n_sysdep_strings; i++) + system dependent strings and the augmented hash table. + At the same time, also drop string pairs which refer to + an undefined system dependent segment. */ + n_inmem_sysdep_strings = 0; + memneed = domain->hash_size * sizeof (nls_uint32); + for (i = 0; i < n_sysdep_strings; i++) { - const struct sysdep_string *sysdep_string = - (const struct sysdep_string *) - ((char *) data - + W (domain->must_swap, - i < n_sysdep_strings - ? orig_sysdep_tab[i] - : trans_sysdep_tab[i - n_sysdep_strings])); - size_t need = 0; - const struct segment_pair *p = sysdep_string->segments; - - if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) - for (p = sysdep_string->segments;; p++) - { - nls_uint32 sysdepref; - - need += W (domain->must_swap, p->segsize); - - sysdepref = W (domain->must_swap, p->sysdepref); - if (sysdepref == SEGMENTS_END) - break; - - if (sysdepref >= n_sysdep_segments) + int valid = 1; + size_t needs[2]; + + for (j = 0; j < 2; j++) + { + const struct sysdep_string *sysdep_string = + (const struct sysdep_string *) + ((char *) data + + W (domain->must_swap, + j == 0 + ? orig_sysdep_tab[i] + : trans_sysdep_tab[i])); + size_t need = 0; + const struct segment_pair *p = sysdep_string->segments; + + if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) + for (p = sysdep_string->segments;; p++) { - /* Invalid. */ - freea (sysdep_segment_values); - goto invalid; - } + nls_uint32 sysdepref; - need += strlen (sysdep_segment_values[sysdepref]); - } + need += W (domain->must_swap, p->segsize); - memneed += need; - } + sysdepref = W (domain->must_swap, p->sysdepref); + if (sysdepref == SEGMENTS_END) + break; - /* Allocate additional memory. */ - mem = (char *) malloc (memneed); - if (mem == NULL) - goto invalid; - - domain->malloced = mem; - inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem; - mem += n_sysdep_strings * sizeof (struct sysdep_string_desc); - inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem; - mem += n_sysdep_strings * sizeof (struct sysdep_string_desc); - inmem_hash_tab = (nls_uint32 *) mem; - mem += domain->hash_size * sizeof (nls_uint32); - - /* Compute the system dependent strings. */ - for (i = 0; i < 2 * n_sysdep_strings; i++) - { - const struct sysdep_string *sysdep_string = - (const struct sysdep_string *) - ((char *) data - + W (domain->must_swap, - i < n_sysdep_strings - ? orig_sysdep_tab[i] - : trans_sysdep_tab[i - n_sysdep_strings])); - const char *static_segments = - (char *) data - + W (domain->must_swap, sysdep_string->offset); - const struct segment_pair *p = sysdep_string->segments; + if (sysdepref >= n_sysdep_segments) + { + /* Invalid. */ + freea (sysdep_segment_values); + goto invalid; + } + + if (sysdep_segment_values[sysdepref] == NULL) + { + /* This particular string pair is invalid. */ + valid = 0; + break; + } + + need += strlen (sysdep_segment_values[sysdepref]); + } - /* Concatenate the segments, and fill - inmem_orig_sysdep_tab[i] (for i < n_sysdep_strings) and - inmem_trans_sysdep_tab[i-n_sysdep_strings] (for - i >= n_sysdep_strings). */ + needs[j] = need; + if (!valid) + break; + } - if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END) + if (valid) { - /* Only one static segment. */ - inmem_orig_sysdep_tab[i].length = - W (domain->must_swap, p->segsize); - inmem_orig_sysdep_tab[i].pointer = static_segments; + n_inmem_sysdep_strings++; + memneed += needs[0] + needs[1]; } - else + } + memneed += 2 * n_inmem_sysdep_strings + * sizeof (struct sysdep_string_desc); + + if (n_inmem_sysdep_strings > 0) + { + unsigned int k; + + /* Allocate additional memory. */ + mem = (char *) malloc (memneed); + if (mem == NULL) + goto invalid; + + domain->malloced = mem; + inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem; + mem += n_inmem_sysdep_strings + * sizeof (struct sysdep_string_desc); + inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem; + mem += n_inmem_sysdep_strings + * sizeof (struct sysdep_string_desc); + inmem_hash_tab = (nls_uint32 *) mem; + mem += domain->hash_size * sizeof (nls_uint32); + + /* Compute the system dependent strings. */ + k = 0; + for (i = 0; i < n_sysdep_strings; i++) { - inmem_orig_sysdep_tab[i].pointer = mem; + int valid = 1; - for (p = sysdep_string->segments;; p++) + for (j = 0; j < 2; j++) { - nls_uint32 segsize = - W (domain->must_swap, p->segsize); - nls_uint32 sysdepref = - W (domain->must_swap, p->sysdepref); - size_t n; + const struct sysdep_string *sysdep_string = + (const struct sysdep_string *) + ((char *) data + + W (domain->must_swap, + j == 0 + ? orig_sysdep_tab[i] + : trans_sysdep_tab[i])); + const struct segment_pair *p = + sysdep_string->segments; + + if (W (domain->must_swap, p->sysdepref) + != SEGMENTS_END) + for (p = sysdep_string->segments;; p++) + { + nls_uint32 sysdepref; + + sysdepref = + W (domain->must_swap, p->sysdepref); + if (sysdepref == SEGMENTS_END) + break; + + if (sysdep_segment_values[sysdepref] == NULL) + { + /* This particular string pair is + invalid. */ + valid = 0; + break; + } + } + + if (!valid) + break; + } - if (segsize > 0) + if (valid) + { + for (j = 0; j < 2; j++) { - memcpy (mem, static_segments, segsize); - mem += segsize; - static_segments += segsize; + const struct sysdep_string *sysdep_string = + (const struct sysdep_string *) + ((char *) data + + W (domain->must_swap, + j == 0 + ? orig_sysdep_tab[i] + : trans_sysdep_tab[i])); + const char *static_segments = + (char *) data + + W (domain->must_swap, sysdep_string->offset); + const struct segment_pair *p = + sysdep_string->segments; + + /* Concatenate the segments, and fill + inmem_orig_sysdep_tab[k] (for j == 0) and + inmem_trans_sysdep_tab[k] (for j == 1). */ + + struct sysdep_string_desc *inmem_tab_entry = + (j == 0 + ? inmem_orig_sysdep_tab + : inmem_trans_sysdep_tab) + + k; + + if (W (domain->must_swap, p->sysdepref) + == SEGMENTS_END) + { + /* Only one static segment. */ + inmem_tab_entry->length = + W (domain->must_swap, p->segsize); + inmem_tab_entry->pointer = static_segments; + } + else + { + inmem_tab_entry->pointer = mem; + + for (p = sysdep_string->segments;; p++) + { + nls_uint32 segsize = + W (domain->must_swap, p->segsize); + nls_uint32 sysdepref = + W (domain->must_swap, p->sysdepref); + size_t n; + + if (segsize > 0) + { + memcpy (mem, static_segments, segsize); + mem += segsize; + static_segments += segsize; + } + + if (sysdepref == SEGMENTS_END) + break; + + n = strlen (sysdep_segment_values[sysdepref]); + memcpy (mem, sysdep_segment_values[sysdepref], n); + mem += n; + } + + inmem_tab_entry->length = + mem - inmem_tab_entry->pointer; + } } - if (sysdepref == SEGMENTS_END) - break; - - n = strlen (sysdep_segment_values[sysdepref]); - memcpy (mem, sysdep_segment_values[sysdepref], n); - mem += n; + k++; } - - inmem_orig_sysdep_tab[i].length = - mem - inmem_orig_sysdep_tab[i].pointer; } - } - - /* Compute the augmented hash table. */ - for (i = 0; i < domain->hash_size; i++) - inmem_hash_tab[i] = - W (domain->must_swap_hash_tab, domain->hash_tab[i]); - for (i = 0; i < n_sysdep_strings; i++) - { - const char *msgid = inmem_orig_sysdep_tab[i].pointer; - nls_uint32 hash_val = hash_string (msgid); - nls_uint32 idx = hash_val % domain->hash_size; - nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); - - for (;;) + if (k != n_inmem_sysdep_strings) + abort (); + + /* Compute the augmented hash table. */ + for (i = 0; i < domain->hash_size; i++) + inmem_hash_tab[i] = + W (domain->must_swap_hash_tab, domain->hash_tab[i]); + for (i = 0; i < n_inmem_sysdep_strings; i++) { - if (inmem_hash_tab[idx] == 0) + const char *msgid = inmem_orig_sysdep_tab[i].pointer; + nls_uint32 hash_val = hash_string (msgid); + nls_uint32 idx = hash_val % domain->hash_size; + nls_uint32 incr = + 1 + (hash_val % (domain->hash_size - 2)); + + for (;;) { - /* Hash table entry is empty. Use it. */ - inmem_hash_tab[idx] = 1 + domain->nstrings + i; - break; - } + if (inmem_hash_tab[idx] == 0) + { + /* Hash table entry is empty. Use it. */ + inmem_hash_tab[idx] = 1 + domain->nstrings + i; + break; + } - if (idx >= domain->hash_size - incr) - idx -= domain->hash_size - incr; - else - idx += incr; + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + } } - } - freea (sysdep_segment_values); + domain->n_sysdep_strings = n_inmem_sysdep_strings; + domain->orig_sysdep_tab = inmem_orig_sysdep_tab; + domain->trans_sysdep_tab = inmem_trans_sysdep_tab; - domain->n_sysdep_strings = n_sysdep_strings; - domain->orig_sysdep_tab = inmem_orig_sysdep_tab; - domain->trans_sysdep_tab = inmem_trans_sysdep_tab; + domain->hash_tab = inmem_hash_tab; + domain->must_swap_hash_tab = 0; + } + else + { + domain->n_sysdep_strings = 0; + domain->orig_sysdep_tab = NULL; + domain->trans_sysdep_tab = NULL; + } - domain->hash_tab = inmem_hash_tab; - domain->must_swap_hash_tab = 0; + freea (sysdep_segment_values); } else { @@ -1299,8 +1398,7 @@ _nl_load_domain (domain_file, domainbinding) #ifdef _LIBC void internal_function -_nl_unload_domain (domain) - struct loaded_domain *domain; +_nl_unload_domain (struct loaded_domain *domain) { if (domain->plural != &__gettext_germanic_plural) __gettext_free_exp (domain->plural); diff --git a/intl/localcharset.c b/intl/localcharset.c index d04d05368..4865f1037 100644 --- a/intl/localcharset.c +++ b/intl/localcharset.c @@ -86,7 +86,7 @@ # define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) #endif -#ifdef HAVE_GETC_UNLOCKED +#if HAVE_DECL_GETC_UNLOCKED # undef getc # define getc getc_unlocked #endif diff --git a/intl/locale.alias b/intl/locale.alias index bd7b9b31e..bd6bb2562 100644 --- a/intl/locale.alias +++ b/intl/locale.alias @@ -1,5 +1,5 @@ # Locale name alias data base. -# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. +# Copyright (C) 1996-2001,2003 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published @@ -29,8 +29,8 @@ # Packages using this file: -bokmal no_NO.ISO-8859-1 -bokml no_NO.ISO-8859-1 +bokmal nb_NO.ISO-8859-1 +bokml nb_NO.ISO-8859-1 catalan ca_ES.ISO-8859-1 croatian hr_HR.ISO-8859-2 czech cs_CZ.ISO-8859-2 @@ -61,9 +61,9 @@ korean ko_KR.eucKR korean.euc ko_KR.eucKR ko_KR ko_KR.eucKR lithuanian lt_LT.ISO-8859-13 -nb_NO no_NO.ISO-8859-1 -nb_NO.ISO-8859-1 no_NO.ISO-8859-1 -norwegian no_NO.ISO-8859-1 +no_NO nb_NO.ISO-8859-1 +no_NO.ISO-8859-1 nb_NO.ISO-8859-1 +norwegian nb_NO.ISO-8859-1 nynorsk nn_NO.ISO-8859-1 polish pl_PL.ISO-8859-2 portuguese pt_PT.ISO-8859-1 diff --git a/intl/localealias.c b/intl/localealias.c index 7c4ce58f2..2eaf8813e 100644 --- a/intl/localealias.c +++ b/intl/localealias.c @@ -110,11 +110,11 @@ __libc_lock_define_initialized (static, lock); # define freea(p) free (p) #endif -#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED +#if defined _LIBC_REENTRANT || HAVE_DECL_FGETS_UNLOCKED # undef fgets # define fgets(buf, len, s) fgets_unlocked (buf, len, s) #endif -#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED +#if defined _LIBC_REENTRANT || HAVE_DECL_FEOF_UNLOCKED # undef feof # define feof(s) feof_unlocked (s) #endif @@ -140,16 +140,15 @@ static size_t maxmap; /* Prototypes for local functions. */ -static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) +static size_t read_alias_file (const char *fname, int fname_len) internal_function; -static int extend_alias_table PARAMS ((void)); -static int alias_compare PARAMS ((const struct alias_map *map1, - const struct alias_map *map2)); +static int extend_alias_table (void); +static int alias_compare (const struct alias_map *map1, + const struct alias_map *map2); const char * -_nl_expand_alias (name) - const char *name; +_nl_expand_alias (const char *name) { static const char *locale_alias_path; struct alias_map *retval; @@ -172,8 +171,8 @@ _nl_expand_alias (name) if (nmap > 0) retval = (struct alias_map *) bsearch (&item, map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, - const void *)) + (int (*) (const void *, + const void *) ) alias_compare); else retval = NULL; @@ -215,9 +214,7 @@ _nl_expand_alias (name) static size_t internal_function -read_alias_file (fname, fname_len) - const char *fname; - int fname_len; +read_alias_file (const char *fname, int fname_len) { FILE *fp; char *full_fname; @@ -361,7 +358,7 @@ read_alias_file (fname, fname_len) if (added > 0) qsort (map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, const void *))) alias_compare); + (int (*) (const void *, const void *)) alias_compare); return added; } @@ -387,9 +384,7 @@ extend_alias_table () static int -alias_compare (map1, map2) - const struct alias_map *map1; - const struct alias_map *map2; +alias_compare (const struct alias_map *map1, const struct alias_map *map2) { #if defined _LIBC || defined HAVE_STRCASECMP return strcasecmp (map1->alias, map2->alias); diff --git a/intl/localename.c b/intl/localename.c index faacecd50..5662e54ff 100644 --- a/intl/localename.c +++ b/intl/localename.c @@ -1,5 +1,5 @@ /* Determine the current selected locale. - Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000-2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -34,6 +34,124 @@ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include <windows.h> +/* List of language codes, sorted by value: + 0x01 LANG_ARABIC + 0x02 LANG_BULGARIAN + 0x03 LANG_CATALAN + 0x04 LANG_CHINESE + 0x05 LANG_CZECH + 0x06 LANG_DANISH + 0x07 LANG_GERMAN + 0x08 LANG_GREEK + 0x09 LANG_ENGLISH + 0x0a LANG_SPANISH + 0x0b LANG_FINNISH + 0x0c LANG_FRENCH + 0x0d LANG_HEBREW + 0x0e LANG_HUNGARIAN + 0x0f LANG_ICELANDIC + 0x10 LANG_ITALIAN + 0x11 LANG_JAPANESE + 0x12 LANG_KOREAN + 0x13 LANG_DUTCH + 0x14 LANG_NORWEGIAN + 0x15 LANG_POLISH + 0x16 LANG_PORTUGUESE + 0x17 LANG_RHAETO_ROMANCE + 0x18 LANG_ROMANIAN + 0x19 LANG_RUSSIAN + 0x1a LANG_CROATIAN == LANG_SERBIAN + 0x1b LANG_SLOVAK + 0x1c LANG_ALBANIAN + 0x1d LANG_SWEDISH + 0x1e LANG_THAI + 0x1f LANG_TURKISH + 0x20 LANG_URDU + 0x21 LANG_INDONESIAN + 0x22 LANG_UKRAINIAN + 0x23 LANG_BELARUSIAN + 0x24 LANG_SLOVENIAN + 0x25 LANG_ESTONIAN + 0x26 LANG_LATVIAN + 0x27 LANG_LITHUANIAN + 0x28 LANG_TAJIK + 0x29 LANG_FARSI + 0x2a LANG_VIETNAMESE + 0x2b LANG_ARMENIAN + 0x2c LANG_AZERI + 0x2d LANG_BASQUE + 0x2e LANG_SORBIAN + 0x2f LANG_MACEDONIAN + 0x30 LANG_SUTU + 0x31 LANG_TSONGA + 0x32 LANG_TSWANA + 0x33 LANG_VENDA + 0x34 LANG_XHOSA + 0x35 LANG_ZULU + 0x36 LANG_AFRIKAANS + 0x37 LANG_GEORGIAN + 0x38 LANG_FAEROESE + 0x39 LANG_HINDI + 0x3a LANG_MALTESE + 0x3b LANG_SAAMI + 0x3c LANG_GAELIC + 0x3d LANG_YIDDISH + 0x3e LANG_MALAY + 0x3f LANG_KAZAK + 0x40 LANG_KYRGYZ + 0x41 LANG_SWAHILI + 0x42 LANG_TURKMEN + 0x43 LANG_UZBEK + 0x44 LANG_TATAR + 0x45 LANG_BENGALI + 0x46 LANG_PUNJABI + 0x47 LANG_GUJARATI + 0x48 LANG_ORIYA + 0x49 LANG_TAMIL + 0x4a LANG_TELUGU + 0x4b LANG_KANNADA + 0x4c LANG_MALAYALAM + 0x4d LANG_ASSAMESE + 0x4e LANG_MARATHI + 0x4f LANG_SANSKRIT + 0x50 LANG_MONGOLIAN + 0x51 LANG_TIBETAN + 0x52 LANG_WELSH + 0x53 LANG_CAMBODIAN + 0x54 LANG_LAO + 0x55 LANG_BURMESE + 0x56 LANG_GALICIAN + 0x57 LANG_KONKANI + 0x58 LANG_MANIPURI + 0x59 LANG_SINDHI + 0x5a LANG_SYRIAC + 0x5b LANG_SINHALESE + 0x5c LANG_CHEROKEE + 0x5d LANG_INUKTITUT + 0x5e LANG_AMHARIC + 0x5f LANG_TAMAZIGHT + 0x60 LANG_KASHMIRI + 0x61 LANG_NEPALI + 0x62 LANG_FRISIAN + 0x63 LANG_PASHTO + 0x64 LANG_TAGALOG + 0x65 LANG_DIVEHI + 0x66 LANG_EDO + 0x67 LANG_FULFULDE + 0x68 LANG_HAUSA + 0x69 LANG_IBIBIO + 0x6a LANG_YORUBA + 0x70 LANG_IGBO + 0x71 LANG_KANURI + 0x72 LANG_OROMO + 0x73 LANG_TIGRINYA + 0x74 LANG_GUARANI + 0x75 LANG_HAWAIIAN + 0x76 LANG_LATIN + 0x77 LANG_SOMALI + 0x78 LANG_YI + 0x79 LANG_PAPIAMENTU +*/ /* Mingw headers don't have latest language and sublanguage codes. */ # ifndef LANG_AFRIKAANS # define LANG_AFRIKAANS 0x36 @@ -41,6 +159,9 @@ # ifndef LANG_ALBANIAN # define LANG_ALBANIAN 0x1c # endif +# ifndef LANG_AMHARIC +# define LANG_AMHARIC 0x5e +# endif # ifndef LANG_ARABIC # define LANG_ARABIC 0x01 # endif @@ -62,12 +183,24 @@ # ifndef LANG_BENGALI # define LANG_BENGALI 0x45 # endif +# ifndef LANG_BURMESE +# define LANG_BURMESE 0x55 +# endif +# ifndef LANG_CAMBODIAN +# define LANG_CAMBODIAN 0x53 +# endif # ifndef LANG_CATALAN # define LANG_CATALAN 0x03 # endif +# ifndef LANG_CHEROKEE +# define LANG_CHEROKEE 0x5c +# endif # ifndef LANG_DIVEHI # define LANG_DIVEHI 0x65 # endif +# ifndef LANG_EDO +# define LANG_EDO 0x66 +# endif # ifndef LANG_ESTONIAN # define LANG_ESTONIAN 0x25 # endif @@ -77,27 +210,57 @@ # ifndef LANG_FARSI # define LANG_FARSI 0x29 # endif +# ifndef LANG_FRISIAN +# define LANG_FRISIAN 0x62 +# endif +# ifndef LANG_FULFULDE +# define LANG_FULFULDE 0x67 +# endif +# ifndef LANG_GAELIC +# define LANG_GAELIC 0x3c +# endif # ifndef LANG_GALICIAN # define LANG_GALICIAN 0x56 # endif # ifndef LANG_GEORGIAN # define LANG_GEORGIAN 0x37 # endif +# ifndef LANG_GUARANI +# define LANG_GUARANI 0x74 +# endif # ifndef LANG_GUJARATI # define LANG_GUJARATI 0x47 # endif +# ifndef LANG_HAUSA +# define LANG_HAUSA 0x68 +# endif +# ifndef LANG_HAWAIIAN +# define LANG_HAWAIIAN 0x75 +# endif # ifndef LANG_HEBREW # define LANG_HEBREW 0x0d # endif # ifndef LANG_HINDI # define LANG_HINDI 0x39 # endif +# ifndef LANG_IBIBIO +# define LANG_IBIBIO 0x69 +# endif +# ifndef LANG_IGBO +# define LANG_IGBO 0x70 +# endif # ifndef LANG_INDONESIAN # define LANG_INDONESIAN 0x21 # endif +# ifndef LANG_INUKTITUT +# define LANG_INUKTITUT 0x5d +# endif # ifndef LANG_KANNADA # define LANG_KANNADA 0x4b # endif +# ifndef LANG_KANURI +# define LANG_KANURI 0x71 +# endif # ifndef LANG_KASHMIRI # define LANG_KASHMIRI 0x60 # endif @@ -110,6 +273,12 @@ # ifndef LANG_KYRGYZ # define LANG_KYRGYZ 0x40 # endif +# ifndef LANG_LAO +# define LANG_LAO 0x54 +# endif +# ifndef LANG_LATIN +# define LANG_LATIN 0x76 +# endif # ifndef LANG_LATVIAN # define LANG_LATVIAN 0x26 # endif @@ -125,6 +294,9 @@ # ifndef LANG_MALAYALAM # define LANG_MALAYALAM 0x4c # endif +# ifndef LANG_MALTESE +# define LANG_MALTESE 0x3a +# endif # ifndef LANG_MANIPURI # define LANG_MANIPURI 0x58 # endif @@ -140,9 +312,24 @@ # ifndef LANG_ORIYA # define LANG_ORIYA 0x48 # endif +# ifndef LANG_OROMO +# define LANG_OROMO 0x72 +# endif +# ifndef LANG_PAPIAMENTU +# define LANG_PAPIAMENTU 0x79 +# endif +# ifndef LANG_PASHTO +# define LANG_PASHTO 0x63 +# endif # ifndef LANG_PUNJABI # define LANG_PUNJABI 0x46 # endif +# ifndef LANG_RHAETO_ROMANCE +# define LANG_RHAETO_ROMANCE 0x17 +# endif +# ifndef LANG_SAAMI +# define LANG_SAAMI 0x3b +# endif # ifndef LANG_SANSKRIT # define LANG_SANSKRIT 0x4f # endif @@ -152,18 +339,36 @@ # ifndef LANG_SINDHI # define LANG_SINDHI 0x59 # endif +# ifndef LANG_SINHALESE +# define LANG_SINHALESE 0x5b +# endif # ifndef LANG_SLOVAK # define LANG_SLOVAK 0x1b # endif +# ifndef LANG_SOMALI +# define LANG_SOMALI 0x77 +# endif # ifndef LANG_SORBIAN # define LANG_SORBIAN 0x2e # endif +# ifndef LANG_SUTU +# define LANG_SUTU 0x30 +# endif # ifndef LANG_SWAHILI # define LANG_SWAHILI 0x41 # endif # ifndef LANG_SYRIAC # define LANG_SYRIAC 0x5a # endif +# ifndef LANG_TAGALOG +# define LANG_TAGALOG 0x64 +# endif +# ifndef LANG_TAJIK +# define LANG_TAJIK 0x28 +# endif +# ifndef LANG_TAMAZIGHT +# define LANG_TAMAZIGHT 0x5f +# endif # ifndef LANG_TAMIL # define LANG_TAMIL 0x49 # endif @@ -176,6 +381,21 @@ # ifndef LANG_THAI # define LANG_THAI 0x1e # endif +# ifndef LANG_TIBETAN +# define LANG_TIBETAN 0x51 +# endif +# ifndef LANG_TIGRINYA +# define LANG_TIGRINYA 0x73 +# endif +# ifndef LANG_TSONGA +# define LANG_TSONGA 0x31 +# endif +# ifndef LANG_TSWANA +# define LANG_TSWANA 0x32 +# endif +# ifndef LANG_TURKMEN +# define LANG_TURKMEN 0x42 +# endif # ifndef LANG_UKRAINIAN # define LANG_UKRAINIAN 0x22 # endif @@ -185,9 +405,30 @@ # ifndef LANG_UZBEK # define LANG_UZBEK 0x43 # endif +# ifndef LANG_VENDA +# define LANG_VENDA 0x33 +# endif # ifndef LANG_VIETNAMESE # define LANG_VIETNAMESE 0x2a # endif +# ifndef LANG_WELSH +# define LANG_WELSH 0x52 +# endif +# ifndef LANG_XHOSA +# define LANG_XHOSA 0x34 +# endif +# ifndef LANG_YI +# define LANG_YI 0x78 +# endif +# ifndef LANG_YIDDISH +# define LANG_YIDDISH 0x3d +# endif +# ifndef LANG_YORUBA +# define LANG_YORUBA 0x6a +# endif +# ifndef LANG_ZULU +# define LANG_ZULU 0x35 +# endif # ifndef SUBLANG_ARABIC_SAUDI_ARABIA # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 # endif @@ -242,6 +483,12 @@ # ifndef SUBLANG_AZERI_CYRILLIC # define SUBLANG_AZERI_CYRILLIC 0x02 # endif +# ifndef SUBLANG_BENGALI_INDIA +# define SUBLANG_BENGALI_INDIA 0x00 +# endif +# ifndef SUBLANG_BENGALI_BANGLADESH +# define SUBLANG_BENGALI_BANGLADESH 0x01 +# endif # ifndef SUBLANG_CHINESE_MACAU # define SUBLANG_CHINESE_MACAU 0x05 # endif @@ -266,12 +513,54 @@ # ifndef SUBLANG_ENGLISH_PHILIPPINES # define SUBLANG_ENGLISH_PHILIPPINES 0x0d # endif +# ifndef SUBLANG_ENGLISH_INDONESIA +# define SUBLANG_ENGLISH_INDONESIA 0x0e +# endif +# ifndef SUBLANG_ENGLISH_HONGKONG +# define SUBLANG_ENGLISH_HONGKONG 0x0f +# endif +# ifndef SUBLANG_ENGLISH_INDIA +# define SUBLANG_ENGLISH_INDIA 0x10 +# endif +# ifndef SUBLANG_ENGLISH_MALAYSIA +# define SUBLANG_ENGLISH_MALAYSIA 0x11 +# endif +# ifndef SUBLANG_ENGLISH_SINGAPORE +# define SUBLANG_ENGLISH_SINGAPORE 0x12 +# endif # ifndef SUBLANG_FRENCH_LUXEMBOURG # define SUBLANG_FRENCH_LUXEMBOURG 0x05 # endif # ifndef SUBLANG_FRENCH_MONACO # define SUBLANG_FRENCH_MONACO 0x06 # endif +# ifndef SUBLANG_FRENCH_WESTINDIES +# define SUBLANG_FRENCH_WESTINDIES 0x07 +# endif +# ifndef SUBLANG_FRENCH_REUNION +# define SUBLANG_FRENCH_REUNION 0x08 +# endif +# ifndef SUBLANG_FRENCH_CONGO +# define SUBLANG_FRENCH_CONGO 0x09 +# endif +# ifndef SUBLANG_FRENCH_SENEGAL +# define SUBLANG_FRENCH_SENEGAL 0x0a +# endif +# ifndef SUBLANG_FRENCH_CAMEROON +# define SUBLANG_FRENCH_CAMEROON 0x0b +# endif +# ifndef SUBLANG_FRENCH_COTEDIVOIRE +# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c +# endif +# ifndef SUBLANG_FRENCH_MALI +# define SUBLANG_FRENCH_MALI 0x0d +# endif +# ifndef SUBLANG_FRENCH_MOROCCO +# define SUBLANG_FRENCH_MOROCCO 0x0e +# endif +# ifndef SUBLANG_FRENCH_HAITI +# define SUBLANG_FRENCH_HAITI 0x0f +# endif # ifndef SUBLANG_GERMAN_LUXEMBOURG # define SUBLANG_GERMAN_LUXEMBOURG 0x04 # endif @@ -290,12 +579,30 @@ # ifndef SUBLANG_NEPALI_INDIA # define SUBLANG_NEPALI_INDIA 0x02 # endif +# ifndef SUBLANG_PUNJABI_INDIA +# define SUBLANG_PUNJABI_INDIA 0x00 +# endif +# ifndef SUBLANG_PUNJABI_PAKISTAN +# define SUBLANG_PUNJABI_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_ROMANIAN_ROMANIA +# define SUBLANG_ROMANIAN_ROMANIA 0x00 +# endif +# ifndef SUBLANG_ROMANIAN_MOLDOVA +# define SUBLANG_ROMANIAN_MOLDOVA 0x01 +# endif # ifndef SUBLANG_SERBIAN_LATIN # define SUBLANG_SERBIAN_LATIN 0x02 # endif # ifndef SUBLANG_SERBIAN_CYRILLIC # define SUBLANG_SERBIAN_CYRILLIC 0x03 # endif +# ifndef SUBLANG_SINDHI_INDIA +# define SUBLANG_SINDHI_INDIA 0x00 +# endif +# ifndef SUBLANG_SINDHI_PAKISTAN +# define SUBLANG_SINDHI_PAKISTAN 0x01 +# endif # ifndef SUBLANG_SPANISH_GUATEMALA # define SUBLANG_SPANISH_GUATEMALA 0x04 # endif @@ -350,6 +657,18 @@ # ifndef SUBLANG_SWEDISH_FINLAND # define SUBLANG_SWEDISH_FINLAND 0x02 # endif +# ifndef SUBLANG_TAMAZIGHT_ARABIC +# define SUBLANG_TAMAZIGHT_ARABIC 0x01 +# endif +# ifndef SUBLANG_TAMAZIGHT_LATIN +# define SUBLANG_TAMAZIGHT_LATIN 0x02 +# endif +# ifndef SUBLANG_TIGRINYA_ETHIOPIA +# define SUBLANG_TIGRINYA_ETHIOPIA 0x00 +# endif +# ifndef SUBLANG_TIGRINYA_ERITREA +# define SUBLANG_TIGRINYA_ERITREA 0x01 +# endif # ifndef SUBLANG_URDU_PAKISTAN # define SUBLANG_URDU_PAKISTAN 0x01 # endif @@ -381,9 +700,7 @@ The result must not be freed; it is statically allocated. */ const char * -_nl_locale_name (category, categoryname) - int category; - const char *categoryname; +_nl_locale_name (int category, const char *categoryname) { const char *retval; @@ -454,7 +771,7 @@ _nl_locale_name (category, categoryname) { case LANG_AFRIKAANS: return "af_ZA"; case LANG_ALBANIAN: return "sq_AL"; - case 0x5e: /* AMHARIC */ return "am_ET"; + case LANG_AMHARIC: return "am_ET"; case LANG_ARABIC: switch (sub) { @@ -489,12 +806,18 @@ _nl_locale_name (category, categoryname) case LANG_BASQUE: return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ case LANG_BELARUSIAN: return "be_BY"; - case LANG_BENGALI: return "bn_IN"; + case LANG_BENGALI: + switch (sub) + { + case SUBLANG_BENGALI_INDIA: return "bn_IN"; + case SUBLANG_BENGALI_BANGLADESH: return "bn_BD"; + } + return "bn"; case LANG_BULGARIAN: return "bg_BG"; - case 0x55: /* BURMESE */ return "my_MM"; - case 0x53: /* CAMBODIAN */ return "km_KH"; + case LANG_BURMESE: return "my_MM"; + case LANG_CAMBODIAN: return "km_KH"; case LANG_CATALAN: return "ca_ES"; - case 0x5c: /* CHEROKEE */ return "chr_US"; + case LANG_CHEROKEE: return "chr_US"; case LANG_CHINESE: switch (sub) { @@ -516,13 +839,13 @@ _nl_locale_name (category, categoryname) switch (sub) { case SUBLANG_DEFAULT: return "hr_HR"; - case SUBLANG_SERBIAN_LATIN: return "sr_YU"; - case SUBLANG_SERBIAN_CYRILLIC: return "sr_YU@cyrillic"; + case SUBLANG_SERBIAN_LATIN: return "sr_CS"; + case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic"; } return "hr"; case LANG_CZECH: return "cs_CZ"; case LANG_DANISH: return "da_DK"; - case LANG_DIVEHI: return "div_MV"; + case LANG_DIVEHI: return "dv_MV"; case LANG_DUTCH: switch (sub) { @@ -530,7 +853,7 @@ _nl_locale_name (category, categoryname) case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; } return "nl"; - case 0x66: /* EDO */ return "bin_NG"; + case LANG_EDO: return "bin_NG"; case LANG_ENGLISH: switch (sub) { @@ -551,6 +874,11 @@ _nl_locale_name (category, categoryname) case SUBLANG_ENGLISH_TRINIDAD: return "en_TT"; case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW"; case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH"; + case SUBLANG_ENGLISH_INDONESIA: return "en_ID"; + case SUBLANG_ENGLISH_HONGKONG: return "en_HK"; + case SUBLANG_ENGLISH_INDIA: return "en_IN"; + case SUBLANG_ENGLISH_MALAYSIA: return "en_MY"; + case SUBLANG_ENGLISH_SINGAPORE: return "en_SG"; } return "en"; case LANG_ESTONIAN: return "et_EE"; @@ -566,11 +894,22 @@ _nl_locale_name (category, categoryname) case SUBLANG_FRENCH_SWISS: return "fr_CH"; case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU"; case SUBLANG_FRENCH_MONACO: return "fr_MC"; + case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */ + case SUBLANG_FRENCH_REUNION: return "fr_RE"; + case SUBLANG_FRENCH_CONGO: return "fr_CG"; + case SUBLANG_FRENCH_SENEGAL: return "fr_SN"; + case SUBLANG_FRENCH_CAMEROON: return "fr_CM"; + case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI"; + case SUBLANG_FRENCH_MALI: return "fr_ML"; + case SUBLANG_FRENCH_MOROCCO: return "fr_MA"; + case SUBLANG_FRENCH_HAITI: return "fr_HT"; } return "fr"; - case 0x62: /* FRISIAN */ return "fy_NL"; - case 0x67: /* FULFULDE */ return "ful_NG"; - case 0x3c: /* GAELIC */ + case LANG_FRISIAN: return "fy_NL"; + case LANG_FULFULDE: + /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */ + return "ff_NG"; + case LANG_GAELIC: switch (sub) { case 0x01: /* SCOTTISH */ return "gd_GB"; @@ -590,21 +929,21 @@ _nl_locale_name (category, categoryname) } return "de"; case LANG_GREEK: return "el_GR"; - case 0x74: /* GUARANI */ return "gn_PY"; + case LANG_GUARANI: return "gn_PY"; case LANG_GUJARATI: return "gu_IN"; - case 0x68: /* HAUSA */ return "ha_NG"; - case 0x75: /* HAWAIIAN */ + case LANG_HAUSA: return "ha_NG"; + case LANG_HAWAIIAN: /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) or Hawaii Creole English ("cpe_US", 600000 speakers)? */ return "cpe_US"; case LANG_HEBREW: return "he_IL"; case LANG_HINDI: return "hi_IN"; case LANG_HUNGARIAN: return "hu_HU"; - case 0x69: /* IBIBIO */ return "nic_NG"; + case LANG_IBIBIO: return "nic_NG"; case LANG_ICELANDIC: return "is_IS"; - case 0x70: /* IGBO */ return "ibo_NG"; + case LANG_IGBO: return "ig_NG"; case LANG_INDONESIAN: return "id_ID"; - case 0x5d: /* INUKTITUT */ return "iu_CA"; + case LANG_INUKTITUT: return "iu_CA"; case LANG_ITALIAN: switch (sub) { @@ -614,7 +953,7 @@ _nl_locale_name (category, categoryname) return "it"; case LANG_JAPANESE: return "ja_JP"; case LANG_KANNADA: return "kn_IN"; - case 0x71: /* KANURI */ return "kau_NG"; + case LANG_KANURI: return "kr_NG"; case LANG_KASHMIRI: switch (sub) { @@ -628,8 +967,8 @@ _nl_locale_name (category, categoryname) return "kok_IN"; case LANG_KOREAN: return "ko_KR"; case LANG_KYRGYZ: return "ky_KG"; - case 0x54: /* LAO */ return "lo_LA"; - case 0x76: /* LATIN */ return "la_VA"; + case LANG_LAO: return "lo_LA"; + case LANG_LATIN: return "la_VA"; case LANG_LATVIAN: return "lv_LV"; case LANG_LITHUANIAN: return "lt_LT"; case LANG_MACEDONIAN: return "mk_MK"; @@ -641,7 +980,7 @@ _nl_locale_name (category, categoryname) } return "ms"; case LANG_MALAYALAM: return "ml_IN"; - case 0x3a: /* MALTESE */ return "mt_MT"; + case LANG_MALTESE: return "mt_MT"; case LANG_MANIPURI: /* FIXME: Adjust this when such locales appear on Unix. */ return "mni_IN"; @@ -663,9 +1002,9 @@ _nl_locale_name (category, categoryname) } return "no"; case LANG_ORIYA: return "or_IN"; - case 0x72: /* OROMO */ return "om_ET"; - case 0x79: /* PAPIAMENTU */ return "pap_AN"; - case 0x63: /* PASHTO */ + case LANG_OROMO: return "om_ET"; + case LANG_PAPIAMENTU: return "pap_AN"; + case LANG_PASHTO: return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ case LANG_POLISH: return "pl_PL"; case LANG_PORTUGUESE: @@ -677,18 +1016,36 @@ _nl_locale_name (category, categoryname) case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; } return "pt"; - case LANG_PUNJABI: return "pa_IN"; - case 0x17: /* RHAETO-ROMANCE */ return "rm_CH"; - case LANG_ROMANIAN: return "ro_RO"; + case LANG_PUNJABI: + switch (sub) + { + case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ + case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */ + } + return "pa"; + case LANG_RHAETO_ROMANCE: return "rm_CH"; + case LANG_ROMANIAN: + switch (sub) + { + case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; + case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD"; + } + return "ro"; case LANG_RUSSIAN: - return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA". */ - case 0x3b: /* SAMI */ return "se_NO"; + return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */ + case LANG_SAAMI: /* actually Northern Sami */ return "se_NO"; case LANG_SANSKRIT: return "sa_IN"; - case LANG_SINDHI: return "sd"; - case 0x5b: /* SINHALESE */ return "si_LK"; + case LANG_SINDHI: + switch (sub) + { + case SUBLANG_SINDHI_INDIA: return "sd_IN"; + case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; + } + return "sd"; + case LANG_SINHALESE: return "si_LK"; case LANG_SLOVAK: return "sk_SK"; case LANG_SLOVENIAN: return "sl_SI"; - case 0x77: /* SOMALI */ return "so_SO"; + case LANG_SOMALI: return "so_SO"; case LANG_SORBIAN: /* FIXME: Adjust this when such locales appear on Unix. */ return "wen_DE"; @@ -718,7 +1075,7 @@ _nl_locale_name (category, categoryname) case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR"; } return "es"; - case 0x30: /* SUTU */ return "bnt_TZ"; + case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */ case LANG_SWAHILI: return "sw_KE"; case LANG_SWEDISH: switch (sub) @@ -728,19 +1085,33 @@ _nl_locale_name (category, categoryname) } return "sv"; case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */ - case 0x64: /* TAGALOG */ return "tl_PH"; - case 0x28: /* TAJIK */ return "tg_TJ"; - case 0x5f: /* TAMAZIGHT */ return "ber_MA"; + case LANG_TAGALOG: return "tl_PH"; + case LANG_TAJIK: return "tg_TJ"; + case LANG_TAMAZIGHT: + switch (sub) + { + /* FIXME: Adjust this when Tamazight locales appear on Unix. */ + case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; + case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin"; + } + return "ber_MA"; case LANG_TAMIL: return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ case LANG_TATAR: return "tt_RU"; case LANG_TELUGU: return "te_IN"; case LANG_THAI: return "th_TH"; - case 0x51: /* TIBETAN */ return "bo_CN"; - case 0x73: /* TIGRINYA */ return "ti_ET"; - case 0x31: /* TSONGA */ return "ts_ZA"; + case LANG_TIBETAN: return "bo_CN"; + case LANG_TIGRINYA: + switch (sub) + { + case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET"; + case SUBLANG_TIGRINYA_ERITREA: return "ti_ER"; + } + return "ti"; + case LANG_TSONGA: return "ts_ZA"; + case LANG_TSWANA: return "tn_BW"; case LANG_TURKISH: return "tr_TR"; - case 0x42: /* TURKMEN */ return "tk_TM"; + case LANG_TURKMEN: return "tk_TM"; case LANG_UKRAINIAN: return "uk_UA"; case LANG_URDU: switch (sub) @@ -752,19 +1123,18 @@ _nl_locale_name (category, categoryname) case LANG_UZBEK: switch (sub) { - /* FIXME: Adjust this when Uzbek locales appear on Unix. */ - case SUBLANG_UZBEK_LATIN: return "uz_UZ@latin"; + case SUBLANG_UZBEK_LATIN: return "uz_UZ"; case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; } return "uz"; - case 0x33: /* VENDA */ return "ven_ZA"; + case LANG_VENDA: return "ve_ZA"; case LANG_VIETNAMESE: return "vi_VN"; - case 0x52: /* WELSH */ return "cy_GB"; - case 0x34: /* XHOSA */ return "xh_ZA"; - case 0x78: /* YI */ return "sit_CN"; - case 0x3d: /* YIDDISH */ return "yi_IL"; - case 0x6a: /* YORUBA */ return "yo_NG"; - case 0x35: /* ZULU */ return "zu_ZA"; + case LANG_WELSH: return "cy_GB"; + case LANG_XHOSA: return "xh_ZA"; + case LANG_YI: return "sit_CN"; + case LANG_YIDDISH: return "yi_IL"; + case LANG_YORUBA: return "yo_NG"; + case LANG_ZULU: return "zu_ZA"; default: return "C"; } diff --git a/intl/log.c b/intl/log.c index 9c84791b9..cb6076e80 100644 --- a/intl/log.c +++ b/intl/log.c @@ -28,9 +28,7 @@ /* Print an ASCII string with quotes and escape sequences where needed. */ static void -print_escaped (stream, str) - FILE *stream; - const char *str; +print_escaped (FILE *stream, const char *str) { putc ('"', stream); for (; *str != '\0'; str++) @@ -52,12 +50,8 @@ print_escaped (stream, str) /* Add to the log file an entry denoting a failed translation. */ void -_nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural) - const char *logfilename; - const char *domainname; - const char *msgid1; - const char *msgid2; - int plural; +_nl_log_untranslated (const char *logfilename, const char *domainname, + const char *msgid1, const char *msgid2, int plural) { static char *last_logfilename = NULL; static FILE *last_logfile = NULL; diff --git a/intl/ngettext.c b/intl/ngettext.c index 17a27f4aa..e73e00c48 100644 --- a/intl/ngettext.c +++ b/intl/ngettext.c @@ -1,5 +1,5 @@ /* Implementation of ngettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -54,10 +54,7 @@ LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ char * -NGETTEXT (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; +NGETTEXT (const char *msgid1, const char *msgid2, unsigned long int n) { return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES); } diff --git a/intl/plural-exp.c b/intl/plural-exp.c index c937c011a..8c04e6426 100644 --- a/intl/plural-exp.c +++ b/intl/plural-exp.c @@ -1,5 +1,5 @@ /* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2003 Free Software Foundation, Inc. Written by Ulrich Drepper <drepper@cygnus.com>, 2000. This program is free software; you can redistribute it and/or modify it @@ -96,10 +96,8 @@ init_germanic_plural () void internal_function -EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp) - const char *nullentry; - struct expression **pluralp; - unsigned long int *npluralsp; +EXTRACT_PLURAL_EXPRESSION (const char *nullentry, struct expression **pluralp, + unsigned long int *npluralsp) { if (nullentry != NULL) { diff --git a/intl/plural-exp.h b/intl/plural-exp.h index 9e5d16583..49e2c5bfc 100644 --- a/intl/plural-exp.h +++ b/intl/plural-exp.h @@ -1,5 +1,5 @@ /* Expression parsing and evaluation for plural form selection. - Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 2000-2003 Free Software Foundation, Inc. Written by Ulrich Drepper <drepper@cygnus.com>, 2000. This program is free software; you can redistribute it and/or modify it @@ -20,14 +20,6 @@ #ifndef _PLURAL_EXP_H #define _PLURAL_EXP_H -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - #ifndef internal_function # define internal_function #endif @@ -109,18 +101,18 @@ struct parse_args # define EXTRACT_PLURAL_EXPRESSION extract_plural_expression #endif -extern void FREE_EXPRESSION PARAMS ((struct expression *exp)) +extern void FREE_EXPRESSION (struct expression *exp) internal_function; -extern int PLURAL_PARSE PARAMS ((void *arg)); +extern int PLURAL_PARSE (void *arg); extern struct expression GERMANIC_PLURAL attribute_hidden; -extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry, - struct expression **pluralp, - unsigned long int *npluralsp)) +extern void EXTRACT_PLURAL_EXPRESSION (const char *nullentry, + struct expression **pluralp, + unsigned long int *npluralsp) internal_function; #if !defined (_LIBC) && !defined (IN_LIBINTL) -extern unsigned long int plural_eval PARAMS ((struct expression *pexp, - unsigned long int n)); +extern unsigned long int plural_eval (struct expression *pexp, + unsigned long int n); #endif #endif /* _PLURAL_EXP_H */ diff --git a/intl/plural.c b/intl/plural.c index 3a4fa20ca..72494f9eb 100644 --- a/intl/plural.c +++ b/intl/plural.c @@ -19,7 +19,7 @@ #line 1 "plural.y" /* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2003 Free Software Foundation, Inc. Written by Ulrich Drepper <drepper@cygnus.com>, 2000. This program is free software; you can redistribute it and/or modify it @@ -75,28 +75,13 @@ typedef union { #line 55 "plural.y" /* Prototypes for local functions. */ -static struct expression *new_exp PARAMS ((int nargs, enum operator op, - struct expression * const *args)); -static inline struct expression *new_exp_0 PARAMS ((enum operator op)); -static inline struct expression *new_exp_1 PARAMS ((enum operator op, - struct expression *right)); -static struct expression *new_exp_2 PARAMS ((enum operator op, - struct expression *left, - struct expression *right)); -static inline struct expression *new_exp_3 PARAMS ((enum operator op, - struct expression *bexp, - struct expression *tbranch, - struct expression *fbranch)); -static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); -static void yyerror PARAMS ((const char *str)); +static int yylex (YYSTYPE *lval, const char **pexp); +static void yyerror (const char *str); /* Allocation of expressions. */ static struct expression * -new_exp (nargs, op, args) - int nargs; - enum operator op; - struct expression * const *args; +new_exp (int nargs, enum operator op, struct expression * const *args) { int i; struct expression *newp; @@ -125,16 +110,13 @@ new_exp (nargs, op, args) } static inline struct expression * -new_exp_0 (op) - enum operator op; +new_exp_0 (enum operator op) { return new_exp (0, op, NULL); } static inline struct expression * -new_exp_1 (op, right) - enum operator op; - struct expression *right; +new_exp_1 (enum operator op, struct expression *right) { struct expression *args[1]; @@ -143,10 +125,7 @@ new_exp_1 (op, right) } static struct expression * -new_exp_2 (op, left, right) - enum operator op; - struct expression *left; - struct expression *right; +new_exp_2 (enum operator op, struct expression *left, struct expression *right) { struct expression *args[2]; @@ -156,11 +135,8 @@ new_exp_2 (op, left, right) } static inline struct expression * -new_exp_3 (op, bexp, tbranch, fbranch) - enum operator op; - struct expression *bexp; - struct expression *tbranch; - struct expression *fbranch; +new_exp_3 (enum operator op, struct expression *bexp, + struct expression *tbranch, struct expression *fbranch) { struct expression *args[3]; @@ -236,8 +212,8 @@ static const short yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const short yyrline[] = { - 0, 174, 182, 186, 190, 194, 198, 202, 206, 210, - 214, 218, 223 + 0, 150, 158, 162, 166, 170, 174, 178, 182, 186, + 190, 194, 199 }; #endif @@ -1027,7 +1003,7 @@ yyreduce: switch (yyn) { case 1: -#line 175 "plural.y" +#line 151 "plural.y" { if (yyvsp[0].exp == NULL) YYABORT; @@ -1035,68 +1011,68 @@ case 1: } break; case 2: -#line 183 "plural.y" +#line 159 "plural.y" { yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); } break; case 3: -#line 187 "plural.y" +#line 163 "plural.y" { yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); } break; case 4: -#line 191 "plural.y" +#line 167 "plural.y" { yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); } break; case 5: -#line 195 "plural.y" +#line 171 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); } break; case 6: -#line 199 "plural.y" +#line 175 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); } break; case 7: -#line 203 "plural.y" +#line 179 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); } break; case 8: -#line 207 "plural.y" +#line 183 "plural.y" { yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); } break; case 9: -#line 211 "plural.y" +#line 187 "plural.y" { yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); } break; case 10: -#line 215 "plural.y" +#line 191 "plural.y" { yyval.exp = new_exp_0 (var); } break; case 11: -#line 219 "plural.y" +#line 195 "plural.y" { if ((yyval.exp = new_exp_0 (num)) != NULL) yyval.exp->val.num = yyvsp[0].num; } break; case 12: -#line 224 "plural.y" +#line 200 "plural.y" { yyval.exp = yyvsp[-1].exp; } @@ -1334,13 +1310,12 @@ yyreturn: #endif return yyresult; } -#line 229 "plural.y" +#line 205 "plural.y" void internal_function -FREE_EXPRESSION (exp) - struct expression *exp; +FREE_EXPRESSION (struct expression *exp) { if (exp == NULL) return; @@ -1366,9 +1341,7 @@ FREE_EXPRESSION (exp) static int -yylex (lval, pexp) - YYSTYPE *lval; - const char **pexp; +yylex (YYSTYPE *lval, const char **pexp) { const char *exp = *pexp; int result; @@ -1511,8 +1484,7 @@ yylex (lval, pexp) static void -yyerror (str) - const char *str; +yyerror (const char *str) { /* Do nothing. We don't print error messages here. */ } diff --git a/intl/plural.y b/intl/plural.y index 616b7c11a..4d33bd7c7 100644 --- a/intl/plural.y +++ b/intl/plural.y @@ -1,6 +1,6 @@ %{ /* Expression parsing for plural form selection. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2003 Free Software Foundation, Inc. Written by Ulrich Drepper <drepper@cygnus.com>, 2000. This program is free software; you can redistribute it and/or modify it @@ -54,28 +54,13 @@ %{ /* Prototypes for local functions. */ -static struct expression *new_exp PARAMS ((int nargs, enum operator op, - struct expression * const *args)); -static inline struct expression *new_exp_0 PARAMS ((enum operator op)); -static inline struct expression *new_exp_1 PARAMS ((enum operator op, - struct expression *right)); -static struct expression *new_exp_2 PARAMS ((enum operator op, - struct expression *left, - struct expression *right)); -static inline struct expression *new_exp_3 PARAMS ((enum operator op, - struct expression *bexp, - struct expression *tbranch, - struct expression *fbranch)); -static int yylex PARAMS ((YYSTYPE *lval, const char **pexp)); -static void yyerror PARAMS ((const char *str)); +static int yylex (YYSTYPE *lval, const char **pexp); +static void yyerror (const char *str); /* Allocation of expressions. */ static struct expression * -new_exp (nargs, op, args) - int nargs; - enum operator op; - struct expression * const *args; +new_exp (int nargs, enum operator op, struct expression * const *args) { int i; struct expression *newp; @@ -104,16 +89,13 @@ new_exp (nargs, op, args) } static inline struct expression * -new_exp_0 (op) - enum operator op; +new_exp_0 (enum operator op) { return new_exp (0, op, NULL); } static inline struct expression * -new_exp_1 (op, right) - enum operator op; - struct expression *right; +new_exp_1 (enum operator op, struct expression *right) { struct expression *args[1]; @@ -122,10 +104,7 @@ new_exp_1 (op, right) } static struct expression * -new_exp_2 (op, left, right) - enum operator op; - struct expression *left; - struct expression *right; +new_exp_2 (enum operator op, struct expression *left, struct expression *right) { struct expression *args[2]; @@ -135,11 +114,8 @@ new_exp_2 (op, left, right) } static inline struct expression * -new_exp_3 (op, bexp, tbranch, fbranch) - enum operator op; - struct expression *bexp; - struct expression *tbranch; - struct expression *fbranch; +new_exp_3 (enum operator op, struct expression *bexp, + struct expression *tbranch, struct expression *fbranch) { struct expression *args[3]; @@ -230,8 +206,7 @@ exp: exp '?' exp ':' exp void internal_function -FREE_EXPRESSION (exp) - struct expression *exp; +FREE_EXPRESSION (struct expression *exp) { if (exp == NULL) return; @@ -257,9 +232,7 @@ FREE_EXPRESSION (exp) static int -yylex (lval, pexp) - YYSTYPE *lval; - const char **pexp; +yylex (YYSTYPE *lval, const char **pexp) { const char *exp = *pexp; int result; @@ -402,8 +375,7 @@ yylex (lval, pexp) static void -yyerror (str) - const char *str; +yyerror (const char *str) { /* Do nothing. We don't print error messages here. */ } diff --git a/intl/relocatable.c b/intl/relocatable.c index 16f79a528..bf7c70854 100644 --- a/intl/relocatable.c +++ b/intl/relocatable.c @@ -42,7 +42,12 @@ #ifdef NO_XMALLOC # define xmalloc malloc #else -# include "xmalloc.h" +# include "xalloc.h" +#endif + +#if defined _WIN32 || defined __WIN32__ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> #endif #if DEPENDS_ON_LIBCHARSET @@ -152,6 +157,8 @@ set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg) #endif } +#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR) + /* Convenience function: Computes the current installation prefix, based on the original installation prefix, the original installation directory of a particular @@ -266,6 +273,8 @@ compute_curr_prefix (const char *orig_installprefix, } } +#endif /* !IN_LIBRARY || PIC */ + #if defined PIC && defined INSTALLDIR /* Full pathname of shared library, or NULL. */ @@ -304,7 +313,8 @@ DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved) static void find_shared_library_fullname () { -#ifdef __linux__ +#if defined __linux__ && __GLIBC__ >= 2 + /* Linux has /proc/self/maps. glibc 2 has the getline() function. */ FILE *fp; /* Open the current process' maps file. It describes one VMA per line. */ diff --git a/intl/relocatable.h b/intl/relocatable.h index d141200a6..48c5b71e2 100644 --- a/intl/relocatable.h +++ b/intl/relocatable.h @@ -20,6 +20,11 @@ #ifndef _RELOCATABLE_H #define _RELOCATABLE_H +#ifdef __cplusplus +extern "C" { +#endif + + /* This can be enabled through the configure --enable-relocatable option. */ #if ENABLE_RELOCATABLE @@ -64,4 +69,9 @@ extern const char * compute_curr_prefix (const char *orig_installprefix, #endif + +#ifdef __cplusplus +} +#endif + #endif /* _RELOCATABLE_H */ diff --git a/intl/textdomain.c b/intl/textdomain.c index f259c696d..8745a8435 100644 --- a/intl/textdomain.c +++ b/intl/textdomain.c @@ -1,5 +1,5 @@ /* Implementation of the textdomain(3) function. - Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published @@ -77,8 +77,7 @@ __libc_rwlock_define (extern, _nl_state_lock attribute_hidden) If DOMAINNAME is null, return the current default. If DOMAINNAME is "", reset to the default of "messages". */ char * -TEXTDOMAIN (domainname) - const char *domainname; +TEXTDOMAIN (const char *domainname) { char *new_domain; char *old_domain; diff --git a/kbx/ChangeLog b/kbx/ChangeLog index f13434de8..546b4c34d 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,7 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * Makefile.am: Adjusted fro gettext 0.14. + 2004-08-24 Werner Koch <wk@g10code.de> * kbxutil.c: New command --import-openpgp. diff --git a/kbx/Makefile.am b/kbx/Makefile.am index 6b6a59b26..0b35587cb 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -45,7 +45,7 @@ libkeybox_a_SOURCES = $(common_sources) kbxutil_SOURCES = kbxutil.c $(common_sources) kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ - -lgpg-error @INTLLIBS@ + -lgpg-error @LIBINTL@ diff --git a/m4/ChangeLog b/m4/ChangeLog index efcded757..a7a9d1e36 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,25 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * gpg-error.m4, libassuan.m4, libgcrypt.m4: Updated. + +2004-09-30 gettextize <bug-gnu-gettext@gnu.org> + + * gettext.m4: Upgrade to gettext-0.14.1. + * intmax.m4: New file, from gettext-0.14.1. + * lib-ld.m4: Upgrade to gettext-0.14.1. + * lib-prefix.m4: Upgrade to gettext-0.14.1. + * longdouble.m4: New file, from gettext-0.14.1. + * longlong.m4: New file, from gettext-0.14.1. + * po.m4: Upgrade to gettext-0.14.1. + * printf-posix.m4: New file, from gettext-0.14.1. + * signed.m4: New file, from gettext-0.14.1. + * size_max.m4: New file, from gettext-0.14.1. + * ulonglong.m4: Upgrade to gettext-0.14.1. + * wchar_t.m4: New file, from gettext-0.14.1. + * wint_t.m4: New file, from gettext-0.14.1. + * xsize.m4: New file, from gettext-0.14.1. + * Makefile.am (EXTRA_DIST): Add the new files. + 2004-03-06 Werner Koch <wk@gnupg.org> * libgcrypt.m4: Updated. diff --git a/m4/Makefile.am b/m4/Makefile.am index 0eb02f694..a31103ff6 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -1,3 +1,3 @@ -EXTRA_DIST = codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 +EXTRA_DIST = intmax.m4 longdouble.m4 longlong.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 EXTRA_DIST += gpg-error.m4 libgcrypt.m4 libassuan.m4 ksba.m4 diff --git a/m4/gettext.m4 b/m4/gettext.m4 index 16070b40a..a374f03fa 100644 --- a/m4/gettext.m4 +++ b/m4/gettext.m4 @@ -1,4 +1,4 @@ -# gettext.m4 serial 20 (gettext-0.12) +# gettext.m4 serial 28 (gettext-0.13) dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General @@ -354,9 +354,18 @@ AC_DEFUN([AM_INTL_SUBDIR], AC_REQUIRE([AC_ISC_POSIX])dnl AC_REQUIRE([AC_HEADER_STDC])dnl AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([bh_C_SIGNED])dnl AC_REQUIRE([AC_C_INLINE])dnl AC_REQUIRE([AC_TYPE_OFF_T])dnl AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([jm_AC_TYPE_LONG_LONG])dnl + AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([jm_AC_HEADER_STDINT_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) AC_REQUIRE([AC_FUNC_ALLOCA])dnl AC_REQUIRE([AC_FUNC_MMAP])dnl AC_REQUIRE([jm_GLIBC21])dnl @@ -364,14 +373,57 @@ AC_DEFUN([AM_INTL_SUBDIR], AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])dnl AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ stdlib.h string.h unistd.h sys/param.h]) - AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \ -geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \ -strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next \ + AC_CHECK_FUNCS([asprintf fwprintf getcwd getegid geteuid getgid getuid \ +mempcpy munmap putenv setenv setlocale snprintf stpcpy strcasecmp strdup \ +strtoul tsearch wcslen __argz_count __argz_stringify __argz_next \ __fsetlocking]) + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include <stdio.h>]) + gt_CHECK_DECL(_snwprintf, [#include <stdio.h>]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(feof_unlocked, [#include <stdio.h>]) + gt_CHECK_DECL(fgets_unlocked, [#include <stdio.h>]) + gt_CHECK_DECL(getc_unlocked, [#include <stdio.h>]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + AM_ICONV AM_LANGINFO_CODESET if test $ac_cv_header_locale_h = yes; then @@ -411,5 +463,25 @@ changequote([,])dnl ]) +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, + [AC_TRY_COMPILE([$2], [ +#ifndef $1 + char *p = (char *) $1; +#endif +], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) + + dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/m4/gpg-error.m4 b/m4/gpg-error.m4 index 931630b14..a5875f004 100644 --- a/m4/gpg-error.m4 +++ b/m4/gpg-error.m4 @@ -4,7 +4,7 @@ dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS dnl -AC_DEFUN(AM_PATH_GPG_ERROR, +AC_DEFUN([AM_PATH_GPG_ERROR], [ AC_ARG_WITH(gpg-error-prefix, AC_HELP_STRING([--with-gpg-error-prefix=PFX], [prefix where GPG Error is installed (optional)]), diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 index 11d0ce773..38aeaec19 100644 --- a/m4/lib-ld.m4 +++ b/m4/lib-ld.m4 @@ -1,4 +1,4 @@ -# lib-ld.m4 serial 2 (gettext-0.12) +# lib-ld.m4 serial 3 (gettext-0.13) dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General @@ -14,11 +14,12 @@ dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. -if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then - acl_cv_prog_gnu_ld=yes -else - acl_cv_prog_gnu_ld=no -fi]) +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + acl_cv_prog_gnu_ld=yes ;; +*) + acl_cv_prog_gnu_ld=no ;; +esac]) with_gnu_ld=$acl_cv_prog_gnu_ld ]) @@ -88,11 +89,12 @@ AC_CACHE_VAL(acl_cv_path_LD, # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. - if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then - test "$with_gnu_ld" != no && break - else - test "$with_gnu_ld" != yes && break - fi + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac fi done IFS="$ac_save_ifs" diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 index c719bc809..8aff5a9d2 100644 --- a/m4/lib-prefix.m4 +++ b/m4/lib-prefix.m4 @@ -1,4 +1,4 @@ -# lib-prefix.m4 serial 2 (gettext-0.12) +# lib-prefix.m4 serial 3 (gettext-0.13) dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General @@ -13,7 +13,7 @@ dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], -[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that diff --git a/m4/libassuan.m4 b/m4/libassuan.m4 index 2afc69737..16b664ce4 100644 --- a/m4/libassuan.m4 +++ b/m4/libassuan.m4 @@ -14,7 +14,7 @@ dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS dnl -AC_DEFUN(AM_PATH_LIBASSUAN, +AC_DEFUN([AM_PATH_LIBASSUAN], [ AC_ARG_WITH(libassuan-prefix, AC_HELP_STRING([--with-libassuan-prefix=PFX], [prefix where LIBASSUAN is installed (optional)]), diff --git a/m4/libgcrypt.m4 b/m4/libgcrypt.m4 index e5f2a43c0..20bd10556 100644 --- a/m4/libgcrypt.m4 +++ b/m4/libgcrypt.m4 @@ -20,7 +20,7 @@ dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using dnl this features allows to prevent build against newer versions of libgcrypt dnl with a changed API. dnl -AC_DEFUN(AM_PATH_LIBGCRYPT, +AC_DEFUN([AM_PATH_LIBGCRYPT], [ AC_ARG_WITH(libgcrypt-prefix, AC_HELP_STRING([--with-libgcrypt-prefix=PFX], [prefix where LIBGCRYPT is installed (optional)]), diff --git a/m4/po.m4 b/m4/po.m4 index 861e3dec3..e16199881 100644 --- a/m4/po.m4 +++ b/m4/po.m4 @@ -1,4 +1,4 @@ -# po.m4 serial 1 (gettext-0.12) +# po.m4 serial 3 (gettext-0.14) dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General @@ -111,7 +111,7 @@ AC_DEFUN([AM_PO_SUBDIRS], test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" - # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then @@ -127,19 +127,27 @@ AC_DEFUN([AM_PO_SUBDIRS], # The set of available languages was given in configure.in. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= - GMOFILES= UPDATEPOFILES= DUMMYPOFILES= + GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" - GMOFILES="$GMOFILES $srcdirpre$lang.gmo" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. @@ -174,7 +182,7 @@ AC_DEFUN([AM_PO_SUBDIRS], done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" - sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in @@ -188,10 +196,231 @@ AC_DEFUN([AM_PO_SUBDIRS], esac done], [# Capture the value of obsolete ALL_LINGUAS because we need it to compute - # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" ]) ]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat <<EOT +$* +EOT + } + gt_echo='echo_func' + fi + fi + + # A sed script that extracts the value of VARIABLE from a Makefile. + sed_x_variable=' +# Test if the hold space is empty. +x +s/P/P/ +x +ta +# Yes it was empty. Look if we have the expected variable definition. +/^[ ]*VARIABLE[ ]*=/{ + # Seen the first line of the variable definition. + s/^[ ]*VARIABLE[ ]*=// + ba +} +bd +:a +# Here we are processing a line from the variable definition. +# Remove comment, more precisely replace it with a space. +s/#.*$/ / +# See if the line ends in a backslash. +tb +:b +s/\\$// +# Print the line, without the trailing backslash. +p +tc +# There was no trailing backslash. The end of the variable definition is +# reached. Clear the hold space. +s/^.*$// +x +bd +:c +# A trailing backslash means that the variable definition continues in the +# next line. Put a nonempty string into the hold space to indicate this. +s/^.*$/P/ +x +:d +' +changequote([,])dnl + + # Set POTFILES to the value of the Makefile variable POTFILES. + sed_x_POTFILES="`$gt_echo \"$sed_x_variable\" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`" + POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"` + # Compute POTFILES_DEPS as + # $(foreach file, $(POTFILES), $(top_srcdir)/$(file)) + POTFILES_DEPS= + for file in $POTFILES; do + POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file" + done + POMAKEFILEDEPS="" + + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"` + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS. + sed_x_LINGUAS="`$gt_echo \"$sed_x_variable\" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`" + ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"` + fi + # Hide the ALL_LINGUAS assigment from automake. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + # Compute PROPERTIESFILES + # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties) + # Compute CLASSFILES + # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class) + # Compute QMFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm) + # Compute MSGFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg) + # Compute RESOURCESDLLFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + PROPERTIESFILES= + CLASSFILES= + QMFILES= + MSGFILES= + RESOURCESDLLFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties" + CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class" + QMFILES="$QMFILES $srcdirpre$lang.qm" + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg" + frobbedlang=`echo $lang | sed -e 's/_/-/g'` + RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + JAVACATALOGS= + QTCATALOGS= + TCLCATALOGS= + CSHARPCATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties" + QTCATALOGS="$QTCATALOGS $lang.qm" + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg" + frobbedlang=`echo $lang | sed -e 's/_/-/g'` + CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll" + done + fi + + sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp" + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" <<EOF +$frobbedlang.msg: $lang.po + @echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \ + \$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; } +EOF + done + fi + if grep -l '@CSHARPCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g'` + cat >> "$ac_file.tmp" <<EOF +$frobbedlang/\$(DOMAIN).resources.dll: $lang.po + @echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \ + \$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; } +EOF + done + fi + if test -n "$POMAKEFILEDEPS"; then + cat >> "$ac_file.tmp" <<EOF +Makefile: $POMAKEFILEDEPS +EOF + fi + mv "$ac_file.tmp" "$ac_file" +]) diff --git a/m4/ulonglong.m4 b/m4/ulonglong.m4 index c375e474c..1da8b809e 100644 --- a/m4/ulonglong.m4 +++ b/m4/ulonglong.m4 @@ -1,5 +1,5 @@ -# ulonglong.m4 serial 2 (fileutils-4.0.32, gettext-0.10.40) -dnl Copyright (C) 1999-2002 Free Software Foundation, Inc. +# ulonglong.m4 serial 3 +dnl Copyright (C) 1999-2003 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program @@ -8,16 +8,18 @@ dnl the same distribution terms as the rest of that program. dnl From Paul Eggert. +# Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. + AC_DEFUN([jm_AC_TYPE_UNSIGNED_LONG_LONG], [ AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, - [AC_TRY_LINK([unsigned long long ull = 1; int i = 63;], + [AC_TRY_LINK([unsigned long long ull = 1ULL; int i = 63;], [unsigned long long ullmax = (unsigned long long) -1; return ull << i | ull >> i | ullmax / ull | ullmax % ull;], ac_cv_type_unsigned_long_long=yes, ac_cv_type_unsigned_long_long=no)]) if test $ac_cv_type_unsigned_long_long = yes; then AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, - [Define if you have the unsigned long long type.]) + [Define if you have the 'unsigned long long' type.]) fi ]) diff --git a/po/ChangeLog b/po/ChangeLog index 25d7d4595..b7a550c11 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,8 @@ +2004-09-30 gettextize <bug-gnu-gettext@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.14.1. + * Rules-quot: Upgrade to gettext-0.14.1. + 2004-09-30 Werner Koch <wk@g10code.com> * de.po: Updated. diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 27b721aa8..53efc5e16 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -1,5 +1,5 @@ # Makefile for PO directory in any package using GNU gettext. -# Copyright (C) 1995-1997, 2000-2003 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# Copyright (C) 1995-1997, 2000-2004 by Ulrich Drepper <drepper@gnu.ai.mit.edu> # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public @@ -7,6 +7,8 @@ # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. +# +# Origin: gettext-0.14 PACKAGE = @PACKAGE@ VERSION = @VERSION@ @@ -55,7 +57,7 @@ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: -.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-update +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ @@ -86,7 +88,7 @@ all-no: # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot - test -z "$(CATALOGS)" || $(MAKE) $(CATALOGS) + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @echo "touch stamp-po" @echo timestamp > stamp-poT @mv stamp-poT stamp-po @@ -128,9 +130,13 @@ $(srcdir)/$(DOMAIN).pot: # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ - test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ - echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ - cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi install: install-exec install-data @@ -310,6 +316,13 @@ update-po: Makefile test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + # General rule for updating PO files. .nop.po-update: diff --git a/po/Rules-quot b/po/Rules-quot index 5f46d237d..9c2a995e3 100644 --- a/po/Rules-quot +++ b/po/Rules-quot @@ -4,6 +4,11 @@ DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.heade .SUFFIXES: .insert-header .po-update-en +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + en@quot.po-update: en@quot.po-update-en en@boldquot.po-update: en@boldquot.po-update-en diff --git a/scd/ChangeLog b/scd/ChangeLog index 9640ef6b2..493af3fd6 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,7 @@ 2004-09-30 Werner Koch <wk@g10code.com> + * Makefile.am: Adjusted for gettext 0.14. + * app-openpgp.c (do_sign): Add the error string to the verify failed messages. diff --git a/scd/Makefile.am b/scd/Makefile.am index 5c49ee6f9..d1d669a1a 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -53,7 +53,7 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @INTLLIBS@ \ + $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @LIBINTL@ \ @DL_LIBS@ sc_investigate_SOURCES = \ @@ -69,7 +69,7 @@ sc_investigate_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ - @INTLLIBS@ -lgpg-error @DL_LIBS@ + @LIBINTL@ -lgpg-error @DL_LIBS@ sc_copykeys_SOURCES = \ @@ -86,7 +86,7 @@ sc_copykeys_LDADD = \ ../common/libsimple-pwquery.a \ $(LIBGCRYPT_LIBS) $(pth_libs) \ $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ - -lgpg-error @INTLLIBS@ @DL_LIBS@ + -lgpg-error @LIBINTL@ @DL_LIBS@ pcsc_wrapper_SOURCES = pcsc-wrapper.c pcsc_wrapper_LDADD = @DL_LIBS@ diff --git a/scd/apdu.c b/scd/apdu.c index 5f800c983..fceb4f396 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -92,6 +92,7 @@ struct reader_table_s { /* Function pointers intialized to the various backends. */ int (*close_reader)(int); + int (*shutdown_reader)(int); int (*reset_reader)(int); int (*get_status_reader)(int, unsigned int *); int (*send_apdu_reader)(int,unsigned char *,size_t, @@ -244,6 +245,7 @@ new_reader_slot (void) } #endif /*USE_GNU_PTH*/ reader_table[reader].close_reader = NULL; + reader_table[reader].shutdown_reader = NULL; reader_table[reader].reset_reader = NULL; reader_table[reader].get_status_reader = NULL; reader_table[reader].send_apdu_reader = NULL; @@ -1117,7 +1119,8 @@ open_pcsc_reader (const char *portstr) { if (!*p && !p[1]) break; - log_info ("detected reader `%s'\n", p); + if (*p) + log_info ("detected reader `%s'\n", p); if (nreader < (strlen (p)+1)) { log_error ("invalid response from pcsc_list_readers\n"); @@ -1201,6 +1204,14 @@ close_ccid_reader (int slot) } +static int +shutdown_ccid_reader (int slot) +{ + ccid_shutdown_reader (reader_table[slot].ccid.handle); + return 0; +} + + static int reset_ccid_reader (int slot) { @@ -1273,7 +1284,7 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, /* Open the reader and try to read an ATR. */ static int -open_ccid_reader (void) +open_ccid_reader (const char *portstr) { int err; int slot; @@ -1284,7 +1295,7 @@ open_ccid_reader (void) return -1; slotp = reader_table + slot; - err = ccid_open_reader (&slotp->ccid.handle, 0); + err = ccid_open_reader (&slotp->ccid.handle, portstr); if (err) { slotp->used = 0; @@ -1300,6 +1311,7 @@ open_ccid_reader (void) } reader_table[slot].close_reader = close_ccid_reader; + reader_table[slot].shutdown_reader = shutdown_ccid_reader; reader_table[slot].reset_reader = reset_ccid_reader; reader_table[slot].get_status_reader = get_status_ccid; reader_table[slot].send_apdu_reader = send_apdu_ccid; @@ -1879,12 +1891,21 @@ apdu_open_reader (const char *portstr) #ifdef HAVE_LIBUSB if (!opt.disable_ccid) { - int slot; + int slot, i; + const char *s; - slot = open_ccid_reader (); + slot = open_ccid_reader (portstr); if (slot != -1) return slot; /* got one */ + + /* If a CCID reader specification has been given, the user does + not want a fallback to other drivers. */ + if (portstr) + for (s=portstr, i=0; *s; s++) + if (*s == ':' && (++i == 3)) + return -1; } + #endif /* HAVE_LIBUSB */ #ifdef HAVE_OPENSC @@ -2042,6 +2063,19 @@ apdu_close_reader (int slot) return SW_HOST_NOT_SUPPORTED; } +/* Shutdown a reader; that is basically the same as a close but keeps + the handle ready for later use. A apdu_reset_header should be used + to get it active again. */ +int +apdu_shutdown_reader (int slot) +{ + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + if (reader_table[slot].shutdown_reader) + return reader_table[slot].shutdown_reader (slot); + return SW_HOST_NOT_SUPPORTED; +} + /* Enumerate all readers and return information on whether this reader is in use. The caller should start with SLOT set to 0 and increment it with each call until an error is returned. */ diff --git a/scd/apdu.h b/scd/apdu.h index a0654a242..f31e42e3d 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -76,6 +76,7 @@ int apdu_open_remote_reader (const char *portstr, void *writefnc_value, void (*closefnc) (void *opaque), void *closefnc_value); +int apdu_shutdown_reader (int slot); int apdu_close_reader (int slot); int apdu_enum_reader (int slot, int *used); unsigned char *apdu_get_atr (int slot, size_t *atrlen); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 0fc168590..77fea944b 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -63,9 +63,9 @@ for security reasons. It makes use of the libusb library to gain portable access to USB. - This driver has been tested with the SCM SCR335 smartcard reader - and requires that reader implements the TPDU level exchange and - does fully automatic initialization. + This driver has been tested with the SCM SCR335 and SPR532 + smartcard readers and requires that a reader implements the TPDU + level exchange and does fully automatic initialization. */ #ifdef HAVE_CONFIG_H @@ -106,44 +106,49 @@ # include "scdaemon.h" #endif -/* Disable all debugging output for now. */ -#undef DBG_CARD_IO -#define DBG_CARD_IO 0 - /* Define to print information pertaining the T=1 protocol. */ #undef DEBUG_T1 -# define DEBUGOUT(t) do { if (DBG_CARD_IO) \ +# define DEBUGOUT(t) do { if (debug_level) \ log_debug (DRVNAME t); } while (0) -# define DEBUGOUT_1(t,a) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_1(t,a) do { if (debug_level) \ log_debug (DRVNAME t,(a)); } while (0) -# define DEBUGOUT_2(t,a,b) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_2(t,a,b) do { if (debug_level) \ log_debug (DRVNAME t,(a),(b)); } while (0) -# define DEBUGOUT_3(t,a,b,c) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_3(t,a,b,c) do { if (debug_level) \ log_debug (DRVNAME t,(a),(b),(c));} while (0) -# define DEBUGOUT_CONT(t) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_CONT(t) do { if (debug_level) \ log_printf (t); } while (0) -# define DEBUGOUT_CONT_1(t,a) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_CONT_1(t,a) do { if (debug_level) \ log_printf (t,(a)); } while (0) -# define DEBUGOUT_CONT_2(t,a,b) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_CONT_2(t,a,b) do { if (debug_level) \ log_printf (t,(a),(b)); } while (0) -# define DEBUGOUT_CONT_3(t,a,b,c) do { if (DBG_CARD_IO) \ +# define DEBUGOUT_CONT_3(t,a,b,c) do { if (debug_level) \ log_printf (t,(a),(b),(c)); } while (0) -# define DEBUGOUT_LF() do { if (DBG_CARD_IO) \ +# define DEBUGOUT_LF() do { if (debug_level) \ log_printf ("\n"); } while (0) #else /* Other usage of this source - don't use gnupg specifics. */ -# define DEBUGOUT(t) fprintf (stderr, DRVNAME t) -# define DEBUGOUT_1(t,a) fprintf (stderr, DRVNAME t, (a)) -# define DEBUGOUT_2(t,a,b) fprintf (stderr, DRVNAME t, (a), (b)) -# define DEBUGOUT_3(t,a,b,c) fprintf (stderr, DRVNAME t, (a), (b), (c)) -# define DEBUGOUT_CONT(t) fprintf (stderr, t) -# define DEBUGOUT_CONT_1(t,a) fprintf (stderr, t, (a)) -# define DEBUGOUT_CONT_2(t,a,b) fprintf (stderr, t, (a), (b)) -# define DEBUGOUT_CONT_3(t,a,b,c) fprintf (stderr, t, (a), (b), (c)) -# define DEBUGOUT_LF() putc ('\n', stderr) +# define DEBUGOUT(t) do { if (debug_level) \ + fprintf (stderr, DRVNAME t); } while (0) +# define DEBUGOUT_1(t,a) do { if (debug_level) \ + fprintf (stderr, DRVNAME t, (a)); } while (0) +# define DEBUGOUT_2(t,a,b) do { if (debug_level) \ + fprintf (stderr, DRVNAME t, (a), (b)); } while (0) +# define DEBUGOUT_3(t,a,b,c) do { if (debug_level) \ + fprintf (stderr, DRVNAME t, (a), (b), (c)); } while (0) +# define DEBUGOUT_CONT(t) do { if (debug_level) \ + fprintf (stderr, t); } while (0) +# define DEBUGOUT_CONT_1(t,a) do { if (debug_level) \ + fprintf (stderr, t, (a)); } while (0) +# define DEBUGOUT_CONT_2(t,a,b) do { if (debug_level) \ + fprintf (stderr, t, (a), (b)); } while (0) +# define DEBUGOUT_CONT_3(t,a,b,c) do { if (debug_level) \ + fprintf (stderr, t, (a), (b), (c)); } while (0) +# define DEBUGOUT_LF() do { if (debug_level) \ + putc ('\n', stderr); } while (0) #endif /* This source not used by scdaemon. */ @@ -180,8 +185,10 @@ enum { /* Store information on the driver's state. A pointer to such a structure is used as handle for most functions. */ -struct ccid_driver_s { +struct ccid_driver_s +{ usb_dev_handle *idev; + char *rid; int seqno; unsigned char t1_ns; unsigned char t1_nr; @@ -189,17 +196,21 @@ struct ccid_driver_s { int auto_ifsd; int max_ifsd; int ifsd; + int powered_off; + int has_pinpad; }; +static int initialized_usb; /* Tracks whether USB has been initialized. */ +static int debug_level; /* Flag to control the debug output. */ + + static unsigned int compute_edc (const unsigned char *data, size_t datalen, int use_crc); static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen); static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, size_t *nread, int expected_type, int seqno); - - /* Convert a little endian stored 4 byte value into an unsigned integer. */ static unsigned int @@ -239,6 +250,7 @@ parse_ccid_descriptor (ccid_driver_t handle, handle->auto_ifsd = 0; handle->max_ifsd = 32; handle->ifsd = 0; + handle->has_pinpad = 0; if (buflen < 54 || buf[0] < 54) { DEBUGOUT ("CCID device descriptor is too short\n"); @@ -378,9 +390,15 @@ parse_ccid_descriptor (ccid_driver_t handle, DEBUGOUT_1 (" bPINSupport %5u ", buf[52]); if ((buf[52] & 1)) - DEBUGOUT_CONT ( " verification"); + { + DEBUGOUT_CONT ( " verification"); + handle->has_pinpad |= 1; + } if ((buf[52] & 2)) - DEBUGOUT_CONT ( " modification"); + { + DEBUGOUT_CONT ( " modification"); + handle->has_pinpad |= 2; + } DEBUGOUT_LF (); DEBUGOUT_1 (" bMaxCCIDBusySlots %5u\n", buf[53]); @@ -404,240 +422,541 @@ parse_ccid_descriptor (ccid_driver_t handle, } -/* Read the device information, return all required data and check - that the device is usable for us. Returns 0 on success or an error - code. */ -static int -read_device_info (ccid_driver_t handle, struct usb_device *dev) +static char * +get_escaped_usb_string (usb_dev_handle *idev, int idx, + const char *prefix, const char *suffix) +{ + int rc; + unsigned char buf[280]; + unsigned char *s; + unsigned int langid; + size_t i, n, len; + char *result; + + if (!idx) + return NULL; + + /* Fixme: The next line for the current Valgrid without support + for USB IOCTLs. */ + memset (buf, 0, sizeof buf); + + /* First get the list of supported languages and use the first one. + If we do don't find it we try to use English. Note that this is + all in a 2 bute Unicode encoding using little endian. */ + rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8), 0, + buf, sizeof buf, 1000 /* ms timeout */); + if (rc < 4) + langid = 0x0409; /* English. */ + else + langid = (buf[3] << 8) | buf[2]; + + rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) + idx, langid, + buf, sizeof buf, 1000 /* ms timeout */); + if (rc < 2 || buf[1] != USB_DT_STRING) + return NULL; /* Error or not a string. */ + len = buf[0]; + if (len > rc) + return NULL; /* Larger than our buffer. */ + + for (s=buf+2, i=2, n=0; i+1 < len; i += 2, s += 2) + { + if (s[1]) + n++; /* High byte set. */ + else if (*s <= 0x20 || *s >= 0x7f || *s == '%' || *s == ':') + n += 3 ; + else + n++; + } + + result = malloc (strlen (prefix) + n + strlen (suffix) + 1); + if (!result) + return NULL; + + strcpy (result, prefix); + n = strlen (prefix); + for (s=buf+2, i=2; i+1 < len; i += 2, s += 2) + { + if (s[1]) + result[n++] = '\xff'; /* High byte set. */ + else if (*s <= 0x20 || *s >= 0x7f || *s == '%' || *s == ':') + { + sprintf (result+n, "%%%02X", *s); + n += 3; + } + else + result[n++] = *s; + } + strcpy (result+n, suffix); + + return result; +} + +/* This function creates an reader id to be used to find the same + physical reader after a reset. It returns an allocated and possibly + percent escaped string or NULL if not enough memory is available. */ +static char * +make_reader_id (usb_dev_handle *idev, + unsigned int vendor, unsigned int product, + unsigned char serialno_index) { - int cfg_no; + char *rid; + char prefix[20]; - for (cfg_no=0; cfg_no < -#ifdef HAVE_USB_CREATE_MATCH - dev->descriptor->bNumConfigurations + sprintf (prefix, "%04X:%04X:", (vendor & 0xfff), (product & 0xffff)); + rid = get_escaped_usb_string (idev, serialno_index, prefix, ":0"); + if (!rid) + { + rid = malloc (strlen (prefix) + 3 + 1); + if (!rid) + return NULL; + strcpy (rid, prefix); + strcat (rid, "X:0"); + } + return rid; +} + + +/* Combination function to either scan all CCID devices or to find and + open one specific device. + + With READERNO = -1 and READERID is NULL, scan mode is used and + R_RID should be the address where to store the list of reader_ids + we found. If on return this list is empty, no CCID device has been + found; otherwise it points to an allocated linked list of reader + IDs. Note that in this mode the function always returns NULL. + + With READERNO >= 0 or READERID is not NULL find mode is used. This + uses the same algorithm as the scan mode but stops and returns at + the entry number READERNO and return the handle for the the opened + USB device. If R_ID is not NULL it will receive the reader ID of + that device. If R_DEV is not NULL it will the device pointer of + that device. If IFCDESC_EXTRA is NOT NULL it will receive a + malloced copy of the interfaces "extra: data filed; + IFCDESC_EXTRA_LEN receive the lengtyh of this field. If there is + no reader with number READERNO or that reader is not usable by our + implementation NULL will be returned. The caller must close a + returned USB device handle and free (if not passed as NULL) the + returned reader ID info as well as the IFCDESC_EXTRA. On error + NULL will get stored at R_RID, R_DEV, IFCDESC_EXTRA and + IFCDESC_EXTRA_LEN. With READERID being -1 the function stops if + the READERID was found. + + Note that the first entry of the returned reader ID list in scan mode + corresponds with a READERNO of 0 in find mode. +*/ +static usb_dev_handle * +scan_or_find_devices (int readerno, const char *readerid, + char **r_rid, + struct usb_device **r_dev, + unsigned char **ifcdesc_extra, + size_t *ifcdesc_extra_len) +{ + char *rid_list = NULL; + int count = 0; + struct usb_bus *busses, *bus; + struct usb_device *dev = NULL; + usb_dev_handle *idev = NULL; + int scan_mode = (readerno == -1 && !readerid); + + /* Set return values to a default. */ + if (r_rid) + *r_rid = NULL; + if (r_dev) + *r_dev = NULL; + if (ifcdesc_extra) + *ifcdesc_extra = NULL; + if (ifcdesc_extra_len) + *ifcdesc_extra_len = 0; + + /* See whether we want scan or find mode. */ + if (scan_mode) + { + assert (r_rid); + } + + usb_find_busses(); + usb_find_devices(); + +#ifdef HAVE_USB_GET_BUSSES + busses = usb_get_busses(); #else - dev->descriptor.bNumConfigurations + busses = usb_busses; #endif - ; cfg_no++) - { - struct usb_config_descriptor *config = dev->config + cfg_no; - int ifc_no; - for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++) + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) { - struct usb_interface *interface = config->interface + ifc_no; - int set_no; - - for (set_no=0; set_no < interface->num_altsetting; set_no++) + int cfg_no; + + for (cfg_no=0; cfg_no < dev->descriptor.bNumConfigurations; cfg_no++) { - struct usb_interface_descriptor *ifcdesc - = interface->altsetting + set_no; - - if (ifcdesc->bInterfaceClass == 11 - && ifcdesc->bInterfaceSubClass == 0 - && ifcdesc->bInterfaceProtocol == 0) + struct usb_config_descriptor *config = dev->config + cfg_no; + int ifc_no; + + if(!config) + continue; + + for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++) { - if (ifcdesc->extra) + struct usb_interface *interface + = config->interface + ifc_no; + int set_no; + + if (!interface) + continue; + + for (set_no=0; set_no < interface->num_altsetting; set_no++) { - if (!parse_ccid_descriptor (handle, - ifcdesc->extra, - ifcdesc->extralen)) - return 0; /* okay. we can use it. */ + struct usb_interface_descriptor *ifcdesc + = interface->altsetting + set_no; + char *rid; + + /* The second condition is for some SCM Micro + SPR 532 which does not know about the + assigned CCID class. Instead of trying to + interpret the strings we simply look at the + product ID. */ + if (ifcdesc && ifcdesc->extra + && ( (ifcdesc->bInterfaceClass == 11 + && ifcdesc->bInterfaceSubClass == 0 + && ifcdesc->bInterfaceProtocol == 0) + || (ifcdesc->bInterfaceClass == 255 + && dev->descriptor.idVendor == 0x04e6 + && dev->descriptor.idProduct == 0xe003 + && ifcdesc->bInterfaceSubClass == 1 + && ifcdesc->bInterfaceProtocol == 1))) + { + idev = usb_open (dev); + if (!idev) + { + DEBUGOUT_1 ("usb_open failed: %s\n", + strerror (errno)); + continue; + } + + rid = make_reader_id (idev, + dev->descriptor.idVendor, + dev->descriptor.idProduct, + dev->descriptor.iSerialNumber); + if (rid) + { + if (scan_mode) + { + char *p; + + /* We are collecting infos about all + available CCID readers. Store + them and continue. */ + DEBUGOUT_2 ("found CCID reader %d " + "(ID=%s)\n", + count, rid ); + if ((p = malloc ((rid_list? + strlen (rid_list):0) + + 1 + strlen (rid) + + 1))) + { + *p = 0; + if (rid_list) + { + strcat (p, rid_list); + free (rid_list); + } + strcat (p, rid); + strcat (p, "\n"); + rid_list = p; + } + else /* Out of memory. */ + free (rid); + rid = NULL; + count++; + } + else if (!readerno + || (readerno < 0 + && readerid + && !strcmp (readerid, rid))) + { + /* We found the requested reader. */ + if (ifcdesc_extra && ifcdesc_extra_len) + { + *ifcdesc_extra = malloc (ifcdesc + ->extralen); + if (!*ifcdesc_extra) + { + usb_close (idev); + free (rid); + return NULL; /* Out of core. */ + } + memcpy (*ifcdesc_extra, ifcdesc->extra, + ifcdesc->extralen); + *ifcdesc_extra_len = ifcdesc->extralen; + } + + if (r_dev) + *r_dev = dev; + if (r_rid) + { + *r_rid = rid; + rid = NULL; + } + else + free (rid); + return idev; /* READY. */ + } + else + { + /* This is not yet the reader we + want. fixme: We could avoid the + extra usb_open in this case. */ + if (readerno >= 0) + readerno--; + } + free (rid); + } + + usb_close (idev); + idev = NULL; + goto next_device; + } } } } + next_device: + ; } } - return CCID_DRIVER_ERR_NO_READER; /* No suitable device found. */ + + if (scan_mode) + *r_rid = rid_list; + + return NULL; +} + + +/* Set the level of debugging to to usea dn return the old level. -1 + just returns the old level. A level of 0 disables debugging, 1 + enables debugging, other values are not yet defined. */ +int +ccid_set_debug_level (int level) +{ + int old = debug_level; + if (level != -1) + debug_level = level; + return old; +} + + +char * +ccid_get_reader_list (void) +{ + char *reader_list; + + if (!initialized_usb) + { + usb_init (); + initialized_usb = 1; + } + + scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL); + return reader_list; } /* Open the reader with the internal number READERNO and return a pointer to be used as handle in HANDLE. Returns 0 on success. */ int -ccid_open_reader (ccid_driver_t *handle, int readerno) +ccid_open_reader (ccid_driver_t *handle, const char *readerid) { -#ifdef HAVE_USB_CREATE_MATCH - /* This is the development version of libusb. */ - static int initialized; - int rc; - usb_match_handle *match = NULL; + int rc = 0; struct usb_device *dev = NULL; usb_dev_handle *idev = NULL; + char *rid = NULL; + unsigned char *ifcdesc_extra = NULL; + size_t ifcdesc_extra_len; + int readerno; *handle = NULL; - if (!initialized) + + if (!initialized_usb) { usb_init (); - initialized = 1; + initialized_usb = 1; } - - rc = usb_create_match (&match, -1, -1, 11, -1, -1); - if (rc) + + /* See whether we want to use the reader ID string or a reader + number. A readerno of -1 indicates that the reader ID string is + to be used. */ + if (readerid && strchr (readerid, ':')) + readerno = -1; /* We want to use the readerid. */ + else if (readerid) { - DEBUGOUT_1 ("usb_create_match failed: %d\n", rc); - return CCID_DRIVER_ERR_NO_READER; + readerno = atoi (readerid); + if (readerno < 0) + { + DEBUGOUT ("no CCID readers found\n"); + rc = CCID_DRIVER_ERR_NO_READER; + goto leave; + } } - - while (usb_find_device(match, dev, &dev) >= 0) + else + readerno = 0; /* Default. */ + + idev = scan_or_find_devices (readerno, readerid, &rid, &dev, + &ifcdesc_extra, &ifcdesc_extra_len); + if (!idev) { - DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, - dev->descriptor->idVendor, dev->descriptor->idProduct); - if (!readerno) - { - *handle = calloc (1, sizeof **handle); - if (!*handle) - { - DEBUGOUT ("out of memory\n"); - rc = CCID_DRIVER_ERR_OUT_OF_CORE; - free (*handle); - *handle = NULL; - goto leave; - } + if (readerno == -1) + DEBUGOUT_1 ("no CCID reader with ID %s\n", readerid ); + else + DEBUGOUT_1 ("no CCID reader with number %d\n", readerno ); + rc = CCID_DRIVER_ERR_NO_READER; + goto leave; + } - rc = read_device_info (*handle, dev); - if (rc) - { - DEBUGOUT ("device not supported\n"); - free (*handle); - *handle = NULL; - goto leave; - } + /* Okay, this is a CCID reader. */ + *handle = calloc (1, sizeof **handle); + if (!*handle) + { + DEBUGOUT ("out of memory\n"); + rc = CCID_DRIVER_ERR_OUT_OF_CORE; + goto leave; + } + (*handle)->idev = idev; + (*handle)->rid = rid; - rc = usb_open (dev, &idev); - if (rc) - { - DEBUGOUT_1 ("usb_open failed: %d\n", rc); - free (*handle); - *handle = NULL; - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; - goto leave; - } + DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid ); - /* fixme: Do we need to claim and set the interface as - determined by read_device_info ()? */ - rc = usb_claim_interface (idev, 0); - if (rc) - { - DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); - free (*handle); - *handle = NULL; - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; - goto leave; - } + if (parse_ccid_descriptor (*handle, ifcdesc_extra, ifcdesc_extra_len)) + { + DEBUGOUT ("device not supported\n"); + rc = CCID_DRIVER_ERR_NO_READER; + goto leave; + } + + /* fixme: Do we need to claim and set the interface as + determined above? */ + rc = usb_claim_interface (idev, 0); + if (rc) + { + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } + + /* FIXME: Do we need to get the endpoint addresses from the + structure and store them with the handle? */ + + leave: + free (ifcdesc_extra); + if (rc) + { + free (rid); + if (idev) + usb_close (idev); + free (*handle); + *handle = NULL; + } - (*handle)->idev = idev; - idev = NULL; - /* FIXME: Do we need to get the endpoint addresses from the - structure and store them with the handle? */ + return rc; +} - break; - } - readerno--; + +static void +do_close_reader (ccid_driver_t handle) +{ + int rc; + unsigned char msg[100]; + size_t msglen; + unsigned char seqno; + + if (!handle->powered_off) + { + msg[0] = PC_to_RDR_IccPowerOff; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* RFU */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, 0); + msglen = 10; + + rc = bulk_out (handle, msg, msglen); + if (!rc) + bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,seqno); + handle->powered_off = 1; + } + if (handle->idev) + { + usb_release_interface (handle->idev, 0); + usb_close (handle->idev); + handle->idev = NULL; } +} - leave: - if (idev) - usb_close (idev); - /* fixme: Do we need to release dev or is it supposed to be a - shallow copy of the list created internally by usb_init ? */ - usb_free_match (match); - if (!rc && !*handle) - rc = -1; /* In case we didn't enter the while loop at all. */ +/* Reset a reader on HANDLE. This is useful in case a reader has been + plugged of and inserted at a different port. By resetting the + handle, the same reader will be get used. Note, that on error the + handle won't get released. - return rc; -#else /* Stable 0.1 version of libusb. */ - static int initialized; + This does not return an ATR, so ccid_get_atr should be called right + after this one. +*/ +int +ccid_shutdown_reader (ccid_driver_t handle) +{ int rc = 0; - struct usb_bus *busses, *bus; struct usb_device *dev = NULL; usb_dev_handle *idev = NULL; + unsigned char *ifcdesc_extra = NULL; + size_t ifcdesc_extra_len; - *handle = NULL; - if (!initialized) - { - usb_init (); - initialized = 1; - } - - usb_find_busses(); - usb_find_devices(); - busses = usb_get_busses(); - - for (bus = busses; bus; bus = bus->next) - { - for (dev = bus->devices; dev; dev = dev->next) - { - DEBUGOUT_3 ("%-40s %04X/%04X\n", dev->filename, - dev->descriptor.idVendor, dev->descriptor.idProduct); + if (!handle || !handle->rid) + return CCID_DRIVER_ERR_INV_VALUE; - if (!readerno) - { - *handle = calloc (1, sizeof **handle); - if (!*handle) - { - DEBUGOUT ("out of memory\n"); - rc = CCID_DRIVER_ERR_OUT_OF_CORE; - free (*handle); - *handle = NULL; - goto leave; - } + do_close_reader (handle); - rc = read_device_info (*handle, dev); - if (rc) - { - DEBUGOUT ("device not supported\n"); - free (*handle); - *handle = NULL; - continue; - } + idev = scan_or_find_devices (-1, handle->rid, NULL, &dev, + &ifcdesc_extra, &ifcdesc_extra_len); + if (!idev) + { + DEBUGOUT_1 ("no CCID reader with ID %s\n", handle->rid); + return CCID_DRIVER_ERR_NO_READER; + } - idev = usb_open (dev); - if (!idev) - { - DEBUGOUT_1 ("usb_open failed: %s\n", strerror (errno)); - free (*handle); - *handle = NULL; - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; - goto leave; - } - /* fixme: Do we need to claim and set the interface as - determined by read_device_info ()? */ - rc = usb_claim_interface (idev, 0); - if (rc) - { - DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); - free (*handle); - *handle = NULL; - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; - goto leave; - } + handle->idev = idev; - (*handle)->idev = idev; - idev = NULL; - /* FIXME: Do we need to get the endpoint addresses from the - structure and store them with the handle? */ - - goto leave; /* ready. */ - } - readerno--; - } + if (parse_ccid_descriptor (handle, ifcdesc_extra, ifcdesc_extra_len)) + { + DEBUGOUT ("device not supported\n"); + rc = CCID_DRIVER_ERR_NO_READER; + goto leave; } - + + /* fixme: Do we need to claim and set the interface as + determined above? */ + rc = usb_claim_interface (idev, 0); + if (rc) + { + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } + leave: - if (idev) - usb_close (idev); - /* fixme: Do we need to release dev or is it supposed to be a - shallow copy of the list created internally by usb_init ? */ - - if (!rc && !*handle) - rc = -1; /* In case we didn't enter the while loop at all. */ + free (ifcdesc_extra); + if (rc) + { + usb_close (handle->idev); + handle->idev = NULL; + } return rc; -#endif /* Stable version 0.1 of libusb. */ + } @@ -648,29 +967,8 @@ ccid_close_reader (ccid_driver_t handle) if (!handle || !handle->idev) return 0; - { - int rc; - unsigned char msg[100]; - size_t msglen; - unsigned char seqno; - - msg[0] = PC_to_RDR_IccPowerOff; - msg[5] = 0; /* slot */ - msg[6] = seqno = handle->seqno++; - msg[7] = 0; /* RFU */ - msg[8] = 0; /* RFU */ - msg[9] = 0; /* RFU */ - set_msg_len (msg, 0); - msglen = 10; - - rc = bulk_out (handle, msg, msglen); - if (!rc) - bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno); - } - - usb_release_interface (handle->idev, 0); - usb_close (handle->idev); - handle->idev = NULL; + do_close_reader (handle); + free (handle->rid); free (handle); return 0; } @@ -719,6 +1017,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, int i, rc; size_t msglen; + /* Fixme: The next line for the current Valgrind without support + for USB IOCTLs. */ + memset (buffer, 0, length); retry: rc = usb_bulk_read (handle->idev, 0x82, @@ -895,6 +1196,8 @@ ccid_get_atr (ccid_driver_t handle, rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno); if (rc) return rc; + + handle->powered_off = 0; if (atr) { @@ -977,9 +1280,6 @@ ccid_get_atr (ccid_driver_t handle, if (rc) return rc; - /* Fixme: The next line for the current Valgrid without support - for USB IOCTLs. */ - memset (msg, 0, sizeof msg); rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno); @@ -1170,10 +1470,6 @@ ccid_transceive (ccid_driver_t handle, if (rc) return rc; - /* Fixme: The next line for the current Valgrid without support - for USB IOCTLs. */ - memset (recv_buffer, 0, sizeof recv_buffer); - msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, RDR_to_PC_DataBlock, seqno); @@ -1324,14 +1620,97 @@ ccid_transceive (ccid_driver_t handle, #ifdef TEST + +static void +print_error (int err) +{ + const char *p; + char buf[50]; + + switch (err) + { + case 0: p = "success"; + case CCID_DRIVER_ERR_OUT_OF_CORE: p = "out of core"; break; + case CCID_DRIVER_ERR_INV_VALUE: p = "invalid value"; break; + case CCID_DRIVER_ERR_NO_DRIVER: p = "no driver"; break; + case CCID_DRIVER_ERR_NOT_SUPPORTED: p = "not supported"; break; + case CCID_DRIVER_ERR_LOCKING_FAILED: p = "locking failed"; break; + case CCID_DRIVER_ERR_BUSY: p = "busy"; break; + case CCID_DRIVER_ERR_NO_CARD: p = "no card"; break; + case CCID_DRIVER_ERR_CARD_INACTIVE: p = "card inactive"; break; + case CCID_DRIVER_ERR_CARD_IO_ERROR: p = "card I/O error"; break; + case CCID_DRIVER_ERR_GENERAL_ERROR: p = "general error"; break; + case CCID_DRIVER_ERR_NO_READER: p = "no reader"; break; + case CCID_DRIVER_ERR_ABORTED: p = "aborted"; break; + default: sprintf (buf, "0x%05x", err); p = buf; break; + } + fprintf (stderr, "operation failed: %s\n", p); +} + +static void +print_data (const unsigned char *data, size_t length) +{ + if (length >= 2) + { + fprintf (stderr, "operation status: %02X%02X\n", + data[length-2], data[length-1]); + length -= 2; + } + if (length) + { + fputs (" returned data:", stderr); + for (; length; length--, data++) + fprintf (stderr, " %02X", *data); + putc ('\n', stderr); + } +} + +static void +print_result (int rc, const unsigned char *data, size_t length) +{ + if (rc) + print_error (rc); + else if (data) + print_data (data, length); +} + int main (int argc, char **argv) { int rc; ccid_driver_t ccid; unsigned int slotstat; + unsigned char result[512]; + size_t resultlen; + + if (argc) + { + argc--; + argv++; + } + + while (argc) + { + if ( !strcmp (*argv, "--list")) + { + char *p; + p = ccid_get_reader_list (); + if (!p) + return 1; + fputs (p, stderr); + free (p); + return 0; + } + else if ( !strcmp (*argv, "--debug")) + { + ccid_set_debug_level (1); + argc--; argv++; + } + else + break; + } - rc = ccid_open_reader (&ccid, 0); + rc = ccid_open_reader (&ccid, argc? *argv:NULL); if (rc) return 1; @@ -1339,34 +1718,67 @@ main (int argc, char **argv) fputs ("getting ATR ...\n", stderr); rc = ccid_get_atr (ccid, NULL, 0, NULL); if (rc) - return 1; + { + print_error (rc); + return 1; + } ccid_poll (ccid); fputs ("getting slot status ...\n", stderr); rc = ccid_slot_status (ccid, &slotstat); if (rc) - return 1; + { + print_error (rc); + return 1; + } ccid_poll (ccid); + fputs ("selecting application OpenPGP ....\n", stderr); { static unsigned char apdu[] = { 0, 0xA4, 4, 0, 6, 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01}; - rc = ccid_transceive (ccid, - apdu, sizeof apdu, - NULL, 0, NULL); + rc = ccid_transceive (ccid, + apdu, sizeof apdu, + result, sizeof result, &resultlen); + print_result (rc, result, resultlen); } + + ccid_poll (ccid); + fputs ("getting OpenPGP DO 0x65 ....\n", stderr); { - static unsigned char apdu[] = { - 0, 0xCA, 0, 0x65, 254 }; - rc = ccid_transceive (ccid, - apdu, sizeof apdu, - NULL, 0, NULL); + static unsigned char apdu[] = { 0, 0xCA, 0, 0x65, 254 }; + rc = ccid_transceive (ccid, apdu, sizeof apdu, + result, sizeof result, &resultlen); + print_result (rc, result, resultlen); } + ccid_poll (ccid); +/* if (!ccid->has_pinpad) */ +/* { */ +/* fputs ("verifying that CHV1 is 123456....\n", stderr); */ +/* { */ +/* static unsigned char apdu[] = {0, 0x20, 0, 0x81, */ +/* 6, '1','2','3','4','5','6'}; */ +/* rc = ccid_transceive (ccid, apdu, sizeof apdu, */ +/* result, sizeof result, &resultlen); */ +/* print_result (rc, result, resultlen); */ +/* } */ +/* } */ +/* else */ +/* { */ +/* fputs ("verifying CHV1 using the PINPad ....\n", stderr); */ +/* { */ +/* rc = ccid_secure_transceive (ccid, */ +/* result, sizeof result, &resultlen); */ +/* print_result (rc, result, resultlen); */ +/* } */ +/* } */ + + ccid_close_reader (ccid); return 0; } diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 0cb52e1c3..cbadb40c1 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -75,7 +75,10 @@ struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; -int ccid_open_reader (ccid_driver_t *handle, int readerno); +int ccid_set_debug_level (int level); +char *ccid_get_reader_list (void); +int ccid_open_reader (ccid_driver_t *handle, const char *readerid); +int ccid_shutdown_reader (ccid_driver_t handle); int ccid_close_reader (ccid_driver_t handle); int ccid_get_atr (ccid_driver_t handle, unsigned char *atr, size_t maxatrlen, size_t *atrlen); diff --git a/scripts/ChangeLog b/scripts/ChangeLog index e485a905e..5c8b95c8c 100644 --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,372 +1,9 @@ -2004-07-27 Werner Koch <wk@g10code.de> +2004-09-30 Werner Koch <wk@g10code.com> - * autogen.sh: Updated to the moder version, grepping the required - tool versions from configure.ac. + * config.guess, config.sub: Updated. -2004-06-14 Werner Koch <wk@gnupg.org> - * mk-w32-dist: Do not include the en@* po files. - - * autogen.sh <--build-w32>: Build keyserver helpers again. - -2004-04-02 Thomas Schwinge <schwinge@nic-nac-project.de> - - * autogen.sh: Added ACLOCAL_FLAGS. - -2003-12-28 Stefan Bellon <sbellon@sbellon.de> - - * build-riscos, conf-riscos/*: Updated to reflect latest changes. - -2003-10-25 Werner Koch <wk@gnupg.org> - - * autogen.sh: Updated required versions and add -I m4 to aclocal. - -2003-08-28 David Shaw <dshaw@jabberwocky.com> - - * autogen.sh: Touch po/all for --build-w32. From Werner on stable - branch. - -2003-08-25 David Shaw <dshaw@jabberwocky.com> - - * gnupg.spec.in: Rework much of the spec to use %-macros - throughout. Fix to work properly with RPM 4.1 (all files in - buildroot must be packaged). Package and install info files. Tweak - the English description. Do not install gpgv and gpgsplit setuid - root. Make sure that install-info is called in such a way that - doesn't bork the RPM install if it cannot complete (necessary for - some upgrade scenarios). - -2003-05-26 David Shaw <dshaw@jabberwocky.com> - - * mk-w32-dist: Don't iconv {hu,sk,zh_TW}.po. (From wk on stable - branch) - -2003-04-08 Werner Koch <wk@gnupg.org> - - * autogen.sh: Add options to build for coldfire and uClinux. - -2003-02-22 David Shaw <dshaw@jabberwocky.com> - - * distfiles, gnupg.spec.in: convert-from-106 is in the tools - directory now. - - * convert-from-106: Move to the tools directory. - -2002-12-01 David Shaw <dshaw@jabberwocky.com> - - * distfiles, gnupg.spec.in: Include convert-from-106. - - * convert-from-106: Script to automate the 1.0.6->later - conversion. It marks all secret keys as ultimately trusted, adds - the signature caches, and checks the trustdb. - -2002-11-13 David Shaw <dshaw@jabberwocky.com> - - * mk-w32-dist: Don't use iconv for pl.po. From Werner on stable - branch. - - * mk-w32-dist: Include gpgkeys_ldap and gpgkeys_hkp. - -2002-11-12 Werner Koch <wk@gnupg.org> - - * config.sub, config.guess: Updated from ftp.gnu.org/gnu/config - to version 2002-11-08. - -2002-10-31 David Shaw <dshaw@jabberwocky.com> - - * gnupg.spec.in: Update source ftp path. - -2002-10-31 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/Makefile: Updated to reflect latest changes. - -2002-10-28 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/include/config.h: Updated to reflect latest changes. - -2002-10-26 David Shaw <dshaw@jabberwocky.com> - - * gnupg.spec.in: Use new path for keyserver helpers, /usr/lib is - no longer used for cipher/hash plugins, and include gpgv, - gpgsplit, and the new gnupg.7 man page. - -2002-10-17 Werner Koch <wk@gnupg.org> - - * autogen.sh: Allow env variables to override the auto* tool - names. Suggested by Simon Josefsson. - -2002-09-11 Werner Koch <wk@gnupg.org> - - * distfiles: Include mk-w32-dist. - - * mk-w32-dist: Convert the character sets on a per language base. - -2002-09-02 Werner Koch <wk@gnupg.org> - - * mk-w32-dist: Include more man pages and gpg split. Changed name - of ZIP file to better indicate that this is a command line version. - -2002-08-23 Werner Koch <wk@gnupg.org> - - * autogen.sh : Don't run gettextize. - -2002-08-06 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/include/config.h: Changed #define FOO to - #define FOO 1. - * conf-riscos/include/g10defs.h: Likewise. - -2002-08-03 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/include/g10defs.h: Added GNUPG_LIBEXECDIR. - * conf-riscos/include/config.h: Changes due to dynload removal and - minor changes to avoid some warnings. - * conf-riscos/Makefile: Changes due to dynload removal. - * conf-riscos/cipher/*: Not needed anymore due to dynload removal. - -2002-07-25 David Shaw <dshaw@jabberwocky.com> - - * gnupgbug: "Warning" -> "WARNING" - -2002-07-01 Werner Koch <wk@gnupg.org> - - * mk-gpg-texi: New. - -2002-06-30 Werner Koch <wk@gnupg.org> - - * mk-w32-dist (bindir): Fixes vor VPATH builds in a subdir, - include gpgv. - -2002-06-21 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/Makefile: Changes due to moving around RISC OS - specific stuff in the code. - -2002-06-07 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/include/config.h [__riscos__]: Fixed macro bug. - -2002-05-10 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/include/config.h [__riscos__]: Changes for later - Norcroft compilers. - - * conf-riscos/Makefile [__riscos__]: Updated. - -2002-04-22 Stefan Bellon <sbellon@sbellon.de> - - * conf-riscos/include/config.h [__riscos__]: Development - versions automatically define DEBUG from now on. - - * conf-riscos/Makefile [__riscos__]: Updated for LDAP keyserver - code. - -2002-04-19 David Shaw <dshaw@jabberwocky.com> - - * gnupg.spec.in: Removed pubring.asc and OPTIONS. Added - samplekeys.asc. - -2002-03-31 David Shaw <dshaw@jabberwocky.com> - - * gnupg.spec.in: Added the gpgkeys_xxx keyserver helpers. Added a - * to catch variations on the basic gpg man page (gpg, gpgv). Mark - options.skel as a config file. Do not include the FAQ/faq.html - twice (in /doc/ and /share/). - -2002-01-02 Stefan Bellon <sbellon@sbellon.de> - - * build-riscos [__riscos__]: Set filetype of Makefile correctly. - - * conf-riscos/include/g10defs.h [__riscos__]: Added GNU GPL - header and exec code defines. - - * conf-riscos/include/config.h [__riscos__]: Moved parts to - include/util.h where they really belong to. - - * conf-riscos/Makefile [__riscos__]: Updated for new keyserver, - exec and photo id code. - -2001-12-22 Werner Koch <wk@gnupg.org> - - * autogen.sh: Fixed last change. - -2001-12-21 Werner Koch <wk@gnupg.org> - - * distfiles: Removed those files which which automake installs by - default. - - * autogen.sh: Replaced $() by backticks for system without a posix - shell. Removed gawk specific quoting. By David Champion. - -2001-10-22 Werner Koch <wk@gnupg.org> - - * autogen.sh (aclocal_vers): Require automalke 1.5. - -2001-08-21 Stefan Bellon <sbellon@sbellon.de> - - * build-riscos [__riscos__]: New. - * conf-riscos [__riscos__]: Ditto. - -2001-08-13 Werner Koch <wk@gnupg.org> - - * autogen.sh: Test on gettext 0.10.38. By Michael Engels. - -2001-08-07 Werner Koch <wk@gnupg.org> - - * autogen.sh: Adjusted --build-w32 for autoconf 2.52 - -2001-07-09 Werner Koch <wk@gnupg.org> - - * autogen.sh (autoconf_vers): Require autoconf 2.50 - -2001-05-06 Werner Koch <wk@gnupg.org> - - * config.guess, config.sub: Add updates from subversions.gnu.org. - -2001-04-19 Werner Koch <wk@gnupg.org> - - * autogen.sh: Add VPATH build support for option --build-w32. - -2001-03-12 Werner Koch <wk@gnupg.org> - - * config.guess, config.sub: Replaced with the current GNU CVS ones. - -2001-01-18 Werner Koch <wk@gnupg.org> - - * autogen.sh: New options --build-w32 - * build-w32: Does now call autogen.sh - -2000-11-24 Werner Koch <wk@gnupg.org> - - * build-w32: New script to build the W32 version. - * distfiles: And put it into the distribution - -Thu Sep 14 17:45:11 CEST 2000 Werner Koch <wk@openit.de> - - * gnupg.spec.in: Updated. - -Wed Sep 6 17:55:47 CEST 2000 Werner Koch <wk@openit.de> - - * config.guess, config.sub: Replaced with the latest version from the - CVS archive. Hope that does not break too much. - -Fri May 12 14:01:20 CEST 2000 Werner Koch <wk@openit.de> - - * gnupg.spec.in: New version from Fabio with some updated descriptions. - -Mon May 1 15:38:04 CEST 2000 Werner Koch <wk@openit.de> - - * gnupg.spec.in: New version from Fabio. - -Fri Mar 17 16:26:05 CET 2000 Werner Koch <wk@openit.de> - - * config.gues, config.sub: Support for s390-ibm-linux-gnu. Thanks - to Holger Smolinski. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de> - - * config.guess: Add support for QNX. By Sam Roberts. - * config.sub: Ditto. - -Thu Sep 23 09:49:25 1999 Werner Koch (wk@gnupg.org) - - * commit: Remove leading and trailing empty lines when copying - Changes to Changelog - -Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * gnupg.spec: Add Portuguese description - -Thu Sep 2 16:40:55 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * mkdiff: changed format of diff file name and made script more - general. - -Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * config.guess: Updated from gnu/common and applied my emx patch again. - * config.sub: Updated from gnu/common. - -Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * ltmain.sh, ltconfig.sh : Updated to libtool 1.3.3 - -Mon Jul 12 14:55:34 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * autogen.sh: Run libtoolize - -Sat May 22 22:47:26 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * autogen.sh: Fixed the error message for a missing libtool. - -Sat May 8 19:28:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * mkinstalldirs, install-sh: New from GNU repository - * config.sub, config.guess: Merged with rep version. - -Sun Mar 14 19:34:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * autogen.sh: Add a check for libtool because some autoconf macros - are needed. - -Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * autogen.sh: Enhanced the version testing code (Philippe Laliberte) - - * mkwebpage: Edits the buglist. - -Sat Feb 13 12:04:43 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * autogen.sh: Now uses gettextize - -Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * config.sub, config.guess: Support i386-emx-os2 - -Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * autogen.sh: Now checks for installed gettext - -Sat Jan 16 09:27:30 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * config.guess (m68k-atari-mint): New. - * config.sub: Add support for atarist-MiNT - -Wed Jan 13 12:49:36 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * gnupg.spec.in: New - * gnupg.spec: Removed - -Wed Dec 23 13:18:14 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * gnupg.spec: Updated version by Fabio Coatti - -Thu Dec 17 18:31:15 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * gnupg.spec: New version by Reuben Sumner and did some more - changes. - -Fri Nov 27 12:39:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - - * commit: New - - -Fri Nov 20 12:01:57 1998 Werner Koch (wk@isil.d.shuttle.de) - - * mkdiff: signs the patch file - -Sat Oct 17 16:10:16 1998 Werner Koch (wk@isil.d.shuttle.de) - - * autogen.sh: New. - -Wed Oct 14 09:55:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * config.guess (FreeBSD): Changes from Jun Kuriyama to support ELF - * config.sub: (freebsd): Add to maybe_os - - - Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 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 @@ -375,3 +12,5 @@ Wed Oct 14 09:55:25 1998 Werner Koch (wk@isil.d.shuttle.de) 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. + + diff --git a/scripts/config.guess b/scripts/config.guess index ed2e03b7f..77c7cbab0 100755 --- a/scripts/config.guess +++ b/scripts/config.guess @@ -1,9 +1,9 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2002-03-20' +timestamp='2004-08-13' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -53,7 +53,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -88,30 +88,42 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' +esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -142,6 +154,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; @@ -167,21 +180,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + luna88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; @@ -197,83 +227,76 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; sgi:OpenBSD:*:*) - echo mipseb-unknown-openbsd${UNAME_RELEASE} + echo mips64-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <<EOF >$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? @@ -296,6 +319,9 @@ EOF *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; @@ -313,6 +339,13 @@ EOF NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; @@ -381,6 +414,9 @@ EOF *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; @@ -419,15 +455,20 @@ EOF exit (-1); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; @@ -500,8 +541,7 @@ EOF exit(0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 @@ -599,11 +639,21 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) @@ -637,8 +687,7 @@ EOF exit (0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) @@ -696,21 +745,26 @@ EOF CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; @@ -732,14 +786,17 @@ EOF i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; - x86:Interix*:3*) - echo i386-pc-interix3 + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix + echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin @@ -751,17 +808,28 @@ EOF echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) + # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; @@ -782,8 +850,26 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - rm -f $dummy.c - test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu @@ -819,6 +905,9 @@ EOF s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; @@ -845,7 +934,7 @@ EOF ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; + exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; @@ -876,9 +965,11 @@ EOF LIBC=gnuaout #endif #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; @@ -896,6 +987,26 @@ EOF # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -917,22 +1028,19 @@ EOF UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about @@ -956,9 +1064,15 @@ EOF # "miniframe" echo m68010-convergent-sysv exit 0 ;; - M68*:*:R3V[567]*:*) + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[5678]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` @@ -975,9 +1089,6 @@ EOF mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; @@ -1049,6 +1160,9 @@ EOF SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; @@ -1056,7 +1170,12 @@ EOF echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + *86) UNAME_PROCESSOR=i686 ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` @@ -1069,7 +1188,7 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; - NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) @@ -1092,11 +1211,6 @@ EOF fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; @@ -1115,12 +1229,19 @@ EOF *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms && exit 0 ;; + I*) echo ia64-dec-vms && exit 0 ;; + V*) echo vax-dec-vms && exit 0 ;; + esac esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1241,8 +1362,7 @@ main () } EOF -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. diff --git a/scripts/config.rpath b/scripts/config.rpath index fa24bfc2d..4db13e50f 100755 --- a/scripts/config.rpath +++ b/scripts/config.rpath @@ -143,7 +143,7 @@ if test "$with_gnu_ld" = yes; then ld_shlibs=no ;; beos*) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no @@ -162,9 +162,9 @@ if test "$with_gnu_ld" = yes; then netbsd*) ;; solaris* | sysv5*) - if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no - elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no @@ -174,7 +174,7 @@ if test "$with_gnu_ld" = yes; then hardcode_direct=yes ;; *) - if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no diff --git a/scripts/config.sub b/scripts/config.sub index f3657978c..ac6de9869 100755 --- a/scripts/config.sub +++ b/scripts/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2002-03-07' +timestamp='2004-06-24' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -118,7 +118,8 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -144,7 +145,7 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) + -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; @@ -228,28 +229,42 @@ case $basic_machine in | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ - | d10v | d30v | dsp16xx \ - | fr30 \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el | mips64vr4300 \ - | mips64vr4300el | mips64vr5000 | mips64vr5000el \ - | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ - | mipsisa32 | mipsisa64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ - | tahoe | thumb | tic80 | tron \ + | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ @@ -281,34 +296,51 @@ case $basic_machine in | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armv*-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c54x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | fx80-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ - | m32r-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ - | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ - | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ - | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | msp430-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ @@ -332,6 +364,9 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -346,6 +381,12 @@ case $basic_machine in basic_machine=a29k-none os=-bsd ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -405,12 +446,24 @@ case $basic_machine in basic_machine=j90-cray os=-unicos ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; @@ -611,10 +664,6 @@ case $basic_machine in mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; monitor) basic_machine=m68k-rom68k os=-coff @@ -706,6 +755,10 @@ case $basic_machine in basic_machine=or32-unknown os=-coff ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose @@ -728,49 +781,55 @@ case $basic_machine in pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon) + pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; - pentiumii | pentium2) + pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; + pentium4) + basic_machine=i786-pc + ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pentiumii-* | pentium2-*) + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown - ;; + ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown - ;; + ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown - ;; + ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; @@ -801,6 +860,16 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; @@ -808,6 +877,9 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sh64) + basic_machine=sh64-unknown + ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks @@ -866,7 +938,7 @@ case $basic_machine in sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; - sv1) + sv1) basic_machine=sv1-cray os=-unicos ;; @@ -874,10 +946,6 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; - t3d) - basic_machine=alpha-cray - os=-unicos - ;; t3e) basic_machine=alphaev5-cray os=-unicos @@ -890,6 +958,14 @@ case $basic_machine in basic_machine=tic54x-unknown os=-coff ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; tx39) basic_machine=mipstx39-unknown ;; @@ -903,6 +979,10 @@ case $basic_machine in tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi @@ -924,8 +1004,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -946,11 +1026,7 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; - xps | xps100) + xps | xps100) basic_machine=xps100-honeywell ;; ymp) @@ -980,6 +1056,9 @@ case $basic_machine in romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; @@ -996,16 +1075,16 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb) + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; - sparc | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -1020,10 +1099,6 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -1079,18 +1154,20 @@ case $os in | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1102,8 +1179,10 @@ case $os in ;; esac ;; + -nto-qnx*) + ;; -nto*) - os=-nto-qnx + os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ @@ -1112,6 +1191,9 @@ case $os in -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; @@ -1124,6 +1206,9 @@ case $os in -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; @@ -1145,6 +1230,9 @@ case $os in -atheos*) os=-atheos ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; @@ -1155,7 +1243,7 @@ case $os in os=-rtmk-nova ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1167,6 +1255,9 @@ case $os in -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; @@ -1194,8 +1285,14 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos ;; -none) ;; @@ -1228,11 +1325,14 @@ case $basic_machine in arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1274,6 +1374,9 @@ case $basic_machine in *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; @@ -1325,19 +1428,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1406,10 +1509,16 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; - -vxsim* | -vxworks*) + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) diff --git a/sm/ChangeLog b/sm/ChangeLog index 28a397182..1192c8523 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,7 @@ 2004-09-30 Werner Koch <wk@g10code.com> + * Makefile.am: Adjusted for gettext 0.14. + * keylist.c (list_cert_colon): Make sure that the expired flag has a higher precedence than the invalid flag. diff --git a/sm/Makefile.am b/sm/Makefile.am index 1ac7cbe84..0cb96c57f 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -53,4 +53,6 @@ gpgsm_SOURCES = \ gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(KSBA_LIBS) -lgpg-error \ - $(INTLLIBS) + $(LIBINTL) + + diff --git a/tests/ChangeLog b/tests/ChangeLog index c012c2346..749220d9a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * Makefile.am (SUBDIRS): Remove pkits until the copyright issues + have been cleared. + 2004-08-16 Werner Koch <wk@g10code.de> * Makefile.am: Descend into the new pkits directory diff --git a/tests/Makefile.am b/tests/Makefile.am index b44336bfb..bc2e50e10 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,13 +20,13 @@ ## Process this file with automake to produce Makefile.in -if RUN_PKITS_TESTS -pkits = pkits -else -pkits = -endif - -SUBDIRS = . ${pkits} +#if RUN_PKITS_TESTS +#pkits = pkits +#else +#pkits = +#endif +# +#SUBDIRS = . ${pkits} GPGSM = ../sm/gpgsm diff --git a/tools/ChangeLog b/tools/ChangeLog index befb1bf3c..fa6572ae7 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-09-30 Werner Koch <wk@g10code.com> + + * Makefile.am: Adjusted for gettext 0.14. + 2004-09-29 Werner Koch <wk@g10code.com> * gpgconf-comp.c: Made the entries fro GROUPs translatable. diff --git a/tools/Makefile.am b/tools/Makefile.am index 71a77356f..5395a90ca 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -34,6 +34,6 @@ bin_PROGRAMS = gpgconf watchgnupg gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c -gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @INTLLIBS@ +gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @LIBINTL@ watchgnupg_SOURCES = watchgnupg.c -- cgit v1.2.3 From 048635bedefb5c3244cc5a28b38ab4daafb3cf78 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 30 Sep 2004 21:37:11 +0000 Subject: * gpgv.c (i18n_init): Always use LC_ALL. * kbxutil.c (i18n_init): Always use LC_ALL. * gpgsm.c (i18n_init): Always use LC_ALL. * certdump.c (gpgsm_format_name): Factored code out to .. (gpgsm_format_name2): .. new. (gpgsm_print_name): Factored code out to .. (gpgsm_print_name2): .. new. (print_dn_part): New arg TRANSLATE. Changed all callers. (print_dn_parts): Ditto. (gpgsm_format_keydesc): Do not translate the SUBJECT; we require it to stay UTF-8 but we still want to filter out bad control characters. * gpgconf.c (i18n_init): Always use LC_ALL. --- NEWS | 2 ++ g10/ChangeLog | 2 ++ g10/gpgv.c | 7 +------ kbx/ChangeLog | 4 +++- kbx/kbxutil.c | 7 +------ sm/ChangeLog | 12 ++++++++++++ sm/certdump.c | 46 ++++++++++++++++++++++++++++++++++------------ sm/gpgsm.c | 5 ----- sm/gpgsm.h | 2 ++ tools/ChangeLog | 2 ++ tools/gpgconf.c | 5 ----- 11 files changed, 59 insertions(+), 35 deletions(-) diff --git a/NEWS b/NEWS index a93c7ce80..880e1b92b 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ Noteworthy changes in version 1.9.11 * [gpg-agent] When used without --daemon or --server, gpg-agent now check whether a agent is already running and usable. + * Fixed some i18n problems. + Noteworthy changes in version 1.9.10 (2004-07-22) ------------------------------------------------- diff --git a/g10/ChangeLog b/g10/ChangeLog index 187d8584b..36d5e3314 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,7 @@ 2004-09-30 Werner Koch <wk@g10code.com> + * gpgv.c (i18n_init): Always use LC_ALL. + * Makefile.am (LDADD): Adjusted for gettext 0.14. 2004-09-20 Werner Koch <wk@g10code.com> diff --git a/g10/gpgv.c b/g10/gpgv.c index 9bd954c6f..015736c33 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -119,12 +119,7 @@ i18n_init(void) set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS -#ifdef HAVE_LC_MESSAGES - setlocale( LC_TIME, "" ); - setlocale( LC_MESSAGES, "" ); -#else - setlocale( LC_ALL, "" ); -#endif + setlocale( LC_ALL, "" ); bindtextdomain( PACKAGE_GT, LOCALEDIR ); textdomain( PACKAGE_GT ); #endif diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 546b4c34d..c10ea126a 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,6 +1,8 @@ 2004-09-30 Werner Koch <wk@g10code.com> - * Makefile.am: Adjusted fro gettext 0.14. + * kbxutil.c (i18n_init): Always use LC_ALL. + + * Makefile.am: Adjusted for gettext 0.14. 2004-08-24 Werner Koch <wk@g10code.de> diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index cd5da5f77..7fe6178d6 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -129,12 +129,7 @@ i18n_init(void) set_gettext_file( PACKAGE_GT ); #else #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_TIME, "" ); - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif + setlocale( LC_ALL, "" ); bindtextdomain( PACKAGE_GT, LOCALEDIR ); textdomain( PACKAGE_GT ); #endif diff --git a/sm/ChangeLog b/sm/ChangeLog index 1192c8523..36390c344 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,17 @@ 2004-09-30 Werner Koch <wk@g10code.com> + * gpgsm.c (i18n_init): Always use LC_ALL. + + * certdump.c (gpgsm_format_name): Factored code out to .. + (gpgsm_format_name2): .. new. + (gpgsm_print_name): Factored code out to .. + (gpgsm_print_name2): .. new. + (print_dn_part): New arg TRANSLATE. Changed all callers. + (print_dn_parts): Ditto. + (gpgsm_format_keydesc): Do not translate the SUBJECT; we require + it to stay UTF-8 but we still want to filter out bad control + characters. + * Makefile.am: Adjusted for gettext 0.14. * keylist.c (list_cert_colon): Make sure that the expired flag has diff --git a/sm/certdump.c b/sm/certdump.c index 33052b186..cdf4edcc1 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -427,7 +427,7 @@ parse_dn (const unsigned char *string) static void -print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) +print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key, int translate) { struct dn_array_s *first_dn = dn; @@ -446,7 +446,10 @@ print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) if (!dn->done && dn->value && *dn->value) { fprintf (fp, "/%s=", dn->key); - print_sanitized_utf8_string (fp, dn->value, '/'); + if (translate) + print_sanitized_utf8_string (fp, dn->value, '/'); + else + print_sanitized_string (fp, dn->value, '/'); } dn->done = 1; if (dn > first_dn && dn[-1].multivalued) @@ -461,7 +464,7 @@ print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key) /* Print all parts of a DN in a "standard" sequence. We first print all the known parts, followed by the uncommon ones */ static void -print_dn_parts (FILE *fp, struct dn_array_s *dn) +print_dn_parts (FILE *fp, struct dn_array_s *dn, int translate) { const char *stdpart[] = { "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL @@ -469,17 +472,17 @@ print_dn_parts (FILE *fp, struct dn_array_s *dn) int i; for (i=0; stdpart[i]; i++) - print_dn_part (fp, dn, stdpart[i]); + print_dn_part (fp, dn, stdpart[i], translate); /* Now print the rest without any specific ordering */ for (; dn->key; dn++) - print_dn_part (fp, dn, dn->key); + print_dn_part (fp, dn, dn->key, translate); } void -gpgsm_print_name (FILE *fp, const char *name) +gpgsm_print_name2 (FILE *fp, const char *name, int translate) { const unsigned char *s; int i; @@ -493,7 +496,12 @@ gpgsm_print_name (FILE *fp, const char *name) { const unsigned char *s2 = strchr (s+1, '>'); if (s2) - print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0); + { + if (translate) + print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0); + else + print_sanitized_buffer (fp, s + 1, s2 - s - 1, 0); + } } else if (*s == '(') fputs (_("[Error - unknown encoding]"), fp); @@ -508,7 +516,7 @@ gpgsm_print_name (FILE *fp, const char *name) fputs (_("[Error - invalid DN]"), fp); else { - print_dn_parts (fp, dn); + print_dn_parts (fp, dn, translate); for (i=0; dn[i].key; i++) { xfree (dn[i].key); @@ -520,6 +528,12 @@ gpgsm_print_name (FILE *fp, const char *name) } +void +gpgsm_print_name (FILE *fp, const char *name) +{ + gpgsm_print_name2 (fp, name, 1); +} + /* A cookie structure used for the memory stream. */ struct format_name_cookie @@ -558,9 +572,11 @@ format_name_writer (void *cookie, const char *buffer, size_t size) /* Format NAME which is expected to be in rfc2253 format into a better human readable format. Caller must free the returned string. NULL - is returned in case of an error. */ + is returned in case of an error. With TRANSLATE set to true the + name will be translated to the native encodig. Note that NAME is + internally always UTF-8 encoded. */ char * -gpgsm_format_name (const char *name) +gpgsm_format_name2 (const char *name, int translate) { #if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) FILE *fp; @@ -587,7 +603,7 @@ gpgsm_format_name (const char *name) errno = save_errno; return NULL; } - gpgsm_print_name (fp, name); + gpgsm_print_name2 (fp, name, translate); fclose (fp); if (cookie.error || !cookie.buffer) { @@ -601,6 +617,12 @@ gpgsm_format_name (const char *name) #endif /* No fun. */ } +char * +gpgsm_format_name (const char *name) +{ + return gpgsm_format_name2 (name, 1); +} + /* Create a key description for the CERT, this may be passed to the pinentry. The caller must free the returned string. NULL may be @@ -618,7 +640,7 @@ gpgsm_format_keydesc (ksba_cert_t cert) char *orig_codeset = NULL; name = ksba_cert_get_subject (cert, 0); - subject = name? gpgsm_format_name (name) : NULL; + subject = name? gpgsm_format_name2 (name, 0) : NULL; ksba_free (name); name = NULL; sexp = ksba_cert_get_serial (cert); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 5e3e0f2d9..6e2bbe742 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -560,12 +560,7 @@ i18n_init(void) 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 diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 72486aadb..18f50e9fe 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -202,6 +202,7 @@ void gpgsm_destroy_writer (Base64Context ctx); /*-- certdump.c --*/ void gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p); void gpgsm_print_time (FILE *fp, ksba_isotime_t t); +void gpgsm_print_name2 (FILE *fp, const char *string, int translate); void gpgsm_print_name (FILE *fp, const char *string); void gpgsm_dump_cert (const char *text, ksba_cert_t cert); @@ -210,6 +211,7 @@ void gpgsm_dump_time (ksba_isotime_t t); void gpgsm_dump_string (const char *string); char *gpgsm_format_serial (ksba_const_sexp_t p); +char *gpgsm_format_name2 (const char *name, int translate); char *gpgsm_format_name (const char *name); char *gpgsm_format_keydesc (ksba_cert_t cert); diff --git a/tools/ChangeLog b/tools/ChangeLog index fa6572ae7..1eefac53a 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,7 @@ 2004-09-30 Werner Koch <wk@g10code.com> + * gpgconf.c (i18n_init): Always use LC_ALL. + * Makefile.am: Adjusted for gettext 0.14. 2004-09-29 Werner Koch <wk@g10code.com> diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 7aca335fa..e3e1b9f1a 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -106,12 +106,7 @@ i18n_init(void) 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 -- cgit v1.2.3 From a90acadd51081fcb69460cb2222ed4be20e903d3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 1 Oct 2004 12:53:09 +0000 Subject: * gpgconf-comp.c (my_dgettext): Also switch codeset and directory for the other used domains (i.e. dirmngr). * gpgconf.c (main): Fixed translation markers. --- po/de.po | 98 ++++++++++++++++++++++++++++------------------------ sm/gpgsm.c | 2 +- tools/ChangeLog | 7 ++++ tools/gpgconf-comp.c | 15 +++++--- tools/gpgconf.c | 7 ++-- 5 files changed, 76 insertions(+), 53 deletions(-) diff --git a/po/de.po b/po/de.po index 3c4d90a44..77ce206c0 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-09-30 15:22+0200\n" -"PO-Revision-Date: 2004-09-30 15:23+0200\n" +"POT-Creation-Date: 2004-10-01 14:24+0200\n" +"PO-Revision-Date: 2004-10-01 14:27+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -41,7 +41,7 @@ msgstr "ausf #: agent/gpg-agent.c:102 kbx/kbxutil.c:82 scd/scdaemon.c:98 sm/gpgsm.c:316 msgid "be somewhat more quiet" -msgstr "etwas weniger Aussageb erzeugen" +msgstr "Etwas weniger Ausgaben erzeugen" #: agent/gpg-agent.c:103 scd/scdaemon.c:99 msgid "sh-style command output" @@ -121,30 +121,30 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:608 +#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:603 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:446 agent/protect-tool.c:1050 kbx/kbxutil.c:436 -#: scd/scdaemon.c:357 scd/sc-investigate.c:181 sm/gpgsm.c:731 +#: agent/gpg-agent.c:446 agent/protect-tool.c:1050 kbx/kbxutil.c:431 +#: scd/scdaemon.c:357 scd/sc-investigate.c:181 sm/gpgsm.c:726 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:519 scd/scdaemon.c:437 sm/gpgsm.c:829 +#: agent/gpg-agent.c:519 scd/scdaemon.c:437 sm/gpgsm.c:824 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" #: agent/gpg-agent.c:524 agent/gpg-agent.c:998 scd/scdaemon.c:442 -#: sm/gpgsm.c:833 +#: sm/gpgsm.c:828 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:532 scd/scdaemon.c:450 sm/gpgsm.c:840 +#: agent/gpg-agent.c:532 scd/scdaemon.c:450 sm/gpgsm.c:835 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" @@ -412,7 +412,7 @@ msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" #: scd/scdaemon.c:126 msgid "allow the use of admin card commands" -msgstr "Erlaube die Benuztung von \"Admin\" Kommandos" +msgstr "Erlaube die Benutzung von \"Admin\" Kommandos" #: scd/scdaemon.c:171 msgid "Usage: scdaemon [options] (-h for help)" @@ -569,23 +569,23 @@ msgstr "keine" msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:490 +#: sm/certdump.c:493 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:499 +#: sm/certdump.c:507 msgid "[Error - unknown encoding]" msgstr "[Fehler - Unbekannte Kodierung]" -#: sm/certdump.c:503 +#: sm/certdump.c:511 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungltige Kodierung]" -#: sm/certdump.c:508 +#: sm/certdump.c:516 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungltiger DN]" -#: sm/certdump.c:655 +#: sm/certdump.c:677 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -907,7 +907,7 @@ msgstr "Eingabedaten sind im PEM Format" #: sm/gpgsm.c:269 msgid "assume input is in base-64 format" -msgstr "Eingabedaten sin im Basis-64 Format" +msgstr "Eingabedaten sind im Basis-64 Format" #: sm/gpgsm.c:271 msgid "assume input is in binary format" @@ -1009,6 +1009,10 @@ msgstr "|HOST|Benutze HOST als Schl msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" +#: sm/gpgsm.c:338 +msgid "|LEVEL|set the debugging level to LEVEL" +msgstr "|STRING|Die Debugstufe auf STING setzen" + #: sm/gpgsm.c:345 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" @@ -1078,50 +1082,50 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:579 +#: sm/gpgsm.c:574 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:645 +#: sm/gpgsm.c:640 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:661 +#: sm/gpgsm.c:656 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:736 +#: sm/gpgsm.c:731 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1183 +#: sm/gpgsm.c:1178 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1195 +#: sm/gpgsm.c:1190 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1221 +#: sm/gpgsm.c:1216 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1229 +#: sm/gpgsm.c:1224 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1259 +#: sm/gpgsm.c:1254 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1423 +#: sm/gpgsm.c:1418 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1646 sm/gpgsm.c:1679 +#: sm/gpgsm.c:1641 sm/gpgsm.c:1674 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" @@ -1330,54 +1334,58 @@ msgstr "" "Syntax: gpgconf {Optionen]\n" "Verwalte Konfigurationsoptionen fr Programme des GnuPG Systems\n" -#: tools/gpgconf.c:180 +#: tools/gpgconf.c:175 msgid "usage: gpgconf [options] " msgstr "Gebrauch: gpgconf [Optionen] " -#: tools/gpgconf.c:181 +#: tools/gpgconf.c:176 msgid "Need one component argument" msgstr "Bentige ein Komponenten Argument" -#: tools/gpgconf.c:190 +#: tools/gpgconf.c:185 msgid "Component not found" msgstr "Komponente nicht gefunden" -#: tools/gpgconf-comp.c:432 tools/gpgconf-comp.c:493 tools/gpgconf-comp.c:558 -#: tools/gpgconf-comp.c:611 tools/gpgconf-comp.c:674 +#: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:496 tools/gpgconf-comp.c:561 +#: tools/gpgconf-comp.c:614 tools/gpgconf-comp.c:677 msgid "Options controlling the diagnostic output" msgstr "Optionen zur Einstellung Diagnoseausgaben" -#: tools/gpgconf-comp.c:445 tools/gpgconf-comp.c:506 tools/gpgconf-comp.c:571 -#: tools/gpgconf-comp.c:624 tools/gpgconf-comp.c:697 +#: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:509 tools/gpgconf-comp.c:574 +#: tools/gpgconf-comp.c:627 tools/gpgconf-comp.c:700 msgid "Options controlling the configuration" msgstr "Optionen zur Einstellung der Konfiguration" -#: tools/gpgconf-comp.c:452 tools/gpgconf-comp.c:529 tools/gpgconf-comp.c:578 -#: tools/gpgconf-comp.c:631 tools/gpgconf-comp.c:704 +#: tools/gpgconf-comp.c:455 tools/gpgconf-comp.c:532 tools/gpgconf-comp.c:581 +#: tools/gpgconf-comp.c:634 tools/gpgconf-comp.c:707 msgid "Options useful for debugging" -msgstr "Nützliche Optionen zum Debuggen" +msgstr "Ntzliche Optionen zum Debuggen" + +#: tools/gpgconf-comp.c:460 +msgid "|FILE|write server mode logs to FILE" +msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" -#: tools/gpgconf-comp.c:465 tools/gpgconf-comp.c:539 tools/gpgconf-comp.c:644 +#: tools/gpgconf-comp.c:468 tools/gpgconf-comp.c:542 tools/gpgconf-comp.c:647 msgid "Options controlling the security" msgstr "Optionen zur Einstellung der Sicherheit" -#: tools/gpgconf-comp.c:591 +#: tools/gpgconf-comp.c:594 msgid "Configuration for Keyservers" -msgstr "Konfiguration der Schlüsselserver" +msgstr "Konfiguration der Schlsselserver" -#: tools/gpgconf-comp.c:687 +#: tools/gpgconf-comp.c:690 msgid "Options controlling the format of the output" msgstr "Optionen zum Einstellen der Ausgabeformate" -#: tools/gpgconf-comp.c:723 +#: tools/gpgconf-comp.c:726 msgid "Options controlling the interactivity and enforcement" -msgstr "Optionen zur Einstellung der Interaktivität und Geltendmachung" +msgstr "Optionen zur Einstellung der Interaktivitt und Geltendmachung" -#: tools/gpgconf-comp.c:733 +#: tools/gpgconf-comp.c:736 msgid "Configuration of LDAP servers to use" msgstr "Konfiguration der zu nutzenden LDAP-Server" -#: tools/gpgconf-comp.c:758 +#: tools/gpgconf-comp.c:761 msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 6e2bbe742..0f620c091 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -335,7 +335,7 @@ static ARGPARSE_OPTS opts[] = { { oOptions, "options" , 2, N_("read options from file")}, { oDebug, "debug" ,4|16, "@"}, - { oDebugLevel, "debug-level" ,2, "@"}, + { oDebugLevel, "debug-level" ,2, N_("|LEVEL|set the debugging level to LEVEL")}, { oDebugAll, "debug-all" ,0, "@"}, { oDebugWait, "debug-wait" ,1, "@"}, { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" }, diff --git a/tools/ChangeLog b/tools/ChangeLog index 1eefac53a..c18562f01 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2004-10-01 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c (my_dgettext): Also switch codeset and directory + for the other used domains (i.e. dirmngr). + + * gpgconf.c (main): Fixed translation markers. + 2004-09-30 Werner Koch <wk@g10code.com> * gpgconf.c (i18n_init): Always use LC_ALL. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index b140db76e..e69b177e4 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -364,7 +364,10 @@ struct gc_option and options. Note that we try to keep the description of groups within the - gnupg domain. */ + gnupg domain. + + IMPORTANT: If you add a new domain please make sure to add a code + set switching call to the function my_dgettext further below. */ const char *desc_domain; /* A gettext description for this group or option. If it starts @@ -454,7 +457,7 @@ static gc_option_t gc_options_gpg_agent[] = "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT }, { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED, - "gnupg", "|FILE|write logs to FILE", + "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, @@ -760,7 +763,7 @@ static gc_option_t gc_options_dirmngr[] = "dirmngr", "allow sending OCSP requests", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, - "dirmngr", "|URL|use OCSP responder URL", + "dirmngr", "|URL|use OCSP responder at URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|FPR|OCSP response signed by FPR", @@ -874,8 +877,12 @@ my_dgettext (const char *domain, const char *msgid) if (!switched_codeset) { - bind_textdomain_codeset (PACKAGE_GT, "utf-8"); switched_codeset = 1; + bind_textdomain_codeset (PACKAGE_GT, "utf-8"); + + bindtextdomain ("dirmngr", LOCALEDIR); + bind_textdomain_codeset ("dirmngr", "utf-8"); + } /* Note: This is a hack to actually use the gnupg2 domain as diff --git a/tools/gpgconf.c b/tools/gpgconf.c index e3e1b9f1a..dd505e99d 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -172,8 +172,9 @@ main (int argc, char **argv) case aChangeOptions: if (!fname) { - fputs (N_("usage: gpgconf [options] "), stderr); - fputs (N_("Need one component argument"), stderr); + fputs (_("usage: gpgconf [options] "), stderr); + putc ('\n',stderr); + fputs (_("Need one component argument"), stderr); putc ('\n',stderr); exit (2); } @@ -182,7 +183,7 @@ main (int argc, char **argv) int idx = gc_component_find (fname); if (idx < 0) { - fputs (N_("Component not found"), stderr); + fputs (_("Component not found"), stderr); putc ('\n', stderr); exit (1); } -- cgit v1.2.3 From 88458e8679bb1aedb725e5868f1d75d0b7f06761 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 1 Oct 2004 12:54:53 +0000 Subject: *** empty log message *** --- ChangeLog | 4 ++++ NEWS | 2 +- configure.ac | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb7379bf1..0e83541c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-10-01 Werner Koch <wk@g10code.com> + + Released 1.9.11. + 2004-09-30 Werner Koch <wk@g10code.com> * README: Minor updates. diff --git a/NEWS b/NEWS index 880e1b92b..d76ef3451 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.11 +Noteworthy changes in version 1.9.11 (2004-10-01) ------------------------------------------------- * When using --import along with --with-validation, the imported diff --git a/configure.ac b/configure.ac index bce1555b0..21cdfa76a 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.11-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.11, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 59806c405802ca0c8d8cc25bf0835065c65ec041 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 1 Oct 2004 12:55:04 +0000 Subject: updated --- po/de.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/po/de.po b/po/de.po index 77ce206c0..0a5ed54a6 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-10-01 14:24+0200\n" +"POT-Creation-Date: 2004-10-01 14:54+0200\n" "PO-Revision-Date: 2004-10-01 14:27+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -1338,11 +1338,11 @@ msgstr "" msgid "usage: gpgconf [options] " msgstr "Gebrauch: gpgconf [Optionen] " -#: tools/gpgconf.c:176 +#: tools/gpgconf.c:177 msgid "Need one component argument" msgstr "Bentige ein Komponenten Argument" -#: tools/gpgconf.c:185 +#: tools/gpgconf.c:186 msgid "Component not found" msgstr "Komponente nicht gefunden" -- cgit v1.2.3 From 9fff2719b6bb09ffb0bb445db636e92ff61a34c9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 1 Oct 2004 13:31:46 +0000 Subject: post release preparations --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d76ef3451..88baf21d1 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.12 +------------------------------------------------- + + Noteworthy changes in version 1.9.11 (2004-10-01) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 21cdfa76a..5fd8efe42 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.11, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.12-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 545ddc6f3d7d79e48bd72f10efefe18b7585865b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 1 Oct 2004 16:51:18 +0000 Subject: Made all strings for --log-file read the same. --- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index c18562f01..ccfd39293 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-10-01 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c: Made all strings for --log-file read the same. + 2004-10-01 Werner Koch <wk@g10code.com> * gpgconf-comp.c (my_dgettext): Also switch codeset and directory diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e69b177e4..67623ccfd 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -534,7 +534,7 @@ static gc_option_t gc_options_scdaemon[] = "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, - "gnupg", "|FILE|write logs to FILE", + "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, { "Security", @@ -583,7 +583,7 @@ static gc_option_t gc_options_gpg[] = "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, - "gnupg", "|FILE|write logs to FILE", + "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG }, /* { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */ /* NULL, NULL, */ @@ -636,7 +636,7 @@ static gc_option_t gc_options_gpgsm[] = "gnupg", "|LEVEL|set the debugging level to LEVEL", GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, - "gnupg", "|FILE|write logs to FILE", + "gnupg", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM }, { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, @@ -712,7 +712,7 @@ static gc_option_t gc_options_dirmngr[] = "dirmngr", "do not detach from the console", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, - "dirmngr", "|FILE|write logs to FILE", + "dirmngr", N_("|FILE|write server mode logs to FILE"), GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR }, { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, NULL, NULL, -- cgit v1.2.3 From 31cdfcafe4940a34616beaa1cbfb92bae1ce03e9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 4 Oct 2004 11:52:42 +0000 Subject: Typo fixes. --- po/ChangeLog | 4 ++++ po/de.po | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/po/ChangeLog b/po/ChangeLog index b7a550c11..f1396acfc 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2004-10-04 Werner Koch <wk@g10code.com> + + * de.po: Typo fixes. + 2004-09-30 gettextize <bug-gnu-gettext@gnu.org> * Makefile.in.in: Upgrade to gettext-0.14.1. diff --git a/po/de.po b/po/de.po index 0a5ed54a6..489164ff6 100644 --- a/po/de.po +++ b/po/de.po @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" "POT-Creation-Date: 2004-10-01 14:54+0200\n" -"PO-Revision-Date: 2004-10-01 14:27+0200\n" +"PO-Revision-Date: 2004-10-04 13:48+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -1011,7 +1011,7 @@ msgstr "|NAME|Den Zeichensatz f #: sm/gpgsm.c:338 msgid "|LEVEL|set the debugging level to LEVEL" -msgstr "|STRING|Die Debugstufe auf STING setzen" +msgstr "|NAME|Die Debugstufe auf NAME setzen" #: sm/gpgsm.c:345 msgid "|FD|write status info to this FD" @@ -1023,7 +1023,7 @@ msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" #: sm/gpgsm.c:358 msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAME|Den Verhsclsselungsalgrithmus NAME benutzen" +msgstr "|NAME|Den Verschlsselungsalgrithmus NAME benutzen" #: sm/gpgsm.c:360 msgid "|NAME|use message digest algorithm NAME" -- cgit v1.2.3 From ad5d5fce4fd8a254f00cb18a983a2fea23a33e7e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 4 Oct 2004 13:21:37 +0000 Subject: (setup_pinentry_env): Try hard to set a default for GPG_TTY. --- sm/ChangeLog | 4 ++++ sm/misc.c | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 36390c344..feef043ef 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-10-04 Werner Koch <wk@g10code.com> + + * misc.c (setup_pinentry_env): Try hard to set a default for GPG_TTY. + 2004-09-30 Werner Koch <wk@g10code.com> * gpgsm.c (i18n_init): Always use LC_ALL. diff --git a/sm/misc.c b/sm/misc.c index 281056177..bfe8191fd 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -30,7 +30,7 @@ #endif #include "gpgsm.h" - +#include "i18n.h" /* Setup the environment so that the pinentry is able to get all required information. This is used prior to an exec of the @@ -42,8 +42,23 @@ setup_pinentry_env (void) if (opt.display) setenv ("DISPLAY", opt.display, 1); + + /* Try to make sure that GPG_TTY has been set. This is needed if we + call for example the protect-tools with redirected stdin and thus + it won't be able to ge a default by itself. Try to do it here + but print a warning. */ if (opt.ttyname) setenv ("GPG_TTY", opt.ttyname, 1); + else if (!(lc=getenv ("GPG_TTY")) || !*lc) + { + log_error (_("GPG_TTY has not been set - " + "using maybe bogus default\n")); + lc = ttyname (0); + if (!lc) + lc = "/dev/tty"; + setenv ("GPG_TTY", lc, 1); + } + if (opt.ttytype) setenv ("TERM", opt.ttytype, 1); -- cgit v1.2.3 From f0c793c5a74aec13e73e6b585f3f84b8c130fc80 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 6 Oct 2004 13:13:51 +0000 Subject: (ccid_open_reader): Store the vendor ID. (ccid_transceive_secure): New. (parse_ccid_descriptor): Workaround for an SCM reader problem. --- scd/ChangeLog | 10 ++ scd/ccid-driver.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++++++---- scd/ccid-driver.h | 5 + 3 files changed, 369 insertions(+), 26 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 493af3fd6..60311e705 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,13 @@ +2004-10-06 Werner Koch <wk@g10code.de> + + * ccid-driver.c (ccid_open_reader): Store the vendor ID. + (ccid_transceive_secure): New. + (parse_ccid_descriptor): Workaround for an SCM reader problem. + +2004-10-04 Werner Koch <wk@g10code.de> + + * ccid-driver.c (send_escape_cmd): New. + 2004-09-30 Werner Koch <wk@g10code.com> * Makefile.am: Adjusted for gettext 0.14. diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 77fea944b..287a8d87d 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -154,8 +154,6 @@ - - enum { RDR_to_PC_NotifySlotChange= 0x50, RDR_to_PC_HardwareError = 0x51, @@ -183,12 +181,21 @@ enum { }; +/* We need to know the vendor to do some hacks. */ +enum { + VENDOR_SCM = 0x04e6 +}; + + /* Store information on the driver's state. A pointer to such a structure is used as handle for most functions. */ struct ccid_driver_s { usb_dev_handle *idev; char *rid; + unsigned short id_vendor; + unsigned short id_product; + unsigned short bcd_device; int seqno; unsigned char t1_ns; unsigned char t1_nr; @@ -251,6 +258,8 @@ parse_ccid_descriptor (ccid_driver_t handle, handle->max_ifsd = 32; handle->ifsd = 0; handle->has_pinpad = 0; + DEBUGOUT_3 ("idVendor: %04X idProduct: %04X bcdDevice: %04X\n", + handle->id_vendor, handle->id_product, handle->bcd_device); if (buflen < 54 || buf[0] < 54) { DEBUGOUT ("CCID device descriptor is too short\n"); @@ -417,8 +426,25 @@ parse_ccid_descriptor (ccid_driver_t handle, "this is not available\n"); return -1; } - else - return 0; + + + /* SCM drivers get stuck in their internal USB stack if they try to + send a frame of n*wMaxPacketSize back to us. Given that + wMaxPacketSize is 64 for these readers we set the IFSD to a value + lower than that: + 64 - 10 CCID header - 4 T1frame - 2 reserved = 48 */ + if (handle->id_vendor == VENDOR_SCM + /* FIXME: check whether it is the same + firmware version for all drivers. */ + && handle->bcd_device < 0x0513 + && handle->max_ifsd > 48) + { + DEBUGOUT ("enabling workaround for buggy SCM readers\n"); + handle->max_ifsd = 48; + } + + + return 0; } @@ -436,7 +462,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx, if (!idx) return NULL; - /* Fixme: The next line for the current Valgrid without support + /* Fixme: The next line is for the current Valgrid without support for USB IOCTLs. */ memset (buf, 0, sizeof buf); @@ -825,6 +851,9 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) } (*handle)->idev = idev; (*handle)->rid = rid; + (*handle)->id_vendor = dev->descriptor.idVendor; + (*handle)->id_product = dev->descriptor.idProduct; + (*handle)->bcd_device = dev->descriptor.bcdDevice; DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid ); @@ -1082,6 +1111,43 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, } +/* Note that this fucntion won't return the error codes NO_CARD or + CARD_INACTIVE */ +static int +send_escape_cmd (ccid_driver_t handle, + const unsigned char *data, size_t datalen) +{ + int i, rc; + unsigned char msg[100]; + size_t msglen; + unsigned char seqno; + + if (datalen > sizeof msg - 10) + return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large. */ + + msg[0] = PC_to_RDR_Escape; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* RFU */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + memcpy (msg+10, data, datalen); + msglen = 10 + datalen; + set_msg_len (msg, datalen); + + DEBUGOUT ("sending"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno); + + return rc; +} + + /* experimental */ int ccid_poll (ccid_driver_t handle) @@ -1617,10 +1683,232 @@ ccid_transceive (ccid_driver_t handle, } +/* Send the CCID Secure command to the reader. APDU_BUF should contain the APDU template. PIN_MODE defines now the pin gets formatted: + + 1 := The PIN is ASCII encoded and of variable length. The + length of the PIN entered will be put into Lc by the reader. + The APDU should me made up of 4 bytes without Lc. + + PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0 + may be used t enable usbale defaults. PIN_PADLEN should be 0 + + When called with RESP and NRESP set to NULL, the function will + merely check whether the reader supports the secure command for the + given APDU and PIN_MODE. */ +int +ccid_transceive_secure (ccid_driver_t handle, + const unsigned char *apdu_buf, size_t apdu_buflen, + int pin_mode, int pinlen_min, int pinlen_max, + int pin_padlen, + unsigned char *resp, size_t maxresplen, size_t *nresp) +{ + int rc; + unsigned char send_buffer[10+259], recv_buffer[10+259]; + unsigned char *msg, *tpdu, *p; + size_t msglen, tpdulen, n; + unsigned char seqno; + int i; + size_t dummy_nresp; + int testmode; + + testmode = !resp && !nresp; + + if (!nresp) + nresp = &dummy_nresp; + *nresp = 0; + + if (apdu_buflen >= 4 && apdu_buf[1] == 0x20 && (handle->has_pinpad & 1)) + ; + else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2)) + return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */ + else + return CCID_DRIVER_ERR_NOT_SUPPORTED; + + if (pin_mode != 1) + return CCID_DRIVER_ERR_NOT_SUPPORTED; + + if (pin_padlen != 0) + return CCID_DRIVER_ERR_NOT_SUPPORTED; + + if (!pinlen_min) + pinlen_min = 1; + if (!pinlen_max) + pinlen_max = 25; + + /* Note that the 25 is the maximum value the SPR532 allows. */ + if (pinlen_min < 1 || pinlen_min > 25 + || pinlen_max < 1 || pinlen_max > 25 + || pinlen_min > pinlen_max) + return CCID_DRIVER_ERR_INV_VALUE; + + /* We have only tested this with an SCM reader so better don't risk + anything and do not allow the use with other readers. */ + if (handle->id_vendor != VENDOR_SCM) + return CCID_DRIVER_ERR_NOT_SUPPORTED; + + if (testmode) + return 0; /* Success */ + + msg = send_buffer; + if (handle->id_vendor == VENDOR_SCM) + { + DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n"); + rc = send_escape_cmd (handle, "\x80\x02\x00", 3); + if (rc) + return rc; + } + + msg[0] = PC_to_RDR_Secure; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 4; /* bBWI */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + msg[10] = 0; /* Perform PIN verification. */ + msg[11] = 0; /* Timeout in seconds. */ + msg[12] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */ + if (handle->id_vendor == VENDOR_SCM) + { + /* For the SPR532 the next 2 bytes need to be zero. We do this + for all SCM product. Kudos to to Martin Paljak for this + hint. */ + msg[13] = msg[14] = 0; + } + else + { + msg[13] = 0x00; /* bmPINBlockString: + 0 bits of pin length to insert. + 0 bytes of PIN block size. */ + msg[14] = 0x00; /* bmPINLengthFormat: + Units are bytes, position is 0. */ + } + msg[15] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ + msg[16] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ + msg[17] = 0x02; /* bEntryValidationCondition: + Validation key pressed */ + if (pinlen_min && pinlen_max && pinlen_min == pinlen_max) + msg[17] |= 0x01; /* Max size reached. */ + msg[18] = 0xff; /* bNumberMessage: Default. */ + msg[19] = 0x04; /* wLangId-High. */ + msg[20] = 0x09; /* wLangId-Low: English FIXME: use the first entry. */ + msg[21] = 0; /* bMsgIndex. */ + /* bTeoProlog follows: */ + msg[22] = handle->nonnull_nad? ((1 << 4) | 0): 0; + msg[23] = ((handle->t1_ns & 1) << 6); /* I-block */ + msg[24] = 4; /* apdulen. */ + /* APDU follows: */ + msg[25] = apdu_buf[0]; /* CLA */ + msg[26] = apdu_buf[1]; /* INS */ + msg[27] = apdu_buf[2]; /* P1 */ + msg[28] = apdu_buf[3]; /* P2 */ + msglen = 29; + set_msg_len (msg, msglen - 10); + + DEBUGOUT ("sending"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + + msg = recv_buffer; + rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, + RDR_to_PC_DataBlock, seqno); + if (rc) + return rc; + + tpdu = msg + 10; + tpdulen = msglen - 10; + + if (tpdulen < 4) + { + usb_clear_halt (handle->idev, 0x82); + return CCID_DRIVER_ERR_ABORTED; + } +#ifdef DEBUG_T1 + fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 + ); +#endif + + if (!(tpdu[1] & 0x80)) + { /* This is an I-block. */ + /* Last block sent was successful. */ + handle->t1_ns ^= 1; + + if (!!(tpdu[1] & 0x40) != handle->t1_nr) + { /* Reponse does not match our sequence number. */ + DEBUGOUT ("I-block with wrong seqno received\n"); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + + handle->t1_nr ^= 1; + + p = tpdu + 3; /* Skip the prologue field. */ + n = tpdulen - 3 - 1; /* Strip the epilogue field. */ + /* fixme: verify the checksum. */ + if (resp) + { + if (n > maxresplen) + { + DEBUGOUT_2 ("provided buffer too short for received data " + "(%u/%u)\n", + (unsigned int)n, (unsigned int)maxresplen); + return CCID_DRIVER_ERR_INV_VALUE; + } + + memcpy (resp, p, n); + resp += n; + *nresp += n; + maxresplen -= n; + } + + if (!(tpdu[1] & 0x20)) + return 0; /* No chaining requested - ready. */ + + DEBUGOUT ("chaining requested but not supported for Secure operation\n"); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + else if ((tpdu[1] & 0xc0) == 0x80) + { /* This is a R-block. */ + if ( (tpdu[1] & 0x0f)) + { /* Error: repeat last block */ + DEBUGOUT ("No retries supported for Secure operation\n"); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + else if (!!(tpdu[1] & 0x40) == handle->t1_ns) + { /* Reponse does not match our sequence number. */ + DEBUGOUT ("R-block with wrong seqno received on more bit\n"); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + else + { /* Send next chunk. */ + DEBUGOUT ("chaining not supported on Secure operation\n"); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + } + else + { /* This is a S-block. */ + DEBUGOUT_2 ("T1 S-block %s received cmd=%d for Secure operation\n", + (tpdu[1] & 0x20)? "response": "request", + (tpdu[1] & 0x1f)); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + + return 0; +} + + #ifdef TEST + static void print_error (int err) { @@ -1682,6 +1970,9 @@ main (int argc, char **argv) unsigned int slotstat; unsigned char result[512]; size_t resultlen; + int no_pinpad = 0; + int verify_123456 = 0; + int did_verify = 0; if (argc) { @@ -1706,6 +1997,16 @@ main (int argc, char **argv) ccid_set_debug_level (1); argc--; argv++; } + else if ( !strcmp (*argv, "--no-pinpad")) + { + no_pinpad = 1; + argc--; argv++; + } + else if ( !strcmp (*argv, "--verify-123456")) + { + verify_123456 = 1; + argc--; argv++; + } else break; } @@ -1755,28 +2056,55 @@ main (int argc, char **argv) print_result (rc, result, resultlen); } - ccid_poll (ccid); + if (!no_pinpad) + { + } + + if (!no_pinpad) + { + static unsigned char apdu[] = { 0, 0x20, 0, 0x81 }; + + + if (ccid_transceive_secure (ccid, + apdu, sizeof apdu, + 1, 0, 0, 0, + NULL, 0, NULL)) + fputs ("can't verify using a PIN-Pad reader\n", stderr); + else + { + fputs ("verifying CHV1 using the PINPad ....\n", stderr); + + rc = ccid_transceive_secure (ccid, + apdu, sizeof apdu, + 1, 0, 0, 0, + result, sizeof result, &resultlen); + print_result (rc, result, resultlen); + did_verify = 1; + } + } + + if (verify_123456 && !did_verify) + { + fputs ("verifying that CHV1 is 123456....\n", stderr); + { + static unsigned char apdu[] = {0, 0x20, 0, 0x81, + 6, '1','2','3','4','5','6'}; + rc = ccid_transceive (ccid, apdu, sizeof apdu, + result, sizeof result, &resultlen); + print_result (rc, result, resultlen); + } + } -/* if (!ccid->has_pinpad) */ -/* { */ -/* fputs ("verifying that CHV1 is 123456....\n", stderr); */ -/* { */ -/* static unsigned char apdu[] = {0, 0x20, 0, 0x81, */ -/* 6, '1','2','3','4','5','6'}; */ -/* rc = ccid_transceive (ccid, apdu, sizeof apdu, */ -/* result, sizeof result, &resultlen); */ -/* print_result (rc, result, resultlen); */ -/* } */ -/* } */ -/* else */ -/* { */ -/* fputs ("verifying CHV1 using the PINPad ....\n", stderr); */ -/* { */ -/* rc = ccid_secure_transceive (ccid, */ -/* result, sizeof result, &resultlen); */ -/* print_result (rc, result, resultlen); */ -/* } */ -/* } */ + if (!rc) + { + fputs ("getting OpenPGP DO 0x5E ....\n", stderr); + { + static unsigned char apdu[] = { 0, 0xCA, 0, 0x5E, 254 }; + rc = ccid_transceive (ccid, apdu, sizeof apdu, + result, sizeof result, &resultlen); + print_result (rc, result, resultlen); + } + } ccid_close_reader (ccid); diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index cbadb40c1..9cb23253b 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -86,6 +86,11 @@ int ccid_slot_status (ccid_driver_t handle, int *statusbits); int ccid_transceive (ccid_driver_t handle, const unsigned char *apdu, size_t apdulen, unsigned char *resp, size_t maxresplen, size_t *nresp); +int ccid_transceive_secure (ccid_driver_t handle, + const unsigned char *apdu, size_t apdulen, + int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen, + unsigned char *resp, size_t maxresplen, size_t *nresp); -- cgit v1.2.3 From 6cb8f7ad4d19f7edf53d278b983d2b8c239c6575 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Fri, 8 Oct 2004 11:10:47 +0000 Subject: 2004-10-08 Moritz Schulte <moritz@g10code.com> * certchain.c (gpgsm_validate_chain): Do not use keydb_new() in case the no_chain_validation-return-short-cut is used (fixes memory leak). --- sm/ChangeLog | 6 ++++++ sm/certchain.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index feef043ef..928611eb8 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-10-08 Moritz Schulte <moritz@g10code.com> + + * certchain.c (gpgsm_validate_chain): Do not use keydb_new() in + case the no_chain_validation-return-short-cut is used (fixes + memory leak). + 2004-10-04 Werner Koch <wk@g10code.com> * misc.c (setup_pinentry_env): Try hard to set a default for GPG_TTY. diff --git a/sm/certchain.c b/sm/certchain.c index ad30a36e1..c51327e0d 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -534,7 +534,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, int rc = 0, depth = 0, maxdepth; char *issuer = NULL; char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); + KEYDB_HANDLE kh = NULL; ksba_cert_t subject_cert = NULL, issuer_cert = NULL; ksba_isotime_t current_time; ksba_isotime_t exptime; @@ -555,7 +555,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, log_info ("WARNING: bypassing certificate chain validation\n"); return 0; } - + + kh = keydb_new (0); if (!kh) { log_error (_("failed to allocated keyDB handle\n")); -- cgit v1.2.3 From e1f3dc1c77fe155b05f106c1711bce1e5b62c9b6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 14 Oct 2004 09:12:36 +0000 Subject: Added ID keywords because these files are often used in other packages. --- scd/apdu.c | 2 ++ scd/apdu.h | 2 ++ scd/app-common.h | 2 ++ scd/app-openpgp.c | 2 ++ scd/ccid-driver.c | 2 ++ scd/ccid-driver.h | 2 ++ scd/iso7816.c | 13 +++++++++++++ scd/iso7816.h | 4 ++++ 8 files changed, 29 insertions(+) diff --git a/scd/apdu.c b/scd/apdu.c index fceb4f396..0d9ef3d0c 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -16,6 +16,8 @@ * 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 + * + * $Id$ */ #include <config.h> diff --git a/scd/apdu.h b/scd/apdu.h index f31e42e3d..e0f50b72b 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -16,6 +16,8 @@ * 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 + * + * $Id$ */ #ifndef APDU_H diff --git a/scd/app-common.h b/scd/app-common.h index c15f174bf..f54f6da92 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -16,6 +16,8 @@ * 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 + * + * $Id$ */ #ifndef GNUPG_SCD_APP_COMMON_H diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 6f9837c90..86c907d1d 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -16,6 +16,8 @@ * 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 + * + * $Id$ */ #include <config.h> diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 287a8d87d..0a876f0bc 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -51,6 +51,8 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ */ diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 9cb23253b..82feed5c9 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -50,6 +50,8 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ */ #ifndef CCID_DRIVER_H diff --git a/scd/iso7816.c b/scd/iso7816.c index cbb314eb2..4861466c1 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -16,6 +16,8 @@ * 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 + * + * $Id$ */ #include <config.h> @@ -103,6 +105,17 @@ map_sw (int sw) return gpg_error (ec); } +/* Map a status word from the APDU layer to a gpg-error code. */ +gpg_error_t +iso7816_map_sw (int sw) +{ + /* All APDU functions should return 0x9000 on success but for + historical reasons of the implementation some return 0 to + indicate success. We allow for that here. */ + return sw? map_sw (sw) : 0; +} + + /* This function is specialized version of the SELECT FILE command. SLOT is the card and reader as created for example by apdu_open_reader (), AID is a buffer of size AIDLEN holding the diff --git a/scd/iso7816.h b/scd/iso7816.h index 8f2b150e6..b9ba1800b 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -16,6 +16,8 @@ * 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 + * + * $Id$ */ #ifndef ISO7816_H @@ -25,6 +27,8 @@ #include "cardglue.h" #endif +gpg_error_t iso7816_map_sw (int sw); + gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen); gpg_error_t iso7816_select_file (int slot, int tag, int is_dir, -- cgit v1.2.3 From 2c31e2f8536487416ea6d5f4fda9e22361086bae Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 14 Oct 2004 13:22:03 +0000 Subject: (parse_login_data): New. (app_select_openpgp): Call it. (do_setattr): Reparse it after change. --- scd/ChangeLog | 6 +++ scd/app-openpgp.c | 135 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 112 insertions(+), 29 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 60311e705..7fbc524b3 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2004-10-14 Werner Koch <wk@g10code.com> + + * app-openpgp.c (parse_login_data): New. + (app_select_openpgp): Call it. + (do_setattr): Reparse it after change. + 2004-10-06 Werner Koch <wk@g10code.de> * ccid-driver.c (ccid_open_reader): Store the vendor ID. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 86c907d1d..d6cbe88a6 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -101,6 +101,11 @@ struct app_local_s { unsigned int change_force_chv:1; unsigned int private_dos:1; } extcap; + struct + { + unsigned int no_sync:1; /* Do not sync CHV1 and CHV2 */ + unsigned int def_chv2:1; /* Use 123456 for CHV2. */ + } flags; }; @@ -411,6 +416,75 @@ count_bits (const unsigned char *a, size_t len) return n; } +/* GnuPG makes special use of the login-data DO, this fucntion parses + the login data to store the flags for later use. It may be called + at any time and should be called after changing the login-data DO. + + Everything up to a LF is considered a mailbox or account name. If + the first LF is follewed by DC4 (0x14) control sequence are + expected up to the next LF. Control sequences are separated by FS + (0x28) and consist of key=value pairs. There is one key defined: + + F=<flags> + + Were FLAGS is a plain hexadecimal number representing flag values. + The lsb is here the rightmost bit. Defined flags bits are: + + Bit 0 = CHV1 and CHV2 are not syncronized + Bit 1 = CHV2 has been been set to the default PIN of "123456" + (this implies that bit 0 is also set). + +*/ +static void +parse_login_data (app_t app) +{ + unsigned char *buffer, *p; + size_t buflen, len; + void *relptr; + + /* Set defaults. */ + app->app_local->flags.no_sync = 0; + app->app_local->flags.def_chv2 = 0; + + /* Read the DO. */ + relptr = get_one_do (app, 0x005E, &buffer, &buflen); + if (!relptr) + return; /* Ooops. */ + for (; buflen; buflen--, buffer++) + if (*buffer == '\n') + break; + if (buflen < 2 || buffer[1] != '\x14') + return; /* No control sequences. */ + buflen--; + buffer++; + do + { + buflen--; + buffer++; + if (buflen > 1 && *buffer == 'F' && buffer[1] == '=') + { + /* Flags control sequence found. */ + int lastdig = 0; + + /* For now we are only interested in the last digit, so skip + any leading digits but bail out on invalid characters. */ + for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--) + lastdig = xtoi_1 (p); + if (len && !(*p == '\n' || *p == '\x18')) + goto next; /* Invalid characters in field. */ + app->app_local->flags.no_sync = !!(lastdig & 1); + app->app_local->flags.def_chv2 = (lastdig & 3) == 3; + } + next: + for (; buflen && *buffer != '\x18'; buflen--, buffer++) + if (*buffer == '\n') + buflen = 1; + } + while (buflen); + + xfree (relptr); +} + /* Note, that FPR must be at least 20 bytes. */ static int store_fpr (int slot, int keynumber, u32 timestamp, @@ -479,7 +553,7 @@ store_fpr (int slot, int keynumber, u32 timestamp, static void -send_fpr_if_not_null (CTRL ctrl, const char *keyword, +send_fpr_if_not_null (ctrl_t ctrl, const char *keyword, int number, const unsigned char *fpr) { int i; @@ -502,7 +576,7 @@ send_fpr_if_not_null (CTRL ctrl, const char *keyword, } static void -send_key_data (CTRL ctrl, const char *name, +send_key_data (ctrl_t ctrl, const char *name, const unsigned char *a, size_t alen) { char *p, *buf = xmalloc (alen*2+1); @@ -520,7 +594,7 @@ send_key_data (CTRL ctrl, const char *name, /* Implement the GETATTR command. This is similar to the LEARN command but returns just one value via the status interface. */ static int -do_getattr (APP app, CTRL ctrl, const char *name) +do_getattr (app_t app, ctrl_t ctrl, const char *name) { static struct { const char *name; @@ -622,7 +696,7 @@ do_getattr (APP app, CTRL ctrl, const char *name) static int -do_learn_status (APP app, CTRL ctrl) +do_learn_status (app_t app, ctrl_t ctrl) { do_getattr (app, ctrl, "EXTCAP"); do_getattr (app, ctrl, "DISP-NAME"); @@ -661,7 +735,7 @@ verify_chv2 (app_t app, if (strlen (pinvalue) < 6) { - log_error (_("prassphrase (CHV%d) is too short;" + log_error (_("PIN for CHV%d is too short;" " minimum length is %d\n"), 2, 6); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); @@ -698,7 +772,7 @@ verify_chv2 (app_t app, /* Verify CHV3 if required. */ static int -verify_chv3 (APP app, +verify_chv3 (app_t app, int (*pincb)(void*, const char *, char **), void *pincb_arg) { @@ -780,7 +854,7 @@ verify_chv3 (APP app, /* Handle the SETATTR operation. All arguments are already basically checked. */ static int -do_setattr (APP app, const char *name, +do_setattr (app_t app, const char *name, int (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen) @@ -793,7 +867,7 @@ do_setattr (APP app, const char *name, int special; } table[] = { { "DISP-NAME", 0x005B }, - { "LOGIN-DATA", 0x005E }, + { "LOGIN-DATA", 0x005E, 2 }, { "DISP-LANG", 0x5F2D }, { "DISP-SEX", 0x5F35 }, { "PUBKEY-URL", 0x5F50 }, @@ -824,6 +898,8 @@ do_setattr (APP app, const char *name, if (table[idx].special == 1) app->force_chv1 = (valuelen && *value == 0); + else if (table[idx].special == 2) + parse_login_data (app); return rc; } @@ -831,7 +907,7 @@ do_setattr (APP app, const char *name, /* Handle the PASSWD command. */ static int -do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, +do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, int (*pincb)(void*, const char *, char **), void *pincb_arg) { @@ -918,7 +994,7 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, /* Handle the GENKEY command. */ static int -do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, +do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, int (*pincb)(void*, const char *, char **), void *pincb_arg) { @@ -1060,7 +1136,7 @@ convert_sig_counter_value (const unsigned char *value, size_t valuelen) } static unsigned long -get_sig_counter (APP app) +get_sig_counter (app_t app) { void *relptr; unsigned char *value; @@ -1076,7 +1152,7 @@ get_sig_counter (APP app) } static int -compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr) +compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr) { const unsigned char *fpr; unsigned char *buffer; @@ -1116,7 +1192,7 @@ compare_fingerprint (APP app, int keyno, unsigned char *sha1fpr) known to gpg was not updated. If there is no fingerprint we assume that this is okay. */ static int -check_against_given_fingerprint (APP app, const char *fpr, int keyno) +check_against_given_fingerprint (app_t app, const char *fpr, int keyno) { unsigned char tmp[20]; const char *s; @@ -1147,7 +1223,7 @@ check_against_given_fingerprint (APP app, const char *fpr, int keyno) not match the one required for the requested action (e.g. the serial number does not match). */ static int -do_sign (APP app, const char *keyidstr, int hashalgo, +do_sign (app_t app, const char *keyidstr, int hashalgo, int (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, @@ -1222,20 +1298,20 @@ do_sign (APP app, const char *keyidstr, int hashalgo, { char *prompt; - if (asprintf (&prompt, "PIN [sigs done: %lu]", sigcount) < 0) + if (asprintf (&prompt, _("PIN [sigs done: %lu]"), sigcount) < 0) return gpg_error_from_errno (errno); rc = pincb (pincb_arg, prompt, &pinvalue); free (prompt); } if (rc) { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc)); return rc; } if (strlen (pinvalue) < 6) { - log_error (_("prassphrase (CHV%d) is too short;" + log_error (_("PIN for CHV%d is too short;" " minimum length is %d\n"), 1, 6); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); @@ -1282,7 +1358,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo, not match the one required for the requested action (e.g. the serial number does not match). */ static int -do_auth (APP app, const char *keyidstr, +do_auth (app_t app, const char *keyidstr, int (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, @@ -1341,7 +1417,7 @@ do_auth (APP app, const char *keyidstr, static int -do_decipher (APP app, const char *keyidstr, +do_decipher (app_t app, const char *keyidstr, int (pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, @@ -1403,7 +1479,7 @@ do_decipher (APP app, const char *keyidstr, dangerous CHV3. KEYIDSTR is the usual card's serial number; an optional fingerprint part will be ignored. */ static int -do_check_pin (APP app, const char *keyidstr, +do_check_pin (app_t app, const char *keyidstr, int (pincb)(void*, const char *, char **), void *pincb_arg) { @@ -1450,7 +1526,7 @@ do_check_pin (APP app, const char *keyidstr, /* Select the OpenPGP application on the card in SLOT. This function must be used before any other OpenPGP application functions. */ int -app_select_openpgp (APP app) +app_select_openpgp (app_t app) { static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 }; int slot = app->slot; @@ -1503,8 +1579,8 @@ app_select_openpgp (APP app) relptr = get_one_do (app, 0x00C4, &buffer, &buflen); if (!relptr) { - log_error (_("can't access CHV Status Bytes " - "- invalid OpenPGP card?\n")); + log_error (_("can't access %s - invalid OpenPGP card?\n"), + "CHV Status Bytes"); goto leave; } app->force_chv1 = (buflen && *buffer == 0); @@ -1513,8 +1589,8 @@ app_select_openpgp (APP app) relptr = get_one_do (app, 0x00C0, &buffer, &buflen); if (!relptr) { - log_error (_("can't access Extended Capability Flags - " - "invalid OpenPGP card?\n")); + log_error (_("can't access %s - invalid OpenPGP card?\n"), + "Extended Capability Flags" ); goto leave; } if (buflen) @@ -1531,6 +1607,7 @@ app_select_openpgp (APP app) if (app->card_version <= 0x0100 && manufacturer == 1) app->app_local->extcap.change_force_chv = 1; + parse_login_data (app); if (opt.verbose > 1) dump_all_do (slot); @@ -1562,7 +1639,7 @@ leave: buffers or NULL if the data object is not available. All returned values are sanitized. */ int -app_openpgp_cardinfo (APP app, +app_openpgp_cardinfo (app_t app, char **serialno, char **disp_name, char **pubkey_url, @@ -1644,7 +1721,7 @@ app_openpgp_cardinfo (APP app, /* This function is currently only used by the sc-copykeys program to - store a key on the smartcard. APP ist the application handle, + store a key on the smartcard. app_t ist the application handle, KEYNO is the number of the key and PINCB, PINCB_ARG are used to ask for the SO PIN. TEMPLATE and TEMPLATE_LEN describe a buffer with the key template to store. CREATED_AT is the timestamp used to @@ -1652,7 +1729,7 @@ app_openpgp_cardinfo (APP app, RSA public exponent. This function silently overwrites an existing key.*/ int -app_openpgp_storekey (APP app, int keyno, +app_openpgp_storekey (app_t app, int keyno, unsigned char *template, size_t template_len, time_t created_at, const unsigned char *m, size_t mlen, @@ -1697,7 +1774,7 @@ app_openpgp_storekey (APP app, int keyno, /* Utility function for external tools: Read the public RSA key at KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */ int -app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, +app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen, unsigned char **e, size_t *elen) { int rc; -- cgit v1.2.3 From 837c74f7e4a3d01a230095053919e29026ca01e3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 15 Oct 2004 16:10:50 +0000 Subject: Fixed copyright years --- NEWS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 88baf21d1..595684dc3 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ Noteworthy changes in version 1.9.12 ------------------------------------------------- + Noteworthy changes in version 1.9.11 (2004-10-01) ------------------------------------------------- @@ -186,7 +187,7 @@ Noteworthy changes in version 1.9.0 (2003-08-05) development branch. - Copyright 2002, 2003 Free Software Foundation, Inc. + Copyright 2002, 2003, 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 -- cgit v1.2.3 From d33703e5fe46068ddfe7b04c44ec2e45f1f79ee3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 20 Oct 2004 08:54:45 +0000 Subject: * sc-investigate: Removed. * Makefile.am (sc_investigate): Removed. * pcsc-wrapper.c (load_pcsc_driver): Load get_status_change func. (handle_open): Succeed even without a present card. (handle_status, handle_reset): New. * apdu.c (apdu_open_reader): Load pcsc_get_status_change fucntion. (pcsc_get_status): Implemented. (reset_pcsc_reader): Implemented. (open_pcsc_reader): Succeed even with no card inserted. (open_ccid_reader): Set LAST_STATUS. * iso7816.c (iso7816_select_application): Always use 0 for P1. --- NEWS | 4 + README | 2 +- doc/ChangeLog | 5 + doc/gpg-agent.texi | 6 +- doc/scdaemon.texi | 3 +- scd/ChangeLog | 21 ++ scd/Makefile.am | 18 +- scd/apdu.c | 488 ++++++++++++++++++++++++++++--- scd/ccid-driver.c | 2 + scd/iso7816.c | 9 +- scd/pcsc-wrapper.c | 274 ++++++++++++++--- scd/sc-investigate.c | 812 --------------------------------------------------- 12 files changed, 727 insertions(+), 917 deletions(-) delete mode 100644 scd/sc-investigate.c diff --git a/NEWS b/NEWS index 595684dc3..9ba9ddac9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.9.12 ------------------------------------------------- + * [scdaemon] Partly rewrote the PC/SC code. + + * Removed the sc-investigate tool. It is now in the separate + gscutils package. Noteworthy changes in version 1.9.11 (2004-10-01) diff --git a/README b/README index c08c16af1..c14534e93 100644 --- a/README +++ b/README @@ -472,7 +472,7 @@ HOW TO EXPORT A PRIVATE KEY There is also limited support to export a private key in PKCS-12 format. However there is no MAC applied. - gpgsm --export-secret-key-p12 userIDey >foo.p12 + gpgsm --export-secret-key-p12 userID >foo.p12 SMARTCARD INTRO diff --git a/doc/ChangeLog b/doc/ChangeLog index c8e955ef2..c5ff57691 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2004-10-05 Werner Koch <wk@g10code.com> + + * gpg-agent.texi (Invoking GPG-AGENT): Tell that GPG_TTY needs to + be set in all cases. + 2004-09-30 Werner Koch <wk@g10code.com> * gpg.texi: New. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 26b5634cc..f361cbf6b 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -43,10 +43,8 @@ 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: +You should aleays add the following lines to your @code{.bashrc} or +whatever initialization file is used for all shell invocations: @smallexample GPG_TTY=`tty` diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 42dedb6b4..872000175 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -170,7 +170,8 @@ 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}. +is @code{libtowitoko.so}. Note that the use of this interface is +deprecated; it may be removed in future releases. @item --allow-admin diff --git a/scd/ChangeLog b/scd/ChangeLog index 7fbc524b3..eba39c731 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,24 @@ +2004-10-20 Werner Koch <wk@g10code.com> + + * sc-investigate: Removed. + * Makefile.am (sc_investigate): Removed. + + * pcsc-wrapper.c (load_pcsc_driver): Load get_status_change func. + (handle_open): Succeed even without a present card. + (handle_status, handle_reset): New. + + * apdu.c (apdu_open_reader): Load pcsc_get_status_change fucntion. + (pcsc_get_status): Implemented. + (reset_pcsc_reader): Implemented. + (open_pcsc_reader): Succeed even with no card inserted. + (open_ccid_reader): Set LAST_STATUS. + + * iso7816.c (iso7816_select_application): Always use 0 for P1. + +2004-10-18 Werner Koch <wk@g10code.com> + + * ccid-driver.c (ccid_get_atr): Reset T=1 state info. + 2004-10-14 Werner Koch <wk@g10code.com> * app-openpgp.c (parse_login_data): New. diff --git a/scd/Makefile.am b/scd/Makefile.am index d1d669a1a..0d83271e0 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -18,7 +18,7 @@ ## Process this file with automake to produce Makefile.in -bin_PROGRAMS = scdaemon sc-investigate sc-copykeys +bin_PROGRAMS = scdaemon sc-copykeys pkglib_PROGRAMS = pcsc-wrapper AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common @@ -56,22 +56,6 @@ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @LIBINTL@ \ @DL_LIBS@ -sc_investigate_SOURCES = \ - sc-investigate.c scdaemon.h \ - apdu.c apdu.h \ - ccid-driver.c ccid-driver.h \ - iso7816.c iso7816.h \ - tlv.c tlv.h \ - atr.c atr.h \ - app.c app-common.h app-help.c $(card_apps) - -sc_investigate_LDADD = \ - ../jnlib/libjnlib.a ../common/libcommon.a \ - $(LIBGCRYPT_LIBS) $(pth_libs) \ - $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ - @LIBINTL@ -lgpg-error @DL_LIBS@ - - sc_copykeys_SOURCES = \ sc-copykeys.c scdaemon.h \ apdu.c apdu.h \ diff --git a/scd/apdu.c b/scd/apdu.c index 0d9ef3d0c..f4b32d141 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -125,6 +125,8 @@ struct reader_table_s { rapdu_t handle; } rapdu; #endif /*USE_G10CODE_RAPDU*/ + char *rdrname; /* Name of the connected reader or NULL if unknown. */ + int last_status; int status; unsigned char atr[33]; size_t atrlen; /* A zero length indicates that the ATR has @@ -169,13 +171,47 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn); #define PCSC_UNPOWER_CARD 2 #define PCSC_EJECT_CARD 3 -struct pcsc_io_request_s { +#define PCSC_UNKNOWN 0x0001 +#define PCSC_ABSENT 0x0002 /* Card is absent. */ +#define PCSC_PRESENT 0x0004 /* Card is present. */ +#define PCSC_SWALLOWED 0x0008 /* Card is present and electrical connected. */ +#define PCSC_POWERED 0x0010 /* Card is powered. */ +#define PCSC_NEGOTIABLE 0x0020 /* Card is awaiting PTS. */ +#define PCSC_SPECIFIC 0x0040 /* Card is ready for use. */ + +#define PCSC_STATE_UNAWARE 0x0000 /* Want status. */ +#define PCSC_STATE_IGNORE 0x0001 /* Ignore this reader. */ +#define PCSC_STATE_CHANGED 0x0002 /* State has changed. */ +#define PCSC_STATE_UNKNOWN 0x0004 /* Reader unknown. */ +#define PCSC_STATE_UNAVAILABLE 0x0008 /* Status unavailable. */ +#define PCSC_STATE_EMPTY 0x0010 /* Card removed. */ +#define PCSC_STATE_PRESENT 0x0020 /* Card inserted. */ +#define PCSC_STATE_ATRMATCH 0x0040 /* ATR matches card. */ +#define PCSC_STATE_EXCLUSIVE 0x0080 /* Exclusive Mode. */ +#define PCSC_STATE_INUSE 0x0100 /* Shared mode. */ +#define PCSC_STATE_MUTE 0x0200 /* Unresponsive card. */ + + +struct pcsc_io_request_s +{ unsigned long protocol; unsigned long pci_len; }; typedef struct pcsc_io_request_s *pcsc_io_request_t; +struct pcsc_readerstate_s +{ + const char *reader; + void *user_data; + unsigned long current_state; + unsigned long event_state; + unsigned long atrlen; + unsigned char atr[33]; +}; + +typedef struct pcsc_readerstate_s *pcsc_readerstate_t; + long (* DLSTDCALL pcsc_establish_context) (unsigned long scope, const void *reserved1, const void *reserved2, @@ -184,12 +220,21 @@ long (* DLSTDCALL pcsc_release_context) (unsigned long context); long (* DLSTDCALL pcsc_list_readers) (unsigned long context, const char *groups, char *readers, unsigned long*readerslen); +long (* DLSTDCALL pcsc_get_status_change) (unsigned long context, + unsigned long timeout, + pcsc_readerstate_t readerstates, + unsigned long nreaderstates); long (* DLSTDCALL pcsc_connect) (unsigned long context, const char *reader, unsigned long share_mode, unsigned long preferred_protocols, unsigned long *r_card, unsigned long *r_active_protocol); +long (* DLSTDCALL pcsc_reconnect) (unsigned long card, + unsigned long share_mode, + unsigned long preferred_protocols, + unsigned long initialization, + unsigned long *r_active_protocol); long (* DLSTDCALL pcsc_disconnect) (unsigned long card, unsigned long disposition); long (* DLSTDCALL pcsc_status) (unsigned long card, @@ -211,7 +256,6 @@ long (* DLSTDCALL pcsc_set_timeout) (unsigned long context, - /* Helper @@ -254,11 +298,13 @@ new_reader_slot (void) reader_table[reader].dump_status_reader = NULL; reader_table[reader].used = 1; + reader_table[reader].last_status = 0; #ifdef NEED_PCSC_WRAPPER reader_table[reader].pcsc.req_fd = -1; reader_table[reader].pcsc.rsp_fd = -1; reader_table[reader].pcsc.pid = (pid_t)(-1); #endif + return reader; } @@ -662,18 +708,293 @@ dump_pcsc_reader_status (int slot) } - static int -pcsc_get_status (int slot, unsigned int *status) +reset_pcsc_reader (int slot) { - *status = 1|2|4; /* FIXME!!!! */ +#ifdef NEED_PCSC_WRAPPER + long err; + reader_table_t slotp; + size_t len; + int i, n; + unsigned char msgbuf[9]; + + slotp = reader_table + slot; + + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 + || slotp->pcsc.pid == (pid_t)(-1) ) + { + log_error ("pcsc_get_status: pcsc-wrapper not running\n"); + return SW_HOST_CARD_IO_ERROR; + } + + msgbuf[0] = 0x05; /* RESET command. */ + len = 0; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) ) + { + log_error ("error sending PC/SC RESET request: %s\n", + strerror (errno)); + goto command_failed; + } + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC RESET response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + if (len > DIM (slotp->atr)) + { + log_error ("PC/SC returned a too large ATR (len=%x)\n", len); + goto command_failed; + } + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + { + log_error ("PC/SC RESET failed: %s\n", pcsc_error_string (err)); + goto command_failed; + } + + /* The open fucntion may return a zero for the ATR length to + indicate that no card is present. */ + n = len; + if (n) + { + if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n) + { + log_error ("error receiving PC/SC RESET response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + } + slotp->atrlen = len; + + return 0; + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return -1; + +#else /* !NEED_PCSC_WRAPPER */ + long err; + char reader[250]; + unsigned long nreader, atrlen; + unsigned long card_state, card_protocol; + + if (reader_table[slot].pcsc.card) + { + err = pcsc_disconnect (reader_table[slot].pcsc.card, PCSC_LEAVE_CARD); + if (err) + { + log_error ("pcsc_disconnect failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return SW_HOST_CARD_IO_ERROR; + } + reader_table[slot].pcsc.card = 0; + } + + err = pcsc_connect (reader_table[slot].pcsc.context, + reader_table[slot].rdrname, + PCSC_SHARE_EXCLUSIVE, + PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, + &reader_table[slot].pcsc.card, + &reader_table[slot].pcsc.protocol); + if (err) + { + log_error ("pcsc_connect failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + reader_table[slot].pcsc.card = 0; + return SW_HOST_CARD_IO_ERROR; + } + + + atrlen = 33; + nreader = sizeof reader - 1; + err = pcsc_status (reader_table[slot].pcsc.card, + reader, &nreader, + &card_state, &card_protocol, + reader_table[slot].atr, &atrlen); + if (err) + { + log_error ("pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + reader_table[slot].atrlen = 0; + return SW_HOST_CARD_IO_ERROR; + } + if (atrlen >= DIM (reader_table[0].atr)) + log_bug ("ATR returned by pcsc_status is too large\n"); + reader_table[slot].atrlen = atrlen; + return 0; +#endif /* !NEED_PCSC_WRAPPER */ } + static int -reset_pcsc_reader (int slot) +pcsc_get_status (int slot, unsigned int *status) { - return SW_HOST_NOT_SUPPORTED; +#ifdef NEED_PCSC_WRAPPER + long err; + reader_table_t slotp; + size_t len, full_len; + int i, n; + unsigned char msgbuf[9]; + unsigned char buffer[12]; + + slotp = reader_table + slot; + + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 + || slotp->pcsc.pid == (pid_t)(-1) ) + { + log_error ("pcsc_get_status: pcsc-wrapper not running\n"); + return SW_HOST_CARD_IO_ERROR; + } + + msgbuf[0] = 0x04; /* STATUS command. */ + len = 0; + msgbuf[1] = (len >> 24); + msgbuf[2] = (len >> 16); + msgbuf[3] = (len >> 8); + msgbuf[4] = (len ); + if ( writen (slotp->pcsc.req_fd, msgbuf, 5) ) + { + log_error ("error sending PC/SC STATUS request: %s\n", + strerror (errno)); + goto command_failed; + } + + /* Read the response. */ + if ((i=readn (slotp->pcsc.rsp_fd, msgbuf, 9, &len)) || len != 9) + { + log_error ("error receiving PC/SC STATUS response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4]; + if (msgbuf[0] != 0x81 || len < 4) + { + log_error ("invalid response header from PC/SC received\n"); + goto command_failed; + } + len -= 4; /* Already read the error code. */ + err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; + if (err) + { + log_error ("pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return SW_HOST_CARD_IO_ERROR; + } + + full_len = len; + + n = 8 < len ? 8 : len; + if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != 8) + { + log_error ("error receiving PC/SC STATUS response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + + full_len -= len; + /* Newer versions of the wrapper might send more status bytes. + Read them. */ + while (full_len) + { + unsigned char dummybuf[128]; + + n = full_len < DIM (dummybuf) ? full_len : DIM (dummybuf); + if ((i=readn (slotp->pcsc.rsp_fd, dummybuf, n, &len)) || len != n) + { + log_error ("error receiving PC/SC TRANSMIT response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + full_len -= n; + } + + /* We are lucky: The wrapper already returns the data in the + required format. */ + *status = buffer[3]; + + return 0; + + command_failed: + close (slotp->pcsc.req_fd); + close (slotp->pcsc.rsp_fd); + slotp->pcsc.req_fd = -1; + slotp->pcsc.rsp_fd = -1; + kill (slotp->pcsc.pid, SIGTERM); + slotp->pcsc.pid = (pid_t)(-1); + slotp->used = 0; + return -1; + +#else /*!NEED_PCSC_WRAPPER*/ + + long err; + struct pcsc_readerstate_s rdrstates[1]; + + memset (rdrstates, 0, sizeof *rdrstates); + rdrstates[0].reader = reader_table[slot].rdrname; + rdrstates[0].current_state = PCSC_STATE_UNAWARE; + err = pcsc_get_status_change (reader_table[slot].pcsc.context, + 0, + rdrstates, 1); + if (err == 0x8010000a) /* Timeout. */ + err = 0; + if (err) + { + log_error ("pcsc_get_status_change failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + return SW_HOST_CARD_IO_ERROR; + } + + + /* log_debug */ + /* ("pcsc_get_status_change: %s%s%s%s%s%s%s%s%s%s\n", */ + /* (rdrstates[0].event_state & PCSC_STATE_IGNORE)? " ignore":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_CHANGED)? " changed":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_UNKNOWN)? " unknown":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_UNAVAILABLE)?" unavail":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_EMPTY)? " empty":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_PRESENT)? " present":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_ATRMATCH)? " atr":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_EXCLUSIVE)? " excl":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_INUSE)? " unuse":"", */ + /* (rdrstates[0].event_state & PCSC_STATE_MUTE)? " mute":"" ); */ + + *status = 0; + if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) ) + *status |= 2; + if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) ) + *status |= 4; + /* We indicate a useful card if it is not in use by another + application. This is because we only use exclusive access + mode. */ + if ( (*status & 6) == 6 + && !(rdrstates[0].event_state & PCSC_STATE_INUSE) ) + *status |= 1; + + return 0; +#endif /*!NEED_PCSC_WRAPPER*/ } @@ -889,6 +1210,8 @@ close_pcsc_reader (int slot) #else /*!NEED_PCSC_WRAPPER*/ pcsc_release_context (reader_table[slot].pcsc.context); + xfree (reader_table[slot].rdrname); + reader_table[slot].rdrname = NULL; reader_table[slot].used = 0; return 0; #endif /*!NEED_PCSC_WRAPPER*/ @@ -999,8 +1322,14 @@ open_pcsc_reader (const char *portstr) slotp->pcsc.rsp_fd = rp[0]; /* Wait for the intermediate child to terminate. */ - while ( (i=pth_waitpid (pid, NULL, 0)) == -1 && errno == EINTR) +#ifdef USE_GNU_PTH +#define WAIT pth_waitpid +#else +#define WAIT waitpid +#endif + while ( (i=WAIT (pid, NULL, 0)) == -1 && errno == EINTR) ; +#undef X /* Now send the open request. */ msgbuf[0] = 0x01; /* OPEN command. */ @@ -1041,12 +1370,23 @@ open_pcsc_reader (const char *portstr) log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err)); goto command_failed; } + + slotp->last_status = 0; + + /* The open fucntion may return a zero for the ATR length to + indicate that no card is present. */ n = len; - if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n) + if (n) { - log_error ("error receiving PC/SC OPEN response: %s\n", - i? strerror (errno) : "premature EOF"); - goto command_failed; + if ((i=readn (slotp->pcsc.rsp_fd, slotp->atr, n, &len)) || len != n) + { + log_error ("error receiving PC/SC OPEN response: %s\n", + i? strerror (errno) : "premature EOF"); + goto command_failed; + } + /* If we got to here we know that a card is present + and usable. Thus remember this. */ + slotp->last_status = (1|2|4| 0x8000); } slotp->atrlen = len; @@ -1132,41 +1472,63 @@ open_pcsc_reader (const char *portstr) p += strlen (p) + 1; } + reader_table[slot].rdrname = xtrymalloc (strlen (portstr? portstr : list)+1); + if (!reader_table[slot].rdrname) + { + log_error ("error allocating memory for reader name\n"); + pcsc_release_context (reader_table[slot].pcsc.context); + reader_table[slot].used = 0; + return -1; + } + strcpy (reader_table[slot].rdrname, portstr? portstr : list); + xfree (list); + err = pcsc_connect (reader_table[slot].pcsc.context, - portstr? portstr : list, + reader_table[slot].rdrname, PCSC_SHARE_EXCLUSIVE, PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, &reader_table[slot].pcsc.card, &reader_table[slot].pcsc.protocol); - if (err) + if (err == 0x8010000c) /* No smartcard. */ + reader_table[slot].pcsc.card = 0; + else if (err) { log_error ("pcsc_connect failed: %s (0x%lx)\n", pcsc_error_string (err), err); pcsc_release_context (reader_table[slot].pcsc.context); + xfree (reader_table[slot].rdrname); + reader_table[slot].rdrname = NULL; reader_table[slot].used = 0; xfree (list); return -1; } - - atrlen = 32; - /* (We need to pass a dummy buffer. We use LIST because it ought to - be large enough.) */ - err = pcsc_status (reader_table[slot].pcsc.card, - list, &listlen, - &card_state, &card_protocol, - reader_table[slot].atr, &atrlen); - xfree (list); - if (err) + + reader_table[slot].atrlen = 0; + reader_table[slot].last_status = 0; + if (!err) { - log_error ("pcsc_status failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - pcsc_release_context (reader_table[slot].pcsc.context); - reader_table[slot].used = 0; - return -1; + char reader[250]; + unsigned long readerlen; + + atrlen = 32; + readerlen = sizeof reader -1 ; + err = pcsc_status (reader_table[slot].pcsc.card, + reader, &readerlen, + &card_state, &card_protocol, + reader_table[slot].atr, &atrlen); + if (err) + log_error ("pcsc_status failed: %s (0x%lx) %lu\n", + pcsc_error_string (err), err, readerlen); + else + { + if (atrlen >= DIM (reader_table[0].atr)) + log_bug ("ATR returned by pcsc_status is too large\n"); + reader_table[slot].atrlen = atrlen; + /* If we got to here we know that a card is present + and usable. Thus remember this. */ + reader_table[slot].last_status = (1|2|4| 0x8000); + } } - if (atrlen >= DIM (reader_table[0].atr)) - log_bug ("ATR returned by pcsc_status is too large\n"); - reader_table[slot].atrlen = atrlen; reader_table[slot].close_reader = close_pcsc_reader; reader_table[slot].reset_reader = reset_pcsc_reader; @@ -1311,6 +1673,12 @@ open_ccid_reader (const char *portstr) slotp->atrlen = 0; err = 0; } + else + { + /* If we got to here we know that a card is present + and usable. Thus remember this. */ + reader_table[slot].last_status = (1|2|4| 0x8000); + } reader_table[slot].close_reader = close_ccid_reader; reader_table[slot].shutdown_reader = shutdown_ccid_reader; @@ -1970,11 +2338,21 @@ apdu_open_reader (const char *portstr) #ifdef _WIN32 if (!pcsc_list_readers) pcsc_list_readers = dlsym (handle, "SCardListReadersA"); +#endif + pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange"); +#ifdef _WIN32 + if (!pcsc_get_status_change) + pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA"); #endif pcsc_connect = dlsym (handle, "SCardConnect"); #ifdef _WIN32 if (!pcsc_connect) pcsc_connect = dlsym (handle, "SCardConnectA"); +#endif + pcsc_reconnect = dlsym (handle, "SCardReconnect"); +#ifdef _WIN32 + if (!pcsc_reconnect) + pcsc_reconnect = dlsym (handle, "SCardReconnectA"); #endif pcsc_disconnect = dlsym (handle, "SCardDisconnect"); pcsc_status = dlsym (handle, "SCardStatus"); @@ -1990,7 +2368,9 @@ apdu_open_reader (const char *portstr) if (!pcsc_establish_context || !pcsc_release_context || !pcsc_list_readers + || !pcsc_get_status_change || !pcsc_connect + || !pcsc_reconnect || !pcsc_disconnect || !pcsc_status || !pcsc_begin_transaction @@ -2001,11 +2381,13 @@ apdu_open_reader (const char *portstr) /* Note that set_timeout is currently not used and also not available under Windows. */ log_error ("apdu_open_reader: invalid PC/SC driver " - "(%d%d%d%d%d%d%d%d%d%d)\n", + "(%d%d%d%d%d%d%d%d%d%d%d%d)\n", !!pcsc_establish_context, !!pcsc_release_context, !!pcsc_list_readers, + !!pcsc_get_status_change, !!pcsc_connect, + !!pcsc_reconnect, !!pcsc_disconnect, !!pcsc_status, !!pcsc_begin_transaction, @@ -2048,8 +2430,12 @@ apdu_open_remote_reader (const char *portstr, readfnc, readfnc_value, writefnc, writefnc_value, closefnc, closefnc_value); +#else +#ifdef _WIN32 + errno = ENOENT; #else errno = ENOSYS; +#endif return -1; #endif } @@ -2102,9 +2488,17 @@ apdu_reset (int slot) if ((sw = lock_slot (slot))) return sw; + reader_table[slot].last_status = 0; if (reader_table[slot].reset_reader) sw = reader_table[slot].reset_reader (slot); + if (!sw) + { + /* If we got to here we know that a card is present + and usable. Thus remember this. */ + reader_table[slot].last_status = (1|2|4| 0x8000); + } + unlock_slot (slot); return sw; } @@ -2139,7 +2533,16 @@ apdu_activate (int slot) /* We don't have an ATR or a card is present though inactive: do a reset now. */ if (reader_table[slot].reset_reader) - sw = reader_table[slot].reset_reader (slot); + { + reader_table[slot].last_status = 0; + sw = reader_table[slot].reset_reader (slot); + if (!sw) + { + /* If we got to here we know that a card is present + and usable. Thus remember this. */ + reader_table[slot].last_status = (1|2|4| 0x8000); + } + } } } @@ -2201,7 +2604,22 @@ apdu_get_status (int slot, int hang, unlock_slot (slot); if (sw) - return sw; + { + reader_table[slot].last_status = 0; + return sw; + } + + /* Keep track of changes. We use one extra bit to test whether we + have checked the status at least once. */ + if ( s != (reader_table[slot].last_status & 0x07ff) + || !reader_table[slot].last_status ) + { + reader_table[slot].change_counter++; + /* Make sure that the ATR is invalid so that a reset will be by + activate. */ + reader_table[slot].atrlen = 0; + } + reader_table[slot].last_status = (s | 0x8000); if (status) *status = s; diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 0a876f0bc..01c8a9980 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1307,6 +1307,8 @@ ccid_get_atr (ccid_driver_t handle, /* Note that we ignore the error code on purpose. */ bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno); + handle->t1_ns = 0; + handle->t1_nr = 0; /* Send an S-Block with our maximun IFSD to the CCID. */ if (!handle->auto_ifsd) diff --git a/scd/iso7816.c b/scd/iso7816.c index 4861466c1..9eff9d3f7 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -126,15 +126,8 @@ iso7816_map_sw (int sw) gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen) { - static char const openpgp_aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 }; int sw; - int p1 = 0x0C; /* No FCI to be returned. */ - - if (aidlen == sizeof openpgp_aid - && !memcmp (aid, openpgp_aid, sizeof openpgp_aid)) - p1 = 0; /* The current openpgp cards don't allow 0x0c. */ - - sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, p1, aidlen, aid); + sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid); return map_sw (sw); } diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c index 4f47ee95c..93e78fdfe 100644 --- a/scd/pcsc-wrapper.c +++ b/scd/pcsc-wrapper.c @@ -86,6 +86,26 @@ static int verbose; #define PCSC_UNPOWER_CARD 2 #define PCSC_EJECT_CARD 3 +#define PCSC_UNKNOWN 0x0001 +#define PCSC_ABSENT 0x0002 /* Card is absent. */ +#define PCSC_PRESENT 0x0004 /* Card is present. */ +#define PCSC_SWALLOWED 0x0008 /* Card is present and electrical connected. */ +#define PCSC_POWERED 0x0010 /* Card is powered. */ +#define PCSC_NEGOTIABLE 0x0020 /* Card is awaiting PTS. */ +#define PCSC_SPECIFIC 0x0040 /* Card is ready for use. */ + +#define PCSC_STATE_UNAWARE 0x0000 /* Want status. */ +#define PCSC_STATE_IGNORE 0x0001 /* Ignore this reader. */ +#define PCSC_STATE_CHANGED 0x0002 /* State has changed. */ +#define PCSC_STATE_UNKNOWN 0x0004 /* Reader unknown. */ +#define PCSC_STATE_UNAVAILABLE 0x0008 /* Status unavailable. */ +#define PCSC_STATE_EMPTY 0x0010 /* Card removed. */ +#define PCSC_STATE_PRESENT 0x0020 /* Card inserted. */ +#define PCSC_STATE_ATRMATCH 0x0040 /* ATR matches card. */ +#define PCSC_STATE_EXCLUSIVE 0x0080 /* Exclusive Mode. */ +#define PCSC_STATE_INUSE 0x0100 /* Shared mode. */ +#define PCSC_STATE_MUTE 0x0200 /* Unresponsive card. */ + struct pcsc_io_request_s { unsigned long protocol; unsigned long pci_len; @@ -93,12 +113,25 @@ struct pcsc_io_request_s { typedef struct pcsc_io_request_s *pcsc_io_request_t; +struct pcsc_readerstate_s +{ + const char *reader; + void *user_data; + unsigned long current_state; + unsigned long event_state; + unsigned long atrlen; + unsigned char atr[33]; +}; + +typedef struct pcsc_readerstate_s *pcsc_readerstate_t; + static int driver_is_open; /* True if the PC/SC driver has been initialzied and is ready for - operations. The follwoing variables + operations. The following variables are then valid. */ static unsigned long pcsc_context; /* The current PC/CS context. */ +static char *current_rdrname; static unsigned long pcsc_card; static unsigned long pcsc_protocol; static unsigned char current_atr[33]; @@ -112,12 +145,21 @@ long (* pcsc_release_context) (unsigned long context); long (* pcsc_list_readers) (unsigned long context, const char *groups, char *readers, unsigned long*readerslen); +long (* pcsc_get_status_change) (unsigned long context, + unsigned long timeout, + pcsc_readerstate_t readerstates, + unsigned long nreaderstates); long (* pcsc_connect) (unsigned long context, const char *reader, unsigned long share_mode, unsigned long preferred_protocols, unsigned long *r_card, unsigned long *r_active_protocol); +long (* pcsc_reconnect) (unsigned long card, + unsigned long share_mode, + unsigned long preferred_protocols, + unsigned long initialization, + unsigned long *r_active_protocol); long (* pcsc_disconnect) (unsigned long card, unsigned long disposition); long (* pcsc_status) (unsigned long card, @@ -284,7 +326,9 @@ load_pcsc_driver (const char *libname) pcsc_establish_context = dlsym (handle, "SCardEstablishContext"); pcsc_release_context = dlsym (handle, "SCardReleaseContext"); pcsc_list_readers = dlsym (handle, "SCardListReaders"); + pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange"); pcsc_connect = dlsym (handle, "SCardConnect"); + pcsc_reconnect = dlsym (handle, "SCardReconnect"); pcsc_disconnect = dlsym (handle, "SCardDisconnect"); pcsc_status = dlsym (handle, "SCardStatus"); pcsc_begin_transaction = dlsym (handle, "SCardBeginTransaction"); @@ -295,7 +339,9 @@ load_pcsc_driver (const char *libname) if (!pcsc_establish_context || !pcsc_release_context || !pcsc_list_readers + || !pcsc_get_status_change || !pcsc_connect + || !pcsc_reconnect || !pcsc_disconnect || !pcsc_status || !pcsc_begin_transaction @@ -307,11 +353,13 @@ load_pcsc_driver (const char *libname) available under Windows. */ fprintf (stderr, "apdu_open_reader: invalid PC/SC driver " - "(%d%d%d%d%d%d%d%d%d%d)\n", + "(%d%d%d%d%d%d%d%d%d%d%d%d)\n", !!pcsc_establish_context, !!pcsc_release_context, !!pcsc_list_readers, + !!pcsc_get_status_change, !!pcsc_connect, + !!pcsc_reconnect, !!pcsc_disconnect, !!pcsc_status, !!pcsc_begin_transaction, @@ -327,8 +375,8 @@ load_pcsc_driver (const char *libname) /* Handle a open request. The argument is expected to be a string - with the port indentification. ARGBUF is always guaranteed to be - terminted by a 0 which is not counted in ARGLEN. We may modifiy + with the port identification. ARGBUF is always guaranteed to be + terminted by a 0 which is not counted in ARGLEN. We may modifiy ARGBUF. */ static void handle_open (unsigned char *argbuf, size_t arglen) @@ -350,6 +398,7 @@ handle_open (unsigned char *argbuf, size_t arglen) { fprintf (stderr, PGM ": PC/SC has already been opened\n"); request_failed (-1); + return; } err = pcsc_establish_context (PCSC_SCOPE_SYSTEM, NULL, NULL, &pcsc_context); @@ -398,45 +447,64 @@ handle_open (unsigned char *argbuf, size_t arglen) p += strlen (p) + 1; } + current_rdrname = malloc (strlen (portstr && *portstr? portstr:list)+1); + if (!current_rdrname) + { + fprintf (stderr, PGM": error allocating memory for reader name\n"); + exit (1); + } + strcpy (current_rdrname, portstr && *portstr? portstr:list); + free (list); + err = pcsc_connect (pcsc_context, - portstr && *portstr? portstr : list, + current_rdrname, PCSC_SHARE_EXCLUSIVE, PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, &pcsc_card, &pcsc_protocol); - if (err) + if (err == 0x8010000c) /* No smartcard. */ + { + pcsc_card = 0; + } + else if (err) { fprintf (stderr, PGM": pcsc_connect failed: %s (0x%lx)\n", pcsc_error_string (err), err); pcsc_release_context (pcsc_context); - free (list); + free (current_rdrname); + current_rdrname = NULL; request_failed (err); return; } - atrlen = 32; - /* (We need to pass a dummy buffer. We use LIST because it ought to - be large enough.) */ - err = pcsc_status (pcsc_card, - list, &listlen, - &card_state, &card_protocol, - atr, &atrlen); - free (list); - if (err) - { - fprintf (stderr, PGM": pcsc_status failed: %s (0x%lx)\n", - pcsc_error_string (err), err); - pcsc_release_context (pcsc_context); - request_failed (err); - return; - } - if (atrlen >= sizeof atr || atrlen >= sizeof current_atr) + current_atrlen = 0; + if (!err) { - fprintf (stderr, PGM": ATR returned by pcsc_status is too large\n"); - exit (4); + char reader[250]; + unsigned long readerlen; + + atrlen = 33; + readerlen = sizeof reader -1; + err = pcsc_status (pcsc_card, + reader, &readerlen, + &card_state, &card_protocol, + atr, &atrlen); + if (err) + fprintf (stderr, PGM": pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + else + { + if (atrlen >= sizeof atr || atrlen >= sizeof current_atr) + { + fprintf (stderr, PGM": ATR returned by pcsc_status" + " is too large\n"); + exit (4); + } + memcpy (current_atr, atr, atrlen); + current_atrlen = atrlen; + } } - memcpy (current_atr, atr, atrlen); - current_atrlen = atrlen; + driver_is_open = 1; request_succeeded (current_atr, current_atrlen); } @@ -452,8 +520,11 @@ handle_close (unsigned char *argbuf, size_t arglen) { fprintf (stderr, PGM ": PC/SC has not yet been opened\n"); request_failed (-1); + return; } + free (current_rdrname); + current_rdrname = NULL; pcsc_release_context (pcsc_context); request_succeeded (NULL, 0); @@ -461,7 +532,133 @@ handle_close (unsigned char *argbuf, size_t arglen) -/* Handle a transmit request. The argument is expected to be a bufer +/* Handle a status request. We expect no arguments. We may modifiy + ARGBUF. */ +static void +handle_status (unsigned char *argbuf, size_t arglen) +{ + long err; + struct pcsc_readerstate_s rdrstates[1]; + int status; + unsigned char buf[20]; + + if (!driver_is_open) + { + fprintf (stderr, PGM ": PC/SC has not yet been opened\n"); + request_failed (-1); + return; + } + + memset (rdrstates, 0, sizeof *rdrstates); + rdrstates[0].reader = current_rdrname; + rdrstates[0].current_state = PCSC_STATE_UNAWARE; + err = pcsc_get_status_change (pcsc_context, + 0, + rdrstates, 1); + if (err == 0x8010000a) /* Timeout. */ + err = 0; + if (err) + { + fprintf (stderr, PGM": pcsc_get_status_change failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + request_failed (err); + return; + } + + status = 0; + if ( (rdrstates[0].event_state & PCSC_STATE_PRESENT) ) + status |= 2; + if ( !(rdrstates[0].event_state & PCSC_STATE_MUTE) ) + status |= 4; + /* We indicate a useful card if it is not in use by another + application. This is because we only use exclusive access + mode. */ + if ( (status & 6) == 6 + && !(rdrstates[0].event_state & PCSC_STATE_INUSE) ) + status |= 1; + + /* First word is identical to the one used by apdu.c. */ + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = status; + /* The second word is the native PCSC state. */ + buf[4] = (rdrstates[0].event_state >> 24); + buf[5] = (rdrstates[0].event_state >> 16); + buf[6] = (rdrstates[0].event_state >> 8); + buf[7] = (rdrstates[0].event_state >> 0); + + request_succeeded (buf, 8); +} + + +/* Handle a reset request. We expect no arguments. We may modifiy + ARGBUF. */ +static void +handle_reset (unsigned char *argbuf, size_t arglen) +{ + long err; + char reader[250]; + unsigned long nreader, atrlen; + unsigned long card_state, card_protocol; + + if (!driver_is_open) + { + fprintf (stderr, PGM ": PC/SC has not yet been opened\n"); + request_failed (-1); + return; + } + + if (pcsc_card) + { + err = pcsc_disconnect (pcsc_card, PCSC_LEAVE_CARD); + if (err) + { + fprintf (stderr, PGM": pcsc_disconnect failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + request_failed (err); + return; + } + pcsc_card = 0; + } + + err = pcsc_connect (pcsc_context, + current_rdrname, + PCSC_SHARE_EXCLUSIVE, + PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, + &pcsc_card, + &pcsc_protocol); + if (err) + { + fprintf (stderr, PGM": pcsc_connect failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + pcsc_card = 0; + request_failed (err); + return; + } + + + atrlen = 33; + nreader = sizeof reader - 1; + err = pcsc_status (pcsc_card, + reader, &nreader, + &card_state, &card_protocol, + current_atr, &atrlen); + if (err) + { + fprintf (stderr, PGM": pcsc_status failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + current_atrlen = 0; + request_failed (err); + return; + } + + request_succeeded (current_atr, current_atrlen); +} + + + +/* Handle a transmit request. The argument is expected to be a buffer with the APDU. We may modifiy ARGBUF. */ static void handle_transmit (unsigned char *argbuf, size_t arglen) @@ -479,8 +676,8 @@ handle_transmit (unsigned char *argbuf, size_t arglen) { fprintf (stderr, PGM ": PC/SC has not yet been opened\n"); request_failed (-1); + return; } - if ((pcsc_protocol & PCSC_PROTOCOL_T1)) send_pci.protocol = PCSC_PROTOCOL_T1; else @@ -502,15 +699,6 @@ handle_transmit (unsigned char *argbuf, size_t arglen) - - - - - - - - - static void print_version (int with_help) { @@ -613,6 +801,14 @@ main (int argc, char **argv) handle_transmit (argbuffer, arglen); break; + case 4: + handle_status (argbuffer, arglen); + break; + + case 5: + handle_reset (argbuffer, arglen); + break; + default: fprintf (stderr, PGM ": invalid request 0x%02X\n", c); exit (1); diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c deleted file mode 100644 index 1f1920650..000000000 --- a/scd/sc-investigate.c +++ /dev/null @@ -1,812 +0,0 @@ -/* sc-investigate.c - A tool to look around on smartcards. - * 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 <ctype.h> -#include <unistd.h> -#ifdef USE_GNU_PTH -# include <pth.h> -#endif - -#ifdef HAVE_READLINE_READLINE_H -#include <readline/readline.h> -#include <readline/history.h> -#endif - -#define JNLIB_NEED_LOG_LOGV -#include "scdaemon.h" -#include <gcrypt.h> - -#include "apdu.h" /* for open_reader */ -#include "atr.h" -#include "app-common.h" -#include "iso7816.h" - -#define _(a) (a) - -#define CONTROL_D ('D' - 'A' + 1) - - -enum cmd_and_opt_values -{ - oInteractive = 'i', - oVerbose = 'v', - oQuiet = 'q', - oReaderPort = 500, - octapiDriver, - - oDebug, - oDebugAll, - - oDisableCCID, - - - oGenRandom, - -aTest }; - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, "@Options:\n " }, - - { oInteractive, "interactive", 0, "start in interactive explorer mode"}, - { oQuiet, "quiet", 0, "quiet" }, - { oVerbose, "verbose", 0, "verbose" }, - { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"}, - { octapiDriver, "ctapi-driver", 2, "|NAME|use NAME as ctAPI driver"}, - { oDisableCCID, "disable-ccid", 0, -#ifdef HAVE_LIBUSB - "do not use the internal CCID driver" -#else - "@" -#endif - }, - { oDebug, "debug" ,4|16, "set debugging flags"}, - { oDebugAll, "debug-all" ,0, "enable full debugging"}, - { oGenRandom, "gen-random", 4, "|N|generate N bytes of random"}, - {0} -}; - -#ifndef HAVE_OPENSC -#ifdef USE_GNU_PTH -/* Pth wrapper function definitions. */ -GCRY_THREAD_OPTION_PTH_IMPL; -#endif /*USE_GNU_PTH*/ -#endif /*!HAVE_OPENSC*/ - -static void interactive_shell (int slot); -static void dump_other_cards (int slot); - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "sc-investigate (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: sc-investigate [options] (-h for help)\n"); - break; - case 41: p = _("Syntax: sc-investigate [options] [args]]\n" - "Have a look at smartcards\n"); - break; - - default: p = NULL; - } - return p; -} - -/* Used by gcry for logging */ -static void -my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) -{ - /* translate the log levels */ - switch (level) - { - case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; - case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; - case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; - case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; - case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; - case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; - case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; - default: level = JNLIB_LOG_ERROR; break; - } - log_logv (level, fmt, arg_ptr); -} - - -int -main (int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - int slot, rc; - const char *reader_port = NULL; - unsigned long gen_random = 0; - int interactive = 0; - - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - log_set_prefix ("sc-investigate", 1); - - /* Try to auto set the character set. */ - set_native_charset (NULL); - - /* Libgcrypt requires us to register the threading model first. We - can't use pth at all if we are using OpenSC becuase OpenSC uses - ptreads. Note that this will also do the pth_init. */ -#ifndef HAVE_OPENSC -#ifdef USE_GNU_PTH - rc = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); - if (rc) - { - log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", - gpg_strerror (rc)); - } -#endif /*USE_GNU_PTH*/ -#endif /*!HAVE_OPENSC*/ - - /* Check that the libraries are suitable. Do it here because - the option parsing may need services of the library */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - - - gcry_set_log_handler (my_gcry_logger, NULL); - /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/ - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - while (arg_parse (&pargs, opts) ) - { - switch (pargs.r_opt) - { - case oVerbose: opt.verbose++; break; - case oQuiet: opt.quiet++; break; - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - case oReaderPort: reader_port = pargs.r.ret_str; break; - case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; - case oDisableCCID: opt.disable_ccid = 1; break; - case oGenRandom: gen_random = pargs.r.ret_ulong; break; - case oInteractive: interactive = 1; break; - default : pargs.err = 2; break; - } - } - if (log_get_errorcount(0)) - exit(2); - - if (opt.verbose < 2) - opt.verbose = 2; /* Hack to let select_openpgp print some info. */ - - if (argc) - usage (1); - - slot = apdu_open_reader (reader_port); - if (slot == -1) - exit (1); - - if (!gen_random && !opt.quiet) - { - rc = atr_dump (slot, stdout); - if (rc) - log_error ("can't dump ATR: %s\n", gpg_strerror (rc)); - } - - if (interactive) - interactive_shell (slot); - else - { - struct app_ctx_s appbuf; - - /* Fixme: We better use app.c directly. */ - memset (&appbuf, 0, sizeof appbuf); - appbuf.slot = slot; - rc = app_select_openpgp (&appbuf); - if (rc) - { - if (!opt.quiet) - log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); - memset (&appbuf, 0, sizeof appbuf); - appbuf.slot = slot; - rc = app_select_dinsig (&appbuf); - if (rc) - { - if (!opt.quiet) - log_info ("selecting dinsig failed: %s\n", gpg_strerror (rc)); - dump_other_cards (slot); - } - else - { - appbuf.initialized = 1; - log_info ("dinsig application selected\n"); - } - } - else - { - appbuf.initialized = 1; - log_info ("openpgp application selected\n"); - - if (gen_random) - { - size_t nbytes; - unsigned char *buffer; - - buffer = xmalloc (4096); - do - { - nbytes = gen_random > 4096? 4096 : gen_random; - rc = app_get_challenge (&appbuf, nbytes, buffer); - if (rc) - log_error ("app_get_challenge failed: %s\n",gpg_strerror (rc)); - else - { - if (fwrite (buffer, nbytes, 1, stdout) != 1) - log_error ("writing to stdout failed: %s\n", - strerror (errno)); - gen_random -= nbytes; - } - } - while (gen_random && !log_get_errorcount (0)); - xfree (buffer); - } - } - } - - return log_get_errorcount (0)? 2:0; -} - - - -void -send_status_info (CTRL ctrl, const char *keyword, ...) -{ - /* DUMMY */ -} - - - -/* Dump BUFFER of length NBYTES in a nicely human readable format. */ -static void -dump_buffer (const unsigned char *buffer, size_t nbytes) -{ - int i; - - while (nbytes) - { - for (i=0; i < 16 && i < nbytes; i++) - printf ("%02X%s ", buffer[i], i==8? " ":""); - for (; i < 16; i++) - printf (" %s ", i==8? " ":""); - putchar (' '); - putchar (' '); - for (i=0; i < 16 && i < nbytes; i++) - if (isprint (buffer[i])) - putchar (buffer[i]); - else - putchar ('.'); - nbytes -= i; - buffer += i; - for (; i < 16; i++) - putchar (' '); - putchar ('\n'); - } -} - - -static void -dump_or_store_buffer (const char *arg, - const unsigned char *buffer, size_t nbytes) -{ - const char *s = strchr (arg, '>'); - int append; - FILE *fp; - - if (!s) - { - dump_buffer (buffer, nbytes); - return; - } - if ((append = (*++s == '>'))) - s++; - fp = fopen (s, append? "ab":"wb"); - if (!fp) - { - log_error ("failed to create `%s': %s\n", s, strerror (errno)); - return; - } - if (nbytes && fwrite (buffer, nbytes, 1, fp) != 1) - log_error ("failed to write to `%s': %s\n", s, strerror (errno)); - if (fclose (fp)) - log_error ("failed to close `%s': %s\n", s, strerror (errno)); -} - - -/* Convert STRING into a a newly allocated buffer and return the - length of the buffer in R_LENGTH. Detect xx:xx:xx... sequence and - unhexify that one. */ -static unsigned char * -pin_to_buffer (const char *string, size_t *r_length) -{ - unsigned char *buffer = xmalloc (strlen (string)+1); - const char *s; - size_t n; - - for (s=string, n=0; *s; s += 3) - { - if (hexdigitp (s) && hexdigitp (s+1) && (s[2]==':'||!s[2])) - { - buffer[n++] = xtoi_2 (s); - if (!s[2]) - break; - } - else - { - memcpy (buffer, string, strlen (string)); - *r_length = strlen (string); - return buffer; - } - } - *r_length = n; - return buffer; -} - - -static char * -my_read_line (int use_readline, char *prompt) -{ - static char buf[256]; - -#ifdef HAVE_READLINE - if (use_readline) - { - char *line = readline (prompt); - if (line) - trim_spaces (line); - if (line && strlen (line) > 2 ) - add_history (line); - return line; - } -#endif - /* Either we don't have readline or we are not running - interactively */ -#ifndef HAVE_READLINE - printf ("%s", prompt ); -#endif - fflush(stdout); - if (!fgets(buf, sizeof(buf), stdin)) - return NULL; - if (!strlen(buf)) - return NULL; - if (buf[strlen (buf)-1] == '\n') - buf[strlen (buf)-1] = 0; - trim_spaces (buf); - return buf; -} - -/* Run a shell for interactive exploration of the card. */ -static void -interactive_shell (int slot) -{ - enum cmdids - { - cmdNOP = 0, - cmdQUIT, cmdHELP, - cmdSELECT, - cmdCHDIR, - cmdLS, - cmdAPP, - cmdREAD, - cmdREADREC, - cmdREADSHORTREC, - cmdDEBUG, - cmdVERIFY, - cmdCHANGEREF, - cmdREADPK, - - cmdINVCMD - }; - static struct - { - const char *name; - enum cmdids id; - const char *desc; - } cmds[] = { - { "quit" , cmdQUIT , "quit this menu" }, - { "q" , cmdQUIT , NULL }, - { "help" , cmdHELP , "show this help" }, - { "?" , cmdHELP , NULL }, - { "debug" , cmdDEBUG, "set debugging flags" }, - { "select" , cmdSELECT, "select file (EF)" }, - { "s" , cmdSELECT, NULL }, - { "chdir" , cmdCHDIR, "change directory (select DF)"}, - { "cd" , cmdCHDIR, NULL }, - { "ls" , cmdLS, "list directory (some cards only)"}, - { "app" , cmdAPP, "select application"}, - { "read" , cmdREAD, "read binary" }, - { "rb" , cmdREAD, NULL }, - { "readrec", cmdREADREC, "read record(s)" }, - { "rr" , cmdREADREC, NULL }, - { "rsr" , cmdREADSHORTREC, "readshortrec RECNO SHORT_EF" }, - { "verify" , cmdVERIFY, "verify CHVNO PIN" }, - { "ver" , cmdVERIFY, NULL }, - { "changeref", cmdCHANGEREF, "change reference data" }, - { "readpk", cmdREADPK, "read a public key" }, - { NULL, cmdINVCMD } - }; - enum cmdids cmd = cmdNOP; - int use_readline = isatty (fileno(stdin)); - char *line; - gpg_error_t err = 0; - unsigned char *result = NULL; - size_t resultlen; - -#ifdef HAVE_READLINE - if (use_readline) - using_history (); -#endif - - for (;;) - { - int arg_number; - const char *arg_string = ""; - const char *arg_next = ""; - char *p; - int i; - - if (err) - printf ("command failed: %s\n", gpg_strerror (err)); - err = 0; - xfree (result); - result = NULL; - - printf ("\n"); - do - { - line = my_read_line (use_readline, "cmd> "); - } - while ( line && *line == '#' ); - - arg_number = 0; - if (!line || *line == CONTROL_D) - cmd = cmdQUIT; - else if (!*line) - cmd = cmdNOP; - else { - if ((p=strchr (line,' '))) - { - char *endp; - - *p++ = 0; - trim_spaces (line); - trim_spaces (p); - arg_number = strtol (p, &endp, 0); - arg_string = p; - if (endp != p) - { - arg_next = endp; - while ( spacep (arg_next) ) - arg_next++; - } - } - - for (i=0; cmds[i].name; i++ ) - if (!ascii_strcasecmp (line, cmds[i].name )) - break; - - cmd = cmds[i].id; - } - - switch (cmd) - { - case cmdHELP: - for (i=0; cmds[i].name; i++ ) - if (cmds[i].desc) - printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); - break; - - case cmdQUIT: - goto leave; - - case cmdNOP: - break; - - case cmdDEBUG: - if (!*arg_string) - opt.debug = opt.debug? 0 : 2048; - else - opt.debug = arg_number; - break; - - case cmdSELECT: - err = iso7816_select_file (slot, arg_number, 0, NULL, NULL); - break; - - case cmdCHDIR: - err = iso7816_select_file (slot, arg_number, 1, NULL, NULL); - break; - - case cmdLS: - err = iso7816_list_directory (slot, 1, &result, &resultlen); - if (!err || gpg_err_code (err) == GPG_ERR_ENOENT) - err = iso7816_list_directory (slot, 0, &result, &resultlen); - /* FIXME: Do something with RESULT. */ - break; - - case cmdAPP: - { - app_t app; - - app = select_application (NULL, slot, *arg_string? arg_string:NULL); - if (app) - { - char *sn; - - app_get_serial_and_stamp (app, &sn, NULL); - log_info ("application `%s' ready; sn=%s\n", - app->apptype?app->apptype:"?", sn? sn:"[none]"); - release_application (app); - } - } - break; - - case cmdREAD: - err = iso7816_read_binary (slot, 0, 0, &result, &resultlen); - if (!err) - dump_or_store_buffer (arg_string, result, resultlen); - break; - - case cmdREADREC: - if (*arg_string == '*' && (!arg_string[1] || arg_string[1] == ' ')) - { - /* Fixme: Can't write to a file yet. */ - for (i=1, err=0; !err; i++) - { - xfree (result); result = NULL; - err = iso7816_read_record (slot, i, 1, 0, - &result, &resultlen); - if (!err) - dump_buffer (result, resultlen); - } - if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) - err = 0; - } - else - { - err = iso7816_read_record (slot, arg_number, 1, 0, - &result, &resultlen); - if (!err) - dump_or_store_buffer (arg_string, result, resultlen); - } - break; - - case cmdREADSHORTREC: - { - int short_ef; - - short_ef = strtol (arg_next, NULL, 0); - - if (short_ef < 1 || short_ef > 254) - printf ("error: short EF must be between 1 and 254\n"); - else - { - err = iso7816_read_record (slot, arg_number, 1, short_ef, - &result, &resultlen); - if (!err) - dump_or_store_buffer (arg_string, result, resultlen); - } - } - break; - - case cmdVERIFY: - if (arg_number < 0 || arg_number > 255 || (arg_number & 127) > 31) - printf ("error: invalid CHVNO\n"); - else - { - unsigned char *pin; - size_t pinlen; - - pin = pin_to_buffer (arg_next, &pinlen); - err = iso7816_verify (slot, arg_number, pin, pinlen); - xfree (pin); - } - break; - - case cmdCHANGEREF: - { - const char *newpin = arg_next; - - while ( *newpin && !spacep (newpin) ) - newpin++; - while ( spacep (newpin) ) - newpin++; - - if (arg_number < 0 || arg_number > 255 || (arg_number & 127) > 31) - printf ("error: invalid CHVNO\n"); - else if (!*arg_next || !*newpin || newpin == arg_next) - printf ("usage: changeref CHVNO OLDPIN NEWPIN\n"); - else - { - char *oldpin = xstrdup (arg_next); - unsigned char *oldpin_buf, *newpin_buf; - size_t oldpin_len, newpin_len; - - for (p=oldpin; *p && !spacep (p); p++ ) - ; - *p = 0; - oldpin_buf = pin_to_buffer (oldpin, &oldpin_len); - newpin_buf = pin_to_buffer (newpin, &newpin_len); - - err = iso7816_change_reference_data (slot, arg_number, - oldpin_buf, oldpin_len, - newpin_buf, newpin_len); - - xfree (newpin_buf); - xfree (oldpin_buf); - xfree (oldpin); - } - } - break; - - case cmdREADPK: - if (arg_number < 1 || arg_number > 255) - printf ("usage: readpk CRTBYTE1\n"); - else - { - unsigned char crt[2]; - - crt[0] = arg_number; - crt[1] = 0; - err = iso7816_read_public_key(slot, crt, 2, - &result, &resultlen); - if (!err) - dump_or_store_buffer (arg_string, result, resultlen); - } - break; - - - case cmdINVCMD: - default: - printf ("\n"); - printf ("Invalid command (try \"help\")\n"); - break; - } /* End command switch. */ - } /* End of main menu loop. */ - - leave: - ; -} - - - -/* Figure out whether the current card is a German Geldkarte and print - what we know about it. */ -static int -dump_geldkarte (int slot) -{ - unsigned char *r = NULL; - size_t rlen; - const char *t; - - if (iso7816_read_record (slot, 1, 1, 0xbc, &r, &rlen)) - return -1; - /* We require that the record is at least 24 bytes, the first byte - is 0x67 and the filler byte is correct. */ - if (rlen < 24 || *r != 0x67 || r[22]) - return -1; - - /* The short Bankleitzahl consists of 3 bytes at offset 1. */ - switch (r[1]) - { - case 0x21: t = "Oeffentlich-rechtliche oder private Bank"; break; - case 0x22: t = "Privat- oder Geschftsbank"; break; - case 0x25: t = "Sparkasse"; break; - case 0x26: - case 0x29: t = "Genossenschaftsbank"; break; - default: - xfree (r); - return -1; /* Probably not a Geldkarte. */ - } - - printf ("KBLZ .....: %02X-%02X%02X (%s)\n", r[1], r[2], r[3], t); - printf ("Card-No ..: %02X%02X%02X%02X%02X\n", r[4], r[5], r[6], r[7], r[8]); - -/* Byte 10 enthlt im linken Halbbyte eine Prfziffer, die nach dem */ -/* Verfahren 'Luhn formula for computing modulus 10' ber die Ziffern der */ -/* ersten 9 Byte berechnet ist. */ - -/* Das rechte Halbbyte wird zu 'D' gesetzt. */ - -/* Fr die Berechnung der Luhn-Prfziffer sind die folgenden Schritte */ -/* durchzufhren: */ - -/* Schritt 1: Mit der rechtesten Ziffer beginnend ist einschlielich dieser */ -/* Ziffer jede bernchste Ziffer zu verdoppeln (mit 2 multiplizieren). */ - -/* Schritt 2: Die einzelnen Ziffern der Produkte aus Schritt 1 und die bei */ -/* diesen Multiplikationen unberhrt gebliebenen Ziffern sind zu addieren. */ - -/* Schritt 3: Das Ergebnis der Addition aus Schritt 2 ist von dem auf die */ -/* nchst hhere Zahl mit der Einerstelle 0 aufgerundeten Ergebnis der */ -/* Addition aus Schritt 2 abzuziehen. Wenn das Ergebnis der Addition aus */ -/* Schritt 2 bereits eine Zahl mit der Einerstelle 0 ergibt (z.B. 30, 40, */ -/* usw.), ist die Prfziffer 0. */ - -/* Beispiel: Kartennummer ohne Prfziffer: 992 839 871 */ - -/* 9 9 2 8 3 9 8 7 1 */ - -/* x 2 x 2 x 2 x 2 x 2 Schritt 1 */ - -/* 18 4 6 16 2 */ - -/* 1+8 +9 +4 +8 +6 +9 +1+6 +7 +2 = 61 Schritt 2 */ - -/* 70-61 = 9 Schritt 3 */ - -/* Prfziffer zu 992 839 871 = 9 */ - - - printf ("Expires at: %02X/%02X\n", r[11], r[10] ); - printf ("Valid from: %02X.%02X.%02X\n", r[14], r[13], r[12]); - printf ("Country ..: %02X%02X\n", r[15], r[16]); - printf ("Currency .: %c%c%c\n", isascii (r[17])? r[17]:' ', - isascii (r[18])? r[18]:' ', isascii (r[19])? r[19]:' '); - printf ("Cur.-Mult : %s\n", - r[20] == 0x01? "0.01": - r[20] == 0x02? "0.1": - r[20] == 0x04? "1": - r[20] == 0x08? "10": - r[20] == 0x10? "100": - r[20] == 0x20? "1000": "?"); - printf ("ZKA ChipID: %02X\n", r[21]); - printf ("OS version: %02X\n", r[23]); - - xfree (r); - return 0; -} - - - -/* Try to figure out the type of teh card and dump its contents. */ -static void -dump_other_cards (int slot) -{ - - if (!dump_geldkarte (slot)) - return; - -} - -- cgit v1.2.3 From c5487b7982128851b682d54f4ffd67c32e444b6f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 20 Oct 2004 08:55:26 +0000 Subject: typo fix --- kbx/keybox-openpgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 7e6e0e412..7401949c9 100644 --- a/kbx/keybox-openpgp.c +++ b/kbx/keybox-openpgp.c @@ -301,7 +301,7 @@ parse_key (const unsigned char *data, size_t datalen, else { /* Its a pitty that we need to prefix the buffer with the tag - and a length header: We can't simply psss it to the fast + and a length header: We can't simply pass it to the fast hashing fucntion for that reason. It might be a good idea to have a scatter-gather enabled hash function. What we do here is to use a static buffer if this one is large enough and -- cgit v1.2.3 From 280a222553ed75ec36b2e2f81d8d5889f9b77e9d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 09:39:47 +0000 Subject: (parse_rereadable_options): Return "not handled" when the log file has not beend hadled. This is will let the main option processing continue. Fixed a bug introduced on 2004-09-4 resulting in logging to stderr until a HUP has been given. (main): Don't close the listen FD. --- agent/ChangeLog | 8 ++++++++ agent/gpg-agent.c | 12 +++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index b65e7b1de..756711f1a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * gpg-agent.c (parse_rereadable_options): Return "not handled" + when the log file has not beend hadled. This is will let the main + option processing continue. Fixed a bug introduced on 2004-09-4 + resulting in logging to stderr until a HUP has been given. + (main): Don't close the listen FD. + 2004-09-30 Werner Koch <wk@g10code.com> * Makefile.am: Adjusted from gettext 1.14. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 4e3f0b507..d3d628766 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -166,7 +166,7 @@ static char *config_filename; static const char *debug_level; /* Keep track of the current log file so that we can avoid updating - the log file afte a SIGHUP if id didn't changed. Malloced. */ + the log file after a SIGHUP if it didn't changed. Malloced. */ static char *current_logfile; /* Local prototypes. */ @@ -362,9 +362,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oDebugLevel: debug_level = pargs->r.ret_str; break; case oLogFile: - if (reread - && (!current_logfile || !pargs->r.ret_str - || strcmp (current_logfile, pargs->r.ret_str))) + if (!reread) + return 0; /* not handeld */ + if (!current_logfile || !pargs->r.ret_str + || strcmp (current_logfile, pargs->r.ret_str)) { log_set_file (pargs->r.ret_str); xfree (current_logfile); @@ -416,6 +417,7 @@ main (int argc, char **argv ) int gpgconf_list = 0; gpg_error_t err; + set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); /* Please note that we may running SUID(ROOT), so be very CAREFUL @@ -861,7 +863,7 @@ main (int argc, char **argv ) /* Close stdin, stdout and stderr unless it is the log stream */ for (i=0; i <= 2; i++) { - if (!log_test_fd (i) ) + if (!log_test_fd (i) && i != fd ) close (i); } if (setsid() == -1) -- cgit v1.2.3 From e733aad405f0aa3d25fce1768a1e20eebcea4cdc Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 09:41:01 +0000 Subject: Updated from 1.3 --- g10/card-util.c | 619 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 489 insertions(+), 130 deletions(-) diff --git a/g10/card-util.c b/g10/card-util.c index 2d7f00800..1d2e47ea2 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -34,6 +34,7 @@ #include "status.h" #include "options.h" #include "main.h" +#include "keyserver-internal.h" #if GNUPG_MAJOR_VERSION == 1 #include "cardglue.h" #else @@ -46,7 +47,7 @@ /* Change the PIN of a an OpenPGP card. This is an interactive function. */ void -change_pin (int chvno) +change_pin (int chvno, int allow_admin) { struct agent_card_info_s info; int rc; @@ -70,52 +71,61 @@ change_pin (int chvno) return; } - for (;;) + if(!allow_admin) { - 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; - } + 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 + 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 * @@ -510,6 +520,49 @@ change_url (void) return rc; } +static int +fetch_url(void) +{ + int rc; + struct agent_card_info_s info; + + memset(&info,0,sizeof(info)); + + rc=agent_scd_getattr("PUBKEY-URL",&info); + if(rc) + log_error("error retrieving URL from card: %s\n",gpg_strerror(rc)); + else if(info.pubkey_url) + { + struct keyserver_spec *spec=NULL; + + rc=agent_scd_getattr("KEY-FPR",&info); + if(rc) + log_error("error retrieving key fingerprint from card: %s\n", + gpg_strerror(rc)); + else + { + spec=parse_keyserver_uri(info.pubkey_url,0,NULL,0); + if(spec && info.fpr1valid) + { + /* This is not perfectly right. Currently, all card + fingerprints are 20 digits, but what about + fingerprints for a future v5 key? We should get the + length from somewhere lower in the code. In any + event, the fpr/keyid is not meaningful for straight + HTTP fetches, but using it allows the card to point + to HKP and LDAP servers as well. */ + rc=keyserver_import_fprint(info.fpr1,20,spec); + free_keyserver_spec(spec); + } + } + } + else + log_error("no URL set on card\n"); + + return rc; +} + + static int change_login (const char *args) { @@ -524,17 +577,24 @@ change_login (const char *args) for (args++; spacep (args); args++) ; fp = fopen (args, "rb"); + if (fp && is_secured_file (fileno (fp))) + { + fclose (fp); + fp = NULL; + errno = EPERM; + } if (!fp) { - tty_printf ("can't open `%s': %s\n", args, strerror (errno)); + tty_printf (_("can't open `%s': %s\n"), args, strerror (errno)); return -1; } + data = xmalloc (254); n = fread (data, 1, 254, fp); fclose (fp); if (n < 0) { - tty_printf ("error reading `%s': %s\n", args, strerror (errno)); + tty_printf (_("error reading `%s': %s\n"), args, strerror (errno)); xfree (data); return -1; } @@ -705,26 +765,142 @@ toggle_forcesig (void) } -static void -generate_card_keys (const char *serialno) +/* Helper for the key generation/edit functions. */ +static int +get_info_for_key_operation (struct agent_card_info_s *info) { - 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); + memset (info, 0, sizeof *info); + rc = agent_scd_getattr ("SERIALNO", info); + if (rc || !info->serialno || strncmp (info->serialno, "D27600012401", 12) + || strlen (info->serialno) != 32 ) + { + log_error (_("key operation not possible: %s\n"), + rc ? gpg_strerror (rc) : _("not an OpenPGP card")); + return rc? rc: -1; + } + rc = agent_scd_getattr ("KEY-FPR", info); if (!rc) - rc = agent_scd_getattr ("CHV-STATUS", &info); + rc = agent_scd_getattr ("CHV-STATUS", info); if (!rc) - rc = agent_scd_getattr ("DISP-NAME", &info); + rc = agent_scd_getattr ("DISP-NAME", info); if (rc) + log_error (_("error getting current key info: %s\n"), gpg_strerror (rc)); + return rc; +} + + +/* Helper for the key generation/edit functions. */ +static int +check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1) +{ + int rc = 0; + + *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)); + *forced_chv1 = 0; + } + } + + if (!rc) { - log_error ("error getting current key info: %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 (info->serialno); + if (rc) + log_error ("error checking the PIN: %s\n", gpg_strerror (rc)); } + return rc; +} + +/* Helper for the key generation/edit functions. */ +static void +restore_forced_chv1 (int *forced_chv1) +{ + int rc; + + 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)); + } + } +} + +/* Helper for the key generation/edit functions. */ +static void +show_card_key_info (struct agent_card_info_s *info) +{ + tty_fprintf (NULL, "Signature key ....:"); + print_sha1_fpr (NULL, info->fpr1valid? info->fpr1:NULL); + tty_fprintf (NULL, "Encryption key....:"); + print_sha1_fpr (NULL, info->fpr2valid? info->fpr2:NULL); + tty_fprintf (NULL, "Authentication key:"); + print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL); + tty_printf ("\n"); +} + + +/* Helper for the key generation/edit functions. */ +static int +replace_existing_key_p (struct agent_card_info_s *info, int keyno) +{ + assert (keyno >= 0 && keyno <= 3); + + if ((keyno == 1 && info->fpr1valid) + || (keyno == 2 && info->fpr2valid) + || (keyno == 3 && info->fpr3valid)) + { + tty_printf ("\n"); + log_info ("WARNING: such a key has already been stored on the card!\n"); + tty_printf ("\n"); + if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key", + _("Replace existing key? (y/N) "))) + return -1; + } + return 0; +} + + + +static void +generate_card_keys (const char *serialno) +{ + struct agent_card_info_s info; + int forced_chv1; + int want_backup; + + if (get_info_for_key_operation (&info)) + return; + +#if GNUPG_MAJOR_VERSION == 1 + { + char *answer=cpr_get("cardedit.genkeys.backup_enc", + _("Make off-card backup of encryption key? (Y/n) ")); + + want_backup=answer_is_yes_no_default(answer,1); + cpr_kill_prompt(); + m_free(answer); + } +#else + /* Does 1.9 have answer_is_yes_no_default() ? */ + want_backup = !(cpr_get_answer_is_yes + ( "cardedit.genkeys.backup_enc", + _("Inhibit off-card backup of encryption key? (y/N) "))); +#endif + if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) || (info.fpr2valid && !fpr_is_zero (info.fpr2)) || (info.fpr3valid && !fpr_is_zero (info.fpr3))) @@ -733,7 +909,7 @@ generate_card_keys (const char *serialno) 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? "))) + _("Replace existing keys? (y/N) "))) { agent_release_card_info (&info); return; @@ -743,47 +919,207 @@ generate_card_keys (const char *serialno) { tty_printf ("\n"); tty_printf (_("Please note that the factory settings of the PINs are\n" - " PIN = \"%s\" Admin PIN = \"%s\"\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) + if (check_pin_for_key_operation (&info, &forced_chv1)) + goto leave; + + generate_keypair (NULL, info.serialno, + want_backup? opt.homedir:NULL); + + leave: + agent_release_card_info (&info); + restore_forced_chv1 (&forced_chv1); +} + + +/* This fucntion is used by the key edit menu to generate an arbitrary + subkey. */ +int +card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) +{ + struct agent_card_info_s info; + int okay = 0; + int forced_chv1 = 0; + int keyno; + + if (get_info_for_key_operation (&info)) + return 0; + + show_card_key_info (&info); + + tty_printf (_("Please select the type of key to generate:\n")); + + tty_printf (_(" (1) Signature key\n")); + tty_printf (_(" (2) Encryption key\n")); + tty_printf (_(" (3) Authentication key\n")); + + for (;;) + { + char *answer = cpr_get ("cardedit.genkeys.subkeytype", + _("Your selection? ")); + cpr_kill_prompt(); + if (*answer == CONTROL_D) { - log_error ("error clearing forced signature PIN flag: %s\n", - gpg_strerror (rc)); - return; + xfree (answer); + goto leave; } + keyno = *answer? atoi(answer): 0; + xfree(answer); + if (keyno >= 1 && keyno <= 3) + break; /* Okay. */ + tty_printf(_("Invalid selection.\n")); } - /* 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); + if (replace_existing_key_p (&info, keyno)) + goto leave; + + if (check_pin_for_key_operation (&info, &forced_chv1)) + goto leave; + okay = generate_card_subkeypair (pub_keyblock, sec_keyblock, + keyno, info.serialno); + + leave: agent_release_card_info (&info); - if (forced_chv1) - { /* Switch back to forced state. */ - rc = agent_scd_setattr ("CHV-STATUS-1", "", 1); - if (rc) + restore_forced_chv1 (&forced_chv1); + return okay; +} + + +/* Store the subkey at NODE into the smartcard and modify NODE to + carry the serrialno stuff instead of the actual secret key + parameters. */ +int +card_store_subkey (KBNODE node, int use) +{ + struct agent_card_info_s info; + int okay = 0; + int rc; + int keyno, i; + PKT_secret_key *copied_sk = NULL; + PKT_secret_key *sk; + size_t n; + const char *s; + int allow_keyno[3]; + + assert (node->pkt->pkttype == PKT_SECRET_KEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY); + sk = node->pkt->pkt.secret_key; + + if (get_info_for_key_operation (&info)) + return 0; + + show_card_key_info (&info); + + if (!is_RSA (sk->pubkey_algo) || nbits_from_sk (sk) != 1024 ) + { + tty_printf ("You may only store a 1024 bit RSA key on the card\n"); + tty_printf ("\n"); + goto leave; + } + + allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); + allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); + allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); + + tty_printf (_("Please select where to store the key:\n")); + + if (allow_keyno[0]) + tty_printf (_(" (1) Signature key\n")); + if (allow_keyno[1]) + tty_printf (_(" (2) Encryption key\n")); + if (allow_keyno[2]) + tty_printf (_(" (3) Authentication key\n")); + + for (;;) + { + char *answer = cpr_get ("cardedit.genkeys.storekeytype", + _("Your selection? ")); + cpr_kill_prompt(); + if (*answer == CONTROL_D || !*answer) { - log_error ("error setting forced signature PIN flag: %s\n", - gpg_strerror (rc)); - return; + xfree (answer); + goto leave; } + keyno = *answer? atoi(answer): 0; + xfree(answer); + if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) + break; /* Okay. */ + tty_printf(_("Invalid selection.\n")); + } + + if (replace_existing_key_p (&info, keyno)) + goto leave; + + /* Unprotect key. */ + switch (is_secret_key_protected (sk) ) + { + case 0: /* Not protected. */ + break; + case -1: + log_error (_("unknown key protection algorithm\n")); + goto leave; + default: + if (sk->protect.s2k.mode == 1001) + { + log_error (_("secret parts of key are not available\n")); + goto leave; + } + if (sk->protect.s2k.mode == 1002) + { + log_error (_("secret key already stored on a card\n")); + goto leave; + } + /* We better copy the key before we unprotect it. */ + copied_sk = sk = copy_secret_key (NULL, sk); + rc = check_secret_key (sk, 0); + if (rc) + goto leave; } + + rc = save_unprotected_key_to_card (sk, keyno); + if (rc) + goto leave; + + /* Get back to the maybe protected original secret key. */ + if (copied_sk) + { + free_secret_key (copied_sk); + copied_sk = NULL; + } + sk = node->pkt->pkt.secret_key; + + /* Get rid of the secret key parameters and store the serial numer. */ + n = pubkey_get_nskey (sk->pubkey_algo); + for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) + { + mpi_free (sk->skey[i]); + sk->skey[i] = NULL; + } + i = pubkey_get_npkey (sk->pubkey_algo); + sk->skey[i] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->is_protected = 1; + sk->protect.s2k.mode = 1002; + s = info.serialno; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); + + okay = 1; + + leave: + if (copied_sk) + free_secret_key (copied_sk); + agent_release_card_info (&info); + return okay; } + /* Menu to edit all user changeable values on an OpenPGP card. Only Key creation is not handled here. */ void @@ -791,8 +1127,8 @@ card_edit (STRLIST commands) { enum cmdids { cmdNOP = 0, - cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, - cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, + cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, + cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdINVCMD }; @@ -800,34 +1136,38 @@ card_edit (STRLIST commands) static struct { const char *name; enum cmdids id; + int admin_only; 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_("cafpr"), cmdCAFPR, N_("change a CA fingerprint") }, + { N_("quit") , cmdQUIT , 0, N_("quit this menu") }, + { N_("q") , cmdQUIT , 0, NULL }, + { N_("admin") , cmdADMIN , 0, N_("show admin commands") }, + { N_("help") , cmdHELP , 0, N_("show this help") }, + { "?" , cmdHELP , 0, NULL }, + { N_("list") , cmdLIST , 0, N_("list all available data") }, + { N_("l") , cmdLIST , 0, NULL }, + { N_("debug") , cmdDEBUG , 0, NULL }, + { N_("name") , cmdNAME , 1, N_("change card holder's name") }, + { N_("url") , cmdURL , 1, N_("change URL to retrieve key") }, + { N_("fetch") , cmdFETCH , 0, + N_("fetch the key specified in the card URL") }, + { N_("login") , cmdLOGIN , 1, N_("change the login name") }, + { N_("lang") , cmdLANG , 1, N_("change the language preferences") }, + { N_("sex") , cmdSEX , 1, N_("change card holder's sex") }, + { N_("cafpr"), cmdCAFPR, 1, N_("change a CA fingerprint") }, { N_("forcesig"), - cmdFORCESIG, N_("toggle the signature force PIN flag") }, + cmdFORCESIG, 1, 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 } + cmdGENERATE, 1, N_("generate new keys") }, + { N_("passwd"), cmdPASSWD, 0, N_("menu to change or unblock the PIN") }, + { NULL, cmdINVCMD, 0, NULL } }; enum cmdids cmd = cmdNOP; int have_commands = !!commands; int redisplay = 1; char *answer = NULL; - int did_checkpin = 0; + int did_checkpin = 0, allow_admin=0; char serialnobuf[50]; @@ -845,6 +1185,7 @@ card_edit (STRLIST commands) const char *arg_string = ""; char *p; int i; + int cmd_admin_only; tty_printf("\n"); if (redisplay ) @@ -887,61 +1228,79 @@ card_edit (STRLIST commands) } trim_spaces(answer); } - while( *answer == '#' ); + while ( *answer == '#' ); arg_number = 0; /* Yes, here is the init which egcc complains about */ + cmd_admin_only = 0; 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; - } - + 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; + cmd_admin_only = cmds[i].admin_only; + } + + if (!allow_admin && cmd_admin_only) + { + tty_printf ("\n"); + tty_printf (_("Admin-only command\n")); + continue; + } switch (cmd) { case cmdHELP: for (i=0; cmds[i].name; i++ ) - if (cmds[i].desc) + if(cmds[i].desc + && (!cmds[i].admin_only || (cmds[i].admin_only && allow_admin))) tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); break; + case cmdADMIN: + allow_admin=!allow_admin; + break; + case cmdLIST: redisplay = 1; break; case cmdNAME: - change_name (); + change_name (); break; case cmdURL: - change_url (); + change_url (); break; + case cmdFETCH: + fetch_url(); + break; + case cmdLOGIN: - change_login (arg_string); + change_login (arg_string); break; case cmdLANG: - change_lang (); + change_lang (); break; case cmdSEX: - change_sex (); + change_sex (); break; case cmdCAFPR: @@ -961,7 +1320,7 @@ card_edit (STRLIST commands) break; case cmdPASSWD: - change_pin (0); + change_pin (0, allow_admin); did_checkpin = 0; /* Need to reset it of course. */ break; -- cgit v1.2.3 From 23d73cdeb8e5e3f0a56189c25a362f258de1f7d1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 09:41:24 +0000 Subject: * logging.c (do_logv): Use set_log_stream to setup a default. (log_set_file): Factored code out to .. (set_file_fd): .. New function to allow using a file descriptor. (log_set_fd): Make use of new fucntion. (fun_writer): Reworked. --- jnlib/ChangeLog | 8 ++ jnlib/logging.c | 304 ++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 193 insertions(+), 119 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index db9b68d0d..3c2d6d84a 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,11 @@ +2004-10-21 Werner Koch <wk@g10code.com> + + * logging.c (do_logv): Use set_log_stream to setup a default. + (log_set_file): Factored code out to .. + (set_file_fd): .. New function to allow using a file descriptor. + (log_set_fd): Make use of new fucntion. + (fun_writer): Reworked. + 2004-08-18 Werner Koch <wk@g10code.de> * stringhelp.c (print_sanitized_utf8_string): Actually implement diff --git a/jnlib/logging.c b/jnlib/logging.c index f91339687..7a5e1552e 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -37,14 +37,20 @@ #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> +#include <fcntl.h> +#include <assert.h> #ifdef __MINGW32__ # include <io.h> #endif + #define JNLIB_NEED_LOG_LOGV 1 #include "libjnlib-config.h" #include "logging.h" +#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) +#define USE_FUNWRITER 1 +#endif static FILE *logstream; static int log_socket = -1; @@ -94,10 +100,12 @@ log_inc_errorcount (void) /* The follwing 3 functions are used by funopen to write logs to a socket. */ -#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN) +#ifdef USE_FUNWRITER struct fun_cookie_s { int fd; int quiet; + int want_socket; + int is_socket; char name[1]; }; @@ -135,64 +143,78 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) processes often close stderr and by writing to file descriptor 2 we might send the log message to a file not intended for logging (e.g. a pipe or network connection). */ - if (cookie->fd == -1) + if (cookie->want_socket && cookie->fd == -1) { /* Not yet open or meanwhile closed due to an error. */ - struct sockaddr_un addr; - size_t addrlen; - + cookie->is_socket = 0; cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); if (cookie->fd == -1) { if (!cookie->quiet && !running_detached) fprintf (stderr, "failed to create socket for logging: %s\n", strerror(errno)); - goto failure; } - log_socket = cookie->fd; + else + { + struct sockaddr_un addr; + size_t addrlen; + + memset (&addr, 0, sizeof addr); + addr.sun_family = PF_LOCAL; + strncpy (addr.sun_path, cookie->name, sizeof (addr.sun_path)-1); + addr.sun_path[sizeof (addr.sun_path)-1] = 0; + addrlen = (offsetof (struct sockaddr_un, sun_path) + + strlen (addr.sun_path) + 1); - memset (&addr, 0, sizeof addr); - addr.sun_family = PF_LOCAL; - strncpy (addr.sun_path, cookie->name, sizeof (addr.sun_path)-1); - addr.sun_path[sizeof (addr.sun_path)-1] = 0; - addrlen = (offsetof (struct sockaddr_un, sun_path) - + strlen (addr.sun_path) + 1); + if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) + { + if (!cookie->quiet && !running_detached) + fprintf (stderr, "can't connect to `%s': %s\n", + cookie->name, strerror(errno)); + close (cookie->fd); + cookie->fd = -1; + } + } - if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) + if (cookie->fd == -1) { - log_socket = -1; - if (!cookie->quiet && !running_detached) - fprintf (stderr, "can't connect to `%s': %s\n", - cookie->name, strerror(errno)); - close (cookie->fd); - cookie->fd = -1; - goto failure; + if (!running_detached) + { + if (!cookie->quiet) + { + fputs ("switching logging to stderr\n", stderr); + cookie->quiet = 1; + } + cookie->fd = fileno (stderr); + } + } + else /* Connection has been established. */ + { + cookie->quiet = 0; + cookie->is_socket = 1; } - /* Connection established. */ - cookie->quiet = 0; } - - if (!writen (cookie->fd, buffer, size)) + + log_socket = cookie->fd; + if (cookie->fd != -1 && !writen (cookie->fd, buffer, size)) return size; /* Okay. */ - log_socket = -1; - if (!running_detached) - fprintf (stderr, "error writing to `%s': %s\n", - cookie->name, strerror(errno)); - close (cookie->fd); - cookie->fd = -1; - - failure: - if (!running_detached) + if (!running_detached && cookie->fd != -1) { - if (!cookie->quiet) - { - fputs ("switching logging to stderr\n", stderr); - cookie->quiet = 1; - } - - fwrite (buffer, size, 1, stderr); + if (*cookie->name) + fprintf (stderr, "error writing to `%s': %s\n", + cookie->name, strerror(errno)); + else + fprintf (stderr, "error writing to file descriptor %d: %s\n", + cookie->fd, strerror(errno)); } + if (cookie->is_socket && cookie->fd != -1) + { + close (cookie->fd); + cookie->fd = -1; + log_socket = -1; + } + return size; } @@ -204,110 +226,148 @@ fun_closer (void *cookie_arg) if (cookie->fd != -1) close (cookie->fd); jnlib_free (cookie); + log_socket = -1; return 0; } -#endif /* HAVE_FOPENCOOKIE || HAVE_FUNOPEN */ - +#endif /*USE_FUNWRITER*/ -/* Set the file to write log to. The special names NULL and "-" may - be used to select stderr and names formatted like - "socket:///home/foo/mylogs" may be used to write the logging to the - socket "/home/foo/mylogs". If the connection to the socket fails - or a write error is detected, the function writes to stderr and - tries the next time again to connect the socket. - */ -void -log_set_file (const char *name) +/* Common function to either set the logging to a file or a file + descriptor. */ +static void +set_file_fd (const char *name, int fd) { FILE *fp; + int want_socket; +#ifdef USE_FUNWRITER + struct fun_cookie_s *cookie; +#endif + + if (name && !strcmp (name, "-")) + { + name = NULL; + fd = fileno (stderr); + } - force_prefixes = 0; - if (name && !strncmp (name, "socket://", 9) && name[9]) + if (name) + { + want_socket = (!strncmp (name, "socket://", 9) && name[9]); + if (want_socket) + name += 9; + } + else { -#if defined (HAVE_FOPENCOOKIE)|| defined (HAVE_FUNOPEN) - struct fun_cookie_s *cookie; + want_socket = 0; + } - cookie = jnlib_xmalloc (sizeof *cookie + strlen (name+9)); - cookie->fd = -1; - cookie->quiet = 0; - strcpy (cookie->name, name+9); +#ifdef USE_FUNWRITER + cookie = jnlib_xmalloc (sizeof *cookie + (name? strlen (name):0)); + strcpy (cookie->name, name? name:""); + cookie->quiet = 0; + cookie->is_socket = 0; + cookie->want_socket = want_socket; + if (!name) + cookie->fd = fd; + else if (want_socket) + cookie->fd = -1; + else + { + do + cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT, + (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)); + while (cookie->fd == -1 && errno == EINTR); + } + log_socket = cookie->fd; #ifdef HAVE_FOPENCOOKIE - { - cookie_io_functions_t io = { NULL }; - io.write = fun_writer; - io.close = fun_closer; - - fp = fopencookie (cookie, "w", io); - } + { + cookie_io_functions_t io = { NULL }; + io.write = fun_writer; + io.close = fun_closer; + + fp = fopencookie (cookie, "w", io); + } #else /*!HAVE_FOPENCOOKIE*/ - { - fp = funopen (cookie, NULL, fun_writer, NULL, fun_closer); - } + fp = funopen (cookie, NULL, fun_writer, NULL, fun_closer); #endif /*!HAVE_FOPENCOOKIE*/ -#else /* Neither fopencookie nor funopen. */ - { - fprintf (stderr, "system does not support logging to a socket - " - "using stderr\n"); - fp = stderr; - } -#endif /* Neither fopencookie nor funopen. */ - - /* We always need to print the prefix and the pid, so that the - server reading the socket can do something meaningful. */ - force_prefixes = 1; - /* On success close the old logstream right now, so that we are - really sure it has been closed. */ - if (fp && logstream) - { - if (logstream != stderr && logstream != stdout) - fclose (logstream); - logstream = NULL; - } + +#else /*!USE_FUNWRITER*/ + + /* The system does not feature custom streams. Thus fallback to + plain stdio. */ + if (want_socket) + { + fprintf (stderr, "system does not support logging to a socket - " + "using stderr\n"); + fp = stderr; } + else if (name) + fp = fopen (name, "a"); + else if (fd == 1) + fp = stdout; + else if (fd == 2) + fp = stderr; else - fp = (name && strcmp(name,"-"))? fopen (name, "a") : stderr; + fp = fdopen (fd, "a"); + + log_socket = -1; + +#endif /*!USE_FUNWRITER*/ + + /* On success close the old logstream right now, so that we are + really sure it has been closed. */ + if (fp && logstream) + { + if (logstream != stderr && logstream != stdout) + fclose (logstream); + logstream = NULL; + } + if (!fp) { - fprintf (stderr, "failed to open log file `%s': %s\n", - name? name:"[stderr]", strerror(errno)); - return; + if (name) + fprintf (stderr, "failed to open log file `%s': %s\n", + name, strerror(errno)); + else + fprintf (stderr, "failed to fdopen file descriptor %d: %s\n", + fd, strerror(errno)); + /* We need to make sure that there is a log stream. We use stderr. */ + fp = stderr; } - setvbuf (fp, NULL, _IOLBF, 0); + else + setvbuf (fp, NULL, _IOLBF, 0); if (logstream && logstream != stderr && logstream != stdout) fclose (logstream); logstream = fp; + + /* We always need to print the prefix and the pid for socket mode, + so that the server reading the socket can do something + meaningful. */ + force_prefixes = want_socket; + missing_lf = 0; } +/* Set the file to write log to. The special names NULL and "-" may + be used to select stderr and names formatted like + "socket:///home/foo/mylogs" may be used to write the logging to the + socket "/home/foo/mylogs". If the connection to the socket fails + or a write error is detected, the function writes to stderr and + tries the next time again to connect the socket. + */ void -log_set_fd (int fd) +log_set_file (const char *name) { - FILE *fp; + set_file_fd (name? name: "-", -1); +} - force_prefixes = 0; - if (fd == 1) - fp = stdout; - else if (fd == 2) - fp = stderr; - else - fp = fdopen (fd, "a"); - if (!fp) - { - fprintf (stderr, "failed to fdopen log fd %d: %s\n", - fd, strerror(errno)); - return; - } - setvbuf (fp, NULL, _IOLBF, 0); - - if (logstream && logstream != stderr && logstream != stdout) - fclose( logstream); - logstream = fp; - missing_lf = 0; +void +log_set_fd (int fd) +{ + set_file_fd (NULL, fd); } @@ -351,9 +411,10 @@ log_get_prefix (unsigned int *flags) int log_test_fd (int fd) { - if (fileno (logstream?logstream:stderr) == fd) + int tmp = fileno (logstream); + if ( tmp != -1 && tmp == fd) return 1; - if (log_socket == fd) + if (log_socket != -1 && log_socket == fd) return 1; return 0; } @@ -367,15 +428,20 @@ log_get_fd () FILE * log_get_stream () { + /* FIXME: We should not return stderr here but initialize the log + stream properly. This might break more things than using stderr, + though */ return logstream?logstream:stderr; } - static void do_logv (int level, const char *fmt, va_list arg_ptr) { if (!logstream) - logstream = stderr; + { + log_set_file (NULL); /* Make sure a log stream has been set. */ + assert (logstream); + } if (missing_lf && level != JNLIB_LOG_CONT) putc('\n', logstream ); -- cgit v1.2.3 From 9aa7d0bc353daa9728bfb69a6e775ddc82075f87 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 09:41:56 +0000 Subject: * app-openpgp.c (do_sign): Replace asprintf by direct allocation. This avoids problems with missing vasprintf implementations in gnupg 1.4. * app-common.h (app_openpgp_storekey: Add prototype. --- scd/ChangeLog | 8 ++++++++ scd/app-common.h | 7 +++++++ scd/app-openpgp.c | 9 +++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index eba39c731..32fbdf9d9 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,11 @@ +2004-10-21 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_sign): Replace asprintf by direct allocation. + This avoids problems with missing vasprintf implementations in + gnupg 1.4. + + * app-common.h (app_openpgp_storekey: Add prototype. + 2004-10-20 Werner Koch <wk@g10code.com> * sc-investigate: Removed. diff --git a/scd/app-common.h b/scd/app-common.h index f54f6da92..48bd349f4 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -88,6 +88,13 @@ struct app_ctx_s { #if GNUPG_MAJOR_VERSION == 1 int app_select_openpgp (app_t app); int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); +int app_openpgp_storekey (app_t app, int keyno, + unsigned char *template, size_t template_len, + time_t created_at, + const unsigned char *m, size_t mlen, + const unsigned char *e, size_t elen, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); #else /*-- app-help.c --*/ gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index d6cbe88a6..f73b4f946 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -824,7 +824,7 @@ verify_chv3 (app_t app, if (strlen (pinvalue) < 6) { - log_error (_("prassphrase (CHV%d) is too short;" + log_error (_("passphrase (CHV%d) is too short;" " minimum length is %d\n"), 3, 6); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); @@ -1298,10 +1298,15 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, { char *prompt; - if (asprintf (&prompt, _("PIN [sigs done: %lu]"), sigcount) < 0) +#define PROMPTSTRING _("PIN [sigs done: %lu]") + + prompt = malloc (strlen (PROMPTSTRING) + 50); + if (!prompt) return gpg_error_from_errno (errno); + sprintf (prompt, PROMPTSTRING, sigcount); rc = pincb (pincb_arg, prompt, &pinvalue); free (prompt); +#undef PROMPTSTRING } if (rc) { -- cgit v1.2.3 From 5b12394f805405daea5532be8256ca736f6ca486 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 12:30:34 +0000 Subject: (Helper Tools): Document gpgsm-gencert.sh. --- doc/ChangeLog | 4 ++++ doc/tools.texi | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index c5ff57691..4262865a5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * tools.texi (Helper Tools): Document gpgsm-gencert.sh. + 2004-10-05 Werner Koch <wk@g10code.com> * gpg-agent.texi (Invoking GPG-AGENT): Tell that GPG_TTY needs to diff --git a/doc/tools.texi b/doc/tools.texi index 79ae85d90..086f71df1 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -11,6 +11,7 @@ GnuPG comes with a couple of smaller tools: * watchgnupg:: Read logs from a socket. * addgnupghome:: Create .gnupg home directories. * gpgconf:: Modify .gnupg home directories. +* gpgsm-gencert.sh:: Generate an X.509 certificate request. @end menu @c @@ -575,3 +576,20 @@ $ echo 'force:16:' | gpgconf --change-options dirmngr The @code{--runtime} option can influence when the changes take effect. + +@c +@c GPGSM-GENCERT.SH +@c +@node gpgsm-gencert.sh +@section Generate an X.509 certificate request + +This is a simple tool to interactivly generate a certificate request +whicl will be printed to stdout. + +@noindent +@command{gpgsm-gencert.sh} is invoked as: + +@samp{gpgsm-cencert.sh} + + + -- cgit v1.2.3 From d230475aaf781e4464c65e299c5ba8973dc32838 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 12:30:52 +0000 Subject: (gpgsm_genkey): Remove the NEW from the certificate request PEM header. This is according to the Sphinx standard. --- sm/ChangeLog | 5 +++++ sm/certreqgen.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 928611eb8..6dd5a28f3 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * certreqgen.c (gpgsm_genkey): Remove the NEW from the certificate + request PEM header. This is according to the Sphinx standard. + 2004-10-08 Moritz Schulte <moritz@g10code.com> * certchain.c (gpgsm_validate_chain): Do not use keydb_new() in diff --git a/sm/certreqgen.c b/sm/certreqgen.c index ab1f539de..bbc7c98e9 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -706,7 +706,7 @@ gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp) return tmperr; } - ctrl->pem_name = "NEW CERTIFICATE REQUEST"; + ctrl->pem_name = "CERTIFICATE REQUEST"; rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer); if (rc) { -- cgit v1.2.3 From 77a15fc9f878ba4f5c734554ea2df1d79106b97a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 12:31:04 +0000 Subject: * Makefile.am (bin_SCRIPTS): Add gpgsm-gencert.sh * gpgsm-gencert.sh: Fixed copyright; its part of GnuPG thus FSF. --- tools/ChangeLog | 6 ++++++ tools/Makefile.am | 2 ++ tools/gpgsm-gencert.sh | 28 ++++++++++++++++------------ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index ccfd39293..18412753c 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * Makefile.am (bin_SCRIPTS): Add gpgsm-gencert.sh + + * gpgsm-gencert.sh: Fixed copyright; its part of GnuPG thus FSF. + 2004-10-01 Werner Koch <wk@g10code.com> * gpgconf-comp.c: Made all strings for --log-file read the same. diff --git a/tools/Makefile.am b/tools/Makefile.am index 5395a90ca..271195c2a 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -30,6 +30,8 @@ AM_CFLAGS = @GPG_ERROR_CFLAGS@ sbin_SCRIPTS = addgnupghome +bin_SCRIPTS = gpgsm-gencert.sh + bin_PROGRAMS = gpgconf watchgnupg gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c diff --git a/tools/gpgsm-gencert.sh b/tools/gpgsm-gencert.sh index 3241efd94..ec5025b8f 100755 --- a/tools/gpgsm-gencert.sh +++ b/tools/gpgsm-gencert.sh @@ -1,7 +1,7 @@ #!/bin/sh - -# gpgsm-gencert.c - Generate X.509 certificates through GPGSM. -# Copyright (C) 2004 g10 Code GmbH +# -*- sh -*- +# gpgsm-gencert.c - Generate X.509 certificates through GPGSM. +# Copyright (C) 2004 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -37,8 +37,8 @@ query_user() { message=$1; shift - echo "$message" - echo -n "> " + echo "$message" >&2 + echo -n "> " >&2 read answer ANSWER=$answer; @@ -49,15 +49,15 @@ query_user_menu() message=$1; shift i=0 - echo "$message" + echo "$message" >&2 for choice in "$@"; do i=$(expr $i + 1) - echo " [$i] $choice" + echo " [$i] $choice" >&2 done while true; do j=1 - echo -n "Your selection: " + echo -n "Your selection: " >&2 read idx while [ $j -lt $i -o $j -eq $i ]; do @@ -81,7 +81,7 @@ query_user_menu() shift done - echo "You selected: $ANSWER" + echo "You selected: $ANSWER" >&2 } query_user_menu "Key type" "RSA" @@ -90,7 +90,7 @@ KEY_TYPE=$ANSWER query_user_menu "Key length" "1024" "2048" KEY_LENGTH=$ANSWER -query_user_menu "Key usage" "sign, encrypt" +query_user_menu "Key usage" "sign, encrypt" "sign" "encrypt" KEY_USAGE=$ANSWER query_user "Name" @@ -100,6 +100,7 @@ query_user "E-Mail address" EMAIL_ADDRESS=$ANSWER file_parameter=$(mktemp "/tmp/gpgsm.XXXXXX") +outfile=$(mktemp "/tmp/gpgsm.XXXXXX") cat > "$file_parameter" <<EOF Key-Type: $KEY_TYPE @@ -109,7 +110,10 @@ Name-DN: $NAME Name-Email: $EMAIL_ADDRESS EOF -echo -e "$ASSUAN_COMMANDS" | gpgsm --server 4< "$file_parameter" 5>&1 +echo -e "$ASSUAN_COMMANDS" | \ + gpgsm --server 4< "$file_parameter" 5>"$outfile" >/dev/null + +cat "$outfile" -rm "$file_parameter" +rm "$file_parameter" "$outfile" exit 0 -- cgit v1.2.3 From 29ddea6cbda40e1e509d5006a9e24313706218bf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 12:31:26 +0000 Subject: Cleaned up --- TODO | 7 ------- 1 file changed, 7 deletions(-) diff --git a/TODO b/TODO index 89db14aad..a80dfa453 100644 --- a/TODO +++ b/TODO @@ -86,7 +86,6 @@ might want to have an agent context for each service request * doc/ ** Explain how to setup a root CA key as trusted ** Explain how trustlist.txt might be managed. -** Document watchgnupg ** Write a script to generate man pages from texi. * Requirements by the BSI @@ -94,12 +93,6 @@ might want to have an agent context for each service request This needs support in libksba/src/cert.c as well as in sm/*.c. Need test certs as well. Same goes for CRL authorityKeyIdentifier. -** For pkcs#10 request header. - We use "NEW CERTIFICATE REQUEST" the specs say "CERTIFICATE - REQUEST" should be used. However it seems that their CA software - is also able to use our header. Binary pkcs#10 request are not - allowed. - ** Dirmngr: name subordination (nameRelativeToCRLIssuer) is not yet supported by Dirmngr. -- cgit v1.2.3 From 17c2c406016e51a6ecce5bd139d0c8e81ee07ec8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 16:03:04 +0000 Subject: Compile fixes. --- ChangeLog | 4 ++ Makefile.am | 3 +- NEWS | 6 ++- g10/ChangeLog | 9 ++++ g10/card-util.c | 30 +++++++++-- g10/g10.c | 8 ++- g10/main.h | 2 +- po/ChangeLog | 4 ++ po/POTFILES.in | 1 - po/de.po | 149 ++++++++++++++++++++++++++++-------------------------- scd/ChangeLog | 5 ++ scd/app-openpgp.c | 6 +-- tools/Makefile.am | 2 +- 13 files changed, 142 insertions(+), 87 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e83541c8..1a51c9557 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * Makefile.am (AUTOMAKE_OPTIONS): Set option to create bzip2 tarball. + 2004-10-01 Werner Koch <wk@g10code.com> Released 1.9.11. diff --git a/Makefile.am b/Makefile.am index 9be193353..08d025abf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ # Makefile.am - main makefile for NewPG/GnuPG -# Copyright (C) 2001 Free Software Foundation, Inc. +# Copyright (C) 2001, 2004 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -20,6 +20,7 @@ ## Process this file with automake to produce Makefile.in ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = dist-bzip2 EXTRA_DIST = scripts/config.rpath autogen.sh README.CVS DISTCLEANFILES = g10defs.h diff --git a/NEWS b/NEWS index 9ba9ddac9..b48546877 100644 --- a/NEWS +++ b/NEWS @@ -3,8 +3,10 @@ Noteworthy changes in version 1.9.12 * [scdaemon] Partly rewrote the PC/SC code. - * Removed the sc-investigate tool. It is now in the separate - gscutils package. + * Removed the sc-investigate tool. It is now in a separate package + available at ftp://ftp.g10code.com/g10code/gscutils/ . + + * [gpg-agent] Fixed logging problem. Noteworthy changes in version 1.9.11 (2004-10-01) diff --git a/g10/ChangeLog b/g10/ChangeLog index 36d5e3314..01bbf649d 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * g10.c (main): Display a bit fat warning that this gpg should not + be used. + + * card-util.c (fetch_url): Disable for gnupg 1.9 + (card_generate_subkey): Ditto. + (card_store_subkey): Ditto. + 2004-09-30 Werner Koch <wk@g10code.com> * gpgv.c (i18n_init): Always use LC_ALL. diff --git a/g10/card-util.c b/g10/card-util.c index 1d2e47ea2..1ff57ade5 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -523,6 +523,7 @@ change_url (void) static int fetch_url(void) { +#if GNUPG_MAJOR_VERSION == 1 int rc; struct agent_card_info_s info; @@ -560,6 +561,9 @@ fetch_url(void) log_error("no URL set on card\n"); return rc; +#else + return 0; +#endif } @@ -577,12 +581,14 @@ change_login (const char *args) for (args++; spacep (args); args++) ; fp = fopen (args, "rb"); +#if GNUPG_MAJOR_VERSION == 1 if (fp && is_secured_file (fileno (fp))) { fclose (fp); fp = NULL; errno = EPERM; } +#endif if (!fp) { tty_printf (_("can't open `%s': %s\n"), args, strerror (errno)); @@ -839,6 +845,7 @@ restore_forced_chv1 (int *forced_chv1) } } +#if GNUPG_MAJOR_VERSION == 1 /* Helper for the key generation/edit functions. */ static void show_card_key_info (struct agent_card_info_s *info) @@ -851,8 +858,9 @@ show_card_key_info (struct agent_card_info_s *info) print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL); tty_printf ("\n"); } +#endif - +#if GNUPG_MAJOR_VERSION == 1 /* Helper for the key generation/edit functions. */ static int replace_existing_key_p (struct agent_card_info_s *info, int keyno) @@ -872,7 +880,7 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno) } return 0; } - +#endif static void @@ -895,10 +903,10 @@ generate_card_keys (const char *serialno) m_free(answer); } #else - /* Does 1.9 have answer_is_yes_no_default() ? */ - want_backup = !(cpr_get_answer_is_yes + want_backup = cpr_get_answer_is_yes ( "cardedit.genkeys.backup_enc", - _("Inhibit off-card backup of encryption key? (y/N) "))); + _("Make off-card backup of encryption key? (Y/n) ")); + /*FIXME: we need answer_is_yes_no_default()*/ #endif if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) @@ -928,8 +936,12 @@ generate_card_keys (const char *serialno) if (check_pin_for_key_operation (&info, &forced_chv1)) goto leave; +#if GNUPG_MAJOR_VERSION == 1 generate_keypair (NULL, info.serialno, want_backup? opt.homedir:NULL); +#else + generate_keypair (NULL, info.serialno); +#endif leave: agent_release_card_info (&info); @@ -942,6 +954,7 @@ generate_card_keys (const char *serialno) int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) { +#if GNUPG_MAJOR_VERSION == 1 struct agent_card_info_s info; int okay = 0; int forced_chv1 = 0; @@ -988,6 +1001,9 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) agent_release_card_info (&info); restore_forced_chv1 (&forced_chv1); return okay; +#else + return 0; +#endif } @@ -997,6 +1013,7 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) int card_store_subkey (KBNODE node, int use) { +#if GNUPG_MAJOR_VERSION == 1 struct agent_card_info_s info; int okay = 0; int rc; @@ -1117,6 +1134,9 @@ card_store_subkey (KBNODE node, int use) free_secret_key (copied_sk); agent_release_card_info (&info); return okay; +#else + return 0; +#endif } diff --git a/g10/g10.c b/g10/g10.c index 915011026..039074f6b 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -2038,6 +2038,10 @@ main( int argc, char **argv ) } #endif + log_info ("WARNING: This version of gpg is not very matured and\n"); + log_info ("WARNING: only intended for testing. Please keep using\n"); + log_info ("WARNING: gpg 1.2.x, 1.3.x or 1.4.x for OpenPGP\n"); + /* FIXME: We should use the lggging to a file only in server mode; however we have not yet implemetyed that thus we try to get away with --batch as indication for logging to file required. */ @@ -2926,9 +2930,9 @@ main( int argc, char **argv ) case aChangePIN: if (!argc) - change_pin (0); + change_pin (0,1); else if (argc == 1) - change_pin ( atoi (*argv)); + change_pin ( atoi (*argv), 1); else wrong_args ("--change-pin [no]"); break; diff --git a/g10/main.h b/g10/main.h index 52bfa7659..939d12ded 100644 --- a/g10/main.h +++ b/g10/main.h @@ -259,7 +259,7 @@ int hash_datafiles( MD_HANDLE md, MD_HANDLE md2, void run_in_pipemode (void); /*-- card-util.c --*/ -void change_pin (int no); +void change_pin (int no, int allow_admin); void card_status (FILE *fp, char *serialnobuf, size_t serialnobuflen); void card_edit (STRLIST commands); diff --git a/po/ChangeLog b/po/ChangeLog index f1396acfc..cc20b6227 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * POTFILES.in: Removed sc-investigate.c + 2004-10-04 Werner Koch <wk@g10code.com> * de.po: Typo fixes. diff --git a/po/POTFILES.in b/po/POTFILES.in index eb4e36c85..9ea9c3fd9 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -15,7 +15,6 @@ jnlib/logging.c kbx/kbxutil.c scd/scdaemon.c -scd/sc-investigate.c scd/app-openpgp.c sm/base64.c diff --git a/po/de.po b/po/de.po index 489164ff6..16d945418 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-10-01 14:54+0200\n" -"PO-Revision-Date: 2004-10-04 13:48+0200\n" +"POT-Creation-Date: 2004-10-22 15:02+0200\n" +"PO-Revision-Date: 2004-10-22 15:02+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -100,12 +100,12 @@ msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: scd/sc-investigate.c:113 sm/gpgsm.c:485 tools/gpgconf.c:85 +#: sm/gpgsm.c:485 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: scd/sc-investigate.c:113 sm/gpgsm.c:485 tools/gpgconf.c:85 +#: sm/gpgsm.c:485 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -126,48 +126,48 @@ msgstr "" msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:446 agent/protect-tool.c:1050 kbx/kbxutil.c:431 -#: scd/scdaemon.c:357 scd/sc-investigate.c:181 sm/gpgsm.c:726 +#: agent/gpg-agent.c:448 agent/protect-tool.c:1050 kbx/kbxutil.c:431 +#: scd/scdaemon.c:357 sm/gpgsm.c:726 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:519 scd/scdaemon.c:437 sm/gpgsm.c:824 +#: agent/gpg-agent.c:521 scd/scdaemon.c:437 sm/gpgsm.c:824 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:524 agent/gpg-agent.c:998 scd/scdaemon.c:442 +#: agent/gpg-agent.c:526 agent/gpg-agent.c:1000 scd/scdaemon.c:442 #: sm/gpgsm.c:828 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:532 scd/scdaemon.c:450 sm/gpgsm.c:835 +#: agent/gpg-agent.c:534 scd/scdaemon.c:450 sm/gpgsm.c:835 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:1031 agent/gpg-agent.c:1065 +#: agent/gpg-agent.c:1033 agent/gpg-agent.c:1067 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: agent/gpg-agent.c:1034 agent/gpg-agent.c:1070 +#: agent/gpg-agent.c:1036 agent/gpg-agent.c:1072 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/gpg-agent.c:1248 +#: agent/gpg-agent.c:1250 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1255 common/simple-pwquery.c:286 sm/call-agent.c:128 +#: agent/gpg-agent.c:1257 common/simple-pwquery.c:286 sm/call-agent.c:128 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1267 common/simple-pwquery.c:298 sm/call-agent.c:140 +#: agent/gpg-agent.c:1269 common/simple-pwquery.c:298 sm/call-agent.c:140 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" @@ -327,7 +327,7 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:555 +#: jnlib/logging.c:621 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" @@ -432,100 +432,87 @@ msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" -#: scd/sc-investigate.c:116 -msgid "Usage: sc-investigate [options] (-h for help)\n" -msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" - -#: scd/sc-investigate.c:118 -msgid "" -"Syntax: sc-investigate [options] [args]]\n" -"Have a look at smartcards\n" -msgstr "" -"Gebrauch: sc-investigate [Optionen] [Argumente]\n" -"Den Inhalt einer Smartcard inspizieren\n" - -#: scd/app-openpgp.c:458 +#: scd/app-openpgp.c:534 #, c-format msgid "failed to store the fingerprint: %s\n" msgstr "Der Fingerprint kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:471 +#: scd/app-openpgp.c:547 #, c-format msgid "failed to store the creation date: %s\n" msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:656 scd/app-openpgp.c:745 +#: scd/app-openpgp.c:732 scd/app-openpgp.c:821 scd/app-openpgp.c:1313 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:662 scd/app-openpgp.c:751 scd/app-openpgp.c:1236 +#: scd/app-openpgp.c:738 scd/app-openpgp.c:827 scd/app-openpgp.c:1319 #, c-format -msgid "prassphrase (CHV%d) is too short; minimum length is %d\n" -msgstr "Die Passphrase (CHV%d) ist zu kurz; Mindestlnge ist %d\n" +msgid "PIN for CHV%d is too short; minimum length is %d\n" +msgstr "Die PIN fr den CHV%d ist zu kurz; Mindestlnge ist %d\n" -#: scd/app-openpgp.c:671 scd/app-openpgp.c:685 scd/app-openpgp.c:761 -#: scd/app-openpgp.c:1245 scd/app-openpgp.c:1259 +#: scd/app-openpgp.c:747 scd/app-openpgp.c:761 scd/app-openpgp.c:837 +#: scd/app-openpgp.c:1328 scd/app-openpgp.c:1342 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:708 +#: scd/app-openpgp.c:784 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:725 +#: scd/app-openpgp.c:801 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:731 +#: scd/app-openpgp.c:807 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:738 +#: scd/app-openpgp.c:814 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" "Noch %d Admin PIN Versuche mglich bevor die Karte dauerhaft gesperrt wird\n" -#: scd/app-openpgp.c:742 +#: scd/app-openpgp.c:818 msgid "Admin PIN" msgstr "Admin PIN" -#: scd/app-openpgp.c:1504 -msgid "can't access CHV Status Bytes - invalid OpenPGP card?\n" -msgstr "" -"Zugriff auf die CHV Status Bytes nicht mglich - ungltige OpenPGP Karte?\n" +#: scd/app-openpgp.c:1301 +#, c-format +msgid "PIN [sigs done: %lu]" +msgstr "PIN [erzeugte signaturen: %lu]" -#: scd/app-openpgp.c:1514 -msgid "can't access Extended Capability Flags - invalid OpenPGP card?\n" -msgstr "" -"Zugriff auf die Extended Capability Flags nicht mglich - ungltige OpenPGP " -"Karte?\n" +#: scd/app-openpgp.c:1587 scd/app-openpgp.c:1597 +#, c-format +msgid "can't access %s - invalid OpenPGP card?\n" +msgstr "Zugriff auf %s nicht mglich - ungltige OpenPGP Karte?\n" -#: scd/app-openpgp.c:1584 +#: scd/app-openpgp.c:1668 #, c-format msgid "error getting serial number: %s\n" msgstr "Fehler beim Holen der Seriennummer: %s\n" -#: scd/app-openpgp.c:1679 +#: scd/app-openpgp.c:1763 #, c-format msgid "failed to store the key: %s\n" msgstr "Fehler beim Speichern des Schlssels: %s\n" -#: scd/app-openpgp.c:1721 +#: scd/app-openpgp.c:1805 msgid "reading the key failed\n" msgstr "Fehler beim Lesen des Schlssels: %s\n" -#: scd/app-openpgp.c:1728 +#: scd/app-openpgp.c:1812 msgid "response does not contain the public key data\n" msgstr "Die Antwort enthlt keine Public Key Daten\n" -#: scd/app-openpgp.c:1736 +#: scd/app-openpgp.c:1820 msgid "response does not contain the RSA modulus\n" msgstr "Die Antwort enthlt keinen RSA Modulus\n" -#: scd/app-openpgp.c:1747 +#: scd/app-openpgp.c:1831 msgid "response does not contain the RSA public exponent\n" msgstr "Die Antwort enthlt keinen ffenlichen RSA Exponent\n" @@ -664,7 +651,7 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" msgid "number of issuers matching: %d\n" msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:403 sm/certchain.c:561 sm/certchain.c:921 sm/decrypt.c:260 +#: sm/certchain.c:403 sm/certchain.c:562 sm/certchain.c:922 sm/decrypt.c:260 #: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" @@ -691,64 +678,64 @@ msgstr "" msgid "checking the CRL failed: %s" msgstr "Die CRL konnte nicht geprft werden: %s" -#: sm/certchain.c:581 +#: sm/certchain.c:582 msgid "no issuer found in certificate" msgstr "Im Zertifikat ist kein Herausgeber enthalten" -#: sm/certchain.c:594 +#: sm/certchain.c:595 #, c-format msgid "certificate with invalid validity: %s" msgstr "Zertifikat mit unzulssiger Gltigkeit: %s" -#: sm/certchain.c:610 +#: sm/certchain.c:611 msgid "certificate not yet valid" msgstr "Das Zertifikat ist noch nicht gltig" -#: sm/certchain.c:623 +#: sm/certchain.c:624 msgid "certificate has expired" msgstr "Das Zertifikat ist abgelaufen" -#: sm/certchain.c:660 +#: sm/certchain.c:661 msgid "selfsigned certificate has a BAD signature" msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:674 +#: sm/certchain.c:675 msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert" -#: sm/certchain.c:685 +#: sm/certchain.c:686 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:690 +#: sm/certchain.c:691 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" -#: sm/certchain.c:705 +#: sm/certchain.c:706 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:731 sm/import.c:166 +#: sm/certchain.c:732 sm/import.c:166 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:743 +#: sm/certchain.c:744 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:776 +#: sm/certchain.c:777 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:799 +#: sm/certchain.c:800 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:822 +#: sm/certchain.c:823 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" @@ -1361,7 +1348,8 @@ msgstr "Optionen zur Einstellung der Konfiguration" msgid "Options useful for debugging" msgstr "Ntzliche Optionen zum Debuggen" -#: tools/gpgconf-comp.c:460 +#: tools/gpgconf-comp.c:460 tools/gpgconf-comp.c:537 tools/gpgconf-comp.c:586 +#: tools/gpgconf-comp.c:639 tools/gpgconf-comp.c:715 msgid "|FILE|write server mode logs to FILE" msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" @@ -1389,6 +1377,25 @@ msgstr "Konfiguration der zu nutzenden LDAP-Server" msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" +#, fuzzy +#~ msgid "passphrase (CHV%d) is too short; minimum length is %d\n" +#~ msgstr "Die Passphrase (CHV%d) ist zu kurz; Mindestlnge ist %d\n" + +#~ msgid "Usage: sc-investigate [options] (-h for help)\n" +#~ msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" + +#~ msgid "" +#~ "Syntax: sc-investigate [options] [args]]\n" +#~ "Have a look at smartcards\n" +#~ msgstr "" +#~ "Gebrauch: sc-investigate [Optionen] [Argumente]\n" +#~ "Den Inhalt einer Smartcard inspizieren\n" + +#~ msgid "can't access Extended Capability Flags - invalid OpenPGP card?\n" +#~ msgstr "" +#~ "Zugriff auf die Extended Capability Flags nicht mglich - ungltige " +#~ "OpenPGP Karte?\n" + #~ msgid "Enter passphrase:" #~ msgstr "Bitte das Mantra (Passphrase) eingeben:" diff --git a/scd/ChangeLog b/scd/ChangeLog index 32fbdf9d9..660865638 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-10-22 Werner Koch <wk@g10code.com> + + * app-openpgp.c (verify_chv3): The minium length for CHV3 is + 8. Changed string to match the other ones. + 2004-10-21 Werner Koch <wk@g10code.com> * app-openpgp.c (do_sign): Replace asprintf by direct allocation. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index f73b4f946..c37308054 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -822,10 +822,10 @@ verify_chv3 (app_t app, return rc; } - if (strlen (pinvalue) < 6) + if (strlen (pinvalue) < 8) { - log_error (_("passphrase (CHV%d) is too short;" - " minimum length is %d\n"), 3, 6); + log_error (_("PIN for CHV%d is too short;" + " minimum length is %d\n"), 3, 8); xfree (pinvalue); return gpg_error (GPG_ERR_BAD_PIN); } diff --git a/tools/Makefile.am b/tools/Makefile.am index 271195c2a..2378df813 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -19,7 +19,7 @@ EXTRA_DIST = Manifest watchgnupg.c \ rfc822parse.c rfc822parse.h gpgparsemail.c \ - addgnupghome + addgnupghome gpgsm-gencert.sh AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am -- cgit v1.2.3 From 8dee43cc0bd54d7a23a7d6dadc760d62ae4e2795 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 19:48:12 +0000 Subject: Releasing 1.9.12 --- ChangeLog | 2 ++ NEWS | 2 +- configure.ac | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a51c9557..4751d4dca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2004-10-22 Werner Koch <wk@g10code.com> + Released 1.9.12. + * Makefile.am (AUTOMAKE_OPTIONS): Set option to create bzip2 tarball. 2004-10-01 Werner Koch <wk@g10code.com> diff --git a/NEWS b/NEWS index b48546877..cbc64d0a2 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.12 +Noteworthy changes in version 1.9.12 (2004-10-22) ------------------------------------------------- * [scdaemon] Partly rewrote the PC/SC code. diff --git a/configure.ac b/configure.ac index 5fd8efe42..d87156be6 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.6" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.12-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.12, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From a2ecb6285e8ed04eb4b650641d3eedddf5d127a5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 22 Oct 2004 19:57:03 +0000 Subject: Post release preparations --- NEWS | 4 ++++ configure.ac | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index cbc64d0a2..2d75cb013 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.13 +------------------------------------------------- + + Noteworthy changes in version 1.9.12 (2004-10-22) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index d87156be6..b0affbbeb 100644 --- a/configure.ac +++ b/configure.ac @@ -20,11 +20,11 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) -min_automake_version="1.7.6" +min_automake_version="1.7.9" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.12, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.13-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From c7b97075aa213a7ac54b8c56679719679816b3fa Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 Nov 2004 17:09:51 +0000 Subject: * b64enc.c: Include stdio.h and string.h * gpgsm.c: New option --prefer-system-dirmngr. * call-dirmngr.c (start_dirmngr): Implement this option. * gpgconf-comp.c <dirmngr>: Add the proxy options. <gpgsm>: Add --prefer-system-daemon. --- TODO | 11 ++--------- common/ChangeLog | 4 ++++ common/b64enc.c | 2 ++ doc/ChangeLog | 4 ++++ doc/debugging.texi | 23 +++++++++++++++++++---- doc/gpg-agent.texi | 2 +- doc/gpgsm.texi | 6 ++++++ jnlib/ChangeLog | 9 +++++++++ jnlib/logging.c | 10 +++++++--- sm/ChangeLog | 5 +++++ sm/call-dirmngr.c | 50 ++++++++++++++++++++++++++++++++------------------ sm/gpgsm.c | 7 ++++++- sm/gpgsm.h | 1 + tools/ChangeLog | 9 +++++++++ tools/gpgconf-comp.c | 24 +++++++++++++++++++++++- tools/watchgnupg.c | 2 +- 16 files changed, 131 insertions(+), 38 deletions(-) diff --git a/TODO b/TODO index a80dfa453..138f9bade 100644 --- a/TODO +++ b/TODO @@ -25,6 +25,8 @@ might want to have an agent context for each service request * sm/certlist.c ** ocspSigning usage is not fully implemented We should review the entire CRL and OCSP validation system. + Okay. This has been fixed in dirmngr when running it in system + daemon mode. * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution @@ -93,12 +95,3 @@ might want to have an agent context for each service request This needs support in libksba/src/cert.c as well as in sm/*.c. Need test certs as well. Same goes for CRL authorityKeyIdentifier. -** Dirmngr: name subordination (nameRelativeToCRLIssuer) - is not yet supported by Dirmngr. - -** Dirmngr: CRL DP URI - The CRL DP shall use an URI for LDAP without a host name. The host - name shall be looked by using the DN in the URI. We don't implement - this yet. Solution is to have a mapping DN->host in our ldapservers - configuration file. - diff --git a/common/ChangeLog b/common/ChangeLog index f0e7bf67a..d5ded50c9 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-11-23 Werner Koch <wk@g10code.com> + + * b64enc.c: Include stdio.h and string.h + 2004-08-18 Werner Koch <wk@g10code.de> * simple-pwquery.c (simple_pwquery): Handle gpg-error style return diff --git a/common/b64enc.c b/common/b64enc.c index edcf6e3ad..5b7a42ab3 100644 --- a/common/b64enc.c +++ b/common/b64enc.c @@ -19,7 +19,9 @@ */ #include <config.h> +#include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <assert.h> diff --git a/doc/ChangeLog b/doc/ChangeLog index 4262865a5..9a9e213a3 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2004-11-05 Werner Koch <wk@g10code.com> + + * debugging.texi (Common Problems): Curses pinentry problem. + 2004-10-22 Werner Koch <wk@g10code.com> * tools.texi (Helper Tools): Document gpgsm-gencert.sh. diff --git a/doc/debugging.texi b/doc/debugging.texi index 9406ba567..b9ae06e2b 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -5,7 +5,7 @@ @node Debugging @chapter How to solve problems -Everone knows that software often does not do what it should do and thus +Everyone 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. @@ -87,9 +87,24 @@ in a standard way and directly available from @command{gpgsm}. @itemize @bullet @item Error code @samp{Not supported} from Dirmngr - Most likely the option @option{enable-ocsp} is active for gpgsm - but Dirmngr's OCSP feature has not been enabled using - @option{allow-ocsp} in @file{dirmngr.conf}. +Most likely the option @option{enable-ocsp} is active for gpgsm +but Dirmngr's OCSP feature has not been enabled using +@option{allow-ocsp} in @file{dirmngr.conf}. + +@item The Curses based Pinentry does not work + +The far most common reason for this is that the environment variable +@code{GPG_TTY} has not been set correctly. Make sure that it has been +set to a real tty devce and not just to @samp{/dev/tty}; +i.e. @samp{GPG_TTY=tty} is plainly wrong; what you want is +@samp{GPG_TTY=`tty`} --- note the back ticks. Also make sure that +this environment variable gets exported, that is you should follow up +the setting with an @samp{export GPG_TTY} (assuming a Bourne style +shell). Even for GUI based Pinentries; you should have set +@code{GPG_TTY}. See the section on installing the @program{gpg-agent} +on how to do it. + + @end itemize diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index f361cbf6b..cccbef02a 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -43,7 +43,7 @@ fi @end smallexample @noindent -You should aleays add the following lines to your @code{.bashrc} or +You should aleways add the following lines to your @code{.bashrc} or whatever initialization file is used for all shell invocations: @smallexample diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 94e6936ad..beedab7b7 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -262,6 +262,12 @@ 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 --prefer-system-dirmngr +@opindex prefer-system-dirmngr +If a system wide @command{dirmngr} is running in daemon mode, first try +to connect to this one. Fallback to a pipe based server if this does +not work. + @item --no-secmem-warning @opindex no-secmem-warning Don't print a warning when the so called "secure memory" can't be used. diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 3c2d6d84a..517cfb73f 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,12 @@ +2004-11-22 Werner Koch <wk@g10code.com> + + * logging.c (log_test_fd): Add test on LOGSTREAM. Reported by + Barry Schwartz. + +2004-11-18 Werner Koch <wk@g10code.com> + + * logging.c: Explicitly include sys/stat.h for the S_I* constants. + 2004-10-21 Werner Koch <wk@g10code.com> * logging.c (do_logv): Use set_log_stream to setup a default. diff --git a/jnlib/logging.c b/jnlib/logging.c index 7a5e1552e..5397a1184 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -35,6 +35,7 @@ #include <time.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/stat.h> #include <sys/un.h> #include <unistd.h> #include <fcntl.h> @@ -411,9 +412,12 @@ log_get_prefix (unsigned int *flags) int log_test_fd (int fd) { - int tmp = fileno (logstream); - if ( tmp != -1 && tmp == fd) - return 1; + if (logstream) + { + int tmp = fileno (logstream); + if ( tmp != -1 && tmp == fd) + return 1; + } if (log_socket != -1 && log_socket == fd) return 1; return 0; diff --git a/sm/ChangeLog b/sm/ChangeLog index 6dd5a28f3..acfa7f3bd 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-11-23 Werner Koch <wk@g10code.com> + + * gpgsm.c: New option --prefer-system-dirmngr. + * call-dirmngr.c (start_dirmngr): Implement this option. + 2004-10-22 Werner Koch <wk@g10code.com> * certreqgen.c (gpgsm_genkey): Remove the NEW from the certificate diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 849b8a04c..c70f56580 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -35,6 +35,8 @@ #include "i18n.h" #include "keydb.h" +/* The name of the socket for a system daemon. */ +#define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket" struct membuf { size_t len; @@ -145,6 +147,7 @@ start_dirmngr (void) int rc; char *infostr, *p; ASSUAN_CONTEXT ctx; + int try_default = 0; if (dirmngr_ctx) return 0; /* fixme: We need a context for each thread or serialize @@ -153,6 +156,12 @@ start_dirmngr (void) to take care of the implicit option sending caching. */ infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO"); + if (opt.prefer_system_dirmngr && !force_pipe_server + &&(!infostr || !*infostr)) + { + infostr = DEFAULT_SOCKET_NAME; + try_default = 1; + } if (!infostr || !*infostr) { const char *pgmname; @@ -197,26 +206,31 @@ start_dirmngr (void) int pid; infostr = xstrdup (infostr); - if ( !(p = strchr (infostr, ':')) || p == infostr) + if (!try_default && *infostr) { - log_error (_("malformed DIRMNGR_INFO environment variable\n")); - xfree (infostr); - force_pipe_server = 1; - return start_dirmngr (); - } - *p++ = 0; - pid = atoi (p); - while (*p && *p != ':') - p++; - prot = *p? atoi (p+1) : 0; - if (prot != 1) - { - log_error (_("dirmngr protocol version %d is not supported\n"), - prot); - xfree (infostr); - force_pipe_server = 1; - return start_dirmngr (); + if ( !(p = strchr (infostr, ':')) || p == infostr) + { + log_error (_("malformed DIRMNGR_INFO environment variable\n")); + xfree (infostr); + force_pipe_server = 1; + return start_dirmngr (); + } + *p++ = 0; + pid = atoi (p); + while (*p && *p != ':') + p++; + prot = *p? atoi (p+1) : 0; + if (prot != 1) + { + log_error (_("dirmngr protocol version %d is not supported\n"), + prot); + xfree (infostr); + force_pipe_server = 1; + return start_dirmngr (); + } } + else + pid = -1; rc = assuan_socket_connect (&ctx, infostr, pid); xfree (infostr); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 0f620c091..c9ce8fd9f 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -107,6 +107,7 @@ enum cmd_and_opt_values { oLCctype, oLCmessages, + oPreferSystemDirmngr, oDirmngrProgram, oProtectToolProgram, oFakedSystemTime, @@ -272,7 +273,8 @@ static ARGPARSE_OPTS opts[] = { { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, - + { oPreferSystemDirmngr,"prefer-system-dirmngr", 0, + N_("use system's dirmngr if available")}, { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, { oForceCRLRefresh, "force-crl-refresh", 0, "@"}, @@ -1047,6 +1049,7 @@ main ( int argc, char **argv) case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break; case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break; case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; + case oPreferSystemDirmngr: opt.prefer_system_dirmngr = 1; break; case oProtectToolProgram: opt.protect_tool_program = pargs.r.ret_str; break; @@ -1333,6 +1336,8 @@ main ( int argc, char **argv) GC_OPT_FLAG_NONE ); printf ("auto-issuer-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE ); + printf ("prefer-system-dirmngr:%lu:\n", + GC_OPT_FLAG_NONE ); } break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 18f50e9fe..faa6e8b5c 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -55,6 +55,7 @@ struct { char *lc_messages; const char *dirmngr_program; + int prefer_system_dirmngr; /* Prefer using a system wide drimngr. */ const char *protect_tool_program; char *outfile; /* name of output file */ diff --git a/tools/ChangeLog b/tools/ChangeLog index 18412753c..9158d7ca5 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,12 @@ +2004-11-23 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c <dirmngr>: Add the proxy options. + <gpgsm>: Add --prefer-system-daemon. + +2004-11-11 Werner Koch <wk@g10code.com> + + * watchgnupg.c (main): Fixed test for read error. + 2004-10-22 Werner Koch <wk@g10code.com> * Makefile.am (bin_SCRIPTS): Add gpgsm-gencert.sh diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 67623ccfd..ec606ea2b 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -628,6 +628,9 @@ static gc_option_t gc_options_gpgsm[] = { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM }, + { "prefer-system-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "use system's dirmngr if available", + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, @@ -731,10 +734,29 @@ static gc_option_t gc_options_dirmngr[] = "dirmngr", "force loading of outdated CRLs", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "HTTP", + GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, + "gnupg", N_("Configuration for HTTP servers") }, + { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "inhibit the use of HTTP", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "|URL|redirect all HTTP requests to URL", + GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, + { "LDAP", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Configuration of LDAP servers to use") }, - { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "inhibit the use of LDAP", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "dirmngr", "|HOST|use HOST for LDAP queries", + GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, + { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "do not use fallback hosts with --ldap-proxy", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "add new servers discovered in CRL distribution points" " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index 7f79f2f18..50f9d7274 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -354,7 +354,7 @@ main (int argc, char **argv) int n; n = read (client->fd, line, sizeof line - 1); - if (n == 1) + if (n < 0) { int save_errno = errno; print_line (client, NULL); /* flush */ -- cgit v1.2.3 From 7d8f27e4224c47864842c790eaff3c65474fbf01 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 24 Nov 2004 10:43:53 +0000 Subject: Add --ignore-http-dp and --ignore-ldap-dp. --- tools/ChangeLog | 5 +++++ tools/gpgconf-comp.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 9158d7ca5..201a496a8 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-11-24 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c <dirmngr>: Add --ignore-http-dp and + --ignore-ldap-dp. + 2004-11-23 Werner Koch <wk@g10code.com> * gpgconf-comp.c <dirmngr>: Add the proxy options. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index ec606ea2b..d2eac7dd9 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -740,6 +740,9 @@ static gc_option_t gc_options_dirmngr[] = { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "inhibit the use of HTTP", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "ignore HTTP CRL distribution points", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|redirect all HTTP requests to URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, @@ -750,6 +753,9 @@ static gc_option_t gc_options_dirmngr[] = { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "inhibit the use of LDAP", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "ignore LDAP CRL distribution points", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "|HOST|use HOST for LDAP queries", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, -- cgit v1.2.3 From 0b135bc6d481dc5dab549d1a357f725add7b9756 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 24 Nov 2004 14:50:20 +0000 Subject: Add dirmngr options to gpgconf and updated the DE translation --- doc/debugging.texi | 2 +- po/de.po | 216 ++++++++++++++++++++++++++------------------------- tools/ChangeLog | 4 +- tools/gpgconf-comp.c | 3 + 4 files changed, 118 insertions(+), 107 deletions(-) diff --git a/doc/debugging.texi b/doc/debugging.texi index b9ae06e2b..49ab70bde 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -101,7 +101,7 @@ i.e. @samp{GPG_TTY=tty} is plainly wrong; what you want is this environment variable gets exported, that is you should follow up the setting with an @samp{export GPG_TTY} (assuming a Bourne style shell). Even for GUI based Pinentries; you should have set -@code{GPG_TTY}. See the section on installing the @program{gpg-agent} +@code{GPG_TTY}. See the section on installing the @command{gpg-agent} on how to do it. diff --git a/po/de.po b/po/de.po index 16d945418..1c85954d8 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-10-22 15:02+0200\n" -"PO-Revision-Date: 2004-10-22 15:02+0200\n" +"POT-Creation-Date: 2004-11-24 15:41+0100\n" +"PO-Revision-Date: 2004-11-24 15:43+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -34,12 +34,12 @@ msgstr "Im Server Modus ausf msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:101 kbx/kbxutil.c:81 scd/scdaemon.c:97 sm/gpgsm.c:315 +#: agent/gpg-agent.c:101 kbx/kbxutil.c:81 scd/scdaemon.c:97 sm/gpgsm.c:317 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:102 kbx/kbxutil.c:82 scd/scdaemon.c:98 sm/gpgsm.c:316 +#: agent/gpg-agent.c:102 kbx/kbxutil.c:82 scd/scdaemon.c:98 sm/gpgsm.c:318 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" @@ -63,7 +63,7 @@ msgstr "Im Vordergrund laufen lassen" msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:112 scd/scdaemon.c:108 sm/gpgsm.c:318 +#: agent/gpg-agent.c:112 scd/scdaemon.c:108 sm/gpgsm.c:320 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" @@ -100,12 +100,12 @@ msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:485 tools/gpgconf.c:85 +#: sm/gpgsm.c:487 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:485 tools/gpgconf.c:85 +#: sm/gpgsm.c:487 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -121,30 +121,30 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:603 +#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:605 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:448 agent/protect-tool.c:1050 kbx/kbxutil.c:431 -#: scd/scdaemon.c:357 sm/gpgsm.c:726 +#: scd/scdaemon.c:357 sm/gpgsm.c:728 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:521 scd/scdaemon.c:437 sm/gpgsm.c:824 +#: agent/gpg-agent.c:521 scd/scdaemon.c:437 sm/gpgsm.c:826 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" #: agent/gpg-agent.c:526 agent/gpg-agent.c:1000 scd/scdaemon.c:442 -#: sm/gpgsm.c:828 +#: sm/gpgsm.c:830 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:534 scd/scdaemon.c:450 sm/gpgsm.c:835 +#: agent/gpg-agent.c:534 scd/scdaemon.c:450 sm/gpgsm.c:837 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" @@ -327,12 +327,12 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:621 +#: jnlib/logging.c:625 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:68 sm/gpgsm.c:226 tools/gpgconf.c:53 +#: kbx/kbxutil.c:68 sm/gpgsm.c:227 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -340,7 +340,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:76 sm/gpgsm.c:261 tools/gpgconf.c:59 +#: kbx/kbxutil.c:76 sm/gpgsm.c:262 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -350,7 +350,7 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:83 sm/gpgsm.c:323 tools/gpgconf.c:64 +#: kbx/kbxutil.c:83 sm/gpgsm.c:325 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" @@ -382,7 +382,7 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:101 sm/gpgsm.c:335 +#: scd/scdaemon.c:101 sm/gpgsm.c:337 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" @@ -529,20 +529,20 @@ msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" -#: sm/call-dirmngr.c:164 +#: sm/call-dirmngr.c:173 msgid "no running dirmngr - starting one\n" msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" -#: sm/call-dirmngr.c:202 +#: sm/call-dirmngr.c:213 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" -#: sm/call-dirmngr.c:214 +#: sm/call-dirmngr.c:225 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "Die Dirmngr Protokollversion %d wird nicht untersttzt\n" -#: sm/call-dirmngr.c:225 +#: sm/call-dirmngr.c:239 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " @@ -788,239 +788,243 @@ msgstr "Schwacher Schl msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:228 +#: sm/gpgsm.c:229 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:229 +#: sm/gpgsm.c:230 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:230 +#: sm/gpgsm.c:231 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:231 +#: sm/gpgsm.c:232 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:232 +#: sm/gpgsm.c:233 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:233 +#: sm/gpgsm.c:234 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:234 +#: sm/gpgsm.c:235 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:236 +#: sm/gpgsm.c:237 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:237 +#: sm/gpgsm.c:238 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:238 +#: sm/gpgsm.c:239 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:240 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:242 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:243 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:244 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:245 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:246 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:246 +#: sm/gpgsm.c:247 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:248 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:248 +#: sm/gpgsm.c:249 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:249 +#: sm/gpgsm.c:250 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:251 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:252 +#: sm/gpgsm.c:253 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:253 +#: sm/gpgsm.c:254 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:263 +#: sm/gpgsm.c:264 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: sm/gpgsm.c:265 +#: sm/gpgsm.c:266 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:267 +#: sm/gpgsm.c:268 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:269 +#: sm/gpgsm.c:270 msgid "assume input is in base-64 format" msgstr "Eingabedaten sind im Basis-64 Format" -#: sm/gpgsm.c:271 +#: sm/gpgsm.c:272 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:273 +#: sm/gpgsm.c:274 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:276 +#: sm/gpgsm.c:277 +msgid "use system's dirmngr if available" +msgstr "Benutze den System Dirmngr when verfgbar" + +#: sm/gpgsm.c:278 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:281 +#: sm/gpgsm.c:283 msgid "check validity using OCSP" msgstr "Die Gltigkeit mittels OCSP prfen" -#: sm/gpgsm.c:284 +#: sm/gpgsm.c:286 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:287 +#: sm/gpgsm.c:289 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:290 +#: sm/gpgsm.c:292 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:294 +#: sm/gpgsm.c:296 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:298 +#: sm/gpgsm.c:300 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:300 +#: sm/gpgsm.c:302 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:306 +#: sm/gpgsm.c:308 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:309 +#: sm/gpgsm.c:311 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:311 +#: sm/gpgsm.c:313 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:314 tools/gpgconf.c:61 +#: sm/gpgsm.c:316 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: sm/gpgsm.c:317 +#: sm/gpgsm.c:319 msgid "don't use the terminal at all" msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:320 +#: sm/gpgsm.c:322 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:321 +#: sm/gpgsm.c:323 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:326 +#: sm/gpgsm.c:328 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:327 +#: sm/gpgsm.c:329 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:328 +#: sm/gpgsm.c:330 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:330 +#: sm/gpgsm.c:332 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:331 +#: sm/gpgsm.c:333 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:332 +#: sm/gpgsm.c:334 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:333 +#: sm/gpgsm.c:335 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:334 +#: sm/gpgsm.c:336 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:338 +#: sm/gpgsm.c:340 msgid "|LEVEL|set the debugging level to LEVEL" msgstr "|NAME|Die Debugstufe auf NAME setzen" -#: sm/gpgsm.c:345 +#: sm/gpgsm.c:347 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:352 +#: sm/gpgsm.c:354 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:358 +#: sm/gpgsm.c:360 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verschlsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:360 +#: sm/gpgsm.c:362 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:362 +#: sm/gpgsm.c:364 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:370 +#: sm/gpgsm.c:372 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -1028,7 +1032,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:373 +#: sm/gpgsm.c:375 msgid "" "@\n" "Examples:\n" @@ -1048,11 +1052,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:488 +#: sm/gpgsm.c:490 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:491 +#: sm/gpgsm.c:493 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -1061,7 +1065,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:498 +#: sm/gpgsm.c:500 msgid "" "\n" "Supported algorithms:\n" @@ -1069,50 +1073,50 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:574 +#: sm/gpgsm.c:576 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:640 +#: sm/gpgsm.c:642 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:656 +#: sm/gpgsm.c:658 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:731 +#: sm/gpgsm.c:733 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1178 +#: sm/gpgsm.c:1181 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1190 +#: sm/gpgsm.c:1193 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1216 +#: sm/gpgsm.c:1219 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1224 +#: sm/gpgsm.c:1227 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1254 +#: sm/gpgsm.c:1257 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1418 +#: sm/gpgsm.c:1423 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1641 sm/gpgsm.c:1674 +#: sm/gpgsm.c:1646 sm/gpgsm.c:1679 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" @@ -1334,26 +1338,26 @@ msgid "Component not found" msgstr "Komponente nicht gefunden" #: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:496 tools/gpgconf-comp.c:561 -#: tools/gpgconf-comp.c:614 tools/gpgconf-comp.c:677 +#: tools/gpgconf-comp.c:614 tools/gpgconf-comp.c:680 msgid "Options controlling the diagnostic output" msgstr "Optionen zur Einstellung Diagnoseausgaben" #: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:509 tools/gpgconf-comp.c:574 -#: tools/gpgconf-comp.c:627 tools/gpgconf-comp.c:700 +#: tools/gpgconf-comp.c:627 tools/gpgconf-comp.c:703 msgid "Options controlling the configuration" msgstr "Optionen zur Einstellung der Konfiguration" #: tools/gpgconf-comp.c:455 tools/gpgconf-comp.c:532 tools/gpgconf-comp.c:581 -#: tools/gpgconf-comp.c:634 tools/gpgconf-comp.c:707 +#: tools/gpgconf-comp.c:637 tools/gpgconf-comp.c:710 msgid "Options useful for debugging" msgstr "Ntzliche Optionen zum Debuggen" #: tools/gpgconf-comp.c:460 tools/gpgconf-comp.c:537 tools/gpgconf-comp.c:586 -#: tools/gpgconf-comp.c:639 tools/gpgconf-comp.c:715 +#: tools/gpgconf-comp.c:642 tools/gpgconf-comp.c:718 msgid "|FILE|write server mode logs to FILE" msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" -#: tools/gpgconf-comp.c:468 tools/gpgconf-comp.c:542 tools/gpgconf-comp.c:647 +#: tools/gpgconf-comp.c:468 tools/gpgconf-comp.c:542 tools/gpgconf-comp.c:650 msgid "Options controlling the security" msgstr "Optionen zur Einstellung der Sicherheit" @@ -1361,19 +1365,23 @@ msgstr "Optionen zur Einstellung der Sicherheit" msgid "Configuration for Keyservers" msgstr "Konfiguration der Schlsselserver" -#: tools/gpgconf-comp.c:690 +#: tools/gpgconf-comp.c:693 msgid "Options controlling the format of the output" msgstr "Optionen zum Einstellen der Ausgabeformate" -#: tools/gpgconf-comp.c:726 +#: tools/gpgconf-comp.c:729 msgid "Options controlling the interactivity and enforcement" msgstr "Optionen zur Einstellung der Interaktivitt und Geltendmachung" -#: tools/gpgconf-comp.c:736 +#: tools/gpgconf-comp.c:739 +msgid "Configuration for HTTP servers" +msgstr "Konfiguration fr HTTP Server" + +#: tools/gpgconf-comp.c:752 msgid "Configuration of LDAP servers to use" msgstr "Konfiguration der zu nutzenden LDAP-Server" -#: tools/gpgconf-comp.c:761 +#: tools/gpgconf-comp.c:789 msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" diff --git a/tools/ChangeLog b/tools/ChangeLog index 201a496a8..ac8d54a47 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,7 +1,7 @@ 2004-11-24 Werner Koch <wk@g10code.com> - * gpgconf-comp.c <dirmngr>: Add --ignore-http-dp and - --ignore-ldap-dp. + * gpgconf-comp.c <dirmngr>: Add --ignore-http-dp, --ignore-ldap-dp + and --ignore-ocsp-service-url. 2004-11-23 Werner Koch <wk@g10code.com> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index d2eac7dd9..8873cdf13 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -790,6 +790,9 @@ static gc_option_t gc_options_dirmngr[] = { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "allow sending OCSP requests", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, + { "ignore-ocsp-servic-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", "ignore certificate contained OCSP service URLs", + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|use OCSP responder at URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, -- cgit v1.2.3 From e0e1585fc80e4ab7642b62459d6d919bddfacf07 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Tue, 30 Nov 2004 09:48:37 +0000 Subject: 2004-11-30 Timo Schulz <ts@g10code.com> * w32-afunix.c: New. AF_UNIX emulation for W32. * w32-afunix.h: Likewise. --- jnlib/ChangeLog | 5 +++ jnlib/w32-afunix.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++ jnlib/w32-afunix.h | 47 ++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 jnlib/w32-afunix.c create mode 100644 jnlib/w32-afunix.h diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 517cfb73f..4c52590f5 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2004-11-30 Timo Schulz <ts@g10code.com> + + * w32-afunix.c: New. AF_UNIX emulation for W32. + * w32-afunix.h: Likewise. + 2004-11-22 Werner Koch <wk@g10code.com> * logging.c (log_test_fd): Add test on LOGSTREAM. Reported by diff --git a/jnlib/w32-afunix.c b/jnlib/w32-afunix.c new file mode 100644 index 000000000..eac4f9560 --- /dev/null +++ b/jnlib/w32-afunix.c @@ -0,0 +1,115 @@ +/* w32-afunix.c + * Copyright (C) 2004 g10 Code GmbH + * + * 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 _WIN32 +#include <stdio.h> +#include <windows.h> +#include <io.h> + +#include "w32-afunix.h" + +int +_w32_close (int fd) +{ + int rc = closesocket (fd); + if (rc && WSAGetLastError () == WSAENOTSOCK) + rc = close (fd); + return rc; +} + + +int +_w32_sock_new (int domain, int type, int proto) +{ + if (domain == AF_UNIX || domain == AF_LOCAL) + domain = AF_INET; + return socket (domain, type, proto); +} + + +int +_w32_sock_connect (int sockfd, struct sockaddr * addr, int addrlen) +{ + struct sockaddr_in myaddr; + struct sockaddr_un * unaddr; + FILE * fp; + int port = 0; + + unaddr = (struct sockaddr_un *)addr; + fp = fopen (unaddr->sun_path, "rb"); + if (!fp) + return -1; + fscanf (fp, "%d", &port); + fclose (fp); + /* XXX: set errno in this case */ + if (port < 0 || port > 65535) + return -1; + + myaddr.sin_family = AF_INET; + myaddr.sin_port = port; + myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + /* we need this later. */ + unaddr->sun_family = myaddr.sin_family; + unaddr->sun_port = myaddr.sin_port; + unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; + + return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); +} + + +int +_w32_sock_bind (int sockfd, struct sockaddr * addr, int addrlen) +{ + if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) + { + struct sockaddr_in myaddr; + struct sockaddr_un * unaddr; + FILE * fp; + int len = sizeof myaddr; + int rc; + + myaddr.sin_port = 0; + myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + rc = bind (sockfd, (struct sockaddr *)&myaddr, len); + if (rc) + return rc; + rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len); + if (rc) + return rc; + unaddr = (struct sockaddr_un *)addr; + fp = fopen (unaddr->sun_path, "wb"); + if (!fp) + return -1; + fprintf (fp, "%d", myaddr.sin_port); + fclose (fp); + + /* we need this later. */ + unaddr->sun_family = myaddr.sin_family; + unaddr->sun_port = myaddr.sin_port; + unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; + + return 0; + } + return bind (sockfd, addr, addrlen); +} + +#endif /*_WIN32*/ diff --git a/jnlib/w32-afunix.h b/jnlib/w32-afunix.h new file mode 100644 index 000000000..1319de5e6 --- /dev/null +++ b/jnlib/w32-afunix.h @@ -0,0 +1,47 @@ +/* w32-afunix.h + * Copyright (C) 2004 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 _WIN32 +#ifndef W32AFUNIX_DEFS_H +#define W32AFUNIX_DEFS_H + +#include <sys/types.h> +#include <windows.h> +#include <unistd.h> + +#define DIRSEP_C '\\' + +#define AF_LOCAL AF_UNIX +/* We need to prefix the structure with a sockaddr_in header so we can + use it later for sendto and recvfrom. */ +struct sockaddr_un +{ + short sun_family; + unsigned short sun_port; + struct in_addr sun_addr; + char sun_path[108-2-4]; /* Path name. */ +}; + +int _w32_close (int fd); +int _w32_sock_new (int domain, int type, int proto); +int _w32_sock_bind (int sockfd, struct sockaddr *addr, int addrlen); +int _w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); + +#endif /*W32AFUNIX_DEFS_H*/ +#endif /*_WIN32*/ -- cgit v1.2.3 From 4a73d94757f61e4aa2d1841535409622c2c473e3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 2 Dec 2004 07:48:09 +0000 Subject: First take on a W32 port --- ChangeLog | 6 + agent/gpg-agent.c | 12 +- common/ChangeLog | 9 + common/Makefile.am | 2 + common/fseeko.c | 1 + common/ftello.c | 1 + common/simple-gettext.c | 437 ++++++++++++++++++++++++++++++ common/simple-pwquery.c | 8 + common/strsep.c | 73 +++++ common/util.h | 4 +- common/w32reg.c | 172 ++++++++++++ configure.ac | 18 +- jnlib/ChangeLog | 4 + jnlib/logging.c | 4 +- jnlib/types.h | 4 + kbx/ChangeLog | 6 + kbx/Makefile.am | 7 +- kbx/keybox-defs.h | 5 +- kbx/keybox-update.c | 2 +- scd/app-p15.c | 691 ++++++++++++++++++++++++++++++++++++++++++++++++ sm/ChangeLog | 7 + sm/gpgsm.c | 44 +-- 22 files changed, 1476 insertions(+), 41 deletions(-) create mode 100644 common/simple-gettext.c create mode 100644 common/strsep.c create mode 100644 common/w32reg.c create mode 100644 scd/app-p15.c diff --git a/ChangeLog b/ChangeLog index 4751d4dca..c95cd9a10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-11-26 Werner Koch <wk@g10code.com> + + * configure.ac: Replace strsep. Replaced use of "target" by + "host". + + 2004-10-22 Werner Koch <wk@g10code.com> Released 1.9.12. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index d3d628766..92af49b7a 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -244,12 +244,12 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) } -/* Setup the debugging. With a LEVEL of NULL only the active debug - flags are propagated to the subsystems. With LEVEL set, a specific - set of debug flags is set; thus overriding all flags already - set. Note that we don't fail here, because it is important to keep - gpg-agent running even after re-reading the options due to a - SIGHUP. */ +/* Setup the debugging. With the global variable DEBUG_LEVEL set to NULL + only the active debug flags are propagated to the subsystems. With + DEBUG_LEVEL set, a specific set of debug flags is set; thus overriding + all flags already set. Note that we don't fail here, because it is + important to keep gpg-agent running even after re-reading the + options due to a SIGHUP. */ static void set_debug (void) { diff --git a/common/ChangeLog b/common/ChangeLog index d5ded50c9..9224055df 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,12 @@ +2004-11-26 Werner Koch <wk@g10code.com> + + * simple-gettext.c: New taken from gnupg 1.3.x + + * simple-pwquery.c [_WIN32]: Include winsock2.h. + (agent_open): Disable it until we have our AF_UNIX implementation + ready. + * fseeko.c, ftello.c: Include sys/types for the sake of W32. + 2004-11-23 Werner Koch <wk@g10code.com> * b64enc.c: Include stdio.h and string.h diff --git a/common/Makefile.am b/common/Makefile.am index 64b565cd2..12fdf7b5e 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -41,6 +41,8 @@ libcommon_a_SOURCES = \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ asshelp.c asshelp.h \ + simple-gettext.c \ + w32reg.c \ signal.c \ dynload.h diff --git a/common/fseeko.c b/common/fseeko.c index f151b09ec..06838e4c4 100644 --- a/common/fseeko.c +++ b/common/fseeko.c @@ -22,6 +22,7 @@ #include <config.h> #endif #include <stdio.h> +#include <sys/types.h> /* Defines off_t under W32. */ int fseeko (FILE *stream, off_t off, int whence) diff --git a/common/ftello.c b/common/ftello.c index e3141900d..6837be959 100644 --- a/common/ftello.c +++ b/common/ftello.c @@ -22,6 +22,7 @@ #include <config.h> #endif #include <stdio.h> +#include <sys/types.h> /* Defines off_t under W32. */ off_t ftello (FILE *stream) diff --git a/common/simple-gettext.c b/common/simple-gettext.c new file mode 100644 index 000000000..4287606e3 --- /dev/null +++ b/common/simple-gettext.c @@ -0,0 +1,437 @@ +/* simple-gettext.c - a simplified version of gettext. + * Copyright (C) 1995, 1996, 1997, 1999 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 simplified version of gettext written by Ulrich Drepper. + * It is used for the Win32 version of GnuPG beucase all the overhead + * of gettext is not needed and we have to do some special Win32 stuff. + * I decided that this is far easier than to tweak gettext for the special + * cases (I tried it but it is a lot of code). wk 15.09.99 + */ + +#include <config.h> +#ifdef USE_SIMPLE_GETTEXT +#if !defined (_WIN32) && !defined (__CYGWIN32__) +#error This file can only be used under Windows or Cygwin32 +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "util.h" + + +/* The magic number of the GNU message catalog format. */ +#define MAGIC 0x950412de +#define MAGIC_SWAPPED 0xde120495 + +/* Revision number of the currently used .mo (binary) file format. */ +#define MO_REVISION_NUMBER 0 + + +/* Header for binary .mo file format. */ +struct mo_file_header +{ + /* The magic number. */ + u32 magic; + /* The revision number of the file format. */ + u32 revision; + /* The number of strings pairs. */ + u32 nstrings; + /* Offset of table with start offsets of original strings. */ + u32 orig_tab_offset; + /* Offset of table with start offsets of translation strings. */ + u32 trans_tab_offset; + /* Size of hashing table. */ + u32 hash_tab_size; + /* Offset of first hashing entry. */ + u32 hash_tab_offset; +}; + +struct string_desc +{ + /* Length of addressed string. */ + u32 length; + /* Offset of string in file. */ + u32 offset; +}; + + +struct overflow_space_s +{ + struct overflow_space_s *next; + u32 idx; + char d[1]; +}; + +struct loaded_domain +{ + char *data; + int must_swap; + u32 nstrings; + char *mapped; /* 0 = not yet mapped, 1 = mapped, + 2 = mapped to + overflow space */ + struct overflow_space_s *overflow_space; + struct string_desc *orig_tab; + struct string_desc *trans_tab; + u32 hash_size; + u32 *hash_tab; +}; + + +static struct loaded_domain *the_domain; + +static __inline__ u32 +do_swap_u32( u32 i ) +{ + return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); +} + +#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) ) + + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + +/* The so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ + +static __inline__ ulong +hash_string( const char *str_param ) +{ + unsigned long int hval, g; + const char *str = str_param; + + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} + + +static struct loaded_domain * +load_domain( const char *filename ) +{ + FILE *fp; + size_t size; + struct stat st; + struct mo_file_header *data = NULL; + struct loaded_domain *domain = NULL; + size_t to_read; + char *read_ptr; + + fp = fopen( filename, "rb" ); + if( !fp ) + return NULL; /* can't open the file */ + /* we must know about the size of the file */ + if( fstat( fileno(fp ), &st ) + || (size = (size_t)st.st_size) != st.st_size + || size < sizeof (struct mo_file_header) ) { + fclose( fp ); + return NULL; + } + + data = malloc( size ); + if( !data ) { + fclose( fp ); + return NULL; /* out of memory */ + } + + to_read = size; + read_ptr = (char *) data; + do { + long int nb = fread( read_ptr, 1, to_read, fp ); + if( nb < to_read ) { + fclose (fp); + free(data); + return NULL; /* read error */ + } + read_ptr += nb; + to_read -= nb; + } while( to_read > 0 ); + fclose (fp); + + /* Using the magic number we can test whether it really is a message + * catalog file. */ + if( data->magic != MAGIC && data->magic != MAGIC_SWAPPED ) { + /* The magic number is wrong: not a message catalog file. */ + free( data ); + return NULL; + } + + domain = calloc( 1, sizeof *domain ); + if( !domain ) { + free( data ); + return NULL; + } + domain->data = (char *) data; + domain->must_swap = data->magic != MAGIC; + + /* Fill in the information about the available tables. */ + switch( SWAPIT(domain->must_swap, data->revision) ) { + case 0: + domain->nstrings = SWAPIT(domain->must_swap, data->nstrings); + domain->orig_tab = (struct string_desc *) + ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset)); + domain->trans_tab = (struct string_desc *) + ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset)); + domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size); + domain->hash_tab = (u32 *) + ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset)); + break; + + default: /* This is an invalid revision. */ + free( data ); + free( domain ); + return NULL; + } + + /* Allocate an array to keep track of code page mappings. */ + domain->mapped = calloc( 1, domain->nstrings ); + if( !domain->mapped ) { + free( data ); + free( domain ); + return NULL; + } + + return domain; +} + + +/**************** + * Set the file used for translations. Pass a NULL to disable + * translation. A new filename may be set at anytime. + * WARNING: After changing the filename you should not access any data + * retrieved by gettext(). + */ +int +set_gettext_file( const char *filename ) +{ + struct loaded_domain *domain = NULL; + + if( filename && *filename ) { + if( filename[0] == '/' +#ifdef HAVE_DRIVE_LETTERS + || ( isalpha(filename[0]) + && filename[1] == ':' + && (filename[2] == '/' || filename[2] == '\\') ) +#endif + ) { + /* absolute path - use it as is */ + domain = load_domain( filename ); + } + else { /* relative path - append ".mo" and get dir from the environment */ + char *buf = NULL; + char *dir; + char *p; + + dir = read_w32_registry_string( NULL, + "Control Panel\\Mingw32\\NLS", + "MODir" ); + if( dir && (buf=malloc(strlen(dir)+strlen(filename)+1+3+1)) ) { + strcpy(stpcpy(stpcpy(stpcpy( buf, dir),"\\"), filename),".mo"); + /* Better make sure that we don't mix forward and + backward slashes. It seems that some Windoze + versions don't accept this. */ + for (p=buf; *p; p++) + { + if (*p == '/') + *p = '\\'; + } + domain = load_domain( buf ); + free(buf); + } + free(dir); + } + if( !domain ) + return -1; + } + + if( the_domain ) { + struct overflow_space_s *os, *os2; + free( the_domain->data ); + free( the_domain->mapped ); + for (os=the_domain->overflow_space; os; os = os2) { + os2 = os->next; + free (os); + } + free( the_domain ); + the_domain = NULL; + } + the_domain = domain; + return 0; +} + + +static const char* +get_string( struct loaded_domain *domain, u32 idx ) +{ + struct overflow_space_s *os; + char *p; + + p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset); + if (!domain->mapped[idx]) + { + size_t plen, buflen; + char *buf; + + domain->mapped[idx] = 1; + + plen = strlen (p); + buf = utf8_to_native (p, plen, -1); + buflen = strlen (buf); + if (buflen <= plen) + strcpy (p, buf); + else + { + /* There is not enough space for the translation - store it + in the overflow_space else and mark that in the mapped + array. Because we expect that this won't happen too + often, we use a simple linked list. */ + os = malloc (sizeof *os + buflen); + if (os) + { + os->idx = idx; + strcpy (os->d, buf); + os->next = domain->overflow_space; + domain->overflow_space = os; + p = os->d; + } + else + p = "ERROR in GETTEXT MALLOC"; + } + xfree (buf); + } + else if (domain->mapped[idx] == 2) + { /* We need to get the string from the overflow_space. */ + for (os=domain->overflow_space; os; os = os->next) + if (os->idx == idx) + return (const char*)os->d; + p = "ERROR in GETTEXT\n"; + } + return (const char*)p; +} + + + +const char * +gettext( const char *msgid ) +{ + struct loaded_domain *domain; + size_t act = 0; + size_t top, bottom; + + if( !(domain = the_domain) ) + goto not_found; + + /* Locate the MSGID and its translation. */ + if( domain->hash_size > 2 && domain->hash_tab ) { + /* Use the hashing table. */ + u32 len = strlen (msgid); + u32 hash_val = hash_string (msgid); + u32 idx = hash_val % domain->hash_size; + u32 incr = 1 + (hash_val % (domain->hash_size - 2)); + u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]); + + if ( !nstr ) /* Hash table entry is empty. */ + goto not_found; + + if( SWAPIT(domain->must_swap, + domain->orig_tab[nstr - 1].length) == len + && !strcmp( msgid, + domain->data + SWAPIT(domain->must_swap, + domain->orig_tab[nstr - 1].offset)) ) + return get_string( domain, nstr - 1 ); + + for(;;) { + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + + nstr = SWAPIT(domain->must_swap, domain->hash_tab[idx]); + if( !nstr ) + goto not_found; /* Hash table entry is empty. */ + + if ( SWAPIT(domain->must_swap, + domain->orig_tab[nstr - 1].length) == len + && !strcmp (msgid, + domain->data + SWAPIT(domain->must_swap, + domain->orig_tab[nstr - 1].offset))) + return get_string( domain, nstr-1 ); + } + /* NOTREACHED */ + } + + /* Now we try the default method: binary search in the sorted + array of messages. */ + bottom = 0; + top = domain->nstrings; + while( bottom < top ) { + int cmp_val; + + act = (bottom + top) / 2; + cmp_val = strcmp(msgid, domain->data + + SWAPIT(domain->must_swap, + domain->orig_tab[act].offset)); + if (cmp_val < 0) + top = act; + else if (cmp_val > 0) + bottom = act + 1; + else + return get_string( domain, act ); + } + + not_found: + return msgid; +} + +#if 0 + unsigned int cp1, cp2; + + cp1 = GetConsoleCP(); + cp2 = GetConsoleOutputCP(); + + log_info("InputCP=%u OutputCP=%u\n", cp1, cp2 ); + + if( !SetConsoleOutputCP( 1252 ) ) + log_info("SetConsoleOutputCP failed: %s\n", w32_strerror (0)); + + cp1 = GetConsoleCP(); + cp2 = GetConsoleOutputCP(); + log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 ); +#endif + +#endif /* USE_SIMPLE_GETTEXT */ diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 0bc8128e1..fab6306fa 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -31,8 +31,12 @@ #include <string.h> #include <errno.h> #include <unistd.h> +#ifdef _WIN32 +#include <winsock2.h> +#else #include <sys/socket.h> #include <sys/un.h> +#endif #ifdef HAVE_LOCALE_H #include <locale.h> #endif @@ -255,6 +259,9 @@ agent_send_all_options (int fd) static int agent_open (int *rfd) { +#ifdef _WIN32 + return SPWQ_NO_AGENT; /* FIXME */ +#else int rc; int fd; char *infostr, *p; @@ -346,6 +353,7 @@ agent_open (int *rfd) *rfd = fd; return 0; +#endif } diff --git a/common/strsep.c b/common/strsep.c new file mode 100644 index 000000000..af3f02e07 --- /dev/null +++ b/common/strsep.c @@ -0,0 +1,73 @@ +/* strsep.c - Replacement for strsep(). + * 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> +#include <string.h> + +/* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c */ +#warning need to get the correct copyright years from glibc +char * +strsep (char **stringp, const char *delim) +{ + char *begin, *end; + + begin = *stringp; + if (begin == NULL) + return NULL; + + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if (delim[0] == '\0' || delim[1] == '\0') + { + char ch = delim[0]; + + if (ch == '\0') + end = NULL; + else + { + if (*begin == ch) + end = begin; + else if (*begin == '\0') + end = NULL; + else + end = strchr (begin + 1, ch); + } + } + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); + + if (end) + { + /* Terminate the token and set *STRINGP past NUL character. */ + *end++ = '\0'; + *stringp = end; + } + else + /* No more delimiters; this is the last token. */ + *stringp = NULL; + + return begin; +} + diff --git a/common/util.h b/common/util.h index b9ffe6562..fad7d38cc 100644 --- a/common/util.h +++ b/common/util.h @@ -144,7 +144,9 @@ int is_file_compressed (const char *s, int *ret_rc); int vasprintf (char **result, const char *format, va_list args); int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3); #endif - +#ifndef HAVE_STRSEP +char *strsep (char **stringp, const char *delim); +#endif /*-- some macros to replace ctype ones and avoid locale problems --*/ diff --git a/common/w32reg.c b/common/w32reg.c new file mode 100644 index 000000000..19fb613e7 --- /dev/null +++ b/common/w32reg.c @@ -0,0 +1,172 @@ +/* w32reg.c - MS-Windows Registry access + * Copyright (C) 1999, 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> +#if defined (_WIN32) || defined (__CYGWIN32__) + /* This module is only used in this environment */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <windows.h> + +#include "util.h" + +static HKEY +get_root_key(const char *root) +{ + HKEY root_key; + + if( !root ) + root_key = HKEY_CURRENT_USER; + else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) ) + root_key = HKEY_CLASSES_ROOT; + else if( !strcmp( root, "HKEY_CURRENT_USER" ) ) + root_key = HKEY_CURRENT_USER; + else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) ) + root_key = HKEY_LOCAL_MACHINE; + else if( !strcmp( root, "HKEY_USERS" ) ) + root_key = HKEY_USERS; + else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) ) + root_key = HKEY_PERFORMANCE_DATA; + else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) ) + root_key = HKEY_CURRENT_CONFIG; + else + return NULL; + + return root_key; +} + + +/**************** + * Return a string from the Win32 Registry or NULL in case of + * error. Caller must release the return value. A NULL for root + * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. + * NOTE: The value is allocated with a plain malloc() - use free() and not + * the usual m_free()!!! + */ +char * +read_w32_registry_string( const char *root, const char *dir, const char *name ) +{ + HKEY root_key, key_handle; + DWORD n1, nbytes, type; + char *result = NULL; + + if ( !(root_key = get_root_key(root) ) ) + return NULL; + + if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) + { + if (root) + return NULL; /* no need for a RegClose, so return direct */ + /* It seems to be common practise to fall back to HLM. */ + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + return NULL; /* still no need for a RegClose, so return direct */ + } + + nbytes = 1; + if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) + goto leave; + result = malloc( (n1=nbytes+1) ); + if( !result ) + goto leave; + if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) { + free(result); result = NULL; + goto leave; + } + result[nbytes] = 0; /* make sure it is really a string */ + if (type == REG_EXPAND_SZ && strchr (result, '%')) { + char *tmp; + + n1 += 1000; + tmp = malloc (n1+1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) { + free (tmp); + n1 = nbytes; + tmp = malloc (n1 + 1); + if (!tmp) + goto leave; + nbytes = ExpandEnvironmentStrings (result, tmp, n1); + if (nbytes && nbytes > n1) { + free (tmp); /* oops - truncated, better don't expand at all */ + goto leave; + } + tmp[nbytes] = 0; + free (result); + result = tmp; + } + else if (nbytes) { /* okay, reduce the length */ + tmp[nbytes] = 0; + free (result); + result = malloc (strlen (tmp)+1); + if (!result) + result = tmp; + else { + strcpy (result, tmp); + free (tmp); + } + } + else { /* error - don't expand */ + free (tmp); + } + } + + leave: + RegCloseKey( key_handle ); + return result; +} + + +int +write_w32_registry_string(const char *root, const char *dir, + const char *name, const char *value) +{ + HKEY root_key, reg_key; + + if ( !(root_key = get_root_key(root) ) ) + return -1; + + if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, &reg_key ) + != ERROR_SUCCESS ) + return -1; + + if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) { + if ( RegCreateKey( root_key, name, &reg_key ) != ERROR_SUCCESS ) { + RegCloseKey(reg_key); + return -1; + } + if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, + strlen( value ) ) != ERROR_SUCCESS ) { + RegCloseKey(reg_key); + return -1; + } + } + + RegCloseKey( reg_key ); + + return 0; +} + +#endif /* __MINGW32__ || __CYGWIN32__ */ diff --git a/configure.ac b/configure.ac index b0affbbeb..8b6bc4d73 100644 --- a/configure.ac +++ b/configure.ac @@ -343,7 +343,7 @@ GNUPG_CHECK_DOCBOOK_TO_TEXI try_gettext=yes have_dosish_system=no -case "${target}" in +case "${host}" in *-*-mingw32*) # special stuff for Windoze NT ac_cv_have_dev_random=no @@ -660,7 +660,7 @@ fi AC_SUBST(GPGKEYS_MAILTO) -case "${target}" in +case "${host}" in *-*-mingw32*) PRINTABLE_OS_NAME="MingW32" ;; @@ -782,7 +782,7 @@ AC_REPLACE_FUNCS(mkdtemp) AC_REPLACE_FUNCS(fseeko ftello) AC_REPLACE_FUNCS(isascii) AC_REPLACE_FUNCS(putc_unlocked) - +AC_REPLACE_FUNCS(strsep) @@ -970,7 +970,7 @@ GNUPG_CHECK_GNUMAKE # add some extra libs here so that previous tests don't fail for # mysterious reasons - the final link step should bail out. -case "${target}" in +case "${host}" in *-*-mingw32*) W32LIBS="-lwsock32" ;; @@ -1038,6 +1038,14 @@ if test "$build_agent_only" = "yes" ; then build_scdaemon=no fi +# We don't yet want to build some parts for W32 +case "${host}" in + *-mingw32*) + build_gpg=no + ;; +esac + + AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") @@ -1140,7 +1148,7 @@ AC_OUTPUT echo " GnuPG v${VERSION} has been configured as follows: - Platform: $PRINTABLE_OS_NAME ($target) + Platform: $PRINTABLE_OS_NAME ($host) OpenPGP: $build_gpg S/MIME: $build_gpgsm diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 4c52590f5..5ca33d5fb 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2004-11-26 Werner Koch <wk@g10code.com> + + * logging.c [_WIN32]: Don't include socket headers. + 2004-11-30 Timo Schulz <ts@g10code.com> * w32-afunix.c: New. AF_UNIX emulation for W32. diff --git a/jnlib/logging.c b/jnlib/logging.c index 5397a1184..960d816eb 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -34,9 +34,11 @@ #include <errno.h> #include <time.h> #include <sys/types.h> -#include <sys/socket.h> #include <sys/stat.h> +#ifndef _WIN32 +#include <sys/socket.h> #include <sys/un.h> +#endif #include <unistd.h> #include <fcntl.h> #include <assert.h> diff --git a/jnlib/types.h b/jnlib/types.h index 230d1502f..934b7a6ee 100644 --- a/jnlib/types.h +++ b/jnlib/types.h @@ -42,7 +42,11 @@ #ifndef HAVE_BYTE_TYPEDEF #undef byte /* maybe there is a macro with this name */ +/* Windows typedefs byte in the rpc headers. Avoid warning about + double definition. */ +#if !(defined(_WIN32) && defined(cbNDRContext)) typedef unsigned char byte; +#endif #define HAVE_BYTE_TYPEDEF #endif diff --git a/kbx/ChangeLog b/kbx/ChangeLog index c10ea126a..ea5b9dbd1 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,9 @@ +2004-11-26 Werner Koch <wk@g10code.com> + + * Makefile.am (kbxutil_LDADD): Add ../common/libcommon.a + + * keybox-defs.h: Include stringhelp.h. + 2004-09-30 Werner Koch <wk@g10code.com> * kbxutil.c (i18n_init): Always use LC_ALL. diff --git a/kbx/Makefile.am b/kbx/Makefile.am index 0b35587cb..ea8436d72 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -43,11 +43,8 @@ common_sources = \ libkeybox_a_SOURCES = $(common_sources) +# Note that libcommon is only required to resolve the LIBOBJS. kbxutil_SOURCES = kbxutil.c $(common_sources) kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ - -lgpg-error @LIBINTL@ - - - - + -lgpg-error $(LIBINTL) ../common/libcommon.a diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 4906a386e..5724b85a0 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -31,8 +31,11 @@ /* We include the type defintions from jnlib instead of defining our owns here. This will not allow us build KBX in a standalone way - but tehre is currently no need for it anyway. */ + but there is currently no need for it anyway. Same goes for + stringhelp.h which for example provides a replacement for stpcpy - + fixme: Better the LIBOBJ mechnism. */ #include "../jnlib/types.h" +#include "../jnlib/stringhelp.h" #include "keybox.h" diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index 16955502f..eabaa1db2 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -66,7 +66,7 @@ create_tmp_file (const char *template, strcpy (tmpfname + strlen (template)-4, EXTSEP_S "tmp"); } else - { /* file does not end with kbx; hmmm */ + { /* File does not end with kbx; hmmm. */ bakfname = xtrymalloc ( strlen (template) + 5); if (!bakfname) return gpg_error (gpg_err_code_from_errno (errno)); diff --git a/scd/app-p15.c b/scd/app-p15.c new file mode 100644 index 000000000..af2eed465 --- /dev/null +++ b/scd/app-p15.c @@ -0,0 +1,691 @@ +/* app-p15.c - The pkcs#15 card application. + * 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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <time.h> + +#include "scdaemon.h" + +#include "iso7816.h" +#include "app-common.h" +#include "tlv.h" + + +/* Context local to this application. */ +struct app_local_s +{ + unsigned short home_df; /* The home DF. Note, that we don't yet + support a multilevel hierachy. Thus we + assume this is directly below the MF. */ + struct + { + unsigned short private_keys; + unsigned short public_keys; + unsigned short trusted_public_keys; + unsigned short secret_keys; + unsigned short certificates; + unsigned short trusted_certificates; + unsigned short useful_certificates; + unsigned short data_objects; + unsigned short auth_objects; + } odf; + + +}; + + + + +/* Do a select and a read for the file with EFID. EFID is a + desctription of the EF to be used with error messages. On success + BUFFER and BUFLEN contain the entire content of the EF. The caller + must free BUFFER but only on success. */ +static gpg_error_t +select_and_read_binary (int slot, unsigned short efid, const char *efid_desc, + unsigned char **buffer, size_t *buflen) +{ + gpg_error_t err; + + err = iso7816_select_file (slot, efid, 0, NULL, NULL); + if (err) + { + log_error ("error selecting %s (0x%04X): %s\n", + efid_desc, efid, gpg_strerror (err)); + return err; + } + err = iso7816_read_binary (slot, 0, 0, buffer, buflen); + if (err) + { + log_error ("error reading %s (0x%04X): %s\n", + efid_desc, efid, gpg_strerror (err)); + return err; + } + return 0; +} + + + + +/* Read and parse the Object Directory File and store away the + pointers. + + Example of such a file: + + A0 06 30 04 04 02 60 34 = Private Keys + A4 06 30 04 04 02 60 35 = Certificates + A5 06 30 04 04 02 60 36 = TrustedCertificates + A7 06 30 04 04 02 60 37 = DataObjects + A8 06 30 04 04 02 60 38 = AuthObjects + + These are all PathOrObjects using the path CHOICE. The paths are + octet strings of length 2. Using this Path CHOICE is recommended, + so we only implement that for now. +*/ +static gpg_error_t +read_ef_odf (app_t app) +{ + gpg_error_t err; + unsigned char *buffer, *p; + size_t buflen; + unsigned short value; + + err = select_and_read_binary (app->slot, 0x5031, "ODF", &buffer, &buflen); + if (err) + return err; + + if (len < 8) + { + log_error ("error: ODF too short\n"); + xfree (buffer); + return gpg_error (GPG_ERR_INV_OBJ); + } + for (p=buffer; buflen >= 8; p += 8, buflen -= 8) + { + if ( (p[0] & 0xf0) != 0xA0 + || memcmp (p+1, "\x06\x30\x04\x04\x02", 5) ) + { + log_error ("ODF format is not supported by us\n"); + xfree (buffer); + return gpg_error (GPG_ERR_INV_OBJ); + } + switch ((p[0] & 0x0f)) + { + case 0: value = app->app_local->odf.private_keys; break; + case 1: value = app->app_local->odf.public_keys; break; + case 2: value = app->app_local->odf.trusted_public_keys; break; + case 3: value = app->app_local->odf.secret_keys; break; + case 4: value = app->app_local->odf.certificates; break; + case 5: value = app->app_local->odf.trusted_certificates; break; + case 6: value = app->app_local->odf.useful_certificates; break; + case 7: value = app->app_local->odf.data_objects; break; + case 8: value = app->app_local->odf.auth_objects; break; + default: value = 0; break; + } + if (value) + { + log_error ("duplicate object type %d in ODF ignored\n",(p[0)&0x0f)); + continue; + } + value = ((p[6] << 8) | p[7]); + switch ((p[0] & 0x0f)) + { + case 0: app->app_local->odf.private_keys = value; break; + case 1: app->app_local->odf.public_keys = value; break; + case 2: app->app_local->odf.trusted_public_keys = value; break; + case 3: app->app_local->odf.secret_keys = value; break; + case 4: app->app_local->odf.certificates = value; break; + case 5: app->app_local->odf.trusted_certificates = value; break; + case 6: app->app_local->odf.useful_certificates = value; break; + case 7: app->app_local->odf.data_objects = value; break; + case 8: app->app_local->odf.auth_objects = value; break; + default: + log_error ("unknown object type %d in ODF ignored\n", (p[0)&0x0f)); + } + } + + if (buflen) + log_info ("warning: %u bytes of garbage detected at end of ODF\n", buflen); + + xfree (buffer); + return 0; +} + + + +/* Read and parse the Private Key Directory Files. */ +/* + 6034 (privatekeys) + +30 33 30 11 0C 08 53 4B 2E 43 48 2E 44 53 03 02 030...SK.CH.DS.. +06 80 04 01 07 30 0C 04 01 01 03 03 06 00 40 02 .....0........@. +02 00 50 A1 10 30 0E 30 08 04 06 3F 00 40 16 00 ..P..0.0...?.@.. +50 02 02 04 00 30 33 30 11 0C 08 53 4B 2E 43 48 P....030...SK.CH +2E 4B 45 03 02 06 80 04 01 0A 30 0C 04 01 0C 03 .KE.......0..... +03 06 44 00 02 02 00 52 A1 10 30 0E 30 08 04 06 ..D....R..0.0... +3F 00 40 16 00 52 02 02 04 00 30 34 30 12 0C 09 ?.@..R....040... +53 4B 2E 43 48 2E 41 55 54 03 02 06 80 04 01 0A SK.CH.AUT....... +30 0C 04 01 0D 03 03 06 20 00 02 02 00 51 A1 10 0....... ....Q.. +30 0E 30 08 04 06 3F 00 40 16 00 51 02 02 04 00 0.0...?.@..Q.... +30 37 30 15 0C 0C 53 4B 2E 43 48 2E 44 53 2D 53 070...SK.CH.DS-S +50 58 03 02 06 80 04 01 0A 30 0C 04 01 02 03 03 PX.......0...... +06 20 00 02 02 00 53 A1 10 30 0E 30 08 04 06 3F . ....S..0.0...? +00 40 16 00 53 02 02 04 00 00 00 00 00 00 00 00 .@..S........... +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + +*/ +static gpg_error_t +read_ef_prkdf (app_t app) +{ + + +} + +/* Read and parse the Public Key Directory Files. */ +static gpg_error_t +read_ef_pukdf (app_t app) +{ + + +} + + +/* Read and parse the Certificate Directory Files. */ +/* + +6035 (certificates) + +30 2A 30 15 0C 0C 43 5F 58 35 30 39 2E 43 48 2E 0*0...C_X509.CH. +44 53 03 02 06 40 04 01 0A 30 03 04 01 01 A1 0C DS...@...0...... +30 0A 30 08 04 06 3F 00 40 16 C0 00 30 2A 30 15 0.0...?.@...0*0. +0C 0C 43 5F 58 35 30 39 2E 43 48 2E 4B 45 03 02 ..C_X509.CH.KE.. +06 40 04 01 0A 30 03 04 01 0C A1 0C 30 0A 30 08 .@...0......0.0. +04 06 3F 00 40 16 C2 00 30 2B 30 16 0C 0D 43 5F ..?.@...0+0...C_ +58 35 30 39 2E 43 48 2E 41 55 54 03 02 06 40 04 X509.CH.AUT...@. +01 0A 30 03 04 01 0D A1 0C 30 0A 30 08 04 06 3F ..0......0.0...? +00 40 16 C5 00 30 2E 30 19 0C 10 43 5F 58 35 30 .@...0.0...C_X50 +39 2E 43 48 2E 44 53 2D 53 50 58 03 02 06 40 04 9.CH.DS-SPX...@. +01 0A 30 03 04 01 02 A1 0C 30 0A 30 08 04 06 3F ..0......0.0...? +00 40 16 C1 20 00 00 00 00 00 00 00 00 00 00 00 .@.. ........... +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + + 0 42: SEQUENCE { + 2 21: SEQUENCE { -- commonObjectAttributes + 4 12: UTF8String 'C_X509.CH.DS' + 18 2: BIT STRING 6 unused bits + : '10'B (bit 1) + 22 1: OCTET STRING 0A + : } + 25 3: SEQUENCE { -- commonCertificateAttributes + 27 1: OCTET STRING 01 + : } + 30 12: [1] { -- certAttributes + 32 10: SEQUENCE { + 34 8: SEQUENCE { + 36 6: OCTET STRING 3F 00 40 16 C0 00 + : } + : } + : } + : } + + + +6036 (trustedcertificates) + +30 35 30 06 03 02 00 00 04 00 30 16 04 14 2D 36 050.......0...-6 +33 39 33 33 39 34 30 33 39 37 37 36 34 30 31 32 3933940397764012 +31 36 A1 13 30 11 30 0F 04 06 3F 00 40 16 C7 08 16..0.0...?.@... +02 01 00 80 02 02 29 30 35 30 06 03 02 00 00 04 ......)050...... +00 30 16 04 14 2D 34 30 31 39 30 35 32 37 32 36 .0...-4019052726 +38 30 31 36 39 33 34 39 32 A1 13 30 11 30 0F 04 801693492..0.0.. +06 3F 00 40 16 C7 0E 02 01 00 80 02 04 12 30 34 .?.@..........04 +30 06 03 02 00 00 04 00 30 15 04 13 37 39 36 33 0.......0...7963 +32 38 33 36 35 30 37 36 36 34 38 32 39 36 30 A1 283650766482960. +13 30 11 30 0F 04 06 3F 00 40 16 C0 08 02 01 00 .0.0...?.@...... +80 02 04 11 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + + 0 53: SEQUENCE { + 2 6: SEQUENCE { + 4 2: BIT STRING + : '00000000'B + : Error: Spurious zero bits in bitstring. + 8 0: OCTET STRING + : Error: Object has zero length. + : } + 10 22: SEQUENCE { + 12 20: OCTET STRING '-6393394039776401216' + : } + 34 19: [1] { + 36 17: SEQUENCE { + 38 15: SEQUENCE { + 40 6: OCTET STRING 3F 00 40 16 C7 08 + 48 1: INTEGER 0 -- index + 51 2: [0] 02 29 -- length + : } + : } + : } + : } + + +*/ +static gpg_error_t +read_ef_cdf (app_t app) +{ + gpg_error_t err; + unsigned char *buffer = NULL; + size_t buflen; + unsigned short value; + unsigned short fid; + const unsigned char *p; + size_t n, objlen, hdrlen; + int class, tag, constructed, ndef; + + fid = app->app_local->odf.certificates; + if (!fid) + return 0; /* No certificates. */ + + err = select_and_read_binary (app->slot, fid, "CDF", &buffer, &buflen); + if (err) + return err; + + p = buffer; + n = buflen; + + /* Loop over the records. We stop as soon as we detect a new record + starting with 0x00 or 0xff as these values are commonly used to pad + the the read datablocks and are no valid ASN.1 encoding. */ + while (n && *p && *p == 0xff) + { + const unsigned char *pp; + size_t nn; + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > n || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + log_error ("error parsing CDF record: %s\n", gpg_strerror (err)); + goto leave; + } + pp = p; + nn = objlen; + p += objlen; + n -= objlen; + + /* Skip the commonObjectAttributes. */ + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + log_error ("error parsing CDF record: %s - skipped\n", + gpg_strerror (err)); + continue; + } + pp += objlen; + nn -= objlen; + + /* Skip the commonCertificateAttributes. */ + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + log_error ("error parsing CDF record: %s - skipped\n", + gpg_strerror (err)); + continue; + } + pp += objlen; + nn -= objlen; + + /* FIXME: Check that this is a reference to a certificate. */ + + + } + + + leave: + xfree (buffer); + return err; +} + +/* Read and parse Authentication Object Directory Files. */ +static gpg_error_t +read_ef_aodf (app_t app) +{ + +} + + +/* 6037 (dataobjects) + +30 1E 30 0B 0C 06 45 46 2E 47 44 4F 04 01 0A 30 0.0...EF.GDO...0 +02 0C 00 A1 0B 30 09 04 04 3F 00 2F 02 80 01 0E .....0...?./.... +30 30 30 18 0C 0F 64 69 73 70 6C 61 79 20 6D 65 000...display me +73 73 61 67 65 03 02 06 C0 04 01 0A 30 05 0C 03 ssage.......0... +42 53 53 A1 0D 30 0B 04 06 3F 00 40 16 D0 00 80 BSS..0...?.@.... +01 20 30 2B 30 0C 0C 03 53 53 4F 03 02 06 C0 04 . 0+0...SSO..... +01 0A 30 0B 0C 09 53 61 66 65 47 75 61 72 64 A1 ..0...SafeGuard. +0E 30 0C 04 06 3F 00 0F FF 30 02 80 02 03 00 30 .0...?...0.....0 +30 30 11 0C 08 53 47 41 53 64 61 74 61 03 02 06 00...SGASdata... +C0 04 01 0A 30 0B 0C 09 53 61 66 65 47 75 61 72 ....0...SafeGuar +64 A1 0E 30 0C 04 06 3F 00 0F FF 40 01 80 02 00 d..0...?...@.... +80 30 30 30 11 0C 08 55 73 65 72 64 61 74 61 03 .000...Userdata. +02 06 40 04 01 0A 30 0B 0C 09 53 61 66 65 47 75 ..@...0...SafeGu +61 72 64 A1 0E 30 0C 04 06 3F 00 0F FF 30 01 80 ard..0...?...0.. +02 01 00 30 2C 30 13 0C 0A 62 61 73 69 63 20 64 ...0,0...basic d +61 74 61 03 02 06 C0 04 01 0A 30 05 0C 03 49 44 ata.......0...ID +44 A1 0E 30 0C 04 06 3F 00 40 17 D0 01 80 02 02 D..0...?.@...... +00 30 2F 30 16 0C 0D 65 78 74 65 6E 64 65 64 20 .0/0...extended +64 61 74 61 03 02 06 C0 04 01 0A 30 05 0C 03 49 data.......0...I +44 44 A1 0E 30 0C 04 06 3F 00 40 17 D0 02 80 02 DD..0...?.@..... +08 00 30 34 30 1B 0C 12 73 70 65 63 69 61 6C 20 ..040...special +70 72 69 76 69 6C 65 67 65 73 03 02 06 C0 04 01 privileges...... +0A 30 05 0C 03 49 44 44 A1 0E 30 0C 04 06 3F 00 .0...IDD..0...?. +40 17 D0 03 80 02 04 00 @....... + + 0 30: SEQUENCE { + 2 11: SEQUENCE { + 4 6: UTF8String 'EF.GDO' + 12 1: OCTET STRING 0A + : } + 15 2: SEQUENCE { + 17 0: UTF8String + : Error: Object has zero length. + : } + 19 11: [1] { + 21 9: SEQUENCE { + 23 4: OCTET STRING 3F 00 2F 02 + 29 1: [0] 0E + : } + : } + : } + + + +6038 (authobjects) + +30 2A 30 0B 0C 05 62 61 73 69 63 03 02 00 C0 30 0*0...basic....0 +03 04 01 0A A1 16 30 14 03 03 00 0C 10 0A 01 01 ......0......... +02 01 06 02 01 06 02 01 08 80 01 01 30 51 30 19 ............0Q0. +0C 13 73 70 65 63 69 66 69 63 20 50 49 4E 20 66 ..specific PIN f +6F 72 20 44 53 03 02 00 C0 30 03 04 01 07 A1 2F or DS....0...../ +30 2D 03 03 00 4C 10 0A 01 01 02 01 06 02 01 06 0-...L.......... +02 01 08 80 01 02 18 0F 32 30 30 32 30 34 31 39 ........20020419 +31 32 31 33 34 31 5A 30 06 04 04 3F 00 40 16 121341Z0...?.@. + + 0 42: SEQUENCE { + 2 11: SEQUENCE { + 4 5: UTF8String 'basic' + 11 2: BIT STRING + : '00000011'B + : Error: Spurious zero bits in bitstring. + : } + 15 3: SEQUENCE { + 17 1: OCTET STRING 0A + : } + 20 22: [1] { + 22 20: SEQUENCE { + 24 3: BIT STRING + : '0000100000110000'B + : Error: Spurious zero bits in bitstring. + 29 1: ENUMERATED 1 + 32 1: INTEGER 6 + 35 1: INTEGER 6 + 38 1: INTEGER 8 + 41 1: [0] 01 + : } + : } + : } + + + +*/ + + +/* Read and parse the EF(TokenInfo). + +TokenInfo ::= SEQUENCE { + version INTEGER {v1(0)} (v1,...), + serialNumber OCTET STRING, + manufacturerID Label OPTIONAL, + label [0] Label OPTIONAL, + tokenflags TokenFlags, + seInfo SEQUENCE OF SecurityEnvironmentInfo OPTIONAL, + recordInfo [1] RecordInfo OPTIONAL, + supportedAlgorithms [2] SEQUENCE OF AlgorithmInfo OPTIONAL, + ..., + issuerId [3] Label OPTIONAL, + holderId [4] Label OPTIONAL, + lastUpdate [5] LastUpdate OPTIONAL, + preferredLanguage PrintableString OPTIONAL -- In accordance with + -- IETF RFC 1766 +} (CONSTRAINED BY { -- Each AlgorithmInfo.reference value must be unique --}) + +TokenFlags ::= BIT STRING { + readonly (0), + loginRequired (1), + prnGeneration (2), + eidCompliant (3) +} + + + 5032: + +30 31 02 01 00 04 04 05 45 36 9F 0C 0C 44 2D 54 01......E6...D-T +72 75 73 74 20 47 6D 62 48 80 14 4F 66 66 69 63 rust GmbH..Offic +65 20 69 64 65 6E 74 69 74 79 20 63 61 72 64 03 e identity card. +02 00 40 20 63 61 72 64 03 02 00 40 00 00 00 00 ..@ card...@.... +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + + 0 49: SEQUENCE { + 2 1: INTEGER 0 + 5 4: OCTET STRING 05 45 36 9F + 11 12: UTF8String 'D-Trust GmbH' + 25 20: [0] 'Office identity card' + 47 2: BIT STRING + : '00000010'B (bit 1) + : Error: Spurious zero bits in bitstring. + : } + + + + + */ +static gpg_error_t +read_ef_tokeninfo (app_t app) +{ + unsigned short efid = 0x5032; + +} + + +/* Get all the basic information from the pkcs#15 card, check the + structure and init our context. This is used once at application + initialization. */ +static gpg_error_t +read_p15_info (app_t app) +{ + gpg_error_t err; + + err = read_ed_odf (app); + if (err) + return err; + +} + + +static int +do_learn_status (APP app, CTRL ctrl) +{ + gpg_error_t err; + char ct_buf[100], id_buf[100]; + int i; + + /* Output information about all useful objects. */ + for (i=0; objlist[i].fid; i++) + { + if (filelist[i].certtype) + { + size_t len; + + len = app_help_read_length_of_cert (app->slot, + filelist[i].fid, NULL); + if (len) + { + /* FIXME: We should store the length in the application's + context so that a following readcert does only need to + read that many bytes. */ + sprintf (ct_buf, "%d", filelist[i].certtype); + sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid); + send_status_info (ctrl, "CERTINFO", + ct_buf, strlen (ct_buf), + id_buf, strlen (id_buf), + NULL, (size_t)0); + } + } + else if (filelist[i].iskeypair) + { + char gripstr[40+1]; + + err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr); + if (err) + log_error ("can't get keygrip from FID 0x%04X: %s\n", + filelist[i].fid, gpg_strerror (err)); + else + { + sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid); + send_status_info (ctrl, "KEYPAIRINFO", + gripstr, 40, + id_buf, strlen (id_buf), + NULL, (size_t)0); + } + } + } + + return 0; +} + + + + +/* Release all resources. */ +static void +do_deinit (app_t app) +{ + if (app && app->app_local) + { + xfree (app->app_local); + app->app_local = NULL; + } +} + + +/* Select the PKCS#15 application on the card in SLOT. */ +int +app_select_p15 (APP app) +{ + static char const aid[] = { 0xA0, 0, 0, 0, 0x63, + 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; + int slot = app->slot; + int rc; + + rc = iso7816_select_application (slot, aid, sizeof aid); + if (!rc) + { + app->apptype = "P15"; + + app->app_local = xtrycalloc (1, sizeof *app->app_local); + if (!app->app_local) + { + rc = gpg_error_from_errno (errno); + goto leave; + } + + /* Read basic information and check whether this is a real + card. */ + rc = read_p15_info (app); + + /* Special serial number munging. We need to do one case here + because we need to access the EF(TokenInfo). */ + if (app->serialnolen == 12 + && !memcmp (app->serial, "\xD2\x76\0\0\0\0\0\0\0\0\0\0", 12)) + { + /* This is a German card with a silly serial number. Try to get + the serial number from the EF(TokenInfo). We indicate such a + serial number by the using the prefix: "FF0100". */ + const char *efser = card->p15card->serial_number; + char *p; + + if (!efser) + efser = ""; + + xfree (*serial); + *serial = NULL; + p = xtrymalloc (strlen (efser) + 7); + if (!p) + rc = gpg_error (gpg_err_code_from_errno (errno)); + else + { + strcpy (p, "FF0100"); + strcpy (p+6, efser); + *serial = p; + } + } + else + rc = app_munge_serialno (app); + + app->fnc.deinit = do_deinit; + app->fnc.learn_status = do_learn_status; + app->fnc.readcert = do_readcert; + app->fnc.getattr = NULL; + app->fnc.setattr = NULL; + app->fnc.genkey = NULL; + app->fnc.sign = do_sign; + app->fnc.auth = NULL; + app->fnc.decipher = do_decipher; + app->fnc.change_pin = NULL; + app->fnc.check_pin = NULL; + + leave: + if (rc) + { + xfree (app->app_local); + app->app_local = NULL; + } + + } + + return rc; +} + + diff --git a/sm/ChangeLog b/sm/ChangeLog index acfa7f3bd..5f35e4858 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-11-29 Werner Koch <wk@g10code.com> + + * gpgsm.c (set_debug): Changed to use a globals DEBUG_LEVEL and + DEBUG_VALUE. + (main): Made DEBUG_LEVEL global and introduced DEBUG_VALUE. This + now allows to add debug flags on top of a debug-level setting. + 2004-11-23 Werner Koch <wk@g10code.com> * gpgsm.c: New option --prefer-system-dirmngr. diff --git a/sm/gpgsm.c b/sm/gpgsm.c index c9ce8fd9f..c96683a46 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -438,6 +438,10 @@ int gpgsm_errors_seen = 0; /* It is possible that we are currentlu running under setuid permissions */ static int maybe_setuid = 1; +/* Helper to implement --debug-level and --debug*/ +static const char *debug_level; +static unsigned int debug_value; + /* Option --enable-special-filenames */ static int allow_special_filenames; @@ -580,45 +584,44 @@ wrong_args (const char *text) } -/* Setup the debugging. With a LEVEL of NULL only the active debug - flags are propagated to the subsystems. With LEVEL set, a specific - set of debug flags is set; thus overriding all flags already - set. */ +/* Setup the debugging. With a DEBUG_LEVEL of NULL only the active + debug flags are propagated to the subsystems. With DEBUG_LEVEL + set, a specific set of debug flags is set; and individual debugging + flags will be added on top. */ static void -set_debug (const char *level) +set_debug (void) { - if (!level) + if (!debug_level) ; - else if (!strcmp (level, "none")) + else if (!strcmp (debug_level, "none")) opt.debug = 0; - else if (!strcmp (level, "basic")) + else if (!strcmp (debug_level, "basic")) opt.debug = DBG_ASSUAN_VALUE; - else if (!strcmp (level, "advanced")) + else if (!strcmp (debug_level, "advanced")) opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE; - else if (!strcmp (level, "expert")) + else if (!strcmp (debug_level, "expert")) opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE |DBG_CACHE_VALUE|DBG_CRYPTO_VALUE); - else if (!strcmp (level, "guru")) + else if (!strcmp (debug_level, "guru")) opt.debug = ~0; else { - log_error (_("invalid debug-level `%s' given\n"), level); + log_error (_("invalid debug-level `%s' given\n"), debug_level); gpgsm_exit(2); } + opt.debug |= debug_value; if (opt.debug && !opt.verbose) - { - opt.verbose = 1; - gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); - } - if (opt.debug && opt.quiet) + opt.verbose = 1; + if (opt.debug) opt.quiet = 0; if (opt.debug & DBG_MPI_VALUE) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); if (opt.debug & DBG_CRYPTO_VALUE ) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); } @@ -695,7 +698,6 @@ main ( int argc, char **argv) int greeting = 0; int nogreeting = 0; int debug_wait = 0; - const char *debug_level = NULL; int use_random_seed = 1; int with_fpr = 0; char *def_digest_string = NULL; @@ -1010,8 +1012,8 @@ main ( int argc, char **argv) case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break; - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; + case oDebug: debug_value |= pargs.r.ret_ulong; break; + case oDebugAll: debug_value = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugAllowCoreDump: @@ -1201,7 +1203,7 @@ main ( int argc, char **argv) gcry_control (GCRYCTL_RESUME_SECMEM_WARN); - set_debug (debug_level); + set_debug (); /* Although we alwasy use gpgsm_exit, we better install a regualr exit handler so that at least the secure memory gets wiped -- cgit v1.2.3 From d45e223fdcfbeaddc2943895a142116791225f41 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 3 Dec 2004 17:44:57 +0000 Subject: Preparing 1.9.13 --- ChangeLog | 5 +++- NEWS | 6 +++- build-w32.sh | 10 +++++++ configure.ac | 2 +- po/de.po | 86 ++++++++++++++++++++++++++++------------------------------ sm/ChangeLog | 6 ++++ sm/certchain.c | 21 +++++++++++--- 7 files changed, 84 insertions(+), 52 deletions(-) create mode 100644 build-w32.sh diff --git a/ChangeLog b/ChangeLog index c95cd9a10..6dbe8663f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,12 @@ +2004-12-03 Werner Koch <wk@g10code.com> + + Released 1.9.13. + 2004-11-26 Werner Koch <wk@g10code.com> * configure.ac: Replace strsep. Replaced use of "target" by "host". - 2004-10-22 Werner Koch <wk@g10code.com> Released 1.9.12. diff --git a/NEWS b/NEWS index 2d75cb013..606612c38 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ -Noteworthy changes in version 1.9.13 +Noteworthy changes in version 1.9.13 (2004-12-03) ------------------------------------------------- + * [gpgsm] New option --prefer-system-dirmngr. + + * Minor cleanups and debbuging aids. + Noteworthy changes in version 1.9.12 (2004-10-22) ------------------------------------------------- diff --git a/build-w32.sh b/build-w32.sh new file mode 100644 index 000000000..c9ea984dc --- /dev/null +++ b/build-w32.sh @@ -0,0 +1,10 @@ + ./configure --enable-maintainer-mode --prefix=/home/wk/w32root \ + --host=i586-mingw32msvc --build=`scripts/config.guess` \ + --with-gpg-error-prefix=/home/wk/w32root \ + --with-ksba-prefix=/home/wk/w32root \ + --with-libgcrypt-prefix=/home/wk/w32root \ + --with-libassuan-prefix=/home/wk/w32root \ + --with-zlib=/home/wk/w32root + + + diff --git a/configure.ac b/configure.ac index 8b6bc4d73..38e649f5a 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.9" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.13-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.13, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. diff --git a/po/de.po b/po/de.po index 1c85954d8..eac1827bc 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.10\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-11-24 15:41+0100\n" +"POT-Creation-Date: 2004-12-03 18:30+0100\n" "PO-Revision-Date: 2004-11-24 15:43+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -100,12 +100,12 @@ msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:487 tools/gpgconf.c:85 +#: sm/gpgsm.c:491 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" #: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:487 tools/gpgconf.c:85 +#: sm/gpgsm.c:491 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -121,30 +121,30 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:605 +#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:609 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:448 agent/protect-tool.c:1050 kbx/kbxutil.c:431 -#: scd/scdaemon.c:357 sm/gpgsm.c:728 +#: scd/scdaemon.c:357 sm/gpgsm.c:730 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:521 scd/scdaemon.c:437 sm/gpgsm.c:826 +#: agent/gpg-agent.c:521 scd/scdaemon.c:437 sm/gpgsm.c:828 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" #: agent/gpg-agent.c:526 agent/gpg-agent.c:1000 scd/scdaemon.c:442 -#: sm/gpgsm.c:830 +#: sm/gpgsm.c:832 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:534 scd/scdaemon.c:450 sm/gpgsm.c:837 +#: agent/gpg-agent.c:534 scd/scdaemon.c:450 sm/gpgsm.c:839 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" @@ -163,11 +163,11 @@ msgstr "Verzeichniss `%s' wurde erstellt\n" msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1257 common/simple-pwquery.c:286 sm/call-agent.c:128 +#: agent/gpg-agent.c:1257 common/simple-pwquery.c:293 sm/call-agent.c:128 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1269 common/simple-pwquery.c:298 sm/call-agent.c:140 +#: agent/gpg-agent.c:1269 common/simple-pwquery.c:305 sm/call-agent.c:140 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" @@ -302,32 +302,32 @@ msgstr "WARNUNG: Unsichere Besitzrechte f msgid "Warning: unsafe permissions on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" -#: common/simple-pwquery.c:272 +#: common/simple-pwquery.c:279 msgid "gpg-agent is not available in this session\n" msgstr "Der gpg-agent ist nicht verfgbar\n" -#: common/simple-pwquery.c:320 +#: common/simple-pwquery.c:327 #, c-format msgid "can't connect to `%s': %s\n" msgstr "Verbindung zu `%s' kann nicht aufgebaut werden: %s\n" -#: common/simple-pwquery.c:331 +#: common/simple-pwquery.c:338 msgid "communication problem with gpg-agent\n" msgstr "Kommunikationsproblem mit gpg-agent\n" -#: common/simple-pwquery.c:341 +#: common/simple-pwquery.c:348 msgid "problem setting the gpg-agent options\n" msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: common/simple-pwquery.c:479 +#: common/simple-pwquery.c:487 msgid "canceled by user\n" msgstr "Vom Benutzer abgebrochen\n" -#: common/simple-pwquery.c:486 +#: common/simple-pwquery.c:494 msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:625 +#: jnlib/logging.c:627 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" @@ -651,7 +651,7 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" msgid "number of issuers matching: %d\n" msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:403 sm/certchain.c:562 sm/certchain.c:922 sm/decrypt.c:260 +#: sm/certchain.c:403 sm/certchain.c:562 sm/certchain.c:931 sm/decrypt.c:260 #: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" @@ -699,43 +699,43 @@ msgstr "Das Zertifikat ist abgelaufen" msgid "selfsigned certificate has a BAD signature" msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:675 +#: sm/certchain.c:679 msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert" -#: sm/certchain.c:686 +#: sm/certchain.c:690 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:691 +#: sm/certchain.c:695 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" -#: sm/certchain.c:706 +#: sm/certchain.c:710 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:732 sm/import.c:166 +#: sm/certchain.c:736 sm/import.c:166 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:744 +#: sm/certchain.c:748 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:777 +#: sm/certchain.c:781 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:800 +#: sm/certchain.c:809 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:823 +#: sm/certchain.c:832 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" @@ -1052,11 +1052,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:490 +#: sm/gpgsm.c:494 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:493 +#: sm/gpgsm.c:497 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -1065,7 +1065,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:500 +#: sm/gpgsm.c:504 msgid "" "\n" "Supported algorithms:\n" @@ -1073,50 +1073,50 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:576 +#: sm/gpgsm.c:580 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:642 +#: sm/gpgsm.c:645 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:658 +#: sm/gpgsm.c:661 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:733 +#: sm/gpgsm.c:735 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1181 +#: sm/gpgsm.c:1183 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1193 +#: sm/gpgsm.c:1195 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1219 +#: sm/gpgsm.c:1221 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1227 +#: sm/gpgsm.c:1229 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1257 +#: sm/gpgsm.c:1259 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1423 +#: sm/gpgsm.c:1425 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1646 sm/gpgsm.c:1679 +#: sm/gpgsm.c:1648 sm/gpgsm.c:1681 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" @@ -1385,10 +1385,6 @@ msgstr "Konfiguration der zu nutzenden LDAP-Server" msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" -#, fuzzy -#~ msgid "passphrase (CHV%d) is too short; minimum length is %d\n" -#~ msgstr "Die Passphrase (CHV%d) ist zu kurz; Mindestlnge ist %d\n" - #~ msgid "Usage: sc-investigate [options] (-h for help)\n" #~ msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" diff --git a/sm/ChangeLog b/sm/ChangeLog index 5f35e4858..930584af3 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2004-12-02 Werner Koch <wk@g10code.com> + + * certchain.c (gpgsm_basic_cert_check): Dump certs with bad + signature for debugging. + (gpgsm_validate_chain): Ditto. + 2004-11-29 Werner Koch <wk@g10code.com> * gpgsm.c (set_debug): Changed to use a globals DEBUG_LEVEL and diff --git a/sm/certchain.c b/sm/certchain.c index c51327e0d..f32507f34 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -292,7 +292,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) keydb_search_reset (kh); /* In case of an error try the ephemeral DB. We can't do - that in find-netx mode because we can't keep the search + that in find-next mode because we can't keep the search state then. */ if (rc == -1 && !find_next) { @@ -311,7 +311,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) signature because it is not the correct one. */ if (rc == -1) { - log_info ("issuer certificate (#"); + log_info ("%sissuer certificate (#", find_next?"next ":""); gpgsm_dump_serial (authidno); log_printf ("/"); gpgsm_dump_string (s); @@ -565,7 +565,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, } if (DBG_X509 && !listmode) - gpgsm_dump_cert ("subject", cert); + gpgsm_dump_cert ("target", cert); subject_cert = cert; maxdepth = 50; @@ -659,6 +659,10 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, { do_list (1, lm, fp, _("selfsigned certificate has a BAD signature")); + if (DBG_X509) + { + gpgsm_dump_cert ("self-signing cert", subject_cert); + } rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN : GPG_ERR_BAD_CERT); goto leave; @@ -775,10 +779,15 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, if (rc) { do_list (0, lm, fp, _("certificate has a BAD signature")); + if (DBG_X509) + { + gpgsm_dump_cert ("signing issuer", issuer_cert); + gpgsm_dump_cert ("signed subject", subject_cert); + } if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE) { /* We now try to find other issuer certificates which - might have been used. This is rquired because some + might have been used. This is required because some CAs are reusing the issuer and subject DN for new root certificates. */ rc = find_up (kh, subject_cert, issuer, 1); @@ -940,6 +949,10 @@ gpgsm_basic_cert_check (ksba_cert_t cert) { log_error ("selfsigned certificate has a BAD signature: %s\n", gpg_strerror (rc)); + if (DBG_X509) + { + gpgsm_dump_cert ("self-signing cert", cert); + } rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } -- cgit v1.2.3 From 237611cddff696bd3aeb36487ee24fd6fd4f908b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 3 Dec 2004 18:38:23 +0000 Subject: Fixed copyright comments. --- common/ChangeLog | 4 ++++ common/strsep.c | 31 +++++++++++++++++-------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 9224055df..3a3d02d8e 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-12-03 Werner Koch <wk@g10code.com> + + * strsep.c: Fixed copyright comments. + 2004-11-26 Werner Koch <wk@g10code.com> * simple-gettext.c: New taken from gnupg 1.3.x diff --git a/common/strsep.c b/common/strsep.c index af3f02e07..dd01a826f 100644 --- a/common/strsep.c +++ b/common/strsep.c @@ -1,31 +1,34 @@ /* strsep.c - Replacement for strsep(). - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 1992, 1993, 1996, 1997, 1998, 1999, + * 2004 Free Software Foundation, Inc. * - * This file is part of GnuPG. + * This file is part of the GNU C Library. * - * 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. + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * - * GnuPG is distributed in the hope that it will be useful, + * The GNU C Library 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser 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 + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. */ +/* Code taken from glibc-2.3.2/sysdeps/generic/strsep.c and slightly + modified for use with GnuPG. */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <string.h> -/* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c */ -#warning need to get the correct copyright years from glibc char * strsep (char **stringp, const char *delim) { -- cgit v1.2.3 From 52efac06d7e52a309da71a698e2bd837b66ca1c3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 3 Dec 2004 19:43:11 +0000 Subject: post release version number updates --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 606612c38..18f84ed1c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.14 +------------------------------------------------- + + Noteworthy changes in version 1.9.13 (2004-12-03) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 38e649f5a..25446a04a 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.7.9" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.13, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.14-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 14524a8e79a08c829f5ae991aa49b9ffca5acd1d Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sun, 5 Dec 2004 15:36:49 +0000 Subject: 2004-12-05 Moritz Schulte <moritz@g10code.com> * query.c (start_pinentry): Allow CTRL be NULL. --- agent/ChangeLog | 4 ++++ agent/query.c | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 756711f1a..e0bf52b45 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-12-05 Moritz Schulte <moritz@g10code.com> + + * query.c (start_pinentry): Allow CTRL be NULL. + 2004-10-22 Werner Koch <wk@g10code.com> * gpg-agent.c (parse_rereadable_options): Return "not handled" diff --git a/agent/query.c b/agent/query.c index b514f6f5e..cdf6ff259 100644 --- a/agent/query.c +++ b/agent/query.c @@ -152,7 +152,7 @@ start_pinentry (CTRL ctrl) pgmname++; argv[0] = pgmname; - if (ctrl->display && !opt.keep_display) + if (ctrl && ctrl->display && !opt.keep_display) { argv[1] = "--display"; argv[2] = ctrl->display; @@ -189,7 +189,7 @@ start_pinentry (CTRL ctrl) NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return unlock_pinentry (map_assuan_err (rc)); - if (ctrl->ttyname) + if (ctrl && ctrl->ttyname) { char *optstr; if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 ) @@ -200,7 +200,7 @@ start_pinentry (CTRL ctrl) if (rc) return unlock_pinentry (map_assuan_err (rc)); } - if (ctrl->ttytype) + if (ctrl && ctrl->ttytype) { char *optstr; if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 ) @@ -210,7 +210,7 @@ start_pinentry (CTRL ctrl) if (rc) return unlock_pinentry (map_assuan_err (rc)); } - if (ctrl->lc_ctype) + if (ctrl && ctrl->lc_ctype) { char *optstr; if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 ) @@ -220,7 +220,7 @@ start_pinentry (CTRL ctrl) if (rc) return unlock_pinentry (map_assuan_err (rc)); } - if (ctrl->lc_messages) + if (ctrl && ctrl->lc_messages) { char *optstr; if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 ) -- cgit v1.2.3 From 8f620c8c2c9a283e74c0cf75f348bfc929117d72 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 6 Dec 2004 13:49:14 +0000 Subject: * configure.ac (have_w32_system): New. Disable Pth checks for W32. Link jnlib/w32-pth.h to pth.h. * Makefile.am (pkglib_PROGRAMS): Build only for W32. * keydb.c: Don't define DIRSEP_S here. --- ChangeLog | 5 +++++ NEWS | 2 +- build-w32.sh | 19 ++++++++++++------- configure.ac | 40 ++++++++++++++++++++++++++++------------ jnlib/w32-pth.h | 29 +++++++++++++++++++++++++++++ scd/ChangeLog | 4 ++++ scd/Makefile.am | 2 ++ sm/ChangeLog | 4 ++++ sm/keydb.c | 2 -- 9 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 jnlib/w32-pth.h diff --git a/ChangeLog b/ChangeLog index 6dbe8663f..d290c9481 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-12-06 Werner Koch <wk@g10code.com> + + * configure.ac (have_w32_system): New. Disable Pth checks for W32. + Link jnlib/w32-pth.h to pth.h. + 2004-12-03 Werner Koch <wk@g10code.com> Released 1.9.13. diff --git a/NEWS b/NEWS index 18f84ed1c..0d0a7058f 100644 --- a/NEWS +++ b/NEWS @@ -7,7 +7,7 @@ Noteworthy changes in version 1.9.13 (2004-12-03) * [gpgsm] New option --prefer-system-dirmngr. - * Minor cleanups and debbuging aids. + * Minor cleanups and debugging aids. Noteworthy changes in version 1.9.12 (2004-10-22) diff --git a/build-w32.sh b/build-w32.sh index c9ea984dc..0983012aa 100644 --- a/build-w32.sh +++ b/build-w32.sh @@ -1,10 +1,15 @@ - ./configure --enable-maintainer-mode --prefix=/home/wk/w32root \ +#!/bin/sh + +[ -z "$w32root" ] && w32root="$HOME/w32root" + + ./configure --enable-maintainer-mode --prefix=${w32root} \ --host=i586-mingw32msvc --build=`scripts/config.guess` \ - --with-gpg-error-prefix=/home/wk/w32root \ - --with-ksba-prefix=/home/wk/w32root \ - --with-libgcrypt-prefix=/home/wk/w32root \ - --with-libassuan-prefix=/home/wk/w32root \ - --with-zlib=/home/wk/w32root - + --with-gpg-error-prefix=${w32root} \ + --with-ksba-prefix=${w32root} \ + --with-libgcrypt-prefix=${w32root} \ + --with-libassuan-prefix=${w32root} \ + --with-zlib=${w32root} \ + --with-pth-prefix=${w32root} + diff --git a/configure.ac b/configure.ac index 25446a04a..2b5d21a23 100644 --- a/configure.ac +++ b/configure.ac @@ -141,7 +141,7 @@ AC_ARG_ENABLE(agent-only, build_agent_only=$enableval) -# Configure option to allow ot disallow execution of external +# Configure option to allow or disallow execution of external # programs, like a photo viewer. AC_MSG_CHECKING([whether to enable external program execution]) AC_ARG_ENABLE(exec, @@ -343,6 +343,7 @@ GNUPG_CHECK_DOCBOOK_TO_TEXI try_gettext=yes have_dosish_system=no +have_w32_system=no case "${host}" in *-*-mingw32*) # special stuff for Windoze NT @@ -356,6 +357,7 @@ case "${host}" in MingW32 systems and these systems lack Posix functions, we use a simplified version of gettext]) have_dosish_system=yes + have_w32_system=yes try_gettext="no" ;; i?86-emx-os2 | i?86-*-os2*emx ) @@ -409,12 +411,18 @@ esac if test "$have_dosish_system" = yes; then AC_DEFINE(HAVE_DOSISH_SYSTEM,1, - [defined if we run on some of the PCDOS like systems + [Defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) with special properties like no file modes]) fi AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes) +if test "$have_w32_system" = yes; then + AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system]) +fi +AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) + + # # Checks for libraries. @@ -480,6 +488,7 @@ AM_CONDITIONAL(HAVE_OPENSC, test "$have_opensc" = "yes") # # Check whether the (highly desirable) GNU Pth library is available +# Note, that we include a Pth emulation for W32. # AC_ARG_WITH(pth-prefix, AC_HELP_STRING([--with-pth-prefix=PFX], @@ -489,7 +498,8 @@ if test x$pth_config_prefix != x ; then PTH_CONFIG="$pth_config_prefix/bin/pth-config" fi AC_PATH_PROG(PTH_CONFIG, pth-config, no) -if test "$PTH_CONFIG" = "no"; then +if test "$have_w32_system" = no; then + if test "$PTH_CONFIG" = "no"; then AC_MSG_WARN([[ *** *** To support concurrent access to the gpg-agent and the SCdaemon @@ -498,7 +508,7 @@ if test "$PTH_CONFIG" = "no"; then *** On a Debian GNU/Linux system you might want to try *** apt-get install libpth-dev ***]]) -else + else GNUPG_PTH_VERSION_CHECK(1.3.7) if test $have_pth = yes; then PTH_CFLAGS=`$PTH_CONFIG --cflags` @@ -507,6 +517,12 @@ else AC_DEFINE(USE_GNU_PTH, 1, [Defined if the GNU Portable Thread Library should be used]) fi + fi +else + have_pth=yes + PTH_CFLAGS="" + PTH_LIBS="" + AC_DEFINE(USE_GNU_PTH, 1) fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) @@ -968,15 +984,11 @@ AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) GNUPG_CHECK_GNUMAKE -# add some extra libs here so that previous tests don't fail for +# Add some extra libs here so that previous tests don't fail for # mysterious reasons - the final link step should bail out. -case "${host}" in - *-*-mingw32*) - W32LIBS="-lwsock32" - ;; - *) - ;; -esac +if test "$have_w32_system" = yes; then + W32LIBS="-lwsock32" +fi if test "$GCC" = yes; then @@ -996,6 +1008,10 @@ AC_SUBST(W32LIBS) AC_DEFINE(HAVE_JNLIB_LOGGING, 1, [Defined if jnlib style logging functions are available]) +# For W32 we need to use our Pth emulation code +if test "$have_w32_system" = yes; then + AC_CONFIG_LINKS(pth.h:jnlib/w32-pth.h) +fi # diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h new file mode 100644 index 000000000..b9c03323f --- /dev/null +++ b/jnlib/w32-pth.h @@ -0,0 +1,29 @@ +/* w32-pth.h - GNU Pth emulation for W32 (MS Windows). + * Copyright (C) 2004 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + */ + +/* Note that this header is usually through a symlinked pth.h file. + This is needed so that we don't have a pth.h file here which would + conflict if a system really has pth available. */ +#ifndef W32_PTH_H +#define W32_PTH_H + + + +#endif /*W32_PTH_H*/ diff --git a/scd/ChangeLog b/scd/ChangeLog index 660865638..628055e80 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-12-06 Werner Koch <wk@g10code.com> + + * Makefile.am (pkglib_PROGRAMS): Build only for W32. + 2004-10-22 Werner Koch <wk@g10code.com> * app-openpgp.c (verify_chv3): The minium length for CHV3 is diff --git a/scd/Makefile.am b/scd/Makefile.am index 0d83271e0..43bee4889 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -19,7 +19,9 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = scdaemon sc-copykeys +if HAVE_W32_SYSTEM pkglib_PROGRAMS = pcsc-wrapper +endif AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common diff --git a/sm/ChangeLog b/sm/ChangeLog index 930584af3..a0d5cc033 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-12-06 Werner Koch <wk@g10code.com> + + * keydb.c: Don't define DIRSEP_S here. + 2004-12-02 Werner Koch <wk@g10code.com> * certchain.c (gpgsm_basic_cert_check): Dump certs with bad diff --git a/sm/keydb.c b/sm/keydb.c index 6c5c77364..293e5233d 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -33,8 +33,6 @@ #include "keydb.h" #include "i18n.h" -#define DIRSEP_C '/' - static int active_handles; typedef enum { -- cgit v1.2.3 From 0a058ac53c45f65a075aa87d3fd687a685c6a775 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 6 Dec 2004 18:28:56 +0000 Subject: * exechelp.h, exechelp.c: New. Based on code from ../sm/import.c. * gpgsm.c (run_protect_tool) [_WIN32]: Disabled. * import.c (popen_protect_tool): Simplified by making use of gnupg_spawn_process. (parse_p12): Likewise, using gnupg_wait_process. * export.c (popen_protect_tool): Ditto. (export_p12): Ditto. --- common/ChangeLog | 4 + common/Makefile.am | 1 + common/exechelp.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++ common/exechelp.h | 45 +++++++++++ sm/ChangeLog | 8 ++ sm/export.c | 131 +++++------------------------- sm/gpgsm.c | 2 + sm/import.c | 143 +++++---------------------------- 8 files changed, 331 insertions(+), 233 deletions(-) create mode 100644 common/exechelp.c create mode 100644 common/exechelp.h diff --git a/common/ChangeLog b/common/ChangeLog index 3a3d02d8e..8c311f4dc 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-12-06 Werner Koch <wk@g10code.com> + + * exechelp.h, exechelp.c: New. Based on code from ../sm/import.c. + 2004-12-03 Werner Koch <wk@g10code.com> * strsep.c: Fixed copyright comments. diff --git a/common/Makefile.am b/common/Makefile.am index 12fdf7b5e..795d66a1a 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -41,6 +41,7 @@ libcommon_a_SOURCES = \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ asshelp.c asshelp.h \ + exechelp.c exechelp.h \ simple-gettext.c \ w32reg.c \ signal.c \ diff --git a/common/exechelp.c b/common/exechelp.c new file mode 100644 index 000000000..206e16d51 --- /dev/null +++ b/common/exechelp.c @@ -0,0 +1,230 @@ +/* exechelp.c - fork and exec helpers + * 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 + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <signal.h> +#include <unistd.h> +#ifdef USE_GNU_PTH +#include <pth.h> +#endif +#ifdef _WIN32 +#else +#include <sys/wait.h> +#endif + +#include "util.h" +#include "i18n.h" +#include "exechelp.h" + + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + +/* We have the usual problem here: Some modules are linked against pth + and some are not. However we want to use pth_fork and pth_waitpid + here. Using a weak symbol works but is not portable - we should + provide a an explicit dummy pth module instead of using the + pragma. */ +#ifndef _WIN32 +#pragma weak pth_fork +#pragma weak pth_waitpid +#endif + + + +/* Fork and exec the PGMNAME, connect the file descriptor of INFILE to + stdin, write the output to OUTFILE, return a new stream in + STATUSFILE for stderr and the pid of the process in PID. The + arguments for the process are expected in the NULL terminated array + ARGV. The program name itself should not be included there. if + PREEXEC is not NULL, that function will be called right before the + exec. + + Returns 0 on success or an error code. */ +gpg_error_t +gnupg_spawn_process (const char *pgmname, const char *argv[], + FILE *infile, FILE *outfile, + void (*preexec)(void), + FILE **statusfile, pid_t *pid) +{ +#ifdef _WIN32 + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + +#else /* !_WIN32 */ + gpg_error_t err; + int fd, fdout, rp[2]; + + *statusfile = NULL; + *pid = (pid_t)(-1); + fflush (infile); + rewind (infile); + fd = fileno (infile); + fdout = fileno (outfile); + if (fd == -1 || fdout == -1) + log_fatal ("no file descriptor for file passed" + " to gnupg_spawn_process: %s\n", strerror (errno) ); + + if (pipe (rp) == -1) + { + err = gpg_error_from_errno (errno); + log_error (_("error creating a pipe: %s\n"), strerror (errno)); + return err; + } + +#ifdef USE_GNU_PTH + *pid = pth_fork? pth_fork () : fork (); +#else + *pid = fork (); +#endif + if (*pid == (pid_t)(-1)) + { + err = gpg_error_from_errno (errno); + log_error (_("error forking process: %s\n"), strerror (errno)); + close (rp[0]); + close (rp[1]); + return err; + } + + if (!*pid) + { + /* Child. */ + char **arg_list; + int n, i, j; + + /* Create the command line argument array. */ + for (i=0; argv[i]; i++) + ; + arg_list = xcalloc (i+2, sizeof *arg_list); + arg_list[0] = strrchr (pgmname, '/'); + if (arg_list[0]) + arg_list[0]++; + else + arg_list[0] = xstrdup (pgmname); + for (i=0,j=1; argv[i]; i++, j++) + arg_list[j] = (char*)argv[i]; + + /* Connect the infile to stdin. */ + if (fd != 0 && dup2 (fd, 0) == -1) + log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); + + /* Connect the outfile to stdout. */ + if (fdout != 1 && dup2 (fdout, 1) == -1) + log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); + + /* Connect stderr to our pipe. */ + if (rp[1] != 2 && dup2 (rp[1], 2) == -1) + log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); + + /* Close all other files. */ + n = sysconf (_SC_OPEN_MAX); + if (n < 0) + n = MAX_OPEN_FDS; + for (i=3; i < n; i++) + close(i); + errno = 0; + + if (preexec) + preexec (); + execv (pgmname, arg_list); + /* No way to print anything, as we have closed all streams. */ + _exit (127); + } + + /* Parent. */ + close (rp[1]); + + *statusfile = fdopen (rp[0], "r"); + if (!*statusfile) + { + err = gpg_error_from_errno (errno); + log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno)); + kill (*pid, SIGTERM); + *pid = (pid_t)(-1); + return err; + } + + return 0; +#endif /* !_WIN32 */ +} + + +/* Wait for the process identified by PID to terminate. PGMNAME should + be the same as suplieed to the spawn fucntion and is only used for + diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for + any failures of the spawned program or other error codes.*/ +gpg_error_t +gnupg_wait_process (const char *pgmname, pid_t pid) +{ + gpg_err_code_t ec; + +#ifdef _WIN32 + ec = GPG_ERR_NOT_IMPLEMENTED; + +#else /* !_WIN32 */ + int i, status; + + if (pid == (pid_t)(-1)) + return gpg_error (GPG_ERR_INV_VALUE); + +#ifdef USE_GNU_PTH + i = pth_waitpid ? pth_waitpid (pid, &status, 0) : waitpid (pid, &status, 0); +#else + while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) + ; +#endif + if (i == (pid_t)(-1)) + { + log_error (_("waiting for process %d to terminate failed: %s\n"), + (int)pid, strerror (errno)); + ec = gpg_err_code_from_errno (errno); + } + else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) + { + log_error (_("error running `%s': probably not installed\n"), pgmname); + ec = GPG_ERR_CONFIGURATION; + } + else if (WIFEXITED (status) && WEXITSTATUS (status)) + { + log_error (_("error running `%s': exit status %d\n"), pgmname, + WEXITSTATUS (status)); + ec = GPG_ERR_GENERAL; + } + else if (!WIFEXITED (status)) + { + log_error (_("error running `%s': terminated\n"), pgmname); + ec = GPG_ERR_GENERAL; + } + else + ec = 0; +#endif /* !_WIN32 */ + + return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); + +} + diff --git a/common/exechelp.h b/common/exechelp.h new file mode 100644 index 000000000..f00d18dd8 --- /dev/null +++ b/common/exechelp.h @@ -0,0 +1,45 @@ +/* exechelp.h - Definitions for the fork and exec helpers + * 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_EXECHELP_H +#define GNUPG_COMMON_EXECHELP_H + + + +/* Fork and exec the PGMNAME, connect the file descriptor of INFILE to + stdin, write the output to OUTFILE, return a new stream in + STATUSFILE for stderr and the pid of the process in PID. The + arguments for the process are expected in the NULL terminated array + ARGV. The program name itself should not be included there. if + PREEXEC is not NULL, that function will be called right before the + exec. Returns 0 on success or an error code. */ +gpg_error_t gnupg_spawn_process (const char *pgmname, const char *argv[], + FILE *infile, FILE *outfile, + void (*preexec)(void), + FILE **statusfile, pid_t *pid); + +/* Wait for the process identified by PID to terminate. PGMNAME should + be the same as suplieed to the spawn fucntion and is only used for + diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for + any failures of the spawned program or other error codes.*/ +gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid); + + +#endif /*GNUPG_COMMON_EXECHELP_H*/ diff --git a/sm/ChangeLog b/sm/ChangeLog index a0d5cc033..02f0014e8 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,13 @@ 2004-12-06 Werner Koch <wk@g10code.com> + * gpgsm.c (run_protect_tool) [_WIN32]: Disabled. + + * import.c (popen_protect_tool): Simplified by making use of + gnupg_spawn_process. + (parse_p12): Likewise, using gnupg_wait_process. + * export.c (popen_protect_tool): Ditto. + (export_p12): Ditto. + * keydb.c: Don't define DIRSEP_S here. 2004-12-02 Werner Koch <wk@g10code.com> diff --git a/sm/export.c b/sm/export.c index 15ad87b04..b4450b2c2 100644 --- a/sm/export.c +++ b/sm/export.c @@ -23,25 +23,17 @@ #include <stdlib.h> #include <string.h> #include <errno.h> -#include <unistd.h> #include <time.h> #include <assert.h> -#include <signal.h> -#include <fcntl.h> -#include <sys/wait.h> #include "gpgsm.h" #include <gcrypt.h> #include <ksba.h> #include "keydb.h" +#include "exechelp.h" #include "i18n.h" -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif /* A table to store a fingerprint as used in a duplicates table. We @@ -522,92 +514,23 @@ popen_protect_tool (const char *pgmname, const char *prompt, const char *keygrip, pid_t *pid) { - gpg_error_t err; - int fd, fdout, rp[2]; - int n, i; - - fflush (infile); - rewind (infile); - fd = fileno (infile); - fdout = fileno (outfile); - if (fd == -1 || fdout == -1) - log_fatal ("no file descriptor for temporary file: %s\n", - strerror (errno)); - - /* Now start the protect-tool. */ - if (pipe (rp) == -1) - { - err = gpg_error_from_errno (errno); - log_error (_("error creating a pipe: %s\n"), strerror (errno)); - return err; - } - - *pid = fork (); - if (*pid == -1) - { - err = gpg_error_from_errno (errno); - log_error (_("error forking process: %s\n"), strerror (errno)); - close (rp[0]); - close (rp[1]); - return err; - } - - if (!*pid) - { /* Child. */ - const char *arg0; - - arg0 = strrchr (pgmname, '/'); - if (arg0) - arg0++; - else - arg0 = pgmname; - - /* Connect the infile to stdin. */ - if (fd != 0 && dup2 (fd, 0) == -1) - log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); - - /* Connect the outfile to stdout. */ - if (fdout != 1 && dup2 (fdout, 1) == -1) - log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); - - /* Connect stderr to our pipe. */ - if (rp[1] != 2 && dup2 (rp[1], 2) == -1) - log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); - - /* Close all other files. */ - n = sysconf (_SC_OPEN_MAX); - if (n < 0) - n = MAX_OPEN_FDS; - for (i=3; i < n; i++) - close(i); - errno = 0; - - setup_pinentry_env (); - - execlp (pgmname, arg0, - "--homedir", opt.homedir, - "--p12-export", - "--prompt", prompt?prompt:"", - "--enable-status-msg", - "--", - keygrip, - NULL); - /* No way to print anything, as we have closed all streams. */ - _exit (31); - } - - /* Parent. */ - close (rp[1]); - *statusfile = fdopen (rp[0], "r"); - if (!*statusfile) - { - err = gpg_error_from_errno (errno); - log_error ("can't fdopen pipe for reading: %s", strerror (errno)); - kill (*pid, SIGTERM); - return err; - } - - return 0; + const char *argv[20]; + int i=0; + + argv[i++] = "--homedir"; + argv[i++] = opt.homedir; + argv[i++] = "--p12-export"; + argv[i++] = "--prompt"; + argv[i++] = prompt?prompt:""; + argv[i++] = "--enable-status-msg"; + argv[i++] = "--", + argv[i++] = keygrip, + argv[i] = NULL; + assert (i < sizeof argv); + + return gnupg_spawn_process (pgmname, argv, infile, outfile, + setup_pinentry_env, + statusfile, pid); } @@ -618,7 +541,7 @@ export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen, { const char *pgmname; gpg_error_t err = 0, child_err = 0; - int i, c, cont_line; + int c, cont_line; unsigned int pos; FILE *infp = NULL, *outfp = NULL, *fp = NULL; char buffer[1024]; @@ -722,21 +645,7 @@ export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen, fclose (fp); if (pid != -1) { - int status; - - while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) - ; - if (i == -1) - log_error (_("waiting for protect-tools to terminate failed: %s\n"), - strerror (errno)); - else if (WIFEXITED (status) && WEXITSTATUS (status) == 31) - log_error (_("error running `%s': probably not installed\n"), pgmname); - else if (WIFEXITED (status) && WEXITSTATUS (status)) - log_error (_("error running `%s': exit status %d\n"), pgmname, - WEXITSTATUS (status)); - else if (!WIFEXITED (status)) - log_error (_("error running `%s': terminated\n"), pgmname); - else + if (!gnupg_wait_process (pgmname, pid)) child_err = 0; } if (!err) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index c96683a46..0feca2608 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1688,6 +1688,7 @@ open_fwrite (const char *filename) static void run_protect_tool (int argc, char **argv) { +#ifndef _WIN32 const char *pgm; char **av; int i; @@ -1706,5 +1707,6 @@ run_protect_tool (int argc, char **argv) av[i] = NULL; execv (pgm, av); log_error ("error executing `%s': %s\n", pgm, strerror (errno)); +#endif gpgsm_exit (2); } diff --git a/sm/import.c b/sm/import.c index 938bc17d0..457ef6423 100644 --- a/sm/import.c +++ b/sm/import.c @@ -23,27 +23,17 @@ #include <stdlib.h> #include <string.h> #include <errno.h> -#include <unistd.h> #include <time.h> #include <assert.h> -#include <signal.h> -#include <fcntl.h> -#include <sys/wait.h> #include "gpgsm.h" #include <gcrypt.h> #include <ksba.h> #include "keydb.h" +#include "exechelp.h" #include "i18n.h" -#ifdef _POSIX_OPEN_MAX -#define MAX_OPEN_FDS _POSIX_OPEN_MAX -#else -#define MAX_OPEN_FDS 20 -#endif - - struct stats_s { unsigned long count; unsigned long imported; @@ -471,103 +461,27 @@ static gpg_error_t popen_protect_tool (const char *pgmname, FILE *infile, FILE *outfile, FILE **statusfile, pid_t *pid) { - gpg_error_t err; - int fd, fdout, rp[2]; - int n, i; - - fflush (infile); - rewind (infile); - fd = fileno (infile); - fdout = fileno (outfile); - if (fd == -1 || fdout == -1) - log_fatal ("no file descriptor for temporary file: %s\n", - strerror (errno)); - - /* Now start the protect-tool. */ - if (pipe (rp) == -1) - { - err = gpg_error_from_errno (errno); - log_error (_("error creating a pipe: %s\n"), strerror (errno)); - return err; - } - - *pid = fork (); - if (*pid == -1) - { - err = gpg_error_from_errno (errno); - log_error (_("error forking process: %s\n"), strerror (errno)); - close (rp[0]); - close (rp[1]); - return err; - } - - if (!*pid) - { /* Child. */ - const char *arg0; - - arg0 = strrchr (pgmname, '/'); - if (arg0) - arg0++; - else - arg0 = pgmname; - - /* Connect the infile to stdin. */ - if (fd != 0 && dup2 (fd, 0) == -1) - log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); - - /* Connect the outfile to stdout. */ - if (fdout != 1 && dup2 (fdout, 1) == -1) - log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); - - /* Connect stderr to our pipe. */ - if (rp[1] != 2 && dup2 (rp[1], 2) == -1) - log_fatal ("dup2 stderr failed: %s\n", strerror (errno)); - - /* Close all other files. */ - n = sysconf (_SC_OPEN_MAX); - if (n < 0) - n = MAX_OPEN_FDS; - for (i=3; i < n; i++) - close(i); - errno = 0; - - setup_pinentry_env (); - - if (opt.fixed_passphrase) - execlp (pgmname, arg0, - "--homedir", opt.homedir, - "--p12-import", - "--store", - "--no-fail-on-exist", - "--enable-status-msg", - "--passphrase", opt.fixed_passphrase, - "--", - NULL); - else - execlp (pgmname, arg0, - "--homedir", opt.homedir, - "--p12-import", - "--store", - "--no-fail-on-exist", - "--enable-status-msg", - "--", - NULL); - /* No way to print anything, as we have closed all streams. */ - _exit (31); - } - - /* Parent. */ - close (rp[1]); - *statusfile = fdopen (rp[0], "r"); - if (!*statusfile) + const char *argv[20]; + int i=0; + + argv[i++] = "--homedir"; + argv[i++] = opt.homedir; + argv[i++] = "--p12-import"; + argv[i++] = "--store"; + argv[i++] = "--no-fail-on-exist"; + argv[i++] = "--enable-status-msg"; + if (opt.fixed_passphrase) { - err = gpg_error_from_errno (errno); - log_error ("can't fdopen pipe for reading: %s", strerror (errno)); - kill (*pid, SIGTERM); - return err; + argv[i++] = "--passphrase"; + argv[i++] = opt.fixed_passphrase; } + argv[i++] = "--", + argv[i] = NULL; + assert (i < sizeof argv); - return 0; + return gnupg_spawn_process (pgmname, argv, infile, outfile, + setup_pinentry_env, + statusfile, pid); } @@ -583,7 +497,7 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, { const char *pgmname; gpg_error_t err = 0, child_err = 0; - int i, c, cont_line; + int c, cont_line; unsigned int pos; FILE *tmpfp, *certfp = NULL, *fp = NULL; char buffer[1024]; @@ -712,7 +626,6 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, if (!child_err) child_err = gpg_error (GPG_ERR_DECRYPT_FAILED); - cleanup: if (tmpfp) fclose (tmpfp); @@ -720,21 +633,7 @@ parse_p12 (ctrl_t ctrl, ksba_reader_t reader, fclose (fp); if (pid != -1) { - int status; - - while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR) - ; - if (i == -1) - log_error (_("waiting for protect-tool to terminate failed: %s\n"), - strerror (errno)); - else if (WIFEXITED (status) && WEXITSTATUS (status) == 31) - log_error (_("error running `%s': probably not installed\n"), pgmname); - else if (WIFEXITED (status) && WEXITSTATUS (status)) - log_error (_("error running `%s': exit status %d\n"), pgmname, - WEXITSTATUS (status)); - else if (!WIFEXITED (status)) - log_error (_("error running `%s': terminated\n"), pgmname); - else + if (!gnupg_wait_process (pgmname, pid)) child_err = 0; } if (!err) -- cgit v1.2.3 From b50a587d8df43b01b5c3b99950aab8fc050b3fe1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 7 Dec 2004 11:21:40 +0000 Subject: * asshelp.c (send_pinentry_environment) [W32]: Do not use ttyname. * w32-pth.c, w32-pth.h: New. * Makefile.am (gpgsm_LDADD): Put libassuan before jnlib because under W32 we need the w32 pth code from jnlib. * misc.c (setup_pinentry_env) [W32]: Disabled. --- common/ChangeLog | 4 ++++ common/asshelp.c | 5 +++++ configure.ac | 4 ++-- jnlib/ChangeLog | 4 ++++ jnlib/Makefile.am | 4 +++- jnlib/w32-pth.c | 42 ++++++++++++++++++++++++++++++++++++++++++ jnlib/w32-pth.h | 6 +++--- sm/ChangeLog | 7 +++++++ sm/Makefile.am | 5 +++-- sm/misc.c | 3 ++- 10 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 jnlib/w32-pth.c diff --git a/common/ChangeLog b/common/ChangeLog index 8c311f4dc..afdded6d9 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-12-07 Werner Koch <wk@g10code.com> + + * asshelp.c (send_pinentry_environment) [W32]: Do not use ttyname. + 2004-12-06 Werner Koch <wk@g10code.com> * exechelp.h, exechelp.c: New. Based on code from ../sm/import.c. diff --git a/common/asshelp.c b/common/asshelp.c index 23feca507..751412e6c 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -66,8 +66,13 @@ send_pinentry_environment (assuan_context_t ctx, if (!opt_ttyname) { dft_ttyname = getenv ("GPG_TTY"); +#ifdef HAVE_DOSISH_SYSTEM + if (!dft_ttyname || !*dft_ttyname ) + dft_ttyname = "/dev/tty"; /* Use a fake. */ +#else if ((!dft_ttyname || !*dft_ttyname) && ttyname (0)) dft_ttyname = ttyname (0); +#endif } if (opt_ttyname || dft_ttyname) { diff --git a/configure.ac b/configure.ac index 2b5d21a23..481e52c52 100644 --- a/configure.ac +++ b/configure.ac @@ -345,7 +345,7 @@ try_gettext=yes have_dosish_system=no have_w32_system=no case "${host}" in - *-*-mingw32*) + *-mingw32*) # special stuff for Windoze NT ac_cv_have_dev_random=no AC_DEFINE(USE_ONLY_8DOT3,1, @@ -677,7 +677,7 @@ fi AC_SUBST(GPGKEYS_MAILTO) case "${host}" in - *-*-mingw32*) + *-mingw32*) PRINTABLE_OS_NAME="MingW32" ;; *-*-cygwin*) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 5ca33d5fb..cc3ec9f4f 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2004-12-07 Werner Koch <wk@g10code.com> + + * w32-pth.c, w32-pth.h: New. + 2004-11-26 Werner Koch <wk@g10code.com> * logging.c [_WIN32]: Don't include socket headers. diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index bad3c5a71..69eac4bf7 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -37,7 +37,9 @@ libjnlib_a_SOURCES = \ argparse.c argparse.h \ logging.c logging.h \ dotlock.c dotlock.h \ - types.h mischelp.h + types.h mischelp.h \ + w32-pth.c w32-pth.h \ + w32-afunix.c w32-afunix.h # xmalloc.c xmalloc.h diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c new file mode 100644 index 000000000..c23cebf4a --- /dev/null +++ b/jnlib/w32-pth.c @@ -0,0 +1,42 @@ +/* w32-pth.c - GNU Pth emulation for W32 (MS Windows). + * Copyright (C) 2004 g10 Code GmbH + * + * 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> +#ifdef HAVE_W32_SYSTEM +#include <stdio.h> +#include <windows.h> +#include <io.h> + +#include "w32-pth.h" + +ssize_t +pth_read (int fd, void *buffer, size_t size) +{ + return read (fd, buffer, size); +} + +ssize_t +pth_write (int fd, const void *buffer, size_t size) +{ + return write (fd, buffer, size); +} + + +#endif /*HAVE_W32_SYSTEM*/ diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h index b9c03323f..6b57d9bd2 100644 --- a/jnlib/w32-pth.h +++ b/jnlib/w32-pth.h @@ -18,9 +18,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -/* Note that this header is usually through a symlinked pth.h file. - This is needed so that we don't have a pth.h file here which would - conflict if a system really has pth available. */ +/* Note that this header is usually used through a symlinked pth.h + file. This is needed so that we don't have a pth.h file here which + would conflict if a system really has pth available. */ #ifndef W32_PTH_H #define W32_PTH_H diff --git a/sm/ChangeLog b/sm/ChangeLog index 02f0014e8..c1e445e4e 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-12-07 Werner Koch <wk@g10code.com> + + * Makefile.am (gpgsm_LDADD): Put libassuan before jnlib because + under W32 we need the w32 pth code from jnlib. + + * misc.c (setup_pinentry_env) [W32]: Disabled. + 2004-12-06 Werner Koch <wk@g10code.com> * gpgsm.c (run_protect_tool) [_WIN32]: Disabled. diff --git a/sm/Makefile.am b/sm/Makefile.am index 0cb96c57f..ff4524fc7 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -51,8 +51,9 @@ gpgsm_SOURCES = \ certreqgen.c -gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a ../common/libcommon.a \ - $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(KSBA_LIBS) -lgpg-error \ +gpgsm_LDADD = $(LIBASSUAN_LIBS) ../jnlib/libjnlib.a ../kbx/libkeybox.a \ + ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) $(KSBA_LIBS) -lgpg-error \ $(LIBINTL) diff --git a/sm/misc.c b/sm/misc.c index bfe8191fd..36c4dda70 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -38,6 +38,7 @@ void setup_pinentry_env (void) { +#ifndef HAVE_W32_SYSTEM char *lc; if (opt.display) @@ -75,6 +76,6 @@ setup_pinentry_env (void) else if ( (lc = setlocale (LC_MESSAGES, "")) ) setenv ("LC_MESSAGES", lc, 1); #endif - +#endif /*!HAVE_W32_SYSTEM*/ } -- cgit v1.2.3 From 98f0a18e77c0d2b13ebfef5083ab95d571df1254 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 7 Dec 2004 18:07:30 +0000 Subject: (keybox_release): Close the file pointer. --- kbx/ChangeLog | 4 ++++ kbx/keybox-init.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index ea5b9dbd1..d75700216 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,7 @@ +2004-12-07 Werner Koch <wk@g10code.com> + + * keybox-init.c (keybox_release): Close the file pointer. + 2004-11-26 Werner Koch <wk@g10code.com> * Makefile.am (kbxutil_LDADD): Add ../common/libcommon.a diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c index e11c4f09c..46a29978a 100644 --- a/kbx/keybox-init.c +++ b/kbx/keybox-init.c @@ -102,6 +102,11 @@ keybox_release (KEYBOX_HANDLE hd) if (!hd) return; _keybox_release_blob (hd->found.blob); + if (hd->fp) + { + fclose (hd->fp); + hd->fp = NULL; + } xfree (hd->word_match.name); xfree (hd->word_match.pattern); xfree (hd); -- cgit v1.2.3 From 907c91960e0f3775cabaa500f7e54370cddaa2d7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 13 Dec 2004 09:05:31 +0000 Subject: Added real code written by Timo Schulz. Not finished, though. --- jnlib/ChangeLog | 5 + jnlib/w32-pth.c | 1053 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- jnlib/w32-pth.h | 219 +++++++++++- 3 files changed, 1270 insertions(+), 7 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index cc3ec9f4f..b33b7842f 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2004-12-13 Werner Koch <wk@g10code.com> + + * w32-pth.c, w32-pth.h: Added real code written by Timo Schulz. + Not finished, though. + 2004-12-07 Werner Koch <wk@g10code.com> * w32-pth.c, w32-pth.h: New. diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index c23cebf4a..80a58d859 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -1,4 +1,5 @@ /* w32-pth.c - GNU Pth emulation for W32 (MS Windows). + * Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com> * Copyright (C) 2004 g10 Code GmbH * * This file is part of GnuPG. @@ -16,6 +17,12 @@ * 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 code is based on Ralf Engelschall's GNU Pth, a non-preemptive + * thread scheduling library which can be found at + * http://www.gnu.org/software/pth/. MS Windows (W32) specific code + * written by Timo Schulz, g10 Code. */ #include <config.h> @@ -23,20 +30,1054 @@ #include <stdio.h> #include <windows.h> #include <io.h> +#include <signal.h> +/* We don't want to have any Windows specific code in the header, thus + we use a macro which defaults to a compatible type in w32-pth.h. */ +#define W32_PTH_HANDLE_INTERNAL HANDLE #include "w32-pth.h" -ssize_t -pth_read (int fd, void *buffer, size_t size) + +static int pth_signo = 0; +static HANDLE pth_signo_ev = NULL; +static int pth_initialized = 0; + + + +#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) + + + +struct pth_event_s +{ + struct pth_event_s * next; + struct pth_event_s * prev; + HANDLE hd; + union { + struct sigset_s * sig; + int fd; + struct timeval tv; + pth_mutex_t * mx; + } u; + int * val; + int u_type; + int flags; +}; + + +struct pth_attr_s +{ + unsigned int flags; + unsigned int stack_size; + char * name; +}; + + + +int +pth_init (void) +{ + SECURITY_ATTRIBUTES sa; + WSADATA wsadat; + + printf ("pth_init: called.\n"); + pth_initialized = 1; + if (WSAStartup (0x202, &wsadat)) + return -1; + pth_signo = 0; + if (pth_signo_ev) + CloseHandle (pth_signo_ev); + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL); + + return 0; +} + + +int +pth_kill (void) +{ + pth_signo = 0; + if (pth_signo_ev) + CloseHandle (pth_signo_ev); + WSACleanup (); + pth_initialized = 0; + return 0; +} + + +long +pth_ctrl (unsigned long query, ...) +{ + implicit_init (); + + switch (query) { + case PTH_CTRL_GETAVLOAD: + case PTH_CTRL_GETPRIO: + case PTH_CTRL_GETNAME: + case PTH_CTRL_GETTHREADS_NEW: + case PTH_CTRL_GETTHREADS_READY: + case PTH_CTRL_GETTHREADS_RUNNING: + case PTH_CTRL_GETTHREADS_WAITING: + case PTH_CTRL_GETTHREADS_SUSPENDED: + case PTH_CTRL_GETTHREADS_DEAD: + /*case PTH_CTRL_GETTHREADS:*/ + default: + return -1; + } + return 0; +} + + + +pth_time_t +pth_timeout (long sec, long usec) +{ + pth_time_t tvd; + + tvd.tv_sec = sec; + tvd.tv_usec = usec; + return tvd; +} + + +int +pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev) +{ + implicit_init (); + return 0; +} + + +int +pth_read (int fd, void * buffer, size_t size) +{ + int n; + + implicit_init (); + n = recv (fd, buffer, size, 0); + if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { + DWORD nread = 0; + n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); + if (!n) + return -1; + return (int)nread; + } + return n; +} + + +int +pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev) +{ + implicit_init (); + return 0; +} + + +int +pth_write (int fd, const void * buffer, size_t size) +{ + int n; + + implicit_init (); + n = send (fd, buffer, size, 0); + if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { + DWORD nwrite; + n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); + if (!n) + return -1; + return (int)nwrite; + } + return n; +} + + +int +pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds, + const struct timeval * timeout) { - return read (fd, buffer, size); + implicit_init (); + return select (nfds, rfds, wfds, efds, timeout); } -ssize_t -pth_write (int fd, const void *buffer, size_t size) + +int +pth_fdmode (int fd, int mode) { - return write (fd, buffer, size); + unsigned long val; + + implicit_init (); + /* XXX: figure out original fd mode */ + switch (mode) { + case PTH_FDMODE_NONBLOCK: + val = 1; + if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) + return PTH_FDMODE_ERROR; + break; + + case PTH_FDMODE_BLOCK: + val = 0; + if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) + return PTH_FDMODE_ERROR; + break; + } + return PTH_FDMODE_BLOCK; +} + + +int +pth_accept (int fd, struct sockaddr *addr, int *addrlen) +{ + implicit_init (); + return accept (fd, addr, addrlen); +} + + +int +pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, pth_event_t ev_extra) +{ + pth_key_t ev_key; + pth_event_t ev; + int rv; + int fdmode; + + implicit_init (); + + fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK); + if (fdmode == PTH_FDMODE_ERROR) + return -1; + + ev = NULL; + while ((rv = accept (fd, addr, addrlen)) == -1 && + (WSAGetLastError () == WSAEINPROGRESS || + WSAGetLastError () == WSAEWOULDBLOCK)) { + if (ev == NULL) { + ev = pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_MODE_STATIC, &ev_key, fd); + if (ev == NULL) + return -1; + if (ev_extra != NULL) + pth_event_concat (ev, ev_extra, NULL); + } + /* wait until accept has a chance */ + pth_wait (ev); + if (ev_extra != NULL) { + pth_event_isolate (ev); + if (pth_event_status (ev) != PTH_STATUS_OCCURRED) { + pth_fdmode (fd, fdmode); + return -1; + } + } + } + + pth_fdmode (fd, fdmode); + return rv; +} + + +int +pth_connect (int fd, struct sockaddr *name, int namelen) +{ + implicit_init (); + return connect (fd, name, namelen); +} + + +int +pth_mutex_release (pth_mutex_t *hd) +{ + if (!hd) + return -1; + implicit_init (); + if (hd->mx) { + CloseHandle (hd->mx); + hd->mx = NULL; + } + free (hd); + return 0; +} + + +int +pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) +{ + implicit_init (); + + if (!hd) + return -1; + if (!hd->mx) + return -1; + +#if 0 + /* still not locked, so simply acquire mutex? */ + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) { + mutex->mx_state |= PTH_MUTEX_LOCKED; + mutex->mx_count = 1; + pth_ring_append(&(pth_current->mutexring), &(mutex->mx_node)); + pth_debug1("pth_mutex_acquire: immediately locking mutex"); + return 0; + } + + /* already locked by caller? */ + if (mutex->mx_count >= 1 && mutex->mx_owner == pth_current) { + /* recursive lock */ + mutex->mx_count++; + pth_debug1("pth_mutex_acquire: recursive locking"); + return 0; + } + + if (tryonly) + return return -1; + + for (;;) { + ev = pth_event(PTH_EVENT_MUTEX|PTH_MODE_STATIC, &ev_key, mutex); + if (ev_extra != NULL) + pth_event_concat (ev, ev_extra, NULL); + pth_wait (ev); + if (ev_extra != NULL) { + pth_event_isolate (ev); + if (pth_event_status(ev) == PTH_STATUS_PENDING) + return return -1; + } + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) + break; + } +#endif + + hd->mx_state |= PTH_MUTEX_LOCKED; + return 0; +} + + +int +pth_mutex_init (pth_mutex_t *hd) +{ + SECURITY_ATTRIBUTES sa; + implicit_init (); + if (hd->mx) { + ReleaseMutex (hd->mx); + CloseHandle (hd->mx); + } + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + hd->mx = CreateMutex (&sa, FALSE, NULL); + hd->mx_state = PTH_MUTEX_INITIALIZED; + return 0; +} + + +pth_attr_t +pth_attr_new (void) +{ + pth_attr_t hd; + + implicit_init (); + hd = calloc (1, sizeof *hd); + if (!hd) + return NULL; + return hd; +} + + +int +pth_attr_destroy (pth_attr_t hd) +{ + if (!hd) + return -1; + implicit_init (); + if (hd->name) + free (hd->name); + free (hd); + return 0; +} + + +int +pth_attr_set (pth_attr_t hd, int field, ...) +{ + va_list args; + char * str; + int val; + int rc = 0; + + implicit_init (); + va_start (args, field); + switch (field) { + case PTH_ATTR_JOINABLE: + val = va_arg (args, int); + if (val) { + hd->flags |= PTH_ATTR_JOINABLE; + printf ("pth_attr_set: PTH_ATTR_JOINABLE\n"); + } + break; + + case PTH_ATTR_STACK_SIZE: + val = va_arg (args, int); + if (val) { + hd->flags |= PTH_ATTR_STACK_SIZE; + hd->stack_size = val; + printf ("pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", val); + } + break; + + case PTH_ATTR_NAME: + str = va_arg (args, char*); + if (hd->name) + free (hd->name); + if (str) { + hd->name = strdup (str); + if (!hd->name) + return -1; + hd->flags |= PTH_ATTR_NAME; + printf ("pth_attr_set: PTH_ATTR_NAME %s\n", hd->name); + } + break; + + default: + rc = -1; + break; + } + va_end (args); + return rc; +} + + +pth_t +pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) +{ + SECURITY_ATTRIBUTES sa; + DWORD tid; + HANDLE th; + + if (!hd) + return NULL; + + implicit_init (); + + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + + th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)func, arg, 0, &tid); + return th; +} + + +int +pth_join (pth_t hd, void **value) +{ + return 0; +} + + +/* friendly */ +int +pth_cancel (pth_t hd) +{ + if (!hd) + return -1; + implicit_init (); + WaitForSingleObject (hd, 1000); + TerminateThread (hd, 0); + return 0; +} + + +/* cruel */ +int +pth_abort (pth_t hd) +{ + if (!hd) + return -1; + implicit_init (); + TerminateThread (hd, 0); + return 0; +} + + +void +pth_exit (void *value) +{ + implicit_init (); + pth_kill (); + exit ((int)(long)value); +} + + +unsigned +pth_waitpid (unsigned pid, int * status, int options) +{ + implicit_init (); +#if 0 + pth_event_t ev; + static pth_key_t ev_key = PTH_KEY_INIT; + pid_t pid; + + pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name); + + for (;;) { + /* do a non-blocking poll for the pid */ + while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0 + && errno == EINTR) ; + + /* if pid was found or caller requested a polling return immediately */ + if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) + break; + + /* else wait a little bit */ + ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, pth_timeout(0,250000)); + pth_wait(ev); + } + + pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name); +#endif + return 0; } +static BOOL WINAPI +sig_handler (DWORD signo) +{ + switch (signo) { + case CTRL_C_EVENT: pth_signo = SIGINT; break; + case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; + } + SetEvent (pth_signo_ev); + printf ("sig_handler=%d\n", pth_signo); + return TRUE; +} + + +pth_event_t +pth_event (unsigned long spec, ...) +{ + va_list arg; + SECURITY_ATTRIBUTES sa; + pth_event_t ev; + int rc; + + implicit_init (); + printf ("pth_event spec=%lu\n", spec); + va_start (arg, spec); + ev = calloc (1, sizeof *ev); + if (!ev) + return NULL; + if (spec == 0) + ; + else if (spec & PTH_EVENT_SIGS) { + ev->u.sig = va_arg (arg, struct sigset_s *); + ev->u_type = PTH_EVENT_SIGS; + ev->val = va_arg (arg, int *); + rc = SetConsoleCtrlHandler (sig_handler, TRUE); + printf ("pth_event: sigs rc=%d\n", rc); + } + else if (spec & PTH_EVENT_FD) { + if (spec & PTH_UNTIL_FD_READABLE) + ev->flags |= PTH_UNTIL_FD_READABLE; + if (spec & PTH_MODE_STATIC) + ev->flags |= PTH_MODE_STATIC; + ev->u_type = PTH_EVENT_FD; + va_arg (arg, pth_key_t); + ev->u.fd = va_arg (arg, int); + printf ("pth_event: fd=%d\n", ev->u.fd); + } + else if (spec & PTH_EVENT_TIME) { + pth_time_t t; + if (spec & PTH_MODE_STATIC) + ev->flags |= PTH_MODE_STATIC; + va_arg (arg, pth_key_t); + t = va_arg (arg, pth_time_t); + ev->u_type = PTH_EVENT_TIME; + ev->u.tv.tv_sec = t.tv_sec; + ev->u.tv.tv_usec = t.tv_usec; + } + else if (spec & PTH_EVENT_MUTEX) { + va_arg (arg, pth_key_t); + ev->u_type = PTH_EVENT_MUTEX; + ev->u.mx = va_arg (arg, pth_mutex_t*); + } + va_end (arg); + + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL); + if (!ev->hd) { + free (ev); + return NULL; + } + + return ev; +} + + +static void +pth_event_add (pth_event_t root, pth_event_t node) +{ + pth_event_t n; + + for (n=root; n->next; n = n->next) + ; + n->next = node; +} + + +pth_event_t +pth_event_concat (pth_event_t evf, ...) +{ + pth_event_t evn; + va_list ap; + + if (!evf) + return NULL; + + implicit_init (); + va_start (ap, evf); + while ((evn = va_arg(ap, pth_event_t)) != NULL) + pth_event_add (evf, evn); + va_end (ap); + + return evf; +} + + +static int +wait_for_fd (int fd, int is_read, int nwait) +{ + struct timeval tv; + fd_set r; + fd_set w; + int n; + + FD_ZERO (&r); + FD_ZERO (&w); + FD_SET (fd, is_read ? &r : &w); + + tv.tv_sec = nwait; + tv.tv_usec = 0; + + while (1) { + n = select (fd+1, &r, &w, NULL, &tv); + printf ("wait_for_fd=%d fd %d (ec=%d)\n", n, fd, (int)WSAGetLastError ()); + if (n == -1) + break; + if (!n) + continue; + if (n == 1) { + if (is_read && FD_ISSET (fd, &r)) + break; + else if (FD_ISSET (fd, &w)) + break; + } + } + return 0; +} + + +static void * +wait_fd_thread (void * ctx) +{ + pth_event_t ev = ctx; + + wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); + printf ("wait_fd_thread: exit.\n"); + SetEvent (ev->hd); + ExitThread (0); + return NULL; +} + + +static void * +wait_timer_thread (void * ctx) +{ + pth_event_t ev = ctx; + int n = ev->u.tv.tv_sec*1000; + Sleep (n); + SetEvent (ev->hd); + printf ("wait_timer_thread: exit.\n"); + ExitThread (0); + return NULL; +} + + +/* void */ +/* sigemptyset (struct sigset_s * ss) */ +/* { */ +/* if (ss) { */ +/* memset (ss->sigs, 0, sizeof ss->sigs); */ +/* ss->idx = 0; */ +/* } */ +/* } */ + + +/* int */ +/* sigaddset (struct sigset_s * ss, int signo) */ +/* { */ +/* if (!ss) */ +/* return -1; */ +/* if (ss->idx + 1 > 64) */ +/* return -1; */ +/* ss->sigs[ss->idx] = signo; */ +/* ss->idx++; */ +/* return 0; */ +/* } */ + + +static int +sigpresent (struct sigset_s * ss, int signo) +{ +/* int i; */ +/* for (i=0; i < ss->idx; i++) { */ +/* if (ss->sigs[i] == signo) */ +/* return 1; */ +/* } */ +/* FIXME: See how to implement it. */ + return 0; +} + + +int +pth_event_occured (pth_event_t ev) +{ + if (!ev) + return 0; + implicit_init (); + switch (ev->u_type) { + case 0: + if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) + return 1; + break; + + case PTH_EVENT_SIGS: + if (sigpresent (ev->u.sig, pth_signo) && + WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) { + printf ("pth_event_occured: sig signaled.\n"); + (*ev->val) = pth_signo; + return 1; + } + break; + + case PTH_EVENT_FD: + if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) + return 1; + break; + } + + return 0; +} + + +int +pth_event_status (pth_event_t ev) +{ + if (!ev) + return 0; + implicit_init (); + if (pth_event_occured (ev)) + return PTH_STATUS_OCCURRED; + return 0; +} + + +int +pth_event_free (pth_event_t ev, int mode) +{ + pth_event_t n; + + implicit_init (); + if (mode == PTH_FREE_ALL) { + while (ev) { + n = ev->next; + CloseHandle (ev->hd); ev->hd = NULL; + free (ev); + ev = n; + } + } + else if (mode == PTH_FREE_THIS) { + ev->prev->next = ev->next; + ev->next->prev = ev->prev; + CloseHandle (ev->hd); ev->hd = NULL; + free (ev); + + } + return 0; +} + + +pth_event_t +pth_event_isolate (pth_event_t ev) +{ + pth_event_t ring = NULL; + + if (!ev) + return NULL; + implicit_init (); + return ring; + +} + + +static void +free_threads (HANDLE *waitbuf, int *hdidx, int n) +{ + int i; + + for (i=0; i < n; i++) + CloseHandle (waitbuf[hdidx[i]]); +} + + +static int +pth_event_count (pth_event_t ev) +{ + pth_event_t p; + int cnt=0; + + if (!ev) + return 0; + for (p=ev; p; p = p->next) + cnt++; + return cnt; +} + + +int +pth_wait (pth_event_t ev) +{ + HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; + int hdidx[MAXIMUM_WAIT_OBJECTS/2]; + DWORD n = 0; + pth_attr_t attr; + pth_event_t tmp; + int pos=0, i=0; + + if (!ev) + return 0; + + implicit_init (); + attr = pth_attr_new (); + pth_attr_set (attr, PTH_ATTR_JOINABLE, 1); + pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 4096); + + printf ("pth_wait: cnt %d\n", pth_event_count (ev)); + for (tmp = ev; tmp; tmp = tmp->next) { + if (pos+1 > MAXIMUM_WAIT_OBJECTS/2) { + free_threads (waitbuf, hdidx, i); + pth_attr_destroy (attr); + return -1; + } + switch (tmp->u_type) { + case 0: + waitbuf[pos++] = tmp->hd; + break; + + case PTH_EVENT_SIGS: + waitbuf[pos++] = pth_signo_ev; + printf ("pth_wait: add signal event.\n"); + break; + + case PTH_EVENT_FD: + printf ("pth_wait: spawn event wait thread.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = pth_spawn (attr, wait_fd_thread, tmp); + break; + + case PTH_EVENT_TIME: + printf ("pth_wait: spawn event timer thread.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = pth_spawn (attr, wait_timer_thread, tmp); + break; + + case PTH_EVENT_MUTEX: + printf ("pth_wait: add mutex event.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = tmp->u.mx->mx; + /* XXX: Use SetEvent(hd->ev) */ + break; + } + } + printf ("pth_wait: set %d\n", pos); + n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); + free_threads (waitbuf, hdidx, i); + pth_attr_destroy (attr); + printf ("pth_wait: n %ld\n", n); + if (n != WAIT_TIMEOUT) + return 1; + + /* + switch (ev->u_type) { + case 0: + n = WaitForSingleObject (ev->hd, INFINITE); + if (n != WAIT_OBJECT_0) + return 1; + break; + + case PTH_EVENT_SIGS: + n = WaitForSingleObject (pth_signo_ev, INFINITE); + if (n != WAIT_OBJECT_0) + return 1; + break; + + case PTH_EVENT_FD: + if (wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE)) { + SetEvent (ev->hd); + return 1; + } + break; + + default: + return -1; + } + */ + return 0; +} + + +int +pth_sleep (int sec) +{ + static pth_key_t ev_key = PTH_KEY_INIT; + pth_event_t ev; + + implicit_init (); + if (sec == 0) + return 0; + + ev = pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, pth_timeout (sec, 0)); + if (ev == NULL) + return -1; + pth_wait (ev); + pth_event_free (ev, PTH_FREE_ALL); + return 0; +} + + + + + +/* + Some simple tests. + */ +#ifdef TEST +#include <stdio.h> + +void * thread (void * c) +{ + + Sleep (2000); + SetEvent (((pth_event_t)c)->hd); + printf ("\n\nhallo!.\n"); + pth_exit (NULL); + return NULL; +} + + +int main_1 (int argc, char ** argv) +{ + pth_attr_t t; + pth_t hd; + pth_event_t ev; + + pth_init (); + ev = pth_event (0, NULL); + t = pth_attr_new (); + pth_attr_set (t, PTH_ATTR_JOINABLE, 1); + pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096); + pth_attr_set (t, PTH_ATTR_NAME, "hello"); + hd = pth_spawn (t, thread, ev); + + pth_wait (ev); + pth_attr_destroy (t); + pth_event_free (ev, 0); + pth_kill (); + + return 0; +} + + +static pth_event_t +setup_signals (struct sigset_s *sigs, int *signo) +{ + pth_event_t ev; + + sigemptyset (sigs); + sigaddset (sigs, SIGINT); + sigaddset (sigs, SIGTERM); + + ev = pth_event (PTH_EVENT_SIGS, sigs, signo); + return ev; +} + +int +main_2 (int argc, char ** argv) +{ + pth_event_t ev; + struct sigset_s sigs; + int signo = 0; + + pth_init (); + ev = setup_signals (&sigs, &signo); + pth_wait (ev); + if (pth_event_occured (ev) && signo) + printf ("signal caught! signo %d\n", signo); + + pth_event_free (ev, PTH_FREE_ALL); + pth_kill (); + return 0; +} + +int +main_3 (int argc, char ** argv) +{ + struct sockaddr_in addr, rem; + int fd, n = 0, infd; + int signo = 0; + struct sigset_s sigs; + pth_event_t ev; + + pth_init (); + fd = socket (AF_INET, SOCK_STREAM, 0); + + memset (&addr, 0, sizeof addr); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons (5050); + addr.sin_family = AF_INET; + bind (fd, (struct sockaddr*)&addr, sizeof addr); + listen (fd, 5); + + ev = setup_signals (&sigs, &signo); + n = sizeof addr; + infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev); + printf ("infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), htons (rem.sin_port)); + + closesocket (infd); + pth_event_free (ev, PTH_FREE_ALL); + pth_kill (); + return 0; +} + +int +main (int argc, char ** argv) +{ + pth_event_t ev; + pth_key_t ev_key; + + pth_init (); + /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0)); + pth_wait (ev); + pth_event_free (ev, PTH_FREE_ALL);*/ + pth_sleep (5); + pth_kill (); + return 0; +} +#endif + #endif /*HAVE_W32_SYSTEM*/ + diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h index 6b57d9bd2..efb17d255 100644 --- a/jnlib/w32-pth.h +++ b/jnlib/w32-pth.h @@ -1,5 +1,6 @@ /* w32-pth.h - GNU Pth emulation for W32 (MS Windows). - * Copyright (C) 2004 g10 Code GmbH + * Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com> + * Copyright (C) 2004 g10 Code GmbH * * This file is part of GnuPG. * @@ -16,6 +17,11 @@ * You should have received a copy of the GNU Lesser 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 code is based on Ralf Engelschall's GNU Pth, a non-preemptive + * thread scheduling library which can be found at + * http://www.gnu.org/software/pth/. */ /* Note that this header is usually used through a symlinked pth.h @@ -24,6 +30,217 @@ #ifndef W32_PTH_H #define W32_PTH_H +#include <windows.h> /* We need this for sockaddr et al. FIXME: too + heavyweight - may be we should factor such + code out to a second header and adjust all + user files to include it only if required. */ + +#ifndef W32_PTH_HANDLE_INTERNAL +#define W32_PTH_HANDLE_INTERNAL int +#endif + + +/* Filedescriptor blocking modes. */ +enum + { + PTH_FDMODE_ERROR = -1, + PTH_FDMODE_POLL = 0, + PTH_FDMODE_BLOCK, + PTH_FDMODE_NONBLOCK + }; + + +/* Mutex values. */ +#define PTH_MUTEX_INITIALIZED (1<<0) +#define PTH_MUTEX_LOCKED (1<<1) +#define PTH_MUTEX_INIT {{NULL, NULL}, PTH_MUTEX_INITIALIZED, NULL, 0} + + +#define PTH_KEY_INIT (1<<0) + + +/* Event subject classes. */ +#define PTH_EVENT_FD (1<<1) +#define PTH_EVENT_SELECT (1<<2) +#define PTH_EVENT_SIGS (1<<3) +#define PTH_EVENT_TIME (1<<4) +#define PTH_EVENT_MSG (1<<5) +#define PTH_EVENT_MUTEX (1<<6) +#define PTH_EVENT_COND (1<<7) +#define PTH_EVENT_TID (1<<8) +#define PTH_EVENT_FUNC (1<<9) + + + +/* Event occurrence restrictions. */ +#define PTH_UNTIL_OCCURRED (1<<11) +#define PTH_UNTIL_FD_READABLE (1<<12) +#define PTH_UNTIL_FD_WRITEABLE (1<<13) +#define PTH_UNTIL_FD_EXCEPTION (1<<14) +#define PTH_UNTIL_TID_NEW (1<<15) +#define PTH_UNTIL_TID_READY (1<<16) +#define PTH_UNTIL_TID_WAITING (1<<17) +#define PTH_UNTIL_TID_DEAD (1<<18) + + +/* Event structure handling modes. */ +#define PTH_MODE_REUSE (1<<20) +#define PTH_MODE_CHAIN (1<<21) +#define PTH_MODE_STATIC (1<<22) + + +/* Attribute commands for pth_attr_get and pth_attr_set(). */ +enum + { + PTH_ATTR_PRIO, /* RW [int] Priority of thread. */ + PTH_ATTR_NAME, /* RW [char *] Name of thread. */ + PTH_ATTR_JOINABLE, /* RW [int] Thread detachment type. */ + PTH_ATTR_CANCEL_STATE, /* RW [unsigned int] Thread cancellation state.*/ + PTH_ATTR_STACK_SIZE, /* RW [unsigned int] Stack size. */ + PTH_ATTR_STACK_ADDR, /* RW [char *] Stack lower address. */ + PTH_ATTR_DISPATCHES, /* RO [int] Total number of + thread dispatches. */ + PTH_ATTR_TIME_SPAWN, /* RO [pth_time_t] Time thread was spawned. */ + PTH_ATTR_TIME_LAST, /* RO [pth_time_t] Time thread was + last dispatched. */ + PTH_ATTR_TIME_RAN, /* RO [pth_time_t] Time thread was running. */ + PTH_ATTR_START_FUNC, /* RO [void *(*)(void *)] Thread start function.*/ + PTH_ATTR_START_ARG, /* RO [void *] Thread start argument. */ + PTH_ATTR_STATE, /* RO [pth_state_t] Scheduling state. */ + PTH_ATTR_EVENTS, /* RO [pth_event_t] Events the thread + is waiting for. */ + PTH_ATTR_BOUND /* RO [int] Whether object is + bound to thread. */ + }; + + + +/* Queries for pth_ctrl(). */ +#define PTH_CTRL_GETAVLOAD (1<<1) +#define PTH_CTRL_GETPRIO (1<<2) +#define PTH_CTRL_GETNAME (1<<3) +#define PTH_CTRL_GETTHREADS_NEW (1<<4) +#define PTH_CTRL_GETTHREADS_READY (1<<5) +#define PTH_CTRL_GETTHREADS_RUNNING (1<<6) +#define PTH_CTRL_GETTHREADS_WAITING (1<<7) +#define PTH_CTRL_GETTHREADS_SUSPENDED (1<<8) +#define PTH_CTRL_GETTHREADS_DEAD (1<<9) +#define PTH_CTRL_DUMPSTATE (1<<10) + +#define PTH_CTRL_GETTHREADS ( PTH_CTRL_GETTHREADS_NEW \ + | PTH_CTRL_GETTHREADS_READY \ + | PTH_CTRL_GETTHREADS_RUNNING \ + | PTH_CTRL_GETTHREADS_WAITING \ + | PTH_CTRL_GETTHREADS_SUSPENDED \ + | PTH_CTRL_GETTHREADS_DEAD ) + + +/* Event status codes. */ +typedef enum + { + PTH_STATUS_PENDING, + PTH_STATUS_OCCURRED, + PTH_STATUS_FAILED + } +pth_status_t; + + +/* Event deallocation types. */ +enum + { + PTH_FREE_THIS, + PTH_FREE_ALL + }; + + +/* The Pth thread handle object. */ +typedef void *pth_t; + + +/* The Mutex object. */ +struct pth_mutex_s +{ + unsigned mx_state; + W32_PTH_HANDLE_INTERNAL mx; +}; +typedef struct pth_mutex_s pth_mutex_t; + + +/* The Event object. */ +struct pth_event_s; +typedef struct pth_event_s *pth_event_t; + + +/* The Attribute object. */ +struct pth_attr_s; +typedef struct pth_attr_s *pth_attr_t; + + +/* The Key object. */ +typedef int pth_key_t; + + +/* The Pth time object. */ +typedef struct timeval pth_time_t; + + +/* Function prototypes. */ +int pth_init (void); +int pth_kill (void); +long pth_ctrl (unsigned long query, ...); + +int pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev); +int pth_read (int fd, void *buffer, size_t size); +int pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev); +int pth_write (int fd, const void *buffer, size_t size); + +int pth_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, + const struct timeval *timeout); + +int pth_accept (int fd, struct sockaddr *addr, int *addrlen); +int pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, + pth_event_t hd); + +int pth_connect (int fd, struct sockaddr *name, int namelen); + + +int pth_mutex_release (pth_mutex_t *hd); +int pth_mutex_acquire(pth_mutex_t *hd, int try_only, pth_event_t ev_extra); +int pth_mutex_init (pth_mutex_t *hd); + + +pth_attr_t pth_attr_new (void); +int pth_attr_destroy (pth_attr_t hd); +int pth_attr_set (pth_attr_t hd, int field, ...); + +pth_t pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg); +int pth_join (pth_t hd, void **value); +int pth_abort (pth_t hd); +void pth_exit (void *value); + +unsigned int pth_waitpid (unsigned int, int *status, int options); +int pth_wait (pth_event_t hd); + +int pth_sleep (int n); +pth_time_t pth_timeout (long sec, long usec); + + + +pth_event_t pth_event_isolate (pth_event_t hd); +int pth_event_free (pth_event_t hd, int mode); +int pth_event_status (pth_event_t hd); +int pth_event_occured (pth_event_t hd); +pth_event_t pth_event_concat (pth_event_t ev, ...); +pth_event_t pth_event (unsigned long spec, ...); + + + +/*-- pth_util.c --*/ + +/* void sigemptyset (struct sigset_s * ss); */ + +/* int sigaddset (struct sigset_s * ss, int signo); */ + #endif /*W32_PTH_H*/ -- cgit v1.2.3 From 801ab885224b7d85aa11cb9f239f33cb420d3159 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 13 Dec 2004 15:49:56 +0000 Subject: VArious hacks to make it at least build under W32. * stringhelp.c (w32_strerror) [W32]: New. * w32-pth.c, w32-pth.h: Added real code written by Timo Schulz. Not finished, though. * gpgconf-comp.c <ignore-ocsp-service-url>: Fixed typo. --- agent/call-scd.c | 6 ++++++ agent/findkey.c | 6 +++++- agent/gpg-agent.c | 48 +++++++++++++++++++++++++++++++++++++++--------- common/simple-pwquery.c | 2 ++ jnlib/ChangeLog | 2 ++ jnlib/stringhelp.c | 46 +++++++++++++++++++++++++++++++++++++--------- jnlib/stringhelp.h | 5 +++++ jnlib/w32-afunix.h | 1 + jnlib/w32-pth.h | 8 +++++++- sm/call-agent.c | 2 +- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 2 +- 12 files changed, 110 insertions(+), 22 deletions(-) diff --git a/agent/call-scd.c b/agent/call-scd.c index 2427d8ca3..575986dc9 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -34,7 +34,9 @@ #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> +#ifndef HAVE_W32_SYSTEM #include <sys/wait.h> +#endif #ifdef USE_GNU_PTH # include <pth.h> #endif @@ -213,6 +215,7 @@ start_scd (ctrl_t ctrl) /* We better do a sanity check now to see whether it has accidently died. */ +#ifndef HAVE_W32_SYSTEM /* fixme */ pid = assuan_get_pid (scd_ctx); if (pid != (pid_t)(-1) && pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) @@ -221,6 +224,7 @@ start_scd (ctrl_t ctrl) scd_ctx = NULL; } else +#endif return 0; } @@ -275,10 +279,12 @@ start_scd (ctrl_t ctrl) simply as a pipe server. */ if (ctrl->connection_fd != -1) { +#ifndef HAVE_W32_SYSTEM char buf[100]; sprintf (buf, "OPTION event-signal=%d", SIGUSR2); assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); +#endif } return 0; diff --git a/agent/findkey.c b/agent/findkey.c index 9866b54b9..b54528295 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -76,7 +76,11 @@ agent_write_private_key (const unsigned char *grip, The mode parameter to open is what fopen uses. It will be combined with the process' umask automatically. */ fd = open (fname, O_CREAT | O_EXCL | O_RDWR, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + S_IRUSR | S_IWUSR +#ifndef HAVE_W32_SYSTEM + | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH +#endif + ); if (fd < 0) fp = 0; else diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 92af49b7a..6801839aa 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -29,9 +29,11 @@ #include <assert.h> #include <time.h> #include <fcntl.h> -#include <sys/socket.h> #include <sys/stat.h> +#ifndef HAVE_W32_SYSTEM +#include <sys/socket.h> #include <sys/un.h> +#endif #include <unistd.h> #include <signal.h> #ifdef USE_GNU_PTH @@ -40,11 +42,13 @@ #define JNLIB_NEED_LOG_LOGV #include "agent.h" -#include <assuan.h> /* malloc hooks */ +#include <assuan.h> /* Malloc hooks */ #include "i18n.h" #include "sysutils.h" - +#ifdef HAVE_W32_SYSTEM +#include "../jnlib/w32-afunix.h" +#endif enum cmd_and_opt_values { aNull = 0, @@ -175,7 +179,9 @@ static void create_directories (void); static void handle_connections (int listen_fd); /* Pth wrapper function definitions. */ +#ifndef HAVE_W32_SYSTEM GCRY_THREAD_OPTION_PTH_IMPL; +#endif #endif /*USE_GNU_PTH*/ static void check_for_running_agent (void); @@ -432,14 +438,14 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ -#ifdef USE_GNU_PTH +#if defined(USE_GNU_PTH) && !defined(HAVE_W32_SYSTEM) err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -#endif /*USE_GNU_PTH*/ +#endif /*USE_GNU_PTH && !HAVE_W32_SYSTEM*/ /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library. */ @@ -707,10 +713,12 @@ main (int argc, char **argv ) } /* Make sure that we have a default ttyname. */ +#ifndef HAVE_W32_SYSTEM if (!default_ttyname && ttyname (1)) default_ttyname = xstrdup (ttyname (1)); if (!default_ttytype && getenv ("TERM")) default_ttytype = xstrdup (getenv ("TERM")); +#endif if (pipe_server) { /* this is the simple pipe based server */ @@ -720,6 +728,7 @@ main (int argc, char **argv ) ; /* NOTREACHED */ else { /* Regular server mode */ +#ifndef HAVE_W32_SYSTEM int fd; pid_t pid; int len; @@ -888,18 +897,21 @@ main (int argc, char **argv ) #ifdef USE_GNU_PTH if (!disable_pth) { +#ifndef HAVE_W32_SYSTEM /* FIXME */ struct sigaction sa; sa.sa_handler = SIG_IGN; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGPIPE, &sa, NULL); +#endif handle_connections (fd); } else #endif /*!USE_GNU_PTH*/ /* setup signals */ { +#ifndef HAVE_W32_SYSTEM /* FIXME */ struct sigaction oact, nact; nact.sa_handler = cleanup_sh; @@ -915,10 +927,11 @@ main (int argc, char **argv ) nact.sa_handler = SIG_IGN; sigaction (SIGPIPE, &nact, NULL); sigaction (SIGINT, &nact, NULL); - +#endif start_command_handler (fd, -1); } close (fd); +#endif } return 0; @@ -1029,9 +1042,15 @@ create_private_keys_directory (const char *home) fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL); if (stat (fname, &statbuf) && errno == ENOENT) { +#ifdef HAVE_W32_SYSTEM /*FIXME: Setup proper permissions. */ + if (!CreateDirectory (fname, NULL)) + log_error (_("can't create directory `%s': %s\n"), + fname, w32_strerror (-1) ); +#else if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR )) log_error (_("can't create directory `%s': %s\n"), - fname, strerror(errno) ); + fname, strerror (errno) ); +#endif else if (!opt.quiet) log_info (_("directory `%s' created\n"), fname); } @@ -1063,9 +1082,15 @@ create_directories (void) || (*defhome != '~' && !strcmp (home, defhome) ) ) { +#ifdef HAVE_W32_SYSTEM + if (!CreateDirectory (home, NULL)) + log_error (_("can't create directory `%s': %s\n"), + home, w32_strerror (-1) ); +#else if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR )) log_error (_("can't create directory `%s': %s\n"), - home, strerror(errno) ); + home, strerror (errno) ); +#endif else { if (!opt.quiet) @@ -1096,6 +1121,7 @@ handle_signal (int signo) { switch (signo) { +#ifndef HAVE_W32_SYSTEM case SIGHUP: log_info ("SIGHUP received - " "re-reading configuration and flushing cache\n"); @@ -1134,7 +1160,7 @@ handle_signal (int signo) cleanup (); agent_exit (0); break; - +#endif default: log_info ("signal %d received - no action defined\n", signo); } @@ -1178,6 +1204,7 @@ handle_connections (int listen_fd) pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024); pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent"); +#ifndef HAVE_W32_SYSTEM /* fixme */ sigemptyset (&sigs ); sigaddset (&sigs, SIGHUP); sigaddset (&sigs, SIGUSR1); @@ -1185,6 +1212,9 @@ handle_connections (int listen_fd) sigaddset (&sigs, SIGINT); sigaddset (&sigs, SIGTERM); ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); +#else + ev = NULL; +#endif for (;;) { diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index fab6306fa..1e8eae63b 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -182,8 +182,10 @@ agent_send_all_options (int fd) } dft_ttyname = getenv ("GPG_TTY"); +#ifndef HAVE_W32_SYSTEM if ((!dft_ttyname || !*dft_ttyname) && ttyname (0)) dft_ttyname = ttyname (0); +#endif if (dft_ttyname && *dft_ttyname) { if ((rc=agent_send_option (fd, "ttyname", dft_ttyname))) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index b33b7842f..f27ef87b6 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,5 +1,7 @@ 2004-12-13 Werner Koch <wk@g10code.com> + * stringhelp.c (w32_strerror) [W32]: New. + * w32-pth.c, w32-pth.h: Added real code written by Timo Schulz. Not finished, though. diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 568152fdd..5a3b41528 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -1,5 +1,6 @@ /* stringhelp.c - standard string helper functions - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,14 +24,17 @@ #include <string.h> #include <stdarg.h> #include <ctype.h> +#ifdef HAVE_W32_SYSTEM +#include <windows.h> +#endif #include "libjnlib-config.h" #include "utf8conv.h" #include "stringhelp.h" -/**************** - * look for the substring SUB in buffer and return a pointer to that +/* + * Look for the substring SUB in buffer and return a pointer to that * substring in BUF or NULL if not found. * Comparison is case-insensitive. */ @@ -72,11 +76,12 @@ ascii_memistr( const char *buf, size_t buflen, const char *sub ) return NULL ; } -/**************** - * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein - * '\0' angehngt. Ist n = 0, so geschieht nichts, ist Destination - * gleich NULL, so wird via jnlib_xmalloc Speicher besorgt, ist dann nicht - * gengend Speicher vorhanden, so bricht die funktion ab. +/* This function is similar to strncpy(). However it won't copy more + than N - 1 characters and makes sure that a '\0' is appended. With + N given as 0, nothing will happen. With DEST given as NULL, memory + will be allocated using jnlib_xmalloc (i.e. if it runs out of core + the function terminates). Returns DES or a pointer to the + allocated memory. */ char * mem2str( char *dest , const void *src , size_t n ) @@ -452,8 +457,29 @@ sanitize_buffer (const unsigned char *p, size_t n, int delim) return buffer; } + /**************************************************** - ******** locale insensitive ctype functions ******** + ********** W32 specific functions **************** + ****************************************************/ + +#ifdef HAVE_W32_SYSTEM +const char * +w32_strerror (int ec) +{ + static char strerr[256]; + + if (ec == -1) + ec = (int)GetLastError (); + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, DIM (strerr)-1, NULL); + return strerr; +} +#endif /*HAVE_W32_SYSTEM*/ + + +/**************************************************** + ******** Locale insensitive ctype functions ******** ****************************************************/ /* FIXME: replace them by a table lookup and macros */ int @@ -626,3 +652,5 @@ memicmp( const char *a, const char *b, size_t n ) return 0; } #endif + + diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index fe5786e59..412da3a0e 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -49,6 +49,11 @@ size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); char *sanitize_buffer (const unsigned char *p, size_t n, int delim); +#ifdef HAVE_W32_SYSTEM +const char *w32_strerror (int ec); +#endif + + const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); int ascii_isupper (int c); int ascii_islower (int c); diff --git a/jnlib/w32-afunix.h b/jnlib/w32-afunix.h index 1319de5e6..367832299 100644 --- a/jnlib/w32-afunix.h +++ b/jnlib/w32-afunix.h @@ -23,6 +23,7 @@ #include <sys/types.h> #include <windows.h> +#include <ws2tcpip.h> #include <unistd.h> #define DIRSEP_C '\\' diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h index efb17d255..bb010ae99 100644 --- a/jnlib/w32-pth.h +++ b/jnlib/w32-pth.h @@ -53,7 +53,7 @@ enum /* Mutex values. */ #define PTH_MUTEX_INITIALIZED (1<<0) #define PTH_MUTEX_LOCKED (1<<1) -#define PTH_MUTEX_INIT {{NULL, NULL}, PTH_MUTEX_INITIALIZED, NULL, 0} +#define PTH_MUTEX_INIT {PTH_MUTEX_INITIALIZED} #define PTH_KEY_INIT (1<<0) @@ -235,6 +235,12 @@ pth_event_t pth_event (unsigned long spec, ...); +/* Backward compatibility (Pth < 1.5.0). */ +#define pth_event_occurred(ev) \ + ( pth_event_status(ev) == PTH_STATUS_OCCURRED \ + || pth_event_status(ev) == PTH_STATUS_FAILED ) + + /*-- pth_util.c --*/ /* void sigemptyset (struct sigset_s * ss); */ diff --git a/sm/call-agent.c b/sm/call-agent.c index 2e8c75496..3ea1c4565 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -113,7 +113,7 @@ start_agent (ctrl_t ctrl) no_close_list[i++] = fileno (stderr); no_close_list[i] = -1; - /* connect to the agent and perform initial handshaking */ + /* Connect to the agent and perform initial handshaking. */ rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv, no_close_list); } diff --git a/tools/ChangeLog b/tools/ChangeLog index ac8d54a47..cb341ad4f 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2004-12-13 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c <ignore-ocsp-service-url>: Fixed typo. + 2004-11-24 Werner Koch <wk@g10code.com> * gpgconf-comp.c <dirmngr>: Add --ignore-http-dp, --ignore-ldap-dp diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 8873cdf13..5d78df86d 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -790,7 +790,7 @@ static gc_option_t gc_options_dirmngr[] = { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "dirmngr", "allow sending OCSP requests", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, - { "ignore-ocsp-servic-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "ignore certificate contained OCSP service URLs", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, -- cgit v1.2.3 From db27cdff413da847c956bd36c68e46f3b47c3808 Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Mon, 13 Dec 2004 18:00:35 +0000 Subject: 2004-12-13 Timo Schulz <twoaday@g10code.com> * w32-pth.c (enter_pth, leave_pth): New. (pth_init): Initialize global mutex section. (pth_kill): Release global mutex section. (helper_thread): New. (pth_spawn): Make sure only one thread is running. --- jnlib/ChangeLog | 8 + jnlib/w32-pth.c | 1297 +++++++++++++++++++++++++++++-------------------------- 2 files changed, 693 insertions(+), 612 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index f27ef87b6..de73ef40e 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,11 @@ +2004-12-13 Timo Schulz <twoaday@g10code.com> + + * w32-pth.c (enter_pth, leave_pth): New. + (pth_init): Initialize global mutex section. + (pth_kill): Release global mutex section. + (helper_thread): New. + (pth_spawn): Make sure only one thread is running. + 2004-12-13 Werner Koch <wk@g10code.com> * stringhelp.c (w32_strerror) [W32]: New. diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 80a58d859..ed0eb93ad 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -27,8 +27,9 @@ #include <config.h> #ifdef HAVE_W32_SYSTEM -#include <stdio.h> #include <windows.h> +#include <stdio.h> +#include <stdlib.h> #include <io.h> #include <signal.h> @@ -38,38 +39,51 @@ #include "w32-pth.h" +static int pth_initialized = 0; + +/* Variables to support event handling. */ static int pth_signo = 0; static HANDLE pth_signo_ev = NULL; -static int pth_initialized = 0; +/* Mutex to make sure only one thread is running. */ +static CRITICAL_SECTION pth_shd; #define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) +static void * helper_thread (void * ctx); -struct pth_event_s +struct pth_event_s { - struct pth_event_s * next; - struct pth_event_s * prev; - HANDLE hd; - union { - struct sigset_s * sig; - int fd; - struct timeval tv; - pth_mutex_t * mx; - } u; - int * val; - int u_type; - int flags; + struct pth_event_s * next; + struct pth_event_s * prev; + HANDLE hd; + union + { + struct sigset_s * sig; + int fd; + struct timeval tv; + pth_mutex_t * mx; + } u; + int * val; + int u_type; + int flags; }; struct pth_attr_s { - unsigned int flags; - unsigned int stack_size; - char * name; + unsigned int flags; + unsigned int stack_size; + char * name; +}; + + +struct _pth_priv_hd_s +{ + void *(*thread)(void *); + void * arg; }; @@ -77,44 +91,65 @@ struct pth_attr_s int pth_init (void) { - SECURITY_ATTRIBUTES sa; - WSADATA wsadat; + SECURITY_ATTRIBUTES sa; + WSADATA wsadat; - printf ("pth_init: called.\n"); - pth_initialized = 1; - if (WSAStartup (0x202, &wsadat)) - return -1; - pth_signo = 0; - if (pth_signo_ev) - CloseHandle (pth_signo_ev); - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL); - - return 0; + printf ("pth_init: called.\n"); + pth_initialized = 1; + if (WSAStartup (0x202, &wsadat)) + abort (); + pth_signo = 0; + InitializeCriticalSection (&pth_shd); + if (pth_signo_ev) + CloseHandle (pth_signo_ev); + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL); + if (!pth_signo_ev) + abort (); + EnterCriticalSection (&pth_shd); + return 0; } int pth_kill (void) { - pth_signo = 0; - if (pth_signo_ev) - CloseHandle (pth_signo_ev); - WSACleanup (); - pth_initialized = 0; - return 0; + pth_signo = 0; + if (pth_signo_ev) + CloseHandle (pth_signo_ev); + DeleteCriticalSection (&pth_shd); + WSACleanup (); + pth_initialized = 0; + return 0; +} + + +static void +enter_pth (void) +{ + EnterCriticalSection (&pth_shd); + /*LeaveCriticalSection (&pth_shd);*/ +} + + +static void +leave_pth (void) +{ + LeaveCriticalSection (&pth_shd); + /*EnterCriticalSection (&pth_shd);*/ } long pth_ctrl (unsigned long query, ...) { - implicit_init (); + implicit_init (); - switch (query) { + switch (query) + { case PTH_CTRL_GETAVLOAD: case PTH_CTRL_GETPRIO: case PTH_CTRL_GETNAME: @@ -124,11 +159,11 @@ pth_ctrl (unsigned long query, ...) case PTH_CTRL_GETTHREADS_WAITING: case PTH_CTRL_GETTHREADS_SUSPENDED: case PTH_CTRL_GETTHREADS_DEAD: - /*case PTH_CTRL_GETTHREADS:*/ + case PTH_CTRL_GETTHREADS: default: - return -1; + return -1; } - return 0; + return 0; } @@ -136,63 +171,65 @@ pth_ctrl (unsigned long query, ...) pth_time_t pth_timeout (long sec, long usec) { - pth_time_t tvd; + pth_time_t tvd; - tvd.tv_sec = sec; - tvd.tv_usec = usec; - return tvd; + tvd.tv_sec = sec; + tvd.tv_usec = usec; + return tvd; } int pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev) { - implicit_init (); - return 0; + implicit_init (); + return 0; } int pth_read (int fd, void * buffer, size_t size) { - int n; - - implicit_init (); - n = recv (fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { - DWORD nread = 0; - n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); - if (!n) - return -1; - return (int)nread; + int n; + + implicit_init (); + n = recv (fd, buffer, size, 0); + if (n == -1 && WSAGetLastError () == WSAENOTSOCK) + { + DWORD nread = 0; + n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); + if (!n) + return -1; + return (int)nread; } - return n; + return n; } int pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev) { - implicit_init (); - return 0; + implicit_init (); + return 0; } int pth_write (int fd, const void * buffer, size_t size) { - int n; - - implicit_init (); - n = send (fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { - DWORD nwrite; - n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); - if (!n) - return -1; - return (int)nwrite; + int n; + + implicit_init (); + n = send (fd, buffer, size, 0); + if (n == -1 && WSAGetLastError () == WSAENOTSOCK) + { + DWORD nwrite; + n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); + if (!n) + return -1; + return (int)nwrite; } - return n; + return n; } @@ -200,279 +237,306 @@ int pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds, const struct timeval * timeout) { - implicit_init (); - return select (nfds, rfds, wfds, efds, timeout); + implicit_init (); + return select (nfds, rfds, wfds, efds, timeout); } int pth_fdmode (int fd, int mode) { - unsigned long val; + unsigned long val; - implicit_init (); - /* XXX: figure out original fd mode */ - switch (mode) { + implicit_init (); + /* XXX: figure out original fd mode */ + switch (mode) + { case PTH_FDMODE_NONBLOCK: - val = 1; - if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - return PTH_FDMODE_ERROR; - break; + val = 1; + if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) + return PTH_FDMODE_ERROR; + break; case PTH_FDMODE_BLOCK: - val = 0; - if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - return PTH_FDMODE_ERROR; - break; + val = 0; + if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) + return PTH_FDMODE_ERROR; + break; } - return PTH_FDMODE_BLOCK; + return PTH_FDMODE_BLOCK; } int pth_accept (int fd, struct sockaddr *addr, int *addrlen) { - implicit_init (); - return accept (fd, addr, addrlen); + implicit_init (); + return accept (fd, addr, addrlen); } int -pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, pth_event_t ev_extra) +pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, + pth_event_t ev_extra) { - pth_key_t ev_key; - pth_event_t ev; - int rv; - int fdmode; - - implicit_init (); - - fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK); - if (fdmode == PTH_FDMODE_ERROR) - return -1; - - ev = NULL; - while ((rv = accept (fd, addr, addrlen)) == -1 && - (WSAGetLastError () == WSAEINPROGRESS || - WSAGetLastError () == WSAEWOULDBLOCK)) { - if (ev == NULL) { - ev = pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_MODE_STATIC, &ev_key, fd); - if (ev == NULL) - return -1; - if (ev_extra != NULL) - pth_event_concat (ev, ev_extra, NULL); - } - /* wait until accept has a chance */ - pth_wait (ev); - if (ev_extra != NULL) { - pth_event_isolate (ev); - if (pth_event_status (ev) != PTH_STATUS_OCCURRED) { - pth_fdmode (fd, fdmode); - return -1; + pth_key_t ev_key; + pth_event_t ev; + int rv; + int fdmode; + + implicit_init (); + + fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK); + if (fdmode == PTH_FDMODE_ERROR) + return -1; + + ev = NULL; + while ((rv = accept (fd, addr, addrlen)) == -1 && + (WSAGetLastError () == WSAEINPROGRESS || + WSAGetLastError () == WSAEWOULDBLOCK)) + { + if (ev == NULL) { + ev = pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_MODE_STATIC, + &ev_key, fd); + if (ev == NULL) + return -1; + if (ev_extra != NULL) + pth_event_concat (ev, ev_extra, NULL); + } + /* wait until accept has a chance */ + pth_wait (ev); + if (ev_extra != NULL) + { + pth_event_isolate (ev); + if (pth_event_status (ev) != PTH_STATUS_OCCURRED) + { + pth_fdmode (fd, fdmode); + return -1; } } } - pth_fdmode (fd, fdmode); - return rv; + pth_fdmode (fd, fdmode); + return rv; } int pth_connect (int fd, struct sockaddr *name, int namelen) { - implicit_init (); - return connect (fd, name, namelen); + implicit_init (); + return connect (fd, name, namelen); } int pth_mutex_release (pth_mutex_t *hd) { - if (!hd) - return -1; - implicit_init (); - if (hd->mx) { - CloseHandle (hd->mx); - hd->mx = NULL; + if (!hd) + return -1; + implicit_init (); + if (hd->mx) + { + CloseHandle (hd->mx); + hd->mx = NULL; } - free (hd); - return 0; + free (hd); + return 0; } int pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) { - implicit_init (); + implicit_init (); - if (!hd) - return -1; - if (!hd->mx) - return -1; + if (!hd) + return -1; + if (!hd->mx) + return -1; #if 0 - /* still not locked, so simply acquire mutex? */ - if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) { - mutex->mx_state |= PTH_MUTEX_LOCKED; - mutex->mx_count = 1; - pth_ring_append(&(pth_current->mutexring), &(mutex->mx_node)); - pth_debug1("pth_mutex_acquire: immediately locking mutex"); - return 0; + /* still not locked, so simply acquire mutex? */ + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) + { + mutex->mx_state |= PTH_MUTEX_LOCKED; + mutex->mx_count = 1; + pth_ring_append(&(pth_current->mutexring), &(mutex->mx_node)); + pth_debug1("pth_mutex_acquire: immediately locking mutex"); + return 0; } - /* already locked by caller? */ - if (mutex->mx_count >= 1 && mutex->mx_owner == pth_current) { - /* recursive lock */ - mutex->mx_count++; - pth_debug1("pth_mutex_acquire: recursive locking"); - return 0; + /* already locked by caller? */ + if (mutex->mx_count >= 1 && mutex->mx_owner == pth_current) + { + /* recursive lock */ + mutex->mx_count++; + pth_debug1("pth_mutex_acquire: recursive locking"); + return 0; } - if (tryonly) - return return -1; - - for (;;) { - ev = pth_event(PTH_EVENT_MUTEX|PTH_MODE_STATIC, &ev_key, mutex); - if (ev_extra != NULL) - pth_event_concat (ev, ev_extra, NULL); - pth_wait (ev); - if (ev_extra != NULL) { - pth_event_isolate (ev); - if (pth_event_status(ev) == PTH_STATUS_PENDING) - return return -1; - } - if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) - break; + if (tryonly) + return return -1; + + for (;;) + { + ev = pth_event(PTH_EVENT_MUTEX|PTH_MODE_STATIC, &ev_key, mutex); + if (ev_extra != NULL) + pth_event_concat (ev, ev_extra, NULL); + pth_wait (ev); + if (ev_extra != NULL) { + pth_event_isolate (ev); + if (pth_event_status(ev) == PTH_STATUS_PENDING) + return return -1; + } + if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) + break; } #endif - hd->mx_state |= PTH_MUTEX_LOCKED; - return 0; + hd->mx_state |= PTH_MUTEX_LOCKED; + return 0; } int pth_mutex_init (pth_mutex_t *hd) { - SECURITY_ATTRIBUTES sa; - implicit_init (); - if (hd->mx) { - ReleaseMutex (hd->mx); - CloseHandle (hd->mx); + SECURITY_ATTRIBUTES sa; + + implicit_init (); + if (hd->mx) + { + ReleaseMutex (hd->mx); + CloseHandle (hd->mx); } - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - hd->mx = CreateMutex (&sa, FALSE, NULL); - hd->mx_state = PTH_MUTEX_INITIALIZED; - return 0; + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + hd->mx = CreateMutex (&sa, FALSE, NULL); + hd->mx_state = PTH_MUTEX_INITIALIZED; + return 0; } pth_attr_t pth_attr_new (void) { - pth_attr_t hd; + pth_attr_t hd; - implicit_init (); - hd = calloc (1, sizeof *hd); - if (!hd) - return NULL; - return hd; + implicit_init (); + hd = calloc (1, sizeof *hd); + if (!hd) + return NULL; + return hd; } int pth_attr_destroy (pth_attr_t hd) { - if (!hd) - return -1; - implicit_init (); - if (hd->name) - free (hd->name); - free (hd); - return 0; + if (!hd) + return -1; + implicit_init (); + if (hd->name) + free (hd->name); + free (hd); + return 0; } int pth_attr_set (pth_attr_t hd, int field, ...) { - va_list args; - char * str; - int val; - int rc = 0; - - implicit_init (); - va_start (args, field); - switch (field) { + va_list args; + char * str; + int val; + int rc = 0; + + implicit_init (); + va_start (args, field); + switch (field) + { case PTH_ATTR_JOINABLE: - val = va_arg (args, int); - if (val) { - hd->flags |= PTH_ATTR_JOINABLE; - printf ("pth_attr_set: PTH_ATTR_JOINABLE\n"); - } - break; + val = va_arg (args, int); + if (val) + { + hd->flags |= PTH_ATTR_JOINABLE; + printf ("pth_attr_set: PTH_ATTR_JOINABLE\n"); + } + break; case PTH_ATTR_STACK_SIZE: - val = va_arg (args, int); - if (val) { - hd->flags |= PTH_ATTR_STACK_SIZE; - hd->stack_size = val; - printf ("pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", val); - } - break; + val = va_arg (args, int); + if (val) + { + hd->flags |= PTH_ATTR_STACK_SIZE; + hd->stack_size = val; + printf ("pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", val); + } + break; case PTH_ATTR_NAME: - str = va_arg (args, char*); - if (hd->name) - free (hd->name); - if (str) { - hd->name = strdup (str); - if (!hd->name) - return -1; - hd->flags |= PTH_ATTR_NAME; - printf ("pth_attr_set: PTH_ATTR_NAME %s\n", hd->name); - } - break; + str = va_arg (args, char*); + if (hd->name) + free (hd->name); + if (str) + { + hd->name = strdup (str); + if (!hd->name) + return -1; + hd->flags |= PTH_ATTR_NAME; + printf ("pth_attr_set: PTH_ATTR_NAME %s\n", hd->name); + } + break; default: - rc = -1; - break; + rc = -1; + break; } - va_end (args); - return rc; + va_end (args); + return rc; } pth_t pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) { - SECURITY_ATTRIBUTES sa; - DWORD tid; - HANDLE th; - - if (!hd) - return NULL; + SECURITY_ATTRIBUTES sa; + DWORD tid; + HANDLE th; + struct _pth_priv_hd_s * ctx; - implicit_init (); + if (!hd) + return NULL; - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - - th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)func, arg, 0, &tid); - return th; + implicit_init (); + + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + + ctx = calloc (1, sizeof * ctx); + ctx->thread = func; + ctx->arg = arg; + + /* XXX: we don't use all thread attributes. */ + enter_pth (); + th = CreateThread (&sa, hd->stack_size, + (LPTHREAD_START_ROUTINE)helper_thread, + ctx, 0, &tid); + leave_pth (); + + return th; } int pth_join (pth_t hd, void **value) { - return 0; + return 0; } @@ -480,12 +544,12 @@ pth_join (pth_t hd, void **value) int pth_cancel (pth_t hd) { - if (!hd) - return -1; - implicit_init (); - WaitForSingleObject (hd, 1000); - TerminateThread (hd, 0); - return 0; + if (!hd) + return -1; + implicit_init (); + WaitForSingleObject (hd, 1000); + TerminateThread (hd, 0); + return 0; } @@ -493,217 +557,242 @@ pth_cancel (pth_t hd) int pth_abort (pth_t hd) { - if (!hd) - return -1; - implicit_init (); - TerminateThread (hd, 0); - return 0; + if (!hd) + return -1; + implicit_init (); + TerminateThread (hd, 0); + return 0; } void pth_exit (void *value) { - implicit_init (); - pth_kill (); - exit ((int)(long)value); + implicit_init (); + pth_kill (); + exit ((int)(long)value); } unsigned pth_waitpid (unsigned pid, int * status, int options) { - implicit_init (); + implicit_init (); #if 0 - pth_event_t ev; - static pth_key_t ev_key = PTH_KEY_INIT; - pid_t pid; - - pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name); - - for (;;) { - /* do a non-blocking poll for the pid */ - while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0 - && errno == EINTR) ; - - /* if pid was found or caller requested a polling return immediately */ - if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) - break; - - /* else wait a little bit */ - ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, pth_timeout(0,250000)); - pth_wait(ev); + pth_event_t ev; + static pth_key_t ev_key = PTH_KEY_INIT; + pid_t pid; + + pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name); + + for (;;) + { + /* do a non-blocking poll for the pid */ + while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0 + && errno == EINTR) + ; + + /* if pid was found or caller requested a polling return immediately */ + if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) + break; + + /* else wait a little bit */ + ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, + pth_timeout (0,250000)); + pth_wait(ev); } - pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name); + pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name); #endif - return 0; + return 0; } static BOOL WINAPI sig_handler (DWORD signo) { - switch (signo) { + switch (signo) + { case CTRL_C_EVENT: pth_signo = SIGINT; break; case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; } - SetEvent (pth_signo_ev); - printf ("sig_handler=%d\n", pth_signo); - return TRUE; + SetEvent (pth_signo_ev); + printf ("sig_handler=%d\n", pth_signo); + return TRUE; } pth_event_t pth_event (unsigned long spec, ...) { - va_list arg; - SECURITY_ATTRIBUTES sa; - pth_event_t ev; - int rc; - - implicit_init (); - printf ("pth_event spec=%lu\n", spec); - va_start (arg, spec); - ev = calloc (1, sizeof *ev); - if (!ev) - return NULL; - if (spec == 0) - ; - else if (spec & PTH_EVENT_SIGS) { - ev->u.sig = va_arg (arg, struct sigset_s *); - ev->u_type = PTH_EVENT_SIGS; - ev->val = va_arg (arg, int *); - rc = SetConsoleCtrlHandler (sig_handler, TRUE); - printf ("pth_event: sigs rc=%d\n", rc); + va_list arg; + SECURITY_ATTRIBUTES sa; + pth_event_t ev; + int rc; + + implicit_init (); + printf ("pth_event spec=%lu\n", spec); + va_start (arg, spec); + ev = calloc (1, sizeof *ev); + if (!ev) + return NULL; + if (spec == 0) + ; + else if (spec & PTH_EVENT_SIGS) + { + ev->u.sig = va_arg (arg, struct sigset_s *); + ev->u_type = PTH_EVENT_SIGS; + ev->val = va_arg (arg, int *); + rc = SetConsoleCtrlHandler (sig_handler, TRUE); + printf ("pth_event: sigs rc=%d\n", rc); } - else if (spec & PTH_EVENT_FD) { - if (spec & PTH_UNTIL_FD_READABLE) - ev->flags |= PTH_UNTIL_FD_READABLE; - if (spec & PTH_MODE_STATIC) - ev->flags |= PTH_MODE_STATIC; - ev->u_type = PTH_EVENT_FD; - va_arg (arg, pth_key_t); - ev->u.fd = va_arg (arg, int); - printf ("pth_event: fd=%d\n", ev->u.fd); + else if (spec & PTH_EVENT_FD) + { + if (spec & PTH_UNTIL_FD_READABLE) + ev->flags |= PTH_UNTIL_FD_READABLE; + if (spec & PTH_MODE_STATIC) + ev->flags |= PTH_MODE_STATIC; + ev->u_type = PTH_EVENT_FD; + va_arg (arg, pth_key_t); + ev->u.fd = va_arg (arg, int); + printf ("pth_event: fd=%d\n", ev->u.fd); } - else if (spec & PTH_EVENT_TIME) { - pth_time_t t; - if (spec & PTH_MODE_STATIC) - ev->flags |= PTH_MODE_STATIC; - va_arg (arg, pth_key_t); - t = va_arg (arg, pth_time_t); - ev->u_type = PTH_EVENT_TIME; - ev->u.tv.tv_sec = t.tv_sec; - ev->u.tv.tv_usec = t.tv_usec; + else if (spec & PTH_EVENT_TIME) + { + pth_time_t t; + if (spec & PTH_MODE_STATIC) + ev->flags |= PTH_MODE_STATIC; + va_arg (arg, pth_key_t); + t = va_arg (arg, pth_time_t); + ev->u_type = PTH_EVENT_TIME; + ev->u.tv.tv_sec = t.tv_sec; + ev->u.tv.tv_usec = t.tv_usec; } - else if (spec & PTH_EVENT_MUTEX) { - va_arg (arg, pth_key_t); - ev->u_type = PTH_EVENT_MUTEX; - ev->u.mx = va_arg (arg, pth_mutex_t*); + else if (spec & PTH_EVENT_MUTEX) + { + va_arg (arg, pth_key_t); + ev->u_type = PTH_EVENT_MUTEX; + ev->u.mx = va_arg (arg, pth_mutex_t*); } - va_end (arg); + va_end (arg); - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL); - if (!ev->hd) { - free (ev); - return NULL; + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL); + if (!ev->hd) + { + free (ev); + return NULL; } - return ev; + return ev; } static void pth_event_add (pth_event_t root, pth_event_t node) { - pth_event_t n; + pth_event_t n; - for (n=root; n->next; n = n->next) - ; - n->next = node; + for (n=root; n->next; n = n->next) + ; + n->next = node; } pth_event_t pth_event_concat (pth_event_t evf, ...) { - pth_event_t evn; - va_list ap; + pth_event_t evn; + va_list ap; - if (!evf) - return NULL; + if (!evf) + return NULL; - implicit_init (); - va_start (ap, evf); - while ((evn = va_arg(ap, pth_event_t)) != NULL) - pth_event_add (evf, evn); - va_end (ap); + implicit_init (); + va_start (ap, evf); + while ((evn = va_arg(ap, pth_event_t)) != NULL) + pth_event_add (evf, evn); + va_end (ap); - return evf; + return evf; } static int wait_for_fd (int fd, int is_read, int nwait) { - struct timeval tv; - fd_set r; - fd_set w; - int n; - - FD_ZERO (&r); - FD_ZERO (&w); - FD_SET (fd, is_read ? &r : &w); - - tv.tv_sec = nwait; - tv.tv_usec = 0; - - while (1) { - n = select (fd+1, &r, &w, NULL, &tv); - printf ("wait_for_fd=%d fd %d (ec=%d)\n", n, fd, (int)WSAGetLastError ()); - if (n == -1) - break; - if (!n) - continue; - if (n == 1) { - if (is_read && FD_ISSET (fd, &r)) - break; - else if (FD_ISSET (fd, &w)) - break; - } + struct timeval tv; + fd_set r; + fd_set w; + int n; + + FD_ZERO (&r); + FD_ZERO (&w); + FD_SET (fd, is_read ? &r : &w); + + tv.tv_sec = nwait; + tv.tv_usec = 0; + + while (1) + { + n = select (fd+1, &r, &w, NULL, &tv); + printf ("wait_for_fd=%d fd %d (ec=%d)\n", n, fd,(int)WSAGetLastError ()); + if (n == -1) + break; + if (!n) + continue; + if (n == 1) + { + if (is_read && FD_ISSET (fd, &r)) + break; + else if (FD_ISSET (fd, &w)) + break; + } } - return 0; + return 0; +} + + +static void * +helper_thread (void * ctx) +{ + struct _pth_priv_hd_s * c = ctx; + + leave_pth (); + c->thread (c->arg); + enter_pth (); + free (c); + ExitThread (0); + return NULL; } static void * wait_fd_thread (void * ctx) { - pth_event_t ev = ctx; + pth_event_t ev = ctx; - wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - printf ("wait_fd_thread: exit.\n"); - SetEvent (ev->hd); - ExitThread (0); - return NULL; + wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); + printf ("wait_fd_thread: exit.\n"); + SetEvent (ev->hd); + ExitThread (0); + return NULL; } static void * wait_timer_thread (void * ctx) { - pth_event_t ev = ctx; - int n = ev->u.tv.tv_sec*1000; - Sleep (n); - SetEvent (ev->hd); - printf ("wait_timer_thread: exit.\n"); - ExitThread (0); - return NULL; + pth_event_t ev = ctx; + int n = ev->u.tv.tv_sec*1000; + Sleep (n); + SetEvent (ev->hd); + printf ("wait_timer_thread: exit.\n"); + ExitThread (0); + return NULL; } @@ -746,216 +835,199 @@ sigpresent (struct sigset_s * ss, int signo) int pth_event_occured (pth_event_t ev) { - if (!ev) - return 0; - implicit_init (); - switch (ev->u_type) { + if (!ev) + return 0; + implicit_init (); + switch (ev->u_type) + { case 0: - if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) - return 1; - break; + if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) + return 1; + break; case PTH_EVENT_SIGS: - if (sigpresent (ev->u.sig, pth_signo) && - WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) { - printf ("pth_event_occured: sig signaled.\n"); - (*ev->val) = pth_signo; - return 1; - } - break; + if (sigpresent (ev->u.sig, pth_signo) && + WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) + { + printf ("pth_event_occured: sig signaled.\n"); + (*ev->val) = pth_signo; + return 1; + } + break; case PTH_EVENT_FD: - if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) - return 1; - break; + if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) + return 1; + break; } - return 0; + return 0; } int pth_event_status (pth_event_t ev) { - if (!ev) - return 0; - implicit_init (); - if (pth_event_occured (ev)) - return PTH_STATUS_OCCURRED; + if (!ev) return 0; + implicit_init (); + if (pth_event_occured (ev)) + return PTH_STATUS_OCCURRED; + return 0; } int pth_event_free (pth_event_t ev, int mode) { - pth_event_t n; - - implicit_init (); - if (mode == PTH_FREE_ALL) { - while (ev) { - n = ev->next; - CloseHandle (ev->hd); ev->hd = NULL; - free (ev); - ev = n; - } + pth_event_t n; + + implicit_init (); + if (mode == PTH_FREE_ALL) + { + while (ev) + { + n = ev->next; + CloseHandle (ev->hd); ev->hd = NULL; + free (ev); + ev = n; + } } - else if (mode == PTH_FREE_THIS) { - ev->prev->next = ev->next; - ev->next->prev = ev->prev; - CloseHandle (ev->hd); ev->hd = NULL; - free (ev); + else if (mode == PTH_FREE_THIS) + { + ev->prev->next = ev->next; + ev->next->prev = ev->prev; + CloseHandle (ev->hd); ev->hd = NULL; + free (ev); } - return 0; + return 0; } pth_event_t pth_event_isolate (pth_event_t ev) { - pth_event_t ring = NULL; + pth_event_t ring = NULL; - if (!ev) - return NULL; - implicit_init (); - return ring; - + if (!ev) + return NULL; + implicit_init (); + return ring; } static void free_threads (HANDLE *waitbuf, int *hdidx, int n) { - int i; + int i; - for (i=0; i < n; i++) - CloseHandle (waitbuf[hdidx[i]]); + for (i=0; i < n; i++) + CloseHandle (waitbuf[hdidx[i]]); } static int pth_event_count (pth_event_t ev) { - pth_event_t p; - int cnt=0; - - if (!ev) - return 0; - for (p=ev; p; p = p->next) - cnt++; - return cnt; + pth_event_t p; + int cnt=0; + + if (!ev) + return 0; + for (p=ev; p; p = p->next) + cnt++; + return cnt; } int pth_wait (pth_event_t ev) { - HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; - int hdidx[MAXIMUM_WAIT_OBJECTS/2]; - DWORD n = 0; - pth_attr_t attr; - pth_event_t tmp; - int pos=0, i=0; - - if (!ev) - return 0; - - implicit_init (); - attr = pth_attr_new (); - pth_attr_set (attr, PTH_ATTR_JOINABLE, 1); - pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 4096); + HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; + int hdidx[MAXIMUM_WAIT_OBJECTS/2]; + DWORD n = 0; + pth_attr_t attr; + pth_event_t tmp; + int pos=0, i=0; + + if (!ev) + return 0; + + implicit_init (); + attr = pth_attr_new (); + pth_attr_set (attr, PTH_ATTR_JOINABLE, 1); + pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 4096); - printf ("pth_wait: cnt %d\n", pth_event_count (ev)); - for (tmp = ev; tmp; tmp = tmp->next) { - if (pos+1 > MAXIMUM_WAIT_OBJECTS/2) { - free_threads (waitbuf, hdidx, i); - pth_attr_destroy (attr); - return -1; - } - switch (tmp->u_type) { - case 0: - waitbuf[pos++] = tmp->hd; - break; - - case PTH_EVENT_SIGS: - waitbuf[pos++] = pth_signo_ev; - printf ("pth_wait: add signal event.\n"); - break; - - case PTH_EVENT_FD: - printf ("pth_wait: spawn event wait thread.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = pth_spawn (attr, wait_fd_thread, tmp); - break; - - case PTH_EVENT_TIME: - printf ("pth_wait: spawn event timer thread.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = pth_spawn (attr, wait_timer_thread, tmp); - break; - - case PTH_EVENT_MUTEX: - printf ("pth_wait: add mutex event.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = tmp->u.mx->mx; - /* XXX: Use SetEvent(hd->ev) */ - break; - } + printf ("pth_wait: cnt %d\n", pth_event_count (ev)); + for (tmp = ev; tmp; tmp = tmp->next) + { + if (pos+1 > MAXIMUM_WAIT_OBJECTS/2) + { + free_threads (waitbuf, hdidx, i); + pth_attr_destroy (attr); + return -1; + } + switch (tmp->u_type) + { + case 0: + waitbuf[pos++] = tmp->hd; + break; + + case PTH_EVENT_SIGS: + waitbuf[pos++] = pth_signo_ev; + printf ("pth_wait: add signal event.\n"); + break; + + case PTH_EVENT_FD: + printf ("pth_wait: spawn event wait thread.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = pth_spawn (attr, wait_fd_thread, tmp); + break; + + case PTH_EVENT_TIME: + printf ("pth_wait: spawn event timer thread.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = pth_spawn (attr, wait_timer_thread, tmp); + break; + + case PTH_EVENT_MUTEX: + printf ("pth_wait: add mutex event.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = tmp->u.mx->mx; + /* XXX: Use SetEvent(hd->ev) */ + break; + } } - printf ("pth_wait: set %d\n", pos); - n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); - free_threads (waitbuf, hdidx, i); - pth_attr_destroy (attr); - printf ("pth_wait: n %ld\n", n); - if (n != WAIT_TIMEOUT) - return 1; + printf ("pth_wait: set %d\n", pos); + n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); + free_threads (waitbuf, hdidx, i); + pth_attr_destroy (attr); + printf ("pth_wait: n %ld\n", n); + if (n != WAIT_TIMEOUT) + return 1; - /* - switch (ev->u_type) { - case 0: - n = WaitForSingleObject (ev->hd, INFINITE); - if (n != WAIT_OBJECT_0) - return 1; - break; - - case PTH_EVENT_SIGS: - n = WaitForSingleObject (pth_signo_ev, INFINITE); - if (n != WAIT_OBJECT_0) - return 1; - break; - - case PTH_EVENT_FD: - if (wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE)) { - SetEvent (ev->hd); - return 1; - } - break; - - default: - return -1; - } - */ - return 0; + return 0; } int pth_sleep (int sec) { - static pth_key_t ev_key = PTH_KEY_INIT; - pth_event_t ev; + static pth_key_t ev_key = PTH_KEY_INIT; + pth_event_t ev; - implicit_init (); - if (sec == 0) - return 0; - - ev = pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, pth_timeout (sec, 0)); - if (ev == NULL) - return -1; - pth_wait (ev); - pth_event_free (ev, PTH_FREE_ALL); + implicit_init (); + if (sec == 0) return 0; + + ev = pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, + pth_timeout (sec, 0)); + if (ev == NULL) + return -1; + pth_wait (ev); + pth_event_free (ev, PTH_FREE_ALL); + return 0; } @@ -971,111 +1043,112 @@ pth_sleep (int sec) void * thread (void * c) { - Sleep (2000); - SetEvent (((pth_event_t)c)->hd); - printf ("\n\nhallo!.\n"); - pth_exit (NULL); - return NULL; + Sleep (2000); + SetEvent (((pth_event_t)c)->hd); + printf ("\n\nhallo!.\n"); + pth_exit (NULL); + return NULL; } int main_1 (int argc, char ** argv) { - pth_attr_t t; - pth_t hd; - pth_event_t ev; - - pth_init (); - ev = pth_event (0, NULL); - t = pth_attr_new (); - pth_attr_set (t, PTH_ATTR_JOINABLE, 1); - pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096); - pth_attr_set (t, PTH_ATTR_NAME, "hello"); - hd = pth_spawn (t, thread, ev); - - pth_wait (ev); - pth_attr_destroy (t); - pth_event_free (ev, 0); - pth_kill (); - - return 0; + pth_attr_t t; + pth_t hd; + pth_event_t ev; + + pth_init (); + ev = pth_event (0, NULL); + t = pth_attr_new (); + pth_attr_set (t, PTH_ATTR_JOINABLE, 1); + pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096); + pth_attr_set (t, PTH_ATTR_NAME, "hello"); + hd = pth_spawn (t, thread, ev); + + pth_wait (ev); + pth_attr_destroy (t); + pth_event_free (ev, 0); + pth_kill (); + + return 0; } static pth_event_t setup_signals (struct sigset_s *sigs, int *signo) { - pth_event_t ev; + pth_event_t ev; - sigemptyset (sigs); - sigaddset (sigs, SIGINT); - sigaddset (sigs, SIGTERM); + sigemptyset (sigs); + sigaddset (sigs, SIGINT); + sigaddset (sigs, SIGTERM); - ev = pth_event (PTH_EVENT_SIGS, sigs, signo); - return ev; + ev = pth_event (PTH_EVENT_SIGS, sigs, signo); + return ev; } int main_2 (int argc, char ** argv) { - pth_event_t ev; - struct sigset_s sigs; - int signo = 0; - - pth_init (); - ev = setup_signals (&sigs, &signo); - pth_wait (ev); - if (pth_event_occured (ev) && signo) - printf ("signal caught! signo %d\n", signo); - - pth_event_free (ev, PTH_FREE_ALL); - pth_kill (); - return 0; + pth_event_t ev; + struct sigset_s sigs; + int signo = 0; + + pth_init (); + ev = setup_signals (&sigs, &signo); + pth_wait (ev); + if (pth_event_occured (ev) && signo) + printf ("signal caught! signo %d\n", signo); + + pth_event_free (ev, PTH_FREE_ALL); + pth_kill (); + return 0; } int main_3 (int argc, char ** argv) { - struct sockaddr_in addr, rem; - int fd, n = 0, infd; - int signo = 0; - struct sigset_s sigs; - pth_event_t ev; - - pth_init (); - fd = socket (AF_INET, SOCK_STREAM, 0); - - memset (&addr, 0, sizeof addr); - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons (5050); - addr.sin_family = AF_INET; - bind (fd, (struct sockaddr*)&addr, sizeof addr); - listen (fd, 5); - - ev = setup_signals (&sigs, &signo); - n = sizeof addr; - infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev); - printf ("infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), htons (rem.sin_port)); - - closesocket (infd); - pth_event_free (ev, PTH_FREE_ALL); - pth_kill (); - return 0; + struct sockaddr_in addr, rem; + int fd, n = 0, infd; + int signo = 0; + struct sigset_s sigs; + pth_event_t ev; + + pth_init (); + fd = socket (AF_INET, SOCK_STREAM, 0); + + memset (&addr, 0, sizeof addr); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons (5050); + addr.sin_family = AF_INET; + bind (fd, (struct sockaddr*)&addr, sizeof addr); + listen (fd, 5); + + ev = setup_signals (&sigs, &signo); + n = sizeof addr; + infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev); + printf ("infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), + htons (rem.sin_port)); + + closesocket (infd); + pth_event_free (ev, PTH_FREE_ALL); + pth_kill (); + return 0; } int main (int argc, char ** argv) { - pth_event_t ev; - pth_key_t ev_key; + pth_event_t ev; + pth_key_t ev_key; - pth_init (); - /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0)); + pth_init (); + /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0)); pth_wait (ev); pth_event_free (ev, PTH_FREE_ALL);*/ - pth_sleep (5); - pth_kill (); - return 0; + pth_sleep (5); + pth_kill (); + return 0; } #endif -- cgit v1.2.3 From 837ce29cbc563f6b7631ca37572e43c6aff18c59 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 14 Dec 2004 11:25:04 +0000 Subject: * w32-pth.h (pth_event_occured): Removed macro. * w32-pth.c: Fixed license statement; its under the LGPL. (enter_pth, leave_pth): Use them to bracket almost all public functions. --- jnlib/ChangeLog | 7 + jnlib/w32-pth.c | 392 +++++++++++++++++++++++++++++++++++++++++--------------- jnlib/w32-pth.h | 8 +- 3 files changed, 296 insertions(+), 111 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index de73ef40e..4605c0db6 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,10 @@ +2004-12-14 Werner Koch <wk@g10code.com> + + * w32-pth.h (pth_event_occured): Removed macro. + * w32-pth.c: Fixed license statement; its under the LGPL. + (enter_pth, leave_pth): Use them to bracket almost all public + functions. + 2004-12-13 Timo Schulz <twoaday@g10code.com> * w32-pth.c (enter_pth, leave_pth): New. diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index ed0eb93ad..329233b35 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -4,19 +4,19 @@ * * 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 free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 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. + * 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 + * Lesser 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 + * You should have received a copy of the GNU Lesser 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 code is based on Ralf Engelschall's GNU Pth, a non-preemptive @@ -51,7 +51,6 @@ static CRITICAL_SECTION pth_shd; #define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) -static void * helper_thread (void * ctx); struct pth_event_s @@ -87,14 +86,23 @@ struct _pth_priv_hd_s }; +/* Prototypes. */ +static pth_event_t do_pth_event (unsigned long spec, ...); +static unsigned int do_pth_waitpid (unsigned pid, int * status, int options); +static int do_pth_wait (pth_event_t ev); +static int do_pth_event_status (pth_event_t ev); +static void * helper_thread (void * ctx); + + + int pth_init (void) { SECURITY_ATTRIBUTES sa; WSADATA wsadat; - - printf ("pth_init: called.\n"); + + fprintf (stderr, "pth_init: called.\n"); pth_initialized = 1; if (WSAStartup (0x202, &wsadat)) abort (); @@ -128,18 +136,20 @@ pth_kill (void) static void -enter_pth (void) +enter_pth (const char *function) { - EnterCriticalSection (&pth_shd); - /*LeaveCriticalSection (&pth_shd);*/ + /* Fixme: I am not sure whether the same thread my enter a critical + section twice. */ + fprintf (stderr, "enter_pth (%s)\n", function? function:""); + LeaveCriticalSection (&pth_shd); } static void -leave_pth (void) +leave_pth (const char *function) { - LeaveCriticalSection (&pth_shd); - /*EnterCriticalSection (&pth_shd);*/ + EnterCriticalSection (&pth_shd); + fprintf (stderr, "leave_pth (%s)\n", function? function:""); } @@ -193,15 +203,19 @@ pth_read (int fd, void * buffer, size_t size) int n; implicit_init (); + enter_pth (__FUNCTION__); + n = recv (fd, buffer, size, 0); if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { DWORD nread = 0; n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); if (!n) - return -1; - return (int)nread; + n = -1; + else + n = (int)nread; } + leave_pth (__FUNCTION__); return n; } @@ -220,15 +234,32 @@ pth_write (int fd, const void * buffer, size_t size) int n; implicit_init (); + enter_pth (__FUNCTION__); n = send (fd, buffer, size, 0); if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { + char strerr[256]; + + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, sizeof (strerr)-1, NULL); + fprintf (stderr, "pth_write(%d) failed in send: %s\n", fd, strerr); + + DWORD nwrite; n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); if (!n) - return -1; - return (int)nwrite; + { + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,(int)GetLastError (), + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, sizeof (strerr)-1, NULL); + fprintf (stderr, "pth_write(%d) failed in write: %s\n", fd, strerr); + n = -1; + } + else + n = (int)nwrite; } + leave_pth (__FUNCTION__); return n; } @@ -237,8 +268,13 @@ int pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds, const struct timeval * timeout) { + int n; + implicit_init (); - return select (nfds, rfds, wfds, efds, timeout); + enter_pth (__FUNCTION__); + n = select (nfds, rfds, wfds, efds, timeout); + leave_pth (__FUNCTION__); + return n; } @@ -246,32 +282,41 @@ int pth_fdmode (int fd, int mode) { unsigned long val; + int ret = PTH_FDMODE_BLOCK; implicit_init (); + /* Note: we don't do the eter/leave pth here because this is for one + a fast fucntion and secondly already called from inside such a + block. */ /* XXX: figure out original fd mode */ switch (mode) { case PTH_FDMODE_NONBLOCK: val = 1; if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - return PTH_FDMODE_ERROR; + ret = PTH_FDMODE_ERROR; break; case PTH_FDMODE_BLOCK: val = 0; if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - return PTH_FDMODE_ERROR; + ret = PTH_FDMODE_ERROR; break; } - return PTH_FDMODE_BLOCK; + return ret; } int pth_accept (int fd, struct sockaddr *addr, int *addrlen) { + int rc; + implicit_init (); - return accept (fd, addr, addrlen); + enter_pth (__FUNCTION__); + rc = accept (fd, addr, addrlen); + leave_pth (__FUNCTION__); + return rc; } @@ -285,10 +330,14 @@ pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, int fdmode; implicit_init (); + enter_pth (__FUNCTION__); fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK); if (fdmode == PTH_FDMODE_ERROR) - return -1; + { + leave_pth (__FUNCTION__); + return -1; + } ev = NULL; while ((rv = accept (fd, addr, addrlen)) == -1 && @@ -296,27 +345,32 @@ pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, WSAGetLastError () == WSAEWOULDBLOCK)) { if (ev == NULL) { - ev = pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_MODE_STATIC, - &ev_key, fd); + ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_MODE_STATIC, + &ev_key, fd); if (ev == NULL) - return -1; + { + leave_pth (__FUNCTION__); + return -1; + } if (ev_extra != NULL) pth_event_concat (ev, ev_extra, NULL); } - /* wait until accept has a chance */ - pth_wait (ev); + /* Wait until accept has a chance. */ + do_pth_wait (ev); if (ev_extra != NULL) { pth_event_isolate (ev); - if (pth_event_status (ev) != PTH_STATUS_OCCURRED) + if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED) { pth_fdmode (fd, fdmode); + leave_pth (__FUNCTION__); return -1; } } } pth_fdmode (fd, fdmode); + leave_pth (__FUNCTION__); return rv; } @@ -324,8 +378,13 @@ pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, int pth_connect (int fd, struct sockaddr *name, int namelen) { + int rc; + implicit_init (); - return connect (fd, name, namelen); + enter_pth (__FUNCTION__); + rc = connect (fd, name, namelen); + leave_pth (__FUNCTION__); + return rc; } @@ -335,12 +394,14 @@ pth_mutex_release (pth_mutex_t *hd) if (!hd) return -1; implicit_init (); + enter_pth (__FUNCTION__); if (hd->mx) { CloseHandle (hd->mx); hd->mx = NULL; } free (hd); + leave_pth (__FUNCTION__); return 0; } @@ -349,11 +410,13 @@ int pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) { implicit_init (); + enter_pth (__FUNCTION__); - if (!hd) - return -1; - if (!hd->mx) - return -1; + if (!hd || !hd->mx) + { + leave_pth (__FUNCTION__); + return -1; + } #if 0 /* still not locked, so simply acquire mutex? */ @@ -376,7 +439,10 @@ pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) } if (tryonly) - return return -1; + { + leave_pth (__FUNCTION__); + return -1; + } for (;;) { @@ -386,8 +452,11 @@ pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) pth_wait (ev); if (ev_extra != NULL) { pth_event_isolate (ev); - if (pth_event_status(ev) == PTH_STATUS_PENDING) - return return -1; + if (do_pth_event_status(ev) == PTH_STATUS_PENDING) + { + leave_pth (__FUNCTION__); + return -1; + } } if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) break; @@ -395,6 +464,7 @@ pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) #endif hd->mx_state |= PTH_MUTEX_LOCKED; + leave_pth (__FUNCTION__); return 0; } @@ -405,6 +475,8 @@ pth_mutex_init (pth_mutex_t *hd) SECURITY_ATTRIBUTES sa; implicit_init (); + enter_pth (__FUNCTION__); + if (hd->mx) { ReleaseMutex (hd->mx); @@ -416,6 +488,8 @@ pth_mutex_init (pth_mutex_t *hd) sa.nLength = sizeof sa; hd->mx = CreateMutex (&sa, FALSE, NULL); hd->mx_state = PTH_MUTEX_INITIALIZED; + + leave_pth (__FUNCTION__); return 0; } @@ -427,8 +501,6 @@ pth_attr_new (void) implicit_init (); hd = calloc (1, sizeof *hd); - if (!hd) - return NULL; return hd; } @@ -455,6 +527,7 @@ pth_attr_set (pth_attr_t hd, int field, ...) int rc = 0; implicit_init (); + va_start (args, field); switch (field) { @@ -463,7 +536,7 @@ pth_attr_set (pth_attr_t hd, int field, ...) if (val) { hd->flags |= PTH_ATTR_JOINABLE; - printf ("pth_attr_set: PTH_ATTR_JOINABLE\n"); + fprintf (stderr, "pth_attr_set: PTH_ATTR_JOINABLE\n"); } break; @@ -473,7 +546,7 @@ pth_attr_set (pth_attr_t hd, int field, ...) { hd->flags |= PTH_ATTR_STACK_SIZE; hd->stack_size = val; - printf ("pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", val); + fprintf (stderr, "pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", val); } break; @@ -487,7 +560,7 @@ pth_attr_set (pth_attr_t hd, int field, ...) if (!hd->name) return -1; hd->flags |= PTH_ATTR_NAME; - printf ("pth_attr_set: PTH_ATTR_NAME %s\n", hd->name); + fprintf (stderr, "pth_attr_set: PTH_ATTR_NAME %s\n", hd->name); } break; @@ -512,6 +585,7 @@ pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) return NULL; implicit_init (); + enter_pth (__FUNCTION__); memset (&sa, 0, sizeof sa); sa.bInheritHandle = TRUE; @@ -519,16 +593,23 @@ pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) sa.nLength = sizeof sa; ctx = calloc (1, sizeof * ctx); + if (!ctx) + { + leave_pth (__FUNCTION__); + return NULL; + } ctx->thread = func; ctx->arg = arg; /* XXX: we don't use all thread attributes. */ - enter_pth (); + + fprintf (stderr, "pth_spawn creating thread ...\n"); th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)helper_thread, ctx, 0, &tid); - leave_pth (); - + fprintf (stderr, "pth_spawn created thread %p\n", th); + + leave_pth (__FUNCTION__); return th; } @@ -547,8 +628,10 @@ pth_cancel (pth_t hd) if (!hd) return -1; implicit_init (); + enter_pth (__FUNCTION__); WaitForSingleObject (hd, 1000); TerminateThread (hd, 0); + leave_pth (__FUNCTION__); return 0; } @@ -560,7 +643,9 @@ pth_abort (pth_t hd) if (!hd) return -1; implicit_init (); + enter_pth (__FUNCTION__); TerminateThread (hd, 0); + leave_pth (__FUNCTION__); return 0; } @@ -569,15 +654,16 @@ void pth_exit (void *value) { implicit_init (); + enter_pth (__FUNCTION__); pth_kill (); + leave_pth (__FUNCTION__); exit ((int)(long)value); } -unsigned -pth_waitpid (unsigned pid, int * status, int options) +static unsigned int +do_pth_waitpid (unsigned pid, int * status, int options) { - implicit_init (); #if 0 pth_event_t ev; static pth_key_t ev_key = PTH_KEY_INIT; @@ -608,6 +694,19 @@ pth_waitpid (unsigned pid, int * status, int options) } +unsigned int +pth_waitpid (unsigned pid, int * status, int options) +{ + unsigned int n; + + implicit_init (); + enter_pth (__FUNCTION__); + n = do_pth_waitpid (pid, status, options); + leave_pth (__FUNCTION__); + return n; +} + + static BOOL WINAPI sig_handler (DWORD signo) { @@ -617,22 +716,19 @@ sig_handler (DWORD signo) case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; } SetEvent (pth_signo_ev); - printf ("sig_handler=%d\n", pth_signo); + fprintf (stderr, "sig_handler=%d\n", pth_signo); return TRUE; } -pth_event_t -pth_event (unsigned long spec, ...) +static pth_event_t +do_pth_event_body (unsigned long spec, va_list arg) { - va_list arg; SECURITY_ATTRIBUTES sa; pth_event_t ev; int rc; - implicit_init (); - printf ("pth_event spec=%lu\n", spec); - va_start (arg, spec); + fprintf (stderr, "pth_event spec=%lu\n", spec); ev = calloc (1, sizeof *ev); if (!ev) return NULL; @@ -644,7 +740,7 @@ pth_event (unsigned long spec, ...) ev->u_type = PTH_EVENT_SIGS; ev->val = va_arg (arg, int *); rc = SetConsoleCtrlHandler (sig_handler, TRUE); - printf ("pth_event: sigs rc=%d\n", rc); + fprintf (stderr, "pth_event: sigs rc=%d\n", rc); } else if (spec & PTH_EVENT_FD) { @@ -655,7 +751,7 @@ pth_event (unsigned long spec, ...) ev->u_type = PTH_EVENT_FD; va_arg (arg, pth_key_t); ev->u.fd = va_arg (arg, int); - printf ("pth_event: fd=%d\n", ev->u.fd); + fprintf (stderr, "pth_event: fd=%d\n", ev->u.fd); } else if (spec & PTH_EVENT_TIME) { @@ -674,7 +770,6 @@ pth_event (unsigned long spec, ...) ev->u_type = PTH_EVENT_MUTEX; ev->u.mx = va_arg (arg, pth_mutex_t*); } - va_end (arg); memset (&sa, 0, sizeof sa); sa.bInheritHandle = TRUE; @@ -690,6 +785,36 @@ pth_event (unsigned long spec, ...) return ev; } +static pth_event_t +do_pth_event (unsigned long spec, ...) +{ + va_list arg; + pth_event_t ev; + + va_start (arg, spec); + ev = do_pth_event_body (spec, arg); + va_end (arg); + + return ev; +} + +pth_event_t +pth_event (unsigned long spec, ...) +{ + va_list arg; + pth_event_t ev; + + implicit_init (); + enter_pth (__FUNCTION__); + + va_start (arg, spec); + ev = do_pth_event_body (spec, arg); + va_end (arg); + + leave_pth (__FUNCTION__); + return ev; +} + static void pth_event_add (pth_event_t root, pth_event_t node) @@ -712,6 +837,7 @@ pth_event_concat (pth_event_t evf, ...) return NULL; implicit_init (); + va_start (ap, evf); while ((evn = va_arg(ap, pth_event_t)) != NULL) pth_event_add (evf, evn); @@ -739,7 +865,7 @@ wait_for_fd (int fd, int is_read, int nwait) while (1) { n = select (fd+1, &r, &w, NULL, &tv); - printf ("wait_for_fd=%d fd %d (ec=%d)\n", n, fd,(int)WSAGetLastError ()); + fprintf (stderr, "wait_for_fd=%d fd %d (ec=%d)\n", n, fd,(int)WSAGetLastError ()); if (n == -1) break; if (!n) @@ -761,9 +887,9 @@ helper_thread (void * ctx) { struct _pth_priv_hd_s * c = ctx; - leave_pth (); + leave_pth (__FUNCTION__); c->thread (c->arg); - enter_pth (); + enter_pth (__FUNCTION__); free (c); ExitThread (0); return NULL; @@ -776,7 +902,7 @@ wait_fd_thread (void * ctx) pth_event_t ev = ctx; wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - printf ("wait_fd_thread: exit.\n"); + fprintf (stderr, "wait_fd_thread: exit.\n"); SetEvent (ev->hd); ExitThread (0); return NULL; @@ -790,7 +916,7 @@ wait_timer_thread (void * ctx) int n = ev->u.tv.tv_sec*1000; Sleep (n); SetEvent (ev->hd); - printf ("wait_timer_thread: exit.\n"); + fprintf (stderr, "wait_timer_thread: exit.\n"); ExitThread (0); return NULL; } @@ -832,57 +958,81 @@ sigpresent (struct sigset_s * ss, int signo) } -int -pth_event_occured (pth_event_t ev) +static int +do_pth_event_occurred (pth_event_t ev) { + int ret; + if (!ev) return 0; - implicit_init (); + + ret = 0; switch (ev->u_type) { case 0: if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) - return 1; + ret = 1; break; case PTH_EVENT_SIGS: if (sigpresent (ev->u.sig, pth_signo) && WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) { - printf ("pth_event_occured: sig signaled.\n"); + fprintf (stderr, "pth_event_occurred: sig signaled.\n"); (*ev->val) = pth_signo; - return 1; + ret = 1; } break; case PTH_EVENT_FD: if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0) - return 1; + ret = 1; break; } - return 0; + return ret; } +int +pth_event_occurred (pth_event_t ev) +{ + int ret; + + implicit_init (); + enter_pth (__FUNCTION__); + ret = do_pth_event_occurred (ev); + leave_pth (__FUNCTION__); + return ret; +} + + +static int +do_pth_event_status (pth_event_t ev) +{ + if (!ev) + return 0; + if (do_pth_event_occurred (ev)) + return PTH_STATUS_OCCURRED; + return 0; +} + int pth_event_status (pth_event_t ev) { if (!ev) return 0; - implicit_init (); - if (pth_event_occured (ev)) + if (pth_event_occurred (ev)) return PTH_STATUS_OCCURRED; return 0; } -int -pth_event_free (pth_event_t ev, int mode) +static int +do_pth_event_free (pth_event_t ev, int mode) { pth_event_t n; - implicit_init (); if (mode == PTH_FREE_ALL) { while (ev) @@ -901,9 +1051,22 @@ pth_event_free (pth_event_t ev, int mode) free (ev); } + return 0; } +int +pth_event_free (pth_event_t ev, int mode) +{ + int rc; + + implicit_init (); + enter_pth (__FUNCTION__); + rc = do_pth_event_free (ev, mode); + leave_pth (__FUNCTION__); + return rc; +} + pth_event_t pth_event_isolate (pth_event_t ev) @@ -912,7 +1075,6 @@ pth_event_isolate (pth_event_t ev) if (!ev) return NULL; - implicit_init (); return ring; } @@ -941,8 +1103,8 @@ pth_event_count (pth_event_t ev) } -int -pth_wait (pth_event_t ev) +static int +do_pth_wait (pth_event_t ev) { HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; int hdidx[MAXIMUM_WAIT_OBJECTS/2]; @@ -954,12 +1116,11 @@ pth_wait (pth_event_t ev) if (!ev) return 0; - implicit_init (); attr = pth_attr_new (); pth_attr_set (attr, PTH_ATTR_JOINABLE, 1); pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 4096); - printf ("pth_wait: cnt %d\n", pth_event_count (ev)); + fprintf (stderr, "pth_wait: cnt %d\n", pth_event_count (ev)); for (tmp = ev; tmp; tmp = tmp->next) { if (pos+1 > MAXIMUM_WAIT_OBJECTS/2) @@ -976,40 +1137,53 @@ pth_wait (pth_event_t ev) case PTH_EVENT_SIGS: waitbuf[pos++] = pth_signo_ev; - printf ("pth_wait: add signal event.\n"); + fprintf (stderr, "pth_wait: add signal event.\n"); break; case PTH_EVENT_FD: - printf ("pth_wait: spawn event wait thread.\n"); + fprintf (stderr, "pth_wait: spawn event wait thread.\n"); hdidx[i++] = pos; waitbuf[pos++] = pth_spawn (attr, wait_fd_thread, tmp); break; case PTH_EVENT_TIME: - printf ("pth_wait: spawn event timer thread.\n"); + fprintf (stderr, "pth_wait: spawn event timer thread.\n"); hdidx[i++] = pos; waitbuf[pos++] = pth_spawn (attr, wait_timer_thread, tmp); break; case PTH_EVENT_MUTEX: - printf ("pth_wait: add mutex event.\n"); + fprintf (stderr, "pth_wait: add mutex event.\n"); hdidx[i++] = pos; waitbuf[pos++] = tmp->u.mx->mx; /* XXX: Use SetEvent(hd->ev) */ break; } } - printf ("pth_wait: set %d\n", pos); + fprintf (stderr, "pth_wait: set %d\n", pos); n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); free_threads (waitbuf, hdidx, i); pth_attr_destroy (attr); - printf ("pth_wait: n %ld\n", n); + fprintf (stderr, "pth_wait: n %ld\n", n); + if (n != WAIT_TIMEOUT) return 1; return 0; } +int +pth_wait (pth_event_t ev) +{ + int rc; + + implicit_init (); + enter_pth (__FUNCTION__); + rc = do_pth_wait (ev); + leave_pth (__FUNCTION__); + return rc; +} + int pth_sleep (int sec) @@ -1018,15 +1192,25 @@ pth_sleep (int sec) pth_event_t ev; implicit_init (); + enter_pth (__FUNCTION__); + if (sec == 0) - return 0; - - ev = pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, - pth_timeout (sec, 0)); + { + leave_pth (__FUNCTION__); + return 0; + } + + ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, + pth_timeout (sec, 0)); if (ev == NULL) - return -1; - pth_wait (ev); - pth_event_free (ev, PTH_FREE_ALL); + { + leave_pth (__FUNCTION__); + return -1; + } + do_pth_wait (ev); + do_pth_event_free (ev, PTH_FREE_ALL); + + leave_pth (__FUNCTION__); return 0; } @@ -1045,7 +1229,7 @@ void * thread (void * c) Sleep (2000); SetEvent (((pth_event_t)c)->hd); - printf ("\n\nhallo!.\n"); + fprintf (stderr, "\n\nhallo!.\n"); pth_exit (NULL); return NULL; } @@ -1098,7 +1282,7 @@ main_2 (int argc, char ** argv) ev = setup_signals (&sigs, &signo); pth_wait (ev); if (pth_event_occured (ev) && signo) - printf ("signal caught! signo %d\n", signo); + fprintf (stderr, "signal caught! signo %d\n", signo); pth_event_free (ev, PTH_FREE_ALL); pth_kill (); @@ -1127,7 +1311,7 @@ main_3 (int argc, char ** argv) ev = setup_signals (&sigs, &signo); n = sizeof addr; infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev); - printf ("infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), + fprintf (stderr, "infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), htons (rem.sin_port)); closesocket (infd); diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h index bb010ae99..bcd82659c 100644 --- a/jnlib/w32-pth.h +++ b/jnlib/w32-pth.h @@ -229,18 +229,12 @@ pth_time_t pth_timeout (long sec, long usec); pth_event_t pth_event_isolate (pth_event_t hd); int pth_event_free (pth_event_t hd, int mode); int pth_event_status (pth_event_t hd); -int pth_event_occured (pth_event_t hd); +int pth_event_occurred (pth_event_t hd); pth_event_t pth_event_concat (pth_event_t ev, ...); pth_event_t pth_event (unsigned long spec, ...); -/* Backward compatibility (Pth < 1.5.0). */ -#define pth_event_occurred(ev) \ - ( pth_event_status(ev) == PTH_STATUS_OCCURRED \ - || pth_event_status(ev) == PTH_STATUS_FAILED ) - - /*-- pth_util.c --*/ /* void sigemptyset (struct sigset_s * ss); */ -- cgit v1.2.3 From 2946819dfc8961d8939a6da9ecee01c11164acc4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 14 Dec 2004 14:49:21 +0000 Subject: More fixes. First successful use; leaks threads, though. --- agent/gpg-agent.c | 27 +++++++++-- jnlib/w32-pth.c | 134 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 57 deletions(-) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 6801839aa..5ac02645e 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -446,6 +446,9 @@ main (int argc, char **argv ) gpg_strerror (err)); } #endif /*USE_GNU_PTH && !HAVE_W32_SYSTEM*/ +#ifdef HAVE_W32_SYSTEM + pth_init (); +#endif /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library. */ @@ -728,7 +731,6 @@ main (int argc, char **argv ) ; /* NOTREACHED */ else { /* Regular server mode */ -#ifndef HAVE_W32_SYSTEM int fd; pid_t pid; int len; @@ -739,8 +741,10 @@ main (int argc, char **argv ) default to a specific display. There is still a default display when gpg-agent weas started using --display or a client requested this using an OPTION command. */ +#ifndef HAVE_W32_SYSTEM if (!opt.keep_display) unsetenv ("DISPLAY"); +#endif *socket_name = 0; snprintf (socket_name, DIM(socket_name)-1, @@ -750,12 +754,15 @@ main (int argc, char **argv ) if (!p) BUG (); *p = 0;; + +#ifndef HAVE_W32_SYSTEM if (!mkdtemp(socket_name)) { log_error ("can't create directory `%s': %s\n", socket_name, strerror(errno) ); exit (1); } +#endif *p = '/'; if (strchr (socket_name, ':') ) @@ -769,8 +776,11 @@ main (int argc, char **argv ) exit (1); } - +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif if (fd == -1) { log_error ("can't create socket: %s\n", strerror(errno) ); @@ -783,7 +793,13 @@ main (int argc, char **argv ) len = (offsetof (struct sockaddr_un, sun_path) + strlen(serv_addr.sun_path) + 1); - if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1) + if ( +#ifdef HAVE_W32_SYSTEM + _w32_sock_bind +#else + bind +#endif + (fd, (struct sockaddr*)&serv_addr, len) == -1) { log_error ("error binding socket to `%s': %s\n", serv_addr.sun_path, strerror (errno) ); @@ -803,6 +819,7 @@ main (int argc, char **argv ) fflush (NULL); +#ifndef HAVE_W32_SYSTEM pid = fork (); if (pid == (pid_t)-1) { @@ -857,7 +874,6 @@ main (int argc, char **argv ) } /*NEVER REACHED*/ } /* end parent */ - /* This is the child @@ -893,6 +909,8 @@ main (int argc, char **argv ) exit (1); } +#endif /*!HAVE_W32_SYSTEM*/ + #ifdef USE_GNU_PTH if (!disable_pth) @@ -931,7 +949,6 @@ main (int argc, char **argv ) start_command_handler (fd, -1); } close (fd); -#endif } return 0; diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 329233b35..ed3fe9b61 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -573,8 +573,8 @@ pth_attr_set (pth_attr_t hd, int field, ...) } -pth_t -pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) +static pth_t +do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) { SECURITY_ATTRIBUTES sa; DWORD tid; @@ -584,9 +584,6 @@ pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) if (!hd) return NULL; - implicit_init (); - enter_pth (__FUNCTION__); - memset (&sa, 0, sizeof sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; @@ -594,21 +591,32 @@ pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) ctx = calloc (1, sizeof * ctx); if (!ctx) - { - leave_pth (__FUNCTION__); - return NULL; - } + return NULL; ctx->thread = func; ctx->arg = arg; /* XXX: we don't use all thread attributes. */ - fprintf (stderr, "pth_spawn creating thread ...\n"); + fprintf (stderr, "do_pth_spawn creating thread ...\n"); th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)helper_thread, ctx, 0, &tid); - fprintf (stderr, "pth_spawn created thread %p\n", th); + fprintf (stderr, "do_pth_spawn created thread %p\n", th); + + return th; +} + +pth_t +pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) +{ + HANDLE th; + + if (!hd) + return NULL; + implicit_init (); + enter_pth (__FUNCTION__); + th = do_pth_spawn (hd, func, arg); leave_pth (__FUNCTION__); return th; } @@ -895,33 +903,6 @@ helper_thread (void * ctx) return NULL; } - -static void * -wait_fd_thread (void * ctx) -{ - pth_event_t ev = ctx; - - wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - fprintf (stderr, "wait_fd_thread: exit.\n"); - SetEvent (ev->hd); - ExitThread (0); - return NULL; -} - - -static void * -wait_timer_thread (void * ctx) -{ - pth_event_t ev = ctx; - int n = ev->u.tv.tv_sec*1000; - Sleep (n); - SetEvent (ev->hd); - fprintf (stderr, "wait_timer_thread: exit.\n"); - ExitThread (0); - return NULL; -} - - /* void */ /* sigemptyset (struct sigset_s * ss) */ /* { */ @@ -1079,16 +1060,6 @@ pth_event_isolate (pth_event_t ev) } -static void -free_threads (HANDLE *waitbuf, int *hdidx, int n) -{ - int i; - - for (i=0; i < n; i++) - CloseHandle (waitbuf[hdidx[i]]); -} - - static int pth_event_count (pth_event_t ev) { @@ -1103,6 +1074,65 @@ pth_event_count (pth_event_t ev) } + +static pth_t +spawn_helper_thread (pth_attr_t hd, void *(*func)(void *), void *arg) +{ + SECURITY_ATTRIBUTES sa; + DWORD tid; + HANDLE th; + + memset (&sa, 0, sizeof sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + sa.nLength = sizeof sa; + + fprintf (stderr, "spawn_helper_thread creating thread ...\n"); + th = CreateThread (&sa, hd->stack_size, + (LPTHREAD_START_ROUTINE)func, + arg, 0, &tid); + fprintf (stderr, "spawn_helper_thread created thread %p\n", th); + + return th; +} + + +static void +free_helper_threads (HANDLE *waitbuf, int *hdidx, int n) +{ + int i; + + for (i=0; i < n; i++) + CloseHandle (waitbuf[hdidx[i]]); +} + + +static void * +wait_fd_thread (void * ctx) +{ + pth_event_t ev = ctx; + + wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); + fprintf (stderr, "wait_fd_thread: exit.\n"); + SetEvent (ev->hd); + ExitThread (0); + return NULL; +} + + +static void * +wait_timer_thread (void * ctx) +{ + pth_event_t ev = ctx; + int n = ev->u.tv.tv_sec*1000; + Sleep (n); + SetEvent (ev->hd); + fprintf (stderr, "wait_timer_thread: exit.\n"); + ExitThread (0); + return NULL; +} + + static int do_pth_wait (pth_event_t ev) { @@ -1125,7 +1155,7 @@ do_pth_wait (pth_event_t ev) { if (pos+1 > MAXIMUM_WAIT_OBJECTS/2) { - free_threads (waitbuf, hdidx, i); + free_helper_threads (waitbuf, hdidx, i); pth_attr_destroy (attr); return -1; } @@ -1143,13 +1173,13 @@ do_pth_wait (pth_event_t ev) case PTH_EVENT_FD: fprintf (stderr, "pth_wait: spawn event wait thread.\n"); hdidx[i++] = pos; - waitbuf[pos++] = pth_spawn (attr, wait_fd_thread, tmp); + waitbuf[pos++] = spawn_helper_thread (attr, wait_fd_thread, tmp); break; case PTH_EVENT_TIME: fprintf (stderr, "pth_wait: spawn event timer thread.\n"); hdidx[i++] = pos; - waitbuf[pos++] = pth_spawn (attr, wait_timer_thread, tmp); + waitbuf[pos++] = spawn_helper_thread (attr, wait_timer_thread, tmp); break; case PTH_EVENT_MUTEX: @@ -1162,7 +1192,7 @@ do_pth_wait (pth_event_t ev) } fprintf (stderr, "pth_wait: set %d\n", pos); n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); - free_threads (waitbuf, hdidx, i); + free_helper_threads (waitbuf, hdidx, i); pth_attr_destroy (attr); fprintf (stderr, "pth_wait: n %ld\n", n); -- cgit v1.2.3 From 4becd8ddccdf0349ac5d7bc63c461f8273d17c2a Mon Sep 17 00:00:00 2001 From: Timo Schulz <twoaday@freakmail.de> Date: Tue, 14 Dec 2004 17:47:12 +0000 Subject: 2004-12-14 Timo Schulz <twoaday@g10code.com> * w32-pth.c (pth_kill): Just release the crit section if pth_init was really called. And set all handles to NULL. (_pth_strerror): New. (do_pth_wait): Before we enter the loop we check if there are too much events in the ring. --- jnlib/ChangeLog | 8 ++++ jnlib/w32-pth.c | 127 +++++++++++++++++++++++++++++++++----------------------- 2 files changed, 83 insertions(+), 52 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 4605c0db6..fa871caab 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,11 @@ +2004-12-14 Timo Schulz <twoaday@g10code.com> + + * w32-pth.c (pth_kill): Just release the crit section if + pth_init was really called. And set all handles to NULL. + (_pth_strerror): New. + (do_pth_wait): Before we enter the loop we check if there + are too much events in the ring. + 2004-12-14 Werner Koch <wk@g10code.com> * w32-pth.h (pth_event_occured): Removed macro. diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index ed3fe9b61..60c4a4e99 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -127,14 +127,30 @@ pth_kill (void) { pth_signo = 0; if (pth_signo_ev) - CloseHandle (pth_signo_ev); - DeleteCriticalSection (&pth_shd); + { + CloseHandle (pth_signo_ev); + pth_signo_ev = NULL; + } + if (pth_initialized) + DeleteCriticalSection (&pth_shd); WSACleanup (); pth_initialized = 0; return 0; } +static const char * +_pth_strerror (void) +{ + static char strerr[256]; + + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, sizeof (strerr)-1, NULL); + return strerr; +} + + static void enter_pth (const char *function) { @@ -211,7 +227,11 @@ pth_read (int fd, void * buffer, size_t size) DWORD nread = 0; n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); if (!n) - n = -1; + { + fprintf (stderr, "pth_read(%d) failed read from: %s.\n", fd, + _pth_strerror ()); + n = -1; + } else n = (int)nread; } @@ -238,22 +258,18 @@ pth_write (int fd, const void * buffer, size_t size) n = send (fd, buffer, size, 0); if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { - char strerr[256]; - - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - strerr, sizeof (strerr)-1, NULL); - fprintf (stderr, "pth_write(%d) failed in send: %s\n", fd, strerr); - - DWORD nwrite; + + /* this is no real error because we first need to figure out if + we have a handle or a socket. */ + /*fprintf (stderr, "pth_write(%d) failed in send: %s\n", fd, + _pth_strerror ());*/ + n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); if (!n) { - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,(int)GetLastError (), - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - strerr, sizeof (strerr)-1, NULL); - fprintf (stderr, "pth_write(%d) failed in write: %s\n", fd, strerr); + fprintf (stderr, "pth_write(%d) failed in write: %s\n", fd, + _pth_strerror ()); n = -1; } else @@ -344,17 +360,18 @@ pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, (WSAGetLastError () == WSAEINPROGRESS || WSAGetLastError () == WSAEWOULDBLOCK)) { - if (ev == NULL) { - ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_MODE_STATIC, - &ev_key, fd); - if (ev == NULL) - { - leave_pth (__FUNCTION__); - return -1; - } - if (ev_extra != NULL) - pth_event_concat (ev, ev_extra, NULL); - } + if (ev == NULL) + { + ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE| + PTH_MODE_STATIC, &ev_key, fd); + if (ev == NULL) + { + leave_pth (__FUNCTION__); + return -1; + } + if (ev_extra != NULL) + pth_event_concat (ev, ev_extra, NULL); + } /* Wait until accept has a chance. */ do_pth_wait (ev); if (ev_extra != NULL) @@ -450,14 +467,15 @@ pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) if (ev_extra != NULL) pth_event_concat (ev, ev_extra, NULL); pth_wait (ev); - if (ev_extra != NULL) { - pth_event_isolate (ev); - if (do_pth_event_status(ev) == PTH_STATUS_PENDING) - { - leave_pth (__FUNCTION__); - return -1; - } - } + if (ev_extra != NULL) + { + pth_event_isolate (ev); + if (do_pth_event_status(ev) == PTH_STATUS_PENDING) + { + leave_pth (__FUNCTION__); + return -1; + } + } if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) break; } @@ -894,11 +912,14 @@ static void * helper_thread (void * ctx) { struct _pth_priv_hd_s * c = ctx; - - leave_pth (__FUNCTION__); - c->thread (c->arg); - enter_pth (__FUNCTION__); - free (c); + + if (c) + { + leave_pth (__FUNCTION__); + c->thread (c->arg); + enter_pth (__FUNCTION__); + free (c); + } ExitThread (0); return NULL; } @@ -1019,7 +1040,8 @@ do_pth_event_free (pth_event_t ev, int mode) while (ev) { n = ev->next; - CloseHandle (ev->hd); ev->hd = NULL; + CloseHandle (ev->hd); + ev->hd = NULL; free (ev); ev = n; } @@ -1028,9 +1050,9 @@ do_pth_event_free (pth_event_t ev, int mode) { ev->prev->next = ev->next; ev->next->prev = ev->prev; - CloseHandle (ev->hd); ev->hd = NULL; + CloseHandle (ev->hd); + ev->hd = NULL; free (ev); - } return 0; @@ -1061,14 +1083,14 @@ pth_event_isolate (pth_event_t ev) static int -pth_event_count (pth_event_t ev) +_pth_event_count (pth_event_t ev) { pth_event_t p; int cnt=0; if (!ev) return 0; - for (p=ev; p; p = p->next) + for (p = ev; p; p = p->next) cnt++; return cnt; } @@ -1103,7 +1125,10 @@ free_helper_threads (HANDLE *waitbuf, int *hdidx, int n) int i; for (i=0; i < n; i++) - CloseHandle (waitbuf[hdidx[i]]); + { + CloseHandle (waitbuf[hdidx[i]]); + waitbuf[hdidx[i]] = NULL; + } } @@ -1146,19 +1171,17 @@ do_pth_wait (pth_event_t ev) if (!ev) return 0; + n =_pth_event_count (ev); + if (n > MAXIMUM_WAIT_OBJECTS/2) + return -1; + attr = pth_attr_new (); pth_attr_set (attr, PTH_ATTR_JOINABLE, 1); pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 4096); - fprintf (stderr, "pth_wait: cnt %d\n", pth_event_count (ev)); + fprintf (stderr, "pth_wait: cnt %lu\n", n); for (tmp = ev; tmp; tmp = tmp->next) { - if (pos+1 > MAXIMUM_WAIT_OBJECTS/2) - { - free_helper_threads (waitbuf, hdidx, i); - pth_attr_destroy (attr); - return -1; - } switch (tmp->u_type) { case 0: -- cgit v1.2.3 From 53ae21e7450c3d8e1aa8589d4c66d2dda1c50d53 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 14 Dec 2004 19:20:36 +0000 Subject: Yep. No lost threads anymore. (_pth_strerror): Renamed to ... (w32_strerror): .. this. And let callers provide a buffer. (spawn_helper_thread): Removed HD arg and hardwire the stack size to 32k. (do_pth_wait): Removed use of ATTR; not needed for the helper threads. (helper_thread): Renamed to .. (launch_thread): .. this. Release handle if not joinable. (struct pth_priv_hd_s): Renamed to ... (struct thread_info_s): .. this. Add member JOINABLE and TH. --- agent/gpg-agent.c | 2 +- jnlib/ChangeLog | 13 ++++++++ jnlib/w32-pth.c | 95 +++++++++++++++++++++++++++++++++---------------------- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 5ac02645e..0a483ac48 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1194,7 +1194,7 @@ start_connection_thread (void *arg) /* FIXME: Move this housekeeping into a ticker function. Calling it for each connection should work but won't work anymore if our - cleints start to keep connections. */ + clients start to keep connections. */ agent_trustlist_housekeeping (); start_command_handler (-1, fd); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index fa871caab..2eaa7916f 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,16 @@ +2004-12-14 Werner Koch <wk@g10code.com> + + * w32-pth.c (_pth_strerror): Renamed to ... + (w32_strerror): .. this. And let callers provide a buffer. + (spawn_helper_thread): Removed HD arg and hardwire the stack size + to 32k. + (do_pth_wait): Removed use of ATTR; not needed for the helper + threads. + (helper_thread): Renamed to .. + (launch_thread): .. this. Release handle if not joinable. + (struct pth_priv_hd_s): Renamed to ... + (struct thread_info_s): .. this. Add member JOINABLE and TH. + 2004-12-14 Timo Schulz <twoaday@g10code.com> * w32-pth.c (pth_kill): Just release the crit section if diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 60c4a4e99..b47e8c9be 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -49,9 +49,6 @@ static HANDLE pth_signo_ev = NULL; static CRITICAL_SECTION pth_shd; -#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) - - struct pth_event_s { @@ -79,19 +76,27 @@ struct pth_attr_s }; -struct _pth_priv_hd_s +/* Object to keep information about a thread. This may eventually be + used to implement a scheduler queue. */ +struct thread_info_s { - void *(*thread)(void *); - void * arg; + void *(*thread)(void *); /* The actual thread fucntion. */ + void * arg; /* The argument passed to that fucntion. */ + int joinable; /* True if this Thread is joinable. */ + HANDLE th; /* Handle of this thread. Used by non-joinable + threads to close the handle. */ }; +/* Convenience macro to startup the system. */ +#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) + /* Prototypes. */ static pth_event_t do_pth_event (unsigned long spec, ...); static unsigned int do_pth_waitpid (unsigned pid, int * status, int options); static int do_pth_wait (pth_event_t ev); static int do_pth_event_status (pth_event_t ev); -static void * helper_thread (void * ctx); +static void *launch_thread (void * ctx); @@ -139,14 +144,13 @@ pth_kill (void) } -static const char * -_pth_strerror (void) +static char * +w32_strerror (char *strerr, size_t strerrsize) { - static char strerr[256]; - - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - strerr, sizeof (strerr)-1, NULL); + if (strerrsize > 1) + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, strerrsize, NULL); return strerr; } @@ -228,8 +232,10 @@ pth_read (int fd, void * buffer, size_t size) n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); if (!n) { - fprintf (stderr, "pth_read(%d) failed read from: %s.\n", fd, - _pth_strerror ()); + char strerr[256]; + + fprintf (stderr, "pth_read(%d) failed read from file: %s\n", fd, + w32_strerror (strerr, sizeof strerr)); n = -1; } else @@ -259,17 +265,16 @@ pth_write (int fd, const void * buffer, size_t size) if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { DWORD nwrite; + char strerr[256]; - /* this is no real error because we first need to figure out if - we have a handle or a socket. */ - /*fprintf (stderr, "pth_write(%d) failed in send: %s\n", fd, - _pth_strerror ());*/ + /* This is no real error because we first need to figure out if + we have a handle or a socket. */ n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); if (!n) { fprintf (stderr, "pth_write(%d) failed in write: %s\n", fd, - _pth_strerror ()); + w32_strerror (strerr, sizeof strerr)); n = -1; } else @@ -597,7 +602,7 @@ do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) SECURITY_ATTRIBUTES sa; DWORD tid; HANDLE th; - struct _pth_priv_hd_s * ctx; + struct thread_info_s *ctx; if (!hd) return NULL; @@ -607,20 +612,32 @@ do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof sa; - ctx = calloc (1, sizeof * ctx); + ctx = calloc (1, sizeof *ctx); if (!ctx) return NULL; ctx->thread = func; ctx->arg = arg; + ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE); /* XXX: we don't use all thread attributes. */ + /* Note that we create the thread suspended so that we are able to + store the thread's handle in the context structure. We need to + do this to be able to close the handle from the launch helper. + + FIXME: We should no use th W32's Thread handle directly but keep + our own thread control structure. CTX may be used for that. */ fprintf (stderr, "do_pth_spawn creating thread ...\n"); th = CreateThread (&sa, hd->stack_size, - (LPTHREAD_START_ROUTINE)helper_thread, - ctx, 0, &tid); + (LPTHREAD_START_ROUTINE)launch_thread, + ctx, CREATE_SUSPENDED, &tid); + ctx->th = th; fprintf (stderr, "do_pth_spawn created thread %p\n", th); - + if (!th) + free (ctx); + else + ResumeThread (th); + return th; } @@ -909,14 +926,22 @@ wait_for_fd (int fd, int is_read, int nwait) static void * -helper_thread (void * ctx) +launch_thread (void *arg) { - struct _pth_priv_hd_s * c = ctx; + struct thread_info_s *c = arg; if (c) { leave_pth (__FUNCTION__); c->thread (c->arg); + if (!c->joinable && c->th) + { + CloseHandle (c->th); + c->th = NULL; + } + /* FIXME: We would badly fail if someone accesses the now + deallocated handle. Don't use it directly but setup proper + scheduling queues. */ enter_pth (__FUNCTION__); free (c); } @@ -1098,7 +1123,7 @@ _pth_event_count (pth_event_t ev) static pth_t -spawn_helper_thread (pth_attr_t hd, void *(*func)(void *), void *arg) +spawn_helper_thread (void *(*func)(void *), void *arg) { SECURITY_ATTRIBUTES sa; DWORD tid; @@ -1110,7 +1135,7 @@ spawn_helper_thread (pth_attr_t hd, void *(*func)(void *), void *arg) sa.nLength = sizeof sa; fprintf (stderr, "spawn_helper_thread creating thread ...\n"); - th = CreateThread (&sa, hd->stack_size, + th = CreateThread (&sa, 32*1024, (LPTHREAD_START_ROUTINE)func, arg, 0, &tid); fprintf (stderr, "spawn_helper_thread created thread %p\n", th); @@ -1164,7 +1189,6 @@ do_pth_wait (pth_event_t ev) HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; int hdidx[MAXIMUM_WAIT_OBJECTS/2]; DWORD n = 0; - pth_attr_t attr; pth_event_t tmp; int pos=0, i=0; @@ -1175,10 +1199,6 @@ do_pth_wait (pth_event_t ev) if (n > MAXIMUM_WAIT_OBJECTS/2) return -1; - attr = pth_attr_new (); - pth_attr_set (attr, PTH_ATTR_JOINABLE, 1); - pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 4096); - fprintf (stderr, "pth_wait: cnt %lu\n", n); for (tmp = ev; tmp; tmp = tmp->next) { @@ -1196,13 +1216,13 @@ do_pth_wait (pth_event_t ev) case PTH_EVENT_FD: fprintf (stderr, "pth_wait: spawn event wait thread.\n"); hdidx[i++] = pos; - waitbuf[pos++] = spawn_helper_thread (attr, wait_fd_thread, tmp); + waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, tmp); break; case PTH_EVENT_TIME: fprintf (stderr, "pth_wait: spawn event timer thread.\n"); hdidx[i++] = pos; - waitbuf[pos++] = spawn_helper_thread (attr, wait_timer_thread, tmp); + waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, tmp); break; case PTH_EVENT_MUTEX: @@ -1216,7 +1236,6 @@ do_pth_wait (pth_event_t ev) fprintf (stderr, "pth_wait: set %d\n", pos); n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); free_helper_threads (waitbuf, hdidx, i); - pth_attr_destroy (attr); fprintf (stderr, "pth_wait: n %ld\n", n); if (n != WAIT_TIMEOUT) -- cgit v1.2.3 From 69967b04125e53811182a01d2700984469117339 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 15 Dec 2004 14:15:54 +0000 Subject: A whole bunch of changes to allow building for W32. --- ChangeLog | 10 ++ Makefile.am | 8 +- acinclude.m4 | 22 ++-- agent/ChangeLog | 13 +++ agent/call-scd.c | 2 +- agent/gpg-agent.c | 16 +-- agent/protect-tool.c | 20 +++- common/ChangeLog | 15 +++ common/asshelp.c | 119 ++++++++++----------- common/exechelp.c | 276 +++++++++++++++++++++++++++++++++++++++++++++--- common/iobuf.c | 4 +- common/simple-pwquery.c | 6 +- common/sysutils.h | 7 ++ common/ttyname.c | 32 ++++++ common/util.h | 4 +- common/w32reg.c | 5 +- configure.ac | 30 +----- g10/call-agent.c | 2 + jnlib/ChangeLog | 4 + jnlib/logging.c | 7 +- m4/ksba.m4 | 2 +- scd/ChangeLog | 11 ++ scd/Makefile.am | 14 ++- scd/apdu.c | 7 +- scd/command.c | 5 + scd/scdaemon.c | 40 ++++++- sm/ChangeLog | 10 ++ sm/Makefile.am | 8 +- sm/gpgsm.c | 15 ++- tools/ChangeLog | 10 ++ tools/Makefile.am | 5 +- tools/gpgconf-comp.c | 18 ++++ 32 files changed, 589 insertions(+), 158 deletions(-) create mode 100644 common/ttyname.c diff --git a/ChangeLog b/ChangeLog index d290c9481..95cf87d25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * Makefile.am (SUBDIRS) [W32]: Do not build in tests/. + + * acinclude.m4: Add proper macro name quoting for use with + automake 1.9. + + * configure.ac: Add replacement check for ttyname. + Removed support for a included zlib. + 2004-12-06 Werner Koch <wk@g10code.com> * configure.ac (have_w32_system): New. Disable Pth checks for W32. diff --git a/Makefile.am b/Makefile.am index 08d025abf..e6cbde893 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,8 +53,14 @@ else scd = endif +if HAVE_W32_SYSTEM +tests = +else +tests = tests +endif + SUBDIRS = m4 intl jnlib common ${kbx} \ - ${gpg} ${sm} ${agent} ${scd} tools po doc tests + ${gpg} ${sm} ${agent} ${scd} tools po doc ${tests} dist-hook: @set -e; \ diff --git a/acinclude.m4 b/acinclude.m4 index f6bbae78e..5f742b279 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -20,7 +20,7 @@ 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_DEFUN([GNUPG_CHECK_TYPEDEF], [ AC_MSG_CHECKING(for $1 typedef) AC_CACHE_VAL(gnupg_cv_typedef_$1, [AC_TRY_COMPILE([#define _GNU_SOURCE 1 @@ -38,7 +38,7 @@ AC_DEFUN(GNUPG_CHECK_TYPEDEF, dnl GNUPG_CHECK_GNUMAKE dnl -AC_DEFUN(GNUPG_CHECK_GNUMAKE, +AC_DEFUN([GNUPG_CHECK_GNUMAKE], [ if ${MAKE-make} --version 2>/dev/null | grep '^GNU ' >/dev/null 2>&1; then : @@ -55,7 +55,7 @@ AC_DEFUN(GNUPG_CHECK_GNUMAKE, dnl GNUPG_CHECK_FAQPROG dnl -AC_DEFUN(GNUPG_CHECK_FAQPROG, +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 @@ -82,7 +82,7 @@ dnl fi dnl GNUPG_CHECK_DOCBOOK_TO_TEXI dnl -AC_DEFUN(GNUPG_CHECK_DOCBOOK_TO_TEXI, +AC_DEFUN([GNUPG_CHECK_DOCBOOK_TO_TEXI], [ AC_CHECK_PROG(DOCBOOK_TO_TEXI, docbook2texi, yes, no) AC_MSG_CHECKING(for sgml to texi tools) @@ -101,7 +101,7 @@ AC_DEFUN(GNUPG_CHECK_DOCBOOK_TO_TEXI, dnl GNUPG_CHECK_ENDIAN dnl define either LITTLE_ENDIAN_HOST or BIG_ENDIAN_HOST dnl -define(GNUPG_CHECK_ENDIAN, +AC_DEFUN([GNUPG_CHECK_ENDIAN], [ tmp_assumed_endian=big if test "$cross_compiling" = yes; then @@ -158,7 +158,7 @@ define(GNUPG_CHECK_ENDIAN, # Check for the getsockopt SO_PEERCRED -AC_DEFUN(GNUPG_SYS_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>], @@ -183,7 +183,7 @@ AC_DEFUN(GNUPG_SYS_SO_PEERCRED, # 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, +AC_DEFUN([GNUPG_BUILD_PROGRAM], [build_$1=$2 m4_if([$2],[yes],[ AC_ARG_ENABLE([$1], AC_HELP_STRING([--disable-$1], @@ -210,7 +210,7 @@ AC_DEFUN(GNUPG_BUILD_PROGRAM, # 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, +AC_DEFUN([GNUPG_PTH_VERSION_CHECK], [ _pth_version=`$PTH_CONFIG --version | awk 'NR==1 {print [$]3}'` _req_version="ifelse([$1],,1.2.0,$1)" @@ -253,7 +253,7 @@ AC_DEFUN(GNUPG_PTH_VERSION_CHECK, # mlock is there a macro using memlk() dnl GNUPG_CHECK_MLOCK dnl -define(GNUPG_CHECK_MLOCK, +AC_DEFUN([GNUPG_CHECK_MLOCK], [ AC_CHECK_FUNCS(mlock) if test "$ac_cv_func_mlock" = "no"; then AC_CHECK_HEADERS(sys/mman.h) @@ -343,7 +343,7 @@ define(GNUPG_CHECK_MLOCK, 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_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([ @@ -371,7 +371,7 @@ 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_DEFUN([AM_PATH_OPENSC], [ AC_ARG_WITH(opensc-prefix, AC_HELP_STRING([--with-opensc-prefix=PFX], [prefix where OpenSC is installed (optional)]), diff --git a/agent/ChangeLog b/agent/ChangeLog index e0bf52b45..3669b0e43 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,16 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * gpg-agent.c [W32]: Various hacks to make it work. + + * findkey.c (agent_write_private_key) [W32]: Adjust open call. + + * call-scd.c (start_scd) [W32]: Don't check whether the daemon + didn't died. To hard to do under Windows. + (start_scd) [W32]: Disable sending of the event signal option. + + * protect-tool.c (read_file, export_p12_file) [W32]: Use setmode + to get stdout and stin into binary mode. + 2004-12-05 Moritz Schulte <moritz@g10code.com> * query.c (start_pinentry): Allow CTRL be NULL. diff --git a/agent/call-scd.c b/agent/call-scd.c index 575986dc9..828040772 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -215,7 +215,7 @@ start_scd (ctrl_t ctrl) /* We better do a sanity check now to see whether it has accidently died. */ -#ifndef HAVE_W32_SYSTEM /* fixme */ +#ifndef HAVE_W32_SYSTEM pid = assuan_get_pid (scd_ctx); if (pid != (pid_t)(-1) && pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 0a483ac48..307d43d36 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -33,7 +33,7 @@ #ifndef HAVE_W32_SYSTEM #include <sys/socket.h> #include <sys/un.h> -#endif +#endif /*HAVE_W32_SYSTEM*/ #include <unistd.h> #include <signal.h> #ifdef USE_GNU_PTH @@ -438,17 +438,18 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ -#if defined(USE_GNU_PTH) && !defined(HAVE_W32_SYSTEM) +#ifdef USE_GNU_PTH +# ifdef HAVE_W32_SYSTEM + pth_init (); +# else /*!HAVE_W32_SYSTEM*/ err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -#endif /*USE_GNU_PTH && !HAVE_W32_SYSTEM*/ -#ifdef HAVE_W32_SYSTEM - pth_init (); -#endif +# endif/*!HAVE_W32_SYSTEM*/ +#endif /*USE_GNU_PTH*/ /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library. */ @@ -716,12 +717,11 @@ main (int argc, char **argv ) } /* Make sure that we have a default ttyname. */ -#ifndef HAVE_W32_SYSTEM if (!default_ttyname && ttyname (1)) default_ttyname = xstrdup (ttyname (1)); if (!default_ttytype && getenv ("TERM")) default_ttytype = xstrdup (getenv ("TERM")); -#endif + if (pipe_server) { /* this is the simple pipe based server */ diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 286adde54..ef8a50916 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -35,6 +35,9 @@ #ifdef HAVE_LANGINFO_CODESET #include <langinfo.h> #endif +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif #define JNLIB_NEED_LOG_LOGV #include "agent.h" @@ -262,6 +265,9 @@ read_file (const char *fname, size_t *r_length) size_t nread, bufsize = 0; fp = stdin; +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(fp) , O_BINARY ); +#endif buf = NULL; buflen = 0; #define NCHUNK 8192 @@ -975,6 +981,9 @@ export_p12_file (const char *fname) if (!key) return; +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno (stdout) , O_BINARY ); +#endif fwrite (key, keylen, 1, stdout); xfree (key); } @@ -1056,12 +1065,12 @@ main (int argc, char **argv ) gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); -#ifdef __MINGW32__ +#ifdef HAVE_W32_SYSTEM opt_homedir = read_w32_registry_string ( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); -#else +#else /*!HAVE_W32_SYSTEM*/ opt_homedir = getenv ("GNUPGHOME"); -#endif +#endif /*!HAVE_W32_SYSTEM*/ if (!opt_homedir || !*opt_homedir) opt_homedir = GNUPG_DEFAULT_HOMEDIR; @@ -1213,9 +1222,10 @@ get_passphrase (int promptno) if (!pw) { if (err) - log_error ("error while asking for the passphrase\n"); + log_error (_("error while asking for the passphrase: %s\n"), + gpg_strerror (err)); else - log_info ("cancelled\n"); + log_info (_("cancelled\n")); agent_exit (0); } diff --git a/common/ChangeLog b/common/ChangeLog index afdded6d9..3115ad897 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,18 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * sysutils.h [W32]: Prototypes for registry functions. + * w32reg.c: Include sysutils.h + + * simple-pwquery.c [W32]: Dummy code to allow a build. + + * exechelp.c [W32]: Implemented for W32 . + + * ttyname.c: New. + + * asshelp.c (send_one_option): New. + (send_pinentry_environment): Cleaned up and made sure that empty + values are not send. + 2004-12-07 Werner Koch <wk@g10code.com> * asshelp.c (send_pinentry_environment) [W32]: Do not use ttyname. diff --git a/common/asshelp.c b/common/asshelp.c index 751412e6c..243d6b9e7 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -32,8 +32,32 @@ #include "asshelp.h" -/* Send the assuan command pertaining to the pinenry environment. The - OPT_* arguments are optional and may be used to overide the + +static gpg_error_t +send_one_option (assuan_context_t ctx, const char *name, const char *value) +{ + gpg_error_t err; + char *optstr; + + if (!value || !*value) + err = 0; /* Avoid sending empty strings. */ + else if (asprintf (&optstr, "OPTION %s=%s", name, value ) < 0) + err = gpg_error_from_errno (errno); + else + { + assuan_error_t ae; + + ae = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); + err = ae? map_assuan_err (ae) : 0; + free (optstr); + } + + return err; +} + + +/* Send the assuan commands pertaining to the pinenry environment. The + OPT_* arguments are optional and may be used to override the defaults taken from the current locale. */ gpg_error_t send_pinentry_environment (assuan_context_t ctx, @@ -43,62 +67,49 @@ send_pinentry_environment (assuan_context_t ctx, const char *opt_lc_ctype, const char *opt_lc_messages) { - int rc = 0; + gpg_error_t err = 0; char *dft_display = NULL; char *dft_ttyname = NULL; char *dft_ttytype = NULL; char *old_lc = NULL; char *dft_lc = NULL; + /* Send the DISPLAY variable. */ 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); + err = send_one_option (ctx, "display", + opt_display ? opt_display : dft_display); + if (err) + return err; } + + /* Send the name of the TTY. */ if (!opt_ttyname) { dft_ttyname = getenv ("GPG_TTY"); -#ifdef HAVE_DOSISH_SYSTEM - if (!dft_ttyname || !*dft_ttyname ) - dft_ttyname = "/dev/tty"; /* Use a fake. */ -#else if ((!dft_ttyname || !*dft_ttyname) && ttyname (0)) dft_ttyname = ttyname (0); -#endif } 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); + err = send_one_option (ctx, "ttyname", + opt_ttyname ? opt_ttyname : dft_ttyname); + if (err) + return err; } + + /* Send the type of the TTY. */ 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); + err = send_one_option (ctx, "ttytype", + opt_ttyname ? opt_ttytype : dft_ttytype); + if (err) + return err; } + + /* Send the value for LC_CTYPE. */ #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) old_lc = setlocale (LC_CTYPE, NULL); if (old_lc) @@ -111,18 +122,8 @@ send_pinentry_environment (assuan_context_t ctx, #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); - } + err = send_one_option (ctx, "lc-ctype", + opt_lc_ctype ? opt_lc_ctype : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) if (old_lc) @@ -131,8 +132,10 @@ send_pinentry_environment (assuan_context_t ctx, free (old_lc); } #endif - if (rc) - return rc; + if (err) + return err; + + /* Send the value for LC_MESSAGES. */ #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) old_lc = setlocale (LC_MESSAGES, NULL); if (old_lc) @@ -145,18 +148,8 @@ send_pinentry_environment (assuan_context_t ctx, #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); - } + err = send_one_option (ctx, "display", + opt_lc_messages ? opt_lc_messages : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) if (old_lc) @@ -165,7 +158,9 @@ send_pinentry_environment (assuan_context_t ctx, free (old_lc); } #endif + if (err) + return err; - return rc; + return 0; } diff --git a/common/exechelp.c b/common/exechelp.c index 206e16d51..0a9cb824f 100644 --- a/common/exechelp.c +++ b/common/exechelp.c @@ -30,8 +30,7 @@ #ifdef USE_GNU_PTH #include <pth.h> #endif -#ifdef _WIN32 -#else +#ifndef HAVE_W32_SYSTEM #include <sys/wait.h> #endif @@ -39,6 +38,9 @@ #include "i18n.h" #include "exechelp.h" +/* Define to 1 do enable debugging. */ +#define DEBUG_W32_SPAWN 1 + #ifdef _POSIX_OPEN_MAX #define MAX_OPEN_FDS _POSIX_OPEN_MAX @@ -57,6 +59,105 @@ #endif +#ifdef HAVE_W32_SYSTEM +/* We assume that a HANDLE can be represented by an int which should + be true for all i386 systems (HANDLE is defined as void *) and + these are the only systems for which Windows is available. Further + we assume that -1 denotes an invalid handle. */ +# define fd_to_handle(a) ((HANDLE)(a)) +# define handle_to_fd(a) ((int)(a)) +# define pid_to_handle(a) ((HANDLE)(a)) +# define handle_to_pid(a) ((int)(a)) +#endif + + +#ifdef HAVE_W32_SYSTEM +/* Build a command line for use with W32's CreateProcess. On success + CMDLINE gets the address of a newly allocated string. */ +static gpg_error_t +build_w32_commandline (const char *pgmname, const char **argv, char **cmdline) +{ + int i, n; + const char *s; + char *buf, *p; + + *cmdline = NULL; + n = strlen (pgmname); + for (i=0; (s=argv[i]); i++) + { + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + } + n++; + + buf = p = xtrymalloc (n); + if (!buf) + return gpg_error_from_errno (errno); + + /* fixme: PGMNAME may not contain spaces etc. */ + p = stpcpy (p, pgmname); + for (i=0; argv[i]; i++) + { + if (!*argv[i]) /* Empty string. */ + p = stpcpy (p, " \"\""); + else if (strpbrk (argv[i], " \t\n\v\f\"")) + { + p = stpcpy (p, " \""); + for (s=argv[i]; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + } + else + p = stpcpy (stpcpy (p, " "), argv[i]); + } + + *cmdline= buf; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + +#ifdef HAVE_W32_SYSTEM +/* Create pipe where the write end is inheritable. */ +static int +create_inheritable_pipe (int filedes[2]) +{ + HANDLE r, w, h; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + if (!CreatePipe (&r, &w, &sec_attr, 0)) + return -1; + + if (!DuplicateHandle (GetCurrentProcess(), w, + GetCurrentProcess(), &h, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1)); + CloseHandle (r); + CloseHandle (w); + return -1; + } + CloseHandle (w); + w = h; + + filedes[0] = handle_to_fd (r); + filedes[1] = handle_to_fd (w); + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to stdin, write the output to OUTFILE, return a new stream in @@ -73,10 +174,121 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], void (*preexec)(void), FILE **statusfile, pid_t *pid) { -#ifdef _WIN32 - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#ifdef HAVE_W32_SYSTEM + gpg_error_t err; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int cr_flags; + char *cmdline; + int fd, fdout, rp[2]; -#else /* !_WIN32 */ + /* Setup return values. */ + *statusfile = NULL; + *pid = (pid_t)(-1); + fflush (infile); + rewind (infile); + fd = _get_osfhandle (fileno (infile)); + fdout = _get_osfhandle (fileno (outfile)); + if (fd == -1 || fdout == -1) + log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n"); + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Build the command line. */ + err = build_w32_commandline (pgmname, argv, &cmdline); + if (err) + return err; + + /* Create a pipe. */ + if (create_inheritable_pipe (rp)) + { + err = gpg_error (GPG_ERR_GENERAL); + log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); + xfree (cmdline); + return err; + } + + /* Start the process. Note that we can't run the PREEXEC function + because this would change our own environment. */ + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; + si.hStdInput = fd_to_handle (fd); + si.hStdOutput = fd_to_handle (fdout); + si.hStdError = fd_to_handle (rp[1]); + + cr_flags = (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED); + log_debug ("CreateProcess, path=`%s' cmdline=`%s'", pgmname, cmdline); + if (!CreateProcess (pgmname, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); + xfree (cmdline); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + return gpg_error (GPG_ERR_GENERAL); + } + xfree (cmdline); + cmdline = NULL; + + /* Close the other end of the pipe. */ + CloseHandle (fd_to_handle (rp[1])); + + log_debug ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + /* Process ha been created suspended; resume it now. */ + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + + { + int x; + + x = _open_osfhandle (rp[0], 0); + if (x == -1) + log_error ("failed to translate osfhandle %p\n", (void*)rp[0] ); + else + { + log_debug ("_open_osfhandle %p yields %d\n", (void*)fd, x ); + *statusfile = fdopen (x, "r"); + } + } + if (!*statusfile) + { + err = gpg_error_from_errno (errno); + log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err)); + CloseHandle (pi.hProcess); + return err; + } + + *pid = handle_to_pid (pi.hProcess); + return 0; + +#else /* !HAVE_W32_SYSTEM */ gpg_error_t err; int fd, fdout, rp[2]; @@ -87,8 +299,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], fd = fileno (infile); fdout = fileno (outfile); if (fd == -1 || fdout == -1) - log_fatal ("no file descriptor for file passed" - " to gnupg_spawn_process: %s\n", strerror (errno) ); + log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n"); if (pipe (rp) == -1) { @@ -170,7 +381,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], } return 0; -#endif /* !_WIN32 */ +#endif /* !HAVE_W32_SYSTEM */ } @@ -183,10 +394,51 @@ gnupg_wait_process (const char *pgmname, pid_t pid) { gpg_err_code_t ec; -#ifdef _WIN32 - ec = GPG_ERR_NOT_IMPLEMENTED; +#ifdef HAVE_W32_SYSTEM + HANDLE proc = fd_to_handle (pid); + int code; + DWORD exc; + + if (pid == (pid_t)(-1)) + return gpg_error (GPG_ERR_INV_VALUE); + + /* FIXME: We should do a pth_waitpid here. However this has not yet + been implemented. A special W32 pth system call would even be + better. */ + code = WaitForSingleObject (proc, INFINITE); + switch (code) + { + case WAIT_FAILED: + log_error (_("waiting for process %d to terminate failed: %s\n"), + (int)pid, w32_strerror (-1)); + ec = GPG_ERR_GENERAL; + break; + + case WAIT_OBJECT_0: + if (!GetExitCodeProcess (proc, &exc)) + { + log_error (_("error getting exit code of process %d: %s\n"), + (int)pid, w32_strerror (-1) ); + ec = GPG_ERR_GENERAL; + } + else if (exc) + { + log_error (_("error running `%s': exit status %d\n"), + pgmname, (int)exc ); + ec = GPG_ERR_GENERAL; + } + else + ec = 0; + break; + + default: + log_error ("WaitForSingleObject returned unexpected " + "code %d for pid %d\n", code, (int)pid ); + ec = GPG_ERR_GENERAL; + break; + } -#else /* !_WIN32 */ +#else /* !HAVE_W32_SYSTEM */ int i, status; if (pid == (pid_t)(-1)) @@ -222,7 +474,7 @@ gnupg_wait_process (const char *pgmname, pid_t pid) } else ec = 0; -#endif /* !_WIN32 */ +#endif /* !HAVE_W32_SYSTEM */ return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); diff --git a/common/iobuf.c b/common/iobuf.c index 4d735397e..52a388514 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -1096,7 +1096,7 @@ iobuf_cancel (iobuf_t a) if (s && *s) { #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - remove_name = m_strdup (s); + remove_name = xstrdup (s); #else remove (s); #endif @@ -1267,7 +1267,7 @@ iobuf_sockopen (int fd, const char *mode) size_t len; a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192); - scx = m_alloc (sizeof *scx + 25); + scx = xmalloc (sizeof *scx + 25); scx->sock = fd; scx->print_only_name = 1; sprintf (scx->fname, "[sock %d]", fd); diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 1e8eae63b..e7f992a88 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -31,7 +31,7 @@ #include <string.h> #include <errno.h> #include <unistd.h> -#ifdef _WIN32 +#ifdef HAVE_W32_SYSTEM #include <winsock2.h> #else #include <sys/socket.h> @@ -182,10 +182,8 @@ agent_send_all_options (int fd) } dft_ttyname = getenv ("GPG_TTY"); -#ifndef HAVE_W32_SYSTEM if ((!dft_ttyname || !*dft_ttyname) && ttyname (0)) dft_ttyname = ttyname (0); -#endif if (dft_ttyname && *dft_ttyname) { if ((rc=agent_send_option (fd, "ttyname", dft_ttyname))) @@ -261,7 +259,7 @@ agent_send_all_options (int fd) static int agent_open (int *rfd) { -#ifdef _WIN32 +#ifdef HAVE_W32_SYSTEM return SPWQ_NO_AGENT; /* FIXME */ #else int rc; diff --git a/common/sysutils.h b/common/sysutils.h index 66f714acd..9df292031 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -27,5 +27,12 @@ int enable_core_dumps (void); const unsigned char *get_session_marker (size_t *rlen); int check_permissions (const char *path,int extension,int checkonly); +#ifdef HAVE_W32_SYSTEM +/*-- w32reg.c --*/ +char *read_w32_registry_string( const char *root, + const char *dir, const char *name ); +int write_w32_registry_string(const char *root, const char *dir, + const char *name, const char *value); +#endif /*HAVE_W32_SYSTEM*/ #endif /*GNUPG_COMMON_SYSUTILS_H*/ diff --git a/common/ttyname.c b/common/ttyname.c new file mode 100644 index 000000000..822beef99 --- /dev/null +++ b/common/ttyname.c @@ -0,0 +1,32 @@ +/* ttyname.c - Replacement for ttyname. + * 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 + */ + +/* This one is a simple dummy and suitable for Dosish systems. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> + +char * +ttyname (int fd) +{ + return NULL; +} diff --git a/common/util.h b/common/util.h index fad7d38cc..0b9357d3a 100644 --- a/common/util.h +++ b/common/util.h @@ -147,7 +147,9 @@ int asprintf (char **result, const char *format, ...) JNLIB_GCC_A_PRINTF(2,3); #ifndef HAVE_STRSEP char *strsep (char **stringp, const char *delim); #endif - +#ifndef HAVE_TTYNAME +char *ttyname (int fd); +#endif /*-- some macros to replace ctype ones and avoid locale problems --*/ #define spacep(p) (*(p) == ' ' || *(p) == '\t') diff --git a/common/w32reg.c b/common/w32reg.c index 19fb613e7..a85ac7348 100644 --- a/common/w32reg.c +++ b/common/w32reg.c @@ -19,7 +19,7 @@ */ #include <config.h> -#if defined (_WIN32) || defined (__CYGWIN32__) +#ifdef HAVE_W32_SYSTEM /* This module is only used in this environment */ #include <stdio.h> @@ -29,6 +29,7 @@ #include <windows.h> #include "util.h" +#include "sysutils.h" static HKEY get_root_key(const char *root) @@ -169,4 +170,4 @@ write_w32_registry_string(const char *root, const char *dir, return 0; } -#endif /* __MINGW32__ || __CYGWIN32__ */ +#endif /*HAVE_W32_SYSTEM*/ diff --git a/configure.ac b/configure.ac index 481e52c52..facbfe416 100644 --- a/configure.ac +++ b/configure.ac @@ -218,12 +218,6 @@ if test "$use_exec" = yes ; then AC_MSG_RESULT($enableval) fi -AC_MSG_CHECKING([whether the included zlib is requested]) -AC_ARG_WITH(included-zlib, - [ --with-included-zlib use the zlib code included here], -[g10_force_zlib=yes], [g10_force_zlib=no] ) -AC_MSG_RESULT($g10_force_zlib) - dnl dnl Check whether we want to use Linux capabilities dnl @@ -799,6 +793,7 @@ AC_REPLACE_FUNCS(fseeko ftello) AC_REPLACE_FUNCS(isascii) AC_REPLACE_FUNCS(putc_unlocked) AC_REPLACE_FUNCS(strsep) +AC_REPLACE_FUNCS(ttyname) @@ -923,14 +918,10 @@ fi dnl Do we have zlib? Must do it here because Solaris failed dnl when compiling a conftest (due to the "-lz" from LIBS). -use_local_zlib=yes -if test "$g10_force_zlib" = "yes"; then - : -else - _cppflags="${CPPFLAGS}" - _ldflags="${LDFLAGS}" +_cppflags="${CPPFLAGS}" +_ldflags="${LDFLAGS}" - AC_ARG_WITH(zlib, +AC_ARG_WITH(zlib, [ --with-zlib=DIR use libz in DIR],[ if test -d "$withval"; then CPPFLAGS="${CPPFLAGS} -I$withval/include" @@ -938,23 +929,12 @@ else fi ]) - AC_CHECK_HEADER(zlib.h, +AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, deflateInit2_, - use_local_zlib=no LIBS="$LIBS -lz", CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) -fi -if test "$use_local_zlib" = yes ; then - AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, true) - AC_CONFIG_LINKS(zlib.h:zlib/zlib.h zconf.h:zlib/zconf.h ) - ZLIBS="../zlib/libzlib.a" -else - AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, false) - ZLIBS= -fi -AC_SUBST(ZLIBS) # See wether we want to run the long test suite. diff --git a/g10/call-agent.c b/g10/call-agent.c index f93132fde..473b38236 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -171,6 +171,8 @@ start_agent (void) if (rc) return map_assuan_err (rc); +#warning put this code into common/asshelp.c + dft_display = getenv ("DISPLAY"); if (opt.display || dft_display) { diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 2eaa7916f..71512715b 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * logging.c [W32]: Don't include unavailable headers. + 2004-12-14 Werner Koch <wk@g10code.com> * w32-pth.c (_pth_strerror): Renamed to ... diff --git a/jnlib/logging.c b/jnlib/logging.c index 960d816eb..781f03e6d 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -35,16 +35,13 @@ #include <time.h> #include <sys/types.h> #include <sys/stat.h> -#ifndef _WIN32 +#ifndef HAVE_W32_SYSTEM #include <sys/socket.h> #include <sys/un.h> -#endif +#endif /*!HAVE_W32_SYSTEM*/ #include <unistd.h> #include <fcntl.h> #include <assert.h> -#ifdef __MINGW32__ -# include <io.h> -#endif #define JNLIB_NEED_LOG_LOGV 1 diff --git a/m4/ksba.m4 b/m4/ksba.m4 index c59ac8024..99017c39e 100644 --- a/m4/ksba.m4 +++ b/m4/ksba.m4 @@ -14,7 +14,7 @@ dnl AM_PATH_KSBA([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libksba and define KSBA_CFLAGS and KSBA_LIBS dnl -AC_DEFUN(AM_PATH_KSBA, +AC_DEFUN([AM_PATH_KSBA], [ AC_ARG_WITH(ksba-prefix, AC_HELP_STRING([--with-ksba-prefix=PFX], [prefix where KSBA is installed (optional)]), diff --git a/scd/ChangeLog b/scd/ChangeLog index 628055e80..fe3b3f6c4 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,14 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * scdaemon.c [W32]: Various hacks to make it run under W32. + + * command.c (scd_update_reader_status_file) [W32]: Don't use kill. + + * apdu.c [W32]: Disable use of pcsc_wrapper. + + * Makefile.am (scdaemon_LDADD): Reorder libs. + (sc_copykeys_LDADD): Add libassuan because it is needed for W32. + 2004-12-06 Werner Koch <wk@g10code.com> * Makefile.am (pkglib_PROGRAMS): Build only for W32. diff --git a/scd/Makefile.am b/scd/Makefile.am index 43bee4889..fba006c5a 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -19,7 +19,7 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = scdaemon sc-copykeys -if HAVE_W32_SYSTEM +if ! HAVE_W32_SYSTEM pkglib_PROGRAMS = pcsc-wrapper endif @@ -53,10 +53,8 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ - $(LIBGCRYPT_LIBS) $(pth_libs) \ - $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error @LIBINTL@ \ - @DL_LIBS@ + $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(pth_libs) $(LIBASSUAN_LIBS) \ + $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) sc_copykeys_SOURCES = \ sc-copykeys.c scdaemon.h \ @@ -70,10 +68,10 @@ sc_copykeys_SOURCES = \ sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(LIBGCRYPT_LIBS) $(pth_libs) \ - $(KSBA_LIBS) $(LIBUSB_LIBS) $(OPENSC_LIBS) \ + $(LIBGCRYPT_LIBS) $(pth_libs) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ + $(LIBUSB_LIBS) $(OPENSC_LIBS) \ -lgpg-error @LIBINTL@ @DL_LIBS@ pcsc_wrapper_SOURCES = pcsc-wrapper.c -pcsc_wrapper_LDADD = @DL_LIBS@ +pcsc_wrapper_LDADD = $(DL_LIBS) pcsc_wrapper_CFLAGS = diff --git a/scd/apdu.c b/scd/apdu.c index f4b32d141..9120616de 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -65,11 +65,16 @@ #include "dynload.h" #include "ccid-driver.h" + +/* To to conflicting use of threading libraries we usually can't link + against libpcsclite. Instead we use a wrapper program. */ #ifdef USE_GNU_PTH +#ifndef HAVE_W32_SYSTEM #define NEED_PCSC_WRAPPER 1 #endif +#endif - + #define MAX_READER 4 /* Number of readers we support concurrently. */ diff --git a/scd/command.c b/scd/command.c index 6fa100ff9..b99fffc09 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1260,8 +1260,13 @@ scd_update_reader_status_file (void) int signo = primary_connection->server_local->event_signal; log_info ("client pid is %d, sending signal %d\n", pid, signo); + +#ifdef HAVE_W32_SYSTEM +#warning Need to implement a notification service +#else if (pid != (pid_t)(-1) && pid && signo > 0) kill (pid, signo); +#endif } } } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index b54a63816..135f0973a 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -29,8 +29,10 @@ #include <assert.h> #include <time.h> #include <fcntl.h> +#ifndef HAVE_W32_SYSTEM #include <sys/socket.h> #include <sys/un.h> +#endif /*HAVE_W32_SYSTEM*/ #include <unistd.h> #include <signal.h> #ifdef USE_GNU_PTH @@ -47,6 +49,9 @@ #include "i18n.h" #include "sysutils.h" #include "app-common.h" +#ifdef HAVE_W32_SYSTEM +#include "../jnlib/w32-afunix.h" +#endif enum cmd_and_opt_values @@ -131,7 +136,12 @@ static ARGPARSE_OPTS opts[] = { }; +/* The card dirver we use by default for PC/SC. */ +#ifdef HAVE_W32_SYSTEM +#define DEFAULT_PCSC_DRIVER "winscard.dll" +#else #define DEFAULT_PCSC_DRIVER "libpcsclite.so" +#endif static volatile int caught_fatal_sig = 0; @@ -148,8 +158,10 @@ static char socket_name[128]; #ifndef HAVE_OPENSC #ifdef USE_GNU_PTH +#ifndef HAVE_W32_SYSTEM /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; +#endif static void *ticker_thread (void *arg); #endif /*USE_GNU_PTH*/ @@ -341,12 +353,16 @@ main (int argc, char **argv ) Note that this will also do the pth_init. */ #ifndef HAVE_OPENSC #ifdef USE_GNU_PTH +# ifdef HAVE_W32_SYSTEM + pth_init (); +# else /*!HAVE_W32_SYSTEM*/ err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } +# endif /*!HAVE_W32_SYSTEM*/ #endif /*USE_GNU_PTH*/ #endif /*!HAVE_OPENSC*/ @@ -649,12 +665,15 @@ main (int argc, char **argv ) if (!p) BUG (); *p = 0;; + +#ifndef HAVE_W32_SYSTEM if (!mkdtemp(socket_name)) { log_error ("can't create directory `%s': %s\n", socket_name, strerror(errno) ); exit (1); } +#endif *p = '/'; if (strchr (socket_name, ':') ) @@ -669,7 +688,11 @@ main (int argc, char **argv ) } +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif if (fd == -1) { log_error ("can't create socket: %s\n", strerror(errno) ); @@ -682,7 +705,13 @@ main (int argc, char **argv ) len = (offsetof (struct sockaddr_un, sun_path) + strlen(serv_addr.sun_path) + 1); - if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1) + if ( +#ifdef HAVE_W32_SYSTEM + _w32_sock_bind +#else + bind +#endif + (fd, (struct sockaddr*)&serv_addr, len) == -1) { log_error ("error binding socket to `%s': %s\n", serv_addr.sun_path, strerror (errno) ); @@ -702,6 +731,7 @@ main (int argc, char **argv ) fflush (NULL); +#ifndef HAVE_W32_SYSTEM pid = fork (); if (pid == (pid_t)-1) { @@ -800,6 +830,8 @@ main (int argc, char **argv ) exit (1); } +#endif /*!HAVE_W32_SYSTEM*/ + scd_command_handler (fd); close (fd); @@ -846,6 +878,7 @@ handle_signal (int signo) { switch (signo) { +#ifndef HAVE_W32_SYSTEM case SIGHUP: log_info ("SIGHUP received - " "re-reading configuration and resetting cards\n"); @@ -882,6 +915,7 @@ handle_signal (int signo) cleanup (); scd_exit (0); break; +#endif /*!HAVE_W32_SYSTEM*/ default: log_info ("signal %d received - no action defined\n", signo); @@ -901,6 +935,7 @@ ticker_thread (void *dummy_arg) sigset_t sigs; int signo; +#ifndef HAVE_W32_SYSTEM /* fixme */ sigemptyset (&sigs ); sigaddset (&sigs, SIGHUP); sigaddset (&sigs, SIGUSR1); @@ -908,6 +943,9 @@ ticker_thread (void *dummy_arg) sigaddset (&sigs, SIGINT); sigaddset (&sigs, SIGTERM); sigs_ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); +#else + sigs_ev = NULL; +#endif for (;;) { diff --git a/sm/ChangeLog b/sm/ChangeLog index c1e445e4e..096c4ca8e 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * misc.c (setup_pinentry_env) [W32]: Don't use it. + + * gpgsm.c (main) [W32]: Init Pth because we need it for the socket + operations and to resolve libassuan symbols. + (run_protect_tool) [W32]: Disable it. + + * Makefile.am (gpgsm_LDADD): Move LIBASSUAN_LIBS more to the end. + 2004-12-07 Werner Koch <wk@g10code.com> * Makefile.am (gpgsm_LDADD): Put libassuan before jnlib because diff --git a/sm/Makefile.am b/sm/Makefile.am index ff4524fc7..9136eb920 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -51,9 +51,9 @@ gpgsm_SOURCES = \ certreqgen.c -gpgsm_LDADD = $(LIBASSUAN_LIBS) ../jnlib/libjnlib.a ../kbx/libkeybox.a \ - ../common/libcommon.a \ - $(LIBGCRYPT_LIBS) $(KSBA_LIBS) -lgpg-error \ - $(LIBINTL) +gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a \ + ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -lgpg-error \ + $(LIBINTL) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 0feca2608..f79375da7 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -26,6 +26,9 @@ #include <ctype.h> #include <unistd.h> #include <fcntl.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif #include "gpgsm.h" #include <gcrypt.h> @@ -736,6 +739,11 @@ main ( int argc, char **argv) NEED_KSBA_VERSION, ksba_check_version (NULL) ); } +#ifdef HAVE_W32_SYSTEM + pth_init (); +#endif + + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); may_coredump = disable_core_dumps (); @@ -746,7 +754,8 @@ main ( int argc, char **argv) i18n_init(); opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/ -#ifdef __MINGW32__ + +#ifdef HAVE_W32_SYSTEM opt.homedir = read_w32_registry_string ( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); #else @@ -1688,7 +1697,7 @@ open_fwrite (const char *filename) static void run_protect_tool (int argc, char **argv) { -#ifndef _WIN32 +#ifndef HAVE_W32_SYSTEM const char *pgm; char **av; int i; @@ -1707,6 +1716,6 @@ run_protect_tool (int argc, char **argv) av[i] = NULL; execv (pgm, av); log_error ("error executing `%s': %s\n", pgm, strerror (errno)); -#endif +#endif /*HAVE_W32_SYSTEM*/ gpgsm_exit (2); } diff --git a/tools/ChangeLog b/tools/ChangeLog index cb341ad4f..34e985947 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,13 @@ +2004-12-15 Werner Koch <wk@g10code.com> + + * Makefile.am (bin_PROGRAMS) [W32]: Do not build watchgnupg. + + * gpgconf-comp.c (gpg_agent_runtime_change) [W32]: No way yet to + send a signal. Disable. + (change_options_file, change_options_program) [W32]: No link(2), + so we disable it. + (gc_component_change_options): Use rename instead of link. + 2004-12-13 Werner Koch <wk@g10code.com> * gpgconf-comp.c <ignore-ocsp-service-url>: Fixed typo. diff --git a/tools/Makefile.am b/tools/Makefile.am index 2378df813..112c77e7c 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -32,7 +32,10 @@ sbin_SCRIPTS = addgnupghome bin_SCRIPTS = gpgsm-gencert.sh -bin_PROGRAMS = gpgconf watchgnupg +bin_PROGRAMS = gpgconf +if !HAVE_W32_SYSTEM +bin_PROGRAMS += watchgnupg +endif gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 5d78df86d..fe696301c 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -861,6 +861,7 @@ static struct void gpg_agent_runtime_change (void) { +#ifndef HAVE_W32_SYSTEM char *agent = getenv ("GPG_AGENT_INFO"); char *pid_str; unsigned long pid_long; @@ -888,6 +889,7 @@ gpg_agent_runtime_change (void) /* Ignore any errors here. */ kill (pid, SIGHUP); +#endif /*!HAVE_W32_SYSTEM*/ } @@ -1741,7 +1743,12 @@ change_options_file (gc_component_t component, gc_backend_t backend, arg = NULL; } +#if HAVE_W32_SYSTEM + res = 0; +#warning no backups for W32 yet - need to write a copy function +#else res = link (dest_filename, orig_filename); +#endif if (res < 0 && errno != ENOENT) return -1; if (res < 0) @@ -2005,7 +2012,12 @@ change_options_program (gc_component_t component, gc_backend_t backend, src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ()); orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ()); +#if HAVE_W32_SYSTEM + res = 0; +#warning no backups for W32 yet - need to write a copy function +#else res = link (dest_filename, orig_filename); +#endif if (res < 0 && errno != ENOENT) return -1; if (res < 0) @@ -2418,12 +2430,18 @@ gc_component_change_options (int component, FILE *in) err = rename (src_pathname[i], dest_pathname[i]); else { +#ifdef HAVE_W32_SYSTEM + /* FIXME: Won't work becuase W32 doesn't silently + overwrite. */ + err = rename (src_pathname[i], dest_pathname[i]); +#else /*!HAVE_W32_SYSTEM*/ /* This is a bit safer than rename() because we expect DEST_PATHNAME not to be there. If it happens to be there, this will fail. */ err = link (src_pathname[i], dest_pathname[i]); if (!err) unlink (src_pathname[i]); +#endif /*!HAVE_W32_SYSTEM*/ } if (err) break; -- cgit v1.2.3 From 4350c587579b730065fd24ec593f00298ec7e534 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 15 Dec 2004 14:38:37 +0000 Subject: (lookup_status_cb): Send progress messages upstream. (isvalid_status_cb): Ditto. (gpgsm_dirmngr_isvalid): Put CTRL into status CB parameters. (gpgsm_dirmngr_run_command, run_command_status_cb): Pass CTRL to status callback and handle PROGRESS. --- sm/ChangeLog | 7 +++++++ sm/call-dirmngr.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 096c4ca8e..b33ed5409 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,12 @@ 2004-12-15 Werner Koch <wk@g10code.com> + * call-dirmngr.c (lookup_status_cb): Send progress messages + upstream. + (isvalid_status_cb): Ditto. + (gpgsm_dirmngr_isvalid): Put CTRL into status CB parameters. + (gpgsm_dirmngr_run_command, run_command_status_cb): Pass CTRL to + status callback and handle PROGRESS. + * misc.c (setup_pinentry_env) [W32]: Don't use it. * gpgsm.c (main) [W32]: Init Pth because we need it for the socket diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index c70f56580..44246daa6 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -57,6 +57,7 @@ struct inq_certificate_parm_s { }; struct isvalid_status_parm_s { + CTRL ctrl; int seen; unsigned char fpr[20]; }; @@ -348,7 +349,16 @@ isvalid_status_cb (void *opaque, const char *line) { struct isvalid_status_parm_s *parm = opaque; - if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24) + if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) + { + if (parm->ctrl) + { + for (line += 8; *line == ' '; line++) + ; + gpgsm_status (parm->ctrl, STATUS_PROGRESS, line); + } + } + else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24) && (line[24]==' ' || !line[24])) { parm->seen++; @@ -413,6 +423,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, parm.cert = cert; parm.issuer_cert = issuer_cert; + stparm.ctrl = ctrl; stparm.seen = 0; memset (stparm.fpr, 0, 20); @@ -608,7 +619,16 @@ lookup_status_cb (void *opaque, const char *line) { struct lookup_parm_s *parm = opaque; - if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) + if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) + { + if (parm->ctrl) + { + for (line += 8; *line == ' '; line++) + ; + gpgsm_status (parm->ctrl, STATUS_PROGRESS, line); + } + } + else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) { if (parm->ctrl) { @@ -728,10 +748,21 @@ run_command_inq_cb (void *opaque, const char *line) static AssuanError run_command_status_cb (void *opaque, const char *line) { + ctrl_t ctrl = opaque; + if (opt.verbose) { log_info ("dirmngr status: %s\n", line); } + if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8])) + { + if (ctrl) + { + for (line += 8; *line == ' '; line++) + ; + gpgsm_status (ctrl, STATUS_PROGRESS, line); + } + } return 0; } @@ -790,7 +821,7 @@ gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, rc = assuan_transact (dirmngr_ctx, line, run_command_cb, NULL, run_command_inq_cb, &parm, - run_command_status_cb, NULL); + run_command_status_cb, ctrl); xfree (line); log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay"); return map_assuan_err (rc); -- cgit v1.2.3 From 0ccb120f68954cead774b821b52fbd0d9d5eb65c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 17 Dec 2004 14:36:16 +0000 Subject: * call-dirmngr.c (isvalid_status_cb, lookup_status_cb) (run_command_status_cb): Return cancel status if gpgsm_status returned an error. * server.c (gpgsm_status, gpgsm_status2) (gpgsm_status_with_err_code): Return an error code. (gpgsm_status2): Always call va_end(). --- sm/ChangeLog | 10 ++++++++++ sm/call-dirmngr.c | 9 ++++++--- sm/gpgsm.h | 8 ++++---- sm/server.c | 23 +++++++++++++---------- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index b33ed5409..b28c45af8 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2004-12-17 Werner Koch <wk@g10code.com> + + * call-dirmngr.c (isvalid_status_cb, lookup_status_cb) + (run_command_status_cb): Return cancel status if gpgsm_status + returned an error. + + * server.c (gpgsm_status, gpgsm_status2) + (gpgsm_status_with_err_code): Return an error code. + (gpgsm_status2): Always call va_end(). + 2004-12-15 Werner Koch <wk@g10code.com> * call-dirmngr.c (lookup_status_cb): Send progress messages diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 44246daa6..d00a53db5 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -355,7 +355,8 @@ isvalid_status_cb (void *opaque, const char *line) { for (line += 8; *line == ' '; line++) ; - gpgsm_status (parm->ctrl, STATUS_PROGRESS, line); + if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line)) + return ASSUAN_Canceled; } } else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24) @@ -625,7 +626,8 @@ lookup_status_cb (void *opaque, const char *line) { for (line += 8; *line == ' '; line++) ; - gpgsm_status (parm->ctrl, STATUS_PROGRESS, line); + if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line)) + return ASSUAN_Canceled; } } else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) @@ -760,7 +762,8 @@ run_command_status_cb (void *opaque, const char *line) { for (line += 8; *line == ' '; line++) ; - gpgsm_status (ctrl, STATUS_PROGRESS, line); + if (gpgsm_status (ctrl, STATUS_PROGRESS, line)) + return ASSUAN_Canceled; } } return 0; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index faa6e8b5c..fe4e93910 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -171,10 +171,10 @@ void gpgsm_init_default_ctrl (struct server_control_s *ctrl); /*-- server.c --*/ void gpgsm_server (certlist_t default_recplist); -void gpgsm_status (ctrl_t ctrl, int no, const char *text); -void gpgsm_status2 (ctrl_t ctrl, int no, ...); -void gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text, - gpg_err_code_t ec); +gpg_error_t gpgsm_status (ctrl_t ctrl, int no, const char *text); +gpg_error_t gpgsm_status2 (ctrl_t ctrl, int no, ...); +gpg_error_t gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text, + gpg_err_code_t ec); /*-- fingerprint --*/ char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, diff --git a/sm/server.c b/sm/server.c index e39c78a8d..7bfd3fc20 100644 --- a/sm/server.c +++ b/sm/server.c @@ -964,18 +964,19 @@ get_status_string ( int no ) } -void +gpg_error_t gpgsm_status2 (CTRL ctrl, int no, ...) { + gpg_error_t err = 0; va_list arg_ptr; const char *text; va_start (arg_ptr, no); - if (ctrl->no_server) + if (ctrl->no_server && ctrl->status_fd == -1) + ; /* No status wanted. */ + else if (ctrl->no_server) { - if (ctrl->status_fd == -1) - return; /* no status wanted */ if (!statusfp) { if (ctrl->status_fd == 1) @@ -1030,19 +1031,21 @@ gpgsm_status2 (CTRL ctrl, int no, ...) *p++ = *text++; } *p = 0; - assuan_write_status (ctx, get_status_string (no), buf); + err = map_assuan_err (assuan_write_status (ctx, + get_status_string (no), buf)); } va_end (arg_ptr); + return err; } -void +gpg_error_t gpgsm_status (CTRL ctrl, int no, const char *text) { - gpgsm_status2 (ctrl, no, text, NULL); + return gpgsm_status2 (ctrl, no, text, NULL); } -void +gpg_error_t gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text, gpg_err_code_t ec) { @@ -1050,9 +1053,9 @@ gpgsm_status_with_err_code (CTRL ctrl, int no, const char *text, sprintf (buf, "%u", (unsigned int)ec); if (text) - gpgsm_status2 (ctrl, no, text, buf, NULL); + return gpgsm_status2 (ctrl, no, text, buf, NULL); else - gpgsm_status2 (ctrl, no, buf, NULL); + return gpgsm_status2 (ctrl, no, buf, NULL); } #if 0 -- cgit v1.2.3 From d75eda2b87af9bf605a92c11a20b8979129a4e44 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Fri, 17 Dec 2004 20:41:50 +0000 Subject: 2004-12-17 Moritz Schulte <moritz@g10code.com> * query.c: Undo change from 2004-12-05. --- agent/ChangeLog | 4 ++++ agent/query.c | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 3669b0e43..81c979414 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2004-12-17 Moritz Schulte <moritz@g10code.com> + + * query.c: Undo change from 2004-12-05. + 2004-12-15 Werner Koch <wk@g10code.com> * gpg-agent.c [W32]: Various hacks to make it work. diff --git a/agent/query.c b/agent/query.c index cdf6ff259..b514f6f5e 100644 --- a/agent/query.c +++ b/agent/query.c @@ -152,7 +152,7 @@ start_pinentry (CTRL ctrl) pgmname++; argv[0] = pgmname; - if (ctrl && ctrl->display && !opt.keep_display) + if (ctrl->display && !opt.keep_display) { argv[1] = "--display"; argv[2] = ctrl->display; @@ -189,7 +189,7 @@ start_pinentry (CTRL ctrl) NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return unlock_pinentry (map_assuan_err (rc)); - if (ctrl && ctrl->ttyname) + if (ctrl->ttyname) { char *optstr; if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 ) @@ -200,7 +200,7 @@ start_pinentry (CTRL ctrl) if (rc) return unlock_pinentry (map_assuan_err (rc)); } - if (ctrl && ctrl->ttytype) + if (ctrl->ttytype) { char *optstr; if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 ) @@ -210,7 +210,7 @@ start_pinentry (CTRL ctrl) if (rc) return unlock_pinentry (map_assuan_err (rc)); } - if (ctrl && ctrl->lc_ctype) + if (ctrl->lc_ctype) { char *optstr; if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 ) @@ -220,7 +220,7 @@ start_pinentry (CTRL ctrl) if (rc) return unlock_pinentry (map_assuan_err (rc)); } - if (ctrl && ctrl->lc_messages) + if (ctrl->lc_messages) { char *optstr; if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 ) -- cgit v1.2.3 From 3666a2859bd31115708b027cb69fa824c8111de4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 18 Dec 2004 10:22:10 +0000 Subject: Avoid the " map_to_assuan_status called with no error source" diagnostic. --- agent/ChangeLog | 5 +++++ agent/agent.h | 2 ++ common/ChangeLog | 7 +++++++ common/asshelp.c | 16 +++++++++------- common/asshelp.h | 1 + common/maperror.c | 4 ++-- common/util.h | 2 +- g10/ChangeLog | 9 +++++++++ g10/Makefile.am | 2 +- g10/call-agent.c | 2 ++ g10/gpg.h | 2 ++ kbx/ChangeLog | 5 +++++ kbx/keybox-defs.h | 4 +++- scd/ChangeLog | 5 +++++ scd/scdaemon.h | 3 +++ sm/ChangeLog | 7 +++++++ sm/call-agent.c | 2 +- sm/gpgsm.h | 3 +++ 18 files changed, 68 insertions(+), 13 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 81c979414..b22241bc9 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * agent.h (map_assuan_err): Define in terms of + map_assuan_err_with_source. + 2004-12-17 Moritz Schulte <moritz@g10code.com> * query.c: Undo change from 2004-12-05. diff --git a/agent/agent.h b/agent/agent.h index 8112c258a..7ff692504 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -26,6 +26,8 @@ #endif #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGAGENT #include <gpg-error.h> +#define map_assuan_err(a) \ + map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) #include <errno.h> #include <gcrypt.h> diff --git a/common/ChangeLog b/common/ChangeLog index 3115ad897..9b048ae49 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,10 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * maperror.c (map_assuan_err): Renamed to .. + (map_assuan_err_with_source): .. this and add arg SOURCE.c + * asshelp.c (send_pinentry_environment, send_one_option): Add arg + ERRSOURCE. + 2004-12-15 Werner Koch <wk@g10code.com> * sysutils.h [W32]: Prototypes for registry functions. diff --git a/common/asshelp.c b/common/asshelp.c index 243d6b9e7..efaf71e30 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -34,7 +34,8 @@ static gpg_error_t -send_one_option (assuan_context_t ctx, const char *name, const char *value) +send_one_option (assuan_context_t ctx, gpg_err_source_t errsource, + const char *name, const char *value) { gpg_error_t err; char *optstr; @@ -48,7 +49,7 @@ send_one_option (assuan_context_t ctx, const char *name, const char *value) assuan_error_t ae; ae = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - err = ae? map_assuan_err (ae) : 0; + err = ae? map_assuan_err_with_source (errsource, ae) : 0; free (optstr); } @@ -61,6 +62,7 @@ send_one_option (assuan_context_t ctx, const char *name, const char *value) defaults taken from the current locale. */ gpg_error_t send_pinentry_environment (assuan_context_t ctx, + gpg_err_source_t errsource, const char *opt_display, const char *opt_ttyname, const char *opt_ttytype, @@ -78,7 +80,7 @@ send_pinentry_environment (assuan_context_t ctx, dft_display = getenv ("DISPLAY"); if (opt_display || dft_display) { - err = send_one_option (ctx, "display", + err = send_one_option (ctx, errsource, "display", opt_display ? opt_display : dft_display); if (err) return err; @@ -93,7 +95,7 @@ send_pinentry_environment (assuan_context_t ctx, } if (opt_ttyname || dft_ttyname) { - err = send_one_option (ctx, "ttyname", + err = send_one_option (ctx, errsource, "ttyname", opt_ttyname ? opt_ttyname : dft_ttyname); if (err) return err; @@ -103,7 +105,7 @@ send_pinentry_environment (assuan_context_t ctx, dft_ttytype = getenv ("TERM"); if (opt_ttytype || (dft_ttyname && dft_ttytype)) { - err = send_one_option (ctx, "ttytype", + err = send_one_option (ctx, errsource, "ttytype", opt_ttyname ? opt_ttytype : dft_ttytype); if (err) return err; @@ -122,7 +124,7 @@ send_pinentry_environment (assuan_context_t ctx, #endif if (opt_lc_ctype || (dft_ttyname && dft_lc)) { - err = send_one_option (ctx, "lc-ctype", + err = send_one_option (ctx, errsource, "lc-ctype", opt_lc_ctype ? opt_lc_ctype : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) @@ -148,7 +150,7 @@ send_pinentry_environment (assuan_context_t ctx, #endif if (opt_lc_messages || (dft_ttyname && dft_lc)) { - err = send_one_option (ctx, "display", + err = send_one_option (ctx, errsource, "display", opt_lc_messages ? opt_lc_messages : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) diff --git a/common/asshelp.h b/common/asshelp.h index 993594882..2d6dc79e6 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -26,6 +26,7 @@ gpg_error_t send_pinentry_environment (assuan_context_t ctx, + gpg_err_source_t errsource, const char *opt_display, const char *opt_ttyname, const char *opt_ttytype, diff --git a/common/maperror.c b/common/maperror.c index 89ecee987..91731468f 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -38,7 +38,7 @@ 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) +map_assuan_err_with_source (int err, int source) { gpg_err_code_t ec; @@ -77,7 +77,7 @@ map_assuan_err (int err) ec = err < 100? GPG_ERR_ASSUAN_SERVER_FAULT : GPG_ERR_ASSUAN; break; } - return gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, ec); + return gpg_err_make (source, ec); } /* Map GPG_xERR_xx error codes to Assuan status codes */ diff --git a/common/util.h b/common/util.h index 0b9357d3a..835be4e0e 100644 --- a/common/util.h +++ b/common/util.h @@ -61,7 +61,7 @@ typedef char gnupg_isotime_t[16]; /*-- maperror.c --*/ int map_kbx_err (int err); -gpg_error_t map_assuan_err (int err); +gpg_error_t map_assuan_err_with_source (int source, int err); int map_to_assuan_status (int rc); /*-- gettime.c --*/ diff --git a/g10/ChangeLog b/g10/ChangeLog index 01bbf649d..6966bbd7b 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * gpg.h (map_assuan_err): Define in terms of + map_assuan_err_with_source. + +2004-12-15 Werner Koch <wk@g10code.com> + + * Makefile.am (LDADD): Remove ZLIBS. + 2004-10-22 Werner Koch <wk@g10code.com> * g10.c (main): Display a bit fat warning that this gpg should not diff --git a/g10/Makefile.am b/g10/Makefile.am index aa7833fb9..8e63e9335 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -108,7 +108,7 @@ gpgv2_SOURCES = gpgv.c \ # ks-db.h \ # $(common_source) -LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @ZLIBS@ @W32LIBS@ +LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @W32LIBS@ gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error diff --git a/g10/call-agent.c b/g10/call-agent.c index 473b38236..9c7f8409b 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -171,7 +171,9 @@ start_agent (void) if (rc) return map_assuan_err (rc); +#ifdef __GNUC__ #warning put this code into common/asshelp.c +#endif dft_display = getenv ("DISPLAY"); if (opt.display || dft_display) diff --git a/g10/gpg.h b/g10/gpg.h index bf61411f7..42c9cc662 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -29,6 +29,8 @@ #error GPG_ERR_SOURCE_DEFAULT already defined #endif #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPG +#define map_assuan_err(a) \ + map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) #include <gpg-error.h> diff --git a/kbx/ChangeLog b/kbx/ChangeLog index d75700216..3688174bd 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,8 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * keybox-defs.h (map_assuan_err): Define in terms of + map_assuan_err_with_source. + 2004-12-07 Werner Koch <wk@g10code.com> * keybox-init.c (keybox_release): Close the file pointer. diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 5724b85a0..b58294459 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -25,8 +25,10 @@ #error GPG_ERR_SOURCE_DEFAULT already defined #endif #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_KEYBOX - #include <gpg-error.h> +#define map_assuan_err(a) \ + map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) + #include <sys/types.h> /* off_t */ /* We include the type defintions from jnlib instead of defining our diff --git a/scd/ChangeLog b/scd/ChangeLog index fe3b3f6c4..87328f650 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * scdaemon.h (map_assuan_err): Define in terms of + map_assuan_err_with_source. + 2004-12-15 Werner Koch <wk@g10code.com> * scdaemon.c [W32]: Various hacks to make it run under W32. diff --git a/scd/scdaemon.h b/scd/scdaemon.h index c8d78c88b..c59879448 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -26,6 +26,9 @@ #endif #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_SCD #include <gpg-error.h> +#define map_assuan_err(a) \ + map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) + #include <errno.h> #include <time.h> diff --git a/sm/ChangeLog b/sm/ChangeLog index b28c45af8..167ec8753 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * gpgsm.h (map_assuan_err): Define in terms of + map_assuan_err_with_source. + * call-agent.c (start_agent): Pass error source to + send_pinentry_environment. + 2004-12-17 Werner Koch <wk@g10code.com> * call-dirmngr.c (isvalid_status_cb, lookup_status_cb) diff --git a/sm/call-agent.c b/sm/call-agent.c index 3ea1c4565..0d15a5595 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -168,7 +168,7 @@ start_agent (ctrl_t ctrl) if (rc) return map_assuan_err (rc); - return send_pinentry_environment (agent_ctx, + return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT, opt.display, opt.ttyname, opt.ttytype, opt.lc_ctype, opt.lc_messages); } diff --git a/sm/gpgsm.h b/sm/gpgsm.h index fe4e93910..17ad21ed6 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -26,6 +26,9 @@ #endif #define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GPGSM #include <gpg-error.h> +#define map_assuan_err(a) \ + map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) + #include <ksba.h> #include "../common/util.h" -- cgit v1.2.3 From 694037f2a58df62e94b6f4da86ad2af5d2e19109 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 18 Dec 2004 18:53:32 +0000 Subject: * configure.ac (AH_BOTTOM): Define EXEEXT_S. * autogen.sh: Updated --build-w32 feature. * gpg-agent.c (main): Remove special Pth initialize. * w32-pth.c (pth_init): Reverse return values. Use TRUE and FALSE constants. (pth_kill, pth_mutex_acquire, pth_attr_set, pth_join, pth_cancel): Ditto. * scdaemon.c (main) [W32]: Remove special Pth initialize.. --- ChangeLog | 6 +++ agent/ChangeLog | 2 + agent/gpg-agent.c | 6 --- autogen.sh | 98 ++++++++++++++++++++++++------------------------ common/exechelp.c | 2 +- configure.ac | 12 +++--- jnlib/ChangeLog | 7 ++++ jnlib/w32-pth.c | 110 +++++++++++++++++++++++++++++++++++------------------- scd/ChangeLog | 2 + scd/scdaemon.c | 6 --- sm/gpgsm.c | 1 + 11 files changed, 147 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index 95cf87d25..3db690f2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * configure.ac (AH_BOTTOM): Define EXEEXT_S. + + * autogen.sh: Updated --build-w32 feature. + 2004-12-15 Werner Koch <wk@g10code.com> * Makefile.am (SUBDIRS) [W32]: Do not build in tests/. diff --git a/agent/ChangeLog b/agent/ChangeLog index b22241bc9..52673e5b3 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,7 @@ 2004-12-18 Werner Koch <wk@g10code.com> + * gpg-agent.c (main): Remove special Pth initialize. + * agent.h (map_assuan_err): Define in terms of map_assuan_err_with_source. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 307d43d36..dfa457282 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -179,9 +179,7 @@ static void create_directories (void); static void handle_connections (int listen_fd); /* Pth wrapper function definitions. */ -#ifndef HAVE_W32_SYSTEM GCRY_THREAD_OPTION_PTH_IMPL; -#endif #endif /*USE_GNU_PTH*/ static void check_for_running_agent (void); @@ -439,16 +437,12 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ #ifdef USE_GNU_PTH -# ifdef HAVE_W32_SYSTEM - pth_init (); -# else /*!HAVE_W32_SYSTEM*/ err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -# endif/*!HAVE_W32_SYSTEM*/ #endif /*USE_GNU_PTH*/ /* Check that the libraries are suitable. Do it here because diff --git a/autogen.sh b/autogen.sh index a607d63da..87ddc6369 100755 --- a/autogen.sh +++ b/autogen.sh @@ -40,64 +40,66 @@ MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} DIE=no -if [ "$1" = "--build-w32" ]; then +# ***** W32 build script ******* +# Used to cross-compile for Windows. +if test "$1" = "--build-w32"; then + tmp=`dirname $0` + tsdir=`cd "$tmp"; pwd` shift - target=i386--mingw32 - if [ ! -f ./config.guess ]; then - echo "./config.guess not found" >&2 + if [ ! -f $tsdir/scripts/config.guess ]; then + echo "$tsdir/scripts/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 + build=`$tsdir/scripts/config.guess` + + [ -z "$w32root" ] && w32root="$HOME/w32root" + echo "Using $w32root as standard install directory" >&2 + + # See whether we have the Debian cross compiler package or the + # old mingw32/cpd system + if i586-mingw32msvc-gcc --version >/dev/null 2>&1 ; then + host=i586-mingw32msvc + crossbindir=/usr/$host/bin + else + host=i386--mingw32 + if ! mingw32 --version >/dev/null; then + echo "We need at least version 0.3 of MingW32/CPD" >&2 + exit 1 + fi + crossbindir=`mingw32 --install-dir`/bin + # Old autoconf version required us to setup the environment + # with the proper tool names. + 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 fi - - if [ -f config.h ]; then - if grep HAVE_DOSISH_SYSTEM config.h | grep undef >/dev/null; then + + if [ -f "$tsdir/config.log" ]; then + if ! head $tsdir/config.log | grep "$host" >/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 $? + ./configure --enable-maintainer-mode --prefix=${w32root} \ + --host=i586-mingw32msvc --build=${build} \ + --with-gpg-error-prefix=${w32root} \ + --with-ksba-prefix=${w32root} \ + --with-libgcrypt-prefix=${w32root} \ + --with-libassuan-prefix=${w32root} \ + --with-zlib=${w32root} \ + --with-pth-prefix=${w32root} + rc=$? + # Ugly hack to overcome a gettext problem. Someone should look into + # gettext to figure out why the po directory is not ignored as it used + # to be. + [ $rc = 0 ] && touch $tsdir/po/all + exit $rc fi +# ***** end W32 build script ******* + diff --git a/common/exechelp.c b/common/exechelp.c index 0a9cb824f..dc0a6b0e1 100644 --- a/common/exechelp.c +++ b/common/exechelp.c @@ -231,7 +231,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], cr_flags = (CREATE_DEFAULT_ERROR_MODE | GetPriorityClass (GetCurrentProcess ()) | CREATE_SUSPENDED); - log_debug ("CreateProcess, path=`%s' cmdline=`%s'", pgmname, cmdline); + log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); if (!CreateProcess (pgmname, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ diff --git a/configure.ac b/configure.ac index facbfe416..463358f28 100644 --- a/configure.ac +++ b/configure.ac @@ -255,11 +255,13 @@ AH_BOTTOM([ #define EXTSEP_C '.' #define DIRSEP_S "\\" #define EXTSEP_S "." +#define EXEEXT_S ".exe" #else #define DIRSEP_C '/' #define EXTSEP_C '.' #define DIRSEP_S "/" #define EXTSEP_S "." +#define EXEEXT_S "" #endif /* This is the same as VERSION, but should be overridden if the @@ -283,20 +285,20 @@ AH_BOTTOM([ /* Setup the hardwired names of modules. */ #ifndef GNUPG_DEFAULT_AGENT -#define GNUPG_DEFAULT_AGENT ( GNUPG_BINDIR DIRSEP_S "gpg-agent" ) +#define GNUPG_DEFAULT_AGENT ( GNUPG_BINDIR DIRSEP_S "gpg-agent" EXEEXT_S ) #endif #ifndef GNUPG_DEFAULT_PINENTRY -#define GNUPG_DEFAULT_PINENTRY ( GNUPG_BINDIR DIRSEP_S "pinentry" ) +#define GNUPG_DEFAULT_PINENTRY ( GNUPG_BINDIR DIRSEP_S "pinentry" EXEEXT_S ) #endif #ifndef GNUPG_DEFAULT_SCDAEMON -#define GNUPG_DEFAULT_SCDAEMON ( GNUPG_BINDIR DIRSEP_S "scdaemon" ) +#define GNUPG_DEFAULT_SCDAEMON ( GNUPG_BINDIR DIRSEP_S "scdaemon" EXEEXT_S ) #endif #ifndef GNUPG_DEFAULT_DIRMNGR -#define GNUPG_DEFAULT_DIRMNGR ( GNUPG_BINDIR DIRSEP_S "dirmngr" ) +#define GNUPG_DEFAULT_DIRMNGR ( GNUPG_BINDIR DIRSEP_S "dirmngr" EXEEXT_S ) #endif #ifndef GNUPG_DEFAULT_PROTECT_TOOL #define GNUPG_DEFAULT_PROTECT_TOOL \ - ( GNUPG_LIBEXECDIR DIRSEP_S "gpg-protect-tool" ) + ( GNUPG_LIBEXECDIR DIRSEP_S "gpg-protect-tool" EXEEXT_S ) #endif diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 71512715b..4a9665c45 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,10 @@ +2004-12-18 Werner Koch <wk@g10code.com> + + * w32-pth.c (pth_init): Reverse return values. Use TRUE and FALSE + constants. + (pth_kill, pth_mutex_acquire, pth_attr_set, pth_join, pth_cancel): + Ditto. + 2004-12-15 Werner Koch <wk@g10code.com> * logging.c [W32]: Don't include unavailable headers. diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index b47e8c9be..7710a622f 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -33,11 +33,24 @@ #include <io.h> #include <signal.h> +#include "logging.h" /* For log_get_prefix () */ + /* We don't want to have any Windows specific code in the header, thus we use a macro which defaults to a compatible type in w32-pth.h. */ #define W32_PTH_HANDLE_INTERNAL HANDLE #include "w32-pth.h" +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#if FALSE != 0 || TRUE != 1 +#error TRUE or FALSE defined to wrong values +#endif + + static int pth_initialized = 0; @@ -107,10 +120,12 @@ pth_init (void) SECURITY_ATTRIBUTES sa; WSADATA wsadat; - fprintf (stderr, "pth_init: called.\n"); - pth_initialized = 1; + if (pth_initialized) + return TRUE; + + fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); if (WSAStartup (0x202, &wsadat)) - abort (); + return FALSE; pth_signo = 0; InitializeCriticalSection (&pth_shd); if (pth_signo_ev) @@ -121,9 +136,11 @@ pth_init (void) sa.nLength = sizeof sa; pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL); if (!pth_signo_ev) - abort (); + return FALSE; + + pth_initialized = 1; EnterCriticalSection (&pth_shd); - return 0; + return TRUE; } @@ -140,7 +157,7 @@ pth_kill (void) DeleteCriticalSection (&pth_shd); WSACleanup (); pth_initialized = 0; - return 0; + return TRUE; } @@ -160,7 +177,8 @@ enter_pth (const char *function) { /* Fixme: I am not sure whether the same thread my enter a critical section twice. */ - fprintf (stderr, "enter_pth (%s)\n", function? function:""); +/* fprintf (stderr, "%s: enter_pth (%s)\n", + log_get_prefix (NULL), function? function:""); */ LeaveCriticalSection (&pth_shd); } @@ -169,7 +187,8 @@ static void leave_pth (const char *function) { EnterCriticalSection (&pth_shd); - fprintf (stderr, "leave_pth (%s)\n", function? function:""); +/* fprintf (stderr, "%s: leave_pth (%s)\n", + log_get_prefix (NULL), function? function:""); */ } @@ -234,7 +253,8 @@ pth_read (int fd, void * buffer, size_t size) { char strerr[256]; - fprintf (stderr, "pth_read(%d) failed read from file: %s\n", fd, + fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n", + log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); n = -1; } @@ -273,7 +293,8 @@ pth_write (int fd, const void * buffer, size_t size) n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); if (!n) { - fprintf (stderr, "pth_write(%d) failed in write: %s\n", fd, + fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", + log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); n = -1; } @@ -437,7 +458,7 @@ pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) if (!hd || !hd->mx) { leave_pth (__FUNCTION__); - return -1; + return FALSE; } #if 0 @@ -488,7 +509,7 @@ pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) hd->mx_state |= PTH_MUTEX_LOCKED; leave_pth (__FUNCTION__); - return 0; + return TRUE; } @@ -513,7 +534,7 @@ pth_mutex_init (pth_mutex_t *hd) hd->mx_state = PTH_MUTEX_INITIALIZED; leave_pth (__FUNCTION__); - return 0; + return TRUE; } @@ -537,7 +558,7 @@ pth_attr_destroy (pth_attr_t hd) if (hd->name) free (hd->name); free (hd); - return 0; + return TRUE; } @@ -547,7 +568,7 @@ pth_attr_set (pth_attr_t hd, int field, ...) va_list args; char * str; int val; - int rc = 0; + int rc = TRUE; implicit_init (); @@ -559,7 +580,8 @@ pth_attr_set (pth_attr_t hd, int field, ...) if (val) { hd->flags |= PTH_ATTR_JOINABLE; - fprintf (stderr, "pth_attr_set: PTH_ATTR_JOINABLE\n"); + fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", + log_get_prefix (NULL)); } break; @@ -569,7 +591,8 @@ pth_attr_set (pth_attr_t hd, int field, ...) { hd->flags |= PTH_ATTR_STACK_SIZE; hd->stack_size = val; - fprintf (stderr, "pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", val); + fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", + log_get_prefix (NULL), val); } break; @@ -581,14 +604,15 @@ pth_attr_set (pth_attr_t hd, int field, ...) { hd->name = strdup (str); if (!hd->name) - return -1; + return FALSE; hd->flags |= PTH_ATTR_NAME; - fprintf (stderr, "pth_attr_set: PTH_ATTR_NAME %s\n", hd->name); + fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", + log_get_prefix (NULL), hd->name); } break; default: - rc = -1; + rc = FALSE; break; } va_end (args); @@ -627,12 +651,14 @@ do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) FIXME: We should no use th W32's Thread handle directly but keep our own thread control structure. CTX may be used for that. */ - fprintf (stderr, "do_pth_spawn creating thread ...\n"); + fprintf (stderr, "%s: do_pth_spawn creating thread ...\n", + log_get_prefix (NULL)); th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)launch_thread, ctx, CREATE_SUSPENDED, &tid); ctx->th = th; - fprintf (stderr, "do_pth_spawn created thread %p\n", th); + fprintf (stderr, "%s: do_pth_spawn created thread %p\n", + log_get_prefix (NULL),th); if (!th) free (ctx); else @@ -660,7 +686,7 @@ pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) int pth_join (pth_t hd, void **value) { - return 0; + return TRUE; } @@ -675,7 +701,7 @@ pth_cancel (pth_t hd) WaitForSingleObject (hd, 1000); TerminateThread (hd, 0); leave_pth (__FUNCTION__); - return 0; + return TRUE; } @@ -689,7 +715,7 @@ pth_abort (pth_t hd) enter_pth (__FUNCTION__); TerminateThread (hd, 0); leave_pth (__FUNCTION__); - return 0; + return TRUE; } @@ -759,7 +785,7 @@ sig_handler (DWORD signo) case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; } SetEvent (pth_signo_ev); - fprintf (stderr, "sig_handler=%d\n", pth_signo); + fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); return TRUE; } @@ -771,7 +797,7 @@ do_pth_event_body (unsigned long spec, va_list arg) pth_event_t ev; int rc; - fprintf (stderr, "pth_event spec=%lu\n", spec); + fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec); ev = calloc (1, sizeof *ev); if (!ev) return NULL; @@ -783,7 +809,8 @@ do_pth_event_body (unsigned long spec, va_list arg) ev->u_type = PTH_EVENT_SIGS; ev->val = va_arg (arg, int *); rc = SetConsoleCtrlHandler (sig_handler, TRUE); - fprintf (stderr, "pth_event: sigs rc=%d\n", rc); + fprintf (stderr, "%s: pth_event: sigs rc=%d\n", + log_get_prefix (NULL), rc); } else if (spec & PTH_EVENT_FD) { @@ -794,7 +821,8 @@ do_pth_event_body (unsigned long spec, va_list arg) ev->u_type = PTH_EVENT_FD; va_arg (arg, pth_key_t); ev->u.fd = va_arg (arg, int); - fprintf (stderr, "pth_event: fd=%d\n", ev->u.fd); + fprintf (stderr, "%s: pth_event: fd=%d\n", + log_get_prefix (NULL), ev->u.fd); } else if (spec & PTH_EVENT_TIME) { @@ -908,7 +936,8 @@ wait_for_fd (int fd, int is_read, int nwait) while (1) { n = select (fd+1, &r, &w, NULL, &tv); - fprintf (stderr, "wait_for_fd=%d fd %d (ec=%d)\n", n, fd,(int)WSAGetLastError ()); + fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n", + log_get_prefix (NULL), n, fd,(int)WSAGetLastError ()); if (n == -1) break; if (!n) @@ -1005,7 +1034,8 @@ do_pth_event_occurred (pth_event_t ev) if (sigpresent (ev->u.sig, pth_signo) && WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) { - fprintf (stderr, "pth_event_occurred: sig signaled.\n"); + fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n", + log_get_prefix (NULL)); (*ev->val) = pth_signo; ret = 1; } @@ -1080,7 +1110,7 @@ do_pth_event_free (pth_event_t ev, int mode) free (ev); } - return 0; + return TRUE; } int @@ -1134,11 +1164,13 @@ spawn_helper_thread (void *(*func)(void *), void *arg) sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof sa; - fprintf (stderr, "spawn_helper_thread creating thread ...\n"); + fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n", + log_get_prefix (NULL)); th = CreateThread (&sa, 32*1024, (LPTHREAD_START_ROUTINE)func, arg, 0, &tid); - fprintf (stderr, "spawn_helper_thread created thread %p\n", th); + fprintf (stderr, "%s: spawn_helper_thread created thread %p\n", + log_get_prefix (NULL), th); return th; } @@ -1163,7 +1195,7 @@ wait_fd_thread (void * ctx) pth_event_t ev = ctx; wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - fprintf (stderr, "wait_fd_thread: exit.\n"); + fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); SetEvent (ev->hd); ExitThread (0); return NULL; @@ -1177,7 +1209,7 @@ wait_timer_thread (void * ctx) int n = ev->u.tv.tv_sec*1000; Sleep (n); SetEvent (ev->hd); - fprintf (stderr, "wait_timer_thread: exit.\n"); + fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL)); ExitThread (0); return NULL; } @@ -1199,7 +1231,7 @@ do_pth_wait (pth_event_t ev) if (n > MAXIMUM_WAIT_OBJECTS/2) return -1; - fprintf (stderr, "pth_wait: cnt %lu\n", n); + fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); for (tmp = ev; tmp; tmp = tmp->next) { switch (tmp->u_type) @@ -1233,10 +1265,10 @@ do_pth_wait (pth_event_t ev) break; } } - fprintf (stderr, "pth_wait: set %d\n", pos); + fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos); n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); free_helper_threads (waitbuf, hdidx, i); - fprintf (stderr, "pth_wait: n %ld\n", n); + fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n); if (n != WAIT_TIMEOUT) return 1; diff --git a/scd/ChangeLog b/scd/ChangeLog index 87328f650..68421fc86 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,7 @@ 2004-12-18 Werner Koch <wk@g10code.com> + * scdaemon.c (main) [W32]: Remove special Pth initialize.. + * scdaemon.h (map_assuan_err): Define in terms of map_assuan_err_with_source. diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 135f0973a..901644edc 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -158,10 +158,8 @@ static char socket_name[128]; #ifndef HAVE_OPENSC #ifdef USE_GNU_PTH -#ifndef HAVE_W32_SYSTEM /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; -#endif static void *ticker_thread (void *arg); #endif /*USE_GNU_PTH*/ @@ -353,16 +351,12 @@ main (int argc, char **argv ) Note that this will also do the pth_init. */ #ifndef HAVE_OPENSC #ifdef USE_GNU_PTH -# ifdef HAVE_W32_SYSTEM - pth_init (); -# else /*!HAVE_W32_SYSTEM*/ err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -# endif /*!HAVE_W32_SYSTEM*/ #endif /*USE_GNU_PTH*/ #endif /*!HAVE_OPENSC*/ diff --git a/sm/gpgsm.c b/sm/gpgsm.c index f79375da7..709263cba 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -740,6 +740,7 @@ main ( int argc, char **argv) } #ifdef HAVE_W32_SYSTEM + /* For W32 we need pth. */ pth_init (); #endif -- cgit v1.2.3 From e73100a940f7115e4be9f34dca160f622d869005 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 19 Dec 2004 13:38:24 +0000 Subject: * maperror.c (map_assuan_err_with_source): Oops, args were swapped. * w32-pth.c (pth_init): Enable debugging depending on env var. --- agent/gpg-agent.c | 6 ++++++ common/ChangeLog | 4 ++++ common/maperror.c | 2 +- jnlib/ChangeLog | 4 ++++ jnlib/w32-pth.c | 26 +++++++++++++++++++------- sm/keylist.c | 4 ++-- 6 files changed, 36 insertions(+), 10 deletions(-) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index dfa457282..ed12fed4f 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -437,14 +437,20 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ #ifdef USE_GNU_PTH +#ifdef HAVE_W32_SYSTEM + /* For W32 we need pth. */ + pth_init (); +#else err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } +#endif #endif /*USE_GNU_PTH*/ + /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library. */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) diff --git a/common/ChangeLog b/common/ChangeLog index 9b048ae49..336b3928a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-12-19 Werner Koch <wk@g10code.com> + + * maperror.c (map_assuan_err_with_source): Oops, args were swapped. + 2004-12-18 Werner Koch <wk@g10code.com> * maperror.c (map_assuan_err): Renamed to .. diff --git a/common/maperror.c b/common/maperror.c index 91731468f..9efd64338 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -38,7 +38,7 @@ 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_with_source (int err, int source) +map_assuan_err_with_source (int source, int err) { gpg_err_code_t ec; diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 4a9665c45..e194cea4c 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,7 @@ +2004-12-19 Werner Koch <wk@g10code.com> + + * w32-pth.c (pth_init): Enable debugging depending on env var. + 2004-12-18 Werner Koch <wk@g10code.com> * w32-pth.c (pth_init): Reverse return values. Use TRUE and FALSE diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 7710a622f..489b28300 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -40,6 +40,9 @@ #define W32_PTH_HANDLE_INTERNAL HANDLE #include "w32-pth.h" +#define DEBUG_ENTER_LEAVE 1 /* Set to 1 to enable full debugging. */ + + #ifndef FALSE #define FALSE 0 #endif @@ -51,12 +54,15 @@ #endif +/* States whether trhis module has been initialized. */ +static int pth_initialized; -static int pth_initialized = 0; +/* Controls whether debugging is enabled. */ +static int debug_enter_leave; /* Variables to support event handling. */ -static int pth_signo = 0; -static HANDLE pth_signo_ev = NULL; +static int pth_signo; +static HANDLE pth_signo_ev; /* Mutex to make sure only one thread is running. */ static CRITICAL_SECTION pth_shd; @@ -124,6 +130,8 @@ pth_init (void) return TRUE; fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); + debug_enter_leave = !!getenv ("DEBUG_PTH"); + if (WSAStartup (0x202, &wsadat)) return FALSE; pth_signo = 0; @@ -177,8 +185,9 @@ enter_pth (const char *function) { /* Fixme: I am not sure whether the same thread my enter a critical section twice. */ -/* fprintf (stderr, "%s: enter_pth (%s)\n", - log_get_prefix (NULL), function? function:""); */ + if (debug_enter_leave) + fprintf (stderr, "%s: enter_pth (%s)\n", + log_get_prefix (NULL), function? function:""); LeaveCriticalSection (&pth_shd); } @@ -187,8 +196,9 @@ static void leave_pth (const char *function) { EnterCriticalSection (&pth_shd); -/* fprintf (stderr, "%s: leave_pth (%s)\n", - log_get_prefix (NULL), function? function:""); */ + if (debug_enter_leave) + fprintf (stderr, "%s: leave_pth (%s)\n", + log_get_prefix (NULL), function? function:""); } @@ -296,6 +306,8 @@ pth_write (int fd, const void * buffer, size_t size) fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); + fprintf (stderr, "--> fd = %d, handle = %p, size = %lu\n", + fd, (HANDLE)fd, size); n = -1; } else diff --git a/sm/keylist.c b/sm/keylist.c index e9985f3ec..aa6db46c3 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1149,8 +1149,8 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp, char *p = gpgsm_get_keygrip_hexstring (cert); if (p) { - rc = gpgsm_agent_havekey (ctrl, p); - if (!rc) + rc = gpgsm_agent_havekey (ctrl, p); + if (!rc) have_secret = 1; else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY) goto leave; -- cgit v1.2.3 From 8f22f895e94d45755c99470eb76fd9fd508b5b5f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 19 Dec 2004 17:44:20 +0000 Subject: * query.c (initialize_module_query): * call-scd.c (initialize_module_call_scd): New. * w32-pth.c (pth_init): Enable debugging depending on env var. (pth_self): New. (pth_mutex_release, pth_mutex_acquire): Implemented directly using the W32 API. --- agent/ChangeLog | 6 +++ agent/agent.h | 2 + agent/call-scd.c | 21 ++++++++- agent/gpg-agent.c | 4 ++ agent/query.c | 21 ++++++++- jnlib/ChangeLog | 3 ++ jnlib/w32-pth.c | 131 ++++++++++++++++++++++++------------------------------ jnlib/w32-pth.h | 12 +++-- scd/scdaemon.c | 5 +++ 9 files changed, 123 insertions(+), 82 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 52673e5b3..d3c4af337 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2004-12-19 Werner Koch <wk@g10code.com> + + * query.c (initialize_module_query): + + * call-scd.c (initialize_module_call_scd): New. + 2004-12-18 Werner Koch <wk@g10code.com> * gpg-agent.c (main): Remove special Pth initialize. diff --git a/agent/agent.h b/agent/agent.h index 7ff692504..e6c8e2a35 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -145,6 +145,7 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl, int agent_key_available (const unsigned char *grip); /*-- query.c --*/ +void initialize_module_query (void); int agent_askpin (ctrl_t ctrl, const char *desc_text, const char *inital_errtext, struct pin_entry_info_s *pininfo); @@ -212,6 +213,7 @@ int divert_generic_cmd (ctrl_t ctrl, /*-- call-scd.c --*/ +void initialize_module_call_scd (void); int agent_reset_scd (ctrl_t ctrl); int agent_card_learn (ctrl_t ctrl, void (*kpinfo_cb)(void*, const char *), diff --git a/agent/call-scd.c b/agent/call-scd.c index 828040772..90c625f8b 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -52,7 +52,7 @@ static ASSUAN_CONTEXT scd_ctx = NULL; #ifdef USE_GNU_PTH -static pth_mutex_t scd_lock = PTH_MUTEX_INIT; +static pth_mutex_t scd_lock; #endif /* We need to keep track of the connection currently using the SCD. For a pipe server this is all a NOP because the connection will @@ -153,6 +153,23 @@ get_membuf (struct membuf *mb, size_t *len) +/* This function must be called once to initialize this module. This + has to be done before a second thread is spawned. We can't do the + static initialization because Pth emulation code might not be able + to do a static init; in particualr, it is not possible for W32. */ +void +initialize_module_call_scd (void) +{ +#ifdef USE_GNU_PTH + static int initialized; + + if (!initialized) + if (pth_mutex_init (&scd_lock)) + initialized = 1; +#endif /*USE_GNU_PTH*/ +} + + static int unlock_scd (int rc) { @@ -163,7 +180,7 @@ unlock_scd (int rc) if (!rc) rc = gpg_error (GPG_ERR_INTERNAL); } -#endif +#endif /*USE_GNU_PTH*/ return rc; } diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ed12fed4f..65d5fd5a6 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -627,6 +627,10 @@ main (int argc, char **argv ) exit (1); } + initialize_module_query (); + initialize_module_call_scd (); + + /* Try to create missing directories. */ create_directories (); if (debug_wait && pipe_server) diff --git a/agent/query.c b/agent/query.c index b514f6f5e..4aafcbe99 100644 --- a/agent/query.c +++ b/agent/query.c @@ -51,7 +51,7 @@ static ASSUAN_CONTEXT entry_ctx = NULL; #ifdef USE_GNU_PTH -static pth_mutex_t entry_lock = PTH_MUTEX_INIT; +static pth_mutex_t entry_lock; #endif /* data to be passed to our callbacks */ @@ -64,6 +64,25 @@ struct entry_parm_s { +/* This function must be called once to initialize this module. This + has to be done before a second thread is spawned. We can't do the + static initialization because Pth emulation code might not be able + to do a static init; in particualr, it is not possible for W32. */ +void +initialize_module_query (void) +{ +#ifdef USE_GNU_PTH + static int initialized; + + if (!initialized) + if (pth_mutex_init (&entry_lock)) + initialized = 1; +#endif /*USE_GNU_PTH*/ +} + + + + /* Unlock the pinentry so that another thread can start one and disconnect that pinentry - we do this after the unlock so that a stalled pinentry does not block other threads. Fixme: We should diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index e194cea4c..5a566aedb 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,6 +1,9 @@ 2004-12-19 Werner Koch <wk@g10code.com> * w32-pth.c (pth_init): Enable debugging depending on env var. + (pth_self): New. + (pth_mutex_release, pth_mutex_acquire): Implemented directly using + the W32 API. 2004-12-18 Werner Koch <wk@g10code.com> diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 489b28300..609a03705 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -68,7 +68,6 @@ static HANDLE pth_signo_ev; static CRITICAL_SECTION pth_shd; - struct pth_event_s { struct pth_event_s * next; @@ -306,8 +305,6 @@ pth_write (int fd, const void * buffer, size_t size) fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", log_get_prefix (NULL), fd, w32_strerror (strerr, sizeof strerr)); - fprintf (stderr, "--> fd = %d, handle = %p, size = %lu\n", - fd, (HANDLE)fd, size); n = -1; } else @@ -444,107 +441,94 @@ pth_connect (int fd, struct sockaddr *name, int namelen) int -pth_mutex_release (pth_mutex_t *hd) +pth_mutex_release (pth_mutex_t *mutex) { - if (!hd) - return -1; + int rc; + implicit_init (); enter_pth (__FUNCTION__); - if (hd->mx) + + if (!ReleaseMutex (*mutex)) { - CloseHandle (hd->mx); - hd->mx = NULL; + char strerr[256]; + + fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n", + log_get_prefix (NULL), *mutex, + w32_strerror (strerr, sizeof strerr)); + rc = FALSE; } - free (hd); + else + rc = TRUE; + leave_pth (__FUNCTION__); - return 0; + return rc; } int -pth_mutex_acquire (pth_mutex_t *hd, int tryonly, pth_event_t ev_extra) +pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra) { + int code; + int rc; + implicit_init (); enter_pth (__FUNCTION__); - if (!hd || !hd->mx) - { - leave_pth (__FUNCTION__); - return FALSE; - } - -#if 0 - /* still not locked, so simply acquire mutex? */ - if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) - { - mutex->mx_state |= PTH_MUTEX_LOCKED; - mutex->mx_count = 1; - pth_ring_append(&(pth_current->mutexring), &(mutex->mx_node)); - pth_debug1("pth_mutex_acquire: immediately locking mutex"); - return 0; - } - - /* already locked by caller? */ - if (mutex->mx_count >= 1 && mutex->mx_owner == pth_current) - { - /* recursive lock */ - mutex->mx_count++; - pth_debug1("pth_mutex_acquire: recursive locking"); - return 0; - } - - if (tryonly) - { - leave_pth (__FUNCTION__); - return -1; - } - - for (;;) + /* FIXME: ev_extra is not yet supported. */ + + code = WaitForSingleObject (*mutex, INFINITE); + switch (code) { - ev = pth_event(PTH_EVENT_MUTEX|PTH_MODE_STATIC, &ev_key, mutex); - if (ev_extra != NULL) - pth_event_concat (ev, ev_extra, NULL); - pth_wait (ev); - if (ev_extra != NULL) + case WAIT_FAILED: { - pth_event_isolate (ev); - if (do_pth_event_status(ev) == PTH_STATUS_PENDING) - { - leave_pth (__FUNCTION__); - return -1; - } + char strerr[256]; + + fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n", + log_get_prefix (NULL), *mutex, + w32_strerror (strerr, sizeof strerr)); } - if (!(mutex->mx_state & PTH_MUTEX_LOCKED)) + rc = FALSE; + break; + + case WAIT_OBJECT_0: + rc = TRUE; + break; + + default: + fprintf (stderr, "%s: WaitForSingleObject returned unexpected " + "code %d for mutex %p\n", + log_get_prefix (NULL), code, *mutex); + rc = FALSE; break; } -#endif - hd->mx_state |= PTH_MUTEX_LOCKED; leave_pth (__FUNCTION__); - return TRUE; + return rc; } + int -pth_mutex_init (pth_mutex_t *hd) +pth_mutex_init (pth_mutex_t *mutex) { SECURITY_ATTRIBUTES sa; implicit_init (); enter_pth (__FUNCTION__); - if (hd->mx) - { - ReleaseMutex (hd->mx); - CloseHandle (hd->mx); - } memset (&sa, 0, sizeof sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof sa; - hd->mx = CreateMutex (&sa, FALSE, NULL); - hd->mx_state = PTH_MUTEX_INITIALIZED; - + *mutex = CreateMutex (&sa, FALSE, NULL); + if (!*mutex) + { + free (*mutex); + *mutex = NULL; + leave_pth (__FUNCTION__); + return FALSE; + } + leave_pth (__FUNCTION__); return TRUE; } @@ -695,6 +679,12 @@ pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) } +pth_t +pth_self (void) +{ + return GetCurrentThread (); +} + int pth_join (pth_t hd, void **value) { @@ -1271,9 +1261,6 @@ do_pth_wait (pth_event_t ev) case PTH_EVENT_MUTEX: fprintf (stderr, "pth_wait: add mutex event.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = tmp->u.mx->mx; - /* XXX: Use SetEvent(hd->ev) */ break; } } diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h index bcd82659c..5ef0ab240 100644 --- a/jnlib/w32-pth.h +++ b/jnlib/w32-pth.h @@ -53,7 +53,9 @@ enum /* Mutex values. */ #define PTH_MUTEX_INITIALIZED (1<<0) #define PTH_MUTEX_LOCKED (1<<1) -#define PTH_MUTEX_INIT {PTH_MUTEX_INITIALIZED} + +/* Note: We can't do static initialization, thus we don't define the + initializer PTH_MUTEX_INIT. */ #define PTH_KEY_INIT (1<<0) @@ -158,12 +160,7 @@ typedef void *pth_t; /* The Mutex object. */ -struct pth_mutex_s -{ - unsigned mx_state; - W32_PTH_HANDLE_INTERNAL mx; -}; -typedef struct pth_mutex_s pth_mutex_t; +typedef W32_PTH_HANDLE_INTERNAL pth_mutex_t; /* The Event object. */ @@ -214,6 +211,7 @@ int pth_attr_destroy (pth_attr_t hd); int pth_attr_set (pth_attr_t hd, int field, ...); pth_t pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg); +pth_t pth_self (void); int pth_join (pth_t hd, void **value); int pth_abort (pth_t hd); void pth_exit (void *value); diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 901644edc..49e392e7d 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -351,12 +351,17 @@ main (int argc, char **argv ) Note that this will also do the pth_init. */ #ifndef HAVE_OPENSC #ifdef USE_GNU_PTH +#ifdef HAVE_W32_SYSTEM + /* For W32 we need pth. */ + pth_init (); +#else err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } +#endif #endif /*USE_GNU_PTH*/ #endif /*!HAVE_OPENSC*/ -- cgit v1.2.3 From e212805a9cf833cac6c8cdabc2db5421adcebd47 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 19 Dec 2004 17:45:50 +0000 Subject: * query.c (initialize_module_query): New. * call-scd.c (initialize_module_call_scd): New. * gpg-agent.c (main): Call them. --- agent/ChangeLog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index d3c4af337..1c56529b8 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,9 +1,9 @@ 2004-12-19 Werner Koch <wk@g10code.com> - * query.c (initialize_module_query): - + * query.c (initialize_module_query): New. * call-scd.c (initialize_module_call_scd): New. - + * gpg-agent.c (main): Call them. + 2004-12-18 Werner Koch <wk@g10code.com> * gpg-agent.c (main): Remove special Pth initialize. -- cgit v1.2.3 From 18fd4964f66ab297a5540f38f5dd6fb22b8e4572 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 20 Dec 2004 08:32:56 +0000 Subject: * call-scd.c (init_membuf, put_membuf, get_membuf): Removed. We now use the identical implementation from ../common/membuf.c. * pksign.c (agent_pksign): Changed arg OUTFP to OUTBUF and use membuf functions to return the value. * pkdecrypt.c (agent_pkdecrypt): Ditto. * genkey.c (agent_genkey): Ditto. * command.c (cmd_pksign, cmd_pkdecrypt, cmd_genkey): Replaced assuan_get_data_fp() by a the membuf scheme. (clear_outbuf, write_and_clear_outbuf): New. * membuf.c (put_membuf): Wipe out buffer after a failed realloc. --- agent/ChangeLog | 13 +++++++++ agent/agent.h | 7 ++--- agent/call-scd.c | 79 ++++--------------------------------------------------- agent/command.c | 64 +++++++++++++++++++++++++++++++++++++++++--- agent/genkey.c | 18 +++++-------- agent/pkdecrypt.c | 22 +++++++++------- agent/pksign.c | 8 +++--- common/ChangeLog | 4 +++ common/membuf.c | 5 ++++ 9 files changed, 112 insertions(+), 108 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 1c56529b8..f2b82466c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,16 @@ +2004-12-20 Werner Koch <wk@g10code.com> + + * call-scd.c (init_membuf, put_membuf, get_membuf): Removed. We + now use the identical implementation from ../common/membuf.c. + + * pksign.c (agent_pksign): Changed arg OUTFP to OUTBUF and use + membuf functions to return the value. + * pkdecrypt.c (agent_pkdecrypt): Ditto. + * genkey.c (agent_genkey): Ditto. + * command.c (cmd_pksign, cmd_pkdecrypt, cmd_genkey): Replaced + assuan_get_data_fp() by a the membuf scheme. + (clear_outbuf, write_and_clear_outbuf): New. + 2004-12-19 Werner Koch <wk@g10code.com> * query.c (initialize_module_query): New. diff --git a/agent/agent.h b/agent/agent.h index e6c8e2a35..241b37b05 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -33,6 +33,7 @@ #include <gcrypt.h> #include "../common/util.h" #include "../common/errors.h" +#include "membuf.h" /* Convenience function to be used instead of returning the old GNUPG_Out_Of_Core. */ @@ -166,16 +167,16 @@ void agent_unlock_cache_entry (void **cache_id); int agent_pksign_do (CTRL ctrl, const char *desc_text, gcry_sexp_t *signature_sexp, int ignore_cache); int agent_pksign (ctrl_t ctrl, const char *desc_text, - FILE *outfp, int ignore_cache); + membuf_t *outbuf, int ignore_cache); /*-- pkdecrypt.c --*/ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, const unsigned char *ciphertext, size_t ciphertextlen, - FILE *outfp); + membuf_t *outbuf); /*-- genkey.c --*/ int agent_genkey (ctrl_t ctrl, - const char *keyparam, size_t keyparmlen, FILE *outfp); + const char *keyparam, size_t keyparmlen, membuf_t *outbuf); int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey); /*-- protect.c --*/ diff --git a/agent/call-scd.c b/agent/call-scd.c index 90c625f8b..619a549f9 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -82,75 +82,6 @@ struct inq_needpin_s { void *getpin_cb_arg; }; -struct membuf { - size_t len; - size_t size; - char *buf; - int out_of_core; -}; - - - -/* 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. */ - -static void -init_membuf (struct membuf *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 = 1; -} - -static void -put_membuf (struct membuf *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 = 1; - return; - } - mb->buf = p; - } - memcpy (mb->buf + mb->len, buf, len); - mb->len += len; -} - -static void * -get_membuf (struct membuf *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 = 1; /* don't allow a reuse */ - return p; -} - - /* This function must be called once to initialize this module. This @@ -468,7 +399,7 @@ agent_card_serialno (ctrl_t ctrl, char **r_serialno) static AssuanError membuf_data_cb (void *opaque, const void *buffer, size_t length) { - struct membuf *data = opaque; + membuf_t *data = opaque; if (buffer) put_membuf (data, buffer, length); @@ -519,7 +450,7 @@ agent_card_pksign (ctrl_t ctrl, { int rc, i; char *p, line[ASSUAN_LINELENGTH]; - struct membuf data; + membuf_t data; struct inq_needpin_s inqparm; size_t len; unsigned char *sigbuf; @@ -591,7 +522,7 @@ agent_card_pkdecrypt (ctrl_t ctrl, { int rc, i; char *p, line[ASSUAN_LINELENGTH]; - struct membuf data; + membuf_t data; struct inq_needpin_s inqparm; size_t len; @@ -643,7 +574,7 @@ agent_card_readcert (ctrl_t ctrl, { int rc; char line[ASSUAN_LINELENGTH]; - struct membuf data; + membuf_t data; size_t len; *r_buf = NULL; @@ -679,7 +610,7 @@ agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf) { int rc; char line[ASSUAN_LINELENGTH]; - struct membuf data; + membuf_t data; size_t len, buflen; *r_buf = NULL; diff --git a/agent/command.c b/agent/command.c index 02bbf3429..9fc08e211 100644 --- a/agent/command.c +++ b/agent/command.c @@ -50,7 +50,7 @@ struct server_local_s { ASSUAN_CONTEXT assuan_ctx; int message_fd; int use_cache_for_signing; - char *keydesc; /* Allocated description fro the next key + char *keydesc; /* Allocated description for the next key operation. */ }; @@ -58,6 +58,41 @@ struct server_local_s { +/* Release the memory buffer MB but first wipe out the used memory. */ +static void +clear_outbuf (membuf_t *mb) +{ + void *p; + size_t n; + + p = get_membuf (mb, &n); + if (p) + { + memset (p, 0, n); + xfree (p); + } +} + + +/* Write the content of memory buffer MB as assuan data to CTX and + wipe the buffer out afterwards. */ +static gpg_error_t +write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb) +{ + assuan_error_t ae; + void *p; + size_t n; + + p = get_membuf (mb, &n); + if (!p) + return gpg_error (GPG_ERR_ENOMEM); + ae = assuan_send_data (ctx, p, n); + memset (p, 0, n); + xfree (p); + return map_assuan_err (ae); +} + + static void reset_notify (ASSUAN_CONTEXT ctx) { @@ -369,14 +404,21 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) int rc; int ignore_cache = 0; ctrl_t ctrl = assuan_get_pointer (ctx); + membuf_t outbuf; if (opt.ignore_cache_for_signing) ignore_cache = 1; else if (!ctrl->server_local->use_cache_for_signing) ignore_cache = 1; + init_membuf (&outbuf, 512); + rc = agent_pksign (ctrl, ctrl->server_local->keydesc, - assuan_get_data_fp (ctx), ignore_cache); + &outbuf, ignore_cache); + if (rc) + clear_outbuf (&outbuf); + else + rc = write_and_clear_outbuf (ctx, &outbuf); if (rc) log_error ("command pksign failed: %s\n", gpg_strerror (rc)); xfree (ctrl->server_local->keydesc); @@ -395,6 +437,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) ctrl_t ctrl = assuan_get_pointer (ctx); unsigned char *value; size_t valuelen; + membuf_t outbuf; /* First inquire the data to decrypt */ rc = assuan_inquire (ctx, "CIPHERTEXT", @@ -402,9 +445,15 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) if (rc) return rc; + init_membuf (&outbuf, 512); + rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc, - value, valuelen, assuan_get_data_fp (ctx)); + value, valuelen, &outbuf); xfree (value); + if (rc) + clear_outbuf (&outbuf); + else + rc = write_and_clear_outbuf (ctx, &outbuf); if (rc) log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc)); xfree (ctrl->server_local->keydesc); @@ -434,14 +483,21 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) int rc; unsigned char *value; size_t valuelen; + membuf_t outbuf; /* First inquire the parameters */ rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM); if (rc) return rc; - rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx)); + init_membuf (&outbuf, 512); + + rc = agent_genkey (ctrl, value, valuelen, &outbuf); xfree (value); + if (rc) + clear_outbuf (&outbuf); + else + rc = write_and_clear_outbuf (ctx, &outbuf); if (rc) log_error ("command genkey failed: %s\n", gpg_strerror (rc)); return map_to_assuan_status (rc); diff --git a/agent/genkey.c b/agent/genkey.c index 3c56ba33e..17d85f77c 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -88,7 +88,7 @@ reenter_compare_cb (struct pin_entry_info_s *pi) KEYPARAM */ int agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, - FILE *outfp) + membuf_t *outbuf) { gcry_sexp_t s_keyparam, s_key, s_private, s_public; struct pin_entry_info_s *pi, *pi2; @@ -171,7 +171,8 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, gcry_sexp_release (s_key); s_key = NULL; /* store the secret key */ - log_debug ("storing private key\n"); + if (DBG_CRYPTO) + log_debug ("storing private key\n"); rc = store_key (s_private, pi? pi->pin:NULL, 0); xfree (pi); pi = NULL; gcry_sexp_release (s_private); @@ -182,7 +183,8 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, } /* return the public key */ - log_debug ("returning public key\n"); + if (DBG_CRYPTO) + log_debug ("returning public key\n"); len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0); assert (len); buf = xtrymalloc (len); @@ -195,15 +197,7 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, } len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len); assert (len); - if (fwrite (buf, len, 1, outfp) != 1) - { - gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); - log_error ("error writing public key: %s\n", strerror (errno)); - gcry_sexp_release (s_private); - gcry_sexp_release (s_public); - xfree (buf); - return tmperr; - } + put_membuf (outbuf, buf, len); gcry_sexp_release (s_public); xfree (buf); diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index eaa2b2254..7a93e58f8 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -37,7 +37,7 @@ int agent_pkdecrypt (CTRL ctrl, const char *desc_text, const unsigned char *ciphertext, size_t ciphertextlen, - FILE *outfp) + membuf_t *outbuf) { gcry_sexp_t s_skey = NULL, s_cipher = NULL, s_plain = NULL; unsigned char *shadow_info = NULL; @@ -88,11 +88,16 @@ agent_pkdecrypt (CTRL ctrl, const char *desc_text, log_error ("smartcard decryption failed: %s\n", gpg_strerror (rc)); goto leave; } - /* FIXME: don't use buffering and change the protocol to return - a complete S-expression and not just a part. */ - fprintf (outfp, "%u:", (unsigned int)len); - fwrite (buf, 1, len, outfp); - putc (0, outfp); + /* FIXME: Change the protocol to return a complete S-expression + and not just a part. */ + { + char tmpbuf[50]; + + sprintf (tmpbuf, "%u:", (unsigned int)len); + put_membuf (outbuf, tmpbuf, strlen (tmpbuf)); + put_membuf (outbuf, buf, len); + put_membuf (outbuf, "", 1); + } } else { /* No smartcard, but a private key */ @@ -119,10 +124,7 @@ agent_pkdecrypt (CTRL ctrl, const char *desc_text, buf = xmalloc (len); len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len); assert (len); - /* FIXME: we must make sure that no buffering takes place or we are - in full control of the buffer memory (easy to do) - should go - into assuan. */ - fwrite (buf, 1, len, outfp); + put_membuf (outbuf, buf, len); } diff --git a/agent/pksign.c b/agent/pksign.c index 11e964837..3337e188c 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -176,7 +176,8 @@ agent_pksign_do (CTRL ctrl, const char *desc_text, /* SIGN whatever information we have accumulated in CTRL and write it back to OUTFP. */ int -agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) +agent_pksign (CTRL ctrl, const char *desc_text, + membuf_t *outbuf, int ignore_cache) { gcry_sexp_t s_sig = NULL; char *buf = NULL; @@ -193,10 +194,7 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len); assert (len); - /* FIXME: we must make sure that no buffering takes place or we are - in full control of the buffer memory (easy to do) - should go - into assuan. */ - fwrite (buf, 1, len, outfp); + put_membuf (outbuf, buf, len); leave: gcry_sexp_release (s_sig); diff --git a/common/ChangeLog b/common/ChangeLog index 336b3928a..eeba09341 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2004-12-20 Werner Koch <wk@g10code.com> + + * membuf.c (put_membuf): Wipe out buffer after a failed realloc. + 2004-12-19 Werner Koch <wk@g10code.com> * maperror.c (map_assuan_err_with_source): Oops, args were swapped. diff --git a/common/membuf.c b/common/membuf.c index 69e4ab908..75f6bdb2a 100644 --- a/common/membuf.c +++ b/common/membuf.c @@ -60,6 +60,11 @@ put_membuf (membuf_t *mb, const void *buf, size_t len) if (!p) { mb->out_of_core = errno; + /* Wipe out what we already accumulated. This is required + in case we are storing sensitive data here. The membuf + API does not provide another way to cleanup after an + error. */ + memset (mb->buf, 0, mb->len); return; } mb->buf = p; -- cgit v1.2.3 From f105ceb39cad128746457d635775d4bfcaebb3b9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 20 Dec 2004 11:36:46 +0000 Subject: (do_pth_event_free): The events are hold in a ring buffer. Adjust for that. (do_pth_event_body): Ditto. (pth_event_isolate): Ditto. (do_pth_wait): Ditto. (_pth_event_count): Renamed to .. (event_count): .. and adjusted as above. (pth_init): Define 3 debug levels and change all debug calls to make use of them. This makes the moule now silent. --- jnlib/ChangeLog | 12 +++ jnlib/w32-pth.c | 258 ++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 169 insertions(+), 101 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 5a566aedb..a879254ae 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,15 @@ +2004-12-20 Werner Koch <wk@g10code.com> + + * w32-pth.c (do_pth_event_free): The events are hold in a ring + buffer. Adjust for that. + (do_pth_event_body): Ditto. + (pth_event_isolate): Ditto. + (do_pth_wait): Ditto. + (_pth_event_count): Renamed to .. + (event_count): .. and adjusted as above. + (pth_init): Define 3 debug levels and change all debug calls to + make use of them. This makes the moule now silent. + 2004-12-19 Werner Koch <wk@g10code.com> * w32-pth.c (pth_init): Enable debugging depending on env var. diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 609a03705..2f041c490 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -40,8 +40,6 @@ #define W32_PTH_HANDLE_INTERNAL HANDLE #include "w32-pth.h" -#define DEBUG_ENTER_LEAVE 1 /* Set to 1 to enable full debugging. */ - #ifndef FALSE #define FALSE 0 @@ -54,11 +52,14 @@ #endif -/* States whether trhis module has been initialized. */ +/* States whether this module has been initialized. */ static int pth_initialized; -/* Controls whether debugging is enabled. */ -static int debug_enter_leave; +/* Keeps the current debug level. Define marcos to test them. */ +static int debug_level; +#define DBG_ERROR (debug_level >= 1) +#define DBG_INFO (debug_level >= 2) +#define DBG_CALLS (debug_level >= 3) /* Variables to support event handling. */ static int pth_signo; @@ -67,7 +68,7 @@ static HANDLE pth_signo_ev; /* Mutex to make sure only one thread is running. */ static CRITICAL_SECTION pth_shd; - +/* Events are store in a double linked event ring. */ struct pth_event_s { struct pth_event_s * next; @@ -124,12 +125,14 @@ pth_init (void) { SECURITY_ATTRIBUTES sa; WSADATA wsadat; + const char *s; if (pth_initialized) return TRUE; - fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); - debug_enter_leave = !!getenv ("DEBUG_PTH"); + debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0; + if (debug_level) + fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); if (WSAStartup (0x202, &wsadat)) return FALSE; @@ -184,7 +187,7 @@ enter_pth (const char *function) { /* Fixme: I am not sure whether the same thread my enter a critical section twice. */ - if (debug_enter_leave) + if (DBG_CALLS) fprintf (stderr, "%s: enter_pth (%s)\n", log_get_prefix (NULL), function? function:""); LeaveCriticalSection (&pth_shd); @@ -195,7 +198,7 @@ static void leave_pth (const char *function) { EnterCriticalSection (&pth_shd); - if (debug_enter_leave) + if (DBG_CALLS) fprintf (stderr, "%s: leave_pth (%s)\n", log_get_prefix (NULL), function? function:""); } @@ -262,9 +265,10 @@ pth_read (int fd, void * buffer, size_t size) { char strerr[256]; - fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n", - log_get_prefix (NULL), fd, - w32_strerror (strerr, sizeof strerr)); + if (DBG_ERROR) + fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n", + log_get_prefix (NULL), fd, + w32_strerror (strerr, sizeof strerr)); n = -1; } else @@ -302,9 +306,10 @@ pth_write (int fd, const void * buffer, size_t size) n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); if (!n) { - fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", - log_get_prefix (NULL), fd, - w32_strerror (strerr, sizeof strerr)); + if (DBG_ERROR) + fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", + log_get_prefix (NULL), fd, + w32_strerror (strerr, sizeof strerr)); n = -1; } else @@ -395,21 +400,21 @@ pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, (WSAGetLastError () == WSAEINPROGRESS || WSAGetLastError () == WSAEWOULDBLOCK)) { - if (ev == NULL) + if (!ev) { ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE| PTH_MODE_STATIC, &ev_key, fd); - if (ev == NULL) + if (!ev) { leave_pth (__FUNCTION__); return -1; } - if (ev_extra != NULL) + if (ev_extra) pth_event_concat (ev, ev_extra, NULL); } /* Wait until accept has a chance. */ do_pth_wait (ev); - if (ev_extra != NULL) + if (ev_extra) { pth_event_isolate (ev); if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED) @@ -452,9 +457,10 @@ pth_mutex_release (pth_mutex_t *mutex) { char strerr[256]; - fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n", - log_get_prefix (NULL), *mutex, - w32_strerror (strerr, sizeof strerr)); + if (DBG_ERROR) + fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n", + log_get_prefix (NULL), *mutex, + w32_strerror (strerr, sizeof strerr)); rc = FALSE; } else @@ -483,9 +489,10 @@ pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra) { char strerr[256]; - fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n", - log_get_prefix (NULL), *mutex, - w32_strerror (strerr, sizeof strerr)); + if (DBG_ERROR) + fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n", + log_get_prefix (NULL), *mutex, + w32_strerror (strerr, sizeof strerr)); } rc = FALSE; break; @@ -495,9 +502,10 @@ pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra) break; default: - fprintf (stderr, "%s: WaitForSingleObject returned unexpected " - "code %d for mutex %p\n", - log_get_prefix (NULL), code, *mutex); + if (DBG_ERROR) + fprintf (stderr, "%s: WaitForSingleObject returned unexpected " + "code %d for mutex %p\n", + log_get_prefix (NULL), code, *mutex); rc = FALSE; break; } @@ -576,8 +584,9 @@ pth_attr_set (pth_attr_t hd, int field, ...) if (val) { hd->flags |= PTH_ATTR_JOINABLE; - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", - log_get_prefix (NULL)); + if (DBG_INFO) + fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", + log_get_prefix (NULL)); } break; @@ -587,8 +596,9 @@ pth_attr_set (pth_attr_t hd, int field, ...) { hd->flags |= PTH_ATTR_STACK_SIZE; hd->stack_size = val; - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", - log_get_prefix (NULL), val); + if (DBG_INFO) + fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", + log_get_prefix (NULL), val); } break; @@ -602,8 +612,9 @@ pth_attr_set (pth_attr_t hd, int field, ...) if (!hd->name) return FALSE; hd->flags |= PTH_ATTR_NAME; - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", - log_get_prefix (NULL), hd->name); + if (DBG_INFO) + fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", + log_get_prefix (NULL), hd->name); } break; @@ -647,14 +658,16 @@ do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) FIXME: We should no use th W32's Thread handle directly but keep our own thread control structure. CTX may be used for that. */ - fprintf (stderr, "%s: do_pth_spawn creating thread ...\n", - log_get_prefix (NULL)); + if (DBG_INFO) + fprintf (stderr, "%s: do_pth_spawn creating thread ...\n", + log_get_prefix (NULL)); th = CreateThread (&sa, hd->stack_size, (LPTHREAD_START_ROUTINE)launch_thread, ctx, CREATE_SUSPENDED, &tid); ctx->th = th; - fprintf (stderr, "%s: do_pth_spawn created thread %p\n", - log_get_prefix (NULL),th); + if (DBG_INFO) + fprintf (stderr, "%s: do_pth_spawn created thread %p\n", + log_get_prefix (NULL),th); if (!th) free (ctx); else @@ -787,7 +800,8 @@ sig_handler (DWORD signo) case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; } SetEvent (pth_signo_ev); - fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); + if (DBG_INFO) + fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); return TRUE; } @@ -799,7 +813,8 @@ do_pth_event_body (unsigned long spec, va_list arg) pth_event_t ev; int rc; - fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec); + if (DBG_INFO) + fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec); ev = calloc (1, sizeof *ev); if (!ev) return NULL; @@ -811,8 +826,9 @@ do_pth_event_body (unsigned long spec, va_list arg) ev->u_type = PTH_EVENT_SIGS; ev->val = va_arg (arg, int *); rc = SetConsoleCtrlHandler (sig_handler, TRUE); - fprintf (stderr, "%s: pth_event: sigs rc=%d\n", - log_get_prefix (NULL), rc); + if (DBG_INFO) + fprintf (stderr, "%s: pth_event: sigs rc=%d\n", + log_get_prefix (NULL), rc); } else if (spec & PTH_EVENT_FD) { @@ -823,8 +839,9 @@ do_pth_event_body (unsigned long spec, va_list arg) ev->u_type = PTH_EVENT_FD; va_arg (arg, pth_key_t); ev->u.fd = va_arg (arg, int); - fprintf (stderr, "%s: pth_event: fd=%d\n", - log_get_prefix (NULL), ev->u.fd); + if (DBG_INFO) + fprintf (stderr, "%s: pth_event: fd=%d\n", + log_get_prefix (NULL), ev->u.fd); } else if (spec & PTH_EVENT_TIME) { @@ -854,6 +871,8 @@ do_pth_event_body (unsigned long spec, va_list arg) free (ev); return NULL; } + ev->next = ev; + ev->prev = ev; return ev; } @@ -938,8 +957,9 @@ wait_for_fd (int fd, int is_read, int nwait) while (1) { n = select (fd+1, &r, &w, NULL, &tv); - fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n", - log_get_prefix (NULL), n, fd,(int)WSAGetLastError ()); + if (DBG_INFO) + fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n", + log_get_prefix (NULL), n, fd,(int)WSAGetLastError ()); if (n == -1) break; if (!n) @@ -1036,8 +1056,9 @@ do_pth_event_occurred (pth_event_t ev) if (sigpresent (ev->u.sig, pth_signo) && WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0) { - fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n", - log_get_prefix (NULL)); + if (DBG_INFO) + fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n", + log_get_prefix (NULL)); (*ev->val) = pth_signo; ret = 1; } @@ -1090,18 +1111,21 @@ pth_event_status (pth_event_t ev) static int do_pth_event_free (pth_event_t ev, int mode) { - pth_event_t n; + if (!ev) + return FALSE; if (mode == PTH_FREE_ALL) { - while (ev) + pth_event_t cur = ev; + do { - n = ev->next; - CloseHandle (ev->hd); - ev->hd = NULL; - free (ev); - ev = n; + pth_event_t next = cur->next; + CloseHandle (cur->hd); + cur->hd = NULL; + free (cur); + cur = next; } + while (cur != ev); } else if (mode == PTH_FREE_THIS) { @@ -1111,6 +1135,8 @@ do_pth_event_free (pth_event_t ev, int mode) ev->hd = NULL; free (ev); } + else + return FALSE; return TRUE; } @@ -1131,24 +1157,39 @@ pth_event_free (pth_event_t ev, int mode) pth_event_t pth_event_isolate (pth_event_t ev) { - pth_event_t ring = NULL; + pth_event_t ring; if (!ev) return NULL; + if (ev->next == ev && ev->prev == ev) + return NULL; /* Only one event. */ + + ring = ev->next; + ev->prev->next = ev->next; + ev->next->prev = ev->prev; + ev->prev = ev; + ev->next = ev; return ring; } static int -_pth_event_count (pth_event_t ev) +event_count (pth_event_t ev) { - pth_event_t p; - int cnt=0; + pth_event_t r; + int cnt = 0; + + if (ev) + { + r = ev; + do + { + cnt++; + r = r->next; + } + while (r != ev); + } - if (!ev) - return 0; - for (p = ev; p; p = p->next) - cnt++; return cnt; } @@ -1166,13 +1207,15 @@ spawn_helper_thread (void *(*func)(void *), void *arg) sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof sa; - fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n", - log_get_prefix (NULL)); + if (DBG_INFO) + fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n", + log_get_prefix (NULL)); th = CreateThread (&sa, 32*1024, (LPTHREAD_START_ROUTINE)func, arg, 0, &tid); - fprintf (stderr, "%s: spawn_helper_thread created thread %p\n", - log_get_prefix (NULL), th); + if (DBG_INFO) + fprintf (stderr, "%s: spawn_helper_thread created thread %p\n", + log_get_prefix (NULL), th); return th; } @@ -1197,7 +1240,8 @@ wait_fd_thread (void * ctx) pth_event_t ev = ctx; wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); + if (DBG_INFO) + fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); SetEvent (ev->hd); ExitThread (0); return NULL; @@ -1211,7 +1255,8 @@ wait_timer_thread (void * ctx) int n = ev->u.tv.tv_sec*1000; Sleep (n); SetEvent (ev->hd); - fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL)); + if (DBG_INFO) + fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL)); ExitThread (0); return NULL; } @@ -1223,51 +1268,62 @@ do_pth_wait (pth_event_t ev) HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2]; int hdidx[MAXIMUM_WAIT_OBJECTS/2]; DWORD n = 0; - pth_event_t tmp; int pos=0, i=0; if (!ev) return 0; - n =_pth_event_count (ev); + n = event_count (ev); if (n > MAXIMUM_WAIT_OBJECTS/2) return -1; - fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); - for (tmp = ev; tmp; tmp = tmp->next) + if (DBG_INFO) + fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); + if (ev) { - switch (tmp->u_type) + pth_event_t r = ev; + do { - case 0: - waitbuf[pos++] = tmp->hd; - break; - - case PTH_EVENT_SIGS: - waitbuf[pos++] = pth_signo_ev; - fprintf (stderr, "pth_wait: add signal event.\n"); - break; - - case PTH_EVENT_FD: - fprintf (stderr, "pth_wait: spawn event wait thread.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, tmp); - break; - - case PTH_EVENT_TIME: - fprintf (stderr, "pth_wait: spawn event timer thread.\n"); - hdidx[i++] = pos; - waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, tmp); - break; - - case PTH_EVENT_MUTEX: - fprintf (stderr, "pth_wait: add mutex event.\n"); - break; + switch (r->u_type) + { + case 0: + waitbuf[pos++] = r->hd; + break; + + case PTH_EVENT_SIGS: + waitbuf[pos++] = pth_signo_ev; + if (DBG_INFO) + fprintf (stderr, "pth_wait: add signal event.\n"); + break; + + case PTH_EVENT_FD: + if (DBG_INFO) + fprintf (stderr, "pth_wait: spawn event wait thread.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, r); + break; + + case PTH_EVENT_TIME: + if (DBG_INFO) + fprintf (stderr, "pth_wait: spawn event timer thread.\n"); + hdidx[i++] = pos; + waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, r); + break; + + case PTH_EVENT_MUTEX: + if (DBG_INFO) + fprintf (stderr, "pth_wait: ignoring mutex event.\n"); + break; + } } + while ( r != ev ); } - fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos); + if (DBG_INFO) + fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos); n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); free_helper_threads (waitbuf, hdidx, i); - fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n); + if (DBG_INFO) + fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n); if (n != WAIT_TIMEOUT) return 1; -- cgit v1.2.3 From 581f5ddb1724f469dc7f934f5093179dfb1e05a9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 20 Dec 2004 16:17:25 +0000 Subject: * configure.ac: Add PATHSEP_C and PATHSEP_S. For W32 let all directories default to c:/gnupg. Require libassuan 0.6.9. * gpg-agent.c (main) [W32]: Now that Mutexes work we can remove the pth_init kludge. (main): Add new options --[no-]use-standard-socket. (check_for_running_agent): Check whether it is running on the standard socket. * sysutils.h [W32]: Define sleep. * util.h: Add prototype for mkdtemp. * call-agent.c (start_agent): Before starting a pipe server start to connect to a server on the standard socket. Use PATHSEP * call-dirmngr.c (start_dirmngr): Use PATHSEP. * import.c: Include unistd.h for dup and close. --- ChangeLog | 5 ++ NEWS | 6 ++ TODO | 7 ++ agent/ChangeLog | 6 ++ agent/gpg-agent.c | 181 +++++++++++++++++++++++++++++++-------------------- agent/protect-tool.c | 14 ++-- common/ChangeLog | 3 + common/mkdtemp.c | 3 +- common/sysutils.h | 8 +++ common/util.h | 4 ++ configure.ac | 16 +++-- doc/gpg-agent.texi | 29 ++++++++- doc/gpgsm.texi | 10 +++ doc/scdaemon.texi | 9 +++ sm/ChangeLog | 8 +++ sm/call-agent.c | 72 +++++++++++--------- sm/call-dirmngr.c | 2 +- sm/import.c | 1 + 18 files changed, 270 insertions(+), 114 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3db690f2d..1ca430c63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-12-20 Werner Koch <wk@g10code.com> + + * configure.ac: Add PATHSEP_C and PATHSEP_S. For W32 let all + directories default to c:/gnupg. Require libassuan 0.6.9. + 2004-12-18 Werner Koch <wk@g10code.com> * configure.ac (AH_BOTTOM): Define EXEEXT_S. diff --git a/NEWS b/NEWS index 0d0a7058f..525fdbe72 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,12 @@ Noteworthy changes in version 1.9.14 ------------------------------------------------- + * [gpg-agent] New option --use-standard-socket to allow the use of a + fixed socket. gpgsm falls back to this socket if GPG_AGENT_INFO + has not been set. + + * Ported to MS Windows. + Noteworthy changes in version 1.9.13 (2004-12-03) ------------------------------------------------- diff --git a/TODO b/TODO index 138f9bade..c7eca304e 100644 --- a/TODO +++ b/TODO @@ -95,3 +95,10 @@ might want to have an agent context for each service request This needs support in libksba/src/cert.c as well as in sm/*.c. Need test certs as well. Same goes for CRL authorityKeyIdentifier. + +* Windows port +** gpgsm's LISTKEYS does not yet work + Fix is to change everything to libestream +** Signals are not support + This means we can't reread a configuration + diff --git a/agent/ChangeLog b/agent/ChangeLog index f2b82466c..507a90c9d 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,11 @@ 2004-12-20 Werner Koch <wk@g10code.com> + * gpg-agent.c (main) [W32]: Now that Mutexes work we can remove + the pth_init kludge. + (main): Add new options --[no-]use-standard-socket. + (check_for_running_agent): Check whether it is running on the + standard socket. + * call-scd.c (init_membuf, put_membuf, get_membuf): Removed. We now use the identical implementation from ../common/membuf.c. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 65d5fd5a6..911afb881 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -84,13 +84,14 @@ enum cmd_and_opt_values oDisablePth, oDefCacheTTL, oMaxCacheTTL, + oUseStandardSocket, + oNoUseStandardSocket, oIgnoreCacheForSigning, oAllowMarkTrusted, oKeepTTY, - oKeepDISPLAY, - -aTest }; + oKeepDISPLAY +}; @@ -115,6 +116,9 @@ static ARGPARSE_OPTS opts[] = { { oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, { oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")}, + { oUseStandardSocket, "use-standard-socket", 0, + N_("use a standard location for the socket")}, + { oNoUseStandardSocket, "no-use-standard-socket", 0, "@"}, { oPinentryProgram, "pinentry-program", 2 , N_("|PGM|use PGM as the PIN-Entry program") }, @@ -154,7 +158,7 @@ static int shutdown_pending; static int maybe_setuid = 1; /* Name of the communication socket */ -static char socket_name[128]; +static char *socket_name; /* Default values for options passed to the pinentry. */ static char *default_display; @@ -177,12 +181,11 @@ static char *current_logfile; static void create_directories (void); #ifdef USE_GNU_PTH static void handle_connections (int listen_fd); - /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; - #endif /*USE_GNU_PTH*/ -static void check_for_running_agent (void); + +static int check_for_running_agent (int); @@ -293,7 +296,7 @@ set_debug (void) static void cleanup (void) { - if (*socket_name) + if (socket_name && *socket_name) { char *p; @@ -419,6 +422,7 @@ main (int argc, char **argv ) int debug_wait = 0; int disable_pth = 0; int gpgconf_list = 0; + int standard_socket = 0; gpg_error_t err; @@ -437,17 +441,12 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ #ifdef USE_GNU_PTH -#ifdef HAVE_W32_SYSTEM - /* For W32 we need pth. */ - pth_init (); -#else err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -#endif #endif /*USE_GNU_PTH*/ @@ -468,18 +467,28 @@ main (int argc, char **argv ) may_coredump = disable_core_dumps (); + /* Set default options. */ parse_rereadable_options (NULL, 0); /* Reset them to default values. */ - +#ifdef HAVE_W32_SYSTEM + standard_socket = 1; /* Under Windows we always use a standard + socket. */ +#endif + shell = getenv ("SHELL"); if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) csh_style = 1; - + + opt.homedir = getenv("GNUPGHOME"); +#ifdef HAVE_W32_SYSTEM + if (!opt.homedir || !*opt.homedir) + opt.homedir = read_w32_registry_string (NULL, + "Software\\GNU\\GnuPG", "HomeDir"); +#endif /*HAVE_W32_SYSTEM*/ if (!opt.homedir || !*opt.homedir) opt.homedir = GNUPG_DEFAULT_HOMEDIR; - - /* check whether we have a config file on the commandline */ + /* Check whether we have a config file on the commandline */ orig_argc = argc; orig_argv = argv; pargs.argc = &argc; @@ -509,7 +518,6 @@ main (int argc, char **argv ) Now we are now working under our real uid */ - if (default_config) configname = make_filename (opt.homedir, "gpg-agent.conf", NULL ); @@ -584,6 +592,9 @@ main (int argc, char **argv ) case oLCmessages: default_lc_messages = xstrdup (pargs.r.ret_str); break; + case oUseStandardSocket: standard_socket = 1; break; + case oNoUseStandardSocket: standard_socket = 0; break; + case oKeepTTY: opt.keep_tty = 1; break; case oKeepDISPLAY: opt.keep_display = 1; break; @@ -695,7 +706,7 @@ main (int argc, char **argv ) if (!pipe_server && !is_daemon) { log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX); - check_for_running_agent (); + check_for_running_agent (0); agent_exit (0); } @@ -736,6 +747,7 @@ main (int argc, char **argv ) else { /* Regular server mode */ int fd; + int rc; pid_t pid; int len; struct sockaddr_un serv_addr; @@ -750,28 +762,28 @@ main (int argc, char **argv ) unsetenv ("DISPLAY"); #endif - *socket_name = 0; - snprintf (socket_name, DIM(socket_name)-1, - "/tmp/gpg-XXXXXX/S.gpg-agent"); - socket_name[DIM(socket_name)-1] = 0; - p = strrchr (socket_name, '/'); - if (!p) - BUG (); - *p = 0;; - -#ifndef HAVE_W32_SYSTEM - if (!mkdtemp(socket_name)) + /* Create the socket name . */ + if (standard_socket) + socket_name = make_filename (opt.homedir, "S.gpg-agent", NULL); + else { - log_error ("can't create directory `%s': %s\n", - socket_name, strerror(errno) ); - exit (1); + socket_name = xstrdup ("/tmp/gpg-XXXXXX/S.gpg-agent"); + p = strrchr (socket_name, '/'); + if (!p) + BUG (); + *p = 0;; + if (!mkdtemp(socket_name)) + { + log_error (_("can't create directory `%s': %s\n"), + socket_name, strerror(errno) ); + exit (1); + } + *p = '/'; } -#endif - *p = '/'; - if (strchr (socket_name, ':') ) + if (strchr (socket_name, PATHSEP_C) ) { - log_error ("colons are not allowed in the socket name\n"); + log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S); exit (1); } if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) @@ -797,13 +809,22 @@ main (int argc, char **argv ) len = (offsetof (struct sockaddr_un, sun_path) + strlen(serv_addr.sun_path) + 1); - if ( #ifdef HAVE_W32_SYSTEM - _w32_sock_bind + rc = _w32_sock_bind (fd, (struct sockaddr*)&serv_addr, len); + if (rc == -1 && standard_socket) + { + remove (socket_name); + rc = bind (fd, (struct sockaddr*)&serv_addr, len); + } #else - bind + rc = bind (fd, (struct sockaddr*)&serv_addr, len); + if (rc == -1 && standard_socket && errno == EADDRINUSE) + { + remove (socket_name); + rc = bind (fd, (struct sockaddr*)&serv_addr, len); + } #endif - (fd, (struct sockaddr*)&serv_addr, len) == -1) + if (rc == -1) { log_error ("error binding socket to `%s': %s\n", serv_addr.sun_path, strerror (errno) ); @@ -823,7 +844,10 @@ main (int argc, char **argv ) fflush (NULL); -#ifndef HAVE_W32_SYSTEM +#ifdef HAVE_W32_SYSTEM + pid = getpid (); + printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); +#else /*!HAVE_W32_SYSTEM*/ pid = fork (); if (pid == (pid_t)-1) { @@ -1286,53 +1310,72 @@ handle_connections (int listen_fd) /* Figure out whether an agent is available and running. Prints an - error if not. */ -static void -check_for_running_agent () + error if not. Usually started with MODE 0. */ +static int +check_for_running_agent (int mode) { int rc; char *infostr, *p; assuan_context_t ctx; int prot, pid; - infostr = getenv ("GPG_AGENT_INFO"); - if (!infostr || !*infostr) + if (!mode) { - log_error (_("no gpg-agent running in this session\n")); - return; - } + infostr = getenv ("GPG_AGENT_INFO"); + if (!infostr || !*infostr) + { + if (!check_for_running_agent (1)) + return 0; /* Okay, its running on the standard socket. */ + log_error (_("no gpg-agent running in this session\n")); + return -1; + } - infostr = xstrdup (infostr); - if ( !(p = strchr (infostr, ':')) || p == infostr) - { - log_error (_("malformed GPG_AGENT_INFO environment variable\n")); - xfree (infostr); - return; - } + infostr = xstrdup (infostr); + if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) + { + xfree (infostr); + if (!check_for_running_agent (1)) + return 0; /* Okay, its running on the standard socket. */ + log_error (_("malformed GPG_AGENT_INFO environment variable\n")); + return -1; + } - *p++ = 0; - pid = atoi (p); - while (*p && *p != ':') - p++; - prot = *p? atoi (p+1) : 0; - if (prot != 1) + *p++ = 0; + pid = atoi (p); + while (*p && *p != PATHSEP_C) + p++; + prot = *p? atoi (p+1) : 0; + if (prot != 1) + { + xfree (infostr); + log_error (_("gpg-agent protocol version %d is not supported\n"), + prot); + if (!check_for_running_agent (1)) + return 0; /* Okay, its running on the standard socket. */ + return -1; + } + } + else /* MODE != 0 */ { - log_error (_("gpg-agent protocol version %d is not supported\n"), - prot); - xfree (infostr); - return; + infostr = make_filename (opt.homedir, "S.gpg-agent", NULL); } + rc = assuan_socket_connect (&ctx, infostr, pid); xfree (infostr); if (rc) { - log_error ("can't connect to the agent: %s\n", assuan_strerror (rc)); - return; + if (!mode && !check_for_running_agent (1)) + return 0; /* Okay, its running on the standard socket. */ + + if (!mode) + log_error ("can't connect to the agent: %s\n", assuan_strerror (rc)); + return -1; } if (!opt.quiet) log_info ("gpg-agent running and available\n"); assuan_disconnect (ctx); + return 0; } diff --git a/agent/protect-tool.c b/agent/protect-tool.c index ef8a50916..43dd67eea 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -44,6 +44,8 @@ #include "minip12.h" #include "simple-pwquery.h" #include "i18n.h" +#include "sysutils.h" + enum cmd_and_opt_values { aNull = 0, @@ -1065,12 +1067,12 @@ main (int argc, char **argv ) gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); -#ifdef HAVE_W32_SYSTEM - opt_homedir = read_w32_registry_string ( NULL, - "Software\\GNU\\GnuPG", "HomeDir" ); -#else /*!HAVE_W32_SYSTEM*/ opt_homedir = getenv ("GNUPGHOME"); -#endif /*!HAVE_W32_SYSTEM*/ +#ifdef HAVE_W32_SYSTEM + if (!opt_homedir || !*opt_homedir) + opt_homedir = read_w32_registry_string (NULL, + "Software\\GNU\\GnuPG", "HomeDir"); +#endif /*HAVE_W32_SYSTEM*/ if (!opt_homedir || !*opt_homedir) opt_homedir = GNUPG_DEFAULT_HOMEDIR; @@ -1162,7 +1164,9 @@ get_passphrase (int promptno) char *pw; int err; const char *desc; +#ifdef HAVE_LANGINFO_CODESET char *orig_codeset = NULL; +#endif int error_msgno; diff --git a/common/ChangeLog b/common/ChangeLog index eeba09341..11bf8029a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,8 @@ 2004-12-20 Werner Koch <wk@g10code.com> + * sysutils.h [W32]: Define sleep. + * util.h: Add prototype for mkdtemp. + * membuf.c (put_membuf): Wipe out buffer after a failed realloc. 2004-12-19 Werner Koch <wk@g10code.com> diff --git a/common/mkdtemp.c b/common/mkdtemp.c index abe731e0a..a85b89eb4 100644 --- a/common/mkdtemp.c +++ b/common/mkdtemp.c @@ -35,7 +35,8 @@ # define mkdir(a,b) mkdir(a) #endif -char *mkdtemp(char *template) +char * +mkdtemp (char *template) { int attempts,idx,count=0; unsigned char *ch; diff --git a/common/sysutils.h b/common/sysutils.h index 9df292031..08198f685 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -28,11 +28,19 @@ const unsigned char *get_session_marker (size_t *rlen); int check_permissions (const char *path,int extension,int checkonly); #ifdef HAVE_W32_SYSTEM +/* Windows declares sleep as obsolete, but provides a definition for + _sleep but non for the still existing sleep. */ +#define sleep(a) _sleep ((a)) + /*-- w32reg.c --*/ char *read_w32_registry_string( const char *root, const char *dir, const char *name ); int write_w32_registry_string(const char *root, const char *dir, const char *name, const char *value); + #endif /*HAVE_W32_SYSTEM*/ + + + #endif /*GNUPG_COMMON_SYSUTILS_H*/ diff --git a/common/util.h b/common/util.h index 835be4e0e..1159da925 100644 --- a/common/util.h +++ b/common/util.h @@ -150,6 +150,10 @@ char *strsep (char **stringp, const char *delim); #ifndef HAVE_TTYNAME char *ttyname (int fd); #endif +#ifndef HAVE_MKDTEMP +char *mkdtemp (char *template); +#endif + /*-- some macros to replace ctype ones and avoid locale problems --*/ #define spacep(p) (*(p) == ' ' || *(p) == '\t') diff --git a/configure.ac b/configure.ac index 463358f28..7eb3a6b71 100644 --- a/configure.ac +++ b/configure.ac @@ -34,7 +34,7 @@ NEED_GPG_ERROR_VERSION=0.7 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.1.94 -NEED_LIBASSUAN_VERSION=0.6.6 +NEED_LIBASSUAN_VERSION=0.6.9 NEED_KSBA_VERSION=0.9.7 @@ -252,15 +252,19 @@ AH_BOTTOM([ than one character because the code assumes strlen()==1 */ #ifdef HAVE_DOSISH_SYSTEM #define DIRSEP_C '\\' -#define EXTSEP_C '.' #define DIRSEP_S "\\" +#define EXTSEP_C '.' #define EXTSEP_S "." +#define PATHSEP_C ';' +#define PATHSEP_S ";" #define EXEEXT_S ".exe" #else #define DIRSEP_C '/' -#define EXTSEP_C '.' #define DIRSEP_S "/" +#define EXTSEP_C '.' #define EXTSEP_S "." +#define PATHSEP_C ':' +#define PATHSEP_S ":" #define EXEEXT_S "" #endif @@ -278,9 +282,9 @@ AH_BOTTOM([ comply with the GNU coding standards. */ #ifdef HAVE_DRIVE_LETTERS #define GNUPG_BINDIR "c:\\gnupg" -#define GNUPG_LIBEXECDIR "c:\\lib\\gnupg" -#define GNUPG_LIBDIR "c:\\lib\\gnupg" -#define GNUPG_DATADIR "c:\\lib\\gnupg" +#define GNUPG_LIBEXECDIR "c:\\gnupg" +#define GNUPG_LIBDIR "c:\\gnupg" +#define GNUPG_DATADIR "c:\\gnupg" #endif /* Setup the hardwired names of modules. */ diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index cccbef02a..28d99673d 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -43,7 +43,7 @@ fi @end smallexample @noindent -You should aleways add the following lines to your @code{.bashrc} or +You should always add the following lines to your @code{.bashrc} or whatever initialization file is used for all shell invocations: @smallexample @@ -53,7 +53,8 @@ export GPG_TTY @noindent It is important that this environment variable always reflects the -output of the @code{tty} command. +output of the @code{tty} command. For W32 systems this option is not +required. Please make sure that a proper pinentry program has been installed under the default filename (which is system dependant) or use the @@ -129,6 +130,15 @@ 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 --homedir @var{dir} +@opindex homedir +Set the name of the home directory to @var{dir}. If his option is not +used, the home directory defaults to @file{~/.gnupg}. It is only +recognized when given on the command line. It also overrides any home +directory stated through the environment variable @var{GNUPGHOME} or +(on W32 systems) by means on the Registry entry +@var{HKCU\Software\GNU\GnuPG:HomeDir}. + @item -v @item --verbose @opindex v @@ -279,6 +289,21 @@ Use program @var{filename} as the Smartcard daemon. The default is installation dependend and can be shown with the @code{--version} command. +@item --use-standard-socket +@itemx --no-use-standard-socket +@opindex use-standard-socket +@opindex no-use-standard-socket +By enabling this option @command{gpg-agent} will listen on the socket +named @file{S.gpg-agent}, located in the home directory, and not create +a random socket below a temporary directory. Tools connecting to +@command{gpg-agent} should first try to connect to the socket given in +environment variable @var{GPG_AGENT_INFO} and the fall back to this +socket. This option may not be used if the home directory is mounted as +a remote file system. + +@noindent +Note, that as of now, W32 systems default to this option. + @item --display @var{string} @itemx --ttyname @var{string} diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index beedab7b7..4c167ebf5 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -236,6 +236,16 @@ 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 --homedir @var{dir} +@opindex homedir +Set the name of the home directory to @var{dir}. If his option is not +used, the home directory defaults to @file{~/.gnupg}. It is only +recognized when given on the command line. It also overrides any home +directory stated through the environment variable @var{GNUPGHOME} or +(on W32 systems) by means on the Registry entry +@var{HKCU\Software\GNU\GnuPG:HomeDir}. + + @item -v @item --verbose @opindex v diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 872000175..5265ed21e 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -81,6 +81,15 @@ 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 --homedir @var{dir} +@opindex homedir +Set the name of the home directory to @var{dir}. If his option is not +used, the home directory defaults to @file{~/.gnupg}. It is only +recognized when given on the command line. It also overrides any home +directory stated through the environment variable @var{GNUPGHOME} or +(on W32 systems) by means on the Registry entry +@var{HKCU\Software\GNU\GnuPG:HomeDir}. + @item -v @item --verbose @opindex v diff --git a/sm/ChangeLog b/sm/ChangeLog index 167ec8753..19e7b0e8d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2004-12-20 Werner Koch <wk@g10code.com> + + * call-agent.c (start_agent): Before starting a pipe server start + to connect to a server on the standard socket. Use PATHSEP + * call-dirmngr.c (start_dirmngr): Use PATHSEP. + + * import.c: Include unistd.h for dup and close. + 2004-12-18 Werner Koch <wk@g10code.com> * gpgsm.h (map_assuan_err): Define in terms of diff --git a/sm/call-agent.c b/sm/call-agent.c index 0d15a5595..0647acbb8 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -81,41 +81,53 @@ start_agent (ctrl_t ctrl) { const char *pgmname; const char *argv[3]; + char *sockname; int no_close_list[3]; int i; - if (opt.verbose) - log_info (_("no running gpg-agent - starting one\n")); - - gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0"); + /* First check whether we can connect at the standard + socket. */ + sockname = make_filename (opt.homedir, "S.gpg-agent", NULL); + rc = assuan_socket_connect (&ctx, sockname, 0); + xfree (sockname); - if (fflush (NULL)) + if (rc) { - gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); - log_error ("error flushing pending output: %s\n", strerror (errno)); - return tmperr; + /* With no success start a new server. */ + if (opt.verbose) + log_info (_("no running gpg-agent - starting one\n")); + + gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0"); + + if (fflush (NULL)) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_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); } - - 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 { @@ -123,7 +135,7 @@ start_agent (ctrl_t ctrl) int pid; infostr = xstrdup (infostr); - if ( !(p = strchr (infostr, ':')) || p == infostr) + if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) { log_error (_("malformed GPG_AGENT_INFO environment variable\n")); xfree (infostr); diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index d00a53db5..9c4a5f22f 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -209,7 +209,7 @@ start_dirmngr (void) infostr = xstrdup (infostr); if (!try_default && *infostr) { - if ( !(p = strchr (infostr, ':')) || p == infostr) + if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) { log_error (_("malformed DIRMNGR_INFO environment variable\n")); xfree (infostr); diff --git a/sm/import.c b/sm/import.c index 457ef6423..6d00e91ea 100644 --- a/sm/import.c +++ b/sm/import.c @@ -25,6 +25,7 @@ #include <errno.h> #include <time.h> #include <assert.h> +#include <unistd.h> #include "gpgsm.h" #include <gcrypt.h> -- cgit v1.2.3 From 878cf2076633742ad5f4e4008059b0fc8d776d37 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Dec 2004 10:03:00 +0000 Subject: * gpg-agent.c (main): Use default_homedir(). * protect-tool.c (main): Ditto. * signal.c (got_fatal_signal, got_usr_signal) (got_fatal_signal) [DOSISH]: Don't build. * simple-gettext.c: Include sysutils.h * homedir.c: New. * Makefile.am (libcommon_a_SOURCES): Add it. (EXTRA_DIST): Removed mkerror and mkerrtok. * gpgv.c, g10.c (main): Use default_hoemdir (). * scdaemon.c (main): Use default_homedir(). * gpgsm.c (main): Use default_homedir(). --- TODO | 2 ++ agent/ChangeLog | 6 ++++++ agent/gpg-agent.c | 9 +-------- agent/protect-tool.c | 11 ++--------- common/ChangeLog | 10 ++++++++++ common/Makefile.am | 3 +-- common/homedir.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ common/signal.c | 14 ++++++++++---- common/simple-gettext.c | 2 +- common/util.h | 4 ++++ g10/ChangeLog | 4 ++++ g10/g10.c | 11 ++--------- g10/gpgv.c | 11 ++--------- scd/ChangeLog | 4 ++++ scd/command.c | 4 +--- scd/scdaemon.c | 16 +++------------- sm/ChangeLog | 4 ++++ sm/gpgsm.c | 11 ++--------- 18 files changed, 103 insertions(+), 67 deletions(-) create mode 100644 common/homedir.c diff --git a/TODO b/TODO index c7eca304e..16311a204 100644 --- a/TODO +++ b/TODO @@ -101,4 +101,6 @@ might want to have an agent context for each service request Fix is to change everything to libestream ** Signals are not support This means we can't reread a configuration +** No card status notifications. + diff --git a/agent/ChangeLog b/agent/ChangeLog index 507a90c9d..cf3569264 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * gpg-agent.c (main): Use default_homedir(). + * protect-tool.c (main): Ditto. + + 2004-12-20 Werner Koch <wk@g10code.com> * gpg-agent.c (main) [W32]: Now that Mutexes work we can remove diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 911afb881..2c3d834a5 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -478,15 +478,8 @@ main (int argc, char **argv ) if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) csh_style = 1; + opt.homedir = default_homedir (); - opt.homedir = getenv("GNUPGHOME"); -#ifdef HAVE_W32_SYSTEM - if (!opt.homedir || !*opt.homedir) - opt.homedir = read_w32_registry_string (NULL, - "Software\\GNU\\GnuPG", "HomeDir"); -#endif /*HAVE_W32_SYSTEM*/ - if (!opt.homedir || !*opt.homedir) - opt.homedir = GNUPG_DEFAULT_HOMEDIR; /* Check whether we have a config file on the commandline */ orig_argc = argc; diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 43dd67eea..ee0276a43 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -84,7 +84,7 @@ struct rsa_secret_key_s }; -static char *opt_homedir; +static const char *opt_homedir; static int opt_armor; static int opt_store; static int opt_force; @@ -1067,14 +1067,7 @@ main (int argc, char **argv ) gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); - opt_homedir = getenv ("GNUPGHOME"); -#ifdef HAVE_W32_SYSTEM - if (!opt_homedir || !*opt_homedir) - opt_homedir = read_w32_registry_string (NULL, - "Software\\GNU\\GnuPG", "HomeDir"); -#endif /*HAVE_W32_SYSTEM*/ - if (!opt_homedir || !*opt_homedir) - opt_homedir = GNUPG_DEFAULT_HOMEDIR; + opt_homedir = default_homedir (); pargs.argc = &argc; diff --git a/common/ChangeLog b/common/ChangeLog index 11bf8029a..667deb51a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,13 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * signal.c (got_fatal_signal, got_usr_signal) + (got_fatal_signal) [DOSISH]: Don't build. + * simple-gettext.c: Include sysutils.h + + * homedir.c: New. + * Makefile.am (libcommon_a_SOURCES): Add it. + (EXTRA_DIST): Removed mkerror and mkerrtok. + 2004-12-20 Werner Koch <wk@g10code.com> * sysutils.h [W32]: Define sleep. diff --git a/common/Makefile.am b/common/Makefile.am index 795d66a1a..ccbaaad75 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -19,8 +19,6 @@ ## 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) @@ -31,6 +29,7 @@ libcommon_a_SOURCES = \ sexp-parse.h \ maperror.c \ sysutils.c sysutils.h \ + homedir.c \ gettime.c \ yesno.c \ b64enc.c \ diff --git a/common/homedir.c b/common/homedir.c new file mode 100644 index 000000000..8b5bc9f05 --- /dev/null +++ b/common/homedir.c @@ -0,0 +1,44 @@ +/* homedir.c - Setup the home directory. + * 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 + */ + +#include <config.h> +#include <stdlib.h> +#include <errno.h> + +#include "util.h" +#include "sysutils.h" + +/* Set up the default home directory. The usual --homedir option + should be parsed later. */ +const char * +default_homedir (void) +{ + const char *dir; + + dir = getenv("GNUPGHOME"); +#ifdef HAVE_W32_SYSTEM + if (!dir || !*dir) + dir = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir"); +#endif /*HAVE_W32_SYSTEM*/ + if (!dir || !*dir) + dir = GNUPG_DEFAULT_HOMEDIR; + + return dir; +} diff --git a/common/signal.c b/common/signal.c index dc026c10f..4e773c4c0 100644 --- a/common/signal.c +++ b/common/signal.c @@ -30,15 +30,17 @@ #include "util.h" +#ifndef HAVE_DOSISH_SYSTEM static volatile int caught_fatal_sig; static volatile int caught_sigusr1; +#endif static void (*cleanup_fnc)(void); +#ifndef HAVE_DOSISH_SYSTEM static void init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign ) { -#ifndef HAVE_DOSISH_SYSTEM # ifdef HAVE_SIGACTION struct sigaction oact, nact; @@ -64,9 +66,10 @@ init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign ) signal (sig, SIG_IGN); } # endif -#endif /*!HAVE_DOSISH_SYSTEM*/ } +#endif /*!HAVE_DOSISH_SYSTEM*/ +#ifndef HAVE_DOSISH_SYSTEM static const char * get_signal_name( int signum ) { @@ -76,7 +79,9 @@ get_signal_name( int signum ) return "some signal"; #endif } +#endif /*!HAVE_DOSISH_SYSTEM*/ +#ifndef HAVE_DOSISH_SYSTEM static RETSIGTYPE got_fatal_signal (int sig) { @@ -106,14 +111,15 @@ got_fatal_signal (int sig) #endif /* __riscos__ */ raise( sig ); } +#endif /*!HAVE_DOSISH_SYSTEM*/ - +#ifndef HAVE_DOSISH_SYSTEM static RETSIGTYPE got_usr_signal (int sig) { caught_sigusr1 = 1; } - +#endif /*!HAVE_DOSISH_SYSTEM*/ void gnupg_init_signals (int mode, void (*fast_cleanup)(void)) diff --git a/common/simple-gettext.c b/common/simple-gettext.c index 4287606e3..b6b851c77 100644 --- a/common/simple-gettext.c +++ b/common/simple-gettext.c @@ -40,7 +40,7 @@ #include <sys/stat.h> #include "util.h" - +#include "sysutils.h" /* The magic number of the GNU message catalog format. */ #define MAGIC 0x950412de diff --git a/common/util.h b/common/util.h index 1159da925..4ab55acb4 100644 --- a/common/util.h +++ b/common/util.h @@ -121,6 +121,10 @@ gpg_error_t b64enc_write (struct b64state *state, gpg_error_t b64enc_finish (struct b64state *state); +/*-- homedir. c --*/ +const char *default_homedir (void); + + /*-- miscellaneous.c --*/ /* Same as asprintf but return an allocated buffer suitable to be diff --git a/g10/ChangeLog b/g10/ChangeLog index 6966bbd7b..bd4b54894 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * gpgv.c, g10.c (main): Use default_hoemdir (). + 2004-12-18 Werner Koch <wk@g10code.com> * gpg.h (map_assuan_err): Define in terms of diff --git a/g10/g10.c b/g10/g10.c index 039074f6b..e02ad0d13 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1264,16 +1264,9 @@ main( int argc, char **argv ) opt.mangle_dos_filenames = 1; opt.use_agent = 1; -#if defined (_WIN32) - set_homedir ( read_w32_registry_string( NULL, - "Software\\GNU\\GnuPG", "HomeDir" )); -#else - set_homedir ( getenv("GNUPGHOME") ); -#endif - if( !*opt.homedir ) - set_homedir ( GNUPG_DEFAULT_HOMEDIR ); + set_homedir ( default_homedir () ); - /* check whether we have a config file on the commandline */ + /* Check whether we have a config file on the commandline */ orig_argc = argc; orig_argv = argv; pargs.argc = &argc; diff --git a/g10/gpgv.c b/g10/gpgv.c index 015736c33..0a97d56b9 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -150,15 +150,8 @@ main( int argc, char **argv ) 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; - } + opt.homedir = default_homedir (); + tty_no_terminal(1); tty_batchmode(1); disable_dotlock(); diff --git a/scd/ChangeLog b/scd/ChangeLog index 68421fc86..ece9abc4f 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * scdaemon.c (main): Use default_homedir(). + 2004-12-18 Werner Koch <wk@g10code.com> * scdaemon.c (main) [W32]: Remove special Pth initialize.. diff --git a/scd/command.c b/scd/command.c index b99fffc09..b41e7aa16 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1261,9 +1261,7 @@ scd_update_reader_status_file (void) log_info ("client pid is %d, sending signal %d\n", pid, signo); -#ifdef HAVE_W32_SYSTEM -#warning Need to implement a notification service -#else +#ifndef HAVE_W32_SYSTEM if (pid != (pid_t)(-1) && pid && signo > 0) kill (pid, signo); #endif diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 49e392e7d..88f393bb1 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -351,17 +351,12 @@ main (int argc, char **argv ) Note that this will also do the pth_init. */ #ifndef HAVE_OPENSC #ifdef USE_GNU_PTH -#ifdef HAVE_W32_SYSTEM - /* For W32 we need pth. */ - pth_init (); -#else err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -#endif #endif /*USE_GNU_PTH*/ #endif /*!HAVE_OPENSC*/ @@ -392,14 +387,9 @@ main (int argc, char **argv ) if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) csh_style = 1; - /* FIXME: Using this homedir option does only make sense when not - running as a system service. We might want to check for this by - looking at the uid or ebtter use an explict option for this */ - opt.homedir = getenv("GNUPGHOME"); - if (!opt.homedir || !*opt.homedir) - opt.homedir = GNUPG_DEFAULT_HOMEDIR; - - /* check whether we have a config file on the commandline */ + opt.homedir = default_homedir (); + + /* Check whether we have a config file on the commandline */ orig_argc = argc; orig_argv = argv; pargs.argc = &argc; diff --git a/sm/ChangeLog b/sm/ChangeLog index 19e7b0e8d..0dcaa9c20 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * gpgsm.c (main): Use default_homedir(). + 2004-12-20 Werner Koch <wk@g10code.com> * call-agent.c (start_agent): Before starting a pipe server start diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 709263cba..935d50474 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -756,16 +756,9 @@ main ( int argc, char **argv) opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/ -#ifdef HAVE_W32_SYSTEM - 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; + opt.homedir = default_homedir (); - /* first check whether we have a config file on the commandline */ + /* First check whether we have a config file on the commandline */ orig_argc = argc; orig_argv = argv; pargs.argc = &argc; -- cgit v1.2.3 From 7b9e5a343f05b51a5e5cb0ea6b92028187849d9f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Dec 2004 12:44:42 +0000 Subject: * homedir.c: New. Use CSIDL_APPDATA for W32 as the default home directory. --- common/ChangeLog | 3 ++- common/homedir.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index 667deb51a..6a381b300 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -4,7 +4,8 @@ (got_fatal_signal) [DOSISH]: Don't build. * simple-gettext.c: Include sysutils.h - * homedir.c: New. + * homedir.c: New. Use CSIDL_APPDATA for W32 as the default home + directory. * Makefile.am (libcommon_a_SOURCES): Add it. (EXTRA_DIST): Removed mkerror and mkerrtok. diff --git a/common/homedir.c b/common/homedir.c index 8b5bc9f05..ab5b1d270 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -21,6 +21,22 @@ #include <config.h> #include <stdlib.h> #include <errno.h> +#include <fcntl.h> + +#ifdef HAVE_W32_SYSTEM +#include <shlobj.h> +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a +#endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_FLAG_CREATE +#define CSIDL_FLAG_CREATE 0x8000 +#endif +#endif /*HAVE_W32_SYSTEM*/ + + #include "util.h" #include "sysutils.h" @@ -36,6 +52,30 @@ default_homedir (void) #ifdef HAVE_W32_SYSTEM if (!dir || !*dir) dir = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir"); + if (!dir || !*dir) + { + char path[MAX_PATH]; + + /* fixme: It might be better to use LOCAL_APPDATA because this + is defined as "non roaming" and thus more likely to be kept + locally. For private keys this is desired. However, given + that many users copy private keys anyway forth and back, + using a system roaming serives might be better than to let + them do it manually. A security conscious user will anyway + use the registry entry to have better control. */ + if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) + { + char *tmp = xmalloc (strlen (path) + 6 +1); + strcpy (stpcpy (tmp, path), "\\gnupg"); + dir = tmp; + + /* Try to create the directory if it does not yet + exists. */ + if (access (dir, F_OK)) + CreateDirectory (dir, NULL); + } + } #endif /*HAVE_W32_SYSTEM*/ if (!dir || !*dir) dir = GNUPG_DEFAULT_HOMEDIR; -- cgit v1.2.3 From 01f3f2515834876e2131d077e34c3cae4f9a2dc0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Dec 2004 19:05:15 +0000 Subject: * preset-passphrase.c (preset_passphrase): Handle --passphrase. * Makefile.am (gpg_preset_passphrase_LDADD): Reorder libs so that pwquery may use stuff from jnlib. Conditionally add -lwsock2 (gpg_protect_tool_LDADD): Ditto. * preset-passphrase.c (main): Use default_homedir(). (main) [W32]: Initialize sockets. * simple-pwquery.c (agent_open) [W32]: Implement for W32. (readline) [W32]: Use recv instead of read. (writen) [W32]: Use send instead of write. (my_stpcpy): Define a stpcpy replacement so that this file continues to be self-contained. (agent_send_all_options) [W32]: Don't call ttyname. * gnupg-badge-openpgp.eps, gnupg-badge-openpgp.jpg: New * gnupg.texi: Add a logo. * sysnotes.texi: New. * gpgsm.c (main): Use default_homedir(). (main) [W32]: Default to disabled CRL checks. * gpgconf-comp.c (get_config_pathname) [DOSISH]: Detect absolute pathnames with a drive letter. --- agent/ChangeLog | 29 +- agent/Makefile.am | 18 +- agent/agent.h | 1 + agent/cache.c | 9 +- agent/command.c | 61 +- agent/gpg-agent.c | 5 + agent/preset-passphrase.c | 293 ++ common/ChangeLog | 14 + common/simple-pwquery.c | 124 +- common/simple-pwquery.h | 3 + doc/ChangeLog | 6 + doc/Makefile.am | 7 +- doc/gnupg-badge-openpgp.eps | 7798 +++++++++++++++++++++++++++++++++++++++++++ doc/gnupg-badge-openpgp.jpg | Bin 0 -> 63450 bytes doc/gnupg.texi | 10 + doc/gpg-agent.texi | 2 +- doc/gpgsm.texi | 2 +- doc/scdaemon.texi | 2 +- doc/sysnotes.texi | 107 + doc/tools.texi | 504 ++- jnlib/w32-afunix.c | 7 +- sm/ChangeLog | 1 + sm/gpgsm.c | 3 + tools/ChangeLog | 5 + tools/gpgconf-comp.c | 6 + 25 files changed, 8986 insertions(+), 31 deletions(-) create mode 100644 agent/preset-passphrase.c create mode 100644 doc/gnupg-badge-openpgp.eps create mode 100644 doc/gnupg-badge-openpgp.jpg create mode 100644 doc/sysnotes.texi diff --git a/agent/ChangeLog b/agent/ChangeLog index cf3569264..d835c8e60 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,8 +1,33 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * preset-passphrase.c (preset_passphrase): Handle --passphrase. + + * Makefile.am (gpg_preset_passphrase_LDADD): Reorder libs so that + pwquery may use stuff from jnlib. Conditionally add -lwsock2 + (gpg_protect_tool_LDADD): Ditto. + + * preset-passphrase.c (main): Use default_homedir(). + (main) [W32]: Initialize sockets. + +2004-12-21 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (libexec_PROGRAMS): Add gpg-preset-passphrase. + (gpg_preset_passphrase_SOURCES, gpg_preset_passphrase_LDADD): New + targets. + * agent.h (opt): New member allow_cache_passphrase. + * cache.c (housekeeping): Check if R->ttl is not negative. + (agent_put_cache): Allow ttl to be negative. + * command.c (parse_hexstring): Allow something to follow the + hexstring. + (cmd_cache_passphrase): New function. + (register_commands): Add it. + * gpg-agent.c: Handle --allow-preset-passphrase. + * preset-passphrase.c: New file. + 2004-12-21 Werner Koch <wk@g10code.com> * gpg-agent.c (main): Use default_homedir(). - * protect-tool.c (main): Ditto. - + * protect-tool.c (main): Ditto. 2004-12-20 Werner Koch <wk@g10code.com> diff --git a/agent/Makefile.am b/agent/Makefile.am index 6f3ea70d2..4cedbe74e 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -19,7 +19,7 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = gpg-agent -libexec_PROGRAMS = gpg-protect-tool +libexec_PROGRAMS = gpg-protect-tool gpg-preset-passphrase AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl @@ -53,8 +53,20 @@ gpg_protect_tool_SOURCES = \ protect.c \ minip12.c minip12.h -gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \ - ../common/libcommon.a ../common/libsimple-pwquery.a \ +gpg_protect_tool_LDADD = ../common/libsimple-pwquery.a \ + ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ +if HAVE_W32_SYSTEM +gpg_protect_tool_LDADD += -lwsock32 +endif +gpg_preset_passphrase_SOURCES = \ + preset-passphrase.c + +gpg_preset_passphrase_LDADD = ../common/libsimple-pwquery.a \ + ../jnlib/libjnlib.a ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ +if HAVE_W32_SYSTEM +gpg_preset_passphrase_LDADD += -lwsock32 +endif diff --git a/agent/agent.h b/agent/agent.h index 241b37b05..7d6bf9f47 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -63,6 +63,7 @@ struct { int ignore_cache_for_signing; int allow_mark_trusted; + int allow_preset_passphrase; int keep_tty; /* don't switch the TTY (for pinentry) on request */ int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ } opt; diff --git a/agent/cache.c b/agent/cache.c index 8017b1414..b6762edd0 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -39,7 +39,7 @@ struct cache_item_s { ITEM next; time_t created; time_t accessed; - int ttl; /* max. lifetime given in seonds */ + int ttl; /* max. lifetime given in seonds, -1 one means infinite */ int lockcount; struct secret_data_s *pw; char key[1]; @@ -88,7 +88,8 @@ housekeeping (void) /* first expire the actual data */ for (r=thecache; r; r = r->next) { - if (!r->lockcount && r->pw && r->accessed + r->ttl < current) + if (!r->lockcount && r->pw + && r->ttl >= 0 && r->accessed + r->ttl < current) { if (DBG_CACHE) log_debug (" expired `%s' (%ds after last access)\n", @@ -118,7 +119,7 @@ housekeeping (void) Expire old and unused entries after 30 minutes */ for (rprev=NULL, r=thecache; r; ) { - if (!r->pw && r->accessed + 60*30 < current) + if (!r->pw && r->ttl >= 0 && r->accessed + 60*30 < current) { if (r->lockcount) { @@ -194,7 +195,7 @@ agent_put_cache (const char *key, const char *data, int ttl) log_debug ("agent_put_cache `%s'\n", key); housekeeping (); - if (ttl < 1) + if (ttl == 1) ttl = opt.def_cache_ttl; if (!ttl) return 0; diff --git a/agent/command.c b/agent/command.c index 9fc08e211..dc8a4a158 100644 --- a/agent/command.c +++ b/agent/command.c @@ -141,7 +141,7 @@ parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len) /* parse the hash value */ for (p=string, n=0; hexdigitp (p); p++, n++) ; - if (*p) + if (*p != ' ' && *p != '\t' && *p) return set_error (Parameter_Error, "invalid hexstring"); if ((n&1)) return set_error (Parameter_Error, "odd number of digits"); @@ -741,6 +741,64 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) return map_to_assuan_status (rc); } +/* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <passwd> + + Set the cached passphrase/PIN for the key identified by the keygrip + to passwd for the given time, where -1 means infinite and 0 means + the default (currently only a timeout of -1 is allowed, which means + to never expire it). If passwd is not provided, ask for it via the + pinentry module. */ +static int +cmd_preset_passphrase (ASSUAN_CONTEXT ctx, char *line) +{ + int rc; + unsigned char grip[20]; + char *grip_clear = NULL; + char *passphrase = NULL; + int ttl; + + if (!opt.allow_preset_passphrase) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + rc = parse_keygrip (ctx, line, grip); + if (rc) + return rc; + + /* FIXME: parse_keygrip should return a tail pointer. */ + grip_clear = line; + while (*line && (*line != ' ' && *line != '\t')) + line++; + if (!*line) + return map_to_assuan_status (gpg_error (GPG_ERR_MISSING_VALUE)); + *line = '\0'; + line++; + while (*line && (*line == ' ' || *line == '\t')) + line++; + + /* Currently, only infinite timeouts are allowed. */ + ttl = -1; + if (line[0] != '-' || line[1] != '1') + return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED)); + line++; + line++; + while (!(*line != ' ' && *line != '\t')) + line++; + + /* If there is a passphrase, use it. Currently, a passphrase is + required. */ + if (*line) + passphrase = line; + else + return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED)); + + rc = agent_put_cache (grip_clear, passphrase, ttl); + + if (rc) + log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc)); + + return map_to_assuan_status (rc); +} + /* SCD <commands to pass to the scdaemon> @@ -837,6 +895,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "PKDECRYPT", cmd_pkdecrypt }, { "GENKEY", cmd_genkey }, { "GET_PASSPHRASE", cmd_get_passphrase }, + { "PRESET_PASSPHRASE", cmd_preset_passphrase }, { "CLEAR_PASSPHRASE", cmd_clear_passphrase }, { "GET_CONFIRMATION", cmd_get_confirmation }, { "LISTTRUSTED", cmd_listtrusted }, diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 2c3d834a5..e76623f75 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -89,6 +89,7 @@ enum cmd_and_opt_values oIgnoreCacheForSigning, oAllowMarkTrusted, + oAllowPresetPassphrase, oKeepTTY, oKeepDISPLAY }; @@ -141,6 +142,8 @@ static ARGPARSE_OPTS opts[] = { N_("do not use the PIN cache when signing")}, { oAllowMarkTrusted, "allow-mark-trusted", 0, N_("allow clients to mark keys as \"trusted\"")}, + { oAllowPresetPassphrase, "allow-preset-passphrase", 0, + N_("allow presetting passphrase")}, {0} }; @@ -392,6 +395,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break; + case oAllowPresetPassphrase: opt.allow_preset_passphrase = 1; break; + default: return 0; /* not handled */ } diff --git a/agent/preset-passphrase.c b/agent/preset-passphrase.c new file mode 100644 index 000000000..6a9f07a3e --- /dev/null +++ b/agent/preset-passphrase.c @@ -0,0 +1,293 @@ +/* preset-passphrase.c - A tool to preset a passphrase. + * 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 + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <sys/stat.h> +#include <unistd.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif +#ifdef HAVE_W32_SYSTEM +#include <windows.h> /* To initialize the sockets. fixme */ +#endif + +#define JNLIB_NEED_LOG_LOGV +#include "agent.h" +#include "minip12.h" +#include "simple-pwquery.h" +#include "i18n.h" +#include "sysutils.h" + + +enum cmd_and_opt_values +{ aNull = 0, + oVerbose = 'v', + oPassphrase = 'P', + + oPreset = 'c', + oForget = 'f', + + oNoVerbose = 500, + + oHomedir, + +aTest }; + + +static const char *opt_homedir; +static const char *opt_passphrase; + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oVerbose, "verbose", 0, "verbose" }, + { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, + { oPreset, "preset", 256, "preset passphrase"}, + { oForget, "forget", 256, "forget passphrase"}, + + { oHomedir, "homedir", 2, "@" }, + {0} +}; + + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "gpg-preset-passphrase (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: + p = _("Usage: gpg-preset-passphrase [options] KEYGRIP (-h for help)\n"); + break; + case 41: + p = _("Syntax: gpg-preset-passphrase [options] KEYGRIP\n" + "Password cache maintenance\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 + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); +#endif +#endif +} + + +static gpg_error_t +map_spwq_error (int err) +{ + switch (err) + { + case 0: + return 0; + case SPWQ_OUT_OF_CORE: + return gpg_error_from_errno (ENOMEM); + case SPWQ_IO_ERROR: + return gpg_error_from_errno (EIO); + case SPWQ_PROTOCOL_ERROR: + return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); + case SPWQ_ERR_RESPONSE: + return gpg_error (GPG_ERR_INV_RESPONSE); + case SPWQ_NO_AGENT: + return gpg_error (GPG_ERR_NO_AGENT); + case SPWQ_SYS_ERROR: + return gpg_error_from_errno (errno); + case SPWQ_GENERAL_ERROR: + default: + return gpg_error (GPG_ERR_GENERAL); + } +} + + +static void +preset_passphrase (const char *keygrip) +{ + int rc; + char *line; + /* FIXME: Use secure memory. */ + char passphrase[500]; + + if (!opt_passphrase) + { + rc = read (0, passphrase, sizeof (passphrase) - 1); + if (rc < 0) + { + log_error ("reading passphrase failed: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + passphrase[rc] = '\0'; + line = strchr (passphrase, '\n'); + if (line) + { + line--; + if (line > passphrase && line[-1] == '\r') + line--; + *line = '\0'; + } + + /* FIXME: How to handle empty passwords? */ + } + + rc = asprintf (&line, "PRESET_PASSPHRASE %s -1 %s\n", keygrip, + opt_passphrase? opt_passphrase : passphrase); + if (rc < 0) + { + log_error ("caching passphrase failed: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + if (!opt_passphrase) + wipememory (passphrase, sizeof (passphrase)); + + rc = map_spwq_error (simple_query (line)); + if (rc) + { + log_error ("caching passphrase failed: %s\n", gpg_strerror (rc)); + return; + } + + wipememory (line, strlen (line)); + free (line); +} + + +static void +forget_passphrase (const char *keygrip) +{ + int rc; + char *line; + + rc = asprintf (&line, "CLEAR_PASSPHRASE %s\n", keygrip); + if (rc < 0) + { + log_error ("clearing passphrase failed: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + free (line); +} + + +int +main (int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + int cmd = 0; + const char *keygrip = NULL; + + set_strusage (my_strusage); + log_set_prefix ("gpg-preset-passphrase", 1); + + /* Try to auto set the character set. */ + set_native_charset (NULL); + +#ifdef HAVE_W32_SYSTEM + /* Fixme: Need to initialize the Windows sockets: This should be + moved to another place and we should make sure that it won't get + doen twice, like when Pth is used too. */ + { + WSADATA wsadat; + WSAStartup (0x202, &wsadat); + } +#endif + + i18n_init (); + + opt_homedir = default_homedir (); + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* (do not remove the args) */ + while (arg_parse (&pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: opt.verbose++; break; + case oHomedir: opt_homedir = pargs.r.ret_str; break; + + case oPreset: cmd = oPreset; break; + case oForget: cmd = oForget; break; + case oPassphrase: opt_passphrase = pargs.r.ret_str; break; + + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit(2); + + if (argc == 1) + keygrip = *argv; + else + usage (1); + + if (cmd == oPreset) + preset_passphrase (keygrip); + else if (cmd == oForget) + forget_passphrase (keygrip); + else + log_error ("one of the options --preset or --forget must be given\n"); + + agent_exit (0); + return 8; /*NOTREACHED*/ +} + + +void +agent_exit (int rc) +{ + rc = rc? rc : log_get_errorcount(0)? 2 : 0; + exit (rc); +} diff --git a/common/ChangeLog b/common/ChangeLog index 6a381b300..3e060258a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,17 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * simple-pwquery.c (agent_open) [W32]: Implement for W32. + (readline) [W32]: Use recv instead of read. + (writen) [W32]: Use send instead of write. + (my_stpcpy): Define a stpcpy replacement so that this file + continues to be self-contained. + (agent_send_all_options) [W32]: Don't call ttyname. + +2004-12-21 Marcus Brinkmann <marcus@g10code.de> + + * simple-pwquery.h (simple_query): Add prototype. + * simple-pwquery.c (simple_query): New function. + 2004-12-21 Werner Koch <wk@g10code.com> * signal.c (got_fatal_signal, got_usr_signal) diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index e7f992a88..0b70ddecc 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -1,5 +1,5 @@ /* simple-pwquery.c - A simple password query cleint for gpg-agent - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -40,6 +40,10 @@ #ifdef HAVE_LOCALE_H #include <locale.h> #endif +#ifdef HAVE_W32_SYSTEM +#include "../jnlib/w32-afunix.h" +#endif + #define SIMPLE_PWQUERY_IMPLEMENTATION 1 #include "simple-pwquery.h" @@ -63,6 +67,25 @@ #endif + + + + +#ifndef HAVE_STPCPY +static char * +my_stpcpy(char *a,const char *b) +{ + while( *b ) + *a++ = *b++; + *a = 0; + + return (char*)a; +} +#define stpcpy(a,b) my_stpcpy((a), (b)) +#endif + + + /* Write NBYTES of BUF to file descriptor FD. */ static int writen (int fd, const void *buf, size_t nbytes) @@ -72,7 +95,11 @@ writen (int fd, const void *buf, size_t nbytes) while (nleft > 0) { - nwritten = write( fd, buf, nleft ); +#ifdef HAVE_W32_SYSTEM + nwritten = send (fd, buf, nleft, 0); +#else + nwritten = write (fd, buf, nleft); +#endif if (nwritten < 0) { if (errno == EINTR) @@ -102,7 +129,11 @@ readline (int fd, char *buf, size_t buflen) while (nleft > 0) { +#ifdef HAVE_W32_SYSTEM + int n = recv (fd, buf, nleft, 0); +#else int n = read (fd, buf, nleft); +#endif if (n < 0) { if (errno == EINTR) @@ -182,8 +213,10 @@ agent_send_all_options (int fd) } dft_ttyname = getenv ("GPG_TTY"); +#ifndef HAVE_W32_SYSTEM if ((!dft_ttyname || !*dft_ttyname) && ttyname (0)) dft_ttyname = ttyname (0); +#endif if (dft_ttyname && *dft_ttyname) { if ((rc=agent_send_option (fd, "ttyname", dft_ttyname))) @@ -259,9 +292,6 @@ agent_send_all_options (int fd) static int agent_open (int *rfd) { -#ifdef HAVE_W32_SYSTEM - return SPWQ_NO_AGENT; /* FIXME */ -#else int rc; int fd; char *infostr, *p; @@ -286,7 +316,7 @@ agent_open (int *rfd) strcpy (p, infostr); infostr = p; - if ( !(p = strchr ( infostr, ':')) || p == infostr + if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr || (p-infostr)+1 >= sizeof client_addr.sun_path ) { #ifdef SPWQ_USE_LOGGING @@ -296,7 +326,7 @@ agent_open (int *rfd) } *p++ = 0; - while (*p && *p != ':') + while (*p && *p != PATHSEP_C) p++; prot = *p? atoi (p+1) : 0; if ( prot != 1) @@ -306,8 +336,13 @@ agent_open (int *rfd) #endif return SPWQ_PROTOCOL_ERROR; } - - if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) + +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else + fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif + if (fd == -1) { #ifdef SPWQ_USE_LOGGING log_error ("can't create socket: %s\n", strerror(errno) ); @@ -321,7 +356,12 @@ agent_open (int *rfd) len = (offsetof (struct sockaddr_un, sun_path) + strlen(client_addr.sun_path) + 1); - if (connect (fd, (struct sockaddr*)&client_addr, len ) == -1) +#ifdef HAVE_W32_SYSTEM + rc = _w32_sock_connect (fd, (struct sockaddr*)&client_addr, len ); +#else + rc = connect (fd, (struct sockaddr*)&client_addr, len ); +#endif + if (rc == -1) { #ifdef SPWQ_USE_LOGGING log_error ( _("can't connect to `%s': %s\n"), infostr, strerror (errno)); @@ -353,12 +393,11 @@ agent_open (int *rfd) *rfd = fd; return 0; -#endif } /* 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 + 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 * @@ -505,3 +544,64 @@ simple_pwquery (const char *cacheid, spwq_free (pw); return result; } + + +/* Perform the simple query QUERY (which must be new-line and 0 + terminated) and return the error code. */ +int +simple_query (const char *query) +{ + int fd = -1; + int nread; + char response[500]; + int rc; + + rc = agent_open (&fd); + if (rc) + goto leave; + + rc = writen (fd, query, strlen (query)); + if (rc) + goto leave; + + /* get response */ + nread = readline (fd, response, 499); + if (nread < 0) + { + rc = -nread; + goto leave; + } + if (nread < 3) + { + rc = SPWQ_PROTOCOL_ERROR; + goto leave; + } + + if (response[0] == 'O' && response[1] == 'K') + /* OK, do nothing. */; + else if ((nread > 7 && !memcmp (response, "ERR 111", 7) + && (response[7] == ' ' || response[7] == '\n') ) + || ((nread > 4 && !memcmp (response, "ERR ", 4) + && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) ) + { + /* 111 is the old Assuan code for canceled which might still + be in use by old installations. 99 is GPG_ERR_CANCELED as + used by modern gpg-agents; 0xffff is used to mask out the + error source. */ +#ifdef SPWQ_USE_LOGGING + log_info (_("canceled by user\n") ); +#endif + } + else + { +#ifdef SPWQ_USE_LOGGING + log_error (_("problem with the agent\n")); +#endif + rc = SPWQ_ERR_RESPONSE; + } + + leave: + if (fd != -1) + close (fd); + return rc; +} diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h index 5947c42b5..c7ebf9401 100644 --- a/common/simple-pwquery.h +++ b/common/simple-pwquery.h @@ -57,6 +57,9 @@ char *simple_pwquery (const char *cacheid, const char *description, int *errorcode); +/* Perform the simple query QUERY (which must be new-line and 0 + terminated) and return the error code. */ +int simple_query (const char *query); #define SPWQ_OUT_OF_CORE 1 #define SPWQ_IO_ERROR 2 diff --git a/doc/ChangeLog b/doc/ChangeLog index 9a9e213a3..41d6b811b 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,9 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * gnupg-badge-openpgp.eps, gnupg-badge-openpgp.jpg: New + * gnupg.texi: Add a logo. + * sysnotes.texi: New. + 2004-11-05 Werner Koch <wk@g10code.com> * debugging.texi (Common Problems): Curses pinentry problem. diff --git a/doc/Makefile.am b/doc/Makefile.am index d44765a2e..988bbf849 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2002 Free Software Foundation, Inc. +# Copyright (C) 2002, 2004 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -18,11 +18,14 @@ ## Process this file with automake to produce Makefile.in +EXTRA_DIST = gnupg-badge-openpgp.eps gnupg-badge-openpgp.jpg + info_TEXINFOS = gnupg.texi gnupg_TEXINFOS = \ gpg.texi gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi \ - tools.texi debugging.texi glossary.texi contrib.texi gpl.texi + tools.texi debugging.texi glossary.texi contrib.texi gpl.texi \ + sysnotes.texi DISTCLEANFILES = gnupg.tmp gnupg.ops diff --git a/doc/gnupg-badge-openpgp.eps b/doc/gnupg-badge-openpgp.eps new file mode 100644 index 000000000..8edbaa617 --- /dev/null +++ b/doc/gnupg-badge-openpgp.eps @@ -0,0 +1,7798 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1.10 by Peter Kirchgessner +%%Title: /home/wk/gnupg-badge-openpgp.eps +%%CreationDate: Thu May 4 10:58:15 2000 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 14 14 250 250 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +14.173228 14.173228 translate +% Translate to begin of first scanline +0.000000 235.680000 translate +235.680000 -235.680000 scale +% Image geometry +491 491 8 +% Transformation matrix +[ 491 0 0 491 0 0 ] +% Strings to hold RGB-samples per scanline +/rstr 491 string def +/gstr 491 string def +/bstr 491 string def +{currentfile /ASCII85Decode filter /RunLengthDecode filter rstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter gstr readstring pop} +{currentfile /ASCII85Decode filter /RunLengthDecode filter bstr readstring pop} +true 3 +%%BeginData: 538041 ASCII Bytes +colorimage +JcFO*s8Mfn"T8)mr;QTn!<2ut"TA>srVl]o#6">np\=R`kPk_ar;-9cq"j^aoEFs_q>:*fjo>>Z +!W;rhs8W'#rVlirq>^Kos8;oos87HJgAc[~> +JcFL)!<2urs8;lpqu?]qrr!0&q>UBnrVuoss8N#ss8W)rs82fqr;c`nq%EAjmd0/tgXXWn_SEgo +ZEUO:YkkX)Y8FOM['mHQ\\5o'cI:M)kN_R0q"aXYrr;urrrE&prrW/srqlWsr;HWprr2p#rr<#t +rpKg]rdk+4s*t~> +JcFa0"T.i_q"sO[s8Dro!;?Bir;R!!qYU6is8Mrr+8l!3q=saWna,K$j58S8^UCAGU7%7*Kn+Sq +EGoZ/AGTg9@38uiAnYmnDfpM`Ng?H@\\QG<gtglHn+-&@p@e@YrVcNk#lal&qtp3crVcTm$NBu% +qtp6dqtp?jq>^Knq>5aCk5Tr~> +JcFR+s8E)trr2`nrr2co"T8;us8W)trr;usr;Qcqp\u$-q"*n9hqQc6eC2mtg>:ZBhV[8OjQ63p +)<0W6i8EMMhW*VRhVHr>f@JI%g#2/eoCVnNrrE&rs8W)rs8W'"s8N#qrrDuqs8Mutr;HVGs4[L'~> +JcFC&s8E#urVlZn#lXZ!rql]lrr;usrr<#t!<)iqs8;oqrqnJIp@@>&f$24J['-I,VP9f\Vl6Jg +US=NZV5C#`USOZ\USOcaV59u`US=Z`USFW\rhBgsVldAAajAYun+QbW')VV*rVZQjrVl`orr)ip +qYL3jrquotrVlcq"9/?"qsOL^rdk+3s*t~> +JcFa0"TA2nqu-$as8<0"qY^<fs8;]ms82oprVl\#qY9dSmHj-%j5/D.]sFZ0Q&:*7Dej$!B4u$l +A78nS@:3GG=B\g1=B\g4>$P37=B\j7?sm>MA7oUmEHZegQ(b4c_U.#oio]LlnauMLq>1'gs8W)u +r;$0erVlfkrrW/sp\t'hrV6EkrIP"-s*t~> +JcFa0s8E#rrr)usqt^3c!W2fjrri?!q>C0irW)ops8MutrV$6qq"*b.g>h5mi=b//hq$?0f@\^+ +e_Jm6hVdGUk5"<bjlGI\i83;Ff@/*pf%Sj2hVR)Dgu%&Lk2tdcjQuX?pAY0ms8Dros8W'$r;6Ek +rqcZprqcWrrqu]lqZ?Tjrdk+4s*t~> +JcF^/!<2Qhs8;urrr)isrVc`trVZWnrr;rqs$m"aq"jg\pup\gbe^]cSu/<XTqS3TUnjofX/rA% +WNib9[^`r_^;Ik*_ns=._n<Xn\[T#SZ`^=+Vl?_rVlH\lU7e3SUAghtUSkH9ce@ILq>0s`qY^Bn +rquforWN2trVcZnrqHHmrdk+%s*t~> +JcFL)rr)ls#6"GrqYL*dr;?Zrr;$?mrVZ\#rr)]`lfmEeg;LM%SW8)7?tE\L>$>-7?tF+jCi*p$ +BPhU(E,p)DG^b*lIXlltIX63_FEMSDEGT<"@qB:`?t!GI=]ed/>$PBAASus\UU7ngj6#Uln+QYU +r:Bpkrr)iqs8Doorri5qqYU5Bs4dR(~> +JcFa0$3'htr;?Qnr;6<hp]C9grqcZprr;m!q"F[brq-3sr:K49h:gN7gY_tf"68S2o)A=_ptYlb +p[7P?m-3WhhWa7cjQ,@Xg==g/hWFCss8Douqu6Tds8W)ur;QTmq#LDFs6'E4~> +JcF-t"TA8rrVl`p"oS5rrr<#trW)lqrVua7q!?nhah5*_Vkg)`VPU/dVlHo-]>;M5f&>uepAX^h +p@n@XqYU-bq#C0ip]1'fp*o\/q>C'UhU9H_^q6tVW2-5_SXuOLTq@pPWj97Xf]2JqqYL-dqu6Tp +qu6Nn!W;qJs3:Ro~> +JcFO*#6"Gqqtp?jrqccnqtpBkqu6ZprVnDFq"XUWo^V84iQo6CT9"_LDJEfp@p`ME>$G?FCN4ZZ +Q_LRf[^EKK['[7?[K3kKqRljAs1A?DrjjPe\@K2ZWgAWkH$!q9?<0s);c-S!?=IDVDg?ttTWu;_ +io]Oomdp5NrV$6krqHEnrVQTmJcFL)J,~> +JcFa0"oeDpr;?Qks8W)tr;ZclrrrE%rr2cnqu6j!p[7G0h>Z7:hq?Z:hW*njo'HAWrr)6a!<2Ti +&b"f=hV-Z>hr*DLi8iqUlLb&Nrseo'r;6Bequ$Bhr;-Elr;Qs"qtU!arqZQrrqu]nJcFp5J,~> +JcF!ps8Muq!;ucp$N0l$qt&q!ah+s[rLjRqUSb&r]Z8FQp%JC["o8&pqYL*gr;linrr*'!r;?Hg +q>C3grVR*(r;$-_qY^9krVH?brq@T'hTW^CZE:(,WMZGaTq\<UY.r69k3r3DrVulor;HTlrVc`u +rVlisr;M9Iec1.~> +JcFO*#6"GrqYU6inc's7qt^$Wna,Dj_Q&uXHu3>#?s[>SCN+NNO-lTP]=bbd\@T>c^;'Z_$,OEo +`5KR3_ns:d`VmaQ`<sJq]Y2"n^;7Or]Df;a\#l<^Is5mI@qB(S>#nU'>\8;AT<uJaj6,n&p%J.T +qYpK]rs/N"qYL*drV_<IjSs`~> +JcF^/rr2Zls83&tqYL-frq6:$rT`1fdb*I7hV-cJn+ZeSs8W#sqZ-Wps8W)trrN-!rVcconbrRe +rr)j&rqu`nr;?NlrqQKsp\"%@k2cO$#isq!g=Y*9meHVX#QFZ#s8Murrql]uqt^'brdk+(s*t~> +JcFR+s8N&s"8r,rrqQKsrr)flr;6Kl)u0C$iQ\s8V5C5hV4sch\\lY_p%J(Np%eOarVlisrr2p% +rr)fprr;uqrrN-!nbrOer;Zfqs8E-!r;?Nmr[@[>p\+:Qo$Y^t\$)g.US+<QT;&0_[`dClq#(*h +rr<#sr;Q`rrr<#trr;osrqcWrrr;tKs5<p-~> +JcFI(rVcBg,lRW5na,AnhpB$4NI,PYBk(IO>%MVuLU+A"]">_p`lQ<GaN4A"s25>b`5KX7a2lBG +bK\;Un]E`1`5Tj@aiDB=`Pod8`lH0@a2>[)\[A`FMgoe]>ujj%<a/d7AScXJUUJM+kj7^.q"sm` +rp]pgrVQKg!W2hHs5s?3~> +JcF7"s83-!rr2imqYU6grseqdgZ.2IgXss'fB;Vrqu6ZpoDejhqu?]qqu?Kjrqu`l!<)`ns8E6& +rr;urr;H<g&H)%aj5ShEg>(QGio&M>h":CA!<.QLcMrC~> +JcFa0s8N#rs8;oo"8r,rrqQL&rqu]mr:]gFcEEt?Undpe$a$hYdba6\q"OU[r;6HprVZTlr;uur +rr)lsrr)fqrq-6hrX/W(rr)cnrVliqrql]rr;Q]qs8F2?rr2lno]b,X]sau<V5'c`V50cVX2j8o +p&4jgrVlfps8MutrVl]prVc]rs8ITLh>`!~> +JcF^/s8D<a)uK?rgsW[!E*lpR=^GQICj(`&TW>N3[^iu^^AYkN`5BR5`r3p\_ns=0a8X*Y`W+$Z +bQ#cdbPK?[aSa'[`l,jq`;[dXaN=G*.EffN`Poj8_SEq%^V@CgVj`WfCL:1F<`rg>Anc+4TY]@@ +n+$#BqYU0es8W&ms8W#tqu6Emqu)*GkPp&~> +JcF7"!ri,qq#:cleC3"-hVmJSlhCAVq>^Ko"T%ogq>C6kl2M:kqYU-dqYU-equ$?hqu-Kirr`9# +s8Muo$N0o$qYC!crr)iprr2fp%fQ4kiSE;Lk2YC\jP8AWlMgk`JcF[.J,~> +JcFa0!ri/rqYgHnq>V3/r;6<bkKg<.USa]YUo(N=e(a-\q#:6lrW)onrr`8us8Doo#Q+Ass8N#r +r:p6jrWW?$s8N&tq#:HqrVZWnrW<&us8DosrVlg$rVZWos8N#rrVuj5rVZ<MgsX!@UnFKXT:VdP +U9)Z-q=sgbqu6Wo!;ufos8Mio!<.QLjo9i~> +JcF^/s8Dcnr;APNq"FFSo'bl(bcHA6A7/D8;,^qJM3OpK]u7n.a2Q!;aN)9=_o':)_Sa70`l?'= +a2Z*;`5V\prQ#u$aN)9?`Q,s<`Q6'?`lQ0Aa2Z-<`lH3Ba3)TJrlGMjb0%`B_o0R7`Q8"us2Z.s +\#GgUK5t=#='K$<@VBUtJZ-`Gi9'Fuq"t$grri;tqu-Kis8W&sqZ-SGs6'E4~> +JcG!7!<)os!<2lq%0$2&qu6WqrVuoqr;6El$iKVbhr!8Cf\Pf]rV6C#rqlNcp%A+Uqu$Bkqu?]q +!;uKhr;I0'rqucnrqucnrqucnrqcQerqH?grqQL%p[I>)jQZ$slKIL#q"k"&rVl]os8N&urr<#t +s8Dups8ITLjSs`~> +JcG!7!<)os!ri6"r;H]pr;Rl;s8W)urr;usqWQ>A[\BOlUo1N8cemsWq"ad`rr)ihrrN-!rVcs" +rr;rprqlZls8Duss8N)unGi%Xqu?Kks8Dus/,]5>q"!\"a0VY9T:MLCStr[2g$SV4qu6Wps8;lq +qYpHkrr)irrVucprdk+1s*t~> +JcG!7!<)os!<2cn-N*c;q"=FYq>^3VjPeh0VN64@ARf+YD1.;6W3WtF]Y;4u_oBd?rQGboaN2B@ +`P]U4`Q#p=b0'P$qo08i`l?!;`Q#m:`Q#m:`Q#m:aNXV-rQP5_!6FuYq90i'aM59p\@]>YWg8E[ +?rp<(9i"\pFHE]NiTp%2qu6`ps8Mlp!<%KKir=N~> +JcFm4%fZG+rr)inrqu]kqYL!dq>UQ[f$i=Oh?)p4rq$-or;69`p%S@\rqu]nqZ-QhrrW2tr;QTn +r:Bpfr;QTjr;6Kkr;?Q^rsSenkj@Qmi83/<de<J9%/g,)s8Dusqu6QorVhBJjo9i~> +JcFm4#6+T#rr)ipp\u94qu$9^ilA3uVPU)aYeefImJ-_UqYgBiqY^<krqcZlrqQNkr;QZprp0Ra +rr2rrrr<#qrWN9#rr<#rrqlZnru(e7s8;Wfp[I=s`jDY?T:;FGV5UKHk5"lMr;I-$r;Zfprr;op +r;QWmJcFj3J,~> +JcFm41&h.Nrr)ios8W&rqYBgXp@Ih?m,?C&R!NLY?s?fHHB+W$]Z7t3aiDB<_Sa:1`lQ=%bl>i] +aSX-Xbl5c_a:lS7`l?!;`Q#m:`Q#m:`Q#m:aNXY.rQP8`r5\r^bfp(/rlk8^,fn$F`l?'A`kfO( +YG$r!@T-,u9iPG5FFUO9iT]e(q"t$iqu)*GgAc[~> +JcFs6s8Mus$i]trqYL*gqYBs^rr)j&qsik'f@nm9oBcMWrquctrquTkq#C-mqu$Hkqt'U`qssXb +rqcZorqZKkroX4ho]tGjh:p]AiSs.mr;Q^(rr;utrqH?fq"t'hJcFa0J,~> +JcFs6s8Mio!WE#qrttY3q<5u3Yc4:iX0KLom.'lLr;-*YrVuiqquZirrVc`qrrE&trVulms8DrV +s8)]rs8N#ns8;lnrVZTnq^MIBrr)ZjrVcZkqt\se\?Dj+T:r!X[_p_bp\aabrVuops8Vuqs8;lo +rr.KKkPp&~> +JcFs6s8Moq-iWu9p%\=ZrV6$Pho2.?G\gboAS-+GTrbc@aN;THdEg+^aiDEA`qm[S_[sf,aNDcR +cdC(bc-4>ScdC/>ci;8ibl5a!aNDTF`lQ0@`lQ0@`lQ0@`lQ0>`V[[NaSs?]aSs0\`P]Um_'[.F +c-4ATbf[rB^q[Us]"5DDNdGYQ=]SX1BRGrEb1YqCqYC*irdk+)s*t~> +JcG!7s8;rsrVm$"q=sjdqYpicdbE^CjlGP%qu6Zqr;QitrVl9c!W;ioq>^?lquZlpq#:$eq#C0g +qsXF_rql`orqZKkrq??lrr2irrqud"rqc?[oD&7`$N',Jjl5F^g=G*Hqu6j!q"ssdrdk+/s*t~> +JcG!7s8;rspAb0l%eoqpaJGZ)U7nEdcLCT&rVm0&r;?HjqYU3hrVlfprVliq"8r,rrqcWrrr;uV +s8)`cs8;itrVlfqr<N8tr;-9frVcNk(A[^tkKL6.UnOZ`Unt98lM:AVrVliqrVm$"r;?HkJcFp5 +J,~> +JcG!7s8;rsqYq]:qY'RPn`K&iVgEAm@:3P[MQ!_]]XkksaNW#[eBQ1\rltJds2Y2[rPefS$cU-* +aND`Ocd0k\bl5`bc2Q&hc2Preb500gb/h`Hb/h`Hb/h`Hb/jFupr<?TrPniUs24fO-H43Wd*9_T +aMu9AaN)?Baj&,P_n)^uAQ2W+>[_/YH^i7<lL"3=qZ$To!;h?Ik5Tr~> +JcFg2s8<'"rql]lrs.Z@hqcf0jneoT"oA,pqtp<jrqZQsrVZTmrr)lsrqHF#rquZhq=sa\qtp<j +q>UHoo)/C^rVZWns8W#rr;?Hh!VuTkr;Z^&s8;flqt^$]p\k'frsJJ_hq[)GhrikGoDJUjr:]XX +JcFa0J,~> +JcFg2s8Dut(B+:4rqu<SdB0%:W2H]8g[b16qYU'crVm-%r;?HkrVc`prrE#rrW<&trqHBjrq6<i +rr)d*rr;utrr;utrr;utrr;ugs8W)crs&K$rVlcorql^:qtg9eoBu+n\>uF#TqJ?[TuZX!rVlis +rUp3ir;HPEs5s?3~> +JcFg2s8Dut)Z9X8qX`RiUi^!PA7TM4U:S1R^VIOu`l?*BrQH/&b0%uScHXPWbfn5PaN2NKccs\V +aMu3<_u@XT`r='W`r3mT_[j`-b08#Pb08#Pb08#Pb09e+rlG)You6^G1!%VdcHXSTa2Z'9`Q63G +bfe8P`l>j(Y,mFu?s-Q3;dj6PQH.eEo)&Iequ?]pqtg8Bs6'E4~> +JcFm4s8Dcn#P6g&hVdGXo)&FeqYpKpr;HNlquH`qs8N#pr;Z`ss8N#q!<2fo"9/5qqu-Hmrq?@' +r;QWnr;QWnr;QWnr;QWkq>L3jr;Q]ms8N#sr;QTlq>^6iq#pWor;?Qnrs8T!qYU6ir;6EersA2Y +h;78PkgRiNJcFO*J,~> +JcFm4s8Dut'`S(.qtTL-[%X1aUp%esnbr@bqtL'hs8Mrr#QFc&rr)iqs8)]prVZZnrVuitrVlQk +r;Q`ps83E+rr;utrr;utrr;utrr;ujs82f^rrE&trrW/srVc`rrr2rtrr<!/q<uqMYbIbbTrjr^ +e+<J4rr*&trVlcpJcFp5J,~> +JcFm4s8Dut)Z00sn`nf>NcAN/=(6TL[)0c(a26!Fc-"/Mr5o/`b/_TDrlY/_rQ>/d$I-f;`l5j3 +_8F10rPnZP!5n`R!QN4Ib5]Q]`r!aR`r*pSaq)\>aiMQDb/hWBaND`Nb/aM(s2Ptr_RQY-F(8*E +='BBLE2h:Fl1=]IqYpNoJcFm4J,~> +JcFm4!;u]n#4C=!e(EgTqu6m"r;Q`rqY^<l"TA2mq>C6hs7uforr;fnrqlcnrVZ]poDejirqufn +')_b.s8N&ts8N&ts8N&ts8N&to)JUdq"tHtr;?QorVc`orVZZqr;QWrqtg0gq>C7!q!?klhWNtU +iUm$I!rVckJcFp5J,~> +JcFm4!;uir&GGqcftOJ]TVoEJiq33Ks8Dor"9/)ks8;fsrr<#trr;osrql`prqQNnrqlWor;?Nl +rql`Xrr)crrr)]mrr;rrs8W,ts8N6$rVlcorr3*"r;6Kkru(_0p\=[^p[["VWLoo`V4ONrg@=b2 +q>UEkJcFm4J,~> +JcFm4!;uir)"$.uYE![:?Y"A=TsVYSa2H!;b0A,K`m4S+!6>)Y!6>)Xs24uX`lJ%trl>)ZrPefV +rQ+lY!6G)XrQ+lYiQ2&Aqoo&^rQGPi`l#^5a2Q*?rl5;caiDB;`5]j=rlGqr`59L.]<doW@oliB +?<_&pX3&oUnGIk;jSs`~> +MuWYQo)JUdqu6Zqqu6oucIq+.fB3&0rs8T$s8;ijq>:-ersSc$q"ad`rVcZlrVcQkrquZj!rW&s +pAb0l#Q4Jrq>'g]ro3tJrr<!)rr<#trr;rqrr2fp$2jSnr;6<hqu6Tlrs7uDi8j(bjPJ\ds8N#k +s8)_GrrE(L~> +JcG!7,6%WBqu-H`i1m0MUS>-CnFHVWrVZQmqu?]qrr)iqq>1'hpAb0ln,NFe!<)fmrr)fpqu?Hj +!<;lo')hh.rr)iprr)iprr)fprVc`opAY*l"o\H#s8N&sr;uoqrr)isrVZ[5rVZQjrqQ6_n%YZp +TqJ'PU8m8Nqu6Wqrr2`nr;M9IpA]X~> +JcG`Jli/X:qXa7DhSXSXEFW6jLoISm_8X@3b/;<@`lH3EbK%]HbK7iE`Q#m:a2c3>`5KXl`WsK! +_8F73aN4A'rQGGibfIfF`r='Zb59B`b/jS%rl>Ab`P][7aN2B?rPnZS#fas,b08,Tbg$+1qoT8e +a2>j7`l?*Aa2e1u,K.UB_oB^8aj8>[d`fnU`lQ!0\upEb=]83t>%DiiiTg+5rUTsirVQQhrrE"L +s*t~> +N;j%[r;?Hhrqufqr;Zfrs8NW/s8W#mr;6?gq>UBnr;QWlrs&&Pgsj^'mJHq^rr<!"rqu]nrr)lr +rqu]irXSl'rr<#sq>^Hkr;-Bhr;HWnrrE&srr`3!rr2fm)ZKd8qZ$Noqu?NlrVufls8N#trr;ut +rr;urrr3T)rqufqs8;opr;HZms82iqs7QBis8N#pr;Zcnrs\c(s81m:k2kabf%9ZnrrrDuq>C6k +q#:Bmqu6Blqtu$F!<7Q~> +O8f:\s8M`lrr2oss8E0!rr;usrVm`5s8W)qs8Drpq=s0lW26AhZ-2A.rV6?jrVulrs8W)trVc`p +r;ZTl!W;iorsA]$s8W)urVulsrVcrur;HWnrr3'!rVufpr;R3)qu?Wpr;Z`qrVufmrr;rr"TA>u +rqucq%efo"s8N&rs8;fns8;opq>^0fs8N)uqu?Worr!]6pAFd<[&9aqV5Boce+W_;rVlisrr2rt +q>U$ds8IcQJ,~> +OoPI[oDejc!;lWm#Q=PrrVulsrqcX+q<d+WP&"WEDg%/@]>(qn_u%FRaSa3Ybl>ibaT'9[b5KE] +aplG2`lZ<@_90d:aMu?BrQ#Glc-OYU`5os?`l-!Ab5TWbaoof*b/D0rb6u5(]#2S:b/)3=`lA#! +rlQ"t_o0L7^<"ICbfe/RaMu9B_oTa;`Q.nrq8iKRrlFuZs2b5[&]iD@aM*gN=&Dan?=7iLcJeBo +r<E<#qYgBjr;QWus8D`dqYg<k"9&,qrIk3$~> +NW9%X!;uins8;lqqu6Zqrr3'!rVl`m"9&5prVZ[#qV]uZhV@Ppqu6p!qtp<jrr<#_rX\o*s8W)s +r;?Tnrr;los8Voos8N8ts8N&urV6Blq@*E'rVufps8DulqZ$?drr2p!r:g3hrseu-qtg6jrVufq +r;ZZlir0)Xq"=I^rr39&leL(MiRHNCqYpWpqu6Bj!WN#rqZ6WoJc>`MJ,~> +O8f4Zo`#9ts8W)us8N#trr)Zm'D_P(rqQ?_h7KV^U85c_oDeger;?Qqrr;Hds8Vuq!W2lqrseu+ +r;Z`qs82cps8N#trr2rrs8N8us8N&urV6Blq[WZ*r;Z]ps8N&mqZ$Bks82fprrN,pr;R6*s82Zj +s8Duqs8DuqrSmhVrtGD1q=adUca]gBVl62_]BAh`q#1*i"oeJtqu$Hes8DqOs*t~> +OoPI[oD\mhqYg9j"9&8urVlg5rr;lprql9Ri4Y1j@p)uhT=DhW^r4=6rQ+uXqoJWV"N\a,`l@nu ++j%sPb/VB<`llEBaMl3Fb/hZDaND`Qc,n&Bb/h`Na2l@"b5]No_SOL@bga_M`PTa9aND38`r4!Y +ap-)5a1o4%aSs?lb0.iFaNhiJ`lZ0?_o1QU)9gOVbJC]uVLiM^:gR^>BSsmhm-F9<qu-Nnrs/Q$ +r;6Bfqu-ElrV_ELJ,~> +NW9"WrqufqrVuoqr;R$$p\Xmdqu$Hgrs&#Rf\G?=nbW:crWiAur;?Qns8V9]#ljo&r;Q`rqu-No +!W;ijrWN0!rr;cmr:p9krs\l's7lWmp&Fsis8DunrX&W"qu?]ps7uNgrr2rt#l=T$rVufqrVtjU +"T&&rrqcQm#kd!1kNM*hg\:[H$hsMnq>:0ks8Dlnrdk+Fs*t~> +JcG]K!<2ut+8c';s8Dlps8N#ts8MulkJF<lV672Rr:]p]q>:*grr)lqrq$-irr2rnrr<!!rr)ir +!W;rrrrN&prr)otrVd'#s8N&mqu$Bjs8;lrrsSi'rqHHkp&Fsis8N#tqu-p%q#(0lrr;fjqu6Tp +rs8H"s8Duqs8DurrqHH^rW3&urr3Z/s8V]go$+21Un=?UU;uTqq>U-frr2ourqu`pqYgNqrr2ir +reLN(~> +M#[GPqu?Zos8N)urr;uq)?'C,qtp0YiQ%1)?XdhpRDZ_P^VI_)`Q6.!b5]QR`W4*Z`qd\!ai;9: +`lZEA`5K^;aN;ZKaMu<Bbfn#GbgX\Yb/VH?`l@r!%F<&5ajA5\bJ2?Bbg49-`r!gnb/2'>b/MQE +`lH6Ebg4YXcHaVXb0.oMrQ+`QnAlHd_8474^W"7)_R>M@@U<5CAS[XPiTp:3p&>$hrqZWnJcGcM +J,~> +NW9"Wq#CBk!<2or"9/5prV6BsrTDblhW"D,s8W'%rVZQjr;QZplM_=orVQNkrVlijs8W&trqHHg +rWiK!s8Dlqq>^9i&,c,#p](*dqt^9fs8;`hs7uWtqZ$Tnqt^3j%K?8%rr;onr;?Qmrr2rWrr<!' +qu-QloD/C`rVm/mhrj1]inWr"r;Quuq>1*ir;;-Gq#>j~> +JcG`Lrr2lrs8Er:rr2lpq"amai5)7hU8Z0"q>'pdqtg3erVl`p"TJAurr2Bdrr2os#QFZ"rr2rt +pAFpnp](3krr2rtrW`Dus82Wlq#(0jrX\r"s7cQhq"XU`q#C9hqZ$Bj"oA9!r;6<grseu)qu6Wn +qu$BkrVlfrrVlQkn,=@-qYgHoqYgHfq"OF:\"TXoT;/3rfCf%>rr<#srr)lsrr2lmrr;osreLN(~> +M>mSSrVQWnr;Zcn!<)co)#Emklg!EDP\k,<?@f/j`Q,s4^VRh,aNOG&!Q`:S`VmgV`;mpWaT'6m +ai208`5K[;^rja6`PoaCc-49.`rF+%bf/&]f%J3n`P]U4aND`NaMH0<d`p4jd+HF``koR4q8aDk +b/qZDa4/G`bK@lGbg4GRb0%rObfn8QrlFiRnAlNe_RI;%aMuEL`5KF"RrVV6<`NOCOL*j3q#0se +"9&)mqgneHs*t~> +OoPCZp&G'i!<2`m!W)`mrs&>Rf%f'AqYU9mrVccrqulurr;Q]ns6BU`r<<3#s8Dilrr3,trVuio +q>LWos8;H=\D[2Yrr<!,r;Z\tS"H7\rqcZjs7lTnrs\`#s8W#srVHNns82]jrrW/sqVqMMrrE#o +rs7oDhV-u\gtr&/rr`8tqYBse"9/5trdt0#~> +K`D&NrVmo;s8N#trVlfrq>:0cr:ndBTV\Qoe*Q`)s8W&prql`orr2lrrq?Bjrr)lsrr<#urr2p! +rqlTlrs/H$s8DlorVl`p#Pe>pmaAN"q>L?lrr<!,r;ZYqR%'MNr;-His8)`nrs\`"s8Mlnr;$?l +s82`krrW/sqYgEds7-'js8)Qhrr3]2s8W&mp\a@!X/2D^Z(%N5n+?GSrr39$rr)fprVlirrVuos +s8;rsL];l~> +MuNkWqtp?gs82`o!WDlnp_`l-s8N&sl/U?mF^efgEKI61_TBp<^r+7laoK]abl>icaSs3V`W*sV +a:-)-`Q$!?`l>s8`Q#ps`>m7M`kT=1ai_lQb/VE>`l>sHf$Usm[Dg%u_8XLpaq2kEb0SCgH%:@/ +e&]bKccF9,aT'7!b07oKf%&7!cH4;XcGd]CaN;WJbK%]Db0%fHrPnfTrPnEL)oft:_oU'HcH45L +_Rd.aV1N8b<ENm:CS]SGq#:9or:kjCpA]X~> +OoGO_r;Q]_rrDumrrqZ6f\#0YrVmH-rqQ<fs8;WcqY^6dr;?QnrVu-]!;uir$iU))s8Mils82fq +qYC*qs5t^[,UrWjq>UEm%K?:=-7:#^.aRefrV??drYPG2s8Mfjnb`+]q"jpgrr)clrql]ms8V*X +qu6s#qu$Kks8Vonrr39$kMb=]lJ^dsrVuosqYpQprVQZpKE$H~> +LAq8Qrr;oqrr3*"p\t0kr>#8%n&D6&UT;H'q"a^_rqlQks8W#prr2usrVlcorr2coqu6Qorr)ru +rVlisrr<!'rV6<jr;ZfnrVl`p"m$pU+!pa\s8Dp-rVZWj]-AOA*$ri$s8Mikqu6Wq(]473r:TjQ +q=ad]q>:3krVZTmr;QWos8;lis7-(8q>L<kqYL*es8;osq>C9jp!gILStMgKWQ=B$r;?Tprr)fp +rr;unrrE%Qs*t~> +N;itXqtpBhrVQKl,lRT7nbDtVp\=IDd[YDq@:Ob`\%KJoaMbp5bJqE;aihoNc-?73rQ>/]qSrQV +s2lt<b/VE>`lQ<D`l#a7`l6$AcHjYSbJM9F`luZLaMl-9`m;@&&ISrmc,%02`Q8&$&]r8Cd?Ob? +$4INIaNMN>a3)R'aT'6d_TC0Rdauamcd_s;%+EA>`l#m8aMuHMb0'_)rPniUrPn?J*mDmPaN)?@ +a25g6\\#_iZ]As-:/Y8'H`#<Zo(2YRJcGHDJ,~> +OoPI\p&>$kr;Zcqq>UWff%\j5lMLScr;-<frUosbr;uinrS[\TrsS`%s8D]js7H?kpAape#Q'Z2 ++s_d8s7uZorsei):a@;.*[kh&r;QZpq>M31oDeWQ8gmPPO.jSNqXXOYq>^Enqu-ENrW<-!qu6U% +rr;umq>^Kkq>U?m#Nab'lf$mgpAY'pqYU*drquctrquZmquH_Ns*t~> +O8f4Zrr3*"s8N#prr`5trVl]o%fQ+tqW#MhW2Qu>m/I"XqYpQprVuos!<;HcrVZ`qrr<#t!WE#s +s8W!&s8DZgrUTsfpAY*jrr2p%q2Z[>++Eq]s8N#trso&'rCnCV)AaT1qu$Kms8N!!s8N#srtb5+ +p6.rk:2#TX_qb%Vq=j[arVucnqtg<es7$!nqYC*is8N&uqtg<pp%e0grhB^bSup#qr;QQjs8W(L +s8DtJ~> +NW0+Zqtp6hqtg9grt55,pZgnu_3\nLBQAj3`5TF2rlYYmcHaDMbg+GUbg$+1rQ>,`s2t8\A]i6A +c-OYU`l5s?bg";L`PfX5bK7cRf?;Ug_TKm<aNDZH`P]^BE!m!]A'N04^Ve(6b/hTHcI1K#"UPDC +(/EE&`lH?Hb/hTDaMu3@^XgkY/I=(#COMkdd`KkZb0S8U`Q,ssb5KEV`q%1nb0A,Nbg4MSaiM?: +b/qT>_nrmnZ?K\^>>A=>Q,2POq#13mrVcTnrIOtKs*t~> +L&V8Sr;?QmrrW2trql^!k185>jnSiT#la`"qYBpbq=ag_"o7riqu?]TrX\u,rVZ]qm+//+BU/,f +rVZKj#PUk=)CO,1s7uX)qu?PM,:4EZ,Tn;Js8)cmq>M3-s8Jf@-QjQS-lk#g,V3M]RD%8Eq#C<O +rWE#srqQKhs833'qY'meqZ$Elr;Q^$mG@!jj4`;Wrr2utq#CBnrqlcqL];l~> +OoPI\r;Zfr!WW/srr`9!rr2lr')qe+qr58dV5:QFnbN4^qu?]prr2usqu6`ss8VKcrVZits8W)r +r=K#.rVul`eY\^EP4/GLrVuorrWrQ'oL9u<,1?2`s8N#trt##,pk9b4(aC%=*5;ILs82fp!WW/u +rtkV5r1G2W*$#tD)(ZmP-X_Ok]%-?Frr)NhrVuEe"T8<"rVcWn'`7q1rVu]np@nCR]VM<tTUr4* +l26,4pA]X~> +NW9%U"8_olrVQWprVQU5q=*V(]SpiE@;h.4^rja?cHXMRbf[uJaN2O'aTB`2bl,]`aSsE[b5]]c +c!erCb/VHBc-aqba2>j6cd',"KmcO6aOA2G_o9dBbfI]Cd4c.8%^jI%_nj@8bf[rE`RELV#R^\F +'+YMHe&K\Pbf\#HaMu6=_U6nd%M&XC!"/cB$4.;:Bm?,Qb0//Tq9&ZWrPnELs2lk=cH"#Ja2uEI +a2?'CaN;6?]Y;1iH!40G;HS"2bNes(rVQKgqY9p`qu-JGs*t~> +L]7b]qtg-apA+U`s8VomrrqK<g=4^Nr;R!!p\FX^r;Q]q"oJ,mr;Q]ps$6P\rVlcqr;HZmqu?]q +s8Vurr;HZjs8;fpr;ZWhrVucprr)lj0Hhhg-FEgKs8Vlorr;uqr50s+-;FI7rVu]lrt5#*rVY"h ++s:$o-QFC+qu6Qmr;Q]q0)b_F=<Ah3,pji],pXWX,U"H\,q2Wbo_nggrVu]nrVccps8DutqY^<l +rVHNlqYgZsqt^$^p\spiq>:*hqZ$Tpr;QuVi8!>Ih=LRE!;QBi!WMtNs*t~> +OT5@[r;Qlus8W)trttb8s8Dusq#:*aqV8EUVl-cRmeZhWs8W)rs8N#rs8W'&rVlipqu-Nns#L&X +qtpEnrr<#qs8;iqq#C9is8;olpA=mfs8Mrroe.=1*$MQcq>^Kks8DusrVXDT)Bh]Kq#:<irVmB& +s8Df;+<2>#Xs"N#8GN2_s8N&u!<2ut0)keD;]-Yr+X%mI*ZZ+9)]0S;+!aLOo)/OdrVu]nr;HZo +s8Dutqu$EmrVHNlqYgNorqHEorr)for;Za/s8Munpt2XFTVnN]`UNa#rVu]mrs&H%s82irrJ(?&~> +NrK7\qtg3eo`#^*s7Y^5Y^:(qA8e'F_8O@<cHFGUb/jP$qoF3.aNhfEa2l<C`lZNHa3;ZHb0%]I +aNMuNc,duOaO\egeBPkNaNW,P!s0#D%[G\a`PK11c-abQb,,m^%PZMU`Q#a>cd9nMaN)]9&e#%. +PnON=2:p0ra3;cI`lQ3@`kogI4Ui&.#R_"N'GhQ(*Z5n5'+m!Obfn8PaV)n>dEKeYaih`FbJM9> +c,[cDa83mWa8X0Tb500o`l5d,[Zb<2>%;#RPLA[[o(_kUqtg<c"82NhqM,$#~> +M#ReYq>C-cq=sUXp\b$prRKN[e`co1#5\5nq>:*hr;Qlur;Q]ks8Mm*q#:9mrqufqr;-?kq>^Hm +s"O?Ed[k*.oDejgs7lWH-R9iR/Dp=%r;Zfrq#C0fIO$*\V#LDlr;Zcrp&G'grqB4f-OJ&k9.V/5 +Qi-g^qu6Qo/b1P@+"P=VXbLL\/0Q>i+!`'U+<cU?qZ$Hlr;$6is8DipqYpKmr;?Qos82imrW2rm +r:gBiqu$HirrrE"qt^'crVm)fgu@GUhU2<%s82`o!WN%Os*t~> +OoPI\qZ$Tnr;RK0s82iqr:9^;WM?Vl_"%9nrVulpqu?]qs8<#us8W)trr!N.rVuosrr;utrr;uq +s8Mrmr;ZTirtYG)d$nO"o)Jafs7cQF,9@a:-JS@prr4JHp]('dGo[kEU&=rhr;Z`qo`+sgrq/l+ ++X5&!7OArqP5>.Wrr2rtrr2lr/ak/1(ad)BWI\PH,oIaJ(EFJ9)B=J/qZ$HkqtU$frquZnqZ$To +r;?Qos82imrqHEprr)fnrqc`prqud4rqcBW]VD3qUSjpTq>C6er;Z]nrr2clL&ZZ~> +O8fC^qtg0drV-=0rr)]cjQ!^qBl%.$X1>g^c-+8Rc-"2M`l@tr!64lV"38F(ao98._T'[@aMuBD +`l,m@_o]p>b0eJS`i=DWA\ua8aOJD]WsTCN$PpIu_7[_0c-+SRcXmn%#(k=O`5^*IdDX>P_9C4a +()7@]eM7sQ(OX`UaiqoI`Q6-@`l6-H(D[PnUoo_n:c07/*$>q3'G1ZYB[4Q@aj&)ScI:.aaj.j) +`WsQ(`lQEI`QI_lpr`QV)TKb4]t(7i>Zas0DgKO^m.BoDqtKj[qY0jbLAuc~> +MZ<_Us83-!qYBs]q>'sersmoEjON;js82irrr)`krq??lrqQLkrqQEjqu?3brVuZks8Voos8)Tl +p%SLa^aUNP:](1irr<#rrjO6r.3M=\r;Zfkrr;fopb*g5/bJu;r;ZZoq>^Kgs8/-3+W>Y"rjO-k ++tWK_r\40Gi@#Wf/bo)8r;Z`di7"<[Al9ft,:<0`s8%;3bkq>3s82]ns8)corVucps8;lprVuls +quciorr2cos8N&rs8E9'rr2ikq>L-grs%uRl1!frgAV$RrVliqK)^?~> +OoPI\q#;$,rVuors8N&rq"`U<TVnU#p]'j`rrN)trr<#ts8<0"rVZWns8Moo"9/?#r;HXio)AXg +q>L?nq>^Klr;ZKbs89VY*umrLs8;lrrVZW#+Vu:>8,3#^s7cKlq#C%:)At!pqtg9kqu6Bjs7cQi +PTq([FS#F:*toS?oDS[fs8W,us8OeLr8&V2)(>1Op\XsfnD;N^N+,L%*ZZHurr;eEPKN^to`+db +s8VurrVccns8W#rrVccq"onT%s8N&krW3&uqu7K/rr22qU7IpATr$E6qu6QorqucorVZYMs*t~> +O8f@]qtg0dqYq`;q>:$gp$(;8CLC[^J\/n/`6?QPbK7cE`5BF/_o9X:aS<bja2u<:`Q6$@\AZA- +^rO^E_oBp8]u.G!cH)+O#miB6c,e,[eB6+)'+l8t1XX4^`50^LbgXoZ(CL_rbJ_?Baj/&YbeD3C +FVPMq@FE_m$k!def$DL_b/VEAaMu35b.eW%',&a9a3DuX,KI<rHZ)D5#n%1KaMlEG;JMuUeBQ^k +aj8&FbK%ZF`Q?HGaSj0YaT'Hob/hTA`P][6`lQ<Hc-49-`r=$jbeV-2VK5d8:eY><[+t*ErVQTp +rJ(?&~> +N;rnVs8;orqu6p!s8UO+i8OM2rrW0!q#:'hr9XFgrr)flr;QTlrr39!s82fpr;Z]mrVn)=s5kLP +-R8!Ss8Vfms7lSA-6O?VCA@Q"s8Vimrj*ji-\;9s)#jI5rVuljs8:q!+!N*$rVlLc.3TpsqYU-g +#lXf$dN^.bAbZ3(,l.B<s7cEgp$O.P*[gmbq>\nl/gbeLq>:3drVuirs8Mijs7uZns8Dlpq#:Qt +r;?Hhr;Q]q"oeDon+lkZrs%uZq=*G%g\h*OrW2opL&ZZ~> +OoPI\q>UHoqYpoor9U5UTVKHns8Dors8Dutr;Q]os82rsrr2fn!WW,trr2otrr2p'q#C6jrqufp +rVca?qu>b!+X%olq>^Kes8VlkGTRe>+D1?Aqu?]ir;<`='I&#*ruD%9s8DuspAb$L)AsJ;lMLMN +8g5,mMYR)Jrr<#srWiK$c5duH@J0X",l7K>s7lKgoBIJ?(F&bVq>\hh.jK/@p\Fj`rVuirs8Mij +s7uZns8Dlp"o\H!rr)forW3&urVulrrr3Q-s8MronCOt;V4jHUXR>f[rVlils8IfRJ,~> +O8f@]qtg3gqu7N3q"F@OioJ4&B3ADeYf=]+c,n2Pb/hT?rP8]U`Q$!AaN44tE66);`5BR7`5Kj> +cc"5Qbfn5R`50@2`6l]N\H*0T$cL05ccan_`nFr<'+kjKc,7EAe&p.gOqeQ>?.$d:aN2WLd*0AU +c+F&d',B$Ie'Kfd()1r>aiqiF`Q63C`Q63,&Khi[cHaYS^r+76^W6>u&IT-Z%aE#4dAR$P"BCQ2 +d+628`s0`/aMYs=_u@aWa8X0ZapuM4`Poa4`Q$!Abg"AQ`r<pk`lQ<@bf@T6Y*<Ql:Jt8/Ia-jB +qu-Npr.Y0$~> +N;rqW"8r/qqYC-oq:Oc\o_nghp]C-erqcWsrqu]np&A(irVuoqr;6ElqYC0cqY9a]s8)cooDeag +rVfS:+XFMms8N&qrr;ro>9kI<-'J<-s7--hnm*:a-,]WYp&G$kr;ZTlrUj>?,q5AXs82i!+se9X +m/Qq]0E(_HSg5:%J,fQHqYgElrVuoqs6M$X)CtLXs7?2?+WVj[eG]4Cr;ZTmr;Q`rr;HZnrql`m +rr)lnrWE)us7cEj#3=e+mG[?prr3,tr;?TlLAuc~> +OoGI\rqcX1r;$<jqYU<irV4O/WM[l6q#:9hr;Z]mrs/K!r;Q]qrr2oqqu0n"rr;ios8W&rr;?Tk +q#C$^p@J.\qZ$Qfs8;oqrC\+K*jb\BrVcTls8;Xm*ZZ1ANrK"Wnc/XX=;N)&_>F6)s8N&rs7uZl +nl?hS,F7p#qZ!T9*Z$!as8Drss8Dp)qZ!!)'-;N!s82Zlr;Rf8s6(RH&LI)Is76&9*>p"KdJN_= +r;ZTmr;Q`rr;HZbrWW9"rVc`pq>V3'qY^-dnC4G0St_XQ\)[5^qu?]pq1ep"~> +O8f@]qtg3gr;Rl9nE]H'iQ[Tp@pt;/_TL'Caih]G`Q#j4^;%P(aNDa+b503Z`dc%G`QH9?`5BU= +aN2oUdEg%adE'GH[`->6ajDjR&eL/JcHXkaaN`)`5S+YD&TuaNcb%WYbX)m[$Cf/V^Wk!K`ll9D +d*Fic',QDTfZ_m'%N#ckb1"VV_o'R<aMkm<IhNM5?I[KJ`l5j0^;It3g<0p@&fJ^+dDXO?!!!N8% +C4O.cGmuDbf7`Mb/Va+ao'6Y`qd[Vb/jS)!m&C#rPSZY&AZ<+_8EU<>>@jh:Mbd(jnerU!;qTOJ +,~> +NrT+Xs82lqq>UTkf[e[Grr36"q"jsgs8W)prrE&tqZ6Worr3#us8;k1s8;osrr)lsqY^Biqn[t\ +/Sj,;s7QEgpAam^Jg;TdK)GQCs8W#lrquX?*[;[M^]+31s8211,UZ=_r;?Tos8;ijs8Vhc+=8F% +q>^9jq#=,6-6[$rrVc`ps8N#rrqqg%-RGG[r;QQm*r#W\,U4gCqZ$Els7R]i+X(Lkrr)lps8Dup +p](9grr2rtrr2lrs8Mups8Mrrqu-g"qZ$Qps8;fp#3=n3jPn_\Jc>`MJ,~> +OoPI\qu?]q&cMM&rVcKZe>].:`:NX"r;?Qirri?"rVulrs7ZFqs8Muss8Mrrs7uQlq"VOR8L\?* +q#C$eqtC'apO+&%*.Rk`qZ$Toq>U9d+Vu(4*4u.Irr;i[+WV[sq#(*jrr;oqq>^KfRi3@k4S8[K +s7cLb)]fo-p&+ggs8N!(s87cp*ZgmGqu-Bk*r#QW*uuV,q>^<krpq6\*#rJZr;?Tns8Dupp](9g +rr2rtq#:6lrr2oqrr2lr(]O71qu?Zns8Vuggo[?HSY;e$n,<7cre:B&~> +O8f4Yrqc]orVn);oBkbpbboGf>(!Qb`lcEHc-F\_`l#a3_8+"0b08,Tbf]_%s2K<%a3)KAbKe5S +f$`0CAhFK`[Em@=c,.?F_96I))%p9#b/i5__nF.9eI)g'&e^qiai)HLb75=*0$hVWdEKtY`4aFE +c[lQ?'J/,$bgFJ_2A7#@9$YZ"_8FC=b/M9@E"jH4I`TdYcHF;H_SX=1d]Wrf*^[uj'u\MPe-?Zo +#Y<@lbg+/Qa32H<b/qO"aT'B]aSs3YaSX-VaT'9Z`>-53`mDoOd)s&)O]tOU:L.b1f'W82K`?Q~> +NrT.Ys82osp\XsnqpjNRkPbDcq#CBns8Vuorr!-!q>:-hqtp<hr;H`prqu\4s8N&sr;Zfns7F3W +,V'o^+<aV^q>^-es8W&t\fDn=;#((hq#CBnrqlHN-R:#]-0"b#qu;O!)C_*Ms8)ZkqZ$Knr:oM( +,9e;Arp]s`s7WW@+!E,[r;?Qns8W)ts8-=R(bWZ#qZ$TmqYpNkrr3bI-"pbPq>^?hs88r<+<E/K +o`"mgrUp-h$24Drr;HWprr2llrr;oqrqufrrr2g/rr<#rs8)K_q>:*is6S7pjQP=VrVllrLAuc~> +OoPI\qu6]jrVcX$n_9e8W5SK*s8W#qrs/Q!qY^?lrVlZns8E0$rr2rsqu7o?s8Dfnrq?B^^j."J +(`sY9:&Xhdo`"mjrVs8@(EH6Es8D]jrtG>(i?90\(EVH/s8;nO*YTcaq#C?j)>X=3s8D]R+WMC> +[/04iq>^,g*>]V?bkqA;s8W'Is8-1G%k#*eqZ$TmqYpNks8W)1,%Y)Dq>^?gs7iK-)Ajp7o)8Ue +rUp-h$24Drr;HWprr2llrr<#irr<!4qZ$NlqYpNlqu+^8WM?5SV:,#4r.Y0$~> +NrL^0qtp?lqu?]kn*&9,BkD1=^V@n4_90p>aN2BA`5KX7aNVrTbfn5PaN2BBaSX+\aN;NFa2c<F +`nJ_3?4.JT&IJh$i6g&mbg4DOeXm<g'e[VPbK8)N^;%P)^_%J1*#-6.a268?&.KG"bfdlHc,n/D +_SaF8&Jc/lT\[]9a3Mei&JPpF&ZNsl_8FC>b/hNC7i)d]S]Aanb/M<?ai;TTeWg/)6#=HW`Q[,n +P6MF$':[1ibf%Q:c-+8Q^rs^:a2lBDaN*hls2?#"b08,Tbg+GQbf7Z@aN263]7aBj;,p>'U!i)p +r.b6%~> +PQ1[^s8N)urqlfor;?R(nBoD6mf*7drV6-dq"ssg$3'o"q>1!`qu$BkrqH=pqu-Nls8VZ@Ijcin +,9n0Q+sSDIrVlisrql`nk:Ru$,jbF.r;ZNks82ikZ7-h>,$XmCr:ru3-7/!Xqu?Zqs8N#tq=neL +,9S.JS=Q+=QCsZi-6"16qu$Elrr4hSqu'&3,pLb:s8Dors8;iqs82Zmq"t*erVucprqZ@q,UXX* +r;ZTmrr;oirjHjWq"ajdrr)orq>UElqu6Wqs8Mup(&e12rV6Elq=O^Yrr<#shrX1fgY_u%s8N#q +s8Dqfs*t~> +ScAZfq>UHoqYq!'q=jaVd'07D]A!&UrVuoq"TSK!rVZZp!<2ips8Moq!<2rs>5eL"qu$K]dWm&b +*ZZ7:*#fk>\GH.&s8Moqqr9%B(a//As8;ols8W#spT>_U)B2`Ps8;U\*ZlKfrql`prr;uts7uA& +)B0M4C7(HWRZsD/)]fY5=8MmprVn_Rr;8o'*#m6(s8N#ts8Dors8)Qkp\Fd_rr;orr:]bb*[)@h +q>^9jrr;ohrO$URp\=Xarr)orq>UEooDSmks8Donrr3N,s8)cpr7A$GUnF6[gACjHs8N#trrE%\ +s*t~> +U&Y,jp](9lr;QcqrVmu6n*&?&LMppQT#&ImbK%]=^rFI;b/qcJbKJ/VccjW4ap?).`Poj<b08$- +aDB&FdEg:m`N<JV'FkQ_$5+!d&Z"13d*BeQa32UG)\N=ha3VoQ]YVJ#c,l(a(`sJZbfRrO0GG<8 +ajS;Rbg+MT_oB[?:_"?Y%p+7-EcZ#@Ih*M2&O+LY_SaL=aiMBF0,PcEW6<H)`Q?4P`6$BPb0/8W +d+$.Ua2?0PfA8q+&I:&Df#>bPccX5QM+<KIb0.uNaN2ECrlXuV#0P$+`Q63GrllD*c,[lCccs\W +eAfME[u=Nf;H-eDYh\L8qtp?crrE#js8Mtns*t~> +U&Y/lp](9ms830$s8MrnqYBsdrr3,RhUUN^rVuoss82cos8R';s7ZKir;?BgrVQWoq>C9fs7u]o +qZ$Hmqu?B`jH*7a+sS?Z+!XT-,Te=Rq>^<ks8N&spJ2tU,J!XMrr)lrrVufnqLKn7,U.m<s260* +,^9(`qZ$NoqY^BjrMq4e+sA3Z+XSE\-7'`a*??IR5Ip^js8N&is8MaA-64N/rVlisrr;urs8Dup +s8;omrVucprqZTidjH(Z.@^,4r;ZZedqC-U,:d'3rVucpr8dkWr!!*"s8Mrorr3>kh:C]IgZ/>6 +r;6?j#la\tr;Z`qs8Mup!<2lqs8JnqJ,~> +Sc8cjrVZZn!<2or!<2lqs83?%o]r<OUUT7OqYgBms8;lqr@e0Mq#C<ms8N&urr<#rs8W&tqZ$Nj +s8;ons7Q$AMbP32*$$(=*_ROo(ERGes8)]o5Q14G)AjO)q>^Kns8MusrVcP@*Z5t<J,&rW*Z6#> +p&+XcrVucms8)Vj+;u1:*?Z7C*?cRK)'fq2*?_ihrr2p(o`+p`,9@OCpAXsh.K9AHs82ios7lQm +r;Zfms7Xb_'c\E`p&G!jqt&0F,9S$T=h4J0qu?Wbrq69qrr<#tr;?Qnru(e2`iGT)URnLLrr)`o +s82cnr;Q]orr<#rq>UNqs8J_lJ,~> +UAkApqtg3gq>UHnrqc`lrVQU'rU/=RCMII/X1ZEk`;RXVaNDa+c"P>G`mW)UbJqTEajA>R`Pf@( +^sUEHb.u'Ah:^Q)FZKsD'GV;e#W3)0'c:6.e]?%Z`l6!I3>`J<Oi>>[a32WKbJV9?>n.G_&7j>E +UC[qK?eX)UcH"&D`m;lZM@9t0()If!&e,?M%7D0L'cn'OaMl6?ah,gAcPIQ9'Ze/2aMu'5^V\(2 +bK%lMd`TbW_SjF6f[[>="V_f+f#ttRai^_W%h/jU4Hn.;a2u9uaSF!WaS!RQa;<"Cc-4DS`kf<r +J7_eh?<_'Jj6uO7rVZKk"9&#nrV6BmrVlZorMKUF~> +U&Y/lpAYEtr;Q`qrV6<irVlu\e^i@LrrW3"s7lRSr;ZZjs7lHir;ZNbs7ZHjrr<#rrr)lmqq[9% ++!DUN,Ut0\]`7Df,pF9YrVlilr;Z]pqL9b9,)?'pr=o;1s8Dipqta\G*[`55o7A/4-cGi[s8W&t +s&JjjkpR]&,:FT],UOf`.3p&[,:FEP9DSVbq>^Kms5k^P*[^d_r;HKis8VumrqQEks7cQlrqcZp +qZ$TcK.A&b./s)@p\ojq*ZcRO-+<jKs8Vinir8oV!rVrnrVmT1h:h2Xj730Lr;Zfls8W)tr;HKk +rr2utrVQZpqu?]qVZ2/~> +Sc8]hrr)iqqu6`ss7uZo')VLi\tc$th=L@>s8Musrr)iqrr)iqs8N6#r;ZZnrr3)qp]('es!%@> +rr;ijfo&3;*Z-(B,U$s6r9KRg)&"=mrVu]ks8N&nHN"lbK_tcJ'`\+2rVZ]mq-4sW+<RHJI2a4O +_"Rd-s8N&u<VQ:M,9%dH+rDLF+<M[M*ZH%<+:oD\q#C6es8W&tiuo3S+Su*8rVQQns8Dipq#(0l +p](3kqu?]ms8VM:-5dRBq>'s^r.643(`j\?ZN'\!s7lW^rqQNmrWE,sr;HWp)ZK[)p<fh/W1^'7 +o)81Xrq$-erVlirqu6WpqZ$NnUAo`~> +U&Y/k!rMrpqYpQorVHZorql]p')(P4MJ-I-RBscUc,R]>`Pop@rltJes2o6)bKA)J_oKjIbfeDN +_7dS%c-=DL`PL!:GVfd;$l0Hk'3CXUb'k0I&K09JahYp;^W=f5)&`urai)-:c-4SY_SjF<57S,<% +$B1W&JPbPf@nWq`PfmFajS6@%2BHj$l0Hi&J5Zd%1a-n&J75Wbg"2GaiMEH_A=%'&B_l0ahks6_ +nNn*_T'jF`RN)P_SjF3d+?HM&ePZkj3,Nbemf*o$5*dTQ.a@+c+h<taSF!Ta8j6W`W*sXaT'Bub +f\/Pb/hQ<[^M9,;d*"+U"&;eo_\C[rs&H"qu?]prV?KlqZ-Sms*t~> +UAk;or;QZp"T/#lr;QWo!WDomrri5PgYD&js8W&trrE#ss8;kFqZ$Hfrr)]kq"adbrr2]krr)ls +qYpMs9.2,6+sA0U>.F/'p&>!U,q'f^Zhj_%r;ZTmqmmso,>@t5rr<#tqu?]mrVu@7+t"EUc6a_\ +:&aqfs8DurqZ$NoDB(#GB?SlSP,"V<R@0dcA0E9E/=HA7rr2lqpX:?6,AZuNs!RdBqYpNor;ZZi +r;ZNkqu6Wnr;Zfp*%<!ML%tSG.4#r\-m55`qYU6kiVirWqtpBfrrq]>guRMKrVlruqYpBl!<2ut +rVlZns8JnqJ,~> +TE"rjq#C?m&,lD)rVlcdpVrc#Yg<@Bp\t3mr;ZcsrVlisrqud"rql`qrVuln%K6>,qu?]qs8Vrp +s/eik,QAi++X1!rnG`+[roP7D(*TpYs8W&tqZ$B")]0Sdq>UBn5Q:Q[s82cpm3<So(`^U>)]hTK +p\t3ls8Mlpqu1:F+;eS.da!lFR[9;)SnDCL*uu_op\t-jrr;`?*?H/2o_ne;r;6?is8MrrqY9se +p](-js8;cos8!QW)&7\pqPGM[(*FhAT)JK^rVuHf!<;opqZ$Tprr3#urVl[*r;ZZfm(f<bTVA+9 +q=FUcrr2rtrWN9#r;Q]mrri?"r;Q\js*t~> +T)\fgr;ZfqrVllrrVmAifT]`SF-aeS\]E":`l.ksrl]3%aMu6=^W=C2b/_HAaNi;gf?qIP^V\:E +aN2DK-Ogb($j[1E2NZ&/_8t!D'He))O3#D]`6,g9d%(md&M;8K`lH?Ja32ZCaj\H@$kisX]G)"j +/ChqhcGdiB`6Zlf;[=3M9WGS.F+esfG^)W/;+qE6&JKE=e]l7T`l"hf)]2SrajA\ibfRlGccXDX +bf\2U`QQ6>a2lHRf[Km7%h!7(e;FnL"qV=JJ(Mlcb/hWDo#LjOaSj9]aSNpUa8sH)rlQD*`l6!2 +ZDMkL<*<[E[,'d;rVuorrVZWms8DutqtTmYqtpBqrVHBhVuM8~> +UAt5ls8N9%qt^$arql]sqZ$Hkrs8,Ni7S)0rVuosrW)orrrW,us8Drss#U&Os8Vlnq=M(3BVbA% +qtpEgs8W#sqN<-L*$$A-WTa0TrVQWmr;'PD+XD=-q>UBnqZ$HT.ioo_kPkL$rr;rsq>^Hopuj+I +,pjT_*@.6Vr;6Nls8Dros10L"*A$XXqZ$TepAFgbr;62%-QjHYlMghYs8;o"*??MJp&FmcqYgHo +rqcZpnPcUbq>^Kor;Q`pqu->m+"S]_ZW/7n,9n^]l21ARs8Viks81gT"8qrirqucrr;HX"p#Y8t +lJUt,rrW/srr2rtrqufrrqQKnrhf^G~> +U&Y,kq#C?m&H2A%pA+R[k.RLdXn_Ses8W)s"T85us8;Zl/c>YKqu?Qe[V]WNp&G!is7u]pr;ZVU ++W_I<,Z^o.q"t$es8Dlj;]ckuFnbb3rs8N%qVie;*$XMDs)J&<rr;iprVlNP,T.[G'dXV;SH&Na +s8DusrqcT&+<)(Cli$VXs7,aXq>'m^nmip_(aJ2?s7lWms/[%Q+)LQKq>0pbs8W)prr;FaXS)Ag +s8Muss8Dflpo>>\*Z_C[*Z5q<-?82Dqtg?mq#16ioDSaipAXmf(&n..qYU3es8)cgcEa:;T:`^R +p&=shrrW,pr;Q]mrri?"r;HVis*t~> +RK!9crqlZo?iL*'qXipdL0Rtt]YDJ0aMc'<`lcNKaNM]F`l5j6_S*P&bJqiMa,WeeM:U>&`Q#[; +dE9YPAHWAL%1bFR_TL!D`Po[7dR>,k&6-]c_8aU3aNhaB&J>Sgc,n&Nb\tJ@_9pNUcbp1q',M0$% +LdO-aMl08`l,s@esHjV&/`R;cdgXgc-t+heCW;I%LNOSbLk=abeqSW"V;Y[bg4JXc-Y%jbfJ)Za +=Dtgb0\JW`5^$Eb0J.`!Z2[bQoYch&e>XV_pHNA`PfF,bf01p!li=(rQP;arlFuVrQ,#]'$/)/_ +mmCcMf<')>\/f,h=1.5rqZZjp\k*qqY'RRpA4[ds8)fpVuM8~> +T`55qr;6<cqu6Nn"TJ>us8)`p$LZs5gA1dKrr;loqu6]rrVZXFs8Dors7l<fnXCsR,Uk$@pA=gg +rVZEir;58!,9&#7oD&4_rr<#rs8MterZF-Qp&G!irr)lqr(\IZ+M@[PrVQToqYU<js8DGt.3'HX +*u?Hiqu?ZprVlcqrqIug,U\oQr;Q<es%*.hr;ZWemNWqu.Y7Hps82foQRX.$U@S!Vs8W#qrr)lo +rR*,@+dVp&s8Dors8DrpqHFpa,:=cb+X::8pA4ges82Zms8)cTrWE)qqu6Km!<2or#34S%l/UOj +rr3#pqYpKqr;Q9e!</kqJ,~> +QN$sarr3Z2qX4:Xo":cnX5*aTrVu`lrr<#srW2usq#=.eq#BlR-mKl],$"@7s8W)rpAb'eg*RgV +,HgY6rVlcps8Dusqj/3>)_CX]rVlirs8;[a*#T[)r;Q]mrr;onrql`nm^=DV(`jJ)-KY1)rso&. +rr;rj-lsEPOn\hRoD\b\rr;lqq"*en*Z65Np\Y!gs8A3/)Ant4o`"miqu$Eks8)W=,pFCqp\k-j +rVuorrquRo(E=A:+!;IB=2sk-s8DusrVuoos7uZjs8W)srVHNirrE&srVca/q#']oTq@sJT#UR) +s8Moqs8;fhrrE&tr;chms*t~> +S,WZjqY9dZqu$J>q#0U+LL""nR`3:bb/D<=a2lHKc-4AR`l5j3_SX++`l,pLbBXF'&/c-FeBlCZ +`6-0Lb0%%"%h9GCdEg+bcd'nTa3)na%LraPaOA2N`l,pAei"-S%\(hf`Q-'>]uA:AeBZ$u$k!gm +'a>5[_oKa6_Sa=;cd,Vu#S%VubJ_K:dE^(^cHF_`d*)Os%2`d2da,eJa(u>#(6Qtbb0/)Vd*Kn[ +b0mEu!s!&Uc-=;LcHjVR`lU4D()Rf#(_RENXjG><_8<gq`Q#j@b0'V&qSiQWbl,fdbl5cbaSs0Z +`W!jWaSa0t`l,^(]sE#k=]SU2P1Adgp\"CZq>UEkqYp?pqY'XXqk3t>~> +TDo#jq"X[]rrN,sr;R)PjPBS1rVQ3drVQWprr<#urVukGs8Mroq"F^\Ppdmq+<MF?/7\YXrr)ln +s8;os9d(f!K)PHBs8Dulp](9S;Cs(9,l[H9s8DuqrV_9l+=2^:s8Dlps8)cqpA=jhq2lmH+X/L\ +qu?TorVucpqtPIj+=COos8W)uq>^0gqu?<gs87Hq,pjnqqu6Wqr1,,5,8NsdPG,nTpA4RZrVui+ +-6=RKrVQWprVlfrrtbOY-6s`W+!2u;s8;osr;Zfpr;ZfrrSIPRr!*&rr;6Norqud#kiD0shU_#i +rrN,rrr<#tp\t6mVZ2/~> +P5c'lp\FXDU9(34p@nUbs8;fnrs&H"r;Q`prql_&qt^9cPU7Oh*#]J,.:W;Vs8N&os8;or8/iZb +JGo<Ds8;ojpAY$L9d^o#+oLs3s8N&rrVM!`(`n2$s8Mrqs8;osp%n[fpPp75(`FcAqZ$Norr;or +qtG=d*$\Y^rVnVKs7cQjs7H?kqL9\2+<TG9rr<#rRi`Uh7:VIQ_W(1]p%J=^qQqC`,\HuNs8W&s +rr2p-r6-<((`=/.,cpt?s8W&srri?$s8MumrqcZmrr;rorqHHmrYPJ3rV?Kls7c/jU8OcYVp"f6 +s8N#ts8D`m!<2rq!</hpJ,~> +UAk;nqYU6k"oJ)gpA4ads*=V=l+gtA;L#FXaMlBAaj%iEaND`NcHaPN_nj:/_o9L2e'`CM%L3X_ +&.oaKeBZ(Qd)jSUdF^2b)@1-5b0/&Rcc3uOeA=6a%L<-da3VrJa2Z<PA.]OlC!k2EaN294cHjPR +bgF^S%i?0#)ck2)_oT^6_T9d<=&0,&$:`dpai2?;b.c$;d)+>ce6W@j&dc4rb/V<<EXNR!4\]^2 +P.T/nd`p.gf:*3O#=$MVccjGPaMu<AaJfXe)&!Jh'U[n4f?hIS^q@A!aND]Kb599V`W=0'rlkDe +rQGAdaMu6u`W*sXb5][(aiqiB`koU([Vf2M<EO16h!an2qYgHlqYL0irri2lo_ABYs*t~> +TDo#jp\Fgds8W)rrr_TEin+20"8_clqu-Nprr)fqrrN)trr"_OqYC']Qn'C"+s\0O-7'BPbP(l3 +s8Vrps72'r*?c^%s8;ols8Vo&E@E4W*@>Ons8W)urr2gD\g&CE:%\Jbs8Mumrr<#qrVQWcCa1&E ++i=$Squ?Wpqu?Wps7H-9l2LKQrVZ]ns8;iqrV6Edl>(-D/T(Faqu-?G,:+?S,:"N^-SJ)/N1\GC +RjfF)Pl1O\s8MomrVucppJ)\Q+X`fSs7cQjpAb*kqYpNko`*qMrr3H,q=jRVq>^Ens8Murr;Q^" +hqd_]i9gOD"S;<arr2in!</PhJ,~> +U&P,lr;Qcrrr)cp&H;Uh];2F*p\Opir;ZWks7uWls82rts8Dor+TD<9rUcC(*u,e<(E+A;&L,Ho +r;?TpqYpNaLE[QU+nbj7)YsF5p9ABX*uPk<BCc*&rr;uqr;3rD)B;9;r;U[3rr<#qrqufcB,hd+ +*5D7Jqu?Zqr;Z`qrq#m3k4e]Jrr)lps8;iqrV-?ak@eI6.Vnt]rVu]I*Zc%8*ZuUN+Xf]jLmuT2 +Pp.(fP5G4Ws8W#prr;oroLKZ7)BkL?s7QBfpAb-lqu?]mo`+gfp]'pcrr3'!rVcTm'_hY*qu6Wo +q=3=DSuJ?T^#K"jq>U'es8N#r!</kqJ,~> +UAk;lo_/7`"8_`frVlg5rVQ<Wb)L(D?E^fWa2ZQMc-aGI`5g!DrltMarl4uY&B`5IdX;iD%iH?+ +*[Vs4$)IR?;:3V-b0S1I'G;)if$_XZ^sC]cQs1@C&IAh9bhLRgaN2BBc'SqV))p!i`luH<]ZSUN +ai20Cb#8od%LJfMc,IiEahu<Bcd'SVX2E<'^r4/ccGn#Ha3MlKeBPp'9g]:Vb/M*1_m9[a&ebWV +!XKAZ3EL-JYdK<)$OLXocd'YP_ns:/_U6gl&K;DtHdUQme]btR`5TL1c,@EGb0'\(pW!6Ss2t5_ +"3S^)`r3mV`rF3]bSejLcH*rBb/(m%SRtZ%<+([$m/$JTrVQKjr;Qosq"FL[UAo`~> +TDnulqu$Bls8Mus%dVBkk4&ENq"FU_qZ$Torr6g6s8W)sr;Q]orVZQgpR<NR)'L+G*$Z@F)^6A? +p\b'grVuips5>@D,9Xr$q"F^$E[i4Y+X80[D#"&0qtpEks8N&[.3]c]mJd%`qu?Zpr:g6krr;ll +;'dbjr;ZWnrr2rqrr;ipqu?Wn;#gOpqZ$Hgs8;oorVuZmrqlHip%n^er;Zfn_HAN:.O$,c+s%pT +,U+Ng+<V[O]DDR*r;Zfrrr)llhBaEh,2`=qrVucprVlcqs8Mlps8CsVrr36&q=jRVq>^Hnrr`)f +q>C6l#5?p6nDE*jrr3)trr2ioqZ6WoT)X<~> +U&P,lr;Zcp!<2ut#lX]!e#]@L_=[[*=o/0spAb0lrr;urr;?Qns8W)rqY-C'*>BJ4*#9P/)AO;6 +D#+#/qu-QnrVt[u'cnC4qtg$b]P]#6*Z?"<,\ZlLr;-<jr;ZcriZoHX,O,1)s8;osrquNhs%3(\ +9HPWVq>U6jrr2rqrr;ipqu?Tls8N&ps82Wlr;ZZms7cQkq=OXWq>^Hns8Vl.;^`Y4*ZuXG()e8: +*?ZgL(`":)q>^BkrVm`6s7b4h*#BRJqYU6kqu?WorVuosqZ$Toqu66fp\t3m!ri/sqYpWls7uWn% +fQG*n]RVqUn"F/pAb0joDedgVuM8~> +UAk>mo_/7_rrW/rrVlh?qt014Xa+DiH*5!(aN_oLdETPM`l?*EcHXSUaN2KHc-XnhJ.iM)(`4,+ +*uH.9'*q.Ob0@uIaiDNQ^^pnk%]Rq!_TeBD&eGlo'Fk[Idalmka32QIaNqU2'bV8*cc42H`P]j@ +`QlKBaj/R!%hpeMd`Bf7b$2m,ai)EDccjVZaN_ZHa2Q?Db/MKMak,(ldFZOab/1p6bL*.T*YAtd +"UktV(DdJb$lTcp%M"iMe&oVL`P]U1aiV:0)ANk&dDsGVajJ5QaiV`I`66HJb0'\(p;R0Q`lS/% +rlkDb"3AL%`W!jsaNDZLbg+;Wa32K?aMZ$6Z@l4O=BK^IjRi<@q>($nrVH<aqkO1A~> +SGrckqtpBmrr)j'nC#kCq#CBns8W)r!<2rs55P<Zq>U?kqu$HiqXg=(,pFBN,9%pR@j<-A)(6cT +qtg?mrVlcppJ;nS,C9(%L+">o*[)UL,)=M:s82`nrr3E*r;ZOc+X8>>rr;rsq>LX!rqYa0kkk50 +rr;p3r;6$;\tjsh/g_Jj,U4K[+<DgYo)JOb#QOOr-mBa3o]c>as8DlqqZ$Nos82cps8;NgrVZ]p +s8NZ0r;6<crVZTns820CkiUgdrVm3$r:g*aq=OR^rh0:A~> +T`5/orVlcorVomss8;`L_5=HPiVr`Hs8;lqs8W)srVu`os7uZmrVlisqtfoR+X%jD(`jG9+($'/ +*YftFc2.;:s8N&trq/r'*$9Ct`.B6W*u>h4*$'[Uo)JR`rVlisr<iSu8/`HjY5SD!s8;lprs&Gr +jONAeq#:6grquffrr)fprr)j7rVQEbm+&S=JRKuM'Ik1H*?Z16*@1(PrVlZn#PFf7)Al6>rr)lr +rr2lkrqud)rr)lns8Dutr;Q`rr:p6ks8N#rs8W)ur;ciprt550s7tEZTU_UL]BoFos7uZlrr2ur +qZ$TpVZ2/~> +T`5,kp\=[art58,n`.';ASHI]]tqJ1cd0hVrl,/`ai)HJa3+D'>KY:<eC9'[()I`$)A!Yt<#?Jl +$l0/Kbf7iH`5T^>cSH%H(1u0mAIAqZ%hoQd$"g0[e]c:_cH48O`6?IX&/Gn@ccO5LaN2NHaMu3< +aj&2M[`6kDccs_Ybl5cbaSa$ZaND[(bQ,faa=#-ScdC(`bfn5L_nj=8db<R/]U4.O4qeP7*!lfS +&eu0$(t7-bb/O@r&];W5cAibZ&j+C[_8F73aNDa+c2Z#cb5]Q]`X^)/`5fg>a2uH=`6$'>aSX-[ +a8j6YaSO'ZaT'6k`Pf[:c,-&j;GL8+Nm?_SqYgEorVZZtqtTs`V#Pr~> +UAk8np\b$mq=XI[rs.]AfAci1r:p3is8;ip:\t+fs8N&uqZ$3cnX_3J,p+!K+WE#&p@k%!*$ZCH +BDql-rVuoqrr'#D+rVmQ+!;UQ*?c^R+JIcjr;HQnrV63ds8MroKI.ocL&1iKqtU0irr`&ns8CXM +(]XI3rr<#oo_/7Wq:`i[NbD-5.S@JUr;$<rrVp[Y*?p[1rW3&prr3?%s8Mrps8W&ts8;`m"8r&n +rql]qrqlU&qYp9]rr<#ljlGR]g@kOG$2OW!q"aaZqu$Ges*t~> +U&Q&.s8Doqs8W#ms8Mum_5a<@li6\Ps8VrmrVl`p:\t+fs8N&uqZ$9fnXV$C+W;%8*#C)np%=[l +(EOA7B)DW*rr<#srqri=*YftA*?#b=()e56)P#XXqYU0irV63ds8W#oJKPsOJbf?Fqu-NmrrE&t +rri)ms8;ijrql`orW)orrr)lprW<-!rqud5r;-<irV,pVr:BU3_OHHp8KT0F]);I(rqud%rqu_, +*#0EQrVQWprr)fkrqucrqYpL%qZ$Qnrr<#ts8W#nrr2rtrqu]prql^/rr<#pr;Pm!VOsQSVpG56 +qtC'hrr2upT)X<~> +U&P8ps8)Nfrr6g6rU]7-QZZeST>%hKbfn2Rc-48J_o9X6cGn/Nb0S)Sa4&:a'F,Hj&K)>l(Ojuk +Kb4n6%M27\bf.N>`PKXBN=?U7*!urY$l06c(`!U;^spi]c-aYO`Q6<D`m%m&&I2jiaiMHDbf\#H +rl#/abgXt_cIC.arlk>`s2Y2[rP\fWb5TUPc-4>O`l5s;aND`NaMuBF`l#^6c-Xtmf[e?e`R*,i +^SuTo7PGJn32G6Rc-!r=^VRn1cJ2G9&eT34`P97*_oBd?rQPSkb/hZHb/h[&`Xp2,a32ZGcH*o? +`5]d:b/VO"b5B?Yb5]Q_`r<pf_9'pAbK$N0=&E"*Ei.XTrr3&qq#10k"9&)kqP=.A~> +UAkQ!r;6?err<#trr2p"hV$02p](-i56(QZrVHQiq>:&q<?WG/*?QLH-_9i$qtg(4+W_^C.GXt" +rVuoprqke#+s8!M-n$Pf,:XTR,Ub0GUuV4@rr3H,r;Q`oZmd:G<;HLmrV?Etr;6Hms8Dlog&D$O +s8Mus&,uV-s8)`lrquNip%\7Ws7uX!rUqHU.j`%,kl)(hs82ipqtg<lrV6Emr;ZWm"8qujrql]q +rr2fsrr<#trW)lorrq!<jlPaYqu6Zqrqccprr/YlJ,~> +T)TQ&r;HWps8McLWhc?(o`+phs8VrorVlfos!msFrVQWmqu-Gu;]Zl!(`FJ6-(OT$rVQ@5*>ob0 +-JJLsrr<#rs81gu*r[)h,pFTQ*@):7*?c_.T]#P9rr3E+r;ZfoZ6^V8;>C+irquirr;R*$qu-Qp +rVZWns7lTls7uZjs8W)us8N#trri?$rr)fort581qu6?fqYpBcqssIRqu?Zpr;R*&qskaB,Tjer +rqcZlrr<#srqud,r;ZZorVQHks8Mios8Dutqu6Tp#6+T!qu$Bkr;Zfrrr3T-rr;uinu&LZSZ&+O +qY^0grgWq<~> +R/]nUh6Cj,@Xtc!a2lTM_oB^;b0%`A^VS(6aiD9?`Q?ETP<'-a(_RMs%1n!3`ll]X$ka9k&/DOp +_SjC4^rFL/#SS$l&/H#u$4Rg['`Jmr5_Ztq]?&.Bb/hTEbDZi<"u+3Ac,\)RaMl'7`Q#p<a32WI +b/q`EprNERs2b2^:X$u&`l#^1_o9X:aMu6BbfIfDaNr5Zc,n)NbfJ/\gXOctbfe/]dEfeH_oTp8 +^;%M'bgP#P%ic+J`lQ0=`P][7`lcHJb0%fF`lQ<DaSa$g_p$0HbK7cDbJ_0:aMc6@rlFoXr5eoX +s2G#U'ZJ)5`PTX<a1/<[>>A13CXMA<o_\Lbs8Dro!<&hqJ,~> +UAkAqq"FL\qu6cdf&,Qerri8ss8N#rs8W'rr;Q]qrVlcqqt0il9dpc!-5n$R,F/3'q#C3foTgXA ++s%r.q>^Kks8Dooqd(Kg,9J+H]Ct34/gqkb*@2dT<KbSts8DrsqtokVHbAeFq>^KjrWiK&qYU9i +r;YIL$N0l&s8MrnqZ$Qnrr3<'qZ$TjrVu`os7lQt_(-iQ-hmZ*rX]&.s8)`pqZ$Ths8W&rs7lHi +"8qujrql]trqu]nrVllqrr3#op\t0slf76oleVL9rri2rr;Q\is*t~> +Sc9B&r;?Nkpr&o)ZetNWs8)Qir;?TnrqudnrVlfrr:g5r9ICDl+r)+B+d;g#qZ$QooopI7*#K`q +q>^Kls8N#qqHY3]*?#u3[dr7#.3]ZI(*4>;;N]2ps8DrsqtfbQGe*2=q>^KnrVlcq#QFc&qu$Km +r;-H`rq?BlrW`?#rr;upr;HX+rVZ]pr;Q`rrVQWpp\b'grr2utr;R'%r4XI!(F&SQrr2fprVlfr +rVl`p&H;_+rr;fos7ZKmrVccls8W#rrr3#urVcWorqufrrY>J3rVuonr;Z]o]r%NpU7g'3qtg3c +SH"*~> +SH&WgHMdErRV#i<S@QY^aiVcK_oBU3`lQ0=_8478aMlB@_U+2n&crX_%hoTaHJHohbeqQIHP%#7 +(_VG>ai;0<`5Ta?5nOkQ'G=QCf>(f0((q)c'FbR/A!k*XaiMTCb/5Q/R)[FjaihrRaMl'7`lQEG +_SX:0`llB@rPn]Ts2t;]s2kGb`l5jp_#_Hmrl-P2bg";O`lQ?IbJqB2]Y2D/bg=eba25sCaj/AP +_8=45_8!h(`luo('bq)bb5TTlaMu3:_o9X:b0%g)`WO<)aN4>"(<=M@aNW&ReBYqQcc=)K^rFC8 +aNDZLr6"uZs2P&W*5fb7bJ_9:`4s=:_7Xeh<)R"7WnQb0rVccnqu-Kn!rMimVuM8~> +UAk;mo(;eY"4l/co)AXorVuorqYC$erVuoqs8GglrVuons8,M;,9e6O+rVqupAOm]q>:$cnPUMI +-64J9qu?]ls8Drsq4o&R+!KeGq>UEkm^d$[,UXo]+XSdSbl@_=s8Vrqr;QHjs8;]frr<!$rr<#t +s4@5NrVlcqs8EK-r;?Eirr)iqqt^9eqYC*qq1^%3,'!PXl2D4nr;Q`ps8VN]s8W#rrVZ]jrW)lq +rqQNmrqud(rV?6ds8V$/n`eiWqu?QmV#Pr~> +T)TQ)r;?Edjee`Sb4,H0p\t3mrr<#trql^orqu`ps8)co:*h#()]9\6.@9c-r:g-hrVc7_*>9P4 +,cghBs7u]nrr;bh)]BS6j8/KJs8))k@jE*<*Z#_<.V?m(s7u]pq>^?ipAb0kqYgBlrr;uso)JOb +rr;uspAY?rrVc`ps8W)tq>^Km$i9i$rVlclq#C0erqud*rr)VE*#0K2qtp?jrr2fprr2osrVl`p% +K-5*r;Q``p&G'hrVcZls8;irs7QBkrr`9#rr)ir&,c>!qXUeSUnOZbkk=fJrLNt=~> +TDq=Vq"jj^lH"3\C5&b(^W"UJc-+8N`504'_8XF6aN2KGa2#pC-4(+p'b_;j'mS*Vd`08E`6?If +'G)B%'njQKa2Q9Erl?sK#Sn9neD\m&e&oRq8eD[S*#K:t#sFd*b/;NNajJG`b1=hU_9L6G`P][9 +b0%rK`Poj:a8<jU`rF-Zb5]Zcb5TE[a9'B#_u@IQ_o;Vp1W[hebfIfDbfn&B^V7P'`Q$$@aMu9A +air/Xb0n)AaMu-6_oBjDb[:VY$<#-hc-OVT`W!dT`r='Y`r4!W`Xg53b0S;YfYPe`eB?+Y`m=V' +s2b2^r5e`S*Q?%<b/qW<^Vn.0`4s'mB1Yus??+$Kq#1'apA"UcrrW/rrMT[G~> +UAk;mp\=[d"8C@%h>R?[qu?Wls8Vohqu6Tp"9/5trr2phqYp3_Kd%BQ+<Vh[nFchVs8Duiq3Nf\ +,pO6L-fY1(r;HZns8VlX0H))][/0Oms82ckr9fUf,pspkcLh/7p](6gs8;`ks7H<jq>LWprVulq +rr;oLrr<!!rVZZn!rW#rqYpcns8Durrr;fn#P_=L,;,knqs"([rVlg(rVu&+e,'(8s8VigrW3&u +qu$Kns8W,us83N+s8W&ss8Vuos8)cqr86VoiS"20!r`0!rViVmJ,~> +TDoK$q>C0YeYB%BhXgdHq>^9drr2utqZ$Tprr3N+s7Z5A*u,M0)]aP#pAb!gs#0TJQS0F'*YTM> +iW&lSr;ZZos7ke1'c\C%p\+I`r;HHfl\cW%*uogSo)JX^s8Mior;-?koD\dhrr2rtrWi8ts8W)u +s8Dcnq>UBnrVl]orr**$rr)fprr)lsrr<!"rquckrs/8tr;Z`ps8Muss8EH*pJ`L^.AQq?rVc`p +r;Z]os8W&srVmE,s8W)rroJ@Np\aR]s7cNks82fks8DrsrtkP3s8;fps8N&up\OX/U8+H\VWRC9 +qt?W]J,~> +TDrm*n+#bsZ>aMkS@-2I^=(0Fc-XYTaMl!1_8XL>bg";N_8X46@gibY(_m[$d`U"[d*C+Yb]+C3 +*#fG&%^jO!`lulUcHX;G)%RT(T[q3"_SF4:eBDq>(*"$)XNAo3_9:!AbK.]Ge&BVQaiquMrl#2b +b/_WH`l,j:`;.FPaSs<bbf[rE`r3sY`r3k"`lQ<F`lQELb/hQAccsGD]tMA(`Q$!>aN)HHcG\2W +d)l:.(rjP6`lcNMa"%E"'84cRcd0hV`P]U4`lS/%!m&C$rQ+rW&')l<cHakN:p&="b1"_TaSj-Y +a8jBZaSa'Ua;W(BbJV09aMl?L_SN^8;,'bjEQ-l!o^;GJrLs7A~> +U&P/krVc`uo%Mjbrr3H*s8W)us8;TerV?9drr2rtrWE2ps8)`p/)hfu,p4EJm/$\WrV#pUPq+-r +*?-"C.'`gPqu$Kor;ZNko2@.X,B3JYrVlg.r;6Bas2;eQp&G!jrVccprr)j!o`+jeq#1KtrVuop +s8UaN!rW#rrr<#t&-)Y+rr)imq"aserV?Elr;$<sqY\0i;"";^l2D4ks8W#oqLfn6B[-STr;Zfk +rr;opqu$BkqZcusrr2fhr;-Etp!i'ahV[Jms8;kns*t~> +U&Pi*r;QWkkJO3t`VKB/qu?]os8W&nr;Zcqrqus!q#C6js!cnL*?Q1B($tkurr;ceo9CdL&f29" +*[S)ks8;forqcWgs7B/9'd%>fr;R?*qYKja_8#j=s8;oqrVuiqrVm#ms82cprr2oss8E0$rVuop +rr;lpr;Z`prVuWkrr)lsrr2os!rW#rrr<#s+92?<s8N&qq>1-grVHNnrVulss8MuqrqcN,MbNI7 +s8N#qs8W)trVuius8N#prseo+s82ZfJf>bAao;/6q>^Hno)AplrVuorq>C6l&,c>%oA6XFSXugo +q=FL^rh0:A~> +T)Wa#j1gLaB7de4`l6'?_oBg:_TC*Jbf\#HaNDcPbeM35aO&Y['H/29)$A78a2,s@bft2=%ga$g +'bq@BccX/Hdaumn_9pId*"N`ddEfVC_p-BKb/W,+T\%30cI'bSccaPS`lH6;f#u"Nb0%g)`WF6( +cMkun`Q-0Ab08#NaN4;!rQ,#Y!l`1#rQ>,\50D*odET\Nbfn/I_o9^?aMu-;c-ahX_o9L1_8*n4 +`Q,g5beqHA`l?6Ic-42NR;=V%cHOMTaMl-9`Q$'ErlkSgaMu<BqSj&icHFMZ>6"auXPM@OeB>l2 +`W*sWaSNpUaSa0saN;`RbK%]JaiDB=_6obD;+jl(Oko6trr<#sU]5i~> +Y5eM#qu?]qqYpu_f\Glos7uQlqZ$Tprr61#r:]p]r;Q`rrqu]oqu?Whqtkpe*??(EJ+rp=p\^L* +.iTER+!N!V`VB<+s8W&srVlimqkkS\*[g^^qZ$Ejs8Dutqtg9jrVlcqrr)lms8;ims8W&ss82Wk +$NKu%s8;lrqu?ZqoDSafoD\Rcs8N&u'E7t0s8N&ts8;ops8;lor;ZZlr;HWnr;Z^!qtU-fqu>p[ +&-)M)s7u"--6sc^B@$POrV-<jr;?Enr;6Ekq\B,-q"jsfrr)cps8;ops8V]QkhFe@rVm!!r;Q\k +s*t~> +U&Pc(qtp*;Xe2Q5pAb$hs8)`pr;QZp!<)os./s2Drr2iqr;Zfnr;(j](Ddi2Ie`sBq>?[)-l3XA +)BBtF`;09,s8W)r./j2Ar2(MU)C>(Vr;ZZns8Dutqtg6irr;lpr;?Tjs8;los8W#qs8;]l$NKr" +s8)]oqYgElrr2Tjp\t-is8N&ss8E-#rqucps8W$$rqufps8Dcn!rW#qqYpNp#lXVnqY9jcrr2iq +s8Muqqu6Km&,Q8)q!'(K*ulG5bPLr1rql`qrq??lrr)j6rqucqs8Moks8Vurq>^3(USjZWVs!dO +rr)lsrqHEorr;u(s*t~> +Z2ak&o)BR)p>`8r;H8%K`lZQS`5T[2`Q?9EbK8#QrQ>/a;96qt`5]^AgMI`E)%mTld)j8Lep\#F +$kOBp)&3UXdDj#EbKeS`c-OG[M@UC3%a<,0_S=(6aiMNCaNVlH`QHKJ`llEK`koO4bfn>W_og.# +a:HG;d)jJVa2c<=b08#NaN4%o!m&O,rlkDbs3)_4cdC([`lcHD`P][:b/q]Ca3W2Wai2<:`Pop< +aMu6B_Sa=ka:HG;c-4>Pair)_e'#tXaN"4u!li=*rQP>br5efU(sBqBeBGf1":GVJ:9`EucHO;J +`Poj:aN44ts2b5_rlkDbs2c/&dF$1Z_T9g9aMQ'3G#VI<@<TiXqZ$TorV?KlrVZ]qrO2`V~> +YQ"V%rqm?,s8W&rrqcQjs8Dutp?CN"rr36#q>:*frr2rrrr)cdrYOrM+!MmK.dHd&ZVDSa,oe$N +,Uf&VqYg6h&,lD)p`gn-,dRIFs8Mlpr;-Ehs82forrE&rr;Zcbs82crqtg3equ5p]%0$2%qt^'b +qu$Hnrr2opr;-Qnrr2iqlM_:ks8N&qK-_Zc,9\B[AC(5Qp\t*g!ri,srqufqrVZ]prr2utr;R2h +j5oRhht-mJr;6Klr;Qourr2rqY5a"~> +WW*P/qu-Qns8Dror:7Y!S?_/Prr<#trr3#us8N#rs7lTmru(h7l6@)_)&FR_q"V-f)]9V/(`FJA +PkXtMq>Lp'qY]t,)BL!)s7u]pqZ$KjrWE3"rVZWmqu6NlqYpNnrqlrsr;?NmrVHNjrrN-!p&=sh +rqufp"TJAurr)iqrVccqq#:HqrVlfks8W'&rVZTlrVlfqs7H<grt>;1rr2_E+rq[D)'0i*b52#6 +rVccqrqZTmrqufkrr;p1r;6?,X.l5\WQt8<rr<#srVlcpr;Qiss8W)tZi>O~> +ZMt")qYL'g!<2lq')_@VRVPi,N3Bn:dF$4X_o9X8rQ+u\rQ,#]rl?,"`Q$!Fb7G@-)A*\.d*S": +&fDc*'bCc]GLY'hbkfBkai`2d$P!jZLWmQV`l-0BrlG)]"3/F)bkoQ^a9Kf2bf\)Qc1fH^b5TK[ +`rF$R`rF*Vao0B\bl,W_`WO3"aN4>"s2k>]qo&QTqoJTUs2YPeaND`Oc-4>QaN4A#s2b,\rlG,^ +!m&C$rl#YjbKA,W=o\U9()@i+;RY?0bK%T>_oD\ss2P&W!li=(rQGSjaMu6@bg"DVb5KBkb082S +_15rm:02;,h=LIArrE&srseu+qtg'arVuorrVQKj\,Us~> +YQ"V%rqufr!<)lr!;ZTn"687rpAY'oqt^'ck5H.lIjlH_+shTB:+.,-*?6RV/!p88q>L'es8NN$ +HmKaYGl7U:s8VopqYpBls8E#rrVlcqqu63epAXser;H`srosFarqu]lqu6NkrW)lpqZ?]prquf] +rW3&qrr3>ADC6SR)BU1N-><DWh>R`\rr<#eip>a`mf!.lrqcTns8Mljqu!SrJ,~> +WrEY0qu6Tps7u]mp[GM`T=s[grVuosrr;Ecrr3r:pNn)#(`FH=Z:uV_*>]A6+"!6Ms7lNjrVlfo +s8W'-rUY7V(*Ii!s7lWoq>^9ir;HZp!<<#srVcWmp\k'iqu6fus8N&tqu?Tn!WE#rr;cirrUKm\ +s8;llrr`9!r;H$^r;RB+s8N&5CEjc>&f2K/+CtBIrVccqrql`krr<#krr;p.q#BimS"ZLSb4#-* +rr2]ir;Q]ns8Dr's*t~> +ZMt")qYL*h!;ufq'Dqh)lIV#5?#Z@7]#E"Eccj;C`ph(Latq&V`Q6>4(_mo*'P!F`'G)9((a0V, +Fk,$bcHjbXb/VE<`Q$'Gf$n%9#RX5Eb/2EG_oh_p"j4p/aNDU$b5BH`b5KQ^ao]Z,aS3[VaMu<@ +rlFZQr5]5baMu<@aMu<@aN"1trPnfWq8r]YqSrQVs2slQs2tA_)TKb8_oT^=cI8.O#RqU^'c@l% +9@_8,`P]U5rlG,Z"i\Bu`lQ=%bl>fgaMu6@b5TTbb5KBsb082V`5\lp8PiE$Ra:3ms8Vuorr;us +r<)rnqu-Norr';*J,~> +W;ckoqYpZEe^<gas8Vrrr;6NYrY4]F+=A?U-6OHM*$QXL,GFT+qtL-arXSo,qR[q&>cIQ!rVZZm +s7uZos8N#tquHWmr;HWirr`8uqt^6d!;l?br;QHj!WMuqq>U9jr;6Hsr;6Eirr2oss8E0!qt^'b +qu?Nlrr;6^&c_V*rVl`gcXeOT+=8*YK`1l(rr)j#o&&TskhlC>!ri)rrr3-!p\+C[r;QlsqtpB% +s*t~> +XT/;!%fcD*qtg6dpYMR?VpG)9rr2usrqlfrs7-'gs8DrsrtbV4koUcb)AsY<*YoS5*u>rgm/QqV +s8;lort#,-s7j)F-Wm>Cs8Dlpr;ZKi!WW/qs7uZmr;ci^s7cKnrVlfp!<2`mqu6Qor;QQm"o\As +rVc`os8N#srU'U^rt+r)r;HKab[;Y@)B]hBJc#EEs8Dros7-*`rsS]'o>d\tT:r%No_SRes82lr +qu?ZpZN#F~> +Yl=e'qYL-i(\mt'o^qY7[r65$NjHF<aN`,YbfI]<`q%1q`lQ<FaMu3?dE2t5*>fA$$k3OS(E!Yk +KZVff_op3Fbf\)Jrl#GgaNN&\R0+$_HGdnG`lQ0BprEZZaMu<@aN"+u!QrL_`W4!T`r=$Z`q@CU +b/h`Hb4*LMapZ;5aNDTHaNDTHaN4A#rQ+rWqT/]Vrl+oWs2b5_!R/^VaT'E_a8j6Z`=gD2c-4S_ +c)XGM((M#b%q<u1`r<sUaT'9[`W*pXaSX*[aSa3[aSEgaaMPj$Jm;/S?Z!p<mf*4erVQQn!<2ur +YlB4~> +Z2Xh'qYpQnqu7&pg=t-Ws8;idq>:0gs6BRrs8.Ho*$6@I+!DdP+X2s4pAb!fs7lR(r;Z]lla>aO +s8;fpq#:<kq>U9hrql`ns8M]k#QFYuq>'g]q>1!cr;ZcnrVulnrrN,prqQNhs82ios8N#t!<2uq +rr2lrs8N&r!W2fks82cqr9!tiqZ$Qpr;ZWhcX\@J)(ObHrS.;^r;ZHis7GL=nEJs,s8W#orr30$ +qtTs`rr2p#rquTfrjVoX~> +XoJA!&c2P,q#'s_d\`h@nbrFdqZ$QmrUBgds8Dp2s8N#nIiT4>)]9S8*?Q=EMWj^4qY^Blrr)j- +rVuckl*K:Fs8;fpq#:<kq>U*fqu6Tp!WN,urp9[brqZNgrqHHmrr2irrr2rorql`prVc`ps8Mut +s6K[^rt,&,rr;lqq"Dm=+s.OHj8AlSs8Drps7?6`rt>;1q#C07VjX!BVU#)=r;?Nkrql`prj)QS~> +YQ+Xt!<)oss8*T-n*fArXDMH]Z,"9&a3i;\bf[rE`Q%Jis2H8*bf\#HaNi7M&J5]l&J>cj'FtUl +aj&DVaN;HE`lcNJaN"4u&&cW6cGGRTf$D@UcbdcJ`qd^M`r*mY`l7knrPe]S!6F`R!6FuVq8hpF +rQ+lU"3&:!`r*gU`rF-[ao]f0b4<XRb5]Q\`YcY=bgOhddFGBg#mgS<^!=a>`Poj>b/h[%`W4*X +b5TK]b5]Q\`r<sU_[sl)aM*U@:et)+U>YY@s8W"qs*t~> +Z2Xh'r;Zfrqu6che)0`qrrhoer;?Qnr;HZ\rYPJ0kq",%-QjHP+<uF'p&4ggqtpEiqY^-f%fcM- +qYC0cs8W#rs8W&rqYgKmq>:3i!<2fo!ri,prVQZpr;QcprqZNis8;ip!rr9!mem%_o`#*or;6Bh +rqucsrqlEe!rMonl2Ch`s8VlnrVuon"k-m7K`1l'rr<!!p\b$j"m>@@ki;U?rrW2trr2p"r;6Bh +rr3*"qtpB%s*t~> +YQ+V#"oeQ%rqcWnr<p`>VS`*+s8;osrr)ir!ri,qo)AXgrVlis(]4'j-QX'G(`=53+F`\KrVZ]n +r;ZZkrVc`mrser,q=t!`s8W#rs8W&rqYp0fs8N&s!<2`ms8E#srqlcqq#C3imf37brVc]ms82io +!WE#qs8W'"rVZWcrrN-!mJd+b#6+Q#s7lTmrr<#m#16a0K)GTHrr;rr!<;clrr;usnGa$tp"lX@ +R\$G*qY:$gr;?NjrrE&'s*t~> +YlFb%!rMikrr3c/p@.A'Rq#lQZFnB%dFQXgb/hTDb0':r-H=$Eb08)P`l?-Ja:o=#*#05)&J&Ho +b0.fG_SF=/_8OL?b/hTBrl+oX%+32>e]>tV`lQ9Ha2e"s!64fQr5JcV_u@LP_uI^U`r*mXb5'9[ +b5B?O`r4!Wb4NpXb5TK^`r<pZ_o9O4rkncTs2P)["Nns4b0'.nrl,kt`llTGbg+S_e'?=@3t#<? +bK.]B`lQBJaN"/!rlY5]!li3urlG,Zrl+lVs2>Vg_84"0aj%o?Tk.;#<G8,^li$h_s7u`mXT*e~> +Z2Xh'qu6Zqr;QlOiS+80rrVWbq>UBrqt^'brr;9_')hk*JfZ$Z*?lMSl1t)Qrr;lqrql`qq>Lp) +q"Xmequ$Kirr)cps8)ckrqQEkrqucrrr2iqqu?Torql]ur;$0cqu6NnrqZTkr<E2sr;6Ehqu6Nm +rpg$gr;ZWpr;QWo"oJ)jq>:'dr;HNWrX\l's8W)ss82ims8;c3lhUMY!<:pT"8`&ip\k*qp#Y>r +ip6UD!;l]o"8r&nrr2rtquH`*s*t~> +YQ"h*r;?Qos8N#r%I^s9Vp=o6s7u]ms8;lps8VusrU^$fs8Drsrser,p3mhr)\a8/I-:>$rr3#t +s8Mrrs8;lps8Vm's8;cls7uZmr;Zfns7uZfs8MuurVlWmrr)oqrVHToqZ$NnrVc-`rVlcorVZZl +!rW#rrVuos"9&/qrUKpTrr<#urXer(s8W)ss82ims82Z0lM1AWs8Doss7lT[rtYJ3r;Q`oo^0Dg +T:`$oq"Odfrr)cnqu6ZqZi>O~> +Z2ae$s8)`p(]*acbD^XVMQX_2_:6fZbfIcB`lQBJb4E[n`l5p>bfn5L`lHTU@gEY`'c[p,cI9kS +_ns./rk\]Xa8X6]aT'6k`Q>m1bJqNBdDO&G`lcHBbPB3a`l5s:`l5s:q8NHS_u7RS`r4!Wb5]]_ +b5KE[`qdaPaSj-WaSj6^bf]q/s3:Pes2t>^s2OfPrl4uZ"3Sj3b3d:M`rF*t`5^0Mb/qiIcGn>X +cBc,ab/VE>ai_iOaN"5#r5o5b`l?!8_o;>hs2G#U&&$'%b1+SIYBNuB<bm`Ll2L\bq=OF[XoEn~> +WW*1rrr<#Ig"-0&"9%rnqu-O!qtKdYrr<#`rY#8%s6VB_*%)^TbOPH/r;Zfrr;Q]srquTk&,lP. +qu?]qq#C<ls82]ns8)`ks8;lpquuunq"agbq>^Ko!;uins8;oro`+mh"TA5rqu-Nk!W;ior;Q]k +rrN,sp&53rr;$-`q>:*frW)lpqs"(^s8)KhrVm-"s7lTnp\t3lrr<#Trr)lsp\t0skMG1Yj5'Y/ +rrW2triuKR~> +YlF_%s8<W1s8N&koqJ@enau_Tqu?Zpo_\UcrrN,to)AXgr;Q`r%J'Pa-lj!C(F@/mr;ZcqrrE#s +rrN,sqYgWtrr<#rrr39"s8DrsqtpEnq>UBlrVcfsrr2Zlrr)lprr)lrq>UNqrVc]ms82cnrVlZl +!<2fos8N&srqlcpo_nmkrqZTmrqufdrr)lqrWE2sp\t-k#lO_trr;`ls8Musrr2rtq#:'gqu6Wq +rVd0(rr<#oqu?]l`Mrj/!hn-:rr*#trr;urrrE&)s*t~> +Z2Xn(qtpBkrr3N-iQc(FE4*<r_o'mDbeh?u_ZRm!b0':r"3/6raSsC%aMuH<e&N(5&K_],[Em+@ +]u%\)`6$<Jb/ha&a:QA1aN)0<bf7HEa2lHC`QH<ta9KZ*`lQ0@`qRRKb5TTbb5KE[`rF!U_?.Nk +b50?Yb5o`)r5J]UrQ#)`aND['bkoQ_aS3^PaSj9OaSj-YaT'C&dDj#DaiVWE_T'I8d)F5SaMu3= +ai_iO`l?*@b5TWbapQ50`l5j5_8F73aSs?^aT'9[a;N.A_o'O<a2u`N\pdpb>%2?RmJm.]o_A:\ +r;Zcp[f:j~> +VZ-_?g#N&2"9&/lrr)j#r:fs\r;Z$\(]==3pmWQO+s/"=rV6EhrV?Kgrr;uqs7uWorVlisqu?[$ +qu$KorVlinqYp<jrr2rqrVQWi"8VilrqcZprmC`TrqlNequ$Hms8W)tr;?Kis82lrqu6]rr;QTX +rXo#,rql`pq>^Kls8Vrqrqucprr:gRrVm9&oC`(^s4lbtjkTb.s8W)(s*t~> +ZN'q's8W)ts8NZ,l(t2\nbi@_s8W)tqYg<ir;Z<drr;oq)#sR7rUuR"(E",4@K$'&r;ZZoq#:9k +r;ZTl!<)oss8;os#Q+H!s8DrsqYC-gr;lorrr2Zls8Mlnrr)rrqu-Bkq>L$[p&"I_pAk'hqu?Qo +qu-HkrVQWprr;rsrqQKrrr)fprVlfps760es8Dp-qZ$Qls8Vrqs8;osqZ$Qmr;Zcqs8Vooq>^Ko +rVccqs8W,u"o\H!rVQKjrsA]#or"RVStk*1rr)lr!<)fp!<0D+J,~> +Z2Xq)qtp?krt>;*kJV=IC9tk&bKeARaMc0=_u@XT`pq+m`l#^8b08)N`l$!Ac$Bm7)Aa&ZfuV7H +]tDV.bg+JUbk]?[`sp/2_nsO9`Q$*Ea2lNDq8iKV"j"j-b/ha(a8jBZbkoQ_a8s<"rPSWNrk86B +!5\9Es1n]MrPAKNrl+iU!6G/^rlFWPqT&ZZn]:aM'ue24aN2NH`m2ZEaMks6`PBR8`6?=$`X'W, +b08#J`lQ=$bQH#/`l@tr,f@UBbg4\accjJM`lQ<Ibf.N>a3W)TaMPHl@9m#@DSY6$o_8@]!<)lr +"9&,orO;fW~> +YQ"t.s8;ZirVu]De+ik@"8qujqu$KoquQ]mkPbtis82I7,p=HR-d)A_s8UpSrr!N0rVcThrVQHj +qu-NlqYL-hqtp3gp]13jr;ZchrtkJ'na#>sio&_Nh;$fAh;7,Lio]Rtq"s[_&cV\'p\4I[rVc`q +rVZTns8;`erri?$s8Dc8rWN9!s8Vrprt#&-p?gi6qu$Els8Dims8Dlq%/fqss8)cqhqmVXhu3QS +!WN#qrri;urr;r*s*t~> +Z2YI9s8;opq>^<ff;GLro(W1]r;Q]q!<2uq!<)fpoD\^grVlis%0$;'nfJnj*?$6Hrqucq!<2rq +!<2orq#19noD\af$3'u)r;?Tor;Z`ps8W&js"aQNq>0s`o'bu4lJg@=_n`jjXf81oU8"?STV8*T +VP^ArZb!rjbgkV6lgF<:q"XU[r:g3orr;rprr2p+r;HKfqY^<iqu$BjrVlierquflrqZTmrr)lq +rr<#trr;p#rr;ors82fq'`A"(le_=0qY^?mrqlWmr;QZnr;HTos7m&oYG.hbUsSo3s8VuqrW3&u +rr2ur[f:j~> +Yl>F9q#13js7+mDCL`jF]ZA=Abf\#HrQ#2caMu3:_oD;h)TKb8`lcNLb/VE;ai_p;()Il$&?*jk +`Pfd?rm(Vib5B9ZaSs?\a8j6OaSs4mb0A2Rb0A&Nbfe2Tb/hZHbfn>UbK7oNbK%W@_ns7,_7mRo +\@/Q5R#d,XIX#mPD/!TnA7T7`B520uEHZb_MjC$;ZaR?T]tV1l]YD;!_o0O4`5]j<aN;QFbg=b^ +b0A/Pb08/UrlPDca2uHG`q%4N`WO3"`lS)#s2YGb`Poa4`Q#praSj-YaT'E_`]2&^bg"DVbJqWC +_T9mA`m2]F^"1fbcH=2H`Q6?KaN2NJbf[rEa18mkDd6FIC8TbLqZ$Bgq"jsgrrW)mrO;fW~> +Z2Xk(s8N#srrViBg\q-Xq>^Koqt^'brquctrqu]YrX]&)rr;ql*?uUJ+)gcNr;5CNrr3W1s8D]j +rVHKms8;opq"t*krqZ6e'E.@Wg=b*)cHt(mg=tB<hVmPYl2Krbl0@NulKd]tjl>@[i7lu=f$Mdi +dFd=Br:9jiqt0ISp&>0nrr2rqao2AAqt^6k$MFH!mY*889>16%rVluss82fnrt58.qu?Tos7b.. +l/C_'s8)cprr<#q!<0A*J,~> +Z2Xn)s8N#ts835LU8lo<s8V`hrVlcq!<2uqs8DoroD\^gr;I9-qZ$TmT,/F`)]Wbfs8;cnrVZ`q +qu?!]rr33%s8Vurs8N#t*rQ'9q"t*krqQHir;HWmq=XRZp$Ub`]<@lpOc5<_r075H&"&fUR[TV3 +R$jD3S"#h4Q2[!WO-#KcOd)<-Xh)a6mI^DP"8VlorVcZorrW2pq>UC!rr<#sq"agarqlcprr;Nf +rr;cmqZ$KmrVuiqs8W,urqurus8;`mrsJH!s6P=e)Fh72r;HWtqu?NlrVZ`qrVmE(s7FI(US+9g +o(VnYrVc`"s*t~> +Z2YX>s8N&uqs`O7@qD%@cHNuEb/hZD`lQ=%bQZ/1`l5p:o>h'S`Poj<rlkD`*59D8e:\2H(_mET +b1"ALbg"P_c-"&D`Poj:aN45#!Q`FWaSs:7aN;WHcd0eZccsPUaMc-AbfIZFaiMND`PT='^:^kP +Q%XBt@pW8@>[LlH?=.)KraZ%:?2\%.>rQ(q>?P$.<a&^7?X6uGA8$.:Oe]1j\[]2^^r+%,_SjF7 +c,mrDbL4__dF-@`aihfJa2Z*<a2[Yjrl4uZr6#&\!64uVs2OuXrPnfWs2G)\b5TX%bfdo>a2c<> +ce$-G&I(%cg==NlaN;EJrlY8b(<XY9_o0d9`jUUs;H$nUeEQQ$q>1!err<#s[f:j~> +ZMt(,qu$6err32Vh!"\9s7uTm"oeGsq>:0hrrW,qr94+hr;Q]b0-VDV+sG8*s8V'W"TA?!s8W)t +#kn2qqtp<ks8;iq!<2fo)#j0agt:-+g#D)PioK=flKIHulg4!+mdL/E!qPmQp$`O]m-EltjlYOW +f$MXffA5fiq>^Hn%/p%tqY'XYqYL-is8Musa8QhPq>^Bjs8W#h@N6L5-miEqq"Xg\s8;cprr)j) +qu?Hjs8V<>l0I?`rr39$qYU0frqu`o[f:j~> +Z2YI8s8DutqW4fR[GLf[qu?]qs8Mrr!WN#rqZHcqs8VZhrr;oqs8NQ,s8D=7)]'82+3jQZs8Dlr +rqcZ^rWN3!rr<#tr\O?Ks8DimrVucos8W)srr2T]naYo"ah".6P)YH_Q^aJ8T:r!QT:M[KT:hgK +TV%gISY,bMr1=n#T:_^FSXuICR?N\kOd_rF][>d+o(DhTqYU0i!r_uorr2rt#6+Z&rqu]mjo55Y +p&=jgs8N&srr*T-s8Dlqs8)=p)&sVA,@L0>qZ$Bgs8W)tr=Ac)qu-Qa_53]nT;^oMrr)cps8KG+ +J,~> +Z2Xh%rr3Z/k.,G=F/$[taihlH_o9U7aND[%bQ,fUaSs0naND`Nb/V?8`m;jE',_Q!$Eh_%d/M?" +c-"#?^Ve%1`lQ6Db5BHbb08$(a>1fWaN;QFaNDNHcHF>Nb/qWDaiVQA`Q,g0^V77ZQ\]Kj?<:32 +?t<bXBPD3rBOkdhBDuNCBDuNCBDZ<>B*2g_C2*W[-u!=)?<LB8A86FIT<>];^V[n)`5^!GbK8#N +a3)TKbg4JTaiVQA_o:r_s2t;]!65#WouR*O*lZ.?b0A2Tb/M0?`5^'QeC@+r&/,oq8^bl)a1f[: +rQ5hq`l?!;`6H6=_l@lZ77^R$_s$glr;Qcq[/YX~> +ZMtR:r;?Has8V-6o`+sdqYKsdrr2os"8r&nr;?Qrr;6EWrX\o*r;ZcnR3*On+!>:ls81dS!<<#s +s8<)ss8;]jp&>j,p?()\g"bKMme$8Kp\"(ClKmm)m-X3>mKE"HmHs?@nGi%Xn,i"FmelMTlg4'= +n.G'RmI0W;naPu5kiL^Sf%fESq>Ug"rVZQgqY^9gqu6Kmb5N4Us7u]pqu?A1,97pO(Eb#'fDYLE +rVZWnquH`orsS]'q"asinE'$%iRe)/#Q+8jr;Q]orO2`V~> +Y5\n$rTg_^^?tmns8Vros8W)srrE#sqZHcqrr;Nfrr;rr&,ZD*s8MhZ)&aA2*GG3GqYpEnrqZT] +rW)usrr2lrs!@[Es8Mups8;Wbp@\%GcG$<JP`_&gQ^F53SXc.<SY)ULTV.mJrLX@eSXl:BSXl@D +rga+ZS"9JK)P!@jTqS*KR[ftATUqU>QBIDlO-?6C_<(+ZrV?Nlq#CBns8N0!qu#RTrVuNhr;Zfr +s8Drr'*%h.s8)]cD]]f9*>0>9;qM$Fq>V*,rVZTmr;Z]is7aO0TVA$QiqN?Mrr0A+J,~> +Y5]+&lbdaEFK3I'cHX>P_nj70`r='YaoT`2rm(Sen]:^L*6?:Hb/M?9aNW(Y$Q9ru$r#."cHjh] +bf7K5^;Kris2b/]r6,/`q8`QXrQ,#Z/]Q2]aN2KDa2Q3?_7m[u]""2eG%b8j?<guOAnPdg@q&t[ +BP2!jAS#IcA7T3L@K^:UB4tuXB*)UTB)H9\@q91cBkV'fAS5dpC1h*f@:3>F?Yk1MYdV9_rkeoX +`lcKIaSs?fb/_THai;9<jiID?!m&O,pW3?R2oWeXb0A2Tb/MQ>bKe>_e6Wh%()[Mm&N@&EaNVZC +a2l?A`Poj<bg+DY_7.(^H;7"+=),D.q#13nrVj2(J,~> +Z2Xk(rVlfuf\>9^rs/GtrVcKdqu6Tp"9/5rrr)iur;6EWrX]&,r;Z]npb*m2-5n2Zq#B=P!WW/u +rVuj#qXX1OrVcTm+8"LDg#1iKk3MI+o'c&:o(2MJp%%YBmdBQ6o^;/9nbr"]n*]W2mJcPRnH/4K +mf)SVn*KB*m/HJPnIP3_o^_SAmd')tj58M;fB2u1$3'bus8DWeq"amds2t<Ys7lQkq#C/\+sA$Q ++sS6Q*$NH(pAOmbr;?Km"T85ls8;iq"o7*9n*/L(rrW&mqYpKprjMiW~> +Yl>43s8LrRU9*k[s8W&ts8)`prr)fqs8Duq!<)?brr;us&HD_-s8;ff.N]?J(F.E&rr)iqr;Z'] +!WW/urVulprtPD.qXs7DlIWVAQBRPtQ'n5;USFL]Se%B`StD[LT:VUGTqn9OT:c(T"J26XSt>qR +s.TRgTV)4T"/DTaTDkJdStM^GSGf!#USOWUS!fV1P*;B?c/eEgqZ$Khr;Zfns8Dlos8W&rlMge_ +pAP'lq>U?ms8E#srr*`6q>U?es7Vg$*#]k>*uu==+3=KWs8W)ss8W)ur;lrrrr3?(s74U;TVnTV +h>%!L!<2ut!<0G,J,~> +Yl>43p>iSr?"L4Rb0A5XahdtqqSi`\b0A8]dEM1&!QrL_`>cn@bg")B`l?<P()n#.#R[i_d*9eW +aMl!1_8c8kqo\`U!QrL_a8a43a2>g7a2>a0]XPJ\V20,%?sm;J@q]RlC1h-h@U`hXA7fFd@qB1_ +Bk(X`Abp$=Ac?<AB`_s\B)Z?hB4YUbAnPagBP1mfAnPagC2.Eo@q&qY?X@AnR'=3;^VIUr^rXR3 +rl"rZaiX"mrQ>,\rl4iVs2t>^!li=&rlY5]s2I(<`lQ<Ibf\#N^Vn15g!tZh)&=&('G1]W#-$:t +ai)$8`P]O0aN`,_cHjDD]u.%/=%lUsA%:Ons8Do's*t~> +Y5]!if&6&ts7uZoq"asgqu$Em$2j\tr;Q`rrqu]YrX\u-r;?Qlrg"`G*$ZeBs8V'W"98B!rVlfs +rqcX!qrQYae_]Qin0%;no'l&4lL"!-nF5o9n*TT6o();=mdfo<nF,f4mI0H@m/QPRm/QG[mdKZ4 +lg!g%mdKZEmL/OWp%.Y;lKn$3o^`"N#4:I&dFHn;p](9k!WN,?rYbP3rVu]m`?llK+!;V3+!2dO ++dDd$r;Z]orVm-#qtfs^r;ZTkrrqE=m-<I(rr3#srNlNS~> +Z2ak&'DB>?WP/!&q#CBjqu?Zqs8Muqrqucsrr)3_rVuos%K6>*rVufnOrb;S+=1Xtrqufmrqufh +rWE3"rVcWn0E1hBqX2e;Um$h#Q^XA4SXuLHSt):AStD[ISXc.<SY)RJSt2CET:_^GS=?"@U&1M^ +Sc>8^T:l1W!20=`s.CI*S=H1DTq7gHTV/$SU7e'JTV.a:OHuT[iV3<Hq#(-js8Vutrr;9_rVuZl +rVu]mrr;oq('".1rr;cj_&sj6)B9]$*#p+B*g6<qs8;iss82fq$hsSupZnuQUSOa8q>C6nrr';* +J,~> +ZMtO8qX`O4CM%q%_8=LHaiV]D`r4!U`WaH+bg"ASo>hrpbf[oB_oBjCbK[l>`QHYR'bLla#t!1f +bfIlF`r<sVb5KEZ`q@D5aiMNCai_`Fahbg,]YV"EI;`Ir?Y*qaA7fIfB4YLZ@q0%\@UWYQ@:Nk\ +An5C\BOtgeAR].ZB4q0Ts(D=As()=FB4bX_raQFKARf4X@U`t]ARStT@V#IOs(<'^C1CIM?tbIn +]>;4p_8OF:ai;?AamdCMb5]Q]`r*pXb5]Q]`W4*Xb5]Q^`]D2`bfn5L^rOC;bh/^&*"s"u$qgs; +'b1[ueBc.T`Poa2`Q6<Md`BSM`k9:1\>3S.<*X=BiUQ^Ar3QER~> +YQ"_&f[Tftrr`8qp\k!h!ri,nrqHWlr;Q`rkPc"cs8Muss7cO?+XA=^kPtA:rW`E%rVlisr;?R' +iR$'#gYqA`nac8?mf)VRn,MnTmL&IRo(2D?mdBQ5nG_hYn*oi:nc%qUmKN"Gmd]f9rpTmT$gmBO +naZ,;n+?5AnG_kXnF?#ImK;qGmI1#?#OUgBjP8AGq"t'prqZHfqY\M8)>a@4s81P&+<)@D-(Oh@ +-6XTU-?8bTqY^?krs/K!rV-<ir;QWo"Ph_njQ6C@!ri&o[/YX~> +ZMt@4r:A@9U<iT,rr;oorr;rp!<2ips8MusnG`Cd!ri/kr;R)sr$*4*,(AbUq>UElrW)oprqQNg +rYY\7rVlisr:fgPmanY3Q][Z(SY2^OTV.qVU&UecT`C_`SI2!^TqS*LS=H.AT)P8`StDXJT`1P_ +TDkD`TqJ(XTDtJjSXuLJTqJ$MUnaWVrh0CfUS@a\"/2B[U&L\rU8+KVQ]R?*_r1([o_eagr;HZ^ +rr)lmrquflrr2rqrW3&rrr3`/fI.XR)&jfhq6_Fe*Z?5@pA=jhs8Dros8W!*s8DrsnZSISR\\?t +rr2p!rql](s*t~> +ZMtU7mF\F]B99g?b0J,KaiVK>b08*-ap?56b/hT?_8F:aa=#-Sb/M35`QHHEcc*]@b/i<O&eG@S +^<a^:`Q$!?b08)Sbfn5NaN".srl4`S(s0k>aN;QD_SEgrUO6]a>[q;VBPD*kARt^Ms(M=B#\[pe +BkM!fA7baP$Y<p^BP2$mARf4\AH$'?An>QQAH--O?t!PUA7K(VB4PO]@prkV@q,FF"(>YIA,^!P +AS,Lc@9d)UNN9\.]uS@<a3)TIo#M6^bfn5PaN2B?`Q$!?r5o&]`r<p_`lQ<Fbf\)LaSs1$aND`L +aMkp3`luf=&e#Eh%h=0HSe;eX()L*"ahu*:qo0;l`6HKJbL4PR`j0DZ;Ggu!b3f')rrDr)s*t~> +])Va.qu6c[db4<mrs&K"qu-QorVca'rqlNdq"agbrr2r\rX]&*s8Vlns7Vm0C$#0grr;usr;Z`n +rVcfsqYpNpr;QKk$2!*)hr<\]mI'H?mf2VPlkSpSm-X0+lKIHpk2bUbk3(pijlPO_ro=CJjlGOc +kNM*kjo4<Yjlbghk32*pki_*ll0%9rlKRNumI9W6mdL/B&+8iOmI9W6nFcGCm,6IIi;3KOrW)ut +rr)cprr<#orr)lsrr;o\rr<!Np\aen*$lUM,B*DPq9:-/+s.t4k5>/Vrr<#trquQfq>:3lrVcWj +s8VB<mHWj5s8W&srrE&ns8N#9s*t~> +_>jN6q#C?m&H)79TVp'+q>UBnrVuosqu6Tm!<2WjnG`Cds8EN.qZ$Tks8V_Z->;N;rr2lr!<2rq +rr**$rr2rtrqcZlrXAi+rVZQhq=aCE^RUGcSGo2_TV).Rs.B:`!29Cbr1O+`rh0IhUSOc`rM9Ii +s/-.$WN*##X/`.trh^:*VP^2dVPU)`U7n<VTq\?XUAgkdTE:aYU&LbfUS=I]U(sAoS=,k;Q^+2J +f]r;/qYpNns8W)urVlcqrr)orr;Q]qqYgQrrr2iqnc&Of'_hLu>8J@u+!>Frp\E#U*uu7@=m#V\ +rr3f6s8MusrqlZmq>0]rS>)RLc1V)7rr2inrrE&nrrE&<s*t~> +^Ae?7qtp?jr;RH-qX<+$D/><C_TC$HbKIuD^;e=pbl>ibbl>fh`l#X,^W,ic*R)[F_o'I9bgOMN +`P9F<c$^*r_pZlTai;<>aNDa+c2Z#fao]Z(`r!aT`r!jV`rF!W`>$/%[uG-1BPD-rD/3fs@preQ +@:<[FA-caYAnYjmC2%J^C'8<gD/O:jDZ=V^E,fl9E,fo=EH#jqD>nGQD%g`#BkV-kAnP[cAn>L_ +A7K+X?srqA)e*5`@:E\S?t<eZAR]"]H_e$c_o'L8`Q#p=`qIIXb08)PaN2C"`<aK)b0%rNb/hU% +`<+'#aSa3ZaT'C3bf\#H`lZ'Acp.^I&f)!Wf@/?U&Jc9#%m[qVc-",I`Poa4^r479dEqm9s2GP[ +H;RO8?^fR7qu?]qs8W)srVllr_#Jo~> +])Mp2qt^-grVluhf%'QprrW/sr;6KmrrE&squcurrVQTo#lO]$s8Muns8)!Z#l!*Gr:^0cs8Mlp +"oJ)iq>C6krri8us82NfrrW/srVHO'lIseCj6>gnlg4$-nF-;E*V&XfmdBE*ki1[_hqm>Mg"tQB +jm2F.pA=aes8DfgrrDurrtk\3q"XOTo'GT#iS`YQiT'(`kihL*o'lYH'_(JVnaQ&:n*ol:n*]`9 +mcN0Oi;3BO!W)]ms8W'$qY^Bkq>UBorquZorql]trqlTjo)9O*s7lNhs8W&tp]'er+X%mO+("m@ +s7cEW>Q,iL-R@.5rr3)ss8Mopr;?O$s8N#ts6JJ%kMu13s8Vusrr2otr;Q]urqlTj`;b>~> +_Z'c<r;?Nmq>Uiur;6!&V5Vo:rVlcorr)lsrW)orrr2rtrW)lqrs8T&rr;urqZ$Hhs8N#rs8Drr +s8W'(rV"q;rV6Eis8N!#rVZTjrVZ[Arr)fqqu6Wpq>^KmrVlcnrr<#qqYBU/YaCK9S=lOITV%gK +TV).R.%d*'TV%pOU7e9XUo(/nWjfRR`6-KXf\PKHk2bRenbDkOp%\=PlK/$-(?=?/g!Is`_7R(Y +XfSM!Unsl^T:V[Jrgt:,UnFEVU7n6QTqS3QStD[JS!0,:bNefqqZ$Hhs8W)qrri/tq>C6hs8N#s +r;cirs8W)ts7cL8rVuZjqu?]ps7cQaAKMs3*?&)Up]'s`l;nuG*$??Knc&OjrVuoqrr3r:rVc`p +s8;fpnAM#mT;0C%qYg<is8Vumrr2ils8N#<s*t~> +_>jN5"T.obq"t$i$i0MbfU-GkQFF]Ma8X:&aMu-6_oBd?b08)Pb0.cC_T9[7_oU!Fb/_HC_YV:O +aSj*\aNDZHrl,;db0A)5bL+AV`m+M(rlPAfb0%fHr5o2d`Pp*@_#DFnb0.iF`Q#m4^qmORIV<%q +A8,akB4kghARt^J!+Z";s().A+Co2&C27g0Ee&h!Ng6*+U8OuoYcb+7]>21p]thFpZ`jA46a!Jg +URRR4N.cY)G&qV?DJa6*BP1skB4PObAn#7[@UEGJ?XdPT@:a+a@U*8[PH_X2^;n(,aN;HAaMl3D +ai2WIb5TK^`r*d]`lQ<Fbf\)LaSs3Ra?@Yk`5p!Db/_`Ff$$Vk%h9*T6eg#@`lu@`%hocp%(4U= +b.tU(`P][6`lQENbf\)MbK[JF;+XJePhb['rVm/so_\Uds8DinrVllr`rCP~> +]Di$5r;-?frVm5ef\-'"s82ior;Q]q!ri,qq>Lp%rVuokr;Z]prqcHhrr<#_rWiJms8VopqYU9k +r;R?*q>:'err2rrs82]nrqlBeq>V!"gX+U7n+,o9nF,i9o()8KnGhqdnF,W+lKREiiS`e\me6/M +#6+Z&rr)iprr2uqmf*RblfI'_jlbdgrTG$bmHa-*n+-,5m.'Z:nb)PIm,?O?f(Jt@s8E<(rr;W` +s8N&nrr30$r;?HirqucurqlTjo):$8qu$KmrVZTmrqD[&-PmpP,2W(nqZ$TjpP'q6)_!)=oDA=_ +rV?Kirr2rtq>^HuqV^H"g?nn>!r_rmr;R!!s8W)rr;OY7J,~> +_Z'`;r;?NkrtPJ4qu6QioY7<'ebo:>s8W)trVc`ns82d,qu6Wqp\k-is8DcgrVlisrqcZbrW`Dl +s8W#srVc`pr;lipr;Zfr"TA5tqu6Tp1ALeIs8;corUf[-W0<@/R@Kh?T:VXITqS'MT:hdIT:hdL +Unjc]VQ-r5`6R-&o_8%PrqI-&qu$<equ-HirVulsrr)lsrqcTk6i6`UpA=^^q"OOTo_%J%ah5!_ +WMZJdUna]ZTVJ9SSt;RKVOXBXU7IdDStMXBQ'J/ckj\TOr:p3hrr;fjs8N#ls8N#qs8Dorrr2rg +r[.U@r;ZcqrVZZnpQQgH&fi)9g@Y=>s8VleJfY[@+s3rVqt^9lq>C73rr)iqr;QThs7am=TVe9n +q"=R_rr;usqu6Woqu?Zpa8^Y~> +^]+K9qY'XXqu-O&q!6Y"DeYKL]Y;P2rlcD*`l5j5`Q$!Abfn5N`Pp$E]u8+8e'6"UbKA)PaSNpH +a9U&(ccsMUaN=;$1<@JTaN2NHbfn/O`Q-0C`kTO;bf.N@`4NRHDd6RWBPD'lB4bahBk_0lB4Y[e +B4kaerFmHlDKgSdPFo(i^V7M"_8O=4`l,d6`l5m9b/h]Ga2uKF`5hku*ll:>_T0X6_8*du]Y(PD +P(\4)EH#c2C2.EpASGadra7!]Am8\T@p`PO@qT=Z>?YZtWjK[b_7mh,aNVK;bf\#CccF,IrPeiV +rPeiYrlXcP)Tg%>cc*lA`lucVFpo)o&deZQe'lC_a2H29rX^1j':R=j]u.Y'cc3rC`lu]MaMl3A +a3(oH<D-=sNSWmurr36#q"O[cs8DoorrE#;s*t~> +_>aN7rr30!q>C9mq>L<pe(E7Lrr_fir;Q]q!ri,qq>Lp)pA=aerVulis7q5$qXjgPrWiK&s8W#s +rqZEf!;ucp%K?8%q#CBns7uNkrqZ?gru^phdG*[GmdKZ8o^qbJo^VD9lg=0/lg!fugY1WJmJ#fD +"TJB"rr)Qjs82orrq6:7qsih*h;@5Qk3;7#n*o`/nEfE*nb)SDnaGl2k2+\<h>[<O#Q=]&rV$9c +qYpKurqlNgqu6Tp!<2uqnbsp9q#:<hrr<#sqlq@h(b$OLchd\@rqHEls7`]K,oe3QL]72Nrqufm +rW3&tqYp]Zi8a(Prr3'!r;6Kn!rDio^]/f~> +_>jN6r;RK1oDJC[p8P!jm/$2Ns7ZKlrr)fpr;ZZn&-)D%r;Z`qrU^$_Itd^is69Lfs8Dutr;Zfr +q>Up'rVZTlrr<#ss8W&tr;Q^`rV$$_m`MGlQ'n28StDXGR[KY9S=5h6SY)UJStDdRX0T=Te)^&i +p%S1Squ$<gr;6Bfqt^'frr)fprqucps8W)srr<#trqufp"oeDrr;HWnrrN)orqHHd#N+"K\?W09 +VZ*84U8+ERSYi-PSY;jQS"H=HUS49HQ_hsmo_\[erVQToqt^6ks82orrr)lqrr)lerWN8rs8Vuq +ruh:9Yot,$,8qQHq#10jq#CBnoVs8['cn6Fr;-Hmr;Zcqs8Dosq#::'rVlEGXIYlYU%n<[rr;lp +rrW,us8;l7s*t~> +^],#Hqu?]prVuQho^CLXC2L,cZ,Y#%rQGPiaMu3<`l?*@rlPhobeD!4bfS;Zbh1<F>g:16b3I%Q +bfA#N`luTFq8iTUs2b/](!"_Ha3)<=bfIT3]u7IHF'`9cB4kiUB-LntAnYdeA7]FhCMR[#DJXBA +K8c5"]"5Sj^;%V*`Q-$=`W!dg_o]s=`lH*>aN2KGaN)EFb/qd)aT'@Lb/;*6`5T[5_ns4%]=GMa +\=f%>H$""DCM7?oBPD-k@:s(W?XdSV?XmVXBP([Y>AB>*]"l;+b0%uSaMQ*<`Q6-CrQ##ZaSj-H +a=GNP`lYm0`Q-0KNsZI.,npBWdF?F`^;J.>d?GLa%291be]Q1[b0J)J`Q%o"&&u?&bKJ&L[[CJr +:1A4sm/I%bqZ?Qhq>1-krPnkf~> +_Z'l?qtpBjq=smbrrUHmi;NZZr;$3`r;QZp!WN#mrX\l*s8Musq"t*c==Yc.qu#^X$N:#'r;Q`r +qYU*arV-Bir;R!!qt]m`qu$Hn!<2rs%HYj_k3;F/oC))4lhL5RoEt*Um-Eiohr3hlpuh\WrX&W( +rqucos8Mror;QcrrVm3&r;?Eeq>:$`r:U((rUoI>jlPXhlK[U!mHs?1nac5?n,DVVl0%-]bh;dk +!rM]drr3-#r;6EirVlipn,=%$r;Z]js8W&th'a<b+rVf-o`+merr3N(s82T8.3Tre(g$Y.s8W#n +rqucsqYU9l"Q\V-hpME&#QF\us8N#qrqucrrl4tg~> +])Mj2qYU9g&?2J4o(Dn[r;Q`qrr)cmrVlcqqu.-'s8W)ss7c?ho2I+`[JB^arWN)sr;6HdrrE#s +quH]prr`)sqtpBm%0$/&qrPJXPFnA:TUu.R,+G0lR$sS:StMmTUS4Ng]ZK*so(`"Sq>0scrVZWo +rr2flrqlcprr*]2qu-NorVZZps8Mrorr;rpr;6?gqu6Ek!W;opru(e3q"jmdpZ^8M[]l^+USOZ[ +TV8-STV8'Rrh0=arh0^lS<]58f^nn8rVQKirr`5trVlcqrr2iqnbs7&r;Zcns8W&tg*RaV*>B]p +oDeacrr3Q*s8)E0,9%XL'3"_urr;oqrr;rr'`\(/s8DiprRe3ATV%qSqtg<ls8;fp"9/8trl"he~> +\c3ECqtBC3H"1]s\\Q(t`6$*Ec-4DSaSj-YaSs<qaMQ3CaNMoOdc/n<#m$(5c-4>Qm)TFLa2Gm9 +b0.j$aT'9[aSj7A_ofs;bK.`@]thIcL1FV+BP;-n@piYMBk:jfBPD6uE,]]4EI3P-XL5j_`59L5 +`5g!@aN;WH`Phbp!65#Y(<+52`l?'=aN;QF`l?*AaN)?@`lH-@rlI:C`l?!9^VRb(`504$\[fAd +\u_B\I<T[ICi+$)ARoC_@UikWA7T1[A7T:_@9QZJT=r._aiDHEbK.ZBpr`WXr5S9J.*fiP^Uh>% +a4.R-$4n*k)25uYbf@lIaM?0Je?9Mr',LX.fZ_dkb/jS%rl>nqaM,O4aN)E>P@$p\?ZFumqZ$Tp +p\Odbs8VrrrPeee~> +_Z'i>r;69aqu6Km"6SOro`"jprVlQ`s8;lps7cL's8;fis8DureKuOb+sZ4Lkl(ngrVuorrqu]k +qu6C"q"t*krqlNequ$KmqtpC3qq9EPj6,gumd9B2o^hSFp@RqEkiCaViU-L4rrN#nrqHKmp&>$k +qYpWrrVlKis8N&rrr2uto)B[+p$Cbtkj7^(lfm[!kj@j+lg=95lgO3#gXY?_rr`&ip\Omb!W;rp +s8W)rr:0b6rVuoqs8VunnPL;I,9S7[s7l?gs8Duls8W)uqqYX%+Y+`ah>I<Oq>Lm&qu?]ps8W)u +n`/`lkNVsF#Q4Jus8)Zjrk\Vb~> +]Di]HrVZN_o<PI*g&CpFr;Zfqs8N#qr;HThrr<!/rVZHjr;ZW?+<MRE+QNJ"li%+gr;ZZns8Mcm +s8;rsqu7Q5r;ZfnqXEsoTTtt;StMaJS"-1LV4a<HSGo-"U8FfpaP#bGpA+R]q=s^Zqu6Qns8Drs +s8;inrVZfss8M]k!ri/trVm!!s8N&trW<-!rq?@Brqu]mr;-3_m,$+,\#Z9tTq\9ST:_dIU84NV +U84WZVkKK@P-!1)q>C0ir;Zfr!<)op!r`,tqu?6d./j2Grr<#rqX7,s)'0_=HN3d7s8W&tp](9m +s7t>P)&jkA,2)ejr;QWos8Ei7r;HWms8Vogb,V2/Wk7s$q>^Kmrr;iorrW2url"he~> +\Gm'7jjeTaCm;cQ^Ve15`mOb/s2t,X'#r,5`l?EQf\*nK$jH_4][G'Kqo\KN#0+R%_SsX9rPnHM +1=!kVai;39]"!c7?=[\]BP1g`?XdVY@qK@gCM[g)E,U/eUTh5B`5g!@`l,g;bKA)SrQG>ba2Rtr +!QW:\ao9H[aTBQ(aSEsWb5fZ^aT'9q`Q#p<`Po[/^;%Iu]tUhNR>uiAD/&u_)eNPe@9d5N@:*GR +B4Pgl@9m/^S[lJO_8F:9b4s0_b/hTBrl"lWo#UjQ-H3a8_SaO<1'nF-(E7)?_SaUAa3;B?c-"Pb +]LN8;(Cgtkf[S-fr5ScX(WXD0_o0^E_RYA);,q=edd$K)s8N#rqYpKsrVH<f`W(G~> +_>aZ;qtU!dqu6`LiRIf*"o@rjrq63ds7lTnq@*E%r;ZB!.O?5_,]!,;rr<!%rr<#srVulrrqlor +r;Zfprqccprr)`o([]Z.kO.m1nEfW6o'u)1ki_6qj5/b\q==OirqcTkqtp3gqYC-oqu-KjqYp?n +s8Doqrri?"rVlfprrE&rrrrE%rr;rorqZZmrVlisrqHF2rpT.1i8s4hlgaK3n+$#<lK[^$n+lM4 +e][I[rri/mp\Xsds8N#tr:0b6rVlcps82ioGp"1S)B2oUrVZ]mrr2rtqtpEbs8Dh@,:"<V.cg@( +qYgcuo_\[grr2lprr3,\gYgrBrr36"r;QKkrquc3s*t~> +]`/cHrVcQfpo13eoD87\s8W)us8;oqr;?QmqYpNp&Gu>(qtpE_[3Qe4*[#.grVc']#QOf'r;Zfp +r;Q]rrqufrrql^Fr;ZcjoD7gfO-5s'U8"9LT:r'UTq7jKTq\3PV7+P"m.'iIr;Q`rq>:0jrr`2q +rVlEg"T//trr)iq!rr5trr3-#rVZWmrVcfqrql]m"TA?"s8N#rs8N&u"TJAurr;us-2dZ6m,6F, +ZDaUtWMcSjUnOKWUS"'LTpqUKTU(q6bkD&8qu?Eirs8W%qtp<hrVc`ns76.<rVlfrs8;lmFW)2@ +()L*Ir;?Tmrr2rtqtpEbs82S7*Zc+=,iJ@qrr2lr!ri5srr3Z0rVuirnFiuSSt`.Dqu6Kms7ZHj +s8N#:s*t~> +\c3<>nD&7s<2mFC`llEAbg=APb09e+qoJfW&]2K6bKnqfRMHSH$3`rFdEg&6b4<U\`l5p7a2u6; +a2Z-maSs16_oBX.]>D%7>$PTPC2.BkA7fFb?sR&IC2@TuDh+(H[CO&g`Pom=a2uWPdEg"WbKTt1 +s3:_kb/h[%`rsB%aiDF#`sTr/a2uKGaN)<@a8O'\a32[)aoBKbbfS!+`\GNQaN)9<`5T[5_o0F/ +^:(&6K6M0HCi!j!C1^sa@q8tP@q8tWCM6sV?&lG4`Pp-@rQ5,arltJe!m8U(rl"lWo#O;BaMc!; +_p6b8$4n'a$V/ss`m)EBb0A;Ta3VHDdaqb4&ePrra3N,UaMu6=`Q63@aN)68`QcTM['3t7;I"+T +k4noTs7cKl!r_ul`;b>~> +_#OH6qYpWQfBiJ9#Pe,pq"FU\rql`jrX\u-qYp?dOXMCo+Y&<Js8)!Z!WDrfrrN&srVuosr;RP^ +cen$YoC;5;oCDD:kiq?ok2OeEmeQYX%K#nos8W&pr;Q`rrr)forWW5uqu-Ejrqm9'rVcZkr;?Hk +r;?Qorr)fpp&>*mr;6Hks82ror;H0c#4ps4hW<terpL?bnFGu8m-3g$mI'5keEd)5!rVllpAb0i +!;uEe)ZTg6s8Vurg+4-c,TnZ#q=jp`rVccolb!&mrr38upmWNT+XU[oq>L]urV6-ds8W)uq>UC$ +e`5lPhuE`Pq>:*hrrE&7s*t~> +^&JTArVZQinuAA%q#:<nq#:6lrr)rsr;QZkrr<!0rr;inq"9Xm*#BP?K`:uHrTjFgs8Murs8W&q +s8Mrpr<E9$rr)cnrr2pGq"=:&QA_#tTV7mCS"?:ES=H:JUo(/j]?]0ooD&.UqYpNprquWmrVlWs +r;Q`orVc]o"onQ#rVlcprrE&trsJc*s8N#qr;Q`qrVc`ns8Musr;Z]srqucms8VusrVlgGrr)io +qu$Hnrqu`fkL7,EUSFKSStDXHTVS9XV4sZXU8+?DPI003qY^?m!ri/rrr)io!WE#ss76.-s8Mrr +s8)cH-5.@@*@g4JpAamdrVucZ\bc:(s8VcsQQ@.a+'nX?rr)lsrr<!5qYpNorVuWeq"CS`U7A%I +qt0gdqu6Hl!<1"<J,~> +_Z'`:qYL0hrt>5#fQCJM[CsK&`5p<JaNDNDaSX-WaT'6r`QuWOdF)q@%LWXVC#.Cac-"2Mb0%rN +o#M6Z`50F4a2Z0BaN2NHrQ,#]s2Y5\`W!dT]I^a_AR&bUAnPU^A7oRf@q'%_B4u-sIZ^8&\%TMh +_8aO;a2Gm<aN)6>aihs.ao'<Za8X-ia2uHEa2l?BaMu6@aiMO$aSa0Zc2>ceb/qp-bl>jDa2Z0A +aN)?@`l,^1`5T[2^:(#,JoPL=An>RbA78t[AS>^c?!^lG?rgK\X1QQr`l5s=b09k0s3(YhaMu3< +`q%2<bK.TAai`;K(_%<"%M?S)`mMWAa3DrIP0V1jaNDNLIM*S;(J2utb/hTA_o9^@d`fPE`Pfa< +`596s?<U&uBZB9*rVulqs8)fp`;b>~> +\c309db<[[s82ins82Kbqtp6ip\k^'nGi@bAKi?A-R?2#p&>!UrWN9!s8MujrrN,sq>V5fcJ@m[ +o'u/:nau;<nF5`)iniV\p\k!h$NC)*rqlWjr;HQmrVm!!rVulos8W&or!iW&qYgBmrVulrs8W&r +rr<#ts8Dusq>^Hl"oJ/mq"XgeqZ-Wos8W'%r;HQgq>U<ls8Ec!kiV4!nF#`5l0.Hum.'Z<p[I+l +eb]:Irqucnrr`8uqu$$a-N3uDs8DrlTHPg)*$sA9qu?Wos8N&m?R_H>rVQWpr:`c,+<N2lq>L]u +q#('gs8W)urr)j(eE?2\iV``Uq>C0grrW2tr5Sbe~> +^AecDr;6EhgoREZqYU!dqu?]orVllsr;HHjrr3Gss7uV&*Zl=E+1(k9rTX=]rs&H%s8;oprVHF? +rVlirrVZWmr:]'OOd)?,S=c=BT:_[DT;/*SUo(6+d-:9%qtpEnr;Q]rrqucrrr)lsrr<!$rr<#t +rq6<krVum&rVulrs8W&rrr<#ts8Duss8<0"rVlfrs8N#ts8Musrr2rt!<2cn-iNu?o]FcMZDs^q +US4<PUS"6UUnONVStVa>PFKqkq>C3irr2rsrVl]qrVlfro):!7s8N&srUlWu,8D"=gACjKrVlir +rq0MBQh^OWs8Vug6Q-aX.,=h$rVuosrr3]3s8W#srr;okpS4OYSu10<s8N&r^Ai]~> +_Z(JOqY9pas8Vra^jBX-]>D;'a3VuLb0%fIrl4uZrlY,Zs2GVl]$njS5lh/q&IY&_c-ahZrQ#&_ +bf]Lts2G8\aMu0@a2n5%rQ#l!aN2B?_nWprV06'OBl.Qq?t!VYAS#OlCAquoEe0LW\A#Yi_oBO4 +a2Z0@b0.rKaN;TIa2l6A`l?'>`l?'@anj'saiMKBaiVTGaN2KFa2c?EaiMQDa2l?Eb08$,blc27 +c-6.02U'=caiMTGaN;HA`Q-!:_o':(^UgP=PC%:aBkh<nA7o@[@UEDJ?X@>V?!h<<^q[Y#_oBd? +r6,8caMu6iaT'?maNDWPe;"Y['bLtgccab[rl@%DcTMPWbfdoDb0AHm(`3eu[EQ_5`l5j7b08&T +bJhQ@_oL!Jb/(Mf9hSH'[-[bks8Munqtp?0s*t~> +_>aN7qu7!"h9b-\s82forquZorql]srqu]irX]&'s8I-l+Whn&i;NWSs8:pVs8N-!rVQTrr;ZEf +rsAM[gth;gnF#c5rp'gWm-Elnki1[rs8N#rrrN,sr;6Hjqu6Qlq>LHqrr;cmnbiC`r;$Bfs7l]m +r;?Qor;ZWor:g4+o^(f)lgX<-mIKoAoCMVDmdBE#gtDW*$N'Pss8MrrrV-?lnc&Rg-2miAs7X&M ++X/"JoDSUcs8W&tr.6.9.;o"^qu?Y>,9A-U-ggd+rX/])qt^-es8W)trVlg'mG[=!gAh3Pq>1'i +"TA5mp&<#3J,~> +^]+lEr:p0dhQ3?ao)J[fqu-NnrVuiq"TA?!s8Vuqrr3K&s8@!f*?-%kh"ppIs8;iqmJd+brr2rr +)#X:1rqu]nqtpEhs8Vidd&NS"SthmFSY5nQ%%s;cXKAtcp%J(Ws8W#r!<;opmJlSQj8]&Vr;Qfr +r;HR"r;60IbdjdJT)PE(U84QWT:_dJT;&!IQC#_Yp@nUerr;uoqZ$Tls8VWgs8OGErr)lg[N-5+ +)fP?Jrqucqrr;kF*Z?;=p](-jrcK;!*??BjqYpEmrr2iq%fZG*rqufrk..(PUSH`Err3-!rVZQk +_uG5~> +_Z'Z8qu6F)q>0WsEDq+db08)Pc-4DSaMu6u`W*sQaT'6jahcBN9aC_!"YRRCeC)X`rPnlYs2slQ +rl4uZrlQV3aNMcKb0%cDb.l*;]"+2KAR/naAn#7Z@:NeZB5)3tG^4h7^;%A\_uI^S`qd^S`WO3" +`Q%bn!6FrXl,WnJaSF!WbkfK\a8s<%rl4uZs2HS._nj(!VicLPD/*cp?t!SV@UWbW@Us(_?Wpa! +Z+7Ea`l$'Eb/r#T`QQEoa>(l[a2lBTd\7Bj)A66$d*0e\a2H0G?3glM:Xme4a37<`%iQ#e_T'[: +`l5j7b07lFrlc/#`l?'Cbg+5'D,!Z/D7]$/s8VunqYA#.J,~> +_Z']:r;6Els4%>As8W&mrVuiqq>UQrr;6Berr;p+s8M[:,Ud@%p\t*es8V3[#Q4Jsqtg?kq"k"* +r;ZfCdc0`fn*BE5nF,T)lg!KfhXL@@oDSdgqu-?iqu-Hjrr2imrql`krpK[equ$?hqu-?jqu-Hj +rr)j"rquZkrqud;rpAe3l0.L'nF?,=oC(r1o^_2(ea`\>q>^?ks8;]lrrDuer[7aFrr;fks7'8> +)^$AUoDegirr;`]/1Dka.UCg.qYH!s+s8"Go)JRcrr3-!q>'perr3#upAY'tiU#ahfDkmMr;?Qs +p%.tVa8^Y~> +_#FrDrquQfnu\V(mf3=br;Z`hrr)lorr<!-rr)lqo-#8'AbPfpqtg0hlMgh`.K9AFs8Vlorr)co +s8V]bjIVR$S=c7<StVgPTV/-XUnk!,iq)j=q=t!\rp]pfrr2rbrp0Rarq?BjrW3&urqlcqrVn,> +qYL!OcaKaKU7RpIStD^KV5'WRV4j6?Pf*+eq#C9js8)Qis7-(8s8N&uq>1-Y<$)kq+Fj"_rVlis +q!KRV*Y]l%f_tXAL*[fX)f,!?rri?"rVlfqs8W)trsA>js6["bRA-MSrr30$qtU*grP\_d~> +_#GDNqtg'Wep:A9VT$d%d*g1_b/hTB`Poa4`Poj:q8iTU&&lT7ccc@j#"6qde'5tUao00\`lQ<F +m`>CMs3)k5cHF/JaiMHAa3;',X(GXHBP:m_@qB4aAS#UmCMn3RY.hZh`PfsfaSX!S`<"!"pr_[= +qT8f^pr`KT!QN4[bUgoXaMu38^V@LgR=K6jA78qXA7]CaB4Y@T@piDD>_fYn\&,r"bK%TNccsW& +a=#0P`lZ-@g!E,%&.o@[c.(.d`l>d-#S7[Y(db^ZaiRlq$k<M9_pA;$+2u7Bb/M?Dc-=JR`lZKO +`5'?lAl_Z3CXhSBs8DcgrPJSb~> +_Z']:pA+[e#hRbos8Vuqs8DWjs8E)tqtp3gs8W,t#63X5J,B0<rr3#sqs"+[rsSi(qt^$]qt^0a +rVZZp(&S%2eC3aWnF?&;nF5f/lg!crh;@r&rrE#ms8W'"r;6Bjq>C-hr;HWos8)`hs7?6hr;Q]f +s8W'!r;6Hg!W2fgs8W'!s8Moq'_Ct`lKRX$mI'3%oC_YCoC(huf]2u2!WDrqrr`#ko)&"W-ia,B +s8Dips5>4J+s/"3kP5)WqZ$9^>U1X;,:1,)qt0Ao-6q(9p\Omgrs&K#qtp<jr;-Erf&Z&Sf)#CL +rqlThrl>%h~> +_>b&Fs8Mrnl(t2poDejirVHNmr;uusrVZZms82fors8T$s5,8Qq>9mbrrN)rqu?*`!r`,tqYpWp +s8Drs#P.W>R#@H/Sc55tTV8$LSt;^RVR"\EpAb0grr2flr;6EirVccqoDegh!<;Tgrr)Eequ?]q +r;?`srVlcorqZR!rr)cmqtp<hrr)lr.0'2@rVcQeotRi4US+9RTq\'KW2cYgW26)QQa,KKrr)fp +r;HKlrVuHf-ia,Cs8Mrrs4nb>*ZQ8'k4\fSqu?B]<ui=t*$Dlkq=<od+s5;.p\Xsjrr2lrrr2ou +rqu`p%f#\fUnXNRU@S9]s8Muq_Z,,~> +^Af,Ko[.VaH`=p#_T'pPc-"2M`l?!:_o'I4`l@hqs2Geob/qlW\HZ3`c,S5UcG[T=_o9U7`pUqJ +b5BHoc-+AMa2>s<`4*RWAm&kerb!!WAS,I_BPMC&DL%_b^<+L9bK\2Qbfot,rQ+uX!6G)\qoJ`U +!6G&[kK*M>qT&ZZn]1^QrQYAd.E]`R`59F/]tCq2HZEt;B4tpi?<q,S?<q)R@pNA`U;4LX_8XI; +`QlHma=#0N_oBR1dFc5B&J>N]5fh=!a1og7bs<'a'GM"Lg!\'f:C.*)a2.Yms2tA]!6Y;b(!=V= +bKeDW_nEE_<)-A(a6NBss8W)8s*t~> +_Z']:qt^6k$/jXos8W#gs8W)ls8W)sr;$<lr;Q^(q>9%Kr;ZferVulsl2L__$i^)$q"OOTn,<:d +r;HX-c-l7Wq=+"GnF>r1kNh9hl2CS\s8E2uq#('erqZQsrqu]kqu6Eir;HWjs82fis760gr;Zce +rrE&tr;ZWpr;QTns8Mus#lal'rVuloq#:9m'Cb2Fj5fRrnEfQ3o'l)@nEf8ag\h'SrVHEfr:9h7 +r;Z`os8W)ms6<c++sS-Uh#IEOrVuZfI4??^,q,Vhs7uK=_"@[,q>UBnrr2rq%Jp&!rVulos8Up: +kNDC5rri8urr;r:s*t~> +_#OH6%f5b,W3,^ls7uZoqYgBlr;HWoqu?Nl!WW,trs8Drh#I9Os7-*`s6oserVulprrDins!.=9 +q"3F1NhVu5Pan88TV%dIVPKulcKk<&q#(0lrVlfmr;6Hjrquirq>^<js8Doq!<)Qhrr)Bdr;Zfr +p&4piqu?]q!<)opqY^Kps8Mus+9)-4jj:cKX/DblWMZA]USXf_Wh>iPQ*9QQr;6NjqYpNcrWE)u +rr2os+ntru=;N&$)C*r7s8;lrp@NPR(Dn2;T_eZ]p<UJEs8W)ss7lTnrtkY6qu-Qmq#BEWTq.sl +pA"Obs8Drss8Bt;J,~> +^AeZ7h2Z)TYJS,f_8jaGbl5]_`r3mU`q[Ud`l,pAd)sYAf#u7a]>_h0a8X'W`p_"Kb5BHbb/_9r +a<S=4]tLFX?#sdt@:j(_BP1jeD/aHCR'aZD^Ve.5a3;fNbg$+1rlY2\rl+u[b5TW^b599Wb3-kA +`p1VGb09e.s3)k6b/qcH`PB1)Z(-SqEbf<%Bk:UV?X[AQCh7*d=`UUW^;.h-`6HNqa=#*J_SX71 +_plan":u4V&A$E:_o0mGf4c6B()@UAh:pE/XI$uUbK0Y%!m&O,qT';laN_iMd`]VPUgm(h>(b>g +oDSUe!;je9J,~> +_#Fc9s8VK@dJs7FrVl`p!<2ips8Mupp\k[$s82imqtpEgqZ$Tps82'[s8N0"qt^6dqYq3'hW4"j +l0Is9nb)SEmHs2qoD8@a!rDior;QcprVQKir;Q3cqYp<jp&=sj#6+Msr;?Qnqu?Qmq#:Hqr;6Bi +q#L<jr!*,rq>'m`rVQU.qWd"tkj7g1q"=+@mIKuCmcN9cr;Qiss8VZh-i<rDqu$Knrq?B^H6F@L +,:C"ps8VTgrr8i;-6F]ZI/3a@pAY*crVHKqr;6BjrVmE+rqH9equ?]js8V'IkNLt*rr`,nr;=M5 +J,~> +_>b2JoDSI$WN,gorr)lsrqucps8N#rr;cios8W&us82d&s8N&qs7uNfs7lHhrrDums7-*gr;cin +ruV14qu?92OGB$hR$sV?Q^aP:T;89Zb2)O^q>1$hqu-NsrVQWop](0j!<)clqu$TorVbaTqu?Ei +s8W,u!<)ops8Dusq>^Em"TSGur;HWprr!Z1nD(m`Vl-AcUSafYS>)mZUn='@Z0M/arrMuonbr[g +s8W#rrr45:s7(=T)]'S?[IjM!nGiFaTbnge,8k^uqYp0ds7ZEjrr<#trr2rtrY>D2rr<#qrr2fp +s7H<WY-+7hYPA%orr3&tqu+P7J,~> +_#Fr9qW=&ZBt(sr]tqb1aihd"`r=$_b/hZDaN4A'&BMl1a2QHJbf\2I`6$*?b/=%pn]:OK.*p#T +]"l7nP[[m/Bk(^fCLUmkCMn-3E0R3/_SO+.a25pAc-OVWcHQ1.prEHXqTSWTqoJZSn]:IEqoJfW +o>psSqofSqaN)9>`Q63AaMu$&SqM%]B,"lgC1h!^@;'CiAmnthY.MNfbeqEia=G<Vb.t^,^Ve"A +cX.+l%MK8:cI9tJe'm37&0)B)%:e,De]5q``6$*A`lA#!+j/$QaMl'7`lQKIbKS#PdD*Mq?Wp01 +IG!iWqu?]oq"t$1s*t~> +_>b#Es8Uisj8]/Xq#CBjqZ$Nnr;QcrrVZBg"TSB!qY:'is8E3%r;-Hhs69Lbs8MrnrqQTmpAP"& +lc.fXqZ$B^o]u#=o'>AplM:Gfrql`oq"amgs8MrlrVQTlrr2<bq#:-ip&=sj"oeGsqu$Bgrqu]o +rqZQtrquTfq"amcrqufp#lal'r;-3`q>:*i'(G)DlgjQ7o_\%BoC2JOo&\?Zqu?6d#64]&rVlfo +rr4#8pR<EN*ZZ_Xq>L?ks7ZHE*$u[P.Tl3;s7lNls8)]sr:p*erVm-#qYL6lrV?Birrgj1k2be+ +rrW#mrP\_d~> +_Z(2HoDAI%T!nIkr;6NorVccorr;us!r`,trVuiq!<;rq"TSE"qtU0j#QFc'rVHQis8;lqs7-'h +rVl]o-h[K4qY%glSXGP3U7nEPT:qsNSt`O8k4&?Ls8Dlor;Z`jq>:0jr:p<grpp$GrqHHmrql`q +rW)oqquZirrq??lrql`qrVZ[7qsighZ_jUtTqJ3^T:r*RTVJ'HR(N%_qZ$Hko)8jnrr;uts8N#t +,Q%5'+WMC:-$].]s8DujqpQ9$'cnW!mJ?kYr;Zfrrr<#trr)lprr<!3rr<#sq>C9mqVe*;S>3L] +qu?]qrquira8^Y~> +_Z(&Cn+5n=@rf,o`59R;rl>)Wr5S`Wq8rf\`lQ7#aq2Y:_ofj5cI:"Y`m)H?c,7^%aSs3LaSO%- +aM#R,_7k_2B5D'qD/!fqB5;=!CN4orZb+6#ai;<=_p6<>_oU$EammIJb5'-Wb599W`pq.E`r!jW +`q.:O`rF-ZaskQZc-4GTaMu3@b/hT>]s=VoGA:o1An>[o?XRGQASYmd?@B;k]ZA%2o>jeOcH=8I +_8!\(c-=YdJe/M)#ngUqd*]eRakFN>)\No%4j;-p^rF^Gb/hTBb/hTDc-=>K_84+1aihrTa2?!@ +ah4'A:/PMTdHg]0s8DfjrQ"qg~> +^]+B#c/\a%"oS5mr;ZZnr;Q[%s8Mrnqu$Bks8Voo%f?;"rVuTcrr)lnq#C0ik5GAYrqc]pr;R;P +f^S(in)rs*md99%g=u5rrrW&mrVlg"r;HZqrr2lrrr)lrrq-6hrpp!XrqZQsrqu]nrqufrrr;ls +qu$6g!;u`nrr<#trqu`k!;uirs8;oo!<)iq')UbGk3_U,naH#>naZAAo\%UarVuHf-ia&Arr<#o +rqZBgs7F8X*[MpT?17glr;ZTdGTS(S*[ae]qZ$Tks8)]tr;$0drr2p(rqHHmp](9ms8)`p#hA,! +k4J]RrqaP4J,~> +_Z(2Gp[Q%o_tE]us8N&urVuoqrVuos"TA?!s8W)ts8;uts82d*qu?Eis7c9err;iis7u]lrr2rd +rr)j<rr)chptM$uUmI^KR$s_?StW!QWm'o0qXjgdq"O^crrN#rrr3-#s8N&urVliss8MrpqYo[X +nG`Ifq#:6lq#19nqYgNqrqcZpr;lipr;Rf:rVufiq!QY<U84Z\USFNXV4jQYSu@g;aR&a%rUTq% +s8)]ns8VrqqYC0koY`$p*Z,r#m/Htos7u8-(`FD2,#.q2s8Voorr<#urql^7rr;utqZ$Tjs8W&t +q>L'RUo'WU_rgptqu?Zn`rCP~> +_Z(5Em+[tKMRU.1a2lQQbK@l@`W!jWaSs?YbT4jI`lQ<Hbf\#Gbe:s=^;7n0aMbs?`QcWNb0%fH +rl46E.)s3@_l$jLEaiTm?!h2R@qKLfEg=/V`k]g@`Pfd>bfdoCaiVQA`l.\ms2b,\qT/ENq8iBO +e]@a4$HU3(`Poj:aNDWHrlG,^"3em/aSs3u`koO"R<W=VAn5Ia@:NkX@;04h>$[8s^Ve(_a@j\' +aN;NEa1fI,_p6r`W"9@S'bj'XcGI9;a3n<)'Gh2h0$;#MaN)TMaMu6BaMl-Bbf[rE_o9U2c,[T? +bJhN<`Or0P<_d(jcM%8;!r2Kfa8^Y~> +c2[hCpAY3`ddI#4"oA&nr;6Klr;HU"r;6Eirr2rtq>Lp)q#CBhs8W)qs82irrqZThrr2imrr)lr +rWE)qqu$Bl&(/kep?VG9kj.Quk2tRPoDJV"rr;lns8W&qr;ZcrrqcTnqsj^`rquZqqu$?ar:Bp` +s8Dros8W)sr!36$rr2imr;6Kks8Mlps8N#q!r`,urr*3%qtp<fr;Q`qrVm/uj5/n\nF>r8rp^3c +n+c/&ch[M=!<2uqq#1Hms8MrrrVlg;qt^9bi(YC@+=8Voqu-Nh[j!.@+!`5`q#C?ks8)Tk&cDP' +r;Q]qrr2ros8W)ts8Moorrh0AkM,V-rrE&js8N#Is*t~> +ao;A?r;R3)r:n4(`UW[$rqu`np](3k!<;rq!<;op"TS;ts7uZo#Q4W!s8W)os82fqrrE&ts7lQn +rVlfps!RgDq=iL2PaeM6TqS9ZUn46VVl7r3qtL!frr;uss8W&pqu?Wps8Drss8E)urr)cor;HZp +irA->rVuiqqZ$Tprr)fpq>UTsr;HQmqu?]o)ZBU%dC63XTr+Z\Uo'o]Un+BSS"/%&q>:*grVufp +s8N?'s82iqqZ$KmruM(8s7P2>)]T\:-JJ@rs7irA*u>b8,LZAes8Dunqu6Nn!ri6!rr3]0rr;rq +s8W)us7Q&`Tq7aln,<:cqZ$Kmd/SU~> +dJs7FpAZ*1qX<=4Bns42_o0O:d*^1^`5fsAaMu6@aNDa+bm)D7aMu6@aSj6naND<>aM5d;`l#p; +bKS2Nd*2L3s2b5[oZ7$SrlG,Zs2G#S.\UN_AoM*l@q0(^@:X(eD3_ZL_SjR=bK7uQc,mrDa2Q*< +`5]m:`Poj9rPnlYr6#&\qo/o\`l5s:`l5s;q8iBOe]@a4!m&?url$V3aN2NIbfe/Na2Z*<aN)HI +cH4&F_mG_UD/<ctBk1^`@:3YTCh7*dRCg;S`Q#p=aSj9]aT'7/aNhoSb/_ZEa2lHIbgt+Q0G>?> +'bIak_SsN[$5XBh&dk_[bJhEHaiaV(#Kk-*_og3GaSj*qa2,d;`Pfj;aj%r>Z!'q#?'s=;rVlZi +qu$KorQbFn~> +cMmtFr;?Km!;ufq!qXmor;RB,s8Vuor;HQis8W&sr;Zcqr7h2Nr;QTnr;Z`rqY^?sr;ZWmqu$Em +&)5q!lLFH8n+#Z*l/L@OkkP2IrW<-!s6KXcr;QW:rW<#sr;-Eks7?3kr;QWmrW3&sr;RAiiT][o +lL"02oBPl7jm:XJp\t0rq"j[_rr)ir"o\>rqtp<hs8W#pr@%SX,TJ$K.Co'JgES!`*@2l?p&G!i +rVuoss8W)qs8N&tq#CBks8DomrX8YuqYC0knD3Bsj7`KP#5eH!s8Dior;Qcrrqk4FJ,~> +dJs7Gr;RN2qu6Wos8)Zda.f]nq>:0kr;Zfqr;Q^)r;Q`qs8Dutrr2lprr)llrr2rcrqZR"q>^Ej +q>^<krVlg5rqcBWUn!gCU7e'HTpqULVPLQ>p\F[_rqufpp\k3nrqucsrr;Ec#64]&rr;utb5MJB +rr;]ks8Vck!rr9"rVe/Dq>UBerpe%2VP^,]U84N\T;JHVVN[:bo(i=]s8;osrVlcprqu`ps8Duq +!<)iq+8u$0AKVd1(alldrS&G;'c.u7\Fon#rr)lsrr<#tqu-O(qu?]ns8Doqs8N&ts8N#t&cM_& +aeGN'T>pX%s82iqs8MooquZcnrmCar~> +df0CIqtp9j!;ufq,PU`^QtL<0^;@q6aN`&Tb0%iIc-X\R_nj@4bg"JYb/M-1`V@OR`qd^Sb503Y +b5]Q^`[/IDaN)?Jaj.uM`l5j2^:8&m@:a(^@:*PN?ta:gH&]ST`Q$!?rlP8_b5'*Z`lS(t!Q`:K +a9KZ*`lQ0@`kTUm`ph&!b/h`Ba2bs6\W:iNCM73d@U<MJ@q8t^=Bplu^;[k-`m;rRc-"&E^r=Cn +b5TUVb0/#Sc-+5T9GA'W%2+rIe%$&1(E"+uO295cbfe2OaN;]La3)<=b/VZO`QcHDaMu<@aMu<D +bg4GP]7a'V9idP4n,<.`q>L<m!rVokqYpQof)L7~> +cMmtFr;Q]q!r;lnrr3)le)L9'rt+u(s8W&qr;6?jrVu`js7u]JrW)lqqu6Knrqucrrr2Zmqu-O* +m`ODRo^V>9nF>]/l.t=lpA]^CqYhB4r;Zfls8W#sp>>$"m-aK9lKn02nEfSsh#@<Vr;ZH`rVZZu +qYU0frr)jMrVZWms8W)sp5L7B*[2SclmF+r+=&+[nc/L^s8N#ts7lKks8Duos8DfnrqQNnqYgTp +p\4O`rse\\kj.-is8VlorqlTlqu6ctqt^0>s*t~> +dJs4Frr;us+8>g5s8;T7V6ehJr;Q`ms8W&pqY^?krqufnqu?Nmrr2irrr)lVrqQL;rV?<ir;-?i +rr;chn\'pKStr!JSY2aIV5L/re*m/2rVlfprIOtDrYtn8s8Vlos7,^$X/W.rUSXfZTrF]XR\,kA +n+Zh]"T8,pr;?Ek!<2op!<2ut.fT>BoSXb5)'0]WlQm\d)BTuKnc/L^s8N#ts7lKks8Duos8Dfn +rqQNnqYpKo)#jL5m`2)mTqf9prqHHlrVZ]prVQHgrVl`p!<1UMJ,~> +df0CIqtp6i+8Gm8rU\pCBlB<G^r=F:c-=JRa2Z0@cHOSN^W=43b5TWgaMYd-`T"u<b5]Q^`ZraJ +`Q?KMaN;E?aM#@!KiVPmBk:XZ@qB"^CMJ*^[_]l$aN4A'J]RW-,0S!Kahl3F]=O&CE,TAu@prSI +AmSnPAmB/Z]>_b7`lH9HrlG2^`;[jXb5TU<bKS/Qai;9?c>jO9',(IfcO_$/*ZPc"^WFI6ccjPR +bJM6FbK7uHcH4)Kb/DKKqT';lbKS/PaK^4k6qgmEh"14=r;?Qo!r_riqu?]pf)L7~> +a8Z/<rr3)odaIgfs8W#tqYpHms8W!%q#C?js8M]kg&D$Ls8E0!qtp<jrr3,rp&4d`rVmAZhXpI* +l1"6.kj7Nah>R9O!;uin!;qEIp\k?rr;ZfqrVZ[<mG7$tlLt#Ep?qA?n`oD_f`2!IpA=mes8W#s +p&>!jrr2iqrr)jBrqu]npTu1i)^ZdU)]g1H**i7<s82fqr;HZos8N&nq>:3lqu6Tsr;ZTgrW2ro +r;R2phrN\Tq#CBis82fpr;Qlur;6E@s*t~> +ci<k@'*%t2r;4g8VUG8>qYpNos8DiorVm,us8W#ss7QEirr)lVrr<#urr)j#q#C'fq#(*j(A.+9 +OHHB9S=-%CS"6IXU9E/=q"Xmgr;V?Ip\l66r;ZfqrVuoorpRk+W2H)YUn=KUT;/0UW/dnFq>L<m +$2=;qr;ZWnrr;usrs&K#r;HTnrr2p6pp)%a(F(%H(E"55(gHb7s8;osr;HZorr<#n"8Vopqu6Ts +r;ZTgrXo20s8Dcnn&;)rS>OO%rV?Hjrr3'!r;HQn!ri/tf)L7~> +`r@%WoB3&jBp-$E^r=O@c,n&JaiDE@^raU6c,RNErQ5,]rl"lWg;kGUc,J#I`m;rO`4WaI>[)#Z +?<h&T@Us@sBQT`S]tVJ)`du5&a=#*Lb07oHbfRN5ZAWX=D-^[a?Y!GJA7]Ck=)YCW^r4IFa3)TF +c+s=us2b2^s2k;`rQ$A4d$YFY$ks-_$PaQs$pW.fc,7QF`lZHFc,RfBb0nkda3W&UaN_^"a:H;0 +bK.ZEZ%,kO:1^!Ko_\Oc"9&/rrVc`trVQQFs*t~> +df9=GqYpQprr3)le_9csrrrAuqY^3erVm3'r;Z]nrV$9hrRCfRr;Q`rqu?]is7?*drsn)AoCMD= +o^hD7mH<*\rqufrqZclkq"aa_r.4kBrr;rsrri;sr;QWnru(:jmd]c9p@IkElgO3#hTblrs8M`l +s8N&irVm#uqt^0hr;RZ4qYL-epY7,@)'9kA+<;UOp&"L_s8W)ss8Mp'pAb0g@^Q(.s7uBfs8)`p +rr`6"s7uZo"m"\%kiDC8rr`6!rqZQmrVY+DJ,~> +cMnLUrVlfrs8N&trRIgFe*[&0r;Q]trVQNirs&H$rq?BirVc`qs53hSrrN-!rr*u3s8Vopqu-Ef +kGjT9SX>nAUS"3VVP(ETq"OCWs8;]mJc>HDs8Dut-2m]=s8;llhncFnU7IjLU8+HUUS=<PSD!T8 +r:U*ir;ZNkrVlfprrrE"qtp<jrVmH-pY-r8'cS#1)]9\Ap&4U`rr3#us8Mp'p](9f?Ej>%s7uBf +s7uX.s82iqpAFpX]WI`tVo\W2rqufrqtg?mrW2usf)L7~> +cN!nBrr4)>rUo<XF`*PL^r"%2bKn8Ka2lBC`l6$8`5TO8aN;U(aT'9;a90H$`l@tu+Nq[McGIoE +`503mF^/Zl>?tcO@qTb"C4N.r^:V;(_oDYrrl0N1prNKU-HaNP`5KX/^qQY"FDY`%@:WeT?sR>T +@V'#?\\l>"dETeX`6lTDrPnlY0?;2Wb/hZGaiDTP^Cq7e&.T?g&.],ocGn#LaMu3BaN2B8bgFg, +PL%1k`PTsGbPK9k`l5a7bJVEAZZfhO<+qc\q#:9orVHNns82cp!rMimfDg@~> +df9@H!W;rnrri?$s4tlsrs&H%qt9d_rVlg(rVZWopAY*lr;ZZJrr2rtr;?Top&Y*frr3K"akZ=F +nG)\HnF5StlMLJY!;uik"o%ffq>:)@rqZQnrsAW"rr2lrr;HWorr3N!jQZO0lh'Z8mdB]4jOWMn +rseo&qtg?is8W)rqt^0hrVn2CqtU!]s7Q6c=sG49*Z?OLh>@6Orr;oms8VrqrVuT`>:Ll-r;HWq +q"apgrr`6"s8N#t"Q&8%l.Z.:"TAB"r;?Qk!W;rEs*t~> +cMmnDrr)ir(]OBfXI\2=qtg6js8N&urVccqr;HWpp\t0or;ZZnrW)uRrr2p"rquZkr;RQ-s7u&m +N16c7Tr"EPTV\EY\C:3GpAFR_Jc>NFs8N6"qYpKmrVmr:rr(rrVkU/]R\cgVUSFfaS<L2Bq>^En +rqufrrVl]o"TJ>srVlfr+oVH8qY=27*Zl:9-lh(As8N#trVQWpqZ$Nop$u00*k)"FrrDihrXo2, +qZ$ToqtfupW1BTOjneiNp\t?prVlfIs*t~> +c2[hBrr4>Dp?8Z"@@t*H_o0mFaiqoJ`l?!8`5K^.`Q6HLdDsDNaMu<Bb0&_b.E9?E`Q$!?b0&&O +ai;?8begrH<b#rM?XmGJASc1$KqQ?#_8XO=b/qg*a8j6Z`;mo/aSNt+ai_WAaN2EE`l?!6_8*+- +DJF0">@V&L?XRPZ@U+/`^rOC6ai`#T`r*gU`W4'YaSs=1ahQ$=eDNe0'c%Ah(BCqgc-4DQ_njI? +`m;cS`QUF]$]W6QbfnDOb500n`PK4)bL"MW`k-7m8Q0!4kkP/Squ-NrrVHKls8VrrrR_("~> +dJs7Gqu6lus8VoNg$Sb<"oA/mp%nX`rs/;us8)KdrVP=Jrr<#trVmW(r9O7Xs8W)OipGpno'Gi9 +nE8corVZ[(rVZQhpA+LZq>:'er.4kCrW<#ts8Ms#rr;rprr)cp&*`$3nabi2lLjT5rpK'trVlg! +rq?Bcrr2lo!<2rs.fB2>q>L-ds7Gl@-6F6S+1qOMp&FshrVZ]os7u]dhbbg>.O3^Ar;Zcoq>UBn +"TA2srV6Bl"Qe_2le_X@#QFc$q"agbrm:[q~> +ci4%Fs8Dp&rVulPWh[Q/q#(-lrr2p!rVQNlrs/;us8)KdrVP4Gs8O>Cr;6Egs8)clqXW+$Pbb%M +XIl)UTV&!eeElr*rVZQjs8Muls+11GrW<#ts8Mrurr;rrruD%<rq,ckV4aieS"uURTqAEVSW;"c +q#C?hs7lThs8N#qs!@XCs7Gf;,9%OG*kVIOq#C9krr)lqs7u]ch+].,,U(q9r;Zcoq#2',s8;fp +s8)]kqR!#kV5<2Krql`qrVl`ps8LOJJ,~> +aSuM?kd5,2LVCM%aV<(GaihfH`l#d9b0%]NccF)HaiDR%aT'EBa=YEL_o9X:b08)LdD*c;_7Q:J +@r5jhB3SVI@q9>'T"2h\aN;NEbfe,Nb/hZDrl"lWJ]R]/!liF,rl6;*bK%]Ha2Q*:\@?s&@qoXY +?s-rE?#X=c<gL5/aiMEL`lQ0>r5J]Vs2b5_.EolO^rOpNf6.i=$P!0%dEKMVaN2?=a2cBDd)NOM +&IB3QVo$O"b/ha%a:uV-_8OLDd*'\Q\nFr;?#[RDp@S4Zs8Vs!rVuorqptdt~> +c2S:Orr<#ts8Ud6mJm4cs8;lj!r2cnqu6rr\K]r/r;Z`qf`(jL"TJ5lr:Bme%Go_"oBYW'kORs, +j5p.9rsAZ(s8D`is8W#prr2osJc>KE$2a`%s8MrorVuikrsn#=jRVd7mIg#9qX3q.jo,2_nc/L^ +r;QWo!<)oos848Ds7cQkrr<#AF>7d`q#1-jrqcZprr)ZmqZ#P*,9%pQ@.jR"qYC0err)lsq$R#t +s8N&uhrieTjSo/^rql<brqucurqu]nfDg@~> +ci=%E!<<&t$ig.gVQ7E(q>:3lrr)j-rVuinrr;uk[NF?&qu?Wpqu6Wqir8uX"TJAtrVlfr,Q%N@ +q=gqSR\HILU7e<QU7nj@nbi@aqu?]pqYgHorr;uss8Muts+11Gr[.OAs8W)rr;HZmrVlWirr;ik +n@k`sW1TuYU7RjRSth@Fm.^DWo_eafrqcXBrr;cnr;HZna)<PId.dJ8s8Mlps8N#os7uZN-63dA +*FAF=s8)Qkq#2*-s8VunrVcclrU$qjQ^t,6rVQQnqZ$Tpr;ciFs*t~> +b5Wmgs6R@1@<8us`6-9GbKJ#Pa2c3<aj85QPlS;>bL";Rb0%rPb/hTBilD;C`Poj<b5TU1d)+#G +]Xr8mA85^e@:!DKA7ThM[`$5.aN`)TaNMoVbf\#J`r<pW`du5-a="sJbKIuH`lH9Db0.cB`l#I" +Y^BqmBjbLS?<gZK@;8na[(X2t^!H]!r5ScWs2P)[s2l_1^WjjGgY]/:&l#@IbfeDV`6-6D`PKd? +e\Mk/$5<e(_9gBF`QcR%a:uY0aNVcKbKJ/I_lINW8lorBjR2j@rri;tqYU6As*t~> +c2[hArVlrOiog:?(Amn'r;-9grVuoss8V`O-7L:Ks7u]nf`(mM"oe>jp&4[brs[*/mIKZ2m-<p# +kiD74rsJc&qu-BfrVuorrV6DDrqcU#s82]ns8N&urVl`p'`.b(s8V`EjR2@-nFQABnFZA6e+<S= +"T8/mr;QZp'E%\$qY^<ls8Duqrr;rms82Tfrr2p5rVuirr;Q`ns8Ue$+W_gS=n_mls8N&nrr2p$ +rVZTns8;iq"OlH"jP9b7"8qiir;?Qsr;6BjfDg@~> +dJs1ErVm6(oVSOpp%eUerqu]o&,cG*qu6Wei?9EhZ2aV!rVQTos5Eq[s8Mrorr)j7p\saOQ_'nG +T:hpRUnX`c_Vk+crVlisrVc`qs8)foqu)*Fq#1g(qtpEnrr<#sr;QZkrVuiqrtP+WXJVkcV4XKY +StD[MR?kter;ZWmrrE&tr;ciorseu+rVuirs8;Wkq"FO_rr3c3s8N&rrr;lqrRW84(E4Jsp&Fmg +rr;]k)Z9R5rr<#qs82cWUo'iUWq6/es8;onqtp<jdf4g~> +b5Wmdo$qGYBs,4ocH42QccaGP`5fm;bKe#;%M]A5f#Z(Ub0%rPb/hTBiQ2&=!Q`F]bTad>[^07M +B4t^_@q0+]C2J^%]#)D)aNMZGc-OYWb08#LaSj,0aSEmkbJhHBaiMTHaiV`LaihiF`kK0kQ2YP7 +?"7/J@pE>LAm\i'[_BeuaNDZHaMu="`[o0PaiMWHahu*>bg>.sd*9eXbL+PV`QQ?Dbf.lW\.B2^ +&J."Fbf7rNbKA!(a90H$`QA,'%EcT2_o&B[>>\48b38TrrrW)oqUGOq~> +d/OUSs8Dutq>UEAip$LCqu?Qk)#jR8qu?]ms7@`d*$Q_fq#C<is7uZoq>]CPrr<#o'(l%qrVuod +f]qtik3MI&mHWcgr;Quuq"Xaarr2QiJc>9?rqu]o"8r#iq>UC(oAAg#nF5o6nFQ#4kLA5ars\f$ +qu?]ps82Weq>:0js76."s8Duns8DrqbpOe_+<k.em/Hq_%/^))gue%`hZ*WTp[n@_rqlcqfDg@~> +dJj^Ur;Z`ps8W&mW2?lsq"jjerr*].s8D`modCjp)^1%2s8Dipq>UEis8V!U)ZTd9rVuosrT^\I +S#N0VV4sQSUT(Kip\Ojfr;ZfrrVc`nrV_<Hnc&Of"TJ>rqu-Hm)ZK3LX/2VhV4a?OUnaf^QD3I> +qu?]mq>^<fqZ$Qn!<2rs!<2ur(B4@6rr)fqrr;forVcW9+s%^A**W(7l2D=qq>9``TV.jWp%\Rd +p\t'dr;P.EJ,~> +dJj7FqY^@#pt9ap@^j"ecH=6+ar&4>_9:!AeB&%7'GCsjcdL"WcGdrN_oTjVaT'F&c-"8OccF&C +[!YtcCLCCTA7K:gEHf%/^r+13r5e`WJ]R&rrQ68(a2Ga.^TWc<BObU_?!:H>?=RMKB;`MYaiqiG +c,RfHrQ+uX+j/'R`P]U5bg4\]aMl0Acd0eRbeqZHc-iX'()[\o6.!sSb5'-WaqDe8`P][;`l>N# +91r0&f'EA9r;HWsrVQKAs*t~> +d/X.Crr3?'s7,"4s8W)qpAFphqu7E-s82Ol+=A$T*%Z:.qu?Nls7ZKmqr.MYrVZ9_qu6Ejrs[fC +rV,dHmH<d'lf.O8s8W''r;69aqu$Hmp&BUBo)AXd!<2ut"oeGrqtp?jrse>WhWFD%o'l/7lL3ia +q>UNps8;ln!W;rrs76."q>^9js8D`'-n-5Y-%l$no)8ahqtpBirrDimrs@NHmH4?Hs8)`lr;Qcr +eGk%~> +d/OXQrVulss8L6B[I<khs8Dusrr;p7rr)lsp](*b=s+mt*u-/DpA4gcs8Vfms81dS!r`,prr3`2 +s8(fLOJ/8>V5U,]Uo(-6p%eOarqZQorr2lrr;Z_HrpKdbs8W)ur;ciqru:t;s7u,tXJ)AdVPBod +Vkg8`Qd>9orr<#rrqlQlrquirrVuos!WE#srt58/rV?Khs8W#j[Nct4'd%nunc&Ofqu.9/q>^Kd +j.`3?UX8o;rr;lnr;HWCs*t~> +dJjaUq#(0gqYfcQBPXNYaNV^(aSs?]a;2n7cH=?a"<A:$%2;ghcHaAJahZ6E`T"r@b0/#Krll.p +`k\]l?#F7_?t3PPCN"<\^r444rQ+lUs2b2^J]R/us2P)[rQ65&aMu*7_nNI-D.6pcA6rPN?=.;Q +=H0]"bg"MWbK.s,aSs1&aN_rJ_8!n1bg";L_8F@?dDsGJbKnDWQOjuJ&ees-d`hR1qT'Mrc-=DP +`l?!:aM?3K^S=[u9jOOSq#CBmcMrC~> +dJj4Err30$s8VNEg&D!Rq>C'dq>V6.s8N&sgasQm+s\6Q=7,b]s8N&trVtmV#5n/nq#('crr3A[ +kk+67o'Pl9k2#S+rrE&trrN,srqccprr2iqs8N&r!W2eGrp]mfr;6Kg!r;`mrr<#srr3K$jlZ!u +m-j?*mHO*'imR]'!;QNl!<;Kd%fcP.r;Q?"+sJ*K,)H$inbrUfq>:0k"oeGtrVu]mrrhrTm-`R* +rrE&trrE&Hs*t~> +dJj4Err3<$rqP'HV"4?]rVlirrr)csr;$BlrX7U9(E453(`H?<pAY'k!ri/uir/uYr;HX0p\OO) +Q^a\;US46MVP0a$meunYrr2irrqcZkrr)kJrpg!`ru_1=s8)Nfs8W#K[&U("TqnHVWMZbnS!<C6 +q"OXbs7lNkrr<#trVm!!rVc`ort,2.s8N&srq!T>)]'5/K_>-1rr2rtrXo,.s8W#sr;Z]pbGq&( +U#,VDqu?]q!r`,tfDg@~> +dJjaTs8Dibn`I,r?F%>gb0J0/`r*mpa2H6HcI0'1&Ki&3&e$hAaN2QDa2lHKb2^P\b/r,UbK7K7 +]p</>CLCda?=.AXBT0LE`6/)'"3S^+`r*gU`r*pVb(7Y(a=#!H`l?*@b0%iNbJ_33`59-QH#@G/ +?=7#=?sdMS>?SMQ`P]U:c,BV(,fn!F`Q$-E`PKC.b0A2R`PKC0bg4_]ai)?BQjOK@%hNO)bfon* +qT&i_c-=8I`r=$k_oKgCaM`d;8lTE0jnJ`RrVcZo!;k@IJ,~> +dJs7GrVm5ieC+9ps8)KeqY^-g(&S%.q"a)X-6XET+>"o$p%eXeq#C6NrY,5/pA=mfs8V9;p@%A; +kN_d,kO/6Ir;Hm"rquZkr;?Qnr;ZWqq>:)@rpfsmr;$-^p\=Xar;RH,q#:<no\ecsmITo=lK%R( +o?[C6rrDrns8W&ur:0ars7ZKerO"1!*[rLkpA=m[rW<#nqu6U"rqlTgs7lTmrri#\mc;psrr`8u +r;P.EJ,~> +d/OORr;Q`qcE*_hrVZTmrr3'!rVc`n)#aL7qu?WkqWCm$)&=,.-R%OBq>^KirqbXRs8Ni4s8Vfm +n#hbISt2aLR\laT\(LBMq>L9jrqQKnrqZSFrpp'arrDrqr>Yb9s8;fpn]Ir2WMZVmX/;PiS>i"1 +q=4L^qZ$Nm!<2uts8Mus"9/8trr)j.rr)ihs7cGt-Q3aE,(T:]s7-*frtPJ2rVlisqZ$Bis7uK5 +Tq%pUlMCMXs8W#ur;P:IJ,~> +d/OaXq"41AVg)O/`Q?9Fc,mrD`l@tu(sL.AccjSX`C:^]'H7])#ee0oa2Z'Cb0&bc(Wt1Kb/q<9 +[WbtpAn#I^?Ya7iI\+6k`r4-dbf\#J`l5jo`W*sVaSj84aRR>!`l5s;aN2NHaNMfLaiDB:^W![D +E+s&tA78tR=(PQO@\^iPaMYsArQ5,]rl-#%aMl'7`QHHMb/M99`QHHP`QZ6FN=cX6*#<;9bgQ:/ +qT'Stc-4/E`lcNJ_9B^8bJCcD<`!(>`8gLequ-Kn!r`#pfDg@~> +df0CJr;QZp$fBRss8W&ms76!`rql^.rr)fqs7u]iphqB#,9RmN+2msRrrMuriVilXpAP"!f]r%t +l079kn)*+%q>UHorql`qpAFjc!;qEIoD\dfrql`ns8)osqtg6grt581s8M*7l0S$&o(2A?l0$.? +rVllqr;Zfr!;uBd&,lP.qi!!D,UOS*pAY*hq==Oar;Q^$rqlTmqZ$Ekrr3,fkMkIQrr3)uq>:0> +s*t~> +d/ORSqY's_Y+`T(qu?QnqYpNprqu`prr<!-qu?B_C)n33(_Ro0_>!s/!W)iTrYkh1s8Di\PF%c2 +U8Xl`VOXd=oD&(Vqtg0erVlisrp]r=rq$-`rrW2ur;Q^:rVuWis677nV4j`PW2ZYkUSj3Rp@nUa +q>L6hrVlfrs8MusrVlcqs8EQ,rr;hO-5@OC(nC3rs82W_rr2p"rr)fprr3K(s7lNhs7!FjTVn^Y +r;$<k"9&/rrmq+"~> +d/PcunE02lFBa7/a3DWM_8aI5`l?*Bb/hWB`QQWMd*:-@%h]`q%hf#9bK\DZaOA;la;<"F_T0R2 +Z<UgLARoIdBQ%I(R^p,G`6%u&#0b62aMu6=qo43.l,`hCrQ$8+a2Z-Abfe)K^r"!hIqNA$@oHfF +?XI,R<GoC[a2Gp=bfn5Nrl+u]aSs-^`lcNLb/XG"&]i2?d+$?Q$O7C_$A6^OcGd]sb5'*qb/hQ@ +aNDcOahc*4_o'X(E`Z.FDp%50qY^?prVQQFs*t~> +df0CJqYgEn%I2O=s8N&ks8Vilr;Q]mrtbP3qXOUbrr)DA,p=QY,9\A(oDedeqr7VQrsSYOlh:2= +n*&ZfjRi3H"oS2lr;ZfprWE)tr;QQjJc>6>"8r&nr;HX#rr)]gp\=Xarr3T,qu?]kk32F4nac)= +m-=9&`;9N#rXAi(pU)Cq)C-T<q#C0hs6oscs8W!1s7QElrVu`os5;qqh<k7BrqQBidf4g~> +d/X.E$iKS?Tu6Eks7u]pr;HWqrr2irrr2p3rUg-hrqu8:+;u7<)]Bifnc&Lbqr.MlrVZZac]sof +TpM^VUSb!+i:R'Lrr2flr;HToqYgTsrr;uos+11?rr)j"rr)fprr)j!rVQHer;RE%d]fXKX.lA^ +X/;SpUls^.q>^Hmq>UEoqu6Tps8EH,qXq->*toY9[.XIprr;Nfs8N)urr)lr&-)>&s82iprnj`M +S=7"arVccqrmh%!~> +d/OaWn`\W%?[B,odDjAP_T0X7`lS/%(s'h=aMbd>b08/QA.9.j)Aj"oHcj^YaMm,Z)9U%?[Zt*+ +@V&YTBOu"#N2aA+`Q#s=b08*/b(7Xba90T,a2\(u(sgFH`5/gFEbB'"?XR&I?sRVZ;kph>b0'_- +!6Y;^s2kGb`l?+!b5]Q^`Y-A8d*0dt$P*OW%\(np`Q-*EaSO'TaSs0oaNDZLbg!oC_SF:7a.Zs? +92g>klMLJY!<(LKJ,~> +df0ROr;$BmrQWpmrrr<"rUg-grqucp)?9^4s7lEis7H?krV<lQ*@2^L+sVp9r;ZWQrr)j)dFmaQ +oBl;9lK$e"rr;us!W)Qiq#^EirqZQqrr;uns+11>rr;onrs\i&qtg0drVufor;6EkrseMQmdKi= +kjn?7kj$Ikrr3-!qt^-grr;Qg&,ZA).3'KU-b'$Rs82inqXORbs8W)srrW,qq#:<nq@N](iU6:! +rVuonr;Q`rr;6KFs*t~> +d/OUOrqtB>Y4;PkpAb0es8N#trr*i7rr)lrrVuohs8W&lZR-G-'Gq`/K_#$?qu>XS&,,IdS"QLO +S>`!SVlA,<qtC'irqcQorr)corr%EInG`If!<)oprr)]n)>j@2rr<#poYdDuT;83PW2$)ZX..Z4 +q#13krrE&srVc`ms8Dp-qu-@:'cJ&8Zhj\$qu?Tko)8XhrVlco&H;_,s8N#trVkNJU8"@-qu4qA +J,~> +d/Pcpp>i5cEO<a*^WXa5beh?<`lQ<Hb/hTF_SXO=]?A=<cBK(U*>oe4%r'82be_<Ya;2q8\nkhe +A7A_S>\7kmS%ut_`l?*=`;RgVa9'N.bl#W_aSWu.aRR@Nb5TK^`\#-KaN2KEair#Tc,[`:\Zp]l +ARK"T=^bK9>%h00^;J+;c-4DSaND`Obf\#Jqo0>kb08)Mc.NX9'G;"FeBlCXb/2!9qTAZU)90S5 +aNVfLaND`N_TBX5c,dhi<_Q.eT&BSHrrMukeGk%~> +i;`fUr;Zfr!;ufp#5S<!le9tgrVm!!r;6Kkr;?O0q>U?hr;Z]ps7uQ?-Qs`X+sA=7rVHQarr;oq +rq-3tbhqgXlL"''l/qR9rsSf&qY0map\"7TqY]^[Jc>6>!W;rnrs\l&q"aa_qu-HjrVlcprseVW +md9H3m.C#CmHiBdrr3)rq"t'gs8W&ur:g1$s7lCB,U"JAqu$Ems8;iqo)AXgs8;iq&,lG'rVuop +q"t*XlL+,snGE7cqZ6Worr<#t!W;rps8W)\s*t~> +h#@HTrVlWm&,Q>$c)@Msp@nC_rVulqr;HZorr)j1qu-Qls8Vojc6=/H(E")6;Z$=jnc&Rg!ri6" +p\ka%p?S':U8+?TVP']_^Z>(arr2urq>^Kos8<#srVZTlrr2iof_u$Rrr;uto)8Xhir8rWdJa4I +rr)ios8D`ms8Mus')hFFUogMjVkU#`V4soW^%M:%rr3#urVl]rrVlfms8Dp-s7l::*>os'q"t$i +s8Drsq#:6jr;I''rr)fnrVuosrr)ir$N'h:VOF*Lanu&9dJn^~> +huE`Tp&>^'qWOnoA#6uX_T9[8`PfR0`Q$("bS\LD_o9R1`6?-;a2cQ3%h]d#*#92HeB#c%aT'B_ +aSa'UaT'6s`PT)oBPD$a?=I5PD2,1-`6$6D`5]m<`r=!]`lQ6Db5TTcb09k-s2b)WhoGf?qoAo[ +aMu<@rlG&\q8`QUilM,=dE):/s2b5["3AO%`W!ptb0J8VbK.W:]s<Q-D.[3c=^#!7?Ya&%]u.k2 +r5o5fc-4>O`lA"ss2Gbob08#M`mkh@()*.ec,n&J`5Ka<qT8i_c2Q#obf[rC`QHEIrlG,a%`cN) +`luWF_K/X@9OX[arr<#nrr2usqZ$Nmj8XW~> +iVs&[r;6Bjrr36$qt9aXqY^?lrrV!*rql^Gqu$Korr;oqs8Vcls8N&srr<#srVliqqrCd',Tn6T +,q7[Iqu?Qis8;`nqYgWqqtp<jo`#9Hl0@a,nEB2oir/lV!;ZNirVHTmrr*'#rr;utq>U<liVr`P +qu6QoTDn`fs8Mons8)iprqcX'hqI5YlL=H:o(_b6h#@<UpAP$jr;QlrqY^<hrr;m+rr;h`,Tp1a +rVHQor;ZNjrsnr*qZ$KnrUtK/qu$Hns8Drrru(h6rr2rsr;6His6At?lf8!Es8;osr;QWlrr3-! +q=sjdrVlrsqu5dYJ,~> +h#@WXqYL$frVulrrtbV.n>iA;o`"ddrVlisrVc`qrVlisp&4mjrr2rtrVum3rVGMO*ZZ%6)]p?Z +q>1-gqZ$Kis8Drlru1n8rVQWls8;fnptq.,T:hpTSu89beb/t?r:^0grW<&trRCiHrrE&ns7QBe +s7-*es82fls2b37s8N#tr>bb7n%#EuW2-2cUS4KWS>u8Xs8;osqYL*dr;Q]ls8W)srs\[g*Z7lK +qtg?mrVuZlrt##+qZ$Knr:G*$q"jshrr;io"98B#rr)j+q"2.kS!fu$qu$Hns8Mrr!<2orrr1sX +J,~> +iW&rVs82irs8D`m$gc#U>)g&7bfn)G`W!k)_T'O:c-jMRa2c-:`lcTMa2Z9Dbe#eD(Dn#-'+he( +b0@uHbf7TDrQ+uX"N\g2aMn.r'ue5=aj%fC_7cdNCh@6hA6ieVEgjZ?`UV%KaoTT+f#[m6"3ep/ +aSs0a`Q#m:`Q#p?rQG>caN4;!"NAC#aNF+qrPnlYs2tA_rl4rV!62[m+i_L9^ohooARShJ?=$uN +AmoPb\AQ,(bKA#Nb/hZC`Q#ss`rF++b/V?Ad<uW<5M4E*aiVKC^WjpGa3)EG`m)lU=+T&Rc-+,H +aNFJ&s2k>_rl,YnbgXJ=E_]/$A[CaurVcWlrVQKjqu6frq"X^ajSs`~> +iVs&[r;6BhrVmB*p\+L`r;Q`rf[]Zps8Drs!ri,srVm9$s7lNls8;ior;?QnrtbS0rVQBhB-/QA ++<;USiW&cSs7uZls7uZoquH`nrrE&rrt3N'mIp2Ap#b_tkPYA[r;$Bj_Z'H1qu6QoP5YR]qtpBj +rrDrqrs\/JhWsOqlh:/EmGQ%arrE&qrri?!qYU0brX/]"s'$co=Sr-qpAY'nq>U<krsJZ"s8#nC +0!Y?QrUTpgr:p9k"R>IHo&0NI"oeK#rqu]nrri8qq"apfrrW)nroa<3~> +h#@KUqYL*ers\l(r;!@fb4Yc4r;HWos8W!+rr;ipq#(0lrVlfpr;Q]q(B441qtL"u)'T\0'cJ@R +s8)cqq>U<lrVlfrr;Q`r)ZK^4q#C3gq=UYISu&6SV4+H\]A3,Zqu6Wq_Z'T8!<2cnpAXjenGWFf +q#:3k_Z'N6!<2ur)uf^3s7FC:V5pJgS>E$PU7dt:o`+jgrVZQirVlisrr)lrrr2p(pA\/9*`Vt7 +qtL*i!rDoorr3?&qYp4i*@\,dr;H3crr3H$oWFpXU8R;Ps8W)urr2rtrquctrr)fUs*t~> +iVs/]qtp?ls8Domrtt_0j*4mXW56U%c,R`A`lQ6?aMH3@b0\9/`#H_=cd'kU_SsL7eOBib',V>n +&\uu;c-O;K`l\2#rl-)%bfn/I_o'I5a2ZBD`kJut<b6,^A85FgA:C/__nsL?_8uZ!"3ep/aS3^P +b5]QX`ph%L`r4!Yb5TK]`rF#pa99N%`Q#psar8@<^V[=2Cg^d]>ZkQH?"%,BUU.kUaND`LaSs3Y +`VmgUa<8L?aNEC*%15&Cd)WlCaNMEBaNMcN`Q$9S3slaff$)2*a:-59d)!)#;G157aQ`U$rr`2r +qu-Hm"o\;mpA4aKs*t~> +hu<]Urqu`p%/]\ss8DutkKW2Ys8W#r(&\(2s8;orrr;ipr;Q]qs8Muqs8Dfnrri&oqLg?s,7,5< +ir&fUq#CBlqYpEm#6+Ptqu?Bfrr3Aag$%\lkk+B,iUHaDrrDurs2+d4r;$?ls-!?`r;6BjrVuos +r;R/iiU,t.o]P]1l/9__rri?!s8W)tr!*,ts8N#qr;HU8rVuTd?7-t"p](9is8;cks8W&sq#C"l +-70`[[f>mss83H$s8W&Om-Wa!s8W#js82fprVlutq>:0irrW)nroa<3~> +gA_icr;HZos8VuopV`rGdJin<rVlfqs8W$&qu?Zps82iprVm'#rVccpqu6U.p&+T8,odjC*"jUV +r;Q`ks8W#qrr2p#rr)cnrqufrq\9#+gTR3ET;@jGSXlY!iVWZTqu$K1rql`irqHHhrqueprr)is +rr2lrrY,>.s7G0]WiD_pVk:#iWLo:)oD8Idrr2os!WDrqrr<#trZD1=s7Q%g+s'_Us8VurrVQKl +s8N&ns7056+;Z6/s8VZhs8NT(s7k0:T:VO`qYL6hs8)`ps8Mrr"9/8uroF*0~> +iW&rVqu7<+rVufhpAXsLSo&q5\\?21bfKb&.*0BOaN2N@a2H!;aiV]IbKIrCc-4SSd*cJ<'GqZ& +#S=Jdb0@fGbJsM%rPnlYrPnlY(X^.>`knEl@Ui_W>%hP\DN1O.`l>p:b.l!tb4NdO`W!mRaSa'V +aSO$ZaS<oka99N%`Q#praqr.A^;I=LHtd+rBOOtO@q&_@S[lPVb0'V&!QW4Ua</FBe&g$$$j\l@ +e^)+S`5TjDb/M?:f$?Vn'F+l&bJj"m$d$0-]ouGl;-8_5nG`Fjq"spbrVca!rVQHfqr@^,~> +hZ!l\r;6<fs8W&rrVluqcHZ"[rri>uqu$Hls8Vs#s8Dutp](6lru1k6rVucns7?9ir:m!9*ucLT ++H-6prVufqr;-EjrrrE"q=sIXrr3&Kg["k+"RkdGlMCM[!VuWks2+d4r;$?ls,m<\r;?TprW)`k +rs\AUlfRTtjRVU0p!<:0rs&>qq"jmfs7cNmrVum-rU_Nb-[5F[rr;`ms8D]krsA1!+rqsW-KG.' +nbrRhr;Q^)o\\s$g%,1=qtpEmrr)j!rqu]nrVuop!<20]J,~> +i;`iVr;R?-qYgHoqY^3;UT<5DrqlZnrVulr$30o"s8Dutq#C?mru1k6rVufos7?9iqt?U,(_[o5 +)N"IhrVufqr;HWorrE&trVulrrtkM2s7PcLQDCFVU7n3TXN^;3rr)irrqXD0qu?Kk!WE#ns7lTk +s/>qrs8W)tr>,D4qu?]kp%6/$X.lSiU9LGlWK"giq>C6orr<#mrr;rsrsntt,p4CQp[nIbq#CBl +p\t1"mT1AD+!Mrhs8;ogrr<!4rVuZ_bFkK#REPO's8)`ps8Muprr)lrro=$/~> +iVroVqu7?.q"Xmgp@%eDX_r$F[DKo*bfn0,`[JpOaiV`HaiqN?aN;]NaiMTG_o^0>e'-(_JJ8Y, +)]f>qb/MKG`luI$aSj-Y`>ut>b0%rN_T9d/[:<KS@UWVRB5`'_]Y_Y)`Q6*=_8uVqrQ+u\!6kDa +!Q`7Z_uI^U`rF-WaoKN\`r='Yb5KQVb5]Zcb/24'`l5p:`lS,$(W+52]t(\.An5+R=]T'<Ant>% +]Y);(aSs6[anNk!aiDNHcHHV(%U.B'b/h?DeBGbMa3Vgj&.T?`!k-=i`q.7\`l5d;_7,8":/Y5h +kk+lSrqlWlrVHTnj8XW~> +hu<lZr;?Heqt^73gthW&s8)cqr;$0cs8W)rrVuonqYgBmrqu]ns8N!0qu?Wps7uBgrV4Gc+WhUP +Abc9)!r;`nq>UEorVlio%KHA+n]'hdnEfE-l/:Cqs8W#rs2"^3r:g3\s69OYs1eR2rri8prVHBh +rtG%bhr*trkOeN9p"8%!s82Tcqu-No!r`&rrVn&?r;Zcms7lNQ,Te:ap\k!hr:g6kr;52",U4NZ +>4MC_s7-'qqu?Hjs8V<An*JX(rrW/urqufqrr)lsquH`Zs*t~> +irB&X!WE#prseo'rr;ijg81n*r;ZNir;Zfrs8NN+s8Vlir;HZpr;?Qorr*N-s8Dutq=ajep;A<r +((hg%q#:9pq>:3jrqcZprW)orrt5,$abc^hU7\'VW26Nfm/$YYr;XY5qZ$Nn!<)Qhq>C?ns7cNk +rV-<grPJR5ruD%:r;HTorVuops7cH_c*OCFXf\(iUn"?KXn2GgrrN)trVn8ErVcZmrr<#tqu?Hg +i?&pYJ+W[9s8DZks8;cH.39HK*`hb)q>^KdrYGP4s8Dusppm&iTqC3=s8Muss8MrorVZ]qro=$/~> +iVroVrVmN/qtp6cq"ss[kdPABRD-bZaj'h-!6G/Z%EQ`BdE9STbKn>N`lQ:$aqqt;bL+eZ^s(!J +WuDfj'GrsNbfe8K`QS5$rl,tt_o'L:bg"DVbeLcK:hFEL=]f0IBlh/&a2lEEaSs5sa8j6Z`<4-$ +aNFM+!6tMe!m8U(rl+oWs2b5_qof)^`r4!Xb5TW`blGueb599[aoor5c-4>Ja=,'I`Q#p=aNDZG +b/_B?_8j-ECLLFW@8L38>%q/\\%TZ!aN2ECaihm+b5TI*b0S5Ia26*:#mh)Re'Q.W`5^0G`lYIs +&/H#m435FW`l@Vk%E5uu_og-9EDB&$B"RO2s8;inqr%L)~> +hu<oYqu$Bhqu$?ks5O%X'DVV-qY^0bqu?]oqt^$_rEt9KrVlisr;cirrtbP4qYpNls8W)iXsY8= +,H^b@qu-Qis7uZmquZlqrr2p)kgT"inEfo9i83GkrrE&ts8Vors89b5qu$3fo)IqQq>\5/r;Qru +s7Q'bq#(..lJLjnp@e+Ip$pV\s8W#mrVuosr;6BhrVm?+r;ZNkrr;ifi%H0"K`:l\rr;rprn/bH +*?cn6nc&Res7-'jr;HKcrr<#Z!qPF*rr3&rr;QTn!ri,srr<#tk5Tr~> +ir9,[rVc`ns8W'-r;6KlkcU]+p&Fsir:Ksf$i^,)s8;Wdqd"aAqu6Wprr2p5rVu]ls8;osrU6[, +'d"Hsq#C6is7lWmrqZR3rVlcoqs_=eW1]cPW2$&e]CtRjq>1'is8Drs_uBN4s8N#rpAXjcs8E#u +mf*4crr2io_>aK7*WH$8rVlisr;?Tirr;]_m)6$+USji[SYW0NV>:#frrW2trVca$rVZTlrr<#m +rr3o5o@tf5,(TLdr;Q`oqu,+n*YoY=;XXM`rVuHf'EA(3s8Duml`lnTTrRYXrVHQorr2inrrE&X +s*t~> +h#A/dq"X[^qYL6a`cYO<ZcU>:b.u*>b0'_'.*0HLbg\[Zb0nV[a2Gs<c-+2Hd`Kb]_Sj[Ed[D-k ++q]LHcc=)K_TVo!rl-)"_o'L:c-OYW`O:A'C1CXT@pWDSI(Zo6b0%uTbJ_BA_T3#&`P][6aN2TL +rltJes2tA_!64uYrlY,^!m8U(r5el[qoo&^s2b5["i\L&aNDa+blGo'aSj-Xa<&LL`l?EEbL+/2 +VL<&d>$P33=(5iIBXtdoa2c9Aa8=$Ya<8XM_p$$CaNVC7#nL\"cc4&RcHFP<#nRR\)*H*gbf@ir +a:Q>(^r=@A_5Um09j2_mn,<1`s8W$#qtg0drS[^+~> +huE`R!<2ut!W;opru1Lah>dNMqXX[drqlTjs8W#orr2q2+=(pup\t13r;Q`qr;ZZoqYL3jpAaqo ++Y"H\p](9gr;ZWnqYg]sq>'sdqtpBm%ccF5mIKT;lK[:,s8N&nr;Qlqo_/0Urpp!_rqZT1rW2rr +r;R$$pAY!dpAOgcrsS&IlgjiDqX!S=hoGZp"oeApqtp<irrrE"rr;ffrr3i4fd7mkHi3pCs8)]N +.3f`].8KpCrVucpnc&Rg$Mj_rrVulUk3(Odrr<#rqu6ctr;?QRs*t~> +ir9)ZrVcQl%fH2$oYI)nr:g6kq"t*jrr<#srr<#t"_8PoC[h#rru:q:s8Musqu?Kgs8VinoiE%U +'I3;Ns7lNlqZ$NnqYqH4s8W&nn#VqPU849VS>NCHo_SU_s82WhrVcc6rquf\rpBabrqufprr)f3 +rW<-!rr2lrrW)iprrW0!q#::,o#7N'T;&*^T;/K_Rdp.Ms8MuqrVuip"oeQ$s8)KhrttR^+WM\M +q>^Hnq"rek*>9\C8c8Ves82ierr2p,rVucls4sTFT:E^kq#:9m"9&/qrqucrro=$/~> +h#A/do_/1[rVli\N)3BR\]`LFaj%oJb0'_'s2ZP2f1-&S=4>I>b/2!7c-4,Maj8)K_o'4>g.;u$ +&JNI5bJ_EH`6%u!rl-)"_o9^@c-=DM]5q:h@:WVV>\.ZAZb+K#d*9eYb/M?>_T2r$`P][6aN4;' +s2t8\qTAfYm`#j[b0%fF`l5j5`Poj<b08,Sb.bsr`X^)-cd'hXcH+5J^TW3!?iF1;@96cNA6H1L +`5]j:`l\)"s2Z;)c,%-8bg4YG%1EkUf$MRdcd]N9%gsEp1YL3uaN)KpaSs0f_T^-CaI#st93%,3 +nGE4frVQHgr;Qfrqr[p/~> +huE`SrVlotq#13nf\ui01\UMArVuoqr;Q`rr;6EgI3^$b+(++$s8W#ss8;lps8Durs8DulBd"fE +-H>o^rVlirqt^6kr"/c'qt^6ks5Dl.n*fE/lfd=,rr`8mr;HTo"8hcaqkF)[r;$?fs2"^7quH`p +rs/Q'oD/%VqYL-i$hi]Lo()>Cn*9-%ao25BrqcNir;-C7r;ZZos7cQjr4+%!.CJsLs7aD^)^H[M +CARi,qu6Tpnbs-sq>UEkr;HZpi9BR_r;ZfrqtpBnrr2fqro=$/~> +iVrrXrVHO.qYg<fk+em2o)J^gs7cHjs8W)srr2pDqKj;(+;e8?oDejhs8W#srr;rsrVulsojo'a +(EgTjs8DrsrqlWmq#;00qXgYLURn9OU7eBag\LdIrr;roqu$Eks24j6s7lTls7lTZs8N#os8N#s +rPAL5s8W)trVum,qu?Wps8N&tr;ZH9Y,D8n#cOSnUT9^Go)&=aqYhT7s82irq#C6f[2pG9Z1e+p +otMjh*?>u.p\Omes8N&grr;rrrt58,q:)13US-$1qu?]qrqu`oqu?]qjo9i~> +h#A&bp@eCZs8Vr@@8Vl\a3E#a_o9^rastEMaN2BB<='9V&4saZb/D-:bK.]BbKJ8Qa2H9K9FVdK +'WK@$ai_lL`VdgU`Yc\7b08)P`P-4nB3f"OB4bsuS[uMS_Tg:'blc,0`l>m:!65#W$-('-b0%rN +b/h[&`q[XS`r<pWaSj9\aSs3X`=^,2b/hTA`P]O0_o9X:b08#N^<$8m)U-(AaO&5Vd)a)@[#Ad/ +>?P$5?<glO=0fKTrl"oZbPTH^a</FEa3MiBbK85#$4mc7cd:4gU([hJ'b!mhbfI]Ab09Cs&B)H) +aNVlI^5>`V;.6Bcp&4ggs8)fpr;QiqqYfUWJ,~> +iVroWq#:a$s8UR(mf3=dq>'sas8W!0s10X*+!MdR-f=drrr<#sr;ZQkrsAZ$qh$1=,9iiXq>LNq +s8W)srVmE-qYBgas469%o'br0n)<m:rr`5mqY^?m"TJ;nq#%`&&,lM,s8Muqrqu]kqYL*fs82^& +qtg<hqu-KiqYpBirVl^$rVlfnqY^<hr;QWo^Ae01!<2or#QFYuq>'pbr;?R&n_iR&p@7P6m.BVn +rr3E'rVZQmrr2Wes8N&uq>Lm#\1&gQ\G,g.,pX]U-&)?slMgh`%fZD(s8Ud6lKd1(s8Mrnrr33$ +s8Mrnr;PaVJ,~> +i;WfVrr3W1s8Musrqc&YXi1&4rr<#trVZZnrr2os$G%Q,(E!u0,2E"irr<#s!WVrorsJ`%q1'S- +*?C^GrVHKrrVuosrr2p7rql`qqZ$,\S=uXLU8"NZ`9mHqs8W&ts8Mrsrr)l6rr2rqrW`?#rr<#t +rr)iurr)ilrsJc(s8Dors8;fprqZQprr)ir!<)fprr'\4s8W,us8DusqYq9/r;-<jqpr$LV4sZY +Uo(&`Qe(s,rr3<%rVZ]os8W&trVc`prt>>+Zm6k>[.O'u+<;F;++a:drVliarr;rrrX\r'YG7\b +TB?%Js8;lorqlTmrr2'[J,~> +huE`Ts8P.YqtU-iqq6.$DQLFle'ZF[`Q63EaMl->b/fAB%29d")\9X*_oBa=a2H3=bKJ&Kaj=H* +&.o8$d`qd6rQ$)$b0%fEa2l<D`llQBaLl4q@UEDLA8c=F\&,esa25ssb.Ymq`r*m^aiMQD`l,gp +_Zdur`5Td?r5]>e`Q$6LcHsq]b0J,Oao03\aNVd*`X9Z#_o'F2`l?!<a2,jrao]Z(`r<sW`ZrRI +bfn>VaMc*0O_\<3>Zb06?=RMSU;+=Ta2c0Aaj%lKd)Z..s3)8"`l5sAc^,+P$^]DoQ44KC&.rU- +cH6(*n&Q'_aMu6Bbg"5@AP>QoA&IO&r;QirrVcZo!rD]jkPp&~> +irB#WqYps%s8UC$ec5[Kr;?Qhs8W'?q"f+Z+X\QW,TOJsr;-<jrVQWerr)ls[ich;-@kpeq>UEo +!ri,qrr)lss82ir$-qo+na>]+le:t0rseo+rqcTkr;Q]nr;6Bh])Ma.s8N&ss8O)9r;HWnqt^!a +qtg0dqY0XKlKdj)lgON?q"jpdrqc`rrVl^"qu6Wpr;6Bjrr9k7s82rqr;QWo!<2uq!rMonrr3u4 +q>^KSl0S3<m-X?<n'CD$s7uWns8Dupq"a^bq>Lp'r;!TE,:L.2.j,o[,(oUgrTsO]rtGD/r;Zfa +jQPdXs8Vfmr;HWorVlfo!<2$YJ,~> +huE]Ts8W,u$2=DlT;]!irr;usr;ciqrVZX3q"\qQ)BKk5*>c9cr;-?krVQWfs8Dus[/M!H+aj%Y +q>UEo*<,m7rr2ikrVulsn=$5JTV8!PWLh#orquNjs8Dor!<2or])Ma.s8W,uqYqB2qt^6iqtp<g +q"="<lKmp(n+HGNqu-NnrVum"rr<#trr3*!r;?Nms2+a>s8N&urr2lqrql^6rr;utq"asWZ_j@o +X/DecUnWsiqu6Kls8VuqrrW2ps8;lqrtPG/pT>\],IOa&)AjM8J+NU:rVulrs7-*drVld*p[knc +S>2tXrqHEirVlZnrr2'[J,~> +huE`RrVnkSp]'Q%BO\$R`R!#Zb/M9>b0%fE`lcNDa\`H\+X%U9".7NZ`5BX9`Qu3:a3N5##7V1R +@F3-?rlY2\s2lA'`l,j8`5p*B`QG]!CLLOR>\%bdP.JiW^rOO7aSs2daT'<\`rF!]`lQ*;a2n8% +&'3)Bcd0tabg";QbK\5Nao0O"dEg+^bg=YZb/hQA`l5d0_SjI8ahl+'b08)Pb/hU#`BhMbaND`T +dETG<_5M9]>@_2J>?GEN>)9i*]#)S3aNr)PaMQ'Abfn5N`l#d9bKu4R#S3Vt&e5Hi&8';5a2c3@ +rl4KLs2tA_%Eco@c+pYr7S$^*g?nJ/rrN&rr;Zfl!<)*\J,~> +irB&XrVuoq!<2rs#2Rc.s7l9bp\u!-s8N&uq26[G)C$LT+ccKus8;oprVlg'pV%pt-mhshs8Voo +('"72rr<#trr<#ts8UR5lgXE2lKdF-s8W&trrW/urqu]'rr<!&qYU9kqtL'eq]5M-lK$aOe'ZF_ +aN)BDaN)NRf$r0ug?%l#pA+Xarqccnrr)fp!WDo4rr;luqu$Hmqu?]q#5nK"r;ZcprVm8]l/qF' +n+lMCm+1V'rrN,prqus!rr;omrXo2-rVrl8.NfoW+s87dp\t-im/Hk]$2j]!s8UjAj43u)rrr;t +qtp?krqlcqj8XW~> +hu<`VrVcaGrV-0FVP<k_s8W&qr;HWorVZTlrr;rrs8MbJ,9%76*$?5YqYU<ks8;lqrsAA1+<2OI +;>1%iq>LKrrVc`mrtP;+m[Bc;U8=Z^WiFkArr;lms8W#ns1A:-rrrB#s8W)prr<#t,5qE7lf?jP +da64[`l5s<`l6-Le^N!sg?%l$q#(0lrr;rqqu6]rr5/F8s8N&ur;QTns8E&rrVca3q=CkqT:r$R +WhH)]SAP"!rr<#or;?Hks8Drprt##*s/-SW)B9V6)'OP'rr)corr;Qgqu-Qo$iU+cU8XTNc2@G; +qY:'lrr)iYs*t~> +iVs#Yqtg3frt"ei\n+mI]ZA@FdEK\N`Q%nus2H5)bgFkdC_IHn)]9J!D:?\S`6ZNDaiMiQS.-#G +&ie7aao0B\a<&IDa2l<A`l?3F_S`rpAmSkR?t=4sW4C1"b/hfJ`;R[T`rF*[b.Ymp`\P]W`lH6E +a2?*Ec-Oeff%J9g_S3^q\$roY]">M]\\Q%q]=br&e_8EueC)[fbK.iH`r<pX`5BI5#g1B8b0%fF +`Pqhos2@@FaNDiYdETeM\?Kph?!UZ9?WplP?%]Mu^Vn42`l?*EbKe>Ub/hTA`Q$'>bL;+E'FkT^ +&J#IdcHO>Jb08#L_o'Laa:ZS=bf\/UccaD";,^.jT&8r6rVlrsqu-Kn!rD]jkPp&~> +iVroWrVuoqrVm,Kj8]/Yo()_Xs8W)ss8W)uru^t7rqO#O+s7pH/0]'3p](3hs8;fii%$/r+scm\ +s8Dcm!r`&qrr3'!rVQTo#h&)-p@.>1k1K\5!r;Ncrr<#t!WW/uquZlts1/+`qu?]pq"XderquN\ +kM".sb/_H=`lQ9DaN)<?`5K[=`5]j=a2Ps5bLu.Pqu6TkqY^?lrr9h6rVZ]pqu?Zp)#X40r;$Bj +qu?]\ioft.kk+K?mF(%ps8Mus"TJH#o_eRb&c_b-qu)Er+s\<X,-(J=qu-K[rr)j+rr<#rqu$Bl +qV^T&fD#:E"8qukr;?QSs*t~> +hu<`VrVca#rV>iPY2AmNrs&H!qu$Korr2lrrr;p<p&Fs_[3?S.()/&7D#<r+r;-Hlr:f"o+Vu+? +oDJX`rW<&rrVQU2rqtoDTq%sRTVJH^h"q'Jqu6Wqr;6HlrVuos!<'V1rVllqrr<#p.fTJJrqZ-K +g<7=R`PKC.`Q#m8_ns:+^r+70_o0O5_nj14g?SD1s8Vuorr2lr^]+95q>U?m(]472qu?Wls7aO6 +TV\QVW2-AhQ+$2[rVlg"qY:*jqu6Tnrt,20r;ZZlL`@BU)]p)tp](0jrW<&trr2rgrr2j0rr)fp +s8VfecD.24T@Wr9rVuiqqu?Zpk5Tr~> +ir9/[qtg3gr;R?!c":FG[Em1HdEg%X`Poj:rQ$2*bf/5`d[CXW',2$!$rPQpcHOGS`5p'5&etog +$e!>B`5qr#rQ$)$`lH6Da2Z0@a2P8iC1(R[>[hJbV8CEubKS;Va2Gpp`<4-$aND??s2tA_rPg\3 +aj//Qaj8Jff$r'g^p^GW\[]5`^;7\(_SO(%]tVCq]Xthe\$`EC]#`:Of[nHoc-",Irl;ms$HgT: +b0%fH`l5p7rP_+Cb08D`b0Ir?`O1A6?=7)9>[M)R<ctX[]u7t4`l?9H`QcWJ`l5s;aN;?>a3\N, +&/#Kc$B*<Y_o0O<c-48H_8c#d&^&>Ab0%uRd)*8G;H$e/XlT!MrrW/qqu-Nrqtg9Ss*t~> +h>[NTr;HX$gtCTbs7GsVrr2p#r;6Eks8N#sruUn6rVYLt-mfrW*\1I[r;HZqrqc@f*@2aSj8]/S +s7ZEms8N#q(&7h/g$S>#mITW-h"h!Mq#1*grVQQls8N#ss2"^7s82d5r;HKgr;QWhkhOM&^r"(2 +_8F73`PfX0aN"+r!65#W'?8,9bJqWD`m3N6rV6<jr;-<grP8F1r;Zcps8W)ur##D.s8W)us8)cq +k2u.$o'>`5naYJss8VuorrW)kr;-C(r;Z`qp%O4f+sA>Aq"aserTaC^s8W)urrW2sr;Q^!jPf7Y +h>R?Tq#(-js8W)Ys*t~> +huE`Urr3K-rV3Fg[e0Uts8W&pqu-Knqu.];p&FsdgE7[^'c7`5=6KGWrr;unohH;E(F%f:s7u]g +rr<#ur=K#.s6,Z:S>;mUSu8RCq#C6irs/H!s8W)ts8Te3s8DusrVmc5rVZQkrquNShU0<Y_SsO1 +_Sa=0_SEq)_Y_.L_Z%@b_SjI8a3)NFd,X`sqYpNor;Q`r_#F93!WN,trqud4rVlfirVucpou!l- +TWP/jVP0cRYj_Vfrr30!r;Z`prr)lsrX\r,rr;W`K-20S,I7%<s8;lq!r`,trr;Ec!r`,trr3B* +n[,'cT<@e]r;QZks8N#[s*t~> +ir9,Zqtp?js#KuOicA78Xi\c4c-=JVb/hTA`Q$!Ab/hZN`QuiW\d&ia',D/p5/bpud*'SRc8Z1K% +hHM)bJ;6@rlY)Y*6H4=`5][4Zs[NVA79%YD/c5^ai)KLcHXDLaN+8!]u^5rs2YJc`Poj:aii#\r +n%h.`k8X_[_9Mi^r4:5`P]R3_u%:N_>_4`_8F7.\$WKG\Am.We^i6pb/_NB_8uZ!r5eoX!6+lU6 +-.ErcHaJRcG@N,K5>(&?s-W:>[^o[Yedulb/q]EaN)NI`l5s;b0%`H`5omBBFG4S$BrfWbJM3=b +g"AQ`P]^ba8jB^a:6;9cHO84CfXD7GgP[Nrr3&sq"Xgf!r`#pkPp&~> +hZ*TSrr3&mdc:?,s7cTirVlusq>:'gquH`qrs8N"s8;`P>9G?n+;#tLhuEHMs8#eD,9J,Bq=jge +q#:<n!ri/sr;R&Km.U)=lKIQorr3?)q>^Enrr2rtrVulrr;XY5s8Vuqs8N?&r;?6Ke&]T/`Wa?! +_84%-rkf,`aMu3<a2uKFa2Z-u`tHA/^;@b*`5TmHe*$5trr;uqpqHb+r;Zcrs8W)uquZcoq>UEo +r=Aqurr;ENmcO'-mechNjl6:>!;l]oq>Lp)r;ZZoqu+EODUSRXs82iprW)uerr2fqrr2p"r;6Eh +rr3>\iTf+bs8W#mr;?Nns8M*ZJ,~> +gA_Z]qph@FoD&:`s8W&pr;HNmrVdl<qu$Klq;,0k+W)%6+X>bAp&4pd<$3.s)n>Y:rVuZls8N0" +rVlcq%dfIPTqJ$NSZ/^Mq#CBnrr3-#r;Zfpqu-To_#FB4!<2ip-N<r?o]"<@a2Z-<`59=)_8=%) +_SsR5_SX72a2Q!7_o0L2_8!\#rko#\bL"]#nb`:b!;jM0rVucorVn)>rr;oiqu?Kio#Io6U9:Mn +WMZJd[-IViq>L?ks8W)ts8W&s&HD\.qu?Ni^hdc3s7H?hs8W)t"98B#s760fs8N#srs\l+pZ&-A +US#I#r;-Ejrr`9#s8M-[J,~> +iW&rVrVnnVo]NA]A#d,_cHOANb08)PaMYp8b08#J`QuTEbf\2B4q&AG((h2j^u!;[ccn6W().@Q +d)ErJaSj9[aT'@&aN)9?aN)<-?"mt]?X[G_G-/Nta2H9HbK@rNbJq*6s2kA``r<pc`lucWf%ep" +^:Ckg^Abnd^;.V'_SX++_n<Oj]>).q^V7Fs^VIRr\@B$I\-fj^^!5!We^Dac`3IB/a2?!Fc,e&Q +^;%"/Ch-US=&`O9A7p.i_T'C2c,[rNaN2B@aSs<ubf7]Be'-@7;,=:I`6Z?D`lQ<FbK.]Cn]2Wk +aMu3<`lQBLbK[_p>Y8"'Pi)*2s8VlfpAOsi!<)'[J,~> +huE]RrVlrIgA1aJ!<2or!WMooq#C.7r;Q`rq>L?fs8VrgBI+ZH,on0XYl=OuKI@`c-)1,5s7H?c +q#1?prqu]o#h\4sn+#]4jkg":"o\8rqY^?ks8W'#r;6EkrVsb6rVuiq#Pe>un__d:`;[S'_Sa:0 +`5]d7_SX41ajntof\,!3f\"ZtaMu9Aa2Pp4_o0I3a2ZK`l1P&U_#FB6#6+Puqtp<hrVd0%qu$Bl +rqHHmr;QWo&E2XBn+,u@o',Dos8Vrfqtg<lqYh$&s8Vrms7lWjs7u?fq>('irr<#erW;ulq#14# +qt^*aq>^Kmiof@Trr3&srr2lrrr2$ZJ,~> +iW&rWrVm0%r9:5cfD>@Drr2rr!W;ons8N!?s7lTnq#CBinm`aW*uu(7,-:_=r.61-*Z^dBs8Vcl +p\=^hs8MrqrugppQD:+OURJ'XXlB$Or;HZprVc`ps8Mrqrr<#trr)f3rr;rsrr2pTrqQKmnD2F1 +_SO++_o0L4`Q-!<`5K[;bLP4sg"G*4f\"Wra2Q'=aMl'6`5T[6a2cWdlh:>X^]+*0rVlfr,5V?; +pAb0ir;Zfnr8Y&TXf&4rVk]f[VsOH_rr;rkqYpNpr;I<*s8Vrls7lTgs7l9eq>('irr2rdrr)ls +rr2p+rqlHip<TG)Tq^KBr;-HnroF*0~> +g]';4mD*RNNP!*Sbf.E9`m)iSaMGX2b0S;N_8!q1^<4[Ed7k2_*#fP-(6R1lc<CS]*#ajcd*92F +`VmsWa<o$M`lH9C]Wu!\?tNhOBl8'q^r=7/aMYs8a3;fOaiquOb/hZD`kfarb!!hc`Poj<`mE>b +`4WRf\\,Sh^V@S!_7mOj[^3EM\[T)[]tV7s^qI4`Za@-O]tV:s^qRFm[CX2obgFe]_8uSps2auX +6--g]_7n4Dc-4JW]sjME<a\g(;I!U<DfN2*_nsU:`5TX3`lcNLb/hQGcH+/S`m2ubb/;NB`QQEF +`l?'?bfn6$a;`:GaMGU,_oU'Fai)B6Mc!2MBtis2s8Voeo_[VIJ,~> +kl1Y^qYpWrqu$Em!p%qrrr2urqu6]pq>U-kq>:*hrVmo4s82]nrqh6p*$cLL+XiHCX!&W;++a:g +pAb0hs8MrprXo))rVcZos8DoCnEK6!kO[d#qu6]prr)lsrW3&srqc]nrVsb6rr<#trqm!!nCbn$ +aN4:t&&Z9$_oL!Qj6lU8q"ad`qu-@%q"jpeq!R1rdEBPL`50:.rkel[fBW,,_>aK7s8E&squ-Hm +rr;lsqu$Em"Shfms8Mus%K5JOmI'N5oChY4h>dNSqYpL3rr<#trquZkq#:<nrr;utqu6Wlr;ZZn +rr2rdrW<#mq#13qqt^*grr2p(hr3n[mJm4cqYpKo!ri,qjSs`~> +j8],XrVmH.r;4(*aSGc6qZ$Qnrr)fpqu?]qrVnnRs8;corV1dc(*!u+(a=q-W#cp*(jkrUpAb0h +s8N&urr2rss8Dutr;Zfeg5;MtWLoi^Tt9UgrVlg'rVulrrVZHfs8Mus!ri/sc2R_Bq#:<l!<2ut +rr*/lfuLtK`PKIj`W*k)`lQHYk4/9FrVZWnrr)fnr;-?jrqZ$Dg<ds]`l5g3`Poj:bLl1Uqtg<k +s8;irs3L]?s8N#rrttY5s82]nrV6?jr;,<YV5^DnW2?JcSZM5XrrrB!rVlirrr)ir"T/2urqucq +#lFW$qu-Qlrr2os!ri/soD\[frr2rt%fZM+rV>obU8"6mq#(-gqZ$Tpk5Tr~> +h#CRTp>^U/IC-r;ai_H7_8aaGc-"#C`lcQM_nX(/]#qn/dF$KR&.09j+rM/;d"_T*)@g]CfYY\Q +`m;lOb/hZDaN2BCai;?>\"m&<AS57UDJFd2`Q$'Da2@nq"NJO&aO1"2"Nng,`l?EIs2tA_rl4rY +rlY5]s2mOH`l?*DcdpCTZF.?Z]YD7s]t1Y\[C3W`bL4tneBuXjdF-ImeC2t$gt0lj^:q7k]Y1tj +]stJTYdqg%ccl@1s2b2Zr5\lXdE):+s2b/]:!Cc(b07rG^Vn76aj85Qaht`uR;cG4;HR%-AS#Cm +[)p;/`lH-9_oU'Hc-",L`6?NOaiMKHaiM`C`6cWMaMu0<aN_uRb/hZHb08*,b5]I"bfIW8_8XL> +bL"AO^TV*F<EbC;pAb*gp@eIDs*t~> +lMpn`!rW&srVm!!p\XshrrVW@iVid.rVlirr;?TlrqcQmp&=jgs7lWmr;Q`prVuii\0NLE+<hmT +@jiND-<U0CrVlfr$iKntqu$Kor;6Kgp&4n#bO=uep$:c+jT#8Zqu$HmrrE&rs8W)tr;Zcrs3^i@ +rt58-rVuosqu-QorVcQdp;b1krkf/`a2c$4`Q$*Yp\Xmdrr2rqs82Wir;.''qZ$EMahkj.^V7V+ +_7n:[rqlrurqucqrr)iur;HZ>rW)llrW2rrrr2utrqufqr;R/siTfjplLOT>o%r:'s8W#orri8p +p\4L]s!dsIqu6Wpqu?ZprVZWorqufos7ZHlpAapcrqu`or;Zfpr;Q`rrqu]kqu7/Nm,mL-s8W)m +s8Muoqu5[VJ,~> +nc/Re!r`,tqZ$Tp49,9Zs7lHccDn;Ds8;oqs8W)qqu?Qnr;Q`ks82irqZ$Tos8W&rs8DW!+<qU: +(D\)t+rhOF<;?=frqZTorr2p/rVHQom.cU;TU_pPSZK-iqYpKtrr)fps8)`os3:QBrVZX@s8;]i +s8W)qqu?Zos8DcfaiDB=_84%/`koX9bgPVMrVZWlrVlcqq>U<l'E7h,pYjB:`lH*<ai_N9cfb9+ +rqHHmr;ZfArW)uorWW?$rVc`prr3o9r;ZfprqG0ZY,S:tWMZDdT!%PYr;$6irr2oq!<2rs!<2uq +"9&6!rVlftr;Zcq'E.q1rqufns7ZHkp&Fd`rqlWlr;?Torr<!7qu?Wnq>9EOTTuG#pAFpes8W)t +s8Muok5Tr~> +k5YGZs8QF(qu?]lp?JP]?EM5kccO2J_SX:;aj8/ScGRlHaiM*0^;7e1a2cBHacHZB(*OtC*E3^] +#7EQFeBZ4Wa2uKKbf\#G`Q$!Da2H0@Z+X.L?Wq/TAp8a@`Q$!AaN4>"rQ+r[c,^%1bfn5Lrl$>+ +bK7iJcHXGLaN_fHbKJ;bZamca_SX70_S!=cZE_6sf[eU%ccjJOb4EjWbobKc_R-_\]Y;(o^U:2U +bL=_^d*KkS`l5s>c-42GaMu<B$-L?3aNDTD`lQ7"areaJ`koX+U3pNV=BSm5=^PKW\]Dk1_SsL6 +aND`Nb/jS%s2b5_,07d<_oKa6aiMQB`5Td<aNr&W_TL0Ef#u7\bKeGVa2H'Arl,Ynb0%cK`l>a+ +WEW7i@%HH[s8Mlhr;QfnrTF32~> +lMgk`rqlcqrVlutqtL'grt3i3oDejhrVuipq>^Kls7ZKirVlllrr<#ts8W,trr4)8e0Q1a*@E$T +,9S1,qu$Bkrr<#tr;6<frr<#tr;-6frs6j6mIBr7n*/[-rr`)lq>UBn_Z'B2!<)os*<,m8s8W&t +rVZ34`PTI,_oKa3]Z%k8i:?dBqY^3hs8;]lr;7T7s8Mliq=NO``Orat`l,m?i:d*ErVQHks8Dil +rVli5rr<#urr)`prVZ[(rV#L7kj[p/r:BI4iVicWqYpHn"TJ2jp\Fae,6%Q@q>L?hs8;lrr:^!_ +r:BX-f>jDTNGWM's8Dutq>UEorVlip!<)fp$KpRBkLon8qtpBkrqc]pjSs`~> +nc/XgrVZ`qqYpZrrr<#tq\]+iXf9\CrqlWnrr2`ns82iis8)cps8Vljs8W&srtP4U+;c.5*>o_7 +)BDNHqYU9ks8W)rs8N!1s8N#trV#T?US+?YRAR!bo(i7`rrW2tr5&C4rVQR#r;HZqrqucqs8Drs +(\?+q`59C0a2Pm.`Q$9bpAY*irr2lqrquflrqcX8rVHBiqW,rG_S=%0_o'OPpAFderql`qrquZl +s8Tn6s8DusrVmo:s8Mrrs7>0ZVlHnoUT:2hS?hSZqu?Zqrr)cmrr)isrr2g?rVlfrqYgHhrqlZn +qt9d[qXO1#e]!rJMJ?nrs8;lrqZ$QnrVlis%fQG*rqlWfaJ#8uU#>bBrVm$"s8W&qk5Tr~> +kPtMZ>Q=[!qu$HlnA]ZUI(7;Abf[oD_p-BDbJM]MdE^"a^W+C4_8XR?aiDHDb/^Rj&0i/@*Z>e& +#qsiVbK@oJaiMQIbf[rE`Q6-DaO.u=Y?,:??"I>\Fa1[?aSj8sa99Z0bfIg'`W*q+b0SAWaN2QJ +aj/2]cFC6l]tq_/_n<Ij\@]c.dEThXbg"AS`l#^8b5'-U`ZN7?`llrcb.50n[CsDj^:V;2f$Mdc +_T9a8_o9[<ai;0<qo\r[+NMUD`Q?9:VfuHS?rL$0=_(le]>he1_oBd?b08)PaN"4us2ZD,aMPg0 +a3ViRc-Ob]a3DiUb0[)iSp#Nt8OUYNd*TtM_8c>o'$&,5`kfL(LJplBAAn'<s82Wkrr3&uqYfUW +J,~> +lMgk`rqlcqrVlotp\k*njOiSns%34ds8Duss7u]ks7uQls7QBkqY^?ls8W)srVu`hs8CYX,U=NL +,TnE`h#%'Krr2rsrr)cms8Mrorr2fprVuoCiofe"m-*NdrVlusq>:0js2+d2s8;j2s8N#ms8)KM +a2Gp4`5TX2_T'^Mli$_\"oeGsr;?Q`rrE&tru:t9rV5R0c,[c=_o9dIl1k)Ps8Dusrr)cps89_4 +s8W,urVZ]qs8Mus')L\No'l/Ao'bo!dJs7As8;cnrr3)uqt^-es!%I?s8VWbjO)5PPalW*@j`cS +.Np8i.OH>^HiO!Arr)irs8DrsquZltrVZ[#iooO\o`+pgrr)utr;>XUJ,~> +n,NFe!WE#nruqCAs8;orqY.:j`;'?3rVHQns8N&ps82ilqYpNerr;lorVmZ4rVccnq#C9D=rn\%% +ilQ3-JA4mrVlcq"9/?#rr2rtrXo,/qXrp8U8"?TU84ckq=sjdrr3'!rVaS3!<)Tirr3r5s8;WO` +l,d2`5T[3_oKsSlh^SVqYgBlrr<#trp]jdrqud+r;#O0bf.E6^;7k<lMCDTrri?"s8Vr3rr;rsr +ql^0rVQQnrV,*XWi`(jW2?AgUoF4jnc&Ojrr)cnrVuosrr!u=r;Zfcp>O9<VN7'XA6pH,+XA!P+ +s\9N)gD8VrVulsqu6Wq%fZM)s8DfomB*1TSAk@#qZ$QokPp&~> +kl:\]7/Qr]s8Digs8VuYIp[W1_TC'DaMc9Gb/)'3aMZ0If>c%V_84+1aihoOaiVE:d*T3e%MKTd +'b1Z\\C/[GaMu9?`l7qu$c^9/bfn8T_nE-UAH#p@@qT_'_o'L8rQ;mr!m8U*rPeiYrlY8^&')Z. +^sC9Qa0N4h^V[n&\GilC`6m>kbfRoE`lQ=%bk9-UbTP!Kb0/#RcI'VF\@B2c_SX+(bL4PSbf@fE +`Pf[9ccXDIaSj9[aT'@!a2Z-@aM4<hA7AS;>$GBHA8Ap!]$&19b5TU7b/hTB`Pop>b0%`Jd`0bQ +ZET=6JQ#<7%MKQo%2KWn&e#"OgsF6a_SaCmaT'E]a:Z>1_nX-l@8fp)RH*o=s8Dflrr2usk5Tr~> +l2Lb_rqlcqrr3W-s8N&umbR")s82irqu6Wms8;lr"T7Y*gA(XH!<2lo!<2uts8EE&pMD)u/K5ra +e+s%?rW)orrr`8tqu6Nn#h\;,n+5i.kMQ7<!<2uq!ri6"_>a60)#jI2rr;uos8Vf8^<X[7`5T[3 +_U%-)p\t!grVl9c"oJ/nrr;usrtbM#hpBHba25p7cLV#1qYpHns8;fps2"^7s8W)squHcrrqud" +r9EG8o^DeN!pRqdrr3)uq>:0irrN,squ.c=p](7o-RU5k-RU)[-mKfV*?l[G+XA0Z*2`T1r;Z`q +s8DrrquQiqqu6cQl07.&s8W#Xs*t~> +mf37bqZ$Tp')_e-rV4X4Z0hSds8Vuqs82iorr30"lttDJrr)lor;cirs8W'*q=SJD*%)IC-.)Dc +rquforr<#ur<<5up"c+/rhp*qVQmQ'q#10jrr9G+"98AurVlg4rVuokb.Pp7_8O=3_o0mZlhLJZ +qY0jcr;lotrr2rrs8E&trqlZlr;QZorYkb7s8Vl\gWd^U_nO++ch%25rVlfrs8Dlor5&C4rVulp +rr`9!rVZZl&,G.oVPpDfVl$MqSA+OgrVlg#rr)cnrVlfrrVdl<p](7k+sJ-U+<VU?+WM=:()n2+ +)BB\>(8CU%rVu`ns8NT,s82irqu?TKUS=HYf_tXG!<2-\J,~> +lMpn_rql`os8O;=rVcT\Y%2.Ibeq]Oa25g9d)O)H`Q#PYZI7CUc,[`BaiXP*'?\GAbfJ#QcUe3I +)[-TVYL(_Ab5B9Y`>?P8b08,Tcc<esA7T=bB4GXsH+Uc.`lS/%^<$8mrQ$A1aMu0<a2Q!Ae'bJ& +`l#a5_nEI\[DBu9f[nEg`Pf[3`Q$!Abg"B1aSX-Ybl>p&bK.`F`l6!Ccd0eO]Y)"r]tUVPbL$70 +#K=a'_oU3Nb/26ub5KC"aiMNC`Pfa7^7TRT?!165?=RGDHaUf6aN2O'bl>fcaSs3ZaT'C*c,J/f +2%1!.)&<u"%Mofj'+bll#nRg`)@2&CaMZ0=`r='Zb5]Nr`lZ->aMGj0PZUmfBs$b!s8Vrlir=N~> +nc/Xgqu?]qrqufqqu6uPht@$Jq#C9jrr2p+rVlNcs)B>6M"(<<qYpL0rVZWorr)ijp](9gqOJoS +.kB6Js8Voorr3*"r;?Qmrs6d;o^_>8lfId<rs8K!r;Q`rrqu]1rql`qrW)iprt>2*rVlNM`5p-8 +`5TU2`Qd3+q>UEoqZ-Wis8N!&s8N&ts8N&tqYpWpqYpKo)#aL7rqZ$De&08F`l#mWqu6Kgr;Zco +rr9h6s8W,urVQ`oqYg9j')UbRo(2MGn*B2aiW&rWq"ajer;S)Br;6Bhr;HTopVn^),p"$G-QaZS ++=8Qb,V;c!,p4]jq>UEmrVccrrr;ltqZ$Kjrrh'>kN(Irrr`2rr;PjYJ,~> +mJm1bp\u95rVQ,^Wm1PCpAb-lrr;utrr;`fs)&u*KC&C/qu6U2rVZWorr)ijp](9gq3rNG-RdL> +rr;uprrE#prr;p5rqZ#CVPL,aU8b??p\b'js8W)srr2rt_YsQ8rVliqs8E#qrr2utrr3Z-k/>Ba +]>;D$_oBsWmeZq_r;-<is8Murr;Z]qrr)j#rr;utrr2fn+9235rVuosr;Q]oq![:l_SsF4`5q!< +s8Mrps8Mrps2"^7rVulqrso&,rVuoqr;QWlgp<rXV>d@rW3)`)p\b!i!<2uq!WE#pru_7=s7O8W +)'9Y0'd+;6',_o=+<Dq%=rnM+.eiuCrVcWms8N]0s8DrsrVZTl[%s._Wp]c`ro!g,~> +nc/OcqYL9kr;SbUo$VPhKuVEWbfn2E`5p3B`P'.>9*c)Ie()XX`6-9FaN;WJa2l*5bgOMQEWcLR +$*hn)cH=/Hrl#eq`5BL4b0A8Yc-4/==D_\]?>+7uO1E!A_oVi"rl>)Z_T2l"`Poj<rQ65$a2u?= +`5g*G_5b,e^rXU3]<noVaO&AbccXARc,dd$_Ze$!b08#IrkncTs2P)[r5p2,e'ZFbd*'GIaNMiP +ahkEe]Y:t_Y//T6ai23=aNDcSb/27"b597!a2Z0AaiDB@`5.s_?sd,@=]JO1=FA$.`lQ<FrlbDc +aSs3Za<SjK`Q-?LU(.A@%1Ngd'H7Vt&/#Na'f\r('cIV.`l,p>aN"+u'ZS85`Q6$:^Un>c9N#ZN +n,<:[pAO%OJ,~> +o)Agkr;?QkrrE&sr;ZcprsntZh>dNKs8Vims8Vurq>UBubU4JR+=j)`r;Q`rrWE3"r;$?l$hjVq +s6cquo_AIdpA4dfrrN,srr2os&(L";p%.G.j8/fUr;-3ar;Q]urqlTj_Z'H4s8El5rr<#ts7u3) +`ll*4bJD*5ce[m[s8W)trr3)tp%eU_s7QBhs8W$;rr)fqs8N&urr)TTh8mgY_9'dMq>L<jr;Zfp +s2"^7s8W)squZior;?R0rr<#ski(q&nFZ>6m*Y>&s82Zir;QZp,l[]:q>:*gs8VopO<l8'.4->^ +)^g?/[*S72q9(!%-:mt4s8)Zns8N#q!ri/qr;QrpjQH$hl2:Par;-9eroa<3~> +mJm4cpAYO!r:.q)[IF+hs8Vrprt#&-qZ$TpaWhZ>)'tdKr;?Qos8N&u!WDinrsSQ#q>]f[[ds.l +s7Z<hrr2rtrr!?)q!aZFTVSHZTrQK;rr2lrs8Dusrr9n8!<<#ss8Dus!<)iq'DqFEaNV?4ahP^0 +cJ@d[s8W#nrr2p#rVuosrVcZorqQNjrX/W(rr2lnr;Q`orr2p1qX3=bbf%?<a4U:gs8;fps8;o5 +rr;rsrqud5rqufrrr2rrrV56YTVJK^Wi`#"T#U3rrr2p#rqu]krVQU9rr<#ns,A0G,9n9O(D@m> +Qa+d%mIeF<'-BX;s8Vrlrr)j!rqufrrqm&YW1'NS_#!s,i;\<~> +nGiLds82fls8)fpr;SbUqV@QHDm7C+cHO8N`5BL8_9'sIV@!\A&Jp&Kb/V`PbK@oJ`l,d@b/qHE +^s0lSPKV5%d)*fBrl+oW"NA3p`le;,&^82+@VK@_@UNhiQG:5Ma2c:#b5]Q_`koeG`l5p:aND`N +b/D<?a3)ZLaf2S[\AHP0^pq%n`m)oWbKA#Qc,RT;a2S%trl>5^_nj7.rl+oWqoBo&e'ugjb/VKE +_oBjCcHX5?[D9A_]!Jrsda#qTccsPS_8uZ!qoBc!a2Z6CaMu9>`Oqdb>Zt?.;cch/?&Z80`Q--D +rlch6aMu6@aNDN>b0.l[D?paf(DR\t&05k?NiUINgpIb+'dq/D`lQHH`qmahb/M9=a2Pp0RpSc_ +;Ng&4rV$$Gs*t~> +o)Agkr;?QkrrE&qquHNkru^@Wo`+sjs8VomrVHKmqZ$Ne:+7V9+=A:%a8Pf2s8W)t!r`/lrr3,u +s7lWfrr3&tq>^?krVlrur;QZp#h8)0p$VA>iq36M"SME]q>C6l"9/2nr5/I3s8;j.r;$6iqW?8F +a1oL2^rFCIl1k8X%fZD+s8N#trVcWhq>:*hqZ$Hlqu6cop\OgerrE#srtG;(p@e@FbeD*=`5]sc +rVlWmrqaG0s8W,us8;oo!;uinrr!W3s82irqr[)6oCDPDl07$es8W)qq>:-j,l[]:q>:*hqtg<h +rg]FFZ(NBi,oQ%Cr;ZHiqJ.0"*5;:Is8DrsrVlipr;HWp#6+YnjQYserVm'#qtg0eroa<3~> +mJd1cpAZ<3rU\[=UYl(KqZ$Tns8W&rs8)cno1C8P)AjS86cAlrqu$Hqrr;ZjrsAT&q#C!cs8Mrl +qu6Zqrr;usrr!?'nXZ/AV4aT`WQFr0s8Dors8Dusrr9n8!<;los8Nu7rr;lZe&BDD_Ss:-`7aDN +s8MupqY^6grql]qrr2lnrr2rqrr2lqrr)itrV6Bl!WE#srt+PC^W+@4`6%BGs82irqu?]1rql`q +rr)d.s8)coh6`uVWMlhsUSt'(p\b!hrr`5tqu$<j+TD9<qu)tMQ*$Mu+<D0XpAFs`s7g1D*u;Ka +rVufprVlTls8;uurr2p&_kETpVrRLIi;\<~> +n,NFd!;lcls8)fpr;SbUrT:Lr<hRRYb0e>Ka2c-=cc",SbV'PH(`""u.\kG8bKe5L`Pod>^WamG +`QZ9LbL4ncb/;KDrl#eqaN;K?`Q69Jc-"#;ARf4^?=@YjPearO_8Z>ps2b5[_T3tA`Poj<b08#L +aMu->d*]b?\&,bm_n3Lf^W4aNcHOMSa2>am^^J-&bg4\ac-"#C`PqbpqT&ZVrl?/$aN;QC^rOO< +bKJ8^fZ(5#^;Rap[*7.Nb0S5H`Q#L1!QiF\`u;q<_8aBdF^A6L:K(A"A7^;)_SjI:b08)PaSj+& +aMkp+^W+CCFEVnlLCFq3$Id/;c,%cT:^\'FR`WCebg=N1`rF-Zao9<iaN)99HVd%(CqSp&qYfFR +J,~> +o)Agkr;?QjrrE&sr;Q[!s4Z2is7ZHl/H#PCq>L3es82inXX##2,9J*X-"lZ?s8W)ss8Vurq>:3h +s8W&trVcWnrqlWmrr;oqrr38lhXpL4m-<^#rr3/ur:]g\rr2p"rqZBf_Z'N6rVdN.rVl`ilI!/[ +_SjF4_p%$4r;Z`oqu?]q#lX\qq"ORZqu6Tprr2fms8N#t"oeGurr)fortbV4qt^$\p@nLMcGRT? +`m"&Sp\k'es2"^7s8W)ur;ZX1q>1'grr2rtqu?Nks8D*AnF>o9p?;%krr3*!q"Xdcs!I[@q>C0i +rVufqqu?Khq#,=X+YHdop\b'hb9ePX;Y^7fs8Mrrs8Drrr!rT's8Drqs7u]pk3_Bnhu<WYr;6<f +roX62~> +i;Y_,pSOIkqu6Tkqt^9ks8W)ps8)`jW?3#q*#KV=+(OX0rr;uss8W#sq>:3hs8W#sr;HNms8;iq +!<2orrr*H,qtI^iTV/-XUoD?%qZ$Hkrri?"rVlfqs1A7Js8N&urqPa*]#2A&`l5m?i:m3MrVQQm +rVlKiqYpBlr;QZp"TJ>us8N#r!<2lq%dhTZ_o'F9oDeUcs82ir^Ae*2!<2uts8N&u'Dhb-qYf<X +VQ-PhVQ?GmPk4\Irr2p"rVQNlq>VN7s82ikq=aZ))]L/$rV6?kr5g*)(es`'qu?WlrVlZn&cMb0 +rVlcqrr)MpVOX<Wo(`1Bs*t~> +mf*Liqtg0dqu-Bk2XfID;/<qkc,drBaMQ*Dai;TJdaO-_$kO0e',D*Nb0JAZaMc*<_p?BFcc=5P +bgO_Ya32K?rl#ksaN;WI`l?*Bbf[o=JmDnpAS#IjO1N9L_90g<rQ>/]s2Mmrs2P)[s2lk5`l6!B +cdL"IXMMop_7d4_^sUQUbK.iNb/VK>^V@Y(`6?QTdETbO_oBdnb5]Q_`rF!c_o9U3_o9[:aN)EE +rQGhuf[@OJ_7mFgfA+Zra1oX6]#Z)8a2uHEaN;K=b/hQAUN'F::ek#!=CtF<]thS+b0%rNb/jS% +,07d?^;n.7ajA8Yd+_Y.%37UZ^Ve4:UC@nI3RGp`a3DlOr5S`W&]W#;a2l<D`kelh:.SN0eEZkg +s*t~> +o)Agkr;?Qjrseu+rr)cprVuoVhZ*WHr;Ru=q"Xdds8W)sqtZ0s,UXZT.Nfstr:g0ir;Z`qqZ$Qn +s82Bds83B,q>^Kos7k7Ap[[e3kN2[B"TJ>rr;QZp"8r&nr;-Bts7cKlqYpNndJj+E(&Rt/qu?Wg +rp@_@a2Ym1`Pp$qrVlfors&K"pA=jdqYpBpqYC!brr;rnrV-`rq>0sdrr<#ts8W)t)?'F0qtp<j +s8Mimq>9a9`P]g7fB2i-s7QBjrVum!rr)fCrWiK&qZ$Tms8W&srVZ]mr;70+s8N#qrr<#Ukk"?5 +oC25<d/O%IqsaR]rr2utrquQj(B=C4odqF0.%C8:qYt4N+XNubs8;oqrr;rrp\Y$err35^lL!^' +s8Vrpq;qX,~> +m/R+b('":5s8N&trVufmfqbhCs82cmr;Q]ps8W'=s8Mupq=f^h+!DI:+W)8Zq=X[crVuirqZ$Qn +s82]mr;Z`prr3W*s8Vofb*&ZtUSslf\G,murVlfr!<2ur!<2rsqYga"p\k-grr;rCrr<!5qu6Wp +s8VopmDZcY`PB=1a3OP]rr2io#6+Z%s8W)squ6fus8N&srr2Kg!<2ut"8r/srr)j6rVuoro@Usq +`P9sbq#CBis8Muqs8W)srR(TLs8Mlps82irrVlHh)ZB[5r;P`_WN)bgWi)PjR.U1Os8N&trVZWn +rr;cm)?9[4ngGOp,+&</q>OnA)'5LMs8Durs8N#hrsJ](pu80ETV0-trVlfsqrRj.~> +mf*:crVQBi2".PXBs#V!b/hZC_8FODc-4GXcd:%dC'G%Z&/6B)$ZFV?bf[lEa3;WNbfS,Mbfn5P +aN4;!)T^(Dbf\&O`6HQA]T-$+@ps%\Ee2'G`l?*@qo\r[s2OlU#LC6,bf%TGa3VgBc,mrDaMl9E +b1Y7M[)C/,^V$hTda657aq2S1`lZ9@aN;QE`l5p;a3)L#b:q&]b/_K@`PfX,^;%P(b0.rObK7iH +a2>d<cdgL^\%KSf`lZTVah5U3a2c<DaN)?Ka9To0`6$0@bfTFss2Gnob0%iGU2!q;<)d.,<ao:D +]"Q/#cH45OouR0U(sUCVdh3-!'RJBXak05r()2SSbJV?AccGt&qoJf[s2PDRQrm6a?'F7Drr3#q +qr[p/~> +o)Agkr;?Qjrri<"rr;usrrhE<p&Fd`rri>rp\Omgru1k6qtf_r,p4?V+<r9WZhO:qqu?Nmr;-Hl +s76."r:^-is7cQCiq;s5mH*Quo`#'nr;6BhqYgKkrr3)sr;ZfErYbb8s8W&trqlTjr9;>CcbIH: +`PCL/q"t'ir;T%]r;$0`qu?Zgq"jmaqt^$Zp[dtGnF,l9mI'H5nac5Brr;uoq>0p^rVHEjrVQWp +qYC*fn`/$4b/hU&oCW(\rr3-#rVc`qdJa.Brr3)ps8;iorr)cpqu$BlrYGJ4s8)cqqr$].o^;;G +mHW:&s8DrbrVcchrYb\7rqjee,9eVbs8((e,pY)6r;-Bls8)cqrVlTi!<2rs$M3$FkiMjErqQBh +jo9i~> +m/R+bs8W,urr3H+rr),_U"9)8s8Dlorr)lsrr2p9rVZQglt@O\)&a;2,93r\q#C6kqZ$Kis8Dup +rr2rorXer+rr)NiXJM_bTr4`m^[h:$rqZKmrr)lnrW)forr`,qs8ULG(B+12s8N&urr2rsl,^cc +]u7h/_rgmnrVlco!<2ip!r2Zlm/I(brr3#ur;?R.rr;olr;Z`os8V]Ncb7B<_uB<&r;Qp!rVc`q +dJa.Brr3)ps8;iorq69lrVQQn&c(@fV5L8dVl65bU@\3\s7cQlrVZWprVlfqru(h9rV=DY*?6BM +rV4SW*?6HqqtpBms8)`oo`#I$s8;oga-i`lWnR@LrVuiXs*t~> +mJd:eqtp?hs8VsNp=+1iQG(#WaN2B=^Ve=DbKA#Oc-+8ObJQgU%Mg6.'G(A/cH=PTbJqoM`m2WK +b0'\(rl4uZ!6Y8a&BE&=`k''*An>:T@V9k?]Z'lkq9&`Ys2OlU#K4m0ai)3@b0e9Hb/qiL`Q-'= +ajAYa[_0i$b/:lp`R2cIrlG)]s2b5^4j(smdE]YH_o9[?d+-b+iS`VMhV[/Bf[eU&dE]nR_Sa:1 +aiqrRaiDE=^;%b/b0JG\ahkR)]Wg;7_Tg+"aTT]*a2lBMa9TZ,ccO#I`lIYk)TK_4b0A&M]:EYB +>[16/=&`gEZamrs^<FaBr5])bbg"ASaN"4u(XC@UW"BUQ'!g-;YmhWj):HdH`5^$>aSNpRaT'Bi +c,IK$J59*>E45E<s8VrrrTF32~> +o)Agkr;?QkrrW/srqud!p".ptr;-Eur;$-brVlfrrr*`6p]&E7.iBWY)^le#de`qBp\t3mrqZTa +rr<!0rVuoneEci#ki1[ds8W)or;$Bmrr2ijrW`Dss8W)qpsK'Vs8Drsrr2lnr:]?t^;S"/_Saa[ +q>L?mrqud#rqQ?fq=OL]ruV+4nE]2qeBlFY_8!^t^r=XNh;RG\o(i1Zq>1!erVHO1rqu`nrqu$, +^WaX;l21>Trr<#trVccrdJaCNp\amfrr)lorqQC!rr;rss7Z<hs8)$FrppKio^LYms8W&squ6Nn +p\t3j(&7h,OW5_n<VH?".46+#s7ZKmr;$B_rW3&rrr3,Yl0dTrrr3&qs8D*[J,~> +lMpk_!<)os%K?>$c_IZCr;ZcprVlfgrt5#)a\F,o*#oY:)Fi'Jr;ZNjrr3#qs7?6irVca-qq%4. +USOW\YeKo1rr<#sr;QQor;HWorr;cm#64Gts8Mojd/F(Crr)j+rr;cWbeD!4_SO.<k5>5Ys8N#r +s8E'!qu6TrqY^*f%.`lQkMtOZhrEqip\k*k!<2cn#QF]$s8;Wirr2p1rTMM<aMQ!_rVlirs8W)s +rVuoFrW`Dsr;-HmrVliqrqQNnrY,/.s8N&urS"f]WMZMjVkolfo_ndh!<2rqrr2oqs8N#t(]OC. +s7qWj+WO;Kpg#'b'Ti@gs8W&os82fos8)^)qZ$KVWh#]R\bZ1&rVufXs*t~> +mJd7dqu-El1B%%=ii6^2aMu09`l?!8_8X[D`5':0a2Z*;ahc8t2&?`C)@dMf/[!OKd`'ARai;0; +prNKXrlkDe&C8VC`kIgC?X[;I@W[@CaN4/!rQ,#YprEZ__9C'C`PU'E!Qr[db5]Hpa2u]Ubdt0t +aMkj%]Z&:Dbf7`FrlRjS`l5g8cd0h]da#tTbKnetkjn66mciimiSNJOl0e-6o]t)Td*L"_bfn2N +`l?0Fai;TLaiViWb.+Xg[Bn$+bf\#KaiMNCai`#P$-C$'`6ZNFai;?na;<"?`l#p@_o9a8STeOL +<`<%%@U!fW]>F?a+Ni$XccjJL_nj+*`7WX]";;D6fA0%9*t`qY`6--=_92YrrPnlYrQ5Jj`5]Hh +BMV<)M!G!>!rM`jkPp&~> +nc/Xgqu6fur;HWorVm#Hd/X.?qu6fur;6BhrVlfr'Dhb)rV;d6+s\!R-RU3\mIUAXoD\aiqXXXc +rt5)*s8LX?p[Ie9ioU4?rV?6cqYpQprquNi"TSDrs7lTndJa7JrVccqr=]#*iQ8jTaLoO3b4GQ- +s7cQmrqudGrr;onrr)ZgpA=IGg;gIhP*1iaMM[4KN/ijRLQ.UpZ-qLjlL"-7q"F^`rt,//qYgHj +ld<hl`5DBIq"jsgrW<-!rR(TLrVuoqs7cQnqu6Bg'`S.2s8Miiqu?]ojlQ+)m.L&?g>i/3!<2lq +q#2'-s8Vlipfnsc,E0Yl)Bp["qu?Wis8VTf$30u&qZ$NJnE8m3rrE#Ys*t~> +li.[us8W&srr)fpqrsfQq>1!gqu-Nno`#U%s8)ZfP:IRl&0W/>+E$K7s8V]irrN#soDT="s7ZBd +hk[0IT;ncl^@M3rrr3#tr;QQpr;HWms7uWss8;`nq#:<@rYtn7rVulrs8DrUb.ks:]#D\6p\t0l +q#C?mrVc`ps8O8?rVuosrqufrr:K7.cG[T8^:h1m^VI_%]XthrdG"*_qu-L4s7uWns8;ckrVlis +rVliold*Se_SZ-Iqu-KmrW<-!rR(TJrVuoqs7cKlrVlTl(&n72rr<#ts8;iNZD4FrTrFreTtL!q +rrE&trVlfqrVulort5&#oiN1P*/DBU',i+]q>^Hirr;lprVuco&,cD+qtSd4V4adCqYpHnroX62~> +mJd4cqtpCMqt]mI_Ja;*`lQ<=`l?!8`Q6<H_7m\%`Q#p9^W"%5d<HK?)%IT$'+@g]b1=qQc,[l@ +`qmdVb59Bncb[N2T4;PF?"IM`K=f4BpWEHUs2OlU#L19,cGI]IcdKlPb0J/Oa2Gs?cIp1HZbaVm +_7$Z#f$)=PbK0\*/]brN`Q6-Ddacn!f%f*<gXsosbLYA"f[nd-f\"a#air2ihWEkZinDl-bJM6t +a:$,7cHa\V`5U$Ja12,V"g6S0bfIj(a9'K)a3hs7a3VrKc,%ZH`l@\ms2l2'`l5p7`6--=T5[q= +<DZn,@9e)`_8OC6qoBo&c-OYYaMl!1^;S16cI=u`&/')f'aYZod*TtQ^WOU:qoJ`Us2b/]&BVu5 +^VH74<)RPJnb`:^qYfUWJ,~> +lMpn`!WE#qrt3uAkPtP]q>UEns8Mrorr2rtrVlfr(An.3r;?8<-m]fO*%2sYTD&<[r;HWpo)AUf +#lW3>n+#u2io^4>s7lZmqu6Zqrqliss8Vln#6"T$qu?HfdJas^rVlfmr;HKUaMYs2`l,[>s7lKk +rVufos8Drrrs\l(qXrpj[%3)+J:N4LHS^%rI!p6fJqJ]+It<<5T"3G;o(E%\qYg?ep\jses8W)u +s82W=a2lNDoDAIcrr)irrqk+B$2ac!s8)]ks8;fdrY5D3r;6Els82irr9!>:mI'K<l.#A"s7lR0 +s7cNmq#B>"-5n:-,psRbq#CBjs82ipp\t3mqYg`ts8V0=jlPM$rrDlVs*t~> +nc/XgqYq**s8Murrq<:lc2.>;q#13is8W)nrtPD2s82]cHm0UG'GVc1,Fe?*q#13hs7ZF&rVHNk +je&HBTW+ii]_;3urVllrrVQ]prr2rjrW`?$rql`jqU,9\s8Drsrr<#pkf:TY^rOF1e,T=Ds8Dup +rr)fprr2p-rquZjs8VrXgs*dR_T0^r^GNaB_o0O0_oBd8_7mXr^<>F*s8W#sqtg<lrVliqrVuor +s8Vrlcc3uJ_tO'.s8Murs8MoCrW`9"qZ$Ejqu$KdrW)oprt,)+qqAEVX/MqkX/;H4o(i7`rr;ot +rr)cor;RQ.s8Vimi#s3W,"Wk"'7oiUs82ios8DiorVu`ns8W,t$2V0,SY*"PqYp<Ps*t~> +mf*@eqtp9j0)5)-f5ken_oC!=a2Z*9_oU!EaM>L(_o9X;a3)<@dEBk\>nRn_%M'Ed%t;gPrkniT +b5K?YaSEsh`lGfi?tinRARoS,]u.b4rQ=KJ#04m-`Qc9<d`<BMc,n&H_oU-QcF(3s]"u(b[+`mP +d`K\OaND[)aT'7McHF>Pc.Ct:gt^N0e(EL8ioK7bkiqI"k3)!nk25"LgYC`Nmd/iXdDEW9`lH9M +aN)NIa2c?Fd^-<l^TlJCc,n&IaNDTCdDuR3ai)??a2Q4"`qd^Sar/CC`P]U7bf@`=RVuP?>$"^3 +?WrDr^;It1rQ+oZ*6?.=_84%#_p-6M\c`QM&iL76")H?1b.l!7bK9_*s2b/YrQ+r[%EQH,^2[1H +=anoiqtL'Os*t~> +li.(dr;?HirrW2Ohu<WXp](6lrVQZpr;Z]o(]471pAb0fs6#7d+X.pJ+sJJBs8W)uq""F_rt!W@ +meuS=iSOV7qu-Efqu6Nn"oeGsqu$Hms8)^"rVufls8Vinci3tE'E%k*m`WMfaM5O3e+<V=q>1-k +rr2rtrr2g&q"jp^nE%NQOG82_GS>4?GB\4QEcH&;FE;SGFa&4_GCfaL%%4iemIpDOq#(!^s8N#t +')qq1rVb<caMc'orr<#rr;ZfqdJaIPq#CBns8;opr:Bn&qu?Zmrr<#tr;ZfqjQ,dtoC2>:eGT=G +rr2rtp\l!'s763iq>-U*-QFEO*%pOTr;-Hnq"Xm`rr<#srX/T#s8W&ts4$?!i;W`XrVZZXs*t~> +kl:\^$NL)(qVn3KnG`I]rr2lr!ri,rr;Zcq')V_,pAb0fro8YR)As5))]^91rVllnrVuQi%KH4r +X.c)_T;AHfnc/F`s8W)trVulqs7ZEsrVufls8Vinci3nC&c1n;^r=@0_TUO's8Vums8Doqr[n0L +s8W)prVlfpqVf3.`5KR5`P]L0`5T[4_SO(-`59=(^r+1*_o9C"^te\`qu76)s8Dutrr)lrs8CNd +`koalrr<#rs8N)tdJa@Mq#CBns8;fpp&4sgrr3`3s8W)rs8:TSVQ?\oV5U>`de!M<s8)`krtkJ1 +oDejcq3`6H'cn)*.HgU+qu?]lq#C6jrVucos8NN,s8;lWUnX?Kdej%Bjo9i~> +n,ECdrqc]orVmZ3p$^tT@:ZdecG7]KaMu-8aND`L`l.krs2Z&"`QQ9:bfdrQ`cMq0)ANnt#mZ:3 +b/VN;rPnfWr5oYnb/h]<[qfGZBO,.^F1B9+aisb,m)TFPai;9Fahc<NaT'Coa2Z-Cd*K54_o93p +\@Kl3ccO8Sb/_TE`l?*@b08&Wf%K$FgV_RtjQc.$lK@U'nF,l8nF6)?nEfE*mIKc>n_VC,eD]9< +eBQ4_beqK?aj%oIai_u^]Wo#U[c#WXai;?BaiDfM#L('2aiM`Hao06TaSj7!a32QB`5g$C`lGi] +CL(7J<E*75?'`(B`Q%kts2k>_r5ScU*PBP*b0S/RFpSlk'F=sWaO85IaN;6;d`fqXb/h[&`r4!Y +apuV9`Q5s5UKUJf?)Qi[qrRj.~> +li.(dr;?Hjrsee[f)PdLqZ$Tpqt^-er;ZTl(B=:3qu?]fqsL"&+!i$Q+"11brr)cpo)AXg!o)`" +rq-<Xjo58^rqc9brr;us!;ufm!W;rrs8)^"rVuoqrV$9cci+UXrr)i`e\T>E`Q,sKnc/I\s7lBf +s8N#tr"]#!o&dfWKn+VrF)c;FH$Xd[FEDYIrcJrsFE_tVH?sj`F`_hWK8,8]`oHIVq>:3lrr<!. +qu?W@^<+4EpAP$jrVuoErWiJuq#C-hs82cmrVlZn"TJ8rs8Mrr%/p5+n)*C!nFu;Eld5Y2rquHg +)?9X7r;Zfks(<Vu+=&=Gp&FsirV?KkrVZTlrqQL*r;$*es8;fpl0e*3nGiOdq#9IVJ,~> +nc/Xgq#C?m$1#I%g]%-Js8;iorrN,trqufpqu.?1qu?Qns7?'PQlm.a(E")8;tp:ir;-HirW)ut +rX\V(U7@pNVl$WXp\Y!jrVuiqq>^0f#Q=]&r;H?hpWrj;rt=eN^;Rk*aN3-0s8D`mp@eOcrr2rs +rr)j$j2ALC`59Cj_`>QK^qmn*`5Ta9`P]X3`5BI._Sa.%^r441_Ue/Ts8;iqrr;usrVHHlrr)ls +d(mc=fD#7Drr)lsd/F:Mq"Xmas8Vuns8Drpr;cirrtYM1rVccqq#0g/Y,A4sYFhkkQ07i=rr;rr +rr;oq(]XF5r;Zcir*^W\(EFZ-oDeagrqcZlr:BmfrVlg)qu?WmrPkb)T<e"ajSs`~> +n,ECbrqZWnrVmc4oBakk?]r(<_UHiWbfIc@`lQ<Icd0k[b5THub0S,Sa32`Bd*..Y(Ejb7%1P#7 +bfRlNqo8KR'#r#3_6\/n>[_&RCNZbq`5]s<r5e`SouIBYb/qZD^sBjCa>V&Wa3Mi@[Dg/(^pCYt +e&]PX`l?BH`P]U4aNVoXf]DDRbKeu.l0I['naZ5@lfmd)o(2PJo`"M5oCDA=oBto.lfHsMgudt_ +d`TSG`5BR8b088[cICIMWkH-icc=2La2uHMa9Ti(_TB[:cc,e$rQ+lY)9L+Ha2Q!6`5TI/\;k9/ +<`<1!AS,5P]Yhbfa9Kf.`l5s=b5TU*ccFMTcHaMa;&C#b(D0-]f#l+O^<OjHc-4DSaN47us2b5_% +F)o2`PK:(JlbKAGLc6Es*t~> +l2Lh_qYpKo%JIlrs8Vrqrql`mq>:*grrE#orYth9qu?WjoZ;2'.30WU*$lgVci*nArVQWorquZm% +fH>+s8N&urm:'*p[.8*rVm3'pA+^fs8N#qr;HKqr;Q]qs7lQtrVlirs7^T^rYPP4rqlZjiP!@Q_ +SsIFq#16js8Vrqq#C<l2>m@Hn`RNON.l\&EGf`;F`qtSH[C$`G'.nLFa&"OG'\I^H?aRUGB\.NG +_(:/b3ns#s8W)rrt##'qtg<4aiDKfp&>!jrr:@E!rTiZrr3)qs8MrnrqcWsrqu]mrr2utqu6utk +j%O#q"47AdJj1Gr;Zd!r;6Eiqu.K5q#C<js8Vo\+=8<S-e&%ls8DlqrVQWor;HWirrr>srVuorr +r38\n*]T;s8Vrnrr3#ur;?Tprq$/?~> +nc/Xgq#:a$r;>9EY42Jfs8MlmrrW2urVl`prVulsrtt_7qu?Tho>bhr,8M47'-/);bl%J<rVQTk +s8N!1s8N#rs8DlNQD:7NT;8LTq"4Rbs8Drms8Doss7uX!rVuoss7UL3j8T&X"oeK!rr2rsrW)us +rYGJ3s8N&siP*:L^r44GrVuops8W#sp\4\*i5ECG^qmq,a2l9<^V@V'`5BL2_ns7-_SQ5g0#,3= +_8=11_Sa:2]#X7=s8)cmrVulnr;Z]ns8;o:aMZ!]pAb0lrr;uts8N#trr2rt!<2urs8N&urVlis +nc&Rgqu-p"^N]\Ws7lWns7cNlr>tt<s8Dors8;lqs8Dumf!DEWUT:2gU7:ZJrVuosrqufrrr2j5 +s8)cor;Zcjjr#0X(F%6'qu?Wns8MlprUg'hrVlg)r;6Norq<(XRAJ4,p](9mnGe"~> +n,EOhqtg0drVmB%mGbNmC8nkYaNVlVbfKe&,K@mNd*p=cb/hTBa3D`Qbf[nr:^[pH)&a8/%gf5^ +cH+,HaSX!SaT'6k_n2F?A7K+VBQ:Q$^rjg?b5KEW`r3s\`lQ6Dr5],``lQ6Gb!sYSb4s$Xb500\ +b/ha&aSs0cb0A2TaMuBFaN"2"4ibX_`QQ]KYf+Z&^pUl*ccO)JcHXq\bf7Q:_oBsPiU,:<dc0Zb +oCMVJoC)/=o'Pf5n*B9,o(DVFoCV\So.0D'p%@nDlK-:7jQkI=a1T+)a2Z?Nd*BnZe#0Xk^rsmE +b/hZGaMu6@aN"5#s2G;fcdC(_b/VI"aT'9MaT'9[a8jB^a9TkM:=@D1_TMPmrQ>,](<Xh?_8F11 +`5]ETD-g1:?!V#M?*qGfrQ,#]"NA9uaNXY.)pcXPai_oSd*`LK*>&gcd`p(X_ofs@dETq[b599[ +`rF-[apu\?`PKL5`OAuE7U;bPqu6WqrVlfurVQK]s*t~> +n,NFcrVlrrq>C6l#hmu/s8W)qrr;rr0DthLr;Zfop\jsgqYgHgqtT<4:a@81,U"0N,TnLIs7l?g +s8N&ur;6Eirr2rtnGN:kmbI$so^:o(rVm$"r;$-cqu6QlqYpBl&,lP)rqcJ$>i#/Sq>UBirVQTo +s7$!ks8;`mq>($fs8Mrr%J]turS#0.`5BL6d/*V;s#pAUpAFmeqYgElq=3@=ML^>1I=$9]F)l8C +H$ajaH[9s^G^OsfH$4=VI"$KfGC+RXGBIkDFa]"Xiq)pArVmN0q#1$]s8W#H`6-3erVZQjrVc]p +rVd&us7p]Hs8Dlorr)l]rX&O'G1??as8;orrVuNhs8W)tqu6ulea)Pqn+5l8eGfJ!rr;lop%\F^ +r;Q]nr;HQiqZ$Tprq9&**@Fk\rqZTms8W#qs8;lps8Vrqs7lTmrt>5)r;Z?Hn*Jp2s8Mrns8Voi +qYgHoquH`gs*t~> +nc&UgrVm!!r;?QnrsShrV5)u@s8Vuqs8N#t-N3uDqu?]qqZ$Norr<#prV>T6:*CSr*#TJ/*ZHA7 +rqH0es8Doqqu7B0s7cQlqu?N0T;/<\TVJ[No)8RcrVucorVuiqrr;in%fcG+rVL#,h>.*Js8W&t +qu6Woo`"dg$2aMsqY^Bmrr<#srY#8+s82iQ`5TR/_TC:)rr;omrVZ[>rr)lsrr<#od)3N4^V%># +`Q#m6_o0L2_n`t#_o0C-^qdec_E#BF^;.V&^r+.._Sj=,k5PAVr;Z`ns8;cos8;ospWgLla6N^) +rr;rqs8W)ts8W)tr;ZM0[f61%rr3#urVlfbs8Dp)s8MmmER4@Rs8)]nrVccqrVuZlrr;uss839! +f<;?PXei%nWgWGWquQflqu?Wos8W,ts8Nu8r:<Ps(aDuOrV?Kls8VunrqlZms8Vurs8Doss8Dou +rVZWnrt>4NTq7jNmJR"arVulss82forUBi;~> +mJfEJqYL0js8DQPb\q!^[)0f$b0J5RaN)3;`l63Jai2B?b/)$<_9:*?D`8:E)&a;(&J>?U5h3om +c-=;MaMu7!`>HV9b/)BFaN)#I?=7;R?tOP_^!+aEb/qZoa99N%`lcO(aq)V<_8XLE9LZG3d)sYX +aNOJ'!R/^baT'Btbf\/Pb/hZD`l5d7c-kCq_o'^B`l7nrJ'5^S`m_W._oTj3\[9l1aiDBCcHt"f +d*0GH`Pp0[mbm$[lLOK3mHa31mHNs(m-3g-o&/<emdKT0me$5Gp@e7SoC;JHo'u&'bi%^?bJ:p2 +_o9I3dEp"Xc-Nc&^Uhe>aN;THa2>g7`l5s?aM#gC:n?Rpb/M9<aNDTC`UUtJ`=9o2bf[rHe21LB +c,\5Pqo\r[rPeu]b08)PrQ+rWs2>km^q#eF>u>'7>>e^+\]E":aMH<L`P][7b5TU2c-+,Hb/q]J +dP_XN(d-'fa3VlLbJhQJc-OSUbJMKHbf\#J`lS,$(s'_9`Q#`N=\MLt_t3p.r;-9is8Dfdo_n=[ +J,~> +nG`Rhqu$Em#QFPms8V-;oDS\=r;Q`qqt^6krVuooqZ$TgrV?3bq=M(0,p=?N+!qpI.j?B?VtU/h +s7uEgrrW,qr;HWprrDimrs.';p$:i0jSSrV"o\H!qY:!Xrql`qr;Zd(qRh>Wm/?qYrVl]jrr<#g +rX8c$rr1hjiVWQNrr2lr')qq+s5_A@_Sj@2`r#B-r;ZfrrqQs!q#16fpA=7!W/#a!HN/@VG'%\F +H$a[UFD>,^;+X5K:KCb3CN"9=I"-KhH$=:KG&h\NIu:,;nF?PYr;Zfnp@eC^s8V`@_SO=gr;QQi +s8Dp$s7uCn?'YHfrr)l]rW`46[U0"6qYL6drr<#srr;lrrqud'q!6o3kjn98p#O[%rrrDpoD&4\ +rVlfo!r`&orr322*%2gJ])2L,!rVomr;Qs!q"t*eq>($hrrE&tqu?Zuf'Mkhrr33#rVuljp\Xph +s8;orp&BO~> +m/IIlqu$Hnr;ZZ/UqZO$s"40Js8Mrms8W)us8)]os7lWlqYpBb[:pj,)]0>2&euZ3,>Y--rr)lm +q#C<lqu7B0s8VlirVGrLR\ugLW3"M>r;ZfrrVuKgrr;los8;os$iIVa:[J,]qZ$Tps82fqr;uuu +s7lTkrs\`$qqc)Ks8N#ts8N#sr=/f(s5qSE_Sa:1aSkl5rqd!"rr<#tqYgHkrr4\4cbI64_S*\" +^r+%,`l5^)]X=]-R@K\3S"H[g]tD"k_8O4+_83n&aMl0<_8=XXrVlolqY^@6r;ZNWcbRB=qZ$Tn +s8W)urr2rtrr2rooi>.Us8N#t"9/8trr2p+rr;utrr;utrr;utrr2rrrX&W(ph$a4rVuZmqu-Qo +rVuiq!<)iprr<#t'Dqb-maA)=UT:AnWhQE]p](6krVZ]orr)j(rr<#tZPb#*)S,_Drseo&qZ$To +s8W&nr;ZTgq>UBl!<2ut#lO4hTqA"'p\t0l!<)os"9/5rrpg#=~> +mJf9Hqtg9ks8)9AO(EXE`6--?b0.lD_8XF4ai_QAbg4,I`P]g?acT4+%h]Tp+qkS-$k4tCbL"G[ +_nXCoaT'6u`Q#p=c-F2Dai(Sj=CkcCC2]NO`QlcQbK7`oa99N%`lcO(aq)S5aN2PpEC@mnccF;R +a3+D&rlPDgb/hTBaSO$jaMu6=_ns1;gr2gd_T^9E`Vmeja3M]R_7.(qai1fpf#?"R`l?'?cI(%_ +bK7]Fh;[#:i9p+,o(),0lK[g,lK7?thq-Q1^:2)-eD'*OnFQ;IqtTdQmd'H?q=sF;dFHh;f$_UO +]Y__3bg+/Mai_6&\[U&4cH=PV`P_\o1WISY_naS`7ss.:_nj@8bf[oB`l?*>aMu<@aMu<@aMu<@ +_o'R<bf[oGdS6N.g<dmab5KNlb/hZD`Poj<b08)PqT/]V)TBP/^p/u.@TH]4;HHt9]uA:<a3)QD +_o9X<rlcP.aiMK@a2lPj"re0]S'9%!bf\#Ibg4MZd`9/@b/;3@b5KEZaq2Y6`lQ-.@SfZrRH4>H +rqcHirrW&go^Mm2~> +nc/Ufr;R!#pA=migXuK)s8;rsrVn2Bqu?Zos7uZgs8Vlmc[.2c+!_aS)^6FT+Xqlrp\Opds7Q<i +r;?Qorr`8so)8Oe#LM3#lh0N&q>L<rrr<#sq<@khrVuomqcC=Jq#C<gs8W#srVlcqnbrpns7j'Z +=7cIir;Q]ortYJ3q"W(L_ns73_X%1#qu6TprV--crVm<'o@9e$O+2@qFEi1[rc9K4Dbho/-6!jD +)\WYh&/>ol&frl(@Wm'@G'\CTH?OL[I"$m'T@3!"rr3,ur:g*err3,_a2Z'QrqZZpqYgHmrWi?# +op2RckkP,UrVu-]#QM5pKsgmWrUKmes8Drsr;Zcnrt=VXmHO<;l0?jls82ioq>^Blrr)lsrY,2. +rVHQooOo3d,Yn13rr;cns8N#q#QOW!s8W#ss7uZos8;lrrrhuRlK[F/rrrB$s7Q0bqu?ZppA]X~> +mJd1crr!<+qu?]SWi"JIs8W&rrr)jCrqufrrVucpq>^Kkrm,j=*#]n6,o.F<,TA"Tg@Y1?qZ$6d +s8;]l(B=.,s8VocSsZRIV4ss:q#16lr;HZqnG`Ifqu.*(s8Vll<jci@s8W#ss8Dorrr)rsrql`n +rqud(rVuStKi[mHrr2rtrr!T2qu?Nhbeh<8_90^bs8Vuqqu?]prVlisq_nHRqq/X#_8=11_oKj: +`P]O!P\slCD/jN9FE2DCDJsN7FG-6i]Y;(qaN29>^qRRu^;n%>p\=aoqY^0hkfh,eh>[<QrqcTm +s8W,us8N8qPbVLFp\t0orr)farr2rsrr2p%Z]'F?r;?Nhrr)lkrr2p4rVl`ms8MQ#VQQbrX/;tf +`q]3+rr2lr!<2urrr2rt(&e14nmrUT+&)M-s8Vlos8MrmqZ$EkrrE#rs7cNmrsA]'s377.SuD/U +r;Q`r"oeGtrVlffs*t~> +m/IIlqu-Qos7*R;B:?X8a",9SaiVWF`59R7a3MfPa3W2Weu`<s&JQ/r+V5A"(^gm^]@"sUaO.cB +cc5n()TKk>ahPj=aM>N(>A75PA87=@_T9pDbfn2Kn]:aMs2b5_&Br;;bfe#U3iQE2bfRcCa2@kq +rl>,_aSs0X`r*pX`rF#+_nOCAQ?#%)aiquK`lcHD`P^'Ge$??q_SO*mcILFbaMc3?_8+(8d)X2Q +i9]1@gZ7_jnEoc:nb)PBhS#SUXehr$Z`0n/\$E0=X0KFgiU,sokj7^%oC;DCm,[<\hsf^S`l6$A +d)aAKbKJP]\@T#\e]l7Z`5os<`PjXQb/hHFd=%3L_T0X5`lcQMaMu<Bb/h`Hb/h`Hb/h`Hb/hQ@ +`lQ<D_oC/iG\iGdb/_U$b5]Q]`rF-[b5'*u`l5p6_Sj?tG?nNO<`iF3=c0u.cHXGQ`Poj<b5TU0 +b/_TD`5g!A<"g,e2q,X[aMQ9Rbf\&Ja2#[7aMc0A`Q$!?rQ>/]'["M:`lQ-;Lf$fDE7FFXs82Zk +s8W)prVuorpA]X~> +o)Adjr;QTn/H5MGs68Cts8Vuorr<#trr)fps8VrmrVl`ipu\JA,Tn6S*?QF@+snUE^\%O)$30Vs +s7cQnqY^9hrso&*rr<#rs5)W'oBti1g\q-Trqucqs60I^r=&T'R?a57qYg<hs8Monrr)lerX8c" +nR%ELp&Fsfrr2lr"9&)qhYtDj`P]IMrqZTnrqZNjqYpNos8VoecAm7,H@'dVFE;SKFC7<V)]p.C +*Y/hr$O-nE#nRXU$5!se)&btSDfp/@FEi4dH%'pYI$);/p\OpgpA=X`rs88T_8jFXs8)`ms8Dp% +rV?GqJof<=rVlcql2Cq^g1KAGpAb0_rr<#srr;lsrVZNl#i=q5p$q;3nCIU="T/,rs8Mlp'Dqe- +qYp6I-R0`XVYC,cs8)cqrr2p&qZ$Nis8VTgp\t3jqu7,hjQtXos8W&ts7uQir;?TprW)lis*t~> +mf37bs8NZ.s80F+\*a(ir;Q`rrr;usrr4;@qu$Kmq>'0M5p70e*#BJ4&fr2=?+]Y)r;HZes8Vin +s8Dutrr)d4rr<#ss7l;kSZ&BUS?T3lr;ZfpqY^?lrU9acs8Drsr<E/uR$3l/r;?Qpr;?Tnrp]pm +p?u4GS+cm]rr;urs8EQ,s5(]2_o9R2jo>5Xrr2ips"XNOqu-Hhs7!t?`k072aiD63^qQq0D.dWu +Ao)@/F`;>GH['XSG'7nHFEMDa[(sc&rkB\o`P'7,_8FCZs8Vrqs8DuprV?Hkr9;/@_<V'urr;rq +rr2rsrW`E"riCKbc2RbCrr;rcrr<#trr<!(rq=rQhc'1Hs7uZms7cNms"XNOs8Vups81WRZ`'n' +Vl[%jg&M$NrVc`qrr)cmrVccos8W&tqV`Y>)BP^Ls8)clrr*6(rVucprV?KnnbrLarr<!-rr)iq +q"Cq_Ssdmur;6El!W;rrrUTu=~> +n,NFdr;Rr;rTK)MH*P3)`lQ?HaMu0:`QZQGair5_cdBO`.M*=4*r[#h$ka$W6CuQTe^;j^bKI`G +bJsJ$rlPnubJqT5]6e1+@pWPcEk9!'a2uC$b5fTQa99Z,`l?+!b5]Koajk]dL5*sm`5Tg:^r+.1 +`l@tuqo/?MI`9@Ca[1K3bg+GT`l?9I`l5p>f>=o._o'-jaP"eabf[uI`4s%%`m)fWjPnJ:l/V4# +o'bf*lgNfLT:)=KYdU^D]XYA]_8*k$]XP>RXJh`/iTp""kiqL*p[7Y=lf6^]hpKNjcH")Eai;TP +f?CG,Xj5M?b/qlM`l5s=s2kkmakW5!>,ouh_oU'Hc,dusao]Z(`r=$d`l6$?Zq&+mc-FQ4aSs?^ +aSj-YaT'EYa;`+:a2Z$7`kS-Y@T$9/=^biBS&ik!`5KX7aNFM+s2lY*`lH$?`OQd*)AS1Sb.5I/ +cHseZb0IcCa2Q<I\B)Y.`lQBJb5TK^b5THn`OiBb9iPDpiqNHNqtp?jqYU<mqZ-Ths*t~> +o)Adjr;QZp!ri,nrr3/Yg%bUIrr2pKrr)ipqY^BhrVu`brPr_&,pjc_*$-1I*[agTkPt8Ps8)Zl +s8MusqYg<equ-Nsrqufnrr3Moht$:,mdK!3s8Monrr)fos760hs82d*s7lKV=l3]Or;HTos8Dlj +s7-'rs8Cqk["/,Nr;?QnrVmN/q=D\G`l5j:c2[_<q#C6dpA4af6N6oMZ\F-\DKKf;Df'lUAMGPT +)Aj/"%hK-S!WiT7#mLqL!s8i<#mh.U$Q)EOG^F[^G'JCOH%(""\*!A\q#10grr<#n#kH3WbL?F^ +s8Dcm#64W!BZacEq#9UZs8E9'q.%jFR.U=Hrr)lsrr)cjrsR]Rn*TZ3mc)n!qY9da*rGs:qYp6I +-Q=6Sp\Xger;ZfkrVucirr;ujjbiF)q#1?mqu$<j"5rS2ec,RPrqu]jrVZTns8E#rpA]X~> +mf3:cs8NE(s8)/\T\TMFrr2pLrr)lrqu-Qjr;ZQ_r5NIt+X%dJ()Rr4)C/+Hjo=uKs8)Zls8Mus +qYgEns8N#qs8EN.rr;ok_jmKpUS+WgmeZq_!<2urs82?cs8Drsrr*H.qu#_\ggK:Brr2rtrr)lo +rW2usp](0js8N<%hdis=rVQTo'`S%.rr2rroZ+kf_nsOBs8W#ls8Dip<VZ:es4kB/`k04-a2G^0 +_jtLUCN+B9E--GTHZsUVH?jRTFE_qRH$OUYF_c,k^rF@0_S<q-]#`")a56gqs8DutqZ$HkqZ$QA +`Q?R,pAb*irr<#srX]&.qe!lUir/oWrr2lprr2Hds8N&ss8EH,rr;_%d%-Nrrr2rtmf*4c4oPE\ +r;6Hho\QROW2?_sX.u9Xo`+jhrVlfpr;?Nms8;osrVu`Q,SqIDpAOmgrVulkrVufks8W&hj,!%" +s8Drprso#*rVc`letSh0U?h^Srr)lsrWE,srVlEgJ,~> +n,NFdrVo"ZrUJBQ=e3LOb0/&Rb/_N?_8OO;bh1=gh5XBf(*+>=(`4#)%MLgH^>-oTccF8NcH+&N +`6$'>`lQ6Drlc)$`Q#U&LhCL3@:F.q[(O;p`lQ3BrlXfQ+NhpN`P]^:b/hiId)\Ps9?52l_SsL2 +_8O=3`l?*@b/j=sr5a<+a2tthVf:D7b/VHBcd0VMa32u?^W4@-\[1#:b/ViPc,dZ7_o':1g$./3 +i9g"0n*]T-n++boSYE6q]"5Pj_8O@4_8!LgaN;B9^V%(`\$i6>fCnt2mdBB,n`KH5h:p]Hg!@^\ +ai)<>`lQ`^[BR?[fu;4Xc-42HaSs<ncHk<D[Re'U`l6$Cc-=DPb4Eg[b/hZHb5TBgb0eR'[t]1Q +c-"&Glc;W8a2l6;`PT6Y>?k30?s?f6?Fdqr`5Ta;aND`Nb/h`C`lH$?`OQQj(D5<F_8sR@cGdiG +_S=+6ccj(2]?S@7`lQBHaMu6@r5oSj_7,A'=C,d_nbiCbqY9pcr;QltqYL0bs*t~> +o)J^grVm-"q>:3ln(dO3ruM+;rr;cnrqQNio^%Y_+se6S*#fk;+"/F_aRT0+rr2rt$NBr&q#C9j +s82WfrVm]5r:U*ds8U@6me#i3iVrlWqY^BmrVQQms760hs82d*o_S<8['k;Vs8N&urVZZis7-'r +qu?@mfOEh7r;?Qnrr3Z2r;50c`Pfd3d.[56qYpNnq"=U`rtak$K7&&hEcQ5@I"#H_,pF?I&I]$P +!W<!)#RLbL)%?iT!Wi6"(C:Q]&04,SDL-ANGC+XTIsHshhXgI@rVlg)q>U0]n]/nmh>RBKq>LWn +qq#Q-@fQ<#rp0UarWrJsV3Th(Zhs[krr)lsrr;m!rql]prqud&mH![)mI'E4iSOM4!<2ip*rc3> +r;HQ`_(-[urr2fjqu?Wps8DutrV,H7+tA?<q>LKoqt^0drsIcKl.ke.s8Monqu-Nns8N#ks*t~> +n,NCdrVm'#n\_$9q>C75rr)lsq>^HhrqQ$JNuoGe(`aA,()Io9,C@K$qYgEmrr3?'s7u]mrVuls +s8N#q%fQD"s8;ceP+n>=TVedHq>UQqqYL0]rr;rqs8W''p\ac;Z*S]NrVm!!rVuoprr;rprW<-! +s7uX!r;Z@fdpCr-rr3Z2r;?Qos8L]f_nj:,deN\=qYpKlrtbJ/s8W#I^rFC2_o0O0_nr0qAnPgr +FT-G9GBS+MG^k0bFEqkKH@1*dH$F@VI<TaZRD6JV]uIq.`4F%%^Zt[qrr;lpr;ZQkrsSSCb/2s5 +s7lQls8W&s%/KhOB$4T^q>^Korr)iqmJ[%`$2sepV3BS"[/L"'s6osds8W'#s8Dlprqm;EX/`1u +WiN7lWqu\ms8Dror?)%;s8W#ss7F)U*h!$-r;-?krVuoss8W#ij,+j(KCSg;r;RT2qu$HnqXLe` +T:Ndiqu6Wqrr<#trqu`cs*t~> +kl1n_hO\2&]>r%mb=g!u`lPs?b/VlWcH:26%Mfa!)Aa/$&/5O[WQi`3bf\#Mai;6@^raU:cH!rD +`lcNMc-4#G]=PIPC0b:UC2]leaN)<@aN;NDaia1q(s:(F`P][7aN20?dqb\R?dm9=`l>s7`Q8%u +rlG,^r5\rZaN"5#!6Y;bIEKFScp5iU`mMrJ`Q6HQaMl6J_77M+`O<A,bL"8ObK\>T`5'++ceRd8 +dc9Z_qu66Pn+##6StMj[\A6,'^U^qd`m;i:UT;)NaiD94]tM"q`4NIgeFi;'lL=02oB5`%eEZ#H +bKe2O`PoX9c-XqG_7%&*cG[uO`l6$uaqVqH]Ml=1g<%@RaNDcOaN2NHbf\0'b5TTob/VHDc-FUe +HHIt-e]e$4mDoXWa2l?@`Q,s;^jH&c10Rg[>ZYg[`l,d7aNDZLb0%fF`Q-$=bK\/'&ds<FdDEW8 +cH48N`5g-JcGX]-$XgrtrlG,^!6G/Z!6G,]&'2l'X(PR;>*%S9rr;ifq>:0orV60dp]#a~> +li/I1q"t*kfA?Q-q>C3ir;HWps8;ogs89?6+s\*R*#p%H+Wr=@WVZGcrVZZo%fQ8$s8;oprr<#m +s7uQkrr3f6r;Z]ps5E/9qtTO6nGiIaqu?]oq=smes760hs8Drsr;Zd#[mAZ#^A@g.s8D-\#Q=\s +J\B!<rr)cor]C&Vl,L][_TC!cs82]nrr;uop](9ms81TGM0a5_G'S:\JTa^/&eGE\#64`*"98E3% +LNC?"sb`7$3gA.!<WT+!<337$Pu?FI!p!cIXH<fI#FfYp@A1^$i9ntp]'*f`5V`Us7lQtnQOb"] +_MNkrql`qrWiK&mT8AbA,?0%p&>!krVlip"TA5qs8Dip#jh$OlgO<0r6,*>!r2cmrVl`p!<2ur# +Q4:</`ud*rVlg+q#CBms75N-.Np&W/+*03"8r&lr;HX#q>^KgioBRdrr3?!r;HZqr;?Tprr2QiJ +,~> +mJd1crVn8?hk$n;rqu]mrVZWns8W&to)JQn>TFt)+Vtn3+<2CO>H.Mrq>^Blrs&K"r;Z`qrVlfs +p\k+)rVQKjrr;orrhc'WUSO`abkh8:rquctqYC*\rr;rmrscA"e:PC2s8Drrr;?Tprr2Zj!ri/t +qu$j!rVliiI(6q*rr)lsrB1)Zs6[kF^q[k1lMph[s8Duss8N&toD8LYdEBYN^r+.-_RlIeA8?C6 +H?XLTG^Y!eI!Bj[GB%J=EHQR+HS'VoJpMTcHZjLVUUS@a\&H5%^W!n(dJs7?qYpEmrVuoss5(N+ +_uB]9rr2rtrVd$$nlXUq]Cu4'rr2rtnbs*ur;HTnrr)fqr9dSA^gd3?r;ZWmrr;lprr3i7s8W&t +s8Drmm_>j'V6$Sk[#X8DqtC$hrVclsrr)ir!<)os#5E6hj7N9Krr3Q*s8W)unE>6F)BBS?l2:MZ +rr2utr;Zco$NBu'qpD:1V4HB;rr<#trr3#trpp)>~> +nc&Ufrr<#srr4A7]P22d_8F:7aiMNDa2c-A_UI#"5mIl+((h<"*>T+u4G2&,c-FE0`Xg#(_T9X; +`5]pF_op$<`le;*&^8D5_n0YhB4POaBop*JaiVX'`rj?&b0':r"3Sj3`r<ph`lQKWS1i!(T@;-/ +bKIoFaiaV(pW@s+b/h`Jbfn>VccjAQcXsJn<nb^6`Q6HQaMuQI\%p&(_Rdn@bK%iIai_lNc,[N> +guI)JlKd^'p@@b<d]T.=]"Ptq]t_G(a1o0l]"c%[J;(5H`5BF-aNMoJ^qddt[C4lZrV,OJn*fQ1 +jkS)Bh8IIZ_SjC8`5p`P['UsUf[J0jb/VHDb/h`WdR2&iT?kg%_oBd?b/VHBaNDTHpW*uic-OYY +`lQKRe^MZ)f=Ol6ccH()s2b2^s2b2ZqoJf[)9^.EaiDNH`lGirHY$JZ<Dlb39rPb>]?&.obl>g1 +aMu6?`lH9Kd)eld_Tg<Db/hZ>b/VELaj"N:&/>Nbbgjt\rl+rZrl,Ynb08)PaMZ!*MHs"]@(G\) +s8D`hqZ$Tj!<)ZlJ,~> +n,NFes8W,p3rAsPhWOq=rr2rtrr<#tqZ$3fqLKk=+s7sL+s&!M-]HmSs7QBdrVucns8Dutqu?Tl +s8DfoqYU0frVmZ4r;Zf`j8/E?nE0KFs8Dfos8Mffq#(-ko)A[hrr2op&,l'F]AI)Srr;rss8N&u +rTX@]r<2Xmi`PLEr;Q[/r;Y0``P]X9f`(XFrr)lqs8Vfkrr3MaR=93qE-HJMJ9+OG.i\ro!"K#0 +!!O/Z&-N(M-l+'A"nhp."UkkdAo`-CFaeO\FFT+[jno&W%/p5#q>^9iccjPip\ame#5n+rO3qD1 +kPkAYs8E<%rqV5NfQYL8rquHgs8W&ss83T.qYg?irr;lprVuo]lgjQ9p$(qmrr3#ur;HNmrr<#u +rVuotq\T,.TDeffs8;corVu]jjb>',,U"3U++sCg!;uin!<2ut!;lcq#ik"3n,!(ap&+gh"oeH! +rqlWcs*t~> +nG`Lfqu?]n$,E.Hq>:3ks8W)ts![aDo`+]8+!M[E)]B_8+;uPah=gmDs82irr;Q`qs8W#srVccp +qZ$NnrtbS1qu-Nms7"!sTq%aJVU,#:s8;oqrVc`tqtg9^rr;rsrr)j-rpk9BgL&h9rVQQmr;HZm +rr)cooDK$orVlcmm8VnAl2L\^s8?a4s8UTf_nj40f`(^Hrqufos8VrorVQWb`50F0_oBO+^p/]- +Ao`*@H['jcIsZHfHZO1FE.!1L:2k9!I"$NjG^+O`J:)WgH$"YN_8O7%`PTR-`P_!@s8;cmrVuip +s8;o@aiNB7rr2rrrX&W(ora8!?hXHtrVuosrr;rrp\tj)rVZWmrr2loqu-ACXO_U>rqufmrr2rp +rr<!6rr)lsr;Q`nrV6?_YGeY(W2cJkRd'\FrrE&ts8W#ss8W$9qYm)`s8;oqr;Z`qq>0*%*uu== +(*4<AqY^?ls8W)srtGD0rVcWns7<XmR@h@gs8N&urVc0aJ,~> +nc&Ufrr<#qs8Q*tlAo8%]tVP.bKJ&Mb/VBD_V!:D"qM7W&el,o'akRi\]W=;bf%WF_SsR6a2u3< +`5Kj>`6ZHB`Q63HccsVN`it,(AR/VNAs'XDcHFPVa2Q!:aSs?Ra;E(Dbf\#H`PopHct9B+9YAct +b08,Pb07s+b5B?\aoKZ^b5]]cbrsCs`Q-KX9@lYUbeqE@cd0\Tft"Z3`l5X,fZ;C[`lQ'<d)X>S +bi.R(h!==qna#B)i4GMPYIMHj`Pfa8rkq[GU7J-b_mFDZPc_R8_T'X;`Pom>_nWt![_hk:q"*_> +m.'K-e)f`Mcc<r>be_*:dGVRFZ,"Z/aMu<Bb0%`Je!>9k8Cu83_nj=3aN2?>`r4!S`Yuh9aN`&U +b/MHJe'HFiBrBR"[+!1=aMu6@aSj6`aMu3<qoJf[)9KtCb/VNE`Q,d2Zt`cH;,^UsAlkqD`Q$(" +bX0In`lH*:`6-?Kbf%YEdaQ@[_o'd?bJh]?CD.L%().\tCYdI^`P][9aMu6@b08)Pb/MB;YA.$, +=HhJ8s8W&orql]sqY:$`s*t~> +n,EIbqu6Tjs8N8]huE`Ss7uZnr=mO*,9J!N+<_pSG/3eErr)HgrV6E_rZ1n7qZ$Norr2lrrn$c/ +r9`e0s8Vojr;Q`rqt^'crr;Qg'*%n0r;$Bfrq`:MhSO71rr<#trr30"s8W)srVc`qr?_ICqu?]m +s8)cnqu?]prVulnZ\cY7q"k$bqu6WmnAWMb_o9mqrVlfr)?0R3s8W#ZU4IN*FaA1TJS6GV)@coO +!sAl.!"o>5!#-t!*tehf.Olhn#lju+"8`)u!>5J8&J6R-EHHJQDfg/LLofk7rVlg8rr<#sq"r4S +aSYi3qu-QpqZ$9^<8)-=r;6Nnr=&]*p&Fsiqu6QorVQWlrr;rsrtYM/s8W&trr;]1J(`:RqY^9d +rqcWjq>UEorVlNgrr3;ujR;R1mHs2slMgegrqH*`qY'pfrVn,Ar;?Qkr;?Tpq#CBlrqaii-mKu\ +,U=EL.3eWcqu?Zqqu?TmqZ-Qns8W!'s7b@>o]H2Rqtp?l"TJ>rq>9gaJ,~> +o)B=$rVlcqs8)coqs'rOq#(!gs8)^1rVZQ9,TR^=*#fn?,'C]pp](9ds8VuqrrE&qs7uX+s8Dun +s8;lrr7%(0RAldSZ1@no"8hrmrr)lrrUTpts8)cnr;Z]pr1K,*^M`rJr<`E$s8Dlqs8MurrVuor +-N=&Bs8VrqqZ$Kjs8W&ss8D\rKu7U%s8Vros8W&haND<8`Q\)Tr;Q]q0E1kHs813^`kf[8^V@U^ +B52@-H@'m\I!L$eI!9jaDGG%kIsZ3E@<6[<I<p9bHMr3jH5(XGI<^[d_SX40]Z.t-^s`8]r;?Qm +ruM+6qT-Xqqu$KorVuoos7l7efP8q6qZ$Qprr<#nrr30"s8N&tr;-Hnrr<!5rVQWpqu-KmpVVC1 +dTZSJrql`os8Dlprr;lpp\u00s8M`<XK/1rTr=o_\G#k#s8Mrrs82irrr)`nrql`q'`%e/r;HH6 +I3KUL(`XP4'-S=fq"t'j!;lWms8<N.qu$KKVONsIf_tjLrr)fpr;ZfrpA]X~> +nc'0us8N&mo`+sac=U:n`P9@2qT'SucIAj%%1X!g(_dGf<h.IYdE]YVahl9A`lS%srlG)](!+A6 +`m)ZRbK.W6Qs+-*B3\tfZGX]]blu>4`l5s=rlXfQGg+4Sb/;B:c.@c(d]ca%ccs\Wc-=DPbfRrH +`Q#p:`lH-Bb/MKF`6?0DaN;`Qai)BMfV*]$:<LMs_p$HKbga&;^;.Flf[7peb/hT=_og3Dc/7mB +iU-+*oBb`)c'+a&\A,u&a2u*/_TBd6["`"RY/@Jm>?_AcYJJ,lbJqT?qnYM.`P'Ilp[[hEk3VEq +f@0$6`l5p:_o'OCeD%12XjtV6_T0sI`m2]Z6ciB@g<@[U^r477^W=C8_oB[?`P]gq`>ZY4`QZ]N +_SjI;d`p(\Uik>78Cu24`lc<B`r4$^aMu3<pW39T;olu#b.imB<_caq>$=sH[(j]*aMuNL_oTj: +`l?*Dc-=>KbKJ/N]u\=<c-<%n()\)0)&Eko*YIA]a25U/a3ViHaN2NHbf\,H^qZ"27S@<ro)A[h +rVQTrqtg9cs*t~> +n,Ejoq>UBks8VH@q#C9ls7uX1qZ$P!+XS0V*?6#hnFukWs82TkqYU<cnbs:$qu?Zqs7ZKks4?o/ +nEfK)r;ZfiqYgEtrqucpr;?*a(&It1q>^-arSM8Fj)W9Aq#CBlr;Zfqr;ciqrsJc*s8N&ur;6Nm +rVlg8r:^0gr;-Ha<8=::o_n^frV?BF`PK=3_<:[nrr2p2rr)ZmqrOf8E,9lLG'/4#,p3s.r;[Z: +!!<3%!"KPZ,UP)Q!!a\pAj@4:#Qau.rW!]7"9\f-#64f:*,9D3Fa\:FH[gsho^MbX8,`J^il'%' +qu?Qnqu-Efs*(s!AFfZuq#C<mq>^Bfr;-HnrV-3hr;Zcpr;HWps8)Wls8W)ss82ioohaZ!UlGEN +r;6NirV?Hms8Drkr##D0r;Zfdk4\H>lL<rgnGiO[s8MT_qtL*fruqC>rVuorp&G'grqXiQ/0H)] +*[2jK:b!>4S,WB`s7u]orqllqq>:0jrsS]'s5!>AlL4cQrr)fq"8quiqt0o=~> +o)Adjr;QWo#5e86Tu?^'rr;io(]+10=<&Fu*u>\/Rd^"Mr;Zcns8Drsq=4G%rVZ]ns8;Nhq>-PV +S"cUTZJ#-TrVuinr;Q]q!ri6"nbs:!s8Vloq#CBOA_c3_aT)#6rqcKks8Dolrs/Q's8;corVc`q% +/fi!rVcQjn57o7S,*$_$MjYUa25X7^ukOmrr)rsrr2rtr%S*Dd*08?c,[N.^kQQ>E-?SWI!KmVH +$Y!^Jp2!+:NgYqG^*e`G'J7XGBS@[H[:#;Gp%EaEHm"daMl$5b/V0:^qSn0q>^Ejs8Drps7kTja +liX%rs\f'qt^88\'ALRr;ZTlrt5,-s82ims8W&lqu?Wps8Murrr3#qqu6U.rql`ms8MafiRaods +82fps8;oprr2rprq?@*qtg<ab,;5:W2HhoT$-s/pAb0irVllsr;@c;rVuorpAb0hrV+KH-lNp@' +cJ,.8gG#oQ2COYs82ipqu6`sr;-Em%.^]rR%:q_s8W#qr;QWo!WN&ks*t~> +nc'0us8MojqZ$EURU:ES`lH$;qoBYtaO8X""qh@c)&Nj?dF$:_ccO2S`l6$5aSj9XaSs=#aMc!@ +bL+SNb.>/mCg:@SA9+*N_o0gHcHOB/`WF6(b43Og_p6]ObeM-C_cG=>>H-;rc-+/Jbf\',a"GBP +`l>s9c-FDPbJqTIa2cHIb/V6>_o0[Kfg<rDE5TlAdETYZ`k9!r^okc-ci2.<b/M35a2cETkLJe[ +meukDk3]F>SufQA`5Tg;^;%=u_9K6F<E#<_Za,^!Cg<:6_8O:8a2Ps4^V@V&b.>=(^Adirme#i* +p?9u`lH7Jl_8X@9cI^@WXgH'm`k]d>bK7`T@B7.=e^i6c`k]U1cH*lB`6ZWI_o9g;ai;<<s2>nt +b/VKAa2Z!;dDsJTcp-=5QZ(O&c,n/Ha2n8&!6G/ZpW36S(<ab?ag6J!=]o!1>uXdY]YqM-cG[iJ +r5LY;bg"APcdBkJb/VBIdATMF$l^E0(D6m4(^q@;gr[:F][+pHaMu<Bb08)Ob/M2p@n]?lLuA73 +"8_olrVlfurVQQfs*t~> +n,Ejpp\t0hs8U[+s8W&ts7uX1s7ZK-.3]fW*?lmJIHpJ)qZ$Tjr;QWonbrOdrVllrrr35ehX^:( +jkfV.rrr8ss8W)trVlrop\XO\s8N]-q>^Kgoh=3'dp)YFs8)cqrVl]nrsJc(r;6BhqtKpdoDS[h +r;Q]mrtG>1BZ8V%rUp$drV6-+`5'41c2%59'E7q,qYBNbJTbsQG'SFj6kUIK#5\B9%0m"<!!Oc) +E'GHS%0d=n?XGQ0&-)t6!!EK5$4$b4!"K,@Bk_U-Ee84OKoXLJp&4n!rVQWlq9@%0qYU'fr;Q^U +j'(?9MYm;Ls7ZKhr;6KlqYfm]qtpEmrVQNkrr;rnq#C<iq"amgrVcZkoV[`*giCO9p\t0gqtpBm +s7$!srVulss7,IFmHNj"j4XG3#Q"5oo^_nWrr)lsrYbb0r;ZfrqZ"lU,Tn!S)BL%J:;$7N,9\<0 +rVuoqrr*#sq"Xjfs8Vp%s6o@JlehR=s8Mus"8quiqt0o=~> +o)J^g%KHD,s82`ZUTEPOs8W)ss8Dp1s7Q?',TIU=(E=Y5Hg:;(rVuoprVuEes8W&r(]X=0\sAqa +Uo(3>rqufprr;rrrr)fnrr2rgrr<!4q=t!iqY*b@imCp)qZ$Els8MroqtU0or:g$eoDS[ir;QNl +'`7oB_q.ieq#:<nqY8+N_8FC>q>U<j!<2lq!SkBf_,A"[\ANu+G'8+VH[U<hH@L*`J9c?W>Dd!1 +FanX\H@gThH?aL_G'eR]GBS.RH$aghI<^"Y_8X=.dC['1_t=!+s7lHjr;-HjpWLS(qu?Wprr2p4 +j&k35M>I/Ks7QEgr;HZqrr;NgrVc`q!WE#rrrN&prr3Z1qu?]orr)llViT`kEm"FYs8W&prW)ud +rY>D3rVuAsU84T_WiN.qjS/]OrVuorrr2utrr)lr!rqulrr3Z.rQA[o*#9e5(E";e\ak.h)BJVO +s8VrsrVlcq"9/5nrr2p*d\3,#VVV4MrVcZnr;Qitr;QHjJ,~> +mf*alqYU0]`b]@^]ue@7`W!mWaT'BudDsk0%L`d_)^$7.AB;s@aNMfG`lQ0sbkT?\a;W(=aNMfL +bItZ>>[h8R@qh%>^;S%8ccs\VaSs3Ia;3(CaNi&NcT0P3`B_nrc,@`H`P]U4a8X.2a2Q!8`P]O2 +dD+#QbKRuI`l6'=a2Z6HceqU-`A,obbKS5Qf"/c3\@8`ldf%C<b/M33_opNjhUUiZn*]H%n$JIh +\%]i#^;%\.aM#7(`O:b7JS(:V`ODdq5WEPO^W=a;bfn/I_8!b$_S=%%Z`a5pna#K<mHj&cm-2d< +]thh8bgX\Z['R*d`4aC=c-k%T8_')JgX=9c]Ze=8bKnJXcG7fNcI't_bfh-QcHj\V`m2]E]t2#" +`l,d5`f#>pcW[@%c-FJM`Q8&$!6G/Z!Q`FXaSa0sbKe/GX)hKJ<Dun%?!a;<aMGd=`Pp$Arl4u\ +rld.7aNM`GaO[Xq&eGBk)BK\,0:(!p%hK9+c,.?8bKnGU`l5s=bfn/QahkZE;b9Vl^%D=("8_ff +qu-NprV$8A~> +nGiOfrqufr!qk17rr2urq#2*,s7uB_Te.<0*ZHIT,`DEppAY!arqZ?ZrW)orrrDrprt*TKo^1u" +mJm4_rr;rrr;6KlrrVlcqss^es7lTn%eBErgu-qYRed!]s8W#prVm$"qtg0err)ir%0$;#qY0jd +q>L6frVlfr'D_:0MVi`uqt^*drTV28`l5p^qYU<mrXo)'p[6%WHu=(QI=6</*>]4fq>_63$ipD0 +(e/mW3#r52!sKf+^IgBq$N'l,":,>>"8i-`&Ih]VBRjoGH#eJ%f^8_=rVuforVulZ`Q7QFqtpEh +qu2;TflPC4s7lWor;HZqoD\I0YH"qup%\@Zq=sd^rql`ks8N)urVm?)qZ$7ffA>Ogli6bVqtg<l +s7-(!s8N&np&G'Zm.B]*lgENfrr<#p"TS#gqu6Qos8F)9s8N&qs3,:2(F:.B*$QRS[.=(icn$:f +P5G1Pr;Z`p"8qrhr;Q^%qYC$gkjIp!jneuZr;$0co`'F~> +nc&XhrVlg(rVHE1Tulm*s82cns8Dp8qu6?]o:.0E*#KG9,pJ6@rV6EmqZ$Kjrr2lgrr<!;q>L3j +s7tH4USOZdWQ4Q/q#CBmrr2rsr;6?hrr;Qg!WVlmrsnc#=5;]cS=06RrVuorrVc`urr)cmqYps% +s7Q3]q>^9hr;6KlrtP8$[YWac`Vo`5s8M9#_T0[8lM:JYr;cirs*XhGs67A=^W4:/]!6itF*`1] +I=-BhI!]s^FaJ=XDN&XMF`r.WGBmQHDfTT<G^k*fH$FLUGBnIcI=$0iG.#E(cFCp7]>VkirVuol +s8Muqs8D#qa70'-rr;fjr.M<-EQn4Xq#CBkrVlihs7jpDWjD3fq"jmaq>1!fquQ]mqYq'(rr;ao +f\YUgm/Qq\rr;6^)ZBU6rVliRXer5%Vlm:qZ2=7pq>^Kks8W)trr)lr+o;6<s8;o>BI=<5)Aa20 +*$DHSq>&;`)Bt4<rVHKmrVc`orr`8uq>:0k$h^NjT:ijlqu6Nlrqufrr;ciks*t~> +nG`Lcrr"GDo]DBHL9\bC`Poj9`l?*@b0%iOcHt-s(C_?&',hVoCXLPLbfIWA`Q$-Gc2Gl`b5THu +aiqfKa2uB9Ti>]<A8,\2[)fr"c,n2RrlY8^s2OQL)9TkCdF#n[37-F/O*f7!`5p$<`66BJbf\-. +b5]Xtc-F_acdU"\b0AGVai;39`Q66HaNKoqd:/s&c,e&Wc+_-5\?!Wod)sMTb/hT?_8+CXimd2Y +p@I_8hmAo^_SF+3a1oC0aM#L*_RlRTEFj0g]u@^nM&CY&E1b4f`lcNH`PK=(?bsP!^q@+iYj1oF +ros4Mk2Fq_g!.LLbg">QbKnA8X3/H#a3hrOdq5E'@^=M7`6?KFbL"kbf[-USKT4.#daHUmdEp:h +da6.WbfdoEbK%cA_9^Ljb0nX#bhC7]`W!p`b08#L`l?*BpW39T(Wk"B^Vc^]?=-f3>@CKI]=Q"t +`QuHGb5KCFb08)Ld)sJJbFqQJ$lfrk&KVo/REE^rW"TRRFj.b8_:6l[bf.K=aNVlMb/qZ:Y$k't +<0$#6s8W&mpA4aYs*t~> +nG`dnrVlZjs8Um3rr3'!r;ZTl%/p5&s7Z3OGU=UQ*uY&&#H.@mrVlcms7-'us8N&rs8W#sipZ:( +l/(S%rs/N&s82]hq>C3k!r)Bbo);,Yr;ZcirQB<=guD3&rV-<krqucpqY0mdqtg-bq"!hArUfl_ +D.II4eFrqAqZ$Knr;$Bmj^ZodB(c'!q#/^^^WOI=r;-?krr*N-qsVjjI!U$]G_'ul+rLpl!WE'< +!<`Q0"on]2%P;P6/05N+!!<H@4G;$D0an3equH]s@06K0!sSc;$rD"bF*N%TGC,tGmf3=_rr;`m +rV=^Vhtm9IrquZS?/=@@m.^PYq#(*hs7Z)U;I<[*=&AqaY*+H_Jtg?Ko`"LWs8Mops82fkoDZ+N +hqc[jpAb*iqu$Bjrr<#mrr<#trr<!#rV69drr38cnE9'&jm^dnrVm#ps7Z?hrVuosrr3u8s8QdZ +*[2UO+t+HO+1D4Is71+O-Rnris82iirr3)uq>'sfrs8Dqq>^*Hlg!4#rr`8ur;Q?gJ,~> +nGa(!s8W)pr91#YkP5)WqYgHoqu.6,s7u]eo]:-<*YfS-+!;`(q>:0k!WN,krr<!6rr;utq>^Hb +o:V_NX/2W,o)J^err;oprr`/pqu-Noo):6@qZ$Qis3,ZAgYbj!s7cQnrqucqr;$9jr;6BhqXj7G +rUfl^Ch%70eFrqBr;Q^4r;$Bmk$cc^AbQ-'rVb3`^<4F?rV?Ejrr2fp1ASu)_o9R1_6.ZjE-cPP +IXQTgGBe@VF*`7XEd#8sBR=iCG^=FQT[Zh]F*N1^H[L0erd%dsGBeCZF+AMAc+q!.`l5g-ci<h@ +rV?Knq#C9ebJ`?;s8Dupq;GQ6i*5UDs8D`hqtpEeo:8cd>YnKus6ZtPKQr*CaQN6rp\OpgqY^<g +s8DZk\;&nqcXceIs7QBis8;j6rVufos8W)ngnq-QXfJ1sRaD$/qu?TorVu`nrr4);s8HUQ()[r5 ++!hdA)7';?s7'nE+XHm\s8;oir;HWort58.qu-KnrVss5TqeFDqu-NnqYpQppA]X~> +nc'4"r;?Tpp?fh4@]$i\b/_ZE`r!gqajA/^cI9pC()7Ds&/GidLXF8fb/q]Kb0%s*b5KE]`Yce= +b0J#N`O3-dA7B4aA:1]&`l,m?_oTptaoKN^`pq,@bf@rOa478"f@eh>da5hLa2l9CcHFAWe^W's +e^Mdab1Y4oLJC94?aA&4dE9_TbK.TEc+[*#]hm>0bK&5L`P]QsY1(M8b5TK[`Y$hke_]Zao'Yo" +SYWU3]YD5#rl?,%aMl'DaJjGJK1CX+_oB[/NC?E^(5T-&_8F70_u7Db`k]F.`Os@(lMp\Mm-X6* +gtV>Ed)O&KahQ0Kg9dlocHF5ObL"$me(%%8d*ftOa32oceCB+07mo=$39AVRG\C>oL9/JHgW[pi +c-"5P`5][/dZo"-cbN6)e]c(P`lQ<Hb/hTBaSs?^aSX!WaT'C"bf7WFai1uc@9ur8=]8X(O28QI +a2HBGb5B?[au[Vc`Qun"%20]r)%[Jn%1ANTb07h%#S@Qpai_NKa4&;P_8F::bf\&Ha2#QI=A2S* +^$P^ts8)NerUTu=~> +nc/Re"o&&sma^J!rrVoos7uX1s7uZfs8VolbY9N-+sA!P,#?Y]p](9enbs!trquTlrr;?DqX<G+ +hu<W]p&G'jr;66crr)iuq=smYrXSi*rr;im;V0a_Q`'NVrr2rtr#Pe8qu5s-Tm'd@;cQn!Tj3Mb +VMU16ABO]IrV?Kkrr3W(=kW"_](u7!ouG%d`l.!:s82cp'`S%.q>00JI<fm[GB\QZ-Q<Kt!Wi6" +)[$HQ#6=r40Kd[;4Vn>'!<<9=/jJ:(2('":!Vl^k"p=r2!s&Q=AScdAGB%hTJ\:@As8;iqq>^Ko +i5O(;r;HBis0@^=d9lG?q#CBns8)PZ>='f&;-m*e8l^qHZG*Z/F'r*jS^d6,s8W)rrr3<"oM"-+ +f4*\3rVcZmrr<#mrr<#trXo20s7Q6gq>^KegZn1mmdoYbrVm#os7lKhrr4/@r;?Bjr;Z]e_&t!N +*$\t:7j]WSpAb'ja!r)VR/d$]qu-NsrqlTjrr3#mqu6Tuio]Xcp&=skrVQWprq?AB~> +n,Epts8)`l`h9j8s8Voprr2rprYPV1rq?Blp\;p)-5mmE)'9qpdeNY<s7u?err<#t'`@t0s7lW+ +Q)(:NX0:R_s7lWlr;HWp"TJ>rr;Q]qo)8Xbrr39%r`%M)hit#2r;Rl:qu?Zmrp.h&G?n-F<)lkh +=bsGZKni`=anYo8qu?Tnrt>'.e`:kaqu?Zf`P]F0`9$mrq>L<js!.Ko^r!k)^q.9dCiaZCIX6Bi +I!Kp[G^OgaD0K7$K6)*WH$fO9#BaP0[:"3)G5cggI/SBpFan^[HN&(YI)EV:_SO+.`4P(0rVuiq +s8)cornk]Aq>^Kks8T6\g!aC&qtpEnr;ZNaQWcX&4&9*W5tFq6TWl)6O`Ff4FJ.1UqY^?iqYpL# +r:Wk@jj[_tq>C9crr)lorY>>1qZ$Tkqu"F+XK/:tX/VQWo_JO\rVllrrr2rt,5V?;s8;K&)]^"; ++CWA[,9fMIs8;o8,o7_irqcTjs8;forr3T0rVQWjs8Vo`Z(Re\_tX*/rpKf:~> +o)B@$qtpBms81c?>&1Ufb/DWLaN"(t(;n53f%/7#Y;R++(Dml&%Q(E8b0\>KouR-P+iqjKbfIuA +_gkm&@U3\dUVY*jcc*f>a2Q-Bbfn5L`PojfaC3*7`luWZ50_g;MilK<`Pp!Eb0ADde_JBRLL!>1 +4[2+mMFMfdQ?d^C9<6Rpd`Tt[aiVWF7ag70U=@?,e[WW:]WArodDj8I`Poj:b0AGogYM8eoBYK& +N2*_m`lPp0+iVUJb/D0?aj$lE7!:e;U;"jsaMai`*Fqi4OKGq)^VRhd`Flp+`59R7`koFhq>9O@ +mITbpi9A\8`5K[2c.(OdX0gC)ahuQ]PC(Ws9@D/+bf\/]eC]:@0cMc5:d[*%7Y$\rXeLDT9gr<> +[F*X[e]u=`c-FGW5M>&>9u>3$`l5s=b08#NaN4>&s2b)Ws2YVkaMc<>bL=MM^O]?er`'8->ZeAD +_99XAbPoZ`a?Ibf_8jR?b/^+[(E<kn8?ala&h;/PaO-gr#7Ye'`lH-Ke'H"J_8XXBb0@fEb.t?" +92/EJht6sKrVHEgrU^&>~> +o)B:#r;?Toq>^KMhu<ZUrq6<kq>M31r;Zfor;ZZlnZ3rV,p"!J+WkF_nc/X[rr2p5nb)eZs3^H- +o'"p/s8W&ms8Vrmq=smerrW2tr9sVSs8)Qkdr!t)fhCl3o`+marr;i]`f"20Eg4)\h;@&Ies/m" +<F0?G<E`:-`Uim#rr;ohqIRt0`cC_JqWGi9^r=Olqu?WnrtYP2r:fR!Mh?%jG(#$%-lN-m!!!3+ +r;[fB"onZ1,ra0&;C2\Q!<<*$#U_C=j,QGE%L*"9quC.,!!!'##lt>;'5r#>Fa8%UIuW(EqZ$No +rqufmoZYGFrVlTjqJX:0a^Y&Eq#:-il_dd!5%&;PEH-)&Dr]L.h:p`Ah:^>jS8M;EXQ9E]p]'s^ +s&.P'l&hk<r;?Bgr;HWprrN,srVlQk(B"42q#1*bs8VN\o'uJ<mF^"is82imrqufrs8N&qrr45> +s8Vji+=C[Gq"M?B+Y0nos8Vq,-m0i3s8W&ns8W)tr;?Qnrsel(s8N&fjQl*ms8W#kqu?]n!<2`m +J,~> +mf*^oqu#TWY1`[Ns7u]nqYpNp'`J(3qu$Hirpm-7)^-(6)B9]/l14?D(&n.2rr<#kjH-41V5LKP +p%\L`s8;cmrr`5trVlcqo);5Ys82cpe8=%'fM1i3pAb0hs8Vu_`J\).E0@WUgtpiCdum3i;-@C5 +;--S#`Urs"rVuimr+*t(_K#8KroV)7^r=OmqZ$Klrr)jPrr<#^]YqY'^VIX.EH5fAH@'j[H[L0e +H$OL]GAp9n]23?gH$ORWH$+OF]@N<dE.3*/H=;>KH$adbFa8"L`59@'`kf^4^A.O(s8;orqu?Na +bfT;Qs82`gC;8]MAGlK)rqQHTUJYYc?#Fe(E-#)uin*)Cg=tH>g"!^*D,Y8Khu3TIs7lQm;V0Oa +O/DdRs8Dutli%q%s8VrqrVQQe^p0]3Xe;_gW:BcQs8Duss8Doqrqud;q#CBe9,f'ad/!FG*?$6- +pAb-c?m6L4p](9mq>C0hrt#,-rVucns7cK:URdsTir/fT!<2QhJ,~> +o)AdiqYL3k%/[t^@Z.e;cH">TaN4A's2b5[(;n5;`Q6?KccCnH#Sn0j)Aiu_a2ZBHo#;iob0S/P +`k&3OB3o"VC7;WGbKA/M^Ve"/aND`Nb/V?:`q.8bb0/)F_UPu%gZI!Mf@S!^^r=^Qe&\D)7nR9G +XN9#If@A$'6pspYB3\2,5tS'(da$+^_77WcbML!@e&feU\];RtYgCP>`l?!6_8XL?f&,6*lM:JN +lK"J4Z*VKd_8jX<b07i7\9P^/[Z<>)Gq"BSaNqoHafpd`4A&(EPJ4WB_8j^Dbf\/F^V[q6aN_T6 +qs`q6o^D8+bjjK9`jrh!c.U[t['A'3behTR<j^Mn9\7\1aMlTGLd##u=DDnpDK/Zmi7$H4e^iC' +dESqW><c>U_:mVdd`9D^8D;c7jFW?=c,RW?aND`Nb/hZHbf\)LaMu6=`VmdpaMu*@aiMiS`kem% +@o?0+9O2%C\&5c&aN_s.b5B=;a3;TPeC#rS$q%&@e"I6_'p?npf@`h3$3no*bf.QMdDN]5`QZTJ +b/MEI_o.I3853j5mJd.cr;ulmqt0o=~> +o)Adjr;$<k#lE9<s8VopqZ$<h(B=:1rVu]ns8DQgM'F5f+<;[O,,4W&qYgKmrVlis!<2ut$Mj8m +s3^3%nb222rr3N.rVHQlrq?3fs8W)rr;Zfcr^?ecp8!o-h;3UhqYp3cqrOhl<d:[hh;.)KhVI&H +hrNPP<,cc!F`;>'=`7<(iqiBDs6k<Cin@H+s7b6f`PT^Krr;flrt,)&q=<=3Km%W\H@]-?'atBI +!<39%!$)7G!!XK+Y26`^,67cH!!!'&&N+RjjC:7c$3UJ6q>gNs>Q=s2$kj[sH?+7QFEiY=lLaoP +rVlcpq#Ag`i;3?NqY*kHhqV)sp\40qHX)kD7q?[[FDPo9JC`]:i8NYQhqm;Ohq[#D`/SJFVW[UK +abAO/jOq.lp\jgbr;?Nms8N-!r;HWirtGD3p&G'gs8)Njs6K4Ime5r4dd[58!<2uqs8N#q*WH$; +s7lWk]5H!kqY^<^:*CoupAY*edNKh]T)/<^s8W)ur;Za-s8;osrVuiriTTagnGiObrquctqt^6c +s*t~> +nGa$us8MukbbMoLr:p<krVccorr)j"r;QZpq>UC(p&Bgk*uc+7*?QAso(r@`rrE&rs8W'"s8Mlo +rso&'QCsqGW2R`/s8;osq#(-trr)fps8W)ts7$$fs$QOWOk\XHI^f1Qq#10RX(bUYWm08QhV[,C +gtpfDfA9;=BlJ$,D,s_T<0Q;;p\Op[H*Q2V<VHIhfYk_Fak-Fiq>^Hnr;RE*ahPO._S*aMBQ&'B +G^Od[G'X(7ApS`PHuW\o_4t+UGBA4WH$sp\FaMWeDKp5IH$OX[H?spaH[gEeF*i+SGC@BN]YqY& +^r"Ius8Duss8;lls3o$Fq>L?iohOE$hGWn>q!Q"D=HQfU@rZC,C2Rs=eDK*=hr!;I);X30hqQr@ +_22]6U>tkBbD=p1in1egq>^9is8Dp!rVlfro`"mj)u9O4q#CBnrq!4dVkgMpY+*<%rqZNlrr<#t +rr)j>r;HZjrqX*?c27J>s6rZ"*bFs@rUnGT*?^gGqZ$Tnr;HZprXA](rVQWgkGb#DSB(U,s8N#h +s*t~> +o)AdiqY:'i%-sQpG.#'"d`fkS`lS,$*6,t:ahu*<c,7fLc,S@M$ksNu)''J$K?D<W`Pqhrs2b&V +s2Z;.d)Eo9>\%2KBP<(*_8X^G`Q,s;_oBd?bfn5L`PojgaC*07b/_THL5"=9gN9:KfZ)+b`f*VU +@[OpXfA#-;hV[;Ghq6pgEcZPNDer3B?9ieQeB>q[a_eNIeO.j6bJCs8_R[5(d)XGQ`PKC1b08N$ +bh)%WrUK3bOJK8$^r41jaT':u_7-nn\WL-1F`0pG^VnC:`m)5nAICh3.XReo]Y;A2e'H1R_T'X9 +_og'E`O51,l1OW7k24k_g;:P7_p6o^fse0,g<7a^cTTq6dm2F4cGc8S4ap0i?ZL./D/jTIfAbZE +i8EMJgYLfDf@8:h\pdLMM9+2uUM8<?kLQ_CdE]PJ`lQ<Hbf\)LrQ>/]q8O5l`lPm;bfJ2T_Rcj\ +=]\C#<+T6f]uS+kbQ,faa>h>``l-$I`mE(r8ug+Vb0\Qr&en3me^i6X$P*YoccF;OdEfeH_8XR@ +aMZ3Db0@`$?:mmkRH+&?rrW/rqt0o=~> +o)Adjr;?Nns4@MOs8W&nr;Q`erYkh8s8N&SFrVbL*$uaS.(T6RrVulrr;6EirqcX$p](9Yi:6C' +o]6#Orqucprqu$[8,rAaq"p,JhVI;M;2DWrSRP`ZbMV(-jl5+Rgu7)Lh;%#Mhl:1+E,T`>DJ)qq +V.+2*][EN_i8r^.g@tK_aM5[2nc/UerVca,p%7hBZ%IFHF*<=3+;PCirW!Z6!!NQ-!!*-*!u+7X +gu)L,(]aU:"9&9.#pqjmo]&"a%Km(=q>`na#RCM7#o*UnDf9fDFFAXrb4,<.rqlTjq>0HtgA:jE +s5RJ>h;$ja>$+^V[F\A^CNFT8EH?"p`oPk3i8!&Ii8*PNrnnRKhrNM3P?q*^FJddOiS;"qp&"^b +rr2fpo)8^gq>:-j%/BSms8V'Jmd]f8kgTJ0"oeDpq>C6ks8)^2s82fprVcE!,p+D`qY^BhBd+iK +qYgEno`"ji"RY.8lJ2C=!W;ios8W'!r;QHjJ,~> +mf*dqp\1AVh!k@DrVuors8W&srr2utrquirrr3N-s8DoMEYf`4'HS)5,.7CHrr)lprY,81qYp?. +R\6LLWN5gns8Dutrr2lrqu6Wqnbu/\qu?NjOJCR`i7q.b[`"hK=c1D[gY(`JhVR&Hh;d>Fi8NLj +@;g%#Dffi.;pV:JBpQE[UL2j;gM5O?rPQ[n`kq*Aqu?]qrqcQm9\dG(a2,F)Lh^pTI=-?cG^"U` +H@($aI!g'VLWIYEBleQGH?jg`H[Ks6bgOj?F*W4]G'nR]H@C<iG]e.SH#\.MPg71`_841-]]f=o +7/m/br;H!$eb9%=s5[M=h;7$d>?=^RZIMfSC3"?4EH?"p`oPk3i8!&Ii8*PNhVR/GhVm)*O^([Y +Ff=$Phq>MjpAP!j!<2opnc&Of(B+1/rr<#sr7RmHVQ?i"WLE&MrVZNkrVm$"r;?QorVlfp)#F73 +rr)Gq*Z,sHq"t*cA/l[5p\b$jrr2lrq#1Np_kE`pU$MXUrr`9!rr2QiJ,~> +nc/Xf;?-LWfP+cc[E$D3b/hH;`QHEKb/VE?aN`&Wbf7WDbKnG_[oW\G'G;Au(DN=^`5Tg?bfn5N +aMu6=`Q$!AcGdi>KNqhj>]4_t_8O74b/h[&`rF-[b5]Q_`pq,hc,RrJdVt>ug>q-dJ>T<";b__W +e^Mq(h:^T;hqd>KgYq/KX(66jE,]r8@SY(8<*+I?\s6[ak0m5;ce,M?`5Ah'd)aS_cH3uFb0IoV +e^N[Jn*TYSR@pRc\A651_oKj9]t_;"_k1F4DgFWnXT$7d_o9^;^P3(l9kPr$Vn]dSe'u[^^VS"8 +b/_93`lt^-r:0FOp%[b"kiU.+_8X^Jc-XJ._;!GSbIC6sh;-dT9gq<dUW>u'AoMg1EH?"p`oPk1 +hV-WAhV7,Fhr!8Cg>'uaKhk$%B:[]6i7+`;cHF8H`lQ<Hbf\)ma;`.7^R\qG<)HCj>#hTAaj/,S +aMl-<aNVlJ`le;)+jJEacH*o?a3:"e&eMV$c-k!9%M9)ucHOJUb/VE?`lQ=$a:6;5aM*"!:/blF +l1k5Vrr3'!rVcHiJ,~> +nc/Xg"oJ?"qV1$/rrW/pr;Q`erYk\5qtpEnn'Y#W-QXE[)cHS1rVulrr;6Bhrr)iurqcTmrsR!@ +o'u//q>^Enq#'+M7eQf]oX'G6k1o(MX+GGYa55q0hrN_LhV[,Kh;$fFj4iMIh,%j0G'.JAF)4V$ +g;]V3BSPI$gtlVqq!Z>>^Ve1fs8VrlrVmE%o(UUlH?O.OK4ubQ%gW48!<3*"!"fA>$NLMA2dG>+ +b;M!d!<<*#r;[6H7@a#:`%iJF!=&T,quC%($4$V3"pYM?;J^Q*Fa&7_TBYqCrquZkr;H34b5_28 +s5RG@io]+Ig"#-:hJZ))FEMAAEc,hqfA5HCio&hSgtUWBh;@2Jgu75Gi8!)Kf&>ZEjPu8ps7cQi +rr2fpo)8^gq"amg&,Gtss8V]SmIBZ7k31FsrVlg"r;$-brr2rorYPJ0s8W)us0E^q,[pTMrr(1b +,:f2[s8;Hes8NA\l0R[/s8W#nrr3'!rVlNjJ,~> +n,Epsqt\O4Z17ems8N&urVuorrr2otrr2j3rr<#qrqlTms6\-**?Z.:+r!cMs8Doqrr)j3rr)fp +rqcTnp?7a@U84]acM.><rVtmV6iZr]s7NaTi8WAJe>\"BQcS%FfAGZIg>:`Bj5&MGio/SIg=oA9 +FEDS9FE)%hdb2U0J7sYngY:Usg\UE[^r4@<p&=nos8Mups8N&unA)i_`P]Q`AScF6I=-?aGC4aY +GC>*\HuF4?bfmasD0'rJH[:$dHuaCGQd*Xj>'"q/IWg9gH[gKkGBA"UI!9aaH+:f._nO%,\]+UJ +rr<#srr5@WcGf\Ps8V7hgu@MReC`:/f@t+7CiaZ5F`MA=<7fschW!JQi8!)Bi7m)FgtUcFg#(Q< +jOW;MgYh"LU]:2jrr;uqrUKmdrr`5sr;Q]q&,Pk9XJi5"WM?Dhp[S7ZrVca!rqu]ns82crqYU3j +&?cin*F/F?rqstX*@7!Is8;He#Q3PYSt2[rqYpKsrr)iqo`'F~> +n,G?Eo%g!ODn*p6aiMQC_Sa@8bf\#G_oBjFdF$1X`Pp!=a3`>UYW!(0&JQ2n3R5R`b08)Sbf\$) +`Xp50a3DE&<b>QBASmjN`QH*WaEPkGd*^%"E7<_#l.`4cBo9d_j42uFhUpW>g>Uf?g>LuEhqQp^ +Bm"Q?B6A61:"._0Nc8<Wj5AV<8[d*q]">bmZd6n;cI1"\`Q6<QeBuP%nE]H/c^Ul<[^j&dc-FGK +^qdY#\AP"j/oPEF7?Y.$a2Pm2a2`><Sjke88T$JDY-,XbfZM(F^WOjG`Ork(a2>.Go^hhMp[["_ +ma/kl`lufSccNAqj2fNc[8#B9l/:(Bd+cpuB1?QSFDZ/@Ci3/$gYglFhVd8Eg"P<<hVd5ChV?Z9 +f%/d/hr38Ef6N&#`QZ6>aND`Nb4!FOas5!I`Poj:aMYQFAm/&(9h\l(^:hn;bfIcB`lQBJaMuBH +b0'_-(!F\9^WP#i$m-3Te'uOcY6GRRGgk"/a9f\S>tn.*Phkm,r;Qirqu-9hJ,~> +nG`^krr<#Of_kaK!WN#rs82fqrV?F)rVucnr:p9boq3]X*ZZrPqtp?krVZ]ps8W,u!;lcq#2eA$ +n+,r,rVlonr8R]Hr;ZWjs4(oAiT8qXfA,<Bg>h&AjP/JKh;[AFhrWnSh<<bShJ$hICj1&=FDl+b +dGWpIg"tHBi8\S(rT(r8^r"\!qu6Ehrr2pDrV62qLj<iRJ::$9((1BN!!!$$!!!3/#6b>=1-=1R +k^5E.$Np8+%L*P346l_/Sj4A+"9Jc7r;Zm"#6b#+<WW7.*GotMHusX^L</ZUrVlWiqu6<CaR0$' +rq]UGf%]$?inWG:4@sa:F)ko:EH>r(gYUrJgYLrDgumSThVdJUhr*MQhr<GJhq[AOh;;?-p\=dd +rVlcqo)8^gq>(!h!ri)prr38^lL=?5o'4Wkr;Qlrq"ajes7uZortPJ-rVD*n,TnS_q"OgcC*4cI +p&Fp[rr<!)mcE]riW&rUq#:9ms8)fqp]#a~> +mf*Ihm\co2qYU9orr<#trZ(t;rr<#trVc`qs8N&rrr)Wjo^\Ls*Z5eF_#=<2rqufprXeu,p@t\[ +Tr4Zd\b#Ups8DuWr^ZndrVccHC>7V(guHr>i8EAMhUgiCgu7)Ki7QrKj5&JPh;6q"CN+$2FD>i5 +DEuP*hs8tOf\kZJCYAaK_o0O;g\q*NrVulr;Z6Ojs3SKt`50?uH!tT5GBnL[G^4O[H['XUJoc$6 +b/_JDDfU#GH@($eH[:'[I88/<d\1AkI"-*WJp;`nH['^YIXcZoG^b1Y]>DFu_niqOrVo@arVuol +fu*(Sq>^@kf@Sd5io/YHb;_q6E,fi0G&_S>@,'Pti7m)Kg"bcJj4rMNj5/\Pi83GIh;6oJhV-^b +p%eLbrVulrs8DHdrr3*"rVZWmrt"qpYH4b%WNW7fa85Z4rVlcqs8;]l!<)os'Dh\&INTUJ--Z,Y +s7p7F*[(%Rqss^kr:RgtR[pGLrr;ur!<2WjJ,~> +nGa[2s7=BRAsUBXb/VNEa2Z*<b0%fF_SX41b0A2T`l5p?_Z%Ieccspk%grRE'q`[faN2NHbf\#J +rl4rY&&lf,^N*af?X[bt\&$)+_r8ZG`llHHe?;WifAPWOf%9oPIc9)4in<&CgYgr>h;dJKgumPO +h.UVECNai9F)Gn^d+d%*ce7(5gXJp(g;pb<^::f'bK@uPb/hTEd+n0@jRhp)mGkOJ\AQG1a2Z?J +aiV]B[CFPdJ1bbEB0UU9]Z8(3^V@\(`hIer@Sg<-=c0i9]tr(3^:qY1aMkp/?c1$t]=IY+p@e"H +jN$''`Pfd=bf\8V]!'K1_o9b^cdLM$i8*#;`\g)'DK9f4G&_M:?J4,lhV$ZCf@o?BiSEDOiS<8H +gtLT9g"P':g=+A4e&oVP_oBd?bf\)L`pq.Maoof*`Pojra>L]9C0sq89itS!N5W`\b/hZDaN2TL +aN2NJb/h`LccsSL]>r<1(`<nuWQ2d#dRsoW#LCi;o#M-T[<YYC<cHOTqu$Kor:^/@~> +nG`gjrr;lJgAh3OrVlicrW<#tr;6L"p%a+j-XcfJqu$Hir;Zcqrs/#CpuCc-lM1AY!WN#Sr^Zhb +pA]lOg#_8Ll.b.Rhqm5LiSEVQh;@5Qin`8Hj5/_Sf5GYMEcQ/DDKg&D8"%o]inNMQhU#O&psmI+ +_T(m=r;6Bhr;HWp,l-AdKQ_3VLhJOf%g<+<!!!$$!!!-/"qUb]35Y+RhG,=&"9JB"%0d(Z27W2E +kBfE2!>Pq=!!30(!W2p-"q*M?FF/1RH\\9VpAFsiqa15XkfDlbqYg;eQJp]]i7m2B7q[$`EH?,? +Ec?2=>M@uiiT&bRio/kNhW3PLhr!ANhrEYUgudPMiT+J4p](9gr;HWns76-kr;6Bjr;Qcorr3T! +ipl[3q<77qs8W&ts82Wequ6WlrW3&trr*N0qG&.T)C0.ss7uYt-6OhLq!n@_rs7]MkMlL@rqQKl +rrW,qrqHGC~> +nG`mls8C9:XRc2arr<#prqcZnrWE3!s8Dip#4hJ9.jSEqqYp?ks8EQ/qYnO#Y+DSfZJbc[rVccR +r]pG^q#?)OfAb]Akh=tPi83>MiSEVQh;@5Qin`8HiS<;KeST5EE,]`<CisW<7@;WZinNJOhU,X* +q:3I(`6%BFs"+0Ls8N&trVc2r]u%_2_jY1MF*MnRH?sg]H?sj_F+%qO<k6Jr]iB#tG^4W7I/eL= +Hua47Y04o5J8KURH>dnSI=6HeGBnUeIscTkEg=\V_na1/`6J;]8,iDarr;o[`o6mms8JdXiSWbU +g>CCI@rlI)EGol<E-?)&g>C]Ej5&_SiSiPJj5&MIhV[8JinreNjknhLi*Y^Bs8Vons8MutrU9aa +rrE&tr=],,s7u]>Z*(+-Z_ajpmeHh\rVc`srVZKj!WW,srt4us)&Er-C&@r+r2UqY-FW[Ko)9-t +q;.s<R%W+1s8W&rr;Q?gJ,~> +nG`gjs6ZOjE43a,`W!mSa</F@`P]U4`lQ<FaMu-;_8aU<d*LCkf3Sjf3mYpeaN4>&qoB>kaNDE> +N*("$@qKkV^rFI7hT/sAc,\FHQce.@gZI)>fA#*9i8<;Lh:pcDio&SBi8WSMimr!dEcH)<G&;D@ +G"@qDcIUJ&hpfD)e^qLK_R[%od*'MN`l>s8`mEf=g%>44nEnDnXM;m%ccX;Lrl]?(`jiabR6#(c +<,OUO[_^#)_nWt*a2Y3A9ik(U?q>%1]#)"oaM,C-aN)9=_oBX0^U2JimIT`:m+KP<cGmlGbfS,X +`imD0`59WOLY(/6gXY$*5[nbNE--,BEc?,9=kMQahr3>Ji8<GFgu7#AgtWh(hV@&Dhq-i@f%8DF +bgFh]^VRq2b08#LaN!bk(s9q>`l5s=aMl?9^kQB*<Dct$BO8'Za2n,"s2b5_rl>r!cca>G`R**l +&JYZ`9$bo(duFtL&spYYo#M-V]q&8!9k1Hlqu6WqrUg,?~> +nG`dis8V?Dn,NFcrr3'!r;6Kmr;ZNj%fcG$rVQWpqZ$?:E8^cprr2os!ri,qrVHWnrr2p%cL(2m +m,@U8rrN-!iVlsXqu?Nmq"@kJi8*;Uin`\PhV[;Bg>CWDi7d&>jkStVhVI8F@rlX2FDYu?DJa?2 +<k@#@k2>%RSsB0KdE9ALdf'4Gq>^Hmq=sa^n?RdrGB8"P80nlOqu@9/!WW3%"9T/\3MGj:n>Akn +pAbX.$8Z,PqXWBG.MNO+"T/6#"9\N$rsB*>Ci=H?E.sD)o)&Fd6i?o]ouu"as7H?k:T3+(hqZ.E +4`YabFDQ2FCiF968_r=]hW3JGiS3)IhUpN<hU^0.gsk6<i7m8Fih;#$q#C-hs69O_quQ]mrVm?* +r;QWokj%d1m.9W*kPkJarquZhqu6WlrYPV4rVlisk:.`#.4$1_qZ$9+.NKO6nc/1Zrr35ekO@Wn +s8VuprrW)nrqHGC~> +nG`dirpm@ma7oQ3rr3&ur;HWop](6lrr3H*q>U<ls7u]gc#;M>rVHNjs8N!-p$n?CUSauecMRY? +qtpEOr^Qhcqu?Eb=PVcegZIAHj58_NiRQZ>g>_&EhUglEjknkJimqOXDfKf5DKK]1DJ`@`g>:uJ +g#&?dr;4j]^;%_]rVufqrql^(f"/H/a2Y0+C2\KKI/\I\H$XjbG'%qRG\*;acH2;\FaAC\H[C-f +H?sgcF*MKCdEBRFD0'fDGBnRaI!U!]H[L9eI<^3]]>DD)ah>U*n,<4brVca[p<;(bs7ZKl9W?n( +hqZ.A3GrnTEb]c@CiF968_r=]hW3JGiS3)IhUpN<hU^0,g="j6hq6i<i1>Gmp]('gs82cqs7-*e +rtGD1r;?Nns82T.XK&=tYGn/#p\k*jrr3#urVc`pru(h9r;Q`rro57E)'U.Cb4u#/^*FI1=7H7i +o)9*ro<P$]T!J4ms8Muqrq-5@~> +nGa*rr7u[-MSREZ`l?!9aNM`IaSa'Y`r<pk`lQ<D`l6!6]u7h3d*:.dUdMK8anNmUaplS;`k/W] +A78t\C66$Drl+r[iQ,3A_oT^?a3Qfgdad"1gXY07gtgl:f\P3<hUpW6j4`POh;%&B@WHF.F)5c; +D/=34<OC&ug=F^#Lih8(]Y_:kZd?q>_o0F1_na.7jl5:os7>U/X.uc._T)PnFND\Lai;9,Q<6sa +7oWZ!T>&Ch`PK:)bg+2FXbSQ46U50BG,)Rea2G^+_oKg=bfn2FaMl?5o^V,2q!74nl.sP'b0A#N +e't\6d*9&Eh)UhIcI:4S7Q>=.E-6#CG\h>8E_"m@gt^oCf\bB7inW,:gtWXqe(<@'gtCH2fZqs( +ACSfO^rFI8aSs?^a8j6KaSj*paNDWGaL\U"@9ZZ)>[C`\\A6,,c-=JTrQ,#]rl,hscH=,FaO%p@ +(D[u&#H?&#cD)3d$Tu5J`q.7X`l5?!:/+c@hY@*Ms82HgJ,~> +nc&dks8VuSj8T&YqYpKrrqu`nrr)lmrX\r(s8DorrVlios82]hr;6HlrVlotr;QKmqu6Tp#NFh7 +o'b`"s8N#rs5O#DrVuirs8)`f=ch%ef%f'3`j)8/U8bE;h:1Q@inrVGgZdMSgfAN8DKU#@D09iC +E`?FJb2h15EKKkjqS^7pc.r<u');M+r;$*Zp>;'`I<TgZ?nE?.p](a)"U##F5BZDkq;l!G%fQJ. +!W)j*$5PPFnbhh'0eO=T!W2ou!sJT'%g)e5!!t&kEc?,<I#G5uq>UC]rqcTjda@shs7ZHjN.%Xj +AnFnQE-6&>G].D>EGokpaQML=g#_5Pi8N.\K5".Q92JAPBOQ41It(p0CA@i/r;6Nil2ChcrqlTj +rVm<$qXsmghs^+*p$;>%rr33"r;?Hhrr;`l('"71pTP_^)BpCNAbGbl*?udV.fT86rX&N&s5W\: +h#IERrVlrsq>U-gJ,~> +nc/Xg"o[;RVsF3Yrs&K$r;Q`qrql`qrr)lsrr;m*s8N#trr2rprqcKer;6Hl!<<#sr;Qcrrr!;1 +T;&'RVRQ*ps8;]lr8@QDs8N&uqZ$4iNR$8+f\"`nZ(de`WNjJ!eE,HEhqm&>kM"qL<,uhlF)c/7 +F)Q5@;I<MKjji7-OSA_M_nO%(c2.A<r;Zcos!@HY^VR\'^5cT=H@CEoI=-BfH?jj_FEVYEIa?-X +`aEP+JUDfjrd4Zj%XiVQDH+NsccX=)D/a]Brd/""H['aZH?k'_I<Tsqb/_HA^;.P0rVZ]orr2lr +rR0-nrr;`hq2Bg'QY0o)@r$%"EHZ28F)c,=;97qYhq@,NiS`\DUkEJZ84ucQ6Y9\NFaSRE<G(q' +s8;fpqZ$Torr<#err2p5rVQKkrVulsk,GD\VlunqQJVZ@s8N#ss8;lqs8N!5s8MrhX;Mlh)]]r, +na`:h*#g"IrVHQbrXJf)eY8e1U#>nLrr2ipo`'F~> +n,G$4^h-rX`m)cJ_8*t4ccX>K`lZEKc-",F_8F:8bf7QD`5Km=aN_iPb0%cIa3+D&!Qi@[aT'E^ +bRhq:_fK-k?"%Dn[(s]!`QZH_aBQX*`5fs=e'U@,`RW;be^;:<TUVUPYJf2Dj4WAHgt19DgZ.$g +F)Gi:EcGo;E-ZS+>"cETaO"16dam9[]>V4jf#c+O`PBI3_T1-bea<A4mH)*LWjoaX^VTic.E]lS +^7At,AO\sj5('BOb0%Q7^;J:Eb/;;`11s!=:NJCCVS^?o^:qYeaC3B<`Qc<Fahu3qm-+36n`&3e +ccF8PaN2i_[^4H'aM-3]EbCVj=^4R.DffuBH#RYBDf'Gh`oZ(5fAkfHhVZ_TIq;AE92J>NB4,q& +F`UMM:"7eEaMZ-8`l?*Bb/hTBn&YLJ435Rec,[r<]qAkC<DZgt@oJo5`QHNQc-"&GaN2TJ`l5s= +bfn,HaNThW'+GTe%8>F+KEW,.((JO(`pq+T_i7Pg;.mQ5rr3#qqt0o=~> +o)B=$q#CBZht$gIq"Oads8W)ss8N#rrV?F&s8Mrnrr<#sqtp<ks7u]orW)lorrrE"q=sa^rr3E* +dId#$mcj?Cqu-?grr;!W=9&3us7u]pp\1Rn6V'X57T390CijT)=\2Vh`o5S0jQ,.ShTel9G'%M= +H>mkHCij\Uj'Z)->H.GorThVL`6@6@rV?6gs8Mrlp$ftTI!TsbHr)=*!r2g+!<W<1'/EDEnbi$u +3\(I7!!39-!W)k5*B8T;nakhF67WNG!!<<'!!<H2"98K'!<`lD=a4t*F*</!iV3BOs8VokqqB-b +r;?Qos8'KhSCb>>Dg$>FF)PoCDK0i;C7<`.iTAhHhQ^K`Dh*S*QBI>lO%)`/;Hul9m.^JRrVlin +s8Drqr:9jdrttY/qu6WqrV?']rr;HOnbMYGoBP]Bs7cEirr;olrW2oqrr3W0Cb$kYQmEq)8Lbc4 +)Bp7OpAOR]#lOJts68h=jQudD!ri,sp]#a~> +nc&gjrqaO,]);R-"9/5rrr2p'rr;urr;6Birr)j#rr)lrr;6Kn#Q=Psr;Zfms8N#srr`9!rVl`p +&cMY+h3"P0V4apCs8;opr;ZZPr^$G]rqcZpp%G4e5".b%78d*.CijT)=\2Vh`o5S0jPnqMgrrH1 +FE2)5G]%G@C3"8NjBl,,>H.Jrs6IbK^r+t)rVulrrr7E0^Vdn#_RFl#DKpPXI=6HgH[C'aF*`"O +?d6[8aKnicFFAO`H$O^^G^4XUI",mfeAoeSVd".`GC4[]H[9mZG'A1ZH$4CXF1'-+_T'O2^%_I) +qu-QmrVbQrr;Zfqqtp6*NL\S05\k@[E,f`1H>RVDD/#Egg>M)FfGiYN?qbKiLm49iOHGSl83]mQ +8]9lbqtBses82fqs8MusnbrRfrr2otrr2iprt55-_l]rBWNN+mZg[nnrr)fprr;usrVloqrr2p2 +qe%/s*KhK`+[RCi,nV%4,kh6;oDT7"r;ZDrStM^gpAP!ir;H9fJ,~> +nGbNGjd9Co_p$?J_S<k)cHj\T`lQ?KdaZ[g`PKC0bg"GS`l5s?aiDHDb0nPTe&ohSaN)??`l?*@ +b5KNqaMsrQ@Tm&HF.U@fa2>p@al1<B`l#m:^s19PfT8oh5X%A!:f;CMEc#2c7oQ/#hq$`Fj4rMI +btW/"F)#W=DfBf8GB5Li8jQKFNS)_4cah'1]Z/LH`l,m9aNVlWhqZiPp$_/&YbAG>rPANO0#><; +_oBa!J0nr'85EYeQ)qgCa1f."a3W)P\AYIW8nC:]?"QWk\Al_,^Wb!GrPr$`aMu<?[-7/Io_S7C +bNdQt`lcEDcIT_1d*'>FdFQm?DM#g.4)/n_F`q_?HY[M?CM0!_f\YZ>f%[?68o8s.Od2)mPEA@, +5"\X7\CT6]c-48N_8sX9rQ,#Yn&YOKs2Y2_rlkD^1q^DOB3JD7=B8OCYJJB-dEThQ`Q$!Cb/M9; +`lH6Daj/C7)Aj3D',)<I)\!f#(_@(n_T)2g%a)o7Z"?O%>`Rk@s8W#no`'F~> +o)B'rr;ZfOhZ*WOq"amg$2s`#s8Mupr;6BerX8Z(r;Zfms8Dors82fq"T88urVcZo"T8&hq#(-k% ++aY3me#l@s82fjq>UBnir8uXs8,^oqtg?j]ML=90eH*G0p%ZdNgc&qMfDm%]A2,qi8NCGEH5u=G +&MA>Ec?,BCfkfJlIYA!p](-Tahbm;kkY8PqYU<ls8M]UZ%@1CI=boY.hV[Z&ci%6!!EH1&h,B\o +(qn@JNXhZrW"t^"p4r1!rrT,$S+6po'u;3OuXQh!!WQ+!!<H3#6=f/!WWK82f<kZEH6>b_tX30s +8W&pqrYlfq>1'i2Y6h@ofdG=F)c;DE-H,@Dfp)>G-BKQf>WJ<A<;q;Q]mSqPaIeuQ8gl^1cSp>q +YgHls8VoprVlcno)AXg$2aPor;ZfrqY'X^rt+/YmI]o=o\TWJq"t'js8;fjrr<#ur"K&).3KjHn +L>S&-6OKU+<r=rqu?6d#lOSns8:pFkMuRA!<2ut!<2]lJ,~> +nG`^hl)CN5qtpBm!<2ut$iL&)rr)`jq"O[arr2rtr<rQ'r;Zfms8Dors82fq!rW&srr3*"rVc`o +rtGD0q=1J[TV/<^a8#]7rVliprVb^S6i[#Zs82WlqmoKR/1i;D,VbCGQB%DqQA]`c=M*ABg>:`> +L2V$JEHH&9DK'K6Eb\Zun*AWmrV?Kll,UTVaQE@!rr2our;HWp,2:#R_oBEW>&8D/H$XgbH$Xgb +HZsaXE)4X&cG[VHD/XlMrd+Ti(O1.JG(b-aEE(-&`Q>oSA8up@G^+L[GlDnQH$=^`Fa8.s^rF70 +_SO+Ls8Vrps8DoqlH/f"rr;ons7ZEeofR24DJX?6DK]f;DKKl:Ffs9Mf#388@ul_8R$IZ8&X\lE +PVtBS0fE=3p\Y!fs8Vrps8W)ss7-*grVccqrVca-p[k_lV6R/$W0kj-s8MuprVlirrql`pr"JcL +)'!#M,o7C=(E+/.*$^C=s8V]is8NK#rmIF1S#5THrr;rgs*t~> +nGbK>a`LpT_o^0H`50C6c-+;PaNMoZg"P*+aMYp7c-OPVaNi#IaiDHHc,\)RbK.iKaiDE?`Q$!A +rQGns`k$"r=]SsENP39O_o0a?b0&_bGK.eA_9Ks@g>&Ge,UY,m9Hl-MPE_#nNg,B==&ulcf\><A +fnXNdDK9l;E,T`7Fa%\$B@Fu4bh1=le^(h>^:_e?d)3lAa2uQQg?[JMmd]i-^Q>P3`Pf^3_oKd5 +^V@J!Y(SNJ;+X8c7!k`@^;n4(\A?5.b&P2=^8cT;E_o;.C0YME^rF.*cdBhO^VRn-bfI]@\C'g< +o_A%Bf\Y?(a2lEDbgXV0bK.N?bg+VXf%Jk2BlA$4GBIhGBl\$1Df'Qse(W<gK1TL2NffNeOcbru +S!00t1bC+*;2s5Xe'#qU_8sX9rQ,#Yn&YOK1s!h`bg"DU`PoBrDdcLF<)HgsNkWT\dEThQ_oBd? +b/M9;`llWH`lumD%hqsq&e,Qu)ArGh";Pgra2[_l&B`A8^PGKR:iFeNs8W)qrVcHiJ,~> +o`+pi.Js/7io^:@rqQ<gs8W)rr;HQnq<r`HAZkG#qYgHorVc`ms8Voprr<#rrr2rtquH`prri)i +r;$?krs@';m.9T's8W)rrqc`qs5EtVs!7LAr;6NjU+A\s/2B@8Q&q2qP+.MuQB@Dm;GM>2\>j@c +DKg'pEY`V<46QD<q>:-is4k`9_TD->r;HNiq>UCaqq-dVDf9oU66mQX!<NW3!X8W)!<<E7,t,$& +o(2G+7k5,P!<EK."98Z4"p=u.#T5P(meQ;;h.](f":525!!*'($3C2.rW")C%;'m,G&M_YVss]c +s8;oorTqMer;HTos82`opua\XFnp&*E,Tc>E+)X;7ojCeQ^O2)Q][Q!O-u,pP'0SP5!Co[og@7) +s8W&trVlcno)AXg"TJ;oq>:0h!VuTjrt"AZoC22CnCdjAq#(-ks8;]ls8O)5rr:q%-R"]MQ7O(# ++s8'T.@U24s8;ops8Vupq>Lm%p\t3miU,soo`+sfrquEgJ,~> +o`+sjs8N9#_5=X2p\k-irr;p5s7kr+ARMP's82fqrqu]nqu?]ls8N&ur;HctrVc]ps8;uuqYpL' +r;H9;R&-OTW3>girr)itrr(dSs8OA@s8;`lq4K0%4=DgD-'aRUQBI_uQBmYtO&A_pUpd4:E,9Z7 +pi$IUF?/O[s8)Zmrs%B'`PTjerr)k9r;HKls7sIN_8F:+G%>N:H?O[[GBe:VI<^-`F()6"d*9hJ +95SotH?FX[I!0j[F`r+ZH?*Mg_TBL'^2.S,H?aR[H@'a]J9Z?cH@1-fH,.P:`4a1,e,B4Ds82ip +s7"5"s8W#ps82irqWBkWEVseTE@,UAEHH,,;+a;XC-%ZJQB[c#Q^Ei%OHYcJ8h)nb1P>3`deNkB +rqQN`rW<#rrr)isrqud-rU]*RVQm>(Y+V6Vs8;onrr2rsrql^8p\t0K*?Z8[p6$d>(`=/0*[I'I +r;Z]pr;ZforV?HlrsS\oW2#fS`:s90s8;NhJ,~> +o`+sjs8PUXP@npA_9^?J_nj=5bfn,Gd)sI:;GE:oc,.EAd*U"\air#Kb/h]HaN2NHbg"ASaMu3: +`Q$0Ab0eARbJB`R?s-`CDRdU`a8s<%rlX6A-cX6J_TL$Ff%Prt2)cm94<p&MOd(rqNKfZgP)W:3 +Ei$7ECN437Du"B\F)PtH`R!/ad*U+h`4Wms]@#0SaMl0:`5Bs^m`OSSn+,P2Pc)(0_p$0AcH*i> +]tLV,6=F7p7TsmjO12^:_T9=#^W=7)]thCeP[%Eq>?"sX9m!;M^r+^MaLJgq^*ge6^r44-\b5gg +o^2/0hVZGubeqTHe'"T)c,RZBbf.`Re&s%IDK5Ys!HE&WD'j(;Ec#,Y846Bi30]_nP*:ojQ'%Q$ +R$2Ya,r@;'E7>i+b0\>Na8O$BaT'E_bWa=sb/_N=\"mV9>#S1!=')fQajA5Sa2>p<b/hQ>_o9gC +_91-:%2]Y)gNO>B)]fb0&eTQCb/_NE`llTFa8*dgb0/#DY?+Ij@%QNXs8W#oqu-9hJ,~> +n,EFGgA_*qpA+O`s8N#qr;ZfhpEM"9,9h1,s8Mlpqu?Klp\Fjgrr;lprr3&tqu$Hn"TJ>qp%SIc% +bTn/l1*^*s8W)tr;6Bhi;P,(q>C9mr9HK:VD:P.0NTYTPaRl'Q^F/,Od;Aq5[eb=@V9>"EGp!pE +X$](6-B*%rVl[<psd4"_qb"cqY^9grVuoso#ZuAG&;AG0H^c,!!<6&"pY5/!&5'+2O3OioBtk<9 +HF9<!=T&1!WW<,$3gJ2#nnt,m-O`EjOm-V'+G0I!!<H+!!EE+r;[T;7W3g2JUiB<k5P5Urr;upo +$HLqrVlcq"nhlM5]UrAE[Q*REccDCDJjQ<E&NT:R@0/+P`hW#S!K>.Bg"X%3j).1q#:<irqcTmr +VZ6crVm*"q=sa\qYg<k#O(L7n`fT?h>[EWp&Fsds7uWoqu6U3rMq.\,e!aK=sb=;,q>8\s7uWms +8VuprVu`n&H);#s8VZLmd/m3s82Wks8DZkJ,~> +nc&jnr2?+=p\Xjcs8W)trtP(t+!DpN*H1lUrqcThs7u]hq>^Hls8N!!rVZWms8W$1qu?]qqZ$?Y +TVSN_X/+5Ar;Q]os5<l(s7lKks82%@nt[p(67c%^/<lQhQ'[l*Q][T$O$I,q=^YfPG].G?pi$ph +C-]r?rVuiqrqk9a`5CO1s8;cmrr5Icq"sI#`5T^4Wag$jH?sgVEHunVH$FF\GAEDcaO/)MO^W3O +I!U3_H@L0bGBnFVIXu`\B#M=']sG:GCiacEHZaafGBNk4(k-m[GG)Rc`P]L*_=mp*qu-QorqG%1 +s8W)ss8N2qs4op9E;ji)GB7bFF)Yu5F)u7WM340mOI_]%SroJ-PF,oA3ug/Z81jQ5s8)`kq>^!a +s82lrr;RW5s8W)ts8;GuXerA$Vl?$<qZ$Knq>('jrr2lr!;lcq(]:3P&g"=UpK&LT*?HJiqu?Hi +rr<#qrVccmrXf,/s8D`2TU_OLo_SUes8Mfes*t~> +o)C0;qW)QoRCpJWb/hK<`lcNJai_NH":c@_#uK!raN2lXdDs_Ta3huJa8X'XaT'C"bf\#G`P][7 +aNDfK`Q5s,B4PFU@pY;5`r=-\aT'EAa=#*H`R3&W_A:X^+?)G6<$s8\Q^*c"QBmesPa7:m?ZK=Y +AnH=-DKP\oIrfaD/u6_:cHF>McG$d#\&[(NbJV9Bb/V?=h!<bVm-X/iOJ&Sa_o9L1bg=PM]XkJ2 +=\2mj91*&rAtZcP_99X._SO.'^qmh&]rZT>CfOnMA:ZarXh)O!aiME0[D^#"^r""+]AE#GlfR6c +cJ-[daMl9Dcd&].c,[cB`](r\`R_^P@r$(*F)c2:Ci"66DfKc7CMRp0D)6s.QBmPuPEVZ'T9tq4 +A2Z7X/"/$ud*pIbb/F7ul,`nIs3*^Nc-+2Ka250(?r9us:0LMa^WFRC`5'C4aNDTC_o'I6c-=S[ +KaeA%S_;CM%1jEl'R8?cbfe)Oai2<Bb0.s(aT'BhbJq):9M/<.f^\t@!rMWgp]#a~> +p\t6mqYpTQjSo0%rVQNls8Mrqrql`kAgSB;,:]epq#84Yqu-?ds7lWjs8)`orrW,qr;HWsrVH6e +rs%uDp#P/rl2:P]rr2cpr8IW%rVuosnbrAQ0ZQ@83a>0nR?<`"Q&UfkQBIQ#O#:fqG]mnEFED?o +EY3;5E^RtEs8DuqqtJOU`5^a2rVmT0qu$KloZ)N8HZa[J-lE$c!!3-'rW!T9!sTN"?K:tSm.K:C +5SO2#!!39#!#,P;!<<*#-UZ2IoC2;<b<7Kt!!*5s!"/f8/:`;4LP_:MVXaZc#Q=Z"qqp9+rVca# +r;6NW3d5K:E[G^BEH?/AFDc)95^\f]PF%YtPa@DnQ^X#%@nC/i:.\,Pq>C!es6BU^rs&K"q=j[X +rVQU*rSd&+mdTl5g].<Hr;Zfmq>MK9p\t3eE[`@fbl.D6E[ahYn,N7Xrr)cnr;ZforVZQhrX&N" +qu-Qph!FOerr3#rr:L#>~> +p\t6mr;QrukG,$MqY^BnrYbb8rql`i@j)I%*$qQ^p\i"Sq#'p^s7lWjq>UNqrVc]p&H2P)s8W&t +rpmmgX/;ks\b?"#!<2rsiVk2&s8W&eqtrc5`&oh7=@6qlOd)/sNK0BlP*VGq2/[GXFD>f9EbbAg +F`2>=6H]6+rVuosqUEC$a5[!rqtp<ks7lWeqs(Z)^r=3S>^CdBH@gToG]S4]G^4ISFNr=]aj%_/ +Bl\EHG]S+\H[^BcIX-6hH#dt#Z,45c\@&A2C3suJIWg$dKQhZeI"$NlH%WuA]<\cUUpTmrs8Mrq +rX\)Os8W)srr<#ts6)LdCN9;lrGa3%Ci=<4EH5l6Cd*0.PEM9"O-GukOHl2nQ"!3j2+p>.8G;oR +s8W)ts6]gbr;ciqrtt_7s8;cns8LfWZ)b"-Whc?Ws8Dlqs7lWnrqud;p\t3dD^6JRaSYf.E$\/J +m/QqUrr)cnr;ZforVZQhrX8c*s8W#XURn$Eg%YLGs8DZkJ,~> +p\t6mrVm?'n&AdA]#2b7aMu3<aSs<c`R)mu%LE%H+cFpnc'PH\d)a;V`ll<@_o'=,`Poj<b0%fE +`P][7aj&-1`sTJ9<GGfHATtMt`r=-:a<nsRcHX;Wg*@K>0.J_Y6uJBSPa7SoNgQ,qQC!XiDK9rD +CN=K;C\VmuE,fYIU;tO#aiMHE^::kc]un[Ea2uWN]>h\@m*FhZlKcESYI1s[c-"8N_8X@)\t!4c +?r9Wg8nCSNYf"Do_oTs;a2GU1bKJ&C[Zr[b@8p66BREC/\%Kf(^V\+?_na"#^Vn74b5U5H_S=?m +R`X%'`l,sBdCZs8bJqL"_`c&g`Zf),DfKi<EG]N.Df0E2EcH,@D/a>VH]s\UQ'RJqR?3W"Ru`b> +6!5a$0J+a&e&p(aaMu3=aN2NHmE#7K5KCskaN)?B^mSeB<)67h=(/MU`5p3G^W+@;aMl'9`m)KF +bf3<g'c4"#ai[0^21irtaMQ*Cb/qZHai2<?`VIRdai_fCSQ&6Z?F&bks8VrlrV->B~> +pAb0lrVm)[htmBMr;HHj(]XBh,pF]X,ppY0s792:;5WjVs8W)uqtg<krr`/oqu6Tp!rD`krr38Q +o^Ur#i;`iVrVlutqtp<Mr[.[@pAb0i?sPoS6s*o'15CpWP*)'"Rurl%P*CD\DK'K8E-#f<F80bf +EH64eg%k[Frr;uof#,GFg\(OF'`7Z]OMTJOR>[2\KNB`:#QtJ7!!3'!'*JON.6uJRo(2MF]K@YS +!<`W9$Msi'"oeQM#9cHgl1=N;q<"S<*!??D!s&B%#7hRh)]TnE13@JF=A(tU5f3*krr3Q-rT`/5 +r;Q`rrVZ]noJ1Q/pi7^#EH?5ADf9`?F];S3Q'[Q"R$a("OdM;sR"In9/Nu<DBOgc9pA=+RrVm$" +qtTs\rVm<*r;ZfbkNVR-mdo-#qu?Kkrr3N(qPkJS+Su*;s82Tdp](*gs8W'&r;Zfps8MumrXSu, +qZ$TXkO7[%s8VunrUp2@~> +pAb0ls8N<&qS&iHpA+UcrVdW5qV*/5+;Z+C_tsE';'J`1me$MYrVuflrrW2trVc`urVZ]lrr3?" +k*W$AVQd;_s8MuqrVtjU-NEo7s8Vk#><4W-<F8i\Ko_R`Od;K+Ocl,qP^Yl8E,9Q4EG9N7pi$IV +EH47sr;Z]os%iUD_o9^TqYgBmrr;kLLq2-[^pV+s]Q[V!HusaYG^Og_IX?<`F^NVGa32]MWDRAS +I=$6aH[L9jIsZQdH$amfHY.]G^V$nZYE2e*H$oU:.XuMbG^+LYF`MA5R=oHd<)-Uib4u#:rr;or +nDaKIrr)iprVulh137>QrG_^T-Z3jBEc5f3EcZ;"=d>29O-uB&P<=nlOHZ#_6X2*&3Zqp>oDeL\ +rr)l`rW<&trr2p1rr;roqYgHoqT#qDZ*1.1PeHhjrrW0!s8N#srrE&trt"o$W"p-fp\k-lqtBaV +s82cp#lXc#s8W#srr)Zlrr36&oXLNbT!\:lrrMlmpA]X~> +pAb0ls8NQ$ifRSp]Z/+:`l5s;aSs=!c-3['&/l&m$`)8&at<oSI`9LYe]l@V`W![n_o9X:b0%fF +`Poj<ccF>Q`kJQ[AmeqZDP=n``r=-:a<o*Na4Att77J^S3)3XW/V]=QP*)'"Rurl%P*CD\DK'H6 +DfTT8EqjW@E,TYGYf"]&`lH-F_7RCe\&?M5bKJ/K5Ws"PV67)D`m('3SZfB:]>D\1`5TKuWe)R4 +:cq6E;I!+i]Z7ds\\Z5`aEbV>_T'[<c)kGKCf484?>jghUV=RY_8X[6\?Dg&R?a,(NjO^V:-h9C +/YU>4ai2?BdDWK@bfIZ;^VS.?dMc_1DfKi>EGoZ1Df9T8F)Z#7F*)M&>*bD=O-uB&Ps1@tOd),] +5Z]0c.h,3@dbDgaaMu3<`lQ<FmE#7K)p$.Ca2Z0A`4:J4=]J<o?;Z6baNDZDa2Z3CaSs.$aNi,U +`5mK2"pNT&b/q]KccjnT_oBaDc-"&Ob/VTFa8*dfb/qcEZ#*32>D(c(s8VijrV->B~> +q>UWts8W)srr2pGeCXa#rqcHjs8Mrrs8Mrmrdl:;.3fldq#C63,9e9Z.WW>up%SLbrVZZorr`/o +q>C6l!VuZmrs&)PpZq)#kPkJ]rr2p!r;6EMr[.OBb"hV?2'b"P7:StPG*SDWRl6+gMjTZqOd9!G +DfBc<FF%qGE;4H&F*)=]j8]&Wr;QZkf##>Cj7iKJrr)`j=K%=0>#8F/F*(GS/L2DR'*e@7&eQ$/ +`U)p`rU8lp3#i,&$ksirqZ$X2'E.tm#VA-lmeQMKmG_M"%KQPA!"'A]00i--;,9qkF-NrRd`-cr +meZ\Tr;Zfpmb@U7rr<#ts7uTb3Gis:ErU5/G&q\DEcQ5DFDu5.3g>elS!9,$O=+h*R@08)Ma(NQ +.jud$o0fq[rVlcqnbrRerr2p#rqlNgrVlg*rqucqs4HW'mIBZ:c2R_ErqZTirW)orru1e-/14a' +qYL6ks8Dorr;?Tlqu-Qmqt^0is7lTnrsSW%s8:g?lf%mDq>9gaJ,~> +q>V!)s8W)srr;rhWhnePs8W#rrW)utrYkh4r-fV)+rqOOpAOg**ul4F-Z?]ioCi4`rquctrqu`n +rtYJ/rV6Emp[Z.iVk'rpanYc5s8MurrVtjU-N!hd:@r!N+>QMT@S/\(Pa@Q&2Mm]WR$*l"Q;pk% +E,fi;G].J;pi(7oF)*brs8Durs8W&J_8OC[s8W&srr<"#Ul'G+?#4VENb2mBG]@YIG'SCbIWTpS +=2i\4d*]bKF_GoEH[0d_GB&@_I=c`fF`DVQEGeXk]>:k[XK>W@Is6*hDgQeOE,B8u>ZOd)ApKE7 +YcW#2qZ$Qls8NZ0o]#oLrr)lrs7uWc3GWeXqJ[j)EH#i8E,fr>DJrlAP)tipP*(of-#&C+R$*_l +5$_;<,UA-87'ZLcrr<#ts8DKe!WW/ur;ciqrtbS2qu-Qnr:I.uXK/S+X-*&Mrr;cns8N#srrN,s +rr36#o-Y_cs8)Wls8W$,s8N&ur;6Elr;6<fs8Vlns8NT-s7Y'<SXlG<qtpEmqu6?iJ,~> +q>Us(s8W)srr;N6E+#<Sd)l:+!Q`F_a>qDbeR8at*"`>_cd^C<"q1kI#Z.,>bf\AQ_SO(+`Q$!A +b/hTA`Q63IaN_l?[YA$r<G-3+]t_V-r5eoXilELiajHe1ek7/#-:0k$7Q,=NQ]dgrM3X!dP*qGu +<E!gTEcH/GE,T[iE>ie9C+6[4`5om:a3_`:]X5Q#c,duF`ju.1&H2ZR$mo/!ApB6)UT(l>`lH<? +[BGHUCJ[>c8kNGSI'LN([&9^o[*ln4be:?i^<4[#KK=6P<)?k6HV'4/\%Bkp_6fP\Ea1se/1ND; +6;D$3KN)s@fZD+Lai_iI\CAgH_Sa10`R3*W?>a\&F`VVDDf9c=EH#o;.<9NODfB)EPED&tQ'@Pp +->JU/QB7;d3a#E))&7/B,)F:\`l5p:aNDZoaSj9\a?@S``Q-$A`PAck@oQ0%<b#%9]Z%n+c,RiI +aMu3=b085TaiDO9%Qi7__Sj@7aihl@]#DJ,cHXAJ_oBmBpW*ida2kcQ<)6M+_s$gos8DZkJ,~> +q>UHnrr2utrr4VJgtMf.r;?Qos8;fps8Mrrpa@F.*G/Snp&F`,/0#lU+<i9`ScAH_rVlfrrr2os +"8hlhr;HWqqu6U+d-gJqjjj5-rVulrs8W)rhu5#%s2mY]VDThJ>[^u(4aiNZQ9R?YOd26!P*M1b +@!-L5Df9W8E-$-sE[l-NF#WdkrVulrr:ngZ`5Lg7r;-?gr;HG!j5]Ucca0'o@n&:+5;t)6&H)Ss +'fSkOp\O7Vn(:&]%KHMJ(`t+0!!!'#%i6N+!!!3E1njF0n+lS?LGTPF#RU\U+sfTgMm(4QhVRSk +pZgJ+G.@>?qYpL"r;,m>qYL3jrr3-!rq]'$qJuUX!HN2ZE$B:BF)l2AG!qO`QBdW)RX$nOPF.?' +NfZn<@k9;mM*Nfcs8Drqs76-jr;6Ejrri?!rVZZos8W)urs82Olg=E2o%Ed9rrDokrZ;+7rVu`k +RO3^Xs8M`lp](6hs8)Wis8W#srVuoor;$?krrDinrs.WHm,[O5rVQ6eJ,~> +q>UHnrr36&s8W&FWNYsms8W'#s8N#rrr*c-,9IX9@9I@;s7C4V'c\&0*@2qurq66hrVm!!rVQNk +rt,/,qYgHop@+BETVSTikPb;Ws8N#ss5Er)rVt&,/Yb$H+';oW5!44UQ'OWoJ!$"^Q]dVs0jo-E +FDYl5Df0Q8q/?OYE,RQ(s8MusAc'rm`Q.?Fs8Duss8W"'h:h#Dbd<^g?qjKtBPMC*I<KjaGC4RF +e]u^adDimrF*`.XH=pf7H$sscH[9"9IslNdG@?TJ\Zr]MWGZKmFaSLNH>ZelDM"4S\A,Yl^:LYR +MK6W5s8W''qu$$Gs8Drrrr<#r"8P?$EVOJQDuOW!DfB]8D0'ecOdVGtOIV\^2`-Y`N1c/k8QfIM +.l)fB0^o&@rr2utrr)Eerr<#s!rW#rrr<#s3r]0Yr;-H>XKAM0VlQ93qY:*jqZ$Tprr<#trr;`k +s8)SX,(f=arqHHfs8MoqrVlcqrqufps8Vrnq#1j&rr)lln#W%MT>LR*s8Mlop]#a~> +q>UHnrr5^ls8VGXB5=oud*9_N`QHEE`lQBPdL?j#%Sf,R`n&C6((V/f#RV.QI+ulg`Poa7`lcHJ +b/hTA`lcNNc-48>Yub@7=_;TR_nsL7`r4!Y`o>&fb0/8/+r6=g*un9e>WOihOHl+r3.I'UQC!c" +Otg?eEcl8;E,]`9F89g*E,fhEb/M<>`l?*H`4`jkaO&,MaN)<6V#XFY5r()C/2Jk/4%j=8OK#t/ +_Ss-dHSo@u7QF"=F#9,m]sb"rB8!S6`l5d"IZ_On`k%jS=CP*!@:s:MJ?$)t`3-(e3[upK5tkBk +B5M-a=_D,DV<6@Ucc*l@b/:jBd*0AD#fOd+e(QH^CiTDr!-A-Z!-%pU,B.XCEGfl@6^!n'QBRr1 +GW7RDQ&;/kNCmA`.4?`m.2'_Nb5T?_`lcNLb4*LNb5]OHa2Z*<aiVcK_SM.;=AMsm>ucp!^WF^< +`l?*@`l?*Bcc=)N`6N]9>JS_/]u@_-b/200\\?J<aNV]Hb/D<pa:-&/`QPru@S]g*P2Gm&s*t~> +q>UHor;R'%s4lE$s8Vferr48Aqu?]oqt.BE)^Qriq>('coeI=+,TnNZ+<W$UhYd?Orr<#trr3)t +q"Xabrt5),s7=\.p@dM5s8)cos8W#prVtjU-iNi=4A'NM+?3J//iJ!?Q^*Cb7V\$UP*hAuI5G\] +Ec,r>EcZJID>A2aFE2XeoDJXes8W#mf>PYIkl1S]@/g3*roS%go_n=NoC;/(gV'M@>W!Q.!!WE6 +7ucp,q>^-LTK4(q!!OMg<]h?%"ptY\.O5i4!!E]_?g7(Pk3h371*6r+!?N^KbhqUNnF5f1mIU/A +nZbrXYNtZOrVZZp"RY7Fq>UBn#5nN"l:>o5qf;^Y.<0ENF`_\FEHH;BD+eW/P*hT!OF0>cCm^NR +S<T.#=(4TX/QP[<q>UBjs76-kr;$6hr;Qlur;?Qjrse/Zo(;G9jO!r,qu$<gqYpKo*;oj8q^nN: +rVccps82ipr;Q`qrVQKlo_ngdrr;iorr2uqrr35ojR;?as8Vrfs*t~> +q>UHor;S#@or=h8pAXpfs8Drrs8Muss7N`@'HJCOp\Fj`o.:Li)]'[s)%7Z0g\UjIrr<#srVQNk +rtbS2qZ$HlpW\kpV5gH8pAP$irr2rtrSIN$s7uUT7r'n#1fIU020bFSQ&.@fC65!LR$!_`1hq/R +CiOH6EHZA<pi$FTF#ELds8;lrCAZQ!`l@-:rVccpr;?QUBBJ"/i8;u/e]l1:T8RPrGBn:[HusCe +c,@iTb/KWHEd<%YF'!^/Iros]EH"K?F*r7_H#?Ti\[nrNUmG,%G]n(UDdV;Tf[\EqcHF;F\?<Z< +@_'Y\qu?]nrr3Q!kl1M[rr2rps82%NDf0N5rbj?,DfBW7EcZ8@E,Tc;DehpXPE;)qOH+WO88FQW +PF@_u5?1uS1b)F!o)&Fdrr)utr;H3crr30$rVQKjrqud&rr)fqq"_P,XKDK&".JZXr;HZqrr<#u +rr2p.rVufi.A6J6r;Z`qqu?Wnrr3<'qYU<brVu`ns7uX)r;HWpr;"1%StDkSs8N#rpA]X~> +q>UHor;SVQiGD_\]u\78bJV<Dc,ITAc-;Rc$lTu!d)X;LbngR$+;c.8'+YZY]$\aEaNMcOc-4>O +rl,hubg+YY`OUq*>ZP*@NP<ESa2Q$;aNDTD`o>&fb0J8b+#I@X)`:]%/MhL2PEUh\7V\$UP*hAu +I5G\]Ec#i;EH68ED"qu_Dg*\P`6#s?ai`)S_8*Frc,RbGbg"JW^5Dt^+s.s[2b..^@Sfft>B6FF +^!=`m?U7^K2*O93B3C_4\?DB.:f=:2ahb3G6V+/t`5Am;3-8J-;.<sQ@\CHT]s2Z,=#icH:f:=t +?sZZ'DeE1a\_bf\ahl$<bJCsEdEfeJ`l6BUb;3XCEHV8(.s5oQE,p#AF)l8>F)u;:8njNPR@9>% +HU(&7Q'7H%P`nC:@mi*r68Hd/b5T?_`lcNLb4*LNb5]OI`l5p:aiVfMah"p"?;scu<aJt9`59^> +`l?*@`l?*Dda-.Uaj/TKEl?2GdDsMNdEBJE_njO=a3VK?cc!oKq8`ubaN)H?\pRLR=DcU[oDa=~> +s8N-!r;HZqrW3&urVnA&fDkmMrV?<is8;fps8;cj>p1@;=S_srs88i>,9n6Q*?lXL+se]9rVlfr +s8N&u)>s:)q>^Kns8;osa7AlnkMlOAqu?Wps8;lps5EtWr$D&f8k_?9>\>iGQ&qGuPBB2^BpXjH +Q'RYH9lk2lE-?5BD0'Z<q/QU[G],gurr39'rVQHD`P]X^rVpp:s8W&pep[2fo_ngio'lDIlJg9. +1F!>4!#\>8o`+samG(5q'*&">+=t8g,SLFn-SV#U('=O:"<p=Rj6lErpW,!E%L*^t3PO_Lq"OFL +lg=6:rURp+NJO.aoDACas8;o`k4ncPs8DutqYS#tCj#Vqs)]`1EcQ/=EH6)9GB7V.:R7?5Pa7YG +93>8ZR$*]&Oc;P53%7m#I676%rr2iqo)8ahqtpBjrrE&tr;ZcrrrDrqrs\#Xm.9W2hs17AqtpBk +s8N!>rVlfos8Dkfd/O(Er;ZWnqZ$?is8Dioq=MnerqcZnqYpKo!<2ut#lEWFmbIjBrqlBgJ,~> +!WE#ms8N!%p["lTr;-?js8Dp<rVlirq,eOR*`D_1s8Vqm)]Tb2)&4&-(`OPBq>C6krr`5tr;HTo +)#jL2s8;c[QEI*_V6B^ks8W&srr<#sr;H-as8Vrprr;uss8=;Bom]J'3'gVT0eJWNS!9+Z6:YaV +NgH#sP\*X2DK0Q9DfKQ4DK>PlF)Q,644XB1s8Murr78g)_Wh!tr;HNjrVcZEG2_E3gXFWsc-4>J +`4p;*GB8"SG%.8mcd9bQaAm2'I=ccZ<7>#lHus@N?_:2/I"6HgF&Jg?\@SZLUHs!BFaJ1;al2.1 +eBuRdbJ_0.];J`?^qojHrtkY5s7u]_m/?k^rr)irq>@rrCiaQ7Df>Sn.W99FDf0K4E,'N8CL'Z! +Q'@GrQ!m6c<g&f2P+%Mm4C9lj;b29sq#:9mrr2rro)AXg!WN&squH`prtPJ2r;Q`qq;\W[VQd2+ +T==Rprr<#srZ_CArqu`or;Z]jS^7<8rVZ]ls7u]is8W)pr:fd)h#@3NrV?F's8Duss7b'DS"ZM/ +qZ$EjpA]X~> +!<)iqrV\YSrr;rdc"C%i`lZNK`P][=c,R`Bce:bu'Ga$cccaMZLC4k:(`*f%(D[`!%bT.PaiV`N +bfp(-s2Gqtb0/2T`3N?T>?4gC^r4IDai;<>`lQ6@`pq.M`qmdU`rF+/b0ADff4[-/2*tMZ1bOrL +QB./N6:YaVNgH#sP\*X2DK0T;E,oc8Dfb_oI<0UL0X&U>b/h]He]G\BZcg_9`6-9LcH3M1!%f*$ +)Bgan5=.k4@Y.ZtS$U2[U-D7K5<LqrE^Pb`\%Jf"8UM#"^;%(NBmr"&`Q,X+TMg2N=B\O@GsRn4 +`34G8:E^&d/ic3h:f1+i@;.jGf=g(rdDj/G_U-'5eBcH&`PKR;ajQh;A9;m8G'8"NEH,r;EH#i8 +EH,c;Ebo&WQ'Rc%Q^2)Q<E,'FOcu5tO$@/6-;H[:*7E0Url,#\b0'1orQ>/]6,pm``lQ3BbK.Z7 +SR,Am=&rX0Ge;&;b/VHBaMu6@bfn>S`llTWGG!%*ccXJMb/r/M`PTR;e'?(/Y0+W&a3)R%a:-54 +`l?'2P[I-_@BSkds*t~> +s8N/tq#:9m!rDfnrVlr\eE-]04T,*Nqu?]ls8VckkU%Gu-)CS>s82Xs+se<Z+X/3P*[;^TcMdeA +s8;oqs8W#mp\=[cqtC'inDEX&kh,n7"9&5srqcZbrr;oprr<!kr;ZTmq>^Kjs6i.V4'k!"93jK! +PF.StP%IEj;3mB6QBmn9=`JM&EccAFCi+B5BPMU,E,]l=GBJ"*T)AWfs8DljhSd@Omf!%[rr4hS +rV6/`O7E,Is8;]fnFZ>Fl.;4_+9i)o5Mc#1o_@[S1*?c$!"C85f75q.%i.>lc:K&ZrW"5Z3+Lk/ +n*oi$;)o0t.Rgl8nbrCco'c#9rUKX87ZrO]Ph>[.rVca`n`fiEs8W)urr;b/?#4Y%EHQ2@EaE!E +:0;@PFDc8BEc?,65a@\(Q^*\&@SpBuOHl0!Q'tWV:fq'X1c[Vgr;6Nlrr;Nfs8;orrr;io%KH@u +q>^KZjlu4&o^U?.rrDuoruV1;qu?]ps8ViXs8;`nq>UEkrVZTls7Z9)K./+!rVlimrW<-!qu-O" +hWO7jn,NFcp&BO~> +!W2fjs8W')r;$3-WP8-$rVl`p-MdZ@q#BFt)''fls8;omp/W+R(a0qB+Vtt9(*h!!s8N&ss8Doq +qYq$$s7<pnUoLGlj7N9Hs8;lqrUKmcs8N"$rVl]oq#C3js7cN]4g6qN3%IU*204tKP`h,=93+iQ +OI28sQ;CY$EGof:EH>l1F_bT&EG]T2EH#r;DGH\us8N&srqbHh`Q%6Arr<#trr)lqs/hLHeCE.L +c;;L#_Sj$rQXXuTG]?Krc-F;RaJi?_G^b'aBNjP_Ed)YGDb@`?DLHn]H['FF^Tk2OWi/d.D09r< +^>Ro/eCMmibfIZ-_73(A]tqMYs8W&sr^?_Sn,N:brr)iqs8$J8CNF?2F)>o9?!Brr=);erD09f: +DK9>QPEhK"PE84A:g9<JPa7W!Qr7-a='dL93'-^1rVucos7-*gs8)]ps8;lqrrW,k])Jc:WiW.c +o(rCarr2lqrZ2%;s8Vups7Y[Uqtg?hs8Vupr;HWpp@l7L,9MF5rr<#s(B4@5rr<#tr;-HkrpmCg +Su'-qs7cKkp]#a~> +!VlWms&T*pqY9ses8VcQQXk*F_Tg?L`59U=a32T>eC#3M'b?#Mbg4Yh6P1.J(CLWe',hr,(U)?4 +`6#s@bK@oKb/hTA`luKN_MDGs<F&t+]>r(?bf[rE`W!mIa99N%`Q$!ub#$0sb.l'7bgF_nf-m4B +;DT[k>W-\dQBI>lAP?0%Q'%K"Q'Y?ME,oo;F)lA<Cj'W-Bl\*0DfToDFDsTnbKe2Nair5W]YCu# +cGdZB`l5oHcGd(S!BVAE.PO.Z6:adS??'adU;+pD-"9_?5uh9/A>$$6^T`SZB,=dE[A\U8M_:(+ +_8X<sLgl*A;,UkM7u"UaFY#F!&JQ3>2FC58:.AT1.^nC%bNRX'a2Z-?d)<]Caih]EbKS/Q91ioC +EccJBFE(Gb8P<&uD/j?4s)ATgF([_'QC*u&N^I/K=dG&1rfdq]:g$Lm=t(pJ+O\`^b/ME`a8j6W +a:H80`jp+o=]SL'=\c?@aiOG#4N5=]b0/,Vb0%rJ]$SXAd)!`G`Q?3=_TTmFU2(JUAB`'4aN`&R +`lQ6@`llKBai)-+Db`l-LueI1s8Vlm!<7Q~> +s8N/rp\t0ls8)fprVlrPchIG="T/&kqY^?m2#71FOWtqj/b]#?qZ#;#,TA,7^k!^W,9%mSf_k^F +s8Durs8W#oq"XdbqYU<meEukmhr=Y8"TA>rr;QTnnc&RdrVl`p8G`Aap&FJPCFUlH>@KfW+deLY +M`[)B7VFrKRZ<`"PtPG(F)c5=EH$&H-u<"F@6egTDKBl@E+DfAs8;oqr;#6g`5V*@q"k!i2#d1J +nBcTRqu-<hp\=LUq=4FTgIa7F&MdVUnG;e>]0[q\!!!-9/2cAM5<'l<1sFNL*<H->-4(b\:>4t" +mGrU^/LNQ`lMgSMs8D`bo()\We6.liI=@4*o`+mhrr5CWm.gMYs8MlpqY`3_G&VJJDfg2:2C:7S +:O%#(Ec6#?EH>hUQ'RYuQBsaN4aW/YJs)7]PFPNP?=d@o0KrORpA=dbi;O2_p\b$js5WG2p%%h3 +n+cndrquWms8N#t#Q"K#rVuosqYpNpp^=Wd-Rp8`-78H\s7lBg!WW,srrhTHkj.-ss*t~> +!VuZhrsSf)r;5faWnI.DrVcTm+oMB9M]3KO.J*?7q>]"l*>BZs^ORFN*>KM7eGB.As8N&trV?I% +p%"EBW2?W,mJ-SUs8DrqrUKmcs8N!jrVlisrqZTlo`+ANBdbE>>%'TS+-r.UM`[#>6tSNCR#I;o +P=]"uEGof5Df0W@->HS>?TrCLCiO?2C1'd3s8;oqrqkQj`Q%6Crr5^krr;`ms5f93gs40nbg"PX +`4*Lq\P-d_Df]1)c-sbOYukdbG^b-eD-5of??'q#7_u`=Cj:;TGBS"F8$ob0V5e<<G'.Q;h;dGE +f)F$!b/;!7ZWFNN^V.ARs8W&srr)canGiFdrquWmrVn]dFDYuAD0'i42'k%O:3Uf$EGfc9DfKDM +PE_8oQ'OOJ4F2rUJWZ%YP+,<L?"@.k0L&UTp\k$drVbaTrr3Q,pu/E^Wii5!S]:U's8Muqrr2rt +2uWdUr;HZqqZ$Tos8W)ps8N&mpUGf!,T7RB+SGO0q>L9ks8N#ts8N&rs8)`haJGDuV"4H]rV$8A~> +!VlWms#U,Tq"jmbs8Vc8H=N&I`6HNL`l,j<bg4>Qc@$QC%M7".bfe_U)&3PnQD%as)'9_9'YDi9 +^r=7:bPfR$aMu-:b0%]@@q/S;?ZiKc`lcWObfIc@`Q%Dg"NJF"`lS/%;96eu`PKmC`n]*&=rSSg +<F%^F+IA7SM)g]<7;"`GR>mMsPY,5$Ec?#9E,TiD-YleB?pAUPD00lBC/ch/c,e#KbgX_G^UVM4 +`PT^9_oB]FeA@Y.,ss".3C6A48lA>b@W<cCW3)+->t[d_?#2fd[C!Q`Z\pG/8If3iME$fN2N,/Z +_8*UWJh;.T='^,OBVC824!+n?%Nm;a7SZ`VC2>N.h='UVlds8!aMuBNa1f[:aiMTFcH+9D<-<;* +HZ!hHAM>5[8PF8IEGo[nE[>[FBKDHEOcYck3b^X"MF;rTNfoKl9i>2)=Xb[L4J9sCaMc':i5e[; +`kJ$T@9-E(<_e=c_og'?`l5p:`lQ6GcHFAUb/V]Pa2cEFaO/Gga2a-G$lBTn*"^6+`k]pHb/VND +`l?0E`lQ*;^P,QR:28GTrVuWj!<7Q~> +s8N/rp\b$js8E6&rr2rqf@9d!s7n_Qr;?Nnr;-H`.O62aIf06Cs7_*c*@!93q>Kr&*uuLTmf3:b +s8Duqs8W#oq>:0jq#CB]e*lhnhtI'L"TA8qr;QZpn,E@brVlis9E"n`s8)`pf/e:22E,)J>q%^\ +P*2/"23<tYF>&WBQC!l#5\4tWEGp&>F)Q&$0d1%#LN7HSF`_\GCGkterr2inqVT90`9dEtqY^@u +q!HG)>f,h$pA!q=m/$AFp>s^p5VGH[pZh&9i@?W#$NU5-$8"1%o@$H/:R9_a;^2JK"U>A?-;&(% +j7(ou<^es\nFlVKs7Q*bn+->?d;",SH?+:ie+E\=rr2p"o'H2Mrr4#;s7uG*>]aq,C2\#Z4B,cm +Bk):(D09uAF`MM=2ZAs_R?i1aBKVHH7k9pjS!/ne:gREt0.S_-Y?(]'rVQWSrXJf$qtpEnmH<m- +mIfVnq>U^!r;?Nns8MurrtkJ1rqlQip]'rlKIJAs*$c[R)^ri+pAasf!rN#srVm$"hrX4[o)F4~> +!W)`mrrE&trsSi)s8CHEYOqShrVQQn*rQ'9r;Z@6*?-,JqZ$HmomR\n*@p^VrUOY@(E+Ucrr**$ +rr;inrV?I$pVE)jV5^ZKpA=acrVu6`rVulr9E"kfs7ZKhrVtJ0H7Lg/?W^P]2LCOKQUE]kO>Co/ +MjT`oPEA%=E,ff5F_u,8Dc\S6@7l5mEG]c8DJa#Aq>L<lr;QWN`Pfa^rr2p!rVZWns*j4GBY)[D +dF-+[aMtcs]!AnPEGfT?e'H=\a@:/iG'A:VFECXFiRqj]ArOL0;Jpi4K6VQXEbAjaXK8:S?"dTo +o&ec_jNu-#_nsL*Z>H;IcGRB2o`+sirr2lpnF6JUs8Muqs8;_0>B=Y%BPhWS4&]QiBOZ($Cijc< +F8p2(C,D-<PaI_^5%cs>R78ZlPF@YpKMPiW7P62G/$E"Rs8Dfoir8rW%K-&!^9"B=W3)nhjno)U +rr2pWrVulpqu-Qpq>^KmqYTs`nu[Ef,p*g@)BKP9a8G]3rr)irrr2rtrr;rrqY^<PVOa?LiqWKO +rqHGC~> +!;cZos8<B'rVcTis7EO3Bs"ncrQ6M.`Pfp?b0nHI(D.*]dE]_ZcXd=h%i<jJg"TdK(DIV.e]PhM +`QcO'aoKN^`YZV9`K4D:='0$s\\lJ2cHOGN`P][7aNF(p"NJF"`lS/%5KLdb^!FdGfX2u?*%*7= +;ckA'I$'MU68O[b1ik:.R?a)&P!<JsEc>o>DK9W6=>1k,987G,DK^/CD-IUqbPoR;bgaeI]X>i) +aMl<Ec-=JRbJ0r990YL!91(m.<`N12@t$a^J7p]B5X%tg1Q8EL]tJd$Ukg?a)`n+(?s.f"4dNmr +^r4'pUNodaBkqQl5#NOh/.DXh+WW%#5!i7SE`/[\oC1kglds8!aMuBOa1f^;aiMWJcGdmt7r`Wp +CMmrV3DWmZAmfXqC3"?7FE);923a>gQBQPUAN>g<6n":^R#m8Y9jM!l.O-/C(6^N*d)j5LiQ2&A% +E#lkH=0fR9itD$WPcjWaSj+;aN;WMbK.iKaM#[4_oU0Mh:Im(%MBEf)A3es'VNI[c-4GR`lQ6@` +lZHFa2Gs:TN+NY?H2I2p&BO~> +s8N/rp\Xsis8N&u"T/5bgZ8A6,l[Z;rVZ]ps8)]g`[)]K,K0QYs82@2/0c3hp&4X[=W]"5>l=U$ +'`S(2r;Zfpqu$Hns8;osbNA9\lfe<I"T8&jqu6Tp!ri,qnc&RdrVlis9E+tkrr;_,@ot*50je*p +2,0:#S!\a_6'mU.>"`[nS<oP*3,ESTEclGED0g#D2`j*71/i@9EHQ;H=F^/Ds8MrpqV]?1`9[Bu +qYgG"r:]R!O.T.nk4A<;l1+9:pA+=E^.)0l[cH`;iDrN!-6O9G'-f^rnGhm]3bmU8hG63L%hfp+ ++Wj!VLu$bCThJG*j7<!?oDA@[p&4pSk^dN'Eb'3>Nn*h&rVlfr7e5pBrVulss8Muhg-BOtFE;_J +?ntGo92]_HH?=.FEHQ;AD_dQBQ^F"1=C4deO%hZTQ]Rc*R>=(5@6Hq0BJb,(qu?Qkir0#Wqt^3j +$f^[Bn+?&+lMpe^s8N#tr#l";rr<#tr;6Hks7cBfqnI#"-6j]R.3fu\)^HMXq>^3brW;rrrqufr +j9"c3m.:7-~> +!W)cns8Dp)s8N&q^SSdFp](0hrVmr;s7lWia<)6:+2RmQs8)4+-QO(To)AFY<Z3/"=8Djq"oeK# +qY^<ks8N!,s7u,JUoC,j_!_(!rVlcq!ri6!rr;Nfs8Vuq8H&Sgrr;Y*@TOj/03hRg1ea'sR@&O] +6'[C(=@m7fR[',"2JR/LE-$#=CNsT<2*![/0Muq1DfBQ6<.+K<s8Mrrr85K3`U!O'!WMuqr!!*" +k-2O)rluD-c,e)>\$`]L\#iDJ<hR4VeAY=6I=d00MuJBL;W[6,[R+ZI_RiNiJV&Q+K8Ou"E-JX^ +XG'#DcfOENhq?o;d`BYV\]8rM_8jC0_SPsGs8DrrrVc6Ts8DurrVulsp=qlLEH6&CEF(@nD+[ZD +D0^2ADJsT8Df%1kPEqQ!8lo=mPE&<sE0cQTQ^82:4^2;V5qZb*HgUY/q>91Ns8NZ0s8D`HWirP- +Y,\&&rVQQlrr2os,Q7Q=rquWirr<#nqYL!!BdOrB)\aG6)''G4)1_M^q#:9ms8Dp,rVufnqtg?b +[A'@g_>!m#s*t~> +!<)co2u`aOq>]oHB7IM'`lZBIb/VK?a2Q?HUCe%F#+j,[c-"04'Fb7XdF?Ot7hcpP6.XN.b/hWJ +a8O0[a;Dq9^q*icA6<2bXLuKmbfe5O`l5j7`lcHoaT'9[aC`T9aMu3>c-4ba7n,oa,9p2d?SG*6 +Q(""g0gCt`:K^;*O.2H#OuI/qEH-)@Ebp#:GW%TDB/*;,E,]o=E_'EUa3;WEc.'nJ]X,T%bK%fL +cd0\Uh:BKY*+)0$9M%<8:0:_/@<HU7-!Mur9LVZd,D`G=bKe8CY*0ef&K2Gc061rW2PRsr]Z&%; +Z(HDLJRiFV!"2sS"9Ac@,UYE192A?0:Pdclm.0>fmF]S%aMuBOa1fa=aiDQKbfRf4.r0BRFEh_2 +01]eJ:MjlkEGfT3FE)8;0p@id*gMjY<Er.YN(Q$HP`;,sR#+"3?8t%m<ut_jd*K_LiQ)PP`l>d- +S7#W!:f^_"H,IQ!b5]Q^`\tlZb0.oI`PoX3^<"dVU/i*F&eb`s*>]:m(Ca`ocbIWF`l?0DaN2BF +aiMNA`j9;Q:LKdVp@\H9~> +s8N2sq"t'frri;rgtVc*rr`/sr;-Bl)ZKAG+sS:3qu$HgrOXHu-7@=Crr(Xs)'C02rqlitrVc]p +!rVrpr;Qupg?%kij8/`S$iBYnqu6WqrquZjr:9jer;HWos%<4gq!pV%1Ij8O=^GK5/rc6ZQB5NI +6B[[?:iS[POI);u2/mMSF)l5@EHZ8<AP=bVQ"=iTE-$)B7+V54s8Mrpqr,N3`9@-rqYgHoqciEf +OGAiVl1FcCp@RqSr;-?bmE/@?F3j(&COgnPEGT2tC3FqkiV<36gjn#<fMHs4C2.X%BP_^FAYQkW +HfM4#p%\C[q!\.Vp\=FIQuRk3Df^DZOk'.)rVlfr7e,g@rVulsr;HZooKR,5E,]`8GtLCrEbg&; +FE)>BEHH5@EAN`CQ'6>WFAHM5RS?g<OHPinPa?YX=^arT.64Y#med%air0#WrVHKm"7bX>nG`"Z +ec,RLrqucm+T26<rVlisrr2rss7j'O,:"NV,oe-V+XJL?KI.ujp&"O`!rMrpr;Qomh<aFYr;ZZn +rr7K~> +!W2lps8W&trr2p*m&?`8q>C3jrr<#prr3*!s7L:/*$J2Tr;QKh\0Dh6,16GjrnJS1*$2B^r;?Tn +rVuior;Zfrrr!3(ou!/iXJW#NrV?Hm!<)Zlo)A[hqu1a<qu6?\5(bRY1+-+.?Vi>4QAq,i?qEYG +Q!-q$4G&TYQ'*q@DJsN6DK0T:D/<]S/Z4eBCiXE2Df7qjq>C9mr;Z`R`PfaZrr;usqu-Hfs8UNb +]!tGbbK.WF`jE7aZ)O_2WCpW#XjP@3T"i%S]Y_\-`IG@-iTp'uflFR9\4s<Iai;*.aN2!"BSr'E +?-\i!kiq'`hpg?)`l5j9ML`1W_o9U+_"Rg.rVlfprU94TrVuiqr;HZqp-*53DJj<0G=Y"lEGBi7 +F)Z)<DfTf8D_[<;P`g,SF&$;1R7pU8O-,WiP*L5P=^juS.6"Crlh^Y]ir8lU%JB>.YH+n0X/DBM +r;HWlrs&H"rVuosrr2p!pU,;G*=`o-'c\;6*[+R6+!)Qrqu$KlrXJo)r;HNlqTkq/SY>BHp&BO~> +rVllrrVnVMq"X^=FC1QM^Ve.7cHF/G`5]sIbtel`$oZPVaMQ;j%0[4MZJ!RP^'k>\$Bi`Xb5TQa +cMkudaSs?^`YQ.C>[M,LA!XmB`Q?9Cb/VE<_o9X<b3I&B`lZ3DbKLr=*&o8d:KUgp.u]gTQ&T*? +5EV79:N/ILO-Z)q1iI;OEcH#<E-6&8A4nPRP[nWPDfTf519emAa2Z-De]YM9Zbjr4bKFbCair#f +n'U.FX;,\M9L_TI;-d7'>@hqh!Y>K-;-Z/Jf^/>+qt]mH_CIDI(ahQK8n2chaRo6"o^VM>hSro7 +=o\Ou+&O$_#SJ@.1Gh6c:h`R4^?4YOq<-2nfZM7U`lccM^!"O>a2l?DaZRhq.;!dFEGf`A8O#[_ +BR+61DK0]9F)c/<16@caOE*R*9Oj3O8lIC&O-,ZlRX.%s>t-1b.[qd+cI9noa:c_;`5KC#HX0BB +<EWO)Xi8B(b5TK^`ZE+=a3;cMb/qQ@a,aU;',;,s%i-#s()9)K(DI,!ao99p`Q$'EaN2EFb07uH +`k6t%9j)Pcnbr1]J,~> +s8N2uq>C6krs&H$s8VN=j8AoYr;HQms!%FAr9>aY*\!HQr;$Bh@O2sB8,rJ^pQ?UG+"mBfr;Zfq +rVc`sr;6Bk'%H=7lf@=1s8Durq=aX^rr;usrqc]no)A[erVlis!<2ut8,#e42C_:$?t!:s7[9.0 +O,Gr$:6^uk5Aj^rT9bh.1N@ARFDu>@G&;,ADJX/u<-`;%FE2SA7eZf\rVlcoqr,N3`8pdlqY^@u +nE-m&ItWt`iUcp6oDALcn,*"Fj1afjHJj[(K7\AqGB.\HJqleMp\"4La*uaj:lg*IEI)qMEH[P= +=DPbBp@<Cpq=sg`p\FO_nEm8_Q%4"&G']%+de!J9rr2pen*9cKs8N&urVZ]a?!q_pF`;G@DfKl< +F)Q&=EHH2?EcQ/>2i<ogQTo#%3/Eo_>?="=S<B8)Sr[bP=Bd[W-oY=!eb]=*rr;lsrqlZo$fC18 +oCVh6m/R+br;QKlr;Q]trVlfprtb?p-l=KX+XJ6T-7W&rlLj`t+=5Y9s8)]sr;6Bjrr33%s8Uj? +m+qU>qu6TpJ,~> +!WE#rrser)rVZWos4O*Go_JOcrVuos.KBAHrTYgR(F57@r;$Bf?Q^(/6iHlYq2lXA*%L^]r;Zfp +rVuoqr;Zfqr<iAjR%pLVV7?!oq#:9nrV-?_rr<#trcS8?rr)irs7T/<1akgo?!pkm7?`h)NJ]Vt +9p1Zd4`":jSWoD&0lLrJEc,o8FDG]9Chd`m;KlkrEc#l16hC6Urr;utro(i7`T6sss8MusrVuTj +ftPGB\l6Pc`kB*t\%/H=Y,&:od$IeOK9!=Y`PTO4rl#ti@GC)1kN&sS\@##@`5KO0_o0X5a/qs0 +T@2B;<n?@2gKiCZb0e&FQtX(G`66'/^:j.;rqucprVQ!Ms8N&srr;rss7'?$EH-&;Ec#Z4F)Q): +E,fi;Df9T6Df7LhPa@\"@raM`QB,3M4b&r`QBRhuD*D*+2+o;S=$kC2iVriV&,ZD*qW4obXfSJ$ +S&P='rqud"rr;rprVlcq(&*q<&g\A4*Z5q?,Z1H%o'[e@+4L&`s8N#trrE&tr!E9!r91)OR[i(0 +p&BO~> +s8W,r!<)lr3r8XFo=SXE[D'SraN2ZLaMl*6c-aTH'b(atd)s8RcThmB&1H8Xai\Z2(CLc#bK.rS +bfe/Nb0%fHrlQ+u^U%*Q?X[>cYJn5rai_ZF`l5j7`lQBJb3d:L`b!38dG*80)'p7e:KUk'0gh1f +T8n^a=A+jAHp2CO7\5m2P;7)qE-#r=Dfol5GAV,3?rM;cF)u>A@kuETb/MB>bL=SD]X>W$ccO8H +`5p`hnDDs_fs2E-=AVI\<`iO#@;&qP=>aMG!*1Ul_s-mip\".Gikd&t#RhCe"9;//-HY]Gnac,1 +k2b<p,mH.j3]mBV%g<Fi0/PR[9kRBnZdIn)naGkklIO%raMuBM`4X:9aiDKHa2ZBH7pGt91N@JT +DJjB0E,9E1DKBc9EH,r:2Mm]aPWWAn22.9S=B%A1R?*]%Toa%M<)t_D+t5o+XP_)2aiM69ahj`W +;bU(g=AaagaNXY+#KXp)aMu0=aSs@:aMVj$"<S?o((Urj(-[`!cdEUA&%9a)`P][7bfn5NaN;WN +bK%T8T34reB"%(&rV->B~> +"TSJuqu6Qo#6+N"s52W+rr3-!s82`lrr3u9s8/T4*%36"s8W&olms5%,cpk>s77EY(aFD*rVuos +!<)oss8;fp"oHg;p$(N9s8W$'qY9j_r;Q`qrr2cpr:9jer;6Kns*"5%3JfjS@Rsp59JBY6Q^3r( +GXbS.Pa@Y)@r4DfQ'ILgEH6)@G]%P>HZ<kFF)Z59F)c>@FEhItq#:<nrr)fli5NXQj88`Krr2rt +q"s?XIrKL^LMZ&DqXOUXm.9]&c[Y]^p?duYQ\g38F`V\FF+'?^cMmhuq"FN#X\Fh5HZjUWEI`=n +5[n3rr:Bs)MY[;Prr)`jo]X7sR=]d*E.34jNmdOur;Q]q)Xckdrr;uts8;flqJ'5SCO0o:Fa@_D +EcZ/@rc0B+Ec?)@E'/c<R<Ul?;c'$NPu1^RB9.".P`qE%P"T%c@5^A'0DPD&rW<#nr;?R"jlu=0 +p%[e'rr3-!q=sd`rVlosr;QZprtXB<.ifKR-R)]qkP"rPs8R$_-AML!qYgQorV?El$N0r(k3V^* +nc/Oeq#19nJ,~> +!<2or1&_%Kr;?Ti^88gErVuirs8N#trVcZmr1Y,F+X?.Ls8DcY-lO$HW;-5hoH54i+F*e_rtk\5 +rVlforVuorr;HN`c]b')VQAGFs8;`n!<2lqo)A[hs8Mrr4T>*:2hj@I?UnL/9.sD0Q'@MuG=>A* +P*M5!@;@u^PEV(_DfBZ8G&2,6H#IG>EGff1EGoo8E-,SdpAY'k#lal&i5N^Thtd9OIf9<Gp](9I +a2>[+Uhdrd`4*FaYI_3BRo7Y[b/8.-\&,hi_8O@1_S3^$^uXY<hV6j_PXhXb^r+(+^WO4#93+dA +h9OK9D;X4*da6@ebK$qq]Y;G)]u@Xu^%;7&r;Q]oqX!VLrr;rss8;orr+T>QBm=K2F*M;=EH5r< +rbs6'E,KZ8DE<?4R!1Z;;GWgJPYbLNAr^e)P*(usP>#7f?Sjns/bo/#rr2p/q#(0gq80G;Wi3"t +V<dsUrr)j=rr<#tr;?Nlqu?]N+s[m8*[2Y*WT<^OqZ$M/*$9b/r;RH0rVlisr;HQir;Z`g]V1mg +]_h^%s*t~> +s8N/tqYU6k%/oqmiK[u'^W+7/aiOJ*3Q/_Kb1)7V%2TPoeBQ+W`!lqZ$]EEVd)lS'#Rsk[b/hoU +ccsGKaNDTFb08#J\WBTi@pj)@]u@qhaTBN(`r<p[`lQBJb4<XRb5]OO`l5p:bKeDO*cin\=@-4o +7kIl,QBd`$F[Jr"PEqG%@Ve2bPa%:cE,fl<GAV>:H>mYBEc6#5Ec?,<EH>JMd*0_S`Pm>Md`Au2 +\&Qk=_T'O0`QR<1f[f$Ggn-`F;ccOg93,bA>u1N#853)!.&b_bp\XdZmH`KC1Ed>C$NU_o!(83H +m.^DMnE0,kaZUgJ9Jn+[!rsYT#9,6Q6;(^+5f27@m-4-3kKiGEaMu<@b0\&<bK@rIaj.oFajj?k +FDcF2E,BcFB6%p0D#J?%E,ff:Ec4$kPa6GQG#1o%PEJ[B6=c$l:R@B4Q]4I:>@9<J*u<ALb2LDI +`lGp9bepi.=T2&`<`ib4`QHEIb/hTBa2Z*:`lZ?Fc.'B9*"rer%g>"Q`QliKdFVP9'lDIG_8!n- +bg";OaMlELbK@oAZ#WZ=@?BL?rV->B~> +rVZQm"T8<"dG4a$"T8)pqYL-is8406-6jXKp&Fshs5@Q@,:;jUs7X#K*@2rWrVc`qr;Q`prr<#q +r;?R*e`QGgm-OcPrVullqY^6irr3-#r;6Bho)A[equ6WqIJQ2q1+l=.>[^`"EflWL?=f@294LMX +QC)t_G#2>,PE.M=FE2A?EH?;ADg?8@E,p)?F)u>DEbAMOqu-QprVcTN`PfaSq>C$crVufpqWb/6 +FE;_aG_=u?m.U2BiniU9f(Jt8nD[\LNf/U=GC"alMP=n4s8Dutp[[l_Q<937MM?h<MMd7-?#cY. +mJc\ELsPnjr;#gAfV1d&JoPRBG'JCgO4<h%rVlisrpAqGrr;utr;?Tmp0VBIG\M8CDK9c=GA;GA +F*2;AFDl8BDa8c:P;mE!23+&gP5\Jq>`X=`J!Z@fPCZ&+>[9!F;`ssUir0Jdq"asiq>UEbk4SQE +q!HQ0rsSc#p\=[drVuosr;Q]q(B4/'+X&=V[dWnes8;oqrqO#I-rKd;qYgQorqQHls83'#p#G]/ +hZ!QMrW)tK~> +r;T^prVc`qrr;8YVq^nErVccrr;Zfqs8Vrk7NrfjBCc'"rr:kb-QXJtqZ$<$+W;LIcMdbBs82cp +rr;rqs8W&qrVH2YU8aoi]^ksts8W&ts8N&srr)lfrr;uurql^drqJ]B/h9S#>@:MsEK?<E>[rq+ +8n(;SPa6PWFA>o$Oc;)5Ec>r7DfKl9D0Ki8DK'Z7EH,o:DIQWAqu-Qprr;rT`Q#pQp\t2<rr<#t +s8Ufsai2'/O)qtI\[T)XZ*1N*X38i0_nT)_]=PYj^qRY(^:J*niS3DMg"+f(8X6Qj^;.Fq\#t9] +>`@:`h8[<DZJ=$]e'6"QR7b$(_T'X7^qRV"p&G'jrr2lllg4ZNs8Duqr;Zfl?Y!npB6&*1E,Z\8 +G%l5=EH>l9Ec#i:D*E?2OuI2r1l[icOoA>o>E4+[I?fq_P_)8.>$EL;:cnLOir8rW&,lP(s8:ZX +Y,\G,XI%H3r;?QrrqlZlrso#,rV&c")'a")mIU2Rqu6U"pTth^9D/5]rt>>0rr<#srVZHgs8W)I +St;7Ao(E$5~> +s8N/tqYU6ks8=qKaDYXV][+O5aN)HJai)';b189`'FmmacGn#Q\O@/=#Kk?=bE`PE'b%%a`Q$0I +dEfeNaNDTFrlPbh\Qr9A=(Zol_o0^?a2uI%`<F9&b08)Po#UjR!Q`:[`Abf]daB9i+s]W[='SZe +Dig3F?"B.,874lNQ'Zb[F\c,(P)_;9F)c/;E,p)=DKp&<DfKl;EcQYKEc#&Je&fYO`l6'JaLSpm +`mDcA`l5g4bhD7,g$&+seV?D-BO+YA@Us+c!('%:5>Gc!1o/FYmH`lojijeN*u"tf!<jK4)%q_= +dbj!:fZLRD1Dq0"-87/9!#Zag018T>@oP(piplU2o'l58dHoK,a2l9Ccbd9:b/q[QaiMKDaO!Fa +DgQ5?F`DJBE-,`:CN=N4FE;>@Ec+*iP`Rb;DDI-8OcTK?'NpBA.>!qMQ&L)S?!Ubd1-HW(bKAkd +'#qo.b0J&I\<(#t:/"bl:R8i<rQ71B`ko^8`Q$'Ebg+Ve1(k?A?'NCRe()XZ^;\9e&/dRZb/(g0 +`lu]MaN;EHcH=AS`P%4,;,V2Xnb`(\J,~> +s8)foqu6osr;ZcLh#IEPr;Za<s8DutqV`_@,TsYtrVufprVPf<K_kZIo6);s,"qh3q>LNsrV6Ej +rVm#Tkjn'"rr2utrVQZpqu6`sr;?*as8;`m-NEU%0hFK8?!pS\9U(j/CGKdn?qjisPa.`#A4pi$ +Nff)\E-5f<nT&bpF)"MJrVZ]qrVcTN`P]XHrqcHfqtg6gq!P\DG&qnXO?HL*cK+<Tk23A#pAOj_ +l'Is\<I0O.L6@RXQ="R4qu$<iqtTaMd>Ct6KoLppAR(kdh0.fBnFPnoETQQNba)a*?'^(c:aK"Y +Fa\_"eF`e>rr2p"kj8*DrVm'"r;Q:t>jcVaG]7^mD3p)=D)I9?PF%J'?XHQoI6'i]QB[Z"P!E8Y +@6#i4pAOsis8N#rr;Z']&H)>#s8W)qqu?!Mq>KXEn(%F;"8hohqYgF7rqu]os8DlqN[#fdq>C9h +s8MurrVlcb,T\Djr;ZZnrqlZos7u]p"Q8h>kO&6J"9&5urVc_G~> +rVm?+rVc`pq>^E>SZh_`rr)lsrZ_C>s8McL+rMC>[Jp.)r;QTgjGAH_rVuM4*u>tiq>L?nrr2lp +rt#).qZ$Tgc^Lc:W2SVIrVlcqkPkM]!<2rs./s2En38Np3*]]q;CP5$Pa#l9Cm8:#>"Fg?R?(fK +D)[E7Kfj6oATmT_&TM`#9_nYcs8W)urSYZ5`ROh\s'Xj(`Pf[/\O&W6YdCaE\$(<ibL4VV^NYXW +A!3sP\A5V]Y@(q6l/URTg=t3+[Wk\iS"lEa@o.ogYYrQpgX*d?;pjIQ^5ur%F1o<5\rsVD_Sj.& +p&G'jrr2lmk4&ELrW`E%s8Vb%>OHG^G&D=gCmKl9Cc%';P*V8#?=$?kHoONVQ'7N"P<`;V>rF*) +pAb*ks8N#rr;Z']rr3Q,qYpNprOo52Y,\Y+SFlaYrr3*!s8Dops8Ms*r;MQo*bb6Cs7u]nrVlg$ +rTkRA,MDtmrtGD1rr2rtr;6Bis8W&mTUqUGc2R_B"9&9"rr)kI~> +s8N/tqYU6k8,*&RTjDN@`luND`lQ<FbehB>b.eT$'+1,WaiDEFeCV`W?I-gAbZPJc&iA%Y`Pp'I +dETYJa2u<Da3;Z;PZCjk>%F>@`r*s[aN"4u"ieX+bfn6#aT'B`aN"4u.*0Z`d3p)"2-X6i:a\o" +Q'H)=D3\C!=@SL=RZM#ODE*W;L-9HsAp<cbHuNn/3Rc0i`l?!>d`Au3\%0u.`Q6-;_SaUQeD'E[ +lf-5[1/i..An#Cm2ulTA6:XNQ(dA".VO5]^cGZ\="99AM#Sn9u.S38['hX.GP[d`B9laS@9f"Ii +84NY@5>G'B0.LVYir8;Viq<$Cl-o"NaiDKBb0[i9aiaV(#0Fj%b0<R[rcA*Z!HiJVE>Wn<E'e<( +L,E^$M3a6fO@3>Y99XZ^8!9)7NY"H_@9tZ)0[S1gbKIuJa2Z6daAg0s`QZTN`kSp"<DHCf=C,(@ +`l?0Fb/VK@`P][7aND`Kb1CJ>&lmZ5ccOY`bJCm.bKg_3(VIr.^;It7c-")HaNVoRbf[r>[8p+$ +AZ"\ds8W&os*t~> +!r;`krVnSNs8W)un)a*>s8;ckr;?Qnr;Z]pqg]k4,V&6^r;Zfrq>^Kls8N#on/rhs*h3!*q#1]u +r;?Tpr;Y[AjPoOqrr;rp!<2fon,E@bqYhi=s)0>I@V&nI1dRFiPa+fuH&kp+CcRWHP*)8!BKCX4 +HTc"aG&Qnks)\fe:AXtgrr;rqqV]?1`7Y+drqg'tr;?B[^4glVG^G*tQ#KK0Nk3<dDY!N$p$ppP +oBt\&<D6Xo@7O>9ZCUF\q#1-ep@\.Lhm.N<H'5i!n*KhhG3J/Zo&>CmJl,TgM3=!FCc`dQ95\ut +I>ubKs8Drrrr_KOq#:9ms8E0!rUjN)mrBmtC34JeCQs917qn9TR?Nt#BNe,pKf;8@R?a/'R?9X@ +>Xpt?bkV&6rVZWolM^k_q>:0k$N'Vus5j(KmdKYsrr3)tq"OacrrW,qr;Q^3rVPG!+><<`s8Duq +r;Zfqs79>G+HlNrrr;iqr;Q^&rqQ<hs6T%BlfJ$Dqu2*~> +rVlrsrVc]p#5>Hub4kl6rVuos*rH!6s7q$`)BL3jrr)lsrqQNlq>^HnqX>LF*?(@?rr3*"rVc`m +rser+p&1Y]VPpZ2nGW=brr;lp!r`,sm/Ht`./s2@s(j&A?=7&=1I.1cP*8BmGE#O%CH.BBOH5hn +AiP4,GroSYFD^Jc&7nN0rr2rtrr;rT`PfaGr;QNl!oUl2rkhpRVPo)H<cXk5[7&-\f?(t>8_i4Y +OBbn*B66sIZ^m3;k2"eFgXXa#cc;u+?#+_T]"kScQW2PbbJ^l%NeCSJLT%`#]>UbAMn$dH_SEt[ +s8W&srr)]UnGiFcrr3&o?XE2?.W9!@ECXc-I60o3Q'I`"Q98e_9Tt,f5'<6WR?X/&4'u&W3]bL\ +qYpHkrVu0^rr<#q!<)os$f7ncWNNM)QgF>@rr)lsrVccrr=/f*qV*24.e!97rVuclrVm&j;^`ND +p\k-jrr<!#r;6Bjrr39"[[s%_]D_^-q#>j~> +s8W,r!<)os8cAPdkC$Qg\]E";`lQ6Db/;?;cd6)6'G;#!d)<oFb0&>edacR_aNb,)'Fo`?bJhHE +cd0hQ_8s[=aNDW=_.?tP<+C9_`lcO)ao]Z(`r<p\`lQ<Hbf]Ou0ZqV`b/VE>`lcWVj&m<V?Y!JA +0g:kaPE\TqG`GX#Bf;'@OcZ%rB/tF0H9>e]F`-_hHuEk/37?$i`Q#m=d`Au3\$j]-aNDTB`50IE +dbscblKdNQ\TTka6=jnU!(f.B6qooH5U8!)(,/]\=>;"2-ib;##T+X+,W81m>uNF(4A]X.BN8V4 +!(K"><Eft^*sjN6U;PjIo%hU"iUlm<lI5+OaiDKBb0[i9aiaS'#KF['cUV,ZF8g1YF8'Z,E+sB3 +7;.g13CIJCPEq;p3b;AbOb,DSG*J&MN0TMjA6V8N,HB)2aN)<BbKA&oa<&@=`Qc`QaMYTR>#e6s +>ZOS%]>;J-aihfG`P]U5aSs=:aiq7'$5V"3a2cKMbJh94aj33r&Tc.5^;It7bf[uIaNVoRbf[rC +\8G2@?&@J0r;HHkJ,~> +!r;`mrVulrs8N>_kl:\^qu$BjrZD%:s7l=4.3Kdis8Dusqu-Qhs82`ks8S<2*?6^"o`+des82up +r;Q]prrggHk1ntqrri?!r;Q]is7$$fr;$=<gc@8p>$YDj6>i$TQ"3?GI[!l:F#9,GPFmqn1e)PK +GsQXpEHCYjF`_eB:&+bfrr;rqqV]?1`7Y(dqu$BeqY^0[^kmMdH$aXfIX?m2FAk_XQN-sZmH98J +o_\1NkMaRn\`2lIbCf!Sp\b!iqYBmWlf@*fkO8'2lL4<*GLZ$Qq<ZZiGE%9,K7J/\8.Ph8:2tW# +I>ubKs8Drrrr_KOq#:9m#Q=]#qt=0%EU[uqE)^Rk8o0`A4>;kaP+7c#3,DhoPDD/*99>@%Q'7Mr +10n.4/5?!?rri9!rqlTWrr;m+rr<#tq>^K]o(DA:o]599rsAAls8DutrqlTjrr3f2s7[o`-+s3S +s8W#ps8VrqpT,\^8H&MarW<#pr;Q^&r;$0es8CmFle249rr)orrr.E~> +rVlrsrVlcq"mDSSkP>,Vs8Dp<r;ZfloGo+n)he1gs8W#rs7cQjrVZ]qOs:e\/+)s-rr`9!rVlfr +&cVh1rVZHPNN/tWY1i[Nrr2rrrqZN[rr)jFrr)`J2_e<7>?`jJCm(*J@RN5(P#>>!0TqT]SW8I\ +6ue935BUp`EU[oLEb7r;rVm9)s8Clp`5U:*rVulos'X]s^VRe*^!+C/_6A]&8S`S+e'Q+MA$+MF +g"=KbZEggY`m_)5gZ@8Hf\"QuccO5Oc,ml;^V77e\#i3,ahbZtYVD-G\[]Ae^W3mJMi5'`aM>a1 +p&G'jrr2lmk4&ELrWiE%s8Mdr@W1aT/oFU%Db4`.IQK3DQ][c$OuI/\9Tk/h?V6BBQ'RZ#OYL'E +H7MYbrr<#rrr2fllMge_(]F:1rr<#k^9FcAXfA&)p](9ls8VrorVccrr>P_4s7IWU+LqCKs8Vun +s8W#sor&rJ6i6l_s8DrrrtYM1r;Q`rrqOj1T:_tIr;?Qorr2rsrr7K~> +s8W,r!<)os:&F\]csg.Q]u\F?aNDTHaMZ!=`mG#0'+J[,bJqB6`QZ<Ka2Gj7cZp??%ij!;b/M?D +c-=DK_8aL:bf@]8VGCc*<b%N1b0%rNb/h[%`W4*Yb4<V-b08)P`l5p:bgG(Z-7Dbr?<f9PD3L<N +@mrG,P>P=t09_T_Sr\[`7<4K75^%-dEq+/LDgGeMd*9SL`l6-LaLSskZHph@bfIcC`QHi_iqMj+ +n`]K#d`SkJ="5O(6S:Ml=TAmP()8Jb9h%B6@U<Cm!%f#j%i?`H1d"-"?>!q_@UiYA:K_0-7ScTO +=(qe^YeeQ=l0n6(^::i=oCD/,cg99*a2l9Cd(R08b5TK^aT]Z(cp:iSrGhgXpMhg(;.j`9Bp!d' +/WH$VR?<RgBj"&iKf!(+MiEdZO-Ytf?<;"\1=japai;EC`Pq,`4N>:YcdBtX`kS]s>#\L&;bqVN +_o0L7c,[iC_o'L8b0&#Nccun'%@bPY`ll]QbJ_*=cArbO/_%bU`Q8&$rl>bqbg"AS`l,HI;c$G/ +`pENurVlfos*t~> +!rMopr;R$$q>^!DlMph^r;6I7s8;l0+!VpQg\^pKr;6NoqtU3kr;Z4V-Qj^Qn,N:]rXJf&r:g6g +s8V!?o'55frr<#rs8M]knc&RdqYhi4BeV5H@UMPP6%+iXS5*ETI[=AADEEo;T95J-4ZmeLHp2@d +/TgN'6?@<d9_\SerVuipqV]?1`7Fqbr;Q]lqY^6__M`qlH%'OLBQ80IMMif=hXC@5n?[fEqtg-e +s8VfZk4efGj_j>XrqeAKqt^'dq<R;7oD\=Np?q>=cZ&1Ao])6%OFMb,F`q@n&-;nH;f[)$HApAG +s8Drrrr_KOq#:9m#Q4W!qY+!#EU[uuEC<Q>7rjlL2+!UoPa7S]6Yp.-P_M28240_mR$3`&KKi[2 +9K8^<r;HQls6'C]r;Zcsr;Q^#iqMd*q<uE(rrW)lrr2p>r;$0cs8W)tr;)'j*d%AZrr2rrs8;co +robdQ/D^7&qu.-(rr<#tr;$6es8Us@lJ)77rrW0!rVleH~> +rVuor$3'u)q>Sg8XS2Sks8Drrru_1;\f)P,*7t#`s8Dlqs8;]ms8Duc73WZoD!q?#s8W&srVm<& +s8)ZnZ^mhmZa'/rrr;rrrquotrVlcomf*4c.K9;DnRjI+>[Ul(-U2s<OIAjK4FEDt;JJ.MM4K]m +Q9.-IOa9-)D_#kuE"[)0B1_drs8N&ts8:cn`5U=+rVlfos'XZr^;.V,]ZS4:`PB-s75`94d*0^t +B].n0h:L?*b1"Y\bK.Y/h;dDKg"4Qtd*g=db/V32[(XDcYdToe^:^qXG=oH[aMbj1^VGqnO,^fm +`PTU1p&G'jrr2lmk4&ELrX8Z(s8DanA8cF+EH1Vi.W7[KD+8N0Keu)\P`qAsH9uCS:m6SmCc%KE +P*qMtRY3h-6qT>/o_e[crVu0^rr<#t(&e.3s8(WR[Ag+/XHN/Prr;usqu$Eks8W$(r;HNfJ/fDF +r;Q]q%K-8)r;Z`W,8_f^r;Q`orXf,/r;?Qns8W)mjeJB;SC7?6rW<&urr2qJ~> +"98>squ-O#qsX![?t$L]aSa1'aMu3>`m:+Z().1id`]_J_T^<C^Vn..a1sGM'c'lsf)EW'b08)N +_nj=4`R)Q?_fT-f?"7TT^<HT!rlG)YrlG&\o#NN-bfn5L`PopCe^@>=-<anf67>*HO-,o+?9N_& +=]&lkNf'EiQBs]qEftc4CN(hGnSo.YDdbQMc,[cB`QQcR\\,>Wci2.$b/qcHc.^\,p[R_Hl1!m* +lJL4@5QG@X1dP"l!%A<b%hp?F2)mK]84,Q@3u.l*(bIL!3(6J59he2S786cS;f,M7B3SPI84:nc +oC),Fq=;54]YNn'lf[9Rm+9A"aMuBL]tVV2rQ#Di`5^4g>]=\&Df9]<p2M^(5tbu]Dj#`.5Eh7m +PEL/UBjFJrK/RI"PELoiOcu;i5#sa.,_<tTa2Z6DaiWhh)TKb9cd0hVaMYQS=^P0-<)lVu^;7h1 +bfe)Irl#ntaND]NbKjf0$<PHi`Q$<NbJV-;cc-b4'Xu*!`qd[gb08)N`l5Qd>u+6tT]l7Kqu$Ej +s*t~> +q>U^!s8V0:q#CBnrr2rsrX/W"r-g4>,U^D,qYpL+q>:3frr;iof.@gX.^/jOrV?F$r;QKkr;ZfB +p?h,&m/I%br;ZcorrN-!rr2rtnc&Rdqu.u93&`?l?=,W71PV0cR$KdF5Cnu-<H(]LQ]RZ'OAe#_ +P'f];6=k0,EclGHCeXU's8DurrVGHk_o(%%qu6Wqqu$Bfo"^*1H$FFSE+s<7H[U0mE*^Q[l/Zs: +q"Nh@r;6Nko(hkKp>p,RpA4R[s8;ianb)88q#CBjnE]Q4lK4&*lFLb7JphfaEdMe4'*\F@&63[g +EHd;io`+mhrr3)am.gSZrs/K%qtg%eA9%-[06))#2Jb^)P_gttPaIi$Q;gt)<*toG3,1F?O-Q&p +S<T4s9j0;01@Fu<rr2rss69Lbs8Mroqu6oZl1"B>n_<j<rrMljrr4/=q"Xads82ios2603.I[<7 +r;Zcqr;ZHip0JjkR/?j]s8Dp%r;Q`rr;6Bhrr3,`j6Z$rr;Qfss8DqI~> +rVuos#lXc&qu".'`qfW6!<2ur!<2ut+8c"_-PdXE]DMC&s8Vols8)cqqu5+q',Dsurr;rss8Drq +rs\f)qu5oJWL^&pci<qBs8MutrVc]qrTX=\s!dsGof"]V=C#2k+Z"k<S<oL$ANkO&?VtW3C6agH +QB"fuG`[5=DEq]MnSf7^Eb@u:s8W)urVufQ`PfaGrVliqr;HTo@,AW5^qmh,aMGj5_8!drJl/Jm +^qj<pk2k+PhUL!"d+QL]c,X&AiSiVHeBlgjbgOk\ahk[#^V7+^Xfl2c\rB6ZVS'[\]u\+,MiWp` +LqCaFai;3js8W&srr)]UnGiId$iL&)rV9H(DfBZ8EW0nWEVOK*F$V[!6$JNK/6nC*Q][P3=)LrC +P_M,22j]PiQ]dl'PD`+90/>6Kq>^Hns8N&^rW<-!rr)d-s7Nh)XKA_0S]LEts8Mior;HTo*W>p3 +s8;o4*[2lss8DorrVlcqpAabe)'tRFrr2rrrWN9#rVc`ors/Dk[[s(b[.sY"s8;uurr2qJ~> +"98>squ-ObqsWL,A:_G8`l?0Fbf\#G`Q$$M?Pa:i'rBX1cHOVTa3)-4aMH$&)\!5lP1\.%`Pop@ +b/hQ>`Q6'E_o&QVAQ2rJM87'RrlY8^rl+rZr6"NM0ZqV`b/VE?b0SBO+WXKc?8j#^KThjiP;cu6 +I#VN3D+eZ1O-u>q;D`Z]HUMd<A8q'YHu<k22UBXi`Q-$BeB5D;\@^;3`Q69IcH=Jhf&6;po^_YB +kO\?<n*8)4'h)7t9`R-k!!!cS+#,`:83fU<70#CZ!"^5(0fUgE5X@_,9iFn\8PrYrCbS_29HHR. +hsBjoo_\U-`ko[*lgEs)jj3;FaiDKBb0[i9aiaS'%a;l2dQLiSEH,o8F)u>>q/J'*EBc6n5BW*C +.U%t"Q&h,+<GYN;P(Y]*23j,cQ]dl)PDi%1-n-+O_o^!@aiMWhaT'6\bg$.0'#q_kC11=K;,^AI +Z+8*"ajJ8Prl#quaNDWQb1EO()A0p1_8F^GaMZ*4d*5)n&pDC9aN=D%s2l(raNVlL`lQ!*FAPY1 +Hf4\oqYL*hrr2qJ~> +rr<#trr3-!s8UX"rr2utr;Zcq*r,^+Afr6C-RMHRjnJTMr;Q`mq#CA>+ri'Wo`+sgq#:<n#l=T$ +khu%)lJMU@"T88srr2oss8N#qs8N&unc&Rdqu.u61+G.e>uaHePa[`%LmL295C\o>8oSB/Pa@]' +P%68"Rt*P60gT^IEY<J;CJFU(rr2rrrVGHk_o'puqu6WqrE]Eun\9j*G&qhHDgHYLH$4:bKj8A< +hiN'<jn8N@pA"ITp[J%Xm-KGQp%n@Vr;QHaqXWk<r;6?jn`TW<iQQ[QDJ"Wh08"dlIV)_!!<N6,% +TRIdFEWVmo`+mhrr3)am.gSZrs/N&r;61j@WCpY06)//1grRrP)_,,Q'dl'OZ[;u5BE*E3-$j;P +*qPuOHZ#qF@nhW5O\OMs8Dlmr9=4\s8W#ors/DYnb;GBmF2(7!W)corr`/nq"t$i-1gp+.i0VJs +8Diprr2rtqZ$DY,:.(#r;Q`qrVliprr<#qq>C6krrhrNm.B33s8DqI~> +!<)lr%0$5)rr;8`UZ;(Js8Muqrr4&=s7TtA(`OS?7[E*-p\apfs82WlrcK7u-6`$]s8;lrrr2iq +&GlG*]V2.!VQfgos8)`prr;oqrr;6^s8OPIrUMWk1L+0b8P#)7OdCih3bCR&ODm[*@R-*APa7D? +/qTL?3+jm/D")CiEb7r;s8N&urVufQ`PfaGrVlipqu$Kns8Uul_SX4/_SXR;^;Rk)_j=A'@EO:N +iS*;UhV6]2b0J&QdDO+G^"hQ%gX4BodFZjhaMtm$^V7+d[^*#Q:K^P<RT.&C^!XX0MM%%NP_Qfj +^rXC/p&G'jrr2lmk4&ELrWrK&s8Mdr@W-5bEW0nWEVOK*F\=Mu4a`BO/7t-5Q'IFmB6$1VP_D&9 +1QIQbPEM#kQ]lJ[4Yf1fr;Zfqr;6ETrr<!1rVZTls81TSXKAD*X.AqXs8W)r!<)lr-2mc@s7?!V +,nD33s8Mrrrr2rtqu?JT*$8bfr;Q`rrr2rsrr)fnrsnr"c(LZ'TBZ=Qrr2iqrr2qJ~> +"98>squ6UgrVQ'%F(D)]ai26Ac-=JP_o'@;d7k#_)&Nu<FhQ#Ge'6%Z^VA"@=;)8b%+<\N_o9U7 +aNDTD`PomA`lPrD>[1QAC9kRra3)KErPeiYr6"KL0ZqV`b/hTBb0eKN(FN9d;b'<?R#dMdPW329 +HB3&9D.>kqQBdf!@kWJ'IlV0r5]-%2s)33k2pfgj`lH-CeB5D;]"lt=_8sdCcHO\leD9cjp@[n> +p%S.Xq!d1/3uf&`1F-QP#osj$,;1l;4%E%59E6:K"W&O91,:gP4$#Z"92f%f7UU"JG>p^f1hN.f +iVN'>jm9dtc,@Z4lh'N8im6uCaiDKBb0[i9aiaV(s2t_fajECXE,ff5DuO_VDu"B+DKAB(?9<Io +M^i8#Q'7Dl3G!.lE0>i2D_[<8S!]P*PEh8M6TQqS`5^$Ca2Z*<k/\@]bfn5L_mu(E?<0Qp?!">@ +aNMfPbfIg'`Au#^c-sAHfGP)5R*WXbccjJMa25mAIM*/^bJq]J`l6$Bbf[rFbfn)Ga2G]P;+jbn +cM$u,qYC*hrr7K~> +rr3E)q>C9mqZ$NDf`2!Nqu7f<r;-9^rbj&',TS9T,r'/EqYC0bs8W)i/1)A^MZ3DLq#1s,rr;or +s3L3(q![eRp](3kr;Q]prrN,srqcfqrr<#_r[7GU-pD'H2)^S[NLuE'P;d8FFdS(KDK@alP*qQ! +J0p8=M)]**89=<As)\fe:AXtgrr;rqqV]?1_pS8Vr;SYRq=)%MGB%VFFEMhPFa8+VL,l62BUU]6 +1;<;Js7>mVp%n^ep\X0ZWVQ>[p%n^go^VVFo)AJ2me$5IjeQ:M<_B0cSQg,[G%+Gb"T\W($5?EW +Fa/=qeF`e>rr2p"kj8*Drr<#t"T85k?XN5A.T8`+4+WZ]/T[5APaQV^Df%UlQ$5N10p\H!P+7f( +QBm\@7k[!jq#C<lrr;3]qYrPRs8V?Po^28>eGoRGrVuirs7uE`qu?]ns8VrqHn-7UpAY$jrr)lq +s8;o,-6Q%Yr;Q`qrVlirrr3,sq#(0krr3,Xm.TN1qu?WoJ,~> +!W2iort#)+r;P6@ZL[ehs8Mupr;HTo*;]\P*YfS-+;l:RB!h=,s7ZKmr9u'X(a+\8qYg?lrr*?+ +rr)lns7Mn^U8k'*rr3,trr;utrVl`plM`=6rr2iiBdPoL?8a^(P)Z)sR?BIC6ZJ?G2em7gKohXa +P("[7OG>`)1e)KRE#rR`q#:6ls8Duqho3OQf)GXHqYL-irr<#V_SjF3`W!_U^V.V'`3qt(Ui<M; +^KS8$d,E^4eBH.]ai2K?P)\)JgtU0%d`]k`d)Nc/^pgk^YH<q)_1Q3uWLmpgZGj]#P`_/nNf].2 +`koU+_"Ia-rVlfpqW@;Iqu6Wq"8?/0E;aeUDuanRE;so-;F<r8J<Z6KEg;fOQubZ5CcdB9G!Kgr +Pb"/'S!98*Q'#9;.QQbgs8Drrs5j4prVZTlrVlQ*XJi,'WL2N<qu?]lqu-Kn-2mc<s8VuoFs@f= +pAb-lrr)lqs8Dr'+<!iGr;Q`rrr<#trVc`prt,2.r:o6ISt;G"qu-Kmr;Zcqs*t~> +s8W,qrr4YMqsC1hFM#H2_o'XAccjDF^rFOQ=:u/_'cd_l'MFeFdF5tVd*pAV)%mHsf?))4`W*sW +a:QA1`6H?C[p*BF?t=i)_90gtaSj*aaND`Nb0%fF`q%2)b08)PaMu<Fe(%>410[p:1lm`VSWK2" +1h]0oPDD26E&NH5R$3_`-&dtB2e=j:Eq+,^Df&i@d`fbOa2cHSb.GC!^tR$3`XKi.bgYCrfC&8( +p@.MLmoK8RjipPnQ!'VAUD,7')^cRL2*=2p69n(,'`]9i-8$c'4#JfX853#a>Z+F#ATVWf\qt=6 +W17e*kPji1Z*_Np`l5OUr:omBcg99*a2l9Cd(R08b5THibf[rKcpq/WDf9K2rc&!XEHD"ss)0Jc +5t*b^P*%55PE:omEC+JV3J<Q;5%u^;U7IXER?s/%O'G..0Z(]Ka2lEGbj!1eb/hQAbg";M_8*R, +>u4'h=\tEp^Wb*Lc-"'*`W+!g_SsO3gLq`@9Z4oebKTt+(!4A=SJ2JdcH+5Q`l,m?bf[oDb07m) +`=9_[=@l"a[IX%cqYC*hrr7K~> +rr3'!q>:-j!rCX6q#;N:r;QKkplm9T+!hjN+rqsR.>6@RqYC0$,9IpQhY[3Ls8)`orrE&trt<lP +o]bW?qu-Elrqucps8W)tr;QQqr;Q]ql2E(#.6gO03\WCUPa[f#R#sLF95B]V2KEe7@?R"CQ&6oP +R#<sh;+kluEY<M9C/=a*r;ZfqrVPNl`5C!trVZ[irqPuqKQ_?TF*`4TIsQ6aJRNT"G#_4):cBf[ +q=jXOnbN"Zr;Q?Yd>.MinauYWqtp0[m-soNn+62EmBKrUH$G7/1oH^$MK)]0!!W?%$j[_LCj1&S +O4<h%rVlfr"6f+Hrr)j#rVlfg@p\YF06;#2;_^7aR?T+SR$<r&:0V^I7Zs$J9klkTO-l,nQ]m`" +Q]!ae2=USErVc`prT4%Wrso#-s7,CHp[.Y<df9@Er;Q]uqtTs`rr39$r;HT6+sSW$rVmf7rr;or +r6?T3.J`o@s8Murs8;lrs82Wis8Drs"QAb:lg"HK!r`/urr7K~> +!rW&srr<#t%KH7GUrW3.rr;urr;?NmruD";qN<0G(*!r,)]'S9,_4GDq"Ocp*?,kAhYdBNs8;j- +rVZTnq<=3?W2-NNp](*irr2rrrqucsrr;Bbs8OSJrVZ.44\Ag<0Jo&ZRZir%O?7,JB9&-1DJ`0V +OHu)oLa8+KM)RRn8T+EErc.dR*-#n/:&4bcs8W&tqqoB1`Rb%drVQNks8N&uiPYZ6>J\7t]>h\% +_nC_AT7:p8P,s@+f@SF+f[/!gbeqN>aK9+,fA,0-d*0b\c-"&A^:V.fZEB1"]YhV!Y"#[d9"i*Y +P)c#pNK/pV\])S&_8,aDs8DrrrVG[Gs8Dp&s8Drsoj_6HEVseUEW:"XEW'i0Ec"cR0/nKMP:)'N +PEqG->&[n=Od'BMBfqK:Q]dGsPEqDuM)7:Ln,34arr;urkPkM](&e(-rVZ]fc`aIWWNE(np\k-h +s8;ios8W$(s8DusqnX3k-ft=,(&n75rVuc:*ucL"qu6Wqrr<#trr)iqs8W'.s8DGfU7.dip&4pj +r;Zcqs*t~> +s8P(UrVuorqtoH8?Au\BaMYp<c-=JO_o0IAeThf>%il<!&IT0Z&SJQ'cd:L;%2'-]][4d?a2Q$; +r5]Ji`Q?<=X&E5.=_j\?bJ_]IaSj-YaT'Bdbf\#J`l@Pis2lt8`l?*Gf$Y0b5uTZo16[lgOcboh +3G(foNKZ/:DGX`'Q^!_k-'FUP3'L/2DfPbts)J$Vr,I1,EH5l"2U]diaiDHHe]PM<]"ctEaMu3; +a3<#fd+.LSo^VPGlh'Z6le.YUXb_CjUpk1@>!aV_,<&"V6U!n)8i6Su*@ilq1,q<T4@N(O@9?]4 +@<cWo^sLisdSR0=>3u(OZDkLTa2Ym,lMpnRjNm2EaiDKBb0[i9aiaV(#gLK4bfrXSD/]Dn4*,C[ +D/jQ6DfKc<EH#Vi:bXbUP`[8EQ'%;o93?(=6][C>8nU;NP+@u*R?NktP_qCc/^Vefa2Q'>a8O'Z +b3m>Pb/hTBbg";M_oTBL@oZDt=^,1>^rX^Ibf[rE`l?*>a1f.%e>j5s%_g3.bK7]Aa2?!CZP*i\ +dEBbU_nsF8bf[oDb0%`C`Q6*,@o#?jRH4#:qY:$grr7K~> +#5eE"s8;]lrr32Xi;<QOs8Musrr+#7s7H<fN@$%p+s.dI*ulCJ,$1`:nlR1[-s-3Bqu?Eerr2p) +qu?]RkkFQ+kPtJZs7lTmr9aJ]qZ$Qns8VuqC,d\Q80X1[PFIo&R$<b%@9QWnR9Nd1BL\,OPaIV% +OI_7a1g<gqEcu>@H#7SBFE)A?FE;MCEckr$q>L?ms8Doni5NXQe,0+Cs%WLmr:oiuKm.TZH$=OU +H$+FcMDVQ=3/VE:%N@)aiqr9;p%\7Urr)NXj)OVanFZMSr;?Nfm-4'3nE0H6\l4f>I!1.$;.un? +;I^CEqu@-0)-L]mFF0"so`+mhrr3)am.gSZrt,20rVubr9lkArFE)8CDfTjsE\_QWE-?>F<Du%4 +N0]fbQ'du#Pr3Jt5^8Q[:0D3kPEqAqS<B8'PF@S58iBiFrquZnrVli_rWN9#q>($grtP;/s5`J< +p@7Y"s8Voos8W)tr;$6hs"sTPqu?C<,9`]Xs82WlrVuonr2Cbf+o2'8s8MurrVQNms8Mopr;6Kn +s7YR=le_[Aqt^0fs*t~> +"98AtrVca$rqN.\g\q!Krr2rr,l[iDqu?Biq2-CA(EFD1)]BM3+!+CYo^Gm+)'W#Pr;6Nhs8W&s +&HDb+rVQWgYFhYhX2Of0s8;Wjrr;Bb;uQarrr<#oqe.i8?q2H(PEVE"Od;/l6=3hmOI'*NCLfbm +QB[c"7$*ss1,<!,CN+B3E-H,<EH?)=D/sW9Df'N)@/0^#r;Z`qqqoB2`7Fncrr2lprrLumrkr$Y +^r=++]YVFm7\cJA\A,>0Oapf`e(<:!bg">M_o0O.;UjRSf[A0mbf\&Ob.t^*Z+@N7;np/i^V%'u +IB7I>\;lc6O-,WhNek6b`5TU0p&G'jrr2lmk4&ELrXf#-rVu_q96"leEGf]<E-$$uE].]RCN4<5 +<)Pk2NL,raPEqPpP;@&l5'E-S9NPjgPEqAqS<B8'PF@S582XNAs8W#srVulrs8Doss6osertbV3 +qu$Kjqs1VgYH4b)OR<)Grr)fprr2rtrXJo)s8;oi+rqVlqYpBgrVm0!qP4rQ*;9:/qZ$Tn!<2or +#laS;Tq.pOli$e^"9&9!rI=~> +!rr9!rr3<$o^gmJ=e<UNc2Pfaau[V``PTs?e'hq4%1a?n'GqW#(D[WNOknVP%Lj+5da#hU]Z%n3 +b0%fF`lQ?Dah;Ur>?bKc]"uS1anNjVb3R,Gc,IQ@bL#$C-6-)R*g)YMR[0,'PEA4?=]:HM>$#NO +6]dY!R$'k!SVf0Y>#&mTH#[tQC2Ig+DK9]=FEVbID,*:=bL"AQa3N5X\\,Gaf$"'6B#i$9dG31' +nFQ8@mJ$2=k3M6[>cjl$cf!EUST?5f4X_jF76`t&7S?TW!%oWH/h]%B4?Gbr9ikV.;d+-d;9[e[ +kjdbiJ?OEriO-5,^<=gB^p`S,qXE@fm+9A"aMuBL]tVV2rl>\pc,n8VMDf$`F*`%PG%tf2E;jT5 +G&_YACf!qm/VfCOKp7pkNg)A<D*N6/Ptb@n4-Q%rQ(F/+PEVGs<D,&9e^;CR`lH3B`l?*Db/hTk +aSj9]`XTu(_5qHS:J4Mi9WlCQrlbGdaN"2"+3D@:^s:79%h"!@d)E`9]t_G'e;t.X$.mMG`501* +a8X3taNDTD`Q$*B]n9?U;ejSLrqZEjrqlZoJ,~> +#5J/ss8Milrr3/]k5YJ[r:p74r;Z]hs3Yd6,9@pM*ZZFF+s\6[J05mU+M[aPrV-?grr2p'r;ZfK +o()5(nG`IFr_rals8;oks7;-o3a+p.Q][T$Q'mu+P=&hm6&;"Z3-T=%P)u;sP)tujPq>$r<dSh) +F)c&<EcH#>EHl5BD01&<459Z4p\t3ks81`p`5L4(rVulr?N9otoYQB/F`i(QG&_MSI"b=;Ui9gl +70`qq)a\N/p$VVOp@eF]p$_@3a7B!!qtL!cr:oaInFH)DkM8n(J9#RTKS#78SXh&b&c`1;"TSN) +(0PKoF*W_oo`+mhrr3)am.gSXs$utas7KW.FEVVDD/sW9E-6,+F`VhGEcYJY:+hWpQ]ml&PEgJ^ +E)p#(Q]4:E?UL!@R#mDlOd_T!PCl+S8"fJRs8)cns8VEa"TSJsq#:9m$iBu&s6f+Co_7_6mf!1c +rXo20qtpBmrVccps7VWu,TupWrr3W.rqQNmAgJTMq>C6lrr)ipq>C6l&cDY+q>L9lrnHW!kl:\[ +q>:-hs*t~> +s8W,r!<2ut#QEk^W9+$Ws8DrqruV1;s82NicYY!N)B'S5(E=84*ucPT*?,n9]D)@)q#:<lrXo20 +rql`nl^alIWN+bRrVlcoiVlaTrr;rsp\jQ:+?*Im249VlQBRZ#QB=IAANtp;Ho?+`23<ijO-5Tj +O-M:V;Gq^WD/jK0EcH&9F)Q58F_c#>B0+iEs7Q<irVl]P`Pf^FrVc`p!<)lr!T(Wk_ct*n`5077 +_Rsc:ST'5"ZB1B0N.l;rgs=9ic-+)D`5KW2WRoeSf$DXba2c?E_S3\#Y-^U+^Vmk*_RI9RUo-k: +N/X'ZQB%,hM7LUE`l#Xcs8W&srr)]UnGiId%/p5'r;Z@m@W6=(Df#Dn3cK4\??'n*Bl7lo8PUn% +R[0)'P*(rR6#KY$P*LqiAm[ogPaIPoOcc)uP*:M`0h%c-s8Vurr;Q]qrVcfsn,E@e&H;Y*rVlip +pW'J>Wj&=i\+ot&s8EW/rr<#trr)irrr;YP)BKgio`"jurVu]nqd:Kb-2.68qYpWpqu-Hm#lXMG +T:qmNf_k^J"9/?"r."~> +s8Mus#l=/]`b&ST`5hl"s2b/Ys2Z;0bK/529G%pK'GqT%*#0A0&fPQn#Rh!3dF-"Hai2:!aqDe8 +`m2cM_ld9N=Bo:$_8a[=a5P*>b/_H:b/;f[G82`.5;8IhQ'[`&QC!b$@V.l\RXI,<D)RN;T9#.s +QB.:_3E&k$EcQ8BCiF6-C2n3:CNsfBG[MT"b0IrIaiD]WaLJmm]@G*Eb0">:ai_rbdbF9_nabu< +o'?#3gP(Z`GaRLF]YCYMIOS)S-U'm^5"8.=;dTM>0J>%40g.ij6q'[G=]o<9Fu[S"lKS$@l.&_4 +Y[F-/\AZ,+`lGs+l1ai>i6UcAaiDKBb0[i9aiaV(:Wgr&aOJEu;/LQ&H?+%@C2S*+<,QZ$D/3og +8l.-tOd)#sPEM/V6>ok(PEq.mB4"#hPaIPoOcc)uP*:M`/3/I+ai;*>`lQ0>aNVlL`p^t`bf\)J +`l6!?_n1M.;+X_c=*M6raj0n.r5^q@`Q5p=a`7Ut$Ja%Wc,@90^X_+9'+Y`-ccF&@^r+46b08#N +`l?!=bf@G_=%l7qYjqbjqu6Wlqu;0~> +$i9l&s8Mons8VEEmJd+cqt^45r;HWps8;`kl_70!*$ZXG*[)XF+s.jL+Y*-[s8VloqYpNps8E6& +ps\p)mc+0E!;tgT7Jd#]rVQWp]hCIj<^(hkPE_GuOHPip=]9-$N0'Bi1il9#R#mc)R$=,&1dY,C +DK9`6G$-qQDfTf@EH?,@FDc@tp&FmfrsJ`)qr#N5`7=eas8N!Os82T`_M<DZF`VeLF*MMCH9@dW +0mtSd!!!36-q($"qY9j[q>C-_o'b.do)JaXrr2Znp\=^](%CO?Lm*%)H$4O_LM0tbD^$#(!!``- +!"098EHlSNN7@M"rVlfr"6f+Hrql^bq#15q8p#&kFDYo7EG]Z:7l!S=G]%n#0k;tmOd;8uR@9IF +<a\@iQ]lt[E`uJ)P*]QcRZj,)Pa7Y34ZCI[qu$HnrVuo`rWN9#qt^6jrsSZ&rr<#\n+-5?p!<X; +s83*#s8W#prr2os+oVH<l74,*FT2+0s8Doqq62%f+*RMYrr;urrr)`ls8W)tr!rT'rVuoPkNM4& +s8MolrVcbH~> +s8N,tqu-O!qoP_Bnc&Rdrr)itr;HWo)>j7+l_.&r)'Bt9)&sS2*?#h:)^Y%Ks8Voos8Dp/s8N#o +rqt*,X.u]#o)J^err(gT;Z6Xorqufr\Oe\\<^1nnP`h>pNf]Eh=&E]qMN3sa12fWlQB7Q'R$=,& +1dFo;C2e*-F]^_MD/jK;E,ff9Eb]bjpAb!fs8W&sqr#H3`7=hbrr)orrVloT_#D5U^r=11cb?rl +<NM`k`0-@DO-GZXA>.H'cd'bV`5BR3];K,`gtBd"ccaAK`PfR*]!f1^Nk<!Fb.t^$]oHp,Kis%h +MNs9aPECj<`59L1_=dj.rVlfpqW@;IrVlfr8,3&^X[dAICiO3+EH5o8F%7lN=*/2%7k\@+M3O9h +Pa@c&=&`KnT9YOg2K2i"OHPr<@[`LJQB[]%:HgVVrVlcqs8Drrs8Doss6oseru:t9r;HQnrVGHW +XJrA!Xd8PWs8W)trVccrrr2os)ZKd5k9_5kDu05$s8Dlnp8]/R)05KKrr<#trVuoq!<2or#lODX +V5'TT^A@j/"TJH$rqq9~> +!<2or%K#b[UhFVM`5fp@b/h[%`\tr_cHsn^e&d4t#mLtT%20Qp&f25o&do5ud*B_Iai29Bbf\#H +`m2`J_N@])='o^H`lcEE`8J^Cb/(s3ce4mL.o&i"G`e;UQ]dDlPEo<KCHdZ;QBF%C7q@sJR[KP- +S<,Qn;H7LRE,'Al2g0(WD00Z9E,p#8D(WuY`lu]Ja3N5V\@f>`e]YtTb/_WHceQt'nFQ6Vmd]f; +r8uYI>-4K.i4-G1^Vm[F5=\!o2a0Gn8PD]M<BgIO4tn':6VL?Q7R^!J:fV9iNn*%Up[S"Df:-ia +OD^u/\&5tsa2PXQnF,r0dHoK,a2l9Cd(R08b5TIXaihlEbL2D-CiFNEEG]K-DfTb\.R7$UB6?a# +BJ>$tPE_?"R?grT?UUQQP(5K2>#gZIQXF9kPF.Z#QBtB-/$RLC_8FC8aMu6@b0%fFn&Q9gb0%`D +`Pp'?^RSe28lAJq;mO9_b09k-rQ#2ba2Z'BcH,tr0O3M_aj%rOe(9in%gcCgc,doB`5]pAb08#N +`l?!<bJq;p>u4.!P3i5Gr;Zfoqu;0~> +!W2lqrsJc's8Ua+p](9mrV?HmruM%6s8W#srV6*9I4H*\+<DLJ,TA!N+,BUjrr;roq>U?m"l8)- +m-+*@rrW0!rSd`Ss7H?krVQKF.6_!7;O<H0R?2;hP*VAC:iAUDQBd\Q6[:PKQBdVtQ'IO`<^K,q +EHFVs5YuK@E-c,)=`JV*G<WP.s8W#ss8Doni5`dSeboCGrr,^nqtTg#LO"#bG]\.PD/PM"KqLqF +3=Z&l!!!'86!EOIp\=LXq=sXRoC-tmq>'p^p@RtLqY^9fs6Im-RXoa(Cj(,MLP%4>U-1%E!!*E* +!"0-0EI)hUNR[V#rVlfr"6f+Hrr2phrqufos82LLEHuMCBN9"iG].J27YsQtH#c/dGq+uHQ(",( +P&*I)3JNBUPYPJ(9jEsPO\ohJQ]dT$QB6>R2+[9;rr)lrs8V?_s82lrrr3#uqu6U"kN_[/p@cu7 +s!7I<rr<#tr;Q]qs8;cns879b0H#K?r;-EkpP^OK)(<)nrVliqrWN/us8W)tquH]ors@lMlfd:, +s8;`mrVqB~> +s8W,t!<2ut#PYBr`qfT5s8DroruV+7s8Mops7uE=Hn#jU*#]V8*u5q;)M@\^rr;uqs8;lrs8W$, +qtd@`X/Du>r;HTjs8V'W;ZHLks8Mokf-WRa;,`gDQ'[MI=-/Z1@8:Z'G*J2RD*N/!MjBWkPa.Mt +.o\btEGone-U:IHDf0i3?s%AjEH=7Oo`+sfrVulsqr#H2`7=hbrr)orrVloT_#D5U`50C3_nF6% +OfW8hRYZfaO-#EXJ8Wo_cd'_T`Pfa6]t@(^dEpFkccaGM_SEgq]X+S2[^jGt]u7e&a1"d9XBp=8 +Lm+-_PEM!@`50@,_"Ia-rVlfpqW@;IrVf:bqu?WpqXugbF_u#-;fQ`"DJ`oOL-guEDE_f[.[6Hf +R$WnrC-Z\rKSPbS9NlC0>a:b?;/(fPP*DB#OE`oD8+Q][rr;uss8W)t!<;Ne!<<&ts8Dus$iftn +\ZDp3XK@lHo`"k8rr)fps8N#ts8Dios7ppV.MI7*q=smao7nS7'-k!^r;Q`rrr*'#rqu]nrr3?( +s8;]b\>#RdW:p2i"9/?#rI=~> +qu7-(oA5.4K=o+Aai_cIaSj+8aiqiIcd9q`d*9h<>n-iI&.oKn*"s;)#A2B6bfI`>`lQBJb/hTB +bf[i:Cfk%J@>)A5bPoQ@aDoYFa2Z*?e%QVR<(p&POI)>qD-2pcP[[F+5BiBWPAWX/1lR`cP*D5s +P:KX!5B:^_3u^(MF*)>E@9ciNF)>kLR)mUsa3)HAcIL"G^::f*bJq]Ia2uKMgsXsHoCMYDo(2M9 +k&$0ZFh>T&]>qk.9"gsD1KZIo5"&"=:.\&S<WH,].P*>C:K(._85;uY<bX5(hX9q!p&+FHc!RQ[ +D4@o9]Yh:u_S#.$mI]Shm+9A"aMuBL]tVV2rl@UM_oK^>bgISEFED_C<buW#F),,DI6!.)D*`)g +.Z]pZR@',!CI)o!KnttW9j;U3>a:b?;/(fPP*DB#OE``61<@_Z`6?C&`rF0^aN!\i)9U1GaMu6@ +a3)'#CfO5&<FA^r\&c\8bf\*,a;rCD`5TmLem8J!")?`Gdam1*EtJud%@GSfaMu6@rQ>/a(<X_< +`Q-*@_R4>[:02SsqYU9ls82ZmJ,~> +!W;rqrri9"s3fNurrN#sq>MK9qu6Wqr;QZnqtKjbp:"`_,oRm@+s@aTl21M[rVcclrW)iprsR3A +nEf07s8;oqrr(gT;uQ^ms8Muc1I"u=.?0LZR@'+@0U7oeG=QIZ7ZNk&R9i]d@?Zq<QB@Gt040Gd +F_<g.l:Pf*H>[_=>Z5TVDe`/Hs82irr;Z`oqr#N5`7=eas8N!ls82T`_M<DZFaJCZH?"IV;65O, +<=]'2"pG,0$mn3EnFuSKp@RtHnF?%<](>dro_%hDnFuk[s8;)H@uPqQE-Z5@DJX_Y24'1D//8$_ +$j@#4D0UAVO4<h%rVlfr"6f+Hrr2phrVuorrVubK;g!+_^U[ilE,'N?47Ro+88LGPH8LbKR#mPt +PrikBN0g'(OY:uo6@"TVPql((Q'7JuPa%=h0.-8iqYg9is8V3[rr2urrr3E#jn/-?mbm1+s8)Wj +rr2utrqufr(B"(0qrfIP+Xp$PS""%5,U4N\:@e>]q>UEo"9/5qr;?R(p#,3%g].<Pr;?Qns8RT~> +rr<#ts8NB(n"6H3rVufqrVl`p)Z0O6s82cns8Mljs7a!9,U+!D&02`(.H^I+rr)otqu6Wq%K?>) +kE`'DWikI]q>L3is5O#UrVl`ps8;=?4&o-+Nfoj!QB,0$PEV,O7;?7!N0]`q>Y\%$PE_2qOd21b +?%abM@l[*E87uITCiF/o;K$>hB2JL*qu?Wls8N&qi5NUPec#IGrW)oqrrLulrkhsW^V@\#^m/-& +OC+o9I>3]@P)ti^D5+toc-")F`5T[0_0;<id+6Rhbfe,G^::V\[Y&V8aLoR9]>hY"`GJ\KQVrI% +P)YfjOH.)p_SX('p&G'jrr2lmk4&ELr^Qhcs8N#tr.IpfE)jQ[@;KdnEHO;2JQP?S4-+\EOd)/l +P*;(iCc.*8R[K3gG@s6fNg5kb9q7K4Q'ISuOu=j;oDe^eqYpKos8W)us7-'gs8)^Qs8;onqTu@J +WNW1n[.=4rs8Muqrr2rtrVuoqqu?KR,odjK7$X+*@2U+,*[+/Fqu-Norr2lqrr;osrr2p+rqcTk +ps>V)S=]'GrqucrrdX~> +qYpuqcZ!Wg^r4.6b0%fHrPgh<`Q6BMbK\5P`P]aGc]q07&IK0[)Arkq_pHfR`Pfg<b08)PaMu6A +aMXuX@U!)KUVk$paN2B@ilGTPb/20<bf^nX:.Z[eOIVf,OBO<%P`g2ZCLT_lQ^4"E:JYA^P`_8o +Q'F"/Ke7CW1,RK@?tt.1DJ*!HD.R?d4P/!$bf[oF`Qm#T\A#Jbe]YtTb/_WHceQt'nFQ8HoCH,Y +o^8kmVj2V[]YDM/`PfKuRSuO96:=OH<DlL^6rFmV3\3'D6VC!C9i5%s;IN[Eh"^4-q<n:Xm-B[N +Wh<jn\@K2h]t:f?oCMP5dHoK,a2l9Cd(R08b5TIX`5p!;`R31I6>^dK_n9GqFDc,</Db;<5\WKL +Ho-nIQ]I>pPWEY>MjBj$O=kck6@"TVPql((Q'7JuPa%=f,n\>F_SsO;`l5p:b/hTBn]2ZhaND`L +aMu6D`lu91LK[YM<)d"@[DU/2bf\*,a>CiUaiMTPd_lP#%i7-TIXY3+&e>?X/]u>[aMu<Fc-4>Q +bfn5N`l6$=ahtQD:esu#ch$u3rrW/qrI=~> +s82lrrr3-#s8Ua-rr3#rs7uWsrVucerVlg5qYpNnp\=RVjc)n[.iKT^Pl:UXrVccrqYgg!qu?]` +fCSIqjo#,Zr;,CO7K*5cqZ$Sd-QQk[0:S)aOcl/C0T;3[O#:rq0pn#iPF"jG5C/QbP*hMp/T$_; +C-c3em7V&=F*MS'XKY$.GX9@Dq>L0hs8W$'qr#H3`7=eas8N!3s82T`_M<DZF`r4UH\$Z,T;jeR +&,cJb"UP//&3<P\o^hbJo^_PCn`]"\mIBuEp\++GpA"O_qq+uAHZO4HG'7V:@hBq/J>>al&,lP< +!XB0.CNb&TO4<h%rVlfr"6f+HrqcX`q>:'N6Y^O<;cec_FEV_B6Mn/l4D6X5O`-GIQ^O>&2/5Hs +PFIJpIRIgo1Qe2fBI-68PF%MtP*qGA4unJrrVuoqs8VEas8;osrVcitrr)j)jR)X6n`nR&s7uKg +rr3r:r;?Qmrr<#rr;XDN-6sf`-Qj][,Tn<UdJs1?rWW?$r;6<fqu7)^lgE[.s8W#pqu6TpJ,~> +rVm9)s8W#OT<Rb_s8;oqrr)j"rr;lfrVlfsrr2p5q>0s[jGZYT-PdaOOo,+RrVlisrr2lqrr2p* +r;FR$X/;o1q"X[arVtmV;Z6Upqu?\e,o^DS/tA&aOcYr=/rGdSNAGNi0:%TaOd/F?4aN?`P*hMp +/SgM5Bg#a_mRq&6D09YpX04g,GX'4Cqu-Elrr;utr8>T4`7=hbrr)orrVloT_#D5U]u.J!`3;k* +W(EM!GC+afM3a?fN.OREbfn/J`59C-^::aSa3)lXc-4DS_nERg\ZJfE]#DV*`5oj>_J=6pNM^6+ +Kp7sgOcPL:`PTI*_"Ia-rVlfpqW@;IrVlcq8c&>^j?dKp;,C8I??(%)C-ha)<]O\HMihqAPEhK& +M_f$3DNU?DP'fT-G;GAONbB_1Q'7Q!PEM>r@QQQ+r;HZqr;Q]qs8N#ss760hs8W&srr<!4r;HZi +kcq7kX/W%coDJXgrqu`orr2rtrr<#uq[rk=)'Bq>+X.gG)]]h<+4'ucr;Q`ps8E&trr)j-rqcTl +qW4E@T:ad6rVuosrr7K~> +rVuop%KGq*BQ^Vu`l#m?b/h[&`]1r\`P0I@c-+#Db/_QGd*BUL1_L`8'cD&?ccF/Ga2lEIc-4DQ +`l?0?_h:rs=^?6]`6-EN`PfdUaBd!3a2,mKHOp]q1+JWOOHYlr@P<Y&PE%J>D(q<:R$*b+><[@t +SW]A*N\,(25A*)UE6^7CIX?HZ:o:?ZBPoT.d)j>FcH+&Fc.'hE^::f*bJq]Ia2uKMgsXsHrps@j +nb2b2>bnE&`id%raMu9E_7?e"!*Vrc;-$[q:.n,M@K8YJ3]]Vt6:4II?XQuC36U@VoC)8HrVu_d +UO/Z>Dh=[o_nWgm]'T1`o&J'_f?)(S`lcZA^<+OsaABq!`l>g7d)@VDC0"D>M.(^VE+:KWR6`T> +3g,\DOcbrsRZ'(;6#VpTMN`HUAp?+oS;q8/8X5L+P`q8uO^L'oA'2j7bK.]B`Q$!?`l5sga;`.? +b08#LaMuHGb0%8f@TH6!<*E8-^<+UDbf]n*(rjP;c-OSXgmS<X'+u#j$5aTp$jZj4f?=07(s:(I +c-",Mbf\#H`Q-!?`j_I=:JtQ,mJ-\\!r`#nJ,~> +"9/5qrr)j%pYP-6s82irq>LEnqYpL!qYpEjrqcEfrsnW"`eS5B[f?4(s8Dutq>1'sr;$Bmf]2Jj +kkY2W!r`#miVldUr:p<ep8:;.>VD&%Q^=,+Q<$"^Q'RFgDfn]YQ'.MtMEQ)>L7=EiR[02,O@<&9 +9\B2P?Z^=,AVE`FJm`O[kkb>Zqu$KorVcWO`Pf^Fr;HZprYbb5q"2FYH$+7SF`;MOAo">\66-42 +!s&B+r;])21$eB#o^qkOq=sUFm_4qXnFQJOp[e(Mo'u/*7#-;-I=$$UCfD2X%jj$$SK&m^!!!',% +oI1eH%(b&o`+mhrr3)am.gSYs$c_Ys8W)uoKI;(:M=BZ7riWl?=Wm'AnWkZQ^a#&Q'%Ao5&XY#Q +^*r.P?q7,@6p*=P[R$OQ'@]"QB[YsO?,Cqo`+pgrr;<`s8;os!<2uq!rr8srr3Apjn&$9n_=*Dp +\Facs8W!5s8Moqs82cgpU_[m)'pIM*[;sM/]7V_qYgd!s8W)rr;6<frVmB,s68h=j6-IBrqlTjr +r7K~> +r;R!#rVF7$_>*j*rVlotqu6U"qYpEks82Tjs8W'1nG^=XA7i.Hq>^Kns8Voorr)iqrr3B(n=ubX +Uo`ANpA"Xcs5O#Us8;]mq":LM-Wi!ZQC!r+Pa#-+C6Om@1i7;*>Eb/7OGGu>1PD0ZO-l/pR#XO2 +6:oi,@p<hdBjlZd6\&N_46QM@s8;cns8N&ri5W[Qec#IGrW)oqrrLulrkhsY_8*jqMf5J<DKL&N +Jp_g"L6n<fL,d,obK.Z?^V.7o[C;-7eBc@^b0%fC^q@7e]LoHI]ZS7-`6,]BG'A%#T;kG<PE;)m +Nf:Zj_Sa1*p&G'jrr2lmk4&ELr_<FgqZ$Tps7AEm>tSU9D+/;YE*QoOoO_bh2jBelR$E_sN]_/] +9U1g-RZUiRCgTJlOHa0C8!T=,P*V>tOcVI[U%\Ncr;Zcqs8W)trr;Qgs8N0!r;Q]q(&e%,s8)B* +X/r5&XdIZ8s8W)rr;HWnrtYG2s82cfosc(]&g&,5(E4D2.Dc&YqYgKnrVlcq%fQ8%rr)GlS=lLe +q#16lrVqB~> +rr3Q.qYL3ZO^j-[`5Ta9b0%fHrPgh9_T^?J`lc<>`koU9da?Flb1i_*921]'bKe;OaN)3@bg"AU +aMu6@_R<lU>?GC$^rXgKcGdZ?ilHPpaM?$:a+l8g<@WiiQ^O>0PuTeZPa.4cDKJKUP`_;pM*,l: +Kpn3eR?`u(O$lc,33pq#:O%5-@Xgd6JQcS3aj85R_o9^:`QcoR\A#Pde]YtTb/_WHceQt'nFQ8E +oCMG.V0]1sMlOG2dEKVV_T0R&O9B,n8l&;\:d.ZP=]T&f!)#XD69mUq85`Vs=*R!Qna?,=lLb,M +_7-kLBWeX<TXD>J]t:rFp[dt9cg99*a2l9Cd(R08b5TIYahY^6bfJ;\-"C+RBk_T[FE;@s8(c-[ +?8"L3RuEYsOHkkiDH]c#Pa@l&>uYZK6'ICp@7EbPPaR]#Pa.Ak1FR[jcH+)N`l5p:aN2?>`q%24 +`lQ<Hb/hZDb/hWG]<HN_:e4Mg;3SZ2bg"ASaMu<Bai;BGd`KVMbaAkK#SROQ&Ju2a%%Gbcb/hZH +rlc,#aN2NJb/hTAa2l?@]W5XA:KWb<q#16mqg\~> +"98;rr;HX$j5KD*s7u]ns8)^#rVuflrVuoqqu-O-r;$?hs7lHjq"aperVZ]ms82imrWrGts8UL6 +md009rr`5rr;>OQ7K*5cr;QQa0j7p9Q^!PtPEqJ78kG)4Q:kJ$A4MiPP*qVt1N?3%PaRZ#QB[Y7 +->%MqqM86iGB?_T=)(<5E's3qr;QWns8W$'qV]?1_q"\`s8N!6s82T`_M<DZF)uSHG)RuISgPfm +#64`,qZ&;l7b7"uo(2PLr;?3Sm,MTtlh1/RqtKdTmd'2W9T"4EF*E"O>7L`?!>-o"S6I0PrW!?3 +&lNUiG'o;!o`+mhrr3)am.gSZs%31hs8D]lpA%a$B3ASY>=3IUF&JG$pPET-B9A=EPa7`$4^i4f +O-H#tQ'O7AF\-22P`m[t?'CJBOd)2sRuL*.qu$Eis82irm/I"^s8Ni5r;6Elrr2fps8D!JnauA9 +j8])Tr;HX#r;6Hmr;Q`prr3N)_(?rZ,:"N]-&:a\q>^KlrWrK&s8Mroqt^0grs&K&oBYo+f`(mR +q>:*hrdX~> +r;R-&r:m+_c27M<s8;iprVm0&s8Dins8W#orVmW1q>U9kp\Fj_p\aper;Z]pqu?ZprVlfrrs\o* +iKC1<UpBgoq=jgcs5O#DrVliqrql7=='I5AP`M/pP`o';7u`n#8Qot?7?Nt!Q^!LbDbX`)Q]IDr +P*8fj@<VDCLfJ),Db`l)BLc?G61Y$T%K6>+s8N&ri5W^Sec#IGrW)oqs'X^!_o'F0a2Pj,7&6YP +BlnuJG^F[\M3+*eMcdI2bK7fA^::Y_[BR&9^X:<JaN2?;^q[RmUfOt?ah5I0`4UD<H[9[8I&2(+ +LlmsbNf(Kf_o9F-p&G'jrr2lmk4&ELr_<@ks8Mfnq"[p"A5ufH=[?qHE)E)$qMK#0A<)e@Q'Rc! +4'ue^NKTTlPE[h9F%9i.P`m[t?'CJBOd)2sRuKs(qu6Qks82fps8W)trr;Thrr3&ur;QZp&GuJ( +s7b9NY,SS)SZ;Ses8N#r#lal(rr;ops8Drs&,3ac+!2OG*ZlMWkP4lQs82fqrVlfprsno(qYpNl +^7V$eVXs`br;HYG~> +rr3Q.q"O^NEaP!I`l#p:aNDTFrPfnta2Gj8bK@iFc-=GVaMlBFeB,tgcdC4dai;K@bJjJ)(<t(G +aMu3;_PBt6=]fFG^Wb'Mc,R]AilH2ab/_HAcdWt3==TPuO-u9"PZ::GNgZ/)>Adq?P*qH"Q&d\> +:1TQUOHu/qPZ/l3@E?T%6uINu:IJ&q86K@NcHjML`666A`66ZM\A#Pde]YtTb/_WHceQt'nFQ2; +o'thj:oLL-QF"cG`QcNCb/M=j]9k9`=@u:_9i+bj?!q;[!*rc#69[Ip9N,"s>\@'hmJ#`+oChdc +]#MRgK9NBcK;Z<"^qRSQp[dn7cg99*a2l9Cd(R08b5TIYa3)TD^<F^J3Ds-^?>a(;Ecc(]GgO]K +>TdgIO-PfkR$'R>D)[K=Q^*f#1MLr%AsS[F/Q5r=PFRc"Q^!u!7l/iEai2QG`l5p:aN2?>`q%22 +`lQ<Hb0%`Db/hfG`jCt:;b'S];.[>Ybg"ASaMu<@`Q?9Ic,n)Jc-W1"&J5?X&etjh_9BsCaiOD& +(!">8b08#L`l5p=ai;3)H;mU7F4^'_rrN)qJ,~> +s8E&pqu-O#iSOV7p](9ls3goHrseGUmd0B6s8N&ur;$6eiVldUrVZ]nr/iX64)gLROIMAqRq>&H +NKf`d2fNdmNL#otQBuJKEAW`DP*qT#RVF-MZhjF+7riir7tP;`4)AY,p](6ls8W#srVcTN`P]UD +r;HZpra,X%q"2FZH$+1QE-H_.I@XOm'*8.6!<`K-!!!*$(eV@+mdTc;p](-gnEGp*459H.r;69_ +m-a0,U1TL9G^Xga<>boE!!!<O)Od$3+q=SQ#80jPFDQJeeF`e>rr2p"kj8*Drr;lps85$F9m&'k +ASY7cH#GP:p\=#;07o@QRZ<Vr>$5E'Pa@MqS=!k[G$RY,OdLVU1Q7QdOI),sR$*_[4]M=UqYgH\ +rr2iqrtbV3qu$EmqY^<ls5<D2p%%k,s8W&prr2rtqtU.#rVuE!H=C`E]^c%#rVuilrr<!%rqu]k +q>UBn#QFJts5iY6h>[EWrqcQlrdX~> +!<)lr$N9hbTV(uWqZ$Tnqu6Bjs8E#snc&Leq>UBn$i@T*VPgN:rVu`irr)lUr_`Rks8W%Z/lXcI +PaIK#OcYuA68XU`P__27E%m37Q'IT!Cc62eNL#ZmPEVAI,ZCuGqRK%2E,S*n@UM-.BMJ:%s8Drs +qZ$QprSY]6`7=hbrr)orrVnM,_8F1/a2#a/EJ^H1CNFcKI!^*_I!LI/P)!_Kbf@lJ_7dIc\$E8X +>uAbfb/4.o#J7je]nC=7^Abtob--A<I!L*bDFLV,8U$/WNKB",aMkj5_=dj.rVlfpqW@;IqYpNp +s8GLdPY6'J<FKN:D00PKrVQKY5;%JJQ^a&#O]Y[p5a%CnOIDJF89A'*R?<kd2)C2UR?3buQ^Er$ +FZWP#qtg?mrr2rtrr2osoD\ah!r`&rrr3c1s8;orr9:MkUTpntPkP(UrVZ]qrVlfrrr2lr%K-1l +[<5eiJ@P%Ir;HZlrr<#srr)j+rq?<js8LK>S=l_>q#:3kJ,~> +&c;V.rV6*[dq2^p`l$$@`5p+"aS<aZaNVoQbf\*+aT'E_bl>fcaSj*ZaNFJ*'["M:`PoT?=B\j: +J\&hFdEftS_oC]WGg4=Jbf\=R*)/>0Q'RK%PEVGH6T'gdQ&.D;EA<E;QBmf%D)ZDiNgGlqPa%SM ++A/$D_2g3dI<@l&?">p+>;=LJ`Pfd?a2Z'@d`/f3]Xu_;`lcHEai_rbdbO?`na>N(eolb@J!@(I +^qRP%a3)38_mkk!>?`%792/&V>Zb6<F@JbNE`G[o6V:EZ<E3EtDV*tKkp6/e\?j&lah+6X[BWr# +[_fl#_sdBiki^:Yf?)(S`lcZA^<+OsaT'CXaMu6@c.-tqAgC>bBMiM^?lRY<bf;@fKp@gdMNX-* +=Ca^]QB75uQXi[1>Xt3ER"$tLN0K`lQ]d]&P*L2D1sX.[bfn)G`Q$!?`l5sgaT'7"b08)P`l?!C +b0.`:VI`do:/+_^ZbXi0bK@oGa8X*YbV72Z_nj@:g<uU#5tkp`ce-Obai2?Dbf\)L`l5p:b08#L +`l6':bJq?/OB5%MC;B06rrN)qJ,~> +s8N,qqu6U%qr?c;s8)]orr:IHrr3>_l1=E)s8W#ss8N#piVk8(s82cno;"'B17jbqS!K>-Q'=9s +DO$QT?rV)[6&q@sPa.Fs:hhqPrf\^tPERF_jo>2W6Z$pf<(1+eAoLA9r;6Kms8N&urVcTN`P]UB +r;HZprY#8.q"2FZH$+7JKmS/2S<Y07"o\Km!sSr2!!WK-+\IaVoC1u8q=FLTkEo%.1IC$brqcTf +o]kl*X)=)QGC4:++U\SW!!!*20M%dO+W(Ib"qXI?G&htieF`e>rr2p"kj8*Drr;lps84_DFBNL* +GZK$2EEd)Oqu?1O@?I%EOdDJA<GXIJQB.T(O,u_@D+8T+R#b$F2j]\hRZNu"rfmeL8"oq\s8Mlp +s6K[ar;Zd4rqu]nrr;fkr;Zf`lL=<7qVM&Js82corrN#pq#1d%s8W&mp\OO[s82Wks8Voos8N9% +r;?Hhrr2p&r:U*ijQc$err3-#qu6TmJ,~> +!<2rs$N'VNUT4"erVulqqu6Bjs8E#srVlBfq#1d'rr2GaSu8Wij8T)UqYgBmir1A's8;lroV=*> +/tA,hR?j,)PEIjkCm1-L?;bZS5E(qkP*;"k:1uMHrfJOoOc_%Wj8])X6>17V;*nJX@Vn]0rVZ]o +rqu`prr;rT`l,gHrVc`p!<)lr!T(Zl_csdu]rY,,Ue#HKH[L0dG^"=SJ:ioBDM,sOb/2*5Z*psG +J6I#1:X$Sn_T0I,]"bY5GIbW.a1n[/H%1-aI=,pSA#tDdIufVRLpY"?_8F+^s8W&srr)]UnGi4] +2?!&d=DW)%;K?bp=D%F0s78NaO-u;sR$q8YC,(L.NLQ5nN^72k6ue3RO&&k:Q]dH!OID:1Pn/^> +T`=ujrqcWns8W)ts8VZhrr<#s!<2ut!rN#rrr3;q`j)SGWi2?:q#:3ls8N#ss8N#rrsSf)rqc<\ +q"":\qYC-jr;Q]qrVlcq!W2Zjrs.GXS=QA(q#:3kJ,~> +&cDV-s8)EV]ObN`aiM]G`Q64#aS<a\aNVoQbf\#H`r3mO`WF6(b5TU"b/hZD`PJll>$G<AT>&Cm +dEThQ_oCZV-dKWKbK>V_:bA6&Od_Z(R$<do6Z&'RQ=!R/Bg@ZFP*;,n5#5lNOoCLmR$*UX2p0Ib +dNi@DE(i>m7q$!gJ^MBQ`5]pA`l-'K`jidr]@G*Eb0">:ai_rbdbO?`n`KH!]hk6"A?!;[^q77q +_nj()]XjP25$:KN78?fY>?GcJ<fM;KG"tb1?!CH*<EW:Ef]VPgmc2-l^Ve%6_lB2J[?ks5^Ve75 +lgFB0j3R)DaiDKBb0[i9aiaV(s3(Jcrl@"AdEbl^?YsaXDJ!6E8C5W4c7rReS<8bnQ!..&15M3U +S<o7s6=jt%EfHHI:KTQBP)u,oRZRN6%uNH"dE0YU`l?!:`lQ6@`q%4M``(%(bf[rE`6HHMahkB4 +>"hL\<(rIfb07uLa2Q*?`l?0FaMl!1_oL-Vg!n?rbgb(`_oBg>aND`LaMu3:`Q$'Eb/hTA`l?6D +_7uXN8P<HkkPP5X!;h9~> +s8W,rrr32hiUHmIrVQToe,K@H#Li58n_=*Dr;Q]trquZPr_raprVZWic7_#.Pa@YtQ'IH%M`tN- +Q][8o4D8XoMNX9iQ(3nZ6XEWUPb4,'Q\S8hq>0j]<`a<dBmFZ983u_Dqu6TprVuorrVGHk_o't$ +rVulr&c_b'oYQE0F`r7aMFEH#5qW]H!!!*"#:K][!!FTLJEudoo'H2Co\ll3+rDFV0[TLWnGi4X +lJ\1KN.PbX>S[G@!#Pb;!!O&ZOJ"QV)@6BX9lFuqJ;r(Ns8Drrrr_KOq#:9mq>NSXTQ3D"AS>s[ +5Y_4Wp[lX!SW]A*P*TTOF>0)NR%'8)P%%@,@nMfNP&3R(1lIWdP$=-;PEV8s6g+1As8)`pkPkMZ +!<2ut(&@b)s8W&Xo^25Gk264=rVQTos8Mumrr<!"rV?BhrrE&trrN)qq>UBn"TJ>rqu6Tp#lF;p +s5rV4iUm-L"8i,urdX~> +!<2rs#l=83VS)R#s8D]kqu?Nlo)JC^%K5:PUo(9!q>UEmr;HWos5O#UqZ$Qns8("m1P:jUP`M#l +Ngkkf?8\"/Mj6>8D)d?5QB[Z)NHINl:R%$5P*D;f8_O">q>!rfDKKH4CMQ=&n,N=crr;lps8N&s +i5W^Rf)>RHrW)oqs'X^"_o'@/]!u43X'][aH$k!dH[0maH$=:]Mgfuo`l?0:`jiUbRpTuPGAp3e +ah>F*[_T>WIs8<>]th:1Fa/%SI<Bm`Dbd%':htoMMN>9k_o9L/p&G'jrr2lmk4&EEr^d"fTQ*7q +@:X.K4A#MOq=i*(S<0&$Od0BKE\<ZFQC3i!OC1q$@7ZBHP&3R(1lIWdP$=-;PEV8o5j%h>s8)cp +rr<#trr<#hrr2rsrr<!#rr)lqrr3H(gon&cXK.u!p\b!hs8N#ss8N#qrs8Suqu?]qs8W)trrN,s +r;QZp"9/8urr2p!qY^?lrs.tqT:MRjq#1-jJ,~> +s8Dut$iTYXS7H]ObK\5M`qd^Q`rF-Zb5]Q_`r*gO`rF-Xb5KBn`P8*H?<grP[)'o0ccjJM`Q$oY +FN;YF`6HZ7*\N,0QBI>qQB.Pn4^U+5OGoJeB5T_dOd;5sS;qbZ>u6fMSs#>)Jj@2s`lQ[u8nD^> +C1Uj6.*KrR_8=78bJqKDd`/f3]Xu_;`lcHEai_rbdbO?`oCV1uFHNbNS%d+ha2,R.^qme'\@>&' +Cd;Q)9Me5X9j(_6@$@apHn8r=?=-f,<DcpjG1H'Jp%H;;^V.Y1`5T?[A[&[\P./EHaR&]hn)Vg] +f?)(S`lcZA^<+OsaT'Hab5TIRbg4pj<@gF9=^4!4/D8OqbcEdjOdD5iOBkG!0:/)nRZWkt@8^oN +8WK7&D*r1tMj9Zm>EbG<PEh:iaNMcK`m2TC`Q$!?`l@Sjrl-k=bfn5L`Q$*DcH4,@QX!T_8l&6# +]>i%9`l5p<ai;?Cb/hQ<^Ve%4aNrDdcIC1_a2c3=_oVi")T]n8_8F77bfn5L`PfmAb/2*$CedT) +OlH07rr2usJ,~> +s8W,srr3&Yg&1jL!r;lrdf0:H%e&-Co]t`@s8Mros8W#piVldUrr<#ns5#:VOHH!$P!"kqPF4aO +:gT<SQ&[eADE3f@UQ1M,P"&\[;N[**R?EnHTE"laqk80t<*W'\9YU?&rVulqs8W&trVcTL`59F@ +r;HZprXo2-q"2FZH$+@ZMfqjeK-qKAquB4i"pG&7"9]Q9H0b+pmJ>u4k0Ye)$jI%L0MosVm.L5J +nEZ9bNd5SB$3C>2!!<H+!s02_3NJ)b(CC<]7:UIhI>ubKs8Drrrr_KOq#:9mq>N\XoD6Fe<('E? +p%eLaqYQmrNKfTnQ(0mH:1fNMPF7Yq9j_[T3KfbpO?I/\99Gd/Hm3ErPa%N%?E4#%s8Vops69O^ +quH`prtY;(qYpNpi9p(,q<QQ1s8Mons8W)sq>Lp$qu6WqqtpBhq>C9mr;?Tirr2p.r;6Eks8W&r +pAb0Zl0[Zurr3*"s8W(K~> +!<2rs#lO>#User8s82Qiqu?]qoD\pls8N&jrX&N!aI/j"X31D>rr*#urr<#Wrr;rss#^)WhC9t7 +O-lAu3ffYjQU#1Y>`bA;N&>Hg2ia#qNfofl6s<\hO,oKmP*TLHs8VomTQE=p=\(YH\bQ.'%fQG, +qu?ZqrSbc7`7Fncrr)orrVmAa_8F1-]=XG;UQJMgG'a+6s*77bGBe7ZH#n#H_oBI7\%95d6Z@?p +GB%_4]#_Us]XthgG_N]EbI2J6IXcNhJTlQjH=KsTP#?%JMiY'U`5o^0p&G'jrr2lmk4&ECr^-8R +`/[_^8r<*4q>^?jT4X%FOHu-#3FkfoN006hP)N%>Bl5kkQBdOpAR.rkSWeFFD46]RQ]t^Rs82ir +q>UBns8Muts760fs82d.s8N&urVc)fZ*1C6URq&Qrr<#trW)usrr)lsr;Q`rq[!2uqYgHorVccp +rqucurr)fprr3W.rr)lrs7sF(T:`F]rVuosrr7K~> +s8Drs$M<#)@#2D;ccX>Kq8iHQs2afO"3AL'`r4!Xb596k`Ogh(?X%#k\AQJ6c-",I`o5!Gb/_TF +aP+QO-'+.UR#a=lR?Eq'BMVorRZrdiDJ_@oOe[r"RZU$C=](9BPF7Ss=,>PTaOGlM-p:$W.la<X +g<IUQ_8smDa2H0L`jidr]@G*Eb0%cHb0Skkh!jq,>jgj`EN,OVU;bI&aMl!1]Y;)%`P%^R4D@Mb +7o_uTAqVq#\\PkNIlVY"Al;E$=_:$Ug[Y=6[(XZ+_TL0@`4`=*C:pKdPdS<FiTfh'im6uCaiDKB +b0[i9aiaV(rlY5]8]o9'bgrY34"W1'cI("fdFa(PLQdjeOHq_49kB<IP*hGm9O;IP30BPmO?I/\ +99Gd/Hm3ErPa%N";N'#Gbg48J`Poj>b/hTnaSs1"b08)P`l6!@b0A&I^o:aE9hS2U=LH,jaMu3< +aNOP'1WIDO_7dY'bKJ#Lb/1s3`l>p7b/h`JaMu3<_o'I9bfn5L`Pfp@bf.W9HrNg?HJ.odrVlhI~> +s8N<%r;Q`rgsZ3%!ri)sdJj1G"P)`,o]#lM#6+Mss8W)riVl4Er;Q`hrO=s`Padf"HS0N.OI9TK +D(hKCPaQJXFC[CrNg5ouR?BsP3KoksR#RPq:%nG`q==F]O*d\crV?Kis8W)trs\l+rVcTL`59F@ +r;HZprXo2-q"2FZH$+@^P:qia.juJCquH`urr>Cg!Ws94OR;r9qs3S9]f%e_!!`K5&1fcCjm2C' +lfG9UM/u-%#mgS3#6=f4#R(qe-\/'j2A?H/=)re0H]?PIs8Drrrr_KOq#:9mq>NSVs8Moiq"FFU +rr;ljqs$P1T95V0P[7-t5F%\$Q'db.?upESI@$+U2f3P:;jNN/M_n=qPF7T#D2n8hq#(-kli%%e +rqlTjrVm?*q"ad`s8VKJn+6>CgA_-PqZ$TirW`E#r;Zfpr;Q^"rVQNls8Vims8W,s!<2ut$2OW" +s8VcQmH`d.s*t~> +s8N#t$N0.fVWR^Qqtg?ko)AIbn,E=drr*K,oqnL[VPrh[rVlisrr)iriVl+Bqu?]jrjY!^P*qAp +H7X3'NgF0CCFu';P*^&PEagtlNg5osQ]==B23F5kR#RMm9_\Mcqt'^]N-CrTqXsj`rVm?+s82iq +s8Cor`5L7*rVlcrrVcb(hSI+I_S*`VS?5M$I<Km\H$Xd^H?sd]H$sgOKZ(d=`4Nh(W_7DVGC=Ra +F`C?N]=u%l]![`8[D8YfH$aXWJTl-\F`VeI=GN\\CO:bi^r=F.^qfXCs8DrrrVG[Gs7lQps8N#s +s$6MVq"FFQqu?Ngqs$M0SroM-P$Lgo4d27qPEq>&??(!KH^0\O2f3P:;jNN/M_n=qPF7SsC5hoe +q#(0krr<#drW3&urr2utrr)fq%0$/%p;=#;Yct'pg%bOGqu6Kms8Dut!WDrqrrW2trVlirrqcZp +r;uuus8N!/r;Z`or6h=2T;^uOs8W)ss*t~> +&,Z>)s8V`2E*o0JaNi#P`U_(M`r<sU`qmaYb/h`HrQ>,\rl4uZ%EcSs@U<;G?_k<Rbfn5caAp@" +`Q6$JSh!<pRZNYV/U!D?QsrO$/tJ)fQu><4@lT^5Q'Rf)O$RA9P*hQ&NL,>[f@&*kbLbEa>(aiL +dauae`4s=5d)sDJaj@u9^V%2/bJq]IB#i$9ceQt(nFQ2:l!ga-Asg3IaiDE>^q7.j^s:3ETOgr7 +<(0SV=(uSBQ*7g;[_/5`7;$=;;c$G$?>%p_j1i4E_8=F4\\GSYYF9X$Z#tr&\[_%onEoDdm+9A" +aMuBL]tVV2rlG)]s2[aNaN2WQe'udpeC)Ugf$)Ilc7Xd<Oe%l'=\<0fPaR]!Q]asJEcXElQB@+b +D/iZVQB7;g1fBO$R?EkGDTg;Ab0@rF`l?0DnAtUK+NhpPb/M9<a32cO`PT!+<_c1Z:fEt'aiDE= +`QHEIaN4;!&';`*`Q6!=b0.iD_SjI:bPoT]`r<plb08)P`l5p;a3_rJ_2q\n;/+/=o_\XfJ,~> +s8W,t"T8<"g"$*%s8E#udJj1G%*S24o&9WIs8Moms8V!Us8PI`rr;YFB98CCQBto9G*SM^QrI4+ +0U//eRS-n-DDmoKQB7?!HU;:+NLc)rOdgr;qt0pgr;HZnrr;ons8;onrr;oqrsJZ%ptis+_peP^ +s8N!0s82T`_MEJ[H%B1-T5#l"&eFmIrsV='$OHn?-:4Kks7H6Me=Ar_+qY@n$iphU1JWn`jQ>gm +a\%:N,U=BP*uQ(?*%<-_,r.bAUR38J'cKJaG'8OueF`e>rr2p"kj8*Drr;fn/cYP>p](*ir;ZWk +s82^^Ng#isP`D"`DE<o?PFIo!:g7jW=]1TOQ]*e?9P0RhQO8IL:6Uj/OdCu.q>UBqp](9[rr<!# +rqZ?erVm#tq"ajdrr3GfmdBc=k3N'Iqt^6ks7ZHlr;cirrr`)prr2os!;uZl$iL#(s8;fos8W)n +rr)j"ip?!gq"t)A~> +s8EK+rr;iGUp'FfrVHEkrUKmcs6]gas8N!-qrsBEV5UKms8N#ts8MuRr_`^ns8VeHAWN%<Q'P]5 +FH`)VQ;Ue#/s;`]Qq:J%Cc7]IQB%,nG<TFrMk,lpOdCT5rV$9krqu`kr;6<brql`ns8VuqrVuls +ro(o9`7Fncrr)orrVm>`_8F1-\:AY(Kj&A7Gl;pdH:iR1FEr4;OhJrMaM#-A94i6dI<p?bI!':) +GJV,)\[8>4Z&+'gKnbM?N/E:IKSkA;J4QQ/6#D(+WQ;omah[TLs8DrrrVG[Gs8)`ls"+!Bq>^Bm +qu?HfrquX\N0BTpPDbVYD)mZ9OdVJn:0DFO=&>0GQ&IS=9P0RhQO8IL:6Uj/OckN%qYpKsp\t0l +m/@"`rr3-#rVZWnrVuor$N/baYH>%0S[8"grr3-#rVc`prr;lpr;QlqrVulrrrN&srVulrs8Nr7 +r;Q`rrr<#ss82ZjjJ8?<U=T5As8DlpJ,~> +rql`q$M(9-AurYbc-FPPn]:^K!li=&q9&`Yqo\r[rPnlY&^&"j:Ld[=B"#Fpbf\#H`lcH^aD/i6 +`QcV@<f<3+PE]3+Fd/;ZQW%"'09_raR7^\)D)RfJQB.5qGX#Y!N1GuqO-F`_fZ2@cc-Fhff%&'h +cHFGF^W=C>c,mrHd)<B-]Xu_;`lcHEai_rbdbO?`mGFIf]U3r6XLZ']_,.q[\$`c^_na$]85il# +8m>V:;Ds0.[(s5`Y-FdT5<sC)>?tWU9[UPj`kog@bL+MNa2#a/\"?[$W`bReZIAF2oC1/of?)(S +`lcZA^<+OpaT'76`Q#p@`5p$Nc.("fa2uWVh(O87P*_Q!QnE)3OH#ElQAn[DDJrWSQB[\o2/c0# +Q2[*bL0.37P*qGuJN;$&c-O;I`Q$!Abf]Isrl-&&bfn5K_o9X>cHXJL]9QSq77g9WGe_8=`5BR: +c-4?0`W4*ZbR_e5^r+17be_3:aNMfN`lS+u)T^(B`Pp!Dbf[rE`l?'FbJqGp>>@k!Z0:`Qrr7K~> +s8W,u"T/5jgY_o.dJaRSo%3R,n+6SXr;6BhrVtgT;ZH^os7U;^P+Ru*PZgLMPEM8nRQ,/(6Bn(( +P;R8p@m,j:Ss,Y0A56*5O-l6"PF#IWr;$'as7H?kq>^Kms8Moqs8N#ts82cihSd:Ke,91Err-7( +qtTg#Lj=,jMC5$Y.=-&B?sR#B?!LQ:>@:W7<,,FVmd]r(b@k=OHuEk=AnGphCj_=d;Sq>Yo$g-q +H"h#4Bm+6$CN"*1Dea6;;JDk9:j$M:A8Za;NR[V#rVlfr"6f+Hrr2rnrW)ips#TlMs8Vrqs8Dgr +O-Z*#OdM=uBKLU.R[98)A5@5c?9*n)Q@LZ0=A4sFP*:l";bE=<Q^<nj@e0Qsrr2rarr<!#rqQ6b +rVmZ1q"Xgfrr<#amI'K8o%O-Cq=spgs8Dcm!<)os"T85squ-No"8r&os8)^'r;6Els8Mrrs8Mrl +qu-NtkNqNmkPP:0~> +%fQD*s8Vo4U;-['rV?Ejrr;Ths8Vcks8Voor;Zfr#PuW5W2?Q4qY^Bnrr;rUr_i^prr2rlD1Rh? +P*V;76qi`)Q&V.hCMuJ$S<&dgD/*QDNg-&rQ]b`K;IGQQQC!Ys=gA#+qZ$Tfs8Mcms82iqrVulp +qu-Qos8Lut`5L7*rVlcrrVcb(hSI+I_72k7TLuH%[^`fT[C*HQ\?WTT]",+TZ,OJo[(0mh]t_@q +]tMA2_SX."LJb1[[C*&)]=kqp`k0@2^;e1._8!Y$_L$^1Fb@NMT";YX]#"(>s8DrrrVG[Gs8;lm +rrDurs$$8Ws8Vlns8DgpNK]WqOdD.nAib:(R$Ei!@SLf[>W7J!P^Y<,=A4sFP*:l";bE=<Q^<_b +@IsNsrr;uss6T^brVc`trVZTkrtPJ2s7*V(Xfnn&RIL+Rs8N#rr;Q]prr`9!rVZZps8E)uqu-No +!rMilr;Zfr$2sl's8;fos8N#rrsnr&qt$k\SY=%#s8W#orI=~> +%f-#!s8VVP>B[Ec`m)rSrl4oXprWf^`l?*@b0'\,s2tA_s2G&]rQGAdaN2C#`>$>5b/9*:@U<Pn +\%p)-aMu3=b08#faAp:'`5L'J;0%YfPE_206;!E'QB%@lCiD\(SWK!kDJN`FNg-)tR$1rO;dk`S +QC!Vk8!;<A^W"@4e'>tYc,7fI^;7e1cHXJMaj@u7^V%2/bJq]IB#i$9ceQt(nFPkj:U$["bi7UF +m.C&Fo'G]-oC;>;a>mO2:/k;=7rm>Kp%S=Sp\jRRld(2=G][_1CHBr4p\+@Iqt]p`qsa7Wq"!0j +I^=m(j6OeRnb:kcm+9A"aMuBL]tVV2rQ,#Ys2@RI`Po^;c-*uDbK7`Eb0/C#J;fSTPF\+1B/Y%$ +R?j&%@nq#_>r[\%Q%(K.=A4sFP*:l";bE=<Q^<k_6c[Qnbfn/J`lQBJb43RP`ZN@Ibf[oB_o9dB +c-+)BWb50t7o*Gu\\uM*_Ss[Abf]q)#g1K@cHjYO^Vp)ms32e3b0%oI`Poj<b0A/L`QHEKb/VE> +`luZMa2>2m;+b#akO&!Bs*t~> +!<)os"TJGhhrt"<!W;uVrWE3"rqu`os82lrr;R#Okk"E,s8W&squH`ps53fPs82fjBmuG4R[0.9 +;`Bu*R[B.j4)[>XQ'dVu:hFQD?B:88PaddrD)mB5S!02+PXP$9s8)Wmq>UEjr;Zcms8Vrqs8Dur +rVGBh_o'purVlisrET9rotlH/H%Sn6TjD2`FEM\IF)uJFEH-)EDfg)Q;;C<se;$VGPCImqH@C9\ +EcQ8FIuKLdFMlh^@=a#ZEcuqPF`qbIG'nCWE-@$fSY7W_G%PW<Dgm\qo`+phrr_KMq#:9mq>N\[ +q>:-hqu?Torr)\p?BpkEQ'IPo2.&_;Pa%H#JNmpc;bEIAQs_[eD`<fCQ'I`#0iq/7PE_?#O&>cR +q>^Ens6Tabrr`8rq#(-k(B44,p](9js8VNRn*K]Df`2!HpA=miq#1Bqr;$9gs8W#srrW2us8)^# +r;6Els8Mrrs8Mp&q#CBms6K(:j5Tt9J,~> +&H)S+rr;i(VTf)7s82fns8W)ts8V?_s8VrprVm9)rVc`lVl$;fX5`sQs8W)urSdbUrD`gprqU8U +Q]RT!P#>19PED5uNJ'</4\M!)NKd1KD,ai&OHbinNAbQ2LQJ!fQ'@G!o)/Ofr;ZNhs7uTmrqcZp +q>^Ejs8DuriQ&mUf)GUHrVc`orsml%_ns3/Kr]-J^qRq1`W!^n_o9U3`PKR3\5gDa`OUCuT=VJK +]t_M+^r=:2rkC+j=D">2ZX007a2#X7]>_k-_nX.(aMYj09VeR\[Dp&#bItg0p&G'jrr2ilk4&EL +rqQKnqYpLXrr;rsrVZJl?':M?Pa.Gk10m53P*2#pIm%L[;+R%9Q<l7_D`<fCQ'I`#0iq/7PE_>s +N)9EOq>^Emrr;?a!<)os"9/8rr;Q^+rr;uqs7jL>Z)t1.PO&#Crso&,r;Q]qs8N#rrVuflrVZ]q +r;ZfsrVZ]qrZ(n9s8W&rrr;usrVuoqqY^9g[A9Ch])2O,r;6JD~> +&GZ/"s8VD6=bFK%aNW&QaN"5#s2P)[q9&`YrQ>)_rlPSh`l?*Bbg"AUaN"4u!65#Z$Gg7X>@(j3 +]>r(8rl"u\bfn5haT'4ra2?'G:N)DYS!T43:,J2uR?rqf3c7,TPa@Dq:M"BB?B:56OdM.fCcI33 +S!')"L+^`nbJ1p=`66ND^r4=4`PoX:bf\&Jc-jP=]Xk`+bfIlF`Q?9Mgsk3OmGE>IX`pDoj6l:) +qYU-aoCGiMp@7hB_BWr.A8":mUuC\6nFlYPmHsB:o'>#88PFGKIS[*,qXO4Nkk=lFoBc2Js6ngh +;6I61ali'fs6J[ilIX.saN2TP]thh4`lQ0>`W!kK`P]O1^;S(4`Q5s<`Q$)\98f$uOHl)p3F4t: +PEV5tJ3I^_;G!7=QX;IbD`<fCQ'I`#0iq/7PE_?"Keh!"_p?HG`l?*Dbf]Frs2P)];p<D(`Poj> +aN_oG_6nDf9L_f`;R=3X`59L9bKS,K`lQ<KdF-1R_o9^@cHOAPc-OYXbJqN?`lQ<Ibf7WCb08#J +`PfgAai_fF]l-tF=c(r#p&=uA~> +!W;inrr_BBrVHHl!;tjUrr36$qu$Hnrr)Zkrt#,/e+*.tg].<Ns8W)ts8UsT3rT!VrUjcVOdV?! +P?M-OJ!ZIeQ'5oUE^rroQBlM>Bm3WRQC=&+Q>Aoq:Q_04R$EtdC%qB%rr2rto_o0prVGBi`5Bpo +r;Q^HqY:'ho=fm(H@nATQ8jqSF`D;;EclPJEcH5BI"$s5?Iul97;[d0IXucfrHS?f/UD>\I!gcf +6<0FtB9IggG]n4NF*;hSG]mtKG^O(8Vg(BeA9N69Iu)_JrVuiqrs%]To)AUbs7-(Kq>^?b8s#L1 +R$F#'3+"b1Q'@W#P<WMu8l1b8Q'=(EE(OT)Pa@Z%F['#(Q'df&Q&\i?r;?Tls8VEa#ljo%r;Q]q +s8N#qrr2os%c6RCnb)&:s8DWfrVuirir0&Xrr<#rrr2iqrs&K&puCPof_kaLrdX~> +&-)V-rV,WTUu_4Ks8Dors8N#qs7H<is7uWrrVlfrrr2rts8EZ0qY^9`R\cp]\+Te$rVlisrr(dS +s8OtUqu?QbA:p#4OHu#3=#YSnPa%AoB1d,3:7%30D^T4A<_\jIPF.VN6=*EKS!0/%Q%!HCqYpNo +r<3-"s8N#qs8W(@r;QWQ`l,jKrVuors8Murs8C`j`4E6OX.W1r\\cJ/`l,a2_o9X9_8EpsWa*ND +EE&(8^q7@s_SO+,_ns:/]>hk*_3eD+P';/_^:_D#_Sa:.^qde*^W==-OD:MIC50==`4Nt%q#:3k +qYg<gk4JNMrqcWorVlcqrVlis48T!Rogb"-R$X,+Q8i53OHYloP`e4=F%K/kOd)%bE,\BZPa%N" +QZYMq:6h32Q]R,(qu$Blqu6Tps6K[as8W'!rVlcqrr*9'p#30]Z)XXm`:a-0!ri/ppAY'kpAY!i +s8N&ur;H`srr2p-rVlfma.]9#V==H`r;HVF~> +&-)S+qt8<E;51bJcHOGQ`r=$``l5p:`lQ=$bl>icbQ>r.aSs3ZaSa1$aMu6Dc-=JR`Q,p<bK@rE +[T-L7>A^[gc-"&D_oD\uilFL,`Pfa@aN@5$M3jU'P#YC:I$U%_P`f]QECN`kQ'H;:Aoq!FPF%Dt +PA*9e9TGO*Q^!VQ;:<G)_o9dBc-"&FaN2C#`AtrZaNDr_`jE7b]@PES`l,d6bgkItjR_3G;Q-R( +g>VDgn+$&Do^hV?mHXH5hQAYe@l$!%e)]`^rq$urmHa**p$D><gt8T24a([mg$850qY:$_s7C4- +o_7\,UN<;iF/A.#qrcqZmFK4s_p6ZY]u\7:`59^8`QHEKaMYd/_oU'GaMl'2bf\<iKU%sjOctnc +?TO=6Od)#j4C<(u9p(L"OYCZl8S"'MQ^*n[5?UaHR$<r%KK%<$`mMiH`Poj>bf]:n"Nng,`lA#! +'?\D;`O_O>:K("^:PQX+aN2?A`V[^Zb08#NaSs0]aNDTFr6#&\r5ScXs2P)["3S^+`r='Zb5]Nj +^4]K_:hI]3qu-QpJ,~> +!VuTkrsJ_cjo>;Xqu-Qpr8R_Trs/Gsr;Zfrr;$9j&G=`Ip#b<7rqcZprr2rtrqtaS48o3ZrVuk1 +H^U+cO-s<I=^dbZS!95+8mH+D4I)"uNBh&l=CI/SP*M>-?S@b)R?a))O\s:#q>UBns7H9tr;HKM +`Pf[AnGi=`s!dmGp%$(RI=aD;SP4?hLiR<LDfp;LG&qYAE.<Ou<*rC"JW#5&G(=d]rc\<ds*?/A +H#mqAEHalB7l2?JK7@c]F`V\MH$FLTEI)VPJOPcm4>M&&FFA\%eai_>$3'u&kMu@9s8Vlar\jfL +s.WqeP*2&qQ$c"r<g]D@R$:*LCenB$Pa?VQCiW3\Q^F&%P)r4H94<pCR?Enj@/'Quq>UELrr2p* +iTT\&p$LQ7s7cEgrr:IHs8N2[jlG=srrE%K~> +&c_k0r:o'AVssT`rql]ps8N#ps7uZorVulps8)`prVum:rr)irs8MupqYL0HR\Qg^anl&9r;HZq +rr)irir24Crr;uprqpARR?X)"QX*-_@$ln@P*D8'>%hJ.PE))i5@eS3@#L;4Pa+pK/s_E_Q'R\s +:Wre7s8W)srVlfrrr2iq%0$2(qr#N6`nL4fp@eIb.JE`$_8NidRA4#S]u\+1a2c*7_Sa=3`4s:* +\9<%%@[agG^W+@._8=(g_uIRQ_\9u*_8aTUFC[s*]Y_b&_8=.._SH/f&\c?#`O8d2WEsPY^;%h3 +a7fK2rri)npZ:Z<rs&5ts8Muqrr)j!rr)fprr5%Ps.Ne^OH>]nQ@24u<0iu9Q]jmHCJJ/uPEpDM +CN3$ZQ^F&%P)r4H94<pCR?E_b?hjNuq>^Hns8UsT&H2Il\[&<=WMZN^rr<#rrVu'[qu?6d$iA\U +U7nC>q>U?krdX~> +s8No6q!GUo<3XHiccF2J`lQ6@`l5j7`lQ=%bl5cbblZ&/`r<q&`lQ<Fbf\)L`Q$-Hc-42H`l-$E +b/V>i<EN@-I^m\Kbf7K:aSs?Aa@+%d`llNJdnstCP,+S9=[Q%mR>mZ!Q'Y'HBkBGkO.2(k@VSnL +M3F!`P=f(2P_k]kQBmFoXO4l%_oU'HbfIfFb/hU%`?3+@b1,+aZF@6TdFc@N`6?ENbhLq2nC2$9 +Tkh$sp?qqKD=R5hnaGl0kkXZ#Jmpc*KY-+*q>0UQo^hP;lKdj/o^hV?n*d-!@SB;Cli6hYq"+%I +o^h_Ko(_M<eRY&A?]".Ep@R=klda+sb/r&W]Y2S1aN2-6`QHHMb/M35`QHHMb/M3>^Xe$8Ng#Y_ +P`h,N5tt@GRuint6saS$>EFu3FYd`M9P'QXQ'7Am87kM'OH5fmQ?u!Eaiq`K`l5p:rlX3@&&uJc +@T$*$8PWa,aNVfH`obAA`WF-!`q%1Y^R&,$;I6Hgr;HZqJ,~> +!W2forsJ/Oli7"_q>C9mrSmhUs8Vm!r;Zfrqtg9irt*uBo(;,>s8;`ns8N#ts8MrTr\sfTs82ir +FENk1Q'.MO9klJCSs>S*PE\7JDEUdfOID@nCi:nkSX>h,O??6:S!KA(Q^DEDo`+F[$2jbui5NXP +c2[eBs!da8qYKs"H$b':Rts^mIW]^KEcubVH?aLNGBJ(QHiPES>(D*NFEMeMrHA0_3-KLlI!BUC +0-MoQK33A9E-$/EF*2_PG'8([E-c\WDFg7Q/pVS_F`W2apAP$fs8N&am.^/Ls8VWg2Z3RL=GWN2 +RZX,'85_U<P)l5sM)fKe8!fI&M*c0#88a`UP`hB'EB@r2B9\UFQ^<&>p\t3err:dQrr3Gnjm2^9 +o$7:8qY^<js3goHrrh6>l/_U;rrE%K~> +s8NN,r;4X2ZMOV$rVZ]qrr2fpp&=mhq#:<n!ri/trr<#ss8!?+]q2%!Y2B3WrVZWos8Murs5O#: +s8N&uq>^D6F-ViPP*ToVB/5@7PEV/lP!!Mr4&)9+R$'FEDCh'CQ^Ehp4%rSAQ'RW!QXu*JrVuiq +!<;urrr4/@r;QWP`l,jGs8N&sqYg<fs8V,g\u&r3P@V#4_T0U6_u@Fa_SjI;aM>O.5&c1F^VRk* +_o':h_>qLQ`"^,*_8F40a-VU;WPOh8]u%e,`5]dp_]?M5]ue7/RUW:e=gbiWa1f4\s8;oks8)c\ +o)JI^rVm!!rVc`os$?Y_rVlisrVlUnL7+-jOe%\-;a$G.NLl2e3,W=tQBRDd6#U[3DO-ELP*_\Y +4)7T(P`qB!PB_*Brr;`mrr2rthYn)bqtA(9WirJ(POJMNs8DlqjSf/ZnGWgnm])nRUriT8rVcbH~> +rr3`.m%dcm\]W4@b/q]CaN2B@`Poj:aSO'ZbQ>r.`r<pZ`lQ<HrlPJe`Q$-Hc-43,`=g;;ai;8I +='8X4Q+bDebf7Q<aSs?Aa@4+e`luNKe6?OCNh;o2BLQAaMk-)sPEM+mCi):0Sr];$2JHtWPF@c& +NK#qj;4*Q3PEqD7EQcVG_oBjCbfIfFb0%fHrl-##b0nn][(*TQgs!jX_SsL6d,WX$h7IO$R<[*= +mdpGHs7'XknaGr@o^D)1=b)U4d+RLEnb;eOo^hP=lg=03p%eCSn[tcn^t,UGjRi<?mHEd"mHsB4 +qW[S=k-K!(RqgXHqX)hRmG,_$^sgQV]Y_n,_Tg3A`QHHMbf7Q<`lu]Pb/M993m,i5H'XY`OdM+o +:-4f)Ngu)`2JcnlP`^u\5Ab7+DO-ELP*_\Y4)7T(P`qB!P]'LEb0.]K`l5p:rlX3@&B;\sF&l+9 +92eQma3MlK`ldhmqo\cV!64NL$c/iL:/YAalM^\]s*t~> +!W;rrrsIZ?p&G'iqYpNor8R_Ts8Vm!rr<#tqtg9irt*H<o'tuEs82`os8N#ts8MrTrWiK#rr<#m +PA^Ad/=)HL5''b4MjfisS!K!gH$*4hOI)/^5]0q3N0TKqP\*HHNfK9pNL6&)p\jU\s8@':i5NXQ +chdG:s8;`ls81rlNJK9VTg+-_F`_\GG^=ddI!KjTCNFK87j&K\6?7<uGB%SGF`hkMF)uACG'S:O +DD)G*'LHh^G'@bHG'8"NG'8"OJ9lQ]Df]_=I$R]HH?"%PN6q7tqZ$Hjrnm/8s8W)rnbtHFs6iFF +R$*i*N.X,LJWlLeQ^:'MBg.ZGP_go+DdZ)!QBn#'Ng*"GGXmm^R$3`#CQA8kqu6Tph#@<Q$i8rO +p\FC2s8Vils3UcFrrh9?mH3X2rrE%K~> +s8N?'r;*pu_YF*/rr<!"rVulps7QBhs7cNms8W#trr2p4rVl`mpnX^_WjM?srVlcos8W)srr;!W +s8W,ss8E)nO)4f^/!c?J4)e2+M3sEkR?WR_GB6e`Ng5cX5Aa_/Mj09mP@[6DNK'*nMjKZ"p\k-c +rr2p+rVuiS`l,gFrUp-fq>L=(r8bo27A6\XVnKgba2Z!4rkB5b_o9@1`6#!;Kn?)>`lQ-7]u7e* +_SlGm'Z@l*^:qaYM2@.la26!C^raO5`lA"r?Gj^o`PKR8]3C>fBpHBJ`l#des8Vurq>0sEo_\[g +rVQWprr)fprr<#trr)fps8W&tmmNM,OHu>pKK;)DOdD8tQ9o(p4cktnLam.W?Ug6FQCF%tPX];1 +8!0+)rf[\&NVibQrr;uss8UsT&,lA%fsRrbXfIiErVlisrR(TPr:dFfU7esns8N#tJ,~> +rr32tk)EYf\]4Wm"Ne[$`lS(t!6G)\rlG,^!Q`:[`=Ku0b08)PaN2B?`lu]Pbf9Y$'$8>;`kQ+l +>?kd>^WXsG`l#^8rlX6A5/tX\aj&#OG$g5oTqIWs2JZ5uMOBWoR[&dcG]["dO-YlV4_n;'M3<je +O^gg<Mi3[fNg5MZe'>tN`Q63ErlG&\!6G/ZHcaXc`jECg[aN%4`kp!Ia3N5`e'qF"ZsUZ+kO\B; +n*ff:oCMMBnFlAAcEaRQcLUAhlg+*=p@RtFmHa0.oCqtPrPl%DZde@(me-&DlfdEjlKdd'p$VD; +oC:USQ(W6%lLaGud-TT5_Tg0EbHAe)b/q]C`Q$'Fbo4gI`Q$!Cc-=DN`Q-KO/W5gVR@8q\1c'WE +R/W="5[e7dNg,Z\-tmF&7$Eq&S!&er7V?s9Od;AuPE]Emcd'MPbJqN?`lcH]a:?2&MHa"U:JjoZ +`lcEFa7.1Ib36nP_6mlM;-8D3qu6VG~> +&,cG+s8UX&r;Zfrr;?QnrSmhVrs&Juq>^Kor;QR%r;Q`rcL(,fmJm4_rVlfurr<#Ur\slUr;Z`i +]NLM`R$*_u5&tL$N0]QiQ][G4<-!"L=co#7G"$=2KpS-lQ]a=78<oO*T9>O9dJ*/0s8<0!i5NXP +ht-jICB"2-rV,]oMd^FqD,6%AF_u,?H@LEmH?jaXG%tkc$jm7R5&>(RFEr+VF`V\JF)uABEHQ5; +1(j]p$or!?F)Q8HH?j[VG'.kLH\-H^C/Z!!0WpftJTGj_OjNUqs7ZBjs6/_?s8MrrnbtQKo>Odp +Q(!r"Rm9SIPa[`&NG)((4+`rdLcBKs<BHM)SsPA+PtG.o5uEo2Q'Rc(<4_u,r;Z]ps4mVPrs7]Q +oD.t8k5Y5Us3^iGrrhQJnEAd.rrE%K~> +s8E9%qsgY]d.[D9rWE3"s8VflpAb$h!rr9!rr<#srVmK/s8W#\R&Hm^^&.g-s8Doqs5*bTs#9rS +s82N"=-\u:P*M1kDJV:iP`ColO-!@>E,\6IO-PoO6uG&=QBmf%OZ-Q9PaIZ*OH`Gcq#:9mpAY*l +3r]0Xi5W[PhspaFrVlisrr<#\]SCR#H>U@9`l#d4_8!_!^qmn*a2#p,Ll[X\W6)fd_oTd8_Sj@1 +rP^\2_S=*ZN09TnZ,ac%^r=.,_o9U4_o0I-_Rm_.^Q!h<XI2Sq`koa8oD\ahpAFshkO8?KrV?Hm +s8E-!rr2rsrW<&trr2pXoYa^jOdM;oRmB\LPaIMuN+Yk$3e<``LGs9o<'$;&SsPA+PtG.o5uEo2 +Q'Rc$;Ruc+r;Z]orr;rr!<;$W%f?1h\$2m9X.Hluqu6Wqkl1V^m/@CkqnSquS#H)]rr2qJ~> +&cM_/p"4RuLUY7Fbfn5L`5]gpaSs?]a9'B#`W!mV`W*pXb5TU0b/hTA`Q$'Ebf[rE`Q$$B`l5/e +@pN>Z[(j]-b/VE>`lQ<FilH#Wa2Q$DaNC&EMij[&Q]O.AC,q3;O->lkO]GD#ECO&lPEBoQCcI$2 +P`q>m2-WM4PEDN#O$0eoaMYp7aN2NFaNDZLbf\#H`Pp*P`jWUl_oU6FaNDuV_T1N\^m'8KMhTsQ +nac;@n*ff:oCFU)oDJ4TgT7p%alNKjjm)C0q=aFMn*TN2nacJMrm/3f_T:j3mI'<3mcrrskjAB> +Dsm2]o(qa\TNnt"<T<H0j4*GOc-=,JdET/8aiq`DcGmlHbg"AQ`lQ6Fc-4>M`m;f(6&CbqQ]mh" +78oA;OI1o:956G9R$!([EGn`7PDc$!Mk-,*=DL3"Q'7K!Q]jn-cHO;QaMu3=aNDZH`o4uL`P8'T +<D64d:j0XoaN;WJo#LgRrQP;as2b5[s2b/]o#M*S\TgtH;fLUfrr7K~> +s8N6$s8U[%rVm$!qtpEniVjYnrqZBis8Mroqtp6gs8:U@mHF<Es82corrW3"s53f7rVufqqu>YF +PEM#mR$MeYCMQ1oR[oS.R[./1F_WsfPadb&A8!raR$=&&GWS$OP+.Z'Q"ZBXnG`Id2Z)FO`5U(& +rr;ooqtg9gkJE66V5c51JTYsJEd2t]I=-<bG]e.G7go_)!WtH"Fa8.MEd2_JrH/?dEcc&52\?/k +!%pQRF`r"]EdW1VF`qqNG'n[_C0;#N)_u*4CIWMkJ;DSDpAb*drV>p@rVuirs7-(Kr;Le_Pa@l+ +P(YhRMisWnO+p);;Il8YP$V.1EE7g[SWT"uQZb`:D)RN@R?<_uQpp-5qu?Qls8UmRrVm)algOT? +l-oY3rr(:Es8N5nkORutrVllsJ,~> +s8NK*r8aZOi;*BPs8Drqs7lTds82fprrE&ts8W&orsnqNR&Hscc2@S<s8Doqs4mT4s82ilrn^)- +PED,sQ>\m#Bg.EARu`l&PZ]PYBK1I)RZBgGB/bm<PF7PW3]iLgRus&"AWcigrVu`n&H2V-s8W)u +rntf6_Ti,Sq>1*irr4A+[8!Hq7_HFM`PKI/^q[Y"_8=(,`lYNDRZ<PbUW:BpaMY[,_o0Ij`&YlS +bb0lPP)bC/bJ_<9b.,:)`5KO0_o':*`PffVO,7:bX`]'1^r*nXs7u]pq>U0WkPtS[rVlisp&6WE +rr)h:G*/&XQ'-e]2iNohO,eo^BMi9.O-*^IF)Y-5Q(=&!Pa?P\Ec!^sPaR[5PR0_=r;6NkrVlfr +rVcfsiVjAfqt7b/WNNA"U%nWdr;Zf]rr<#arX/MNU7IaJlMpn`s*t~> +&cMb0oYPNXR_-S^c-+5La2Z-uaSa0caMu6=_o'I5rP]#]aND`Nb0%a'`?*%Abfn5L`Q#p?ai;,] +>\%,KK=8M7cH=5I`Q$!Ab2LEk`Q?*E`mV[ZLQ7[kS<RhMBPKbiR@KA*R?^r-FD3abOdM+o@:_<U +Q'%DoFZ;CCNgZ-#OBd+]bf.E7`lQ<FaN2NJc-48J_o0aI`43Xs[+WOAaj&/T^rb9TYYhL0?/+B( +o^_SCmHsB4oCMMErVYNV^UV:uiW&fJnE]K6s78MGn*TT4oD/+[f=nl1]u'@;n*TN=l0IX"mITuB +na5f=p@u52Y'ko/IZ`RKi6(EHbgb%bd`fS?e^)7XbJqQErlbJeaN2O'bX0IlaO/^EB8i.JRZrC] +0o(j\OGnfYAkuj&NK7:AEGe^-PF[htPa?P\Ec!^sPaRYuP`n#Cc,IrJai;<>aNDZH`o4uMb.t3! +<_?.b;HUWRa2Z<Gb4E[Sb5TWbb5TK^`rF-[aoT`/o#M3X\Va?\:hn2GrVunJ~> +s8N6$s8Ug)r;Qlsqu6WSrY#81q>:3lrqu`kqtL*ikNVO&kPkJ^r;Q]qrr2rtiVkk7s8Duqs7K$L +R?<o$Od\=RDcU,.NL#lnPFFgAG%Nh&P*21fGs6S>Q'Rf'8MkjZPa%N#N)T<Fr:BnLs8Doni5NXR +ebfCHr;?Bjs7>d#=*L0J@=<`QE.;nVH?sj]G'.tLCJ5<I!!!*76$7?hDg?bTF`V\KrcgDDD.P.* +!<<3&%7b,aI!9phI!TpVG^+LZIWB.(%LiFL1`i<e-\R)#PKi^ooD5Vtq;(H4qZ$TonGY<3;3IB7 +O->i25u!Q5PaInD:g-SZR?W1^EGIFtR?a/#Ss5:,?>rAINh);qS!8t0q>C*hqu6WMrr2p%nEBH6 +o^^H0rr`5tqY\hA$ig2(jn&$(oDejirdX~> +%K?D,r77aJo)/Les8N#rs7lTds82fprrE&ts8W#nrt>.2SYiBmi;<QPrr)fps8N#rrS[Z6s8N&p +s7/dHRZa)%Od7nID,a]&Mj0HfOdSC9FC[CtOcbtbGWgA:Pa.T#82GXXQ'.DsMc00Gr;Zcq.0';G +rVlfrs8N&ti5W[Nd.[>9qu6Kms8DuRDMO^!L:P:@^sBa7_86,frkfDdZ&4g.R#m9!`PT=*b/_97 +`5KRm_E,TTbFaiTP*_2fZFe/m]"c5!^r+(+_8*n)^W4<PQB$cQ6_^JN^;Re,nc/R_s00!+h=:F= +rVufqs7Q@Rs8N#`:lq!.NKTQ/6;Ec8P*VM>:K^AVR$2tZE,%4pR$<u!Ss5:,?>rAINh);qS!8h* +q>U6jqu?Zps8Doss5Eqds82]>Z)t+0X.&JTs8;lrmJct^mJ[=fjeA04UY5VGJ,~> +'`7k/nZ6PEZ+n5ubKS)J`Poj<aNFM+s2kMd`l?!8_u%D%`lQ<Hbf\)J`P][7b08)P`l6!;bf7W6 +G%"ieBUQBI`luTH`l?*@b0&\aJ&TOKaiDlZ22IN`TpLn*1NIA5>Ek)3Q'%5u5?`2@3g>\dPqR;B +G`e/QQ'4ZlHB4/QR[8dpe'H%M^W"4:b/hTFbg"AQ`PTL6dDWQ2^:`%IfZhabbeh3Sb@H@$I\GTe +o^i+OoBY`2nalABo_7IX^:(bf]@6WKlgFH>n,MqVmh,*^q>ARS^;J"/_s$CTkN240rpqB,q"XRQ +mHaWD]YqIhVHp@*:sA(Xdc]Z?ce")<e%*cRbKS?4`W4*Sb!O1hb1P$&KThddQ^:`98<94'Q^:fK +=%\[BOaK**BJPd;P*h<%P`J@AE(4N$SWT))P))<Pc,@cFbK.]CaNDZH`o4uMb/(W?=&)Ie;baL: +aMuEFb4E[Sb5TTcb/jG!s2b5_o#M3X]U`"p:hI0)rVunJ~> +s8N6!s7tO%r;Qluqtp?NrY#81qtpEnrqu`kr:^-ig[t%$kl1SarVlisrVlisiVkk8qYgHmrqToW +OdM5nR['.;EcFNfQ'[c$R?<e=:ip#6P+@eX7;+cGS<]A*FZi?]Pa.T%P>B<ur:Bn4s8Doni5NXR +MJDk\q#CBmqY]or8"lJ2LOsVpG&qkPH$FLTrc/*Y;AorA!#$2?EclYKE-?PMF*2YOH$F=;/ID@U +0EqnWF*W4^IX-6aF)uSOH?sgO?4@)>!"U)%>Fp11KnP?9nb;lt@RrINj7WHNs8DKe3Vf"UPa7c$ +R#s9dL6\!fQ'*t@16RocPr`]"3K9)eQ'@PtOA9&">!S19PEDDuQ%`]Bs8Diprr<#Prr<!'qW@J= +o(CQ0rr3'!q#&S>s8NAdo_%D4s8W)tJ,~> +s8N&q#0EdJr;6Ejrr<#ts8Voop&Fmfrr2utrr<#rr;RK1s7MeQVQ@>urVuiqrVc`qrr2lpiVkh: +rVlioqt=<MOI2/mRZrq5E,S*^PEh>qQ]IA5:3'T/OdqST6t\QCS!9/&F?E-[Q'7JuO\Nsrr;Zfr +s8W#rs8O/>s8Lus_nh":nb2bXs8N&uqo2L5Th;u<]YqY$_86)frko>e[Z$3+QC*MkVS^0g`kfIh +`&trS_8=.0TotS+PDYEW[)BYp_83k#_8F1,^qde(`6=1%O,]3RDeu,.CqRNqq>U9jEFh[!8`ogH +qYg<js7cNms#9rPQ=l>FR$!_t2E?PYP`h5m1Mee.P`_1jC2Z(jNgGupQ'7;)>]<k3OI)/nSWT1h +@JKm%r;Zcq!<<#s!<;!V%/Tt[ZEpO3XI.c8r;Q]qmf*%^mf*7d#4nUYS"e%'rr7K~> +'Dq_)m$VL-^V7S)bg+GO_SsO9b5KNdb/hTBpr*<SaN4A))p67A`P][7b08)P`l6!=c,7H-?".8Q +F03-ra8X3baMu<Bb0&\a6H6s_a2lQT7X9r]QBmu$N_se86u\BVPa%PsQ!$n(>ssaBODmNt300Jj +P*9oI8!&guR[TC*YLU_3^Ve(8bf7ZFrldCD`PTL6dDE?.^iW2ue^E!m`P'IQ\43<r?eb#8p\=@L +m-<p(nauJFp?KN/]"c"b]\2uLp@@Y?oDJ%tnalJJd([33`4s:*kjd`ulh0rEp@S(Rp@Ib?mf3:$ +)83bfOaO$cESB6dmc)mT<(\b`/^)huc-49.`r='Xb5TK^`^%c$JQR_lS!KS.1c0cGP*;,k0krA& +P)kbbBPfYbN0TQjQ'7;)>]<k3OI)/nSWT+a:X[V/_p-?F`l?*Bb/hT]a:HG2^m//'8ki,PS%cqa +c,oLsrlP5^q8VjD$c^,f=%lCuT]c4Ps*t~> +rVlrdgZeY9"8r&or;$?lr=&W&s8Dipr;Z`qrVlijrXeu)s8W)rqu-6cs8UdJoB#TCs8W&ts8W'# +r;Q`riVmoqrr)`os7_=fQB@N!PF7SE3cT1'J=;alP*_Gu>#fQ1FH`#U?;`e:Q'7`'O#f"\NgZ8u +P^mB>s8Vupqu?Qgs8;oos8W)us7cQL_SIa,G)&?Up&G!crqU&aThBHWG^+LZG^+CTG]dkBE+VcX +$3^J0!"oW$CN=W@F`qnLFE_qVG\_.J'E%oX!=0&tD0C,HF`hkKEHHGMIX#s4'`\=9"9o8[,E/<` +H\n!4p\'VKE-#u".Q[8#qYpNprV?KlqZ$QprVlcps7uO^PaR`!R?EUe2342mR$;>V<a(TLR9WR) +95TcZPEqSrO\8kuDc2g_Q'[c#Q',jBq>1-hs8Dutg\q3Nrr32[oC2GIi8O\8s7lZmo)91"rVuls +s8Drsr;QQmrVuogrr;m&s60+Lki;^Crr7K~> +%0$2)qm`BDq#13jrr2iqrr2rr!<2ur$i^2*qu?Torr;uts82fors/Q'rr)fqs8Mus#k*qMWN48; +rVuips8E-#rr)fRr\slVr;Q]gLM`<=QB[T#O^g@hE'&N9PF.GsPEK$HDaST/Q'>QO3.mHYS!8pn +0U@`eQ]RA[B_VK*#Q4W!q>^Bmqu$J<qZ#Bh^aE3&Kg55's8Dorp0`oY?CSaJ_SEt'_SjC6`4s=8 +`O1Y_NKTQlP)cHZ_Sa7._SO.-`50C/]?-V0P*M>tNfB"&`l,a3_8=+-`Q#j2_njU2Q&:cfOc>6O +:n"OiV7XS3s7VOXEcc+s-opkoq>UEo7K3/`rqcZos8N&ts8Vlj7?X%$OdM8l1H(>_QBm\J7o`]Q +PF,QMCJ&E(R?Ei&Nfct<Ec4j?P*MB!Pa.DDNr&_SrVuimrW)uWrXf#-r:mJ&X/rFr](c""rr<#h +rW3&trVm3's8W&tqu?Zqs760hrs&=uR[p%`rr2qJ~> +-iNr@kCd3%]tqV+aN_rK_o9X:b08,TbfRoD`6H9?bf7fEai29BaSsC/b/hTA_o9^>bf\#H`Pp!@ +aM4iV@:E]$[_Kr)ai_cIaMu<Db2LEba2l6;bL+XO@$$M?R?a(t@6&:H4F`c`R?<f"P?Ck(6#i!M +P$:^?JWc+_P)M=POc5d"Q^)kqe^;OT^r"@<^rj[@a3;ZE_SsLH_6^d$9ON#of$;XY^!G_CL8Aap +j6cI3q"F1BlL"'.p\OLB_8<t%_8*ir^YAVXo^MDCoBtu7me$,=qTH[c]u.e,`l$p/lg!m/q"OFP +p%@_>lM'P_]u@e%]Xk1WUSV&+f#H\4g3Q8"Ame%F,h(,^b/q]C_9Bm:aiMWD`l5s>b2,%2PE;$" +QB<mV1lI]bQ]l&N;ces@Q<?pr88=-NOHZ&lO\8kuDc2g_Q'[c#Q&o@!d`BJHbK7iFaN2NHaN!/Z% +a)\r>?+?k:.]ZD_TU$Cn]26_a2u?AaMl0>`5][;`Q60la:$#/[U;j-?&[b;s8RT~> +rVlrXh<b(>"9/2qr;$?krs\hurr)fps7ZKhr;HNerWN/us8W)tr!<#ps8(RIn)F$>rrE&ts8W)u +r;ZfUrr;orrr<!orN0:iQ'7Q!Q'RbA;JU&>EgW/ZPb+2'3GWUeR$<l&0jmb:R?!]!4#2JXOHZ#u +N_JC(p%n^br;Zfos8Vuoq>UEgs7kG!LOk51LO;nqrr3o6_IK['4c"E,G^4RZG'.kDFa.M49G7X3 +!Wi9#"9pbsEI%P+$?U<6FEhtOD)`.0r;\SR"pd8'EcQ5AF)ZA@F)cGSE`3eX"9AK&#6bi"0q4%c +O.4nkDG>(fEGp,>8QkogrqZQn7K*/aq#:9mrVlfns0H*rQBdc&Q'!LpQ'IK#Ou[)5NguAo3-8;% +NL-#qRZ`t.@r?*ENKo]mQB[Z#PZkHkr;Q]qrVuoPrW)iprs%]Sn+HD;g&D$Oq>gHarWrQ'rVuio +s7uTlrr`2ns8DNf$iB\unauJ7i;`iVs*t~> +%/p2'po1(;q>UBlrVl`ps8N#r!<2ut%/oo!rVc`qpAb$grVQNlrVm$"s8Muqqu7?-fp&5/XOd7G +s8DurrVlfrs8MuUrque2r;3QuQ'IQ!Pa%Gu>#8pI7rXcYQ'.Z%O#Lcl/XMZcQ7uZ?NL5]mOub=N +RZN\sQAnVsq"Xjgqu$Kor;Zfor;-Hnq#C3I.>E8&I#*5Gq>UBnr4#h+P@2,A`507)_8F41^rFO4 +bIEN1N_P\$P`q3.`l#^2_ns7*`kK=)`Q+[5OHGipPE(W^[)^/(`59F+ai)98_TBd.P)PWhNf'*a +Lj)drQ<^i6p[r>tEGof2FD=<Fp\b!crr51]rVuZls8W)us82i%?BUS;Pa7Ss.9)UtOI2+hA2fL; +P`.PB=Ak*DQ][]!Q:YS(CcdWAPEhGuQ'R\:Zi'e%!<)cn!<;!V%0-8"^9t)FXJW#kq#:9mo)A[h +#6+Z%r;ZTjrr3&uq#Bm`s8NE'[@WeSZhXP"rdX~> +'E7t*iG`(f^r+.1aNVlJ_o9X:b5TX(bfRrG_nF.7bKA5Ja25d8`QHEKb/hTA`Q$!uaqDe8`Q60B +a1[d8?!h-+]>DY.ao9EcaMu6@b2:9Y`Q$-Je;d._PEhW'P*;29;/0i:EL2rVPF[u#3,3=]Q'%5o +/mV,.QA_&j3%olNP*_Z-M*Jr'_844/aNMiFa32HA_8XI0daQ,RJp_rgJo`p&bJhWPY$%QcFPuBO +o_A4Rn*B9$oD8%Uk.AUPrkVUM_SP.-p%%P@p@[kElgaQ@qpE$c\\5o!`5T^YoBki3oChYJn+#f6 +nEo>R]Z.n)\&6.lQX?GLEm2JdhGlgTC2@L$ANN**d*9VTaN;B<bJM??`^Iba`lH]%;MpU$Q^a>( +-W6(iNgZ"f@Ps(3P);,:<`"[<Q&h8pQ:YS(CcdWAPEhGuQ'RM,T$k^!`QQBE`lQ6Fb/hT]a:HD8 +`OK_d9hS&OAA#h$a3!hl%`ZK/`Q$'<`lcQM`4sF5n]2'V]5L\G<IE?gs8RT~> +rVm8[h>@6Orr<#tr;6EfrXAZ%s8W&ts7lWcs8W#rs7cNjrt#,,qtL*ijl?(%ir8uVrr2lr"TJ;r +s8V'W!WDins'Yd)g..EqOI2;rRZWk#C3=,RPEVB#N0Tlh3cJ).O-l/]3AH;ZQCO.I085pVR$Wr' +C5;Q`q#(0es7ZHjp](9mr;-Hhni:l@LkL\5Lk>C#s7c4lVl)\'H?aUYH$FK2EXHr5D/DiT"onW( +"TAB5">s_0H?XOREcuPREcPkO'*S14('+OsAoVg3FEVePD/Xc>BOVta"98E)rW!lI.PuL@<d0nc +nN'3]G&q_JG]R7ds7ZKmrr;Zjs8W$^s8DrqqXeBMPa%K#Pa7=e6]dJ%PA!6>PF@Js;d!`nOIM]' +P*_M$A8Q<FI\E'lQ'RZ"QBXnsr;QWorr2rth#7f]qu-KnpZCr<p?g6,s8Drpo)A[h$2X]"rVuoq +s7Z?hrrDlcrX8Vss829SjkBb7rr7K~> +s8EE'n"?T=r;ZfqrVlfps8W)urVuj*qu6WqrVuolrq$0irVliprr)isrr2lrrr2p,rr)])RA?ab +kPtJ[rVulq!ri6"hu3ZVr;Q_>qZ#5;PaIQ!P`V;oP<NZ$A3Q-<QBd>kR>3b?<+1fRPC>JFL7=Ht +P$fnrS;ru&OdKm<q>^Bks7cQfs8Mfns8Mrms8)=HG'esoMLUM4nbiF_o1bUK;67RN_na((_o9X6 +a2Pd9[#'m,OcGNdP*;!-aMYnd_8=+,`50O/_S`"(MiX-gP*(fcO1!'K`Po^2^W=:4cG@02Q&1W` +MjBZlNJiR1PGDcM[Ij/O89/lnD/aQ7>tG"irr;utpAY*lr]C/Zs8DccAUou.QC!i%N\s1cOdqPG +5W"XlN0R:CAiPj?R?Nc!QU,/!EAr??QB[Z#Pa.Q"7Gn(DrVuZl!<;'Xrr3B'pX?IPY-+jpn+ln\ +s7?6hrsAT&r;HZqr;ZKfrr2upo)A[h$2qf7R[C&Arr;tJ~> +-ia)7dUZX[`5]g9`luZH`Poj<b0A2Tb/2*:bfA&\bL")QbJ_KEao0?caMu3<`lS/%!m&C#rl>_j +]QR1W?YQ=P_oB[:b08)PaN!,YFN_YC`luTV\i,V8OI_f%Q]RFrBlmoNP*2/tMj0Zd3GhZ$N0TNQ +2D0ZNPF7M=/;'IQR[]M,?ua]F_84=2beD'7^WFaA`l?KUdj&UOLOY,1LND(kb/_q$T;l/:jQl:, +p@e.Ilg!s4p&F6c^;e73_8-r'_SP.+oC22>q"O@Hq=+.Re%N9'^;%Pa`-95bp$M&3o(25<kO&-8 +kjZX*^V7D%_S<q!WI^80GbDJ,iZpd.G]n(KGAL#+hp'NoaN2$7a3)B?`l,j:aj*h0O-,`rQC*[g +6&q"pP%Qs6OI(ig:f_*bNL6&pO-GtsA8Q<FI\E'lQ'RZ"QB4,GdE'/Eb0'\("3ep/`o4uLb0.l< +Kih)B8lAQn_T'U9o#MB^bJqE>`lZ]Tb0@fBaN;N>n]2'U^4BB^;JX2<s8RT~> +rVm&Xh>dNPr;Q]ur;6BhqYpNp%Jou$pAFsjr;ZcorVccjrr<#urr2p,qtg?mf';kokl:\]rr2lr +!ri)orr;$XE;]_0s8N&ps7JgAR?Eo%P+%o+P>#.sBL%iGR\#q.PZ_"%0U%`bQ!I$XN09Nj:-Fi* +QC=#!Q^C#0p\=dfr;Z`qrr;oirr<#qj?@^9LP(A4IXPumh"UTAHDkseI!9aYH$FIQEH-&@EH+V]% +KZP/(Bad>!!Y>oEdDtTF`VYKFEqLQ$jQk:"T/66#!-C;EclSOG^FFJDeNW#":5&/#lXfF"ooKU/ +"r4iVV&dSFDQ#:HuX%AF_<Z-q#C0gs8)`nrVumXr;XN.QBd`$Q'7GtK1D2sP*/""C6k6PIlqO2K +pe6kP+[k.>ASCGGaXDSPa7W"Q'IItp%nXbs8;lrh#7l_qY^?ms5<A>o^C6.s8MupnbrRdrVlg(q +tg0fs8W#sr:g6^rX8Z"s8V<NlJ)@=rr7K~> +#6+T!ihWLErr3*!r;HWns8W)urVulsrsel'rq6-frql`pr;Q]qqu6Tp(B4:2rr;uss8N&spS4CY +X1@p'rr2lqrquots8V$Vs8P=]s8W)nrpiC9R$*c"OI;Q$O\/_kAj2E?R%0M&P#kUt09VN^P[$gT +Mij<f9g"Z(QC=#!Q'X]-q"t*kqu?Zpruq@8rr<#oj$%O6L4P&/Jpq2cgA:Z@C7KWp]>__*^qmn+ +rl,,[^r<F,P5^[EOB7R-OK-@=_nj4,_ns=,b.s6mMN=!eOcPQdOcQlj`Pf^2_8""/`lH$7MM7:R +O-GWfQC*>]\4s&r8\aW15&kCZCisK+CiEoDq"Xmbrr;lqrr)iqs8P1Ys1V6nP`qDuPE_>b8!TR+ +O??$IQ'[_a4)7!4R$EktT8lNJCihmdR>I5oQBmc#Q'+B)r;Z`qr;Z`mrW)uXrr2p*r:oEZYHG(3 +QJ;66rr;Th!rr2trr3?%q>'sgs8;oqq#Bpas8NE(d@d##U>c(MrI=~> +.0'/4_.6iZ`lQ6?`QHEE`Poj<b0A2Tb0%`?_p$0Mg==Hsb/VE>aN4A's2b2Z*6?:FaMu6=aiDNB +]4"cC@<8ir`Q6!<b08)PaN!,YFNh\D`QQ?Ld5-WDP+7u)Q^a5&93H(D5Eq:uSX>G$=AifaOHGWf +>"D;CO-G\u3g>hoR['&%Ot>2.`5op:ai2NDai(p9dF-I]-=h=PJqel2J7'P,bL28_W/6Dem-F-4 +p@e+HmI'N>s6@25`5g!<_nc8c-/&%`nF#i?p@@kJs8('N^;.S'^qRY(`5Up2mHX*.n`fH+me?Hj +pqOPd]YDM%_SjX)XjU:VX]2slZnQ<6G]S7PEcGhm)qNHea2Q9=`l6!;`5]j?et56jP*D9!Q'@J` +7?a.#OZc-GPEh;Y3GCR,QBRGlSW$0FCihmdR>I5oQBmc#Q&RQPc,[Z>aNVg+a90Z/aN!2[&BW,= +^7AD%8kMuUS\rLf`Q%Mj&B;T*aj&#ObKJ8`dE9VM^Wc5h$HKoB=Ai.+Z0V>fJ,~> +$3'u)r86E3rqZHjrr`2rqu$<i&,Q5(r;Q]Bq>1-`q#CBkrV?Err;Q`rr;?Qo%/Tr&s4$K)lgOlQ +qu-No"TJH#qtpBmj8NHarV?Kls8Dro;2CR)Pa.N$P`V8q20EYJ4IMA!P+mr(4Dn2*O-uGr1cL;Z +QBcQWR?<o$P*qGtF*[N[p](9lrV?6gp](9gqt<L2MMm.AI#3H*Mf+(;nO'UW22-L$rceHeF8g1a +FDc#!$46q8!<3-;!<NB64_o1eG^+CQG&VJ92?s9a!<WN-r;[N>6#CdhG^4[iFa%\0B+k:G$31&1 +r;^+0&mS7NT5%ok96>/pEc5`>F`_tLC,l(grVuoqrr)iqqZ$Tms*ARNPa7T!P`hB!P*2&pE^;mN +QB@V3>[U*gQ'dW%N_EVsBg%Q>S!B;)QBmc#PDr3.qu$Hnqu6WNrW<#or;Q^#hsU40mb[I4rrE#f +rX\u,s7lQmqu?BKo_eahq#0d_#Q4K!s5`G3i;N\+~> +#64Preu#VErr3&ur;HQns8E#srr*K+rVufor6=s1s7?$cs8;lrqYh--rqu]os8DrsrVuiaRAZsa +`Vf`8#QF]#rr)irs5<nVs'>X(rr2fmpeHX2QBRPsQBI8oO>CrkB0)B@Q&qYsQTK%a>`P2>N&*AK +Q^*eVPF%>uPEM>rQ?.EKs7lWor;HHes7lWop\=;IJ;9#7K6iB/J:M3]qXd%MThDc2rkncQ!Q2kT +`GiW1Zu^hYNK]QfO,oEdO/U(8_SO+-_o0@0`1;1(M2m[YN/Nd_P)Z`d`59F,^r3h+`k9KDG^bg9 +OHPN`PE2#i[sED!F*?h=C2Is1D.Rg0EHQ)548JdOs8W&srVlfns8VrqG\`\2QBd]#PaRp<OsQ<2 +5<Y'mOI8jJ?UpBGQ]@Mo93Q@M4ckbpQ'R]$QB[YuN_&pCrr3&ss8Dlps8V*Xrr3K-qX_+tY-4t" +^A.a.rr;Th&-)Y/s7lNlq>KsCoDARfq=4IarsAY\Un+3QfDY^IJ,~> +.0'&+Z"%7Q`QH?B`QH?E`l5s=b0A/QaMGd<`m*&8e^E0j`luWD`Q%\os2l5#`l?!?`lZ3+='8O1 +ID3eFai23@bg"AO`o"j_bJqK=bKA&Z4b/ZZR@9G.PE2&m1j!GF4.).rOeI`$3GVPsN0]ff0f4ZN +PEKpMRZa#"OI;5nB4K?<^WF[=ahtp<^Wb$Ie^Z<oIYE?+I>`l4KO/3?eLd`'@*n-&lg=<9o^hP? +o()hR[DBetaMu39^V.4fddmD*Ie!(&p%/(ZfXJK1`5TX-]Y_V)_;k+PlL"*2nDj'0p&Dn?^Ws^4 +`P'+)^;I>/P)Q\kG2kYlC34W<B6\iNF^nPsgXXTma2?!=b/hE@bKS[I@[<7EQ'@PrQBdPnPE^&P +4,oGaQV:Of7?`n"N0oMp>&n=?OH>rsQBdc%%$[$@LcO,5`P]X7bf]q+"3ep-`o4uMa32cGX'\Rl +9N+i=_T]s8`q.7_`l,j;`6?f\f$:eGc-FSL`ULqT^Rne0<a)3YqYu'~> +$2ji'p>#$7s7lEhrr`2rqu$<i$30\urr;UD,YN4XrrW)qs7uWor;Q]sr;6Kn%/^&(s4Zl,kPG5R +q#:9m"TJH#qtpBmj8K2Zqu$Hlrr4nP?%\E1P*VH#Pb=D/Rm^J)@RcQFR#.>rH9QI-P*M/t=@-)P +Q^!o"QBmc"QC!huP=5*@s7uTms8=#=o`+YhL5C_4J;8l0Jqo/84k>.0VeKI`Is$!ZG'3b)"F+`e% +1E(6'*SI<!!<TjCNXuKG^":PEG@99"o\K(!sSi/rW!]D7<!KqG^4[fHus.:&-)b3!!WE'"p4c(> +Rt5!/tSq%F'Eg1G\hVRE,fl<FDaH,p\=dgqYU<ls8)cqqr1S;Pa%N"Pa@SoQ'7Z%P?KVoQ^s4\6 +WlsEQ'@]&OF'H4G;**eP`h>tQ'R`#Q'7))o)AOdrqcWoh#7BQqYU9l$K^[Jn*TGss8W)snbs'tr +;ZcrpTn`g0V8.;rr<#hrWrH!s8V6CkiDR=s*t~> +#64\qbbMiErr3&ur;HQnr;Q`r%JKi$s7%T^89+Y/s82cos82d.s8Mons8W)ss8N&qgmP1BXO@%F +s8W$%rr)irs8MuVr\4BOs8W)urr)RpK9VddQ'ISsSsGS.6<SG=7$3UtLRO<M4`iHAP`V865us,6 +PF.C0PRNhDQ^!Vr7eZi]qZ$Qos8W'9s7?9^<J#sYH%1O&JV8c)GsL8=GbK)2\]Oig!5e`Qs28Hh +_7+H5I"%!7P*(feP*1j'`koU/_Sj@1`l49iIslp)MiE[UP*D#dYJe>p_S<k%_8XF7G]J7]I?BVJ +P`h)gNf_,l7&R(WI8jp"G&2AJC2Rp+E,\3)o_/=bqtpEms82ir2#6$+NfoWnQ'@]%OI)0"PEAs! +KpJ6iF@')"PE_8uQ&g5[CNhI6RZru$Q'IZ$Pa.Gj;Y0ke!rDrqr;Q`rir8rW%fZA#^TO]BXer&j +s8N&uoDT=$rr)lrs7NU3.4q(bq>UEoo)9$srqu/aSY)Y"r;QVE~> +.KB8'U0qrI`luZG`QH?E`l5s=b08)P`lbm4b1=iJ"Xcsnf$)+Nb/VHsaT'C#aMu3=aiDQBU/tJs +?AuV=bKRuEb08,S`l6iVs2eZd_TL-Id7J\GQ^=81Q'7i,PaXsCG%!h&P*^uoO`rm-0TVBWQ;p.K +O-GcmO-uE!OHPlpO,GaBccj2GaO8>V`Pp0@g=AT7JUr#nL5:J5KS4b,`,'4cJtUiclKdj/rq-6\ +>P\'f[_oko`Q#m:_S<gt\CL3?nEfW7oC`%\e%*9._T'R5^qmk)^:rRsmI'N9oC)#7p&De?aMP[8 +`P0@3^qRCijkX.FY"F(8@;U4)F`qSHH#mh61*P2mbtH0qa3i&Q_TU3N^cmU=Pa@YuQBI5lOdMAr +=Y>>kRZ2>Q<^i.6Od;2jGXH7j0NX^-P*VAuQBmc#PD)BQcc!f?`m2`JaND`L`l6oX&BDr=`NsAT +7nloaB#2a/^rGue&B;Z+air>]NCjH`G0e@UbfB7p$H9iaB2_]/O5p'9J,~> +$2ac&kM>q5s7c<frr`8rq>C*g&-)P,r;#"g+s8Q;o_SUfqYC*jr;Q^.qt^9lrql]pqr-i)kl:\V +q#13l"TJH#q>:0kj8K/Yqu6Qms&o,'K9_ddQ^*i%PEV/mRo<"#?p^9KR@9M5;,0euPa[bp4ue^m +PEVK%R?Nu(Od;H#9%<S2s8DuqqYpKoq>C"PG(G:&N/31:KS,,?M0D9WYFRe5H?jXVrc8<eG'J1I +>R_5A!!33+"9&9/"#OV1H?a[YF)>_M$iBu+!sJi+!&G*RDKTu?FEi"XEFfjh#64r.!!rZ+!!N?-% +:=Hl@%DL-FEr+OE,ff:G'%kEF`;Rcs7cNm5Pb<XrVuloWa2*YQ'R]#Pa.`%NguDs1ddInP`e%>3 +KonpR?a1l4_]'nH'+PXQ'7JuQBd]#P`/N4s8)cqr;Q`Orr;m+qYpNpo'c5<nF+m,s8Dufrr<!-q +>^KiWZ<<*GPqF>s8)9b#Q4W%kiCphli-p7~> +#64\p];3OBrr3*!r;HWns8;lrrt,,.r:eb]*?6X-oD8Lequ?]nrY#81qtpEnrVZZos7XC"WNNGb +r;Q`rrr;p#r;Q`rrr(jUAcMc0rr;urs7TZLQ'd]"Q'ISrOcYZm;+bb55aRe'R$O4<9hT,_R?<Fk +2j'GiP*qN#PF.`#QC="1ebT(Ar;QThrr2rnqt3!hI"-g,L4ar0KSFu)Hqd5:S56r=_nX./`5BLl +_BZb%F+AFXJq8c=OH5NfP`Mf__Sa4-`5KC/R!X.)J9Z[$NKF.&1ldNu`5BI1_83h)_ngS<JU2od +Iu]YQN0TQjMo*8dCS$&GCMIg.EH#Z0F)c,7GB.g`s7ZHl6M^W[rVuilVHT=LQ'R]#QC"/-Ngu>o +1-q(hPE@h:30K\lR$<th4D8mlH'+PXQ'7JuQBd]#P`8Q5s8N&ur;Z`orVlisir8rW%fQ>%c`jLR +Ybmo_rVccroD\ah%Jg#'oqrZL)KbiRs8VrcrX/W$oWt3^Tt(%"qg\~> +%fcC^NaI1Aa3;cH_oU!Arl,hsb08#L`Q#^7aNh0s#65([a2lHE^W"46aSj9]aT'BmaMu3=aN;T? +N*'(Z?C\h1bQ#Nbb0A8V`l6iV@`cg1`5p0JcUrPDPF%l-Q'IMqOcc)195n6(R$X2.Q^LTA8S+$N +O,?"VO-PfgR[Tb/P*1flRZ9J;bf%N=`llKHaNVWJdNi@KJ;B2?KRe]&JVf/)4?TO8@,gM9jQc($ +rq(1$o^_IY`kT=3_8=%)^qmt._Vb7`nEfK1oCMq0]"Pi"^rFF8`P]R-]Y*.nnalJMq!dnGoXVQY +`lPI(cc*Z5a25["l/A:TTS5sL@r?4$CLh1-I!KXNB4Mq:aNMlQa3;]HbKnXq99b^.QBdYt0Tqfb +N1-#m1I@1fOcMD22NX8dQBIP`3bEOhH'+PXQ'7JuQBd]#P_VKRd)3i@aNa\+"3ep-`Sno<aUZS8 +[s_%A9ib=t_T]d0`Uh.^`lZ9?cIUF"!!E:#eBlOd`::nU`5&d!=&DnAi;*D'~> +$2FQ#f%p0%rqQ9frr`8tqu$<i$N0r%s8K;N,:6psrr3#ps7uWor;Q^6r;6NorVZ]qn)iitjo>AW +qY^Bnrr2rsqtpBmir3B`s8;oqqu?FoLR+3hR$3i(PaRl)P*SLFF%(,4R?EerPsT+IJs;UiC,(7) +Q'@T!Q^<etQ]dPsG]`i_qZ$Tos8Vuls7JR0LP^eAH%q$-J;Ao:M0;(DUfNe2EIE(VG5cR_FTlef +(^U0Cr;Zm##6Xo)$Sl43H$FRWEG[H?!rDut"9&9'!Y%P7FoHCcF*;Y9(Bt<I!+cE9!!*'&!!!38 +?$;5iR&!;qH$=4GFE_kLE--8>EH>Duqu$Bkrr)irrVl_BG*82YQ'IYsQB7?"Od'Z4O-u)rF$ri2 +P`qK"QBOaGF>Ac<R?Eo"R$O#'Pa%N#O%K-Hq#:<mrr:dQ&H)M&rr<#mmdfc:m*l"7rr;Nf&,H8( +s7u]@-ls[>o`+pds7-*frrhBEm-<L-s*t~> +#6"PpVP_N5rr<#s!W;rrs82d's8Durs89#C*[5"err2uprr;lp'*%t.r;ZfrrVccrnZnX]YI*j! +rr;uss8<*"s8W)si;R*`rVucjs7TNIQBdW"PEqPuQ^*htPX8bt6ZA-ROHPZh6"W92PEqSM0Ro@P +PE_2pQ][N"P*;)TFSu19s8Muss82Wko0%STK7\c#KS,#0Lk'r+HUa*n>d1oVaMPjo`,NW2_S`O# +G'8:^G^P.$NK93cP`Mf`_o'=.`Poi]H[1!fH@C0iLQ7IYPEV!1`l#[3_8=%.^jL0QG("OdGC5@2 +P)YQbN5EEH:S=a\C2S'1E--,>Df'E7DKKl&B))9$rr2lqs8DomGB/h2Q^*glQBIVuQC<r!C+5.0 +O-XfR:L00IQ^!bu6st'kMj'QlQ]d`%Q'RZ!Q^3\'q#C6ks8N&sr;Q`rir8uX&,uM*qV&9XXgFmj +oD/=as7?4$s8)cos7cK9,T._,nc/Uas7-'qs8)K"Un=9Vqu6MD~> +.KB+qG%6-8a3DiG_p$?E`Q$!Abfn5N`PKO2c..pc$O8uGe'Q7Qa2Z-tb5KE]ar/4<`Q$$Bb.;k" +:f_53_TU'D`Pp!Ec-48KhoKl\c,7TCaNr*tH]F;WT9Y_0PF.Z%Od/:BE^Xo0R$!SlP!<J=J!#t] +B.eUrP*)#sR[&eiP*2)kCKT*2_8XC:cd0_Rd*3YNI"dB7I#!B2IXlg%MK_.<T3T(hmI9B*lgOH= +q"X^M\%BApaMbm.^;@`p`5Td8iViH?m-X<7rmA<h_8aI9`5K^:`P]R.]&*#JoCi"Vq"XHfZcU)+ +]ue.,_ns:(^V@;FkhB:8YtetIDf'6*Ci+<<G'Rk=@RNc;c-"2MbKA)Oc.$06O-l?#Pr+_dPE1op +O-=?/Ng>ZhE'[3&OcYikPE8+;EAEH9Q]d\uR$O#'Pa%N#LGRH,_SsO;bK@p*ao]Z(`o4uMb/hfK +\r9W[934qc]>_P$`q.7_`k]^>e]udI#mC`%d*p4Vc1/j^a2,B0=AMV#hY7&#~> +%K$2*g"ZQ,qYC$gs8MrhrXAi(q4K#X,*Mg$s8W#lrW2rrrr;rrrr3Yin*fK$s8W)urr;rrr;Q]n +rr<#Vrr;pXrr<#rqHecDPF%W$Q^3f"P*_K!O=+dS30TMnP*hAd3)EY>PEh1b9p2$-Q'@T"R$Eu+ +P*h,/o`+mhs"!pFs8DUZKSP84K8+u4K7Sf3KSP>9K1^/h]SCQPH$Xa]G&_D2;@j3@!Wi3!#mCP8 +!!!0WCM\4oFouD.&cqh/rrE*%rW!?65B(dmF`__CAeP4Lq#Fk)!sAT.&QO%+Gt"Bs9Qb8oEH-&D +CgD%*DK']=7)JWsrVc`qr;Z]g>DSK/Q^3c)O-c/qOID=j7$EjtPWEJ2P`qH#QB68UE`?#%R?<c" +Pa@]!Q'@N#PD369s8W)ts8UgP!rVrjrVm)an+,u?fDPXJnbs$urVuios7[fb+"7!`rql6brVm#` +kjIp"rr7K~> +s8N5gV52`@rr<#ts8Drsqu6Qo&,Z*k+<2D^p\b'krVulrrVlfps8W#trr2p.r;Z]iTV&']_Y=*. +rVccorVcp!rr)fRrr;pXrr;uppg&E<Od))qQ^3f"P*_K!O=+dS30TMnP*hAd3)EY>PEh1b9p2$- +Q'7JuR?j2,OHbQ%o`+pis"!pFrr2RYK7ec(JV8N+JUrT-IY!-(KM6T$f>GA@_ns.)`5BR/Z?CJ< +H[Ga><Hs(MNffEdQDMd?`5':3_NBIpH%(*dI<g*dKoV@]OH?`f^r=1-`P]ZFFaeRbIslTeH\.-; +Q'%/d]>hLV>c!iZEH$#?E,T`+<butuFEMUj^\.X+r]pM]s8VgrKp%agQB@`!Q^3erRZ]QsPE_2o +3bU12PF%W%OENp1<)f'LP*M;sQ^3f"Pa%Q!L043Ms8N#ts8N&trr2rWrr<!.rVl`ln$T@(Y-4DK +q>L?arr<!.rr;onrq.HV(aA\Ns8;oerX/T&proV*S"f?Ms*t~> +&cM1?F(CKKa3DcA_9p`O_oBjubS\LD`P]U9aj>MH$jUe%d*BbN`lQ<Ibfn0,`rF1#`l#^5bKe/B +@TZH/Hb%)4`l6'>b08)Pb/h`Ji5kr=BZeTFbKiIoPa%`0Q^=#$Q'.K"P`R8-AN5m:R?Er"L,`"1 +PEV8m1JO%&O-c9'PEV#hR?<\\5L@fs_o0^8cHt(g-uO6WI"[?2M2$Y<Jq/K,JU^10@,U8=o^M// +mIKrIqsV&._SlGnJ&8_-_8sa9_Sat'n+,l9p\*"V]t_S,a3)E?_oBg?`kJn4o'Q#;oD8Cb]=,Vl +a2uEB`PB1$^VRY!]^,%AZ!s]"7;cmZChmj,BO,S"BkCj]26>9U`PTd@aNDZM6@=l^Q^3c)O-Q#o +OID=j7$EjtPWEJ2P`qH#QB68UErT)UPF%8mPEM8uPa@]#R#u\UcI'q[aNM]H`r='Y`o4uLbfA#O +_l-^29heMYR_ct_o#MB^_SX[Fc-XZ:&eGc3c,RZ@n]:aN#eu3u7RLM/pA9@~> +&,ZD,g"cW-qtpBms8Mrrs7lR$rV-?l@NcjBYl+Csrr;fns8;iq!rVrprr3,VoCD21qu?ZnrVlis +i;WcTBE%r2rVLPZR$F#*PEhJtSW];%PaRamCJn8pPF%PtNBq8GEKlTSF=3',S<fD,Od2/oOd_Vu +;"akdrr;`mq>C#"G_([&L5L\5<HWkDMMR(?L4Xk=i4=hcHZFLZHZNq98.Gk-!W2p0!s/H&!<E0# +5A5=aFEV=U%KZJ-('+L=!<N9&!!!BlD1$8MF),Cn"UP/1pAe+o!>f-bK8MRBV,q,HF)5An90b:: +A9E'4E-Xq2qY^BnrVQWnohUR8P`h?%N1,usR?X%t.tX.YOCV0Z@[*+@Q&q;"@ouQdPa7`$R['5, +PE_C4PR)DXq>U?lrr;rNrW<#pp\k*ukO7p1o[r[5s8DKe&-)S,rr<#h/fuAed/O(Fr:9jdrrrAc +jRMj)rr7K~> +s8NSiUo*,Ms8W)urqu`os8Vuqs8NK+q#CA#)]Bs&qYL0is8W)urVulqs8Murrt52/qX^2MUoho< +rql]ns8;osrVliqiVioYrr)iqAGl7AG*S/RQ'7K"P+@c%P*DB!1i#ukNg#fpP)VbA6ZJ?QRWKp: +N1?2tQ][T!PE2)pNDB0Hr;HZjs7uNdATrWXIt`]2HW,!:It`N.JV&H'7dSdH]ZIn*^r=4-aKBf4 +G^945GCFseIuBJQNj$CE_SF1+R=0:$H$k!cH['d]Its#GOcZia`4*n,^qjl4KR&)nH@'s_H$t@* +P*Cfa`5KR-<fEYN@WZa0A6VG\.og)&G]%MD6f._=s8W&ps8VdfMO9WkQCEi%Pa7`%Q]3MIR%07K +:e>,\PTQ*SOHr:E=AXs@QC=&-Q'[l%PEqGtQ$.KKrVZZos8Dcnir8uX%fH>(r:@P*YH>%$aS#E0 +o)A[hrr!6(s7%TV*?`T)s8W&frX/W(r77^6S"o*Es*t~> +&c1k-DJ5]YaN_lB_pd/U_8aXsbVI>^`l#[.e([4t$k89IcH4/Ia3)WNc-48K`Poj>b/M97`QQTG +\62m1>`-54_8aF:`qdd9a90H$aisb0A'e%^OHuH/Q'I]!SW];%PaRamCJn8pPF%PtNBq8GEKlTS +F=3',S=#_7O-#?]OIMDd3RcHs`5B74a3iI0@rd$EK8G>5=E]7GMhcq5JU`#2i7dJcqX<n<o(;YU +m_-BQ`Vmi%`PTF)^WFU6]&!&VoCD_Ld_`c4_8aI6aMl$6_T'[;^q&.fp?25Ep]%G/b/;HA`Q6-@ +`5'.&^;IM"q"*\"A!!<`@W?@">Z*a@-rF;iD-g^m4NGje`6$-?aN)F`K9hgdQCEi%Pa7`%Q]3MI +R%07K:e>,\PTQ*SOHr:E=AXs@Pa.;qPEhT%R$a,$OD%b=ccjVUbK'FuiQ)PR`m2`IY[gL%8l&!1 +]Yhk^a:QA0_9LBQc,0ku)]5p-b/qTja9]_K<CB/Y`q/tU~> +&,cJ-g"uc/rVZZps8N#ts7uWopAY("nKfD,+k?Vmr;HZqq>UElrVlrsqu6Tp"P<88kk"]O!r`&p +rVlisi;WcT#6+Z%rVMpprg#:+P*M9"NgQ&pQ^!ng1N"q1Q'dc&RYih28<K7*N@0OHPEV5nS<'&- +R?No&8+uu\rr2pEq>9A;KnbG<LjD#*LH&@]Mh6Y5MM,JDi4k(kG]IkMDJjA_&HW+2!!!-#!&"?Q +#;U"6H#[UR&I&=>"pG)3"U,#1!!!$&#nfXBJ:;EZ@N,ae!!*3&"TSQ,"TeQ%*sNNcG("rn34,VP +E,%^0A"rAO>Zu,aF`hY5?haTsrVldEqtWmHQ^!`#PuX-6Mk?/sGU8Q9P`dY92NjDhRZs2#3,1L6 +RZs&%Pl?dUQ]mZ$P`h;;Y5A1qrr2rqgAV0OqY0sg$1[EPnb(brs8W&erXJf*s8;in@NH^>ZMaRt +nc&Of#laJTnFGf@s8RT~> +#QO_TU9!_]s8DrsquZlts82d2s7cQnrpCmL+<8i0rqucqs8N#rrVlfps8Murrt52/q<4-?V6AVN +r;6Nms8Dutg\rf)rr)irrquSXAWr7?Q'.DsR?!Z!PF%N%J2;'tP*MDuR$rmeAOqrMQ]3AKPl?k* +Oe%T%SX5J&PXP3Er;HWps7lEQ3.lj;JVSM/c%\/XH&$g!ItiSfA*r*i_oBU1aMGj@WdJi3rd+Tk +s*>H*H[:!mOHbfr^;%V%_304jG^4[cI!Yd;*-cg[L5h7TY._iq^;mg0F+J7SHZFR]H?ja\I>7`[ +@>MM3]t.*+Y+n@(CdUa%S`em5=)`&"F_kDip](-irr<#tqFHR2Pa%K!<L/i,T9>F`-'OIUOtLT0 +P*_<"PaILkC-%?CPa%GuP*(lnPE_H!P*TFWqY^6irr;oqrr<#Trr<!.r;HQmp;F5=Xg+V-p&"d[ +rr<!-rVulor;0h;)BQ'Yqu-$`$N:#'iM<!7U=oDCJ,~> +9DI\RC2C&ga3;]B_pd)S_8aR=bfn5N`kBR>d`i+2'F(nrd)a2GaN2TMc-48K`Q$!Ab/M99`ll`G +XAi>"?C/LG_8jL9a2l?Eb2(-R`l6'Bc-4DYG>aHdR[fV-PaRQ!P`qGuR=I)20p7fhPF.er0kEn< +Q^<[ZLm4*gR$3npPF.f)P`7EKeB#VJ`lH0Kb9_@[Jpr>p1s:P.;0@\GJ9uou?Wc+<j72j6nbMkT +s6IJ3_oKjsb$`<1a2Gd6bf7EEp%SF^rm/3g^;7b.`Pf^3^V7=m^Vdq'i:[-LpAas#]?7b,bJMNF +bKS/M`50:*_8>j<l.]i@Ybt$5Bfe:JLXF:;:2FW[D/ENLdE95CaMl-=co6g\PW4to<L/i,T9>F` +-'OIUOtLT0P*_<"PaILkC-%?CP`h5lNK9-gQ'Rl'OHE:qbg+DUb0.fGaMu6Ua:HJ6c-"/9Dbj)" +:eGZ;_8l,f&&uH'dF-4^bruRQ'U?q[a6q"S`Lg*t6X71ipOE~> +$3'u$g#E&3rVlfos7lR(s82]np+%@..J*T>rVccpq>UElrVlorqu6Tup"8m)k5>8Yrr;oprr<#U +rW)orraPj(b#OaoPa7N"PEh;tQBmbuQ'jF"3f0/cPF.H)9N!m%P`Ck]=d#5<R$*^bMMmjjQ'=]0 +s8DusrVZWk>()*[KS+qQRD-@kMUk1IMMHq:F[k]7L3.KYF),Z-65'G-"8Mot!s/?#'+R?JG].FV +$3C2/!WrH)!W`H+!WE'7"Ubl-E,oi1=VLrO!!!6(#Qb#."U5&-!+,g<(0>U,JPS^XWbPa\3jS;; +li-[5;KQtlI!7a:q>^<ks8)Qj</Zs*R$EUXMjKloQ]mk$Kp[jA7m2Q_R$<`$R"RC]G*nDWR?O#$ +SWoD(Pa@Z"PtU!4s8Durs81OL!rVoirVm)slL=B<jO=,.nc&Res8NH(rVr'0+=*HVrr;Nfr;QuZ +mdfQ3s8RT~> +%fcCOUU'Rjs8N#trqu]nrr;lp%fcG's7.KV(FASMs8Drsrr)orrr2lrrr)ir&cMY&eX*,1YNl,b +qu?Worr<#Rrr2otrVldRrVO`9PEM&lPF%JuP*_K#P`h<"1J'WaQBIH!OJ#9F3J!ETOYU(&RZs2& +Q7RrPQC*l"61k-S.K9;DpfMfnK7JH(:78i0M2KkJIYNT/Is=``ikiOK`l5a6`h[p"H['i5H<PH; +I!pX)OclWZa1fBSG'A4YH[0gYG'/.YH@('lLQ%1n`4it#[s2Y>G&r.THZsa]G]n7UJ:s#HLUP+; +_0]!tV.WtT41"D8kP=b%;KHnjGB,_+q>^?ls$6JZs&"Q7Q'dhq-]==[OI)0"4b]8_F@SKJM3sNi +R@&Xd4a*3TQ'mi'PF[r'Pa%N"Q'P,#r;QZprVucorr<#Trr<#ur=&W(q9ZFOY-P"%pAFs]rX]&. +rr;upr;Vj&)'5.Ds8VTf$N0r'mA6>CU!EN7J,~> +7JPr<B6:Yta3)QB`R3)Q_o9X:b08#LaN_]Gf$tBG$Ok;1cc=#E`Q63Hbfn/J`Q$!Cb/V?:`lu]D +Qr@0e?`1iZ_8jOnaT'E>aSs1ma3)WMbKm+NN0]j"Q'[]"P*_K#P`h<"1J'WaQBIH!OJ#9F3J!ET +OYU(&RZs8(OX>d=S"5k*0%JIpb/M69cIYF$I=crrIR]I.[=NkR5(A9<IsQ#tjP8PVmIg5Is8V,m +[D^&*aSj7_aMl<E`l?!9_qk1hq>\sR]"Z&"_nj1,^r=1*]tD.u`PU^9qYBpY[]dig^s0g@`l6$B +bfRlA^W+=1nGDb=PZDb&DI@]HUXm9"g"UL;DJN[0FtLbT7*NNia2,aH6A1GcR$EUXMjKloQ]mk$ +Kp[jA7m2Q_R$<`$R"RC]G*nDWR?<eqS!98*QC!esO?C+ucHFJSai2?B`l?iU&'N#<b0%5@;bft_ +:gU`Na7@:^`ko[Ae]Z1bD\a!!IaH*XnAksWaMt8^7R^O]lLo`~> +s8N/lgZ8>5"TJ>us8Vim&,H2(r66N3,"_h2r;Q`rqYC-jr;HWrr;6Kn"QSA0mcFHJ"9/?"rVl`p +rr)lOrr;pDmn/b2Pa7N"Q]Rf&QB[N"OcPe`7W=HXPaRMjQoe>CR?igiOHu"-PrFg\KVXosQAST3 +rr2rsr;ZSn;0n4WL4iorhn[1NdAS[SKS,/2>);g]J:DW[EboAV'F50P"9\N%!!<#t"q!5)Chb[5 +q>^Nt"8W!)!X0/oAnc$b#71b9!!36+!<!!"!r`1,!WX'CCj(&/4[?'F6Z,(To^))Is7oZ+Ed)G? +C.S3prVuopr;LP_R$3buOt(jGOIhc%PEM)nPse/AQC!f&P*M;U4[>9mR?<f"PaRAsPF%Q!Q'[G% +p\k-ks8;oqgA_-M!;ZQm#O([Hp$0g%s7$!us8;cos8Mel+!DtJp\Fgeo)AXg#lak_lga3)s8RT~> +%KH7CUV$?ts8N#ts8;fns82d.q>L?iaWMNB7K<2]rr<#qrr2lqrr)lrr=T&/s8Mih^Rh=&ZLn1o +r;Zfqrr:dQrr;rrA,Z>o8<9%!P`qH#OIhZ%P`_ArO-VOjE0-NQR>m2n4'#(DQAmb`QB7AqPE7MQ +Um-q)M,3^?rVlcos8&`iFbbO"JR"8o_8OCBW%!FNJqe\ZOoO+Jc,.B>`PS?nDgQVOGl)biI!U!_ +J:`Q9R`*%[Oa(u!I=6HdGBnL[H[U<kI=?a$OK6@;b/8CNJpDNjI!g9`H?sdYG'\RdMh6r-_o06L +909&I6>\kOo',Q?s7fT+Ecl27B1VpqrVuosr&JD9Q]mYtOt(jGOIhc%PEM)nPse/AQC!f&P*M;U +4[>9mR?<f"PaRAsPF%Q!Q'dP(p\k-ks8;oqgA_-Ps83<&rqbBUZ*1F7Sal^Zo)A[h%fQ8(s8D\g +)&aW3pA+^dnbrmnrr)MhSXlFlq>Ys~> +7eYi+Apq>+`lQ6?`m)cJ`Poj<aNDZHaMZ-Ie#Wuj%P$2Wb/hZE_T9mEbfn/J`Q$!Cb/VE>`m)T? +JQH#VA$a4n_oTj<qT/]VilM,=!6G/^@`cp=0nu!\R?No&OIhZ%P`_ArO-VOjE0-NQR>m2n4'#(D +QAmb`QB7ArP`./DUm[O8KKR`4c-=;HbL2D:EJ]C#HrGXFZadWcS0iuAJ;&5GId,))o]u)FrVPK^ +ZG=/kqSdd&a2Gj3]Xk`#qY:$7\[]VtaN2BAaiqiJaN2B=`Q#j:i;``Tpo_-C]tDD(`P]=#^;S(6 +a2,C([_hn9o&clG2lN]JF#u84`l-<\ff`ANG'A"80[[hZaMu$8eld3^Ockii.X[SESsGS(P*2&p +6qC7BQ]mf"Q'E>44[>9mRus#"P*_#oQ'mu'PEUb^dEBeYc,e#IqoJf[iQ)PQa3;ZI\VaB`92JSf +[)9oSaT'6i`6?]Vc,kPF&e[s\_og*kaT'9d`O/rA7p)>Fp4*~> +s8N/ehWk(>#6+Mts8W)rq>Lg"s8Mr"+<r(Er;?TppAP-krr2os!W;iorrgm5nEfK?rs8W(rqlZl +r;Q]os4RBZr)n]AQ^<r%Q^M`[Occ#sR%0+#4Dg7GQ'\#)Q$#5DNKo]mQC3`%Pa@"FR[&l$Q?[B@ +rVliqr;?7LN0&^JLL?/2hT3UKY;:'OJUrZ2<KlgcMfEi_BMpW-().>h$i10M#Qt>;#6=uH7qG+4 +((:cT!<NE1$P!RO"Tnf-!sAi7&iFKG0bG-*"UYD:!tG\L%L`aQ$OI"?!sKN:BmY>R11Y-uKhlko +Fli#erqcI]BQS9:F&n.ms82]ns7h^lR$*`!Q9nc;Q&h&nQBIZ$M(^M-JrZ1cPF@T"D_lQlSX,P& +PEh@uOd)6"PEqM^@/Km"rr;oqs4[GRr;6?grs.`Sn+6"ns8VTf!rr8trr3<%d3p1[8H8_hs7$!o +s8N&[lLF)us8RT~> +%fc@8UrN6+s8N#ts8;forr;lp$N'l%qQ(VV*+o'Er;ZZnrr<#ts8<Q/s8W)opTC<iX1\9.rVccr +rr2rQrr2rqra>^&=+Za'Q'@Q#R;SIUOdMH%S;]]qD3C-KQ^j8)FZhF<Q'7K!R>m]!Q@^3IQ&:om +G]<<Qrr2lrrq8=,MLC&.?B"=1ai(ru0kl2dIt`MWSG_<d^Ve1-WK)=KGBe?-GURl`G'S=WK9N:J +S:#U)L3@rkH$FU\H?j^[I!g6cH@(RJaiKQeK6VV>J-C+CGC+[_rd"Nj=F>UJN4?gK^nX&"AtsrP +FB*DAlM1>RqF>7@DfK\qM>I8Lr;ZfjMe8<=Q'@S$>*5)2Od;;rR?`U^07o4NR?O)$QZ"['LRj`r +OHYro6'7D!Q]m`%I:E3R"TJH!rr:^Os8W,t%/^#$k-hOtYHODWrVc<drr3H)rr2rocQaDI7/m5c +s7-'qrVlckZ(ISY\G6&R~> +8+tkoA;\+8`lQ6@aNVlL`Q#p=aNDZHaMlQOdu=SC$qJ^ic,[fB`lQ<Hbf\#H`lQ<Hbf7W@`llB8 +D-U7IDRmd,`Q-!=ans0Z`o>)=`W4*Yb$iQG5'E3[RZs#&R;SIUOdMH%S;]]qD3C-KQ^j8)FZhF< +Q'7K!R>m]"P^XR=Q][l)DHP94bg"8Nc.!thN.cn8;LR9B\$iQ7,\D[ZJ;/PJLYpM6jm;d4hoE13 +\@T;crP/?F(r<u$^Ug_Y^tS8)Za@0_]"l+u_SjF4_nQ,bs1EWj]"m)#s2M(KYdM9a_n!Lk\[Ju] +_8aF-\@&WUkk"K2]K]P1Vhn;o:0tcOaN_uZ.pI"<H>Gr]bL"5D`6$>P@Zun;P*SF<Od1uiQBm]% +Q&..IJrZ1cPF@T"D_lQlSX>b*PEV.qOd;H(PE_2P:"78,b0.lIans0Zb2LDPb/hiLaLmdA;+aSb +;5_=No#MB^a2Z<LcHXS4%h8dkd)jANn]2'X`l5K"9Li0Di:MO~> +s8N/\hXLLD#6+Gqs8W)rq>L^!qtg8m.jld<p\t0orVZ]hrr2rtr;Q^!cfOZ\p&>!krWN2srVZTl +rr<#SrW)orra5MQE0uuZPa%Al1RF8gRuinoQCC]bP`q>nS!&r&,X-C8S;W_uSW0)$>=+L:Pa[hL +Q21FXs8DrlG\DVZLPT$,qtB$f_8g8#LP:YFIu$k2m`'s&Hu4.$5Yam<8432@(d15X8kDB==#b,+ +=]8I#;c6Oo=BSa/='5H&(0+C;<Fe%/F),Po?!^K+?!LTE?XI&@r`ET4=]SQo958g0CG9ZpWM`L2 +EI-[2s7u]nni(c0DKp4ah#I9Krr;l5=Hnu:P`fE4O-H&sSqrSsO]4V7NL?&mQ][PtFX)m=OH?#u +Q^Nm]C6b*NPF.MJLA1`Err;rqs4[GRr;-<grs7cRn+6(sr;Z`crW)orrsS`'s8";p/R%iIrr)?c +$31#)m-4*+h#ID)~> +&-)@)UXJr8rr)irs8;fos7uX#rVQEgW@&l8SbE'_!ri/uqu6Wqrr2rr&cVh1rVZ8]V5p]@qYpNo +rr;uos5<nUs8W(.rVlfpqL<CIQ'RZ!PE%GcP*;AsQ&M#u:hc/XP`VAtP*mRZG*AGSQ^"&#R#kK; +OHGZmPA$6XrVccps7pkMH[LBr;kX$]jMo'WC1;dEL51&-:r<+k_SXL1bFOinU7eEZr20Ik0VkVC +US4?_^6$1>Z)kC?\$`TLZa-j>Yd:^F[^EKK[E=iL\@B8Z\@]&O^UCDX['onA@CE\V^U1;`^po.Y +Cd=hl8o8Hihs(1:s8DOJGACu9E&l_Qqu$Kopq9OgPF7Yu?oF(1R?X;!PF%D25t$^#Q&h8oQ'?D9 +NM)ApSX#P0O!\V,QBm`&PAH'Ms8)`prVccMrr<!.rr)corURP)Xfnssf)#=8rXf,/s8W)qrr;aB ++t6Ucs8W&frX/W(rVX7$SXlkRrdX~> +$hW1q@@"[G`l?*Bb5TH^`r='Yb5]Q_`t$5<L("P%GKA(Ua2Gm:aSj7$aMu6@b08)L`Q#p?`j];Z +?!Dfm`lcBDaiDNEaSX!:aSs3ZaCE93aN`4H@Zd%GP*2#h1RF8gRuinoQCC]bP`q>nS!&r&,X-C8 +S;W_uSW0&"=?i"8R%9@CH.'sZbKJ5Z>?6!!Kn;jTj4qk`[(BLAItN]>I=jtjhq$?Bp?hb)a4f8# +iSXRnro+mSjlY[`gYhD3n`AflnacA@lfm^"l0.?rlKRR3k^!'Io^D/;kO8-6nG`(Jo'>W.o_87Y +p%%V@in`n_hOcrD4f"lHChI@s_U-3DaiPWCE,p)6+LokA_SaF=Valc-Q]dG:2NO)jPb*\pQ&em1 +7#dV"O-buoP]\41TTG>/Q'[hs->Jm7QB@Dk@<0Z8`lQ9Ba2uEDqo[m=&')f:aiM5n@oH&p<_epp +`:Ct\`l,sEcH45Vd1-Wt1rRMUa777N`sBYrEDT8-I+\%@~> +s8N/Wh=U[G#QFPrs8W)qr;-C's8DunrV6<;irArQrr;urp&>!ks83K-s8UI.o&TcLrVuoprVQQk +r;HWps5!\SrA=NRpnqSdQ'mo&P%QM%R[0,'PaIc!1KTa,Q(!f#R$)hT>*,)<PEV8tQ'OC7P+7c% +P$>0ir;ZaDqpn,iN/*()D#*l(gr@=..><P5KnkD84P]D?K6hW`Ed2SAFDko6rG2@K)f0D1EHcG9 +BQJ35F)Z/<D0'];FE;JDG]e+MEW0njD.%:-K6_Z^F`_\HC3XuGH?XLQrbu+bG&(c'?ZCOZ2]m3[ +:og$VF[`A$rVccqqWB_WEHQ5(L%t]Jqu6W[8X>O+P*CDCPF.PuPF7]#OZ=nPPa%K$PF.W#G"\*` +Q'RSsR>m.s23j>hPaRS?V"Xicrr2urg&;'Nqu$Bl#3P4@o^^N*rr;Nf%KHG,r;Z]l]%m/Ws82ca +rr<!(rr;BKna"g,s*t~> +&HD?sU>#GCrVc`qs8Dlps8Vrp$ig2*q"saZc/AX"qYpNkrr<#qrr<!.r;H,VUp$oPqYgHorr;uo +s53hUs8Drss'PT!@$-Y>Q'RSG0nYp\P*_E#QB<t)P*hN'OHu8sHo>/iQ^Eu#Q'RVu2Hl31Octo4 +Z2ak%rr)cF5_FfBIVWZmq>K3l`M4o8JUr9%J:BcCr8,3-_8X40_8++1_8uSo!6"lU(rjP/]=u/$ +ai208a2>m7_SsF1`PfR.`P_\lG/M28`kop6_S<q'`P]U7]Z%h(`50@2`PTF+_nsL@`Q#X%8Kr1h +9W4:IEC-SlrVlisr9-%ZDfBPpK_>?Er;HZV7$a%'P*CDCPF.PuPF7]#OZ=nPPa%K$PF.W#G"\*` +Q'RSsR>m.s23j>hPa[\CVYC,frr2urg&;Q_rr;uqrr;`,Z`gU:REPF)o)AXgs8EE(s8;`&f_>+> +r;Q`crX&W'qn])#SYYfTJ,~> +"nC2Y>b/\0`WXB,b/VI#aSj9\a:ZS8cH+M`gTJ$3aMc*@`Pop>rlQ5%`l?0Dbfn)G`lQ0>Yut1: +?&lY>bK7fHa2uEDqo7U9s2P)[s2AEdc-_DINg?,tOcj?3K:8*hQ^!l'OY^(%R$F,%QC*h_2Hl3/ +R$3`!QB[Xn>EtkKQAeFsd`TSPc.'3SHA7'$@TM:9h8HY1R2gF%LkUY<IP]C2ce%XSp$h\GnG2kQ +rVlZnq>U-gqKVc0r;HEap$hGCp&"^`p[[nIoBu/?oC28<n+#u>n+uYMnF6#Dqu6WhrV5mRnFQMS +r;6?fp\=[RmGci..s#AqUQRoV0oX,q`Q#p@a<YYDFD+-WdaH7S`R2[[N/j0bP'eX@R$3buR?`qr +3@^)SPa7]#R$EpUG"\*`Q'df"R>Zqo24'PlP*Li)Nm#bfai_`FrlFuZiQ)SNaNhoK_6%EP:/+\\ +LV:XGo>hK_`Q69I`lZ<IQFk_ocbm`AnAkpV`P$Lr9iGuVmsk~> +s8N2Zh"q!Krs/Q!qu?]oqu#IQs8W,u"98Aur;Q^"dd?>Ws8VllrVlisg&>7Tb#4UlQ^*f!4]6Eh +P`V5tPa7W"P`_5rQ^3c#P`JILQB@T'PF%MrOt:j>R$X,$:>#:;q>^Eh>BPaSMLe(fs7uQK_Si<3 +J;K&<Lk:FBj6OL;HZO=SG]n7QqK)UX%X)r>H[0^E9NQ4RF)uPJrcS9arc8fsG'&+WFEDJ:BfB=? +H@'jYG'J1OF8^8iH$FUTFaSX_DIFbuEIonmEGBMoNi6Pr/;3Egrr;rqprPjFFE;Ifch[P<s8Vg^ +QC=,)P)_56Q^!i#PaRf$PED/pQ&q8uQ'[PuR>mK!P+%]#R=%Y3GES;WQ'G7gqu-NorRq/[r;$Bl +s8N&unEKQ8oB+p/s3LZLs7kI<mb\!DJ,~> +%K>OdU?;@Or;HWps8Dlps82fps8W)urVucqrVlfps82fqs8W&srr2p'rqPcHX/iD`r:L$Hrr<#u +rr2rtrWC8=P`u*3;3O.@FdJ>SQ^3l%QB[VrQ'I]%OdD;n94jKPR@08*P`LnUG)hiPP`\erqYpEm +r:jH:KmeZ'55,$SrSbZ3V)`sVJ:`E$KK8>lhSR7H_ns:i_uI[S_uI[S_[j]+_nWq"_o8dY_SjI1 +`52Gi!5nfSs2,G_`l#X4`l6)q^r!h(_SX4,_YqCP`#?M/`kK1(_84(+Nl]2R:bm*)DGl@f@Tt=7 +mf*5Rqu$935]La]Da2MBr;HZqoKe_0Q'@Dj/o6f9Q'%8tP`q;nQBRSqQ'di'O-c8oQ'dZ#P`_;Y +8Qg1tQ'7Gt;TSe9rr2rrg&;Q_r;ZWlrVlT:['Qj:Vm#moo)AXgs8N&us8N#q!WE#rs760gr<N#B +T:DLMjnsW~> +%e%MO=fK9U`Q$!Cb/VEAr6##[rl,nub0A>ae'6%XaMu3=`lQ6Db/hZD`lcHJb/hU%a9]P^;I*L8 +SAEAFaSEj7aT'9[aSs1_b1*IZOd;AuOHVh*FdJ>SQ^3l%QB[VrQ'I]%OdD;n94jKPR@08*P`h.Z +GE\PdQ%_3'a2Ps>d+Us%J:3#k/(`G$f#4i-TeCSCLP^k<K/)*;eDKogo^VDLnc/4[o`"I^nIY0[ +mdg&Hr:o+'na>o8o(2MQoDe?.n+#l6p%%SEp%%dul1"*/m-aE9pA"@OmHX!&me#u<p@\(Nn[e8U +i,)#:E,SI%R9*&sAAZL/aN2ZSXYXj7DItK-e]c(Tbf_>gP`_&gM_Aq5PEqAoQBIAoOd;2rOHl2u +Q]IK$NKolpS!B/(HV.IdPEq>lMajqt`r='Z`rO3Vb2LDQ_p$9Ja2501=A_[f=)#:c`q.7\`l5p< +aMu6@bgk:pccH+)!64TN$HL-)[YdsU<GTA9J,~> +s8N2\hYmBOrs/Q!qu?]oqu#IQs8W,u"98Aur;Q^"ea2M[s8VllrVlisg&<f#m6d8*Q^O"^:gA7- +Q(!r'Q]mSsQ(O2*Ng#lsPFmr#OdhDpS;rl%A3,O6PF%Q"54\aQrZLpH8r8.UKMeWArVlQQb/)&. +7Y$8BKo1M97H;(>FE_s.GkcI^G^"FXFa/.VEGS#b;/^GrFEr(TH$ORUEcQ5EH?ORVDK&i;+AH`u +H?FFUH?saWG'8"NGBe.RH$jmX=t(.oEHu\:ApA9=6`d+Pki2%+s82cpr;Bu2DfC#@8,3)_rV6D5 +G*A2[R#*jpOIq]0PE_W(OdD5qR[P.\OHts!Ng#ltPF@r*R>uApG>afoR?s./g&(aIs8CUL%Jp,( +s8N&un`TK6p$191s3^iFrs&DWlg<X1s*t~> +&,kLaVX=?]r;HWps8Dors82fms8W)urVlfos82cts8N#rrr2os#laGJQE.-qoDJ7\hu3WUrVlis +1]I+76'[UuR?Dhl>^2BrRZs,)PEM/qT95J#PF7`#T9,8!Ru``&Ng5o>3/3`]Q'@S#p&=t7rqEuo +L4=i+:8Rdds8(m$^r'\MH@U3jKR\\Kn(P^n_o)Jjpqni'_ns=,_nj4*`NG'"_o0O1`59C-_8F10 +`Pf[3^;7_(be]p6\&#o"_ns7*^r"",`;[_`_n<n&_o'F(PD%)u\<h5MF`2@dWM)W?iUHdFr;6Nn +s'K,KCj'V_p\b!gq#>8SP*DB$Lc@kaSWKJ,PFRo#Q]dT%R[0&$O.MAqR?s,)R$3kqEa*Z_QB[c& +PXsL+s8N#trRh)[rVu`mrVlZC['Hd:W2TLio)AIb!<2ur!<2oro)9!prr;iHUn"$Pi;8$~> +&+%/F>d))c`Q$!Cb/M?@b5TTeb/hZDrP]#]aNVoRb/h[%`rF-[b5]Nf`lQ6Dbf\#Hrl>AWQqppl +C9GIsqoJTQiQ,EHaNDTF`l6$AbqbBER$Wn[:gA7-Q(!r'Q]mSsQ(O2*Ng#lsPFmr#OdhDpS;rl& +AN>U:QC<ni,08*NaNDi+5(S$0G<:Q*cHjhW]=c'h5(&-4JqeZ$4knNHnFu\IrpTaSrpTmS'^OrI +me-ARi47e:nF5c3m-jK9naZSHH1:7loC;_HbIQKsm-X*)mdp&BoC(u.kj7^$nF#i;oBO6!p[-Y> +Km8&`CGVEE1=<tT`Q,m=dEU95;J9ie@l)lic,[]I9P'3FQ'I(a7us7(TTG;)PED2pPa\&,OHts! +Ng#ltPFIu)R#Q/lG#OfoQB@%e_9U("aT'9\aSF!;a:Q;5b0@uC[Y@p]8l/Jo\])S[a:ZG2`Q#p: +`Q$!FdEg%V`P][7o#M0YaN2#V=%uV)[-E/~> +"onDYiW&fSrs/Q#r;Zfpqu#IQs8W&ss8;os#5[-BkMQ=>b5PKBkX^u'Pa[b$Nb;^aNg6#sNg?-% +OI),qQ][AnOckupQ][]!Q'n,*6TU9rQBdbYG5;%,s8)U`G):p,?_I&hs7lNJ`PK=3838OsB827o +3kW4ZG'\B3G5QL]G5ZYYH#n%@AO$Y58nr<eFE_bJH$X^XEcQ5EH$XRPE*b@4&P6ndGBJ+SI=6Ba +G]n.JCNjl?HZs"$('PR_CjUdZCNFgg@=Y8&Np?$(rr5:]q>9;=H#mhF=+pJCs8VuT9Tb^,P`Ipn +J")RaS!o7UQBdf$OB$"`Q^3c$Pa.Z!P*M5oRq?;r<.0suP`eYpqu-NorRh)Yqu?Zqrr<#nk4&$< +ma_=:d/O(F#6*EDn)=<HJ,~> +&,Y"VWV6Alqu-Nos8N#ts82fks8N#rs7$$ers//6R&[<uqYg?krVtIJs8N3#s5ulNP#@a36&oSb +Q&_,tP`D&uR?3buQ'[VpPED#nQ'[W$P*MH)OZt^\Q^!]!GC'5fpAasb7WjE:JR"`9r;ZZohS[+A +`^Ma86Y(b&K0[K4]"c5&_Y1nH_@=E$_T'O9ZAa[E`5KX2rknoT^r""g`W*i"_SF(5`2&0H[`-/& +_SO"%^;.V&`5Td7bJh3:aMGZLJ!%pn^Tg"FF*d+XI%tnFlgXZKs8MiirT67eDeX2jKDP9@s81eK +OdD8qN]KFRR?*K!R>Q!MQ'[_s<G@ngQB@Q!Q'mbrPECurAS$s$H]a\ZP"XX0rr3'!rVb@I%fcD) +rr;oS['6a;W1`k^o)AFarVl`pnGW^nqq\->SYFd6J,~> +&*L?3?FIkq`Q$!Cb/M?@b5TTlb/hZD`Poa4`Q#psaSj-NaT'E_aT'BgbIW@(>?u0V_u@gYaSj-3 +aBm$1aMu3?e]9\/PEhSu6&oSbQ&_,tP`D&uR?3buQ'[VpPED#nQ'[W$P*MH)P!D$fS=,V'@TUam +^!4aT3cft&G"I2*aN_`Q^U1el_a$.45[SqhGVZ_]h=UXAoD\:YoD\:Ymsj`jl14HEk.S@fq"+(D +md0?2oC;A>mHsB3o'u>Mo[:%Pht6L/m-a94o^qbDlg!d$p[[\Ep$CtSYf6P/ilOoAF)p)4E11Ti +beq6<a3D]CbJGZCChR]ZESSgfd)W^XM3<p^N&s=US</o$Q\]RGQ'[_s<G@ngQB@Q!Q'qZ7&!W6< +Qt'`j<IU*sNefj9cMkfbaN)F%b1juK`Q63IaMYWU>>@de;H1*A`q.7O`r*d`_o9X<bfn/J`P][7 +n&PaKRTrWc?)Hh9~> +"on/Sj8\oRrs&K#rr<#rr8IYTs8N#sr;Zd$nE96'iW&r#r`B$f6Bdb)Ne0]_Cg*BqQ'@W"SW/Vs +Pa7St67\4bQB[_D309nrO-"K_4-l5%P`n_pqtpEdrI871KS*rcp](*io`*dh`l2qTZ"/bqJqeVE +`5ma[F)q)!qfZ1gG'%qA@Rpb+$V"lNGBS1MF*W(VF`VVHG'.tIDdY@1$kZ0QF`__NH$t*dG^+CP +DesB7G'%A%*"WPk>A\kC)/3\6^A1C"W)(t+s8VinqZ$-dgHBV!G&_L\63$fVqu(#VQBIc#85`BP +RZNl!BM"DRRZMJ\>@W_ZR#df#Pa@])QCNqDEg(oFR$s/%:Y#@@rr)orfDZ6Xs8N&urVuoZme$>H +e,KBqrX/])s8W)Ql1!a2s*t~> +$Mr&DY5A8!qu-Norr2rtr;Q<fnG`@c#PPNqX0K>3r;?Qms472Ks"XKA6'.A!Ne0]_Cg*BqQ'@W" +SW/VsPa7St67\4bQB[_D309nrO-"?W2j'AmP*8Strr42:qL)\'J:M3Xp&Fphp]'*i`5?GIWF(E^ +ItW5IcfMsZ^;'9W%`6-#b/;61LQ7P&`59F-rko&X^r""-`Pf[n_A:85V2C4l]?.t-_o'7(^;.S% +_oBa9ao94d_T.t+Oc%/r_m_[NBeR9q8#)hRe`d&5q#C-hp&E`,E,Tc6Da46rp\Xr!JsDIfO@E&D +PaIJsO_74KQC<nS8m>edQ'dW'Od)2sR?a8#@;q?U8sYm,PYfp/rr<#trRh,Krsno)s8N#b[]Zg; +WLEATrUTs`s8N#ps76-rs8N&oiMW09U!NRc~> +&*'[#@^sD!a2l?EaMl->b5TTeb/hTBpr36Prl>)^oZ.'QaSs<e]QI7[@<K*!rlY8^rPmO3s2nTf +`PojEd4^EDRuW"fP&+<mQBd]$Pb!enR?X#&P!U[^QBmc%?oX7CO,oBC:cO`-S!/[e]?SFEaOb$, +Kn"AI?d@$8aM?HF\])X)Ju;h#88r]i6,)C>p\".MqXaXT/+<#sl14?<m^g0MkP=lEmI'?0nal;@ +n*TN2nFQ5JpXd!e]'0%`nF#f8oD\@bnaGf0n,;oen+"0/_SQ0@kgE%I?llB/31ZU+]ti%=^<OX> +][aYDBl8!,@k-B`a2c\)HB=)RN^lrGQ^No!O(CeEQC<nS8m>edQ'dW'Od)2tQ]mhp?ZD6X9p_3) +MF+r#`Q#p=a8O09a:ZG4a3)]L`4r0U9M/&X9s;ISo#UjNr5AZUrlG,Zrl"lWo#M0\aN)#e?;OL# +R-&o~> +"omuMkPt8Ts8;lrr8IYTs8N#sr!<<%k3_R"lMpn`rr<#Er`B!`8!T=.OB$mrK2[\oP*D2pP*)$# +P*hG5DKeI6O-u+r9TbI'R[?cd7@TF'P]_3Hp\t'_:i_8FL42kjs7uTlr;#Eq^91;4Q<*Wk<GcP2 +fsl`bFa!_)pN:CtF`;>6:_!j5#"NNSH[:$\F*;eOG'.qNF`qV>?n`#m"qO=DEH$#EH$k!bG^+CQ +Ecu2CG%PD%#QP5BA9NQP)Ib7hp\:e(X+kHTo)&:`s8MonrMN)0Ed;G3DY=&.p>SE%Od;>'G"71L +Sro-[>rI\2OHi=^Hr"O>R?s&#S<T>(OHZ8ADNpSWN09Ws9$mG5rr)orfDb^J#lXf'kO&!=p<rs? +df0:Frr3/Ul0md.s*t~> +$M_W9Zi:"(qYgEmr;Z]ooDe[drVufpr;R'"pSOR_[E84Br;QZpf)G[K=8_ARP*25p<J$Ee;i?s) +Pa%ApOd2K#R$1NfG=.[WR?9d/OcbruQq1sXQ]I8mFa<u`s8DUcE.j"#HqX25q>L?nqW,]1XA#OQ +;Y"L"D/VZ"e\0#>`:Llb_Sa41`k$qfNfL?\^qmb%_o0F/_o'F2_o0L0b/U68N/in-`P01-a2>[, +^qmn*`5Tm3`l#F4MMm=OK#bmIYs37bUAFV`Au:/smIgJUs8W)rr;EHXF`)>8@rCr=s7bJ=OcYio +7!(kKP+7Vq,$[!bRZNe)H@/M(OI;GtPamu'PE1lt>\oRj6&LemQqGa'rVcfqqu6Qoir8rW%f?8* +rr;]&Xfee,Qg"AGnG`%ZnbrmqrVlWVWgfNP`VY/~> +$K.OdB=c"&ai_]Grl+u[b5TTcb/j@trl+oW#0=s0bf\#JrPncVrl4u\$,jGf='9'e]uJ4naSj-Y +aSj9?aT'Cgbf\#G`Q$9K1l[]hOAgapK2[\oP*D2pP*)$#P*hG5DKeI6O-u+r9TbI'R[?TZ5a[^t +O_\CYaj88Y2e.GpJ8[9od_io=aNhl<]<=f!LIU#l3`T?5e'm7Op%A:Uq"#9koC;8Bq<ko6^qf./ +p[mqDmd]o?naZSH%.`obpXQsi^;'"1o'lYLC%Lujo^hVAn+Q)Fqss`r\$s5ds7u$.:N%D3gY7ru +UOQXp`lGj7bJ;!;f8_b0DffJi<n5mKccnM0Mj'AoF\%1LSW8_41Q@ibPt-.J:MZ&[Q][N&P`q5h +Ngj3hPFFsuO-GYg\BW"la8j9Zb5]Q]`o>&O`lH-Cc,moAZ"$F!92J-T_8buco>^=A$H^?.^8>@9 +:/m/5J,~> +"omiEm/QeYrrW3"s8DlSrr<#trX8Z$r;ZfSoBPH0s8W)ts8UCD4lSi"QBQ>aQ&BZbPEDH!NKfcu +P`V/l:4\U,4boPiPV#n#P`hAV;05KsPEhJ7\G,mtoSd:;KR&AB`;f]5rtPG*ikrH9PH8K>pA&H7 +4$`2JLOF7@Fo?IaFa!_+'Q\A+=qM;M!!Gf/GC=gbF`V\JG'<k0&p827?oAQ!!W`j+DK0]<F`_qU +rchssF)uGKF_ke0#QY#<)IIN<JK6Otp%S@\>b7rs`r,i9qZ$Qps8MgcCNFT;F#VhIs8)G/G*SJ\ +=D2JJPaI`*AO:4#Oc2JTKml^<Q]dW(MiUPUQBdS9F-quP2i`re;n`&+e,BCJrr2p*r;Q`^me?JO +f_5@Fdf0:Err3/Vkj[j*s*t~> +#ku*.]Dqp/r;HWorVuiqrr;lpr;ZTlrVuos!WE#prs8PsS"ZaeebK+@rr)lJrr)j[iBiutO`F3^ +MfMp`Oe.\pPa@i'OHko&JWitpLRaKk/QJ(#P*^>dE(H+RPEo4[qu6TfMdM3jH&+r-s8)]o'DLM& +]NgPuA&e6>C1]\$q:ra*^\5PF_Yq@d`6,s3K8u%VNj6I:^qIS$`5BL0_u@OQ__KEUW/ch"O,g]g +_8O@5_na((_8=+.`5BX4_97UlNffWg_S=%"7Rr=4r;HLqS#KK1rr5=]rVlisr:i`pDfBQ42;%[' +r:P&QPaI\9Anb))QB[hK6#;pNN';fHIS=mNP*MPqO%XY]P`T$fQAgtaNK0E*^&7U'rVtmVrr3#s +rVlg'qnK;;X/q`BrVc3aq#Ba\$NL&(rUR.^R\7@jJ,~> +#2Y\TDn*^*rlY5[rlG)]!6G/Zs2b5_s2b2Zs2>#[b5KNbb/jP$rQ,#Y%E6?0b/M"s=B9!t^W+Fp +aSj-YaT'Babf\)faT'Cfbf\#G`Q$BD0U7ofE_MaVE`eNfSro"sQ^X/#Q&nalP>XQ!S<9$f<L&f3 +QZPi:7?E[sPY%V#cd0jS;hK^JJ2F1VaNMNBbK\&6\6Y#a=0^9)6pr:TjkAYfnGDhTnb_nkqss?f +_83q"jnSH>n+,u<o^qbFrpLHho)/48^qRb'_<_!joC2;<oD\AnoC;;<me?MQs1GnS^W+7goC1I9 +7<I53e_*KXVbaPMccNo<^rk!Pg,3;VEGT>9_:@2giFd%hP`f*\Cf?OaP*fW?Cm^?D5(SE:9Qc\b +Q(3bn8T^)VN`U7fO-MV]M2t0'c,KY&rQ>/]s2P)XilM,=s3(nn`l>N%9M7rR8XI<6o#UjR!6G)X +s2G#Xm)TLQaMP,o;,'o<ja[~> +%fbYJoDeU`s8W)us8;cli;WcV!<2uq#lFQ"s4d>6iVW?KrVlipf`"pe=d"i41lINeHs2JpP"%Q. +OHYitOCW3jP#t;$PETNQ?'(D<Pt?1?=Hf5FHU[Yuq=e?:L4P,7DH-Z6rr)fqqZ#QqSm/=SCA@H$ +p@h!Gk/*$uGC'11rHJ?dGl;eEEF<#]&deX>#=N<IH$FXWF)l;DG^=[]F_tYN&I/F=!"r(IFE2;> +EHl_OG'J7SFa/(AC)[0XrW$"2@s!$C865-PqYg'.=JD9bp%eF`s8Dilr:Xr:E,p8EGs&A'oSl%& +RZiYH?@YM&P*D2H>"4I=I8#<EJQb7!Q&V,s?t`JCQ]PosP*qSC8<]NKSGN34rr<!-rVlcms75[S +pAEe3s8UOHs8;lr"lAM6lK\D"~> +$hh-*_uKc6rr)iprr2rrrr2rlrr<#trr;rrrql]rrVl`p$NC(uPbb4]htR'Io_njjh#@9P4MP!Z +NKl>YP+6o'N0]Vr4ACp$P+7VED39u`8U6M`A5?KmQ^*h-FDk0?R@JRlq"=R]@;LLBKnaJGs8Drr +(B==4il.HlWeb6\p&Fg`92P3:`4j11r58KM!Q2eR_[s](_T77dNfK?hZc0i"^Vdqf_u[cmrk\WP% +`YN/O-GfiOL`BL`lH*<qniBO@)KsrbDq4AQ'@/^aiM</GAHmNs8Vf7=/)3eq#'sfs82Zhqt=c5C +i4E5Fuuu#oo)(&R?EGC>^f(sOHYlC=[n@<I8#<EJQb7!Q&V,s?tWA@QB,]nOI)/;8!9?ISG`*[r +VtmVrr3K+qu6Wpr5GtGX0%r8r;Gs\rVu6`$NL&(rqNahS>*LiJ,~> +$ephQGIYW2cHOGN`VmmXaoKN^`rF*[b5KQaapQ50`Q63Gc-=JTaS3[b`Q$-GagtAS<ahT8aNDTF +qo8ZW"Nns4b0&_b?cpU:b/hQ@`m^SMMN4&\MisTX>)\c17QaD,PEMGtA8RHl=@me%P@RHpOI)5t +7rN-=N1-2Y3T/?3cU(c`Jr#(j6/g;8`59O:fZ(@e<hk">fuqjdcRCa*gZ%VioD\:Vn,;c,oCVSI +ZG"#c]tN@pnF5i7nF?/CoC;;<naZ2CfY5,?`5KR\r:TXJlg!s/rpr;Cn*TH1n,L>6`4isn]))0e +g5Bq6gs4!ZVa[&=7G6#)`l>g1`6He1<G?AqC2GDdc-ptq4Htk^CgDT^M>iV`AlV<ZR=.b^J:Ulf +OHkflQXFB"<g&AQC6=sN?U]s:;2!35aN48$s2Y2[rl*m<&]Vf1bf\#I`Og(b9L_iOLV_"%a9'N. +bl#Nb`l5p:aSs?Na9fl-_maJ\9MfuoJ,~> +$if;Dq#C<is8N#ts8MrSrr;uurr)a"rr<#LrU8_Dqu6cts8N&Hr`Srs?'Lg?LQe'bEE8HI7>Had +Pa.MrF'FZrOASDfP*%b<?'1P:Hr,K2@[3:A5W1anojgFIK8G>36fn(<s8)cks8Cfl8"leZjSo/W +qYBaRn\Bp'HZF@VrHS<es*,Z0F`VV?;%O6F!rr<'6tpU`G'S1NEcQ>KI!TsUC,ce/r;[3;9lP5q +DK9lCG&qa(Fp<).G%2Eq$2sp,#8(HaH$tI=hY-[@s8$\pWF3%0rr;rsrVu`opNp%aEd2YC7TtmW +KP4MVQ?$#ZCfHagQ#fr$GE@SJK7SD5N'<JpP*7teR<Uo_A8.6mQ]X@iP'2!ErVZWps4RA_rVuop +rr2coo^MPGqr-Z:s3glIrVZZp"l8A3m-4P#~> +$hUs&aSu5:s8N#rrVccqrr2rlrr<#nrqufqrr2rtrX&MkOK#:bjno#Trr*$"rr2ldrW)u\rr<"$ +rqEKuOI8+aPF%;L<g[nrLPeB^Q'IJQ>E5;:;+,MhOZ-rZOdV;Y:k31cOd;%m2Ep^*AO2'!KS=kC +jnJQMqu?NlrSGC]TqkQDr;ZfqrV6<ih8$hI^Vfi`rkncS&')JCNK0!\QB&;k`5TO0_Z%K'_nj.) +_o9crNf9!\P`Ca2`l#d5`lH!6`5KO1_o0=4`JTD8Od)#lMTNcQ_S*MGs8DutqeqFmA$u=8s8;op +s8)chGuns&FDkq_=HHa?B3:OdEE%O);jNc7E`>eXOG?5VJUBV>5*VM!P<4_jG<M:&B9ACCO#i8` +G'Ei^r;H]rrr2lrmJd+bp\ka&s8Vuqs8Do=Za$R7TYUC%lMge_m/@@lr;QTgZCd_^ZMB"~> +&($5DJ@ie>c-"2M`lQ6@`r='Y`rF*[b5KQaaoof*`lQ=$bQ>r.aSNmfaMu6@bf[o0941q5V8UHt +aSs0\aND[)aT'B`bf]_%!64uYs2slQs2n]mb/hTAaNKT;NLW1fPF%;L<g[nrLPeB^Q'IJQ>E5;: +;+,GfO#UfYOdV;Y:46STNg,Mb/1K3%74`e8LkBe)aj\J\_T'F;f>OmVQ^9nRf$;CYbL"r'f\Pre +l0[m6mk4"rnaZ5Em^^*I^:q@ihXU+'mI9W8oCMMBn*ff=qUN<m^r+1/_<UjfmHEm)nbr&inaGr3 +q"DA2`kK-u]smh-lf6O6in__oaj3h7Ti.?1bf@WE`6?<Rf47NiD09Z(2*Z=[Ht$$=O`+6PCJg=] +OD[lgGE@SJK7SD5N'<JpP*7tbP]]!O@;(giR#j:aMJQ_Ka8O'bb0.rMaMu3<`pq+Pb08)Nrl+rZ +r6#&\s2knnbK\/MaMb]8<_PqZ9RORno>h$Vbfn6-aSs0ZaSj9Oa9p&/aMPE';bg).iIC~> +&-(#2s8W)qq"t!grr;usr8IYTrri?!rqu]nrtX5Xo],uNs8W)srr)lps8Duss7lWkiVmouqu?Qn +rqcZmFaKC38WK+"P\4T[15h<Y4-,JhQSb%mQ((`=H^IZP?=fFgPXKbK@rIa#B4HW]77V6KLPCJ: +>+53as8;ons8W)QJ9Rf=M>.&LrVufmp[l=XH$+:UH?jd\G^4R_G'81LDerGf#R(;/!!rp%CiOT? +G]e.LrcnZpG\q+L(An.I#8'aOF`qnMG]e=OCN4<<EG]#*#RUG0@K[NYF*W(_P1fL*qu6BZ9Wk$_ +pAFadrr2rtq"j_eCN4B<EcF`<KS"Y<Od(JoIu6RQQBuYrH:='L7YH=nCQVD=R$NjtOHu,L<.%?( +Q'7G6H'O1]q=O^er;Zfps8W)trVZ3brVZ]pr;RN-s7lKkrr;fes8VinpZh2;pZCE6s3^fPs8N&u +m,RI"huA3~> +"nJLbchIA9rrW/urr2rSrXf,/s8W)rlBe9JYO2;frr;usrrW3"r;Q]tp]('crquf`raPp*s82ip +qZ$D5G`dhQNg>imB4c`NMis5bO-#Zo1maDkRoDY!QV_X,A<iIF7!O2gCQsul@"LR07;RO.Jq8SX +S+lgXqZ$Els8Lc%GbokFp&G$is8W)us4tK.`5BI._Z%A^^qn%*_8jC3a1RCoO-#HdP`N)f`Q#d6 +_o':0_SF(+_9/R=N0'<eOHGO5a25j8_ns(,`l#d3`50O5ObJmTQBmbpN5ifQ`501[s8N#tq!CPN +U/C^bq>^Hns8VllpK)$ECd)fUD+HjCJUKbEPCH5PL-CKXP]0cN6]upeJq$a6O%jkbP`InfQBZ;e +HqT`iPE]-oQ&/?5pAb0ks8VrorVZ]brr;rqru1n8rVZ]is7lQlr;HTjs8Vlnd'BmZZ)4f!r6bKM +s8Mri_P*ToU@j$~> +&&)ppOhANL`Q63Hbf7WA`q[XRb503Xb5'*Z`lS)#)TKXo9iPD/YK+o2`l,j<cd1"_bJq]>dDj8K +rlY8^s2G;_`l?*Bbfn6"aC<'2aj.rFcdQ'9P)`4rP`h8DAqDdrP*.nfOHu4iQ]m](<'GJj9Q+-E +PEqG&G^`t4OcNmSHSm`B@!I*LI!A)-dF?RdbeD*AfY_WBQ"asVccF/Kb0SVsf%oian*B<.nc&1\ +o5s9^na#f=m(C*K_Sj@,]\rAPnaQ/?na>u8m-jE4qprj)`5oj3_Sbd9md'*%naQGMoCMJEo(Vdm +[D9Dl_S3Rmp$qA2g<8sBc,I]@a#KcW376!ic-4DVai;TQ4'?67FDkt]2h$1#4,f5J89fbKLQ@KO +CK5RHPCQ)SJ5p?G:3i1kO?AVhP\jBI99kd+PZN'mKL45-c,[cDc,n2P`l5p:b08$"a<AdTdE9GE +_oU'Kcd0VW`66HTeB>eUa1f3=>>7Ub:M[JXo#UjRj2_SMbK@f4H;dO4A(lG~> +!rpd)rr3<&p\Xmdrr<#tr8IYTrri?!rr2iprr^jCp#l;R%K?>(rVcWbs8MZis8DuTrr<!_rr)lq +qbW6<ISH5pR#tH_6_BI*P<=ksM-G7bQ'IAn5(A8UIU[/XQ&.SWLJE8\N(JhWKlqTrKo(J=BQO"J +rr3r7s8VujiCTcB7JQf[q>L?jqtTg#LO"#bH$X`7G5lgeG6`P7E,/>i$3L,*&dh6JEHQAJG'8(P +H$=CVAiUS.qu@K;&PmIlH$FOYIW0.DD09r@?kWYS#6Ff(>m)$VFa87\N7IRurVuijQ@,EKQhpaX +r;ZQjs8)cL4`l$oF(RLeJV/nu:RH`*Lk9\GS!SRtKNquQ4&\16H]sj_P`h%jOc>`sM`jOjQ^<t^ +;3R,6jo,#Ts8;lqs8W)sr:0dbr;Zcrs8W$5qu?TmeR\FOqZ$His8W)^m-aK-h>dN&rX&W(s8VNF +lgEd4J,~> +"nALdde3P:s8W&trr<#QrXJo+pu.R9XL%KtrVlirrr39%oDed]rVufqqYpEms8N&so)ARe;uHOm +r:j$DP']fhPaIS7B1&;QQ'4=jSr$ZsNKochP<FAG6@)sSP*LkcL4W$CNeg,WIXuK[Kn4r/KkGK' +s8W&tq#C?ipYSK9WC?U[rVHNnqu6U3h8$qG`59@-_ns:,_SEt._9'j0NK0*^rK16BYf"H"_o9O2 +`5'7*^WXToPDtNaQ'.2hNOd*H`PfX0`Os+1_8a@5aGGS:PEV)lPDtO?_ns@/_"Ia,rVuiiO*IFD +R/?p\qu?Hjs8)cL4)f=\DIGJSJ2i.=Ceg=G7>-,.:7%/j8:k#QPrV]$8pQPc5*D"d4HYVjRYs<u +O-c2uGYsZe8`p'Ks8W&qrr)fos6oserVca7rr)]iq#C6hen"CJs8Vums7t<SZELI/X7Z;:rX&W( +r:\((TUheHJ,~> +&%6:iR(gGU`Q$'Jcc3rD`o4u@`lQ<HrlQ/!]U_Yn?"g[jbfduB_oL-Rc.^L\a3;QFaN4A's2b5[ +s2>/]aNDcPb4E\b`l5p@c,n&ObgeY(Q@_u%P*hA5B1&;QQ'4=jSr$ZsNKochP<4)>5Bg=HOHkYc +Lk\QIMhOKKH[p'WKReZ%HrX7rd*g:g`Q6$@e&j_:QRgS.`PKO;`QZ`eeD9Wan*B<.nc&/JoBkl5 +l1=]6]Y;1u`5KO.]AW8Ona?#=naPi2lg4K@fYtS=`5]X-^VT=2m-3a#nb_hJp[@eHqtn"5a2Gp5 +_SNjrAbGZ^leg"Whp'9da3&dHQ"#!ed`K\[`5U!@d^CK8F`qk<3.HC-M/#_LI7/X5CeL"SG=R9i +@?rrP3D4[]Qp6dsNBND`R$rpr7ZWn&Q$?/iO[$k4`Q6-=aj&&P`P][7bg"<%a<AdVdE9AC_8sjF +ccah_d&]FXe'QL]_8s*H?qs0d:L^]Kd`;d<c-4/8Hr<[4@FK`~> +!rpd)rr3<&q>:*frr<#tr8IYTs8Dp%r;ZfmfCSS!r;R3(r;?HfI$AaFrqQ<hiVmfps8DuprVuZb +5F@dAF-`)WOZbdmN0Tcr2O0DW7Zs1)PF@M!P\jlb?YYdl6$\-6:PP9,I"[90L5UhAK7Sb<o`+db +s7u]ls82_;Ju3CKp](9ks7lWkq"2FYH$+7SG]e%HEcZDLH$"%;<#GrEqu@!($qkGWF`i"UrceWi +F*(nS'a=I7BEf#DF*W(VFa&1UH?==VD-e+b%0-A/!!*'&).dr9GC5A"o_e[fs8D^dVlE/Sq>UEm +rquHbs7UbDEb/$+KSbD=H\#[DQo]tRHqT0XIT1fP6A.R9OckutOGlDoO[>%oQ'IDi-]S+i$Bd?6 +Q<KOQs7H9grVuosrVZ3brVZ]pr;RN*qNOQF@/']is8W#ss5rb<n`\R(s3U`NrVuogi9Tgjs*t~> +"mi.`fCo.@s8W&trr<#QrX8c)pXGS/X1J'*rVlcq#lXRGPB6Bpq"k!ir;QWomf$;frr;rsqu-Qh +oKAJ&=E'RkQB=<lQ].2sQ8Y"jK1;#lQ'7Ys6Bc+iK3N&QQpH"NHV/jS6?n$5JqA`/JU`*#3VEFN +qZ$?iqu?NiF+:')PP>+WrVuWjrtXA*_o'F1_o0O6`Pf[4`50F4^5[l-rK)JjOGpE^`Q,j7_SX41 +_SO=1VN-UqP*M>sOH,=2`PBF0_Sj@+a2>g9^qYtjR>d,nMj]`eMo<KJ`59=`s8Muss8;FZW2rAT +qZ$Tos8Dcks7UbBDI?'nK8>28H%07<Q8jPJH:`aPHr>BH5_;.1O-#QlNf#ugO$J\kQ'DH4N@0_b +PR*F2QBk^>s8V`jrW<,urr)larr)lsrr2p4p%X_@8mCugpAb0krSXugYck"$o)$f5#lX\paJ5H" +U$I4~> +%^BhaSA)kY`l?0Kcc3rDi5c#?aNDa+ar8:3O@rSXDS+0;bJq?6`QZe:G>ul8`kf^8`r*pU`WXB* +bfn6$aC<0-`lH?GbL+GY.#sU#GF"GYOZbdmN0Tcr2O0DW7Zs1)PF@LsO_.gJ=D*__6$n?9:5,!$ +GCP3sK8PD;J:)_ie()OXcbd]:b0JdOG+;lce'6(Sbe_EFdGNI0nF>u7mJQD[mI'E0nal1_\@oZV +_?[lj\_clHn*L&BGO+Yan+ZD(]t:nh_8="&^:ie'm-Es'o(DMDmdKrCo"r)_]thh)bJh31qY9^R +jNd/JbfS&NcIb+FShAF;cHaPO_nO+>dUGseA55"5KS"u*J7<>]3JW689SSg^<ITZgK0En/Od)5o +Ma!Vl6&h4rQ&gnPNW,.WOuJ\m:j1F<^;\(7ccX>J_o9X>bf]Ou+j/'SaMl'7`lQHPccOUW/hoN7 +f"fDK_7Q">:e+8X>I25qaT'BgbJgo?;G9bmb('~> +!rpd&rr3<$q"t!err<#tr8IYTs8Dp7r;Zfbh"'q&s8W)us8MroqY*17IRTb+s8(XP6i-i]rr;i% +@[!$CQB7DoMCaIJPF%Dh7$*KtO-PokR?<jpJ38=6<-jgg6\BiE5)=ndKntM9LP:26M1oPhoC`.U +qu6U5rVPGKW1cr5qZ$KnqYL6hq"2FYH$+7QF`RJ$$$165G\q(k&e>9F!##DB8o8QiFF&4XGBS+P +B/gJ4"p+Z&'*AIM:3(Q(F`MSJH?O^[Ci(6q#5S=/";tclG^"Ooeb&e:rr;rrV.?KXJGB!9s8Vrq +s7H?Q2eGlmJ:i9%Ko(M(6BsTVMMkhOQ%DDVH;8-NG`eDZQ^XC5I@Wi`Ng,fkR<Lr\OHu&%Lm*4+ +p%SLdrVuTks8N#rr:0dbr;ZcrrttV4pjm!`Q%2'lrV6EmrVuoWmd]o8df9?orWrK&s7PC:mH+@u~> +"llJUh=pjGrrrE#rr2rtg\qQ[rV4L*WiNo2s8;fp$iK`]N-dp]rr;lqs82fos6fmcs&AjprVlfl +Zs\uV5Eh1pOGYTCQ]mbuMF<Pf6][LrOdV?!21IT4Io(ETN'i5HLH1!;8:cGHI=cupKS4ndI.d76 +p&"dhrr)ZJ:Sj^YdJEn?s82WjrrLrkr5/NRrl,;a`5KX0_n(P^Oc]R)s,Ts;N3L4=a2>m4_SX4. +ahjU$Mia0gQ'.;mO,^`j^Vn(.`PKF+aMYa8N.dFZOcbfkP*1c^`59@._SGmFs82fqrVE:#WIoZp +r:p<lqu?[`p&F,2@n^'UJp`-%LP'P2P;m`AM-XPRJ3ng39P.(DO-c&qR$g?hRm`'mPa.B!G<qFS +QBFjrPC.BDpAb0ls7H9hrVu?cqu?]q%/KqtJRi#JI6.$#rVulr#j&:tZE^L&o)-l6#lX\qc(gr% +U#LS~> +%]O5WU;"L]`Q$'Hcc3rDi5c#?aNDa+ar8:5KhtlTF2#i>ai)$1_opLTHYP0Yd`fJF`r!jU`rF-[ +b4<V[`l5p8bKJ,Tc&t_VP=D"&P`UbRKpS!iObuPgO@,(oPED8qQns.JG^N;2P)Mb^J;QLFKLpcL +KRnl2I>E]2>\).!c+Ca3b/MKO_aC)d6+PRk_ofj6c-4SmeD9WlnGr%Vm4Ro"n+Q4^`Po^2`5KR0 +^:E1mnaGi5naGi5oDSF4\\>ho^q[Ru_nj%Mp$_>9nG`!%lLOK7s2;Fe`l#g9aMc'5_>O3*p#aQc +fZ;+Ua33(n=.XVMd`]SOa2,mFakb2i?;"LNI<U0oLkKh:Q90GQNacUfKggT=9kR:HOI28uR@6Ql +S4/6oPa.B!G<qFSQBFjrPB'aMaO//LdDO,J`P][7bfn6#aT'B`aN"4u)90SBa]h;-L2J$Vcc=8K +_Rl:A:e=J_;mO6faT'BgbJq&G;bKbk^46~> +!rpg'rr3<$q>:*frr<#tr8IYTs8W)tr;Zd4jP]Xro`+mhs8W)rr;-.ZQ'RXnme?b?r^["drVlis +rVfcVP'g;pQBdaiCmL0KPadRtO^;shQBdi#RX.q"=[%=0I$[0CK7eM6P;J5NJV8c4LkgD7F'/,2 +rql`os7uZn'kio7=.[_;qYpEms8;choYQB/F`V^'F8p@fF)c%o&-r@=q>_-87qup_Ed)\OHZF:G +4qIo)"TeT&(BXgH%SCY\FE)2>GBJ.QD/^R"!s/H&!rW+("W:lmG'81heF`_;rVlcqgKp2E;qLaB +r;Zflr;$0_OWfL5L4k><JVK)=F%AWBLOsnELkS>g3`nI[@[`LHQB%8t5ET,mQ][i)P`04@OdV;O +@#gC@m/?bYqYgHmrr;o\rXJi+oV>N5QB=i5q>^Egrr35^lgXH4dJs6prr;m%rVuooip6!os*t~> +"l#rNjS/TNrrrE#rVlish>[ER$2s_6TrY66qYg?irs8Ps8<T-u2X^G>s5s=\s8W$]rr;uqr)8N7 +G>s`kQ'O+?QB7DsRu9Uq?>l!mQ'd`'H;d+34ap%MPsTYHK6]P@15^X4JqSf3KmSPo=S;Rhrt+u) +rVL/iW)]G6s8)]ms8W#rs('s$_o'F0_o'F2`Pf[1_T&p2KSbeSP`q5kOHGU/`Q-$:`PTI/]>_a[ +I"$p4OckfeOcbZa]#VY*`Pfa5]u%\%bD1J&PDPQmNKoTgMi5Nj_8F.*pAb0jrVuipg0^2B:Y,:= +s$char;-,J+GPN&K8>;5Ko1V)7R2-NJ9j\>K1/0f<]Oo&R$!VtN0KSjO'$RlOe%f&N+SE=R?2Gs +Nfls"rqlZkrVuiqr;Z9crr2utrVm`6s7N-cG*.bSoDS^fq>^E\Z*^d?Y++tZdf0:Hs8</re>&Y* +U"Y"~> +%\RTNW4p3e`Q$'Hc,R`Bi5br=aSj6eaMko?<*<@N^])=e`504+bL8A-Obt@*`QH0=`l@/^s2KN+ +a3)ZPcIFdsML/KmQBRUgCmL0KPadRtO^;shQBdi#R!;Im<]b\&H^7'EKnXn:Ou&#JJ:iQ0LPC23 +E_tN>bf%K9`P9L?ges03<gL8QaMl*<bJqcRhpgKOnalPNo^VD;mIBcCs7!_?aNV`FaN;H?^qAXu +oCMJCo^lkjmf*7D]tMG)_nj($_oBU/kkXfBo_%tOn*ff:s2;IbaLo[@_T0R5^;9aEqY03tk1.Mn +ai;HP]MFT^7(:@``llKBbgG/'JfB;mJUW3'IY3H3E_/WFMM6OOM2"Pi3EJ7W@@<:DPpVKUQ9LC5 +G*e>^QB[>?Q][\tEaXob0Z_\aa26!Eb/hQ>_o9dBb4<XQ`Z<.?`l#^4cc_#/EKuD4b0/)N^W='` +>Ydma<`--<d`DI2#g:9"NDiD??F,.~> +!rpp*rr;ups83$!s8W)riVrlWs8N#qs8Nkhj72I2s8Drss8MroqY*CBPEnL#rUSnG!r`/trr-!V +6^=3;IZp"^Q]%&pPEqPpG?BndQ'IMuPaRe?<`b>D4&CBS;MTUMGXarKJ:WH,I>3E1Jq?O%antl2 +q>^Ens8037UlA^$g@5%?qu?]mqtTg#LO"%AErgE,rcnHc"DV'O!!Dur%LGX?Df]rCF`htRAj@.7 +r;[N4!!!*'":e%@E,ol7F*)eSB5]($rVup!r;^.)!!O6NEcuPNMU_:trVuoss5URlVjV/rr:]j\ +s82iV7mVu]I>N?*Jr=o*JUg<eEI*Y"G"7WUGA(K491+o2P+.`$RTO]>BUb*NQ&_H+QBR]%N^neh +G]N]Xs8;iqrVliplM_7jqY'_\KqFQr-hIB3qu-O"jlu7%mEtt6df0:E#lXf'ro383l2Q8~> +"P'HJm/$Y["oeK!rr<#Srr2p(r:mRnWiaPCrVZTn$2jNaOH,Ge63$WVs5j5]s8N&srr)fQ6'Ia/ +I$'YZQ]%&pPEqPpG?BndQ'IMuPaRe?<E>,@3DOsK;MTUMG""WEIXd$$H\I*,JUp="aSku8qZ$Kn +s7s!/TSQjmg$nq>r;Zfnrr3#T_#D7L_Bm+:_oBU+HussmM3*pbP*(liOKldEa2>m6_SjI+T7;!2 +K8YhRrK)>aNk39J`l5m7]uA+,b)(@jH]4,MOH5NhP)P=<_nj:/_"Rg.rVuoss5UUnUQf<grqZBg +s8;oW7R)]XI#*3*JVn]&J::!^Dg74oF@D3MF_5',8O8K*OI;;qQr\96BUb*NQ&_H+QBR]%N^neg +GB*QYs8;lqrVl]oo)AUfs8N#t)#a7*:4f$uPU>u$q>UEor:RS*YcY$qmebH3s8NB'rqG*@T:D\+ +J,~> +%[q-FYJA/ra2Z9Jc,R`Bi5kr<rQ5De`P-:m=B^<lrlGbl_8!n1dkcuKQSg/>]Z.q1`oY9g`l60D +bg"PG."mj[JX2ObQ]%&pPEqPpG?BndQ'IMuPaR_;;cJ]83_t0O</H$SG=+NCIt36(I"R!'It'mi +Ze3C>^;e(:daFR`SW$pl`6?BK_p$6@bgG=th=0t,qYKpWn*TT8rVuf2]#i+<bK.iJaMbs1iUla5 +=Ru.WpA=meiPrOI`l?!:_SX:3^q]11o_%qPq===Um/P&;^UV5(a2Z$7`PK4%qYU'^k02u<a2cBD +aO7o%;kf:FfZ_4LaO8Gma##T)H?b*eJ:*)nIXX>-85F8QO,%jIO#hGs@X1R4P*hB#P`qM:FC&XM +OI2;nSt)+1R$Nb&KofeBeB?+VbKJ&L`P]U4b0':r+i_F;`lQ6@_o'F5eN%uLR?Iutcbd`C`k/?_ +:.IlS:9D@\aT'BgbK%8Z;b9SfWIO~> +!rq!+rr3<%rVZTjrr<#tr8IYSrrE&tr;Zd$f&Z8aqu?Zprseu*r;67MHD-@]Ab,fti;RQmrVc`l +OEHYE7?j7&Q^3o#Q'[o"S8hVBBpXsGR$*_r:JZ>'NDVQf<bd,=LjCsbK7S]5J;8u1IZ824?UAGr +q#CBnq#0kdVQ3V"^sW2^qu?Hks82T`_M<DZF)uJLI"-QjF_+_d"9SW*q#Cj38oJcpFE_eHDe;'B +"8i-"!<W3",S!I_DfBW7GC"=FC)mN`!=&T)$NL53!!*6?@W?O4HApAFrVlfr;>'A<Dipi-Yl4Fu +r:]dN8:Q2AL5(/4ItNQ.Lk(23-=hUGA6qHH3gG_lPY"E#PF@]#SqrgqGZ'clPED;tNg#]mQBu)m +PE\`7q#:<kr;Zfqrr;o^rr;m*s5HP=R#R8KF85_6rr)ir#O(@@n*\X(s3glJrVQQmrrhBJna6@,~> +"OF$Eo(r7`rVcfshu3ZTrr2p(r:[.eWj("Lrr)cp#laW[G+OVQB(l*$q>UEonc&Ofrr#[jOE6G= +6^!guQ^3o#Q'[o"S8hVBBpXsGR$!Vo:/-"uMbc-^<+p]5L3YX]Jq/K1Itic-I>hu0?U8AqqZ$Tp +p\XS]U8L_h^X3#\qZ$BjrVnP,^r+(._ns4)^VIY%^:\f;I<:'nMiX$bP*2#jYf"E!_SsF1`5%sk +G^OdcL5_8oOsZ9NN4R'Ia2Z$6_7me0L3J#lKPuR.M3!p`PDtRB`5BR3_=dj.rr2ppo'YX[NhBmc +rqufpq"=&FJ:W6)L4>#0Jqnl3ItWD"A:JT0?U&p"P`1lj7n//oR$!T&L6soC;O!K2Od_JoPE_>u +QXaTiP"YQFrr;oorVl]oo)AUfrr2os#j"RFP`(TAEqfS5$i^2$p:df;Y-",UqpPHNs8Muqpt_a; +S>FP^~> +&!L^?[)0i$a2Z9Hbf.K@b2LGA`rF3\a;Mt1BinGALVM!SaiDB<`Q?LRF/P=c<n#I;r5ScXrQ>/] +s2OTMs2K?-aii#ZDI.mK7[KU+Q'R]!Q'[o"S8hVBBpXsGR#dDi9MTo!N)DQh=)3>ALNP:QJ:<') +I>!9!H&-,u="d7jbKS)La3rL'RANie]"?eG_TK[8bKSAkeD9WaoD&+Qna5`6pA"O#_8sF:aN2BD +b/qT=^#8JOnM9V,o_ACahnQnC_8=76`l>p5_nNeIp@7_Fp%eFVo_uV6`5K^!_Tfs9a1T'o\b5[g +oO-b+lI<hpai;HAbg9jTQV`gobLFqde'^$mH$k6tH@pNlJpW,sJq,(TI;`Ru3Hd9CNL#c!7tm+o +P*DMmR5fCgPa7MqRZibqPa.Q$@qCXP1"4CiaiMQGaMl'7`Q63ma<AR@_oBjAaMl-G\h/o*OHs]^ +bK\8R`Q5WpC/%8l;bX+*d`;d=aihf>R8cXI?(lc~> +!rq',rr2uprqlrsr;Zfrqr.PRrs\o(qu6WqfB2GbrVulrrseu*rVZK">E5>=P#B^*ir8uXC&@i- +rU`IAQt'p!Q'RZ!R$*o!Pad\6G!(_MQC3l)OH)=tPa%Mt6#f_RLOk)0.YiJ0KR\f2IuK)+4)\qU +@CK8*qYpEbV/`AbEPf`Fqu6Eks7uZkq"2FYH$+1NG'\ReI<]a;$NLA.!!!&t!"961F*N%UG]I\7 +4;@tq!!*-'rW!]8%o."]EcQ;JGBdRC#Qb#,!"/c,$OQe49*?&>EHQALNn!Xtr;QZns5<,+7BNOd +p%eLJQSF2EJ;Si/JV8]-K61U(7RT'p2*=<,@WFmsPEqE%MDAS(QBdf&Q]YWf7ZWmsRf8T^Q'do" +Q]aOmQ=$Nhqu6QorVlipli-q^%J][`Q]mo'>-\,'rVQEirs.cNo^hP#s8UOH!r`#prr3,\lgF-; +J,~> +#0Ng?p%n^erVm$"rVc`qhu4/brr<#tr:QtcWj::Rrr)iorsJV2=H&c3O]9g/rr)lnrr)lfrr<!u +qu$HmoL"h-@VM-lQB[W$P+%GrRuUNm4H,VmR?<r!NAs[rP*M+nDbbk;ItE5#L4+i/I><H(MhH:8 +DJO/t[8l_orVcA`D52St^r=e"rqQNnq#:9mFksjN_o0I0^qd\!_8Es2Fb+mdH?t7%O->flPE)f^ +_Sj:0`5]`fJTc3bJUDp!MN3aZP`q':a2>s:_8<n(_2rqdHZsXaI=@6?N0BKdNl]2W`P]Udrr;rs +rr)lTlg@->VGHm]qra;#KRSH.IY*-(Kn=n$F(/-<6Sgb]4[rF]F%86RP`_Ai0OBp,PEhAtO'Q<d +O-borrg".]R$Wo$P!4qk?D[]!rr<#srql`drr2rrrr<!8qtQG@OdVG;Z2aY"rqZTnoY@`>ZEBSS +qpPHNs8Murpu&!?R\IlR~> +%uk77[_^#&a2Z9Hbf.K@b2LGA`rF3\a;W%2B3J>AMS@6UbK7cDa2lPr:Q_K=N'=DhaSj-YaSj6a +aMu3<`pq,ua2Q-Dd`s4kN*^=gQBm\uR$*o!Pad\6G!(_MQC3l&NJf\jPEV;r6?5qVL4Xr(,_CB! +K78N*HA?uj2JQi9:n0>]c-b(iN+&<,DSa-&f?D%NbJM?EdGNI0nF?&@oC;58n+?MR\\$&*`PfR/ +_8j[;`4ih>naH#9oCI,"s5:c)]#;_._SaC4_nNq$]'&\Pmd9WAq#C02[CX;p^rO7*c,m]7]!Jp< +o^VG3e*PZ*`5]a9e@s5[1nBsoe'cdcHPpjDG_CBnItE3!IVrIh5s[4b0fVHp>AH>UOHkutM(rA$ +Q'@T"QB5Eb7ZWmsRf8ThQ'do"Q]aOiLe<ERaiM]Lb/hQ>_o9^>o#Muo_o'R<b/hTDcIdc1P+7b3 +O3tqga2>s6X_U^+9N"KU_:$C3bK7rL_4=Op6s5h+~> +!rq!4rr3<%rVZTjr;Zfrqr.PRrsA]%qu6Wqe*6;[rr;lps83?!A<iULPY'9tp](9mqrdtYs&&Ul +r;<X'OE+]uOHu5tQBRQ$Q'7Gr7q,egP*;2pQAoB2O-Z)rPs%0TI"R',LKoXlI>NZ2KSt;4=^#Wa +EI1)5MhV!$nOo[X7_cp[eboCGrr*Q1qtTg#LO"#bG'81ZG^OF6$Np>-"T\],"9Sc*!"BE8H[C9g +FE;1X(]jd@qu@Z;#6t5/!=VhGGB.qWG'[aV"onf-!!i`.!!*3$!"/i?@rH@3H]?PHrVc`p:]0M= +p5sR*Efg")2aE"HLOY&5Jq\r0H:UA"?"IVd7QlfpP`q5*2NO&gQ',30PF7VtQ^Eo"3]!1fP*qK! +Pa.E!Q][Sa9pUEEq"jmfr;HZ_rXf&.qZ$Elqu6G+Gaat[C$tourr;oqrsJ,Yn*oo#s8W)ts4.)K +rVca"r8R/6mJMJ~> +#/d4Bo)&Idr;Zfq!WN,VrW2usrr36#oV&:eY2f?SrX8c*pLBAOP`nbhq=jmg!W;uprr)lfrr<!t +qZ$QnXC%!.?CHtAQ^!f"PaRf#P`nUH?B^P9QBIMl@Pa".P`h4l3-fh%JVJn`LPL53K7\`5I=kX) +CNF?:5rX[Sq"F/KTr15k`5C+&rVlisrVca"h8$qG`5DSj&&$!"\p&IJI=-EhH[:7#OT(GBNi^+0 +^qde,`ghU#H%(*dI=$9iM3*j`PD?Ze_SO12]tq1EGBSI_FEr%RH\.*9PEh5hc,RK<_8,^Cs8N&u +rqPdBr/l-*DNOV&2El\@KRSW/4b89?IsFFG9j)"<DFH[JP*M8p:cFH!Q^*_83g5tqP*_PuPWCUg +PEM>sQB[YtR$Wr$J5)5YB)2<#s8;iprr<#frY,>0s8)cos8N&rBR#r2Nb\+_rVlfr%K65"aL/7U +Z('GBrr2rJrX/W(s8;cOV4O3N_gh~> +%u"M4ZG=N"a2Z3Eb/M9>b2LGA`rF3]a=>3I]4,&K>*cqHb0%rNb/hZKdS>diQ]XPFcbmuM`l#g; +b08)PaMu3<`q%2Kb/qKCbgD;<JSJG\P*VArQBRQ$Q'7Gr7q,egP*;2pPDWa&Ng5rrQ9I<TH[p^$ +JldY^IZ0#8JVJH"<)mXSDKIiaDIqMRfJo7m5J4kF^Y$a/`X9c.bgG=th=0t'n,DWMkOnQ>[Cj>p +_nj'u\%BMr_n`mlg$n7mm-XKAfu(2-^:_.r_na.0`kK$oZ/b<;iop%+s7k'L[_g&$ai;69`5]a3 +]XG0>oBc&.ea_D9`PkutaO8/KfQCSt@WpCq+YRt^IsQZuIt3)uG==_i=CPcV6TBs^O,Sre0o_B` +Q',30PF7VtQ^Eo"3]!1fP*qK!Pa.E!Q][Sa99+$bdE';O`lcBB`P][9b4<Uf`l#g7bf7oLdFV<9 +Q^!>3f%&$d`r=$f_6S/]7nHWPQ+k>\ajnH>a3)TG`LTmq7TPIu~> +&-(GCs8W&rr;?Hhr;Zfrqr.PRrsA]#q>UEoe*65Vrr;lps83E+RmWC*SV]o5s7ZKhs8Vu\r_rjq +s7lWhJT.&9Od)&qPa7W#QB7>tQB=-bOIDK!R?O#,/7k33QC*Rg><Gi=J:rK.J:if.J:rW(Kj@Mp +G&MGFF(oYP<OR@1Vf@m?aMcX,rVulr'*%k(oYQB/F`hqRI!'OJ<=]<8r;Zg!rWE3%r;\;V9R:u8 +F`VC['F"[E!WW3$!WrQ.!s/H&'Mr[oJo5jRE%1hi!rr?*"U=f'$N^iJDKU>TNR[RurVc^ilL+35 +;P^B^7k0@FLPUbAJr##)J5/7=FEVPHDf9VXOI),qP_plKPa7Q"LamY4Q'df#QBtiBHBst_R?Nl% +P*M>sQ],fBN)0BOrVl`pmJ[k!s8Drms7uEM7@]a0QS\72rr;uqr;Q^'mcs92o%F'Crr2rJrX/W( +rr<#tipQ='rI=~> +#/Ht@o_\[er;Zfq!WN,VrW2usrr39#nt<"cYN>QXrr*W1rr2rtrgZ<:P+.8!q>^0gqu?]or;QZp +o);\irVuZmq1<OR233oaQB[]$Q'RMrQ^3an2NXAnPF7W$R4Dg6OHc&f1g)n<Kn"`*KmnT0H$t9s +H\>X"E-6#8EGoH,1/kT.K;<CI`lH$Jr;HWps8Dor%c+q<_o0I1`PTU5[!?tFrdFcn'R+qWMij6f +N2OJ'_nF%1S:,O'I=D0As*&p<Iu'2NOcd2j`QYp5^qkeCH@0sbIX$$[H@CO,PEM&fbf%B<^;'=> +s8N&urqbpOq".FVVa<j$LO=`-KSG&5JU2f?3FHcFC34?2E'',JPEqJl.?0RXPa7+TG`n>ZPa%K# +>X<\%R?O&&Pa@PuQBRYoDDd;Gr;Z`ps8Drrs8VQe&,cJ+rqufnpuFf3Q]mdpp&=sirser)q9-4P +Yd'YHq>UBnec#pSs8Mroih`6:T>5s~> +%t\81Zbji)`l?*Db/M9>b2LGA`rF3]a=>3I\m\lI>*ltIb0%rQbf\#LdX!U(Odq(df@Imd_T0m< +b08)Pb/VE>`q%2KaiDZCda)E-O>2i^PEqArQBdbtPa@\u3&ZkeQBR`#Q'Wq/Q][W&N&Op#:k<tC +I"Qp%OFW">KR&)M95JZgFE_\4@NRe-D0MObN5<EC^"CO-`\GNUbgG=th=0t'mHa3,o_7^[]u%e1 +`koF$[^j/i`50'nf(85!mIg5&^V%4q^:_1trl"iSIDEM*^#nYIn)!^3s3.^]_847>bK@lG`Pom: +]XbKEoC2A4f(7\?`5BL8f>u+YbVPNX1GThpGCY<uJpi5uEdC87A92m/F_kl32iElZOH5,AMj0Nl +QA@#8P*ME!Pa7Y@6$eibPF7W!Q]dW"PF%5E1k%:4e&TPQb/hU%`<"'&n]2B^aN)B@cH=MT1maJf +L`+LabfIg'a:,nlG>h%);bN4daN2KRa9ou0b/_Pr<(08ULO]~> +&-(JEs8W&rrquZjr;Zfrqr.PRrsA]#q>UEoe*6/Srr;io%K,ttGab"_R96cjrVZQls69M]s8Dip +q"n3@13/GCRZEStQ'.SuQBmbf5$sP9P`h>rQ#eUAQBI]$S2#SLFF&IlK8k_<KSGPFL5'M4CiXZ< +G'7hHF`hUs;PTpcg;1V?eboCGrr*K/qtTg#LO"#bG'e1HBMJp;q#CEu!rN$E$VkYjEcQ"N%0Q_: +!rr<("U559!!!*&!<Yf2HZ+=JA/,UY!!3#u!!2or$NgoID0^JVO4<e"rVc^XiSsn5Ui!%sD0pnn +KS,&:JTbKs4AS"THZF(MGB.\0?B:MCPESk*Q'mf#Q!HG:Q&q,oQ]m1XBoeLBQ2[-MPQ-mTQ^3Ve +7cj1?qY1!fs6]e#s8N&uq>L3gNbaiCQ:P0Or;Q`rqu$Hn$Ld<MnaYB6s8N#teG]LKrr2p#jR;U* +r."~> +#JHk?pAP$irr)j!r;HWphu3ZTrr2p)qXC&UXg70erVlfqrVuj(s8)Y;R?`o$<O);tr;Q`orr)le +rr;mps8)XrGqj<"R$s(uQ^*`&Od;;tK0EY,OHbooPE^)?Od;/uPFO@YL3%WiKn"r4H[^L%Kn=nj +6"t4VD/jQ1DfKf792D=V<SG:)^X`8\rr<#srVloS_#D4V^r=+0agZVArH\Eh)LHdUH%(L/Pa.61 +]u[n*bE[ErGC+^_H@:$]rci..Ng,]^[`?>!cGdYHH[:$dH?sp^GC+X^Its,KP`3`"_Sa%#oD\dh +s8W)piTU=?UhQPfD0gehIt!$)IWSsj3__JEFDGZ6F)Gi#?&k;@PESk*Q'mf#Q!HG:Q&q,oQ]m1X +BoeLBQ2[-MPQ-mZQ^3Va6fmq>rV-<irVlfrs6fjrrVuoqs8;eSBTJ7>86kofrr<!-rVQH<[^*-B +Ra1a.rr:OJs8NB(rVl#YSt)CbJ,~> +%t7o+[):#+aMu<Db/M9>b2LGA`rF3]a:$#*\R/WG>FE7Mb0'_.)pHCE`R%_@N/a3"Q-R[t_oKd; +b0%rNb/VE>`q%2KbJqHBaj`Oi/8pZ>RZ3GrQ'.SuQBmbf5$sP9P`h>rP&;h3QB[u.ShkqNDfg;U +I#*T0Ll.CSK7@DoA8?.%GBe4PDJ<ND8=Q#Ad'pWp^"CO-`^RqibgG=th=0t)n+?/GrpdV6`5g!A +a2G^*^:h>#aiVK8j7WHEr;Y$Q^rFI7^VIk1b0J2M`Q,s4\EN_Xk54uS^rFF9rlS9ec-FSU`l#d7 +_niq[o_%n=f_++E`5BR<f>"iEbCX&p2Igl[LkC;2JTYX)4tT&RCO:)?F`M>6=]pWJR$3e6OHl5s +Q'GW9QBdPoQC!ej056K3PEl-6s-*JJ&snoDKfmW*eAf>Gb0%fE`Q$!AnAlfoaiVNHd+WbPNfAfH +0u_AZ`l?*Bb/:Z9<_Gt[8rLF)aN;uR!QN7\ap"hH77L4*J,~> +&-(MFs8W&rrr2fjr;Zfrqr.PRrsA]#q#(0ldd$)Qrr;fn&,Q*u4B[o9KOXiYrVulmrTX;[s8N&r +s7tnGM3=0iNLZB!QB@Q#Q]d\M/!5mYQ]dZ%PVI*GP*MGuNIR%ZO&S)#K7eu8LkgS4JTF@c8N0CX +Ec6,EF`_Y"Oel."g;D"SeboCGrr*Q1qtTg#LO"#bG'%b;7Ks)"!!*!!rVus%!W2p)$:/TIDe(j< +!s8T&!!EB*"pY5-!"9B(DKKo4?P!2C!rrE$!<3)s!"0&F@;^F:IZN"MrVc`p5QC':nbDoN-\$Q! +It`f6Kml6]O37+Q5C.0mEHl8B9j^/AQ&grmR[9;+PE^um/:a4UQC*quQUOo:QC!f$PQ$jIQN*3T +Q^)-BpA4gdr;Z0`('"11s82Zlp/$j9Dts&$rqucqs82`nrsJ;\nac8-qZ$Qos3prIrVlg"jmV^* +rI=~> +#J$P=q#:<lrVccrr;lothu3ZTrr2p'qXBrSYI3cnrVlfrrVld+qYR-O<frVt@/0d"s8Vrlrr<#f +r]pD]r;ZZY6AU_hQ&V<$P*V5tQC!c$C+GF-QC!c#R$04AR?Ei&Oc=jPS;pQ.4+Mj7K7ec(I"$$( +=@Y5AASu8]E"Hq]OJGsugV_(SeboCFs8W&rrrLrkrkncN#KOigG^Y!cH2`&;H@(!`GC"aoNKK3r +_nX1,SU,F*H?sgZH$a[WGBS.WKoM1Z[)Kht^qtA6H[L*eH?Xj`H@1'bI"I3:P)@8o`4s""o`"mi +s8W)rlh(&Oq*ZHTI"ZouL4Fi&5#%*Zo%lHNB67s2BQHdN5_kS`NgH0#Q'[]!MjQ&GS!K?JR$E`! +79,J9Q]m`!rg!MLs-4(\P@9IGr;ZZorVc`ps8VQe&HDS+s8MrrohUR1D"mZ"s8W)ts8NQ+qtnpQ +Za$a(aSGi7s4.,Ks8W$%s6lnXS=R3@~> +&:%T'[DU5/a2Z-AaMYp<bf\qds2P)]/',`M_ms&Z>@!o<bf\)Pc-=JRaMc2J*(,OIHqDlBbf[o? +`5p*Fbf\#H`pq,JbK7iFd+$H$L6J!iMjg#rQB@Q#Q]d\M/!5mYQ]dZ#OXt=;Pa@r,O+31VM+fTX +GBnamM26e4H"T024"3L(D/OZGFDkn_N1`tYc*tR*^"CO-`Ycb<bgG=th=0t+o(N(^m'jmRaND`L +aN)3s_0El;aN)3Us82iqgUb#=bK.Q9`5fmAc-+)D`Pod<lhg>Go)$#.bKJ#Pb/_oQbKS&H_Sj@2 +_nQ!@q=Eh&oA%O-_oBpR`PB=3eN"gtGD1R%N.HFs/3%dWgW;*hBln'-@;8).3.d6POI`#3Q'[]! +MjQ&GS!K?JR$E`!79,J9Q]m`!rg!MLs-3tYQ<njcbKRrMb0%g)`W=0'n]2s#`l?*?b1G6.KT0L$ +d`BMPb/VHBb07i5JlYQ::eHASaN2KRaT'6ca3)Z5=%,STH@P~> +&-(MGs8Muqrr2fjr;Zfrqr.PRrsA]"q#(0le*H5Rrr2utrqufqrVm?#b_Is=QqcZ8s8Moqqs")/ +s8Dutp\B_ZOHGfqRZ<Q#R$<f#PEMA'9TGO,QB[i#EA`oEQ^*`#R[F)=-BMkK76aY!LObABHW0V8 +p\pRF<b-MtE,]SrVho?_i6&gMeboCGrr*i9qtTg#LO"#bH?O=%#m^M4":#2<#6Y&."pFi(#Rj7B +An!S($3pD."T\Z)!s/N%!"K,88SN3e>nI>Q!!!'#!WE'%!WrK+!r`0-#8UikI!1(#eFWY;rVfRL +m.()H3GF/'K8P>2L-SK&o^_kVs6DXoFE:eX8"[)a?BUeGO-#cpP*VK$Q>/=7R?`l!QBcbIN0fct +PEh>uQB[]#PEh\s8+uoYs8)Wmn,=(%rVulqrV=9+R4aHks8Vomrr<#qqu6U&p#tr;o&99Arr2rH +rWrK%s8V3Lna$+'~> +#IU;=q>UEmrVccrr;lothu3ZTrr2p(qX9fQYdj<%rVlfrs8N&ss8NT&c%[m5P=XX(s8Mrrr;Z]o +s8VWg6N-f]s7uPLAr_t<R$s%sR@'5&QBRK#78/`0QBmc(O`3%;PF%PsQC=2*Q'@AA?U?kLH\-U# +LNl\fqt9lR4B,a3rb`9^=f.!noARm,^sr;\rr<#srVloS_#;/O_T8j&I<BaXG'.qNG^4R\H$Oad +KoD"obJ_8dF*W(XH$aseI=-9dH@($eIYNf;]#);,^3b-UEcubNG(+a^G^4OXG^FmnL5!O^`P9:) +o`+sjs8N!pqV^uAs78*ZJ;Ac4Jp`/69CMNEq"jpO13d\U>XClNZ(tWfR[8tmR?`r$R$O%Q2Mmie +OHl,sH7Y#APa[f$PF%T"QBdZ!Ru0]0s8N&prVc']!WW&qrsJS;9pI2bo_ngds8N#trseo&qUr<` +ZETn;q>UBnec,UK#lXc&oVe@PS@="~> +&9M/u[)1&-a2Z-AaMYp<bf\qds2P)]%EQQ/_7<fX>@=;Fc,e!'aqrCI`1pueMN'L2cI0kPaM>g: +b08#L`l@Pi;Td))b/i.V>`Y/:R$`hpR[B>'QBRK#78/`0QBmc(O)?S2PaRl(S",k/OGnos;DB[f +Edi4aHtPRqhq[=F.n<cgF`VJ5<MY:ZjjCcP\A-\>rl,Vlair/ieD9WaoD8Idm((!H`5fsua8X$Y +a2\(rs2P-+rr6`e[D'Q!`lH->a2c0@aN2B=^Vn.-o)/@aosqc[_SX=/`QQ<?_Sa7+^:q4m]=e%; +qXX"(n_)%'`lQBR[_9N(d4&OQKS5>?It'43dEp(beD&7oDIR$I0//9UPu*@*RZiu*Q'.H#QBib1 +2MmieOHl,sH7Y#APa[f$PF%T"QBdZ#TSPGTcH")Gb0%g)`W=0'o#N*!ccF/Haj/A24Gb,&e^Vm\ +aN2?>aND`H[t[mV8l&',]u\::e]@d1#fk*6\l_Bk:Nh6~> +&,tPKs8Diprr2fjr;Zfrqr.PRrsA]"q#(0ldHp)Rrr2utrqufqs8NW,qZ$?^k4G$YOSf"Vqu?]\ +r_rjqpA+ab9obO.QBRH'O-YusPEh;qO=#jLPEM/oQ]EhGOHu9"OI;2pQ^O&&7G7J/X\M)nF+[0[ +s7H<`nGdtoAp/066)12P2Xf\@_o^I,rVulr?2sfsoYQB/F`V_94WG(7%g<:L%LrpT#6kMB#mLJ6 +#7s72:b<4e$jd+>"pkG;#RL_>"9nr.!=BQ2Ec4_g%L<:J%LNOR$NgV>#R_.R$O-tN+C]M?F+0+u +oDSXdr_;VAr;5bCL4P/.J;K+YkO\KKs8Dujs&@]A6Z'g8r:TJISVNf&R$<u&PaIi#P;@`PP`_9# +P*&7lOcu&rR$3l%P*M>uQ&q87]`7a'qZ$!_s8N`-r;Z8-Jp(;lqYpNpr;Q`rqtpBm$M`fRoCCu5 +s8N#tdJj1G"QSq>lhc2~> +#IC/=qu-QnrVccrr;lothu3ZTrr2p(qX'TNYe'W-rr2oss8N&ss7m'&p[RA7P\?$Nr;Z]os82cq +s7-(hrVQ?es85ZPQC4#%Oe@\uPF.Q!P*D%TMNj<fP`qGp/9Qu;R$Nf$OHc-$PEeMfp[kO\4CiD^ +9D8DYs7Pm\IkkJQDf7n8U/3c;jhSaSeGT:Es8W&rrup46_o'F/ZBfrgEI`4UF`__JG'A1WH?ja[ +I>*NU^9NiFrcK<-GC+dbG^=^_G^4X_GC+q!Yf+8TG^+@OG^Xm\H@'f5GlMpsGBe^mLqU^D^Vdk[ +s8W&sr_NFVo)J^R4+i'=H@CX*9]kpAs8W&to)2>669f;*p&+OO7@T%%PEhB"Pa%Q&OcqSOP*D)p +RZ`e'MNO*fQC*l&Q'.DuQ'I>m=hXk3r;Zcpm/@Ils8Vrqs6t&YF'&,2rVccrrr<!-qtg0G[Bd0D +TY:1#rr:RKrr;us"o"seSt*6>~> +&9(ot[DC)0a2Z-?`kfR8bf\qds2GPkaN2B?_73ZV>@OSOcH-"))p$1Gbf7QFa32TcM-+iNd*';I +_SsU=bf\)L`pq,JbfIN;dapO9R%Kh2O.2/pPF.Q!P*D%TMNj<fP`qGn.rp]9R[B>/P*2#nM2=./ +gXVBC.oT_g/^i=qf?_[u@j#-$FE0R:TM-ind'17%^Y$a/`_ORrbgG=th=0t+q!6AA^U;(o^:q7o +^;%M#_SX4*]tV;!iq_f\ZF7<W^:_8!^q[\$]t:qk]!f8d^uYFehQaN!]"l1q\\Q+p]"#8^]4JO_ +[_05eo_J4NlI51O`lH0Cbg*i2cI9rfI!^QqJVo1LdaQUjdE0eTfJL>l,#+i]g=Oh/Ne*aiS<fP, +PaIi#P;@`PP`_9#P*&7lOcu&rR$3l%P*M>uQ^!_)S(,?nbf\/PrlG,^o#N*!bKS&C`mW"1Cgo`a +dEg%YaMu3<aNDcI[Ye*Y92A9+]u\::f#[m2$,t!.cG!CL85F;W~> +&,tPLs8;`ns8Mokr;Zfrqr.PRrsA]"q#:<nd-TrPrr2utrqufqrVm?+q>^AW?'e7Zrr;uns69O] +s%iHc@$6b<PED>uPa@N!Q'[c%M+N\sPae#&PF=\-PF%Q$PEqT(Ng-,j;tp%dqXWNtA,,]pp](*h +s7uWAIW9=>Br6DYEq\8-bJDa,rVulr?2sfsoYQB/F`V[m0fUU8/ho+<2)I'C/hSY,0JG+1.PO2) +6p!Y#:-_366UO(%69m[s4?Ykk5=/"FG&g>M6V:$G5=&(=6VBa46q9mE8OPKu5\>+\EHmGloDSXe +rY,=pjmW59>_J#aLkUG/E;BP1s7cNm.Ja#<mecqZs7cKkTjsRTQ'IQ"R$*_rS!&;cQ^X;,P`hDr +QBdetQBda7Pl-gOQ$@KArr;uns7-('r;Zfnr;Z4VO#>8_s8;lor;Q`rqtpBm$N&rSoCD,7s8N#t +eGfLJ#QF]%ipZC&qg\~> +#I'r;qu-QnrVc`urVZZphu3ZTrr2p(q<X?JZ+Tr3rVlcq&cVb,rr;rms7qg]O[o'As8Vuqs6KXa +rVlgpqk[_`PEM)kS!9)$OdD?"Q'R7uNLZ6&Q]dQ$3h)7sQ'[Z"R$j##Sqp8<q#C6^hLoD6pAb!h +rVuops3l@4DImLXJ5^RchT<pUeGT:Es8W&rrsml#_o'F4Q&(`bQBdi&Q2[$IPn9(@P)kTaR$sP] +URe*QWgoj`U&UZ$U8+BTU7n3MSY)pe^qQ\GUSt&eStW9aTW.pg#c4;jUSOQWTYCEB"iJ1Ms8W&s +rY,7qmJ$XG=b2K\LkUD-DYa>/s7cNm%eotom/$VUs7uZnU10ONrf\.bR$*_rS!&;cQ^X;,P`hDr +QBdetQBda7Pl6pJPQ,h/o)Jahrr)iqs8DKe,PqH?qu?]b7u]=Kr;HKiqZ$Tprr<#qqYT9ZZF$m2 +](l:(s472Jrs/Q$q59mWS@*k~> +&8kcs[):)0aMu6@`kfR8bf\qds2GPkaN2B?_6m<O>@X_Rc,fn')90hDcd'kW`R`Ue8V&\Je'>qF +_SsO;bfn5uaAU70aNVeW:Q1[0Q][\sPEq>tQ'[c%M+N\sPae#&PF+@tP*VH&Q^F5.MN*dF6Jp/< +dEK@:6.3fu_90^=cH=\EDes?(AtaZJB'.4FaLo:?bPoLfa2uQQhpgKOnaZ:k^!+OEd*g4`bg+Vb +f\"Tue'ZFabKA-$dEL+qleUCOhV[/Fhqlu8e(*%&gYCN=naG&ah<!_WeC3@4h<*PLi8WbVio/SB +e*utun)MaXd_s9+bWiMB`8#f6G_:<uKn";Rh:flf\&62,`mr>Obfe/UaO8^n9oY'sQBdf(P*M,u +P(8a_R[BA)P*hAtQ'[PtQ'M?5rg!qZS<RSb_og'Ab08$-aT'ERa<\pMcH!c@d*!q_*3If?b0.iH +`l5p<b0@r8N`A_F9hfZAaN2KSaSs0bai_iC=%#YVE.@~> +&,bDKs8;fps8Mrlr;Zfrr8IYSrsA]#q>UEocg0cNrr2utrqufqrr3K's8W#i?qQP:]_qX+r;Z![ +;Z$Lcqbr?8Pa7Z(Occ6!Q'@JtQBm_sQB@VqPa[euR?!l%Pa@PuQ'.Z"O^#Nqs8D]lqYBp]s7H?h +rVcKhqSb(*D*P,!4Dn8Igr7+JeboCGrr-4'qtTg#LO"#`Dfoo.DJ3NlBkqO#BkV'hAnc.#Deiru +<*a-PA8lI*Ec?#;E--/8DJj6(CiFE3E+sTED/40-Ec?)ADK'`9C2.U)EH-#:CM73rF)uGKN7@It +qu6R,qs3JAqOCT?JV8Z+K7uYcr;6Kn3r]'WrVuosqZ$Hmr;-6;:7RQ6R#mMsQ^3i$R#mVuOdD?" +Q'IN#P*V>tQ]mZ$Q^!`"R?F"7eGK1Cq>]s`$ig/(r;-+XHY<?Rrr2p$r;Q`rr;?Qo$N&uUoC;&4 +s8N#teGfLJ#QFZ$ipZC%qLA~> +#I1#=qYU<mrr)lsr;loth>[ER$2NnNXKT;7r;HWnrt58/rVuTks8;Iq8<,:4qtg?krr;<`2#[:N +p&8!LP`qB!R?<W%Od2/pQ'R`"Od;,uNKflqOdM,uOHc)pQ'IN&OHE_[qZ$Tks82fl!WVrnrttY5 +r5UC*Cd"ep3cA/LhoERNeGT:Es8Muqrt!r$_o'F,`kfI7aMZ!8_nuDjr59#\_8447W3F1_^rO:, +r5()+`P0:2a2Q!9_S+(*_o9I0ahYa.a2l-7`5'=2`P]O-_8FL=]u%\*a2Pphs8W&s&c(b]s7r*^ +K7S`/J:`J@pA=des#U/Us82fqrqcZms8W#odnQ6oPF.GqQ'[f#QC*c"P`_;tQ^*i!R?El#Q'[]! +R$X&%Q'RN!:Y#FArr)cqrr2lqrW<-!s7cL;r;Z`qs8;R\G\-dIr;HTns8W)ss8MrorT(>k['6:7 +q#:9mf)GXJ#QFYsVk9QM["&~> +%;f<p[DL,1aMu3?`l5prb2(/=`[8O/<F&^<Yf4i-`l5p:b0A2W_oL'Fb!7\0)Of!lbJD-9`lQ<H +b4!Dia2H<Adl2T6R%'M3O,oipQ'@JtQBm_sQB@VqPa[euQA_;tQC3u(Q]deqKgqigd*'JZcd'_U +c+V06`5KI5bG#qeC-J\n4)%?&bdtR'^XgTJ`lQ3Bb0f%pg[Ob'l1+62s82K^oC;ABp\Omg0`(VD +rr)]hp=J*dp$_hUq"=4PqY^Bno^hVBme$DVq"<h>o^MJPp\FFRo^;;Jq"Xj_B_M5sqZ$K`p@RhB +hot<4`lZHIb/Up$ce=">GBn^mJq/8$eBPnK^V@S#bKA)Rb/DB=b0%uYZoaG5QC*btPF%T!QC*c$ +P`_;tQ^*i!R?El#Q'[]!R$X&%Q_0J"1TS^?aND`Lb/jS)rl>/\aN"%ss2lS.b/D9=bKqbN:>!_4 +b0A,N`l5s?bfn&;PZ(.G8ka3;aN2KSaSs0ba3)Q?=\).YDh%~> +"Sgp@s8W)r!<2uq!WN,Vrr<!*rquZkrr<#EmH3I.s7uZorsAT%rquGOC-M4brVlisp&=^`s8N5u +s5cS2r075Hs-Do7$($dAQWD#rrVZTarY"cpCK,n\BOu*^K%n>a_UJG]s8N!Ms82T`_M<DZFa87T +EGTE,DfTuDG&qY@DKKf>FDl88AScO.DK'W?G^+CQEcQ7#Fq/Y4CN=?1DDPgCF*2YHFT-M3G'.kK +F)cAHGB.eMCi<<FC2\05I#Z\JrVQNjrqu$Lq"mNKKnk3XKaNB%oD\Rcs7u]or;?TorWrK!s7^&T +Q("'=Plm85OI,p1s-<VMn<F-<RWNiNr;Qp!rVQQnnGXR1qZ$KioLNbPrqHHkrr;uss8W)rr;Zfo +lgsc@kjAEKrr)orfDbgMs8N&u"R#.>m.Gl~> +"L+]>q#1'hgA_'N#Q!hQXKB;4r:p9krsJ]'rql;KB05\^rr2rtrW)usrW)uqrq69oqZ#\FPl-jI +Q2d*;Q2d*IPm<Y;QBP:bp&FR]')hAnBiK\ZAn,^WKA4Jd`7Fkbrr)orrVloT_#D7O_B-Y8aN2EA +`5BI/_o9X8aMPp7^<+L8^;n76a2>g1_u@Ri_ns7,_oK^7bK%B:R)d+Z_8F.._8=(g_uIRf`5oa1 +_8aO2d^Pg[`QQ0;_=dj.rVlg7qWIJIpd.9!L44`+J:9uZrqcZpq>^Bhrr2oq!<2ut%fQG%A:K`/ +Q^*i%QBRK"l'2F:OIC?=qY^?srr)`ms8Mfnqu.3+s82irr:NQmK)YWHrr)lrrr2j)rr<#rjL)4t +Z(e`&rVlcrrRh,LrrE&trrr/!St;RYJ,~> +$"R7h\]2e7aMu3MaT'6c_m`ZK<,](]bP]H\b5]Qj_oU'Hb&LH3cHF<.`rF!]`lQ<FaN!norlPSf +`5TaIa"`O:Q'M<3s-N5?".,FDQ2ZsRR?a8)8#FDQbfp(/prFf)bg4Ql>tfdFCM%<OFj\">\%C57 +`lQ6Aai`#ddbF9]na5Z0n+$8Gs7@'"o^qSFq=jpeo^MSEnac8Fo'Pc5pAXmto^D21kk4]Eqnhjn +nb)nU3V;q5nalDLqY9pWmcs60m/6"qo(M\=gs#'8aihiH`lGO'bge-rGCb7#M1g(+c-4#DahuEG +a2l@$ar8@@`Q#pHd7eVCS!T>&OctlhR$X/-Q^*i"POatSQ^X)#@9V+,cHFGTb/q]GbfIfD`Q#mq +`rF-[as5-Qa2u3>`lcOV>^"c=bf.WEaN2BBc-=>I]U2\f6qL!f]uU,n!6<a5$c^6+`l?-2@nTBf +COc~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprr^U9l/VaBq>Ld%rVulrr0:qYnbW4`rr<#krqZHuqu$Km +qXfq`P*5d.s-<VMl'2RAQ'R,7rr2fmr:Bn$r:riq9Vn1IF)X59fY>DBe,91Err+8EqtTg#LO"#b +H$XXTEGoi;G'J:XG]e%IF*)VLDeEH+Ao_j1Fa!b1(O:1FF*2_QH$4CNC2[ND,$Sr.H?aLSGlE!e +Ft[u[Jp;Q[Dg"l'2g'(TFb5\)oDSO_r;Q``k5Y2B7=T`GLjt567JZu`qu?ZprVl]os8EB'qtL-K +8"5X*P*Q$4!L&ZEPlI$KQLU4JOIVDr9)&&Vqu$Elrr2uqnc&Rg&,ZD(r:NQuJbf6Dr;Zfrrr2p+ +r;6Elr9O"Jo]YW@rVlcrrR_&Jrs/Q's5rY8m.Gl~> +"gOo@p\k*grrN-!hu<ZS!<2ut$3'efQ*%4(p\b!crr<!+rr;urqit_Tnbi@crVcfsrVcfsqu6<h +#6+PoO_L#DrKdJKs-2u;!0mJJs-<qWPECE)rr2iqrr2lrq>M$(q*o$kVO9kkD)q=B^rF@ErVc`p +!<)lr!T(Wk__]0G`5Ta:`l5j4_84"+`Po^1`Q#d2`/;+C`5]g7_SO+,_o0I0_84")a2Ps>^RgM' +`5;Mi!6"iQ!5nfQ'Z7c*]ZA"+caf7&b/hH;`PM6Is8N#t(B*R_s7PS@I<pj+I"Qu;q>^Kms8N#r +rr2oq!<2ut%fZ;(i'j#oPEM2tR$a/&l'2X;S<&n,q"OX^r;HWorrN#rq>^6h%/^)(s7SlrIJX!D +rVulrs8<E)rr<#sjL)4sZ(e`&rVlcrrRCiHrrr/"St;RYJ,~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KBh`l#;e=&a1G`QH9CrQ>/])TKh:air#UF&jd8b/_NCaMu3= +aNDZH`lQ<FrQ"uYrQ+u\&B;T(bL(]BNffNhOcbimQ^@6-s-FRjQ^*bsOdVT'ISehB_TL*FaMu3< +`lQ6Dr6-G2eM15oTq4kqBIr>n]"YP^e]YtTb/_WHceQt'nFQ2;lg*s*rpT^R.IZTgoD/1Tp:KY] +nF,o9o'bl-mIU&Hp@I\8m-=!7o?k/:p%J.Pnac5LmksY,p@RtFo]bo3lhf_YaoD/'l/9eNfuqR] +`Q$-6[ardL/T>ilNeN@</CVtd_og3IbK@oGrlP8_`r<pla4A0ePE:ogPEM,pP`hB$R?s2(PEYR& +&XS`RMM<n=ccjMNa2lEIai2?s`r='Zaq2e>aMu3A`QHCUAouJBaMc4!a:?A=c,df:RT2^A84m^3 +a8X-[a4JB5a2S%t"h/#98PNuN~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprr^U9lK%pDqYgKnrr3H,s8S3q5O\LJrr;rss7-*cr!3&t +qt<CDQBhE5s-<VMk`l@=Q:Ka.p]'d_'DhYp9TQ)QBQ/&Nmc2=#`RFb`s8N!+s82T`_M<DZF`r"Q +FoHFtF`qqQG]n7QG'ACUCM?c^*F<])FEVm-H3/A:FoHGQG'A@]F`CeK'c:+pH?j[QF)uMLG]n7U +G^4:YKkY[F=r@l#AoVm8KojjVrVHEhrr)*IqYU)(CQ3[rJqnk9q>:3hrr;lqrql`qrXo))s7Yu# +I$p=eQBdVuQBIJsrK[DKnWaWNP`h>IQi$g_rr;rqs8VrcrXSu-rVu]mpI07IpAb0is8N#srs\i& +r;Z]]o_%k>li6q_rW)oKrr2p&rr<#\lgF-4J,~> +"gOo@p\k*grrN-!hu<ZS!<2ut$3'efQ*%7*q#(*crr2rsrX4j#54AIKs8W&srr;]kq>Ud#s8)cn +pHk:7Qi36MQ2d*5Pm<M<P!n%%p](3krVu]m')_\p9TQ,RBPhcHmGl7$a4C4frr)orrVloT_#)%J +`;[[S_Yq@b_8sO3ah<Fc[_Ti#`PKF-_8F.g_[=8r`59C5`MeWJ]DTPIaMn(p(;du1]t_Uube^lQ +N0M<'`4a"&p&G'krr3c2kO&3Cp1A&sH@gNrHo:`us8;lrqu?Zprquirrr33$s7c)$H'nSs"I54< +R$?j##+(X>Q>)]_rVuoss8N)qnG`Id*rl0<pd9%?p](9ks8DrrrVcZns8W&Y[]m$ATssgqrr)or +eGfLJ"o#0kStE9<~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KBh`l#;e=&j:J`QH9CrQ>/]+2u:Bair&YDc\L5bK%WEa2Z*< +aNDZHaND`Nb/hZD`W!jkaNDZLaM?'If.N)HQBdYrOcu&sQg^1@Q^*j8P7*V@OZUJ3_9C!CaN4>" +s2b,\--XWe/jP2e=_MJ[+5#2[[^is!bJq]Ia2uKMgsXsHoC;;:mI0N;nHnXVo(DqM[CGGjrpU-[ +o'bo0n+6PP&G,;YmdTuBfXeQ[q"XLOlgOf>rpMW.l/1n*m/QqS`k]aoq=3e4cKa*+bK@iEb.#"- +e(7DuJTcj(M0U;sbfRcDc,\#MaN"5%$-:-*`Pg-JdogYgPQ[24Pa@U4QiE?NPOXnLR?`ek=+/cT +c,RcA`6$3Bb4Naeb/hZEa3)<FcmimDccjGIb/aM&%a*,BaMY`\<^T2F8Sl)\rl>)[f>n<>`lQ0> +[q&0(9ko1~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprs-j<lfJ0Hrr;io&cMb0rqu`oJ8[dArVc`qrVuofrqlTu +qtg#SBT/RErKR>Is-Do7#EYL"EW>k7qXOOus7/T^UQJ;jG':aoiP`dQe,91Err*9)qtTg#LO"#` +F`mA#s*-,FEH#Sd&e#RYEHZPNGBe@XH$FLREcQ;JH[9pN3t2N5>]Y19F`DMEG'J7TG5cb>HZs^W +@V$GY&Lpq#H[::*earb9qu$Hnk4/HNr'`bOL4bD>LI'qoqu6QnrVuins8N!%q#:<h;a$?CQ3*/1 +Qi<6JQ2d0?Pn&qCRZWP'nG<.`s8Vrns7$""s8Drsq#C%UJme?Ps8;osrr2os"oS8qs8D<`oE4:A +s8Drr!<(OKs8W,us8N5algF-4J,~> +"gOo@p\k*grrN-!hu<ZS!<2ut$3'eePc_1+q#('brr;uurr2g'J8@O=s8DutrVlfrpAXgd#Q+Al +R;%VPOo:UGQ2d*5Pm<A?F)_0Us82corVu]m'*%Ji>,.6UDfg->oA[d2_q+ebrr)orrVm#W^r+(. +o>CUF&')B'b.NXjNjljC`59=,_>_=O_uIXf_nj1&`5S^;NJbHg_SO+-ai23s_uIS,_o97&a1oiX +KTr+G`Q5d+_"Ia-rr<#ts5W_NrV8`@=,)0YJqH8Gq#:<mrr)lqrr2oq$NC)*qu?]m;`g)+rg!YL +PF7a6Q2d*=PmESAS!&_(n,!"^rrW)rs760grseo*s82ii6@E,6s8W&trr2rr%K-5*s8M,gYd1O- +[e]n$rW)oKrW)utrW`DsY+D5WZ%)~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KBh`l#8c=&sCL`Q?3BrQ>/]*Q?(@b0&#Y?<o5+c,[iGa2Z*< +aNDZHaND`Nb0%g'`rF-Zaq)J4c[ArLSWK,%PED&mQ'^a#$]UNg>iX,T_8sd?aSj-YaSs?^a<8^V +dP=XgND+,$@AMN%]>1hbe]YtTb/_WHceQt'nFQ8AnItZbp\X?h[^kSlo'l,8na>f3n+$DL&G,G_ +nbDn5^:UlAq=X@Km-t#?rTuE,kj7[/s7lW6]#`Clp%Ik5cKa*+bK@iGcaL[9eCGrn8:H/MM1dP" +bfRlDaN;`J`l?+!aq;_7aMQ0RfK1X@PEqN!O-#`orKlo:%?QmAN.<t<eBQ"P_S="aaoKZbb5KE] +`X^,1aNDBHcms<;d)sMLao09jb0S>R_nV[A6UXL;CV@dfa8j94a9ou-aN2E2A5#QhC4H~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprs-j=lfJ0Hrr;fn!WE#sr<<%4H:R2trr)uts8VEa#QO\' +=I>A4RJiBMQ2d07Pm<h@6g4:EqZ$*b'D-Q<TW:G!CcO]Uq;K*,^=3#Ys8N!+s82T`_M<DZF)l>E +G5cafG]s(/'6\VGH$FFC<"K-;$<M:nH?j^[G5c^sG'.kIFaJ4WDa"d6!Z,0arcnQeGBj+4rcTu@ +I!U*XChOLa#7)_fB6A]UOO`t$qYU3ipugr>q>^Ha3GjD"L4X_Ns8;orr;ZfqrVuiq&cDV)s7b#J +MNX6eQ^<o%P*D40Q2d0?PmrnENLPu`B(c&urr<#sn,<q!rVuons7/R;9`+Ycrr)lrrr2p+r;6Kn +rTs1Ko&]0:rVlcrrR_&Krs8W%rVu$Gn*Th!~> +"gOo@p\k*grrN-!hu<ZS!<2ut$i^"gPch7,q#('hs82d.s8N#rr;?>(G"(Wprr;urrr2rrrW)uj +rr<!)rr;er=I>>3R?dc;s-<VKl'2LCO@&4,s82igrr<!3rq1M&TW1CuCcFZUqr>N3^t/J_rr)or +rVluV^r+(h_u[cmrkSTOr50/a_83n)`km^mQA`;k`P]L,_o)Jjs24lT&AuH"`5/4-NffC>`PK=) +_SuJj1W72K_7m\)_8FN^O-GTscGIH9]tj=@s8N&urq>F>rV6Ein2Y96I"6Wg;ZHars8DutrVlcr +rVc`qrt#,/pX<B'OctooQ]mf$QBqK7s-3&=$'^p?RuW57o_SIarrW,sr;6HnrVZZmrsel*s8;of +6AS21r;Zcnrr2oq%0$;,roUYnZE^.4q>L<l!<(OK$NL,)s8VhrSt2LXJ,~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KC2`l#8c=B9LM`Q?3@aN2NHaN2B?aN;ZOcUqq1`6HBCb/q`E +`lQ<FaMu=!b503Z`X9f9d#1/JOGoZqQ2Qp8Q2QmSQ'[i&R>*?:d*9GLoZ7'P*mDl62414(CLSP3 +eCMmN]sG?$bJq]Ia2uKMgsXsHp[e4N&bGblo=MKG[HR8SnF#]7naGrFnc/1lp[\4WftG&/ZKCfN +oCVYGn,;SPm7?dBqZ$Bes22Lc][6TFnF5>ZlIjA(bfIrH\%9c*f\"Uq?@7?^JSdL$bf[rDb0%cE +`lQ<Hb0%fFa2u`VZp]8#QBRZ%PF%L3Q2[-?PnK:AQAh5hHr8G>`PKC-_oKmAb5KO%c-4DSaN2B@ +`Pos?aiVNLcn0i3eA]SOaNOS(%a*&?`kfBX<^T8H8Sc#[rl>)[f>ms6rl>;a\R\B*9ko1~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprs-m>lfJ0Hrr;fn&H)P+s8VmrL.^D&s8Doqs8VEa#Q"'g +MjK`tQi30KQ2d07Pm*:uEVTD1mf!i.BWZD]E,.l1oDIXh_oU=)rVulr&c_b'oYQB/F`VSDFa/1X +H?jc6FVAqCG]\".%L*%9$<;.nH@'m^G'<k0rcSlrF*MOj)$9j>&m9-rH?s[RGlE!gG5lgeG:[fP +@NkjR!sg2aDfp>ZOO`t$qYU3irUfIUrVcZlh(Er)Kn4J7mJd(arr;oos8Dp/r;Zfkq=_0qQ^j2% +R?a)$Pa)-3s-E2?&!30DP*D)SK`;#Nr;Zfqs7-(#s8N&tqYohNPX>-=s8W&trr2oss836's8D<W +o^_,0s8Drr!<(OK$NL,'r;HZXlgO67J,~> +"gOo@p\k*grrN-!hu<ZS!<2ut$i^"gQ*.@-q#(*is82d*s8Drqrr2XmJk4i"s8MurrW)usrr)ll +rr2p/rqZ1^MO0TrQBd`$QBd`"PjakEQBd`"Pa.>ZEV]G/s7ZHks8W'1?tH<Z>]=LInb)qBai)?Q +rVc`p!<)lr"5^i2_u@RY_ns7*^qmnc_uIRb_90TMO-brk\\lA%^VRq._u@OO_[XE'_l/NLOctgA +`koR0rkeZNs24lR._ig=aiKs8PEh,tbf@Q8_8,aDs8N&urqc0Qs8;fkr8'#JIt2of54/CKrr3#s +s8MutrVc`prsnl$p9dkaRZEZ#Q'df%QMm*KPjt"DP+%`%P`U*Brr3*"s8W#orr2lprr)j,rqufq +rVu1NO$EF9s8Vuprr;p*rr<#tk-hP#Z(e`'rVlcrrR_#Ls8N#t"o#0kSY*-:~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KC0`l#8d=B9LM`Q-!<aN2NHaN2B>aN;`Uc8To,]["X<ai_]E +`lQ<FaSj*[aND[(bRhq<`l5j:c-eIoO-?'&R?s3<POFe:P7*M:Q'n&,N,VeEaj'h)p;m6Q,0\\2 +>c)F?BO3+0`mi,B^;%;1bJq]Ia2uKMgsXsHoCMVHr:BaS&G,Spo=)EM\%:ksoC),8o^`"OrpLBf +oCW(\iPN+>]X$\koC_hVoD\:Zmn!'Hs8Dlkb.kU'\B"F>o'YP`lIX5&bf\/S`4XC>cI(:Z(i4_X +Jo<6adE0JLa2Z3?`lQ<Hbf\)LbKn5Sd$6hVSW]8+Q'[^5Q2R'?Pn0(<Q'RVuMe["Yd)Ec;`5MYr +!m8a2rlkSib0%fFrl#Dhai_]EdEF;$0[Re\b/hd*a:?A;bf7K5RT;gE8P*a3a8X-[a4JB4ao9?c +a15_S8PNrM~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprr^U:lfJ*Fq>Lj$s8N&tpe$ZAf_b^Ir;Q`drqud$rqCeg +Q'@Q"rfmAHs-Du9s-<kS=MF\4q>^0fqtq,o9W+RUE*uW8s8VfR]Z@_6r;HZprY,>/q"2FYH$+1K +F*2_QH$Xd^G]s%."EJ<Y)[ZKD$jT^OH@1$aG]S"NG'O"3*Hc1058+5%!!Ns8CiXT=DJjN=G^+CV +H$4.AC18Fd!$Mn*A9N9@JWJ@QrVHEhrr:jArr<#pqtQ=[MhZt.7@a2Lrr)orrr;io&GuD#s8;Rk +K:J6jQBRZ#Pa)-3s-E/>%[;m?R$*>#mf3=^s8W&tnG`If$2sf!j[b\*m/-_[s8W)ts8W!(rr;r` +p%._8l2U_]rW)oKrX/])r;6Hmk3VR(p4*~> +"gOo@p\k*grrN-!hu<ZS!<2ut$NBngQ*.@-q#(-jrr;rr'*%q1rr2li8W?<orVuios8N#trVl`p +s8Mrps8N#t!r%(irf[AJPP^XFPjakHQBd`"PE_53^A\*.s8N#tqYpEm'E7;hUn(%p>uL7ns7t`i +ah64'rVlcrrVca-hS@%H`5KR2_SO((_8=(,`;[Xf`5]EMNK06nOL`6F^qmn-`5BI0rk]Dd_nsEr +OcGQbOc.#p`5K^8`P]O,_#D.h_oB[3`M/HZP`:or^rXO/_SGjEs8N&urqtO=rr3E&r:lCXL4Onp +6_!rLrr3#ts7lR)qu?QnrV'?CRZro"PF%Q#QMm*KPjt"KQ^Ni&R$*>"mf3=_s8W#rs7cNks8W$, +s8Duqj@,4tmJd%`rVc`ps8<B*s8W)\[^!0EUUU'trr)orfDYgNrr2p$pTC*YT<Nh~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KBj`l#;e=B9LM`Q6'<`l@tu29*SVbg+V\.Y0^jbf[uIbK.]C +aNDZH`PKC.`lcNMcd0k[aMl'5`mJ71LQ@[gR$j;+Q'7F#Q2d$WOcu-"S=,@*R`rskb/jS%s2b2^ +s2b/Y+iqpP31l^/C/dCDe^;O\Yf*o\e]YtTb/_WHceQt'nFQ8No`+O_nbhkUnI5$]q!>f0]"Z+o +l1OWHmoB#MoCMM@mHsH8p&!df^r*t)^@M'knaZ,>q"t$eqXj=Jp%7\@bIkd2[_'NIqYK^Fcg'-* +bKS,QdBL:-c-FGXdWJ38LPKe+J'uH[`l?'>`l?*BrlbqraMl6?eBuT'GFOk[QBRZ#rf[JMQ^=,, +ns'rRP*:iqRZN%YbgjqP`5T[9`l?*@b5KQaaoTT'rl#;db07uMd)\&#0#brPrlY5]%a*&?`kfBX +<^]AJ9Q%Parl>)[f>n<Bb0%fG\R\B*9ko1~> +$23<Cs8W)rqu6Tnr;ZfUrr;uurr2iprr^U:lfJ*FqYh!)rVuiqr:WLD9@N_:r;?Qonc&Id$NBK^ +R$F))QBd]!rK[DKl]qL9#DcLUr;HZnrV-<gr"FR3Wbu-\6LapLq>B3i_T((&rVulr#QO\roYQB/ +FoHFoF`r"SH$O^]G]n.JEGJ\p#7(5.'*M9TH$Xa\F`2>DG'J=ZH#d^]&,lPr!sB9=D/jQ:DfKi@ +G]n4QG]d_<DESL;$3:D>0lV,TG']5"oDSO_r;QW^mdpJXr;QKfBP`HVK0M`mqu$Els8;osqYgs( +qY^Bhq8HO"R?j5&Q2[$HQ2d0@Pn91GNgPunR?^:_o)JUes82icrr<!.r;QQO8sN!,s8)cqrVlfq +s8W!(rr;r`p%.b9l2U_]rW)oKrX/])r;6HmkNq[)p4*~> +"gOo@p\k*grrN-!hu<ZS!<2ut$NBngQ*.@-q#13krr;rr'*%t2rVcWc6BXphqu?Tls8N#trVl`p +s8Moos8E?)rpE.>Q'dc#Pl$aGPjFYBP`q>c=82aos8;ips8)`mrs8RPI\pjcDF!^jr!35[`kodH +rVc`p!<)lr"Q$r3_o2Plr5'Dh_SX4/`Pom7NJEa_PF%9=_Sa4,_T'I2_o'@j_%ai3X-8O(PEUl_ +_TB^5a2c9=_8!eb_D&pIbeop+Oct`fMjh`'_o0=*p&G'ks8W)olgXWJrquflqIXDnIXaIGnGWCd +s8W#lrXf,.s8Vun`E8+eQ'RPtPa7X6Q2d*>Pn97KPF7VuR?^=`o)JUes8)`ns7uZmrt#)-s8;oo +ha`f!irAlTs8Drrs8<B*s8W)\[^!0FUUU'trr)orfDYgNrr2p$pT:$XT<Nh~> +%qAam]>i"7`l?!=aNVfJ`o5#=b5KBj`l#;e=B9LM`lQ0=`l@tu293\[bK\AV,DSCdb07lHbfIfD +aNDZH`PK=,`Q69Jcd0k[b/VE<b0Vl#NL#m!R[KS1Q'IR$Q2ZsXQ^XG2IR;B'`5fs@`l5s=rQ>/] +s2P)[+j/2AEi!PSAi&)jbJVTD\A5qoe]YtTb/_WHceQt'nFQ8NoE"RRqsXRTs76Wlo"MWN_8!dr +lLj`ImniWDoCMM@mHsH9rnYN-_8XC,_=mftlg4$1q"t*iqY'CFmdfSTV6R_C]X>lXo^qh=cg'-* +bKS,QcG732d)sGTc.Gm#KS4k3/C)P^`Q$+#`W=0'rQGepbf7fOb06VRMO'HmOd210PQ.!LR/iTD +Pn]:KQ'7Po33CKVai_`B`l5j7`lQ7"b5]Q_`Y$20a32]Jbg4?iL,-9``6-<Grl>Slc-42D^7&(l +77p6k]uU,n!6<^4$HpT7aN:u'9LhflJ,~> +$2!6>s8W&rqu6Tnr;ZfUrr;uurr2iprr^[8lKJ3HqYgs&rqucqrUN:><P&5/r;HZmrYPV3s8)cp +rqufjs8Dorp\%F/PE_E#PEtHu&X\`OQ^4&.PYf<nqZ$HkrVuoprYth8q#C*drnU>PT0mO1;t^+f +s81`m_o't$rVulr$NL"uoYQB/F`V_LrcJZnG^4^[H$O@ECfD#T#5nN7$WhCmGBn=OEcuVIH$FUV +D*/L1!%e9a'j,BtFa%nJG^OORF)>u?FD=/s/LMbU%1k@7EcZ>NO4Ek#qYU3irorhIrr*K,s7^J" +KS+tCJ9Lefs8W&tp\t3jrVHhlA<rOFR@93%Q2d'KP5UUVQ'P"\qt^9fqu?]ns8Vrms7lR*r;Z]h +s7af8Qp(?As8)cnrr2oss833&s8D9Xn+,N*s3^iGrs/E#s5`S;n+M8~> +"g=i;p\OjcrrN-!hu<ZS!<2ut$NBnhQ`@7-pAFphrr;oq&c_e.s8;@POAiajrVZ]qrr2rrrr<!8 +r;ZZos8Mrrp](3js7c7aH'=GWQ]dVuPj=SIR$*u+Pa@Ys9Z$W(s8;iorr2rqrYkb8qu?Nls4pAK +Rm(_';YC%fs8Clq_o1+(rVlcrrVca#hS@%H`59Ci_uIS)`4Wt,_T'd6MiEg[P*;,l\AQ5#_nsC3 +a2Gd2^V[k0XHnp5PDtWbMo!KR_#2._]>2D$`Q-*8P^n::N/<RSQi=o5_Sa1^s8W)us8MoXn,E=b +rsA@:5_4E94FVJNrr2urrr;fns8W,u$2sdn@?Zt>R$s*5Q2d*>Plm>;QBhB6%S4S8qYp<fs8W&t +s82`oqYh*,rqcZmp]($49U%X:qu?Nmr;Q]qr<rW)s8D)fZ`g^1]_TtSs8N?&s7iUdSY!'9~> +%q/[h]>Mb4`l?!=aNVfJ`o5#=b5KBj`l#>h<)n+I`Q6'<`l@tu1<%8Sbgb"[,)&LRdE0DObfIfD +aNDZH`PoX4_8jR:aNMKLbKJ2KbrBQuO-Z3#S!f\2m$/6OP+7l*S=G^-WQiH%_TU-B`Q$!tasG*J +`6ZEIdC2'.S3gpp5hXZ/a3;K4_nWn8bJq]Ia2uKMgsXsHr:BsYs6jdknETK7nalM@\A#_p_8<t# +lh9l:nF#i:p@ReBlgOE>g;LS?_nX()\aK+Zkj.R%oD%bEo^(u6o&R*COHQ?9[_:&bo^VG6cg'-* +bKS,Qd(@$6aMu6@d*>QEI"6f-Dd(W7b/qZH`l?*BrQP;as2b5^$-UhU=H&B(QC<m5PQ.!LR/iTE +Q2[*`Q'7>jMDVBgda5tPb/_68`kfR7qT'5faN)]J_9gK:5_pW4`m;ZLrQ#Gjc-4/A]p_ql5tjso +^!at/b0/&LagtkS7nm`K~> +$2!6>s8W&rqu6Tnr;ZfUrr;uurr2iprr^^9lKA-GqYh!)rVucfqu9<P>.*o#s7lTnqu.E.s8Drq +s8Vrns8Mfnp\fMZN0oipQB[^"PnB%FOcGipPB)oPs7uZos82irqu.Q7rVH<dqt=Q`X]9+Y1W04l +rVucQ`5BLAr;HZprYkh6q"2FYH$+7SG]n4NF*;eRH[9gMDGD/W"8r34!=i1PF`_eKEcQ>@I<KjZ +E'4s6!%e?\&mK4%KRJW0L4>,;J;/SuI8WR#1bBM"&e?a5EH?2MNRdY!qYU3irorhIrr*K,qYR.' +F+]<f9i]d>rVZ]gp\t0irqcrE:6V<1OHuF$Pl[,4rKR>I&!C"gp\k-lq#(0hr;Zcks7uZoruV1< +qYds+NC`a@rVuoqrr2rtrqu]ns8;3WnFGT-s3LZLqZ$TUm.'Q<J,~> +"g=i;p\OjcrrN-!hu<ZS!<2ut$NBniR&[@-pAFphrr;rr'*%t2qt0aa8rd#]oDejcs8N#trVd`8 +qu?Zqrr<#qrVulks7Q8:DMsjFQ'RW!Pa(L!$]^[<NgGrjDis8`r;Q]rqt^40s8MuorVZD"O/Ple +FYq#8rr)lqi5W[Qec#IGrW)oqrrLulrkncQ!5nfSs2,D`_SX4.cFK."OcklhOcka7rkgV4_o9U8 +]ZS%,aNLNHNfoltPE1QW`PKI0[_fekZ+n/mb/:g)Nd>SJ>#L-5N1%W&`Pf^2p&+gnrqkjHrr2os +s8!8'AoW<SCJ%RWq>L6ko`+serr2rtrWrGF9Tbj)O-Z=5Q2d*<Pl[29r0@nW<h]6as8Vlms8;iq +s7u]pqYpNn%K?>)rjGa_8+uu]s8Dlprr;p)rr<#sjgDG![%b>2d/F=NrVuYlSt2IWJ,~> +%q/[h]>Mb4`l?!=aNVfJ`o5#=b5KBj`l#Aj<)n(H`Q6'<`l@qt1<%GY`6QmaK1hEHcHF5OaMu6@ +b0%fF_TBd9`5g';`6ZZJfZ_iN?\Xc,Q'dr-R@0D.m?J?HS<8i#QB5j3ak"AKa3_rJ`Q6."asP3R +`Q#pAd*G+/Uf:uD,-0MGa2cED]>MCse]YtTb/_WHceQt'nG`%Znc&"Wm;D:[o(2JPjhACB_ns=. +_7f1.na>o7naZ><q![bIqUWEm]uJ(/^q-oAmHs&beB5\?b0JGmhUTu?HXf?)5`)>Ke,Jk(n`\<a +f?).WaNW#E^<+I9`Q#pCJkos*L2'"=[*?e6bJ)!9aN2NHbl5caaT'9dd'#TdQ&1KdSGeWSQ'[o, +Qh-I[Q^O8.Q'7>lNeTr\f[\Ns_SO.*_99g5ai=1us2kbka2lc,8:)l0bK7uNrQ#Gjc-4/A]pVkk +6;:*s^!b"%ap?52a1>VO7nm`K~> +$2*9<s8W)rqu6Tnr;ZfUrr;uurr2iprr^a:lK8'FqYh!)qYL3ks7KKHBpebss8)`pqu.E3q#C<l +p\4^aqu-Ean5s^jR@05'QB[^"Pn'+IN1cH'RR5s3s8N&qrqufprYt\2qu?Ti^0n(*;0?2#p%\Rc +s81`m_o't$rVulr)?9U/oYQB/F`hqSG&q\EF`r.XH>dUt*=)]E!##D:&6NsoEcc>CF)cJIHZ3dc +('FI7rrahf=aGX`5tjR:<_-GGM2dd,<+rhqeC[5(#V9Y/GB8(iearb9qu$Hml0\BIrXA`)s8)Jd +MM6@DQWs:as7H<jr<W;rDhO:BTSo#uQ2?gFPm!Ia>dEu#rW`E#s8Dlqq>("4s8;iqqtm*uMdH>V +s8N&prr2rtrqu]ns82-UnF>K/s3glRs8N#os8V-HnaH1%~> +"gFl9p\XserrN-!hu<ZS!<2ut$i^"jRB!I-p\b$is82d.s82Zls8V[lIqP,Gs8Vrqrr2rqrYPV0 +s8N&or;Zfrs8;NX<cF%dR?Ei$Pa:R!&!iTATTke052Q;=rr;oqs7uX4r;ZcrrV=39WJjPk>VbsI +rr)lqi5W[Qec#IGrW)oqrrLulrkg8'_8F41`Pf[5_8F+3]TJ#5Pa%;lO-#@2`5KR4_o0L1a2#a4 +aJk;^OHc(1Os5gI_T'*r>%1<+>uPR/WNNUUB4e?nce3/bNLn2-`PfX/o_e^mrqkjHrr2lr%fZA" +UkjSF5a>RLs8W&to`"jg$MeOkOI;`!PEhE!rg!MJmZm[8%[^[/Z1J"qrr;rsrr)lnrr;lp%f6/( +rqrBrLgC#Ws8N#or;Q]q#l`nmZa-p1_tha[$NL,*rVuShS=Q7UJ,~> +%q8^f]>Vk5`l?!=aNVfJ`o5#=b5KCI`l#Ak<)n%H`Q6'=aN2NHaN2E=`6-TYauOQJGg4LTaNhlH +`lQ<FaN2`JdDa#7]#2;%c-k%h5@K84Q]dW$QC.W;m?J?PRZ*o&PE7Q=g<[j^_p$BF`Q6."asb?K +`lHQUe"91%M,&"c)V3<]a2cKF]>M@re]YtTb/_WHceQt'nFQ8Nnc/(Wm:Z"[p@J7L^pUnk_o0O4 +_7f1.na>o7naZ)@nbMhQftFr.^r+"+_RmeXpYjS.9dLPn&N4m&[C9U+1MCW@Ma;oseGnq%n`\Be +f?)(SaNDrE^<+I9`Q$9MdFF;*IW[`.6.=6*b0Tt+!6Y2[s2PAgf2cgBPb!a3P6R/5Q'[o,Qh-I_ +Q^O8.Q'7>mOH>K%8!VENccF8Ha2Gm>^r==5aN4A'+NqgGbK87q=*HjS`6-0E`lQ6@aNVfG^Uok5 +84-'EHbIkK$HpT9`lPVq91M]lJ,~> +$2<B<s8W)rqYpKmr;ZfUrr;uurr2iprr^g;lK%pDqYh*)rVulmrVq(fEd@]_rVulss82ctrVu`f +rr3N)rVQB^G!peGQC4#%Q^3j!Pn'1CR?ituF+O;gq#:<irVZ]orYte8o_n[^9W+mYFE0*frVccp +s81`m_o't$rVulr)#sL.oYQB/F`hqSG'.kIF`qtSE,Sep&IA:7&cr7K=E8G%FEDYHF)lDCBKHn4 +qZ&2L";"7OK8gp4<.Lad[<c%T;gjjqkN_KbD%6XtAo`0<GE(/ErVHEhrr20Lqu6R+r;QEioP6gI +I6sQCYkA%orUKjlp@M1@Q][c%k`u(1s-4+]OH5&uNVWMPoDe[_s82ikrZD1:s8VYEEI;<kr;6Bf +s8;fos8N#qrr;i\p@7V-p]&\@$NL))rVuoXmIBZ>J,~> +"gXu9p\b$frrN-!hu<ZS!<2ut$i^"kS#NU,p\b!hs82d*rVlirq#(,7G&V^+r;HZprW)urrWE)u +qY'pg&,uV.q=ShsI$BqbQ'7Q#PN\8BR#m`%OH4@1rVlTks8)]orr)orrr2os)#+(-pIqH]5B(Np +KDkfLrVufR`l#aFrVc`p!<)lr!T(Wk_bn:e_o0O5`5BF1^ra6HNKB?hP`_&gOH$cg`Pfa5_o0L2 +_SX-^N/a!dQBI5iP`Up6`OrQ>:Lo3SaKp5!<)\4&Ge_,?]Rt?`T?5!h`5'1\r;RW5qr[AGrr2rt +rq?BbCdN\u5+HGooDe[bnbrpjoMCL5OIMK"Q'Ra'Pld28Q2[*LPn'.CO+LMmq#(-_s8)Qkr;?Tn +rXSl+qZ$TeJo#aDq>^?hq#16lrr2p&jgDG$[%GG8df'URrVuirp8=FOT!<e~> +%qJgf]>_q6`Q#m<aNVfJ`o5#=b5KCH`l#Dn;cRkE`QH9AaN2NHaN2<=c-",QeQ?Tt=jkI7cHOAL +`lQ<FaN2TTaM?!;`kKI7c-olOE0$6OQ'7Q#PPgd7Ps_"'R?WVa@;+EF`lQBBaiqcEaND`LaMu6C +_Tp]a1mFOmDeL)"f@%j_ajA,@_7[J3bJq]Ia2uKMgsXsHoCMMBn*g8C(@Ubep&=Nr_8*e$_o0O4 +_7f1.na>o7rp`bSp@nC6^qIS%`PK:*_nj1SqruKo3&<frF_F&u4ul2)0P=3bA5[NNec5('oBF`j +f?)(Q`lcZA^rsmA`l?*:d`Y?;H?_T<=HUhSa2[\k&BrDI2L:@AS!92%OcbimQ^@6-s-WqTQ'M?4 +'U=W4F[^?(f$M7Y`l$'=b/M?>`lS/%s2bScaj/(QAn=<MaSs-jdE'DKaNVfG^V#k4846-DK"f[S +$HpQ7a2k_r91M]mJ,~> +$2NK:s8W)qqYpKmr;ZfUrr;uurr2iprr^j<lJ_^Aq>Ls*qt^9foUTN@B_;6&rVccrqYh6*rr;fo +p\jm_fM?dTPa7SuPEhK#Pj"A=Ocl&qPb(P=qu?Zos8N)squ?]q)u]U4p\12$VKlfh5FM->rVuls +qr#E1_peP^s8N!7s82T`_M<DZFa/.SG'.qNF`MP@<tc,K"8i-3!X'!7EH6)CF`qnLDKf_U%gN48 +!&"?Q!!<R;E,U2TIs,U78q+2$eSJJd?f:J3b9%9$.qN^GF*N\poDSO_r;Q][mJHn^&H)S,s8VX\ +GDS8PU/V*iq>^!a#QOaqA<<"FPNA).PRitBS!BLW7_ANsrVZ]qrV-*d+9269rq'WL7-saGs8N&m +r;?Qorr2ips7u$Tna>01s3glRs8Durs8V-JnF64'~> +#.128p\k*jr;Qfss53hUr;cirrsA]$n=6J]^%hL'q>UEo&Gu;'q!sq_HY<'Ms8Doqrr;oq(B+%- +s7u]ks8;fJ;0S.dQBd\uQ'[f$k`lI<Pa@Z"SP&JLrr2lrrrDurrr2j9rr<#rs7lAZFJO"fB0D^W +r;HZos8:fp`5U=+rVlcrrVc`shSB-.s2+fRs2=rT8\i9c\q5coNfoTjOcYWcN4?gF_o9L1_o9F6 +^n-(1NfT<aOckiiObhB+]>D@tY*=66JZm2-:ImK1\A#Jf6?\-TaMPm5_8,^@rri>uk3r9Jrr<!. +rVuoi89]kITV,6^qtL-hrr)lmrX8c*TOa1JS<K5'QBpWts-*t_Q(2GT\bH.$qu?]pq#16krX\r, +qu-Qf?$ep)qu-Qos7cNmrr2os#NW>"[BlFLq9f0JrVuiror"COT<j%~> +%q\pd]>i"6`Q#m<aNVfJ`o5#=b5KBh`l#Gp;cRbC`6-0BrQ>/]0#l&Q`R;oNI8t2Va3)ZMbK.]C +aNDZHaN_lOcGRfBbKA5A3G=83QC!o$Q'ISsrg!GKn!+*?PF%AgM_>"SrlG2`c2P^9aND`LaMu9< +dEL0pAXI@??nQfLc-+5LajA,>^Uh&-bJq]Ia2uKMgsXsHoCMMBr9s[UCAIi"]#);&_SF(-`PfU* +lh9l:nF#i<o^MnWgUt>@_Sj=,_8*q(])Vg!n)2HkJlsTtF,PJ\$NL6LDf(CbNOmmEmHaK4eaD,4 +`Q#m<d(R6=bf\#Jb/_ZQbUdOa31c?rg<[d`b0%fHrPnlYrlY8^&B`DMIS>BRS<K5%OcbimQ^@0+ +s-N_Q&=8]GQA^i+0qd+Qd`p.^a1qVm!QN4[arngM`PfpD;KXM0ai)KGahc'>`lQBH_nNgL<_,_T +8r14/a9fo/a2k\q9h%lsJ,~> +$2`W:s8W)qqu6Tnr;ZfUrr;uurr2iprr^p=lJMR?qYh!&rr;rsr;O;iP#2)Ts8Drsqu.E0s8Vfm +qt^0^<CD_4QC!i$PEhH"Q'Rd#Pn'"GP+,Xtq>C3ks8;lrr;6NorYth5q#BtRWi/7!ED?0+qu?]q +s81`m_o't$rVulr#ljesoYQB/F`[P*rHJQiG\UUs"TSW#!"T)><GunuGB\=UE-c1d&Hht30`_=X +!!!*/<G?MrG]%eUOH4Qb@$.=u\lXTmSjP:I%4l+3H$"Cmearb9qu$Hml0\BIrXf#%s82Hek!XVu +A=dt-rVucbrWi5pp3LtIP`k9rs-EYLrfdqWQB%8lQ^q2lbk_;:p](9grr2p;q#*gF/`HR)qYpNp +r;?Qorr2ips7bmRo'Y01s3glNs8N&ss8V'Wn,W97~> +#.C>8pAP!ir;Qfss53hUr;cirrsA]$n=HS^]D;@&q>M$*s8W&tqu+)bOAGiRs8Dusrr;oq(]==5 +pAb*frq0A_Mj]ltPa7Q!QBmf%Qg'bIQ^*u&R9Ic1r;HZqr;Q`prr2lp*<-!<rqcZf6DpYCAoCB< +s82irrVufR`l,jIrVc`p!<)lr"Q$r3_o2PlrPAlYb/D)@H[pm/OT(CBO?8Vb\])P*`50:,_9g#r +I<p6tNf]<`P`_#hM8RBR`lZ$9]YLe3@Uk:aZ*-`?T:'#/K8Z8=_8F4._"@O((]3@_rVc`ps7ZKj +p]'DFHrOREFcZG"q>UBks7uX!qu$26G*A,QrfmJLlBV=4%[E9GO-booRT4"ApAXs_qu?Wo!<)os +$2a]kM(@T`s8)`ms8N#srs.PlZaR30eG7Mk$2so'rplnXS=d0=~> +%qo'd]#Mn5`l?!=aNVfJ`o5#=b5KBh`l#Gr;H7SA`6-0BrQ>/]$cL',a3`#WRk04HdJh;nc,doE +aND[)a;)nF`73)Xf$c]7I?Bb\QC=,+QB[Strg!GKn!+9HP*_/e6DhuJa3Dj-a=tNOaNDZLb/hTB +`Q6]_/tS^p?"5h@cc=/J`QQ]N\\,D`e]YtTb/_WHceQt'nFQ8Nnc/(XnSIgpq"h>,]u\73^r411 +`50+Pp@7S?mdp&>s7t`i^:hY0`PK@-^q[^ro_\L[p>t;]bclL`3*'^PO![M?F%^n]`nUIWlLjMo +mb,_$`P]^@]u&(>bf\#BcbmQF`AMmCAX6hFdaZ:Zb/hU%`<+'#aSa0laMc6I?"](XPa.MtOctuq +Qh$CYPED&oR@9Y9R[BG!Ob]!]85QA;f[%Rbao03YaT'C*a2uBB`7@#('"Z6+`5p'BaN2BBbf[i; +]ouJf852X8^<t".a3)B?ZWp6p:2td~> +$2r`9s8W)qr;Q]or;ZfUrr;uurr2iprr^s>lJ;F=qYh!)o)Jabs7C5/LdUh3rVlfrqu.E3rqcZm +pA1IJNgQ,kQ^!c$Pa.Q"Q'Ra#Pn'.FNgO1Jp&G'hrr;uoq>1-krYth9q=K2kWG>.M8B15ps8N&t +s8Clo_o't$rVulr'`\(*oYQB/F`VVHG^4U]H$*q5%gr78rrW)u%16!OEccSOH?aCD7h6",!!*-) +quA8R),k<fG]n.OI=-]s9JA@K.OHSc#pgi4#n/D"GC=X]NRdY!qYU3irorhIrr*Q.s8;oqs6fQ5 +H7?#!:$M]WrquBes8N9%oNRB<RH^"9QN!0LPRj+FQ^4),MjArpY5A4uq>L*f+8u6>q<U\+=7?1a +s82ipr;?Qorr2ips7P^OoC(?3s3goGrs/Q%s5<D8nb[h~> +#.UG7p&4mhr;Qfss53hUr;cirrs8W#nXlb`\bZ-trY#8&s8Vloo5@H[6M:6Srr;uss8DrsrtbV1 +s8DZeTg+R)Q].8qQ^<u'R$Eu(QKaYHR?io%?DI5os8;lrrqcTnrr2lp!<2ut$iBUIK;E3ME^n(A +r;Q^&rVl]P`l5sKrVc`p!<)lr(Z)sF_o0L2_SO%'_8=%*G^Od`KSb\KOT(A(PE3>p`P]U0^r!t, +WdB8=GCPI2OH5TfNfoaE`kKF-_Sa4$^UT)8Dc9D!76WYDKoD+RR_uqX_o0@_qu7!"k3i3Hrr2rt +qu6U)nFhKY-E=+<kPkDYs8MoqqYpKo"S5fXO-fj2!1*#;(RC>NP`q;qPaIc(Q^O.rP($6-q#(0f +rVccprX\u*s8W#a7=S>,s82ins8N#trr2rt#lW\hZa[<2g%j"o#ljl#m\6;BTXK@~> +%r,0c\]2e4a2Z*>aNVfJ`o5#=b5KBh`l#Jt;H7M?`666CrQ>/]$I$*&bf8/Q9gs@RrlHD/ccF,G +aNDZH`Q,j6cI((pM(O=@P)>NhQC4),Q]mPpPa.O4Qg^2&QB@&e9SCR3aMQ$Ebf%B:`lQ<Hbf\#H +`lcEJAp0n\6>&6Y`koa5`l6-LaLJaf\^emCb0%cHb0Skkg[P46r:)*)p@n?f]",Jrb/D'5`5T[2 +]^,:]mdTZ9oCDV8\]2A"`Q?6=^AbrV_nbO-lgaB0nac#3h4f7>>$auq3@nTtVSC4&q!785jjW\O +ai26:`m297cHXSWb0e2H`m;`eIsruKSh.\&bKS,M`l5j5`Q$!Ab08#NaMuBOe4>@SR[9;'Octuq +Qh$CZPE(`iR@^+FSt)".Od2/gO`ERHg"+]oa2\+ts2b5_+NMLBaMl+\HT]<p_TBd>`Q6-?aNVfE +^:TM-84cQIPJ5Db#g:3(X]J1b:NM$~> +&-(M@s8W)srVZTmr;6Eks5EtVrsA]&r;Q`rfBV\\rr;fn%f65*q>^6ipSqIoanl&5rr;lp%K$2* +rq>,9?^?b;R$a0<PQm;8QB[Z#PNe>DPEhY,h"gaFrr2rpqu?ZorqufrrYte7qVk;LSO%@@oC`.] +s8;ors8Clp_o't$rVulr'`\(*oYQB/F`V_NH$Xd^G&_(,#RC;.!s]#4!WE'/#Z>P\FaAC\G&BY] +"98T(!(?tk!!*'""q+ORH?OX]G&qqI2AR,?)^?s`0d[hG!!!6UD0pbTH&^AGrVQNjrr20LqYpNo +rqcZnqu?Ii8q9T9TT+0nnG`If#Pn;kM//HDQKsh7QN*6MPRit@QC!o'R@053=&m*4qYg3g+929; +r5_WIPQ1CWs8Dlqr;?Qns8Mrqs7P[No^:<1s3goGs8W#us53hE!;h9~> +#.UD5o_ndfqZ#=Ls8NB(qX^G[Y.+3&q#1s(s8Vopq#C)d>#!-7s7u]nrr<#trW3&trr3Z*gdGG6 +Ng,ouQ'R]#PEqT#QBma!Pm3G<S4;<0qYgHoqu?Zsrr;ops8NK*s81eNV3sJbEq8r'rsSf*rVl]P +`l5sKrVc`p!<)lr#N!86_o0I0_Z%>=_8F'4G("dbIX[-4O-,QfPE<Dr`PTO-^r"0iIW]g_H$Xdn +O,oKfNfJt7b/M'2`50.*^5I&XEHZ2:BR>;eNffK`QN"`*_ns4]s8W)trtkRpn,E:arr2corqufo +;G)C0;4WVgqYgBlqu?Tnrr36#r:GbXQBd]uPld26PPp^TQ^F&&Q^<c(<)^U.q>L6krVd9+rVlf; +8n=+bqZ$Tpqu6WqrXAc)s8W#R['R9MSDF"frWrQ%q!+KBS"[<A~> +%r>Bf\AlV1a2l?AaNDZH`nJK@`OfMU<GT"YbK.d'b5]O;_Tg-=cc4A]QqfQ9ajA#Mb/hTBb0%fE +^;\@GeA<t<Nf'!eR$Er'Q^*i&P*(ukQ'M<7n!3p8&!T&je&]VJ`QQBFbf@ZAb5TU7b/VE<bg4'c +S<uEQB&1tb`Q,m9`QQ]N[^``Ue]YtTb/_WHceQt'nFQ2LmqqUdo_A=ZZa7?\_8sO3_8O=2_S3VH +o^VA=md]rIh7C)0bJqK7`l5a3_ns-kkjn3*me-AOs8U9FXIu>[S;W]!TWPfE`6\5JmHW]Ymb,_$ +`P]^@]thk:bfn5Ja25X9d5XCB:fWg)=4,:8rlG,Zrl#DfaND`Nb/VB>b1PNp?]pW=Po5dIOHZ*( +TUq[>OckolQ(4;#P!qR1e]l:Wrl$/&aNVfJa2>m?Ud&1/eAKAK`P]g;`lQ<Hb/M*)OA\VA:.gth +d)ZL;`kJBO91)L"J,~> +&-(\@s8W#srqu]nrqZBhs5Eqfr;Q`rr;6Els4ZZ+jo>AZo)9R*j@F0;qu-Qlqu?]ps8W&tp]($\ +`($/[QBqK7s-2c5&!WNHOdMAtR@fX`LA:fGrV?Ens7lTn*rH!9s8)G(P,DPkF'":rs82ips8Dup +i5NUOe,91Err*Z4qtTg#LO"#cH@gNgH$3h1&.AjK!r`09"U5)4!WW608T8foI!^9Z57dl'!sAr4 +rW!9+!WrK-%TmduJ:@K?2InKH"pk;7&/#Qe&e,$F!!b/tGC4RYN7IP"rVlfrs68nHrr<#trr;lq +qtf>6LP%ISW*%[KrVlusrr;rmrX\o+s8)ch9Tk[,S!KD'Q]U0k0Tq`cIqYkUr;ZQls8Dlqqu6Hl +qt+`Q:%nJ`rr)iqrVuosrr;uprr;NYq![Xus8UOH!rr8srr3,anF#Z>J,~> +$+m"8pAb$hrVlfps53eds8Mros8W)qorFmh[.*tko)9L)i^R[1r;Zfrqu?]qrr;lqq#C0_`'foU +iKXt=RZil$Pa%N(NGjLFs82fqr;Q]q"Si#rrVHNn)>Wu>OJH)aDcDVks82ios8N&ri5WaTf)>RH +rW)oqrrLulrkirp`kfI0a1]<4G^+O]H?spdK8YkTOH>O0aiM<6^W"$dJ9-'[FaJ=XIt`iBOcYT_ +`PoR/_S*h*]T[D[I!9dWF)uSWM3*m^M3l2p^r=4-o`+sis8W)pk3r<KrVc`qs8;orr8TejIk[4c +=4mHNs8Mumr;Zcqs8Dp.s8;osq>U%ZOcklqPEq;uP3nP6Pk^LbP*V8\B<(\)s7u]prqufps8Dus +ok\b@o(rCdrr<#rrXAc)s8W&K\[AcSRd'^trX/])rVufSURRgJ]mp~> +%rtrk\AlG*`QZQG`QH?E`ne]D`lQBF\7863BX#@ooZ7'T(t6Yg?>%^.aiDNHai)9BaND6Cc-raQ +O-'=("I5=AR@!l;!0cl:&X8`JOd_T%R$rkAD:I.W`Q$!ub^RXQ`luBIcHO5E^ra^H;1tQC=(Xg8 +dEfeV`lH'CeAer.\%1&4`lcHEai_rbdbF9_n*'0)mJ$VTs0fJO^r""._7[Iu`l>d+\_ZlHlg=-5 +oAIBk_7mh/`4s.*_o0I.]!1>algXH5q#C6@[(*fY\[f2TZFIQ^_8<h.qu?0qnDhp_f?)(Q`lQN? +^ru`"0Z_8R_T9jD_'FAX2Og:,\Br=5aNVcLahks5`lcNJaMu$=bg"no1Ok7BSsl17QAtF"s-!JK +Qi<C5Q^*i"PEhE"Q^!erF]FOOcd';DaMl6Ibf[lGa3@Fr44VQp_o0O5`5Ta=bfn5L^UJo!8jcHJ +W56p's2kVjbe]rS84$()J,~> +&-(\Bs8W&ts8;corqZBhs5O"hr;6Els8;]js8Up<o'$,RrUKk)p0i5Oo_/1]s8;cks8N&qrquG/ +;43T6QBqK7s-2c5&"&KCQ]mf$P`LQ=rql`os7uWrqu?ZlrVmi/s0lF7P!j2(9(ViVs8;osrVcTN +`P]UDr;HZprY5D0q"2FYH$+:YIWKdRAnDGY"p>&,!!*0'qu@67=_VbuG'%[p'EA.?"9So,!<3*9 +!!<^6FaS7VG&q+J"onf,!!<6'!<<0"!"B#>11toYFEiboo`+mhrr3)am.gSZrt550r;QTkmV6`m +>th;c<VZIdrVloqrV?F's7cBirr;CYR[]S,NL5uqiKZ*_OIM2o@A*Jos8VclqY^?jqYg?M6]>7E +r;Zcprr2lrs8N#trqlWnnaZAAm*G_3df'=JrVHNn"R#=Cl2#o~> +"hg_5p&FshrW3&urr:pUrr3H)r;ZfrqtRLnX0Cpes76-qrUjN?=nVUis8W)r%KHD+qu?ZiEDMm_ +Q'@NnPn07EPF%K#P`goRD#=&.rVulr!<)or"TSB!rqcTn)YF'<?DNTKD.lK3qYgHjrVulsr8>T5 +`RXqcrr)orrVloT_#D4Z_SNn(_nX03GBe@Xrcg,BG^P.&OHGZb^qde,^qdgbKQ_QhG^"IVG^Fpo +MN<j\NlB#R\&-&%]U!bdIscNjrcT-(I>!QAP`M?I_8"%/_=dj.rVlfpqW@;Ir;H`srVld(mqH]g +=@]?W=8MjirVloqrr2rrrr<!.q"k!grU*7DR#mGhQ^=#sPoc9SRuN\BTDJEas7ZKhrr<#ss8LnA +L0"!Es8W)us8Drsr<rW)s8CKWZaI93mJ>91$NL)(s81ZIS"6:iJ,~> +%s_Mt\&ZD+a3DlJ`QH?E`o5#=`XU)3`lQEI\S"W8Aui_ho#N!#fhcKUc,@TBd`TGBa2Q-?bg4^= +6BR=pQ'IPsQ'[r.Qg0i7R$!T!Q("#&LNQ_Sd*9VRaND`Obf\#H`QucLccF)D^=\fISVo^G>r0aI +aihfKa2Q<Q`ji[k]@G*Eb0%cHb0Skkg[Oh'lg*a-q>('!]YDA%rkp\2]tM8#`PT<tlg=*1nac>. +`4Ne+`Pfp;`50:,`5TU,Zg75Qkk+WJpscjfaMu3B`P]U1_u@SF_naXip[[q:cg99*a2l9Cd(R08 +b/hZD`5]a:aj%k!@!Z0TWf96k_Rdk8da#hK_8F:6b0%fEa1T@9dFQMnL67djPb"&$PN%i]S!0=t +Mbo&Ub0.f;ai)HMb/VQJ^ase!eBQ%O`5]d7_o9jEbf[r?["21I6r?a`_pZX+aU$,6^mnCo5u<Gh~> +&-(Y?s8W)us8;corqZBhs5O"er;6Els8;cls8V-@o&frOnbrpkC3rk"rVuQhs8N#qrrq\F@[<+C +rg*MJs-2c5&!rHFR#mc$Q]YAEr;QTnqtU.)s82fpp\OpipJmui9LEZ/?2+C!p\t3mr<W8X`P]UD +r;HZprY,>/q"2FYH$+1SF*)D8<Y,N?!Whro#ma1JGB%M36P'=i!!s32F*_kICLJ[tnc0((->.LG +CO1lfo`+mhrr3)am.gSZrtkY6rqu]mql<POJQmr.C9[L5rr;ior;ZQk%K6>,p](6a7Zj.0RZj&p +Q2d!PR%'!tc2.J>rr3K%rVHQjpP3m:HM[U?rr)iqs8W,u%0->(rr;NWp%.Fos8UOH$NL)#s8W#Z +nF#Q>J,~> +"i6t6nGiIdrW3&urr:pUrr3H)r;ZfrqtRh!WikFZs76-qrV'rK:WWS9q#'sf"mh+TPDkh,PQ@&8 +jcp@CP*VJsRZs+t;Y9haqu?TnrW)orrYGP5s82fqq"t*koi%K^84%0&>PS6up\t1!rr;oS`l,jH +rVc`p!<)lr@,A]:_o0U3`lQ-/H$=O[H[L0eI!^3dIts,MQBAAla25p7VKm9-I!p9eIX-9cH%(I, +PEM-Bahtm4`5.OZFFJO]I!Bp_I!g?mMNO!]QGpk]^WF@cs8W&srr)]UnGiFcs8Nc1s8W"s:PaBu +L8SjnqZ$QpqYpHls8Drsrso&.s7ZKmnjJP)R@05*Qf42:Q^!Z$RYs;Pq#C?mrt5),rVufiKlV6X +q#(0lrVlisrr2rr$i^2+r6i!Y\$VasqpGECr<NB!fqFn+U;_W~> +%t.buYf+K"a3DlK`QH?E`o5#=`XU)3`lQEI]5^PFA"p`[o#N!#fiDlNU<_'#bg4;H`5fpDe]2W) +N/O*jQ'IPqPEhQ(Qg0iTQ]dZ%OIDK"Jj.f9c,I`?aND`Obf\#HaO%uK`kK:2eB^7@U.%7W<^b<] +bJDQLa2Q<Q`ji[k]@G*Eb0%cHb0Skkg[Oh+p$qhUs7a4@_T'[=bKJ#LaMc$<bK7]9iViWIrVPQb +]"l>-`lQEHa_/W2_SsR:_nYI6qXsa`rQr*c`Q#pAaN)?B`PKC0`koI2q>'[Kkg/VIaiDKBb0[i9 +ai_]G`l,p;`lcTTM`l]E?\tCUNQBAecH+/HaMYp8aNDZH`kfO5dE'njdk???TV%R9P*=mj0U@oa +Pa-_GY0kV=aiM`DbK/#Sd;30"?.-s=`lH0?`P][=c-4>M^U/Jg7n6<OZbt23$-C?3^6MYg6;its~> +&-(M:s8W&ts8;corqZBhs5O"gr;6Els8;cls8VHDn`TrPnGX=(GZpA-eG]FDs8N&up]'s[<0<K5 +SsGP*QMm*KPj+GCPa[o%Q'[Vr9`Fecs8W&mrWN8tr;Z`pru:X%FK0OQEck'Fq>^0gs8DurrVGHk +_o(%&rVulr&HDY&oYQB/F`MM>ASG0T$3Kbu$4'XRBl.<@&c`(<qZ$Wu!W2p.!=)S?Cj'W%-O0YS +!<<*(p](a*#:=&(Ec$,]eF`e>rr2p"kj8*Drr3f5s8W#qrVt_CItUfcUSUc`n,N@ar;Z]jrX\o+ +o`+jbrpc4`Q^!MqP*Y'l)O$8LQ]IK'CRkG%qYg'dq>C'fbY<I8qYgEnr;Q`rs8N&u$N'i&nF#rB +jjF,.df'URrqcZppu_)7k5Tr~> +$HAd<l2:JXrVlirrr:pUrr3E(r;ZfrqtS1'X0(=Unc&Re)Ko2G:"B:Dq>^Hos7lWeoi.$:PF7Ys +Pa.Q#jcpLDR[0/&Q][D%qt9pfs8N&urr2lprZ_C=r;Zcrs8MVXEMdhCEHOjAqZ$9hrVQWos8:fp +`5U:*rVlcrrVca+hS@%H`5TU-aLZS@G'J<0H:rU1H@^p6P)m&h]#2L`IrTa]H?adcI!L'aGC"gr +O-,:;_Rn"3_N/e^Jq8#hIs$'bI=-?hKSknPR``Xf_8a=as8W&srr)]UnGiFcs8N)srr3Pd7!sJ[ +4JJ]Lr9jU`r;HZorr;rr&HD\.p&Fsbs7):^PELojPaLBo)3U>QNgH2KR/d$Zrq6<hrqcW;8pMcX +qu6WorW)utrr2lrrs8MK['I9HU%A0-rWiK"eY/J(U!%r~> +%te2"W56Ek`m)cJ`QH?E`o5#=`XL#2`lQEI]7!=PA":=(a<8a^?UT>qXjGP=c,drG]ZS:D4FW0N +SXGb0PECukPF%X#Q$nmcQBRT#PDhETcd0eS_SsO;bg"ASaN2TF`ll<?bKe=Z@%2'tD/D=_d*]YR +b/hWBc.'bC]XYT(bJq]Ia2uKMgsXsHoCVePpAaou^q[h-a2c<Da2cBC`lH0?_nPI7o)/OJ_RID' +a2>p=b/h`G_ns:1aMka_qtC'i$2r)U]>r(1aNha'a9'>q^])+a^<?HLo'PScm+9A"aMuBL]tVV2 +rl?e4a3)EFc.'B[FbNsaSWkkW^<XpC`6-!:`Q$!Ab/hT<aLod?b1"OX;im9-Q]I>oifu3\NKocd +O,[+cg!%IT]?A+9cJ#H\Ae<VCbfe)Mb/hTA`lcQMb/V3%HVd+(93&F<dDuX:bK7J\<(KGVRt(~> +&-(J8s8W)us8;forqZBhs5O"hr;6Kns8;cns8VcFn`g)RrUKk)pj#,HK4FZNr;?TopAb0lDgI\2 +Pa%<#QBpQr$'pg?S!f5$QLanOrrW)tqt^49s82imrVuilp.M6_5>ZZ>6K\1Cs8N&ts8Domi5NUO +eboCGrr*T2qtTg#LO"#_Chmrf&.SsM!s/N&!<3)r!"'<=EcZ"S$Np\=#5\B;"UGA;!W`<+(.rUi +An2qk#QXo*!<i`6!W2p.!<<?103i@4G]o%qo`+mhrr3)am.gSZrtkY6s8Dror:Y\mN-mp9W,n+$ +r;Zfos8;Zk%f?;*s82]nL,=+<R$s/"iKY1IO-Z'#Q^3Xlh>I-Hs8)]moBK#:T(`-^!<<&trr<#t +s8NH's8VKSp%RIrs8UOHs8NB%s8VcSn*]9:J,~> +$-f3Bj88fTrVlfps5<nUs8W#srsAZ$ps>M2YhT$PnbsF%Gs68"@e]]trr<#ns8W"6G`n&LOcGio +Q2[*3PmNb@Pae)"QBq(9rr33#s8;orrr)fp,6.Q?qu?]pp[q(NVE@OtBKtVWs8W)ur;ZcrrSY]6 +`RXqcrr)orrVm;_^r+(._oC!0G^4R\rd=Zm(4:RYI"$^*OHHod`Q4^"G'eFZH@(0lrd#'"H?t!l +M2db0aMkp4LO/rH+F83SGBeC\H[9s`I=R<7UW(3gbJ1mds8W&srr)]UnGiId)?'U8rVuiqp47[J +G!C2MEfg=us8W#srVuoqrr<!.r;Zcrqu-PK1N\bHRZiroPoH6VQ^*u)PDhETr;?Qorr<#ikXh&/ +o)/Icrr;us!<<#ss8Dut#l;`PZb*<:o_[)9$NL,*s8(*9SXuM%J,~> +%?4b*TtnXe`m)`I`Q63ZaT'6hb/hTDc-!_V8605d^;TT`+O&/5-!P+Re'H@aai1g4dFME8Mi=!i +Q(XJ-OcY]hQ^?s%;3mH2S!f5$N7H8%c,[W@^rFO@c-4>OaNMWE^VJ(:cIXq>TJoGd?nTIEaN;NI +ai;9Bd`/f2]"?M9`lcHEai_rbdbF9_o_ACbo!c<I_o9[paTff-bK7lH_u@M@lMCP\hS-\C_o9O4 +bK@iFa2Ps3^qmq,`p<[)q>S4>]Y;1t_o0R7`Pf[0^qIFm_S"Ckp$h_6cg99*a2l9Cd(R08b5TI" +a2uKGbfe>ZBm#>a7!4u)ESJa`aMQ$9`l@tu'$A53^rOOAairCL*c7(/S;rVnj-:UJQ]%#jRZrh_ +,JMaRaj%ZBd*L*!L5=C1ccjPTrlPhp`Q$'Ebf[r>YB!B,9hJ[!_pZU5aihoK]o#c\7oc=7~> +"973/rr)lsr;ZcrqZ6]rir8uU%fZM.r;6Kns8:F:lMpn_nGX-oqi[7VXS`%is8N&upn:9BT:D75 +rKcK/%[33EOcuDc0(&Q8qu6Tkq#:9m+SYp3q#>huVenqIEGn)3qtU3ko`+sirVGHk_o(%&rVulr +&c_b'oYQB/F`D;/:`0]I#RL\2!s&H(rW5=c#8L'Y?9Ai("UG>>#R:M7!X]2@$jm1@!sTE8FE(h( +)[6TT!!!B:$kE^O"U>DD$O6q@+(]82FFK5!o`+mhrr3)am.gSZrrE#srY,8,qtWj+Jqm8kW2`GY +s8Dupqu?Kks8;os$haProU15HQ^a&%RGjDPPEhYtQ^!f*0erS*r:9d_r;9HOQn.+ks8N#ts8N#s +s8W)ursJZ's6B(Hp>FX(s3goHrs8N%s7,7@m,S+r~> +$.YfLhu!EQrVlfps5<nUs8W#srsA]&qV.C=YLi[Lnbrjpp%si7@]K>*pAP"!p7Fj8S!TA&PEV5r +rg)]3&<iEGOcuDc0(&Q8r;Zfps8Vrprr4)9s8)KiI"J),6ZR-a4n8LJs8VZis8N&si5W^Sec#IG +rW)oqrsdi#_o'I4^or-,E-6JNq04N9G'J:]L5DqN[@;JbFa/(SH$O^[GC+FTGB\:WIY*EfahYK/ +KQMKeGBS:UEHhD.(jU@MG^4jiOit\__SX.^s8W&srr)]UnGiId!<)or'EA%0qFYdWJl"_2W(64Q +rVufns7uZorVum*p&G!aR=K(=Ru`r+iKYLNR%0/$P*21a0)GVIp&G$iqbN$4.Gah"rr2rtrr2rr +rr;rsrs8D=[^<TFYOh\>rr2p%qT>M'StO_d~> +%@Ug<SA*"`aNVlJ`Q63ZaT'6haNDTFbfIP`7os,]^;TT`+Ni$Rfm/6LOkJC+dDj2Jd"XW?S=Q.= +S=5e.OcY]hQ'^a#&X/NHOcuDc,0@sJ_Sa4'_oBjubWEtgaN_rL\A>u&he@;+AjC9PB.2*M_T0s: +dDj,Jd`/f2]"?M9`lcHEai_rbdbF9_o_\IK\$<3J^:jKZs1M.@^qme"]=>D_hu;rj\$`od]tM1q +^qIFt]Y(kf\$icS]BoRpo;]L-\@];]^V.1l_8*h#]tLtc\?a$Lo_%_8cg99*a2l9Cd(R08b5TI" +a2lEGbK.oU0P,`j=$`LI1=+OpahYd9aNFJ&'$A;5_9's:bK._HBO@!pOcu)pj-;?_O-,ljR$El! ++rf=jcbRQBe(m39L_RGDc-"2PaiM]L`l?0Fbf[r>XDCU#:.f*,_pZX+aU$&0]S0<Y8Qi0G~> +"9700rVccrr;ZcrqZ6]rir8rTs8W,s!<2ut"Olo*r;Z9c(]+10/r,QWq"Oddo`+J[5@g.HNLuK$ +Pi7l<Ruif(Oc++)oDedcs8Dutq>LEnqu6U:qZ#5FWM)XdEc,JgrVHQjqu?HkrVcTN`P]UDr;HZp +rXf,,q"2FYH$+.@58bCX*#&n]&H*1X&.]<a',)*%>&#rC/MSM$/1`A'.Om#(.fLqI.OQVm*E6s" +68UPN-SR/)1Gq'J0.\V)0f(U<.4-KNE-cVZO4<h%rVlfr"6f+Hrr2rtrY,81qtg<eIq=:gJi[DA +O)Xphs8D]k&-)P*q#CBls8T*'Q'.DrP2VZ6Q][;tPa.Z!=$ogLrr4/<nnE?27"P(3s8Dors8Mur +s8W)ts8Vurs6/qCo\SO+s3goHrs8Q&s6\n9mG\(q~> +#25lNg\_$Nrr2lri;W`Us8Dut$3'l#jd<0Qde`q4rY5>2r@EPZ62('Qs7ZKa:ci'NPDYn0P5ggH +QKFG?Ruif(Oc++*o`+pfrVuco"98B!qu6U9qu>8AUn'\SEG];crVZ]mr;ZKjrr;rT`l,gGrVc`p +!<)lr%,Se;_o09TF*;eXG]`n/rH\Efs*=Wg'7YV>]on/2PDYNdPECobN/s-\NW"niOHPI2^V5nl +QB@2qS!TD(OHP`hPEM#gO-#ZmQ,1DY]#)8Us8W&srr)]UnGiCb&cMb/rVu\D@t9/\3+AeDDYa,, +s8Doss8N!"s8;lkr;Qu$=d5)7Q'C6m$^d*;S!&u"NDr2<l2L\jr:4KBNBr*es8W&rrr3#srVc`q +rVum'pV4/D[Ag\/r6kQErVlg$pr/quT:k%k~> +$`%KGPeP2ZaNVlJ`SJW8`XU#3aN2TH^nOG)?AQ85n]2fjd+&eWLbdf6e'>nWa#PhZR@',5S!fV. +PECrhPEhL!PnBLIP+@YjCi@PD`4s=-`Q6-CrldFG`lQ?D`PBL1ftKbGS3:(nCKrsQb07]>cbmc@ +ajA&;^V%2/bJq]Ia2uKMgsXsHoCVRrW3*;8['KY>rO*QP\[o;YZEpmsn%lQRd*1"dcHjbYbKeMY +rlPqq`l5m*kOeGg_TU!@e'udnd*0h_rmDY5daHIeb/WrBpZq"gm+9A"aMuBL]tVV2rlG,^0$2>X +aNi+?<.BaZ4^O_1=k1U9^r+17bf\#HaNDZL_SsC5aiMl^N_GP!Q]dDnj-BY.s,8P!Q^F5%:Gk2X +hqHK&c;&&+11\SQbK7fF`l?6IaMu<Dbfn/BX(+di9MKK:`R2a5ai_W6Io8s6>do4~> +"97*/rr2otrqlTorr:sVs8;oss82lrrr3)KnEK`Is76.*rV66X4Hc:$qXs^_oM@_)B9JRER$Ei& +iKXq8S<K5(R:)Wcq>UEkrr;olrZhI>s8Mrqp19Si>XEFODaDV@r;6Ejs8DurrVGHk_o(%&rVulr +&HDY&oYQB/F`VY:EGT?&A8(sR!+u.Bs(3iqC2%6o5&4nJ@W-$lAnGdnD0'`4ChdZtC2%Bo@Q/FQ +FE;&1C1UshBkqX+D#S,\Ci=6-A7&A#F*31bOOWq&rVlfr"6f+Hrr2p6rr;rsq>C9ejZJ9OK0_MZ +W*@mPq>:3hq>Lp#rr<#os8D`d`E/=kOID?kPq\DiP*_K"S<T=2FC4[goD#FeQ$R$3s8W)rrVuos +rVlisrr2rtqu?]ZnFQ2+jT#8.rr<!(qu?]`jQu9ms*t~> +$/MAQf_YUIrVlfps5<nUs8W&trsA]&rp?)TXO$eDo)A[h(]4-u2iO1gq=XU_ohRV!AWW.<Q'.5q +Q2[*2Pn/tHPEhH%@%[Jqs8W#ss8Diorr4/<s8W)tp0s2[=$:MCDF)J?s8W&ss82iqs8Clq`5L4) +rVlcrrVca)hS@%H`5]@+_SF%'`r<gT`;IMF`5T[1^Ve'U_T0d2`l5a3`5BF.`PfO/`5Ta9`P][= +R_ukVa1fX6_o0U5_8=++_Sj@-^;.\-ahOCc]uRUsp&G'jrr2lmk4&EKrYGP4s8;osq;sbjJ:KjD +O/#e-s8)]oqu-Kos8Mutq>UC%qZ$TmpVp3tQ]R`%iKY=GRZa#%PF%>n7W;W'dI[.7;NZ-4nc&Rf +r;Q]q!rW#qrr*?(rVulj]XG2QVn`!(df'UPrr2lk_kEZpU#LS~> +$*7lKOhA]Sa3;d,`o"l:`X^)4aNDZH_l?I:>Ca<)`q.7h`l,a=cnUKA.b`4ue]fd#.VP*8Q^jJ/ +RZm`5"-]":Qg'c2OIVMuPa>^;e\T5I^r+42aND`Lb/hQAcc3r=^WP&'O/H2JDJj8LYKb/,_o9pB +`l-!G`jidr]@G*Eb0%cHb0Skkg[Oh+q!7_Jp%S1Xrql`lrV/2FrVcWgp\2Soo(DGKs82Zfqtg3i +rq?0`q"aa\p\"6uoC2AFnGE(VqYL!Zo_8.WrVulqrtG:uc1UK"h9YH>aiDKBb0[i9aiaV(0?VJ[ +c,IcOb/>ZWL5//TMkE_Qd(mB=`QZQKaMu<Db/;6Bb/)0>`m(DPOI;9"OlDW\PE1ulR@0G6PES:C +8_LDoe;c\GC/3+%bK@iC`5BR<ccX8Kb08)N^8>4/6VC.!]Z&7=#g(&rHW!L3@D@<~> +#QNK3p](6mrVQKnrr:sV"oSB"s8;fnrs$j<l14lRs76."q>^BiW/d716+=p]1R32_qj--)%[N<A +R$X+7]DDR-rr)irq#2$.rr)iqp:t.8O@=2/E,Itpq>:-jr;Q`rr<W8X`P]UDr;HZprWrQ$q"2FY +H$+3-FTQW)Er0kVErU2LH#@\ECisW.CNFB1EclMHEcQ;GG^4OYG&VPICi"-,?#=D(H$"4LF)u8< +F*2PHFEV\FF*DeFAn>@aE-chaOOWq&rVlfr"6f+Hrr2rrrr)a*ogXRcK7enGX.<Vor;ZZloD\df +#PcqCQ'[T"P22E%Q4K1.<-Oj377:@KGW,HmrVcEgs8NH(s8V<No'b<%s8UOHs8NB%s8V3Dlg3O/ +J,~> +#j8(]c2.D=r;QWoi;W`Us8N&us8<3#p6r%`a85`)rXf,+s8;YfM3O/f[`EbNP]TXsPl?sIQK=A; +QBRK!Q^:O]qu6Tsrr<#qrr)lsrr<!=pqL.1Ma2,tDf%emqu6Wqr;Z`qrr;rT`l,gGrVc`p!<)lr +"Q$r3_o2MkpV[W\`5o^6`kBF8_njC9`l#^2rkph7_SO%(_8O.1bJM-9`Q-?:^r+%0_8F10`P]U3 +`50=/`4j+*^rOX<aMPg,^VBIAs8DrrrVG[Gs7uZnrt,2(7Y#o;J:p4bQsKUhs8N&srW)uorr2p& +q:S9&Q]IT"h3Ir'&<VB<FdZ,p6<T[u2#?tFrVl`ps8Dus%fcP+rVui\]!SiIUsJl8df'UOs8N&k +[\TIdU$I4~> +$G(.]K>#7H`luTHrl3m;rl4uZrlPPe_R<?I=a7Ho`q.7_`k]a>eX2&KJL6hg@N0o=;uW-`R0/e@ +PEZ!."-]":Qgp@@PPpdHQOfCGOHu/p9<?Uab/VE?aiOG'1!%AR`m)ZC_8s`n;l#RHEG]K*27h#N +`5fmFb/V<=cG[6-]Xu_;`lcHEai_rbdbF9ioD\C^pAXjdpAadbo+(-\qXjgdo^MJDmdTiAp\FFr +p$qeQnaZ;Cme>r8nF6/Bo_/"No^VqL)tW^qp\b$er;?9^o()51cg99*a2l9Cd(R08b5TK\b5TI! +c-e4iJVT#76Dou7e&]VLaNVlNaMu<Dbl,ZlaMu3Acal0!R?X,'iKXJ.Q'M?8.[cWdGtMe.4Y/$I +K4H(Yc-+/M`kfC'_p-TOaMu<FbfIDa>"1kO9T$R'd`;d9bK%T0E)fP,ABTK~> +#liQ4pAb-lr;QZm!ri6"iVj#Yrr<#rr;HWtdHp2hrr;Qg&-)M+qt*`HS=3\\GCkrZIJ]>ePms.I +Q&gr^=o&'srr)irq#2N<qZ$Eer)05l6$79iF`082s82Zmq>L6krVcTN`P]UDr;HZprXAi(q"2FY +H$+7QG]n90FT?L^FoHOrG^4FZG&_P8=t46-F)Z8HH$]I7!."Nh/U;YaDK'T4B-pr.Is,p[Fa84S +F*;_LG'eLWEdi%KFC?@HE-?GTJ</4Ps8Drrrr_KOq#:9mrVlcn%,X!sKSkJ5G)WA1[/'^uoD\df +#6/F_R?F#&gm.i(&!N5GOd))oPFPNpdIdJ<rUp0irsJ](s68tCn^mO8s3goHrs8Q&s5W>/lJMVl~> +#j8([b5D5<r;QWoi;W`Us8N&u$3'o%pme@d`;9E%rX]&*s7u4\2jp%9:j%;K;g\D+s-<SLj-:(A +QBdPmMH]lUs8Murs8;loruq7=qtg7fSuOnlDfKl:3V3:Nrr;fkqZ$QprSY]6`7=hbrr)orrVloT +_#D7M_YV.a_Sa:._S*t._oKX0Nk`QR`Pf[2_u@LS_8*kc_(rsG^r4@9aHX]b`k]F2^VRe)`5BL2 +`59=,^W=.)bJfI.dE'/A]YO4?s8DrrrVG[Gs7uZnrsetd2h?L8Jph`rULCP,qYgKpq>U?m#&ACL +OdVH#h3Ir'"-Ja3Nr>%FRS\.Rp&G$irqufrrVuj,s8Mrps8;#g[^E?4f_k]rrX/W(s8M\tURdsN +m=5~> +$GUXeJ%inDaNDZHrl3m;s2GSgaN2NHaMu30<a8aH\AZDXa:Q\9cHt<1.#<LF6YUXt=+HY8Q2d'I +OTCZ2rg3/?s-*DHs-F4\R?WnnMM4[Nb0.rLb00b+1<@JS`Q$-Ac,.QP4-cs9GB7\AC+I]]`50L3 +b/_N=a3MW5^V%2/bJq]Ia2uKMgsXsHq=FRWs7?9\&b#,KmI9`Gp[Q#fo^hM<mI0QAnc/%gnal>? +oCqqL\a/n[mHsT7rq$0[+78CZm-<s)q===\pUeEDq!dq7cg99*a2l9Cd(R08b5KE\ar/:?aNV49 +G_(j2J9?jE:6<W=a2uQLb/hTDrQ5Snb/hTBb197#Pa7o,QJe&)QRJ#\4c+rIJUN/0>dDW(b/_ZE +^V%.oc-abV`lQBJaLd[;779gDQ,:Pga9g#1_R+)Y92B3KJ,~> +&-(>=o)JXfr;Q]nr;Q]qs5!YTr;QZp"4lc)mJd.VrXei(rVlcq7pUe3NL$0#3K]W]PlR!HPQmSE +Le[XBs7H:(pAadbrL7W*HphdkG&B*3b4ko1r;Zfq#l<Ju_o(%&rVulr#ljesoYQB/F`mP(!-S9a +rHJiuH?jXR@SdaQA9E'9Fa&*0H2r6hGV48`I<KOM@lbS?=`o"2GC"IZH?aRUF`V\RGBJCNFDbD2 +(GoT9FF&CqeF`e>rr2p"kj8*Drr;rrrVR2X4bAH;M1B/2TVl#fpAb$err<#qrr;m$o1b@5P`qMs +iKaA-rKRn\PtlXmQ]ugd`VT9-q#C<grr;orrr<!'r;Zf]n+-)!rr:FG$NL,'s8V'@lfmL1J,~> +$1=df_YsB3r;Q]orrN,tir8rWs8EB*rr)fpq4jml^\@6s&,6,&rql[`>D&&qP+7[oO8G4BQJn)/ +P5^[MS!o1/p\k-frqud0pAadbrgIW&GX?.aF_rm1b5))8rr3B)s8N&si5W^Rec#IGrW)oqrrLul +rknTL!5nQJ&AuT/^lF5b_Sj@1`50:*^qoud(;[Z&_SOL9V2^2Jahtp4a1oF*_Sa:0rl#ej_p5g4 +aMO7#TuXsca2#Oas8W&srr)]UnGi=`rr3Q/ffak<H\[&[8"?D[p\=derVlis#6+T#rr)iqrr35q +9okR'P+%QmQ2QsGPn97F9R2nfOE^03qY'sds8Drps8W#trr2p+r;HZniNp&'Z(1"WrR(TNrVulg +XeVGVWUkW~> +&'K6%G/(r:aNDZH`l5s=b2UMB`Xg&0aNDZH`lGf%>ZbaJ`5_Di&B_u;a3<)m/4=E.Kp/'k3fs6& +s,m;Es-<SMnWj-<s-<PL$BgX:P*VAc4OM?sr652`1W[SU`Poj6dD4&WHWd+h7rNHiBe;TIa2bs8 +bgFYT`5g0A\A,\ge]YtTb/_WHceQt'nG`%Uo_nC\nIb6TlgafGo"Va,q"4(Emd0?2rq$*Y&+92a +oDeO5\Z>)lo^;;Cn,DqYnK7/alKdQrpZM8Ho>7r[oC)2Aj3R)DaiDKBb0[i9aiaP&s2tA_.E9T: ++`r<dN.GM6S!H:ba4&5Ubf\#H`lQ<Fbg"AS`l?0D0nPOTQ^j2sQ2R'JPpi&b9m)PUKkT,9fZqma +c,n,J^:Ltnc-abV`Q$-HaLR=,6pjdCUrLF&a9p,2aMP8o;G0i+gOK~> +#63T<m/Qq^rr2rqs8N&uh>RHQrr)j!hraCkrr;Qgrr3E*rqH3_>A\SPNIj`ifp)l(SrT/!O-i3+ +r;?NorV?Hmruq=?nO0UU2-OsCD0'Ya^[qL'rr2rrs8Domi5NUOeboCGrr*6(qtTg#LO"#`FnTuM +G]n=VHZF1@;%EaA@!-[9F`qtTI!U$\F`hkPH$++G@m:b6)-q*#G'.tRH?sgZG'.hHHuaXRDJW`4% +2q'/FE_PNNR[V#rVlfr"6f+Hrr2rrrr)a*l:->[L4Y#-3..T@Qi-[Uqu6Wqqu6Wn#PUoQR?sA)Q +Jn,-QMm'ZN1H.l>[9][q"aabqtU$fq>UEls8N&u#Q4W%l0n37dJj0orX/](rVuoSl0R^%s*t~> +#559r\GQ+%rr2lr!WN&Wrr2rtrX/])rVccmY,&83oC)\Ys8W'*p%\8cCil#%J4H"'QJe#7Nh28t +OcYtspA=jfs8E)urr2`n&,ZCs7'<.==Di7tEc4:Zp&=t#rr)`orr;rT`l,gGrVc`p!<)lr"l@&4 +_o0Ic_A:&+_T'@0aMEpqOM/HI_8O=0_8*k'_Z%F^_Sa4+a2b<DK9XNr^Vp,hs1nZO+2c%9`Q#R7 +_SsX<SVWQ-_TKj2`PM6Is8DrrrVG[Gs8Drss8W)trt,1s7t6/EJ:N))Gbf2BrVQNkrr<#orr<!' +pe?a8Q^O&)iKaA+rKRqORuoX4>!G(Bq>1-jqtg?lr;QitrVlfr$iKu'r7eNe\$;Cls3U`Or;Z`a +W1olRYkNY~> +&(Q89Cq[a0b0%fH`l5s=b2UMB`Xg&0aNDZF`lGi1=BAq7`5_Di&B`AGai2KJf%WPqDjZW?8='+7 +s-*JJrKm#=s-*JJrKdhNSrAqnMNKR=bPocdbW*_eaMu6=`Q#p@d*(%e/>8Lf>An\"DJCts_p$$< +b0A,M`5g0A\A,\ie]YtTb/_WHceQt'nFQ8Io_nC\nIb6Zlh1,G^q7JWq=jIKmd0E4rU^'Z&G,Pc +o_eOA^TkNGo^VSDnacYM+S"pflg*O$lL=K>ag/\/nG2bBkKiMHaiDKBb0[i9aiaV(s2H,$b/hZD +bebcKJ;8i0IlDS==Ei<>b08#LaMu6@aNFM+$d-Q1b0DViPaS,+Qf45/QS"JdPEhDmSrts1;)BZR +e'QF_`5^0H`kT7&_p$HNaMl0Cc,dGN90kpB9!Q@Td`;d=`lGit?r0NoHJa5~> +%0,AIkl:V]s8N#qr;Q]qhu<WQ!<2rs"7G.9jo5;NrX]&(rVuoqs7ss$HTX>QMNc_Y$(I0?PF[ns +5kb-RrW)omrZhI<rV(kpVf#.FDes`<EA[7dr;6NkqZ$TorVGHk_o(%&rVulr#ljesoYQB/F`[4u +(3XhDF`284<YPW<#[VRtGBJ(OGBnFVrGsT6H#7J54V7f0&R96tG&D2DH$ORUG'.hGG("%@Cg\Ut +$3r4tF*;VMN7@M"rVlfr"6f+Hrr2rrrr)a,pd&\MKnG2.7nfb\7dU-Sr;?Nms8Vuqs83-$7@'$t +R?!NjQ2R$IPn0@JP(d#=p%eF[qZ$Kks7?'cs8;ors8N?%s8VKUo'b*-s3glRs8Dors4uo*m.:7-~> +$2Cs(ZhjV"s8N#ss8W&urSmhRrsJc(rVu]-T<>NfrUBdtpAY*lr;ZT=O*j&L4c5JiQ2R$+PmNqE +O-?0"N^<F;r;H`qrqufrrXf,)qt,AgUhr_@DJON8DDUk^rsel"s8W)urSY]6`7=hbrr)orrVm#W +^r+(.otqEZ_ns=,a2PlVNKoI9^r!q*`PVVj!5e]Q1rIAK`lY?BN15jK`P]a3^W41,_Sa7.`Po[: +]>i+;Sr8bhU<:Ko`59@`s8W&srr)]UnGiIds8W,urr3K-qa,"LK7Sf(6V*rO7d^0Sp&=sj#"Fi< +OdV;siKaA+rKR_ZPE:GtWV$#^r;?Nn!V?<hs8DrrrsSc's819N]!nf3pAE;:$2ji%kbXuES@A?F~> +&)<+KA\,n*bK@oI`l5p<b2UMB`Xg&0aNDZF`lZ#H<E*/"_8c)f'$AM=`Q??Hf%$sHC,A"=LlRU] +rK./FQ'M<7mZmg9s-<PL$([<?OdV5a0@.f=bVmSa`l?!;`lQ6F`mW=LELUW2Bl%L+C2"j8cGdZE +ai`#O`5g0A\A,\ie]YtTb/_WHceQt'nF,r]n+QPL_n<q#p%\:PnaPu9oCV\Qo/la;qu5Kg]ZIh\ +q"OLNm.KuAo^h\EnaG`5jmr9CagJdgchmM0n`.s^f?)(S`lcZA^<+O=aMu3<aNFM'&^8TH>(2-X +Km5pQS!u%Te^2J:a9'B&aSs?^a9fl/eL--1Odh>oiKaD//X;N`Q'Io*Oap,oi8)l,b0A#KdD*cA +_o'I7b08)N`Pp'Gb.2sn5XA1A\AZD8a9p,1a1nKU:J4W;j+%~> +%0,MMkPtS]r;Q]nr;Q]qhu<WQ$i^2+r;ZfPmcFEIs76."q>^Hoq#'pco_n:O=+m!(fp)o.Pa@r" +S;p28rVuNh'Dqh0k"i%E:0h"EE,BVO2u`dMq#(0lr<W8X`P]UDr;HZprY,>/q"2FYH$+1NF`qnN +F`qnNFa!_+&T_u+=V_/F!!cbLGB\4SF`hm)FTli+E+qiXrW"5Q??:71EH$)GH$4@UG&q_LEcPo) +.gZ@Z"?:.2G'\=jeF`e>rr2p"kj8*Drr;rrrVR9'M`urFLPBDOVe`5cHMmO8r;HWps82fqr!2lh +Q(=,,PaUKqrKdDI&!<-CPsO^3o_\R]rVQHbs7uZor;ZcrrsJ](q=*kBm,%dAs3goHrs8Q&s4lf( +m.gU2~> +"SKF'YkS.ss8N#ts8E#sir8lUs8N&s#lj_JS?9*Yqu-*b!;HKm$i0_srqHHbp/cp9P5(=BPiS): +PE_E*NLc,'q#16jrqufqrZ_7>ro?bOQVCagF)Pl70K/q1qu$Kor;Zfrs8Lrr`5L4)rVlcrrVca! +hS@%H`:CeX`5p$9Mi![`NkiKK_8F4._8?)e'#_]/ag7.dO,Ae7`kfX4_o9L/rPJTQ)o]V6aiU-5 +OH5C%b.>C3_85gEs8DrrrVG[Gs8Drss8W)trt,2-N'2lBKnX)HUhHTXHMmU<s8;irs8Drrrs/5m +PFRi)QCHiurKR8G!0R8G$:!eOpAP$gs8MujrVufprVm9'rVu`;ZamTDVYU,8rWrQ&i2!'<S@n]K~> +&)<=P@(=A'b0%fH`l5p<b2UMB`Xg&0aNVfH`lQ#_<)H_h^W,ic&&cl8`4s=8eBHRoiDkVtN;JeC +Q'[i*R?s3<POXq<PQ-pHQO9"BQ^NYrLGmH"bPfQaaN"4u1WIMYb/MWXb<;JY86&N)CM7N5,hU;U +^Wb'Pe&T>Gbf%$+]Y2k=`lcHEai_rbdbF9_oCMMPo+1Znp;"8X^qKC9p%%YDnFHMKs7--\&Gl=f +_RR=i\+falo^M8;naZSLs7%?*me?PRc+:O!\_?uKnbD(hm+9A"aMuBL]tVV2aN2B?`Q64$a:leF +Cb's\L4Nc<T4=C6@+NKA`lA#!rl4oXs2GAfbM%W9OdV>tPMVQTPEhE"PEh>k0\"t,cH*lCa2l3H +`l5s?bfn5Nb/hK>bg";@F\+e`8mAmFdDu[<aMtra=\MIeLuj-~> +%0,bUj8]/Wr;Q]nr;Q]qiVjDgrquZkrr<#ss8Ud>jnJfTo)A[h!W2iprs8DtqsjMBO-Q+2PhhT7 +Q]IT%Nf[/8q>UEnrVlikrZ_4=?'MQq_Jr[uF*_ahd.I/6r;?Toq>^ElqV]?1_q"\`s8N!2s82T` +_M<DZF`qqQG'J1TG'J1TrH:YNC0DP^#6b5A>]+Y+H$XUUEcQ;GH$OXWEb7`W!sSo/'k;<,EccDD +G^4OYH$OXXGB%V80Fn6g!sUJqH[9aZN7@M"rVlfr"6f+Hrr2rrrqu[*nO%b^Jp`<&H:2M18D=(@ +r;HWps82fqr!39!6^!LrP`Xjh".#=?QMm'ZQ^*f&<P/8/s8)ckrVuZkq>UEls8N&u#lakoo'Pu2 +li5?2s8NB%s8Cg;m-O]NJ,~> +"SK^.Wpp#fs8N#ts8E#sir/uYrr2rrrWrQ#jI**Thtm<Crr2ouqY^?m#l=T$q#3=8QC7];rg!GH +rg!MLl'2^EO.)GsO]/1Srr;urrql`qrZqIArqcOrOK;O#EEI7%H#>ajo_eahr;ZZfs8N&ti5W^R +ec#IGrW)oqrrLuloYU[GrPK>f`kmdkNK93`_SjF1_8=%+`5TX3rk]8bai1KHLmOWkNlT&N_oKj: +_u@OQ_>h@k_njF6Ru*,jR#dlY`5'1+_=dj.rVlfpqW@;IrVlfr!<2ut&,uV"6@4N>H\Hrp5\?$H +gAV'Lrr<#urqud#r'?L-QC!foQ2d*HPm3J=Q'7S7]`.p?rr;rss7lQms8MuprVl`p$iKu&qSKYL +\>-D+rR(TOrVulqfVG44SAG)Q~> +"l>\P=g?0Lb5]Nc`l5p<b2UMB`Xg&0aNVfG`QQ,s;,C;[^;fcc&B;c2_8FC>f#u7X`7Z`%Od,a. +!13YP"dbL<OcbjuQ2d'JQ2R$ZR?*f#MMk,jcH+,Ka2l="`AY`Wb0A/OaP04?WD^<?:24WfBf3NJ +a2l6@dF-.W_T0m=\A,\ie]YtTb/_WHceQt'nFQ2=n+lALmhG<`q=hb:^qROro(2MCnac8BoC;AL +mh>6boA73h`6#U(q"F4Hn*TE-mI1#D47i.=rqt0V]Z%e%de`k5mc;^\f?)(S`lcZA^<+O=aMu-8 +`lQ<FaNW/^0Q_ttGCXmZ4_'1%[aE18`r=$l`l5p:aN2B?`QHcf15_!SOGoC^Q2[!IPpr&fS!B%n +5FpKTbJD69bLFPR`Pp'Ie^;IWb/hK<bg";@C.g]X885`UdE)@1#fXNB>"hRfNTbl~> +%0,kYiW&rUrVlfor;Q]qiVilXrr2d&rr<#ss8UU8kk>&Vq>LBlrVlis"o\K!s7cQlq??nk?^?kA +rKQ-'%[NBGPa?cCp\Opirr)irq#2$,rk;gCO$GooF`2>?Ak)[tq#16jrVlisr<W8X`P]XEr;HZp +rX&W%q"2FYH$+7Qqfr*cs*.+YF`VG-)@-]O!!Wd9Dfp2KH?=4KF*;eSH?aIF7i;L7!!!6>@<Qs> +EH?;JG]n=WH$FINFCdBE$O6Y3#<$FFI<^1"eF`e>rr2p"kj8*Drr;rrrVR9+o6tD&MM>&,?"dLn +Q!4"]r;HWps8)^#r;ZKe6C*t%R,O>0QMm*KPRX%GOaM6Aqtp<iqu$Klq#:6is8NE)s6fUJn`'*= +s3U`Os8)clip,msrr7K~> +$2_o>V!%aTs8N#ss8W&urS[\Rs8N!'s82>TX0^OUrVc]qs8Muts82d+rVucpq#C9irVunn@[E:F +rKdJKr072Gs-Di5$^R!CI<t\ds8W)srquforWW9#\mD@or]_9CDK9Z-7/R#]s8W#prr<#ts8Clq +`5L4)rVlcrrVc`shSB!*qni?Ms27UNa,Pk<NK09^`5Ta5^r!t+`5KR1_84",ag.(ePE1ZeN5NQM +`5BX:_ns=._84"+^raHcL5M7VOcQ<U^V7S&_=dj.rVlfpqW@;IrVlfr!<2ut&H;_%I:mtbKi1`P +A6C:D=o/*srVlWm#QFGn6^F+(RGjD2PkpXLPaRf!HZ\uZrsJc*r;Q`rrr)cnrqufrr<iQ#]<nuV +TY1.#s3glRr;Z`od\NM,T>ph[~> +&*0Ni<2IUSbK@oG`l5s=b2LG@`XU#3b/M?C`O&K>=-:/8rQ"uYprEuc_8O79^WOaC`5TuJ;3Ht: +Pm`qHR@9P3Q^*bsOd#@$rKI8Hs-H6EQ^3\nDeRhIa3)KDaMu-8`Q$!Abfn5Mc^dk/ME3[RCM@[$ +>W(Ei`lH3BbgFhY`5g0A\A,\ge]YtTb/_WHceQt'nFQ2KmJZMPmJlWSnau[q]#DJ!_6rh*oC2;@ +oCVYEn*fZ2nalM5_7IIs]Y_>Rp[[e;m-a90nal;@n+$)NqprHqa1]=(g&1X;n`A*`f?)(S`lcZA +^<+O=aMu3<`r3sjbgY!S>Bu!V:ek2(=<`J_d`VR/"3S^(`VmgU`<jW4dc*-EP)PNeiKa>).[??d +S!/V?<6NG&_o0L;d)sGK`lui\dE';H`l5sAbf[D&7Qa46GeD#8d`;d;cG[JV=%l:jQ0a#~> +&-)=`k5G>[qYpEir;Q]qs5<kVr;QL#r;Zfqs8UU7lKeKMrr2rtrr;luqu$BkrVuco#lOT!pMkD- +PF(g)#EbF?OI)3!PkgUEQOK.DP*2#mQ^*r%R;r*&r;HWnrtbP4r;?BgqYF![X@d;M>t8mUF'`n\ +r;-C#s8Domi5NXQeboCGrr*9)qtTg#LO"#bG^974%!d/EH?jdTFDtM!#m:,+&dqucGB\:UEH68K +H?OR^D/Mi_r;[W9$Q!5pH$FLTF``"QG'.tRDfB,F'FG-F!"9/kCj:ARIuVtMs8Drrrr_KOq#:3k +rVlip(B4/j>_\#fItiH/K7#mkZ2".ms8;`nr;Q]q&H;V+q=Kl9QBmf'OI2>qS!*K1"IG:/PaV?4 +rg*SLs-*ePQBIW#OA>HGnbrsqs7Z3erVuodq=3h%rr:CF$NL,)s7YUBm,e9IJ,~> +#l`JKT%s5BrVlcq!ri/si;WZSs8<6$qXgP_Y/gP?rVlZns8N&sqYgd#rr;h;H@_9Hqj%)Drg!ML +#EbF?OI)3!Pk^ODQ2m3KPR3Y?QB7DOq"t*kr;Q`r)#jI5qu$BlrV]H]W((K?>!m+DDd7AZs8Vuq +$NL,*rSYZ4`7=hbrr)orrVloT_#;1M_Z.IP^b!7:_Sj:3aME^lO-,QgPE<W!_nj4._o0I/_S<t. +^<!RDLQI[ZO,](:`5':i`$<";_8F+,aMPs3UPF\fOcY]aUW(!__SO(]s8W&srr)]UnGiIds8Dus +r;R]3N`q'eJp`6#L4Xb:?Es>(s8W#ns8W)ts8W&s&,Z;#oT>E)Q^*r"R$Ni'P4k.DQ]d5jRJE-I +PQ@&8rg*nXPF%Mo:A+Ydrr;rr!<;rq&c_h0rr2ros7`q,[C2UVq#CBBrX/])rqa^3T:DM)qg\~> +&*pZ/;OP8>aNVfG`Q$!Ab2LGAb5]I!b/hQ@`l#;m<`XR]`QH9C`l5s;aN2NHaN4A#r5eo\#Kb?= +<+gK=Qi<3KPlR0KR1,FIPECugR?ir$PaI^2PnB=HOcYWdQC+22R>Zi"d`oqUrlfl5`P]X6b0nJU +_oB^C1m+\)A8+t-Ecc+l;p<D(b0%fHb0%cDajA,>^Uh&-bJq]Ia2uKMgsXsHoC;56n+68Jp@RkC +mI'?5p@>i2_SX4-_7fI6o^MDAoCV_Io'Gc9mJ>kb^;\+0`4rtYp$V55lg=0;p\4:Ln*Kf?f=eou +`"g2,^tAV[oC(_cm+9A"aMuBL]tVV2rlG,^s2b2Z0ZqeoFA74=M2..HM1Be/:R02F`lZ<?a2Q-B +`P][6`lQ-Ce_5\9NffNmOI2>qS!*K1"IG:/PaV61%?lp9OHGlpS<AFYbK@p*`r=*_aMu<Drlc"r +`PKR5b0e8QYu*\J8l(eb_T($F$HpT5]6d@K;dccnJ,~> +&-)Idm/6n`rqu]kqu6Tps5<kZr;6<cr;?R!d-0fZs8W)ts8W)ur;ZWpr;QZpqYg`sr:a]MHBXT` +Pm<eAIr^j;QBq?3!gAk6rg*SL$'CR=SNPI&rVl`nrr<!7rql`nrVufqpR69/G[#6-FE;VIG'N?K +q>Ld%rVcTN`Pf^Fr;HZprYkh6q"2FYH$+7QG]n4PG'J:WI!KsS@q$>`"8i-3$X[t!GBe:OF*VtQ +IX5pP7Ml=-!#>_I(L_E2G]n4QH?=FKH?X+IA2Ol)$2ji4#rc[EI!L4$eF`e>rr2p"kj8*Dr;Z`p +s83Z.oLjafK8GD7J:<<.<c(V0s8)`jrVufpqYpuu<0i]6Oe%`%Od2)sq3;2LQ'mi!9nJE$Q2d0M +Q2d*KP5gXJPE_7sp&+C[rr3?#pAb!fqsaIRm*GY1df'UPr;HZbk3_Kns8RT~> +"omSRT\'&>rr2rtrr;rSrr)j,rVZZmp8G!n^\ds.rVlfmrrE&srVZX$s8Muqq."o$PEbs0rKR2E +#Fgm+EgDiRQMHdZOcl#sR@'>,OHtus2q%[(s8W&rrr**$rqcZlr;Q^.qj_f1FB3<rE,T]6Ed-pL +s8W)t%KHG,s8N&si5NUPec#IGrW)oqrrLulqSQCO_83q$_nsI5_T@drO-,TgPa%6E_o'=-`5BO1 +^V7b,^s'!DMia9hNfK'V`PfO/`5KR3]uIV&`P'U;TneSjOH>]gNM=G.^V[h'p&G'jrr2lmk4&EM +rr2irrqud8qt3U4J:E<,I"$HuKN2b]r;Z`qq>L?nrr2rtrVlfr%/3\bP*V6$Pa.ArP*l'1#F(LA +PEJXlNqnt?PlI$KQO0%GQ'.;pO?rU?nbs'ts8W)up\a9`ZF.*2iqrc'rr<!(rV=:(St)G2rdX~> +%.:u?<Kk,9b08#I_oVi"ilE=dbfn)HaN2?>aMkf%='0FN`QZKG`l5p:aN2NHaN2B@b0'\($-('0 +dF(O'F-DphP6.#9Qi3?PQN3<MP6[S?Ir^j;QBq?3;j*?,OckooR[BV-OWgpP`Q$!Dc-4>L_ns:: +c-4YVbfP'=Vfc0ZB5MU6G&Ls3b/VHFbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_na5`6o`"Un +o^VJ=o'l)@]Y2+trkrZi^[q0knF?)?oC_YAo^V>Gho*=NcH*o?^V':5nEoQ/n+H8Ln+cM9p[utF +]u7e)`koIBqt9RLj3R)DaiDKBb0[i9ai_]Gb08)P`l?!;aNDa\DL$bnP)G0FK7Hd.3S;]uaMZ'B +`lcHD`Vd^cbgP$*LPh7USWoD%Q'.O1Pm<P=R?Ne.Jr]Yls-F4\PE:fbOHc&uQA6p5b0'=s&]VW+ +aihuH`1Kaa5#,(S]YMM7a9p27a1H=c:KM,<m!o~> +"TJG[m.C;Ws8;oos8N&uiVj#\rquZgqu$HugZ7h^s8W#prquZorr)lnrWi?!oK\:dPEta(#Eb7* +2ij&fPPLIUR$X)&PEV/mSW9,)Q2gRXrqu`os8No7s82fkrVc<S:SajRE-ZMBG&__H@Q*rUrX8c) +rVGHk`5L4(rVulr)?9U/oYQB/F`V\JEcH#;F*;nWFE;1u)@6TE!"f]JEcuSMH$+7OFa8.MBgisC +qu@H6"VtNgGBItJG'eRZJ8KFJ>qlfh"8i--#rc[EH?ajteF`e>rr2p"kj8*Dr;Z`ps8;oo'Qe#A +N.6M;Ko1D6Cf>MApA"[fr;?Klr;R9%p&+APS!&quPa@])OI,d.#F(F7Q"a-IR/*$IQN*6MPlHmO +Q^*r!BhIOco)AXg$MsSurr;W[q=O%!rVt=F$N0o's6&J1lJV^BJ,~> +#lj:_U<WQ4s8N#ts8N&siVilVrr)lsr<WE$q6[$&[e0OtrqZTorr2lqrr2rtrWW>q5`:5Xn<F6@ +P_M,XOI27-PlR-LPmWhBP`qVtQ'IL3p&=slrr)iq)ZTg:qu6Eis7G_STqXYbF`2#7CiXE%2u3LR +rr*B,rr2rss8Clp_o1+(rVlcrrVc`uhS@%Hrl"iU%*$9)_o0L-`lZ)ZM3%Xu8!&mtNkrZP_SX4- +_ns=2_o'KuQAgiePE:rlN/Y`o_8F41_nj+%b.5O4^nd!JPa%AtP*(`u`k]C-_SPpFs8DrrrVG[G +s8N#sr;ciprtt_4F_?;^H\.!)M1C4o:NVfpqu?]or;Q`qrY,80rr<#np\j\SRurktPa@])OI,d. +#F(F7Q"a-IR/*$IPlI!KQN!3UR?j2#AkM7dnbrOerVm6%s518k[^D^orVt1B#Pkg$St2M<s*t~> +%.DJL=bs`-aiqoH_oVi"ilDhVbf[rFb0%`DaMtr4;cm\8_p$9ErPnlYs2tA_s2P)]s2b2Z#ft-7 +d3O'eQ(%];pm1uGrf[SLP_M,XOI27-Pu=$;PE:iePEhi'P)+;6^W4@:bg"AS`l#[9`QH6Cahu=` +R\N5jG&D#:F*MIr(!=P9bfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHoC;;<nbr(YnKI5hp[Go, +^;.V(_ns1%o(;M@n*oi:o'uABo((SQ]"Q&%rkiE]](YmhnaGl4o'l/GlLj`5dCm'+_8=.,^qJ=q +p$qG.cg99*a2l9Cd(R08b/hZHbfn5L`l5s=bg]WjG(k=!NJN:5IV)8eGL+:Mc,RiI`lQBJb/VE< +a25gEdkd2KP*;,sQC<o%q3;2LPED,E;Lt50Pn'.GOcYZeR$sS.>r'+9b4E[d`ko[;c-=2DO@qW! +:0+^7^W"XB$I$Z4\S"Q2=(fG>J,~> +"TAAXlK\BKs83&tr;?Qos5EtWrt#,,q"asirr<#ih"'D's8;cnrqufqrr;fn#Q=Si1i&2<QLU4F +Q^NeU7Zit%q3;PXQ^3r&Q'R`!QC%@>q#C?mr;HWprtkP3p](9ls8I\#WG?-hF*`+LG^"0s`q]B/ +$ig2(qV]?2`7=eas8N!*s82T`_M<DZF)uAArbi*`Fa/%IBjVka#Q"K6!tSaYFEDbRG^+@LF`h.d +'EeL9!#5M9";YEeF`VSEG'nXaFa.b:-O9bVqZ%$32f*V^FaB%so`+mhrr3)am.gSXs8Drrr"f>! +;g!YGJp`0)JU_u<V+C"Rr:Bpfq#13jrt"u+rquQ<7$a1,R$!Z"Q^%<2#+^j?OZ8#Upm(lFs-<VK +s,mVKQA_.n;:kU4rX8]&r;Q`rmdBlCl-B8-df'UOrVuoTk3V<gs8RT~> +#laOgU;Ha's8Mus!ri/siVrlUrVllrrqluscCM2Ekl(JZ!rr9!rr;cmrr36&s8MRGClahMPm<YD +N-7[QQ'V62%@!-DQC!r*R$*c"p@\1Ys82d5q>^6is8DutK6sG,@W67/F_Z#>Da_YCrr;us%KHG, +s8N&si5NUPec#IGrW)oqrs.Dr_o'F2`Pqhs#fXa!_SF+2PDB."#a1=2OHGR>`Pqho4i,"T_8aO. +Z&O[,QBRGlPEh,e`l,^3`Pf[0]u.V'^r2FmOI;DrQ'd\rNMFM0_8O:.p&G'jrr2lmk4&ELrr;rs +rr)j7rr;@aFFSplH\$p&IsFMX7I:'So`+sds8W)ss8ET0qu?]qqTqWpQ^F/&Q'Rc$q3;/TOHbke +KTPtos-3PKs-E\O#Eb@1QT7pqqXXUrs8Drss8N&ue[DfmZD.$id/FCPrVuYrTUhXInGe"~> +%.Mq[>(*uuaiqoH_oVi"iQ2&As2P)]s2YYk`P74'>%+/Cbf\)L`r4!Yb5]Q_`rF3]aSs0baNMoS +)IA;hS+W-HPm<YDN-7[QQ'V93&so#TQB[PqQ'[`$O6"m6aMZ$?rldFGaMu$>^<=aBce!&VUhjag +E-68:F`M(JV9I$#bfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHoCMtOrpTmS0(8;uoD$56_SEt( +`5BI,]C>F]m-X6/nal8Cp[7"O\A5tu^qR\%\[_;-p%._Brp:p"me65E_RI7t_S*h+]tV,.q"+%C +iQplBaiDKBb0[i9aiaV(s2tA_1WIDRaN`A\3F[&WH[1$eF`hdnRl&C=`k'1=`l5sBccsPM_njU? +c-j$_Q'[l*Od26!PkgRKSWK(u3/!CePn'.GPECukPFR`'0KH;Wb4E[d`l,g=c-"&@JOqmh9j>9E +_8apE$HgK1[TuO$=_l4LJ,~> +#QFb_kMuUBrquZqrr<#Wrr2p!rqH3brs.!Fjo,5Vr;>s]#QOPi5s1BsP4=eBP`q8^:hlA\q3;)I +Q'R`#rfRPLPre^=qu?]qrqufqs8No6s8Moqr:nr=XIM_"G&h25GALhVp\+X_rX8c)rVGHk`5L4( +rVulr$30ntoYQB/F`VU&EW:(ZFTul)D.+7g$iBu;!<WN;?ZC./G^Fd`G\M878I>t*!#,G6!!X3I +Ecc;@Ecuk_FEMeE,mabP!<3*/$o_sDG]S.heF`e>rr2p"kj8*Dr;ZZn(AIh.<[fV78Prc;KSFh6 +Xc@W%p](9hq#1g(q#1!`qER*"Q&_,qPaIX0Pm<A9QU6%QQ'V62s-E\MrKIMSOJ%qP6N?QS%0-;) +r;$BmkO/*<j4+&-df'7Err32YkO%Hls8RT~> +#la[qTt'pqrr2lr!ri/shu3WSrr3?(r;HKikEE'Si;ETSp\t3mrVl`p#5RpX4d2+mrKQu?#F(F8 +Jl$3LP51@DOco^0rfdSKQ8eR:qYU<mrYth8r;Zfps8MiH8uS(AD/sN(CijB$5kk'Rrr;us%KHG, +s8N&si5NUPec#IGrW)oqrs%>q_o'F2`VmeV`PfU/a2NpkP`(]gOcYWbOH%)q`l#^2^VIt)a2G', +OGf3bQ'@GnOcbXC`PKL3`P]L.]>)D,ML:DJPEM/oOd;,gUW:6g`PfUcs8W&srr)]UnGi=`s8W,u +)>X=4<@KJ47o*?4K7nJ,WJYiqqZ$TjrVuosr;cirrsnl)qu$:U3/a&^Q'RZ%P51@JO-Z,!H\I`N +pltoFQ'M<6#+1IBQ"3/[n,<dps8W#rr5lCT\#lb+qp><Ls8N#gW1ffSW:^(>~> +&+\Up>]dNlaNVfG_oBd?b2:;?`W=6+rlPJ`^S4,$?^/D*aoKN]b5KE]`rF3]a9or+`Q$0FcmLK- +Rf&TRQhQaMP`q8^:hlA\qNV8OR$j>-OcTI'#;5&kb/V<<aSa1=aMc!6^rssH\N[!^6ud9`?>"+_ +<\3"Se&]PQbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9io.'4rlg!d$m.'uK^q\%-_SX70_8*dq +md]`1lgF32p?_\Pj06D2]thFu^Abbr\FfUip@IhAlgEs(qY\4:^Vmt'`507-]t)Sbo'u,-cg99* +a2l9Cd(R08b503Z`\GQWa4&g%%i88+6;D'2F`0%4JRHmCb0%fM`Pp*LccjAG`4a11dG?cAMj9<f +QB[c"q3;2GQBspbKp@u"Plm58Q^@Z9#b@6VQ<5Nebf]Lt&B;c6b/_E,Db3)\8S>iQ_oC-G$HgH. +Y?4Iq>'AEcJ,~> +s8N;ijPU";rr2in!WN,Xrr)lsp\XsqdIHPts82`lm/@4aq+*o9R$@-+s-EnTP^tuQRJE*XR$X&$ +PEhH"M`X[7qtg?jr;ZcqrtbP4r:g-_Cmh/(Ao1't4$5bf4]qCVqYC*us8Domi5NXQeboCGrr*c7 +qtTg#LO"#`EcQ5DG'J7SFDYP/!WrE)r;[K4"U5NFEH?/FH[C'VIV):a"onc(!##J9!!a9IEcc;@ +EcuqZHuj-[$3Bu'%KZ_@2f!MYEd3Pmo`+mhrr3)am.gSXs82d3rVuKfq1jF7]8flS;K#$hV,l%E +rVcHiq>Lp%s82`d4`sOOOIDK!PE)40Pm<P:>#pQFS!<`6s-E\MrKIPNOckc)Ac)AprXAi*s8;co +s6&hDp"e^-s3glHr;Q^#h<F:fli7!8~> +#ljh.TWn1hrr2iq!WN&Urr;p+rr<#sr;Z]kooZ8\fDY^Kp\k0mrVl]o#5\-d6BIIrrKQu?s-EnT +P^tuQRJ<$WP`q;rQ^F.u4A8cPr;Z`os8W)ur>GY5s8Mlop1fnf<aof52*!]^2a(=<s8;osrr*B, +rr2rss8Clp_o1+(rVlcrrVc`uhS@%HqSWZW`5]j<ML'o2rfTj8OH,B`Nkr]T`5BI,^qS=5Y^:hL +OHG]eOd2)kOH%<"_8O=3_o0:/_o.^]I#!iGOI25kQ&ps"a25a5`PM6Is8DrrrVG[Gs7uZos8W)u +rtP,(qM9U9]8flS;/J[^TMj2;rr2TirrE&tr=T&/r;Zcqp-!On/<H<dPEV#tq3;2LP$1nEPFIg, +Pm<J6OGcqFq>9[\%fQG-rr;f5[^EQA^A%L&dJaLQrr)#WTq@pcpA]X~> +&,,(7?Ym*daNVfG_oBd?b2C>C`l5s?rlbYna1\`J=C-ftpr`QV'#r#8b/hTB`Poj@bLJ4'NguT- +rg<bQpm(fE"dYC(4boI%Q!p#LS!]D&P*M;h2F'O\c,d`@aMu<Bb08#N^rF.,c-TCOUK(Z23[lU1 +.j?,sdb)ga`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8DoC)#1kj%R/qu=XE^r4I9rkq@F +^qR;Gna,N+mdBW6s7bcd]",i!^q77q^:V%fo_J7ToC;59lgscFcF17!`PTL7`P'+$\^C-AnaGMa +m+9A"aMuBL]tVV2qT/]V1!%M^d`U1oBO[j4F?:^0?9F4;7^CCZ`5U6G`QZZSc,dl>ai2KM-#61* +OIDK!PE)40Pm<P:>#pQFS!<`6s-*;Gs-3bF6qYnLb43O`aihiK^o:j75t+:l_SX72d`;d<`knKO +9i55Qg%0^~> +s8NQ'i7e52rVl`orqu]ns5EtUrrVrfrqud!g[+=ts8;fprr)lsrr;olrWiK$qK>YlR$dE/#EY@; +QCKR"OSP.PR$El$R?rqf6#1L,\b?%&rVZWn(]XI6s7u]2>HNZ]92oW`n%;fOp\+L[s7uX%s8Dom +i5NXQeboCGrr*c7qtTg#LO"#`F*2_TI=6EaCLA4b!rr</r;[B0!sB-AEH?5FH?jaSCf^iIrW)s' +rrE'$-NOGd??11/EcZDKHZ!UV$O-Y4!!<3'!s&B*$o_m@G&hhdeF`e>rr2p"kj8*Drr;fn(]47/ +qYg3cs8MTho0RuOA#uA1o_\Ocq>("#s7lKf;He!_;+G)ZR?O)"q3;2QFARIMR?*R-Q2d0IPm3S? +Q#KTep[J1^r<iT(rr<#^nFZ;(p&4p=rX/W(s8:d>m,[j>s*t~> +#lje?TW.DYrr2iq!WN&TrXSl*s8W)rrVu`gT;Ag9rVccqrr;rsrr)lrrql^"rq^e4M3XA)PkUFL +Pa.>uPEq^k8s&h5s,mbUR?rqf6#:L*\G-""s8N!5s8N&ur;XQ7W.Io<;J=tU]33VXq#1*hs8N!, +s8N#trr;rT`P]XErVc`p!<)lr"Q$r3_o2Pl(W!o&_8F.-MfsPtG`e)NOcYTaOcI8s`r<k=^VR_& +[rZtGHA%<?Mi<mbO,f4?`PKL3`5BF1^r;R\H[^6oNK90_O,]3ZUWC<i`PfUcs8W&srr)]UnGiId +rVufp)ZTa4rqZHks7H?^6%6p_Vjq#arr2rprr;usrr!E-s8;lp;HRj\;+G)ZR?O)"q3;2QFARIM +R?*R*Q2[$JPm3S?PAF![p$ht\rVulsrsA>6\@&]=f(f7BdJaLQrVG9ET:V^qp\o[~> +&,>4N@UuRU`QZKD_oBd?b2LDU`l5p:aNVlQc,mW*<`N:I]ZA1:b5TWbb5]Q_`rF-[aqVq:`l5j7 +aj&==5_Y`"R[TY4Q^*j8PQ-pJQO0(HOI;;uS1[EqqNYKUS=,_0Q^*M^5A"FWRa94"aMu3<`lQBJ +ai)';a4R1ZUjbcj4&!Q?SN!Una3;]Q`l?6HaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[Oh+o^hJ9 +lK[d/q#8II_SEe1a8X%K`597!md]`1mI'K9p&"?e^qdV%aMtm(_83gu](Ysmo^VD;me$)Hd^I!1 +]>Vn7aMu'0]t)SdoC;A3cg99*a2l9Cd(R08b5TK\`r3t3ajSG[eBuaug!AU*,A"AcUm=Nrai2QI +aMu<Dc-OYWahc*I2G%P%:IelXR?O)"q3;2QFARIMR?*R.Plm54PF)9:s-F"ZQ^2>MHHaUUo#UjQ% +Eli8]q/Ct6UsY3`5fjEa9p,1]p;Vk;dl3QoRH~> +s8NQ-h:DW+rVlfrrqu]ns5EtUrsnerrr;lqrr;6HlK\EKrr2iqrr)j"rquZjr:p6oq8Y+=Qgg7F +S;Wc"O-+Tpplu>RQ'db_=[$\EF*:LUs7uWkrVdW3s8Milp.hK^=/.nSp\t*brql]nq#C*arX8c) +rVGHk`5L4(rVulr)?9U/oYQB/F`V\MI"-ZrH#dO1!sS`*"TSZ&!"B#??ZL71G'A%LE_d8NquHa( +.K]_P!!s<FEd)YIF*2PEA24Z$!!!*$!!WQ0"p"l92/.)SF*W_oo`+mhrr3)am.gSZs7lR/q>C9f +rVQNks7l:leb3p>VJ*@6q>^3crX\r&r;1Y1HYmhHBNIHXQ^@K4#CeIWPaR_tRJE-JQMZpPQBdV> +DPdC5nG`=b"Q]+En'q@:!WN,Hrr<!'q;LW*j8&`TJ,~> +#QOVGTqpoMr;Q]prrN,tir0Pirr2ios8W&qq>^BdYbS>9r;HZprr;rsrqufrrqud$rr)]5/:NkI +rfm,A$'^^FMjTcjO`k40Pn0(@Q'db_=[$\DE-+tNrVQNmrr*f6s8Vrpp.M-S;kZ>Nq#C<fs8N&u +qu?Nms8N!,s8N#trr;rT`P]XErVc`p!<)lr#N!86_o0I0_#D(j^r+-<G^t!cIX$j6OHGTcOcR>s +`P]U3_SaEqH?agcrd"s0OcPTbNKK4@`PBCj_umip_3Y(H*-cmUJW#DFP)YN]Ur^Ei`5BFas8W&s +rr)]UnGiIdrVuiq0)tkKs8)corr<#op06)?CkeWoZi'b$qYpKos8MuqrqufqG=d$qEcbtr5`D%r +plu)60n,@TPED:,Q2[$JPm<V>Na$:prr;Ke%fcP-s8))l\[A`;kPG5UdJaLQrV"^7T:Vb&pA]X~> +%Jo4`ARD1G`6?BC_o9^rb2^PC`r<ph`lQ<Ic,n/DZY<E=C:M7&aNFM+s2tA_s2P)[s2l"r`l?!8 +`Q6<PWZ?APR@9P3Q^*j7PQ-pJQO0(HS;Wc"O-+TpqNXgBR$a5-Oa:(kCN!ou3n2[%b/VE<`Q69I +aiD<8c-eS<R7E,Qe'?RqcI'bT`kp-B`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[P461\'ku +lg=?As1c:i_8O=)bK7lH`l,X&mdor7n+-)Fs67/-`6$$;]uS40^qRS"]_D6nnc%tjnbN%2^;J"0 +aM5^<aiDH9]t)SdrppT]dHoK,a2l9Cd(R08b5TK\`r3t2bf@rTaj/,TcI1+e26kh=Jt?)2d)F;J +aN2??bg"JY`QHY23cSeMEbJN>N0fn+Pm;dnI[$7aOdZ'2&X/?>Q^O;2Q^*l"NDs)9e]l8.a:QM< +c-+2K[#[jN6qBnJ`lc6Ia9p/1\VsH^<+Vudp4*~> +&,cJ-g>Df-s8N#ts82]ms5EtUrrVuirqucuoAK'!rr3,srqu`orVm$"r;6Bhrr2lr:]17m^/g/B +R$Er$R$3u*QC!o&QC!o#Ng#csQ'@bk="'DtR?`u%Q'IPuP_Cf%DJj`?DJ;<0qXsjfp&G'gs8Dip +rpuXtXF?!"q#C<iqt^0crX8c)rVGHk`5L4(rVulr'*%k(oYQB/F`hqVH[gEgD.sF`r;Zg"rVup# +r;]"i>]Fn1Ec?,8:)<m6!!!'#!!<B0!rr<&$t"(%G'A%JEFCO*!s/H&"9JQ("pY82!Y7%sG'S=\ +NR[V#rVlfr"6f+Hrr2rjrr)ajrVl`kqu$0V8ZARco_AI^rr<#rs8)clqt#G-D0p/AE,fr*>EtGA +R$!c+P+%GL/V'@TOHQ&rPDY0ZR?j&$R?Ef%QBmf'R$NM\6LXsPnbrReqYgEtrT`eDld5Y2!WN,I +rX/Q#s6Sn3l/;R@s*t~> +#QF\SU8cW:s8N#srrN,tir0eprr2ios8W&rrr<#j^n.^;q#16gs8Mrqrquirr;Zfr<WE'ts8Mus +s1MEhJ!Q:^P*V5tQBdc$PE_>sOGoBhR?a#+KNBRgOdVJuQBd`!Q'?tVA8Z4-DJNlKp\OXas7u]p +qZ$Nks8MY[CoMc9p\OpirVc`js8N!,s8N#trr;rT`P]XErVc`p!<)lr!T(Wk_ct!q^VRY"]u>,< +H$Xd^GBn^tPEM#gPE3Gq_o9O1ai1E3E.<:^I!BjaLQ7IYOcYIB`59=.`P]^2R<Nk%H$jm]H\.-9 +O,f<dU;Xsb`507^s8W&srr)]UnGiIdrVu]mqu8t]qu-NgmR<qF;"XVarVlisrVu`oqu$,>6>C^Z +Ec,f8>Zm8RR$Nf!RZNnrCb:1-PE:rrPEUl[P*qW"PaISrQ2[!IQNib/JjAf)r:'[cqYpL%r8"un +]!.k#rVucArX&;p^n[BiU>#GCJ,~> +%JfCsBk*(6aNDZE_o9Xpb2^PC`r<pg`lQ<Ic-FMLZ@5\P@C!bm_u7gZaoKN^`rF-[b(%LP`l5j7 +`6d),6%+*JR$a5.P*qPuP`q>sR$X"tPEqW%Pad>-.$p'aQ'7N!Q^*o%K.^\PD0Ti*==2_N`llK: +b/_NJbK%]Hb^X#pCi@eGc,n/PbfI]:^VS"4`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[Oh+ +naTfNnaQ2Gs1H7jb/_H9^;7q;c,IQ7]C#4[oCDPRr9M/,aNViRahu!5`l5m8_RfR=o^2)9o)/@< +]u%q5bfRlD`llQF^qRY5p@n4QkgAbKaiDKBb0[i9aiaV(rPn`Us2t;]:rgf+cd'k]coRkk6.!]q +^rjpB_og'Kcd9sM0P,EAE,T]9?!<JVR?s#%Rus,!D(U:.PE:rrPEUl[P*qW"P*:ljS=H%6Q'./S +FXbScb0'=s&B`5<bfIf1H:^Fq9MDn;bf8&O$HKfjGuRF7B=?t!J,~> +&,lP.f\lT*s8N#ts82]ms5EtUrrr5nrr;rnrr3&PmcXTL"T/5squ6Nn"8r&nr;Q]ms%Mn]7sKiM +Padu.R#dDrQ'IZ%Q'$rXQ&q/oPa7MfF@DFQPaml&R$X&$1h_5RG&2AFG?nP<rqQNkq>^?krVu`m +qb*oa9(`/[p%eX_r;$="s8Domi5NXQeboCGrr*Q1qtTg#LO"#bH$X^ZFD5P"#Qal(rr`)t$k-Zd +F`;>B@7_+9!sST&!!3'#rW!?:>]=b1Hu!b31'[d]rW)s"rW!K2!<<**0kklXH$t\%o`+mhrr3)a +m.gSZs7QBir(m=lr;-?jqt?,!VfJ:)qYg?gq>UEkrqQ;/3,sCaH?"1LD08ToQ]dZ'OHc-$OZe5] +PF%i(Pa%&XK8c%[Q'[T)PFdf$R#d2ZIV)1Lqu?3c!WDoorrr8bn+,_rr;Y4Err3,ekj%Kjrr7K~> +#64Y[USZ-/rVlfr!WN&WrW`E%rr)fqs8Dm*s81<6Y-dNns8)cprVlco!<2rsqYpNp%IjBdGD2$> +R?X,*NKKM*PWG(nO,/FROHPlnQBR&F7?iaqS<9/*Q^![jBR=W=C3+E;>?g7ir;Zfns82fos8)Zj +8Z&1OoDedbrUp3irXJo,rr;utrSYZ4`7=hbrr)orrVloT_#D7O_$@]j_7n'5G^B@9#'tQ?I"@09 +rfKU0`kfR,_oofsIs-3iGBS@YGC"anNKTHdON>8K_o]X8^R0:kIX--bGB\@]Jr5SNMN=RT`P0.% +_"Ia-rVlfpqW@;IrVlcqqYp?k:&b(js8MbQGG8uCrVlipq"k$jrr;ciEAh]\BQe69DejDfE0ZNL +R#[>qR#a=ZQ]mc,PE_;hK7f,IQ'I\sSroM#Q'[MiKm[H&r;-H`rX]&+rVlfne@;rqY,h?rqu"k@ +$NKts\YG^eUZ;:OJ,~> +&H;44D-qn,`lcHC_o9X<bf\te'ZS,2`l?*Bc-=GO`OqL7<a2<5`PVSt!QrL^`rF-[b5]N_`r<r* +a3V]Z/7j3cPFRo,Q]@,jP*2)rQBI/\Q&q/oPa7MfF@DFQPaml&R$X&$11klNGAVA;CJ7:?f#c+S +^rFF=bL+DXfef7g1t:$p]YMe5aMu'1^;7n5`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[Oh) +naGr;p%;Ac\AZM6bfIc>^V@Y,bK7]<^%_0kn+H_RkeF^Hc,e)VbK%N:`5]m=_nl*@m-aK1qY8^Y +_p6HHcH!rC`5]m<`4<P0qtp'Yk0`PIaiDKBb0[i9aiaV(rPn]TrPh">_oBpDb07uRH#]HfJCDES +`l5d5aiVrYg0#k=HYdnDGAqA?9lZJ]Q'm\sQ^NptJ<uIdSWf;&MM$P?Pl?pYMOKd(Pa[koJ9>^* +/Cr%ko#MBbc,n/L_lmuG6:apZ]#i"5dDu[=^UJ/^9ibuHme_M~> +#6+Z&f\Z3!rr2rt"8hons5EtUs8VurrW2rkrr35KmHX?Ds8N&tr;?QsrquZkrr2lr:]((ir/X*F +L51SROd)B"R$O)+QBI2\JVK5OQ'7N%R#->GT9>D+P*:um;`Af6EHQ/BG\_Cg46ZP1s8)Znqu6Wq +om24eEi\j4s8)cprUKjps8Domi5NXQeboCGrr*N0qtTg#LO"#cI!p0]AR#WI!VQL'!<<*0<HWM/ +D.ZWR!!!)u!!!'!!"B#2!!!C2Ed<7TEG73=qZ-Wsqu@3-!t$YmF*W.aO4<h%rVlfr"6f+Hrr2re +rr<!+r;HZqrq0!bY=%dOr;SkPrV6=X@rHC-E-H;>E--,10TM9XR[TP+N'2WSR#R8sPEUuZJUrT9 +P*M?$Q^*SuP)>9VMaarOq"t*]rW2uqrVm5qmIKc)l2Ue]s8UOHrr3,^lKdZgrr7K~> +#QOeiVP:g#rVc`qrrN,tir0\mrr2lqs8W&rrqcZpl^+`[gA_'Ks8N!#rVlcprr)lnrr;mls8@sC +=+l<`R?3W%P*_DuQB[JgK7AW:QBdZ"R@&h]/t\;jR?EbqPuBS^BlA'/EHGi55W\0.o)J[gs82fp +s7LYeUMm.&s8W#ss8DrrrVuoss8W)t%KHG,s8N&si5NUPec#IGrW)oqrrLulrkf/]_o0d;_gH`T +H?jg_rHh._J;]PQOcHig`5][3[<d"BIXH?dIX6BeH@Up:Q'79L_nXC/`Pe*iG(4gaI<^*cI=?^$ +Ng,fmU;k!]_SEt[s8W&srr)]UnGi+Zq#:a"rVuosoLbpZ6LjpMs#^&VqYicgCMdm'EboQ0Ec>G> +N/s$eR$<_j4+*9[NKT]nPDt6HJVT5JQ'Rf'PDb]fL5^qH6a?XaqZ$*b%fcJ*rVlW7[^WTA_>O<. +d/FCPqs^b^S=ZJDrr7K~> +&HD@HF'Ndt`6-6A_o'L:bf\te+NDC>`lQ0@c-=JM`PSiY<`tNt_8FI?c-4>O`l5s;aNFJ&!65#W +HGdhReScd%GCbC5Nff`kQ'IZ%Q'$uXJ;0,NQ'7N%R#->GT9>D+P*:oi;)E9-E-?/BF(B#E-HFKK +bf%NHa3;o\cWtFYArt6_be;':a3)K@_8F79bf7ZHbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_ +nalDF$N9i"^;@q5cHOAIrP(tBaj%i@^$,=fqt^0Z\$`ohaN;cVbf[l>_8jaB`P;-Ao(_JAq:!-q +cHOMW`lQ0>_ns=3aMu'Fq=sRTl-\kLaiDKBb0[i9aia7srl4rV"2Vq!b5TFPbgeeKVCp*2aNM`P +bJMHGgauZDEH#i@E,TZ9EFLS\OH>luQ'.%fI?^+YP*qMtNJ)k6LQ.I^P`q8rP+7_gJ9GubQ/0^- +bOW^cb0A)O`PJT_5s\%=H,%A;ajJ0:bJ:5j;GC/,eF`]i~> +&,uV/gu%Gts8N#ts82Wks5EtVs8N!)s8N#or;ZfCm-F!9rr`2rr;QZp!ri,qrVl`p%J]tuo_FPE +JrY;AOI):4Prt:mMhd">I>X5RQBdYsR=T-LR>[PsR[&=rDJsZ?DKg,@HZO+I/C4=is7u]oqtp3I +<iV]jq#('es82carX8c)rVGHk`5L4(rVulr&-)P%oYQB/F`i%PCh?rV!rW*!!W;uu"o\K1!<N?6 +A8lO,DFP-@"TAB$!VQL#$=/+%FE1tH$NgM1!!!5t!"8u\B6S`NI?2nMs8Drrrr_KOq#:9mnbtfP +s8W&qrr;unZsg4mGlIO8s82Zhrr8*WE,fc=EH->KF),r8B2=e_N0Tcf5_G/YR?s5&OH+gDKS+r5 +MiNdXrf@MBKSb)'7/-NLs8Vudrr;rqrs@rXp%$]6s8MusdJaCJs8V!Am-*=*s*t~> +#64\sY+N&qrr**"rr<#trS@Gds8Muqs8W&toq&4ibPh>;s8N&uqu6Wqq>O+gq#C*\q2eC(NdZtL +QBd\uPELr_KnFu*MNa<kQ'7B!JSS&LMjoitQ$uGEDKBl8F_tr=DejAEdJs%Br;ZcnqYB#JVj^QV +qY^9kr;HWorri?"rr<#trXJo,rr;utrSYZ4`7=hbrr)orrVloT_#;/9]t_S.GC4^_H$OX\H[L3f +H$k:(O-,F?^VRe-VK[99I<Kg]H?a^]GBS7_MNO$\aj7Q7`5%ITFFSa[G^a^ZHiAC.J;B2INLe,. +^V[\"p&G'jrr2lmk4&EBrqQNnrVlgeqQaD.Jp@=nqu?QirVun\9l+W[EG]N8FE)#:C1U,'RYm;p +Ld$BMNgZ6"P)t]RKS4u2LPq1PNfT3[K7\i(HU[Z(o)Jaenbs(!rVZTnotIlD[@c1Ps8;oDrX&G` +V4O0JWVQSnJ,~> +&HDIXI9:0l`QH?B_o'I;bf\qds2P)[)oftCc-FAI_S08V=b+)s`6$6Jc-"&F`Q$!Ab5B?[`c]PC +e&fneEB88tG`.KEPEM/pPE1TUKS+]1PEhH!PEM>bCJU@VRus)%HqS6kFEDGIEH$/?BP%mYe]Q7X +aiMTLe%e28O[RgKaMQ$6`QHEI`l5s=c-42Ibfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHrpq?% +nbN3k^V\%6b/hQ<^V@V#_8XI6_7fU;pA"[I[^X/j^;Blj29*\R^V.M'`l,Las6f@Io#J,Kaj%]C +beM$4^q[Rs^r!t#chdM3p>aQef?)(S`lcZA^<+OiaSs1W`Q#m4`6$->`PTXCR8g&+>h$a0aN)BC +ce3A-D0'Z=DK:,KEb]`4AknS[Mj0Qb5D"rVR?s5&OH+gDKS+r5MiN^PMij6]K7@ZF-.g\jeBZ&' +a:HJ9ai(rh<Bi`A9pri;`lc]M$HKoU>>S!pF5ZinJ,~> +&,cJ-jl,A%s8N#ts82Wks5EqZs8Mrorr3<(r;QNls4c`'kPbD`qt^*drr2p!rqu]mrr)j\q>^?l +s7l,j=akpZL4kG@N/W[MKS+r3Kn+f<RZrr%P`grC9U(^,N0ZbGEcc;>Ec?&AFEhkHE]WRas8)Kh +rsea3PGhd(pAb!erqcZnnbrprrVcTN`Pf^Fr;HZpr_*:gq"2FYH$+7LG]$Uj#QOu/":#/8!WW6+ +#6Fl*"UGcHF)Gqg&J#<P!!*?4!WW?(!sSo1!<EH==DWG$EA@t6#QOi,"pkS>!s/<"%0m=tBm4fI +I>ubKs8Drrrr_KOq#:9mnbrOerr;rr8,)mgQ`X'6p](3ls8)cJ6$-pbI<9LTDK'QBDg61lH'4h^ +G>3sPQ^F&'R?NM`J:`H-JqAZ0K8"o6M1^>;J4f&*rr;ios7-'irVlfqrs@iXp@QW0s82irdJaCI +s8V*GmHO!:s*t~> +&-)Y+\Xokls8N#rrVuosrS[\Srt,2.rVlisqYg,nVQRi5r;Zcos8Drss8DosrVld[q#C6ks7u2l +>(2$[KnG5;MMd7EJqAW.Kn+f<RZrr%P`grC9U(^,N0Z_EEH?&8E,KN3Dffo8E'!Cbs8D`lrs\[0 +P,;I"oDe[cs82iqrVc]trVlisrr*B,rr2rss8Clp_o1+(rVlcrrVc`shSB-.>J8"s]mG9NJ9uTe +G^4XaI!L!aI"I6;NP*3Ib,BH-IXQWjI=HKcIX?HgH[UO*P)mGma1TKUFEi(XH[0j]H[L6jI=6Tt +L67Oka2G^.^VTUCs8DrrrVG[Gs7cNks8N!qs8N&rrr;urrVuonqd#Dd:=f4?r;Zfos4KYYC2nQ= +DKKT1DL-/CD+Af3SrRqdLkq=`Q'Ic$MMH_6KS4r/KS>&3JVSu/I#*5Cl2U_^q>UEarXSu-r;?Q\ +]!f#SRI:(Ss3UcFr<V8UTU_XbrVunJ~> +&HDOcN*'Gl`lQ6@`P][=bf\qds2P)[*Q?%Bbfe2F`5$Io=*:p__oBpFc-"&F`Q$!Ab/h['b5]P- +`k]X8d+6OdPt5q>Jq8K.LlICQL4b#-Jq\`-Od_MsR$<blDbQCYQ\q"kBlA!1DKBf;FE;SDBji42 +f$h^Tc-Fnk7Xg[tXO,P<`5TR7bK\;Sb/h`Mbf7ZHbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_ +o*=^Zr:@>0[`89a!5eWK/AAp;_S5L9q>]H\]#)7u^Ve%+^rOC4_nj.'_o'+Uo).qSa03(h_8F1, +_8?2es1eTJ'thE!eGAt2n`%m]f?)(S`lcZA^<+OsaT'E]aSj-XaAU%!`l#d9aN)9=`lQb(LS$W9 +bf[iJe'H^V.rK9MJT5USDfK]BDKfthG`eVZG"daLQC*r&R?NM`J:`H-JqAZ0JU`**NJ)Y,Be$sO +dFZL_bjia`ai_`D]pVY]5>4hW^r4R?$HBlL=\qgpK]`13J,~> +&H)S.o&Sp2s8N#ts82Wks8V*X"98Arqu6U%rqZTjs8VZHlfA$E"T/&jqu6Qo!WN#qrql^-qYpBi +qt6IKL4FZ(Ljju0KnTGX"b_Y]Iu'6dQ7nAjPCdjKOd;AL:NCN#D0C#DEH?;>E--5::&";[s7uTf +]OIt!F7oS-q>^HorVZ3b$ig2(qV]?2`7=eas8N!Hs82T`_M<DZF*2G+'+4dB"U,):#mLJ3!X/r; +!<<90&mfEk5SanA"p4c.rs0/>#6G,9"p"`-$Q*8oH#=rCrX'5<!"'#:$O6k>"U>23!!!NbB)ZrX +IuVtMs8Drrrr_KOq#:9mnbrOeq>W,Fa]bO4@fH6(s7cQG4EbUaE,9Q:F*D\IAoMj/EB]JMPW4;P +R[9;$P*:iYK7njRK+NWfK7/B,MHWaHs7Q6grr2fbrX\r+rr<#lkk+W<ec5[Gs8C@E$N'l%jmMR" +qZ$HlJ,~> +&HDb-a.T<ks8N#qrVuosrVb[Rs8NW/rVZZos82chcC_/NnGN:_s7cNlr<*'!s82fp(B*ut7tuP@ +JqeZ(JqJZ+JqAW1J:EB;rg#$rS<JPG99GO-C//bhG&)2?F)5c7BP_X.B2&*ns8Vrnp:F_5LiW4h +p\Fgg"9&/rrVQTos8N!,s8N#trr;rT`P]XErVc`p!<)lr.,MbW_o0O3\U&UFI=-6_G'8(SH$FFT +H$4FaMi56b`h%?sG]e+QGBWt1)L?UQH?aUYJVT6*aMu,OG]\+SG'A4TEHZPMrHK'&H@C^B_Sa1, +`kh?Js8DrrrVG[Gs7cNks82d!r;Q`rrr)ir0DrmmURYckqZ$Ths49ATD/sN/DK'K6EH5T-EbfSU +Ng,\bJVTVXQ&q/mN.ln;K):03JqJZ%JUrPW9_AAWq>^Hnr:0ass8MrprS>#nZEBtqr;Q`oci+3u +US"$IaSl/<J,~> +&HDUfS69!k`lQ6@`P][;bf\qd+i_UGaMl-BbfIuE`l+$9<,SYG^rOUBbf[rE_oBd?bfIm'arSRG +ahl-@bg+Rg3I5jlIYW?)Knb53J:<!%J:EB;rg#@&S<JPG99GO+BM<>`FDQ)@FDu2ABl.d(=ub3[ +ccj5Jc^d^sG$W_P`P]j;b/qfNc-4E2at:]R`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8H +p[>K#[(sJj]t:nirk9#X^V@=g]Y1oGq"iLG[_08a^:XBS)8!Sq^qmdr[^iuZo_e^b]sG#R^:V"k +]=#6K\JVog[^<BPch7&&n)hs_f?)(S`lcZA^<+OsaT'E]aSj-XaT'CCaMc*=a2lEFaj&247$j!2 +hT!X[b1a?NB5)L0Df9W9G&hY8Df]`64cbkl2hHjRQBdPpPDk3JKS')R!.b&t%#0Oi82/?=`6$<I +aM[Jf%EZT$M,-H"86igC_90dFa9ou)NE8qP=dA:Os*t~> +&H)S.ro`A3s8N#ts82Wks8V*X"98;oqu6Ttr;$<jrr3)Rm,J!Crri8qp\Xmes82fnrtG5+s8)Qk +qtA5sKnb>0N.Q\8Kn]MZ2h?U9K7oDTNgYrtP(e*ENg)MIDKBN;DffrGC3OrHEH6A.B`.c-qtp@i +V6!ASpAP$jq>^<ks7-'rs8Domi5NXQeboCGrr*N0qtTg#LO"#_D+#-R#o3jM%K6l0%LiaQ$kEjX +#mq(S>&5o*+;>(l'+tc`%MB?`$k*LN#n%:X(1Lln1)UT2#S@RT&ebff&eYch'GCub#oGF+GBn1Q +N7@M"rVlfr"6f+Hrr2rlrq$.Hq>:,4Ml13is8MroqH%BMEHZSJF`_SDF)QAHCiX_tCR%53PEh<" +Q'n&$Kn=l,KS+o1L&HZ7K8tY;HpRW,q#CBgs8)ccrW)ios8V<hoD%G8s8VoprR(TOqu?-GmdB6; +s8)bG~> +#64\ueY/_hrr*-"rVuosrVb^Srr3N-r;?Qns8Dlmk+&N^iVWKKs8W&urVHNmr=f21q#16kr;Zci +bs$i9KmJW,JV*fP2h?U9K7oDTNgYrtP(e*ENg)MHD/s<7DK'E:Ap&<>Df0`"BDh`.r;6CfU8glM +q#(0lqZ$Hms8;los8N!,s8N#trr;rT`P]XErVc`p!<)lr(#HaD_o0?[F*M_XH#n7UH$FU[H?j`6 +H5:dTL53:WO)fo"E-HSPGBS4YHZs[ZHN&1%H@:Ff\\=#NG^+=YIsZKeG'<h/(O(%IH$kL9]>qt1 +_nl$Gs8DrrrVG[Gs7cNks8W)qr;lotrr+eTr;Q\:M54[^s8Dlmq,M'HE-6AEE,TQ2EG]r@C2e;l +Bp1f+OctloQ'n&$Kn=l,KS+o1L&Q`9K7\r1I<e$PrVHQop](-jnGWptrVcW>]!er@^%D=(s8:7C +$2qc8SXZ2%rr;tJ~> +&HDXfWEW>e`Q6-?`P][;bf\kbs2tA\s3*@?aMl-@X\;`/R('`JbK\/M`l5j8aNVlLaNDZLb0%fM +^Ve13`Qurc].SAXJU<B1L4t;6Jc:-WK8,#3P*h8tO.2;dG<_+P3-8qTAp/!/CO'K7G]dtDF%]E` +bf@TBeM`JX2pB[nc,RQC_T^:(bW*bd`l?!8`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ;E +dB9pa`kJjl\[T,__8O:,^qd_a\OEsmp;3`B]!oJm^q$hZ[^io[^;7Us\?rNDo^DUu]=GJ[^:q1h +\[JrV\@T8`\[f/T^<>p=p$C\am+9A"aMuBL]tVV2rlG&\s2b/Ys2Y2_rle0\aMl3EcHaVPajsOA +T3mr3`5^'U5[.o;E-62CF)>f8DL$;=EHY2oPX0PWP`_B!R@0+iJq8K+K7ei2KS4r+IZ9)5F=Z(m +aNVoHbJMNoa:H83b/Li9:dI3-HG753ai;`L$H9c-;bg+jVX4?_J,~> +!;uir!pAV/r;Qfpq>UERrWE3"q>($is830"s8;oseF)>jrr3?'q=jdcs8W)ts8W&srVmQ.s8Vrn +s7cHkmDhbNKS>#3KS5!VKK"O7L5(/3Q'RT%PF.Yo9MJi!Ciai>F`;AGDg6>;F)c>AED<P-rqu_a +FK'SDq#(-gs8Vurs8DKe$ig2(qV]?2`7=eas8N!0s82T`_M<DZEckGj>#S9q<E&lts&B"ss&)3_ +<DuR_;+bD9AR&VT@V'%[An,4W@U`YH=^,9E@Tu!?FCf5q@qK(S@:a%`B4u!kAnPaiAn+q7>AeS' +HApAGs8Drrrr_KOq#:9mp\t!gs8N&us8>Ifp\O5LWMrbhr;ZUuB6&!6DK9f=F`h_DEHPu?F)H"] +9l5rXQ^O#(Oc"dCK7\i4Jq8Q-JqAZ/KnP)-:\a_^rr2iqs82Z_rW)oqrrhELo)%8BrrMuri;WcV +rr)oqpAPBulf[^&j8]/Us*t~> +s8NQ%h4gUdqu6Tnrr<#trSRVSrrW2urVca%q>U&WYd2jVq>UBqrr<#srr;rqrr2j1rqcWoqu?]m +rr;B+7tQAHJ:iH*Jc(-YJVJo.L6\'fRZj,)MbHiO?#+J)DKKf7FDGu=BQ7s1Ci)hHpAb0iRW50L +MYd>Or;Zfps8W&qrqufqrXJo,rr;utrSYZ4`7=hbrr)orrVm/[^r+(.a/le[rj;j=[^N[C[f<^+ +[C<QM\@ncObK%<3`PK:$_T'O1^qmn'_8F4/^V.FUbJUs5_T0g;_oBX4`5KO1`5BF+_SjX5WO'C[ +`5TRcs8W&srr)]UnGi7^rVuosrVZcsrr)dfr;HZlr9QtOUJ:FZs8-#3DfBc7EH,i7EH,o8F(]Z9 +CiDI0CQ4UEQ]RMqMM$M5Jqf#3JV/W-JqJ],J:Do?p\Fdfrqufrr;6NarX/](r;"=E[^;OSp&=sk +rS7APs7ZEuq6urdStG$As8RT~> +#ljea\6i6l^;^)ms2G)\b2CA@arJLA`QH?FaN26B]2;jAM7C:?ai_]D_o9X:b08$-aSj82aMPp> +_8XR7c/-jO20OG#K8,)6Jq8K&It<0*L44lBQBI]#R$NY(9jV%<E-5u;D/F?/F)Y`3E,o`/5EO+3 +aO5HDR:U9dccX/I`l#j>ai_cMb/hTA`P]^>bfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_o_IM9 +o()DD(A74emdTiBqYKmVo_.qFmI&Tmq=sU\rr36&s8Vuiq"t'is8W'&q"!dos8;ThrrN&prr2rt +!<2fo'D'u=n+#c*cg99*a2l9Cd(R08b5TK\b5]Q]`rF*[b5TU]cH*uDbg"ARb/)?F2kQj2ccXM[ +5?;N:DJ3m-F*);:D/aT1GB.P?4A'FMQBmu'R?<AZJqJZ0L4Xu-KReZ*JUi<#F?\I,bf\#HbfIZ; +`q%1]`Q--=Z"cus69CFI`l,s=d)ZO,DGNr)@(>\*s*t~> +#5e>us5)r#rr3)uqtg0gs5X+Xrs8Q"r;Q]nqtp<jrr_!8lLk/V#l4Drrr;upp\=afo)A[h-25AP +JrPD6N.ck<Kmei3K7no1KSu"US!fM,Q@;^rF),o@Ecc9rEY!/2Dfp*rrqc@YWi&YfpAaCV$ig2( +qV]?2`7=eas8N!,s82T`_M<DZF*;\IEGtho!,qdTs)/EgDfK`:Eai^"F)Pi3E-$(!F8p7nEH6)A +Bl%TrEHH/1D/FTCGBRs(DuF\kEHH/<EH$#DCh7L%D00rKNR[V#rVlfr"6f+Hrr2r^rr<!,qu2Y' +ZZDK/qU.ZGHMDLnF)l5>Ec,u83aRK'Pa.Q#Q&UOtKFriiKnFl-L4t&3LOkA38bW)^rVlcqnbrRh +rr2p#jQZ71h>[ESp&>!Orr)iurquZmr;Zcqs8N!(s6&n7kM-%:r;V9~> +#ljo&m[^,_qu$El!r`,uiVrlUq#:^#p\:_dZ,lY=s8Mios8D`lrVuiq-N3VR8Uu\JIu8i1KS4`0 +Jq8N*JV&`?O-u>tPa$Pl5&tC[FE)>=rG_[S%WZB,F8Gq8p-PUN:&4Sarr)otp\t-krr*B,rr2rs +s8Clp_o1+(rVlcrrVca&hS@%H`59F0`Pqhr!6+lSrl#Aa_ns:3_T0O3aN2B@`5MYms25_m`5K[1 +aN_]I_8*t4^Vde$`l,m:`Podp_]-G3`lH-9]Yqh/b/V9:`PKC`s8W&srr)]UnGhYMrr3]0r/5g# +DjC.pdm.YkDK0Z8E,T]8rc/QhEH5r=CcYpVPE_>tP`q#Yrdk`7KS>&.KS>),L4Xc,Gt7T*s7uWo +s7?6irsnu(qWPZ*\?;=gp&Fsis5EtWrVulns8;j'qY$k\R\Q\DrVunJ~> +&HDY"eRMd)\A#r,dEK\N`l@#Zs2lA'`l#^6aNDZI`kB#s>ZZ!UaN2BDaM5I/bg"DT`q[XR`rF+. +b0AA\Uc*=KIXm?/JV&K"LP(22K7\`5OcZ$!PEhD];*8`.E,ol<DuF\TD\-c"DKBu2f[.pt2PHQr +dDsH0a8j6Wa8jB^aT'7#`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[P15s7H9br:^-b%eoVe +o_ngfrUKFKoCi"UqtC$]%ef>bqXXUZoC)JCp@@hLrpp3`p@eL\*;&t!p\OUWr:os\o^DA?im6uC +aiDKBb0[i9aia.ps2t8\s2m[L`l?*AeT,B&Aq&@]Yq'.%Df'?2F`qhBC2S!.DfT`9C,fCKOd)3$ +R@'"iKnY/3JqJW&ItN8tLPUG4D(sJccH?+,"3/=!`q.:O`XTi+^R8:l4%2T@^s'g?grT<2rQ#>g +]j"-#>].^Vs8%6~> +#5e>us5W5#rr30"q>:0ks5O%WrrE&tqu?WsrVH?hrr_iCmdL/T#lOPus8W)oo_8@bnc&Rg%/dq@ +I#!K'I>`Z3Ljo;U'8(mkMOBirQ^O5(IlDUmDKK]6GPQ7iG&V\G6`KeRH\/8=W:Bocl2D(jrVcTN +`Pf^Fr;HZprWrQ$q"2FYH$+9/GQi52EcQ5DqK<?kG^+CRD.+o4F`MD@G'X"1r,sW>F(oZ,G\KKU +EdiFbHusLPF`hqRG'8.OE,orAHus'q;eU5qFaT1uo`+mhrr3)am.gSZs69Lns7lWcq+d`f9'c2^ +8:#,rq/Rj(Df9W9DfSEeK9_ghQBmbqM1^G6KS+r/K8"u/LP^V@MK_trr;HHirr)lerqud(l0@m8 +i;`iTq>L?nj8T#W!WN#rqZcutrr<#trr2p'j7DNlg].<Qs*t~> +#ljo'o;A7cn,31brr2rtir0#WrVl]o%K?D-qY81*YIsK)s8W&orrN)rnbs'rrr;i.;0mnMG^G9s +Knk*TJeN]cKSYt\P*MB"OFB*3EG]c4DKYnsrG`?kDfoqbXSM[<J#%"\oDej]rr2rsrXJo,rr;ut +rSYZ4`7=hbrr)orrVloT_#D7N_?@cp`Podk_Z7IN_[FE"_MZ1Ja2c-:_o)Gir50/k`kfj4bJ0af +_T'@*_ns@2`5DPj)ofY/_ns@0_8rjb^;\%*^;9LBs8DrrrVG[Gs6]gcs8Drrs$$8Yo(GYGWCQ:J +\jpsYEcH)<E,T]8Ecc8=EH5u<8T'3IR$Eu&P)4jCJV&K+KRnc0KR\`4IYEGr;#L=kq>L9mrVlcr +s7?6irso&+r8,0!\ZVY"rr<#rrSdbUquQcqqZ$Km$N9+YT:V[Uo_ngiJ,~> +&HDY(hK)n6W4U'rf$V^\_oC]W+O&!L`P]U4`llQJaM#3B<`3A3a32TG`k9%*c-akY`Q%Ji&&cZ? +e=o-EItW)pML^G8Hi8R1Jq8W4R$X#&R$Wq_1imMJEG9?7rGhgT&8c<#J9<f3cI-BPUh#;"bf0.o +,0%UAbfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHoCMM@p[S4N&a\oPnbN(X^%(RZn+62@mI0NA +nMTe&p$V);m/?G"mdp5Dn*fN.mI0T:oCVYHlgF94p%S.Qgt_;ho'G>]m+9A"aMuBL]tVV2m`>FJ +8'&iqaMu3=^X:'Q23X[ke(UHPDJ4*0Df^&EF)5T/CMe!1DfS?aJ!$%^R$sA&LkLG8K7ec*JV/Q& +KSFo3L1iU"ccO)GaSs<a`l5p:o>psO%`?8uMH)c$92`4<ccjDKh8oE3rQ#>iXAMP^=FJoss7h*~> +s8;os!q5+*rr3,uq>L?niVriV!<2ups8E)uq=spg#g;]"s8N&tq>UBn!rMZbrr;Qgrr3E%rNK4T +KnbJ7JqJ]0rIbi:JqJ`6PEhDtQ^<MY2JdJVG&26qEY!)0BQ[(;pYSiMTiL^aqY]UW$ig2(qV]?2 +`7=eas8N!'s82T`_M<DZFoHUcFoHI^FT?UaGlMqLG^"[[Ci*Dq*,Kb=EclSMG^4RWF`qqQG\_VI +G'%U`,VN_OH$OgbF`VSEFa/.SF`_YOH?+:V>q?jUC]8S`JrS:Ps8Drrrr_KOq#:9mkl)(es8Vht +Dl&58q3supF*7;!-Za9HEcc>/7"^J`PEV?"PD=jDKS>)3KRnf/Ljt,4KR8GHnbE%^r;6Kns7-*e +rs\SdlgsQ/s8Vrpr;ZfWrr)isrr)ckrr<!)pYk`1hrk%>rr7K~> +$NL,)qR<,sj88fSrr<#t!<;'X!rW#rrVmE-s8DutqtB?DYHdEhs8W#rrrE&trrN,tnbrajrr;`h +Y>Y@Q"c.SWJUrIPJeN]cJV&]?PEV/pQ%siHCNFK;C2s2krG`?cEb9AgS+to;Wh!&Zs8Dugrr2rs +rXJo,rr;utrSYZ4`7=hbrr)orrVloT_#D7N_>qLQ`;daR_Z.M#_S=41^raEKL;LmK`P]U3_ns:. +_ns=._Rdk*`5]rsPEs/-_n<hb_udor_u@Lm_o9I1^q%G,]qUR]_8jI2`kh?Js8DrrrVG[Gs6]gc +s8;lrrsnl)s7EC,TnI^eRRh75EVj_TE@5dGDfB`9>sj4&PEM&nQ'$ZKJ:`E*K7nf/K8=r.JUhoq +8FZHSs8Dcm!<;Tg$30u%d(?iuV69XnrrN#qiVrlUs8Musq>LHneXZW2"M4I/s8RT~> +&H2M&k([,JS@Z_de'Q@Y_T(TV+O&!L`P]U4aNM`Jb.tTi:fUSp_91$C`P0+.c-OYS`Q%Ji&&lZ: +bL_qAG^kF*JqJ`.K`-N:Jq8N+M3=*fPEqMgI5,GUEcl/<rGhdS%;KitF?tH._*Xo]5L%[Ha<&@? +`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nG`"ZnbMeRnL*f!mdC#I]sdJ"mdKc>nEo]5naZ5@ +naGT3mIKuJeA/ukp[mtGna6>E!:g$Z*:iIgoBlARmE2o_nFuMCl-J_JaiDKBb0[i9aia%ms2IRM +b08#L`P]I7e^9RbQ#gKpKfNX\EcH)?F`hbBCi4'+EHQ8-6%FiTOHPosP_OjDK7nl0KRnf/Ljk#/ +Ir]`jdEg%\`5p%!aof`)`Q%Ji%`ZQ,[s(V15Xo4oaN;cId`;j>aN0`E8PN<Kj7rZLJ,~> +%fZD+s81X.s8W)qqY^BniVriV!<2uqrr3#qq>L=!c0a`gs8Dlkr;Q]tr:fsbs76-us8;fpr:.3k +I>`T0LOoGYre1<*s+Co8OHu9"Q^*8ZC.i\dDgH9rEY!,6DfSd%mUVK_>/L.5rqu$[$ig2(qV]?2 +`7=eas8N!As82T`_M<DZFa/.SF`hbJG'8+UH$FRWG^a[TCJu)_(2.jiG5lb+G'S=TF`qqQG^FFX +F)O_b">4G1Ed2tVF)l;BG5c_%F`DSTI<KgB1^++OEd2hOHB$GHs8Drrrr_KOq#:9ml2D4ls760h +r)KPo<7$5"FaA!%EY3;5E,p&99l#NGQ^=#'O,&FDre1u<K7ei4I=[-)NJEH]p&Fdcr;ZZns8VWg +!<)os$gR0In_jEHqY:$fs5EtVs8W)tr;?Qor;Zd'nE03-j7rZSrr7K~> +#ljl&qoGG,gA1aH"TJH$rVtmV!rW#rrr<#t&HDb/s8)HaSuo3Mq>C9ls8W)ts8N-!rUKjrs7uQl +qsh-jI>WH*Kn')Srdt0&s+1c4Ng,ioQ'6iSBhEJ_D0TjpE;abeDK]l:<."%COK)Buqu6Wqo)AXg +rr*B,rr2rss8Clp_o1+(rVlcrrVc`shSB-.rke]Q!Q;nT_Z.IP_A0u*`4X18]oA&0`Pfa5_Sa=0 +_SX4.rPB5h^;e".ZB'X/bK%?2_SX71`Pf[n_ApJ1`PfO)aM=U0Mlb"9^;@\%p&G'jrr2lmk4&E= +rr2rqrXf,/s76-gpe[Z`;pTtqEcu6qE;sniE-#o9EbS0\Ko_OcP`q)\JV*lR'7tjhKSOr+KReo4 +LdUh7q>^Ens6BRoqu?Wg_RR(`S]^g-rVucph#@<Qr;Q`r$iTnCTq.jNcM@J>s*t~> +&H2D$lC2-bO1WHVd*9bS`5^fX+O&!L`Poa7aNMcJbe^p'<`N1_]Z/49`PKC3c-OVR`Q%Ji&Br#1 +e'6('3cg+/MMd(AKS9>Ws+LE)%t]k-Q^*l$KS*i,EboW=D#JAOD[pu/Cd_jc:P>E2UX.'-b4<Up +`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9aoDA&*p[.VImD-HHnaGo7oCVP>n*ff:oCMMB +p?_PEpuB&jaS>Juo(DPArUKmY*V&Odp%.eRo$XeJg%k:/mc)RZf?)(S`lcZA^<+Oda>1cS`Q63G +b/hT@bIl*QgH:Rb6+q82CNF<3F)uJFEGo]1EGoi>Cee`"NKfZmP`CKMKDpQ(K+`lmM1L;7K8P/+ +/CrIpb/DHBb5TTdb/VHia:5k`@nSmM6@ZYda32QGe&Vs?`kI7-8PNNgk4nuQJ,~> +!WW,trsIN:r;ZfpqYgHorSdbUrs8W%r;Q`rrqlNirs7NCmcjcNqYC$frrrDsq#:<no)A[f-3*f? +s6lCYM1C;4L5:A6KnP,5L4t;9Knu%^PEqG_L2KJ%EH-*rEY!#.G]7,&\7DY#D>jM-qu>p[$ig2( +qV]?2`7=eas8N!*s82T`_M<DZF`r"QrcS6a!-nKgs*+opG]n1D>nmMM$Y=JZGm8G7F`qqQGlDjr +HZsUP8eD@;->%.:H[Bf4E<LE-H$OZ6Fq].IG[N<6!XV53GC+RXN7@M"rVlfr"6f+Hrr2r^rX\o+ +s8;oncW@-6>)$$qD0u)!'QA89EcY,_Lk_(^RZrhfJ;/i6KnTGX%tTFcLkLP1KKSPqs8;osqW[tZ +r;Q^(kO\<6g&M*IrVc`qec,RGs8N5fkO%Wsrr3#us*t~> +&HDb/qq%L7cM7D<r;HZqrr;!Ws8;rsrr;us%0-;+qtg)sUThi:qu6Tp!ri/trr;Kes842CqYpNb +RT>/lJq/N/IY39)JqJ`/Jq\i3Pa7GrP(&+$6ud-`ErBtVE=d))EHcA3A[Z'HN,8Lnq"t*^rr2rs +rXJo,rr;utrSYZ4`7=hbrr)orrVloT_#D4Q_SO+g_u@OP_>V4`]tqh5O,9*Y`l,g4_8F71`5BLj +_DB0I_8ia9PEhQV`50C2^r442_o'=,_Sa@1]YMV(UPtM'YJe/k`P97^s8W&srr)]UnGhqUrr;oq +&HD\.s8;lkb>kI+=G'LfBm9Jorc'-#G&M>>:g&O+OI;K"NJ;q7K8"u2JV/T*KRSZ*Jp2c,lMCJZ +!W2o^rX\o+rU%2*\$MRhrr)lqr;GURs8Vimrr39&p:R,iStk'9rr7K~> +$N'YqmB'o$K>#@NrlYA``5^fX+O&!L`Poa7aND`LbJV*+EDK__\AZS1_o'I9bg";L`Q%Jis26A1 +_8t-KIRes?M2-qEJV8]/K7nr3K8,&7Q'[Z!PC/""7<3?fF`VVDEW0kgEH$#@AlDX-<hFe:f$M7T +ccYk#+NDC?bfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHoCMkOp[\CTrq-]6\\biGn*]Z9o^M8: +rpfsY&GG\dqW#3)_o;9@o(VkInFQMH*:WLfo_nC1\@fH1p[[nFhp:Z@aiDKBb0[i9aia(n(rjP6 +aND`LaMu*<bf\A^Y!/)*9R99AAp4,o!-/!V.;a0GEHG,aM2.4^R?<D\I=[!&Jq8N+KnYA;Mh?b/ +GTk)RdE'DK_8aXsbQ,fTa:QM;b.3j;76a4/UVOdjaiV]aaT'9WaSO$e`O9qh8kWU%lMCPXJ,~> +s8N9$s8Ud.mf*4hrr)lsrSd_Us8Drrrr`5tqYpKo&Gk,Lj8]/VqY:'is8Mfgrr;Ke-3*o@qu-Ei +MI)0gKnP&2KnY24K7no1KRnZ2O-5rtLOaP7DffmlEY!A5E,eO(9q\@ZhtZsEs7tpY$ig2(qV]?2 +`7=eas8N!)s82T`_M<DZF`qs-FoQUtG^4U]H$FLTF`_b2'ab!B%qKh^H8p1nEcQ5GH$OXZG&MYC +;\]H9![_N!FF&.MF`DGEG^=[]G^4OYG%!6;!!!*aCjLGQIZ2eKs8Drrrr_KOq#:9mkl)(iqu?]l +s)O'rBUq/%JSb.&!HE8]E=Y$VKS5ANP)G*LK8,/8K7a)T%u5[gI"dN88)O=Fo`"j_s69LnrVuoi +l1Oi<f)PdDs8N&uec,UH#Q+Q$jQ#Rlir8rYrr7K~> +%fZM,rT'fI^%hX-rr)lsi;OJirr2rtrr)iprr2rrrq4m4YIaH,rVlisr;cirrrN-!o):!7s8;in +s8DqR>`!f[Jq/H*K7\Z*JqAQ*It!35OI28eIrmqmEbtYmrc&KgFDc&<9S?$/UJB_CqZ$Tjo)AXg +rr*B,rr2rss8Clp_o1+(rVlcrrVc`shSB-.s2+cQrk]Dd^qde'_Sa:-b/KF(PDkaG_o'=+_u@UW +`59@,rk]kia2PTKN0''fa2c-9^qn(1`P]R._84"+_SO:0V2L=uOK&5qs2PM`p&G'jrr2lmk4&E= +rr)lprX]&-r;ZflrGd^kAXYMnIVA\!s)J'X!H3)ZD^%)cJqArFOG\dGJqAW.Jq8N+K8+l-H@^m+ +7Gn.Fp](9es8MutrU'Rpr;ZfS\[JuMUA+Wcs8N#riVrlWp\t0l#lO1qSt2FHjSf)XJ,~> +&,Q2#n\AsAEP9TAbfRuI`Sno<ar\XD`Poj<aiqrP`l#BO93>l0a32K>`Q$'Ebf[oD`q%1t`Q#^0 +_TC*VFAR[?LkgV:KS4u0JqJ]-K7JH.Nff`pKRIu/DKBaqF8p7ZD\6u9EG/lFGX\!g3P!8Laj\>R +o>i&o`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[Oh+r:L$\!:fpW&bPhto!lEL\&%\+nF,u@ +nEo]Dnbr%jlM1,=^V%J!`q9'#p@IeIoDS2$n+#l;naubPe[rE,]A!#Ro((tim+9A"aMuBL]tVV2 +n&PXO`Poj<rlR^O`l,d?d*1*>FdQL#0kYcEF*2PDD/F94E,oo:E]JW)Ko_O^LkL;-JV&K(It36, +MhQq9Jqnk7^!Y-@a2PX2aND`Obf]Fr&B`;@[=V%<6UsqY^W"I?bKAebs2OrWqT92^X(+t!94Gs5 +qu?PD~> +s8N9#s8Um3j8Ju[rVuinh>[BQ"9&/pqu-O#f^.Yus8;`hrr2rtq#L?^r[.[Cs8;omp&=f!ArMY" +LP:A7KnG#2KS"f3LPCVIR?2rOMD00gFSKkeGAM>:5F5ucJ<'I)s8Moql2D(jrVcTN`Pf^Fr;HZp +rXf,,q"2FYH$+7QG'.qNG'J<3H3ee>F`VP@?6TgW!!3O;FoH\0H#mtDEd2nXH?sg`B2fEB!X&WX +Ble<:F`MYGF*;hTHMr+&F'L@(!!WE16>h$iD0_)io`+mhrr3)am.gSZs69LnrVlilr;Zc[9W>$^ +4B-0?q/R^$EcH,<2M-C9OHPTXKS4u3L4k/2KnP)0J;B2;J4[9Hq>^?js69LkrVuo]mIgA=k5YJU +rr2rVrr;orrr)lsrqu]orrh?Clg*a5s8W(K~> +%fZM-r:@(bY4;Dhrr)lsh>S&err)fprVlirs8Di^SZ9*[rVZZp!r`&qr;Z?e-NEuCrr;ojs8->; +M2-P3J:W?*JUrE)J:NB.KSGPSNdcP8/ot`IqJ[$dE-,i9D*=+mX*fp's8W)qs760gs8N!,s8N#t +rr;rT`P]XErVc`p!<)lr!T(Wk_uIUR_ZRcn_SZ;f:r1#d`5Tj8Q&greQ]fD,_nj.+`l?'<_SEq% +^r"72^lOD>Q&;-Tahkj0_oTg8_ns7+_SX(*ahk'=MNj6cXM_uj^;Rk\s8W&srr)]UnGhqUrVuco +s8P(Sr;Z`Z8uJOR3)OF1E,T]7EH,r:EH,o9D)?cjM2m[UKnG#0JV&N*JqSf0It!-1Isjbop\Fje +rVulr!<)or!<;Qf$2skL]!Sf@]Cu4%rrE#Vrr<#srr;rsrqud%qr+BCSt)eKrr2qJ~> +&,H,$o@84j@^X8$bK%`Ha5P,>aoKN]`Y-A7bfn2M`PATQ<aD'0aMc!9aSs<aaMl-<o#N0$_T9L7 +_o:0\:KN4(ItiW.KS4r/K7e`+LPCM<OI2)YJr).(Cj#_urG`HgEI2P:>qh7HW,Qb%b/hZGdE;(% +,0%UAbfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHoCMVHrq$0[!:TmVrppirrq=4>]Y25!p$qP? +oCVP>mI0T8rUUQsna='#`lc'>p%\.LoCDYTnc/&"mI0N5o_S.0]Xbnl^u5%`n*/lYm+9A"aMuBL +]tVV2n&PXO`Poj<rlRdQ`Q$$8aO&8M1Rb(*2,%S!F`qnID/F?:Ec5o:DE!9#NffNaK7SN$J:iE& +J:`N0KS,,?HuqB@cGe#EaMl0=aND`Obf\#Ho#MBdd`/G)76F"-D6q+!b0/#OiQ2&=rQ+cV$br$. +:/4N"f(f4DrI=~> +s8N9#s8V$:hYmHVrVlcmhZ!HQ&H;V*q>^?ls4cf#pAb*er;Q]q!rMfknGXg5s8W&qs8Viglq)k] +M2$h;KSG/5KnY27KRni/JrG_IIt9RtF)u?sEXm&0E`7BSWMiG]qYg?krTO4gs8Domi5NXQeboCG +rr*H.qtTg#LO"#`F`qnMG'J<2H3eb<Ec5`%-OpC\!##ZLFaA@ZGB7\@Ecu_UI!TpR9bI=($P"_# +EH62JFDl5CGlE$hGSPOF?oJ2g!rr<46>1LdEI!Mmo`+mhrr3)am.gSZs69LnrVu`os8DroOF*[I +N$`C_q/Rj(E,p&;6u[p3KS>)3KS>)7LkUJ7L4t56KSP&5:VZf*s8Dups8)c[rX\u-s5WS?qV_;O +s8;]js8V*X"T8/or;QWo!<2uqs8N&u#3P7:l0nZNrr.E~> +%fHA+rqj1"V!7UPrr)irh#@<OrVdB+s8)cjV5UfNq>1-krr)cnr;ZBf.0'2Es8Muss7uKX8V;JG +JV/H(KS"f.K7\c.ItN9%MN!@>Il;.`EGt_n&92Z+EH5$)6)CDKo_eaerr)Bdrr;us%KHG,s8N&s +i5NUPec#IGrW)oqrs%>q_o'F1_Z%IQ_Z%A*^r""-`lH)eNKB<dPE<f%_nj1,`lH-=_nj+&^r+=) +P*))pO,odMa2>a5`PTR2_Z%@l_ns:/`NYJbP`C`dWkHBk`5KLbs8W&srr)]UnGhqUr;Z`p5Q1WZ +s8W&sr/Z,oG).>WDfBW6E,fl:DfK]7Ebe!ZKmnW+Jq8Q-K7ei0JqJc2JqS`1IYLV2qu$Kns8;oo +s82fqs7-(!s8;f6]<\W5h"UjKrr;rqir8oVrr2oq!<2uts8E<#c_@/*S[\Iorr7K~> +&,?&#p#Cm6>-,Q\aN)BDa5P,>aoKN^`rF*kb08)Mb/20/?!(6Z^;\"0aSj6`aMl-<o>iE$_T0U3 +_oU6HdE=1_Fb5=(JqJc0K7no1KnFo/JUr`=M10t6E--2BF*%;"&T;Z2FD+-`4Jnc-d)sDKaN;Tq +a<ejF`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8DoCMMBr9s[UrppZoqTHC[_84"'p$qP? +oCVPOm/c\Grppirq;f,u_o0R7an#/roCqnFnaZ):rp:`po^qb0]XYkn]u8n%q"F.9cg99*a2l9C +d(R08b4!CS`l5j8`r4%*a3)9?c,n,VF)7:hLEC)DF`qnICi+<<Ec#f;CdW2uK8528K)U6:KS>)0 +JV/Z0LP:D,H9A(XbfduF_T'I7b5TTeb/hTBo#M<`d))V\5r_G,PIJZU`lS/%ilM/>rQ+cV#ekmd +;c6MBjno&WJ,~> +s8NQ,s8ViHj8&`Trr;orrSd_Wr;Q]nrrE&sr;Za&s75"1lMpn\q>UBn!rVrnl2CtdrV,hQKS5/: +nUq-tL4_F%G&DL!EY!/1Fusl&UM["#s7u]nrr;6^$ig2(qV]?2`7=eas8N!.s82T`_M<DZF*2VK +G'J7Wrd#Z3F)c23A029b!W`9$%VBg-G]n4LEcl;BH?OUZF\N\N!#5YD/Sf?KH$=FQE-l_QIs,pT +F(RB;r;[92%n(8TF*)_eeF`e>rr2p"kj8*Drr;!W$N0WfX/\X6;0?o"rc.sY#]Xd/D0'neE/"+@ +s+^E(#DIb`K5tZ!r8IV[qu?TRn+ZP/rr3-#qu-Qpir0)Yqtp<jr;Qlrs7uZnrsJDal0%=,s8;lq +s*t~> +$iU)(s7k*6Vq:_CrVlfsrSd_Us8N#trVlcss8Mus"o?'-ZbZ>7rr`9!rVl`poD\[frVd$$q=-t- +JV3HD#ChGZ2J[DNFSTkdDfBbXF+^*#W:Kubs8Drso)AXgrr*B,rr2rss8Clp_o1+(rVlcrrVca( +hS@%H`5BL0_ns=.rkT)^_8FC4bE\0LOctoiNlM%7/]5TKahbs:]Y2)$\sSGBP`q>hRE3@b_nj:0 +^W=.)`kT@.`PnsBP*_;iNf0n9`!s]'_=dj.rVlfpqW@;Imf*.ar;QTn)#j4tW2;n':2t5kDfBZ8 +E,KN;CiX\aDhIt>rdt`5JV&K+K7\]-JV&GkBD2<'rr2rnrr<#grX\o+jh8=8Wg`_]rr2rtrr(jU +rVllsrV[6*qu?Tns8Vi,US46R`Vf]7J,~> +&,Q2'qW4e]?CJaO`Q?3Da5P,>b5]Q_`rF-[aqi4DaMu66ISs<`\]M_+aNDZHb/hQ@`q.7``l5p: +`lQ<Fbg";R.<0ZhLkYDP#CV5T1i.;QGPuU]E=[/2C+X7PSmRApc,%WGaN*km*lc1=bfn/IaN2E@ +bL4JB^Uh&-bJq]Ia2uKMgsXsHr:9sZn,;WPn+,r<p[@mr_7I=s`59:_nF,i;oC),8l1"B7o(2_> +^Tb>c`QZ0=oCMMEnFH&5o]tr;m-X?9p"?me_SX()^Z#%_oC1edm+9A"aMuBL]tVV2n&PXO`P]^8 +rQ5,]qo1G:f/'+s5B086F`qeCCMe3:E-Z2;F?XPpKnkG;K7A?"K8"r1JUrH+KR\Dm>YEMmbfIm) +`WF6(b5TTeb/hTBo#MEcahrp-4[)J2ZG=K$`lZEHb2UMB`rF-YapuV8c,[oIb.):`:JtMam/?s7~> +s8N<%s8W#MhsgXF!WDrRrW2rrr;Qitr;?Qns8;os#Lr#&s8W&nrr2rtr9!t^qteT+LkG2M#D[hF +6$%$gD>A2_F)XI8;l?9io)Jahs8;ool2D(jrVcTN`Pf^Fr;HZprYkh6q"2FYH$+1NF`qqQG^4UX +H$44EBOiD!!rW*3!Y8pcG'8"LEH5uFD/t/IF&<eP!#,GB/Sf?KH$=ITH#J(SGC=CLB/^:u!"K8=% +n(8TF`r.leF`e>rr2p"kj8*Drr;!Ws83)%B;^])5]cpFs)SNfEH68;Ecu.tA:=9,s+^E(#D7_bL +I'esrSd_br;ZNWmITl0s8)cqqu$Hnj8K/YqtpBirrVuprr)j(m-EltjT#8Xr;Q_H~> +%K-5)s8:cHUWE3/rr<#UrW)utrr;rsrr<#trr<!,r8X<Q\b,Xqs8Murrquffrr2rprWiK&r6@]b +It.$@#_Rk]C-ZfXF)1Sj&92SPQr'TL<q?:jrr;orr;ZBfrr;us%KHG,s8N&si5NUPec#IGrW)oq +rrh2o_o'Fi_\9o'^;In-a2uGgP)t]eP)t`a`kq_m5/bI]_99R1ahG^"PE;0%P)PK^RE3@b_nj:0 +aLoL-^WOF8aek)\R?WeqNf0mT`5BR3_=dj.rVlfpqW@;Imf*.aqYpEm#Q1W6UkreJDuO_UEXHf) +Dfo]4F_FcbI/JTqKE$N&K)^K'Jd6j[K7uPHs8V`jrr;Nfs8*8Y^:L_LX8;kqrr<#srSmhUs8W)s +r=8l)s8N&ss7ijkSY;e-rVcbH~> +%/Kf#qsD()>Dg,5`l[)Ys2tA_s2P)[r6#&\&](2==Ce_N_SsU=aN2NF`Pojga99N%`Q64$bl>`h +a31D2H%(I$o7I="JpV)nE,]o:rH%pW&9MhMO%Z+26Hmp$aO//N_T)2g*lc1=bfn/IaN2E@bL4JB +^Uh&-bJq]Ia2uKMgsXsHrq$0[!:TmR<9`oCoCVbN_ns.!]u.e,^\70cn+6/>mcjB.o)/(SjLqt5 +_nNn,`5hK>nac,;n+5c6mI0i<p\<7J]"u5#a25UMqY'OMj3R)DaiDKBb0[i9aia(n"ieO#`l?+! +b5TK^`rF"6b1Mn[SV1N6DKU)CE,BH6G'I\=EFVgPH@pp,KnFr*It`Z3K7ST+K7\]&FsafKc-",K +rQ>)_"Nng*`PqAg&&ku$8NK%.@_'FsaN2KGb2LGA`rF-YapuY8bfIrHagbbN9NG`*nbrK<~> +s8N<#rr<#Rhraq<s8)ips5EqXr;QZp"9/5qr;Q^#rql`qcK46grrW,ts8;irs69Lfs82WfBQ&Z_ +n:V"#@S:c\Fa*Y%%WHJO@#q?q`W,i0s8Mfnkl(tirVcTN`Pf^Fr;HZprX&W%q"2FYH$+1Nrc\<d +s*4lsEH,o-?n;ijrW!W5!X03LEclMGF)l>GEd)_EDGqDRqZ%rK/Sf?KH$=IUGBS=ZEcZA11_9Wf +!!!-*!t.G4F*;bUNR[V#rVlfr"6f+Hrr2rWrYYS*r`>Yh;*f/AEH-&@EH-)FE--8E5"C\0LA6E+ +K7Zb4q>^0_rqlWarr2p*m-X01irB&Prr;lmrr;$X"8r&nrql]rq#1-j$K^X;k2ZLAr;?QoJ,~> +!W)fprrqkiU:0aorr2uri;Nr\rr2lprr2os'`S(0rr;rkT<,<Yo)Jahrr<#trr;Nfrr2utrr)lr +#QO`"qe9r$K^s`pK*I$<8oefjFnotcCi;=>N2U""s8McmrV6BloD\ahrr*B,rr2rss8Clp_o1+( +rVlcrrVca!hS@%H`;@IP_@af&_og!@RYm2hP*;#gNf1oprPUk<`l>d4a1fX-O,B*eQ&q)jNg[u- +_o'=/_o0I2`4j48_l/ZTPa%>nNfT1"`5BL2_SPpFs8DrrrVG[Gs6]gas8)`mru:Y2<h#p\4`#(U +DfTl;DfKi6E-#t[7#Z_LJV!WKrIb-%"b0.[qZ$<arql`crX]&-`O`OfT$dN:rr2rtrVbaTrr<#t +rVZcsqu6U%qY]i[St)OQkPbAZJ,~> +&,?,'rU\BS?Z`]na2l?A`n&60aq2J$=&iIp[)U5/aMu6Bb/VHla:QA1`QHHOccjJL^r=Mh>^qS# +K*m0YJ6YQ]Ciji?EW'tYE=cu)1ff=&9;^.X_9C0Dahu-ia<8LA`luZJ`Q6-@`QQ]N\\G_fe]YtT +b/_WHceQt'nFQ8NnQG>Jlg*s-mIL)Gq9-Ca]t;"t_o0@anF,i;oC),9lh1&Er9V,(\%TMi_oBO5 +oC;A?mdBK1n+$#<p&4O7]sb_o_oBX3^Z#%_naPSbm+9A"aMuBL]tVV2m`>@HrQ%%BaN2B@`PopA +ha*9m8NLX.Ec>u8DKL,KDf9N-1-LDDK8##3JU`6)LP:A3It<0'IWdWDd*KGIb0'S)"j4p-`l5pf +a9or(Z<fpX6V3?P`VmmXb2LGA`rF-Yapu\9aiDK?`j/Z;8R$2SoDS]>~> +s8W,rs8NDehr"J6r;$3es5EqXr;QZp"8r&nr;Q^/rqZToi8<bls8VuqrquZmrr<#^rW`9!qt<(( +K(+EtIni+GG&D<qEY!>29O=ZSEVT;(rr;rms8;-\$ig2(qV]?2`7=eas8N!'s82T`_M<DZF8^:^ +GR8Y?H#RV5>pU-kr;[!%!X03LEr9tcFE;\KEbS;b"U,#-!%7pL"tOJ/Fa81TG&qtPGB.J-3=#Zk +"98E*!!!9iCNXlIIuVtMs8Drrrr_KOq#:9mir0ems7OlCUR"\]FE)8?EcH,AEccJKA5,75q1e]u +s+U\p>ke0os7cNir:9jdrsRoXo'b'-s7ZHlqtpBmir8uU!<2rs"TJAprVlcq$K^[@j6$CArVZZp +J,~> +!WE#srrr>.UoEeZrr2usi;No[rr2lprr)j,rr)fps8Mc'V68&7s8N#ss6fmcrrE&tr<`K's8Dur +p,R\Qnq-mo#(KB0E-6#9q/?mcC.VX+LMutarVlipq>^EnoD\ahrr*B,rr2rss8Clp_o1+(rVlcr +rVca!hS@%H`;@Fc_SaC0`Q-#cMiNsbPa.AjN/P]nr5:_;_Sj7-_mbYbPaISmP*M2jR`NIc_ns@1 +^rO4-_ns9gMiX-gO-,N_OcQQ^_ns=-_=dj.rVlfpqW@;ImJd(aq#:6l)#)Q]Tp&,PEc5l9EGof: +D/XH:@S8h,K7a)Rqh"`u#_[nI>PJ-qs8W)trr)iqqu?3cs8387\\#>=nGWCdrVuoTrr<#urr2j, +rr;rss8MlhgnUL5TX4:hrr2utJ,~> +&,Z>*rq>?)@UlIRaND]E`n8?4`r='Zaq2S(FAl@nZ-(20`l5s?bfIfpa:QA1`lu]RccjDH^;nII +,^On0K*m0YG=FK+EGKN5EW'tYE=d2*6r]\$<mnt(aO&5Qahc!gaF2(I`luZJ`Q6-@`QQ]N\\G_f +e]YtTb/_WHceQt'nFQ8AnaGr6lg=*1nFcVQahPU+^V7M&`5BCanF,i;oC),7p%%nQm(g6K_nEUu +`l5a7o^hVBm-a3)oBu;Hp\!7N]u.e*`5f^0^>JbYnaPSbm+9A"aMuBL]tVV2m`>@HrQ,#]rl?)! +`Q$?P[R$.<8m6:TD/X?3F*D\HEG\`?0Pu8ire2,?JV/`5Kn4`'JUrN-@Rntp_og!Abfp(2s3(Pe +aN4>"o#M6Y];\Li4\/)I^raaAh8oW9s2b/]&'W#5`Q#d2SlJBV>(kZ&rr2qJ~> +s8NQ,qu-Q_gu8;5qY9scs5EqXr;QZp"8hoir;HX*qu$KnfC8&)s8N#qq>'ses760hr;HWors&<! +s7ChQM=H6(L3Z0n??C.*q/Qjc:dh%W>2o>Vs8N#srrDu]rX8c)rVGHk`5L4(rVulr$NL"uoYQB/ +F`V_Lr-/KjE-5r%+qP+`qu@c="VG?dF)uJIG'A%NF_at`"T\T,"9JZ*!!k)hDfbo%*d2jKFE)D2 +/.`!d!!*0%!!WE-5&5:dH$t\%o`+mhrr3)am.gSZs5O"cr;-6YG*&V58p#)nrGi0bEHlPH9:]:5 +q1e]u$&+$pB_VE(p&G'frqlWarr<!,rp07RinaY6q#(-gr;Q`Urr;lrrr2p$rquTfr;HWp#OgdA +mG@=3s8Muts*t~> +$N0o&s8W)9U8-WArr2usi;No[rr)cnrVca+rr)cns8VuRS?KNqr;?QnrrE&trUKmes8W&urVld% +s8)cqoR:8'KCa[#K8+Y>?<qVjDtn8Y9L5;K>2oAXs8N#srrN&toD\ahrr*B,rr2rss8Clp_o1+( +rVlcrrVca#hS@%H`5BLl_@si(_nO43_NB\6Mj'EjP`Lc`NQ1t95Jt@U`59F/^q,)VOc5KcNg5fi +OI=2/`5KO2`5fR,_99]^LlRUXNg#N_P`q62`P]O0_SPpFs8DrrrVG[Gs6K[_s8)`os8W$(nop.j +@7>6WE,kkr%<63*DfJ@<=a5RNJq8LMK)L<-Jq/A1Ab>j!p\4[as7-'tqW58u^9"L2rVuoss8V!U +s8W,us8;rsrVmE+rr)N1US"6N_tj91s8W(K~> +s8<E,rqYcF@p555ai_lH`o"l9b5]Nu`l5s;aNDZH^n+;,C9>S$aMYp7bg"<"a:QA4bfn>UaMu04 +aj\[P=b;4rK*m0YD`Up$Dej30EVjegFA4l`QpSU5b0%fLccsJF`q.7q`l5sAbfIcEaN)9Cd`Au6 +]"?M9`lcHEai_rbdbF9_oC;AMmoSoFn*^&LprL7i_8F+(^Vdt-_=mBen+6/>nF6)Fp[Yc/_nO+- +_8aC-^rlHEoCD89lga<3pAas7]thP$_oK^3`kK+Aq=O4Hj3R)DaiDKBb0[i9ai`tkrPnlYrlY8^ +rPff"b#j(_@S(QXCi=<5F*)GHChPqi8o&g(K8#$YK+j#oK7SN%JV/W*0iZ]Ia10.1b0'_-s2tA_ +rPnBK$,Np*8j>d3@(4)Qb1ar8b5]Nla2>j6]STW^9j+(OpAFpiJ,~> +s8NT-qu$Kig#`86q"FUas8V*X!W;rrrri>sq"Xabs8VurrrU^;k5G;^r:p'brVuHfs8;ips8N?# +s7Z-clTp*lKEm3S;8#/6Ed@J$%sUQcYBklsrVZQfqZ$Tns69Ljs8Domi5NXQeboCGrr*9)qtTg# +LO"#bG'<e.#^1E.Ag@N_#6Xl(5QLruAT2^5G'J:XGBRk4#QOu-!!EE+!WW3-.VNaAGBJ+QG]\(O +AiBtq!WrE&"98E*!!YW&G'S:[NR[V#rVlfr"6f+Hrr2rWrr2g1s5ZYNVFYE>F)uACF)c>GEc+2# +VG?rAq1Js+LIniKs82fqq>U9ho)A[h$0LjQo[Ws@s7uQkr;ZfUrW2rrrVm'#qtKsbrVlg#i8j1i +hu!EQs8E#uJ,~> +!W;rrrrrDNTqTX(rVllriVj#\rr)cnrr)j!rr)cnrr35pR]<aWp\k*jrr`9!r;?*as8Vuq#lFYq +o`+/?IY76D$%mqT;8#/5EHlL"E!CAMENOM?q>UBuq"k$jqu?]frr2rsrXJo,rr;utrSYZ4`7=hb +rr)orrVloT_#D4P_Sc8f&BD]-O*Q>:OHG]iOcGH`NlV.;rke]Q3l\tNG'o@1N/rsYP`_#iR`NIc +`59I1`PTL5_k)1%Mi`gTP`UcfPEDrc_SO1-_=dj.rVlfpqW@;IlMge_q#:6l(Zn/cU-iU3EcQ,= +EGof9DJMJnV+cPpK)C3!K)L<-Jq/JAYkJ(os7lTis7-'os2_p^[@c1JrqufRrW)utrr;osrr)j- +rVlfe\"]IcT\'&>rr<#tJ,~> +&H2Y.s82,`Ala>maihrK`5^`VrQ5/^`r3jh`lQBH`j8KE?_#']`kfL1bg";uaSs<iaMu36behH] +e2)B$o7IC"HYQ!U2Jd5PDfPYq&:$WZTO_Z^c,R]=aO&2LaN!hm*lc1=bfn/IaN2E@bL4JB^Uh&- +bJq]Ia2uKMgsXsHrq$0[rpNnXoD87\a0`P&aMbm.]u%_,_=mBen+6/>nFc\RqQ[KM`5Ka8_oKU- +_T_lMo^_G<mIBc@s8L][\&-/$_TBd3a1f4Bp[n"Fj3R)DaiDKBb0[i9ai`qjrl4uZr6#&\)ofk; +eA!`4UISp2DK'Z=Ec?2ECLT!?OZdr<KDL95K7A?"JVAc15bZlX_T0X8aSj9]aSj-Ia9o\fBM:QV +4-$nlbl,]a`ne`7aq)M4`kfR2\T_(H93o$ppA4dgJ,~> +s8NK*qu$Koi9Bb2q"+=\s5O"Yr;Q]q"TJ2jq"t$i#Q4Dqs6Jb0oD\alqtKj^rVuHfs8;ips8W,s +"TSJpCM*$g#$m#T6?$j]q/QdC8Z8FXqYL0jrr2p!rVQWZrX8c)rVGHk`5L4(rVulr$30ntoYQB/ +F`hm*GQi85F(?[1rW)ouqu@07@W6C3G^4U^GApas"TAE$"oJ?6#:aA(EcuSLF`DbIB0H_)!!!'* +qZ%$05](XgG'o;!o`+mhrr3)am.gSZs5O"pr;ZWgp5XNpHVn9nF)c8BEHc;EC.J'i6huK4KEm*b +M(u(,s8)]oqu6Kjo)A[h"Q/bDnCdg@#5nAqr;Q`rhu<TS"T8)iq"t$i"PDc#lKS9I!ri,tJ,~> +!W;oqrrr;`WM$ZprVllriVj#\rr)cnrr)j,rquZkrr<#lZCeGKp\b$hrrW,qqsj[crrE&rs8Vs# +s8;P(A:]C)JdI'_?AJ)<Df0H4qJZX:7&?VMqY^6j!r_uqo)AXgrr*B,rr2rss8Clp_o1+(rVlcr +rVc`shSB-.qSEub`4_(WH$tU5NfT9aOH>Wcai)-8_Z%A5^;%7,I!L6qO,o6YOHPcfRE3Cd`59I2 +^WXI,TR(s7I#3oGOctoiP`Vuc_nsC1_=dj.rVlfpqW@;IlMgb^q>UBn)#a8jH(B+T@W?F,EH,o; +BldrWp[LS'K7a#Ps+:3%s+1N)K7bbRp](*iqu6Bjnbrpn^UghSU\Fcdrr<#Qrr)fmrsJ`$lDgPL +S>tiOrr2otrdX~> +rr*B,qru(>;e<YdbKS#G`o>):ar/:?`P]U4`lQBH`jfe]>(OZ@`kT:+c-OVVn]29aaN2B@`P]U1 +`R35f<*+Bso7I3rGYibN3rWjpDfP\r%s;#GTT_"Zc-+/Ib0A8S`::ni`l5sAbfIcEaN)9Cd`Au6 +]"?M9`lcHEai_rbdbF9hoD\8\oCVkO`jiFgaj%c?]tM>&`P;-9n*fl>n+-,Fo!Q!;_8OXDa2Gp6 +_S=Cnq"F@Jmd9E>q"W[U]"P\mai23<`4s!sg\(1.nDhj]f?)(S`lcZA^<+Oca9g#1aMu6=`lQ<F +rlkDbs2H"p_p3FGTmTO>CiFE:Ec?8?E*P6Zgb*euJVAmXKbB#hIsum"KnP;8+cO^g^;Iq0`r='Z +`rF$X`WF6(b4<Ub^8Y:)4Zu06^rXaBb08#J`o"l7aq)P4`P]L+Z#!K87q^*=q"t'jJ,~> +!WW/ur;Zd$kNh@3rUosbs5O"Yr;Q]q"T8)jq>C3k%fH5#s8Us@jo>>[r;$-crVuHfs8;iprr<#s +"T.jeK8&iK#Cf5+pLRQMF89he:3s'YVY^5fs82fnqZ$Tnl2D(jrVcTN`Pf^Fr;HZprY>J1q"2FY +H$+7SH$FLUF)l24/e/$crW)s%!!<*!%0p9XEclVPH?jI8'*&78!!33(!WE'5"Xn#$F*W"SF`VD7 +57n&!!!*'%"T/6.#=*-KG]nCmeF`e>rr2p"kj8*Drr:sV)#F7/s78saV`e+"F)Z/AEH-8B@;#0, +oS<<upk/j0Itr&PrVcZoqu6Ehrr33%r;?Qns8W)t%fcIikPOc/s8W#oqu$HnhZ!HQ"T8/lq>:-j +"P;c&kO8BLs82lsJ,~> +$N9o%s8Vul[@aAmrVllriVilXrr2lorr`8ur;HWp#5QoAZ+Ki,rVllsrqu<cs8W,ur;R$#r;6([ +JV&OGJd@!W7HX;U>B4c[E">N_X(nL.rr2rqrquWms82Bdrr;us%KHG,s8N&si5NUPec#IGrW)oq +rrLulrkecR_>_=O_c4RlNd,_pJV&K5Nf]?bP*:pJ`l5m5_8*t)\p\XOI<C'nN099aP*:rqaMl'7 +_8O:2_n_gfG^FmgI><rHPa7DqOK?F=_SsF/p&G'jrr2lmk4&E8rr2rlrr2p5nk5gS3EC$<DK'Z8 +CijH"BCkulK7edSJc:9"KE$N2L3eDg>PnC!rr;usoDejh!<2utq>LW\_6LSQYP%nns8W&ss5EtT +rVQTrqt&kIU'.!op&4gfrrE%K~> +&HD_-s8DEAJl,O\ccaJN`Q$oYr6#&\!64uV'#r#8b/q>_;HRYK`l#R-`m)iPm)TUT`P]U7ajAYn +4*>n$o7IC"EAQ&&<_mROEH1qu&TMkfH)+JqdEKYO_og'?c-+)sa<8LA`luZJ`Q6-@`QQ]N\\G_f +e]YtTb/_WHceQt'nFQ8Nnc/2^o_A=]bI4pq`5TU6`5'7.`P]=]nF,i;oC;JKos_0B^q.S,bKe2J +_nj(4qtfsWmdT];pA*IS]>;A#]Z&"3`lPm-]%ZiKnaPSbm+9A"aMuBL]tVV2m`>FNs2b2Zs2Y2_ +rlkDb)p#k7`7!-tU80\FC2e06EH#rCBMqXUgY@"%KD^K+KnFsUIgq$cNIc^n7FfT'`P][6rPniU +!QN4[b5]Nbb/hTBrQ,#Y'ZeG<\qj<E6q:Ie`Q63Cb0A/M`Q$oYs2tA_rlPen`l5m9^p^(G<)H;3 +hYR'Hrr7K~> +s8NK)rql`ql0IO1s8;fos5<nVs8W)tquH`prsA]&q>^KAmd'`Krr3&trVu3_r;Quur;KcBKnB,R ++,59!JqJK/Ir/urpk)IaEHH)@E-?5@<(sEd<V?4gqu-Nms69Ljs8Domi5NXQeboCGrr*T2qtTg# +LO"#bG^OdVF)ti"*Y&;L!#,G9!W`9$#[;4aDfg#ED,(N?!rrGu!"K/X@rZdDJ9l<VAi^D+"nhp) +#XiKOGBA7meF`e>rr2p"kj8*Drr:sV+8c*<p]%L1W/*o_FDc2<EcQ;A<da]B`(YlBL4Y;5L&6Q' +K*I*]Kn_nWpA=mfrquZqqtU'frri>rq#:3jrs\o,s7PUJq:GZHqtKjarrW2tqr.PQs8N!!r;$9h +rs\;UlfdI%s8Dlmr;Q_H~> +!ri5trr32u_kNpcrr2osg]%0Or;I!%rquAUXgdHirr30"s8W&ss7?6hs8W'!rVlfr#5e8q<-EkE +q19oIIt`K,I>WJfC&%IV;/gGoCiaK9DfAWFVjgWXr;Z]ps8N#rrUBgcs8N!,s8N#trr;rT`P]XE +rVc`p!<)lr!T(Wk_csmn_S=(7_Sq:YG^4aeI=@!2OHPchPE<f-`l,j3`59$:Fa\UcI!g?sNffHe +P`hEQa2>a1_8=:3S9K+&GC"O]IYa)MP)trkY/J5o_oBOcs8W&srr)]UnGh>D*rH!;qYdX.V1_0R +F)H);Ec?)9<."H@_a]-.J:36%rdt'#$A*qZJ:g&Kp](6lnc&[gqu-Kn%K$2%rr2rpe@3-*Ra^m- +rr`8ur;HWpir8rUrVlfr$iKeuqSB#'SY<mtqu$JE~> +s8<H*s8MfSQ;pb\cHXMO`5^NPrPnfW&B)Js=BT('\A#l&b0J>O_T)2grl,Gjbfn/G_oTmGhEbn' +I=qBM-&-o%J:i9/HsTe'e7CdYE-6)BEHuSB;+mgK4O;3m_SsO;bfn6!aF2(I`luZJ`Q6-@`QQ]N +\\G_fe]YtTb/_WHceQt'nFQ29mI0N<s8;o=_S3h)`l5j6_oBa;`4ihPo^;,;nFcSI_6h"m`5KR0 +`QH9@_8*h-pA4FQo'c)CqUrEl`Pom7^VRq3ai2'0]AE8RnF#Jcm+9A"aMuBL]tVV2jN.>Crl?h7 +ccF)TP#S*,6Z@$]Eboc=G%jBMdG(HXIuB2:NJ*.DK7SN%JVAl;KS4_)aj&)M`W!mV`W!mWaSs=) +`lQBH`P]d>b/;38bKS,5CHasT6&iM!`P][;dEfeJ`oG,Cb08#J`r=$h`l#a8a2Yc<<_l=iNp-E= +s*t~> +s8NT-rr)lsoAo$$s8N&ss8UOH#5nN$jQG[qr;Zfp!W2i_rr)j%q#C*?5DY#Fq1Ki@Mh?P3M1("2 +g&L]3:iUMtF),r?DK&.0Wa*mFrqZTmrr)l]rX8c)rVGHk`5L4(rVulr'*%k(oYQB/F`r4XH$jXD +?m?*aq#CBqrW!B.%VKHmH#@eD>7U]7"82^+""7o&Ed`=XFCd?@"pY,.!VcX'"?UOHH?OIjeF`e> +rr2p"kj8*Drr:sVs8O,:s8DRuT;PXsG&V;:FE2/=A:"%GrB,+MM2?b9JGY$"K*Ha^Jr4;eqtpEk +rquZqqtU'frr`8qp\t0l%K?>+r93\BmFVC<qXsU^rr`2rqu#FPrr;us!rViirVm;hkj.Ber;Zck +q>C6lJ,~> +%fQG+s8N&se"<5Wr;-Hjd/FUVr:dXqWn7:MrVZWns8W)uoD\ah!<2ur$3'u#s7k/.KnP$QJf]K$ +K7JQ1I=a'$s7MgVE,]i;Bln?2Db#b_=jHjCqYpNprr;rdrr2rsrXJo,rr;utrSYZ4`7=hbrr)or +rVloT_#D5U`P9:4aMPlVIX63aH[0mbIY<W?O-#TicG.6?^W=:'Jp)TlFa/1UH[^[+OHPljSBSj_ +^V7J'`1;7!H[0jbH?jjgMN3d\NfBmS`5KX0_=dj.rVlfpqW@;Ih>[HQ*W5s8nm@l]:LA6aDJsW9 +BlIO-q=j_DC3YDbIY3.LK)L<0JpN6$LM(c,s8Drro)AdgqYgBm%K6>(r;6N]^q@4aT^;UUrr`8t +r;Q]qiVrlU!ri6!rVm6'r;HN!U7\$MdJWnAJ,~> +&Gl;&s8Vu`XAhlWcH=>I_oC-G&B;]*H<!psZ+Iruc-=GK_T)2g&]Vf0bg"AS`P]I<d(1iYIt*+I +KdDA2K7JQ1H[R'Mf?&.rCNF]CCj1&@D*s8U9!Zde^raR8b08)PnAn8B`Q$-GaMl6Aa2Q6MaLT's +]@G*Eb0%cHb0Skkg[Oh)n)s*7qtpE?_SEt(`P]U3^r4@:`l#R(q<[PEmeZ_N_77>"^;7b&_SX4i +`@f!?bPUr!naQ&DqU`?m`l?*F`PB=,`lH'8\[U,ap@Ie3cg99*a2l9Cd(R08b2:8tb08#Gc-4C& +OJ5Z]F)5Q/G'.V<;cq;df-Y0\Mhlq@Knk;5JU`6)LOkM;Jll:0d`TPKa2e+trQ$2*aMu6Db/;-< +b0%`D_op-<S527078C#.c,7<6b0ePS_8bNV(!=bC`l5s=`l5a1bK\&=B2(li?`*5fs*t~> +!r`/trr2rt!pAY&rr3#rs3^iFrsShXlfA*GrVuooqYfUV"o\=AC41m3KH>MoM1^D4F^4eCrJFBp +DJsZDBle6*=KRX"nc/Ldp\Xsis69Ljs8Domi5NXQeboCGrr*c7qtTg#LO"#bH?jdUBkJq'#R(;4 +!<<*&qZ%oC%V9j5H#dY,$NgD9!rrB)!!*'"!<`N*"!_>oH[g6ZAMXbr"nhp+!<<KlF*)SKHApAG +s8Drrrr_KOq#:9miVjqtrr<#ps3=TEQUbq4EHQ2AF`DBtqu?KB8V2qVIu9$WKFEZjJqSS6oD&@c +rr2rqrquZqqtU'frr`8qq"ssg%JAiSp#YQ?s82Whs8W)tr87MQs8W'"r;$0errh3BlKI('rri/p +r;Q_H~> +!rW)srr3?)k,4i_qtU3fs8URIs8NK'r7[R?_"dp,r;QWms76-hs8;lqrs&DuFD,uTKDpK%KDpHE +H@^j&JV%rHp](5N:3LGjF*M>;DIlnJMeV\\rr;cnli-n`rr*B,rr2rss8Clp_o1+(rVlcrrVc`s +hSB*->/J1o^Vl1SG^"F\H['jbG'\^rNffKa_8+(+^V@L(EclkZG^b'dH$FXdMij0^QGp_]`k]O1 +S:,L+G^+X^I!^-cJV]>MQBnGg]=u>)_=dj.rVlfpqW@;Ih>SMnr;ZfmrQS3<P=9;+Dfou=F)>gk +r;ZN<6@F]BIYigYK)UE&Jd@*`IXui*oD/@arW)urrqZQqqtg9jrso&.s8MuqrntH%[&:V3qYpKs +rr)fprr:pU!<)lqrr3E+s8);`TUhdQl21M[rVqB~> +&GZ/$s8Vrc`*cGia2H<?`l?KKs2GSb`h$"3BVrAZbg+AO`l5sga:cM6bfn5N_o'L<fj.j*Jq8Q. +KDpENK8#)1Ll?q6I:bq#f$\7nEcH,EHYR_D@oB+Q<70@?`k9:3b08#NaN!elIE'7Gbfn/IaN2E@ +bL4JB^Uh&-bJq]Ia2uKMgsXsHoC;25nF?)JbI"jo^Ve"+^r4%+`Q6*<^:<\(q"4=Upp.BCa2Pp: +b/D98^r"(2`Os+ZnbN%SqYA^T\&6/'b/VNA`59F2`l>p4gALF-o&S-`f?)(S`lcZA^<+ORaT'@: +bfSG@5bX?1D/F67EHcS@@GB5Zd(22^Ljsf4N/*%<JU`6'Ko:b:Hu'nPc-42KaN=8!$HC0,`Q$'C +_o'R<rPoVp`k.!q4[)2N\]2k2_8XREcc*fAj2_tXbf[rE`lQ6@_o'[B_m3E<78[a9med$7~> +!ri5urr2rt!q>@+rr2updJj1G"o\K$eFVSsrrrE%q>('hl2Cqfo@Q9[NJ)lYKHGu&Kn=u1Kf\r" +qY$"HEH?5>EI)YC7%U5Siq`KDrVucos8V?_$ig2(qV]?2`7=eas8N!0s82T`_M<DZF`qkIDJ(=, +&-`%8('4I9":,)0!!*0*%Vp`BG]?[m"UtY:r;Zm""U4i-&-<%`CN=B3G%iZ9!!EH*!!E&trrNW0 +"$q!PH$+=ieF`e>rr2p"kj8*Drr:sVs8O,:s8N&lHA/P0@rld/FE2AB>#4ejr;WBkK7eo4IJJO& +Jprr9LMK9LrVu]mr;6Wnq>C6l"oeDpq>U<js8VEjoD$r;s82Wkrr;uqi;NcTrr2p,rquZlqYU<m +rS[&.kiMgD!<)op!<.K~> +&,lP,rr;uroX(ErnbE.]s3^fUs7lW`S$]EZrr2iqrr2r`rr)j&o%-!SM1^;0K)C6EJqS],J:`E. +3VDt@pQ83iEH5l6G]7IdSY8p=q>L'es8VEarr;us%KHG,s8N&si5NUPec#IGrW)oqrrLulrPMgU +`5KNJFF87VH$js`G^=X[I"m`JP)7#q]>)1dGBSCZFa&.XGBnIWG'\h"O,]IKaM>@,`0bakI=HEc +IW^'dH?jpiLl[UUWQ)`i`koRbs8W&srr)]UnGh;C*rl-;rVcD6K</BfEH>r<E,TYs:A+V_s-cr; +JVJf)rdt-%s+1N,I#ri2BgVLjq#:*hs8)fprr3K+rr)lrrqOjU]!Rp`p\Omh"9/8urr2rWrWW?$ +rVc`prVuos$MiPQTUqpbq>C9lrVqB~> +%f-##rr;ogeok55[_g8*dE)@-%_fuj=D(Zn\]2b9aMu?@nAmf9bfn/I_o'^<\LVr[JUiH.JU`,t +JVB#>MhQe1GU1nbc-()hDK^5BE-ZMC6(!s'a48JN`6?6Bb08#L`l@SjIE'7Gbfn/IaN2E@bL4JB +^Uh&-bJq]Ia2uKMgsXsHoC;;=o_81![(X&b_8F4+^Vn15`lQ<D^U<_3o(W.P\@BMo^qdn.`5Ta5 +^VIb+`P'1^p[dnSrR86d`5od5bJD9>`PTI.`PoO%h#-d6n_qg\f?)(S`lcZA^<+ORa<\pIbK\Pf +@<SJP@WZd2G'.hA9/=c?dG]gLFEN%cJVSr3JU`1KK*d$iH?E+1c-48MrQ>&Zrl-,#`l?0B`Pp!D +a2l3>aMY&q76*e"Qb:2X_nj@8ccsJI`o>)>b5]K[a:-,-a2u)e<D5k_IbF5fs*t~> +"TJH"rVlfr#k[!-s8W)nq>A_@s8NT-s8VHFm.:8WrVcNds8D-["\Xi(L4P3WKHGqsJVer38C%88 +r:2RDF)Q/ADf'Q-D6A;FqZ$Hmr;>OQ$ig2(qV]?2`7=eas8N!1s82T`_M<DZEc5`2Af:pc!s8W% +!!*9*r;[92&ncK6E``eS!<`N,!WE'2!sJo7"Te`-$nGq+F`q7U$O6S1)$9m?!WW3%!rr?)":,6" +C3P&JG`C5Fs8Drrrr_KOq#:9miVrlW+8l09s7PJEZ(FL*G&qS@G'%^pd/!_<qLr:3K8,/9LAQW1 +K8Fu5KmuA_rVcQkqtpKlr;HX!r;6?gq#(-k"QSe>p=B6C!;c]prqt^R!rVrnrr3`4r;6Eip](9] +kj7]umJm4bs8W#prdX~> +s8W,t%0-;)qSAl%ht[0Ks8UOH$N9l%qR`N+`q]T4rVllqmJd%`0E+P"H@g[&JqAW-KS4u0K6i!% +J;$VAs8W)i0i`40EcGr3EF`jeHAVLurVuips8;lrs760gs8N!,s8N#trr;rT`P]XErVc`p!<)lr +,i6>S_o0F/ai/XHHusRWG^=[]H$FUYH%:^3OGgfd^;74$H[Ym<3.67"G("X\H$XpmN/j:F_oKg. +Sp5[0H$jsbH@:-fH?jd`J;'5EXhhur`50:_s8W&srr)]UnGh;C+ohK?qZ$6L8$ALPDffu9DKKi9 +7aUr1q"KGIL4k87JUrFPKE$N0JVSQ.K76&[r;HHjq>^Km!r`,trr3Z1s8;cY^Uq%]SFZUXs8Doq +s8N#ss5X+Xs8Mrsrqud(rqOL0St2Urr;HQmrVqB~> +%f6)$s8W)kif%2NS%Ze[dDum=`PBO.J6Z,jZH()3a2Q9Bn]3r;bfn5L_nj79fJ7o"K78W1Kn4]# +I"-j-K85D5Gr2bXe'5oJ89/cqFDbo:B5FM\E7iaccbmZ?aND`LaMu6ja=YEN`luZJ`Q6-@`QQ]N +\\G_fe]YtTb/_WHceQt'nFQ;Ep](9(YJ7Za_SjF4rkpV7`l#[2_nNYMp%J7Q\A,qt_8=14^qe%2 +`59=(^r*t*mdU&Po\@!n^r+14_nj70`l>pq^_OW)]&35Tp$^kcm+9A"aMuBL]tVV2h8h=m`llNS +cc%Z6R724CFDu5BDdtB#bgFhhBL[#cJV])8K7SN%K7ei7H\?QW,Lk#\b5KQ`b5]N_`r<pW`r=%! +`lQBKaiVNC`OV%,3B9](Y//6#`P]d>c-42H`o>&Bb/hTBaSs?^`s]i)]n'6V86_PDo_SLcJ,~> +s8N0"rVlfr#l<63q>^Kkp\`M>&HDb0q#CB<p[8(]rqQ<as8D3]#Pn-cI>W`7JG=d=IZ/o4>3u7b +rV4o0E,9l=DgHJH3MNHJo(`.Yq#1-LrX8c)rVGHk`5L4(rVulr)ZT^0oYQB/F`D5:>S7DU"U,)4 +!s&K-"U##4r;]%g)f0bA;\'6<!!!?/!s8N)"9\r9"p"],%Ou:6EG7E=$3^J2!!WT/#m186"pG,9 +#6t])AoVs8KT4LRs8Drrrr_KOq#:9miVk##r;Zfmqu?YXDQ\%eCiFT;EHuFj[ep+'s7fSVFG5@% +LAQW1Iu8l-Mh4+hrVcQkqYU?mrVmH.r;?Ebr;ZfnkO8$(nc/XcrVm#uqu$Hnir0#Wqu$Em'`7_( +qY:*jj6Z*siqi]TrVuoqr;M3~> +s8NK+rVuloqTkk1anYc4s3glRr;ZfqkE3$Ukl:Y\rrDuarr)jMqtNU+L4G&/JqAW-KS+o/JU<9+ +KO"!Gr;HKC6>gO_CMe<:E]9Yf:%J,Zr;6Klqu6Wqo)AXgrr*B,rr2rss8Clp_o1+(rVlcrrVca- +hS@%H`5^'7G&r%QGC"OZH2`.aH?XU\H[^[.O2A`OWH!96F`i(XI"$BgH?OLYH$OdkMNu<'`4hFQ +H@1-aG'\@SI!Bp]G^"@TH%q0W_Sa7,`kh?Js8DrrrVG[Gs4mSoqu?]kqZ$SYD6%\^C2S03Dfoh_ +[JBk#s7oYWF+sUEs+:9's+1Q*Lk0u1J33W*rV?HhrrE&rr;ciqrso#(g:Ou+UV6O's8W#prr)lU +rr2p"rVZTlqu7#oZ)*q[UYPeHq>U?mJ,~> +s8)fqrr3<"kG;cpJ%<J=ajS6A`l#j9_lup>=e<INaiVNG`pq.LbVdJ\_8!n1ehhN)KS=i.Kn4]# +IXd!+JrbG.8'or4aiLP3@VpU8E-ZDD32)p%cI'tY_SsI7rQ52_`l7MiIE'7Gbfn/IaN2E@bL4JB +^Uh&-bJq]Ia2uKMgsXsHoCi(]pp.3=\\>u!`Pom:`Pf[3_7mIk]tX15r8Olk_Rd@s^qmt)_SX"$ +^q@1e^:h;Pp%\4+Y.VQf^V@\"\A,bo^V@In\[T2`hXg@.mHDm_f?)(S`lcZA^<+OSa</F>cHaMT +f[k1IU2XOZF*M\DFCHkgd*p:jd5)nPI=hHP%tfFaK7e]4JpDic-JQhfb5BK`b5]N_`r<sVa;i4@ +b0A2SaiMTAYB</g4%42%`Pp!=`Q63Gb/VH[a;<"?`l?*Bbfn/I`ko&u<CTPf\Erq_qu-NoJ,~> +s8N0"rVc]p#MeA,s8W&lqpGBOs7cHkg%"\+s8M`fp\t3Zrr;m#qYip2Ne)cVKH?&/G]-!Cp\k-f +s3NiSE,]oCBQ%"$[qDW5s8Muss5<kas8Domi5NXQeboCGrr*N0qtTg#LO"#^Cdo6Z$4@RS#Q=lu +"pbG=#RLeB#71bR@WY$S'*JRL#7Lb@#RV%I$O[@L#6tSK,ACp[/0YH5!t,PE%1j$]&J,E[$P+!e +#oba8DKBuQO4<h%rVlfr"6f+Hrr2rVrZ;+:qu?ZqnGE#XUSpV)G&MDCE-OpQqY9m`qu?"YIJeis +KE[!aJ;?_`rr)Eer;R<,r:p'bs8V][p@6W3s7u?drri8sr;Q`UrW<#nqu-O&qt^3dqZ$TSm-X-! +qu6`qqu2*~> +rr;us#Q4G\WhZrjrVliFrX&Q's8DnoVQJ5Br;Qcpmf*.a$2j`hG_pp#K7\^QK,oPuL3.6!U&"`g +qZ"o'G]%A<F_>SnI'[C]pAb-jrr;lps8VZhrr;us%KHG,s8N&si5NUPec#IGrW)oqrsdi#_o'F5 +VL*`3FFn^]rceBe!dAm7rd$/CI>*Eg`h.I&Ed`RdI<KgZGC+IWH[L0cH[^O'`kdpkHuFCUJ:Dfg +H$=LXH2`.+G]e1UOeKq>`4s.(p&G'jrr2lmk4&E-rr<!>r;6Nms76-b:na[MEHH&:Ec61mWVcPi +rr)lb:O@]mJHCFUKDgB-JVSZ.7IC$OrV6Bjs8N#trVucqrVca+r:J1E]X=3hrVZNlr;?Nms5<nU +rr`5tr;HWp%fHA+ih`9:SuD2Ys8;lqrr7K~> +s82cp$Ms,/F]i:Y_9C-Gd`;s<ai20:BN%o_[`->1`6--jaT'Hqb/V94^;J4P2Kb"2IY!3,Jc:-C +JV/i8EFUYRda?4Qe#F^6EHHGMASP.gYZZb(e',kSa2Z4!ao]Z(`U_(u`l5sAbfIcEaN)9Cd`Au6 +]"?M9`lcHEai_rbdbF9_pAX!Y]<Sf`]`#Q@^VIUu]tD"g\@/iQmeG84[BIBd]>(kd]"5Vc\\#Mb +\$icS\+9+3\@ATP\&61u]XkP\]">Ve]=GDYZGY&bp@%;+cg99*a2l9Cd(R08b2:8_`lQ'<dEU.U +cI+P6TgX*ME-$);E&EX(aiDHFe&aIbJ,Y-4K7ST+K8##2Km%c#dE]eQqTAiZ!65#Ws2b5[(!+VF +ccaAPa1\0O4#T5hUVt3gai2:!b1t)<`Xg/5bfn8La1e6Q9h/#rf(K%;!;lcqJ,~> +"TSH"rqlZo#N"P(s8W&kqpPKDr!WAss8([Lm/R+Yq=agfm/I%_#6+6\JU`?.pk0`?Lh:Dnq>1!c +s7WrjEHZ;BDfTqfWgd#^s82iprVufSrX8c)rVGHk`5L4(rVulr&c_b'oYQB/F`D+f6:+.-3^>k- +56!eG5".Ur3^,ko2)Jr\<_uRf8k;QJ8lAP\<)HCb91qlK8P;*IDe2jQ=&Vpj:Jt.m<`N:';,'b^ +>Zjm$0Ond=H\%:.o`+mhrr3)am.gSZs5Er!qu?Wnr;Q`lql+G2KiDo3E--&=:i5t*rql`frU<Ek +rJ(9(rIY3-L4N/"rUTsbrt#&%q>:3ll1+?9d/X.ErVQTorqlfrs5O"Zr;$6grsel$s7uQls5`M9 +lfA*DrVlruqu2*~> +%KHG-s8;lpr;*aoV<7XRs3goGrs&>se<[2LpAY*lrW)obrql^"o07YOJqepSJfo\oKk+oiqu-No +s7j)kDKK`8D/jVbWgHcXs82iqrr;rprr2rgrr2rsrXJo,rr;utrSYZ4`7=hbrr)orrVm>`^r+(/ +_l09&VPBf]V#I4gU_fc!U84W\S\MkGZF%'GYdCgB[^*!AZa0S;0=.sgYb&AF\>HU@]"5D\[^<EM +['R-I[^NNGZ+7`AaMl6;]ta7?s8DrrrVG[Gs5*_ks8;oqr;6Knr;EU2V1DEXF)H#:E)(9ErVm<# +s7&ZjJq8N*K7ec-rIP!$"Fa/Err)WkrVuiq!<)oprVm9!l+".-\"EBjs8W#rr;uuus5<nUrr`5t +r;HWp%f-/&e"E/%Ts=Rrrr2iorr7K~> +!W2]krsJ_rj+^Z7T=i=ib0e<1`sTW#Q:kCsWkld!_sb\Haq)S4_8!b(e(6C)Jqo#/K8'5U+G"if +=&d`"d)j/Ga-JGoGBA"IDf.\3O[@@BaihZBai+/#"3AL%`U_)!`l5sAbfIcEaN)9Cd`Au6]"?M9 +`lcHEai_rbdbF9_o_74qgZ%/Jk2u[+s5kckinrSIhVmACc118aj6H.(n*of6o'bi5nF#c5md09) +k0N2cmbI0uo`"P-o^VJ@m-jK6n*oi:nF6"ko^MG>hp:Z@aiDKBb0[i9ai`M^,K@UCbKS/Rcc==b +>+U=GDK^#@D/2F;e'Q7S`k^'N2-PQbKDpE&K8';X$%d\TFZ7Uba2l@"b5]Q]`Z*(A`Pp!Ecd0eT +begTF5qt&^:qF]laMPp9b08V]'un>;b0A2Z_o&pD<CfhdI-UV*q"=C\s*t~> +s8Mlps5jLKrr;rmr6tZFr!`8ts8DuUo'HDQrV63fs7-(@s8MoqqY^6cp.KmiJq8]/KRno2Lk(>; +@Y"=NrVQNhs7ol8Cj'o=F_XU;V-q6prX8c)rVGHk`5L4(rVulr&-)P%oYQB/F`VPBE,]]3D>e8L +D&$r*EFs<8D/`uuE,fc2Ci464D/4$.rc/0^G%GN.AH$<J@;K\%F)c4!BcCl+EGo`5E-6&3C27a, +C05([CNFfSOOWq&rVlfr"6f+Hrr2rPrr;m&s6j3`VGV8PE-2)#+CFd>rVHHkrr)Y:BodjtM1L;3 +Jr+o.Knt:Eq#:<lrVZEhs8W,urVmE*p\=dgnFH5Hh!Y4Br;Zcps8Vutrr;!W!rVrmrVmB)q>L?k +s6K"@mcO9DpAFpi!ri,sJ,~> +rVuos$N9o"_P<pVq#:<ne,KCI$iU,*qt?PU[-./_s6]gcrrDurs""*Fp.0O`J:NB*Jq&K'K7&E- +@=S.Ms8Duss8#o6BQS93F(n=5UL(n;rr2iqr;Q]qo)AXgrr*B,rr2rss8Clp_o1+(rVlcrrVca# +hS@%H`5BLl_u[iqrPecS&&Z?-^;e4.`l,s9_oBa:`W!aV`P]Rl_)0$M]Z8./`Pop8be_?;_T0X9 +a2Q!7`5]d3`lQ0@`4j+7`6ZNE`504'p&G'jrr2lmk4&E-rr2p"rr)iqrr35m>aqH]C2IkfEW^8e +oD\[f)#a5OArD+eLk(&-J;8K&JV8G8p](9mrquNis8Dut"9&/prVca0q9?RZ[%ke>rVQWprr2lp +s8W)sir8rW(&e(.rVuors8N&-U7\!MbPqP@s8;lqs*t~> +s82`o$23bX>uQ]l`QcQRa:HP6`PfX(>?P6r[`ut7`lIPh29*MQ^VRt=gcp1CK7&6"KnP>;M1'r# +9k2c$d*'MHbK`4UATr?=G%F(#QVsp4aN2B@`Q#praof`)`l7Mi-cX-Fbfn/IaN2E@bL4JB^Uh&- +bJq]Ia2uKMgsXsHoCMPDoCMYLq>C*fq%ESorr;lqqtp3^o_/(VrVcZjr;?Bos76*epAXt@p&=[_ +q"OX[qtp?jqtg*_oDAC[r;?Bgs7?0]o'bu)cg99*a2l9Cd(R08b2:8u`l5p@c-4>L`QlIkO.T6d +EGoo;DJ)Ynd`9&9`R!/k@pt7CI>33&KS>A8KS"i&/Bc&S`PojkaT'E_`>ctEccs\S`l"ci4tnuX +JAKLRb/;6?bfn/JaNEJ_s2P)[s2tAd&'N,/\8G;@:0sO^rqlQ`q#:;D~> +s8Mlp#P[-:kPtSWr6tWQr;$*es82iljmVsDrqccsrr;Qg0DtkMq>(!brqBH8MgpV>IYWK1K8"o= +IVs]1q>L!dqYp*]q/pq!EclD:?)Eg"pt>WSs8Domi5NXQeboCGrr*-%qtTg#LO&c>s)e3[rH/'^% +s*/BD0Ki&4E5I_EH?;KH2_pdGPub<FaS.KG%tko6=ObRFEMhLEcQ;GG]n.NHZa@LD/XT:?Tq7qE +cuYWO4<h%rVlfr"6f+Hrr2rPrr;mLqZ"Z@Wg6A#F`_YAF$8CVrVuZkqtKpdCiG)bIu&f3JVf#7L +5(4Tdej%As8Vopq>UEos8Mus$2aDks8V3MrqOtArs&H%s8;fps5*_Vr;6Ejs8Vrrr;Q^%l0Rd&h +uE`Lr;HWrr;M3~> +rVuos$N9o$g7k7Lo_ngie,KCI%fZM-s89U$ZI&LKs8Mupnbt6@s8Vros8;om<H3bALk^>4ItiK' +I>iMiJb]-Bq#C<mpA"B'FDGi:E+iOQP%aUgqu?Nls8VZhrr;us%KHG,s8N&si5NUPec#IGrW)oq +rrLulrkn]O!Q2eQ_u%:]^rjO*`l#N\_SO41`59=*rkTbn^VIV!^<"+.bf%W0VSg<k^qn%1`5KR1 +_8=..`P9=1_u@UgaJu\cai2'1_"Ia-rVlfpqW@;IhZ!NSrVlis0E(pn=f7ESDf]r=D/_SlqZ$To +s8Mfhs(ZD&L44o1Jq&N+Kn4i':=K+>r;Zfms7uX0r;HZqrVZQks8DusmC]j=[@Za`r;6Kms8W&t +s5<nUrrE&trVum(qZ$KdYFh8SUZ27P!WE#ss*t~> +!W2inrsAPo]O=TQZGk#0e&W-Dc,doC`4pn*=`q0maN)<<`q%2)`5^!9_T'L>e3Ii-Jr>5*KS#,; +M1^_,=CKS#c,7fGa2-3^B5qa/G]RCqQ[i&gc2P`_`<+'#aSs?^aT'9Na<npG`luZJ`Q6-@`QQ]N +\\G_fe]YtTb/_WHceQt'nFQ2<m-O0.nGDeTn1!`!o^MnYo?[7*oC;ABo^qbHp%.eGoCMMKoCi4Z +r8u`.q"sXQo^_VFrU_0&nac&9p%8%Xr:nq)me6/9i6UcAaiDKBb0[i9ai`M^36&qWb08)N_o'FD +X%/hF8oSlnDeWu>`RN#J]#)S7fB?LPH\$KsKS>)=L5L\;I6jpSb/VTI_o_br+NhpN`Pp!Dc-=JN +_6oJ'2*"&iVT6s)`P]^<bfn)HaNEJ_s2P&Z'$AGBaiV,oAPkurB>!m:s8)Harr7K~> +s8Mio"lA=ms8W#FrXSl#r;Zfns8UjBl2U_]rr2rgrYkh4rVuomrV<chMhcY:JVSr/M1gA:IoT\G +qtpC&rSBb[DglVDBgSMs9]YpHqu#^X$ig2(qV]?2`7=eas8N!'s82T`_M<DZFnL"XGmJeHG&M>. ++>.R2FTH`4rd=`lrHU#AH$"CTAnOm`1LtKJG'\I[G^4[bI!U$^I!:$eD/XN*1*0),H$4C_NR[V# +rVlfr"6f+Hrr2rNrr;aFpN)=q@Ua@kF*VXuRJHLPrqHHmqt0bEFbGL#JVSc0K7ec2MKqY[s8DZk +q>^9is8W,srVllqrr39&nFQG:jT#2Xrr<#o!ri6"hYm]Vrr2rtrr2iprs@cPlfm:+s7Q<grr3#u +s*t~> +rVuoss8<3%nu/:WkPY8+rr2p,rr)lsjdWHbqYgHns8DNfs8Nu5rr<#ps895oMM6>3J;/`*KR\<& +HrO8CrVQU*rn]eWCOL&;B0i5o9]Q-Or;Z`pqu?6drr;us%KHG,s8N&si5NUPec#IGrW)oqrrLul +pqujC%Dg$$_90WRQGgVW`5BIk^]D9erPCD-^q.M'^;m[?R)R.c^qmq,_ns4(^qmn*`4s:2^;\=5 +UQ;Ora2#R0_=dj.rVlfpqW@;Ih>[HSrr2os0)PM>EJ^Su?>sLsG\Tm=qY'shr;Zfpo_C=bJqef+ +KmnZ)JUiH.G!tm#s7lWirr;lp#Q4Q#s8MuprVlg)rntW$[\pV7rVZWjrr3*"r;Q`RrW)urrX8c* +qZ$BJV4=!JWqZMms8E,us8W(K~> +s8Dlq#Q+AOCfXZ5`6lX<b0.uK_o0?n>?>.7^W+@8`5_Di0uhAO`QQNIcdA"8L5:;:I"?m"MM?\> +G="C9bKIrJbK\>\_CfP;HZ!h<4dVZqa4ec:`W*sAa<S^D`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WH +ceQt'nFQ2;lg+Q;qsXOO$g[*HnaZVQ]ug$?nbheSmhkT`n*TT4md'T>me>bQbkh;5n*TK.lg*s: +miCf^kOJ02pAX^1]A3&QmHir\m+9A"aMuBL]tVV2hT5`:rlR.=_o'@5do_$l>[MJ`E-,e^L>'V` +_7\"BdaI,"A9NELIY`W4LPCM=M/=QXeBZ(]_og!=aN4A's3)J*`Pop@bfn8Q^oi&Z2`sE;_8jdE +_SjO<bfn)Hh8fT=rl>\obfRr9PZUXO=aJirs8Voiq>UDE~> +s8Mio#3b.(r;Zcre,B^PpAY*lq>L?QjQQUC!ri6"nbt3ArVZTnq#BkLLOXu4Ljk,.N/3.BLNZkt +qu?Kfs8;ifr1HW'GB%MA@<JSnMYm)@rqlWXrX8c)rVGHk`5L4(rVulr$30ntoYQB/F`hm"GlN$s +HusIG>8n&%CNXfFrcoE.I!g3aG'8+UH$sjSB2B9T2J[;RH@1!_H@5^A(jpURG^4gcE,T)E%2)Zb +G]n@]NR[V#rVlfr"6f+Hrr2rNr\"6Jq<1JMW((lUCi4B<3Ka7=r;$Berr;ch9m)DKJqJl7Kn+]+ +L5BGsp%SL`s7uZns8W#qrrDoprs7r]o^L6-s7lTmrrW#kr;Q]srqtaSs8W&ss83?*s8VTKlg3`r +s8Volr;?SF~> +r;R-'rVc`o\Yu:Oqtnh@rr3B(qu?]lYGSVequ6Qns7?6is"FBLqu?Qnnj8.]Jq\r-L4+r3ItE;p +>5J3trVHQlr:Tu[7W<EfD/ip)Wca6spAY!irVl]oo)AXgrr*B,rr2rss8Clp_o1+(rVlcrrVc`s +hSAp(qniBNs2$5'^W=R9Nej7F_8F1-_o'=+^r""-`5BI-`l#^8]8;<9b/V98_nj4,_>_1j^r"") +_8X=/b/'s2M7(C>^;e..p&G'jrr2lmk4&E'rr)jNrqbeKUn^7qH>@A;EAisXs8W&tq>^Kipe>jf +Kn4f0KnFi'JUrPbM"UQCrVulss8;lqrVum1rr)fprVufl`P/^aRcsbLr;ZTlrrrE#rr2rth>[BQ% +fHA"`1WZlTtC4$s8W)urVh<~> +s8Dors8<3#l@iVKMS[<\aT'Bnc,[c?^qt%f=I?V<a2l9?o>i`-`59O;eBlmq.XHJrMMZV0H]<l9 +L4Eo%eB?"M^<"C>akD_=D/sN0FCK3\?u+B:b/M@!`otJe`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHE +ai_rbdbF9_naHDCqsXLN&+&KOq")2.bkL_tmHa'&li$5MlP/aQoC;DEkHqSDs8;HWmHNftlKdd8 +m2bNVkO7p1q=)n>ZfV&SmdfJcm+9A"aMuBL]tVV2fuP5S_o'^?d)\)4T0[IAB5)C*/U>gd_naR< +cd^P$2.6E3*.j$)LkC>7LOi*1cd:7ecH+#FaN2NHbfn>U`l7ks'$%GU=@>,56D2-7bKn&EaND`N +rl3g9s2tA]&]i,:ag?Cl928lZk4eoUqtg0gs*t~> +q>UWss7k=0mJd.7rW2rnrr3?$qu?KBl086JrVuBd1&1eFs8DleoLOacL4t;=K8P/2MM4crp&"R[ +s8)]ooZ,lLGAqG<G&T[GV*jhRs8N&orqlWXrX8c)rVGHk`5L4(rVulr#ljesoYQB/F`[1t%!-Q6 +G&Cts'a"mfB6=,t"a4s.G^+B1F8p@pG][h3<Y#<@2/I2NH[9g\H$]I<(jpROG^4ISEF:^9$P69X +FaA@XN7@M"rVlfr"6f+Hrr2rNr\+!Ds7CqmU3'OZEd)A@;EXA`o`+d`s82Teq(QQ4MM6_9KnG)4 +IYNP9o_\I\qu?Qmrr3*"qtpBlrs\l&s8V0IpZpQ5r;?Qnrs/Apq>C9mrqtdTrr3)uqu$Bkrr<!+ +k32-th>70OrqZHjrVqB~> +rVuiq#lXbOUo1d"qu,"Crr3B'rVuoqe"!V[pAXpfs7?4Gs8)clrr)fep.:$dKS"f2Iti9!L4W'g +p&4gas82cpo>f]FF)Gf3F`'@>UI4\Rs8N#tr;QNlo)AXgrr*B,rr2rss8Clp_o1+(rVlcrrVca! +hS@%H`:Uq^`5BL2_TKu^LmFUP_SX4.`5T^5_SlGms2=rV'?%f-N/WdjaMP^1_na7/_8*k$_#D4i +_S<t3`28ERO0l[6^raC.p&G'jrr2lmk4&E)rqudOq>^KfJpX&-<H<)&CN*$1n8S.%qYC0gqYL"A +BmbekJq8Q*K7\K&JN!)qq>:$grr<#trr2irrr2rsrXSu)qWkVs[]lq6p](0kqY^Bnrr<#Wrr;os +rr)j)rqu`^Y+_J\T@s/ArVuos!WW.L~> +s8Dors8*$!n#']$DSa]@&BW2;`l5g2P"f/%Xhhop`Q%Mj1WI&IaOSu"fA8H7I#3]6L4"c*J;&D8 +K@.u`]ue+2e&S6(/p)#KC2n5YV3`XUeBu@W`r*pV`rF-[b4<Up`l5sAbfIcEaN)9Cd`Au6]"?M9 +`lcHEai_rbdbF9[o*b-Wp\)8+^rc?Bna6>As6Vo:mHs6*mHsH7oC2=\[^soao^D>:kNqL"lg=00 +mHs6*m-soFe@)p!k4S35o\e'^f?)(S`lcZA^<+OSaT'BaaMu7!`B1lWe'2K>QYf]@D/sN89.A%J +^<=O8cH",Vf+_5'Jq/K,L4k;8It;_cg"b-*bfe)I`lQ<Fbg"DV`l7nr'[+4qNBf?b87TKNb/qlE +a2lEIb/jS%iQ2&A(!Oh?`Q$!@`i`iJ92]61n+Ze\s8)Wls*t~> +q>UWps8UU.ir8u+rW)orrs&E"s8Um9hu3QTr:0b@s82fon[1Q%Ljt26J:`Q2LP^k>:g*emp](9m +rVuLs9QYSpG^+7K<._2hT(i*Vs8Vooqu#^X$ig2(qV]?2`7=eas8N!'s82T`_M<DZF7sbVF8g1l +G@t5("9J`HB68EEG]e"GF*7G&s)fo8DIQ`T"TnlaDK0iHFDuJIG'SI_H$4=SG]n+93u%r($VbVf +H?XUmeF`e>rr2p"kj8*Drr:XMs7n5GnO'OZ6uHsaGAh\B3`5qNs8Vrqs7u6`EGg8XJUrE*LPLM: +N/Ct+WW3"pqu6Tp#6+Msrr<#trr3/mmIg8&rr2otrVlg%qtTs`s8W)rir8rW%K-&!r;Q`qs8V3H +lKI%%rrVrjrVcbH~> +rVufp#QO(aU8[SXrR1ZUrVufps8VuhVQ-rdr;?Tpo)A[h(]=71n?bH&Ljk&1I=Qs%Jq\o.:0ISl +qYpL.rr;Op95o&bG'7kE;Lk]^TDJK_q>U9knG`Ferr*B,rr2rss8Clp_o1+(rVlcrrVca!hS@%H +`:UtH`(S7jb*\*LQ_2=8_8=(-`l5m6`5KX6`5KX5_o7:fQAqKU_o'I0^WOL4_SEt(_o0L4`5oou +O,9'\Z,+8l`kfLas8W&srr)]UnGh5Aqu?]o/cY?,XJA*uDfKo:F)!d9s7u]pqu?]noDETFIt<-" +J:WE.JV8f4><Ae`s7uZns8W)tr;cirs8W)urseu*cFUQsSDEr;s8N#or;Zfrs8V'W!rW#rrVm9) +rV>0AUS+6To(r@_s8W(K~> +s8Dors8*'"o>YKH?F@f#a:H>6aiMN@]s1mK?^ndJa2[\k0ZM2Nc.CI;.qF$QL5:M:KRnl4KQo^I +gs*g^`l5p@_DX&XGADPLChlt%VdP&$b/3tqrPeu]b08)Po>hum`Q$-GaMl6Aa2Q6MaLT's]@G*E +b0%cHb0Skkg[P15!qc*Vqt'dY$hjMjq8^"Y^rc?BnbqqUnc/(XmJlW3o(2ABYdqW_cM$l"o'>H- +mI0N6naGr6nF?/Hp=m<j^:N@up$qS2cg99*a2l9Cd(R08b2:8Bb08)Nrl+oW0Z_5Rf?Z"CTg*7+ +D0g5E@2p`C`6HWE`QZKHfN29uI"$TsJr#/7KnOqO.#cp5aiOJ$#ft04c-=JP`Q%nr'[OV!D*'UD +4IX1/c,I]>`lQ<Hb/jS%iQ2&A(sL.A_o9X9_44_*92]KWoD&4_s8;ios8RT~> +q>U`us8V*:i;EWTe,K=G#lFZ$r;ZcNk4S`R!W2fcrr;gHs5B,>DM*OpKS,&8IY`T/LMa<irVZQk +pAb*jpk1P4EI)YEDJW.HRnE8Oq>:-jqu6Kjl2D(jrVcTN`Pf^Fr;HZprWrQ$q"2FYH$+9'G5l^b +EtiV/@OM`p!<F?WGC4daG&hMAF*2a,GqO8^Bj;A_"98`eDfg5KEc,l:EclVOG&q_IF`_%N&dJ^C +#"s#bGBA=oeF`e>rr2p"kj8*Drr:[N0E:qJrqMCaWJ+SlF)Z,?BgD=ir;-Hnqu-?jp[WE3KS>29 +KS"f/K7&Q1F[q5_qYgEkruV1:qu6Wpr;-HniUcp4df9:Gs8Drqs8;Zdq#CBnr8R_Trr`/nq>:-j +"nq3HlKIa9rrW#kqu-PF~> +s8Vuqs8N;s\"9>Hq#/Y?"8r,trr)j#c(D;fo_ndhoDUKEr;6NPOATnJJqS`+KS4W(I=QudZ1n7s +r;QHjqu$,<1gFj=E,TW1:8F4IoDeagrr2lprql`brr2rsrXJo,rr;utrSYZ4`7=hbrr)orrVloT +_#D4S_Sa7._YM+K`"U&-Q]72lP+p"4^VIY%`5T[4_nuDh$Gsg%`J]b<PEDNXrl+oT,fmsC_nj1+ +`5KR4b/1->Mj'*ZZc9u!_8a=as8W&srr)]UnGh>D!r`,trr<#t$ig,(s7hF\VL_rcErKr"AjH(i +rqZTorVufqq"&Q5KSG89K7JN)JTZWrEC>QUq>UBn!<2rq!<2ut&cVh1rVl,l]"5#:q==Rcrr;ln +rr`9!s8V'W!W2fmrsSi+p:d/lTV8pnrVl`prr.E~> +r;R0'qYU<df7Ht%SA`Foa:$25b/M$)McX54Zc;LU0ugoCe%pB!@X39MKnkYGI>*6'IpSJld`fVI +]u\:=b$H/iF+ACMAn4]8Q93RH_nsLmb5]Ng`l5p:aND`Nb4E[q`l5sAbfIcEaN)9Cd`Au6]"?M9 +`lcHEai_rbdbF9jo)nOSnalYJrUU`squ4mV`P9.2p[e"HoCM\Lo^qbHrp^Tlp@e0k^VRq+ch$_t +na>c8oDS;'oC;ABpAO[=^q7In]&rqena5Jbm+9A"aMuBL]tVV2hoGoBc-49.`W+"5bJhTLdVr9] +ITL&tF*2S5.+-MgaihW8_SaaGdp>juJVA`-JU`<(I#*2_0ketXb5TC'aND`Nc-48K`Po[2`kn3B +2`*We]u84;`5BI4b08)PaSs3<aT'Bpbf[oB_o9a3JQPW>;h=0/pA"Xes8DutJ,~> +q>Ud!s8ViOiTgICqu6WprW3&urqt[QrVm?%s8;iqs30rls8W&or:9h>r;ZIM7=C&DJVo)0KnY;< +L5BJarqcHis7u]kr;Z]iAl!AgDfTtmOf2ECq"Oabs82fmr9=1gs8Domi5NXQeboCGrr*<*qtTg# +LO"#bG^4Q3G5c_YG'.kGCh#%3#Qk&0+DQ+JI!U$XEH6,DH$Xd^F)4kp"pk>2#rld@F*MnLDJjB5 +F`qnKEcZ&*5nX2%!!!F"Bm4fGIZ;kLs8Drrrr_KOq#:9mg&<W#s7ZEdejc()9lY;rFE'^uq>1'i +pAb-jqu?Qmpm4j$J:rZ0Jr"u9KnYD6N'I7>qu7*&qtp<jrr)ljlLjQ#rVuos$NL))r;69brr;uq +ir8rW"8qujr;HWukO%Krjo,2^rqlEerr2qJ~> +s8N0"s8W)ts8N?"d\3DLp&4pirW)usrr2rSrr;p,s82ios8;GQ\$bJsrr<#srr)lnr\4<No/8sa +MLU/4JUE'%JqS`1@Wh\Iqu?]ms8)Tlq=\>nCN"'/F\7an<fQtQs8W)trVlfms7$$es8N!,s8N#t +rr;rT`P]XErVc`p!<)lr!T(Wk_u@Lf_ns:._ns=._o'F3`lOX0MiX!aT>piF!5\ZQ3lAhN^qde( +`kILiP*1Z`Tu=d__oB[7`l5j4_Sa=2`Pfa#OGT*]PEiMh_na++_=dj.rVlfpqW@;Ig]%0Os8Ec0 +s7u]jeO,Y!9Q5)mDf%bgqY^9kpAFq*rVlVZ;KdPBKn=l1ItiK(KmS\>r;Q]qs8N&s!W;onrsnu* +f=JT!Ut>G@qt^9lr;?Tprr<#WrW<&rrr)j,rVuMiT:DUOd/*eAqu?Zps8W(K~> +qu79*rVucSVHd,N]ZA=:`Q#p=b1XiTaiM`Ha2#R(Zr1@?U;"Rb`lQ<FaMu3<`lQ<FrQ$\2cI*jp +Fb4peM2$Y>Lk^V7IoBS*ccO>P^s0g<da$345]:pgEG\%&V,;TiaiDKDr5o)^`lA"s"NJO,bf]Ou +5/tR]bfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHoCMM@naZ5BnaGr6n*ff<o_AI;a2,X.^WcNF +naZ5Crq8GGoCMMBoCi%N_7IY+^;/%_m-O-0n+-,Eq"XLQnaZAIpZ'-$_S<n(kk+W=mc;^\f?)(S +`lcZA^<+OTa@47qb/VE<`Q63AdDF)O[PX,A8o&?bF)EqGd`p"`_Sa+'^rt$Ufmc8'H@LQtItr]: +LP17uFWJrT`l5j8aNVoRb/VE>rPK;YI7uLM4,:Ytb/2-;_oU!Cbf\$+`o4uP`lQBH`P]U4b.;:d +7S@'^li$VPrVlrts8RT~> +s8E6&rqucqs8Drs#MJ2!s8;Qis8N#srrr5nqu6Wqhu4,_r;Zfps8V]@lMCP\qu6NnrVl]l')/_6 +J;f,4JqJo3L4b>5Lg*i.rqc`rq>(!tpionWF`V;"W/O6frqlcqqu>RQ$ig2(qV]?2`7=eas8N!A +s82T`_M<DZG'\O\F`MMDFa&4[G'8(B@iu9d!<`K-+_l0!GUR`VF*D_KI<TjYDGqGR!<<*)#W?F< +G^Og]F)c2:Fa8"MEGK,G$j-V2!"9$(DK^5MIui+Os8Drrrr_KOq#:9miVrfRs8N&u&,cJ+r;Z=Q +;5TOREH6+sUA=d!qYU0hpAafg1NnS1L4t24re(6+!el.%qYpHn"8DTer;Q^!m-aH1des.Crr2iO +rWW?"s8VrlrVm#\mHs,ir;ZcqrVqB~> +qu?]p&cVh+ntW(do`"mjrVZ]ns8Drrs4mVRs8W$&s8DQ3T=!5Irr2utrquirrr;usrVm`.YZ,t* +JUrH+M1:2-KmJAQ;LJE=qu?Kkrr<#ts8<K(H!"g&EG8LPN((hdrqucmr;cios6osds8N!,s8N#t +rr;rT`P]XErVc`p!<)lr!T(Wk_ZR`j_ScAk%)]s"_nX16_TA1.NfF%#!hREJrk]Gg`5KX3_T0I- +`Q#NQLQ[d^P_u6V`P_\k,fI[B^;\.-`5K^>Xc/7(OHYol[DTr!_nj.]s8W&srr)]UnGh>Dqu7<. +rVQWns8V^U:8F"HDJsDdSc&EbrVm?+s7lWfXY=gMKS>&/K`6Q&K*-^Rr;HTo"TJAtq>L9l%K6;* +pVF;I[&<QnrVlfqs8W)ts5*bTrt#&+rr;rorq5<ISY2dRmelhZJ,~> +rr)]n(%'F^?"^LfdE');`Q?EJaMu6Bb/hT[a>V2\_o'R8\qip]L9nY6_oBsGb/M-1`QHHMb/hZH +aGiW4M1U/)K8YJ@JqeZ'906G-b/_cEaSs0oaNDiVbum_UG]mXrU4bG+e',hQb0'_-$d-Q1`l5j7 +`lQBJb4E]&`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_naGl8oCV\Hna,Z/kj\E<qTQsr +_T'L.bk^l#n*ff<oC_\Do]to;q!c>9a2Gs=]?^!9mHa*+nauVJqY9IHnFle:]=c%t_SEqNq=X1D +iQplBaiDKBb0[i9ai`J]rPnlV.`TWScc=,Ubq2M`P"'"tBL.F(bfIlLb/M31^rOa?e'<sqC4Lkd +KSGA=re)ADH"bpV`kfF-aN`&Rai;08`Pfd2VH>o;4\Mrqb/h['`r=$Zb2(,Q`l,[:cH!lAa1\9M +846<ld.@;9rVHPE~> +s8E6&rqlWns8N#t"mXk&s8DKes8W)trr`)lqu6Tpir8rT"9/?#rr2p%cKX6ds8N#qs8Drqr;ZX1 +s/f7PL4Y#4It`B'Mh7"&=4I*Hrr;foq>Lp'pKM<NC-e\n7mH/.qu?Zms53e`s8Domi5NXQeboCG +rr,XlqtTg#LO"#cH?sgYEcQ5DH[BpYF(]#9%g)e3!s&NLC34WBG]n4PEHu_IH?="(*X2TH!!!*1 +1h^oSI!g0]FDH,@E-u\DAiC8("T8</#>B)YFa8IteF`e>rr2p"kj8*Drr:sVrVZ]pr;R3!nD#d$ +M6'oqGu]UprVuiq(]+..s8;iqo_(n*JqJf/K7o#4K854uMu*GOrr`,lq>C6l#3b[Lh!+k=dJa7H +s8MrprrqiPm-Wlqp&BO~> +qu7?/rVlfppq*3!gAV!Hr;Zfps8;lqs5*bRs8W$-rr)fWS$B9^rr<#trVc`os8N#qrt25,IY!$$ +LOY#+ItrK0@oC_Lrr3)rs8N#srtGD1rVu^tBQ%QLUnpRFk4S]Qs8Mrp!<2lqn,E=drr*B,rr2rs +s8Clp_o1+(rVlcrrVc`shSB-.s1n`Q_u@Re_o0F,_T0U7Ss,:tNf]<aTZ4kG_`PWQ_nO11`OV4i +Od_>iOc?-W`PTF+_8F:+aM,C2_o9cuNfB3`OHu,n[)9i!`507^s8W&srr)]UnGhAEqYpTqrVlg+ +q=EDr</7JUAp%"&pAOmfrr3c5s8Doro(5FuItE?(JqSo1JV/ViMZ*MR"TJAtqY^<l$N0kuijZG, +W5e]4e,K@H%fZG,s8DijaeG<!U:0jqp]#a~> +s8)fpqYq<)i.kKAPKD(d]t_P0d)sGL`lcHF`nnd2`l#^:b/U2K>$[N,`Poj@c,df;^W"@?c-",K +bhA"EI>*<(Kn"l0Jr"i3>!B1:cc3uBc,duG`Q$!Dc-+@#?ug*JTV+@tb0A/V`lS/%$d?c7`l?!8 +`Q$!Ab4<V8`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_na5`6oChnLnaGi.m.9`@cG[Q: +_Ss@+cM@&"rpBaU4R_q2lLFH<lc-WXcc!W:][66>n*TN1nb);Ho'cGCo)%+S]>DD"`PB7Oq=X1B +iQplBaiDKBb0[i9ai`M^s2G)YaSs1OaNDcSbf%H3+]4,t;dF-*CXp\N`lQBJaMkp5`QZ9@eBHZ, +EI*(fL5:S>KS4r*=DQ7%^V@\-cd0hV`5':1aMY6:5r^kdFh>Q?a:ZD+^s13Jai;<7Ki(3)</T`0 +p]#a~> +s8W,u"T89!s8Dor$.Rkrs82fqs8;forr`)lqu$Hnir8uU!<2ip"lJ>(qu?Wfrr;orq\8k)1PgX= +L4=l,NJ;q=LcP/*p\OphrV?F'qt]>DDe3m_H;cMfq>Bsbg&;BZrVcTN`Pf^Fr;HZprYbb5q"2FY +H$+7QG'.kIF`r"WG'7tA@P/?!qu@?4,\hIHG^4OVF`_hMI;s(0*!cBA-Njc5BQ80?H$+7NFE`"O +EH>_T('OjB!!3-##Yo>\FE`.meF`e>rr2p"kj8*Drr:sVs8;ips8NT,rVZ]i@6efuWi/3nA+KQt +rVdW2s7Z?ipAP$bFDZVeJV8Q#L4Y/8DI*,9rX\r+s8W)qr;6Bks6T%Ao[<a=df'aTs8Vros8N&u +gZ\"ihY-XBJ,~> +qu?]q&cDY,qU_=6]`.s/rr<#rrVZZns53hUs8W&urVld$qY@P%[FY<VrVl`prr2lr)>Bs^L44l3 +ItW?1KR8B)2=^M9qZ$QnrVlfps8N!.rT6Od@rJ)e;_FR7rVHQoqu6Kmn,E=drr*B,rr2rss8Clp +_o1+(rVlcrrVc`shSB$+s25>`_SX:-_oTg<RZ*5drf@AFOeKe2_Sa7i_`P`S^W4+-_N9V4P*:lc +P)lBY`P]O._Sa=/_o9C,ai16>M3<p\P`V)kZbs_u`59@`s8W&srr)]UnGh>Ds8W&s(&e.1rr<#n +?pAQoW2)Ua@IO6prr2lprr<!6qZ$Thr;ZG1CO_1jKReE(J;&Ym>Pe<ss8W'"rVQQms8W')rUS(? +\$qsnq>JeA&c_h0s8;osrV?,fTq%aJbk_84s*t~> +s8Dcn&bk@c?<VEhbeq9:`lcQKaMu6Qa:QA1`l>p-CKk5$[D9l+aN2C#`<"!"rQ6n:bg(q_H@(F% +ItW?4Km\N&.G3+j`lZ0>ai_cG`Poj@bf@oI2JQc>SodOJLYC.j_SuMq"Nng,`lA"s"3/F)b4<Uu +`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_naGr:rUVK.o'Po>o_?VD]tVG&`5'+3p[[e= +mHsH6nFQ)An+-(b]"H#&_SX7(d/NY:nL!bqnaQ2EnacJJg;(87^VRn)^q](.p$hD.cg99*a2l9C +d(R08b1OcLb/hN?aO/R33cIEdUH)7HcIg@^aSj79aMu?:`5f[;g"'A4G_L[&JpiB+K7@8ufZhFP +_8XL?ccjJJ_8XI:^Rnpr2+0O!]Z&@@&]VT)c-=GQa2,/q:IRcTV!7[Ks*t~> +s8W&ss8N)trVlrQguA;4$3'l$rVuopq>:*hs5X+Xr;6Ktr;ZZ9nEg/Ss8E#rq#230qtp<kS6(Mq +KnFu.L4b28;l0Hls8Murs82Wk&,c(tlngl)VEo-=2pq[*q:Y`Ts8Domi5NXQeboCGrr*0&qtTg# +LO"%?EtrkCH$OUWF(o,7'FFsC!<<-#"=@l+rcnNhG5cV?G'.e1)@$KK!!!')!XU\sDf^)HFEMYO +FF&7N@7:k:#mLA0#QOi4:2k8pFF9(to`+mhrr3)am.gSZs5EtWr;HWorsnf'q0Q%`DdmL[FE@9V +qu-QnrYG>0p\OpirquG*Lk:>7M1^S:LOaeBk5,)Wr;Za(qu-Qos8VrZme,`,rr:FG%K6>(qYg<j +s8Ug>n*&^%s*t~> +qu?]q#lO`%qs1;UY4;Gi"9&,qrr)itrr(jUrr;rq$i^2'rn*UH]^Yt"rr)lqrr;uurr2p8qu*!a +L4+],Jq8W-JV-^lqY^Bnrr<#qrr2lrs8EQ/pAXA44K,)BDeq;Ws8W)ts8;lps6fmcs8N!,s8N#t +rr;rT`P]XErVc`p!<)lr"5^i2_u.Ff_ns7+^V\"0ad\6GNf]HeOcGQt`khVjrPSZP2oi[lLQn$a +NK9<fNhaY6_ns7,_nsL.`5od0XbV^rP`(WhN09:/_o9O5_nl$Gs8DrrrVG[Gs5!\Ss8Dp3rVlil +s8%(=FDYE"U2Y&Gqtp?krVc]o)#O@1rr<#sqXnWZJ:rQ3K85,6IsOQFrr)fqrr*K-rr<#tr;Z]O +^:CkW\bZ("e,BsZrVuios8Mungn:@4TVgcGrqHGC~> +!<)]m&c(Y0F')q[aMc!;aNM`KaN2BWaT'9Zb"]mp_ns9V9O_\2^WOd>_o9X<bf\#H`lcHFbg5!j +5^I^1Kn=f,J:`;BOk\@6`l,j<aiqoI`Poj>b/hNSeg`_XTfHau.D"3T]>MY.r5],_`Q#p=aNDZr +a<8LA`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8InJ1Naq"FR/^:_4t`l,j1^<QECmHa0. +rp`)Ao_/.N^:;&!^qRb,_Rn1dp@e.No'u,<lLXiEoAI<o`5K@+aLf1"kP=f?mc2X[f?)(S`lcZA +^<+OSaT'E_aT'Htb/h`>cdH;nF`Lu,VJThud`KYQqoUV7bJ:s;b0A>[9lkE,KSP2:L5(%p1We:o +`l#^5aNVoRb/2$:ai_)@82i[tA@B4le&W-@_8sgCai265Qr[$W:1h<-qY1#?~> +s8W,urVuosrr3PrgZ//1s7lHfs8N&ur;6Bhrr;$Xrqu]o%0$/(s4u]%p&G'ir;6Kks8N&us8Er7 +qtpEmnm-?mMM$_:I=R'$/bJi:s8Dutqu?Kk&,cD)mX9bjBOQ+)E(Tcss4RAZs8Domi5NXQeboCG +rr+SNqtTg#LO"#_EH-#AG^4U]G'.J'-4^@c!s&B%!<NKPC3=fJH?jaXF`DP@?Q'@N!#5Y=!!tPs +DfTuCFEM_OHZ++G2\lo-rW!K2!s8N3:N1>oF*`epo`+mhrr3)am.gSZs53hSs8W'/q>^$E5B^m_ +D*tD$8aZQUq>M3-rr<#trr<#pYuc($IXZp)HB*qkLA^lErr)`pqY^?rkjRp1e,B<orXAi%qu-?j +s6Ak;n)j!/s*t~> +!<2`m#laP8T;^B<s8Drs!rW#rrVuorir8rW"9&/qrVlg&rq<Rl[+P?Urr)lsrVlcss8Mus)>s)3 +F,,R%LkC))JpJs<p&+jhs8VurrVlfqs8W)urs\npH\&/-@<ZR)8,)oWs8Muts6Taas8N!,s8N#t +rr;rT`P]XErVc`p!<)lr"Q$r3_o2Pn0Z:lG_8*h*_82CmMN*a\P)tffOeB_2_SO(*_Sa:-`PT?E +MN!X]P*(riO-$*V`P_\l,f@L;`4="3Rtlr]Nf]?`O-,QcZbsf$`l#Xcs8W&srr)]UnGh8BrVccq +&,ZD!i&u*qDJVY;Tge>IrVHNnrVHO*qls4DK7&*!Km8K3>_MqIrr)j0rr;uts8N&rrVuT0^9tSE +lM1D-rXo2/s8;osr;ZW'TUqaJ\bH+&p]#a~> +r;QcqrVmB)n_'11>a)e=_o^'GaiaV("3/F'b2UK(`l5s?c-=DI_8aL.D,FSp\B<%3^Ve.?dEK\N +`Q63Cb0e\[4(!JqLPUD(H\$A_h9sNh`5K^8e'6+Xrl+oY'#r2IdVaH0?rq8_CHL1b_nj=2rl4rY +!64BH*lc1=bfn/IaN2E@bL4JB^Uh&-bJq]Ia2uKMgsXsHrq$0[0(82pn+#uIq>&7J^;7_)`P]U/ +^WQ6=mHa0.nalACqYBj"]tM5!_SF.+^:hndrqIl7oC;26n*'ZKf"o;B_Sa=1_SNptjnJH;nDhj] +f?)(S`lcZA^<+OTaAL+(bf\)Qc-48A`l#VIF)c895cpb@cHaALaNDZHaNVoScGdW;`mW>^NB_$) +I<g9tH\m>KCY6qV`l5p:aND`PbJD-@c,ZVZ4"`cbU:SFce&W-@`Q60Fahu-2EDoS->(YQ$qtL,@~> +s8W,urVmW3qu6WqqqU3!s8VifqZ$Norr2imr;Q`UrW2rrrr3H,s8;Zjs8UI<mJm4ar;QQor;QZp +)ufd4qu-HjqEBRYMM$A4MhcIIq#:9ms7lWop%eRuq>UBH;Q6!ODK9cB<-7j.r7_,Xs8Domi5NXQ +eboCGrr*c7qtTg#LO"#_DfKiAH$Xd^G&1V2"U"u2qu@<2#:+)/H$Xd^G]e%RBOqYR&GuMW!<<*, +2JR/NF`heKFa/1TCdSd9#mC;/!<<*(!";YBEc?)GN7@M"rVlfr"6f+Hrr2rTrr)lsrr2p+8Rup[ +F`1AhY).<$s7uX1s8)`pqY:!cqXmR'LkChAJ;8Dp=o&*tqu-`rqtU'arVm&tjmr''i;Wc'rXAi$ +rqu]os5EY@l/DF0s*t~> +!<2fo$2so(q:hO7^[qL)rWN9!rVlfqs8W&Wrr2rsquH`qrs/N%lBSlto_eXe!r`&qrVlcq)>jF1 +5(\$7K78N4K6'QWr;Q`rqZ$TfrVc`nrt#&-s4C,EPX9;/DKAWqqYg<kkl1S]rr*B,rr2rss8Clp +_o1+(rVlcrrVca&hS@%H`5]d7_nuDh#0"HtNI?M@rK&.^OHG]u`kfO._8=(,^s'R3G^#F4OHP]f +PE1`dU;k0irk]qu_T'O4_kV^-Mi`sZP)tTbOcQid`l,m7_=dj.rVlfpqW@;Ig]%3N!rW&srr3Bs +@;fn%Dcg5DKlm@pqYh<0s8;osr;$9er:Nd'LOkP<IYDof=8;anrr<#urr)j+rVuforStQ(\uN+8 +q>\h@%KHA+s8DufUS=3GU!<Q/s*t~> +rVmi8qu-Qpr;H?OZsH^UYf4],bg+5Nb/hZD`lcH`aAKsr`QZTQb/(j4a3(JR@WJNhb/(g0b1"nc +aMl->b/h`NbKS?ZG'f7'I"6j"DEHk.b/q]9b0.`Lc,dlA_oB^8cI]]oT8bj>BQ&)h?H9asrl+oW +kf=gb`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[P150CS;olgOHDrVt'O^W"42_o'=-_7dt` +nEoQ/n+62As7QAuZd-G+_8*k'^:h>/p&=_6p@@b?mI'WBhnHYAai2*:`4j.&]B/e[o((kfm+9A" +aMuBL]tVV2hoIq&bfn5Pc-OVT`6$Ra>]k%.APQL0H!&D8aN2NHaN2TMe]YkI]t__6c-J7WKn>83 +JV\>\5hX`6b/hTBrl>Ync-F2HbfRAK4u"oV@_TRsd)Za>`m)WC`N<6?8l&ulk4\]Hs*t~> +s8W,urr3c5s82`ns8V6@kl:\Yq=jpfrr2rsqu$Hni;WcV$NBu&qtg-gs4lW"rr<#rs8)iprr)j9 +rquZjr;Z`oQ<B&qJVf)3J4_iEs8Vfirr2iqq>Lp$s7TuiWFKU7G]InL7]Z.Zr8%>[s8Domi5NXQ +eboCGrr*`6qtTg#LO"#_EH62HH?sjZC1J[s!!!)t!##D=,\qULH?jaYF`hG.%KQP0!<r?#-3uME +EH?;JF`hbKDJhoR!s&B'!WW3$!W`9/:N1>oFF9(to`+mhrr3)am.gSZs5EtSs8W'/r:5nAF*N"% +6h=QOXAIL@q#1<iqu6Wqr=Anb3e;X5JUrT2N)$kZrVZQl"T8/kqYL0j"Rb[JpXoKF!;k.B%fQ5& +qYpNjkk=`6irB&SpA]X~> +!WE#ors8T'rr)2aSZh>XrsJ`)r;Q]orr<#srSmhUs8VutrVlfr#lOAiWi3Jaqu6Qo!WDrqrVulr +ru1n:rVr3dLOO`.KRnPA2Tbptp\k-lr;Z`orqud,qZ$.rPGM]#8p5)jE^[&)qZ$Eks8VZhrr;us% +KHG,s8N&si5NUPec#IGrW)oqrtF8)_o'F3`5KR0_8=((`05RoK8okk$':1/OHQ6U_8=%d_E,HKH +?aphNKfQdOctrjO.sY4_ns7,`59R1_k_L$IXR6@OH5NaO-5U2_o9O4_SPpFs8DrrrVG[Gs5!\Or +Vuj-s7D=CDf^1p6Ln3CW(tt>qYpNn!VlTirsR^EIX6]uJ:`B09t('!qu6Qo%Jp)&rU\7I\[eHlp +\k$:rW3&urr3<(fqFn)R],?Jrq?AB~> +rVmi6qYU6ir;Z]cc>QTiUVb:&c-!uGb0%fF`lcH`a;i4=`QZTQbeq9<a2>Z#<aq-)`kfF/b1"ha +b/VF!a=ti_a3JluLkUM<IsH3&/[X$L]=u,#aOAJ[aMl'7`Q#jEcq0"]<)khjD0'bWL;M%0`<+'# +aSs?^aT'9NaAU$s`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8DoC))4lgOQBs3n`p_T9d9 +`5TR0^qIh\md9?-nauPMpAVS5_84=?`kT7'^r!k5p&=Y4o^M>:o'cD5\@o_mbK\,J`kf@%]B/e] +o((kfm+9A"aMuBL]tVV2hT5Z<s32.uaN2>>3c94e4tYVgP+=P8_u%Llb0A>T_Sa@6aj/AI,^"?f +IX[$(JiT4JbkT6ibKe,NbeKfY1b(aUSA<+]dDumCbJq`I`P%@38kN!)`:*I!p]#a~> +s8W,urr3c5s8Mljs8VWPiW&rRr:p<lrr2rtqtpBmiVriV"oeGsqt^-grrUI0kl1SbrquZkr;?R5 +r;6BkqZ$Nf6%=N?Jq\l8Cg2qqrVuosqZ$HgrX]&%_IT[3AG)TaEHcP?4SesRh>Rf^rVcTN`Pf^F +r;HZprY,>/q"2FYH$+1LFa/1XH$41@/IVLWrW*W5!!*-*,\qULH$FLTEcP\(!!E3#rW2rt%L"b* +Ecu_RGBIq@Ce#0Cq>_'-"T\T0:2Y,nGC>J#o`+mhrr3)am.gSZs5EtTs8N!.q8u$HG&1qWo(pR4 +Wg[Ajq>M-+s8Vros7uWfL0]LkKR\i8JpUGgqYC+"r;63bqu?Zqs6&qFkMZ@>d/FUSs82chs8VET +meQ23s8Voop]#a~> +!WE#krt+t<TqC0:s8Vurs8N#rrr<#trT!nWrrE&tr;cirrs8W(p?\<S]DDO*s8W)sr;ciqrt,&, +rUrL(JV&E*KSO8DNV`YRrrr<"qYgBlqu72u^0db"A+cK_DKBf14T#-Ss82fqs760gs8N!,s8N#t +rr;rT`P]XErVc`p!<)lr*o=]M_o0I1_SX.+_SjHYI!C$fK8knRPE1ifOe0S/r5'/c`4gS?KR\?! +Ll@O^P*;&gU;k-grk\WQ,/D3qHZj^]I>*ZBO-,WhPEE5j`P]U0_"Ia-rVlfpqW@;Ig]%3Nrr*K* +b!C&gBPTj(qoMg7QXKUfrr;rr(]+13qu?]os7_4OJr,)-LP:2&;tU"es82forsef%rVPrn]"4oH +q>('jd/FIRrr;oqpqihhStNOfo`'F~> +rVm#sq"t$grr3T-ieUf9P.Socbf[uIb0%fF`r=-@a;r:>`lcQNbf.Q@a325s9j2/;_84%/bg4V[ +b/hTBrl@%?`5g'J.sHZ%K7J>u?r;9t`Pfa3_9L-Kc,dlA_o9X@b+VLtKhgBW0P>EF?6n%FaMu6= +`Q#pqao]Z(`q%3!`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_oChhHmHa02qZ#-`^;.S% +b/VHB`5TO)a7JffmI0Z?qYp?&[)g8*a2l<@`50=0^X;`Jo^hV@n+6#Fi4Ze@_nj:6bK.]B^V.8@ +p\47NjO*>GaiDKBb0[i9ai`D[s2tAc'$AGDW%Vq+AR?n6fsj\GLdKD2rl4rY)Tp:NahPX1`QlkF +9RDYNJ;Ar,Ccg"gb/VNDrlPkp`l?*Faiq`1MF&jJ5@;4JaMuZL&B`8D`Q-!;Z?&u2:L0"@o_nL` +J,~> +s8N,trr2rsrY,&%qu?]Uk3E!ErVZKkrr2rtqtpBmir8uXs8E3"qt^'dq>UBrgu[f"rr3)urr;ln +rsSi(qu?ZqqYQ^gK7NrU.tNA"9`"\^s8W&rqu6Tms82`krVuIhX/8\SqYH"9G'ItC:Aaqbs8Vij +rSd_`s8Domi5NXQeboCGrr*T2qtTg#LO"#bH?X[\F`qS7-4p=W!##J:"9AN+$7';)H[0dREc>A( +!Wi3!rri9#%L+\(F*DqZH#[Y95S!r"qZ$Tsr;[618T&TqG(>Y'o`+mhrr3)am.gSZs5EtVs"s`Q +s8Mlb2gB=cBM\F#q###hY%t<:q>^KlrVu`oq>^Hkr;-Bc8:?5LK7AW'I6RB$s8;oorWE)qr;-Bl +$1@<Uq98m=qu-QBrXeu*s8)`ps4lu6p#Q#MrqQEcs*t~> +!WE#nrs8Q&s81`GTsadsrs/B"rr2lqs8W)sj8K&Yr;QZp'DhY(qmNT4jS8cRr;ZfrrVZWmrr)jT +rVu]kRpCMmK8#&2KR$2dr;$Bmrr)]lrVZ]nrVZWnn5,pT9]Z'HLI-')D/E#ErVZ]qqYpNlrr<#h +rr2rsrXJo,rr;utrSYZ4`7=hbrr)orrVloT_#D5U`kK=,^Vn"/N.H5$IslZnO,oE`Nf]Hr_nO+0 +`5':0\UJUIH[g<gI#*iEP*;&iTZ4ma^;@e+`lb*%FFAI]I!^F&OH5E`P**)h`Q#X+_"Ia-rVlfp +qW@;IhZ!KRs83l:rqu7BF_u23:\t%dqeM"eBX%=1s8Vups82ilrVmN/s7]$0Jq\Z%KQqf)p%\Rc +s8W#rrVmB*qu-?4]XYV>meZn]s8UOH%K6>,qu?TfWLfQJS^dT0s*t~> +rVm#sq"jmarVmGrZs?XF]#`4C_o^!Bb/hTBrlX9B*6,t;b08)Pb/hZ?`PfN0<Ekfu`5]mBcH4;S +b/jP$5KCacajb]7I"R</IW]mW4k.Qf_T'O9b0S>Pb.tj2aj/-oR[6+Uf%=aoC2dir3Ru?rcca/D +a3)QKb0%fF`q%2E`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_oD8%Kn*KW:r5upm`lQ-8 +^rj^>`5BF+a7/Hdo(;JKrq3q3^rFU?aMZ-@_u@Rn_pS/Ln*BH3nG*%A]"5o$`Po[1aNDQ?^Uq); +rq?olj3d5FaiDKBb0[i9ai`M^3l].ZaiVQFb0A<YE,'2j2:]poh-,E*=-C_F`lH'=b/2BAb/M04 +`6d-oF+K'tJqnPi.+cei`5fm=rlPnq`l?'@cca"q<])Ek3i^9H`Q-!Ia:HG;c,@BA_Q-^292/d& +nbVqYJ,~> +s8W,srVuos#P\#hs8V0Ej8T&ar;ZZnrr;upr;Q`Urr<!'rqu]kq>('grVlrMmc=?H"9%ukrr)j3 +rqu]is8)clqK=lSKnP50LP/+@rVulos8O2>qZ$Kls8N&uQ?TKYNVi\Nqti'gEbe:Np%eIUrr;cP +rX8c)rVGHk`5L4(rVulr#64SqoYQB/rcJKlI!TpPB.+5kq#D!/"9S`1+_uLEFDc/=>T3\J!rN$6 +!X/]/!!!3YC34fOHZX.>3YDZ%!!!&t!"]56!!!3oCiFKFL6'jVs8Drrrr_KOq#:9miVioSs8)`p +0`(Q:DJsi/=TA-pqYobMWh`GhrqQNnqYpNjs8N&nqZ$5s8!/OZL5CLI;#9e^s8)Tks83E+qu6Wq +qW@GMg@bLDq>^EArWE)squ$Hn$N&fNna#B<s82Hdp]#a~> +!WE#krs&GbWM-9Squ6U$r;Q]orr<#srSIPNrtG;0s7YuT[D_h7rVlips8MuprVc`q#Q"Jss82Y7 +2u\F7L4+i06HoB-rqufr+8l!8rVlirs8J1$Vg"'rrqlTh06(oE8$DX_r:^0jqtpBms760gs8N!, +s8N#trr;rT`P]XErVc`p!<)lr!T(Wk_csdg_Sj@0`K,@iFaAI^G^Y-sNfT3[O.+,4]u@e,`jpS: +H[^0eH[C!gLQ.L^P`h]Y`PfU._8OEgI<U'bH\$NlJVT/FP*;&nZGaPm_SX+]s8W&srr)]UnGhAE +"982sq>UCLr:risCNa#ds82ips62nIT1o4`q>^Kks8Vrqrr;oqs7WlhNIcV3LO_N`q"+F`qu?]o +rr2rtqu?[(kJ"XESAk*ps8W&te,KCIs8Dut$Mr>MSsl(Gli$k_pA]X~> +rVm#tq"jmarVmN&_J`R^V8:BuaMZ*Ab/hTBb0&\as2P#[s3+Qc_TBj5Y=r/?XhDj"bJM9Cc-=DN +`Q#p5bf8#Uem0eZLk1+sH\"2Zbg4/A_TpEMaNMN?c,eAaF_.7_G1G$gfA7HWBPKerbg+AIaN_TE +b08)PaMu6jaF2(I`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8@oC_eJo_HVA]YMP._ns7* +_9'd;^:VAXqs3nDqZ$9&YJA/rcHOJN`l5m;a2l6Io^q\?lL"3BgqgbFa2Z?B`5T^:aMu'.]]/YV +n+5_gm+9A"aMuBL]tVV2hoJ[7]?.t9ccO>W1h1?C:H[@Qa2HNQ3hi$&f?V1Rai)0@_9U-F^VS4> +Si_mbJV/o62EfsDcHj>G`lQ<Hb/hTA`l66H["1:l4"Y`jaj8,G`m`!?b0\>J`6#`J:JFP[En:*e +rV$8A~> +s8N-!r;HZqrWr;pqu?]bjPfP*rrDrprW2oorr:gR$iKeqrr<#rqu?$;gALsPpAFpgs#U/Wr;ZWm +s8Vuc3J<0:J<,/6?AA@Qs7ZKiqu6Wns8)`pp$YhUX\n`cs8VikP#HLJG<Y$cr;Z]nqYU9ls69Lj +s8Domi5NXQeboCGrr*c7qtTg#LO"#cJ9Z6_E+gX-"9AK(!WW3$rW!Q5"pPAZCMRs4De<8g#65/: +!!<*!&HW(=!!!*RC3+TFHZNp_%fcb1!!!*"!"]27!!!?uE--/PJrnLSs8Drrrr_KOq#:9miVk\6 +qZ$EbqY[EdF*DA$q=jmgs7uSWFKBeOpAP$irVu`ms8)]os76#'C57IqNIHP35kY0Rr;Z`p"8r/s +rVlg(mHX9<df9@Eq#C<@rWE)sr;?Qos5s[Qmc+*Cs7uKip]#a~> +s8Moq!<2rs$NBS1T;0[0qu6WnrVliss8CaPrr3]2s8Vups1P28k4ncLs8;orrVZTlrVnDDrr2rq +ml5lNI=I<,KNj-*q#C*gqtpBmr;ZZnrq#SUTr:WRp](9hr/jnVEreGar;QcqlMge_rr*B,rr2rs +s8Clp_o1+(rVlcrrVca$hS@%H_T'4$rl,5)H$O^`I=6Khrd7:kMiWm[S]A@\aMu!+GB\1[HZjg^ +GBnL^JW,VMOe0P1^qR\(`h@g"H$OX_H?X^aI=[9:OHu0?aMbd0]YF.>s8DrrrVG[Gs5*bTrsei) +qXsdbX$plFAQJ['rr<#o,*?f@G*2P!s8Dorqu$KjrVuolr+fnrIt3B$J:9]Ts7u]pqYpNp&H)D) +p\N4N]=4-qqYL6lr;Y7Fs8NN,r;ZZe[%Wt\S&P7&o`'F~> +rVm$!qYL*erVmN(f8j0?MSR-LbeqNEb/hTBb0&M\>0>19`59I1bJnHo>aN+Ca3;9;b0A2T`l5s; +aMH*IeC)\gI"ZimK62fJCXU;K]u\17bgFGN_T:$FbrV5d4k7a!d)sp[4_K%^.Dsied)a8Gb0%rP +b/hTBo#Q7!`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[Oh+qXF%Oq>A@C]YVV1b/VE;^:_D) +`koL3p?_DFqtKim\%9]&`QcKE`l#R-`l>s7cLg_qlgXNAgUt#8`l6$=_o0L-^rFC2^qf(.p$VM4 +cg99*a2l9Cd(R08b2:9;`lPg?aMH$HN&kfs?TliXa25a5eq._8D0*nBb/_QF^Ve46a3)N?eQc[A +Kn5&.Ir?X^g<%LX`Q$!Abf\#H`P]U@\Y<@d/O)8!aiquO_oC0H%a*)@^r+!s@nTKq>FFjWo`'F~> +s8N0"r;Q]qs8N&o!<2ut!o;nor;ZcqrqufriVrlTrr3]3q"asirVcZis3Tils8W)uqtp<jrr3f6 +r;?TorVuWlq=o_uLkUJ5I>CPirVulrru_(:p](9ls8RS&WbAI1s7uKjs7<0aDfT_^p\+R\oDe^e +s8V?_$ig2(qV]?2`7=eas8N!/s82T`_M<DZG'nOTD.b4("8`'"!<<0"!<39g#U*r'FDtnu(((BK +!<E?.!!<<+!WrT/!!Y8tFEMqW@6tP."U4r-"TSZ/!<<*$"p=o,7Vd-lJ:E[1o`+mhrr3)am.gSZ +s5EqXqt^6k2#"aTGBRjhq>L*frVccioMq]c7e-NTq#16lrr<#rrV6E`22-[8MLUX_7H4(?s8Dur +s8W&s!W;rprsIuWo&93?s8Dfls3^fIqu6TorsIcOlKR%&s8D]hrqHGC~> +s8Moq&,uV.s8W)pgmk.JqY1!hs8N#ss53hUs8Drsrs\o,qu-Qel_(c-p@e1Xrr`8ur;QZps8<Q0 +pAb!`Kn4r2K7SB&8Fu`Yrr2p>q>^6is8DurI=e>,VYL2fq>^KeVbLrDCdIjks82NilMge_rr*B, +rr2rss8Clp_o1+(rVlcrrVca'hS@%H_SX%$^r294H2i1eG]n7SGC=^`KT(nOR`WLgaMYZ:G(4a\ +Fa/7WI=$9aHA.<?P,$.;^Ve+&UO@<4IWp-iG'J:[H@1C(OH>@(_o9O3]>+%=s8DrrrVG[Gs5*_V +s82ZlrsAJ87<3?]4o,-TrVn/9nkl!R7.L<Uq#16mrVuoqs82if14Xe%L3neQ6fRn@s8N&rqu6Wq +&,lD*q;]?-]VN@:rr;uqs3^fUrVuloq;eBESYMb;q#(*`s*t~> +rVm$!qtg3hrVm6"l*t2-FLo$#aN=G(g;s95>0>19`PTF2d_2GM?ZNNe^<=F5aNVoQ`l5s;aiDTN +`m`;eG'\[gH$k!j2:U($aN)HK`R2HDbfeMiA9"/CP1A'u_p-QPM*#Nn?nC!Yd)NiFaND`Nb/hTA +o#Q7!`Q$-GaMl6Aa2Q6MaLT's]@G*Eb0%cHb0Skkg[Oh+p%%\IrQ)LZ^;Iq-_SX.'_n3Y"a25R2 +q=aX\qY%G.`4s.*aNMTGa2G[*`5]d6dJ3D(p%dq-]=Gi%`Q66=`PfX,^V[q,]=-_lp@@h5cg99* +a2l9Cd(R08b2:9:`kB+0d*U"+/o5K=0%\Cc_7dS(akK@XT.eI;`kod<`Pfj@`lH$Kdj]s*KnXc, +67fq!d*0JK_oBd?b/hZD`PfU5Z%#7u2*,`kcHaVQa3r$>b0/#G]tC%<92/](_sm^)p&BO~> +s8N3#r;?QnrrW,or;HWshr<;frrE#srrr>tr;?Tpir0#Wq>:-js7m!$rr2rlr;Z*:hYmHVqtU'd +rr2utrqnbUqu?Tns6*!CML^D8M1(%_qYU6kp&+^crql`pqV+uGTiq0gs8Duns8Vql9QYAn;#1(i +s7H6erVlisl2D(jrVcTN`Pf^Fr;HZpr_!4fq"2FYH$+7KIW]-I%Kut9!Wi?("pP26!!*3.#mqe] +HY@%q$k*FB!!3?2"98W,"9\].#QtMjAo2X8C-)q4!s/Q."9JW0"o\K5!<iZ4#>T#QH$Fn$eF`e> +rr2p"kj8*Drr:sVs8W,p#ljNnAoD]Zc1q;<-2dcBs8/j+YEEl"r;ZfqrVulls8Vig<)&%&JVo1i +K_kHCs8)Zls8Dotr;QZps6U-Wm+VL>r;Z]ks3^iGr;Q^"o]GW0hq7r.!WMrhs*t~> +!WW/ss8W'0rVlisrVc>aTr$ZBr;?TnrVccSrr2p"rr)cnrr3B(rVu`jq8]S@h>-dBs8W#trr2pR +r;ZTmr;Q`\7n&2]KS>81J6;RBrVuThqu6Wns8D`E;59acp\k-ks8)cqqP-T"EGJAHrr3&os8VHb +rr;us%KHG,s8N&si5NUPec#IGrW)oqrrLulrkhsOb/hAXI!U3fI!U'`I!g6hH@CO)N/j=?cG7<. +Ed2nUGBS4VF``+WH?OF\MNEmi_8+"1^RKLqG]n:VH@(!aGBnL[H\%$;N3g:9`kT=)p&G'jrr2lm +k4&E-rr2p)q>:3`:h4<X6d,3&rrE&ts!.E??`]?.q>UEorVccpq#CBiqG^.?L44l0?A/1Ms8Vrn +s8Vuqrr3K-pAW.I\@AI%o_eahqZ"tBrr3E'qoGD$U7eLZqu6WppA]X~> +!<)lr!r`#nrVm?*p[m0\?XoS7]Yhk6b1aoP`l5p<b0A/M^VnIAa1-Is>EcP-a2Gsrb!a=j`lQ6@ +ai;QGb0[mP0n+@tK8Fhp6Ia<&aM#U4`Q#gAcdB<hQ]a_ge'5kP^rk'SMEbol?96fjd*KGIb08)P +aMu3ia?R\``luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8;r;QN5]>);&`Q#d4`l,a5^;7e0 +`4s=]s75pVYdsbKs1oSl_7n",`4rq"`5TO8nFHDTpsld`]t_G&`;[XR_#M+b]YD;$\``YVo^1\b +m+9A"aMuBL]tVV2hoIjua2uBGf[Ml^Ana*-c-FDI^Ve1>f9B=4JQC+@c,n#HaMl$AcH+Hs7u*.Z +KmHU4f$)Rf`l?*B`l@qt&B;f.Z):Vb00W(-^rjpC`m)oPs2kej]Xr_l9Mo#@hY7'MrV$8A~> +rr3&tqu$Hns82lrrVlumiS<\srs8T's82Wirr2rWrW;ukq#16mqZ?]qrquctdH0Tkrr`)nqu$Hn +s8Ef3s7lWorr)fqpp<hLKnb)6KLbD,s82fq+Su-8q>U,(Og8-1q>:0irVuQjp\.[(Ec=7oo_J@` +r;?Nms8V?_$ig2(qV]?2`7=eas8N!-s82T`_M<DZF*V\:-O0_O!$MCG"U5&/!WW6$!!3KSBl@ff +(CLEI":#5=#m^\;!X8l3rWOVX3GW_W?9K//!s\r2#R1;5#Qt/2"p4u4!t\7IEHQ;QNR[V#rVlfr +"6f+Hrr2rVrZ;":s7lAI=EJ[`V>1)bs8;orqYC$c?C%3ge+`kApAP",rVHHB8;)VIL51=GpA=Ua +rr;`mqZ$TorXf#,rVuookO@rpn,NFarr;rDrX]&'rr<#YkO@Zgn,NFcs8DZkJ,~> +qu?Zp%K6>,rVHNk_P*[:s8DusrVlftrr:sVrr2usrqufr%fQG+s8W&qnY*(up\t-hrr;oqs8Nf- +rr;urs8Vo$9n7kLIu&S?kkb>Wrr4#9s8;]koP'>h=NL@;rr)irpAap];J9rb4kB?*rVli`rr2rs +rXJo,rr;utrSYZ4`7=hbrr)orrVp9^^r+(.a2,TLFa&+UH?a[YH$ag[G]nCZI"RHOai)9-HZs[U +H@L?hH?j^[G'\FYI"@$/TZG9r\!qniG^O[UG^+CYH?OLYG]e:_M2np]_oB@,_=dj.rVlfpqW@;I +h>TA2rr;fgM,nV8:8@Uap](-js82Zkqd#DU>LWEIs7ZKls8W)srROJkJU`?*ImNl.qZ$Qpp]('d +rXo20r;Z`S]=PMOaS>f3s8W&rdJa[VqYpKcXdP`PU!<N6r;Z`hs*t~> +s8Dors82cp'D_:um?_<gG.>*(ai_cIaNDZF`o+oW`l#d:bfn/E`5TsGb/18V=Dk7S_o9gAaMu3= +rl@=L_8spCa2u]UPs0PJLOXu&1X"7m_o^$C_9'U8dEtjGW'mW5bf[uEah#a@f0<PVBJ-sDbJq`H +aND`LaMu6ja>:iT`luZJ`Q6-@`QQ]N\\G_fe]YtTb/_WHceQt'nFQ8Enb0r/]Y_S*`59=,_83k$ +^;9f]7_d7HqYTQd[Ca,jbJqB6^V.Cs_ns.%]tM)'o_nd\gVUD2_7dIr^V%D!^V@S!]=bhk^utUd +oBGA_m+9A"aMuBL]tVV2hT.^saOADdF@p@a6Aj4>_8jF5`kfL:fh73d8[6FZb/2KGa2u<AdC1u^ +KSYJ8E[fJ_`QcQO_99[7`r!gg`knm+4u>2ZH+_;<`Q$*Gb0n?AbJVE;Y%(4$9jXaaqYpNnpA]X~> +rr3&tq>C6ls8N#t"oA9!kMk7qrrrE%s7uKghu3]So_8=a;uZ[hs8;fpr;Q`ejPg%:s8;]gqu6Wq +rr2iqqu?Hjs82Wgq2Ag=Iu&]3>*Aj_s8)ZnrVuops2/'DMJ2hbo_nges8VfmrUE$jE-42.pAad_ +r;HWps69Ljs8Domi5NXQeboCGrr-7(qtTg#LO"#_EF1%,#6=o,!s8`4#Qk&,#6k>3!!NZNA8P'X% +1<IG!sSc+!t#JB#R:J6!<<<C2/-`".hMjd!!j&C$k!7D#R:J9#mq"F!Z==CEH?/MNR[V#rVlfr" +6f+Hrr2rVrXJo%r:kMBDf]Sir;Z`orr4DEs8VuidoWcA>PeBqs8;oqs7lTlF_?;ZJ;8_WX8;epr +;ZZos8N&urVlip#Q+Q$iU-4+h#@<Vr;ZcrqU,9Ks8)]orSm/3jl6:>!<)QiJ,~> +qu?Zp&H2V-r;HZpj//TOo)JahrVc`q!ri6"ir8rW'`In*r;Q`ps8;`nq>^H.VR#%Rrr2iqrr2rt +3;NUKs8W#nr;)=ZKm\]-Jl@[*r;ZZms8N&uqu=H6WekEds7cKlqZ$Tis82:HD/OARn+m"Xs8VHb +rr;us%KHG,s8N&si5NUPec#IGrW)oqs'X^!_o'F3\qb`\H@C3fG^+L[H?a[]H@'j_K8Z,9`2n9- +H[^<`GBJ%RI=69`H$XgaGC>@8`kng:G]\4QI=6<`G^4X^H$Xd]G'A:`P+fb3`l,m5p&G'jrr2lm +k4&E,rXJo'rqUeCCN!`[q>U9hrr51Ys8W)ne5`W:>5S?rs82ios7u]nF_-,UI>*/NXSr2!rVu]n +s8Drrs8W)ts8VuqpqXSQ[ArTgs82iqs814C%KH>*rmdd3S=QnSrr2fes*t~> +s8)fprr3#tqu-QppBU`l]PLn\VRcZJs2b5_s2O$==j"b%_og3E`P'@4a3V]K^iN@VMR1.Cd*0MI +_8aR=b0S)P^;\73_912L=c.idI"+e5f?DFT_oBX7b/r;07Akf6e'GnQcG@?:^!bEX-Z!^8,Ke0V +^;e7nao]Z(`q%2X`l5sAbfIcEaN)9Cd`Au6]"?M9`lcHEai_rbdbF9_oC;"T\@of'aiVN<^qd[t +^Vn%-]Xtkja8#JgZ*M![`PTU.\@K8e]>2;#^q@%`^Vo^:kK^cP^UV.t]=YbhqnO#^]Y(hrg%b4/ +m,ZLZf?)(S`lcZA^<+OTa>h>ha3;k9:MOiQ3S)R"`lQ?LaiM]FagFU:NBYb3^sC3M`l5^<f3ML+ +K7o&,6]012b/DKCc-XN0`rF-[aq2V,T2.C"4\;Qec,.31dEg%aa:?)1_i7\m:.]6Ko_\RbrV$8A~> +rr3-!qu$KorVlis&c)D*jQ,4os8W)urqZ?drr<#XrW;uiq#14+rqufms8W&tpAb0>ki)O@s7c?d +qYgWtrVufmrr3,rnO/(]re2bX6gO^Nr;Zcrs7u]h:8Xp`l1b2Ss82irqu?Zks-HH*Dg"8Ao)JXc +rVlisl2Gc(rVcTN`Pf^Cq>L?mrr)lrqt.[ZH$+.G4YJH8+s\E]-n$Po-71/i-RL#_,8_G:C.13I +1bggG3&`fU2*3cY2)-sD/O!H&E+hm+5<h+i3'BVq5!2"i4?>Jb5X7=h91a2HE--DbeFEM:s8W)s +k3W!Es5<l:qY^9W5&GIb3eIA+s8W&trVulls8)G0L8\jnrVZ]krVufqp$"_qJr521HW9\8rqufp +s8)]ls8Vuqs8N>ukje?$mf37brrW)rr7_,Mr;HWps8W'.rVliskj.g-kNr6Hs8Vofs*t~> +qYq3-r;HZnr;Q`oq66Wif_bXHrVlfrhu<WT(&e%,r;Q`rrr<#ns8VrcRC0Whqu?Njs8N!$r;HQn +rVZZp%JoQ\JUW9*JV?ASr;Z`oru:h6pIq?X9Bu?Qrr;lqs8Dusq#?XPF_l1_s7H<jo)8Xhqu6Wq +rr.*@rr2rss8Clp_o1.*rVlirrVulrs5(Q/`5TZ\NKfTgP`q;nO-,WhPa7GnP)trpNf1rnT:2FC +T:qgJTVS9QT:DRESYMjHVS8D;^S[EnW26GeTr"QZUo:#aVP9]VU7\?lUW(6j`kfLas8W&srVl`X +nGVbRrVuWk3WK*Vs8D:IC3"8PK)PKEs8;ilr;QNlrV(>bV.[.4r;ZQhrr)lkks'cNLk1##<;6Cl +rVulsqYg?jrr<#urX]&*g:t;3UW!0.rVccns8C[N!<;op&HDb0s7NaoS=64frVZ]pp\smdJ,~> +rr)irs8Dor'DMA'pYC:*=GsT)aNDZHaNVfH`Snm>b/hK>b07rG`l#sC_9U3?X@ZT&S%[.kb/V96 +`lQ<Fai_QE`5BU9aiVseJ:W6$IXa#ocH=)H`lH*8d*je8SNb-;bfA&K`l#O2b0&=\6$-[J+POf[ +rlG)]!Q`:Ua8j6YaF24P`Q$-GaMl6Aa2Q6MaLT's]@G*E`lQ9Fb0Skkg[O\#mD?Z_dam4.gXXa$ +dEp@oe'ujmdETJ>qX`1_g"G6CjlGC[gXk36iniPOh:(3M`:W]Zg#_M]kht@XiS`\WiTB:_ioT4V +hs/kgp$M2+cg9?,a2lEId(@$8mE#7GrlG&\rl@(=b0AGbasgh?D'WN8_TU-Bbg"JV^rOC>>'uo@ +Oj(hnaNDT?bfIgVI=I**H>GXgai;0:`QcKGrl4uZs2G\oaN(H(5r(D\EkoT4_SO"4dELIgrlY&X +&&uT.c+@[e:Jk5IjRi<Gq"=Z;~> +rr;usq>V!)s8VlMlK8-Hrr;okp\Fgfs5X([r;6Ejs82fqrrDurrs[*?q#CBmrV6?grr;oos8;j) +qY@*iLOk26IT*BAqu6U*r;QZgT5^i[MYd;Orqu`nrr2j-qk6],G[ODCrVcZfrVulps69M&s8Dom +i5NXPcLq/9rqlQls8Mc/KQqZ\F)u>>D>\5MDZ4JNC]A)WBP2'NDK]i8E+j0,DuOVODuFMcDfB`= +FE2A?DJj<.DfBZ6Df'FlD$FotE,TW3ErC+lI#H>@q>C9mq=s";rr<#tqs"(rpAb0js7uQlrUo27 +Ecu@\h=(@CrVuorrVlis)#3PlWi&efp]('hr;HZcF)$DcK8"_Lp@nRd$i^)$qu$BlrVuosrVlg& +qWdPAmFD7:rr)iur;6EOrX/T&rr;usr;6Eirr)itrqucq"Qo=Jm+Lk-J,~> +qYpQprVllsrr39%f:AbDo`"ggrVlrurVbaTrr3-#rVlcprr;rr$ig4uk*<L)nc/RfrVc`tq>^Hn +rVulrruV.8W)84rJqSSMXnVbnrr;iprqE%&WI0R"r;ZcorVccrrVud"T1X0I?;UFrrrr5us8Moq +qYpEmrVlisrr+#>rr2rss8Clp_o:=/rVlisrr;lns5Cc2`PfX0_8=(g_u7FO_>qFN_Z.L\_Sa6Z +^W=41aMPsr_Z.OM_Z.OR_>qLP_Z%FX_Sa7,_8=(,r5/KM"N&*q_SQ5g&AZ3Us8Mios8;l\n,3+^ +rr;Qgqu?Zp(\Rh.r;ZWks8VoT4`GIZ2r*p%s8N&ur;QX8rr<#nmmj4L;"XS`r;Z`ps71/BJ:rB' +HqsG3s8Mio&cVb.rVlisro:o/\[&.+qu?ZprVliVrWE3"rr)iqrVm!!rVc`prse_[US"$GSDX2C +s82cmpA]X~> +p&G'j&c_at[TusKZ,"<!b/hZJbf7WZaT'6]aNDU'`r3skb/Uua4'[B>`lZ??`59[@`6-1"au[V` +`PojBM*QE6JU_c0PK(J]aNhiF`Qa$DSS)]dcHseVa2Z*;`lH3Fe:p&"Cf3CKe]u:RbK\2KbP]N_ +aT'71`Q#p=b08#J`luZJ`Q6-@`QQ]N\\G_fe]YtM`QQNHbhgq'lg3p(n+-,GrqQQhrqHHcqtCcs +o^_LomeH8FqY'g^q"XRVo_/"Wq#C$lo^_SBoC_kWq#L3cpAF^cp)!JroCDD?mc2a^h8mO\dEg+K +^<=U;aNF(p!64uV<6!#%bf/)VaNhW=bLbCg.:d1%,JD%:`l-$Fbg4V[b/D6<b;c,]4jM-p`Q?': +d)oHsKStG/C,!uVbf7Q<`lu]M`lH'@bJ_?Ba1$aj0/5XgZbud^!6G/^iQ),@aN2O'bQ>r.aSj*Y +aSs0e_kg=&8Q033lMC/Go`'F~> +n,EdVjk]n8s8Mihq"t'is3goHrrV!;lMgedrql]kr;-HlrZD%;q#=eXLPgh9IT-%?r;HQnr;HF] +Vl!)\s8D]gs8Dlprr!B!9O;Xa>^c5>p](*gqu?KVrYY\6rVGHk`5Bmprr;upq#16lo=fj!EcQBq +H2MmdG5l[jDL?YHG'J(RGk-1VH1?4WGmf(\cggo4s8;]dipZmH!rVrnlMaNXq"t$err;iflT&m' +68rTLr;Zfprr;rqrr)fqs8;VRI&D"Sr;$9is8DlM8V2\KM2$MFrVuirs8Momq>:*is8;iqrqZTo +nE003f)G[Mr;Q]qs8)foir8uU#lal'rquZjr;QZp$3'o$s6T(Eo'"p,rrE#ks*t~> +nG`a_XIZ!1p\b$hrrW2trR(TKrV!Cq\Erkdrr`9!s8;lqs8Duss8O2=s82h)/qSh3J::Mos8;cj +s8Dun7]3%Rp&Fs`qZ$NmrtGD1rVZ7Z>\nXgI.[@7s8Dons7lHir;Zfr"9&6!s8N!-s8N#trr;rT +`P][Js8;iors8T"rnkN-`5BOb_uI[S`W*mV_[*ot`P'40_8aIb`;.=@`;7CO_@62=s82`ks8VBP +qu$Els7?6es8N!Es7cEhqu?]pp[("\DEp*no`"mjrVlipr;HQls8W#iO*IC:Rf3-_rt#)*gIH^D +I"d6'Q2gm]rVlWm'DhY,rqZEccF:9oU"]GCs8W)rrVliVrr<!!rr)iqrVmT2rVc`ps8)W,URdpG +W9aE^s8DompA]X~> +o)B:"qU]^a<fFQ*aN2BBbfn/JdE"8d[TQL<TXMtbaN29;b/_WFaND`Nb/VE9b/W.(++AooG]Z3s +ai;EDd)=,Z17sp`bgk"YaO&!+`Y?M7aj/3e:M"TBB@>,Gcc4)IbehI!askEO`l5p:aNVoQ`l?6H +aMl6Aa2Q6MaLT's]@P3G_8FIAb0/Yoh!OIrnFHSMs763[#O;*Ulgj]:o^VPKo'u>Jndt!4mbc7/ +bKnY_\%^&*`lQ<na8j6Y`E^F(b08AUaiVNAaiMo\-t6aE,YZG+ai)*<c-4DVbfRlD`lr[DS76rt +b/hTDa31qIH\dE2G@b^>ccF2H_o9dBb/h]Ha2Z$6`P86Y/LNS>PJY;Y`lQBJ`l5sWa90H'b0'_- +(<X_<`l5s;aN2E:`ILfR7p1;joD8(Po`'F~> +nc''ss7kO5mJm4aq>:'err2rGrr<!/ps&4%s8W#krqucqs8N&uqu.-+q>'dW6%"'5K7?/*q>C6k +rs\LFJu!Ffo`+sfs8Mrorr2j,rq%gdDJh[dq"sjdrr;ipl2D"hrVcTN`Pf^Cr;Q^(r;-Blr9h+J +FE)ACqK2=Os)\HiGB._KG&kuQ$[dr\med%aqYU!Gn,E=gr;6EWrY>2,s8;iqq>#ItEd;cOeare> +s8Dlor;IZ6rr<#sohDHi7.BpMs82imQ;rZrMhP6$s82KgrrE&tq[`W)rr;ros8W&troWV;iT:(= +!W2lqrrW)nr8R_Ur;HWnr;Zcrs8N#trrq-@mI0'+rr3*"rVuljs*t~> +nc&gmr5bM)\bZ.&!ri/sci++#S[-<1r;Q]urVHQoq>UEo%f6+uo07JFK7n\>`;9B1rr3E!G^uT/ +X7Q>jq>^HlrVmQ1rVcZoo.4otCd*7CrqcZos7u]krqufprr<#trX]&.rr;utrSYZ4`7Fk^qYpKo +#QFW"i53=I`;.7@_Z.FV`PfO+`P]I<_@FAto`+shr;$BmlL+QIrVlifrr2rqrX\c&s8;iqqYPb% +F*_lMeF`b?!ri/sr;H]prr3o7oLl'^61=RJs82ikPu<3eL4N<ls8DWjr;HQn(B++/r;6Nor;PN^ +\[nrTr;6Kns8Mrprr;!Ws8W#rr;Z`p&-)UqW1ocPS]:C%s8W)tqtC&?~> +o)Asnq<4/L<c5JIaT'6\aNDiM2TNUo8QKf;`669E_nF+9bfIlJb08#L`Q#^6bg\+ZFFJ[b1SrC? +b0%cKb$fC\@>W%QeB-.]r5KDka2uQWe/)_+?n>^7ccF;NaM?%!aSs<^aSa%'aND`L`Q$-GaMl6A +a2Q6MaLT's^"CQK_8FC>b0Ao$jn8BDnbV_GnGhq]oCD;9oC;4qn.=X+kh=2#bKJA[\%^&*`lQ<m +aSs3ZaSs=a_og<Fa3MND?mB/tB"Yn.e]u1O_oL!Fb/h`G`lH3HeM`ni0[\.mbK%oSG<pe<N.+-@ +fZ_7[b/hTB`Q$'EbKe&@_SaC+HpBGD4']84`Q#p=bfn)G`o+r<b5TTcb/jS%s2Y_naMu*$@o>fi +>c$WUqY0gXs*t~> +nc&sqs8Us;huE`Uq>C6ks8ULGrr38XjQljGqt9mdrr3&srr;io*rGp9qohNfK8##'=S`!os8;ZM +=0.ukp\ascs8;lrq>LcuogqtiG]6MEr;ZKirrDfXrWrQ&rVGHk`5L4)s![mCr;Z`a\qYHPF`qqP +G'A+RG'A+RG'A+RG'J4UGBe:TG'.hKH?sc6G<'hjG'A+RG'A+RG'A+RG'J4UGBe=VGB\4SG'A+R +G'A+RG'A+RG'J4UGBe=VJ!&7Lq>^KmqtK+=rr3&tqu#aYs8N]/qu??ho/CH(E+3SOs82WhrVlfp +rrN,trr*u8Zsg4nGlIL9s7u+JMhcn;HVXD1rVufqs8Mrnqu6Qo!W;oqrrh]Wp$^!$rs8Q"rr<#t +qt^0Lrr;oorqcO!rr;utnDEEnlJqjC!ri&qp&BO~> +nG`^kk,+oNhY-mI!ri/sd/FFLpU7'-iVNQQs8Vuqs8)`pruM%;s80r+M1UG6FB85;qu6Keh,C;C +;>9tbq>^Blr;Z`p$iKZg:18<`:dG$[q>UBpp]('gs8W#rs8W)t&-)Y.s8N&si5NUPebf+:rVlg% +rVliU_Sj=1n\k@Erko&Y^r+76`5KXb`;.CB`;7F_`5D6Irr2rps8VBPqu-Kms6BU`rser)s7QEa +2JdAQ?to-1rqllts8N#rru_7=rr2lnZX0bbFoM77s7kqDLP(#*GYIr.s8Vrnr;Q]q&cV_(rr;us +s8Vi0[_BGFp@\@_rrW2trr2rWrr<#rrqcZprXAW&a/,H!Su1cKq>L?mrq?AB~> +o)B3uqX)%5=')!,`lQ0=`lS/%d`=Ae_745S<gUG=aiVN8`QufM`lQ<Hb/hTA_TC6XYqg`UK7n// +f@\-__oKD\Ul[^dc-=AYaN2L%`rF*mb08,V.QLIC?TTF_d_sAL_n3qfaT'E^aT'9[aT'C+aMl0C +bfIcEaN)9Cd`Au6]"QbA`l#^9c,e>qhW4D*q"4.Jr:BpY#Oq0Op@\"IoC;DIoC;DJo+:$-jjqGl +bfeDX\%^&*`lQ<jaSj7@aN)?>_p-$HbTU;&@o64ThpBE]`5]m@bK%WCaN;TIc-_bOUip5$bKJ>X +aX2CgK7Rque]H(aao9Eb`kfR8rm)A#]tD2!X&(T86oh'P`5T^8aNVfH`Q$iWr5o#\rPnlY&'Du0 +_hD;k9N,fSoC_nWrUg,?~> +nc&pps8V?<ip?^Fq>UBqrqu]Arr)j$dIHB!s7lHirrN)rq>MK5s8)`op1\;qJVo.MUAXids8?Jk +V-M"3s82`mq>^KjrX]&.q.Ma2DK\Rhqu?Hcs8V?_#ljl%qV]?2`n(+gAcDK&rVuDsL4+>kF`MSE +FE2JDFE2JDFE2JDFE2MFF`MSEF`DPFEH$)BF`V\HF`V\HF`V\HF`V\HFE2JDFE2JDF`V\HF`V\H +F`V\HF`V\HFE2JDFE2JNOkBC+s8W)qpuCiBrrW,qr9=1squ?]ms7qUDF`VY1]_qU'qu6WqrVc`p +rr3r:rVc`iqd>bn:tG@=qYOfFM1:A2<5A>0qZ$NnrrW,qr;?R0rqZTop%%hMe`d&4rVQKks8W)q +qu#=Mrr3'!r;?Nj!;uir"l/>'ki)(2rr`8uqu-3fJ,~> +nG`pppUZih^\Ig.rr2rtcMe%Es6Q;b\+BRu"oeH"s8N&rrZ;+;s8Dutp1J,nIt`G>T_\B_s8-/^ +Tj#G.s8)Zlq>:3jrr<!+q.DX.CNN(cr;ZTfqu??gs8W)t&-)Y.s8N&si5NUOeGAq9rVlg&rVuoO +^;7P!_XPJB`;[XY`59I2^qn"Z`;.=@`;7CO_$p#:s82ios8VBPqu-Nns6K[art,,.s8)ciMa_Z* +Ea69TqYpKns8W&qru1n8rVlWj?B_?^ebAt9qdOPuH\?`D^\\!/s8MlqrVlfsrVl]orsJT%ptNEf +]V`aLq>L<prr)iqs5*_VrVlfmrt,2.q!Y/XSY2^nq>:!ds8W)ks*t~> +nc'1!n_]:&;gc6s`l5p7`QZTLdE"5`a/MR2?`1lea2Pp4c-FDMaND`LaMu*@`m32c:0;moMh3pH +f#YhQe4GUn9rZCeb0%iDaiFA"s2b5_&C8bQ9-\(YB/?F7d_NN8a2S%touJ5o`luZJ`Q6-@`QQ]N +\\G_hf$).O`Q?BHf&Y<1ki_4!mf)\SmKW.In*fT/nF5oBmd]cBmL\<qiRc,hbKJ/S\%p2,`QH?m +a8jB]bZW*.`PBF7`mi:M3,N;>8"eS_c,muHaN)?@_ns@4bfe2Pa3mP8V*VZ<da-N:@Xri^G!htM +d)O8Mbf\)J^VS(?eBGqI\\54r3[d9XG.kZ4`l5s=b0%`DiQ1r>s2b2Zs2b5_%Euo0Y?t='<*tdO +qY0mXs*t~> +nc&Ufrr3/Wm,%dBr;Q]urquZkdf04F!pJ7uqu6csqu-HhrZD":qtL!dq*p-lKRo+WqYg<d^LaO) +F85e0qZ$Knr;HHj%eonqqXecTDIc-.pAb0bkl(kfrVcTN`PfdIrVp1$q"jpem^eUAM2I"=K7\`- +K7\]+Jq8N)Jq8N)K7\`-Jq8W-K7ST+Kn"`,K7\`-K7\`-K7\`-K7\`-K7\`-K7\`-K7\`-K7\`- +K7\`-K7\`-K7\`-K8Q&Kp\k*orV5LCrr3#sqs")<s7lWmr;Z:oEcH.rQhC4Sr;?Tprqu`prVc`q +s8Doqs80oAVOh8rqtjWAI=dQ3CO,mRrVucns8Vusrr2ouqYU9l&cUtirS$<3rVlZhqu6WqrquZL +rr)itrquck$2a`%s7bO;jQ,"mrri>uqu$Eds*t~> +nG`dmqr+6LWUB`brr*$"rr2rErW`<"_kaKaq>L<oqu-Noqu.]7s8MlnrqSs9Jq&0'8bW)Zpq0t3 +KQ?kfp\Opfs8Drqs8Dp,qYp9dno&eh@7'\_s8Vcis7ZHks8N!.s8N#trr;rT`P]UCqt^-grr6X/ +s8:Ka`59I1`5BO2`5BO1_ns=._ns=._o'F1`59F2`5BL/`Po[2`5BO2`5BO2`5BO2`5BO2`5BO2 +`5BO2`5BO2`5BO2`5BO2`5BO2`5BO2`5BI,nGiO`qYgHol0eHIrr<#drr;rsrr<!-qZ$Nks6a02 +D/`49pA=df!ri,rqu7]7rVliqaB,('@/]lq>B>%:Mg];brVHQoqu-EhrVlg-r;6Hfs8W)tlG:*B +U:gErr;Zcqs8UdOqu7-)r;P!:St)OPh"UaFrUTu=~> +nc'0up[,\#>@XkO`Q#m5_p$HLd)\)b_KALLICRJ@`l5g<cH+#Hb08#NaMQ3@`Qm&d.sZZ!Jr)\E +d)F"o;5o4Tf$q[[cGn#F`VmgVaT'Br_p$?UgL>8:=>&+Fb0%94`Poj:rQ+u\rQ$/%`Q$-GaMl6A +a2Q6MaLT's]@G*E`Q$*GaO/\[`n8hoh"on%h>Q41h$;lphVHuEi7l]:%ahl=e&fJIb0A/>^rsa: +rlXfQs2nBdc-=JT`l5R0a33,[88;sT5(1r.ccX>Na2l9@`k]=+a3DiOaN;Z+8=br;hUU4B@WHjW +HsL14aiV`Fb08)P`P975cdTqQ_S<OA;D9XV@CX"pbK0\&h8oT<s2b,Xs2b5_$d?W/N)WG@=DbS4 +rVZZqr:^/@~> +nc&Ugrr3)cj4<YqrrW)nr6bNDrs\l+e*?;us8W#sr;HTirZ;+7s8Duns1qQ]M1pM</X?/.:8P-j +lLk)Ts7u]is7lTmrsSbR6uI0fDc,'[qu>mZ(B=@3qV]?2`7"P^s8;]eqY^6^d_*3#rk2.B]tV1o +]tV1o]tV1o]tV1o]tV1o]tM(m^V[e$]>)(p^;%Cs^;%Cs^;%Cs^;%Cs^;%Cs^;%Cs^;%Cs^;%Cs +^;%Cs^;%Cs^;%Cs^qJ\"r;R#ujmW3Ks8;cYrY52.qtg-T4)o1_75s]8o`"acrr)forZ(k7rr;us +s7uQjFH!/3Xn\eJMMd+FE+&D5r;HEhrs8W%r;Q`rrqQ3drri#]p&*)6rr_ulqu#.H!W;rqrrrE" +q=sa^rr3/alg!cmi;NZYrqlWkrV$8A~> +nc&mos8Mi'URK'rrVlcqdf'aTrr2WbYHkUmr;Z]pr;HWpqu.W9q>^Enq#A0,IY<6!L+APcqb3]` +9^29Js8Vopq>:3jrr2p)rR*uHEG]MhfD>LBs7uZms8N!-s8N#trr;rT`P]XGrqu`ns(D9.r8l\l +gu7,Hh;6uEh;6uEh;6uEh;6uEh;6uEh;6rCh;I8NhV?uFhV[2IhV[2IhV[2IhV[2IhV[2IhV[2I +hV[2IhV[2IhV[2IhV[2IhV[2IhVQoVrr;cirr;u]mem%_s8VKc)?'R6s8Dutr;,_>D/4/W2"(D; +s8N&trVc`ps8Dp;rVliqrr$knUh-V$VCdOUItVTCp%SLcq>^Hlr;Q]qs83B+rVlisnC,"V]U\Wj +s8)Tlh>RESr;QTn%K6.mZ)!q^TY'ahr;HWcs*t~> +nc'1"rV5?#=]'OW_oB^4_p$BJd`<*BaNM?*@8g3g]>V_3`lZED`lQ7#are^J^rOLAb1N=KG)1p+ +K,/ORd5.&c6d<iucca5O^rZGns2YboaN2KJe$_#EF`(\JYK4])r5J]Us2ZV2bfn5NaMu3:`luZJ +`Q6-@`QQ]N\\GYbe&fVNb08/NbL+;Pf$DmslIZ'e"kVG^g=Xs(fFHEMe]l1O`Q?<I\\cS1`W"$M +aB6U/bg"AQ`PBO4b0nKZ@Vg3K+jel\b/_TEa2c9@`PK=-aNi&Sahl0O=acc?QJ798H\?s)B2$q# +aMkp=bKS2O`P][=c-45I`kn?Z3$pUCWPR$(cH=6,`rF3?aSs<_aN"4us2G&[rQ5JdZYNH-8m.2- +n,<4b!rMimp]#a~> +n,ERfs8:^<jSo/_rr<#qq>A\?!WW)rrs6s<mJm4`s8;ijrZD+<rql`qq"SuFKS>;7BRf`DG,fkE +q>UEls8W#ss82Wk%fHA"s7o3!GBRsr_Yj3/kl)G!rVcTN`Pf[Ap\Xmaq"OXbrr2HSm-!m.o(2\I +rUL'\mI'Vpo)nONo(N%^#lFJ[n,E@er;>dX')DP'q419'F*:Pbo(i=^r;Q`qrr42>s8Mrqs8N#t +s7cBV9<+sgnOS:cLP^U^[J]t&r;QZls8W)trr3`0r:^-iq<R_Ii:[-Mr;ZWkrr2inrr2rUrr;lr +rr)j"r:p$]r;Q^"hs0e#g[P4B!<)or!W;rjs*t~> +n,EXhrRRaBXS;Ylrr)lFrXo2,s8N&dS[H<(rVQWprVlisqu.]9s8W#ss7lD4Bn1_eI:Rd!Quf-J +L&(cKr;Zfqs8W#qs8Dp-rVuQjpdJ_6EG\1_rVHQnqu?Nlr;Zcq%KHG,s8N&si5NUQf`1sKrs8W& +s8;osrVuo_rr)j!rqcNld/FOTrVucos82fZmem%_s8VWg!<;rqs8NT-s82S\8oSZg;-!2as8N#t +!<2ut,5hK@rVliqrr<#pr9R"QV+pDJIt*$%Hr.0Irr;rsrVQNkrr3'!rVc]p$N/Vi]=+Z_q"jsh +rVlfrrr(dSrr3*"rVlforseo$eXrA*US??<r;-?jo)F4~> +n,Emon#9f%?a[YgaMGd:bf\AT'?S;?aMt/H<bS8C`QcQIaMu3?aSs=)aN)<?_p$BFcWOJ%LQ6gc +B%D99RVHlncca>Ob/D?A_u7UTa:cY:_oogBfed2aG\f43dE'SR`r<sW`rF-Zbl>g1`l5p7`luZJ +`Q6-@`QQ]N\\GY`dE0JPbfn>Qa3`5gin<5GlJVX""5qtjj3ccoiSDVu`5p$?bdkU7`l7r"o#LmP +aNFM+>0+_(_T^?ZL-KNsF%ARAbg42HaN;NFb/_B=_o0^Bc-4;Q_p-7ZR$p=p0m%brLO;OZf$)=T +`Q-$Cbf7Q>`lcHGbK.N+I6/u40m:(KdF$.]b/hTA`lcNJilD8Hb0%`Drl"oXaSs?^a9obM=%>eX +?aK.nrVlg!rV66fp]#a~> +nGa$uqu?]]j5]k5s7lWoqY^9>rW3&srVluicL1N-s8VrrqXXUsr:EO4LP:J=4QK,9VG@!drUKje +rVlg/pPhslDg-5Dq>:$bs7ZKgq>]p_&-)V,qV]?2_pA)Qr;-3_r;Q^!r:p$]q=4@Pq9o-Bq=O@W +rVm0&qr[AGs8W#pn,=(%q>^Khs8W#mp+U!$EcZG1FSPk/s7-($s7cQgNdRmQEE%dHN.bncqtp?e +rr2p)r:fp^s8VK\qsDo4rs8K#r;ZfpqtpBls5O%Xs8Vusrr2p#rr;ugp\t0rk3D1&kNhsDs8M`l +J,~> +nc'1!rr;of\tPkDpAb$is8DutdJa^Rs8W&kd@dqjqYgHorr)lsqYpHnrr*K&8:Z;BJV?/E8>r:W +qY^<kq#C6j(&\(2rqD=DEG9H3FSc"6r;ZNkqYL6grqufqrX8c*rr;utrSYZ4`S(+f"9/8urr)le +rpg$9rr2p+rqu]mrr)$Ir;Q]qs760frr`)ss8)`p%/]`N?Z^.$EER>Xs7uZorVlfrqYh--qZ$DP +HDYe&;MKXSIUmBnr;HTorr2rtrr2iq%K",U\@&:.qYU3jr;HTmrrW,qrSmhVrVlg0rr)fms8W&t +s7cAnTpMOI\b?%%rVulgs*t~> +nc&sqs8VcEM,dB.\]Xoi!QN=1a:lb;bg+;>L.GBb[DU21ai;?>aN4A's2Z"r`Q#p=aN`$bH%q*. +IP'#/S<>\\d)jB(`r3srb/hK>a3N.W89f3!AmF!;ccaMGc,%3;aN4A)s2lS+`P]U5bfn/IaN2E@ +bL4JB^UUc%bfe8TbfduEaNVuVc-=S@d14^\f#ktN`l?*D]>W"7`W"$Oa:?5/`Q5sDbJVTJb089M +<;pqIED9T`cG7H=`lQ<DaSs0[aNFM+s2m=I`QcS@A"[dM6\0`GJm_p>d)X,C`Q$'Eb/M9;`l?*A +aih5e;_BR_8$0YOc-FJVbfIc@`QZTLilD8Hb0%`Drl#GebL"5Jahbc/<'EoPIbXPmrVlusq"js` +s*t~> +n,EUfr;ZHIk26.;s8;uor6YEJs82cpr8-E.rr3#os7$!urN&nLKnP)-:O]?aVXXW`nbs@)r;HHk +Jm32>FE;7GV>gDms7lWoqZ$E^rX]&-rVGHk`5C!tqtp<eqYgBm!ri,snc/Xgo)-r9"8qrhr;HX$ +rr)!JrVulrr:0b&s7u]pq"t*dp&4PL88rBjFAQ(_qYU<inbs0qrVlZk7B31PLOt54KgP5)qu-Hl +s82lrrr3?)qt^3js7>gUps/m=!ri/rrr3)uqtpBls5X+XrrW,qr;HWtr;--crr3/alLO9"q"Xjh +rq?AB~> +o)B=$rVuosps5S,Xml;hs82iqs3U`Qs8)ZnmCfL8h"C[DrVu`nqu79-s/f+IJ:E&q97*RSVXjcb +rqQNjrYPV3r;$AC=)2nrE,$btrr)lsq#CBks8)Zmr;Zcq$ig5*s8N&si5NUQf_YUPrr)fprr<#e +rpp*:rr2p+rr)fps8;'Ir;Q`qs760hrtP>0s7lKkqtL*_5=B:"FDa`OFo21:s8Drss8W&urVZX- +q>^Knr^<TT6%j];I"+?Hr;HWns8W)ts8W)rrsnkX_m?Y@li-b[s8)cmr;HWsr;6HPrW2rqrr2ut +rr)cp#l3>TS"?1EbkqA<s8DQhJ,~> +nc'.!s8Vu\W`W&/ZGXl*_TBgFa:le?ai)3AXDgd@NjH^EccX8IaN4A's2b5[!6+rW&^&IY6%"E@ +IWe8*Sm-fabf7a!`r3ssb/hZ@`5gPD:2bK%CKh7&g==Nq_T^-<aMc7#bT=pH`P]U5bfn/IaN2E@ +bL4JB^Ugu+c-4JWaiD<:`r='Z`j3YqbgXt\`Q#p:`lu'7cGmd$b4E\B`l5[5aMQ!D`l?HS-9,[U +HZ2D?<mf%1_SsO9b/hZD`lcNMbf\#Lb/_cJ`m6!*Tf@CIKS+b1e^Vd]_o'I5aNVfG_u@Um`llWG +W+nOB/iT98a3;iLbg"DT`PKI9c-#%e(X1%E`l?!:`lQ<H`lH*6TO:G_86VMGqY^?qrV60dp]#a~> +n,EUgr;ZfTjOO5/!ri5sdf0:E$2X]%rr<#te*$&rrrMojqu$3f&,-#pKntJ=Gu1?+<Vc[js7-() +s82irq3?:p??(+5BLTc0q#CBjs8Vlonbs$urVcTN`Pf^Fr;HWprr)*]s8MTedf0FKqtpBkrri?" +k3r99rYPP5q>L?no`+lg2/75VI;N5F<8.BOs82?c&cD\(r;Ea/Y_c/3N.Q@[nbrFarWE)qqu6Tp% +fH5%q>1$Kk5Xu%s8;opr;QlsqtpBls5X+XrrW,qr;HWsqY0jcrrqfNmdfMprr<#rnGe"~> +o)B7"rVlisr9:2TRbn#Cs82iDrXf,/r;Zcos8D;\YIX?'s82fms8N#ort5&+7tH>EKm-:eQW*b\ +q#C?mqu?Kk*<5m8s7hh'5?_oDG%O.YoCi4aqZ$Tks8N#rrr2iqrr*E-rr2rss8Clp_o1+'r;HWo +!rr9!qu-*bnGgo8rr3?)rVc`qr9*JFs8VTf)ZTg:qYpNppAb,j2/$uMG\C01:tP^Gs8;osrVcit +rr2lrrW)utrXf,-s8T3/WeO9%LO=5HnGN7ZrrE&srsSf"mD?3AYHduqs8;lr!W2fnrrW,qrSmeW +r;HWp"TJAtrr)ir$2jA-St2OHVsO<[rr`8urVlHhJ,~> +nc&Uerr3B%ctQHYS\`=d`6$'Ja:QM=b/VB;ai:DY;IHE9bf%NraSs3Y`W*phfe.H%LPC%PVN<pc +c+qTFaSX!Qa8sN%rld6BB/s16E,AZ0Vpru;bf%QD^W=RAc-4>M`P]U5bfn/IaN2E@bL4JB^Uh,2 +d*9k[`PfU1b5TTdc-488`X^)7bf7WA`l5sA]>i4;_u@gMa@!ta_nO(6bJ_iYL)X91F+8()E]:AP +aN;6:`lQ<DaMu<Gcd0hV`lQBKd_WoGMd3E98VN(OEC\F'a2Z*;`l?*Db/O=s)9'k;We`_\2*P<Z +^!=^@aN2WNb/V98b08#fa;<(Cb/VH?`lQ?EaiD?6[XD1M8l9HGm/?q`"o\K$qY:$`s*t~> +n,Ejnqu?]ch;7Q!rr<#tqpPKDr!rT's8Dcls7Fk,qu?ZlrqlWfrX]&#JR=1\LJX&5>fZ[>s7u3a +'`\13s8;Tja[B3PEcQLg;#L+grV6BlnbrmqrVcTN`PfdIrr2os!<2`m%fZM-s8N&ts8N&ts8N&t +nbiFd0`V.Prr;utrr;utrr;utrr;utrr;utrr;utrr;utrr;utrr;utrr;utrr;uqr;QZp"TJA^ +n,;VPs8Nf1pAb-lo07D8Ec-&AJ+<=6r;HEjnGX!ls8)Ef8X-5TI"%#dJGT6Cr;Hfrq>($hs8W!+ +p](9Pmd9Yts8W)ur;QZp"9/2prr2rXrr2p"qt^-grVlonrVlg#j6,n!h=CRF!VuW^s*t~> +o)J[f$ig5&_P*^:p%A=as3^iGrseo+s82Wls4!gIbl.A7qZ$NnqYq-"J6[_OKhdT,=i^=;s7lTm +qu?Kk'`\(/s82Hg`^*OBDJse\;#L(erV?Hms8E)urr2iqrr*B,rr2rss8Clp_o("$qu-KnrrE&s +rVud*rr;utrr;utrr;utrr;ucs"+0Lrr;utrr;utrr;utrr;utrr;utrr;utrr;utrr;utrr;ut +rr;utrr;urs8Dp$s8;'Ir;Zfdrr)itr:g3j%eDi*C2Ra*Dg^sFrqlZirr;rr!WW/ur>GV7s8N#t +p](6fr^;gE<-NVB@Xe1Prr<#tqu?Zps8NH"s8U-\\[.mrp\b!i"8_omrr2rtr8IVUr;HTo!rVrn +rr3T-q;83CStVarqY^?ms8Mrprq-5@~> +nc&UfrVm5iNa#b6[CXB!`l6BI&B`AB`PoX1cH1o:;09=__TV\prl4uW'#r,7@7u-"Lf9M>;Qn0Z +`kTU9qo8HQ5K_!dbfe8mZT(d"CM7N637uF"ahZ$=a3)WNbf[rE_o'L<bfIcEaN)9Cd`Au6]YE1I +c-=DL_SaC;c-4DXcX=i5`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s: +`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l5s:`l?*@`l?*@`Q$-8a3_iDaNDZsa?@P^`lZ$1 +bg4ng-=p\(D0U#:daZgja1od9`lQ<DaMu<GccsVP`lQBM`Q?$8g-1^q:j[VF=(Tn)`Q#p=rl,#^ +aN"4us2,Yd]V\L_-TaPm_TUHM`Po^<c-48H_oU!Za;3"Bb/hTBaND`Oa2bj%SnCqq;-04FoD\ao +qtg?mqtg9cs*t~> +n,E[lr;Q`rg#:W_rr3#srR1ZRr;6Kns8DutrVtg7mJd+crqlWhrXo20s8A-bM264RTp7q=s8)cq +nbrObrr<#t$i9GcEHc5@Eckr"qu6TspAb*]rX/](rVGHk`5^I0rqufkrXJf)r;QWnr;QWnr;QWn +meeU7r;QWnr;QWnr;QWnr;QWnr;QWnr;QWnr;QWnr;QWnr;QWnr;QWnr;QWgrWiDcmJHn^s8VWg +!WVuort+hs8o/KcFEDP3Fo24;s82icrXer%rquZU:KXTV:5*,2oDeddrW<#pqu6Trrqucq"S:L; +o[3X;"8Dclqu6Ttrqu]nrr;$Xrr3)tq>'serrDoprrr,Tm-*WarVlonq>C6mrq?AB~> +o)J[f$ig2'j/AiMf_54BrR(TSs8N&tqYU<mqYIk%[H78Zs8;j/s8N&ur0(6;L2g1bPWnmBqu?]d +rXno)rr;urqss;rG&)/=F_"eRrr3#ns8)`ns8N!Hs8N#trr;rT`P]UBqYU6hrVccrrr)fprr)fp +s8N&ts8N&ts8N&ts8MHd/H5\Ks8N&ts8N&ts8N&ts8N&ts8N&ts8N&ts8N&ts8N&ts8N&ts8N&t +s8Musrr2rt#Q3`Or;ZfrrUKjfs8)]o&,#ZhC2Rg-Ec>?,q>U<lqu6WnrWN9#rVc`ps8W)ur;Zd+ +rT-[OV2\0">_DPGrVuiqrVuiqrr3T)d^R!.Sal^Zs82irqu?Tlrr2rTrW2rqrVlrsqtpBm$iKk? +Tq@gLU[e-WrVlirrUg,?~> +nc&UfrVm5r^2@CaP./BO`5U0G'["bI`4Wt1d)EY<8m%Ik`66<GaN4>"r5elW&(&U?6%Ol7=/(j: +i7PoebONY<`6ZWNb0A>\h.(J>EG]Jh5LS$/ah>d6aND`Nb/hTA_oBpEaMl6Aa2Q6MaLT'u^Y7&Y +c-!o?`Q6BQbfnDZ:<LSt`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@ +`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@`lQ0@rPf;fb/hQAbe;'D`l#m?b4<UjbJ;'7aNVcT +10nU/F`hb,=OPaFc,IlG`r*n(`lQELb/VE>aNDZGaN2ZH6<0h>:P)VfdFQFZaN2NF`l?*@`lA#! +(rO"Z?S3lk2kn47e&]VJ]>M_6bf[rE`Q$lX(<jqDaMu6@b0/)N`OiO0=]%gqC!c/Arr3#qq#:9n +rV$8A~> +mJdOls8V06gueY:qZ"qA!W)forsAW%s8CO?kl:\Wqu$9hs8NW*p[C.iIRp0678p;`qu?WbrY,>2 +s8N&uqu;OSE-,o?B6?61rUg*h!;l<c$ig2(qV]?2`n(.frr)isrr2iqrW<-!rpp!WrmL]Grr<#q +rWiDcmJHn^s8VWg(]474r;Z`qpiLh$H[':G1@P8=q>^<jrUKjtqu??hpQSo\M6(0'>#ab]rVd'% +rr2imr;Zfrrr2p#m/-,*g]%6QpB(6fqYgHorW)lSrr2p"qtU!brVllmrr3/ejm20bn,E=grqQ<e +rrDujs*t~> +nG`sss8W&rqS&Ys[e]k"s3U`Ir;QZorr3?&qW+B_]D):%s8Moqq>Lp#p@1+fHq'd078U&Zqu?Ta +rY,2*s8Dutrr7mVDfTT8Aofp)qt'ge!W;uqrr)lrrXSu-rr;utrSYZ4_pnV^rr2lqrs&H$rr;rr +rpp*Zrm(QCrr<!'r9!DEs8W)snbs@%s8W&trVuV5GAMGGBQ5`ps7uKjqYpHjrW)utrr)lrrY5D- +s7_[Y:5GoXCfXHsq#CBnrr;urs8N#sr<rPg^;m[c\+B7ipA=ggrVZ`qrVtmV!W2fnrt55-qYpHn +rpR+_S=Q:kqY^0grr3'!r;H9fJ,~> +nc&UfrVm2sifRPICpq7&ajJ0Db0/#J_8aR=aMX`G?=p=Q`6-<HaSj-Sa:H>4aW,>N8Y2hC8!_NB +bJ`ql)9^1Ia2l?DfP<cfF`2M6B-,OM_og*?^rFOrbTk3K`P]^>bfIcEaN)9Cd`Au6]"?P=bg";K +`5]sIccF,Kbf[95&]V`+`lcNJ`Q$3<ajS2HaNDZra;;h9a2?*Df@aSOD1$\GD^!6Pa2cTIaN+2! ++i_UIbf7W>`Q63Bcb\#VGtgqdX'oa942JqV`QHELb/VF"`Z<.Ec-=))Il0)73FB&)bf7`F_7db+ +b0A2R`l#^6ilM/Bs2YhmaND`Nc,IT3W+o7*;-fIIpAP!js8)<dJ,~> +lMh.fgZ75ks7uZmd/F4Irr<#pqYpKun_W4!s82]kqu6Km%Iu)^C1aPo?#FWQs8DufrYPV2s8Dlq +r:K\OBQn?7J8AG?qZ$EerVuEe'EA%0qV]?2`7"GUqu6WprquZkrr)lerpg$9rr;uurr2iqrWiDc +mJHh\s8VWg(]XI4r;$Ba88iTmDfB`68,)iZrqcZprUKmequ?R$oK7h_8>DnFG$ak?rr<#trr;or +s8N#trrhWXr:S>5rs&B#qtKp^rr2p"rquZjir8rW"8hlgqu-O#qu?]fj6?!ph>[EWqYU*cr;Q]t +rql]hs*t~> +nGa!trVlfpr84HNV;V@Ps8ULG&cMY,s8Vums8Vc8XJsMCs8N#ps8DrqrVum,o.FKcB!$DdCiAhC +r;ZBf)ZTg:pAb'hs8Vih7;-gZDglD'IJEj=q>UEor;QZprr*E-rr2rss8Clp_o1+)s8W)srr<#s +r;X,&r;Qcrrr36$k3`*Hs8MuerYbb7rr)]no1!S9E,'90D+=?ts8Mlps8DrrrVuiqrVuos&c_k1 +rUW%#KL_f15]U0&rr<#srr)itrr)fn$LPU;]Xaa1qu?Wlqu6ctrVZZns5O"Yqu$Em&H2P)rVlfi +c_[2'T<.GTqtU*h!W;ogs*t~> +nc&Ufrr3B(p[Q"2<`YU*aNVcRa;N%<aNDT?`6HE6J6,Kj]#`+>b/hTA`Q$!?r5oVqeC2MM>AIiK +DbaYDcdBbQaS<pVa;`.?dDjJO_8O1*c7<:IFEW.C6se9l`4s11`lS/',KRmD_oBpEaMl6Aa2Q6M +aLT'q[aN@Ac-4/GaNW&V^V%>!`j<_u`l#^6b08#I`m2?@d`02Gb0':r)9p:B`50mH/RWL?EH?,2 +1!7>SaMuHIaiMR%`rF+$bf[i>_oBd=`5TmJf-kci7AHP=AjOMZ`Pp!FcHO<-`?*%Ae(*!`M*2k+ +5<u<abfRoPahtm,_oU*Kbf7K6`o>)>b5]Np`lQ<HcHXDGZ%ZF[9N,rNkPP8YrVc?fJ,~> +mf*:drVm2bj5]P,r;$<ks8Mp#rr<#trqu]Mrr<!%r:g3js82fq!oN&%rr3-!rr2inrVdQ3rqu]n +s8)cnBP9c5Tg+0^6fe7Hs7-()rVulqs8Vinq,:jIF)u8DG!Prus8Moqnbs7&rVcWOa2Z'Gp\=R^ +rr)ioqu$Bkrr3N.r;QWnr;QWnr;QWnr;Q]cs"aTOrqucnrqucnrqucnrqucnrqucnrqucnrqucn +rqucnrqucnrqucnrqucnrr2rtrr2iqrWiDcmJHh\s8VWg(]FC0s8Vrl3H&n]F*;_>;>L.gs8Vrq +qXOOsqYpHdZ;ZF/?%&Sm@8Qpurr2oss8N&r!<2lq)!^_iqUGQFqu-Qpp%\CXqu$Hns8Mrnqu#LR +rr3-!q>'pequ6iQipH6hnGW@eqYpBrrr<#tr;QHjJ,~> +nc/Uf%fQG,r:mb!U:L1!r;Z`prVuiqs8UpSrr2uprr36#rqQ<#Y.<fqrqufrrY5>1s8W)sq>U>* +AO3;i5_OYRi;EWGrYkh9qu?Qks8W#sqc%'FDJj32F?THms8W#ss8;lps8W)ts![mHrVufR`P][F +rr2rrr;?Nlrqu`ps8N#rrr)iprr)iprr)iprr)fcr%7mHrVlcprVlcprVlcprVlcprVlcprVlcp +rVlcprVlcprVlcprVlcprVlcpq>L?m#Q*ZNr;ZfrrUKk)rVu]ns7uLNCMe'/EcYehqu-Nos8)cl +rr2lrrVlcqrr2rt%/$i#J:LmOUi]s@rqu]os8N#ts8Doo$cg&o\Xr!ar;-?kqY^?qrr)fprVlls +rr;oqrVu?c!W;oprt58/rquflkc12FURT@$qt^3grVuor!<2ZkJ,~> +o)B=#qtpEnrVQBMJ6l,j]uJ+;b5KB]`n&3EbK.T?b0%]F^:%cS?(JaObfIfDrl#esb0%fHb08,R +da^us6Dp8-FE]R\e]c"Rb0'_)r6##[6H7*fcH*rD`4X491feL7FDbr&*n&*V`ko[6aND`LaMu3< +`luZH`Q$!@a3E&P\@T/ZeBlOje'?4ce(3!f_o9^AZd03-b0%uVe'ZC`d_NuQaMl6Co#M`lbL"/P +b/r-Q?YX_(EGel9ahu*>b/V]GaN4>"s2[LKaMYj5`lQ6=b0\P*6[*fXI&Cp[1=F.]`Q?<Jbf\#G +`Q$'Le&npm0-Dc%QG18S`QuE@`P01-aN_uRaMG^4aSs0ZaSs<^aSj-Yb4!Cbb/hTBb08/TbIa?N +:Jk+mQ/(p-rr3)trVuifs*t~> +n,EIdq>U?m!nuc%rr33#s8Voiqu6Tp"8r&nrr2rPrr2ips!u4Ok5YJXqZ$NoqYg?ks8Vlhr;Zfp +p0LsPV/:+%LO2tps8N&ms8MrrrVuWk!<;ur&-$9IA9)d;F*^"Js7u]pq!n@`r=&`'i5ijZg"+^# +cHsr9chu,ucd:"bcd:"bcd:"bcgK.4cd:"bcd:"bcd:"bcd:"bcd:"bcd:"bcd:"bcd:"bcd:"b +cd:"bcd:"bcd:&7dKIq?nGi:_s7$!ts7u]ns7q1DF_l/3Ff'$GrZ_C?s8W&trVuWlqr^A&LPURI +VQW0VoD/=`s8W)tr;?Nlr;HX'o'>r@kOANMo_eagr;?Hks83-$s82ipqZ$KYrr2p%r;6Ehp\4L_ +rrqrOm-<T`q>UNqr;Q<fJ,~> +o)AdjrVlfrs8EB'hP6[BhY.!Kr;HTos8;rsrr3#urSIPLs"=<FoqSq+p&Fscs8N&qrr;urrr<#t +rVucf>?H<MD/OrXGYRl2rVuWls8Durs82fqs8N#rrt>>2B3J_]Df]i?48]'Qs8Vops8)]rs8N#r +s8W$,s7tQl_8k3]e^2Ufcd)I7!77pqqp,5f"O5$UrV-<knGX"!q>^EnpO,eVAT)$uUMTo/oDTX- +qu?Zns8N&ps8D.KKS+r.4/&c@:A4Ycrr2rsrXJo,q>1-hs4b?$[]dmKrr3#trql`nrr<!)rr;or +rqcZlrr2lrn,<Cerr2iqs8*9*o>[PsS"HP<q>:-hrqufqrq?AB~> +o)Adgo_A@a'(`YK:0<prbg"ASaN2B?`l?*@rQ=!<r5S`Y:rg,K:gIM+`6,m:`Q,a3b07rH`lQEL +cHk'4;gY'FA9riK4k.cqbe_NC`6$'Cb08)Pb/hTBaN2B@`Poj>dmHK#AScF">8>T:aNhoC`l@kr ++3)CC`l5p:aii/^_6L5Q_nN[gZEpmAZa7'GYcb47Z*Ue8Z2_-;Z*(72V9%0,bfe-!a:cY>cGduK +da2;]ARB.Q@usF0`q.8.ai2EB`5op>_pR#V0n"Y+GrVb,0/(MlbfIZ<`lucTbJh?<e&Se92C9k4 +EjER$b0%fH`r<po`lQ<Hb/hQ@aNDB?`5L!FbfIc>_o9jDb4E[h`l#d>bf7WEbfRuMZZf/;9NZ)E +jS/ZR!rMimnc++~> +n,EIbp\t-k'BS05li7"\s8Voiq>UEorquZjrr2rVrr;oprWE)qrr)ir!mBj'rVn,>r;Z`ps8W)q +qu$BkrqfPeZ(F@7K85=SebT7@s8D`lqu$?]rX\r!F\5D5<a.3:p\t3grr;Nf&,lD)qWcqpj5T(W +hVI)HhQ#H5i;)@:kMc:;qu?WarX\r,rr<#ls7MXE9M&35TD.mT!rr/srr3Z.rr;Ze:OS+OJq\D^ +T8$5;q>C6ks8W'$r;6Elrr2p(j72d&iW&rPp\XO\#QOGrrVuoos69O_rs&K#rqlB_qu6U!jl5aq +h=LIB"9/5rrq-5@~> +o)AdjrVlfrs8EB(osU<^^\@^(qu-Kns8;rsrr:gRr;Qcrrr3B)rqb`M\'4UHr;HNlrrW2urr2rs +rW`>t:.h[]6N2QFKgX5\s7u]nq>^Bkqtg<gs8W'.qsnbs8QAPd/)g4#s7uZls8)`mrt#))rV5R0 +gY^uLiSNDJhqk?iqVDM8jPTb4qZ$Nonbs*ts8N&upAa`H5"A":H^j^,o)8^jq#13l'Dqe/pA.R3 +LOXi+FCUkr<;c[nrr2p!rr)iqrsAJpp?BE-]<&@3rVulrrVufprVm/qs8N&uqZ$QorVlotrUTpf +s8DrqrsSf*nF!HLSXlIro)/Ld!W;rps8N#ls*t~> +o)AdgoD&7`'):=>;GD>Fai_lNb/hTA`Q$!?rlX$;rl-b8b082P`4).-=ECab_SjF7aiDQHaMu6@ +bfn/Sgc\$(PrO)=Ll"1(bK@fMa2#^4`5TmubQ>r.aSj*m`Q#p=bg"=0/N-0j7guoMcd0YSc2GZ^ +aT'E^aT'9[`=U&2b0eVV]u%e.`l5g2_o'?j_u7RS_[4/p_n"+Db07oGo#UjR&'rD?ahlWRF=8t# +4(<Zbc18qPbeqKAaiVE@eBHQ(DM!IkHZ*YnH9'L"c,dc;_oU0Mb/V`F_Qeb]/M&bXX2;j"bf\#J +`l5s;aN2NFaMu3=c+_E=aNMZNbfI]<_8XXCb4E[n`l#d>bf7WAb0/2BX'A%a:h,pCmJHq`rVQHi +nc++~> +n,EIdq>U?m#lNf?gAh3Ns8MupfDbgJ#6+Z&rqu]jrVluPg#W&0ruM"4rqZToqu$Kor;$Bcrb.Ck +=EfLQLP1=<s7Z?drr<#t!<;Tg&,lP&5bNaXK^Sm?q#C9kq=4I_rri2nr;HHiqu?Vnr;$<srV$9k +rVucpnGWmqrql`op]'sap%J7VqsaUas8N!1r;Z]kEERsGKnY/07\-MUcMme>rr`9#p\Xsi"RkaI +nBCn3!r`#oo)8mls8)]cs8Mr[rr2p+rqlTjrVcceh<"7tg&:pOqYpHnrr2QiJ,~> +nc/Xgrr3E+rVcWEX.?*DrVHKlqu?Nl!<;$Ws8W&s(]XL6s82irZ`CUlq#1*hs8W#rrr<#rr;Q^- +o_i?\Uf_hpJq8B"1&ghAqYU<hrW3&ur;Zfr&,cJ#4e-tGJ*[.6p](0jq>L?irqZQtrqQ3_qYL0g +s8Jtqq>:Nqp&G'js8;osnbs$ss8;orp]'m\o(2VKqYfm^/cYeLs8;oqqJfVjJ:iK+Imfd);U>C@ +rVuosrr)irrVlispWL:a]q+`lrVuorrr)lprr2p'r;ZZno`+pgrquf`rr;osrr)j-p%QM&T:VdQ +lMLPZrVuosr;Zcqp]#a~> +o)AdgpA4^e%/B%kCf=K(`lZHIb/jP$s2b5_rl>)ZiQ)#Ar5]Spbfn>L^pmlQ?\b`'bK%]Oa2Ps9 +rQ#hqb/E.7KUkkVJ:ic9J0s0sb/hcPai;?Gr6#&\!QN4Y`Y$;7bgar[JS8V/aOS_\e&ohNrPnlY +rlY8^r5Sc["jbWEd+HtJd/VOnd/_Yoec45#eHjUDdEoqS_T'Uda:QM7`kom;_q!&ae'uspcHXN& +a90W,ai48!/CMqs<CV:^L4ju$8YDhDXjbM:a2Gg5b0%fAaiqVn:bXLc6*%`>c-=JTaN4>"r5]Pk +`Q#pC_8Nq+b/h`F`P][7bfn6!aT'BnaMl':cG[AI;bBbfDT(W-rVlrtqu-'bJ,~> +n,EIgr;QWo%e\K1kl:\^r;Zfrqt^'crr:gRs8;iq$NBtus8Vurs2=$_rr4);pA=[cs82fqs8;]l +rOZF<Q:lp^LPU\B5'Hu*s7Q3errDocrX]&.qY^$[q"a^bs8;oms8;Ed$2sf$s8DutrVHEhr2BMg +r<NB$s8N#tqZ$*b#QOW"rVHQnqu6TuqZ$Tis7-(*qu?]orVulpou].IK7\c2Lk:%PVO_#frql^& +rr)Zmo`+XNmI/*orrMrqnbrdnrVHQor;Q`\rWW6!s8W)rr;QrQj6,mkjo58^r;-?jrr<#toDa=~> +mJm4c%K65&o>dQ!\G,k!s8Muprs&K$rVlfrs5EtWrrE#qrX/N%s7-!XT"2Pro_ndoqu6TprqlTl +rt>7=>cEo[Kn"f.J:fk(rVZ]gq>UBoqtg9ns8N#rs8W'/s8Dcio(2PJpAb-hs7u]mrVuZlrr3<' +r;Q`orr;oorqueprr)for!<?$s8N&uqu?]erX]&*s8Mrrs82iqs7lTnp]'d_)u9O6qu6Wprq4Ai +Kn=i,KSP,+:o0XcpAFmgs8N#rrsSJug:k,2S+?:OrV6<irr;oqr;R$#qZ$Tnrr;urs6fk"s8Mro +rr<#ts7GoYUn=0F\G?+$p\t<os8McmJ,~> +o)AdiqYU6k%K6"hes0WDCqIX.b/h['`r=$Zb5TK^`o5#<b5TK^bV7/cagARX9k%Fh\BW1=ccO)@ +`Q63C`Pp!HRS0<46[a<;OH,5V?/!cW_o9a<aMQ$raof`)aN4>"&BN#@c-=_`dalsndEp(_`R"J% +s2b,\s2b2Z$-1'.c-F\ccH=3*aJm5[ao9K^bQuS=bfIfD_8jRda:HG0ahka1`lZf^g!A*o_9DGj +*QHCK_o0X=cd/X7H$t6tLP:/&9VIM6d*0YS`l#^n`Xfu7[]"!s-TWr[^!"[CcHQ:/rl4lWs2G\j +`llE@c-ODNb/hTA`Q$!Cbf]Lts2t>^%`Z?&dD3(k<)$+iNo'0srVuorr;QcqpA]X~> +mJd1ar;R$$fAtrks8Moprr`/mp\b!irqtaSs8;iq"TJ?!qtg9k$-;*&p](*aqZ$QkrtkV3:T:'T +:O\+QKR\H-I8fq8s8Vrqr;Z<d"8i,ur;Q^%qZ$Els8;ols7-*grVum"r;Q`nRK!NkrVcWns82id +rX/]"rr;fks8VomrVc`rqXOP%rVuiqs8Vuhr'uHnIuel0HTl4SNi6R#rqcX#rqlZon`fE4e,B:J +rr;odrWiB#s7lWor;Gp[#5nArs8W)trVm&jhWO1kjSo/^rqQ<arpKf:~> +m/I+crVl^%i2WWMgA:jLr;?Qmrr`5tr;Q]qhu<WRrr*E-qY1$apZeBMb2iU#rVc`q!WN&rrYYJ- +8u8.D:OS(QJU;ZsHrB\3s8VrqrVuogrWE&ts82fq#PnDqrr;orq#(0drr<#urr<!#r;Q`nRK!Ql +rVcWns8;oso)9!rq#CBkr;Zfmqu$Em!W;ugrW;urrVlg0rV$+XK7A</GD(9+Ch&C"A$u45rVuj/ +s8N&ts8Ufj]"aolqZ$Bes8;QhrVm3%rr;cns8;lrs6Tabrt58/r;Q`qr:fs%TVJ*NUZ).Mrr3*! +s8N#es*t~> +nc/XfrVm6%p@ddaF')G1^W-/lrlY5]rl3s=3QfRib0%fHbfnMX`6>cuU.n6sQ,1VhcHX8C`Q$!? +`Q$-T2O^'r7sK]AN/<(9BJe)Ye^MO]`5ostaT'EWa:H>:d*'qge'6IccHjSV_TMhss2b5_!mJg0 +rlG,Zs2G#["3/F*a8O)Va8a-i`5]g;aiV`KaiDB@`kod9o#MBc^W"@.^rsj?bKS5QaMbd3o>psS +0?qPWaN;WLgbF##IZSl4Im.1;KUu)/cH+)H`P]U4`l6$,C-!Xs1PNEacdC:cb599Zb5]Q_`XTo, +aNVrLcHF5H`l?*@rQ=]P!m8a2rl>Sh_84%(I8a$?=)5_@pAOacs8)fpp]#a~> +nc/Xgs8N,trqud#jkSnWs8Vuqrr`/kp&+dgrqtaSs8;fps8E)rs8Drs$1-g<li7"aqu?Wos8W#s +rtgujFKL(M6\U&AL5Ut>J4JW!s82Niqu$!`&-)D#s8)Wms7cQnq>^9hqsj[arrE#srs/Q%r;HTl +rViJg"onQ"s8W&drXSu(s8W&qpAb!fs8;fos7-(+s8DlqrVQWpP?EHnMLL,3Kg<iC6DUSGrVlZn% +fZM.jRVp!kPtS[s8W)unc&Rg"T/&qs7tpY"oS8qs8W)rrrq0<lfmL*rr2uqrqHKmmf.e~> +mf*mus8W&qrquQ.TVAgdrr;onrr)j!rVQNlrr:mT!WE#sr=Ao-q>^3hqtS=9ZI&IJs8)`p+8u3= +s8DhWQ#<RJL-pZGJV/c5H[\KEs8Mlgs8;iqs7?4#s7cBiqYU<mp](9hs7uZlrVuTjr;QcrrVm*$ +rVlfprr8qr!<;urs8<0%rVccrrr;Ke%0-/'s8Muks8)]orVc`qnbsC&r;Zcos8S9aI>!E(It`P@ +c/h3`UHJDOrr*B,rr<#rrVjaS^T,*HqYpBpqu?Zqp\t0ls8E3%q=sshq>UElrW)uhrr<!0rr)fp +rr)cfgS(:4T:NjqqYgEqrVuosrpp)>~> +n,ECdrr3B'q"jU@Qrm7&[)'c\aSj9]aSj-<a90T/bf]q+2p0@jaj\/G]siMk;K]%]e&onS`5BR8 +aMc,7HX<@hJNJ:-JW,ePG],1Lf[@pZb/2'9`lQ6Db4isfcb[QE`lH?M`QuiKcbm`>rPnlYqo\oZ +&B;i4aN2<>aiDE?`5T^6`Q"ps&B)H$_SX71`Q-*DaiV]I`Q%Ghs2khhb/_H<^<ssDbJ_63^r>od +1<Rka`lQ$7db8t=HAIQ1Jr#:J\'$RoQQshsaN2?<`Q$$9\Xu#9/hgkE]ZAUPcHF;KrQ+r[s2b5[% +)p<5eBlOidDNuC`le;)!Q`:Oa90T/bf]q+%)p&qSQATa<*b^Mo_nL`s7u`op]#a~> +o)Apnr;Q`rr;QWo#6*N>gAh3Prr3)tp\4[cs8MrTrr;oorrW2rqtpBqqV(02rr;urs8W,r)?0Z' +1lS5(pY%WYKS=]*MLC(Fq>U?mq>^KbrX\o+s8)Wmr;?Tpr;Z]js8VTf%K$)%qu$Hms8N#ts8N"j +rs/Q'rr<#ts8DKe#l=T$rV6Bls82fq"9/?#qsjY's8N#tp\FjW4aMd?GDM<0IRqWTO`!jXr;HQm +rVuo_"Rtm)s8Mus!;#^Z#P[V(nal\Ys69O^quH`orsn>Xkj%9ds8VuqqYBsarpKf:~> +mf*@fs8W&r$NK:iTV'p8s8;forr2utrqlcqrr:mT(&e.1rVlforVulnq#C$5W4q0ds8;ckrtkY2 +PV.]`8G(UrJqSf%Jr+o,7/-WWs8)Wmr;Q]qrVd9's8Vuos8Dors8;opqYU<brWN,srqu`os8W)u +s8W(krs/Q'rr<#ts8DKe&GlG,rV6Bls82iqs8N&urVu?c(]XC1s6`!nJ;89%Ndc@Gb4gs28!3ZH +rr2rtrr;m)s2r0m\Y8Tes8DorpAP$drr2p%rq5PmmdU,Prr`9!rVlfro)A[hrVcruqt@Otrga.b +g\^gCs8N#gs*t~> +n,ECdrr3]0q#(![aDY$VOhAZQaN2NJbf\)Lr5Ra;"3Sj3b5KE]at:f`bJV*4Z%5\UK=AqDb0.iC +_oBd:bAS)<PX"KZ078A/J;K&$CaRQYcI'JNrl+oWs2Y8aaN4A#rQ#MgaiqW=`l#^<bK.rJ_8jh! +`rF-Tb5]Nm`Pfa4_8F78bfn>VbfnA4bn/(<`5]j<aihlOcHOPXbfe-!a:ZS9e'6"OaNMuQc-FMR +`l,U2o>hlncHOAN^;J@@-Z4KqHART.JO?TjG#gGEdEBW1`Z<.Dah4QN.4%2FXLc6bbg=2K`l5s= +aND`Nb0%fHrl,Pmbf<H&c-OYW`Q$-Hc-42H`q%4NaoT`/rl>G_[Vo5@9iYr<nbi+\"9&)mrV->B~> +o)Apnr;Q`rr;QZp"o\JghrO&#rri>uq>:0irrW2tr8IYTr;-Epq>:*frrUU(l2CY^r;QZqr;QX0 +o6,5Oq;X_nJqJc3IYTp_ZMX[os7l*_&,cJ's8W#srVlZnq>^Kjr:0ass82cps8N#rrr)fqs8Doq +U&G#j"TAB!rVuBd&-)M)s8)cnqu6WmrVucns7-*gs8W':r;ZAu5_k#HMLgD6K4oB&pGqX>qYU3f +r;?Qnrri/ho'FX"rrrE%r;QNio)8mi?lgZ*r;$<Srr;iqrr)j,j6#mpjRW?Nrr2ckqY^?is8W)l +s*t~> +mf*mus8W&qrr;rq`2'*3q>L6irr2p#rr)cnrr2rVrr<#urr;rsrW<,trVlg'r;HJnYJ'5ps8Dip +)#aC.mW*6>pu4SmK7\c/I"jRYYPJ4js7uTmrVlcqrVd?*s8)cqrVulsqZ$Bks8)]ms7Q?ms82cn +s8W)urVuotr;chqr;cimr<3&tr;HZarX\i's8)cnqu-QkrVufps8VWg!WW/urtG(85D4N:Lk()2 +JnB0$oJYt1qu-Knrr*E$e&9#5T^_jYs8Durs8N#tp&5<sp08IZ[JK^us8N#r!<2uto)9=&rr<#t +rVcQKUn4?LTYg@!s8W)rrrW2urpp)>~> +n,ECdrr3]0qYgHkm$;*ZA@B=n`lQ<Hbf\#Jr5R^:s2k>_rPgh<c,\#Mb/qT:Zs6I7R^'lTc-+,G +`lQ9Ge';$!Non\CH@CX.MLU1*2iQ28_Tfj5`Poj:aN2NFrPnfW&&uc.b/V99_T'O<_o^*<`;R^U +aT'E^aSa0kbf.WE`l#^4b0.uQc-+;SWlkIca2S%u$H^K7c-=JXbfe>To#MEccH48W`m)THc-XVV +c,7KB`q.84b0J8Q`P]s?Q7IB9LPpV0I=>@#e'SoSgXFBh`l?*Baht#e3[QI>V8LKo]u.e1`5T^8 +aNDZLbf\*+a:ZbK6N[X^e&TGIaN`&Wbf.K>o#MTdaNVlNaND8_<(^"_@?fL@s8W&rqu-El"9&)m +rV->B~> +o)Apnr;Q`rr;QZp%/^))ddQ;ks8Vuqr;HKls8:jTs8;co#6+Puqu$Bkrr4:kkj8?LrVuQequ?Zo +p\OgN=nDKF?@m`^L4b28KO0f8s8;osqoSi2s2"[Ts82cps8;e9>DIfdL4=ko:haqIqYpBgrqQ0` +s8;lr"T7ZWpWid<rr2rt!rMfkqYh$*qY^Bis8VeU,9A-[JbT3/rWN8uqtU'frrqWSmd0/so)Agk +r;?Qgs*t~> +li-tarr)ls%.p<mT[EW8qZ$Tos8Dlps8V'Ws8W,u!<)orqu?Zp-MjRC\+][ss8;orrVQWpr;5SW +oD=;NK7SZ-J:`K+>`SLWr;ZfprVuiqrVu`no)JUdrr;`lrr8Gd!<(mUrVc-_!rr/rrr48CF'=6G +K7\K)Dbk"bq>(!cqu?Zns8W#sqYT$]]"FR&qu$Elq>^Bl&c__*s8)cqoSjk.+!lC0s8W)tr;cir +s7?4&s8Mrrs8Drmp9U]hS"Qb<r;HWls8W'!rVlBfJ,~> +n,ECdrVmQ.rVlijeSSMgNP<<Hb0%oQb/h[%`nnf:`rF$X`W4*Zb5]O@`P/][=]q?,a3i#Pa2l?K +bKA#@1""`k899'2N/NUOH:)JneB5hS^r=:4`lQ6DaMl-<`lQ7#b5]Q_`r<sO`r3sZb/jS%!m&O, +rlkAa!6G/ZTud/Ss3(Jfr65/_o#LgRrlkAas31Gd!R/^Ua90T2aiFD#0$dBaH[gg%GB[=S:fQ)l +c-4M`cGn#NaNVE'F>>!p.@[rlc,df8^;\+2`Q$!ArQH(r`llBKccpYE$kEbN`luHDc-OYW_nj@a +a;Dq9_TpBKbJh&(:e+)ZEkLc;s8VumqYU6hrr`5squ-9hJ,~> +nc/Xgs8N,trr)j$q>C9eh<3brrri2urVuosrr<!!rqtaS!rW&sr;Zfr!;ufm#5S#ns3C*,rr4&4 +rV?KhqtL-crr;ukMDS4OJVAW-J;@r+s7cNkqu=e;U&Vq--2ml@q>]nl:MbW9JRh#<[\\BDs8N&p +pA=a\qu?Qns69@RjPU"8rWN9#qtp<frX\r,rVuclps:<.-6+@=s82'[s8NK)pAb!hpZ1E+lJ;(& +rr`8tqu6?iJ,~> +li7"a!W2orrY!_JT!7n^s8Dunq>L<ls8N#ts5EtVs8;lkrs\i%S$U'1qu?Qnrr;cmrtYA/s8VhP +2,\LGK78E$KkN^NpAY'hr;Z`prVuZlo`+gfrVqHJec,UI&c_e-s7'MlC4Ce`@R!JmV0MP/rtGA2 +s8Moqp]'6d_nN4Zr;HWnrVl]oqu.3*s8DupqY/5V(EXD9>Q4O!rr2irrr2rhrX]&-s8W&tp\WI? +RA$1Ba8#Z5qu?]q!r`,toDa=~> +lMhOrq#16im&X,]D76pm`6ZQIb/h[&`o"l:`r3mV`W4*Xau.5S[nKY/XM)g#dE'MJcHFJJb0e\_ +B,*I;I"m9/JUUB4f>u+R_T'R6`l?*@b/hQ@`l?*@r6#&\oZ$jN#Kk--`Q#p=b59E_b5]PV`rF0] +bl5cbbl5cIaT'E\bl5cUa>D&abK@]=ahU%t?$^m@<@]bhK3QXM`llEEcH=,JbIY*15V"3<<jT`g +ccsPD]Z%n0`Q64$bS&(<bf@uMbfd'u%i5KZ3mbpgaSsEdaMYj6o>hcg_T0d?d_s+h=?]8M?^fpE +s8W&opA"L_r;ZcppA]X~> +mJm1brr36$q#CBSlIYk.s8MrrrrN,sh>[BQs8FVJqtp3bq"4Rcs4lo5s8W)tqZ$Hfr;6Eiq>^9] +?\qlP?"/P79hVYfr;Zfrs+10Kr\"!GrVZ]is8B_l2_e$diO*V"r;?HeqZ$E`s8;Wks8D'Fo]ap+ +s8Dims8Vulr:p7$s7cQnq>^1>)D!*T.ba[]rr<!!r:p9k"m=q0mHWEqrr`8tqu6?iJ,~> +lMhIqqYpNos7*"]SC$s/rr;uorVlirrW)uWrr)lqrqZR%rr;TUV6\MGrr<#trVmQ1rVZKkqt"6R +=@$+tK6L!]XShtms82fos7?6es7uZms82fqrVc_hs7uZhs7?6`s6KXsq#C<ks7lWn^GRi#8rMW8 +E;KG1q%`f,s8;osoDejU^q@7bX7cMjs8Mroqu?Qm%fc>(s7lWe-PIaF)(*u0rVclsrr2osoDTd1 +rVuors8)8pU7RpMVX=?^s8N&urr;uss8Murrq$/?~> +l2MCjqu?Zlen\GkNjHR@aiqoMaN4A#hoPf:qo/TTrl?M1bf\/>Ue4L-Y/JZ6bfI`GcH!iB`R;oN +3bgo8;-83`3\,p2bKe2Jrl4uZs2tA_s2G#Xs2b5_rlk>`rlFuVq8``Z`Q#p=b5KQac2Pofb/U3q +"3/F'b5B?\`r<sV_Z7^Ja8s<"rkncTrPn3F;9Ho-a2?'7e(138,p,'f`03[9eBl4M^WF@)bf[lJ +Y_,%d-ne)f]u/"=e'H"L`l?!:aND`Nb0%f?bKJ&^cO:+''FPAWai_]Ibg"AQ_o'Lca:lS3`Q#mF +`j9SY77LC$cL(B+s8)`g!;lZn!<)QiJ,~> +m/ILnr;Q`rrVQKls52ehrr3*!s8W)tr;ZctrqtRNrr;us#5nAoq=sj_rr3AZjSSuWrVZHjqY^?l +rtG5.rVQMoBnV()8A=rprr;lqr;D3GWW!M0rVHQor;QQeahkr$o)8F^pAFpmo_JFZrVm#VjR_]Z +rVuoq"onStq>UEirXSu+rr<#gBI#&D*@A,js60Fns8Mrprr;iVipu3hp&G$hrq-3lr;6Kfs*t~> +l2M=nrr2rto$X,(W94!TqYgHnrr;us!<;$Wr;Zcqq#:m's81QL[b(3Pqu?Zqr;Q]prtPD2s8;es +BS:t(8A4flrVucprVliorquffrql`krr)lnrr)fqrhBGkrq-6^rq$0Xr\=HOqZ$TorqZ<0_89II +rVQQgrr;uts8)cqr;Z`fs1u@a[\!9orVuosr;HZqrr2rtqu.**rVuosmq!Rc%i-=mqZ$Ekrr;Qg% +fcM+rquW=W1KrVT[3Q6rr<#t#Q=Z%s8N&trpp)>~> +nc/Uer;Qfoqu6U(iM9deA"pQM_op<IaSs0\aNDZaaSs0]`Q#m:rl+oWs2Z\4bgO\X\Va']J$[>@ +b.u-Ac-"2PbK%uVdaj=MChbFRT@1m.cH",H`Q%nus2k>_r5ScXrlY/_s2tA_qo8HQrPnlYrlY8b +rQPAeaJ-]QaSj-Y`W*jT_#_Hno>h*T_nj1,_u%FQ`pUo;c,moEaMc<Ie#B1@518-3bf7rXaNDZ: +^;%>%ag.F(-S.#*UqOOab0AD_b/VND`l?*Bbfn5NaMZ$Cd`Frd*=WDdOjh_Wb5]Zgb/hQ@`q%1d +a2Gm6ai'*>8Pr&eWp&sLs8DffpA"Ubs8Muhs*t~> +nc&Ugr;R3'rr<#qr;6Nog>UfOrr3<$s8;forr<#tr8IYTs82fprrN,srqc`mrVlfup!WI2ru:q7 +s8;fls8)Qkqu?TiqY'[`rq6$`s8VloqYu-GW;Zeprr3`.s8W&qqtU!ds82`op](!erVQTkqYgEs +hWXFma8Z,=rr<!%r;6<err;fn&,?2(qu<c?,TIgVE;KS4qs"+[rrDrqrsS#Okiq!\s8W)qr;QWo +s82lrrVlrur;QHjJ,~> +l2M7mqtpEnqt$\YTu-?qs7cHkg]%6Q"9/?"s8N#qs!RdFs8)WFTtoLVr;HWpr;6?jqYC0gs82Tg +o_AIdpA"Oas7lWks8Vrp!<;!Vr;W)^nc/4[o)J1X(Ae%1s7cQnr;6<`p\b'fqu?Nmq#10grVmE- +p\hnF_nDfAqY^<krVZZos8W)us8;j-s7u]pqu*N6*YfG<D#!u-qtpBms7-*grsS`(pu/?GSt_jX +qYL-i!ri/tm/MS~> +nGiIcrVm]1qu?]ddWAo"I':9)_T^0D`l?*@bfn5haSj*\aMu<@rP^>-aND`PcHX#3MFD*?[DB\o +`lQ?GccF/Oaj85UdEU%ke]Q+\cHaAP_TBg=r5o&]`q[XQaoT`/nAtOIrlG,^r61kW!6G)XrPeZO +!64WO"3/<t_u.LQ_uI[U`p^t^a32`K^W4RBcd:"be^r*icbmi=rl5\n^Uh+hYG4QF0/bbb[(aK" +b08*/bo+[F`l?*Bbf\#H^W4@9er'S@%hKOQdETeRrQ>/]s2OTM(!FY4`5/6Z8OlTZGiS>gqu?Wk +q"Xabrr`/pqYg'dJ,~> +nc/XgrVuoqrr3K-r;Zfjg$.2^s8W)nqu$Hn!ri,qiVrlWs8N&rs8Mus!<2uq!rMrmrr3)ieF*;7 +rsS]'rr;fos8;oms8N#t"8;Niq>UBsrr<#os+10KrW<-!qu6U/o`+pfs8Mcmq>^3hs7lWmrqQHk +rr3,bm-a#Zrr39$s8N&ur;$6fp\k^'q>^KN.N]i\,Z"74s7lWYrWN)tqu?]qlO!(Ah>70NrqlNh +rVm!!qtp<hrrE&ls*t~> +mf3:crr3H+s8N&uqTth3UsB#=rr2ourr(OLs8Vuqrr4,?qYU-gs89m0_;+tds82iqs7lWor;ZTm +rVlispA=mfrr3-#s8Vrqo)8Xhk5P5WQ2^OXnc&OfrVlZnmf"X5qZ$Tpo`+pfs8Mcmq>^<ks7u]n +s8)cps7uW4_n`aVq#(-fs8;clrr;`ls8NT*s8Lb")B9e=9DA8^q>]^Y%K-8's7O+%R@p+KfDPUF +s8Muos8N#js*t~> +n,NCarVm]5rVZ]jk,DTi?B)nCaN;NE`l?*Bc-4>ia9'B&aSj6^aN"4us2HM1bf\)H`lGZ48oB]s +\\u>-bg=GVbf7rKd*9kccGITH`QcZNaN2N?chtrbaSs?\a8j6YaT'Babf\)saSNpVaIUKNaSa$X +`VmgHaSs3Xa8j6Y`W*sGa@O@iaj%o@c-")Tbf.rJc,J#M^WO[DaN;<6W0pF?0/YS\[_Tc*bKS,K +`lu]Ob/hZHb08#L`QGp8cF"#b&/Z'9dE0SIccXE/aT'ERaT'BscG.<*H;m7%9l%$&q>:'hrVHBf +rVc`uqY9j_o`'F~> +nc/XgrVm*$qu$Hns8;lr"7PO2hu<WWo_JFarrW2tr8IYTs8W'#r;6Ekr;Qitr;Q]q#5S5ts2Ed^ +rr3N-r;HHkr;?Tjs8)cnr;Z]ors/K%s7cQhr;;-FWW!)$r;Zciqu6U)rV6Emp](-eqY'mfqYpEm +$1$sJmEkn5p](0irrN,sp&5?ms8Vr]DC6SH.ban$rrDu]rX/K#rVulWnFcM<lMgecrV?6arVlut +q>'pWs*t~> +n,N@cr;R-%qu?]j\>>e!meQh]s8CUL!<<#s,5qN?s8W)ts8Vokqtm(j_;b:jqu?]os8;iqqZ$El +qYL6jrr36$s8VloqYg?`rql`arW)urrqQMErql]orVc`qs6]dhs82ipp%n[f+T2$7s7ZKls8Vop +s8)cqr;QBhcc*N*U[n<Us8Mrpr;Q]qs8E#squ6Wq$i'c%q<2Q:)AFIKrVlfsrVlfrs6fjpqu?Tm +fr1X9StNgpp\Xslrr)fms8Drjs*t~> +n,ELeqYL0hrtbM+pA"@9GZRsa[(su/aN2B@aNDcPb2C>@b5KNbb/jM#s2lb5cI'VM_73EA@>qD/ +aN2NEdDj,J_9U'GaiDTCa2l<@bK[fB_8O@9rlbAbrlG)_"Nng,`l7nrs2alUrQ#5`aNDZHaMu6s +`;moLaS!^SbQ,fVa9'N.bl5ikbf\#J`l?+!b43PLbf.`F^VnI=b/:m6b.c*=a2c!9b/DNPg!m@! +7k,`<5,5QpbfnD]bf7E4_oU'Hb/h`Lbf[rE\]Vt7`DI9[$l$4taMQ!9aNDTD`lQBJb4E[hb082M +^6;et6psq4j7<6Jq>^Klqu-Hm"8_`bqt0o=~> +nc&Ugr;Qlur;?BirrDrqrs7NDjm`<Ip\XshrrW2tr8IYTs8W)tr;Zcps8N!)s7uTms8N&udbjKl +rs8;qrr)iks8)]nrsei)qZ$Kns8Dlqqu6WnJc;YJ#lFZ%q>^Hks8;lr'E%h/rVucor;$Bfs8Dut +mcX!,f`(mQrqH<grr<#t"98B"r;$=&s82`os7;a/.%^D8s82cnq>UEls8N#tq#1d'qu?]Ykj.p/ +hYmKSr;Q]krVlutqt^0Zs*t~> +n,N@crr2uprr3<$s8(iQTV]^)r;Q]srVY%A.f]MIs7lTns7cEdVlmi.p&Fgerr)los8Doqrr;ip +qu?Wps8Dorr;ZfpoD\Xen,<=er;QHjs8Jbmo)8Xfmf*._kl(kas8Mfns8;oprr4#9rr;utqu?]o +s7lWhqYSg]_RQB!o)Jahs7lKhrr)llrr<!,r;HZon<bFFRf!$_rVZZps8W'$rVlirs8)`ps8N!. +s7uZdZCmPSS>"j>s8Dusrr;usqu?WopA]X~> +n,ELeqYU6jrsnu(qYKpal*4W%AVn.<aSs3Za90T/bf\qds2G;bb08,Sbf\$*`rF+2bJMKJbe_3( +91WH_[EH>,aN)B=ai)6@bK\&P_TKd9a2c-?_oC$Bb0%rNb5TK]bR2M6aMu3=`Q#p=aS!^Sa9T`+ +b0%fH`l@nps2P)[U;dJ[b0%rNbf\/Pqof,dbf]Ou%*Hf<c-=SZc-4>QaN4>&n]3B%c,dcH`ko[0 +_T'U5`Q6$Ba3)K@ahlBPaJiMr*@EM%[`$8.bg+SZ`kT7(`lu^,b5]Zub/hQB^r4OLd=2Z;J(2W] +^;@hfaT'6`aNVoQb/jS%r5eoXs2Ynsd)a55AkYK]8mo:"rVuiks8W&rqu6cpq"XaYs*t~> +lMpn`q>UQVj6,J$rs&E$s8DusrTX:lr;Q`nrr)lns8Mlpr;ZfqqYgQoqtp<js8N/Cl0J?K&H2Y. +qYC!crVccqr;?Qnr;;-FU&P&k!<2uqrr2rts8E9$rr;rrs7?*crrr5`mcrWjrr3'!r;?Qoo)9-s +rr2iqs7+Zbp](9krVu]m"8r&nrql]qq>U:"s8N&ss8W)[nFQ,#rr30"q#CBnrr)lqrp]r<~> +m/I(bp\td#]q:ahg\:^IrVuoqrr2ldrr)lqrXo)-s82fos82irqu?Torr)iqq>^Bl$N'Ic[_Vb; +r;6HkrVlosr;?Qms6KXcs8N&[rql_Hrn[SRr;cinrr`5trVc`q'_VD(qu?]pq#B9l_n2q^qYgEm +s8W)s!<2utpAPU#rr2iqs7"Q_pAb0krr<#orr)isrr2iss8;iq&,uP&s7Y9CS=6+=g@kRHr;?Tp +rp0T7~> +n,NCcr;Z`o&c_L]OC2$rS\N1c_oKm=aN2ElaSj-Wa>h2\bJhWGbeh96^WOXFcHFAO`l5p:`lQ6D +bfn/Lbep>B93A1*`QH<CaihuSai;?Ac-=DN_o'Lha8jB\aSs?\a9'B&`oY;=`gb$Qb/h`Hb/jD$ +n]:OKlGs1Pc-48K`P_\k+N;LLdEfnRcc4)P_T0d8\Zos3-7(NZ[DU#*aND`Nb/jS%!m&O.qT8i[ +`r=$ec-aD-9?>E%`5Tg;qoBu(bg"AO_nj71b07oG`Pop@b/)97RScC@<Eu]cqZ$Nkqu-<irVcBg +J,~> +hu<f4oB>K=rrMrprr3#ur9=1arVlWms8;lr#5eH"rVHKkq>UEl!WN#rqu?ZuqpFHar;R'%q=jdd +rr<#trqufnJc;ABs8N<&r;?Hirr2lr!ri,srr3&ms7ZHl"Rka;m+MC<lM_=orr;ros8Vlis7cNi +s8W&orWE)qqu6Qo#QFZ"rqlWlrVca)f]W(slJ_dCqYU0iroX62~> +i;X;NSYVg[qtL-gs8W#rrr;NfrVuiq"o\Grs8W#rrs8Q&s8DfmrVlforr`9#s8Mus&H2=TV7FS? +s8;]ls8W)us8DlprVqHJUAb5lrVl]o)#jL3r;HZqq#CBjs82imrmf-$^9$#^rVu3_&-)Y/rVQWp +q>('brql`qrVHNls8N!!rVlfqrser+rVlifor+FTQCkGJr;Qcqk5Tr~> +ir9Mco>tWR=`(pg`l#g:`Q%AfrPnfW&]_u1ccsPYb/V6:`lZ<Fai_^&`rF-YaqW(E`j:Cf<GSYO +`l6-Gb/h`Ka2Z4"bQGr*`Q!JMUW=Y%ccsVP_nj1,`Q6<MccsPN`66?@d)3u9Ve84=/M2:O^W-5n +n&c0ab/q]CaiD37cb[]Aaiqg%a<A^Nbf7K6_8aXAbK.W>`Q?<I\$f[884-U4d.@/7r;6<gkPp&~> +hu=)ThX'+ms8Mfms8W)tr9F:]rsJT%r;?Ehqu?Zqrr2rorr2p"r;$-brr3H,s3KZjs8W)qs8W)t +r;?Qsqt^-dJc;8?rqufqr;Zcq%K6>'rqcZis8V?Jp!r7)s69Lcr;Zfqr;Q^#p](9krVlclrW<#p +r;HX$rquWls8N&ur;Q^*lJ1gkpYu&Ls7uWms8D*[J,~> +iVs5`qnnqrRa:m1s8Doqs760fs8DrsrsJT%r;?EhqZ$Norr)lnrW2rqrVuos%0,k\X0oqBrVuor +r;Q]qs82orrr)kJrh9>kr;ciprr`5trVlfrs8EQ/qu?Top\s3e]#CVcq>(!RrWN0!s8Dlprs&5t +s8;iprVHNns8;lorrE#rs8Vj#]UbgaUn-$6s8N#t!<)'[J,~> +ir9Vfp#;BI=&4jlb0.`@_o9dAb4<XP`r3siaiqZFaN2BDb0eJYb/qiO`qd[s`l6$Dc,RT9XeK*+ +C8n__c-"#B_o9[;aMl0CbfIeTaJ-a!b0A2TaMGX/`m)iP`kfL2aMPp4b0&2L[Wsq[1G`UF]#3dR% +`ZW7a2Z9HcG@WK`lH0@qT'Vuc-42F_8F:6aiqlGa2c9D_Rsk_:e"JjYNko^qZ$HTs*t~> +hZ"&MkO@+'s8;lrs8Dimr9=1jr;Z]ps82imH2%49s7?-arr2p%rqZ?ds8W&srsHs5mJm4_r;Zfr +r;?Qsqt^-eJc;>Ar;6QoqYpd!r;ZEhqtpBms6p*[jN[Z'l2D1hrVuoqr;69ds7u]pqu?Kks8;iq +"T8)mrVQTo&GuM-qV(E+lf@U9s8Mrrr;GaWJ,~> +i;X5_o=1BiUA"TdrVc`nrr;QgrVufp&,cJ*s8VurpNH6+s8V`hs82csrVQNks8N!1s8D>V\&nFF +rV?Hmrr2rqqu$Hls+10@rr)j"rVZTlrqud*qu?Tks8D0"]XkMMr:oIS%f6/(s8;flq"t*es8Vur +q#19nrVlcq&,H/'rr2rmgRk=8St!=]rr2ouqu,XVJ,~> +ir9Vhq!6Ld=^#(>bL"2C_8FLBb4<XP`r*n7`lc<Fcc=G_=3o1?b.>I0aNDZLb0%fF`P]^Ac,7<5 +bK$_X>&0tP`koa8^q[q2aMu6Bb(7X,a:?A:c-48J_o9dEccEr8^Ac(]\AuM/bd`R$.k*8G[(=<A +a:?//bf[rF`PTU=_op6Bana""bf\#G_o9X:aNMTDbf7WA_4".p9i+lDf(8_9qtL!dk5Tr~> +h>[o;mbmm?s8N#trquTil2D(ds8Vojs4JhIEqK))s8)`nrs\i&qu?]pqu?]ifAlf,rrN)trVm!! +r;6DCrh08hr;Zckrs\hurV6?js8VHUnF,-1s69L_s8DorrrE&trri&qqYC0erW2rrrr3T0qtU$c +q>^Kkr;ZfQl0\',h#@<Vr;HZorT4'0~> +iVsAdrVH#RUnQ!'s8W)urr2rgrr)lprX8Q%s7uKjf-DGUo(Dt]rr)orrr)usrVlZn#QFMEVmFtJ +r;Q`rrW)utquH`qs+10Brr)lsrqu]prr)j-rr;uss8)N+]!f,Qo_SUfq>U9krVlZnrVccr!<2ut +"SVllq>^9i!WW/urVZ[$q>L<erVlVtV>ctjUZ).NrVuosr8ms/~> +ir9Dbqt97!?Wg?`^X:(#_Z.j\b4<XP`r*n7_p?NF`R(at%o^]kbK@iDaNVlQbf\#G_o9X>beq9; +aN_PY;GD54]>_k5`P0++aN_rJ_h#n$aS<m[aMu-6rkB#Xa25g7Z^!s.,W\Jj]$8[GqT/QRrQ+lU +!6Y8\$H^K4cHjVJcc!`HouR*O(Wjk@c-*uA^q4>Z5t+Xe^$POhr;6<drT=-1~> +h>[oPhs'(qs8VurrVcTjlM_=oq>('jr8'%N,pAKKq>^9drr)lsr;Za%rV?Kjs6\J$qu6Trp\Xph +s8N&uJc;;@"oS8qr;Q]lrri?$r;?0brsA#^oAo!4s8;lel2C\]rr2uqrr32urVlispAape!W;rr +rt58-q=jd`s8Mrrs8(R8o(;/?rVllorr2utk5Tr~> +ir9Viqu6Hi^Rh6sgA1aIs8Duss760fs8Dp2s7uKjs8:_)*?H2]q"asds8N#rrVZZprVZ[1r;ZEd +`hp5so)Jadrr;rrrr)iqs8RZLT`4rj!<2rqr;QZp%f?;+r;=@B\ZWI8s8Dujq>U9krVl]o!<)os +!;lcq#5S5ss8Vfmq#:<nrquirrVm-$s82QjqphPBSd(h3p\Y!jr;Q]rrT=-1~> +iVsJeqt/s0>$"q#`5op7_9U9Io#UdLrQ$nC_o'XBaJoCS((#$-a3;?=aNVoRbfn/I`Q63EaMl': +`Ql96GsbAWVo-Qma2c'9aN_rJ_o@8KS]Dhqc-OYW`l5s;aMkp/`k]a5XHu1%-R_cb^;SF?bkfEX +`r4!U`X^&2bK7`Fc-!rEaN;ZAanWsW`r=*raMu3<b0//Q^rEsH=@ktR>G^<Kqtp3gr;c`Ws*t~> +huE`U$ifSWkN`*IqYg9jqW[tiqu?]or;ZVE,U4EZ\,H4%qYgTpq>:0jrrN&squ7)bjQ?@>s82Zj +qYU0frVqHJT`4uhs8MrrrVd6'rqufrp](9Xp$hM&r;Qcpl2D4krr<#srVucprr)`ns8Vlgrr)j7 +rquKdq#C?ns81j9lgaEBs8W)us8;ips8M0\J,~> +ir9ShrVccko"Cch[HRPgs8N&snc&LerVd?)s8W#ps8%3d*#^$.qtg6err2p%rVZZos8VuqrsS\t +\Z`Eko_e[fs8Drs"TJ>trr7QKU&P)ls8N#q!<)os!ri/trVm6#rqXFK\@/=*qYL3kqu6'a!<)os +s8<9(qu?Zoqu6Wqq"k!hs8DorrrE&trt##*rnX`KSY)Ffk5YD[s8;lr!<)'[J,~> +hu=2blHtAj;/rVTbK%NFaNF(prPnfW%`QZ8`lQEE=:c5X%$T,^rl>)^rQH/#`Q$0KaMu6=^;\%5 +_mj2P<e.Bf^;\CCbl,Ta`l5oJaJ$]T`ZN:GdF$:__nj@8ccsGJc-X&%Kf11q1cq89^rk'Lb0'\( +n&>mV`llQGa32NGaN)9@b0Im#a<8LA`lcNLb/VE;b085R`kn'M91V]PLX#Pfqtp6hs8VuYs*t~> +i;X;cqZ$Tpj6>A!s8Muls8D3]%fcJ*qZ$Njqe@<!,:)4Fq>LNpq=sjdqu76+s7cQni6pW[s8W)m +q"OR_rVllqJc;AB!rW&srVuoss82lorqlcqrVm#dnF?(krr3'!qYB@S&-)S)rVccrrVZZprVuil +s7cKnr;QZps8!,rq>UEohr=1qk2uR?rrrB$s8N#rjo9i~> +ir9ShrVQTorSF<>R+_66s8Duqnc&LerVd?-r;HKlrVH>#)]TnAh>7*Hrr2p3rr)fprr;ipq>^Bk +os:F(h"^pLrVca!rqlWms+10Crr<!%rr)fnrVlcqr;I3%s6mq@]"=R+qu?Wir;ZZnmf*dqqu-Kn +s8Dlps8Durq>^<jrVuor!W;oorsel(n$&FXSscD"pAb0krVllrjo9i~> +hZ"#Zl*k8(:QrN:b/MQDn]:[KrQ$q?`lH$Eai;b.'+bNT][P3Nb/hZHb08#I`mN2T`Poa0_Rd_+ +_l[<<?\tl!`R!,]b/M?@aMu5NaJ$]T`ZN:Ec-OYW`l6$Ccd0hXcG-W:2B<S`/Y'/ha2Q*Cb0'\( +n&>m\`5Td;aiqlHaN;KGa2?-ta</F@`QHHMbf7Q=aN2NB`3<oM8k;TfV<@mYqtp?ls8D'ZJ,~> +i;X>brr2rtrS?`!s8W)ms8N&XrWi9l+<_pYpA=[b"8quhq"k"#r;$?ls6%>[o)Jaep%%kUrrW,o +r.4j?rqucurquNdrqu]o#3tXIo$RL:rr<#t!<;lo&-)J*rV-?lrr;lqr;Zcqs60F`r;6EirrVue +pAY'qiU$%,kNMdB!ri,sjo9i~> +iVrrWqYpL%p!&nqV;V:Orr;lcrr)ljrX/Vt6lI!b-1^m1rr2rsrr)lor;cirrs/Dpae68koD/@b +#6+T!rVlcqJc;>Arr)iq!WW/urt>>0r;6Hh_n<UlVt9cbs8Doqs8DrprsJW&rqHHmrr;lqr;$B\ +rr)j"rqu]krVZ[&o@]n1R@p7ep\FgFs*t~> +hZ"#]p"Z0C;HTU0bf\&In]:[Kq8iQX)U[@t$4@1Oe^Mje`l5s=b0%`FcdBtV_8!h(rl#Pg_7G1i +<c+kOcdpRj_nX78bf\(ZaIpTSb5KC$b0J2QbK8#[d_MrC3#`\c0q#;]aN2ECai_cIaSj*hbJD<> +_90m@b/MQDaMu6?rPnlYs2soR(WOA3b0A8V`l6!<a2Gs+Qs*-L9jEnAo)A[hrSmj-~> +iW&rW%fcJ's81X8mGIsBqu?Wpir02XkU%As)IiI:rWN9!p\4U`rr`2rqu$Em#L)E,s8VH[qYgEq +rV6;Arh9>hrs&K#qtg-_q>C7!n+#u<c2[h=rVulr!<;lo!r;lmrr3<#rVl`ps8N&qqrn"\r;6Bi +rs\i(n,E@ei99h$lJ2=6rr`8urr2'[J,~> +iW&rW%KHG-rnOHDV69gmrVu`arr)ljrX/Vsj<5E_'OCA/rr)lrrr)lqr;ciqrt>8,q!b#ich7>3 +s8W)qr;Zfrs+10Crr2lrrr;uurr2p+rVuljs6%A8]=ag/qu6TtrVQQlrVlcq!rDrorr3<#rVl`p +s8N&rr;HZ`rqud-rVZNiqu?Wpq;eHDT9u+AjSf)8s*t~> +hZ*WO$LtfQ=]oIQ_9:0Bn]:[Kq8iQX1!e:i$O74G8(H)4`P]U5b0%fHbfn5L_84.4b/hQ@bfIAg +5ZW<:a2-*I_nX.6dE]mcaJ-cTarAF@`Q$'Hd*9MGb1+;.Fupum.kR-n_T0d=`lJ)$s2b/Y&&HH+ +b0J5Mai_]JbK.fC_u7UTaT'ERa;i4=`QHHMbfIc?ahPp,ULI(o78R^@pAP$krVQQQs*t~> +ir9)Zr;QWo"7tR7i;W`XrVuoWrWiK"Zm7+D,_l0prr3H)q"Xads8Mojq#:<jqu6Tsa6<?urrDur +rr`/nqYYpDUAk&i#6+MppA4^crVm#blg"#arr3*!qYU9js8)`prri2us8)Qirri/pq#CBXrWE)q +qu6Qo%f-/%s5W,1naYH2s82fnrVlrsqu5^WJ,~> +i;X;ds8N&up!T_0T$m<3q#Bm`rVuQi$30e*+!_aHK)GWHrr`9!r;HTos8Dusrr2utrr3/ul^593 +nGE7crW)tLrh9>irVulrrso&.s8Dlor92/7[(;n-qu-NprVl]prVlfnrri2us8)QirrW#nq"t*Y +rr)j1rquWis8DuqqR`>lR\HA!qu-Qmrr1mVJ,~> +hu=,`q>0gHZYroCMS%*KnAtRJq8iQX1!J(nOpMg2$Y@l4`PKC0b08)N`P]^:`l?6KdET\Mc-4&3 +Tgi.,XN8;ua2l9@d+$9jaJ-cUas"jG`Poj<bfe2M^VIglBe18G4?0:G^rFL=a2cEKbf\#JrPfAh +ai)EIaN)`ScdB_N_T^.#`rF-[b43RQ`W40\bSA4=ahZ!-[<5JK8l]8smem+aqtg3gir=N~> +ir9)Zr;$6i"6\V-l2:S@rWi>sr/DpH,)Z6rrVm?)q"aphqtTp\s8Voiq>UBq`p*9trs&H%rqlNh +r.4jArql]urqlQeqY^@%jmh[!ec5[Ks8Mojr;HZlrX\u,s7lWorql`iq#C9lrVYjXs82lrrVmB+ +s8VN?m.BT&kPtSYr;Q]q"9/2proO01~> +i;WiUrVca%qn&MpWo!OKrUKmcs7Q?tqt^)F*ZlDWr;QZp"9/8rr;HWsrr)iqs8W)srseM`S%[>E +s8Dlqs8MrrJc;ABrr)iqqu7$&s7bira1JdZo_JCa!<2urrr2lrs8EK-q#CBmqZ$9`s8;oqrVcc^ +rr<!3rr)`lrVQKlcD@2*R%:kbrr2rtrr1mVJ,~> +hu<`Tq#:*rl&K.N?(\mL`5_AhrPnZSrQ6h7ajb,6$jULqb/M35`QHELb/(g0`lcNOdF6F_aNVlG +^pTt$>_&lf^;J"1`R!&XJ]OS,s2k>]rl#YmaNMWC_nELTI3omR0Li%R`Q#p?aiaV-s2tA_rPfAe +aNMNIeBQ.``lHQLbf@[#`rF-[b3m@LaplG3^:V"2=]A6l>)qS:rr3&sq"s%MJ,~> +ir9)Zr;6Kn#Q+Ats3pE%h#793rr<!$o5?.joD&=arrN#mrqcusq"asiqtpEkrr3&Gm/$_]"T/,s +s8%<GTDnfh"TJ?!rr2lr%d<3HhU_`,r;ZfrrVH?frr;io&,cG,qZ$?jrqQNnr;ZWnrTX=]s8;lo +rrLd7rp0X?rVlomr;Q]tr;6BPs*t~> +huE`U$N9i$s5KZHU8RV]nG`Cdo`"mj#4ZLW\+'@qrVm'#rVcZmrr2rtrr2rtrVlg,qtg3JV8(CK +q>U?ks8W"JrgNicrt,2+rr2'!^VI"VqYU*grr)fps8W&rrr)j-r;Q`ms7cQlp](9js8)corVu9a +s8Dlp')h\+p@Y>[S!g%LmJ6b\r;Zcqi;\<~> +hu=2`qY'X^oYbTP<FN2M`Q%JirPnZSrlY8^(XUXS9a[94dE9GG_oBjDccj5>^W"IFci)*%bfIfJ +_SEjQ;-Ik7\A,boajA;TJ]OS,"Nng)`Q%nu)p-(7\[.uO2\?lZ9s21Hc,R`CajADU`lQ<DaSa$f +aNV`RajSMYf$V[c`llF$`rF-[b43RQb5TK]apc2([&dG28kWK3ddHu2rrW&lrVc`rrT=-1~> +ir9)ZrVlcq#5S/rmc!NfrVtjU#5%rpptu#IqYgQoqu6Tp!;uils8*'!s8W#pq>^9irrUd6li-nd +qZ$ToJc;8?s8W,u!rW&qrVm#lkOmTjrr3?%s8N&urqZBhrr;io&-)Y-s8DcnZhsRqrr2rrs69O] +rr`2rq"t'j#4CX@mI&X*rVm-$r;ZfrqtpBRs*t~> +hu=/brVlisr;":#SXIjus7-*es7Q?ts7H?ip>,TArVlfrrr*'#rqu`oqZ$Tos8NW+s8;oli2X?, +li7"]s8VtIrh'/is8DrsrtbS5s7kWu]>Ub^p%n^bs8W)srr<#tr;HWmrseu+s8;ZlZMF:lrVccp +r;Z0`rquirr;R?(o=UonS"ZA(rVlirrqucpqu6ZqkPp&~> +iVsJgs82ZirVuTQS6]#cL:>1Bo#UdLq8iQX1!%AKd*^1Je'ZF_`l5s=b08,S`PKC0bg4PXaN2TJ +`l5d<`Q#Z[8Q'N#]YD2&ccXC]aJ-a#b/hQ@`lQ<FaMG[$Rr:P5+W41T]ZJ+6`l?0FdETPC`lcBD +rPfAkb0//WbgV<nbg+PZdE0Q0`rF-[b4<Ulb08#L`l?*Db/qB%F&bq';dcisqYgHorqlTkrrN)q +k5Tr~> +iVroUrVm9)r;HZqhWt!mrVuoVrW`Dur;Q]os8)]rr:p*drr`8rq>:0krr)ruqY^?pdF@[brrDur +s+10Drr;orrY>J4rqu`os8W&algX-0s8W)qs8)Zmrr3*!qYL-drX\o+s8MupZS>Y`qZ$KlrVu-] +rVm<(q"4=Zs7+t0o'5Jlrr3#sqYpKsr;$0fj8XW~> +iVsGes8Mrqs8W)nq4aIZT&TV:rr)lirr<!%q>C6jr;Zcq!<<#ss8N3"qtg6hs8N#trt,20qZ$Qm +qqnBPbjbQ-qu$DDrh9>gs8W'5r;6Nii5WC@ZGZ)0qYpNos8MrnrVlfrrr2lr%f?;+rVZPt03J2K +s82cnr;Z0`"9&/rrr)j-r:n*tR@]hDXS);es82coqu6`ss8M3]J,~> +ir9Vhq"jsfs8W&kl.g/[<_K(#`q%4L`qd^Taqr.=c,IiLc-4PWaN2BBb08)Pb08#J`Q%nu'ZIu/ +`l?*E`6HBB]9Q8dCmq]F`Q*PNTZI/U+i_F;`QHHN`k%dW2]3\o?(/F>`Q5m7aNr8X`P&t)b/h[& +`Xg&4c-=P[L^#T`c.:(]aijY&s2b5_o#M]kc-42H`Q69I`4^_$8k;-JHeRc`s8VrjrVccqqr[p/~> +iVroWrVlorqu-NsjQGjZqZ$Kms8N0"r;?*a#QOSus8;iqqYL0nr;$0drVm#tq>C9mrr*'#rVuok +rVlrRg?AJ7#lac$rqu]kr;Q]q!<2uqJc<Lbrr;oqrVuoss8;oos8;lqrVm&ojm)-agAV$Sr;HTl +rr2p"rqZEgqYh!)rVHQlZR?qB=S_mprVZHis8W)trVZWns82lrrVm9'q"=I_s4Zr8md&O)rrW/r +q>UBqqt^-Ks*t~> +hu=2crVufos8MiITpV[Up\asgs8W)t!r`,tqu??g#QOW!s8;iqqYL3jrri?!qYU9kru(h7s8W)s +qu?]ls8M]Q['7C-r;HNmrr;usrVufprr7QK_>aH4q>LHorr2`n%K?>&s8(Hb^U^;Gq>0scrri?! +r;6Hls8N#qrso#'s8&rF*?nPYqu6Qlrr)llrr)lqrr;uurr2irrr)j*q"pSSTU_dNo_JLbs8Muo +rrE&[s*t~> +ir9Vhq>1$hs8;`ipuo,#92Js%_u@aU`rF-[b5KE[`qd^Tap?)2^rXd?a3DX&aSj6aaNDcPb5TE\ +a;;h5_o9^>b0S;Kb/Cl^=%m.e\%fc#b0'\(rlP;``l<SN]u^)nr5el[s2b5_*lc+6_og3E_kCWt +,9@q&YI2!^`l,g7aNr2S`4j"*rlG&X&'N):eC0B^!!"[tcd9kVaSj-YaT'E_aSX-Ua;<"?`l5s= +b/h?0;c-7[;..c7pAP$kq"F[d"9&,orT=-1~> +f)GmChr=.gqYpWqr;?Nns8)foir8uU!<2ut"oeGtrr<#prW<#pqu6TseDB]os8Vm"qYp?jp%eOb +rr2utrqc]nJc<Rdr;ZfrqYpj!qtp?hqYU-drVm#flgX2fr;ZWms8N0"r;?Bi&-)M+q6MFq*@!#G +rVlisr;-EkrrN,srVQQks8*?)rVuors8D]ls4?i:n*\p-s8W)ts8N#Ws*t~> +huE`UrVmW3q=qn&S#W^hrVZTjrr;uts8Dlorr2rWrr;uurr2j!rr<#trVZZpr;cirrtYM0p8=k# +f_kdIrVliqs8N&urVZTlr;V?I_u9r?r;6Ejrr2lqrquorrVlTl%fH2'beh0*VW[gRrVlirrr<#t +!WE#os8Dp-s8)ciY9G&)+"+YtrVuoqqu?]qrr)lrpAYa's8;cos8)WbV4sNMUn?B=rr)lsrnd[*~> +irB#Vs8O&:qu-Qppun8Y92o<2`l5p7`Q?'>b08)PaMu6WaS<pVa<8XOccX8Kb0%Q';FX]7X1lQr +bf[lGa3i>[b/M9<aN2MTaMQ""b0SE4bTG!K`l?0Fc-42Ibf[uH_SjR5Z_C#@+<rInZ+n,o`lS/! +$HUB4aMu3:_o9X8rQ#Jj`mrJ$%i5TT!0PXSccc1)s2b5_s31Mfs3(PeaN4A#'Ze;1`5fsCbJV0* +?:dCL=_4u*q"t'j!WDons8W&Zs*t~> +iVroWqu?]qrr3,aj6>_'rVm#us8DlnrVuop!;t1B"8quiq#:9qk1oG&rVuop"T8/mp&=pi"8quj +r.4jarq-3rr;6Bip\4R^rr2p#jmDQsf)G^7rX8c$pqS-q*@<&)o_e^e!<;oprVlotr;HNkr;ZWt +r;Z`qs8)`p#3Y7<pZgMpec1.~> +huE]Trr<#r'D2%,URS"1r;Zcrqu6Tprr)cmrr2rWrr<#irr;osrr)j%rV#fhVS:[Urr3#srr2ou +qu6Tn!<2rsJc<Ocp\b3lrVc`prrDuprsA])_na!jWp99UoD\Xerr*E-p\)9B()7o6T(;dVrVcTm +s8E0"r;HTnp&>R$s8Vrqrqa:-R\-.>[J'RNs*t~> +h>dNP!<)os%di,)>XhGP_8s[>_SsI7rlbDa`o"l;`rF-[b5BK_as"jKc-=>Lb082S\>WV"?[o,n +a3_`Caj/2TbfIc@`Q$'CJ]P^L!6Y;b"3Sj3b5TBraND`Nb0&#L`5fj7_Qo_&.3T]`OKlXna9'B# +`W!mVa:HJ7c^kLQ',Lapaj82SaijS$s2b5_!6kDd!mJg.rPfJk`l>j8b/V`J^N`sF4[iD2iV(n' +J,~> +gAh3P!<)os"5W&"iVriZpAOphrr2oss8::DrVlutqtpBlrt",.jRW?NpAb0jr;Zfpqu$Hn!r;Wh +Jc<Rd"T8)jqu$9is8N&r%/Kr"p](9ls7,UIkh,k6lM_=ms3`#>,pOUhp&G'irr)fkrr2otrqu]k +rXSl'q>:-jrr;ZMk3qKtime!Y~> +hZ!TTrVmE-qu$<QVP'Zch"UjGs82inrr<#Wrr)lirr)fprt,2+s7a=%^s`/\o)Jaequ6TorrW2u +rVlhJrkna5s82a1rr<#trr)cprVQWpp&E.H\$N@"oD\^Xrr)lsrX\r+cQ"5Q*#sY's8VuqrVc]p +r;Q`ps8Mfn')qq1r;Zcrp\E+.S>;^MVsXB\fDg@~> +hu<fWqtg3grtY=k^MR%N@[OgQ`QZ6Ab08)N`P]d>iQ)2B`Q#p=aSa3[a8jB]aT'E_bR_e1_m4G] +C3ukiZHC>5bK0\&s2b5[!m8a0J]PaM#K=Hm`Q63C`r<sW_\C)4cdC"d`5'X4UmXRu,VMcRZcC)T +aSj*jaND`TX8rnF'Fn]sf[7mdaiFA"r5eo\s31Mcs2b5['ue24aN2KB`59O1`fjIo8OQHldII(b +s*t~> +gAh0Mrr39#g#M#Ls8Vohrr3-#r;Q`rd/NtC!<2uq#QO`%s7jFmoD\airVca%rqlNhs8W#or.4jb +rWW5pq"ajequ?Qm!<)iq"Q].Kk1oq8l2D4ij!>lk*[6F4rqHHks8)]err2iqrql]trquZlrVm&[ +l1F/qhUDLT~> +iVruYs8N#t%fZM.rVlWfc_ID0XS)Jirr3#trr)lTrqufhrr)cqrr)j,q>^0GTYAbIp](*hrVl`n +s8W)ts+10erql`qrr;rsrr2rtr;liprVm/f]tD"]Z2aIrmJd(a&H;La+s%X?*/!e[pAb*kqYgBm +q>U<lqYpEm$i8VUS>;dLVr@IKrn%1#~> +hu<fUq"jsfrtYCshPFjl:gg]KaNMcKbfn5L_o'R<ilM/>!l`1!pW+H!aMYp:b08#L`lQ$@^77u+ +DP4)J`QufL_SaC9b/h['b(7XOa90Dq^;9ce)90b;`P]U5c-abYaht]kHorf,0M/[`c-=E%a;<(C +aMu3<`lcK9!sJl5$uO;;aO/2U`5hhrp;m9Rrl+oW'$/5Bc,IK:_5(a<9hJ5m[-7>afDg@~> +g]%EUr:g*frr3Gge*6&ls8Dror;Q]nr6G<?rs/Q$r;Zcop\"Oc!m'9brVllprVlutq=j[`s+10d +rr)`prqcQmrqcX$q"+1Nf^]">s8V<^&-#ue.N:!no`+jes8W)os7uZkquH`ls8W'.p&+jhs6AtB +l0%*\s8VuIs*t~> +iVroWq#CBn%Jfb3TV/(0qY^Blr;Q]os5<nSs8N#qs7uZortGD3s8Dlpr:QSa`;TE/s7lTnrr2lr +!WDqIrk\U0s8N#srt58/q>1*jrStr2[@kb=pAb*hnc&Re!<2rs&,uT6-RKTXJFW[:qu?]qq>C9k +rqcZmrr2j.rr;lqs7Z)gStVREWjqs)p\reEJ,~> +hu<fRpA"UbrtG>*leR_4;,E7d`mW&Qbf\#H`PpcVs2G,Z`lA#!r5ScX+Nh^?_8sjCaMl-Ac-k%W +X$'!\VR=Ie_oB[7`lQ<HbfYLX^W7J8_7mXu`QHNQbfI]>`Q$!@`k%UN1F+@rEO!+#b/s4q(s:+J +b/VE>`lupm$4QtKB@>GUbK\;S_p&)!s2Y8aaN4>"qSa,faND`XbJqE/[;Ar?6q_$Jiq2rqs*t~> +g]%EUqt^$arVmG[i:#J#s8Vlkrr;uqqu$Hndf07G$2j\trr<#orpT^_rrUd"g%kXMr:os[rr7QK +_uBW7!ri,prV6Qmr;?QkrrhNEo((B1rrVoes69Lnq>XG=.=_6mq>^KorVHQmqYgQoqtpBj!<2cn% +fZ:uqZ$T]lLF?1in+50eGk%~> +iVroWp\ta&r;6#aS"ut<pAb'jrr2iqiVrfUrVl]orVcfqrVuos&cD\+s8;KfW2I,iq>^9is8;lp +rrN)rJc<Oc"9&/qrqcZprr2p.rr;cnp=$dh[\)CFs8VuinG`Id!<2uts8EQ's&'maI/*R5s8W)s +qZ$Qns8N#ms8Drqr=8c(rr;W)TU2(=TW7V[rmh%!~> +hu<fRpA"Uarseo$mF6DX;-TL&bfS)Mrl4uZs2O'>s2G)Y`r3sY`r3jq`lQ<D_8F@<b/V?:a4Jkp +a02=18R@po^q7V.rl>5bc-42HJ]P^L+NhsQ`PK:'`QHTWdEKVJ_847*[$4B7*$?Y\Xieu/]uKWa +(s:+Jb/VE>aNVrc1B@bef@7sfccXAJc,KY$s2b5_!6G/Zs2FuTs2>YkaNDZMccsAEZ[,VC7SQp' +f^\ggs*t~> +iVroWqu7*&q=s[_rVuooio&nTrr39"rr<#tq>($idf07G"8V`fr;HWrq=ade"7<e_p\t0rq>^Bg +q>C3kJc<Rdr;R!!qt^$_q>:-grVm#Zlgj&_rr3,us8W)ul2Ckdq"RsJqYpL!rVQWnqZ$<drWW5s +qu$Bkqu6j!s8N&tqu-O%h"UC4lJhjDr;Q]Hs*t~> +i;WfVq>Uj%s7uTjfr1C4V<@CIs8W)trrN-!j8T#WrVl]os8N&s!<2rss8;rprVm<'p[ZY#^!lKN +rqHBjrr3#urIOsarWN2rq>1$ds8W)srsSN"lG^TUY+t:Qs8Dlqmf*7d&cVb/p@VF?q#C?nrVQWn +qu?His8N#ms8Dp.rVlcprVuomi0pI.S=Ze=rR:ds~> +hu<fTq"jmbrtP>'m'^V';-Tp+cHX>G`Q6<K`l5sXaT'6b`Q$!Ab/hTArkg#$aNDZF`lcNJ`l#^4 +c.11c]s">h9jVk1]Z8(:bg"DT`l#^6J]PaM+j/'UccsPM`Q$0Me'H1U_nN=VFZ(6[*%R8ZbKIuK +_8sXfa;E(Dbf\#H`lcQUcdFRYdb3'raiDQE_Tfjo`rF-Zaof`)`l7qps2>&ZaNFM+%*Qu<\X6&i +7S6U"\an5LJ,~> +iW&rWr;R9+qY9m`s8Vurn_rcqnGiLes8N9%q>($is3glMs8;Zdq>C3k!r)Nfr;Qi:hWXt="9/2n +r;?SGrkna5rrN,srqccprr2iq"o[KGp>Y04rrr;ts8Dinl2D4lrr;ojr;6KmrVlisr;6NjrWN/r +qu$Hls8W)sr;Za,s8Dusi:641n_s<Ds82`mf)L7~> +eGfjSo)$J)Tq/^jp&>!krr)lUrr<#qrqufqrW)oprri;ur;ZZnrt55-o^&-T`:Wd'rr2rsrVc`q +Jc<Oc"oS2kqY^?krrE&tr=f21s8Crm^W!Ijp%n^err2los8VEa&,lG)s82NeqYgElrr<#sr;?To +rqucurr<#trVuiq$ig#"iMWK9TUqe(r6kUq~> +hu<iXqtg3gqu7?,l/\1A<).>C]ZS..`luiV`l#gUaT'6\aNFM+!Q`7Z_^*4Bb08#Nbf\#H_o'I7 +aN_lJ_SE^Y5YYd][*$V=dETbO_84-BaMZ(BbgFneccX8H`QHHQccX5@Z(>ed+!;@dQatDcbf7K7 +`l@De'$AGCcI(+eb0S;Vb/_TFa2Gm;rPnlYrQ5Gf`l5j5`Poj<b5TTrb/qH9T3>,Z:/YQ#kkb>Z +rmq+"~> +ir9)Zr;?Hl"8r&nr;?QtjPoOlrVca#qZ$Kfs8DuWrWE2qs8;lr%fHA)rVufqrVcZkq"Xacr;Qls +qtpBkrs[B2k5YJ\qtg?ls8Vuqs8W'"s8MnHrlP->rVHNqqu?TlrrqrQo',&_rr2utrr3*"r;6E@ +rWN/rqu$Hmrs/Q%q=sjaqYgBm#2eS2o]b91rVuosf)L7~> +huE]Tq#:s*r;=-rS"dt#r;Zfms8W&trSd_es7lWkrr<#rs8DrsrVuiprqud!rVZTlrr2rtr>5D1 +oWG4&hu!<Mq>^?js82fqs8N#trqh9Gao3(OqY^<ks8W)ps7u]pr;$BG^;[UeZM"4s!WN&srr<#i +rr)lrrW)okrqQNkrqufqrr;uurr2p,rr<#tp%GM^S=Z%6aRmm[J,~> +h>[TSqYL*frtPG/qsiKu<_?;=]>;D)_pI#[ahc!Ua;)S9bL"bdb0%W=ahu3AbK\;Ub/hTArkfbq +`lcNMb.tZk>t\(LXi/W3d_s#?]uJ4;aN2NF`IZ+Qa<AdVeBGqO`lH*8bf8#Q^9*u*,pXKZ5bGa- +`l5s=b08)Po>h6X`Poj<bfn>Ubl,]`bQ,`Z`r4!Yb5]ZdaN"1t(!4P?cHOJTai:j!A5Plj8m7eC +pA4[9s*t~> +ir9,[r;?Qls8Drorrh9SkNMpDs8Viqqt^9NrY5;1p](3cqZ$Qpp%SL_s8Dijq>:0grrrE!q>'pc +rr3)fcg0oqrsSi+q#C9jrVZTms8RZLb5MYDrVZWns8W)trrE#rrsIcJkO$s^s8Vrnrr2p"r;6Bh +df0:E!<2rs#Q4Jtq=XOZr;Q`rk6gYIn*fQAs8)cqqpk^s~> +huE`Up\tm*rV5ZQX.#m6rVcWnr;Q`ls8V*X%K6>#rql?_s8N&lq#C6gs8W)srVZ[,rql]irP4u= +bjtf4qYU<fs8MusquZlts+10jrr;rsrr;p3rr<#nqtKsWahta&WPA<+rVuosrr)iq!<;ZirVuos +s8DusrVuiqq#C*f!r`,trVmT1s8W&sp\V@pU7[sPYjMDds8Voof)L7~> +h>[TUqY9pdrtYM/qZ$EWb%b<V<fXl0_og*HcbmlEilDSIcc4D_c-Oe]b.PC,_Yq^_bf\#H`l7qp +*6-.GdEf\F]t.uA??3-gai;9?]#DV.a2Z-?ai]1Ub/baMeBu=R`Pfa8`5TO-\ZLlb.2jT`=fK!N +`P]O0b0A8Yb4E[d`l#^6b08,TbfIc@_oBd?b/j@trQ$,(bg"ASaMu3<`lcZRb0.oF`k/g"=&)C` +A;Jb,p@e:Xec1.~> +ir9,[r;?Qars[`BlJqpErr;rls8N&WrX&N"qSlInq>UBkrr3/os8)Qer;HWqrqlWnqtpBpakcIb +rrW2trVc`urr)irJc<gk"8r#jqu6Wqrr;rqrrhENlf-%brrDoorrDurqZ-QBrr;lrrr)j.r:p0` +p](9ks8VWIjmM9kg\q-PrmUmt~> +huE]Trr2utr;RB.rVlTGUR@jThXgF?s8DusrSd_^r;6<.:uD!ErVZZp!qlTlrr;ur!<2ors8Mus +$iBkojdW?jn+lhYrVQTsrr)irJc<gkrr3-#s8W&srVmW/roCZ*]!J!hp\b'grr;uss8W)us7?6g +rrE&tr;cios8N#os7Q?mrVlfprt#,/s8)Te`hAlpR@'T-q#:9m!rVrpfDg@~> +h#@HQq"k!i'`7\%s8VuYY[gI)>ai7<cHO>Qb0&\a'ZS2:SLqS+f$DF\bfIHAaNVlNb/jM#(!+PA +bg"AR_nj*oSOH=eR'F<C`Q#ssaTKW)aNK.UaiGUHa2Q0Eb/hW@^;7(OGVUWh-T.+#aj%Z<^VRn1 +bg4PVo>h'S_84.6rlkbl`PK=(_oBd?aSNpRa<8XLc-=JR`l5s=bL"JUcH*c7]7NpM91Ms"e+EG/ +o_/76s*t~> +ir9,[r;?Qdrt#&-s75.4jludEs8Durs8:jTs8NM^-79qnrqQHlo)A[hrqlZo"oeDoq"t!grWE)t +s7Q?j"6.bqnbrIhrVulrrrN,tJc<djs83W,r;Q`pqu-Hks8;TSp%%#,s8W&trr)lsrWE)qqu"nA +s82lrrVm#uq=j[^rVm<!hrj1lleqX>s8Drpe,Op~> +huE]Ts8W)trVuos&,Z@naeY])Yh]*Rrr;utqr.PSrs@@',95J8pAFs^rr3*"s8W)tquH`ps8Dp, +s8N&js8;][ZCo"as7lNkrrE&trrN,tJc<djqu7<-rr;urqWleJ^:CDao_ItUqYp9ioD\^gs8E)u +rr2fps8Miop&5$krr2fp%K65#bbq5*Una^0q>1$grrW/qrn%1#~> +h#@ZYqYU<mrVH<crr3N&e!jiL<GA)B`Pom:ccaJja:HD<YQ+k.^td8]ah#I8aiX>!!6Y;bs2t>^ +'YMW/^SY:"?%',g^W4I<aN;TIaN&kQaiGUE`59U>cH4,H^U9eg?8aAb/Q\pjaP+eU_84%.`lQ<F +o#MB^_o'L:bg"AQ`PK=(_o9^<q8W<Qs2tAd"j4p+`Q64$bS&+>_nN[=>uF*d=)G28rqH-Yp=0+m~> +iW&oVo`"pjrr3B&g>CoRs8VurrV6EOrWrP_/gDJ_0\64%rrrE!r;QWnrVm'!q=jXZqu-Nsqu?]j +rVlunb2VL]s8W)uqZ?`rs+10irW`E%s8;`hqu-NumGmQjdd[58"oA9!qt^0hrrW)nr6kTEquH`p +rrr>tq#CBmrr3/Zk2tjgf)>UNrq?9heGk%~> +hZ*KPqu76,s8W&lcCUK!]Cl'os82QjiVj/`i%,rh*@oS7rVlisr!*0#s8Dlmr;6Nnr>,D0s8Vil +s7Z*0S@6<6r;QNjqtp?ls+10jrr)j1rr;uss8Vure\]/!S'1I(qY]pZrVlrurVlfro)A[hr;QQm +s8N&um/Ht`(&mk%r90oLTqe0Ff_>%;s8;osqY^?Es*t~> +iVroVq>UTrqtg0drr3N-o%]jF<EjdY^:2,!a48>la:HM#"p+r8(qJ>Lc-ODI`lS/!rQ,#]rlc8& +aMu6=bgF>NbIt0-5#YjfZbsZ#`Pom>aaqOSa;Dn2^WF^A`lH*>WJa%_,UYNsZH159`5g.$`rF$X +_Z7^IaT'9[aT'BaaMu3u_Ze$!aN2B@oZ/,sbfn/J`Pop@bfnGT]=tnO>#S?r92r@cpAb$\pA4d= +s*t~> +eGoOI$2aZ!s8Ua;hqn#(rrW&qr8IVcpKT0i,:"V`rV?KirVufpr;Qruq=j[[r;?QurqucorVQTo +"3]-Mo)8Rkrqu`ps+10krr2p!rqZHirrr>WhW*&PrVllprr3)rqt^0hrrN&pdf'@HqtpBkrrW,q +q>C6skNqKsjP\hlrr`2rr;P4GJ,~> +hZ*WTs8Dusp\t^%q5C?aW6G,<qu?Tos5Eqkp/r^[*?HBKqtU3grr;rsrr)cmrVQTprr2j3s8Mrq +s8Vopo'3!O`SC:fs8W)rrVunKrlG'@rVulqrr3c5o\dEo^T>9CpAam[qu?Zjs8W)sr;HWpmf*(_ +r;Q`ro`"ghrVlis&,lP*q>]`hUR@dLTW.bZqY^BnrRV"!~> +irB#VqZ$Ql!<)iq%fZ(UH>ZbmL:=t4a32lQj2`1^bfVgQ#n[^YYgph;_Ssd<`l5s;aNDZLb0%g' +`YQhAb08,TaN(EN6qM'IY.DToaMu9BaaqOTa<AO9^WO^?`kf!RFYXpZ*EoDRc,dlJdE9>Ib08)P +`kfL2o#UgQ!6G#Vr5eoXo>psS!65#W(WOVAbK\#?^SG^G7o3/fFQDuis8DilrRCjt~> +f)PdLrqm*"p\Xsis6Sb'h#.0Qp&*hK&-)J%IOZ?\,UTeoqu?]jrql]ur;6Bhrqud$rr;orq=t!d +rr3)YbM_mgrri?!s8W%KrlY6>rrW,prVlg#kk+N(de<\?"SVlqq#:9m!<2uq!<2ute,BIIqtpBk +rr`8ur;HWp#4'e,puUN'rVm)mp\b!grqb4GJ,~> +h>dHPq#:m's8;QU\"f[qg%b:@s8;oVrX]&(pN\#")'1!)qtpEnq#C6i!<2ors8N&s(]++-s82`o +qu-Qg_5"EXq=t!irqufrrIOsirW2lorVmQ*k/"jGVl&&As8Vins7lTns8N#qrUBgdrVulqs8)]p +s760errN-!rr*]2qYU3V_jd6jQ_M4`pAP$crVulrs81CIJ,~> +irB&Ws8)fpr;Zfo!<)lr&H2M+s6J!`?rpKn\%Bl3ai`Yb&'E5BemfO,%hK&*c,\#M^])5!`Q$!A +c-4>L_8!h*b08#PbL4PTcGIK:X`$j5@%OdJbK.]FaiAtRb/baG^r+78be]lp2Cp@*4+FKH_Rn"< +`5os:`QHTYe'5kJ`q.7Yb0A8VaMl'7`Q64$bQ>r.`r4!Sb596[`W!ah`lcNJa2YopI83@*6s>St +kP4rGq9f4m~> +fDkjLqtpHnrr3G]hW3Mgs8Vllr;Q`rrr2g!rr<#tr;?!^%K-8$JgDWb+Y1"urVu]ks8W)ur;Zck +rrMlnrqlfnq#:9qbhh7Rrr3*"s8W&qrW)lqrW)ukrr;nIrqucos6BU\rrr8`n*Sd%rr36%r;6?d +s7uZnrr`2rqu6Tpe,BIIqtpBlrrW2tqu-O"map^nkj[@"rr39#r;QTkrqlTlfDg@~> +h>[KSrr)Qj%K65$k,>#NV9er4qZ$Torr2rrrr<#drXSi)oR.f%)]U95qYgHjs8Muorqufrr<)rp +s7cHk%f-+tgnD'djn/TOr;Zfqr;H]rqu6Qoqu6WqJc>ZJs8W&s!<;Whrr;rr%f?;+rr2]M`4i[R +`Td-prr36%r;Z]ps8N#rrVuforr)lmrr;rsrr)lrrW)obrr)lqrY>J4s8;f_^RqEsPc(;)qtpBi +s8W#oe,Op~> +iVs#Yqtg9hs8VuorrE#srtkY&_fK!^=GON*aO//O`l?*@b0%fFaN4A'nAl-ac.L]a'+kTV$&csJ +bJD=!`Y$A;c-=>K^V7J#b08&Ncc+2SrlYee_6Stf9j3da]=u,%b/aG$rQ>,\rPjE0p;m*MrlG)] +prNHSs2ZM/aMGd3]="2E3$TIg@\UQQ`59F1`R2T@_SaIBe^`!e`Q63CaSj-YaSj6laNDcRbfIc@ +`Pop@bg"ASrQ+oZ"3AX+b5B?\`r3mVa:l\<aMb9-;H$(L>%k;1q"sd`s8LIHJ,~> +eGoRJ!WW/urtGA2rVbF6kiVpFq>L*ds8Vrlr;6Kn"TJ;qrr;Ke%fQ/%nqJJ8)(@$1r;Q`prr;cm +!rr9!rVm*$r;6<cq"jsh"6%#Wn,34crW`E%r;6BhqYpKprr2iqrr2p#rquZjr.4hIrqHHmrW)lp +rqu[!rr<#ss8Vror;Qo^kj[NRqu6]rr;6I0s8N#qr;Q`rrVccrr;6Njrr;fnqu6Wmnc&RdrVlTl +$3'l&rql`qr:p*drs%WNmHNikq#:9nr;?Qsr;$-efDg@~> +g]%9Qq#;'+rr)`ns7GBHUn+@=rV6EkrVulorr<#t"o\H#rr2lcrXJi"s6kO_*>KkIp\Xsiqu6Wo +s8Moq!<2ur!<2rss8<9%rVl9+Tteb9p\t0mrVca#rr;uqrVc`ms8Drqs+:7Ms8W&us7QBdrri?! +s8W#rrt###k.J:?ZD6=WpAP!gs8W)trr3#us8DrsrVufqs8W$(s82fqq>L3is82corVu]ms8Vck +*rZ*<s8D`ks8W&os7uNGUn40JUo)E3qu-Ekrr)fpe,Op~> +i;`iUqu?]pr;Zfqs82ir)=,:W=\;VY^qe=;`5KR1aj82N`Q$'FccjQ$a<8UGgX'R@#65#3cHFAP +`Q#p=b08,Tbf[rC_8F10`lQ6uapc>/_S<a_HqRXPO/B_l`rO-Ya:688bf\/PaMu3:`Poj:J]R`0 +rl,Dd_o'=,_o9X:b08,SaSs3Xa<\dH`P]d?b/qW8Z(#ek+!`6hMSHpJa25j;b0%fF`P][7b0A31 +bR`"CccO#;ahc'Ea3D`MdDc+-!6G,Ys2b2^rlG,^#L(?5aN2BB`r3spb/hTE`P]jCb/;$7_n_O< +84#XACT?b"q>^Kl!<(OLJ,~> +c2SLTq>C9lj6Z*is8V`ks8Dutr:0U^rr3&tqu#s_rr3E*r:cp1/L@e(rVuoro)AUf#QFYuqt^6i +rVlg"r:8(jir&fYrVQNkrr2lr!<2rprVlcnJc>]Is8Mlps8N#qs8N)urqufq#6"T$rVcThrVm6$ +iqi#nhZ*WNr;HWpo)8^jrq??k#lal%qqe+Dqt0CWs8;ipq#:EpqtpBm%Jff!s82irg?\S&mFM47 +rrN,sr;Qluq=ss@s*t~> +df1![r;HQkrr<#me"`P/W:Ku\s8Vuqrs/B"s8Muqrr;Hdrr3K+qXg@$.3Ytpr;Zfrs8W)ts8Drr +r;Qp!rVc`pqu73)qYg<Xg7kmcjmr-Fs8N#ps8W&trqcWprr)kJrql`frr2rtrYPM4rVZZnrVuim +qUMjf[\p_4s7Q6cs8DiorVufp"9&8upAFppqtf*Ap\OOArZ;%;s8W)us7uQls7QBNTqeEQVk)0/ +p\Fggrr2lprmUmt~> +dJs7F!W)Wkru(+$APZ!(X2VftahYj>bJqcG`Poj@c-=JTo#M`kb0nSad=DE1"HM'Yc,mrE`lQ<H +c-=JTaN".ss2P)[rQ6,'a2>^0^T`e`7TYG>Y//#o`Q$$Bbg+PYb/hZDrPefVs2b2^J]Ir7`l?!r +_Z[ruaND[)bl#Q]ar&.=`5BR4`ko$SP[Gmo+s0FN^VIt6aMl7"b5]O"`l5p:aN2NHbg"Y^^rF=0 +`Q?<K[<g-B_!oGEbQ>r.aSX!Wa;2q>`PfjDcc<uJago<`>#@mV;HTdUp\FgkrVQKjfDg@~> +c2RhCrr2p.p#kQ!i;`iSr;-<ir:p3fr;Zfo!;uBd%f65)r;Z>r,II@Is8;osnc&Of!WN#rqZ?]p +rql^)f[8aEs8W&pqu?]pq>:$g!ri,prqQZnrr<"MrW`;tq>:'er;?Qor;ZWor;Q`qrr2p$qu-Qp +qu$Hn%HQpMjkT\3s7Q0eq"t!Zrr;j)s7ZEkq>:$+,pT\ks8V9]s8W&s"9&/rrr2otrr2p%gu%,\ +mb-t*rrW#nrqufrqZ-WIs*t~> +dJs7G&c_k/rr;rhaJPZ(XlKHVr;6BhrrE&tr;cirs76-us82ipqu?,k+L1b@s8;iqq#:9mqu6Km% +K62%rr2ffZD=tMo)8OcrrrDuqu?ZprVZ`qqu?ZoK)YWHs8N#r!<2rsrr)iqs8<$!p\Ogf&,bV)^ +:gYLf(&e8rr;ors82fos82fqq[NT"s8VokpV.gmY5&%sli-k_qu6Wq'`J%2s8MuprS=?GSXuLF^ +@D'rrVZZp!ri/te,Op~> +ci5'br;6Eho@ojI;bp_oaMGm5`QHBIccF)C_o9^Ac-#Uu%`ZB0c-P4iOoUNkdEfnSrl+u[b5KNc +b/h['`rF-[`rF-Yao]Z(`;[Ro_RZXO7oj,bWjT^bbK@f?`Q?->b08,SaMu-8`Q$("blGn<aSs=5 +aMu6Bbg"DYc-",H`lcNLb0%rQc-XMObK%E5\<Ue\-o*VSKr)Jh^sU9F`r!jU`rF-Zaq2e=a3;02 +aMlHUU^@6accsc*aT'Kab5]Q]`r4!YaqVt=ai_iL`Pfa4RU02p85!$AdH^T,s8W&ss8W&Ks*t~> +d/O1Hr;QTn"PDc#hqJ&/#6+Grs82]krVlrsqu$$a&,ZD+rVlWgs6TIZr;Q]ns7-*gs8W)squQWl +q>Ucoe'ZkArVuopqu6Ttqu$BkrVlotqu6Blr;Q]qKDklKrV?Kjqu$Hj!;u]n%fZA*s8N#ts7>aF +m-E?]rr36!r;?9`qYL-\rX]&*s82imq>ZF*)CHcfs8(pXs8W&s&HD\*p\b'krr<#Vk2bpkj4aJ3 +"TJ8or;QZps8LULJ,~> +c2S1Nr;6Hkq50m\T!%Y_rs&E$s8N&urr2itrr<#irX]&,s8Muqq"OgRo`+gfrr)irn,E:c'E%h/ +s8Dfjqtp!5XK&_`li6qZqYpL#r;ZfrrVZWmrqucurVZTlKDt`Iqu6Qo!<)los8<]3qZ$Tnq>^?R +e%rf3WNtsis8)cqrr)lprr2rorX]&+s8;onp\osq'I"XUrqbs[rVucos8N`1r;?Tpq"s!JTqJ6M +T<%DTo)8Ics8LLIJ,~> +c2Re>rq.,shK<.'9P:ZMaNi#MaNMWHaMl'5`QZQKo>h`f_T0a@ccjbk`6HfVbfI]E`l?*@b0%s) +ap$#3aMu<BrQ5,Zrl5#VrkBShY^oS=:jeP<]tV>&b/_B=aNVoTc-48J_o9X<c-O_YK#mr8rlP8c +c2Q#mbfIfA`QJ&$(Wt%L_6pVCHrVsL-nA)pa3)6:`l#m?ans0Y`r='Yaq2Y9_TB[>aNi[b('Y9N +\'Dq^aSj9]aSj-WaT'BsbKA#J`lZ<9_Ot47='J="GK]%3rVlfurVQQ@s*t~> +dJj=JqYC$brt*iDmGR1-s8Moqs8Donq>:0js7$$frrN,trr38tq>UEks7lWkl2C_`rqHEppX8$j +rVm3&r;HQhq>:*frr2rrrr2qLrW)lnqtL$crri8qrU][[rrq`Ojk.ZNrr39&r;Z]hr:Bjao)90u +s7u]kq>XkM*[`'T_>a>jrWW>uqu$<crr32\l07^#h;S;3"TA5kqu"h@J,~> +bPr1Rs8VuVV4ONW\FKOsrVuopr;HWsrr)fcrr)j*rVuosp%\Lcqu?Klr;Q`irWE,urr;lp!<<&t +&HD\+rr;cnqU_RD]AiG^s8Moqs8N#r!<2ut"9/8srIY%Fs8N#orrN,trqlcqrr3`4q>L<hiki13 +Xf(1Yp&+X]s8;corVZ]hrXf,/s8)ckp\S2<(EaV<^]"&qrr)lorW2uorr3Q,s8MMdUn"-JS?:iK +r;?Qnr;Z]of)L7~> +dJk9drr<#no_/(Wn&00G;cIeC_og0Ga2#U8bf[rA_8c#drPf8dc-anYbg4YXbJ;08rl4rYr6##_ +"jP94`lQ7"ar/FEaN)<;_SjO3^p8Va7TY23\\c>*`5B[?rQP\nb/VE>`lcNOc,tXZrlkAdrlbJe +aMu7!`?3+@b08#L`l?<B^UgM1A2Y_]/N/-`Zc:57eAf;D^rlVqp;dfb`6#jAbL,6>'Ftrd"IRHQ +lcB%Es2b/]'@"VBcGdZB`N3BI:/k%pHc54@qYpNoq>gE?s*t~> +dJj=JqtKmarrDinrt"&MkMkJ#s7QElrVuciq"t!ho)8gkqYgHlrVca"qZ$HmqZ#gZ"98B!rr2p) +rqZTkqZ$TRh;Io'rs/Q%q=sd_r;QHjJc>QErr*-"rqucnrr2iq"TJ;oq"t'j"n1jIlIY>"rsA]) +s8;osrV-3eo)A[f%KH8(i$T`o*@ObBo_ngLrr<!#rVZQfrr3W&o'#W/inOJ4rr<#prqcNhr;P+D +J,~> +ao;kKrqtcPTUqsloDeF^s7uTms8E#snbramrql]pr;HTo"T&/rs82ZmqYpNns8E#uqu.?1rqu`p +s8N&rs8M`hm&d+cbO#*%qtpBrrr)cnrVlcurVlcoJc>WJr;H`srql]urr)fprql^.jN"g?[]@RG +q>UEms7u?bs8W&qs7ZF's8N#tq#&ki*#o_<9AT1;s6K[_s8;itrVl]mrso"l\YkdcR@L20qtL'f +qYC-nrr)fpfDg@~> +dJj4Frr3u7p@e@]qWbe1=A`.B[*$2.b.Pa:c-48H_8F73o>hH^`50F5`lZQQc-=8P_ofgl`r=$Z +b5TWbbll83`lQ7"asbKV`lH->`Q#sGa18^R<(9GpQ)qC*]u%e1b08,Tccs\T`Poj<b08"[aSj9] +bl,ZdaMu3<rkecU`r=$r`PK6qZ(Q;91+Y(6B;McC^W"aObKS/J_>_FR`r4!Yb5B<l`koU>bhL)M +&ek`e28%&SbNm7J`rF-Yaqi1AbK\/O_l@WU78?HVFh@&2rVufqr;QNmrR(Xq~> +d/O7Hq=jabrr2utrr3)RmHEC&rri>uq"ajds76."qZ$Tns8Vuos8W&ms8;lrnc&Lbs8N&u!<)ip +"T%lgs7lNls4m_6oD\amrVQEgrr)lrrql_IrqQKrrr;utrr2p$rquTeq>C3k"n([@kLnYhrrDll +rri5us8DugrX]&*qtd]K-QsKZD"RT(qZ$*bs8W&sq"tX$s8W&koDejUk4eK<khuI?$N'l#qYp?h +qtp<hdf4g~> +c2SIVs8MrrrVcWTTqe0Sh>I*Hs8;lns6optqu?]ps8Vuos8W&ns8Dutrr2iqq>U?ms8N&s!W2fo +rY#80r;Zfks8Vril*ROqaQ`['r;HX!rVZQirVlfr!ri,rJc5lQrVlfrrr2lps8M`l)#a?rcG6rj +U:'Lfs8W&ts8)]krqQBjqu6Tpq#:6l%f?+sYTY,-(F3_cq>^<kn,DtZ!ri/srVmGq\t5O^S=ZS9 +p&+aeqYL6iqu6ctrVc`Is*t~> +dJj4Frr3i6qYBseqtKBiBNRl*PeY/Yb/2*:b08#Jrke`Uo#M?YbK7]Dai29BbK%E@`5]puaT'6_ +`Q#p=aSs?^bQQ)0`lQ7"asY9Pb/hZD`59O=_9L0A];/n48RRCS\@fSk_8a^He^`'k`PK=*`Q!JM +29<eV`P][7b0A8Wbf7Q7^;Iq+_8XL:^8R'$4YSZR5$4>`aMu*6`5KmEcc*oK_SsF3`lQ7!b5]Q_ +`Xp,+_9CK$(E*tq&5(-he&KN"aSEjQaT'BobK.`Dbg3D39LqH@<GfS8q>UBqr;ZNjq>gKAs*t~> +dJjCIs8;ckr;HX+rr<#^kiV!^pAb0is8N&trqccps8VWg%fcJ(rr<#srqcWorVufonG`Cas8N&u +(&e14rqlWlr;6<iqu6Kjs8VQ9eE-K#s8N#os+C=FrrE&rs8W'#r;6BhrVm&mkj%9`mf!1cqZ?cs +rV6E`rr<!,qS+I!+sSJ,oDeacs7$$fs8Drlr;HX5rqQHbh!aq/lf%^?s8Dils8W#squ$?gr;P1F +J,~> +dJj4Dqu79,rr2rtqn](rU8?98qY:*frqufrrW)uhrW<,uqu6U$rr;lqs8N&srVc`ns7uZms8W)u +r<3#ts8N#rrsnu,q>^Hns7XU2UqP@Eq>UC%rr)cmrVc`ps8N#rJc5ZKrr)cos8<&trVc`kru1k6 +k0UiT[]-t+qt:!brVuoprVccpr;?Nnrr2rnrql^(q7@jd)]U&ko)JXbs6fmYrrW3"qYpL-oZs)! +R@B_Cd.[D:s8N#tqu?Wmrr`9!rVkFKJ,~> +dJj4Dr;R]6qYg?lqW4#Q7nZd?_8jO<`5]g<b/hTA`Q%Ji'[+G6`lQ3>`koa9`Q?'=aNDZH`lA"s +s2b2^rlG,Zs2b/].*0WWb/_WHai;<GaO/>X`is_X5[/W*Xfo(B_91*QdEThQ_nj1,`Q!JM!QN+X +_(WdIbg"JYb/M33_o'=*^V$tNGu-%?/2CV)\@]r(bK@l@_o9jFc-42K`P][7aN4;%'?J25`P]R5 +c(5X\'bV"(`m2TCb4*LJ`r!ghb/hZ@`lZ93Le^N.6VV3ljSJfS"Sqriqu+nAJ,~> +cMn"GqtpBls8Vuqrs7HKjPT\2s8Mrprri5pqY^9LrX&W!s8Vuqs8;Zjrr;uqs8Moqs8E]0qtp<k +s82Whr;Q`qs8VE)eEur,rr`9#s8N#t"TA5qq##dDq>UNps8;fo"8r&jrVca"p[@k;f@BWq!ri/s +rVm3&qYpHns8Mios7uX)rVuZfDB(/LaR]B.s8Vrqnc&RgrVlip'`It,qu6WprVuoms8Uj5m.'Z5 +iUQpI!rVlnr;Qp!r;6Eke,Op~> +dJs4FrVlrurVZZp$iAA@U7J40q#10js8;lqs6fm^s82d%s7lWor;Zfpq#13l!r`0!rr*-%rr2lp +rr2lrs8Dips83B*d@[5HanPT.s8)Zns8N#t"T/2urVqKK!r`&qrVm!!s8W)srVZ[(q"j="]"P,; +WTX<Xr;HQpr;HWo!rr2rrVm*$s8W)os8W&squ7-"ok>0f)o_@Ir;Zfns6os_s8N!1s8Mros7u]j +\u20kS=cY(qu$<hs8Dros8N#Ls*t~> +b5VqJqYC0kpu7oE9LW-E_#DR`ai)*9a2lBGn&POPaSEjUaT'E_bR_t5aiM?<b/VBAbf[rC`lA#! +!m/X/q8sf'c-4>O`l5j1]XW_n:L%LsT<c;Oai_W=_8sd?aiVGOa9p)2`l?!:`59R9bl,dOaMkp7 +_Qon_81lbQ2c,gI\B)q6_oBdAb/D6=aj8AV`5fg:aiMBDbf\)LaMu6=_naF<elE%m#Gf>a_T0^: +bjidO`rF*raiMNCaN;NA_T'C4\oh.M7n69\U>tnDrVulqc2W:~> +c2RkCqu6Tp&,Z.us8VlVmG?b#s8;oqrr2rtq>pTnir0,]rVc`qrVca&r;Z?cr;Z]mrr2fps8Ec2 +qtp<ks82Whr;Q]ls8)cqmEFSXq#(-uq#C9jr;?Hiqtu'Fs8NH*rVZWkqtU*fqu$Hn!<)lr"n1dJ +mGm@.rr`/pr;QWo&H)S*qu?TeoDJC^r;6Kns7uKi&,lG+s7A*Slgk)Uq#CBks7-*gs8Drsr!*&r +rr<#trqud$q<$`+m-`QrrVlrsqu6Km"9/5rrmUmt~> +dJs7Fs8Mus!WN&rrs\54U8"-VoC_nYqYC$cs6]g_s8;j"s8Doqs8Mus"T8;jrVc`qqu6Wos8Mus +s8;]m&,5bj_O7RBdH^T-s8W&trVl`ns+1.Xrqucorr<#qs8W&prqud0qrG`,\Zr*:i:HsBrr2lq +rVZWmrr3H(s8)Kds82fnqu6Wqq>L<krt#,-s8MOA>NkSVs7u]pqu?-aqu6ZqrVuor&H;_,s7Y'L +S"6"BTZd3/r;HTo!<2ur!<1=EJ,~> +b5VPAqY^?m%e7T"=&2Fq[(j`2`PKC2rlkJib4<XPaoKN[`W4*ZaqDqCbK7iI`5g$De&p+O`5B^: +`r4!YbPB<\blZ,1`W!ak`Qu?2ZZA9&??DR<\\>kk_nj:2aNDcMK#e;Ac-=AL_o0F1_T;`"/'cMa +]sYDPKN0i]/2C+i[DTJic-=5D`Q$-Eb/D->ai23B_SsO6aNr)Lb5TK]`Y$2,`6m2b'L'RXcc<f? +a2cKJo#U^Js2YtraNDZI`Q,s:]udaE@nB6_<a1pHn,<4b!r`#pqZ$Qnf)L7~> +aSuAAqt^!crrhiRk31\"rrrDtq>^Hei;O5dqu?]os8;`jrVlisrVHKlrVuiq!;uin#Q4T$s8;fl +r;-F)hq-fInc/XfrquWhr;Z`nqgnbGr;ZTsq"jm_qu$9i"mk^NleL4nrri<#rVZZnrrrE"qtL-c +rVm&qs8;oqq>UEirXSu+r;HQIp&+jir;?Tpr:'^as8W)uquZlqrVQU$rVucQm-sH/h<Xt<!<2ip +"TJ>srr1FIJ,~> +dJs4E!<2or(B4@6rVuoe_5Ep$VY0W\s8W&mr;Zfli;O8equ?]ps8;]hr;HZqrql`hrqufqrr)j+ +rVQQmo(hmbSu9$DnG`7`!W;hGrr2onrrE&trsnr$qYK3i^qd7PWS@7KpAP!nrr)fprr3&ts7uWn +"oeQ"s8Dcms8Muts8N#trser)rVP:?qu?]or;ZfplMgb^(&n74rVccroDIFBU7RjHU!3?4s82`m +rri?!r;HT?s*t~> +ao<1Urr<#sqWuOfA5Q90[)(#7cH!fBd*0Dta90T/b0'P$s2t>b&'`/=a2H0DbKeJ\e&fPE`qmdR +b5B<\`r3mV`;dgjZaQoK9i+r1Oe];'cHaVTaMu6?K#e8@c-=JSa2Q0Cao9L!bK.T3ZD)M51bpX; +9p!'4_Tg->_o)Gms2>Mcb.l'?bgFSZaNquIbK@s+a8j6Za:ZG6_oBgAX2`?2d)a;Qbf\/Po#UjN +qoBf#aMl3>`5]j8[D%u.9hJ&W@\DNJqu-QprVQHgrVQWpqu?WGs*t~> +ao;PDrVZTgrr2p-khtRcirB&Trr<#rqu?]SrXSu+rr)lsr;4k3qZ$Ehs8DrrrrE#rrquZorr2p$ +rqu]os7uQl%ckpbf^]"Aq>'m^r;Q`rK)PoNqYC!arqQ]orr)fpr;RH(m.9Jli;N]Urr;ono_ndh +s8N#sr!iZ!s7l?fp&>!jq#C?ip\k<is8Dusrr36$qY^BnrVccdrr)lsrr;lts8DllrsSJWiplL( +hrt+>o_eC^rVk=HJ,~> +dJj@KrVc`prr<#ts8NW-s8W)j\=]:cXS)G\r;ZfPrXSu+s8N&uqt\P,q#C0es8)]prVc`mrrW2u +rr2p0rr)Kfs8Mccjg1\a]A*2\q#1*iK)PfNrqZR/r;-6bqYpNXc,%?/VR+kEq"F^es8;lrrr2lr% +/^)(qu?<es8D]lrqcWnrr;rr!r2fpr;R$"qY^BnrVcc^rr2rtr=o82rVZQiqU;X<T:2@D^\n-.s +8MoorrrE#r;?Nmd/SU~> +bl@_A!WW/us8W$0qX)dg>>J4-\AQ/+dEg%YaN!bkrQ=rWs2tAc&'E/:`l6'Ec-iQ5dFQFYbkfB\ +a8=!uaMu3:`Poj:aN2KC]Yhh+]XXYJ8PN30U9D&ArknlWa3'"T2Tj7gbK7iHb082Ua2,9kY,I.b +5r^535^BNMa3`,U_oKO.`lQ6@`Pos8beUs6`mN8[a4&8PrlG)YrQ#PaaMc6?aiMZH`lcWQbKJ/Q +o#UjNqoBc#a2Gs:`PfR*[uOrg8P)liOlZ60s8W#qqtg0dqu6cqqYU6As*t~> +ao;D@rVlg'rqlZos4?Mnl0/-H"8i&rr;Q`UrX\u-s8DrrrVu+30td8\qtp?lrr)utrquZmqYpWr +qYgBm$2X]"s8V<2fBi;3rri;tr;Q_JrX&Muq>0p^q>1'fqu6lYlgEodd-^f3#5e/hrqcTkrqc]p +rr3N-p\"%Uqu?]jq#C6krVu`irX\u-r:g6kq"k!gs8Vrms8VWgs8W&ss8;oqqYq!%jQ#Ckm,Qq% +s7lKgnc/Xgf)L7~> +dJs4Fs8W,us8W,u'`\.2s8W&kV5TfZ[dF+kqZ$Tlqu>XS&,lP.rr;uqs5kX[\Ffgtqtg9nrVlip +rr)isrr2g5rVZ]qrr)fjs7cQ\_P3m?dI7)7s8N&srr7WMqu7<.rVQ9fs7lKklGL6D[Ap=Up&4mi +"9/?#rVZ]qrr2lprsJPtmd^&OqZ$Noqu-QmrXSu,q#CBiqu6Qos7uQls6K[as8W&srt>8,q"E=? +T:2LFT!J"grr;orrr)isrr)cqrm:[q~> +c2RnEqtp?js8W'2s8;EAFCn0ID6:k"b0ePU_o]phaSs?UaT'E^`sfr,b0J_[#ni`TfZM82a8j9W +a<AO;^;%S,bg4VYbfn&C_S=+(_5_]R6rdoYV7FC\`l,j9J]K"U`l5m7aNMcVc+'U>F$VT:1,1t3 +UU\1eb/hTG`5fj9`r*mga2>a-cHG%nc-+b`d)jPLrPnlY&^&26aMY[/`4a%/bKnMVaj/,taT'E_ +aSa'p_SNmmOBbIQ<)?kUh"LaIrr)`mqtg0fr;Qlrq"Xa9s*t~> +ci=%Equ6Zqrr3<&qu6WqhrNbPnG`IfqYgHQrW)forsJW%n7a$f/V*Knr;?TprW<&rr;Q]irsJc( +p&Fmcs8)]jqu6U!pY4Q`oDJLcKDtoKs7l]mr;$?rm,[NncJAI!%K?1rp&"dgqu?QhqtpBkrso&% +pY_$=/q;7ErVuims7uWurVuins8Vrnrr`2us8;Eds8W&srquWm#P6a6n`o<"o`"jmq#:9go)Jah +f)L7~> +dJj4Gqu6j!s8Muqrr2p.rqlMpV4O9knG<(YqZ$QjiVilXqu6U0qY]_l*#^5Qnc/F_r;HWprr2lr +s8)`prsSi)r;?Nnr;ZZjs8Drss7H`d_kjKFe)p9%s8@NJrVllsrr3K-s7>[HiQApPZ_+V`o_JLd +!WN&srrDonrri?"r;?QnrsIbA:E=]*q#(0jqY^BlrW`?$rqufrqu$Hrr;Q`oli-qa)>sO7r;6El +rm7R8TpqUH^ZbXqqu?]ns8N#ss8MuurVl`p!<1RLJ,~> +c2RnEqYL*brt,+sg4!L-:N<VRb/q`Ka25jUa;;k4`lH9De'(Jk#8CUnfZ_IXaN2KEaN+.u#0"En +_o9^@rm)D#ahbg7`lu]I]t'tY77L$kOJTJ$\\#h5aT'7$`P][9ai_Z@YF^o!:HLNd*C>7M[)C&, +`Pfj@`l-!taT'E_bU:TXaNV5157Lhpcd:%\`6?3>`l?*@b0%cG`PTX9_8sdBcHXMSbf9%ks2tA_ +&]Vl4`50:.^l2Jj9MSVrNQ^qlrrr,nrVcWjqu6cno_A=5s*t~> +ci=%B!;u`o!<)`n"mF\"jP9V.s5Eqgqu6WqqYm?:.39]Y:=K";rr)lqr;ZcnrrE&rr!EB$s8W&t +s7ZHdr;Qoab15A8r;VBJ"9&,prql^#q<@25k0N/`r;R0!r;?Tpqu$Kor;?Qlrt"u+nq/PA'dY+J +oD&7_s82Tj!;?El"o&&rrVZWnrrN,rnc&RgrVlip%fZM.rr<#sqpt'!lM9`-qYpTjqYpKtrqu]n +rql`qrmq+"~> +dJj4Gqu?Zp!WDrnrXJi']V1pkWS%4Mr;ZfpnG`Feq>U<l!;uir%f-$s*[;IA*_OfPqYU6jq>^Ko +s8<#srVl]o(B4@6rr<#ps7u]pnbr*sS>WX2i9g1:K)YcL(&[t+r;-3go\@Bt\uV=<htd-Arr;in +rs&>qrVlisrqu^*pA4-&-Q`mE+<C"Hqu6WnrVufp!;?El"o&&rrVc`orrDuerr;rqrr<!9rr;rm +qu$'FTqe*BVPLZmr:Tsbqu?Torr)fqrVlcqrr1OLJ,~> +bl7eBq"Xa^rsnnqiJV#:9NmRqc,n8Ua7.1L`qd^S`Xp&'_oKsBeqFJJ%1rt$YKY2haT'BW`W4*Z +bl>icaT'6r`QH6?bK7N<]#r1-`3a_Y8PEH=OI`_mK?,=W^qe%:eBYk0RX.pl1H76E@>Ckj\Auk3 +`l?-@_SjU?aN2NJrQQ)!d`c5<'ab][!6WL.b0%T?_o9X:aSs<l_U6ZS`R;oL`5Td<aMu-faSF!Y +a8j6Z_$dcG<Dc=U=C6d4mI^AW!VZ?arri;moCi.4s*t~> +ci="A!<2or!<)]m"mY.6hs'q8rrrE%r;6KmrVllsrVZ'^&HD\,rr2gu-QaNT,:+S,rVlcq!<)op +s8Mrrs8E#rrqd-%qu?TnrV-9hr;Z]kqu6fUcI^q>qYpQprquWl!;u!Y!W;rjquQfpmJd+brVl]l +rr2lop&=pis8N#qrr2Tj#4CU5j4)BDqZ$To!WW,rrrW)srr2rsrX\mu/L;Va)&jYEK(o<Fq#C-g% +KH8%rVu`ns8Mrprqu]ms6fmdquH`ors.o?kjIg*k3MmD!ri,qrr2utrqlcqqu?]qf)L7~> +b5W:WrVlforr2lqrVuopp:R)oT!d8Fs82]mrrN-!r;QZp!<2lqq>U9k!<)or%Jj*L)&sM7+!-mG +qY^<fs8W)rr;ciqrtkS4qu6Wls8W)us8)]io_S:8ZD4\:cg:Z0s8Mrrqu6WqpAY'ko_nmkrq??m +rr;9_!<<&tqu?ZprVm!!s8N&nrr2lrrr2pGrr<#trr)irs8Domo]tYc`4ig]S\4Cas8Dflrr)ls +rr;rps8Voorqu^*r:cL"(`=50*$$8Rp&G'er;Z]o%fcA%r;ZTls8W&ss8Doro`"jiqu6Tp)#jL3 +s7b!BUn4'KS[/(iq#1'dr;?Tprr2fps8Musrr1OLJ,~> +dJj4FrVm$!qY9mbrVllsrVmW%fSEU(8njU(b/q`Kb0%fF`Poj:aSs?^aSX!QaSj-Y`>$/,aNW$h +$jdIU&J#4sd)sJQbK7m%`[AjPccs_WaMl'3ahu3A_o]s6_o9R=bJ_<(MGlT+;eqGq[CElc_oDJm +s2P&ZrlY/[rl43D#0P$0aNDTHn&PRMaN"(tr6"rY!li=$r5el[s2b,\rlG,Zs2[FI`l5g4_S3.: +HVujW/0uZFQE@s?_p$ELbK7`D`lH?OaNDTJbg"J[e'`LQ&/Q6$'F4hHcI1"T`l5j7`lQ7#aq)k> +bKS;Sb0%`A`5TX3b/X;!!6Y8]rl4uZr5oVm`l>s6`4;">;b9Y`=aSceo)/OfrV6BqqtB[WrRCjt~> +ci="Dp&>?tq#:<ne`lAZf)5OLqt'a`rs/Jtq"Xaas8VTfrr3W1rVZPa,p43U*?uk5jSf)Xs82Zl +s8N)trr3N.qXsmcs82cps7uTiqu$Hhrrh5tbiJ*frtGD1p\Opiqu?]np\Xsgr;HTlqu$Elqu?Wo +r;6]pr;6<cq>13jqu6NnrpKgdrW)lnqu6Nlqu?TorW2usrr3'!rVlcq$iU#$qtU$fs8;osrql^" +o^25*ceA-hs8N!!qZ$KmrttV4qYpKlrVlGd.jH;a*ul:D*@!2mq#CBYrqucrrqu]orr2g&qtg0e +r;-?jqZ$Hkrs%<Clh0_tg&:pNrr)lsrr)lrrltIn~> +aSu8>rVulr(B=@4rV<(`US=XFp\Odes8Dutr;-Bkq#Bpar;RE.r;)p,)]'V3)]r&<qu-Qpqu6Qo +rVcfqrVm3&q#C9lr;HZqq>C7)rVZQiqYL$P`MBEGa5H:Zs8)Wm"T8<"qYU0is8EB*rr;rqrr;ur +rr26`"9/?"s8N#srV?Hjr;uusrqQNmrqZRDrr;uts8MroqYU0fr;Q`rrVccrq>UEfs8)ZlnCl!s +]rIa2fCo4?rVc`prVuj:qZ$Kms8Vlor;ZcorVuPf-QX3G(Ddr0)BLB^pA4g\rqucrrr2lrrr2p" +rr;usq>V*+s8W&tqu?Hii2EH@USjQ]m/6k_rr0h8J,~> +bQ%S?p\u!+m+#TM;,CMl^;e7=cH+#H^:_;$b5TWgb/V?:`q%1N`r=!l`lH6GFp&$V(_R]"1pkHN +cca;KrPnfW6c[<mc-FDFahl0;a3i2Qb/M9;`lcNMbf7E)R:nfJ:K;CiTX;/Fb/VKGaMZ*C_SF.3 +ai_lQbfRrI`l5m8`lQ<DaSEjUaS3g]bf\/Pbf\0-b5]Q]`rF-YaofZ&`l7qss2b5_"jG69ccjK/ +``C'u`Poj:aihoPbK7oNc-4GWb/M<?`kosIa3VQ'RsA$u1HdTT;h1[HYJ8)ub08,Sbf7uKaNM`F +d)sYXb0/2UJd`#"(_m`#((1BY\]rLE`l5p:`r!jTb5TKW`rF-Zaoor2aN2C!`>-M;aNDZDaM5a+ +^7/A)6r.)nHHPLInG`Uhqtp?@s*t~> +_>aoBrVQNls8VKEjQY7orr`,lqYpHn!;uil"8i#qs6oses8W)ur!rMM:*pr',TeGJpAb!fs7lTn +rrW,pr;6L!r:Tser;6BjrVlotrVZ["o$,G3i:?mFrr`2rqu-Kn!WDrpr;ciqs7ZHWr:'^as8Drm +r;HNkr;Zd#rr)cnrVlcq"oeAprr;lkrs/Mlk3(p`d-CT0!rMonqYpKo*;][4r;6Bip&Fj"9dCW$ ++s&$W,TJ'M+_LcLqZ#j[r;Qp!r;6EirVlfo#lXYtr;-Emrr)fq#2J>*n_W-frr3-#r;?Qn_Z,,~> +_>jQ5s8W,r$1YHqTW4aJqsaR`rrN,sp&FO\rVuoq&,4FC+Vbh5(aZifs8)]orr)lqrr<!"r;-?g +rrW,kqu$Horr)d1rr;okrUnI3Up%GZjmDg@s8Vuor;QTnrVZ`qrr2utrr;fnlMp_[rVuWk!<<&t +rVulrpAY3nrVZZn*WQ-;s8Mrqs8W)ts82`nq=F+<eAK#1X.6i_qZ$Nns8)`oru:h6r;?Hjs7cQi +]1aCb+!)=D+s7^C(E?oap\OgfmJ[=gr;HWos8W#rq>V'*rr;rprqH3MW1KBKP+TA]p:UEU~> +^&K)EjMu[J:Kpts_S"%;bf.H5_oTm@c-=JR`l#^6nAkXPa8X'iaN:D5%1<ml&dFH<dE'GRaSj-W +a9K]+aMu<Fci1rhai;0;d)sB-`?<1Cc-Oha`O`=GDEBU8:2PfRX1-$`_SX40a2c?Ea2Z1!aTK]/ +aiXM$!Q`F[aSa'XaS*aWaNFM'rQ>/]rPnlYs2kDeb/jP$s2b,\rlbDcaSNn)b/q`F`lH3AbKA#P +bfe2Ud)Eu@]=Y__X.4W?2(0^q/7+^T`PK@0aSs?^bl>g1c-4;JaMu6?bKe2Zd[)Qm":u1V()[o! +'+"q7gWR[^`l5s;mDoIN`Q$!Ab5TTeb/hZDrl+oYs2tA_&BD`,_n<LR>tdRV6sPMsiV'tbJ,~> +^]+Z?qu6NnrRg;pjk]q9!W)`nrri;qq>C0irrW2tr:0aurVlfrrr2lps7ZJD.Nol_II$k3!W2ik +rY#/-rVuils7Z?frr<#squ?Tlrr)iur:g3errgokdGO9drrr>srVHEhp\tBpqtg3equ$<inc&Ug +o)&[gq>'pcrqQNlrquZtqu-HjrVlfr$N0_ss8Mros82Zlqu6lejm:mKf'WG9"ShT^qYU-g*rYp7 +s7u]pq#C0bdTS1L+"&16bk/4c+<hgO/B7_dl2LY]!<2rp!<2lq"oeQ"rVulnrs%BDp?_#/ec,RO +r;QWlrk\Vb~> +_>jQ7rr3B$r7e$FSY;n:qtpBls8W'#qu$Korr2osnbrUgrr2oss8<9(p&'4a)]0fGlM^_`qu-Kn +rVd<)rVccpq>^3erVlisrqu]orVdc5s8Vrgq=a@8[%=/$^tAM[qu$Hns8N&sqtpBkrr`2tr;QBh +s8Mrr!<2oorr)iq!WW/arrN,trVHZorVlcq!<2ips8E#sq#:Nrs8W&or;Q^,qWuqP]#(qRZHW(= +q=jXZrr;usrVmu=qZ$Tls8VloqtSQ?-mKZV*`pMTYoar)(*4j@s7uZis7-*grVulqrrN,tr;Q`r +(&\%1rr<#sr;ZHKUn=KTTWFmGq#1$drrE&9s*t~> +_Z']9q>:0k)XlmuCL9_.=II%HbKnAP`l5s<b0%`C`Q$!An]2NgaN2EA`lH3Jak:,8%1j1U^=1HS +bJhO#`rF-[atq,\aj8)Ha1fI0aNMfH_oKd:`P]U4aNVcSdDil3[Af-i4[)>3DjdE*]u.q2_oKj= +`Q%nts2YJgbg"DUb/q`GqT9#``l?!:_o;Pprl4rV#/eEt_o9^>rQ+rWs2b,\"3AX-bl,ckbfIfC +_nj1/r5^>0bg+JWa2Pm1_8F1-`5T[;d*0MI^9F8jF]^RV3\r3OCT"VX`lH3Fci(r``ZN.7bg!uF +cbe&Od^)=](_@>e5dB"4%M0?d&eh(raiaG!n]:aMs2b)[rlG)Y(<X_Ac-"/L_oBp5TNFic9N5_A +[+t'@qu?Zo`rCP~> +^]4<2#lFT#s4Hf%lIZ%8#lX]"s8)Njr;QZp!W;ibrW)onrX\l*q=_lW-:m_-rr;fls82Wk!<<&t +!W;oqrs8T's8)cqqu$Hkrr`2to_81]#5Qcne)06_rVllrp](6ls8W,uqu$6gnc&Ugo)&^hq=sd_ +r;Q9es8E0!qtp<irr3-!p\4L^q>U`uoB5&pkh=;:r;R!!qYgBfp&+[cs8O,3r;Zfis7,B&.NolV ++@`g9r;65.,U"BT,>n@;s69O_s8W)tquH`krrN)tqYpfrhWaFombc=fs8VusrkSPa~> +^],2Mrr;omqV\'FS#E+@q>1'erVulps8W)trVlcrs7-'grVc^.s8N#os7c-',9]JEs8Dunr;ZZm +s8Doss8Muur;HWp%/p5+qZ$Tns8N#trr2os(&Rk-s7uBcpA+R7WhH>t^tS8Pqt^-grri?!qu$Bj +qZ6Wnrr2fpr;QZp!<2inqYog\!WN&qqulutrr<#rrVlfrrUp1*r;-9is7Y^6d(m6"X/!/`rVZWl +qYgEn!<)Zl*qfL3s7QE`l?js")B0Ya[JKk!p2;)l)AsPiq#16lqZ#s^rr2utqu-Nn!rMoqrr*E) +r9Ve,TUV:BUS$W@rVHHl!<0k8J,~> +_Z'W7rqIN4s8M]V]4bJ><*,a/_o]m>c-+8Wb/hQ>`Q69Ib4<USaiaV(!65#Z%b&_MV[<k^b1=h` +`Q6<CrPnlYs2m1Cbf\#Ha32`Oaj/#HaiM??b/V?8_8F:<aNN#[aMc'/Z`8@A3'L)FK;#ERZ*:p] +b/_K=rko&^`lQ9EbK@p*`r='Zb5TH^`r3mR`r<sS_ZRm!b0'\(rl4uZrQ>/]s2k>crlk_mb/hQ> +_8!h+r6#&`s2ub3ai;98_8O:0_nj.$\@8lLRXf*K3@u^0.nt`"\A?/+cILRsbf]q)rP],^`k014 +c,7oH`*iQY&ets0QIaU<f2`M#*>8r?e^;X_qSqpDqo\fW(<t"FbfIfE`5o?L?r9E`<b-!Ue`uZ& +r;Z`o`rCP~> +_Z'l?rVZ]qqu$<irrq$<j5f"hrr33!rVcWmr;Q]qmf!4bqYh$*qu$Kkqe=[\s7?*erqZThrr<!. +p\k-grV?BiqZ$Tis8N#qs8W!"qtg0br;$?ro#oM9i9pF@!;uir!rW&soDejiqu$Hjrqu`or;Z9c +s8;oorqZTk!W;rhrsSi(r;6?dp\aj\p&"[e#l3oRj4r;-g\h!L#QFc'rquWirV?Emr;Q^8q>L9f +OXDOs+!;Vrs7QEkq#9G(+=/$M,ddUOkPkMZrr2Zl"9/?#rqud#iU,_!n`J6trri<"q#(-,s*t~> +^&JW@s8DojophbKV5r)Cs8)Nfs6KXarVZX+s8N&qqu?KfB%?hZo(rCcq>UEkrXf&.s7cNmqYg3d +r;-Hnq>^Hnr;cioru(e1p%S@YpAFRUq9l+:Wj'CslL=WGs8W#nr;Zfq"T/,orVcQk!WW/hs6TaX +rs\o*rVZQiqYU0frVlfprrW2trVlftqu6Tp&F\`1`kJmbX.H]Oo(MYJqYU9l"T8,mr;QQm!<)os +)Yj7-p5gRH(`OG6ScAHas8)cY,SqC6(a$$]rr2fpn,E@er;Hcrr;?Nl)?0R5s8;lrqY/O0SsH7F +TVMAVrVl`pr;Zfrrknbd~> +_Z(MPqY9j_rr<#sl-WsD:/tY^_90d:cHjb]aSs0ZaSs?Pa9'K+b5THs`lQBEbLFnf6a+kc_T:*H +_p$-?aN4A'3m>jpc,%BC`llHHbfIuK]#W%>b/V94_8FIBcd'\Rb0%W8_n!:cLJgc98m6@gMOh&k +aiDNLda-(UrknlWa2\+prkncTs2OrWqo/HPrQ+oZqT/ZY!6G)Xr5eiV"3&:$b5KO6b/VE<`PopA +c-=__aM5?sXI=QO;F3H&1,q-mKrMMm_T'U;b0%fHbfn0-`rF$X_]ck:ai_]MeC/LN((:`c#_C^N +cd'_c`=X"6'b1V7eBZ4Xqo8-HrlY&XrQ5l#bfe&E`llB:PuCOQ=\r:Bf%K9Zq#(0irPnkf~> +_Z'o@qYL6lrVZQlrr3,Uio\tQrVlusqYBpcrr;ltrr<#^rXSu-r;ZKdqu?Hjs8DrsqYC-jr;Q^& +rqQNnrVuios8)`or;Qcprq-EirVuosq#:Tkg!\F&iUQpErrDobs8W)uquZcnqu$9hqu-Hkrp]sf +rW<#pq>U-kq>:*hoD]!nr;?NnqY^@"rU]::j58M>j7rHM"9/5qr;?TkrZD1<s7lWeUEh*%+X&(o +qYBd^q"Xmbp3\)-+XSXMrVPjYrVZ]ppAY-lqu6o\h"::.k2tCrrri8rq>C6,s*t~> +^&S-2)?9^6qWt#PUmnF=oDedcrr)`os8N&urr)f]rr<!1rr;uqs7Q0`rqQKmrVlios8Vuqs82cp +$2FQ#qu?Tks82iorVlftrVl`p)#O7/s8Vulp\3spWM?N!^t%]Ar;HNkrqu`p%fQ;%r;HWnrVlfr +s8N&trr2uto`+mhrqulsrUp0`rrE&trVQKnrVlWm*W#d8s8DTMe&&f+Yc=Y2dJEG*qu-Hlrqu`m +rVlirrqZR:rVuWknt.!I'HJ5;OnnkIs82]nqtGCT()S,=A,H-%rql`crr)lqrqZKprr)lrrr3N# +\XoRfTU_[Mq=spfqtp?ks8N#8s*t~> +_>aN5rqZWnrr3W.keq7@<_H__[E?V6bf[lD`lS)#n]:[Os2b5[!6G/^&'`)9bg+5PdE0JN_T'U: +aSs=Abg">SaN;HAf%JR,d*'SK`m;uT`l#R+_84+5cI(%baN)?LdEKSBZ'fAp3B]c1EKHotZaRK[ +^&Gqc_o9U7a2>a2_nj1,_o9U9aND`Nb/VEt`r4!Tap,r0aN2BB`r!jS`VdaUaSs?[bU^iU`Pf^4 +`Q66Kc+LZuZ`'.3>X:5"/hf.XFKVp\ajS\gdE0>D_8XRBc,fk'rl$&#`6H?Qc[lH7#S@RXHJ6fd +ahkpBb0=?6*uc"-7+06#aSX!IaSj9WaSs<tbg+JT`P]g=\9CqN:/t:uC=hM5o_8=_s8;i7s*t~> +_Z'l?q>'g`s8;fmrrqTEjQbXmrr3#qrr2p"r;6Bhrr;Qgs8Vuq%fcG(s7lWoo`"mjqYpNmq#1m* +rqQNmr;ZEGTum?1p](9krqucsrquck#P[les7Q?eq>($qma]V1hrXA)qYp`sqtg0er:U$ir;QKh +qtgEiqsF@_s8N#tr;QR!q>:!_q"agbrqcWqrVZWo$3'bjmHrf^dGFZprr`9#s8Mus"9/5rrV?Hm +r>kq9[oOIo*@MqOl1juIqu?Znq>^9G.3BWS*c(TOl2Ch`qu$Bkqu?Tn(]412s8N&so\o$"l0RTn +s8W&tq>U<irVHNorl4tg~> +^]4?4%fcD&rr2WcpUI#iUSPlqrr2rts8N#t!ri/snc&Rgqu.**qu$Khs8V`js8Vrps8Drsqu.6. +rV6Emr;Z?AS]1X'pAb0lrVc`pqYqQ5rr;rsrV$'es7ZEgqX;_3TVJm-bhVFQqu?Tnrr<#ts8W)t +qu?Wo!WE#fs8Muus8LsVs8E,urVc`pr>>J4oAeHD]<eiBVPh)_nb2hZr;6Bcq>:'frr`5tr;HKk +&c_h.rqa!!(*4>>)Kb3<p\Omgrt#&-qqN>0()\!'p](6ls8VKcrVuoss8Dcm!<)lr%fYe?WM,lK +SYNIdrV?Khrr3#us8Dr7s*t~> +^]+E3q#1*hrtY(deq@O/;,hqFa3DiPai26?bg"ASnAtXOqoB8i`Q$-=b0e#Ic-42MbJaD"s2b5_ +s3)2)c,.Q@`n&AIJuIPRb1"_`c-"&DrkTht`lQ6?^qn(.bf7E7`l#9sZ`]jE<_>_H6r[fCL6nj@ +]>VhjbQZ86b/hZDr5J]W"Nns5c-#n(q9&]X#0+a(`l5s:r5ScUr58QRs2GDeb08)Sc-OYYaN"1t +s2Gko^qI:\TSIVu:H^Tq1ce'8N2<\f`PomsaU-/1aN)9;`5]m?qT'r%a2uWUPrf6a%2K7Ub1+VV +aj%lF`QcN9*ZZ%-"%UY]b/hTBmDoIRbf\)LaSj-YaT'E_bl>iu`l#d3WJFeV91DfgIamZPqY0me +"9&,qrP\_d~> +_Z'rAr;-?jr;Z]prr)j0mcNWok4nuVrqucqs8;ckr;Zferr2rqrr;p(s8)cqq#C?is8Mops7uX( +q>^?lqZ$8Q,qUPmEn9s`quH`prt58.qYBm]qu$6_rV6EmrVlirqu6s$gsja(h;IYqr;Qltqu-Hh +rqcZmrqH<kqu#p^q>Uj%r;6<cq"OOXq>C6frsJ]$n*0$$kM+_Jn,!%pqYU<mrVuorr;Q`rrqu`n +q>MK7s8'ef*[MjK+LCb<q#C6jp\b'`s7`B6,pXE][eTmerr2fqrr)lsrr;lrqu6L(qu6Wps8VT@ +jlc'uhWY">rr*#sr;?Bes8W)<s*t~> +^&J03rqcWo%0$2!]V:pgWQk,9r;?Hl!ri/snc&Ofr;Q`p$NL#'s7u]oqZ$Qlr;ZZn&GZ;'s82ig +O!#eq+`>d#qYg?kq#;E7s8Vurs7lNlrVc`nq"O('Z)Xb-]"ueRo(`._rr)irq#:3iqYp6h"TJH# +s8MZjq#9sd,6%K;rVQ?Zl/^.+]",)@TrPrhp@\1Yrr2ios8W&ts8;cmqu?Kk,Q7Z<`@)QE()e3u +o_\Iarr;lqs7cQhVA^Ep'e-Nas8N#ts6KXas8MuurVlWm&H;_0r:o[&TqS$PUn+piq>:*i!W)ip +rke\c~> +^&J03s82fq(&7.HMd]CS=GXH0ai;<;_oBjCc-4?#aSs<ZaT':1b/23?^s0s?cH=,Ja2u?@aN2NH +bfn/W_oKU=c#O70&IVOEd+$Ifb/hR#_uI_%`5BL.^;S74aihE7aMbs4]X>#>J4MLP3^cYLHBY#+ +\\5bpa7m[Rb5'9Zb596^`lQ0@qo/ZU`r<sV`r!_7`lQ<Hbg"DVaMu-4^:_%e[^<65Q]$;s7m/sj +-n[bpOfl.*`lH9FbKnDSb/qT=`5BO4`lH-@aSj9]a<SgSc(Y^U(_[DgSCZ68e&TPF`m)BKb(LBJ +(Bk;/aj8&L`l@Des31Mcs2b/Ys2b/]&BDl4^UgCm:/"2V>$HO.jRW6K!ri6"rVaY6J,~> +^]+E6qtp<errr2Pkj[9dr;R!#rVuZlrqt1Cs8<T1rr;]..3fl[+!`"-Zh=%ls8N#t%/^&#q>^9j +r;Zfrrqucm!W;rmrs8JZcHO_iio]n#rrrE%rVZQlr;Qcro`+sjqu6cts8W)prs8W&qu$BjrVlfl +rsASnnF>Yqccb)8o`+sjrqmi;o`+g_qZ$?jrVHEkrqcZnr;ZFo,oS*R+)CKGrVlfn%K6=uqi)gD ++sA:bq>^EXrr;lrrr)j(rqZHfp\=[cq"t$hrs.66n*K<#hV\;3rVQZpqYpZsr;?Q7s*t~> +_Z0Z8p\tp)qsVLnS"u^iqY^<ls8Musq#CB`rr)lYrr;rrrtb:A,TIUA)'0blYP.bks8Dusrqufr +rr)lsrVulprrW2urVcX9qt/g_W1g&f[(XcHpAFmhrVc`qrVQHgr;?HirVZWmrr2rrrr33%rVcZl +rVulr!r`,srr2rrs8Muss8E#srqm'$s8MurrVc`pp\t]tm,$"%\[eoATVT0Qnbi4fqu$BjrVlfn +ru:e6s8DrsrVulnqu?Zls8Dlqnl?hF*ZZ57o)8Fb"8)JL+oWDb,(K@erVli\rWW9"rVliqqu76) +r;Q`kl)C8OTV%mQ[eK[uqu?Qm_Z,,~> +_>jQ6rVufo(%ge<RU&KY;g5sn`5]d5_9'R>ccsW'aSj-YaSa3MaSj7+aiD?;bK$4e'G2)i%L>(Z +cH"5Ra2c0<_T9^7ahu3=b08#NrlG&\3QB%S^UgkSQ#T_i5!DA-?[J*5XL5[S`5p'Bbg4Y_c-",H +`5U$Mcd'e^cd'_Va2Q$;`lH0Ab/ha)aT'9jaMu?Ba3)WObfRoE`lH*u`F$[-bfIT5]t:k`YGRnL +G@XW=4$G\a1d,&qTsM8C_8XF6aN2NFaMu6=`l?6=b/V96`kBL5`5U*G`6$'Be'C8m&0);h;Ua1A +b/D08ajS>`D@@$f$OL.bc,[oFaN4>&n]:aSs2tA_s2Gnm`Q,s<bKIi@`6#Zd=%5eQ8lK;Yg?\J2 +qZ$Nm_Z,,~> +^]+H9qt^-grr3#trr2p$qrm2)i7e21#lal#rVuohrVY+Cs8N5srUg+=rZN@%-QFNY,UK/NqZ$Tp +s8W)us7uWnrVuosqt^$^q>C6krrW2trqcX%mG$(4ce.7?kP>#Hrr`9!s8Drp!;cKjqYpHn"9/8r +qX4@nr;6NhlfR3ci8NPIf&HK$rrE&orso&,qtg0dqtg3iqZ$NopAY(9rql`js8VcldO61\*[)]W +r:g$cqZ$K`SfT*s+sJD)s7uWWrW2rrr;R$$r;$'\qtKm`rs-sAoCDG:hr4P6"TJ>srr2`n"9/5r +rl>%h~> +_>jQ6q#CBm'Dpq7U77pY[.s@nrVu`ms8Vins7?6fs5j7[ruCn7o_p*S(`3l.(*X\@,bsc&s8Dlq +s8N&uq>L?mr;ciprrE&sr?)%=s82Q_pA".0^ojQ.VR""Ybi@jQp%nR`r;$3drVlfr#QFc'rVZTj +q>UBmrrN)rq>U?ms8E&sqYpEpr;HTnquQ]mrVuos&c_XlkN_$SaMPQrY,7n`Z-DV6q$6fsrVlcp +rVc]o!WW/prrE#srrDfms!%I>s7u]po_m&Z(`=23+4U8br;ZcrrpcO!+;l.>,FSQ+rVli_rW3&u +rVZ`qqYq0)s8Vuoj.**AS"QOQ\GZ'trql`qrW)orrke\c~> +_Z']9qu-Kn)ZBO0qu6KdmE_D085rr5[^sApb.b^7bJhfMo>psO"NAC#aN45#!Q`FUaSs=&aN;T: +_SFb5&/c>r(^_#j&-dO$c-aeXb0.lJbJX>"r5pA1c-=S\c-=DP`l?-@^q@1SK4@J72*=T?D0:l( +TW,6*]=tql^;'Z_&]Dc8bK7iH`P]d<a2l?A`Poppau%;`b/q`D_o0dDbfn5N`PTF(]=bei\?Mp0 +TTbCqJSS@\5W:DJ-7VZ.Q)_+!_9'jDb/h[$`r<n1`Q69Hb0@lG^r="/bfS#JbJ;<C`7D7-&f22n +$F\F(_oBU;cc^kE&If-T#^Fn@ao9<[aT'Babf\*!aSj9]aT'6ra2Z*<ai)';aM5Qb:/jVF7oa/[ +j6H=9qZ$To!W2i3s*t~> +^Ae<7r;?Qns8W&rrsJDWhrX"^s8W)oqu6Trqu+qA,6.94s8/WA*?ZLS*?cLJ+X/!WLZJ=1rVl]o +r;6Njs8;ckrV6Nlr;Q3c$h`9"db3O:k3r'BrqZQqrqcTjrs/Q'rVZQis8Voms82im!rMopmf*[i +naPu1inDr1eD^,rrseu)q"ORZqu$Hkr;6BfrqHKfrr)ls.K9AIr;?Bjr;Zfpr;ZfaD^HPI+!aYS +rr;rsoX7@>+WW!UD!Uons7lWWrqud2r:p-^pAP!gs8N&uj7)[8r:AS*s8Muss8Mcm"9/5rrl>%h~> +_Z']:rVcNk&H2V,qsq\$S"ZgipAOshrr;us!<;Whr;YmX*rkm3s8&H7'c.]1()n,0*?Q=OL?&%( +qY^0hqYC0dq>VT:rVcZmrVliqqtp<fqYgBip%@\!ZCmkgXKK"Mce.1<rVlfp!WMuis8W)ms8W)u +r;cirs!RaAr;Q`rrVZ]prVZTioBkGebf%<0[B?F(VQ@J^mJ?SRqYBsds8MQg*;fd9rVufjqu?Wm +q>^Bms8Dorrp"8A(`4,5:%eJb%J@,",9.OG*GOd4q>^9is60FarVZWnqYq3+rqZKEWhc)LR\#k` +rV-<ir;Q]qrr)orrVj\6J,~> +_>aN6r;RZ5qtg3hrVcWeh3;>E:fqD:_8jX;b/M??bOWaS`WjE%`lQ6Db5BHbb08#uaC!0&^WaiO +'b_Q+*XiPg'GM)c&Sf86e'H7ZdDs8Qa3VcE`lQBKcdC4hccsVP_o'U@bJhE:_nNUfW/"kU7n,j3 +85ro/E-RY:TVnou[^`fY^qde&_ns=2a2Z*=aijM$s2QY0`5T^9aMl3@aiqoI^V@1XU7%-tH"U>W +7mo^05X%P+<+giPXKoOS_Ss[sbQH#/`l@trs2I%>a2c<DaNi&PccO2KbJ_E>ccF5L_84CCa&3N_ +*#fVLc-FGOccMJ-(D[`,#>2nZajIoF`l?*BrlkDblc9g\`Q?'9aiD37_82=@<^o5>9i[_Gn+m"] +rP8G`~> +])Vd/"9&/rrr2p-oASrqhrXV4qY^Bhrr;lCrZM%:s7H(^+t+WV+bV3e,T@aH)]U;>bP_;<rVcco +rqu]kqu6KnrqQKqrVQHfq>Uolk1J)-db!72i8j4qqUb`Xq=a@Glf[<hm,d$ReCEF;p\t9nr;Q^& +qYU'^p\=R]r;?Kis83$!s7uNjrVn5Ds8;fjs7Q<iqu?]U.3KcQ+t1+rrV+NK+X.sN-;`:bs8N&p +rVu'[r;Qrup\=U\r;HX(rS$E,qYU'TlMpn`q""Iarl4tg~> +_>jQ6s8Mlprr!H.r:\1,Tq.d`g].-Js7cHkr:0dbs5s;'s8)cqo_(os*uPe3INfdQ'Gqi.)CB%9 +p\=[^q>^6dqYU<frWN2mq#('hr?V=?q=F1OpZ^AEZ`'XpX0fIS`luoejm2C,q"ssbqtg0drVuos +r;cigs!dsFrqlNdp\"%CjPSV<c,df9^9ac4TVAKpdGO<^p%eOarr2ilqu?ZooDejis8O_Iq#(0l +rr2lqqtp0gpAP$hs8Ut%)&a20-G9$Oprm=k*Z?"A:"/Y3rVucos8V9]"9&/rrqud3rVlipp"Q43 +TUV=<U::$rs7uWlrr<#ork\Vb~> +]`8$1s8)iqrr)j.p=YgE<Cof#R`EFfa1fC4_sthH`rF-Zb59E_b4E\$`kfj?^<J>F+s%L2D@['f% +MBHb$PQ:8f@&*kb1+MTa2Z*<b08-0cS`tkaMu3:_nX.1aN;ZOc-a\K\[JZ-Iof*"1GLdO7Sd,qD +gmY1R@BkFUo12mX0/b;\[f5]pppF90=\L"Za-jBZ*170VkKN:JTPO1<(o\L3\Dm300iH]Nhinf] +>2>-cHF>Qbfe)Mb5TK^`r<q?`lQ<FbfnAW`Pp$HdEg(^d*9nXbe:j0^s:ZJ%M'^%(D3%Vd*/@X$ +PF$e)a:XMd`p.U`Q6'?b0%rPb0&tirl5#VrP8rSRoiK_8OZB_Lue4.rql`qr;ulprP/A_~> +_Z0W7qu?]ns82rtrVlfr"oI9@kMt:qrrE#qs3goHr>kq:Zn!+:+<ua7oU76[,U4ES+WDq-](Z.% +rql`jr;Zfr"T8/or;?Hl#5n;nrVQNipAY^$lIjP(b0\bqiT97gnb;q[kl2CsqYBs]o^qY@lg3s" +hV$E-d*U\>r:U'prr;uqq>:3lqu6Wn!rMurqu7-'p]($\o_8(;W10=.r;Q^:rVu`hK.%`\,TfPQ +icHIe-QsU*\G?1#p](!fs7Y^V!W;rqrs&K"rq-'erVca$gZ.Dcp[[A:rr3'!s8KG+J,~> +^]4?5!WE#orso&.s8DW7URe$RX7#ueqYgHErr)lsr?)(;YpL/!(EA+tnWtOJ*?H.=*Z6A#[dj.f +qY1$_rr2lp!<2lq#6+T"s8W&qrVnSNs8W#nrVQBhqtKU>c+'mKTqeNdY-G:@]Yhk:e_8m=l1=fN +rr)ckqYC!`qYC!^rqRQ*m,QsSe'H7Z_nEUk[BHR)T:MOG[E7(apA4OXrr3,ur;Q]oq>^?kqu79- +rVlcmq#C<jr;66EV3m\#qu$I5q=]=`(`+;77JYn_+rMRF*D*a9rqQ6fp](9fl2L__!<2ur%K?D- +rr<#oq>Bd2V59a^RL#:uq=t!irqZNlrW)utrk8>^~> +^Ae?5qY9sdqYq0+o\H6R:eOo#YJnW&bKIoH`p(SBao]f0b4`pT`rF(^bKPtZ&K)K&E7*$W&K)B' +(DRYn(H@o3eBlI\e&'2Ib08,Tbf[rC_84%,`P][3_o'UAccsSQ`P0!u]!AQ>VP'*#B3S#!7R]^4 +6UF79<E`jHEHcbaP+2HC!hGXBqj'"%Q'IMkJpMEPA6i,.6p*@f2`N`T3BKN"@sX**Z+%3P_8X:+ +_SjL8aiMH;_oBd;aNFJ*50CaY`Q-*Dc-=DM^Wj[4_oU*6KR%gFcd9_R^rFLB@1X.k(CMeK`ENuc +*#&l>RFTa,`QZ0?c+_9Ab08#Nn&YOKs2b2^(s't=`lG[&^9N]&>Z"*e;I5jOnGWCerVlfrr;FA0 +J,~> +_Z']:qu$?k!WN#orW)iprrqEMi9'"jrr;uod/G'ar;::P,:"H`cM@M>oX%4;+X8!L*>fkJS,3-a +p\Fghrr)`prr2p+p\Omgqt^*crVlcmr:9jkpZ^VjcdVjD"P;2Vg=lP\!o2ViqVqJ3!oD_drn.Y1 +eCE$qd*p\0nc&:_s7ufoqYU3j#6"Gss8D`aqu6ctr;HWis!@43o\,3q-mp>h+1h7Go`+ses6:aQ ++!MOI<@T4?+!)Ssp\+X_rr3)tr;6NYrr;oprri?!qtL$ers7rKl/h9slK@g<rr`9#s8MiorVj\6 +J,~> +^]4<4!WE#mrs\i(p<fV6S#N[Ao_e^fq:5KCrri?"r;1.+)AsD=bP;)8nZP>')BTk;)AX;=QM1.Q +p&G!irVZ`qqu6ctrVl]mrs/Q%rr<#tr;HWps8<r:s8MieoCqe:f>b;$VO=!JTqeH_WNED3\@K5a +pq?X<+1\ni['?g7W268^SY2jd^s1WtnFQ>Fp\XshqYgEnrr2p"rr;rrrr3N.p\t0jr;HTns8N&t +s8N#srVumDoDSUGP"?lB+X.l7p\jdbs7u]X*?Z7@'Hp@$+!DO@*h<!!s7uZo"8r,qs82fqs760g +rrE&tr;ciqrtbV4s6[UrU7e9NS#+$pr;$Bls8W&srq??lrl"he~> +^Ae<4q"jsart#,&hPXpk9j)1l\\uP+_85Z_rlXuVrlXoTrPg#'bKA.%$6(0-)6D'-dF+F>'G)#n +'bLc\&UDjQd)=>SaSj6_aMu-s_)9-L`l>a0aN;TGaN;QD`59F4aN)05_8O4)\[8`AQ%3RJ7Q`=[ +2E*TX5X7h3:Jt1n='/I$qc3Yp*`5a/8k;953AW67,9IpN0LT)aLRP0J\@]MqbKIoHrl5Mjb0%fI +a2Q'=_n`k&`le8()Tp%<`lH3CaNDZLcGIlO[:q3'%h9*OQHRC^rl"rk`!$&U*!m6F)AF,)&J'NC +bKn5VbfmuC_p$9Gbfn5N`l@Sj"NJF"`lS)#&]DZ)^Vd=(<DZRo:0)/!ht6aDrr`5ss8W#qqZ$To +`rCP~> +_Z']:r;?<h"TJH#rVlcq"OZPtiTU:@"9&8tr6kQis8;i=-mKTW,\$ZNs8MrnqpB1'+WhOI*[E'T +Mtd8Gr;6EkrqcX&rquZjs8;Zfrr<#tr;Qluq>($Xrs\\ll/pjYf[A'jcd'T-`XL&5b0/)Yf@f'A +lLOrIrrrB!s8W)rrr3H)r;?Hdq#16kr;6Els7lTls"=<Lr;ZTb`.9-W+XS$P+!2dWmJd%`r;Zcn +SK&gl,o[dP)]g;]p\FR`qZ$6_s8MutrTX=]r;HWurquQjrr2p&n^?jmnDrT\rr33%s8Dusq#(!g +!<2uq!<0k8J,~> +^&S-3!<)orqYq!&r:Ja3VOEpRg@kFBrr;?aqZ$3eqYpm!r5g3)&0;fsqYpL,qt^!2B-89<(Ej_? ++<6./s7uQls8E0"rr2lqr;SDJr;Q`pqu$Bks8W)rr;QZns8Muqrqu]kqY9m\p\O[UkMFb5a1]'k +XJr(nVP4!`rLk:1VP^8kYI(dS`6?immIg;Jq"agaqYU3jqtL-jr;6Kns8N&u$3'l$rr)clr;Zfp +rr<!#rqu`nrr+JIqu6B\_g`jQ+!M7:(De,;lM^Y\rVuilR2I"[+;P_<()eBPp\O^crVuQbrr3#u +rVZZns7?6hs8W)ur>>P6rVulnr:A+&UR@aBUSd8JrVHNls8W&gs8W)<s*t~> +^]4<3qZ$Tl')28&s7YBY?s?)g>*QM9bLFh[o>gpSrlbGdaN44toZ7!N,/qRIbKcgi&JHB,8^>At +`m<,]W_*X3(D@i*(D$UZbgOPQrl+oTs2>&ZaN4;%&'`58`Q63C`lH-Cc-4>Na8O4!ai208^V7@k +[^<BHZ`g@!PDF[3DJ3EZ;>s>k9`@fc:bPaF:esth>$Y`TFF]C@V6-i'[(!TW]tVM%]u8"0_T0sE +air#SbK7lIaiMNDc-cI1s2I@Gbg"AQ`PTI/c-4J0C(M$l)%@N"'GM)"dE'JJbKnXd$5X9p',)K"% +M*@(d)aPQbJ1m7`l?*Ab08)PaMu3<`q.7q`l5p:aNDZLb/MH=]Y:b4=&;+N7U0iKi:QjFrVcWeq +YgHmrVHNrrVQKja8^Y~> +_Z'`;r;?QlrrE&qrr`9#qYU9l"m+n8j50#!rrW/sr;?Qor;Za!s8N#qr8IVsqu6DE.2jWT-aisO +rqufqs82]TJL;Q^)^-:K,Uh=Crqccprr2fp#6+Ptq>1!dqYpd!s8W)ss8W)t"o\Ats8N#prrE#M +rtYJ/qu$?fpA=mgrVlisrqucpr:g!aqu6`rqYpEjs8FtUrr;urr;-6)L+"Dk,9%gL+sA-M,pSHL +qY^<lqYg1;+W;IG,8hhNk54rQrVQQls8Dorq>^Bgrr2ifrr;onrqud$mFUXmmd')err<#t#5nN# +p\aaar;Zfrrqlcq_Z,,~> +^&S'1"T/2ts8Muss7m3(pu/3DTpqmon,!"]s8W)trri?$s8N&trW)uprqcZerql^;qu6>@,8215 ++L1nEs8N&rs7uKPJL)?W(`XA6+!fM;qu6m"rVcZlrVlcq!<2ut&cVb-rqlTks8N&urr)fprVZZo +s8N!#rVlfor;QWqr;-Eds7QEcrq-!Y!;?Bc!quB`r;$Nns8W)rrrE&qrs&K$r;Q`rrr2rtr<<3# +rVQHjqYrMPrVc`or;-3&JgM]]*Yob5)Aj>**Z^.9qYgEnqY^"5*>KJ2*>B]=k5>)Us8N&ss8N#t +q>^Bjrql`prr)lorr2rqrr<#uq?lZ+Tr=WQT;\^NrVlg#rVuoos82Efs8L%<J,~> +_>jN5q>V90qYL!_s8Mrkk.5D-9L`-2[`6J5b0%g)`r4!Y`rF*[b5KNeb/hZD`r<sW`q7@L`[\sO +c=.Fr,o.8\c+h!+bK7rId)0Q5&etuo%LrdM[*d%9_nj+(`Q63Gbl#U"a2Q-Aa2Q$;b/q`IbKA#T +d*Kt\ai;<@rPfPmb0.uJ`Poa3^qI1aZEUO8XfSS+ril@,s0*$;Yct73XKJn;\\5bqa3Ms/bX0Lq +a2Q-A`5'4-`PopBcHaVWd*9eYc-OVV`lcBD`l?!8`luiTbfRrIba;rR(D7W")AO&+)AF"tD:?SE +`6?<LeG^%")BKt3(0nf+aiqlGa2cNF`QZ6DaNDZLb/hTA`r4'[aSj-XaT'BbaMl-<rQ5\maiD00 +Y'jMZ90c-XEP_#:rVm&toD8.Ys8Mumrr`5squ+S8J,~> +_>jQ7o)A^hr;QrTio]I_g&:pVrr;rsrqQHhr;Q]ur;$0dq#C<ls8;]l!<;urs8NH(q<0+I*$?G$ +pAP!i(]XL7rqu]onWt[I,U=KU+"ZdUqYpNpq>UEorr<!#rqu`mrVl]oli,W<rr2`ks8N#r#lO]" +s8Dfoqu?Zp48f*XrqZTks7cEjr;?QorU@aU,p=TX)B^.C+<`0\,pOEXGl7L>rr2fpqm.[i,pXWY +ZMaY#p](6ls76-hr;QTmr;6KkrrrDur;ZZhr;R#[j72L&j4<)ds8Mlqrr2rtrqZTnrk\Vb~> +Z2Y@6qZ$Qmr8FTKT:hjShY6sIrr`6"s82fqrr2os!ri/sqYgKprr2rtq>LBor;Q]q+T1FJ)\s5. +9(W#]rr2rss8W#os7)C'*Zc=>)Ajjcr;HWp"oA8urqu]irrE&srrW2urr2ourr)`nqZ$Ek!WE#r +rU0UYrVZZfrsA]&rqufrr;Z`qrr"/@rr<#ps82ijr;Z`ns8W)f_gWdM+WD.8*#Tb:,Tn-J(*[nu +r;Q^/r;ZVt,8;+:)',mVr;ZNkrr2rhrr2p!rr;uorrE&srVultrVlg/qu6WopuSEFV4=3OS[.5P +rr0)#J,~> +[K$7)s8+&:s8VfV]5_%P<*!P%\\cV;a2,^3_T9g<`Poj>c-OVVb/h[$`W4*Yb5'*Yao'4Hai;07 +_@@A#)Ab<YbJV'._na++aNrVeG74ch'b_8k'[+qGa25j1bKeMZai;<;`Q#[-`lQ-:_8F@:aMu3< +bg"B2b5]QZ`qmaZ`l5p7_sP;>^]2.M_ZRlt`lS)#rQ#Jf_8!^t^r"+6b0S>TdEDO8!6tMc36&eW +`Qc6:bJVEHdF?=7B+Yaq(D.Aq%1W[V'G_Gm%T^oq`PKO2bKc4]%NQZ.&!PJbdD=)MaN=1t!6Y;^ +#KFp2ccs\V`r3jr`lQ<Hc-"&FaNi2W`5Td9^8>:7;+F;W>(OZ]rVccqrUKpfrPnkf~> +YQ"\'r:U'h&aSKAki:Ums8W)rs82]nq#(-jrr`8tqu6BjrVlipo)9d3rVhZo,9J9\W;lhrs8Mrr +rr<#qq>^Kd\l'Uo+sS;'rr3E'rVuorrr2rtr;6HmXT&.t7K!2aqu?Tfs8;]ms7ZHls8Dfos8Dij +ql4Zc,U4NU*Zl[R)_+I>hRb*_B[unXqu?Tnrr;or9ICf"+!kUms763iq>^Kcrr;ltqu$Bjrr2fq +rr)j#rVZWko_JIc#l<?=na#]*h=gjJ"TA5pr;QZp!<0G,J,~> +Z2ak$s8Ni0s8;/kUS4?SW5eQ)rVQTls8W&ts8DrsrrN,to_njjo)AXg%#GfA(`jirs8Dutrqu`p +&Gu8&s7*Qm(`F82*1?d*s8;lr#Q4Q!s8W&qrVlirrr2rsrr2rnrr)j!rr;utc2RP=%/g/(qu?Tf +s8;]ms7cNm+oV9;s8Dilr2O`a+WhaC(`=G=(aqq4gUA=NA'suLqu?Wort,,,80JZ\(E[2Zs763i +q>^KcrW<-!s8Drpru:t9rVZWjqu?]ns8W)mo[B_6UmIaIVonW.q#.>pJ,~> +ZMu!Eq"Xmhq"EjhKk"7b='gKe^;n.1^r4L8`l?!:`le;)!m8U*qo8ZW"Nns4b0'=s6-$pfCCMF/ +*u0R^aiME9^;.M#b/qfUeB4.=&/Z<&&;/TZ`kB1-cd'qabJqB8aihN:b07rG_o9dBb/V98b08$+ +aSj*\aMu<@rlG)]q8iNWiQ+g;aMl!1^r47<d)sPR`QZEAccX5RaM#R6a2c3IcH!uLdY(L.&/6$# +)AsM0#88b+]UfQD:U\^"a2u08`Q63R0,5*8'b<gTd(IND_op0ma9]r5c-4DSaMu3u`Yuq@bfn5I +_TU0Db0.W4[#e]s;Em`QBq*W@q>L<qrVQKj[/YX~> +YQ"_&q=X^crs&8Tkh>7^k5G;_q#'pbrqZTnrr<#]r[Im80-MGX+sZ[Yqu?Zqr;Zfrrr;uor;ZK[ ++s.sL-(k,8rVu`oq>UEnrVlosql0Q"r;6?js8N&rrr5+[rVlisp](9kqu?EhRj':),8q[C*ZuIO +<0bu2s8W(3eG/tAs7lTks8W)sq9C96+=&0VbQ%V<s8;]mn,E7b!;uin!W;rprrE#sq?m0#p\<b3 +h<*h]g&(dNq#:9ks8VusrjVoX~> +Z2Xh'rr3]3s8DihaJ>c%Vl-p"o`+sgs8Dutr;H]pqYpHnli%7kmOT=q()n=`s8;lr!;lcq(]OI6 +qY^BblPgWX(E].Crr2rqs7uWmrVc`uqt^6jrr!-%s8Muqrr2rt^]+62s8E3%rr2imqYgEorVc`r +rr2pBq#CBlqZ$9dRNNpu+;Pq4)&sM?;O#Z.rVcY+de<P:rqHEirr3Q.pWF[%(E4>8aT);9s8Dcn +nc&Rgs8N#rr;QlurVZTjrt55-fZ9ndS>)CEU=K&7qu-NkY5a"~> +XoB%2qXj")RUol!='BIS]?JL=bJjJ#s2b5[s2>#[b5KE[`rF-[ao]f0b4E\>b1+QQ(a'_3$d?u8 +`l6!;aN;HEcHOAPe'QVW'c.GoK%/)baM#^7c-Xe]c-Xkgd`fq_dEThRaN`&TaMYp:b4is[b/h`H +b0e:,bgFh_b/hTDb0%iIbK7cG_oKa9`Pfa7`k9=8aNDiMe:%c=%1rs]%20Bb'Kp]Jf[n^)5HN5\ +e^DR^`lZ9@aj-ss(`45,$`DS*`QuK?ammIP`rF-YaoKZab5THrcca>H`l,d1Q$cJ+8l8&YC9-%O +p&+gnqY9j^qu*u'J,~> +Z2Y%-qtKm]qu-Kn$eXLuk2c(4s8N&nqtL-irr<#]rY"k&+=.pK-D1>9rVcZos8MurrVlg+rr;qh ++s\?X,0'Z[s7QBk#lO`$qYU6js8T5#rVZftrr2lr5Q(QVs8Vrms7lWkrr2rppg,3`+!_XJ,:=[B +Y2oESqZ$3fpAb!hrVH9gs8;fkqu?ToAge`E*@G4fqYpBks7$$arrrE"qtp<jrr3)qrVZKirs.]G +l0%9dm+M:9!;u`o"9/2prjVoX~> +Z2Xn(r;HWp'E.e)p"-%:StDjqo_%tYrr<#trVc`qrVQTms6T^urUd!-+;>_:S,`Ecrqufqr;HWn +rr<#t$i6>3*#]h<_Z'E3pAY'pr;QZkqtp?lquH]prr2itrr<#trr<#:rW2uqqu$Trrr2lr4oYKX +s8Vuos7u]mrr2rnp0&US)^#e:+=&%7XQ0-Pqu?6ep&FmgqtTjas8;flqu?Ql@NlU*'d-]Oq>U9j +s760hs8W)rr;uuus8N#tr>55,rVlisp@5PdTUqsNXeOMBqtU-hqu3buJ,~> +YQ"V$rr3r7oBb,-AmA,-<dD$a_:-]Rc,RcEaMu38_8aXraSj-YaSj9Pa?IkoNY!3J)A7MJ`l,g8 +cI'kZb0.uPbK.u\Je8k:'agehb/q68a3_uSbJqTGdF[!tcdU@hb/hZMdEThQ`W!sY`r*pVb5TTb +b0n@-bgFnec-+5NbKe>Sb/_N@^VRP$bJM0<^s0d<bgOkb4VA/9'aPKc'+@Eq`RiSff#cF\cH+A\ +dE^ClaMu*9d*:06()7]#(.Q`sbf.TE`q%1U`l#^5`lQ<HrQPAeb5TBp_8jI-`PK$eBi.8b;,Lq? +[G^?=qu-O!qtTm[q"t#us*t~> +Z2ah$rqQQkrVm<&f&lD\khc@>qYU0cq#BFSs8=AB<$N2&-m@jPs8W)urVucns8Mllr;?N`-RBiZ +,Tlp\rVZ]qq>($grr3*"r;?Mmr^["fs8Mops8W)urVZ]prr;orq>^6fOWPPi+<)dT<ho!KpAP!f +q=t!`s8Dikq;R^prr;urqu?Wph]j?i.3TtCs8Vrps8DNfpAb-krqm9+qu?]qs8V$;md93"jjEu* +!;u]n"9/2prjVoX~> +Z2Xq)s8W)srt"o&o[BP4V449Xhu*3IrqlZmrr)orqu6QomJ[Ikr;';5&f`/;kPP8Y*<,j8q>C9l +qY^<jr9baM(`XS8q"jses8Vrkrr)fq$N0f!rVcZmrr2rsrr!!!s8W)tqu?Qmrr)lr!<;`ks8V'W +rr)co"TSK$s8;fp4T53XrVccos7u]hqMlI2+WD4F+]Y<'n+Zk^rVQHkp&G!fq=id1f_tjLrVQWn +rnJP7)'Bb:Y5\Ius8VHbrVZlsrVc`prVmc4s8Vlefr(I<TUVOMU#u4HqYpNos8W)uriuKR~> +WrE\0o'P&-Bjt+5;d5j4`mN2Vb5TE\`<*lnaSs?^aSj-Ga?dkjfK0cW)&WRma2c0=cI1Cod*KqS +_Sa=9b7#'t((pc%cHF5Oa2,a=ai_cG`Q$*Hcd1(fbfIfFcdC"[`l6$?rl+lVs2b5_s31Je!mJa* +ouR0QilD,BrlkGerlPYjbfIoG_o9R3_oKg=rm*RRb0.cQbLCG7%iuGo((*'Qa2cBMccaGPfZDL^ +a2u`CEja<@aN)?GbL4!0()eJ:':@G"_SsU8o#M9[_8!n,aND`Occs_Yb5TC%dDs;I]!7B"9MIuD +8mcPXmIL&Ls8Durqtg*_qYU6!s*t~> +Z2Y+/r;QWkqtg6irVm2[f^.qfh>I<QrqQNUrYPV6rr)f2*?u[I+FF.es8;lrr;Z`mqu6Qo(&P]h +*$H:ENq`GNpAF^`s8;lpqtp<js0;P'rVlfps%!(bs8W)ur;-Hir;QKap\+RZs8)]kB.+oB-rcl) +qu6Kks82Kds8VckrqG?29ID3Jq#C?nrqZNkqM6F7*Zun,p&+jgq>^$br;Zfrqu6fuqtTsZrVm0& +jQlC$kjdcar;Qosq>C3fr;QluqtpB%s*t~> +Y5\M#r;R9'r;,l\RAZXMVq1hCr;QZnp\t-knGX7(rr2lo^De76(`di#rr;rss82clqYL3irtYCB +*>KG,)iF=cs7ZBcqu?QlrVZWnrr3-#rVc`prr36&rVc`ps8W)ts7?3is7QBks5EqWrVlfps"aTM +s8W)urVHQiqY^$Wo^htQs8)Zg@j2m.,>k&sr;Z`qs8Mfms8V]grV#--80T::p\t1)rV6?ipk0_# +'Ghrbo)&IdqZ$*b!<)or"98B!rVcWorr2p:qZ$HeqU;:5U6hCMUnR;Tq#:<lrVuops8MurZN#F~> +WW*\2o^Ch]E`Q=::LBI-air&Sb/hTBrl"lYrlY8^rPn?J(!4P<a3:1\'GV5j>1CO1_8ajJf$r"E +b5]O3a3'hW%2K<WD9g8L^rF=9f$2I]_S3e'aN;ZNc-48J_oBpFc-",I`lS/!qT/TWs2Y2[ouR0Q +iQ+I.aNDZMc-+>R`luZLbf%HEajJYgdF6Ij`QcKNeOU;g'-0Dpb1+h^aihZ>a3`A]f$VRFAh=Du +Cs1/Ebg"5NbL(#;%fRFP2UBRh_SF4_a9T`&_8F73aNFG)!6Y;^*5p1A]t05)91qQA>[VBtmIpS[ +r;?Nip%nO^qu*l$J,~> +Z2Xn&qYU6k"9&/qrVca"eE?2[h=LUF!;uiq!rVrmp\b!hs8Vims8W,u%fQ<s,p"?T/D^7'rVHNl +rr2os*;oL*rq];..O$)`jo5;Qs8D#([-.5^s8Murrqrqur;@3,q>U<gqX*I_Rt+m%,qUC0rVn#8 +IN'@K*-2#Rp%SL\qZ$Tlq"+C(Gu?+9,on"-p&+[brr3K(roYa[,9\-RT)\cds8VZhrr3-#r;6Bj +r;R?-q"44Wr;Zfei9p4,nEnm"rr33"r;69dqtU'g"9/2prjVoX~> +Z2Y"+r;6Hlrr2p.rqZKgq:_F4T:ht#oDALbrVl<dp&>!ks8EW/qjS]F*Z6<XqYpKls8DrrrVlg: +rV-3gpdc/E)B9mZrVuTkrSi%+jS&KNs8N&urV6Ekrr<#urr;rprq6<err)lVrr)lsrVl^+s7lNg +q"X1:^R':O/0?5]Q2U_<p3IGm(Dq,hqY0jdqu6Wqr;#sY_f\a%*?Gt4;tU"brr;utq>KA#+rV:8 +*h<90r;Zferr;rprrrB!qYL*grVmi2s7*RaS"6%?URT@#o_eObs8N&uqu?ZprVc`%s*t~> +Z2Xn'qu-No(&e(1rV6$KfWAO[9i>,H[DgA7c-4?0aSs?ZaSEjMaT'B^a>(`YHjgE!&K&1.aMPX0 +a3;cPda#qM[_0]-/I3F7&dlCubIYg=\P\I+d*KtV_SO.-rl,,\_8!b$`r=*baMu6@bg"E3bR2M6 +`l5j5_8!b$`W!mQaSj-<a9BT"_8XO>rldmZb1"hedDWekH=]Sf&Jkgug<\*mcsHqh&I_n"d`0,E +^;8%<bK\AiX]R7d$5<sV3lo=W`R<,X_p?.2)BBb0$[0h6^rX^haS<dTaT'E^bSeR=bd_jk91VHC +>%4>gl1k2Vs8)Who(`+\YlB4~> +Yl=_&rVm'#s7uTlrr2p&pYFonkM>(nrr30$r;?Heq"O^brr<#orW2usrr3]3rVU@S,p"-Rc1h25 +s8Vinrql]mrVmc/dO6=Z+X1Y#qtg?jp7rrW/6n7]p&G!hs0)DrrVZQhq>'R2\W^u41*@ti,UOZU ++se_(r;HThX"#86+sZg\r;ZWlrqQ<^`.00]-lsBT*[DpUlMU\[rVlins8/-*+<i0ZI/![@rVc9c +!rr8trqQTlrqud+qtKmcs7P4/pA"4HlJV.0rs/Q"qtp0cr;6Bks8KJ,J,~> +YlF\$(An(1rVuoor;$*8U7S!OTWd#Bqu-Nnn,N.]!WE#srtPJ2qdplj(De+5o_eRcs7lWor;QWm +ru1RV,9.=6*+f*Gr;Z]fTcb=&=H(Jrrr)fqrqQNirW)oorq6<err)lVrr2pCrVQEcp\4.)[?#-# +/fQ#U*Zl78)BL2fqu-HdV^3?$*[14Vrr)jBqtg!'INTaX)&F>/)]Kp`r;Z`nrVucpq3)^7)^->M +p](9lrUKjfrVl]o"TA8qr;HWp&,Q%LVjX-IR@BkE_ts3*rVHNurr;urr;HW%s*t~> +Yl>O=s8Diiq>L<ms82NSh5G!h;cHS'QG(<;bkoQ[aSEjOa8s?&rlHh7a3@*]'G2#mZI-n7aiM6> +`PTd=`koR7`N0Ud',M-NeA],B`lW`9#STF>VT@'^b6c80`l#X-^VRn/qoAf^c2PreapH//`P]O, +^:qA$rl4cTrPmj<:rU2ca3E&\dF$(>Qul7f'a5*W&f2;t(DIBuc-+>WM@pU:&e*@AbfRW:a2ZEN +V.U>P%g<7T(`jD#^W+C6cHjYMda3.E',;5h;o?\sa3!kmrlY8^s2P&W'ZS5:b08#D\X$r0<),qV +=`'hspA+[e"oJ,jq"O`js*t~> +WW*)"r;Q]nrrpj0jlkshrr<#q%K-&$q>L?nrqlTjrVZTlrr<#gr\^f)+<MpR->Bgdo`"mes8)Zn +qu$Elr+RAu+W;f[q>^Koq=e2@)^HUT+t.ZEl1b/Rr;Z]nrr4nTs8W&os8Drss7lWkqu?]nrr;ro +rqlTmrqu]or;Q`or;Q`qrr;los8Mrqs8N&ns82irr;Z<d-Md]'c*!.E-R0r_,pji^*?H=G,:+HS ++Wi30s8Vl],on*M.'`UJrq[9)rei<N,9\'R,on!M+s884qu-No&,ZD*q>)Ed,#ZP^qY^?mrUKjn +s8Mlgq>:'crr2lr%/U##qq^H+p[7Y4jR`BN"oSE#rr2ipqZ?]prilEQ~> +Z2ah&rVuosrVuos%/fajUn+$MW7U\>p\k'j!r`0!rr2`nnGXO.WZ`5r*>ou1Yl=7ns8;oqrVuiq +s8Mk+*#BG),LZAdrtG5#=WS7t)^-4HF0k!#qtg6jrVlfr#6+Z&rVHQmrr3i2s8;fps8;osrqufo +r;Zfqr;Z]os8;forVmE*rVulprr;utq#C6ks8;ofr[7aBs5V8$Me=4T+WVUG*$#e3)AsM7(D[l+ +-i!`ApZ`k<)]L*-q>^El,l``O*?Q18+!275(`4&4Vu-Jns8MoqrV6.3,90FtrVQQns8DKes8N-! +rVZ[3rVlisr;$<Ne"WG,Tp24>XO$V;rVHQnq#:?nrr)lr[f:j~> +YQ"b&q"X^ar;Rf7q"F(%DduX68m%+_a2cELbg4ANaiVWEa2lBDaSX!JaDfI`%M9Eu(DKW*e]#\T +]u%@uahGI(aO*Zq(`Nu!Zc^;'_8jql&e5]i'+#+OR*=+/b/h`D`6$$=`Q69D`m2WEaiD3>_o'R: +_o9[7^r*t)bf7T@bfIrMaMu<A`l?'<a3)KCaNDTK_TBd@b/VQoaAKsmbIXa>GZ,"V%1a-h()75d% +M9Hs)As:s#g1?8bK1/*(_ROIe()OX`llnJ'bM2o$kEjW&g/>7'7n3Ba3W,OaN)BM#7q;&VpE5t` +QlZLo>i#rcd'_SaN;NBa2Gs<ai209U5`2N<)c=d=aRRBqZ$NnrrN)prqHKjY5a"~> +WW2horr32nh=9gljl?@?%JTerqYpHlrr;onq>C0hrr<#gr^-9`-la?O+!W:%ZM3thrr<#qs8Vol +n/ro%+Y6:Xs8)Qks7%Q],on*S+=/6T-<u\Wp\k-fs8DlqqYU'frVucnrVlftrr;us!WW/trs8K! +s8Vuprr;uss8W&ts8W#srsJc'r;6ElrVZ]mr:0b6s/7S$,p"*P,:4QV*ZcRO-m:)d)BpXS,:D@A +rr;k!,9n*PDtsA.rr489Pp7:n,:"?R-715\+<ster;HKis7lWoqRS/`nc/Las8Duqnbrplr;Zcn +q"OLTqt^3irsAGPjlu:"jmh0qrr<#qs8N#t!WN#qqZ6WoZ2]=~> +Z2ak&r;Zcqr;RW5q>/+)W1TWY[.""op&G$irVZTms8W)rqu?0b%fPs$+qth/(`aqdYP%Jbrr4_N +s8Vrlm2?l`(aVZAs82]ns6V'L*>KG6)BTt<+BFKEp&+jbs8Dlqqtp0gr;Z]orr2ourr;us!WW/t +rs8N#s8Vuprr;uss8W)us8W#srsJc'r;6ElrVZ]mr:0b6s/.@n*Z#V5*?Z7<()@o1+r_gL&fDi1 +*@'D6rr;do*ZYt<D>4)-rr48:PTUha*$-";+<Md<(E?EQr;QQjs7u]pq7%fVmf31_s8N&qnbrRe +rqZR1rVQKlq:DRBT:hU<V4>3YqY^$^s8W)tq>^Ko!<)lq\,Us~> +YQ"_%q"Xa]ru1e"gm;JQ8OZTpYK"f'b/VHA`5]m?aN)9@aSX!Ja?\"r5SaqK(D7;m,*:-ha2,X7 +_oTd3b0120+r_UZbL=5;b14iS',qPr'+>B^$ku0MUs.3:b0eDPa25g6e'-&8_CWaIaiMTFb0%oM +dE0MO_SjL;`Q?9Gb0.rL`Pom>`l?-DaMu6=`m2WEai29ia9p(8%M]`k%1`mZ&H3>0(D7Di(D75s +,Sq$uYJA6*dm"Zi&JS9uf?2@`dEQhD&/Q#l"pY\U-Pm[62:':]aNDcCaj/.o#a<Nfa2?'=c-+9# +a9fo2ccjPRa2Z$;rkK)`^m\Y38kDNC>$R'-oDSF]rVllrrqZZmrVHNorO2`V~> +Y5\_*r;6Bhrr2lr&,uV,s8V`Bh<s[ohspaHrqcX!rVZZmr;Q]os7-(hs7)$p-mK`Y,UXNYOmMc; +qZ$Hhs7_'p+<)@J[K$1's7cN+,9J<YV/n1:+"&BW+tP0_Z2++ms8N&trVlZls8W)tr;Q]ms8W&s +q>^<kr;6NoqtpEmrr<!3rqu`prVuorrr)irrVuorqZ$QpnbtWIcmKnU/LDPX,:+]`,:FpMLm$8t +,97dJ-cGr_s8%j&*?cIVp%8:`q=a^B+=/$Q-WubkY9P57,q7mRrt#&'s8Vokr:^0jrV6Emq>]s` +(]4.1s8DfhqXaF\rr<#kj6c:'jR)6en,<7grVl`krVlotr;HKnr;O#%J,~> +Z2Xk'rql]rrr;usrr3H)rq=a6SYMmSVTJ<,q>L<qr;Q`qrVu3_5QC2.+<_[=*ZZ@>,`h9br;$Bj +qu?>:,Sq%-*jP\Arr;`i\/Z;.*M@9t,T.aI(`atMD6<L&r;Zcrrqu`ir;HX.r;Q]lrr;opq#:*h +r;?TpqtpEmrr<!3rqucqrVuorrr)irrVuorqZ$QpnbtWIc6=)>,Tdm=*ZlOI*?l\8KoaTe*#02- +,K'HZs7hQq(E=>Do^r1`r;$<J*[2IC,?C#]WZ2ln*[K\Crt,/*s8Vojqt0jerV?Knq>^E_rr<!" +rr)cmrtG8)o#7DpR\QLRWM[f0r;?Nls8W&rp](6l[f:j~> +U&Pr'oA-BZ;c$%]=+d]t_TBj@`l5s<`Q64!aT'9NaDf;Ja_qe2)%mc$((1e#bfn>RcbmWGb[qh5 +)&<pPeAfAG`Rpt!'H%LB=:l)N'bq2c&I_R%g=4^#aNV`LdEg+]`5Ta9b08#RdE^(\d*'kW_op9E +a3VuRb0.rK`l6!=b/q]Fa2lNGaiqfDb/h`raAL+%V[a=U-Q*?p$4dd`&J>L>AoP/N&eboh$CAcT +bg1;F(DmZ"fZqsi`Pg'5"VV=Q$9*"<Q4t5T(_FC.b/qT<aj%fHccahfbJ;3=_pQ`Oo#MolaN;WK +b0A8Sa2kj$Z@uXY6;'^><FhWWpAP!fqtg$cs8Munrr`/nq#.]%J,~> +YQ"h+r;$-`qu6Km!ri#prr32kiT9Cjj5Tk6#5nK#r;?QnrVuEes8PR\dsrbg+rMaO+W_kZchIJ1 +s8W$C*?ZUS./!W=s8W)kF<2_RFo(t-_hq23-R0cY.46L&q#0scqRaDjkkOoMpAb'js82]n$2OT" +q>^?lrVc`nrVuj#qZ$Tmr;Zcq#5\8qs8N&unbt`PqBR4-,oA$a8SO<pe*m//p](!_Kd.lc-(Xl1 +rVtRp-6+-N\c)Bus8;oi:b#VLlM^GMr$EX1+XX/ds82fq"nqupr;$?jrr`9!s7u3a*rl09rr;ro +qXs[Zs8V?EmJ?P9kLS_ls8W#ns8Molqu6]rr;QQor;O#%J,~> +Z2ak'q>^Hm)?0[9rVuorjhRRYSYE'kmJ-YXrVZWorr)iqs6K[as&S^:H6=+F&g&)5)BaOTo`+I] +rq[ZN(E4D>o)J^hs8DJ*(EOW:p\46oL.N:,*?,tC+X)[6r:g0d\[g/Mp\+LWs8)coq>^Hmrr;um +rr;foqu?Wnrqu^"rr;ips82`orr*,ur;?Tos8VWg.0'&`)&F5(+tQ/oNNgaqq"OL]p%3bS*>fog +q>U?mf,Z"N*$)Qfr;$?l')#-N=/b<Zo^qo$*#BJ8V#12irr3/qs8DiirquctrVu]arr2rtqu?To +rt>>2q>]llTpqXDR&Q^fhYdBMqY^?qrVZWnWrIS~> +TDo;mkeE!Y8OuT[Dlp_P_Zn&ua2Z'=bkoK]`pq,]b0A/;C(q3m$lg-&&J8]\dFZ:cdb,*C*$?15 +e'Z.Ub0e^F&Ju-cf[S6>CGcG2%1<RX'btlCd)3oDOI!5ibJqfKe'Zh!db*+"dacdeb/V?Ba3VrP +bfe2OaiDKB`6HNF`l\5$#/nO$bK.fJo#O\NcI*1=+!V.+&L^7nR^UJhcH=S\f529A&.E["`Q-E: +&fq\u%%Pqo_TKmEat*ucMoO2gc.`dF'c%F=d`]MH`ll0BbKIuNbfIiI`lHKIb4E[t`lc9<`luZO +c,IT0]r,gQ;+jAE<(q;5i;!?Ms8Dccq#0se"o\>np@eHos*t~> +YQ"h+r;$0cqu6Ek$i9eps8UI-k3h<ih"^mLrVl`nrr<#grW)`ms%<1JROBU,+<i-P+sV!2s7u>V +,paZ\+IW3-s8Musq'md2,.77Hs82ion"t=R.j#rX*GbKNq=cZk+sn[1D1\CdcKkE)p%JC[rr2p4 +rr<#qq#CBnr;?Nns8Dlqrr)lsrV6Bl"TAAts7u3a6iZj/+=&$ZU\"<Wqtp6irVu`os7`00*?Z\Q +qu?Tor_"+V*$0+pq>^9fr;OD"o_&7Ys8Vq2+<qsOE:s8's8VlorVlg&q>L3bqu6Kms7-'hr;HTo% +fZM.rr;rRjQuO/m-WEPr;Zfrs7u`oq>UHorqlcqZN#F~> +VuHktr;?QnrttY5p\sf\WLTZQUo`VMp%\C]rr;urr;Zf`r_NRhs8W&mhNfB2(`OG;(*+K2Y5\.c +Q6.+`*ZC=@rVuors7IW\'-4CRs8VurqWstu*@2RB(`$`Xs7u@B+WV^M7VI4=YKH&(p[e%Up\t0l +(&n75qtL-jrqu]ms8W&qs8Muss8D`lrri<#qu?K^rX/\t,T%I9-(j`&p\st-s8Duos8Vb^)AO,4 +FSc%9s8,>%,8_A=q"t*jrr3bKo(DVRpAb*cAf2O()f,'Fp&G'fs8Drs#l=Puq#(-gs8VZhs8W&s +'`@k+s7ZEIXeMAWR@:"FYPS;!r;QQm!ri/srr0&"J,~> +Z2Xh&qu?ZorVlopqu6U4o'b+MC/Ii&=(Ir4\@fVo`5]g;`lQ6Db3m>U`k'(5eCVN`%209i*[DL; +'317Pe'WRW)AjG(I+?K^`lZfc()mVgPK_4qajee]KO"p"%2BTd:sRG*`X`=^%Lt0jB7uSSb1b@i +bKn5QcH=ARc-FGOe'H7\aSs9ma2Z6Ba3)TG_TU'Ga3MZG_stfDc-$Y5+;l&ObKS8[d`p%YcGmuN +c@ZZA'+e$`a2H9U2[gN3#ZT6pb.bU+b)XQfb0n;ZeCIM.(_dK\c-<lA`k^!Fcd'qS`597+aN)KL +o#UjN+2l1@bK7iGag\dE@8ous:Jb.nEmNn?q>^Knq=s^\rV6BsrVQHfq"jrus*t~> +Z2ah&rqufqp\t<jr;HWp#2nV%l/:@\q>^HlrVlisnc&Rg;>g:js8)>b:`p\t+<hpO.7gT:,9S-O ++=I-es8;ips2ZN.-8+N^rVu]krU^'brk;8[+sn]0s8;R6,pjfY-m'W\/gMbh:2Y6?Z-*(CrVcBf +rrW)ts8N#trt,//qYgHlqu?]lrr;cjqZ$Tcr\+-DBIb2J,K9Z^rVlcos8DurrVui@-mBf[;Z-Rm +q"]sp)^-=Sp\Xddq=jddoDAOe(&Rk#W#m6.*_Q5+s82ims8)Hho`+mgrrW)ms7-'gr:p:(nCHX` +mdKN)i;*EQq>C9mrr)iq!W)fls8N#&s*t~> +VuQbp*<-!<rr2iqrV?6KV4a6PTVT'mrr;omr;Zfps8VHbrr5jnqZ$TknYAet()Il0)]BqgWUq5L +)&F/7qYgHmrr<#:+;Z+Kjo>>[qY^<_s7Z<#9HtGt,4bd3oc5+r)]9h;*$H^O+Wj<kF-EfKrVQQl +o`"k-qYpKmrr2rtrVu`ms8;cos7uZoq"spfs7-(AqY4PG(De+.rVufor;HZps8DrsqoL!!(`cBK +s8D`eN?/lW*@^a]r;Zcos8Vcjrr3`0q!k*r*#f\_p&+jgs82ilp&F[arr)iuqtU3]rYGJ4s8Mrp +s8VTbaJ,AtR[TkCUs8l<r;HWqrr2p!r;ZfprqZQorjMiW~> +X8`;!qYL0hs8VuprtkS"g:(j':KLS#Ejrj&_na42ai;ECb0'.nE5oi7`lQQVc,t`!&JH$%)ANl$ +09G#u&Jc&m%b]7Q`5TaDW=fdZ'u\P=`PBR<_Um>qTfa>4)%Od6aN">o(DRGr%1j0k%Lre"9i>ha +T?kQuahZ3HccXPYc-4>SaiDQBa32KAbKn)Iahl$8ccbk":W1IQ*ZQ"-Us[N4c-4;M_TBj:bgNX3 +)As2Ccd'GHd!-02%gilscGdl;]#)e3cHsn`bgFq%%Mfcg1"=Ll^<+7=ai2W@bJMBFc-FAHbONXs +`5fs?a2Z6A[(1ci;b9AK>@hK<h!F_6rVQHeqtp?hrVcTms8Dups8BA*J,~> +ZMt%+r;?Qgs8W)mrs7iGhX9Uiir&fQs8W#qrr<#grZ(b6s8Dusp](0`\n3B7+WDIH-6F?W,T\*X +JGJp;s#Tk9,p"..qYU<is8)cqrVQWk`uZ0H-i!Z?i$]`d-7'ri,T[pO+=/$O-S$2kl2U_^s7Z6` +p\=[ds8N!/rVucps7lNlp&=sas8W&pr:0bPs7:db*@)`"q#1-js8Dupr;QQkn#7QV+<W<,rVZ]q +eh/$e*$W&qqZ$Egr:g0ir:g'^Z?RoD*?cM+q"as\q#13l$3'u&qu$<br;ZfdrWN3"rVHHjrs7E: +nF#`6mFge&rrN)trVllrrVHTmWW.J~> +X8i1u!r`,trVmT0qtg9krr)]\\YGXkT;&IJo_n^ar;Z`ps8DKe*;KR4qu?]ks8;Gu@jN-9(DRf0 +)&aV<(E+NGp\+Rc3qeRU()Kd?qZ$KnqZ$ToqZ$?.(_e&9p\k-K,8q+6+!;pP(`"23*u>k>,oA/o +s8Dutp@n@Up\Y!jrr*K-s82irq#(0brr2Wks8DimnbtiSnpD>i)]>1?rVZ]qrVufnrqcT\V&U<f +(b+qPrVuoI.iTKH+M7[Os8N#tqZ$Tnp\FKbF!_e@)AuHGq#Bs^rr2p&rVuiorVQ?err;Nf(]FC6 +rVc`imG+J*Un+$JU7AgWoC`(]rr)iurVQTlrr`9!rVl`prr0A+J,~> +Y5\_'q"FLXqu-?js8EK+qX`dlMe?$n:f1Yp\,O5G`llL"b43Pk_TpBJcc3W=aN9oJ)%mMi()dts +$5+'c&eeX!`6QWI`5$4#',3[acH3uH`luoTbgY"=$k=!\bK%l8%hoa$'+G`f$4%:T'+56]'a5Dp +d`9SZ`5g$Aaii#Tb0%fGb/MNG_T'a5aN20CbK%TAn]4ML`+B]$*XdJ@ai_lQa2Pj:bf%WCN#<`Z +'be[/_o^H@*"NMd$_>tobe_-8`QlrR`Qc_m?lBXh&dphOb0RQ/`6H`Yc-+#?_8=+2ccF)qa:ub? +bJqH9]<7W2;cud`7Sd<Kali?rrrDopp&P$hrrN#qr;Z`oZN#F~> +ZMt%+r;?Qhrr`8ur;QWo!;ZQm#3"D(l/U:]p](9ms8;lrs8Mros8MrrDZ0M5r;HZnr;Zcfc@@/b +-6"-Q,U"9T,U;[Ss8Vlos7fhF+!jOVl1b5Tr;QTls7lM\-mBp=qYg?=,9n:DpW^sYRr;de,Ut;b +,q:&9rquckC+:T8n+Zk^rVc`qs82iqrVuN*S"-8>r;ZNknc&Re9UdIQ+t.R1s8Domq"sjZe>S48 ++<i!O,:WHgqu?Nh8K8lq-%YdhqYL6hqY0dPWG*S+,S_[O,pJKIs8;osq>^Emq#C6kqu?]prVlfr +pAY*i!<2lq$N9JOnaQ#:lf?mlr;Qiqrr2iq"oS/kqu$Hhs8W)*s*t~> +X8`;$rVc`mrtkY3rVc`ks8DiefW(@5St`12o`"^arVlcos8N&ur;QWos8MuqDu]_2s8Drsrr)ls +o?Db0+Wh=9)]]h7*$-0cr;Zfls8Vjs*u>qcU#u%Hq>1'erVuWgQQd@i<;HLjc5mo>?h2=\TU'>! +-6FN\(a(+Dq>L9kph2$#=RGh]s8Doqs8W#srr)lg^R:OblMU\Vs7$"^r0JTC)'X%qrquZgpA4OS +dAD\-)]BS0*$t@Zr;ZTg7i<<d,(TCer;HZor:p*RVe$no*Y';5+!$@8s8;osqZ$Klq#C9lqZ$Tm +qu-Bjs8W#rs8No7qu6Wps7tNfT;8$FSXuILa8#H+qYU*es8VuurVl`nrrN,trr2iq!WE#+s*t~> +YQ"e)qY'XXqYgBhrtPJ4q>^9Ygp(s'<_ZJ#O0l^<_8aRlb4`pSb&>YLaj%c@_S*e/e^:R1#7MI` +'b_5n',D2daO&5S_T0U53Y<)G3/bc$eBlUhaiVoMd<H99&j+:Wb,5Ub*FRa*Y(qO,8eMOF'*SgX +#i<hEb/cjQ"#\$>d*BbTb/q`BaiMTO_i\nXFLoQ:_9MMk4iPWo)AsM1<RB%<daHIcaj72A@71A; +*#TM#d*BMKakAKW&J#IadaQ@[dEKk\dDUT,#SRgR((h&`E6ur1`Xff,bg4;Q_T9R9cH=5I`Q%hs +s2P&Zr6#&_&BVo.\=7hI>Z"'e:/YMeh!b1@"T%oepAFmh!W2ins8Mu%s*t~> +Z2ak'pAb-krVm!!r;?Qmrs.iCj5oCcmIg>U"TJH"q"k!i#QFYsq=sd_r;6Njrr;ors$QS]j,k]; +,U"BU+!E%]rVQWls8Mu],TmsM,9J=)P.pG_rV6<jpK&ab+HQL!r2M"c-Z](^r;6Egp\4@DbcI7R +JG&p@*;X=o+X8DYr;HZkrr<#rs7u]ppM)$$-e&%orr)?c56&kX*?ZV0q<d.gRXf-#-7:2d,9e0Q ++=;@+s8VloreMXB(ag['rVH<bpZ/JV,UOWW,TJ'O-m<d6q>^HkrVZWnpAYR#r;?Qns8Duss8;cn +r;R)ii9'RuoCV8(n+-MVri,pJ~> +WW3"tqu?Zpr;RK1qYKWlT:hdHUpnYCqtp<krqQ9frr3'!rVcQl!<)lo!<)lqrr6X0r;Zfkro/t_ ++rqR@)&F28HMdR=qu?Zql672]*Zl@J7?>(KqYp?gs7B56(`J>1r;3B6)BWeir;6<dq"==Pk0'fm +E..?Xs8Me'*?#qEanu&:q>UEorVu]nrq'eG+=#;4s8Muer]gG^as@c=*E2[thT_:2A0E$;+WMI@ +(E489Fn>Y5q>^JM*$H"A,k_07q>0jGX\p2^)&aM1*Z?7DF8bn6s8;iqr;Q]orVZ]os8Mus"9/5u +rr2p2rr;`kqt\40TqIgCT:DOehu*HOrVl`p!<2forVl`p!<0D+J,~> +Y5\Y'qtp?jnGa:!mF.2/>#7jlD2Gd;`5g-HaiM`Ob/sP#s2b2^r65/_s2\rp`Pod8cHjVZZtTpa +',29"'G;$ce]c@[bf\2G%20Br((Cm3J?7GYd`BV]d5VgM$?"/1c%HK>*FRCBcd:.gcHOA>SUYQM +>0=k&aO*g!&e,&>c-+>Mbg"5FaMZ<Md7XrY#cl.haN*hl6cREP'b_E!5h3ie["`Ht&Jl?'&eYii +'+PIPb0J5Gc.?Y9'ak`ae'uXedaQ-p3t`DE'Gh,i#7UZ2eB#nS_Sa@6aSs?]aSj6]aSs3ZaT'9[ +`W*ppcHOVZbf\/H`kf39>uONe6qgHdN4eBHqY^Bnr;lfor;QcqW;hA~> +U&Y/lrr3*"r;?EirsSh[ipH$kiTgFBs8;lr"9/,iqu6Trr;6Hg!W2lns8)^Xs8;`nrVZ]ir2<76 +,9e6W,lI]BqYpElqm.Ih,oRpR*@)^S.W26KqY'(q,9SP_q#C,Y-QsS+qYpKlrVc`q-M[K8s8DNg +rVlfmBI"]F,U]/_p&G'cs7QElqu?M),U4Yar;Q]onbt6?rS8YD,9S=11*n@o,q'r[,p+<W+=&0X +,23%rq#CBejWPZh*Zr5jr91"a,TS-XrZVar-7(!Ydej"=s7u]orqu`op&G!i#64Yqs7lE\rVm5l +kMGCgo()>3h"-d1J,~> +RK"3(rqH0^e#&k3S=cdti;!?Drr<#trr<#trVlZns8N&s!W;olrb)9/qZ$Nls7Z8a7NNNg)'C't +rr;ior;QW#*uc=;*[;RH)BpMEWTa-KiuB$V-d28apR!-C(nLI$rqlWkrr<#or;?Tmnc/Ugs7g%B +(E4G@RfE$[s7ZKes8VurpL,'^+OBrbrr)Bds8>(6*??%8+&+@2,9.^I)]'J1)BKb;*[)WXrVuZm +s7bUs)BB_9_"@QfV-G2`+WhR>)BBqC,&Yd'r;$Bhr;Z`p!WE#rrVl`pr;ciprtkY-s82`gs82cd +cFTgES=5n>StsHtr;N&_J,~> +T)Sljqu-Kn(&I=TWGPj67o!B<TY&1UaNr,RaN2O&aSa'WaSj9Wa?.Yd`663@c,S=k1Ct68%hJus +da?(U`luel%M]ur%hJsY'HS2pKtc!bapA[k'<K7%a`e7.&;nfVbfg"2.+$)N_SaXB`R2WA`mIg. +*#K(gGMC-be&',7a3DZRfM3.s&?s?taN*hl*Q6.1$5sp#'f6L.',DN+'c7r+(Dm_s$O?a<dE]W. +a<&/)%MoW^UsRc8M+%jX&fhr1(DRVn#u@SJbf.iCb5K?[aSs<aaNDTHrlG,^s2Z2"`PojBahlEE +a2-$<_mbVK>#%LP6V^ZtT%33&QiDR~> +RK!<eqY^?tlK$g`inWJjrs8;lrVQNmrqu]nqu?Qorr)ljrabp+rVuoprr;fnp;V#"11fGAqYgHk +s8Vh6+!D_MM,trJ,9IdI+t6<$;C!M,/bB#8rcoY1-`-S2qY'sdqtU3gs8Vuqs82cos8$CS+!MpQ ++ERJSrVucps7Q6br+R>u,glPXrr<!Wngbe),p"HX*ulLM(aLIK,U4HV.8,d#s8Vfms7cH];&g\u +*cd6>+Xe9W)^64E+=&@U[Jg($rr3#rr;-Ejr;HKnr;QWo#QFVlqZ$9hrr)j(mG7$mlLOQ6ip$B) +s*t~> +T`=rhs8N`2qu-KeqWkeoSYDaIW7189s82fq!WE&trq$0drabp+rVuoprr;cko>55f/n*Z6qYpNm +s8Vk6*$#u?LfYiH+<)%;+=B`i9-"ud..I90rH9+u+JAE$qXsmbqY:*gs8Vups8)]os7p.E()\)2 +)K,BDrVufqs7Z?dqILTa+3scPrr2p\n0Snd)\jP:)AX;4&fr23*ZZ1?,Y*jis8Vfms7lTa:Db#e +)K1O3*[MUI(EO;1)BL,?Z24@nrr<#rrVucop\t6lrqm$"rr2ros8Voort5/(k.[RcTUhdJT;&pV +q>C3jQiDR~> +TDo&kqY9pcrVmT,kM=+5@7sHm:0ij]^V7=sb/hNDrlbJeaMu3p_Z@`rqT*3db/_WI`Q6EIe'Opj% +M_CBbf7WC^rXdI<=KQP@qme$#8%RW&-i\*<^@H<$5Cb0^X#mf&f?VP_T9^Fbf[rJ_oKpAcd^1Z` +Q$(s)&X>,%h)XoaihlEa3)'3aOElq&e(tgn&Rc6a3VmA(EXn<'F4pL'GLZ['abK_$OR@pDV!Fe_ +T^0;bfVgP'b_*aFup'I$Ps0`#nIFS&6G1Pe^2[hbJV9<prFi&aMu<@`lcWRb/VE>aNDNIdDErCb +eCZ`G#h[?77KX=A<+dsmdg7As*t~> +R/[0aqu7B"gYh2_i90"ps8Vlgrr;upq>:*hqu6]rr;QQnr;-Btqu?Zks8W&orVoLgoCDkXs8Vop +s8)Ze.N]lYY5%bWYAZ!?*[`'O+WqaD.!5Ccs7U(L+!Mn&Ck8RidGY$!s8Dorp\Y!hrr;h.,9J'P ++sS70i;!<N!;QQn#5)XQ+XGJ4mf#NLs8?(D+X/3O+=8EX-7L;h=a?IGebAn:q#(!erqufro84q< ++<_dR+"/'L*ZlOR/p+Q$r;??iqu?Wlr;Z]ps8;lrr;ZZoq>^3kq>:0irrrE!rV?*arVm5sf@o`] +mI9<%hY$jI!<&5`J,~> +TE"rjs8Drr(B+74q#('aaJl#1W0jHbg@bLGrVuorrVufpq>^<j#Q+Q#q>^KnqYgFhqsa+Pqu?]n +s8Vuop*Ue$*j#25mBCIX,TA$N(E+/+'I%MmrVuM"*#KV7883OMXj5f$p](3js7Z<hrVlimA/lC& +)&aG4:>P[Drr;fnrs&(*)]BgDqX=DJs8;oo<#?Df*#'>8+W;IL,9g-1QF,*4pA+FZqYgHms8VbK +,oR^B)C$1H(E+22*[<.RZMXIopAb!hrVQQnrr)cop](9ls82orrr2otq>UC+r:JL<SY_gCSslCL +bP;&9s8J>aJ,~> +T`5&kqYp6iqu-O7rUK7:esC2[<)uCf@["%2]Y2;*`QZTNb/hTA_tq1M_oDPoAAug7_o^'A`5g!G +f%&$fd`]kY]ZA"*b1%+9'Fg8RaLm7*(DR8e#n7R^%h9@VeB?7_7Lg%E%P("QKoE(Be&TnYaj%iL +dE0JLa\*6])&F,-&idJGbfIf>aN2]M7h$"<YKZIV(<4/5e3Flq,p<U$%LrmY$j[)!>'ZI@rmUnl +,fn*I_o^3DCD7I"(_IPp)%7)f%h/sY<L)@leBcUfcH4&Db/F;%rQ+fS+iqpQb/hTBb088Y_oKa6 +]Wd<!9iO\Q8k;rnUYteCqt^2Ws*t~> +U&P,lqYpcurqlTms8Drs#N=Osn*'&rn,<7hqu$6ar;6KprqlZh!VuZirW3&trr51\rr;lqqY'je +s8DuopAapcs8:%g)'C:#s8)NhqX;Ul;C*n>,9eH^c2I\>pa742+=/<Z+!N!X,q7:?rr)ir*WH$: +rq^7P+!N$O+s.jS[K$4*rVufkrFdB!-.2YYrYY\5pO+5/*$ZpV.;FC)e(O]mr;$9jp&Fshs!@[E +r;6?jfd.RU+s7dN)]U1N07:b,s8MTfs8DrrqYpNpqu-Nnr;Zfrs83&tq>'g]r;Q]prr`8qs8)]o +$L?j;jmD^/l/q@/rr3)sp\FfTs*t~> +T)SunrVcZmqu$I*q#(!L[A9:fS><+%iq`WSr;HX!rquZkr;QNlqYgNqrVlg\rVliqs82Nes8W&t +qtU3frr;l;,SV4CpAb-is826,P>WYR*??+B,0Kf_qXl$N*>on>*>f_:+<VuVqYgBlruh==rr;e( +*>f\9',_Q&,I7:Gs8DusqYXnE*$EQ(rr<#hrr<!brUkCR(D7W3*$o3DRaB[`oD84Xrq-6frr<#t +s8Dlps4JV5'ce5.+r;(?+tS&Xm/?nQr;Z]orqcWos8;iprr)fprq?Blrr2j4rql`prquNI\tl!i +TV.aBVShEhs8MlmQ2c@~> +U&Y/k!;c]i!rMrorVmN-o(24iL1EnJ6r.-=U:nRa_T2Yus2Y8]`PqenrPeTRB?J9:bfRoHb.ba/ +_TUBSaiD0,^q7A'bH_uq',&sE_njIBc`VIG"r@j^$kNiJda-(a$kaHl(`4&%',2&f#cuFubL+VY +b08)La[QdR(`X52(CUb8eBZF]a1oF66jsV9YKb/.`q%2@`l,g>@Mg4.*uG7l9kAgVYgU\AcI(1` +f$2Lcd)a8F_Saa0%Ls*i(CqAl%2KTp@@b<cdDaD\bfn5LaN_lFa3;cMb/hZDr5JWS!l`1#r5obo +e'#hK\!Lr,84cQK7nmT^`p*3lpltf/~> +UAk;oqtp6i#5e>qpAFpbrr38ss5E5.l/1FprVlrpqu6Km!W;cmp]C9gr;-Bus7cQnrquWhqu6UW +rr)fqrVHQns8MonNZBJk<VH=eq#C9lqtosOYBV<B.Co<Ss82XB*[2gQ,pXf^-mBobf_PRGq"Oge +rr*o6B-\TEVBR90-7'pqr:p<kpAao#,9nM_r;Q]onbs4%r;)j,+!Mq?p@J"Xq>1-es7lHis8W$= +r;Z]op](9mnb?rJ+Wh[H,U4[k^ZYXos82irqZ$Hkrr_fhs8Drrq>UNqr;?Ki!;ucp!;c]p$0C70 +melP3lKRs?rs&Duq#C6^rg3Y8~> +T)Tc/rVZTls82irqZ$ThqtKj.bFbK#TUi(.o)&@ars&K#qtg3frV?KirWrPus8W)rqYU6jrrrE# +rVulprVnSLqhuC:*`D_1s8Duss8;fdm]1FP-7-+qrVu`g,o7I>)]ft@*$H:D,h;YhrV6-err!0& +q-tH`*1n/h)ZCfhL\^ZDrqHHeA/u[5cMRV@nc&Rg')hWl*#9D2?h3^Xr:]sdq>^6drr<#s"T8;t +s7lTn(A.E<+rhL;*$HFNKYHUKqZ$Hms8)cmrVlujrVuiqrW)onrqQNlr>5M.qYp&sWh,ZWTp;4E +\(UZUs8Vlos7_iZJ,~> +T`>&jrql]n(]474rVuons750CNDiPE;,_.l\%ol&`p1WXb/)3FaMu08^;\7:aN;KC_S*t*`Poa@ +FUfB)5Ldln]u\FOeC;OWN`uSl#aNiccd(/U&Jl,n(`=2*(CgfZZHgnA_SO=6cd0bW8.Z:GQPCJW +(D.$kf[%sd]>qrX%1s&Sc,doDo#O>@aMc>M'H%r/9\%J;gXFEp`Qc9>bK\MZbK.oI`kTX9`P'Ys +()@Sr&J>TcD5,,)b/q]Jd)O;KaihlL\\uV1bfn5PaN2C"`W*sXa99N#_oBdraqr7:_o&d&?qrs\ +9LMcbJ?nD0rVuTks8A8`J,~> +UAkAoq"O[br;R#uq>C6dr;Zcprs8DZj66($jQQI7rrE&sr:^*ms82chqYgFSrqlTmrr)lsrU^'h +rql\%-6Fh*r;ZfrrV-'drVuZlp&4a^p&Fmes48qE+=d*BeYT$ZA1f5'r;HTos8F)>rqU1Q+skP, +@3Qa5-7;sopAb*kq.h3!-.;_jrr)Bd&bl8(_CZoV+(kHKs8Dfnr;ZZnrrN&irr3#pqu6U!r;$Bm +nlYl=&kdhoo_JOer;Q`ls7QEis8;omrr3#orr2fqrq??orqH*_qYprtr9<;-oChA>m+pe%rr`,p +q>?KWJ,~> +Sc9W-rVc`qqYU<mq#10er:]sDc)[M+TUh^^f(&b=!<)los8DNf"TSAtp\Ogf'E%b-rr)lsrq-6j +rqlUt+W2Yiq>UC;rqH0drVu]lo_eOZo`+abs3iG4)'nb,d@m4L@4W\tqu-Kn+9)6<rV'bC*$<;k +>9"Fp+!=PXoDedhph1Ze+3sc_s7-($s7lTn^F'p?).NI>s8;]lr;Z]orrN)jrr3#pqu6U7rVHQo +mo(AQ,"@$so(W.`r;Zfns7ZKks8Duorr3,srr;utrr2ios82rsr;QZp!<)op&cV[]d]fC6St2"< +Unt]kr;?Qms8Vusrg3Y8~> +RK"Z5q"Xmhr;Zfqs7Z$)UM<Xp:/kPER^9cF`Q$!Abg"DYccs_Ybf\*(a?[qfa2,^>bK.`A_o9gA +a2l<<\B)h6ajWKb$Q"0BccF#B_o9pCaM?'?bfS&LfZVRk\/Geg'\gF1KRli_"ougEb9G!KaNr5X +c:el_&$sq^&.K$c(-pX$e&T\T7h61BZd6_4`U_)>`kKF@Sei"S$UrOjf$MUa`lPs8aiVK8bfS)H +`Q?0A_nOIIcohsQ%kqLcbg+S^aMu?;aLoR2a2>s6aN_oDaND`Lb/h[%`WaH+b08#IrkfMkb08)N +^6XR`:J=MV4AK!nPM,R'r;6Kn!WN%`s*t~> +UAkDpq"OR\rr2p"rVuosrr3&ts8Dlq#MSA*m-WfalMLS]rr2fqrqcZkr[IgFs8Dutp](3lrr<#t +qu-Nos8;iqqu4Hs9.Jp!s8)]orr<#qs8Duorr*f8qYpKjdip(^@f-*$qY^9dpA=^ds82irqYpL5 +rqU1Q,::b6q0je?*?c[UdJNt?q.Lrr-.2YYrr<!bpsCB0+X&6/rVHBjp](-jrqQEks82cks8W&t +q>UEkqu?WBdd6i0q>^Bhs8Drls82irrr2rsrqu]ns8Dlmr;?Qfs8Vfnr;-F"k2PdpqX3e<iS4A3 +#5nN#rquQhPlH7~> +ScA`h!r`,sr;RW5qYpBjqu$0CW2#lOT:_dnn+lkXr;HWorr)cm!<)`m&,lM-rVuols8Duss8W)q +rVlisr=K#*rP4Oc-JnY"qYpNos8W#rs$$;Zs8N&orVcN;*$-)+q"jm`qtp-\qYL6lqu?]ns8N#r +pL50a+jBcUH6j[K)''pGq#C0aA/lO1c27M>s7-*gs"X8o+;l+<,l%?7qZ$?jr;ZfmrVuoqrVHQo +rr;ips8;`lqT[=Lp\agdr;6Nns7u]mqZ$ToqZ$Tprr)lprVHTnrr4#<qtg0bp"m0TVOF3CS>)OK +kPP5Trr2rtr;HQkrg3Y8~> +RK*6_!<)lr(&n75p>N;o>Y\$o=^?HX]"Z#"aNW!/d0.e?bf\*(aCiQ7bf@iJ_9'a>b0/&Pa2c3A +a2H*Eb0cYs.LX#Ad)<oHb0J2J`PBR5`Q$'Gaj8;\Zj[W[7G#r5c-O_Xa3)KLb/MHB_91'Mc-]<$ +&Ik_gf3o:+',M;mZIR@EcpnW\&[Ka(aN!bk1rmh\W<s"D#m&2l`lQNAahYp6]u/"8_oK^=ai2H> +`l>p=f%I:6bLG(bdDj&D_Sa(0^rQGn#KOg'`5K[;ao0B^aSs3Za9B`1c-=JPrl+oY'ZRtsQ=j#h +6r-9M>?>RVkkb>Zrr)ir!r_uoQiDR~> +UAkDrq=sd_r;?Qis8W)rrs.fIk2Pdiipm$J"oeJrpA4aas5O"_rV?-[q>L<knbtKIppVLo-"HcN +r;HZqrVccrqZ$Nor;Z]nrVlV1+<W&Wr;ZK!.4?2\*@Rl_s7g:T+!f/2s8Muerr;m*rVS#b+!E!, +s8N&qs7k%As82lorqufqs8W,urVluuqu-HjrsJ8Wi8j7pp$:K3l\YXl~> +SH&Wgqu6Zqrr)fq)Z9C&e[;9MS>DdN_!Umor;Zfpqtg9fr:p3gnG`Cbrr2osrr2oq#l4,cq#(-i +rr2oq#6+Z&rr2rtrr*`4s7Wc@*["kbrqu`ps8Dors8)cos8Durr>PBC)&aaEr;ZDq,U!m@(*]RL +rUj\C(`pius6osdr!`EH)&XD=q#C?nqu?Kis7lTlrs/Q%rVZTlrVl?er;QTnrr*u=qtp?irVZQl +s8Mokq!R1TXJ)A^TU_IAa2@<@qtpBm"TJAurr/2_J,~> +U&P,kq>Vf?qYL*fs8W)sqtg*Yl.iCg>#%I^;-SLO\%fc%c-4M[eBQ:X`l@Sj!QrXbblZ,3aSs1Y +aND`Oc,mrCair&Sai_iPccsVO`Q6->`Q63Gc-ae%$P3b5cHs_WcHaVVcHF5La3)<=_o^*HdomCp +$DGVic'/bW',M,kMpg2-:)=NUZ-g\7`UV"[`lQBR$4..J!mJs2c,IoArl+oWprNER%EcrCe'l^h +b/V?8_8F1f`VmgJa</XIaN_uVd*'JMc-4GQ[%D&16psL785!6RT@NE)q#13hs8A/]J,~> +U&P8pr;QWnr;6Qoqu6ZqrqlcprVm/PeE$)dn_3'urVllsq#B@Q#64Z!qu6WqnGY?Bs.1M[,,,&6 +s8W&qrr)Wjs8;ois8Mrrrr;gn+sJDbqYpKmgES-l,:+UWr:aeJ*[f\@rr)?crr3E#:*;&/-d;Ac +q=t!idJit>"o.ros8;fjrrhrLjQc45klTl,eF`bBrqub^s*t~> +Sc8]hqZ$Tp!rW#qr;R<*q>9]^T;/0LSsHP'oDSUdrs&Juq>1-jr:0darVlfqs8;lrrri8srr<#t +rr2lorr2rsr\s]QRNNOiSc8Kcs8DlprV6?kr;ZKjs8Duss7f;-*$`u0rr)`H*[;UC*Zo@so3`LQ ++kHVkrVuEerr3>t8K&il,Kfc\q=ssho`"dgqu6KmnG`7`*rGp9s8;`mrqufop$gtVStD[RTV8*K +VPr\Nr;6Hlrr<#s!W;n\s*t~> +UAk;nqYU*g-2[Q9qu?]qrV6*]q>'XIcZ3/e:J"G[BSW_$]Z&%=c,n,MbK%Tma9]r5cd0k\bf\$+ +``1%%b08#I^r+.6cHF;Obg"JYbfIlJb/VE?aNDZHdX;N5$@paNbg"8Nb/qZHe&]\Fahts8b0A@! +'bC_L`6-?Q[gEog(_dBWg=f@?',A.,aN)<ja:Q_Cccn6S*"<1La32H=`lc=!a8jBZaSa$caNDZL +b/hQ>_84%/kf=gbaN`)Sb0J8Na32K;X+!i45=In4;G_%Pa6**nrql]ks8)fpPQ-.~> +SGrfmr;6Bhr;QZp!WN&rrrW3"rr2p'e)KicmI0&kq>UBur;HQmqYg<LrW)utrr<!!rr)Bd%0-!R +-m'Uup%nX_rV-<k-i3`?rr;lqrVlcppb3m9-2%08s8)Qh=sY=4*[XnB9d:c3li7"as7-'qq>:3e +BIFlD,.@ILrrDc;rXA`%q>'g^q>'g\qu6NlrsJDThs^+)mc*9\f(/hBr;6J[s*t~> +PlLd_!WE#os8W$-qraTCSXZ7LTr-*&rqZHhrrN)unG`Idrr2Eeq#1Borr2rrrXAi!J0GgKOR`/F +q>L'es!RX=s8N&qs8N&trq7f\)^+bLs8VrjqGn[V()S2kej^Pp-KkC.rr;Nf$MjT!p1#6[(`]jY +rr3#ns7$$cs8W)rrrE&trUTs\ru:q:s82Zgp#a2hSYr0RT9uCLWoisPrqlTkrql]o!r`,tPlH7~> +UAkAnp@e@]qZ$TorVmr<qtTmYqYL$[lH+!P;+OA\;-ALI\[T2ha3D`MbKTOu#Kk98c-4>O`r3mS +`X9Z%`Q$$A`l6$?b5TTgb08,SaN"2"2pK?P&eG\+eBQ+Sahu<Hd`]k]bg=>L`5T^:cPdN1%*H]8 +cH+)U3>3)8$4T&94<#%Qb0\8Ob43Ob`Q?TU:Djl_%[Y\md`]>Cb09h,!6kA`r5]Dg`P][6aN2B@ +`Poj>dF$5<bk]E[aSj-YaT'Bobfe2M`Q63>^V..UKO@YU8H(se>A/H(hXUC;s8W&lqYL*fP5g%~> +S,`Eas8N#ts8Mus"TJ>rrVlfr'&W!AiToa`hY[3Ms7uB_q>1!dir/rVrr2lpnGY?>BcS<@.8Xc) +T<6Z#p%/4ZpAb$cqZ$Nlrq7HZ+"$pcq"Oggq=oF`.3Tca*[2gO/GT5Err;Nfs8NQ'rgY2T+sNBJ +p](3ks3^iGrsJc'qt^$]pA4^`q>C7#mbQ^^m-+$#mH*$krr3,trr<#sqYpZsr;?P\s*t~> +U&P2nrVlNj!<2`m&cVJ!pYDO>Tp24ESZ1#or;Q]ms6]gZrrE&ts8Drrs7uWqs8N#ss#0O^(E"/9 +94rI>X4,kqnc/@UrqcHfs8MusoGS\d+o;66p](9hp3I]')]C%>)B'D=p&4pis7-*grt"l%QQ-bY +)j9jes8Dutrr)Eequ?Zps8N3#rVZTmrUp-ks8N#lruV%:s8D`R`2TB'Tph[@USas7nbrLcrr;up +r;QZorfR52~> +UAkDop@S.VrU^%0rVH<drVuooo\m2g>#Ra`<)-_QQ*[s3_8jgGc-#Y!!6Y;b!m8U(p;R$Nrl##Y +`Q#p=rlY5a"3AL'aSs1;`CC.H(`55';0R\p[EQhIdEU+^`PTg:_oBk,((^u*d`02Ib/;J7%M]?V +((D'#(`:iKb/h`qa:ZeCa45eV)]TH;dE9eU`Q--Gr65)]r5]&]_nj1,`r='Z`WjT3e^`!jc2>fa +b5TK^`[\sI`lQ6Db/_ZH`4j(,^9sS\?;sm#85DWU@s"[(nbDqXs8W)ss8DilrK@22~> +RfE3_s82lrqu6Zlqu76#hWO7emH<Wkp\4^ds7Z?ci;W`Us8N&unbtKGr)Fpj*#p+G.4QJb.4lo\ +FJ#Y]o)JObrr;X<,onH.q#CBnqu?Zq]-SaG+s7pM+"$m^s8;icrX\i)rqWTG)^QnEr;Z]hs7t+B +rVlrsqt^6d!W)fors\eujkAbZjQH'phUqK!rrMuirr39's8Dutrqu]nPlH7~> +U&Y,jo)J[fs8N?#rr)Zeq=Vo0U^WW_SYWI?jSo2Zqu?Q]rq-6jrr;uurqHHmrr2rtrr<!7rqoY7 +,8:k2)^6LG*$ZjU@rRp:cLLr2rr32o+W_CDoCr7a')_e/rO3ml)]T_2(`+=iqu?Tmnbs'ps8Mek +-5%:B@f$-&p](*Yrr)lprWW?$rVZTlo)8^hrr2fps8N#t'D18,Z(\%mS=64DStaI%qu-EhqYpKt +r;QZorr)lsrg*S7~> +UAkGrqY9p`qu,m](&d^efpu\[>YnEu<aLKFZFe8sc-"3"a90T+aN".srl4uW$H'm-cHXPR`lH-= +rkh+B`l?*@`l5p<aMu6<atF&?&If9b)As%q',;!Q=+5n#_99X5`Q?74(_.5-bL+SR^raaNS-fZ1% +M9Bq'bK!=a2Z6ka:Q>6b05e_'-.i[eCMdYahc.!bl#W[a:QM8_nj1,aNVlNaMuBIe^`"Ebl#W]a +T'6]`Q#pra;r7;^q[XsYEsWC:fUFd8m#)$F/\!bq"jsdqtg3gr;QcqP5g%~> +PlCmcr;?QnqYpQpqYq&nhr*Y^m,Hg[r;?Tos8V'Wrr;uss8VWgs84aAH"/<W+t+TT-R0ZO,TJ<W +,;.C:s8MusoIV:..Ja#>s82fnqtp'E9-YE++<_jQqY^BlrUKjts8DrodNfq[,ZOO:qu?Wndf04F +!;uin!;u`o$Lcm/jQ>UimHNQcrVm9(s8Dlns7lNlrql]nquH_\s*t~> +UAt2kr;Z]or;Z`p)?9^8qu-Kkp&4gZ^S[ZoSY2RM[GC!Dp&G'\rql`nrr2rtrW)utrq$0hr]'rV +r0DJ3,UsfX)&=>7(_n)--6"$Wch.8;rr;O:*#9dms7lWls8DlloA)nX(*aV4(a&MMs8DodrXJo+ +s81+a)&s_qpAOmgmJd(a"9/8trr2p!rr)fcrW<&trqcX0rVH'DbH[b7TV/$TTq%t0mJ6VSrr2os +"o%oos82fns8N"as*t~> +TDo)nqtg0drU'UurU][Db):1J>?+Qo:LK0Q]XlA3n&YOKrl"lWr5_dU`Q$3Kc-",KaiVQA`P][6 +`l?!8_oBjCb/V9;D-0FH(((op&/Gle#7q(Q"Tet,`6ZHBbK1P9%MRCAaNhZ?_8FF<]IXBq*>fe3 +$e38<a3!km&(/M=afGj^'FQ\=aiDZF`VdmQa:ZS=b/M37`QHHMbf7W@aNr8XrQ55`b/ha%a90H$ +`lA#!(<4J5^UUA7JRhMJ91r#[='KREdd-Q!rVlrro(W%]rr&)]J,~> +U&P,lrqufqq>^Kmrr2utrqm'#s8;orrqu6arr3>ef](uao]YT%qu$Hni;W`Smf#'?s8Mfjp@mFn +WL\'G.k2hk.4-&_hu3TSqu?=<+!E!,q>^<hs7cQlrr;_+-Q=<S,UN9crr;Nf&,Q2's7msUGFcPL +q#:<hs3^iGs8W'!r;QTn$h338jR2F(nEAcmo)/LjqY:*eq#:6squ?Zpr;?PWs*t~> +U&P,lqYp]trVc`prr<#tr;RZ6rVHQms8Vlop\X0gV4sERT9u@Nbh_sfrUBgbs8N#srV6?ls7cNl +rrE&trAFTPs8McfoCgteV3u47-RKrY,U"!Lh#%-Nqu?74(E+Ikq#C3hs7cQmrr;V$+VYk4*?b+U +rr;Nf&,Q2's7ddLEgjcCq>^Kjs8N#ks8W'!rVlcqrquirr;ZZn"98B#rr2rnrZ2%<rr)Wcn__*^ +US"6MSY)C>X2=0!q#(0hq>^Elrr2urq>^HnQiDR~> +Sc8ljqY9parVZZqrV6Emq\Ar(rUp$OjN<a*@S]lq6Vq$BS@H;QnAtRJ!m&O.rlkJfb5KB``Pfa8 +rQ>)[6-@9d_8XLAdEThLa3)TUd)r]#ML88o$k3OP&IedG]@>6Pa3MpE'G:o'aOA)Gbe_TCaO\g5 +&Iod"(CJO3a32Zra:H;0a3;[,:L&1/cbIKF_or&#p;RZbb0A/M_o9X?ccsVM^V7J%qoAlZaMu=# +`r4!Y`rF-[arAFA^q6nAH=9oR;bKbX92TVjb3&0fqtBRTpA+I_s8DupQN)I~> +UAk8nr;QQor;QNls8N#t%K?;&r;HZqqu?Kep\4[crsJGWkjA!9ki:Xorqucrrr)cprr)llrW)ln +rW)utqucotrr)co!;uTj"985ps8Musq^qaCq"a^Vm*W/0L1gP_rVufqq'-n--2@N=rr;lqqu$Ki +qYuO$+W_mTp\t0lnG`Fe%/9f"pA4^eq#CBgs8Dior;?Ejq>C9lq>^Emrqu]np\tWij5B%cm-X-( +k2u=6rs\i$rr2forqZQmr;HNlrfR52~> +RK!EhrVc`prr<#tr;Zfr"985trr)j2rr)TLa.f2pS=l:CX30>rr;HTnrr)lqrr;rrrr2rrrr2lq +rql]rrr)co!rr9!rr2utrr!-%s82`or;?QkrqcZh.JE;rcEEUeAGu<$s8;ok*Z$"DpAY$is8;oo +rVuZfreMX7(EOamrr<#frr2p,q#C6_p\Y!ds8VinrVlHhs8N&srVulrr;ZZns8W,urr;uss8W)t +s8=/>qY9d>^oa9#T:MI@S=QOmiqiTLs8W)us8N&uqZ$TorVQQn!ri6!Q2c@~> +Sc8]grqZZmrVccrrVucqrVQTtqt9g\rr2p3qXNISQ=jAr9i4M\@=k#\^VRn/aSj9[aSs?^aSs0\ +aNDa*c2Yugb/aM##0+^+aiqoMrl@CJaMYp8b0SJ]b/h?8cHOMO`QZ`TbKeGWaKLbTAOY>#d*KeY +cj0pg#1(T<b/hKF`PK[;dGJsV&.]<Tbf[rKb43RQbRVY,c-Obdcca)Ca2,s>aSj-X`V[X[aNDcP +aMu6@rlkVh_nWq#_u.LR`qd^S`ZW@B`l5d.\!qbV<`)^h;,U:oAr!kOmIL5UqYU'Zq"t!grrW/p +rVc`urVQKjQiDR~> +U&Y&io)J^gr;ZfrrquZn$LH[.kj.F"o&99@rr3/tqXsX[r;HWtrr;uqrr!3%rquZkr;Q]qs8;im +q>:<kr;>dX!<)oo%K-2(rqu`i.junur;HWorr`9!qu?Wm$+290+>*Bfs82iTrr2rtrW)loqu6Nn +rr;orqu?Klp]C9gr;$?mrVlftqtg<h"9&6!rV?I$mcWTllg=**l/(:ar;Z`nrVhTPJ,~> +R/d0bmJeL2s82Tgpt`TYT:hjHU8FU(i;3?Mq>U?mrr;uts8Dfor;6Ekrql`qrr;rcs82fqs7QBj +r;ccpq@3?#rr2iopF.F<.Js&Brr<#t&,cJ*qtg,o-QsK\p\t3is6oses8W)urVulss8)`gs8Drl +ruV1<r;6Els8Dios8W&ss8W&rs8Mrrrr)Zdp$U_GWVrIhS->UWVS_BgJcGZJJ,~> +SH&Qdnc/Rdr;S8Do'PGINbVct9h.lT:3r;9]u7h3b0.uNbKS5Ub0J,J`5T[6a2Z-?b0'_-!6G)X +s2b)Ws2G#Xs2YVkbf\#H`lQ6Db/hZHr652c!RK'jbl>j/bf\#MaT;GE!mf*7bK7lI`P]j@c-t7- +$3gJ6bKS2Nam[=N`WsT/c-=JR`l@krpr<<S#0P07bf\#JrlQA)`l5s;aMu-6^qdq4c-+>Uc-+5K +`P]g=`kf<uXdO!3r_XA(8kiAkCQH-^m.C2Rs8W&rqtp?jp&G'jQN)I~> +JcGcLqYpomgu7VbmdfDlkP+rT!W;oqquH`mrrW,pqYpEmrr<!!rqucms8;cnrVYmYs8Duq,5qN@ +s7lWnqsj::r;HWos8W)ts8W#sr;-3ATq@tTrVQWpiVriV!ri,qrVQWmr;Q`orql`ks8)for;Qcr +rVm9)rVHEirVQNls8W)srs\_jj6Gpsna>],jkK%ursAVtq>:*hs8W)tLAuc~> +JcG`Ls8<N,qt0*kVP0cTR\HOS]@?EKr;R!!qYU3is8Muss8Muss8E&trql`qrqZTXrr;rsr!r]) +s8Vlorqc-Ti;<HOrql^)r;ZZhp=Gq-SbrB_s8UpSq>^Blp\tHsrVZQiq>UBn#QF]"rVuosr;Q^1 +rVQNdjNOs'St)=DT:MOHTXrqOrdk+Hs*t~> +JcG`L/H5P?mG>jKC0FY.5Y4dSEfdTBbKS,Pb/hWEbg+GUbKS)J_o'I4`l?*@b0'P$q8VX>s2Y/Z +,0.dHd)=>Ub.ts$c-4DSbK7cDaihcNc-O_?G]n2RbK%cKh8oE3rlG#[q8iTY.*TiM_oBa=b0.rN +c-=AM`lQ6?_ns!\LhTa`8kVrV:JY)'L9fCoo_nagrr%NMJ,~> +Jc>`Mrr)rrqu$I$f[A^>k3;-oi9gL@s8W$*r;Q`prVZQhqYU9kr;Zfro`*kKs8N<!r;HWprquco +s8E#urVd-'q#16ls8Vfiq#:3mrr:gRqu$KnoDejis836$r;HWps8Murs8Mus')_M"s8W)eiS`nc +o^VA9kMtLUr;QltqtpADs8W+L~> +JcG]K(&[n)qtg*AWLKWWTUqjPU:Jb?pAFpgrrN-!rqlcqrVuoss8Duss8N)ur;HTlrr(dSs8N<! +r;HWprVQTls8E'!rr)j+q#16ks8Vcgp\b!grr:gRqu?Wo!<)cns8Dio$NL,&r;Q]orVliqr;RT4 +r;ZQRafV8/S"H1<S"64JX5<:ArVlcos8W&urVleNs*t~> +K)ZtlqY9sdr;?Tnp?]SE@TcDr92APfDMtU*_8jdFbK@oJrl4rX$HgT6aMu6=`P][9p<*BY!6X?C +s2bJ_`lZHNc--(0!m8^-rl,Gl_TC9Qf%.sgaiqlIaN)cN!QrLZ`rF-[b5KO1bKS8Wc-+8O`5Ta8 +a2lEDbIaO$@T#ol:.RoL;HdXQ[F+(&p&"^frr%KLJ,~> +Jc>uQq>1!cqYC-grsJJRg$.V]lg*Ejo(r@krr<#trVc`prVuosrqu<djo,8[rr*6(qtp?is8Vup +rVQR!q#C<irqlTfrVluus82`Mrr;orrpKdqr;6<bq>U?gqu$Hms8Dcn%->mkkNM:)nF#W(ip?RB +rqlcqJcG`LJ,~> +Jc>cNrr)lsr"o2(p\F7%XeDPWR@g:IZH2\2p\Y!jrr)irs8Dus"98>urqucsrVZWmqu$Km!W;oX +rW)utrX&W%qu-Hms8)Zlrr2os#l4N!qu6Khp\t0l"9&8trS@JQs8;lorVlfqrVl]qrVl]o!rVon +rr)ruqu6L1rVlflm_bluVOj<NS"6.DVn1RQqu$Ejr;Q]rrr2iur;HTnLAuc~> +K)YuPq"OU_r;S/An`7f[C0+P4:/OteAq%"n]Yhb0`PfsA`lH-Bb0.rMaMu6=_o9^pb59E^blQ&2 +k/[PErl>Mo`Q-*Ccd^+]bKS,Mrl,Jabf@]Fai_ZLda$%VbJV9Ia90T+`l7nrr5eiZ--Xc`cHab[ +b/_B6^qRY'`4`=$>Zars7nQBK<aBKpXO-%spA+^cs8VrrrIb-#~> +K)YuQqt^!]rqQQlqYpokg$/%ikihHtj73$Hs8;rsr;Qitqt^3c!;ucps8;ln!W;rps5X(arV?Kn +qZ$Bgs7cKprVulprr30"q#C9js5<nTr;Zcjs8N#nrrN,srV6Zor;Q`rrVcWn%JoJRj5oXmkj%Hs +i8*eurrN#qrVM0GrVqB~> +JcGQG+TD?;qtg3Vbb:l2R[KV?UT25lq>L0fs8N#rr;HWnrVlZn"TA8rrr2iqs8E0"r;6Ejj8K>_ +q>^Kks7uQlr;QWo"9/?"r;Q^#r:p<jrr<#Wrr)lqrr2lpr!*-!s8N#rrVl]qrVl]os8N&u*W>m4 +s8;Q`qXW=UW1Tc[U7@dGTqA=$iq`HJq>:0js8W)urVl`pr;chOs*t~> +JcGKE(&dgkjNXK<BP(.77o)l_G+>tQ]=l2__un!!b/sG$qoJf[rQP8c!R/^Ha9]i(aj%iPa2uU* +bS84@`l?!;`l6'@`m2rTaMQ0>`Q-!WaT'9WaSEsZaN"2"rlY8^s2P)X,0%dKbg+MXbKJAW_7mXe +P'0r&:fC+Y77^9[E0\2pjR)R9qYpZpqYL/Cs*t~> +K)Z2Wqt^'_p\Oa^rVHBj$iB,Fm-3j%khk.VoCi1crqlNjp]:3grVlotqu-<lqu$Hls6BR`rVc`p +r;ulrq>UBop\=^hs8)Zlrs8H#r;ZfqpAb'Mrr;luqu$BkpAb*jqu?]q!;uin!Vu]nrqcX(oAe`h +me-)5iT94Xm.UAWs8E&rp\ssgqtg<orqubNs*t~> +JcG`Ls8Dut%K?D(rr2]lrV#^&YG.onSI2$]Upnb6p&4acrr2crrVulns8MusrqcWsrqu]ml2C\] +rVlfp!rN#nrr2umr;QWo!W2iors8K$rVuosp](3Orqufrrr;rqr;HTmrqlWorqudIrr<#trVlis +pA=UFaK_V7S=H1>R@pIS]$BO9r;-0_s8W)us8Mrqrqu`nre(6$~> +JcG]K*W?!:qYp?krV$$]k0KZIB44Y18kVcUC5JXh^;%Sb_un$$b/jG%rPnfWrQ>,`!6XQI!6>&Z +rl5\kcGRcLdDa>Rb0%fF`l5p>_SjRq`sBN*`5g$>^<OUTaT'9WaSF!YaSj9\bQH#/`l7qp+2l:D +aN)EHbeh93V1`Sd;+aAQ84QQ]>C2gShsL(/qYC-oqtg*arIb-#~> +Jc>fIrVl]o!<2cn%/&W5jlu$un*/]cmf*.as82oprr)iurqu]mrr;oqqu?Qorr)lXrr2j"s82ip +r;$?lqYh$'s8W#lr;Zfpqu?ZpqZ$HPrr;luqu$Bkq#CBns8W,us8;cks82lrrVuoqrVmB'lf.!l +mHsW8n+5\pjRi?L#Q4JsqYC$drqcWsqt^'eL];l~> +Jc>cIrqcZprW)usrYYP2pX?RFTq@dFUSFN^^Y.c>qu6NjrVliqrpp*hrW)oWrr2j"s8;orr;$?l +rr2lr$2so(rV?Els8DlprrW)tqr7VQs8W)urVuforV?Heru(e8rqlTlqXN^r\"oXhSXH"2R&$IO +]\3&Vrr<#ts8N-!rVccprdk*"~> +Jc>`Jr;Qs!qY9d[qu-O3mGlj$LM:-s92&,V;-eC2XLlBi`59I3`r='Y`r*gK`oP5>`u`.?`Q#g? +bKJ&NaMu6=`Pfm?`4s40a2Gj9`Q#d<`Sno<`r4!Qb5]Q_b5]]bblc24aMn.r*6-.C_o'='Xdt/] +=&N$t:f'SR=^,BlY1;LtoD8Cb!<2ut!WDlop]:6iKE$H~> +JcGWIs8E6$s8W#srV?HlrVm8ohra4imHWcliR[8brrr>tqu$HmqZ#^W!<;op$30r&rVulsr;Zfp +rr<!.rVZWos7u]prVcZms8)cSrr2fqrqZQorr2iprr;orqu?KkqZ?]prqcX)rp8=sk3;:%o'br1 +k2>S(rs\l(qY^6dq>C9mr;-Eirri8qq"XiDs*t~> +K)biLrquiprr)ls"TAAuq>UBn'DhL\^n[ToS=Z=CTVnX%i:QmCr;Q]orVulos8)`os69L_s8)^& +s8Duss8N&rs8W)tr;R9*r;Q`rqZ$Tprr)irqZ#ORrr;usqu$Nor;Qcrp&>I"r;?Eer:o3jWMcJ_ +rga"Xs.9Rk\)@,Zs8W)trr30#rr<#tr.4nFs*t~> +JcGcK!<2ut"oJ)fpA"C\rttY'n)rN=P\jf.:JXe_<*j'dU:%YI^r+(c`W*p[`Q#m:pr2L=!6P)Y +(rsS7`Q?3EaNMcJaMu6=a2uBA`QQ<;`lA"r"3&O'al1>@`r4!RaplG3`lQ<Fbfn>Vbf\#HrP]\q +_nNdiQZlG.9hJ&R;,^V(@:t;&gZJ,'q>L9l%/p)%qt^*cqY9j^qu)0IJ,~> +JcGTH"9/5rrqucur;6BhrVmArm,mHrmd90%i8`_cs82cp!<)lr"8V]bqYL3qrr)ipqu!)cqu?]p +s83K)q"FU_r;$0gs8;iqrVZ]pqu$I(o]kArl/q6slg!j!gZ/&)rri5oq"ap^rrrE"qt^-gL];l~> +K)Z&Sr;6EirVlZn!ri,sr;S/Cp[Q/.Un"$LSslOKVPh;chYR0Ks8;ioq>L?nrr)lrq>(!eqt^0g +s5O%Vs7uZms8Drms5!\Ss8W)prVc`rrr2rtr;Zd@r;HZor;Zfps8DNJgVg@kTqS'LTq7gHTqf*E +l1OoNr;HWls8W(Ls7lVE~> +K)YrOqY9scrri;sq"jmes"F?Jqtg*Wj40ZPC0Oe?;bU1e<a9s:S@cMN`P]X7`5]m>`Pfs?`l6'@ +`50@3a2R#YrPnZSrPniZ!m&C$rPefV!6G/^iQ2&=s2b,\s2ch7aiMN?_o0O3`QQNKbKe5Nb/V?> +`jhh1G[O<@9hJ&R9M8&[BS`b5i9^(3qu6iuqY9j^qYL'hrIY'"~> +JcGWI"TJ>rr;QWo!<2um!VuZkrs\DVhraCilL=!!j5'2"rri5qqt^6err`2oq#$ibqu6]rqu6Nq +qt^*fr!*-"s8Dlqr;$?sp#G#ik3Va>m0)Y4hWF%rrr`2rqu$<jpATgHJ,~> +K)YiMrqccprVlZn!ri/tqu7Q4q>0U4\tbacUR@^NT;/?a`:ETtqu6Wjrr2p%r;6Bfrq?6cs5O%V +s7uZns82fms4mSRs8N#sr;uuqrVHNprVl`p,5_<9rVcQcpYEusVOa6IURe'RUnXT_[cQuRrr)cm +qY^<kr;Z`pJcGTHJ,~> +K)YrOqtp?hrrE#squ?Trs8Drqs!dg7lIE2!D-U4G7n?KO<*Wg\YHk^P`lc6?aNV`E`lH-C`5]sB +a2Z*;iQ1u;q8iQT#ft04b0%fF`l7qs"j"j/bf\)faT'9[aSj6la2uNHaMu9A`P][:bfRrLrl#eo +_nNdqT8%)a8ju*>85<5h>$PZd][>g/q#1'h#Q=AgpA"L]rV6EmrJ(?&~> +JcGZJ!<2rps8Moq!WN&srW3&urVm?+khkLil/q6kjmM6rq#:9prVu`lrsJ]$s8;Zequ$?fr1a2h +s8Dp%s8Mrnr;6?frr3-"qY'XYqu72ujQPdjlL=91l0INggZA"krrE&tr;ZbIs*t~> +K)YuQrVZTloD\gir;RW1rVZQ\e@;<JURmsHS=Q[TZ,bVgq"Fa`r;Qruqu?]nrVZ]Trql`brW)uG +rr2otrr2p%r;QTjrVulrru1n5q<lnJV4a?LStr*PS=cIFTXDu&q>L?nrqu]rrr)ips8;lmrr`9! +rr.ZPJ,~> +JcGBB#6"GrrVc`prVn8@p?gnbWeY7i;GB\T84crcBS;h^^V@n.b0.oNbK.`Lb/VKEbK@rcaSX!O +a90T/b0'_)!64uYs2kDeb0&_bs2P)[rQ5PnbfIcC`Pf[<bfe,Krkfbq]XPAPR!`@B91hfO8ju-@ +;H@=]U;>gSo(;YPrqud"rVH<aqYTsc"9&,orJ1E'~> +JcGcLs8Vckqu6fur;6<br;Zfe%,^%.kj7[(lfR-elLXiO#lXJkqYg9dr;WJirr;oq"8r,srU^%# +r:K%-l1"B=p[%8/kiLjnp&"ahrVZ]qrq69krr2fqrdk(Ls*t~> +JcG`KqYpQpqu?]q!r`,trr3r:qYgBjn`@X"V4sfYSXGt=U8PTIhtm0HqY0sfrrE&srrW/us5EtS +s1eR4s8W)ts!%:<rqcTns7uBOg;^1bT:qmLUR[sIUS=Wp`S0q\q>UEorr2llrr<#qrr2rsrWE,s +r;DBMJ,~> +JcGZJ!<)co#6"DprVuioqu7u<o^1_g]oISR?!L9&8PN#_@!7I$^;7h,^W"=:aMZ'BcHFAScJckA +`qRRQb5'-Wb2LGA`rF-Xat1ZS`5T[6`lc]TaMu9;Z`fp]HXKfR<(]\U7nl`Z>@i2HZe+F/q"t!c +qY^?krrrAuqYL*fo`#$lqYL/Gs*t~> +K)Z#Rq>'pcrql]urquZhqtg<rrquZhqu$Bl%e/iLj6Q!um-EcmhUp]Tr;R*%rr)Wcp\Xphs.TGk +s8W)tquHQ`rt"Y^jQPjomca*)lf$semd0QF"oeK#s8N#rs8N#ss8N"Ks8W+L~> +JcGWI"oeJur;HWms8W$#r;HTnrqQL*p=I<mUnO6GS"?4HVkgN8h=1F=!;ZWo"TJH#rVb[RrVs\4 +rr4>@s8W&np\XpbrVZE`p?LAFX.lDbUS=9MStDIGWOfk$me6JTrV?Hks8N#t!<2ors8E-!s8N&t +rr2rrrW<#rreCH'~> +JcGBB!r_ohrr3-"qtp?krVm<)q"4%?gpiu3DIQUCr_*u(='0*gT<Yo9\%08k_SX73ai_fcaSj-U +aSa3WaSj95aSj6p_o^'?^V%7s`QQ<;]st&-FC/!Gr_=A"779d@>AK%\^=_Q9o_7tRqu-KnrVcTg +qu,s_"9&,orJ1E'~> +K)Z#Rq>'pcrql`qrr2cprqcWsrVZQirqQTlpAP"%q!Hu'jQ>Uflg!WkgtC][p&Ccc!rr9!r;?<h +')h\#m,[0ml0\!*k31segYC]UqZ$Tp!;uir"9/8trr2p"rqu]nrr3'!r;M9Iq>Ys~> +JcGWIs8<#srVcZo#6+T"rr)iqqu7''s8Vurqt]L#\"KSsSeI`kTV&!SUpJD.n+Q_Zs8N#trqtaS +rVuQirr;`lrr:jSqYq];r;Q`opAagGfZL\"S=l=@T:D@?TV.pNWP6sMp\+Oarr30"s8)TirV6Bo +rr)ips8Drqs8N"Os*t~> +JcGBB!r`#nrr<#s"8i&qrql^<rqH9Ykg6;eCM6gJ9M8/S9itY,D2=^]Z+I]b`5]m=a5P,<`r!jT +aoKN^`r='Xb5TK]`ne`6arndF_o0O1]>_7VR>Z2o<)cL`9h.N<8lA\qD2YRDk3r0Frs\c&qY^Bn +rqlQeqYU6YrrE"Ps*t~> +JcG9?rr2op!<2Kf&FAZMl/V4)nEB3*kMk:Vn+-;STDnlgs8)foq>V)ulJq$ijll4,nE]N4mHETp +l1XuR"oJ&jqtp6grr2lqrql`qquH`mrrE&tquZcnreLN(~> +JcG?ArVl]o#QFYtr;Zfrrqu^5q=Wsk]=Fr0SY)F@USOWVS>Ws;h=LI;qYpNBrqufnrql`Qrql^> +rV6$Zp[-nX[]?@%S=?.DS!fhBTV/*m`ma/Equ$?irquZ_s8W(Ls7QDB~> +K)YuPqtg3grVuipp&>0kp\4L^r;Ri7q"*b+b+FQ>APPok6q:*S<)HP%G(Q<n]tM2!aMulRrQ5Ah +aMl'9`l?*uap,r,`l5j7`o+r7aoTMurk0J\Tn-ue?!'lq:/=JP92SM\?&>5\bhqdYq>L?mr;Zfq +rr)iurquWlqu?Wlrs/Gtq"FFVqYPjD!<7Q~> +JcGWIrVlZn#6+PtqYL-hp&>$kqu79-i8Ek`mHNcun*B3'jl,.[q=ajgrqu]WrW)lprr<#Wrqu]g +rq-4(mGQUKjlksnm-X93lL*ruhqI/\q>Up%rVZThqYC$ar;?QnrVlfnrr`8ur;QQm#6+Ptqt^-g +L];l~> +JcGBB!ri/sq#CBns8;lp.K'&?rr2rtrquHYc_mG2StV^CSYD[FUS4Na\'ja@pA4X_r;?Nmrr;uq +s8W&us6fjds8Muts82fms82fns760es7H<jrVufqq]YY.oARj&Y,8(iSt):>SY)=BTV%jIX2ON$ +q#('hqu?Qmqu6Zqp&>$kJcGBBJ,~> +K)Z;YqYL*fs8W&rqtg0drV$6pqtg*`r;Q]q-iX/Gr;--Tkh!tNE+3-R<DQ7`<)QRr>$YZ[O06"# +^;%M#_o9U7`qd[U`pUnJ`q[UZ`l5j7`Q#prb5]Nc`l5j5`o"i^`l5d/^::_ZTo+)4@9HH%8kDNE +9h8/`>%(r`Qe:Nio_87\r;Qisrr)`o!<2inrVlrtqtU-`!r2ZkJcC6~> +JcG3=r;Q?gs8Mio(&%%Mio9%^kj%Etlg*cpjm2=-s8W)srs/K#rqcEcr;?Ek!ri/tr;HWms8N&u +s8E0!qu$Bkr;ZfrrqlltrVlfqrrrE%rVZQirr2oqs8EW/rr2inqtg3dqY^?kr;ZfrrqHF,qXES+ +k2kXblgF-,nF,]/l/(.Uq"4U]rq-6jrqQNkreCH'~> +JcFj3s8Mcm$NC#%r;,g6a/,N(rh'4]&>#MfTUqmWZ,G/Mh=pX@s82Zms8E6&rr2rsrVlTl"9/?# +rqcZmrqud#rr)cmrVc`os8W)ts8N#tr;cimrsAZ(s8Dlqs8Dorrqmi7p[7(rf>=kjU84QXTV%mK +SXuIET;/*V\C9g=qYgBl!WW.Ms5!^*~> +JcG`Jr;Z`op&G!hp]!&JqtTaKki:+'TPn@L>$"Tr8OuEH:/FnqBRPu5R^]fA_SX@:aiDKC`l?!< +`l?'=`PojpaTfi/aN2BA`V[[T`W*jS`W*sXb5TQibf\#G`lH*<`W!mS`W*pfaN;THb/q`Gb/_NB +aMl-t`tHJ5]s"&mMfiN0;H?dt;c-:_8H)3k;-dXNO1*[)nFl_Tqu-KTs8W&rqu?VGrrE(L~> +JcF^/q>LEprqZR!pugMjiofUorU:*]m,d<dht$L<pAY0mr;Q]rrr2rsrVuj&qYU6js8W)rqu6Em +rVl`p!<)op!<)iq#6+Suqu$BkrVcZo"oeQ$r;HWes8Vs3p[RP0iSj.glgF3+lKma"k2bU_jQ6#b +s3L^q~> +JcFC&$i^)(rr2lmpuKW+Vu<>#TqJ'MSt2FFVP^?0cIh7Srq[-&s8MoqrV?<hs8Moqs8N#rs8E<& +rr)lrrr<#trr<#ts8D`mrVccq!WW/urr`6!rVlfrs8E*"rr2iq/,oMEs82]ip\4R]j5&8,\u_Ws +Tq%UDSt)=CS"?.?TVJHj`nU"[q=a[`rdk+$s*t~> +JcF^/s8Dfo1&UkDq"F@FftF)4De!!O:eaSU8k_lQ;d!@4HAIl]\@fMg_8F.+a2Pm2`Q6*<a2c:# +a8X-\aiF>!rl5&Y`;[UZ`lH*=a2c<Fc2Pp!b/hN>`Q$!=a2Q*<bK7lGaN"5#/]l/Xai;98`PB4$ +\[oMfVk96/Ea_m?:.IcD8Ol?H9i=hd=^GfdQ*Jg#n+-F.s4.."~> +JcFR+s8MTh(&[:Oh;@/PlL+**l0@?mm-EcunFZPCs8W)trr`9!qYgEkrVlrur;6Hg!W2lprri;u +r;-EirrMrmr;Qcro`#d'lJq$kkN1jilKdZumI0H,lL!]oiSWeeJcEsoJ,~> +JcF@%s8FSJs8N#qrVZQ^g:s\bTU_OETUq[IUR[jIT:;[Z[DL>MmI^,Fq>L<iqY^Bkr;?]rs8Mln +qu6ZqnG`Ofrql]sp\Ojfs"+-Gr;QZlqY^3_p@\1Nj3kiOVkp/^T:qsQS=ZCKT:;CET;8?d^!c3E +r;HZprW2uqJcF=$J,~> +JcF^/s8Dfo0`CnEp\+=QoCMG7e[L`eC0ah8:/4AP9i4MU;H$CqAoN6\Trtl:]YVS+_Sa@6`Pqeq +$-103c-4>Qa2c3ub6,l,a2\%rs2G&[rlkDa4ibO\`lQBIbfS)P`5Kg@c-"2Ka2c3<_SX$qZa-j: +S;DK'=B&0p:Jk"g:/+JZ8k)6E=(H,lOfm!nmIU&Mp]:*eJcF@%J,~> +JcFR+s8N&u!<)co!rVrpqYqN*jPSnSj5K4gmIK`9p@7\AlK%$klg=3<rqlW^rrE&tqu?Zqs8W'' +r;6Bequ$Ekrr)utqu,p^*W5s;q<mD'gtCH?jmVg2md09)kiq9kjlGC\iq!$FrrrE!q=j^aJcF4! +J,~> +JcFF'5lL`_rr2lorVuoss8Dlhn`JB9XeheeTq%aIS=Q%6S=6"BTqeTn]?8X[io9%fq=j^^r;6Be +p\F[_r;HWps8;lps8E&trqZTor<iK$rVlirs8Mupqu6FEs8Dcep%S:Yq=j=;hVQu8_RQeIU8"KZ +T:VUDS=Q4@T:_^JTqS3X^X2!0qu-Kkrr`9#s8ITLf)L7~> +JcF^/s8Dip48o3Xqtg'\q#C?kqXa(3eAA8HF_5)g=&2Xg92.uL:/+\j>[M,aH]"#XUS=Wi]Y(to +_ns7)_8aO8a8X-\b/sY+s3(MdaSX!WaSs<]`ra5u`W!t8aN)6;_og$:^V%:r^V.1_Un4'AN-T8L +=]/*s:ImlB7Rp*G:f^Y">?b9;B8WIrdH'cjr;QotqY'UZJcF@%J,~> +JcFC&!<2lqs8;rsp\u9-k2G=amH!^$na>i7nEoE"kNUs]gtpuMlL+B@rQY?Sr:p'Wk2PL_hWNq[ +kiqF!l0836$1@<NlfdHik3`$@rsJc*rVl`lr;-<grdk+$s*t~> +JcFC&"9/8urql`prr;mMqtg$Ujjh;XVPL,YU7@jFS"6.BR[ThCU8"E\X0B1PbL,&(mIU/Mp@\+P +p%@tMr;HWorrW/urr2rtrr;p\r;HTns8Mrlp\+CYq=sINp@n+>g![gS\?2[-VOs`YTV8'SURn*N +TUq^HT:MUJVR""dkOn]Lr;HTlqYg>Cs3L^q~> +JcF^/s8Dfos8GIbqtg0ap\4LZqY9dUn*K)eag@[sC0tCH=&Dmj9i4ee;H$_&<Dl^r?"@o"L5_Lp +Xg>UQ]tCqf\[oGfaihuVd*^7ec2,W_c2YucaT0<Y_@jYsZa@0JXeM&;H#mb-=]e^#<rGho;&;kt +9M.lL:/Y"pA8m0hZHM(`kj7d1q>:'h"8r&nrIP"#s*t~> +JcF7"!ri5tr;Qcrp&?6/fA5-?gu78Skj@d(lLF6,lf[<fj5&JCf\,$8h!"(npA3kM*W>g,oC)#- +jl,(Ng"Y?ElfmTrlg*d$kiqF!m-Nm6j9=N#iS`Pjq#:BorVQU!r;-9eq=sr?s4@:$~> +JcF@%s8<'!rVQKjrr`5tqYU3g1B%+Gk0h)?VP0oYTUq^GTq@mFTq@mJT:DOLT;&*XWN<8+]YDG/ +db*C6o(;SJp%J(Or:U-brq6Edo_&1T1[O5[f@%pb_n!4\WhlMdU7n6OS=Q=GSY)CASt)@BR\6IP +TqA$QTuYaLq"agarVccpr;6HmquH_Is3q!u~> +JcF^/s8Dcns8E)tq=ss_55P0Us8N&urVQ<[n*8cDUQ95/A8#.O=&i7$<DlRc7n?3D8kr>`<EWU9 +Anl./IY!96Q(+GT\@]Jj^:q7nrk&6Erk&6Erk/9C2S-E&W1KB>N.l_'E+r`b=BJNt9hS&M9he5U +92&)T:f'ng?!UW<@:sACY0,YcmI^2Kqt^*er;Qfsqu6Nor.4n!s*t~> +JcFF'!WE#irrW2urq?@9rq>U<i7m#EjQZ+$nFH5@lfmd'lKI?jjQ5L]i8N\Vio8qphu_ouj8S9A +kPscGkPsZYjPo(Tk2kX]j5T%UjlGI^jQ,FclMTuYlKRX#mdB<&lf[-am.C5LrrW,qr:g3nrVQKk +JcF@%J,~> +JcFX-rVlis!WE#ps8W&tquH]prW)onrs\i%r:]mNi6K<PX/)HgT`:GcS=lICS"HFLrLjUnUS+?U +US=NYUo13kVuirsW;`n*Y-"k/Xf/1rVl'Ej#c+2gU8+HVUS@^\s.]C_&tYYdStVjLSY2[QZG=W8 +kk4iLrquooq#('i#QFYsq=smdrdk*ts*t~> +JcF^/s8DZkrr)ln!<2fo0)PG8naGi/khb.=\YGC@D.-UJ;bfhM7nQBC852lV;,C.g<**+%<E)pr +;cHk%r`]J.=BJr0@239\@:*5A=B\j3>$+m+;Gg=j;c6UprDW_q!)EMhs%sY3;,gS!>?=s4@r?m^ +U9r,!k3MR/o^_PEqY^@#rVH?`qYL*dqYL,@s474#~> +JcF=$!ri/tqYpTqr;QTnquQcqqu6Zqq>UZmmdKo;j5g1&!p8b4rp0dTlg!d$rp9[N&*iEElKdg* +n*]Q/lg*p(mf)Z!md'0$l0e$/mdBH-lfm^"lg*j$l0.9kkN:gaj5/e^nF?AMrri?!qtg3hrri>t +q>1$_rrE%Ls474#~> +JcFX-rVl`p%0$5)s8Muqr;Q]qs8Mio)ZK[7s8Muss8Mc\jk%Sd[C3$(SYDjOSt)@CrL`tY!2'7^ +#+qQ]T:_dLrgs.^qORe[StDYPT)YE,S=Q:FT:VUESt;RJTqJ*STV\m%\\cbJlLarMqY^?ls8W)s +rrE&trr`6!rql]n!rDioJcF4!J,~> +JcF^/s8D]l#6"Q$s8Doqq#<5Jq=sa^q>:$^naGc&e&A\fN.#hjAQi;D>Zb!';,C%a9heAZ:ej\W +7n,s=84cBC779O68cDB_8H;9Z74Uo$91hW?77Tj>91qlM:/=_`:JXni='Jp7@:a"dH@gm6U9D\k +j65h"q#(-k"TJAsqY^6j$2j\sqY0d^qu-JEs474#~> +JcF4!!<2or#6+Puqu$BklMh=in`o9"lJUX^lg=$)nG_hUn,Dh`n*]W0n*]T6n*^,?,4=pfnaYr5 +kiV*so'u5?n*TT2n+#o7m-j?%h;dhglg=EFoDejip&+dfJcF'rJ,~> +JcFX-qu6$`s8N#rpAPs0rVlfpnE8QO`4WUhV4jNTT:DCAS=H.@SGo)ZSd1g[St)LGStGnOs.(=+ +S"cIGTU_UES=Q4@St)CFT:DC@TqA$W[(*W^bhD.Jq>U6or;HTnrp'O]rdk+#s*t~> +JcF^/s8DQhs82ipp](9ls82ip+TME=qtTgRm-!BdhUK`_Y+Ll7Jo,"&>#e?l:Jak_91f+Qs%*Gd +9LhH@77TlH8MEY'6:41.9M/#Q7Rfm;8kVcN9i"V_9h\;_?=e)'KSbqh[`-hVk3D:$o_/(TqYU5B +s1SG_~> +JcF4!!<2rss8N&r!rMonn,ELgqtp?brs8A`iS`_UjQ5V)l2U#Kk5OZKn)s-,rTkEin+,u<l0d]q +jm;I&l0@Hmk2YFXgu%Akrq-3krr)Nhr;?Qnrqufns82lrJcF-tJ,~> +JcFX-qu6Ek!<2`ms8E9%r;HWps8N#srVlfnrt>>/qYBp]pZUMab.FaMTVA-QT`1S`TE_*\T:VUF +Qhm9XSXuIHS"lVTTH0c"T;&$OU8"?RStW3r`RNW'o(VkQqt9d`rr;usjT#8Z!r`,tJcF@%J,~> +JcF^/s8DNgq#0[]-2dW8q=s[TmHNZefYb+nQA'Bn@qB1Z?!:9.;cQdn;,0bX6:jcI9*n0[7Rfm; +:et(krDXY<>?kTG@q&kYE.<nHZ,"W8f\biOlh'uLrdk*Vs*t~> +JcF:#rr2lrs8N#q"8i#orr)j!qt^-eq#:EprVc'^s8E?$r:p-crVZ0OmeuMPmeuMXq"OX\q>:*g +l2Ue^!rW&srr;ioq>^<jJcF*sJ,~> +JcFL)rVl]os8;rspAY-lr;Zfrs8;rqrr!!!rVlfprr*o9r;6?hqtg6ep\4LSn*/leeBc=X`4W^l +\$Vs&qORYU*M9"/ZaREV^r4=BfA#9Kme-AOqYU3equ-NnrVQQls8W)js8MutrVc`jrrE&tr;chJ +s4@:$~> +JcEpn!<)oorr)9b9)SP^q"F=Lmd9?(kiLg^iRcJu]s4E'P)P0EG]I_9<_Q1^:/F\Z91MKG:h4Bb +H[^X+P+JVV]>r:Qi8j%bm-<s*nal;@o_SI`r;QcorqcZls8DTi!<)oo!<%KKd/SU~> +%%EndData +showpage +%%Trailer +end +%%EOF diff --git a/doc/gnupg-badge-openpgp.jpg b/doc/gnupg-badge-openpgp.jpg new file mode 100644 index 000000000..d396b7c38 Binary files /dev/null and b/doc/gnupg-badge-openpgp.jpg differ diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 478bb4395..d74a76ca9 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -82,8 +82,16 @@ Boston, MA 02111-1307 USA @title Using the GNU Privacy Guard @subtitle Version @value{VERSION} @subtitle @value{UPDATED} + +@sp 6 + +@image{gnupg-badge-openpgp,8cm,,The GnuPG Logo} + +@sp 6 + @author Werner Koch @code{(wk@@gnupg.org)} + @page @vskip 0pt plus 1filll @copyrightnotice{} @@ -111,6 +119,7 @@ the administration and the architecture. Developer information * Assuan:: Description of the Assuan protocol. +* System Notes:: Notes pertaining to certain OSes. Miscellaneous @@ -133,6 +142,7 @@ Indices @include scdaemon.texi @include assuan.texi +@include sysnotes.texi @include tools.texi @include debugging.texi diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 28d99673d..9d2cdfc46 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -135,7 +135,7 @@ below the home directory of the user. Set the name of the home directory to @var{dir}. If his option is not used, the home directory defaults to @file{~/.gnupg}. It is only recognized when given on the command line. It also overrides any home -directory stated through the environment variable @var{GNUPGHOME} or +directory stated through the environment variable @env{GNUPGHOME} or (on W32 systems) by means on the Registry entry @var{HKCU\Software\GNU\GnuPG:HomeDir}. diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 4c167ebf5..1e7368041 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -241,7 +241,7 @@ below the home directory of the user. Set the name of the home directory to @var{dir}. If his option is not used, the home directory defaults to @file{~/.gnupg}. It is only recognized when given on the command line. It also overrides any home -directory stated through the environment variable @var{GNUPGHOME} or +directory stated through the environment variable @env{GNUPGHOME} or (on W32 systems) by means on the Registry entry @var{HKCU\Software\GNU\GnuPG:HomeDir}. diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 5265ed21e..cb165da35 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -86,7 +86,7 @@ below the home directory of the user. Set the name of the home directory to @var{dir}. If his option is not used, the home directory defaults to @file{~/.gnupg}. It is only recognized when given on the command line. It also overrides any home -directory stated through the environment variable @var{GNUPGHOME} or +directory stated through the environment variable @env{GNUPGHOME} or (on W32 systems) by means on the Registry entry @var{HKCU\Software\GNU\GnuPG:HomeDir}. diff --git a/doc/sysnotes.texi b/doc/sysnotes.texi new file mode 100644 index 000000000..6ca10c195 --- /dev/null +++ b/doc/sysnotes.texi @@ -0,0 +1,107 @@ +@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 System Notes +@chapter Notes pertaining to certain OSes. + +GnuPG has been developed on GNU/Linux systems and is know to work on +almost all Free OSes. All modern POSIX systems should be supproted +right now, however there are probably a lot of smaller glitches we need +to fix first. The major problem areas are: + +@itemize +@item +For logging to sockets and other internal operations the +@code{fopencookie} function (@code{funopen} under *BSD) is used. This +is a very convient function which makes it possible to create outputs in +a structures and easy maintainable way. The drawback however is that +most proprietary OSes don't support this function. At g10@tie{}Code we +have looked into several ways on how to overcome this limitation but no +sufficiently easy and maintainable way has been found. Porting +@emph{glibc} to a general POSIX system is of course an option and would +make writing portable software much easier; this it has not yet been +done and the system administrator wouldneed to cope with the GNU +specific admin things in addition to the generic ones of his system. + +We have now settled to use explicit stdio wrappers with a functionality +similar to funopen. Although the code for this has already been written +(@emph{libestream}), we have not yet changed GnuPG to use it. + +This means that on systems not supporting either @code{funopen} or +@code{fopencookie}, logging to a socket won't work, prompts are not +formatted as pretty as theyshould be and @command{gpgsm}'s +@code{LISTKEYS} Assuan command does not work. + +@item +We are planning to use file descriptor passing for interprocess +communication. This will allow us save a lot of resources and improve +performance of certain operations a lot. Systems not supporting this +won't gain these benefits but we try to keep them working the satndard +way as it is done today. + +@item +We require more or less full POSIX compatibility. This has been +arround for 15 years now and thus we don't believe it makes sense to +support non POSIX systems anymore. Well, we of course the usual +workarounds for near POSIX systems well be applied. + +There is one exception of this rule: Systems based the Microsoft Windows +API (called here @emph{W32}) will be supported to some extend. + +@end itemize + + +@menu +* W32 Notes:: Microsoft Windows Notes +@end menu + + +@node W32 Notes +@section Microsoft Windows Notes + +The port to Microsoft Windows based OSes is pretty new and has some +limitations we might remove over time. Note, that we have not yet done +any security audit and you should not use any valuable private key. In +particular, @strong{using it on a box with more than one user, might +lead to a key compromise}. + +@noindent +Current limitations are: + +@itemize +@item +The @code{LISTKEYS} Assuan command of @command{gpgsm} is not supported. +Using the command line options @option{--list-keys} or +@option{--list-secret-keys} does however work. + +@item +No support for CRL checks. By default the option +@option{--disable-crl-checks} has been turned on and the log will show +an appropriate warning message. The reason for this is that the +separate CRL checking daemin (@command{dirmngr}) has not been ported to +W32. + +@item +@command{gpgconf} does not create backup files, so in case of trouble +your configuration file might get lost. + +@item +@command{watchgnupg} is not available. Logging to sockets is not +possible. + +@item +The periodical smartcard status checking done by @command{scdaemon} is +not yet supported. + +@item +Detached running of the gpg-agent is not directly supported. It needs +to be started in a console and left alone then. + +@end itemize + + + + + + diff --git a/doc/tools.texi b/doc/tools.texi index 086f71df1..53233cbd0 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -12,10 +12,11 @@ GnuPG comes with a couple of smaller tools: * addgnupghome:: Create .gnupg home directories. * gpgconf:: Modify .gnupg home directories. * gpgsm-gencert.sh:: Generate an X.509 certificate request. +* gpg-preset-passphrase:: Put a passphrase into the cache. @end menu @c -@c WATHCGNUPG +@c WATCHGNUPG @c @node watchgnupg @section Read logs from a socket @@ -593,3 +594,504 @@ whicl will be printed to stdout. +@c +@c GPG-PRESET-PASSPHRASE +@c +@node gpg-preset-passphrase +@section Put a passphrase into the cache. + +XXXX +The @command{gpgconf} is a utility to automatically and reasonable +safely query and modify configuration files in the @file{.gnupg} home +directory. It is designed not to be invoked manually by the user, but +automatically by graphical user interfaces (GUI).@footnote{Please note +that currently no locking is done, so concurrent access should be +avoided. There are some precautions to avoid corruption with +concurrent usage, but results may be inconsistent and some changes may +get lost. The stateless design makes it difficult to provide more +guarantees.} + +@command{gpgconf} provides access to the configuration of one or more +components of the GnuPG system. These components correspond more or +less to the programs that exist in the GnuPG framework, like GnuPG, +GPGSM, DirMngr, etc. But this is not a strict one-to-one +relationship. Not all configuration options are available through +@command{gpgconf}. @command{gpgconf} provides a generic and abstract +method to access the most important configuration options that can +feasibly be controlled via such a mechanism. + +@command{gpgconf} can be used to gather and change the options +available in each component, and can also provide their default +values. @command{gpgconf} will give detailed type information that +can be used to restrict the user's input without making an attempt to +commit the changes. + +@command{gpgconf} provides the backend of a configuration editor. The +configuration editor would usually be a graphical user interface +program, that allows to display the current options, their default +values, and allows the user to make changes to the options. These +changes can then be made active with @command{gpgconf} again. Such a +program that uses @command{gpgconf} in this way will be called GUI +throughout this section. + +@menu +* Invoking gpgconf:: List of all commands and options. +* Format conventions:: Formatting conventions relevant for all commands. +* Listing components:: List all gpgconf components. +* Listing options:: List all options of a component. +* Changing options:: Changing options of a component. +@end menu + + +@node Invoking gpgconf +@subsection Invoking gpgconf + +One of the following commands must be given: + +@table @gnupgtabopt +@item --list-components +List all components. This is the default command used if none is +specified. + +@item --list-options @var{component} +List all options of the component @var{component}. + +@item --change-options @var{component} +Change the options of the component @var{component}. +@end table + +The following options may be used: + +@table @gnupgtabopt +@c FIXME: Not yet supported. +@c @item -o @var{file} +@c @itemx --output @var{file} +@c Use @var{file} as output file. + +@item -v +@itemx --verbose +Outputs additional information while running. Specifically, this +extends numerical field values by human-readable descriptions. + +@c FIXME: Not yet supported. +@c @item -n +@c @itemx --dry-run +@c Do not actually change anything. Useful together with +@c @code{--change-options} for testing purposes. + +@item -r +@itemx --runtime +Only used together with @code{--change-options}. If one of the +modified options can be changed in a running daemon process, signal +the running daemon to ask it to reparse its configuration file after +changing. + +This means that the changes will take effect at run-time, as far as +this is possible. Otherwise, they will take effect at the next start +of the respective backend programs. +@end table + + +@node Format conventions +@subsection Format conventions + +Some lines in the output of @command{gpgconf} contain a list of +colon-separated fields. The following conventions apply: + +@itemize @bullet +@item +The GUI program is required to strip off trailing newline and/or +carriage return characters from the output. + +@item +@command{gpgconf} will never leave out fields. If a certain version +provides a certain field, this field will always be present in all +@command{gpgconf} versions from that time on. + +@item +Future versions of @command{gpgconf} might append fields to the list. +New fields will always be separated from the previously last field by +a colon separator. The GUI should be prepared to parse the last field +it knows about up until a colon or end of line. + +@item +Not all fields are defined under all conditions. You are required to +ignore the content of undefined fields. +@end itemize + +There are several standard types for the content of a field: + +@table @asis +@item verbatim +Some fields contain strings that are not escaped in any way. Such +fields are described to be used @emph{verbatim}. These fields will +never contain a colon character (for obvious reasons). No de-escaping +or other formatting is required to use the field content. This is for +easy parsing of the output, when it is known that the content can +never contain any special characters. + +@item percent-escaped +Some fields contain strings that are described to be +@emph{percent-escaped}. Such strings need to be de-escaped before +their content can be presented to the user. A percent-escaped string +is de-escaped by replacing all occurences of @code{%XY} by the byte +that has the hexadecimal value @code{XY}. @code{X} and @code{Y} are +from the set @code{0-9a-f}. + +@item localised +Some fields contain strings that are described to be @emph{localised}. +Such strings are translated to the active language and formatted in +the active character set. + +@item @w{unsigned number} +Some fields contain an @emph{unsigned number}. This number will +always fit into a 32-bit unsigned integer variable. The number may be +followed by a space, followed by a human readable description of that +value (if the verbose option is used). You should ignore everything +in the field that follows the number. + +@item @w{signed number} +Some fields contain a @emph{signed number}. This number will always +fit into a 32-bit signed integer variable. The number may be followed +by a space, followed by a human readable description of that value (if +the verbose option is used). You should ignore everything in the +field that follows the number. + +@item option +Some fields contain an @emph{option} argument. The format of an +option argument depends on the type of the option and on some flags: + +@table @asis +@item no argument +The simplest case is that the option does not take an argument at all +(@var{type} @code{0}). Then the option argument is an unsigned number +that specifies how often the option occurs. If the @code{list} flag +is not set, then the only valid number is @code{1}. Options that do +not take an argument never have the @code{default} or @code{optional +arg} flag set. + +@item number +If the option takes a number argument (@var{alt-type} is @code{2} or +@code{3}), and it can only occur once (@code{list} flag is not set), +then the option argument is either empty (only allowed if the argument +is optional), or it is a number. A number is a string that begins +with an optional minus character, followed by one or more digits. The +number must fit into an integer variable (unsigned or signed, +depending on @var{alt-type}). + +@item number list +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of numbers as described above. + +@item string +If the option takes a string argument (@var{alt-type} is 1), and it +can only occur once (@code{list} flag is not set) then the option +argument is either empty (only allowed if the argument is optional), +or it starts with a double quote character (@code{"}) followed by a +percent-escaped string that is the argument value. Note that there is +only a leading double quote character, no trailing one. The double +quote character is only needed to be able to differentiate between no +value and the empty string as value. + +@item string list +If the option takes a number argument and it can occur more than once, +then the option argument is either empty, or it is a comma-separated +list of string arguments as described above. +@end table +@end table + +The active language and character set are currently determined from +the locale environment of the @command{gpgconf} program. + +@c FIXME: Document the active language and active character set. Allow +@c to change it via the command line? + + +@node Listing components +@subsection Listing components + +The command @code{--list-components} will list all components that can +be configured with @command{gpgconf}. Usually, one component will +correspond to one GnuPG-related program and contain the options of +that programs configuration file that can be modified using +@command{gpgconf}. However, this is not necessarily the case. A +component might also be a group of selected options from several +programs, or contain entirely virtual options that have a special +effect rather than changing exactly one option in one configuration +file. + +A component is a set of configuration options that semantically belong +together. Furthermore, several changes to a component can be made in +an atomic way with a single operation. The GUI could for example +provide a menu with one entry for each component, or a window with one +tabulator sheet per component. + +The command argument @code{--list-components} lists all available +components, one per line. The format of each line is: + +@code{@var{name}:@var{description}} + +@table @var +@item name +This field contains a name tag of the component. The name tag is used +to specify the component in all communication with @command{gpgconf}. +The name tag is to be used @emph{verbatim}. It is thus not in any +escaped format. + +@item description +The @emph{string} in this field contains a human-readable description +of the component. It can be displayed to the user of the GUI for +informational purposes. It is @emph{percent-escaped} and +@emph{localized}. +@end table + +Example: +@example +$ gpgconf --list-components +gpg:GPG for OpenPGP +gpg-agent:GPG Agent +scdaemon:Smartcard Daemon +gpgsm:GPG for S/MIME +dirmngr:Directory Manager +@end example + + +@node Listing options +@subsection Listing options + +Every component contains one or more options. Options may be gathered +into option groups to allow the GUI to give visual hints to the user +about which options are related. + +The command argument @code{@w{--list-options @var{component}}} lists +all options (and the groups they belong to) in the component +@var{component}, one per line. @var{component} must be the string in +the field @var{name} in the output of the @code{--list-components} +command. + +There is one line for each option and each group. First come all +options that are not in any group. Then comes a line describing a +group. Then come all options that belong into each group. Then comes +the next group and so on. There does not need to be any group (and in +this case the output will stop after the last non-grouped option). + +The format of each line is: + +@code{@var{name}:@var{flags}:@var{level}:@var{description}:@var{type}:@var{alt-type}:@var{argname}:@var{default}:@var{argdef}:@var{value}} + +@table @var +@item name +This field contains a name tag for the group or option. The name tag +is used to specify the group or option in all communication with +@command{gpgconf}. The name tag is to be used @emph{verbatim}. It is +thus not in any escaped format. + +@item flags +The flags field contains an @emph{unsigned number}. Its value is the +OR-wise combination of the following flag values: + +@table @code +@item group (1) +If this flag is set, this is a line describing a group and not an +option. +@end table + +The following flag values are only defined for options (that is, if +the @code{group} flag is not used). + +@table @code +@item optional arg (2) +If this flag is set, the argument is optional. This is never set for +@var{type} @code{0} (none) options. + +@item list (4) +If this flag is set, the option can be given multiple times. + +@item runtime (8) +If this flag is set, the option can be changed at runtime. + +@item default (16) +If this flag is set, a default value is available. + +@item default desc (32) +If this flag is set, a (runtime) default is available. This and the +@code{default} flag are mutually exclusive. + +@item no arg desc (64) +If this flag is set, and the @code{optional arg} flag is set, then the +option has a special meaning if no argument is given. +@end table + +@item level +This field is defined for options and for groups. It contains an +@emph{unsigned number} that specifies the expert level under which +this group or option should be displayed. The following expert levels +are defined for options (they have analogous meaning for groups): + +@table @code +@item basic (0) +This option should always be offered to the user. + +@item advanced (1) +This option may be offered to advanced users. + +@item expert (2) +This option should only be offered to expert users. + +@item invisible (3) +This option should normally never be displayed, not even to expert +users. + +@item internal (4) +This option is for internal use only. Ignore it. +@end table + +The level of a group will always be the lowest level of all options it +contains. + +@item description +This field is defined for options and groups. The @emph{string} in +this field contains a human-readable description of the option or +group. It can be displayed to the user of the GUI for informational +purposes. It is @emph{percent-escaped} and @emph{localized}. + +@item type +This field is only defined for options. It contains an @emph{unsigned +number} that specifies the type of the option's argument, if any. The +following types are defined: + +Basic types: + +@table @code +@item none (0) +No argument allowed. + +@item string (1) +An @emph{unformatted string}. + +@item int32 (2) +A @emph{signed number}. + +@item uint32 (3) +An @emph{unsigned number}. +@end table + +Complex types: + +@table @code +@item pathname (32) +A @emph{string} that describes the pathname of a file. The file does +not necessarily need to exist. + +@item ldap server (33) +A @emph{string} that describes an LDAP server in the format: + +@code{@var{hostname}:@var{port}:@var{username}:@var{password}:@var{base_dn}} +@end table + +More types will be added in the future. Please see the @var{alt-type} +field for information on how to cope with unknown types. + +@item alt-type +This field is identical to @var{type}, except that only the types +@code{0} to @code{31} are allowed. The GUI is expected to present the +user the option in the format specified by @var{type}. But if the +argument type @var{type} is not supported by the GUI, it can still +display the option in the more generic basic type @var{alt-type}. The +GUI must support all the defined basic types to be able to display all +options. More basic types may be added in future versions. If the +GUI encounters a basic type it doesn't support, it should report an +error and abort the operation. + +@item argname +This field is only defined for options with an argument type +@var{type} that is not @code{0}. In this case it may contain a +@emph{percent-escaped} and @emph{localised string} that gives a short +name for the argument. The field may also be empty, though, in which +case a short name is not known. + +@item default +This field is defined only for options. Its format is that of an +@emph{option argument} (@xref{Format conventions}, for details). If +the default value is empty, then no default is known. Otherwise, the +value specifies the default value for this option. Note that this +field is also meaningful if the option itself does not take a real +argument. + +@item argdef +This field is defined only for options for which the @code{optional +arg} flag is set. If the @code{no arg desc} flag is not set, its +format is that of an @emph{option argument} (@xref{Format +conventions}, for details). If the default value is empty, then no +default is known. Otherwise, the value specifies the default value +for this option. If the @code{no arg desc} flag is set, the field is +either empty or contains a description of the effect of this option if +no argument is given. Note that this field is also meaningful if the +option itself does not take a real argument. + +@item value +This field is defined only for options. Its format is that of an +@emph{option argument}. If it is empty, then the option is not +explicitely set in the current configuration, and the default applies +(if any). Otherwise, it contains the current value of the option. +Note that this field is also meaningful if the option itself does not +take a real argument. +@end table + + +@node Changing options +@subsection Changing options + +The command @w{@code{--change-options @var{component}}} will attempt +to change the options of the component @var{component} to the +specified values. @var{component} must be the string in the field +@var{name} in the output of the @code{--list-components} command. You +have to provide the options that shall be changed in the following +format on standard input: + +@code{@var{name}:@var{flags}:@var{new-value}} + +@table @var +@item name +This is the name of the option to change. @var{name} must be the +string in the field @var{name} in the output of the +@code{--list-options} command. + +@item flags +The flags field contains an @emph{unsigned number}. Its value is the +OR-wise combination of the following flag values: + +@table @code +@item default (16) +If this flag is set, the option is deleted and the default value is +used instead (if applicable). +@end table + +@item new-value +The new value for the option. This field is only defined if the +@code{default} flag is not set. The format is that of an @emph{option +argument}. If it is empty (or the field is omitted), the default +argument is used (only allowed if the argument is optional for this +option). Otherwise, the option will be set to the specified value. +@end table + +Examples: + +To set the force option, which is of basic type @code{none (0)}: + +@example +$ echo 'force:0:1' | gpgconf --change-options dirmngr +@end example + +To delete the force option: + +@example +$ echo 'force:16:' | gpgconf --change-options dirmngr +@end example + +The @code{--runtime} option can influence when the changes take +effect. + + + diff --git a/jnlib/w32-afunix.c b/jnlib/w32-afunix.c index eac4f9560..c93d389da 100644 --- a/jnlib/w32-afunix.c +++ b/jnlib/w32-afunix.c @@ -49,17 +49,18 @@ _w32_sock_connect (int sockfd, struct sockaddr * addr, int addrlen) struct sockaddr_in myaddr; struct sockaddr_un * unaddr; FILE * fp; - int port = 0; + int port; unaddr = (struct sockaddr_un *)addr; fp = fopen (unaddr->sun_path, "rb"); if (!fp) - return -1; + return -1; fscanf (fp, "%d", &port); fclose (fp); + /* XXX: set errno in this case */ if (port < 0 || port > 65535) - return -1; + return -1; myaddr.sin_family = AF_INET; myaddr.sin_port = port; diff --git a/sm/ChangeLog b/sm/ChangeLog index 0dcaa9c20..7a16cb570 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,6 +1,7 @@ 2004-12-21 Werner Koch <wk@g10code.com> * gpgsm.c (main): Use default_homedir(). + (main) [W32]: Default to disabled CRL checks. 2004-12-20 Werner Koch <wk@g10code.com> diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 935d50474..074027bf2 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -757,6 +757,9 @@ main ( int argc, char **argv) opt.def_cipher_algoid = "1.2.840.113549.3.7"; /*des-EDE3-CBC*/ opt.homedir = default_homedir (); +#ifdef HAVE_W32_SYSTEM + opt.no_crl_checks = 1; +#endif /* First check whether we have a config file on the commandline */ orig_argc = argc; diff --git a/tools/ChangeLog b/tools/ChangeLog index 34e985947..38b9e9cf4 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2004-12-21 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c (get_config_pathname) [DOSISH]: Detect absolute + pathnames with a drive letter. + 2004-12-15 Werner Koch <wk@g10code.com> * Makefile.am (bin_PROGRAMS) [W32]: Do not build watchgnupg. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index fe696301c..e4758c1e6 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1272,7 +1272,13 @@ get_config_pathname (gc_component_t component, gc_backend_t backend) else pathname = ""; +#ifdef HAVE_DOSISH_SYSTEM + if (!(pathname[0] + && pathname[1] == ':' + && (pathname[2] == '/' || pathname[2] == '\\'))) +#else if (pathname[0] != '/') +#endif gc_error (1, 0, "Option %s, needed by backend %s, is not absolute", gc_backend[backend].option_config_filename, gc_backend[backend].name); -- cgit v1.2.3 From e5f5833d0745dddd63f7fa61c9cd958277b150bd Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Dec 2004 20:47:04 +0000 Subject: (gpg-preset-passphrase): New section. --- doc/ChangeLog | 2 + doc/tools.texi | 516 +++++---------------------------------------------------- 2 files changed, 44 insertions(+), 474 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 41d6b811b..f6f41f2b5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,7 @@ 2004-12-21 Werner Koch <wk@g10code.com> + * tools.texi (gpg-preset-passphrase): New section. + * gnupg-badge-openpgp.eps, gnupg-badge-openpgp.jpg: New * gnupg.texi: Add a logo. * sysnotes.texi: New. diff --git a/doc/tools.texi b/doc/tools.texi index 53233cbd0..a7081e429 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -600,498 +600,66 @@ whicl will be printed to stdout. @node gpg-preset-passphrase @section Put a passphrase into the cache. -XXXX -The @command{gpgconf} is a utility to automatically and reasonable -safely query and modify configuration files in the @file{.gnupg} home -directory. It is designed not to be invoked manually by the user, but -automatically by graphical user interfaces (GUI).@footnote{Please note -that currently no locking is done, so concurrent access should be -avoided. There are some precautions to avoid corruption with -concurrent usage, but results may be inconsistent and some changes may -get lost. The stateless design makes it difficult to provide more -guarantees.} - -@command{gpgconf} provides access to the configuration of one or more -components of the GnuPG system. These components correspond more or -less to the programs that exist in the GnuPG framework, like GnuPG, -GPGSM, DirMngr, etc. But this is not a strict one-to-one -relationship. Not all configuration options are available through -@command{gpgconf}. @command{gpgconf} provides a generic and abstract -method to access the most important configuration options that can -feasibly be controlled via such a mechanism. - -@command{gpgconf} can be used to gather and change the options -available in each component, and can also provide their default -values. @command{gpgconf} will give detailed type information that -can be used to restrict the user's input without making an attempt to -commit the changes. - -@command{gpgconf} provides the backend of a configuration editor. The -configuration editor would usually be a graphical user interface -program, that allows to display the current options, their default -values, and allows the user to make changes to the options. These -changes can then be made active with @command{gpgconf} again. Such a -program that uses @command{gpgconf} in this way will be called GUI -throughout this section. +The @command{gpg-preset-passphrase} is a utility to seed the internal +cache of a running @command{gpg-agent} with passphrases. This is mainly +useful for unatteneded machines, where a pinentry may not be used and +the passphrases for the to be used keys should be given at machine +startup. + +Passphrases set with this utility don't expire unless the +@option{--forget} option is used to explicitly clear them from the cache +--- or @command{gpg-agent} is either restarted or reloaded (by sending a +SIGHUP to it). It is necessary to allow this passphrase presetting by +starting @command{gpg-agent} with the +@option{--allow-preset-passphrase}. @menu -* Invoking gpgconf:: List of all commands and options. -* Format conventions:: Formatting conventions relevant for all commands. -* Listing components:: List all gpgconf components. -* Listing options:: List all options of a component. -* Changing options:: Changing options of a component. +* Invoking gpg-preset-passphrase:: List of all commands and options. @end menu -@node Invoking gpgconf -@subsection Invoking gpgconf +@node Invoking gpg-preset-passphrase +@subsection List of all commands and options. -One of the following commands must be given: +@noindent +@command{gpg-preset-passphrase} is invoked this way: + +@example +gpg-preset-passphrase [options] [command] @var{keygrip} +@end example + +@var{keygrip} is a 40 character string of hexadecimal characters +identifying the key for which the passphrase should be set or cleared. +This @emph{keygrip} is listed along with the key when running the +command: @code{gpgsm --dump-secret-keys}. One of the following commands +must be given: @table @gnupgtabopt -@item --list-components -List all components. This is the default command used if none is -specified. +@item --preset +Preset a passphrase. This is what you usually will +use. @command{gpg-preset-passphrase} will then read the passphrase form +@code{stdin}. -@item --list-options @var{component} -List all options of the component @var{component}. +@item --forget +Clear the passphrase for the given keygrip from the cache. -@item --change-options @var{component} -Change the options of the component @var{component}. @end table The following options may be used: @table @gnupgtabopt -@c FIXME: Not yet supported. -@c @item -o @var{file} -@c @itemx --output @var{file} -@c Use @var{file} as output file. - @item -v @itemx --verbose -Outputs additional information while running. Specifically, this -extends numerical field values by human-readable descriptions. - -@c FIXME: Not yet supported. -@c @item -n -@c @itemx --dry-run -@c Do not actually change anything. Useful together with -@c @code{--change-options} for testing purposes. - -@item -r -@itemx --runtime -Only used together with @code{--change-options}. If one of the -modified options can be changed in a running daemon process, signal -the running daemon to ask it to reparse its configuration file after -changing. - -This means that the changes will take effect at run-time, as far as -this is possible. Otherwise, they will take effect at the next start -of the respective backend programs. -@end table - - -@node Format conventions -@subsection Format conventions - -Some lines in the output of @command{gpgconf} contain a list of -colon-separated fields. The following conventions apply: - -@itemize @bullet -@item -The GUI program is required to strip off trailing newline and/or -carriage return characters from the output. - -@item -@command{gpgconf} will never leave out fields. If a certain version -provides a certain field, this field will always be present in all -@command{gpgconf} versions from that time on. - -@item -Future versions of @command{gpgconf} might append fields to the list. -New fields will always be separated from the previously last field by -a colon separator. The GUI should be prepared to parse the last field -it knows about up until a colon or end of line. - -@item -Not all fields are defined under all conditions. You are required to -ignore the content of undefined fields. -@end itemize - -There are several standard types for the content of a field: - -@table @asis -@item verbatim -Some fields contain strings that are not escaped in any way. Such -fields are described to be used @emph{verbatim}. These fields will -never contain a colon character (for obvious reasons). No de-escaping -or other formatting is required to use the field content. This is for -easy parsing of the output, when it is known that the content can -never contain any special characters. - -@item percent-escaped -Some fields contain strings that are described to be -@emph{percent-escaped}. Such strings need to be de-escaped before -their content can be presented to the user. A percent-escaped string -is de-escaped by replacing all occurences of @code{%XY} by the byte -that has the hexadecimal value @code{XY}. @code{X} and @code{Y} are -from the set @code{0-9a-f}. - -@item localised -Some fields contain strings that are described to be @emph{localised}. -Such strings are translated to the active language and formatted in -the active character set. - -@item @w{unsigned number} -Some fields contain an @emph{unsigned number}. This number will -always fit into a 32-bit unsigned integer variable. The number may be -followed by a space, followed by a human readable description of that -value (if the verbose option is used). You should ignore everything -in the field that follows the number. - -@item @w{signed number} -Some fields contain a @emph{signed number}. This number will always -fit into a 32-bit signed integer variable. The number may be followed -by a space, followed by a human readable description of that value (if -the verbose option is used). You should ignore everything in the -field that follows the number. - -@item option -Some fields contain an @emph{option} argument. The format of an -option argument depends on the type of the option and on some flags: - -@table @asis -@item no argument -The simplest case is that the option does not take an argument at all -(@var{type} @code{0}). Then the option argument is an unsigned number -that specifies how often the option occurs. If the @code{list} flag -is not set, then the only valid number is @code{1}. Options that do -not take an argument never have the @code{default} or @code{optional -arg} flag set. - -@item number -If the option takes a number argument (@var{alt-type} is @code{2} or -@code{3}), and it can only occur once (@code{list} flag is not set), -then the option argument is either empty (only allowed if the argument -is optional), or it is a number. A number is a string that begins -with an optional minus character, followed by one or more digits. The -number must fit into an integer variable (unsigned or signed, -depending on @var{alt-type}). - -@item number list -If the option takes a number argument and it can occur more than once, -then the option argument is either empty, or it is a comma-separated -list of numbers as described above. - -@item string -If the option takes a string argument (@var{alt-type} is 1), and it -can only occur once (@code{list} flag is not set) then the option -argument is either empty (only allowed if the argument is optional), -or it starts with a double quote character (@code{"}) followed by a -percent-escaped string that is the argument value. Note that there is -only a leading double quote character, no trailing one. The double -quote character is only needed to be able to differentiate between no -value and the empty string as value. - -@item string list -If the option takes a number argument and it can occur more than once, -then the option argument is either empty, or it is a comma-separated -list of string arguments as described above. -@end table -@end table - -The active language and character set are currently determined from -the locale environment of the @command{gpgconf} program. - -@c FIXME: Document the active language and active character set. Allow -@c to change it via the command line? - - -@node Listing components -@subsection Listing components - -The command @code{--list-components} will list all components that can -be configured with @command{gpgconf}. Usually, one component will -correspond to one GnuPG-related program and contain the options of -that programs configuration file that can be modified using -@command{gpgconf}. However, this is not necessarily the case. A -component might also be a group of selected options from several -programs, or contain entirely virtual options that have a special -effect rather than changing exactly one option in one configuration -file. - -A component is a set of configuration options that semantically belong -together. Furthermore, several changes to a component can be made in -an atomic way with a single operation. The GUI could for example -provide a menu with one entry for each component, or a window with one -tabulator sheet per component. - -The command argument @code{--list-components} lists all available -components, one per line. The format of each line is: - -@code{@var{name}:@var{description}} - -@table @var -@item name -This field contains a name tag of the component. The name tag is used -to specify the component in all communication with @command{gpgconf}. -The name tag is to be used @emph{verbatim}. It is thus not in any -escaped format. - -@item description -The @emph{string} in this field contains a human-readable description -of the component. It can be displayed to the user of the GUI for -informational purposes. It is @emph{percent-escaped} and -@emph{localized}. -@end table - -Example: -@example -$ gpgconf --list-components -gpg:GPG for OpenPGP -gpg-agent:GPG Agent -scdaemon:Smartcard Daemon -gpgsm:GPG for S/MIME -dirmngr:Directory Manager -@end example - - -@node Listing options -@subsection Listing options - -Every component contains one or more options. Options may be gathered -into option groups to allow the GUI to give visual hints to the user -about which options are related. - -The command argument @code{@w{--list-options @var{component}}} lists -all options (and the groups they belong to) in the component -@var{component}, one per line. @var{component} must be the string in -the field @var{name} in the output of the @code{--list-components} -command. - -There is one line for each option and each group. First come all -options that are not in any group. Then comes a line describing a -group. Then come all options that belong into each group. Then comes -the next group and so on. There does not need to be any group (and in -this case the output will stop after the last non-grouped option). - -The format of each line is: - -@code{@var{name}:@var{flags}:@var{level}:@var{description}:@var{type}:@var{alt-type}:@var{argname}:@var{default}:@var{argdef}:@var{value}} - -@table @var -@item name -This field contains a name tag for the group or option. The name tag -is used to specify the group or option in all communication with -@command{gpgconf}. The name tag is to be used @emph{verbatim}. It is -thus not in any escaped format. - -@item flags -The flags field contains an @emph{unsigned number}. Its value is the -OR-wise combination of the following flag values: - -@table @code -@item group (1) -If this flag is set, this is a line describing a group and not an -option. -@end table - -The following flag values are only defined for options (that is, if -the @code{group} flag is not used). - -@table @code -@item optional arg (2) -If this flag is set, the argument is optional. This is never set for -@var{type} @code{0} (none) options. - -@item list (4) -If this flag is set, the option can be given multiple times. - -@item runtime (8) -If this flag is set, the option can be changed at runtime. - -@item default (16) -If this flag is set, a default value is available. - -@item default desc (32) -If this flag is set, a (runtime) default is available. This and the -@code{default} flag are mutually exclusive. - -@item no arg desc (64) -If this flag is set, and the @code{optional arg} flag is set, then the -option has a special meaning if no argument is given. -@end table - -@item level -This field is defined for options and for groups. It contains an -@emph{unsigned number} that specifies the expert level under which -this group or option should be displayed. The following expert levels -are defined for options (they have analogous meaning for groups): - -@table @code -@item basic (0) -This option should always be offered to the user. - -@item advanced (1) -This option may be offered to advanced users. - -@item expert (2) -This option should only be offered to expert users. - -@item invisible (3) -This option should normally never be displayed, not even to expert -users. - -@item internal (4) -This option is for internal use only. Ignore it. -@end table - -The level of a group will always be the lowest level of all options it -contains. - -@item description -This field is defined for options and groups. The @emph{string} in -this field contains a human-readable description of the option or -group. It can be displayed to the user of the GUI for informational -purposes. It is @emph{percent-escaped} and @emph{localized}. - -@item type -This field is only defined for options. It contains an @emph{unsigned -number} that specifies the type of the option's argument, if any. The -following types are defined: - -Basic types: - -@table @code -@item none (0) -No argument allowed. - -@item string (1) -An @emph{unformatted string}. - -@item int32 (2) -A @emph{signed number}. - -@item uint32 (3) -An @emph{unsigned number}. -@end table - -Complex types: - -@table @code -@item pathname (32) -A @emph{string} that describes the pathname of a file. The file does -not necessarily need to exist. - -@item ldap server (33) -A @emph{string} that describes an LDAP server in the format: - -@code{@var{hostname}:@var{port}:@var{username}:@var{password}:@var{base_dn}} -@end table - -More types will be added in the future. Please see the @var{alt-type} -field for information on how to cope with unknown types. - -@item alt-type -This field is identical to @var{type}, except that only the types -@code{0} to @code{31} are allowed. The GUI is expected to present the -user the option in the format specified by @var{type}. But if the -argument type @var{type} is not supported by the GUI, it can still -display the option in the more generic basic type @var{alt-type}. The -GUI must support all the defined basic types to be able to display all -options. More basic types may be added in future versions. If the -GUI encounters a basic type it doesn't support, it should report an -error and abort the operation. - -@item argname -This field is only defined for options with an argument type -@var{type} that is not @code{0}. In this case it may contain a -@emph{percent-escaped} and @emph{localised string} that gives a short -name for the argument. The field may also be empty, though, in which -case a short name is not known. - -@item default -This field is defined only for options. Its format is that of an -@emph{option argument} (@xref{Format conventions}, for details). If -the default value is empty, then no default is known. Otherwise, the -value specifies the default value for this option. Note that this -field is also meaningful if the option itself does not take a real -argument. - -@item argdef -This field is defined only for options for which the @code{optional -arg} flag is set. If the @code{no arg desc} flag is not set, its -format is that of an @emph{option argument} (@xref{Format -conventions}, for details). If the default value is empty, then no -default is known. Otherwise, the value specifies the default value -for this option. If the @code{no arg desc} flag is set, the field is -either empty or contains a description of the effect of this option if -no argument is given. Note that this field is also meaningful if the -option itself does not take a real argument. - -@item value -This field is defined only for options. Its format is that of an -@emph{option argument}. If it is empty, then the option is not -explicitely set in the current configuration, and the default applies -(if any). Otherwise, it contains the current value of the option. -Note that this field is also meaningful if the option itself does not -take a real argument. -@end table - - -@node Changing options -@subsection Changing options - -The command @w{@code{--change-options @var{component}}} will attempt -to change the options of the component @var{component} to the -specified values. @var{component} must be the string in the field -@var{name} in the output of the @code{--list-components} command. You -have to provide the options that shall be changed in the following -format on standard input: - -@code{@var{name}:@var{flags}:@var{new-value}} - -@table @var -@item name -This is the name of the option to change. @var{name} must be the -string in the field @var{name} in the output of the -@code{--list-options} command. - -@item flags -The flags field contains an @emph{unsigned number}. Its value is the -OR-wise combination of the following flag values: - -@table @code -@item default (16) -If this flag is set, the option is deleted and the default value is -used instead (if applicable). -@end table - -@item new-value -The new value for the option. This field is only defined if the -@code{default} flag is not set. The format is that of an @emph{option -argument}. If it is empty (or the field is omitted), the default -argument is used (only allowed if the argument is optional for this -option). Otherwise, the option will be set to the specified value. +@opindex verbose +Outputs additional information while running. + +@item -P @var{string} +@itemx --passphrase @var{string} +@opindex passphrase +Instead of reading the passphrase from @code{stdin}, use the supplied +@var{string} as passphrase. Note that this makes the passphrase visible +for other users. @end table -Examples: - -To set the force option, which is of basic type @code{none (0)}: - -@example -$ echo 'force:0:1' | gpgconf --change-options dirmngr -@end example - -To delete the force option: - -@example -$ echo 'force:16:' | gpgconf --change-options dirmngr -@end example - -The @code{--runtime} option can influence when the changes take -effect. - -- cgit v1.2.3 From 10c258591ac6d58f6a70c7488a6fb2e7036a4135 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Dec 2004 20:47:40 +0000 Subject: Adding the tool itself. --- preset-passphrase.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 preset-passphrase.c diff --git a/preset-passphrase.c b/preset-passphrase.c new file mode 100644 index 000000000..564980b78 --- /dev/null +++ b/preset-passphrase.c @@ -0,0 +1,290 @@ +/* preset-passphrase.c - A tool to preset a passphrase. + * Copyright (C) 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 + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <sys/stat.h> +#include <unistd.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif + +#define JNLIB_NEED_LOG_LOGV +#include "agent.h" +#include "minip12.h" +#include "simple-pwquery.h" +#include "i18n.h" +#include "sysutils.h" + + +enum cmd_and_opt_values +{ aNull = 0, + oVerbose = 'v', + oPassphrase = 'P', + + oPreset = 'c', + oForget = 'f', + + oNoVerbose = 500, + + oHomedir, + +aTest }; + +struct rsa_secret_key_s + { + gcry_mpi_t n; /* public modulus */ + gcry_mpi_t e; /* public exponent */ + gcry_mpi_t d; /* exponent */ + gcry_mpi_t p; /* prime p. */ + gcry_mpi_t q; /* prime q. */ + gcry_mpi_t u; /* inverse of p mod q. */ + }; + + +static char *opt_homedir; +static const char *opt_passphrase; + +static ARGPARSE_OPTS opts[] = { + + { 301, NULL, 0, N_("@Options:\n ") }, + + { oVerbose, "verbose", 0, "verbose" }, + { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, + { oPreset, "preset", 256, "preset passphrase"}, + { oForget, "forget", 256, "forget passphrase"}, + + { oHomedir, "homedir", 2, "@" }, + {0} +}; + +static const char * +my_strusage (int level) +{ + const char *p; + switch (level) + { + case 11: p = "gpg-preset-passphrase (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: gpg-preset-passphrase [options] KEYID (-h for help)\n"); + break; + case 41: p = _("Syntax: gpg-preset-passphrase [options] KEYID\n" + "Password cache maintenance\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 + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); +#endif +#endif +} + + +static gpg_error_t +map_spwq_error (int err) +{ + switch (err) + { + case 0: + return 0; + case SPWQ_OUT_OF_CORE: + return gpg_error_from_errno (ENOMEM); + case SPWQ_IO_ERROR: + return gpg_error_from_errno (EIO); + case SPWQ_PROTOCOL_ERROR: + return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); + case SPWQ_ERR_RESPONSE: + return gpg_error (GPG_ERR_INV_RESPONSE); + case SPWQ_NO_AGENT: + return gpg_error (GPG_ERR_NO_AGENT); + case SPWQ_SYS_ERROR: + return gpg_error_from_errno (errno); + case SPWQ_GENERAL_ERROR: + default: + return gpg_error (GPG_ERR_GENERAL); + } +} + + +static void +preset_passphrase (const char *keygrip) +{ + int rc; + char *line; + /* FIXME: Use secure memory. */ + char passphrase[500]; + + rc = read (0, passphrase, sizeof (passphrase) - 1); + if (rc < 0) + { + log_error ("reading passphrase failed %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + passphrase[rc] = '\0'; + line = strchr (passphrase, '\n'); + if (line) + { + line--; + if (line > passphrase && line[-1] == '\r') + line--; + *line = '\0'; + } + + /* FIXME: How to handle empty passwords? */ + + rc = asprintf (&line, "PRESET_PASSPHRASE %s -1 %s\n", keygrip, passphrase); + if (rc < 0) + { + log_error ("caching passphrase failed %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + wipememory (passphrase, sizeof (passphrase)); + + rc = map_spwq_error (simple_query (line)); + if (rc) + { + log_error ("caching passphrase failed %s\n", gpg_strerror (rc)); + return; + } + + wipememory (line, strlen (line)); + free (line); +} + + +static void +forget_passphrase (const char *keygrip) +{ + int rc; + char *line; + + rc = asprintf (&line, "CLEAR_PASSPHRASE %s\n", keygrip); + if (rc < 0) + { + log_error ("clearing passphrase failed %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return; + } + free (line); +} + + +int +main (int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + int cmd = 0; + const char *keygrip = NULL; + + set_strusage (my_strusage); + log_set_prefix ("gpg-preset-passphrase", 1); + + /* Try to auto set the character set. */ + set_native_charset (NULL); + + i18n_init (); + + opt_homedir = getenv ("GNUPGHOME"); +#ifdef HAVE_W32_SYSTEM + if (!opt_homedir || !*opt_homedir) + opt_homedir = read_w32_registry_string (NULL, + "Software\\GNU\\GnuPG", "HomeDir"); +#endif /*HAVE_W32_SYSTEM*/ + if (!opt_homedir || !*opt_homedir) + opt_homedir = GNUPG_DEFAULT_HOMEDIR; + + + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* (do not remove the args) */ + while (arg_parse (&pargs, opts) ) + { + switch (pargs.r_opt) + { + case oVerbose: opt.verbose++; break; + case oHomedir: opt_homedir = pargs.r.ret_str; break; + + case oPreset: cmd = oPreset; break; + case oForget: cmd = oForget; break; + case oPassphrase: opt_passphrase = pargs.r.ret_str; break; + + default : pargs.err = 2; break; + } + } + if (log_get_errorcount(0)) + exit(2); + + if (argc == 1) + keygrip = *argv; + else + usage (1); + + if (cmd == oPreset) + preset_passphrase (keygrip); + else if (cmd == oForget) + forget_passphrase (keygrip); + else + usage (1); + + agent_exit (0); + return 8; /*NOTREACHED*/ +} + + +void +agent_exit (int rc) +{ + rc = rc? rc : log_get_errorcount(0)? 2 : 0; + exit (rc); +} -- cgit v1.2.3 From c9489fc76e2fbf041a39d3d6311e2ace165d970d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 22 Dec 2004 17:24:13 +0000 Subject: * gnupg.texi: Reordered. * contrib.texi: Updated. --- doc/ChangeLog | 5 +++++ doc/assuan.texi | 18 +++++++++++------- doc/contrib.texi | 54 ++++++++++++++++++------------------------------------ doc/glossary.texi | 6 ++++++ doc/gnupg.texi | 17 ++++++----------- doc/tools.texi | 22 ++++++++++++---------- 6 files changed, 58 insertions(+), 64 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index f6f41f2b5..407b706b0 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2004-12-22 Werner Koch <wk@g10code.com> + + * gnupg.texi: Reordered. + * contrib.texi: Updated. + 2004-12-21 Werner Koch <wk@g10code.com> * tools.texi (gpg-preset-passphrase): New section. diff --git a/doc/assuan.texi b/doc/assuan.texi index 2e2219263..cb6eb9c31 100644 --- a/doc/assuan.texi +++ b/doc/assuan.texi @@ -3,14 +3,15 @@ @c For copying conditions, see the file gnupg.texi. @node Assuan -@chapter Description of the Assuan protocol. +@appendix Description of the Assuan protocol. +@cindex Assuan, IPC 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: +@appendixsubsec Goals @itemize @bullet @item Common framework for module communication @@ -22,7 +23,7 @@ Goals: @end itemize -Design criteria: +@appendixsubsec Design criteria @itemize @bullet @item Client Server with back channel @@ -36,8 +37,10 @@ Design criteria: @item Subliminal channels are not an issue @end itemize -Implementation: +@appendixsubsec Implementation + +@noindent The implementation is line based with a maximum line size of 1000 octects. The default IPC mechanism are Unix Domain Sockets. @@ -57,7 +60,7 @@ state. All textual messages are assumed to be in UTF-8 unless otherwise noted. -Server responses: +@appendixsubsec Server responses @table @code @item OK [<arbitary debugging information>] @@ -98,7 +101,7 @@ treated as a communication error. (The rationale for having a line length limit is to allow for easier multiplexing of multiple channels). -Client requests: +@appendixsubsec 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 @@ -171,7 +174,8 @@ to indicate a partial end of data. @end table -Error Codes: + +@appendixsubsec 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 diff --git a/doc/contrib.texi b/doc/contrib.texi index 73d722c23..28ea2e1d3 100644 --- a/doc/contrib.texi +++ b/doc/contrib.texi @@ -10,42 +10,7 @@ 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: +are not listed. David Shaw, Matthew Skala, Michael Roth, Niklas Hernaeus, Nils Ellmenreich, Rmi Guyomarch, Stefan Bellon, Timo Schulz and Werner @@ -60,6 +25,23 @@ 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 new modularized architecture of gnupg 1.9 as well as the X.509/CMS +part has been developed as part of the gypten project. Direct +contributors to this project are: Bernhard Herzog, who did extensive +testing and tracked down a lot of bugs. Bernhard Reiter, who made sure +that we met the specifications and the deadlines. He did extensive +testing and came up with a lot of suggestions. Jan-Oliver Wagner made +sure that we met the specifications and the deadlines. He also did +extensive testing and came up with a lot of suggestions. Karl-Heinz +Zimmer and Marc Mutz had to struggle with all the bugs and +misconceptions while working on KDE integration. Marcus Brinkman +extended GPGME, cleaned up the Assuan code and fixed bugs all over the +place. Moritz Schulte took over Libgcrypt maintenance and developed it +into a stable an useful library. Steffen Hansen had a hard time to +write the dirmngr due to underspecified interfaces. Thomas Koester did +extensive testing and tracked down a lot of bugs. Werner Koch designed +the system and wrote most of the code. + 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 diff --git a/doc/glossary.texi b/doc/glossary.texi index 7c1b7d5a0..e739947ef 100644 --- a/doc/glossary.texi +++ b/doc/glossary.texi @@ -16,6 +16,12 @@ certificates. The @emph{Certificate Revocation List} is a list containing certificates revoked by the issuer. +@item Keygrip + This term is used by GnuPG to describe a 20 byte hash value used +to identify a certain key without referencing to a concrete protocol. +It is used internally to access a private key. Usually it is shown and +entered as a 40 character hexadecimal formatted string. + @item OCSP The @emph{Online Certificate Status Protocol} is used as an alternative to a @acronym{CRL}. It is described in @code{RFC 2560}. diff --git a/doc/gnupg.texi b/doc/gnupg.texi index d74a76ca9..006e604a0 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -107,7 +107,7 @@ Boston, MA 02111-1307 USA @top Introduction @cindex introduction -This manual documents how to use the GNU Privay Guard system as well as +This manual documents how to use the GNU Privacy Guard system as well as the administration and the architecture. @menu @@ -116,21 +116,15 @@ the administration and the architecture. * Invoking GPG-AGENT:: How to launch the secret key daemon. * Invoking SCDAEMON:: How to handle Smartcards. -Developer information +* Helper Tools:: Description of small helper tools -* Assuan:: Description of the Assuan protocol. * System Notes:: Notes pertaining to certain OSes. - -Miscellaneous - -* Helper Tools:: Description of small helper tools * Debugging:: How to solve problems +* Assuan:: Description of the Assuan protocol. * Copying:: GNU General Public License says how you can copy and share GnuPG * Contributors:: People who have contributed to GnuPG. -Indices - * Glossary:: Short descrition of used terms. * Option Index:: Index to command line options. * Index:: Index of concepts and symbol names. @@ -141,12 +135,13 @@ Indices @include gpg-agent.texi @include scdaemon.texi -@include assuan.texi +@include tools.texi + @include sysnotes.texi -@include tools.texi @include debugging.texi +@include assuan.texi @include gpl.texi @include contrib.texi diff --git a/doc/tools.texi b/doc/tools.texi index a7081e429..684975e19 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -601,10 +601,10 @@ whicl will be printed to stdout. @section Put a passphrase into the cache. The @command{gpg-preset-passphrase} is a utility to seed the internal -cache of a running @command{gpg-agent} with passphrases. This is mainly -useful for unatteneded machines, where a pinentry may not be used and -the passphrases for the to be used keys should be given at machine -startup. +cache of a running @command{gpg-agent} with passphrases. It is mainly +useful for unattended machines, where the usual @command{pinentry} tool +may not be used and the passphrases for the to be used keys are given at +machine startup. Passphrases set with this utility don't expire unless the @option{--forget} option is used to explicitly clear them from the cache @@ -630,28 +630,29 @@ gpg-preset-passphrase [options] [command] @var{keygrip} @var{keygrip} is a 40 character string of hexadecimal characters identifying the key for which the passphrase should be set or cleared. -This @emph{keygrip} is listed along with the key when running the -command: @code{gpgsm --dump-secret-keys}. One of the following commands +This keygrip is listed along with the key when running the command: +@code{gpgsm --dump-secret-keys}. One of the following command options must be given: @table @gnupgtabopt @item --preset Preset a passphrase. This is what you usually will -use. @command{gpg-preset-passphrase} will then read the passphrase form +use. @command{gpg-preset-passphrase} will then read the passphrase from @code{stdin}. @item --forget -Clear the passphrase for the given keygrip from the cache. +Flush the passphrase for the given keygrip from the cache. @end table -The following options may be used: +@noindent +The following additional options may be used: @table @gnupgtabopt @item -v @itemx --verbose @opindex verbose -Outputs additional information while running. +Output additional information while running. @item -P @var{string} @itemx --passphrase @var{string} @@ -663,3 +664,4 @@ for other users. + -- cgit v1.2.3 From de6f6d2015cc02833d10b06f6507a97a89fceed6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 22 Dec 2004 17:55:28 +0000 Subject: (set_binary): New. (main, open_read, open_fwrite): Use it. --- ChangeLog | 4 ++++ NEWS | 6 ++++-- configure.ac | 4 ++-- sm/ChangeLog | 5 +++++ sm/gpgsm.c | 40 ++++++++++++++++++++++++++++++++++++---- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ca430c63..ac2784365 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-12-22 Werner Koch <wk@g10code.com> + + Released 1.9.14. + 2004-12-20 Werner Koch <wk@g10code.com> * configure.ac: Add PATHSEP_C and PATHSEP_S. For W32 let all diff --git a/NEWS b/NEWS index 525fdbe72..2b43e6dd1 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,13 @@ -Noteworthy changes in version 1.9.14 +Noteworthy changes in version 1.9.14 (2004-12-22) ------------------------------------------------- * [gpg-agent] New option --use-standard-socket to allow the use of a fixed socket. gpgsm falls back to this socket if GPG_AGENT_INFO has not been set. - * Ported to MS Windows. + * Ported to MS Windows with some functional limitations. + + * New tool gpg-preset-passphrase. Noteworthy changes in version 1.9.13 (2004-12-03) diff --git a/configure.ac b/configure.ac index 7eb3a6b71..54a1372bd 100644 --- a/configure.ac +++ b/configure.ac @@ -20,11 +20,11 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) -min_automake_version="1.7.9" +min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.14-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.14, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. diff --git a/sm/ChangeLog b/sm/ChangeLog index 7a16cb570..df1670082 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2004-12-22 Werner Koch <wk@g10code.com> + + * gpgsm.c (set_binary): New. + (main, open_read, open_fwrite): Use it. + 2004-12-21 Werner Koch <wk@g10code.com> * gpgsm.c (main): Use default_homedir(). diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 074027bf2..ff404dc69 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -39,6 +39,11 @@ #include "keydb.h" #include "sysutils.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + enum cmd_and_opt_values { aNull = 0, oArmor = 'a', @@ -562,6 +567,17 @@ build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int)) } +/* Set the file pointer into binary mode if required. */ +static void +set_binary (FILE *fp) +{ +#ifdef HAVE_DOSISH_SYSTEM + setmode (fileno (fp), O_BINARY); +#endif +} + + + static void i18n_init(void) { @@ -758,7 +774,7 @@ main ( int argc, char **argv) opt.homedir = default_homedir (); #ifdef HAVE_W32_SYSTEM - opt.no_crl_checks = 1; + opt.no_crl_check = 1; #endif /* First check whether we have a config file on the commandline */ @@ -1374,6 +1390,8 @@ main ( int argc, char **argv) break; case aEncr: /* encrypt the given file */ + set_binary (stdin); + set_binary (stdout); if (!argc) gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */ else if (argc == 1) @@ -1386,6 +1404,8 @@ main ( int argc, char **argv) /* FIXME: We don't handle --output yet. We should also allow to concatenate multiple files for signing because that is what gpg does.*/ + set_binary (stdin); + set_binary (stdout); if (!argc) gpgsm_sign (&ctrl, signerlist, 0, detached_sig, stdout); /* create from stdin */ @@ -1408,6 +1428,7 @@ main ( int argc, char **argv) { FILE *fp = NULL; + set_binary (stdin); if (argc == 2 && opt.outfile) log_info ("option --output ignored for a detached signature\n"); else if (opt.outfile) @@ -1432,6 +1453,8 @@ main ( int argc, char **argv) break; case aDecrypt: + set_binary (stdin); + set_binary (stdout); if (!argc) gpgsm_decrypt (&ctrl, 0, stdout); /* from stdin */ else if (argc == 1) @@ -1502,6 +1525,7 @@ main ( int argc, char **argv) break; case aExport: + set_binary (stdout); for (sl=NULL; argc; argc--, argv++) add_to_strlist (&sl, *argv); gpgsm_export (&ctrl, sl, stdout); @@ -1509,6 +1533,7 @@ main ( int argc, char **argv) break; case aExportSecretKeyP12: + set_binary (stdout); if (argc == 1) gpgsm_p12_export (&ctrl, *argv, stdout); else @@ -1644,11 +1669,14 @@ open_read (const char *filename) int fd; if (filename[0] == '-' && !filename[1]) - return 0; /* stdin */ + { + set_binary (stdin); + return 0; /* stdin */ + } fd = check_special_filename (filename); if (fd != -1) return fd; - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY | O_BINARY); if (fd == -1) { log_error (_("can't open `%s': %s\n"), filename, strerror (errno)); @@ -1668,7 +1696,10 @@ open_fwrite (const char *filename) FILE *fp; if (filename[0] == '-' && !filename[1]) - return stdout; + { + set_binary (stdout); + return stdout; + } fd = check_special_filename (filename); if (fd != -1) @@ -1679,6 +1710,7 @@ open_fwrite (const char *filename) log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno)); gpgsm_exit (2); } + set_binary (fp); return fp; } fp = fopen (filename, "wb"); -- cgit v1.2.3 From 1f11db582973b7ffb48574ba27e0890f3bc319f9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 22 Dec 2004 18:05:14 +0000 Subject: Preapring a release --- po/de.po | 446 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 226 insertions(+), 220 deletions(-) diff --git a/po/de.po b/po/de.po index eac1827bc..086df87b9 100644 --- a/po/de.po +++ b/po/de.po @@ -8,17 +8,17 @@ # msgid "" msgstr "" -"Project-Id-Version: gnupg2 1.9.10\n" +"Project-Id-Version: gnupg2 1.9.14\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-12-03 18:30+0100\n" -"PO-Revision-Date: 2004-11-24 15:43+0100\n" +"POT-Creation-Date: 2004-12-22 18:57+0100\n" +"PO-Revision-Date: 2004-12-22 19:00+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:97 agent/protect-tool.c:101 scd/scdaemon.c:93 +#: agent/gpg-agent.c:103 agent/protect-tool.c:106 scd/scdaemon.c:98 msgid "" "@Options:\n" " " @@ -26,94 +26,102 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:99 scd/scdaemon.c:95 +#: agent/gpg-agent.c:105 scd/scdaemon.c:100 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:100 scd/scdaemon.c:96 +#: agent/gpg-agent.c:106 scd/scdaemon.c:101 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:101 kbx/kbxutil.c:81 scd/scdaemon.c:97 sm/gpgsm.c:317 +#: agent/gpg-agent.c:107 kbx/kbxutil.c:81 scd/scdaemon.c:102 sm/gpgsm.c:325 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:102 kbx/kbxutil.c:82 scd/scdaemon.c:98 sm/gpgsm.c:318 +#: agent/gpg-agent.c:108 kbx/kbxutil.c:82 scd/scdaemon.c:103 sm/gpgsm.c:326 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" -#: agent/gpg-agent.c:103 scd/scdaemon.c:99 +#: agent/gpg-agent.c:109 scd/scdaemon.c:104 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:104 scd/scdaemon.c:100 +#: agent/gpg-agent.c:110 scd/scdaemon.c:105 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" -#: agent/gpg-agent.c:105 +#: agent/gpg-agent.c:111 msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:110 scd/scdaemon.c:107 +#: agent/gpg-agent.c:116 scd/scdaemon.c:112 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:111 +#: agent/gpg-agent.c:117 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:112 scd/scdaemon.c:108 sm/gpgsm.c:320 +#: agent/gpg-agent.c:118 scd/scdaemon.c:113 sm/gpgsm.c:328 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:113 +#: agent/gpg-agent.c:119 msgid "do not allow multiple connections" msgstr "Nicht mehr als eine Verbindung erlauben" -#: agent/gpg-agent.c:116 +#: agent/gpg-agent.c:121 +msgid "use a standard location for the socket" +msgstr "Benutze einen Standardnamen fr den Socket" + +#: agent/gpg-agent.c:125 msgid "|PGM|use PGM as the PIN-Entry program" msgstr "|PGM|benutze PGM as PIN-Entry" -#: agent/gpg-agent.c:118 +#: agent/gpg-agent.c:127 msgid "|PGM|use PGM as the SCdaemon program" msgstr "|PGM|benutze PGM as SCdaemon" -#: agent/gpg-agent.c:125 +#: agent/gpg-agent.c:134 msgid "ignore requests to change the TTY" msgstr "Ignoriere Anfragen, das TTY zu wechseln" -#: agent/gpg-agent.c:127 +#: agent/gpg-agent.c:136 msgid "ignore requests to change the X display" msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:130 +#: agent/gpg-agent.c:139 msgid "|N|expire cached PINs after N seconds" msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" -#: agent/gpg-agent.c:133 +#: agent/gpg-agent.c:142 msgid "do not use the PIN cache when signing" msgstr "benutze PINs im Cache nicht bem Signieren" -#: agent/gpg-agent.c:135 +#: agent/gpg-agent.c:144 msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" -#: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:491 tools/gpgconf.c:85 +#: agent/gpg-agent.c:146 +msgid "allow presetting passphrase" +msgstr "erlaube ein \"preset\" von Passphrases" + +#: agent/gpg-agent.c:205 agent/protect-tool.c:139 scd/scdaemon.c:178 +#: sm/gpgsm.c:499 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:195 agent/protect-tool.c:134 scd/scdaemon.c:168 -#: sm/gpgsm.c:491 tools/gpgconf.c:85 +#: agent/gpg-agent.c:205 agent/protect-tool.c:139 scd/scdaemon.c:178 +#: sm/gpgsm.c:499 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:198 +#: agent/gpg-agent.c:208 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: agent/gpg-agent.c:200 +#: agent/gpg-agent.c:210 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -121,62 +129,63 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:271 scd/scdaemon.c:242 sm/gpgsm.c:609 +#: agent/gpg-agent.c:281 scd/scdaemon.c:252 sm/gpgsm.c:628 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:448 agent/protect-tool.c:1050 kbx/kbxutil.c:431 -#: scd/scdaemon.c:357 sm/gpgsm.c:730 +#: agent/gpg-agent.c:462 agent/protect-tool.c:1061 kbx/kbxutil.c:431 +#: scd/scdaemon.c:367 sm/gpgsm.c:749 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:521 scd/scdaemon.c:437 sm/gpgsm.c:828 +#: agent/gpg-agent.c:537 scd/scdaemon.c:442 sm/gpgsm.c:850 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:526 agent/gpg-agent.c:1000 scd/scdaemon.c:442 -#: sm/gpgsm.c:832 +#: agent/gpg-agent.c:542 agent/gpg-agent.c:1056 scd/scdaemon.c:447 +#: sm/gpgsm.c:854 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:534 scd/scdaemon.c:450 sm/gpgsm.c:839 +#: agent/gpg-agent.c:550 scd/scdaemon.c:455 sm/gpgsm.c:861 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:1033 agent/gpg-agent.c:1067 +#: agent/gpg-agent.c:775 agent/gpg-agent.c:1090 agent/gpg-agent.c:1094 +#: agent/gpg-agent.c:1130 agent/gpg-agent.c:1134 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" -#: agent/gpg-agent.c:1036 agent/gpg-agent.c:1072 +#: agent/gpg-agent.c:1098 agent/gpg-agent.c:1140 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/gpg-agent.c:1250 +#: agent/gpg-agent.c:1327 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1257 common/simple-pwquery.c:293 sm/call-agent.c:128 +#: agent/gpg-agent.c:1337 common/simple-pwquery.c:323 sm/call-agent.c:140 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1269 common/simple-pwquery.c:305 sm/call-agent.c:140 +#: agent/gpg-agent.c:1349 common/simple-pwquery.c:335 sm/call-agent.c:152 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" -#: agent/protect-tool.c:137 +#: agent/protect-tool.c:142 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" -#: agent/protect-tool.c:139 +#: agent/protect-tool.c:144 msgid "" "Syntax: gpg-protect-tool [options] [args]]\n" "Secret key maintenance tool\n" @@ -184,16 +193,16 @@ msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" "Werkzeug zum Bearbeiten von geheimen Schlsseln\n" -#: agent/protect-tool.c:1187 +#: agent/protect-tool.c:1193 msgid "Please enter the passphrase to unprotect the PKCS#12 object." msgstr "Bitte geben Sie die Passphrase zum Entsperren des PKCS#12 Objekts ein" -#: agent/protect-tool.c:1190 +#: agent/protect-tool.c:1196 msgid "Please enter the passphrase to protect the new PKCS#12 object." msgstr "" "Bitte geben Sie die Passphrase zum Schützen des neuen PKCS#12 Objekts ein" -#: agent/protect-tool.c:1193 +#: agent/protect-tool.c:1199 msgid "" "Please enter the passphrase to protect the imported object within the GnuPG " "system." @@ -201,11 +210,11 @@ msgstr "" "Bitte geben Sie die Passphrase ein, um das importierte Objket im GnuPG " "System zu schützen." -#: agent/protect-tool.c:1196 agent/genkey.c:110 agent/genkey.c:224 +#: agent/protect-tool.c:1202 agent/genkey.c:110 agent/genkey.c:218 msgid "Please re-enter this passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" -#: agent/protect-tool.c:1198 +#: agent/protect-tool.c:1204 msgid "" "Please enter the passphrase or the PIN\n" "needed to complete this operation." @@ -213,14 +222,23 @@ msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" "wird bentigt um diese Aktion auszufhren." -#: agent/protect-tool.c:1202 agent/genkey.c:131 agent/genkey.c:244 +#: agent/protect-tool.c:1208 agent/genkey.c:131 agent/genkey.c:238 msgid "does not match - try again" msgstr "Keine bereinstimmung - bitte nochmal versuchen" -#: agent/protect-tool.c:1203 +#: agent/protect-tool.c:1209 msgid "Passphrase:" msgstr "Passphrase:" +#: agent/protect-tool.c:1222 +#, c-format +msgid "error while asking for the passphrase: %s\n" +msgstr "Fehler bei der Abfrage der Passphrase: %s\n" + +#: agent/protect-tool.c:1225 +msgid "cancelled\n" +msgstr "Vom Benutzer abgebrochen\n" + #: agent/divert-scd.c:200 #, c-format msgid "Please enter the PIN%s%s%s to unlock the card" @@ -232,16 +250,16 @@ msgid "Please enter the passphrase to%0Ato protect your new key" msgstr "" "Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlssel zu schtzen" -#: agent/genkey.c:223 +#: agent/genkey.c:217 msgid "Please enter the new passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: agent/query.c:126 +#: agent/query.c:145 #, c-format msgid "failed to acquire the pinentry lock: %s\n" msgstr "Die Sperre für das Pinentry kann nicht gesetzt werden: %s\n" -#: agent/query.c:288 +#: agent/query.c:307 msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" @@ -249,7 +267,7 @@ msgstr "" "Bitte geben Sie Ihre PIN ein, so da der geheime Schlssel benutzt werden " "kann" -#: agent/query.c:291 +#: agent/query.c:310 msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" @@ -257,31 +275,31 @@ msgstr "" "Bitte geben Sie Ihr Mantra (Passphrase) ein, so da der geheime Schlssel " "benutzt werden kann" -#: agent/query.c:346 agent/query.c:358 +#: agent/query.c:365 agent/query.c:377 msgid "PIN too long" msgstr "Die PIN ist zu lang" -#: agent/query.c:347 +#: agent/query.c:366 msgid "Passphrase too long" msgstr "Das Matra (Passphrase) ist zu lang" -#: agent/query.c:355 +#: agent/query.c:374 msgid "Invalid characters in PIN" msgstr "Ungltige Zeichen in der PIN" -#: agent/query.c:360 +#: agent/query.c:379 msgid "PIN too short" msgstr "Die PIN ist zu kurz" -#: agent/query.c:372 +#: agent/query.c:391 msgid "Bad PIN" msgstr "Falsche PIN" -#: agent/query.c:373 +#: agent/query.c:392 msgid "Bad Passphrase" msgstr "Falsches Mantra (Passphrase)" -#: agent/query.c:412 +#: agent/query.c:431 msgid "Passphrase" msgstr "Mantra" @@ -302,37 +320,37 @@ msgstr "WARNUNG: Unsichere Besitzrechte f msgid "Warning: unsafe permissions on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" -#: common/simple-pwquery.c:279 +#: common/simple-pwquery.c:309 msgid "gpg-agent is not available in this session\n" msgstr "Der gpg-agent ist nicht verfgbar\n" -#: common/simple-pwquery.c:327 +#: common/simple-pwquery.c:367 #, c-format msgid "can't connect to `%s': %s\n" msgstr "Verbindung zu `%s' kann nicht aufgebaut werden: %s\n" -#: common/simple-pwquery.c:338 +#: common/simple-pwquery.c:378 msgid "communication problem with gpg-agent\n" msgstr "Kommunikationsproblem mit gpg-agent\n" -#: common/simple-pwquery.c:348 +#: common/simple-pwquery.c:388 msgid "problem setting the gpg-agent options\n" msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: common/simple-pwquery.c:487 +#: common/simple-pwquery.c:526 common/simple-pwquery.c:592 msgid "canceled by user\n" msgstr "Vom Benutzer abgebrochen\n" -#: common/simple-pwquery.c:494 +#: common/simple-pwquery.c:533 common/simple-pwquery.c:598 msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:627 +#: jnlib/logging.c:624 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:68 sm/gpgsm.c:227 tools/gpgconf.c:53 +#: kbx/kbxutil.c:68 sm/gpgsm.c:235 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -340,7 +358,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:76 sm/gpgsm.c:262 tools/gpgconf.c:59 +#: kbx/kbxutil.c:76 sm/gpgsm.c:270 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -350,7 +368,7 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:83 sm/gpgsm.c:325 tools/gpgconf.c:64 +#: kbx/kbxutil.c:83 sm/gpgsm.c:333 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" @@ -382,43 +400,43 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:101 sm/gpgsm.c:337 +#: scd/scdaemon.c:106 sm/gpgsm.c:345 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" -#: scd/scdaemon.c:106 +#: scd/scdaemon.c:111 msgid "|N|set OpenSC debug level to N" msgstr "|N|Den OpenSC Debugstufe auf N setzen" -#: scd/scdaemon.c:109 +#: scd/scdaemon.c:114 msgid "|N|connect to reader at port N" msgstr "|N|Verbinde mit dem Leser auf Port N" -#: scd/scdaemon.c:110 +#: scd/scdaemon.c:115 msgid "|NAME|use NAME as ct-API driver" msgstr "|NAME|Benutze NAME als CT-API Treiber" -#: scd/scdaemon.c:111 +#: scd/scdaemon.c:116 msgid "|NAME|use NAME as PC/SC driver" msgstr "|NAME|Benutze NAME als PC/SC Treiber" -#: scd/scdaemon.c:114 +#: scd/scdaemon.c:119 msgid "do not use the internal CCID driver" msgstr "Den internen CCID Treiber nicht benutzen" -#: scd/scdaemon.c:121 +#: scd/scdaemon.c:126 msgid "do not use the OpenSC layer" msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" -#: scd/scdaemon.c:126 +#: scd/scdaemon.c:131 msgid "allow the use of admin card commands" msgstr "Erlaube die Benutzung von \"Admin\" Kommandos" -#: scd/scdaemon.c:171 +#: scd/scdaemon.c:181 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" -#: scd/scdaemon.c:173 +#: scd/scdaemon.c:183 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" @@ -426,7 +444,7 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon fr GnuPG\n" -#: scd/scdaemon.c:630 +#: scd/scdaemon.c:635 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " @@ -521,28 +539,28 @@ msgstr "Die Antwort enth msgid "invalid radix64 character %02x skipped\n" msgstr "Ungltiges Basis-64 Zeichen %02X wurde bergangen\n" -#: sm/call-agent.c:88 +#: sm/call-agent.c:98 msgid "no running gpg-agent - starting one\n" msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" -#: sm/call-agent.c:151 +#: sm/call-agent.c:163 msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" -#: sm/call-dirmngr.c:173 +#: sm/call-dirmngr.c:174 msgid "no running dirmngr - starting one\n" msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" -#: sm/call-dirmngr.c:213 +#: sm/call-dirmngr.c:214 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" -#: sm/call-dirmngr.c:225 +#: sm/call-dirmngr.c:226 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "Die Dirmngr Protokollversion %d wird nicht untersttzt\n" -#: sm/call-dirmngr.c:239 +#: sm/call-dirmngr.c:240 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " @@ -717,7 +735,7 @@ msgstr "Das Wurzelzertifikat wurde nun als vertrauensw msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:736 sm/import.c:166 +#: sm/certchain.c:736 sm/import.c:157 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" @@ -760,7 +778,7 @@ msgstr "(dies is wahrscheinlich keine verschl msgid "certificate `%s' not found: %s\n" msgstr "Zertifikat `%s' nicht gefunden: %s\n" -#: sm/delete.c:112 sm/keydb.c:1403 sm/keydb.c:1496 +#: sm/delete.c:112 sm/keydb.c:1401 sm/keydb.c:1494 #, c-format msgid "error locking keybox: %s\n" msgstr "Fehler beim Sperren der Keybox: %s\n" @@ -788,243 +806,243 @@ msgstr "Schwacher Schl msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:229 +#: sm/gpgsm.c:237 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:230 +#: sm/gpgsm.c:238 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:231 +#: sm/gpgsm.c:239 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:232 +#: sm/gpgsm.c:240 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:233 +#: sm/gpgsm.c:241 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:234 +#: sm/gpgsm.c:242 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:235 +#: sm/gpgsm.c:243 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:237 +#: sm/gpgsm.c:245 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:238 +#: sm/gpgsm.c:246 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:247 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:240 +#: sm/gpgsm.c:248 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:250 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:251 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:252 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:253 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:246 +#: sm/gpgsm.c:254 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:255 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:248 +#: sm/gpgsm.c:256 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:249 +#: sm/gpgsm.c:257 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:258 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:251 +#: sm/gpgsm.c:259 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:253 +#: sm/gpgsm.c:261 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:254 +#: sm/gpgsm.c:262 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:264 +#: sm/gpgsm.c:272 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: sm/gpgsm.c:266 +#: sm/gpgsm.c:274 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:268 +#: sm/gpgsm.c:276 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:270 +#: sm/gpgsm.c:278 msgid "assume input is in base-64 format" msgstr "Eingabedaten sind im Basis-64 Format" -#: sm/gpgsm.c:272 +#: sm/gpgsm.c:280 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:274 +#: sm/gpgsm.c:282 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:277 +#: sm/gpgsm.c:285 msgid "use system's dirmngr if available" msgstr "Benutze den System Dirmngr when verfgbar" -#: sm/gpgsm.c:278 +#: sm/gpgsm.c:286 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:283 +#: sm/gpgsm.c:291 msgid "check validity using OCSP" msgstr "Die Gltigkeit mittels OCSP prfen" -#: sm/gpgsm.c:286 +#: sm/gpgsm.c:294 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:289 +#: sm/gpgsm.c:297 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:292 +#: sm/gpgsm.c:300 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:296 +#: sm/gpgsm.c:304 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:300 +#: sm/gpgsm.c:308 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:302 +#: sm/gpgsm.c:310 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:308 +#: sm/gpgsm.c:316 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:311 +#: sm/gpgsm.c:319 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:313 +#: sm/gpgsm.c:321 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:316 tools/gpgconf.c:61 +#: sm/gpgsm.c:324 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: sm/gpgsm.c:319 +#: sm/gpgsm.c:327 msgid "don't use the terminal at all" msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:322 +#: sm/gpgsm.c:330 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:323 +#: sm/gpgsm.c:331 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:328 +#: sm/gpgsm.c:336 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:329 +#: sm/gpgsm.c:337 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:330 +#: sm/gpgsm.c:338 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:332 +#: sm/gpgsm.c:340 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:333 +#: sm/gpgsm.c:341 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:334 +#: sm/gpgsm.c:342 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:335 +#: sm/gpgsm.c:343 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:336 +#: sm/gpgsm.c:344 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:340 +#: sm/gpgsm.c:348 msgid "|LEVEL|set the debugging level to LEVEL" msgstr "|NAME|Die Debugstufe auf NAME setzen" -#: sm/gpgsm.c:347 +#: sm/gpgsm.c:355 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:354 +#: sm/gpgsm.c:362 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:360 +#: sm/gpgsm.c:368 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verschlsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:362 +#: sm/gpgsm.c:370 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:364 +#: sm/gpgsm.c:372 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:372 +#: sm/gpgsm.c:380 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -1032,7 +1050,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:375 +#: sm/gpgsm.c:383 msgid "" "@\n" "Examples:\n" @@ -1052,11 +1070,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:494 +#: sm/gpgsm.c:502 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:497 +#: sm/gpgsm.c:505 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -1065,7 +1083,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:504 +#: sm/gpgsm.c:512 msgid "" "\n" "Supported algorithms:\n" @@ -1073,201 +1091,170 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:580 +#: sm/gpgsm.c:599 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:645 +#: sm/gpgsm.c:664 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:661 +#: sm/gpgsm.c:680 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:735 +#: sm/gpgsm.c:754 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1183 +#: sm/gpgsm.c:1205 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1195 +#: sm/gpgsm.c:1217 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1221 +#: sm/gpgsm.c:1243 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1229 +#: sm/gpgsm.c:1251 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1259 +#: sm/gpgsm.c:1281 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1425 +#: sm/gpgsm.c:1452 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1648 sm/gpgsm.c:1681 +#: sm/gpgsm.c:1682 sm/gpgsm.c:1719 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" -#: sm/import.c:118 +#: sm/import.c:109 #, c-format msgid "total number processed: %lu\n" msgstr "gesamte verarbeitete Anzahl: %lu\n" -#: sm/import.c:121 +#: sm/import.c:112 #, c-format msgid " imported: %lu" msgstr " importiert: %lu" -#: sm/import.c:125 +#: sm/import.c:116 #, c-format msgid " unchanged: %lu\n" msgstr " nicht gendert: %lu\n" -#: sm/import.c:127 +#: sm/import.c:118 #, c-format msgid " secret keys read: %lu\n" msgstr " gelesene private Schlssel: %lu\n" -#: sm/import.c:129 +#: sm/import.c:120 #, c-format msgid " secret keys imported: %lu\n" msgstr "importierte priv. Schlssel: %lu\n" -#: sm/import.c:131 +#: sm/import.c:122 #, c-format msgid " secret keys unchanged: %lu\n" msgstr "ungenderte priv. Schlssel: %lu\n" -#: sm/import.c:133 +#: sm/import.c:124 #, c-format msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: sm/import.c:235 +#: sm/import.c:226 msgid "error storing certificate\n" msgstr "Fehler beim speichern des Zertifikats\n" -#: sm/import.c:243 +#: sm/import.c:234 msgid "basic certificate checks failed - not imported\n" msgstr "Grundlegende Zertifikatprfungen fehlgeschlagen - nicht importiert\n" -#: sm/import.c:429 sm/import.c:461 +#: sm/import.c:420 sm/import.c:452 #, c-format msgid "error importing certificate: %s\n" msgstr "Fehler beim Importieren des Zertifikats: %s\n" -#: sm/import.c:490 -#, c-format -msgid "error creating a pipe: %s\n" -msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" - -#: sm/import.c:498 -#, c-format -msgid "error forking process: %s\n" -msgstr "Fehler beim \"Forken\" des Prozess: %s\n" - -#: sm/import.c:609 sm/import.c:634 +#: sm/import.c:524 sm/import.c:549 #, c-format msgid "error creating temporary file: %s\n" msgstr "Fehler beim Erstellen einer temporren Datei: %s\n" -#: sm/import.c:617 +#: sm/import.c:532 #, c-format msgid "error writing to temporary file: %s\n" msgstr "Fehler beim Schreiben auf eine temporre Datei: %s\n" -#: sm/import.c:626 +#: sm/import.c:541 #, c-format msgid "error reading input: %s\n" msgstr "Fehler beim Lesen der Eingabe: %s\n" -#: sm/import.c:728 -#, c-format -msgid "waiting for protect-tool to terminate failed: %s\n" -msgstr "" -"Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" - -#: sm/import.c:731 -#, c-format -msgid "error running `%s': probably not installed\n" -msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" - -#: sm/import.c:733 -#, c-format -msgid "error running `%s': exit status %d\n" -msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" - -#: sm/import.c:736 -#, c-format -msgid "error running `%s': terminated\n" -msgstr "Fehler beim Ausfhren von `%s': beendet\n" - -#: sm/keydb.c:189 +#: sm/keydb.c:187 #, c-format msgid "error creating keybox `%s': %s\n" msgstr "Die \"Keybox\" `%s' konnte nicht erstellt werden: %s\n" -#: sm/keydb.c:192 +#: sm/keydb.c:190 msgid "you may want to start the gpg-agent first\n" msgstr "Sie sollten zuerst den gpg-agent starten\n" -#: sm/keydb.c:197 +#: sm/keydb.c:195 #, c-format msgid "keybox `%s' created\n" msgstr "Die \"Keybox\" `%s' wurde erstellt\n" -#: sm/keydb.c:220 +#: sm/keydb.c:218 #, c-format msgid "can't create lock for `%s'\n" msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: sm/keydb.c:1327 sm/keydb.c:1389 +#: sm/keydb.c:1325 sm/keydb.c:1387 msgid "failed to get the fingerprint\n" msgstr "Kann den Fingerprint nicht ermitteln\n" -#: sm/keydb.c:1334 sm/keydb.c:1396 +#: sm/keydb.c:1332 sm/keydb.c:1394 msgid "failed to allocate keyDB handle\n" msgstr "Kann keinen KeyDB Handler bereitstellen\n" -#: sm/keydb.c:1351 +#: sm/keydb.c:1349 #, c-format msgid "problem looking for existing certificate: %s\n" msgstr "Problem bei der Suche nach vorhandenem Zertifikat: %s\n" -#: sm/keydb.c:1359 +#: sm/keydb.c:1357 #, c-format msgid "error finding writable keyDB: %s\n" msgstr "Fehler bei der Suche nach einer schreibbaren KeyDB: %s\n" -#: sm/keydb.c:1367 +#: sm/keydb.c:1365 #, c-format msgid "error storing certificate: %s\n" msgstr "Fehler beim Speichern des Zertifikats: %s\n" -#: sm/keydb.c:1411 +#: sm/keydb.c:1409 #, c-format msgid "problem re-searching certificate: %s\n" msgstr "Problem bei Wiederfinden des Zertifikats: %s\n" -#: sm/keydb.c:1420 sm/keydb.c:1508 +#: sm/keydb.c:1418 sm/keydb.c:1506 #, c-format msgid "error getting stored flags: %s\n" msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" -#: sm/keydb.c:1429 sm/keydb.c:1519 +#: sm/keydb.c:1427 sm/keydb.c:1517 #, c-format msgid "error storing flags: %s\n" msgstr "Fehler beim Speichern der Flags: %s\n" @@ -1385,6 +1372,25 @@ msgstr "Konfiguration der zu nutzenden LDAP-Server" msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" +#~ msgid "error creating a pipe: %s\n" +#~ msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" + +#~ msgid "error forking process: %s\n" +#~ msgstr "Fehler beim \"Forken\" des Prozess: %s\n" + +#~ msgid "waiting for protect-tool to terminate failed: %s\n" +#~ msgstr "" +#~ "Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" + +#~ msgid "error running `%s': probably not installed\n" +#~ msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" + +#~ msgid "error running `%s': exit status %d\n" +#~ msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" + +#~ msgid "error running `%s': terminated\n" +#~ msgstr "Fehler beim Ausfhren von `%s': beendet\n" + #~ msgid "Usage: sc-investigate [options] (-h for help)\n" #~ msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" -- cgit v1.2.3 From 543a671a6d4064612884a7dd9fcd2b8f1624f642 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 22 Dec 2004 18:22:49 +0000 Subject: Minor tweaks --- g10/g10.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/g10/g10.c b/g10/g10.c index e02ad0d13..0be5636a2 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -812,12 +812,12 @@ log_set_strict (int yesno) static char * make_username( const char *string ) { - char *p; - if( utf8_strings ) - p = xstrdup (string); - else - p = native_to_utf8( string ); - return p; + char *p; + if( utf8_strings ) + p = xstrdup (string); + else + p = native_to_utf8( string ); + return p; } @@ -884,7 +884,7 @@ set_debug (const char *level) /* We need the home directory also in some other directories, so make sure that both variables are always in sync. */ static void -set_homedir (char *dir) +set_homedir (const char *dir) { if (!dir) dir = ""; -- cgit v1.2.3 From b85cf46a428f7e1e22ce2115cb0484877d56f398 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 22 Dec 2004 19:07:46 +0000 Subject: Post release updates --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2b43e6dd1..3fae5417e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.15 +------------------------------------------------- + + Noteworthy changes in version 1.9.14 (2004-12-22) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 54a1372bd..35886dfa6 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.14, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.15-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From 6a899889bc540fcbf8484a84a5ad8fabcfc48cc2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 28 Dec 2004 07:13:24 +0000 Subject: (find_endpoint): New. (scan_or_find_devices): Add new args to return endpoint info and interface number. (ccid_open_reader, ccid_shutdown_reader): Take care of these new args. (bulk_in, bulk_out): Use the correct endpoints. (ccid_transceive_apdu_level): New. (ccid_transceive): Divert to above. (parse_ccid_descriptor): Allow APDU level exchange mode. --- scd/ChangeLog | 12 ++++ scd/ccid-driver.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 171 insertions(+), 21 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index ece9abc4f..4aae08536 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,15 @@ +2004-12-28 Werner Koch <wk@g10code.com> + + * ccid-driver.c (find_endpoint): New. + (scan_or_find_devices): Add new args to return endpoint info and + interface number. + (ccid_open_reader, ccid_shutdown_reader): Take care of these new + args. + (bulk_in, bulk_out): Use the correct endpoints. + (ccid_transceive_apdu_level): New. + (ccid_transceive): Divert to above. + (parse_ccid_descriptor): Allow APDU level exchange mode. + 2004-12-21 Werner Koch <wk@g10code.com> * scdaemon.c (main): Use default_homedir(). diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 01c8a9980..eeea651a9 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -198,6 +198,9 @@ struct ccid_driver_s unsigned short id_vendor; unsigned short id_product; unsigned short bcd_device; + int ep_bulk_out; + int ep_bulk_in; + int ep_intr; int seqno; unsigned char t1_ns; unsigned char t1_nr; @@ -207,6 +210,7 @@ struct ccid_driver_s int ifsd; int powered_off; int has_pinpad; + int apdu_level; /* Reader supports short APDU level exchange. */ }; @@ -260,6 +264,7 @@ parse_ccid_descriptor (ccid_driver_t handle, handle->max_ifsd = 32; handle->ifsd = 0; handle->has_pinpad = 0; + handle->apdu_level = 0; DEBUGOUT_3 ("idVendor: %04X idProduct: %04X bcdDevice: %04X\n", handle->id_vendor, handle->id_product, handle->bcd_device); if (buflen < 54 || buf[0] < 54) @@ -372,9 +377,15 @@ parse_ccid_descriptor (ccid_driver_t handle, have_tpdu = 1; } else if ((us & 0x00020000)) - DEBUGOUT (" Short APDU level exchange\n"); + { + DEBUGOUT (" Short APDU level exchange\n"); + handle->apdu_level = 1; + } else if ((us & 0x00040000)) - DEBUGOUT (" Short and extended APDU level exchange\n"); + { + DEBUGOUT (" Short and extended APDU level exchange\n"); + handle->apdu_level = 1; + } else if ((us & 0x00070000)) DEBUGOUT (" WARNING: conflicting exchange levels\n"); @@ -421,10 +432,10 @@ parse_ccid_descriptor (ccid_driver_t handle, DEBUGOUT_LF (); } - if (!have_t1 || !have_tpdu || !have_auto_conf) + if (!have_t1 || !(have_tpdu || handle->apdu_level) || !have_auto_conf) { DEBUGOUT ("this drivers requires that the reader supports T=1, " - "TPDU level exchange and auto configuration - " + "TPDU or APDU level exchange and auto configuration - " "this is not available\n"); return -1; } @@ -546,6 +557,36 @@ make_reader_id (usb_dev_handle *idev, } +/* Helper to find the endpoint from an interface descriptor. */ +static int +find_endpoint (struct usb_interface_descriptor *ifcdesc, int mode) +{ + int no; + int want_bulk_in = 0; + + if (mode == 1) + want_bulk_in = 0x80; + for (no=0; no < ifcdesc->bNumEndpoints; no++) + { + struct usb_endpoint_descriptor *ep = ifcdesc->endpoint + no; + if (ep->bDescriptorType != USB_DT_ENDPOINT) + ; + else if (mode == 2 + && ((ep->bmAttributes & USB_ENDPOINT_TYPE_MASK) + == USB_ENDPOINT_TYPE_INTERRUPT) + && (ep->bEndpointAddress & 0x80)) + return (ep->bEndpointAddress & 0x0f); + else if (((ep->bmAttributes & USB_ENDPOINT_TYPE_MASK) + == USB_ENDPOINT_TYPE_BULK) + && (ep->bEndpointAddress & 0x80) == want_bulk_in) + return (ep->bEndpointAddress & 0x0f); + } + /* Should never happen. */ + return mode == 2? 0x83 : mode == 1? 0x82 :1; +} + + + /* Combination function to either scan all CCID devices or to find and open one specific device. @@ -579,7 +620,9 @@ scan_or_find_devices (int readerno, const char *readerid, char **r_rid, struct usb_device **r_dev, unsigned char **ifcdesc_extra, - size_t *ifcdesc_extra_len) + size_t *ifcdesc_extra_len, + int *interface_number, + int *ep_bulk_out, int *ep_bulk_in, int *ep_intr) { char *rid_list = NULL; int count = 0; @@ -597,6 +640,8 @@ scan_or_find_devices (int readerno, const char *readerid, *ifcdesc_extra = NULL; if (ifcdesc_extra_len) *ifcdesc_extra_len = 0; + if (interface_number) + *interface_number = 0; /* See whether we want scan or find mode. */ if (scan_mode) @@ -721,6 +766,16 @@ scan_or_find_devices (int readerno, const char *readerid, ifcdesc->extralen); *ifcdesc_extra_len = ifcdesc->extralen; } + if (interface_number) + *interface_number = (ifcdesc-> + bInterfaceNumber); + if (ep_bulk_out) + *ep_bulk_out = find_endpoint (ifcdesc, 0); + if (ep_bulk_in) + *ep_bulk_in = find_endpoint (ifcdesc, 1); + if (ep_intr) + *ep_intr = find_endpoint (ifcdesc, 2); + if (r_dev) *r_dev = dev; @@ -787,7 +842,8 @@ ccid_get_reader_list (void) initialized_usb = 1; } - scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL); + scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL, NULL, + NULL, NULL, NULL); return reader_list; } @@ -804,6 +860,7 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) unsigned char *ifcdesc_extra = NULL; size_t ifcdesc_extra_len; int readerno; + int ifc_no, ep_bulk_out, ep_bulk_in, ep_intr; *handle = NULL; @@ -832,7 +889,8 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) readerno = 0; /* Default. */ idev = scan_or_find_devices (readerno, readerid, &rid, &dev, - &ifcdesc_extra, &ifcdesc_extra_len); + &ifcdesc_extra, &ifcdesc_extra_len, + &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr); if (!idev) { if (readerno == -1) @@ -856,6 +914,9 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) (*handle)->id_vendor = dev->descriptor.idVendor; (*handle)->id_product = dev->descriptor.idProduct; (*handle)->bcd_device = dev->descriptor.bcdDevice; + (*handle)->ep_bulk_out = ep_bulk_out; + (*handle)->ep_bulk_in = ep_bulk_in; + (*handle)->ep_intr = ep_intr; DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid ); @@ -867,9 +928,7 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) goto leave; } - /* fixme: Do we need to claim and set the interface as - determined above? */ - rc = usb_claim_interface (idev, 0); + rc = usb_claim_interface (idev, ifc_no); if (rc) { DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); @@ -877,9 +936,6 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) goto leave; } - /* FIXME: Do we need to get the endpoint addresses from the - structure and store them with the handle? */ - leave: free (ifcdesc_extra); if (rc) @@ -944,6 +1000,7 @@ ccid_shutdown_reader (ccid_driver_t handle) usb_dev_handle *idev = NULL; unsigned char *ifcdesc_extra = NULL; size_t ifcdesc_extra_len; + int ifc_no, ep_bulk_out, ep_bulk_in, ep_intr; if (!handle || !handle->rid) return CCID_DRIVER_ERR_INV_VALUE; @@ -951,7 +1008,8 @@ ccid_shutdown_reader (ccid_driver_t handle) do_close_reader (handle); idev = scan_or_find_devices (-1, handle->rid, NULL, &dev, - &ifcdesc_extra, &ifcdesc_extra_len); + &ifcdesc_extra, &ifcdesc_extra_len, + &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr); if (!idev) { DEBUGOUT_1 ("no CCID reader with ID %s\n", handle->rid); @@ -960,6 +1018,9 @@ ccid_shutdown_reader (ccid_driver_t handle) handle->idev = idev; + handle->ep_bulk_out = ep_bulk_out; + handle->ep_bulk_in = ep_bulk_in; + handle->ep_intr = ep_intr; if (parse_ccid_descriptor (handle, ifcdesc_extra, ifcdesc_extra_len)) { @@ -968,9 +1029,7 @@ ccid_shutdown_reader (ccid_driver_t handle) goto leave; } - /* fixme: Do we need to claim and set the interface as - determined above? */ - rc = usb_claim_interface (idev, 0); + rc = usb_claim_interface (idev, ifc_no); if (rc) { DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); @@ -1022,7 +1081,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) int rc; rc = usb_bulk_write (handle->idev, - 1, /*endpoint */ + handle->ep_bulk_out, msg, msglen, 1000 /* ms timeout */); if (rc == msglen) @@ -1053,7 +1112,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, memset (buffer, 0, length); retry: rc = usb_bulk_read (handle->idev, - 0x82, + handle->ep_bulk_in, buffer, length, 10000 /* ms timeout */ ); /* Fixme: instead of using a 10 second timeout we should better @@ -1160,7 +1219,7 @@ ccid_poll (ccid_driver_t handle) int i, j; rc = usb_bulk_read (handle->idev, - 0x83, + handle->ep_intr, msg, sizeof msg, 0 /* ms timeout */ ); if (rc < 0 && errno == ETIMEDOUT) @@ -1402,6 +1461,78 @@ compute_edc (const unsigned char *data, size_t datalen, int use_crc) } +/* Helper for ccid_transceive used for APDU level exchanges. */ +static int +ccid_transceive_apdu_level (ccid_driver_t handle, + const unsigned char *apdu_buf, size_t apdu_buflen, + unsigned char *resp, size_t maxresplen, + size_t *nresp) +{ + int rc; + unsigned char send_buffer[10+259], recv_buffer[10+259]; + const unsigned char *apdu; + size_t apdulen; + unsigned char *msg; + size_t msglen; + unsigned char seqno; + int i; + + msg = send_buffer; + + apdu = apdu_buf; + apdulen = apdu_buflen; + assert (apdulen); + + if (apdulen > 254) + return CCID_DRIVER_ERR_INV_VALUE; /* Invalid length. */ + + msg[0] = PC_to_RDR_XfrBlock; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 4; /* bBWI */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + memcpy (msg+10, apdu, apdulen); + set_msg_len (msg, apdulen); + msglen = 10 + apdulen; + + DEBUGOUT ("sending"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + + rc = bulk_out (handle, msg, msglen); + if (rc) + return rc; + + msg = recv_buffer; + rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, + RDR_to_PC_DataBlock, seqno); + if (rc) + return rc; + + apdu = msg + 10; + apdulen = msglen - 10; + + if (resp) + { + if (apdulen > maxresplen) + { + DEBUGOUT_2 ("provided buffer too short for received data " + "(%u/%u)\n", + (unsigned int)apdulen, (unsigned int)maxresplen); + return CCID_DRIVER_ERR_INV_VALUE; + } + + memcpy (resp, apdu, apdulen); + *nresp = apdulen; + } + + return 0; +} + + + /* Protocol T=1 overview @@ -1478,6 +1609,13 @@ ccid_transceive (ccid_driver_t handle, nresp = &dummy_nresp; *nresp = 0; + /* Smarter readers allow to send APDUs directly; divert here. */ + if (handle->apdu_level) + return ccid_transceive_apdu_level (handle, apdu_buf, apdu_buflen, + resp, maxresplen, nresp); + + /* The other readers we support require sending TPDUs. */ + tpdulen = 0; /* Avoid compiler warning about no initialization. */ msg = send_buffer; for (;;) @@ -1828,7 +1966,7 @@ ccid_transceive_secure (ccid_driver_t handle, if (tpdulen < 4) { - usb_clear_halt (handle->idev, 0x82); + usb_clear_halt (handle->idev, handle->ep_bulk_in); return CCID_DRIVER_ERR_ABORTED; } #ifdef DEBUG_T1 -- cgit v1.2.3 From 832edf9963cbf8a11a49a8f23cc6f4d37f0669c0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 3 Jan 2005 11:30:43 +0000 Subject: (send_pinentry_environment): Fixed changed from 2004-12-18; cut+paste error for lc-messages. --- common/ChangeLog | 5 +++++ common/asshelp.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index 3e060258a..032538bed 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2005-01-03 Werner Koch <wk@g10code.com> + + * asshelp.c (send_pinentry_environment): Fixed changed from + 2004-12-18; cut+paste error for lc-messages. + 2004-12-21 Werner Koch <wk@g10code.com> * simple-pwquery.c (agent_open) [W32]: Implement for W32. diff --git a/common/asshelp.c b/common/asshelp.c index efaf71e30..0edaeae0e 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -150,7 +150,7 @@ send_pinentry_environment (assuan_context_t ctx, #endif if (opt_lc_messages || (dft_ttyname && dft_lc)) { - err = send_one_option (ctx, errsource, "display", + err = send_one_option (ctx, errsource, "lc-messages", opt_lc_messages ? opt_lc_messages : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) -- cgit v1.2.3 From 2f0c8ff6fbd71472604de387592e0181d6bfd8af Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 4 Jan 2005 08:33:20 +0000 Subject: (agent_put_cache): Fix the test for using the default TTL. --- agent/ChangeLog | 5 +++++ agent/cache.c | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index d835c8e60..fa450dfdb 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-01-04 Werner Koch <wk@g10code.com> + + * cache.c (agent_put_cache): Fix the test for using the default + TTL. + 2004-12-21 Werner Koch <wk@g10code.com> * preset-passphrase.c (preset_passphrase): Handle --passphrase. diff --git a/agent/cache.c b/agent/cache.c index b6762edd0..18aa7653b 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -39,7 +39,7 @@ struct cache_item_s { ITEM next; time_t created; time_t accessed; - int ttl; /* max. lifetime given in seonds, -1 one means infinite */ + int ttl; /* max. lifetime given in seconds, -1 one means infinite */ int lockcount; struct secret_data_s *pw; char key[1]; @@ -185,17 +185,18 @@ agent_flush_cache (void) /* Store DATA of length DATALEN in the cache under KEY and mark it with a maximum lifetime of TTL seconds. If there is already data under this key, it will be replaced. Using a DATA of NULL deletes - the entry */ + the entry. A TTL of 0 is replaced by the default TTL and a TTL of + -1 set infinite timeout. */ int agent_put_cache (const char *key, const char *data, int ttl) { ITEM r; if (DBG_CACHE) - log_debug ("agent_put_cache `%s'\n", key); + log_debug ("agent_put_cache `%s' requested ttl=%d\n", key, ttl); housekeeping (); - if (ttl == 1) + if (!ttl) ttl = opt.def_cache_ttl; if (!ttl) return 0; -- cgit v1.2.3 From 902a775ada7bc1eb8d5de9f765393b94f02876fc Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 4 Jan 2005 15:57:10 +0000 Subject: Updated. --- po/ChangeLog | 4 ++++ po/POTFILES.in | 1 + po/de.po | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/po/ChangeLog b/po/ChangeLog index cc20b6227..bfd763bba 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2005-01-04 Werner Koch <wk@g10code.com> + + * de.po: Updated. + 2004-10-22 Werner Koch <wk@g10code.com> * POTFILES.in: Removed sc-investigate.c diff --git a/po/POTFILES.in b/po/POTFILES.in index 9ea9c3fd9..3a5978a62 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -5,6 +5,7 @@ agent/protect-tool.c agent/divert-scd.c agent/genkey.c agent/query.c +agent/trustlist.c common/sysutils.c common/simple-pwquery.c diff --git a/po/de.po b/po/de.po index 086df87b9..e7227df59 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.14\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2004-12-22 18:57+0100\n" -"PO-Revision-Date: 2004-12-22 19:00+0100\n" +"POT-Creation-Date: 2005-01-04 16:45+0100\n" +"PO-Revision-Date: 2005-01-04 16:53+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -303,6 +303,52 @@ msgstr "Falsches Mantra (Passphrase)" msgid "Passphrase" msgstr "Mantra" +#. TRANSLATORS: This prompt is shown by the Pinentry +#. and has one special property: A "%%0A" is used by +#. Pinentry to insert a line break. The double +#. percent sign is actually needed because it is also +#. a printf format string. If you need to insert a +#. plain % sign, you need to encode it as "%%25". The +#. second "%s" gets replaced by a hexdecimal +#. fingerprint string whereas the first one receives +#. the name as store in the certificate. +#: agent/trustlist.c:305 +#, c-format +msgid "" +"Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " +"fingerprint:%%0A %s" +msgstr "Bitte prfen Sie, da das Zertifikat mit dem Namen:%%0A \"%s\"%%0Afolgenden Fingerabdruck hat:%%0A %s" + +#. TRANSLATORS: "Correct" is the label of a button and intended to +#. be hit if the fingerprint matches the one of the CA. The other +#. button is "the default "Cancel" of the Pinentry. +#: agent/trustlist.c:317 +msgid "Correct" +msgstr "Korrekt" + +#. TRANSLATORS: This prompt is shown by the Pinentry +#. and has one special property: A "%%0A" is used by +#. Pinentry to insert a line break. The double +#. percent sign is actually needed because it is also +#. a printf format string. If you need to insert a +#. plain % sign, you need to encode it as "%%25". The +#. "%s" gets replaced by the name as store in the +#. certificate. +#: agent/trustlist.c:334 +#, c-format +msgid "" +"Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " +"certificates?" +msgstr "Wenn Sie vollstndiges Vertrauen haben, da%%0A \"%s\"%%0ABenutzerzertifikate verllich zertifiziert, so antworten Sie mit \"Ja\"" + +#: agent/trustlist.c:342 +msgid "Yes" +msgstr "Ja" + +#: agent/trustlist.c:342 +msgid "No" +msgstr "Nein" + #: common/sysutils.c:87 #, c-format msgid "can't disable core dumps: %s\n" -- cgit v1.2.3 From 444c93043d8d2c9734df9be6067a30292739a9d9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 13 Jan 2005 18:00:46 +0000 Subject: * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Link a simple test program to see whether the installation is sane. * certreqgen.c (proc_parameters): Cast printf arg. --- ChangeLog | 16 ++++++++++ NEWS | 7 ++++- TODO | 10 +++--- acinclude.m4 | 35 +++++++++++++++++---- agent/ChangeLog | 3 ++ agent/trustlist.c | 42 +++++++++++++++++++------ autogen.sh | 3 +- configure.ac | 18 ++++------- doc/ChangeLog | 4 +++ doc/gnupg.texi | 94 +++++++++++++++++++++++++------------------------------ po/de.po | 8 +++-- scd/ChangeLog | 1 + scd/ccid-driver.c | 23 +++++++++++--- sm/ChangeLog | 4 +++ sm/certreqgen.c | 2 +- sm/decrypt.c | 2 +- 16 files changed, 175 insertions(+), 97 deletions(-) diff --git a/ChangeLog b/ChangeLog index ac2784365..237999e8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2005-01-13 Werner Koch <wk@g10code.com> + + Released 1.9.15. + + * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Link a simple test + program to see whether the installation is sane. + +2005-01-07 Werner Koch <wk@g10code.com> + + * configure.ac: Require gpg-error 1.0. + +2005-01-04 Werner Koch <wk@g10code.com> + + * configure.ac: Remove hack not to build gpg2 for W32. + * autogen.sh <build-w32>: Pass option --disable-gpg instead. + 2004-12-22 Werner Koch <wk@g10code.com> Released 1.9.14. diff --git a/NEWS b/NEWS index 3fae5417e..afb519487 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ -Noteworthy changes in version 1.9.15 +Noteworthy changes in version 1.9.15 (2005-01-13) ------------------------------------------------- + * Fixed passphrase caching bug. + + * Better support for CCID readers; the reader from Cherry RS 6700 USB + does now work. + Noteworthy changes in version 1.9.14 (2004-12-22) ------------------------------------------------- diff --git a/TODO b/TODO index 16311a204..7a2292bd6 100644 --- a/TODO +++ b/TODO @@ -67,16 +67,14 @@ might want to have an agent context for each service request * Move pkcs-1 encoding into libgcrypt. -* Use a MAC to protect some files. +* Use a MAC to protect sensitive files. + The problem here is that we need yet another key and it is unlikely + that users are willing to remember that key too. It is possible to + do this with a smartcard, though. * 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. diff --git a/acinclude.m4 b/acinclude.m4 index 5f742b279..31f540640 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -214,6 +214,8 @@ AC_DEFUN([GNUPG_PTH_VERSION_CHECK], [ _pth_version=`$PTH_CONFIG --version | awk 'NR==1 {print [$]3}'` _req_version="ifelse([$1],,1.2.0,$1)" + + AC_MSG_CHECKING(for PTH - version >= $_req_version) for _var in _pth_version _req_version; do eval "_val=\"\$${_var}\"" _major=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\1/'` @@ -237,16 +239,37 @@ AC_DEFUN([GNUPG_PTH_VERSION_CHECK], 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. -***]]) + if test $have_pth = yes; then + AC_MSG_RESULT(yes) + AC_MSG_CHECKING([whether PTH installation is sane]) + AC_CACHE_VAL(gnupg_cv_pth_is_sane,[ + _gnupg_pth_save_cflags=$CFLAGS + _gnupg_pth_save_ldflags=$LDFLAGS + _gnupg_pth_save_libs=$LIBS + CFLAGS="$CFLAGS `$PTH_CONFIG --ldflags`" + LDFLAGS="$LDFLAGS `$PTH_CONFIG --ldflags`" + LIBS="$LIBS `$PTH_CONFIG --libs`" + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pth.h> + ], + [[ pth_init ();]])], + gnupg_cv_pth_is_sane=yes, + gnupg_cv_pth_is_sane=no) + CFLAGS=$_gnupg_pth_save_cflags + LDFLAGS=$_gnupg_pth_save_ldflags + LIBS=$_gnupg_pth_save_libs + ]) + if test $gnupg_cv_pth_is_sane != yes; then + have_pth=no + fi + AC_MSG_RESULT($gnupg_cv_pth_is_sane) + else + AC_MSG_RESULT(no) 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 diff --git a/agent/ChangeLog b/agent/ChangeLog index fa450dfdb..c790482b4 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,8 @@ 2005-01-04 Werner Koch <wk@g10code.com> + * trustlist.c (agent_marktrusted): Use "Cancel" for the first + confirmation and made the strings translatable. + * cache.c (agent_put_cache): Fix the test for using the default TTL. diff --git a/agent/trustlist.c b/agent/trustlist.c index a0b6b9861..edb00650d 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -30,6 +30,7 @@ #include "agent.h" #include <assuan.h> /* fixme: need a way to avoid assuan calls here */ +#include "i18n.h" static const char headerblurb[] = "# This is the list of trusted keys. Comment lines, like this one, as\n" @@ -290,17 +291,30 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) return gpg_error (GPG_ERR_NOT_SUPPORTED); } - /* insert a new one */ + /* Insert a new one. */ if (asprintf (&desc, - "Please verify that the certificate identified as:%%0A" - " \"%s\"%%0A" - "has the fingerprint:%%0A" - " %s", name, fpr) < 0 ) + /* TRANSLATORS: This prompt is shown by the Pinentry + and has one special property: A "%%0A" is used by + Pinentry to insert a line break. The double + percent sign is actually needed because it is also + a printf format string. If you need to insert a + plain % sign, you need to encode it as "%%25". The + second "%s" gets replaced by a hexdecimal + fingerprint string whereas the first one receives + the name as store in the certificate. */ + _("Please verify that the certificate identified as:%%0A" + " \"%s\"%%0A" + "has the fingerprint:%%0A" + " %s"), name, fpr) < 0 ) { trustfp_used--; return out_of_core (); } - rc = agent_get_confirmation (ctrl, desc, "Correct", "No"); + + /* TRANSLATORS: "Correct" is the label of a button and intended to + be hit if the fingerprint matches the one of the CA. The other + button is "the default "Cancel" of the Pinentry. */ + rc = agent_get_confirmation (ctrl, desc, _("Correct"), NULL); free (desc); if (rc) { @@ -309,15 +323,23 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) } if (asprintf (&desc, - "Do you ultimately trust%%0A" - " \"%s\"%%0A" - "to correctly certify user certificates?", + /* TRANSLATORS: This prompt is shown by the Pinentry + and has one special property: A "%%0A" is used by + Pinentry to insert a line break. The double + percent sign is actually needed because it is also + a printf format string. If you need to insert a + plain % sign, you need to encode it as "%%25". The + "%s" gets replaced by the name as store in the + certificate. */ + _("Do you ultimately trust%%0A" + " \"%s\"%%0A" + "to correctly certify user certificates?"), name) < 0 ) { trustfp_used--; return out_of_core (); } - rc = agent_get_confirmation (ctrl, desc, "Yes", "No"); + rc = agent_get_confirmation (ctrl, desc, _("Yes"), _("No")); free (desc); if (rc) { diff --git a/autogen.sh b/autogen.sh index 87ddc6369..67d28ed38 100755 --- a/autogen.sh +++ b/autogen.sh @@ -90,7 +90,8 @@ if test "$1" = "--build-w32"; then --with-libgcrypt-prefix=${w32root} \ --with-libassuan-prefix=${w32root} \ --with-zlib=${w32root} \ - --with-pth-prefix=${w32root} + --with-pth-prefix=${w32root} \ + --disable-gpg rc=$? # Ugly hack to overcome a gettext problem. Someone should look into # gettext to figure out why the po directory is not ignored as it used diff --git a/configure.ac b/configure.ac index 35886dfa6..041a4d1b8 100644 --- a/configure.ac +++ b/configure.ac @@ -24,12 +24,12 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.15-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.15, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. development_version=yes -NEED_GPG_ERROR_VERSION=0.7 +NEED_GPG_ERROR_VERSION=1.0 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.1.94 @@ -133,6 +133,7 @@ test -n "$GNUPG_PROTECT_TOOL_PGM" \ && show_gnupg_protect_tool_pgm="$GNUPG_PROTECT_TOOL_PGM" + # Some folks want to use only the agent form this packet. Make it # easier for them by providing the configure option # --enable-only-agent. @@ -528,9 +529,8 @@ AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) AC_ARG_ENABLE(threads, - AC_HELP_STRING([--disable-threads],[allow building without Pth support]); - -) + AC_HELP_STRING([--disable-threads],[allow building without Pth support]) + ) dnl Must check for network library requirements before doing link tests @@ -1034,19 +1034,13 @@ if test "$build_scdaemon" = "yes"; then fi fi + if test "$build_agent_only" = "yes" ; then build_gpg=no build_gpgsm=no build_scdaemon=no fi -# We don't yet want to build some parts for W32 -case "${host}" in - *-mingw32*) - build_gpg=no - ;; -esac - AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") diff --git a/doc/ChangeLog b/doc/ChangeLog index 407b706b0..855c3ca38 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-01-04 Werner Koch <wk@g10code.com> + + * gnupg.texi: Updated to use @copying. + 2004-12-22 Werner Koch <wk@g10code.com> * gnupg.texi: Reordered. diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 006e604a0..5c6925260 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -1,33 +1,49 @@ \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename gnupg.info - @include version.texi +@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 %**end of header +@copying +This is the @cite{The GNU Privacy Guard Manual} +(version @value{VERSION}, @value{UPDATED}). + +@iftex +Published by the Free Software Foundation@* +59 Temple Place - Suite 330@* +Boston, MA 02111-1307 USA +@end iftex -@macro copyrightnotice Copyright @copyright{} 2002, 2004 Free Software Foundation, Inc. -@end macro -@macro permissionnotice + +@quotation Permission is granted to copy, distribute and/or modify this document 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. The text of the license can be found in the section entitled ``Copying''. -@end macro +@end quotation +@end copying -@settitle Using the GNU Privacy Guard +@dircategory GNU Utilities +@direntry +* gpg: (gnupg). OpenPGP encryption and signing tool. +* gpgsm: (gnupg). S/MIME encryption and signing tool. +@end direntry -@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. +@c +@c Printing stuff taken from gcc. +@c @macro gnupgtabopt{body} @code{\body\} @end macro @@ -48,36 +64,10 @@ section entitled ``Copying''. @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 - +@c +@c Titlepage +@c @setchapternewpage odd - @titlepage @title Using the GNU Privacy Guard @subtitle Version @value{VERSION} @@ -89,26 +79,26 @@ Boston, MA 02111-1307 USA @sp 6 -@author Werner Koch @code{(wk@@gnupg.org)} - +@author Werner Koch (@email{wk@@gnupg.org}) @page @vskip 0pt plus 1filll -@copyrightnotice{} -@sp 2 -@permissionnotice{} +@insertcopying @end titlepage + + @summarycontents @contents @page - +@ifnottex @node Top -@top Introduction -@cindex introduction +@top The GNU Privacy Guard +@insertcopying This manual documents how to use the GNU Privacy Guard system as well as the administration and the architecture. +@end ifnottex @menu * Invoking GPG:: Using the OpenPGP protocol. diff --git a/po/de.po b/po/de.po index e7227df59..bfcf40d67 100644 --- a/po/de.po +++ b/po/de.po @@ -317,7 +317,9 @@ msgstr "Mantra" msgid "" "Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " "fingerprint:%%0A %s" -msgstr "Bitte prfen Sie, da das Zertifikat mit dem Namen:%%0A \"%s\"%%0Afolgenden Fingerabdruck hat:%%0A %s" +msgstr "" +"Bitte prfen Sie, da das Zertifikat mit dem Namen:%%0A \"%s\"%%0Afolgenden " +"Fingerabdruck hat:%%0A %s" #. TRANSLATORS: "Correct" is the label of a button and intended to #. be hit if the fingerprint matches the one of the CA. The other @@ -339,7 +341,9 @@ msgstr "Korrekt" msgid "" "Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " "certificates?" -msgstr "Wenn Sie vollstndiges Vertrauen haben, da%%0A \"%s\"%%0ABenutzerzertifikate verllich zertifiziert, so antworten Sie mit \"Ja\"" +msgstr "" +"Wenn Sie vollstndiges Vertrauen haben, da%%0A \"%s\"%%" +"0ABenutzerzertifikate verllich zertifiziert, so antworten Sie mit \"Ja\"" #: agent/trustlist.c:342 msgid "Yes" diff --git a/scd/ChangeLog b/scd/ChangeLog index 4aae08536..e85c8d81c 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -9,6 +9,7 @@ (ccid_transceive_apdu_level): New. (ccid_transceive): Divert to above. (parse_ccid_descriptor): Allow APDU level exchange mode. + (do_close_reader): Pass the interface number to usb_release_interface. 2004-12-21 Werner Koch <wk@g10code.com> diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index eeea651a9..0694fe762 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -198,6 +198,7 @@ struct ccid_driver_s unsigned short id_vendor; unsigned short id_product; unsigned short bcd_device; + int ifc_no; int ep_bulk_out; int ep_bulk_in; int ep_intr; @@ -914,6 +915,7 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) (*handle)->id_vendor = dev->descriptor.idVendor; (*handle)->id_product = dev->descriptor.idProduct; (*handle)->bcd_device = dev->descriptor.bcdDevice; + (*handle)->ifc_no = ifc_no; (*handle)->ep_bulk_out = ep_bulk_out; (*handle)->ep_bulk_in = ep_bulk_in; (*handle)->ep_intr = ep_intr; @@ -977,7 +979,7 @@ do_close_reader (ccid_driver_t handle) } if (handle->idev) { - usb_release_interface (handle->idev, 0); + usb_release_interface (handle->idev, handle->ifc_no); usb_close (handle->idev); handle->idev = NULL; } @@ -1018,6 +1020,7 @@ ccid_shutdown_reader (ccid_driver_t handle) handle->idev = idev; + handle->ifc_no = ifc_no; handle->ep_bulk_out = ep_bulk_out; handle->ep_bulk_in = ep_bulk_in; handle->ep_intr = ep_intr; @@ -2115,6 +2118,7 @@ main (int argc, char **argv) int no_pinpad = 0; int verify_123456 = 0; int did_verify = 0; + int no_poll = 0; if (argc) { @@ -2139,6 +2143,11 @@ main (int argc, char **argv) ccid_set_debug_level (1); argc--; argv++; } + else if ( !strcmp (*argv, "--no-poll")) + { + no_poll = 1; + argc--; argv++; + } else if ( !strcmp (*argv, "--no-pinpad")) { no_pinpad = 1; @@ -2157,7 +2166,8 @@ main (int argc, char **argv) if (rc) return 1; - ccid_poll (ccid); + if (!no_poll) + ccid_poll (ccid); fputs ("getting ATR ...\n", stderr); rc = ccid_get_atr (ccid, NULL, 0, NULL); if (rc) @@ -2166,7 +2176,8 @@ main (int argc, char **argv) return 1; } - ccid_poll (ccid); + if (!no_poll) + ccid_poll (ccid); fputs ("getting slot status ...\n", stderr); rc = ccid_slot_status (ccid, &slotstat); if (rc) @@ -2175,7 +2186,8 @@ main (int argc, char **argv) return 1; } - ccid_poll (ccid); + if (!no_poll) + ccid_poll (ccid); fputs ("selecting application OpenPGP ....\n", stderr); { @@ -2188,7 +2200,8 @@ main (int argc, char **argv) } - ccid_poll (ccid); + if (!no_poll) + ccid_poll (ccid); fputs ("getting OpenPGP DO 0x65 ....\n", stderr); { diff --git a/sm/ChangeLog b/sm/ChangeLog index df1670082..a4f07b048 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2005-01-13 Werner Koch <wk@g10code.com> + + * certreqgen.c (proc_parameters): Cast printf arg. + 2004-12-22 Werner Koch <wk@g10code.com> * gpgsm.c (set_binary): New. diff --git a/sm/certreqgen.c b/sm/certreqgen.c index bbc7c98e9..7b29a5b8d 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -493,7 +493,7 @@ proc_parameters (ctrl_t ctrl, sprintf (numbuf, "%u", nbits); snprintf (keyparms, DIM (keyparms)-1, - "(6:genkey(3:rsa(5:nbits%d:%s)))", strlen (numbuf), numbuf); + "(6:genkey(3:rsa(5:nbits%d:%s)))", (int)strlen (numbuf), numbuf); rc = gpgsm_agent_genkey (ctrl, keyparms, &public); if (rc) { diff --git a/sm/decrypt.c b/sm/decrypt.c index 8ac2e23fe..9e5518b0f 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -333,7 +333,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp) numbuf, algoid?algoid:"?", NULL); } - /* If it seems that this is not an ecrypted message we + /* If it seems that this is not an encrypted message we return a more sensible error code. */ if (!algoid) rc = gpg_error (GPG_ERR_NO_DATA); -- cgit v1.2.3 From 6cb495ca5caa10a07d58bf074c2f01d596289cf5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 13 Jan 2005 19:03:37 +0000 Subject: post release updates --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index afb519487..101e04b98 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.16 +------------------------------------------------- + + Noteworthy changes in version 1.9.15 (2005-01-13) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 041a4d1b8..6cfc61193 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.15, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.16-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From a5d3f8a6e78844505d9b59f5c41d71d266e4581b Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 26 Jan 2005 22:20:21 +0000 Subject: 2005-01-26 Moritz Schulte <moritz@g10code.com> * command-ssh.c: New file. * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. * findkey.c (modify_description): New function. (agent_key_from_file): Support comment field in key s-expressions. * gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport. (opts) New entry for oSSHSupport. New variable: socket_name_ssh. (cleanup_do): New function based on cleanup(). (cleanup): Use cleanup_do() for socket_name and socket_name_ssh. (main): New switch case for oSSHSupport. (main): Move socket name creation code to ... (create_socket_name): ... this new function. (main): Use create_socket_name() for creating socket names for socket_name and for socket_name_ssh in case ssh support is enabled. Move socket creation code to ... (create_server_socket): ... this new function. (main): Use create_server_socket() for creating sockets. In case standard_socket is set, do not only store a socket name in socket_name, but also in socket_name_ssh. Generate additional environment info strings for ssh support. Pass additional ssh socket argument to handle_connections. (start_connection_thread_ssh): New function. (handle_connections): Use select to multiplex between gpg-agent and ssh-agent protocol. * agent.h (struct opt): New member: ssh_support. Declare function: start_command_handler_ssh. --- agent/ChangeLog | 33 +++++ agent/Makefile.am | 4 +- agent/agent.h | 6 +- agent/findkey.c | 144 +++++++++++++++++++- agent/gpg-agent.c | 399 ++++++++++++++++++++++++++++++++++++++---------------- 5 files changed, 464 insertions(+), 122 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index c790482b4..051ed911e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,36 @@ +2005-01-26 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c: New file. + * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. + + * findkey.c (modify_description): New function. + (agent_key_from_file): Support comment field in key s-expressions. + + * gpg-agent.c (enum cmd_and_opt_values): New item: oSSHSupport. + (opts) New entry for oSSHSupport. + New variable: socket_name_ssh. + (cleanup_do): New function based on cleanup(). + (cleanup): Use cleanup_do() for socket_name and socket_name_ssh. + (main): New switch case for oSSHSupport. + (main): Move socket name creation code to ... + (create_socket_name): ... this new function. + (main): Use create_socket_name() for creating socket names for + socket_name and for socket_name_ssh in case ssh support is + enabled. + Move socket creation code to ... + (create_server_socket): ... this new function. + (main): Use create_server_socket() for creating sockets. + In case standard_socket is set, do not only store a socket name in + socket_name, but also in socket_name_ssh. + Generate additional environment info strings for ssh support. + Pass additional ssh socket argument to handle_connections. + (start_connection_thread_ssh): New function. + (handle_connections): Use select to multiplex between gpg-agent + and ssh-agent protocol. + + * agent.h (struct opt): New member: ssh_support. + Declare function: start_command_handler_ssh. + 2005-01-04 Werner Koch <wk@g10code.com> * trustlist.c (agent_marktrusted): Use "Cancel" for the first diff --git a/agent/Makefile.am b/agent/Makefile.am index 4cedbe74e..df8ec322c 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -29,7 +29,7 @@ AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) gpg_agent_SOURCES = \ gpg-agent.c agent.h \ - command.c \ + command.c command-ssh.c \ query.c \ cache.c \ trans.c \ diff --git a/agent/agent.h b/agent/agent.h index 7d6bf9f47..8afda6463 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -1,5 +1,5 @@ /* agent.h - Global definitions for the agent - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -66,6 +66,7 @@ struct { int allow_preset_passphrase; int keep_tty; /* don't switch the TTY (for pinentry) on request */ int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ + int ssh_support; /* Enable ssh-agent emulation. */ } opt; @@ -136,6 +137,9 @@ void agent_init_default_ctrl (struct server_control_s *ctrl); /*-- command.c --*/ void start_command_handler (int, int); +/*-- command-ssh.c --*/ +void start_command_handler_ssh (int); + /*-- findkey.c --*/ int agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); diff --git a/agent/findkey.c b/agent/findkey.c index b54528295..d39d3aae3 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -1,5 +1,5 @@ /* findkey.c - locate the secret key - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -140,6 +140,108 @@ try_unprotect_cb (struct pin_entry_info_s *pi) } +/* Modify a Key description, replacing certain special format + characters. List of currently supported replacements: + + %% -> % + %c -> <COMMENT>. */ +static int +modify_description (const char *description, + const char *comment, size_t comment_length, + char **description_modified) +{ + size_t description_length; + size_t description_new_length; + gpg_error_t err; + char *description_new; + unsigned int i, j; + unsigned int special; + + description_length = strlen (description); + description_new_length = description_length; + description_new = NULL; + + /* Calculate length. */ + special = 0; + for (i = 0; i < description_length; i++) + { + if (description[i] == '%') + special = 1; + else + { + if (special) + { + description_new_length -= 2; + switch (description[i]) + { + case 'c': + /* Comment. */ + description_new_length += comment_length; + break; + + case '%': + description_new_length += 1; + break; + } + special = 0; + } + } + } + + /* Allocate. */ + description_new = xtrymalloc (description_new_length + 1); + if (! description_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + /* Fill. */ + for (i = j = 0; i < description_length; i++) + { + if (description[i] == '%') + special = 1; + else + { + if (special) + { + switch (description[i]) + { + case 'c': + /* Comment. */ + if (comment) + { + strncpy (description_new + j, comment, comment_length); + j += comment_length; + } + break; + + case '%': + description_new[j] = '%'; + j++; + break; + } + special = 0; + } + else + { + description_new[j] = description[i]; + j++; + } + } + } + + description_new[j] = 0; + *description_modified = description_new; + err = 0; + + out: + + return err; +} + + + /* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP should be the hex encoded keygrip of that key to be used with the caching mechanism. DESC_TEXT may be set to override the default @@ -292,10 +394,42 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, case PRIVATE_KEY_CLEAR: break; /* no unprotection needed */ case PRIVATE_KEY_PROTECTED: - rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache); - if (rc) - log_error ("failed to unprotect the secret key: %s\n", - gpg_strerror (rc)); + { + gcry_sexp_t comment_sexp; + size_t comment_length; + char *desc_text_final; + const char *comment; + + comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0); + if (comment_sexp) + comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length); + else + { + comment = NULL; + comment_length = 0; + } + + if (desc_text) + { + rc = modify_description (desc_text, + comment, comment_length, &desc_text_final); + if (rc) + log_error ("failed to modify description: %s\n", gpg_strerror (rc)); + } + else + desc_text_final = NULL; + + if (! rc) + { + rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache); + if (rc) + log_error ("failed to unprotect the secret key: %s\n", + gpg_strerror (rc)); + } + + gcry_sexp_release (comment_sexp); + xfree (desc_text_final); + } break; case PRIVATE_KEY_SHADOWED: if (shadow_info) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index e76623f75..9f97fb6d7 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1,5 +1,6 @@ /* gpg-agent.c - The GnuPG Agent - * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2002, 2003, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -91,7 +92,8 @@ enum cmd_and_opt_values oAllowMarkTrusted, oAllowPresetPassphrase, oKeepTTY, - oKeepDISPLAY + oKeepDISPLAY, + oSSHSupport }; @@ -144,6 +146,7 @@ static ARGPARSE_OPTS opts[] = { N_("allow clients to mark keys as \"trusted\"")}, { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, + { oSSHSupport, "ssh-support", 0, "Enable SSH-Agent emulation" }, {0} }; @@ -163,6 +166,9 @@ static int maybe_setuid = 1; /* Name of the communication socket */ static char *socket_name; +/* Name of the communication socket used for ssh-agent-emulation. */ +static char *socket_name_ssh; + /* Default values for options passed to the pinentry. */ static char *default_display; static char *default_ttyname; @@ -183,7 +189,7 @@ static char *current_logfile; /* Local prototypes. */ static void create_directories (void); #ifdef USE_GNU_PTH -static void handle_connections (int listen_fd); +static void handle_connections (int listen_fd, int listen_fd_ssh); /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; #endif /*USE_GNU_PTH*/ @@ -297,22 +303,29 @@ set_debug (void) static void -cleanup (void) +cleanup_do (char *name) { - if (socket_name && *socket_name) + if (name && *name) { char *p; - remove (socket_name); - p = strrchr (socket_name, '/'); + remove (name); + p = strrchr (name, '/'); if (p) - { - *p = 0; - rmdir (socket_name); - *p = '/'; - } - *socket_name = 0; + { + *p = 0; + rmdir (name); + *p = '/'; + } + *name = 0; } +} + +static void +cleanup (void) +{ + cleanup_do (socket_name); + cleanup_do (socket_name_ssh); } @@ -404,6 +417,105 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) } +static void +create_socket_name (char **name, int standard_socket, + struct sockaddr_un *serv_addr, + char *standard_identifier, char *identifier) +{ + char *p; + + if (standard_socket) + *name = make_filename (opt.homedir, standard_identifier, NULL); + else + { + *name = xstrdup (identifier); + p = strrchr (*name, '/'); + if (! p) + BUG (); + *p = 0; + if (!mkdtemp (*name)) + { + log_error (_("can't create directory `%s': %s\n"), + *name, strerror (errno)); + exit (1); + } + *p = '/'; + } + + if (strchr (*name, PATHSEP_C)) + { + log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S); + exit (1); + } + if (strlen (*name) + 1 >= sizeof serv_addr->sun_path) + { + log_error ("name of socket too long\n"); + exit (1); + } +} + +static int +create_server_socket (struct sockaddr_un *serv_addr, + int standard_socket, const char *name) +{ + socklen_t len; + int fd; + int rc; + +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else + fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif + if (fd == -1) + { + log_error ("can't create socket: %s\n", strerror (errno)); + exit (1); + } + + memset (serv_addr, 0, sizeof *serv_addr); + serv_addr->sun_family = AF_UNIX; + strcpy (serv_addr->sun_path, name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen (serv_addr->sun_path) + 1); + +#ifdef HAVE_W32_SYSTEM + rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); + if ((rc == -1) && standard_socket) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#else + rc = bind (fd, (struct sockaddr*) serv_addr, len); + if ((rc == -1) && standard_socket && (errno == EADDRINUSE)) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#endif + if (rc == -1) + { + log_error ("error binding socket to `%s': %s\n", + serv_addr->sun_path, strerror (errno)); + close (fd); + exit (1); + } + + if (listen (fd, 5 ) == -1) + { + log_error ("listen() failed: %s\n", strerror (errno)); + close (fd); + exit (1); + } + + if (opt.verbose) + log_info ("listening on socket `%s'\n", socket_name); + + return fd; +} + + int main (int argc, char **argv ) { @@ -596,6 +708,12 @@ main (int argc, char **argv ) case oKeepTTY: opt.keep_tty = 1; break; case oKeepDISPLAY: opt.keep_display = 1; break; + case oSSHSupport: + opt.ssh_support = 1; + opt.keep_tty = 1; + opt.keep_display = 1; + break; + default : pargs.err = configfp? 1:2; break; } } @@ -745,11 +863,10 @@ main (int argc, char **argv ) else { /* Regular server mode */ int fd; - int rc; + int fd_ssh; pid_t pid; - int len; struct sockaddr_un serv_addr; - char *p; + struct sockaddr_un serv_addr_ssh; /* Remove the DISPLAY variable so that a pinentry does not default to a specific display. There is still a default @@ -761,90 +878,26 @@ main (int argc, char **argv ) #endif /* Create the socket name . */ - if (standard_socket) - socket_name = make_filename (opt.homedir, "S.gpg-agent", NULL); + create_socket_name (&socket_name, standard_socket, &serv_addr, + "S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent"); + if (opt.ssh_support) + create_socket_name (&socket_name_ssh, standard_socket, &serv_addr_ssh, + "S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh"); + + fd = create_server_socket (&serv_addr, + standard_socket, socket_name); + if (opt.ssh_support) + fd_ssh = create_server_socket (&serv_addr_ssh, + standard_socket, socket_name_ssh); else - { - socket_name = xstrdup ("/tmp/gpg-XXXXXX/S.gpg-agent"); - p = strrchr (socket_name, '/'); - if (!p) - BUG (); - *p = 0;; - if (!mkdtemp(socket_name)) - { - log_error (_("can't create directory `%s': %s\n"), - socket_name, strerror(errno) ); - exit (1); - } - *p = '/'; - } - - if (strchr (socket_name, PATHSEP_C) ) - { - log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S); - exit (1); - } - if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) - { - log_error ("name of socket too long\n"); - exit (1); - } - -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror(errno) ); - exit (1); - } - - memset (&serv_addr, 0, sizeof serv_addr); - serv_addr.sun_family = AF_UNIX; - strcpy (serv_addr.sun_path, socket_name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen(serv_addr.sun_path) + 1); - -#ifdef HAVE_W32_SYSTEM - rc = _w32_sock_bind (fd, (struct sockaddr*)&serv_addr, len); - if (rc == -1 && standard_socket) - { - remove (socket_name); - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - } -#else - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - if (rc == -1 && standard_socket && errno == EADDRINUSE) - { - remove (socket_name); - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - } -#endif - if (rc == -1) - { - log_error ("error binding socket to `%s': %s\n", - serv_addr.sun_path, strerror (errno) ); - close (fd); - exit (1); - } - - if (listen (fd, 5 ) == -1) - { - log_error ("listen() failed: %s\n", strerror (errno)); - close (fd); - exit (1); - } - - if (opt.verbose) - log_info ("listening on socket `%s'\n", socket_name ); - + /* Make the compiler happy. */ + fd_ssh = -1; fflush (NULL); #ifdef HAVE_W32_SYSTEM pid = getpid (); printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); + printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); #else /*!HAVE_W32_SYSTEM*/ pid = fork (); if (pid == (pid_t)-1) @@ -854,7 +907,7 @@ main (int argc, char **argv ) } else if (pid) { /* We are the parent */ - char *infostr; + char *infostr, *infostr_ssh_sock, *infostr_ssh_pid; close (fd); @@ -866,8 +919,29 @@ main (int argc, char **argv ) kill (pid, SIGTERM); exit (1); } + if (opt.ssh_support) + { + if (asprintf (&infostr_ssh_sock, "SSH_AUTH_SOCK=%s", + socket_name_ssh) < 0) + { + log_error ("out of core\n"); + kill (pid, SIGTERM); + exit (1); + } + if (asprintf (&infostr_ssh_pid, "SSH_AGENT_PID=%u", + pid) < 0) + { + log_error ("out of core\n"); + kill (pid, SIGTERM); + exit (1); + } + } + *socket_name = 0; /* don't let cleanup() remove the socket - the child should do this from now on */ + if (opt.ssh_support) + *socket_name_ssh = 0; + if (argc) { /* run the program given on the commandline */ if (putenv (infostr)) @@ -877,6 +951,20 @@ main (int argc, char **argv ) kill (pid, SIGTERM ); exit (1); } + if (putenv (infostr_ssh_sock)) + { + log_error ("failed to set environment: %s\n", + strerror (errno) ); + kill (pid, SIGTERM ); + exit (1); + } + if (putenv (infostr_ssh_pid)) + { + log_error ("failed to set environment: %s\n", + strerror (errno) ); + kill (pid, SIGTERM ); + exit (1); + } execvp (argv[0], argv); log_error ("failed to run the command: %s\n", strerror (errno)); kill (pid, SIGTERM); @@ -890,12 +978,29 @@ main (int argc, char **argv ) { *strchr (infostr, '=') = ' '; printf ( "setenv %s\n", infostr); + if (opt.ssh_support) + { + *strchr (infostr_ssh_sock, '=') = ' '; + printf ( "setenv %s\n", infostr_ssh_sock); + *strchr (infostr_ssh_pid, '=') = ' '; + printf ( "setenv %s\n", infostr_ssh_pid); + } } else { printf ( "%s; export GPG_AGENT_INFO;\n", infostr); + if (opt.ssh_support) + { + printf ( "%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock); + printf ( "%s; export SSH_AGENT_PID;\n", infostr_ssh_pid); + } } free (infostr); + if (opt.ssh_support) + { + free (infostr_ssh_sock); + free (infostr_ssh_pid); + } exit (0); } /*NEVER REACHED*/ @@ -949,7 +1054,7 @@ main (int argc, char **argv ) sa.sa_flags = 0; sigaction (SIGPIPE, &sa, NULL); #endif - handle_connections (fd); + handle_connections (fd, opt.ssh_support ? fd_ssh : -1); } else #endif /*!USE_GNU_PTH*/ @@ -1230,16 +1335,37 @@ start_connection_thread (void *arg) return NULL; } +static void * +start_connection_thread_ssh (void *arg) +{ + int fd = (int)arg; + + if (opt.verbose) + log_info ("ssh handler for fd %d started\n", fd); + + /* FIXME: Move this housekeeping into a ticker function. Calling it + for each connection should work but won't work anymore if our + cleints start to keep connections. */ + agent_trustlist_housekeeping (); + + start_command_handler_ssh (fd); + if (opt.verbose) + log_info ("ssh handler for fd %d terminated\n", fd); + + return NULL; +} static void -handle_connections (int listen_fd) +handle_connections (int listen_fd, int listen_fd_ssh) { pth_attr_t tattr; pth_event_t ev; sigset_t sigs; int signo; struct sockaddr_un paddr; - socklen_t plen = sizeof( paddr ); + socklen_t plen = sizeof ( paddr ); + fd_set fdset, read_fdset; + int ret; int fd; tattr = pth_attr_new(); @@ -1259,6 +1385,11 @@ handle_connections (int listen_fd) ev = NULL; #endif + FD_ZERO (&fdset); + FD_SET (listen_fd, &fdset); + if (listen_fd_ssh != -1) + FD_SET (listen_fd_ssh, &fdset); + for (;;) { if (shutdown_pending) @@ -1275,28 +1406,68 @@ handle_connections (int listen_fd) continue; } - fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); - if (fd == -1) - { + read_fdset = fdset; + ret = pth_select (FD_SETSIZE, &read_fdset, NULL, NULL, NULL); + if (ret == -1) + { + log_error ("pth_select failed: %s - waiting 1s\n", + strerror (errno)); + pth_sleep (1); + continue; + } + + + if (FD_ISSET (listen_fd, &read_fdset)) + { + fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { #ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ - if (pth_event_status (ev) == PTH_STATUS_OCCURRED) + if (pth_event_status (ev) == PTH_STATUS_OCCURRED) #else - if (pth_event_occurred (ev)) + if (pth_event_occurred (ev)) #endif - { - handle_signal (signo); - continue; + { + handle_signal (signo); + continue; + } + log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); + pth_sleep(1); + continue; + } + + if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); } - log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); - pth_sleep(1); - continue; } + else if ((listen_fd_ssh != -1) && FD_ISSET (listen_fd_ssh, &read_fdset)) + { + fd = pth_accept_ev (listen_fd_ssh, (struct sockaddr *)&paddr, &plen, ev); + if (fd == -1) + { +#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ + if (pth_event_status (ev) == PTH_STATUS_OCCURRED) +#else + if (pth_event_occurred (ev)) +#endif + { + handle_signal (signo); + continue; + } + log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); + pth_sleep(1); + continue; + } - if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) - { - log_error ("error spawning connection handler: %s\n", - strerror (errno) ); - close (fd); + if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } } } -- cgit v1.2.3 From 4d2b474ef2be05995d445ebef9d54634ed24d93b Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 26 Jan 2005 22:24:59 +0000 Subject: 2005-01-26 Moritz Schulte <moritz@g10code.com> * Makefile.am (libcommon_a_SOURCES): New source files: estream.c, estream.h. * estream.c, estream.h: New files. --- common/ChangeLog | 6 + common/Makefile.am | 3 +- common/estream.c | 2609 ++++++++++++++++++++++++++++++++++++++++++++++++++++ common/estream.h | 201 ++++ 4 files changed, 2818 insertions(+), 1 deletion(-) create mode 100644 common/estream.c create mode 100644 common/estream.h diff --git a/common/ChangeLog b/common/ChangeLog index 032538bed..e323dc148 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +2005-01-26 Moritz Schulte <moritz@g10code.com> + + * Makefile.am (libcommon_a_SOURCES): New source files: estream.c, + estream.h. + * estream.c, estream.h: New files. + 2005-01-03 Werner Koch <wk@g10code.com> * asshelp.c (send_pinentry_environment): Fixed changed from diff --git a/common/Makefile.am b/common/Makefile.am index ccbaaad75..6cbbf9f3a 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -44,7 +44,8 @@ libcommon_a_SOURCES = \ simple-gettext.c \ w32reg.c \ signal.c \ - dynload.h + dynload.h \ + estream.c estream.h libcommon_a_LIBADD = @LIBOBJS@ diff --git a/common/estream.c b/common/estream.c new file mode 100644 index 000000000..00cb749e8 --- /dev/null +++ b/common/estream.c @@ -0,0 +1,2609 @@ +/* estream.c - Extended stream I/O/ Library + Copyright (C) 2004 g10 Code GmbH + + This file is part of Libestream. + + Libestream 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. + + Libestream 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Libestream; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef USE_ESTREAM_SUPPORT_H +# include <estream-support.h> +#endif + +#ifdef USE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <fcntl.h> +#include <errno.h> +#include <stddef.h> +#include <assert.h> + +#ifdef HAVE_PTH +# include <pth.h> +#endif + +#ifndef HAVE_MKSTEMP +int mkstemp (char *template); +#endif + +#ifndef HAVE_MEMRCHR +void *memrchr (const void *block, int c, size_t size); +#endif + +#include <estream.h> + + + +/* Generally used types. */ + +typedef void *(*func_realloc_t) (void *mem, size_t size); +typedef void (*func_free_t) (void *mem); + + + +/* Buffer management layer. */ + +#define BUFFER_BLOCK_SIZE BUFSIZ +#define BUFFER_UNREAD_SIZE 16 + + + +/* Macros. */ + +#define BUFFER_ROUND_TO_BLOCK(size, block_size) \ + (((size) + (block_size - 1)) / block_size) + + + +/* Locking. */ + +#ifdef HAVE_PTH + +typedef pth_mutex_t estream_mutex_t; +# define ESTREAM_MUTEX_INITIALIZER PTH_MUTEX_INIT +# define ESTREAM_MUTEX_LOCK(mutex) \ + pth_mutex_acquire (&(mutex), 0, NULL) +# define ESTREAM_MUTEX_UNLOCK(mutex) \ + pth_mutex_release (&(mutex)) +# define ESTREAM_MUTEX_TRYLOCK(mutex) \ + ((pth_mutex_acquire (&(mutex), 1, NULL) == TRUE) ? 0 : -1) +# define ESTREAM_MUTEX_INITIALIZE(mutex) \ + pth_mutex_init (&(mutex)) +# define ESTREAM_THREADING_INIT() ((pth_init () == TRUE) ? 0 : -1) + +#else + +typedef void *estream_mutex_t; +# define ESTREAM_MUTEX_INITIALIZER NULL +# define ESTREAM_MUTEX_LOCK(mutex) (void) 0 +# define ESTREAM_MUTEX_UNLOCK(mutex) (void) 0 +# define ESTREAM_MUTEX_TRYLOCK(mutex) 0 +# define ESTREAM_MUTEX_INITIALIZE(mutex) (void) 0 +# define ESTREAM_THREADING_INIT() 0 + +#endif + +/* Memory allocator functions. */ + +#define MEM_ALLOC malloc +#define MEM_REALLOC realloc +#define MEM_FREE free + +/* Primitive system I/O. */ + +#ifdef HAVE_PTH +# define ESTREAM_SYS_READ pth_read +# define ESTREAM_SYS_WRITE pth_write +#else +# define ESTREAM_SYS_READ read +# define ESTREAM_SYS_WRITE write +#endif + +/* Misc definitions. */ + +#define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR) + +#define ES_FLAG_WRITING ES__FLAG_WRITING + +/* An internal stream object. */ + +struct estream_internal +{ + unsigned char buffer[BUFFER_BLOCK_SIZE]; + unsigned char unread_buffer[BUFFER_UNREAD_SIZE]; + estream_mutex_t lock; /* Lock. */ + void *cookie; /* Cookie. */ + void *opaque; /* Opaque data. */ + unsigned int flags; /* Flags. */ + off_t offset; + es_cookie_read_function_t func_read; + es_cookie_write_function_t func_write; + es_cookie_seek_function_t func_seek; + es_cookie_close_function_t func_close; + int strategy; + int fd; + struct + { + unsigned int err: 1; + unsigned int eof: 1; + } indicators; + unsigned int deallocate_buffer: 1; +}; + +typedef struct estream_internal *estream_internal_t; + +#define ESTREAM_LOCK(stream) ESTREAM_MUTEX_LOCK (stream->intern->lock) +#define ESTREAM_UNLOCK(stream) ESTREAM_MUTEX_UNLOCK (stream->intern->lock) +#define ESTREAM_TRYLOCK(stream) ESTREAM_MUTEX_TRYLOCK (stream->intern->lock) + +/* Stream list. */ + +typedef struct estream_list *estream_list_t; + +struct estream_list +{ + estream_t car; + estream_list_t cdr; + estream_list_t *prev_cdr; +}; + +static estream_list_t estream_list; +#ifdef HAVE_PTH +static estream_mutex_t estream_list_lock = ESTREAM_MUTEX_INITIALIZER; +#endif + +#define ESTREAM_LIST_LOCK ESTREAM_MUTEX_LOCK (estream_list_lock) +#define ESTREAM_LIST_UNLOCK ESTREAM_MUTEX_UNLOCK (estream_list_lock) + +#ifndef EOPNOTSUPP +# define EOPNOTSUPP ENOSYS +#endif + + + + +/* Macros. */ + +/* Calculate array dimension. */ +#define DIM(array) (sizeof (array) / sizeof (*array)) + +/* Evaluate EXPRESSION, setting VARIABLE to the return code, if + VARIABLE is zero. */ +#define SET_UNLESS_NONZERO(variable, tmp_variable, expression) \ + do \ + { \ + tmp_variable = expression; \ + if ((! variable) && tmp_variable) \ + variable = tmp_variable; \ + } \ + while (0) + +/* + * List manipulation. + */ + +/* Add STREAM to the list of registered stream objects. */ +static int +es_list_add (estream_t stream) +{ + estream_list_t list_obj; + int ret; + + list_obj = MEM_ALLOC (sizeof (*list_obj)); + if (! list_obj) + ret = -1; + else + { + ESTREAM_LIST_LOCK; + list_obj->car = stream; + list_obj->cdr = estream_list; + list_obj->prev_cdr = &estream_list; + if (estream_list) + estream_list->prev_cdr = &list_obj->cdr; + estream_list = list_obj; + ESTREAM_LIST_UNLOCK; + ret = 0; + } + + return ret; +} + +/* Remove STREAM from the list of registered stream objects. */ +static void +es_list_remove (estream_t stream) +{ + estream_list_t list_obj; + + ESTREAM_LIST_LOCK; + for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr) + if (list_obj->car == stream) + { + *list_obj->prev_cdr = list_obj->cdr; + if (list_obj->cdr) + list_obj->cdr->prev_cdr = list_obj->prev_cdr; + MEM_FREE (list_obj); + break; + } + ESTREAM_LIST_UNLOCK; +} + +/* Type of an stream-iterator-function. */ +typedef int (*estream_iterator_t) (estream_t stream); + +/* Iterate over list of registered streams, calling ITERATOR for each + of them. */ +static int +es_list_iterate (estream_iterator_t iterator) +{ + estream_list_t list_obj; + int ret = 0; + + ESTREAM_LIST_LOCK; + for (list_obj = estream_list; list_obj; list_obj = list_obj->cdr) + ret |= (*iterator) (list_obj->car); + ESTREAM_LIST_UNLOCK; + + return ret; +} + + + +/* + * Initialization. + */ + +static int +es_init_do (void) +{ + int err; + + err = ESTREAM_THREADING_INIT (); + + return err; +} + + + +/* + * I/O methods. + */ + +/* Implementation of Memory I/O. */ + +/* Cookie for memory objects. */ +typedef struct estream_cookie_mem +{ + unsigned int flags; /* Open flags. */ + char *memory; /* Data. */ + size_t memory_size; /* Size of MEMORY. */ + size_t offset; /* Current offset in MEMORY. */ + size_t data_len; /* Length of data in MEMORY. */ + size_t block_size; /* Block size. */ + unsigned int grow: 1; /* MEMORY is allowed to grow. */ + unsigned int append_zero: 1; /* Append zero after data. */ + unsigned int dont_free: 1; /* Append zero after data. */ + char **ptr; + size_t *size; + func_realloc_t func_realloc; + func_free_t func_free; +} *estream_cookie_mem_t; + +/* Create function for memory objects. */ +static int +es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie, + unsigned char *ES__RESTRICT data, size_t data_n, + size_t data_len, + size_t block_size, unsigned int grow, + unsigned int append_zero, unsigned int dont_free, + char **ptr, size_t *size, + func_realloc_t func_realloc, func_free_t func_free, + unsigned int flags) +{ + estream_cookie_mem_t mem_cookie; + int err; + + mem_cookie = MEM_ALLOC (sizeof (*mem_cookie)); + if (! mem_cookie) + err = -1; + else + { + mem_cookie->flags = flags; + mem_cookie->memory = data; + mem_cookie->memory_size = data_n; + mem_cookie->offset = 0; + mem_cookie->data_len = data_len; + mem_cookie->block_size = block_size; + mem_cookie->grow = grow ? 1 : 0; + mem_cookie->append_zero = append_zero ? 1 : 0; + mem_cookie->dont_free = dont_free ? 1 : 0; + mem_cookie->ptr = ptr; + mem_cookie->size = size; + mem_cookie->func_realloc = func_realloc ? func_realloc : MEM_REALLOC; + mem_cookie->func_free = func_free ? func_free : MEM_FREE; + mem_cookie->offset = 0; + *cookie = mem_cookie; + err = 0; + } + + return err; +} + +/* Read function for memory objects. */ +static ssize_t +es_func_mem_read (void *cookie, char *buffer, size_t size) +{ + estream_cookie_mem_t mem_cookie = cookie; + ssize_t ret; + + if (size > mem_cookie->data_len - mem_cookie->offset) + size = mem_cookie->data_len - mem_cookie->offset; + + if (size) + { + memcpy (buffer, mem_cookie->memory + mem_cookie->offset, size); + mem_cookie->offset += size; + } + + ret = size; + + return ret; +} + +/* Write function for memory objects. */ +static ssize_t +es_func_mem_write (void *cookie, const char *buffer, size_t size) +{ + estream_cookie_mem_t mem_cookie = cookie; + func_realloc_t func_realloc = mem_cookie->func_realloc; + char *memory_new; + size_t newsize; + ssize_t ret; + int err; + + if (size) + { + /* Regular write. */ + + if (mem_cookie->flags & O_APPEND) + /* Append to data. */ + mem_cookie->offset = mem_cookie->data_len; + + if (! mem_cookie->grow) + if (size > mem_cookie->memory_size - mem_cookie->offset) + size = mem_cookie->memory_size - mem_cookie->offset; + + err = 0; + + while (size > (mem_cookie->memory_size - mem_cookie->offset)) + { + memory_new = (*func_realloc) (mem_cookie->memory, + mem_cookie->memory_size + + mem_cookie->block_size); + if (! memory_new) + { + err = -1; + break; + } + else + { + if (mem_cookie->memory != memory_new) + mem_cookie->memory = memory_new; + mem_cookie->memory_size += mem_cookie->block_size; + } + } + if (err) + goto out; + + if (size) + { + memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size); + if (mem_cookie->offset + size > mem_cookie->data_len) + mem_cookie->data_len = mem_cookie->offset + size; + mem_cookie->offset += size; + } + } + else + { + /* Flush. */ + + err = 0; + if (mem_cookie->append_zero) + { + if (mem_cookie->data_len >= mem_cookie->memory_size) + { + newsize = BUFFER_ROUND_TO_BLOCK (mem_cookie->data_len + 1, + mem_cookie->block_size) + * mem_cookie->block_size; + + memory_new = (*func_realloc) (mem_cookie->memory, newsize); + if (! memory_new) + { + err = -1; + goto out; + } + + if (mem_cookie->memory != memory_new) + mem_cookie->memory = memory_new; + mem_cookie->memory_size = newsize; + } + + mem_cookie->memory[mem_cookie->data_len + 1] = 0; + } + + /* Return information to user if necessary. */ + if (mem_cookie->ptr) + *mem_cookie->ptr = (char *) mem_cookie->memory; + if (mem_cookie->size) + *mem_cookie->size = mem_cookie->data_len; + } + + out: + + if (err) + ret = -1; + else + ret = size; + + return ret; +} + +/* Seek function for memory objects. */ +static int +es_func_mem_seek (void *cookie, off_t *offset, int whence) +{ + estream_cookie_mem_t mem_cookie = cookie; + off_t pos_new; + int err = 0; + + switch (whence) + { + case SEEK_SET: + pos_new = *offset; + break; + + case SEEK_CUR: + pos_new = mem_cookie->offset += *offset; + break; + + case SEEK_END: + pos_new = mem_cookie->data_len += *offset; + break; + + default: + /* Never reached. */ + pos_new = 0; + } + + if (pos_new > mem_cookie->memory_size) + { + /* Grow buffer if possible. */ + + if (mem_cookie->grow) + { + func_realloc_t func_realloc = mem_cookie->func_realloc; + size_t newsize; + void *p; + + newsize = BUFFER_ROUND_TO_BLOCK (pos_new, mem_cookie->block_size); + p = (*func_realloc) (mem_cookie->memory, newsize); + if (! p) + { + err = -1; + goto out; + } + else + { + if (mem_cookie->memory != p) + mem_cookie->memory = p; + mem_cookie->memory_size = newsize; + } + } + else + { + errno = EINVAL; + err = -1; + goto out; + } + } + + if (pos_new > mem_cookie->data_len) + /* Fill spare space with zeroes. */ + memset (mem_cookie->memory + mem_cookie->data_len, + 0, pos_new - mem_cookie->data_len); + + mem_cookie->offset = pos_new; + *offset = pos_new; + + out: + + return err; +} + +/* Destroy function for memory objects. */ +static int +es_func_mem_destroy (void *cookie) +{ + estream_cookie_mem_t mem_cookie = cookie; + func_free_t func_free = mem_cookie->func_free; + + if (! mem_cookie->dont_free) + (*func_free) (mem_cookie->memory); + MEM_FREE (mem_cookie); + + return 0; +} + +static es_cookie_io_functions_t estream_functions_mem = + { + es_func_mem_read, + es_func_mem_write, + es_func_mem_seek, + es_func_mem_destroy, + }; + +/* Implementation of fd I/O. */ + +/* Cookie for fd objects. */ +typedef struct estream_cookie_fd +{ + int fd; +} *estream_cookie_fd_t; + +/* Create function for fd objects. */ +static int +es_func_fd_create (void **cookie, int fd, unsigned int flags) +{ + estream_cookie_fd_t fd_cookie; + int err; + + fd_cookie = MEM_ALLOC (sizeof (*fd_cookie)); + if (! fd_cookie) + err = -1; + else + { + fd_cookie->fd = fd; + *cookie = fd_cookie; + err = 0; + } + + return err; +} + +/* Read function for fd objects. */ +static ssize_t +es_func_fd_read (void *cookie, char *buffer, size_t size) + +{ + estream_cookie_fd_t file_cookie = cookie; + ssize_t bytes_read; + + bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); + + return bytes_read; +} + +/* Write function for fd objects. */ +static ssize_t +es_func_fd_write (void *cookie, const char *buffer, size_t size) + +{ + estream_cookie_fd_t file_cookie = cookie; + ssize_t bytes_written; + + bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); + + return bytes_written; +} + +/* Seek function for fd objects. */ +static int +es_func_fd_seek (void *cookie, off_t *offset, int whence) +{ + estream_cookie_fd_t file_cookie = cookie; + off_t offset_new; + int err; + + offset_new = lseek (file_cookie->fd, *offset, whence); + if (offset_new == -1) + err = -1; + else + { + *offset = offset_new; + err = 0; + } + + return err; +} + +/* Destroy function for fd objects. */ +static int +es_func_fd_destroy (void *cookie) +{ + estream_cookie_fd_t fd_cookie = cookie; + int err; + + if (fd_cookie) + { + err = close (fd_cookie->fd); + MEM_FREE (fd_cookie); + } + else + err = 0; + + return err; +} + +static es_cookie_io_functions_t estream_functions_fd = + { + es_func_fd_read, + es_func_fd_write, + es_func_fd_seek, + es_func_fd_destroy + }; + +/* Implementation of file I/O. */ + +/* Create function for file objects. */ +static int +es_func_file_create (void **cookie, int *filedes, + const char *path, unsigned int flags) +{ + estream_cookie_fd_t file_cookie; + int err; + int fd; + + err = 0; + fd = -1; + + file_cookie = MEM_ALLOC (sizeof (*file_cookie)); + if (! file_cookie) + { + err = -1; + goto out; + } + + fd = open (path, flags, ES_DEFAULT_OPEN_MODE); + if (fd == -1) + { + err = -1; + goto out; + } + + file_cookie->fd = fd; + *cookie = file_cookie; + *filedes = fd; + + out: + + if (err) + MEM_FREE (file_cookie); + + return err; +} + +static es_cookie_io_functions_t estream_functions_file = + { + es_func_fd_read, + es_func_fd_write, + es_func_fd_seek, + es_func_fd_destroy + }; + + + +/* Stream primitives. */ + +static int +es_convert_mode (const char *mode, unsigned int *flags) +{ + struct + { + const char *mode; + unsigned int flags; + } mode_flags[] = { { "r", + O_RDONLY }, + { "rb", + O_RDONLY }, + { "w", + O_WRONLY | O_TRUNC | O_CREAT }, + { "wb", + O_WRONLY | O_TRUNC | O_CREAT }, + { "a", + O_WRONLY | O_APPEND | O_CREAT }, + { "ab", + O_WRONLY | O_APPEND | O_CREAT }, + { "r+", + O_RDWR }, + { "rb+", + O_RDWR }, + { "r+b", + O_RDONLY | O_WRONLY }, + { "w+", + O_RDWR | O_TRUNC | O_CREAT }, + { "wb+", + O_RDWR | O_TRUNC | O_CREAT }, + { "w+b", + O_RDWR | O_TRUNC | O_CREAT }, + { "a+", + O_RDWR | O_CREAT | O_APPEND }, + { "ab+", + O_RDWR | O_CREAT | O_APPEND }, + { "a+b", + O_RDWR | O_CREAT | O_APPEND } }; + unsigned int i; + int err; + + for (i = 0; i < DIM (mode_flags); i++) + if (! strcmp (mode_flags[i].mode, mode)) + break; + if (i == DIM (mode_flags)) + { + errno = EINVAL; + err = -1; + } + else + { + err = 0; + *flags = mode_flags[i].flags; + } + + return err; +} + + + +/* + * Low level stream functionality. + */ + +static int +es_fill (estream_t stream) +{ + size_t bytes_read = 0; + int err; + + if (!stream->intern->func_read) + { + errno = EOPNOTSUPP; + err = -1; + } + else + { + es_cookie_read_function_t func_read = stream->intern->func_read; + ssize_t ret; + + ret = (*func_read) (stream->intern->cookie, + stream->buffer, stream->buffer_size); + if (ret == -1) + { + bytes_read = 0; + err = -1; + } + else + { + bytes_read = ret; + err = 0; + } + } + + if (err) + stream->intern->indicators.err = 1; + else if (!bytes_read) + stream->intern->indicators.eof = 1; + + stream->intern->offset += stream->data_len; + stream->data_len = bytes_read; + stream->data_offset = 0; + + return err; +} + +static int +es_flush (estream_t stream) +{ + es_cookie_write_function_t func_write = stream->intern->func_write; + int err; + + assert (stream->flags & ES_FLAG_WRITING); + + if (stream->data_offset) + { + size_t bytes_written; + size_t data_flushed; + ssize_t ret; + + if (! func_write) + { + err = EOPNOTSUPP; + goto out; + } + + /* Note: to prevent an endless loop caused by user-provided + write-functions that pretend to have written more bytes than + they were asked to write, we have to check for + "(stream->data_offset - data_flushed) > 0" instead of + "stream->data_offset - data_flushed". */ + + data_flushed = 0; + err = 0; + + while ((((ssize_t) (stream->data_offset - data_flushed)) > 0) && (! err)) + { + ret = (*func_write) (stream->intern->cookie, + stream->buffer + data_flushed, + stream->data_offset - data_flushed); + if (ret == -1) + { + bytes_written = 0; + err = -1; + } + else + bytes_written = ret; + + data_flushed += bytes_written; + if (err) + break; + } + + stream->data_flushed += data_flushed; + if (stream->data_offset == data_flushed) + { + stream->intern->offset += stream->data_offset; + stream->data_offset = 0; + stream->data_flushed = 0; + + /* Propagate flush event. */ + (*func_write) (stream->intern->cookie, NULL, 0); + } + } + else + err = 0; + + out: + + if (err) + stream->intern->indicators.err = 1; + + return err; +} + +/* Discard buffered data for STREAM. */ +static void +es_empty (estream_t stream) +{ + assert (! (stream->flags & ES_FLAG_WRITING)); + stream->data_len = 0; + stream->data_offset = 0; + stream->unread_data_len = 0; +} + +/* Initialize STREAM. */ +static void +es_initialize (estream_t stream, + void *cookie, int fd, es_cookie_io_functions_t functions) +{ + stream->intern->cookie = cookie; + stream->intern->opaque = NULL; + stream->intern->offset = 0; + stream->intern->func_read = functions.func_read; + stream->intern->func_write = functions.func_write; + stream->intern->func_seek = functions.func_seek; + stream->intern->func_close = functions.func_close; + stream->intern->strategy = _IOFBF; + stream->intern->fd = fd; + stream->intern->indicators.err = 0; + stream->intern->indicators.eof = 0; + stream->intern->deallocate_buffer = 0; + + stream->data_len = 0; + stream->data_offset = 0; + stream->data_flushed = 0; + stream->unread_data_len = 0; + stream->flags = 0; +} + +/* Deinitialize STREAM. */ +static int +es_deinitialize (estream_t stream) +{ + es_cookie_close_function_t func_close; + int err, tmp_err; + + func_close = stream->intern->func_close; + + err = 0; + if (stream->flags & ES_FLAG_WRITING) + SET_UNLESS_NONZERO (err, tmp_err, es_flush (stream)); + if (func_close) + SET_UNLESS_NONZERO (err, tmp_err, (*func_close) (stream->intern->cookie)); + + return err; +} + +/* Create a new stream object, initialize it. */ +static int +es_create (estream_t *stream, void *cookie, int fd, + es_cookie_io_functions_t functions) +{ + estream_internal_t stream_internal_new; + estream_t stream_new; + int err; + + stream_new = NULL; + stream_internal_new = NULL; + + stream_new = MEM_ALLOC (sizeof (*stream_new)); + if (! stream_new) + { + err = -1; + goto out; + } + + stream_internal_new = MEM_ALLOC (sizeof (*stream_internal_new)); + if (! stream_internal_new) + { + err = -1; + goto out; + } + + stream_new->buffer = stream_internal_new->buffer; + stream_new->buffer_size = sizeof (stream_internal_new->buffer); + stream_new->unread_buffer = stream_internal_new->unread_buffer; + stream_new->unread_buffer_size = sizeof (stream_internal_new->unread_buffer); + stream_new->intern = stream_internal_new; + + ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock); + es_initialize (stream_new, cookie, fd, functions); + + err = es_list_add (stream_new); + if (err) + goto out; + + *stream = stream_new; + + out: + + if (err) + { + if (stream_new) + { + es_deinitialize (stream_new); + MEM_FREE (stream_new); + } + } + + return err; +} + +/* Deinitialize a stream object and destroy it. */ +static int +es_destroy (estream_t stream) +{ + int err = 0; + + if (stream) + { + es_list_remove (stream); + err = es_deinitialize (stream); + MEM_FREE (stream->intern); + MEM_FREE (stream); + } + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in + unbuffered-mode, storing the amount of bytes read in + *BYTES_READ. */ +static int +es_read_nbf (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + es_cookie_read_function_t func_read = stream->intern->func_read; + size_t data_read; + ssize_t ret; + int err; + + data_read = 0; + err = 0; + + while (bytes_to_read - data_read) + { + ret = (*func_read) (stream->intern->cookie, + buffer + data_read, bytes_to_read - data_read); + if (ret == -1) + { + err = -1; + break; + } + else if (ret) + data_read += ret; + else + break; + } + + stream->intern->offset += data_read; + *bytes_read = data_read; + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in + fully-buffered-mode, storing the amount of bytes read in + *BYTES_READ. */ +static int +es_read_fbf (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + size_t data_available; + size_t data_to_read; + size_t data_read; + int err; + + data_read = 0; + err = 0; + + while ((bytes_to_read - data_read) && (! err)) + { + if (stream->data_offset == stream->data_len) + { + /* Nothing more to read in current container, try to + fill container with new data. */ + err = es_fill (stream); + if (! err) + if (! stream->data_len) + /* Filling did not result in any data read. */ + break; + } + + if (! err) + { + /* Filling resulted in some new data. */ + + data_to_read = bytes_to_read - data_read; + data_available = stream->data_len - stream->data_offset; + if (data_to_read > data_available) + data_to_read = data_available; + + memcpy (buffer + data_read, + stream->buffer + stream->data_offset, data_to_read); + stream->data_offset += data_to_read; + data_read += data_to_read; + } + } + + *bytes_read = data_read; + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in + line-buffered-mode, storing the amount of bytes read in + *BYTES_READ. */ +static int +es_read_lbf (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + int err; + + err = es_read_fbf (stream, buffer, bytes_to_read, bytes_read); + + return err; +} + +/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER, storing + *the amount of bytes read in BYTES_READ. */ +static int +es_readn (estream_t ES__RESTRICT stream, + unsigned char *ES__RESTRICT buffer, + size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) +{ + size_t data_read_unread, data_read; + int err; + + data_read_unread = 0; + data_read = 0; + err = 0; + + if (stream->flags & ES_FLAG_WRITING) + { + /* Switching to reading mode -> flush output. */ + err = es_flush (stream); + if (err) + goto out; + stream->flags &= ~ES_FLAG_WRITING; + } + + /* Read unread data first. */ + while ((bytes_to_read - data_read_unread) && stream->unread_data_len) + { + buffer[data_read_unread] + = stream->unread_buffer[stream->unread_data_len - 1]; + stream->unread_data_len--; + data_read_unread++; + } + + switch (stream->intern->strategy) + { + case _IONBF: + err = es_read_nbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + case _IOLBF: + err = es_read_lbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + case _IOFBF: + err = es_read_fbf (stream, + buffer + data_read_unread, + bytes_to_read - data_read_unread, &data_read); + break; + } + + out: + + if (bytes_read) + *bytes_read = data_read_unread + data_read; + + return err; +} + +/* Try to unread DATA_N bytes from DATA into STREAM, storing the + amount of bytes succesfully unread in *BYTES_UNREAD. */ +static void +es_unreadn (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT data, size_t data_n, + size_t *ES__RESTRICT bytes_unread) +{ + size_t space_left; + + space_left = stream->unread_buffer_size - stream->unread_data_len; + + if (data_n > space_left) + data_n = space_left; + + if (! data_n) + goto out; + + memcpy (stream->unread_buffer + stream->unread_data_len, data, data_n); + stream->unread_data_len += data_n; + stream->intern->indicators.eof = 0; + + out: + + if (bytes_unread) + *bytes_unread = data_n; +} + +/* Seek in STREAM. */ +static int +es_seek (estream_t ES__RESTRICT stream, off_t offset, int whence, + off_t *ES__RESTRICT offset_new) +{ + es_cookie_seek_function_t func_seek = stream->intern->func_seek; + int err, ret; + off_t off; + + if (! func_seek) + { + errno = EOPNOTSUPP; + err = -1; + goto out; + } + + if (stream->flags & ES_FLAG_WRITING) + { + /* Flush data first in order to prevent flushing it to the wrong + offset. */ + err = es_flush (stream); + if (err) + goto out; + stream->flags &= ~ES_FLAG_WRITING; + } + + off = offset; + if (whence == SEEK_CUR) + { + off = off - stream->data_len + stream->data_offset; + off -= stream->unread_data_len; + } + + ret = (*func_seek) (stream->intern->cookie, &off, whence); + if (ret == -1) + { + err = -1; + goto out; + } + + err = 0; + es_empty (stream); + + if (offset_new) + *offset_new = off; + + stream->intern->indicators.eof = 0; + stream->intern->offset = off; + + out: + + if (err) + stream->intern->indicators.err = 1; + + return err; +} + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + unbuffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_nbf (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + es_cookie_write_function_t func_write = stream->intern->func_write; + size_t data_written; + ssize_t ret; + int err; + + if (bytes_to_write && (! func_write)) + { + err = EOPNOTSUPP; + goto out; + } + + data_written = 0; + err = 0; + + while (bytes_to_write - data_written) + { + ret = (*func_write) (stream->intern->cookie, + buffer + data_written, + bytes_to_write - data_written); + if (ret == -1) + { + err = -1; + break; + } + else + data_written += ret; + } + + stream->intern->offset += data_written; + *bytes_written = data_written; + + out: + + return err; +} + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + fully-buffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_fbf (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + size_t space_available; + size_t data_to_write; + size_t data_written; + int err; + + data_written = 0; + err = 0; + + while ((bytes_to_write - data_written) && (! err)) + { + if (stream->data_offset == stream->buffer_size) + /* Container full, flush buffer. */ + err = es_flush (stream); + + if (! err) + { + /* Flushing resulted in empty container. */ + + data_to_write = bytes_to_write - data_written; + space_available = stream->buffer_size - stream->data_offset; + if (data_to_write > space_available) + data_to_write = space_available; + + memcpy (stream->buffer + stream->data_offset, + buffer + data_written, data_to_write); + stream->data_offset += data_to_write; + data_written += data_to_write; + } + } + + *bytes_written = data_written; + + return err; +} + + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in + line-buffered-mode, storing the amount of bytes written in + *BYTES_WRITTEN. */ +static int +es_write_lbf (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + size_t data_flushed = 0; + size_t data_buffered = 0; + unsigned char *nlp; + int err = 0; + + nlp = memrchr (buffer, '\n', bytes_to_write); + if (nlp) + { + /* Found a newline, directly write up to (including) this + character. */ + err = es_flush (stream); + if (!err) + err = es_write_nbf (stream, buffer, nlp - buffer + 1, &data_flushed); + } + + if (!err) + { + /* Write remaining data fully buffered. */ + err = es_write_fbf (stream, buffer + data_flushed, + bytes_to_write - data_flushed, &data_buffered); + } + + *bytes_written = data_flushed + data_buffered; + return err; +} + + +/* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in, storing the + amount of bytes written in BYTES_WRITTEN. */ +static int +es_writen (estream_t ES__RESTRICT stream, + const unsigned char *ES__RESTRICT buffer, + size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) +{ + size_t data_written; + int err; + + data_written = 0; + err = 0; + + if (! (stream->flags & ES_FLAG_WRITING)) + { + /* Switching to writing mode -> discard input data and seek to + position at which reading has stopped. */ + + err = es_seek (stream, 0, SEEK_CUR, NULL); + if (err) + { + if (errno == ESPIPE) + err = 0; + else + goto out; + } + } + + switch (stream->intern->strategy) + { + case _IONBF: + err = es_write_nbf (stream, buffer, bytes_to_write, &data_written); + break; + + case _IOLBF: + err = es_write_lbf (stream, buffer, bytes_to_write, &data_written); + break; + + case _IOFBF: + err = es_write_fbf (stream, buffer, bytes_to_write, &data_written); + break; + } + + out: + + if (bytes_written) + *bytes_written = data_written; + if (data_written) + if (! (stream->flags & ES_FLAG_WRITING)) + stream->flags |= ES_FLAG_WRITING; + + return err; +} + + +static int +es_peek (estream_t ES__RESTRICT stream, unsigned char **ES__RESTRICT data, + size_t *ES__RESTRICT data_len) +{ + int err; + + if (stream->flags & ES_FLAG_WRITING) + { + /* Switching to reading mode -> flush output. */ + err = es_flush (stream); + if (err) + goto out; + stream->flags &= ~ES_FLAG_WRITING; + } + + if (stream->data_offset == stream->data_len) + { + /* Refill container. */ + err = es_fill (stream); + if (err) + goto out; + } + + if (data) + *data = stream->buffer + stream->data_offset; + if (data_len) + *data_len = stream->data_len - stream->data_offset; + err = 0; + + out: + + return err; +} + + +/* Skip SIZE bytes of input data contained in buffer. */ +static int +es_skip (estream_t stream, size_t size) +{ + int err; + + if (stream->data_offset + size > stream->data_len) + { + errno = EINVAL; + err = -1; + } + else + { + stream->data_offset += size; + err = 0; + } + + return err; +} + + +static int +es_read_line (estream_t ES__RESTRICT stream, size_t max_length, + char *ES__RESTRICT *ES__RESTRICT line, + size_t *ES__RESTRICT line_length) +{ + size_t space_left; + size_t line_size; + estream_t line_stream; + char *line_new; + void *line_stream_cookie; + char *newline; + unsigned char *data; + size_t data_len; + int err; + + line_new = NULL; + line_stream = NULL; + line_stream_cookie = NULL; + + err = es_func_mem_create (&line_stream_cookie, NULL, 0, 0, BUFFER_BLOCK_SIZE, + 1, 0, 0, NULL, 0, MEM_REALLOC, MEM_FREE, O_RDWR); + if (err) + goto out; + + err = es_create (&line_stream, line_stream_cookie, -1, + estream_functions_mem); + if (err) + goto out; + + space_left = max_length; + line_size = 0; + while (1) + { + if (max_length && (space_left == 1)) + break; + + err = es_peek (stream, &data, &data_len); + if (err || (! data_len)) + break; + + if (data_len > (space_left - 1)) + data_len = space_left - 1; + + newline = memchr (data, '\n', data_len); + if (newline) + { + data_len = (newline - (char *) data) + 1; + err = es_write (line_stream, data, data_len, NULL); + if (! err) + { + space_left -= data_len; + line_size += data_len; + es_skip (stream, data_len); + break; + } + } + else + { + err = es_write (line_stream, data, data_len, NULL); + if (! err) + { + space_left -= data_len; + line_size += data_len; + es_skip (stream, data_len); + } + } + if (err) + break; + } + if (err) + goto out; + + /* Complete line has been written to line_stream. */ + + if ((max_length > 1) && (! line_size)) + { + stream->intern->indicators.eof = 1; + goto out; + } + + err = es_seek (line_stream, 0, SEEK_SET, NULL); + if (err) + goto out; + + if (! *line) + { + line_new = MEM_ALLOC (line_size + 1); + if (! line_new) + { + err = -1; + goto out; + } + } + else + line_new = *line; + + err = es_read (line_stream, line_new, line_size, NULL); + if (err) + goto out; + + line_new[line_size] = '\0'; + + if (! *line) + *line = line_new; + if (line_length) + *line_length = line_size; + + out: + + if (line_stream) + es_destroy (line_stream); + else if (line_stream_cookie) + es_func_mem_destroy (line_stream_cookie); + + if (err) + { + if (! *line) + MEM_FREE (line_new); + stream->intern->indicators.err = 1; + } + + return err; +} + + +static int +es_print (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, va_list ap) +{ + char data[BUFFER_BLOCK_SIZE]; + size_t bytes_written; + size_t bytes_read; + FILE *tmp_stream; + int err; + + bytes_written = 0; + tmp_stream = NULL; + err = 0; + + tmp_stream = tmpfile (); + if (! tmp_stream) + { + err = errno; + goto out; + } + + err = vfprintf (tmp_stream, format, ap); + if (err < 0) + goto out; + + err = fseek (tmp_stream, 0, SEEK_SET); + if (err) + goto out; + + while (1) + { + bytes_read = fread (data, 1, sizeof (data), tmp_stream); + if (ferror (tmp_stream)) + { + err = -1; + break; + } + + err = es_writen (stream, data, bytes_read, NULL); + if (err) + break; + else + bytes_written += bytes_read; + if (feof (tmp_stream)) + break; + } + if (err) + goto out; + + out: + + if (tmp_stream) + fclose (tmp_stream); + + return err ? -1 : bytes_written; +} + + +static void +es_set_indicators (estream_t stream, int ind_err, int ind_eof) +{ + if (ind_err != -1) + stream->intern->indicators.err = ind_err ? 1 : 0; + if (ind_eof != -1) + stream->intern->indicators.eof = ind_eof ? 1 : 0; +} + + +static int +es_get_indicator (estream_t stream, int ind_err, int ind_eof) +{ + int ret = 0; + + if (ind_err) + ret = stream->intern->indicators.err; + else if (ind_eof) + ret = stream->intern->indicators.eof; + + return ret; +} + + +static int +es_set_buffering (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buffer, int mode, size_t size) +{ + int err; + + /* Flush or empty buffer depending on mode. */ + if (stream->flags & ES_FLAG_WRITING) + { + err = es_flush (stream); + if (err) + goto out; + } + else + es_empty (stream); + + es_set_indicators (stream, -1, 0); + + /* Free old buffer in case that was allocated by this function. */ + if (stream->intern->deallocate_buffer) + { + stream->intern->deallocate_buffer = 0; + MEM_FREE (stream->buffer); + stream->buffer = NULL; + } + + if (mode == _IONBF) + stream->buffer_size = 0; + else + { + void *buffer_new; + + if (buffer) + buffer_new = buffer; + else + { + buffer_new = MEM_ALLOC (size); + if (! buffer_new) + { + err = -1; + goto out; + } + } + + stream->buffer = buffer_new; + stream->buffer_size = size; + if (! buffer) + stream->intern->deallocate_buffer = 1; + } + stream->intern->strategy = mode; + err = 0; + + out: + + return err; +} + + +static off_t +es_offset_calculate (estream_t stream) +{ + off_t offset; + + offset = stream->intern->offset + stream->data_offset; + if (offset < stream->unread_data_len) + /* Offset undefined. */ + offset = 0; + else + offset -= stream->unread_data_len; + + return offset; +} + + +static void +es_opaque_ctrl (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque_new, + void **ES__RESTRICT opaque_old) +{ + if (opaque_old) + *opaque_old = stream->intern->opaque; + if (opaque_new) + stream->intern->opaque = opaque_new; +} + + +static int +es_get_fd (estream_t stream) +{ + return stream->intern->fd; +} + + + +/* API. */ + +int +es_init (void) +{ + int err; + + err = es_init_do (); + + return err; +} + +estream_t +es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + int fd; + + stream = NULL; + cookie = NULL; + create_called = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_func_file_create (&cookie, &fd, path, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, fd, estream_functions_file); + if (err) + goto out; + + out: + + if (err && create_called) + (*estream_functions_file.func_close) (cookie); + + return stream; +} + + +estream_t +es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len, + unsigned int grow, + func_realloc_t func_realloc, func_free_t func_free, + const char *ES__RESTRICT mode) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + + cookie = 0; + stream = NULL; + create_called = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_func_mem_create (&cookie, data, data_n, data_len, + BUFFER_BLOCK_SIZE, grow, 0, 0, + NULL, 0, func_realloc, func_free, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, -1, estream_functions_mem); + + out: + + if (err && create_called) + (*estream_functions_mem.func_close) (cookie); + + return stream; +} + + +estream_t +es_open_memstream (char **ptr, size_t *size) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + + flags = O_RDWR; + create_called = 0; + stream = NULL; + cookie = 0; + + err = es_func_mem_create (&cookie, NULL, 0, 0, + BUFFER_BLOCK_SIZE, 1, 1, 1, + ptr, size, MEM_REALLOC, MEM_FREE, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, -1, estream_functions_mem); + + out: + + if (err && create_called) + (*estream_functions_mem.func_close) (cookie); + + return stream; +} + + +estream_t +es_fopencookie (void *ES__RESTRICT cookie, + const char *ES__RESTRICT mode, + es_cookie_io_functions_t functions) +{ + unsigned int flags; + estream_t stream; + int err; + + stream = NULL; + flags = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_create (&stream, cookie, -1, functions); + if (err) + goto out; + + out: + + return stream; +} + + +estream_t +es_fdopen (int filedes, const char *mode) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + + stream = NULL; + cookie = NULL; + create_called = 0; + + err = es_convert_mode (mode, &flags); + if (err) + goto out; + + err = es_func_fd_create (&cookie, filedes, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, filedes, estream_functions_fd); + + out: + + if (err && create_called) + (*estream_functions_fd.func_close) (cookie); + + return stream; +} + + +estream_t +es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode, + estream_t ES__RESTRICT stream) +{ + int err; + + if (path) + { + unsigned int flags; + int create_called; + void *cookie; + int fd; + + cookie = NULL; + create_called = 0; + + ESTREAM_LOCK (stream); + + es_deinitialize (stream); + + err = es_convert_mode (mode, &flags); + if (err) + goto leave; + + err = es_func_file_create (&cookie, &fd, path, flags); + if (err) + goto leave; + + create_called = 1; + es_initialize (stream, cookie, fd, estream_functions_file); + + leave: + + if (err) + { + if (create_called) + es_func_fd_destroy (cookie); + + es_destroy (stream); + stream = NULL; + } + else + ESTREAM_UNLOCK (stream); + } + else + { + /* FIXME? We don't support re-opening at the moment. */ + errno = EINVAL; + es_deinitialize (stream); + es_destroy (stream); + stream = NULL; + } + + return stream; +} + + +int +es_fclose (estream_t stream) +{ + int err; + + err = es_destroy (stream); + + return err; +} + +int +es_fileno_unlocked (estream_t stream) +{ + return es_get_fd (stream); +} + + +void +es_flockfile (estream_t stream) +{ + ESTREAM_LOCK (stream); +} + + +int +es_ftrylockfile (estream_t stream) +{ + return ESTREAM_TRYLOCK (stream); +} + + +void +es_funlockfile (estream_t stream) +{ + ESTREAM_UNLOCK (stream); +} + + +int +es_fileno (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_fileno_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_feof_unlocked (estream_t stream) +{ + return es_get_indicator (stream, 0, 1); +} + + +int +es_feof (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_feof_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_ferror_unlocked (estream_t stream) +{ + return es_get_indicator (stream, 1, 0); +} + + +int +es_ferror (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_ferror_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +void +es_clearerr_unlocked (estream_t stream) +{ + es_set_indicators (stream, 0, 0); +} + + +void +es_clearerr (estream_t stream) +{ + ESTREAM_LOCK (stream); + es_clearerr_unlocked (stream); + ESTREAM_UNLOCK (stream); +} + + +int +es_fflush (estream_t stream) +{ + int err; + + if (stream) + { + ESTREAM_LOCK (stream); + if (stream->flags & ES_FLAG_WRITING) + err = es_flush (stream); + else + { + es_empty (stream); + err = 0; + } + ESTREAM_UNLOCK (stream); + } + else + err = es_list_iterate (es_fflush); + + return err ? EOF : 0; +} + + +int +es_fseek (estream_t stream, long int offset, int whence) +{ + int err; + + ESTREAM_LOCK (stream); + err = es_seek (stream, offset, whence, NULL); + ESTREAM_UNLOCK (stream); + + return err; +} + + +int +es_fseeko (estream_t stream, off_t offset, int whence) +{ + int err; + + ESTREAM_LOCK (stream); + err = es_seek (stream, offset, whence, NULL); + ESTREAM_UNLOCK (stream); + + return err; +} + + +long int +es_ftell (estream_t stream) +{ + long int ret; + + ESTREAM_LOCK (stream); + ret = es_offset_calculate (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +off_t +es_ftello (estream_t stream) +{ + off_t ret = -1; + + ESTREAM_LOCK (stream); + ret = es_offset_calculate (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +void +es_rewind (estream_t stream) +{ + ESTREAM_LOCK (stream); + es_seek (stream, 0L, SEEK_SET, NULL); + es_set_indicators (stream, 0, -1); + ESTREAM_UNLOCK (stream); +} + + +int +_es_getc_underflow (estream_t stream) +{ + int err; + unsigned char c; + size_t bytes_read; + + err = es_readn (stream, &c, 1, &bytes_read); + + return (err || (! bytes_read)) ? EOF : c; +} + + +int +_es_putc_overflow (int c, estream_t stream) +{ + unsigned char d = c; + int err; + + err = es_writen (stream, &d, 1, NULL); + + return err ? EOF : c; +} + + +int +es_fgetc (estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_getc_unlocked (stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_fputc (int c, estream_t stream) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_putc_unlocked (c, stream); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_ungetc (int c, estream_t stream) +{ + unsigned char data = (unsigned char) c; + size_t data_unread; + + ESTREAM_LOCK (stream); + es_unreadn (stream, &data, 1, &data_unread); + ESTREAM_UNLOCK (stream); + + return data_unread ? c : EOF; +} + + +int +es_read (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buffer, size_t bytes_to_read, + size_t *ES__RESTRICT bytes_read) +{ + int err; + + if (bytes_to_read) + { + ESTREAM_LOCK (stream); + err = es_readn (stream, buffer, bytes_to_read, bytes_read); + ESTREAM_UNLOCK (stream); + } + else + err = 0; + + return err; +} + + +int +es_write (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT buffer, size_t bytes_to_write, + size_t *ES__RESTRICT bytes_written) +{ + int err; + + if (bytes_to_write) + { + ESTREAM_LOCK (stream); + err = es_writen (stream, buffer, bytes_to_write, bytes_written); + ESTREAM_UNLOCK (stream); + } + else + err = 0; + + return err; +} + + +size_t +es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems, + estream_t ES__RESTRICT stream) +{ + size_t ret, bytes; + int err; + + if (size * nitems) + { + ESTREAM_LOCK (stream); + err = es_readn (stream, ptr, size * nitems, &bytes); + ESTREAM_UNLOCK (stream); + + ret = bytes / size; + } + else + ret = 0; + + return ret; +} + + +size_t +es_fwrite (const void *ES__RESTRICT ptr, size_t size, size_t nitems, + estream_t ES__RESTRICT stream) +{ + size_t ret, bytes; + int err; + + if (size * nitems) + { + ESTREAM_LOCK (stream); + err = es_writen (stream, ptr, size * nitems, &bytes); + ESTREAM_UNLOCK (stream); + + ret = bytes / size; + } + else + ret = 0; + + return ret; +} + + +char * +es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream) +{ + char *ret = NULL; + + if (n) + { + int err; + + ESTREAM_LOCK (stream); + err = es_read_line (stream, n, &s, NULL); + ESTREAM_UNLOCK (stream); + if (! err) + ret = s; + } + + return ret; +} + + +int +es_fputs (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream) +{ + size_t length; + int err; + + length = strlen (s); + ESTREAM_LOCK (stream); + err = es_writen (stream, s, length, NULL); + ESTREAM_UNLOCK (stream); + + return err ? EOF : 0; +} + + +ssize_t +es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, size_t *ES__RESTRICT n, + estream_t ES__RESTRICT stream) +{ + char *line = NULL; + size_t line_n = 0; + int err; + + ESTREAM_LOCK (stream); + err = es_read_line (stream, 0, &line, &line_n); + ESTREAM_UNLOCK (stream); + if (err) + goto out; + + if (*n) + { + /* Caller wants us to use his buffer. */ + + if (*n < (line_n + 1)) + { + /* Provided buffer is too small -> resize. */ + + void *p; + + p = MEM_REALLOC (*lineptr, line_n + 1); + if (! p) + err = -1; + else + { + if (*lineptr != p) + *lineptr = p; + } + } + + if (! err) + { + memcpy (*lineptr, line, line_n + 1); + if (*n != line_n) + *n = line_n; + } + MEM_FREE (line); + } + else + { + /* Caller wants new buffers. */ + *lineptr = line; + *n = line_n; + } + + out: + + return err ? err : line_n; +} + + +int +es_vfprintf (estream_t ES__RESTRICT stream, const char *ES__RESTRICT format, + va_list ap) +{ + int ret; + + ESTREAM_LOCK (stream); + ret = es_print (stream, format, ap); + ESTREAM_UNLOCK (stream); + + return ret; +} + + +int +es_fprintf (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, ...) +{ + int ret; + + va_list ap; + va_start (ap, format); + ESTREAM_LOCK (stream); + ret = es_print (stream, format, ap); + ESTREAM_UNLOCK (stream); + va_end (ap); + + return ret; +} + +static int +tmpfd (void) +{ + FILE *fp; + int fp_fd; + int fd; + + fp = NULL; + fd = -1; + + fp = tmpfile (); + if (! fp) + goto out; + + fp_fd = fileno (fp); + fd = dup (fp_fd); + + out: + + if (fp) + fclose (fp); + + return fd; +} + +estream_t +es_tmpfile (void) +{ + unsigned int flags; + int create_called; + estream_t stream; + void *cookie; + int err; + int fd; + + create_called = 0; + stream = NULL; + flags = O_RDWR | O_TRUNC | O_CREAT; + cookie = NULL; + + fd = tmpfd (); + if (fd == -1) + { + err = -1; + goto out; + } + + err = es_func_fd_create (&cookie, fd, flags); + if (err) + goto out; + + create_called = 1; + err = es_create (&stream, cookie, fd, estream_functions_fd); + + out: + + if (err) + { + if (create_called) + es_func_fd_destroy (cookie); + else if (fd != -1) + close (fd); + stream = NULL; + } + + return stream; +} + + +int +es_setvbuf (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buf, int type, size_t size) +{ + int err; + + if (((type == _IOFBF) || (type == _IOLBF) || (type == _IONBF)) + && (! ((! size) && (type != _IONBF)))) + { + ESTREAM_LOCK (stream); + err = es_set_buffering (stream, buf, type, size); + ESTREAM_UNLOCK (stream); + } + else + { + errno = EINVAL; + err = -1; + } + + return err; +} + + +void +es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf) +{ + ESTREAM_LOCK (stream); + es_set_buffering (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ); + ESTREAM_UNLOCK (stream); +} + +void +es_opaque_set (estream_t stream, void *opaque) +{ + ESTREAM_LOCK (stream); + es_opaque_ctrl (stream, opaque, NULL); + ESTREAM_UNLOCK (stream); +} + + +void * +es_opaque_get (estream_t stream) +{ + void *opaque; + + ESTREAM_LOCK (stream); + es_opaque_ctrl (stream, NULL, &opaque); + ESTREAM_UNLOCK (stream); + + return opaque; +} diff --git a/common/estream.h b/common/estream.h new file mode 100644 index 000000000..382b6da84 --- /dev/null +++ b/common/estream.h @@ -0,0 +1,201 @@ +/* estream.h - Extended stream I/O/ Library + Copyright (C) 2004 g10 Code GmbH + + This file is part of Libestream. + + Libestream 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. + + Libestream 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Libestream; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef ESTREAM_H +#define ESTREAM_H + +#include <sys/types.h> +#include <stdarg.h> +#include <stdio.h> + + +/* Forward declaration for the (opaque) internal type. */ +struct estream_internal; + +/* The definition of this struct is entirely private. You must not + use it for anything. It is only here so some functions can be + implemented as macros. */ +struct es__stream +{ + /* The layout of this struct must never change. It may be grown, + but only if all functions which access the new members are + versioned. */ + + /* A pointer to the stream buffer. */ + unsigned char *buffer; + + /* The size of the buffer in bytes. */ + size_t buffer_size; + + /* The length of the usable data in the buffer, only valid when in + read mode (see flags). */ + size_t data_len; + + /* The current position of the offset pointer, valid in read and + write mode. */ + size_t data_offset; + + size_t data_flushed; + unsigned char *unread_buffer; + size_t unread_buffer_size; + + /* The number of unread bytes. */ + size_t unread_data_len; + + /* Various flags. */ +#define ES__FLAG_WRITING (1 << 0) + unsigned int flags; + + /* A pointer to our internal data for this stream. */ + struct estream_internal *intern; +}; + +/* The opaque type for an estream. */ +typedef struct es__stream *estream_t; + + +typedef ssize_t (*es_cookie_read_function_t) (void *cookie, + char *buffer, size_t size); +typedef ssize_t (*es_cookie_write_function_t) (void *cookie, + const char *buffer, + size_t size); +typedef int (*es_cookie_seek_function_t) (void *cookie, + off_t *pos, int whence); +typedef int (*es_cookie_close_function_t) (void *cookie); + +typedef struct es_cookie_io_functions +{ + es_cookie_read_function_t func_read; + es_cookie_write_function_t func_write; + es_cookie_seek_function_t func_seek; + es_cookie_close_function_t func_close; +} es_cookie_io_functions_t; + + +#ifndef ES__RESTRICT +# if defined __GNUC__ && defined __GNUC_MINOR__ +# if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 92)) +# define ES__RESTRICT __restrict__ +# endif +# endif +#endif +#ifndef ES__RESTRICT +# define ES__RESTRICT +#endif + +int es_init (void); + +estream_t es_fopen (const char *ES__RESTRICT path, + const char *ES__RESTRICT mode); +estream_t es_mopen (unsigned char *ES__RESTRICT data, + size_t data_n, size_t data_len, + unsigned int grow, + void *(*func_realloc) (void *mem, size_t size), + void (*func_free) (void *mem), + const char *ES__RESTRICT mode); +estream_t es_open_memstream (char **ptr, size_t *size); +estream_t es_fdopen (int filedes, const char *mode); +estream_t es_freopen (const char *ES__RESTRICT path, + const char *ES__RESTRICT mode, + estream_t ES__RESTRICT stream); +estream_t es_fopencookie (void *ES__RESTRICT cookie, + const char *ES__RESTRICT mode, + es_cookie_io_functions_t functions); +int es_fclose (estream_t stream); +int es_fileno (estream_t stream); +int es_fileno_unlocked (estream_t stream); + +void es_flockfile (estream_t stream); +int es_ftrylockfile (estream_t stream); +void es_funlockfile (estream_t stream); + +int es_feof (estream_t stream); +int es_feof_unlocked (estream_t stream); +int es_ferror (estream_t stream); +int es_ferror_unlocked (estream_t stream); +void es_clearerr (estream_t stream); +void es_clearerr_unlocked (estream_t stream); + +int es_fflush (estream_t stream); +int es_fseek (estream_t stream, long int offset, int whence); +int es_fseeko (estream_t stream, off_t offset, int whence); +long int es_ftell (estream_t stream); +off_t es_ftello (estream_t stream); +void es_rewind (estream_t stream); + +int es_fgetc (estream_t stream); +int es_fputc (int c, estream_t stream); + +int _es_getc_underflow (estream_t stream); +int _es_putc_overflow (int c, estream_t stream); + +#define es_getc_unlocked(stream) \ + (((! ((stream)->flags & 1)) \ + && ((stream)->data_offset < (stream)->data_len) \ + && (! (stream)->unread_data_len)) \ + ? ((int) (stream)->buffer[((stream)->data_offset)++]) \ + : _es_getc_underflow ((stream))) + +#define es_putc_unlocked(c, stream) \ + ((((stream)->flags & 1) \ + && ((stream)->data_offset < (stream)->buffer_size) \ + && (c != '\n')) \ + ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c))) \ + : _es_putc_overflow ((c), (stream))) + +#define es_getc(stream) es_fgetc (stream) +#define es_putc(c, stream) es_fputc (c, stream) + +int es_ungetc (int c, estream_t stream); + +int es_read (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buffer, size_t bytes_to_read, + size_t *ES__RESTRICT bytes_read); +int es_write (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT buffer, size_t bytes_to_write, + size_t *ES__RESTRICT bytes_written); + +size_t es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems, + estream_t ES__RESTRICT stream); +size_t es_fwrite (const void *ES__RESTRICT ptr, size_t size, size_t memb, + estream_t ES__RESTRICT stream); + +char *es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream); +int es_fputs (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream); + +ssize_t es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr, + size_t *ES__RESTRICT n, + estream_t stream); + +int es_fprintf (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, ...); +int es_vfprintf (estream_t ES__RESTRICT stream, + const char *ES__RESTRICT format, va_list ap); + +int es_setvbuf (estream_t ES__RESTRICT stream, + char *ES__RESTRICT buf, int mode, size_t size); +void es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf); + +estream_t es_tmpfile (void); + +void es_opaque_set (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque); +void *es_opaque_get (estream_t stream); + +#endif -- cgit v1.2.3 From e776d52ba5d24a22f0148e9dbd162055be6aa521 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 26 Jan 2005 22:25:36 +0000 Subject: added missing file --- agent/command-ssh.c | 2327 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2327 insertions(+) create mode 100644 agent/command-ssh.c diff --git a/agent/command-ssh.c b/agent/command-ssh.c new file mode 100644 index 000000000..a76bbfff7 --- /dev/null +++ b/agent/command-ssh.c @@ -0,0 +1,2327 @@ +/* command-ssh.c - gpg-agent's ssh-agent emulation layer + * Copyright (C) 2004, 2005 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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <stdio.h> + +#include "agent.h" + +#include <gcrypt.h> + +#include "estream.h" + + + +/* Request types. */ +#define SSH_REQUEST_REQUEST_IDENTITIES 11 +#define SSH_REQUEST_SIGN_REQUEST 13 +#define SSH_REQUEST_ADD_IDENTITY 17 +#define SSH_REQUEST_REMOVE_IDENTITY 18 +#define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19 +#define SSH_REQUEST_LOCK 22 +#define SSH_REQUEST_UNLOCK 23 +#define SSH_REQUEST_ADD_ID_CONSTRAINED 25 + +/* Options. */ +#define SSH_OPT_CONSTRAIN_LIFETIME 1 +#define SSH_OPT_CONSTRAIN_CONFIRM 2 + +/* Response types. */ +#define SSH_RESPONSE_SUCCESS 6 +#define SSH_RESPONSE_FAILURE 5 +#define SSH_RESPONSE_IDENTITIES_ANSWER 12 +#define SSH_RESPONSE_SIGN_RESPONSE 14 + + + + +/* Basic types. */ + +/* A "byte". */ +typedef unsigned char byte_t; + +typedef int (*ssh_request_handler_t) (ctrl_t ctrl, + estream_t request, estream_t response); + +typedef struct ssh_request_spec +{ + byte_t type; + ssh_request_handler_t handler; +} ssh_request_spec_t; + +typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis); +typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob, + gcry_mpi_t *mpis); + +typedef struct ssh_key_type_spec +{ + const char *ssh_identifier; + const char *identifier; + const char *elems_key_secret; + const char *elems_key_public; + const char *elems_secret; + const char *elems_signature; + const char *elems_sexp_order; + ssh_key_modifier_t key_modifier; + ssh_signature_encoder_t signature_encoder; + unsigned int flags; +} ssh_key_type_spec_t; + + + +static uint32_t lifetime_default; + +/* General utility functions. */ + +static void * +realloc_secure (void *a, size_t n) +{ + void *p; + + if (a) + p = gcry_realloc (a, n); + else + p = gcry_malloc_secure (n); + + return p; +} + +/* Primitive I/O functions. */ + +static gpg_error_t +es_read_byte (estream_t stream, byte_t *b) +{ + gpg_error_t err; + int ret; + + ret = es_fgetc (stream); + if (ret == EOF) + { + if (es_ferror (stream)) + err = gpg_error_from_errno (errno); + else + err = gpg_error (GPG_ERR_EOF); + } + else + { + *b = ret & 0xFF; + err = 0; + } + + return err; +} + +static gpg_error_t +es_write_byte (estream_t stream, byte_t b) +{ + gpg_error_t err; + int ret; + + ret = es_fputc (b, stream); + if (ret == EOF) + err = gpg_error_from_errno (errno); + else + err = 0; + + return err; +} + +static gpg_error_t +es_read_uint32 (estream_t stream, uint32_t *uint32) +{ + unsigned char buffer[4]; + size_t bytes_read; + gpg_error_t err; + int ret; + + ret = es_read (stream, buffer, sizeof (buffer), &bytes_read); + if (ret) + err = gpg_error_from_errno (errno); + else + { + if (bytes_read != sizeof (buffer)) + err = gpg_error (GPG_ERR_EOF); + else + { + uint32_t n; + + n = (0 + | ((uint32_t) (buffer[0] << 24)) + | ((uint32_t) (buffer[1] << 16)) + | ((uint32_t) (buffer[2] << 8)) + | ((uint32_t) (buffer[3] << 0))); + *uint32 = n; + err = 0; + } + } + + return err; +} + +static gpg_error_t +es_write_uint32 (estream_t stream, uint32_t uint32) +{ + unsigned char buffer[4]; + gpg_error_t err; + int ret; + + buffer[0] = (uint32 >> 24) & 0xFF; + buffer[1] = (uint32 >> 16) & 0xFF; + buffer[2] = (uint32 >> 8) & 0xFF; + buffer[3] = (uint32 >> 0) & 0xFF; + + ret = es_write (stream, buffer, sizeof (buffer), NULL); + if (ret) + err = gpg_error_from_errno (errno); + else + err = 0; + + return err; +} + +static gpg_error_t +es_read_data (estream_t stream, unsigned char *buffer, size_t size) +{ + gpg_error_t err; + size_t bytes_read; + int ret; + + ret = es_read (stream, buffer, size, &bytes_read); + if (ret) + err = gpg_error_from_errno (errno); + else + { + if (bytes_read != size) + err = gpg_error (GPG_ERR_EOF); + else + err = 0; + } + + return err; +} + +static gpg_error_t +es_write_data (estream_t stream, const unsigned char *buffer, size_t size) +{ + gpg_error_t err; + int ret; + + ret = es_write (stream, buffer, size, NULL); + if (ret) + err = gpg_error_from_errno (errno); + else + err = 0; + + return err; +} + +static gpg_error_t +es_read_string (estream_t stream, unsigned int secure, + unsigned char **string, uint32_t *string_size) +{ + gpg_error_t err; + unsigned char *buffer; + uint32_t length; + + buffer = NULL; + + /* Read string length. */ + err = es_read_uint32 (stream, &length); + if (err) + goto out; + + /* Allocate space. */ + if (secure) + buffer = xtrymalloc_secure (length + 1); + else + buffer = xtrymalloc (length + 1); + if (! buffer) + { + /* FIXME: xtrymalloc_secure does not set errno, does it? */ + err = gpg_error_from_errno (errno); + abort (); + goto out; + } + + /* Read data. */ + err = es_read_data (stream, buffer, length); + if (err) + goto out; + + /* Finalize string object. */ + buffer[length] = 0; + *string = buffer; + if (string_size) + *string_size = length; + + out: + + if (err) + xfree (buffer); + + return err; +} + +static gpg_error_t +es_read_cstring (estream_t stream, char **string) +{ + unsigned char *buffer; + gpg_error_t err; + + err = es_read_string (stream, 0, &buffer, NULL); + if (err) + goto out; + + *string = (char *) buffer; + + out: + + return err; +} + +static gpg_error_t +es_write_string (estream_t stream, + const unsigned char *string, uint32_t string_n) +{ + gpg_error_t err; + + err = es_write_uint32 (stream, string_n); + if (err) + goto out; + + err = es_write_data (stream, string, string_n); + + out: + + return err; +} + +static gpg_error_t +es_write_cstring (estream_t stream, const char *string) +{ + gpg_error_t err; + + err = es_write_string (stream, + (const unsigned char *) string, strlen (string)); + + return err; +} + +static gpg_error_t +es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) +{ + unsigned char *mpi_data; + uint32_t mpi_data_size; + gpg_error_t err; + gcry_mpi_t mpi; + + mpi_data = NULL; + + err = es_read_string (stream, secure, &mpi_data, &mpi_data_size); + if (err) + goto out; + + err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL); + if (err) + goto out; + + *mpint = mpi; + + out: + + xfree (mpi_data); + + return err; +} + +static gpg_error_t +es_write_mpi (estream_t stream, gcry_mpi_t mpint) +{ + unsigned char *mpi_buffer; + size_t mpi_buffer_n; + gpg_error_t err; + + mpi_buffer = NULL; + + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint); + if (err) + goto out; + + err = es_write_string (stream, mpi_buffer, mpi_buffer_n); + + out: + + xfree (mpi_buffer); + + return err; +} + +static gpg_error_t +es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) +{ + unsigned char *buffer_new; + struct stat statbuf; + estream_t stream; + gpg_error_t err; + int ret; + + buffer_new = NULL; + err = 0; + + stream = es_fopen (filename, "r"); + if (! stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + ret = fstat (es_fileno (stream), &statbuf); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + buffer_new = xtrymalloc (statbuf.st_size); + if (! buffer_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_data (stream, buffer_new, statbuf.st_size); + if (err) + goto out; + + *buffer = buffer_new; + *buffer_n = statbuf.st_size; + + out: + + if (stream) + es_fclose (stream); + + if (err) + xfree (buffer_new); + + return err; +} + +static gpg_error_t +es_copy (estream_t dst, estream_t src) +{ + char buffer[BUFSIZ]; + size_t bytes_read; + gpg_error_t err; + int ret; + + err = 0; + while (1) + { + ret = es_read (src, buffer, sizeof (buffer), &bytes_read); + if (ret || (! bytes_read)) + { + if (ret) + err = gpg_error_from_errno (errno); + break; + } + ret = es_write (dst, buffer, bytes_read, NULL); + if (ret) + { + err = gpg_error_from_errno (errno); + break; + } + } + + return err; +} + + + +/* MPI lists. */ + +static void +mpint_list_free (gcry_mpi_t *mpi_list) +{ + if (mpi_list) + { + unsigned int i; + + for (i = 0; mpi_list[i]; i++) + gcry_mpi_release (mpi_list[i]); + xfree (mpi_list); + } +} + +static gpg_error_t +ssh_receive_mpint_list (estream_t stream, int secret, + ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list) +{ + const char *elems_secret; + const char *elems; + unsigned int elems_n; + gcry_mpi_t *mpis; + unsigned int i; + gpg_error_t err; + int elem_is_secret; + + mpis = NULL; + err = 0; + + if (secret) + { + elems = key_spec.elems_key_secret; + elems_secret = key_spec.elems_secret; + } + else + { + elems = key_spec.elems_key_public; + elems_secret = ""; + } + elems_n = strlen (elems); + + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); + if (! mpis) + { + err = gpg_error_from_errno (errno); + goto out; + } + + memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); + + for (i = 0; i < elems_n; i++) + { + elem_is_secret = strchr (elems_secret, elems[i]) ? 1 : 0; + err = es_read_mpi (stream, elem_is_secret, &mpis[i]); + if (err) + break; + } + if (err) + goto out; + + *mpi_list = mpis; + + out: + + if (err) + mpint_list_free (mpis); + + return err; +} + + + +static gpg_error_t +ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis) +{ + gcry_mpi_t p; + gcry_mpi_t q; + gcry_mpi_t u; + + if (strcmp (elems, "nedupq")) + /* Modifying only necessary for secret keys. */ + goto out; + + u = mpis[3]; + p = mpis[4]; + q = mpis[5]; + + if (gcry_mpi_cmp (p, q) > 0) + { + /* P shall be smaller then Q! Swap primes. iqmp becomes u. */ + gcry_mpi_t tmp; + + tmp = mpis[4]; + mpis[4] = mpis[5]; + mpis[5] = tmp; + } + else + /* U needs to be recomputed. */ + gcry_mpi_invm (u, p, q); + + out: + + return 0; +} + +static gpg_error_t +ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) +{ + unsigned char *data; + size_t data_n; + gpg_error_t err; + gcry_mpi_t s; + + s = mpis[0]; + + err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s); + if (err) + goto out; + + err = es_write_string (signature_blob, data, data_n); + xfree (data); + + out: + + return err; +} + +#define SSH_DSA_SIGNATURE_PADDING 20 +#define SSH_DSA_SIGNATURE_ELEMS 2 + +static gpg_error_t +ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) +{ + unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS]; + unsigned char *data; + size_t data_n; + gpg_error_t err; + int i; + + data = NULL; + + for (i = 0; i < 2; i++) + { + err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]); + if (err) + break; + + if (data_n > SSH_DSA_SIGNATURE_PADDING) + { + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + break; + } + + memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0, + SSH_DSA_SIGNATURE_PADDING - data_n); + memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING) + + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n); + + xfree (data); + data = NULL; + } + if (err) + goto out; + + err = es_write_string (signature_blob, buffer, sizeof (buffer)); + + out: + + xfree (data); + + return err; +} + +#define SPEC_FLAG_USE_PKCS1V2 (1 << 0) + + +/* Table holding key type specifications. */ +static ssh_key_type_spec_t ssh_key_types[] = + { + { + "ssh-rsa", "rsa", "nedupq", "en", "dupq", "s", "nedpqu", + ssh_key_modifier_rsa, ssh_signature_encoder_rsa, + SPEC_FLAG_USE_PKCS1V2 + }, + { + "ssh-dss", "dsa", "pqgyx", "pqgy", "x", "rs", "pqgyx", + NULL, ssh_signature_encoder_dsa, + 0 + }, + }; + + + +/* S-Expressions. */ + +static gpg_error_t +ssh_sexp_construct (gcry_sexp_t *sexp, + ssh_key_type_spec_t key_spec, int secret, + gcry_mpi_t *mpis, const char *comment) +{ + gcry_sexp_t sexp_new; + char *sexp_template; + size_t sexp_template_n; + gpg_error_t err; + const char *elems; + size_t elems_n; + unsigned int i; + unsigned int j; + void **arg_list; + + err = 0; + sexp_new = NULL; + arg_list = NULL; + if (secret) + elems = key_spec.elems_sexp_order; + else + elems = key_spec.elems_key_public; + elems_n = strlen (elems); + + sexp_template_n = 33 + strlen (key_spec.identifier) + (elems_n * 6) - (! secret); + sexp_template = xtrymalloc (sexp_template_n); + if (! sexp_template) + { + err = gpg_error_from_errno (errno); + goto out; + } + + arg_list = xtrymalloc (sizeof (*arg_list) * (elems_n + 1)); + if (! arg_list) + { + err = gpg_error_from_errno (errno); + goto out; + } + + sprintf (sexp_template, "(%s-key (%s ", + secret ? "private" : "public", key_spec.identifier); + for (i = 0; i < elems_n; i++) + { + sprintf (strchr (sexp_template, 0), "(%c %%m)", elems[i]); + if (secret) + { + for (j = 0; j < elems_n; j++) + if (key_spec.elems_key_secret[j] == elems[i]) + break; + } + else + j = i; + arg_list[i] = &mpis[j]; + } + arg_list[i] = &comment; + sprintf (strchr (sexp_template, 0), ") (comment %%s))"); + + err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list); + if (err) + goto out; + + *sexp = sexp_new; + + out: + + xfree (arg_list); + xfree (sexp_template); + + return err; +} + +static gpg_error_t +ssh_sexp_extract (gcry_sexp_t sexp, + ssh_key_type_spec_t key_spec, int *secret, + gcry_mpi_t **mpis, const char **comment) +{ + gpg_error_t err; + gcry_sexp_t value_list; + gcry_sexp_t value_pair; + gcry_sexp_t comment_list; + unsigned int i; + char *comment_new; + const char *data; + size_t data_n; + int is_secret; + size_t elems_n; + const char *elems; + gcry_mpi_t *mpis_new; + gcry_mpi_t mpi; + + err = 0; + value_list = NULL; + value_pair = NULL; + comment_list = NULL; + comment_new = NULL; + mpis_new = NULL; + + data = gcry_sexp_nth_data (sexp, 0, &data_n); + if (! data) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + if ((data_n == 10) && (! strncmp (data, "public-key", 10))) + { + is_secret = 0; + elems = key_spec.elems_key_public; + } + else if (((data_n == 11) && (! strncmp (data, "private-key", 11))) + || ((data_n == 21) && (! strncmp (data, "protected-private-key", 21)))) + { + is_secret = 1; + elems = key_spec.elems_key_secret; + } + else + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + elems_n = strlen (elems); + mpis_new = xtrymalloc (sizeof (*mpis_new) * (elems_n + 1)); + if (! mpis_new) + { + err = gpg_error_from_errno (errno); /* FIXME, xtrymalloc+errno. */ + goto out; + } + memset (mpis_new, 0, sizeof (*mpis_new) * (elems_n + 1)); + + value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0); + if (! value_list) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + for (i = 0; i < elems_n; i++) + { + value_pair = gcry_sexp_find_token (value_list, elems + i, 1); + if (! value_pair) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + + mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG); + if (! mpi) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + mpis_new[i] = mpi; + gcry_sexp_release (value_pair); + value_pair = NULL; + } + if (err) + goto out; + + /* We do not require a comment sublist to be present here. */ + data = NULL; + data_n = 0; + + comment_list = gcry_sexp_find_token (sexp, "comment", 0); + if (comment_list) + data = gcry_sexp_nth_data (comment_list, 1, &data_n); + if (! data) + { + data = "(none)"; + data_n = 6; + } + + comment_new = xtrymalloc (data_n + 1); + if (! comment_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + strncpy (comment_new, data, data_n); + comment_new[data_n] = 0; + + if (secret) + *secret = is_secret; + *mpis = mpis_new; + *comment = comment_new; + + out: + + gcry_sexp_release (value_list); + gcry_sexp_release (value_pair); + gcry_sexp_release (comment_list); + + if (err) + { + xfree (comment_new); + mpint_list_free (mpis_new); + } + + return err; +} + +static gpg_error_t +ssh_sexp_extract_key_type (gcry_sexp_t sexp, const char **key_type) +{ + gcry_sexp_t sublist; + char *key_type_new; + const char *data; + size_t data_n; + gpg_error_t err; + + err = 0; + key_type_new = NULL; + + sublist = gcry_sexp_nth (sexp, 1); + if (! sublist) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + data = gcry_sexp_nth_data (sublist, 0, &data_n); + if (! data) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + key_type_new = xtrymalloc (data_n + 1); + if (! key_type_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + strncpy (key_type_new, data, data_n); + key_type_new[data_n] = 0; + *key_type = key_type_new; + + out: + + gcry_sexp_release (sublist); + + return err; +} + + + +/* Key I/O. */ + +static gpg_error_t +ssh_key_type_lookup (const char *ssh_name, const char *name, + ssh_key_type_spec_t *spec) +{ + gpg_error_t err; + unsigned int i; + + for (i = 0; i < DIM (ssh_key_types); i++) + if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier))) + || (name && (! strcmp (name, ssh_key_types[i].identifier)))) + break; + + if (i == DIM (ssh_key_types)) + err = gpg_error (GPG_ERR_NOT_FOUND); + else + { + *spec = ssh_key_types[i]; + err = 0; + } + + return err; +} + +static gpg_error_t +ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, int read_comment, + ssh_key_type_spec_t *key_spec) +{ + gpg_error_t err; + char *key_type; + char *comment; + gcry_sexp_t key; + ssh_key_type_spec_t spec; + gcry_mpi_t *mpi_list; + const char *elems; + + mpi_list = NULL; + key_type = NULL; + comment = ""; + key = NULL; + + err = es_read_cstring (stream, &key_type); + if (err) + goto out; + + err = ssh_key_type_lookup (key_type, NULL, &spec); + if (err) + goto out; + + err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list); + if (err) + goto out; + + if (read_comment) + { + err = es_read_cstring (stream, &comment); + if (err) + goto out; + } + + if (secret) + elems = spec.elems_key_secret; + else + elems = spec.elems_key_public; + + if (spec.key_modifier) + { + err = (*spec.key_modifier) (elems, mpi_list); + if (err) + goto out; + } + + err = ssh_sexp_construct (&key, spec, secret, mpi_list, comment); + if (err) + goto out; + + if (key_spec) + *key_spec = spec; + *key_new = key; + + out: + + mpint_list_free (mpi_list); + xfree (key_type); + if (read_comment) + xfree (comment); + + return err; +} + +static gpg_error_t +ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, + const char *type, gcry_mpi_t *mpis) +{ + unsigned char *blob_new; + long int blob_size_new; + estream_t stream; + gpg_error_t err; + unsigned int i; + + blob_new = NULL; + stream = NULL; + err = 0; + + stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_write_cstring (stream, type); + if (err) + goto out; + + for (i = 0; mpis[i] && (! err); i++) + err = es_write_mpi (stream, mpis[i]); + if (err) + goto out; + + blob_size_new = es_ftell (stream); + if (blob_size_new == -1) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_fseek (stream, 0, SEEK_SET); + if (err) + goto out; + + blob_new = xtrymalloc (blob_size_new); + if (! blob_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_data (stream, blob_new, blob_size_new); + if (err) + goto out; + + *blob = blob_new; + *blob_size = blob_size_new; + + out: + + if (stream) + es_fclose (stream); + if (err) + xfree (blob_new); + + return err; +} + + +static gpg_error_t +ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) +{ + ssh_key_type_spec_t spec; + gcry_mpi_t *mpi_list; + const char *key_type; + const char *comment; + unsigned char *blob; + size_t blob_n; + gpg_error_t err; + + key_type = NULL; + mpi_list = NULL; + comment = NULL; + blob = NULL; + + err = ssh_sexp_extract_key_type (key_public, &key_type); + if (err) + goto out; + + err = ssh_key_type_lookup (NULL, key_type, &spec); + if (err) + goto out; + + err = ssh_sexp_extract (key_public, spec, NULL, &mpi_list, &comment); + if (err) + goto out; + + err = ssh_convert_key_to_blob (&blob, &blob_n, spec.ssh_identifier, mpi_list); + if (err) + goto out; + + err = es_write_string (stream, blob, blob_n); + if (err) + goto out; + + err = es_write_cstring (stream, comment); + + out: + + mpint_list_free (mpi_list); + xfree ((void *) key_type); + xfree ((void *) comment); + xfree (blob); + + return err; +} + +static gpg_error_t +ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, + gcry_sexp_t *key_public, + ssh_key_type_spec_t *key_spec) +{ + estream_t blob_stream; + gpg_error_t err; + + err = 0; + + blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! blob_stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_write_data (blob_stream, blob, blob_size); + if (err) + goto out; + + err = es_fseek (blob_stream, 0, SEEK_SET); + if (err) + goto out; + + err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec); + + out: + + if (blob_stream) + es_fclose (blob_stream); + + return err; +} + + + +static gpg_error_t +key_secret_to_public (gcry_sexp_t *key_public, + ssh_key_type_spec_t spec, gcry_sexp_t key_secret) +{ + gpg_error_t err; + gcry_sexp_t value_pair; + unsigned int i; + gcry_mpi_t *mpis; + gcry_mpi_t mpi; + void **arglist; + size_t elems_n; + char *template; + size_t template_n; + const char *elems; + char *comment; + const char *data; + size_t data_n; + + err = 0; + mpis = NULL; + arglist = NULL; + comment = NULL; + template = NULL; + value_pair = NULL; + + elems = spec.elems_key_public; + elems_n = strlen (elems); + + data = NULL; + value_pair = gcry_sexp_find_token (key_secret, "comment", 0); + if (value_pair) + data = gcry_sexp_nth_data (value_pair, 1, &data_n); + if (! data) + { + data = ""; + data_n = 0; + } + + comment = xtrymalloc (data_n + 1); + if (! comment) + { + err = gpg_error_from_errno (errno); + goto out; + } + strncpy (comment, data, data_n); + comment[data_n] = 0; + + gcry_sexp_release (value_pair); + value_pair = NULL; + + template_n = 29 + strlen (spec.identifier) + (elems_n * 7) + 1; + template = xtrymalloc (template_n); + if (! template) + { + err = gpg_error_from_errno (errno); + goto out; + } + + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); + if (! mpis) + { + err = gpg_error_from_errno (errno); /* FIXME: errno. */ + goto out; + } + memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); + + arglist = xtrymalloc (sizeof (*arglist) * (elems_n + 1)); + if (! arglist) + { + err = gpg_error_from_errno (errno); + goto out; + } + + for (i = 0; i < elems_n; i++) + { + value_pair = gcry_sexp_find_token (key_secret, elems + i, 1); + if (! value_pair) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG); + if (! mpi) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + gcry_sexp_release (value_pair); + value_pair = NULL; + + mpis[i] = mpi; + arglist[i] = &mpis[i]; + mpi = NULL; + } + if (err) + goto out; + + sprintf (template, "(public-key (%s", spec.identifier); + for (i = 0; i < elems_n; i++) + sprintf (strchr (template, 0)," (%c %%m)", elems[i]); + sprintf (strchr (template, 0), ") (comment %%s))"); + arglist[i] = &comment; + + err = gcry_sexp_build_array (key_public, NULL, template, arglist); + + out: + + gcry_sexp_release (value_pair); + xfree (template); + mpint_list_free (mpis); + xfree (arglist); + xfree (comment); + + return err; +} + + + +static char * +make_cstring (const char *data, size_t data_n) +{ + char *s; + + s = xtrymalloc (data_n + 1); + if (s) + { + strncpy (s, data, data_n); + s[data_n] = 0; + } + + return s; +} + + + +/* Request handler. */ + +static int +ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) +{ + const char *key_type; + ssh_key_type_spec_t spec; + struct dirent *dir_entry; + char *key_directory; + size_t key_directory_n; + char *key_path; + unsigned char *buffer; + size_t buffer_n; + uint32_t key_counter; + estream_t key_blobs; + gcry_sexp_t key_secret; + gcry_sexp_t key_public; + DIR *dir; + gpg_error_t err; + int ret; + int bad; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] request identities\n"); + + /* Prepare buffer stream. */ + + key_directory = NULL; + key_secret = NULL; + key_public = NULL; + key_type = NULL; + key_path = NULL; + key_counter = 0; + buffer = NULL; + dir = NULL; + bad = 0; + err = 0; + + key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! key_blobs) + { + err = gpg_error_from_errno (errno); + goto out; + } + + /* Open key directory. */ + key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL); + if (! key_directory) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + key_directory_n = strlen (key_directory); + + key_path = xtrymalloc (key_directory_n + 46); + if (! key_path) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + + sprintf (key_path, "%s/", key_directory); + sprintf (key_path + key_directory_n + 41, ".key"); + + dir = opendir (key_directory); + if (! dir) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + + /* Iterate over key files. */ + + /* FIXME: make sure that buffer gets deallocated properly. */ + + while (1) + { + dir_entry = readdir (dir); + if (dir_entry) + { + if ((strlen (dir_entry->d_name) == 44) + && (! strncmp (dir_entry->d_name + 40, ".key", 4))) + { + strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); + + /* Read file content. */ + err = es_read_file (key_path, &buffer, &buffer_n); + if (err) + break; + + err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n); + if (err) + break; + + xfree (buffer); + buffer = NULL; + + err = ssh_sexp_extract_key_type (key_secret, &key_type); + if (err) + break; + + err = ssh_key_type_lookup (NULL, key_type, &spec); + if (err) + break; + + xfree ((void *) key_type); + key_type = NULL; + + err = key_secret_to_public (&key_public, spec, key_secret); + if (err) + break; + + gcry_sexp_release (key_secret); + key_secret = NULL; + + err = ssh_send_key_public (key_blobs, key_public); + if (err) + break; + + gcry_sexp_release (key_public); + key_public = NULL; + + key_counter++; + } + } + else + break; + } + if (err) + goto out; + + ret = es_fseek (key_blobs, 0, SEEK_SET); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + out: + + /* Send response. */ + + gcry_sexp_release (key_secret); + gcry_sexp_release (key_public); + + es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); + if (! es_ferror (response)) + es_write_uint32 (response, err ? 0 : key_counter); + if (! (err || es_ferror (response))) + es_copy (response, key_blobs); + + if (key_blobs) + es_fclose (key_blobs); + if (dir) + closedir (dir); + + free (key_directory); + xfree (key_path); + xfree (buffer); + xfree ((void *) key_type); /* FIXME? */ + + return bad; +} + +static gpg_error_t +data_hash (unsigned char *data, size_t data_n, + int md_algorithm, unsigned char *hash) +{ + gcry_md_hash_buffer (md_algorithm, hash, data, data_n); + + return 0; +} + +static gpg_error_t +data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder, + unsigned char **sig, size_t *sig_n) +{ + char description[] = "Please provide the passphrase for key `%c':"; + gpg_error_t err; + gcry_sexp_t signature_sexp; + estream_t stream; + gcry_sexp_t valuelist; + gcry_sexp_t sublist; + gcry_mpi_t sig_value; + unsigned char *sig_blob; + size_t sig_blob_n; + const char *identifier; + const char *identifier_raw; + size_t identifier_n; + ssh_key_type_spec_t spec; + int ret; + unsigned int i; + const char *elems; + size_t elems_n; + gcry_mpi_t *mpis; + + signature_sexp = NULL; + identifier = NULL; + valuelist = NULL; + sublist = NULL; + sig_blob = NULL; + sig_blob_n = 0; + stream = NULL; + sig_value = NULL; + mpis = NULL; + + err = agent_pksign_do (ctrl, description, &signature_sexp, 0); + if (err) + goto out; + + valuelist = gcry_sexp_nth (signature_sexp, 1); + if (! valuelist) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! stream) + { + err = gpg_error_from_errno (errno); + goto out; + } + + identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n); + if (! identifier_raw) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + identifier = make_cstring (identifier_raw, identifier_n); + if (! identifier) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = ssh_key_type_lookup (NULL, identifier, &spec); + if (err) + goto out; + + err = es_write_cstring (stream, spec.ssh_identifier); + if (err) + goto out; + + elems = spec.elems_signature; + elems_n = strlen (elems); + + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); + if (! mpis) + { + err = gpg_error_from_errno (errno); + goto out; + } + memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); + + for (i = 0; i < elems_n; i++) + { + sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1); + if (! sublist) + { + err = gpg_error (GPG_ERR_INV_SEXP); + break; + } + + sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG); + if (! sig_value) + { + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + break; + } + gcry_sexp_release (sublist); + sublist = NULL; + + mpis[i] = sig_value; + } + if (err) + goto out; + + err = (*sig_encoder) (stream, mpis); + if (err) + goto out; + + sig_blob_n = es_ftell (stream); + if (sig_blob_n == -1) + { + err = gpg_error_from_errno (errno); + goto out; + } + + sig_blob = xtrymalloc (sig_blob_n); + if (! sig_blob) + { + err = gpg_error_from_errno (errno); + goto out; + } + + ret = es_fseek (stream, 0, SEEK_SET); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_data (stream, sig_blob, sig_blob_n); + if (err) + goto out; + + *sig = (char *) sig_blob; + *sig_n = sig_blob_n; + + out: + + if (err) + xfree (sig_blob); + + if (stream) + es_fclose (stream); + gcry_sexp_release (valuelist); + gcry_sexp_release (signature_sexp); + gcry_sexp_release (sublist); + mpint_list_free (mpis); + xfree ((void *) identifier); + + return err; +} + +static int +ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) +{ + gcry_sexp_t key; + ssh_key_type_spec_t spec; + unsigned char hash[MAX_DIGEST_LEN]; + unsigned int hash_n; + unsigned char key_grip[20]; + unsigned char *key_blob; + uint32_t key_blob_size; + unsigned char *data; + unsigned char *sig; + size_t sig_n; + uint32_t data_size; + uint32_t flags; + const void *p; + gpg_error_t err; + int bad; + + key_blob = NULL; + data = NULL; + sig = NULL; + key = NULL; + bad = 0; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] sign request\n"); + + /* Receive key. */ + + err = es_read_string (request, 0, &key_blob, &key_blob_size); + if (err) + { + bad = 1; + goto out; + } + + err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec); + if (err) + { + bad = 1; + goto out; + } + + /* Receive data to sign. */ + err = es_read_string (request, 0, &data, &data_size); + if (err) + { + bad = 1; + goto out; + } + + /* FIXME? */ + err = es_read_uint32 (request, &flags); + if (err) + { + bad = 1; + goto out; + } + + /* Hash data. */ + hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1); + if (! hash_n) + { + err = gpg_error (GPG_ERR_INTERNAL); + goto out; + } + err = data_hash (data, data_size, GCRY_MD_SHA1, hash); + if (err) + goto out; + + /* Calculate key grip. */ + p = gcry_pk_get_keygrip (key, key_grip); + if (! p) + { + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + goto out; + } + + /* Sign data. */ + + ctrl->digest.algo = GCRY_MD_SHA1; + memcpy (ctrl->digest.value, hash, hash_n); + ctrl->digest.valuelen = hash_n; + ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2); + ctrl->have_keygrip = 1; + memcpy (ctrl->keygrip, key_grip, 20); + + err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n); + + out: + + if (! bad) + { + /* Done. */ + es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + if (! es_ferror (response)) + { + if (! err) + es_write_string (response, sig, sig_n); + else + es_write_byte (response, SSH_RESPONSE_FAILURE); + } + } + + gcry_sexp_release (key); + xfree (key_blob); + xfree (data); + xfree (sig); + + return bad; +} + +static gpg_error_t +get_passphrase (const char *description, size_t passphrase_n, char *passphrase) +{ + struct pin_entry_info_s *pi; + gpg_error_t err; + + err = 0; + pi = gcry_calloc_secure (1, sizeof (*pi) + passphrase_n + 1); + if (! pi) + { + err = gpg_error (GPG_ERR_ENOMEM); + goto out; + } + + pi->min_digits = 0; /* We want a real passphrase. */ + pi->max_digits = 8; + pi->max_tries = 1; + pi->failed_tries = 0; + pi->check_cb = NULL; + pi->check_cb_arg = NULL; + pi->cb_errtext = NULL; + pi->max_length = 100; + + err = agent_askpin (NULL, description, NULL, pi); + if (err) + goto out; + + memcpy (passphrase, pi->pin, passphrase_n); + passphrase[passphrase_n] = 0; + + out: + + xfree (pi); + + return err; +} + +static gpg_error_t +ssh_key_extract_comment (gcry_sexp_t key, char **comment) +{ + gcry_sexp_t comment_list; + char *comment_new; + const char *data; + size_t data_n; + gpg_error_t err; + + comment_list = gcry_sexp_find_token (key, "comment", 0); + if (! comment_list) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + data = gcry_sexp_nth_data (comment_list, 1, &data_n); + if (! data) + { + err = gpg_error (GPG_ERR_INV_SEXP); + goto out; + } + + comment_new = xtrymalloc (data_n + 1); + if (! comment_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + strncpy (comment_new, data, data_n); + comment_new[data_n] = 0; + *comment = comment_new; + err = 0; + + out: + + gcry_sexp_release (comment_list); + + return err; +} + +static gpg_error_t +ssh_key_grip (gcry_sexp_t key, char *buffer) +{ + gpg_error_t err; + char *p; + + /* FIXME: unsigned vs. signed. */ + + p = gcry_pk_get_keygrip (key, buffer); + if (! p) + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + else + err = 0; + + return err; +} + +static gpg_error_t +ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, + unsigned char **buffer, size_t *buffer_n) +{ + unsigned char *buffer_new; + unsigned int buffer_new_n; + gpg_error_t err; + + err = 0; + buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0); + buffer_new = xtrymalloc (buffer_new_n); + /* FIXME: secmem? */ + if (! buffer_new) + { + err = gpg_error_from_errno (errno); + goto out; + } + + gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n); + /* FIXME: guarantee? */ + + err = agent_protect (buffer_new, passphrase, buffer, buffer_n); + + out: + + xfree (buffer_new); + + return err; +} + +static gpg_error_t +ssh_identity_register (gcry_sexp_t key, int ttl) +{ + unsigned char key_grip_raw[21]; + unsigned char *buffer; + unsigned int buffer_n; + char passphrase[100]; + size_t description_length; + char *description; + char key_grip[41]; + char *comment; + gpg_error_t err; + + int ret; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] registering identity `%s'\n", key_grip); + + description = NULL; + comment = NULL; + buffer = NULL; + + err = ssh_key_grip (key, key_grip_raw); + if (err) + goto out; + + key_grip_raw[sizeof (key_grip_raw) - 1] = 0; + ret = agent_key_available (key_grip_raw); + if (! ret) + goto out; + + err = ssh_key_extract_comment (key, &comment); + if (err) + goto out; + + description_length = 95 + (comment ? strlen (comment) : 0); + description = malloc (description_length); + if (! description) + { + err = gpg_err_code_from_errno (errno); + goto out; + } + else + sprintf (description, + "Please provide the passphrase, which should be used " + "for protecting the received secret key `%s':", + comment ? comment : ""); + + err = get_passphrase (description, sizeof (passphrase), passphrase); + if (err) + goto out; + + err = ssh_key_to_buffer (key, passphrase, &buffer, &buffer_n); + if (err) + goto out; + + err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0); + if (err) + goto out; + + err = agent_put_cache (key_grip_raw, passphrase, ttl); + if (err) + goto out; + + out: + + xfree (buffer); + xfree (comment); + xfree (description); + /* FIXME: verify xfree vs free. */ + + return err; +} + +static gpg_error_t +ssh_identity_drop (gcry_sexp_t key) +{ + unsigned char key_grip[21] = { 0 }; + gpg_error_t err; + + err = ssh_key_grip (key, key_grip); + if (err) + goto out; + + key_grip[sizeof (key_grip) - 1] = 0; + + /* FIXME: What to do here - forgetting the passphrase or deleting + the key from key cache? */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] dropping identity `%s'\n", key_grip); + + out: + + return err; +} + +static int +ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + gcry_sexp_t key; + byte_t b; + int confirm; + int death; + int bad; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] add identity\n"); + + confirm = 0; + death = 0; + key = NULL; + bad = 0; + + /* FIXME? */ + err = ssh_receive_key (request, &key, 1, 1, NULL); + if (err) + { + bad = 1; + goto out; + } + + while (1) + { + err = es_read_byte (request, &b); + if (gpg_err_code (err) == GPG_ERR_EOF) + { + err = 0; + break; + } + + switch (b) + { + case SSH_OPT_CONSTRAIN_LIFETIME: + { + uint32_t n = 0; + + err = es_read_uint32 (request, &n); + if (! err) + death = time (NULL) + n; + break; + } + + case SSH_OPT_CONSTRAIN_CONFIRM: + { + confirm = 1; + break; + } + + default: + /* FIXME: log/bad? */ + break; + } + } + if (err) + goto out; + + if (lifetime_default && (! death)) + death = time (NULL) + lifetime_default; + + /* FIXME: are constraints used correctly? */ + + err = ssh_identity_register (key, death); + + out: + + gcry_sexp_release (key); + + if (! bad) + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return bad; +} + +static int +ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response) +{ + unsigned char *key_blob; + uint32_t key_blob_size; + gcry_sexp_t key; + gpg_error_t err; + int bad; + + /* Receive key. */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] remove identity\n"); + + key_blob = NULL; + key = NULL; + bad = 0; + + err = es_read_string (request, 0, &key_blob, &key_blob_size); + if (err) + { + bad = 1; + goto out; + } + + err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL); + if (err) + { + bad = 1; + goto out; + } + + err = ssh_identity_drop (key); + + out: + + xfree (key_blob); + gcry_sexp_release (key); + + if (! bad) + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return bad; +} + +static gpg_error_t +ssh_identities_remove_all (void) +{ + gpg_error_t err; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] remove all identities\n"); + + err = 0; + + /* FIXME: shall we remove _all_ cache entries or only those + registered through the ssh emulation? */ + + return err; +} + +static int +ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + + err = ssh_identities_remove_all (); + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return 0; +} + +static gpg_error_t +ssh_lock (void) +{ + gpg_error_t err; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] lock\n"); + + err = 0; + + return err; +} + +static gpg_error_t +ssh_unlock (void) +{ + gpg_error_t err; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] unlock\n"); + + err = 0; + + return err; +} + +static int +ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + + err = ssh_lock (); + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return 0; +} + +static int +ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) +{ + gpg_error_t err; + + err = ssh_unlock (); + es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + return 0; +} + + + +/* Associating request types with the corresponding request + handlers. */ + +static ssh_request_spec_t request_specs[] = + { + { SSH_REQUEST_REQUEST_IDENTITIES, ssh_handler_request_identities }, + { SSH_REQUEST_SIGN_REQUEST, ssh_handler_sign_request }, + { SSH_REQUEST_ADD_IDENTITY, ssh_handler_add_identity }, + { SSH_REQUEST_ADD_ID_CONSTRAINED, ssh_handler_add_identity }, + { SSH_REQUEST_REMOVE_IDENTITY, ssh_handler_remove_identity }, + { SSH_REQUEST_REMOVE_ALL_IDENTITIES, ssh_handler_remove_all_identities }, + { SSH_REQUEST_LOCK, ssh_handler_lock }, + { SSH_REQUEST_UNLOCK, ssh_handler_unlock }, + }; + + + +static gpg_error_t +ssh_request_process (ctrl_t ctrl, estream_t request, estream_t response) +{ + byte_t request_type; + gpg_error_t err; + unsigned int i; + int bad; + + err = es_read_byte (request, &request_type); + if (err) + goto out; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] request: %u\n", request_type); + + for (i = 0; i < DIM (request_specs); i++) + if (request_specs[i].type == request_type) + break; + if (i == DIM (request_specs)) + { + err = es_write_byte (response, SSH_RESPONSE_FAILURE); + goto out; + } + + + bad = (*request_specs[i].handler) (ctrl, request, response); + if (bad) + err = GPG_ERR_PROTOCOL_VIOLATION; + + out: + + return err; +} + +void +start_command_handler_ssh (int sock_client) +{ + struct server_control_s ctrl; + gpg_error_t err; + estream_t stream_response; + estream_t stream_request; + estream_t stream_sock; + unsigned char *request; + uint32_t request_size; + size_t size; + int ret; + + /* Setup control structure. */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] Starting command handler\n"); + + memset (&ctrl, 0, sizeof (ctrl)); + ctrl.connection_fd = sock_client; + + stream_response = NULL; + stream_request = NULL; + stream_sock = NULL; + request = NULL; + + stream_sock = es_fdopen (sock_client, "r+"); + if (! stream_sock) + { + err = gpg_error_from_errno (errno); + goto out; + } + ret = es_setvbuf (stream_sock, NULL, _IONBF, 0); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + + while (1) + { + /* Create memory streams for request/response data. The entire + request will be stored in secure memory, since it might + contain secret key material. The response does not have to + be stored in secure memory, since we never give out secret + keys. FIXME: wrong place. */ + + /* Retrieve request. */ + err = es_read_string (stream_sock, 1, &request, &request_size); + if (err) + break; + + if (DBG_COMMAND) + log_debug ("[ssh-agent] Received request of length: %u\n", + request_size); + + stream_request = es_mopen (NULL, 0, 0, 1, + realloc_secure, gcry_free, "r+"); + if (! stream_request) + { + err = gpg_error_from_errno (errno); + break; + } + ret = es_setvbuf (stream_request, NULL, _IONBF, 0); + if (ret) + { + err = gpg_error_from_errno (errno); + break; + } + err = es_write_data (stream_request, request, request_size); + if (err) + break; + es_rewind (stream_request); + + stream_response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! stream_response) + { + err = gpg_error_from_errno (errno); + break; + } + + /* Process request. */ + err = ssh_request_process (&ctrl, stream_request, stream_response); + if (err) + break; + + /* Figure out size of response data. */ + size = es_ftell (stream_response); + err = es_fseek (stream_response, 0, SEEK_SET); + if (err) + break; + + /* Write response data to socket stream. */ + err = es_write_uint32 (stream_sock, size); + if (err) + break; + err = es_copy (stream_sock, stream_response); + if (err) + break; + + err = es_fflush (stream_sock); + if (err) + break; + + es_fclose (stream_request); + stream_request = NULL; + es_fclose (stream_response); + stream_response = NULL; + xfree (request); + request = NULL; + }; + + out: + + /* FIXME: logging. */ + + if (stream_sock) + es_fclose (stream_sock); + if (stream_request) + es_fclose (stream_request); + if (stream_response) + es_fclose (stream_response); + xfree (request); /* FIXME? */ + + if (DBG_COMMAND) + log_debug ("[ssh-agent] Leaving ssh command handler: %s\n", gpg_strerror (err)); +} -- cgit v1.2.3 From 0cb7a855abde6df462c9333ac59d4675cdad790a Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 26 Jan 2005 22:33:11 +0000 Subject: 2005-01-26 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_sign_request): Confirm to agent protocol in case of failure. --- agent/ChangeLog | 4 ++++ agent/command-ssh.c | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 051ed911e..8c6444b25 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,6 +1,10 @@ 2005-01-26 Moritz Schulte <moritz@g10code.com> + * command-ssh.c (ssh_handler_sign_request): Confirm to agent + protocol in case of failure. + * command-ssh.c: New file. + * Makefile.am (gpg_agent_SOURCES): New source file: command-ssh.c. * findkey.c (modify_description): New function. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index a76bbfff7..4c13f5059 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1706,14 +1706,14 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) if (! bad) { /* Done. */ - es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); - if (! es_ferror (response)) + if (! err) { - if (! err) + es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + if (! es_ferror (response)) es_write_string (response, sig, sig_n); - else - es_write_byte (response, SSH_RESPONSE_FAILURE); } + else + es_write_byte (response, SSH_RESPONSE_FAILURE); } gcry_sexp_release (key); -- cgit v1.2.3 From 8bcf546b143decc021bb0adb374390230597a406 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 26 Jan 2005 23:15:42 +0000 Subject: 2005-01-27 Moritz Schulte <moritz@g10code.com> * gpg-agent.texi: Document ssh-agent emulation layer. --- doc/ChangeLog | 4 ++++ doc/gpg-agent.texi | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 855c3ca38..fa61b0466 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-01-27 Moritz Schulte <moritz@g10code.com> + + * gpg-agent.texi: Document ssh-agent emulation layer. + 2005-01-04 Werner Koch <wk@g10code.com> * gnupg.texi: Updated to use @copying. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 9d2cdfc46..01b4227c6 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -326,6 +326,37 @@ 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. +@item --ssh-support +@itemx --ssh-support +@opindex ssh-support +@opindex ssh + +Enable emulation of the OpenSSH Agent protocol. + +In this mode of operation, the agent does not only implement the +gpg-agent protocol, but also the agent protocol used by OpenSSH +(through a seperate socket). Consequently, it should possible to use +the gpg-agent as a drop-in replacement for the well known ssh-agent. + +SSH Keys, which are to be used through the agent, need to be added to +the gpg-agent initially through the ssh-add utility. When a key is +added, ssh-add will ask for the password of the provided key file and +send the unprotected key material to the agent; this causes the +gpg-agent to ask for a passphrase, which is to be used for encrypting +the newly received key and storing it in a gpg-agent specific +directory. + +Once, a key has been added to the gpg-agent this way, the gpg-agent +will be ready to use the key. + +Note: in case the gpg-agent receives a signature request, the user +might need to be prompted for a passphrased, which is necessary for +decrypting the stored key. Since the ssh-agent protocol does not +contain a mechanism for telling the agent on which display/terminal it +is running, gpg-agent's --ssh-support switch implies --keep-display +and --keep-tty. This strategy causes the gpg-agent to open a pinentry +on the display or on the terminal, on which it (the gpg-agent) was +started. @end table @@ -396,6 +427,9 @@ $ eval `gpg-agent --daemon` @node Agent Protocol @section Agent's Assuan Protocol +Note: this section does only document the protocol, which is used by +GnuPG components; it does not deal with the ssh-agent protocol. + The @command{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 -- cgit v1.2.3 From 2b8e9bc5c542316aa9537d4846268d785a7787ae Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Fri, 28 Jan 2005 19:57:14 +0000 Subject: 2005-01-28 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_add_identity): Pass ctrl to ssh_identity_register(). (ssh_identity_register): New argument: ctrl; pass ctrl to get_passphrase(). (get_passphrase): Pass ctrl instead of NULL to agent_askpin(). (start_command_handler_ssh): Use agent_init_default_ctrl(); deallocate structure members, which might be dynamically allocated. (lifetime_default): Removed variable. (ssh_handler_add_identity): Fix ttl handling; renamed variable `death' to `ttl'. (ssh_identity_register): Fix key grip handling. --- agent/ChangeLog | 15 +++++++++++++++ agent/command-ssh.c | 38 ++++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 8c6444b25..1d0833a8e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,18 @@ +2005-01-28 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_handler_add_identity): Pass ctrl to + ssh_identity_register(). + (ssh_identity_register): New argument: ctrl; pass ctrl to + get_passphrase(). + (get_passphrase): Pass ctrl instead of NULL to agent_askpin(). + (start_command_handler_ssh): Use agent_init_default_ctrl(); + deallocate structure members, which might be dynamically + allocated. + (lifetime_default): Removed variable. + (ssh_handler_add_identity): Fix ttl handling; renamed variable + `death' to `ttl'. + (ssh_identity_register): Fix key grip handling. + 2005-01-26 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_sign_request): Confirm to agent diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 4c13f5059..9d1be4a8d 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -94,8 +94,6 @@ typedef struct ssh_key_type_spec -static uint32_t lifetime_default; - /* General utility functions. */ static void * @@ -1725,7 +1723,8 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) } static gpg_error_t -get_passphrase (const char *description, size_t passphrase_n, char *passphrase) +get_passphrase (ctrl_t ctrl, + const char *description, size_t passphrase_n, char *passphrase) { struct pin_entry_info_s *pi; gpg_error_t err; @@ -1747,7 +1746,7 @@ get_passphrase (const char *description, size_t passphrase_n, char *passphrase) pi->cb_errtext = NULL; pi->max_length = 100; - err = agent_askpin (NULL, description, NULL, pi); + err = agent_askpin (ctrl, description, NULL, pi); if (err) goto out; @@ -1851,7 +1850,7 @@ ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, } static gpg_error_t -ssh_identity_register (gcry_sexp_t key, int ttl) +ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) { unsigned char key_grip_raw[21]; unsigned char *buffer; @@ -1862,11 +1861,11 @@ ssh_identity_register (gcry_sexp_t key, int ttl) char key_grip[41]; char *comment; gpg_error_t err; - + unsigned int i; int ret; if (DBG_COMMAND) - log_debug ("[ssh-agent] registering identity `%s'\n", key_grip); + log_debug ("[ssh-agent] registering identity\n"); description = NULL; comment = NULL; @@ -1898,7 +1897,7 @@ ssh_identity_register (gcry_sexp_t key, int ttl) "for protecting the received secret key `%s':", comment ? comment : ""); - err = get_passphrase (description, sizeof (passphrase), passphrase); + err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase); if (err) goto out; @@ -1910,7 +1909,10 @@ ssh_identity_register (gcry_sexp_t key, int ttl) if (err) goto out; - err = agent_put_cache (key_grip_raw, passphrase, ttl); + for (i = 0; i < 20; i++) + sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]); + + err = agent_put_cache (key_grip, passphrase, ttl); if (err) goto out; @@ -1954,15 +1956,15 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) gcry_sexp_t key; byte_t b; int confirm; - int death; + int ttl; int bad; if (DBG_COMMAND) log_debug ("[ssh-agent] add identity\n"); confirm = 0; - death = 0; key = NULL; + ttl = 0; bad = 0; /* FIXME? */ @@ -1990,7 +1992,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) err = es_read_uint32 (request, &n); if (! err) - death = time (NULL) + n; + ttl = n; break; } @@ -2008,12 +2010,9 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) if (err) goto out; - if (lifetime_default && (! death)) - death = time (NULL) + lifetime_default; - /* FIXME: are constraints used correctly? */ - err = ssh_identity_register (key, death); + err = ssh_identity_register (ctrl, key, ttl); out: @@ -2217,6 +2216,7 @@ start_command_handler_ssh (int sock_client) log_debug ("[ssh-agent] Starting command handler\n"); memset (&ctrl, 0, sizeof (ctrl)); + agent_init_default_ctrl (&ctrl); ctrl.connection_fd = sock_client; stream_response = NULL; @@ -2324,4 +2324,10 @@ start_command_handler_ssh (int sock_client) if (DBG_COMMAND) log_debug ("[ssh-agent] Leaving ssh command handler: %s\n", gpg_strerror (err)); + + free (ctrl.display); + free (ctrl.ttyname); + free (ctrl.ttytype); + free (ctrl.lc_ctype); + free (ctrl.lc_messages); } -- cgit v1.2.3 From 5ba1e5cfb7ec1589a33a99dbab6d0071400b4112 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sat, 29 Jan 2005 22:43:00 +0000 Subject: 2005-01-29 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_request_identities) (ssh_handler_sign_request, ssh_handler_add_identity) (ssh_handler_remove_identity, ssh_handler_remove_all_identities) (ssh_handler_lock, ssh_handler_unlock): Changed to return an error code instead of a boolean. (ssh_request_process): Changed to return a boolean instead of an error; adjust caller. (ssh_request_handle_t): Adjusted type. (ssh_request_spec): New member: identifier. (REQUEST_SPEC_DEFINE): New macro; use it for initialization of request_specs[]. (ssh_request_process): In debugging mode, log identifier of handler to execute. (start_command_handler_ssh): Moved most of the stream handling code ... (ssh_request_process): ... here. --- agent/ChangeLog | 19 +++ agent/command-ssh.c | 435 ++++++++++++++++++++++++++-------------------------- 2 files changed, 240 insertions(+), 214 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 1d0833a8e..bf3ffe824 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,22 @@ +2005-01-29 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_handler_request_identities) + (ssh_handler_sign_request, ssh_handler_add_identity) + (ssh_handler_remove_identity, ssh_handler_remove_all_identities) + (ssh_handler_lock, ssh_handler_unlock): Changed to return an error + code instead of a boolean. + (ssh_request_process): Changed to return a boolean instead of an + error; adjust caller. + (ssh_request_handle_t): Adjusted type. + (ssh_request_spec): New member: identifier. + (REQUEST_SPEC_DEFINE): New macro; use it for initialization of + request_specs[]. + (ssh_request_process): In debugging mode, log identifier of + handler to execute. + (start_command_handler_ssh): Moved most of the stream handling + code ... + (ssh_request_process): ... here. + 2005-01-28 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_add_identity): Pass ctrl to diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 9d1be4a8d..db0e8daa9 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -19,6 +19,8 @@ * 02111-1307, USA */ +/* Only v2 of the ssh-agent protocol is implemented. */ + #include <config.h> #include <stdint.h> #include <stdlib.h> @@ -65,13 +67,15 @@ /* A "byte". */ typedef unsigned char byte_t; -typedef int (*ssh_request_handler_t) (ctrl_t ctrl, - estream_t request, estream_t response); +typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl, + estream_t request, + estream_t response); typedef struct ssh_request_spec { byte_t type; ssh_request_handler_t handler; + const char *identifier; } ssh_request_spec_t; typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis); @@ -105,7 +109,7 @@ realloc_secure (void *a, size_t n) p = gcry_realloc (a, n); else p = gcry_malloc_secure (n); - + return p; } @@ -1283,7 +1287,7 @@ make_cstring (const char *data, size_t data_n) /* Request handler. */ -static int +static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) { const char *key_type; @@ -1300,11 +1304,8 @@ ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t respon gcry_sexp_t key_public; DIR *dir; gpg_error_t err; + gpg_error_t ret_err; int ret; - int bad; - - if (DBG_COMMAND) - log_debug ("[ssh-agent] request identities\n"); /* Prepare buffer stream. */ @@ -1316,7 +1317,6 @@ ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t respon key_counter = 0; buffer = NULL; dir = NULL; - bad = 0; err = 0; key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); @@ -1426,11 +1426,25 @@ ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t respon gcry_sexp_release (key_secret); gcry_sexp_release (key_public); - es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); - if (! es_ferror (response)) - es_write_uint32 (response, err ? 0 : key_counter); - if (! (err || es_ferror (response))) - es_copy (response, key_blobs); + if (! err) + { + ret_err = es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); + if (ret_err) + goto leave; + ret_err = es_write_uint32 (response, key_counter); + if (ret_err) + goto leave; + ret_err = es_copy (response, key_blobs); + if (ret_err) + goto leave; + } + else + { + ret_err = es_write_byte (response, SSH_RESPONSE_FAILURE); + goto leave; + }; + + leave: if (key_blobs) es_fclose (key_blobs); @@ -1442,7 +1456,7 @@ ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t respon xfree (buffer); xfree ((void *) key_type); /* FIXME? */ - return bad; + return ret_err; } static gpg_error_t @@ -1609,7 +1623,7 @@ data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder, return err; } -static int +static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) { gcry_sexp_t key; @@ -1626,48 +1640,32 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) uint32_t flags; const void *p; gpg_error_t err; - int bad; + gpg_error_t ret_err; key_blob = NULL; data = NULL; sig = NULL; key = NULL; - bad = 0; - - if (DBG_COMMAND) - log_debug ("[ssh-agent] sign request\n"); /* Receive key. */ err = es_read_string (request, 0, &key_blob, &key_blob_size); if (err) - { - bad = 1; - goto out; - } + goto out; err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec); if (err) - { - bad = 1; - goto out; - } + goto out; /* Receive data to sign. */ err = es_read_string (request, 0, &data, &data_size); if (err) - { - bad = 1; - goto out; - } + goto out; /* FIXME? */ err = es_read_uint32 (request, &flags); if (err) - { - bad = 1; - goto out; - } + goto out; /* Hash data. */ hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1); @@ -1701,25 +1699,32 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) out: - if (! bad) + /* Done. */ + + if (! err) { - /* Done. */ - if (! err) - { - es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); - if (! es_ferror (response)) - es_write_string (response, sig, sig_n); - } - else - es_write_byte (response, SSH_RESPONSE_FAILURE); + ret_err = es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + if (ret_err) + goto leave; + ret_err = es_write_string (response, sig, sig_n); + if (ret_err) + goto leave; + } + else + { + ret_err = es_write_byte (response, SSH_RESPONSE_FAILURE); + if (ret_err) + goto leave; } + leave: + gcry_sexp_release (key); xfree (key_blob); xfree (data); xfree (sig); - return bad; + return ret_err; } static gpg_error_t @@ -1864,9 +1869,6 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) unsigned int i; int ret; - if (DBG_COMMAND) - log_debug ("[ssh-agent] registering identity\n"); - description = NULL; comment = NULL; buffer = NULL; @@ -1941,39 +1943,29 @@ ssh_identity_drop (gcry_sexp_t key) /* FIXME: What to do here - forgetting the passphrase or deleting the key from key cache? */ - if (DBG_COMMAND) - log_debug ("[ssh-agent] dropping identity `%s'\n", key_grip); - out: return err; } -static int +static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; gcry_sexp_t key; byte_t b; int confirm; int ttl; - int bad; - if (DBG_COMMAND) - log_debug ("[ssh-agent] add identity\n"); - confirm = 0; key = NULL; ttl = 0; - bad = 0; /* FIXME? */ err = ssh_receive_key (request, &key, 1, 1, NULL); if (err) - { - bad = 1; - goto out; - } + goto out; while (1) { @@ -2018,43 +2010,33 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) gcry_sexp_release (key); - if (! bad) - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return bad; + return ret_err; } -static int +static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response) { unsigned char *key_blob; uint32_t key_blob_size; gcry_sexp_t key; + gpg_error_t ret_err; gpg_error_t err; - int bad; /* Receive key. */ - if (DBG_COMMAND) - log_debug ("[ssh-agent] remove identity\n"); - key_blob = NULL; key = NULL; - bad = 0; err = es_read_string (request, 0, &key_blob, &key_blob_size); if (err) - { - bad = 1; - goto out; - } + goto out; err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL); if (err) - { - bad = 1; - goto out; - } + goto out; err = ssh_identity_drop (key); @@ -2063,10 +2045,10 @@ ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response) xfree (key_blob); gcry_sexp_release (key); - if (! bad) - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return bad; + return ret_err; } static gpg_error_t @@ -2074,9 +2056,6 @@ ssh_identities_remove_all (void) { gpg_error_t err; - if (DBG_COMMAND) - log_debug ("[ssh-agent] remove all identities\n"); - err = 0; /* FIXME: shall we remove _all_ cache entries or only those @@ -2085,15 +2064,17 @@ ssh_identities_remove_all (void) return err; } -static int +static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; err = ssh_identities_remove_all (); - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return 0; + return ret_err; } static gpg_error_t @@ -2101,9 +2082,8 @@ ssh_lock (void) { gpg_error_t err; - if (DBG_COMMAND) - log_debug ("[ssh-agent] lock\n"); - + /* FIXME */ + log_error ("[gpg-agent/ssh] lock command is not implemented\n"); err = 0; return err; @@ -2114,34 +2094,36 @@ ssh_unlock (void) { gpg_error_t err; - if (DBG_COMMAND) - log_debug ("[ssh-agent] unlock\n"); - + log_error ("[gpg-agent/ssh] unlock command is not implemented\n"); err = 0; return err; } -static int +static gpg_error_t ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; err = ssh_lock (); - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return 0; + return ret_err; } -static int +static gpg_error_t ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) { + gpg_error_t ret_err; gpg_error_t err; - err = ssh_unlock (); - es_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + err = ssh_unlock (); + ret_err = es_write_byte (response, + err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); - return 0; + return ret_err; } @@ -2149,181 +2131,206 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) /* Associating request types with the corresponding request handlers. */ +#define REQUEST_SPEC_DEFINE(id, name) \ + { SSH_REQUEST_##id, ssh_handler_##name, #name } + static ssh_request_spec_t request_specs[] = { - { SSH_REQUEST_REQUEST_IDENTITIES, ssh_handler_request_identities }, - { SSH_REQUEST_SIGN_REQUEST, ssh_handler_sign_request }, - { SSH_REQUEST_ADD_IDENTITY, ssh_handler_add_identity }, - { SSH_REQUEST_ADD_ID_CONSTRAINED, ssh_handler_add_identity }, - { SSH_REQUEST_REMOVE_IDENTITY, ssh_handler_remove_identity }, - { SSH_REQUEST_REMOVE_ALL_IDENTITIES, ssh_handler_remove_all_identities }, - { SSH_REQUEST_LOCK, ssh_handler_lock }, - { SSH_REQUEST_UNLOCK, ssh_handler_unlock }, + REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities), + REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request), + REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity), + REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity), + REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity), + REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities), + REQUEST_SPEC_DEFINE (LOCK, lock), + REQUEST_SPEC_DEFINE (UNLOCK, unlock) }; -static gpg_error_t -ssh_request_process (ctrl_t ctrl, estream_t request, estream_t response) +static int +ssh_request_process (ctrl_t ctrl, estream_t stream_sock) { + estream_t response; + estream_t request; byte_t request_type; gpg_error_t err; unsigned int i; - int bad; + int send_err; + int ret; + unsigned char *request_data; + uint32_t request_data_size; + uint32_t response_size; - err = es_read_byte (request, &request_type); + request_data = NULL; + response = NULL; + request = NULL; + send_err = 0; + + /* Create memory streams for request/response data. The entire + request will be stored in secure memory, since it might contain + secret key material. The response does not have to be stored in + secure memory, since we never give out secret keys. */ + + /* Retrieve request. */ + err = es_read_string (stream_sock, 1, &request_data, &request_data_size); + if (err) + goto out; + + if (opt.verbose) + log_debug ("[gpg-agent/ssh] Received request of length: %u\n", + request_data_size); + + request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); + if (! request) + { + err = gpg_error_from_errno (errno); + goto out; + } + ret = es_setvbuf (request, NULL, _IONBF, 0); + if (ret) + { + err = gpg_error_from_errno (errno); + goto out; + } + err = es_write_data (request, request_data, request_data_size); if (err) goto out; + es_rewind (request); - if (DBG_COMMAND) - log_debug ("[ssh-agent] request: %u\n", request_type); + response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); + if (! response) + { + err = gpg_error_from_errno (errno); + goto out; + } + + err = es_read_byte (request, &request_type); + if (err) + { + send_err = 1; + goto out; + } for (i = 0; i < DIM (request_specs); i++) if (request_specs[i].type == request_type) break; if (i == DIM (request_specs)) { - err = es_write_byte (response, SSH_RESPONSE_FAILURE); + log_debug ("[gpg-agent/ssh] request %u is not supported\n", + request_type); + send_err = 1; goto out; } - - bad = (*request_specs[i].handler) (ctrl, request, response); - if (bad) - err = GPG_ERR_PROTOCOL_VIOLATION; + if (opt.verbose) + log_debug ("[gpg-agent/ssh] Executing request handler: %s (%u)\n", + request_specs[i].identifier, request_specs[i].type); + + err = (*request_specs[i].handler) (ctrl, request, response); + if (err) + { + send_err = 1; + goto out; + } + + response_size = es_ftell (response); + err = es_fseek (response, 0, SEEK_SET); + if (err) + { + send_err = 1; + goto out; + } + + err = es_write_uint32 (stream_sock, response_size); + if (err) + { + send_err = 1; + goto out; + } + + err = es_copy (stream_sock, response); + if (err) + goto out; + + err = es_fflush (stream_sock); + if (err) + goto out; out: - return err; + if (err && es_feof (stream_sock)) + log_error ("[gpg-agent/ssh] Error occured while processing request: %s\n", + gpg_strerror (err)); + + if (send_err) + { + err = es_write_uint32 (stream_sock, 1); + if (err) + goto leave; + err = es_write_byte (stream_sock, SSH_RESPONSE_FAILURE); + if (err) + goto leave; + } + + leave: + + if (request) + es_fclose (request); + if (response) + es_fclose (response); + xfree (request_data); /* FIXME? */ + + return !! err; } void start_command_handler_ssh (int sock_client) { struct server_control_s ctrl; - gpg_error_t err; - estream_t stream_response; - estream_t stream_request; estream_t stream_sock; - unsigned char *request; - uint32_t request_size; - size_t size; + gpg_error_t err; + int bad; int ret; /* Setup control structure. */ - if (DBG_COMMAND) - log_debug ("[ssh-agent] Starting command handler\n"); - memset (&ctrl, 0, sizeof (ctrl)); agent_init_default_ctrl (&ctrl); ctrl.connection_fd = sock_client; - stream_response = NULL; - stream_request = NULL; - stream_sock = NULL; - request = NULL; - + /* Create stream from socket. */ stream_sock = es_fdopen (sock_client, "r+"); if (! stream_sock) { err = gpg_error_from_errno (errno); + log_error ("[gpg-agent/ssh] Failed to create stream from socket: %s\n", + gpg_strerror (err)); goto out; } + /* We have to disable the estream buffering, because the estream + core doesn't know about secure memory. */ ret = es_setvbuf (stream_sock, NULL, _IONBF, 0); if (ret) { err = gpg_error_from_errno (errno); + log_error ("[gpg-agent/ssh] Failed to disable buffering " + "on socket stream: %s\n", gpg_strerror (err)); goto out; } while (1) { - /* Create memory streams for request/response data. The entire - request will be stored in secure memory, since it might - contain secret key material. The response does not have to - be stored in secure memory, since we never give out secret - keys. FIXME: wrong place. */ - - /* Retrieve request. */ - err = es_read_string (stream_sock, 1, &request, &request_size); - if (err) - break; - - if (DBG_COMMAND) - log_debug ("[ssh-agent] Received request of length: %u\n", - request_size); - - stream_request = es_mopen (NULL, 0, 0, 1, - realloc_secure, gcry_free, "r+"); - if (! stream_request) - { - err = gpg_error_from_errno (errno); - break; - } - ret = es_setvbuf (stream_request, NULL, _IONBF, 0); - if (ret) - { - err = gpg_error_from_errno (errno); - break; - } - err = es_write_data (stream_request, request, request_size); - if (err) - break; - es_rewind (stream_request); - - stream_response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+"); - if (! stream_response) - { - err = gpg_error_from_errno (errno); - break; - } - /* Process request. */ - err = ssh_request_process (&ctrl, stream_request, stream_response); - if (err) - break; - - /* Figure out size of response data. */ - size = es_ftell (stream_response); - err = es_fseek (stream_response, 0, SEEK_SET); - if (err) - break; - - /* Write response data to socket stream. */ - err = es_write_uint32 (stream_sock, size); - if (err) - break; - err = es_copy (stream_sock, stream_response); - if (err) + bad = ssh_request_process (&ctrl, stream_sock); + if (bad) break; - - err = es_fflush (stream_sock); - if (err) - break; - - es_fclose (stream_request); - stream_request = NULL; - es_fclose (stream_response); - stream_response = NULL; - xfree (request); - request = NULL; }; out: - /* FIXME: logging. */ - if (stream_sock) es_fclose (stream_sock); - if (stream_request) - es_fclose (stream_request); - if (stream_response) - es_fclose (stream_response); - xfree (request); /* FIXME? */ - - if (DBG_COMMAND) - log_debug ("[ssh-agent] Leaving ssh command handler: %s\n", gpg_strerror (err)); free (ctrl.display); free (ctrl.ttyname); -- cgit v1.2.3 From bbe610117745b714980a83c0eda533e8ff12712f Mon Sep 17 00:00:00 2001 From: Repo Admin <nobody@gnupg.org> Date: Thu, 3 Feb 2005 10:21:26 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'GNUPG-1-9-BRANCH'. --- doc/README.W32 | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 doc/README.W32 diff --git a/doc/README.W32 b/doc/README.W32 new file mode 100644 index 000000000..18f745d9c --- /dev/null +++ b/doc/README.W32 @@ -0,0 +1,186 @@ +README.W32 -*- text -*- + +This is a binary package with GnuPG for MS-Windows 95, 98, WNT, W2000 +and XP. See the file README for generic instructions and usage hints. + +A FAQ comes with this package and a probably more recent one can be +found online at http://www.gnupg.org/faq.html. See +http://www.gnupg.org/docs-mls.html for a list of mailing lists. In +particular the list gnupg-users@gnupg.org might be useful to answer +questions - but please read the FAQ first. + + +Installation directory: +======================= + +The installation directory of GnuPG is stored in the Registry under +the key HKEY_LOCAL_MACHINE\Software\GNU\GnuPG with the name "Install +Directory". The installer does not change the PATH environment +variable to include this directory. You might want to do this +manually. + +Below the Installation directory, you will find directories named +"Doc", "gnupg.nls" and "Src". The latter will be used for distributed +patched, if any, and to store the source file if they have been +included in this package. The source files usually require further +unpacking using a the TAR utility. + + +Internationalization support: +============================= + +Store the locale id (like "de") into the Registry under the key +HKEY_CURRENT_USER\Software\GNU\GnuPG with the name "Lang". This must +match one of the installed languages files in the directory named +"gnupg.nls" below the installation directory. Note, that the ".mo" +extension is not part of the lcoale id. + + +Home directory: +=============== + +GnuPG makes use of a per user home directory to store its keys as well +as configuration files. The default home directory is a directory +named "gnupg" below the application data directory of the user. This +directory will be created if it does not exist. Being only a default, +it may be changed by setting the name of the home directory into the +Registry under the key HKEY_CURRENT_USER\Software\GNU\GnuPG using the +name "HomeDir". If an environment varaibale "GNUPGHOME" exists, this +even overrides the registry setting. The command line option +"--homedir" may be used to override all other settings of the home +directory. + + +Reporting bugs: +=============== + +Please check the documentation first before asking or reporting a +bugs. In particular check the archives of the mailing lists (see +www.gnupg.org) and the bug tracking system at http://bugs.gnupg.org +(login is "guest" password is "guest") whether the problem is already +known. Asking on the gnupg-users mailing list is also strongly +encouraged; if you are not subscribed it may some time until a posting +is approved (this is an anti-spam measure). Bug reporting addresses +are listed in the file AUTHORS. + +If you want to report a bug or have other problems, always give +detailed description of the problem, the version of GnuPG you used, +the version of the OS, whether it is the official version from +gnupg.org or how you built it. Don't edit error messages - replacing +sensitive information like user IDs, fingerprints and keyids is okay. +If possible, switch to English messages by changing the "Lang" entry +to empty (see under Internationalization support). + + +How to build GnuPG from the source: +=================================== + +Until recently all official GnuPG versions have been build using the +Mingw32/CPD kit as available at +ftp://ftp.gnupg.org/people/werner/cpd/mingw32-cqpd-0.3.2.tar.gz . +However, for maintenance reasons we switched to Debian's mingw32 cross +compiler package and that is now the recommended way of building GnuPG +for W32 platforms. It might be possible to build it nativly on a W32 +platform but this is not supported. Please don't file any bug reports +if it does not build with any other system than the recommended one. + +According to the conditions of the GNU General Public License you +either got the source files with this package, a written offer to send +you the source on demand or the source is available at the same site +you downloaded the binary package. If you downloaded the package from +the official GnuPG site or one of its mirrors, the corresponding +source tarball is available in the sibling directory named gnupg. The +source used to build all versions is always the same and the version +numbers should match. If the version number of the binary package has +a letter suffix, you will find a patch file installed in the "Src" +directory with the changes relative to the generic version. + +The source is distributed as a BZIP2 or GZIP compressed tar archive. +See the instructions in file README on how to check the integrity of +that file. Wir a properly setup build environment, you unpack the +tarball change to the created directory and run + + $ ./autogen.sh --build-w32 + $ make + $ cp g10/gpg*.exe /some_windows_drive/ + +Building a version with the installer is a bit more complex and +basically works by creating a top directory, unpacking in that top +directory, switching to the gnupg-1.x.y directory, running +"./autogen.sh --build-w32" and "make", switching back to the top +directory, running a "mkdir dist-w32; mkdir iconv", copying the +required iconv files (iconv.dll, README.iconv, COPYING.LIB) into the +iconv directory, running gnupg-1.x.y/scripts/mk-w32-dist and voila, +the installer package will be available in the dist-w32 directory. + + +Copying: +======== + +GnuPG is + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 Free Software Foundation, Inc. + + 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 + +See the files AUTHORS and THANKS for credits, further legal +information and bug reporting addresses pertaining to GnuPG. + +For copying conditions of the GNU LIBICONV library see the file +README.iconv. + +The installer software used to create the official binary packages for +W32 is NSIS (http://nsis.sourceforge.net/): + + Copyright (C) 1999-2005 Nullsoft, Inc. + + This license applies to everything in the NSIS package, except where + otherwise noted. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +The user interface used with the installer is + + Copyright (C) 2002-2005 Joost Verburg + + [It is distributed along with NSIS and the same conditions as stated + above apply] + + +The term "W32" is used to describe the API used by current Microsoft +Windows versions. We don't use the Microsft terminology here; in +hacker terminology, calling something a "win" is a form of praise. +Keep in mind that Windows ist just a temporary workaround until you +can switch to a complete Free Software system. Be the source always +with you. -- cgit v1.2.3 From 625bafa4dacb7f20cc2c11697048ccafbb6c180a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 3 Feb 2005 13:20:57 +0000 Subject: Forgot to commit the recent fixed to scd and logging - doing it now --- ChangeLog | 5 ++ configure.ac | 6 +- jnlib/ChangeLog | 5 ++ jnlib/logging.c | 41 ++++-------- scd/ChangeLog | 25 +++++++ scd/apdu.c | 12 ++-- scd/app-openpgp.c | 191 ++++++++++++++++++++++++++++++++++++------------------ scd/ccid-driver.c | 4 +- 8 files changed, 188 insertions(+), 101 deletions(-) diff --git a/ChangeLog b/ChangeLog index 237999e8a..f878f60d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-01-17 Werner Koch <wk@g10code.com> + + * configure.ac: Make --without-included-regex work as expected. + Fixed FTP location info for some libraries. + 2005-01-13 Werner Koch <wk@g10code.com> Released 1.9.15. diff --git a/configure.ac b/configure.ac index 6cfc61193..7462a759e 100644 --- a/configure.ac +++ b/configure.ac @@ -889,7 +889,7 @@ if test "$use_regex" = yes ; then AC_MSG_CHECKING([whether the included regex lib is requested]) AC_ARG_WITH(included-regex, [ --with-included-regex use the included GNU regex library], - [gnupg_cv_included_regex=yes],[gnupg_cv_included_regex=no]) + [gnupg_cv_included_regex="$withval"],[gnupg_cv_included_regex=no]) AC_MSG_RESULT($gnupg_cv_included_regex) if test $gnupg_cv_included_regex = no ; then @@ -1060,7 +1060,7 @@ if test "$have_gpg_error" = "no"; then *** *** You need libgpg-error to build this program. ** This library is for example available at -*** ftp://ftp.gnupg.org/gcrypt/alpha/libgpg-error +*** ftp://ftp.gnupg.org/gcrypt/libgpg-error *** (at least version $NEED_GPG_ERROR_VERSION is required.) ***]]) fi @@ -1070,7 +1070,7 @@ if test "$have_libgcrypt" = "no"; then *** *** You need libgcrypt to build this program. ** This library is for example available at -*** ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/ +*** ftp://ftp.gnupg.org/gcrypt/libgcrypt/ *** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API) is required.) ***]]) fi diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index a879254ae..0c82c8724 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2005-01-19 Werner Koch <wk@g10code.com> + + * logging.c (fun_writer): Don't fallback to stderr. Print to + stderr only if connected to a tty. + 2004-12-20 Werner Koch <wk@g10code.com> * w32-pth.c (do_pth_event_free): The events are hold in a ring diff --git a/jnlib/logging.c b/jnlib/logging.c index 781f03e6d..97a2b9c9e 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -1,6 +1,6 @@ /* logging.c - useful logging functions * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -20,11 +20,6 @@ */ -/* This file should replace logger.c in the future - for now it is not - * used by GnuPG but by GPA. - * It is a quite simple implemenation but sufficient for most purposes. - */ - #include <config.h> #include <stdlib.h> #include <stdio.h> @@ -64,23 +59,6 @@ static int force_prefixes; static int missing_lf; static int errorcount; -#if 0 -static void -write2stderr( const char *s ) -{ - write( 2, s, strlen(s) ); -} - - -static void -do_die(int rc, const char *text ) -{ - write2stderr("\nFatal error: "); - write2stderr(text); - write2stderr("\n"); - abort(); -} -#endif int log_get_errorcount (int clear) @@ -150,7 +128,8 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) cookie->fd = socket (PF_LOCAL, SOCK_STREAM, 0); if (cookie->fd == -1) { - if (!cookie->quiet && !running_detached) + if (!cookie->quiet && !running_detached + && isatty (fileno (stderr))) fprintf (stderr, "failed to create socket for logging: %s\n", strerror(errno)); } @@ -168,7 +147,8 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) if (connect (cookie->fd, (struct sockaddr *) &addr, addrlen) == -1) { - if (!cookie->quiet && !running_detached) + if (!cookie->quiet && !running_detached + && isatty (fileno (stderr))) fprintf (stderr, "can't connect to `%s': %s\n", cookie->name, strerror(errno)); close (cookie->fd); @@ -180,12 +160,16 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) { if (!running_detached) { + /* Due to all the problems with apps not running + detahced but beeing caled with stderr closed or + used for a different purposes, it does not make + sense to switch to stderr. We tehrefore disable it. */ if (!cookie->quiet) { - fputs ("switching logging to stderr\n", stderr); + /* fputs ("switching logging to stderr\n", stderr);*/ cookie->quiet = 1; } - cookie->fd = fileno (stderr); + cookie->fd = -1; /*fileno (stderr);*/ } } else /* Connection has been established. */ @@ -199,7 +183,8 @@ fun_writer (void *cookie_arg, const char *buffer, size_t size) if (cookie->fd != -1 && !writen (cookie->fd, buffer, size)) return size; /* Okay. */ - if (!running_detached && cookie->fd != -1) + if (!running_detached && cookie->fd != -1 + && isatty (fileno (stderr))) { if (*cookie->name) fprintf (stderr, "error writing to `%s': %s\n", diff --git a/scd/ChangeLog b/scd/ChangeLog index e85c8d81c..aba75ad54 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,28 @@ +2005-01-26 Werner Koch <wk@g10code.com> + + * ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround + also for newer firmware versions. Need to get a list of fixed + firmware versions and use that. + +2005-01-25 Werner Koch <wk@g10code.com> + + * apdu.c (apdu_send_le, apdu_send_direct): Fix some compiler + warnings. + + * app-openpgp.c (get_cached_data): New arg GET_IMMEDIATE to bypass + the cache. Changed all callers. + (get_one_do): Bypass the cache if the value would have been read + directly for v1.1 cards.It makes things a bit slower but obnly for + 1.0 cards and there are not that many cards out in the wild. This + is required to fix a caching bug when generating new keys; as a + side effect of the retrieval of the the C4 DO from the 6E DO the + cached fingerprint will get updated to the old value and later + when signing the generated key the checking of the fingerprint + fails becuase it won't match the new one. Thanks to Moritz for + analyzing this problem. + (verify_chv3): Removed the CHV status reread logic because we + won't cache the C4 DO anymore. + 2004-12-28 Werner Koch <wk@g10code.com> * ccid-driver.c (find_endpoint): New. diff --git a/scd/apdu.c b/scd/apdu.c index 9120616de..040de1461 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2721,7 +2721,8 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" response: sw=%04X datalen=%d\n", sw, resultlen); + log_debug (" response: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } @@ -2787,7 +2788,8 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" more: sw=%04X datalen=%d\n", sw, resultlen); + log_debug (" more: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } @@ -2920,7 +2922,8 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" response: sw=%04X datalen=%d\n", sw, resultlen); + log_debug (" response: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if ( !retbuf && (sw == SW_SUCCESS || (sw & 0xff00) == SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } @@ -2972,7 +2975,8 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, resultlen -= 2; if (DBG_CARD_IO) { - log_debug (" more: sw=%04X datalen=%d\n", sw, resultlen); + log_debug (" more: sw=%04X datalen=%d\n", + sw, (unsigned int)resultlen); if (!retbuf && (sw==SW_SUCCESS || (sw&0xff00)==SW_MORE_DATA)) log_printhex (" dump: ", result, resultlen); } diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index c37308054..fca0a98b7 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1,5 +1,5 @@ /* app-openpgp.c - The OpenPGP card application. - * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -79,8 +79,13 @@ static struct { { 0x00C4, 0, 0x6E, 1, 0, 1, 1, "CHV Status Bytes" }, { 0x00C5, 0, 0x6E, 1, 0, 0, 0, "Fingerprints" }, { 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" }, + { 0x00CD, 0, 0x6E, 1, 0, 0, 0, "Generation time" }, { 0x007A, 1, 0, 1, 0, 0, 0, "Security Support Template" }, { 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" }, + { 0x0101, 0, 0, 0, 0, 0, 0, "Private DO 1"}, + { 0x0102, 0, 0, 0, 0, 0, 0, "Private DO 2"}, + { 0x0103, 0, 0, 0, 0, 0, 0, "Private DO 3"}, + { 0x0104, 0, 0, 0, 0, 0, 0, "Private DO 4"}, { 0 } }; @@ -133,10 +138,12 @@ do_deinit (app_t app) /* Wrapper around iso7816_get_data which first tries to get the data - from the cache. */ + from the cache. With GET_IMMEDIATE passed as true, the cache is + bypassed. */ static gpg_error_t get_cached_data (app_t app, int tag, - unsigned char **result, size_t *resultlen) + unsigned char **result, size_t *resultlen, + int get_immediate) { gpg_error_t err; int i; @@ -147,23 +154,25 @@ get_cached_data (app_t app, int tag, *result = NULL; *resultlen = 0; - for (c=app->app_local->cache; c; c = c->next) - if (c->tag == tag) - { - if(c->length) + if (!get_immediate) + { + for (c=app->app_local->cache; c; c = c->next) + if (c->tag == tag) { - p = xtrymalloc (c->length); - if (!p) - return gpg_error (gpg_err_code_from_errno (errno)); - memcpy (p, c->data, c->length); - *result = p; + if(c->length) + { + p = xtrymalloc (c->length); + if (!p) + return gpg_error (gpg_err_code_from_errno (errno)); + memcpy (p, c->data, c->length); + *result = p; + } + + *resultlen = c->length; + + return 0; } - - *resultlen = c->length; - - return 0; - } - + } err = iso7816_get_data (app->slot, tag, &p, &len); if (err) @@ -172,6 +181,9 @@ get_cached_data (app_t app, int tag, *resultlen = len; /* Check whether we should cache this object. */ + if (get_immediate) + return 0; + for (i=0; data_objects[i].tag; i++) if (data_objects[i].tag == tag) { @@ -180,8 +192,7 @@ get_cached_data (app_t app, int tag, break; } - /* No, cache it. */ - + /* Okay, cache it. */ for (c=app->app_local->cache; c; c = c->next) assert (c->tag != tag); @@ -294,7 +305,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) if (data_objects[i].tag && data_objects[i].get_from) { rc = get_cached_data (app, data_objects[i].get_from, - &buffer, &buflen); + &buffer, &buflen, + data_objects[i].get_immediate_in_v11); if (!rc) { const unsigned char *s; @@ -315,7 +327,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) if (!value) /* Not in a constructed DO, try simple. */ { - rc = get_cached_data (app, tag, &buffer, &buflen); + rc = get_cached_data (app, tag, &buffer, &buflen, + data_objects[i].get_immediate_in_v11); if (!rc) { value = buffer; @@ -421,7 +434,7 @@ count_bits (const unsigned char *a, size_t len) at any time and should be called after changing the login-data DO. Everything up to a LF is considered a mailbox or account name. If - the first LF is follewed by DC4 (0x14) control sequence are + the first LF is followed by DC4 (0x14) control sequence are expected up to the next LF. Control sequences are separated by FS (0x28) and consist of key=value pairs. There is one key defined: @@ -575,6 +588,23 @@ send_fpr_if_not_null (ctrl_t ctrl, const char *keyword, buf, (size_t)strlen (buf), NULL, 0); } +static void +send_fprtime_if_not_null (ctrl_t ctrl, const char *keyword, + int number, const unsigned char *stamp) +{ + char numbuf1[50], numbuf2[50]; + unsigned long value; + + value = (stamp[0] << 24) | (stamp[1]<<16) | (stamp[2]<<8) | stamp[3]; + if (!value) + return; + sprintf (numbuf1, "%d", number); + sprintf (numbuf2, "%lu", value); + send_status_info (ctrl, keyword, + numbuf1, (size_t)strlen(numbuf1), + numbuf2, (size_t)strlen(numbuf2), NULL, 0); +} + static void send_key_data (ctrl_t ctrl, const char *name, const unsigned char *a, size_t alen) @@ -607,12 +637,17 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) { "DISP-SEX", 0x5F35 }, { "PUBKEY-URL", 0x5F50 }, { "KEY-FPR", 0x00C5, 3 }, + { "KEY-TIME", 0x00CD, 4 }, { "CA-FPR", 0x00C6, 3 }, - { "CHV-STATUS", 0x00C4, 1 }, + { "CHV-STATUS", 0x00C4, 1 }, { "SIG-COUNTER", 0x0093, 2 }, { "SERIALNO", 0x004F, -1 }, { "AID", 0x004F }, { "EXTCAP", 0x0000, -2 }, + { "PRIVATE-DO-1", 0x0101 }, + { "PRIVATE-DO-2", 0x0102 }, + { "PRIVATE-DO-3", 0x0103 }, + { "PRIVATE-DO-4", 0x0104 }, { NULL, 0 } }; int idx, i; @@ -686,6 +721,12 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) for (i=0; i < 3; i++) send_fpr_if_not_null (ctrl, table[idx].name, i+1, value+i*20); } + else if (table[idx].special == 4) + { + if (valuelen >= 12) + for (i=0; i < 3; i++) + send_fprtime_if_not_null (ctrl, table[idx].name, i+1, value+i*4); + } else send_status_info (ctrl, table[idx].name, value, valuelen, NULL, 0); @@ -705,9 +746,20 @@ do_learn_status (app_t app, ctrl_t ctrl) do_getattr (app, ctrl, "PUBKEY-URL"); do_getattr (app, ctrl, "LOGIN-DATA"); do_getattr (app, ctrl, "KEY-FPR"); + if (app->card_version > 0x0100) + do_getattr (app, ctrl, "KEY-TIME"); do_getattr (app, ctrl, "CA-FPR"); do_getattr (app, ctrl, "CHV-STATUS"); do_getattr (app, ctrl, "SIG-COUNTER"); + if (app->app_local->extcap.private_dos) + { + do_getattr (app, ctrl, "PRIVATE-DO-1"); + do_getattr (app, ctrl, "PRIVATE-DO-2"); + if (app->did_chv2) + do_getattr (app, ctrl, "PRIVATE-DO-3"); + if (app->did_chv3) + do_getattr (app, ctrl, "PRIVATE-DO-4"); + } return 0; } @@ -792,8 +844,6 @@ verify_chv3 (app_t app, void *relptr; unsigned char *value; size_t valuelen; - int reread_chv_status; - relptr = get_one_do (app, 0x00C4, &value, &valuelen); if (!relptr || valuelen < 7) @@ -809,13 +859,14 @@ verify_chv3 (app_t app, return gpg_error (GPG_ERR_BAD_PIN); } - reread_chv_status = (value[6] < 3); - log_info(_("%d Admin PIN attempts remaining before card" " is permanently locked\n"), value[6]); xfree (relptr); - rc = pincb (pincb_arg, _("Admin PIN"), &pinvalue); + /* TRANSLATORS: Do not translate the "|A|" prefix but + keep it at the start of the string. We need this elsewhere + to get some infos on the string. */ + rc = pincb (pincb_arg, _("|A|Admin PIN"), &pinvalue); if (rc) { log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc)); @@ -839,13 +890,6 @@ verify_chv3 (app_t app, return rc; } app->did_chv3 = 1; - /* If the PIN has been entered wrongly before, we need to flush - the cached value so that the next read correctly reflects the - resetted retry counter. Note that version 1.1 of the specs - allow direct reading of that DO, so that we could actually - flush it in all cases. */ - if (reread_chv_status) - flush_cache_item (app, 0x00C4); } return rc; } @@ -864,17 +908,22 @@ do_setattr (app_t app, const char *name, static struct { const char *name; int tag; + int need_chv; int special; } table[] = { - { "DISP-NAME", 0x005B }, - { "LOGIN-DATA", 0x005E, 2 }, - { "DISP-LANG", 0x5F2D }, - { "DISP-SEX", 0x5F35 }, - { "PUBKEY-URL", 0x5F50 }, - { "CHV-STATUS-1", 0x00C4, 1 }, - { "CA-FPR-1", 0x00CA }, - { "CA-FPR-2", 0x00CB }, - { "CA-FPR-3", 0x00CC }, + { "DISP-NAME", 0x005B, 3 }, + { "LOGIN-DATA", 0x005E, 3, 2 }, + { "DISP-LANG", 0x5F2D, 3 }, + { "DISP-SEX", 0x5F35, 3 }, + { "PUBKEY-URL", 0x5F50, 3 }, + { "CHV-STATUS-1", 0x00C4, 3, 1 }, + { "CA-FPR-1", 0x00CA, 3 }, + { "CA-FPR-2", 0x00CB, 3 }, + { "CA-FPR-3", 0x00CC, 3 }, + { "PRIVATE-DO-1", 0x0101, 2 }, + { "PRIVATE-DO-2", 0x0102, 3 }, + { "PRIVATE-DO-3", 0x0103, 2 }, + { "PRIVATE-DO-4", 0x0104, 3 }, { NULL, 0 } }; @@ -884,7 +933,17 @@ do_setattr (app_t app, const char *name, if (!table[idx].name) return gpg_error (GPG_ERR_INV_NAME); - rc = verify_chv3 (app, pincb, pincb_arg); + switch (table[idx].need_chv) + { + case 2: + rc = verify_chv2 (app, pincb, pincb_arg); + break; + case 3: + rc = verify_chv3 (app, pincb, pincb_arg); + break; + default: + rc = 0; + } if (rc) return rc; @@ -953,10 +1012,14 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, else app->did_chv1 = app->did_chv2 = 0; - rc = pincb (pincb_arg, chvno == 3? "New Admin PIN" : "New PIN", &pinvalue); + /* Note to translators: Do not translate the "|*|" prefixes but + keep it at the start of the string. We need this elsewhere + to get some infos on the string. */ + rc = pincb (pincb_arg, chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"), + &pinvalue); if (rc) { - log_error ("error getting new PIN: %s\n", gpg_strerror (rc)); + log_error (_("error getting new PIN: %s\n"), gpg_strerror (rc)); goto leave; } @@ -1022,14 +1085,14 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); if (rc) { - log_error ("error reading application data\n"); + log_error (_("error reading application data\n")); return gpg_error (GPG_ERR_GENERAL); } fpr = find_tlv (buffer, buflen, 0x00C5, &n); if (!fpr || n != 60) { rc = gpg_error (GPG_ERR_GENERAL); - log_error ("error reading fingerprint DO\n"); + log_error (_("error reading fingerprint DO\n")); goto leave; } fpr += 20*keyno; @@ -1038,13 +1101,13 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, if (i!=20 && !force) { rc = gpg_error (GPG_ERR_EEXIST); - log_error ("key already exists\n"); + log_error (_("key already exists\n")); goto leave; } else if (i!=20) - log_info ("existing key will be replaced\n"); + log_info (_("existing key will be replaced\n")); else - log_info ("generating new key\n"); + log_info (_("generating new key\n")); rc = verify_chv3 (app, pincb, pincb_arg); @@ -1054,7 +1117,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, xfree (buffer); buffer = NULL; #if 1 - log_info ("please wait while key is being generated ...\n"); + log_info (_("please wait while key is being generated ...\n")); start_at = time (NULL); rc = iso7816_generate_keypair #else @@ -1069,16 +1132,16 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, if (rc) { rc = gpg_error (GPG_ERR_CARD); - log_error ("generating key failed\n"); + log_error (_("generating key failed\n")); goto leave; } - log_info ("key generation completed (%d seconds)\n", + log_info (_("key generation completed (%d seconds)\n"), (int)(time (NULL) - start_at)); keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen); if (!keydata) { rc = gpg_error (GPG_ERR_CARD); - log_error ("response does not contain the public key data\n"); + log_error (_("response does not contain the public key data\n")); goto leave; } @@ -1086,7 +1149,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, if (!m) { rc = gpg_error (GPG_ERR_CARD); - log_error ("response does not contain the RSA modulus\n"); + log_error (_("response does not contain the RSA modulus\n")); goto leave; } /* log_printhex ("RSA n:", m, mlen); */ @@ -1096,7 +1159,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, if (!e) { rc = gpg_error (GPG_ERR_CARD); - log_error ("response does not contain the RSA public exponent\n"); + log_error (_("response does not contain the RSA public exponent\n")); goto leave; } /* log_printhex ("RSA e:", e, elen); */ @@ -1129,7 +1192,7 @@ convert_sig_counter_value (const unsigned char *value, size_t valuelen) ul = (value[0] << 16) | (value[1] << 8) | value[2]; else { - log_error ("invalid structure of OpenPGP card (DO 0x93)\n"); + log_error (_("invalid structure of OpenPGP card (DO 0x93)\n")); ul = 0; } return ul; @@ -1161,17 +1224,17 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr) assert (keyno >= 1 && keyno <= 3); - rc = get_cached_data (app, 0x006E, &buffer, &buflen); + rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0); if (rc) { - log_error ("error reading application data\n"); + log_error (_("error reading application data\n")); return gpg_error (GPG_ERR_GENERAL); } fpr = find_tlv (buffer, buflen, 0x00C5, &n); if (!fpr || n != 60) { xfree (buffer); - log_error ("error reading fingerprint DO\n"); + log_error (_("error reading fingerprint DO\n")); return gpg_error (GPG_ERR_GENERAL); } fpr += (keyno-1)*20; @@ -1290,7 +1353,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, memcpy (data+15, indata, indatalen); sigcount = get_sig_counter (app); - log_info ("signatures created so far: %lu\n", sigcount); + log_info (_("signatures created so far: %lu\n"), sigcount); if (!app->did_chv1 || app->force_chv1 ) { diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 0694fe762..459060830 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -403,7 +403,7 @@ parse_ccid_descriptor (ccid_driver_t handle, if (buf[49] == 0xff) DEBUGOUT_CONT ("echo\n"); else - DEBUGOUT_1 (" %02X\n", buf[48]); + DEBUGOUT_CONT_1 (" %02X\n", buf[48]); DEBUGOUT ( " wlcdLayout "); if (!buf[50] && !buf[51]) @@ -450,7 +450,7 @@ parse_ccid_descriptor (ccid_driver_t handle, if (handle->id_vendor == VENDOR_SCM /* FIXME: check whether it is the same firmware version for all drivers. */ - && handle->bcd_device < 0x0513 + && handle->bcd_device < 0x0519 && handle->max_ifsd > 48) { DEBUGOUT ("enabling workaround for buggy SCM readers\n"); -- cgit v1.2.3 From b326996b784b561ab56af5b41037f60ae8a79849 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 3 Feb 2005 17:40:02 +0000 Subject: * AUTHORS: Copied from 1.4 and edited to refelct the changes in 1.9. * agent.h (agent_exit): Add JNLIB_GCC_A_NR to indicate that this function won't return. * gpg-agent.c (check_for_running_agent): Initialize pid to a default value if not needed. * command-ssh.c: Removed stdint.h. s/byte_t/unsigned char/, s/uint32/u32/ becuase that is what we have always used in GnuPG. (ssh_request_specs): Moved to top of file. (ssh_key_types): Ditto. (make_cstring): Ditto. (data_sign): Don't use a variable for the passphrase prompt, make it translatable. (ssh_request_process): * findkey.c (modify_description): Renamed arguments for clarity, polished documentation. Make comment a C-string. Fixed case of DESCRIPTION being just "%". (agent_key_from_file): Make sure comment string to a C-string. * gpg-agent.c (create_socket_name): Cleanup the implemntation, use DIMof, agent_exit, removed superflous args and return the allocated string as value. Documented. Changed callers. (create_server_socket): Cleanups similar to above. Changed callers. (cleanup_do): Renamed to .. (remove_socket): .. this. Changed caller. (handle_connections): The signals are to be handled in the select and not in the accept. Test all FDs after returning from a select. Remove the event tests from the accept calls. The select already assured that the accept won't block. --- AUTHORS | 140 +++++++++++++++++++ ChangeLog | 5 + agent/ChangeLog | 36 ++++- agent/agent.h | 30 ++-- agent/command-ssh.c | 351 ++++++++++++++++++++++++++++++----------------- agent/findkey.c | 200 +++++++++++++-------------- agent/gpg-agent.c | 383 ++++++++++++++++++++++++++++------------------------ common/estream.h | 3 +- 8 files changed, 729 insertions(+), 419 deletions(-) diff --git a/AUTHORS b/AUTHORS index e69de29bb..0de6a8662 100644 --- a/AUTHORS +++ b/AUTHORS @@ -0,0 +1,140 @@ +Program: GnuPG +Maintainer: Werner Koch <wk@gnupg.org> +Bug reports: <bug-gnupg@gnu.org> +Security related bug reports: <security@gnupg.org> + +Please note that this file is for the 1.9 branch of GnuPG. + + +Authors +======= + +Ales Nyakhaychyk <nyakhaychyk@i1fn.linux.by> Translations [be] + +Birger Langkjer <birger.langkjer@image.dk> Translations [da] + +Maxim Britov <maxbritov@tut.by> Translations [ru] + +Daniel Resare <daniel@resare.com> Translations [sv] +Per Tunedal <per@clipanish.com> Translations [sv] + +David Shaw <dshaw@jabberwocky.com> Assigns past and future changes. + (all in keyserver/, + a lot of changes in g10/ see the ChangeLog, + bug fixes here and there) + +Dokianakis Theofanis <madf@hellug.gr> Translations [el] + +Edmund GRIMLEY EVANS <edmundo@rano.org> Translations [eo] + +Florian Weimer <fw@deneb.enyo.de> Assigns past and future changes + (changed:g10/parse-packet.c, include/iobuf.h, util/iobuf.c) + +g10 Code GmbH <info@g10code.com> Assigns past and future changes + (all work since 2001 as indicated by mail addresses in ChangeLogs) + +Gaël Quéri <gael@lautre.net> Translations [fr] + (fixed a lot of typos) + +Gregory Steuck <steuck@iname.com> Translations [ru] + +Nagy Ferenc László <nfl@nfllab.com> Translations [hu] + +Ivo Timmermans <itimmermans@bigfoot.com> Translations [nl] + +Jacobo Tarri'o Barreiro <jtarrio@iname.com> Translations [gl] + +Janusz Aleksander Urbanowicz <alex@bofh.torun.pl> Translations [po] + +Jedi Lin <Jedi@idej.org> Translations [zh-tw] + +Jouni Hiltunen <jouni.hiltunen@kolumbus.fi> Translations [fi] +Tommi Vainikainen <Tommi.Vainikainen@iki.fi> Translations [fi] + +Laurentiu Buzdugan <lbgnupg@rolix.org> Translations [ro] + +Magda Procha'zkova' <magda@math.muni.cz> Translations [cs] + +Michael Roth <mroth@nessie.de> Assigns changes. + (wrote cipher/des.c., changes and bug fixes all over the place) + +Michal Majer <mmajer@econ.umb.sk> Translations [sk] + +Marco d'Itri <md@linux.it> Translations [it] + +Marcus Brinkmann <marcus@g10code.de> + (gpgconf and fixes all over the place) + +Matthew Skala <mskala@ansuz.sooke.bc.ca> Disclaimer + (wrote cipher/twofish.c) + +Moritz Schulte <moritz@g10code.com> + (ssh support gpg-agent) + +Niklas Hernaeus <nh@df.lth.se> Disclaimer + (weak key patches) + +Nilgun Belma Buguner <nilgun@technologist.com> Translations [tr] + +Nils Ellmenreich <nils 'at' infosun.fmi.uni-passau.de> + Assigns past and future changes + (configure.in, cipher/rndlinux.c, FAQ) + +Paul Eggert <eggert@twinsun.com> + (configuration macros for LFS) + +Pavel I. Shajdo <zwon@severodvinsk.ru> Translations [ru] + (man pages) + +Pedro Morais <morais@poli.org> Translations [pt_PT] + +Rémi Guyomarch <rguyom@mail.dotcom.fr> Assigns past and future changes. + (g10/compress.c, g10/encr-data.c, + g10/free-packet.c, g10/mdfilter.c, g10/plaintext.c, util/iobuf.c) + +Stefan Bellon <sbellon@sbellon.de> Assigns past and future changes. + (All patches to support RISC OS) + +Timo Schulz <twoaday@freakmail.de> Assigns past and future changes. + (util/w32reg.c, g10/passphrase.c, g10/hkp.c) + +Tedi Heriyanto <tedi_h@gmx.net> Translations [id] + +Thiago Jung Bauermann <jungmann@cwb.matrix.com.br> Translations [pt_BR] +Rafael Caetano dos Santos <rcaetano@linux.ime.usp.br> Translations [pt_BR] + +Toomas Soome <tsoome@ut.ee> Translations [et] + +Urko Lusa <ulusa@euskalnet.net> Translations [es_ES] + +Walter Koch <koch@u32.de> Translations [de] + +Werner Koch <wk@gnupg.org> Assigns GNU Privacy Guard and future changes. + (started the whole thing, wrote the S/MIME extensions, the + smartcard daemon and the gpg-agent) + +Yosiaki IIDA <iida@ring.gr.jp> Translations [ja] + + + +Other authors +============= + +The files common/libestream.[ch] are maintained as a separate project +by g10 Code GmbH. These files, as used here, are considered part of +GnuPG. + +The RPM specs file scripts/gnupg.spec has been contributed by +several people. + + Copyright 1998, 1999, 2000, 2001, 2002, 2004, + 2005 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. + diff --git a/ChangeLog b/ChangeLog index f878f60d8..2c86f42a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-02-03 Werner Koch <wk@g10code.com> + + * AUTHORS: Copied from 1.4 and edited to refelct the changes in + 1.9. + 2005-01-17 Werner Koch <wk@g10code.com> * configure.ac: Make --without-included-regex work as expected. diff --git a/agent/ChangeLog b/agent/ChangeLog index bf3ffe824..3bd779256 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,37 @@ +2005-02-03 Werner Koch <wk@g10code.com> + + * agent.h (agent_exit): Add JNLIB_GCC_A_NR to indicate that this + function won't return. + + * gpg-agent.c (check_for_running_agent): Initialize pid to a + default value if not needed. + + * command-ssh.c: Removed stdint.h. s/byte_t/unsigned char/, + s/uint32/u32/ becuase that is what we have always used in GnuPG. + (ssh_request_specs): Moved to top of file. + (ssh_key_types): Ditto. + (make_cstring): Ditto. + (data_sign): Don't use a variable for the passphrase prompt, make + it translatable. + (ssh_request_process): + + + * findkey.c (modify_description): Renamed arguments for clarity, + polished documentation. Make comment a C-string. Fixed case of + DESCRIPTION being just "%". + (agent_key_from_file): Make sure comment string to a C-string. + + * gpg-agent.c (create_socket_name): Cleanup the implemntation, use + DIMof, agent_exit, removed superflous args and return the + allocated string as value. Documented. Changed callers. + (create_server_socket): Cleanups similar to above. Changed callers. + (cleanup_do): Renamed to .. + (remove_socket): .. this. Changed caller. + (handle_connections): The signals are to be handled in the select + and not in the accept. Test all FDs after returning from a + select. Remove the event tests from the accept calls. The select + already assured that the accept won't block. + 2005-01-29 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_request_identities) @@ -67,7 +101,7 @@ and ssh-agent protocol. * agent.h (struct opt): New member: ssh_support. - Declare function: start_command_handler_ssh. + (start_command_handler_ssh): Add prototype. 2005-01-04 Werner Koch <wk@g10code.com> diff --git a/agent/agent.h b/agent/agent.h index 8afda6463..a1196bc0b 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -47,26 +47,28 @@ out_of_core (void) /* A large struct name "opt" to keep global flags */ struct { - unsigned int debug; /* debug flags (DBG_foo_VALUE) */ - int verbose; /* verbosity level */ - int quiet; /* be as quiet as possible */ - int dry_run; /* don't change any persistent data */ - int batch; /* batch mode */ - const char *homedir; /* configuration directory name */ - const char *pinentry_program; - const char *scdaemon_program; - int no_grab; /* don't let the pinentry grab the keyboard */ + unsigned int debug; /* Debug flags (DBG_foo_VALUE) */ + int verbose; /* Verbosity level */ + int quiet; /* Be as quiet as possible */ + int dry_run; /* Don't change any persistent data */ + int batch; /* Batch mode */ + const char *homedir; /* Configuration directory name */ + const char *pinentry_program; /* Filename of the program to start as + pinentry. */ + const char *scdaemon_program; /* Filename of the program to handle + smartcard tasks. */ + int no_grab; /* Don't let the pinentry grab the keyboard */ unsigned long def_cache_ttl; unsigned long max_cache_ttl; - int running_detached; /* we are running detached from the tty. */ + int running_detached; /* We are running detached from the tty. */ int ignore_cache_for_signing; int allow_mark_trusted; int allow_preset_passphrase; - int keep_tty; /* don't switch the TTY (for pinentry) on request */ - int keep_display; /* don't switch the DISPLAY (for pinentry) on request */ - int ssh_support; /* Enable ssh-agent emulation. */ + int keep_tty; /* Don't switch the TTY (for pinentry) on request */ + int keep_display; /* Don't switch the DISPLAY (for pinentry) on request */ + int ssh_support; /* Enable ssh-agent emulation. */ } opt; @@ -131,7 +133,7 @@ enum { }; /*-- gpg-agent.c --*/ -void agent_exit (int rc); /* also implemented in other tools */ +void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */ void agent_init_default_ctrl (struct server_control_s *ctrl); /*-- command.c --*/ diff --git a/agent/command-ssh.c b/agent/command-ssh.c index db0e8daa9..390bfe92a 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -22,7 +22,7 @@ /* Only v2 of the ssh-agent protocol is implemented. */ #include <config.h> -#include <stdint.h> + #include <stdlib.h> #include <string.h> #include <errno.h> @@ -33,9 +33,8 @@ #include "agent.h" -#include <gcrypt.h> - #include "estream.h" +#include "i18n.h" @@ -59,26 +58,31 @@ #define SSH_RESPONSE_IDENTITIES_ANSWER 12 #define SSH_RESPONSE_SIGN_RESPONSE 14 +/* Other constants. */ +#define SSH_DSA_SIGNATURE_PADDING 20 +#define SSH_DSA_SIGNATURE_ELEMS 2 +#define SPEC_FLAG_USE_PKCS1V2 (1 << 0) + + + /* Basic types. */ -/* A "byte". */ -typedef unsigned char byte_t; - typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl, estream_t request, estream_t response); typedef struct ssh_request_spec { - byte_t type; + unsigned char type; ssh_request_handler_t handler; const char *identifier; } ssh_request_spec_t; -typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis); +typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, + gcry_mpi_t *mpis); typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob, gcry_mpi_t *mpis); @@ -96,10 +100,91 @@ typedef struct ssh_key_type_spec unsigned int flags; } ssh_key_type_spec_t; + +/* Prototypes. */ +static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, + estream_t request, + estream_t response); +static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl, + estream_t request, + estream_t response); +static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl, + estream_t request, + estream_t response); +static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl, + estream_t request, + estream_t response); +static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl, + estream_t request, + estream_t response); +static gpg_error_t ssh_handler_lock (ctrl_t ctrl, + estream_t request, + estream_t response); +static gpg_error_t ssh_handler_unlock (ctrl_t ctrl, + estream_t request, + estream_t response); + +static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis); +static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob, + gcry_mpi_t *mpis); +static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob, + gcry_mpi_t *mpis); + + + +/* Global variables. */ + + +/* Associating request types with the corresponding request + handlers. */ + +#define REQUEST_SPEC_DEFINE(id, name) \ + { SSH_REQUEST_##id, ssh_handler_##name, #name } + +static ssh_request_spec_t request_specs[] = + { + REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities), + REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request), + REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity), + REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity), + REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity), + REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities), + REQUEST_SPEC_DEFINE (LOCK, lock), + REQUEST_SPEC_DEFINE (UNLOCK, unlock) + }; +#undef REQUEST_SPEC_DEFINE + + +/* Table holding key type specifications. */ +static ssh_key_type_spec_t ssh_key_types[] = + { + { + "ssh-rsa", "rsa", "nedupq", "en", "dupq", "s", "nedpqu", + ssh_key_modifier_rsa, ssh_signature_encoder_rsa, + SPEC_FLAG_USE_PKCS1V2 + }, + { + "ssh-dss", "dsa", "pqgyx", "pqgy", "x", "rs", "pqgyx", + NULL, ssh_signature_encoder_dsa, + 0 + }, + }; + + + + + + -/* General utility functions. */ +/* + General utility functions. + */ +/* A secure realloc, i.e. it amkese sure to allocate secure memory if + A is NULL. This is required becuase the standard gcry_realloc does + not know whether to allocate secure or normal if NULL is passed as + existing buffer. */ static void * realloc_secure (void *a, size_t n) { @@ -113,10 +198,39 @@ realloc_secure (void *a, size_t n) return p; } -/* Primitive I/O functions. */ + + +static char * +make_cstring (const char *data, size_t data_n) +{ + char *s; + + s = xtrymalloc (data_n + 1); + if (s) + { + strncpy (s, data, data_n); + s[data_n] = 0; + } + + return s; +} + + + + +/* + Primitive I/O functions. + + FIXME: Needs documentation. + + Why are all these functions prefixed with es_ ? They are not part + of libestream, thus they should not use this prefix. + + */ + static gpg_error_t -es_read_byte (estream_t stream, byte_t *b) +es_read_byte (estream_t stream, unsigned char *b) { gpg_error_t err; int ret; @@ -138,8 +252,9 @@ es_read_byte (estream_t stream, byte_t *b) return err; } + static gpg_error_t -es_write_byte (estream_t stream, byte_t b) +es_write_byte (estream_t stream, unsigned char b) { gpg_error_t err; int ret; @@ -153,8 +268,9 @@ es_write_byte (estream_t stream, byte_t b) return err; } + static gpg_error_t -es_read_uint32 (estream_t stream, uint32_t *uint32) +es_read_uint32 (estream_t stream, u32 *uint32) { unsigned char buffer[4]; size_t bytes_read; @@ -170,13 +286,20 @@ es_read_uint32 (estream_t stream, uint32_t *uint32) err = gpg_error (GPG_ERR_EOF); else { - uint32_t n; + u32 n; + + /* FIXME: For what is the cast good for? The proper way of + wrinting it - assuming an unsigned buffer - is: + n = (buffer[0]<< 24)|(buffer[0]<< 16)|(buffer[0]<<8)|(buffer[0]); + + -wk + */ n = (0 - | ((uint32_t) (buffer[0] << 24)) - | ((uint32_t) (buffer[1] << 16)) - | ((uint32_t) (buffer[2] << 8)) - | ((uint32_t) (buffer[3] << 0))); + | ((u32) (buffer[0] << 24)) + | ((u32) (buffer[1] << 16)) + | ((u32) (buffer[2] << 8)) + | ((u32) (buffer[3] << 0))); *uint32 = n; err = 0; } @@ -185,13 +308,15 @@ es_read_uint32 (estream_t stream, uint32_t *uint32) return err; } + static gpg_error_t -es_write_uint32 (estream_t stream, uint32_t uint32) +es_write_uint32 (estream_t stream, u32 uint32) { unsigned char buffer[4]; gpg_error_t err; int ret; + /* Fixme: The 0xFF mask is superfluous. */ buffer[0] = (uint32 >> 24) & 0xFF; buffer[1] = (uint32 >> 16) & 0xFF; buffer[2] = (uint32 >> 8) & 0xFF; @@ -206,6 +331,7 @@ es_write_uint32 (estream_t stream, uint32_t uint32) return err; } + static gpg_error_t es_read_data (estream_t stream, unsigned char *buffer, size_t size) { @@ -227,6 +353,7 @@ es_read_data (estream_t stream, unsigned char *buffer, size_t size) return err; } + static gpg_error_t es_write_data (estream_t stream, const unsigned char *buffer, size_t size) { @@ -242,13 +369,14 @@ es_write_data (estream_t stream, const unsigned char *buffer, size_t size) return err; } + static gpg_error_t es_read_string (estream_t stream, unsigned int secure, - unsigned char **string, uint32_t *string_size) + unsigned char **string, u32 *string_size) { gpg_error_t err; unsigned char *buffer; - uint32_t length; + u32 length; buffer = NULL; @@ -289,6 +417,7 @@ es_read_string (estream_t stream, unsigned int secure, return err; } + static gpg_error_t es_read_cstring (estream_t stream, char **string) { @@ -306,9 +435,11 @@ es_read_cstring (estream_t stream, char **string) return err; } + +/* FIXME: Needs documentation. */ static gpg_error_t es_write_string (estream_t stream, - const unsigned char *string, uint32_t string_n) + const unsigned char *string, u32 string_n) { gpg_error_t err; @@ -323,6 +454,7 @@ es_write_string (estream_t stream, return err; } + static gpg_error_t es_write_cstring (estream_t stream, const char *string) { @@ -334,11 +466,12 @@ es_write_cstring (estream_t stream, const char *string) return err; } + static gpg_error_t es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) { unsigned char *mpi_data; - uint32_t mpi_data_size; + u32 mpi_data_size; gpg_error_t err; gcry_mpi_t mpi; @@ -361,6 +494,7 @@ es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) return err; } + static gpg_error_t es_write_mpi (estream_t stream, gcry_mpi_t mpint) { @@ -383,6 +517,7 @@ es_write_mpi (estream_t stream, gcry_mpi_t mpint) return err; } + static gpg_error_t es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) { @@ -434,6 +569,7 @@ es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) return err; } + static gpg_error_t es_copy (estream_t dst, estream_t src) { @@ -463,9 +599,14 @@ es_copy (estream_t dst, estream_t src) return err; } + -/* MPI lists. */ +/* + + MPI lists. + + */ static void mpint_list_free (gcry_mpi_t *mpi_list) @@ -480,6 +621,7 @@ mpint_list_free (gcry_mpi_t *mpi_list) } } + static gpg_error_t ssh_receive_mpint_list (estream_t stream, int secret, ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list) @@ -593,8 +735,7 @@ ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) return err; } -#define SSH_DSA_SIGNATURE_PADDING 20 -#define SSH_DSA_SIGNATURE_ELEMS 2 + static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) @@ -639,27 +780,9 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) return err; } -#define SPEC_FLAG_USE_PKCS1V2 (1 << 0) - - -/* Table holding key type specifications. */ -static ssh_key_type_spec_t ssh_key_types[] = - { - { - "ssh-rsa", "rsa", "nedupq", "en", "dupq", "s", "nedpqu", - ssh_key_modifier_rsa, ssh_signature_encoder_rsa, - SPEC_FLAG_USE_PKCS1V2 - }, - { - "ssh-dss", "dsa", "pqgyx", "pqgy", "x", "rs", "pqgyx", - NULL, ssh_signature_encoder_dsa, - 0 - }, - }; - - - -/* S-Expressions. */ +/* + S-Expressions. + */ static gpg_error_t ssh_sexp_construct (gcry_sexp_t *sexp, @@ -685,7 +808,9 @@ ssh_sexp_construct (gcry_sexp_t *sexp, elems = key_spec.elems_key_public; elems_n = strlen (elems); - sexp_template_n = 33 + strlen (key_spec.identifier) + (elems_n * 6) - (! secret); + /* FIXME: Why 33? -wk */ + sexp_template_n = (33 + strlen (key_spec.identifier) + + (elems_n * 6) - (!secret)); sexp_template = xtrymalloc (sexp_template_n); if (! sexp_template) { @@ -765,13 +890,13 @@ ssh_sexp_extract (gcry_sexp_t sexp, goto out; } - if ((data_n == 10) && (! strncmp (data, "public-key", 10))) + if (data_n == 10 && !strncmp (data, "public-key", 10)) { is_secret = 0; elems = key_spec.elems_key_public; } - else if (((data_n == 11) && (! strncmp (data, "private-key", 11))) - || ((data_n == 21) && (! strncmp (data, "protected-private-key", 21)))) + else if ((data_n == 11 && !strncmp (data, "private-key", 11)) + || (data_n == 21 && !strncmp (data, "protected-private-key", 21))) { is_secret = 1; elems = key_spec.elems_key_secret; @@ -934,8 +1059,8 @@ ssh_key_type_lookup (const char *ssh_name, const char *name, } static gpg_error_t -ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, int read_comment, - ssh_key_type_spec_t *key_spec) +ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, + int read_comment, ssh_key_type_spec_t *key_spec) { gpg_error_t err; char *key_type; @@ -1093,7 +1218,8 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) if (err) goto out; - err = ssh_convert_key_to_blob (&blob, &blob_n, spec.ssh_identifier, mpi_list); + err = ssh_convert_key_to_blob (&blob, &blob_n, + spec.ssh_identifier, mpi_list); if (err) goto out; @@ -1268,27 +1394,13 @@ key_secret_to_public (gcry_sexp_t *key_public, -static char * -make_cstring (const char *data, size_t data_n) -{ - char *s; - - s = xtrymalloc (data_n + 1); - if (s) - { - strncpy (s, data, data_n); - s[data_n] = 0; - } - - return s; -} - - - -/* Request handler. */ +/* + Request handler. + */ static gpg_error_t -ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) +ssh_handler_request_identities (ctrl_t ctrl, + estream_t request, estream_t response) { const char *key_type; ssh_key_type_spec_t spec; @@ -1298,7 +1410,7 @@ ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t respon char *key_path; unsigned char *buffer; size_t buffer_n; - uint32_t key_counter; + u32 key_counter; estream_t key_blobs; gcry_sexp_t key_secret; gcry_sexp_t key_public; @@ -1468,11 +1580,11 @@ data_hash (unsigned char *data, size_t data_n, return 0; } + static gpg_error_t -data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder, +data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, unsigned char **sig, size_t *sig_n) { - char description[] = "Please provide the passphrase for key `%c':"; gpg_error_t err; gcry_sexp_t signature_sexp; estream_t stream; @@ -1501,7 +1613,9 @@ data_sign (CTRL ctrl, ssh_signature_encoder_t sig_encoder, sig_value = NULL; mpis = NULL; - err = agent_pksign_do (ctrl, description, &signature_sexp, 0); + err = agent_pksign_do (ctrl, + _("Please provide the passphrase " + "for the ssh key `%c':"), &signature_sexp, 0); if (err) goto out; @@ -1632,12 +1746,12 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) unsigned int hash_n; unsigned char key_grip[20]; unsigned char *key_blob; - uint32_t key_blob_size; + u32 key_blob_size; unsigned char *data; unsigned char *sig; size_t sig_n; - uint32_t data_size; - uint32_t flags; + u32 data_size; + u32 flags; const void *p; gpg_error_t err; gpg_error_t ret_err; @@ -1886,6 +2000,11 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) if (err) goto out; + + /* FIXME: What the hell is that: Never have use sprintf in that way. + When marking a string translatbale you might get a buffer + overflow. We have never done this elsewhere. Using [x]asprintf + is the right way!! */ description_length = 95 + (comment ? strlen (comment) : 0); description = malloc (description_length); if (! description) @@ -1896,7 +2015,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) else sprintf (description, "Please provide the passphrase, which should be used " - "for protecting the received secret key `%s':", + "for protecting the received secret key `%s':", comment ? comment : ""); err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase); @@ -1954,7 +2073,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) gpg_error_t ret_err; gpg_error_t err; gcry_sexp_t key; - byte_t b; + unsigned char b; int confirm; int ttl; @@ -1980,7 +2099,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) { case SSH_OPT_CONSTRAIN_LIFETIME: { - uint32_t n = 0; + u32 n = 0; err = es_read_uint32 (request, &n); if (! err) @@ -2017,10 +2136,11 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) } static gpg_error_t -ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, estream_t response) +ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, + estream_t response) { unsigned char *key_blob; - uint32_t key_blob_size; + u32 key_blob_size; gcry_sexp_t key; gpg_error_t ret_err; gpg_error_t err; @@ -2065,7 +2185,8 @@ ssh_identities_remove_all (void) } static gpg_error_t -ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, estream_t response) +ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, + estream_t response) { gpg_error_t ret_err; gpg_error_t err; @@ -2083,7 +2204,7 @@ ssh_lock (void) gpg_error_t err; /* FIXME */ - log_error ("[gpg-agent/ssh] lock command is not implemented\n"); + log_error (_("lock command is not implemented\n")); err = 0; return err; @@ -2094,7 +2215,7 @@ ssh_unlock (void) { gpg_error_t err; - log_error ("[gpg-agent/ssh] unlock command is not implemented\n"); + log_error (_("unlock command is not implemented\n")); err = 0; return err; @@ -2128,39 +2249,19 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) -/* Associating request types with the corresponding request - handlers. */ - -#define REQUEST_SPEC_DEFINE(id, name) \ - { SSH_REQUEST_##id, ssh_handler_##name, #name } - -static ssh_request_spec_t request_specs[] = - { - REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities), - REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request), - REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity), - REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity), - REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity), - REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities), - REQUEST_SPEC_DEFINE (LOCK, lock), - REQUEST_SPEC_DEFINE (UNLOCK, unlock) - }; - - - static int ssh_request_process (ctrl_t ctrl, estream_t stream_sock) { estream_t response; estream_t request; - byte_t request_type; + unsigned char request_type; gpg_error_t err; unsigned int i; int send_err; int ret; unsigned char *request_data; - uint32_t request_data_size; - uint32_t response_size; + u32 request_data_size; + u32 response_size; request_data = NULL; response = NULL; @@ -2170,15 +2271,22 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) /* Create memory streams for request/response data. The entire request will be stored in secure memory, since it might contain secret key material. The response does not have to be stored in - secure memory, since we never give out secret keys. */ + secure memory, since we never give out secret keys. + + FIXME: This is a pretty good DoS. We only have a limited amount + of secure memory, we can't trhow hin everything we get from a + client -wk */ /* Retrieve request. */ err = es_read_string (stream_sock, 1, &request_data, &request_data_size); if (err) goto out; - if (opt.verbose) - log_debug ("[gpg-agent/ssh] Received request of length: %u\n", + if (opt.verbose) /* FIXME: using log_debug is not good with + verbose. log_debug should only be used in + debugging mode or in sitattions which are + unexpected. */ + log_debug ("received request of length: %u\n", request_data_size); request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); @@ -2217,14 +2325,14 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) break; if (i == DIM (request_specs)) { - log_debug ("[gpg-agent/ssh] request %u is not supported\n", + log_debug ("request %u is not supported\n", request_type); send_err = 1; goto out; } if (opt.verbose) - log_debug ("[gpg-agent/ssh] Executing request handler: %s (%u)\n", + log_debug ("executing request handler: %s (%u)\n", request_specs[i].identifier, request_specs[i].type); err = (*request_specs[i].handler) (ctrl, request, response); @@ -2260,7 +2368,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) out: if (err && es_feof (stream_sock)) - log_error ("[gpg-agent/ssh] Error occured while processing request: %s\n", + log_error ("error occured while processing request: %s\n", gpg_strerror (err)); if (send_err) @@ -2301,10 +2409,10 @@ start_command_handler_ssh (int sock_client) /* Create stream from socket. */ stream_sock = es_fdopen (sock_client, "r+"); - if (! stream_sock) + if (!stream_sock) { err = gpg_error_from_errno (errno); - log_error ("[gpg-agent/ssh] Failed to create stream from socket: %s\n", + log_error (_("failed to create stream from socket: %s\n"), gpg_strerror (err)); goto out; } @@ -2314,14 +2422,13 @@ start_command_handler_ssh (int sock_client) if (ret) { err = gpg_error_from_errno (errno); - log_error ("[gpg-agent/ssh] Failed to disable buffering " - "on socket stream: %s\n", gpg_strerror (err)); + log_error (_("failed to disable buffering " + "on socket stream: %s\n"), gpg_strerror (err)); goto out; } while (1) { - /* Process request. */ bad = ssh_request_process (&ctrl, stream_sock); if (bad) break; diff --git a/agent/findkey.c b/agent/findkey.c index d39d3aae3..896cb880e 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -143,101 +143,79 @@ try_unprotect_cb (struct pin_entry_info_s *pi) /* Modify a Key description, replacing certain special format characters. List of currently supported replacements: - %% -> % - %c -> <COMMENT>. */ -static int -modify_description (const char *description, - const char *comment, size_t comment_length, - char **description_modified) -{ - size_t description_length; - size_t description_new_length; - gpg_error_t err; - char *description_new; - unsigned int i, j; - unsigned int special; - - description_length = strlen (description); - description_new_length = description_length; - description_new = NULL; - - /* Calculate length. */ - special = 0; - for (i = 0; i < description_length; i++) - { - if (description[i] == '%') - special = 1; - else - { - if (special) - { - description_new_length -= 2; - switch (description[i]) - { - case 'c': - /* Comment. */ - description_new_length += comment_length; - break; - - case '%': - description_new_length += 1; - break; - } - special = 0; - } - } - } - - /* Allocate. */ - description_new = xtrymalloc (description_new_length + 1); - if (! description_new) - { - err = gpg_error_from_errno (errno); - goto out; - } + %% - Replaced by a single % + %c - Replaced by the content of COMMENT. - /* Fill. */ - for (i = j = 0; i < description_length; i++) + The functions returns 0 on success or an error code. On success a + newly allocated string is stored at the address of RESULT. + */ +static gpg_error_t +modify_description (const char *in, const char *comment, char **result) +{ + size_t comment_length; + size_t in_len; + size_t out_len; + char *out; + size_t i; + int special, pass; + + comment_length = strlen (comment); + in_len = strlen (in); + + /* First pass calculates the length, second pass does the actual + copying. */ + out = NULL; + out_len = 0; + for (pass=0; pass < 2; pass++) { - if (description[i] == '%') - special = 1; - else - { - if (special) - { - switch (description[i]) - { - case 'c': - /* Comment. */ - if (comment) - { - strncpy (description_new + j, comment, comment_length); - j += comment_length; - } - break; - - case '%': - description_new[j] = '%'; - j++; - break; - } - special = 0; - } - else - { - description_new[j] = description[i]; - j++; - } - } + special = 0; + for (i = 0; i < in_len; i++) + { + if (in[i] == '%') + special = 1; + else if (special) + { + special = 0; + switch (in[i]) + { + case '%': + out_len++; + if (out) + *out++ = '%'; + break; + + case 'c': /* Comment. */ + out_len += comment_length; + if (out && comment_length) + { + memcpy (out, comment, comment_length); + out += comment_length; + } + break; + + default: /* Invalid special sequences are ignored. */ + break; + } + } + else + { + out_len++; + if (out) + *out++ = in[i]; + } + } + + if (!pass) + { + *result = out = xtrymalloc (out_len + 1); + if (!out) + return gpg_error_from_errno (errno); + } } - description_new[j] = 0; - *description_modified = description_new; - err = 0; - - out: - - return err; + *out = 0; + assert (*result + out_len == out); + return 0; } @@ -398,35 +376,51 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, gcry_sexp_t comment_sexp; size_t comment_length; char *desc_text_final; - const char *comment; - + const char *comment = NULL; + + /* Note, that we will take the comment as a C styring for + display purposes; i.e. all stuff beyond a Nul character is + ignored. */ comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0); if (comment_sexp) comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length); - else + if (!comment) { - comment = NULL; + comment = ""; comment_length = 0; } + desc_text_final = NULL; if (desc_text) { - rc = modify_description (desc_text, - comment, comment_length, &desc_text_final); - if (rc) - log_error ("failed to modify description: %s\n", gpg_strerror (rc)); + if (comment[comment_length]) + { + /* Not a C-string; create one. We might here allocate + more than actually displayed but well, that + shouldn't be a problem. */ + char *tmp = xtrymalloc (comment_length+1); + if (!tmp) + rc = gpg_error_from_errno (errno); + else + { + memcpy (tmp, comment, comment_length); + tmp[comment_length] = 0; + rc = modify_description (desc_text, tmp, &desc_text_final); + xfree (tmp); + } + } + else + rc = modify_description (desc_text, comment, &desc_text_final); } - else - desc_text_final = NULL; - if (! rc) + if (!rc) { rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache); if (rc) log_error ("failed to unprotect the secret key: %s\n", gpg_strerror (rc)); } - + gcry_sexp_release (comment_sexp); xfree (desc_text_final); } diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 9f97fb6d7..d8b891e5f 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -51,6 +51,7 @@ #include "../jnlib/w32-afunix.h" #endif + enum cmd_and_opt_values { aNull = 0, oCsh = 'c', @@ -146,7 +147,7 @@ static ARGPARSE_OPTS opts[] = { N_("allow clients to mark keys as \"trusted\"")}, { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, - { oSSHSupport, "ssh-support", 0, "Enable SSH-Agent emulation" }, + { oSSHSupport, "ssh-support", 0, N_("enable secure ssh-agent emulation") }, {0} }; @@ -163,7 +164,7 @@ static int shutdown_pending; /* It is possible that we are currently running under setuid permissions */ static int maybe_setuid = 1; -/* Name of the communication socket */ +/* Name of the communication socket used for native gpg-agent requests. */ static char *socket_name; /* Name of the communication socket used for ssh-agent-emulation. */ @@ -186,8 +187,15 @@ static const char *debug_level; the log file after a SIGHUP if it didn't changed. Malloced. */ static char *current_logfile; -/* Local prototypes. */ +/* + Local prototypes. + */ + +static char *create_socket_name (int use_standard_socket, + char *standard_name, char *template); +static int create_server_socket (int is_standard_name, const char *name); static void create_directories (void); + #ifdef USE_GNU_PTH static void handle_connections (int listen_fd, int listen_fd_ssh); /* Pth wrapper function definitions. */ @@ -198,6 +206,12 @@ static int check_for_running_agent (int); + +/* + Functions. + */ + + static const char * my_strusage (int level) { @@ -302,8 +316,9 @@ set_debug (void) } +/* Helper for cleanup to remove one socket with NAME. */ static void -cleanup_do (char *name) +remove_socket (char *name) { if (name && *name) { @@ -324,8 +339,8 @@ cleanup_do (char *name) static void cleanup (void) { - cleanup_do (socket_name); - cleanup_do (socket_name_ssh); + remove_socket (socket_name); + remove_socket (socket_name_ssh); } @@ -417,105 +432,6 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) } -static void -create_socket_name (char **name, int standard_socket, - struct sockaddr_un *serv_addr, - char *standard_identifier, char *identifier) -{ - char *p; - - if (standard_socket) - *name = make_filename (opt.homedir, standard_identifier, NULL); - else - { - *name = xstrdup (identifier); - p = strrchr (*name, '/'); - if (! p) - BUG (); - *p = 0; - if (!mkdtemp (*name)) - { - log_error (_("can't create directory `%s': %s\n"), - *name, strerror (errno)); - exit (1); - } - *p = '/'; - } - - if (strchr (*name, PATHSEP_C)) - { - log_error ("`%s' are not allowed in the socket name\n", PATHSEP_S); - exit (1); - } - if (strlen (*name) + 1 >= sizeof serv_addr->sun_path) - { - log_error ("name of socket too long\n"); - exit (1); - } -} - -static int -create_server_socket (struct sockaddr_un *serv_addr, - int standard_socket, const char *name) -{ - socklen_t len; - int fd; - int rc; - -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror (errno)); - exit (1); - } - - memset (serv_addr, 0, sizeof *serv_addr); - serv_addr->sun_family = AF_UNIX; - strcpy (serv_addr->sun_path, name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen (serv_addr->sun_path) + 1); - -#ifdef HAVE_W32_SYSTEM - rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); - if ((rc == -1) && standard_socket) - { - remove (name); - rc = bind (fd, (struct sockaddr*) serv_addr, len); - } -#else - rc = bind (fd, (struct sockaddr*) serv_addr, len); - if ((rc == -1) && standard_socket && (errno == EADDRINUSE)) - { - remove (name); - rc = bind (fd, (struct sockaddr*) serv_addr, len); - } -#endif - if (rc == -1) - { - log_error ("error binding socket to `%s': %s\n", - serv_addr->sun_path, strerror (errno)); - close (fd); - exit (1); - } - - if (listen (fd, 5 ) == -1) - { - log_error ("listen() failed: %s\n", strerror (errno)); - close (fd); - exit (1); - } - - if (opt.verbose) - log_info ("listening on socket `%s'\n", socket_name); - - return fd; -} - - int main (int argc, char **argv ) { @@ -865,8 +781,6 @@ main (int argc, char **argv ) int fd; int fd_ssh; pid_t pid; - struct sockaddr_un serv_addr; - struct sockaddr_un serv_addr_ssh; /* Remove the DISPLAY variable so that a pinentry does not default to a specific display. There is still a default @@ -877,27 +791,27 @@ main (int argc, char **argv ) unsetenv ("DISPLAY"); #endif - /* Create the socket name . */ - create_socket_name (&socket_name, standard_socket, &serv_addr, - "S.gpg-agent", "/tmp/gpg-XXXXXX/S.gpg-agent"); + + /* Create the sockets. */ + socket_name = create_socket_name (standard_socket, + "S.gpg-agent", + "/tmp/gpg-XXXXXX/S.gpg-agent"); if (opt.ssh_support) - create_socket_name (&socket_name_ssh, standard_socket, &serv_addr_ssh, - "S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh"); + socket_name_ssh = create_socket_name (standard_socket, + "S.gpg-agent.ssh", + "/tmp/gpg-XXXXXX/S.gpg-agent.ssh"); - fd = create_server_socket (&serv_addr, - standard_socket, socket_name); + fd = create_server_socket (standard_socket, socket_name); if (opt.ssh_support) - fd_ssh = create_server_socket (&serv_addr_ssh, - standard_socket, socket_name_ssh); + fd_ssh = create_server_socket (standard_socket, socket_name_ssh); else - /* Make the compiler happy. */ fd_ssh = -1; + fflush (NULL); #ifdef HAVE_W32_SYSTEM pid = getpid (); printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); - printf ("set GPG_AGENT_INFO=%s;%lu;1\n", socket_name, (ulong)pid); #else /*!HAVE_W32_SYSTEM*/ pid = fork (); if (pid == (pid_t)-1) @@ -911,7 +825,7 @@ main (int argc, char **argv ) close (fd); - /* create the info string: <name>:<pid>:<protocol_version> */ + /* Create the info string: <name>:<pid>:<protocol_version> */ if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1", socket_name, (ulong)pid ) < 0) { @@ -937,13 +851,14 @@ main (int argc, char **argv ) } } - *socket_name = 0; /* don't let cleanup() remove the socket - + *socket_name = 0; /* Don't let cleanup() remove the socket - the child should do this from now on */ if (opt.ssh_support) *socket_name_ssh = 0; + if (argc) - { /* run the program given on the commandline */ + { /* Run the program given on the commandline. */ if (putenv (infostr)) { log_error ("failed to set environment: %s\n", @@ -972,18 +887,18 @@ main (int argc, char **argv ) } else { - /* print the environment string, so that the caller can use + /* Print the environment string, so that the caller can use shell's eval to set it */ if (csh_style) { *strchr (infostr, '=') = ' '; - printf ( "setenv %s\n", infostr); + printf ("setenv %s\n", infostr); if (opt.ssh_support) { *strchr (infostr_ssh_sock, '=') = ' '; - printf ( "setenv %s\n", infostr_ssh_sock); + printf ("setenv %s\n", infostr_ssh_sock); *strchr (infostr_ssh_pid, '=') = ' '; - printf ( "setenv %s\n", infostr_ssh_pid); + printf ("setenv %s\n", infostr_ssh_pid); } } else @@ -991,10 +906,11 @@ main (int argc, char **argv ) printf ( "%s; export GPG_AGENT_INFO;\n", infostr); if (opt.ssh_support) { - printf ( "%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock); - printf ( "%s; export SSH_AGENT_PID;\n", infostr_ssh_pid); + printf ("%s; export SSH_AUTH_SOCK;\n", infostr_ssh_sock); + printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid); } } + /* Note: teh standard free is here correct. */ free (infostr); if (opt.ssh_support) { @@ -1003,8 +919,8 @@ main (int argc, char **argv ) } exit (0); } - /*NEVER REACHED*/ - } /* end parent */ + /*NOTREACHED*/ + } /* End parent */ /* This is the child @@ -1181,6 +1097,125 @@ reread_configuration (void) } + + +/* Create a name for the socket. With USE_STANDARD_SOCKET given as + true ising STANDARD_NAME in the home directory or if given has + false from the mkdir type name TEMPLATE. In the latter case a + unique name in a unique new directory will be created. In both + cases check for valid characters as well as against a maximum + allowed length for a unix domain socket is done. The function + terminates the process in case of an error. Retunrs: Pointer to an + allcoated string with the absolute name of the socket used. */ +static char * +create_socket_name (int use_standard_socket, + char *standard_name, char *template) +{ + char *name, *p; + + if (use_standard_socket) + name = make_filename (opt.homedir, standard_name, NULL); + else + { + name = xstrdup (template); + p = strrchr (name, '/'); + if (!p) + BUG (); + *p = 0; + if (!mkdtemp (name)) + { + log_error (_("can't create directory `%s': %s\n"), + name, strerror (errno)); + agent_exit (2); + } + *p = '/'; + } + + if (strchr (name, PATHSEP_C)) + { + log_error (("`%s' are not allowed in the socket name\n"), PATHSEP_S); + agent_exit (2); + } + if (strlen (name) + 1 >= DIMof (struct sockaddr_un, sun_path) ) + { + log_error (_("name of socket too long\n")); + agent_exit (2); + } + return name; +} + + + +/* Create a Unix domain socket with NAME. IS_STANDARD_NAME indicates + whether a non-random socket is used. Returns the filedescriptor or + terminates the process in case of an error. */ +static int +create_server_socket (int is_standard_name, const char *name) +{ + struct sockaddr_un *serv_addr; + socklen_t len; + int fd; + int rc; + +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else + fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif + if (fd == -1) + { + log_error (_("can't create socket: %s\n"), strerror (errno)); + agent_exit (2); + } + + + memset (serv_addr, 0, sizeof *serv_addr); + serv_addr->sun_family = AF_UNIX; + assert (strlen (name) + 1 < sizeof (serv_addr->sun_path)); + strcpy (serv_addr->sun_path, name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen (serv_addr->sun_path) + 1); + +#ifdef HAVE_W32_SYSTEM + rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); + if (is_standard_name && rc == -1 ) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#else + rc = bind (fd, (struct sockaddr*) serv_addr, len); + if (is_standard_name && rc == -1 && errno == EADDRINUSE) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#endif + if (rc == -1) + { + log_error (_("error binding socket to `%s': %s\n"), + serv_addr->sun_path, strerror (errno)); + close (fd); + agent_exit (2); + } + + if (listen (fd, 5 ) == -1) + { + log_error (_("listen() failed: %s\n"), strerror (errno)); + close (fd); + agent_exit (2); + } + + if (opt.verbose) + log_info (_("listening on socket `%s'\n"), serv_addr->sun_path); + + return fd; +} + + +/* Check that the directory for storing the private keys exists and + create it if not. This function won't fail as it is only a + convenience function and not strictly necessary. */ static void create_private_keys_directory (const char *home) { @@ -1218,7 +1253,7 @@ create_directories (void) const char *defhome = GNUPG_DEFAULT_HOMEDIR; char *home; - home = make_filename (opt.homedir, NULL); + home = make_filename (opt.homedir, NULL); if ( stat (home, &statbuf) ) { if (errno == ENOENT) @@ -1248,11 +1283,11 @@ create_directories (void) } } else - log_error ("error stat-ing `%s': %s\n", home, strerror (errno)); + log_error (_("stat() failed for `%s': %s\n"), home, strerror (errno)); } else if ( !S_ISDIR(statbuf.st_mode)) { - log_error ("can't use `%s' as home directory\n", home); + log_error (_("can't use `%s' as home directory\n"), home); } else /* exists and is a directory. */ { @@ -1315,13 +1350,14 @@ handle_signal (int signo) } +/* This is the standard connection thread's main function. */ static void * start_connection_thread (void *arg) { int fd = (int)arg; if (opt.verbose) - log_info ("handler for fd %d started\n", fd); + log_info (_("handler for fd %d started\n"), fd); /* FIXME: Move this housekeeping into a ticker function. Calling it for each connection should work but won't work anymore if our @@ -1330,31 +1366,33 @@ start_connection_thread (void *arg) start_command_handler (-1, fd); if (opt.verbose) - log_info ("handler for fd %d terminated\n", fd); + log_info (_("handler for fd %d terminated\n"), fd); return NULL; } + +/* This is the ssh connection thread's main function. */ static void * start_connection_thread_ssh (void *arg) { int fd = (int)arg; if (opt.verbose) - log_info ("ssh handler for fd %d started\n", fd); + log_info (_("ssh handler for fd %d started\n"), fd); - /* FIXME: Move this housekeeping into a ticker function. Calling it - for each connection should work but won't work anymore if our - cleints start to keep connections. */ agent_trustlist_housekeeping (); start_command_handler_ssh (fd); if (opt.verbose) - log_info ("ssh handler for fd %d terminated\n", fd); + log_info (_("ssh handler for fd %d terminated\n"), fd); return NULL; } + +/* Connection handler loop. Wait for coecntion requests and spawn a + thread after accepting a connection. */ static void handle_connections (int listen_fd, int listen_fd_ssh) { @@ -1363,7 +1401,7 @@ handle_connections (int listen_fd, int listen_fd_ssh) sigset_t sigs; int signo; struct sockaddr_un paddr; - socklen_t plen = sizeof ( paddr ); + socklen_t plen; fd_set fdset, read_fdset; int ret; int fd; @@ -1406,74 +1444,62 @@ handle_connections (int listen_fd, int listen_fd_ssh) continue; } + /* POSIX says that fd_set should be implemented as a structure, + thus a simple assignment is fine to copy the entire set. */ read_fdset = fdset; - ret = pth_select (FD_SETSIZE, &read_fdset, NULL, NULL, NULL); + + ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev); if (ret == -1) { - log_error ("pth_select failed: %s - waiting 1s\n", - strerror (errno)); - pth_sleep (1); + log_error (_("pth_select failed: %s - waiting 1s\n"), + strerror (errno)); + pth_sleep (1); continue; } - + + if (pth_event_occurred (ev)) + { + handle_signal (signo); + } if (FD_ISSET (listen_fd, &read_fdset)) { - fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + plen = sizeof paddr; + fd = pth_accept (listen_fd, (struct sockaddr *)&paddr, &plen); if (fd == -1) { -#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ - if (pth_event_status (ev) == PTH_STATUS_OCCURRED) -#else - if (pth_event_occurred (ev)) -#endif - { - handle_signal (signo); - continue; - } - log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); - pth_sleep(1); - continue; + log_error ("accept failed: %s\n", strerror (errno)); } - - if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + else if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) { log_error ("error spawning connection handler: %s\n", strerror (errno) ); close (fd); } + fd = -1; } - else if ((listen_fd_ssh != -1) && FD_ISSET (listen_fd_ssh, &read_fdset)) + + if (listen_fd_ssh != -1 && FD_ISSET (listen_fd_ssh, &read_fdset)) { - fd = pth_accept_ev (listen_fd_ssh, (struct sockaddr *)&paddr, &plen, ev); + plen = sizeof paddr; + fd = pth_accept (listen_fd_ssh, (struct sockaddr *)&paddr, &plen); if (fd == -1) { -#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ - if (pth_event_status (ev) == PTH_STATUS_OCCURRED) -#else - if (pth_event_occurred (ev)) -#endif - { - handle_signal (signo); - continue; - } - log_error ("accept failed: %s - waiting 1s\n", strerror (errno)); - pth_sleep(1); - continue; + log_error ("accept failed for ssh: %s\n", strerror (errno)); } - - if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) + else if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) { - log_error ("error spawning connection handler: %s\n", + log_error ("error spawning ssh connection handler: %s\n", strerror (errno) ); close (fd); } + fd = -1; } } pth_event_free (ev, PTH_FREE_ALL); cleanup (); - log_info ("%s %s stopped\n", strusage(11), strusage(13)); + log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); } #endif /*USE_GNU_PTH*/ @@ -1527,6 +1553,7 @@ check_for_running_agent (int mode) else /* MODE != 0 */ { infostr = make_filename (opt.homedir, "S.gpg-agent", NULL); + pid = (pid_t)(-1); } diff --git a/common/estream.h b/common/estream.h index 382b6da84..c201b666a 100644 --- a/common/estream.h +++ b/common/estream.h @@ -198,4 +198,5 @@ estream_t es_tmpfile (void); void es_opaque_set (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque); void *es_opaque_get (estream_t stream); -#endif +#endif /*ESTREAM_H*/ + -- cgit v1.2.3 From c4b986c7315a3f288a177cbdc15912b4f5a9fce7 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Mon, 14 Feb 2005 20:07:01 +0000 Subject: 2005-02-14 Moritz Schulte <moritz@g10code.com> * command-ssh.c (es_read_byte): Renamed to ... (stream_es_read_byte): ... this; changed callers. (es_write_byte): Renamed to ... (stream_write_byte): ... this; changed callers. (es_read_uint32): Renamed to ... (stream_read_uint32): ... this; changed callers. (es_write_uint32): Renamed to ... (stream_write_uint32): ... this; changed callers. (es_read_data): Renamed to ... (stream_read_data): ... this; changed callers. (es_write_data): Renamed to ... (stream_write_data): ... this; changed callers. (es_read_string): Renamed to ... (stream_read_string): ... this; changed callers. (es_read_cstring): Renamed to ... (stream_read_cstring): ... this; changed callers. (es_write_string): Renamed to ... (stream_write_string): ... this; changed callers. (es_write_cstring): Renamed to ... (stream_write_cstring): ... this; changed callers. (es_read_mpi): Renamed to ... (stream_read_mpi): ... this; changed callers. (es_write_mpi): Renamed to ... (stream_write_mpi): ... this; changed callers. (es_copy): Renamed to ... (stream_copy): ... this; changed callers. (es_read_file): Renamed to ... (file_to_buffer): ... this; changed callers. (ssh_identity_register): Removed variable description_length; changed code to use asprintf for description. (stream_write_uint32): Do not filter out the last byte of shift expression. --- agent/ChangeLog | 35 ++++++++ agent/command-ssh.c | 249 +++++++++++++++++++++++++--------------------------- 2 files changed, 156 insertions(+), 128 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 3bd779256..09cf0cdbc 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,38 @@ +2005-02-14 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (es_read_byte): Renamed to ... + (stream_es_read_byte): ... this; changed callers. + (es_write_byte): Renamed to ... + (stream_write_byte): ... this; changed callers. + (es_read_uint32): Renamed to ... + (stream_read_uint32): ... this; changed callers. + (es_write_uint32): Renamed to ... + (stream_write_uint32): ... this; changed callers. + (es_read_data): Renamed to ... + (stream_read_data): ... this; changed callers. + (es_write_data): Renamed to ... + (stream_write_data): ... this; changed callers. + (es_read_string): Renamed to ... + (stream_read_string): ... this; changed callers. + (es_read_cstring): Renamed to ... + (stream_read_cstring): ... this; changed callers. + (es_write_string): Renamed to ... + (stream_write_string): ... this; changed callers. + (es_write_cstring): Renamed to ... + (stream_write_cstring): ... this; changed callers. + (es_read_mpi): Renamed to ... + (stream_read_mpi): ... this; changed callers. + (es_write_mpi): Renamed to ... + (stream_write_mpi): ... this; changed callers. + (es_copy): Renamed to ... + (stream_copy): ... this; changed callers. + (es_read_file): Renamed to ... + (file_to_buffer): ... this; changed callers. + (ssh_identity_register): Removed variable description_length; + changed code to use asprintf for description. + (stream_write_uint32): Do not filter out the last byte of shift + expression. + 2005-02-03 Werner Koch <wk@g10code.com> * agent.h (agent_exit): Add JNLIB_GCC_A_NR to indicate that this diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 390bfe92a..68cca909b 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -181,8 +181,8 @@ static ssh_key_type_spec_t ssh_key_types[] = General utility functions. */ -/* A secure realloc, i.e. it amkese sure to allocate secure memory if - A is NULL. This is required becuase the standard gcry_realloc does +/* A secure realloc, i.e. it makes sure to allocate secure memory if A + is NULL. This is required becuase the standard gcry_realloc does not know whether to allocate secure or normal if NULL is passed as existing buffer. */ static void * @@ -220,17 +220,12 @@ make_cstring (const char *data, size_t data_n) /* Primitive I/O functions. - - FIXME: Needs documentation. - - Why are all these functions prefixed with es_ ? They are not part - of libestream, thus they should not use this prefix. - */ +/* Read a byte from STREAM, store it in B. */ static gpg_error_t -es_read_byte (estream_t stream, unsigned char *b) +stream_read_byte (estream_t stream, unsigned char *b) { gpg_error_t err; int ret; @@ -252,9 +247,9 @@ es_read_byte (estream_t stream, unsigned char *b) return err; } - +/* Write the byte contained in B to STREAM. */ static gpg_error_t -es_write_byte (estream_t stream, unsigned char b) +stream_write_byte (estream_t stream, unsigned char b) { gpg_error_t err; int ret; @@ -268,9 +263,9 @@ es_write_byte (estream_t stream, unsigned char b) return err; } - +/* Read a uint32 from STREAM, store it in UINT32. */ static gpg_error_t -es_read_uint32 (estream_t stream, u32 *uint32) +stream_read_uint32 (estream_t stream, u32 *uint32) { unsigned char buffer[4]; size_t bytes_read; @@ -308,9 +303,9 @@ es_read_uint32 (estream_t stream, u32 *uint32) return err; } - +/* Write the uint32 contained in UINT32 to STREAM. */ static gpg_error_t -es_write_uint32 (estream_t stream, u32 uint32) +stream_write_uint32 (estream_t stream, u32 uint32) { unsigned char buffer[4]; gpg_error_t err; @@ -331,9 +326,9 @@ es_write_uint32 (estream_t stream, u32 uint32) return err; } - +/* Read SIZE bytes from STREAM into BUFFER. */ static gpg_error_t -es_read_data (estream_t stream, unsigned char *buffer, size_t size) +stream_read_data (estream_t stream, unsigned char *buffer, size_t size) { gpg_error_t err; size_t bytes_read; @@ -353,9 +348,9 @@ es_read_data (estream_t stream, unsigned char *buffer, size_t size) return err; } - +/* Write SIZE bytes from BUFFER to STREAM. */ static gpg_error_t -es_write_data (estream_t stream, const unsigned char *buffer, size_t size) +stream_write_data (estream_t stream, const unsigned char *buffer, size_t size) { gpg_error_t err; int ret; @@ -369,10 +364,12 @@ es_write_data (estream_t stream, const unsigned char *buffer, size_t size) return err; } - +/* Read a binary string from STREAM into STRING, store size of string + in STRING_SIZE; depending on SECURE use secure memory for + string. */ static gpg_error_t -es_read_string (estream_t stream, unsigned int secure, - unsigned char **string, u32 *string_size) +stream_read_string (estream_t stream, unsigned int secure, + unsigned char **string, u32 *string_size) { gpg_error_t err; unsigned char *buffer; @@ -381,7 +378,7 @@ es_read_string (estream_t stream, unsigned int secure, buffer = NULL; /* Read string length. */ - err = es_read_uint32 (stream, &length); + err = stream_read_uint32 (stream, &length); if (err) goto out; @@ -399,7 +396,7 @@ es_read_string (estream_t stream, unsigned int secure, } /* Read data. */ - err = es_read_data (stream, buffer, length); + err = stream_read_data (stream, buffer, length); if (err) goto out; @@ -417,14 +414,14 @@ es_read_string (estream_t stream, unsigned int secure, return err; } - +/* Read a C-string from STREAM, store copy in STRING. */ static gpg_error_t -es_read_cstring (estream_t stream, char **string) +stream_read_cstring (estream_t stream, char **string) { unsigned char *buffer; gpg_error_t err; - err = es_read_string (stream, 0, &buffer, NULL); + err = stream_read_string (stream, 0, &buffer, NULL); if (err) goto out; @@ -436,39 +433,40 @@ es_read_cstring (estream_t stream, char **string) } -/* FIXME: Needs documentation. */ +/* Write a binary string from STRING of size STRING_N to STREAM. */ static gpg_error_t -es_write_string (estream_t stream, - const unsigned char *string, u32 string_n) +stream_write_string (estream_t stream, + const unsigned char *string, u32 string_n) { gpg_error_t err; - err = es_write_uint32 (stream, string_n); + err = stream_write_uint32 (stream, string_n); if (err) goto out; - err = es_write_data (stream, string, string_n); + err = stream_write_data (stream, string, string_n); out: return err; } - +/* Write a C-string from STRING to STREAM. */ static gpg_error_t -es_write_cstring (estream_t stream, const char *string) +stream_write_cstring (estream_t stream, const char *string) { gpg_error_t err; - err = es_write_string (stream, - (const unsigned char *) string, strlen (string)); + err = stream_write_string (stream, + (const unsigned char *) string, strlen (string)); return err; } - +/* Read an MPI from STREAM, store it in MPINT. Depending on SECURE + use secure memory. */ static gpg_error_t -es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) +stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) { unsigned char *mpi_data; u32 mpi_data_size; @@ -477,7 +475,7 @@ es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) mpi_data = NULL; - err = es_read_string (stream, secure, &mpi_data, &mpi_data_size); + err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size); if (err) goto out; @@ -494,9 +492,9 @@ es_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint) return err; } - +/* Write the MPI contained in MPINT to STREAM. */ static gpg_error_t -es_write_mpi (estream_t stream, gcry_mpi_t mpint) +stream_write_mpi (estream_t stream, gcry_mpi_t mpint) { unsigned char *mpi_buffer; size_t mpi_buffer_n; @@ -508,7 +506,7 @@ es_write_mpi (estream_t stream, gcry_mpi_t mpint) if (err) goto out; - err = es_write_string (stream, mpi_buffer, mpi_buffer_n); + err = stream_write_string (stream, mpi_buffer, mpi_buffer_n); out: @@ -517,9 +515,42 @@ es_write_mpi (estream_t stream, gcry_mpi_t mpint) return err; } +/* Copy data from SRC to DST until EOF is reached. */ +static gpg_error_t +stream_copy (estream_t dst, estream_t src) +{ + char buffer[BUFSIZ]; + size_t bytes_read; + gpg_error_t err; + int ret; + + err = 0; + while (1) + { + ret = es_read (src, buffer, sizeof (buffer), &bytes_read); + if (ret || (! bytes_read)) + { + if (ret) + err = gpg_error_from_errno (errno); + break; + } + ret = es_write (dst, buffer, bytes_read, NULL); + if (ret) + { + err = gpg_error_from_errno (errno); + break; + } + } + + return err; +} + +/* Read the content of the file specified by FILENAME into a newly + create buffer, which is to be stored in BUFFER; store length of + buffer in BUFFER_N. */ static gpg_error_t -es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) +file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n) { unsigned char *buffer_new; struct stat statbuf; @@ -551,7 +582,7 @@ es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) goto out; } - err = es_read_data (stream, buffer_new, statbuf.st_size); + err = stream_read_data (stream, buffer_new, statbuf.st_size); if (err) goto out; @@ -570,36 +601,6 @@ es_read_file (const char *filename, unsigned char **buffer, size_t *buffer_n) } -static gpg_error_t -es_copy (estream_t dst, estream_t src) -{ - char buffer[BUFSIZ]; - size_t bytes_read; - gpg_error_t err; - int ret; - - err = 0; - while (1) - { - ret = es_read (src, buffer, sizeof (buffer), &bytes_read); - if (ret || (! bytes_read)) - { - if (ret) - err = gpg_error_from_errno (errno); - break; - } - ret = es_write (dst, buffer, bytes_read, NULL); - if (ret) - { - err = gpg_error_from_errno (errno); - break; - } - } - - return err; -} - - /* @@ -661,7 +662,7 @@ ssh_receive_mpint_list (estream_t stream, int secret, for (i = 0; i < elems_n; i++) { elem_is_secret = strchr (elems_secret, elems[i]) ? 1 : 0; - err = es_read_mpi (stream, elem_is_secret, &mpis[i]); + err = stream_read_mpi (stream, elem_is_secret, &mpis[i]); if (err) break; } @@ -727,7 +728,7 @@ ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) if (err) goto out; - err = es_write_string (signature_blob, data, data_n); + err = stream_write_string (signature_blob, data, data_n); xfree (data); out: @@ -771,7 +772,7 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) if (err) goto out; - err = es_write_string (signature_blob, buffer, sizeof (buffer)); + err = stream_write_string (signature_blob, buffer, sizeof (buffer)); out: @@ -1075,7 +1076,7 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, comment = ""; key = NULL; - err = es_read_cstring (stream, &key_type); + err = stream_read_cstring (stream, &key_type); if (err) goto out; @@ -1089,7 +1090,7 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, if (read_comment) { - err = es_read_cstring (stream, &comment); + err = stream_read_cstring (stream, &comment); if (err) goto out; } @@ -1145,12 +1146,12 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, goto out; } - err = es_write_cstring (stream, type); + err = stream_write_cstring (stream, type); if (err) goto out; for (i = 0; mpis[i] && (! err); i++) - err = es_write_mpi (stream, mpis[i]); + err = stream_write_mpi (stream, mpis[i]); if (err) goto out; @@ -1172,7 +1173,7 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, goto out; } - err = es_read_data (stream, blob_new, blob_size_new); + err = stream_read_data (stream, blob_new, blob_size_new); if (err) goto out; @@ -1223,11 +1224,11 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) if (err) goto out; - err = es_write_string (stream, blob, blob_n); + err = stream_write_string (stream, blob, blob_n); if (err) goto out; - err = es_write_cstring (stream, comment); + err = stream_write_cstring (stream, comment); out: @@ -1256,7 +1257,7 @@ ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, goto out; } - err = es_write_data (blob_stream, blob, blob_size); + err = stream_write_data (blob_stream, blob, blob_size); if (err) goto out; @@ -1373,6 +1374,7 @@ key_secret_to_public (gcry_sexp_t *key_public, if (err) goto out; + /* FIXME: write better. */ sprintf (template, "(public-key (%s", spec.identifier); for (i = 0; i < elems_n; i++) sprintf (strchr (template, 0)," (%c %%m)", elems[i]); @@ -1479,7 +1481,7 @@ ssh_handler_request_identities (ctrl_t ctrl, strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); /* Read file content. */ - err = es_read_file (key_path, &buffer, &buffer_n); + err = file_to_buffer (key_path, &buffer, &buffer_n); if (err) break; @@ -1540,19 +1542,19 @@ ssh_handler_request_identities (ctrl_t ctrl, if (! err) { - ret_err = es_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); + ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER); if (ret_err) goto leave; - ret_err = es_write_uint32 (response, key_counter); + ret_err = stream_write_uint32 (response, key_counter); if (ret_err) goto leave; - ret_err = es_copy (response, key_blobs); + ret_err = stream_copy (response, key_blobs); if (ret_err) goto leave; } else { - ret_err = es_write_byte (response, SSH_RESPONSE_FAILURE); + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); goto leave; }; @@ -1651,7 +1653,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, if (err) goto out; - err = es_write_cstring (stream, spec.ssh_identifier); + err = stream_write_cstring (stream, spec.ssh_identifier); if (err) goto out; @@ -1714,7 +1716,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, goto out; } - err = es_read_data (stream, sig_blob, sig_blob_n); + err = stream_read_data (stream, sig_blob, sig_blob_n); if (err) goto out; @@ -1763,7 +1765,7 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) /* Receive key. */ - err = es_read_string (request, 0, &key_blob, &key_blob_size); + err = stream_read_string (request, 0, &key_blob, &key_blob_size); if (err) goto out; @@ -1772,12 +1774,12 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) goto out; /* Receive data to sign. */ - err = es_read_string (request, 0, &data, &data_size); + err = stream_read_string (request, 0, &data, &data_size); if (err) goto out; /* FIXME? */ - err = es_read_uint32 (request, &flags); + err = stream_read_uint32 (request, &flags); if (err) goto out; @@ -1817,16 +1819,16 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) if (! err) { - ret_err = es_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); + ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE); if (ret_err) goto leave; - ret_err = es_write_string (response, sig, sig_n); + ret_err = stream_write_string (response, sig, sig_n); if (ret_err) goto leave; } else { - ret_err = es_write_byte (response, SSH_RESPONSE_FAILURE); + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); if (ret_err) goto leave; } @@ -1975,7 +1977,6 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) unsigned char *buffer; unsigned int buffer_n; char passphrase[100]; - size_t description_length; char *description; char key_grip[41]; char *comment; @@ -2000,23 +2001,15 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) if (err) goto out; - - /* FIXME: What the hell is that: Never have use sprintf in that way. - When marking a string translatbale you might get a buffer - overflow. We have never done this elsewhere. Using [x]asprintf - is the right way!! */ - description_length = 95 + (comment ? strlen (comment) : 0); - description = malloc (description_length); - if (! description) + ret = asprintf (&description, + "Please provide the passphrase, which should be used " + "for protecting the received secret key `%s':", + comment ? comment : ""); + if (ret < 0) { err = gpg_err_code_from_errno (errno); goto out; } - else - sprintf (description, - "Please provide the passphrase, which should be used " - "for protecting the received secret key `%s':", - comment ? comment : ""); err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase); if (err) @@ -2041,7 +2034,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) xfree (buffer); xfree (comment); - xfree (description); + free (description); /* FIXME: verify xfree vs free. */ return err; @@ -2088,7 +2081,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) while (1) { - err = es_read_byte (request, &b); + err = stream_read_byte (request, &b); if (gpg_err_code (err) == GPG_ERR_EOF) { err = 0; @@ -2101,7 +2094,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) { u32 n = 0; - err = es_read_uint32 (request, &n); + err = stream_read_uint32 (request, &n); if (! err) ttl = n; break; @@ -2129,7 +2122,7 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) gcry_sexp_release (key); - ret_err = es_write_byte (response, + ret_err = stream_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); return ret_err; @@ -2150,7 +2143,7 @@ ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, key_blob = NULL; key = NULL; - err = es_read_string (request, 0, &key_blob, &key_blob_size); + err = stream_read_string (request, 0, &key_blob, &key_blob_size); if (err) goto out; @@ -2165,7 +2158,7 @@ ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, xfree (key_blob); gcry_sexp_release (key); - ret_err = es_write_byte (response, + ret_err = stream_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); return ret_err; @@ -2192,7 +2185,7 @@ ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, gpg_error_t err; err = ssh_identities_remove_all (); - ret_err = es_write_byte (response, + ret_err = stream_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); return ret_err; @@ -2228,7 +2221,7 @@ ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) gpg_error_t err; err = ssh_lock (); - ret_err = es_write_byte (response, + ret_err = stream_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); return ret_err; @@ -2241,7 +2234,7 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) gpg_error_t err; err = ssh_unlock (); - ret_err = es_write_byte (response, + ret_err = stream_write_byte (response, err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); return ret_err; @@ -2278,7 +2271,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) client -wk */ /* Retrieve request. */ - err = es_read_string (stream_sock, 1, &request_data, &request_data_size); + err = stream_read_string (stream_sock, 1, &request_data, &request_data_size); if (err) goto out; @@ -2301,7 +2294,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) err = gpg_error_from_errno (errno); goto out; } - err = es_write_data (request, request_data, request_data_size); + err = stream_write_data (request, request_data, request_data_size); if (err) goto out; es_rewind (request); @@ -2313,7 +2306,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) goto out; } - err = es_read_byte (request, &request_type); + err = stream_read_byte (request, &request_type); if (err) { send_err = 1; @@ -2350,14 +2343,14 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) goto out; } - err = es_write_uint32 (stream_sock, response_size); + err = stream_write_uint32 (stream_sock, response_size); if (err) { send_err = 1; goto out; } - err = es_copy (stream_sock, response); + err = stream_copy (stream_sock, response); if (err) goto out; @@ -2373,10 +2366,10 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) if (send_err) { - err = es_write_uint32 (stream_sock, 1); + err = stream_write_uint32 (stream_sock, 1); if (err) goto leave; - err = es_write_byte (stream_sock, SSH_RESPONSE_FAILURE); + err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE); if (err) goto leave; } -- cgit v1.2.3 From fce56851f03794a2ce87057a5bf94be9ab1371c9 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Mon, 14 Feb 2005 20:44:22 +0000 Subject: 2005-02-14 Moritz Schulte <moritz@g10code.com> * command-ssh.c (uint32_construct): New macro ... (stream_read_uint32): ... use it; removed unnecessary cast. --- agent/ChangeLog | 2 ++ agent/command-ssh.c | 29 ++++++++++++----------------- agent/gpg-agent.c | 2 +- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 09cf0cdbc..7eb73e013 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -32,6 +32,8 @@ changed code to use asprintf for description. (stream_write_uint32): Do not filter out the last byte of shift expression. + (uint32_construct): New macro ... + (stream_read_uint32): ... use it; removed unnecessary cast. 2005-02-03 Werner Koch <wk@g10code.com> diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 68cca909b..d9e78c148 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -63,7 +63,14 @@ #define SSH_DSA_SIGNATURE_ELEMS 2 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0) + + +/* Macros. */ +/* Return a new uint32 with b0 being the most significant byte and b3 + being the least significant byte. */ +#define uint32_construct(b0, b1, b2, b3) \ + ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3) @@ -283,18 +290,7 @@ stream_read_uint32 (estream_t stream, u32 *uint32) { u32 n; - /* FIXME: For what is the cast good for? The proper way of - wrinting it - assuming an unsigned buffer - is: - - n = (buffer[0]<< 24)|(buffer[0]<< 16)|(buffer[0]<<8)|(buffer[0]); - - -wk - */ - n = (0 - | ((u32) (buffer[0] << 24)) - | ((u32) (buffer[1] << 16)) - | ((u32) (buffer[2] << 8)) - | ((u32) (buffer[3] << 0))); + n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]); *uint32 = n; err = 0; } @@ -311,11 +307,10 @@ stream_write_uint32 (estream_t stream, u32 uint32) gpg_error_t err; int ret; - /* Fixme: The 0xFF mask is superfluous. */ - buffer[0] = (uint32 >> 24) & 0xFF; - buffer[1] = (uint32 >> 16) & 0xFF; - buffer[2] = (uint32 >> 8) & 0xFF; - buffer[3] = (uint32 >> 0) & 0xFF; + buffer[0] = uint32 >> 24; + buffer[1] = uint32 >> 16; + buffer[2] = uint32 >> 8; + buffer[3] = uint32 >> 0; ret = es_write (stream, buffer, sizeof (buffer), NULL); if (ret) diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index d8b891e5f..47488ee69 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1168,7 +1168,7 @@ create_server_socket (int is_standard_name, const char *name) agent_exit (2); } - + serv_addr = malloc (sizeof (*serv_addr)); /* FIXME. */ memset (serv_addr, 0, sizeof *serv_addr); serv_addr->sun_family = AF_UNIX; assert (strlen (name) + 1 < sizeof (serv_addr->sun_path)); -- cgit v1.2.3 From 84282a95388cdcf7ad4595f4777e8dba0da81ca6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 15 Feb 2005 16:23:45 +0000 Subject: (modify_description): Don't increment OUT_LEN during the second pass. --- agent/ChangeLog | 5 +++++ agent/findkey.c | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 7eb73e013..f0e19ad37 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-02-15 Werner Koch <wk@g10code.com> + + * findkey.c (modify_description): Don't increment OUT_LEN during + the second pass. + 2005-02-14 Moritz Schulte <moritz@g10code.com> * command-ssh.c (es_read_byte): Renamed to ... diff --git a/agent/findkey.c b/agent/findkey.c index 896cb880e..1ac57ad07 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -179,18 +179,20 @@ modify_description (const char *in, const char *comment, char **result) switch (in[i]) { case '%': - out_len++; if (out) *out++ = '%'; + else + out_len++; break; case 'c': /* Comment. */ - out_len += comment_length; - if (out && comment_length) + if (out) { memcpy (out, comment, comment_length); out += comment_length; } + else + out_len += comment_length; break; default: /* Invalid special sequences are ignored. */ @@ -199,9 +201,10 @@ modify_description (const char *in, const char *comment, char **result) } else { - out_len++; if (out) *out++ = in[i]; + else + out_len++; } } -- cgit v1.2.3 From cd42f5e45f63969b746580ab3c7e811b3d142289 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Fri, 18 Feb 2005 19:08:24 +0000 Subject: 2005-02-18 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_sexp_construct): Rewritten generation of sexp template, clarified. (ssh_sexp_extract): Support shadowed-private-key-sexp; treat protected-private key and shadowed-private-key as public keys. (key_secret_to_public): Rewritten: simply use ssh_sexp_extract() and ssh_sexp_construct(). --- agent/ChangeLog | 9 ++++ agent/command-ssh.c | 150 ++++++++++++++-------------------------------------- 2 files changed, 48 insertions(+), 111 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index f0e19ad37..17641966a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2005-02-18 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_sexp_construct): Rewritten generation of sexp + template, clarified. + (ssh_sexp_extract): Support shadowed-private-key-sexp; treat + protected-private key and shadowed-private-key as public keys. + (key_secret_to_public): Rewritten: simply use ssh_sexp_extract() + and ssh_sexp_construct(). + 2005-02-15 Werner Koch <wk@g10code.com> * findkey.c (modify_description): Don't increment OUT_LEN during diff --git a/agent/command-ssh.c b/agent/command-ssh.c index d9e78c148..2cb8ee8d7 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -780,11 +780,14 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) S-Expressions. */ + + static gpg_error_t ssh_sexp_construct (gcry_sexp_t *sexp, ssh_key_type_spec_t key_spec, int secret, gcry_mpi_t *mpis, const char *comment) { + const char *key_identifier[] = { "public-key", "private-key" }; gcry_sexp_t sexp_new; char *sexp_template; size_t sexp_template_n; @@ -804,9 +807,15 @@ ssh_sexp_construct (gcry_sexp_t *sexp, elems = key_spec.elems_key_public; elems_n = strlen (elems); - /* FIXME: Why 33? -wk */ - sexp_template_n = (33 + strlen (key_spec.identifier) - + (elems_n * 6) - (!secret)); + /* + Calculate size for sexp_template_n: + + "(%s(%s<mpis>)(comment%s))" -> 20 + sizeof (<mpis>). + + mpi: (X%m) -> 5. + + */ + sexp_template_n = 20 + (elems_n * 5); sexp_template = xtrymalloc (sexp_template_n); if (! sexp_template) { @@ -814,18 +823,25 @@ ssh_sexp_construct (gcry_sexp_t *sexp, goto out; } - arg_list = xtrymalloc (sizeof (*arg_list) * (elems_n + 1)); + /* Key identifier, algorithm identifier, mpis, comment. */ + arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1)); if (! arg_list) { err = gpg_error_from_errno (errno); goto out; } - sprintf (sexp_template, "(%s-key (%s ", - secret ? "private" : "public", key_spec.identifier); + i = 0; + arg_list[i++] = &key_identifier[secret]; + arg_list[i++] = &key_spec.identifier; + + *sexp_template = 0; + sexp_template_n = 0; + sexp_template_n = sprintf (sexp_template + sexp_template_n, "(%%s(%%s"); for (i = 0; i < elems_n; i++) { - sprintf (strchr (sexp_template, 0), "(%c %%m)", elems[i]); + sexp_template_n += sprintf (sexp_template + sexp_template_n, "(%c%%m)", + elems[i]); if (secret) { for (j = 0; j < elems_n; j++) @@ -834,10 +850,12 @@ ssh_sexp_construct (gcry_sexp_t *sexp, } else j = i; - arg_list[i] = &mpis[j]; + arg_list[i + 2] = &mpis[j]; } - arg_list[i] = &comment; - sprintf (strchr (sexp_template, 0), ") (comment %%s))"); + sexp_template_n += sprintf (sexp_template + sexp_template_n, + ")(comment%%s))"); + + arg_list[i + 2] = &comment; err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list); if (err) @@ -886,13 +904,14 @@ ssh_sexp_extract (gcry_sexp_t sexp, goto out; } - if (data_n == 10 && !strncmp (data, "public-key", 10)) + if ((data_n == 10 && !strncmp (data, "public-key", 10)) + || (data_n == 21 && !strncmp (data, "protected-private-key", 21)) + || (data_n == 20 && !strncmp (data, "shadowed-private-key", 20))) { is_secret = 0; elems = key_spec.elems_key_public; } - else if ((data_n == 11 && !strncmp (data, "private-key", 11)) - || (data_n == 21 && !strncmp (data, "protected-private-key", 21))) + else if (data_n == 11 && !strncmp (data, "private-key", 11)) { is_secret = 1; elems = key_spec.elems_key_secret; @@ -1276,115 +1295,24 @@ static gpg_error_t key_secret_to_public (gcry_sexp_t *key_public, ssh_key_type_spec_t spec, gcry_sexp_t key_secret) { - gpg_error_t err; - gcry_sexp_t value_pair; - unsigned int i; + const char *comment; gcry_mpi_t *mpis; - gcry_mpi_t mpi; - void **arglist; - size_t elems_n; - char *template; - size_t template_n; - const char *elems; - char *comment; - const char *data; - size_t data_n; + gpg_error_t err; + int is_secret; - err = 0; - mpis = NULL; - arglist = NULL; comment = NULL; - template = NULL; - value_pair = NULL; - - elems = spec.elems_key_public; - elems_n = strlen (elems); - - data = NULL; - value_pair = gcry_sexp_find_token (key_secret, "comment", 0); - if (value_pair) - data = gcry_sexp_nth_data (value_pair, 1, &data_n); - if (! data) - { - data = ""; - data_n = 0; - } - - comment = xtrymalloc (data_n + 1); - if (! comment) - { - err = gpg_error_from_errno (errno); - goto out; - } - strncpy (comment, data, data_n); - comment[data_n] = 0; - - gcry_sexp_release (value_pair); - value_pair = NULL; - - template_n = 29 + strlen (spec.identifier) + (elems_n * 7) + 1; - template = xtrymalloc (template_n); - if (! template) - { - err = gpg_error_from_errno (errno); - goto out; - } - - mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); - if (! mpis) - { - err = gpg_error_from_errno (errno); /* FIXME: errno. */ - goto out; - } - memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); - - arglist = xtrymalloc (sizeof (*arglist) * (elems_n + 1)); - if (! arglist) - { - err = gpg_error_from_errno (errno); - goto out; - } - - for (i = 0; i < elems_n; i++) - { - value_pair = gcry_sexp_find_token (key_secret, elems + i, 1); - if (! value_pair) - { - err = gpg_error (GPG_ERR_INV_SEXP); - break; - } - mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG); - if (! mpi) - { - err = gpg_error (GPG_ERR_INV_SEXP); - break; - } - gcry_sexp_release (value_pair); - value_pair = NULL; + mpis = NULL; - mpis[i] = mpi; - arglist[i] = &mpis[i]; - mpi = NULL; - } + err = ssh_sexp_extract (key_secret, spec, &is_secret, &mpis, &comment); if (err) goto out; - /* FIXME: write better. */ - sprintf (template, "(public-key (%s", spec.identifier); - for (i = 0; i < elems_n; i++) - sprintf (strchr (template, 0)," (%c %%m)", elems[i]); - sprintf (strchr (template, 0), ") (comment %%s))"); - arglist[i] = &comment; + err = ssh_sexp_construct (key_public, spec, 0, mpis, comment); - err = gcry_sexp_build_array (key_public, NULL, template, arglist); - out: - gcry_sexp_release (value_pair); - xfree (template); mpint_list_free (mpis); - xfree (arglist); - xfree (comment); + xfree ((char *) comment); return err; } -- cgit v1.2.3 From 823eaefb0ba96f68e867745910116ddb15a8d03f Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sat, 19 Feb 2005 17:17:30 +0000 Subject: 2005-02-19 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_receive_mpint_list): Slightly rewritten, do not use elems_secret member of key_spec. (ssh_key_type_spec): Removed member: elems_secret. (ssh_key_types): Removed elems_secret data. (ssh_sexp_construct): Renamed to ... (sexp_key_construct): ... this; changed callers. (ssh_sexp_extract): Renamed to ... (sexp_key_extract): ... this; changed callers. (ssh_sexp_extract_key_type): Renamed to ... (sexp_extract_identifier): ... this; changed callers; use make_cstring(). Added more comments. --- agent/ChangeLog | 15 +++++++ agent/command-ssh.c | 115 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 92 insertions(+), 38 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 17641966a..f9064e46b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,18 @@ +2005-02-19 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_receive_mpint_list): Slightly rewritten, do + not use elems_secret member of key_spec. + (ssh_key_type_spec): Removed member: elems_secret. + (ssh_key_types): Removed elems_secret data. + (ssh_sexp_construct): Renamed to ... + (sexp_key_construct): ... this; changed callers. + (ssh_sexp_extract): Renamed to ... + (sexp_key_extract): ... this; changed callers. + (ssh_sexp_extract_key_type): Renamed to ... + (sexp_extract_identifier): ... this; changed callers; use + make_cstring(). + Added more comments. + 2005-02-18 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_sexp_construct): Rewritten generation of sexp diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 2cb8ee8d7..fbd296ea6 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -75,12 +75,17 @@ -/* Basic types. */ +/* + * Basic types. + */ +/* Type for a request handler. */ typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl, estream_t request, estream_t response); +/* Type, which is used for associating request handlers with the + appropriate request IDs. */ typedef struct ssh_request_spec { unsigned char type; @@ -88,22 +93,51 @@ typedef struct ssh_request_spec const char *identifier; } ssh_request_spec_t; +/* Type for "key modifier functions", which are necessary since + OpenSSH and GnuPG treat key material slightly different. A key + modifier is called right after a new key identity has been received + in order to "sanitize" the material. */ typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems, gcry_mpi_t *mpis); + +/* The encoding of a generated signature is dependent on the + algorithm; therefore algorithm specific signature encoding + functions are necessary. */ typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob, gcry_mpi_t *mpis); +/* Type, which is used for boundling all the algorithm specific + information together in a single object. */ typedef struct ssh_key_type_spec { + /* Algorithm identifier as used by OpenSSH. */ const char *ssh_identifier; + + /* Algorithm identifier as used by GnuPG. */ const char *identifier; + + /* List of MPI names for secret keys; order matches the one of the + agent protocol. */ const char *elems_key_secret; + + /* List of MPI names for public keys; order matches the one of the + agent protocol. */ const char *elems_key_public; - const char *elems_secret; + + /* List of MPI names for signature data. */ const char *elems_signature; + + /* List of MPI names for secret keys; order matches the one, which + is required by gpg-agent's key access layer. */ const char *elems_sexp_order; + + /* Key modifier function. */ ssh_key_modifier_t key_modifier; + + /* Signature encoder function. */ ssh_signature_encoder_t signature_encoder; + + /* Misc flags. */ unsigned int flags; } ssh_key_type_spec_t; @@ -166,12 +200,12 @@ static ssh_request_spec_t request_specs[] = static ssh_key_type_spec_t ssh_key_types[] = { { - "ssh-rsa", "rsa", "nedupq", "en", "dupq", "s", "nedpqu", + "ssh-rsa", "rsa", "nedupq", "en", "s", "nedpqu", ssh_key_modifier_rsa, ssh_signature_encoder_rsa, SPEC_FLAG_USE_PKCS1V2 }, { - "ssh-dss", "dsa", "pqgyx", "pqgy", "x", "rs", "pqgyx", + "ssh-dss", "dsa", "pqgyx", "pqgy", "rs", "pqgyx", NULL, ssh_signature_encoder_dsa, 0 }, @@ -206,7 +240,8 @@ realloc_secure (void *a, size_t n) } - +/* Create and return a new C-string from DATA/DATA_N (i.e.: add + NUL-termination); return NULL on OOM. */ static char * make_cstring (const char *data, size_t data_n) { @@ -604,6 +639,7 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n) */ +/* Free the list of MPIs MPI_LIST. */ static void mpint_list_free (gcry_mpi_t *mpi_list) { @@ -622,29 +658,27 @@ static gpg_error_t ssh_receive_mpint_list (estream_t stream, int secret, ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list) { - const char *elems_secret; - const char *elems; + unsigned int elems_public_n; + const char *elems_public; unsigned int elems_n; + const char *elems; + int elem_is_secret; gcry_mpi_t *mpis; - unsigned int i; gpg_error_t err; - int elem_is_secret; + unsigned int i; mpis = NULL; err = 0; if (secret) - { - elems = key_spec.elems_key_secret; - elems_secret = key_spec.elems_secret; - } + elems = key_spec.elems_key_secret; else - { - elems = key_spec.elems_key_public; - elems_secret = ""; - } + elems = key_spec.elems_key_public; elems_n = strlen (elems); + elems_public = key_spec.elems_key_public; + elems_public_n = strlen (elems_public); + mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); if (! mpis) { @@ -653,10 +687,12 @@ ssh_receive_mpint_list (estream_t stream, int secret, } memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); - + + elem_is_secret = 0; for (i = 0; i < elems_n; i++) { - elem_is_secret = strchr (elems_secret, elems[i]) ? 1 : 0; + if (secret) + elem_is_secret = ! strchr (elems_public, elems[i]); err = stream_read_mpi (stream, elem_is_secret, &mpis[i]); if (err) break; @@ -676,6 +712,7 @@ ssh_receive_mpint_list (estream_t stream, int secret, +/* Key modifier function for RSA. */ static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis) { @@ -709,6 +746,7 @@ ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis) return 0; } +/* Signature encoder function for RSA. */ static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) { @@ -732,7 +770,7 @@ ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis) } - +/* Signature encoder function for DSA. */ static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) { @@ -781,9 +819,9 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) */ - +/* */ static gpg_error_t -ssh_sexp_construct (gcry_sexp_t *sexp, +sexp_key_construct (gcry_sexp_t *sexp, ssh_key_type_spec_t key_spec, int secret, gcry_mpi_t *mpis, const char *comment) { @@ -871,8 +909,9 @@ ssh_sexp_construct (gcry_sexp_t *sexp, return err; } + static gpg_error_t -ssh_sexp_extract (gcry_sexp_t sexp, +sexp_key_extract (gcry_sexp_t sexp, ssh_key_type_spec_t key_spec, int *secret, gcry_mpi_t **mpis, const char **comment) { @@ -1002,17 +1041,19 @@ ssh_sexp_extract (gcry_sexp_t sexp, return err; } +/* Extract the car from SEXP, and create a newly created C-string it, + which is to be stored in IDENTIFIER. */ static gpg_error_t -ssh_sexp_extract_key_type (gcry_sexp_t sexp, const char **key_type) +sexp_extract_identifier (gcry_sexp_t sexp, const char **identifier) { + char *identifier_new; gcry_sexp_t sublist; - char *key_type_new; const char *data; size_t data_n; gpg_error_t err; + identifier_new = NULL; err = 0; - key_type_new = NULL; sublist = gcry_sexp_nth (sexp, 1); if (! sublist) @@ -1028,16 +1069,14 @@ ssh_sexp_extract_key_type (gcry_sexp_t sexp, const char **key_type) goto out; } - key_type_new = xtrymalloc (data_n + 1); - if (! key_type_new) + identifier_new = make_cstring (data, data_n); + if (! identifier_new) { - err = gpg_error_from_errno (errno); + err = gpg_err_code_from_errno (errno); goto out; } - strncpy (key_type_new, data, data_n); - key_type_new[data_n] = 0; - *key_type = key_type_new; + *identifier = identifier_new; out: @@ -1121,7 +1160,7 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, goto out; } - err = ssh_sexp_construct (&key, spec, secret, mpi_list, comment); + err = sexp_key_construct (&key, spec, secret, mpi_list, comment); if (err) goto out; @@ -1221,7 +1260,7 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) comment = NULL; blob = NULL; - err = ssh_sexp_extract_key_type (key_public, &key_type); + err = sexp_extract_identifier (key_public, &key_type); if (err) goto out; @@ -1229,7 +1268,7 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) if (err) goto out; - err = ssh_sexp_extract (key_public, spec, NULL, &mpi_list, &comment); + err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment); if (err) goto out; @@ -1303,11 +1342,11 @@ key_secret_to_public (gcry_sexp_t *key_public, comment = NULL; mpis = NULL; - err = ssh_sexp_extract (key_secret, spec, &is_secret, &mpis, &comment); + err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment); if (err) goto out; - err = ssh_sexp_construct (key_public, spec, 0, mpis, comment); + err = sexp_key_construct (key_public, spec, 0, mpis, comment); out: @@ -1415,7 +1454,7 @@ ssh_handler_request_identities (ctrl_t ctrl, xfree (buffer); buffer = NULL; - err = ssh_sexp_extract_key_type (key_secret, &key_type); + err = sexp_extract_identifier (key_secret, &key_type); if (err) break; -- cgit v1.2.3 From 8c77433de9a208d6ffb03aa482b6a5fe6bcfd4f3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 22 Feb 2005 17:29:07 +0000 Subject: * app-openpgp.c (app_local_s): New field PK. (do_deinit, do_genkey, app_openpgp_storekey): Clear it. (get_public_key, send_keypair_info): New. (do_learn_status): Send KEYPAIR info * app-common.h (app_ctx_t): Add function pointer READKEY. * app.c (app_readkey): New. * command.c (cmd_readkey): Use READKEY function if possible. --- scd/ChangeLog | 16 +++- scd/app-common.h | 6 +- scd/app-openpgp.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++- scd/app.c | 26 ++++++ scd/command.c | 34 ++++++-- 5 files changed, 316 insertions(+), 13 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index aba75ad54..054463d6d 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,14 @@ +2005-02-22 Werner Koch <wk@g10code.com> + + * app-openpgp.c (app_local_s): New field PK. + (do_deinit, do_genkey, app_openpgp_storekey): Clear it. + (get_public_key, send_keypair_info): New. + (do_learn_status): Send KEYPAIR info + + * app-common.h (app_ctx_t): Add function pointer READKEY. + * app.c (app_readkey): New. + * command.c (cmd_readkey): Use READKEY function if possible. + 2005-01-26 Werner Koch <wk@g10code.com> * ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround @@ -18,7 +29,7 @@ side effect of the retrieval of the the C4 DO from the 6E DO the cached fingerprint will get updated to the old value and later when signing the generated key the checking of the fingerprint - fails becuase it won't match the new one. Thanks to Moritz for + fails because it won't match the new one. Thanks to Moritz for analyzing this problem. (verify_chv3): Removed the CHV status reread logic because we won't cache the C4 DO anymore. @@ -934,7 +945,8 @@ * scdaemon.c scdaemon.h, command.c: New. Based on the code from the gpg-agent. - Copyright 2002 Free Software Foundation, Inc. + + Copyright 2002, 2003, 2004, 2005 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 diff --git a/scd/app-common.h b/scd/app-common.h index 48bd349f4..ace57d98c 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -1,5 +1,5 @@ /* app-common.h - Common declarations for all card applications - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -49,6 +49,8 @@ struct app_ctx_s { int (*learn_status) (app_t app, ctrl_t ctrl); int (*readcert) (app_t app, const char *certid, unsigned char **cert, size_t *certlen); + int (*readkey) (app_t app, const char *certid, + unsigned char **pk, size_t *pklen); int (*getattr) (app_t app, ctrl_t ctrl, const char *name); int (*setattr) (app_t app, const char *name, int (*pincb)(void*, const char *, char **), @@ -109,6 +111,8 @@ int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); int app_write_learn_status (app_t app, ctrl_t ctrl); int app_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen); +int app_readkey (app_t app, const char *keyid, + unsigned char **pk, size_t *pklen); int app_getattr (app_t app, ctrl_t ctrl, const char *name); int app_setattr (app_t app, const char *name, int (*pincb)(void*, const char *, char **), diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index fca0a98b7..8d146ba6a 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -90,6 +90,7 @@ static struct { }; +/* One cache item for DOs. */ struct cache_s { struct cache_s *next; int tag; @@ -97,8 +98,20 @@ struct cache_s { unsigned char data[1]; }; + +/* Object with application (i.e. OpenPGP card) specific data. */ struct app_local_s { + /* A linked list with cached DOs. */ struct cache_s *cache; + + /* Keep track of the public keys. */ + struct + { + int read_done; /* True if we have at least tried to read them. */ + gcry_sexp_t key; /* Might be NULL if key is not available. */ + } pk[3]; + + /* Keep track of card capabilities. */ struct { unsigned int get_challenge:1; @@ -106,6 +119,8 @@ struct app_local_s { unsigned int change_force_chv:1; unsigned int private_dos:1; } extcap; + + /* Flags used to control the application. */ struct { unsigned int no_sync:1; /* Do not sync CHV1 and CHV2 */ @@ -114,10 +129,16 @@ struct app_local_s { }; + +/***** Local prototypes *****/ static unsigned long convert_sig_counter_value (const unsigned char *value, size_t valuelen); -static unsigned long get_sig_counter (APP app); +static unsigned long get_sig_counter (app_t app); + + + + /* Deconstructor. */ static void do_deinit (app_t app) @@ -125,12 +146,19 @@ do_deinit (app_t app) if (app && app->app_local) { struct cache_s *c, *c2; + int i; for (c = app->app_local->cache; c; c = c2) { c2 = c->next; xfree (c); } + + for (i=0; i < DIM (app->app_local->pk); i++) + { + gcry_sexp_release (app->app_local->pk[i].key); + app->app_local->pk[i].read_done = 0; + } xfree (app->app_local); app->app_local = NULL; } @@ -736,6 +764,156 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) } +/* Get the public key for KEYNO and store it as an S-expresion with + the APP handle. On error that field gets cleared. If we already + know about the public key we will just return. Note that this does + not mean a key is available; this is soley indicated by the + presence of the app->app_local->pk[KEYNO-1].key field. + + Note that GnuPG 1.x does not need this and it would be too time + consuming to send it just for the fun of it. */ +#if GNUPG_MAJOR_VERSION > 1 +static gpg_error_t +get_public_key (app_t app, int keyno) +{ + gpg_error_t err = 0; + unsigned char *buffer; + const unsigned char *keydata, *m, *e; + size_t buflen, keydatalen, mlen, elen; + gcry_sexp_t sexp; + + if (keyno < 1 || keyno > 3) + return gpg_error (GPG_ERR_INV_ID); + keyno--; + + /* Already cached? */ + if (app->app_local->pk[keyno].read_done) + return 0; + + gcry_sexp_release (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].key = NULL; + + if (app->card_version > 0x0100) + { + /* We may simply read the public key out of these cards. */ + err = iso7816_read_public_key (app->slot, + keyno == 0? "\xB6" : + keyno == 1? "\xB8" : "\xA4", + 2, + &buffer, &buflen); + if (err) + { + log_error (_("reading public key failed: %s\n"), gpg_strerror (err)); + goto leave; + } + + keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen); + if (!keydata) + { + err = gpg_error (GPG_ERR_CARD); + log_error (_("response does not contain the public key data\n")); + goto leave; + } + + m = find_tlv (keydata, keydatalen, 0x0081, &mlen); + if (!m) + { + err = gpg_error (GPG_ERR_CARD); + log_error (_("response does not contain the RSA modulus\n")); + goto leave; + } + + e = find_tlv (keydata, keydatalen, 0x0082, &elen); + if (!e) + { + err = gpg_error (GPG_ERR_CARD); + log_error (_("response does not contain the RSA public exponent\n")); + goto leave; + } + + err = gcry_sexp_build (&sexp, NULL, + "(public-key (rsa (n %b) (e %b)))", + (int)mlen, m,(int)elen, e); + + if (err) + { + log_error ("error formatting the key into an S-expression: %s\n", + gpg_strerror (err)); + goto leave; + } + app->app_local->pk[keyno].key = sexp; + + } + else + { + /* Due to a design problem in v1.0 cards we can't get the public + key out of these cards without doing a verify on CHV3. + Clearly that is not an option and thus we try to locate the + key using an external helper. */ + + buffer = NULL; + /* FIXME */ + + } + + leave: + /* Set a flag to indicate that we tried to read the key. */ + app->app_local->pk[keyno].read_done = 1; + + xfree (buffer); + return 0; +} +#endif /* GNUPG_MAJOR_VERSION > 1 */ + + + +/* Send the KEYPAIRINFO back. KEYNO needs to be in the range [1,3]. + This is used by the LEARN command. */ +static gpg_error_t +send_keypair_info (app_t app, ctrl_t ctrl, int keyno) +{ + gpg_error_t err = 0; + /* Note that GnuPG 1.x does not need this and it would be too time + consuming to send it just for the fun of it. */ +#if GNUPG_MAJOR_VERSION > 1 + gcry_sexp_t sexp; + unsigned char grip[20]; + char gripstr[41]; + char idbuf[50]; + int i; + + err = get_public_key (app, keyno); + if (err) + goto leave; + + assert (keyno >= 1 && keyno <= 3); + sexp = app->app_local->pk[keyno-1].key; + if (!sexp) + goto leave; /* No such key. */ + + if (!gcry_pk_get_keygrip (sexp, grip)) + { + err = gpg_error (GPG_ERR_INTERNAL); + goto leave; + } + + for (i=0; i < 20; i++) + sprintf (gripstr+i*2, "%02X", grip[i]); + + sprintf (idbuf, "OPENPGP.%d", keyno); + send_status_info (ctrl, "KEYPAIRINFO", + gripstr, 40, + idbuf, strlen (idbuf), + NULL, (size_t)0); + + leave: +#endif /* GNUPG_MAJOR_VERSION > 1 */ + + return err; +} + + +/* Handle the LEARN command for OpenPGP. */ static int do_learn_status (app_t app, ctrl_t ctrl) { @@ -760,11 +938,63 @@ do_learn_status (app_t app, ctrl_t ctrl) if (app->did_chv3) do_getattr (app, ctrl, "PRIVATE-DO-4"); } + send_keypair_info (app, ctrl, 1); + send_keypair_info (app, ctrl, 2); + send_keypair_info (app, ctrl, 3); + return 0; +} + + +/* Handle the READKEY command for OpenPGP. On success a canonical + encoded S-expression with the public key will get stored at PK and + its length (for assertions) at PKLEN; the caller must release that + buffer. On error PK and PKLEN are not changed and an error code is + returned. */ +static int +do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) +{ + gpg_error_t err; + int keyno; + size_t n; + unsigned char *buf; + gcry_sexp_t sexp; + + if (!strcmp (keyid, "OPENPGP.1")) + keyno = 1; + else if (!strcmp (keyid, "OPENPGP.2")) + keyno = 2; + else if (!strcmp (keyid, "OPENPGP.3")) + keyno = 3; + else + return gpg_error (GPG_ERR_INV_ID); + err = get_public_key (app, keyno); + if (err) + return err; + + sexp = app->app_local->pk[keyno-1].key; + if (!sexp) + return gpg_error (GPG_ERR_NO_PUBKEY); + + n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0); + if (!n) + return gpg_error (GPG_ERR_BUG); + buf = xtrymalloc (n); + if (!buf) + return gpg_error_from_errno (errno); + n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, n); + if (!n) + { + xfree (buf); + return gpg_error (GPG_ERR_BUG); + } + *pk = buf; + *pklen = n; return 0; } + /* Verify CHV2 if required. Depending on the configuration of the card CHV1 will also be verified. */ static int @@ -1082,6 +1312,11 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, generation. This _might_ help a card to gather more entropy. */ flush_cache (app); + /* Obviously we need to remove the cached public key. */ + gcry_sexp_release (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].read_done = 0; + + /* Check whether a key already exists. */ rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); if (rc) { @@ -1109,11 +1344,12 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, else log_info (_("generating new key\n")); - + + /* Prepare for key generation by verifying the ADmin PIN. */ rc = verify_chv3 (app, pincb, pincb_arg); if (rc) goto leave; - + xfree (buffer); buffer = NULL; #if 1 @@ -1682,7 +1918,7 @@ app_select_openpgp (app_t app) app->fnc.deinit = do_deinit; app->fnc.learn_status = do_learn_status; - app->fnc.readcert = NULL; + app->fnc.readkey = do_readkey; app->fnc.getattr = do_getattr; app->fnc.setattr = do_setattr; app->fnc.genkey = do_genkey; @@ -1818,6 +2054,9 @@ app_openpgp_storekey (app_t app, int keyno, flush_cache (app); + gcry_sexp_release (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].read_done = 0; + rc = iso7816_put_data (app->slot, (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, template, template_len); diff --git a/scd/app.c b/scd/app.c index 55fb5861e..fad4eba55 100644 --- a/scd/app.c +++ b/scd/app.c @@ -263,6 +263,32 @@ app_readcert (app_t app, const char *certid, } +/* Read the key with ID KEYID. On success a canonical encoded + S-expression with the public key will get stored at PK and its + length (for assertions) at PKLEN; the caller must release that + buffer. On error NULL will be stored at PK and PKLEN and an error + code returned. + + This function might not be supported by all applications. */ +int +app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) +{ + if (pk) + *pk = NULL; + if (pklen) + *pklen = 0; + + if (!app || !keyid || !pk || !pklen) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.readkey) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + return app->fnc.readkey (app, keyid, pk, pklen); +} + + /* Perform a GETATTR operation. */ int app_getattr (APP app, CTRL ctrl, const char *name) diff --git a/scd/command.c b/scd/command.c index b41e7aa16..72f48b2b8 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1,5 +1,5 @@ /* command.c - SCdaemon command handler - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -494,9 +494,9 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line) Return the public key for the given cert or key ID as an standard S-Expression. */ static int -cmd_readkey (ASSUAN_CONTEXT ctx, char *line) +cmd_readkey (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char *cert = NULL; size_t ncert, n; @@ -509,9 +509,31 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line) line = xstrdup (line); /* Need a copy of the line. */ if (ctrl->app_ctx) { - rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); - if (rc) - log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); + unsigned char *pk; + size_t pklen; + + /* If the application supports the READKEY function we use that. + Otherwise we use the old way by extracting it from the + certificate. */ + rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen); + if (!rc) + { /* Yeah, got that key - send it back. */ + rc = assuan_send_data (ctx, pk, pklen); + xfree (pk); + rc = map_assuan_err (rc); + xfree (line); + line = NULL; + goto leave; + } + + if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION) + log_error ("app_readkey failed: %s\n", gpg_strerror (rc)); + else + { + rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); + if (rc) + log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); + } } else { -- cgit v1.2.3 From 2af725a37f6b3a1cb187fe986c38571772f8600f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 22 Feb 2005 17:30:17 +0000 Subject: Renmoved stale file --- preset-passphrase.c | 290 ---------------------------------------------------- 1 file changed, 290 deletions(-) delete mode 100644 preset-passphrase.c diff --git a/preset-passphrase.c b/preset-passphrase.c deleted file mode 100644 index 564980b78..000000000 --- a/preset-passphrase.c +++ /dev/null @@ -1,290 +0,0 @@ -/* preset-passphrase.c - A tool to preset a passphrase. - * Copyright (C) 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 - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <sys/stat.h> -#include <unistd.h> -#ifdef HAVE_LOCALE_H -#include <locale.h> -#endif -#ifdef HAVE_LANGINFO_CODESET -#include <langinfo.h> -#endif -#ifdef HAVE_DOSISH_SYSTEM -#include <fcntl.h> /* for setmode() */ -#endif - -#define JNLIB_NEED_LOG_LOGV -#include "agent.h" -#include "minip12.h" -#include "simple-pwquery.h" -#include "i18n.h" -#include "sysutils.h" - - -enum cmd_and_opt_values -{ aNull = 0, - oVerbose = 'v', - oPassphrase = 'P', - - oPreset = 'c', - oForget = 'f', - - oNoVerbose = 500, - - oHomedir, - -aTest }; - -struct rsa_secret_key_s - { - gcry_mpi_t n; /* public modulus */ - gcry_mpi_t e; /* public exponent */ - gcry_mpi_t d; /* exponent */ - gcry_mpi_t p; /* prime p. */ - gcry_mpi_t q; /* prime q. */ - gcry_mpi_t u; /* inverse of p mod q. */ - }; - - -static char *opt_homedir; -static const char *opt_passphrase; - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, N_("@Options:\n ") }, - - { oVerbose, "verbose", 0, "verbose" }, - { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, - { oPreset, "preset", 256, "preset passphrase"}, - { oForget, "forget", 256, "forget passphrase"}, - - { oHomedir, "homedir", 2, "@" }, - {0} -}; - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "gpg-preset-passphrase (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: gpg-preset-passphrase [options] KEYID (-h for help)\n"); - break; - case 41: p = _("Syntax: gpg-preset-passphrase [options] KEYID\n" - "Password cache maintenance\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 - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE_GT, LOCALEDIR); - textdomain (PACKAGE_GT); -#endif -#endif -} - - -static gpg_error_t -map_spwq_error (int err) -{ - switch (err) - { - case 0: - return 0; - case SPWQ_OUT_OF_CORE: - return gpg_error_from_errno (ENOMEM); - case SPWQ_IO_ERROR: - return gpg_error_from_errno (EIO); - case SPWQ_PROTOCOL_ERROR: - return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); - case SPWQ_ERR_RESPONSE: - return gpg_error (GPG_ERR_INV_RESPONSE); - case SPWQ_NO_AGENT: - return gpg_error (GPG_ERR_NO_AGENT); - case SPWQ_SYS_ERROR: - return gpg_error_from_errno (errno); - case SPWQ_GENERAL_ERROR: - default: - return gpg_error (GPG_ERR_GENERAL); - } -} - - -static void -preset_passphrase (const char *keygrip) -{ - int rc; - char *line; - /* FIXME: Use secure memory. */ - char passphrase[500]; - - rc = read (0, passphrase, sizeof (passphrase) - 1); - if (rc < 0) - { - log_error ("reading passphrase failed %s\n", - gpg_strerror (gpg_error_from_errno (errno))); - return; - } - passphrase[rc] = '\0'; - line = strchr (passphrase, '\n'); - if (line) - { - line--; - if (line > passphrase && line[-1] == '\r') - line--; - *line = '\0'; - } - - /* FIXME: How to handle empty passwords? */ - - rc = asprintf (&line, "PRESET_PASSPHRASE %s -1 %s\n", keygrip, passphrase); - if (rc < 0) - { - log_error ("caching passphrase failed %s\n", - gpg_strerror (gpg_error_from_errno (errno))); - return; - } - wipememory (passphrase, sizeof (passphrase)); - - rc = map_spwq_error (simple_query (line)); - if (rc) - { - log_error ("caching passphrase failed %s\n", gpg_strerror (rc)); - return; - } - - wipememory (line, strlen (line)); - free (line); -} - - -static void -forget_passphrase (const char *keygrip) -{ - int rc; - char *line; - - rc = asprintf (&line, "CLEAR_PASSPHRASE %s\n", keygrip); - if (rc < 0) - { - log_error ("clearing passphrase failed %s\n", - gpg_strerror (gpg_error_from_errno (errno))); - return; - } - free (line); -} - - -int -main (int argc, char **argv) -{ - ARGPARSE_ARGS pargs; - int cmd = 0; - const char *keygrip = NULL; - - set_strusage (my_strusage); - log_set_prefix ("gpg-preset-passphrase", 1); - - /* Try to auto set the character set. */ - set_native_charset (NULL); - - i18n_init (); - - opt_homedir = getenv ("GNUPGHOME"); -#ifdef HAVE_W32_SYSTEM - if (!opt_homedir || !*opt_homedir) - opt_homedir = read_w32_registry_string (NULL, - "Software\\GNU\\GnuPG", "HomeDir"); -#endif /*HAVE_W32_SYSTEM*/ - if (!opt_homedir || !*opt_homedir) - opt_homedir = GNUPG_DEFAULT_HOMEDIR; - - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* (do not remove the args) */ - while (arg_parse (&pargs, opts) ) - { - switch (pargs.r_opt) - { - case oVerbose: opt.verbose++; break; - case oHomedir: opt_homedir = pargs.r.ret_str; break; - - case oPreset: cmd = oPreset; break; - case oForget: cmd = oForget; break; - case oPassphrase: opt_passphrase = pargs.r.ret_str; break; - - default : pargs.err = 2; break; - } - } - if (log_get_errorcount(0)) - exit(2); - - if (argc == 1) - keygrip = *argv; - else - usage (1); - - if (cmd == oPreset) - preset_passphrase (keygrip); - else if (cmd == oForget) - forget_passphrase (keygrip); - else - usage (1); - - agent_exit (0); - return 8; /*NOTREACHED*/ -} - - -void -agent_exit (int rc) -{ - rc = rc? rc : log_get_errorcount(0)? 2 : 0; - exit (rc); -} -- cgit v1.2.3 From cf8f6d3cefd3ed45bac7f944c03319746277c292 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 22 Feb 2005 18:08:28 +0000 Subject: (stream_read_string): Removed call to abort on memory error because the CVS version of libgcrypt makes sure that ERRNO gets always set on error even with a faulty user supplied function. --- TODO | 2 + agent/ChangeLog | 7 ++ agent/call-scd.c | 2 +- agent/command-ssh.c | 13 ++- agent/learncard.c | 28 +++++-- doc/ChangeLog | 4 + doc/README.W32 | 222 +++++++++------------------------------------------- doc/gpgsm.texi | 6 ++ jnlib/ChangeLog | 3 +- jnlib/argparse.c | 2 +- 10 files changed, 87 insertions(+), 202 deletions(-) diff --git a/TODO b/TODO index 7a2292bd6..2aace782f 100644 --- a/TODO +++ b/TODO @@ -54,6 +54,8 @@ might want to have an agent context for each service request ** A SIGHUP should also restart the scdaemon But do this only after all connections terminated. As of now we only send a RESET. +** Watch the child process if not invoked as a daemon + and terminate after the child has terminated * agent/command.c ** Make sure that secure memory is used where appropriate diff --git a/agent/ChangeLog b/agent/ChangeLog index f9064e46b..420dc6368 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,10 @@ +2005-02-22 Werner Koch <wk@g10code.com> + + * command-ssh.c (stream_read_string): Removed call to abort on + memory error because the CVS version of libgcrypt makes sure + that ERRNO gets always set on error even with a faulty user + supplied function. + 2005-02-19 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_receive_mpint_list): Slightly rewritten, do diff --git a/agent/call-scd.c b/agent/call-scd.c index 619a549f9..bffdbcbad 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -296,7 +296,7 @@ learn_status_cb (void *opaque, const char *line) return 0; } -/* Perform the learn command and return a list of all private keys +/* Perform the LEARN command and return a list of all private keys stored on the card. */ int agent_card_learn (ctrl_t ctrl, diff --git a/agent/command-ssh.c b/agent/command-ssh.c index fbd296ea6..1719602f2 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -215,15 +215,12 @@ static ssh_key_type_spec_t ssh_key_types[] = - - - /* General utility functions. */ /* A secure realloc, i.e. it makes sure to allocate secure memory if A - is NULL. This is required becuase the standard gcry_realloc does + is NULL. This is required because the standard gcry_realloc does not know whether to allocate secure or normal if NULL is passed as existing buffer. */ static void * @@ -419,9 +416,7 @@ stream_read_string (estream_t stream, unsigned int secure, buffer = xtrymalloc (length + 1); if (! buffer) { - /* FIXME: xtrymalloc_secure does not set errno, does it? */ err = gpg_error_from_errno (errno); - abort (); goto out; } @@ -1530,6 +1525,8 @@ ssh_handler_request_identities (ctrl_t ctrl, free (key_directory); xfree (key_path); xfree (buffer); + /* FIXME: Ist is for sure is a Bad Thing to use the const qualifier + and later cast it away. You can't do that!!! */ xfree ((void *) key_type); /* FIXME? */ return ret_err; @@ -2159,7 +2156,7 @@ ssh_lock (void) gpg_error_t err; /* FIXME */ - log_error (_("lock command is not implemented\n")); + log_error ("ssh-agent's lock command is not implemented\n"); err = 0; return err; @@ -2170,7 +2167,7 @@ ssh_unlock (void) { gpg_error_t err; - log_error (_("unlock command is not implemented\n")); + log_error ("ssh-agent's unlock command is not implemented\n"); err = 0; return err; diff --git a/agent/learncard.c b/agent/learncard.c index 76e8986f8..7dcacee28 100644 --- a/agent/learncard.c +++ b/agent/learncard.c @@ -31,11 +31,16 @@ #include "agent.h" #include <assuan.h> +/* Structures used by the callback mechanism to convey information + pertaining to key pairs. */ struct keypair_info_s { struct keypair_info_s *next; int no_cert; - char *id; /* points into grip */ - char hexgrip[1]; + char *id; /* points into grip */ + char hexgrip[1]; /* The keygrip (i.e. a hash over the public key + parameters) formatted as a hex string. + Allocated somewhat large to also act as + memeory for the above ID field. */ }; typedef struct keypair_info_s *KEYPAIR_INFO; @@ -45,6 +50,9 @@ struct kpinfo_cb_parm_s { }; + +/* Structures used by the callback mechanism to convey information + pertaining to certificates. */ struct certinfo_s { struct certinfo_s *next; int type; @@ -59,6 +67,8 @@ struct certinfo_cb_parm_s { }; +/* Structures used by the callback mechanism to convey assuan status + lines. */ struct sinfo_s { struct sinfo_s *next; char *data; /* Points into keyword. */ @@ -72,7 +82,7 @@ struct sinfo_cb_parm_s { }; - +/* Destructor for key information objects. */ static void release_keypair_info (KEYPAIR_INFO info) { @@ -84,6 +94,7 @@ release_keypair_info (KEYPAIR_INFO info) } } +/* Destructor for certificate information objects. */ static void release_certinfo (CERTINFO info) { @@ -95,6 +106,7 @@ release_certinfo (CERTINFO info) } } +/* Destructor for status information objects. */ static void release_sinfo (SINFO info) { @@ -285,7 +297,7 @@ send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context) } /* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new - certificates are send via Assuan */ + certificates are send back via Assuan. */ int agent_handle_learn (ctrl_t ctrl, void *assuan_context) { @@ -317,7 +329,7 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context) if (rc) goto leave; - /* now gather all the available info */ + /* Now gather all the available info. */ rc = agent_card_learn (ctrl, kpinfo_cb, &parm, certinfo_cb, &cparm, sinfo_cb, &sparm); if (!rc && (parm.error || cparm.error || sparm.error)) @@ -371,15 +383,15 @@ agent_handle_learn (ctrl_t ctrl, void *assuan_context) log_info (" id: %s (grip=%s)\n", item->id, item->hexgrip); if (item->no_cert) - continue; /* no public key yet available */ + continue; /* No public key yet available. */ for (p=item->hexgrip, i=0; i < 20; p += 2, i++) grip[i] = xtoi_2 (p); if (!agent_key_available (grip)) - continue; + continue; /* The key is already available. */ - /* unknown - store it */ + /* Unknown key - store it. */ rc = agent_card_readkey (ctrl, item->id, &pubkey); if (rc) { diff --git a/doc/ChangeLog b/doc/ChangeLog index fa61b0466..49e8b026f 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-02-14 Werner Koch <wk@g10code.com> + + * gpgsm.texi (Certificate Management): Document --import. + 2005-01-27 Moritz Schulte <moritz@g10code.com> * gpg-agent.texi: Document ssh-agent emulation layer. diff --git a/doc/README.W32 b/doc/README.W32 index 18f745d9c..6417e90cb 100644 --- a/doc/README.W32 +++ b/doc/README.W32 @@ -1,186 +1,42 @@ -README.W32 -*- text -*- + README.W32 + ============ + 2004-12-22 -This is a binary package with GnuPG for MS-Windows 95, 98, WNT, W2000 -and XP. See the file README for generic instructions and usage hints. + This is a precompiled version of gnupg 1.9.14 for MS Windows. + Please see the manual (gnupg.pdf) for the current limitations. Be + aware that this is the first released version and thus bugs are + pretty likely. -A FAQ comes with this package and a probably more recent one can be -found online at http://www.gnupg.org/faq.html. See -http://www.gnupg.org/docs-mls.html for a list of mailing lists. In -particular the list gnupg-users@gnupg.org might be useful to answer -questions - but please read the FAQ first. - - -Installation directory: -======================= - -The installation directory of GnuPG is stored in the Registry under -the key HKEY_LOCAL_MACHINE\Software\GNU\GnuPG with the name "Install -Directory". The installer does not change the PATH environment -variable to include this directory. You might want to do this -manually. - -Below the Installation directory, you will find directories named -"Doc", "gnupg.nls" and "Src". The latter will be used for distributed -patched, if any, and to store the source file if they have been -included in this package. The source files usually require further -unpacking using a the TAR utility. - - -Internationalization support: -============================= - -Store the locale id (like "de") into the Registry under the key -HKEY_CURRENT_USER\Software\GNU\GnuPG with the name "Lang". This must -match one of the installed languages files in the directory named -"gnupg.nls" below the installation directory. Note, that the ".mo" -extension is not part of the lcoale id. - - -Home directory: -=============== - -GnuPG makes use of a per user home directory to store its keys as well -as configuration files. The default home directory is a directory -named "gnupg" below the application data directory of the user. This -directory will be created if it does not exist. Being only a default, -it may be changed by setting the name of the home directory into the -Registry under the key HKEY_CURRENT_USER\Software\GNU\GnuPG using the -name "HomeDir". If an environment varaibale "GNUPGHOME" exists, this -even overrides the registry setting. The command line option -"--homedir" may be used to override all other settings of the home -directory. - - -Reporting bugs: -=============== - -Please check the documentation first before asking or reporting a -bugs. In particular check the archives of the mailing lists (see -www.gnupg.org) and the bug tracking system at http://bugs.gnupg.org -(login is "guest" password is "guest") whether the problem is already -known. Asking on the gnupg-users mailing list is also strongly -encouraged; if you are not subscribed it may some time until a posting -is approved (this is an anti-spam measure). Bug reporting addresses -are listed in the file AUTHORS. - -If you want to report a bug or have other problems, always give -detailed description of the problem, the version of GnuPG you used, -the version of the OS, whether it is the official version from -gnupg.org or how you built it. Don't edit error messages - replacing -sensitive information like user IDs, fingerprints and keyids is okay. -If possible, switch to English messages by changing the "Lang" entry -to empty (see under Internationalization support). - - -How to build GnuPG from the source: -=================================== - -Until recently all official GnuPG versions have been build using the -Mingw32/CPD kit as available at -ftp://ftp.gnupg.org/people/werner/cpd/mingw32-cqpd-0.3.2.tar.gz . -However, for maintenance reasons we switched to Debian's mingw32 cross -compiler package and that is now the recommended way of building GnuPG -for W32 platforms. It might be possible to build it nativly on a W32 -platform but this is not supported. Please don't file any bug reports -if it does not build with any other system than the recommended one. - -According to the conditions of the GNU General Public License you -either got the source files with this package, a written offer to send -you the source on demand or the source is available at the same site -you downloaded the binary package. If you downloaded the package from -the official GnuPG site or one of its mirrors, the corresponding -source tarball is available in the sibling directory named gnupg. The -source used to build all versions is always the same and the version -numbers should match. If the version number of the binary package has -a letter suffix, you will find a patch file installed in the "Src" -directory with the changes relative to the generic version. - -The source is distributed as a BZIP2 or GZIP compressed tar archive. -See the instructions in file README on how to check the integrity of -that file. Wir a properly setup build environment, you unpack the -tarball change to the created directory and run - - $ ./autogen.sh --build-w32 - $ make - $ cp g10/gpg*.exe /some_windows_drive/ - -Building a version with the installer is a bit more complex and -basically works by creating a top directory, unpacking in that top -directory, switching to the gnupg-1.x.y directory, running -"./autogen.sh --build-w32" and "make", switching back to the top -directory, running a "mkdir dist-w32; mkdir iconv", copying the -required iconv files (iconv.dll, README.iconv, COPYING.LIB) into the -iconv directory, running gnupg-1.x.y/scripts/mk-w32-dist and voila, -the installer package will be available in the dist-w32 directory. - - -Copying: -======== - -GnuPG is - - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005 Free Software Foundation, Inc. - - 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 - -See the files AUTHORS and THANKS for credits, further legal -information and bug reporting addresses pertaining to GnuPG. - -For copying conditions of the GNU LIBICONV library see the file -README.iconv. + Please copy all files to the directory c:\gnupg and follow the + manual instructions. -The installer software used to create the official binary packages for -W32 is NSIS (http://nsis.sourceforge.net/): - - Copyright (C) 1999-2005 Nullsoft, Inc. - - This license applies to everything in the NSIS package, except where - otherwise noted. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. - - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. - -The user interface used with the installer is - - Copyright (C) 2002-2005 Joost Verburg - - [It is distributed along with NSIS and the same conditions as stated - above apply] - - -The term "W32" is used to describe the API used by current Microsoft -Windows versions. We don't use the Microsft terminology here; in -hacker terminology, calling something a "win" is a form of praise. -Keep in mind that Windows ist just a temporary workaround until you -can switch to a complete Free Software system. Be the source always -with you. + This software has been build using Debian's mingw package, version + 3.3.1.20030804.1-1. Libraries are all compiled statically, versions + of the used libraries are: + + gpg-error-config: 1.1-cvs + libgcrypt-config: 1.2.1-cvs + ksba-config: 0.9.11-cvs + libassuan-config: 0.6.9-cvs + + as these are all CVS versions you need to get the from the CVS. See + www.gnupg.org for details. Use 2004-12-22 18:00 UTC as revision + date. The source code of GnuPG itsself is available at + ftp://ftp.gnupg.org/gcrypt/alpha/gnupg/gnupg-1.9.14.tar.bz2 + ftp://ftp.gnupg.org/gcrypt/alpha/gnupg/gnupg-1.9.14.tar.bz2.sig + + Building has been done by running the command + + ./autogen.sh --build-w32 + + for all these libraries and then for gnupg. The PDF file has been + produced by first converting the logo file to pdf and the running + "make gnupg.pdf" in the doc directory. All executables have been + stripped. + + In case of questions please contact us at info@g10code.com or better + write to the mailing list gnupg-devel@gnupg.org. + + Thanks, + + The g10 Code team diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 1e7368041..09fd7d660 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -190,6 +190,12 @@ 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 --import [@var{files}] +@opindex import +Import the certificates from the PEM or binary encoded files as well as +from signed-only messages. This command may also be used to import a +secret key from a PKCS#12 file. + @item --learn-card @opindex learn-card Read information about the private keys from the smartcard and import diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 0c82c8724..f308a7ea3 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -316,7 +316,8 @@ Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> * You may find it source-copied in other packages. * *********************************************************** - Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, + 2005 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 diff --git a/jnlib/argparse.c b/jnlib/argparse.c index de828e8ce..485c60786 100644 --- a/jnlib/argparse.c +++ b/jnlib/argparse.c @@ -904,7 +904,7 @@ strusage( int level ) switch( level ) { case 11: p = "foo"; break; case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2004 Free Software Foundation, Inc."; break; + case 14: p = "Copyright (C) 2005 Free Software Foundation, Inc."; break; case 15: p = "This program comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" -- cgit v1.2.3 From 4e5bf2fd93a175f64aa1ca2e4b35dcf853f7f828 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 23 Feb 2005 21:06:32 +0000 Subject: * command-ssh.c (get_passphrase): Removed. (ssh_identity_register): Partly rewritten. (open_control_file, search_control_file, add_control_entry): New. (ssh_handler_request_identities): Return only files listed in our control file. * findkey.c (unprotect): Check for allocation error. * agent.h (opt): Add fields to record the startup terminal settings. * gpg-agent.c (main): Record them and do not force keep display with --enable-ssh-support. * command-ssh.c (start_command_handler_ssh): Use them here. * gpg-agent.c: Renamed option --ssh-support to --enable-ssh-support. * command.c (cmd_readkey): New. (register_commands): Register new command "READKEY". * command-ssh.c (ssh_request_process): Improved logging. * findkey.c (agent_write_private_key): Always use plain open. Don't depend on an umask for permissions. (agent_key_from_file): Factored file reading code out to .. (read_key_file): .. new function. (agent_public_key_from_file): New. --- agent/ChangeLog | 40 +++++- agent/agent.h | 12 ++ agent/command-ssh.c | 363 +++++++++++++++++++++++++++++++++++++++++----------- agent/command.c | 54 +++++++- agent/findkey.c | 330 +++++++++++++++++++++++++++++++++++++++-------- agent/gpg-agent.c | 30 +++-- agent/keyformat.txt | 6 + agent/protect.c | 2 +- agent/query.c | 2 +- 9 files changed, 690 insertions(+), 149 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 420dc6368..47ca2debf 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,33 @@ +2005-02-23 Werner Koch <wk@g10code.com> + + * command-ssh.c (get_passphrase): Removed. + (ssh_identity_register): Partly rewritten. + (open_control_file, search_control_file, add_control_entry): New. + (ssh_handler_request_identities): Return only files listed in our + control file. + + * findkey.c (unprotect): Check for allocation error. + + * agent.h (opt): Add fields to record the startup terminal + settings. + * gpg-agent.c (main): Record them and do not force keep display + with --enable-ssh-support. + * command-ssh.c (start_command_handler_ssh): Use them here. + + * gpg-agent.c: Renamed option --ssh-support to + --enable-ssh-support. + + * command.c (cmd_readkey): New. + (register_commands): Register new command "READKEY". + + * command-ssh.c (ssh_request_process): Improved logging. + + * findkey.c (agent_write_private_key): Always use plain open. + Don't depend on an umask for permissions. + (agent_key_from_file): Factored file reading code out to .. + (read_key_file): .. new function. + (agent_public_key_from_file): New. + 2005-02-22 Werner Koch <wk@g10code.com> * command-ssh.c (stream_read_string): Removed call to abort on @@ -1092,21 +1122,21 @@ Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de> - * gpg-agent.c (passphrase_dialog): Cleanup the window and added the + * gpg-agent.c (passphrase_dialog): Cleanup the window and added the user supplied text to the window. (main): Fixed segv in gtk_init when used without a command to start. - * gpg-agent.c: --flush option. + * gpg-agent.c: --flush option. (req_flush): New. (req_clear_passphrase): Implemented. Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de> - * gpg-agent.c: New. - * Makefile.am: New. + * gpg-agent.c: New. + * Makefile.am: New. - Copyright 2001, 2002 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004, 2005 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 diff --git a/agent/agent.h b/agent/agent.h index a1196bc0b..0661cc4ad 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -53,6 +53,15 @@ struct { int dry_run; /* Don't change any persistent data */ int batch; /* Batch mode */ const char *homedir; /* Configuration directory name */ + + /* Environment setting gathred at program start. */ + const char *startup_display; + const char *startup_ttyname; + const char *startup_ttytype; + const char *startup_lc_ctype; + const char *startup_lc_messages; + + const char *pinentry_program; /* Filename of the program to start as pinentry. */ const char *scdaemon_program; /* Filename of the program to handle @@ -150,6 +159,9 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl, const unsigned char *grip, unsigned char **shadow_info, int ignore_cache, gcry_sexp_t *result); +gpg_error_t agent_public_key_from_file (ctrl_t ctrl, + const unsigned char *grip, + gcry_sexp_t *result); int agent_key_available (const unsigned char *grip); /*-- query.c --*/ diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 1719602f2..8ea042e19 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -23,13 +23,14 @@ #include <config.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> -#include <stdio.h> +#include <assert.h> #include "agent.h" @@ -63,7 +64,22 @@ #define SSH_DSA_SIGNATURE_ELEMS 2 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0) - + +/* The blurb we put into the header of a newly created control file. */ +static const char sshcontrolblurb[] = +"# List of allowed ssh keys. Only keys present in this file are used\n" +"# in the SSH protocol. The ssh-add tool may add new entries to this\n" +"# file to enable them; you may also add them manually. Comment\n" +"# lines, like this one, as well as empty lines are ignored. Lines do\n" +"# have a certain length limit but this is not serious limitation as\n" +"# the format of the entries is fixed and checked by gpg-agent. A\n" +"# non-comment line starts with optional white spaces, followed by the\n" +"# keygrip of the key given as 40 hex digits, optionally followed by a\n" +"# the caching TTL in seconds and another optional field for arbitrary\n" +"# flags. Prepend the keygrip with an '!' mark to disable it.\n" +"\n"; + + /* Macros. */ @@ -626,6 +642,155 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n) } + + +/* Open the ssh control file and create it if not available. With + APPEND passed as true the file will be opened in append mode, + otherwise in read only mode. On success a file pointer is stored + at the address of R_FP. */ +static gpg_error_t +open_control_file (FILE **r_fp, int append) +{ + gpg_error_t err; + char *fname; + FILE *fp; + + /* Note: As soon as we start to use non blocking functions here + (i.e. where Pth might switch threads) we need to employ a + mutex. */ + *r_fp = NULL; + fname = make_filename (opt.homedir, "sshcontrol.txt", NULL); + fp = fopen (fname, append? "a+":"r"); + if (!fp && errno == ENOENT) + { + /* Fixme: "x" is a GNU extension. We might want to use the es_ + functions here. */ + fp = fopen (fname, "wx"); + if (!fp) + { + err = gpg_error (gpg_err_code_from_errno (errno)); + log_error (_("can't create `%s': %s\n"), fname, gpg_strerror (err)); + xfree (fname); + return err; + } + fputs (sshcontrolblurb, fp); + fclose (fp); + fp = fopen (fname, append? "a+":"r"); + } + + if (!fp) + { + err = gpg_error (gpg_err_code_from_errno (errno)); + log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err)); + xfree (fname); + return err; + } + + *r_fp = fp; + + return 0; +} + + +/* Search the file at stream FP from the beginning until a matching + HEXGRIP is found; return success in this case and store true at + DISABLED if the found key has been disabled. */ +static gpg_error_t +search_control_file (FILE *fp, const char *hexgrip, int *disabled) +{ + int c, i; + char *p, line[256]; + + assert (strlen (hexgrip) == 40 ); + + rewind (fp); + *disabled = 0; + next_line: + do + { + if (!fgets (line, DIM(line)-1, fp) ) + { + if (feof (fp)) + return gpg_error (GPG_ERR_EOF); + return gpg_error (gpg_err_code_from_errno (errno)); + } + + if (!*line || line[strlen(line)-1] != '\n') + { + /* Eat until end of line */ + while ( (c=getc (fp)) != EOF && c != '\n') + ; + return gpg_error (*line? GPG_ERR_LINE_TOO_LONG + : GPG_ERR_INCOMPLETE_LINE); + } + + /* Allow for empty lines and spaces */ + for (p=line; spacep (p); p++) + ; + } + while (!*p || *p == '\n' || *p == '#'); + + *disabled = 0; + if (*p == '!') + { + *disabled = 1; + for (p++; spacep (p); p++) + ; + } + + for (i=0; hexdigitp (p) && i < 40; p++, i++) + if (hexgrip[i] != (*p >= 'a'? (*p & 0xdf): *p)) + goto next_line; + if (i != 40 || !(spacep (p) || *p == '\n')) + { + log_error ("invalid formatted line in ssh control file\n"); + return gpg_error (GPG_ERR_BAD_DATA); + } + + /* Fixme: Get TTL and flags. */ + + return 0; /* Okay: found it. */ +} + + + +/* Add an entry to the control file to mark the key with the keygrip + HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks + for it. This function is in general used to add a key received + through the ssh-add function. We can assume that the user wants to + allow ssh using this key. */ +static gpg_error_t +add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl) +{ + gpg_error_t err; + FILE *fp; + int disabled; + + err = open_control_file (&fp, 1); + if (err) + return err; + + err = search_control_file (fp, hexgrip, &disabled); + if (err && gpg_err_code(err) == GPG_ERR_EOF) + { + struct tm *tp; + time_t atime = time (NULL); + + /* Not yet in the file - add it. Becuase the file has been + opened in append mode, we simply need to write to it. */ + tp = localtime (&atime); + fprintf (fp, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec, + hexgrip, ttl); + + } + fclose (fp); + return 0; +} + + + /* @@ -1377,6 +1542,7 @@ ssh_handler_request_identities (ctrl_t ctrl, gpg_error_t err; gpg_error_t ret_err; int ret; + FILE *ctrl_fp = NULL; /* Prepare buffer stream. */ @@ -1427,6 +1593,19 @@ ssh_handler_request_identities (ctrl_t ctrl, /* FIXME: make sure that buffer gets deallocated properly. */ + /* Fixme: We should better iterate over the control file and check + whether the key file is there. This is better in resepct to + performance if tehre are a lot of key sin our key storage. */ + + err = open_control_file (&ctrl_fp, 0); + if (err) + goto out; + +#warning Really need to fix this fixme. + /* + FIXME: First check whether a key is currently available in the card reader - this should be allowed even without being listed in sshcontrol.txt. + */ + while (1) { dir_entry = readdir (dir); @@ -1435,6 +1614,19 @@ ssh_handler_request_identities (ctrl_t ctrl, if ((strlen (dir_entry->d_name) == 44) && (! strncmp (dir_entry->d_name + 40, ".key", 4))) { + char hexgrip[41]; + int disabled; + + /* We do only want to return keys listed in our control + file. */ + strncpy (hexgrip, dir_entry->d_name, 40); + hexgrip[40] = 0; + if ( strlen (hexgrip) != 40 ) + continue; + if (search_control_file (ctrl_fp, hexgrip, &disabled) + || disabled) + continue; + strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); /* Read file content. */ @@ -1522,6 +1714,9 @@ ssh_handler_request_identities (ctrl_t ctrl, if (dir) closedir (dir); + if (ctrl_fp) + fclose (ctrl_fp); + free (key_directory); xfree (key_path); xfree (buffer); @@ -1802,43 +1997,6 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) return ret_err; } -static gpg_error_t -get_passphrase (ctrl_t ctrl, - const char *description, size_t passphrase_n, char *passphrase) -{ - struct pin_entry_info_s *pi; - gpg_error_t err; - - err = 0; - pi = gcry_calloc_secure (1, sizeof (*pi) + passphrase_n + 1); - if (! pi) - { - err = gpg_error (GPG_ERR_ENOMEM); - goto out; - } - - pi->min_digits = 0; /* We want a real passphrase. */ - pi->max_digits = 8; - pi->max_tries = 1; - pi->failed_tries = 0; - pi->check_cb = NULL; - pi->check_cb_arg = NULL; - pi->cb_errtext = NULL; - pi->max_length = 100; - - err = agent_askpin (ctrl, description, NULL, pi); - if (err) - goto out; - - memcpy (passphrase, pi->pin, passphrase_n); - passphrase[passphrase_n] = 0; - - out: - - xfree (pi); - - return err; -} static gpg_error_t ssh_key_extract_comment (gcry_sexp_t key, char **comment) @@ -1929,76 +2087,100 @@ ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, return err; } + + +/* Store the ssh KEY into our local key storage and protect him after + asking for a passphrase. Cache that passphrase. TTL is the + maximum caching time for that key. If the key already exists in + our key storage, don't do anything. When entering a new key also + add an entry to the sshcontrol file. */ static gpg_error_t ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) { + gpg_error_t err; unsigned char key_grip_raw[21]; - unsigned char *buffer; - unsigned int buffer_n; - char passphrase[100]; - char *description; char key_grip[41]; - char *comment; - gpg_error_t err; + unsigned char *buffer = NULL; + unsigned int buffer_n; + char *description = NULL; + char *comment = NULL; unsigned int i; - int ret; - - description = NULL; - comment = NULL; - buffer = NULL; + struct pin_entry_info_s *pi = NULL; err = ssh_key_grip (key, key_grip_raw); if (err) goto out; - key_grip_raw[sizeof (key_grip_raw) - 1] = 0; - ret = agent_key_available (key_grip_raw); - if (! ret) - goto out; + key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME: Why?? */ + /* Check whether the key is alread in our key storage. Don't do + anything then. */ + if ( !agent_key_available (key_grip_raw) ) + goto out; /* Yes, key is available. */ + + err = ssh_key_extract_comment (key, &comment); if (err) goto out; - ret = asprintf (&description, - "Please provide the passphrase, which should be used " - "for protecting the received secret key `%s':", - comment ? comment : ""); - if (ret < 0) + if ( asprintf (&description, + _("Please enter a passphrase to protect%%0A" + "the received secret key%%0A" + " %s%%0A" + "within gpg-agent's key storage"), + comment ? comment : "?") < 0) { - err = gpg_err_code_from_errno (errno); + err = gpg_error_from_errno (errno); goto out; } - err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase); + + pi = gcry_calloc_secure (1, sizeof (*pi) + 100 + 1); + if (!pi) + { + err = gpg_error_from_errno (errno); + goto out; + } + pi->max_length = 100; + pi->max_tries = 1; + err = agent_askpin (ctrl, description, NULL, pi); if (err) goto out; - err = ssh_key_to_buffer (key, passphrase, &buffer, &buffer_n); + err = ssh_key_to_buffer (key, pi->pin, &buffer, &buffer_n); if (err) goto out; + /* Store this key to our key storage. */ err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0); if (err) goto out; + /* Cache this passphrase. */ for (i = 0; i < 20; i++) sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]); - err = agent_put_cache (key_grip, passphrase, ttl); + err = agent_put_cache (key_grip, pi->pin, ttl); if (err) goto out; - out: + /* And add an entry to the sshcontrol file. */ + err = add_control_entry (ctrl, key_grip, ttl); + + out: + if (pi && pi->max_length) + wipememory (pi->pin, pi->max_length); + xfree (pi); xfree (buffer); xfree (comment); - free (description); - /* FIXME: verify xfree vs free. */ + free (description); /* (asprintf allocated, thus regular free.) */ return err; } + + static gpg_error_t ssh_identity_drop (gcry_sexp_t key) { @@ -2234,12 +2416,9 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) if (err) goto out; - if (opt.verbose) /* FIXME: using log_debug is not good with - verbose. log_debug should only be used in - debugging mode or in sitattions which are - unexpected. */ - log_debug ("received request of length: %u\n", - request_data_size); + if (opt.verbose > 1) + log_info ("received ssh request of length %u\n", + (unsigned int)request_data_size); request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); if (! request) @@ -2277,17 +2456,28 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) break; if (i == DIM (request_specs)) { - log_debug ("request %u is not supported\n", - request_type); + log_info ("ssh request %u is not supported\n", request_type); send_err = 1; goto out; } if (opt.verbose) - log_debug ("executing request handler: %s (%u)\n", + log_info ("ssh request handler for %s (%u) started\n", request_specs[i].identifier, request_specs[i].type); err = (*request_specs[i].handler) (ctrl, request, response); + + if (opt.verbose) + { + if (err) + log_info ("ssh request handler for %s (%u) failed: %s\n", + request_specs[i].identifier, request_specs[i].type, + gpg_strerror (err)); + else + log_info ("ssh request handler for %s (%u) ready\n", + request_specs[i].identifier, request_specs[i].type); + } + if (err) { send_err = 1; @@ -2295,6 +2485,10 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) } response_size = es_ftell (response); + if (opt.verbose > 1) + log_info ("sending ssh response of length %u\n", + (unsigned int)response_size); + err = es_fseek (response, 0, SEEK_SET); if (err) { @@ -2325,6 +2519,8 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) if (send_err) { + if (opt.verbose > 1) + log_info ("sending ssh error response\n"); err = stream_write_uint32 (stream_sock, 1); if (err) goto leave; @@ -2341,7 +2537,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) es_fclose (response); xfree (request_data); /* FIXME? */ - return !! err; + return !!err; } void @@ -2359,6 +2555,21 @@ start_command_handler_ssh (int sock_client) agent_init_default_ctrl (&ctrl); ctrl.connection_fd = sock_client; + /* Because the ssh protocol does not send us information about the + the current TTY setting, we resort here to use those from startup + or those explictly set. */ + if (!ctrl.display && opt.startup_display) + ctrl.display = strdup (opt.startup_display); + if (!ctrl.ttyname && opt.startup_ttyname) + ctrl.ttyname = strdup (opt.startup_ttyname); + if (!ctrl.ttytype && opt.startup_ttytype) + ctrl.ttytype = strdup (opt.startup_ttytype); + if (!ctrl.lc_ctype && opt.startup_lc_ctype) + ctrl.lc_ctype = strdup (opt.startup_lc_ctype); + if (!ctrl.lc_messages && opt.startup_lc_messages) + ctrl.lc_messages = strdup (opt.startup_lc_messages); + + /* Create stream from socket. */ stream_sock = es_fdopen (sock_client, "r+"); if (!stream_sock) diff --git a/agent/command.c b/agent/command.c index dc8a4a158..997140207 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1,5 +1,5 @@ /* command.c - gpg-agent command handler - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -22,12 +22,14 @@ some buffering in secure mempory to protect session keys etc. */ #include <config.h> + #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <unistd.h> +#include <assert.h> #include <assuan.h> @@ -504,6 +506,55 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) } + + +/* READKEY <hexstring_with_keygrip> + + Return the public key for the given keygrip. */ +static int +cmd_readkey (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int rc; + unsigned char grip[20]; + gcry_sexp_t s_pkey = NULL; + + rc = parse_keygrip (ctx, line, grip); + if (rc) + return rc; /* Return immediately as this is already an Assuan error code.*/ + + rc = agent_public_key_from_file (ctrl, grip, &s_pkey); + if (!rc) + { + size_t len; + unsigned char *buf; + + len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xtrymalloc (len); + if (!buf) + rc = gpg_error_from_errno (errno); + else + { + len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + rc = assuan_send_data (ctx, buf, len); + rc = map_assuan_err (rc); + xfree (buf); + } + gcry_sexp_release (s_pkey); + } + + if (rc) + log_error ("command readkey failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + + + + + /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>] This function is usually used to ask for a passphrase to be used @@ -894,6 +945,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "PKSIGN", cmd_pksign }, { "PKDECRYPT", cmd_pkdecrypt }, { "GENKEY", cmd_genkey }, + { "READKEY", cmd_readkey }, { "GET_PASSPHRASE", cmd_get_passphrase }, { "PRESET_PASSPHRASE", cmd_preset_passphrase }, { "CLEAR_PASSPHRASE", cmd_clear_passphrase }, diff --git a/agent/findkey.c b/agent/findkey.c index 1ac57ad07..86a28d511 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -39,7 +39,9 @@ struct try_unprotect_arg_s { }; - +/* Write an S-expression formatted key to our key storage. With FORCE + pased as true an existsing key with the given GRIP will get + overwritten. */ int agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force) @@ -48,51 +50,44 @@ agent_write_private_key (const unsigned char *grip, char *fname; FILE *fp; char hexgrip[40+4+1]; + int fd; for (i=0; i < 20; i++) sprintf (hexgrip+2*i, "%02X", grip[i]); strcpy (hexgrip+40, ".key"); fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL); - if (force) - fp = fopen (fname, "wb"); - else - { - int fd; - - if (!access (fname, F_OK)) - { - log_error ("secret key file `%s' already exists\n", fname); - xfree (fname); - return gpg_error (GPG_ERR_GENERAL); - } - /* We would like to create FNAME but only if it does not already - exist. We cannot make this guarantee just using POSIX (GNU - provides the "x" opentype for fopen, however, this is not - portable). Thus, we use the more flexible open function and - then use fdopen to obtain a stream. + if (!force && !access (fname, F_OK)) + { + log_error ("secret key file `%s' already exists\n", fname); + xfree (fname); + return gpg_error (GPG_ERR_GENERAL); + } - The mode parameter to open is what fopen uses. It will be - combined with the process' umask automatically. */ - fd = open (fname, O_CREAT | O_EXCL | O_RDWR, - S_IRUSR | S_IWUSR + /* In FORCE mode we would like to create FNAME but only if it does + not already exist. We cannot make this guarantee just using + POSIX (GNU provides the "x" opentype for fopen, however, this is + not portable). Thus, we use the more flexible open function and + then use fdopen to obtain a stream. */ + fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY) + : (O_CREAT | O_EXCL | O_WRONLY), + S_IRUSR | S_IWUSR #ifndef HAVE_W32_SYSTEM - | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH + | S_IRGRP #endif ); - if (fd < 0) - fp = 0; - else - { - fp = fdopen (fd, "wb"); - if (!fp) - { - int save_e = errno; - close (fd); - errno = save_e; - } - } + if (fd < 0) + fp = NULL; + else + { + fp = fdopen (fd, "wb"); + if (!fp) + { + int save_e = errno; + close (fd); + errno = save_e; + } } if (!fp) @@ -263,6 +258,8 @@ unprotect (CTRL ctrl, const char *desc_text, } pi = gcry_calloc_secure (1, sizeof (*pi) + 100); + if (!pi) + return gpg_error_from_errno (errno); pi->max_length = 100; pi->min_digits = 0; /* we want a real passphrase */ pi->max_digits = 8; @@ -285,32 +282,22 @@ unprotect (CTRL ctrl, const char *desc_text, } - -/* Return the secret key as an S-Exp in RESULT after locating it using - the grip. Returns NULL in RESULT if the operation should be - diverted to a token; SHADOW_INFO will point then to an allocated - S-Expression with the shadow_info part from the file. With - IGNORE_CACHE passed as true the passphrase is not taken from the - cache. DESC_TEXT may be set to present a custom description for the - pinentry. */ -gpg_error_t -agent_key_from_file (CTRL ctrl, const char *desc_text, - const unsigned char *grip, unsigned char **shadow_info, - int ignore_cache, gcry_sexp_t *result) +/* Read the key identified by GRIP from the private key directory and + return it as an gcrypt S-expression object in RESULT. On failure + returns an error code and stores NULL at RESULT. */ +static gpg_error_t +read_key_file (const unsigned char *grip, gcry_sexp_t *result) { int i, rc; char *fname; FILE *fp; struct stat st; unsigned char *buf; - size_t len, buflen, erroff; + size_t buflen, erroff; gcry_sexp_t s_skey; char hexgrip[40+4+1]; - int got_shadow_info = 0; *result = NULL; - if (shadow_info) - *shadow_info = NULL; for (i=0; i < 20; i++) sprintf (hexgrip+2*i, "%02X", grip[i]); @@ -336,8 +323,8 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, } buflen = st.st_size; - buf = xmalloc (buflen+1); - if (fread (buf, buflen, 1, fp) != 1) + buf = xtrymalloc (buflen+1); + if (!buf || fread (buf, buflen, 1, fp) != 1) { rc = gpg_error_from_errno (errno); log_error ("error reading `%s': %s\n", fname, strerror (errno)); @@ -347,6 +334,7 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, return rc; } + /* Convert the file into a gcrypt S-expression object. */ rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); xfree (fname); fclose (fp); @@ -357,18 +345,52 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, (unsigned int)erroff, gpg_strerror (rc)); return rc; } + *result = s_skey; + return 0; +} + + +/* Return the secret key as an S-Exp in RESULT after locating it using + the grip. Returns NULL in RESULT if the operation should be + diverted to a token; SHADOW_INFO will point then to an allocated + S-Expression with the shadow_info part from the file. With + IGNORE_CACHE passed as true the passphrase is not taken from the + cache. DESC_TEXT may be set to present a custom description for the + pinentry. */ +gpg_error_t +agent_key_from_file (ctrl_t ctrl, const char *desc_text, + const unsigned char *grip, unsigned char **shadow_info, + int ignore_cache, gcry_sexp_t *result) +{ + int rc; + unsigned char *buf; + size_t len, buflen, erroff; + gcry_sexp_t s_skey; + int got_shadow_info = 0; + + *result = NULL; + if (shadow_info) + *shadow_info = NULL; + + rc = read_key_file (grip, &s_skey); + if (rc) + return rc; + + /* For use with the protection functions we also need the key as an + canonical encoded S-expression in abuffer. Create this buffer + now. */ len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0); assert (len); buf = xtrymalloc (len); if (!buf) { - rc = out_of_core (); + rc = gpg_error_from_errno (errno); gcry_sexp_release (s_skey); return rc; } len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len); assert (len); - gcry_sexp_release (s_skey); + switch (agent_private_key_type (buf)) { @@ -381,7 +403,7 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, char *desc_text_final; const char *comment = NULL; - /* Note, that we will take the comment as a C styring for + /* Note, that we will take the comment as a C string for display purposes; i.e. all stuff beyond a Nul character is ignored. */ comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0); @@ -460,6 +482,8 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, rc = gpg_error (GPG_ERR_BAD_SECKEY); break; } + gcry_sexp_release (s_skey); + s_skey = NULL; if (rc || got_shadow_info) { xfree (buf); @@ -481,6 +505,200 @@ agent_key_from_file (CTRL ctrl, const char *desc_text, return 0; } + + +/* Return the public key for the keygrip GRIP. The result is stored + at RESULT. This function extracts the public key from the private + key database. On failure an error code is returned and NULL stored + at RESULT. */ +gpg_error_t +agent_public_key_from_file (ctrl_t ctrl, + const unsigned char *grip, + gcry_sexp_t *result) +{ + int i, idx, rc; + gcry_sexp_t s_skey; + const char *algoname; + gcry_sexp_t uri_sexp, comment_sexp; + const char *uri, *comment; + size_t uri_length, comment_length; + char *format, *p; + void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2 + for comment + end-of-list. */ + int argidx; + gcry_sexp_t list, l2; + const char *name; + const char *s; + size_t n; + const char *elems; + gcry_mpi_t *array; + + *result = NULL; + + rc = read_key_file (grip, &s_skey); + if (rc) + return rc; + + list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 ); + if (!list) + list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 ); + if (!list) + list = gcry_sexp_find_token (s_skey, "private-key", 0 ); + if (!list) + { + log_error ("invalid private key format\n"); + gcry_sexp_release (s_skey); + return gpg_error (GPG_ERR_BAD_SECKEY); + } + + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + name = gcry_sexp_nth_data (list, 0, &n); + if (n==3 && !memcmp (name, "rsa", 3)) + { + algoname = "rsa"; + elems = "ne"; + } + else if (n==3 && !memcmp (name, "dsa", 3)) + { + algoname = "dsa"; + elems = "pqgy"; + } + else if (n==3 && !memcmp (name, "elg", 3)) + { + algoname = "elg"; + elems = "pgy"; + } + else + { + log_error ("unknown private key algorithm\n"); + gcry_sexp_release (list); + gcry_sexp_release (s_skey); + return gpg_error (GPG_ERR_BAD_SECKEY); + } + + /* Allocate an array for the parameters and copy them out of the + secret key. FIXME: We should have a generic copy function. */ + array = xtrycalloc (strlen(elems) + 1, sizeof *array); + if (!array) + { + rc = gpg_error_from_errno (errno); + gcry_sexp_release (list); + gcry_sexp_release (s_skey); + return rc; + } + + for (idx=0, s=elems; *s; s++, idx++ ) + { + l2 = gcry_sexp_find_token (list, s, 1); + if (!l2) + { + /* Required parameter not found. */ + for (i=0; i<idx; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (list); + gcry_sexp_release (s_skey); + return gpg_error (GPG_ERR_BAD_SECKEY); + } + array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + if (!array[idx]) + { + /* Required parameter is invalid. */ + for (i=0; i<idx; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (list); + gcry_sexp_release (s_skey); + return gpg_error (GPG_ERR_BAD_SECKEY); + } + } + gcry_sexp_release (list); + list = NULL; + + uri = NULL; + uri_length = 0; + uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0); + if (uri_sexp) + uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length); + + comment = NULL; + comment_length = 0; + comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0); + if (comment_sexp) + comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length); + + gcry_sexp_release (s_skey); + s_skey = NULL; + + + /* FIXME: The following thing is pretty ugly code; we should + investigate how to make it cleaner. Probably code to handle + canonical S-expressions in a memory buffer is better suioted for + such a task. After all that is what we do in protect.c. Neeed + to find common patterns and write a straightformward API to use + them. */ + assert (sizeof (size_t) <= sizeof (void*)); + + format = xtrymalloc (15+7*strlen (elems)+10+15+1+1); + if (!format) + { + rc = gpg_error_from_errno (errno); + for (i=0; array[i]; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (uri_sexp); + gcry_sexp_release (comment_sexp); + return rc; + } + + argidx = 0; + p = stpcpy (stpcpy (format, "(public-key("), algoname); + for (idx=0, s=elems; *s; s++, idx++ ) + { + *p++ = '('; + *p++ = *s; + p = stpcpy (p, " %m)"); + assert (argidx < DIM (args)); + args[argidx++] = array[idx]; + } + *p++ = ')'; + if (uri) + { + p = stpcpy (p, "(uri %b)"); + assert (argidx+1 < DIM (args)); + args[argidx++] = (void *)uri_length; + args[argidx++] = (void *)uri; + } + if (comment) + { + p = stpcpy (p, "(comment %b)"); + assert (argidx+1 < DIM (args)); + args[argidx++] = (void *)comment_length; + args[argidx++] = (void*)comment; + } + *p++ = ')'; + *p = 0; + assert (argidx < DIM (args)); + args[argidx] = NULL; + + rc = gcry_sexp_build_array (&list, NULL, format, args); + xfree (format); + for (i=0; array[i]; i++) + gcry_mpi_release (array[i]); + xfree (array); + gcry_sexp_release (uri_sexp); + gcry_sexp_release (comment_sexp); + + if (!rc) + *result = list; + return rc; +} + + + /* Return the secret key as an S-Exp after locating it using the grip. Returns NULL if key is not available. 0 = key is available */ int diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 47488ee69..338248d1a 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1,5 +1,5 @@ /* gpg-agent.c - The GnuPG Agent - * Copyright (C) 2000, 2001, 2002, 2003, + * Copyright (C) 2000, 2001, 2002, 2003, 2004, * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. @@ -147,7 +147,7 @@ static ARGPARSE_OPTS opts[] = { N_("allow clients to mark keys as \"trusted\"")}, { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, - { oSSHSupport, "ssh-support", 0, N_("enable secure ssh-agent emulation") }, + { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") }, {0} }; @@ -458,7 +458,6 @@ main (int argc, char **argv ) int standard_socket = 0; gpg_error_t err; - set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); /* Please note that we may running SUID(ROOT), so be very CAREFUL @@ -513,6 +512,23 @@ main (int argc, char **argv ) opt.homedir = default_homedir (); + /* Record the some original Denvironment settings. */ + opt.startup_display = getenv ("DISPLAY"); + if (opt.startup_display) + opt.startup_display = xstrdup (opt.startup_display); + opt.startup_ttyname = ttyname (0); + if (opt.startup_ttyname) + opt.startup_ttyname = xstrdup (opt.startup_ttyname); + opt.startup_ttytype = getenv ("TERM"); + if (opt.startup_ttytype) + opt.startup_ttytype = xstrdup (opt.startup_ttytype); + /* Fixme: Neen to use the locale fucntion here. */ + opt.startup_lc_ctype = getenv ("LC_CTYPE"); + if (opt.startup_lc_ctype) + opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype); + opt.startup_lc_messages = getenv ("LC_MESSAGES"); + if (opt.startup_lc_messages) + opt.startup_lc_messages = xstrdup (opt.startup_lc_messages); /* Check whether we have a config file on the commandline */ orig_argc = argc; @@ -624,11 +640,7 @@ main (int argc, char **argv ) case oKeepTTY: opt.keep_tty = 1; break; case oKeepDISPLAY: opt.keep_display = 1; break; - case oSSHSupport: - opt.ssh_support = 1; - opt.keep_tty = 1; - opt.keep_display = 1; - break; + case oSSHSupport: opt.ssh_support = 1; break; default : pargs.err = configfp? 1:2; break; } @@ -784,7 +796,7 @@ main (int argc, char **argv ) /* Remove the DISPLAY variable so that a pinentry does not default to a specific display. There is still a default - display when gpg-agent weas started using --display or a + display when gpg-agent was started using --display or a client requested this using an OPTION command. */ #ifndef HAVE_W32_SYSTEM if (!opt.keep_display) diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 6c0bd8b83..726990315 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -31,8 +31,12 @@ Libgcrypt. Here is an example of an unprotected file: (u #304559a..[some bytes not shown]..9b#) ) (uri http://foo.bar x-foo:whatever_you_want) + (comment whatever) ) +"comment" and "uri" are optional. "comment" is currently used to keep +track of ssh key comments. + Actually this form should not be used for regular purposes and only accepted by gpg-agent with the configuration option: --allow-non-canonical-key-format. The regular way to represent the @@ -62,6 +66,7 @@ A protected key is like this: (protected mode (parms) encrypted_octet_string) ) (uri http://foo.bar x-foo:whatever_you_want) + (comment whatever) ) @@ -134,6 +139,7 @@ to keys stored on a token: (shadowed protocol (info)) ) (uri http://foo.bar x-foo:whatever_you_want) + (comment whatever) ) The currently used protocol is "ti-v1" (token info version 1). The diff --git a/agent/protect.c b/agent/protect.c index edcca36d9..cafeb4685 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -117,7 +117,7 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) /* Encrypt the parameter block starting at PROTBEGIN with length PROTLEN using the utf8 encoded key PASSPHRASE and return the entire - encrypted block in RESULT or ereturn with an error code. SHA1HASH + encrypted block in RESULT or return with an error code. SHA1HASH is the 20 byte SHA-1 hash required for the integrity code. The parameter block is expected to be an incomplete S-Expression of diff --git a/agent/query.c b/agent/query.c index 4aafcbe99..622a2662c 100644 --- a/agent/query.c +++ b/agent/query.c @@ -86,7 +86,7 @@ initialize_module_query (void) /* Unlock the pinentry so that another thread can start one and disconnect that pinentry - we do this after the unlock so that a stalled pinentry does not block other threads. Fixme: We should - have a timeout in Assuan for the disconnetc operation. */ + have a timeout in Assuan for the disconnect operation. */ static int unlock_pinentry (int rc) { -- cgit v1.2.3 From 3af261572bdf938f0a2fdde4d9aec82153a7e0e4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 24 Feb 2005 17:36:11 +0000 Subject: * gpg-agent.c (handle_connections): Need to check for events if select returns with -1. * tools.texi (gpg-connect-agent): New. * app-openpgp.c (get_one_do): Never try to get a non cacheable object from the cache. (get_one_do): Add new arg to return an error code. Changed all callers. (do_getattr): Let it return a proper error code. * app.c (select_application): Return an error code and the application context in an new arg. * command.c (open_card): Adjusted for that. Don't use the fallback if no card is present. Return an error if the card has been removed without a reset. (do_reset, cmd_serialno): Clear that error flag. (TEST_CARD_REMOVAL): New. Use it with all command handlers. * scdaemon.c (ticker_thread): Termintate if a shutdown is pending. * apdu.c: Added some PCSC error codes. (pcsc_error_to_sw): New. (reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu) (open_pcsc_reader): Do proper error code mapping. * gpg-connect-agent.c: New. * Makefile.am: Add it. --- agent/ChangeLog | 5 + agent/gpg-agent.c | 5 + common/simple-pwquery.c | 2 +- common/xreadline.c | 2 +- doc/ChangeLog | 4 + doc/gpg-agent.texi | 14 +- doc/tools.texi | 62 +++++++ scd/ChangeLog | 23 +++ scd/apdu.c | 419 +++++++++++++++++++++++++++------------------- scd/app-common.h | 3 +- scd/app-openpgp.c | 45 +++-- scd/app.c | 28 ++-- scd/command.c | 81 +++++++-- scd/scdaemon.c | 3 +- tests/asschk.c | 4 +- tools/ChangeLog | 5 + tools/Makefile.am | 13 +- tools/gpg-connect-agent.c | 362 +++++++++++++++++++++++++++++++++++++++ 18 files changed, 840 insertions(+), 240 deletions(-) create mode 100644 tools/gpg-connect-agent.c diff --git a/agent/ChangeLog b/agent/ChangeLog index 47ca2debf..775a44489 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-02-24 Werner Koch <wk@g10code.com> + + * gpg-agent.c (handle_connections): Need to check for events if + select returns with -1. + 2005-02-23 Werner Koch <wk@g10code.com> * command-ssh.c (get_passphrase): Removed. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 338248d1a..113489306 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1463,6 +1463,11 @@ handle_connections (int listen_fd, int listen_fd_ssh) ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev); if (ret == -1) { + if (pth_event_occurred (ev)) + { + handle_signal (signo); + continue; + } log_error (_("pth_select failed: %s - waiting 1s\n"), strerror (errno)); pth_sleep (1); diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 0b70ddecc..37a45816c 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -1,4 +1,4 @@ -/* simple-pwquery.c - A simple password query cleint for gpg-agent +/* simple-pwquery.c - A simple password query client for gpg-agent * Copyright (C) 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. diff --git a/common/xreadline.c b/common/xreadline.c index 85f0af02e..23aa35269 100644 --- a/common/xreadline.c +++ b/common/xreadline.c @@ -39,7 +39,7 @@ 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 + the end of the line so that the next read start with the next line. Note that MAX_LENGTH must be re-initialzied in this case.. Note: The returned buffer is allocated with enough extra space to diff --git a/doc/ChangeLog b/doc/ChangeLog index 49e8b026f..07f94f338 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-02-24 Werner Koch <wk@g10code.com> + + * tools.texi (gpg-connect-agent): New. + 2005-02-14 Werner Koch <wk@g10code.com> * gpgsm.texi (Certificate Management): Document --import. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 01b4227c6..17bd59c7a 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -326,10 +326,8 @@ 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. -@item --ssh-support -@itemx --ssh-support -@opindex ssh-support -@opindex ssh +@item --enable-ssh-support +@opindex enable-ssh-support Enable emulation of the OpenSSH Agent protocol. @@ -350,13 +348,11 @@ Once, a key has been added to the gpg-agent this way, the gpg-agent will be ready to use the key. Note: in case the gpg-agent receives a signature request, the user -might need to be prompted for a passphrased, which is necessary for +might need to be prompted for a passphrase, which is necessary for decrypting the stored key. Since the ssh-agent protocol does not contain a mechanism for telling the agent on which display/terminal it -is running, gpg-agent's --ssh-support switch implies --keep-display -and --keep-tty. This strategy causes the gpg-agent to open a pinentry -on the display or on the terminal, on which it (the gpg-agent) was -started. +is running, gpg-agent's ssh-support will use the TTY or X display where +gpg-agent has been started. @end table diff --git a/doc/tools.texi b/doc/tools.texi index 684975e19..7c963622f 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -13,6 +13,7 @@ GnuPG comes with a couple of smaller tools: * gpgconf:: Modify .gnupg home directories. * gpgsm-gencert.sh:: Generate an X.509 certificate request. * gpg-preset-passphrase:: Put a passphrase into the cache. +* gpg-connect-agent:: Communicate with a running agent. @end menu @c @@ -665,3 +666,64 @@ for other users. + +@c +@c GPG-CONNECT-AGENT +@c +@node gpg-connect-agent +@section Communicate with a runnig agent. + +The @command{gpg-connect-agent} is a utility to communicate with a +running @command{gpg-agent}. It is useful to check out the commands +gpg-agent provides using the Assuan interface. It might also be useful +for scripting simple applications. Inputis expected at stdin and out +put gets printed to stdout. + +It is very similar to running @command{gpg-agent} in server mode; but +here we connect to a running instance. + +@menu +* Invoking gpg-connect-agent:: List of all commands and options. +@end menu + + +@node Invoking gpg-connect-agent +@subsection List of all commands and options. + +@noindent +@command{gpg-connect-agent} is invoked this way: + +@example +gpg-connect-agent [options] +@end example + +@noindent +The following options may be used: + +@table @gnupgtabopt +@item -v +@itemx --verbose +@opindex verbose +Output additional information while running. + +@item -q +@item --quiet +@opindex q +@opindex quiet +Try to be as quiet as possible. + +@item --homedir @var{dir} +@opindex homedir +Set the name of the home directory to @var{dir}. If his option is not +used, the home directory defaults to @file{~/.gnupg}. It is only +recognized when given on the command line. It also overrides any home +directory stated through the environment variable @env{GNUPGHOME} or +(on W32 systems) by means on the Registry entry +@var{HKCU\Software\GNU\GnuPG:HomeDir}. + + +@end table + + + + diff --git a/scd/ChangeLog b/scd/ChangeLog index 054463d6d..c78bd011f 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,26 @@ +2005-02-24 Werner Koch <wk@g10code.com> + + * app-openpgp.c (get_one_do): Never try to get a non cacheable + object from the cache. + (get_one_do): Add new arg to return an error code. Changed all + callers. + (do_getattr): Let it return a proper error code. + + * app.c (select_application): Return an error code and the + application context in an new arg. + * command.c (open_card): Adjusted for that. Don't use the + fallback if no card is present. Return an error if the card has + been removed without a reset. + (do_reset, cmd_serialno): Clear that error flag. + (TEST_CARD_REMOVAL): New. Use it with all command handlers. + + * scdaemon.c (ticker_thread): Termintate if a shutdown is pending. + + * apdu.c: Added some PCSC error codes. + (pcsc_error_to_sw): New. + (reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu) + (open_pcsc_reader): Do proper error code mapping. + 2005-02-22 Werner Koch <wk@g10code.com> * app-openpgp.c (app_local_s): New field PK. diff --git a/scd/apdu.c b/scd/apdu.c index 040de1461..33b0802c1 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -74,7 +74,7 @@ #endif #endif - + #define MAX_READER 4 /* Number of readers we support concurrently. */ @@ -158,14 +158,14 @@ static char (* DLSTDCALL CT_data) (unsigned short ctn, unsigned char *dad, static char (* DLSTDCALL CT_close) (unsigned short ctn); /* PC/SC constants and function pointer. */ -#define PCSC_SCOPE_USER 0 -#define PCSC_SCOPE_TERMINAL 1 -#define PCSC_SCOPE_SYSTEM 2 -#define PCSC_SCOPE_GLOBAL 3 +#define PCSC_SCOPE_USER 0 +#define PCSC_SCOPE_TERMINAL 1 +#define PCSC_SCOPE_SYSTEM 2 +#define PCSC_SCOPE_GLOBAL 3 -#define PCSC_PROTOCOL_T0 1 -#define PCSC_PROTOCOL_T1 2 -#define PCSC_PROTOCOL_RAW 4 +#define PCSC_PROTOCOL_T0 1 +#define PCSC_PROTOCOL_T1 2 +#define PCSC_PROTOCOL_RAW 4 #define PCSC_SHARE_EXCLUSIVE 1 #define PCSC_SHARE_SHARED 2 @@ -176,7 +176,7 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn); #define PCSC_UNPOWER_CARD 2 #define PCSC_EJECT_CARD 3 -#define PCSC_UNKNOWN 0x0001 +#define PCSC_UNKNOWN 0x0001 #define PCSC_ABSENT 0x0002 /* Card is absent. */ #define PCSC_PRESENT 0x0004 /* Card is present. */ #define PCSC_SWALLOWED 0x0008 /* Card is present and electrical connected. */ @@ -196,10 +196,32 @@ static char (* DLSTDCALL CT_close) (unsigned short ctn); #define PCSC_STATE_INUSE 0x0100 /* Shared mode. */ #define PCSC_STATE_MUTE 0x0200 /* Unresponsive card. */ - -struct pcsc_io_request_s +/* Some PC/SC error codes. */ +#define PCSC_E_CANCELLED 0x80100002 +#define PCSC_E_CANT_DISPOSE 0x8010000E +#define PCSC_E_INSUFFICIENT_BUFFER 0x80100008 +#define PCSC_E_INVALID_ATR 0x80100015 +#define PCSC_E_INVALID_HANDLE 0x80100003 +#define PCSC_E_INVALID_PARAMETER 0x80100004 +#define PCSC_E_INVALID_TARGET 0x80100005 +#define PCSC_E_INVALID_VALUE 0x80100011 +#define PCSC_E_NO_MEMORY 0x80100006 +#define PCSC_E_UNKNOWN_READER 0x80100009 +#define PCSC_E_TIMEOUT 0x8010000A +#define PCSC_E_SHARING_VIOLATION 0x8010000B +#define PCSC_E_NO_SMARTCARD 0x8010000C +#define PCSC_E_UNKNOWN_CARD 0x8010000D +#define PCSC_E_PROTO_MISMATCH 0x8010000F +#define PCSC_E_NOT_READY 0x80100010 +#define PCSC_E_SYSTEM_CANCELLED 0x80100012 +#define PCSC_E_NOT_TRANSACTED 0x80100016 +#define PCSC_E_READER_UNAVAILABLE 0x80100017 +#define PCSC_W_REMOVED_CARD 0x80100069 + + +struct pcsc_io_request_s { - unsigned long protocol; + unsigned long protocol; unsigned long pci_len; }; @@ -262,15 +284,15 @@ long (* DLSTDCALL pcsc_set_timeout) (unsigned long context, -/* +/* Helper */ - + /* Find an unused reader slot for PORTSTR and put it into the reader table. Return -1 on error or the index into the reader table. */ -static int -new_reader_slot (void) +static int +new_reader_slot (void) { int i, reader = -1; @@ -387,8 +409,8 @@ apdu_strerror (int rc) -/* - ct API Interface +/* + ct API Interface */ static const char * @@ -425,9 +447,9 @@ ct_activate_card (int slot) int rc; unsigned char dad[1], sad[1], cmd[11], buf[256]; unsigned short buflen; - + /* Check whether card has been inserted. */ - dad[0] = 1; /* Destination address: CT. */ + dad[0] = 1; /* Destination address: CT. */ sad[0] = 2; /* Source address: Host. */ cmd[0] = 0x20; /* Class byte. */ @@ -446,8 +468,8 @@ ct_activate_card (int slot) return SW_HOST_CARD_IO_ERROR; } - /* Connected, now activate the card. */ - dad[0] = 1; /* Destination address: CT. */ + /* Connected, now activate the card. */ + dad[0] = 1; /* Destination address: CT. */ sad[0] = 2; /* Source address: Host. */ cmd[0] = 0x20; /* Class byte. */ @@ -517,13 +539,13 @@ ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, int rc; unsigned char dad[1], sad[1]; unsigned short ctbuflen; - + /* If we don't have an ATR, we need to reset the reader first. */ if (!reader_table[slot].atrlen && (rc = reset_ct_reader (slot))) return rc; - dad[0] = 0; /* Destination address: Card. */ + dad[0] = 0; /* Destination address: Card. */ sad[0] = 2; /* Source address: Host. */ ctbuflen = *buflen; if (DBG_CARD_IO) @@ -582,6 +604,10 @@ open_ct_reader (int port) } +/* + PC/SC Interface + */ + #ifdef NEED_PCSC_WRAPPER static int writen (int fd, const void *buf, size_t nbytes) @@ -624,7 +650,7 @@ readn (int fd, void *buf, size_t buflen, size_t *nread) #else n = read (fd, buf, nleft); #endif - if (n < 0 && errno == EINTR) + if (n < 0 && errno == EINTR) continue; if (n < 0) return -1; /* read error. */ @@ -637,7 +663,7 @@ readn (int fd, void *buf, size_t buflen, size_t *nread) *nread = buflen - nleft; /* log_printhex (" readn:", orig_buf, *nread); */ - + return 0; } #endif /*NEED_PCSC_WRAPPER*/ @@ -656,48 +682,73 @@ pcsc_error_string (long err) { case 0x0002: s = "cancelled"; break; case 0x000e: s = "can't dispose"; break; - case 0x0008: s = "insufficient buffer"; break; + case 0x0008: s = "insufficient buffer"; break; case 0x0015: s = "invalid ATR"; break; case 0x0003: s = "invalid handle"; break; - case 0x0004: s = "invalid parameter"; break; + case 0x0004: s = "invalid parameter"; break; case 0x0005: s = "invalid target"; break; - case 0x0011: s = "invalid value"; break; - case 0x0006: s = "no memory"; break; - case 0x0013: s = "comm error"; break; - case 0x0001: s = "internal error"; break; - case 0x0014: s = "unknown error"; break; - case 0x0007: s = "waited too long"; break; + case 0x0011: s = "invalid value"; break; + case 0x0006: s = "no memory"; break; + case 0x0013: s = "comm error"; break; + case 0x0001: s = "internal error"; break; + case 0x0014: s = "unknown error"; break; + case 0x0007: s = "waited too long"; break; case 0x0009: s = "unknown reader"; break; - case 0x000a: s = "timeout"; break; - case 0x000b: s = "sharing violation"; break; + case 0x000a: s = "timeout"; break; + case 0x000b: s = "sharing violation"; break; case 0x000c: s = "no smartcard"; break; - case 0x000d: s = "unknown card"; break; - case 0x000f: s = "proto mismatch"; break; - case 0x0010: s = "not ready"; break; - case 0x0012: s = "system cancelled"; break; + case 0x000d: s = "unknown card"; break; + case 0x000f: s = "proto mismatch"; break; + case 0x0010: s = "not ready"; break; + case 0x0012: s = "system cancelled"; break; case 0x0016: s = "not transacted"; break; - case 0x0017: s = "reader unavailable"; break; - case 0x0065: s = "unsupported card"; break; - case 0x0066: s = "unresponsive card"; break; - case 0x0067: s = "unpowered card"; break; - case 0x0068: s = "reset card"; break; - case 0x0069: s = "removed card"; break; - case 0x006a: s = "inserted card"; break; - case 0x001f: s = "unsupported feature"; break; - case 0x0019: s = "PCI too small"; break; - case 0x001a: s = "reader unsupported"; break; - case 0x001b: s = "duplicate reader"; break; - case 0x001c: s = "card unsupported"; break; - case 0x001d: s = "no service"; break; - case 0x001e: s = "service stopped"; break; + case 0x0017: s = "reader unavailable"; break; + case 0x0065: s = "unsupported card"; break; + case 0x0066: s = "unresponsive card"; break; + case 0x0067: s = "unpowered card"; break; + case 0x0068: s = "reset card"; break; + case 0x0069: s = "removed card"; break; + case 0x006a: s = "inserted card"; break; + case 0x001f: s = "unsupported feature"; break; + case 0x0019: s = "PCI too small"; break; + case 0x001a: s = "reader unsupported"; break; + case 0x001b: s = "duplicate reader"; break; + case 0x001c: s = "card unsupported"; break; + case 0x001d: s = "no service"; break; + case 0x001e: s = "service stopped"; break; default: s = "unknown PC/SC error code"; break; } return s; } -/* - PC/SC Interface - */ +/* Map PC/SC error codes to our special host status words. */ +static int +pcsc_error_to_sw (long ec) +{ + int rc; + + switch (ec) + { + case 0: rc = 0; break; + + case PCSC_E_CANCELLED: rc = SW_HOST_ABORTED; break; + case PCSC_E_NO_MEMORY: rc = SW_HOST_OUT_OF_CORE; break; + case PCSC_E_TIMEOUT: rc = SW_HOST_CARD_IO_ERROR; break; + case PCSC_E_SHARING_VIOLATION: rc = SW_HOST_LOCKING_FAILED; break; + case PCSC_E_NO_SMARTCARD: rc = SW_HOST_NO_CARD; break; + case PCSC_W_REMOVED_CARD: rc = SW_HOST_NO_CARD; break; + + case PCSC_E_INVALID_TARGET: + case PCSC_E_INVALID_VALUE: + case PCSC_E_INVALID_HANDLE: + case PCSC_E_INVALID_PARAMETER: + case PCSC_E_INSUFFICIENT_BUFFER: rc = SW_HOST_INV_VALUE; break; + + default: rc = SW_HOST_GENERAL_ERROR; break; + } + + return rc; +} static void dump_pcsc_reader_status (int slot) @@ -713,6 +764,8 @@ dump_pcsc_reader_status (int slot) } +/* Send an PC/SC reset command and return a status word on error or 0 + on success. */ static int reset_pcsc_reader (int slot) { @@ -722,15 +775,16 @@ reset_pcsc_reader (int slot) size_t len; int i, n; unsigned char msgbuf[9]; + int sw = SW_HOST_CARD_IO_ERROR; slotp = reader_table + slot; - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 || slotp->pcsc.pid == (pid_t)(-1) ) { log_error ("pcsc_get_status: pcsc-wrapper not running\n"); - return SW_HOST_CARD_IO_ERROR; + return sw; } msgbuf[0] = 0x05; /* RESET command. */ @@ -763,16 +817,23 @@ reset_pcsc_reader (int slot) if (len > DIM (slotp->atr)) { log_error ("PC/SC returned a too large ATR (len=%x)\n", len); + sw = SW_HOST_GENERAL_ERROR; goto command_failed; } err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; if (err) { - log_error ("PC/SC RESET failed: %s\n", pcsc_error_string (err)); + log_error ("PC/SC RESET failed: %s (0x%lx)\n", + pcsc_error_string (err), err); + /* If the error code is no smart card, we should not considere + this a major error and close the wrapper. */ + sw = pcsc_error_to_sw (err); + if (err == PCSC_E_NO_SMARTCARD) + return sw; goto command_failed; } - /* The open fucntion may return a zero for the ATR length to + /* The open function may return a zero for the ATR length to indicate that no card is present. */ n = len; if (n) @@ -796,7 +857,7 @@ reset_pcsc_reader (int slot) kill (slotp->pcsc.pid, SIGTERM); slotp->pcsc.pid = (pid_t)(-1); slotp->used = 0; - return -1; + return sw; #else /* !NEED_PCSC_WRAPPER */ long err; @@ -827,10 +888,10 @@ reset_pcsc_reader (int slot) log_error ("pcsc_connect failed: %s (0x%lx)\n", pcsc_error_string (err), err); reader_table[slot].pcsc.card = 0; - return SW_HOST_CARD_IO_ERROR; - } + return pcsc_error_to_sw (err); + } + - atrlen = 33; nreader = sizeof reader - 1; err = pcsc_status (reader_table[slot].pcsc.card, @@ -842,7 +903,7 @@ reset_pcsc_reader (int slot) log_error ("pcsc_status failed: %s (0x%lx)\n", pcsc_error_string (err), err); reader_table[slot].atrlen = 0; - return SW_HOST_CARD_IO_ERROR; + return pcsc_error_to_sw (err); } if (atrlen >= DIM (reader_table[0].atr)) log_bug ("ATR returned by pcsc_status is too large\n"); @@ -863,15 +924,16 @@ pcsc_get_status (int slot, unsigned int *status) int i, n; unsigned char msgbuf[9]; unsigned char buffer[12]; + int sw = SW_HOST_CARD_IO_ERROR; slotp = reader_table + slot; - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 || slotp->pcsc.pid == (pid_t)(-1) ) { log_error ("pcsc_get_status: pcsc-wrapper not running\n"); - return SW_HOST_CARD_IO_ERROR; + return sw; } msgbuf[0] = 0x04; /* STATUS command. */ @@ -906,11 +968,12 @@ pcsc_get_status (int slot, unsigned int *status) { log_error ("pcsc_status failed: %s (0x%lx)\n", pcsc_error_string (err), err); - return SW_HOST_CARD_IO_ERROR; + /* This is a proper error code, so return immediately. */ + return pcsc_error_to_sw (err); } full_len = len; - + n = 8 < len ? 8 : len; if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != 8) { @@ -935,7 +998,7 @@ pcsc_get_status (int slot, unsigned int *status) } full_len -= n; } - + /* We are lucky: The wrapper already returns the data in the required format. */ *status = buffer[3]; @@ -950,26 +1013,26 @@ pcsc_get_status (int slot, unsigned int *status) kill (slotp->pcsc.pid, SIGTERM); slotp->pcsc.pid = (pid_t)(-1); slotp->used = 0; - return -1; + return sw; #else /*!NEED_PCSC_WRAPPER*/ long err; struct pcsc_readerstate_s rdrstates[1]; - + memset (rdrstates, 0, sizeof *rdrstates); rdrstates[0].reader = reader_table[slot].rdrname; rdrstates[0].current_state = PCSC_STATE_UNAWARE; err = pcsc_get_status_change (reader_table[slot].pcsc.context, 0, rdrstates, 1); - if (err == 0x8010000a) /* Timeout. */ - err = 0; + if (err == PCSC_E_TIMEOUT) + err = 0; /* Timeout is no error error here. */ if (err) { log_error ("pcsc_get_status_change failed: %s (0x%lx)\n", pcsc_error_string (err), err); - return SW_HOST_CARD_IO_ERROR; + return pcsc_error_to_sw (err); } @@ -997,8 +1060,8 @@ pcsc_get_status (int slot, unsigned int *status) if ( (*status & 6) == 6 && !(rdrstates[0].event_state & PCSC_STATE_INUSE) ) *status |= 1; - - return 0; + + return 0; #endif /*!NEED_PCSC_WRAPPER*/ } @@ -1016,6 +1079,7 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, size_t len, full_len; int i, n; unsigned char msgbuf[9]; + int sw = SW_HOST_CARD_IO_ERROR; if (!reader_table[slot].atrlen && (err = reset_pcsc_reader (slot))) @@ -1026,12 +1090,12 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, slotp = reader_table + slot; - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 || slotp->pcsc.pid == (pid_t)(-1) ) { log_error ("pcsc_send_apdu: pcsc-wrapper not running\n"); - return SW_HOST_CARD_IO_ERROR; + return sw; } msgbuf[0] = 0x03; /* TRANSMIT command. */ @@ -1067,11 +1131,11 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, { log_error ("pcsc_transmit failed: %s (0x%lx)\n", pcsc_error_string (err), err); - return SW_HOST_CARD_IO_ERROR; + return pcsc_error_to_sw (err); } full_len = len; - + n = *buflen < len ? *buflen : len; if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != n) { @@ -1113,14 +1177,14 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, kill (slotp->pcsc.pid, SIGTERM); slotp->pcsc.pid = (pid_t)(-1); slotp->used = 0; - return -1; + return sw; #else /*!NEED_PCSC_WRAPPER*/ long err; struct pcsc_io_request_s send_pci; unsigned long recv_len; - + if (!reader_table[slot].atrlen && (err = reset_pcsc_reader (slot))) return err; @@ -1141,8 +1205,8 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, if (err) log_error ("pcsc_transmit failed: %s (0x%lx)\n", pcsc_error_string (err), err); - - return err? SW_HOST_CARD_IO_ERROR:0; + + return pcsc_error_to_sw (err); #endif /*!NEED_PCSC_WRAPPER*/ } @@ -1159,8 +1223,8 @@ close_pcsc_reader (int slot) slotp = reader_table + slot; - if (slotp->pcsc.req_fd == -1 - || slotp->pcsc.rsp_fd == -1 + if (slotp->pcsc.req_fd == -1 + || slotp->pcsc.rsp_fd == -1 || slotp->pcsc.pid == (pid_t)(-1) ) { log_error ("close_pcsc_reader: pcsc-wrapper not running\n"); @@ -1198,10 +1262,10 @@ close_pcsc_reader (int slot) if (err) log_error ("pcsc_close failed: %s (0x%lx)\n", pcsc_error_string (err), err); - - /* We will the wrapper in any case - errors are merely + + /* We will close the wrapper in any case - errors are merely informational. */ - + command_failed: close (slotp->pcsc.req_fd); close (slotp->pcsc.rsp_fd); @@ -1222,6 +1286,7 @@ close_pcsc_reader (int slot) #endif /*!NEED_PCSC_WRAPPER*/ } +/* Note: It is a pitty that we can't return proper error codes. */ static int open_pcsc_reader (const char *portstr) { @@ -1237,6 +1302,7 @@ open_pcsc_reader (const char *portstr) size_t len; unsigned char msgbuf[9]; int err; + int sw = SW_HOST_CARD_IO_ERROR; slot = new_reader_slot (); if (slot == -1) @@ -1246,7 +1312,7 @@ open_pcsc_reader (const char *portstr) /* Fire up the pcsc wrapper. We don't use any fork/exec code from the common directy but implement it direclty so that this file may still be source copied. */ - + if (pipe (rp) == -1) { log_error ("error creating a pipe: %s\n", strerror (errno)); @@ -1261,7 +1327,7 @@ open_pcsc_reader (const char *portstr) slotp->used = 0; return -1; } - + pid = fork (); if (pid == -1) { @@ -1283,7 +1349,7 @@ open_pcsc_reader (const char *portstr) /* Double fork. */ pid = fork (); if (pid == -1) - _exit (31); + _exit (31); if (pid) _exit (0); /* Immediate exit this parent, so that the child gets cleaned up by the init process. */ @@ -1293,7 +1359,7 @@ open_pcsc_reader (const char *portstr) log_fatal ("dup2 stdin failed: %s\n", strerror (errno)); if (rp[1] != 1 && dup2 (rp[1], 1) == -1) log_fatal ("dup2 stdout failed: %s\n", strerror (errno)); - + /* Send stderr to the bit bucket. */ fd = open ("/dev/null", O_WRONLY); if (fd == -1) @@ -1318,7 +1384,7 @@ open_pcsc_reader (const char *portstr) _exit (31); } - /* + /* === Parent === */ close (wp[0]); @@ -1328,9 +1394,9 @@ open_pcsc_reader (const char *portstr) /* Wait for the intermediate child to terminate. */ #ifdef USE_GNU_PTH -#define WAIT pth_waitpid +#define WAIT pth_waitpid #else -#define WAIT waitpid +#define WAIT waitpid #endif while ( (i=WAIT (pid, NULL, 0)) == -1 && errno == EINTR) ; @@ -1373,6 +1439,7 @@ open_pcsc_reader (const char *portstr) if (err) { log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err)); + sw = pcsc_error_to_sw (err); goto command_failed; } @@ -1401,7 +1468,7 @@ open_pcsc_reader (const char *portstr) reader_table[slot].send_apdu_reader = pcsc_send_apdu; reader_table[slot].dump_status_reader = dump_pcsc_reader_status; - dump_reader_status (slot); + dump_reader_status (slot); return slot; command_failed: @@ -1412,7 +1479,9 @@ open_pcsc_reader (const char *portstr) kill (slotp->pcsc.pid, SIGTERM); slotp->pcsc.pid = (pid_t)(-1); slotp->used = 0; + /* There is no way to return SW. */ return -1; + #else /*!NEED_PCSC_WRAPPER */ long err; int slot; @@ -1434,7 +1503,7 @@ open_pcsc_reader (const char *portstr) reader_table[slot].used = 0; return -1; } - + err = pcsc_list_readers (reader_table[slot].pcsc.context, NULL, NULL, &nreader); if (!err) @@ -1445,7 +1514,7 @@ open_pcsc_reader (const char *portstr) log_error ("error allocating memory for reader list\n"); pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; - return -1; + return -1 /*SW_HOST_OUT_OF_CORE*/; } err = pcsc_list_readers (reader_table[slot].pcsc.context, NULL, list, &nreader); @@ -1457,7 +1526,7 @@ open_pcsc_reader (const char *portstr) pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; xfree (list); - return -1; + return -1 /*pcsc_error_to_sw (err)*/; } listlen = nreader; @@ -1483,7 +1552,7 @@ open_pcsc_reader (const char *portstr) log_error ("error allocating memory for reader name\n"); pcsc_release_context (reader_table[slot].pcsc.context); reader_table[slot].used = 0; - return -1; + return -1 /*SW_HOST_OUT_OF_CORE*/; } strcpy (reader_table[slot].rdrname, portstr? portstr : list); xfree (list); @@ -1494,7 +1563,7 @@ open_pcsc_reader (const char *portstr) PCSC_PROTOCOL_T0|PCSC_PROTOCOL_T1, &reader_table[slot].pcsc.card, &reader_table[slot].pcsc.protocol); - if (err == 0x8010000c) /* No smartcard. */ + if (err == PCSC_E_NO_SMARTCARD) reader_table[slot].pcsc.card = 0; else if (err) { @@ -1505,8 +1574,8 @@ open_pcsc_reader (const char *portstr) reader_table[slot].rdrname = NULL; reader_table[slot].used = 0; xfree (list); - return -1; - } + return -1 /*pcsc_error_to_sw (err)*/; + } reader_table[slot].atrlen = 0; reader_table[slot].last_status = 0; @@ -1544,7 +1613,7 @@ open_pcsc_reader (const char *portstr) /* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */ /* log_debug ("protocol from pcsc_status: 0x%lx\n", card_protocol); */ - dump_reader_status (slot); + dump_reader_status (slot); return slot; #endif /*!NEED_PCSC_WRAPPER */ } @@ -1553,7 +1622,7 @@ open_pcsc_reader (const char *portstr) #ifdef HAVE_LIBUSB -/* +/* Internal CCID driver interface. */ @@ -1570,16 +1639,16 @@ close_ccid_reader (int slot) ccid_close_reader (reader_table[slot].ccid.handle); reader_table[slot].used = 0; return 0; -} - +} + static int shutdown_ccid_reader (int slot) { ccid_shutdown_reader (reader_table[slot].ccid.handle); return 0; -} - +} + static int reset_ccid_reader (int slot) @@ -1596,10 +1665,10 @@ reset_ccid_reader (int slot) assert (sizeof slotp->atr >= sizeof atr); slotp->atrlen = atrlen; memcpy (slotp->atr, atr, atrlen); - dump_reader_status (slot); + dump_reader_status (slot); return 0; -} - +} + static int get_status_ccid (int slot, unsigned int *status) @@ -1615,7 +1684,7 @@ get_status_ccid (int slot, unsigned int *status) *status = 1|2|4; else if (bits == 1) *status = 2; - else + else *status = 0; return 0; @@ -1647,8 +1716,8 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, if (err) log_error ("ccid_transceive failed: (0x%lx)\n", err); - - return err; + + return err; } /* Open the reader and try to read an ATR. */ @@ -1692,7 +1761,7 @@ open_ccid_reader (const char *portstr) reader_table[slot].send_apdu_reader = send_apdu_ccid; reader_table[slot].dump_status_reader = dump_ccid_reader_status; - dump_reader_status (slot); + dump_reader_status (slot); return slot; } @@ -1703,7 +1772,7 @@ open_ccid_reader (const char *portstr) #ifdef HAVE_OPENSC -/* +/* OpenSC Interface. This uses the OpenSC primitives to send APDUs. We need this @@ -1764,7 +1833,7 @@ osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, if (!apdulen) a.cse = SC_APDU_CASE_1; - else if (apdulen == 1) + else if (apdulen == 1) { a.le = *apdu? *apdu : 256; apdu++; apdulen--; @@ -1784,7 +1853,7 @@ osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, a.data = data; a.datalen = a.lc; - + if (!apdulen) a.cse = SC_APDU_CASE_3_SHORT; else @@ -1861,7 +1930,7 @@ open_osc_reader (int portno) slotp->used = 0; return -1; } - + /* We want the standard ISO driver. */ /*FIXME: OpenSC does not like "iso7816", so we use EMV for now. */ err = sc_set_card_driver(slotp->osc.ctx, "emv"); @@ -1912,7 +1981,7 @@ open_osc_reader (int portno) reader_table[slot].send_apdu_reader = osc_send_apdu; reader_table[slot].dump_status_reader = NULL; - dump_reader_status (slot); + dump_reader_status (slot); return slot; } @@ -1921,7 +1990,7 @@ open_osc_reader (int portno) #ifdef USE_G10CODE_RAPDU -/* +/* The Remote APDU Interface. This uses the Remote APDU protocol to contact a reader. @@ -1940,9 +2009,9 @@ rapdu_status_to_sw (int status) { case RAPDU_STATUS_SUCCESS: rc = 0; break; - case RAPDU_STATUS_INVCMD: - case RAPDU_STATUS_INVPROT: - case RAPDU_STATUS_INVSEQ: + case RAPDU_STATUS_INVCMD: + case RAPDU_STATUS_INVPROT: + case RAPDU_STATUS_INVSEQ: case RAPDU_STATUS_INVCOOKIE: case RAPDU_STATUS_INVREADER: rc = SW_HOST_INV_VALUE; break; @@ -2007,7 +2076,7 @@ reset_rapdu_reader (int slot) { log_error ("ATR returned by the RAPDU layer is too large\n"); rapdu_msg_release (msg); - return SW_HOST_INV_VALUE; + return SW_HOST_INV_VALUE; } slotp->atrlen = msg->datalen; memcpy (slotp->atr, msg->data, msg->datalen); @@ -2107,12 +2176,12 @@ my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen, rapdu_msg_release (msg); return sw; } - + if (msg->datalen > maxlen) { log_error ("rapdu response apdu too large\n"); rapdu_msg_release (msg); - return SW_HOST_INV_VALUE; + return SW_HOST_INV_VALUE; } *buflen = msg->datalen; @@ -2196,11 +2265,11 @@ open_rapdu_reader (int portno, reader_table[slot].send_apdu_reader = my_rapdu_send_apdu; reader_table[slot].dump_status_reader = NULL; - dump_reader_status (slot); + dump_reader_status (slot); rapdu_msg_release (msg); return slot; - failure: + failure: rapdu_msg_release (msg); rapdu_release (slotp->rapdu.handle); slotp->used = 0; @@ -2211,7 +2280,7 @@ open_rapdu_reader (int portno, -/* +/* Driver Access */ @@ -2290,7 +2359,7 @@ apdu_open_reader (const char *portstr) return open_osc_reader (port); } -#endif /* HAVE_OPENSC */ +#endif /* HAVE_OPENSC */ if (opt.ctapi_driver && *opt.ctapi_driver) @@ -2300,7 +2369,7 @@ apdu_open_reader (const char *portstr) if (!ct_api_loaded) { void *handle; - + handle = dlopen (opt.ctapi_driver, RTLD_LAZY); if (!handle) { @@ -2322,7 +2391,7 @@ apdu_open_reader (const char *portstr) return open_ct_reader (port); } - + /* No ctAPI configured, so lets try the PC/SC API */ if (!pcsc_api_loaded) { @@ -2371,16 +2440,16 @@ apdu_open_reader (const char *portstr) pcsc_set_timeout = dlsym (handle, "SCardSetTimeout"); if (!pcsc_establish_context - || !pcsc_release_context - || !pcsc_list_readers + || !pcsc_release_context + || !pcsc_list_readers || !pcsc_get_status_change - || !pcsc_connect + || !pcsc_connect || !pcsc_reconnect || !pcsc_disconnect || !pcsc_status || !pcsc_begin_transaction || !pcsc_end_transaction - || !pcsc_transmit + || !pcsc_transmit /* || !pcsc_set_timeout */) { /* Note that set_timeout is currently not used and also not @@ -2388,21 +2457,21 @@ apdu_open_reader (const char *portstr) log_error ("apdu_open_reader: invalid PC/SC driver " "(%d%d%d%d%d%d%d%d%d%d%d%d)\n", !!pcsc_establish_context, - !!pcsc_release_context, - !!pcsc_list_readers, - !!pcsc_get_status_change, - !!pcsc_connect, - !!pcsc_reconnect, + !!pcsc_release_context, + !!pcsc_list_readers, + !!pcsc_get_status_change, + !!pcsc_connect, + !!pcsc_reconnect, !!pcsc_disconnect, !!pcsc_status, !!pcsc_begin_transaction, !!pcsc_end_transaction, - !!pcsc_transmit, + !!pcsc_transmit, !!pcsc_set_timeout ); dlclose (handle); return -1; } -#endif /*!NEED_PCSC_WRAPPER*/ +#endif /*!NEED_PCSC_WRAPPER*/ pcsc_api_loaded = 1; } @@ -2416,7 +2485,7 @@ apdu_open_reader (const char *portstr) only be called once and the slot will not be valid afther this. If PORTSTR is NULL we default to the first availabe port. -*/ +*/ int apdu_open_remote_reader (const char *portstr, const unsigned char *cookie, size_t length, @@ -2436,7 +2505,7 @@ apdu_open_remote_reader (const char *portstr, writefnc, writefnc_value, closefnc, closefnc_value); #else -#ifdef _WIN32 +#ifdef _WIN32 errno = ENOENT; #else errno = ENOSYS; @@ -2489,7 +2558,7 @@ apdu_reset (int slot) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; - + if ((sw = lock_slot (slot))) return sw; @@ -2521,7 +2590,7 @@ apdu_activate (int slot) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; - + if ((sw = trylock_slot (slot))) return sw; @@ -2550,12 +2619,12 @@ apdu_activate (int slot) } } } - + unlock_slot (slot); return sw; } - + unsigned char * apdu_get_atr (int slot, size_t *atrlen) @@ -2564,7 +2633,7 @@ apdu_get_atr (int slot, size_t *atrlen) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return NULL; - + buf = xtrymalloc (reader_table[slot].atrlen); if (!buf) return NULL; @@ -2574,7 +2643,7 @@ apdu_get_atr (int slot, size_t *atrlen) } - + /* Retrieve the status for SLOT. The function does only wait for the card to become available if HANG is set to true. On success the bits in STATUS will be set to @@ -2660,7 +2729,7 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen, returned data. The length of that data will be put into *RETBUFLEN. The caller is reponsible for releasing the buffer even in case of errors. */ -int +int apdu_send_le(int slot, int class, int ins, int p0, int p1, int lc, const char *data, int le, unsigned char **retbuf, size_t *retbuflen) @@ -2682,9 +2751,9 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, class, ins, p0, p1, lc, le); if (lc != -1 && (lc > 255 || lc < 0)) - return SW_WRONG_LENGTH; + return SW_WRONG_LENGTH; if (le != -1 && (le > 256 || le < 1)) - return SW_WRONG_LENGTH; + return SW_WRONG_LENGTH; if ((!data && lc != -1) || (data && lc == -1)) return SW_HOST_INV_VALUE; @@ -2764,7 +2833,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, do { int len = (sw & 0x00ff); - + if (DBG_CARD_IO) log_debug ("apdu_send_simple(%d): %d more bytes available\n", slot, len); @@ -2773,7 +2842,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, apdu[apdulen++] = 0xC0; apdu[apdulen++] = 0; apdu[apdulen++] = 0; - apdu[apdulen++] = len; + apdu[apdulen++] = len; memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen); @@ -2822,7 +2891,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, slot, sw); } while ((sw & 0xff00) == SW_MORE_DATA); - + if (retbuf) { *retbuflen = p - *retbuf; @@ -2836,7 +2905,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, if (DBG_CARD_IO && retbuf && sw == SW_SUCCESS) log_printhex (" dump: ", *retbuf, *retbuflen); - + return sw; #undef RESULTLEN } @@ -2850,11 +2919,11 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, data. The length of that data will be put into *RETBUFLEN. The caller is reponsible for releasing the buffer even in case of errors. */ -int +int apdu_send (int slot, int class, int ins, int p0, int p1, int lc, const char *data, unsigned char **retbuf, size_t *retbuflen) { - return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256, + return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256, retbuf, retbuflen); } @@ -2864,7 +2933,7 @@ apdu_send (int slot, int class, int ins, int p0, int p1, also be passed as NULL. The return value is the status word or -1 for an invalid SLOT or other non card related error. No data will be returned. */ -int +int apdu_send_simple (int slot, int class, int ins, int p0, int p1, int lc, const char *data) { @@ -2880,7 +2949,7 @@ apdu_send_simple (int slot, int class, int ins, int p0, int p1, the end. The function does not return a regular status word but 0 on success. If the slot is locked, the fucntion returns immediately.*/ -int +int apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, int handle_more, unsigned char **retbuf, size_t *retbuflen) @@ -2951,7 +3020,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, do { int len = (sw & 0x00ff); - + if (DBG_CARD_IO) log_debug ("apdu_send_direct(%d): %d more bytes available\n", slot, len); @@ -2960,7 +3029,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, apdu[apdulen++] = 0xC0; apdu[apdulen++] = 0; apdu[apdulen++] = 0; - apdu[apdulen++] = len; + apdu[apdulen++] = len; memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen); @@ -3009,7 +3078,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, slot, sw); } while ((sw & 0xff00) == SW_MORE_DATA); - + if (retbuf) { *retbuflen = p - *retbuf; @@ -3045,9 +3114,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, if (DBG_CARD_IO && retbuf) log_printhex (" dump: ", *retbuf, *retbuflen); - + return 0; #undef RESULTLEN } - - diff --git a/scd/app-common.h b/scd/app-common.h index ace57d98c..4a2adaa54 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -104,7 +104,8 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); /*-- app.c --*/ -app_t select_application (ctrl_t ctrl, int slot, const char *name); +gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, + app_t *r_app); void release_application (app_t app); int app_munge_serialno (app_t app); int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 8d146ba6a..14c802d10 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -306,23 +306,33 @@ flush_cache (app_t app) NULL if not found or a pointer which must be used to release the buffer holding value. */ static void * -get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) +get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes, + int *r_rc) { int rc, i; unsigned char *buffer; size_t buflen; unsigned char *value; size_t valuelen; + int dummyrc; + + if (!r_rc) + r_rc = &dummyrc; *result = NULL; *nbytes = 0; + *r_rc = 0; for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++) ; if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11) { - if( iso7816_get_data (app->slot, tag, &buffer, &buflen)) - return NULL; + rc = iso7816_get_data (app->slot, tag, &buffer, &buflen); + if (rc) + { + *r_rc = rc; + return NULL; + } *result = buffer; *nbytes = buflen; return buffer; @@ -334,7 +344,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) { rc = get_cached_data (app, data_objects[i].get_from, &buffer, &buflen, - data_objects[i].get_immediate_in_v11); + (data_objects[i].dont_cache + || data_objects[i].get_immediate_in_v11)); if (!rc) { const unsigned char *s; @@ -356,7 +367,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) if (!value) /* Not in a constructed DO, try simple. */ { rc = get_cached_data (app, tag, &buffer, &buflen, - data_objects[i].get_immediate_in_v11); + (data_objects[i].dont_cache + || data_objects[i].get_immediate_in_v11)); if (!rc) { value = buffer; @@ -370,6 +382,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes) *result = value; return buffer; } + *r_rc = rc; return NULL; } @@ -488,7 +501,7 @@ parse_login_data (app_t app) app->app_local->flags.def_chv2 = 0; /* Read the DO. */ - relptr = get_one_do (app, 0x005E, &buffer, &buflen); + relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL); if (!relptr) return; /* Ooops. */ for (; buflen; buflen--, buffer++) @@ -678,7 +691,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) { "PRIVATE-DO-4", 0x0104 }, { NULL, 0 } }; - int idx, i; + int idx, i, rc; void *relptr; unsigned char *value; size_t valuelen; @@ -723,7 +736,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) return 0; } - relptr = get_one_do (app, table[idx].tag, &value, &valuelen); + relptr = get_one_do (app, table[idx].tag, &value, &valuelen, &rc); if (relptr) { if (table[idx].special == 1) @@ -760,7 +773,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) xfree (relptr); } - return 0; + return rc; } @@ -1075,7 +1088,7 @@ verify_chv3 (app_t app, unsigned char *value; size_t valuelen; - relptr = get_one_do (app, 0x00C4, &value, &valuelen); + relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL); if (!relptr || valuelen < 7) { log_error (_("error retrieving CHV status from card\n")); @@ -1442,7 +1455,7 @@ get_sig_counter (app_t app) size_t valuelen; unsigned long ul; - relptr = get_one_do (app, 0x0093, &value, &valuelen); + relptr = get_one_do (app, 0x0093, &value, &valuelen, NULL); if (!relptr) return 0; ul = convert_sig_counter_value (value, valuelen); @@ -1880,7 +1893,7 @@ app_select_openpgp (app_t app) goto leave; } - relptr = get_one_do (app, 0x00C4, &buffer, &buflen); + relptr = get_one_do (app, 0x00C4, &buffer, &buflen, NULL); if (!relptr) { log_error (_("can't access %s - invalid OpenPGP card?\n"), @@ -1890,7 +1903,7 @@ app_select_openpgp (app_t app) app->force_chv1 = (buflen && *buffer == 0); xfree (relptr); - relptr = get_one_do (app, 0x00C0, &buffer, &buflen); + relptr = get_one_do (app, 0x00C0, &buffer, &buflen, NULL); if (!relptr) { log_error (_("can't access %s - invalid OpenPGP card?\n"), @@ -1973,7 +1986,7 @@ app_openpgp_cardinfo (app_t app, if (disp_name) { *disp_name = NULL; - relptr = get_one_do (app, 0x005B, &value, &valuelen); + relptr = get_one_do (app, 0x005B, &value, &valuelen, NULL); if (relptr) { *disp_name = make_printable_string (value, valuelen, 0); @@ -1984,7 +1997,7 @@ app_openpgp_cardinfo (app_t app, if (pubkey_url) { *pubkey_url = NULL; - relptr = get_one_do (app, 0x5F50, &value, &valuelen); + relptr = get_one_do (app, 0x5F50, &value, &valuelen, NULL); if (relptr) { *pubkey_url = make_printable_string (value, valuelen, 0); @@ -1998,7 +2011,7 @@ app_openpgp_cardinfo (app_t app, *fpr2 = NULL; if (fpr3) *fpr3 = NULL; - relptr = get_one_do (app, 0x00C5, &value, &valuelen); + relptr = get_one_do (app, 0x00C5, &value, &valuelen, NULL); if (relptr && valuelen >= 60) { if (fpr1) diff --git a/scd/app.c b/scd/app.c index fad4eba55..857f9e10b 100644 --- a/scd/app.c +++ b/scd/app.c @@ -1,5 +1,5 @@ /* app.c - Application selection. - * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -49,21 +49,23 @@ is_app_allowed (const char *name) /* If called with NAME as NULL, select the best fitting application and return a context; otherwise select the application with NAME and return a context. SLOT identifies the reader device. Returns - NULL if no application was found or no card is present. */ -APP -select_application (ctrl_t ctrl, int slot, const char *name) + an error code and stores NULL at R_APP if no application was found + or no card is present. */ +gpg_error_t +select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) { int rc; - APP app; + app_t app; unsigned char *result = NULL; size_t resultlen; + *r_app = NULL; app = xtrycalloc (1, sizeof *app); if (!app) { - rc = gpg_error (gpg_err_code_from_errno (errno)); + rc = gpg_error_from_errno (errno); log_info ("error allocating context: %s\n", gpg_strerror (rc)); - return NULL; + return rc; } app->slot = slot; @@ -75,7 +77,7 @@ select_application (ctrl_t ctrl, int slot, const char *name) if (!rc) rc = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL); if (!rc) - rc = iso7816_read_binary (slot, 0, 0, &result, &resultlen); + rc = iso7816_read_binary (slot, 0, 0, &result, &resultlen); if (!rc) { size_t n; @@ -111,7 +113,12 @@ select_application (ctrl_t ctrl, int slot, const char *name) result = NULL; } + /* For certain error codes, there is no need to try more. */ + if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT) + goto leave; + + /* Figure out the application to use. */ rc = gpg_error (GPG_ERR_NOT_FOUND); if (rc && is_app_allowed ("openpgp") && (!name || !strcmp (name, "openpgp"))) @@ -135,11 +142,12 @@ select_application (ctrl_t ctrl, int slot, const char *name) log_info ("no supported card application found: %s\n", gpg_strerror (rc)); xfree (app); - return NULL; + return rc; } app->initialized = 1; - return app; + *r_app = app; + return 0; } diff --git a/scd/command.c b/scd/command.c index 72f48b2b8..a4fb968cf 100644 --- a/scd/command.c +++ b/scd/command.c @@ -45,10 +45,24 @@ static ctrl_t primary_connection; #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) + +/* Macro to flag a a removed card. */ +#define TEST_CARD_REMOVAL(c,r) \ + do { \ + int _r = (r); \ + if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \ + || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \ + (c)->server_local->card_removed = 1; \ + } while (0) + + /* Data used to associate an Assuan context with local server data */ struct server_local_s { - ASSUAN_CONTEXT assuan_ctx; + assuan_context_t assuan_ctx; int event_signal; /* Or 0 if not used. */ + int card_removed; /* True if the card has been removed and a + reset is required to continue + operation. */ }; @@ -89,6 +103,7 @@ do_reset (ctrl_t ctrl, int do_close) ctrl->reader_slot = -1; } } + ctrl->server_local->card_removed = 0; } @@ -122,11 +137,18 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) /* If the card has not yet been opened, do it. Note that this function returns an Assuan error, so don't map the error a second time */ -static AssuanError +static assuan_error_t open_card (ctrl_t ctrl, const char *apptype) { + gpg_error_t err; int slot; + /* If we ever got a card not present error code, return that. Only + the SERIALNO command and a reset are able to clear from that + state. */ + if (ctrl->server_local->card_removed) + return map_to_assuan_status (gpg_error (GPG_ERR_CARD_REMOVED)); + if (ctrl->app_ctx) return 0; /* Already initialized for one specific application. */ if (ctrl->card_ctx) @@ -137,24 +159,28 @@ open_card (ctrl_t ctrl, const char *apptype) else slot = apdu_open_reader (opt.reader_port); ctrl->reader_slot = slot; - if (slot != -1) - ctrl->app_ctx = select_application (ctrl, slot, apptype); - if (!ctrl->app_ctx) - { /* No application found - fall back to old mode. */ + if (slot == -1) + err = gpg_error (GPG_ERR_CARD); + else + err = select_application (ctrl, slot, apptype, &ctrl->app_ctx); + if (!ctrl->app_ctx + && gpg_err_code (err) != GPG_ERR_CARD_NOT_PRESENT) + { + /* No application found - fall back to old mode. */ /* Note that we should rework the old code to use the application paradigma too. */ - int rc; - /* If an APPTYPE was requested and it is not pkcs#15, we return an error here. */ if (apptype && !(!strcmp (apptype, "P15") || !strcmp (apptype, "p15"))) - rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + err = gpg_error (GPG_ERR_NOT_SUPPORTED); else - rc = card_open (&ctrl->card_ctx); - if (rc) - return map_to_assuan_status (rc); + err = card_open (&ctrl->card_ctx); } - return 0; + + if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT) + ctrl->server_local->card_removed = 1; + + return map_to_assuan_status (err); } @@ -215,12 +241,15 @@ percent_plus_unescape (unsigned char *string) static int cmd_serialno (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc = 0; char *serial_and_stamp; char *serial; time_t stamp; + /* Clear the remove flag so that the open_card is able to reread it. */ + ctrl->server_local->card_removed = 0; + if ((rc = open_card (ctrl, *line? line:NULL))) return rc; @@ -443,6 +472,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) if (rc == -1) rc = 0; + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -485,6 +515,7 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line) return rc; } + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -575,6 +606,7 @@ cmd_readkey (assuan_context_t ctx, char *line) leave: ksba_cert_release (kc); xfree (cert); + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -697,6 +729,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) return rc; /* that is already an assuan error code */ } + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -743,6 +776,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) return rc; /* that is already an assuan error code */ } + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -789,6 +823,7 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) return rc; /* that is already an assuan error code */ } + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -824,6 +859,7 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line) rc = app_getattr (ctrl->app_ctx, ctrl, keyword); + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -871,6 +907,7 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line) rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes); xfree (linebuf); + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -927,6 +964,8 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) return ASSUAN_Out_Of_Core; rc = app_genkey (ctrl->app_ctx, ctrl, keyno, force? 1:0, pin_cb, ctx); xfree (keyno); + + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -966,6 +1005,7 @@ cmd_random (ASSUAN_CONTEXT ctx, char *line) } xfree (buffer); + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -1010,6 +1050,8 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) if (rc) log_error ("command passwd failed: %s\n", gpg_strerror (rc)); xfree (chvnostr); + + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -1044,6 +1086,7 @@ cmd_checkpin (ASSUAN_CONTEXT ctx, char *line) if (rc) log_error ("app_check_pin failed: %s\n", gpg_strerror (rc)); + TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -1226,7 +1269,9 @@ send_status_info (CTRL ctrl, const char *keyword, ...) } - +/* This fucntion is called by the ticker thread to check for changes + of the reader stati. It updates the reader status files and if + requested by the caller also send a signal to the caller. */ void scd_update_reader_status_file (void) { @@ -1239,10 +1284,10 @@ scd_update_reader_status_file (void) int used; unsigned int status, changed; - /* Note, that we only try to get the status, becuase it does not + /* Note, that we only try to get the status, because it does not make sense to wait here for a operation to complete. If we are - so busy working with the card, delays in the status file updated - are should be acceptable. */ + busy working with a card, delays in the status file update should + be acceptable. */ for (slot=0; (slot < DIM(last) &&!apdu_enum_reader (slot, &used)); slot++) if (used && !apdu_get_status (slot, 0, &status, &changed)) diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 88f393bb1..0fefbd960 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -936,7 +936,7 @@ ticker_thread (void *dummy_arg) sigs_ev = NULL; #endif - for (;;) + while (!shutdown_pending) { if (!time_ev) { @@ -968,6 +968,7 @@ ticker_thread (void *dummy_arg) } pth_event_free (sigs_ev, PTH_FREE_ALL); + return NULL; } #endif /*USE_GNU_PTH*/ #endif /*!HAVE_OPENSC*/ diff --git a/tests/asschk.c b/tests/asschk.c index 83a8ca5af..59c0d107a 100644 --- a/tests/asschk.c +++ b/tests/asschk.c @@ -59,10 +59,10 @@ Print VALUE. openfile <filename> - Open file FILENAME for read access and retrun the file descriptor. + Open file FILENAME for read access and return the file descriptor. createfile <filename> - Create file FILENAME, open for write access and retrun the file + Create file FILENAME, open for write access and return the file descriptor. pipeserver <program> diff --git a/tools/ChangeLog b/tools/ChangeLog index 38b9e9cf4..6895198c5 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2005-02-24 Werner Koch <wk@g10code.com> + + * gpg-connect-agent.c: New. + * Makefile.am: Add it. + 2004-12-21 Werner Koch <wk@g10code.com> * gpgconf-comp.c (get_config_pathname) [DOSISH]: Detect absolute diff --git a/tools/Makefile.am b/tools/Makefile.am index 112c77e7c..5a56d65ce 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -24,15 +24,13 @@ EXTRA_DIST = Manifest watchgnupg.c \ AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am -# Note, that we require GPG_ERROR_CFLAGS only because some share header files -# require that file. It is not actually used in gpgconf. -AM_CFLAGS = @GPG_ERROR_CFLAGS@ +AM_CFLAGS = $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) sbin_SCRIPTS = addgnupghome bin_SCRIPTS = gpgsm-gencert.sh -bin_PROGRAMS = gpgconf +bin_PROGRAMS = gpgconf gpg-connect-agent if !HAVE_W32_SYSTEM bin_PROGRAMS += watchgnupg endif @@ -41,4 +39,9 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @LIBINTL@ -watchgnupg_SOURCES = watchgnupg.c +watchgnupg_SOURCES = watchgnupg.c + +gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c +gpg_connect_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ + $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) + diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c new file mode 100644 index 000000000..399a5d369 --- /dev/null +++ b/tools/gpg-connect-agent.c @@ -0,0 +1,362 @@ +/* gpg-connect-agent.c - Tool to connect to the agent. + * Copyright (C) 2005 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 <assuan.h> + +#include "i18n.h" +#include "../common/util.h" +#include "../common/asshelp.h" + + + +/* Constants to identify the commands and options. */ +enum cmd_and_opt_values + { + aNull = 0, + oQuiet = 'q', + oVerbose = 'v', + + oNoVerbose = 500, + oHomedir + + }; + + +/* The list of commands and options. */ +static ARGPARSE_OPTS opts[] = + { + { 301, NULL, 0, N_("@\nOptions:\n ") }, + + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("quiet") }, + + /* hidden options */ + { oNoVerbose, "no-verbose", 0, "@"}, + { oHomedir, "homedir", 2, "@" }, + {0} + }; + + +/* We keep all global options in the structure OPT. */ +struct +{ + int verbose; /* Verbosity level. */ + int quiet; /* Be extra quiet. */ + const char *homedir; /* Configuration directory name */ + +} opt; + + +/*-- local prototypes --*/ +static int read_and_print_response (assuan_context_t ctx); +static assuan_context_t start_agent (void); + + + + +/* Print usage information and and provide strings for help. */ +static const char * +my_strusage( int level ) +{ + const char *p; + + switch (level) + { + case 11: p = "gpg-connect-agent (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: gpg-connect-agent [options] (-h for help)"); + break; + case 41: + p = _("Syntax: gpg-connect-agent [options]\n" + "Connect to a running agent and send commands\n"); + break; + case 31: p = "\nHome: "; break; + case 32: p = opt.homedir; break; + case 33: p = "\n"; break; + + default: p = NULL; break; + } + return p; +} + + +/* Initialize the gettext system. */ +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file (PACKAGE_GT); +#else +# ifdef ENABLE_NLS + setlocale (LC_ALL, "" ); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); +# endif +#endif +} + + +/* gpg-connect-agent's entry point. */ +int +main (int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + const char *fname; + int no_more_options = 0; + assuan_context_t ctx; + char *line; + size_t linesize; + int rc; + + set_strusage (my_strusage); + log_set_prefix ("gpg-connect-agent", 1); + + i18n_init(); + + opt.homedir = default_homedir (); + + /* Parse the command line. */ + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags = 1; /* Do not remove the args. */ + while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts)) + { + switch (pargs.r_opt) + { + case oQuiet: opt.quiet = 1; break; + case oVerbose: opt.verbose++; break; + case oNoVerbose: opt.verbose = 0; break; + case oHomedir: opt.homedir = pargs.r.ret_str; break; + + default: pargs.err = 2; break; + } + } + + if (log_get_errorcount (0)) + exit (2); + + fname = argc ? *argv : NULL; + + ctx = start_agent (); + line = NULL; + linesize = 0; + for (;;) + { + int n; + size_t maxlength; + + maxlength = 2048; + n = read_line (stdin, &line, &linesize, &maxlength); + if (n < 0) + { + log_error (_("error reading input: %s\n"), strerror (errno)); + exit (1); + } + if (!n) + break; /* EOF */ + if (!maxlength) + { + log_error (_("line too long - skipped\n")); + continue; + } + if (memchr (line, 0, n)) + log_info (_("line shortened due to embedded Nul character\n")); + if (line[n-1] == '\n') + line[n-1] = 0; + rc = assuan_write_line (ctx, line); + if (rc) + { + log_info (_("sending line failed: %s\n"), assuan_strerror (rc) ); + continue; + } + if (*line == '#' || !*line) + continue; /* Don't expect a response for a coment line. */ + + rc = read_and_print_response (ctx); + if (rc) + log_info (_("receiving line failed: %s\n"), assuan_strerror (rc) ); + } + + if (opt.verbose) + log_info ("closing connection to agent\n"); + + return 0; +} + + +/* Read all response lines from server and print them. Returns 0 on + success or an assuan error code. */ +static int +read_and_print_response (assuan_context_t ctx) +{ + char *line; + int linelen; + assuan_error_t rc; + + for (;;) + { + do + { + rc = assuan_read_line (ctx, &line, &linelen); + if (rc) + return rc; + } + while (*line == '#' || !linelen); + + if (linelen >= 1 + && line[0] == 'D' && line[1] == ' ') + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + } + else if (linelen >= 1 + && line[0] == 'S' + && (line[1] == '\0' || line[1] == ' ')) + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + } + else if (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + return 0; + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && (line[3] == '\0' || line[3] == ' ')) + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + return 0; + } + else if (linelen >= 7 + && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q' + && line[3] == 'U' && line[4] == 'I' && line[5] == 'R' + && line[6] == 'E' + && (line[7] == '\0' || line[7] == ' ')) + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + return 0; + } + else if (linelen >= 3 + && line[0] == 'E' && line[1] == 'N' && line[2] == 'D' + && (line[3] == '\0' || line[3] == ' ')) + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + /* Received from server, thus more responses are expected. */ + } + else + return ASSUAN_Invalid_Response; + } +} + + + + +/* Connect to teh agebnt and send the standard options. */ +static assuan_context_t +start_agent (void) +{ + int rc = 0; + char *infostr, *p; + assuan_context_t ctx; + + infostr = getenv ("GPG_AGENT_INFO"); + if (!infostr || !*infostr) + { + char *sockname; + + /* Check whether we can connect at the standard socket. */ + sockname = make_filename (opt.homedir, "S.gpg-agent", NULL); + rc = assuan_socket_connect (&ctx, sockname, 0); + xfree (sockname); + } + else + { + int prot; + int pid; + + infostr = xstrdup (infostr); + if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) + { + log_error (_("malformed GPG_AGENT_INFO environment variable\n")); + xfree (infostr); + exit (1); + } + *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); + exit (1); + } + + rc = assuan_socket_connect (&ctx, infostr, pid); + xfree (infostr); + } + + if (rc) + { + log_error ("can't connect to the agent: %s\n", assuan_strerror (rc)); + exit (1); + } + + if (opt.verbose) + log_info ("connection to agent established\n"); + + rc = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + { + log_error (_("error sending %s command: %s\n"), "RESET", + assuan_strerror (rc)); + exit (1); + } + + rc = send_pinentry_environment (ctx, GPG_ERR_SOURCE_DEFAULT, + NULL, NULL, NULL, NULL, NULL); + if (rc) + { + log_error (_("error sending standard options: %s\n"), gpg_strerror (rc)); + exit (1); + } + + return ctx; +} -- cgit v1.2.3 From 1f1f28555a19f76a97824ad7e5a85228b1c16ea9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 24 Feb 2005 21:40:48 +0000 Subject: * call-scd.c (unescape_status_string): New. Actual a copy of ../g10/call-agent.c (card_getattr_cb, agent_card_getattr): New. * command-ssh.c (card_key_available): New. (ssh_handler_request_identities): First see whether a card key is available. * app.c (app_getattr): Return APPTYPE or SERIALNO type even if the application does dot support the getattr call. * app.c (select_application): Return an error code and the application context in an new arg. * command.c (open_card): Adjusted for that. Don't use the fallback if no card is present. Return an error if the card has been removed without a reset. (do_reset, cmd_serialno): Clear that error flag. (TEST_CARD_REMOVAL): New. Use it with all command handlers. (scd_update_reader_status_file): Set the error flag on all changes. --- agent/ChangeLog | 8 ++ agent/agent.h | 1 + agent/call-scd.c | 133 ++++++++++++++++++++++++++++++--- agent/command-ssh.c | 208 +++++++++++++++++++++++++++++++++++----------------- scd/ChangeLog | 4 + scd/app.c | 29 ++++++++ scd/command.c | 24 ++++-- 7 files changed, 323 insertions(+), 84 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 775a44489..118559c64 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,13 @@ 2005-02-24 Werner Koch <wk@g10code.com> + * call-scd.c (unescape_status_string): New. Actual a copy of + ../g10/call-agent.c + (card_getattr_cb, agent_card_getattr): New. + + * command-ssh.c (card_key_available): New. + (ssh_handler_request_identities): First see whether a card key is + available. + * gpg-agent.c (handle_connections): Need to check for events if select returns with -1. diff --git a/agent/agent.h b/agent/agent.h index 0661cc4ad..39e479e48 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -259,6 +259,7 @@ int agent_card_pkdecrypt (ctrl_t ctrl, int agent_card_readcert (ctrl_t ctrl, const char *id, char **r_buf, size_t *r_buflen); int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf); +gpg_error_t agent_card_getattr (ctrl_t ctrl, const char *name, char **result); int agent_card_scd (ctrl_t ctrl, const char *cmdline, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, void *assuan_context); diff --git a/agent/call-scd.c b/agent/call-scd.c index bffdbcbad..f7d32f7cf 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -1,5 +1,5 @@ /* call-scd.c - fork of the scdaemon to do SC operations - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -66,7 +66,7 @@ static pth_mutex_t scd_lock; static int active_connection_fd = -1; static int active_connection = 0; -/* callback parameter for learn card */ +/* Callback parameter for learn card */ struct learn_parm_s { void (*kpinfo_cb)(void*, const char *); void *kpinfo_cb_arg; @@ -266,6 +266,41 @@ agent_reset_scd (ctrl_t ctrl) } + +/* 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; +} @@ -375,14 +410,6 @@ agent_card_serialno (ctrl_t ctrl, char **r_serialno) if (rc) return rc; - /* Hmm, do we really need this reset - scddaemon should do this or - we can do this if we for some reason figure out that the - operation might have failed due to a missing RESET. Hmmm, I feel - this is really SCdaemon's duty */ -/* rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); */ -/* if (rc) */ -/* return unlock_scd (map_assuan_err (rc)); */ - rc = assuan_transact (scd_ctx, "SERIALNO", NULL, NULL, NULL, NULL, get_serialno_cb, &serialno); @@ -395,6 +422,8 @@ agent_card_serialno (ctrl_t ctrl, char **r_serialno) return unlock_scd (0); } + + static AssuanError membuf_data_cb (void *opaque, const void *buffer, size_t length) @@ -644,6 +673,90 @@ agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf) } + +/* Type used with the card_getattr_cb. */ +struct card_getattr_parm_s { + const char *keyword; /* Keyword to look for. */ + size_t keywordlen; /* strlen of KEYWORD. */ + char *data; /* Malloced and unescaped data. */ + int error; /* ERRNO value or 0 on success. */ +}; + +/* Callback function for agent_card_getattr. */ +static assuan_error_t +card_getattr_cb (void *opaque, const char *line) +{ + struct card_getattr_parm_s *parm = opaque; + const char *keyword = line; + int keywordlen; + + if (parm->data) + return 0; /* We want only the first occurrence. */ + + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + + if (keywordlen == parm->keywordlen + && !memcmp (keyword, parm->keyword, keywordlen)) + { + parm->data = unescape_status_string (line); + if (!parm->data) + parm->error = errno; + } + + return 0; +} + + +/* Call the agent to retrieve a single line data object. On success + the object is malloced and stored at RESULT; it is guaranteed that + NULL is never stored in this case. On error an error code is + returned and NULL stored at RESULT. */ +gpg_error_t +agent_card_getattr (ctrl_t ctrl, const char *name, char **result) +{ + int err; + struct card_getattr_parm_s parm; + char line[ASSUAN_LINELENGTH]; + + *result = NULL; + + if (!*name) + return gpg_error (GPG_ERR_INV_VALUE); + + memset (&parm, 0, sizeof parm); + parm.keyword = name; + parm.keywordlen = strlen (name); + + /* We assume that NAME does not need escaping. */ + if (8 + strlen (name) > DIM(line)-1) + return gpg_error (GPG_ERR_TOO_LARGE); + stpcpy (stpcpy (line, "GETATTR "), name); + + err = start_scd (ctrl); + if (err) + return err; + + err = map_assuan_err (assuan_transact (scd_ctx, line, + NULL, NULL, NULL, NULL, + card_getattr_cb, &parm)); + if (!err && parm.error) + err = gpg_error_from_errno (parm.error); + + if (!err && !parm.data) + err = gpg_error (GPG_ERR_NO_DATA); + + if (!err) + *result = parm.data; + else + xfree (parm.data); + + return unlock_scd (err); +} + + static AssuanError diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 8ea042e19..2c0d25ef6 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1201,7 +1201,7 @@ sexp_key_extract (gcry_sexp_t sexp, return err; } -/* Extract the car from SEXP, and create a newly created C-string it, +/* Extract the car from SEXP, and create a newly created C-string which is to be stored in IDENTIFIER. */ static gpg_error_t sexp_extract_identifier (gcry_sexp_t sexp, const char **identifier) @@ -1404,6 +1404,7 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, } +/* Write the public key KEY_PUBLIC to STREAM in SSH key format. */ static gpg_error_t ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) { @@ -1516,7 +1517,78 @@ key_secret_to_public (gcry_sexp_t *key_public, return err; } - + +/* Chec whether a smartcard is available and whether it has a usable + key. Store a copy of that key at R_PK and return 0. If no key is + available store NULL at R_PK and return an error code. */ +static gpg_error_t +card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk) +{ + gpg_error_t err; + char *appname; + unsigned char *sbuf; + size_t sbuflen; + gcry_sexp_t pk; + + *r_pk = NULL; + + /* First see whether a card is available and whether the application + is supported. */ + err = agent_card_getattr (ctrl, "APPTYPE", &appname); + if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED ) + { + /* Ask for the serial number to reset the card. */ + err = agent_card_serialno (ctrl, &appname); + if (err) + { + if (opt.verbose) + log_info (_("can't get serial number of card: %s\n"), + gpg_strerror (err)); + return err; + } + log_info (_("detected card with S/N: %s\n"), appname); + xfree (appname); + err = agent_card_getattr (ctrl, "APPTYPE", &appname); + } + if (err) + { + log_error (_("error getting application type of card: %s\n"), + gpg_strerror (err)); + return err; + } + if (strcmp (appname, "OPENPGP")) + { + log_info (_("card application `%s' is not supported\n"), appname); + xfree (appname); + return gpg_error (GPG_ERR_NOT_SUPPORTED); + } + xfree (appname); + appname = NULL; + + /* Read the public key. */ + err = agent_card_readkey (ctrl, "OPENPGP.3", &sbuf); + if (err) + { + if (opt.verbose) + log_info (_("no suitable card key found: %s\n"), gpg_strerror (err)); + return err; + } + + sbuflen = gcry_sexp_canon_len (sbuf, 0, NULL, NULL); + err = gcry_sexp_sscan (&pk, NULL, sbuf, sbuflen); + xfree (sbuf); + if (err) + { + log_error ("failed to build S-Exp from received card key: %s\n", + gpg_strerror (err)); + return err; + } + + *r_pk = pk; + return 0; +} + + /* Request handler. @@ -1589,91 +1661,95 @@ ssh_handler_request_identities (ctrl_t ctrl, goto out; } - /* Iterate over key files. */ - /* FIXME: make sure that buffer gets deallocated properly. */ + + /* First check whether a key is currently available in the card + reader - this should be allowed even without being listed in + sshcontrol.txt. */ + + if (!card_key_available (ctrl, &key_public)) + { + err = ssh_send_key_public (key_blobs, key_public); + gcry_sexp_release (key_public); + key_public = NULL; + if (err) + goto out; + + key_counter++; + } + + + /* Then look at all the registered an allowed keys. */ + /* Fixme: We should better iterate over the control file and check whether the key file is there. This is better in resepct to performance if tehre are a lot of key sin our key storage. */ - + /* FIXME: make sure that buffer gets deallocated properly. */ err = open_control_file (&ctrl_fp, 0); if (err) goto out; -#warning Really need to fix this fixme. - /* - FIXME: First check whether a key is currently available in the card reader - this should be allowed even without being listed in sshcontrol.txt. - */ - - while (1) + while ( (dir_entry = readdir (dir)) ) { - dir_entry = readdir (dir); - if (dir_entry) - { - if ((strlen (dir_entry->d_name) == 44) - && (! strncmp (dir_entry->d_name + 40, ".key", 4))) - { - char hexgrip[41]; - int disabled; - - /* We do only want to return keys listed in our control - file. */ - strncpy (hexgrip, dir_entry->d_name, 40); - hexgrip[40] = 0; - if ( strlen (hexgrip) != 40 ) - continue; - if (search_control_file (ctrl_fp, hexgrip, &disabled) - || disabled) - continue; - - strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); - - /* Read file content. */ - err = file_to_buffer (key_path, &buffer, &buffer_n); - if (err) - break; + if ((strlen (dir_entry->d_name) == 44) + && (! strncmp (dir_entry->d_name + 40, ".key", 4))) + { + char hexgrip[41]; + int disabled; + + /* We do only want to return keys listed in our control + file. */ + strncpy (hexgrip, dir_entry->d_name, 40); + hexgrip[40] = 0; + if ( strlen (hexgrip) != 40 ) + continue; + if (search_control_file (ctrl_fp, hexgrip, &disabled) + || disabled) + continue; + + strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40); + + /* Read file content. */ + err = file_to_buffer (key_path, &buffer, &buffer_n); + if (err) + goto out; - err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n); - if (err) - break; + err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n); + if (err) + goto out; - xfree (buffer); - buffer = NULL; + xfree (buffer); + buffer = NULL; - err = sexp_extract_identifier (key_secret, &key_type); - if (err) - break; + err = sexp_extract_identifier (key_secret, &key_type); + if (err) + goto out; - err = ssh_key_type_lookup (NULL, key_type, &spec); - if (err) - break; + err = ssh_key_type_lookup (NULL, key_type, &spec); + if (err) + goto out; - xfree ((void *) key_type); - key_type = NULL; + xfree ((void *) key_type); + key_type = NULL; - err = key_secret_to_public (&key_public, spec, key_secret); - if (err) - break; + err = key_secret_to_public (&key_public, spec, key_secret); + if (err) + goto out; - gcry_sexp_release (key_secret); - key_secret = NULL; + gcry_sexp_release (key_secret); + key_secret = NULL; - err = ssh_send_key_public (key_blobs, key_public); - if (err) - break; + err = ssh_send_key_public (key_blobs, key_public); + if (err) + goto out; - gcry_sexp_release (key_public); - key_public = NULL; + gcry_sexp_release (key_public); + key_public = NULL; - key_counter++; - } - } - else - break; + key_counter++; + } } - if (err) - goto out; ret = es_fseek (key_blobs, 0, SEEK_SET); if (ret) diff --git a/scd/ChangeLog b/scd/ChangeLog index c78bd011f..dc394b677 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,8 @@ 2005-02-24 Werner Koch <wk@g10code.com> + * app.c (app_getattr): Return APPTYPE or SERIALNO type even if the + application does dot support the getattr call. + * app-openpgp.c (get_one_do): Never try to get a non cacheable object from the cache. (get_one_do): Add new arg to return an error code. Changed all @@ -13,6 +16,7 @@ been removed without a reset. (do_reset, cmd_serialno): Clear that error flag. (TEST_CARD_REMOVAL): New. Use it with all command handlers. + (scd_update_reader_status_file): Set the error flag on all changes. * scdaemon.c (ticker_thread): Termintate if a shutdown is pending. diff --git a/scd/app.c b/scd/app.c index 857f9e10b..384ee2143 100644 --- a/scd/app.c +++ b/scd/app.c @@ -305,6 +305,35 @@ app_getattr (APP app, CTRL ctrl, const char *name) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + + if (app->apptype && name && !strcmp (name, "APPTYPE")) + { + send_status_info (ctrl, "APPTYPE", + app->apptype, strlen (app->apptype), NULL, 0); + return 0; + } + if (name && !strcmp (name, "SERIALNO")) + { + char *serial_and_stamp; + char *serial; + time_t stamp; + int rc; + + rc = app_get_serial_and_stamp (app, &serial, &stamp); + if (rc) + return rc; + rc = asprintf (&serial_and_stamp, "%s %lu", + serial, (unsigned long)stamp); + rc = (rc < 0)? gpg_error_from_errno (errno) : 0; + xfree (serial); + if (rc) + return rc; + send_status_info (ctrl, "SERIALNO", + serial_and_stamp, strlen (serial_and_stamp), NULL, 0); + free (serial_and_stamp); + return 0; + } + if (!app->fnc.getattr) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return app->fnc.getattr (app, ctrl, name); diff --git a/scd/command.c b/scd/command.c index a4fb968cf..63e3e28e1 100644 --- a/scd/command.c +++ b/scd/command.c @@ -239,7 +239,7 @@ percent_plus_unescape (unsigned char *string) operations are done on the same card unless he calls this function. */ static int -cmd_serialno (ASSUAN_CONTEXT ctx, char *line) +cmd_serialno (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc = 0; @@ -248,7 +248,8 @@ cmd_serialno (ASSUAN_CONTEXT ctx, char *line) time_t stamp; /* Clear the remove flag so that the open_card is able to reread it. */ - ctrl->server_local->card_removed = 0; + if (ctrl->server_local->card_removed) + do_reset (ctrl, 0); if ((rc = open_card (ctrl, *line? line:NULL))) return rc; @@ -1092,7 +1093,6 @@ cmd_checkpin (ASSUAN_CONTEXT ctx, char *line) - /* Tell the assuan library about our commands */ static int @@ -1299,10 +1299,6 @@ scd_update_reader_status_file (void) char templ[50]; FILE *fp; - last[slot].any = 1; - last[slot].status = status; - last[slot].changed = changed; - log_info ("updating status of slot %d to 0x%04X\n", slot, status); sprintf (templ, "reader_%d.status", slot); @@ -1318,7 +1314,19 @@ scd_update_reader_status_file (void) } xfree (fname); - /* Send a signal to the primary client, if any. */ + /* Set the card removed flag. We will set this on any + card change because a reset or SERIALNO request must be + done in any case. */ + if (primary_connection && primary_connection->server_local + && last[slot].any ) + primary_connection->server_local->card_removed = 1; + + last[slot].any = 1; + last[slot].status = status; + last[slot].changed = changed; + + + /* Send a signal to the primary client, if any. */ if (primary_connection && primary_connection->server_local && primary_connection->server_local->assuan_ctx) { -- cgit v1.2.3 From faef9f929b845dc712c8d705620661b5bc6f6767 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 25 Feb 2005 16:14:55 +0000 Subject: * findkey.c (modify_description): Keep invalid % escapes, so that %0A may pass through. * agent.h (server_control_s): New field USE_AUTH_CALL. * call-scd.c (agent_card_pksign): Make use of it. * command-ssh.c (data_sign): Set the flag. (ssh_send_key_public): New arg OVERRIDE_COMMENT. (card_key_available): Add new arg CARDSN. (ssh_handler_request_identities): Use the card s/n as comment. (sexp_key_extract): Use GCRYMPI_FMT_STD. (data_sign): Ditto. * learncard.c (make_shadow_info): Moved to .. * protect.c (make_shadow_info): .. here. Return NULL on malloc failure. Made global. * agent.h: Add prototype. * xasprintf.c (xtryasprintf): New. * app-openpgp.c (get_public_key): Make sure not to return negative numbers. (do_sign): Allow passing of indata with algorithm prefix. (do_auth): Allow OPENPGP.3 as an alternative ID. * app.c (app_getattr): Return just the S/N but not the timestamp. * no-libgcrypt.c (gcry_strdup): New. --- agent/ChangeLog | 19 ++++++ agent/agent.h | 3 + agent/call-scd.c | 22 ++++--- agent/command-ssh.c | 156 +++++++++++++++++++++++++++++++++++++--------- agent/findkey.c | 15 +++-- agent/keyformat.txt | 4 +- agent/learncard.c | 28 +-------- agent/protect-tool.c | 2 +- agent/protect.c | 37 ++++++++++- common/ChangeLog | 4 ++ common/util.h | 4 ++ common/xasprintf.c | 20 +++++- scd/ChangeLog | 9 +++ scd/app-openpgp.c | 86 +++++++++++++++++++------ scd/app.c | 10 +-- tools/ChangeLog | 4 ++ tools/gpg-connect-agent.c | 47 ++++++++++++-- tools/no-libgcrypt.c | 6 ++ 18 files changed, 368 insertions(+), 108 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 118559c64..2138f6674 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,22 @@ +2005-02-25 Werner Koch <wk@g10code.com> + + * findkey.c (modify_description): Keep invalid % escapes, so that + %0A may pass through. + + * agent.h (server_control_s): New field USE_AUTH_CALL. + * call-scd.c (agent_card_pksign): Make use of it. + * command-ssh.c (data_sign): Set the flag. + (ssh_send_key_public): New arg OVERRIDE_COMMENT. + (card_key_available): Add new arg CARDSN. + (ssh_handler_request_identities): Use the card s/n as comment. + (sexp_key_extract): Use GCRYMPI_FMT_STD. + (data_sign): Ditto. + + * learncard.c (make_shadow_info): Moved to .. + * protect.c (make_shadow_info): .. here. Return NULL on malloc + failure. Made global. + * agent.h: Add prototype. + 2005-02-24 Werner Koch <wk@g10code.com> * call-scd.c (unescape_status_string): New. Actual a copy of diff --git a/agent/agent.h b/agent/agent.h index 39e479e48..e12a02b6e 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -116,6 +116,8 @@ struct server_control_s { char keygrip[20]; int have_keygrip; + int use_auth_call; /* Hack to send the PKAUTH command instead of the + PKSIGN command tro scdaemon. */ }; typedef struct server_control_s *CTRL; typedef struct server_control_s *ctrl_t; @@ -204,6 +206,7 @@ int agent_protect (const unsigned char *plainkey, const char *passphrase, int agent_unprotect (const unsigned char *protectedkey, const char *passphrase, unsigned char **result, size_t *resultlen); int agent_private_key_type (const unsigned char *privatekey); +unsigned char *make_shadow_info (const char *serialno, const char *idstring); int agent_shadow_key (const unsigned char *pubkey, const unsigned char *shadow_info, unsigned char **result); diff --git a/agent/call-scd.c b/agent/call-scd.c index f7d32f7cf..904059291 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -225,15 +225,16 @@ start_scd (ctrl_t ctrl) /* Tell the scdaemon that we want him to send us an event signal. But only do this if we are running as a regular sever and not simply as a pipe server. */ - if (ctrl->connection_fd != -1) - { -#ifndef HAVE_W32_SYSTEM - char buf[100]; + /* Fixme: gpg-agent does not use this signal yet. */ +/* if (ctrl->connection_fd != -1) */ +/* { */ +/* #ifndef HAVE_W32_SYSTEM */ +/* char buf[100]; */ - sprintf (buf, "OPTION event-signal=%d", SIGUSR2); - assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); -#endif - } +/* sprintf (buf, "OPTION event-signal=%d", SIGUSR2); */ +/* assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); */ +/* #endif */ +/* } */ return 0; } @@ -505,7 +506,8 @@ agent_card_pksign (ctrl_t ctrl, inqparm.ctx = scd_ctx; inqparm.getpin_cb = getpin_cb; inqparm.getpin_cb_arg = getpin_cb_arg; - snprintf (line, DIM(line)-1, "PKSIGN %s", keyid); + snprintf (line, DIM(line)-1, + ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid); line[DIM(line)-1] = 0; rc = assuan_transact (scd_ctx, line, membuf_data_cb, &data, @@ -518,7 +520,7 @@ agent_card_pksign (ctrl_t ctrl, } sigbuf = get_membuf (&data, &sigbuflen); - /* create an S-expression from it which is formatted like this: + /* Create an S-expression from it which is formatted like this: "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */ *r_buflen = 21 + 11 + sigbuflen + 4; *r_buf = xtrymalloc (*r_buflen); diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 2c0d25ef6..ebb44fa74 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -659,7 +659,9 @@ open_control_file (FILE **r_fp, int append) (i.e. where Pth might switch threads) we need to employ a mutex. */ *r_fp = NULL; - fname = make_filename (opt.homedir, "sshcontrol.txt", NULL); + fname = make_filename (opt.homedir, "sshcontrol", NULL); + /* FIXME: With "a+" we are not able to check whether this will will + be created and thus the blurb needs to be written first. */ fp = fopen (fname, append? "a+":"r"); if (!fp && errno == ENOENT) { @@ -1146,7 +1148,9 @@ sexp_key_extract (gcry_sexp_t sexp, break; } - mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG); + /* Note that we need to use STD format; i.e. prepend a 0x00 to + indicate a positive number if the high bit is set. */ + mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD); if (! mpi) { err = gpg_error (GPG_ERR_INV_SEXP); @@ -1404,9 +1408,12 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, } -/* Write the public key KEY_PUBLIC to STREAM in SSH key format. */ +/* Write the public key KEY_PUBLIC to STREAM in SSH key format. If + OVERRIDE_COMMENT is not NULL, it will be used instead of the + comment stored in the key. */ static gpg_error_t -ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) +ssh_send_key_public (estream_t stream, gcry_sexp_t key_public, + const char *override_comment) { ssh_key_type_spec_t spec; gcry_mpi_t *mpi_list; @@ -1442,7 +1449,8 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public) if (err) goto out; - err = stream_write_cstring (stream, comment); + err = stream_write_cstring (stream, + override_comment? override_comment : comment); out: @@ -1520,17 +1528,23 @@ key_secret_to_public (gcry_sexp_t *key_public, /* Chec whether a smartcard is available and whether it has a usable key. Store a copy of that key at R_PK and return 0. If no key is - available store NULL at R_PK and return an error code. */ + available store NULL at R_PK and return an error code. If CARDSN + is no NULL, a string with the serial number of the card will be + amalloced and stored there. */ static gpg_error_t -card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk) +card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) { gpg_error_t err; char *appname; - unsigned char *sbuf; - size_t sbuflen; - gcry_sexp_t pk; + char *serialno = NULL; + unsigned char *pkbuf; + size_t pkbuflen; + gcry_sexp_t s_pk; + unsigned char grip[20]; *r_pk = NULL; + if (cardsn) + *cardsn = NULL; /* First see whether a card is available and whether the application is supported. */ @@ -1538,53 +1552,135 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk) if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED ) { /* Ask for the serial number to reset the card. */ - err = agent_card_serialno (ctrl, &appname); + err = agent_card_serialno (ctrl, &serialno); if (err) { if (opt.verbose) - log_info (_("can't get serial number of card: %s\n"), + log_info (_("error getting serial number of card: %s\n"), gpg_strerror (err)); return err; } - log_info (_("detected card with S/N: %s\n"), appname); - xfree (appname); + log_info (_("detected card with S/N: %s\n"), serialno); err = agent_card_getattr (ctrl, "APPTYPE", &appname); } if (err) { log_error (_("error getting application type of card: %s\n"), gpg_strerror (err)); + xfree (serialno); return err; } if (strcmp (appname, "OPENPGP")) { log_info (_("card application `%s' is not supported\n"), appname); xfree (appname); + xfree (serialno); return gpg_error (GPG_ERR_NOT_SUPPORTED); } xfree (appname); appname = NULL; + /* Get the S/N if we don't have it yet. Use the fast getattr method. */ + if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) ) + { + log_error (_("error getting serial number of card: %s\n"), + gpg_strerror (err)); + return err; + } + /* Read the public key. */ - err = agent_card_readkey (ctrl, "OPENPGP.3", &sbuf); + err = agent_card_readkey (ctrl, "OPENPGP.3", &pkbuf); if (err) { if (opt.verbose) log_info (_("no suitable card key found: %s\n"), gpg_strerror (err)); + xfree (serialno); return err; } - sbuflen = gcry_sexp_canon_len (sbuf, 0, NULL, NULL); - err = gcry_sexp_sscan (&pk, NULL, sbuf, sbuflen); - xfree (sbuf); + pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL); + err = gcry_sexp_sscan (&s_pk, NULL, pkbuf, pkbuflen); if (err) { log_error ("failed to build S-Exp from received card key: %s\n", gpg_strerror (err)); + xfree (pkbuf); + xfree (serialno); return err; } - *r_pk = pk; + if ( !gcry_pk_get_keygrip (s_pk, grip) ) + { + log_debug ("error computing keygrip from received card key\n"); + xfree (pkbuf); + gcry_sexp_release (s_pk); + xfree (serialno); + return gpg_error (GPG_ERR_INTERNAL); + } + + if ( agent_key_available (grip) ) + { + /* (Shadow)-key is not available in our key storage. */ + unsigned char *shadow_info; + unsigned char *tmp; + + shadow_info = make_shadow_info (serialno, "OPENPGP.3"); + if (!shadow_info) + { + err = gpg_error_from_errno (errno); + xfree (pkbuf); + gcry_sexp_release (s_pk); + xfree (serialno); + return err; + } + err = agent_shadow_key (pkbuf, shadow_info, &tmp); + xfree (shadow_info); + if (err) + { + log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err)); + xfree (pkbuf); + gcry_sexp_release (s_pk); + xfree (serialno); + return err; + } + xfree (pkbuf); + pkbuf = tmp; + pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL); + assert (pkbuflen); + + err = agent_write_private_key (grip, pkbuf, pkbuflen, 0); + if (err) + { + log_error (_("error writing key: %s\n"), gpg_strerror (err)); + xfree (pkbuf); + gcry_sexp_release (s_pk); + xfree (serialno); + return err; + } + } + + if (cardsn) + { + size_t snlen = strlen (serialno); + + if (snlen == 32 + && !memcmp (serialno, "D27600012401", 12)) /* OpenPGP card. */ + *cardsn = xtryasprintf ("cardno:%.12s", serialno+16); + else /* Something is wrong: Print all. */ + *cardsn = xtryasprintf ("cardno:%s", serialno); + if (!*cardsn) + { + err = gpg_error_from_errno (errno); + xfree (pkbuf); + gcry_sexp_release (s_pk); + xfree (serialno); + return err; + } + } + + xfree (pkbuf); + xfree (serialno); + *r_pk = s_pk; return 0; } @@ -1615,6 +1711,7 @@ ssh_handler_request_identities (ctrl_t ctrl, gpg_error_t ret_err; int ret; FILE *ctrl_fp = NULL; + char *cardsn; /* Prepare buffer stream. */ @@ -1665,13 +1762,14 @@ ssh_handler_request_identities (ctrl_t ctrl, /* First check whether a key is currently available in the card reader - this should be allowed even without being listed in - sshcontrol.txt. */ + sshcontrol. */ - if (!card_key_available (ctrl, &key_public)) + if (!card_key_available (ctrl, &key_public, &cardsn)) { - err = ssh_send_key_public (key_blobs, key_public); + err = ssh_send_key_public (key_blobs, key_public, cardsn); gcry_sexp_release (key_public); key_public = NULL; + xfree (cardsn); if (err) goto out; @@ -1740,7 +1838,7 @@ ssh_handler_request_identities (ctrl_t ctrl, gcry_sexp_release (key_secret); key_secret = NULL; - err = ssh_send_key_public (key_blobs, key_public); + err = ssh_send_key_public (key_blobs, key_public, NULL); if (err) goto out; @@ -1845,9 +1943,11 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, sig_value = NULL; mpis = NULL; + ctrl->use_auth_call = 1; err = agent_pksign_do (ctrl, - _("Please provide the passphrase " - "for the ssh key `%c':"), &signature_sexp, 0); + _("Please enter the passphrase " + "for the ssh key%0A %c"), &signature_sexp, 0); + ctrl->use_auth_call = 0; if (err) goto out; @@ -2189,7 +2289,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME: Why?? */ - /* Check whether the key is alread in our key storage. Don't do + /* Check whether the key is already in our key storage. Don't do anything then. */ if ( !agent_key_available (key_grip_raw) ) goto out; /* Yes, key is available. */ @@ -2200,8 +2300,8 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) goto out; if ( asprintf (&description, - _("Please enter a passphrase to protect%%0A" - "the received secret key%%0A" + _("Please enter a passphrase to protect" + " the received secret key%%0A" " %s%%0A" "within gpg-agent's key storage"), comment ? comment : "?") < 0) diff --git a/agent/findkey.c b/agent/findkey.c index 86a28d511..0b5816bf5 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -166,9 +166,7 @@ modify_description (const char *in, const char *comment, char **result) special = 0; for (i = 0; i < in_len; i++) { - if (in[i] == '%') - special = 1; - else if (special) + if (special) { special = 0; switch (in[i]) @@ -190,10 +188,19 @@ modify_description (const char *in, const char *comment, char **result) out_len += comment_length; break; - default: /* Invalid special sequences are ignored. */ + default: /* Invalid special sequences are kept as they are. */ + if (out) + { + *out++ = '%'; + *out++ = in[i]; + } + else + out_len+=2; break; } } + else if (in[i] == '%') + special = 1; else { if (out) diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 726990315..7bdb94c0e 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -161,9 +161,9 @@ term secret key because it can be visually be better distinguished from the term public key. [2] The keygrip is a unique identifier for a key pair, it is -independent of any protocol, so that the same key can be ised with +independent of any protocol, so that the same key can be used with different protocols. PKCS-15 calls this a subjectKeyHash; it can be -calculate using Libgcrypt's gcry_pk_get_keygrip(). +calculated using Libgcrypt's gcry_pk_get_keygrip (). [3] Even when canonical representation are required we will show the S-expression here in a more readable representation. diff --git a/agent/learncard.c b/agent/learncard.c index 7dcacee28..72238507f 100644 --- a/agent/learncard.c +++ b/agent/learncard.c @@ -1,5 +1,5 @@ /* learncard.c - Handle the LEARN command - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -239,32 +239,6 @@ sinfo_cb (void *opaque, const char *keyword, size_t keywordlen, } -/* Create an S-expression with the shadow info. */ -static unsigned char * -make_shadow_info (const char *serialno, const char *idstring) -{ - const char *s; - unsigned char *info, *p; - char numbuf[21]; - int n; - - for (s=serialno, n=0; *s && s[1]; s += 2) - n++; - - info = p = xtrymalloc (1 + 21 + n - + 21 + strlen (idstring) + 1 + 1); - *p++ = '('; - sprintf (numbuf, "%d:", n); - p = stpcpy (p, numbuf); - for (s=serialno; *s && s[1]; s += 2) - *p++ = xtoi_2 (s); - sprintf (numbuf, "%d:", strlen (idstring)); - p = stpcpy (p, numbuf); - p = stpcpy (p, idstring); - *p++ = ')'; - *p = 0; - return info; -} static int send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context) diff --git a/agent/protect-tool.c b/agent/protect-tool.c index ee0276a43..c21aa0517 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -110,7 +110,7 @@ static ARGPARSE_OPTS opts[] = { { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, { oProtect, "protect", 256, "protect a private key"}, { oUnprotect, "unprotect", 256, "unprotect a private key"}, - { oShadow, "shadow", 256, "create a shadow entry for a priblic key"}, + { oShadow, "shadow", 256, "create a shadow entry for a public key"}, { oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"}, { oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""}, diff --git a/agent/protect.c b/agent/protect.c index cafeb4685..ae3061c77 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -831,10 +831,43 @@ hash_passphrase (const char *passphrase, int hashalgo, + +/* Create an canonical encoded S-expression with the shadow info from + a card's SERIALNO and the IDSTRING. */ +unsigned char * +make_shadow_info (const char *serialno, const char *idstring) +{ + const char *s; + unsigned char *info, *p; + char numbuf[21]; + int n; + + for (s=serialno, n=0; *s && s[1]; s += 2) + n++; + + info = p = xtrymalloc (1 + 21 + n + + 21 + strlen (idstring) + 1 + 1); + if (!info) + return NULL; + *p++ = '('; + sprintf (numbuf, "%d:", n); + p = stpcpy (p, numbuf); + for (s=serialno; *s && s[1]; s += 2) + *p++ = xtoi_2 (s); + sprintf (numbuf, "%d:", strlen (idstring)); + p = stpcpy (p, numbuf); + p = stpcpy (p, idstring); + *p++ = ')'; + *p = 0; + return info; +} + + + /* Create a shadow key from a public key. We use the shadow protocol "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting S-expression is returned in an allocated buffer RESULT will point - to. The input parameters are expected to be valid canonilized + to. The input parameters are expected to be valid canonicalized S-expressions */ int agent_shadow_key (const unsigned char *pubkey, @@ -894,7 +927,7 @@ agent_shadow_key (const unsigned char *pubkey, s++; assert (depth == 1); - /* calculate required length by taking in account: the "shadowed-" + /* Calculate required length by taking in account: the "shadowed-" prefix, the "shadowed", "t1-v1" as well as some parenthesis */ n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1; *result = p = xtrymalloc (n); diff --git a/common/ChangeLog b/common/ChangeLog index e323dc148..db0593176 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2005-02-25 Werner Koch <wk@g10code.com> + + * xasprintf.c (xtryasprintf): New. + 2005-01-26 Moritz Schulte <moritz@g10code.com> * Makefile.am (libcommon_a_SOURCES): New source files: estream.c, diff --git a/common/util.h b/common/util.h index 4ab55acb4..bbf7241a3 100644 --- a/common/util.h +++ b/common/util.h @@ -131,6 +131,10 @@ const char *default_homedir (void); 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); +/* Same as asprintf but return an allocated buffer suitable to be + freed using xfree. This function returns NULL on memory failure and + sets errno. */ +char *xtryasprintf (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); diff --git a/common/xasprintf.c b/common/xasprintf.c index 2c8fafc06..a3b5e27ac 100644 --- a/common/xasprintf.c +++ b/common/xasprintf.c @@ -1,5 +1,5 @@ /* xasprintf.c - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -42,3 +42,21 @@ xasprintf (const char *fmt, ...) free (buf); return p; } + +/* Same as above bit return NULL on memory failure. */ +char * +xtryasprintf (const char *fmt, ...) +{ + int rc; + va_list ap; + char *buf, *p; + + va_start (ap, fmt); + rc = vasprintf (&buf, fmt, ap); + va_end (ap); + if (rc < 0) + return NULL; + p = xtrystrdup (buf); + free (buf); + return p; +} diff --git a/scd/ChangeLog b/scd/ChangeLog index dc394b677..e3b4ae64c 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2005-02-25 Werner Koch <wk@g10code.com> + + * app-openpgp.c (get_public_key): Make sure not to return negative + numbers. + (do_sign): Allow passing of indata with algorithm prefix. + (do_auth): Allow OPENPGP.3 as an alternative ID. + + * app.c (app_getattr): Return just the S/N but not the timestamp. + 2005-02-24 Werner Koch <wk@g10code.com> * app.c (app_getattr): Return APPTYPE or SERIALNO type even if the diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 14c802d10..6ebc13704 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -794,6 +794,8 @@ get_public_key (app_t app, int keyno) const unsigned char *keydata, *m, *e; size_t buflen, keydatalen, mlen, elen; gcry_sexp_t sexp; + unsigned char *mbuf = NULL; + unsigned char *ebuf = NULL; if (keyno < 1 || keyno > 3) return gpg_error (GPG_ERR_INV_ID); @@ -835,6 +837,7 @@ get_public_key (app_t app, int keyno) log_error (_("response does not contain the RSA modulus\n")); goto leave; } + e = find_tlv (keydata, keydatalen, 0x0082, &elen); if (!e) @@ -844,10 +847,38 @@ get_public_key (app_t app, int keyno) goto leave; } + /* Prepend numbers with a 0 if needed. */ + if (mlen && (*m & 0x80)) + { + mbuf = xtrymalloc ( mlen + 1); + if (!mbuf) + { + err = gpg_error_from_errno (errno); + goto leave; + } + *mbuf = 0; + memcpy (mbuf+1, m, mlen); + mlen++; + m = mbuf; + } + if (elen && (*e & 0x80)) + { + ebuf = xtrymalloc ( elen + 1); + if (!ebuf) + { + err = gpg_error_from_errno (errno); + goto leave; + } + *ebuf = 0; + memcpy (ebuf+1, e, elen); + elen++; + e = ebuf; + } + + err = gcry_sexp_build (&sexp, NULL, "(public-key (rsa (n %b) (e %b)))", (int)mlen, m,(int)elen, e); - if (err) { log_error ("error formatting the key into an S-expression: %s\n", @@ -874,6 +905,8 @@ get_public_key (app_t app, int keyno) app->app_local->pk[keyno].read_done = 1; xfree (buffer); + xfree (mbuf); + xfree (ebuf); return 0; } #endif /* GNUPG_MAJOR_VERSION > 1 */ @@ -1557,7 +1590,15 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, if (!keyidstr || !*keyidstr) return gpg_error (GPG_ERR_INV_VALUE); - if (indatalen != 20) + if (indatalen == 20) + ; + else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_SHA1 + && !memcmp (indata, sha1_prefix, 15)) + ; + else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_RMD160 + && !memcmp (indata, rmd160_prefix, 15)) + ; + else return gpg_error (GPG_ERR_INV_VALUE); /* Check whether an OpenPGP card of any version has been requested. */ @@ -1668,7 +1709,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, /* Compute a digital signature using the INTERNAL AUTHENTICATE command on INDATA which is expected to be the raw message digest. For this application the KEYIDSTR consists of the serialnumber and the - fingerprint delimited by a slash. + fingerprint delimited by a slash. Optionally the id OPENPGP.3 may + be given. Note that this fucntion may return the error code GPG_ERR_WRONG_CARD to indicate that the card currently present does @@ -1693,27 +1735,31 @@ do_auth (app_t app, const char *keyidstr, return gpg_error (GPG_ERR_INV_VALUE); /* Check whether an OpenPGP card of any version has been requested. */ - if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) - return gpg_error (GPG_ERR_INV_ID); - - for (s=keyidstr, n=0; hexdigitp (s); s++, n++) + if (!strcmp (keyidstr, "OPENPGP.3")) ; - if (n != 32) + else if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) return gpg_error (GPG_ERR_INV_ID); - else if (!*s) - ; /* no fingerprint given: we allow this for now. */ - else if (*s == '/') - fpr = s + 1; else - return gpg_error (GPG_ERR_INV_ID); - - for (s=keyidstr, n=0; n < 16; s += 2, n++) - tmp_sn[n] = xtoi_2 (s); + { + for (s=keyidstr, n=0; hexdigitp (s); s++, n++) + ; + if (n != 32) + return gpg_error (GPG_ERR_INV_ID); + else if (!*s) + ; /* no fingerprint given: we allow this for now. */ + else if (*s == '/') + fpr = s + 1; + else + return gpg_error (GPG_ERR_INV_ID); - if (app->serialnolen != 16) - return gpg_error (GPG_ERR_INV_CARD); - if (memcmp (app->serialno, tmp_sn, 16)) - return gpg_error (GPG_ERR_WRONG_CARD); + for (s=keyidstr, n=0; n < 16; s += 2, n++) + tmp_sn[n] = xtoi_2 (s); + + if (app->serialnolen != 16) + return gpg_error (GPG_ERR_INV_CARD); + if (memcmp (app->serialno, tmp_sn, 16)) + return gpg_error (GPG_ERR_WRONG_CARD); + } /* If a fingerprint has been specified check it against the one on the card. This is allows for a meaningful error message in case diff --git a/scd/app.c b/scd/app.c index 384ee2143..0625dc8ef 100644 --- a/scd/app.c +++ b/scd/app.c @@ -314,7 +314,6 @@ app_getattr (APP app, CTRL ctrl, const char *name) } if (name && !strcmp (name, "SERIALNO")) { - char *serial_and_stamp; char *serial; time_t stamp; int rc; @@ -322,15 +321,8 @@ app_getattr (APP app, CTRL ctrl, const char *name) rc = app_get_serial_and_stamp (app, &serial, &stamp); if (rc) return rc; - rc = asprintf (&serial_and_stamp, "%s %lu", - serial, (unsigned long)stamp); - rc = (rc < 0)? gpg_error_from_errno (errno) : 0; + send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0); xfree (serial); - if (rc) - return rc; - send_status_info (ctrl, "SERIALNO", - serial_and_stamp, strlen (serial_and_stamp), NULL, 0); - free (serial_and_stamp); return 0; } diff --git a/tools/ChangeLog b/tools/ChangeLog index 6895198c5..4d520cfca 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-02-25 Werner Koch <wk@g10code.com> + + * no-libgcrypt.c (gcry_strdup): New. + 2005-02-24 Werner Koch <wk@g10code.com> * gpg-connect-agent.c: New. diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 399a5d369..19ff160f0 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <ctype.h> #include <assuan.h> #include "i18n.h" @@ -40,7 +41,8 @@ enum cmd_and_opt_values oVerbose = 'v', oNoVerbose = 500, - oHomedir + oHomedir, + oHex }; @@ -52,6 +54,7 @@ static ARGPARSE_OPTS opts[] = { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("quiet") }, + { oHex, "hex", 0, N_("print data out hex encoded") }, /* hidden options */ { oNoVerbose, "no-verbose", 0, "@"}, @@ -66,7 +69,7 @@ struct int verbose; /* Verbosity level. */ int quiet; /* Be extra quiet. */ const char *homedir; /* Configuration directory name */ - + int hex; /* Print data lines in hex format. */ } opt; @@ -155,6 +158,7 @@ main (int argc, char **argv) case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; case oHomedir: opt.homedir = pargs.r.ret_str; break; + case oHex: opt.hex = 1; break; default: pargs.err = 2; break; } @@ -220,6 +224,7 @@ read_and_print_response (assuan_context_t ctx) char *line; int linelen; assuan_error_t rc; + int i, j; for (;;) { @@ -234,8 +239,42 @@ read_and_print_response (assuan_context_t ctx) if (linelen >= 1 && line[0] == 'D' && line[1] == ' ') { - fwrite (line, linelen, 1, stdout); - putchar ('\n'); + if (opt.hex) + { + for (i=2; i < linelen; ) + { + int save_i = i; + + printf ("D[%04X] ", i-2); + for (j=0; j < 16 ; j++, i++) + { + if (j == 8) + putchar (' '); + if (i < linelen) + printf (" %02X", ((unsigned char*)line)[i]); + else + fputs (" ", stdout); + } + fputs (" ", stdout); + i= save_i; + for (j=0; j < 16; j++, i++) + { + unsigned int c = ((unsigned char*)line)[i]; + if ( i >= linelen ) + putchar (' '); + else if (isascii (c) && isprint (c) && !iscntrl (c)) + putchar (c); + else + putchar ('.'); + } + putchar ('\n'); + } + } + else + { + fwrite (line, linelen, 1, stdout); + putchar ('\n'); + } } else if (linelen >= 1 && line[0] == 'S' diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c index 0fabec90d..82f6a8bb5 100644 --- a/tools/no-libgcrypt.c +++ b/tools/no-libgcrypt.c @@ -53,6 +53,12 @@ gcry_xmalloc (size_t n) return p; } +char * +gcry_strdup (const char *string) +{ + return malloc (strlen (string)+1); +} + void * gcry_realloc (void *a, size_t n) -- cgit v1.2.3 From 843e844d98499efa9b29416661ea74d64fe61177 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 2 Mar 2005 20:36:50 +0000 Subject: 2005-03-02 Moritz Schulte <moritz@g10code.com> * command-ssh.c (sexp_key_extract): Removed FIXME, since xtrymallos does set errno correctly by now. (sexp_extract_identifier): Remove const attribute from identifier. (ssh_handler_request_identities): Remove const attribute from key_type; removes ugly casts and FIXME. (sexp_key_extract): Remove const attribute from comment. (ssh_send_key_public): Remove const attribute from key_type/comment; removes ugly cast. (data_sign): Remove const attribute from identifier; removes ugly cast. (key_secret_to_public): Remove const attribute from comment; removes ugly cast. (ssh_handler_sign_request): Remove const attribute from p. (sexp_key_extract): Use make_cstring(). (ssh_key_extract_comment): Likewise. (ssh_key_to_buffer): Use secure memory for memory area to hold the key S-Expression. Added more comments. --- agent/ChangeLog | 21 +++++++++++++++ agent/command-ssh.c | 77 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 70 insertions(+), 28 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 2138f6674..c16e0e37a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,24 @@ +2005-03-02 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (sexp_key_extract): Removed FIXME, since + xtrymallos does set errno correctly by now. + (sexp_extract_identifier): Remove const attribute from identifier. + (ssh_handler_request_identities): Remove const attribute from + key_type; removes ugly casts and FIXME. + (sexp_key_extract): Remove const attribute from comment. + (ssh_send_key_public): Remove const attribute from + key_type/comment; removes ugly cast. + (data_sign): Remove const attribute from identifier; removes ugly + cast. + (key_secret_to_public): Remove const attribute from comment; + removes ugly cast. + (ssh_handler_sign_request): Remove const attribute from p. + (sexp_key_extract): Use make_cstring(). + (ssh_key_extract_comment): Likewise. + (ssh_key_to_buffer): Use secure memory for memory area to hold the + key S-Expression. + Added more comments. + 2005-02-25 Werner Koch <wk@g10code.com> * findkey.c (modify_description): Keep invalid % escapes, so that diff --git a/agent/command-ssh.c b/agent/command-ssh.c index ebb44fa74..3b2dcd335 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1075,7 +1075,7 @@ sexp_key_construct (gcry_sexp_t *sexp, static gpg_error_t sexp_key_extract (gcry_sexp_t sexp, ssh_key_type_spec_t key_spec, int *secret, - gcry_mpi_t **mpis, const char **comment) + gcry_mpi_t **mpis, char **comment) { gpg_error_t err; gcry_sexp_t value_list; @@ -1127,7 +1127,7 @@ sexp_key_extract (gcry_sexp_t sexp, mpis_new = xtrymalloc (sizeof (*mpis_new) * (elems_n + 1)); if (! mpis_new) { - err = gpg_error_from_errno (errno); /* FIXME, xtrymalloc+errno. */ + err = gpg_error_from_errno (errno); goto out; } memset (mpis_new, 0, sizeof (*mpis_new) * (elems_n + 1)); @@ -1176,14 +1176,12 @@ sexp_key_extract (gcry_sexp_t sexp, data_n = 6; } - comment_new = xtrymalloc (data_n + 1); + comment_new = make_cstring (data, data_n); if (! comment_new) { err = gpg_error_from_errno (errno); goto out; } - strncpy (comment_new, data, data_n); - comment_new[data_n] = 0; if (secret) *secret = is_secret; @@ -1208,7 +1206,7 @@ sexp_key_extract (gcry_sexp_t sexp, /* Extract the car from SEXP, and create a newly created C-string which is to be stored in IDENTIFIER. */ static gpg_error_t -sexp_extract_identifier (gcry_sexp_t sexp, const char **identifier) +sexp_extract_identifier (gcry_sexp_t sexp, char **identifier) { char *identifier_new; gcry_sexp_t sublist; @@ -1251,8 +1249,16 @@ sexp_extract_identifier (gcry_sexp_t sexp, const char **identifier) -/* Key I/O. */ +/* + + Key I/O. +*/ + +/* Search for a key specification entry. If SSH_NAME is not NULL, + search for an entry whose "ssh_name" is equal to SSH_NAME; + otherwise, search for an entry whose "name" is equal to NAME. + Store found entry in SPEC on success, return error otherwise. */ static gpg_error_t ssh_key_type_lookup (const char *ssh_name, const char *name, ssh_key_type_spec_t *spec) @@ -1276,6 +1282,11 @@ ssh_key_type_lookup (const char *ssh_name, const char *name, return err; } +/* Receive a key from STREAM, according to the key specification given + as KEY_SPEC. Depending on SECRET, receive a secret or a public + key. If READ_COMMENT is true, receive a comment string as well. + Constructs a new S-Expression from received data and stores it in + KEY_NEW. Returns zero on success or an error code. */ static gpg_error_t ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, int read_comment, ssh_key_type_spec_t *key_spec) @@ -1342,6 +1353,9 @@ ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret, return err; } +/* Converts a key of type TYPE, whose key material is given in MPIS, + into a newly created binary blob, which is to be stored in + BLOB/BLOB_SIZE. Returns zero on success or an error code. */ static gpg_error_t ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, const char *type, gcry_mpi_t *mpis) @@ -1417,8 +1431,8 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public, { ssh_key_type_spec_t spec; gcry_mpi_t *mpi_list; - const char *key_type; - const char *comment; + char *key_type; + char *comment; unsigned char *blob; size_t blob_n; gpg_error_t err; @@ -1455,13 +1469,16 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public, out: mpint_list_free (mpi_list); - xfree ((void *) key_type); - xfree ((void *) comment); + xfree (key_type); + xfree (comment); xfree (blob); return err; } +/* Read a public key out of BLOB/BLOB_SIZE according to the key + specification given as KEY_SPEC, storing the new key in KEY_PUBLIC. + Returns zero on success or an error code. */ static gpg_error_t ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, gcry_sexp_t *key_public, @@ -1499,11 +1516,14 @@ ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, +/* Converts the secret key KEY_SECRET into a public key, storing it in + KEY_PUBLIC. SPEC is the according key specification. Returns zero + on success or an error code. */ static gpg_error_t key_secret_to_public (gcry_sexp_t *key_public, ssh_key_type_spec_t spec, gcry_sexp_t key_secret) { - const char *comment; + char *comment; gcry_mpi_t *mpis; gpg_error_t err; int is_secret; @@ -1520,13 +1540,13 @@ key_secret_to_public (gcry_sexp_t *key_public, out: mpint_list_free (mpis); - xfree ((char *) comment); + xfree (comment); return err; } -/* Chec whether a smartcard is available and whether it has a usable +/* Check whether a smartcard is available and whether it has a usable key. Store a copy of that key at R_PK and return 0. If no key is available store NULL at R_PK and return an error code. If CARDSN is no NULL, a string with the serial number of the card will be @@ -1685,16 +1705,21 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) } + /* + Request handler. - */ +*/ + + +/* Handler for the "request_identities" command. */ static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, estream_t request, estream_t response) { - const char *key_type; + char *key_type; ssh_key_type_spec_t spec; struct dirent *dir_entry; char *key_directory; @@ -1828,7 +1853,7 @@ ssh_handler_request_identities (ctrl_t ctrl, if (err) goto out; - xfree ((void *) key_type); + xfree (key_type); key_type = NULL; err = key_secret_to_public (&key_public, spec, key_secret); @@ -1894,13 +1919,12 @@ ssh_handler_request_identities (ctrl_t ctrl, free (key_directory); xfree (key_path); xfree (buffer); - /* FIXME: Ist is for sure is a Bad Thing to use the const qualifier - and later cast it away. You can't do that!!! */ - xfree ((void *) key_type); /* FIXME? */ + xfree (key_type); return ret_err; } +/* */ static gpg_error_t data_hash (unsigned char *data, size_t data_n, int md_algorithm, unsigned char *hash) @@ -1923,7 +1947,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, gcry_mpi_t sig_value; unsigned char *sig_blob; size_t sig_blob_n; - const char *identifier; + char *identifier; const char *identifier_raw; size_t identifier_n; ssh_key_type_spec_t spec; @@ -2064,7 +2088,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, gcry_sexp_release (signature_sexp); gcry_sexp_release (sublist); mpint_list_free (mpis); - xfree ((void *) identifier); + xfree (identifier); return err; } @@ -2084,7 +2108,7 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) size_t sig_n; u32 data_size; u32 flags; - const void *p; + void *p; gpg_error_t err; gpg_error_t ret_err; @@ -2197,15 +2221,13 @@ ssh_key_extract_comment (gcry_sexp_t key, char **comment) goto out; } - comment_new = xtrymalloc (data_n + 1); + comment_new = make_cstring (data, data_n); if (! comment_new) { err = gpg_error_from_errno (errno); goto out; } - strncpy (comment_new, data, data_n); - comment_new[data_n] = 0; *comment = comment_new; err = 0; @@ -2243,8 +2265,7 @@ ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, err = 0; buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0); - buffer_new = xtrymalloc (buffer_new_n); - /* FIXME: secmem? */ + buffer_new = xtrymalloc_secure (buffer_new_n); if (! buffer_new) { err = gpg_error_from_errno (errno); -- cgit v1.2.3 From df05dde9d59e4ed2a8eefd0a5e285f4930ac7e3a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 3 Mar 2005 10:15:07 +0000 Subject: * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Accidently used --ldflags instead of --cflags. Reported by Kazu Yamamoto. * Makefile.am (AM_CFLAGS): Added PTH_CFLAGS. Noted by Kazu Yamamoto. * Makefile.am (gpgsm_LDADD): Added PTH_LIBS. Noted by Kazu Yamamoto. --- ChangeLog | 5 +++++ THANKS | 3 ++- TODO | 2 ++ acinclude.m4 | 2 +- agent/command-ssh.c | 2 +- common/ChangeLog | 4 ++++ common/Makefile.am | 2 +- sm/ChangeLog | 4 ++++ sm/Makefile.am | 2 +- 9 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c86f42a8..c9f9fe3dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-03-03 Werner Koch <wk@g10code.com> + + * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Accidently used + --ldflags instead of --cflags. Reported by Kazu Yamamoto. + 2005-02-03 Werner Koch <wk@g10code.com> * AUTHORS: Copied from 1.4 and edited to refelct the changes in diff --git a/THANKS b/THANKS index d523474c7..e1424cab1 100644 --- a/THANKS +++ b/THANKS @@ -1,5 +1,6 @@ Alexander Belopolsky belopolsky at mac.com -Richard Lefebvre rick at cerca.umontreal.ca Andrew J. Schorr aschorr at telemetry-investments.com +Kazu Yamamoto kazu@iij.ad.jp Michael Nottebrock michaelnottebrock at gmx.net +Richard Lefebvre rick at cerca.umontreal.ca diff --git a/TODO b/TODO index 2aace782f..9efbe6a1c 100644 --- a/TODO +++ b/TODO @@ -104,3 +104,5 @@ might want to have an agent context for each service request ** No card status notifications. +* [scdaemon] release the card after use so that gpg 1.4 is abale to access it + diff --git a/acinclude.m4 b/acinclude.m4 index 31f540640..e933e6ee0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -246,7 +246,7 @@ AC_DEFUN([GNUPG_PTH_VERSION_CHECK], _gnupg_pth_save_cflags=$CFLAGS _gnupg_pth_save_ldflags=$LDFLAGS _gnupg_pth_save_libs=$LIBS - CFLAGS="$CFLAGS `$PTH_CONFIG --ldflags`" + CFLAGS="$CFLAGS `$PTH_CONFIG --cflags`" LDFLAGS="$LDFLAGS `$PTH_CONFIG --ldflags`" LIBS="$LIBS `$PTH_CONFIG --libs`" AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pth.h> diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 3b2dcd335..f48df69e4 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1550,7 +1550,7 @@ key_secret_to_public (gcry_sexp_t *key_public, key. Store a copy of that key at R_PK and return 0. If no key is available store NULL at R_PK and return an error code. If CARDSN is no NULL, a string with the serial number of the card will be - amalloced and stored there. */ + a malloced and stored there. */ static gpg_error_t card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) { diff --git a/common/ChangeLog b/common/ChangeLog index db0593176..e9bb42a57 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2005-03-03 Werner Koch <wk@g10code.com> + + * Makefile.am (AM_CFLAGS): Added PTH_CFLAGS. Noted by Kazu Yamamoto. + 2005-02-25 Werner Koch <wk@g10code.com> * xasprintf.c (xtryasprintf): New. diff --git a/common/Makefile.am b/common/Makefile.am index 6cbbf9f3a..ed7659793 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -21,7 +21,7 @@ noinst_LIBRARIES = libcommon.a libsimple-pwquery.a -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) $(PTH_CFLAGS) libcommon_a_SOURCES = \ util.h i18n.h \ diff --git a/sm/ChangeLog b/sm/ChangeLog index a4f07b048..85af542d0 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2005-03-03 Werner Koch <wk@g10code.com> + + * Makefile.am (gpgsm_LDADD): Added PTH_LIBS. Noted by Kazu Yamamoto. + 2005-01-13 Werner Koch <wk@g10code.com> * certreqgen.c (proc_parameters): Cast printf arg. diff --git a/sm/Makefile.am b/sm/Makefile.am index 9136eb920..d4f972527 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -54,6 +54,6 @@ gpgsm_SOURCES = \ gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a \ ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -lgpg-error \ - $(LIBINTL) + $(LIBINTL) $(PTH_LIBS) -- cgit v1.2.3 From b16d30910ae2c79400d085d8626ed2b25bfe3961 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 9 Mar 2005 10:11:14 +0000 Subject: Add honor-http-proxy. --- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 4d520cfca..e39dd3b04 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-03-09 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c <dirmngr>: Add honor-http-proxy. + 2005-02-25 Werner Koch <wk@g10code.com> * no-libgcrypt.c (gcry_strdup): New. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e4758c1e6..dd35d3701 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -746,6 +746,9 @@ static gc_option_t gc_options_dirmngr[] = { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", "|URL|redirect all HTTP requests to URL", GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, + { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "dirmngr", N_("use system's HTTP proxy setting"), + GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "LDAP", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, -- cgit v1.2.3 From c6de0c2d4e38b23917b0da3ae711f0b36b24e371 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 9 Mar 2005 19:22:54 +0000 Subject: Fixed description for dirmngr:honor-http-proxy --- tools/gpgconf-comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index dd35d3701..5e6777e1f 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -748,7 +748,7 @@ static gc_option_t gc_options_dirmngr[] = GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "dirmngr", N_("use system's HTTP proxy setting"), - GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR }, + GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR }, { "LDAP", GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, -- cgit v1.2.3 From fde76a2cf83eab4e0a229cfcffb12e467ff564e8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 17 Mar 2005 19:10:37 +0000 Subject: * certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509. * certchain.c (gpgsm_basic_cert_check): Dump certificates after a failed gcry_pk_verify. (find_up): Do an external lookup also for an authorityKeyIdentifier lookup. Factored external lookup code out to .. (find_up_external): .. new. --- sm/ChangeLog | 12 +++++- sm/certchain.c | 133 +++++++++++++++++++++++++++++++++++---------------------- sm/certcheck.c | 10 ++--- 3 files changed, 99 insertions(+), 56 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 85af542d0..bb899f5b7 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,13 @@ +2005-03-17 Werner Koch <wk@g10code.com> + + * certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509. + + * certchain.c (gpgsm_basic_cert_check): Dump certificates after a + failed gcry_pk_verify. + (find_up): Do an external lookup also for an authorityKeyIdentifier + lookup. Factored external lookup code out to .. + (find_up_external): .. new. + 2005-03-03 Werner Koch <wk@g10code.com> * Makefile.am (gpgsm_LDADD): Added PTH_LIBS. Noted by Kazu Yamamoto. @@ -1407,7 +1417,7 @@ * server.c (rc_to_assuan_status): New. Use it for all commands. - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004, 2005 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 diff --git a/sm/certchain.c b/sm/certchain.c index f32507f34..514ee23a5 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1,5 +1,5 @@ /* certchain.c - certificate chain validation - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -275,6 +275,69 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) } + +/* Helper for find_up(). Locate the certificate for ISSUER using an + external lookup. KH is the keydb context we are currently using. + On success 0 is returned and the certificate may be retrieved from + the keydb using keydb_get_cert().*/ +static int +find_up_external (KEYDB_HANDLE kh, const char *issuer) +{ + int rc; + strlist_t names = NULL; + int count = 0; + char *pattern; + const char *s; + + if (opt.verbose) + log_info (_("looking up issuer at external location\n")); + /* The DIRMNGR process is confused about unknown attributes. As a + quick and ugly hack we locate the CN and use the issuer string + starting at this attribite. Fixme: we should have far better + parsing in the dirmngr. */ + s = strstr (issuer, "CN="); + if (!s || s == issuer || s[-1] != ',') + s = issuer; + + pattern = xtrymalloc (strlen (s)+2); + if (!pattern) + return gpg_error_from_errno (errno); + strcpy (stpcpy (pattern, "/"), s); + add_to_strlist (&names, pattern); + xfree (pattern); + + rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count); + free_strlist (names); + + if (opt.verbose) + log_info (_("number of issuers matching: %d\n"), count); + if (rc) + { + log_error ("external key lookup failed: %s\n", gpg_strerror (rc)); + rc = -1; + } + else if (!count) + rc = -1; + else + { + int old; + /* The issuers are currently stored in the ephemeral key DB, so + we temporary switch to ephemeral mode. */ + old = keydb_set_ephemeral (kh, 1); + keydb_search_reset (kh); + rc = keydb_search_subject (kh, issuer); + keydb_set_ephemeral (kh, old); + } + return rc; +} + + +/* Locate issuing certificate for CERT. ISSUER is the name of the + issuer used as a fallback if the other methods don't work. If + FIND_NEXT is true, the function shall return the next possible + issuer. The certificate itself is not directly returned but a + keydb_get_cert on the keyDb context KH will return it. Returns 0 + on success, -1 if not found or an error code. */ static int find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) { @@ -292,7 +355,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) keydb_search_reset (kh); /* In case of an error try the ephemeral DB. We can't do - that in find-next mode because we can't keep the search + that in find_next mode because we can't keep the search state then. */ if (rc == -1 && !find_next) { @@ -305,7 +368,12 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) } keydb_set_ephemeral (kh, old); } + + /* If we didn't found it, try an external lookup. */ + if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) + rc = find_up_external (kh, issuer); } + /* Print a note so that the user does not feel too helpless when an issuer certificate was found and gpgsm prints BAD signature because it is not the correct one. */ @@ -315,16 +383,17 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) gpgsm_dump_serial (authidno); log_printf ("/"); gpgsm_dump_string (s); - log_printf (") not found\n"); + log_printf (") not found using authorityKeyIdentifier\n"); } else if (rc) log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc); ksba_name_release (authid); xfree (authidno); - /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */ + /* Fixme: There is no way to do an external lookup with + serial+issuer. */ } - if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */ + if (rc) /* Not found via authorithyKeyIdentifier, try regular issuer name. */ rc = keydb_search_subject (kh, issuer); if (rc == -1 && !find_next) { @@ -338,51 +407,10 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) keydb_set_ephemeral (kh, old); } + /* Still not found. If enabled, try an external lookup. */ if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) - { - STRLIST names = NULL; - int count = 0; - char *pattern; - const char *s; - - if (opt.verbose) - log_info (_("looking up issuer at external location\n")); - /* dirmngr is confused about unknown attributes so as a quick - and ugly hack we locate the CN and use this and the - following. Fixme: we should have far better parsing in the - dirmngr. */ - s = strstr (issuer, "CN="); - if (!s || s == issuer || s[-1] != ',') - s = issuer; - - pattern = xtrymalloc (strlen (s)+2); - if (!pattern) - return OUT_OF_CORE (errno); - strcpy (stpcpy (pattern, "/"), s); - add_to_strlist (&names, pattern); - xfree (pattern); - rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count); - free_strlist (names); - if (opt.verbose) - log_info (_("number of issuers matching: %d\n"), count); - if (rc) - { - log_error ("external key lookup failed: %s\n", gpg_strerror (rc)); - rc = -1; - } - else if (!count) - rc = -1; - else - { - int old; - /* The issuers are currently stored in the ephemeral key - DB, so we temporary switch to ephemeral mode. */ - old = keydb_set_ephemeral (kh, 1); - keydb_search_reset (kh); - rc = keydb_search_subject (kh, issuer); - keydb_set_ephemeral (kh, old); - } - } + rc = find_up_external (kh, issuer); + return rc; } @@ -959,7 +987,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) } else { - /* find the next cert up the tree */ + /* Find the next cert up the tree. */ keydb_search_reset (kh); rc = find_up (kh, cert, issuer, 0); if (rc) @@ -990,6 +1018,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert) { log_error ("certificate has a BAD signature: %s\n", gpg_strerror (rc)); + if (DBG_X509) + { + gpgsm_dump_cert ("signing issuer", issuer_cert); + gpgsm_dump_cert ("signed subject", cert); + } rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } diff --git a/sm/certcheck.c b/sm/certcheck.c index 4f667cbbe..611d3219c 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -101,7 +101,7 @@ do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits, memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; assert ( n == nframe ); } - if (DBG_X509) + if (DBG_CRYPTO) { int j; log_debug ("encoded hash:"); @@ -196,7 +196,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) ksba_free (p); return gpg_error (GPG_ERR_BUG); } - if (DBG_X509) + if (DBG_CRYPTO) { int j; log_debug ("signature value:"); @@ -251,7 +251,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) rc = gcry_pk_verify (s_sig, s_hash, s_pkey); - if (DBG_CRYPTO) + if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); gcry_md_close (md); gcry_sexp_release (s_sig); @@ -294,7 +294,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } - if (DBG_X509) + if (DBG_CRYPTO) log_printhex ("public key: ", p, n); rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); @@ -321,7 +321,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, gcry_mpi_release (frame); rc = gcry_pk_verify (s_sig, s_hash, s_pkey); - if (DBG_CRYPTO) + if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); -- cgit v1.2.3 From 94767297091652c233f35769b88019a7f4169970 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Tue, 29 Mar 2005 20:46:18 +0000 Subject: 2005-03-29 Moritz Schulte <moritz@g10code.com> * app-openpgp.c (retrieve_fpr_from_card): New function. (retrieve_next_token): New function. (retrieve_key_material): New function. (get_public_key): Implement retrival of key through expernal helper (gpg) in case the openpgp card is not cooperative enough. --- scd/ChangeLog | 8 ++ scd/app-openpgp.c | 330 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 324 insertions(+), 14 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index e3b4ae64c..ca7358406 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,11 @@ +2005-03-29 Moritz Schulte <moritz@g10code.com> + + * app-openpgp.c (retrieve_fpr_from_card): New function. + (retrieve_next_token): New function. + (retrieve_key_material): New function. + (get_public_key): Implement retrival of key through expernal + helper (gpg) in case the openpgp card is not cooperative enough. + 2005-02-25 Werner Koch <wk@g10code.com> * app-openpgp.c (get_public_key): Make sure not to return negative diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 6ebc13704..bae9dde49 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -776,6 +776,263 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) return rc; } +/* Retrieve the fingerprint from the card inserted in SLOT and write + the according hex representation (40 hex digits plus NUL character) + to FPR. */ +static gpg_error_t +retrieve_fpr_from_card (int slot, char *fpr) +{ + const unsigned char *value; + unsigned char *data; + size_t data_n; + gpg_error_t err; + size_t value_n; + unsigned int i; + + data = NULL; + + err = iso7816_get_data (slot, 0x6E, &data, &data_n); + if (err) + /* FIXME */ + goto out; + + value = find_tlv (data, data_n, 0x00C5, &value_n); + if (! (value + && (! (value_n > (data_n - (value - data)))) + && (value_n >= 60))) /* FIXME: Shouldn't this be "== 60"? */ + { + /* FIXME? */ + err = gpg_error (GPG_ERR_CARD); /* */ + goto out; + } + + /* Copy out third key FPR. */ + for (i = 0; i < 20; i++) + sprintf (fpr + (i * 2), "%02X", (value + (2 * 20))[i]); + + out: + + xfree (data); + + return err; +} + +/* Retrieve the next token from S, using ":" as delimiter. */ +static char * +retrieve_next_token (char *s) +{ + char *p; + + p = strtok (s, ":"); + if (! p) + log_error ("error while extracting token\n"); + + return p; +} + +/* Retrieve the secret key material for the key, whose fingerprint is + FPR, from gpg output, which can be read through the stream FP. The + RSA modulus will be stored in m/mlen, the secret exponent in + e/elen. Return zero on success, one on failure. */ +static int +retrieve_key_material (FILE *fp, const char *fpr, + const unsigned char **m, size_t *mlen, + const unsigned char **e, size_t *elen) +{ + size_t line_size; + ssize_t line_ret; + char *line; + int ret; + int found_key; + char *token; + int pkd_n; + unsigned char *m_new; + unsigned char *e_new; + size_t m_new_n; + size_t e_new_n; + int is_rsa; + gcry_mpi_t mpi; + gcry_error_t err; + size_t max_length; + + line_size = 0; + line = NULL; + found_key = 0; + pkd_n = 0; + m_new = NULL; + e_new = NULL; + mpi = NULL; + ret = 0; + + while (1) + { + /* FIXME? */ + max_length = 1024; + line_ret = read_line (fp, &line, &line_size, &max_length); + if (line_ret < 0) + { + ret = 1; + break; + } + if (! line_ret) + /* EOF. */ + /* FIXME? */ + break; + + token = retrieve_next_token (line); + if (! found_key) + { + /* Key not found yet, search for key entry. */ + if ((! strcmp (token, "pub")) || (! strcmp (token, "sub"))) + { + /* Reached next key entry, parse it. */ + + /* This is the trust level (right, FIXME?). */ + token = retrieve_next_token (NULL); + if (! token) + { + ret = 1; + break; + } + + /* This is the size. */ + token = retrieve_next_token (NULL); + if (! token) + { + ret = 1; + break; + } + + /* This is the algorithm (right, FIXME?). */ + token = retrieve_next_token (NULL); + if (! token) + { + ret = 1; + break; + } + is_rsa = ! strcmp (token, "1"); + + /* This is the fingerprint. */ + token = retrieve_next_token (NULL); + if (! token) + { + ret = 1; + break; + } + + if (! strcmp (token, fpr)) + { + /* Found our key. */ + if (! is_rsa) + { + /* FIXME. */ + ret = 1; + break; + } + found_key = 1; + } + } + } + else + { + if (! strcmp (token, "sub")) + /* Next key entry, break. */ + break; + + if (! strcmp (token, "pkd")) + { + if ((pkd_n == 0) || (pkd_n == 1)) + { + /* This is the pkd index. */ + token = retrieve_next_token (NULL); + if (! token) + { + /* FIXME. */ + ret = 1; + break; + } + + /* This is the pkd size. */ + token = retrieve_next_token (NULL); + if (! token) + { + /* FIXME. */ + ret = 1; + break; + } + + /* This is the pkd mpi. */ + token = retrieve_next_token (NULL); + if (! token) + { + /* FIXME. */ + ret = 1; + break; + } + + err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, token, 0, NULL); + if (err) + { + log_error ("error while converting pkd %i from hex: %s\n", + pkd_n, gcry_strerror (err)); + ret = 1; + break; + } + + if (pkd_n == 0) + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, + &m_new, &m_new_n, mpi); + else + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, + &e_new, &e_new_n, mpi); + if (err) + { + log_error ("error while converting pkd %i to std: %s\n", + pkd_n, gcry_strerror (err)); + ret = 1; + break; + } + gcry_mpi_release (mpi); + mpi = NULL; + pkd_n++; + } + else + { + /* Too many pkd entries. */ + /* FIXME */ + ret = 1; + break; + } + } + } + } + if (ret) + goto out; + + if (pkd_n < 2) + { + /* Not enough pkds retrieved. */ + ret = 1; + goto out; + } + + *m = m_new; + *mlen = m_new_n; + *e = e_new; + *elen = e_new_n; + + out: + + if (ret) + { + gcry_free (m_new); + gcry_free (e_new); + } + gcry_mpi_release (mpi); + gcry_free (line); + + return ret; +} /* Get the public key for KEYNO and store it as an S-expresion with the APP handle. On error that field gets cleared. If we already @@ -875,30 +1132,75 @@ get_public_key (app_t app, int keyno) e = ebuf; } - - err = gcry_sexp_build (&sexp, NULL, - "(public-key (rsa (n %b) (e %b)))", - (int)mlen, m,(int)elen, e); - if (err) - { - log_error ("error formatting the key into an S-expression: %s\n", - gpg_strerror (err)); - goto leave; - } - app->app_local->pk[keyno].key = sexp; - } else { /* Due to a design problem in v1.0 cards we can't get the public key out of these cards without doing a verify on CHV3. Clearly that is not an option and thus we try to locate the - key using an external helper. */ + key using an external helper. + + The helper we use here is gpg itself, which should know about + the key in any case. */ + + char fpr_long[41]; + char *fpr = fpr_long + 24; + char *command; + FILE *fp; + int ret; + + command = NULL; + + err = retrieve_fpr_from_card (app->slot, fpr_long); + if (err) + { + log_error ("error while retrieving fpr from card: %s\n", + gpg_strerror (err)); + goto leave; + } + + ret = asprintf (&command, + "gpg --list-keys --with-colons --with-key-data '%s'", + fpr_long); + if (ret < 0) + { + err = gpg_error_from_errno (errno); + log_error ("error while creating pipe command " + "for retrieving key: %s\n", gpg_strerror (err)); + goto leave; + } + + fp = popen (command, "r"); + if (! fp) + { + err = gpg_error_from_errno (errno); + log_error ("error while creating pipe: %s\n", gpg_strerror (err)); + goto leave; + } + + ret = retrieve_key_material (fp, fpr, &m, &mlen, &e, &elen); + fclose (fp); + if (ret) + { + /* FIXME? */ + err = gpg_error (GPG_ERR_INTERNAL); + log_error ("error while retrieving key material through pipe\n"); + goto leave; + } buffer = NULL; - /* FIXME */ + } + err = gcry_sexp_build (&sexp, NULL, + "(public-key (rsa (n %b) (e %b)))", + (int)mlen, m,(int)elen, e); + if (err) + { + log_error ("error formatting the key into an S-expression: %s\n", + gpg_strerror (err)); + goto leave; } + app->app_local->pk[keyno].key = sexp; leave: /* Set a flag to indicate that we tried to read the key. */ -- cgit v1.2.3 From 6ece9a0de94511ce5765edd05f6b9671c0354897 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sat, 9 Apr 2005 16:41:28 +0000 Subject: 2005-04-03 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_request_spec): New member: secret_input. (REQUEST_SPEC_DEFINE): New argument: secret_input. (request_specs): Add secret_input flag. (request_spec_lookup): New function ... (ssh_request_process): ... use it here; depending on secret_input flag allocate secure or non-secure memory. --- agent/ChangeLog | 9 +++ agent/command-ssh.c | 157 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 106 insertions(+), 60 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index c16e0e37a..5a709a5db 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2005-04-03 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_request_spec): New member: secret_input. + (REQUEST_SPEC_DEFINE): New argument: secret_input. + (request_specs): Add secret_input flag. + (request_spec_lookup): New function ... + (ssh_request_process): ... use it here; depending on secret_input + flag allocate secure or non-secure memory. + 2005-03-02 Moritz Schulte <moritz@g10code.com> * command-ssh.c (sexp_key_extract): Removed FIXME, since diff --git a/agent/command-ssh.c b/agent/command-ssh.c index f48df69e4..f9ad2a80e 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -107,6 +107,7 @@ typedef struct ssh_request_spec unsigned char type; ssh_request_handler_t handler; const char *identifier; + unsigned int secret_input; } ssh_request_spec_t; /* Type for "key modifier functions", which are necessary since @@ -160,26 +161,26 @@ typedef struct ssh_key_type_spec /* Prototypes. */ static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_handler_lock (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_handler_unlock (ctrl_t ctrl, - estream_t request, - estream_t response); + estream_t request, + estream_t response); static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis); static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob, @@ -195,19 +196,19 @@ static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob, /* Associating request types with the corresponding request handlers. */ -#define REQUEST_SPEC_DEFINE(id, name) \ - { SSH_REQUEST_##id, ssh_handler_##name, #name } +#define REQUEST_SPEC_DEFINE(id, name, secret_input) \ + { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input } static ssh_request_spec_t request_specs[] = { - REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities), - REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request), - REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity), - REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity), - REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity), - REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities), - REQUEST_SPEC_DEFINE (LOCK, lock), - REQUEST_SPEC_DEFINE (UNLOCK, unlock) + REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities, 1), + REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request, 0), + REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity, 1), + REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity, 1), + REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity, 0), + REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities, 0), + REQUEST_SPEC_DEFINE (LOCK, lock, 0), + REQUEST_SPEC_DEFINE (UNLOCK, unlock, 0) }; #undef REQUEST_SPEC_DEFINE @@ -1733,13 +1734,15 @@ ssh_handler_request_identities (ctrl_t ctrl, gcry_sexp_t key_public; DIR *dir; gpg_error_t err; - gpg_error_t ret_err; int ret; FILE *ctrl_fp = NULL; char *cardsn; + gpg_error_t ret_err; /* Prepare buffer stream. */ + sleep (5); + key_directory = NULL; key_secret = NULL; key_public = NULL; @@ -2460,8 +2463,10 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) gcry_sexp_release (key); - ret_err = stream_write_byte (response, - err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + if (! err) + ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS); + else + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); return ret_err; } @@ -2496,8 +2501,10 @@ ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, xfree (key_blob); gcry_sexp_release (key); - ret_err = stream_write_byte (response, - err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + if (! err) + ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS); + else + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); return ret_err; } @@ -2523,8 +2530,11 @@ ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, gpg_error_t err; err = ssh_identities_remove_all (); - ret_err = stream_write_byte (response, - err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + if (! err) + ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS); + else + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); return ret_err; } @@ -2559,8 +2569,11 @@ ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) gpg_error_t err; err = ssh_lock (); - ret_err = stream_write_byte (response, - err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + if (! err) + ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS); + else + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); return ret_err; } @@ -2572,22 +2585,45 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) gpg_error_t err; err = ssh_unlock (); - ret_err = stream_write_byte (response, - err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS); + + if (! err) + ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS); + else + ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE); return ret_err; } +static ssh_request_spec_t * +request_spec_lookup (int type) +{ + ssh_request_spec_t *spec; + unsigned int i; + + for (i = 0; i < DIM (request_specs); i++) + if (request_specs[i].type == type) + break; + if (i == DIM (request_specs)) + { + log_info ("ssh request %u is not supported\n", type); + spec = NULL; + } + else + spec = request_specs + i; + + return spec; +} + static int ssh_request_process (ctrl_t ctrl, estream_t stream_sock) { + ssh_request_spec_t *spec; estream_t response; estream_t request; unsigned char request_type; gpg_error_t err; - unsigned int i; int send_err; int ret; unsigned char *request_data; @@ -2617,7 +2653,26 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) log_info ("received ssh request of length %u\n", (unsigned int)request_data_size); - request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); + if (! request_data_size) + { + send_err = 1; + goto out; + /* Broken request; FIXME. */ + } + + request_type = request_data[0]; + spec = request_spec_lookup (request_type); + if (! spec) + { + send_err = 1; + goto out; + /* Unknown request; FIXME. */ + } + + if (spec->secret_input) + request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+"); + else + request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+"); if (! request) { err = gpg_error_from_errno (errno); @@ -2629,7 +2684,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) err = gpg_error_from_errno (errno); goto out; } - err = stream_write_data (request, request_data, request_data_size); + err = stream_write_data (request, request_data + 1, request_data_size - 1); if (err) goto out; es_rewind (request); @@ -2641,38 +2696,20 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) goto out; } - err = stream_read_byte (request, &request_type); - if (err) - { - send_err = 1; - goto out; - } - - for (i = 0; i < DIM (request_specs); i++) - if (request_specs[i].type == request_type) - break; - if (i == DIM (request_specs)) - { - log_info ("ssh request %u is not supported\n", request_type); - send_err = 1; - goto out; - } - if (opt.verbose) log_info ("ssh request handler for %s (%u) started\n", - request_specs[i].identifier, request_specs[i].type); + spec->identifier, spec->type); - err = (*request_specs[i].handler) (ctrl, request, response); + err = (*spec->handler) (ctrl, request, response); if (opt.verbose) { if (err) log_info ("ssh request handler for %s (%u) failed: %s\n", - request_specs[i].identifier, request_specs[i].type, - gpg_strerror (err)); + spec->identifier, spec->type, gpg_strerror (err)); else log_info ("ssh request handler for %s (%u) ready\n", - request_specs[i].identifier, request_specs[i].type); + spec->identifier, spec->type); } if (err) -- cgit v1.2.3 From c5b1095b6d8af68e40883ebc28c30407ddb7140e Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sun, 10 Apr 2005 22:12:31 +0000 Subject: 2005-04-11 Marcus Brinkmann <marcus@g10code.de> * simple-pwquery.c (simple_pwquery): Use spwq_secure_free. --- common/ChangeLog | 4 ++++ common/simple-pwquery.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index e9bb42a57..f5c5c0982 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2005-04-11 Marcus Brinkmann <marcus@g10code.de> + + * simple-pwquery.c (simple_pwquery): Use spwq_secure_free. + 2005-03-03 Werner Koch <wk@g10code.com> * Makefile.am (AM_CFLAGS): Added PTH_CFLAGS. Noted by Kazu Yamamoto. diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 37a45816c..8a027e799 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -541,7 +541,7 @@ simple_pwquery (const char *cacheid, if (fd != -1) close (fd); if (pw) - spwq_free (pw); + spwq_secure_free (pw); return result; } -- cgit v1.2.3 From 57ee0148635b1315f8d45d1e51230b5cf532e036 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sun, 10 Apr 2005 23:10:52 +0000 Subject: 2005-04-11 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (bin_PROGRAMS): Add symcryptrun. (symcryptrun_SOURCES, symcryptrun_LDADD): New variables. * symcryptrun.c: New file. --- tools/ChangeLog | 6 + tools/Makefile.am | 7 +- tools/symcryptrun.c | 848 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 860 insertions(+), 1 deletion(-) create mode 100644 tools/symcryptrun.c diff --git a/tools/ChangeLog b/tools/ChangeLog index e39dd3b04..aabdedd58 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2005-04-11 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (bin_PROGRAMS): Add symcryptrun. + (symcryptrun_SOURCES, symcryptrun_LDADD): New variables. + * symcryptrun.c: New file. + 2005-03-09 Werner Koch <wk@g10code.com> * gpgconf-comp.c <dirmngr>: Add honor-http-proxy. diff --git a/tools/Makefile.am b/tools/Makefile.am index 5a56d65ce..2616d69a9 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -30,7 +30,7 @@ sbin_SCRIPTS = addgnupghome bin_SCRIPTS = gpgsm-gencert.sh -bin_PROGRAMS = gpgconf gpg-connect-agent +bin_PROGRAMS = gpgconf gpg-connect-agent symcryptrun if !HAVE_W32_SYSTEM bin_PROGRAMS += watchgnupg endif @@ -39,6 +39,11 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @LIBINTL@ +symcryptrun_SOURCES = symcryptrun.c +symcryptrun_LDADD = -lutil ../jnlib/libjnlib.a ../common/libcommon.a \ + ../common/libsimple-pwquery.a $(LIBGCRYPT_LIBS) \ + $(GPG_ERROR_LIBS) $(LIBINTL) + watchgnupg_SOURCES = watchgnupg.c gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c new file mode 100644 index 000000000..9c8fb7052 --- /dev/null +++ b/tools/symcryptrun.c @@ -0,0 +1,848 @@ +/* symcryptrun.c - Tool to call simple symmetric encryption tools. + * Copyright (C) 2005 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 + */ + + +/* Sometimes simple encryption tools are already in use for a long + time and there is a desire to integrate them into the GnuPG + framework. The protocols and encryption methods might be + non-standard or not even properly documented, so that a + full-fledged encryption tool with an interface like gpg is not + doable. This simple wrapper program provides a solution: It + operates by calling the encryption/decryption module and providing + the passphrase for a key (or even the key directly) using the + standard pinentry mechanism through gpg-agent. */ + +/* This program is invoked in the following way: + + symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE \ + [--decrypt | --encrypt] + + For encryption, the plain text must be provided on STDIN, and the + ciphertext will be output to STDOUT. For decryption vice versa. + + CLASS can currently only be "confucius". + + PROGRAM must be the path to the crypto engine. + + KEYFILE must contain the secret key, which may be protected by a + passphrase. The passphrase is retrieved via the pinentry program. + + + The GPG Agent _must_ be running before starting symcryptrun. + + The possible exit status codes: + + 0 Success + 1 Some error occured + 2 No valid passphrase was provided + 3 The operation was canceled by the user + + Other classes may be added in the future. */ + + +#include <config.h> + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <pty.h> +#include <utmp.h> +#include <ctype.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif +#include <gpg-error.h> + +#define JNLIB_NEED_LOG_LOGV +#include "i18n.h" +#include "../common/util.h" + +/* FIXME: Bah. For spwq_secure_free. */ +#define SIMPLE_PWQUERY_IMPLEMENTATION 1 +#include "../common/simple-pwquery.h" + + +/* Used by gcry for logging */ +static void +my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) +{ + /* translate the log levels */ + switch (level) + { + case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; + case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; + case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; + case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; + case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; + case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; + case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; + default: level = JNLIB_LOG_ERROR; break; } + log_logv (level, fmt, arg_ptr); +} + + +/* Constants to identify the commands and options. */ +enum cmd_and_opt_values + { + aNull = 0, + oQuiet = 'q', + oVerbose = 'v', + + oNoVerbose = 500, + oLogFile, + oHomedir, + oClass, + oProgram, + oKeyfile, + oDecrypt, + oEncrypt, + }; + + +/* The list of commands and options. */ +static ARGPARSE_OPTS opts[] = + { + { 301, NULL, 0, N_("@\nCommands:\n ") }, + + { oDecrypt, "decrypt", 0, N_("decryption modus")}, + { oEncrypt, "encrypt", 0, N_("encryption modus")}, + + { 302, NULL, 0, N_("@\nOptions:\n ") }, + + { oClass, "class", 2, N_("tool class (confucius)")}, + { oProgram, "program", 2, N_("program filename")}, + + { oKeyfile, "keyfile", 2, N_("secret key file (required)")}, + + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("quiet") }, + { oLogFile, "log-file", 2, N_("use a log file for the server")}, + + /* Hidden options. */ + { oNoVerbose, "no-verbose", 0, "@"}, + { oHomedir, "homedir", 2, "@" }, + + {0} + }; + + +/* We keep all global options in the structure OPT. */ +struct +{ + int verbose; /* Verbosity level. */ + int quiet; /* Be extra quiet. */ + const char *homedir; /* Configuration directory name */ + + char *class; + char *program; + char *keyfile; +} opt; + + +/* Print usage information and and provide strings for help. */ +static const char * +my_strusage (int level) +{ + const char *p; + + switch (level) + { + case 11: p = "symcryptrun (GnuPG)"; + break; + case 13: p = VERSION; break; + case 17: p = PRINTABLE_OS_NAME; break; + case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); + break; + case 1: + case 40: p = _("Usage: symcryptrun [options] (-h for help)"); + break; + case 41: + p = _("Syntax: symcryptrun --class CLASS --program PROGRAM " + "--keyfile KEYFILE [options...] COMMAND\n" + "Call a simple symmetric encryption tool\n"); + break; + case 31: p = "\nHome: "; break; + case 32: p = opt.homedir; break; + case 33: p = "\n"; break; + + default: p = NULL; break; + } + return p; +} + + +/* Initialize the gettext system. */ +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file (PACKAGE_GT); +#else +# ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); +# endif +#endif +} + + +/* Class Confucius. + + "Don't worry that other people don't know you; + worry that you don't know other people." Analects--1.16. */ + +/* Create temporary directory with mode 0700. Returns a dynamically + allocated string with the filename of the directory. */ +static char * +confucius_mktmpdir (void) +{ + int res; + char *tmpdir; + + tmpdir = tmpnam (NULL); + if (!tmpdir) + { + log_error (_("cannot create temporary directory name: %s\n"), + strerror (errno)); + return NULL; + } + tmpdir = strdup (tmpdir); + if (!tmpdir) + { + log_error (_("cannot copy temporary directory name: %s\n"), + strerror (errno)); + return NULL; + } + res = mkdir (tmpdir, 0700); + if (res < 0) + { + log_error (_("cannot create temporary directory %s: %s\n"), + tmpdir, strerror (errno)); + return NULL; + } + + return tmpdir; +} + + +/* Buffer size for I/O operations. */ +#define CONFUCIUS_BUFSIZE 4096 + +/* Buffer size for output lines. */ +#define CONFUCIUS_LINESIZE 4096 + + +/* Copy the file IN to OUT, either of which may be "-". */ +static int +confucius_copy_file (const char *infile, const char *outfile) +{ + FILE *in; + int in_is_stdin = 0; + FILE *out; + int out_is_stdout = 0; + char data[CONFUCIUS_BUFSIZE]; + ssize_t data_len; + + if (infile[0] == '-' && infile[1] == '\0') + { + /* FIXME: Is stdin in binary mode? */ + in = stdin; + in_is_stdin = 1; + } + else + { + in = fopen (infile, "rb"); + if (!in) + { + log_error (_("could not open %s for writing: %s\n"), + infile, strerror (errno)); + return 1; + } + } + + if (outfile[0] == '-' && outfile[1] == '\0') + { + /* FIXME: Is stdout in binary mode? */ + out = stdout; + out_is_stdout = 1; + } + else + { + out = fopen (outfile, "wb"); + if (!out) + { + log_error (_("could not open %s for writing: %s\n"), + infile, strerror (errno)); + return 1; + } + } + + /* Now copy the data. */ + while ((data_len = fread (data, 1, sizeof (data), in)) > 0) + { + if (fwrite (data, 1, data_len, out) != data_len) + { + log_error (_("error writing to %s: %s\n"), outfile, + strerror (errno)); + goto copy_err; + } + } + if (data_len < 0 || ferror (in)) + { + log_error (_("error reading from %s: %s\n"), infile, strerror (errno)); + goto copy_err; + } + + /* Close IN if appropriate. */ + if (!in_is_stdin && fclose (in) && ferror (in)) + { + log_error (_("error closing %s: %s\n"), infile, strerror (errno)); + goto copy_err; + } + + /* Close OUT if appropriate. */ + if (!out_is_stdout && fclose (out) && ferror (out)) + { + log_error (_("error closing %s: %s\n"), infile, strerror (errno)); + goto copy_err; + } + + return 0; + + copy_err: + if (!out_is_stdout) + unlink (outfile); + return 1; +} + + +/* Get a passphrase in secure storage (if possible). If AGAIN is + true, then this is a repeated attempt. If CANCELED is not a null + pointer, it will be set to true or false, depending on if the user + canceled the operation or not. On error (including cancelation), a + null pointer is returned. The passphrase must be deallocated with + confucius_drop_pass. */ +char * +confucius_get_pass (int again, int *canceled) +{ + int err; + char *pw; +#ifdef HAVE_LANGINFO_CODESET + char *orig_codeset = NULL; +#endif + + if (canceled) + *canceled = 0; + +#ifdef ENABLE_NLS + /* The Assuan agent protocol requires us to transmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset && !strcmp (orig_codeset, "UTF-8")) + orig_codeset = NULL; + if (orig_codeset) + { + /* We only switch when we are able to restore the codeset later. */ + orig_codeset = xstrdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) + orig_codeset = NULL; + } +#endif + + pw = simple_pwquery (NULL, + again ? _("does not match - try again"):NULL, + _("Passphrase:"), NULL, &err); + +#ifdef ENABLE_NLS + if (orig_codeset) + { + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); + xfree (orig_codeset); + } +#endif + + if (!pw) + { + if (err) + log_error (_("error while asking for the passphrase: %s\n"), + gpg_strerror (err)); + else + { + log_info (_("cancelled\n")); + if (canceled) + *canceled = 1; + } + } + + return pw; +} + + +/* Drop a passphrase retrieved with confucius_get_pass. */ +void +confucius_drop_pass (char *pass) +{ + if (pass) + spwq_secure_free (pass); +} + + +/* Run a confucius crypto engine. If MODE is oEncrypt, encryption is + requested. If it is oDecrypt, decryption is requested. INFILE and + OUTFILE are the temporary files used in the process. */ +int +confucius_process (int mode, char *infile, char *outfile) +{ + char *const args[] = { opt.program, + mode == oEncrypt ? "-m1" : "-m2", + "-q", infile, + "-z", outfile, + "-s", opt.keyfile, + mode == oEncrypt ? "-af" : "-f", + NULL }; + int cstderr[2]; + int master; + int slave; + int res; + pid_t pid; + pid_t wpid; + int tries = 0; + + signal (SIGPIPE, SIG_IGN); + + if (!opt.program) + { + log_error (_("no --program option provided\n")); + return 1; + } + + if (mode != oDecrypt && mode != oEncrypt) + { + log_error (_("only --decrypt and --encrypt are supported\n")); + return 1; + } + + if (!opt.keyfile) + { + log_error (_("no --keyfile option provided\n")); + return 1; + } + + if (pipe (cstderr) < 0) + { + log_error (_("could not create pipe: %s\n"), strerror (errno)); + return 1; + } + + if (openpty (&master, &slave, NULL, NULL, NULL) == -1) + { + log_error (_("could not create pty: %s\n"), strerror (errno)); + close (cstderr[0]); + close (cstderr[1]); + return -1; + } + + /* We don't want to deal with the worst case scenarios. */ + assert (master > 2); + assert (slave > 2); + assert (cstderr[0] > 2); + assert (cstderr[1] > 2); + + pid = fork (); + if (pid < 0) + { + log_error (_("could not fork: %s\n"), strerror (errno)); + close (master); + close (slave); + close (cstderr[0]); + close (cstderr[1]); + return 1; + } + else if (pid == 0) + { + /* Child. */ + + /* Close the parent ends. */ + close (master); + close (cstderr[0]); + + /* Change controlling terminal. */ + if (login_tty (slave)) + { + /* It's too early to output a debug message. */ + _exit (1); + } + + dup2 (cstderr[1], 2); + close (cstderr[1]); + + /* Now kick off the engine program. */ + execv (opt.program, args); + log_error (_("execv failed: %s\n"), strerror (errno)); + _exit (1); + } + else + { + /* Parent. */ + char buffer[CONFUCIUS_LINESIZE]; + int buffer_len = 0; + fd_set fds; + int slave_closed = 0; + int stderr_closed = 0; + + close (slave); + close (cstderr[1]); + + /* Listen on the output FDs. */ + do + { + FD_ZERO (&fds); + + if (!slave_closed) + FD_SET (master, &fds); + if (!stderr_closed) + FD_SET (cstderr[0], &fds); + + res = select (FD_SETSIZE, &fds, NULL, NULL, NULL); + if (res < 0) + { + log_error (_("select failed: %s\n"), strerror (errno)); + + kill (pid, SIGTERM); + close (master); + close (cstderr[0]); + return 1; + } + + if (FD_ISSET (cstderr[0], &fds)) + { + /* We got some output on stderr. This is just passed + through via the logging facility. */ + + res = read (cstderr[0], &buffer[buffer_len], + sizeof (buffer) - buffer_len - 1); + if (res < 0) + { + log_error (_("read failed: %s\n"), strerror (errno)); + + kill (pid, SIGTERM); + close (master); + close (cstderr[0]); + return 1; + } + else + { + char *newline; + + buffer_len += res; + for (;;) + { + buffer[buffer_len] = '\0'; + newline = strchr (buffer, '\n'); + if (newline) + { + *newline = '\0'; + log_error ("%s\n", buffer); + buffer_len -= newline + 1 - buffer; + memmove (buffer, newline + 1, buffer_len); + } + else if (buffer_len == sizeof (buffer) - 1) + { + /* Overflow. */ + log_error ("%s\n", buffer); + buffer_len = 0; + } + else + break; + } + + if (res == 0) + stderr_closed = 1; + } + } + else if (FD_ISSET (master, &fds)) + { + char data[512]; + + res = read (master, data, sizeof (data)); + if (res < 0) + { + if (errno == EIO) + { + /* Slave-side close leads to readable fd and + EIO. */ + slave_closed = 1; + } + else + { + log_error (_("pty read failed: %s\n"), strerror (errno)); + + kill (pid, SIGTERM); + close (master); + close (cstderr[0]); + return 1; + } + } + else if (res == 0) + /* This never seems to be what happens on slave-side + close. */ + slave_closed = 1; + else + { + /* Check for password prompt. */ + if (data[res - 1] == ':') + { + char *pass; + int canceled; + + pass = confucius_get_pass (tries ? 1 : 0, &canceled); + if (!pass) + { + kill (pid, SIGTERM); + close (master); + close (cstderr[0]); + return canceled ? 3 : 1; + } + write (master, pass, strlen (pass)); + write (master, "\n", 1); + confucius_drop_pass (pass); + + tries++; + } + } + } + } + while (!stderr_closed || !slave_closed); + + close (master); + close (cstderr[0]); + + wpid = waitpid (pid, &res, 0); + if (wpid < 0) + { + log_error (_("waitpid failed: %s\n"), strerror (errno)); + + kill (pid, SIGTERM); + return 1; + } + else + { + /* Shouldn't happen, as we don't use WNOHANG. */ + assert (wpid != 0); + + if (!WIFEXITED (res)) + { + log_error (_("child aborted with status %i\n"), res); + return 1; + } + + if (WEXITSTATUS (res)) + { + /* We probably exceeded our number of attempts at guessing + the password. */ + if (tries >= 3) + return 2; + else + return 1; + } + + return 0; + } + } + + /* Not reached. */ +} + + +/* Class confucius main program. If MODE is oEncrypt, encryption is + requested. If it is oDecrypt, decryption is requested. The other + parameters are taken from the global option data. */ +int +confucius_main (int mode) +{ + int res; + char *tmpdir; + char *infile; + char *outfile; + + tmpdir = confucius_mktmpdir (); + if (!tmpdir) + return 1; + + /* TMPDIR + "/" + "in" + "\0". */ + infile = malloc (strlen (tmpdir) + 1 + 2 + 1); + if (!infile) + { + log_error (_("cannot allocate infile string: %s\n"), strerror (errno)); + rmdir (tmpdir); + return 1; + } + strcpy (infile, tmpdir); + strcat (infile, "/in"); + + /* TMPDIR + "/" + "out" + "\0". */ + outfile = malloc (strlen (tmpdir) + 1 + 3 + 1); + if (!outfile) + { + log_error (_("cannot allocate outfile string: %s\n"), strerror (errno)); + free (infile); + rmdir (tmpdir); + return 1; + } + strcpy (outfile, tmpdir); + strcat (outfile, "/out"); + + /* Create INFILE and fill it with content. */ + res = confucius_copy_file ("-", infile); + if (res) + { + free (outfile); + free (infile); + rmdir (tmpdir); + return res; + } + + /* Run the engine and thus create the output file, handling + passphrase retrieval. */ + res = confucius_process (mode, infile, outfile); + if (res) + { + unlink (outfile); + unlink (infile); + free (outfile); + free (infile); + rmdir (tmpdir); + return res; + } + + /* Dump the output file to stdout. */ + res = confucius_copy_file (outfile, "-"); + if (res) + { + unlink (outfile); + unlink (infile); + free (outfile); + free (infile); + rmdir (tmpdir); + return res; + } + + unlink (outfile); + unlink (infile); + free (outfile); + free (infile); + rmdir (tmpdir); + return 0; +} + + +/* symcryptrun's entry point. */ +int +main (int argc, char **argv) +{ + ARGPARSE_ARGS pargs; + int no_more_options = 0; + int mode = 0; + int res; + char *logfile = NULL; + + set_strusage (my_strusage); + log_set_prefix ("symcryptrun", 1); + + /* Try to auto set the character set. */ + set_native_charset (NULL); + + i18n_init(); + + opt.homedir = default_homedir (); + + /* Parse the command line. */ + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags = 1; /* Do not remove the args. */ + while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts)) + { + switch (pargs.r_opt) + { + case oDecrypt: mode = oDecrypt; break; + case oEncrypt: mode = oEncrypt; break; + + case oQuiet: opt.quiet = 1; break; + case oVerbose: opt.verbose++; break; + case oNoVerbose: opt.verbose = 0; break; + case oHomedir: opt.homedir = pargs.r.ret_str; break; + + case oClass: opt.class = pargs.r.ret_str; break; + case oProgram: opt.program = pargs.r.ret_str; break; + case oKeyfile: opt.keyfile = pargs.r.ret_str; break; + + case oLogFile: logfile = pargs.r.ret_str; break; + + default: pargs.err = 2; break; + } + } + + if (!mode) + log_error (_("either %s or %s must be given\n"), + "--decrypt", "--encrypt"); + + if (log_get_errorcount (0)) + exit (1); + + if (logfile) + log_set_file (logfile); + + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + gcry_set_log_handler (my_gcry_logger, NULL); + gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); + + if (!opt.class) + { + log_error (_("no class provided\n")); + res = 1; + } + else if (!strcmp (opt.class, "confucius")) + res = confucius_main (mode); + else + { + log_error (_("class %s is not supported\n"), opt.class); + res = 1; + } + + return res; +} -- cgit v1.2.3 From cf502487fca3e7f354dc727c7d20ae87a3644b0c Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sun, 10 Apr 2005 23:54:39 +0000 Subject: 2005-04-11 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c: Implement config file parsing. --- tools/ChangeLog | 2 ++ tools/symcryptrun.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index aabdedd58..aa1151290 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,7 @@ 2005-04-11 Marcus Brinkmann <marcus@g10code.de> + * symcryptrun.c: Implement config file parsing. + * Makefile.am (bin_PROGRAMS): Add symcryptrun. (symcryptrun_SOURCES, symcryptrun_LDADD): New variables. * symcryptrun.c: New file. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 9c8fb7052..d0a8bddb9 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -115,6 +115,8 @@ enum cmd_and_opt_values oVerbose = 'v', oNoVerbose = 500, + oOptions, + oNoOptions, oLogFile, oHomedir, oClass, @@ -143,10 +145,12 @@ static ARGPARSE_OPTS opts[] = { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("quiet") }, { oLogFile, "log-file", 2, N_("use a log file for the server")}, + { oOptions, "options" , 2, N_("|FILE|read options from FILE")}, /* Hidden options. */ { oNoVerbose, "no-verbose", 0, "@"}, { oHomedir, "homedir", 2, "@" }, + { oNoOptions, "no-options", 0, "@" },/* shortcut for --options /dev/null */ {0} }; @@ -771,10 +775,15 @@ int main (int argc, char **argv) { ARGPARSE_ARGS pargs; - int no_more_options = 0; + int orig_argc; + char **orig_argv; + FILE *configfp = NULL; + char *configname = NULL; + unsigned configlineno; int mode = 0; int res; char *logfile = NULL; + int default_config = 1; set_strusage (my_strusage); log_set_prefix ("symcryptrun", 1); @@ -786,11 +795,55 @@ main (int argc, char **argv) opt.homedir = default_homedir (); + /* Check whether we have a config file given on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ + while (arg_parse( &pargs, opts)) + { + if (pargs.r_opt == oOptions) + { /* Yes there is one, so we do not try the default one, but + read the option file when it is encountered at the + commandline */ + default_config = 0; + } + else if (pargs.r_opt == oNoOptions) + default_config = 0; /* --no-options */ + else if (pargs.r_opt == oHomedir) + opt.homedir = pargs.r.ret_str; + } + + if (default_config) + configname = make_filename (opt.homedir, "symcryptrun.conf", NULL ); + + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + next_pass: + if (configname) + { + configlineno = 0; + configfp = fopen (configname, "r"); + if (!configfp) + { + if (!default_config) + { + log_error (_("option file `%s': %s\n"), + configname, strerror(errno) ); + exit(1); + } + xfree (configname); + configname = NULL; + } + default_config = 0; + } + /* Parse the command line. */ - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags = 1; /* Do not remove the args. */ - while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts)) + while (optfile_parse (configfp, configname, &configlineno, &pargs, opts)) { switch (pargs.r_opt) { @@ -800,7 +853,6 @@ main (int argc, char **argv) case oQuiet: opt.quiet = 1; break; case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; - case oHomedir: opt.homedir = pargs.r.ret_str; break; case oClass: opt.class = pargs.r.ret_str; break; case oProgram: opt.program = pargs.r.ret_str; break; @@ -808,9 +860,30 @@ main (int argc, char **argv) case oLogFile: logfile = pargs.r.ret_str; break; - default: pargs.err = 2; break; + case oOptions: + /* Config files may not be nested (silently ignore them) */ + if (!configfp) + { + xfree(configname); + configname = xstrdup(pargs.r.ret_str); + goto next_pass; + } + break; + case oNoOptions: break; /* no-options */ + case oHomedir: /* Ignore this option here. */; break; + + default : pargs.err = configfp? 1:2; break; } } + if (configfp) + { + fclose( configfp ); + configfp = NULL; + configname = NULL; + goto next_pass; + } + xfree (configname); + configname = NULL; if (!mode) log_error (_("either %s or %s must be given\n"), -- cgit v1.2.3 From 1c88f744d615f057bdf5b1142a51645851176c53 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 11 Apr 2005 16:09:18 +0000 Subject: typo fixes --- agent/call-scd.c | 2 +- agent/divert-scd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/call-scd.c b/agent/call-scd.c index 904059291..4d1498b05 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -87,7 +87,7 @@ struct inq_needpin_s { /* This function must be called once to initialize this module. This has to be done before a second thread is spawned. We can't do the static initialization because Pth emulation code might not be able - to do a static init; in particualr, it is not possible for W32. */ + to do a static init; in particular, it is not possible for W32. */ void initialize_module_call_scd (void) { diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 72cf338fe..f2ec2f051 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -112,7 +112,7 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) because the scdaemon is currently not always able to detect the presence of a card. With a fully working scdaemon this would not be required; i.e. the pkcs#15 - support does not require it becuase OpenSC correclty + support does not require it because OpenSC correclty detects a present card. */ agent_reset_scd (ctrl); if (asprintf (&desc, -- cgit v1.2.3 From 45eba6e5de56d963fd47ef0d620055fd4088d671 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 11 Apr 2005 16:10:03 +0000 Subject: * sexputil.c: New. --- common/ChangeLog | 6 +++++- common/Makefile.am | 1 + common/util.h | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index f5c5c0982..a42b07b4d 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2005-04-07 Werner Koch <wk@g10code.com> + + * sexputil.c: New. + 2005-04-11 Marcus Brinkmann <marcus@g10code.de> * simple-pwquery.c (simple_pwquery): Use spwq_secure_free. @@ -442,7 +446,7 @@ (atoi_1,atoi_2,atoi_4,xtoi_1,xtoi_2): New. - Copyright 2001, 2002 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004, 2005 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 diff --git a/common/Makefile.am b/common/Makefile.am index ed7659793..a039be184 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -27,6 +27,7 @@ libcommon_a_SOURCES = \ util.h i18n.h \ errors.h \ sexp-parse.h \ + sexputil.c \ maperror.c \ sysutils.c sysutils.h \ homedir.c \ diff --git a/common/util.h b/common/util.h index bbf7241a3..14180bec4 100644 --- a/common/util.h +++ b/common/util.h @@ -120,6 +120,9 @@ gpg_error_t b64enc_write (struct b64state *state, const void *buffer, size_t nbytes); gpg_error_t b64enc_finish (struct b64state *state); +/*-- sexputil.c */ +gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, + unsigned char *grip); /*-- homedir. c --*/ const char *default_homedir (void); -- cgit v1.2.3 From 6b002f06026b5555aabb84c194e3f4aa1f8692b2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 11 Apr 2005 16:20:10 +0000 Subject: * app-openpgp.c (do_check_pin): Add hack to allow verification of CHV3. (get_public_key): Don't use gcry functions to create S-expressions. (do_deinit, do_readkey, do_genkey, send_keypair_info): Adjust for above change. --- scd/ChangeLog | 30 ++++++++++++ scd/app-openpgp.c | 144 +++++++++++++++++++++++++++++++++++++----------------- scd/app.c | 2 +- scd/ccid-driver.c | 89 +++++++++++++++++++++++---------- scd/command.c | 66 ++++++++++++++++++------- 5 files changed, 241 insertions(+), 90 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index ca7358406..f8f8043c1 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,11 @@ +2005-04-07 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_check_pin): Add hack to allow verification of + CHV3. + (get_public_key): Don't use gcry functions to create S-expressions. + (do_deinit, do_readkey, do_genkey, send_keypair_info): Adjust for + above change. + 2005-03-29 Moritz Schulte <moritz@g10code.com> * app-openpgp.c (retrieve_fpr_from_card): New function. @@ -6,6 +14,19 @@ (get_public_key): Implement retrival of key through expernal helper (gpg) in case the openpgp card is not cooperative enough. +2005-03-16 Werner Koch <wk@g10code.com> + + * ccid-driver.c (parse_ccid_descriptor): Make SCM workaround + reader type specific. + (scan_or_find_devices): Do not check the interface subclass in the + SPR532 kludge, as this depends on the firmware version. + (ccid_get_atr): Get the Slot status first. This solves the + problem with readers hanging on recent Linux 2.6.x. + (bulk_in): Add argument TIMEOUT and changed all callers to pass an + appropriate one. Change the standard timeout from 10 to 5 seconds. + (ccid_slot_status): Add a retry code with an initial short timeout. + (do_close_reader): Do an usb_reset before closing the reader. + 2005-02-25 Werner Koch <wk@g10code.com> * app-openpgp.c (get_public_key): Make sure not to return negative @@ -42,6 +63,15 @@ (reset_pcsc_reader, pcsc_get_status, pcsc_send_apdu) (open_pcsc_reader): Do proper error code mapping. +2005-03-16 Werner Koch <wk@g10code.com> + + * ccid-driver.c (parse_ccid_descriptor): Make SCM workaround + reader type specific. + (scan_or_find_devices): Do not check the interface subclass in the + SPR532 kludge, as this depends on the firmware version. + (ccid_get_atr): Get the Slot status first. This solves the + problem with readers hanging on recent Linux 2.6.x. + 2005-02-22 Werner Koch <wk@g10code.com> * app-openpgp.c (app_local_s): New field PK. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index bae9dde49..1ed057195 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -108,7 +108,14 @@ struct app_local_s { struct { int read_done; /* True if we have at least tried to read them. */ - gcry_sexp_t key; /* Might be NULL if key is not available. */ + unsigned char *key; /* This is a malloced buffer with a canonical + encoded S-expression encoding a public + key. Might be NULL if key is not + available. */ + size_t keylen; /* The length of the above S-expression. Thsi + is usullay only required for corss checks + because the length of an S-expression is + implicitly available. */ } pk[3]; /* Keep track of card capabilities. */ @@ -156,7 +163,7 @@ do_deinit (app_t app) for (i=0; i < DIM (app->app_local->pk); i++) { - gcry_sexp_release (app->app_local->pk[i].key); + xfree (app->app_local->pk[i].key); app->app_local->pk[i].read_done = 0; } xfree (app->app_local); @@ -864,6 +871,10 @@ retrieve_key_material (FILE *fp, const char *fpr, mpi = NULL; ret = 0; +#warning This part should get rewritten for clarity + /* We should use an algorithm similar to the one used by gpgme. + This will reduce the size of the code at least by 50%. [wk] */ + while (1) { /* FIXME? */ @@ -1041,7 +1052,9 @@ retrieve_key_material (FILE *fp, const char *fpr, presence of the app->app_local->pk[KEYNO-1].key field. Note that GnuPG 1.x does not need this and it would be too time - consuming to send it just for the fun of it. */ + consuming to send it just for the fun of it. However, given that we + use the same code in gpg 1.4, we can't use the gcry S-expresion + here but need to open encode it. */ #if GNUPG_MAJOR_VERSION > 1 static gpg_error_t get_public_key (app_t app, int keyno) @@ -1050,9 +1063,10 @@ get_public_key (app_t app, int keyno) unsigned char *buffer; const unsigned char *keydata, *m, *e; size_t buflen, keydatalen, mlen, elen; - gcry_sexp_t sexp; unsigned char *mbuf = NULL; unsigned char *ebuf = NULL; + unsigned char *keybuf = NULL; + unsigned char *keybuf_p; if (keyno < 1 || keyno > 3) return gpg_error (GPG_ERR_INV_ID); @@ -1062,8 +1076,9 @@ get_public_key (app_t app, int keyno) if (app->app_local->pk[keyno].read_done) return 0; - gcry_sexp_release (app->app_local->pk[keyno].key); + xfree (app->app_local->pk[keyno].key); app->app_local->pk[keyno].key = NULL; + app->app_local->pk[keyno].keylen = 0; if (app->card_version > 0x0100) { @@ -1191,16 +1206,29 @@ get_public_key (app_t app, int keyno) buffer = NULL; } - err = gcry_sexp_build (&sexp, NULL, - "(public-key (rsa (n %b) (e %b)))", - (int)mlen, m,(int)elen, e); - if (err) + /* Allocate a buffer to construct the S-expression. */ + /* FIXME: We should provide a generalized S-expression creation + mechanism. */ + keybuf = xtrymalloc (50 + 2*35 + mlen + elen + 1); + if (!keybuf) { - log_error ("error formatting the key into an S-expression: %s\n", - gpg_strerror (err)); + err = gpg_error_from_errno (errno); goto leave; } - app->app_local->pk[keyno].key = sexp; + + sprintf (keybuf, "(10:public-key(3:rsa(1:n%u", (unsigned int) mlen); + keybuf_p = keybuf + strlen (keybuf); + memcpy (keybuf_p, m, mlen); + keybuf_p += mlen; + sprintf (keybuf_p, ")(1:e%u", (unsigned int)elen); + keybuf_p += strlen (keybuf_p); + memcpy (keybuf_p, e, elen); + keybuf_p += elen; + strcpy (keybuf_p, ")))"); + keybuf_p += strlen (keybuf_p); + + app->app_local->pk[keyno].key = keybuf; + app->app_local->pk[keyno].keylen = (keybuf_p - keybuf); leave: /* Set a flag to indicate that we tried to read the key. */ @@ -1224,7 +1252,6 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno) /* Note that GnuPG 1.x does not need this and it would be too time consuming to send it just for the fun of it. */ #if GNUPG_MAJOR_VERSION > 1 - gcry_sexp_t sexp; unsigned char grip[20]; char gripstr[41]; char idbuf[50]; @@ -1235,15 +1262,14 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno) goto leave; assert (keyno >= 1 && keyno <= 3); - sexp = app->app_local->pk[keyno-1].key; - if (!sexp) - goto leave; /* No such key. */ + if (!app->app_local->pk[keyno-1].key) + goto leave; /* No such key - ignore. */ - if (!gcry_pk_get_keygrip (sexp, grip)) - { - err = gpg_error (GPG_ERR_INTERNAL); - goto leave; - } + err = keygrip_from_canon_sexp (app->app_local->pk[keyno-1].key, + app->app_local->pk[keyno-1].keylen, + grip); + if (err) + goto leave; for (i=0; i < 20; i++) sprintf (gripstr+i*2, "%02X", grip[i]); @@ -1303,9 +1329,7 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) { gpg_error_t err; int keyno; - size_t n; unsigned char *buf; - gcry_sexp_t sexp; if (!strcmp (keyid, "OPENPGP.1")) keyno = 1; @@ -1320,24 +1344,11 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) if (err) return err; - sexp = app->app_local->pk[keyno-1].key; - if (!sexp) - return gpg_error (GPG_ERR_NO_PUBKEY); - - n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0); - if (!n) - return gpg_error (GPG_ERR_BUG); - buf = xtrymalloc (n); + buf = app->app_local->pk[keyno-1].key; if (!buf) - return gpg_error_from_errno (errno); - n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, n); - if (!n) - { - xfree (buf); - return gpg_error (GPG_ERR_BUG); - } + return gpg_error (GPG_ERR_NO_PUBKEY); *pk = buf; - *pklen = n; + *pklen = app->app_local->pk[keyno-1].keylen;; return 0; } @@ -1590,7 +1601,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, else app->did_chv1 = app->did_chv2 = 0; - /* Note to translators: Do not translate the "|*|" prefixes but + /* TRANSLATORS: Do not translate the "|*|" prefixes but keep it at the start of the string. We need this elsewhere to get some infos on the string. */ rc = pincb (pincb_arg, chvno == 3? _("|AN|New Admin PIN") : _("|N|New PIN"), @@ -1661,7 +1672,9 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, flush_cache (app); /* Obviously we need to remove the cached public key. */ - gcry_sexp_release (app->app_local->pk[keyno].key); + xfree (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].key = NULL; + app->app_local->pk[keyno].keylen = 0; app->app_local->pk[keyno].read_done = 0; /* Check whether a key already exists. */ @@ -2142,7 +2155,11 @@ do_decipher (app_t app, const char *keyidstr, cheap check on the PIN: If there is something wrong with the PIN entry system, only the regular CHV will get blocked and not the dangerous CHV3. KEYIDSTR is the usual card's serial number; an - optional fingerprint part will be ignored. */ + optional fingerprint part will be ignored. + + There is a special mode if the keyidstr is "<serialno>[CHV3]" with + the "[CHV3]" being a literal string: The Admin Pin is checked if + and only if the retry counter is still at 3. */ static int do_check_pin (app_t app, const char *keyidstr, int (pincb)(void*, const char *, char **), @@ -2151,6 +2168,7 @@ do_check_pin (app_t app, const char *keyidstr, unsigned char tmp_sn[20]; const char *s; int n; + int admin_pin = 0; if (!keyidstr || !*keyidstr) return gpg_error (GPG_ERR_INV_VALUE); @@ -2167,6 +2185,8 @@ do_check_pin (app_t app, const char *keyidstr, ; /* No fingerprint given: we allow this for now. */ else if (*s == '/') ; /* We ignore a fingerprint. */ + else if (!strcmp (s, "[CHV3]") ) + admin_pin = 1; else return gpg_error (GPG_ERR_INV_ID); @@ -2177,12 +2197,46 @@ do_check_pin (app_t app, const char *keyidstr, return gpg_error (GPG_ERR_INV_CARD); if (memcmp (app->serialno, tmp_sn, 16)) return gpg_error (GPG_ERR_WRONG_CARD); + /* Yes, there is a race conditions: The user might pull the card right here and we won't notice that. However this is not a problem and the check above is merely for a graceful failure between operations. */ - return verify_chv2 (app, pincb, pincb_arg); + if (admin_pin) + { + void *relptr; + unsigned char *value; + size_t valuelen; + int count; + + relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL); + if (!relptr || valuelen < 7) + { + log_error (_("error retrieving CHV status from card\n")); + xfree (relptr); + return gpg_error (GPG_ERR_CARD); + } + count = value[6]; + xfree (relptr); + + if (!count) + { + log_info (_("card is permanently locked!\n")); + return gpg_error (GPG_ERR_BAD_PIN); + } + else if (value[6] < 3) + { + log_info (_("verification of Admin PIN is currently prohibited " + "through this command\n")); + return gpg_error (GPG_ERR_GENERAL); + } + + app->did_chv3 = 0; /* Force verification. */ + return verify_chv3 (app, pincb, pincb_arg); + } + else + return verify_chv2 (app, pincb, pincb_arg); } @@ -2415,7 +2469,9 @@ app_openpgp_storekey (app_t app, int keyno, flush_cache (app); - gcry_sexp_release (app->app_local->pk[keyno].key); + xfree (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].key = NULL; + app->app_local->pk[keyno].keylen = 0; app->app_local->pk[keyno].read_done = 0; rc = iso7816_put_data (app->slot, diff --git a/scd/app.c b/scd/app.c index 0625dc8ef..e035e9b89 100644 --- a/scd/app.c +++ b/scd/app.c @@ -489,7 +489,7 @@ app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, /* Perform a VERIFY operation without doing anything lese. This may - be used to initialze a the PION cache for long lasting other + be used to initialze a the PIN cache for long lasting other operations. Its use is highly application dependent. */ int app_check_pin (APP app, const char *keyidstr, diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 459060830..13e11e4bc 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1,5 +1,5 @@ /* ccid-driver.c - USB ChipCardInterfaceDevices driver - * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * Written by Werner Koch. * * This file is part of GnuPG. @@ -52,7 +52,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ + * $Date$ */ @@ -223,7 +223,7 @@ static unsigned int compute_edc (const unsigned char *data, size_t datalen, int use_crc); static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen); static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, - size_t *nread, int expected_type, int seqno); + size_t *nread, int expected_type, int seqno, int timeout); /* Convert a little endian stored 4 byte value into an unsigned integer. */ @@ -446,12 +446,20 @@ parse_ccid_descriptor (ccid_driver_t handle, send a frame of n*wMaxPacketSize back to us. Given that wMaxPacketSize is 64 for these readers we set the IFSD to a value lower than that: - 64 - 10 CCID header - 4 T1frame - 2 reserved = 48 */ + 64 - 10 CCID header - 4 T1frame - 2 reserved = 48 + Product Ids: + 0xe001 - SCR 331 + 0x5111 - SCR 331-DI + 0x5115 - SCR 335 + 0xe003 - SPR 532 + */ if (handle->id_vendor == VENDOR_SCM - /* FIXME: check whether it is the same - firmware version for all drivers. */ - && handle->bcd_device < 0x0519 - && handle->max_ifsd > 48) + && handle->max_ifsd > 48 + && ( (handle->id_product == 0xe001 && handle->bcd_device < 0x0516) + ||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620) + ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0519) + ||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504) + )) { DEBUGOUT ("enabling workaround for buggy SCM readers\n"); handle->max_ifsd = 48; @@ -699,9 +707,7 @@ scan_or_find_devices (int readerno, const char *readerid, && ifcdesc->bInterfaceProtocol == 0) || (ifcdesc->bInterfaceClass == 255 && dev->descriptor.idVendor == 0x04e6 - && dev->descriptor.idProduct == 0xe003 - && ifcdesc->bInterfaceSubClass == 1 - && ifcdesc->bInterfaceProtocol == 1))) + && dev->descriptor.idProduct == 0xe003))) { idev = usb_open (dev); if (!idev) @@ -974,11 +980,13 @@ do_close_reader (ccid_driver_t handle) rc = bulk_out (handle, msg, msglen); if (!rc) - bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,seqno); + bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, + seqno, 2000); handle->powered_off = 1; } if (handle->idev) { + usb_reset (handle->idev); usb_release_interface (handle->idev, handle->ifc_no); usb_close (handle->idev); handle->idev = NULL; @@ -1102,10 +1110,10 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) BUFFER and return the actual read number if bytes in NREAD. SEQNO is the sequence number used to send the request and EXPECTED_TYPE the type of message we expect. Does checks on the ccid - header. Returns 0 on success. */ + header. TIMEOUT is the timeout value in ms. Returns 0 on success. */ static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, - size_t *nread, int expected_type, int seqno) + size_t *nread, int expected_type, int seqno, int timeout) { int i, rc; size_t msglen; @@ -1117,9 +1125,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, rc = usb_bulk_read (handle->idev, handle->ep_bulk_in, buffer, length, - 10000 /* ms timeout */ ); - /* Fixme: instead of using a 10 second timeout we should better - handle the timeout here and retry if appropriate. */ + timeout); if (rc < 0) { DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno)); @@ -1175,7 +1181,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, } -/* Note that this fucntion won't return the error codes NO_CARD or +/* Note that this function won't return the error codes NO_CARD or CARD_INACTIVE */ static int send_escape_cmd (ccid_driver_t handle, @@ -1206,7 +1212,8 @@ send_escape_cmd (ccid_driver_t handle, rc = bulk_out (handle, msg, msglen); if (rc) return rc; - rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno); + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, + seqno, 5000); return rc; } @@ -1276,7 +1283,9 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) unsigned char msg[100]; size_t msglen; unsigned char seqno; + int retries = 0; + retry: msg[0] = PC_to_RDR_GetSlotStatus; msg[5] = 0; /* slot */ msg[6] = seqno = handle->seqno++; @@ -1288,7 +1297,21 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) rc = bulk_out (handle, msg, 10); if (rc) return rc; - rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno); + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, + seqno, retries? 1000 : 200); + if (rc == CCID_DRIVER_ERR_CARD_IO_ERROR && retries < 3) + { + if (!retries) + { + fprintf (stderr, "CALLING USB_CLEAR_HALT\n"); + usb_clear_halt (handle->idev, handle->ep_bulk_in); + usb_clear_halt (handle->idev, handle->ep_bulk_out); + } + else + fprintf (stderr, "RETRYING AGIAN\n"); + retries++; + goto retry; + } if (rc && rc != CCID_DRIVER_ERR_NO_CARD && rc != CCID_DRIVER_ERR_CARD_INACTIVE) return rc; @@ -1303,6 +1326,7 @@ ccid_get_atr (ccid_driver_t handle, unsigned char *atr, size_t maxatrlen, size_t *atrlen) { int rc; + int statusbits; unsigned char msg[100]; unsigned char *tpdu; size_t msglen, tpdulen; @@ -1311,6 +1335,15 @@ ccid_get_atr (ccid_driver_t handle, unsigned int edc; int i; + /* First check whether a card is available. */ + rc = ccid_slot_status (handle, &statusbits); + if (rc) + return rc; + if (statusbits == 2) + return CCID_DRIVER_ERR_NO_CARD; + + /* For an inactive and also for an active card, issue the PowerOn + command to get the ATR. */ msg[0] = PC_to_RDR_IccPowerOn; msg[5] = 0; /* slot */ msg[6] = seqno = handle->seqno++; @@ -1323,7 +1356,8 @@ ccid_get_atr (ccid_driver_t handle, rc = bulk_out (handle, msg, msglen); if (rc) return rc; - rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno); + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, + seqno, 5000); if (rc) return rc; @@ -1367,7 +1401,8 @@ ccid_get_atr (ccid_driver_t handle, if (rc) return rc; /* Note that we ignore the error code on purpose. */ - bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, seqno); + bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, + seqno, 5000); handle->t1_ns = 0; handle->t1_nr = 0; @@ -1414,7 +1449,7 @@ ccid_get_atr (ccid_driver_t handle, rc = bulk_in (handle, msg, sizeof msg, &msglen, - RDR_to_PC_DataBlock, seqno); + RDR_to_PC_DataBlock, seqno, 5000); if (rc) return rc; @@ -1510,7 +1545,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno); + RDR_to_PC_DataBlock, seqno, 5000); if (rc) return rc; @@ -1683,7 +1718,7 @@ ccid_transceive (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno); + RDR_to_PC_DataBlock, seqno, 5000); if (rc) return rc; @@ -1692,7 +1727,7 @@ ccid_transceive (ccid_driver_t handle, if (tpdulen < 4) { - usb_clear_halt (handle->idev, 0x82); + usb_clear_halt (handle->idev, handle->ep_bulk_in); return CCID_DRIVER_ERR_ABORTED; } #ifdef DEBUG_T1 @@ -1960,7 +1995,7 @@ ccid_transceive_secure (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno); + RDR_to_PC_DataBlock, seqno, 5000); if (rc) return rc; diff --git a/scd/command.c b/scd/command.c index 63e3e28e1..ea296b6fb 100644 --- a/scd/command.c +++ b/scd/command.c @@ -108,7 +108,7 @@ do_reset (ctrl_t ctrl, int do_close) static void -reset_notify (ASSUAN_CONTEXT ctx) +reset_notify (assuan_context_t ctx) { CTRL ctrl = assuan_get_pointer (ctx); @@ -117,7 +117,7 @@ reset_notify (ASSUAN_CONTEXT ctx) static int -option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) +option_handler (assuan_context_t ctx, const char *key, const char *value) { ctrl_t ctrl = assuan_get_pointer (ctx); @@ -248,6 +248,10 @@ cmd_serialno (assuan_context_t ctx, char *line) time_t stamp; /* Clear the remove flag so that the open_card is able to reread it. */ + + /* FIXME: We can't do that if we are in a locked state. Retrun an + appropriate erro r in that case. IF the card has not been + removed we may very well continue. */ if (ctrl->server_local->card_removed) do_reset (ctrl, 0); @@ -333,9 +337,10 @@ cmd_serialno (assuan_context_t ctx, char *line) The URL to be used for locating the entire public key. + Note, that this function may be even be used on a locked card. */ static int -cmd_learn (ASSUAN_CONTEXT ctx, char *line) +cmd_learn (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc = 0; @@ -481,9 +486,10 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) /* READCERT <hexified_certid> + Note, that this function may be even be used on a locked card. */ static int -cmd_readcert (ASSUAN_CONTEXT ctx, char *line) +cmd_readcert (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -524,7 +530,10 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line) /* READKEY <hexified_certid> Return the public key for the given cert or key ID as an standard - S-Expression. */ + S-Expression. + + Note, that this function may be even be used on a locked card. + */ static int cmd_readkey (assuan_context_t ctx, char *line) { @@ -619,14 +628,16 @@ cmd_readkey (assuan_context_t ctx, char *line) The client should use this command to tell us the data he want to sign. */ static int -cmd_setdata (ASSUAN_CONTEXT ctx, char *line) +cmd_setdata (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int n; char *p; unsigned char *buf; - /* parse the hexstring */ + /* FIXME: If we are locked return an error. */ + + /* Parse the hexstring. */ for (p=line,n=0; hexdigitp (p); p++, n++) ; if (*p) @@ -652,7 +663,7 @@ cmd_setdata (ASSUAN_CONTEXT ctx, char *line) static int pin_cb (void *opaque, const char *info, char **retstr) { - ASSUAN_CONTEXT ctx = opaque; + assuan_context_t ctx = opaque; char *command; int rc; unsigned char *value; @@ -687,7 +698,7 @@ pin_cb (void *opaque, const char *info, char **retstr) */ static int -cmd_pksign (ASSUAN_CONTEXT ctx, char *line) +cmd_pksign (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -695,6 +706,8 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) size_t outdatalen; char *keyidstr; + /* FIXME: If we are locked return an error. */ + if ((rc = open_card (ctrl, NULL))) return rc; @@ -738,7 +751,7 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line) */ static int -cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) +cmd_pkauth (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -746,6 +759,8 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) size_t outdatalen; char *keyidstr; + /* FIXME: If we are locked return an error. */ + if ((rc = open_card (ctrl, NULL))) return rc; @@ -785,7 +800,7 @@ cmd_pkauth (ASSUAN_CONTEXT ctx, char *line) */ static int -cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) +cmd_pkdecrypt (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -793,6 +808,8 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) size_t outdatalen; char *keyidstr; + /* FIXME: If we are locked return an error. */ + if ((rc = open_card (ctrl, NULL))) return rc; @@ -834,14 +851,15 @@ cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line) This command is used to retrieve data from a smartcard. The allowed names depend on the currently selected smartcard application. NAME must be percent and '+' escaped. The value is - returned through status message, see the LESRN command for details. + returned through status message, see the LEARN command for details. However, the current implementation assumes that Name is not escaped; this works as long as noone uses arbitrary escaping. + Note, that this function may even be used on a locked card. */ static int -cmd_getattr (ASSUAN_CONTEXT ctx, char *line) +cmd_getattr (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -858,6 +876,8 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line) /* (We ignore any garbage for now.) */ + /* FIXME: Applications should not return sensistive data if the card + is locked. */ rc = app_getattr (ctrl->app_ctx, ctrl, keyword); TEST_CARD_REMOVAL (ctrl, rc); @@ -878,7 +898,7 @@ cmd_getattr (ASSUAN_CONTEXT ctx, char *line) setattr function of the actually used application (app-*.c) for details. */ static int -cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line) +cmd_setattr (assuan_context_t ctx, char *orig_line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -887,6 +907,8 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line) size_t nbytes; char *line, *linebuf; + /* FIXME: If we are locked return an error. */ + if ((rc = open_card (ctrl, NULL))) return rc; @@ -932,13 +954,15 @@ cmd_setattr (ASSUAN_CONTEXT ctx, char *orig_line) */ static int -cmd_genkey (ASSUAN_CONTEXT ctx, char *line) +cmd_genkey (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; char *keyno; int force = has_option (line, "--force"); + /* FIXME: If we are locked return an error. */ + /* Skip over options. */ while ( *line == '-' && line[1] == '-' ) { @@ -974,9 +998,11 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) /* RANDOM <nbytes> Get NBYTES of random from the card and send them back as data. + + Note, that this function may be even be used on a locked card. */ static int -cmd_random (ASSUAN_CONTEXT ctx, char *line) +cmd_random (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; @@ -1016,13 +1042,15 @@ cmd_random (ASSUAN_CONTEXT ctx, char *line) Change the PIN or reset thye retry counter of the card holder verfication vector CHVNO. */ static int -cmd_passwd (ASSUAN_CONTEXT ctx, char *line) +cmd_passwd (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; char *chvnostr; int reset_mode = has_option (line, "--reset"); + /* FIXME: If we are locked return an error. */ + /* Skip over options. */ while (*line == '-' && line[1] == '-') { @@ -1061,12 +1089,14 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) */ static int -cmd_checkpin (ASSUAN_CONTEXT ctx, char *line) +cmd_checkpin (assuan_context_t ctx, char *line) { CTRL ctrl = assuan_get_pointer (ctx); int rc; char *keyidstr; + /* FIXME: If we are locked return an error. */ + if ((rc = open_card (ctrl, NULL))) return rc; -- cgit v1.2.3 From 5a6edf162b7bf776cc77bb22d92e7d6b6717cd70 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 11 Apr 2005 16:21:05 +0000 Subject: * call-dirmngr.c (start_dirmngr): Use PATHSEP_C instead of ':'. * call-agent.c (start_agent): Ditto. --- sm/ChangeLog | 5 +++++ sm/call-agent.c | 2 +- sm/call-dirmngr.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index bb899f5b7..e74381bd5 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2005-03-31 Werner Koch <wk@g10code.com> + + * call-dirmngr.c (start_dirmngr): Use PATHSEP_C instead of ':'. + * call-agent.c (start_agent): Ditto. + 2005-03-17 Werner Koch <wk@g10code.com> * certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509. diff --git a/sm/call-agent.c b/sm/call-agent.c index 0647acbb8..885abf421 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -144,7 +144,7 @@ start_agent (ctrl_t ctrl) } *p++ = 0; pid = atoi (p); - while (*p && *p != ':') + while (*p && *p != PATHSEP_C) p++; prot = *p? atoi (p+1) : 0; if (prot != 1) diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 9c4a5f22f..5988ea952 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -218,7 +218,7 @@ start_dirmngr (void) } *p++ = 0; pid = atoi (p); - while (*p && *p != ':') + while (*p && *p != PATHSEP_C) p++; prot = *p? atoi (p+1) : 0; if (prot != 1) -- cgit v1.2.3 From 3441826da79a94cb4af146e1bc87fbfeed6c08b5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 11 Apr 2005 16:21:49 +0000 Subject: * gpg-connect-agent.c (start_agent): Use PATHSEP_C instead of ':'. --- tools/ChangeLog | 4 ++++ tools/gpg-connect-agent.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index aa1151290..924e11017 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -6,6 +6,10 @@ (symcryptrun_SOURCES, symcryptrun_LDADD): New variables. * symcryptrun.c: New file. +2005-03-31 Werner Koch <wk@g10code.com> + + * gpg-connect-agent.c (start_agent): Use PATHSEP_C instead of ':'. + 2005-03-09 Werner Koch <wk@g10code.com> * gpgconf-comp.c <dirmngr>: Add honor-http-proxy. diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 19ff160f0..6372954f6 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -325,7 +325,7 @@ read_and_print_response (assuan_context_t ctx) -/* Connect to teh agebnt and send the standard options. */ +/* Connect to the agent and send the standard options. */ static assuan_context_t start_agent (void) { @@ -357,7 +357,7 @@ start_agent (void) } *p++ = 0; pid = atoi (p); - while (*p && *p != ':') + while (*p && *p != PATHSEP_C) p++; prot = *p? atoi (p+1) : 0; if (prot != 1) -- cgit v1.2.3 From 14f6a82ca9fdde3a806221ff8d63091ef1ec5e48 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 11 Apr 2005 17:22:23 +0000 Subject: (confucius_mktmpdir): Changed to use mkdtmp(3). --- tools/ChangeLog | 4 ++++ tools/symcryptrun.c | 29 +++++++---------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 924e11017..82f26d0d3 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-04-11 Werner Koch <wk@g10code.com> + + * symcryptrun.c (confucius_mktmpdir): Changed to use mkdtmp(3). + 2005-04-11 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c: Implement config file parsing. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index d0a8bddb9..73f7e0369 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -227,32 +227,17 @@ i18n_init(void) static char * confucius_mktmpdir (void) { - int res; - char *tmpdir; + char *name; - tmpdir = tmpnam (NULL); - if (!tmpdir) - { - log_error (_("cannot create temporary directory name: %s\n"), - strerror (errno)); - return NULL; - } - tmpdir = strdup (tmpdir); - if (!tmpdir) - { - log_error (_("cannot copy temporary directory name: %s\n"), - strerror (errno)); - return NULL; - } - res = mkdir (tmpdir, 0700); - if (res < 0) + name = strdup ("/tmp/gpg-XXXXXX"); + if (!name || !mkdtemp (name)) { - log_error (_("cannot create temporary directory %s: %s\n"), - tmpdir, strerror (errno)); + log_error (_("can't create temporary directory `%s': %s\n"), + name?name:"", strerror (errno)); return NULL; } - return tmpdir; + return name; } @@ -702,7 +687,7 @@ confucius_main (int mode) tmpdir = confucius_mktmpdir (); if (!tmpdir) return 1; - + /* TMPDIR + "/" + "in" + "\0". */ infile = malloc (strlen (tmpdir) + 1 + 2 + 1); if (!infile) -- cgit v1.2.3 From f084afaeda288a0111f5d1c0e49a78a0a85c56a8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 13 Apr 2005 09:39:38 +0000 Subject: Added missing file --- common/sexputil.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 common/sexputil.c diff --git a/common/sexputil.c b/common/sexputil.c new file mode 100644 index 000000000..853d7e58a --- /dev/null +++ b/common/sexputil.c @@ -0,0 +1,63 @@ +/* sexputil.c - Utility fnctions for S-expressions. + * Copyright (C) 2005 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 file implements a few utility functions useful when working + with canonical encrypted S-expresions (i.e. not the S-exprssion + objects from libgcrypt). */ + +#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" + + +/* Return the so called "keygrip" which is the SHA-1 hash of the + public key parameters expressed in a way depended on the algorithm. + + KEY is expected to be an canonical encoded S-expression with a + public or private key. KEYLEN is the length of that buffer. + + GRIP must be at least 20 bytes long On success 0 is return, on + error an aerror code. */ +gpg_error_t +keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, + unsigned char *grip) +{ + gpg_error_t err; + gcry_sexp_t sexp; + + if (!grip) + return gpg_error (GPG_ERR_INV_VALUE); + err = gcry_sexp_sscan (&sexp, NULL, key, keylen); + if (err) + return err; + if (!gcry_pk_get_keygrip (sexp, grip)) + err = gpg_error (GPG_ERR_INTERNAL); + gcry_sexp_release (sexp); + return err; +} + -- cgit v1.2.3 From 9f9a18c011cba01c043a50b326b767e19b07019d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 14 Apr 2005 17:25:43 +0000 Subject: (retrieve_key_material): Rewritten. Return a proper error code. (retrieve_next_token): Removed. (retrieve_fpr_from_card): Rewritten to make use of DO caching and to take the KEYNO as arg. (get_public_key): Renamed variable for clarity. --- scd/ChangeLog | 28 ++++ scd/app-openpgp.c | 392 +++++++++++++++++++----------------------------------- scd/command.c | 361 ++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 446 insertions(+), 335 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index f8f8043c1..9d246ffca 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,31 @@ +2005-04-14 Werner Koch <wk@g10code.com> + + * app-openpgp.c (retrieve_key_material): Rewritten. Return a + proper error code. + (retrieve_next_token): Removed. + (retrieve_fpr_from_card): Rewritten to make use of DO caching and + to take the KEYNO as arg. + (get_public_key): Renamed variable for clarity. + +2005-04-12 Werner Koch <wk@g10code.com> + + Basic support for several sessions. + + * command.c (scd_command_handler): Replace the primary_connection + stuff by a real connection list. Release the local context on + exit. + (scd_update_reader_status_file): Update accordingly. Send signal + to all connections who registered an event signal. + (cmd_lock, cmd_unlock, register_commands): New commands LOCK and + UNLOCK. + (cmd_setdata, cmd_pksign, cmd_pkauth, cmd_pkdecrypt, cmd_setattr) + (cmd_genkey, cmd_passwd, cmd_checkpin): Return an error if reader + is locked. + (do_reset): Handle locking. + (open_card): Ditto. Share the reader slot with other sessions. + (get_reader_slot): New. + (update_card_removed): New. Use it in the TEST_CARD_REMOVAL macro. + 2005-04-07 Werner Koch <wk@g10code.com> * app-openpgp.c (do_check_pin): Add hack to allow verification of diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 1ed057195..0d80c41a7 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -784,266 +784,149 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) } /* Retrieve the fingerprint from the card inserted in SLOT and write - the according hex representation (40 hex digits plus NUL character) - to FPR. */ + the according hex representation to FPR. Caller must have provide + a buffer at FPR of least 41 bytes. Returns 0 on success or an + error code. */ +#if GNUPG_MAJOR_VERSION > 1 static gpg_error_t -retrieve_fpr_from_card (int slot, char *fpr) +retrieve_fpr_from_card (app_t app, int keyno, char *fpr) { - const unsigned char *value; - unsigned char *data; - size_t data_n; - gpg_error_t err; - size_t value_n; - unsigned int i; + gpg_error_t err = 0; + void *relptr; + unsigned char *value; + size_t valuelen; + int i; - data = NULL; + assert (keyno >=0 && keyno <= 2); - err = iso7816_get_data (slot, 0x6E, &data, &data_n); - if (err) - /* FIXME */ - goto out; - - value = find_tlv (data, data_n, 0x00C5, &value_n); - if (! (value - && (! (value_n > (data_n - (value - data)))) - && (value_n >= 60))) /* FIXME: Shouldn't this be "== 60"? */ + relptr = get_one_do (app, 0x00C5, &value, &valuelen, NULL); + if (relptr && valuelen >= 60) { - /* FIXME? */ - err = gpg_error (GPG_ERR_CARD); /* */ - goto out; + for (i = 0; i < 20; i++) + sprintf (fpr + (i * 2), "%02X", value[(keyno*20)+i]); } - - /* Copy out third key FPR. */ - for (i = 0; i < 20; i++) - sprintf (fpr + (i * 2), "%02X", (value + (2 * 20))[i]); - - out: - - xfree (data); - + else + err = gpg_error (GPG_ERR_NOT_FOUND); + xfree (relptr); return err; } +#endif /*GNUPG_MAJOR_VERSION > 1*/ -/* Retrieve the next token from S, using ":" as delimiter. */ -static char * -retrieve_next_token (char *s) -{ - char *p; - - p = strtok (s, ":"); - if (! p) - log_error ("error while extracting token\n"); - return p; -} - -/* Retrieve the secret key material for the key, whose fingerprint is - FPR, from gpg output, which can be read through the stream FP. The - RSA modulus will be stored in m/mlen, the secret exponent in - e/elen. Return zero on success, one on failure. */ -static int -retrieve_key_material (FILE *fp, const char *fpr, +/* Retrieve the public key material for the RSA key, whose fingerprint + is FPR, from gpg output, which can be read through the stream FP. + The RSA modulus will be stored at the address of M and MLEN, the + public exponent at E and ELEN. Returns zero on success, an error + code on failure. Caller must release the allocated buffers at M + and E if the function returns success. */ +#if GNUPG_MAJOR_VERSION > 1 +static gpg_error_t +retrieve_key_material (FILE *fp, const char *hexkeyid, const unsigned char **m, size_t *mlen, const unsigned char **e, size_t *elen) { - size_t line_size; - ssize_t line_ret; - char *line; - int ret; - int found_key; - char *token; - int pkd_n; - unsigned char *m_new; - unsigned char *e_new; - size_t m_new_n; - size_t e_new_n; - int is_rsa; - gcry_mpi_t mpi; - gcry_error_t err; - size_t max_length; - - line_size = 0; - line = NULL; - found_key = 0; - pkd_n = 0; - m_new = NULL; - e_new = NULL; - mpi = NULL; - ret = 0; - -#warning This part should get rewritten for clarity - /* We should use an algorithm similar to the one used by gpgme. - This will reduce the size of the code at least by 50%. [wk] */ - - while (1) + gcry_error_t err = 0; + char *line = NULL; /* read_line() buffer. */ + size_t line_size = 0; /* Helper for for read_line. */ + int found_key = 0; /* Helper to find a matching key. */ + unsigned char *m_new = NULL; + unsigned char *e_new = NULL; + size_t m_new_n = 0; + size_t e_new_n = 0; + + /* Loop over all records until we have found the subkey + corresponsing to the fingerprint. Inm general the first record + should be the pub record, but we don't rely on that. Given that + we only need to look at one key, it is sufficient to compare the + keyid so that we don't need to look at "fpr" records. */ + for (;;) { - /* FIXME? */ - max_length = 1024; - line_ret = read_line (fp, &line, &line_size, &max_length); - if (line_ret < 0) - { - ret = 1; - break; - } - if (! line_ret) - /* EOF. */ - /* FIXME? */ - break; + char *p; + char *fields[6]; + int nfields; + size_t max_length; + gcry_mpi_t mpi; + int i; - token = retrieve_next_token (line); - if (! found_key) - { - /* Key not found yet, search for key entry. */ - if ((! strcmp (token, "pub")) || (! strcmp (token, "sub"))) - { - /* Reached next key entry, parse it. */ - - /* This is the trust level (right, FIXME?). */ - token = retrieve_next_token (NULL); - if (! token) - { - ret = 1; - break; - } - - /* This is the size. */ - token = retrieve_next_token (NULL); - if (! token) - { - ret = 1; - break; - } - - /* This is the algorithm (right, FIXME?). */ - token = retrieve_next_token (NULL); - if (! token) - { - ret = 1; - break; - } - is_rsa = ! strcmp (token, "1"); - - /* This is the fingerprint. */ - token = retrieve_next_token (NULL); - if (! token) - { - ret = 1; - break; - } - - if (! strcmp (token, fpr)) - { - /* Found our key. */ - if (! is_rsa) - { - /* FIXME. */ - ret = 1; - break; - } - found_key = 1; - } - } - } - else + max_length = 4096; + i = read_line (fp, &line, &line_size, &max_length); + if (!i) + break; /* EOF. */ + if (i < 0) { - if (! strcmp (token, "sub")) - /* Next key entry, break. */ - break; - - if (! strcmp (token, "pkd")) - { - if ((pkd_n == 0) || (pkd_n == 1)) - { - /* This is the pkd index. */ - token = retrieve_next_token (NULL); - if (! token) - { - /* FIXME. */ - ret = 1; - break; - } - - /* This is the pkd size. */ - token = retrieve_next_token (NULL); - if (! token) - { - /* FIXME. */ - ret = 1; - break; - } - - /* This is the pkd mpi. */ - token = retrieve_next_token (NULL); - if (! token) - { - /* FIXME. */ - ret = 1; - break; - } - - err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, token, 0, NULL); - if (err) - { - log_error ("error while converting pkd %i from hex: %s\n", - pkd_n, gcry_strerror (err)); - ret = 1; - break; - } - - if (pkd_n == 0) - err = gcry_mpi_aprint (GCRYMPI_FMT_STD, - &m_new, &m_new_n, mpi); - else - err = gcry_mpi_aprint (GCRYMPI_FMT_STD, - &e_new, &e_new_n, mpi); - if (err) - { - log_error ("error while converting pkd %i to std: %s\n", - pkd_n, gcry_strerror (err)); - ret = 1; - break; - } - gcry_mpi_release (mpi); - mpi = NULL; - pkd_n++; - } - else - { - /* Too many pkd entries. */ - /* FIXME */ - ret = 1; - break; - } - } + err = gpg_error_from_errno (errno); + goto leave; /* Error. */ } - } - if (ret) - goto out; - - if (pkd_n < 2) - { - /* Not enough pkds retrieved. */ - ret = 1; - goto out; - } - - *m = m_new; - *mlen = m_new_n; - *e = e_new; - *elen = e_new_n; + if (!max_length) + { + err = gpg_error (GPG_ERR_TRUNCATED); + goto leave; /* Line truncated - we better stop processing. */ + } - out: + /* Parse the line into fields. */ + for (nfields=0, p=line; p && nfields < DIM (fields); nfields++) + { + fields[nfields] = p; + p = strchr (p, ':'); + if (p) + *(p++) = 0; + } + if (!nfields) + continue; /* No fields at all - skip line. */ - if (ret) + if (!found_key) + { + if ( (!strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") ) + && nfields > 4 && !strcmp (fields[4], hexkeyid)) + found_key = 1; + continue; + } + + if ( !strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") ) + break; /* Next key - stop. */ + + if ( strcmp (fields[0], "pkd") ) + continue; /* Not a key data record. */ + i = 0; /* Avoid erroneous compiler warning. */ + if ( nfields < 4 || (i = atoi (fields[1])) < 0 || i > 1 + || (!i && m_new) || (i && e_new)) + { + err = gpg_error (GPG_ERR_GENERAL); + goto leave; /* Error: Invalid key data record or not an RSA key. */ + } + + err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, fields[3], 0, NULL); + if (err) + mpi = NULL; + else if (!i) + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &m_new, &m_new_n, mpi); + else + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &e_new, &e_new_n, mpi); + gcry_mpi_release (mpi); + if (err) + goto leave; + } + + if (m_new && e_new) { - gcry_free (m_new); - gcry_free (e_new); + *m = m_new; + *mlen = m_new_n; + m_new = NULL; + *e = e_new; + *elen = e_new_n; + e_new = NULL; } - gcry_mpi_release (mpi); - gcry_free (line); + else + err = gpg_error (GPG_ERR_GENERAL); - return ret; + leave: + xfree (m_new); + xfree (e_new); + xfree (line); + return err; } +#endif /*GNUPG_MAJOR_VERSION > 1*/ + /* Get the public key for KEYNO and store it as an S-expresion with the APP handle. On error that field gets cleared. If we already @@ -1158,52 +1041,49 @@ get_public_key (app_t app, int keyno) The helper we use here is gpg itself, which should know about the key in any case. */ - char fpr_long[41]; - char *fpr = fpr_long + 24; - char *command; + char fpr[41]; + char *hexkeyid; + char *command = NULL; FILE *fp; int ret; - command = NULL; + buffer = NULL; /* We don't need buffer. */ - err = retrieve_fpr_from_card (app->slot, fpr_long); + err = retrieve_fpr_from_card (app, keyno, fpr); if (err) { log_error ("error while retrieving fpr from card: %s\n", gpg_strerror (err)); goto leave; } + hexkeyid = fpr + 24; ret = asprintf (&command, "gpg --list-keys --with-colons --with-key-data '%s'", - fpr_long); + fpr); if (ret < 0) { err = gpg_error_from_errno (errno); - log_error ("error while creating pipe command " - "for retrieving key: %s\n", gpg_strerror (err)); goto leave; } fp = popen (command, "r"); - if (! fp) + free (command); + if (!fp) { err = gpg_error_from_errno (errno); - log_error ("error while creating pipe: %s\n", gpg_strerror (err)); + log_error ("running gpg failed: %s\n", gpg_strerror (err)); goto leave; } - ret = retrieve_key_material (fp, fpr, &m, &mlen, &e, &elen); + err = retrieve_key_material (fp, hexkeyid, &m, &mlen, &e, &elen); fclose (fp); - if (ret) + if (err) { - /* FIXME? */ - err = gpg_error (GPG_ERR_INTERNAL); - log_error ("error while retrieving key material through pipe\n"); + log_error ("error while retrieving key material through pipe: %s\n", + gpg_strerror (err)); goto leave; } - - buffer = NULL; } /* Allocate a buffer to construct the S-expression. */ @@ -1216,11 +1096,11 @@ get_public_key (app_t app, int keyno) goto leave; } - sprintf (keybuf, "(10:public-key(3:rsa(1:n%u", (unsigned int) mlen); + sprintf (keybuf, "(10:public-key(3:rsa(1:n%u:", (unsigned int) mlen); keybuf_p = keybuf + strlen (keybuf); memcpy (keybuf_p, m, mlen); keybuf_p += mlen; - sprintf (keybuf_p, ")(1:e%u", (unsigned int)elen); + sprintf (keybuf_p, ")(1:e%u:", (unsigned int)elen); keybuf_p += strlen (keybuf_p); memcpy (keybuf_p, e, elen); keybuf_p += elen; diff --git a/scd/command.c b/scd/command.c index ea296b6fb..9881b1be0 100644 --- a/scd/command.c +++ b/scd/command.c @@ -26,6 +26,9 @@ #include <ctype.h> #include <unistd.h> #include <signal.h> +#ifdef USE_GNU_PTH +# include <pth.h> +#endif #include <assuan.h> @@ -38,11 +41,6 @@ #define MAXLEN_PIN 100 -/* We keep track of the primary client using scdaemon. This one will - for example receive signal on card change. */ -static ctrl_t primary_connection; - - #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) @@ -52,20 +50,65 @@ static ctrl_t primary_connection; int _r = (r); \ if (gpg_err_code (_r) == GPG_ERR_CARD_NOT_PRESENT \ || gpg_err_code (_r) == GPG_ERR_CARD_REMOVED) \ - (c)->server_local->card_removed = 1; \ + update_card_removed ((c)->reader_slot, 1); \ } while (0) +#define IS_LOCKED(c) \ + (locked_session && locked_session != (c)->server_local \ + && (c)->reader_slot != -1 && locked_session->ctrl_backlink \ + && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot) + -/* Data used to associate an Assuan context with local server data */ +/* Data used to associate an Assuan context with local server data. + This object describes the local properties of one session. */ struct server_local_s { + /* We keep a list of all active sessions with the anchor at + SESSION_LIST (see below). This field is used for linking. */ + struct server_local_s *next_session; + + /* This object is usually assigned to a CTRL object (which is + globally visible). While enumeratin all sessions we sometimes + need to access data of the CTRL object; thus we keep a + backpointer here. */ + ctrl_t ctrl_backlink; + + /* The Assuan context used by this session/server. */ assuan_context_t assuan_ctx; + int event_signal; /* Or 0 if not used. */ - int card_removed; /* True if the card has been removed and a - reset is required to continue - operation. */ + + /* True if the card has been removed and a reset is required to + continue operation. */ + int card_removed; }; +/* To keep track of all running sessions, we link all active server + contexts and the anchor in this variable. */ +static struct server_local_s *session_list; + +/* If a session has been locked we store a link to its server object + in this variable. */ +static struct server_local_s *locked_session; + + + + +/* Update the CARD_REMOVED element of all sessions using the reader + given by SLOT to VALUE */ +static void +update_card_removed (int slot, int value) +{ + struct server_local_s *sl; + + for (sl=session_list; sl; sl = sl->next_session) + if (sl->ctrl_backlink + && sl->ctrl_backlink->reader_slot == slot) + sl->card_removed = value; +} + + + /* Check whether the option NAME appears in LINE */ static int has_option (const char *line, const char *name) @@ -79,10 +122,13 @@ has_option (const char *line, const char *name) /* Reset the card and free the application context. With DO_CLOSE set - to true, close the reader and don't do just a reset. */ + to true and this is the last session with a reference to teh + reader, close the reader and don't do just a reset. */ static void do_reset (ctrl_t ctrl, int do_close) { + int slot = ctrl->reader_slot; + if (ctrl->card_ctx) { card_close (ctrl->card_ctx); @@ -97,20 +143,61 @@ do_reset (ctrl_t ctrl, int do_close) } if (ctrl->reader_slot != -1) { - if (do_close || apdu_reset (ctrl->reader_slot)) + struct server_local_s *sl; + + /* If we are the only session with the reader open we may close + it. If not, do a reset unless the a lock is held on the + reader. */ + for (sl=session_list; sl; sl = sl->next_session) + if (sl != ctrl->server_local + && sl->ctrl_backlink->reader_slot == ctrl->reader_slot) + break; + if (sl) /* There is another session with the reader open. */ + { + if ( IS_LOCKED (ctrl) ) /* If it is locked, release it. */ + ctrl->reader_slot = -1; + else + { + if (do_close) /* Always mark reader unused. */ + ctrl->reader_slot = -1; + else if (apdu_reset (ctrl->reader_slot)) /* Reset only if + not locked */ + { + /* The reset failed. Mark the reader as closed. */ + ctrl->reader_slot = -1; + } + + if (locked_session && ctrl->server_local == locked_session) + { + locked_session = NULL; + log_debug ("implicitly unlocking due to RESET\n"); + } + } + } + else /* No other session has the reader open. */ { - apdu_close_reader (ctrl->reader_slot); - ctrl->reader_slot = -1; + if (do_close || apdu_reset (ctrl->reader_slot)) + { + apdu_close_reader (ctrl->reader_slot); + ctrl->reader_slot = -1; + } + if ( IS_LOCKED (ctrl) ) + { + log_debug ("WARNING: cleaning up stale session lock\n"); + locked_session = NULL; + } } } - ctrl->server_local->card_removed = 0; + + /* Reset card removed flag for the current reader. */ + update_card_removed (slot, 0); } static void reset_notify (assuan_context_t ctx) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); do_reset (ctrl, 0); } @@ -134,6 +221,27 @@ option_handler (assuan_context_t ctx, const char *key, const char *value) } +/* Return the slot of the current reader or open the reader if no + other sessions are using a reader. Note, that we currently support + only one reader but most of the code (except for this function) + should be able to cope with several readers. */ +static int +get_reader_slot (void) +{ + struct server_local_s *sl; + int slot= -1; + + for (sl=session_list; sl; sl = sl->next_session) + if (sl->ctrl_backlink + && (slot = sl->ctrl_backlink->reader_slot) != -1) + break; + + if (slot == -1) + slot = apdu_open_reader (opt.reader_port); + + return slot; +} + /* If the card has not yet been opened, do it. Note that this function returns an Assuan error, so don't map the error a second time */ @@ -154,10 +262,13 @@ open_card (ctrl_t ctrl, const char *apptype) if (ctrl->card_ctx) return 0; /* Already initialized using a card context. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); + if (ctrl->reader_slot != -1) slot = ctrl->reader_slot; else - slot = apdu_open_reader (opt.reader_port); + slot = get_reader_slot (); ctrl->reader_slot = slot; if (slot == -1) err = gpg_error (GPG_ERR_CARD); @@ -177,9 +288,7 @@ open_card (ctrl_t ctrl, const char *apptype) err = card_open (&ctrl->card_ctx); } - if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT) - ctrl->server_local->card_removed = 1; - + TEST_CARD_REMOVAL (ctrl, err); return map_to_assuan_status (err); } @@ -248,12 +357,12 @@ cmd_serialno (assuan_context_t ctx, char *line) time_t stamp; /* Clear the remove flag so that the open_card is able to reread it. */ - - /* FIXME: We can't do that if we are in a locked state. Retrun an - appropriate erro r in that case. IF the card has not been - removed we may very well continue. */ if (ctrl->server_local->card_removed) - do_reset (ctrl, 0); + { + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); + do_reset (ctrl, 0); + } if ((rc = open_card (ctrl, *line? line:NULL))) return rc; @@ -342,7 +451,7 @@ cmd_serialno (assuan_context_t ctx, char *line) static int cmd_learn (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc = 0; int idx; @@ -491,7 +600,7 @@ cmd_learn (assuan_context_t ctx, char *line) static int cmd_readcert (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char *cert; size_t ncert; @@ -630,12 +739,13 @@ cmd_readkey (assuan_context_t ctx, char *line) static int cmd_setdata (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int n; char *p; unsigned char *buf; - /* FIXME: If we are locked return an error. */ + if (locked_session && locked_session != ctrl->server_local) + return gpg_error (GPG_ERR_EBUSY); /* Parse the hexstring. */ for (p=line,n=0; hexdigitp (p); p++, n++) @@ -700,13 +810,14 @@ pin_cb (void *opaque, const char *info, char **retstr) static int cmd_pksign (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char *outdata; size_t outdatalen; char *keyidstr; - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); if ((rc = open_card (ctrl, NULL))) return rc; @@ -753,13 +864,14 @@ cmd_pksign (assuan_context_t ctx, char *line) static int cmd_pkauth (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char *outdata; size_t outdatalen; char *keyidstr; - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); if ((rc = open_card (ctrl, NULL))) return rc; @@ -802,13 +914,14 @@ cmd_pkauth (assuan_context_t ctx, char *line) static int cmd_pkdecrypt (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; unsigned char *outdata; size_t outdatalen; char *keyidstr; - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); if ((rc = open_card (ctrl, NULL))) return rc; @@ -861,7 +974,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line) static int cmd_getattr (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; char *keyword; @@ -900,14 +1013,15 @@ cmd_getattr (assuan_context_t ctx, char *line) static int cmd_setattr (assuan_context_t ctx, char *orig_line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; char *keyword; int keywordlen; size_t nbytes; char *line, *linebuf; - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); if ((rc = open_card (ctrl, NULL))) return rc; @@ -956,12 +1070,13 @@ cmd_setattr (assuan_context_t ctx, char *orig_line) static int cmd_genkey (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; char *keyno; int force = has_option (line, "--force"); - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); /* Skip over options. */ while ( *line == '-' && line[1] == '-' ) @@ -1004,7 +1119,7 @@ cmd_genkey (assuan_context_t ctx, char *line) static int cmd_random (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; size_t nbytes; unsigned char *buffer; @@ -1044,12 +1159,13 @@ cmd_random (assuan_context_t ctx, char *line) static int cmd_passwd (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; char *chvnostr; int reset_mode = has_option (line, "--reset"); - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); /* Skip over options. */ while (*line == '-' && line[1] == '-') @@ -1091,11 +1207,12 @@ cmd_passwd (assuan_context_t ctx, char *line) static int cmd_checkpin (assuan_context_t ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); + ctrl_t ctrl = assuan_get_pointer (ctx); int rc; char *keyidstr; - /* FIXME: If we are locked return an error. */ + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_EBUSY); if ((rc = open_card (ctrl, NULL))) return rc; @@ -1122,15 +1239,83 @@ cmd_checkpin (assuan_context_t ctx, char *line) } +/* LOCK [--wait] + + Grant exclusive card access to this session. Note that there is + no lock counter used and a second lock from the same session will + get ignore. A single unlock (or RESET) unlocks the session. + Return GPG_ERR_EBUSY if another session has locked the reader. + + If the option --wait is given the command will wait until a + lock has been released. + */ +static int +cmd_lock (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int rc = 0; + + retry: + if (locked_session) + { + if (locked_session != ctrl->server_local) + rc = gpg_error (GPG_ERR_EBUSY); + } + else + locked_session = ctrl->server_local; + +#ifdef USE_GNU_PTH + if (rc && has_option (line, "--wait")) + { + pth_sleep (1); /* Better implement an event mechanism. However, + for card operations this should be + sufficient. */ + goto retry; + } +#endif /*USE_GNU_PTH*/ + + if (rc) + log_error ("cmd_lock failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + +/* UNLOCK + + Release exclusive card access. + */ +static int +cmd_unlock (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int rc = 0; + + if (locked_session) + { + if (locked_session != ctrl->server_local) + rc = gpg_error (GPG_ERR_EBUSY); + else + locked_session = NULL; + } + else + rc = gpg_error (GPG_ERR_NOT_LOCKED); + + if (rc) + log_error ("cmd_unlock failed: %s\n", gpg_strerror (rc)); + return map_to_assuan_status (rc); +} + + + /* Tell the assuan library about our commands */ static int -register_commands (ASSUAN_CONTEXT ctx) +register_commands (assuan_context_t ctx) { static struct { const char *name; - int (*handler)(ASSUAN_CONTEXT, char *line); + int (*handler)(assuan_context_t, char *line); } table[] = { { "SERIALNO", cmd_serialno }, { "LEARN", cmd_learn }, @@ -1148,6 +1333,8 @@ register_commands (ASSUAN_CONTEXT ctx) { "RANDOM", cmd_random }, { "PASSWD", cmd_passwd }, { "CHECKPIN", cmd_checkpin }, + { "LOCK", cmd_lock }, + { "UNLOCK", cmd_unlock }, { NULL } }; int i, rc; @@ -1172,7 +1359,7 @@ void scd_command_handler (int listen_fd) { int rc; - ASSUAN_CONTEXT ctx; + assuan_context_t ctx; struct server_control_s ctrl; memset (&ctrl, 0, sizeof ctrl); @@ -1204,20 +1391,24 @@ scd_command_handler (int listen_fd) scd_exit (2); } assuan_set_pointer (ctx, &ctrl); + + /* Allocate and initialize the server object. Put it into the list + of active sessions. */ ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); + ctrl.server_local->next_session = session_list; + session_list = ctrl.server_local; + ctrl.server_local->ctrl_backlink = &ctrl; ctrl.server_local->assuan_ctx = ctx; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); - /* Store the primary connection's assuan context. */ - if (!primary_connection) - primary_connection = &ctrl; - /* We open the reader right at startup so that the ticker is able to update the status file. */ if (ctrl.reader_slot == -1) - ctrl.reader_slot = apdu_open_reader (opt.reader_port); + { + ctrl.reader_slot = get_reader_slot (); + } /* Command processing loop. */ for (;;) @@ -1241,13 +1432,26 @@ scd_command_handler (int listen_fd) } } - /* The next client will be the primary conenction if this one - terminates. */ - if (primary_connection == &ctrl) - primary_connection = NULL; + /* Cleanup. */ + do_reset (&ctrl, 1); - do_reset (&ctrl, 1); /* Cleanup. */ + /* Release the server object. */ + if (session_list == ctrl.server_local) + session_list = ctrl.server_local->next_session; + else + { + struct server_local_s *sl; + + for (sl=session_list; sl->next_session; sl = sl->next_session) + if (sl->next_session == ctrl.server_local) + break; + if (!sl->next_session) + BUG (); + sl->next_session = ctrl.server_local->next_session; + } + xfree (ctrl.server_local); + /* Release the Assuan context. */ assuan_deinit_server (ctx); } @@ -1256,14 +1460,14 @@ scd_command_handler (int listen_fd) buffers. The variable elements are pairs of (char *, size_t), terminated with a (NULL, 0). */ void -send_status_info (CTRL ctrl, const char *keyword, ...) +send_status_info (ctrl_t ctrl, const char *keyword, ...) { va_list arg_ptr; const unsigned char *value; size_t valuelen; char buf[950], *p; size_t n; - ASSUAN_CONTEXT ctx = ctrl->server_local->assuan_ctx; + assuan_context_t ctx = ctrl->server_local->assuan_ctx; va_start (arg_ptr, keyword); @@ -1299,7 +1503,7 @@ send_status_info (CTRL ctrl, const char *keyword, ...) } -/* This fucntion is called by the ticker thread to check for changes +/* This function is called by the ticker thread to check for changes of the reader stati. It updates the reader status files and if requested by the caller also send a signal to the caller. */ void @@ -1328,6 +1532,7 @@ scd_update_reader_status_file (void) char *fname; char templ[50]; FILE *fp; + struct server_local_s *sl; log_info ("updating status of slot %d to 0x%04X\n", slot, status); @@ -1344,33 +1549,31 @@ scd_update_reader_status_file (void) } xfree (fname); - /* Set the card removed flag. We will set this on any - card change because a reset or SERIALNO request must be - done in any case. */ - if (primary_connection && primary_connection->server_local - && last[slot].any ) - primary_connection->server_local->card_removed = 1; + /* Set the card removed flag for all current sessions. We + will set this on any card change because a reset or + SERIALNO request must be done in any case. */ + if (last[slot].any) + update_card_removed (slot, 1); last[slot].any = 1; last[slot].status = status; last[slot].changed = changed; - /* Send a signal to the primary client, if any. */ - if (primary_connection && primary_connection->server_local - && primary_connection->server_local->assuan_ctx) - { - pid_t pid = assuan_get_pid (primary_connection - ->server_local->assuan_ctx); - int signo = primary_connection->server_local->event_signal; - - log_info ("client pid is %d, sending signal %d\n", pid, signo); + /* Send a signal to all clients who applied for it. */ + for (sl=session_list; sl; sl = sl->next_session) + if (sl->event_signal && sl->assuan_ctx) + { + pid_t pid = assuan_get_pid (sl->assuan_ctx); + int signo = sl->event_signal; + log_info ("client pid is %d, sending signal %d\n", + pid, signo); #ifndef HAVE_W32_SYSTEM - if (pid != (pid_t)(-1) && pid && signo > 0) - kill (pid, signo); + if (pid != (pid_t)(-1) && pid && signo > 0) + kill (pid, signo); #endif - } + } } } } -- cgit v1.2.3 From f527f721d4d5b10c04267b2a70f7d4e89cc91ea7 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 15 Apr 2005 01:33:46 +0000 Subject: 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * configure.ac: Add --enable-symcryptrun, disabled by default. Define automake variable BUILD_SYMCRYPTRUN. Check for openpty -lutil, define LIBUTIL_LIBS. tools/ 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * Makefile.am: Define symcryptrun make variable depending on BUILD_SYMCRYPTUN. (bin_PROGRAMS): Add ${symcryptrun} instead symcryptrun. (symcryptrun_LDADD): Use $(LIBUTIL_LIBS) instead of -lutil. --- ChangeLog | 6 ++++++ configure.ac | 12 ++++++++++++ tools/ChangeLog | 7 +++++++ tools/Makefile.am | 10 ++++++++-- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9f9fe3dd..8e23a3d43 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-04-15 Marcus Brinkmann <marcus@g10code.de> + + * configure.ac: Add --enable-symcryptrun, disabled by default. + Define automake variable BUILD_SYMCRYPTRUN. + Check for openpty -lutil, define LIBUTIL_LIBS. + 2005-03-03 Werner Koch <wk@g10code.com> * acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Accidently used diff --git a/configure.ac b/configure.ac index 7462a759e..34463da04 100644 --- a/configure.ac +++ b/configure.ac @@ -66,6 +66,7 @@ GNUPG_BUILD_PROGRAM(gpg, yes) GNUPG_BUILD_PROGRAM(gpgsm, yes) GNUPG_BUILD_PROGRAM(agent, yes) GNUPG_BUILD_PROGRAM(scdaemon, yes) +GNUPG_BUILD_PROGRAM(symcryptrun, no) AC_SUBST(PACKAGE) @@ -468,6 +469,16 @@ AC_CHECK_LIB(usb, usb_bulk_write, AC_SUBST(LIBUSB_LIBS) AC_CHECK_FUNCS(usb_create_match) +# +# libutil has openpty() and login_tty(). +# +AC_CHECK_LIB(util, openpty, + [ LIBUTIL_LIBS="$LIBUTIL_LIBS -lutil" + AC_DEFINE(HAVE_LIBUTIL,1, + [defined if libutil is available]) + ]) +AC_SUBST(LIBUTIL_LIBS) + # # Check wether it is necessary to link against libdl. # @@ -1046,6 +1057,7 @@ AM_CONDITIONAL(BUILD_GPG, test "$build_gpg" = "yes") AM_CONDITIONAL(BUILD_GPGSM, test "$build_gpgsm" = "yes") AM_CONDITIONAL(BUILD_AGENT, test "$build_agent" = "yes") AM_CONDITIONAL(BUILD_SCDAEMON, test "$build_scdaemon" = "yes") +AM_CONDITIONAL(BUILD_SYMCRYPTRUN, test "$build_symcryptrun" = "yes") diff --git a/tools/ChangeLog b/tools/ChangeLog index 82f26d0d3..d6280b776 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2005-04-15 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am: Define symcryptrun make variable depending on + BUILD_SYMCRYPTUN. + (bin_PROGRAMS): Add ${symcryptrun} instead symcryptrun. + (symcryptrun_LDADD): Use $(LIBUTIL_LIBS) instead of -lutil. + 2005-04-11 Werner Koch <wk@g10code.com> * symcryptrun.c (confucius_mktmpdir): Changed to use mkdtmp(3). diff --git a/tools/Makefile.am b/tools/Makefile.am index 2616d69a9..b0a477910 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -30,7 +30,13 @@ sbin_SCRIPTS = addgnupghome bin_SCRIPTS = gpgsm-gencert.sh -bin_PROGRAMS = gpgconf gpg-connect-agent symcryptrun +if BUILD_SYMCRYPTRUN + symcryptrun = symcryptrun +else + symcryptrun = +endif + +bin_PROGRAMS = gpgconf gpg-connect-agent ${symcryptrun} if !HAVE_W32_SYSTEM bin_PROGRAMS += watchgnupg endif @@ -40,7 +46,7 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @LIBINTL@ symcryptrun_SOURCES = symcryptrun.c -symcryptrun_LDADD = -lutil ../jnlib/libjnlib.a ../common/libcommon.a \ +symcryptrun_LDADD = $(LIBUTIL_LIBS) ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) -- cgit v1.2.3 From e0d6d1c476ee8602e8e450a6d45cdc3ca1ec8fbb Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 15 Apr 2005 02:24:44 +0000 Subject: 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * configure.ac: Check for /usr/bin/shred and define SHRED. tools/ 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (remove_file): New function. (confucius_copy_file): Accept new argument PLAIN and shred the file if it is set on error. --- ChangeLog | 2 ++ configure.ac | 23 +++++++++------ tools/ChangeLog | 4 +++ tools/symcryptrun.c | 80 +++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 90 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8e23a3d43..3c3c700c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2005-04-15 Marcus Brinkmann <marcus@g10code.de> + * configure.ac: Check for /usr/bin/shred and define SHRED. + * configure.ac: Add --enable-symcryptrun, disabled by default. Define automake variable BUILD_SYMCRYPTRUN. Check for openpty -lutil, define LIBUTIL_LIBS. diff --git a/configure.ac b/configure.ac index 34463da04..d331566be 100644 --- a/configure.ac +++ b/configure.ac @@ -470,8 +470,18 @@ AC_SUBST(LIBUSB_LIBS) AC_CHECK_FUNCS(usb_create_match) # -# libutil has openpty() and login_tty(). +# Check wether it is necessary to link against libdl. +# +LIBS="" +AC_SEARCH_LIBS(dlopen, c dl,,,) +DL_LIBS=$LIBS +AC_SUBST(DL_LIBS) + +# +# Checks for symcryptrun: # + +# libutil has openpty() and login_tty(). AC_CHECK_LIB(util, openpty, [ LIBUTIL_LIBS="$LIBUTIL_LIBS -lutil" AC_DEFINE(HAVE_LIBUTIL,1, @@ -479,13 +489,10 @@ AC_CHECK_LIB(util, openpty, ]) AC_SUBST(LIBUTIL_LIBS) -# -# Check wether it is necessary to link against libdl. -# -LIBS="" -AC_SEARCH_LIBS(dlopen, c dl,,,) -DL_LIBS=$LIBS -AC_SUBST(DL_LIBS) +# shred is used to clean temporary plain text files. +AC_PATH_PROG(SHRED, shred, /usr/bin/shred) +AC_DEFINE_UNQUOTED(SHRED, + "${SHRED}", [defines the filename of the shred program]) # # OpenSC is needed by the SCdaemon - if it is not availbale we can only diff --git a/tools/ChangeLog b/tools/ChangeLog index d6280b776..981c52f6b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,9 @@ 2005-04-15 Marcus Brinkmann <marcus@g10code.de> + * symcryptrun.c (remove_file): New function. + (confucius_copy_file): Accept new argument PLAIN and shred the + file if it is set on error. + * Makefile.am: Define symcryptrun make variable depending on BUILD_SYMCRYPTUN. (bin_PROGRAMS): Add ${symcryptrun} instead symcryptrun. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 73f7e0369..9f3a55f8b 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -216,6 +216,61 @@ i18n_init(void) #endif } + +/* Unlink a file, and shred it if SHRED is true. */ +int +remove_file (char *name, int shred) +{ + if (!shred) + return unlink (name); + else + { + int status; + pid_t pid; + + pid = fork (); + if (pid == 0) + { + /* Child. */ + + /* -f forces file to be writable, and -u unlinks it afterwards. */ + char *args[] = { SHRED, "-uf", name, NULL }; + + execv (SHRED, args); + _exit (127); + } + else if (pid < 0) + { + /* Fork failed. */ + status = -1; + } + else + { + /* Parent. */ + + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + status = -1; + } + + if (!WIFEXITED (status)) + { + log_error (_("%s on %s aborted with status %i\n"), + SHRED, name, status); + unlink (name); + return 1; + } + else if (WEXITSTATUS (status)) + { + log_error (_("%s on %s failed with status %i\n"), SHRED, name, + WEXITSTATUS (status)); + unlink (name); + return 1; + } + + return 0; + } +} + /* Class Confucius. @@ -248,9 +303,11 @@ confucius_mktmpdir (void) #define CONFUCIUS_LINESIZE 4096 -/* Copy the file IN to OUT, either of which may be "-". */ +/* Copy the file IN to OUT, either of which may be "-". If PLAIN is + true, and the copying fails, and OUT is not STDOUT, then shred the + file instead unlinking it. */ static int -confucius_copy_file (const char *infile, const char *outfile) +confucius_copy_file (char *infile, char *outfile, int plain) { FILE *in; int in_is_stdin = 0; @@ -327,7 +384,8 @@ confucius_copy_file (const char *infile, const char *outfile) copy_err: if (!out_is_stdout) - unlink (outfile); + remove_file (outfile, plain); + return 1; } @@ -712,7 +770,7 @@ confucius_main (int mode) strcat (outfile, "/out"); /* Create INFILE and fill it with content. */ - res = confucius_copy_file ("-", infile); + res = confucius_copy_file ("-", infile, mode == oEncrypt); if (res) { free (outfile); @@ -726,8 +784,8 @@ confucius_main (int mode) res = confucius_process (mode, infile, outfile); if (res) { - unlink (outfile); - unlink (infile); + remove_file (outfile, mode == oDecrypt); + remove_file (infile, mode == oEncrypt); free (outfile); free (infile); rmdir (tmpdir); @@ -735,19 +793,19 @@ confucius_main (int mode) } /* Dump the output file to stdout. */ - res = confucius_copy_file (outfile, "-"); + res = confucius_copy_file (outfile, "-", mode == oDecrypt); if (res) { - unlink (outfile); - unlink (infile); + remove_file (outfile, mode == oDecrypt); + remove_file (infile, mode == oEncrypt); free (outfile); free (infile); rmdir (tmpdir); return res; } - unlink (outfile); - unlink (infile); + remove_file (outfile, mode == oDecrypt); + remove_file (infile, mode == oEncrypt); free (outfile); free (infile); rmdir (tmpdir); -- cgit v1.2.3 From 00853b8a1aa5c4ff8bb10d99e65db52b06f639bf Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 15 Apr 2005 09:04:43 +0000 Subject: 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (TEMP_FAILURE_RETRY): Define if not defined. --- tools/ChangeLog | 2 ++ tools/symcryptrun.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 981c52f6b..62a5e841c 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,7 @@ 2005-04-15 Marcus Brinkmann <marcus@g10code.de> + * symcryptrun.c (TEMP_FAILURE_RETRY): Define if not defined. + * symcryptrun.c (remove_file): New function. (confucius_copy_file): Accept new argument PLAIN and shred the file if it is set on error. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 9f3a55f8b..b35e4d7a5 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -217,6 +217,21 @@ i18n_init(void) } +/* This is in the GNU C library in unistd.h. */ + +#ifndef TEMP_FAILURE_RETRY +/* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno' + set to EINTR. */ + +# define TEMP_FAILURE_RETRY(expression) \ + (__extension__ \ + ({ long int __result; \ + do __result = (long int) (expression); \ + while (__result == -1L && errno == EINTR); \ + __result; })) +#endif + + /* Unlink a file, and shred it if SHRED is true. */ int remove_file (char *name, int shred) -- cgit v1.2.3 From eff62d82bfcb9df1b85ce596f0f5b6ef00d3a0ca Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 18 Apr 2005 10:44:46 +0000 Subject: * configure.ac: Require libksba 0.9.11. sm/ * call-dirmngr.c (inq_certificate): Add new inquire SENDCERT_SKI. * certlist.c (gpgsm_find_cert): Add new arg KEYID and implement this filter. Changed all callers. * certchain.c (find_up_search_by_keyid): New helper. (find_up): Also try using the AKI.keyIdentifier. (find_up_external): Ditto. --- ChangeLog | 4 ++ NEWS | 9 ++++- README | 8 ++-- TODO | 4 ++ agent/command-ssh.c | 1 + common/ChangeLog | 5 +++ common/sexputil.c | 78 ++++++++++++++++++++++++++++++++++++ common/util.h | 3 ++ configure.ac | 2 +- sm/ChangeLog | 15 +++++++ sm/call-dirmngr.c | 21 ++++++++-- sm/certchain.c | 113 ++++++++++++++++++++++++++++++++++++++++++---------- sm/certdump.c | 1 + sm/certlist.c | 40 ++++++++++++++++--- sm/gpgsm.c | 2 +- sm/gpgsm.h | 2 +- sm/keylist.c | 35 +++++++++++++--- 17 files changed, 302 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3c3c700c5..013241648 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-04-15 Werner Koch <wk@g10code.com> + + * configure.ac: Require libksba 0.9.11. + 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * configure.ac: Check for /usr/bin/shred and define SHRED. diff --git a/NEWS b/NEWS index 101e04b98..d2334d9cd 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,13 @@ Noteworthy changes in version 1.9.16 ------------------------------------------------- + * gpg-agent does now support the ssh-agent protocol and thus allows + to use the pinentry as well as the OpenPGP smartcard with ssh. + + * New tool gpg-connect-agent as a genereal client for the gpg-agent. + + * New tool symcryptrun as a wrapper for certain encryption tools. + Noteworthy changes in version 1.9.15 (2005-01-13) ------------------------------------------------- @@ -226,7 +233,7 @@ Noteworthy changes in version 1.9.0 (2003-08-05) development branch. - Copyright 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright 2002, 2003, 2004, 2005 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 diff --git a/README b/README index c14534e93..7e44765a6 100644 --- a/README +++ b/README @@ -399,7 +399,7 @@ modes for gpgsm, here is the entire list of ways to specify a key: +Heinrich Heine duesseldorf - * [NEW] Exact match by subject's DN + * 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 @@ -411,7 +411,7 @@ modes for gpgsm, here is the entire list of ways to specify a key: /CN=Heinrich Heine,O=Poets,L=Paris,C=FR - * [NEW] Excact match by issuer's DN + * 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 @@ -422,10 +422,10 @@ modes for gpgsm, here is the entire list of ways to specify a key: #/CN=Root Cert,O=Poets,L=Paris,C=FR - * [NEW] Exact match by serial number and subject's DN + * Exact match by serial number and issuer's DN This is indicated by a hash mark, followed by the hexadecmal - representation of the serial number, the followed by a slahs and + representation of the serial number, the followed by a slash and the RFC2253 encoded DN of the issuer. See note above. Example: diff --git a/TODO b/TODO index 9efbe6a1c..26b2cee60 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,9 @@ -*- outline -*- +* IMPORTANT +Check that openpty and pty.h are available and build symcryptrun only +then. Run shred on the temporary files. + * src/base64 ** Make parsing more robust diff --git a/agent/command-ssh.c b/agent/command-ssh.c index f9ad2a80e..00c202078 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1741,6 +1741,7 @@ ssh_handler_request_identities (ctrl_t ctrl, /* Prepare buffer stream. */ +#warning Huh, sleep? why that? Anyway, this should be pth_sleep sleep (5); key_directory = NULL; diff --git a/common/ChangeLog b/common/ChangeLog index a42b07b4d..4688d2765 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2005-04-17 Werner Koch <wk@g10code.com> + + * sexputil.c (cmp_simple_canon_sexp): New. + (make_simple_sexp_from_hexstr): New. + 2005-04-07 Werner Koch <wk@g10code.com> * sexputil.c: New. diff --git a/common/sexputil.c b/common/sexputil.c index 853d7e58a..802916b44 100644 --- a/common/sexputil.c +++ b/common/sexputil.c @@ -61,3 +61,81 @@ keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, return err; } + +/* Compare two simple S-expressions like "(3:foo)". Returns 0 if they + are identical or !0 if they are not. Not that this function can't + be used for sorting. */ +int +cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b) +{ + unsigned long n1, n2; + char *endp; + + if (!a && !b) + return 0; /* Both are NULL, they are identical. */ + if (!a || !b) + return 1; /* One is NULL, they are not identical. */ + if (*a != '(' || *b != '(') + log_bug ("invalid S-exp in cmp_simple_canon_sexp\n"); + + a++; + n1 = strtoul (a, &endp, 10); + a = endp; + b++; + n2 = strtoul (b, &endp, 10); + b = endp; + + if (*a != ':' || *b != ':' ) + log_bug ("invalid S-exp in cmp_simple_canon_sexp\n"); + if (n1 != n2) + return 1; /* Not the same. */ + + for (a++, b++; n1; n1--, a++, b++) + if (*a != *b) + return 1; /* Not the same. */ + return 0; +} + + +/* Create a simple S-expression from the hex string at LIBNE. Returns + a newly allocated buffer with that canonical encoded S-expression + or NULL in case of an error. On return the number of characters + scanned in LINE will be stored at NSCANNED. This fucntions stops + converting at the first character not representing a hexdigit. Odd + numbers of hex digits are allowed; a leading zero is then + assumed. If no characters have been found, NULL is returned.*/ +unsigned char * +make_simple_sexp_from_hexstr (const char *line, size_t *nscanned) +{ + size_t n, len; + const char *s; + unsigned char *buf; + unsigned char *p; + char numbuf[50]; + + for (n=0, s=line; hexdigitp (s); s++, n++) + ; + if (nscanned) + *nscanned = n; + if (!n) + return NULL; + len = ((n+1) & ~0x01)/2; + sprintf (numbuf, "(%u:", (unsigned int)len); + buf = xtrymalloc (strlen (numbuf) + len + 1 + 1); + if (!buf) + return NULL; + p = stpcpy (buf, numbuf); + s = line; + if ((n&1)) + { + *p++ = xtoi_1 (s); + s++; + n--; + } + for (; n > 1; n -=2, s += 2) + *p++ = xtoi_2 (s); + *p++ = ')'; + *p = 0; /* (Not really neaded.) */ + + return buf; +} diff --git a/common/util.h b/common/util.h index 14180bec4..6a9b54ef5 100644 --- a/common/util.h +++ b/common/util.h @@ -123,6 +123,9 @@ gpg_error_t b64enc_finish (struct b64state *state); /*-- sexputil.c */ gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, unsigned char *grip); +int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b); +unsigned char *make_simple_sexp_from_hexstr (const char *line, + size_t *nscanned); /*-- homedir. c --*/ const char *default_homedir (void); diff --git a/configure.ac b/configure.ac index d331566be..d0ffa8ca4 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ NEED_LIBGCRYPT_VERSION=1.1.94 NEED_LIBASSUAN_VERSION=0.6.9 -NEED_KSBA_VERSION=0.9.7 +NEED_KSBA_VERSION=0.9.11 NEED_OPENSC_VERSION=0.8.0 diff --git a/sm/ChangeLog b/sm/ChangeLog index e74381bd5..7b67407ad 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,18 @@ +2005-04-17 Werner Koch <wk@g10code.com> + + * call-dirmngr.c (inq_certificate): Add new inquire SENDCERT_SKI. + * certlist.c (gpgsm_find_cert): Add new arg KEYID and implement + this filter. Changed all callers. + + * certchain.c (find_up_search_by_keyid): New helper. + (find_up): Also try using the AKI.keyIdentifier. + (find_up_external): Ditto. + +2005-04-15 Werner Koch <wk@g10code.com> + + * keylist.c (list_cert_raw): Print the subjectKeyIdentifier as + well as the keyIdentifier part of the authorityKeyIdentifier. + 2005-03-31 Werner Koch <wk@g10code.com> * call-dirmngr.c (start_dirmngr): Use PATHSEP_C instead of ':'. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 5988ea952..847e78490 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -1,5 +1,5 @@ /* call-dirmngr.c - communication with the dromngr - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -266,11 +266,25 @@ inq_certificate (void *opaque, const char *line) const unsigned char *der; size_t derlen; int issuer_mode = 0; + ksba_sexp_t ski = NULL; if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8])) { line += 8; } + else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12])) + { + size_t n; + + /* Send a certificate where a sourceKeyidentifier is included. */ + line += 12; + while (*line == ' ') + line++; + ski = make_simple_sexp_from_hexstr (line, &n); + line += n; + while (*line == ' ') + line++; + } else if (!strncmp (line, "SENDISSUERCERT", 14) && (line[14] == ' ' || !line[14])) { @@ -304,7 +318,7 @@ inq_certificate (void *opaque, const char *line) ksba_cert_t cert; - err = gpgsm_find_cert (line, &cert); + err = gpgsm_find_cert (line, ski, &cert); if (err) { log_error ("certificate not found: %s\n", gpg_strerror (err)); @@ -321,6 +335,7 @@ inq_certificate (void *opaque, const char *line) } } + xfree (ski); return rc; } @@ -717,7 +732,7 @@ run_command_inq_cb (void *opaque, const char *line) if (!*line) return ASSUAN_Inquire_Error; - err = gpgsm_find_cert (line, &cert); + err = gpgsm_find_cert (line, NULL, &cert); if (err) { log_error ("certificate not found: %s\n", gpg_strerror (err)); diff --git a/sm/certchain.c b/sm/certchain.c index 514ee23a5..a5fdbc622 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -266,6 +266,42 @@ check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist) } +/* Helper fucntion for find_up. This resets the key handle and search + for an issuer ISSUER with a subjectKeyIdentifier of KEYID. Returns + 0 obn success or -1 when not found. */ +static int +find_up_search_by_keyid (KEYDB_HANDLE kh, + const char *issuer, ksba_sexp_t keyid) +{ + int rc; + ksba_cert_t cert = NULL; + ksba_sexp_t subj = NULL; + + keydb_search_reset (kh); + while (!(rc = keydb_search_subject (kh, issuer))) + { + ksba_cert_release (cert); cert = NULL; + rc = keydb_get_cert (kh, &cert); + if (rc) + { + log_error ("keydb_get_cert() failed: rc=%d\n", rc); + rc = -1; + break; + } + xfree (subj); + if (!ksba_cert_get_subj_key_id (cert, NULL, &subj)) + { + if (!cmp_simple_canon_sexp (keyid, subj)) + break; /* Found matching cert. */ + } + } + + ksba_cert_release (cert); + xfree (subj); + return rc? -1:0; +} + + static void find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) { @@ -275,13 +311,13 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert) } - /* Helper for find_up(). Locate the certificate for ISSUER using an external lookup. KH is the keydb context we are currently using. On success 0 is returned and the certificate may be retrieved from - the keydb using keydb_get_cert().*/ + the keydb using keydb_get_cert(). KEYID is the keyIdentifier from + the AKI or NULL. */ static int -find_up_external (KEYDB_HANDLE kh, const char *issuer) +find_up_external (KEYDB_HANDLE kh, const char *issuer, ksba_sexp_t keyid) { int rc; strlist_t names = NULL; @@ -324,8 +360,13 @@ find_up_external (KEYDB_HANDLE kh, const char *issuer) /* The issuers are currently stored in the ephemeral key DB, so we temporary switch to ephemeral mode. */ old = keydb_set_ephemeral (kh, 1); - keydb_search_reset (kh); - rc = keydb_search_subject (kh, issuer); + if (keyid) + rc = find_up_search_by_keyid (kh, issuer, keyid); + else + { + keydb_search_reset (kh); + rc = keydb_search_subject (kh, issuer); + } keydb_set_ephemeral (kh, old); } return rc; @@ -343,9 +384,10 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) { ksba_name_t authid; ksba_sexp_t authidno; + ksba_sexp_t keyid; int rc = -1; - if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno)) + if (!ksba_cert_get_auth_key_id (cert, &keyid, &authid, &authidno)) { const char *s = ksba_name_enum (authid, 0); if (s && *authidno) @@ -369,28 +411,57 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) keydb_set_ephemeral (kh, old); } - /* If we didn't found it, try an external lookup. */ - if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) - rc = find_up_external (kh, issuer); } + if (rc == -1 && keyid && !find_next) + { + /* Not found by AIK.issuer_sn. Lets try the AIY.ki + instead. Loop over all certificates with that issuer as + subject and stop for the one with a matching + subjectKeyIdentifier. */ + rc = find_up_search_by_keyid (kh, issuer, keyid); + if (rc) + { + int old = keydb_set_ephemeral (kh, 1); + if (!old) + rc = find_up_search_by_keyid (kh, issuer, keyid); + keydb_set_ephemeral (kh, old); + } + if (rc) + rc = -1; /* Need to make sure to have this error code. */ + } + + /* If we still didn't found it, try an external lookup. */ + if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) + rc = find_up_external (kh, issuer, keyid); + /* Print a note so that the user does not feel too helpless when an issuer certificate was found and gpgsm prints BAD signature because it is not the correct one. */ if (rc == -1) { - log_info ("%sissuer certificate (#", find_next?"next ":""); - gpgsm_dump_serial (authidno); - log_printf ("/"); - gpgsm_dump_string (s); - log_printf (") not found using authorityKeyIdentifier\n"); + log_info ("%sissuer certificate ", find_next?"next ":""); + if (keyid) + { + log_printf ("{"); + gpgsm_dump_serial (keyid); + log_printf ("} "); + } + if (authidno) + { + log_printf ("(#"); + gpgsm_dump_serial (authidno); + log_printf ("/"); + gpgsm_dump_string (s); + log_printf (") "); + } + log_printf ("not found using authorityKeyIdentifier\n"); } else if (rc) log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc); + xfree (keyid); ksba_name_release (authid); xfree (authidno); - /* Fixme: There is no way to do an external lookup with - serial+issuer. */ } if (rc) /* Not found via authorithyKeyIdentifier, try regular issuer name. */ @@ -409,7 +480,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next) /* Still not found. If enabled, try an external lookup. */ if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next) - rc = find_up_external (kh, issuer); + rc = find_up_external (kh, issuer, NULL); return rc; } @@ -468,7 +539,7 @@ gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next) rc = keydb_get_cert (kh, r_next); if (rc) { - log_error ("failed to get cert: rc=%d\n", rc); + log_error ("keydb_get_cert() failed: rc=%d\n", rc); rc = gpg_error (GPG_ERR_GENERAL); } @@ -791,7 +862,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, rc = keydb_get_cert (kh, &issuer_cert); if (rc) { - log_error ("failed to get cert: rc=%d\n", rc); + log_error ("keydb_get_cert() failed: rc=%d\n", rc); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } @@ -818,6 +889,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, might have been used. This is required because some CAs are reusing the issuer and subject DN for new root certificates. */ + /* FIXME: Do this only if we don't have an + AKI.keyIdentifier */ rc = find_up (kh, subject_cert, issuer, 1); if (!rc) { @@ -1008,7 +1081,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) rc = keydb_get_cert (kh, &issuer_cert); if (rc) { - log_error ("failed to get cert: rc=%d\n", rc); + log_error ("keydb_get_cert() failed: rc=%d\n", rc); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } diff --git a/sm/certdump.c b/sm/certdump.c index cdf4edcc1..26510c70d 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -75,6 +75,7 @@ gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p) } +/* Dump the serial number or any other simple S-expression. */ void gpgsm_dump_serial (ksba_const_sexp_t p) { diff --git a/sm/certlist.c b/sm/certlist.c index 018ad47ff..b036a85d7 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -1,5 +1,5 @@ /* certlist.c - build list of certificates - * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -412,9 +412,11 @@ gpgsm_release_certlist (CERTLIST list) /* Like gpgsm_add_to_certlist, but look only for one certificate. No - chain validation is done */ + chain validation is done. If KEYID is not NULL it is take as an + additional filter value which must match the + subjectKeyIdentifier. */ int -gpgsm_find_cert (const char *name, ksba_cert_t *r_cert) +gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert) { int rc; KEYDB_SEARCH_DESC desc; @@ -429,10 +431,38 @@ gpgsm_find_cert (const char *name, ksba_cert_t *r_cert) rc = gpg_error (GPG_ERR_ENOMEM); else { + nextone: rc = keydb_search (kh, &desc, 1); if (!rc) - rc = keydb_get_cert (kh, r_cert); - if (!rc) + { + rc = keydb_get_cert (kh, r_cert); + if (!rc && keyid) + { + ksba_sexp_t subj; + + rc = ksba_cert_get_subj_key_id (*r_cert, NULL, &subj); + if (!rc) + { + if (cmp_simple_canon_sexp (keyid, subj)) + { + xfree (subj); + goto nextone; + } + xfree (subj); + /* Okay: Here we know that the certificate's + subjectKeyIdentifier matches the requested + one. */ + } + else if (gpg_err_code (rc) == GPG_ERR_NO_DATA) + goto nextone; + } + } + + /* If we don't have the KEYID filter we need to check for + ambigious search results. Note, that it is somehwat + reasonable to assume that a specification of a KEYID + won't lead to ambiguous names. */ + if (!rc && !keyid) { rc = keydb_search (kh, &desc, 1); if (rc == -1) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index ff404dc69..dae547702 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1566,7 +1566,7 @@ main ( int argc, char **argv) ksba_cert_t cert = NULL; char *grip = NULL; - rc = gpgsm_find_cert (*argv, &cert); + rc = gpgsm_find_cert (*argv, NULL, &cert); if (rc) ; else if (!(grip = gpgsm_get_keygrip_hexstring (cert))) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 17ad21ed6..aafc4815d 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -252,7 +252,7 @@ int gpgsm_add_cert_to_certlist (ctrl_t ctrl, ksba_cert_t cert, int gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, certlist_t *listaddr, int is_encrypt_to); void gpgsm_release_certlist (certlist_t list); -int gpgsm_find_cert (const char *name, ksba_cert_t *r_cert); +int gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert); /*-- keylist.c --*/ gpg_error_t gpgsm_list_keys (ctrl_t ctrl, STRLIST names, diff --git a/sm/keylist.c b/sm/keylist.c index aa6db46c3..8e1233341 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1,6 +1,6 @@ -/* keylist.c +/* keylist.c - Print certificates in various formats. * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -122,7 +122,7 @@ static struct { { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" }, /* X.509 id-ce */ - { "2.5.29.14", "subjectKeyIdentifier"}, + { "2.5.29.14", "subjectKeyIdentifier", 1}, { "2.5.29.15", "keyUsage", 1 }, { "2.5.29.16", "privateKeyUsagePeriod" }, { "2.5.29.17", "subjectAltName", 1 }, @@ -512,7 +512,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, { gpg_error_t err; size_t off, len; - ksba_sexp_t sexp; + ksba_sexp_t sexp, keyid; char *dn; ksba_isotime_t t; int idx, i; @@ -588,9 +588,27 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, fprintf (fp, " keyType: %u bit %s\n", nbits, algoname? algoname:"?"); } + /* subjectKeyIdentifier */ + fputs (" subjKeyId: ", fp); + err = ksba_cert_get_subj_key_id (cert, NULL, &keyid); + if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) + { + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + fputs ("[none]\n", fp); + else + { + gpgsm_print_serial (fp, keyid); + ksba_free (keyid); + putc ('\n', fp); + } + } + else + fputs ("[?]\n", fp); + + /* authorityKeyIdentifier */ fputs (" authKeyId: ", fp); - err = ksba_cert_get_auth_key_id (cert, NULL, &name, &sexp); + err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp); if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) { if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name) @@ -603,6 +621,13 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, print_names_raw (fp, -15, name); ksba_name_release (name); } + if (keyid) + { + fputs (" authKeyId.ki: ", fp); + gpgsm_print_serial (fp, keyid); + ksba_free (keyid); + putc ('\n', fp); + } } else fputs ("[?]\n", fp); -- cgit v1.2.3 From 92ee8d4886d726806a3c8c0269d55aef0fe9d7cd Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Tue, 19 Apr 2005 12:00:29 +0000 Subject: 2005-04-19 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c: Add --input option. --- tools/ChangeLog | 4 +++ tools/symcryptrun.c | 74 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 62a5e841c..7fd4c2899 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-04-19 Marcus Brinkmann <marcus@g10code.de> + + * symcryptrun.c: Add --input option. + 2005-04-15 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (TEMP_FAILURE_RETRY): Define if not defined. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index b35e4d7a5..8637987f8 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -124,6 +124,7 @@ enum cmd_and_opt_values oKeyfile, oDecrypt, oEncrypt, + oInput, }; @@ -132,23 +133,23 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, N_("@\nCommands:\n ") }, - { oDecrypt, "decrypt", 0, N_("decryption modus")}, - { oEncrypt, "encrypt", 0, N_("encryption modus")}, + { oDecrypt, "decrypt", 0, N_("decryption modus") }, + { oEncrypt, "encrypt", 0, N_("encryption modus") }, { 302, NULL, 0, N_("@\nOptions:\n ") }, - { oClass, "class", 2, N_("tool class (confucius)")}, - { oProgram, "program", 2, N_("program filename")}, - - { oKeyfile, "keyfile", 2, N_("secret key file (required)")}, + { oClass, "class", 2, N_("tool class (confucius)") }, + { oProgram, "program", 2, N_("program filename") }, + { oKeyfile, "keyfile", 2, N_("secret key file (required)") }, + { oInput, "inputfile", 2, N_("input file name (default stdin)") }, { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("quiet") }, - { oLogFile, "log-file", 2, N_("use a log file for the server")}, - { oOptions, "options" , 2, N_("|FILE|read options from FILE")}, + { oLogFile, "log-file", 2, N_("use a log file for the server") }, + { oOptions, "options" , 2, N_("|FILE|read options from FILE") }, /* Hidden options. */ - { oNoVerbose, "no-verbose", 0, "@"}, + { oNoVerbose, "no-verbose", 0, "@" }, { oHomedir, "homedir", 2, "@" }, { oNoOptions, "no-options", 0, "@" },/* shortcut for --options /dev/null */ @@ -166,6 +167,7 @@ struct char *class; char *program; char *keyfile; + char *input; } opt; @@ -755,22 +757,31 @@ confucius_main (int mode) int res; char *tmpdir; char *infile; + int infile_from_stdin = 0; char *outfile; tmpdir = confucius_mktmpdir (); if (!tmpdir) return 1; - - /* TMPDIR + "/" + "in" + "\0". */ - infile = malloc (strlen (tmpdir) + 1 + 2 + 1); - if (!infile) + + if (opt.input && !(opt.input[0] == '-' && opt.input[1] == '\0')) + infile = xstrdup (opt.input); + else { - log_error (_("cannot allocate infile string: %s\n"), strerror (errno)); - rmdir (tmpdir); - return 1; + infile_from_stdin = 1; + + /* TMPDIR + "/" + "in" + "\0". */ + infile = malloc (strlen (tmpdir) + 1 + 2 + 1); + if (!infile) + { + log_error (_("cannot allocate infile string: %s\n"), + strerror (errno)); + rmdir (tmpdir); + return 1; + } + strcpy (infile, tmpdir); + strcat (infile, "/in"); } - strcpy (infile, tmpdir); - strcat (infile, "/in"); /* TMPDIR + "/" + "out" + "\0". */ outfile = malloc (strlen (tmpdir) + 1 + 3 + 1); @@ -784,14 +795,17 @@ confucius_main (int mode) strcpy (outfile, tmpdir); strcat (outfile, "/out"); - /* Create INFILE and fill it with content. */ - res = confucius_copy_file ("-", infile, mode == oEncrypt); - if (res) + if (infile_from_stdin) { - free (outfile); - free (infile); - rmdir (tmpdir); - return res; + /* Create INFILE and fill it with content. */ + res = confucius_copy_file ("-", infile, mode == oEncrypt); + if (res) + { + free (outfile); + free (infile); + rmdir (tmpdir); + return res; + } } /* Run the engine and thus create the output file, handling @@ -800,7 +814,8 @@ confucius_main (int mode) if (res) { remove_file (outfile, mode == oDecrypt); - remove_file (infile, mode == oEncrypt); + if (infile_from_stdin) + remove_file (infile, mode == oEncrypt); free (outfile); free (infile); rmdir (tmpdir); @@ -812,7 +827,8 @@ confucius_main (int mode) if (res) { remove_file (outfile, mode == oDecrypt); - remove_file (infile, mode == oEncrypt); + if (infile_from_stdin) + remove_file (infile, mode == oEncrypt); free (outfile); free (infile); rmdir (tmpdir); @@ -820,7 +836,8 @@ confucius_main (int mode) } remove_file (outfile, mode == oDecrypt); - remove_file (infile, mode == oEncrypt); + if (infile_from_stdin) + remove_file (infile, mode == oEncrypt); free (outfile); free (infile); rmdir (tmpdir); @@ -915,6 +932,7 @@ main (int argc, char **argv) case oClass: opt.class = pargs.r.ret_str; break; case oProgram: opt.program = pargs.r.ret_str; break; case oKeyfile: opt.keyfile = pargs.r.ret_str; break; + case oInput: opt.input = pargs.r.ret_str; break; case oLogFile: logfile = pargs.r.ret_str; break; -- cgit v1.2.3 From a78c5e9673bbbee0ec277bbd39a5e38ebaf41052 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Wed, 20 Apr 2005 14:47:19 +0000 Subject: 2005-04-20 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_request_identities): Removed debugging code (sleep call), which was commited unintenionally. --- agent/ChangeLog | 5 +++++ agent/command-ssh.c | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 5a709a5db..e30b2cbc5 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-04-20 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_handler_request_identities): Removed + debugging code (sleep call), which was commited unintenionally. + 2005-04-03 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_request_spec): New member: secret_input. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 00c202078..133dd01dd 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1741,9 +1741,6 @@ ssh_handler_request_identities (ctrl_t ctrl, /* Prepare buffer stream. */ -#warning Huh, sleep? why that? Anyway, this should be pth_sleep - sleep (5); - key_directory = NULL; key_secret = NULL; key_public = NULL; -- cgit v1.2.3 From cb1840720ab761b3e7fdccfcd8a13af40957989e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 20 Apr 2005 18:46:51 +0000 Subject: (Agent Configuration): New section. --- doc/ChangeLog | 6 +++- doc/gnupg.texi | 2 +- doc/gpg-agent.texi | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- doc/gpgsm.texi | 2 +- 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 07f94f338..4ad8b18c8 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-04-20 Werner Koch <wk@g10code.com> + + * gpg-agent.texi (Agent Configuration): New section. + 2005-02-24 Werner Koch <wk@g10code.com> * tools.texi (gpg-connect-agent): New. @@ -171,7 +175,7 @@ * Makefile.am, gpgsm.texi: New. - Copyright 2002 Free Software Foundation, Inc. + Copyright 2002, 2004, 2005 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 diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 5c6925260..4c30980b3 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -22,7 +22,7 @@ Published by the Free Software Foundation@* Boston, MA 02111-1307 USA @end iftex -Copyright @copyright{} 2002, 2004 Free Software Foundation, Inc. +Copyright @copyright{} 2002, 2004, 2005 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 17bd59c7a..52f1fe0d8 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -11,7 +11,7 @@ @c man begin DESCRIPTION @command{gpg-agent} is a daemon to manage secret (private) keys -independelty from any protocol. It is used as a backend for +independently from any protocol. It is used as a backend for @command{gpg} and @command{gpgsm} as well as for a couple of other utilities. @@ -71,6 +71,7 @@ one (e.g. @file{/usr/bin/pinentry}). @menu * Agent Commands:: List of all commands. * Agent Options:: List of all options. +* Agent Configuration:: Configuration files. * Agent Signals:: Use of some signals. * Agent Examples:: Some usage examples. * Agent Protocol:: The protocol the agent uses. @@ -123,6 +124,7 @@ $ eval `gpg-agent --daemon` @table @gnupgtabopt +@anchor{option --options} @item --options @var{file} @opindex options Reads configuration from @var{file} instead of from the default @@ -130,6 +132,7 @@ 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. +@anchor{option --homedir} @item --homedir @var{dir} @opindex homedir Set the name of the home directory to @var{dir}. If his option is not @@ -255,10 +258,11 @@ seeing what the agent actually does. Don't allow multiple connections. This option is in general not very useful. +@anchor{option --allow-mark-trusted} @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 +@file{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 @@ -289,6 +293,12 @@ Use program @var{filename} as the Smartcard daemon. The default is installation dependend and can be shown with the @code{--version} command. +@item --disable-scdaemon +@opindex disable-scdaemon +Do not make use of the scdaemon tool. This option has the effect of +disabling the ability to do smartcard operations. Note, that enabling +this option at runtime does not kill an already forked scdaemon. + @item --use-standard-socket @itemx --no-use-standard-socket @opindex use-standard-socket @@ -326,6 +336,7 @@ 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. +@anchor{option --enable-ssh-support} @item --enable-ssh-support @opindex enable-ssh-support @@ -359,6 +370,87 @@ gpg-agent has been started. All the long options may also be given in the configuration file after stripping off the two leading dashes. + +@c man begin FILES + +@node Agent Configuration +@section Configuration + +There are a few configuration files needed for the operation of the +agent. By default they may all be found in the current home directory +(@pxref{option --homedir}). + +@table @file + +@item gpg-agent.conf +@cindex gpg-agent.conf + This is the standard configuration file read by @command{gpg-agent} on + startup. It may contain any valid long option; the leading + two dashes may not be entered and the option may not be abbreviated. + This file is also read after a @code{SIGHUP} however only a few + options will actually have an effect. This default name may be + changed on the command line (@pxref{option --options}). + +@item trustlist.txt + This is the list of trusted keys. Comment lines, indicated by a leading + hash mark, as well as empty lines are ignored. To mark a key as trusted + you need to enter its fingerprint followed by a space and a capital + letter @code{S}. Colons may optionally be used to separate the bytes of + a fingerprint; this allows to cut and paste the fingeperint from a key + listing output. + + Here is an example where two keys are marked as ultimately trusted: + + @example + # CN=Wurzel ZS 3,O=Intevation GmbH,C=DE + A6935DD34EF3087973C706FC311AA2CCF733765B S + + # CN=PCA-1-Verwaltung-02/O=PKI-1-Verwaltung/C=DE + DC:BD:69:25:48:BD:BB:7E:31:6E:BB:80:D3:00:80:35:D4:F8:A6:CD S + @end example + + Before entering a key into this file, you need to ensure its + authenticity. How to do this depends on your organisation; your + administrator might have already entered those keys which are deemed + trustworthy enough into this file. Places where to look for the + fingerprint of a root certificate are letters received from the CA or + the website of the CA (after making 100% sure that this is indeed the + website of that CA). You may want to consider allowing interactive + updates of this file by using the @xref{option --allow-mark-trusted}. + This is however not as secure as maintaining this file manually. It is + even advisable to change the permissions to read-only so that this file + can't be changed inadvertently. + + @item sshcontrol + + This file is used when support for the secure shell agent protocol has + been enabled (@pxref{option --enable-ssh-support}). Only keys present in + this file are used in the SSH protocol. The @command{ssh-add} tool y be + used to add new entries to this file; you may also add them manually. + Comment lines, indicated by a leading hash mark, as well as empty lines + are ignored. An entry starts with optional white spaces, followed by + the keygrip of the key given as 40 hex digits, optionally followed by + the caching TTL in seconds and another optional field for arbitrary + flags. A @code{!} may be prepended to the keygrip to disable this + entry. + + The follwoing example lists exactly one key. Note that keys available + through a OpenPGP smartcard in the active smartcard reader are implictly + added to this list; i.e. there is no need to list them. + + @example + # Key added on 2005-02-25 15:08:29 + 5A6592BF45DC73BD876874A28FD4639282E29B52 0 + @end example +@end table + +Note that on larger installations, it is useful to put predefined +files into the directory @file{/etc/skel/.gnupg/} so that newly created +users start up with a working configuration. For existing users the +a small helper script is provied to create these files (@pxref{addgnupghome}). + + + @c @c Agent Signals @c diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 09fd7d660..df2f71bce 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -12,7 +12,7 @@ @command{gpgsm} is a tool similar to @command{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. +protocol. It is mainly used as a backend for S/MIME mail processing. @command{gpgsm} includes a full features certificate management and complies with all rules defined for the German Sphinx project. -- cgit v1.2.3 From 526ed521a75d7617fd9fd7a9782a20d4c52bd985 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 20 Apr 2005 19:19:24 +0000 Subject: . --- agent/ChangeLog | 12 +++++++++ agent/agent.h | 1 + agent/call-scd.c | 3 +++ agent/gpg-agent.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++------ agent/minip12.c | 9 ++++--- 5 files changed, 93 insertions(+), 11 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index e30b2cbc5..5f26fc624 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -3,6 +3,18 @@ * command-ssh.c (ssh_handler_request_identities): Removed debugging code (sleep call), which was commited unintenionally. +2005-04-20 Werner Koch <wk@g10code.com> + + * minip12.c (parse_bag_encrypted_data): Fix the unpadding hack. + + * gpg-agent.c: New option --disable-scdaemon. + (handle_connections): Add time event to drive ... + (handle_tick): New function. + (main): Record the parent PID. Fixed segv when using ssh and a + command. + + * call-scd.c (start_scd): Take care of this option. + 2005-04-03 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_request_spec): New member: secret_input. diff --git a/agent/agent.h b/agent/agent.h index e12a02b6e..298b5b142 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -66,6 +66,7 @@ struct { pinentry. */ const char *scdaemon_program; /* Filename of the program to handle smartcard tasks. */ + int disable_scdaemon; /* Never use the SCdaemon. */ int no_grab; /* Don't let the pinentry grab the keyboard */ unsigned long def_cache_ttl; unsigned long max_cache_ttl; diff --git a/agent/call-scd.c b/agent/call-scd.c index 4d1498b05..8373fd46d 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -137,6 +137,9 @@ start_scd (ctrl_t ctrl) int no_close_list[3]; int i; + if (opt.disable_scdaemon) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + #ifdef USE_GNU_PTH if (!pth_mutex_acquire (&scd_lock, 0, NULL)) { diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 113489306..7c682ada7 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -94,7 +94,8 @@ enum cmd_and_opt_values oAllowPresetPassphrase, oKeepTTY, oKeepDISPLAY, - oSSHSupport + oSSHSupport, + oDisableScdaemon }; @@ -128,6 +129,7 @@ static ARGPARSE_OPTS opts[] = { N_("|PGM|use PGM as the PIN-Entry program") }, { oScdaemonProgram, "scdaemon-program", 2 , N_("|PGM|use PGM as the SCdaemon program") }, + { oDisableScdaemon, "disable-scdaemon", 0, N_("do not use the SCdaemon") }, { oDisplay, "display", 2, "@" }, { oTTYname, "ttyname", 2, "@" }, @@ -187,6 +189,11 @@ static const char *debug_level; the log file after a SIGHUP if it didn't changed. Malloced. */ static char *current_logfile; +/* The handle_tick() function may test whether a parent is still + runing. We record the PID of the parent here or -1 if it should be + watched. */ +static pid_t parent_pid = (pid_t)(-1); + /* Local prototypes. */ @@ -387,6 +394,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.max_cache_ttl = MAX_CACHE_TTL; opt.ignore_cache_for_signing = 0; opt.allow_mark_trusted = 0; + opt.disable_scdaemon = 0; return 1; } @@ -415,6 +423,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oPinentryProgram: opt.pinentry_program = pargs->r.ret_str; break; case oScdaemonProgram: opt.scdaemon_program = pargs->r.ret_str; break; + case oDisableScdaemon: opt.disable_scdaemon = 1; break; case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break; case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; @@ -740,6 +749,8 @@ main (int argc, char **argv ) GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); printf ("allow-mark-trusted:%lu:\n", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); + printf ("disable-scdaemon:%lu:\n", + GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME); agent_exit (0); } @@ -819,6 +830,11 @@ main (int argc, char **argv ) else fd_ssh = -1; + /* If we are going to exec a program in the parent, we record + the PID, so that the child may check whether the program is + still alive. */ + if (argc) + parent_pid = getpid (); fflush (NULL); #ifdef HAVE_W32_SYSTEM @@ -878,14 +894,14 @@ main (int argc, char **argv ) kill (pid, SIGTERM ); exit (1); } - if (putenv (infostr_ssh_sock)) + if (opt.ssh_support && putenv (infostr_ssh_sock)) { log_error ("failed to set environment: %s\n", strerror (errno) ); kill (pid, SIGTERM ); exit (1); } - if (putenv (infostr_ssh_pid)) + if (opt.ssh_support && putenv (infostr_ssh_pid)) { log_error ("failed to set environment: %s\n", strerror (errno) ); @@ -922,8 +938,7 @@ main (int argc, char **argv ) printf ("%s; export SSH_AGENT_PID;\n", infostr_ssh_pid); } } - /* Note: teh standard free is here correct. */ - free (infostr); + free (infostr); /* (Note that a vanilla free is here correct.) */ if (opt.ssh_support) { free (infostr_ssh_sock); @@ -1311,6 +1326,27 @@ create_directories (void) #ifdef USE_GNU_PTH +/* This is the worker for the ticker. It is called every few seconds + and may only do fast operations. */ +static void +handle_tick (void) +{ +#ifndef HAVE_W32_SYSTEM + if (parent_pid != (pid_t)(-1)) + { + if (kill (parent_pid, 0)) + { + shutdown_pending = 2; + log_info ("parent process died - shutting down\n"); + log_info ("%s %s stopped\n", strusage(11), strusage(13) ); + cleanup (); + agent_exit (0); + } + } +#endif /*HAVE_W32_SYSTEM*/ +} + + static void handle_signal (int signo) { @@ -1409,7 +1445,7 @@ static void handle_connections (int listen_fd, int listen_fd_ssh) { pth_attr_t tattr; - pth_event_t ev; + pth_event_t ev, time_ev; sigset_t sigs; int signo; struct sockaddr_un paddr; @@ -1434,6 +1470,7 @@ handle_connections (int listen_fd, int listen_fd_ssh) #else ev = NULL; #endif + time_ev = NULL; FD_ZERO (&fdset); FD_SET (listen_fd, &fdset); @@ -1456,16 +1493,33 @@ handle_connections (int listen_fd, int listen_fd_ssh) continue; } + /* Create a timeout event if needed. */ + if (!time_ev) + time_ev = pth_event (PTH_EVENT_TIME, pth_timeout (2, 0)); + /* POSIX says that fd_set should be implemented as a structure, thus a simple assignment is fine to copy the entire set. */ read_fdset = fdset; + if (time_ev) + pth_event_concat (ev, time_ev, NULL); ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev); + if (time_ev) + pth_event_isolate (time_ev); + if (ret == -1) { - if (pth_event_occurred (ev)) + if (pth_event_occurred (ev) + || (time_ev && pth_event_occurred (time_ev))) { - handle_signal (signo); + if (pth_event_occurred (ev)) + handle_signal (signo); + if (time_ev && pth_event_occurred (time_ev)) + { + pth_event_free (time_ev, PTH_FREE_ALL); + time_ev = NULL; + handle_tick (); + } continue; } log_error (_("pth_select failed: %s - waiting 1s\n"), @@ -1479,6 +1533,13 @@ handle_connections (int listen_fd, int listen_fd_ssh) handle_signal (signo); } + if (time_ev && pth_event_occurred (time_ev)) + { + pth_event_free (time_ev, PTH_FREE_ALL); + time_ev = NULL; + handle_tick (); + } + if (FD_ISSET (listen_fd, &read_fdset)) { plen = sizeof paddr; @@ -1515,6 +1576,8 @@ handle_connections (int listen_fd, int listen_fd_ssh) } pth_event_free (ev, PTH_FREE_ALL); + if (time_ev) + pth_event_free (time_ev, PTH_FREE_ALL); cleanup (); log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); } diff --git a/agent/minip12.c b/agent/minip12.c index fc9b26dd1..5ca85033d 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -486,6 +486,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, buffer = p = plain; /* { */ +/* # warning debug code is enabled */ /* FILE *fp = fopen ("tmp-rc2-plain.der", "wb"); */ /* if (!fp || fwrite (p, n, 1, fp) != 1) */ /* exit (2); */ @@ -586,8 +587,10 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, } /* Ugly hack to cope with the padding: Forget about the rest if - that it is less than the cipher's block length. */ - if (n < 8) + that is less or equal to the cipher's block length. We can + reasonable assume that all valid data will be longer than + just one block. */ + if (n <= 8) n = 0; /* Skip the optional SET with the pkcs12 cert attributes. */ @@ -602,7 +605,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, { /* The optional SET. */ p += ti.length; n -= ti.length; - if (n < 8) + if (n <= 8) n = 0; if (n && parse_tag (&p, &n, &ti)) goto bailout; -- cgit v1.2.3 From 314c234e7d1320bcd13e5130c3d7074b19979e46 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 21 Apr 2005 07:16:41 +0000 Subject: (gpgsm_validate_chain): Check revocations even for expired certificates. This is required because on signature verification an expired key is fine whereas a revoked one is not. --- sm/ChangeLog | 16 ++++++++++++++++ sm/Makefile.am | 3 ++- sm/certchain.c | 9 +++------ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 7b67407ad..b209b9d4b 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,19 @@ +2005-04-21 Werner Koch <wk@g10code.com> + + * certchain.c (gpgsm_validate_chain): Check revocations even for + expired certificates. This is required because on signature + verification an expired key is fine whereas a revoked one is not. + +2005-04-20 Werner Koch <wk@g10code.com> + + * Makefile.am (AM_CFLAGS): Add PTH_CFLAGS as noted by several folks. + +2005-04-19 Werner Koch <wk@g10code.com> + + * certchain.c (check_cert_policy): Print the diagnostic for a open + failure of policies.txt only in verbose mode or when it is not + ENOENT. + 2005-04-17 Werner Koch <wk@g10code.com> * call-dirmngr.c (inq_certificate): Add new inquire SENDCERT_SKI. diff --git a/sm/Makefile.am b/sm/Makefile.am index d4f972527..f1a116ab5 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -21,7 +21,8 @@ bin_PROGRAMS = gpgsm -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) \ + $(PTH_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl include $(top_srcdir)/am/cmacros.am diff --git a/sm/certchain.c b/sm/certchain.c index a5fdbc622..2e491f590 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -175,8 +175,9 @@ check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist) fp = fopen (opt.policy_file, "r"); if (!fp) { - log_error ("failed to open `%s': %s\n", - opt.policy_file, strerror (errno)); + if (opt.verbose || errno != ENOENT) + log_info (_("failed to open `%s': %s\n"), + opt.policy_file, strerror (errno)); xfree (policies); /* With no critical policies this is only a warning */ if (!any_critical) @@ -816,8 +817,6 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Check for revocations etc. */ if ((flags & 1)) rc = 0; - else if (any_expired) - ; /* Don't bother to run the expensive CRL check then. */ else rc = is_cert_still_valid (ctrl, lm, fp, subject_cert, subject_cert, @@ -953,8 +952,6 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Check for revocations etc. */ if ((flags & 1)) rc = 0; - else if (any_expired) - ; /* Don't bother to run the expensive CRL check then. */ else rc = is_cert_still_valid (ctrl, lm, fp, subject_cert, issuer_cert, -- cgit v1.2.3 From 3ff9a743bf6faeb99e8ee6113fe54af4f34cc288 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 21 Apr 2005 09:33:07 +0000 Subject: * configure.ac: Do not build gpg by default. * gpgsm.c: New options --{enable,disable}-trusted-cert-crl-check. * certchain.c (gpgsm_validate_chain): Make use of it. * certchain.c (gpgsm_validate_chain): Check revocations even for expired certificates. This is required because on signature verification an expired key is fine whereas a revoked one is not. * gpgconf-comp.c: Add gpgsm option disable-trusted-cert-crl-check. --- ChangeLog | 9 +++++++++ README | 5 +++-- TODO | 29 ++++++++--------------------- configure.ac | 11 ++++++++++- doc/gpgsm.texi | 12 ++++++++++++ scd/ChangeLog | 4 ++++ scd/ccid-driver.c | 2 +- scd/command.c | 26 +++++++++++++------------- sm/ChangeLog | 3 +++ sm/certchain.c | 10 ++++++---- sm/gpgsm.c | 12 ++++++++++++ sm/gpgsm.h | 1 + tools/ChangeLog | 8 ++++++++ tools/gpgconf-comp.c | 6 ++++++ tools/symcryptrun.c | 2 +- 15 files changed, 97 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 013241648..cfe0f863b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-04-21 Werner Koch <wk@g10code.com> + + * configure.ac: Do not build gpg by default. + +2005-04-20 Werner Koch <wk@g10code.com> + + * configure.ac: Test whether GPG_ERR_LOCKED is declared and + provide a replacement if not. + 2005-04-15 Werner Koch <wk@g10code.com> * configure.ac: Require libksba 0.9.11. diff --git a/README b/README index 7e44765a6..7bb83f1f2 100644 --- a/README +++ b/README @@ -11,7 +11,8 @@ available in 1.9. You should use this GnuPG version if you want to use the gpg-agent or gpgsm (the S/MIME variant of gpg). Note that the gpg-agent is also -helpful when using the standard gpg versions (1.2.x or 1.3.x). +helpful when using the standard gpg versions (1.3.x as well as some of +the old 1.2.x). BUILD INSTRUCTIONS @@ -51,7 +52,7 @@ 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 or 1.3 installation. gpg2 behaves just like gpg; it is however suggested to -keep using gpg 1.2.x or 1.3.x. +keep using gpg 1.2.x or 1.3.x. gpg2 is not even build by default. 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. diff --git a/TODO b/TODO index 26b2cee60..6a0e9b18e 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,5 @@ -*- outline -*- -* IMPORTANT -Check that openpty and pty.h are available and build symcryptrun only -then. Run shred on the temporary files. - - * src/base64 ** Make parsing more robust Currently we don't cope with overlong lines in the best way. @@ -23,14 +18,7 @@ might want to have an agent context for each service request * 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/certlist.c -** ocspSigning usage is not fully implemented - We should review the entire CRL and OCSP validation system. - Okay. This has been fixed in dirmngr when running it in system - daemon mode. * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution @@ -58,8 +46,6 @@ might want to have an agent context for each service request ** A SIGHUP should also restart the scdaemon But do this only after all connections terminated. As of now we only send a RESET. -** Watch the child process if not invoked as a daemon - and terminate after the child has terminated * agent/command.c ** Make sure that secure memory is used where appropriate @@ -69,7 +55,8 @@ might want to have an agent context for each service request ** Support DSA * agent/divert-scd.c - Remove the agent_reset_scd kludge. + Remove the agent_reset_scd kludge. We will do this after Scdaemon + has been changed to allow multiple sessions. Currently in progress. * Move pkcs-1 encoding into libgcrypt. @@ -93,11 +80,7 @@ might want to have an agent context for each service request ** Explain how to setup a root CA key as trusted ** Explain how trustlist.txt might be managed. ** Write a script to generate man pages from texi. - -* Requirements by the BSI -** Support authorityKeyIdentifier.keyIdentifier - This needs support in libksba/src/cert.c as well as in sm/*.c. - Need test certs as well. Same goes for CRL authorityKeyIdentifier. + In progress (yatm) * Windows port @@ -108,5 +91,9 @@ might want to have an agent context for each service request ** No card status notifications. -* [scdaemon] release the card after use so that gpg 1.4 is abale to access it +* scd/ +** Release the card after use so that gpg 1.4 is able to access it + This won't be a sufficient change. we need to change gpg 1.4 to make + use of the agent. Work is underway. + diff --git a/configure.ac b/configure.ac index d0ffa8ca4..8654785ee 100644 --- a/configure.ac +++ b/configure.ac @@ -62,7 +62,7 @@ have_ksba=no have_opensc=no have_pth=no -GNUPG_BUILD_PROGRAM(gpg, yes) +GNUPG_BUILD_PROGRAM(gpg, no) GNUPG_BUILD_PROGRAM(gpgsm, yes) GNUPG_BUILD_PROGRAM(agent, yes) GNUPG_BUILD_PROGRAM(scdaemon, yes) @@ -313,6 +313,11 @@ AH_BOTTOM([ #define EXEC_TEMPFILE_ONLY #endif +/* Temporary hacks to avoid requring a libgpg-error update. */ +#if !HAVE_DECL_GPG_ERR_LOCKED +#define GPG_ERR_LOCKED 173 +#endif + ]) AM_MAINTAINER_MODE @@ -437,6 +442,10 @@ AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) # AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION", have_gpg_error=yes,have_gpg_error=no) +_tmp_gpg_error_save_cflags="$CFLAGS" +CFLAGS="$CFLAGS $GPG_ERROR_CFLAGS" +AC_CHECK_DECLS(GPG_ERR_LOCKED,,,[#include <gpg-error.h>]) +CFLAGS="${_tmp_gpg_error_save_cflags}" # diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index df2f71bce..ba98ae87c 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -315,6 +315,18 @@ 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 --enable-trusted-cert-crl-check +@itemx --disable-trusted-cert-crl-check +@opindex enable-trusted-cert-crl-check +@opindex disable-trusted-cert-crl-check +By default the @acronym{CRL} for trusted root certificates are checked +like for any other certificates. This allows a CA to revoke its own +certificates voluntary without the need of putting all ever issued +certificates into a CRL. The disable option may be used to switch this +extra check off. Due to the caching done by the Dirmngr, there won't be +any noticeable performance gain. Note, that this also disables possible +OCSP checks for trusted root certificates. + @item --force-crl-refresh @opindex force-crl-refresh Tell the dirmngr to reload the CRL for each request. For better diff --git a/scd/ChangeLog b/scd/ChangeLog index 9d246ffca..c5a1062b8 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2005-04-20 Werner Koch <wk@g10code.com> + + * command.c: Use GPG_ERR_LOCKED instead of EBUSY. + 2005-04-14 Werner Koch <wk@g10code.com> * app-openpgp.c (retrieve_key_material): Rewritten. Return a diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 13e11e4bc..e9666ee17 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1274,7 +1274,7 @@ ccid_poll (ccid_driver_t handle) } -/* Note that this fucntion won't return the error codes NO_CARD or +/* Note that this function won't return the error codes NO_CARD or CARD_INACTIVE */ int ccid_slot_status (ccid_driver_t handle, int *statusbits) diff --git a/scd/command.c b/scd/command.c index 9881b1be0..7d777d8b7 100644 --- a/scd/command.c +++ b/scd/command.c @@ -263,7 +263,7 @@ open_card (ctrl_t ctrl, const char *apptype) return 0; /* Already initialized using a card context. */ if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); if (ctrl->reader_slot != -1) slot = ctrl->reader_slot; @@ -360,7 +360,7 @@ cmd_serialno (assuan_context_t ctx, char *line) if (ctrl->server_local->card_removed) { if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); do_reset (ctrl, 0); } @@ -745,7 +745,7 @@ cmd_setdata (assuan_context_t ctx, char *line) unsigned char *buf; if (locked_session && locked_session != ctrl->server_local) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); /* Parse the hexstring. */ for (p=line,n=0; hexdigitp (p); p++, n++) @@ -817,7 +817,7 @@ cmd_pksign (assuan_context_t ctx, char *line) char *keyidstr; if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); if ((rc = open_card (ctrl, NULL))) return rc; @@ -871,7 +871,7 @@ cmd_pkauth (assuan_context_t ctx, char *line) char *keyidstr; if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); if ((rc = open_card (ctrl, NULL))) return rc; @@ -921,7 +921,7 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line) char *keyidstr; if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); if ((rc = open_card (ctrl, NULL))) return rc; @@ -1021,7 +1021,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line) char *line, *linebuf; if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); if ((rc = open_card (ctrl, NULL))) return rc; @@ -1076,7 +1076,7 @@ cmd_genkey (assuan_context_t ctx, char *line) int force = has_option (line, "--force"); if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); /* Skip over options. */ while ( *line == '-' && line[1] == '-' ) @@ -1165,7 +1165,7 @@ cmd_passwd (assuan_context_t ctx, char *line) int reset_mode = has_option (line, "--reset"); if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); /* Skip over options. */ while (*line == '-' && line[1] == '-') @@ -1212,7 +1212,7 @@ cmd_checkpin (assuan_context_t ctx, char *line) char *keyidstr; if ( IS_LOCKED (ctrl) ) - return gpg_error (GPG_ERR_EBUSY); + return gpg_error (GPG_ERR_LOCKED); if ((rc = open_card (ctrl, NULL))) return rc; @@ -1244,7 +1244,7 @@ cmd_checkpin (assuan_context_t ctx, char *line) Grant exclusive card access to this session. Note that there is no lock counter used and a second lock from the same session will get ignore. A single unlock (or RESET) unlocks the session. - Return GPG_ERR_EBUSY if another session has locked the reader. + Return GPG_ERR_LOCKED if another session has locked the reader. If the option --wait is given the command will wait until a lock has been released. @@ -1259,7 +1259,7 @@ cmd_lock (assuan_context_t ctx, char *line) if (locked_session) { if (locked_session != ctrl->server_local) - rc = gpg_error (GPG_ERR_EBUSY); + rc = gpg_error (GPG_ERR_LOCKED); } else locked_session = ctrl->server_local; @@ -1293,7 +1293,7 @@ cmd_unlock (assuan_context_t ctx, char *line) if (locked_session) { if (locked_session != ctrl->server_local) - rc = gpg_error (GPG_ERR_EBUSY); + rc = gpg_error (GPG_ERR_LOCKED); else locked_session = NULL; } diff --git a/sm/ChangeLog b/sm/ChangeLog index b209b9d4b..aa8e8671f 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,8 @@ 2005-04-21 Werner Koch <wk@g10code.com> + * gpgsm.c: New options --{enable,disable}-trusted-cert-crl-check. + * certchain.c (gpgsm_validate_chain): Make use of it. + * certchain.c (gpgsm_validate_chain): Check revocations even for expired certificates. This is required because on signature verification an expired key is fine whereas a revoked one is not. diff --git a/sm/certchain.c b/sm/certchain.c index 2e491f590..02e5b409f 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -752,13 +752,13 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, } - /* Is this a self-signed certificate? */ + /* Is this a self-issued certificate? */ if (subject && !strcmp (issuer, subject)) { /* Yes. */ if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) { do_list (1, lm, fp, - _("selfsigned certificate has a BAD signature")); + _("self-signed certificate has a BAD signature")); if (DBG_X509) { gpgsm_dump_cert ("self-signing cert", subject_cert); @@ -816,7 +816,9 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, /* Check for revocations etc. */ if ((flags & 1)) - rc = 0; + ; + else if (opt.no_trusted_cert_crl_check) + ; else rc = is_cert_still_valid (ctrl, lm, fp, subject_cert, subject_cert, @@ -1045,7 +1047,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) rc = gpgsm_check_cert_sig (cert, cert); if (rc) { - log_error ("selfsigned certificate has a BAD signature: %s\n", + log_error ("self-signed certificate has a BAD signature: %s\n", gpg_strerror (rc)); if (DBG_X509) { diff --git a/sm/gpgsm.c b/sm/gpgsm.c index dae547702..fb6533030 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -130,6 +130,8 @@ enum cmd_and_opt_values { oDisableCRLChecks, oEnableCRLChecks, + oDisableTrustedCertCRLCheck, + oEnableTrustedCertCRLCheck, oForceCRLRefresh, oDisableOCSP, @@ -285,6 +287,8 @@ static ARGPARSE_OPTS opts[] = { N_("use system's dirmngr if available")}, { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, + { oDisableTrustedCertCRLCheck, "disable-trusted-cert-crl-check", 0, "@"}, + { oEnableTrustedCertCRLCheck, "enable-trusted-cert-crl-check", 0, "@"}, { oForceCRLRefresh, "force-crl-refresh", 0, "@"}, { oDisableOCSP, "disable-ocsp", 0, "@" }, @@ -973,6 +977,12 @@ main ( int argc, char **argv) case oEnableCRLChecks: opt.no_crl_check = 0; break; + case oDisableTrustedCertCRLCheck: + opt.no_trusted_cert_crl_check = 1; + break; + case oEnableTrustedCertCRLCheck: + opt.no_trusted_cert_crl_check = 0; + break; case oForceCRLRefresh: opt.force_crl_refresh = 1; break; @@ -1352,6 +1362,8 @@ main ( int argc, char **argv) GC_OPT_FLAG_NONE ); printf ("disable-crl-checks:%lu:\n", GC_OPT_FLAG_NONE ); + printf ("disable-trusted-cert-crl-check:%lu:\n", + GC_OPT_FLAG_NONE ); printf ("enable-ocsp:%lu:\n", GC_OPT_FLAG_NONE ); printf ("include-certs:%lu:1:\n", diff --git a/sm/gpgsm.h b/sm/gpgsm.h index aafc4815d..1068e9d5e 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -97,6 +97,7 @@ struct { int ignore_time_conflict; /* Ignore certain time conflicts */ int no_crl_check; /* Don't do a CRL check */ + int no_trusted_cert_crl_check; /* Don't run a CRL check for trusted certs. */ int force_crl_refresh; /* Force refreshing the CRL. */ int enable_ocsp; /* Default to use OCSP checks. */ diff --git a/tools/ChangeLog b/tools/ChangeLog index 7fd4c2899..b5a104ce6 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,11 @@ +2005-04-21 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c: Add gpgsm option disable-trusted-cert-crl-check. + +2005-04-20 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c: Add gpg-agent:disable-scdaemon. + 2005-04-19 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c: Add --input option. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 5e6777e1f..c49d1dcbb 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -449,6 +449,9 @@ static gc_option_t gc_options_gpg_agent[] = { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "|FILE|read options from FILE", GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, + { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "do not use the SCdaemon", + GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, @@ -651,6 +654,9 @@ static gc_option_t gc_options_gpgsm[] = { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "never consult a CRL", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, + { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, + "gnupg", N_("do not check CRLs for root certificates"), + GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, "gnupg", "check validity using OCSP", GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM }, diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 8637987f8..f5fd496b8 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -124,7 +124,7 @@ enum cmd_and_opt_values oKeyfile, oDecrypt, oEncrypt, - oInput, + oInput }; -- cgit v1.2.3 From 07aa7b210aa4203770cd2d6e5ee003e1ecb760e7 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 21 Apr 2005 10:07:41 +0000 Subject: (main): Optionally allow the input file as command line argument. --- tools/ChangeLog | 3 +++ tools/symcryptrun.c | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index b5a104ce6..68b62dd30 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,8 @@ 2005-04-21 Werner Koch <wk@g10code.com> + * symcryptrun.c (main): Optionally allow the input file as command + line argument. + * gpgconf-comp.c: Add gpgsm option disable-trusted-cert-crl-check. 2005-04-20 Werner Koch <wk@g10code.com> diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index f5fd496b8..6771ab953 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -190,7 +190,7 @@ my_strusage (int level) break; case 41: p = _("Syntax: symcryptrun --class CLASS --program PROGRAM " - "--keyfile KEYFILE [options...] COMMAND\n" + "--keyfile KEYFILE [options...] COMMAND [inputfile]\n" "Call a simple symmetric encryption tool\n"); break; case 31: p = "\nHome: "; break; @@ -961,6 +961,20 @@ main (int argc, char **argv) xfree (configname); configname = NULL; + /* With --inputfile an argument is not allowed, without only one + optional argument is allowed. */ + if (argc > 1) + log_error (_("too many arguments\n")); + else if (opt.input && argc) + log_error (_("no argument allowed when using option \"%s\"\n"), + "--inputfile"); + + if (argc) + { + opt.input = *argv; + argv++; argc--; + } + if (!mode) log_error (_("either %s or %s must be given\n"), "--decrypt", "--encrypt"); -- cgit v1.2.3 From ec51140af03ea92a2a0737c4fc3536468fd3a409 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 21 Apr 2005 14:39:00 +0000 Subject: Preparing a release --- ChangeLog | 2 + NEWS | 7 +- configure.ac | 2 +- doc/gpg-agent.texi | 13 +- po/ChangeLog | 6 +- po/de.po | 565 ++++++++++++++++++++++++++++++++++------------------- 6 files changed, 380 insertions(+), 215 deletions(-) diff --git a/ChangeLog b/ChangeLog index cfe0f863b..5538a4503 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2005-04-21 Werner Koch <wk@g10code.com> + Released 1.9.16. + * configure.ac: Do not build gpg by default. 2005-04-20 Werner Koch <wk@g10code.com> diff --git a/NEWS b/NEWS index d2334d9cd..e5107e6c1 100644 --- a/NEWS +++ b/NEWS @@ -1,13 +1,16 @@ -Noteworthy changes in version 1.9.16 +Noteworthy changes in version 1.9.16 (2005-04-21) ------------------------------------------------- * gpg-agent does now support the ssh-agent protocol and thus allows to use the pinentry as well as the OpenPGP smartcard with ssh. - * New tool gpg-connect-agent as a genereal client for the gpg-agent. + * New tool gpg-connect-agent as a general client for the gpg-agent. * New tool symcryptrun as a wrapper for certain encryption tools. + * The gpg tool is not anymore build by default because those gpg + versions available in the gnupg 1.4 series are far more matured. + Noteworthy changes in version 1.9.15 (2005-01-13) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 8654785ee..4b32f581f 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.16-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.16, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 52f1fe0d8..33c8c148c 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -465,14 +465,15 @@ Here is a list of supported signals: @item SIGHUP @cpindex SIGHUP -This signals flushes all chached passphrases and when the program was +This signal flushes all chached passphrases and if the program has been 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. +@code{debug}, @code{debug-all}, @code{debug-level}, @code{no-grab}, +@code{pinentry-program}, @code{default-cache-ttl}, @code{max-cache-ttl}, +@code{ignore-cache-for-signing}, @code{allow-mark-trusted} and +@code{disable-scdaemon}. @code{scdaemon-program} is also supported but +due to the current implementation, which calls the scdaemon only once, +it is not of much use unless you manually kill the scdaemon. @item SIGTERM diff --git a/po/ChangeLog b/po/ChangeLog index bfd763bba..27a63ca73 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2005-04-21 Werner Koch <wk@g10code.com> + + * de.po: Fixed all fuzzies and untranslated strings. + 2005-01-04 Werner Koch <wk@g10code.com> * de.po: Updated. @@ -58,7 +62,7 @@ * de.po: New. - Copyright 2002 Free Software Foundation, Inc. + Copyright 2002, 2003, 2004, 2005 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 diff --git a/po/de.po b/po/de.po index bfcf40d67..da09719dd 100644 --- a/po/de.po +++ b/po/de.po @@ -1,5 +1,5 @@ # German translation for GnuPG 1.9.x -*-coding: latin-1;-*- -# Copyright (C) 2002, 2004 Free Software Foundation, Inc. +# Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. # Werner Koch <wk@gnupg.org>, 2002. # # @@ -8,17 +8,17 @@ # msgid "" msgstr "" -"Project-Id-Version: gnupg2 1.9.14\n" +"Project-Id-Version: gnupg2 1.9.16\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-01-04 16:45+0100\n" -"PO-Revision-Date: 2005-01-04 16:53+0100\n" +"POT-Creation-Date: 2005-04-21 15:21+0200\n" +"PO-Revision-Date: 2005-04-21 16:23+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:103 agent/protect-tool.c:106 scd/scdaemon.c:98 +#: agent/gpg-agent.c:107 agent/protect-tool.c:106 scd/scdaemon.c:98 msgid "" "@Options:\n" " " @@ -26,102 +26,110 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:105 scd/scdaemon.c:100 +#: agent/gpg-agent.c:109 scd/scdaemon.c:100 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:106 scd/scdaemon.c:101 +#: agent/gpg-agent.c:110 scd/scdaemon.c:101 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:107 kbx/kbxutil.c:81 scd/scdaemon.c:102 sm/gpgsm.c:325 +#: agent/gpg-agent.c:111 kbx/kbxutil.c:81 scd/scdaemon.c:102 sm/gpgsm.c:329 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:108 kbx/kbxutil.c:82 scd/scdaemon.c:103 sm/gpgsm.c:326 +#: agent/gpg-agent.c:112 kbx/kbxutil.c:82 scd/scdaemon.c:103 sm/gpgsm.c:330 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" -#: agent/gpg-agent.c:109 scd/scdaemon.c:104 +#: agent/gpg-agent.c:113 scd/scdaemon.c:104 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:110 scd/scdaemon.c:105 +#: agent/gpg-agent.c:114 scd/scdaemon.c:105 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" -#: agent/gpg-agent.c:111 +#: agent/gpg-agent.c:115 msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:116 scd/scdaemon.c:112 +#: agent/gpg-agent.c:120 scd/scdaemon.c:112 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:117 +#: agent/gpg-agent.c:121 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:118 scd/scdaemon.c:113 sm/gpgsm.c:328 +#: agent/gpg-agent.c:122 scd/scdaemon.c:113 sm/gpgsm.c:332 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:119 +#: agent/gpg-agent.c:123 msgid "do not allow multiple connections" msgstr "Nicht mehr als eine Verbindung erlauben" -#: agent/gpg-agent.c:121 +#: agent/gpg-agent.c:125 msgid "use a standard location for the socket" msgstr "Benutze einen Standardnamen fr den Socket" -#: agent/gpg-agent.c:125 +#: agent/gpg-agent.c:129 msgid "|PGM|use PGM as the PIN-Entry program" msgstr "|PGM|benutze PGM as PIN-Entry" -#: agent/gpg-agent.c:127 +#: agent/gpg-agent.c:131 msgid "|PGM|use PGM as the SCdaemon program" msgstr "|PGM|benutze PGM as SCdaemon" -#: agent/gpg-agent.c:134 +#: agent/gpg-agent.c:132 +msgid "do not use the SCdaemon" +msgstr "Den Scdaemon basierten Kartenzugriff nicht nutzen" + +#: agent/gpg-agent.c:139 msgid "ignore requests to change the TTY" msgstr "Ignoriere Anfragen, das TTY zu wechseln" -#: agent/gpg-agent.c:136 +#: agent/gpg-agent.c:141 msgid "ignore requests to change the X display" msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:139 +#: agent/gpg-agent.c:144 msgid "|N|expire cached PINs after N seconds" msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" -#: agent/gpg-agent.c:142 +#: agent/gpg-agent.c:147 msgid "do not use the PIN cache when signing" msgstr "benutze PINs im Cache nicht bem Signieren" -#: agent/gpg-agent.c:144 +#: agent/gpg-agent.c:149 msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" -#: agent/gpg-agent.c:146 +#: agent/gpg-agent.c:151 msgid "allow presetting passphrase" msgstr "erlaube ein \"preset\" von Passphrases" -#: agent/gpg-agent.c:205 agent/protect-tool.c:139 scd/scdaemon.c:178 -#: sm/gpgsm.c:499 tools/gpgconf.c:85 +#: agent/gpg-agent.c:152 +msgid "enable ssh-agent emulation" +msgstr "Die ssh-agent Emulation anschalten" + +#: agent/gpg-agent.c:232 agent/protect-tool.c:139 scd/scdaemon.c:178 +#: sm/gpgsm.c:503 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:205 agent/protect-tool.c:139 scd/scdaemon.c:178 -#: sm/gpgsm.c:499 tools/gpgconf.c:85 +#: agent/gpg-agent.c:232 agent/protect-tool.c:139 scd/scdaemon.c:178 +#: sm/gpgsm.c:503 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:208 +#: agent/gpg-agent.c:235 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: agent/gpg-agent.c:210 +#: agent/gpg-agent.c:237 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -129,54 +137,118 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:281 scd/scdaemon.c:252 sm/gpgsm.c:628 +#: agent/gpg-agent.c:308 scd/scdaemon.c:252 sm/gpgsm.c:632 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:462 agent/protect-tool.c:1061 kbx/kbxutil.c:431 -#: scd/scdaemon.c:367 sm/gpgsm.c:749 +#: agent/gpg-agent.c:498 agent/protect-tool.c:1061 kbx/kbxutil.c:431 +#: scd/scdaemon.c:367 sm/gpgsm.c:753 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:537 scd/scdaemon.c:442 sm/gpgsm.c:850 +#: agent/gpg-agent.c:590 scd/scdaemon.c:442 sm/gpgsm.c:854 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:542 agent/gpg-agent.c:1056 scd/scdaemon.c:447 -#: sm/gpgsm.c:854 +#: agent/gpg-agent.c:595 agent/gpg-agent.c:1104 scd/scdaemon.c:447 +#: sm/gpgsm.c:858 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:550 scd/scdaemon.c:455 sm/gpgsm.c:861 +#: agent/gpg-agent.c:603 scd/scdaemon.c:455 sm/gpgsm.c:865 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:775 agent/gpg-agent.c:1090 agent/gpg-agent.c:1094 -#: agent/gpg-agent.c:1130 agent/gpg-agent.c:1134 +#: agent/gpg-agent.c:1154 agent/gpg-agent.c:1257 agent/gpg-agent.c:1261 +#: agent/gpg-agent.c:1297 agent/gpg-agent.c:1301 #, c-format msgid "can't create directory `%s': %s\n" -msgstr "Das Verzeichniss `%s' kann nicht erstell werden: %s\n" +msgstr "Das Verzeichniss `%s' kann nicht erstellt werden: %s\n" + +#: agent/gpg-agent.c:1168 +msgid "name of socket too long\n" +msgstr "Der Name des Sockets ist zu lang\n" + +#: agent/gpg-agent.c:1194 +#, c-format +msgid "can't create socket: %s\n" +msgstr "Socket kann nicht erzeugt werden: %s\n" + +#: agent/gpg-agent.c:1223 +#, c-format +msgid "error binding socket to `%s': %s\n" +msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n" + +#: agent/gpg-agent.c:1231 +#, c-format +msgid "listen() failed: %s\n" +msgstr "Der listen() Aufruf ist fehlgeschlagen: %s\n" + +#: agent/gpg-agent.c:1237 +#, c-format +msgid "listening on socket `%s'\n" +msgstr "Es wird auf Socket `%s' gehrt\n" -#: agent/gpg-agent.c:1098 agent/gpg-agent.c:1140 +#: agent/gpg-agent.c:1265 agent/gpg-agent.c:1307 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/gpg-agent.c:1327 +#: agent/gpg-agent.c:1313 +#, c-format +msgid "stat() failed for `%s': %s\n" +msgstr "stat() Aufruf fr `%s' fehlgeschlagen: %s\n" + +#: agent/gpg-agent.c:1317 +#, c-format +msgid "can't use `%s' as home directory\n" +msgstr "Die Datei `%s' kann nicht als Home-Verzeichniss benutzt werden\n" + +#: agent/gpg-agent.c:1408 +#, c-format +msgid "handler for fd %d started\n" +msgstr "Handhabungsroutine fr fd %d gestartet\n" + +#: agent/gpg-agent.c:1417 +#, c-format +msgid "handler for fd %d terminated\n" +msgstr "Handhabungsroutine fr den fd %d beendet\n" + +#: agent/gpg-agent.c:1430 +#, c-format +msgid "ssh handler for fd %d started\n" +msgstr "SSH Handhabungsroutine fr fd %d gestartet\n" + +#: agent/gpg-agent.c:1436 +#, c-format +msgid "ssh handler for fd %d terminated\n" +msgstr "SSH Handhabungsroutine fr fd %d beendet\n" + +#: agent/gpg-agent.c:1525 +#, c-format +msgid "pth_select failed: %s - waiting 1s\n" +msgstr "pth_select() Aufruf fehlgeschlagen: %s - warte 1s\n" + +#: agent/gpg-agent.c:1582 +#, c-format +msgid "%s %s stopped\n" +msgstr "%s %s angehalten\n" + +#: agent/gpg-agent.c:1604 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1337 common/simple-pwquery.c:323 sm/call-agent.c:140 +#: agent/gpg-agent.c:1614 common/simple-pwquery.c:323 sm/call-agent.c:140 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1349 common/simple-pwquery.c:335 sm/call-agent.c:152 +#: agent/gpg-agent.c:1626 common/simple-pwquery.c:335 sm/call-agent.c:152 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" @@ -395,12 +467,12 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:624 +#: jnlib/logging.c:609 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:68 sm/gpgsm.c:235 tools/gpgconf.c:53 +#: kbx/kbxutil.c:68 sm/gpgsm.c:237 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -408,7 +480,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:76 sm/gpgsm.c:270 tools/gpgconf.c:59 +#: kbx/kbxutil.c:76 sm/gpgsm.c:272 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -418,7 +490,7 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:83 sm/gpgsm.c:333 tools/gpgconf.c:64 +#: kbx/kbxutil.c:83 sm/gpgsm.c:337 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine nderungen durchfhren" @@ -450,7 +522,7 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:106 sm/gpgsm.c:345 +#: scd/scdaemon.c:106 sm/gpgsm.c:349 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" @@ -500,90 +572,163 @@ msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" -#: scd/app-openpgp.c:534 +#: scd/app-openpgp.c:595 #, c-format msgid "failed to store the fingerprint: %s\n" msgstr "Der Fingerprint kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:547 +#: scd/app-openpgp.c:608 #, c-format msgid "failed to store the creation date: %s\n" msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:732 scd/app-openpgp.c:821 scd/app-openpgp.c:1313 +#: scd/app-openpgp.c:976 +#, c-format +msgid "reading public key failed: %s\n" +msgstr "Fehler beim Lesen des ffentlichen Schlssels: %s\n" + +#: scd/app-openpgp.c:984 scd/app-openpgp.c:1621 scd/app-openpgp.c:2411 +msgid "response does not contain the public key data\n" +msgstr "Die Antwort enthlt keine Public Key Daten\n" + +#: scd/app-openpgp.c:992 scd/app-openpgp.c:1629 scd/app-openpgp.c:2419 +msgid "response does not contain the RSA modulus\n" +msgstr "Die Antwort enthlt keinen RSA Modulus\n" + +#: scd/app-openpgp.c:1001 scd/app-openpgp.c:1639 scd/app-openpgp.c:2430 +msgid "response does not contain the RSA public exponent\n" +msgstr "Die Antwort enthlt keinen ffenlichen RSA Exponent\n" + +#: scd/app-openpgp.c:1253 scd/app-openpgp.c:1341 scd/app-openpgp.c:1861 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:738 scd/app-openpgp.c:827 scd/app-openpgp.c:1319 +#: scd/app-openpgp.c:1259 scd/app-openpgp.c:1347 scd/app-openpgp.c:1867 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" msgstr "Die PIN fr den CHV%d ist zu kurz; Mindestlnge ist %d\n" -#: scd/app-openpgp.c:747 scd/app-openpgp.c:761 scd/app-openpgp.c:837 -#: scd/app-openpgp.c:1328 scd/app-openpgp.c:1342 +#: scd/app-openpgp.c:1268 scd/app-openpgp.c:1282 scd/app-openpgp.c:1357 +#: scd/app-openpgp.c:1876 scd/app-openpgp.c:1890 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:784 +#: scd/app-openpgp.c:1305 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:801 +#: scd/app-openpgp.c:1320 scd/app-openpgp.c:2096 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:807 +#: scd/app-openpgp.c:1326 scd/app-openpgp.c:2105 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:814 +#: scd/app-openpgp.c:1331 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" "Noch %d Admin PIN Versuche mglich bevor die Karte dauerhaft gesperrt wird\n" -#: scd/app-openpgp.c:818 -msgid "Admin PIN" -msgstr "Admin PIN" +#. TRANSLATORS: Do not translate the "|A|" prefix but +#. keep it at the start of the string. We need this elsewhere +#. to get some infos on the string. +#: scd/app-openpgp.c:1338 +msgid "|A|Admin PIN" +msgstr "|A|Admin PIN" + +#. TRANSLATORS: Do not translate the "|*|" prefixes but +#. keep it at the start of the string. We need this elsewhere +#. to get some infos on the string. +#: scd/app-openpgp.c:1487 +msgid "|AN|New Admin PIN" +msgstr "|AN|Neue Admin PIN" + +#: scd/app-openpgp.c:1487 +msgid "|N|New PIN" +msgstr "|N|Neue PIN" + +#: scd/app-openpgp.c:1491 +#, c-format +msgid "error getting new PIN: %s\n" +msgstr "Fehler beim Holen der neuen PIN: %s\n" + +#: scd/app-openpgp.c:1564 scd/app-openpgp.c:1707 +msgid "error reading application data\n" +msgstr "Fehler beim Lesen der Anwendungsdaten\n" + +#: scd/app-openpgp.c:1571 scd/app-openpgp.c:1714 +msgid "error reading fingerprint DO\n" +msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" + +#: scd/app-openpgp.c:1580 +msgid "key already exists\n" +msgstr "Schlssel existiert bereits\n" + +#: scd/app-openpgp.c:1584 +msgid "existing key will be replaced\n" +msgstr "Existierender Schlssel wird ersetzt\n" + +#: scd/app-openpgp.c:1586 +msgid "generating new key\n" +msgstr "Neuer Schlssel wird erzeugt\n" -#: scd/app-openpgp.c:1301 +#: scd/app-openpgp.c:1597 +msgid "please wait while key is being generated ...\n" +msgstr "Bitte warten bis der Schlssel erzeugt wurde ...\n" + +#: scd/app-openpgp.c:1612 +msgid "generating key failed\n" +msgstr "Fehler beim Erzeugen des Schlssels\n" + +#: scd/app-openpgp.c:1615 +#, c-format +msgid "key generation completed (%d seconds)\n" +msgstr "Schlsselerzeugung vollendet (%d Sekunden)\n" + +#: scd/app-openpgp.c:1672 +msgid "invalid structure of OpenPGP card (DO 0x93)\n" +msgstr "Ungltige Struktur der OpenPGP Karte (DO 0x93)\n" + +#: scd/app-openpgp.c:1841 +#, c-format +msgid "signatures created so far: %lu\n" +msgstr "Anzahl bereits erzeugter Signaturen: %lu\n" + +#: scd/app-openpgp.c:1849 #, c-format msgid "PIN [sigs done: %lu]" msgstr "PIN [erzeugte signaturen: %lu]" -#: scd/app-openpgp.c:1587 scd/app-openpgp.c:1597 +#: scd/app-openpgp.c:2110 +msgid "" +"verification of Admin PIN is currently prohibited through this command\n" +msgstr "" +"Die berprfung der Admin PIN is momentan durch ein Kommando verboten " +"worden\n" + +#: scd/app-openpgp.c:2181 scd/app-openpgp.c:2191 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht mglich - ungltige OpenPGP Karte?\n" -#: scd/app-openpgp.c:1668 +#: scd/app-openpgp.c:2262 #, c-format msgid "error getting serial number: %s\n" msgstr "Fehler beim Holen der Seriennummer: %s\n" -#: scd/app-openpgp.c:1763 +#: scd/app-openpgp.c:2362 #, c-format msgid "failed to store the key: %s\n" msgstr "Fehler beim Speichern des Schlssels: %s\n" -#: scd/app-openpgp.c:1805 +#: scd/app-openpgp.c:2404 msgid "reading the key failed\n" msgstr "Fehler beim Lesen des Schlssels: %s\n" -#: scd/app-openpgp.c:1812 -msgid "response does not contain the public key data\n" -msgstr "Die Antwort enthlt keine Public Key Daten\n" - -#: scd/app-openpgp.c:1820 -msgid "response does not contain the RSA modulus\n" -msgstr "Die Antwort enthlt keinen RSA Modulus\n" - -#: scd/app-openpgp.c:1831 -msgid "response does not contain the RSA public exponent\n" -msgstr "Die Antwort enthlt keinen ffenlichen RSA Exponent\n" - #: sm/base64.c:315 #, c-format msgid "invalid radix64 character %02x skipped\n" @@ -616,31 +761,31 @@ msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " "versucht\n" -#: sm/certdump.c:59 sm/certdump.c:142 +#: sm/certdump.c:59 sm/certdump.c:143 msgid "none" msgstr "keine" -#: sm/certdump.c:151 +#: sm/certdump.c:152 msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:493 +#: sm/certdump.c:494 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:507 +#: sm/certdump.c:508 msgid "[Error - unknown encoding]" msgstr "[Fehler - Unbekannte Kodierung]" -#: sm/certdump.c:511 +#: sm/certdump.c:512 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungltige Kodierung]" -#: sm/certdump.c:516 +#: sm/certdump.c:517 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungltiger DN]" -#: sm/certdump.c:677 +#: sm/certdump.c:678 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -702,108 +847,113 @@ msgstr "Das Herausgeberzertifikat ist nicht f msgid "critical marked policy without configured policies" msgstr "kritische Richtlinie ohne konfigurierte Richtlinien" -#: sm/certchain.c:185 sm/certchain.c:214 +#: sm/certchain.c:179 +#, c-format +msgid "failed to open `%s': %s\n" +msgstr "Datei `%s' kann nicht geffnet werden: %s\n" + +#: sm/certchain.c:186 sm/certchain.c:215 msgid "note: non-critical certificate policy not allowed" msgstr "Notiz: Die unkritische Zertifikatrichtlinie ist nicht erlaubt" -#: sm/certchain.c:189 sm/certchain.c:218 +#: sm/certchain.c:190 sm/certchain.c:219 msgid "certificate policy not allowed" msgstr "Die Zertifikatrichtlinie ist nicht erlaubt" -#: sm/certchain.c:349 +#: sm/certchain.c:330 msgid "looking up issuer at external location\n" msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" -#: sm/certchain.c:367 +#: sm/certchain.c:350 #, c-format msgid "number of issuers matching: %d\n" msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:403 sm/certchain.c:562 sm/certchain.c:931 sm/decrypt.c:260 +#: sm/certchain.c:503 sm/certchain.c:662 sm/certchain.c:1031 sm/decrypt.c:260 #: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" -#: sm/certchain.c:492 +#: sm/certchain.c:592 msgid "certificate has been revoked" msgstr "Das Zertifikat wurde widerrufen" -#: sm/certchain.c:501 +#: sm/certchain.c:601 msgid "no CRL found for certificate" msgstr "Keine CRL fr das Zertifikat gefunden" -#: sm/certchain.c:505 +#: sm/certchain.c:605 msgid "the available CRL is too old" msgstr "Die vorhandene CRL ist zu alt" -#: sm/certchain.c:507 +#: sm/certchain.c:607 msgid "please make sure that the \"dirmngr\" is properly installed\n" msgstr "" "Bite vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" -#: sm/certchain.c:512 +#: sm/certchain.c:612 #, c-format msgid "checking the CRL failed: %s" msgstr "Die CRL konnte nicht geprft werden: %s" -#: sm/certchain.c:582 +#: sm/certchain.c:682 msgid "no issuer found in certificate" msgstr "Im Zertifikat ist kein Herausgeber enthalten" -#: sm/certchain.c:595 +#: sm/certchain.c:695 #, c-format msgid "certificate with invalid validity: %s" msgstr "Zertifikat mit unzulssiger Gltigkeit: %s" -#: sm/certchain.c:611 +#: sm/certchain.c:711 msgid "certificate not yet valid" msgstr "Das Zertifikat ist noch nicht gltig" -#: sm/certchain.c:624 +#: sm/certchain.c:724 msgid "certificate has expired" msgstr "Das Zertifikat ist abgelaufen" -#: sm/certchain.c:661 -msgid "selfsigned certificate has a BAD signature" +#: sm/certchain.c:761 +msgid "self-signed certificate has a BAD signature" msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:679 +#: sm/certchain.c:779 msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert" -#: sm/certchain.c:690 +#: sm/certchain.c:790 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:695 +#: sm/certchain.c:795 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" -#: sm/certchain.c:710 +#: sm/certchain.c:810 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" -#: sm/certchain.c:736 sm/import.c:157 +#: sm/certchain.c:836 sm/import.c:157 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:748 +#: sm/certchain.c:848 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:781 +#: sm/certchain.c:881 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:809 +#: sm/certchain.c:911 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:832 +#: sm/certchain.c:934 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" @@ -856,243 +1006,243 @@ msgstr "Schwacher Schl msgid "no valid recipients given\n" msgstr "Keine gltigen Empfnger angegeben\n" -#: sm/gpgsm.c:237 +#: sm/gpgsm.c:239 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:238 +#: sm/gpgsm.c:240 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:241 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:240 +#: sm/gpgsm.c:242 msgid "encrypt data" msgstr "Verschlssele die Daten" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:243 msgid "encryption only with symmetric cipher" msgstr "Verschlsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:244 msgid "decrypt data (default)" msgstr "Enschlssele die Daten" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:245 msgid "verify a signature" msgstr "berprfen einer Signatur" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:247 msgid "list keys" msgstr "Schlssel anzeigen" -#: sm/gpgsm.c:246 +#: sm/gpgsm.c:248 msgid "list external keys" msgstr "Externe Schlssel anzeigen" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:249 msgid "list secret keys" msgstr "Geheime Schlssel anzeigen" -#: sm/gpgsm.c:248 +#: sm/gpgsm.c:250 msgid "list certificate chain" msgstr "Schlssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:252 msgid "list keys and fingerprints" msgstr "Schlssel und Fingerprint anzeigen" -#: sm/gpgsm.c:251 +#: sm/gpgsm.c:253 msgid "generate a new key pair" msgstr "Neues Schlsselpaar erzeugen" -#: sm/gpgsm.c:252 +#: sm/gpgsm.c:254 msgid "remove key from the public keyring" msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" -#: sm/gpgsm.c:253 +#: sm/gpgsm.c:255 msgid "export keys to a key server" msgstr "Schlssen an eine Schlsselserver exportieren" -#: sm/gpgsm.c:254 +#: sm/gpgsm.c:256 msgid "import keys from a key server" msgstr "Schlssel von einem Schlsselserver importieren" -#: sm/gpgsm.c:255 +#: sm/gpgsm.c:257 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:256 +#: sm/gpgsm.c:258 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:257 +#: sm/gpgsm.c:259 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:258 +#: sm/gpgsm.c:260 msgid "run in server mode" msgstr "Im Server Modus ausfhren" -#: sm/gpgsm.c:259 +#: sm/gpgsm.c:261 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:261 +#: sm/gpgsm.c:263 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:262 +#: sm/gpgsm.c:264 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ndern" -#: sm/gpgsm.c:272 +#: sm/gpgsm.c:274 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hlle wird erzeugt" -#: sm/gpgsm.c:274 +#: sm/gpgsm.c:276 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:276 +#: sm/gpgsm.c:278 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:278 +#: sm/gpgsm.c:280 msgid "assume input is in base-64 format" msgstr "Eingabedaten sind im Basis-64 Format" -#: sm/gpgsm.c:280 +#: sm/gpgsm.c:282 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binrformat" -#: sm/gpgsm.c:282 +#: sm/gpgsm.c:284 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlsseln fr NAME" -#: sm/gpgsm.c:285 +#: sm/gpgsm.c:287 msgid "use system's dirmngr if available" msgstr "Benutze den System Dirmngr when verfgbar" -#: sm/gpgsm.c:286 +#: sm/gpgsm.c:288 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:291 +#: sm/gpgsm.c:295 msgid "check validity using OCSP" msgstr "Die Gltigkeit mittels OCSP prfen" -#: sm/gpgsm.c:294 +#: sm/gpgsm.c:298 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:297 +#: sm/gpgsm.c:301 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:300 +#: sm/gpgsm.c:304 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht berprfen" -#: sm/gpgsm.c:304 +#: sm/gpgsm.c:308 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:308 +#: sm/gpgsm.c:312 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" -#: sm/gpgsm.c:310 +#: sm/gpgsm.c:314 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" -#: sm/gpgsm.c:316 +#: sm/gpgsm.c:320 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" -#: sm/gpgsm.c:319 +#: sm/gpgsm.c:323 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:321 +#: sm/gpgsm.c:325 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:324 tools/gpgconf.c:61 +#: sm/gpgsm.c:328 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: sm/gpgsm.c:327 +#: sm/gpgsm.c:331 msgid "don't use the terminal at all" msgstr "Das Terminal berhaupt nicht benutzen" -#: sm/gpgsm.c:330 +#: sm/gpgsm.c:334 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:331 +#: sm/gpgsm.c:335 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" -#: sm/gpgsm.c:336 +#: sm/gpgsm.c:340 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:337 +#: sm/gpgsm.c:341 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:338 +#: sm/gpgsm.c:342 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:340 +#: sm/gpgsm.c:344 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:341 +#: sm/gpgsm.c:345 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:342 +#: sm/gpgsm.c:346 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" -#: sm/gpgsm.c:343 +#: sm/gpgsm.c:347 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlsselserver" -#: sm/gpgsm.c:344 +#: sm/gpgsm.c:348 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" -#: sm/gpgsm.c:348 +#: sm/gpgsm.c:352 msgid "|LEVEL|set the debugging level to LEVEL" msgstr "|NAME|Die Debugstufe auf NAME setzen" -#: sm/gpgsm.c:355 +#: sm/gpgsm.c:359 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:362 +#: sm/gpgsm.c:366 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:368 +#: sm/gpgsm.c:372 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verschlsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:370 +#: sm/gpgsm.c:374 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:372 +#: sm/gpgsm.c:376 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:380 +#: sm/gpgsm.c:384 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -1100,7 +1250,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:383 +#: sm/gpgsm.c:387 msgid "" "@\n" "Examples:\n" @@ -1120,11 +1270,11 @@ msgstr "" " --list-keys [Namen] Schlssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" -#: sm/gpgsm.c:502 +#: sm/gpgsm.c:506 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" -#: sm/gpgsm.c:505 +#: sm/gpgsm.c:509 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -1133,7 +1283,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:512 +#: sm/gpgsm.c:516 msgid "" "\n" "Supported algorithms:\n" @@ -1141,50 +1291,50 @@ msgstr "" "\n" "Untersttzte Algorithmen:\n" -#: sm/gpgsm.c:599 +#: sm/gpgsm.c:603 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:664 +#: sm/gpgsm.c:668 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:680 +#: sm/gpgsm.c:684 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:754 +#: sm/gpgsm.c:758 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" -#: sm/gpgsm.c:1205 +#: sm/gpgsm.c:1215 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1217 +#: sm/gpgsm.c:1227 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " -#: sm/gpgsm.c:1243 +#: sm/gpgsm.c:1253 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" -#: sm/gpgsm.c:1251 +#: sm/gpgsm.c:1261 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" -#: sm/gpgsm.c:1281 +#: sm/gpgsm.c:1291 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht mglich: %s\n" -#: sm/gpgsm.c:1452 +#: sm/gpgsm.c:1464 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1682 sm/gpgsm.c:1719 +#: sm/gpgsm.c:1694 sm/gpgsm.c:1731 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geffnet werden: %s\n" @@ -1374,51 +1524,59 @@ msgstr "Ben msgid "Component not found" msgstr "Komponente nicht gefunden" -#: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:496 tools/gpgconf-comp.c:561 -#: tools/gpgconf-comp.c:614 tools/gpgconf-comp.c:680 +#: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:499 tools/gpgconf-comp.c:564 +#: tools/gpgconf-comp.c:617 tools/gpgconf-comp.c:686 msgid "Options controlling the diagnostic output" msgstr "Optionen zur Einstellung Diagnoseausgaben" -#: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:509 tools/gpgconf-comp.c:574 -#: tools/gpgconf-comp.c:627 tools/gpgconf-comp.c:703 +#: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:512 tools/gpgconf-comp.c:577 +#: tools/gpgconf-comp.c:630 tools/gpgconf-comp.c:709 msgid "Options controlling the configuration" msgstr "Optionen zur Einstellung der Konfiguration" -#: tools/gpgconf-comp.c:455 tools/gpgconf-comp.c:532 tools/gpgconf-comp.c:581 -#: tools/gpgconf-comp.c:637 tools/gpgconf-comp.c:710 +#: tools/gpgconf-comp.c:458 tools/gpgconf-comp.c:535 tools/gpgconf-comp.c:584 +#: tools/gpgconf-comp.c:640 tools/gpgconf-comp.c:716 msgid "Options useful for debugging" msgstr "Ntzliche Optionen zum Debuggen" -#: tools/gpgconf-comp.c:460 tools/gpgconf-comp.c:537 tools/gpgconf-comp.c:586 -#: tools/gpgconf-comp.c:642 tools/gpgconf-comp.c:718 +#: tools/gpgconf-comp.c:463 tools/gpgconf-comp.c:540 tools/gpgconf-comp.c:589 +#: tools/gpgconf-comp.c:645 tools/gpgconf-comp.c:724 msgid "|FILE|write server mode logs to FILE" msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" -#: tools/gpgconf-comp.c:468 tools/gpgconf-comp.c:542 tools/gpgconf-comp.c:650 +#: tools/gpgconf-comp.c:471 tools/gpgconf-comp.c:545 tools/gpgconf-comp.c:653 msgid "Options controlling the security" msgstr "Optionen zur Einstellung der Sicherheit" -#: tools/gpgconf-comp.c:594 +#: tools/gpgconf-comp.c:597 msgid "Configuration for Keyservers" msgstr "Konfiguration der Schlsselserver" -#: tools/gpgconf-comp.c:693 +#: tools/gpgconf-comp.c:658 +msgid "do not check CRLs for root certificates" +msgstr "CRL bei Wurzelzertifikaten nicht berprfen" + +#: tools/gpgconf-comp.c:699 msgid "Options controlling the format of the output" msgstr "Optionen zum Einstellen der Ausgabeformate" -#: tools/gpgconf-comp.c:729 +#: tools/gpgconf-comp.c:735 msgid "Options controlling the interactivity and enforcement" msgstr "Optionen zur Einstellung der Interaktivitt und Geltendmachung" -#: tools/gpgconf-comp.c:739 +#: tools/gpgconf-comp.c:745 msgid "Configuration for HTTP servers" msgstr "Konfiguration fr HTTP Server" -#: tools/gpgconf-comp.c:752 +#: tools/gpgconf-comp.c:756 +msgid "use system's HTTP proxy setting" +msgstr "Einstellungen des System HTTP-Proxy benutzen" + +#: tools/gpgconf-comp.c:761 msgid "Configuration of LDAP servers to use" msgstr "Konfiguration der zu nutzenden LDAP-Server" -#: tools/gpgconf-comp.c:789 +#: tools/gpgconf-comp.c:798 msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" @@ -1438,9 +1596,6 @@ msgstr "Konfiguration zu OCSP" #~ msgid "error running `%s': exit status %d\n" #~ msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" -#~ msgid "error running `%s': terminated\n" -#~ msgstr "Fehler beim Ausfhren von `%s': beendet\n" - #~ msgid "Usage: sc-investigate [options] (-h for help)\n" #~ msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" -- cgit v1.2.3 From a832ff3de0e2a77bd2f9f43adcd965cacc16b1df Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 21 Apr 2005 14:59:18 +0000 Subject: post release version number update --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e5107e6c1..2c5440a9a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.17 +------------------------------------------------- + + Noteworthy changes in version 1.9.16 (2005-04-21) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 4b32f581f..10f45ee92 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.16, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.17-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From a22750dc1e53d4cff4163326019569ef5a780e6e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 27 Apr 2005 12:09:21 +0000 Subject: * configure.ac: Removed OpenSC detection and options. * acinclude.m4: Ditto. * scdaemon.texi: Removed OpenSC specific options. * app-p15.c: New. Basic support for pkcs15 cards without OpenSC. There are quite a couple of things missing but at least I can use my old TCOS cards from the Aegypten-1 development for signing. * app.c (select_application): Detect pkcs15 applications. * Makefile.am (scdaemon_SOURCES): Removed card.c, card-common.h and card-p15.c because they are now obsolete. Added app-p15.c. Removed all OpenSC stuff. * command.c (do_reset, open_card, cmd_serialno, cmd_learn) (cmd_readcert, cmd_readkey, cmd_pksign, cmd_pkdecrypt): Removed all special cases for the old card.c based mechanisms. * scdaemon.c, apdu.c: Removed all special cases for OpenSC. --- ChangeLog | 5 + NEWS | 5 + acinclude.m4 | 67 -- configure.ac | 18 - doc/ChangeLog | 4 + doc/scdaemon.texi | 18 +- scd/ChangeLog | 16 + scd/Makefile.am | 27 +- scd/apdu.c | 246 +---- scd/app-common.h | 2 +- scd/app-nks.c | 4 +- scd/app-p15.c | 2844 +++++++++++++++++++++++++++++++++++++++++++++++------ scd/app.c | 6 +- scd/command.c | 223 +---- scd/scdaemon.c | 27 +- scd/scdaemon.h | 25 - 16 files changed, 2632 insertions(+), 905 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5538a4503..4f58b9198 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-04-27 Werner Koch <wk@g10code.com> + + * configure.ac: Removed OpenSC detection and options. + * acinclude.m4: Ditto. + 2005-04-21 Werner Koch <wk@g10code.com> Released 1.9.16. diff --git a/NEWS b/NEWS index 2c5440a9a..2d43d70ff 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ Noteworthy changes in version 1.9.17 ------------------------------------------------- + * [scdaemon] Support for OpenSC has been removed. Instead a new and + starightforward pkcs#15 modules has been written. As of now it + does allows only signing using TCOS cards but we are going to + enhance it to match all the old capabilities. + Noteworthy changes in version 1.9.16 (2005-04-21) ------------------------------------------------- diff --git a/acinclude.m4 b/acinclude.m4 index e933e6ee0..b8af93245 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -390,70 +390,3 @@ 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) -]) - - diff --git a/configure.ac b/configure.ac index 10f45ee92..dee0a9f09 100644 --- a/configure.ac +++ b/configure.ac @@ -38,9 +38,6 @@ NEED_LIBASSUAN_VERSION=0.6.9 NEED_KSBA_VERSION=0.9.11 -NEED_OPENSC_VERSION=0.8.0 - - PACKAGE=$PACKAGE_NAME PACKAGE_GT=${PACKAGE_NAME}2 @@ -59,7 +56,6 @@ have_gpg_error=no have_libgcrypt=no have_libassuan=no have_ksba=no -have_opensc=no have_pth=no GNUPG_BUILD_PROGRAM(gpg, no) @@ -503,16 +499,6 @@ AC_PATH_PROG(SHRED, shred, /usr/bin/shred) AC_DEFINE_UNQUOTED(SHRED, "${SHRED}", [defines the filename of the shred program]) -# -# OpenSC is needed by the SCdaemon - if it is not availbale we can only -# build a limited SCdaemon -# -AM_PATH_OPENSC("$NEED_OPENSC_VERSION",have_opensc=yes,have_opensc=no) -if test $have_opensc = yes; then - AC_DEFINE(HAVE_OPENSC,1, - [defined if the OpenSC library is available]) -fi -AM_CONDITIONAL(HAVE_OPENSC, test "$have_opensc" = "yes") # # Check whether the (highly desirable) GNU Pth library is available @@ -1052,10 +1038,6 @@ if test "$build_scdaemon" = "yes"; then tmp=", " missing_pth=yes fi - if test $have_opensc = no; then - build_scdaemon_extra="${build_scdaemon_extra}${tmp}no pkcs#15" - tmp=", " - fi if test -n "$build_scdaemon_extra"; then build_scdaemon_extra="(${build_scdaemon_extra})" fi diff --git a/doc/ChangeLog b/doc/ChangeLog index 4ad8b18c8..093e04fa8 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-04-27 Werner Koch <wk@g10code.com> + + * scdaemon.texi: Removed OpenSC specific options. + 2005-04-20 Werner Koch <wk@g10code.com> * gpg-agent.texi (Agent Configuration): New section. diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index cb165da35..971234e52 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -1,4 +1,4 @@ -@c Copyright (C) 2002 Free Software Foundation, Inc. +g@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. @@ -157,10 +157,6 @@ 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 @@ -172,10 +168,9 @@ 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). +This option may 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 @@ -245,9 +240,8 @@ the German signature law and its bylaws (SigG and SigV). @node PKCS#15 Card @subsection The PKCS#15 card application ``p15'' -This is common fraqmework for smart card applications; support is only -available if compiled with support for the OpenSC library. It is used -by @command{gpgsm}. +This is common fraqmework for smart card applications. It is used by +@command{gpgsm}. diff --git a/scd/ChangeLog b/scd/ChangeLog index c5a1062b8..4ce4c656d 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,19 @@ +2005-04-27 Werner Koch <wk@g10code.com> + + Removal of the old OpenSC based code. + + * app-p15.c: New. Basic support for pkcs15 cards without OpenSC. + There are quite a couple of things missing but at least I can use + my old TCOS cards from the Aegypten-1 development for signing. + * app.c (select_application): Detect pkcs15 applications. + * Makefile.am (scdaemon_SOURCES): Removed card.c, card-common.h + and card-p15.c because they are now obsolete. Added app-p15.c. + Removed all OpenSC stuff. + * command.c (do_reset, open_card, cmd_serialno, cmd_learn) + (cmd_readcert, cmd_readkey, cmd_pksign, cmd_pkdecrypt): Removed + all special cases for the old card.c based mechanisms. + * scdaemon.c, apdu.c: Removed all special cases for OpenSC. + 2005-04-20 Werner Koch <wk@g10code.com> * command.c: Use GPG_ERR_LOCKED instead of EBUSY. diff --git a/scd/Makefile.am b/scd/Makefile.am index fba006c5a..c3688da5f 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -27,24 +27,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am -# avoid linking against Pth if we are using OpenSC. -if HAVE_OPENSC -pth_libs = -else -pth_libs = $(PTH_LIBS) -endif - -AM_CFLAGS = $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ - $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) \ + $(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS) -card_apps = app-openpgp.c app-nks.c app-dinsig.c +card_apps = app-openpgp.c app-nks.c app-dinsig.c app-p15.c scdaemon_SOURCES = \ scdaemon.c scdaemon.h \ - command.c card.c \ - card-common.h \ - card-p15.c \ + command.c \ apdu.c apdu.h \ ccid-driver.c ccid-driver.h \ iso7816.c iso7816.h \ @@ -53,8 +44,8 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ - $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(pth_libs) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) $(OPENSC_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) + $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ + $(LIBUSB_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) sc_copykeys_SOURCES = \ sc-copykeys.c scdaemon.h \ @@ -68,8 +59,8 @@ sc_copykeys_SOURCES = \ sc_copykeys_LDADD = \ ../jnlib/libjnlib.a ../common/libcommon.a \ ../common/libsimple-pwquery.a \ - $(LIBGCRYPT_LIBS) $(pth_libs) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) $(OPENSC_LIBS) \ + $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ + $(LIBUSB_LIBS) \ -lgpg-error @LIBINTL@ @DL_LIBS@ pcsc_wrapper_SOURCES = pcsc-wrapper.c diff --git a/scd/apdu.c b/scd/apdu.c index 33b0802c1..d23a4adc9 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -32,12 +32,7 @@ # include <unistd.h> # include <fcntl.h> #endif -#ifdef HAVE_OPENSC -# include <opensc/opensc.h> -# ifdef USE_GNU_PTH -# undef USE_GNU_PTH -# endif -#endif + /* If requested include the definitions for the remote APDU protocol code. */ @@ -119,12 +114,6 @@ struct reader_table_s { pid_t pid; #endif /*NEED_PCSC_WRAPPER*/ } pcsc; -#ifdef HAVE_OPENSC - struct { - struct sc_context *ctx; - struct sc_card *scard; - } osc; -#endif /*HAVE_OPENSC*/ #ifdef USE_G10CODE_RAPDU struct { rapdu_t handle; @@ -1770,224 +1759,6 @@ open_ccid_reader (const char *portstr) #endif /* HAVE_LIBUSB */ - -#ifdef HAVE_OPENSC -/* - OpenSC Interface. - - This uses the OpenSC primitives to send APDUs. We need this - because we can't mix OpenSC and native (i.e. ctAPI or PC/SC) - access to a card for resource conflict reasons. - */ - - -static int -close_osc_reader (int slot) -{ - /* FIXME: Implement. */ - reader_table[slot].used = 0; - return 0; -} - -static int -reset_osc_reader (int slot) -{ - return SW_HOST_NOT_SUPPORTED; -} - - -static int -osc_get_status (int slot, unsigned int *status) -{ - return SW_HOST_NOT_SUPPORTED; -} - - -/* Actually send the APDU of length APDULEN to SLOT and return a - maximum of *BUFLEN data in BUFFER, the actual returned size will be - set to BUFLEN. Returns: OpenSC error code. */ -static int -osc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) -{ - long err; - struct sc_apdu a; - unsigned char data[SC_MAX_APDU_BUFFER_SIZE]; - unsigned char result[SC_MAX_APDU_BUFFER_SIZE]; - - if (DBG_CARD_IO) - log_printhex (" APDU_data:", apdu, apdulen); - - if (apdulen < 4) - { - log_error ("osc_send_apdu: APDU is too short\n"); - return SW_HOST_INV_VALUE; - } - - memset(&a, 0, sizeof a); - a.cla = *apdu++; - a.ins = *apdu++; - a.p1 = *apdu++; - a.p2 = *apdu++; - apdulen -= 4; - - if (!apdulen) - a.cse = SC_APDU_CASE_1; - else if (apdulen == 1) - { - a.le = *apdu? *apdu : 256; - apdu++; apdulen--; - a.cse = SC_APDU_CASE_2_SHORT; - } - else - { - a.lc = *apdu++; apdulen--; - if (apdulen < a.lc) - { - log_error ("osc_send_apdu: APDU shorter than specified in Lc\n"); - return SW_HOST_INV_VALUE; - - } - memcpy(data, apdu, a.lc); - apdu += a.lc; apdulen -= a.lc; - - a.data = data; - a.datalen = a.lc; - - if (!apdulen) - a.cse = SC_APDU_CASE_3_SHORT; - else - { - a.le = *apdu? *apdu : 256; - apdu++; apdulen--; - if (apdulen) - { - log_error ("osc_send_apdu: APDU larger than specified\n"); - return SW_HOST_INV_VALUE; - } - a.cse = SC_APDU_CASE_4_SHORT; - } - } - - a.resp = result; - a.resplen = DIM(result); - - err = sc_transmit_apdu (reader_table[slot].osc.scard, &a); - if (err) - { - log_error ("sc_apdu_transmit failed: %s\n", sc_strerror (err)); - return SW_HOST_CARD_IO_ERROR; - } - - if (*buflen < 2 || a.resplen > *buflen - 2) - { - log_error ("osc_send_apdu: provided buffer too short to store result\n"); - return SW_HOST_INV_VALUE; - } - memcpy (buffer, a.resp, a.resplen); - buffer[a.resplen] = a.sw1; - buffer[a.resplen+1] = a.sw2; - *buflen = a.resplen + 2; - return 0; -} - -static int -open_osc_reader (int portno) -{ - int err; - int slot; - reader_table_t slotp; - - slot = new_reader_slot (); - if (slot == -1) - return -1; - slotp = reader_table + slot; - - err = sc_establish_context (&slotp->osc.ctx, "scdaemon"); - if (err) - { - log_error ("failed to establish SC context: %s\n", sc_strerror (err)); - slotp->used = 0; - return -1; - } - if (portno < 0 || portno >= slotp->osc.ctx->reader_count) - { - log_error ("no card reader available\n"); - sc_release_context (slotp->osc.ctx); - slotp->used = 0; - return -1; - } - - /* Redirect to our logging facility. */ - slotp->osc.ctx->error_file = log_get_stream (); - slotp->osc.ctx->debug = opt.debug_sc; - slotp->osc.ctx->debug_file = log_get_stream (); - - if (sc_detect_card_presence (slotp->osc.ctx->reader[portno], 0) != 1) - { - log_error ("no card present\n"); - sc_release_context (slotp->osc.ctx); - slotp->used = 0; - return -1; - } - - /* We want the standard ISO driver. */ - /*FIXME: OpenSC does not like "iso7816", so we use EMV for now. */ - err = sc_set_card_driver(slotp->osc.ctx, "emv"); - if (err) - { - log_error ("failed to select the iso7816 driver: %s\n", - sc_strerror (err)); - sc_release_context (slotp->osc.ctx); - slotp->used = 0; - return -1; - } - - /* Now connect the card and hope that OpenSC won't try to be too - smart. */ - err = sc_connect_card (slotp->osc.ctx->reader[portno], 0, - &slotp->osc.scard); - if (err) - { - log_error ("failed to connect card in reader %d: %s\n", - portno, sc_strerror (err)); - sc_release_context (slotp->osc.ctx); - slotp->used = 0; - return -1; - } - if (opt.verbose) - log_info ("connected to card in opensc reader %d using driver `%s'\n", - portno, slotp->osc.scard->driver->name); - - err = sc_lock (slotp->osc.scard); - if (err) - { - log_error ("can't lock card in reader %d: %s\n", - portno, sc_strerror (err)); - sc_disconnect_card (slotp->osc.scard, 0); - sc_release_context (slotp->osc.ctx); - slotp->used = 0; - return -1; - } - - if (slotp->osc.scard->atr_len >= DIM (slotp->atr)) - log_bug ("ATR returned by opensc is too large\n"); - slotp->atrlen = slotp->osc.scard->atr_len; - memcpy (slotp->atr, slotp->osc.scard->atr, slotp->atrlen); - - reader_table[slot].close_reader = close_osc_reader; - reader_table[slot].reset_reader = reset_osc_reader; - reader_table[slot].get_status_reader = osc_get_status; - reader_table[slot].send_apdu_reader = osc_send_apdu; - reader_table[slot].dump_status_reader = NULL; - - dump_reader_status (slot); - return slot; -} - -#endif /* HAVE_OPENSC */ - - #ifdef USE_G10CODE_RAPDU /* @@ -2130,7 +1901,7 @@ my_rapdu_get_status (int slot, unsigned int *status) /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be - set to BUFLEN. Returns: OpenSC error code. */ + set to BUFLEN. Returns: APDU error code. */ static int my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen, unsigned char *buffer, size_t *buflen) @@ -2325,8 +2096,7 @@ unlock_slot (int slot) /* Open the reader and return an internal slot number or -1 on error. If PORTSTR is NULL we default to a suitable port (for ctAPI: - the first USB reader. For PC/SC the first listed reader). If - OpenSC support is compiled in, we first try to use OpenSC. */ + the first USB reader. For PC/SC the first listed reader). */ int apdu_open_reader (const char *portstr) { @@ -2352,16 +2122,6 @@ apdu_open_reader (const char *portstr) #endif /* HAVE_LIBUSB */ -#ifdef HAVE_OPENSC - if (!opt.disable_opensc) - { - int port = portstr? atoi (portstr) : 0; - - return open_osc_reader (port); - } -#endif /* HAVE_OPENSC */ - - if (opt.ctapi_driver && *opt.ctapi_driver) { int port = portstr? atoi (portstr) : 32768; diff --git a/scd/app-common.h b/scd/app-common.h index 4a2adaa54..594f93850 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -175,7 +175,7 @@ int app_select_nks (app_t app); int app_select_dinsig (app_t app); /*-- app-p15.c --*/ -int app_select_p15 (app_t app); +gpg_error_t app_select_p15 (app_t app); #endif diff --git a/scd/app-nks.c b/scd/app-nks.c index e69b59879..f14b67972 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -305,7 +305,7 @@ verify_pin (app_t app, void *pincb_arg) { /* Note that force_chv1 is never set but we do it here anyway so - that other applications may euse this function. For example it + that other applications may reuse this function. For example it makes sense to set force_chv1 for German signature law cards. NKS is very similar to the DINSIG draft standard. */ if (!app->did_chv1 || app->force_chv1 ) @@ -444,7 +444,7 @@ do_decipher (app_t app, const char *keyidstr, { static const unsigned char mse_parm[] = { 0x80, 1, 0x10, /* Select algorithm RSA. */ - 0x84, 1, 0x81 /* Select locak secret key 1 for descryption. */ + 0x84, 1, 0x81 /* Select local secret key 1 for decryption. */ }; int rc, i; int fid; diff --git a/scd/app-p15.c b/scd/app-p15.c index af2eed465..7a92da10b 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -1,5 +1,5 @@ /* app-p15.c - The pkcs#15 card application. - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -31,14 +31,232 @@ #include "iso7816.h" #include "app-common.h" #include "tlv.h" +#include "apdu.h" /* fixme: we should move the card detection to a + separate file */ + +/* Types of cards we know and which needs special treatment. */ +typedef enum + { + CARD_TYPE_UNKNOWN, + CARD_TYPE_TCOS, + CARD_TYPE_MICARDO + } card_type_t; + +/* A list card types with ATRs noticed with these cards. */ +static struct +{ + size_t atrlen; + unsigned char *atr; + card_type_t type; +} card_atr_list[] = { + { 19, "\x3B\xBA\x13\x00\x81\x31\x86\x5D\x00\x64\x05\x0A\x02\x01\x31\x80" + "\x90\x00\x8B", + CARD_TYPE_TCOS }, /* SLE44 */ + { 19, "\x3B\xBA\x14\x00\x81\x31\x86\x5D\x00\x64\x05\x14\x02\x02\x31\x80" + "\x90\x00\x91", + CARD_TYPE_TCOS }, /* SLE66S */ + { 19, "\x3B\xBA\x96\x00\x81\x31\x86\x5D\x00\x64\x05\x60\x02\x03\x31\x80" + "\x90\x00\x66", + CARD_TYPE_TCOS }, /* SLE66P */ + { 27, "\x3B\xFF\x94\x00\xFF\x80\xB1\xFE\x45\x1F\x03\x00\x68\xD2\x76\x00" + "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23", + CARD_TYPE_MICARDO }, /* German BMI card */ + { 26, "\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49" + "\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43", + CARD_TYPE_MICARDO }, /* EstEID (Estonian Big Brother card) */ + { 0 } +}; + + +/* The Pin Types as defined in pkcs#15 v1.1 */ +typedef enum + { + PIN_TYPE_BCD = 0, + PIN_TYPE_ASCII_NUMERIC = 1, + PIN_TYPE_UTF8 = 2, + PIN_TYPE_HALF_NIBBLE_BCD = 3, + PIN_TYPE_ISO9564_1 = 4 + } pin_type_t; + + +/* A bit array with for the key usage flags from the + commonKeyAttributes. */ +struct keyusage_flags_s +{ + unsigned int encrypt: 1; + unsigned int decrypt: 1; + unsigned int sign: 1; + unsigned int sign_recover: 1; + unsigned int wrap: 1; + unsigned int unwrap: 1; + unsigned int verify: 1; + unsigned int verify_recover: 1; + unsigned int derive: 1; + unsigned int non_repudiation: 1; +}; +typedef struct keyusage_flags_s keyusage_flags_t; + + + +/* This is an object to store information about a Certificate + Directory File (CDF) in a format suitable for further processing by + us. To keep memory management, simple we use a linked list of + items; i.e. one such object represents one certificate and the list + the entire CDF. */ +struct cdf_object_s +{ + /* Link to next item when used in a linked list. */ + struct cdf_object_s *next; + + /* Length and allocated buffer with the Id of this object. */ + size_t objidlen; + unsigned char *objid; + + /* To avoid reading a certificate more than once, we cache it in an + allocated memory IMAGE of IMAGELEN. */ + size_t imagelen; + unsigned char *image; + + /* Set to true if a length and offset is available. */ + int have_off; + /* The offset and length of the object. They are only valid if + HAVE_OFF is true and set to 0 if HAVE_OFF is false. */ + unsigned long off, len; + + /* The length of the path as given in the CDF and the path itself. + path[0] is the top DF (usually 0x3f00). The path will never be + empty. */ + size_t pathlen; + unsigned short path[1]; +}; +typedef struct cdf_object_s *cdf_object_t; + + +/* This is an object to store information about a Private Key + Directory File (PrKDF) in a format suitable for further processing + by us. To keep memory management, simple we use a linked list of + items; i.e. one such object represents one certificate and the list + the entire PrKDF. */ +struct prkdf_object_s +{ + /* Link to next item when used in a linked list. */ + struct prkdf_object_s *next; + + /* Length and allocated buffer with the Id of this object. */ + size_t objidlen; + unsigned char *objid; + + /* Length and allocated buffer with the authId of this object or + NULL if no authID is known. */ + size_t authidlen; + unsigned char *authid; + + /* The key's usage flags. */ + keyusage_flags_t usageflags; + + /* The keyReference and a flag telling whether it is valid. */ + unsigned long key_reference; + int key_reference_valid; + + /* Set to true if a length and offset is available. */ + int have_off; + /* The offset and length of the object. They are only valid if + HAVE_OFF is true and set to 0 if HAVE_OFF is false. */ + unsigned long off, len; + + /* The length of the path as given in the PrKDF and the path itself. + path[0] is the top DF (usually 0x3f00). */ + size_t pathlen; + unsigned short path[1]; +}; +typedef struct prkdf_object_s *prkdf_object_t; + + +/* This is an object to store information about a Authentication + Object Directory File (AODF) in a format suitable for further + processing by us. To keep memory management, simple we use a linked + list of items; i.e. one such object represents one authentication + object and the list the entire AOKDF. */ +struct aodf_object_s +{ + /* Link to next item when used in a linked list. */ + struct aodf_object_s *next; + + /* Length and allocated buffer with the Id of this object. */ + size_t objidlen; + unsigned char *objid; + + /* Length and allocated buffer with the authId of this object or + NULL if no authID is known. */ + size_t authidlen; + unsigned char *authid; + + /* The PIN Flags. */ + struct + { + unsigned int case_sensitive: 1; + unsigned int local: 1; + unsigned int change_disabled: 1; + unsigned int unblock_disabled: 1; + unsigned int initialized: 1; + unsigned int needs_padding: 1; + unsigned int unblocking_pin: 1; + unsigned int so_pin: 1; + unsigned int disable_allowed: 1; + unsigned int integrity_protected: 1; + unsigned int confidentiality_protected: 1; + unsigned int exchange_ref_data: 1; + } pinflags; + + /* The PIN Type. */ + pin_type_t pintype; + + /* The minimum length of a PIN. */ + unsigned long min_length; + + /* The stored length of a PIN. */ + unsigned long stored_length; + + /* The maximum length of a PIN and a flag telling whether it is valid. */ + unsigned long max_length; + int max_length_valid; + + /* The pinReference and a flag telling whether it is valid. */ + unsigned long pin_reference; + int pin_reference_valid; + + /* The padChar and a flag telling whether it is valid. */ + char pad_char; + int pad_char_valid; + + + /* Set to true if a length and offset is available. */ + int have_off; + /* The offset and length of the object. They are only valid if + HAVE_OFF is true and set to 0 if HAVE_OFF is false. */ + unsigned long off, len; + + /* The length of the path as given in the Aodf and the path itself. + path[0] is the top DF (usually 0x3f00). PATH is optional and thus + may be NULL. Malloced.*/ + size_t pathlen; + unsigned short *path; +}; +typedef struct aodf_object_s *aodf_object_t; /* Context local to this application. */ struct app_local_s { - unsigned short home_df; /* The home DF. Note, that we don't yet - support a multilevel hierachy. Thus we - assume this is directly below the MF. */ + /* The home DF. Note, that we don't yet support a multilevel + hierachy. Thus we assume this is directly below the MF. */ + unsigned short home_df; + + /* The type of the card. */ + card_type_t card_type; + + /* Structure with the EFIDs of the objects described in the ODF + file. */ struct { unsigned short private_keys; @@ -52,16 +270,104 @@ struct app_local_s unsigned short auth_objects; } odf; + /* Information on all certificates. */ + cdf_object_t certificate_info; + /* Information on all trusted certificates. */ + cdf_object_t trusted_certificate_info; + /* Information on all useful certificates. */ + cdf_object_t useful_certificate_info; + + /* Information on all private keys. */ + prkdf_object_t private_key_info; + + /* Information on all authentication objects. */ + aodf_object_t auth_object_info; }; +/*** Local prototypes. ***/ +static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf, + unsigned char **r_cert, size_t *r_certlen); + + + +/* Release the CDF object A */ +static void +release_cdflist (cdf_object_t a) +{ + while (a) + { + cdf_object_t tmp = a->next; + xfree (a->image); + xfree (a->objid); + xfree (a); + a = tmp; + } +} + +/* Release the PrKDF object A. */ +static void +release_prkdflist (prkdf_object_t a) +{ + while (a) + { + prkdf_object_t tmp = a->next; + xfree (a->objid); + xfree (a->authid); + xfree (a); + a = tmp; + } +} + +/* Release just one aodf object. */ +void +release_aodf_object (aodf_object_t a) +{ + if (a) + { + xfree (a->objid); + xfree (a->authid); + xfree (a->path); + xfree (a); + } +} + +/* Release the AODF list A. */ +static void +release_aodflist (aodf_object_t a) +{ + while (a) + { + aodf_object_t tmp = a->next; + release_aodf_object (a); + a = tmp; + } +} + + +/* Release all local resources. */ +static void +do_deinit (app_t app) +{ + if (app && app->app_local) + { + release_cdflist (app->app_local->certificate_info); + release_cdflist (app->app_local->trusted_certificate_info); + release_cdflist (app->app_local->useful_certificate_info); + release_prkdflist (app->app_local->private_key_info); + release_aodflist (app->app_local->auth_object_info); + xfree (app->app_local); + app->app_local = NULL; + } +} + -/* Do a select and a read for the file with EFID. EFID is a +/* Do a select and a read for the file with EFID. EFID_DESC is a desctription of the EF to be used with error messages. On success BUFFER and BUFLEN contain the entire content of the EF. The caller - must free BUFFER but only on success. */ + must free BUFFER only on success. */ static gpg_error_t select_and_read_binary (int slot, unsigned short efid, const char *efid_desc, unsigned char **buffer, size_t *buflen) @@ -86,10 +392,151 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc, } +/* This function calls select file to read a file suing a complete + path which may or may not start at the master file (MF). */ +static gpg_error_t +select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen) +{ + gpg_error_t err; + int i, j; + + /* FIXME: Need code to remember the last PATH so that we can decide + what select commands to send in case the path does not start off + with 3F00. We might also want to use direct path selection if + supported by the card. */ + if (pathlen && *path != 0x3f00 ) + log_debug ("WARNING: relative path selection not yet implemented\n"); + + for (i=0; i < pathlen; i++) + { + err = iso7816_select_file (app->slot, path[i], + !(i+1 == pathlen), NULL, NULL); + if (err) + { + log_error ("error selecting part %d from path ", i); + for (j=0; j < pathlen; j++) + log_printf ("%04hX", path[j]); + log_printf (": %s\n", gpg_strerror (err)); + return err; + } + } + return 0; +} + +/* Parse a cert Id string (or a key Id string) and return the binary + object Id string in a newly allocated buffer stored at R_OBJID and + R_OBJIDLEN. On Error NULL will be stored there and an error code + returned. On success caller needs to free the buffer at R_OBJID. */ +static gpg_error_t +parse_certid (app_t app, const char *certid, + unsigned char **r_objid, size_t *r_objidlen) +{ + char tmpbuf[10]; + const char *s; + size_t objidlen; + unsigned char *objid; + int i; + + *r_objid = NULL; + *r_objidlen = 0; + + if (app->app_local->home_df) + sprintf (tmpbuf, "P15-%04hX.", (app->app_local->home_df & 0xffff)); + else + strcpy (tmpbuf, "P15."); + if (strncmp (certid, tmpbuf, strlen (tmpbuf)) ) + { + if (!strncmp (certid, "P15.", 4) + || (!strncmp (certid, "P15-", 4) + && hexdigitp (certid+4) + && hexdigitp (certid+5) + && hexdigitp (certid+6) + && hexdigitp (certid+7) + && certid[8] == '.')) + return gpg_error (GPG_ERR_NOT_FOUND); + return gpg_error (GPG_ERR_INV_ID); + } + certid += strlen (tmpbuf); + + for (s=certid, objidlen=0; hexdigitp (s); s++, objidlen++) + ; + if (*s || !objidlen || (objidlen%2)) + return gpg_error (GPG_ERR_INV_ID); + objidlen /= 2; + objid = xtrymalloc (objidlen); + if (!objid) + return gpg_error_from_errno (errno); + for (s=certid, i=0; i < objidlen; i++, s+=2) + objid[i] = xtoi_2 (s); + *r_objid = objid; + *r_objidlen = objidlen; + return 0; +} + + +/* Find a certificate object by the certificate ID CERTID and store a + pointer to it at R_CDF. */ +static gpg_error_t +cdf_object_from_certid (app_t app, const char *certid, cdf_object_t *r_cdf) +{ + gpg_error_t err; + size_t objidlen; + unsigned char *objid; + cdf_object_t cdf; + + err = parse_certid (app, certid, &objid, &objidlen); + if (err) + return err; + + for (cdf = app->app_local->certificate_info; cdf; cdf = cdf->next) + if (cdf->objidlen == objidlen && !memcmp (cdf->objid, objid, objidlen)) + break; + if (!cdf) + for (cdf = app->app_local->trusted_certificate_info; cdf; cdf = cdf->next) + if (cdf->objidlen == objidlen && !memcmp (cdf->objid, objid, objidlen)) + break; + if (!cdf) + for (cdf = app->app_local->useful_certificate_info; cdf; cdf = cdf->next) + if (cdf->objidlen == objidlen && !memcmp (cdf->objid, objid, objidlen)) + break; + xfree (objid); + if (!cdf) + return gpg_error (GPG_ERR_NOT_FOUND); + *r_cdf = cdf; + return 0; +} + + +/* Find a private key object by the key Id string KEYIDSTR and store a + pointer to it at R_PRKDF. */ +static gpg_error_t +prkdf_object_from_keyidstr (app_t app, const char *keyidstr, + prkdf_object_t *r_prkdf) +{ + gpg_error_t err; + size_t objidlen; + unsigned char *objid; + prkdf_object_t prkdf; + + err = parse_certid (app, keyidstr, &objid, &objidlen); + if (err) + return err; + + for (prkdf = app->app_local->private_key_info; prkdf; prkdf = prkdf->next) + if (prkdf->objidlen == objidlen && !memcmp (prkdf->objid, objid, objidlen)) + break; + xfree (objid); + if (!prkdf) + return gpg_error (GPG_ERR_NOT_FOUND); + *r_prkdf = prkdf; + return 0; +} + + /* Read and parse the Object Directory File and store away the - pointers. + pointers. ODF_FID shall contain the FID of the ODF. Example of such a file: @@ -99,32 +546,49 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc, A7 06 30 04 04 02 60 37 = DataObjects A8 06 30 04 04 02 60 38 = AuthObjects - These are all PathOrObjects using the path CHOICE. The paths are - octet strings of length 2. Using this Path CHOICE is recommended, - so we only implement that for now. + These are all PathOrObjects using the path CHOICE element. The + paths are octet strings of length 2. Using this Path CHOICE + element is recommended, so we only implement that for now. */ static gpg_error_t -read_ef_odf (app_t app) +read_ef_odf (app_t app, unsigned short odf_fid) { gpg_error_t err; unsigned char *buffer, *p; size_t buflen; unsigned short value; + size_t offset; - err = select_and_read_binary (app->slot, 0x5031, "ODF", &buffer, &buflen); + err = select_and_read_binary (app->slot, odf_fid, "ODF", &buffer, &buflen); if (err) return err; - if (len < 8) + if (buflen < 8) { log_error ("error: ODF too short\n"); xfree (buffer); return gpg_error (GPG_ERR_INV_OBJ); } - for (p=buffer; buflen >= 8; p += 8, buflen -= 8) + p = buffer; + while (buflen && *p && *p != 0xff) { - if ( (p[0] & 0xf0) != 0xA0 - || memcmp (p+1, "\x06\x30\x04\x04\x02", 5) ) + if ( buflen >= 8 + && (p[0] & 0xf0) == 0xA0 + && !memcmp (p+1, "\x06\x30\x04\x04\x02", 5) ) + { + offset = 6; + } + else if ( buflen >= 12 + && (p[0] & 0xf0) == 0xA0 + && !memcmp (p+1, "\x0a\x30\x08\x04\x06\x3F\x00\x50\x15", 9) + && app->app_local->home_df == 0x5015 ) + { + /* This format using a full path is used by a self-created + test card of mine. I have not checked whether this is + legal. We assume a home DF of 0x5015 here. */ + offset = 10; + } + else { log_error ("ODF format is not supported by us\n"); xfree (buffer); @@ -145,10 +609,10 @@ read_ef_odf (app_t app) } if (value) { - log_error ("duplicate object type %d in ODF ignored\n",(p[0)&0x0f)); + log_error ("duplicate object type %d in ODF ignored\n",(p[0]&0x0f)); continue; } - value = ((p[6] << 8) | p[7]); + value = ((p[offset] << 8) | p[offset+1]); switch ((p[0] & 0x0f)) { case 0: app->app_local->odf.private_keys = value; break; @@ -161,8 +625,14 @@ read_ef_odf (app_t app) case 7: app->app_local->odf.data_objects = value; break; case 8: app->app_local->odf.auth_objects = value; break; default: - log_error ("unknown object type %d in ODF ignored\n", (p[0)&0x0f)); + log_error ("unknown object type %d in ODF ignored\n", (p[0]&0x0f)); } + offset += 2; + + if (buflen < offset) + break; + p += offset; + buflen -= offset; } if (buflen) @@ -173,6 +643,70 @@ read_ef_odf (app_t app) } +/* Parse the BIT STRING with the keyUsageFlags from teh + CommonKeyAttributes. */ +static gpg_error_t +parse_keyusage_flags (const unsigned char *der, size_t derlen, + keyusage_flags_t *usageflags) +{ + unsigned int bits, mask; + int i, unused, full; + + memset (usageflags, 0, sizeof *usageflags); + if (!derlen) + return gpg_error (GPG_ERR_INV_OBJ); + + unused = *der++; derlen--; + if ((!derlen && unused) || unused/8 > derlen) + return gpg_error (GPG_ERR_ENCODING_PROBLEM); + full = derlen - (unused+7)/8; + unused %= 8; + mask = 0; + for (i=1; unused; i <<= 1, unused--) + mask |= i; + + /* First octet */ + if (derlen) + { + bits = *der++; derlen--; + if (full) + full--; + else + { + bits &= ~mask; + mask = 0; + } + } + else + bits = 0; + if ((bits & 0x80)) usageflags->encrypt = 1; + if ((bits & 0x40)) usageflags->decrypt = 1; + if ((bits & 0x20)) usageflags->sign = 1; + if ((bits & 0x10)) usageflags->sign_recover = 1; + if ((bits & 0x08)) usageflags->wrap = 1; + if ((bits & 0x04)) usageflags->unwrap = 1; + if ((bits & 0x02)) usageflags->verify = 1; + if ((bits & 0x01)) usageflags->verify_recover = 1; + + /* Second octet. */ + if (derlen) + { + bits = *der++; derlen--; + if (full) + full--; + else + { + bits &= ~mask; + mask = 0; + } + } + else + bits = 0; + if ((bits & 0x80)) usageflags->derive = 1; + if ((bits & 0x40)) usageflags->non_repudiation = 1; + + return 0; +} /* Read and parse the Private Key Directory Files. */ /* @@ -195,135 +729,77 @@ read_ef_odf (app_t app) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -*/ -static gpg_error_t -read_ef_prkdf (app_t app) -{ - - -} - -/* Read and parse the Public Key Directory Files. */ -static gpg_error_t -read_ef_pukdf (app_t app) -{ - - -} - - -/* Read and parse the Certificate Directory Files. */ -/* - -6035 (certificates) - -30 2A 30 15 0C 0C 43 5F 58 35 30 39 2E 43 48 2E 0*0...C_X509.CH. -44 53 03 02 06 40 04 01 0A 30 03 04 01 01 A1 0C DS...@...0...... -30 0A 30 08 04 06 3F 00 40 16 C0 00 30 2A 30 15 0.0...?.@...0*0. -0C 0C 43 5F 58 35 30 39 2E 43 48 2E 4B 45 03 02 ..C_X509.CH.KE.. -06 40 04 01 0A 30 03 04 01 0C A1 0C 30 0A 30 08 .@...0......0.0. -04 06 3F 00 40 16 C2 00 30 2B 30 16 0C 0D 43 5F ..?.@...0+0...C_ -58 35 30 39 2E 43 48 2E 41 55 54 03 02 06 40 04 X509.CH.AUT...@. -01 0A 30 03 04 01 0D A1 0C 30 0A 30 08 04 06 3F ..0......0.0...? -00 40 16 C5 00 30 2E 30 19 0C 10 43 5F 58 35 30 .@...0.0...C_X50 -39 2E 43 48 2E 44 53 2D 53 50 58 03 02 06 40 04 9.CH.DS-SPX...@. -01 0A 30 03 04 01 02 A1 0C 30 0A 30 08 04 06 3F ..0......0.0...? -00 40 16 C1 20 00 00 00 00 00 00 00 00 00 00 00 .@.. ........... -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - - 0 42: SEQUENCE { - 2 21: SEQUENCE { -- commonObjectAttributes - 4 12: UTF8String 'C_X509.CH.DS' - 18 2: BIT STRING 6 unused bits - : '10'B (bit 1) - 22 1: OCTET STRING 0A - : } - 25 3: SEQUENCE { -- commonCertificateAttributes - 27 1: OCTET STRING 01 - : } - 30 12: [1] { -- certAttributes - 32 10: SEQUENCE { - 34 8: SEQUENCE { - 36 6: OCTET STRING 3F 00 40 16 C0 00 - : } - : } - : } - : } - - - -6036 (trustedcertificates) - -30 35 30 06 03 02 00 00 04 00 30 16 04 14 2D 36 050.......0...-6 -33 39 33 33 39 34 30 33 39 37 37 36 34 30 31 32 3933940397764012 -31 36 A1 13 30 11 30 0F 04 06 3F 00 40 16 C7 08 16..0.0...?.@... -02 01 00 80 02 02 29 30 35 30 06 03 02 00 00 04 ......)050...... -00 30 16 04 14 2D 34 30 31 39 30 35 32 37 32 36 .0...-4019052726 -38 30 31 36 39 33 34 39 32 A1 13 30 11 30 0F 04 801693492..0.0.. -06 3F 00 40 16 C7 0E 02 01 00 80 02 04 12 30 34 .?.@..........04 -30 06 03 02 00 00 04 00 30 15 04 13 37 39 36 33 0.......0...7963 -32 38 33 36 35 30 37 36 36 34 38 32 39 36 30 A1 283650766482960. -13 30 11 30 0F 04 06 3F 00 40 16 C0 08 02 01 00 .0.0...?.@...... -80 02 04 11 00 00 00 00 00 00 00 00 00 00 00 00 ................ -00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - - 0 53: SEQUENCE { - 2 6: SEQUENCE { - 4 2: BIT STRING - : '00000000'B - : Error: Spurious zero bits in bitstring. - 8 0: OCTET STRING - : Error: Object has zero length. - : } - 10 22: SEQUENCE { - 12 20: OCTET STRING '-6393394039776401216' - : } - 34 19: [1] { - 36 17: SEQUENCE { - 38 15: SEQUENCE { - 40 6: OCTET STRING 3F 00 40 16 C7 08 - 48 1: INTEGER 0 -- index - 51 2: [0] 02 29 -- length - : } - : } - : } - : } + 0 30 51: SEQUENCE { + 2 30 17: SEQUENCE { -- commonObjectAttributes + 4 0C 8: UTF8String 'SK.CH.DS' + 14 03 2: BIT STRING 6 unused bits + : '01'B (bit 0) + 18 04 1: OCTET STRING --authid + : 07 + : } + 21 30 12: SEQUENCE { -- commonKeyAttributes + 23 04 1: OCTET STRING + : 01 + 26 03 3: BIT STRING 6 unused bits + : '1000000000'B (bit 9) + 31 02 2: INTEGER 80 -- keyReference (optional) + : } + 35 A1 16: [1] { -- keyAttributes + 37 30 14: SEQUENCE { -- privateRSAKeyAttributes + 39 30 8: SEQUENCE { -- objectValue + 41 04 6: OCTET STRING --path + : 3F 00 40 16 00 50 + : } + 49 02 2: INTEGER 1024 -- modulus + : } + : } + : } */ static gpg_error_t -read_ef_cdf (app_t app) +read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result) { gpg_error_t err; unsigned char *buffer = NULL; size_t buflen; - unsigned short value; - unsigned short fid; const unsigned char *p; size_t n, objlen, hdrlen; int class, tag, constructed, ndef; + prkdf_object_t prkdflist = NULL; + int i; - fid = app->app_local->odf.certificates; if (!fid) - return 0; /* No certificates. */ + return gpg_error (GPG_ERR_NO_DATA); /* No private keys. */ - err = select_and_read_binary (app->slot, fid, "CDF", &buffer, &buflen); + err = select_and_read_binary (app->slot, fid, "PrKDF", &buffer, &buflen); if (err) return err; p = buffer; n = buflen; + /* FIXME: This shares a LOT of code with read_ef_cdf! */ + /* Loop over the records. We stop as soon as we detect a new record - starting with 0x00 or 0xff as these values are commonly used to pad - the the read datablocks and are no valid ASN.1 encoding. */ - while (n && *p && *p == 0xff) + starting with 0x00 or 0xff as these values are commonly used to + pad data blocks and are no valid ASN.1 encoding. */ + while (n && *p && *p != 0xff) { const unsigned char *pp; size_t nn; + int where; + const char *errstr = NULL; + prkdf_object_t prkdf = NULL; + unsigned long ul; + const unsigned char *objid; + size_t objidlen; + const unsigned char *authid = NULL; + size_t authidlen = 0; + keyusage_flags_t usageflags; + unsigned long key_reference = 0; + int key_reference_valid = 0; + const char *s; err = parse_ber_header (&p, &n, &class, &tag, &constructed, &ndef, &objlen, &hdrlen); @@ -331,7 +807,7 @@ read_ef_cdf (app_t app) err = gpg_error (GPG_ERR_INV_OBJ); if (err) { - log_error ("error parsing CDF record: %s\n", gpg_strerror (err)); + log_error ("error parsing PrKDF record: %s\n", gpg_strerror (err)); goto leave; } pp = p; @@ -339,144 +815,1299 @@ read_ef_cdf (app_t app) p += objlen; n -= objlen; - /* Skip the commonObjectAttributes. */ + /* Parse the commonObjectAttributes. */ + where = __LINE__; err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, &ndef, &objlen, &hdrlen); if (!err && (objlen > nn || tag != TAG_SEQUENCE)) err = gpg_error (GPG_ERR_INV_OBJ); if (err) - { - log_error ("error parsing CDF record: %s - skipped\n", - gpg_strerror (err)); - continue; - } - pp += objlen; - nn -= objlen; - - /* Skip the commonCertificateAttributes. */ + goto parse_error; + { + const unsigned char *ppp = pp; + size_t nnn = objlen; + + pp += objlen; + nn -= objlen; + + /* Search the optional AuthId. We need to skip the optional + Label (UTF8STRING) and the optional CommonObjectFlags + (BITSTRING). */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto no_authid; + if (err) + goto parse_error; + if (tag == TAG_UTF8_STRING) + { + ppp += objlen; /* Skip the Label. */ + nnn -= objlen; + + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto no_authid; + if (err) + goto parse_error; + } + if (tag == TAG_BIT_STRING) + { + ppp += objlen; /* Skip the CommonObjectFlags. */ + nnn -= objlen; + + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto no_authid; + if (err) + goto parse_error; + } + if (tag == TAG_OCTET_STRING && objlen) + { + authid = ppp; + authidlen = objlen; + } + no_authid: + ; + } + + /* Parse the commonKeyAttributes. */ + where = __LINE__; err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, &ndef, &objlen, &hdrlen); if (!err && (objlen > nn || tag != TAG_SEQUENCE)) err = gpg_error (GPG_ERR_INV_OBJ); if (err) - { - log_error ("error parsing CDF record: %s - skipped\n", - gpg_strerror (err)); - continue; - } - pp += objlen; - nn -= objlen; - - /* FIXME: Check that this is a reference to a certificate. */ - - - } - + goto parse_error; + { + const unsigned char *ppp = pp; + size_t nnn = objlen; - leave: - xfree (buffer); - return err; -} + pp += objlen; + nn -= objlen; -/* Read and parse Authentication Object Directory Files. */ -static gpg_error_t -read_ef_aodf (app_t app) -{ - -} + /* Get the Id. */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn + || class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + objid = ppp; + objidlen = objlen; + ppp += objlen; + nnn -= objlen; + + /* Get the KeyUsageFlags. */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn + || class != CLASS_UNIVERSAL || tag != TAG_BIT_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + err = parse_keyusage_flags (ppp, objlen, &usageflags); + if (err) + goto parse_error; + ppp += objlen; + nnn -= objlen; + + /* Find the keyReference */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto leave_cki; + if (!err && objlen > nnn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class == CLASS_UNIVERSAL && tag == TAG_BOOLEAN) + { + /* Skip the native element. */ + ppp += objlen; + nnn -= objlen; + + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto leave_cki; + if (!err && objlen > nnn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + } + if (class == CLASS_UNIVERSAL && tag == TAG_BIT_STRING) + { + /* Skip the accessFlags. */ + ppp += objlen; + nnn -= objlen; + + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto leave_cki; + if (!err && objlen > nnn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + } + if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER) + { + /* Yep, this is the keyReference. */ + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*ppp++) & 0xff; + nnn--; + } + key_reference = ul; + key_reference_valid = 1; + } + leave_cki: + ; + } -/* 6037 (dataobjects) - -30 1E 30 0B 0C 06 45 46 2E 47 44 4F 04 01 0A 30 0.0...EF.GDO...0 -02 0C 00 A1 0B 30 09 04 04 3F 00 2F 02 80 01 0E .....0...?./.... -30 30 30 18 0C 0F 64 69 73 70 6C 61 79 20 6D 65 000...display me -73 73 61 67 65 03 02 06 C0 04 01 0A 30 05 0C 03 ssage.......0... -42 53 53 A1 0D 30 0B 04 06 3F 00 40 16 D0 00 80 BSS..0...?.@.... -01 20 30 2B 30 0C 0C 03 53 53 4F 03 02 06 C0 04 . 0+0...SSO..... -01 0A 30 0B 0C 09 53 61 66 65 47 75 61 72 64 A1 ..0...SafeGuard. -0E 30 0C 04 06 3F 00 0F FF 30 02 80 02 03 00 30 .0...?...0.....0 -30 30 11 0C 08 53 47 41 53 64 61 74 61 03 02 06 00...SGASdata... -C0 04 01 0A 30 0B 0C 09 53 61 66 65 47 75 61 72 ....0...SafeGuar -64 A1 0E 30 0C 04 06 3F 00 0F FF 40 01 80 02 00 d..0...?...@.... -80 30 30 30 11 0C 08 55 73 65 72 64 61 74 61 03 .000...Userdata. -02 06 40 04 01 0A 30 0B 0C 09 53 61 66 65 47 75 ..@...0...SafeGu -61 72 64 A1 0E 30 0C 04 06 3F 00 0F FF 30 01 80 ard..0...?...0.. -02 01 00 30 2C 30 13 0C 0A 62 61 73 69 63 20 64 ...0,0...basic d -61 74 61 03 02 06 C0 04 01 0A 30 05 0C 03 49 44 ata.......0...ID -44 A1 0E 30 0C 04 06 3F 00 40 17 D0 01 80 02 02 D..0...?.@...... -00 30 2F 30 16 0C 0D 65 78 74 65 6E 64 65 64 20 .0/0...extended -64 61 74 61 03 02 06 C0 04 01 0A 30 05 0C 03 49 data.......0...I -44 44 A1 0E 30 0C 04 06 3F 00 40 17 D0 02 80 02 DD..0...?.@..... -08 00 30 34 30 1B 0C 12 73 70 65 63 69 61 6C 20 ..040...special -70 72 69 76 69 6C 65 67 65 73 03 02 06 C0 04 01 privileges...... -0A 30 05 0C 03 49 44 44 A1 0E 30 0C 04 06 3F 00 .0...IDD..0...?. -40 17 D0 03 80 02 04 00 @....... - - 0 30: SEQUENCE { - 2 11: SEQUENCE { - 4 6: UTF8String 'EF.GDO' - 12 1: OCTET STRING 0A - : } - 15 2: SEQUENCE { - 17 0: UTF8String - : Error: Object has zero length. - : } - 19 11: [1] { - 21 9: SEQUENCE { - 23 4: OCTET STRING 3F 00 2F 02 - 29 1: [0] 0E - : } - : } - : } + /* Skip subClassAttributes. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class == CLASS_CONTEXT && tag == 0) + { + pp += objlen; + nn -= objlen; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + } + /* Parse the keyAttributes. */ + if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + nn = objlen; + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE) + ; /* RSA */ + else if (class == CLASS_CONTEXT) + { + switch (tag) + { + case 0: errstr = "EC key objects are not supported"; break; + case 1: errstr = "DH key objects are not supported"; break; + case 2: errstr = "DSA key objects are not supported"; break; + case 3: errstr = "KEA key objects are not supported"; break; + default: errstr = "unknown privateKeyObject"; break; + } + goto parse_error; + } + else + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto parse_error; + } -6038 (authobjects) - -30 2A 30 0B 0C 05 62 61 73 69 63 03 02 00 C0 30 0*0...basic....0 -03 04 01 0A A1 16 30 14 03 03 00 0C 10 0A 01 01 ......0......... -02 01 06 02 01 06 02 01 08 80 01 01 30 51 30 19 ............0Q0. -0C 13 73 70 65 63 69 66 69 63 20 50 49 4E 20 66 ..specific PIN f -6F 72 20 44 53 03 02 00 C0 30 03 04 01 07 A1 2F or DS....0...../ -30 2D 03 03 00 4C 10 0A 01 01 02 01 06 02 01 06 0-...L.......... -02 01 08 80 01 02 18 0F 32 30 30 32 30 34 31 39 ........20020419 -31 32 31 33 34 31 5A 30 06 04 04 3F 00 40 16 121341Z0...?.@. - - 0 42: SEQUENCE { - 2 11: SEQUENCE { - 4 5: UTF8String 'basic' - 11 2: BIT STRING - : '00000011'B - : Error: Spurious zero bits in bitstring. - : } - 15 3: SEQUENCE { - 17 1: OCTET STRING 0A - : } - 20 22: [1] { - 22 20: SEQUENCE { - 24 3: BIT STRING - : '0000100000110000'B - : Error: Spurious zero bits in bitstring. - 29 1: ENUMERATED 1 - 32 1: INTEGER 6 - 35 1: INTEGER 6 - 38 1: INTEGER 8 - 41 1: [0] 01 - : } - : } - : } + nn = objlen; + /* Check that the reference is a Path object. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class != CLASS_UNIVERSAL || tag != TAG_SEQUENCE) + { + errstr = "unsupported reference type"; + goto parse_error; + } + nn = objlen; + /* Parse the Path object. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; -*/ + /* Make sure that the next element is a non zero path and of + even length (FID are two bytes each). */ + if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING + || !objlen || (objlen & 1) ) + { + errstr = "invalid path reference"; + goto parse_error; + } + /* Create a new PrKDF list item. */ + prkdf = xtrycalloc (1, (sizeof *prkdf + - sizeof(unsigned short) + + objlen/2 * sizeof(unsigned short))); + if (!prkdf) + { + err = gpg_error_from_errno (errno); + goto leave; + } + prkdf->objidlen = objidlen; + prkdf->objid = xtrymalloc (objidlen); + if (!prkdf->objid) + { + err = gpg_error_from_errno (errno); + xfree (prkdf); + goto leave; + } + memcpy (prkdf->objid, objid, objidlen); + if (authid) + { + prkdf->authidlen = authidlen; + prkdf->authid = xtrymalloc (authidlen); + if (!prkdf->authid) + { + err = gpg_error_from_errno (errno); + xfree (prkdf->objid); + xfree (prkdf); + goto leave; + } + memcpy (prkdf->authid, authid, authidlen); + } + prkdf->pathlen = objlen/2; + for (i=0; i < prkdf->pathlen; i++, pp += 2, nn -= 2) + prkdf->path[i] = ((pp[0] << 8) | pp[1]); -/* Read and parse the EF(TokenInfo). + prkdf->usageflags = usageflags; + prkdf->key_reference = key_reference; + prkdf->key_reference_valid = key_reference_valid; -TokenInfo ::= SEQUENCE { - version INTEGER {v1(0)} (v1,...), - serialNumber OCTET STRING, + if (nn) + { + /* An index and length follows. */ + prkdf->have_off = 1; + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_UNIVERSAL || tag != TAG_INTEGER)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + prkdf->off = ul; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_CONTEXT || tag != 0)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + prkdf->len = ul; + } + + + log_debug ("PrKDF %04hX: id=", fid); + for (i=0; i < prkdf->objidlen; i++) + log_printf ("%02X", prkdf->objid[i]); + log_printf (" path="); + for (i=0; i < prkdf->pathlen; i++) + log_printf ("%04hX", prkdf->path[i]); + if (prkdf->have_off) + log_printf ("[%lu/%lu]", prkdf->off, prkdf->len); + if (prkdf->authid) + { + log_printf (" authid="); + for (i=0; i < prkdf->authidlen; i++) + log_printf ("%02X", prkdf->authid[i]); + } + if (prkdf->key_reference_valid) + log_printf (" keyref=0x%02lX", prkdf->key_reference); + log_printf (" usage="); + s = ""; + if (prkdf->usageflags.encrypt) log_printf ("%sencrypt", s), s = ","; + if (prkdf->usageflags.decrypt) log_printf ("%sdecrypt", s), s = ","; + if (prkdf->usageflags.sign ) log_printf ("%ssign", s), s = ","; + if (prkdf->usageflags.sign_recover) + log_printf ("%ssign_recover", s), s = ","; + if (prkdf->usageflags.wrap ) log_printf ("%swrap", s), s = ","; + if (prkdf->usageflags.unwrap ) log_printf ("%sunwrap", s), s = ","; + if (prkdf->usageflags.verify ) log_printf ("%sverify", s), s = ","; + if (prkdf->usageflags.verify_recover) + log_printf ("%sverify_recover", s), s = ","; + if (prkdf->usageflags.derive ) log_printf ("%sderive", s), s = ","; + if (prkdf->usageflags.non_repudiation) + log_printf ("%snon_repudiation", s), s = ","; + log_printf ("\n"); + + /* Put it into the list. */ + prkdf->next = prkdflist; + prkdflist = prkdf; + prkdf = NULL; + continue; /* Ready. */ + + parse_error: + log_error ("error parsing PrKDF record (%d): %s - skipped\n", + where, errstr? errstr : gpg_strerror (err)); + if (prkdf) + { + xfree (prkdf->objid); + xfree (prkdf->authid); + xfree (prkdf); + } + err = 0; + } /* End looping over all records. */ + + leave: + xfree (buffer); + if (err) + release_prkdflist (prkdflist); + else + *result = prkdflist; + return err; +} + + +/* Read and parse the Certificate Directory Files identified by FID. + On success a newlist of CDF object gets stored at RESULT and the + caller is then responsible of releasing this list. On error a + error code is returned and RESULT won't get changed. */ +static gpg_error_t +read_ef_cdf (app_t app, unsigned short fid, cdf_object_t *result) +{ + gpg_error_t err; + unsigned char *buffer = NULL; + size_t buflen; + const unsigned char *p; + size_t n, objlen, hdrlen; + int class, tag, constructed, ndef; + cdf_object_t cdflist = NULL; + int i; + + if (!fid) + return gpg_error (GPG_ERR_NO_DATA); /* No certificates. */ + + err = select_and_read_binary (app->slot, fid, "CDF", &buffer, &buflen); + if (err) + return err; + + p = buffer; + n = buflen; + + /* Loop over the records. We stop as soon as we detect a new record + starting with 0x00 or 0xff as these values are commonly used to + pad data blocks and are no valid ASN.1 encoding. */ + while (n && *p && *p != 0xff) + { + const unsigned char *pp; + size_t nn; + int where; + const char *errstr = NULL; + cdf_object_t cdf = NULL; + unsigned long ul; + const unsigned char *objid; + size_t objidlen; + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > n || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + log_error ("error parsing CDF record: %s\n", gpg_strerror (err)); + goto leave; + } + pp = p; + nn = objlen; + p += objlen; + n -= objlen; + + /* Skip the commonObjectAttributes. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + pp += objlen; + nn -= objlen; + + /* Parse the commonCertificateAttributes. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + { + const unsigned char *ppp = pp; + size_t nnn = objlen; + + pp += objlen; + nn -= objlen; + + /* Get the Id. */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn + || class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + objid = ppp; + objidlen = objlen; + } + + /* Parse the certAttribute. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + nn = objlen; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_UNIVERSAL || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + nn = objlen; + + /* Check that the reference is a Path object. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class != CLASS_UNIVERSAL || tag != TAG_SEQUENCE) + { + errstr = "unsupported reference type"; + continue; + } + nn = objlen; + + /* Parse the Path object. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + /* Make sure that the next element is a non zero path and of + even length (FID are two bytes each). */ + if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING + || !objlen || (objlen & 1) ) + { + errstr = "invalid path reference"; + goto parse_error; + } + /* Create a new CDF list item. */ + cdf = xtrycalloc (1, (sizeof *cdf + - sizeof(unsigned short) + + objlen/2 * sizeof(unsigned short))); + if (!cdf) + { + err = gpg_error_from_errno (errno); + goto leave; + } + cdf->objidlen = objidlen; + cdf->objid = xtrymalloc (objidlen); + if (!cdf->objid) + { + err = gpg_error_from_errno (errno); + xfree (cdf); + goto leave; + } + memcpy (cdf->objid, objid, objidlen); + + cdf->pathlen = objlen/2; + for (i=0; i < cdf->pathlen; i++, pp += 2, nn -= 2) + cdf->path[i] = ((pp[0] << 8) | pp[1]); + + if (nn) + { + /* An index and length follows. */ + cdf->have_off = 1; + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_UNIVERSAL || tag != TAG_INTEGER)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + cdf->off = ul; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_CONTEXT || tag != 0)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + cdf->len = ul; + } + + log_debug ("CDF %04hX: id=", fid); + for (i=0; i < cdf->objidlen; i++) + log_printf ("%02X", cdf->objid[i]); + log_printf (" path="); + for (i=0; i < cdf->pathlen; i++) + log_printf ("%04hX", cdf->path[i]); + if (cdf->have_off) + log_printf ("[%lu/%lu]", cdf->off, cdf->len); + log_printf ("\n"); + + /* Put it into the list. */ + cdf->next = cdflist; + cdflist = cdf; + cdf = NULL; + continue; /* Ready. */ + + parse_error: + log_error ("error parsing CDF record (%d): %s - skipped\n", + where, errstr? errstr : gpg_strerror (err)); + xfree (cdf); + err = 0; + } /* End looping over all records. */ + + leave: + xfree (buffer); + if (err) + release_cdflist (cdflist); + else + *result = cdflist; + return err; +} + + +/* +SEQUENCE { + SEQUENCE { -- CommonObjectAttributes + UTF8String 'specific PIN for DS' + BIT STRING 0 unused bits + '00000011'B + } + SEQUENCE { -- CommonAuthenticationObjectAttributes + OCTET STRING + 07 -- iD + } + + [1] { -- typeAttributes + SEQUENCE { -- PinAttributes + BIT STRING 0 unused bits + '0000100000110010'B -- local,initialized,needs-padding + -- exchangeRefData + ENUMERATED 1 -- ascii-numeric + INTEGER 6 -- minLength + INTEGER 6 -- storedLength + INTEGER 8 -- maxLength + [0] + 02 -- pinReference + GeneralizedTime 19/04/2002 12:12 GMT -- lastPinChange + SEQUENCE { + OCTET STRING + 3F 00 40 16 -- path to DF of PIN + } + } + } + } + +*/ +/* Read and parse an Authentication Object Directory File identified + by FID. On success a newlist of AODF objects gets stored at RESULT + and the caller is responsible of releasing this list. On error a + error code is returned and RESULT won't get changed. */ +static gpg_error_t +read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result) +{ + gpg_error_t err; + unsigned char *buffer = NULL; + size_t buflen; + const unsigned char *p; + size_t n, objlen, hdrlen; + int class, tag, constructed, ndef; + aodf_object_t aodflist = NULL; + int i; + + if (!fid) + return gpg_error (GPG_ERR_NO_DATA); /* No authentication objects. */ + + err = select_and_read_binary (app->slot, fid, "AODF", &buffer, &buflen); + if (err) + return err; + + p = buffer; + n = buflen; + + /* FIXME: This shares a LOT of code with read_ef_prkdf! */ + + /* Loop over the records. We stop as soon as we detect a new record + starting with 0x00 or 0xff as these values are commonly used to + pad data blocks and are no valid ASN.1 encoding. */ + while (n && *p && *p != 0xff) + { + const unsigned char *pp; + size_t nn; + int where; + const char *errstr = NULL; + aodf_object_t aodf = NULL; + unsigned long ul; + const char *s; + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > n || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + log_error ("error parsing AODF record: %s\n", gpg_strerror (err)); + goto leave; + } + pp = p; + nn = objlen; + p += objlen; + n -= objlen; + + /* Allocate memory for a new AODF list item. */ + aodf = xtrycalloc (1, sizeof *aodf); + if (!aodf) + goto no_core; + + /* Parse the commonObjectAttributes. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + { + const unsigned char *ppp = pp; + size_t nnn = objlen; + + pp += objlen; + nn -= objlen; + + /* Search the optional AuthId. We need to skip the optional + Label (UTF8STRING) and the optional CommonObjectFlags + (BITSTRING). */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto no_authid; + if (err) + goto parse_error; + if (tag == TAG_UTF8_STRING) + { + ppp += objlen; /* Skip the Label. */ + nnn -= objlen; + + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto no_authid; + if (err) + goto parse_error; + } + if (tag == TAG_BIT_STRING) + { + ppp += objlen; /* Skip the CommonObjectFlags. */ + nnn -= objlen; + + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto no_authid; + if (err) + goto parse_error; + } + if (tag == TAG_OCTET_STRING && objlen) + { + aodf->authidlen = objlen; + aodf->authid = xtrymalloc (objlen); + if (!aodf->authid) + goto no_core; + memcpy (aodf->authid, ppp, objlen); + } + no_authid: + ; + } + + /* Parse the CommonAuthenticationObjectAttributes. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + { + const unsigned char *ppp = pp; + size_t nnn = objlen; + + pp += objlen; + nn -= objlen; + + /* Get the Id. */ + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn + || class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + aodf->objidlen = objlen; + aodf->objid = xtrymalloc (objlen); + if (!aodf->objid) + goto no_core; + memcpy (aodf->objid, ppp, objlen); + } + + /* Parse the typeAttributes. */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + nn = objlen; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE) + ; /* PinAttributes */ + else if (class == CLASS_CONTEXT) + { + switch (tag) + { + case 0: errstr = "biometric auth types are not supported"; break; + case 1: errstr = "authKey auth types are not supported"; break; + case 2: errstr = "external auth type are not supported"; break; + default: errstr = "unknown privateKeyObject"; break; + } + goto parse_error; + } + else + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto parse_error; + } + + nn = objlen; + + /* PinFlags */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn || !objlen + || class != CLASS_UNIVERSAL || tag != TAG_BIT_STRING)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + { + unsigned int bits, mask; + int unused, full; + + unused = *pp++; nn--; objlen--; + if ((!objlen && unused) || unused/8 > objlen) + { + err = gpg_error (GPG_ERR_ENCODING_PROBLEM); + goto parse_error; + } + full = objlen - (unused+7)/8; + unused %= 8; + mask = 0; + for (i=1; unused; i <<= 1, unused--) + mask |= i; + + /* The first octet */ + bits = 0; + if (objlen) + { + bits = *pp++; nn--; objlen--; + if (full) + full--; + else + { + bits &= ~mask; + mask = 0; + } + } + if ((bits & 0x80)) /* ASN.1 bit 0. */ + aodf->pinflags.case_sensitive = 1; + if ((bits & 0x40)) /* ASN.1 bit 1. */ + aodf->pinflags.local = 1; + if ((bits & 0x20)) + aodf->pinflags.change_disabled = 1; + if ((bits & 0x10)) + aodf->pinflags.unblock_disabled = 1; + if ((bits & 0x08)) + aodf->pinflags.initialized = 1; + if ((bits & 0x04)) + aodf->pinflags.needs_padding = 1; + if ((bits & 0x02)) + aodf->pinflags.unblocking_pin = 1; + if ((bits & 0x01)) + aodf->pinflags.so_pin = 1; + /* The second octet. */ + bits = 0; + if (objlen) + { + bits = *pp++; nn--; objlen--; + if (full) + full--; + else + { + bits &= ~mask; + mask = 0; + } + } + if ((bits & 0x80)) + aodf->pinflags.disable_allowed = 1; + if ((bits & 0x40)) + aodf->pinflags.integrity_protected = 1; + if ((bits & 0x20)) + aodf->pinflags.confidentiality_protected = 1; + if ((bits & 0x10)) + aodf->pinflags.exchange_ref_data = 1; + /* Skip remaining bits. */ + pp += objlen; + nn -= objlen; + } + + + /* PinType */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_UNIVERSAL || tag != TAG_ENUMERATED)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (!err && (objlen > sizeof (pin_type_t) || objlen > sizeof (ul))) + err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + aodf->pintype = ul; + + + /* minLength */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_UNIVERSAL || tag != TAG_INTEGER)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (!err && objlen > sizeof (ul)) + err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); + if (err) + goto parse_error; + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + aodf->min_length = ul; + + + /* storedLength */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nn + || class != CLASS_UNIVERSAL || tag != TAG_INTEGER)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (!err && objlen > sizeof (ul)) + err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); + if (err) + goto parse_error; + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + aodf->stored_length = ul; + + /* optional maxLength */ + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto ready; + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER) + { + if (objlen > sizeof (ul)) + { + err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); + goto parse_error; + } + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + aodf->max_length = ul; + aodf->max_length_valid = 1; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto ready; + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + } + + /* Optional pinReference. */ + if (class == CLASS_CONTEXT && tag == 0) + { + if (objlen > sizeof (ul)) + { + err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); + goto parse_error; + } + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*pp++) & 0xff; + nn--; + } + aodf->pin_reference = ul; + aodf->pin_reference_valid = 1; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto ready; + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + } + + /* Optional padChar. */ + if (class == CLASS_UNIVERSAL && tag == TAG_OCTET_STRING) + { + if (objlen != 1) + { + errstr = "padChar is not of size(1)"; + goto parse_error; + } + aodf->pad_char = *pp++; nn--; + aodf->pad_char_valid = 1; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto ready; + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + } + + /* Skip optional lastPinChange. */ + if (class == CLASS_UNIVERSAL && tag == TAG_GENERALIZED_TIME) + { + pp += objlen; + nn -= objlen; + + where = __LINE__; + err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (gpg_err_code (err) == GPG_ERR_EOF) + goto ready; + if (!err && objlen > nn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + } + + /* Optional Path object. */ + if (class == CLASS_UNIVERSAL || tag == TAG_SEQUENCE) + { + const unsigned char *ppp = pp; + size_t nnn = objlen; + + pp += objlen; + nn -= objlen; + + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && objlen > nnn) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + /* Make sure that the next element is a non zero FID and of + even length (FID are two bytes each). */ + if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING + || !objlen || (objlen & 1) ) + { + errstr = "invalid path reference"; + goto parse_error; + } + + aodf->pathlen = objlen/2; + aodf->path = xtrymalloc (aodf->pathlen); + if (!aodf->path) + goto no_core; + for (i=0; i < aodf->pathlen; i++, ppp += 2, nnn -= 2) + aodf->path[i] = ((ppp[0] << 8) | ppp[1]); + + if (nnn) + { + /* An index and length follows. */ + aodf->have_off = 1; + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn + || class != CLASS_UNIVERSAL || tag != TAG_INTEGER)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*ppp++) & 0xff; + nnn--; + } + aodf->off = ul; + + where = __LINE__; + err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > nnn + || class != CLASS_CONTEXT || tag != 0)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto parse_error; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*ppp++) & 0xff; + nnn--; + } + aodf->len = ul; + } + } + + /* Igonore further objects which might be there due to future + extensions of pkcs#15. */ + + ready: + log_debug ("AODF %04hX: id=", fid); + for (i=0; i < aodf->objidlen; i++) + log_printf ("%02X", aodf->objid[i]); + if (aodf->authid) + { + log_printf (" authid="); + for (i=0; i < aodf->authidlen; i++) + log_printf ("%02X", aodf->authid[i]); + } + log_printf (" flags="); + s = ""; + if (aodf->pinflags.case_sensitive) + log_printf ("%scase_sensitive", s), s = ","; + if (aodf->pinflags.local) + log_printf ("%slocal", s), s = ","; + if (aodf->pinflags.change_disabled) + log_printf ("%schange_disabled", s), s = ","; + if (aodf->pinflags.unblock_disabled) + log_printf ("%sunblock_disabled", s), s = ","; + if (aodf->pinflags.initialized) + log_printf ("%sinitialized", s), s = ","; + if (aodf->pinflags.needs_padding) + log_printf ("%sneeds_padding", s), s = ","; + if (aodf->pinflags.unblocking_pin) + log_printf ("%sunblocking_pin", s), s = ","; + if (aodf->pinflags.so_pin) + log_printf ("%sso_pin", s), s = ","; + if (aodf->pinflags.disable_allowed) + log_printf ("%sdisable_allowed", s), s = ","; + if (aodf->pinflags.integrity_protected) + log_printf ("%sintegrity_protected", s), s = ","; + if (aodf->pinflags.confidentiality_protected) + log_printf ("%sconfidentiality_protected", s), s = ","; + if (aodf->pinflags.exchange_ref_data) + log_printf ("%sexchange_ref_data", s), s = ","; + { + char numbuf[50]; + switch (aodf->pintype) + { + case PIN_TYPE_BCD: s = "bcd"; break; + case PIN_TYPE_ASCII_NUMERIC: s = "ascii-numeric"; break; + case PIN_TYPE_UTF8: s = "utf8"; break; + case PIN_TYPE_HALF_NIBBLE_BCD: s = "half-nibble-bcd"; break; + case PIN_TYPE_ISO9564_1: s = "iso9564-1"; break; + default: + sprintf (numbuf, "%lu", (unsigned long)aodf->pintype); + s = numbuf; + } + log_printf (" type=%s", s); + } + log_printf (" min=%lu", aodf->min_length); + log_printf (" stored=%lu", aodf->stored_length); + if (aodf->max_length_valid) + log_printf (" max=%lu", aodf->max_length); + if (aodf->pad_char_valid) + log_printf (" pad=0x%02x", aodf->pad_char); + if (aodf->pin_reference_valid) + log_printf (" pinref=0x%02lX", aodf->pin_reference); + if (aodf->pathlen) + { + log_printf (" path="); + for (i=0; i < aodf->pathlen; i++) + log_printf ("%04hX", aodf->path[i]); + if (aodf->have_off) + log_printf ("[%lu/%lu]", aodf->off, aodf->len); + } + log_printf ("\n"); + + /* Put it into the list. */ + aodf->next = aodflist; + aodflist = aodf; + aodf = NULL; + continue; /* Ready. */ + + no_core: + err = gpg_error_from_errno (errno); + release_aodf_object (aodf); + goto leave; + + parse_error: + log_error ("error parsing AODF record (%d): %s - skipped\n", + where, errstr? errstr : gpg_strerror (err)); + err = 0; + release_aodf_object (aodf); + } /* End looping over all records. */ + + leave: + xfree (buffer); + if (err) + release_aodflist (aodflist); + else + *result = aodflist; + return err; +} + + + + + +/* Read and parse the EF(TokenInfo). + +TokenInfo ::= SEQUENCE { + version INTEGER {v1(0)} (v1,...), + serialNumber OCTET STRING, manufacturerID Label OPTIONAL, label [0] Label OPTIONAL, tokenflags TokenFlags, @@ -521,105 +2152,678 @@ TokenFlags ::= BIT STRING { */ +/* static gpg_error_t */ +/* read_ef_tokeninfo (app_t app) */ +/* { */ +/* unsigned short efid = 0x5032; */ +/* return 0; */ +/* } */ + + +/* Get all the basic information from the pkcs#15 card, check the + structure and initialize our local context. This is used once at + application initialization. */ static gpg_error_t -read_ef_tokeninfo (app_t app) +read_p15_info (app_t app) { - unsigned short efid = 0x5032; + gpg_error_t err; + + /* Fixme: We might need to read the tokeninfo to get a non-standard + ODF FID. */ + + /* Read the ODF so that we know the location of all directory + files. */ + err = read_ef_odf (app, 0x5031); + if (err) + return err; + + /* Read certificate information. */ + assert (!app->app_local->certificate_info); + assert (!app->app_local->trusted_certificate_info); + assert (!app->app_local->useful_certificate_info); + err = read_ef_cdf (app, app->app_local->odf.certificates, + &app->app_local->certificate_info); + if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) + err = read_ef_cdf (app, app->app_local->odf.trusted_certificates, + &app->app_local->trusted_certificate_info); + if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA) + err = read_ef_cdf (app, app->app_local->odf.useful_certificates, + &app->app_local->useful_certificate_info); + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + err = 0; + if (err) + return err; + /* Read information about private keys. */ + assert (!app->app_local->private_key_info); + err = read_ef_prkdf (app, app->app_local->odf.private_keys, + &app->app_local->private_key_info); + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + err = 0; + if (err) + return err; + + /* Read information about authentication objects. */ + assert (!app->app_local->auth_object_info); + err = read_ef_aodf (app, app->app_local->odf.auth_objects, + &app->app_local->auth_object_info); + if (gpg_err_code (err) == GPG_ERR_NO_DATA) + err = 0; + + + return err; } -/* Get all the basic information from the pkcs#15 card, check the - structure and init our context. This is used once at application - initialization. */ +/* Helper to do_learn_status: Send information about all certificates + listed in CERTINFO back. Use CERTTYPE as type of the + certificate. */ static gpg_error_t -read_p15_info (app_t app) +send_certinfo (app_t app, ctrl_t ctrl, const char *certtype, + cdf_object_t certinfo) { - gpg_error_t err; + for (; certinfo; certinfo = certinfo->next) + { + char *buf, *p; + int i; + + buf = xtrymalloc (9 + certinfo->objidlen*2 + 1); + if (!buf) + return gpg_error_from_errno (errno); + p = stpcpy (buf, "P15"); + if (app->app_local->home_df) + { + sprintf (p, "-%04hX", (app->app_local->home_df & 0xffff)); + p += 5; + } + p = stpcpy (p, "."); + for (i=0; i < certinfo->objidlen; i++) + { + sprintf (p, "%02X", certinfo->objid[i]); + p += 2; + } + + send_status_info (ctrl, "CERTINFO", + certtype, strlen (certtype), + buf, strlen (buf), + NULL, (size_t)0); + xfree (buf); + } + return 0; +} - err = read_ed_odf (app); + +/* Get the keygrip of the private key object PRKDF. On success the + keygrip gets returned in the caller provided 41 byte buffer + R_GRIPSTR. */ +static gpg_error_t +keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr) +{ + gpg_error_t err; + cdf_object_t cdf; + unsigned char *der; + size_t derlen; + ksba_cert_t cert; + + /* FIXME: We should check whether a public key directory file and a + matching public key for PRKDF is available. This should make + extraction of the key much easier. My current test card doesn't + have one, so we can only use the fallback solution bu looking for + a matching certificate and extract the key from there. */ + + /* Look for a matching certificate. A certificate matches if the Id + matches the obne of the private key info. */ + for (cdf = app->app_local->certificate_info; cdf; cdf = cdf->next) + if (cdf->objidlen == prkdf->objidlen + && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen)) + break; + if (!cdf) + for (cdf = app->app_local->trusted_certificate_info; cdf; cdf = cdf->next) + if (cdf->objidlen == prkdf->objidlen + && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen)) + break; + if (!cdf) + for (cdf = app->app_local->useful_certificate_info; cdf; cdf = cdf->next) + if (cdf->objidlen == prkdf->objidlen + && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen)) + break; + if (!cdf) + return gpg_error (GPG_ERR_NOT_FOUND); + + err = readcert_by_cdf (app, cdf, &der, &derlen); if (err) return err; + err = ksba_cert_new (&cert); + if (!err) + err = ksba_cert_init_from_mem (cert, der, derlen); + xfree (der); + if (!err) + err = app_help_get_keygrip_string (cert, r_gripstr); + ksba_cert_release (cert); + + return err; +} + + + + +/* Helper to do_learn_status: Send information about all known + keypairs back. FIXME: much code duplication from + send_sertinfo(). */ +static gpg_error_t +send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo) +{ + gpg_error_t err; + + for (; keyinfo; keyinfo = keyinfo->next) + { + char gripstr[40+1]; + char *buf, *p; + int i, j; + + buf = xtrymalloc (9 + keyinfo->objidlen*2 + 1); + if (!buf) + return gpg_error_from_errno (errno); + p = stpcpy (buf, "P15"); + if (app->app_local->home_df) + { + sprintf (p, "-%04hX", (app->app_local->home_df & 0xffff)); + p += 5; + } + p = stpcpy (p, "."); + for (i=0; i < keyinfo->objidlen; i++) + { + sprintf (p, "%02X", keyinfo->objid[i]); + p += 2; + } + + err = keygripstr_from_prkdf (app, keyinfo, gripstr); + if (err) + { + log_error ("can't get keygrip from "); + for (j=0; j < keyinfo->pathlen; j++) + log_printf ("%04hX", keyinfo->path[j]); + log_printf (": %s\n", gpg_strerror (err)); + } + else + { + assert (strlen (gripstr) == 40); + send_status_info (ctrl, "KEYPAIRINFO", + gripstr, 40, + buf, strlen (buf), + NULL, (size_t)0); + } + xfree (buf); + } + return 0; +} + + + +/* This is the handler for the LEARN command. */ +static int /* FIXME: change this to gpg_error_t */ +do_learn_status (app_t app, ctrl_t ctrl) +{ + gpg_error_t err; + + err = send_certinfo (app, ctrl, "100", app->app_local->certificate_info); + if (!err) + err = send_certinfo (app, ctrl, "101", + app->app_local->trusted_certificate_info); + if (!err) + err = send_certinfo (app, ctrl, "102", + app->app_local->useful_certificate_info); + if (!err) + err = send_keypairinfo (app, ctrl, app->app_local->private_key_info); + + return err; +} + + +/* Read a certifciate using the information in CDF and return the + certificate in a newly llocated buffer R_CERT and its length + R_CERTLEN. */ +static gpg_error_t +readcert_by_cdf (app_t app, cdf_object_t cdf, + unsigned char **r_cert, size_t *r_certlen) +{ + gpg_error_t err; + unsigned char *buffer = NULL; + const unsigned char *p, *save_p; + size_t buflen, n; + int class, tag, constructed, ndef; + size_t totobjlen, objlen, hdrlen; + int rootca; + int i; + + *r_cert = NULL; + *r_certlen = 0; + + /* First check whether it has been cached. */ + if (cdf->image) + { + *r_cert = xtrymalloc (cdf->imagelen); + if (!*r_cert) + return gpg_error_from_errno (errno); + memcpy (*r_cert, cdf->image, cdf->imagelen); + *r_certlen = cdf->imagelen; + return 0; + } + + /* Read the entire file. fixme: This could be optimized by first + reading the header to figure out how long the certificate + actually is. */ + err = select_ef_by_path (app, cdf->path, cdf->pathlen); + if (err) + goto leave; + + err = iso7816_read_binary (app->slot, cdf->off, cdf->len, &buffer, &buflen); + if (!err && (!buflen || *buffer == 0xff)) + err = gpg_error (GPG_ERR_NOT_FOUND); + if (err) + { + log_error ("error reading certificate with Id "); + for (i=0; i < cdf->objidlen; i++) + log_printf ("%02X", cdf->objid[i]); + log_printf (": %s\n", gpg_strerror (err)); + goto leave; + } + + /* Check whether this is really a certificate. */ + p = buffer; + n = buflen; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + + if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) + rootca = 0; + else if ( class == CLASS_UNIVERSAL && tag == TAG_SET && constructed ) + rootca = 1; + else + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto leave; + } + totobjlen = objlen + hdrlen; + assert (totobjlen <= buflen); + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + + if (!rootca + && class == CLASS_UNIVERSAL && tag == TAG_OBJECT_ID && !constructed) + { + /* The certificate seems to be contained in a userCertificate + container. Skip this and assume the following sequence is + the certificate. */ + if (n < objlen) + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto leave; + } + p += objlen; + n -= objlen; + save_p = p; + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (err) + goto leave; + if ( !(class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE && constructed) ) + { + err = gpg_error (GPG_ERR_INV_OBJ); + goto leave; + } + totobjlen = objlen + hdrlen; + assert (save_p + totobjlen <= buffer + buflen); + memmove (buffer, save_p, totobjlen); + } + + *r_cert = buffer; + buffer = NULL; + *r_certlen = totobjlen; + + /* Try to cache it. */ + if (!cdf->image && (cdf->image = xtrymalloc (*r_certlen))) + { + memcpy (cdf->image, *r_cert, *r_certlen); + cdf->imagelen = *r_certlen; + } + + + leave: + xfree (buffer); + return err; +} + + + +/* Handler for the READCERT command. + + Read the certificate with id CERTID (as returned by learn_status in + the CERTINFO status lines) and return it in the freshly allocated + buffer to be stored at R_CERT and its length at R_CERTLEN. A error + code will be returned on failure and R_CERT and R_CERTLEN will be + set to NULL/0. */ +static int /* FIXME: change this to gpg_error_t */ +do_readcert (app_t app, const char *certid, + unsigned char **r_cert, size_t *r_certlen) +{ + gpg_error_t err; + cdf_object_t cdf; + + *r_cert = NULL; + *r_certlen = 0; + err = cdf_object_from_certid (app, certid, &cdf); + if (!err) + err =readcert_by_cdf (app, cdf, r_cert, r_certlen); + return err; } -static int -do_learn_status (APP app, CTRL ctrl) + +/* Handler for the PKSIGN command. + + Create the signature and return the allocated result in OUTDATA. + If a PIN is required, the PINCB will be used to ask for the PIN; + that callback should return the PIN in an allocated buffer and + store that as the 3rd argument. */ +static int +do_sign (app_t app, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) { + static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; + static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */ + { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; + gpg_error_t err; - char ct_buf[100], id_buf[100]; int i; + unsigned char data[35]; /* Must be large enough for a SHA-1 digest + + the largest OID prefix above. */ + prkdf_object_t prkdf; /* The private key object. */ + aodf_object_t aodf; /* The associated authentication object. */ + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + if (indatalen != 20 && indatalen != 16 && indatalen != 35) + return gpg_error (GPG_ERR_INV_VALUE); + + err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf); + if (err) + return err; + if (!prkdf->authid) + { + log_error ("no authentication object defined for %s\n", keyidstr); + /* fixme: we might want to go ahead and do without PIN + verification. */ + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + } + + /* Find the authentication object to this private key object. */ + for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next) + if (aodf->objidlen == prkdf->authidlen + && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen)) + break; + if (!aodf) + { + log_error ("authentication object for %s missing\n", keyidstr); + return gpg_error (GPG_ERR_INV_CARD); + } + if (aodf->authid) + { + log_error ("PIN verification is protected by an " + "additional authentication token\n"); + return gpg_error (GPG_ERR_BAD_PIN_METHOD); + } + if (aodf->pinflags.integrity_protected + || aodf->pinflags.confidentiality_protected) + { + log_error ("PIN verification requires unsupported protecion method\n"); + return gpg_error (GPG_ERR_BAD_PIN_METHOD); + } + if (!aodf->stored_length && aodf->pinflags.needs_padding) + { + log_error ("PIN verification requires padding but no length known\n"); + return gpg_error (GPG_ERR_INV_CARD); + } - /* Output information about all useful objects. */ - for (i=0; objlist[i].fid; i++) + /* Now that we have all the information available, prepare and run + the PIN verification.*/ + if (1) { - if (filelist[i].certtype) + char *pinvalue; + size_t pinvaluelen; + const char *errstr; + const char *s; + + err = pincb (pincb_arg, "PIN", &pinvalue); + if (err) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (err)); + return err; + } + + /* We might need to cope with UTF8 things here. Not sure how + min_length etc. are exactly defined, for now we take them as + a plain octet count. */ + + if (strlen (pinvalue) < aodf->min_length) + { + log_error ("PIN is too short; minimum length is %lu\n", + aodf->min_length); + err = gpg_error (GPG_ERR_BAD_PIN); + } + else if (aodf->stored_length && strlen (pinvalue) > aodf->stored_length) + { + /* This would otherwise truncate the PIN silently. */ + log_error ("PIN is too large; maximum length is %lu\n", + aodf->stored_length); + err = gpg_error (GPG_ERR_BAD_PIN); + } + else if (aodf->max_length_valid && strlen (pinvalue) > aodf->max_length) + { + log_error ("PIN is too large; maximum length is %lu\n", + aodf->max_length); + err = gpg_error (GPG_ERR_BAD_PIN); + } + + if (err) { - size_t len; + xfree (pinvalue); + return err; + } - len = app_help_read_length_of_cert (app->slot, - filelist[i].fid, NULL); - if (len) + errstr = NULL; + err = 0; + switch (aodf->pintype) + { + case PIN_TYPE_BCD: + errstr = "PIN type BCD is not supported"; + break; + case PIN_TYPE_ASCII_NUMERIC: + for (s=pinvalue; digitp (s); s++) + ; + if (*s) { - /* FIXME: We should store the length in the application's - context so that a following readcert does only need to - read that many bytes. */ - sprintf (ct_buf, "%d", filelist[i].certtype); - sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid); - send_status_info (ctrl, "CERTINFO", - ct_buf, strlen (ct_buf), - id_buf, strlen (id_buf), - NULL, (size_t)0); + errstr = "Non-numeric digits found in PIN"; + err = gpg_error (GPG_ERR_BAD_PIN); } + break; + case PIN_TYPE_UTF8: + break; + case PIN_TYPE_HALF_NIBBLE_BCD: + errstr = "PIN type Half-Nibble-BCD is not supported"; + break; + case PIN_TYPE_ISO9564_1: + errstr = "PIN type ISO9564-1 is not supported"; + break; + default: + errstr = "Unknown PIN type"; + break; } - else if (filelist[i].iskeypair) + if (errstr) { - char gripstr[40+1]; + log_error ("can't verify PIN: %s\n", errstr); + xfree (pinvalue); + return err? err : gpg_error (GPG_ERR_BAD_PIN_METHOD); + } - err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr); - if (err) - log_error ("can't get keygrip from FID 0x%04X: %s\n", - filelist[i].fid, gpg_strerror (err)); - else + if (aodf->pinflags.needs_padding) + { + char *paddedpin; + + paddedpin = xtrymalloc (aodf->stored_length+1); + if (!paddedpin) { - sprintf (id_buf, "P15-DF01.%04X", filelist[i].fid); - send_status_info (ctrl, "KEYPAIRINFO", - gripstr, 40, - id_buf, strlen (id_buf), - NULL, (size_t)0); + err = gpg_error_from_errno (errno); + xfree (pinvalue); + return err; } + for (i=0, s=pinvalue; i < aodf->stored_length && *s; i++, s++) + paddedpin[i] = *s; + /* Not sure what padding char to use if none has been set. + For now we use 0x00; maybe a space would be better. */ + for (; i < aodf->stored_length; i++) + paddedpin[i] = aodf->pad_char_valid? aodf->pad_char : 0; + paddedpin[i] = 0; + pinvaluelen = i; + xfree (pinvalue); + pinvalue = paddedpin; + } + else + pinvaluelen = strlen (pinvalue); + + err = iso7816_verify (app->slot, + aodf->pin_reference_valid? aodf->pin_reference : 0, + pinvalue, pinvaluelen); + xfree (pinvalue); + if (err) + { + log_error ("PIN verification failed: %s\n", gpg_strerror (err)); + return err; } + log_debug ("PIN verification succeeded\n"); } - return 0; -} + /* Prepare the DER object from INDATA. */ + if (indatalen == 35) + { + /* Alright, the caller was so kind to send us an already + prepared DER object. Check that it is what we want and that + it matches the hash algorithm. */ + if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha1_prefix, 15)) + ; + else if (hashalgo == GCRY_MD_RMD160 + && !memcmp (indata, rmd160_prefix, 15)) + ; + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data, indata, indatalen); + } + else + { + /* Need to prepend the prefix. */ + if (hashalgo == GCRY_MD_SHA1) + memcpy (data, sha1_prefix, 15); + else if (hashalgo == GCRY_MD_RMD160) + memcpy (data, rmd160_prefix, 15); + else + return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + memcpy (data+15, indata, indatalen); + } + + /* Manage security environment needs to be weaked for certain cards. */ + if (app->app_local->card_type == CARD_TYPE_TCOS) + { + /* TCOS creates signatures always using the local key 0. MSE + may not be used. */ + } + else if (app->app_local->card_type == CARD_TYPE_MICARDO) + { + /* Micardo cards are very special in that they need to restore a + security environment using a infomration from a special + file. */ + log_error ("WARNING: support for MICARDO cards is not yet available\n"); + } + else if (prkdf->key_reference_valid) + { + unsigned char mse[3]; + + mse[0] = 0x84; /* Select asym. key. */ + mse[1] = 1; + mse[2] = prkdf->key_reference; + err = iso7816_manage_security_env (app->slot, + 0x41, 0xB6, + mse, sizeof mse); + if (err) + { + log_error ("MSE failed: %s\n", gpg_strerror (err)); + return err; + } + } -/* Release all resources. */ -static void -do_deinit (app_t app) -{ - if (app && app->app_local) - { - xfree (app->app_local); - app->app_local = NULL; - } + err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + return err; } + + + + + /* Select the PKCS#15 application on the card in SLOT. */ -int -app_select_p15 (APP app) +gpg_error_t +app_select_p15 (app_t app) { static char const aid[] = { 0xA0, 0, 0, 0, 0x63, 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; int slot = app->slot; int rc; + unsigned short def_home_df = 0; + card_type_t card_type = CARD_TYPE_UNKNOWN; rc = iso7816_select_application (slot, aid, sizeof aid); + if (rc) + { + def_home_df = 0x5015; + rc = iso7816_select_file (slot, def_home_df, 1, NULL, NULL); + } + if (!rc) + { + /* We need to know the ATR for tweaking some security operations. */ + unsigned char *atr; + size_t atrlen; + int i; + + atr = apdu_get_atr (app->slot, &atrlen); + if (!atr) + rc = gpg_error (GPG_ERR_INV_CARD); + else + { + for (i=0; card_atr_list[i].atrlen; i++) + if (card_atr_list[i].atrlen == atrlen + && !memcmp (card_atr_list[i].atr, atr, atrlen)) + { + card_type = card_atr_list[i].type; + break; + } + xfree (atr); + } + } if (!rc) { app->apptype = "P15"; @@ -631,37 +2835,49 @@ app_select_p15 (APP app) goto leave; } + /* Set the home DF. Note that we currently can't do that if the + selection via application ID worked. This will store 0 there + instead. FIXME: We either need to figure the home_df via the + DIR file or using the return values from the select file + APDU. */ + app->app_local->home_df = def_home_df; + + /* Store the card type. FIXME: We might want to put this into + the common APP structure. */ + app->app_local->card_type = card_type; + /* Read basic information and check whether this is a real card. */ rc = read_p15_info (app); - - /* Special serial number munging. We need to do one case here - because we need to access the EF(TokenInfo). */ + if (rc) + goto leave; + + /* Special serial number munging. We need to check for a German + prototype card right here because we need to access to + EF(TokenInfo). We mark such a serial number by the using a + prefix of FF0100. */ if (app->serialnolen == 12 - && !memcmp (app->serial, "\xD2\x76\0\0\0\0\0\0\0\0\0\0", 12)) + && !memcmp (app->serialno, "\xD2\x76\0\0\0\0\0\0\0\0\0\0", 12)) { /* This is a German card with a silly serial number. Try to get - the serial number from the EF(TokenInfo). We indicate such a - serial number by the using the prefix: "FF0100". */ - const char *efser = card->p15card->serial_number; - char *p; - - if (!efser) - efser = ""; + the serial number from the EF(TokenInfo). . */ + unsigned char *p; + + /* FIXME: actually get it from EF(TokenInfo). */ - xfree (*serial); - *serial = NULL; - p = xtrymalloc (strlen (efser) + 7); + p = xtrymalloc (3 + app->serialnolen); if (!p) rc = gpg_error (gpg_err_code_from_errno (errno)); else { - strcpy (p, "FF0100"); - strcpy (p+6, efser); - *serial = p; + memcpy (p, "\xff\x01", 3); + memcpy (p+3, app->serialno, app->serialnolen); + app->serialnolen += 3; + xfree (app->serialno); + app->serialno = p; } } - else + else /* Use standard munging code. */ rc = app_munge_serialno (app); app->fnc.deinit = do_deinit; @@ -672,17 +2888,13 @@ app_select_p15 (APP app) app->fnc.genkey = NULL; app->fnc.sign = do_sign; app->fnc.auth = NULL; - app->fnc.decipher = do_decipher; + app->fnc.decipher = NULL; app->fnc.change_pin = NULL; app->fnc.check_pin = NULL; leave: if (rc) - { - xfree (app->app_local); - app->app_local = NULL; - } - + do_deinit (app); } return rc; diff --git a/scd/app.c b/scd/app.c index e035e9b89..b6d46326b 100644 --- a/scd/app.c +++ b/scd/app.c @@ -125,8 +125,8 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) rc = app_select_openpgp (app); if (rc && is_app_allowed ("nks") && (!name || !strcmp (name, "nks"))) rc = app_select_nks (app); -/* if (rc && is_app_allowed ("p12") && (!name || !strcmp (name, "p12"))) */ -/* rc = app_select_p12 (app); */ + if (rc && is_app_allowed ("p15") && (!name || !strcmp (name, "p15"))) + rc = app_select_p15 (app); if (rc && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) rc = app_select_dinsig (app); if (rc && name) @@ -177,7 +177,7 @@ release_application (app_t app) FF 00 00 = For serial numbers starting with an FF FF 01 00 = Some german p15 cards return an empty serial number so the - serial number from the EF(TokeInfo is used instead. + serial number from the EF(TokenInfo) is used instead. All other serial number not starting with FF are used as they are. */ diff --git a/scd/command.c b/scd/command.c index 7d777d8b7..c8eebaac0 100644 --- a/scd/command.c +++ b/scd/command.c @@ -129,13 +129,6 @@ do_reset (ctrl_t ctrl, int do_close) { int slot = ctrl->reader_slot; - if (ctrl->card_ctx) - { - card_close (ctrl->card_ctx); - ctrl->card_ctx = NULL; - xfree (ctrl->in_data.value); - ctrl->in_data.value = NULL; - } if (ctrl->app_ctx) { release_application (ctrl->app_ctx); @@ -259,8 +252,6 @@ open_card (ctrl_t ctrl, const char *apptype) if (ctrl->app_ctx) return 0; /* Already initialized for one specific application. */ - if (ctrl->card_ctx) - return 0; /* Already initialized using a card context. */ if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); @@ -274,19 +265,6 @@ open_card (ctrl_t ctrl, const char *apptype) err = gpg_error (GPG_ERR_CARD); else err = select_application (ctrl, slot, apptype, &ctrl->app_ctx); - if (!ctrl->app_ctx - && gpg_err_code (err) != GPG_ERR_CARD_NOT_PRESENT) - { - /* No application found - fall back to old mode. */ - /* Note that we should rework the old code to use the - application paradigma too. */ - /* If an APPTYPE was requested and it is not pkcs#15, we return - an error here. */ - if (apptype && !(!strcmp (apptype, "P15") || !strcmp (apptype, "p15"))) - err = gpg_error (GPG_ERR_NOT_SUPPORTED); - else - err = card_open (&ctrl->card_ctx); - } TEST_CARD_REMOVAL (ctrl, err); return map_to_assuan_status (err); @@ -367,12 +345,10 @@ cmd_serialno (assuan_context_t ctx, char *line) if ((rc = open_card (ctrl, *line? line:NULL))) return rc; - if (ctrl->app_ctx) - rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); - else - rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); if (rc) return map_to_assuan_status (rc); + rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); xfree (serial); if (rc < 0) @@ -453,7 +429,6 @@ cmd_learn (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc = 0; - int idx; if ((rc = open_card (ctrl, NULL))) return rc; @@ -467,10 +442,7 @@ cmd_learn (assuan_context_t ctx, char *line) char *serial; time_t stamp; - if (ctrl->app_ctx) - rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); - else - rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); + rc = app_get_serial_and_stamp (ctrl->app_ctx, &serial, &stamp); if (rc) return map_to_assuan_status (rc); rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); @@ -506,87 +478,11 @@ cmd_learn (assuan_context_t ctx, char *line) free (serial_and_stamp); } - /* If we are using the modern application paradigma, let the - application print out its collection of useful status + /* Let the application print out its collection of useful status information. */ - if (!rc && ctrl->app_ctx) + if (!rc) rc = app_write_learn_status (ctrl->app_ctx, ctrl); - /* Return information about the certificates. FIXME: Move this into - an app-p15.c*/ - for (idx=0; !rc && !ctrl->app_ctx; idx++) - { - char *certid; - int certtype; - - rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype); - if (!rc) - { - char *buf; - - buf = xtrymalloc (40 + 1 + strlen (certid) + 1); - if (!buf) - rc = gpg_error (gpg_err_code_from_errno (errno)); - else - { - sprintf (buf, "%d %s", certtype, certid); - assuan_write_status (ctx, "CERTINFO", buf); - xfree (buf); - } - } - xfree (certid); - } - if (rc == -1) - rc = 0; - - /* Return information about the keys. FIXME: Move this into an - app-p15.c */ - for (idx=0; !rc && !ctrl->app_ctx; idx++) - { - unsigned char keygrip[20]; - char *keyid; - int no_cert = 0; - - rc = card_enum_keypairs (ctrl->card_ctx, idx, keygrip, &keyid); - if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT && keyid) - { - /* This does happen with an incomplete personalized - card; i.e. during the time we have stored the key on the - card but not stored the certificate; probably becuase it - has not yet been received back from the CA. Note that we - must release KEYID in this case. */ - rc = 0; - no_cert = 1; - } - if (!rc) - { - char *buf, *p; - - buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1); - if (!buf) - rc = gpg_error (gpg_err_code_from_errno (errno)); - else - { - int i; - - if (no_cert) - *p++ = 'X'; - else - { - for (i=0; i < 20; i++, p += 2) - sprintf (p, "%02X", keygrip[i]); - } - *p++ = ' '; - strcpy (p, keyid); - assuan_write_status (ctx, "KEYPAIRINFO", buf); - xfree (buf); - } - } - xfree (keyid); - } - if (rc == -1) - rc = 0; - TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); } @@ -595,7 +491,7 @@ cmd_learn (assuan_context_t ctx, char *line) /* READCERT <hexified_certid> - Note, that this function may be even be used on a locked card. + Note, that this function may even be used on a locked card. */ static int cmd_readcert (assuan_context_t ctx, char *line) @@ -609,18 +505,9 @@ cmd_readcert (assuan_context_t ctx, char *line) return rc; line = xstrdup (line); /* Need a copy of the line. */ - if (ctrl->app_ctx) - { - rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); - if (rc) - log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); - } - else - { - rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); - if (rc) - log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); - } + rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); + if (rc) + log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); xfree (line); line = NULL; if (!rc) @@ -641,7 +528,7 @@ cmd_readcert (assuan_context_t ctx, char *line) Return the public key for the given cert or key ID as an standard S-Expression. - Note, that this function may be even be used on a locked card. + Note, that this function may even be used on a locked card. */ static int cmd_readkey (assuan_context_t ctx, char *line) @@ -652,44 +539,34 @@ cmd_readkey (assuan_context_t ctx, char *line) size_t ncert, n; ksba_cert_t kc = NULL; ksba_sexp_t p; + unsigned char *pk; + size_t pklen; if ((rc = open_card (ctrl, NULL))) return rc; line = xstrdup (line); /* Need a copy of the line. */ - if (ctrl->app_ctx) - { - unsigned char *pk; - size_t pklen; - - /* If the application supports the READKEY function we use that. - Otherwise we use the old way by extracting it from the - certificate. */ - rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen); - if (!rc) - { /* Yeah, got that key - send it back. */ - rc = assuan_send_data (ctx, pk, pklen); - xfree (pk); - rc = map_assuan_err (rc); - xfree (line); - line = NULL; - goto leave; - } - - if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION) - log_error ("app_readkey failed: %s\n", gpg_strerror (rc)); - else - { - rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); - if (rc) - log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); - } + /* If the application supports the READKEY function we use that. + Otherwise we use the old way by extracting it from the + certificate. */ + rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen); + if (!rc) + { /* Yeah, got that key - send it back. */ + rc = assuan_send_data (ctx, pk, pklen); + xfree (pk); + rc = map_assuan_err (rc); + xfree (line); + line = NULL; + goto leave; } - else + + if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION) + log_error ("app_readkey failed: %s\n", gpg_strerror (rc)); + else { - rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); + rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert); if (rc) - log_error ("card_read_cert failed: %s\n", gpg_strerror (rc)); + log_error ("app_readcert failed: %s\n", gpg_strerror (rc)); } xfree (line); line = NULL; @@ -786,8 +663,8 @@ pin_cb (void *opaque, const char *info, char **retstr) if (rc < 0) return gpg_error (gpg_err_code_from_errno (errno)); - /* FIXME: Write an inquire function which returns the result in - secure memory */ + /* Fixme: Write an inquire function which returns the result in + secure memory and check all futher handling of the PIN. */ rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); free (command); if (rc) @@ -829,18 +706,12 @@ cmd_pksign (assuan_context_t ctx, char *line) if (!keyidstr) return ASSUAN_Out_Of_Core; - if (ctrl->app_ctx) - rc = app_sign (ctrl->app_ctx, - keyidstr, GCRY_MD_SHA1, - pin_cb, ctx, - ctrl->in_data.value, ctrl->in_data.valuelen, - &outdata, &outdatalen); - else - rc = card_sign (ctrl->card_ctx, - keyidstr, GCRY_MD_SHA1, - pin_cb, ctx, - ctrl->in_data.value, ctrl->in_data.valuelen, - &outdata, &outdatalen); + rc = app_sign (ctrl->app_ctx, + keyidstr, GCRY_MD_SHA1, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + xfree (keyidstr); if (rc) { @@ -929,18 +800,12 @@ cmd_pkdecrypt (assuan_context_t ctx, char *line) keyidstr = xtrystrdup (line); if (!keyidstr) return ASSUAN_Out_Of_Core; - if (ctrl->app_ctx) - rc = app_decipher (ctrl->app_ctx, - keyidstr, - pin_cb, ctx, - ctrl->in_data.value, ctrl->in_data.valuelen, - &outdata, &outdatalen); - else - rc = card_decipher (ctrl->card_ctx, - keyidstr, - pin_cb, ctx, - ctrl->in_data.value, ctrl->in_data.valuelen, - &outdata, &outdatalen); + rc = app_decipher (ctrl->app_ctx, + keyidstr, + pin_cb, ctx, + ctrl->in_data.value, ctrl->in_data.valuelen, + &outdata, &outdatalen); + xfree (keyidstr); if (rc) { diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 0fefbd960..7b0f31cdb 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -108,7 +108,6 @@ static ARGPARSE_OPTS opts[] = { { oDebugAll, "debug-all" ,0, "@"}, { oDebugLevel, "debug-level" ,2, "@"}, { oDebugWait,"debug-wait",1, "@"}, - { oDebugSC, "debug-sc", 1, N_("|N|set OpenSC debug level to N")}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, @@ -121,17 +120,14 @@ static ARGPARSE_OPTS opts[] = { "@" #endif /* end --disable-ccid */}, - { oDisableOpenSC, "disable-opensc", 0, -#ifdef HAVE_OPENSC - N_("do not use the OpenSC layer") -#else - "@" -#endif - /* end --disable-opensc */}, { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")}, { oDenyAdmin, "deny-admin", 0, "@" }, { oDisableApplication, "disable-application", 2, "@"}, + /* Dummy options to be removed at some point. */ + { oDebugSC, "debug-sc", 1, "@" }, + { oDisableOpenSC, "disable-opensc", 0, "@" }, + {0} }; @@ -156,14 +152,12 @@ static int maybe_setuid = 1; static char socket_name[128]; -#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; static void *ticker_thread (void *arg); #endif /*USE_GNU_PTH*/ -#endif /*!HAVE_OPENSC*/ static const char * my_strusage (int level) @@ -349,7 +343,6 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ -#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) @@ -358,7 +351,6 @@ main (int argc, char **argv ) gpg_strerror (err)); } #endif /*USE_GNU_PTH*/ -#endif /*!HAVE_OPENSC*/ /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ @@ -469,7 +461,7 @@ main (int argc, char **argv ) case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; - case oDebugSC: opt.debug_sc = pargs.r.ret_int; break; + case oDebugSC: break; case oOptions: /* config files may not be nested (silently ignore them) */ @@ -495,7 +487,7 @@ main (int argc, char **argv ) case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break; case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break; case oDisableCCID: opt.disable_ccid = 1; break; - case oDisableOpenSC: opt.disable_opensc = 1; break; + case oDisableOpenSC: break; case oAllowAdmin: opt.allow_admin = 1; break; case oDenyAdmin: opt.allow_admin = 0; break; @@ -592,9 +584,6 @@ main (int argc, char **argv ) GC_OPT_FLAG_DEFAULT, DEFAULT_PCSC_DRIVER ); #ifdef HAVE_LIBUSB printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE ); -#endif -#ifdef HAVE_LIBUSB - printf ("disable-opensc:%lu:\n", GC_OPT_FLAG_NONE ); #endif printf ("allow-admin:%lu:\n", GC_OPT_FLAG_NONE ); @@ -612,7 +601,6 @@ main (int argc, char **argv ) if (pipe_server) { /* This is the simple pipe based server */ -#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH pth_attr_t tattr; @@ -627,7 +615,6 @@ main (int argc, char **argv ) scd_exit (2); } #endif /*USE_GNU_PTH*/ -#endif /*!HAVE_OPENSC*/ scd_command_handler (-1); } else if (!is_daemon) @@ -859,7 +846,6 @@ scd_init_default_ctrl (CTRL ctrl) } -#ifndef HAVE_OPENSC #ifdef USE_GNU_PTH static void @@ -971,4 +957,3 @@ ticker_thread (void *dummy_arg) return NULL; } #endif /*USE_GNU_PTH*/ -#endif /*!HAVE_OPENSC*/ diff --git a/scd/scdaemon.h b/scd/scdaemon.h index c59879448..5e49f3ae5 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -42,7 +42,6 @@ /* A large struct name "opt" to keep global flags */ struct { unsigned int debug; /* debug flags (DBG_foo_VALUE) */ - int debug_sc; /* OpenSC debug level */ int verbose; /* verbosity level */ int quiet; /* be as quiet as possible */ int dry_run; /* don't change any persistent data */ @@ -51,7 +50,6 @@ struct { const char *ctapi_driver; /* Library to access the ctAPI. */ const char *pcsc_driver; /* Library to access the PC/SC system. */ const char *reader_port; /* NULL or reder port to use. */ - int disable_opensc; /* Disable the use of the OpenSC framework. */ int disable_ccid; /* Disable the use of the internal CCID driver. */ int allow_admin; /* Allow the use of admin commands for certain cards. */ @@ -96,7 +94,6 @@ struct server_control_s { typedef struct server_control_s *CTRL; typedef struct server_control_s *ctrl_t; -typedef struct card_ctx_s *CARD; typedef struct app_ctx_s *APP; typedef struct app_ctx_s *app_t; @@ -109,27 +106,5 @@ void scd_command_handler (int); void send_status_info (CTRL ctrl, const char *keyword, ...); void scd_update_reader_status_file (void); -/*-- card.c --*/ -int card_open (CARD *rcard); -void card_close (CARD card); -int card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp); -int card_enum_keypairs (CARD card, int idx, - unsigned char *keygrip, - char **keyid); -int card_enum_certs (CARD card, int idx, char **certid, int *certtype); -int card_read_cert (CARD card, const char *certidstr, - unsigned char **cert, size_t *ncert); -int card_sign (CARD card, - const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - unsigned char **outdata, size_t *outdatalen ); -int card_decipher (CARD card, const char *keyidstr, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - unsigned char **outdata, size_t *outdatalen); - #endif /*SCDAEMON_H*/ -- cgit v1.2.3 From f2fe118bfbf7979dfc7258e694508d0fcca51d0b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 27 Apr 2005 13:39:16 +0000 Subject: (symcryptrun): Added. --- doc/ChangeLog | 2 ++ doc/tools.texi | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/doc/ChangeLog b/doc/ChangeLog index 093e04fa8..b1f5e8037 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,7 @@ 2005-04-27 Werner Koch <wk@g10code.com> + * tools.texi (symcryptrun): Added. + * scdaemon.texi: Removed OpenSC specific options. 2005-04-20 Werner Koch <wk@g10code.com> diff --git a/doc/tools.texi b/doc/tools.texi index 7c963622f..805a17e6c 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -14,6 +14,7 @@ GnuPG comes with a couple of smaller tools: * gpgsm-gencert.sh:: Generate an X.509 certificate request. * gpg-preset-passphrase:: Put a passphrase into the cache. * gpg-connect-agent:: Communicate with a running agent. +* symcryptrun:: Call a simple symmetric encryption tool. @end menu @c @@ -721,9 +722,102 @@ directory stated through the environment variable @env{GNUPGHOME} or (on W32 systems) by means on the Registry entry @var{HKCU\Software\GNU\GnuPG:HomeDir}. +@end table + +@c +@c SYMCRYPTRUN +@c +@node symcryptrun +@section Call a simple symmetric encryption tool. + +Sometimes simple encryption tools are already in use for a long time and +there might be a desire to integrate them into the GnuPG framework. The +protocols and encryption methods might be non-standard or not even +properly documented, so that a full-fledged encryption tool with an +interface like gpg is not doable. @command{symcryptrun} provides a +solution: It operates by calling the external encryption/decryption +module and provides a passphrase for a key using the standard +@command{pinentry} based mechanism through @command{gpg-agent}. + +Note, that @command{symcryptrun} is only available if GnuPG has been +configured with @samp{--enable-symcryptrun} at build time. + +@menu +* Invoking symcryptrun:: List of all commands and options. +@end menu + + +@node Invoking symcryptrun +@subsection List of all commands and options. + +@noindent +@command{symcryptrun} is invoked this way: + +@example +symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE + [--decrypt | --encrypt] [inputfile] +@end example + +For encryption, the plain text must be provided on STDIN or as the +argument @var{inputfile}, and the ciphertext will be output to STDOUT. +For decryption vice versa. + +@var{CLASS} describes the calling conventions of the external tool. +Currently it must be given as @samp{confucius}. @var{PROGRAM} is the +the full filename of that external tool. + +For the class @samp{confucius} the option @option{--keyfile} is +required; @var{keyfile} is the name of a file containing the secret key, +which may be protected by a passphrase. For detailed calling +conventions, see the source code. + +@noindent +Note, that @command{gpg-agent} must be running before starting +@command{symcryptrun}. + +@noindent +The following additional options may be used: + +@table @gnupgtabopt +@item -v +@itemx --verbose +@opindex verbose +Output additional information while running. + +@item -q +@item --quiet +@opindex q +@opindex quiet +Try to be as quiet as possible. + +@item --homedir @var{dir} +@opindex homedir +Set the name of the home directory to @var{dir}. If his option is not +used, the home directory defaults to @file{~/.gnupg}. It is only +recognized when given on the command line. It also overrides any home +directory stated through the environment variable @env{GNUPGHOME} or +(on W32 systems) by means on the Registry entry +@var{HKCU\Software\GNU\GnuPG:HomeDir}. + +@item --log-file @var{file} +@opindex log-file +Append all logging output to @var{file}. Default is to write logging +informaton to STDERR. @end table +@noindent +The possible exit status codes of @command{symcryptrun} are: +@table @code +@item 0 + Success. +@item 1 + Some error occured. +@item 2 + No valid passphrase was provided. +@item 3 + The operation was canceled by the user. +@end table -- cgit v1.2.3 From eb3f014b5d57373b9eb7b3430c7afa115e2f871e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 27 Apr 2005 19:47:53 +0000 Subject: * app-p15.c (micardo_mse): New. (do_sign): Call it. * iso7816.c (iso7816_manage_security_env): Allow passing DATA as NULL to indicate an empty Lc. * tlv.c (find_tlv): Check that a found object fits into the buffer. (find_tlv_unchecked): New as replacement for the old non-checking variant. * app.c (select_application): Keep on using the non-checking variant. * app-openpgp.c (get_one_do, dump_all_do): Ditto. --- scd/ChangeLog | 13 +++++ scd/app-openpgp.c | 6 +-- scd/app-p15.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++------ scd/app.c | 2 +- scd/iso7816.c | 7 +-- scd/tlv.c | 23 +++++++-- scd/tlv.h | 11 ++++- 7 files changed, 175 insertions(+), 29 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 4ce4c656d..d82e92904 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,18 @@ 2005-04-27 Werner Koch <wk@g10code.com> + * app-p15.c (micardo_mse): New. + (do_sign): Call it. + * iso7816.c (iso7816_manage_security_env): Allow passing DATA as + NULL to indicate an empty Lc. + * tlv.c (find_tlv): Check that a found object fits into the + buffer. + (find_tlv_unchecked): New as replacement for the old non-checking + variant. + * app.c (select_application): Keep on using the non-checking + variant. + * app-openpgp.c (get_one_do, dump_all_do): Ditto. + + Removal of the old OpenSC based code. * app-p15.c: New. Basic support for pkcs15 cards without OpenSC. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 0d80c41a7..ca0e2501b 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -357,7 +357,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes, { const unsigned char *s; - s = find_tlv (buffer, buflen, tag, &valuelen); + s = find_tlv_unchecked (buffer, buflen, tag, &valuelen); if (!s) value = NULL; /* not found */ else if (valuelen > buflen - (s - buffer)) @@ -433,8 +433,8 @@ dump_all_do (int slot) if (j==i || data_objects[i].tag != data_objects[j].get_from) continue; - value = find_tlv (buffer, buflen, - data_objects[j].tag, &valuelen); + value = find_tlv_unchecked (buffer, buflen, + data_objects[j].tag, &valuelen); if (!value) ; /* not found */ else if (valuelen > buflen - (value - buffer)) diff --git a/scd/app-p15.c b/scd/app-p15.c index 7a92da10b..d2ed15a59 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -59,11 +59,15 @@ static struct "\x90\x00\x66", CARD_TYPE_TCOS }, /* SLE66P */ { 27, "\x3B\xFF\x94\x00\xFF\x80\xB1\xFE\x45\x1F\x03\x00\x68\xD2\x76\x00" - "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23", + "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23", CARD_TYPE_MICARDO }, /* German BMI card */ + { 19, "\x3B\x6F\x00\xFF\x00\x68\xD2\x76\x00\x00\x28\xFF\x05\x1E\x31\x80" + "\x00\x90\x00", + CARD_TYPE_MICARDO }, /* German BMI card (ATR due to reader problem) */ { 26, "\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49" "\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43", CARD_TYPE_MICARDO }, /* EstEID (Estonian Big Brother card) */ + { 0 } }; @@ -392,7 +396,7 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc, } -/* This function calls select file to read a file suing a complete +/* This function calls select file to read a file using a complete path which may or may not start at the master file (MF). */ static gpg_error_t select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen) @@ -2525,6 +2529,99 @@ do_readcert (app_t app, const char *certid, } +/* Micardo cards require special treatment. This is a helper for the + crypto functions to manage the security environment. We expect that + the key file has already been selected. FID is the one of the + selected key. */ +static gpg_error_t +micardo_mse (app_t app, unsigned short fid) +{ + gpg_error_t err; + int recno; + unsigned short refdata = 0; + int se_num; + unsigned char msebuf[10]; + + /* Read the KeyD file containing extra information on keys. */ + err = iso7816_select_file (app->slot, 0x0013, 0, NULL, NULL); + if (err) + { + log_error ("error reading EF_keyD: %s\n", gpg_strerror (err)); + return err; + } + + for (recno = 1, se_num = -1; ; recno++) + { + unsigned char *buffer; + size_t buflen; + size_t n, nn; + const unsigned char *p, *pp; + + err = iso7816_read_record (app->slot, recno, 1, 0, &buffer, &buflen); + if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) + break; /* ready */ + if (err) + { + log_error ("error reading EF_keyD record: %s\n", + gpg_strerror (err)); + return err; + } + log_printhex ("keyD record:", buffer, buflen); + p = find_tlv (buffer, buflen, 0x83, &n); + if (p && n == 4 && ((p[2]<<8)|p[3]) == fid) + { + refdata = ((p[0]<<8)|p[1]); + /* Locate the SE DO and the there included sec env number. */ + p = find_tlv (buffer, buflen, 0x7b, &n); + if (p && n) + { + pp = find_tlv (p, n, 0x80, &nn); + if (pp && nn == 1) + { + se_num = *pp; + xfree (buffer); + break; /* found. */ + } + } + } + xfree (buffer); + } + if (se_num == -1) + { + log_error ("CRT for keyfile %04hX not found\n", fid); + return gpg_error (GPG_ERR_NOT_FOUND); + } + + + /* Restore the security environment to SE_NUM if needed */ + if (se_num) + { + err = iso7816_manage_security_env (app->slot, 0xf3, se_num, NULL, 0); + if (err) + { + log_error ("restoring SE to %d failed: %s\n", + se_num, gpg_strerror (err)); + return err; + } + } + + /* Set the DST reference data. */ + msebuf[0] = 0x83; + msebuf[1] = 0x03; + msebuf[2] = 0x80; + msebuf[3] = (refdata >> 8); + msebuf[4] = refdata; + err = iso7816_manage_security_env (app->slot, 0x41, 0xb6, msebuf, 5); + if (err) + { + log_error ("setting SE to reference file %04hX failed: %s\n", + refdata, gpg_strerror (err)); + return err; + } + return 0; +} + + /* Handler for the PKSIGN command. @@ -2561,6 +2658,13 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf); if (err) return err; + if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover + ||prkdf->usageflags.non_repudiation)) + { + log_error ("key %s may not be used for signing\n", keyidstr); + return gpg_error (GPG_ERR_WRONG_KEY_USAGE); + } + if (!prkdf->authid) { log_error ("no authentication object defined for %s\n", keyidstr); @@ -2597,6 +2701,16 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, return gpg_error (GPG_ERR_INV_CARD); } + /* Select the key file. Note that this may change the security + environment thus we do it before PIN verification. */ + err = select_ef_by_path (app, prkdf->path, prkdf->pathlen); + if (err) + { + log_error ("error selecting file for key %s: %s\n", + keyidstr, gpg_strerror (errno)); + return err; + } + /* Now that we have all the information available, prepare and run the PIN verification.*/ if (1) @@ -2742,7 +2856,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, memcpy (data+15, indata, indatalen); } - /* Manage security environment needs to be weaked for certain cards. */ if (app->app_local->card_type == CARD_TYPE_TCOS) { @@ -2751,10 +2864,10 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, } else if (app->app_local->card_type == CARD_TYPE_MICARDO) { - /* Micardo cards are very special in that they need to restore a - security environment using a infomration from a special - file. */ - log_error ("WARNING: support for MICARDO cards is not yet available\n"); + if (!prkdf->pathlen) + err = gpg_error (GPG_ERR_BUG); + else + err = micardo_mse (app, prkdf->path[prkdf->pathlen-1]); } else if (prkdf->key_reference_valid) { @@ -2767,11 +2880,11 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, err = iso7816_manage_security_env (app->slot, 0x41, 0xB6, mse, sizeof mse); - if (err) - { - log_error ("MSE failed: %s\n", gpg_strerror (err)); - return err; - } + } + if (err) + { + log_error ("MSE failed: %s\n", gpg_strerror (err)); + return err; } @@ -2782,9 +2895,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, - - - /* Select the PKCS#15 application on the card in SLOT. */ gpg_error_t app_select_p15 (app_t app) @@ -2846,7 +2956,7 @@ app_select_p15 (app_t app) the common APP structure. */ app->app_local->card_type = card_type; - /* Read basic information and check whether this is a real + /* Read basic information and thus check whether this is a real card. */ rc = read_p15_info (app); if (rc) diff --git a/scd/app.c b/scd/app.c index b6d46326b..8e95ef7ef 100644 --- a/scd/app.c +++ b/scd/app.c @@ -83,7 +83,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) size_t n; const unsigned char *p; - p = find_tlv (result, resultlen, 0x5A, &n); + p = find_tlv_unchecked (result, resultlen, 0x5A, &n); if (p) resultlen -= (p-result); if (p && n > resultlen && n == 0x0d && resultlen+1 == n) diff --git a/scd/iso7816.c b/scd/iso7816.c index 9eff9d3f7..e9dc6541c 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -299,10 +299,11 @@ iso7816_manage_security_env (int slot, int p1, int p2, { int sw; - if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 || !data || !datalen) + if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 ) return gpg_error (GPG_ERR_INV_VALUE); - sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, datalen, data); + sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, + data? datalen : -1, data); return map_sw (sw); } @@ -605,7 +606,7 @@ iso7816_read_record (int slot, int recno, int reccount, int short_ef, buffer = NULL; bufferlen = 0; - /* Fixme: Either the ccid driver of the TCOS cards have problems + /* Fixme: Either the ccid driver or the TCOS cards have problems with an Le of 0. */ sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD, recno, diff --git a/scd/tlv.c b/scd/tlv.c index 5b9d0d6b9..3a81ea6d9 100644 --- a/scd/tlv.c +++ b/scd/tlv.c @@ -1,5 +1,5 @@ /* tlv.c - Tag-Length-Value Utilities - * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -113,17 +113,32 @@ do_find_tlv (const unsigned char *buffer, size_t length, /* Locate a TLV encoded data object in BUFFER of LENGTH and return a pointer to value as well as its length in NBYTES. Return - NULL if it was not found. Note, that the function does not check - whether the value fits into the provided buffer. */ + NULL if it was not found or if the object does not fit into the buffer. */ const unsigned char * find_tlv (const unsigned char *buffer, size_t length, int tag, size_t *nbytes) { - return do_find_tlv (buffer, length, tag, nbytes, 0); + const unsigned char *p; + + p = do_find_tlv (buffer, length, tag, nbytes, 0); + if (p && *nbytes > (length - (p-buffer))) + p = NULL; /* Object longer than buffer. */ + return p; } +/* Locate a TLV encoded data object in BUFFER of LENGTH and + return a pointer to value as well as its length in NBYTES. Return + NULL if it was not found. Note, that the function does not check + whether the value fits into the provided buffer. */ +const unsigned char * +find_tlv_unchecked (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes) +{ + return do_find_tlv (buffer, length, tag, nbytes, 0); +} + /* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag and the length part from the TLV triplet. Update BUFFER and SIZE diff --git a/scd/tlv.h b/scd/tlv.h index 26a9905f7..628580431 100644 --- a/scd/tlv.h +++ b/scd/tlv.h @@ -62,13 +62,20 @@ enum tlv_tag_type { }; +/* Locate a TLV encoded data object in BUFFER of LENGTH and return a + pointer to value as well as its length in NBYTES. Return NULL if + it was not found or if the object does not fit into the buffer. */ +const unsigned char *find_tlv (const unsigned char *buffer, size_t length, + int tag, size_t *nbytes); + /* Locate a TLV encoded data object in BUFFER of LENGTH and return a pointer to value as well as its length in NBYTES. Return NULL if it was not found. Note, that the function does not check whether the value fits into the provided buffer.*/ -const unsigned char *find_tlv (const unsigned char *buffer, size_t length, - int tag, size_t *nbytes); +const unsigned char *find_tlv_unchecked (const unsigned char *buffer, + size_t length, + int tag, size_t *nbytes); /* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag -- cgit v1.2.3 From e22f6db54430bcbc1db5ca1b06cf9777230ae8ea Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Thu, 5 May 2005 14:49:54 +0000 Subject: 2005-05-05 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_key_to_buffer): Rename to ... (ssh_key_to_protected_buffer): ... this; change callers. Improved documentation. --- agent/ChangeLog | 6 +++ agent/command-ssh.c | 123 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 91 insertions(+), 38 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 5f26fc624..940294c52 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2005-05-05 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_key_to_buffer): Rename to ... + (ssh_key_to_protected_buffer): ... this; change callers. + Improved documentation. + 2005-04-20 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_handler_request_identities): Removed diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 133dd01dd..0b6769209 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -148,10 +148,14 @@ typedef struct ssh_key_type_spec is required by gpg-agent's key access layer. */ const char *elems_sexp_order; - /* Key modifier function. */ + /* Key modifier function. Key modifier functions are necessary in + order to fix any inconsistencies between the representation of + keys on the SSH and on the GnuPG side. */ ssh_key_modifier_t key_modifier; - /* Signature encoder function. */ + /* Signature encoder function. Signature encoder functions are + necessary since the encoding of signatures depends on the used + algorithm. */ ssh_signature_encoder_t signature_encoder; /* Misc flags. */ @@ -196,11 +200,11 @@ static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob, /* Associating request types with the corresponding request handlers. */ +static ssh_request_spec_t request_specs[] = + { #define REQUEST_SPEC_DEFINE(id, name, secret_input) \ { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input } -static ssh_request_spec_t request_specs[] = - { REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities, 1), REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request, 0), REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity, 1), @@ -209,8 +213,8 @@ static ssh_request_spec_t request_specs[] = REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities, 0), REQUEST_SPEC_DEFINE (LOCK, lock, 0), REQUEST_SPEC_DEFINE (UNLOCK, unlock, 0) - }; #undef REQUEST_SPEC_DEFINE + }; /* Table holding key type specifications. */ @@ -816,7 +820,10 @@ mpint_list_free (gcry_mpi_t *mpi_list) } } - +/* Receive key material MPIs from STREAM according to KEY_SPEC; + depending on SECRET expect a public key or secret key. The newly + allocated list of MPIs is stored in MPI_LIST. Returns usual error + code. */ static gpg_error_t ssh_receive_mpint_list (estream_t stream, int secret, ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list) @@ -982,7 +989,9 @@ ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis) */ -/* */ +/* This function constructs a new S-Expression for the key identified + by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in + *SEXP. Returns usual error code. */ static gpg_error_t sexp_key_construct (gcry_sexp_t *sexp, ssh_key_type_spec_t key_spec, int secret, @@ -1072,7 +1081,12 @@ sexp_key_construct (gcry_sexp_t *sexp, return err; } - +/* This functions breaks up the key contained in the S-Expression SEXP + according to KEY_SPEC. The MPIs are bundled in a newly create + list, which is to be stored in MPIS; a newly allocated string + holding the comment will be stored in COMMENT; SECRET will be + filled with a boolean flag specifying what kind of key it is. + Returns usual error code. */ static gpg_error_t sexp_key_extract (gcry_sexp_t sexp, ssh_key_type_spec_t key_spec, int *secret, @@ -1710,7 +1724,9 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) /* - Request handler. + Request handler. Each handler is provided with a CTRL context, a + REQUEST object and a RESPONSE object. The actual request is to be + read from REQUEST, the response needs to be written to RESPONSE. */ @@ -1925,7 +1941,30 @@ ssh_handler_request_identities (ctrl_t ctrl, return ret_err; } -/* */ +/* This function calculates the key grip for the key contained in the + S-Expression KEY and writes it to BUFFER, which must be large + enough to hold it. Returns usual error code. */ +static gpg_error_t +ssh_key_grip (gcry_sexp_t key, char *buffer) +{ + gpg_error_t err; + char *p; + + /* FIXME: unsigned vs. signed. */ + + p = gcry_pk_get_keygrip (key, buffer); + if (! p) + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + else + err = 0; + + return err; +} + +/* This function hashes the data contained in DATA of size DATA_N + according to the message digest algorithm specified by MD_ALGORITHM + and writes the message digest to HASH, which needs to large enough + for the digest. */ static gpg_error_t data_hash (unsigned char *data, size_t data_n, int md_algorithm, unsigned char *hash) @@ -1935,7 +1974,9 @@ data_hash (unsigned char *data, size_t data_n, return 0; } - +/* This function signs the data contained in CTRL, stores the created + signature in newly allocated memory in SIG and it's size in SIG_N; + SIG_ENCODER is the signature encoder to use. */ static gpg_error_t data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, unsigned char **sig, size_t *sig_n) @@ -2094,6 +2135,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, return err; } +/* Handler for the "sign_request" command. */ static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) { @@ -2198,7 +2240,9 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) return ret_err; } - +/* This function extracts the comment contained in the key + S-Expression KEY and stores a copy in COMMENT. Returns usual error + code. */ static gpg_error_t ssh_key_extract_comment (gcry_sexp_t key, char **comment) { @@ -2239,26 +2283,12 @@ ssh_key_extract_comment (gcry_sexp_t key, char **comment) return err; } +/* This function converts the key contained in the S-Expression KEY + into a buffer, which is protected by the passphrase PASSPHRASE. + Returns usual error code. */ static gpg_error_t -ssh_key_grip (gcry_sexp_t key, char *buffer) -{ - gpg_error_t err; - char *p; - - /* FIXME: unsigned vs. signed. */ - - p = gcry_pk_get_keygrip (key, buffer); - if (! p) - err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ - else - err = 0; - - return err; -} - -static gpg_error_t -ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, - unsigned char **buffer, size_t *buffer_n) +ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase, + unsigned char **buffer, size_t *buffer_n) { unsigned char *buffer_new; unsigned int buffer_new_n; @@ -2287,7 +2317,7 @@ ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase, -/* Store the ssh KEY into our local key storage and protect him after +/* Store the ssh KEY into our local key storage and protect it after asking for a passphrase. Cache that passphrase. TTL is the maximum caching time for that key. If the key already exists in our key storage, don't do anything. When entering a new key also @@ -2345,7 +2375,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) if (err) goto out; - err = ssh_key_to_buffer (key, pi->pin, &buffer, &buffer_n); + err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n); if (err) goto out; @@ -2378,7 +2408,9 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) } - +/* This function removes the key contained in the S-Expression KEY + from the local key storage, in case it exists there. Returns usual + error code. FIXME: this function is a stub. */ static gpg_error_t ssh_identity_drop (gcry_sexp_t key) { @@ -2399,6 +2431,7 @@ ssh_identity_drop (gcry_sexp_t key) return err; } +/* Handler for the "add_identity" command. */ static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) { @@ -2469,9 +2502,10 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response) return ret_err; } +/* Handler for the "remove_identity" command. */ static gpg_error_t -ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, - estream_t response) +ssh_handler_remove_identity (ctrl_t ctrl, + estream_t request, estream_t response) { unsigned char *key_blob; u32 key_blob_size; @@ -2507,6 +2541,7 @@ ssh_handler_remove_identity (ctrl_t ctrl, estream_t request, return ret_err; } +/* FIXME: stub function. Actually useful? */ static gpg_error_t ssh_identities_remove_all (void) { @@ -2520,9 +2555,10 @@ ssh_identities_remove_all (void) return err; } +/* Handler for the "remove_all_identities" command. */ static gpg_error_t -ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, - estream_t response) +ssh_handler_remove_all_identities (ctrl_t ctrl, + estream_t request, estream_t response) { gpg_error_t ret_err; gpg_error_t err; @@ -2537,6 +2573,7 @@ ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request, return ret_err; } +/* Lock agent? FIXME: stub function. */ static gpg_error_t ssh_lock (void) { @@ -2549,6 +2586,7 @@ ssh_lock (void) return err; } +/* Unock agent? FIXME: stub function. */ static gpg_error_t ssh_unlock (void) { @@ -2560,6 +2598,7 @@ ssh_unlock (void) return err; } +/* Handler for the "lock" command. */ static gpg_error_t ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) { @@ -2576,6 +2615,7 @@ ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response) return ret_err; } +/* Handler for the "unlock" command. */ static gpg_error_t ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) { @@ -2594,6 +2634,9 @@ ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response) +/* Return the request specification for the request identified by TYPE + or NULL in case the requested request specification could not be + found. */ static ssh_request_spec_t * request_spec_lookup (int type) { @@ -2614,6 +2657,9 @@ request_spec_lookup (int type) return spec; } +/* Process a single request. The request is read from and the + response is written to STREAM_SOCK. Uses CTRL as context. Returns + zero in case of success, non zero in case of failure. */ static int ssh_request_process (ctrl_t ctrl, estream_t stream_sock) { @@ -2772,6 +2818,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) return !!err; } +/* Start serving client on SOCK_CLIENT. */ void start_command_handler_ssh (int sock_client) { -- cgit v1.2.3 From 2fb1abb84906d37eef459fd70d014c3c5e93294d Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Thu, 5 May 2005 14:57:59 +0000 Subject: 2005-05-05 Moritz Schulte <moritz@g10code.com> * command-ssh.c: Use ssh_key_grip(), where gcry_pk_get_keygrip() has been used before. (ssh_handler_sign_request): Removed unusued variable P. --- agent/ChangeLog | 3 +++ agent/command-ssh.c | 60 ++++++++++++++++++++++++++--------------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 940294c52..f5dbeb9e3 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -3,6 +3,9 @@ * command-ssh.c (ssh_key_to_buffer): Rename to ... (ssh_key_to_protected_buffer): ... this; change callers. Improved documentation. + Use ssh_key_grip(), where gcry_pk_get_keygrip() has been used + before. + (ssh_handler_sign_request): Removed unusued variable P. 2005-04-20 Moritz Schulte <moritz@g10code.com> diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 0b6769209..92a84c662 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1531,6 +1531,26 @@ ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, +/* This function calculates the key grip for the key contained in the + S-Expression KEY and writes it to BUFFER, which must be large + enough to hold it. Returns usual error code. */ +static gpg_error_t +ssh_key_grip (gcry_sexp_t key, char *buffer) +{ + gpg_error_t err; + char *p; + + /* FIXME: unsigned vs. signed. */ + + p = gcry_pk_get_keygrip (key, buffer); + if (! p) + err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ + else + err = 0; + + return err; +} + /* Converts the secret key KEY_SECRET into a public key, storing it in KEY_PUBLIC. SPEC is the according key specification. Returns zero on success or an error code. */ @@ -1643,14 +1663,16 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) xfree (serialno); return err; } - - if ( !gcry_pk_get_keygrip (s_pk, grip) ) + + err = ssh_key_grip (s_pk, grip); + if (err) { - log_debug ("error computing keygrip from received card key\n"); + log_debug ("error computing keygrip from received card key: %s\n", + gcry_strerror (err)); xfree (pkbuf); gcry_sexp_release (s_pk); xfree (serialno); - return gpg_error (GPG_ERR_INTERNAL); + return err; } if ( agent_key_available (grip) ) @@ -1941,26 +1963,6 @@ ssh_handler_request_identities (ctrl_t ctrl, return ret_err; } -/* This function calculates the key grip for the key contained in the - S-Expression KEY and writes it to BUFFER, which must be large - enough to hold it. Returns usual error code. */ -static gpg_error_t -ssh_key_grip (gcry_sexp_t key, char *buffer) -{ - gpg_error_t err; - char *p; - - /* FIXME: unsigned vs. signed. */ - - p = gcry_pk_get_keygrip (key, buffer); - if (! p) - err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ - else - err = 0; - - return err; -} - /* This function hashes the data contained in DATA of size DATA_N according to the message digest algorithm specified by MD_ALGORITHM and writes the message digest to HASH, which needs to large enough @@ -2151,7 +2153,6 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) size_t sig_n; u32 data_size; u32 flags; - void *p; gpg_error_t err; gpg_error_t ret_err; @@ -2192,12 +2193,9 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response) goto out; /* Calculate key grip. */ - p = gcry_pk_get_keygrip (key, key_grip); - if (! p) - { - err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ - goto out; - } + err = ssh_key_grip (key, key_grip); + if (err) + goto out; /* Sign data. */ -- cgit v1.2.3 From d8718bd67f42652d1e43327b7eb7920414dd5b05 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 May 2005 12:37:52 +0000 Subject: (got_fatal_signal): Print the signal number if we can't get a name for it. (get_signal_name): Return NULL if no name is available. --- common/ChangeLog | 6 ++++++ common/signal.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 4688d2765..0651f9ead 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +2005-05-13 Werner Koch <wk@g10code.com> + + * signal.c (got_fatal_signal): Print the signal number if we can't + get a name for it. + (get_signal_name): Return NULL if no name is available. + 2005-04-17 Werner Koch <wk@g10code.com> * sexputil.c (cmp_simple_canon_sexp): New. diff --git a/common/signal.c b/common/signal.c index 4e773c4c0..97e2c39fe 100644 --- a/common/signal.c +++ b/common/signal.c @@ -1,5 +1,6 @@ /* signal.c - signal handling - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -73,10 +74,12 @@ init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign ) static const char * get_signal_name( int signum ) { + /* Note that we can't use strsignal(), because it is not + reentrant. */ #if defined(SYS_SIGLIST_DECLARED) && defined(NSIG) return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?"; #else - return "some signal"; + return NULL; #endif } #endif /*!HAVE_DOSISH_SYSTEM*/ @@ -93,19 +96,43 @@ got_fatal_signal (int sig) if (cleanup_fnc) cleanup_fnc (); - /* better don't translate these messages */ + /* 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) ); + if (s) + write (2, s, strlen(s) ); + else + { + /* We are in a signal handler so we can't use any kind of printf + even not sprintf. USe a straightforward algorithm. */ + write (2, "signal ", 7 ); + if (sig < 0 || sig >= 100000) + write (2, "?", 1); + else + { + int i, any=0; + + for (i=10000; i; i /= 10) + { + if (sig >= i || ((any || i==1) && !(sig/i))) + { + write (2, "0123456789"+(sig/i), 1); + if ((sig/i)) + any = 1; + sig %= i; + } + } + } + } write (2, " caught ... exiting\n", 20); - /* reset action to default action and raise signal again */ + /* Reset action to default action and raise signal again */ init_one_signal (sig, SIG_DFL, 0); - /* fixme: remove_lockfiles ();*/ + /* Fixme: remove_lockfiles ();*/ #ifdef __riscos__ close_fds (); #endif /* __riscos__ */ -- cgit v1.2.3 From a5c4c4bf129a78d1de0990daffb9b8d171824262 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 13 May 2005 12:43:07 +0000 Subject: (got_fatal_signal): Print the signal number if we can't get a name for it. (get_signal_name): Return NULL if no name is available. Fixed conditional for sys_siglist to the correct one. --- common/ChangeLog | 3 ++- common/signal.c | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 0651f9ead..cf294fbd1 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -2,7 +2,8 @@ * signal.c (got_fatal_signal): Print the signal number if we can't get a name for it. - (get_signal_name): Return NULL if no name is available. + (get_signal_name): Return NULL if no name is available. Fixed + conditional for sys_siglist to the correct one. 2005-04-17 Werner Koch <wk@g10code.com> diff --git a/common/signal.c b/common/signal.c index 97e2c39fe..f0d3df75e 100644 --- a/common/signal.c +++ b/common/signal.c @@ -76,7 +76,7 @@ get_signal_name( int signum ) { /* Note that we can't use strsignal(), because it is not reentrant. */ -#if defined(SYS_SIGLIST_DECLARED) && defined(NSIG) +#if defined(HAVE_DECL_SYS_SIGLIST) && defined(NSIG) return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?"; #else return NULL; @@ -101,7 +101,7 @@ got_fatal_signal (int sig) s = log_get_prefix (NULL); if (s) write(2, s, strlen (s)); - write (2, ": ", 2 ); + write (2, ": signal ", 9 ); s = get_signal_name(sig); if (s) write (2, s, strlen(s) ); @@ -109,7 +109,6 @@ got_fatal_signal (int sig) { /* We are in a signal handler so we can't use any kind of printf even not sprintf. USe a straightforward algorithm. */ - write (2, "signal ", 7 ); if (sig < 0 || sig >= 100000) write (2, "?", 1); else -- cgit v1.2.3 From 4237a9cc7fce3bad2a41b755fdf349a42ddd5ccf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 18 May 2005 10:48:06 +0000 Subject: Changed the scdaemon to handle concurrent sessions. Adjusted gpg-agent accordingly. Code cleanups. --- ChangeLog | 5 + NEWS | 4 +- TODO | 14 +- agent/ChangeLog | 16 ++ agent/agent.h | 9 + agent/call-scd.c | 397 +++++++++++++++++++++++-------------- agent/command.c | 1 + agent/divert-scd.c | 7 - agent/gpg-agent.c | 96 ++------- configure.ac | 13 +- doc/ChangeLog | 4 + doc/gpg-agent.texi | 5 - doc/tools.texi | 10 + scd/ChangeLog | 36 ++++ scd/apdu.c | 4 + scd/app-common.h | 101 +++++----- scd/app-dinsig.c | 20 +- scd/app-nks.c | 24 +-- scd/app-openpgp.c | 58 +++--- scd/app-p15.c | 8 +- scd/app.c | 341 ++++++++++++++++++++++---------- scd/ccid-driver.c | 9 +- scd/command.c | 43 +++- scd/sc-copykeys.c | 2 +- scd/scdaemon.c | 491 ++++++++++++++++++++++++++++++---------------- scd/scdaemon.h | 3 +- tools/gpg-connect-agent.c | 20 +- 27 files changed, 1095 insertions(+), 646 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f58b9198..154ae07e9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-05-15 Werner Koch <wk@g10code.com> + + * configure.ac: Remove option --disable-threads; require the use + of GNU Pth. + 2005-04-27 Werner Koch <wk@g10code.com> * configure.ac: Removed OpenSC detection and options. diff --git a/NEWS b/NEWS index 2d43d70ff..c25bbe08e 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,10 @@ Noteworthy changes in version 1.9.17 ------------------------------------------------- + * GNU Pth is now a hard requirement. + * [scdaemon] Support for OpenSC has been removed. Instead a new and - starightforward pkcs#15 modules has been written. As of now it + straightforward pkcs#15 modules has been written. As of now it does allows only signing using TCOS cards but we are going to enhance it to match all the old capabilities. diff --git a/TODO b/TODO index 6a0e9b18e..6e8951f03 100644 --- a/TODO +++ b/TODO @@ -35,6 +35,9 @@ might want to have an agent context for each service request to do that while changing gpgsm to allow concurrent operations. ** support the anyPolicy semantic ** Check that we are really following the verification procedures in rfc3280. +** Implement a --card-status command. + This is useful to check whether a card is supported at all. + * sm/keydb.c ** Check file permissions @@ -54,10 +57,6 @@ might want to have an agent context for each service request ** Don't use stdio to return results. ** Support DSA -* agent/divert-scd.c - Remove the agent_reset_scd kludge. We will do this after Scdaemon - has been changed to allow multiple sessions. Currently in progress. - * Move pkcs-1 encoding into libgcrypt. * Use a MAC to protect sensitive files. @@ -90,10 +89,3 @@ might want to have an agent context for each service request This means we can't reread a configuration ** No card status notifications. - -* scd/ -** Release the card after use so that gpg 1.4 is able to access it - This won't be a sufficient change. we need to change gpg 1.4 to make - use of the agent. Work is underway. - - diff --git a/agent/ChangeLog b/agent/ChangeLog index f5dbeb9e3..00f019ddc 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,19 @@ +2005-05-18 Werner Koch <wk@g10code.com> + + * divert-scd.c (ask_for_card): Removed the card reset kludge. + +2005-05-17 Werner Koch <wk@g10code.com> + + * call-scd.c (unlock_scd): Add new arg CTRL. Changed all callers. + (start_scd): Reoworked to allow for additional connections. + * agent.h (ctrl_t): Add local data for the SCdaemon. + * command.c (start_command_handler): Release SERVER_LOCAL. + + * gpg-agent.c (create_server_socket): Use xmalloc. + (main): Removed option --disable-pth a dummy. Removed non-pth + code path. + (cleanup_sh): Removed. Not needed anymore. + 2005-05-05 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_key_to_buffer): Rename to ... diff --git a/agent/agent.h b/agent/agent.h index 298b5b142..6ab65eeba 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -99,10 +99,19 @@ struct { #define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) struct server_local_s; +struct scd_local_s; +/* Collection of data per session (aka connection). */ struct server_control_s { + + /* Private data of the server (command.c). */ struct server_local_s *server_local; + + /* Private data of the SCdaemon (call-scd.c). */ + struct scd_local_s *scd_local; + int connection_fd; /* -1 or an identifier for the current connection. */ + char *display; char *ttyname; char *ttytype; diff --git a/agent/call-scd.c b/agent/call-scd.c index 8373fd46d..58dd412f0 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -18,12 +18,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -/* Fixme: For now we have serialized all access to the scdaemon which - make sense becuase the scdaemon can't handle concurrent connections - right now. We should however keep a list of connections and lock - just that connection - it migth make sense to implemtn parts of - this in Assuan.*/ - #include <config.h> #include <errno.h> #include <stdio.h> @@ -37,9 +31,7 @@ #ifndef HAVE_W32_SYSTEM #include <sys/wait.h> #endif -#ifdef USE_GNU_PTH -# include <pth.h> -#endif +#include <pth.h> #include "agent.h" #include <assuan.h> @@ -50,24 +42,20 @@ #define MAX_OPEN_FDS 20 #endif -static ASSUAN_CONTEXT scd_ctx = NULL; -#ifdef USE_GNU_PTH -static pth_mutex_t scd_lock; -#endif -/* We need to keep track of the connection currently using the SCD. - For a pipe server this is all a NOP because the connection will - always have the connection indicator -1. agent_reset_scd releases - the active connection; i.e. sets it back to -1, so that a new - connection can start using the SCD. If we eventually allow - multiple SCD session we will either make scdaemon multi-threaded or - fork of a new scdaemon and let it see how it can get access to a - reader. -*/ -static int active_connection_fd = -1; -static int active_connection = 0; +/* Definition of module local data of the CTRL structure. */ +struct scd_local_s +{ + assuan_context_t ctx; /* NULL or session context for the SCdaemon + used with this connection. */ + int locked; /* This flag is used to assert proper use of + start_scd and unlock_scd. */ + +}; + /* Callback parameter for learn card */ -struct learn_parm_s { +struct learn_parm_s +{ void (*kpinfo_cb)(void*, const char *); void *kpinfo_cb_arg; void (*certinfo_cb)(void*, const char *); @@ -76,13 +64,39 @@ struct learn_parm_s { void *sinfo_cb_arg; }; -struct inq_needpin_s { - ASSUAN_CONTEXT ctx; +struct inq_needpin_s +{ + assuan_context_t ctx; int (*getpin_cb)(void *, const char *, char*, size_t); void *getpin_cb_arg; }; +/* A Mutex used inside the start_scd function. */ +static pth_mutex_t start_scd_lock; + +/* A malloced string with the name of the socket to be used for + additional connections. May be NULL if not provided by + SCdaemon. */ +static char *socket_name; + +/* The context of the primary connection. This is also used as a flag + to indicate whether the scdaemon has been started. */ +static assuan_context_t primary_scd_ctx; + +/* To allow reuse of the primary connection, the following flag is set + to true if the primary context has been reset and is not in use by + any connection. */ +static int primary_scd_ctx_reusable; + + + +/* Local prototypes. */ +static assuan_error_t membuf_data_cb (void *opaque, + const void *buffer, size_t length); + + + /* This function must be called once to initialize this module. This has to be done before a second thread is spawned. We can't do the @@ -91,27 +105,35 @@ struct inq_needpin_s { void initialize_module_call_scd (void) { -#ifdef USE_GNU_PTH static int initialized; if (!initialized) - if (pth_mutex_init (&scd_lock)) + { + if (!pth_mutex_init (&start_scd_lock)) + log_fatal ("error initializing mutex: %s\n", strerror (errno)); initialized = 1; -#endif /*USE_GNU_PTH*/ + } } +/* The unlock_scd function shall be called after having accessed the + SCD. It is currently not very useful but gives an opportunity to + keep track of connections currently calling SCD. Note that the + "lock" operation is done by the start_scd() function which must be + called and error checked before any SCD operation. CTRL is the + usual connection context and RC the error code to be passed trhough + the function. */ static int -unlock_scd (int rc) +unlock_scd (ctrl_t ctrl, int rc) { -#ifdef USE_GNU_PTH - if (!pth_mutex_release (&scd_lock)) + if (ctrl->scd_local->locked != 1) { - log_error ("failed to release the SCD lock\n"); + log_error ("unlock_scd: invalid lock count (%d)\n", + ctrl->scd_local->locked); if (!rc) rc = gpg_error (GPG_ERR_INTERNAL); } -#endif /*USE_GNU_PTH*/ + ctrl->scd_local->locked = 0; return rc; } @@ -125,68 +147,115 @@ atfork_cb (void *opaque, int where) } -/* Fork off the SCdaemon if this has not already been done. Note that - this fucntion alos locks the daemon. */ +/* Fork off the SCdaemon if this has not already been done. Lock the + daemon and make sure that a proper context has been setup in CTRL. + Thsi fucntion might also lock the daemon, which means that the + caller must call unlock_scd after this fucntion has returned + success and the actual Assuan transaction been done. */ static int start_scd (ctrl_t ctrl) { - int rc; + gpg_error_t err = 0; const char *pgmname; - ASSUAN_CONTEXT ctx; - const char *argv[3]; + assuan_context_t ctx; + const char *argv[4]; int no_close_list[3]; int i; + int rc; if (opt.disable_scdaemon) return gpg_error (GPG_ERR_NOT_SUPPORTED); -#ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&scd_lock, 0, NULL)) + /* If this is the first call for this session, setup the local data + structure. */ + if (!ctrl->scd_local) + { + ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local); + if (!ctrl->scd_local) + return gpg_error_from_errno (errno); + } + + + /* Assert that the lock count is as expected. */ + if (ctrl->scd_local->locked) { - log_error ("failed to acquire the SCD lock\n"); + log_error ("start_scd: invalid lock count (%d)\n", + ctrl->scd_local->locked); return gpg_error (GPG_ERR_INTERNAL); } -#endif + ctrl->scd_local->locked++; - if (scd_ctx) + /* If we already have a context, we better do a sanity check now to + see whether it has accidently died. This avoids annoying + timeouts and hung connections. */ + if (ctrl->scd_local->ctx) { pid_t pid; - - /* If we are not the connection currently using the SCD, return - an error. */ - if (!active_connection) - { - active_connection_fd = ctrl->connection_fd; - active_connection = 1; - } - else if (ctrl->connection_fd != active_connection_fd) - return unlock_scd (gpg_error (GPG_ERR_CONFLICT)); - - /* Okay, we already started the scdaemon and it is used by us.*/ - - /* We better do a sanity check now to see whether it has - accidently died. */ #ifndef HAVE_W32_SYSTEM - pid = assuan_get_pid (scd_ctx); + pid = assuan_get_pid (ctrl->scd_local->ctx); if (pid != (pid_t)(-1) && pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) { - assuan_disconnect (scd_ctx); - scd_ctx = NULL; + assuan_disconnect (ctrl->scd_local->ctx); + ctrl->scd_local->ctx = NULL; } else #endif - return 0; + return 0; /* Okay, the context is fine. */ + } + + /* We need to protect the lowwing code. */ + if (!pth_mutex_acquire (&start_scd_lock, 0, NULL)) + { + log_error ("failed to acquire the start_scd lock: %s\n", + strerror (errno)); + return gpg_error (GPG_ERR_INTERNAL); + } + + /* Check whether the pipe server has already been started and in + this case either reuse a lingering pipe connection or establish a + new socket based one. */ + if (primary_scd_ctx && primary_scd_ctx_reusable) + { + ctx = primary_scd_ctx; + primary_scd_ctx_reusable = 0; + if (opt.verbose) + log_info ("new connection to SCdaemon established (reusing)\n"); + goto leave; } + if (socket_name) + { + rc = assuan_socket_connect (&ctx, socket_name, 0); + if (rc) + { + log_error ("can't connect to socket `%s': %s\n", + socket_name, assuan_strerror (rc)); + err = gpg_error (GPG_ERR_NO_SCDAEMON); + goto leave; + } + + if (opt.verbose) + log_info ("new connection to SCdaemon established\n"); + goto leave; + } + + if (primary_scd_ctx) + { + log_info ("SCdaemon is running but won't accept further connections\n"); + err = gpg_error (GPG_ERR_NO_SCDAEMON); + goto leave; + } + + /* Nope, it has not been started. Fire it up now. */ if (opt.verbose) log_info ("no running SCdaemon - starting it\n"); if (fflush (NULL)) { - gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + err = gpg_error (gpg_err_code_from_errno (errno)); log_error ("error flushing pending output: %s\n", strerror (errno)); - return unlock_scd (tmperr); + goto leave; } if (!opt.scdaemon_program || !*opt.scdaemon_program) @@ -198,7 +267,8 @@ start_scd (ctrl_t ctrl) argv[0] = pgmname; argv[1] = "--server"; - argv[2] = NULL; + argv[2] = "--multi-server"; + argv[3] = NULL; i=0; if (!opt.running_detached) @@ -216,30 +286,68 @@ start_scd (ctrl_t ctrl) { log_error ("can't connect to the SCdaemon: %s\n", assuan_strerror (rc)); - return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON)); + err = gpg_error (GPG_ERR_NO_SCDAEMON); + goto leave; } - scd_ctx = ctx; - active_connection_fd = ctrl->connection_fd; - active_connection = 1; - - if (DBG_ASSUAN) - log_debug ("connection to SCdaemon established\n"); - - /* Tell the scdaemon that we want him to send us an event signal. - But only do this if we are running as a regular sever and not - simply as a pipe server. */ - /* Fixme: gpg-agent does not use this signal yet. */ -/* if (ctrl->connection_fd != -1) */ -/* { */ -/* #ifndef HAVE_W32_SYSTEM */ -/* char buf[100]; */ - -/* sprintf (buf, "OPTION event-signal=%d", SIGUSR2); */ -/* assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); */ -/* #endif */ -/* } */ - return 0; + if (opt.verbose) + log_debug ("first connection to SCdaemon established\n"); + + /* Get the name of the additional socket opened by scdaemon. */ + { + membuf_t data; + unsigned char *databuf; + size_t datalen; + + xfree (socket_name); + socket_name = NULL; + init_membuf (&data, 256); + assuan_transact (ctx, "GETINFO socket_name", + membuf_data_cb, &data, NULL, NULL, NULL, NULL); + + databuf = get_membuf (&data, &datalen); + if (databuf && datalen) + { + socket_name = xtrymalloc (datalen + 1); + if (!socket_name) + log_error ("warning: can't store socket name: %s\n", + strerror (errno)); + else + { + memcpy (socket_name, databuf, datalen); + socket_name[datalen] = 0; + if (DBG_ASSUAN) + log_debug ("additional connections at `%s'\n", socket_name); + } + } + xfree (databuf); + } + + /* Tell the scdaemon we want him to send us an event signal. */ +#ifndef HAVE_W32_SYSTEM + { + char buf[100]; + + sprintf (buf, "OPTION event-signal=%d", SIGUSR2); + assuan_transact (ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); + } +#endif + + primary_scd_ctx = ctx; + primary_scd_ctx_reusable = 0; + + leave: + if (err) + { + unlock_scd (ctrl, err); + } + else + { + ctrl->scd_local->ctx = ctx; + } + if (!pth_mutex_release (&start_scd_lock)) + log_error ("failed to release the start_scd lock: %s\n", strerror (errno)); + return err; } @@ -248,25 +356,28 @@ start_scd (ctrl_t ctrl) int agent_reset_scd (ctrl_t ctrl) { - int rc = 0; - -#ifdef USE_GNU_PTH - if (!pth_mutex_acquire (&scd_lock, 0, NULL)) - { - log_error ("failed to acquire the SCD lock for reset\n"); - return gpg_error (GPG_ERR_INTERNAL); - } -#endif - if (active_connection && active_connection_fd == ctrl->connection_fd) + if (ctrl->scd_local) { - if (scd_ctx) - rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, - NULL, NULL, NULL, NULL); - active_connection_fd = -1; - active_connection = 0; + if (ctrl->scd_local->ctx) + { + /* We can't disconnect the primary context becuase libassuan + does a waitpid on it and thus the system would hang. + Instead we send a reset and keep that connection for + reuse. */ + if (ctrl->scd_local->ctx == primary_scd_ctx) + { + if (!assuan_transact (primary_scd_ctx, "RESET", + NULL, NULL, NULL, NULL, NULL, NULL)) + primary_scd_ctx_reusable = 1; + } + else + assuan_disconnect (ctrl->scd_local->ctx); + } + xfree (ctrl->scd_local); + ctrl->scd_local = NULL; } - return unlock_scd (map_assuan_err (rc)); + return 0; } @@ -360,13 +471,13 @@ agent_card_learn (ctrl_t ctrl, parm.certinfo_cb_arg = certinfo_cb_arg; parm.sinfo_cb = sinfo_cb; parm.sinfo_cb_arg = sinfo_cb_arg; - rc = assuan_transact (scd_ctx, "LEARN --force", + rc = assuan_transact (ctrl->scd_local->ctx, "LEARN --force", NULL, NULL, NULL, NULL, learn_status_cb, &parm); if (rc) - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); - return unlock_scd (0); + return unlock_scd (ctrl, 0); } @@ -414,16 +525,16 @@ agent_card_serialno (ctrl_t ctrl, char **r_serialno) if (rc) return rc; - rc = assuan_transact (scd_ctx, "SERIALNO", + rc = assuan_transact (ctrl->scd_local->ctx, "SERIALNO", NULL, NULL, NULL, NULL, get_serialno_cb, &serialno); if (rc) { xfree (serialno); - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); } *r_serialno = serialno; - return unlock_scd (0); + return unlock_scd (ctrl, 0); } @@ -495,31 +606,32 @@ agent_card_pksign (ctrl_t ctrl, return rc; if (indatalen*2 + 50 > DIM(line)) - return unlock_scd (gpg_error (GPG_ERR_GENERAL)); + return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL)); sprintf (line, "SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) sprintf (p, "%02X", indata[i]); - rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + rc = assuan_transact (ctrl->scd_local->ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); init_membuf (&data, 1024); - inqparm.ctx = scd_ctx; + inqparm.ctx = ctrl->scd_local->ctx; inqparm.getpin_cb = getpin_cb; inqparm.getpin_cb_arg = getpin_cb_arg; snprintf (line, DIM(line)-1, ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid); line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, + rc = assuan_transact (ctrl->scd_local->ctx, line, membuf_data_cb, &data, inq_needpin, &inqparm, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); } sigbuf = get_membuf (&data, &sigbuflen); @@ -531,7 +643,7 @@ agent_card_pksign (ctrl_t ctrl, { gpg_error_t tmperr = out_of_core (); xfree (*r_buf); - return unlock_scd (tmperr); + return unlock_scd (ctrl, tmperr); } p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" ); sprintf (p, "%u:", (unsigned int)sigbuflen); @@ -542,7 +654,7 @@ agent_card_pksign (ctrl_t ctrl, xfree (sigbuf); assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL)); - return unlock_scd (0); + return unlock_scd (ctrl, 0); } /* Decipher INDATA using the current card. Note that the returned value is */ @@ -567,36 +679,37 @@ agent_card_pkdecrypt (ctrl_t ctrl, /* FIXME: use secure memory where appropriate */ if (indatalen*2 + 50 > DIM(line)) - return unlock_scd (gpg_error (GPG_ERR_GENERAL)); + return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL)); sprintf (line, "SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) sprintf (p, "%02X", indata[i]); - rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + rc = assuan_transact (ctrl->scd_local->ctx, line, + NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); init_membuf (&data, 1024); - inqparm.ctx = scd_ctx; + inqparm.ctx = ctrl->scd_local->ctx; inqparm.getpin_cb = getpin_cb; inqparm.getpin_cb_arg = getpin_cb_arg; snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid); line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, + rc = assuan_transact (ctrl->scd_local->ctx, line, membuf_data_cb, &data, inq_needpin, &inqparm, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); } *r_buf = get_membuf (&data, r_buflen); if (!*r_buf) - return unlock_scd (gpg_error (GPG_ERR_ENOMEM)); + return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM)); - return unlock_scd (0); + return unlock_scd (ctrl, 0); } @@ -619,20 +732,20 @@ agent_card_readcert (ctrl_t ctrl, init_membuf (&data, 1024); snprintf (line, DIM(line)-1, "READCERT %s", id); line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, + rc = assuan_transact (ctrl->scd_local->ctx, line, membuf_data_cb, &data, NULL, NULL, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); } *r_buf = get_membuf (&data, r_buflen); if (!*r_buf) - return unlock_scd (gpg_error (GPG_ERR_ENOMEM)); + return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM)); - return unlock_scd (0); + return unlock_scd (ctrl, 0); } @@ -655,26 +768,26 @@ agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf) init_membuf (&data, 1024); snprintf (line, DIM(line)-1, "READKEY %s", id); line[DIM(line)-1] = 0; - rc = assuan_transact (scd_ctx, line, + rc = assuan_transact (ctrl->scd_local->ctx, line, membuf_data_cb, &data, NULL, NULL, NULL, NULL); if (rc) { xfree (get_membuf (&data, &len)); - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); } *r_buf = get_membuf (&data, &buflen); if (!*r_buf) - return unlock_scd (gpg_error (GPG_ERR_ENOMEM)); + return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM)); if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL)) { xfree (*r_buf); *r_buf = NULL; - return unlock_scd (gpg_error (GPG_ERR_INV_VALUE)); + return unlock_scd (ctrl, gpg_error (GPG_ERR_INV_VALUE)); } - return unlock_scd (0); + return unlock_scd (ctrl, 0); } @@ -744,7 +857,7 @@ agent_card_getattr (ctrl_t ctrl, const char *name, char **result) if (err) return err; - err = map_assuan_err (assuan_transact (scd_ctx, line, + err = map_assuan_err (assuan_transact (ctrl->scd_local->ctx, line, NULL, NULL, NULL, NULL, card_getattr_cb, &parm)); if (!err && parm.error) @@ -758,7 +871,7 @@ agent_card_getattr (ctrl_t ctrl, const char *name, char **result) else xfree (parm.data); - return unlock_scd (err); + return unlock_scd (ctrl, err); } @@ -810,19 +923,19 @@ agent_card_scd (ctrl_t ctrl, const char *cmdline, if (rc) return rc; - inqparm.ctx = scd_ctx; + inqparm.ctx = ctrl->scd_local->ctx; inqparm.getpin_cb = getpin_cb; inqparm.getpin_cb_arg = getpin_cb_arg; - rc = assuan_transact (scd_ctx, cmdline, + rc = assuan_transact (ctrl->scd_local->ctx, cmdline, pass_data_thru, assuan_context, inq_needpin, &inqparm, pass_status_thru, assuan_context); if (rc) { - return unlock_scd (map_assuan_err (rc)); + return unlock_scd (ctrl, map_assuan_err (rc)); } - return unlock_scd (0); + return unlock_scd (ctrl, 0); } diff --git a/agent/command.c b/agent/command.c index 997140207..8af159f6d 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1061,5 +1061,6 @@ start_command_handler (int listen_fd, int fd) free (ctrl.lc_ctype); if (ctrl.lc_messages) free (ctrl.lc_messages); + xfree (ctrl.server_local); } diff --git a/agent/divert-scd.c b/agent/divert-scd.c index f2ec2f051..f460ffe0c 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -108,13 +108,6 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid) if (!rc) { - /* We better reset the SCD now. This is kludge required - because the scdaemon is currently not always able to - detect the presence of a card. With a fully working - scdaemon this would not be required; i.e. the pkcs#15 - support does not require it because OpenSC correclty - detects a present card. */ - agent_reset_scd (ctrl); if (asprintf (&desc, "%s:%%0A%%0A" " \"%.*s\"", diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 7c682ada7..4ac995c26 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -37,9 +37,7 @@ #endif /*HAVE_W32_SYSTEM*/ #include <unistd.h> #include <signal.h> -#ifdef USE_GNU_PTH -# include <pth.h> -#endif +#include <pth.h> #define JNLIB_NEED_LOG_LOGV #include "agent.h" @@ -83,7 +81,6 @@ enum cmd_and_opt_values oLCctype, oLCmessages, oScdaemonProgram, - oDisablePth, oDefCacheTTL, oMaxCacheTTL, oUseStandardSocket, @@ -120,7 +117,6 @@ static ARGPARSE_OPTS opts[] = { { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - { oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")}, { oUseStandardSocket, "use-standard-socket", 0, N_("use a standard location for the socket")}, { oNoUseStandardSocket, "no-use-standard-socket", 0, "@"}, @@ -157,7 +153,6 @@ static ARGPARSE_OPTS opts[] = { #define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ #define MAX_CACHE_TTL (120*60) /* 2 hours */ -static volatile int caught_fatal_sig = 0; /* flag to indicate that a shutdown was requested */ static int shutdown_pending; @@ -190,10 +185,11 @@ static const char *debug_level; static char *current_logfile; /* The handle_tick() function may test whether a parent is still - runing. We record the PID of the parent here or -1 if it should be + running. We record the PID of the parent here or -1 if it should be watched. */ static pid_t parent_pid = (pid_t)(-1); + /* Local prototypes. */ @@ -203,17 +199,15 @@ static char *create_socket_name (int use_standard_socket, static int create_server_socket (int is_standard_name, const char *name); static void create_directories (void); -#ifdef USE_GNU_PTH static void handle_connections (int listen_fd, int listen_fd_ssh); -/* Pth wrapper function definitions. */ -GCRY_THREAD_OPTION_PTH_IMPL; -#endif /*USE_GNU_PTH*/ - static int check_for_running_agent (int); +/* Pth wrapper function definitions. */ +GCRY_THREAD_OPTION_PTH_IMPL; + /* Functions. */ @@ -351,28 +345,6 @@ cleanup (void) } -static RETSIGTYPE -cleanup_sh (int sig) -{ - if (caught_fatal_sig) - raise (sig); - caught_fatal_sig = 1; - - /* gcry_control( GCRYCTL_TERM_SECMEM );*/ - cleanup (); - -#ifndef HAVE_DOSISH_SYSTEM - { /* reset action to default action and raise signal again */ - struct sigaction nact; - nact.sa_handler = SIG_DFL; - sigemptyset( &nact.sa_mask ); - nact.sa_flags = 0; - sigaction( sig, &nact, NULL); - } -#endif - raise( sig ); -} - /* Handle options which are allowed to be reset after program start. Return true when the current option in PARGS could be handled and @@ -462,7 +434,6 @@ main (int argc, char **argv ) int csh_style = 0; char *logfile = NULL; int debug_wait = 0; - int disable_pth = 0; int gpgconf_list = 0; int standard_socket = 0; gpg_error_t err; @@ -481,14 +452,12 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ -#ifdef USE_GNU_PTH err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -#endif /*USE_GNU_PTH*/ /* Check that the libraries are suitable. Do it here because @@ -634,7 +603,6 @@ main (int argc, char **argv ) case oSh: csh_style = 0; break; case oServer: pipe_server = 1; break; case oDaemon: is_daemon = 1; break; - case oDisablePth: disable_pth = 1; break; case oDisplay: default_display = xstrdup (pargs.r.ret_str); break; case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break; @@ -983,45 +951,17 @@ main (int argc, char **argv ) exit (1); } + { + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGPIPE, &sa, NULL); + } #endif /*!HAVE_W32_SYSTEM*/ - -#ifdef USE_GNU_PTH - if (!disable_pth) - { -#ifndef HAVE_W32_SYSTEM /* FIXME */ - struct sigaction sa; - - sa.sa_handler = SIG_IGN; - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sigaction (SIGPIPE, &sa, NULL); -#endif - handle_connections (fd, opt.ssh_support ? fd_ssh : -1); - } - else -#endif /*!USE_GNU_PTH*/ - /* setup signals */ - { -#ifndef HAVE_W32_SYSTEM /* FIXME */ - struct sigaction oact, nact; - - nact.sa_handler = cleanup_sh; - sigemptyset (&nact.sa_mask); - nact.sa_flags = 0; - - sigaction (SIGHUP, NULL, &oact); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGHUP, &nact, NULL); - sigaction( SIGTERM, NULL, &oact ); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGTERM, &nact, NULL); - nact.sa_handler = SIG_IGN; - sigaction (SIGPIPE, &nact, NULL); - sigaction (SIGINT, &nact, NULL); -#endif - start_command_handler (fd, -1); - } + handle_connections (fd, opt.ssh_support ? fd_ssh : -1); close (fd); } @@ -1127,7 +1067,7 @@ reread_configuration (void) /* Create a name for the socket. With USE_STANDARD_SOCKET given as - true ising STANDARD_NAME in the home directory or if given has + true using STANDARD_NAME in the home directory or if given has false from the mkdir type name TEMPLATE. In the latter case a unique name in a unique new directory will be created. In both cases check for valid characters as well as against a maximum @@ -1195,7 +1135,7 @@ create_server_socket (int is_standard_name, const char *name) agent_exit (2); } - serv_addr = malloc (sizeof (*serv_addr)); /* FIXME. */ + serv_addr = xmalloc (sizeof (*serv_addr)); memset (serv_addr, 0, sizeof *serv_addr); serv_addr->sun_family = AF_UNIX; assert (strlen (name) + 1 < sizeof (serv_addr->sun_path)); @@ -1325,7 +1265,6 @@ create_directories (void) -#ifdef USE_GNU_PTH /* This is the worker for the ticker. It is called every few seconds and may only do fast operations. */ static void @@ -1581,7 +1520,6 @@ handle_connections (int listen_fd, int listen_fd_ssh) cleanup (); log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); } -#endif /*USE_GNU_PTH*/ /* Figure out whether an agent is available and running. Prints an diff --git a/configure.ac b/configure.ac index dee0a9f09..369762b02 100644 --- a/configure.ac +++ b/configure.ac @@ -541,10 +541,6 @@ fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) -AC_ARG_ENABLE(threads, - AC_HELP_STRING([--disable-threads],[allow building without Pth support]) - ) - dnl Must check for network library requirements before doing link tests dnl for ldap, for example. If ldap libs are static (or dynamic and without @@ -1106,17 +1102,14 @@ fi if test "$missing_pth" = "yes"; then AC_MSG_NOTICE([[ *** -*** It is strongly suggested to build with support for the +*** It is now required to build with support for the *** GNU Portable Threads Library (Pth). Please install this -*** library first or use --disable-threads to allow building -*** anyway. The library is for example available at +*** library first. The library is for example available at *** ftp://ftp.gnu.org/gnu/pth/ *** On a Debian GNU/Linux system you can install it using *** apt-get install libpth-dev ***]]) - if test "$enable_threads" != "no"; then - die=yes - fi + die=yes fi if test "$die" = "yes"; then diff --git a/doc/ChangeLog b/doc/ChangeLog index b1f5e8037..25840a5b1 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-05-17 Werner Koch <wk@g10code.com> + + * gpg-agent.texi (Agent Options): Removed --disable-pth. + 2005-04-27 Werner Koch <wk@g10code.com> * tools.texi (symcryptrun): Added. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 33c8c148c..fa005c3b7 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -253,11 +253,6 @@ should in general not be used to avaoid X-sniffing attacks. 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. - @anchor{option --allow-mark-trusted} @item --allow-mark-trusted @opindex allow-mark-trusted diff --git a/doc/tools.texi b/doc/tools.texi index 805a17e6c..b2463c351 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -722,6 +722,16 @@ directory stated through the environment variable @env{GNUPGHOME} or (on W32 systems) by means on the Registry entry @var{HKCU\Software\GNU\GnuPG:HomeDir}. + +@item -S +@itemx --raw-socket @var{name} +@opindex S +@opindex raw-socket +Connect to socket @var{name} assuming this is an Assuan style server. +Do not run any special initializations or environment checks. This may +be used to directly connect to any Assuan style socket server. + + @end table @c diff --git a/scd/ChangeLog b/scd/ChangeLog index d82e92904..19bba2bf4 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,39 @@ +2005-05-17 Werner Koch <wk@g10code.com> + + * scdaemon.c: Removed non-pth code paths. + (create_socket_name, create_server_socket): New. Taken from + ../agent/gpg-agent. + (cleanup): Changed to adjust for SOCKET_NAME now being malloced. + (ticker_thread): Always use pth_event_occurred; it is again + defined for all decent PTH versions. + (handle_connections): New. Based on the gpg-agent code. + (start_connection_thread): Ditto. + (ticker_thread): Removed. + (cleanup_sh): Removed. + (main): Run the handler for the pipe server in a separate + thread. This replaces the old ticker thread. + (scd_get_socket_name): New. + * command.c (cmd_getinfo): New command GETINFO. + (scd_command_handler): Renamed argument and changed code to use an + already connected FD. + +2005-05-15 Werner Koch <wk@g10code.com> + + * app.c, app-common.h, app-nks.c, app-p15.c, app-dinsig.c + * app-openpgp.c: Change most function return types from int to + gpg_error_t. + * command.c (pin_cb): Ditto. + * sc-copykeys.c (pincb): Ditto. + + * app.c (lock_reader, unlock_reader): New. Changed call handler + wrappers to make use of these functions. + +2005-05-07 Werner Koch <wk@g10code.com> + + * ccid-driver.c (do_close_reader): Don't do a reset before close. + Some folks reported that it makes the SCR335 hang less often. + Look at the source on how to re-enable it. + 2005-04-27 Werner Koch <wk@g10code.com> * app-p15.c (micardo_mse): New. diff --git a/scd/apdu.c b/scd/apdu.c index d23a4adc9..212b9df24 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -20,6 +20,10 @@ * $Id$ */ +/* NOTE: This module is also used by other software, thus the use of + the macro USE_GNU_PTH is mandatory. For GnuPG this macro is + guaranteed to be defined true. */ + #include <config.h> #include <errno.h> #include <stdio.h> diff --git a/scd/app-common.h b/scd/app-common.h index 594f93850..517286c49 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -46,56 +46,56 @@ struct app_ctx_s { struct app_local_s *app_local; /* Local to the application. */ struct { void (*deinit) (app_t app); - int (*learn_status) (app_t app, ctrl_t ctrl); - int (*readcert) (app_t app, const char *certid, + gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl); + gpg_error_t (*readcert) (app_t app, const char *certid, unsigned char **cert, size_t *certlen); - int (*readkey) (app_t app, const char *certid, + gpg_error_t (*readkey) (app_t app, const char *certid, unsigned char **pk, size_t *pklen); - int (*getattr) (app_t app, ctrl_t ctrl, const char *name); - int (*setattr) (app_t app, const char *name, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*getattr) (app_t app, ctrl_t ctrl, const char *name); + gpg_error_t (*setattr) (app_t app, const char *name, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen); - int (*sign) (app_t app, + gpg_error_t (*sign) (app_t app, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); - int (*auth) (app_t app, const char *keyidstr, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*auth) (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); - int (*decipher) (app_t app, const char *keyidstr, - int (pincb)(void*, const char *, char **), + gpg_error_t (*decipher) (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); - int (*genkey) (app_t app, ctrl_t ctrl, + gpg_error_t (*genkey) (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); - int (*change_pin) (app_t app, ctrl_t ctrl, + gpg_error_t (*change_pin) (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); - int (*check_pin) (app_t app, const char *keyidstr, - int (pincb)(void*, const char *, char **), + gpg_error_t (*check_pin) (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); } fnc; }; #if GNUPG_MAJOR_VERSION == 1 -int app_select_openpgp (app_t app); -int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); -int app_openpgp_storekey (app_t app, int keyno, +gpg_error_t app_select_openpgp (app_t app); +gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); +gpg_error_t app_openpgp_storekey (app_t app, int keyno, unsigned char *template, size_t template_len, time_t created_at, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); #else /*-- app-help.c --*/ @@ -107,72 +107,73 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app); void release_application (app_t app); -int app_munge_serialno (app_t app); -int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); -int app_write_learn_status (app_t app, ctrl_t ctrl); -int app_readcert (app_t app, const char *certid, +gpg_error_t app_munge_serialno (app_t app); +gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp); +gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl); +gpg_error_t app_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen); -int app_readkey (app_t app, const char *keyid, +gpg_error_t app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen); -int app_getattr (app_t app, ctrl_t ctrl, const char *name); -int app_setattr (app_t app, const char *name, - int (*pincb)(void*, const char *, char **), +gpg_error_t app_getattr (app_t app, ctrl_t ctrl, const char *name); +gpg_error_t app_setattr (app_t app, const char *name, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen); -int app_sign (app_t app, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), +gpg_error_t app_sign (app_t app, const char *keyidstr, int hashalgo, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); -int app_auth (app_t app, const char *keyidstr, - int (*pincb)(void*, const char *, char **), +gpg_error_t app_auth (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); -int app_decipher (app_t app, const char *keyidstr, - int (pincb)(void*, const char *, char **), +gpg_error_t app_decipher (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); -int app_genkey (app_t app, ctrl_t ctrl, +gpg_error_t app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); -int app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer); -int app_change_pin (app_t app, ctrl_t ctrl, +gpg_error_t app_get_challenge (app_t app, size_t nbytes, + unsigned char *buffer); +gpg_error_t app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); -int app_check_pin (app_t app, const char *keyidstr, - int (*pincb)(void*, const char *, char **), +gpg_error_t app_check_pin (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); /*-- app-openpgp.c --*/ -int app_select_openpgp (app_t app); +gpg_error_t app_select_openpgp (app_t app); -int app_openpgp_cardinfo (app_t app, +gpg_error_t app_openpgp_cardinfo (app_t app, char **serialno, char **disp_name, char **pubkey_url, unsigned char **fpr1, unsigned char **fpr2, unsigned char **fpr3); -int app_openpgp_storekey (app_t app, int keyno, +gpg_error_t app_openpgp_storekey (app_t app, int keyno, unsigned char *template, size_t template_len, time_t created_at, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg); -int app_openpgp_readkey (app_t app, int keyno, +gpg_error_t app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen, unsigned char **e, size_t *elen); /*-- app-nks.c --*/ -int app_select_nks (app_t app); +gpg_error_t app_select_nks (app_t app); /*-- app-dinsig.c --*/ -int app_select_dinsig (app_t app); +gpg_error_t app_select_dinsig (app_t app); /*-- app-p15.c --*/ gpg_error_t app_select_p15 (app_t app); diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 38fbc79ee..28b70c466 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -85,7 +85,7 @@ #include "tlv.h" -static int +static gpg_error_t do_learn_status (app_t app, ctrl_t ctrl) { gpg_error_t err; @@ -162,7 +162,7 @@ do_learn_status (app_t app, ctrl_t ctrl) FIXME: This needs some cleanups and caching with do_learn_status. */ -static int +static gpg_error_t do_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen) { @@ -273,9 +273,9 @@ do_readcert (app_t app, const char *certid, /* Verify the PIN if required. */ -static int +static gpg_error_t verify_pin (app_t app, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { if (!app->did_chv1 || app->force_chv1 ) @@ -326,12 +326,12 @@ verify_pin (app_t app, If a PIN is required the PINCB will be used to ask for the PIN; that callback should return the PIN in an allocated buffer and store that in the 3rd argument. */ -static int +static gpg_error_t do_sign (app_t app, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - unsigned char **outdata, size_t *outdatalen ) + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) { static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, @@ -397,7 +397,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, /* Select the DINSIG application on the card in SLOT. This function must be used before any other DINSIG application functions. */ -int +gpg_error_t app_select_dinsig (APP app) { static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 }; diff --git a/scd/app-nks.c b/scd/app-nks.c index f14b67972..b6a3037ed 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -117,7 +117,7 @@ keygripstr_from_pk_file (int slot, int fid, char *r_gripstr) -static int +static gpg_error_t do_learn_status (APP app, CTRL ctrl) { gpg_error_t err; @@ -175,7 +175,7 @@ do_learn_status (APP app, CTRL ctrl) the CERTINFO status lines) and return it in the freshly allocated buffer put into CERT and the length of the certificate put into CERTLEN. */ -static int +static gpg_error_t do_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen) { @@ -299,9 +299,9 @@ do_readcert (app_t app, const char *certid, /* Verify the PIN if required. */ -static int +static gpg_error_t verify_pin (app_t app, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { /* Note that force_chv1 is never set but we do it here anyway so @@ -357,12 +357,12 @@ verify_pin (app_t app, If a PIN is required the PINCB will be used to ask for the PIN; that callback should return the PIN in an allocated buffer and store that in the 3rd argument. */ -static int +static gpg_error_t do_sign (app_t app, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - unsigned char **outdata, size_t *outdatalen ) + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) { static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, @@ -435,9 +435,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, /* Decrypt the data in INDATA and return the allocated result in OUTDATA. If a PIN is required the PINCB will be used to ask for the PIN; it should return the PIN in an allocated buffer and put it into PIN. */ -static int +static gpg_error_t do_decipher (app_t app, const char *keyidstr, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) @@ -485,7 +485,7 @@ do_decipher (app_t app, const char *keyidstr, /* Select the NKS 2.0 application on the card in SLOT. */ -int +gpg_error_t app_select_nks (APP app) { static char const aid[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 }; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index ca0e2501b..b8060df03 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -547,7 +547,7 @@ parse_login_data (app_t app) } /* Note, that FPR must be at least 20 bytes. */ -static int +static gpg_error_t store_fpr (int slot, int keynumber, u32 timestamp, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, @@ -671,7 +671,7 @@ send_key_data (ctrl_t ctrl, const char *name, /* Implement the GETATTR command. This is similar to the LEARN command but returns just one value via the status interface. */ -static int +static gpg_error_t do_getattr (app_t app, ctrl_t ctrl, const char *name) { static struct { @@ -1168,7 +1168,7 @@ send_keypair_info (app_t app, ctrl_t ctrl, int keyno) /* Handle the LEARN command for OpenPGP. */ -static int +static gpg_error_t do_learn_status (app_t app, ctrl_t ctrl) { do_getattr (app, ctrl, "EXTCAP"); @@ -1204,7 +1204,7 @@ do_learn_status (app_t app, ctrl_t ctrl) its length (for assertions) at PKLEN; the caller must release that buffer. On error PK and PKLEN are not changed and an error code is returned. */ -static int +static gpg_error_t do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) { gpg_error_t err; @@ -1236,9 +1236,9 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) /* Verify CHV2 if required. Depending on the configuration of the card CHV1 will also be verified. */ -static int +static gpg_error_t verify_chv2 (app_t app, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { int rc = 0; @@ -1292,9 +1292,9 @@ verify_chv2 (app_t app, } /* Verify CHV3 if required. */ -static int +static gpg_error_t verify_chv3 (app_t app, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { int rc = 0; @@ -1366,9 +1366,9 @@ verify_chv3 (app_t app, /* Handle the SETATTR operation. All arguments are already basically checked. */ -static int +static gpg_error_t do_setattr (app_t app, const char *name, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen) { @@ -1434,9 +1434,9 @@ do_setattr (app_t app, const char *name, /* Handle the PASSWD command. */ -static int +static gpg_error_t do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { int rc = 0; @@ -1525,9 +1525,9 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, /* Handle the GENKEY command. */ -static int +static gpg_error_t do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { int rc; @@ -1691,7 +1691,7 @@ get_sig_counter (app_t app) return ul; } -static int +static gpg_error_t compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr) { const unsigned char *fpr; @@ -1731,7 +1731,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr) the key on the card has been replaced but the shadow information known to gpg was not updated. If there is no fingerprint we assume that this is okay. */ -static int +static gpg_error_t check_against_given_fingerprint (app_t app, const char *fpr, int keyno) { unsigned char tmp[20]; @@ -1762,9 +1762,9 @@ check_against_given_fingerprint (app_t app, const char *fpr, int keyno) GPG_ERR_WRONG_CARD to indicate that the card currently present does not match the one required for the requested action (e.g. the serial number does not match). */ -static int +static gpg_error_t do_sign (app_t app, const char *keyidstr, int hashalgo, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) @@ -1911,9 +1911,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, GPG_ERR_WRONG_CARD to indicate that the card currently present does not match the one required for the requested action (e.g. the serial number does not match). */ -static int +static gpg_error_t do_auth (app_t app, const char *keyidstr, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) @@ -1974,9 +1974,9 @@ do_auth (app_t app, const char *keyidstr, } -static int +static gpg_error_t do_decipher (app_t app, const char *keyidstr, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) @@ -2040,9 +2040,9 @@ do_decipher (app_t app, const char *keyidstr, There is a special mode if the keyidstr is "<serialno>[CHV3]" with the "[CHV3]" being a literal string: The Admin Pin is checked if and only if the retry counter is still at 3. */ -static int +static gpg_error_t do_check_pin (app_t app, const char *keyidstr, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { unsigned char tmp_sn[20]; @@ -2124,7 +2124,7 @@ do_check_pin (app_t app, const char *keyidstr, /* Select the OpenPGP application on the card in SLOT. This function must be used before any other OpenPGP application functions. */ -int +gpg_error_t app_select_openpgp (app_t app) { static char const aid[] = { 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01 }; @@ -2237,7 +2237,7 @@ leave: LEARN command returns. All parameters return allocated strings or buffers or NULL if the data object is not available. All returned values are sanitized. */ -int +gpg_error_t app_openpgp_cardinfo (app_t app, char **serialno, char **disp_name, @@ -2327,13 +2327,13 @@ app_openpgp_cardinfo (app_t app, create the fingerprint. M, MLEN is the RSA modulus and E, ELEN the RSA public exponent. This function silently overwrites an existing key.*/ -int +gpg_error_t app_openpgp_storekey (app_t app, int keyno, unsigned char *template, size_t template_len, time_t created_at, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, - int (*pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { int rc; @@ -2377,7 +2377,7 @@ app_openpgp_storekey (app_t app, int keyno, /* Utility function for external tools: Read the public RSA key at KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */ -int +gpg_error_t app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen, unsigned char **e, size_t *elen) { diff --git a/scd/app-p15.c b/scd/app-p15.c index d2ed15a59..831f0d1f4 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -2366,7 +2366,7 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo) /* This is the handler for the LEARN command. */ -static int /* FIXME: change this to gpg_error_t */ +static gpg_error_t do_learn_status (app_t app, ctrl_t ctrl) { gpg_error_t err; @@ -2513,7 +2513,7 @@ readcert_by_cdf (app_t app, cdf_object_t cdf, buffer to be stored at R_CERT and its length at R_CERTLEN. A error code will be returned on failure and R_CERT and R_CERTLEN will be set to NULL/0. */ -static int /* FIXME: change this to gpg_error_t */ +static gpg_error_t do_readcert (app_t app, const char *certid, unsigned char **r_cert, size_t *r_certlen) { @@ -2629,9 +2629,9 @@ micardo_mse (app_t app, unsigned short fid) If a PIN is required, the PINCB will be used to ask for the PIN; that callback should return the PIN in an allocated buffer and store that as the 3rd argument. */ -static int +static gpg_error_t do_sign (app_t app, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) diff --git a/scd/app.c b/scd/app.c index 8e95ef7ef..0a1960267 100644 --- a/scd/app.c +++ b/scd/app.c @@ -23,7 +23,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> - +# include <pth.h> #include "scdaemon.h" #include "app-common.h" @@ -31,7 +31,72 @@ #include "iso7816.h" #include "tlv.h" +/* This table is used to keep track of locks on a per reader base. + The index into the table is the slot number of the reader. The + mutex will be initialized on demand (one of the advantages of a + userland threading system). */ +static struct +{ + int initialized; + pth_mutex_t lock; +} lock_table[10]; + + +/* Lock the reader associated with the APP context. This function + shall be used right before calling any of the actual application + functions to serialize access to the reader. We do this always + even if the reader is not actually used. This allows an actual + application to assume that it never shares a reader (while + performing one command). Returns 0 on success; only then the + unlock_reader function must be called after returning from the + handler. */ +static gpg_error_t +lock_reader (app_t app) +{ + gpg_error_t err; + int slot = app->slot; + + if (slot < 0 || slot >= DIM (lock_table)) + return gpg_error (app->slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT); + + if (!lock_table[slot].initialized) + { + if (!pth_mutex_init (&lock_table[slot].lock)) + { + err = gpg_error_from_errno (errno); + log_error ("error initializing mutex: %s\n", strerror (errno)); + return err; + } + lock_table[slot].initialized = 1; + } + + if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL)) + { + err = gpg_error_from_errno (errno); + log_error ("failed to acquire APP lock for slot %d: %s\n", + slot, strerror (errno)); + return err; + } + + return 0; +} + +/* Release a lock on the reader. See lock_reader(). */ +static void +unlock_reader (app_t app) +{ + int slot = app->slot; + + if (slot < 0 || slot >= DIM (lock_table) + || !lock_table[slot].initialized) + log_bug ("unlock_reader called for invalid slot %d\n", slot); + if (!pth_mutex_release (&lock_table[slot].lock)) + log_error ("failed to release APP lock for slot %d: %s\n", + slot, strerror (errno)); + +} + /* Check wether the application NAME is allowed. This does not mean we have support for it though. */ static int @@ -54,7 +119,7 @@ is_app_allowed (const char *name) gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) { - int rc; + gpg_error_t err; app_t app; unsigned char *result = NULL; size_t resultlen; @@ -63,22 +128,26 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) app = xtrycalloc (1, sizeof *app); if (!app) { - rc = gpg_error_from_errno (errno); - log_info ("error allocating context: %s\n", gpg_strerror (rc)); - return rc; + err = gpg_error_from_errno (errno); + log_info ("error allocating context: %s\n", gpg_strerror (err)); + return err; } app->slot = slot; + err = lock_reader (app); + if (err) + return err; + /* Fixme: We should now first check whether a card is at all present. */ /* Try to read the GDO file first to get a default serial number. */ - rc = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL); - if (!rc) - rc = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL); - if (!rc) - rc = iso7816_read_binary (slot, 0, 0, &result, &resultlen); - if (!rc) + err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL); + if (!err) + err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL); + if (!err) + err = iso7816_read_binary (slot, 0, 0, &result, &resultlen); + if (!err) { size_t n; const unsigned char *p; @@ -104,8 +173,8 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) memmove (result, p, n); app->serialno = result; app->serialnolen = n; - rc = app_munge_serialno (app); - if (rc) + err = app_munge_serialno (app); + if (err) goto leave; } else @@ -114,38 +183,40 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) } /* For certain error codes, there is no need to try more. */ - if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT) + if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT) goto leave; /* Figure out the application to use. */ - rc = gpg_error (GPG_ERR_NOT_FOUND); - - if (rc && is_app_allowed ("openpgp") && (!name || !strcmp (name, "openpgp"))) - rc = app_select_openpgp (app); - if (rc && is_app_allowed ("nks") && (!name || !strcmp (name, "nks"))) - rc = app_select_nks (app); - if (rc && is_app_allowed ("p15") && (!name || !strcmp (name, "p15"))) - rc = app_select_p15 (app); - if (rc && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) - rc = app_select_dinsig (app); - if (rc && name) - rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + err = gpg_error (GPG_ERR_NOT_FOUND); + + if (err && is_app_allowed ("openpgp") + && (!name || !strcmp (name, "openpgp"))) + err = app_select_openpgp (app); + if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks"))) + err = app_select_nks (app); + if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15"))) + err = app_select_p15 (app); + if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig"))) + err = app_select_dinsig (app); + if (err && name) + err = gpg_error (GPG_ERR_NOT_SUPPORTED); leave: - if (rc) + if (err) { if (name) log_info ("can't select application `%s': %s\n", - name, gpg_strerror (rc)); + name, gpg_strerror (err)); else log_info ("no supported card application found: %s\n", - gpg_strerror (rc)); + gpg_strerror (err)); xfree (app); - return rc; + return err; } app->initialized = 1; + unlock_reader (app); *r_app = app; return 0; } @@ -181,7 +252,7 @@ release_application (app_t app) All other serial number not starting with FF are used as they are. */ -int +gpg_error_t app_munge_serialno (app_t app) { if (app->serialnolen && app->serialno[0] == 0xff) @@ -208,7 +279,7 @@ app_munge_serialno (app_t app) no update time is available the returned value is 0. Caller must free SERIAL unless the function returns an error. If STAMP is not of interest, NULL may be passed. */ -int +gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp) { unsigned char *buf, *p; @@ -234,9 +305,11 @@ app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp) /* Write out the application specifig status lines for the LEARN command. */ -int -app_write_learn_status (APP app, CTRL ctrl) +gpg_error_t +app_write_learn_status (app_t app, CTRL ctrl) { + gpg_error_t err; + if (!app) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) @@ -247,8 +320,12 @@ app_write_learn_status (APP app, CTRL ctrl) if (app->apptype) send_status_info (ctrl, "APPTYPE", app->apptype, strlen (app->apptype), NULL, 0); - - return app->fnc.learn_status (app, ctrl); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.learn_status (app, ctrl); + unlock_reader (app); + return err; } @@ -256,18 +333,24 @@ app_write_learn_status (APP app, CTRL ctrl) the CERTINFO status lines) and return it in the freshly allocated buffer put into CERT and the length of the certificate put into CERTLEN. */ -int +gpg_error_t app_readcert (app_t app, const char *certid, unsigned char **cert, size_t *certlen) { + gpg_error_t err; + if (!app) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.readcert) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - - return app->fnc.readcert (app, certid, cert, certlen); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.readcert (app, certid, cert, certlen); + unlock_reader (app); + return err; } @@ -278,9 +361,11 @@ app_readcert (app_t app, const char *certid, code returned. This function might not be supported by all applications. */ -int +gpg_error_t app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) { + gpg_error_t err; + if (pk) *pk = NULL; if (pklen) @@ -292,15 +377,21 @@ app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.readkey) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - - return app->fnc.readkey (app, keyid, pk, pklen); + err = lock_reader (app); + if (err) + return err; + err= app->fnc.readkey (app, keyid, pk, pklen); + unlock_reader (app); + return err; } /* Perform a GETATTR operation. */ -int -app_getattr (APP app, CTRL ctrl, const char *name) +gpg_error_t +app_getattr (app_t app, CTRL ctrl, const char *name) { + gpg_error_t err; + if (!app || !name || !*name) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) @@ -328,36 +419,48 @@ app_getattr (APP app, CTRL ctrl, const char *name) if (!app->fnc.getattr) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - return app->fnc.getattr (app, ctrl, name); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.getattr (app, ctrl, name); + unlock_reader (app); + return err; } /* Perform a SETATTR operation. */ -int -app_setattr (APP app, const char *name, - int (*pincb)(void*, const char *, char **), +gpg_error_t +app_setattr (app_t app, const char *name, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const unsigned char *value, size_t valuelen) { + gpg_error_t err; + if (!app || !name || !*name || !value) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.setattr) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - return app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen); + unlock_reader (app); + return err; } /* Create the signature and return the allocated result in OUTDATA. If a PIN is required the PINCB will be used to ask for the PIN; it should return the PIN in an allocated buffer and put it into PIN. */ -int -app_sign (APP app, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), +gpg_error_t +app_sign (app_t app, const char *keyidstr, int hashalgo, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) { - int rc; + gpg_error_t err; if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb) return gpg_error (GPG_ERR_INV_VALUE); @@ -365,27 +468,31 @@ app_sign (APP app, const char *keyidstr, int hashalgo, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.sign) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - rc = app->fnc.sign (app, keyidstr, hashalgo, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.sign (app, keyidstr, hashalgo, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + unlock_reader (app); if (opt.verbose) - log_info ("operation sign result: %s\n", gpg_strerror (rc)); - return rc; + log_info ("operation sign result: %s\n", gpg_strerror (err)); + return err; } /* Create the signature using the INTERNAL AUTHENTICATE command and return the allocated result in OUTDATA. If a PIN is required the PINCB will be used to ask for the PIN; it should return the PIN in an allocated buffer and put it into PIN. */ -int -app_auth (APP app, const char *keyidstr, - int (pincb)(void*, const char *, char **), +gpg_error_t +app_auth (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) { - int rc; + gpg_error_t err; if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb) return gpg_error (GPG_ERR_INV_VALUE); @@ -393,27 +500,31 @@ app_auth (APP app, const char *keyidstr, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.auth) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - rc = app->fnc.auth (app, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.auth (app, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + unlock_reader (app); if (opt.verbose) - log_info ("operation auth result: %s\n", gpg_strerror (rc)); - return rc; + log_info ("operation auth result: %s\n", gpg_strerror (err)); + return err; } /* Decrypt the data in INDATA and return the allocated result in OUTDATA. If a PIN is required the PINCB will be used to ask for the PIN; it should return the PIN in an allocated buffer and put it into PIN. */ -int -app_decipher (APP app, const char *keyidstr, - int (pincb)(void*, const char *, char **), +gpg_error_t +app_decipher (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ) { - int rc; + gpg_error_t err; if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb) return gpg_error (GPG_ERR_INV_VALUE); @@ -421,23 +532,27 @@ app_decipher (APP app, const char *keyidstr, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.decipher) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - rc = app->fnc.decipher (app, keyidstr, - pincb, pincb_arg, - indata, indatalen, - outdata, outdatalen); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.decipher (app, keyidstr, + pincb, pincb_arg, + indata, indatalen, + outdata, outdatalen); + unlock_reader (app); if (opt.verbose) - log_info ("operation decipher result: %s\n", gpg_strerror (rc)); - return rc; + log_info ("operation decipher result: %s\n", gpg_strerror (err)); + return err; } /* Perform a SETATTR operation. */ -int -app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, - int (*pincb)(void*, const char *, char **), +gpg_error_t +app_genkey (app_t app, CTRL ctrl, const char *keynostr, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { - int rc; + gpg_error_t err; if (!app || !keynostr || !*keynostr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); @@ -445,35 +560,46 @@ app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.genkey) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - rc = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg); + unlock_reader (app); if (opt.verbose) - log_info ("operation genkey result: %s\n", gpg_strerror (rc)); - return rc; + log_info ("operation genkey result: %s\n", gpg_strerror (err)); + return err; } /* Perform a GET CHALLENGE operation. This fucntion is special as it directly accesses the card without any application specific wrapper. */ -int -app_get_challenge (APP app, size_t nbytes, unsigned char *buffer) +gpg_error_t +app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer) { + gpg_error_t err; + if (!app || !nbytes || !buffer) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - return iso7816_get_challenge (app->slot, nbytes, buffer); + err = lock_reader (app); + if (err) + return err; + err = iso7816_get_challenge (app->slot, nbytes, buffer); + unlock_reader (app); + return err; } /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */ -int -app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, - int (*pincb)(void*, const char *, char **), +gpg_error_t +app_change_pin (app_t app, CTRL ctrl, const char *chvnostr, int reset_mode, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { - int rc; + gpg_error_t err; if (!app || !chvnostr || !*chvnostr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); @@ -481,22 +607,27 @@ app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.change_pin) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - rc = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, + pincb, pincb_arg); + unlock_reader (app); if (opt.verbose) - log_info ("operation change_pin result: %s\n", gpg_strerror (rc)); - return rc; + log_info ("operation change_pin result: %s\n", gpg_strerror (err)); + return err; } /* Perform a VERIFY operation without doing anything lese. This may be used to initialze a the PIN cache for long lasting other operations. Its use is highly application dependent. */ -int -app_check_pin (APP app, const char *keyidstr, - int (*pincb)(void*, const char *, char **), +gpg_error_t +app_check_pin (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), void *pincb_arg) { - int rc; + gpg_error_t err; if (!app || !keyidstr || !*keyidstr || !pincb) return gpg_error (GPG_ERR_INV_VALUE); @@ -504,9 +635,13 @@ app_check_pin (APP app, const char *keyidstr, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.check_pin) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - rc = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg); + unlock_reader (app); if (opt.verbose) - log_info ("operation check_pin result: %s\n", gpg_strerror (rc)); - return rc; + log_info ("operation check_pin result: %s\n", gpg_strerror (err)); + return err; } diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index e9666ee17..b817452b1 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -986,7 +986,8 @@ do_close_reader (ccid_driver_t handle) } if (handle->idev) { - usb_reset (handle->idev); + if (getenv ("GNUPG_CCID_DRIVER_RESET_BEFORE_CLOSE")) + usb_reset (handle->idev); usb_release_interface (handle->idev, handle->ifc_no); usb_close (handle->idev); handle->idev = NULL; @@ -1274,7 +1275,7 @@ ccid_poll (ccid_driver_t handle) } -/* Note that this function won't return the error codes NO_CARD or +/* Note that this fucntion won't return the error codes NO_CARD or CARD_INACTIVE */ int ccid_slot_status (ccid_driver_t handle, int *statusbits) @@ -1303,12 +1304,12 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) { if (!retries) { - fprintf (stderr, "CALLING USB_CLEAR_HALT\n"); + DEBUGOUT ("USB: CALLING USB_CLEAR_HALT\n"); usb_clear_halt (handle->idev, handle->ep_bulk_in); usb_clear_halt (handle->idev, handle->ep_bulk_out); } else - fprintf (stderr, "RETRYING AGIAN\n"); + DEBUGOUT ("USB: RETRYING bulk_in AGAIN\n"); retries++; goto retry; } diff --git a/scd/command.c b/scd/command.c index c8eebaac0..5ea3e01db 100644 --- a/scd/command.c +++ b/scd/command.c @@ -122,7 +122,7 @@ has_option (const char *line, const char *name) /* Reset the card and free the application context. With DO_CLOSE set - to true and this is the last session with a reference to teh + to true and this is the last session with a reference to the reader, close the reader and don't do just a reset. */ static void do_reset (ctrl_t ctrl, int do_close) @@ -647,7 +647,7 @@ cmd_setdata (assuan_context_t ctx, char *line) -static int +static gpg_error_t pin_cb (void *opaque, const char *info, char **retstr) { assuan_context_t ctx = opaque; @@ -1171,6 +1171,34 @@ cmd_unlock (assuan_context_t ctx, char *line) } +/* GETINFO <what> + + Multi purpose command to return certain information. + Supported values of WHAT are: + + socket_name - Return the name of the socket. + +*/ + +static int +cmd_getinfo (assuan_context_t ctx, char *line) +{ + int rc = 0; + + if (!strcmp (line, "socket_name")) + { + const char *s = scd_get_socket_name (); + + if (s) + rc = assuan_send_data (ctx, s, strlen (s)); + else + rc = gpg_error (GPG_ERR_NO_DATA); + } + else + rc = set_error (Parameter_Error, "unknown value for WHAT"); + return rc; +} + @@ -1200,6 +1228,7 @@ register_commands (assuan_context_t ctx) { "CHECKPIN", cmd_checkpin }, { "LOCK", cmd_lock }, { "UNLOCK", cmd_unlock }, + { "GETINFO", cmd_getinfo }, { NULL } }; int i, rc; @@ -1218,10 +1247,10 @@ register_commands (assuan_context_t ctx) } -/* Startup the server. If LISTEN_FD is given as -1, this is simple - piper server, otherwise it is a regular server */ +/* Startup the server. If FD is given as -1 this is simple pipe + server, otherwise it is a regular server. */ void -scd_command_handler (int listen_fd) +scd_command_handler (int fd) { int rc; assuan_context_t ctx; @@ -1230,7 +1259,7 @@ scd_command_handler (int listen_fd) memset (&ctrl, 0, sizeof ctrl); scd_init_default_ctrl (&ctrl); - if (listen_fd == -1) + if (fd == -1) { int filedes[2]; @@ -1240,7 +1269,7 @@ scd_command_handler (int listen_fd) } else { - rc = assuan_init_socket_server (&ctx, listen_fd); + rc = assuan_init_connected_socket_server (&ctx, fd); } if (rc) { diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c index 78cb2acc8..66b6894e0 100644 --- a/scd/sc-copykeys.c +++ b/scd/sc-copykeys.c @@ -483,7 +483,7 @@ query_card (APP app) /* Callback function to ask for a PIN. */ -static int +static gpg_error_t pincb (void *arg, const char *prompt, char **pinvalue) { char *pin = xstrdup ("12345678"); diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 7b0f31cdb..9a8b31ac5 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -1,5 +1,5 @@ /* scdaemon.c - The GnuPG Smartcard Daemon - * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -35,9 +35,7 @@ #endif /*HAVE_W32_SYSTEM*/ #include <unistd.h> #include <signal.h> -#ifdef USE_GNU_PTH -# include <pth.h> -#endif +#include <pth.h> #define JNLIB_NEED_LOG_LOGV #include "scdaemon.h" @@ -76,6 +74,7 @@ enum cmd_and_opt_values oNoGrab, oLogFile, oServer, + oMultiServer, oDaemon, oBatch, oReaderPort, @@ -110,6 +109,8 @@ static ARGPARSE_OPTS opts[] = { { oDebugWait,"debug-wait",1, "@"}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, + { oMultiServer, "multi-server", 0, + N_("allow additional connections in server mode")}, { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, { octapiDriver, "ctapi-driver", 2, N_("|NAME|use NAME as ct-API driver")}, { opcscDriver, "pcsc-driver", 2, N_("|NAME|use NAME as PC/SC driver")}, @@ -140,8 +141,6 @@ static ARGPARSE_OPTS opts[] = { #endif -static volatile int caught_fatal_sig = 0; - /* Flag to indicate that a shutdown was requested. */ static int shutdown_pending; @@ -149,16 +148,21 @@ static int shutdown_pending; static int maybe_setuid = 1; /* Name of the communication socket */ -static char socket_name[128]; +static char *socket_name; + + +static char *create_socket_name (int use_standard_socket, + char *standard_name, char *template); +static int create_server_socket (int is_standard_name, const char *name); +static void *start_connection_thread (void *arg); +static void handle_connections (int listen_fd); -#ifdef USE_GNU_PTH /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; -static void *ticker_thread (void *arg); -#endif /*USE_GNU_PTH*/ + static const char * my_strusage (int level) { @@ -265,7 +269,7 @@ set_debug (const char *level) static void cleanup (void) { - if (*socket_name) + if (socket_name && *socket_name) { char *p; @@ -282,27 +286,6 @@ cleanup (void) } -static RETSIGTYPE -cleanup_sh (int sig) -{ - if (caught_fatal_sig) - raise (sig); - caught_fatal_sig = 1; - - /* gcry_control( GCRYCTL_TERM_SECMEM );*/ - cleanup (); - -#ifndef HAVE_DOSISH_SYSTEM - { /* reset action to default action and raise signal again */ - struct sigaction nact; - nact.sa_handler = SIG_DFL; - sigemptyset( &nact.sa_mask ); - nact.sa_flags = 0; - sigaction( sig, &nact, NULL); - } -#endif - raise( sig ); -} int main (int argc, char **argv ) @@ -322,6 +305,7 @@ main (int argc, char **argv ) int greeting = 0; int nogreeting = 0; int pipe_server = 0; + int multi_server = 0; int is_daemon = 0; int nodetach = 0; int csh_style = 0; @@ -343,14 +327,12 @@ main (int argc, char **argv ) /* Libgcrypt requires us to register the threading model first. Note that this will also do the pth_init. */ -#ifdef USE_GNU_PTH err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); if (err) { log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", gpg_strerror (err)); } -#endif /*USE_GNU_PTH*/ /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ @@ -481,6 +463,7 @@ main (int argc, char **argv ) case oCsh: csh_style = 1; break; case oSh: csh_style = 0; break; case oServer: pipe_server = 1; break; + case oMultiServer: multi_server = 1; break; case oDaemon: is_daemon = 1; break; case oReaderPort: opt.reader_port = pargs.r.ret_str; break; @@ -598,24 +581,49 @@ main (int argc, char **argv ) log_set_prefix (NULL, 1|2|4); } - if (pipe_server) - { /* This is the simple pipe based server */ -#ifdef USE_GNU_PTH + { + /* This is the simple pipe based server */ pth_attr_t tattr; - + int fd = -1; + + { + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGPIPE, &sa, NULL); + } + + /* In multi server mode we need to listen on an additional + socket. Create that socket now before starting the handler + for the pipe connection. This allows that handler to send + back the name of that socket. */ + if (multi_server) + { + socket_name = create_socket_name (0, + "S.scdaemon", + "/tmp/gpg-XXXXXX/S.scdaemon"); + + fd = create_server_socket (0, socket_name); + } + tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); - pth_attr_set (tattr, PTH_ATTR_NAME, "ticker"); + pth_attr_set (tattr, PTH_ATTR_NAME, "pipe-connection"); - if (!pth_spawn (tattr, ticker_thread, NULL)) + if (!pth_spawn (tattr, start_connection_thread, (void*)(-1))) { - log_error ("error spawning ticker thread: %s\n", strerror (errno)); + log_error ("error spawning pipe connection handler: %s\n", + strerror (errno) ); scd_exit (2); } -#endif /*USE_GNU_PTH*/ - scd_command_handler (-1); + + handle_connections (fd); + if (fd != -1) + close (fd); } else if (!is_daemon) { @@ -623,87 +631,17 @@ main (int argc, char **argv ) " to run the program in the background\n")); } else - { /* regular server mode */ + { /* Regular server mode */ int fd; pid_t pid; int i; - int len; - struct sockaddr_un serv_addr; - char *p; - - /* fixme: if there is already a running gpg-agent we should - share the same directory - and vice versa */ - *socket_name = 0; - snprintf (socket_name, DIM(socket_name)-1, - "/tmp/gpg-XXXXXX/S.scdaemon"); - socket_name[DIM(socket_name)-1] = 0; - p = strrchr (socket_name, '/'); - if (!p) - BUG (); - *p = 0;; - -#ifndef HAVE_W32_SYSTEM - if (!mkdtemp(socket_name)) - { - log_error ("can't create directory `%s': %s\n", - socket_name, strerror(errno) ); - exit (1); - } -#endif - *p = '/'; - - if (strchr (socket_name, ':') ) - { - log_error ("colons are not allowed in the socket name\n"); - exit (1); - } - if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) - { - log_error ("name of socket to long\n"); - exit (1); - } - - -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) - { - log_error ("can't create socket: %s\n", strerror(errno) ); - exit (1); - } - - memset (&serv_addr, 0, sizeof serv_addr); - serv_addr.sun_family = AF_UNIX; - strcpy (serv_addr.sun_path, socket_name); - len = (offsetof (struct sockaddr_un, sun_path) - + strlen(serv_addr.sun_path) + 1); - if ( -#ifdef HAVE_W32_SYSTEM - _w32_sock_bind -#else - bind -#endif - (fd, (struct sockaddr*)&serv_addr, len) == -1) - { - log_error ("error binding socket to `%s': %s\n", - serv_addr.sun_path, strerror (errno) ); - close (fd); - exit (1); - } - - if (listen (fd, 5 ) == -1) - { - log_error ("listen() failed: %s\n", strerror (errno)); - close (fd); - exit (1); - } + /* Create the socket. */ + socket_name = create_socket_name (0, + "S.scdaemon", + "/tmp/gpg-XXXXXX/S.scdaemon"); - if (opt.verbose) - log_info ("listening on socket `%s'\n", socket_name ); + fd = create_server_socket (0, socket_name); fflush (NULL); @@ -746,7 +684,7 @@ main (int argc, char **argv ) } else { - /* print the environment string, so that the caller can use + /* Print the environment string, so that the caller can use shell's eval to set it */ if (csh_style) { @@ -763,14 +701,15 @@ main (int argc, char **argv ) /* NOTREACHED */ } /* end parent */ - /* this is the child */ + /* This is the child. */ - /* detach from tty and put process into a new session */ + /* Detach from tty and put process into a new session. */ if (!nodetach ) - { /* close stdin, stdout and stderr unless it is the log stream */ + { + /* Close stdin, stdout and stderr unless it is the log stream. */ for (i=0; i <= 2; i++) { - if ( log_get_fd () != i) + if ( log_test_fd (i) && i != fd) close (i); } if (setsid() == -1) @@ -781,23 +720,13 @@ main (int argc, char **argv ) } } - /* setup signals */ { - struct sigaction oact, nact; + struct sigaction sa; - nact.sa_handler = cleanup_sh; - sigemptyset (&nact.sa_mask); - nact.sa_flags = 0; - - sigaction (SIGHUP, NULL, &oact); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGHUP, &nact, NULL); - sigaction( SIGTERM, NULL, &oact ); - if (oact.sa_handler != SIG_IGN) - sigaction (SIGTERM, &nact, NULL); - nact.sa_handler = SIG_IGN; - sigaction (SIGPIPE, &nact, NULL); - sigaction (SIGINT, &nact, NULL); + sa.sa_handler = SIG_IGN; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGPIPE, &sa, NULL); } if (chdir("/")) @@ -808,7 +737,7 @@ main (int argc, char **argv ) #endif /*!HAVE_W32_SYSTEM*/ - scd_command_handler (fd); + handle_connections (fd); close (fd); } @@ -840,13 +769,22 @@ scd_exit (int rc) void -scd_init_default_ctrl (CTRL ctrl) +scd_init_default_ctrl (ctrl_t ctrl) { ctrl->reader_slot = -1; } -#ifdef USE_GNU_PTH +/* Return the name of the socket to be used to connect to this + process. If no socket is available, return NULL. */ +const char * +scd_get_socket_name () +{ + if (socket_name && *socket_name) + return socket_name; + return NULL; +} + static void handle_signal (int signo) @@ -897,18 +835,175 @@ handle_signal (int signo) } } + static void handle_tick (void) { scd_update_reader_status_file (); } + +/* Create a name for the socket. With USE_STANDARD_SOCKET given as + true using STANDARD_NAME in the home directory or if given has + false from the mkdir type name TEMPLATE. In the latter case a + unique name in a unique new directory will be created. In both + cases check for valid characters as well as against a maximum + allowed length for a unix domain socket is done. The function + terminates the process in case of an error. Retunrs: Pointer to an + allcoated string with the absolute name of the socket used. */ +static char * +create_socket_name (int use_standard_socket, + char *standard_name, char *template) +{ + char *name, *p; + + if (use_standard_socket) + name = make_filename (opt.homedir, standard_name, NULL); + else + { + name = xstrdup (template); + p = strrchr (name, '/'); + if (!p) + BUG (); + *p = 0; + if (!mkdtemp (name)) + { + log_error (_("can't create directory `%s': %s\n"), + name, strerror (errno)); + scd_exit (2); + } + *p = '/'; + } + + if (strchr (name, PATHSEP_C)) + { + log_error (("`%s' are not allowed in the socket name\n"), PATHSEP_S); + scd_exit (2); + } + if (strlen (name) + 1 >= DIMof (struct sockaddr_un, sun_path) ) + { + log_error (_("name of socket too long\n")); + scd_exit (2); + } + return name; +} + + + +/* Create a Unix domain socket with NAME. IS_STANDARD_NAME indicates + whether a non-random socket is used. Returns the file descriptor + or terminates the process in case of an error. */ +static int +create_server_socket (int is_standard_name, const char *name) +{ + struct sockaddr_un *serv_addr; + socklen_t len; + int fd; + int rc; + +#ifdef HAVE_W32_SYSTEM + fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); +#else + fd = socket (AF_UNIX, SOCK_STREAM, 0); +#endif + if (fd == -1) + { + log_error (_("can't create socket: %s\n"), strerror (errno)); + scd_exit (2); + } + + serv_addr = xmalloc (sizeof (*serv_addr)); + memset (serv_addr, 0, sizeof *serv_addr); + serv_addr->sun_family = AF_UNIX; + assert (strlen (name) + 1 < sizeof (serv_addr->sun_path)); + strcpy (serv_addr->sun_path, name); + len = (offsetof (struct sockaddr_un, sun_path) + + strlen (serv_addr->sun_path) + 1); + +#ifdef HAVE_W32_SYSTEM + rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); + if (is_standard_name && rc == -1 ) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#else + rc = bind (fd, (struct sockaddr*) serv_addr, len); + if (is_standard_name && rc == -1 && errno == EADDRINUSE) + { + remove (name); + rc = bind (fd, (struct sockaddr*) serv_addr, len); + } +#endif + if (rc == -1) + { + log_error (_("error binding socket to `%s': %s\n"), + serv_addr->sun_path, strerror (errno)); + close (fd); + scd_exit (2); + } + + if (listen (fd, 5 ) == -1) + { + log_error (_("listen() failed: %s\n"), strerror (errno)); + close (fd); + scd_exit (2); + } + + if (opt.verbose) + log_info (_("listening on socket `%s'\n"), serv_addr->sun_path); + + return fd; +} + + + +/* This is the standard connection thread's main function. */ static void * -ticker_thread (void *dummy_arg) +start_connection_thread (void *arg) { - pth_event_t sigs_ev, time_ev = NULL; + int fd = (int)arg; + + if (opt.verbose) + log_info (_("handler for fd %d started\n"), fd); + + scd_command_handler (fd); + + if (opt.verbose) + log_info (_("handler for fd %d terminated\n"), fd); + + /* If this thread is the pipe connection thread, flag that a + shutdown is required. With the next ticker event and given that + no other connections are running the shutdown will then + happen. */ + if (fd == -1) + shutdown_pending = 1; + + return NULL; +} + + +/* Connection handler loop. Wait for connection requests and spawn a + thread after accepting a connection. LISTEN_FD is allowed to be -1 + in which case this code will only do regular timeouts and handle + signals. */ +static void +handle_connections (int listen_fd) +{ + pth_attr_t tattr; + pth_event_t ev, time_ev; sigset_t sigs; int signo; + struct sockaddr_un paddr; + socklen_t plen; + fd_set fdset, read_fdset; + int ret; + int fd; + + tattr = pth_attr_new(); + pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); + pth_attr_set (tattr, PTH_ATTR_NAME, "scd-connections"); #ifndef HAVE_W32_SYSTEM /* fixme */ sigemptyset (&sigs ); @@ -917,43 +1012,101 @@ ticker_thread (void *dummy_arg) sigaddset (&sigs, SIGUSR2); sigaddset (&sigs, SIGINT); sigaddset (&sigs, SIGTERM); - sigs_ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); + ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); #else - sigs_ev = NULL; + ev = NULL; #endif - - while (!shutdown_pending) + time_ev = NULL; + + FD_ZERO (&fdset); + if (listen_fd != -1) + FD_SET (listen_fd, &fdset); + + for (;;) { - if (!time_ev) + if (shutdown_pending) { - time_ev = pth_event (PTH_EVENT_TIME, pth_timeout (2, 0)); - if (time_ev) - pth_event_concat (sigs_ev, time_ev, NULL); - } + if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1) + break; /* ready */ + + /* Do not accept anymore connections but wait for existing + connections to terminate. We do this by clearing out all + file descriptors to wait for, so that the select will be + used to just wait on a signal or timeout event. */ + FD_ZERO (&fdset); + } - if (pth_wait (sigs_ev) < 1) - continue; + /* Create a timeout event if needed. */ + if (!time_ev) + time_ev = pth_event (PTH_EVENT_TIME, pth_timeout (2, 0)); + + /* POSIX says that fd_set should be implemented as a structure, + thus a simple assignment is fine to copy the entire set. */ + read_fdset = fdset; + + if (time_ev) + pth_event_concat (ev, time_ev, NULL); + ret = pth_select_ev (FD_SETSIZE, &read_fdset, NULL, NULL, NULL, ev); + if (time_ev) + pth_event_isolate (time_ev); + + if (ret == -1) + { + if (pth_event_occurred (ev) + || (time_ev && pth_event_occurred (time_ev))) + { + if (pth_event_occurred (ev)) + handle_signal (signo); + if (time_ev && pth_event_occurred (time_ev)) + { + pth_event_free (time_ev, PTH_FREE_ALL); + time_ev = NULL; + handle_tick (); + } + continue; + } + log_error (_("pth_select failed: %s - waiting 1s\n"), + strerror (errno)); + pth_sleep (1); + continue; + } - if ( -#ifdef PTH_STATUS_OCCURRED /* This is Pth 2 */ - pth_event_status (sigs_ev) == PTH_STATUS_OCCURRED -#else - pth_event_occurred (sigs_ev) -#endif - ) - handle_signal (signo); + if (pth_event_occurred (ev)) + { + handle_signal (signo); + } - /* Always run the ticker. */ - if (!shutdown_pending) + if (time_ev && pth_event_occurred (time_ev)) { - pth_event_isolate (sigs_ev); pth_event_free (time_ev, PTH_FREE_ALL); time_ev = NULL; handle_tick (); } + + if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset)) + { + plen = sizeof paddr; + fd = pth_accept (listen_fd, (struct sockaddr *)&paddr, &plen); + if (fd == -1) + { + log_error ("accept failed: %s\n", strerror (errno)); + } + else if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } + fd = -1; + } + } - pth_event_free (sigs_ev, PTH_FREE_ALL); - return NULL; + pth_event_free (ev, PTH_FREE_ALL); + if (time_ev) + pth_event_free (time_ev, PTH_FREE_ALL); + cleanup (); + log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); } -#endif /*USE_GNU_PTH*/ + + diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 5e49f3ae5..eaa9abd35 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -99,7 +99,8 @@ typedef struct app_ctx_s *app_t; /*-- scdaemon.c --*/ void scd_exit (int rc); -void scd_init_default_ctrl (CTRL ctrl); +void scd_init_default_ctrl (ctrl_t ctrl); +const char *scd_get_socket_name (void); /*-- command.c --*/ void scd_command_handler (int); diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 6372954f6..403fa2c45 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -39,6 +39,7 @@ enum cmd_and_opt_values aNull = 0, oQuiet = 'q', oVerbose = 'v', + oRawSocket = 'S', oNoVerbose = 500, oHomedir, @@ -55,6 +56,7 @@ static ARGPARSE_OPTS opts[] = { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("quiet") }, { oHex, "hex", 0, N_("print data out hex encoded") }, + { oRawSocket, "raw-socket", 2, N_("|NAME|connect to Assuan socket NAME")}, /* hidden options */ { oNoVerbose, "no-verbose", 0, "@"}, @@ -70,6 +72,7 @@ struct int quiet; /* Be extra quiet. */ const char *homedir; /* Configuration directory name */ int hex; /* Print data lines in hex format. */ + const char *raw_socket; /* Name of socket to connect in raw mode. */ } opt; @@ -159,6 +162,7 @@ main (int argc, char **argv) case oNoVerbose: opt.verbose = 0; break; case oHomedir: opt.homedir = pargs.r.ret_str; break; case oHex: opt.hex = 1; break; + case oRawSocket: opt.raw_socket = pargs.r.ret_str; break; default: pargs.err = 2; break; } @@ -169,7 +173,21 @@ main (int argc, char **argv) fname = argc ? *argv : NULL; - ctx = start_agent (); + if (opt.raw_socket) + { + rc = assuan_socket_connect (&ctx, opt.raw_socket, 0); + if (rc) + { + log_error ("can't connect to socket `%s': %s\n", + opt.raw_socket, assuan_strerror (rc)); + exit (1); + } + + if (opt.verbose) + log_info ("connection to socket `%s' established\n", opt.raw_socket); + } + else + ctx = start_agent (); line = NULL; linesize = 0; for (;;) -- cgit v1.2.3 From 41862f5f13bef8113cf040ecaba34a35c370eeb3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 20 May 2005 20:39:36 +0000 Subject: * protect-tool.c: New option --canonical. (show_file): Implement it. * keyformat.txt: Define the created-at attribute for keys. * ccid-driver.c: Replaced macro DEBUG_T1 by a new debug level. (parse_ccid_descriptor): Mark SCR335 firmware version 5.18 good. (ccid_transceive): Arghhh. The seqno is another bit in the R-block than in the I block, this was wrong at one place. * scdaemon.c: New options --debug-ccid-driver and --debug-disable-ticker. * app-openpgp.c (do_genkey, do_writekey): Factored code to check for existing key out into .. (does_key_exist): .. New function. * gpg-connect-agent.c (add_definq, show_definq, clear_definq) (handle_inquire): New. (read_and_print_response): Handle INQUIRE command. (main): Implement control commands. --- agent/ChangeLog | 7 + agent/call-scd.c | 7 +- agent/keyformat.txt | 9 +- agent/protect-tool.c | 23 ++- agent/protect.c | 2 +- doc/scdaemon.texi | 50 ++++++- scd/ChangeLog | 27 ++++ scd/app-common.h | 28 +++- scd/app-openpgp.c | 355 +++++++++++++++++++++++++++++++++++++++++----- scd/app.c | 29 ++++ scd/ccid-driver.c | 104 +++++++------- scd/command.c | 81 ++++++++++- scd/scdaemon.c | 33 +++-- scd/tlv.c | 73 ++++++++++ scd/tlv.h | 17 +++ tools/ChangeLog | 9 +- tools/gpg-connect-agent.c | 223 ++++++++++++++++++++++++++++- 17 files changed, 961 insertions(+), 116 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 00f019ddc..015b0b6d8 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,10 @@ +2005-05-20 Werner Koch <wk@g10code.com> + + * protect-tool.c: New option --canonical. + (show_file): Implement it. + + * keyformat.txt: Define the created-at attribute for keys. + 2005-05-18 Werner Koch <wk@g10code.com> * divert-scd.c (ask_for_card): Removed the card reset kludge. diff --git a/agent/call-scd.c b/agent/call-scd.c index 58dd412f0..fc81e2fa3 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -158,7 +158,7 @@ start_scd (ctrl_t ctrl) gpg_error_t err = 0; const char *pgmname; assuan_context_t ctx; - const char *argv[4]; + const char *argv[3]; int no_close_list[3]; int i; int rc; @@ -266,9 +266,8 @@ start_scd (ctrl_t ctrl) pgmname++; argv[0] = pgmname; - argv[1] = "--server"; - argv[2] = "--multi-server"; - argv[3] = NULL; + argv[1] = "--multi-server"; + argv[2] = NULL; i=0; if (!opt.running_detached) diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 7bdb94c0e..2fa53adba 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -30,12 +30,17 @@ Libgcrypt. Here is an example of an unprotected file: (q #00f7a7c..[some bytes not shown]..61#) (u #304559a..[some bytes not shown]..9b#) ) + (created-at timestamp) (uri http://foo.bar x-foo:whatever_you_want) (comment whatever) ) -"comment" and "uri" are optional. "comment" is currently used to keep -track of ssh key comments. +"comment", "created-at" and "uri" are optional. "comment" is +currently used to keep track of ssh key comments. "created-at" is used +to keep track of the creation time stamp used with OpenPGP keys; it is +optional but required for some operations to calculate the fingerprint +of the key. This timestamp should be a string with the number of +seconds since Epoch or an ISO time string (yyyymmddThhmmss). Actually this form should not be used for regular purposes and only accepted by gpg-agent with the configuration option: diff --git a/agent/protect-tool.c b/agent/protect-tool.c index c21aa0517..e8f1d2c10 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -60,6 +60,7 @@ enum cmd_and_opt_values oShadow, oShowShadowInfo, oShowKeygrip, + oCanonical, oP12Import, oP12Export, @@ -86,6 +87,7 @@ struct rsa_secret_key_s static const char *opt_homedir; static int opt_armor; +static int opt_canonical; static int opt_store; static int opt_force; static int opt_no_fail_on_exist; @@ -107,6 +109,7 @@ static ARGPARSE_OPTS opts[] = { { oVerbose, "verbose", 0, "verbose" }, { oArmor, "armor", 0, "write output in advanced format" }, + { oCanonical, "canonical", 0, "write output in canonical format" }, { oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" }, { oProtect, "protect", 256, "protect a private key"}, { oUnprotect, "unprotect", 256, "unprotect a private key"}, @@ -508,14 +511,21 @@ show_file (const char *fname) keylen = gcry_sexp_canon_len (key, 0, NULL,NULL); assert (keylen); - - p = make_advanced (key, keylen); - xfree (key); - if (p) + + if (opt_canonical) { - fwrite (p, strlen (p), 1, stdout); - xfree (p); + fwrite (key, keylen, 1, stdout); } + else + { + p = make_advanced (key, keylen); + if (p) + { + fwrite (p, strlen (p), 1, stdout); + xfree (p); + } + } + xfree (key); } static void @@ -1079,6 +1089,7 @@ main (int argc, char **argv ) { case oVerbose: opt.verbose++; break; case oArmor: opt_armor=1; break; + case oCanonical: opt_canonical=1; break; case oHomedir: opt_homedir = pargs.r.ret_str; break; case oProtect: cmd = oProtect; break; diff --git a/agent/protect.c b/agent/protect.c index ae3061c77..658c8c529 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -60,7 +60,7 @@ hash_passphrase (const char *passphrase, int hashalgo, -/* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to +/* Calculate the MIC for a private key S-Exp. SHA1HASH should point to a 20 byte buffer. This function is suitable for any algorithms. */ static int calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 971234e52..f069a9fb8 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -54,6 +54,12 @@ abbreviate this command. 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 --multi-server +@opindex multi-server +Run in server mode and wait for commands on the @code{stdin} as well as +on an additional Unix Domain socket. The server command @code{GETINFO} +may be used to get the name of that extra socket. + @item --daemon @opindex daemon Run the program in the background. This option is required to prevent @@ -120,6 +126,13 @@ 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. +@quotation Note +All debugging options are subject to change and thus should not be used +by any application program. As the name says, they are only used as +helpers to debug problems. +@end quotation + + @item --debug @var{flags} @opindex debug This option is only useful for debugging and the behaviour may change at @@ -128,7 +141,7 @@ usual C-Syntax. The currently defined bits are: @table @code @item 0 (1) - X.509 or OpenPGP protocol related data + command I/O @item 1 (2) values of big number integers @item 2 (4) @@ -143,8 +156,8 @@ usual C-Syntax. The currently defined bits are: write hashed data to files named @code{dbgmd-000*} @item 10 (1024) trace Assuan protocol - @item 12 (4096) - bypass all certificate validation + @item 11 (2048) + trace APDU I/O to the card. This may reveal sensitive data. @end table @item --debug-all @@ -157,6 +170,17 @@ 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-ccid-driver +@opindex debug-wait +Enable debug output from the included CCID driver for smartcards. +Using this option twice will also enable some tracing of the T=1 +protocol. Note that this option may reveal sensitive data. + +@item --debug-disable-ticker +@opindex debug-disable-ticker +This option disables all ticker functions like checking for card +insertions. + @item --no-detach @opindex no-detach Don't detach the process from the console. This is manly usefule for @@ -286,6 +310,7 @@ syncronizing access to a token between sessions. * Scdaemon PKDECRYPT:: Decrypting data with a Smartcard. * Scdaemon GETATTR:: Read an attribute's value. * Scdaemon SETATTR:: Update an attribute's value. +* Scdaemon WRITEKEY:: Write a key to a card. * Scdaemon GENKEY:: Generate a new key on-card. * Scdaemon RANDOM:: Return random bytes generate on-card. * Scdaemon PASSWD:: Change PINs. @@ -420,6 +445,25 @@ TO BE WRITTEN. TO BE WRITTEN. +@node Scdaemon WRITEKEY +@subsection Write a key to a card. + +@example + WRITEKEY [--force] @var{keyid} +@end example + +This command is used to store a secret key on a a smartcard. The +allowed keyids depend on the currently selected smartcard +application. The actual keydata is requested using the inquiry +@code{KEYDATA} and need to be provided without any protection. With +@option{--force} set an existing key under this @var{keyid} will get +overwritten. The key data is expected to be the usual canonical encoded +S-expression. + +A PIN will be requested in most saes. This however depends on the +actual card application. + + @node Scdaemon GENKEY @subsection Generate a new key on-card. diff --git a/scd/ChangeLog b/scd/ChangeLog index 19bba2bf4..c64fbec7e 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,30 @@ +2005-05-20 Werner Koch <wk@g10code.com> + + * ccid-driver.c: Replaced macro DEBUG_T1 by a new debug level. + (parse_ccid_descriptor): Mark SCR335 firmware version 5.18 good. + (ccid_transceive): Arghhh. The seqno is another bit in the + R-block than in the I block, this was wrong at one place. + + * scdaemon.c: New options --debug-ccid-driver and + --debug-disable-ticker. + + * app-openpgp.c (do_genkey, do_writekey): Factored code to check + for existing key out into .. + (does_key_exist): .. New function. + +2005-05-19 Werner Koch <wk@g10code.com> + + * tlv.c (parse_sexp): New. + + * command.c (cmd_writekey): New. + * app.c (app_writekey): New. + * app-common.c (app_t): Add function ptr WRITEKEY. + * app-openpgp.c (do_writekey): New. + + * app-openpgp.c (do_readkey) [GNUPG_MAJOR_VERSION==1]: Return error. + * app-common.h (app_t) [GNUPG_MAJOR_VERSION==1]: Add a field to + store the Assuan context. + 2005-05-17 Werner Koch <wk@g10code.com> * scdaemon.c: Removed non-pth code paths. diff --git a/scd/app-common.h b/scd/app-common.h index 517286c49..c2c302395 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -23,10 +23,15 @@ #ifndef GNUPG_SCD_APP_COMMON_H #define GNUPG_SCD_APP_COMMON_H -#if GNUPG_MAJOR_VERSION != 1 -#include <ksba.h> +#if GNUPG_MAJOR_VERSION == 1 +# ifdef ENABLE_AGENT_SUPPORT +# include "assuan.h" +# endif +#else +# include <ksba.h> #endif + struct app_local_s; /* Defined by all app-*.c. */ struct app_ctx_s { @@ -35,6 +40,15 @@ struct app_ctx_s { unsupported operations the particular function pointer is set to NULL */ int slot; /* Used reader. */ + + /* If this is used by GnuPG 1.4 we need to know the assuan context + in case we need to divert the operation to an already running + agent. This if ASSUAN_CTX is not NULL we take this as indication + that all operations are diverted to gpg-agent. */ +#if GNUPG_MAJOR_VERSION == 1 && defined(ENABLE_AGENT_SUPPORT) + assuan_context_t assuan_ctx; +#endif /*GNUPG_MAJOR_VERSION == 1*/ + unsigned char *serialno; /* Serialnumber in raw form, allocated. */ size_t serialnolen; /* Length in octets of serialnumber. */ const char *apptype; @@ -72,6 +86,11 @@ struct app_ctx_s { void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); + gpg_error_t (*writekey) (app_t app, ctrl_t ctrl, + const char *certid, unsigned int flags, + gpg_error_t (*pincb)(void*,const char *,char **), + void *pincb_arg, + const unsigned char *pk, size_t pklen); gpg_error_t (*genkey) (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, gpg_error_t (*pincb)(void*, const char *, char **), @@ -134,6 +153,11 @@ gpg_error_t app_decipher (app_t app, const char *keyidstr, void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen ); +gpg_error_t app_writekey (app_t app, ctrl_t ctrl, + const char *keyidstr, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *keydata, size_t keydatalen); gpg_error_t app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, gpg_error_t (*pincb)(void*, const char *, char **), diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index b8060df03..16ebd34c8 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -565,7 +565,7 @@ store_fpr (int slot, int keynumber, u32 timestamp, n = 6 + 2 + mlen + 2 + elen; p = buffer = xtrymalloc (3 + n); if (!buffer) - return gpg_error (gpg_err_code_from_errno (errno)); + return gpg_error_from_errno (errno); *p++ = 0x99; /* ctb */ *p++ = n >> 8; /* 2 byte length header */ @@ -1207,6 +1207,7 @@ do_learn_status (app_t app, ctrl_t ctrl) static gpg_error_t do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) { +#if GNUPG_MAJOR_VERSION > 1 gpg_error_t err; int keyno; unsigned char *buf; @@ -1230,6 +1231,9 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) *pk = buf; *pklen = app->app_local->pk[keyno-1].keylen;; return 0; +#else + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#endif } @@ -1523,6 +1527,318 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, } +/* Check whether a key already exists. KEYIDX is the index of the key + (0..2). If FORCE is TRUE a diagnositivc will be printed but no + error returned if the key already exists. */ +static gpg_error_t +does_key_exist (app_t app, int keyidx, int force) +{ + const unsigned char *fpr; + unsigned char *buffer; + size_t buflen, n; + int i; + + assert (keyidx >=0 && keyidx <= 2); + + if (iso7816_get_data (app->slot, 0x006E, &buffer, &buflen)) + { + log_error (_("error reading application data\n")); + return gpg_error (GPG_ERR_GENERAL); + } + fpr = find_tlv (buffer, buflen, 0x00C5, &n); + if (!fpr || n < 60) + { + log_error (_("error reading fingerprint DO\n")); + xfree (buffer); + return gpg_error (GPG_ERR_GENERAL); + } + fpr += 20*keyidx; + for (i=0; i < 20 && !fpr[i]; i++) + ; + xfree (buffer); + if (i!=20 && !force) + { + log_error (_("key already exists\n")); + return gpg_error (GPG_ERR_EEXIST); + } + else if (i!=20) + log_info (_("existing key will be replaced\n")); + else + log_info (_("generating new key\n")); + return 0; +} + + + +/* Handle the WRITEKEY command for OpenPGP. This function expects a + canonical encoded S-expression with the secret key in KEYDATA and + its length (for assertions) in KEYDATALEN. KEYID needs to be the + usual keyid which for OpenPGP is the string "OPENPGP.n" with + n=1,2,3. Bit 0 of FLAGS indicates whether an existing key shall + get overwritten. PINCB and PINCB_ARG are the usual arguments for + the pinentry callback. */ +static gpg_error_t +do_writekey (app_t app, ctrl_t ctrl, + const char *keyid, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *keydata, size_t keydatalen) +{ + gpg_error_t err; + int force = (flags & 1); + int keyno; + const unsigned char *buf, *tok; + size_t buflen, toklen; + int depth, last_depth1, last_depth2; + const unsigned char *rsa_n = NULL; + const unsigned char *rsa_e = NULL; + const unsigned char *rsa_p = NULL; + const unsigned char *rsa_q = NULL; + size_t rsa_n_len, rsa_e_len, rsa_p_len, rsa_q_len; + unsigned int nbits; + unsigned char *template = NULL; + unsigned char *tp; + size_t template_len; + unsigned char fprbuf[20]; + u32 created_at = 0; + + if (!strcmp (keyid, "OPENPGP.1")) + keyno = 0; + else if (!strcmp (keyid, "OPENPGP.2")) + keyno = 1; + else if (!strcmp (keyid, "OPENPGP.3")) + keyno = 2; + else + return gpg_error (GPG_ERR_INV_ID); + + err = does_key_exist (app, keyno, force); + if (err) + return err; + + + /* + Parse the S-expression + */ + buf = keydata; + buflen = keydatalen; + depth = 0; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (!tok || toklen != 11 || memcmp ("private-key", tok, toklen)) + { + if (!tok) + ; + else if (toklen == 21 && !memcmp ("protected-private-key", tok, toklen)) + log_info ("protected-private-key passed to writekey\n"); + else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen)) + log_info ("shadowed-private-key passed to writekey\n"); + err = gpg_error (GPG_ERR_BAD_KEY); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen)) + { + err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); + goto leave; + } + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + { + err = gpg_error (GPG_ERR_UNKNOWN_SEXP); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && toklen == 1) + { + const unsigned char **mpi; + size_t *mpi_len; + + switch (*tok) + { + case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break; + case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break; + case 'p': mpi = &rsa_p; mpi_len = &rsa_p_len; break; + case 'q': mpi = &rsa_q; mpi_len = &rsa_q_len;break; + default: mpi = NULL; mpi_len = NULL; break; + } + if (mpi && *mpi) + { + err = gpg_error (GPG_ERR_DUP_VALUE); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && mpi) + { + /* Strip off leading zero bytes and save. */ + for (;toklen && !*tok; toklen--, tok++) + ; + *mpi = tok; + *mpi_len = toklen; + } + } + /* Skip until end of list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + goto leave; + } + /* Parse other attributes. */ + last_depth1 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth1) + { + if (tok) + { + err = gpg_error (GPG_ERR_UNKNOWN_SEXP); + goto leave; + } + if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) + goto leave; + if (tok && toklen == 10 && !memcmp ("created-at", tok, toklen)) + { + if ((err = parse_sexp (&buf,&buflen,&depth,&tok,&toklen))) + goto leave; + if (tok) + { + for (created_at=0; toklen && *tok && *tok >= '0' && *tok <= '9'; + tok++, toklen--) + created_at = created_at*10 + (*tok - '0'); + } + } + /* Skip until end of list. */ + last_depth2 = depth; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth && depth >= last_depth2) + ; + if (err) + goto leave; + } + + + /* Check that we have all parameters and that they match the card + description. */ + if (!created_at) + { + log_error (_("creation timestamp missing\n")); + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + nbits = rsa_n? count_bits (rsa_n, rsa_n_len) : 0; + if (nbits != 1024) + { + log_error (_("RSA modulus missing or not of size %d bits\n"), 1024); + err = gpg_error (GPG_ERR_BAD_SECKEY); + goto leave; + } + nbits = rsa_e? count_bits (rsa_e, rsa_e_len) : 0; + if (nbits < 2 || nbits > 32) + { + log_error (_("RSA public exponent missing or largerr than %d bits\n"), + 32); + err = gpg_error (GPG_ERR_BAD_SECKEY); + goto leave; + } + nbits = rsa_p? count_bits (rsa_p, rsa_p_len) : 0; + if (nbits != 512) + { + log_error (_("RSA prime %s missing or not of size %d bits\n"), "P", 512); + err = gpg_error (GPG_ERR_BAD_SECKEY); + goto leave; + } + nbits = rsa_q? count_bits (rsa_q, rsa_q_len) : 0; + if (nbits != 512) + { + log_error (_("RSA prime %s missing or not of size %d bits\n"), "Q", 512); + err = gpg_error (GPG_ERR_BAD_SECKEY); + goto leave; + } + + + /* Build the private key template as described in section 4.3.3.6 of + the OpenPGP card specs: + 0xC0 <length> public exponent + 0xC1 <length> prime p + 0xC2 <length> prime q + */ + assert (rsa_e_len <= 4); + template_len = (1 + 1 + 4 + + 1 + 1 + rsa_p_len + + 1 + 1 + rsa_q_len); + template = tp = xtrymalloc_secure (template_len); + if (!template) + { + err = gpg_error_from_errno (errno); + goto leave; + } + *tp++ = 0xC0; + *tp++ = 4; + memcpy (tp, rsa_e, rsa_e_len); + if (rsa_e_len < 4) + { + /* Right justify E. */ + memmove (tp+4-rsa_e_len, tp, 4-rsa_e_len); + memset (tp, 0, 4-rsa_e_len); + } + tp += 4; + + *tp++ = 0xC1; + *tp++ = rsa_p_len; + memcpy (tp, rsa_p, rsa_p_len); + tp += rsa_p_len; + + *tp++ = 0xC2; + *tp++ = rsa_q_len; + memcpy (tp, rsa_q, rsa_q_len); + tp += rsa_q_len; + + assert (tp - template == template_len); + + + /* Obviously we need to remove the cached public key. */ + xfree (app->app_local->pk[keyno].key); + app->app_local->pk[keyno].key = NULL; + app->app_local->pk[keyno].keylen = 0; + app->app_local->pk[keyno].read_done = 0; + + /* Prepare for storing the key. */ + err = verify_chv3 (app, pincb, pincb_arg); + if (err) + goto leave; + + /* Store the key. */ + err = iso7816_put_data (app->slot, + (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, + template, template_len); + if (err) + { + log_error (_("failed to store the key: %s\n"), gpg_strerror (err)); + goto leave; + } + + err = store_fpr (app->slot, keyno, created_at, + rsa_n, rsa_n_len, rsa_e, rsa_e_len, + fprbuf, app->card_version); + if (err) + goto leave; + + + leave: + xfree (template); + return err; +} + /* Handle the GENKEY command. */ static gpg_error_t @@ -1531,13 +1847,11 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, void *pincb_arg) { int rc; - int i; char numbuf[30]; unsigned char fprbuf[20]; - const unsigned char *fpr; const unsigned char *keydata, *m, *e; - unsigned char *buffer; - size_t buflen, keydatalen, n, mlen, elen; + unsigned char *buffer = NULL; + size_t buflen, keydatalen, mlen, elen; time_t created_at; int keyno = atoi (keynostr); int force = (flags & 1); @@ -1558,41 +1872,15 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, app->app_local->pk[keyno].read_done = 0; /* Check whether a key already exists. */ - rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen); + rc = does_key_exist (app, keyno, force); if (rc) - { - log_error (_("error reading application data\n")); - return gpg_error (GPG_ERR_GENERAL); - } - fpr = find_tlv (buffer, buflen, 0x00C5, &n); - if (!fpr || n != 60) - { - rc = gpg_error (GPG_ERR_GENERAL); - log_error (_("error reading fingerprint DO\n")); - goto leave; - } - fpr += 20*keyno; - for (i=0; i < 20 && !fpr[i]; i++) - ; - if (i!=20 && !force) - { - rc = gpg_error (GPG_ERR_EEXIST); - log_error (_("key already exists\n")); - goto leave; - } - else if (i!=20) - log_info (_("existing key will be replaced\n")); - else - log_info (_("generating new key\n")); + return rc; - /* Prepare for key generation by verifying the ADmin PIN. */ rc = verify_chv3 (app, pincb, pincb_arg); if (rc) goto leave; - xfree (buffer); buffer = NULL; - #if 1 log_info (_("please wait while key is being generated ...\n")); start_at = time (NULL); @@ -2216,6 +2504,7 @@ app_select_openpgp (app_t app) app->fnc.readkey = do_readkey; app->fnc.getattr = do_getattr; app->fnc.setattr = do_setattr; + app->fnc.writekey = do_writekey; app->fnc.genkey = do_genkey; app->fnc.sign = do_sign; app->fnc.auth = do_auth; diff --git a/scd/app.c b/scd/app.c index 0a1960267..f2c427f5b 100644 --- a/scd/app.c +++ b/scd/app.c @@ -546,6 +546,35 @@ app_decipher (app_t app, const char *keyidstr, } +/* Perform the WRITEKEY operation. */ +gpg_error_t +app_writekey (app_t app, ctrl_t ctrl, + const char *keyidstr, unsigned int flags, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *keydata, size_t keydatalen) +{ + gpg_error_t err; + + if (!app || !keyidstr || !*keyidstr || !pincb) + return gpg_error (GPG_ERR_INV_VALUE); + if (!app->initialized) + return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); + if (!app->fnc.writekey) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + err = lock_reader (app); + if (err) + return err; + err = app->fnc.writekey (app, ctrl, keyidstr, flags, + pincb, pincb_arg, keydata, keydatalen); + unlock_reader (app); + if (opt.verbose) + log_info ("operation writekey result: %s\n", gpg_strerror (err)); + return err; + +} + + /* Perform a SETATTR operation. */ gpg_error_t app_genkey (app_t app, CTRL ctrl, const char *keynostr, unsigned int flags, diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index b817452b1..387108559 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -108,9 +108,6 @@ # include "scdaemon.h" #endif -/* Define to print information pertaining the T=1 protocol. */ -#undef DEBUG_T1 - # define DEBUGOUT(t) do { if (debug_level) \ log_debug (DRVNAME t); } while (0) @@ -120,6 +117,8 @@ log_debug (DRVNAME t,(a),(b)); } while (0) # define DEBUGOUT_3(t,a,b,c) do { if (debug_level) \ log_debug (DRVNAME t,(a),(b),(c));} while (0) +# define DEBUGOUT_4(t,a,b,c,d) do { if (debug_level) \ + log_debug (DRVNAME t,(a),(b),(c),(d));} while (0) # define DEBUGOUT_CONT(t) do { if (debug_level) \ log_printf (t); } while (0) # define DEBUGOUT_CONT_1(t,a) do { if (debug_level) \ @@ -141,6 +140,8 @@ fprintf (stderr, DRVNAME t, (a), (b)); } while (0) # define DEBUGOUT_3(t,a,b,c) do { if (debug_level) \ fprintf (stderr, DRVNAME t, (a), (b), (c)); } while (0) +# define DEBUGOUT_4(t,a,b,c,d) do { if (debug_level) \ + fprintf (stderr, DRVNAME t, (a), (b), (c), (d));} while(0) # define DEBUGOUT_CONT(t) do { if (debug_level) \ fprintf (stderr, t); } while (0) # define DEBUGOUT_CONT_1(t,a) do { if (debug_level) \ @@ -216,7 +217,11 @@ struct ccid_driver_s static int initialized_usb; /* Tracks whether USB has been initialized. */ -static int debug_level; /* Flag to control the debug output. */ +static int debug_level; /* Flag to control the debug output. + 0 = No debugging + 1 = USB I/O info + 2 = T=1 protocol tracing + */ static unsigned int compute_edc (const unsigned char *data, size_t datalen, @@ -457,7 +462,7 @@ parse_ccid_descriptor (ccid_driver_t handle, && handle->max_ifsd > 48 && ( (handle->id_product == 0xe001 && handle->bcd_device < 0x0516) ||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620) - ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0519) + ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0518) ||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504) )) { @@ -827,7 +832,8 @@ scan_or_find_devices (int readerno, const char *readerid, /* Set the level of debugging to to usea dn return the old level. -1 just returns the old level. A level of 0 disables debugging, 1 - enables debugging, other values are not yet defined. */ + enables debugging, 2 enables additional tracing of the T=1 + protocol, other values are not yet defined. */ int ccid_set_debug_level (int level) { @@ -1437,12 +1443,13 @@ ccid_get_atr (ccid_driver_t handle, DEBUGOUT_CONT_1 (" %02X", msg[i]); DEBUGOUT_LF (); -#ifdef DEBUG_T1 - fprintf (stderr, "T1: put %c-block seq=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); -#endif + if (debug_level > 1) + DEBUGOUT_3 ("T=1: put %c-block seq=%d%s\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) + : !!(msg[11] & 0x40)), + (!(msg[11] & 0x80) && (msg[11] & 0x20)? " [more]":"")); rc = bulk_out (handle, msg, msglen); if (rc) @@ -1460,14 +1467,15 @@ ccid_get_atr (ccid_driver_t handle, if (tpdulen < 4) return CCID_DRIVER_ERR_ABORTED; -#ifdef DEBUG_T1 - fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), - ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 - ); -#endif + if (debug_level > 1) + DEBUGOUT_4 ("T=1: got %c-block seq=%d err=%d%s\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) + : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0, + (!(msg[11] & 0x80) && (msg[11] & 0x20)? " [more]":"")); + if ((tpdu[1] & 0xe0) != 0xe0 || tpdu[2] != 1) { DEBUGOUT ("invalid response for S-block (Change-IFSD)\n"); @@ -1706,12 +1714,13 @@ ccid_transceive (ccid_driver_t handle, DEBUGOUT_CONT_1 (" %02X", msg[i]); DEBUGOUT_LF (); -#ifdef DEBUG_T1 - fprintf (stderr, "T1: put %c-block seq=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40))); -#endif + if (debug_level > 1) + DEBUGOUT_3 ("T=1: put %c-block seq=%d%s\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) + : !!(msg[11] & 0x40)), + (!(msg[11] & 0x80) && (msg[11] & 0x20)? " [more]":"")); rc = bulk_out (handle, msg, msglen); if (rc) @@ -1731,14 +1740,14 @@ ccid_transceive (ccid_driver_t handle, usb_clear_halt (handle->idev, handle->ep_bulk_in); return CCID_DRIVER_ERR_ABORTED; } -#ifdef DEBUG_T1 - fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), - ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 - ); -#endif + + if (debug_level > 1) + DEBUGOUT_4 ("T=1: got %c-block seq=%d err=%d%s\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0, + (!(msg[11] & 0x80) && (msg[11] & 0x20)? " [more]":"")); if (!(tpdu[1] & 0x80)) { /* This is an I-block. */ @@ -1814,8 +1823,8 @@ ccid_transceive (ccid_driver_t handle, msg = send_buffer; tpdulen = last_tpdulen; } - else if (sending && !!(tpdu[1] & 0x40) == handle->t1_ns) - { /* Reponse does not match our sequence number. */ + else if (sending && !!(tpdu[1] & 0x10) == handle->t1_ns) + { /* Response does not match our sequence number. */ DEBUGOUT ("R-block with wrong seqno received on more bit\n"); return CCID_DRIVER_ERR_CARD_IO_ERROR; } @@ -1835,7 +1844,7 @@ ccid_transceive (ccid_driver_t handle, else { /* This is a S-block. */ retries = 0; - DEBUGOUT_2 ("T1 S-block %s received cmd=%d\n", + DEBUGOUT_2 ("T=1 S-block %s received cmd=%d\n", (tpdu[1] & 0x20)? "response": "request", (tpdu[1] & 0x1f)); if ( !(tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 3 && tpdu[2]) @@ -1853,7 +1862,7 @@ ccid_transceive (ccid_driver_t handle, if (use_crc) tpdu[tpdulen++] = (edc >> 8); tpdu[tpdulen++] = edc; - DEBUGOUT_1 ("T1 waittime extension of bwi=%d\n", bwi); + DEBUGOUT_1 ("T=1 waittime extension of bwi=%d\n", bwi); } else return CCID_DRIVER_ERR_CARD_IO_ERROR; @@ -2008,14 +2017,13 @@ ccid_transceive_secure (ccid_driver_t handle, usb_clear_halt (handle->idev, handle->ep_bulk_in); return CCID_DRIVER_ERR_ABORTED; } -#ifdef DEBUG_T1 - fprintf (stderr, "T1: got %c-block seq=%d err=%d\n", - ((msg[11] & 0xc0) == 0x80)? 'R' : - (msg[11] & 0x80)? 'S' : 'I', - ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), - ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0 - ); -#endif + if (debug_level > 1) + DEBUGOUT_4 ("T=1: got %c-block seq=%d err=%d%s\n", + ((msg[11] & 0xc0) == 0x80)? 'R' : + (msg[11] & 0x80)? 'S' : 'I', + ((msg[11] & 0x80)? !!(msg[11]& 0x10) : !!(msg[11] & 0x40)), + ((msg[11] & 0xc0) == 0x80)? (msg[11] & 0x0f) : 0, + (!(msg[11] & 0x80) && (msg[11] & 0x20)? " [more]":"")); if (!(tpdu[1] & 0x80)) { /* This is an I-block. */ @@ -2062,7 +2070,7 @@ ccid_transceive_secure (ccid_driver_t handle, DEBUGOUT ("No retries supported for Secure operation\n"); return CCID_DRIVER_ERR_CARD_IO_ERROR; } - else if (!!(tpdu[1] & 0x40) == handle->t1_ns) + else if (!!(tpdu[1] & 0x10) == handle->t1_ns) { /* Reponse does not match our sequence number. */ DEBUGOUT ("R-block with wrong seqno received on more bit\n"); return CCID_DRIVER_ERR_CARD_IO_ERROR; @@ -2075,7 +2083,7 @@ ccid_transceive_secure (ccid_driver_t handle, } else { /* This is a S-block. */ - DEBUGOUT_2 ("T1 S-block %s received cmd=%d for Secure operation\n", + DEBUGOUT_2 ("T=1 S-block %s received cmd=%d for Secure operation\n", (tpdu[1] & 0x20)? "response": "request", (tpdu[1] & 0x1f)); return CCID_DRIVER_ERR_CARD_IO_ERROR; diff --git a/scd/command.c b/scd/command.c index 5ea3e01db..c68d0e925 100644 --- a/scd/command.c +++ b/scd/command.c @@ -40,6 +40,9 @@ /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */ #define MAXLEN_PIN 100 +/* Maximum allowed size of key data as used in inquiries. */ +#define MAXLEN_KEYDATA 4096 + #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) @@ -523,7 +526,7 @@ cmd_readcert (assuan_context_t ctx, char *line) } -/* READKEY <hexified_certid> +/* READKEY <keyid> Return the public key for the given cert or key ID as an standard S-Expression. @@ -913,6 +916,79 @@ cmd_setattr (assuan_context_t ctx, char *orig_line) return map_to_assuan_status (rc); } + + +/* WRITEKEY [--force] <keyid> + + This command is used to store a secret key on a a smartcard. The + allowed keyids depend on the currently selected smartcard + application. The actual keydata is requested using the inquiry + "KETDATA" and need to be provided without any protection. With + --force set an existing key under this KEYID will get overwritten. + The keydata is expected to be the usual canonical encoded + S-expression. + + A PIN will be requested for most NAMEs. See the corresponding + writekey function of the actually used application (app-*.c) for + details. */ +static int +cmd_writekey (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int rc; + char *keyid; + int force = has_option (line, "--force"); + unsigned char *keydata; + size_t keydatalen; + + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_LOCKED); + + /* Skip over options. */ + while ( *line == '-' && line[1] == '-' ) + { + while (*line && !spacep (line)) + line++; + while (spacep (line)) + line++; + } + if (!*line) + return set_error (Parameter_Error, "no keyid given"); + keyid = line; + while (*line && !spacep (line)) + line++; + *line = 0; + + if ((rc = open_card (ctrl, NULL))) + return rc; + + if (!ctrl->app_ctx) + return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); + + keyid = xtrystrdup (keyid); + if (!keyid) + return ASSUAN_Out_Of_Core; + + /* Now get the actual keydata. */ + rc = assuan_inquire (ctx, "KEYDATA", &keydata, &keydatalen, MAXLEN_KEYDATA); + if (rc) + { + xfree (keyid); + return rc; + } + + /* Write the key to the card. */ + rc = app_writekey (ctrl->app_ctx, ctrl, keyid, force? 1:0, + pin_cb, ctx, keydata, keydatalen); + xfree (keyid); + xfree (keydata); + + TEST_CARD_REMOVAL (ctrl, rc); + return map_to_assuan_status (rc); +} + + + /* GENKEY [--force] <no> Generate a key on-card identified by NO, which is application @@ -924,7 +1000,7 @@ cmd_setattr (assuan_context_t ctx, char *orig_line) S KEY-DATA [p|n] <hexdata> - --force is required to overwriet an already existing key. The + --force is required to overwrite an already existing key. The KEY-CREATED-AT is required for further processing because it is part of the hashed key material for the fingerprint. @@ -1222,6 +1298,7 @@ register_commands (assuan_context_t ctx) { "OUTPUT", NULL }, { "GETATTR", cmd_getattr }, { "SETATTR", cmd_setattr }, + { "WRITEKEY", cmd_writekey }, { "GENKEY", cmd_genkey }, { "RANDOM", cmd_random }, { "PASSWD", cmd_passwd }, diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 9a8b31ac5..1110d9d76 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -50,6 +50,7 @@ #ifdef HAVE_W32_SYSTEM #include "../jnlib/w32-afunix.h" #endif +#include "ccid-driver.h" enum cmd_and_opt_values @@ -66,7 +67,7 @@ enum cmd_and_opt_values oDebugAll, oDebugLevel, oDebugWait, - oDebugSC, + oDebugCCIDDriver, oNoGreeting, oNoOptions, oHomedir, @@ -85,8 +86,8 @@ enum cmd_and_opt_values oAllowAdmin, oDenyAdmin, oDisableApplication, - -aTest }; + oDebugDisableTicker +}; @@ -97,6 +98,8 @@ static ARGPARSE_OPTS opts[] = { { 301, NULL, 0, N_("@Options:\n ") }, { oServer, "server", 0, N_("run in server mode (foreground)") }, + { oMultiServer, "multi-server", 0, + N_("run in multi server mode (foreground)") }, { oDaemon, "daemon", 0, N_("run in daemon mode (background)") }, { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, @@ -107,10 +110,10 @@ static ARGPARSE_OPTS opts[] = { { oDebugAll, "debug-all" ,0, "@"}, { oDebugLevel, "debug-level" ,2, "@"}, { oDebugWait,"debug-wait",1, "@"}, + { oDebugCCIDDriver, "debug-ccid-driver", 0, "@"}, + { oDebugDisableTicker, "debug-disable-ticker", 0, "@"}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, - { oMultiServer, "multi-server", 0, - N_("allow additional connections in server mode")}, { oReaderPort, "reader-port", 2, N_("|N|connect to reader at port N")}, { octapiDriver, "ctapi-driver", 2, N_("|NAME|use NAME as ct-API driver")}, { opcscDriver, "pcsc-driver", 2, N_("|NAME|use NAME as PC/SC driver")}, @@ -125,10 +128,6 @@ static ARGPARSE_OPTS opts[] = { { oDenyAdmin, "deny-admin", 0, "@" }, { oDisableApplication, "disable-application", 2, "@"}, - /* Dummy options to be removed at some point. */ - { oDebugSC, "debug-sc", 1, "@" }, - { oDisableOpenSC, "disable-opensc", 0, "@" }, - {0} }; @@ -150,6 +149,12 @@ static int maybe_setuid = 1; /* Name of the communication socket */ static char *socket_name; + +/* Debug flag to disable the ticker. The ticker is in fact not + disabled but it won't perform any ticker specific actions. */ +static int ticker_disabled; + + static char *create_socket_name (int use_standard_socket, char *standard_name, char *template); @@ -443,7 +448,10 @@ main (int argc, char **argv ) case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; - case oDebugSC: break; + case oDebugCCIDDriver: + ccid_set_debug_level (ccid_set_debug_level (-1)+1); + break; + case oDebugDisableTicker: ticker_disabled = 1; break; case oOptions: /* config files may not be nested (silently ignore them) */ @@ -463,7 +471,7 @@ main (int argc, char **argv ) case oCsh: csh_style = 1; break; case oSh: csh_style = 0; break; case oServer: pipe_server = 1; break; - case oMultiServer: multi_server = 1; break; + case oMultiServer: pipe_server = 1; multi_server = 1; break; case oDaemon: is_daemon = 1; break; case oReaderPort: opt.reader_port = pargs.r.ret_str; break; @@ -839,7 +847,8 @@ handle_signal (int signo) static void handle_tick (void) { - scd_update_reader_status_file (); + if (!ticker_disabled) + scd_update_reader_status_file (); } diff --git a/scd/tlv.c b/scd/tlv.c index 3a81ea6d9..b5dcd4021 100644 --- a/scd/tlv.c +++ b/scd/tlv.c @@ -221,3 +221,76 @@ parse_ber_header (unsigned char const **buffer, size_t *size, *size = length; return 0; } + + +/* FIXME: The following function should not go into this file but for + now it is easier to keep it here. */ + +/* Return the next token of an canconical encoded S-expression. BUF + is the pointer to the S-expression and BUFLEN is a pointer to the + length of this S-expression (used to validate the syntax). Both + are updated to reflect the new position. The token itself is + returned as a pointer into the orginal buffer at TOK and TOKLEN. + If a parentheses is the next token, TOK will be set to NULL. + TOKLEN is checked to be within the bounds. On error a error code + is returned and all pointers should are not guaranteed to point to + a meanigful value. DEPTH should be initialized to 0 and will + reflect on return the actual depth of the tree. To detect the end + of the S-expression it is advisable to check DEPTH after a + successful return: + + depth = 0; + while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)) + && depth) + process_token (tok, toklen); + if (err) + handle_error (); + */ +gpg_error_t +parse_sexp (unsigned char const **buf, size_t *buflen, + int *depth, unsigned char const **tok, size_t *toklen) +{ + const unsigned char *s; + size_t n, vlen; + + s = *buf; + n = *buflen; + *tok = NULL; + *toklen = 0; + if (!n) + return *depth ? gpg_error (GPG_ERR_INV_SEXP) : 0; + if (*s == '(') + { + s++; n--; + (*depth)++; + *buf = s; + *buflen = n; + return 0; + } + if (*s == ')') + { + if (!*depth) + return gpg_error (GPG_ERR_INV_SEXP); + *toklen = 1; + s++; n--; + (*depth)--; + *buf = s; + *buflen = n; + return 0; + } + for (vlen=0; n && *s && *s != ':' && (*s >= '0' && *s <= '9'); s++, n--) + vlen = vlen*10 + (*s - '0'); + if (!n || *s != ':') + return gpg_error (GPG_ERR_INV_SEXP); + s++; n--; + if (vlen > n) + return gpg_error (GPG_ERR_INV_SEXP); + *tok = s; + *toklen = vlen; + s += vlen; + n -= vlen; + *buf = s; + *buflen = n; + return 0; +} + diff --git a/scd/tlv.h b/scd/tlv.h index 628580431..f587dd9df 100644 --- a/scd/tlv.h +++ b/scd/tlv.h @@ -88,4 +88,21 @@ gpg_error_t parse_ber_header (unsigned char const **buffer, size_t *size, +/* Return the next token of an canconical encoded S-expression. BUF + is the pointer to the S-expression and BUFLEN is a pointer to the + length of this S-expression (used to validate the syntax). Both + are updated to reflect the new position. The token itself is + returned as a pointer into the orginal buffer at TOK and TOKLEN. + If a parentheses is the next token, TOK will be set to NULL. + TOKLEN is checked to be within the bounds. On error a error code + is returned and all pointers should are not guaranteed to point to + a meanigful value. DEPTH should be initialized to 0 and will + reflect on return the actual depth of the tree. To detect the end + of the S-expression it is advisable to check DEPTH after a + successful return. */ +gpg_error_t parse_sexp (unsigned char const **buf, size_t *buflen, + int *depth, unsigned char const **tok, size_t *toklen); + + + #endif /* SCD_TLV_H */ diff --git a/tools/ChangeLog b/tools/ChangeLog index 68b62dd30..76505a6bf 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2005-05-20 Werner Koch <wk@g10code.com> + + * gpg-connect-agent.c (add_definq, show_definq, clear_definq) + (handle_inquire): New. + (read_and_print_response): Handle INQUIRE command. + (main): Implement control commands. + 2005-04-21 Werner Koch <wk@g10code.com> * symcryptrun.c (main): Optionally allow the input file as command @@ -368,7 +375,7 @@ * watchgnupg.c: New. - Copyright 2003, 2004 Free Software Foundation, Inc. + Copyright 2003, 2004, 2005 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 diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 403fa2c45..bb05030ee 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -76,6 +76,23 @@ struct } opt; + +/* Definitions for /definq commands and a global linked list with all + the definitions. */ +struct definq_s +{ + struct definq_s *next; + char *name; /* Name of inquiry or NULL for any name. */ + int is_prog; /* True if this is a program to run. */ + char file[1]; /* Name of file or program. */ +}; +typedef struct definq_s *definq_t; + +static definq_t definq_list; +static definq_t *definq_list_tail = &definq_list; + + + /*-- local prototypes --*/ static int read_and_print_response (assuan_context_t ctx); static assuan_context_t start_agent (void); @@ -129,6 +146,68 @@ i18n_init(void) #endif } +/* Store an inquire response pattern. Note, that this function may + change the content of LINE. We assume that leading white spaces + are already removed. */ +static void +add_definq (char *line, int is_prog) +{ + definq_t d; + char *name, *p; + + /* Get name. */ + name = line; + for (p=name; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + d = xmalloc (sizeof *d + strlen (p) ); + strcpy (d->file, p); + d->is_prog = is_prog; + if ( !strcmp (name, "*")) + d->name = NULL; + else + d->name = xstrdup (name); + + d->next = NULL; + *definq_list_tail = d; + definq_list_tail = &d->next; +} + + +/* Show all inquiry defintions. */ +static void +show_definq (void) +{ + definq_t d; + + for (d=definq_list; d; d = d->next) + if (d->name) + printf ("%-20s %c %s\n", d->name, d->is_prog? 'p':'f', d->file); + for (d=definq_list; d; d = d->next) + if (!d->name) + printf ("%-20s %c %s\n", "*", d->is_prog? 'p':'f', d->file); +} + + +/* Clear all inquiry definitions. */ +static void +clear_definq (void) +{ + while (definq_list) + { + definq_t tmp = definq_list->next; + xfree (definq_list->name); + xfree (definq_list); + definq_list = tmp; + } + definq_list_tail = &definq_list; +} + + /* gpg-connect-agent's entry point. */ int @@ -138,7 +217,7 @@ main (int argc, char **argv) const char *fname; int no_more_options = 0; assuan_context_t ctx; - char *line; + char *line, *p; size_t linesize; int rc; @@ -213,6 +292,57 @@ main (int argc, char **argv) log_info (_("line shortened due to embedded Nul character\n")); if (line[n-1] == '\n') line[n-1] = 0; + if (*line == '/') + { + /* Handle control commands. */ + char *cmd = line+1; + + for (p=cmd; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + if (!strcmp (cmd, "definqfile")) + { + add_definq (p, 0); + } + else if (!strcmp (cmd, "definqprog")) + { + add_definq (p, 1); + } + else if (!strcmp (cmd, "showdef")) + { + show_definq (); + } + else if (!strcmp (cmd, "cleardef")) + { + clear_definq (); + } + else if (!strcmp (cmd, "echo")) + { + puts (p); + } + else if (!strcmp (cmd, "help")) + { + puts ("Available commands:\n" + "/echo ARGS Echo ARGS.\n" + "/definqfile NAME FILE\n" + " Use content of FILE for inquiries with NAME.\n" + " NAME may be \"*\" to match any inquiry.\n" + "/definqprog NAME PGM\n" + " Run PGM for inquiries matching NAME and pass the\n" + " entire line to it as arguments.\n" + "/showdef Print all definitions.\n" + "/cleardef Delete all definitions.\n" + "/help Print this help."); + } + else + log_error (_("unknown command `%s'\n"), cmd ); + + continue; + } + rc = assuan_write_line (ctx, line); if (rc) { @@ -234,6 +364,94 @@ main (int argc, char **argv) } +/* Handle an Inquire from the server. Return False if it could not be + handled; in this case the caller shll complete the operation. LINE + is the complete line as received from the server. This function + may change the content of LINE. */ +static int +handle_inquire (assuan_context_t ctx, char *line) +{ + const char *name; + definq_t d; + FILE *fp; + char buffer[1024]; + int rc, n; + + /* Skip the command and trailing spaces. */ + for (; *line && !spacep (line); line++) + ; + while (spacep (line)) + line++; + /* Get the name. */ + name = line; + for (; *line && !spacep (line); line++) + ; + if (*line) + *line++ = 0; + + /* Now match it against our list. he second loop is todetect the + match all entry. **/ + for (d=definq_list; d; d = d->next) + if (d->name && !strcmp (d->name, name)) + break; + if (!d) + for (d=definq_list; d; d = d->next) + if (!d->name) + break; + if (!d) + { + if (opt.verbose) + log_info ("no handler for inquiry `%s' found\n", name); + return 0; + } + + if (d->is_prog) + { + fp = popen (d->file, "r"); + if (!fp) + log_error ("error executing `%s': %s\n", d->file, strerror (errno)); + else if (opt.verbose) + log_error ("handling inquiry `%s' by running `%s'\n", name, d->file); + } + else + { + fp = fopen (d->file, "rb"); + if (!fp) + log_error ("error opening `%s': %s\n", d->file, strerror (errno)); + else if (opt.verbose) + log_error ("handling inquiry `%s' by returning content of `%s'\n", + name, d->file); + } + if (!fp) + return 0; + + while ( (n = fread (buffer, 1, sizeof buffer, fp)) ) + { + rc = assuan_send_data (ctx, buffer, n); + if (rc) + { + log_error ("sending data back failed: %s\n", assuan_strerror (rc) ); + break; + } + } + if (ferror (fp)) + log_error ("error reading from `%s': %s\n", d->file, strerror (errno)); + + rc = assuan_send_data (ctx, NULL, 0); + if (rc) + log_error ("sending data back failed: %s\n", assuan_strerror (rc) ); + + if (d->is_prog) + { + if (pclose (fp)) + log_error ("error running `%s': %s\n", d->file, strerror (errno)); + } + else + fclose (fp); + return 1; +} + + /* Read all response lines from server and print them. Returns 0 on success or an assuan error code. */ static int @@ -325,7 +543,8 @@ read_and_print_response (assuan_context_t ctx) { fwrite (line, linelen, 1, stdout); putchar ('\n'); - return 0; + if (!handle_inquire (ctx, line)) + assuan_write_line (ctx, "CANCEL"); } else if (linelen >= 3 && line[0] == 'E' && line[1] == 'N' && line[2] == 'D' -- cgit v1.2.3 From 05e1dc22f0feef8d5af7c8bbb0c0a5129f2c0b05 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sat, 21 May 2005 18:49:00 +0000 Subject: * call-scd.c (start_scd): Don't test for an alive scdaemon here. (agent_scd_check_aliveness): New. * gpg-agent.c (handle_tick): Test for an alive scdaemon. (handle_signal): Print thread info on SIGUSR1. * scdaemon.c (handle_signal): Print thread info on SIGUSR1. --- NEWS | 5 ++++ TODO | 15 +++++++++++ agent/ChangeLog | 7 +++++ agent/agent.h | 1 + agent/call-scd.c | 81 ++++++++++++++++++++++++++++++++++++++++--------------- agent/gpg-agent.c | 8 +++++- scd/ChangeLog | 4 +++ scd/app-openpgp.c | 2 +- scd/scdaemon.c | 3 ++- 9 files changed, 101 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index c25bbe08e..79a74cbe4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ Noteworthy changes in version 1.9.17 ------------------------------------------------- + * gpg-connect-agent has now features to handle Assuan INQUIRE + commands. + + * Internal changes for OpenPGP cards. New Assuan command WRITEKEY. + * GNU Pth is now a hard requirement. * [scdaemon] Support for OpenSC has been removed. Instead a new and diff --git a/TODO b/TODO index 6e8951f03..fe10e9f77 100644 --- a/TODO +++ b/TODO @@ -67,6 +67,11 @@ might want to have an agent context for each service request * sm/export.c ** Return an error code or a status info per user ID. +* scd/tlv.c + The parse_sexp fucntion should not go into this file. Check whether + we can change all S-expression handling code to make use of this + function. + * tests ** Makefile.am We use printf(1) to setup the library path, this is not portable. @@ -89,3 +94,13 @@ might want to have an agent context for each service request This means we can't reread a configuration ** No card status notifications. + + +* IMPORTANT: + Check that the PIN cache is cleared after failed card operations. + After receiving a HUP gpg-agent should set a flag to kill scdaemon + as soon as possible, w/o that scdaemon will continue running as a + zombie and gpg-agent won't be able to fire up a new one. + Implement an scd/agent option to wait for a card. + + diff --git a/agent/ChangeLog b/agent/ChangeLog index 015b0b6d8..6c271c8e2 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,10 @@ +2005-05-21 Werner Koch <wk@g10code.com> + + * call-scd.c (start_scd): Don't test for an alive scdaemon here. + (agent_scd_check_aliveness): New. + * gpg-agent.c (handle_tick): Test for an alive scdaemon. + (handle_signal): Print thread info on SIGUSR1. + 2005-05-20 Werner Koch <wk@g10code.com> * protect-tool.c: New option --canonical. diff --git a/agent/agent.h b/agent/agent.h index 6ab65eeba..7e4f555e8 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -247,6 +247,7 @@ int divert_generic_cmd (ctrl_t ctrl, /*-- call-scd.c --*/ void initialize_module_call_scd (void); +void agent_scd_check_aliveness (void); int agent_reset_scd (ctrl_t ctrl); int agent_card_learn (ctrl_t ctrl, void (*kpinfo_cb)(void*, const char *), diff --git a/agent/call-scd.c b/agent/call-scd.c index fc81e2fa3..617ef0d48 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -185,26 +185,15 @@ start_scd (ctrl_t ctrl) } ctrl->scd_local->locked++; - /* If we already have a context, we better do a sanity check now to - see whether it has accidently died. This avoids annoying - timeouts and hung connections. */ if (ctrl->scd_local->ctx) - { - pid_t pid; -#ifndef HAVE_W32_SYSTEM - pid = assuan_get_pid (ctrl->scd_local->ctx); - if (pid != (pid_t)(-1) && pid - && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) - { - assuan_disconnect (ctrl->scd_local->ctx); - ctrl->scd_local->ctx = NULL; - } - else -#endif - return 0; /* Okay, the context is fine. */ - } + return 0; /* Okay, the context is fine. We used to test for an + alive context here and do an disconnect. How that we + have a ticker function to check for it, it is easier + not to check here but to let the connection run on an + error instead. */ - /* We need to protect the lowwing code. */ + + /* We need to protect the following code. */ if (!pth_mutex_acquire (&start_scd_lock, 0, NULL)) { log_error ("failed to acquire the start_scd lock: %s\n", @@ -350,6 +339,50 @@ start_scd (ctrl_t ctrl) } +/* Check whether the Scdaemon is still alive and clean it up if not. */ +void +agent_scd_check_aliveness (void) +{ + pid_t pid; + int rc; + + /* We can do so only if there is no more active primary connection. + With an active primary connection, this is all no problem because + with the end of gpg-agent's session a disconnect is send and the + this function will be used at a later time. */ + if (!primary_scd_ctx || !primary_scd_ctx_reusable) + return; + + if (!pth_mutex_acquire (&start_scd_lock, 0, NULL)) + { + log_error ("failed to acquire the start_scd lock while" + " doing an aliveness check: %s\n", + strerror (errno)); + return; + } + + if (primary_scd_ctx && primary_scd_ctx_reusable) + { + pid = assuan_get_pid (primary_scd_ctx); + if (pid != (pid_t)(-1) && pid + && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) + { + /* Okay, scdaemon died. Disconnect the primary connection now + but take care that it won't do another wait. */ + assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1); + assuan_disconnect (primary_scd_ctx); + primary_scd_ctx = NULL; + primary_scd_ctx_reusable = 0; + xfree (socket_name); + socket_name = NULL; + } + } + + if (!pth_mutex_release (&start_scd_lock)) + log_error ("failed to release the start_scd lock while" + " doing the aliveness check: %s\n", strerror (errno)); +} + /* Reset the SCD if it has been used. */ int @@ -359,15 +392,19 @@ agent_reset_scd (ctrl_t ctrl) { if (ctrl->scd_local->ctx) { - /* We can't disconnect the primary context becuase libassuan + /* We can't disconnect the primary context because libassuan does a waitpid on it and thus the system would hang. Instead we send a reset and keep that connection for reuse. */ if (ctrl->scd_local->ctx == primary_scd_ctx) { - if (!assuan_transact (primary_scd_ctx, "RESET", - NULL, NULL, NULL, NULL, NULL, NULL)) - primary_scd_ctx_reusable = 1; + /* The RESET may fail for example if the scdaemon has + already been terminated. We need to set the reusable + flag anyway to make sure that the aliveness check can + clean it up. */ + assuan_transact (primary_scd_ctx, "RESET", + NULL, NULL, NULL, NULL, NULL, NULL); + primary_scd_ctx_reusable = 1; } else assuan_disconnect (ctrl->scd_local->ctx); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 4ac995c26..e3e952906 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1270,6 +1270,11 @@ create_directories (void) static void handle_tick (void) { + /* Check whether the scdaemon has dies and cleanup in this case. */ + agent_scd_check_aliveness (); + + /* If we are running as a child of another process, check whether + the parent is still alive and shutdwon if now. */ #ifndef HAVE_W32_SYSTEM if (parent_pid != (pid_t)(-1)) { @@ -1301,7 +1306,8 @@ handle_signal (int signo) break; case SIGUSR1: - log_info ("SIGUSR1 received - no action defined\n"); + log_info ("SIGUSR1 received - printing internal information:\n"); + pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); break; case SIGUSR2: diff --git a/scd/ChangeLog b/scd/ChangeLog index c64fbec7e..feeaabfce 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2005-05-21 Werner Koch <wk@g10code.com> + + * scdaemon.c (handle_signal): Print thread info on SIGUSR1. + 2005-05-20 Werner Koch <wk@g10code.com> * ccid-driver.c: Replaced macro DEBUG_T1 by a new debug level. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 16ebd34c8..1165ec683 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1634,7 +1634,7 @@ do_writekey (app_t app, ctrl_t ctrl, log_info ("protected-private-key passed to writekey\n"); else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen)) log_info ("shadowed-private-key passed to writekey\n"); - err = gpg_error (GPG_ERR_BAD_KEY); + err = gpg_error (GPG_ERR_BAD_SECKEY); goto leave; } if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))) diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 1110d9d76..488a4853b 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -807,7 +807,8 @@ handle_signal (int signo) break; case SIGUSR1: - log_info ("SIGUSR1 received - no action defined\n"); + log_info ("SIGUSR1 received - printing internal information:\n"); + pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); break; case SIGUSR2: -- cgit v1.2.3 From 487e41999020c139802df4a7ee0baad1577f0cc5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 23 May 2005 14:17:22 +0000 Subject: (parse_ccid_descriptor): SCR335 FW version 5.14 is good. (do_close_reader): Never do a reset. The caller should instead make sure that the reader has been closed properly. The new retry code in ccid_slot_status will make sure that the readersatrts up fine even if the last process didn't closed the USB connection properly. (ccid_get_atr): For certain readers try switching to ISO mode. Thanks to Ludovic Rousseau for this hint and the magic numbers. (print_command_failed): New. (bulk_in): Use it here. Add new arg NO_DEBUG. --- scd/ChangeLog | 14 ++++++ scd/ccid-driver.c | 127 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 119 insertions(+), 22 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index feeaabfce..91603f61b 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,17 @@ +2005-05-23 Werner Koch <wk@g10code.com> + + * ccid-driver.c (parse_ccid_descriptor): SCR335 FW version 5.14 is + good. + (do_close_reader): Never do a reset. The caller should instead + make sure that the reader has been closed properly. The new retry + code in ccid_slot_status will make sure that the readersatrts up + fine even if the last process didn't closed the USB connection + properly. + (ccid_get_atr): For certain readers try switching to ISO mode. + Thanks to Ludovic Rousseau for this hint and the magic numbers. + (print_command_failed): New. + (bulk_in): Use it here. Add new arg NO_DEBUG. + 2005-05-21 Werner Koch <wk@g10code.com> * scdaemon.c (handle_signal): Print thread info on SIGUSR1. diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 387108559..9ac655e63 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -184,9 +184,18 @@ enum { }; +/* Two macro to detect whether a CCID command has failed and to get + the error code. These macros assume that we can access the + mandatory first 10 bytes of a CCID message in BUF. */ +#define CCID_COMMAND_FAILED(buf) ((buf)[7] & 0x40) +#define CCID_ERROR_CODE(buf) (((unsigned char *)(buf))[8]) + + /* We need to know the vendor to do some hacks. */ enum { - VENDOR_SCM = 0x04e6 + VENDOR_SCM = 0x04e6, + VENDOR_CHERRY = 0x046a, + VENDOR_GEMPC = 0x08e6 }; @@ -228,7 +237,8 @@ static unsigned int compute_edc (const unsigned char *data, size_t datalen, int use_crc); static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen); static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, - size_t *nread, int expected_type, int seqno, int timeout); + size_t *nread, int expected_type, int seqno, int timeout, + int no_debug); /* Convert a little endian stored 4 byte value into an unsigned integer. */ @@ -248,6 +258,53 @@ set_msg_len (unsigned char *msg, unsigned int length) } +/* Pint an error message for a failed CCID command including a textual + error code. MSG is shall be the CCID message of at least 10 bytes. */ +static void +print_command_failed (const unsigned char *msg) +{ + const char *t; + char buffer[100]; + int ec; + + if (!debug_level) + return; + + ec = CCID_ERROR_CODE (msg); + switch (ec) + { + case 0x00: t = "Command not supported"; break; + + case 0xE0: t = "Slot busy"; break; + case 0xEF: t = "PIN cancelled"; break; + case 0xF0: t = "PIN timeout"; break; + + case 0xF2: t = "Automatic sequence ongoing"; break; + case 0xF3: t = "Deactivated Protocol"; break; + case 0xF4: t = "Procedure byte conflict"; break; + case 0xF5: t = "ICC class not supported"; break; + case 0xF6: t = "ICC protocol not supported"; break; + case 0xF7: t = "Bad checksum in ATR"; break; + case 0xF8: t = "Bad TS in ATR"; break; + + case 0xFB: t = "An all inclusive hardware error occurred"; break; + case 0xFC: t = "Overrun error while talking to the ICC"; break; + case 0xFD: t = "Parity error while talking to the ICC"; break; + case 0xFE: t = "CCID timed out while talking to the ICC"; break; + case 0xFF: t = "Host aborted the current activity"; break; + + default: + if (ec > 0 && ec < 128) + sprintf (buffer, "Parameter error at offset %d", ec); + else + sprintf (buffer, "Error code %02X", ec); + t = buffer; + break; + } + DEBUGOUT_1 ("CCID command failed: %s\n", t); +} + + /* Parse a CCID descriptor, optionally print all available features @@ -462,7 +519,7 @@ parse_ccid_descriptor (ccid_driver_t handle, && handle->max_ifsd > 48 && ( (handle->id_product == 0xe001 && handle->bcd_device < 0x0516) ||(handle->id_product == 0x5111 && handle->bcd_device < 0x0620) - ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0518) + ||(handle->id_product == 0x5115 && handle->bcd_device < 0x0514) ||(handle->id_product == 0xe003 && handle->bcd_device < 0x0504) )) { @@ -987,13 +1044,11 @@ do_close_reader (ccid_driver_t handle) rc = bulk_out (handle, msg, msglen); if (!rc) bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, - seqno, 2000); + seqno, 2000, 0); handle->powered_off = 1; } if (handle->idev) { - if (getenv ("GNUPG_CCID_DRIVER_RESET_BEFORE_CLOSE")) - usb_reset (handle->idev); usb_release_interface (handle->idev, handle->ifc_no); usb_close (handle->idev); handle->idev = NULL; @@ -1117,10 +1172,12 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) BUFFER and return the actual read number if bytes in NREAD. SEQNO is the sequence number used to send the request and EXPECTED_TYPE the type of message we expect. Does checks on the ccid - header. TIMEOUT is the timeout value in ms. Returns 0 on success. */ + header. TIMEOUT is the timeout value in ms. NO_DEBUG may be set to + avoid debug messages in case of no error. Returns 0 on success. */ static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, - size_t *nread, int expected_type, int seqno, int timeout) + size_t *nread, int expected_type, int seqno, int timeout, + int no_debug) { int i, rc; size_t msglen; @@ -1170,13 +1227,19 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, buffer[7], buffer[8]); goto retry; } - - DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n" - " data:", buffer[7], buffer[8], buffer[9] ); - for (i=10; i < msglen; i++) - DEBUGOUT_CONT_1 (" %02X", buffer[i]); - DEBUGOUT_LF (); + if (!no_debug) + { + DEBUGOUT_3 ("status: %02X error: %02X octet[9]: %02X\n" + " data:", buffer[7], buffer[8], buffer[9] ); + for (i=10; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", buffer[i]); + DEBUGOUT_LF (); + } + if (CCID_COMMAND_FAILED (buffer)) + print_command_failed (buffer); + + /* Check whether a card is at all available. */ switch ((buffer[7] & 0x03)) { case 0: /* no error */ break; @@ -1220,7 +1283,7 @@ send_escape_cmd (ccid_driver_t handle, if (rc) return rc; rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, - seqno, 5000); + seqno, 5000, 0); return rc; } @@ -1304,8 +1367,11 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits) rc = bulk_out (handle, msg, 10); if (rc) return rc; + /* Note that we set the NO_DEBUG flag here, so that the logs won't + get cluttered up by a ticker function checking for the slot + status and debugging enabled. */ rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, - seqno, retries? 1000 : 200); + seqno, retries? 1000 : 200, 1); if (rc == CCID_DRIVER_ERR_CARD_IO_ERROR && retries < 3) { if (!retries) @@ -1341,6 +1407,7 @@ ccid_get_atr (ccid_driver_t handle, int use_crc = 0; unsigned int edc; int i; + int tried_iso = 0; /* First check whether a card is available. */ rc = ccid_slot_status (handle, &statusbits); @@ -1351,6 +1418,7 @@ ccid_get_atr (ccid_driver_t handle, /* For an inactive and also for an active card, issue the PowerOn command to get the ATR. */ + again: msg[0] = PC_to_RDR_IccPowerOn; msg[5] = 0; /* slot */ msg[6] = seqno = handle->seqno++; @@ -1364,9 +1432,24 @@ ccid_get_atr (ccid_driver_t handle, if (rc) return rc; rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, - seqno, 5000); + seqno, 5000, 0); if (rc) return rc; + if (!tried_iso && CCID_COMMAND_FAILED (msg) && CCID_ERROR_CODE (msg) == 0xbb + && ((handle->id_vendor == VENDOR_CHERRY + && handle->id_product == 0x0005) + || (handle->id_vendor == VENDOR_GEMPC + && handle->id_product == 0x4433) + )) + { + tried_iso = 1; + /* Try switching to ISO mode. */ + if (!send_escape_cmd (handle, "\xF1\x01", 2)) + goto again; + } + else if (CCID_COMMAND_FAILED (msg)) + return CCID_DRIVER_ERR_CARD_IO_ERROR; + handle->powered_off = 0; @@ -1409,7 +1492,7 @@ ccid_get_atr (ccid_driver_t handle, return rc; /* Note that we ignore the error code on purpose. */ bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, - seqno, 5000); + seqno, 5000, 0); handle->t1_ns = 0; handle->t1_nr = 0; @@ -1457,7 +1540,7 @@ ccid_get_atr (ccid_driver_t handle, rc = bulk_in (handle, msg, sizeof msg, &msglen, - RDR_to_PC_DataBlock, seqno, 5000); + RDR_to_PC_DataBlock, seqno, 5000, 0); if (rc) return rc; @@ -1554,7 +1637,7 @@ ccid_transceive_apdu_level (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno, 5000); + RDR_to_PC_DataBlock, seqno, 5000, 0); if (rc) return rc; @@ -1728,7 +1811,7 @@ ccid_transceive (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno, 5000); + RDR_to_PC_DataBlock, seqno, 5000, 0); if (rc) return rc; @@ -2005,7 +2088,7 @@ ccid_transceive_secure (ccid_driver_t handle, msg = recv_buffer; rc = bulk_in (handle, msg, sizeof recv_buffer, &msglen, - RDR_to_PC_DataBlock, seqno, 5000); + RDR_to_PC_DataBlock, seqno, 5000, 0); if (rc) return rc; -- cgit v1.2.3 From a43586d0e81b538009fc86f260592e52d54ef42c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 23 May 2005 20:18:13 +0000 Subject: * Makefile.am: Do not build sc-copykeys anymore. * app-openpgp.c (app_openpgp_storekey, app_openpgp_readkey) (app_openpgp_cardinfo): Removed. --- doc/scdaemon.texi | 31 +++++++- scd/ChangeLog | 6 ++ scd/Makefile.am | 37 +++++----- scd/app-common.h | 17 ----- scd/app-openpgp.c | 212 ------------------------------------------------------ scd/command.c | 20 +++++- 6 files changed, 73 insertions(+), 250 deletions(-) diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index f069a9fb8..134ca40df 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -478,12 +478,39 @@ TO BE WRITTEN. @node Scdaemon PASSWD @subsection Change PINs. -TO BE WRITTEN. +@example + PASSWD [--reset] @var{chvno} +@end example + +Change the PIN or reset the retry counter of the card holder +verification vector number @var{chvno}. @node Scdaemon CHECKPIN @subsection Perform a VERIFY operation. -TO BE WRITTEN. +@example + CHECKPIN @var{idstr} +@end example + +Perform a VERIFY operation without doing anything else. This may be +used to initialize a the PIN cache earlier to long lasting +operations. Its use is highly application dependent: + +@table @strong +@item OpenPGP + +Perform a simple verify operation for CHV1 and CHV2, so that further +operations won't ask for CHV2 and it is possible to do a cheap check on +the PIN: If there is something wrong with the PIN entry system, only the +regular CHV will get blocked and not the dangerous CHV3. @var{idstr} is +the usual card's serial number in hex notation; an optional fingerprint +part will get ignored. + +There is however a special mode if @var{idstr} is suffixed with the +literal string @code{[CHV3]}: In this case the Admin PIN is checked if +and only if the retry counter is still at 3. + +@end table diff --git a/scd/ChangeLog b/scd/ChangeLog index 91603f61b..64a4a8b72 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,5 +1,10 @@ 2005-05-23 Werner Koch <wk@g10code.com> + * Makefile.am: Do not build sc-copykeys anymore. + + * app-openpgp.c (app_openpgp_storekey, app_openpgp_readkey) + (app_openpgp_cardinfo): Removed. + * ccid-driver.c (parse_ccid_descriptor): SCR335 FW version 5.14 is good. (do_close_reader): Never do a reset. The caller should instead @@ -11,6 +16,7 @@ Thanks to Ludovic Rousseau for this hint and the magic numbers. (print_command_failed): New. (bulk_in): Use it here. Add new arg NO_DEBUG. + (ccid_slot_status): Disabled debugging. 2005-05-21 Werner Koch <wk@g10code.com> diff --git a/scd/Makefile.am b/scd/Makefile.am index c3688da5f..e76f83ea4 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -18,7 +18,7 @@ ## Process this file with automake to produce Makefile.in -bin_PROGRAMS = scdaemon sc-copykeys +bin_PROGRAMS = scdaemon if ! HAVE_W32_SYSTEM pkglib_PROGRAMS = pcsc-wrapper endif @@ -47,22 +47,25 @@ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ $(LIBUSB_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) -sc_copykeys_SOURCES = \ - sc-copykeys.c scdaemon.h \ - apdu.c apdu.h \ - ccid-driver.c ccid-driver.h \ - iso7816.c iso7816.h \ - tlv.c tlv.h \ - atr.c atr.h \ - app.c app-common.h app-help.c $(card_apps) - -sc_copykeys_LDADD = \ - ../jnlib/libjnlib.a ../common/libcommon.a \ - ../common/libsimple-pwquery.a \ - $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) \ - -lgpg-error @LIBINTL@ @DL_LIBS@ - +# Removed for now: We need to decide whether it makes sense to +# continue it at all, given that gpg has now all required +# functionality. +#sc_copykeys_SOURCES = \ +# sc-copykeys.c scdaemon.h \ +# apdu.c apdu.h \ +# ccid-driver.c ccid-driver.h \ +# iso7816.c iso7816.h \ +# tlv.c tlv.h \ +# atr.c atr.h \ +# app.c app-common.h app-help.c $(card_apps) +# +#sc_copykeys_LDADD = \ +# ../jnlib/libjnlib.a ../common/libcommon.a \ +# ../common/libsimple-pwquery.a \ +# $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) \ +# $(LIBUSB_LIBS) \ +# -lgpg-error @LIBINTL@ @DL_LIBS@ +# pcsc_wrapper_SOURCES = pcsc-wrapper.c pcsc_wrapper_LDADD = $(DL_LIBS) pcsc_wrapper_CFLAGS = diff --git a/scd/app-common.h b/scd/app-common.h index c2c302395..613ad61f6 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -176,23 +176,6 @@ gpg_error_t app_check_pin (app_t app, const char *keyidstr, /*-- app-openpgp.c --*/ gpg_error_t app_select_openpgp (app_t app); -gpg_error_t app_openpgp_cardinfo (app_t app, - char **serialno, - char **disp_name, - char **pubkey_url, - unsigned char **fpr1, - unsigned char **fpr2, - unsigned char **fpr3); -gpg_error_t app_openpgp_storekey (app_t app, int keyno, - unsigned char *template, size_t template_len, - time_t created_at, - const unsigned char *m, size_t mlen, - const unsigned char *e, size_t elen, - gpg_error_t (*pincb)(void*, const char *, char **), - void *pincb_arg); -gpg_error_t app_openpgp_readkey (app_t app, int keyno, - unsigned char **m, size_t *mlen, - unsigned char **e, size_t *elen); /*-- app-nks.c --*/ gpg_error_t app_select_nks (app_t app); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 1165ec683..91e208a0a 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -2521,215 +2521,3 @@ leave: -/* This function is a hack to retrieve essential information about the - card to be displayed by simple tools. It mostly resembles what the - LEARN command returns. All parameters return allocated strings or - buffers or NULL if the data object is not available. All returned - values are sanitized. */ -gpg_error_t -app_openpgp_cardinfo (app_t app, - char **serialno, - char **disp_name, - char **pubkey_url, - unsigned char **fpr1, - unsigned char **fpr2, - unsigned char **fpr3) -{ - int rc; - void *relptr; - unsigned char *value; - size_t valuelen; - - if (serialno) - { - time_t dummy; - - *serialno = NULL; - rc = app_get_serial_and_stamp (app, serialno, &dummy); - if (rc) - { - log_error (_("error getting serial number: %s\n"), - gpg_strerror (rc)); - return rc; - } - } - - if (disp_name) - { - *disp_name = NULL; - relptr = get_one_do (app, 0x005B, &value, &valuelen, NULL); - if (relptr) - { - *disp_name = make_printable_string (value, valuelen, 0); - xfree (relptr); - } - } - - if (pubkey_url) - { - *pubkey_url = NULL; - relptr = get_one_do (app, 0x5F50, &value, &valuelen, NULL); - if (relptr) - { - *pubkey_url = make_printable_string (value, valuelen, 0); - xfree (relptr); - } - } - - if (fpr1) - *fpr1 = NULL; - if (fpr2) - *fpr2 = NULL; - if (fpr3) - *fpr3 = NULL; - relptr = get_one_do (app, 0x00C5, &value, &valuelen, NULL); - if (relptr && valuelen >= 60) - { - if (fpr1) - { - *fpr1 = xmalloc (20); - memcpy (*fpr1, value + 0, 20); - } - if (fpr2) - { - *fpr2 = xmalloc (20); - memcpy (*fpr2, value + 20, 20); - } - if (fpr3) - { - *fpr3 = xmalloc (20); - memcpy (*fpr3, value + 40, 20); - } - } - xfree (relptr); - - return 0; -} - - - -/* This function is currently only used by the sc-copykeys program to - store a key on the smartcard. app_t ist the application handle, - KEYNO is the number of the key and PINCB, PINCB_ARG are used to ask - for the SO PIN. TEMPLATE and TEMPLATE_LEN describe a buffer with - the key template to store. CREATED_AT is the timestamp used to - create the fingerprint. M, MLEN is the RSA modulus and E, ELEN the - RSA public exponent. This function silently overwrites an existing - key.*/ -gpg_error_t -app_openpgp_storekey (app_t app, int keyno, - unsigned char *template, size_t template_len, - time_t created_at, - const unsigned char *m, size_t mlen, - const unsigned char *e, size_t elen, - gpg_error_t (*pincb)(void*, const char *, char **), - void *pincb_arg) -{ - int rc; - unsigned char fprbuf[20]; - - if (keyno < 1 || keyno > 3) - return gpg_error (GPG_ERR_INV_ID); - keyno--; - - rc = verify_chv3 (app, pincb, pincb_arg); - if (rc) - goto leave; - - flush_cache (app); - - xfree (app->app_local->pk[keyno].key); - app->app_local->pk[keyno].key = NULL; - app->app_local->pk[keyno].keylen = 0; - app->app_local->pk[keyno].read_done = 0; - - rc = iso7816_put_data (app->slot, - (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, - template, template_len); - if (rc) - { - log_error (_("failed to store the key: %s\n"), gpg_strerror (rc)); - rc = gpg_error (GPG_ERR_CARD); - goto leave; - } - -/* log_printhex ("RSA n:", m, mlen); */ -/* log_printhex ("RSA e:", e, elen); */ - - rc = store_fpr (app->slot, keyno, (u32)created_at, - m, mlen, e, elen, fprbuf, app->card_version); - - leave: - return rc; -} - - -/* Utility function for external tools: Read the public RSA key at - KEYNO and return modulus and exponent in (M,MLEN) and (E,ELEN). */ -gpg_error_t -app_openpgp_readkey (app_t app, int keyno, unsigned char **m, size_t *mlen, - unsigned char **e, size_t *elen) -{ - int rc; - const unsigned char *keydata, *a; - unsigned char *buffer; - size_t buflen, keydatalen, alen; - - *m = NULL; - *e = NULL; - - if (keyno < 1 || keyno > 3) - return gpg_error (GPG_ERR_INV_ID); - keyno--; - - rc = iso7816_read_public_key(app->slot, - keyno == 0? "\xB6" : - keyno == 1? "\xB8" : "\xA4", - 2, - &buffer, &buflen); - if (rc) - { - rc = gpg_error (GPG_ERR_CARD); - log_error (_("reading the key failed\n")); - goto leave; - } - - keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen); - if (!keydata) - { - log_error (_("response does not contain the public key data\n")); - rc = gpg_error (GPG_ERR_CARD); - goto leave; - } - - a = find_tlv (keydata, keydatalen, 0x0081, &alen); - if (!a) - { - log_error (_("response does not contain the RSA modulus\n")); - rc = gpg_error (GPG_ERR_CARD); - goto leave; - } - *mlen = alen; - *m = xmalloc (alen); - memcpy (*m, a, alen); - - a = find_tlv (keydata, keydatalen, 0x0082, &alen); - if (!a) - { - log_error (_("response does not contain the RSA public exponent\n")); - rc = gpg_error (GPG_ERR_CARD); - goto leave; - } - *elen = alen; - *e = xmalloc (alen); - memcpy (*e, a, alen); - - leave: - xfree (buffer); - if (rc) - { - xfree (*m); *m = NULL; - xfree (*e); *e = NULL; - } - return rc; -} diff --git a/scd/command.c b/scd/command.c index c68d0e925..738b1f003 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1095,7 +1095,7 @@ cmd_random (assuan_context_t ctx, char *line) /* PASSWD [--reset] <chvno> - Change the PIN or reset thye retry counter of the card holder + Change the PIN or reset the retry counter of the card holder verfication vector CHVNO. */ static int cmd_passwd (assuan_context_t ctx, char *line) @@ -1142,7 +1142,23 @@ cmd_passwd (assuan_context_t ctx, char *line) } -/* CHECKPIN <hexified_id> +/* CHECKPIN <idstr> + + Perform a VERIFY operation without doing anything else. This may + be used to initialize a the PIN cache earlier to long lasting + operations. Its use is highly application dependent. + + For OpenPGP: + + Perform a simple verify operation for CHV1 and CHV2, so that + further operations won't ask for CHV2 and it is possible to do a + cheap check on the PIN: If there is something wrong with the PIN + entry system, only the regular CHV will get blocked and not the + dangerous CHV3. IDSTR is the usual card's serial number in hex + notation; an optional fingerprint part will get ignored. There + is however a special mode if the IDSTR is sffixed with the + literal string "[CHV3]": In this case the Admin PIN is checked + if and only if the retry counter is still at 3. */ static int -- cgit v1.2.3 From e96af3715b9b126b435c7887e47a660a73bf237b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 24 May 2005 12:37:36 +0000 Subject: * call-scd.c (inq_needpin): Skip leading spaces in of PIN description. * divert-scd.c (getpin_cb): Enhanced to cope with description flags. * query.c (agent_askpin): Add arg PROMPT_TEXT. Changed all callers. --- TODO | 8 ----- agent/ChangeLog | 9 +++++ agent/agent.h | 3 +- agent/call-scd.c | 2 ++ agent/command-ssh.c | 2 +- agent/divert-scd.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++------ agent/findkey.c | 2 +- agent/genkey.c | 8 ++--- agent/query.c | 18 ++++++---- scd/app-openpgp.c | 4 +-- 10 files changed, 121 insertions(+), 35 deletions(-) diff --git a/TODO b/TODO index fe10e9f77..74763a71f 100644 --- a/TODO +++ b/TODO @@ -96,11 +96,3 @@ might want to have an agent context for each service request -* IMPORTANT: - Check that the PIN cache is cleared after failed card operations. - After receiving a HUP gpg-agent should set a flag to kill scdaemon - as soon as possible, w/o that scdaemon will continue running as a - zombie and gpg-agent won't be able to fire up a new one. - Implement an scd/agent option to wait for a card. - - diff --git a/agent/ChangeLog b/agent/ChangeLog index 6c271c8e2..dcf0cdfd3 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2005-05-24 Werner Koch <wk@g10code.com> + + * call-scd.c (inq_needpin): Skip leading spaces in of PIN + description. + * divert-scd.c (getpin_cb): Enhanced to cope with description + flags. + * query.c (agent_askpin): Add arg PROMPT_TEXT. Changed all + callers. + 2005-05-21 Werner Koch <wk@g10code.com> * call-scd.c (start_scd): Don't test for an alive scdaemon here. diff --git a/agent/agent.h b/agent/agent.h index 7e4f555e8..e416914cf 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -179,7 +179,8 @@ int agent_key_available (const unsigned char *grip); /*-- query.c --*/ void initialize_module_query (void); int agent_askpin (ctrl_t ctrl, - const char *desc_text, const char *inital_errtext, + const char *desc_text, const char *prompt_text, + const char *inital_errtext, struct pin_entry_info_s *pininfo); int agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *desc, const char *prompt, diff --git a/agent/call-scd.c b/agent/call-scd.c index 617ef0d48..78e28fe97 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -601,6 +601,8 @@ inq_needpin (void *opaque, const char *line) return ASSUAN_Inquire_Unknown; } line += 7; + while (*line == ' ') + line++; pinlen = 90; pin = gcry_malloc_secure (pinlen); diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 92a84c662..030cc70a0 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2369,7 +2369,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) } pi->max_length = 100; pi->max_tries = 1; - err = agent_askpin (ctrl, description, NULL, pi); + err = agent_askpin (ctrl, description, NULL, NULL, pi); if (err) goto out; diff --git a/agent/divert-scd.c b/agent/divert-scd.c index f460ffe0c..41a5dfcda 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -168,35 +168,113 @@ encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo, buf has been allocated by the caller and is of size MAXBUF which includes the terminating null. The function should return an UTF-8 string with the passphrase, the buffer may optionally be padded - with arbitrary characters */ + with arbitrary characters. + + INFO gets displayed as part of a generic string. However if the + first character of INFO is a vertical bar all up to the next + verical bar are considered flags and only everything after the + second vertical bar gets displayed as the full prompt. + + Flags: + + 'N' = New PIN, this requests a second prompt to repeat the the + PIN. If the PIN is not correctly repeated it starts from + all over. + 'A' = The PIN is an Admin PIN, SO-PIN, PUK or alike. + + Example: + + "|AN|Please enter the new security officer's PIN" + + The text "Please ..." will get displayed and the flags 'A' and 'N' + are considered. + */ static int getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) { struct pin_entry_info_s *pi; int rc; - char *desc; - CTRL ctrl = opaque; + ctrl_t ctrl = opaque; + const char *ends, *s; + int any_flags = 0; + int newpin = 0; + const char *again_text = NULL; + const char *prompt = "PIN"; if (maxbuf < 2) return gpg_error (GPG_ERR_INV_VALUE); + /* Parse the flags. */ + if (info && *info =='|' && (ends=strchr (info+1, '|'))) + { + for (s=info+1; s < ends; s++) + { + if (*s == 'A') + prompt = _("Admin PIN"); + else if (*s == 'N') + newpin = 1; + } + info = ends+1; + any_flags = 1; + } + else if (info && *info == '|') + log_debug ("pin_cb called without proper PIN info hack\n"); + /* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole mess because we should call the card's verify function from the pinentry check pin CB. */ - pi = gcry_calloc_secure (1, sizeof (*pi) + 100); + again: + pi = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10); + if (!pi) + return gpg_error_from_errno (errno); pi->max_length = maxbuf-1; pi->min_digits = 0; /* we want a real passphrase */ pi->max_digits = 8; pi->max_tries = 3; - if ( asprintf (&desc, _("Please enter the PIN%s%s%s to unlock the card"), - info? " (`":"", - info? info:"", - info? "')":"") < 0) - desc = NULL; - rc = agent_askpin (ctrl, desc?desc:info, NULL, pi); - free (desc); + if (any_flags) + { + rc = agent_askpin (ctrl, info, prompt, again_text, pi); + again_text = NULL; + if (!rc && newpin) + { + struct pin_entry_info_s *pi2; + pi2 = gcry_calloc_secure (1, sizeof (*pi) + maxbuf + 10); + if (!pi2) + { + rc = gpg_error_from_errno (errno); + xfree (pi); + return rc; + } + pi2->max_length = maxbuf-1; + pi2->min_digits = 0; + pi2->max_digits = 8; + pi2->max_tries = 1; + rc = agent_askpin (ctrl, _("Repeat this PIN"), prompt, NULL, pi2); + if (!rc && strcmp (pi->pin, pi2->pin)) + { + again_text = N_("PIN not correctly repeated; try again"); + xfree (pi2); + xfree (pi); + goto again; + } + xfree (pi2); + } + } + else + { + char *desc; + if ( asprintf (&desc, + _("Please enter the PIN%s%s%s to unlock the card"), + info? " (`":"", + info? info:"", + info? "')":"") < 0) + desc = NULL; + rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi); + free (desc); + } + if (!rc) { strncpy (buf, pi->pin, maxbuf-1); diff --git a/agent/findkey.c b/agent/findkey.c index 0b5816bf5..999a5d620 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -276,7 +276,7 @@ unprotect (CTRL ctrl, const char *desc_text, arg.unprotected_key = NULL; pi->check_cb_arg = &arg; - rc = agent_askpin (ctrl, desc_text, NULL, pi); + rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi); if (!rc) { assert (arg.unprotected_key); diff --git a/agent/genkey.c b/agent/genkey.c index 17d85f77c..e07518d5a 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -120,11 +120,11 @@ agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen, pi2->check_cb_arg = pi->pin; next_try: - rc = agent_askpin (ctrl, text1, initial_errtext, pi); + rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi); initial_errtext = NULL; if (!rc) { - rc = agent_askpin (ctrl, text2, NULL, pi2); + rc = agent_askpin (ctrl, text2, NULL, NULL, pi2); if (rc == -1) { /* The re-entered one did not match and the user did not hit cancel. */ @@ -228,10 +228,10 @@ agent_protect_and_store (CTRL ctrl, gcry_sexp_t s_skey) pi2->check_cb_arg = pi->pin; next_try: - rc = agent_askpin (ctrl, text1, initial_errtext, pi); + rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi); if (!rc) { - rc = agent_askpin (ctrl, text2, NULL, pi2); + rc = agent_askpin (ctrl, text2, NULL, NULL, pi2); if (rc == -1) { /* The re-entered one did not match and the user did not hit cancel. */ diff --git a/agent/query.c b/agent/query.c index 622a2662c..d3b42a416 100644 --- a/agent/query.c +++ b/agent/query.c @@ -288,8 +288,9 @@ all_digitsp( const char *s) number here and repeat it as long as we have invalid formed numbers. */ int -agent_askpin (CTRL ctrl, - const char *desc_text, const char *initial_errtext, +agent_askpin (ctrl_t ctrl, + const char *desc_text, const char *prompt_text, + const char *initial_errtext, struct pin_entry_info_s *pininfo) { int rc; @@ -310,7 +311,10 @@ agent_askpin (CTRL ctrl, desc_text = _("Please enter your passphrase, so that the secret key " "can be unlocked for this session"); - is_pin = desc_text && strstr (desc_text, "PIN"); + if (prompt_text) + is_pin = !!strstr (prompt_text, "PIN"); + else + is_pin = desc_text && strstr (desc_text, "PIN"); rc = start_pinentry (ctrl); if (rc) @@ -322,10 +326,10 @@ agent_askpin (CTRL ctrl, if (rc) return unlock_pinentry (map_assuan_err (rc)); - rc = assuan_transact (entry_ctx, - is_pin? "SETPROMPT PIN:" - : "SETPROMPT Passphrase:", - NULL, NULL, NULL, NULL, NULL, NULL); + snprintf (line, DIM(line)-1, "SETPROMPT %s", + prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:"); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) return unlock_pinentry (map_assuan_err (rc)); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 91e208a0a..14483869b 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1528,7 +1528,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode, /* Check whether a key already exists. KEYIDX is the index of the key - (0..2). If FORCE is TRUE a diagnositivc will be printed but no + (0..2). If FORCE is TRUE a diagnositic will be printed but no error returned if the key already exists. */ static gpg_error_t does_key_exist (app_t app, int keyidx, int force) @@ -2134,7 +2134,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, { char *prompt; -#define PROMPTSTRING _("PIN [sigs done: %lu]") +#define PROMPTSTRING _("||Please enter the PIN%%0A[sigs done: %lu]") prompt = malloc (strlen (PROMPTSTRING) + 50); if (!prompt) -- cgit v1.2.3 From c8efd2bf77a96a068e5c1d81c6e6e1b6b518ae97 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sat, 28 May 2005 13:43:21 +0000 Subject: 2005-05-28 Moritz Schulte <moritz@g10code.com> * gpgkey2ssh.c: New file. * Makefile.am (bin_PROGRAMS): Added gpgkey2ssh. --- tools/ChangeLog | 5 + tools/Makefile.am | 5 +- tools/gpgkey2ssh.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 tools/gpgkey2ssh.c diff --git a/tools/ChangeLog b/tools/ChangeLog index 76505a6bf..085ba094f 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2005-05-28 Moritz Schulte <moritz@g10code.com> + + * gpgkey2ssh.c: New file. + * Makefile.am (bin_PROGRAMS): Added gpgkey2ssh. + 2005-05-20 Werner Koch <wk@g10code.com> * gpg-connect-agent.c (add_definq, show_definq, clear_definq) diff --git a/tools/Makefile.am b/tools/Makefile.am index b0a477910..6d2d2e741 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -36,7 +36,7 @@ else symcryptrun = endif -bin_PROGRAMS = gpgconf gpg-connect-agent ${symcryptrun} +bin_PROGRAMS = gpgconf gpg-connect-agent gpgkey2ssh ${symcryptrun} if !HAVE_W32_SYSTEM bin_PROGRAMS += watchgnupg endif @@ -56,3 +56,6 @@ gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c gpg_connect_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) +gpgkey2ssh_SOURCES = gpgkey2ssh.c +gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) +gpgkey2ssh_LDADD = ../common/libcommon.a $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) diff --git a/tools/gpgkey2ssh.c b/tools/gpgkey2ssh.c new file mode 100644 index 000000000..75b18b29b --- /dev/null +++ b/tools/gpgkey2ssh.c @@ -0,0 +1,294 @@ +/* gpgkey2ssh.c - Converter ... + Copyright (C) 2005 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 <gcrypt.h> +#include <unistd.h> +#include <stdlib.h> +#include <assert.h> +#include <stdio.h> +#include <errno.h> + +#include "util.h" + + + +typedef struct pkdbuf +{ + unsigned char *buffer; + size_t buffer_n; +} pkdbuf_t; + + + +/* Retrieve the public key material for the RSA key, whose fingerprint + is FPR, from gpg output, which can be read through the stream FP. + The RSA modulus will be stored at the address of M and MLEN, the + public exponent at E and ELEN. Returns zero on success, an error + code on failure. Caller must release the allocated buffers at M + and E if the function returns success. */ +static gpg_error_t +retrieve_key_material (FILE *fp, const char *hexkeyid, int *algorithm_id, + pkdbuf_t **pkdbuf, size_t *pkdbuf_n) +{ + pkdbuf_t *pkdbuf_new; + pkdbuf_t *pkdbuf_tmp; + size_t pkdbuf_new_n; + gcry_error_t err = 0; + char *line = NULL; /* read_line() buffer. */ + size_t line_size = 0; /* Helper for for read_line. */ + int found_key = 0; /* Helper to find a matching key. */ + int id; + unsigned char *buffer; + size_t buffer_n; + int i; + + pkdbuf_new = NULL; + pkdbuf_new_n = 0; + id = 0; + + /* Loop over all records until we have found the subkey + corresponsing to the fingerprint. Inm general the first record + should be the pub record, but we don't rely on that. Given that + we only need to look at one key, it is sufficient to compare the + keyid so that we don't need to look at "fpr" records. */ + for (;;) + { + char *p; + char *fields[6]; + int nfields; + size_t max_length; + gcry_mpi_t mpi; + + max_length = 4096; + i = read_line (fp, &line, &line_size, &max_length); + if (!i) + break; /* EOF. */ + if (i < 0) + { + err = gpg_error_from_errno (errno); + goto leave; /* Error. */ + } + if (!max_length) + { + err = gpg_error (GPG_ERR_TRUNCATED); + goto leave; /* Line truncated - we better stop processing. */ + } + + /* Parse the line into fields. */ + for (nfields=0, p=line; p && nfields < DIM (fields); nfields++) + { + fields[nfields] = p; + p = strchr (p, ':'); + if (p) + *(p++) = 0; + } + if (!nfields) + continue; /* No fields at all - skip line. */ + + if (!found_key) + { + if ( (!strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") ) + && nfields > 4 && + (((strlen (hexkeyid) == 8) + && (strlen (fields[4]) == 16) + && (! strcmp (fields[4] + 8, hexkeyid))) + || ((strlen (hexkeyid) == 16) + && (! strcmp (fields[4], hexkeyid))))) + { + found_key = 1; + /* Save algorithm ID. */ + id = atoi (fields[3]); + } + continue; + } + + if ( !strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") ) + break; /* Next key - stop. */ + + if ( strcmp (fields[0], "pkd") ) + continue; /* Not a key data record. */ + + /* FIXME, necessary? */ + + i = atoi (fields[1]); + if ((nfields < 4) || (i < 0)) + { + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, fields[3], 0, NULL); + if (err) + mpi = NULL; + + err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &buffer, &buffer_n, mpi); + gcry_mpi_release (mpi); + if (err) + goto leave; + + pkdbuf_tmp = xrealloc (pkdbuf_new, sizeof (*pkdbuf_new) * (pkdbuf_new_n + 1)); + if (pkdbuf_new != pkdbuf_tmp) + pkdbuf_new = pkdbuf_tmp; + pkdbuf_new[pkdbuf_new_n].buffer = buffer; + pkdbuf_new[pkdbuf_new_n].buffer_n = buffer_n; + pkdbuf_new_n++; + } + + *algorithm_id = id; + *pkdbuf = pkdbuf_new; + *pkdbuf_n = pkdbuf_new_n; + + leave: + + if (err) + if (pkdbuf_new) + { + for (i = 0; i < pkdbuf_new_n; i++) + xfree (pkdbuf_new[i].buffer); + xfree (pkdbuf_new); + } + xfree (line); + + return err; +} + + + +int +key_to_blob (unsigned char **blob, size_t *blob_n, const char *identifier, ...) +{ + unsigned char *blob_new; + size_t blob_new_n; + unsigned char uint32_buffer[4]; + u32 identifier_n; + FILE *stream; + va_list ap; + int ret; + pkdbuf_t *pkd; + + stream = tmpfile (); + assert (stream); + + identifier_n = strlen (identifier); + uint32_buffer[0] = identifier_n >> 24; + uint32_buffer[1] = identifier_n >> 16; + uint32_buffer[2] = identifier_n >> 8; + uint32_buffer[3] = identifier_n >> 0; + ret = fwrite (uint32_buffer, sizeof (uint32_buffer), 1, stream); + assert (ret == 1); + ret = fwrite (identifier, identifier_n, 1, stream); + assert (ret == 1); + + va_start (ap, identifier); + while (1) + { + pkd = va_arg (ap, pkdbuf_t *); + if (! pkd) + break; + + uint32_buffer[0] = pkd->buffer_n >> 24; + uint32_buffer[1] = pkd->buffer_n >> 16; + uint32_buffer[2] = pkd->buffer_n >> 8; + uint32_buffer[3] = pkd->buffer_n >> 0; + ret = fwrite (uint32_buffer, sizeof (uint32_buffer), 1, stream); + assert (ret == 1); + ret = fwrite (pkd->buffer, pkd->buffer_n, 1, stream); + assert (ret == 1); + } + + blob_new_n = ftell (stream); + rewind (stream); + + blob_new = xmalloc (blob_new_n); + ret = fread (blob_new, blob_new_n, 1, stream); + assert (ret == 1); + + *blob = blob_new; + *blob_n = blob_new_n; + + fclose (stream); + + return 0; +} + +int +main (int argc, char **argv) +{ + const char *keyid; + int algorithm_id; + pkdbuf_t *pkdbuf; + size_t pkdbuf_n; + char *command; + FILE *fp; + int ret; + gcry_error_t err; + unsigned char *blob; + size_t blob_n; + struct b64state b64_state; + const char *identifier; + + pkdbuf = NULL; + pkdbuf_n = 0; + + assert (argc == 2); + + keyid = argv[1]; + + ret = asprintf (&command, + "gpg --list-keys --with-colons --with-key-data '%s'", + keyid); + assert (ret > 0); + + fp = popen (command, "r"); + assert (fp); + + err = retrieve_key_material (fp, keyid, &algorithm_id, &pkdbuf, &pkdbuf_n); + assert (! err); + assert ((algorithm_id == 1) || (algorithm_id == 17)); + + if (algorithm_id == 1) + { + identifier = "ssh-rsa"; + ret = key_to_blob (&blob, &blob_n, identifier, + &pkdbuf[0], &pkdbuf[1], NULL); + } + else if (algorithm_id == 17) + { + identifier = "ssh-dsa"; + ret = key_to_blob (&blob, &blob_n, identifier, + &pkdbuf[0], &pkdbuf[1], &pkdbuf[2], &pkdbuf[3], NULL); + } + assert (! ret); + + printf ("%s ", identifier); + + err = b64enc_start (&b64_state, stdout, ""); + assert (! err); + err = b64enc_write (&b64_state, blob, blob_n); + assert (! err); + err = b64enc_finish (&b64_state); + assert (! err); + + printf (" COMMENT\n"); + + return 0; +} -- cgit v1.2.3 From 6e522257a9beb9e7b12888533c9274f1e198ff0d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 31 May 2005 20:03:04 +0000 Subject: * agent.h (out_of_core): s/__inline__/inine. Noted by Ray Link. * dynload.h: s/__inline__/inline/. * tlv.c [GNUPG_MAJOR_VERSION==1]: Define constants instead of including a gnupg 1.4 header. * watchgnupg.c: Make sure that PF_LCOAL and AF_LOCAL are defines. Noted by Ray Link. --- THANKS | 1 + agent/ChangeLog | 9 +++++++++ agent/agent.h | 2 +- agent/gpg-agent.c | 8 +++++--- common/ChangeLog | 4 ++++ common/dynload.h | 8 ++++---- scd/ChangeLog | 10 ++++++++++ scd/app-common.h | 2 +- scd/tlv.c | 8 ++++++++ tools/ChangeLog | 5 +++++ tools/watchgnupg.c | 12 ++++++++++++ 11 files changed, 60 insertions(+), 9 deletions(-) diff --git a/THANKS b/THANKS index e1424cab1..57add954b 100644 --- a/THANKS +++ b/THANKS @@ -3,4 +3,5 @@ Alexander Belopolsky belopolsky at mac.com Andrew J. Schorr aschorr at telemetry-investments.com Kazu Yamamoto kazu@iij.ad.jp Michael Nottebrock michaelnottebrock at gmx.net +Ray Link rlink at pitt.edu Richard Lefebvre rick at cerca.umontreal.ca diff --git a/agent/ChangeLog b/agent/ChangeLog index dcf0cdfd3..86f62be48 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2005-05-31 Werner Koch <wk@g10code.com> + + * agent.h (out_of_core): s/__inline__/inine. Noted by Ray Link. + +2005-05-25 Werner Koch <wk@g10code.com> + + * gpg-agent.c (main): Do not unset the DISPLAY when we are + continuing as child. + 2005-05-24 Werner Koch <wk@g10code.com> * call-scd.c (inq_needpin): Skip leading spaces in of PIN diff --git a/agent/agent.h b/agent/agent.h index e416914cf..a667c0d46 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -37,7 +37,7 @@ /* Convenience function to be used instead of returning the old GNUPG_Out_Of_Core. */ -static __inline__ gpg_error_t +static inline gpg_error_t out_of_core (void) { return gpg_error (gpg_err_code_from_errno (errno)); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index e3e952906..c793e7eab 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -490,7 +490,7 @@ main (int argc, char **argv ) opt.homedir = default_homedir (); - /* Record the some original Denvironment settings. */ + /* Record some of the original environment strings. */ opt.startup_display = getenv ("DISPLAY"); if (opt.startup_display) opt.startup_display = xstrdup (opt.startup_display); @@ -776,9 +776,11 @@ main (int argc, char **argv ) /* Remove the DISPLAY variable so that a pinentry does not default to a specific display. There is still a default display when gpg-agent was started using --display or a - client requested this using an OPTION command. */ + client requested this using an OPTION command. Note, that we + don't do this when running in reverse daemon mode (i.e. when + exec the program given as arguments). */ #ifndef HAVE_W32_SYSTEM - if (!opt.keep_display) + if (!opt.keep_display && !argc) unsetenv ("DISPLAY"); #endif diff --git a/common/ChangeLog b/common/ChangeLog index cf294fbd1..abb3c6427 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2005-05-31 Werner Koch <wk@g10code.com> + + * dynload.h: s/__inline__/inline/. + 2005-05-13 Werner Koch <wk@g10code.com> * signal.c (got_fatal_signal): Print the signal number if we can't diff --git a/common/dynload.h b/common/dynload.h index 3c4652091..2c074141f 100644 --- a/common/dynload.h +++ b/common/dynload.h @@ -27,14 +27,14 @@ #define RTLD_LAZY 0 -static __inline__ void * +static inline void * dlopen (const char * name, int flag) { void * hd = LoadLibrary (name); return hd; } -static __inline__ void * +static inline void * dlsym (void *hd, const char *sym) { if (hd && sym) @@ -48,7 +48,7 @@ dlsym (void *hd, const char *sym) } -static __inline__ const char * +static inline const char * dlerror (void) { static char buf[32]; @@ -57,7 +57,7 @@ dlerror (void) } -static __inline__ int +static inline int dlclose (void * hd) { if (hd) diff --git a/scd/ChangeLog b/scd/ChangeLog index 64a4a8b72..ea1b0d287 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,13 @@ +2005-05-31 Werner Koch <wk@g10code.com> + + * tlv.c [GNUPG_MAJOR_VERSION==1]: Define constants instead of + including a gnupg 1.4 header. + +2005-05-30 Werner Koch <wk@g10code.com> + + * tlv.c: Add hack to compile without gpg-error.h when used with + GnuPG 1.4. + 2005-05-23 Werner Koch <wk@g10code.com> * Makefile.am: Do not build sc-copykeys anymore. diff --git a/scd/app-common.h b/scd/app-common.h index 613ad61f6..812736ece 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -45,7 +45,7 @@ struct app_ctx_s { in case we need to divert the operation to an already running agent. This if ASSUAN_CTX is not NULL we take this as indication that all operations are diverted to gpg-agent. */ -#if GNUPG_MAJOR_VERSION == 1 && defined(ENABLE_AGENT_SUPPORT) +#if GNUPG_MAJOR_VERSION == 1 assuan_context_t assuan_ctx; #endif /*GNUPG_MAJOR_VERSION == 1*/ diff --git a/scd/tlv.c b/scd/tlv.c index b5dcd4021..b436d956a 100644 --- a/scd/tlv.c +++ b/scd/tlv.c @@ -25,7 +25,15 @@ #include <string.h> #include <assert.h> +#if GNUPG_MAJOR_VERSION == 1 +#define GPG_ERR_EOF (-1) +#define GPG_ERR_BAD_BER (1) /*G10ERR_GENERAL*/ +#define GPG_ERR_INV_SEXP (45) /*G10ERR_INV_ARG*/ +typedef int gpg_error_t; +#define gpg_error(n) (n) +#else #include <gpg-error.h> +#endif #include "tlv.h" diff --git a/tools/ChangeLog b/tools/ChangeLog index 085ba094f..103be28e5 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2005-05-31 Werner Koch <wk@g10code.com> + + * watchgnupg.c: Make sure that PF_LCOAL and AF_LOCAL are defines. + Noted by Ray Link. + 2005-05-28 Moritz Schulte <moritz@g10code.com> * gpgkey2ssh.c: New file. diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index 50f9d7274..25ca8c413 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -45,6 +45,18 @@ #define BUGREPORT_LINE "" #endif +#ifndef PF_LOCAL +# ifdef PF_UNIX +# define PF_LOCAL PF_UNIX +# else +# define PF_LOCAL AF_UNIX +# endif +# ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +# endif +#endif + + static int verbose; -- cgit v1.2.3 From cad9562436e61cdaf1a2f03ba96bcc82077205e6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 1 Jun 2005 15:46:01 +0000 Subject: * configure.ac (gl_INIT): Add gnulib stuff. (fseeko, ftello, ttyname, isascii): Replaced the AC_REPLACE_FUNCS by a simple check. (putc_unlocked): Removed check. Not used. (strsep, mkdtemp, asprintf): Replaced checks by gnulib checks. (xsize): Added will probably come handy soon. (CFLAGS): Use -Wformat-security instead of -Wformat-nonliteral. Add --Wno-format-y2k. * gl/, gl/m4/: New. * gpg-agent.c: Include setenv.h. * Makefile.am (AM_CPPFLAGS): Added. * util.h: Add some includes for gnulib. (ttyname, isascii): Define them inline. * fseeko.c, ftello.c: Removed. * strsep.c, mkdtemp.c: Removed. * ttyname.c, isascii.c: Removed. * mkdtemp.c: Removed. * exec.c: Include mkdtemp.h * keybox-file.c (ftello) [!HAVE_FSEEKO]: New replacement function. Copied from ../common/ftello.c. * keybox-update.c (fseeko) [!HAVE_FSEEKO]: New replacement function. Copied from ../common/iobuf.c. * scdaemon.c: Include mkdtemp.h. * misc.c: Include setenv.h. * symcryptrun.c: Include mkdtemp.h. --- ChangeLog | 12 +++++++ Makefile.am | 4 +-- agent/ChangeLog | 4 +++ agent/Makefile.am | 4 +-- agent/gpg-agent.c | 1 + autogen.sh | 4 +-- common/ChangeLog | 10 ++++++ common/Makefile.am | 16 ++------- common/fseeko.c | 41 --------------------- common/ftello.c | 46 ------------------------ common/mkdtemp.c | 97 ------------------------------------------------- common/putc_unlocked.c | 31 ---------------- common/strsep.c | 76 --------------------------------------- common/ttyname.c | 32 ----------------- common/util.h | 40 ++++++++++++--------- common/xasprintf.c | 2 +- configure.ac | 20 +++++------ g10/ChangeLog | 5 +++ g10/Makefile.am | 6 ++-- g10/exec.c | 5 +-- g10/mkdtemp.c | 98 -------------------------------------------------- kbx/ChangeLog | 7 ++++ kbx/Makefile.am | 5 +-- kbx/keybox-file.c | 16 +++++++++ kbx/keybox-update.c | 32 +++++++++++++++++ scd/ChangeLog | 4 +++ scd/Makefile.am | 4 +-- scd/scdaemon.c | 2 +- sm/ChangeLog | 4 +++ sm/Makefile.am | 4 +-- sm/misc.c | 1 + tools/ChangeLog | 4 +++ tools/Makefile.am | 14 +++++--- tools/symcryptrun.c | 1 + 34 files changed, 166 insertions(+), 486 deletions(-) delete mode 100644 common/fseeko.c delete mode 100644 common/ftello.c delete mode 100644 common/mkdtemp.c delete mode 100644 common/putc_unlocked.c delete mode 100644 common/strsep.c delete mode 100644 common/ttyname.c delete mode 100644 g10/mkdtemp.c diff --git a/ChangeLog b/ChangeLog index 154ae07e9..fbd9ad79d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * configure.ac (gl_INIT): Add gnulib stuff. + (fseeko, ftello, ttyname, isascii): Replaced the AC_REPLACE_FUNCS + by a simple check. + (putc_unlocked): Removed check. Not used. + (strsep, mkdtemp, asprintf): Replaced checks by gnulib checks. + (xsize): Added will probably come handy soon. + (CFLAGS): Use -Wformat-security instead of + -Wformat-nonliteral. Add --Wno-format-y2k. + * gl/, gl/m4/: New. + 2005-05-15 Werner Koch <wk@g10code.com> * configure.ac: Remove option --disable-threads; require the use diff --git a/Makefile.am b/Makefile.am index e6cbde893..9fafb1102 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ ## Process this file with automake to produce Makefile.in -ACLOCAL_AMFLAGS = -I m4 +ACLOCAL_AMFLAGS = -I m4 -I gl/m4 AUTOMAKE_OPTIONS = dist-bzip2 EXTRA_DIST = scripts/config.rpath autogen.sh README.CVS @@ -59,7 +59,7 @@ else tests = tests endif -SUBDIRS = m4 intl jnlib common ${kbx} \ +SUBDIRS = m4 intl gl jnlib common ${kbx} \ ${gpg} ${sm} ${agent} ${scd} tools po doc ${tests} dist-hook: diff --git a/agent/ChangeLog b/agent/ChangeLog index 86f62be48..9c57ad43e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * gpg-agent.c: Include setenv.h. + 2005-05-31 Werner Koch <wk@g10code.com> * agent.h (out_of_core): s/__inline__/inine. Noted by Ray Link. diff --git a/agent/Makefile.am b/agent/Makefile.am index df8ec322c..017b84795 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -21,7 +21,7 @@ bin_PROGRAMS = gpg-agent libexec_PROGRAMS = gpg-protect-tool gpg-preset-passphrase -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl +AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common -I$(top_srcdir)/intl include $(top_srcdir)/am/cmacros.am @@ -44,7 +44,7 @@ gpg_agent_SOURCES = \ learncard.c -gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ +gpg_agent_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ -lgpg-error @LIBINTL@ diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index c793e7eab..3537b07f0 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -48,6 +48,7 @@ #ifdef HAVE_W32_SYSTEM #include "../jnlib/w32-afunix.h" #endif +#include "setenv.h" enum cmd_and_opt_values diff --git a/autogen.sh b/autogen.sh index 67d28ed38..aaf0d0ea4 100755 --- a/autogen.sh +++ b/autogen.sh @@ -152,8 +152,8 @@ EOF fi -echo "Running aclocal -I m4 ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..." -$ACLOCAL -I m4 $ACLOCAL_FLAGS +echo "Running aclocal -I m4 -I gl/m4 ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..." +$ACLOCAL -I m4 -I gl/m4 $ACLOCAL_FLAGS echo "Running autoheader..." $AUTOHEADER echo "Running automake --gnu ..." diff --git a/common/ChangeLog b/common/ChangeLog index abb3c6427..fccc71d49 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,13 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * Makefile.am (AM_CPPFLAGS): Added. + + * util.h: Add some includes for gnulib. + (ttyname, isascii): Define them inline. + * fseeko.c, ftello.c: Removed. + * strsep.c, mkdtemp.c: Removed. + * ttyname.c, isascii.c: Removed. + 2005-05-31 Werner Koch <wk@g10code.com> * dynload.h: s/__inline__/inline/. diff --git a/common/Makefile.am b/common/Makefile.am index a039be184..0f9b4324d 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -21,7 +21,9 @@ noinst_LIBRARIES = libcommon.a libsimple-pwquery.a -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) $(PTH_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/gl + +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) $(PTH_CFLAGS) libcommon_a_SOURCES = \ util.h i18n.h \ @@ -49,18 +51,6 @@ libcommon_a_SOURCES = \ estream.c estream.h -libcommon_a_LIBADD = @LIBOBJS@ - libsimple_pwquery_a_SOURCES = \ simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h -libsimple_pwquery_a_LIBADD = @LIBOBJS@ - - - - - - - - - diff --git a/common/fseeko.c b/common/fseeko.c deleted file mode 100644 index 06838e4c4..000000000 --- a/common/fseeko.c +++ /dev/null @@ -1,41 +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> -#include <sys/types.h> /* Defines off_t under W32. */ - -int -fseeko (FILE *stream, off_t off, int whence) -{ - return fseek (stream, off, whence); -} - - - - - - - - - - diff --git a/common/ftello.c b/common/ftello.c deleted file mode 100644 index 6837be959..000000000 --- a/common/ftello.c +++ /dev/null @@ -1,46 +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> -#include <sys/types.h> /* Defines off_t under W32. */ - -off_t -ftello (FILE *stream) -{ - long int off; - - off = ftell (stream); - if (off == -1) - return (off_t)-1; - return off; -} - - - - - - - - - - diff --git a/common/mkdtemp.c b/common/mkdtemp.c deleted file mode 100644 index a85b89eb4..000000000 --- a/common/mkdtemp.c +++ /dev/null @@ -1,97 +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; -} - - diff --git a/common/putc_unlocked.c b/common/putc_unlocked.c deleted file mode 100644 index 02c646130..000000000 --- a/common/putc_unlocked.c +++ /dev/null @@ -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); -} diff --git a/common/strsep.c b/common/strsep.c deleted file mode 100644 index dd01a826f..000000000 --- a/common/strsep.c +++ /dev/null @@ -1,76 +0,0 @@ -/* strsep.c - Replacement for strsep(). - * Copyright (C) 1992, 1993, 1996, 1997, 1998, 1999, - * 2004 Free Software Foundation, Inc. - * - * This file is part of the GNU C Library. - * - * The GNU C Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * The GNU C Library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the GNU C Library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA. - */ - -/* Code taken from glibc-2.3.2/sysdeps/generic/strsep.c and slightly - modified for use with GnuPG. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <string.h> - -char * -strsep (char **stringp, const char *delim) -{ - char *begin, *end; - - begin = *stringp; - if (begin == NULL) - return NULL; - - /* A frequent case is when the delimiter string contains only one - character. Here we don't need to call the expensive `strpbrk' - function and instead work using `strchr'. */ - if (delim[0] == '\0' || delim[1] == '\0') - { - char ch = delim[0]; - - if (ch == '\0') - end = NULL; - else - { - if (*begin == ch) - end = begin; - else if (*begin == '\0') - end = NULL; - else - end = strchr (begin + 1, ch); - } - } - else - /* Find the end of the token. */ - end = strpbrk (begin, delim); - - if (end) - { - /* Terminate the token and set *STRINGP past NUL character. */ - *end++ = '\0'; - *stringp = end; - } - else - /* No more delimiters; this is the last token. */ - *stringp = NULL; - - return begin; -} - diff --git a/common/ttyname.c b/common/ttyname.c deleted file mode 100644 index 822beef99..000000000 --- a/common/ttyname.c +++ /dev/null @@ -1,32 +0,0 @@ -/* ttyname.c - Replacement for ttyname. - * 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 - */ - -/* This one is a simple dummy and suitable for Dosish systems. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> - -char * -ttyname (int fd) -{ - return NULL; -} diff --git a/common/util.h b/common/util.h index 6a9b54ef5..d233dbf5e 100644 --- a/common/util.h +++ b/common/util.h @@ -25,7 +25,13 @@ #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 */ +/* Common GNUlib includes (-I ../gl/). */ +#include "strpbrk.h" +#include "strsep.h" +#include "vasprintf.h" + + +/* Hash function used with libksba. */ #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) /* get all the stuff from jnlib */ @@ -152,24 +158,26 @@ 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 -#ifndef HAVE_STRSEP -char *strsep (char **stringp, const char *delim); -#endif + +/*-- Simple replacement functions. */ #ifndef HAVE_TTYNAME -char *ttyname (int fd); -#endif -#ifndef HAVE_MKDTEMP -char *mkdtemp (char *template); -#endif +/* Systems without ttyname (W32) will merely return NULL. */ +static inline char * +ttyname (int fd) +{ + return NULL +}; +#endif /* !HAVE_TTYNAME */ +#ifndef HAVE_ISASCII +static inline int +isascii (int c) +{ + return (((c) & ~0x7f) == 0); +} +#endif /* !HAVE_ISASCII */ -/*-- some macros to replace ctype ones and avoid locale problems --*/ +/*-- Macros to replace ctype ones to avoid locale problems. --*/ #define spacep(p) (*(p) == ' ' || *(p) == '\t') #define digitp(p) (*(p) >= '0' && *(p) <= '9') #define hexdigitp(a) (digitp (a) \ diff --git a/common/xasprintf.c b/common/xasprintf.c index a3b5e27ac..46740a2e6 100644 --- a/common/xasprintf.c +++ b/common/xasprintf.c @@ -43,7 +43,7 @@ xasprintf (const char *fmt, ...) return p; } -/* Same as above bit return NULL on memory failure. */ +/* Same as above but return NULL on memory failure. */ char * xtryasprintf (const char *fmt, ...) { diff --git a/configure.ac b/configure.ac index 369762b02..c1a3d77ea 100644 --- a/configure.ac +++ b/configure.ac @@ -337,6 +337,7 @@ AC_PROG_RANLIB AC_CHECK_TOOL(AR, ar, :) AC_PATH_PROG(PERL,"perl") AC_ISC_POSIX +gl_EARLY AC_SYS_LARGEFILE AC_CHECK_PROG(DOCBOOK_TO_MAN, docbook-to-man, yes, no) AM_CONDITIONAL(HAVE_DOCBOOK_TO_MAN, test "$ac_cv_prog_DOCBOOK_TO_MAN" = yes) @@ -794,23 +795,21 @@ AC_CHECK_FUNCS(strcasecmp strncasecmp ctermid times gmtime_r) AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat getaddrinfo) +AC_CHECK_FUNCS(fseeko ftello ttyname isascii) AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>]) +# gnulib checks +gl_SOURCE_BASE(gl) +gl_M4_BASE(gl/m4) +gl_MODULES(setenv strsep mkdtemp vasprintf xsize) +gl_INIT + # These are needed by libjnlib - fixme: we should have macros for them AC_CHECK_FUNCS(memicmp stpcpy strlwr strtoul memmove stricmp strtol) AC_CHECK_FUNCS(getrusage setrlimit stat setlocale) AC_CHECK_FUNCS(flockfile funlockfile fopencookie funopen) -AC_REPLACE_FUNCS(vasprintf) -AC_REPLACE_FUNCS(mkdtemp) -AC_REPLACE_FUNCS(fseeko ftello) -AC_REPLACE_FUNCS(isascii) -AC_REPLACE_FUNCS(putc_unlocked) -AC_REPLACE_FUNCS(strsep) -AC_REPLACE_FUNCS(ttyname) - - # # check for gethrtime and run a testprogram to see whether @@ -989,7 +988,7 @@ fi if test "$GCC" = yes; then if test "$USE_MAINTAINER_MODE" = "yes"; then CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" - CFLAGS="$CFLAGS -Wformat-nonliteral" + CFLAGS="$CFLAGS -Wno-format-y2k -Wformat-security" else CFLAGS="$CFLAGS -Wall" fi @@ -1126,6 +1125,7 @@ AC_CONFIG_FILES([ m4/Makefile Makefile po/Makefile.in intl/Makefile +gl/Makefile jnlib/Makefile common/Makefile kbx/Makefile diff --git a/g10/ChangeLog b/g10/ChangeLog index bd4b54894..b33735e1f 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * mkdtemp.c: Removed. + * exec.c: Include mkdtemp.h + 2004-12-21 Werner Koch <wk@g10code.com> * gpgv.c, g10.c (main): Use default_hoemdir (). diff --git a/g10/Makefile.am b/g10/Makefile.am index 8e63e9335..f371dab4a 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -21,14 +21,14 @@ EXTRA_DIST = options.skel -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/include \ - -I$(top_srcdir)/intl +AM_CPPFLAGS = -I$(top_srcdir)/gl -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 +needed_libs = ../gl/libgnu.a ../common/libcommon.a ../jnlib/libjnlib.a bin_PROGRAMS = gpg2 gpgv2 diff --git a/g10/exec.c b/g10/exec.c index a49fe15d2..b1fc2c70f 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -39,6 +39,7 @@ #include "i18n.h" #include "iobuf.h" #include "util.h" +#include "mkdtemp.h" #include "exec.h" #ifdef NO_EXEC @@ -55,10 +56,6 @@ 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 diff --git a/g10/mkdtemp.c b/g10/mkdtemp.c deleted file mode 100644 index 55e5b189f..000000000 --- a/g10/mkdtemp.c +++ /dev/null @@ -1,98 +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 "types.h" -#include "cipher.h" - -#ifdef MKDIR_TAKES_ONE_ARG -# undef mkdir -# define mkdir(a,b) mkdir(a) -#endif - -char *mkdtemp(char *template) -{ - unsigned int attempts,idx,count=0; - byte *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++) - { - unsigned int remaining=count; - char *marker=ch; - byte *randombits; - - idx=0; - - /* Using really random bits is probably overkill here. The - worst thing that can happen with a directory name collision - is that the function will return an error. */ - - randombits=get_random_bits(4*remaining,0,0); - - 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); - - xfree (randombits); - - if(mkdir(template,0700)==0) - break; - } - - if(attempts==4) - return NULL; /* keeps the errno from mkdir, whatever it is */ - - return template; -} diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 3688174bd..7c112085c 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,10 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * keybox-file.c (ftello) [!HAVE_FSEEKO]: New replacement + function. Copied from ../common/ftello.c. + * keybox-update.c (fseeko) [!HAVE_FSEEKO]: New replacement + function. Copied from ../common/iobuf.c. + 2004-12-18 Werner Koch <wk@g10code.com> * keybox-defs.h (map_assuan_err): Define in terms of diff --git a/kbx/Makefile.am b/kbx/Makefile.am index ea8436d72..85704eb66 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -23,7 +23,7 @@ localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" EXTRA_DIST = mkerrors -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl \ +AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common -I$(top_srcdir)/intl \ $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) noinst_LIBRARIES = libkeybox.a @@ -45,6 +45,7 @@ libkeybox_a_SOURCES = $(common_sources) # Note that libcommon is only required to resolve the LIBOBJS. kbxutil_SOURCES = kbxutil.c $(common_sources) -kbxutil_LDADD = ../jnlib/libjnlib.a $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ +kbxutil_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a \ + $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ -lgpg-error $(LIBINTL) ../common/libcommon.a diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c index db3164fef..fe02c1f9f 100644 --- a/kbx/keybox-file.c +++ b/kbx/keybox-file.c @@ -27,6 +27,22 @@ #include "keybox-defs.h" + +#if !defined(HAVE_FTELLO) && !defined(ftello) +static off_t +ftello (FILE *stream) +{ + long int off; + + off = ftell (stream); + if (off == -1) + return (off_t)-1; + return off; +} +#endif /* !defined(HAVE_FTELLO) && !defined(ftello) */ + + + /* Read a block at the current postion and return it in r_blob. r_blob may be NULL to simply skip the current block */ int diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index eabaa1db2..a16c18e23 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -31,6 +31,38 @@ #define EXTSEP_S "." +#if !defined(HAVE_FSEEKO) && !defined(fseeko) + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif +#ifndef LONG_MAX +# define LONG_MAX ((long) ((unsigned long) -1 >> 1)) +#endif +#ifndef LONG_MIN +# define LONG_MIN (-1 - LONG_MAX) +#endif + +/**************** + * A substitute for fseeko, for hosts that don't have it. + */ +static int +fseeko (FILE * stream, off_t newpos, int whence) +{ + while (newpos != (long) newpos) + { + long pos = newpos < 0 ? LONG_MIN : LONG_MAX; + if (fseek (stream, pos, whence) != 0) + return -1; + newpos -= pos; + whence = SEEK_CUR; + } + return fseek (stream, (long) newpos, whence); +} +#endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */ + + + static int create_tmp_file (const char *template, char **r_bakfname, char **r_tmpfname, FILE **r_fp) diff --git a/scd/ChangeLog b/scd/ChangeLog index ea1b0d287..136ed5618 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * scdaemon.c: Include mkdtemp.h. + 2005-05-31 Werner Koch <wk@g10code.com> * tlv.c [GNUPG_MAJOR_VERSION==1]: Define constants instead of diff --git a/scd/Makefile.am b/scd/Makefile.am index e76f83ea4..dadab4f67 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -23,7 +23,7 @@ if ! HAVE_W32_SYSTEM pkglib_PROGRAMS = pcsc-wrapper endif -AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common +AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am @@ -43,7 +43,7 @@ scdaemon_SOURCES = \ app.c app-common.h app-help.c $(card_apps) -scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ +scdaemon_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ $(LIBUSB_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 488a4853b..341719b1e 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -51,7 +51,7 @@ #include "../jnlib/w32-afunix.h" #endif #include "ccid-driver.h" - +#include "mkdtemp.h" enum cmd_and_opt_values { aNull = 0, diff --git a/sm/ChangeLog b/sm/ChangeLog index aa8e8671f..ffb61a294 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * misc.c: Include setenv.h. + 2005-04-21 Werner Koch <wk@g10code.com> * gpgsm.c: New options --{enable,disable}-trusted-cert-crl-check. diff --git a/sm/Makefile.am b/sm/Makefile.am index f1a116ab5..e5311e967 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -24,7 +24,7 @@ bin_PROGRAMS = gpgsm AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) \ $(PTH_CFLAGS) -AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/intl +AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common -I$(top_srcdir)/intl include $(top_srcdir)/am/cmacros.am @@ -52,7 +52,7 @@ gpgsm_SOURCES = \ certreqgen.c -gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a \ +gpgsm_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a ../kbx/libkeybox.a \ ../common/libcommon.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -lgpg-error \ $(LIBINTL) $(PTH_LIBS) diff --git a/sm/misc.c b/sm/misc.c index 36c4dda70..cd072ce6b 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -31,6 +31,7 @@ #include "gpgsm.h" #include "i18n.h" +#include "setenv.h" /* Setup the environment so that the pinentry is able to get all required information. This is used prior to an exec of the diff --git a/tools/ChangeLog b/tools/ChangeLog index 103be28e5..de7e5b89b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-06-01 Werner Koch <wk@g10code.com> + + * symcryptrun.c: Include mkdtemp.h. + 2005-05-31 Werner Koch <wk@g10code.com> * watchgnupg.c: Make sure that PF_LCOAL and AF_LOCAL are defines. diff --git a/tools/Makefile.am b/tools/Makefile.am index 6d2d2e741..bc66118bf 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -21,7 +21,7 @@ EXTRA_DIST = Manifest watchgnupg.c \ rfc822parse.c rfc822parse.h gpgparsemail.c \ addgnupghome gpgsm-gencert.sh -AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common +AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am AM_CFLAGS = $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) @@ -43,19 +43,23 @@ endif gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c -gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @LIBINTL@ +gpgconf_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a \ + ../common/libcommon.a @LIBINTL@ symcryptrun_SOURCES = symcryptrun.c -symcryptrun_LDADD = $(LIBUTIL_LIBS) ../jnlib/libjnlib.a ../common/libcommon.a \ +symcryptrun_LDADD = $(LIBUTIL_LIBS) ../gl/libgnu.a ../jnlib/libjnlib.a \ + ../common/libcommon.a \ ../common/libsimple-pwquery.a $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) watchgnupg_SOURCES = watchgnupg.c gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c -gpg_connect_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ +gpg_connect_agent_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a \ + ../common/libcommon.a \ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) gpgkey2ssh_SOURCES = gpgkey2ssh.c gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) -gpgkey2ssh_LDADD = ../common/libcommon.a $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) +gpgkey2ssh_LDADD = ../gl/libgnu.a ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 6771ab953..09fc8582f 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -82,6 +82,7 @@ #define JNLIB_NEED_LOG_LOGV #include "i18n.h" #include "../common/util.h" +#include "mkdtemp.h" /* FIXME: Bah. For spwq_secure_free. */ #define SIMPLE_PWQUERY_IMPLEMENTATION 1 -- cgit v1.2.3 From 5703db4d03b1449ef25cfb568efc08bcbb9634b4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 1 Jun 2005 15:48:03 +0000 Subject: Add stuff from gnulib. --- gl/Makefile.am | 93 +++++ gl/alloca_.h | 52 +++ gl/allocsa.c | 139 ++++++++ gl/allocsa.h | 113 +++++++ gl/allocsa.valgrind | 7 + gl/asnprintf.c | 37 ++ gl/asprintf.c | 37 ++ gl/m4/alloca.m4 | 42 +++ gl/m4/allocsa.m4 | 15 + gl/m4/eealloc.m4 | 32 ++ gl/m4/eoverflow.m4 | 64 ++++ gl/m4/gnulib.m4 | 46 +++ gl/m4/intmax_t.m4 | 61 ++++ gl/m4/inttypes_h.m4 | 26 ++ gl/m4/longdouble.m4 | 28 ++ gl/m4/longlong.m4 | 23 ++ gl/m4/mkdtemp.m4 | 23 ++ gl/m4/onceonly_2_57.m4 | 86 +++++ gl/m4/setenv.m4 | 70 ++++ gl/m4/signed.m4 | 17 + gl/m4/size_max.m4 | 59 ++++ gl/m4/stdint_h.m4 | 26 ++ gl/m4/strpbrk.m4 | 16 + gl/m4/strsep.m4 | 17 + gl/m4/uintmax_t.m4 | 30 ++ gl/m4/ulonglong.m4 | 23 ++ gl/m4/vasnprintf.m4 | 58 ++++ gl/m4/vasprintf.m4 | 25 ++ gl/m4/wchar_t.m4 | 20 ++ gl/m4/wint_t.m4 | 20 ++ gl/m4/xsize.m4 | 13 + gl/mkdtemp.c | 203 +++++++++++ gl/mkdtemp.h | 32 ++ gl/printf-args.c | 118 +++++++ gl/printf-args.h | 136 ++++++++ gl/printf-parse.c | 536 +++++++++++++++++++++++++++++ gl/printf-parse.h | 74 ++++ gl/setenv.c | 328 ++++++++++++++++++ gl/setenv.h | 54 +++ gl/strpbrk.c | 42 +++ gl/strpbrk.h | 28 ++ gl/strsep.c | 55 +++ gl/strsep.h | 52 +++ gl/unsetenv.c | 99 ++++++ gl/vasnprintf.c | 901 +++++++++++++++++++++++++++++++++++++++++++++++++ gl/vasnprintf.h | 77 +++++ gl/vasprintf.c | 42 +++ gl/vasprintf.h | 63 ++++ gl/xsize.h | 108 ++++++ 49 files changed, 4266 insertions(+) create mode 100644 gl/Makefile.am create mode 100644 gl/alloca_.h create mode 100644 gl/allocsa.c create mode 100644 gl/allocsa.h create mode 100644 gl/allocsa.valgrind create mode 100644 gl/asnprintf.c create mode 100644 gl/asprintf.c create mode 100644 gl/m4/alloca.m4 create mode 100644 gl/m4/allocsa.m4 create mode 100644 gl/m4/eealloc.m4 create mode 100644 gl/m4/eoverflow.m4 create mode 100644 gl/m4/gnulib.m4 create mode 100644 gl/m4/intmax_t.m4 create mode 100644 gl/m4/inttypes_h.m4 create mode 100644 gl/m4/longdouble.m4 create mode 100644 gl/m4/longlong.m4 create mode 100644 gl/m4/mkdtemp.m4 create mode 100644 gl/m4/onceonly_2_57.m4 create mode 100644 gl/m4/setenv.m4 create mode 100644 gl/m4/signed.m4 create mode 100644 gl/m4/size_max.m4 create mode 100644 gl/m4/stdint_h.m4 create mode 100644 gl/m4/strpbrk.m4 create mode 100644 gl/m4/strsep.m4 create mode 100644 gl/m4/uintmax_t.m4 create mode 100644 gl/m4/ulonglong.m4 create mode 100644 gl/m4/vasnprintf.m4 create mode 100644 gl/m4/vasprintf.m4 create mode 100644 gl/m4/wchar_t.m4 create mode 100644 gl/m4/wint_t.m4 create mode 100644 gl/m4/xsize.m4 create mode 100644 gl/mkdtemp.c create mode 100644 gl/mkdtemp.h create mode 100644 gl/printf-args.c create mode 100644 gl/printf-args.h create mode 100644 gl/printf-parse.c create mode 100644 gl/printf-parse.h create mode 100644 gl/setenv.c create mode 100644 gl/setenv.h create mode 100644 gl/strpbrk.c create mode 100644 gl/strpbrk.h create mode 100644 gl/strsep.c create mode 100644 gl/strsep.h create mode 100644 gl/unsetenv.c create mode 100644 gl/vasnprintf.c create mode 100644 gl/vasnprintf.h create mode 100644 gl/vasprintf.c create mode 100644 gl/vasprintf.h create mode 100644 gl/xsize.h diff --git a/gl/Makefile.am b/gl/Makefile.am new file mode 100644 index 000000000..be8e6a5b6 --- /dev/null +++ b/gl/Makefile.am @@ -0,0 +1,93 @@ +## Process this file with automake to produce Makefile.in. +# Copyright (C) 2004 Free Software Foundation, Inc. +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Automake, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# Invoked as: gnulib-tool --import +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=scripts alloca-opt allocsa mkdtemp setenv strpbrk strsep vasnprintf vasprintf xsize + +AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies + +noinst_LIBRARIES = libgnu.a + +libgnu_a_SOURCES = +libgnu_a_LIBADD = @LIBOBJS@ +EXTRA_DIST = +BUILT_SOURCES = +SUFFIXES = +MOSTLYCLEANFILES = +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = + +## begin gnulib module alloca-opt + +BUILT_SOURCES += $(ALLOCA_H) +EXTRA_DIST += alloca_.h + +# We need the following in order to create an <alloca.h> when the system +# doesn't have one that works with the given compiler. +all-local $(libgnu_a_OBJECTS): $(ALLOCA_H) +alloca.h: alloca_.h + cp $(srcdir)/alloca_.h $@-t + mv $@-t $@ +MOSTLYCLEANFILES += alloca.h alloca.h-t + +## end gnulib module alloca-opt + +## begin gnulib module allocsa + +libgnu_a_SOURCES += allocsa.h allocsa.c +EXTRA_DIST += allocsa.valgrind + +## end gnulib module allocsa + +## begin gnulib module mkdtemp + +libgnu_a_SOURCES += mkdtemp.h + +## end gnulib module mkdtemp + +## begin gnulib module setenv + +libgnu_a_SOURCES += setenv.h + +## end gnulib module setenv + +## begin gnulib module strpbrk + +libgnu_a_SOURCES += strpbrk.h + +## end gnulib module strpbrk + +## begin gnulib module strsep + +libgnu_a_SOURCES += strsep.h + +## end gnulib module strsep + +## begin gnulib module vasnprintf + +libgnu_a_SOURCES += printf-args.h printf-parse.h vasnprintf.h + +## end gnulib module vasnprintf + +## begin gnulib module vasprintf + +libgnu_a_SOURCES += vasprintf.h + +## end gnulib module vasprintf + +## begin gnulib module xsize + +libgnu_a_SOURCES += xsize.h + +## end gnulib module xsize + + +# Makefile.am ends here diff --git a/gl/alloca_.h b/gl/alloca_.h new file mode 100644 index 000000000..3e3fdf43f --- /dev/null +++ b/gl/alloca_.h @@ -0,0 +1,52 @@ +/* Memory allocation on the stack. + + Copyright (C) 1995, 1999, 2001, 2002, 2003, 2004 Free Software + Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H + means there is a real alloca function. */ +#ifndef _GNULIB_ALLOCA_H +# define _GNULIB_ALLOCA_H + +/* alloca (N) returns a pointer to N bytes of memory + allocated on the stack, which will last until the function returns. + Use of alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns, + - for huge N (say, N >= 65536) - you never know how large (or small) + the stack is, and when the stack cannot fulfill the memory allocation + request, the program just crashes. + */ + +#ifdef __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +#else +# include <stddef.h> +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +#endif + +#endif /* _GNULIB_ALLOCA_H */ diff --git a/gl/allocsa.c b/gl/allocsa.c new file mode 100644 index 000000000..a54e2d0ca --- /dev/null +++ b/gl/allocsa.c @@ -0,0 +1,139 @@ +/* Safe automatic memory allocation. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include "allocsa.h" + +/* The speed critical point in this file is freesa() applied to an alloca() + result: it must be fast, to match the speed of alloca(). The speed of + mallocsa() and freesa() in the other case are not critical, because they + are only invoked for big memory sizes. */ + +#if HAVE_ALLOCA + +/* Store the mallocsa() results in a hash table. This is needed to reliably + distinguish a mallocsa() result and an alloca() result. + + Although it is possible that the same pointer is returned by alloca() and + by mallocsa() at different times in the same application, it does not lead + to a bug in freesa(), because: + - Before a pointer returned by alloca() can point into malloc()ed memory, + the function must return, and once this has happened the programmer must + not call freesa() on it anyway. + - Before a pointer returned by mallocsa() can point into the stack, it + must be freed. The only function that can free it is freesa(), and + when freesa() frees it, it also removes it from the hash table. */ + +#define MAGIC_NUMBER 0x1415fb4a +#define MAGIC_SIZE sizeof (int) +/* This is how the header info would look like without any alignment + considerations. */ +struct preliminary_header { void *next; char room[MAGIC_SIZE]; }; +/* But the header's size must be a multiple of sa_alignment_max. */ +#define HEADER_SIZE \ + (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max) +struct header { void *next; char room[HEADER_SIZE - sizeof (struct preliminary_header) + MAGIC_SIZE]; }; +/* Verify that HEADER_SIZE == sizeof (struct header). */ +typedef int verify1[2 * (HEADER_SIZE == sizeof (struct header)) - 1]; +/* We make the hash table quite big, so that during lookups the probability + of empty hash buckets is quite high. There is no need to make the hash + table resizable, because when the hash table gets filled so much that the + lookup becomes slow, it means that the application has memory leaks. */ +#define HASH_TABLE_SIZE 257 +static void * mallocsa_results[HASH_TABLE_SIZE]; + +#endif + +void * +mallocsa (size_t n) +{ +#if HAVE_ALLOCA + /* Allocate one more word, that serves as an indicator for malloc()ed + memory, so that freesa() of an alloca() result is fast. */ + size_t nplus = n + HEADER_SIZE; + + if (nplus >= n) + { + char *p = (char *) malloc (nplus); + + if (p != NULL) + { + size_t slot; + + p += HEADER_SIZE; + + /* Put a magic number into the indicator word. */ + ((int *) p)[-1] = MAGIC_NUMBER; + + /* Enter p into the hash table. */ + slot = (unsigned long) p % HASH_TABLE_SIZE; + ((struct header *) (p - HEADER_SIZE))->next = mallocsa_results[slot]; + mallocsa_results[slot] = p; + + return p; + } + } + /* Out of memory. */ + return NULL; +#else +# if !MALLOC_0_IS_NONNULL + if (n == 0) + n = 1; +# endif + return malloc (n); +#endif +} + +#if HAVE_ALLOCA +void +freesa (void *p) +{ + /* mallocsa() may have returned NULL. */ + if (p != NULL) + { + /* Attempt to quickly distinguish the mallocsa() result - which has + a magic indicator word - and the alloca() result - which has an + uninitialized indicator word. It is for this test that sa_increment + additional bytes are allocated in the alloca() case. */ + if (((int *) p)[-1] == MAGIC_NUMBER) + { + /* Looks like a mallocsa() result. To see whether it really is one, + perform a lookup in the hash table. */ + size_t slot = (unsigned long) p % HASH_TABLE_SIZE; + void **chain = &mallocsa_results[slot]; + for (; *chain != NULL;) + { + if (*chain == p) + { + /* Found it. Remove it from the hash table and free it. */ + char *p_begin = (char *) p - HEADER_SIZE; + *chain = ((struct header *) p_begin)->next; + free (p_begin); + return; + } + chain = &((struct header *) ((char *) *chain - HEADER_SIZE))->next; + } + } + /* At this point, we know it was not a mallocsa() result. */ + } +} +#endif diff --git a/gl/allocsa.h b/gl/allocsa.h new file mode 100644 index 000000000..cb6893ad1 --- /dev/null +++ b/gl/allocsa.h @@ -0,0 +1,113 @@ +/* Safe automatic memory allocation. + Copyright (C) 2003-2004 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2003. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _ALLOCSA_H +#define _ALLOCSA_H + +#include <alloca.h> +#include <stddef.h> +#include <stdlib.h> + +/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call + alloca(N); otherwise it returns NULL. It either returns N bytes of + memory allocated on the stack, that lasts until the function returns, + or NULL. + Use of safe_alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns. +*/ +#if HAVE_ALLOCA +/* The OS usually guarantees only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. + This must be a macro, not an inline function. */ +# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL) +#else +# define safe_alloca(N) ((N), NULL) +#endif + +/* allocsa(N) is a safe variant of alloca(N). It allocates N bytes of + memory allocated on the stack, that must be freed using freesa() before + the function returns. Upon failure, it returns NULL. */ +#if HAVE_ALLOCA +# define allocsa(N) \ + ((N) < 4032 - sa_increment \ + ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \ + : mallocsa (N)) +#else +# define allocsa(N) \ + mallocsa (N) +#endif +extern void * mallocsa (size_t n); + +/* Free a block of memory allocated through allocsa(). */ +#if HAVE_ALLOCA +extern void freesa (void *p); +#else +# define freesa free +#endif + +/* Maybe we should also define a variant + nallocsa (size_t n, size_t s) - behaves like allocsa (n * s) + If this would be useful in your application. please speak up. */ + + +/* ------------------- Auxiliary, non-public definitions ------------------- */ + +/* Determine the alignment of a type at compile time. */ +#if defined __GNUC__ +# define sa_alignof __alignof__ +#elif defined __cplusplus + template <class type> struct sa_alignof_helper { char __slot1; type __slot2; }; +# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2) +#elif defined __hpux + /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof + values. */ +# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) +#else +# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +enum +{ +/* The desired alignment of memory allocations is the maximum alignment + among all elementary types. */ + sa_alignment_long = sa_alignof (long), + sa_alignment_double = sa_alignof (double), +#ifdef HAVE_LONG_LONG + sa_alignment_longlong = sa_alignof (long long), +#endif +#ifdef HAVE_LONG_DOUBLE + sa_alignment_longdouble = sa_alignof (long double), +#endif + sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) +#ifdef HAVE_LONG_LONG + | (sa_alignment_longlong - 1) +#endif +#ifdef HAVE_LONG_DOUBLE + | (sa_alignment_longdouble - 1) +#endif + ) + 1, +/* The increment that guarantees room for a magic word must be >= sizeof (int) + and a multiple of sa_alignment_max. */ + sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max +}; + +#endif /* _ALLOCSA_H */ diff --git a/gl/allocsa.valgrind b/gl/allocsa.valgrind new file mode 100644 index 000000000..f4c77d686 --- /dev/null +++ b/gl/allocsa.valgrind @@ -0,0 +1,7 @@ +# Suppress a valgrind message about use of uninitialized memory in freesa(). +# This use is OK because it provides only a speedup. +{ + freesa + Memcheck:Cond + fun:freesa +} diff --git a/gl/asnprintf.c b/gl/asnprintf.c new file mode 100644 index 000000000..1b7f4ba39 --- /dev/null +++ b/gl/asnprintf.c @@ -0,0 +1,37 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include "vasnprintf.h" + +#include <stdarg.h> + +char * +asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) +{ + va_list args; + char *result; + + va_start (args, format); + result = vasnprintf (resultbuf, lengthp, format, args); + va_end (args); + return result; +} diff --git a/gl/asprintf.c b/gl/asprintf.c new file mode 100644 index 000000000..7c4e64a24 --- /dev/null +++ b/gl/asprintf.c @@ -0,0 +1,37 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include "vasprintf.h" + +#include <stdarg.h> + +int +asprintf (char **resultp, const char *format, ...) +{ + va_list args; + int result; + + va_start (args, format); + result = vasprintf (resultp, format, args); + va_end (args); + return result; +} diff --git a/gl/m4/alloca.m4 b/gl/m4/alloca.m4 new file mode 100644 index 000000000..a9e3f452c --- /dev/null +++ b/gl/m4/alloca.m4 @@ -0,0 +1,42 @@ +# alloca.m4 serial 5 +dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_ALLOCA], +[ + dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57. + AC_REQUIRE([AC_PROG_CPP]) + AC_REQUIRE([AC_PROG_EGREP]) + + AC_REQUIRE([AC_FUNC_ALLOCA]) + if test $ac_cv_func_alloca_works = no; then + gl_PREREQ_ALLOCA + fi + + # Define an additional variable used in the Makefile substitution. + if test $ac_cv_working_alloca_h = yes; then + AC_EGREP_CPP([Need own alloca], [ +#if defined __GNUC__ || defined _AIX || defined _MSC_VER + Need own alloca +#endif + ], + [AC_DEFINE(HAVE_ALLOCA, 1, + [Define to 1 if you have `alloca' after including <alloca.h>, + a header that may be supplied by this distribution.]) + ALLOCA_H=alloca.h], + [ALLOCA_H=]) + else + ALLOCA_H=alloca.h + fi + AC_SUBST([ALLOCA_H]) + + AC_DEFINE(HAVE_ALLOCA_H, 1, + [Define HAVE_ALLOCA_H for backward compatibility with older code + that includes <alloca.h> only if HAVE_ALLOCA_H is defined.]) +]) + +# Prerequisites of lib/alloca.c. +# STACK_DIRECTION is already handled by AC_FUNC_ALLOCA. +AC_DEFUN([gl_PREREQ_ALLOCA], [:]) diff --git a/gl/m4/allocsa.m4 b/gl/m4/allocsa.m4 new file mode 100644 index 000000000..474862fe3 --- /dev/null +++ b/gl/m4/allocsa.m4 @@ -0,0 +1,15 @@ +# allocsa.m4 serial 3 +dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_ALLOCSA], +[ + dnl Use the autoconf tests for alloca(), but not the AC_SUBSTed variables + dnl @ALLOCA@ and @LTALLOCA@. + AC_REQUIRE([gl_FUNC_ALLOCA]) + AC_REQUIRE([gl_EEMALLOC]) + AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) + AC_REQUIRE([gt_TYPE_LONGDOUBLE]) +]) diff --git a/gl/m4/eealloc.m4 b/gl/m4/eealloc.m4 new file mode 100644 index 000000000..adcfd06c9 --- /dev/null +++ b/gl/m4/eealloc.m4 @@ -0,0 +1,32 @@ +# eealloc.m4 serial 1 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_EEALLOC], +[ + AC_REQUIRE([gl_EEMALLOC]) + AC_REQUIRE([gl_EEREALLOC]) + AC_REQUIRE([AC_C_INLINE]) +]) + +AC_DEFUN([gl_EEMALLOC], +[ + _AC_FUNC_MALLOC_IF( + [gl_cv_func_malloc_0_nonnull=1], + [gl_cv_func_malloc_0_nonnull=0]) + AC_DEFINE_UNQUOTED([MALLOC_0_IS_NONNULL], $gl_cv_func_malloc_0_nonnull, + [If malloc(0) is != NULL, define this to 1. Otherwise define this + to 0.]) +]) + +AC_DEFUN([gl_EEREALLOC], +[ + _AC_FUNC_REALLOC_IF( + [gl_cv_func_realloc_0_nonnull=1], + [gl_cv_func_realloc_0_nonnull=0]) + AC_DEFINE_UNQUOTED([REALLOC_0_IS_NONNULL], $gl_cv_func_realloc_0_nonnull, + [If realloc(NULL,0) is != NULL, define this to 1. Otherwise define this + to 0.]) +]) diff --git a/gl/m4/eoverflow.m4 b/gl/m4/eoverflow.m4 new file mode 100644 index 000000000..8c28ca305 --- /dev/null +++ b/gl/m4/eoverflow.m4 @@ -0,0 +1,64 @@ +# eoverflow.m4 serial 1 +dnl Copyright (C) 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +# The EOVERFLOW errno value ought to be defined in <errno.h>, according to +# POSIX. But some systems (like AIX 3) don't define it, and some systems +# (like OSF/1) define it when _XOPEN_SOURCE_EXTENDED is defined. + +# Define EOVERFLOW as a C macro and as a substituted macro in such a way that +# 1. on all systems, after inclusion of <errno.h>, EOVERFLOW is usable, +# 2. on systems where EOVERFLOW is defined elsewhere, we use the same numeric +# value. + +AC_DEFUN([gl_EOVERFLOW], +[ + AC_REQUIRE([AC_PROG_CC])dnl + + AC_CACHE_CHECK([for EOVERFLOW], ac_cv_decl_EOVERFLOW, [ + AC_EGREP_CPP(yes,[ +#include <errno.h> +#ifdef EOVERFLOW +yes +#endif + ], have_eoverflow=1) + if test -n "$have_eoverflow"; then + dnl EOVERFLOW exists in <errno.h>. Don't need to define EOVERFLOW ourselves. + ac_cv_decl_EOVERFLOW=yes + else + AC_EGREP_CPP(yes,[ +#define _XOPEN_SOURCE_EXTENDED 1 +#include <errno.h> +#ifdef EOVERFLOW +yes +#endif + ], have_eoverflow=1) + if test -n "$have_eoverflow"; then + dnl EOVERFLOW exists but is hidden. + dnl Define it to the same value. + _AC_COMPUTE_INT([EOVERFLOW], ac_cv_decl_EOVERFLOW, [ +#define _XOPEN_SOURCE_EXTENDED 1 +#include <errno.h> +/* The following two lines are a workaround against an autoconf-2.52 bug. */ +#include <stdio.h> +#include <stdlib.h> +]) + else + dnl EOVERFLOW isn't defined by the system. Define EOVERFLOW ourselves, but + dnl don't define it as EINVAL, because snprintf() callers want to + dnl distinguish EINVAL and EOVERFLOW. + ac_cv_decl_EOVERFLOW=E2BIG + fi + fi + ]) + if test "$ac_cv_decl_EOVERFLOW" != yes; then + AC_DEFINE_UNQUOTED([EOVERFLOW], [$ac_cv_decl_EOVERFLOW], + [Define as good substitute value for EOVERFLOW.]) + EOVERFLOW="$ac_cv_decl_EOVERFLOW" + AC_SUBST(EOVERFLOW) + fi +]) diff --git a/gl/m4/gnulib.m4 b/gl/m4/gnulib.m4 new file mode 100644 index 000000000..46d5e338b --- /dev/null +++ b/gl/m4/gnulib.m4 @@ -0,0 +1,46 @@ +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# Generated by gnulib-tool. +# +# Invoked as: gnulib-tool --import +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=scripts alloca-opt allocsa mkdtemp setenv strpbrk strsep vasnprintf vasprintf xsize + +AC_DEFUN([gl_EARLY], +[ + AC_GNU_SOURCE +]) + +AC_DEFUN([gl_INIT], +[ + gl_FUNC_ALLOCA + gl_ALLOCSA + gt_FUNC_MKDTEMP + gt_FUNC_SETENV + gl_FUNC_STRPBRK + gl_FUNC_STRSEP + gl_FUNC_VASNPRINTF + gl_FUNC_VASPRINTF + gl_XSIZE +]) + +dnl Usage: gl_MODULES(module1 module2 ...) +AC_DEFUN([gl_MODULES], []) + +dnl Usage: gl_SOURCE_BASE(DIR) +AC_DEFUN([gl_SOURCE_BASE], []) + +dnl Usage: gl_M4_BASE(DIR) +AC_DEFUN([gl_M4_BASE], []) + +dnl Usage: gl_LIB(LIBNAME) +AC_DEFUN([gl_LIB], []) + +dnl Usage: gl_LGPL +AC_DEFUN([gl_LGPL], []) + +# gnulib.m4 ends here diff --git a/gl/m4/intmax_t.m4 b/gl/m4/intmax_t.m4 new file mode 100644 index 000000000..44b16523c --- /dev/null +++ b/gl/m4/intmax_t.m4 @@ -0,0 +1,61 @@ +# intmax_t.m4 serial 4 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ(2.13) + +# Define intmax_t to 'long' or 'long long' +# if it is not already defined in <stdint.h> or <inttypes.h>. + +AC_DEFUN([gl_AC_TYPE_INTMAX_T], +[ + dnl For simplicity, we assume that a header file defines 'intmax_t' if and + dnl only if it defines 'uintmax_t'. + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) + test $ac_cv_type_long_long = yes \ + && ac_type='long long' \ + || ac_type='long' + AC_DEFINE_UNQUOTED(intmax_t, $ac_type, + [Define to long or long long if <inttypes.h> and <stdint.h> don't define.]) + else + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.]) + fi +]) + +dnl An alternative would be to explicitly test for 'intmax_t'. + +AC_DEFUN([gt_AC_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, + [AC_TRY_COMPILE([ +#include <stddef.h> +#include <stdlib.h> +#if HAVE_STDINT_H_WITH_UINTMAX +#include <stdint.h> +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include <inttypes.h> +#endif +], [intmax_t x = -1;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.]) + else + AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) + test $ac_cv_type_long_long = yes \ + && ac_type='long long' \ + || ac_type='long' + AC_DEFINE_UNQUOTED(intmax_t, $ac_type, + [Define to long or long long if <stdint.h> and <inttypes.h> don't define.]) + fi +]) diff --git a/gl/m4/inttypes_h.m4 b/gl/m4/inttypes_h.m4 new file mode 100644 index 000000000..a5d075d96 --- /dev/null +++ b/gl/m4/inttypes_h.m4 @@ -0,0 +1,26 @@ +# inttypes_h.m4 serial 6 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists, +# doesn't clash with <sys/types.h>, and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, + [AC_TRY_COMPILE( + [#include <sys/types.h> +#include <inttypes.h>], + [uintmax_t i = (uintmax_t) -1;], + gl_cv_header_inttypes_h=yes, + gl_cv_header_inttypes_h=no)]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, + [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, + and declares uintmax_t. ]) + fi +]) diff --git a/gl/m4/longdouble.m4 b/gl/m4/longdouble.m4 new file mode 100644 index 000000000..40cd7ce02 --- /dev/null +++ b/gl/m4/longdouble.m4 @@ -0,0 +1,28 @@ +# longdouble.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the compiler supports the 'long double' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_LONGDOUBLE], +[ + AC_CACHE_CHECK([for long double], gt_cv_c_long_double, + [if test "$GCC" = yes; then + gt_cv_c_long_double=yes + else + AC_TRY_COMPILE([ + /* The Stardent Vistra knows sizeof(long double), but does not support it. */ + long double foo = 0.0; + /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ + int array [2*(sizeof(long double) >= sizeof(double)) - 1]; + ], , + gt_cv_c_long_double=yes, gt_cv_c_long_double=no) + fi]) + if test $gt_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) + fi +]) diff --git a/gl/m4/longlong.m4 b/gl/m4/longlong.m4 new file mode 100644 index 000000000..7b399e012 --- /dev/null +++ b/gl/m4/longlong.m4 @@ -0,0 +1,23 @@ +# longlong.m4 serial 5 +dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG if 'long long' works. + +AC_DEFUN([gl_AC_TYPE_LONG_LONG], +[ + AC_CACHE_CHECK([for long long], ac_cv_type_long_long, + [AC_TRY_LINK([long long ll = 1LL; int i = 63;], + [long long llmax = (long long) -1; + return ll << i | ll >> i | llmax / ll | llmax % ll;], + ac_cv_type_long_long=yes, + ac_cv_type_long_long=no)]) + if test $ac_cv_type_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, + [Define if you have the 'long long' type.]) + fi +]) diff --git a/gl/m4/mkdtemp.m4 b/gl/m4/mkdtemp.m4 new file mode 100644 index 000000000..e02c8256c --- /dev/null +++ b/gl/m4/mkdtemp.m4 @@ -0,0 +1,23 @@ +# mkdtemp.m4 serial 3 +dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gt_FUNC_MKDTEMP], +[ + AC_REPLACE_FUNCS(mkdtemp) + if test $ac_cv_func_mkdtemp = no; then + gl_PREREQ_MKDTEMP + fi +]) + +# Prerequisites of lib/mkdtemp.c +AC_DEFUN([gl_PREREQ_MKDTEMP], +[ + AC_REQUIRE([AC_HEADER_STAT]) + AC_CHECK_HEADERS_ONCE(sys/time.h unistd.h) + AC_CHECK_HEADERS(time.h) + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T]) + AC_CHECK_FUNCS(gettimeofday) +]) diff --git a/gl/m4/onceonly_2_57.m4 b/gl/m4/onceonly_2_57.m4 new file mode 100644 index 000000000..9fc510e06 --- /dev/null +++ b/gl/m4/onceonly_2_57.m4 @@ -0,0 +1,86 @@ +# onceonly_2_57.m4 serial 3 +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl This file defines some "once only" variants of standard autoconf macros. +dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS +dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS +dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS +dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC +dnl The advantage is that the check for each of the headers/functions/decls +dnl will be put only once into the 'configure' file. It keeps the size of +dnl the 'configure' file down, and avoids redundant output when 'configure' +dnl is run. +dnl The drawback is that the checks cannot be conditionalized. If you write +dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi +dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to +dnl empty, and the check will be inserted before the body of the AC_DEFUNed +dnl function. + +dnl This is like onceonly.m4, except that it uses diversions to named sections +dnl DEFAULTS and INIT_PREPARE in order to check all requested headers at once, +dnl thus reducing the size of 'configure'. Works with autoconf-2.57. The +dnl size reduction is ca. 9%. + +dnl Autoconf version 2.57 or newer is recommended. +AC_PREREQ(2.54) + +# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of +# AC_CHECK_HEADERS(HEADER1 HEADER2 ...). +AC_DEFUN([AC_CHECK_HEADERS_ONCE], [ + : + AC_FOREACH([gl_HEADER_NAME], [$1], [ + AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, + [./-], [___])), [ + m4_divert_text([INIT_PREPARE], + [gl_header_list="$gl_header_list gl_HEADER_NAME"]) + gl_HEADERS_EXPANSION + AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_HEADER_NAME])), + [Define to 1 if you have the <]m4_defn([gl_HEADER_NAME])[> header file.]) + ]) + AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, + [./-], [___]))) + ]) +]) +m4_define([gl_HEADERS_EXPANSION], [ + m4_divert_text([DEFAULTS], [gl_header_list=]) + AC_CHECK_HEADERS([$gl_header_list]) + m4_define([gl_HEADERS_EXPANSION], []) +]) + +# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of +# AC_CHECK_FUNCS(FUNC1 FUNC2 ...). +AC_DEFUN([AC_CHECK_FUNCS_ONCE], [ + : + AC_FOREACH([gl_FUNC_NAME], [$1], [ + AC_DEFUN([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]), [ + m4_divert_text([INIT_PREPARE], + [gl_func_list="$gl_func_list gl_FUNC_NAME"]) + gl_FUNCS_EXPANSION + AH_TEMPLATE(AS_TR_CPP([HAVE_]m4_defn([gl_FUNC_NAME])), + [Define to 1 if you have the `]m4_defn([gl_FUNC_NAME])[' function.]) + ]) + AC_REQUIRE([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME])) + ]) +]) +m4_define([gl_FUNCS_EXPANSION], [ + m4_divert_text([DEFAULTS], [gl_func_list=]) + AC_CHECK_FUNCS([$gl_func_list]) + m4_define([gl_FUNCS_EXPANSION], []) +]) + +# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of +# AC_CHECK_DECLS(DECL1, DECL2, ...). +AC_DEFUN([AC_CHECK_DECLS_ONCE], [ + : + AC_FOREACH([gl_DECL_NAME], [$1], [ + AC_DEFUN([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]), [ + AC_CHECK_DECLS(m4_defn([gl_DECL_NAME])) + ]) + AC_REQUIRE([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME])) + ]) +]) diff --git a/gl/m4/setenv.m4 b/gl/m4/setenv.m4 new file mode 100644 index 000000000..4c76be1ff --- /dev/null +++ b/gl/m4/setenv.m4 @@ -0,0 +1,70 @@ +# setenv.m4 serial 5 +dnl Copyright (C) 2001-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gt_FUNC_SETENV], +[ + AC_REPLACE_FUNCS(setenv unsetenv) + if test $ac_cv_func_setenv = no; then + gl_PREREQ_SETENV + fi + if test $ac_cv_func_unsetenv = no; then + gl_PREREQ_UNSETENV + else + AC_CACHE_CHECK([for unsetenv() return type], gt_cv_func_unsetenv_ret, + [AC_TRY_COMPILE([#include <stdlib.h> +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +int unsetenv (const char *name); +#else +int unsetenv(); +#endif +], , gt_cv_func_unsetenv_ret='int', gt_cv_func_unsetenv_ret='void')]) + if test $gt_cv_func_unsetenv_ret = 'void'; then + AC_DEFINE(VOID_UNSETENV, 1, [Define if unsetenv() returns void, not int.]) + fi + fi +]) + +# Check if a variable is properly declared. +# gt_CHECK_VAR_DECL(includes,variable) +AC_DEFUN([gt_CHECK_VAR_DECL], +[ + define([gt_cv_var], [gt_cv_var_]$2[_declaration]) + AC_MSG_CHECKING([if $2 is properly declared]) + AC_CACHE_VAL(gt_cv_var, [ + AC_TRY_COMPILE([$1 + extern struct { int foo; } $2;], + [$2.foo = 1;], + gt_cv_var=no, + gt_cv_var=yes)]) + AC_MSG_RESULT($gt_cv_var) + if test $gt_cv_var = yes; then + AC_DEFINE([HAVE_]translit($2, [a-z], [A-Z])[_DECL], 1, + [Define if you have the declaration of $2.]) + fi +]) + +# Prerequisites of lib/setenv.c. +AC_DEFUN([gl_PREREQ_SETENV], +[ + AC_REQUIRE([AC_FUNC_ALLOCA]) + AC_CHECK_HEADERS_ONCE(unistd.h) + AC_CHECK_HEADERS(search.h) + AC_CHECK_FUNCS(tsearch) + gt_CHECK_VAR_DECL([#include <errno.h>], errno) + gt_CHECK_VAR_DECL([#include <unistd.h>], environ) +]) + +# Prerequisites of lib/unsetenv.c. +AC_DEFUN([gl_PREREQ_UNSETENV], +[ + AC_CHECK_HEADERS_ONCE(unistd.h) + gt_CHECK_VAR_DECL([#include <errno.h>], errno) + gt_CHECK_VAR_DECL([#include <unistd.h>], environ) +]) diff --git a/gl/m4/signed.m4 b/gl/m4/signed.m4 new file mode 100644 index 000000000..048f59369 --- /dev/null +++ b/gl/m4/signed.m4 @@ -0,0 +1,17 @@ +# signed.m4 serial 1 (gettext-0.10.40) +dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([bh_C_SIGNED], +[ + AC_CACHE_CHECK([for signed], bh_cv_c_signed, + [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) + if test $bh_cv_c_signed = no; then + AC_DEFINE(signed, , + [Define to empty if the C compiler doesn't support this keyword.]) + fi +]) diff --git a/gl/m4/size_max.m4 b/gl/m4/size_max.m4 new file mode 100644 index 000000000..4fe81c7b0 --- /dev/null +++ b/gl/m4/size_max.m4 @@ -0,0 +1,59 @@ +# size_max.m4 serial 2 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS(stdint.h) + dnl First test whether the system already has SIZE_MAX. + AC_MSG_CHECKING([for SIZE_MAX]) + result= + AC_EGREP_CPP([Found it], [ +#include <limits.h> +#if HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef SIZE_MAX +Found it +#endif +], result=yes) + if test -z "$result"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. + dnl The _AC_COMPUTE_INT macro works up to LONG_MAX, since it uses 'expr', + dnl which is guaranteed to work from LONG_MIN to LONG_MAX. + _AC_COMPUTE_INT([~(size_t)0 / 10], res_hi, + [#include <stddef.h>], result=?) + _AC_COMPUTE_INT([~(size_t)0 % 10], res_lo, + [#include <stddef.h>], result=?) + _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, + [#include <stddef.h>], result=?) + if test "$fits_in_uint" = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include <stddef.h> + extern size_t foo; + extern unsigned long foo; + ], [], fits_in_uint=0) + fi + if test -z "$result"; then + if test "$fits_in_uint" = 1; then + result="$res_hi$res_lo"U + else + result="$res_hi$res_lo"UL + fi + else + dnl Shouldn't happen, but who knows... + result='~(size_t)0' + fi + fi + AC_MSG_RESULT([$result]) + if test "$result" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$result], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi +]) diff --git a/gl/m4/stdint_h.m4 b/gl/m4/stdint_h.m4 new file mode 100644 index 000000000..3355f35aa --- /dev/null +++ b/gl/m4/stdint_h.m4 @@ -0,0 +1,26 @@ +# stdint_h.m4 serial 5 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists, +# doesn't clash with <sys/types.h>, and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, + [AC_TRY_COMPILE( + [#include <sys/types.h> +#include <stdint.h>], + [uintmax_t i = (uintmax_t) -1;], + gl_cv_header_stdint_h=yes, + gl_cv_header_stdint_h=no)]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, + [Define if <stdint.h> exists, doesn't clash with <sys/types.h>, + and declares uintmax_t. ]) + fi +]) diff --git a/gl/m4/strpbrk.m4 b/gl/m4/strpbrk.m4 new file mode 100644 index 000000000..68360684e --- /dev/null +++ b/gl/m4/strpbrk.m4 @@ -0,0 +1,16 @@ +# strpbrk.m4 serial 2 +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRPBRK], +[ + AC_REPLACE_FUNCS(strpbrk) + if test $ac_cv_func_strpbrk = no; then + gl_PREREQ_STRPBRK + fi +]) + +# Prerequisites of lib/strpbrk.c. +AC_DEFUN([gl_PREREQ_STRPBRK], [:]) diff --git a/gl/m4/strsep.m4 b/gl/m4/strsep.m4 new file mode 100644 index 000000000..40a087b3d --- /dev/null +++ b/gl/m4/strsep.m4 @@ -0,0 +1,17 @@ +# strsep.m4 serial 3 +dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRSEP], +[ + dnl Persuade glibc <string.h> to declare strsep(). + AC_REQUIRE([AC_GNU_SOURCE]) + + AC_REPLACE_FUNCS(strsep) + gl_PREREQ_STRSEP +]) + +# Prerequisites of lib/strsep.c. +AC_DEFUN([gl_PREREQ_STRSEP], [:]) diff --git a/gl/m4/uintmax_t.m4 b/gl/m4/uintmax_t.m4 new file mode 100644 index 000000000..bf83ed746 --- /dev/null +++ b/gl/m4/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 9 +dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ(2.13) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in <stdint.h> or <inttypes.h>. + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([gl_AC_TYPE_UNSIGNED_LONG_LONG]) + test $ac_cv_type_unsigned_long_long = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, + [Define to unsigned long or unsigned long long + if <stdint.h> and <inttypes.h> don't define.]) + else + AC_DEFINE(HAVE_UINTMAX_T, 1, + [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.]) + fi +]) diff --git a/gl/m4/ulonglong.m4 b/gl/m4/ulonglong.m4 new file mode 100644 index 000000000..dee10ccc3 --- /dev/null +++ b/gl/m4/ulonglong.m4 @@ -0,0 +1,23 @@ +# ulonglong.m4 serial 4 +dnl Copyright (C) 1999-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. + +AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG], +[ + AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, + [AC_TRY_LINK([unsigned long long ull = 1ULL; int i = 63;], + [unsigned long long ullmax = (unsigned long long) -1; + return ull << i | ull >> i | ullmax / ull | ullmax % ull;], + ac_cv_type_unsigned_long_long=yes, + ac_cv_type_unsigned_long_long=no)]) + if test $ac_cv_type_unsigned_long_long = yes; then + AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, + [Define if you have the 'unsigned long long' type.]) + fi +]) diff --git a/gl/m4/vasnprintf.m4 b/gl/m4/vasnprintf.m4 new file mode 100644 index 000000000..7ff343035 --- /dev/null +++ b/gl/m4/vasnprintf.m4 @@ -0,0 +1,58 @@ +# vasnprintf.m4 serial 5 +dnl Copyright (C) 2002-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_VASNPRINTF], +[ + AC_REQUIRE([gl_EOVERFLOW]) + AC_REPLACE_FUNCS(vasnprintf) + if test $ac_cv_func_vasnprintf = no; then + AC_LIBOBJ(printf-args) + AC_LIBOBJ(printf-parse) + AC_LIBOBJ(asnprintf) + gl_PREREQ_PRINTF_ARGS + gl_PREREQ_PRINTF_PARSE + gl_PREREQ_VASNPRINTF + gl_PREREQ_ASNPRINTF + fi +]) + +# Prequisites of lib/printf-args.h, lib/printf-args.c. +AC_DEFUN([gl_PREREQ_PRINTF_ARGS], +[ + AC_REQUIRE([bh_C_SIGNED]) + AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) + AC_REQUIRE([gt_TYPE_LONGDOUBLE]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + AC_REQUIRE([gt_TYPE_WINT_T]) +]) + +# Prequisites of lib/printf-parse.h, lib/printf-parse.c. +AC_DEFUN([gl_PREREQ_PRINTF_PARSE], +[ + AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) + AC_REQUIRE([gt_TYPE_LONGDOUBLE]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + AC_REQUIRE([gt_TYPE_WINT_T]) + AC_REQUIRE([AC_TYPE_SIZE_T]) + AC_CHECK_TYPES(ptrdiff_t) + AC_REQUIRE([gt_AC_TYPE_INTMAX_T]) +]) + +# Prerequisites of lib/vasnprintf.c. +AC_DEFUN([gl_PREREQ_VASNPRINTF], +[ + AC_REQUIRE([AC_FUNC_ALLOCA]) + AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) + AC_REQUIRE([gt_TYPE_LONGDOUBLE]) + AC_REQUIRE([gt_TYPE_WCHAR_T]) + AC_REQUIRE([gt_TYPE_WINT_T]) + AC_CHECK_FUNCS(snprintf wcslen) +]) + +# Prerequisites of lib/asnprintf.c. +AC_DEFUN([gl_PREREQ_ASNPRINTF], +[ +]) diff --git a/gl/m4/vasprintf.m4 b/gl/m4/vasprintf.m4 new file mode 100644 index 000000000..385e92edd --- /dev/null +++ b/gl/m4/vasprintf.m4 @@ -0,0 +1,25 @@ +# vasprintf.m4 serial 1 +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_VASPRINTF], +[ + AC_REPLACE_FUNCS(vasprintf) + if test $ac_cv_func_vasprintf = no; then + AC_LIBOBJ(asprintf) + gl_PREREQ_VASPRINTF + gl_PREREQ_ASPRINTF + fi +]) + +# Prerequisites of lib/vasprintf.c. +AC_DEFUN([gl_PREREQ_VASPRINTF], +[ +]) + +# Prerequisites of lib/asprintf.c. +AC_DEFUN([gl_PREREQ_ASPRINTF], +[ +]) diff --git a/gl/m4/wchar_t.m4 b/gl/m4/wchar_t.m4 new file mode 100644 index 000000000..cde2129a9 --- /dev/null +++ b/gl/m4/wchar_t.m4 @@ -0,0 +1,20 @@ +# wchar_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether <stddef.h> has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, + [AC_TRY_COMPILE([#include <stddef.h> + wchar_t foo = (wchar_t)'\0';], , + gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/gl/m4/wint_t.m4 b/gl/m4/wint_t.m4 new file mode 100644 index 000000000..b8fff9c86 --- /dev/null +++ b/gl/m4/wint_t.m4 @@ -0,0 +1,20 @@ +# wint_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether <wchar.h> has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, + [AC_TRY_COMPILE([#include <wchar.h> + wint_t foo = (wchar_t)'\0';], , + gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/gl/m4/xsize.m4 b/gl/m4/xsize.m4 new file mode 100644 index 000000000..85bb721e4 --- /dev/null +++ b/gl/m4/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 3 +dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS(stdint.h) +]) diff --git a/gl/mkdtemp.c b/gl/mkdtemp.c new file mode 100644 index 000000000..469cf4718 --- /dev/null +++ b/gl/mkdtemp.c @@ -0,0 +1,203 @@ +/* Copyright (C) 1999, 2001-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Extracted from misc/mkdtemp.c and sysdeps/posix/tempname.c. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "mkdtemp.h" + +#include <errno.h> +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include <stdio.h> +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif + +#if HAVE_STDINT_H || _LIBC +# include <stdint.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#if HAVE_UNISTD_H || _LIBC +# include <unistd.h> +#endif + +#if HAVE_GETTIMEOFDAY || _LIBC +# if HAVE_SYS_TIME_H || _LIBC +# include <sys/time.h> +# endif +#else +# if HAVE_TIME_H || _LIBC +# include <time.h> +# endif +#endif + +#include <sys/stat.h> +#if STAT_MACROS_BROKEN +# undef S_ISDIR +#endif +#if !defined S_ISDIR && defined S_IFDIR +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif + +#ifdef __MINGW32__ +/* mingw's mkdir() function has 1 argument, but we pass 2 arguments. + Therefore we have to disable the argument count checking. */ +# define mkdir ((int (*)()) mkdir) +#endif + +#if !_LIBC +# define __getpid getpid +# define __gettimeofday gettimeofday +# define __mkdir mkdir +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to __gen_tempname. TMPL is + overwritten with the result. + + KIND is: + __GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +static int +gen_tempname (char *tmpl) +{ + int len; + char *XXXXXX; + static uint64_t value; + uint64_t random_time_bits; + int count, fd = -1; + int save_errno = errno; + + len = strlen (tmpl); + if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6]; + + /* Get some more or less random data. */ +#ifdef RANDOM_BITS + RANDOM_BITS (random_time_bits); +#else +# if HAVE_GETTIMEOFDAY || _LIBC + { + struct timeval tv; + __gettimeofday (&tv, NULL); + random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; + } +# else + random_time_bits = time (NULL); +# endif +#endif + value += random_time_bits ^ __getpid (); + + for (count = 0; count < TMP_MAX; value += 7777, ++count) + { + uint64_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} + +/* Generate a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + The directory is created, mode 700, and its name is returned. + (This function comes from OpenBSD.) */ +char * +mkdtemp (char *template) +{ + if (gen_tempname (template)) + return NULL; + else + return template; +} diff --git a/gl/mkdtemp.h b/gl/mkdtemp.h new file mode 100644 index 000000000..617604801 --- /dev/null +++ b/gl/mkdtemp.h @@ -0,0 +1,32 @@ +/* Creating a private temporary directory. + Copyright (C) 2001-2002 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if HAVE_MKDTEMP + +/* Get mkdtemp() declaration. */ +#include <stdlib.h> + +#else + +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +extern char * mkdtemp (char *template); + +#endif diff --git a/gl/printf-args.c b/gl/printf-args.c new file mode 100644 index 000000000..0ed1acbb8 --- /dev/null +++ b/gl/printf-args.c @@ -0,0 +1,118 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include "printf-args.h" + +#ifdef STATIC +STATIC +#endif +int +printf_fetchargs (va_list args, arguments *a) +{ + size_t i; + argument *ap; + + for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) + switch (ap->type) + { + case TYPE_SCHAR: + ap->a.a_schar = va_arg (args, /*signed char*/ int); + break; + case TYPE_UCHAR: + ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); + break; + case TYPE_SHORT: + ap->a.a_short = va_arg (args, /*short*/ int); + break; + case TYPE_USHORT: + ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); + break; + case TYPE_INT: + ap->a.a_int = va_arg (args, int); + break; + case TYPE_UINT: + ap->a.a_uint = va_arg (args, unsigned int); + break; + case TYPE_LONGINT: + ap->a.a_longint = va_arg (args, long int); + break; + case TYPE_ULONGINT: + ap->a.a_ulongint = va_arg (args, unsigned long int); + break; +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + ap->a.a_longlongint = va_arg (args, long long int); + break; + case TYPE_ULONGLONGINT: + ap->a.a_ulonglongint = va_arg (args, unsigned long long int); + break; +#endif + case TYPE_DOUBLE: + ap->a.a_double = va_arg (args, double); + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + ap->a.a_longdouble = va_arg (args, long double); + break; +#endif + case TYPE_CHAR: + ap->a.a_char = va_arg (args, int); + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: + ap->a.a_wide_char = va_arg (args, wint_t); + break; +#endif + case TYPE_STRING: + ap->a.a_string = va_arg (args, const char *); + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + ap->a.a_wide_string = va_arg (args, const wchar_t *); + break; +#endif + case TYPE_POINTER: + ap->a.a_pointer = va_arg (args, void *); + break; + case TYPE_COUNT_SCHAR_POINTER: + ap->a.a_count_schar_pointer = va_arg (args, signed char *); + break; + case TYPE_COUNT_SHORT_POINTER: + ap->a.a_count_short_pointer = va_arg (args, short *); + break; + case TYPE_COUNT_INT_POINTER: + ap->a.a_count_int_pointer = va_arg (args, int *); + break; + case TYPE_COUNT_LONGINT_POINTER: + ap->a.a_count_longint_pointer = va_arg (args, long int *); + break; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); + break; +#endif + default: + /* Unknown type. */ + return -1; + } + return 0; +} diff --git a/gl/printf-args.h b/gl/printf-args.h new file mode 100644 index 000000000..cec1cc6c2 --- /dev/null +++ b/gl/printf-args.h @@ -0,0 +1,136 @@ +/* Decomposed printf argument list. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _PRINTF_ARGS_H +#define _PRINTF_ARGS_H + +/* Get size_t. */ +#include <stddef.h> + +/* Get wchar_t. */ +#ifdef HAVE_WCHAR_T +# include <stddef.h> +#endif + +/* Get wint_t. */ +#ifdef HAVE_WINT_T +# include <wchar.h> +#endif + +/* Get va_list. */ +#include <stdarg.h> + + +/* Argument types */ +typedef enum +{ + TYPE_NONE, + TYPE_SCHAR, + TYPE_UCHAR, + TYPE_SHORT, + TYPE_USHORT, + TYPE_INT, + TYPE_UINT, + TYPE_LONGINT, + TYPE_ULONGINT, +#ifdef HAVE_LONG_LONG + TYPE_LONGLONGINT, + TYPE_ULONGLONGINT, +#endif + TYPE_DOUBLE, +#ifdef HAVE_LONG_DOUBLE + TYPE_LONGDOUBLE, +#endif + TYPE_CHAR, +#ifdef HAVE_WINT_T + TYPE_WIDE_CHAR, +#endif + TYPE_STRING, +#ifdef HAVE_WCHAR_T + TYPE_WIDE_STRING, +#endif + TYPE_POINTER, + TYPE_COUNT_SCHAR_POINTER, + TYPE_COUNT_SHORT_POINTER, + TYPE_COUNT_INT_POINTER, + TYPE_COUNT_LONGINT_POINTER +#ifdef HAVE_LONG_LONG +, TYPE_COUNT_LONGLONGINT_POINTER +#endif +} arg_type; + +/* Polymorphic argument */ +typedef struct +{ + arg_type type; + union + { + signed char a_schar; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long int a_longint; + unsigned long int a_ulongint; +#ifdef HAVE_LONG_LONG + long long int a_longlongint; + unsigned long long int a_ulonglongint; +#endif + float a_float; + double a_double; +#ifdef HAVE_LONG_DOUBLE + long double a_longdouble; +#endif + int a_char; +#ifdef HAVE_WINT_T + wint_t a_wide_char; +#endif + const char* a_string; +#ifdef HAVE_WCHAR_T + const wchar_t* a_wide_string; +#endif + void* a_pointer; + signed char * a_count_schar_pointer; + short * a_count_short_pointer; + int * a_count_int_pointer; + long int * a_count_longint_pointer; +#ifdef HAVE_LONG_LONG + long long int * a_count_longlongint_pointer; +#endif + } + a; +} +argument; + +typedef struct +{ + size_t count; + argument *arg; +} +arguments; + + +/* Fetch the arguments, putting them into a. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int printf_fetchargs (va_list args, arguments *a); + +#endif /* _PRINTF_ARGS_H */ diff --git a/gl/printf-parse.c b/gl/printf-parse.c new file mode 100644 index 000000000..3d2fb175f --- /dev/null +++ b/gl/printf-parse.c @@ -0,0 +1,536 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Get size_t, NULL. */ +#include <stddef.h> + +/* Get intmax_t. */ +#if HAVE_STDINT_H_WITH_UINTMAX +# include <stdint.h> +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +# include <inttypes.h> +#endif + +/* malloc(), realloc(), free(). */ +#include <stdlib.h> + +/* Checked size_t computations. */ +#include "xsize.h" + +#if WIDE_CHAR_VERSION +# define PRINTF_PARSE wprintf_parse +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +#else +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#endif + +#ifdef STATIC +STATIC +#endif +int +PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) +{ + const CHAR_T *cp = format; /* pointer into format */ + size_t arg_posn = 0; /* number of regular arguments consumed */ + size_t d_allocated; /* allocated elements of d->dir */ + size_t a_allocated; /* allocated elements of a->arg */ + size_t max_width_length = 0; + size_t max_precision_length = 0; + + d->count = 0; + d_allocated = 1; + d->dir = malloc (d_allocated * sizeof (DIRECTIVE)); + if (d->dir == NULL) + /* Out of memory. */ + return -1; + + a->count = 0; + a_allocated = 0; + a->arg = NULL; + +#define REGISTER_ARG(_index_,_type_) \ + { \ + size_t n = (_index_); \ + if (n >= a_allocated) \ + { \ + size_t memory_size; \ + argument *memory; \ + \ + a_allocated = xtimes (a_allocated, 2); \ + if (a_allocated <= n) \ + a_allocated = xsum (n, 1); \ + memory_size = xtimes (a_allocated, sizeof (argument)); \ + if (size_overflow_p (memory_size)) \ + /* Overflow, would lead to out of memory. */ \ + goto error; \ + memory = (a->arg \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ + if (memory == NULL) \ + /* Out of memory. */ \ + goto error; \ + a->arg = memory; \ + } \ + while (a->count <= n) \ + a->arg[a->count++].type = TYPE_NONE; \ + if (a->arg[n].type == TYPE_NONE) \ + a->arg[n].type = (_type_); \ + else if (a->arg[n].type != (_type_)) \ + /* Ambiguous type for positional argument. */ \ + goto error; \ + } + + while (*cp != '\0') + { + CHAR_T c = *cp++; + if (c == '%') + { + size_t arg_index = ARG_NONE; + DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */ + + /* Initialize the next directive. */ + dp->dir_start = cp - 1; + dp->flags = 0; + dp->width_start = NULL; + dp->width_end = NULL; + dp->width_arg_index = ARG_NONE; + dp->precision_start = NULL; + dp->precision_end = NULL; + dp->precision_arg_index = ARG_NONE; + dp->arg_index = ARG_NONE; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + arg_index = n - 1; + cp = np + 1; + } + } + + /* Read the flags. */ + for (;;) + { + if (*cp == '\'') + { + dp->flags |= FLAG_GROUP; + cp++; + } + else if (*cp == '-') + { + dp->flags |= FLAG_LEFT; + cp++; + } + else if (*cp == '+') + { + dp->flags |= FLAG_SHOWSIGN; + cp++; + } + else if (*cp == ' ') + { + dp->flags |= FLAG_SPACE; + cp++; + } + else if (*cp == '#') + { + dp->flags |= FLAG_ALT; + cp++; + } + else if (*cp == '0') + { + dp->flags |= FLAG_ZERO; + cp++; + } + else + break; + } + + /* Parse the field width. */ + if (*cp == '*') + { + dp->width_start = cp; + cp++; + dp->width_end = cp; + if (max_width_length < 1) + max_width_length = 1; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory later. */ + goto error; + dp->width_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->width_arg_index == ARG_NONE) + { + dp->width_arg_index = arg_posn++; + if (dp->width_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->width_arg_index, TYPE_INT); + } + else if (*cp >= '0' && *cp <= '9') + { + size_t width_length; + + dp->width_start = cp; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->width_end = cp; + width_length = dp->width_end - dp->width_start; + if (max_width_length < width_length) + max_width_length = width_length; + } + + /* Parse the precision. */ + if (*cp == '.') + { + cp++; + if (*cp == '*') + { + dp->precision_start = cp - 1; + cp++; + dp->precision_end = cp; + if (max_precision_length < 2) + max_precision_length = 2; + + /* Test for positional argument. */ + if (*cp >= '0' && *cp <= '9') + { + const CHAR_T *np; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + ; + if (*np == '$') + { + size_t n = 0; + + for (np = cp; *np >= '0' && *np <= '9'; np++) + n = xsum (xtimes (n, 10), *np - '0'); + if (n == 0) + /* Positional argument 0. */ + goto error; + if (size_overflow_p (n)) + /* n too large, would lead to out of memory + later. */ + goto error; + dp->precision_arg_index = n - 1; + cp = np + 1; + } + } + if (dp->precision_arg_index == ARG_NONE) + { + dp->precision_arg_index = arg_posn++; + if (dp->precision_arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->precision_arg_index, TYPE_INT); + } + else + { + size_t precision_length; + + dp->precision_start = cp - 1; + for (; *cp >= '0' && *cp <= '9'; cp++) + ; + dp->precision_end = cp; + precision_length = dp->precision_end - dp->precision_start; + if (max_precision_length < precision_length) + max_precision_length = precision_length; + } + } + + { + arg_type type; + + /* Parse argument type/size specifiers. */ + { + int flags = 0; + + for (;;) + { + if (*cp == 'h') + { + flags |= (1 << (flags & 1)); + cp++; + } + else if (*cp == 'L') + { + flags |= 4; + cp++; + } + else if (*cp == 'l') + { + flags += 8; + cp++; + } +#ifdef HAVE_INTMAX_T + else if (*cp == 'j') + { + if (sizeof (intmax_t) > sizeof (long)) + { + /* intmax_t = long long */ + flags += 16; + } + else if (sizeof (intmax_t) > sizeof (int)) + { + /* intmax_t = long */ + flags += 8; + } + cp++; + } +#endif + else if (*cp == 'z' || *cp == 'Z') + { + /* 'z' is standardized in ISO C 99, but glibc uses 'Z' + because the warning facility in gcc-2.95.2 understands + only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ + if (sizeof (size_t) > sizeof (long)) + { + /* size_t = long long */ + flags += 16; + } + else if (sizeof (size_t) > sizeof (int)) + { + /* size_t = long */ + flags += 8; + } + cp++; + } + else if (*cp == 't') + { + if (sizeof (ptrdiff_t) > sizeof (long)) + { + /* ptrdiff_t = long long */ + flags += 16; + } + else if (sizeof (ptrdiff_t) > sizeof (int)) + { + /* ptrdiff_t = long */ + flags += 8; + } + cp++; + } + else + break; + } + + /* Read the conversion character. */ + c = *cp++; + switch (c) + { + case 'd': case 'i': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGLONGINT; + else +#endif + if (flags >= 8) + type = TYPE_LONGINT; + else if (flags & 2) + type = TYPE_SCHAR; + else if (flags & 1) + type = TYPE_SHORT; + else + type = TYPE_INT; + break; + case 'o': case 'u': case 'x': case 'X': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_ULONGLONGINT; + else +#endif + if (flags >= 8) + type = TYPE_ULONGINT; + else if (flags & 2) + type = TYPE_UCHAR; + else if (flags & 1) + type = TYPE_USHORT; + else + type = TYPE_UINT; + break; + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': +#ifdef HAVE_LONG_DOUBLE + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGDOUBLE; + else +#endif + type = TYPE_DOUBLE; + break; + case 'c': + if (flags >= 8) +#ifdef HAVE_WINT_T + type = TYPE_WIDE_CHAR; +#else + goto error; +#endif + else + type = TYPE_CHAR; + break; +#ifdef HAVE_WINT_T + case 'C': + type = TYPE_WIDE_CHAR; + c = 'c'; + break; +#endif + case 's': + if (flags >= 8) +#ifdef HAVE_WCHAR_T + type = TYPE_WIDE_STRING; +#else + goto error; +#endif + else + type = TYPE_STRING; + break; +#ifdef HAVE_WCHAR_T + case 'S': + type = TYPE_WIDE_STRING; + c = 's'; + break; +#endif + case 'p': + type = TYPE_POINTER; + break; + case 'n': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_COUNT_LONGLONGINT_POINTER; + else +#endif + if (flags >= 8) + type = TYPE_COUNT_LONGINT_POINTER; + else if (flags & 2) + type = TYPE_COUNT_SCHAR_POINTER; + else if (flags & 1) + type = TYPE_COUNT_SHORT_POINTER; + else + type = TYPE_COUNT_INT_POINTER; + break; + case '%': + type = TYPE_NONE; + break; + default: + /* Unknown conversion character. */ + goto error; + } + } + + if (type != TYPE_NONE) + { + dp->arg_index = arg_index; + if (dp->arg_index == ARG_NONE) + { + dp->arg_index = arg_posn++; + if (dp->arg_index == ARG_NONE) + /* arg_posn wrapped around. */ + goto error; + } + REGISTER_ARG (dp->arg_index, type); + } + dp->conversion = c; + dp->dir_end = cp; + } + + d->count++; + if (d->count >= d_allocated) + { + size_t memory_size; + DIRECTIVE *memory; + + d_allocated = xtimes (d_allocated, 2); + memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); + if (size_overflow_p (memory_size)) + /* Overflow, would lead to out of memory. */ + goto error; + memory = realloc (d->dir, memory_size); + if (memory == NULL) + /* Out of memory. */ + goto error; + d->dir = memory; + } + } + } + d->dir[d->count].dir_start = cp; + + d->max_width_length = max_width_length; + d->max_precision_length = max_precision_length; + return 0; + +error: + if (a->arg) + free (a->arg); + if (d->dir) + free (d->dir); + return -1; +} + +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef PRINTF_PARSE diff --git a/gl/printf-parse.h b/gl/printf-parse.h new file mode 100644 index 000000000..82a0d37cd --- /dev/null +++ b/gl/printf-parse.h @@ -0,0 +1,74 @@ +/* Parse printf format string. + Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _PRINTF_PARSE_H +#define _PRINTF_PARSE_H + +#include "printf-args.h" + + +/* Flags */ +#define FLAG_GROUP 1 /* ' flag */ +#define FLAG_LEFT 2 /* - flag */ +#define FLAG_SHOWSIGN 4 /* + flag */ +#define FLAG_SPACE 8 /* space flag */ +#define FLAG_ALT 16 /* # flag */ +#define FLAG_ZERO 32 + +/* arg_index value indicating that no argument is consumed. */ +#define ARG_NONE (~(size_t)0) + +/* A parsed directive. */ +typedef struct +{ + const char* dir_start; + const char* dir_end; + int flags; + const char* width_start; + const char* width_end; + size_t width_arg_index; + const char* precision_start; + const char* precision_end; + size_t precision_arg_index; + char conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + size_t arg_index; +} +char_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + char_directive *dir; + size_t max_width_length; + size_t max_precision_length; +} +char_directives; + + +/* Parses the format string. Fills in the number N of directives, and fills + in directives[0], ..., directives[N-1], and sets directives[N].dir_start + to the end of the format string. Also fills in the arg_type fields of the + arguments and the needed count of arguments. */ +#ifdef STATIC +STATIC +#else +extern +#endif +int printf_parse (const char *format, char_directives *d, arguments *a); + +#endif /* _PRINTF_PARSE_H */ diff --git a/gl/setenv.c b/gl/setenv.c new file mode 100644 index 000000000..33dbeb7a3 --- /dev/null +++ b/gl/setenv.c @@ -0,0 +1,328 @@ +/* Copyright (C) 1992,1995-1999,2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif +#include <alloca.h> + +#include <errno.h> +#ifndef __set_errno +# define __set_errno(ev) ((errno) = (ev)) +#endif + +#include <stdlib.h> +#include <string.h> +#if _LIBC || HAVE_UNISTD_H +# include <unistd.h> +#endif + +#if !_LIBC +# include "allocsa.h" +#endif + +#if !_LIBC +# define __environ environ +# ifndef HAVE_ENVIRON_DECL +extern char **environ; +# endif +#endif + +#if _LIBC +/* This lock protects against simultaneous modifications of `environ'. */ +# include <bits/libc-lock.h> +__libc_lock_define_initialized (static, envlock) +# define LOCK __libc_lock_lock (envlock) +# define UNLOCK __libc_lock_unlock (envlock) +#else +# define LOCK +# define UNLOCK +#endif + +/* In the GNU C library we must keep the namespace clean. */ +#ifdef _LIBC +# define setenv __setenv +# define clearenv __clearenv +# define tfind __tfind +# define tsearch __tsearch +#endif + +/* In the GNU C library implementation we try to be more clever and + allow arbitrarily many changes of the environment given that the used + values are from a small set. Outside glibc this will eat up all + memory after a while. */ +#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ + && defined __GNUC__) +# define USE_TSEARCH 1 +# include <search.h> +typedef int (*compar_fn_t) (const void *, const void *); + +/* This is a pointer to the root of the search tree with the known + values. */ +static void *known_values; + +# define KNOWN_VALUE(Str) \ + ({ \ + void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \ + value != NULL ? *(char **) value : NULL; \ + }) +# define STORE_VALUE(Str) \ + tsearch (Str, &known_values, (compar_fn_t) strcmp) + +#else +# undef USE_TSEARCH + +# define KNOWN_VALUE(Str) NULL +# define STORE_VALUE(Str) do { } while (0) + +#endif + + +/* If this variable is not a null pointer we allocated the current + environment. */ +static char **last_environ; + + +/* This function is used by `setenv' and `putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of `putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a `setenv' call since we can never + free the strings. */ +int +__add_to_environ (const char *name, const char *value, const char *combined, + int replace) +{ + register char **ep; + register size_t size; + const size_t namelen = strlen (name); + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; + + LOCK; + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + + size = 0; + if (ep != NULL) + { + for (; *ep != NULL; ++ep) + if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') + break; + else + ++size; + } + + if (ep == NULL || *ep == NULL) + { + char **new_environ; +#ifdef USE_TSEARCH + char *new_value; +#endif + + /* We allocated this space; we can extend it. */ + new_environ = + (char **) (last_environ == NULL + ? malloc ((size + 2) * sizeof (char *)) + : realloc (last_environ, (size + 2) * sizeof (char *))); + if (new_environ == NULL) + { + UNLOCK; + return -1; + } + + /* If the whole entry is given add it. */ + if (combined != NULL) + /* We must not add the string to the search tree since it belongs + to the user. */ + new_environ[size] = (char *) combined; + else + { + /* See whether the value is already known. */ +#ifdef USE_TSEARCH +# ifdef _LIBC + new_value = (char *) alloca (namelen + 1 + vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + new_value = (char *) allocsa (namelen + 1 + vallen); + if (new_value == NULL) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + new_environ[size] = KNOWN_VALUE (new_value); + if (new_environ[size] == NULL) +#endif + { + new_environ[size] = (char *) malloc (namelen + 1 + vallen); + if (new_environ[size] == NULL) + { +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (new_environ[size], new_value, namelen + 1 + vallen); +#else + memcpy (new_environ[size], name, namelen); + new_environ[size][namelen] = '='; + memcpy (&new_environ[size][namelen + 1], value, vallen); +#endif + /* And save the value now. We cannot do this when we remove + the string since then we cannot decide whether it is a + user string or not. */ + STORE_VALUE (new_environ[size]); + } +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif + } + + if (__environ != last_environ) + memcpy ((char *) new_environ, (char *) __environ, + size * sizeof (char *)); + + new_environ[size + 1] = NULL; + + last_environ = __environ = new_environ; + } + else if (replace) + { + char *np; + + /* Use the user string if given. */ + if (combined != NULL) + np = (char *) combined; + else + { +#ifdef USE_TSEARCH + char *new_value; +# ifdef _LIBC + new_value = alloca (namelen + 1 + vallen); + __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), + value, vallen); +# else + new_value = allocsa (namelen + 1 + vallen); + if (new_value == NULL) + { + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + memcpy (new_value, name, namelen); + new_value[namelen] = '='; + memcpy (&new_value[namelen + 1], value, vallen); +# endif + + np = KNOWN_VALUE (new_value); + if (np == NULL) +#endif + { + np = malloc (namelen + 1 + vallen); + if (np == NULL) + { +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif + __set_errno (ENOMEM); + UNLOCK; + return -1; + } + +#ifdef USE_TSEARCH + memcpy (np, new_value, namelen + 1 + vallen); +#else + memcpy (np, name, namelen); + np[namelen] = '='; + memcpy (&np[namelen + 1], value, vallen); +#endif + /* And remember the value. */ + STORE_VALUE (np); + } +#if defined USE_TSEARCH && !defined _LIBC + freesa (new_value); +#endif + } + + *ep = np; + } + + UNLOCK; + + return 0; +} + +int +setenv (const char *name, const char *value, int replace) +{ + return __add_to_environ (name, value, NULL, replace); +} + +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +int +clearenv (void) +{ + LOCK; + + if (__environ == last_environ && __environ != NULL) + { + /* We allocated this environment so we can free it. */ + free (__environ); + last_environ = NULL; + } + + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; + + UNLOCK; + + return 0; +} + +#ifdef _LIBC +static void +free_mem (void) +{ + /* Remove all traces. */ + clearenv (); + + /* Now remove the search tree. */ + __tdestroy (known_values, free); + known_values = NULL; +} +text_set_element (__libc_subfreeres, free_mem); + + +# undef setenv +# undef clearenv +weak_alias (__setenv, setenv) +weak_alias (__clearenv, clearenv) +#endif diff --git a/gl/setenv.h b/gl/setenv.h new file mode 100644 index 000000000..c89e7da4d --- /dev/null +++ b/gl/setenv.h @@ -0,0 +1,54 @@ +/* Setting environment variables. + Copyright (C) 2001-2004 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if HAVE_SETENV || HAVE_UNSETENV + +/* Get setenv(), unsetenv() declarations. */ +# include <stdlib.h> + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !HAVE_SETENV + +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +extern int setenv (const char *name, const char *value, int replace); + +#endif + +#if HAVE_UNSETENV + +# if VOID_UNSETENV +/* On some systems, unsetenv() returns void. + This is the case for FreeBSD 4.8, NetBSD 1.6, OpenBSD 3.4. */ +# define unsetenv(name) ((unsetenv)(name), 0) +# endif + +#else + +/* Remove the variable NAME from the environment. */ +extern int unsetenv (const char *name); + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/gl/strpbrk.c b/gl/strpbrk.c new file mode 100644 index 000000000..9152440b1 --- /dev/null +++ b/gl/strpbrk.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1994, 2000, 2002-2003 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stddef.h> +#include <string.h> + +#undef strpbrk + +/* Find the first occurrence in S of any character in ACCEPT. */ +char * +strpbrk (const char *s, const char *accept) +{ + while (*s != '\0') + { + const char *a = accept; + while (*a != '\0') + if (*a++ == *s) + return (char *) s; + ++s; + } + + return NULL; +} diff --git a/gl/strpbrk.h b/gl/strpbrk.h new file mode 100644 index 000000000..acc8d358b --- /dev/null +++ b/gl/strpbrk.h @@ -0,0 +1,28 @@ +/* Searching in a string. + Copyright (C) 2001-2002 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if HAVE_STRPBRK + +/* Get strpbrk() declaration. */ +#include <string.h> + +#else + +/* Find the first occurrence in S of any character in ACCEPT. */ +extern char *strpbrk (const char *s, const char *accept); + +#endif diff --git a/gl/strsep.c b/gl/strsep.c new file mode 100644 index 000000000..40c2939c8 --- /dev/null +++ b/gl/strsep.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + + Written by Yoann Vandoorselaere <yoann@prelude-ids.org>. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* Specification. */ +#include "strsep.h" + +#include <string.h> + +#include "strpbrk.h" + +char * +strsep (char **stringp, const char *delim) +{ + char *start = *stringp; + char *ptr; + + if (!start) + return NULL; + + if (!*delim) + ptr = start + strlen (start); + else + { + ptr = strpbrk (start, delim); + if (!ptr) + { + *stringp = NULL; + return start; + } + } + + *ptr = '\0'; + *stringp = ptr + 1; + + return start; +} diff --git a/gl/strsep.h b/gl/strsep.h new file mode 100644 index 000000000..ca28a2ffe --- /dev/null +++ b/gl/strsep.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + + Written by Yoann Vandoorselaere <yoann@prelude-ids.org>. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef GNULIB_STRSEP_H_ +#define GNULIB_STRSEP_H_ + +#if HAVE_STRSEP + +/* + * Get strsep() declaration. + */ +#include <string.h> + +#else + +/* Searches the next delimiter (char listed in DELIM) starting at *STRINGP. + If one is found, it is overwritten with a NUL, and *STRINGP is advanced + to point to the next char after it. Otherwise, *STRINGP is set to NULL. + If *STRINGP was already NULL, nothing happens. + Returns the old value of *STRINGP. + + This is a variant of strtok() that is multithread-safe and supports + empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strtok_r(). */ + +extern char *strsep (char **stringp, const char *delim); + +#endif + +#endif /* GNULIB_STRSEP_H_ */ diff --git a/gl/unsetenv.c b/gl/unsetenv.c new file mode 100644 index 000000000..4b53fc9c8 --- /dev/null +++ b/gl/unsetenv.c @@ -0,0 +1,99 @@ +/* Copyright (C) 1992,1995-1999,2000-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#if !_LIBC +# if !defined errno && !defined HAVE_ERRNO_DECL +extern int errno; +# endif +# define __set_errno(ev) ((errno) = (ev)) +#endif + +#include <stdlib.h> +#include <string.h> +#if _LIBC || HAVE_UNISTD_H +# include <unistd.h> +#endif + +#if !_LIBC +# define __environ environ +# ifndef HAVE_ENVIRON_DECL +extern char **environ; +# endif +#endif + +#if _LIBC +/* This lock protects against simultaneous modifications of `environ'. */ +# include <bits/libc-lock.h> +__libc_lock_define_initialized (static, envlock) +# define LOCK __libc_lock_lock (envlock) +# define UNLOCK __libc_lock_unlock (envlock) +#else +# define LOCK +# define UNLOCK +#endif + +/* In the GNU C library we must keep the namespace clean. */ +#ifdef _LIBC +# define unsetenv __unsetenv +#endif + + +int +unsetenv (const char *name) +{ + size_t len; + char **ep; + + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) + { + __set_errno (EINVAL); + return -1; + } + + len = strlen (name); + + LOCK; + + ep = __environ; + while (*ep != NULL) + if (!strncmp (*ep, name, len) && (*ep)[len] == '=') + { + /* Found it. Remove this pointer by moving later ones back. */ + char **dp = ep; + + do + dp[0] = dp[1]; + while (*dp++); + /* Continue the loop in case NAME appears again. */ + } + else + ++ep; + + UNLOCK; + + return 0; +} + +#ifdef _LIBC +# undef unsetenv +weak_alias (__unsetenv, unsetenv) +#endif diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c new file mode 100644 index 000000000..324d62ecd --- /dev/null +++ b/gl/vasnprintf.c @@ -0,0 +1,901 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 1999, 2002-2005 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Tell glibc's <stdio.h> to provide a prototype for snprintf(). + This must come before <config.h> because <config.h> may include + <features.h>, and once <features.h> has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#ifndef IN_LIBINTL +# include <alloca.h> +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +#else +# include "vasnprintf.h" +#endif + +#include <stdio.h> /* snprintf(), sprintf() */ +#include <stdlib.h> /* abort(), malloc(), realloc(), free() */ +#include <string.h> /* memcpy(), strlen() */ +#include <errno.h> /* errno */ +#include <limits.h> /* CHAR_BIT, INT_MAX */ +#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Checked size_t computations. */ +#include "xsize.h" + +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + +#ifdef HAVE_WCHAR_T +# ifdef HAVE_WCSLEN +# define local_wcslen wcslen +# else + /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 +static size_t +local_wcslen (const wchar_t *s) +{ + const wchar_t *ptr; + + for (ptr = s; *ptr != (wchar_t) 0; ptr++) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if WIDE_CHAR_VERSION +# define VASNPRINTF vasnwprintf +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +# define PRINTF_PARSE wprintf_parse +# define USE_SNPRINTF 1 +# if HAVE_DECL__SNWPRINTF + /* On Windows, the function swprintf() has a different signature than + on Unix; we use the _snwprintf() function instead. */ +# define SNPRINTF _snwprintf +# else + /* Unix. */ +# define SNPRINTF swprintf +# endif +#else +# define VASNPRINTF vasnprintf +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +# define PRINTF_PARSE printf_parse +# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) +# if HAVE_DECL__SNPRINTF + /* Windows. */ +# define SNPRINTF _snprintf +# else + /* Unix. */ +# define SNPRINTF snprintf +# endif +#endif + +CHAR_T * +VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) +{ + DIRECTIVES d; + arguments a; + + if (PRINTF_PARSE (format, &d, &a) < 0) + { + errno = EINVAL; + return NULL; + } + +#define CLEANUP() \ + free (d.dir); \ + if (a.arg) \ + free (a.arg); + + if (printf_fetchargs (args, &a) < 0) + { + CLEANUP (); + errno = EINVAL; + return NULL; + } + + { + size_t buf_neededlength; + CHAR_T *buf; + CHAR_T *buf_malloced; + const CHAR_T *cp; + size_t i; + DIRECTIVE *dp; + /* Output string accumulator. */ + CHAR_T *result; + size_t allocated; + size_t length; + + /* Allocate a small buffer that will hold a directive passed to + sprintf or snprintf. */ + buf_neededlength = + xsum4 (7, d.max_width_length, d.max_precision_length, 6); +#if HAVE_ALLOCA + if (buf_neededlength < 4000 / sizeof (CHAR_T)) + { + buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); + buf_malloced = NULL; + } + else +#endif + { + size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); + if (size_overflow_p (buf_memsize)) + goto out_of_memory_1; + buf = (CHAR_T *) malloc (buf_memsize); + if (buf == NULL) + goto out_of_memory_1; + buf_malloced = buf; + } + + if (resultbuf != NULL) + { + result = resultbuf; + allocated = *lengthp; + } + else + { + result = NULL; + allocated = 0; + } + length = 0; + /* Invariants: + result is either == resultbuf or == NULL or malloc-allocated. + If length > 0, then result != NULL. */ + + /* Ensures that allocated >= needed. Aborts through a jump to + out_of_memory if needed is SIZE_MAX or otherwise too big. */ +#define ENSURE_ALLOCATION(needed) \ + if ((needed) > allocated) \ + { \ + size_t memory_size; \ + CHAR_T *memory; \ + \ + allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ + if ((needed) > allocated) \ + allocated = (needed); \ + memory_size = xtimes (allocated, sizeof (CHAR_T)); \ + if (size_overflow_p (memory_size)) \ + goto out_of_memory; \ + if (result == resultbuf || result == NULL) \ + memory = (CHAR_T *) malloc (memory_size); \ + else \ + memory = (CHAR_T *) realloc (result, memory_size); \ + if (memory == NULL) \ + goto out_of_memory; \ + if (result == resultbuf && length > 0) \ + memcpy (memory, result, length * sizeof (CHAR_T)); \ + result = memory; \ + } + + for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) + { + if (cp != dp->dir_start) + { + size_t n = dp->dir_start - cp; + size_t augmented_length = xsum (length, n); + + ENSURE_ALLOCATION (augmented_length); + memcpy (result + length, cp, n * sizeof (CHAR_T)); + length = augmented_length; + } + if (i == d.count) + break; + + /* Execute a single directive. */ + if (dp->conversion == '%') + { + size_t augmented_length; + + if (!(dp->arg_index == ARG_NONE)) + abort (); + augmented_length = xsum (length, 1); + ENSURE_ALLOCATION (augmented_length); + result[length] = '%'; + length = augmented_length; + } + else + { + if (!(dp->arg_index != ARG_NONE)) + abort (); + + if (dp->conversion == 'n') + { + switch (a.arg[dp->arg_index].type) + { + case TYPE_COUNT_SCHAR_POINTER: + *a.arg[dp->arg_index].a.a_count_schar_pointer = length; + break; + case TYPE_COUNT_SHORT_POINTER: + *a.arg[dp->arg_index].a.a_count_short_pointer = length; + break; + case TYPE_COUNT_INT_POINTER: + *a.arg[dp->arg_index].a.a_count_int_pointer = length; + break; + case TYPE_COUNT_LONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longint_pointer = length; + break; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; + break; +#endif + default: + abort (); + } + } + else + { + arg_type type = a.arg[dp->arg_index].type; + CHAR_T *p; + unsigned int prefix_count; + int prefixes[2]; +#if !USE_SNPRINTF + size_t tmp_length; + CHAR_T tmpbuf[700]; + CHAR_T *tmp; + + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + { + size_t width; + size_t precision; + + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + width = (arg < 0 ? (unsigned int) (-arg) : arg); + } + else + { + const CHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + precision = 6; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + precision = (arg < 0 ? 0 : arg); + } + else + { + const CHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + } + } + + switch (dp->conversion) + { + + case 'd': case 'i': case 'u': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'o': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'x': case 'X': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + break; + + case 'f': case 'F': +# ifdef HAVE_LONG_DOUBLE + if (type == TYPE_LONGDOUBLE) + tmp_length = + (unsigned int) (LDBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + else +# endif + tmp_length = + (unsigned int) (DBL_MAX_EXP + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 10; /* sign, decimal point etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': + tmp_length = + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'c': +# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# ifdef HAVE_WCHAR_T + if (type == TYPE_WIDE_STRING) + { + tmp_length = + local_wcslen (a.arg[dp->arg_index].a.a_wide_string); + +# if !WIDE_CHAR_VERSION + tmp_length = xtimes (tmp_length, MB_CUR_MAX); +# endif + } + else +# endif + tmp_length = strlen (a.arg[dp->arg_index].a.a_string); + break; + + case 'p': + tmp_length = + (unsigned int) (sizeof (void *) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading 0x */ + break; + + default: + abort (); + } + + if (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + } + + if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (CHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } +#endif + + /* Construct the format string for calling snprintf or + sprintf. */ + p = buf; + *p++ = '%'; + if (dp->flags & FLAG_GROUP) + *p++ = '\''; + if (dp->flags & FLAG_LEFT) + *p++ = '-'; + if (dp->flags & FLAG_SHOWSIGN) + *p++ = '+'; + if (dp->flags & FLAG_SPACE) + *p++ = ' '; + if (dp->flags & FLAG_ALT) + *p++ = '#'; + if (dp->flags & FLAG_ZERO) + *p++ = '0'; + if (dp->width_start != dp->width_end) + { + size_t n = dp->width_end - dp->width_start; + memcpy (p, dp->width_start, n * sizeof (CHAR_T)); + p += n; + } + if (dp->precision_start != dp->precision_end) + { + size_t n = dp->precision_end - dp->precision_start; + memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); + p += n; + } + + switch (type) + { +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: + *p++ = 'l'; + /*FALLTHROUGH*/ +#endif + case TYPE_LONGINT: + case TYPE_ULONGINT: +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: +#endif +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: +#endif + *p++ = 'l'; + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + *p++ = 'L'; + break; +#endif + default: + break; + } + *p = dp->conversion; +#if USE_SNPRINTF + p[1] = '%'; + p[2] = 'n'; + p[3] = '\0'; +#else + p[1] = '\0'; +#endif + + /* Construct the arguments for calling snprintf or sprintf. */ + prefix_count = 0; + if (dp->width_arg_index != ARG_NONE) + { + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; + } + if (dp->precision_arg_index != ARG_NONE) + { + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; + } + +#if USE_SNPRINTF + /* Prepare checking whether snprintf returns the count + via %n. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; +#endif + + for (;;) + { + size_t maxlen; + int count; + int retcount; + + maxlen = allocated - length; + count = -1; + retcount = 0; + +#if USE_SNPRINTF +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + arg, &count); \ + break; \ + case 1: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + prefixes[0], arg, &count); \ + break; \ + case 2: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + prefixes[0], prefixes[1], arg, \ + &count); \ + break; \ + default: \ + abort (); \ + } +#else +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + count = sprintf (tmp, buf, arg); \ + break; \ + case 1: \ + count = sprintf (tmp, buf, prefixes[0], arg); \ + break; \ + case 2: \ + count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ + arg); \ + break; \ + default: \ + abort (); \ + } +#endif + + switch (type) + { + case TYPE_SCHAR: + { + int arg = a.arg[dp->arg_index].a.a_schar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UCHAR: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uchar; + SNPRINTF_BUF (arg); + } + break; + case TYPE_SHORT: + { + int arg = a.arg[dp->arg_index].a.a_short; + SNPRINTF_BUF (arg); + } + break; + case TYPE_USHORT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_ushort; + SNPRINTF_BUF (arg); + } + break; + case TYPE_INT: + { + int arg = a.arg[dp->arg_index].a.a_int; + SNPRINTF_BUF (arg); + } + break; + case TYPE_UINT: + { + unsigned int arg = a.arg[dp->arg_index].a.a_uint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_LONGINT: + { + long int arg = a.arg[dp->arg_index].a.a_longint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGINT: + { + unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + { + long long int arg = a.arg[dp->arg_index].a.a_longlongint; + SNPRINTF_BUF (arg); + } + break; + case TYPE_ULONGLONGINT: + { + unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_DOUBLE: + { + double arg = a.arg[dp->arg_index].a.a_double; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_CHAR: + { + int arg = a.arg[dp->arg_index].a.a_char; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: + { + wint_t arg = a.arg[dp->arg_index].a.a_wide_char; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_STRING: + { + const char *arg = a.arg[dp->arg_index].a.a_string; + SNPRINTF_BUF (arg); + } + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + { + const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_POINTER: + { + void *arg = a.arg[dp->arg_index].a.a_pointer; + SNPRINTF_BUF (arg); + } + break; + default: + abort (); + } + +#if USE_SNPRINTF + /* Portability: Not all implementations of snprintf() + are ISO C 99 compliant. Determine the number of + bytes that snprintf() has produced or would have + produced. */ + if (count >= 0) + { + /* Verify that snprintf() has NUL-terminated its + result. */ + if (count < maxlen && result[length + count] != '\0') + abort (); + /* Portability hack. */ + if (retcount > count) + count = retcount; + } + else + { + /* snprintf() doesn't understand the '%n' + directive. */ + if (p[1] != '\0') + { + /* Don't use the '%n' directive; instead, look + at the snprintf() return value. */ + p[1] = '\0'; + continue; + } + else + { + /* Look at the snprintf() return value. */ + if (retcount < 0) + { + /* HP-UX 10.20 snprintf() is doubly deficient: + It doesn't understand the '%n' directive, + *and* it returns -1 (rather than the length + that would have been required) when the + buffer is too small. */ + size_t bigger_need = + xsum (xtimes (allocated, 2), 12); + ENSURE_ALLOCATION (bigger_need); + continue; + } + else + count = retcount; + } + } +#endif + + /* Attempt to handle failure. */ + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EINVAL; + return NULL; + } + +#if !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#endif + + /* Make room for the result. */ + if (count >= maxlen) + { + /* Need at least count bytes. But allocate + proportionally, to avoid looping eternally if + snprintf() reports a too small count. */ + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); +#if USE_SNPRINTF + continue; +#endif + } + +#if USE_SNPRINTF + /* The snprintf() result did fit. */ +#else + /* Append the sprintf() result. */ + memcpy (result + length, tmp, count * sizeof (CHAR_T)); + if (tmp != tmpbuf) + free (tmp); +#endif + + length += count; + break; + } + } + } + } + + /* Add the final NUL. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; + + if (result != resultbuf && length + 1 < allocated) + { + /* Shrink the allocated memory if possible. */ + CHAR_T *memory; + + memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); + if (memory != NULL) + result = memory; + } + + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + *lengthp = length; + if (length > INT_MAX) + goto length_overflow; + return result; + + length_overflow: + /* We could produce such a big string, but its length doesn't fit into + an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in + this case. */ + if (result != resultbuf) + free (result); + errno = EOVERFLOW; + return NULL; + + out_of_memory: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + out_of_memory_1: + CLEANUP (); + errno = ENOMEM; + return NULL; + } +} + +#undef SNPRINTF +#undef USE_SNPRINTF +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef VASNPRINTF diff --git a/gl/vasnprintf.h b/gl/vasnprintf.h new file mode 100644 index 000000000..894008cae --- /dev/null +++ b/gl/vasnprintf.h @@ -0,0 +1,77 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 2002-2004 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _VASNPRINTF_H +#define _VASNPRINTF_H + +/* Get va_list. */ +#include <stdarg.h> + +/* Get size_t. */ +#include <stddef.h> + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + You can pass a preallocated buffer for the result in RESULTBUF and its + size in *LENGTHP; otherwise you pass RESULTBUF = NULL. + If successful, return the address of the string (this may be = RESULTBUF + if no dynamic memory allocation was necessary) and set *LENGTHP to the + number of resulting bytes, excluding the trailing NUL. Upon error, set + errno and return NULL. + + When dynamic memory allocation occurs, the preallocated buffer is left + alone (with possibly modified contents). This makes it possible to use + a statically allocated or stack-allocated buffer, like this: + + char buf[100]; + size_t len = sizeof (buf); + char *output = vasnprintf (buf, &len, format, args); + if (output == NULL) + ... error handling ...; + else + { + ... use the output string ...; + if (output != buf) + free (output); + } + */ +extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); +extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 3, 0))); + +#ifdef __cplusplus +} +#endif + +#endif /* _VASNPRINTF_H */ diff --git a/gl/vasprintf.c b/gl/vasprintf.c new file mode 100644 index 000000000..149c29242 --- /dev/null +++ b/gl/vasprintf.c @@ -0,0 +1,42 @@ +/* Formatted output to strings. + Copyright (C) 1999, 2002 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include "vasprintf.h" + +#include <stdlib.h> + +#include "vasnprintf.h" + +int +vasprintf (char **resultp, const char *format, va_list args) +{ + size_t length; + char *result = vasnprintf (NULL, &length, format, args); + if (result == NULL) + return -1; + + *resultp = result; + /* Return the number of resulting bytes, excluding the trailing NUL. + If it wouldn't fit in an 'int', vasnprintf() would have returned NULL + and set errno to EOVERFLOW. */ + return length; +} diff --git a/gl/vasprintf.h b/gl/vasprintf.h new file mode 100644 index 000000000..d02f15451 --- /dev/null +++ b/gl/vasprintf.h @@ -0,0 +1,63 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 2002-2003 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _VASPRINTF_H +#define _VASPRINTF_H + +#if HAVE_VASPRINTF + +/* Get asprintf(), vasprintf() declarations. */ +#include <stdio.h> + +#else + +/* Get va_list. */ +#include <stdarg.h> + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ +# define __attribute__(Spec) /* empty */ +# endif +/* The __-protected variants of `format' and `printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Write formatted output to a string dynamically allocated with malloc(). + If the memory allocation succeeds, store the address of the string in + *RESULT and return the number of resulting bytes, excluding the trailing + NUL. Upon memory allocation error, or some other error, return -1. */ +extern int asprintf (char **result, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +extern int vasprintf (char **result, const char *format, va_list args) + __attribute__ ((__format__ (__printf__, 2, 0))); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* _VASPRINTF_H */ diff --git a/gl/xsize.h b/gl/xsize.h new file mode 100644 index 000000000..341fb16ca --- /dev/null +++ b/gl/xsize.h @@ -0,0 +1,108 @@ +/* xsize.h -- Checked size_t computations. + + Copyright (C) 2003 Free Software Foundation, Inc. + + 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _XSIZE_H +#define _XSIZE_H + +/* Get size_t. */ +#include <stddef.h> + +/* Get SIZE_MAX. */ +#include <limits.h> +#if HAVE_STDINT_H +# include <stdint.h> +#endif + +/* The size of memory objects is often computed through expressions of + type size_t. Example: + void* p = malloc (header_size + n * element_size). + These computations can lead to overflow. When this happens, malloc() + returns a piece of memory that is way too small, and the program then + crashes while attempting to fill the memory. + To avoid this, the functions and macros in this file check for overflow. + The convention is that SIZE_MAX represents overflow. + malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc + implementation that uses mmap --, it's recommended to use size_overflow_p() + or size_in_bounds_p() before invoking malloc(). + The example thus becomes: + size_t size = xsum (header_size, xtimes (n, element_size)); + void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); +*/ + +/* Convert an arbitrary value >= 0 to type size_t. */ +#define xcast_size_t(N) \ + ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) + +/* Sum of two sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum (size_t size1, size_t size2) +{ + size_t sum = size1 + size2; + return (sum >= size1 ? sum : SIZE_MAX); +} + +/* Sum of three sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum3 (size_t size1, size_t size2, size_t size3) +{ + return xsum (xsum (size1, size2), size3); +} + +/* Sum of four sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) +{ + return xsum (xsum (xsum (size1, size2), size3), size4); +} + +/* Maximum of two sizes, with overflow check. */ +static inline size_t +#if __GNUC__ >= 3 +__attribute__ ((__pure__)) +#endif +xmax (size_t size1, size_t size2) +{ + /* No explicit check is needed here, because for any n: + max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ + return (size1 >= size2 ? size1 : size2); +} + +/* Multiplication of a count with an element size, with overflow check. + The count must be >= 0 and the element size must be > 0. + This is a macro, not an inline function, so that it works correctly even + when N is of a wider tupe and N > SIZE_MAX. */ +#define xtimes(N, ELSIZE) \ + ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) + +/* Check for overflow. */ +#define size_overflow_p(SIZE) \ + ((SIZE) == SIZE_MAX) +/* Check against overflow. */ +#define size_in_bounds_p(SIZE) \ + ((SIZE) != SIZE_MAX) + +#endif /* _XSIZE_H */ -- cgit v1.2.3 From f1dac8851d02a0cb63fc7379ee74692856d0cf39 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 3 Jun 2005 13:57:24 +0000 Subject: * command.c (cmd_updatestartuptty): New. * gpg-agent.c: New option --write-env-file. * gpg-agent.c (handle_connections): Make sure that the signals we are handling are not blocked.Block signals while creating new threads. * estream.c: Use HAVE_CONFIG_H and not USE_CONFIG_H! (es_func_fd_read, es_func_fd_write): Protect against EINTR. * gpg-agent.texi (Agent UPDATESTARTUPTTY): New. * scdaemon.c (handle_connections): Make sure that the signals we are handling are not blocked.Block signals while creating new threads. (handle_connections): Include the file descriptor into the name of the thread. --- ChangeLog | 5 ++ NEWS | 3 + TODO | 7 +++ agent/ChangeLog | 17 ++++++ agent/agent.h | 14 +++-- agent/call-scd.c | 30 ++++++++++ agent/command.c | 34 +++++++++++ agent/gpg-agent.c | 104 ++++++++++++++++++++++++++------- common/ChangeLog | 6 ++ common/estream.c | 10 +++- configure.ac | 3 + doc/ChangeLog | 4 ++ doc/gpg-agent.texi | 60 +++++++++++++++---- scd/ChangeLog | 29 ++++++++++ scd/app-common.h | 6 ++ scd/app-openpgp.c | 2 +- scd/app.c | 167 ++++++++++++++++++++++++++++++++++++++--------------- scd/command.c | 6 +- scd/scdaemon.c | 33 ++++++++--- scd/scdaemon.h | 23 +++++--- 20 files changed, 459 insertions(+), 104 deletions(-) diff --git a/ChangeLog b/ChangeLog index fbd9ad79d..f7efcee89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-06-02 Werner Koch <wk@g10code.com> + + * configure.ac (HAVE_PTH): Define as alias for USE_GNU_PTH. It is + used by common/estream.c. + 2005-06-01 Werner Koch <wk@g10code.com> * configure.ac (gl_INIT): Add gnulib stuff. diff --git a/NEWS b/NEWS index 79a74cbe4..e28f1284a 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,9 @@ Noteworthy changes in version 1.9.17 does allows only signing using TCOS cards but we are going to enhance it to match all the old capabilities. + * [gpg-agent] New option --rite-env-file and Assuan command + UPDATESTARTUPTTY. + Noteworthy changes in version 1.9.16 (2005-04-21) ------------------------------------------------- diff --git a/TODO b/TODO index 74763a71f..5f1b57a0f 100644 --- a/TODO +++ b/TODO @@ -72,6 +72,13 @@ might want to have an agent context for each service request we can change all S-expression handling code to make use of this function. +* scd +** Application context vs. reader slot + We have 2 concurrent method of tracking whether a read is in use: + Using the session_list in command.c and the lock_table in app.c. IT + would be better to do this just at one place. First we need to see + how we can support cards with multiple applications. + * tests ** Makefile.am We use printf(1) to setup the library path, this is not portable. diff --git a/agent/ChangeLog b/agent/ChangeLog index 9c57ad43e..9621e5de0 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,20 @@ +2005-06-03 Werner Koch <wk@g10code.com> + + * command.c (cmd_updatestartuptty): New. + + * gpg-agent.c: New option --write-env-file. + + * gpg-agent.c (handle_connections): Make sure that the signals we + are handling are not blocked.Block signals while creating new + threads. + +2005-06-02 Werner Koch <wk@g10code.com> + + * call-scd.c (agent_scd_dump_state, dump_mutex_state): New. + * gpg-agent.c (handle_signal): Print it on SIGUSR1. + (handle_connections): Include the file descriptor into the + threadnames. + 2005-06-01 Werner Koch <wk@g10code.com> * gpg-agent.c: Include setenv.h. diff --git a/agent/agent.h b/agent/agent.h index a667c0d46..51e66abee 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -54,12 +54,13 @@ struct { int batch; /* Batch mode */ const char *homedir; /* Configuration directory name */ - /* Environment setting gathred at program start. */ - const char *startup_display; - const char *startup_ttyname; - const char *startup_ttytype; - const char *startup_lc_ctype; - const char *startup_lc_messages; + /* Environment setting gathered at program start or hanged using the + Assuan command UPDATESTARTUPTTY. */ + char *startup_display; + char *startup_ttyname; + char *startup_ttytype; + char *startup_lc_ctype; + char *startup_lc_messages; const char *pinentry_program; /* Filename of the program to start as @@ -248,6 +249,7 @@ int divert_generic_cmd (ctrl_t ctrl, /*-- call-scd.c --*/ void initialize_module_call_scd (void); +void agent_scd_dump_state (void); void agent_scd_check_aliveness (void); int agent_reset_scd (ctrl_t ctrl); int agent_card_learn (ctrl_t ctrl, diff --git a/agent/call-scd.c b/agent/call-scd.c index 78e28fe97..00c9df2a7 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -116,6 +116,35 @@ initialize_module_call_scd (void) } +static void +dump_mutex_state (pth_mutex_t *m) +{ + if (!(m->mx_state & PTH_MUTEX_INITIALIZED)) + log_printf ("not_initialized"); + else if (!(m->mx_state & PTH_MUTEX_LOCKED)) + log_printf ("not_locked"); + else + log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count); +} + + +/* This function may be called to print infromation pertaining to the + current state of this module to the log. */ +void +agent_scd_dump_state (void) +{ + log_info ("agent_scd_dump_state: scd_lock="); + dump_mutex_state (&start_scd_lock); + log_printf ("\n"); + log_info ("agent_scd_dump_state: primary_scd_ctx=%p pid=%ld reusable=%d\n", + primary_scd_ctx, + (long)assuan_get_pid (primary_scd_ctx), + primary_scd_ctx_reusable); + if (socket_name) + log_info ("agent_scd_dump_state: socket=`%s'\n", socket_name); +} + + /* The unlock_scd function shall be called after having accessed the SCD. It is currently not very useful but gives an opportunity to keep track of connections currently calling SCD. Note that the @@ -384,6 +413,7 @@ agent_scd_check_aliveness (void) } + /* Reset the SCD if it has been used. */ int agent_reset_scd (ctrl_t ctrl) diff --git a/agent/command.c b/agent/command.c index 8af159f6d..56167118d 100644 --- a/agent/command.c +++ b/agent/command.c @@ -867,6 +867,39 @@ cmd_scd (ASSUAN_CONTEXT ctx, char *line) } + +/* UPDATESTARTUPTTY + + Set startup TTY and X DISPLAY variables to the values of this + session. This command is useful to pull future pinentries to + another screen. It is only required because there is no way in the + ssh-agent protocol to convey this information. */ +static int +cmd_updatestartuptty (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + + xfree (opt.startup_display); opt.startup_display = NULL; + xfree (opt.startup_ttyname); opt.startup_ttyname = NULL; + xfree (opt.startup_ttytype); opt.startup_ttytype = NULL; + xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL; + xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL; + + if (ctrl->display) + opt.startup_display = xtrystrdup (ctrl->display); + if (ctrl->ttyname) + opt.startup_ttyname = xtrystrdup (ctrl->ttyname); + if (ctrl->ttytype) + opt.startup_ttytype = xtrystrdup (ctrl->ttytype); + if (ctrl->lc_ctype) + opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype); + if (ctrl->lc_messages) + opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages); + + return 0; +} + + static int option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) @@ -957,6 +990,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "INPUT", NULL }, { "OUTPUT", NULL }, { "SCD", cmd_scd }, + { "UPDATESTARTUPTTY", cmd_updatestartuptty }, { NULL } }; int i, rc; diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 3537b07f0..90b071d5e 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -93,7 +93,8 @@ enum cmd_and_opt_values oKeepTTY, oKeepDISPLAY, oSSHSupport, - oDisableScdaemon + oDisableScdaemon, + oWriteEnvFile }; @@ -147,6 +148,8 @@ static ARGPARSE_OPTS opts[] = { { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") }, + { oWriteEnvFile, "write-env-file", 2, + N_("|FILE|write environment settings also to FILE")}, {0} }; @@ -438,6 +441,7 @@ main (int argc, char **argv ) int gpgconf_list = 0; int standard_socket = 0; gpg_error_t err; + const char *env_file_name = NULL; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -501,7 +505,7 @@ main (int argc, char **argv ) opt.startup_ttytype = getenv ("TERM"); if (opt.startup_ttytype) opt.startup_ttytype = xstrdup (opt.startup_ttytype); - /* Fixme: Neen to use the locale fucntion here. */ + /* Fixme: Better use the locale function here. */ opt.startup_lc_ctype = getenv ("LC_CTYPE"); if (opt.startup_lc_ctype) opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype); @@ -619,6 +623,7 @@ main (int argc, char **argv ) case oKeepDISPLAY: opt.keep_display = 1; break; case oSSHSupport: opt.ssh_support = 1; break; + case oWriteEnvFile: env_file_name = pargs.r.ret_str; break; default : pargs.err = configfp? 1:2; break; } @@ -855,6 +860,29 @@ main (int argc, char **argv ) if (opt.ssh_support) *socket_name_ssh = 0; + if (env_file_name) + { + FILE *fp; + + fp = fopen (env_file_name, "w"); + if (!fp) + log_error (_("error creating `%s': %s\n"), + env_file_name, strerror (errno)); + else + { + fputs (infostr, fp); + putc ('\n', fp); + if (opt.ssh_support) + { + fputs (infostr_ssh_sock, fp); + putc ('\n', fp); + fputs (infostr_ssh_pid, fp); + putc ('\n', fp); + } + fclose (fp); + } + } + if (argc) { /* Run the program given on the commandline. */ @@ -1273,7 +1301,7 @@ create_directories (void) static void handle_tick (void) { - /* Check whether the scdaemon has dies and cleanup in this case. */ + /* Check whether the scdaemon has died and cleanup in this case. */ agent_scd_check_aliveness (); /* If we are running as a child of another process, check whether @@ -1311,6 +1339,7 @@ handle_signal (int signo) case SIGUSR1: log_info ("SIGUSR1 received - printing internal information:\n"); pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); + agent_scd_dump_state (); break; case SIGUSR2: @@ -1353,7 +1382,8 @@ start_connection_thread (void *arg) int fd = (int)arg; if (opt.verbose) - log_info (_("handler for fd %d started\n"), fd); + log_info (_("handler 0x%lx for fd %d started\n"), + (long)pth_self (), fd); /* FIXME: Move this housekeeping into a ticker function. Calling it for each connection should work but won't work anymore if our @@ -1362,7 +1392,8 @@ start_connection_thread (void *arg) start_command_handler (-1, fd); if (opt.verbose) - log_info (_("handler for fd %d terminated\n"), fd); + log_info (_("handler 0x%lx for fd %d terminated\n"), + (long)pth_self (), fd); return NULL; } @@ -1375,13 +1406,15 @@ start_connection_thread_ssh (void *arg) int fd = (int)arg; if (opt.verbose) - log_info (_("ssh handler for fd %d started\n"), fd); + log_info (_("ssh handler 0x%lx for fd %d started\n"), + (long)pth_self (), fd); agent_trustlist_housekeeping (); start_command_handler_ssh (fd); if (opt.verbose) - log_info (_("ssh handler for fd %d terminated\n"), fd); + log_info (_("ssh handler 0x%lx for fd %d terminated\n"), + (long)pth_self (), fd); return NULL; } @@ -1405,15 +1438,17 @@ handle_connections (int listen_fd, int listen_fd_ssh) tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024); - pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent"); #ifndef HAVE_W32_SYSTEM /* fixme */ + /* Make sure that the signals we are going to handle are not blocked + and create an event object for them. */ sigemptyset (&sigs ); sigaddset (&sigs, SIGHUP); sigaddset (&sigs, SIGUSR1); sigaddset (&sigs, SIGUSR2); sigaddset (&sigs, SIGINT); sigaddset (&sigs, SIGTERM); + pth_sigmask (SIG_UNBLOCK, &sigs, NULL); ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); #else ev = NULL; @@ -1427,6 +1462,8 @@ handle_connections (int listen_fd, int listen_fd_ssh) for (;;) { + sigset_t oldsigs; + if (shutdown_pending) { if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1) @@ -1488,6 +1525,12 @@ handle_connections (int listen_fd, int listen_fd_ssh) handle_tick (); } + + /* We now might create new threads and because we don't want any + signals - we are handling here - to be delivered to a new + thread. Thus we need to block those signals. */ + pth_sigmask (SIG_BLOCK, &sigs, &oldsigs); + if (FD_ISSET (listen_fd, &read_fdset)) { plen = sizeof paddr; @@ -1496,12 +1539,20 @@ handle_connections (int listen_fd, int listen_fd_ssh) { log_error ("accept failed: %s\n", strerror (errno)); } - else if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) - { - log_error ("error spawning connection handler: %s\n", - strerror (errno) ); - close (fd); - } + else + { + char threadname[50]; + snprintf (threadname, sizeof threadname-1, + "conn fd=%d (gpg)", fd); + threadname[sizeof threadname -1] = 0; + pth_attr_set (tattr, PTH_ATTR_NAME, threadname); + if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } + } fd = -1; } @@ -1513,14 +1564,27 @@ handle_connections (int listen_fd, int listen_fd_ssh) { log_error ("accept failed for ssh: %s\n", strerror (errno)); } - else if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) - { - log_error ("error spawning ssh connection handler: %s\n", - strerror (errno) ); - close (fd); - } + else + { + char threadname[50]; + snprintf (threadname, sizeof threadname-1, + "conn fd=%d (ssh)", fd); + threadname[sizeof threadname -1] = 0; + pth_attr_set (tattr, PTH_ATTR_NAME, threadname); + + if (!pth_spawn (tattr, start_connection_thread_ssh, (void*)fd)) + { + log_error ("error spawning ssh connection handler: %s\n", + strerror (errno) ); + close (fd); + } + } fd = -1; } + + /* Restore the signal mask. */ + pth_sigmask (SIG_SETMASK, &oldsigs, NULL); + } pth_event_free (ev, PTH_FREE_ALL); diff --git a/common/ChangeLog b/common/ChangeLog index fccc71d49..08fb06775 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +2005-06-03 Werner Koch <wk@g10code.com> + + * estream.c: Use HAVE_CONFIG_H and not USE_CONFIG_H! + (es_func_fd_read, es_func_fd_write): Protect against EINTR. + + 2005-06-01 Werner Koch <wk@g10code.com> * Makefile.am (AM_CPPFLAGS): Added. diff --git a/common/estream.c b/common/estream.c index 00cb749e8..bf5b02001 100644 --- a/common/estream.c +++ b/common/estream.c @@ -22,7 +22,7 @@ # include <estream-support.h> #endif -#ifdef USE_CONFIG_H +#ifdef HAVE_CONFIG_H # include <config.h> #endif @@ -597,7 +597,9 @@ es_func_fd_read (void *cookie, char *buffer, size_t size) estream_cookie_fd_t file_cookie = cookie; ssize_t bytes_read; - bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); + do + bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); + while (bytes_read == -1 && errno == EINTR); return bytes_read; } @@ -610,7 +612,9 @@ es_func_fd_write (void *cookie, const char *buffer, size_t size) estream_cookie_fd_t file_cookie = cookie; ssize_t bytes_written; - bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); + do + bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); + while (bytes_written == -1 && errno == EINTR); return bytes_written; } diff --git a/configure.ac b/configure.ac index c1a3d77ea..17465c520 100644 --- a/configure.ac +++ b/configure.ac @@ -531,6 +531,8 @@ if test "$have_w32_system" = no; then PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs`" AC_DEFINE(USE_GNU_PTH, 1, [Defined if the GNU Portable Thread Library should be used]) + AC_DEFINE(HAVE_PTH, 1, + [Defined if the GNU Pth is available]) fi fi else @@ -538,6 +540,7 @@ else PTH_CFLAGS="" PTH_LIBS="" AC_DEFINE(USE_GNU_PTH, 1) + AC_DEFINE(HAVE_PTH, 1) fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) diff --git a/doc/ChangeLog b/doc/ChangeLog index 25840a5b1..f353bdf03 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-06-03 Werner Koch <wk@g10code.com> + + * gpg-agent.texi (Agent UPDATESTARTUPTTY): New. + 2005-05-17 Werner Koch <wk@g10code.com> * gpg-agent.texi (Agent Options): Removed --disable-pth. diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index fa005c3b7..5e8c19468 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -25,11 +25,11 @@ eval `gpg-agent --daemon` @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 @command{gpg-agent}, so you should make sure that -only is running: @command{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: +to run multiple instance of the @command{gpg-agent}, so you should make +sure that only one is running: @command{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 && \ @@ -42,6 +42,9 @@ else fi @end smallexample +The new option @option{--write-env-file} may be used instead. + + @noindent You should always add the following lines to your @code{.bashrc} or whatever initialization file is used for all shell invocations: @@ -243,6 +246,21 @@ 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 --write-env-file @var{file} +@opindex write-env-file +Often it is required to connect to the agent from a process not being an +inferior of @command{gpg-agent} and thus the environment variable with +the socket name is not available. To help setting up those variables in +other sessions, this option may be used to write the information into +@var{file}. The format is suitable to be evaluated by a Bourne shell +like in this simple example: + +@example +eval `cat @var{file}` +eval `cut -d= -f 1 < @var{file} | xargs echo export` +@end example + + @item --no-grab @opindex no-grab Tell the pinentryo not to grab the keyboard and mouse. This option @@ -353,12 +371,19 @@ directory. Once, a key has been added to the gpg-agent this way, the gpg-agent will be ready to use the key. -Note: in case the gpg-agent receives a signature request, the user -might need to be prompted for a passphrase, which is necessary for -decrypting the stored key. Since the ssh-agent protocol does not -contain a mechanism for telling the agent on which display/terminal it -is running, gpg-agent's ssh-support will use the TTY or X display where -gpg-agent has been started. +Note: in case the gpg-agent receives a signature request, the user might +need to be prompted for a passphrase, which is necessary for decrypting +the stored key. Since the ssh-agent protocol does not contain a +mechanism for telling the agent on which display/terminal it is running, +gpg-agent's ssh-support will use the TTY or X display where gpg-agent +has been started. To switch this display to the current one, the +follwing command may be used: + +@smallexample +echo UPDATESTARTUPTTY | gpg-connect-agent +@end smallexample + + @end table @@ -544,6 +569,7 @@ secret keys. * Agent HAVEKEY:: Check whether a key is available * Agent LEARN:: Register a smartcard * Agent PASSWD:: Change a Passphrase +* Agent UPDATESTARTUPTTY:: Change the Standard Display @end menu @node Agent PKDECRYPT @@ -944,4 +970,16 @@ This command is used to interactively change the passphrase of the key indentified by the hex string @var{keygrip}. +@node Agent UPDATESTARTUPTTY +@subsection Change the standard display + +@example + UPDATESTARTUPTTY +@end example + +Set the startup TTY and X-DISPLAY variables to the values of this +session. This command is useful to direct future pinentry invocations +to another screen. It is only required because there is no way in the +ssh-agent protocol to convey this information. + diff --git a/scd/ChangeLog b/scd/ChangeLog index 136ed5618..da433e2f8 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,32 @@ +2005-06-03 Werner Koch <wk@g10code.com> + + * scdaemon.c (handle_connections): Make sure that the signals we + are handling are not blocked.Block signals while creating new + threads. + (handle_connections): Include the file descriptor into the name of + the thread. + +2005-06-02 Werner Koch <wk@g10code.com> + + * app.c (app_dump_state, dump_mutex_state): New. + * scdaemon.c (handle_signal): Print it on SIGUSR1. + + * app-openpgp.c (do_writekey): Typo fix. + + * command.c (open_card): Check for locked state even if an + application context is available. + + * app-common.h: Add REF_COUNT field. + * app.c (release_application, select_application): Implement + reference counting to share the context beween connections. + + * app.c (lock_reader, unlock_reader): Take SLOT instead of APP as + argument. Changed all callers. + (select_application): Unlock the reader on error. This should fix + the hangs I noticed last week. + + * scdaemon.h: Removed card_ctx_t cruft. + 2005-06-01 Werner Koch <wk@g10code.com> * scdaemon.c: Include mkdtemp.h. diff --git a/scd/app-common.h b/scd/app-common.h index 812736ece..94087f221 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -39,6 +39,11 @@ struct app_ctx_s { function pointers may be used. Note that for unsupported operations the particular function pointer is set to NULL */ + + int ref_count; /* Number of connections currently using this + application context. fixme: We might want to + merg this witghn INITIALIZED above. */ + int slot; /* Used reader. */ /* If this is used by GnuPG 1.4 we need to know the assuan context @@ -123,6 +128,7 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); /*-- app.c --*/ +void app_dump_state (void); gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app); void release_application (app_t app); diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 14483869b..1ff096138 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1745,7 +1745,7 @@ do_writekey (app_t app, ctrl_t ctrl, nbits = rsa_e? count_bits (rsa_e, rsa_e_len) : 0; if (nbits < 2 || nbits > 32) { - log_error (_("RSA public exponent missing or largerr than %d bits\n"), + log_error (_("RSA public exponent missing or larger than %d bits\n"), 32); err = gpg_error (GPG_ERR_BAD_SECKEY); goto leave; diff --git a/scd/app.c b/scd/app.c index f2c427f5b..2c8c915d7 100644 --- a/scd/app.c +++ b/scd/app.c @@ -39,25 +39,24 @@ static struct { int initialized; pth_mutex_t lock; + app_t app; /* Application context in use or NULL. */ } lock_table[10]; -/* Lock the reader associated with the APP context. This function - shall be used right before calling any of the actual application - functions to serialize access to the reader. We do this always - even if the reader is not actually used. This allows an actual - application to assume that it never shares a reader (while - performing one command). Returns 0 on success; only then the - unlock_reader function must be called after returning from the - handler. */ +/* Lock the reader SLOT. This function shall be used right before + calling any of the actual application functions to serialize access + to the reader. We do this always even if the reader is not + actually used. This allows an actual connection to assume that it + never shares a reader (while performing one command). Returns 0 on + success; only then the unlock_reader function must be called after + returning from the handler. */ static gpg_error_t -lock_reader (app_t app) +lock_reader (int slot) { gpg_error_t err; - int slot = app->slot; if (slot < 0 || slot >= DIM (lock_table)) - return gpg_error (app->slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT); + return gpg_error (slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT); if (!lock_table[slot].initialized) { @@ -68,6 +67,7 @@ lock_reader (app_t app) return err; } lock_table[slot].initialized = 1; + lock_table[slot].app = NULL; } if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL)) @@ -83,10 +83,8 @@ lock_reader (app_t app) /* Release a lock on the reader. See lock_reader(). */ static void -unlock_reader (app_t app) +unlock_reader (int slot) { - int slot = app->slot; - if (slot < 0 || slot >= DIM (lock_table) || !lock_table[slot].initialized) log_bug ("unlock_reader called for invalid slot %d\n", slot); @@ -96,6 +94,39 @@ unlock_reader (app_t app) slot, strerror (errno)); } + + +static void +dump_mutex_state (pth_mutex_t *m) +{ + if (!(m->mx_state & PTH_MUTEX_INITIALIZED)) + log_printf ("not_initialized"); + else if (!(m->mx_state & PTH_MUTEX_LOCKED)) + log_printf ("not_locked"); + else + log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count); +} + + +/* This function may be called to print information pertaining to the + current state of this module to the log. */ +void +app_dump_state (void) +{ + int slot; + + for (slot=0; slot < DIM (lock_table); slot++) + if (lock_table[slot].initialized) + { + log_info ("app_dump_state: slot=%d lock=", slot); + dump_mutex_state (&lock_table[slot].lock); + if (lock_table[slot].app) + log_printf (" app=%p type=`%s'", + lock_table[slot].app, lock_table[slot].app->apptype); + log_printf ("\n"); + } +} + /* Check wether the application NAME is allowed. This does not mean we have support for it though. */ @@ -120,23 +151,48 @@ gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) { gpg_error_t err; - app_t app; + app_t app = NULL; unsigned char *result = NULL; size_t resultlen; *r_app = NULL; + + err = lock_reader (slot); + if (err) + return err; + + /* First check whether we already have an application to share. */ + app = lock_table[slot].initialized ? lock_table[slot].app : NULL; + if (app && name) + if (!app->apptype || ascii_strcasecmp (app->apptype, name)) + { + unlock_reader (slot); + if (app->apptype) + log_info ("application `%s' in use by reader %d - can't switch\n", + app->apptype, slot); + return gpg_error (GPG_ERR_CONFLICT); + } + + if (app) + { + if (app->slot != slot) + log_bug ("slot mismatch %d/%d\n", app->slot, slot); + app->ref_count++; + *r_app = app; + unlock_reader (slot); + return 0; /* Okay: We share that one. */ + } + app = xtrycalloc (1, sizeof *app); if (!app) { err = gpg_error_from_errno (errno); log_info ("error allocating context: %s\n", gpg_strerror (err)); + unlock_reader (slot); return err; } app->slot = slot; - err = lock_reader (app); - if (err) - return err; /* Fixme: We should now first check whether a card is at all present. */ @@ -162,7 +218,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) have some test cards with such an invalid encoding and therefore I use this ugly workaround to return something I can further experiment with. */ - log_debug ("enabling BMI testcard workaround\n"); + log_info ("enabling BMI testcard workaround\n"); n--; } @@ -212,22 +268,41 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) log_info ("no supported card application found: %s\n", gpg_strerror (err)); xfree (app); + unlock_reader (slot); return err; } app->initialized = 1; - unlock_reader (app); + app->ref_count = 1; + lock_table[slot].app = app; *r_app = app; + unlock_reader (slot); return 0; } +/* Free the resources associated with the application APP. APP is + allowed to be NULL in which case this is a no-op. Note that we are + using reference counting to track the users of the application. */ void release_application (app_t app) { + int slot; + if (!app) return; + if (app->ref_count < 1) + log_bug ("trying to release an already released context\n"); + if (--app->ref_count) + return; + + /* Clear the reference to the application from the lock table. */ + for (slot = 0; slot < DIM (lock_table); slot++) + if (lock_table[slot].initialized && lock_table[slot].app == app) + lock_table[slot].app = NULL; + + /* Deallocate. */ if (app->fnc.deinit) { app->fnc.deinit (app); @@ -320,11 +395,11 @@ app_write_learn_status (app_t app, CTRL ctrl) if (app->apptype) send_status_info (ctrl, "APPTYPE", app->apptype, strlen (app->apptype), NULL, 0); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.learn_status (app, ctrl); - unlock_reader (app); + unlock_reader (app->slot); return err; } @@ -345,11 +420,11 @@ app_readcert (app_t app, const char *certid, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.readcert) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.readcert (app, certid, cert, certlen); - unlock_reader (app); + unlock_reader (app->slot); return err; } @@ -377,11 +452,11 @@ app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.readkey) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err= app->fnc.readkey (app, keyid, pk, pklen); - unlock_reader (app); + unlock_reader (app->slot); return err; } @@ -419,11 +494,11 @@ app_getattr (app_t app, CTRL ctrl, const char *name) if (!app->fnc.getattr) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.getattr (app, ctrl, name); - unlock_reader (app); + unlock_reader (app->slot); return err; } @@ -442,11 +517,11 @@ app_setattr (app_t app, const char *name, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.setattr) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen); - unlock_reader (app); + unlock_reader (app->slot); return err; } @@ -468,14 +543,14 @@ app_sign (app_t app, const char *keyidstr, int hashalgo, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.sign) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.sign (app, keyidstr, hashalgo, pincb, pincb_arg, indata, indatalen, outdata, outdatalen); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation sign result: %s\n", gpg_strerror (err)); return err; @@ -500,14 +575,14 @@ app_auth (app_t app, const char *keyidstr, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.auth) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.auth (app, keyidstr, pincb, pincb_arg, indata, indatalen, outdata, outdatalen); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation auth result: %s\n", gpg_strerror (err)); return err; @@ -532,14 +607,14 @@ app_decipher (app_t app, const char *keyidstr, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.decipher) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.decipher (app, keyidstr, pincb, pincb_arg, indata, indatalen, outdata, outdatalen); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation decipher result: %s\n", gpg_strerror (err)); return err; @@ -562,12 +637,12 @@ app_writekey (app_t app, ctrl_t ctrl, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.writekey) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.writekey (app, ctrl, keyidstr, flags, pincb, pincb_arg, keydata, keydatalen); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation writekey result: %s\n", gpg_strerror (err)); return err; @@ -589,11 +664,11 @@ app_genkey (app_t app, CTRL ctrl, const char *keynostr, unsigned int flags, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.genkey) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.genkey (app, ctrl, keynostr, flags, pincb, pincb_arg); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation genkey result: %s\n", gpg_strerror (err)); return err; @@ -612,11 +687,11 @@ app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer) return gpg_error (GPG_ERR_INV_VALUE); if (!app->initialized) return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = iso7816_get_challenge (app->slot, nbytes, buffer); - unlock_reader (app); + unlock_reader (app->slot); return err; } @@ -636,12 +711,12 @@ app_change_pin (app_t app, CTRL ctrl, const char *chvnostr, int reset_mode, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.change_pin) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, pincb, pincb_arg); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation change_pin result: %s\n", gpg_strerror (err)); return err; @@ -664,11 +739,11 @@ app_check_pin (app_t app, const char *keyidstr, return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); if (!app->fnc.check_pin) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - err = lock_reader (app); + err = lock_reader (app->slot); if (err) return err; err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg); - unlock_reader (app); + unlock_reader (app->slot); if (opt.verbose) log_info ("operation check_pin result: %s\n", gpg_strerror (err)); return err; diff --git a/scd/command.c b/scd/command.c index 738b1f003..287f8c921 100644 --- a/scd/command.c +++ b/scd/command.c @@ -253,12 +253,12 @@ open_card (ctrl_t ctrl, const char *apptype) if (ctrl->server_local->card_removed) return map_to_assuan_status (gpg_error (GPG_ERR_CARD_REMOVED)); - if (ctrl->app_ctx) - return 0; /* Already initialized for one specific application. */ - if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); + if (ctrl->app_ctx) + return 0; /* Already initialized for one specific application. */ + if (ctrl->reader_slot != -1) slot = ctrl->reader_slot; else diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 341719b1e..5b5e09176 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -809,6 +809,7 @@ handle_signal (int signo) case SIGUSR1: log_info ("SIGUSR1 received - printing internal information:\n"); pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); + app_dump_state (); break; case SIGUSR2: @@ -1013,7 +1014,6 @@ handle_connections (int listen_fd) tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); - pth_attr_set (tattr, PTH_ATTR_NAME, "scd-connections"); #ifndef HAVE_W32_SYSTEM /* fixme */ sigemptyset (&sigs ); @@ -1022,6 +1022,7 @@ handle_connections (int listen_fd) sigaddset (&sigs, SIGUSR2); sigaddset (&sigs, SIGINT); sigaddset (&sigs, SIGTERM); + pth_sigmask (SIG_UNBLOCK, &sigs, NULL); ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); #else ev = NULL; @@ -1034,6 +1035,8 @@ handle_connections (int listen_fd) for (;;) { + sigset_t oldsigs; + if (shutdown_pending) { if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1) @@ -1093,6 +1096,11 @@ handle_connections (int listen_fd) handle_tick (); } + /* We now might create new threads and because we don't want any + signals - we are handling here - to be delivered to a new + thread. Thus we need to block those signals. */ + pth_sigmask (SIG_BLOCK, &sigs, &oldsigs); + if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset)) { plen = sizeof paddr; @@ -1101,15 +1109,26 @@ handle_connections (int listen_fd) { log_error ("accept failed: %s\n", strerror (errno)); } - else if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) - { - log_error ("error spawning connection handler: %s\n", - strerror (errno) ); - close (fd); - } + else + { + char threadname[50]; + snprintf (threadname, sizeof threadname-1, "conn fd=%d", fd); + threadname[sizeof threadname -1] = 0; + pth_attr_set (tattr, PTH_ATTR_NAME, threadname); + + if (!pth_spawn (tattr, start_connection_thread, (void*)fd)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + close (fd); + } + } fd = -1; } + /* Restore the signal mask. */ + pth_sigmask (SIG_SETMASK, &oldsigs, NULL); + } pth_event_free (ev, PTH_FREE_ALL); diff --git a/scd/scdaemon.h b/scd/scdaemon.h index eaa9abd35..54566b6ad 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -77,19 +77,28 @@ struct { #define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE) struct server_local_s; -struct card_ctx_s; struct app_ctx_s; -struct server_control_s { +struct server_control_s +{ + /* Local data of the server; used only in command.c. */ struct server_local_s *server_local; - int reader_slot; /* Slot of the open reader or -1 if not open. */ - struct card_ctx_s *card_ctx; + + /* Slot of the open reader or -1 if not open. */ + int reader_slot; + + /* The application context used with this connection or NULL if none + associated. Note that this is shared with the other connections: + All connections accessing the same reader are using the same + application context. */ struct app_ctx_s *app_ctx; - struct { + + /* Helper to store the value we are going to sign */ + struct + { unsigned char *value; int valuelen; - } in_data; /* helper to store the value we are going to sign */ - + } in_data; }; typedef struct server_control_s *CTRL; -- cgit v1.2.3 From 941880a28b1ab5064caed0c1445593fc96e16345 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sat, 4 Jun 2005 12:57:26 +0000 Subject: 2005-06-04 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (main): Allow any number of arguments, don't use first argument as input file name. Pass extra arguments to confucius_main. (confucius_main): Accept new arguments argc and argv and pass them to confucius_process. (confucius_process): Accept new arguments argc and argv and pass them to the confucius process. --- tools/ChangeLog | 10 ++++++++++ tools/symcryptrun.c | 54 ++++++++++++++++++++++++++++------------------------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index de7e5b89b..39f17e2ce 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,13 @@ +2005-06-04 Marcus Brinkmann <marcus@g10code.de> + + * symcryptrun.c (main): Allow any number of arguments, don't use + first argument as input file name. Pass extra arguments to + confucius_main. + (confucius_main): Accept new arguments argc and argv and pass them + to confucius_process. + (confucius_process): Accept new arguments argc and argv and pass + them to the confucius process. + 2005-06-01 Werner Koch <wk@g10code.com> * symcryptrun.c: Include mkdtemp.h. diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 09fc8582f..fcecf1770 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -486,15 +486,10 @@ confucius_drop_pass (char *pass) requested. If it is oDecrypt, decryption is requested. INFILE and OUTFILE are the temporary files used in the process. */ int -confucius_process (int mode, char *infile, char *outfile) +confucius_process (int mode, char *infile, char *outfile, + int argc, char *argv[]) { - char *const args[] = { opt.program, - mode == oEncrypt ? "-m1" : "-m2", - "-q", infile, - "-z", outfile, - "-s", opt.keyfile, - mode == oEncrypt ? "-af" : "-f", - NULL }; + char **args; int cstderr[2]; int master; int slave; @@ -523,9 +518,29 @@ confucius_process (int mode, char *infile, char *outfile) return 1; } + args = malloc (sizeof (char *) * (10 + argc)); + if (!args) + { + log_error (_("cannot allocate args vector\n")); + return 1; + } + args[0] = opt.program; + args[1] = (mode == oEncrypt) ? "-m1" : "-m2"; + args[2] = "-q"; + args[3] = infile; + args[4] = "-z"; + args[5] = outfile; + args[6] = "-s"; + args[7] = opt.keyfile; + args[8] = (mode == oEncrypt) ? "-af" : "-f"; + args[9 + argc] = NULL; + while (argc--) + args[9 + argc] = argv[argc]; + if (pipe (cstderr) < 0) { log_error (_("could not create pipe: %s\n"), strerror (errno)); + free (args); return 1; } @@ -534,6 +549,7 @@ confucius_process (int mode, char *infile, char *outfile) log_error (_("could not create pty: %s\n"), strerror (errno)); close (cstderr[0]); close (cstderr[1]); + free (args); return -1; } @@ -551,6 +567,7 @@ confucius_process (int mode, char *infile, char *outfile) close (slave); close (cstderr[0]); close (cstderr[1]); + free (args); return 1; } else if (pid == 0) @@ -587,6 +604,7 @@ confucius_process (int mode, char *infile, char *outfile) close (slave); close (cstderr[1]); + free (args); /* Listen on the output FDs. */ do @@ -753,7 +771,7 @@ confucius_process (int mode, char *infile, char *outfile) requested. If it is oDecrypt, decryption is requested. The other parameters are taken from the global option data. */ int -confucius_main (int mode) +confucius_main (int mode, int argc, char *argv[]) { int res; char *tmpdir; @@ -811,7 +829,7 @@ confucius_main (int mode) /* Run the engine and thus create the output file, handling passphrase retrieval. */ - res = confucius_process (mode, infile, outfile); + res = confucius_process (mode, infile, outfile, argc, argv); if (res) { remove_file (outfile, mode == oDecrypt); @@ -962,20 +980,6 @@ main (int argc, char **argv) xfree (configname); configname = NULL; - /* With --inputfile an argument is not allowed, without only one - optional argument is allowed. */ - if (argc > 1) - log_error (_("too many arguments\n")); - else if (opt.input && argc) - log_error (_("no argument allowed when using option \"%s\"\n"), - "--inputfile"); - - if (argc) - { - opt.input = *argv; - argv++; argc--; - } - if (!mode) log_error (_("either %s or %s must be given\n"), "--decrypt", "--encrypt"); @@ -1001,7 +1005,7 @@ main (int argc, char **argv) res = 1; } else if (!strcmp (opt.class, "confucius")) - res = confucius_main (mode); + res = confucius_main (mode, argc, argv); else { log_error (_("class %s is not supported\n"), opt.class); -- cgit v1.2.3 From 33701641829798ddd7fced64cf9a504cc5f48cc1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 7 Jun 2005 19:09:18 +0000 Subject: New debugging optionhs, updates to the manual. --- NEWS | 5 +- agent/ChangeLog | 21 ++ agent/agent.h | 49 +++-- agent/cache.c | 36 +++- agent/call-scd.c | 30 +-- agent/command-ssh.c | 5 +- agent/command.c | 21 +- agent/findkey.c | 24 +-- agent/gpg-agent.c | 6 + agent/pkdecrypt.c | 3 +- agent/pksign.c | 18 +- agent/query.c | 30 ++- common/sysutils.c | 2 +- doc/ChangeLog | 4 + doc/Makefile.am | 24 ++- doc/debugging.texi | 44 +++++ doc/gnupg-card-architecture.fig | 419 ++++++++++++++++++++++++++++++++++++++++ doc/gnupg.texi | 19 +- doc/gpg-agent.texi | 47 ++++- doc/scdaemon.texi | 8 + scd/ChangeLog | 4 + scd/command.c | 3 +- scd/scdaemon.c | 18 ++ 23 files changed, 759 insertions(+), 81 deletions(-) create mode 100644 doc/gnupg-card-architecture.fig diff --git a/NEWS b/NEWS index e28f1284a..daa18c4c0 100644 --- a/NEWS +++ b/NEWS @@ -13,9 +13,12 @@ Noteworthy changes in version 1.9.17 does allows only signing using TCOS cards but we are going to enhance it to match all the old capabilities. - * [gpg-agent] New option --rite-env-file and Assuan command + * [gpg-agent] New option --write-env-file and Assuan command UPDATESTARTUPTTY. + * [gpg-agent] New option --default-cache-ttl-ssh to set the TTL for + SSH passphrase caching independent from the other passphrases. + Noteworthy changes in version 1.9.16 (2005-04-21) ------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index 9621e5de0..1a157fa52 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,24 @@ +2005-06-06 Werner Koch <wk@g10code.com> + + * gpg-agent.c: New option --default-cache-ttl-ssh. + * agent.h (cache_mode_t): New. + * pksign.c (agent_pksign_do): New arg CACHE_MODE to replace the + ARG IGNORE_CACHE. Changed all callers. + (agent_pksign): Ditto. + * findkey.c (agent_key_from_file): Ditto. Canged all callers. + (unprotect): Ditto. + * command-ssh.c (data_sign): Use CACHE_MODE_SSH. + * cache.c (agent_get_cache): New arg CACHE_MODE. + (agent_put_cache): Ditto. Store it in the cache. + + * query.c (agent_query_dump_state, dump_mutex_state): New. + (unlock_pinentry): Reset the global context before releasing the + mutex. + * gpg-agent.c (handle_signal): Dump query.c info on SIGUSR1. + + * call-scd.c (agent_scd_check_aliveness): Always do a waitpid and + add a timeout to the locking. + 2005-06-03 Werner Koch <wk@g10code.com> * command.c (cmd_updatestartuptty): New. diff --git a/agent/agent.h b/agent/agent.h index 51e66abee..350e5c0d2 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -69,9 +69,13 @@ struct { smartcard tasks. */ int disable_scdaemon; /* Never use the SCdaemon. */ int no_grab; /* Don't let the pinentry grab the keyboard */ - unsigned long def_cache_ttl; + + /* The default and maximum TTL of cache entries. */ + unsigned long def_cache_ttl; /* Normal. */ + unsigned long def_cache_ttl_ssh; /* SSH. */ unsigned long max_cache_ttl; + int running_detached; /* We are running detached from the tty. */ int ignore_cache_for_signing; @@ -147,12 +151,26 @@ struct pin_entry_info_s { }; -enum { - PRIVATE_KEY_UNKNOWN = 0, - PRIVATE_KEY_CLEAR = 1, - PRIVATE_KEY_PROTECTED = 2, - PRIVATE_KEY_SHADOWED = 3 -}; +enum + { + PRIVATE_KEY_UNKNOWN = 0, + PRIVATE_KEY_CLEAR = 1, + PRIVATE_KEY_PROTECTED = 2, + PRIVATE_KEY_SHADOWED = 3 + }; + + +/* Values for the cache_mode arguments. */ +typedef enum + { + CACHE_MODE_IGNORE = 0, /* Special mode to by pass the cache. */ + CACHE_MODE_ANY, /* Any mode except ignore matches. */ + CACHE_MODE_NORMAL, /* Normal cache (gpg-agent). */ + CACHE_MODE_USER, /* GET_PASSPHRASE related cache. */ + CACHE_MODE_SSH /* SSH related cache. */ + } +cache_mode_t; + /*-- gpg-agent.c --*/ void agent_exit (int rc) JNLIB_GCC_A_NR; /* Also implemented in other tools */ @@ -171,7 +189,8 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl, const char *desc_text, const unsigned char *grip, unsigned char **shadow_info, - int ignore_cache, gcry_sexp_t *result); + cache_mode_t cache_mode, + gcry_sexp_t *result); gpg_error_t agent_public_key_from_file (ctrl_t ctrl, const unsigned char *grip, gcry_sexp_t *result); @@ -179,6 +198,7 @@ int agent_key_available (const unsigned char *grip); /*-- query.c --*/ void initialize_module_query (void); +void agent_query_dump_state (void); int agent_askpin (ctrl_t ctrl, const char *desc_text, const char *prompt_text, const char *inital_errtext, @@ -191,16 +211,19 @@ int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok, /*-- cache.c --*/ void agent_flush_cache (void); -int agent_put_cache (const char *key, const char *data, int ttl); -const char *agent_get_cache (const char *key, void **cache_id); +int agent_put_cache (const char *key, cache_mode_t cache_mode, + const char *data, int ttl); +const char *agent_get_cache (const char *key, cache_mode_t cache_mode, + void **cache_id); void agent_unlock_cache_entry (void **cache_id); /*-- pksign.c --*/ -int agent_pksign_do (CTRL ctrl, const char *desc_text, - gcry_sexp_t *signature_sexp, int ignore_cache); +int agent_pksign_do (ctrl_t ctrl, const char *desc_text, + gcry_sexp_t *signature_sexp, + cache_mode_t cache_mode); int agent_pksign (ctrl_t ctrl, const char *desc_text, - membuf_t *outbuf, int ignore_cache); + membuf_t *outbuf, cache_mode_t cache_mode); /*-- pkdecrypt.c --*/ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text, diff --git a/agent/cache.c b/agent/cache.c index 18aa7653b..a032b4fa7 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -42,6 +42,7 @@ struct cache_item_s { int ttl; /* max. lifetime given in seconds, -1 one means infinite */ int lockcount; struct secret_data_s *pw; + cache_mode_t cache_mode; char key[1]; }; @@ -78,6 +79,7 @@ new_data (const void *data, size_t length) } + /* check whether there are items to expire */ static void housekeeping (void) @@ -85,7 +87,7 @@ housekeeping (void) ITEM r, rprev; time_t current = gnupg_get_time (); - /* first expire the actual data */ + /* First expire the actual data */ for (r=thecache; r; r = r->next) { if (!r->lockcount && r->pw @@ -100,7 +102,7 @@ housekeeping (void) } } - /* second, make sure that we also remove them based on the created stamp so + /* Second, make sure that we also remove them based on the created stamp so that the user has to enter it from time to time. We do this every hour */ for (r=thecache; r; r = r->next) { @@ -115,7 +117,7 @@ housekeeping (void) } } - /* third, make sure that we don't have too many items in the list. + /* Third, make sure that we don't have too many items in the list. Expire old and unused entries after 30 minutes */ for (rprev=NULL, r=thecache; r; ) { @@ -186,19 +188,27 @@ agent_flush_cache (void) with a maximum lifetime of TTL seconds. If there is already data under this key, it will be replaced. Using a DATA of NULL deletes the entry. A TTL of 0 is replaced by the default TTL and a TTL of - -1 set infinite timeout. */ + -1 set infinite timeout. CACHE_MODE is stored with the cache entry + and used t select different timeouts. */ int -agent_put_cache (const char *key, const char *data, int ttl) +agent_put_cache (const char *key, cache_mode_t cache_mode, + const char *data, int ttl) { ITEM r; if (DBG_CACHE) - log_debug ("agent_put_cache `%s' requested ttl=%d\n", key, ttl); + log_debug ("agent_put_cache `%s' requested ttl=%d mode=%d\n", + key, ttl, cache_mode); housekeeping (); if (!ttl) - ttl = opt.def_cache_ttl; - if (!ttl) + { + if (cache_mode == CACHE_MODE_SSH) + ttl = opt.def_cache_ttl_ssh; + else + ttl = opt.def_cache_ttl; + } + if (!ttl || cache_mode == CACHE_MODE_IGNORE) return 0; for (r=thecache; r; r = r->next) @@ -217,6 +227,7 @@ agent_put_cache (const char *key, const char *data, int ttl) { r->created = r->accessed = gnupg_get_time (); r->ttl = ttl; + r->cache_mode = cache_mode; r->pw = new_data (data, strlen (data)+1); if (!r->pw) log_error ("out of core while allocating new cache item\n"); @@ -232,6 +243,7 @@ agent_put_cache (const char *key, const char *data, int ttl) strcpy (r->key, key); r->created = r->accessed = gnupg_get_time (); r->ttl = ttl; + r->cache_mode = cache_mode; r->pw = new_data (data, strlen (data)+1); if (!r->pw) { @@ -249,12 +261,16 @@ agent_put_cache (const char *key, const char *data, int ttl) } -/* Try to find an item in the cache */ +/* Try to find an item in the cache. Note that we currently don't + make use of CACHE_MODE. */ const char * -agent_get_cache (const char *key, void **cache_id) +agent_get_cache (const char *key, cache_mode_t cache_mode, void **cache_id) { ITEM r; + if (cache_mode == CACHE_MODE_IGNORE) + return NULL; + if (DBG_CACHE) log_debug ("agent_get_cache `%s'...\n", key); housekeeping (); diff --git a/agent/call-scd.c b/agent/call-scd.c index 00c9df2a7..4dff8e3c1 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -372,25 +372,33 @@ start_scd (ctrl_t ctrl) void agent_scd_check_aliveness (void) { + pth_event_t evt; pid_t pid; int rc; - /* We can do so only if there is no more active primary connection. - With an active primary connection, this is all no problem because - with the end of gpg-agent's session a disconnect is send and the - this function will be used at a later time. */ - if (!primary_scd_ctx || !primary_scd_ctx_reusable) - return; + if (!primary_scd_ctx) + return; /* No scdaemon running. */ - if (!pth_mutex_acquire (&start_scd_lock, 0, NULL)) + /* This is not a critical function so we use a short timeout while + acquiring the lock. */ + evt = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0)); + if (!pth_mutex_acquire (&start_scd_lock, 0, evt)) { - log_error ("failed to acquire the start_scd lock while" - " doing an aliveness check: %s\n", - strerror (errno)); + if (pth_event_occurred (evt)) + { + if (opt.verbose > 1) + log_info ("failed to acquire the start_scd lock while" + " doing an aliveness check: %s\n", "timeout"); + } + else + log_error ("failed to acquire the start_scd lock while" + " doing an aliveness check: %s\n", strerror (errno)); + pth_event_free (evt, PTH_FREE_THIS); return; } + pth_event_free (evt, PTH_FREE_THIS); - if (primary_scd_ctx && primary_scd_ctx_reusable) + if (primary_scd_ctx) { pid = assuan_get_pid (primary_scd_ctx); if (pid != (pid_t)(-1) && pid diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 030cc70a0..870afe059 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2014,7 +2014,8 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, ctrl->use_auth_call = 1; err = agent_pksign_do (ctrl, _("Please enter the passphrase " - "for the ssh key%0A %c"), &signature_sexp, 0); + "for the ssh key%0A %c"), &signature_sexp, + CACHE_MODE_SSH); ctrl->use_auth_call = 0; if (err) goto out; @@ -2386,7 +2387,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) for (i = 0; i < 20; i++) sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]); - err = agent_put_cache (key_grip, pi->pin, ttl); + err = agent_put_cache (key_grip, CACHE_MODE_SSH, pi->pin, ttl); if (err) goto out; diff --git a/agent/command.c b/agent/command.c index 56167118d..ebf3a8220 100644 --- a/agent/command.c +++ b/agent/command.c @@ -404,19 +404,19 @@ static int cmd_pksign (ASSUAN_CONTEXT ctx, char *line) { int rc; - int ignore_cache = 0; + cache_mode_t cache_mode = CACHE_MODE_NORMAL; ctrl_t ctrl = assuan_get_pointer (ctx); membuf_t outbuf; - + if (opt.ignore_cache_for_signing) - ignore_cache = 1; + cache_mode = CACHE_MODE_IGNORE; else if (!ctrl->server_local->use_cache_for_signing) - ignore_cache = 1; + cache_mode = CACHE_MODE_IGNORE; init_membuf (&outbuf, 512); rc = agent_pksign (ctrl, ctrl->server_local->keydesc, - &outbuf, ignore_cache); + &outbuf, cache_mode); if (rc) clear_outbuf (&outbuf); else @@ -623,7 +623,8 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line) desc = NULL; /* Note: we store the hexified versions in the cache. */ - pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL; + pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker) + : NULL; if (pw) { assuan_begin_confidential (ctx); @@ -647,7 +648,7 @@ cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line) if (!rc) { if (cacheid) - agent_put_cache (cacheid, response, 0); + agent_put_cache (cacheid, CACHE_MODE_USER, response, 0); assuan_begin_confidential (ctx); rc = assuan_set_okay_line (ctx, response); xfree (response); @@ -682,7 +683,7 @@ cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line) if (!cacheid || !*cacheid || strlen (cacheid) > 50) return set_error (Parameter_Error, "invalid length of cacheID"); - agent_put_cache (cacheid, NULL, 0); + agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0); return 0; } @@ -772,7 +773,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) Assuan error code. */ rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc, - grip, &shadow_info, 1, &s_skey); + grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey); if (rc) ; else if (!s_skey) @@ -842,7 +843,7 @@ cmd_preset_passphrase (ASSUAN_CONTEXT ctx, char *line) else return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED)); - rc = agent_put_cache (grip_clear, passphrase, ttl); + rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl); if (rc) log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc)); diff --git a/agent/findkey.c b/agent/findkey.c index 999a5d620..56433c9c4 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -230,8 +230,9 @@ modify_description (const char *in, const char *comment, char **result) caching mechanism. DESC_TEXT may be set to override the default description used for the pinentry. */ static int -unprotect (CTRL ctrl, const char *desc_text, - unsigned char **keybuf, const unsigned char *grip, int ignore_cache) +unprotect (ctrl_t ctrl, const char *desc_text, + unsigned char **keybuf, const unsigned char *grip, + cache_mode_t cache_mode) { struct pin_entry_info_s *pi; struct try_unprotect_arg_s arg; @@ -246,10 +247,12 @@ unprotect (CTRL ctrl, const char *desc_text, /* First try to get it from the cache - if there is none or we can't unprotect it, we fall back to ask the user */ - if (!ignore_cache) + if (cache_mode != CACHE_MODE_IGNORE) { void *cache_marker; - const char *pw = agent_get_cache (hexgrip, &cache_marker); + const char *pw; + + pw = agent_get_cache (hexgrip, cache_mode, &cache_marker); if (pw) { rc = agent_unprotect (*keybuf, pw, &result, &resultlen); @@ -280,7 +283,7 @@ unprotect (CTRL ctrl, const char *desc_text, if (!rc) { assert (arg.unprotected_key); - agent_put_cache (hexgrip, pi->pin, 0); + agent_put_cache (hexgrip, cache_mode, pi->pin, 0); xfree (*keybuf); *keybuf = arg.unprotected_key; } @@ -360,14 +363,13 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) /* Return the secret key as an S-Exp in RESULT after locating it using the grip. Returns NULL in RESULT if the operation should be diverted to a token; SHADOW_INFO will point then to an allocated - S-Expression with the shadow_info part from the file. With - IGNORE_CACHE passed as true the passphrase is not taken from the - cache. DESC_TEXT may be set to present a custom description for the - pinentry. */ + S-Expression with the shadow_info part from the file. CACHE_MODE + defines now the cache shall be used. DESC_TEXT may be set to + present a custom description for the pinentry. */ gpg_error_t agent_key_from_file (ctrl_t ctrl, const char *desc_text, const unsigned char *grip, unsigned char **shadow_info, - int ignore_cache, gcry_sexp_t *result) + cache_mode_t cache_mode, gcry_sexp_t *result) { int rc; unsigned char *buf; @@ -447,7 +449,7 @@ agent_key_from_file (ctrl_t ctrl, const char *desc_text, if (!rc) { - rc = unprotect (ctrl, desc_text_final, &buf, grip, ignore_cache); + rc = unprotect (ctrl, desc_text_final, &buf, grip, cache_mode); if (rc) log_error ("failed to unprotect the secret key: %s\n", gpg_strerror (rc)); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 90b071d5e..6cc08f845 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -83,6 +83,7 @@ enum cmd_and_opt_values oLCmessages, oScdaemonProgram, oDefCacheTTL, + oDefCacheTTLSSH, oMaxCacheTTL, oUseStandardSocket, oNoUseStandardSocket, @@ -140,6 +141,7 @@ static ARGPARSE_OPTS opts[] = { { oDefCacheTTL, "default-cache-ttl", 4, N_("|N|expire cached PINs after N seconds")}, + { oDefCacheTTLSSH, "default-cache-ttl-ssh", 4, "@" }, { oMaxCacheTTL, "max-cache-ttl", 4, "@" }, { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, N_("do not use the PIN cache when signing")}, @@ -367,6 +369,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.pinentry_program = NULL; opt.scdaemon_program = NULL; opt.def_cache_ttl = DEFAULT_CACHE_TTL; + opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL; opt.max_cache_ttl = MAX_CACHE_TTL; opt.ignore_cache_for_signing = 0; opt.allow_mark_trusted = 0; @@ -402,6 +405,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oDisableScdaemon: opt.disable_scdaemon = 1; break; case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break; + case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break; case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; @@ -413,6 +417,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) default: return 0; /* not handled */ } + return 1; /* handled */ } @@ -1339,6 +1344,7 @@ handle_signal (int signo) case SIGUSR1: log_info ("SIGUSR1 received - printing internal information:\n"); pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); + agent_query_dump_state (); agent_scd_dump_state (); break; diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 7a93e58f8..42ce69697 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -66,7 +66,8 @@ agent_pkdecrypt (CTRL ctrl, const char *desc_text, log_printhex ("cipher: ", ciphertext, ciphertextlen); } rc = agent_key_from_file (ctrl, desc_text, - ctrl->keygrip, &shadow_info, 0, &s_skey); + ctrl->keygrip, &shadow_info, + CACHE_MODE_NORMAL, &s_skey); if (rc) { log_error ("failed to read the secret key\n"); diff --git a/agent/pksign.c b/agent/pksign.c index 3337e188c..2a355e43e 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -79,8 +79,8 @@ do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash, /* SIGN whatever information we have accumulated in CTRL and return the signature S-Expression. */ int -agent_pksign_do (CTRL ctrl, const char *desc_text, - gcry_sexp_t *signature_sexp, int ignore_cache) +agent_pksign_do (ctrl_t ctrl, const char *desc_text, + gcry_sexp_t *signature_sexp, cache_mode_t cache_mode) { gcry_sexp_t s_skey = NULL, s_sig = NULL; unsigned char *shadow_info = NULL; @@ -90,16 +90,16 @@ agent_pksign_do (CTRL ctrl, const char *desc_text, return gpg_error (GPG_ERR_NO_SECKEY); rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip, - &shadow_info, ignore_cache, &s_skey); + &shadow_info, cache_mode, &s_skey); if (rc) { log_error ("failed to read the secret key\n"); goto leave; } - if (! s_skey) + if (!s_skey) { - /* divert operation to the smartcard */ + /* Divert operation to the smartcard */ unsigned char *buf = NULL; size_t len = 0; @@ -128,7 +128,7 @@ agent_pksign_do (CTRL ctrl, const char *desc_text, } else { - /* no smartcard, but a private key */ + /* No smartcard, but a private key */ gcry_sexp_t s_hash = NULL; @@ -176,15 +176,15 @@ agent_pksign_do (CTRL ctrl, const char *desc_text, /* SIGN whatever information we have accumulated in CTRL and write it back to OUTFP. */ int -agent_pksign (CTRL ctrl, const char *desc_text, - membuf_t *outbuf, int ignore_cache) +agent_pksign (ctrl_t ctrl, const char *desc_text, + membuf_t *outbuf, cache_mode_t cache_mode) { gcry_sexp_t s_sig = NULL; char *buf = NULL; size_t len = 0; int rc = 0; - rc = agent_pksign_do (ctrl, desc_text, &s_sig, ignore_cache); + rc = agent_pksign_do (ctrl, desc_text, &s_sig, cache_mode); if (rc) goto leave; diff --git a/agent/query.c b/agent/query.c index d3b42a416..c1e4dbacc 100644 --- a/agent/query.c +++ b/agent/query.c @@ -49,7 +49,7 @@ #define LOCK_TIMEOUT (1*60) -static ASSUAN_CONTEXT entry_ctx = NULL; +static assuan_context_t entry_ctx = NULL; #ifdef USE_GNU_PTH static pth_mutex_t entry_lock; #endif @@ -82,6 +82,30 @@ initialize_module_query (void) +static void +dump_mutex_state (pth_mutex_t *m) +{ + if (!(m->mx_state & PTH_MUTEX_INITIALIZED)) + log_printf ("not_initialized"); + else if (!(m->mx_state & PTH_MUTEX_LOCKED)) + log_printf ("not_locked"); + else + log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count); +} + + +/* This function may be called to print infromation pertaining to the + current state of this module to the log. */ +void +agent_query_dump_state (void) +{ + log_info ("agent_query_dump_state: entry_lock="); + dump_mutex_state (&entry_lock); + log_printf ("\n"); + log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld\n", + entry_ctx, (long)assuan_get_pid (entry_ctx)); +} + /* Unlock the pinentry so that another thread can start one and disconnect that pinentry - we do this after the unlock so that a @@ -90,8 +114,9 @@ initialize_module_query (void) static int unlock_pinentry (int rc) { - ASSUAN_CONTEXT ctx = entry_ctx; + assuan_context_t ctx = entry_ctx; + entry_ctx = NULL; #ifdef USE_GNU_PTH if (!pth_mutex_release (&entry_lock)) { @@ -100,7 +125,6 @@ unlock_pinentry (int rc) rc = gpg_error (GPG_ERR_INTERNAL); } #endif - entry_ctx = NULL; assuan_disconnect (ctx); return rc; } diff --git a/common/sysutils.c b/common/sysutils.c index 97fa23d95..a8f6f6f5d 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -105,7 +105,7 @@ enable_core_dumps (void) setrlimit (RLIMIT_CORE, &limit); return 1; /* We always return true because trhis function is merely a debugging aid. */ -#endif +# endif return 1; #endif } diff --git a/doc/ChangeLog b/doc/ChangeLog index f353bdf03..c4d263513 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,9 @@ 2005-06-03 Werner Koch <wk@g10code.com> + * debugging.texi (Architecture Details): New section, mostly empty. + * gnupg-card-architecture.fig: New. + * Makefile.am: Rules to build png and eps versions. + * gpg-agent.texi (Agent UPDATESTARTUPTTY): New. 2005-05-17 Werner Koch <wk@g10code.com> diff --git a/doc/Makefile.am b/doc/Makefile.am index 988bbf849..fdcd62dc0 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -18,14 +18,34 @@ ## Process this file with automake to produce Makefile.in -EXTRA_DIST = gnupg-badge-openpgp.eps gnupg-badge-openpgp.jpg +EXTRA_DIST = gnupg-badge-openpgp.eps gnupg-badge-openpgp.jpg \ + gnupg-card-architecture.eps gnupg-card-architecture.png + +BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png info_TEXINFOS = gnupg.texi + + gnupg_TEXINFOS = \ gpg.texi gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi \ tools.texi debugging.texi glossary.texi contrib.texi gpl.texi \ - sysnotes.texi + sysnotes.texi gnupg-card-architecture.fig DISTCLEANFILES = gnupg.tmp gnupg.ops + + +.fig.png: + fig2dev -L png `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.jpg: + fig2dev -L jpg `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.eps: + fig2dev -L eps `test -f '$<' || echo '$(srcdir)/'`$< $@ + +.fig.pdf: + fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@ + + diff --git a/doc/debugging.texi b/doc/debugging.texi index 49ab70bde..429dbd407 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -18,6 +18,7 @@ solve the problem at hand. @menu * Debugging Tools:: Description of some useful tools * Common Problems:: Commonly seen problems. +* Architecture Details:: How the whole thing works internally. @end menu @@ -105,6 +106,49 @@ shell). Even for GUI based Pinentries; you should have set on how to do it. +@item SSH hangs while a popping up pinentry was expected + +SSH has no way to tell the gpg-agent what terminal or X display it is +running on. So when remotely logging into a box where a gpg-agent with +SSH support is running, the pinentry will get popped up on whatever +display t he gpg-agent has been started. To solve this problem you may +issue the command + +@smallexample +echo UPDATESTARTUPTTY | gpg-connect-agent +@end smallexample + +and the next pinentry will pop up on your display or screen. However, +you need to kill the running pinentry first because only one pinentry +may be running at once. If you plan to use ssh on a new display you +should issue the above command before invoking ssh or any other service +making use of ssh. + @end itemize + +@c ******************************************** +@c *** Architecture Details ***************** +@c ******************************************** +@node Architecture Details +@section How the whole thing works internally. + + +@menu +* gpg 1.4 vs. 1.9:: Relationship between the two branches. +@end menu + +@node gpg 1.4 vs. 1.9 +@subsection Relationship between the two branches. + +Here is a little picture showing how the components work together: + +@image{gnupg-card-architecture, 14cm} + +@noindent +Lets try to explain it: + +TO BE DONE. + + diff --git a/doc/gnupg-card-architecture.fig b/doc/gnupg-card-architecture.fig new file mode 100644 index 000000000..e5772cd0f --- /dev/null +++ b/doc/gnupg-card-architecture.fig @@ -0,0 +1,419 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +# Copyright 2005 Werner Koch +# +# 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 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +0 32 #414541 +0 33 #808080 +0 34 #c0c0c0 +0 35 #c6b797 +0 36 #eff8ff +0 37 #dccba6 +0 38 #e0e0e0 +0 39 #8e8f8e +0 40 #aaaaaa +0 41 #555555 +0 42 #404040 +0 43 #868286 +0 44 #c7c3c7 +0 45 #e7e3e7 +0 46 #8e8e8e +0 47 #444444 +0 48 #868686 +0 49 #c7c7c7 +0 50 #666666 +0 51 #e2e2ee +0 52 #94949a +0 53 #dbdbdb +0 54 #a1a1b7 +0 55 #9c0000 +0 56 #ededed +0 57 #86acff +0 58 #7070ff +0 59 #bebebe +0 60 #515151 +0 61 #000049 +0 62 #797979 +0 63 #303430 +0 64 #c7b696 +0 65 #d7d7d7 +0 66 #aeaeae +0 67 #85807d +0 68 #d2d2d2 +0 69 #3a3a3a +0 70 #4573aa +0 71 #000000 +0 72 #e7e7e7 +0 73 #f7f7f7 +0 74 #d6d7d6 +0 75 #7b79a5 +0 76 #effbff +0 77 #9e9e9e +0 78 #717571 +0 79 #73758c +0 80 #414141 +0 81 #635dce +0 82 #565151 +0 83 #dd9d93 +0 84 #f1ece0 +0 85 #c3c3c3 +0 86 #e2c8a8 +0 87 #e1e1e1 +0 88 #da7a1a +0 89 #f1e41a +0 90 #887dc2 +0 91 #d6d6d6 +0 92 #8c8ca5 +0 93 #4a4a4a +0 94 #8c6b6b +0 95 #5a5a5a +0 96 #636363 +0 97 #b79b73 +0 98 #4193ff +0 99 #bf703b +0 100 #db7700 +0 101 #dab800 +0 102 #006400 +0 103 #5a6b3b +0 104 #d3d3d3 +0 105 #8e8ea4 +0 106 #f3b95d +0 107 #89996b +0 108 #646464 +0 109 #b7e6ff +0 110 #86c0ec +0 111 #bdbdbd +0 112 #d39552 +0 113 #98d2fe +0 114 #8c9c6b +0 115 #f76b00 +0 116 #5a6b39 +0 117 #8c9c6b +0 118 #8c9c7b +0 119 #184a18 +0 120 #adadad +0 121 #f7bd5a +0 122 #636b9c +0 123 #de0000 +0 124 #adadad +0 125 #f7bd5a +0 126 #adadad +0 127 #f7bd5a +0 128 #636b9c +0 129 #526b29 +0 130 #949494 +0 131 #006300 +0 132 #00634a +0 133 #7b844a +0 134 #e7bd7b +0 135 #a5b5c6 +0 136 #6b6b94 +0 137 #846b6b +0 138 #529c4a +0 139 #d6e7e7 +0 140 #526363 +0 141 #186b4a +0 142 #9ca5b5 +0 143 #ff9400 +0 144 #ff9400 +0 145 #00634a +0 146 #7b844a +0 147 #63737b +0 148 #e7bd7b +0 149 #184a18 +0 150 #f7bd5a +0 151 #dedede +0 152 #f3eed3 +0 153 #f5ae5d +0 154 #95ce99 +0 155 #b5157d +0 156 #eeeeee +0 157 #848484 +0 158 #7b7b7b +0 159 #005a00 +0 160 #e77373 +0 161 #ffcb31 +0 162 #29794a +0 163 #de2821 +0 164 #2159c6 +0 165 #f8f8f8 +0 166 #e6e6e6 +0 167 #21845a +0 168 #ff9408 +0 169 #007000 +0 170 #d00000 +0 171 #fed600 +0 172 #d82010 +0 173 #003484 +0 174 #d62010 +0 175 #389000 +0 176 #ba0000 +0 177 #003380 +0 178 #00a7bd +0 179 #ffc500 +0 180 #087bd0 +0 181 #fbc100 +0 182 #840029 +0 183 #07399c +0 184 #0063bd +0 185 #39acdf +0 186 #42c0e0 +0 187 #31ceff +0 188 #ffde00 +0 189 #085a00 +0 190 #ff2100 +0 191 #f75e08 +0 192 #ef7b08 +0 193 #ff8200 +0 194 #007d00 +0 195 #0000be +0 196 #757575 +0 197 #f3f3f3 +0 198 #d7d3d7 +0 199 #aeaaae +0 200 #c2c2c2 +0 201 #303030 +0 202 #515551 +0 203 #f7f3f7 +0 204 #717171 +6 9270 1980 13230 6570 +6 9471 3906 13014 5677 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 10540 4394 10540 3936 9471 3936 9471 4394 10540 4394 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 10387 5616 10387 5158 9471 5158 9471 5616 10387 5616 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 12984 5005 12984 4547 9471 4547 9471 5005 12984 5005 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 12984 5616 12984 5158 12067 5158 12067 5616 12984 5616 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 11701 5627 11701 5168 10784 5168 10784 5627 11701 5627 +4 0 0 50 -1 16 11 0.0000 4 173 835 9623 4242 OpenPGP\001 +4 0 0 50 -1 16 11 0.0000 4 132 2770 9776 4853 APDU and ISO-7816 access code\001 +4 0 0 50 -1 16 11 0.0000 4 132 448 9623 5464 CCID\001 +4 0 0 50 -1 16 11 0.0000 4 132 601 12220 5464 CT-API\001 +4 0 0 50 -1 16 11 0.0000 4 132 560 10957 5464 PC/SC\001 +-6 +6 10693 3906 13014 4394 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 11762 4394 11762 3936 10693 3936 10693 4394 11762 4394 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 12984 4394 12984 3936 11915 3936 11915 4394 12984 4394 +4 0 0 50 -1 16 11 0.0000 4 132 377 10998 4242 NKS\001 +4 0 0 50 -1 16 11 0.0000 4 132 804 12067 4242 PKCS#15\001 +-6 +2 4 0 2 0 6 60 -1 20 0.000 0 0 5 0 0 5 + 13137 2072 9318 2072 9318 5739 13137 5739 13137 2072 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 9318 3753 13137 3753 +2 4 0 2 0 6 60 -1 20 0.000 0 0 5 0 0 5 + 11691 6360 10774 6360 10774 5901 11691 5901 11691 6360 +2 1 2 2 0 7 50 -1 -1 4.500 0 0 -1 0 0 1 + 11762 5739 +2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 4 + 10693 5739 10693 6502 11762 6502 11762 5739 +4 0 0 50 -1 18 15 0.0000 4 183 1293 10540 2989 SCDaemon\001 +4 0 0 50 -1 16 11 0.0000 4 133 662 10896 6176 wrapper\001 +-6 +6 90 1980 4050 5760 +6 306 3906 3849 5677 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 1375 4394 1375 3936 306 3936 306 4394 1375 4394 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 1222 5616 1222 5158 306 5158 306 5616 1222 5616 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 3819 5005 3819 4547 306 4547 306 5005 3819 5005 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 3819 5616 3819 5158 2902 5158 2902 5616 3819 5616 +2 4 0 1 0 7 50 -1 -1 0.000 0 0 5 0 0 5 + 2536 5627 2536 5168 1619 5168 1619 5627 2536 5627 +4 0 0 50 -1 16 11 0.0000 4 173 835 458 4242 OpenPGP\001 +4 0 0 50 -1 16 11 0.0000 4 132 2770 611 4853 APDU and ISO-7816 access code\001 +4 0 0 50 -1 16 11 0.0000 4 132 448 458 5464 CCID\001 +4 0 0 50 -1 16 11 0.0000 4 132 601 3055 5464 CT-API\001 +4 0 0 50 -1 16 11 0.0000 4 132 560 1792 5464 PC/SC\001 +-6 +6 2139 3753 3208 4211 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 3208 4211 3208 3753 2139 3753 2139 4211 3208 4211 +4 0 0 50 -1 16 11 0.0000 4 132 784 2291 4058 Gluecode\001 +-6 +2 1 2 2 0 7 50 -1 -1 4.500 0 0 -1 0 0 1 + 2597 5739 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 40.73 81.47 + 2139 4028 1405 4150 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 4 + 153 3753 1833 3753 1833 4364 3972 4364 +2 4 0 2 0 6 60 -1 20 0.000 0 0 5 0 0 5 + 3972 2072 153 2072 153 5739 3972 5739 3972 2072 +4 0 0 50 -1 18 15 0.0000 4 224 866 1375 2989 gpg 1.4\001 +-6 +6 4888 4058 5346 5433 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 5346 5433 5346 4058 4888 4058 4888 5433 5346 5433 +4 0 0 50 -1 16 11 1.5708 4 132 611 5194 5128 Assuan\001 +-6 +6 4680 1980 8640 5760 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 5346 3753 5346 2378 4888 2378 4888 3753 5346 3753 +2 4 0 2 0 6 60 -1 20 0.000 0 0 5 0 0 5 + 8554 5739 4735 5739 4735 2072 8554 2072 8554 5739 +4 0 0 50 -1 16 11 1.5708 4 173 804 5194 3447 ssh-agent\001 +-6 +6 5805 3447 7332 4975 +6 5957 3447 7179 4211 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 7179 4211 7179 3447 5957 3447 5957 4211 7179 4211 +4 0 0 50 -1 16 11 0.0000 4 173 937 6110 3753 Private Key\001 +4 0 0 50 -1 16 11 0.0000 4 173 896 6110 4058 Operations\001 +-6 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1 + 7195 4883 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1 + 7195 4883 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 7332 4975 7332 4517 6721 4517 6721 4975 7332 4975 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 1 2 + 1 1 1.00 40.73 81.47 + 1 1 1.00 40.73 81.47 + 6568 4211 7027 4517 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 1 2 + 1 1 1.00 40.73 81.47 + 1 1 1.00 40.73 81.47 + 6568 4211 6110 4517 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 6416 4975 6416 4517 5805 4517 5805 4975 6416 4975 +4 0 0 50 -1 16 11 0.0000 4 132 397 6874 4822 Card\001 +4 0 0 50 -1 16 11 0.0000 4 132 356 5957 4822 Disk\001 +-6 +6 7638 3600 8401 4058 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 8401 4058 8401 3600 7638 3600 7638 4058 8401 4058 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1 + 7638 3814 +4 0 0 50 -1 16 11 0.0000 4 132 530 7790 3905 Cache\001 +-6 +6 9471 2225 9929 3600 +2 4 0 1 0 7 50 -1 -1 4.000 0 0 5 0 0 5 + 9929 3600 9929 2225 9471 2225 9471 3600 9929 3600 +4 0 0 50 -1 16 11 1.5708 4 132 611 9776 3294 Assuan\001 +-6 +6 6480 360 8640 1440 +2 4 0 2 0 6 60 -1 20 0.000 0 0 5 0 0 5 + 8554 1339 6568 1339 6568 423 8554 423 8554 1339 +4 0 0 50 -1 18 15 0.0000 4 234 967 7027 881 pinentry\001 +4 0 0 50 -1 16 10 0.0000 4 153 1375 6874 1187 (GTK+, Qt, Curses)\001 +-6 +6 10570 270 13137 1003 +2 1 1 1 1 2 50 -1 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 40.73 81.47 + 10632 331 11181 331 +2 1 0 2 1 2 50 -1 -1 6.000 0 0 -1 1 0 2 + 1 1 2.00 81.47 162.94 + 10632 637 11181 637 +2 1 0 1 0 2 50 -1 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 40.73 81.47 + 10632 942 11181 942 +4 0 0 50 -1 16 10 0.0000 4 163 1762 11365 392 Alternative access paths\001 +4 0 0 50 -1 16 10 0.0000 4 163 1426 11365 698 IPC (pipe or socket)\001 +4 0 0 50 -1 16 10 0.0000 4 122 1232 11365 1003 Internal data flow\001 +-6 +# Smartcard ID-1 +6 6840 6120 8550 7200 +6 7069 6526 7307 6746 +2 1 0 1 0 7 48 -1 -1 0.000 0 0 -1 0 0 2 + 7234 6691 7307 6691 +2 1 0 1 0 0 48 -1 20 0.000 0 0 -1 0 0 2 + 7069 6636 7143 6636 +2 1 0 1 0 7 48 -1 -1 0.000 0 0 -1 0 0 2 + 7069 6581 7143 6581 +2 1 0 1 0 7 48 -1 -1 0.000 0 0 -1 0 0 2 + 7069 6691 7143 6691 +2 1 0 1 0 7 48 -1 -1 0.000 0 0 -1 0 0 2 + 7143 6526 7143 6746 +2 1 0 1 0 7 48 -1 -1 0.000 0 0 -1 0 0 3 + 7307 6581 7234 6581 7234 6746 +2 1 0 1 0 7 48 -1 -1 0.000 0 0 -1 0 0 2 + 7234 6636 7307 6636 +2 4 0 1 0 31 49 -1 20 0.000 0 0 1 0 0 5 + 7069 6526 7307 6526 7307 6746 7069 6746 7069 6526 +-6 +2 4 0 1 -1 7 50 -1 20 0.000 0 0 1 0 0 5 + 8472 7185 6904 7185 6904 6197 8472 6197 8472 7185 +-6 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 40.73 81.47 + 5346 3142 5957 3753 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 1 1 1.00 40.73 81.47 + 5346 4669 5957 3905 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 1 2 + 1 1 1.00 40.73 81.47 + 1 1 1.00 40.73 81.47 + 7179 3814 7638 3814 +2 4 0 2 0 6 60 -1 20 0.000 0 0 5 0 0 5 + 11731 7480 10693 7480 10693 6991 11731 6991 11731 7480 +3 2 0 2 1 2 50 -1 -1 6.000 0 1 0 3 + 1 1 2.00 81.47 162.94 + 8022 3600 8096 2225 7513 1360 + 0.000 -1.000 0.000 +3 2 0 2 1 2 50 -1 -1 0.000 0 1 0 3 + 0 0 2.00 81.47 162.94 + 7332 4730 8737 4486 9471 2897 + 0.000 -1.000 0.000 +3 2 0 2 1 2 50 -1 -1 6.000 0 1 0 3 + 1 1 2.00 81.47 162.94 + 3238 3997 4216 4242 4888 4730 + 0.000 -1.000 0.000 +3 2 0 2 1 2 50 -1 -1 6.000 0 1 0 3 + 1 1 2.00 81.47 162.94 + 11243 6502 11304 6747 11181 6991 + 0.000 -1.000 0.000 +3 2 1 1 1 2 50 -1 -1 4.000 0 1 0 3 + 1 1 1.00 40.73 81.47 + 10693 7235 9471 7174 8493 6869 + 0.000 -1.000 0.000 +3 2 1 1 1 2 50 -1 -1 4.000 0 1 0 3 + 1 1 1.00 40.73 81.47 + 9898 5647 9532 6380 8493 6563 + 0.000 -1.000 0.000 +3 2 1 1 1 2 50 -1 -1 4.000 0 1 0 3 + 1 1 1.00 40.73 81.47 + 12465 5647 11731 6624 8493 6747 + 0.000 -1.000 0.000 +3 2 1 1 1 2 50 -1 -1 4.000 0 1 0 3 + 1 1 1.00 40.73 81.47 + 2077 5647 3177 6502 6843 6624 + 0.000 -1.000 0.000 +3 2 1 1 1 2 50 -1 -1 4.000 0 1 0 3 + 1 1 1.00 40.73 81.47 + 733 5647 2444 6808 6843 6747 + 0.000 -1.000 0.000 +3 2 1 1 1 2 50 -1 -1 4.000 0 1 0 3 + 1 1 1.00 40.73 81.47 + 3361 5647 4155 6319 6843 6502 + 0.000 -1.000 0.000 +4 0 0 50 -1 18 15 0.0000 4 214 1191 5957 2989 gpg-agent\001 +4 0 0 50 -1 16 11 0.0000 4 173 387 10998 7297 pcsd\001 diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 4c30980b3..d92f01cd9 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -86,14 +86,15 @@ section entitled ``Copying''. @insertcopying @end titlepage - +@ifnothtml @summarycontents @contents @page +@end ifnothtml @ifnottex @node Top -@top The GNU Privacy Guard +@top @insertcopying This manual documents how to use the GNU Privacy Guard system as well as @@ -120,6 +121,20 @@ the administration and the architecture. * Index:: Index of concepts and symbol names. @end menu +@ifhtml + +@center @image{gnupg-badge-openpgp,6cm,,The GnuPG Logo} + +@end ifhtml + + +@ifhtml +@page +@summarycontents +@contents +@end ifhtml + + @include gpg.texi @include gpgsm.texi @include gpg-agent.texi diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 5e8c19468..bad6639e2 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -42,7 +42,8 @@ else fi @end smallexample -The new option @option{--write-env-file} may be used instead. +@noindent +Note that the new option @option{--write-env-file} may be used instead. @noindent @@ -289,6 +290,11 @@ control this behaviour but this command line option takes precedence. Set the time a cache entry is valid to @var{n} seconds. The default are 600 seconds. +@item --default-cache-ttl-ssh @var{n} +@opindex default-cache-ttl +Set the time a cache entry used for SSH keys is valid to @var{n} +seconds. The default are 600 seconds. + @item --max-cache-ttl @var{n} @opindex max-cache-ttl Set the maximum time a cache entry is valid to @var{n} seconds. After @@ -506,12 +512,13 @@ are still pending, a shutdown is forced. @cpindex SIGINT Shuts down the process immediately. - @item SIGUSR1 -@itemx SIGUSR2 @cpindex SIGUSR1 +Dump internal information to the log file. + +@item SIGUSR2 @cpindex SIGUSR2 -These signals are used for internal purposes. +This signal is used for internal purposes. @end table @@ -523,12 +530,44 @@ These signals are used for internal purposes. @c man begin EXAMPLES +The usual way to invoke @command{gpg-agent} is + @example $ eval `gpg-agent --daemon` @end example @c man end +An alternative way is by replacing @command{ssh-agent} with +@command{gpg-agent}. If for example @command{ssh-agent} is started as +part of the Xsession intialization you may simply replace +@command{ssh-agent} by a script like: + +@cartouche +@example +#!/bin/sh + +exec /usr/local/bin/gpg-agent --enable-ssh-support --daemon \ + --write-env-file $@{HOME@}/.gpg-agent-info "$@@" +@end example +@end cartouche + +@noindent +and add something like (for Bourne shells) + +@cartouche +@example + if [ -f "$@{HOME@}/.gpg-agent-info" ]; then + . "$@{HOME@}/.gpg-agent-info" + export GPG_AGENT_INFO + export SSH_AUTH_SOCK + export SSH_AGENT_PID + fi +@end example +@end cartouche + +@noindent +to your shell initialization file (e.g. @file{~/.bashrc}). @c @c Assuan Protocol diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 134ca40df..d4a21b5ce 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -181,6 +181,14 @@ protocol. Note that this option may reveal sensitive data. This option disables all ticker functions like checking for card insertions. +@item --debug-allow-core-dump +@opindex debug-allow-core-dump +For security reasons we won't create a core dump when the process +aborts. For debugging purposes it is sometimes better to allow core +dump. This options enables it and also changes the working directory to +@file{/tmp} when running in @option{--server} mode. + + @item --no-detach @opindex no-detach Don't detach the process from the console. This is manly usefule for diff --git a/scd/ChangeLog b/scd/ChangeLog index da433e2f8..0f7e4d2fa 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2005-06-06 Werner Koch <wk@g10code.com> + + * scdaemon.c (main): New option --debug-allow-core-dump. + 2005-06-03 Werner Koch <wk@g10code.com> * scdaemon.c (handle_connections): Make sure that the signals we diff --git a/scd/command.c b/scd/command.c index 287f8c921..a308078d3 100644 --- a/scd/command.c +++ b/scd/command.c @@ -70,7 +70,7 @@ struct server_local_s { struct server_local_s *next_session; /* This object is usually assigned to a CTRL object (which is - globally visible). While enumeratin all sessions we sometimes + globally visible). While enumerating all sessions we sometimes need to access data of the CTRL object; thus we keep a backpointer here. */ ctrl_t ctrl_backlink; @@ -860,6 +860,7 @@ cmd_getattr (assuan_context_t ctx, char *line) /* FIXME: Applications should not return sensistive data if the card is locked. */ rc = app_getattr (ctrl->app_ctx, ctrl, keyword); + xfree (keyword); TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 5b5e09176..c75e87a62 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -67,6 +67,7 @@ enum cmd_and_opt_values oDebugAll, oDebugLevel, oDebugWait, + oDebugAllowCoreDump, oDebugCCIDDriver, oNoGreeting, oNoOptions, @@ -110,6 +111,7 @@ static ARGPARSE_OPTS opts[] = { { oDebugAll, "debug-all" ,0, "@"}, { oDebugLevel, "debug-level" ,2, "@"}, { oDebugWait,"debug-wait",1, "@"}, + { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" }, { oDebugCCIDDriver, "debug-ccid-driver", 0, "@"}, { oDebugDisableTicker, "debug-disable-ticker", 0, "@"}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, @@ -318,6 +320,7 @@ main (int argc, char **argv ) int debug_wait = 0; int gpgconf_list = 0; const char *config_filename = NULL; + int allow_coredump = 0; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -448,6 +451,10 @@ main (int argc, char **argv ) case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; + case oDebugAllowCoreDump: + enable_core_dumps (); + allow_coredump = 1; + break; case oDebugCCIDDriver: ccid_set_debug_level (ccid_set_debug_level (-1)+1); break; @@ -604,6 +611,17 @@ main (int argc, char **argv ) sigaction (SIGPIPE, &sa, NULL); } + /* If --debug-allow-core-dump has been given we also need to + switch the working directory to a place where we can actually + write. */ + if (allow_coredump) + { + if (chdir("/tmp")) + log_debug ("chdir to `/tmp' failed: %s\n", strerror (errno)); + else + log_debug ("changed working directory to `/tmp'\n"); + } + /* In multi server mode we need to listen on an additional socket. Create that socket now before starting the handler for the pipe connection. This allows that handler to send -- cgit v1.2.3 From deeba405a9a5868ea478db5003be6335ab9aac6f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 16 Jun 2005 08:12:03 +0000 Subject: gcc-4 defaults forced me to edit many many files to get rid of the char * vs. unsigned char * warnings. The GNU coding standards used to say that these mismatches are okay and better than a bunch of casts. Obviously this has changed now. --- agent/ChangeLog | 46 ++++++++++++++++++++++ agent/agent.h | 15 ++++---- agent/cache.c | 20 +++++++--- agent/call-scd.c | 19 ++++------ agent/command-ssh.c | 75 ++++++++++++++++-------------------- agent/command.c | 4 +- agent/divert-scd.c | 9 +++-- agent/findkey.c | 4 +- agent/genkey.c | 2 +- agent/gpg-agent.c | 11 ++++-- agent/minip12.c | 2 + agent/pkdecrypt.c | 2 +- agent/pksign.c | 2 +- agent/protect-tool.c | 21 +++++----- agent/protect.c | 29 ++++++++------ agent/query.c | 9 +++-- common/ChangeLog | 26 ++++++++++++- common/estream.c | 21 +++++----- common/estream.h | 8 ++-- common/iobuf.c | 19 ++++++---- common/iobuf.h | 4 +- common/miscellaneous.c | 2 +- common/sexputil.c | 9 +++-- common/simple-pwquery.c | 2 +- common/ttyio.c | 2 +- common/util.h | 2 +- doc/gpg-agent.texi | 8 +++- g10/ChangeLog | 5 +++ g10/g10.c | 4 +- g10/misc.c | 5 ++- jnlib/ChangeLog | 13 +++++++ jnlib/argparse.c | 2 +- jnlib/logging.c | 5 ++- jnlib/stringhelp.c | 97 ++++++++++++++++++++++++++++------------------- jnlib/stringhelp.h | 9 ++--- jnlib/utf8conv.c | 21 +++++----- kbx/ChangeLog | 11 ++++++ kbx/kbxutil.c | 2 +- kbx/keybox-blob.c | 45 ++++++++++++---------- kbx/keybox-defs.h | 5 ++- kbx/keybox-file.c | 4 +- scd/apdu.c | 2 +- scd/app-help.c | 2 +- scd/app-openpgp.c | 27 ++++++------- scd/app-p15.c | 28 +++++++------- scd/app.c | 2 +- scd/ccid-driver.c | 14 +++---- scd/command.c | 10 ++--- scd/iso7816.c | 18 +++++---- scd/pcsc-wrapper.c | 4 +- sm/ChangeLog | 32 ++++++++++++++++ sm/base64.c | 14 ++++--- sm/call-agent.c | 25 ++++++------ sm/certcheck.c | 14 ++++--- sm/certdump.c | 28 +++++++------- sm/certreqgen.c | 9 +++-- sm/delete.c | 4 +- sm/encrypt.c | 12 +++--- sm/fingerprint.c | 17 +++++---- sm/gpgsm.h | 10 ++--- sm/keydb.c | 9 +++-- sm/keylist.c | 4 +- sm/server.c | 4 +- sm/sign.c | 2 +- tools/ChangeLog | 5 +++ tools/gpg-connect-agent.c | 2 +- tools/gpgconf-comp.c | 2 +- tools/gpgkey2ssh.c | 3 ++ tools/watchgnupg.c | 2 +- 69 files changed, 558 insertions(+), 348 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 1a157fa52..055dbe53e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,49 @@ +2005-06-16 Werner Koch <wk@g10code.com> + + * protect-tool.c (make_advanced): Makde RESULT a plain char. + * call-scd.c (unescape_status_string): Need to cast unsigned char* + for strcpy. + (agent_card_pksign): Made arg R_BUF an unsigned char**. + * divert-scd.c (divert_pksign): Made SIGVAL unsigned char*. + (encode_md_for_card): Initialize R_VAL and R_LEN. + * genkey.c (store_key): Made BUF unsigned. + * protect.c (do_encryption): Ditto. + (do_encryption): Made arg PROTBEGIN unsigned. Initialize RESULT + and RESULTLEN even on error. + (merge_lists): Need to cast unsigned char * for strcpy. Initialize + RESULTand RESULTLEN even on error. + (agent_unprotect): Likewise for strtoul. + (make_shadow_info): Made P and INFO plain char. + (agent_shadow_key): Made P plain char. + +2005-06-15 Werner Koch <wk@g10code.com> + + * query.c (agent_get_passphrase): Made HEXSTRING a char*. + * command-ssh.c (ssh_key_grip): Made arg BUFFER unsigned. + (ssh_key_grip): Simplified. + (data_sign): Initialize variables with the definition. + (ssh_convert_key_to_blob): Make sure that BLOB and BLOB_SIZE + are set to NULL on error. Cool, gcc-4 detects uninitialized stuff + beyond function boundaries; well it can't know that we do error + proper error handling so that this was not a real error. + (file_to_buffer): Likewise for BUFFER and BUFFER_N. + (data_sign): Likewise for SIG and SIG_N. + (stream_read_byte): Set B to a value even on error. + * command.c (cmd_genkey): Changed VALUE to char. + (cmd_readkey): Cast arg for gcry_sexp_sprint. + * agent.h (struct server_control_s): Made KEYGRIP unsigned. + +2005-06-13 Werner Koch <wk@g10code.com> + + * command-ssh.c (start_command_handler_ssh): Reset the SCD. + +2005-06-09 Werner Koch <wk@g10code.com> + + * gpg-agent.c (create_socket_name): New option --max-cache-ttl-ssh. + * cache.c (housekeeping): Use it. + (agent_put_cache): Use a switch to get the default ttl so that it + is easier to add more cases. + 2005-06-06 Werner Koch <wk@g10code.com> * gpg-agent.c: New option --default-cache-ttl-ssh. diff --git a/agent/agent.h b/agent/agent.h index 350e5c0d2..7a646a85f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -71,9 +71,10 @@ struct { int no_grab; /* Don't let the pinentry grab the keyboard */ /* The default and maximum TTL of cache entries. */ - unsigned long def_cache_ttl; /* Normal. */ - unsigned long def_cache_ttl_ssh; /* SSH. */ - unsigned long max_cache_ttl; + unsigned long def_cache_ttl; /* Default. */ + unsigned long def_cache_ttl_ssh; /* for SSH. */ + unsigned long max_cache_ttl; /* Default. */ + unsigned long max_cache_ttl_ssh; /* for SSH. */ int running_detached; /* We are running detached from the tty. */ @@ -107,8 +108,8 @@ struct server_local_s; struct scd_local_s; /* Collection of data per session (aka connection). */ -struct server_control_s { - +struct server_control_s +{ /* Private data of the server (command.c). */ struct server_local_s *server_local; @@ -128,7 +129,7 @@ struct server_control_s { int valuelen; int raw_value: 1; } digest; - char keygrip[20]; + unsigned char keygrip[20]; int have_keygrip; int use_auth_call; /* Hack to send the PKAUTH command instead of the @@ -289,7 +290,7 @@ int agent_card_pksign (ctrl_t ctrl, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen); + unsigned char **r_buf, size_t *r_buflen); int agent_card_pkdecrypt (ctrl_t ctrl, const char *keyid, int (*getpin_cb)(void *, const char *, char*,size_t), diff --git a/agent/cache.c b/agent/cache.c index a032b4fa7..32b6ac0c7 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -103,10 +103,17 @@ housekeeping (void) } /* Second, make sure that we also remove them based on the created stamp so - that the user has to enter it from time to time. We do this every hour */ + that the user has to enter it from time to time. */ for (r=thecache; r; r = r->next) { - if (!r->lockcount && r->pw && r->created + opt.max_cache_ttl < current) + unsigned long maxttl; + + switch (r->cache_mode) + { + case CACHE_MODE_SSH: maxttl = opt.max_cache_ttl_ssh; break; + default: maxttl = opt.max_cache_ttl; break; + } + if (!r->lockcount && r->pw && r->created + maxttl < current) { if (DBG_CACHE) log_debug (" expired `%s' (%lus after creation)\n", @@ -203,10 +210,11 @@ agent_put_cache (const char *key, cache_mode_t cache_mode, if (!ttl) { - if (cache_mode == CACHE_MODE_SSH) - ttl = opt.def_cache_ttl_ssh; - else - ttl = opt.def_cache_ttl; + switch(cache_mode) + { + case CACHE_MODE_SSH: ttl = opt.def_cache_ttl_ssh; break; + default: ttl = opt.def_cache_ttl; break; + } } if (!ttl || cache_mode == CACHE_MODE_IGNORE) return 0; diff --git a/agent/call-scd.c b/agent/call-scd.c index 4dff8e3c1..7a623fda4 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -465,7 +465,7 @@ unescape_status_string (const unsigned char *s) { char *buffer, *d; - buffer = d = xtrymalloc (strlen (s)+1); + buffer = d = xtrymalloc (strlen ((const char*)s)+1); if (!buffer) return NULL; while (*s) @@ -666,7 +666,7 @@ agent_card_pksign (ctrl_t ctrl, int (*getpin_cb)(void *, const char *, char*, size_t), void *getpin_cb_arg, const unsigned char *indata, size_t indatalen, - char **r_buf, size_t *r_buflen) + unsigned char **r_buf, size_t *r_buflen) { int rc, i; char *p, line[ASSUAN_LINELENGTH]; @@ -714,14 +714,11 @@ agent_card_pksign (ctrl_t ctrl, /* Create an S-expression from it which is formatted like this: "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */ *r_buflen = 21 + 11 + sigbuflen + 4; - *r_buf = xtrymalloc (*r_buflen); - if (!*r_buf) - { - gpg_error_t tmperr = out_of_core (); - xfree (*r_buf); - return unlock_scd (ctrl, tmperr); - } - p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" ); + p = xtrymalloc (*r_buflen); + *r_buf = (unsigned char*)p; + if (!p) + return unlock_scd (ctrl, out_of_core ()); + p = stpcpy (p, "(7:sig-val(3:rsa(1:s" ); sprintf (p, "%u:", (unsigned int)sigbuflen); p += strlen (p); memcpy (p, sigbuf, sigbuflen); @@ -895,7 +892,7 @@ card_getattr_cb (void *opaque, const char *line) if (keywordlen == parm->keywordlen && !memcmp (keyword, parm->keyword, keywordlen)) { - parm->data = unescape_status_string (line); + parm->data = unescape_status_string ((const unsigned char*)line); if (!parm->data) parm->error = errno; } diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 870afe059..a43fee24f 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -297,6 +297,7 @@ stream_read_byte (estream_t stream, unsigned char *b) err = gpg_error_from_errno (errno); else err = gpg_error (GPG_ERR_EOF); + *b = 0; } else { @@ -604,6 +605,9 @@ file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n) gpg_error_t err; int ret; + *buffer = NULL; + *buffer_n = 0; + buffer_new = NULL; err = 0; @@ -1381,6 +1385,9 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size, gpg_error_t err; unsigned int i; + *blob = NULL; + *blob_size = 0; + blob_new = NULL; stream = NULL; err = 0; @@ -1535,20 +1542,12 @@ ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size, S-Expression KEY and writes it to BUFFER, which must be large enough to hold it. Returns usual error code. */ static gpg_error_t -ssh_key_grip (gcry_sexp_t key, char *buffer) +ssh_key_grip (gcry_sexp_t key, unsigned char *buffer) { - gpg_error_t err; - char *p; + if (!gcry_pk_get_keygrip (key, buffer)) + return gpg_error (GPG_ERR_INTERNAL); - /* FIXME: unsigned vs. signed. */ - - p = gcry_pk_get_keygrip (key, buffer); - if (! p) - err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */ - else - err = 0; - - return err; + return 0; } /* Converts the secret key KEY_SECRET into a public key, storing it in @@ -1654,7 +1653,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) } pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL); - err = gcry_sexp_sscan (&s_pk, NULL, pkbuf, pkbuflen); + err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen); if (err) { log_error ("failed to build S-Exp from received card key: %s\n", @@ -1877,7 +1876,7 @@ ssh_handler_request_identities (ctrl_t ctrl, if (err) goto out; - err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n); + err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n); if (err) goto out; @@ -1984,14 +1983,14 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, unsigned char **sig, size_t *sig_n) { gpg_error_t err; - gcry_sexp_t signature_sexp; - estream_t stream; - gcry_sexp_t valuelist; - gcry_sexp_t sublist; - gcry_mpi_t sig_value; - unsigned char *sig_blob; - size_t sig_blob_n; - char *identifier; + gcry_sexp_t signature_sexp = NULL; + estream_t stream = NULL; + gcry_sexp_t valuelist = NULL; + gcry_sexp_t sublist = NULL; + gcry_mpi_t sig_value = NULL; + unsigned char *sig_blob = NULL;; + size_t sig_blob_n = 0; + char *identifier = NULL; const char *identifier_raw; size_t identifier_n; ssh_key_type_spec_t spec; @@ -1999,17 +1998,10 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, unsigned int i; const char *elems; size_t elems_n; - gcry_mpi_t *mpis; + gcry_mpi_t *mpis = NULL; - signature_sexp = NULL; - identifier = NULL; - valuelist = NULL; - sublist = NULL; - sig_blob = NULL; - sig_blob_n = 0; - stream = NULL; - sig_value = NULL; - mpis = NULL; + *sig = NULL; + *sig_n = 0; ctrl->use_auth_call = 1; err = agent_pksign_do (ctrl, @@ -2119,7 +2111,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, if (err) goto out; - *sig = (char *) sig_blob; + *sig = sig_blob; *sig_n = sig_blob_n; out: @@ -2684,7 +2676,7 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) secure memory, since we never give out secret keys. FIXME: This is a pretty good DoS. We only have a limited amount - of secure memory, we can't trhow hin everything we get from a + of secure memory, we can't throw in everything we get from a client -wk */ /* Retrieve request. */ @@ -2824,7 +2816,6 @@ start_command_handler_ssh (int sock_client) struct server_control_s ctrl; estream_t stream_sock; gpg_error_t err; - int bad; int ret; /* Setup control structure. */ @@ -2868,15 +2859,15 @@ start_command_handler_ssh (int sock_client) goto out; } - while (1) - { - bad = ssh_request_process (&ctrl, stream_sock); - if (bad) - break; - }; + /* Main processing loop. */ + while ( !ssh_request_process (&ctrl, stream_sock) ) + ; - out: + /* Reset the SCD in case it has been used. */ + agent_reset_scd (&ctrl); + + out: if (stream_sock) es_fclose (stream_sock); diff --git a/agent/command.c b/agent/command.c index ebf3a8220..c39bcc6ab 100644 --- a/agent/command.c +++ b/agent/command.c @@ -168,7 +168,7 @@ parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf) if (n != 20) return set_error (Parameter_Error, "invalid length of keygrip"); - for (p=string, n=0; n < 20; p += 2, n++) + for (p=(const unsigned char*)string, n=0; n < 20; p += 2, n++) buf[n] = xtoi_2 (p); return 0; @@ -494,7 +494,7 @@ cmd_genkey (ASSUAN_CONTEXT ctx, char *line) init_membuf (&outbuf, 512); - rc = agent_genkey (ctrl, value, valuelen, &outbuf); + rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf); xfree (value); if (rc) clear_outbuf (&outbuf); diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 41a5dfcda..9d2fa446c 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -139,10 +139,13 @@ static int encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo, unsigned char **r_val, size_t *r_len) { - byte *frame; - byte asn[100]; + unsigned char *frame; + unsigned char asn[100]; size_t asnlen; + *r_val = NULL; + *r_len = 0; + asnlen = DIM(asn); if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) { @@ -295,7 +298,7 @@ divert_pksign (CTRL ctrl, int rc; char *kid; size_t siglen; - char *sigval; + unsigned char *sigval; unsigned char *data; size_t ndata; diff --git a/agent/findkey.c b/agent/findkey.c index 56433c9c4..1cb7efaf3 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -345,7 +345,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) } /* Convert the file into a gcrypt S-expression object. */ - rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); + rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen); xfree (fname); fclose (fp); xfree (buf); @@ -500,7 +500,7 @@ agent_key_from_file (ctrl_t ctrl, const char *desc_text, } buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL); - rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen); + rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen); wipememory (buf, buflen); xfree (buf); if (rc) diff --git a/agent/genkey.c b/agent/genkey.c index e07518d5a..d0319f7b4 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -33,7 +33,7 @@ static int store_key (gcry_sexp_t private, const char *passphrase, int force) { int rc; - char *buf; + unsigned char *buf; size_t len; unsigned char grip[20]; diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 6cc08f845..8732c98d7 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -85,6 +85,7 @@ enum cmd_and_opt_values oDefCacheTTL, oDefCacheTTLSSH, oMaxCacheTTL, + oMaxCacheTTLSSH, oUseStandardSocket, oNoUseStandardSocket, @@ -143,6 +144,7 @@ static ARGPARSE_OPTS opts[] = { N_("|N|expire cached PINs after N seconds")}, { oDefCacheTTLSSH, "default-cache-ttl-ssh", 4, "@" }, { oMaxCacheTTL, "max-cache-ttl", 4, "@" }, + { oMaxCacheTTLSSH, "max-cache-ttl-ssh", 4, "@" }, { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, N_("do not use the PIN cache when signing")}, { oAllowMarkTrusted, "allow-mark-trusted", 0, @@ -156,8 +158,9 @@ static ARGPARSE_OPTS opts[] = { }; -#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ -#define MAX_CACHE_TTL (120*60) /* 2 hours */ +#define DEFAULT_CACHE_TTL (10*60) /* 10 minutes */ +#define DEFAULT_CACHE_TTL_SSH (30*60) /* 30 minutes */ +#define MAX_CACHE_TTL (120*60) /* 2 hours */ /* flag to indicate that a shutdown was requested */ @@ -369,8 +372,9 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.pinentry_program = NULL; opt.scdaemon_program = NULL; opt.def_cache_ttl = DEFAULT_CACHE_TTL; - opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL; + opt.def_cache_ttl_ssh = DEFAULT_CACHE_TTL_SSH; opt.max_cache_ttl = MAX_CACHE_TTL; + opt.max_cache_ttl_ssh = MAX_CACHE_TTL; opt.ignore_cache_for_signing = 0; opt.allow_mark_trusted = 0; opt.disable_scdaemon = 0; @@ -407,6 +411,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oDefCacheTTL: opt.def_cache_ttl = pargs->r.ret_ulong; break; case oDefCacheTTLSSH: opt.def_cache_ttl_ssh = pargs->r.ret_ulong; break; case oMaxCacheTTL: opt.max_cache_ttl = pargs->r.ret_ulong; break; + case oMaxCacheTTLSSH: opt.max_cache_ttl_ssh = pargs->r.ret_ulong; break; case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; diff --git a/agent/minip12.c b/agent/minip12.c index 5ca85033d..31be15373 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -1552,6 +1552,8 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, struct buffer_s seqlist[2]; int seqlistidx = 0; + n = buflen = 0; /* (avoid compiler warning). */ + if (cert && certlen) { /* Encode the certificate. */ diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 42ce69697..1d64c1b15 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -52,7 +52,7 @@ agent_pkdecrypt (CTRL ctrl, const char *desc_text, goto leave; } - rc = gcry_sexp_sscan (&s_cipher, NULL, ciphertext, ciphertextlen); + rc = gcry_sexp_sscan (&s_cipher, NULL, (char*)ciphertext, ciphertextlen); if (rc) { log_error ("failed to convert ciphertext: %s\n", gpg_strerror (rc)); diff --git a/agent/pksign.c b/agent/pksign.c index 2a355e43e..e9df19351 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -117,7 +117,7 @@ agent_pksign_do (ctrl_t ctrl, const char *desc_text, len = gcry_sexp_canon_len (buf, 0, NULL, NULL); assert (len); - rc = gcry_sexp_sscan (&s_sig, NULL, buf, len); + rc = gcry_sexp_sscan (&s_sig, NULL, (char*)buf, len); xfree (buf); if (rc) { diff --git a/agent/protect-tool.c b/agent/protect-tool.c index e8f1d2c10..5f59d5e06 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -239,9 +239,9 @@ make_advanced (const unsigned char *buf, size_t buflen) int rc; size_t erroff, len; gcry_sexp_t sexp; - unsigned char *result; + char *result; - rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen); + rc = gcry_sexp_sscan (&sexp, &erroff, (const char*)buf, buflen); if (rc) { log_error ("invalid canonical S-Expression (off=%u): %s\n", @@ -378,7 +378,7 @@ read_and_protect (const char *fname) xfree (result); if (!p) return; - result = p; + result = (unsigned char*)p; resultlen = strlen (p); } @@ -417,7 +417,7 @@ read_and_unprotect (const char *fname) xfree (result); if (!p) return; - result = p; + result = (unsigned char*)p; resultlen = strlen (p); } @@ -434,12 +434,13 @@ read_and_shadow (const char *fname) unsigned char *key; unsigned char *result; size_t resultlen; + unsigned char dummy_info[] = "(8:313233342:43)"; key = read_key (fname); if (!key) return; - rc = agent_shadow_key (key, "(8:313233342:43)", &result); + rc = agent_shadow_key (key, dummy_info, &result); xfree (key); if (rc) { @@ -455,7 +456,7 @@ read_and_shadow (const char *fname) xfree (result); if (!p) return; - result = p; + result = (unsigned char*)p; resultlen = strlen (p); } @@ -682,7 +683,7 @@ import_p12_file (const char *fname) if (!buf) return; - kparms = p12_parse (buf, buflen, (pw=get_passphrase (2)), + kparms = p12_parse ((unsigned char*)buf, buflen, (pw=get_passphrase (2)), import_p12_cert_cb, NULL); release_passphrase (pw); xfree (buf); @@ -773,7 +774,7 @@ import_p12_file (const char *fname) xfree (result); if (!p) return; - result = p; + result = (unsigned char*)p; resultlen = strlen (p); } @@ -932,7 +933,7 @@ export_p12_file (const char *fname) if (opt_have_cert) { - cert = read_file ("-", &certlen); + cert = (unsigned char*)read_file ("-", &certlen); if (!cert) { wipememory (key, keylen_for_wipe); @@ -1040,7 +1041,7 @@ percent_plus_unescape (unsigned char *string) static char * percent_plus_unescape_string (char *string) { - unsigned char *p = string; + unsigned char *p = (unsigned char*)string; size_t n; n = percent_plus_unescape (p); diff --git a/agent/protect.c b/agent/protect.c index 658c8c529..45bdae496 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -134,19 +134,22 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) */ static int -do_encryption (const char *protbegin, size_t protlen, +do_encryption (const unsigned char *protbegin, size_t protlen, const char *passphrase, const unsigned char *sha1hash, unsigned char **result, size_t *resultlen) { gcry_cipher_hd_t hd; const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"; int blklen, enclen, outlen; - char *iv = NULL; + unsigned char *iv = NULL; int rc; char *outbuf = NULL; char *p; int saltpos, ivpos, encpos; + *resultlen = 0; + *result = NULL; + rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE); if (rc) @@ -250,7 +253,7 @@ do_encryption (const char *protbegin, size_t protlen, return tmperr; } *resultlen = strlen (p); - *result = p; + *result = (unsigned char*)p; memcpy (p+saltpos, iv+2*blklen, 8); memcpy (p+ivpos, iv, blklen); memcpy (p+encpos, outbuf, enclen); @@ -261,7 +264,7 @@ do_encryption (const char *protbegin, size_t protlen, -/* Protect the key encoded in canonical format in plainkey. We assume +/* Protect the key encoded in canonical format in PLAINKEY. We assume a valid S-Exp here. */ int agent_protect (const unsigned char *plainkey, const char *passphrase, @@ -469,6 +472,9 @@ merge_lists (const unsigned char *protectedkey, const unsigned char *startpos, *endpos; int i, rc; + *result = NULL; + *resultlen = 0; + if (replacepos < 26) return gpg_error (GPG_ERR_BUG); @@ -487,7 +493,7 @@ merge_lists (const unsigned char *protectedkey, return out_of_core (); /* Copy the initial segment */ - strcpy (newlist, "(11:private-key"); + strcpy ((char*)newlist, "(11:private-key"); p = newlist + 15; memcpy (p, protectedkey+15+10, replacepos-15-10); p += replacepos-15-10; @@ -669,7 +675,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, is nothing we should worry about */ if (s[n] != ')' ) return gpg_error (GPG_ERR_INV_SEXP); - s2kcount = strtoul (s, NULL, 10); + s2kcount = strtoul ((const char*)s, NULL, 10); if (!s2kcount) return gpg_error (GPG_ERR_CORRUPTED_PROTECTION); s += n; @@ -838,7 +844,7 @@ unsigned char * make_shadow_info (const char *serialno, const char *idstring) { const char *s; - unsigned char *info, *p; + char *info, *p; char numbuf[21]; int n; @@ -853,13 +859,13 @@ make_shadow_info (const char *serialno, const char *idstring) sprintf (numbuf, "%d:", n); p = stpcpy (p, numbuf); for (s=serialno; *s && s[1]; s += 2) - *p++ = xtoi_2 (s); + *(unsigned char *)p++ = xtoi_2 (s); sprintf (numbuf, "%d:", strlen (idstring)); p = stpcpy (p, numbuf); p = stpcpy (p, idstring); *p++ = ')'; *p = 0; - return info; + return (unsigned char *)info; } @@ -878,7 +884,7 @@ agent_shadow_key (const unsigned char *pubkey, const unsigned char *point; size_t n; int depth = 0; - unsigned char *p; + char *p; size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL); size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL); @@ -930,7 +936,8 @@ agent_shadow_key (const unsigned char *pubkey, /* Calculate required length by taking in account: the "shadowed-" prefix, the "shadowed", "t1-v1" as well as some parenthesis */ n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1; - *result = p = xtrymalloc (n); + *result = xtrymalloc (n); + p = (char*)*result; if (!p) return out_of_core (); p = stpcpy (p, "(20:shadowed-private-key"); diff --git a/agent/query.c b/agent/query.c index c1e4dbacc..b231f6fc3 100644 --- a/agent/query.c +++ b/agent/query.c @@ -58,7 +58,7 @@ static pth_mutex_t entry_lock; struct entry_parm_s { int lines; size_t size; - char *buffer; + unsigned char *buffer; }; @@ -372,7 +372,7 @@ agent_askpin (ctrl_t ctrl, { memset (&parm, 0, sizeof parm); parm.size = pininfo->max_length; - parm.buffer = pininfo->pin; + parm.buffer = (unsigned char*)pininfo->pin; if (errtext) { @@ -444,7 +444,8 @@ agent_get_passphrase (CTRL ctrl, int rc; char line[ASSUAN_LINELENGTH]; struct entry_parm_s parm; - unsigned char *p, *hexstring; + unsigned char *p; + char *hexstring; int i; *retpass = NULL; @@ -497,7 +498,7 @@ agent_get_passphrase (CTRL ctrl, return unlock_pinentry (map_assuan_err (rc)); } - hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1); + hexstring = gcry_malloc_secure (strlen ((char*)parm.buffer)*2+1); if (!hexstring) { gpg_error_t tmperr = out_of_core (); diff --git a/common/ChangeLog b/common/ChangeLog index 08fb06775..e7905ea58 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,9 +1,33 @@ +2005-06-15 Werner Koch <wk@g10code.com> + + * miscellaneous.c (make_printable_string): Made P a void*. + + * sexputil.c (keygrip_from_canon_sexp, cmp_simple_canon_sexp): + Fixed signed/unsigned pointer mismatch. + (make_simple_sexp_from_hexstr): Ditto. This is all too ugly; I + wonder why gcc-4's default is to warn about them and forcing us to + use cast the warning away. + * iobuf.c (block_filter): Ditto. + (iobuf_flush): Ditto. + (iobuf_read_line): Ditto. + (iobuf_read): Make BUFFER a void *. + (iobuf_write): Make BUFFER a const void *. + * ttyio.c (tty_print_utf8_string2): Ditto. + * estream.c (estream_cookie_mem): Make MEMORY unsigned char*. + (es_write): Make BUFFER a void *. + (es_writen): Ditto. + (es_func_fd_read, es_func_fd_write, es_func_mem_read) + (es_func_mem_write): Ditto. + (es_read, es_readn): Ditto. + (es_func_mem_write): Made MEMORY_NEW an unsigned char *. + * estream.h (es_cookie_read_function_t) + (es_cookie_write_function_t): Changed buffer arg to void*. + 2005-06-03 Werner Koch <wk@g10code.com> * estream.c: Use HAVE_CONFIG_H and not USE_CONFIG_H! (es_func_fd_read, es_func_fd_write): Protect against EINTR. - 2005-06-01 Werner Koch <wk@g10code.com> * Makefile.am (AM_CPPFLAGS): Added. diff --git a/common/estream.c b/common/estream.c index bf5b02001..70b3d9c6e 100644 --- a/common/estream.c +++ b/common/estream.c @@ -294,7 +294,7 @@ es_init_do (void) typedef struct estream_cookie_mem { unsigned int flags; /* Open flags. */ - char *memory; /* Data. */ + unsigned char *memory; /* Data. */ size_t memory_size; /* Size of MEMORY. */ size_t offset; /* Current offset in MEMORY. */ size_t data_len; /* Length of data in MEMORY. */ @@ -350,7 +350,7 @@ es_func_mem_create (void *ES__RESTRICT *ES__RESTRICT cookie, /* Read function for memory objects. */ static ssize_t -es_func_mem_read (void *cookie, char *buffer, size_t size) +es_func_mem_read (void *cookie, void *buffer, size_t size) { estream_cookie_mem_t mem_cookie = cookie; ssize_t ret; @@ -371,11 +371,11 @@ es_func_mem_read (void *cookie, char *buffer, size_t size) /* Write function for memory objects. */ static ssize_t -es_func_mem_write (void *cookie, const char *buffer, size_t size) +es_func_mem_write (void *cookie, const void *buffer, size_t size) { estream_cookie_mem_t mem_cookie = cookie; func_realloc_t func_realloc = mem_cookie->func_realloc; - char *memory_new; + unsigned char *memory_new; size_t newsize; ssize_t ret; int err; @@ -591,7 +591,7 @@ es_func_fd_create (void **cookie, int fd, unsigned int flags) /* Read function for fd objects. */ static ssize_t -es_func_fd_read (void *cookie, char *buffer, size_t size) +es_func_fd_read (void *cookie, void *buffer, size_t size) { estream_cookie_fd_t file_cookie = cookie; @@ -606,7 +606,7 @@ es_func_fd_read (void *cookie, char *buffer, size_t size) /* Write function for fd objects. */ static ssize_t -es_func_fd_write (void *cookie, const char *buffer, size_t size) +es_func_fd_write (void *cookie, const void *buffer, size_t size) { estream_cookie_fd_t file_cookie = cookie; @@ -1122,9 +1122,10 @@ es_read_lbf (estream_t ES__RESTRICT stream, *the amount of bytes read in BYTES_READ. */ static int es_readn (estream_t ES__RESTRICT stream, - unsigned char *ES__RESTRICT buffer, + void *ES__RESTRICT buffer_arg, size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) { + unsigned char *buffer = (unsigned char *)buffer_arg; size_t data_read_unread, data_read; int err; @@ -1388,7 +1389,7 @@ es_write_lbf (estream_t ES__RESTRICT stream, amount of bytes written in BYTES_WRITTEN. */ static int es_writen (estream_t ES__RESTRICT stream, - const unsigned char *ES__RESTRICT buffer, + const void *ES__RESTRICT buffer, size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) { size_t data_written; @@ -2289,7 +2290,7 @@ es_ungetc (int c, estream_t stream) int es_read (estream_t ES__RESTRICT stream, - char *ES__RESTRICT buffer, size_t bytes_to_read, + void *ES__RESTRICT buffer, size_t bytes_to_read, size_t *ES__RESTRICT bytes_read) { int err; @@ -2309,7 +2310,7 @@ es_read (estream_t ES__RESTRICT stream, int es_write (estream_t ES__RESTRICT stream, - const char *ES__RESTRICT buffer, size_t bytes_to_write, + const void *ES__RESTRICT buffer, size_t bytes_to_write, size_t *ES__RESTRICT bytes_written) { int err; diff --git a/common/estream.h b/common/estream.h index c201b666a..ebe575926 100644 --- a/common/estream.h +++ b/common/estream.h @@ -72,9 +72,9 @@ typedef struct es__stream *estream_t; typedef ssize_t (*es_cookie_read_function_t) (void *cookie, - char *buffer, size_t size); + void *buffer, size_t size); typedef ssize_t (*es_cookie_write_function_t) (void *cookie, - const char *buffer, + const void *buffer, size_t size); typedef int (*es_cookie_seek_function_t) (void *cookie, off_t *pos, int whence); @@ -166,10 +166,10 @@ int _es_putc_overflow (int c, estream_t stream); int es_ungetc (int c, estream_t stream); int es_read (estream_t ES__RESTRICT stream, - char *ES__RESTRICT buffer, size_t bytes_to_read, + void *ES__RESTRICT buffer, size_t bytes_to_read, size_t *ES__RESTRICT bytes_read); int es_write (estream_t ES__RESTRICT stream, - const char *ES__RESTRICT buffer, size_t bytes_to_write, + const void *ES__RESTRICT buffer, size_t bytes_to_write, size_t *ES__RESTRICT bytes_written); size_t es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems, diff --git a/common/iobuf.c b/common/iobuf.c index 52a388514..32b9e18c6 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -675,10 +675,11 @@ sock_filter (void *opaque, int control, iobuf_t chain, byte * buf, * without a filter */ static int -block_filter (void *opaque, int control, iobuf_t chain, byte * buf, +block_filter (void *opaque, int control, iobuf_t chain, byte * buffer, size_t * ret_len) { block_filter_ctx_t *a = opaque; + char *buf = (char *)buffer; size_t size = *ret_len; int c, needed, rc = 0; char *p; @@ -1762,7 +1763,7 @@ iobuf_flush (iobuf_t a) if (a->use == 3) { /* increase the temp buffer */ - char *newbuf; + unsigned char *newbuf; size_t newsize = a->d.size + 8192; if (DBG_IOBUF) @@ -1829,8 +1830,9 @@ iobuf_readbyte (iobuf_t a) int -iobuf_read (iobuf_t a, byte * buf, unsigned buflen) +iobuf_read (iobuf_t a, void *buffer, unsigned int buflen) { + unsigned char *buf = (unsigned char *)buffer; int c, n; if (a->unget.buf || a->nlimit) @@ -1915,7 +1917,7 @@ iobuf_peek (iobuf_t a, byte * buf, unsigned buflen) int -iobuf_writebyte (iobuf_t a, unsigned c) +iobuf_writebyte (iobuf_t a, unsigned int c) { int rc; @@ -1933,8 +1935,9 @@ iobuf_writebyte (iobuf_t a, unsigned c) int -iobuf_write (iobuf_t a, byte * buf, unsigned buflen) +iobuf_write (iobuf_t a, const void *buffer, unsigned int buflen) { + const unsigned char *buf = (const unsigned char *)buffer; int rc; if (a->directfp) @@ -2311,7 +2314,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, unsigned *length_of_buffer, unsigned *max_length) { int c; - char *buffer = *addr_of_buffer; + char *buffer = (char *)*addr_of_buffer; unsigned length = *length_of_buffer; unsigned nbytes = 0; unsigned maxlen = *max_length; @@ -2321,7 +2324,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, { /* must allocate a new buffer */ length = 256; buffer = xmalloc (length); - *addr_of_buffer = buffer; + *addr_of_buffer = (unsigned char *)buffer; *length_of_buffer = length; } @@ -2344,7 +2347,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, length += 3; /* correct for the reserved byte */ length += length < 1024 ? 256 : 1024; buffer = xrealloc (buffer, length); - *addr_of_buffer = buffer; + *addr_of_buffer = (unsigned char *)buffer; *length_of_buffer = length; length -= 3; /* and reserve again */ p = buffer + nbytes; diff --git a/common/iobuf.h b/common/iobuf.h index 0af94e22d..b991717c2 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -120,12 +120,12 @@ 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); +int iobuf_read (iobuf_t a, void *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_write (iobuf_t a, const void *buf, unsigned buflen); int iobuf_writestr (iobuf_t a, const char *buf); void iobuf_flush_temp (iobuf_t temp); diff --git a/common/miscellaneous.c b/common/miscellaneous.c index 86b0fcb3a..d81213ef9 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -66,7 +66,7 @@ print_utf8_string( FILE *fp, const byte *p, size_t n ) } char * -make_printable_string( const byte *p, size_t n, int delim ) +make_printable_string (const void *p, size_t n, int delim ) { return sanitize_buffer (p, n, delim); } diff --git a/common/sexputil.c b/common/sexputil.c index 802916b44..8a27ad978 100644 --- a/common/sexputil.c +++ b/common/sexputil.c @@ -52,7 +52,7 @@ keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, if (!grip) return gpg_error (GPG_ERR_INV_VALUE); - err = gcry_sexp_sscan (&sexp, NULL, key, keylen); + err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen); if (err) return err; if (!gcry_pk_get_keygrip (sexp, grip)) @@ -66,8 +66,11 @@ keygrip_from_canon_sexp (const unsigned char *key, size_t keylen, are identical or !0 if they are not. Not that this function can't be used for sorting. */ int -cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b) +cmp_simple_canon_sexp (const unsigned char *a_orig, + const unsigned char *b_orig) { + const char *a = (const char *)a_orig; + const char *b = (const char *)b_orig; unsigned long n1, n2; char *endp; @@ -124,7 +127,7 @@ make_simple_sexp_from_hexstr (const char *line, size_t *nscanned) buf = xtrymalloc (strlen (numbuf) + len + 1 + 1); if (!buf) return NULL; - p = stpcpy (buf, numbuf); + p = (unsigned char *)stpcpy ((char *)buf, numbuf); s = line; if ((n&1)) { diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index 8a027e799..de3689810 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -404,7 +404,7 @@ static char * copy_and_escape (char *buffer, const char *text) { int i; - const unsigned char *s = text; + const unsigned char *s = (unsigned char *)text; char *p = buffer; diff --git a/common/ttyio.c b/common/ttyio.c index eab805e20..5749c59fe 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -322,7 +322,7 @@ tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) break; } if( i < n ) { - buf = utf8_to_native( p, n, 0 ); + buf = utf8_to_native( (const char *)p, n, 0 ); if( max_n && (strlen( buf ) > max_n )) { buf[max_n] = 0; } diff --git a/common/util.h b/common/util.h index d233dbf5e..1ced59b67 100644 --- a/common/util.h +++ b/common/util.h @@ -153,7 +153,7 @@ 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); +char *make_printable_string (const void *p, size_t n, int delim); int is_file_compressed (const char *s, int *ret_rc); diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index bad6639e2..144745b4c 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -293,7 +293,7 @@ Set the time a cache entry is valid to @var{n} seconds. The default are @item --default-cache-ttl-ssh @var{n} @opindex default-cache-ttl Set the time a cache entry used for SSH keys is valid to @var{n} -seconds. The default are 600 seconds. +seconds. The default are 1800 seconds. @item --max-cache-ttl @var{n} @opindex max-cache-ttl @@ -301,6 +301,12 @@ Set the maximum time a cache entry is valid to @var{n} seconds. After this time a cache entry will get expired even if it has been accessed recently. The default are 2 hours (7200 seconds). +@item --max-cache-ttl-ssh @var{n} +@opindex max-cache-ttl-ssh +Set the maximum time a cache entry used for SSH keys is valid to @var{n} +seconds. After this time a cache entry will get expired even if it has +been accessed recently. The default are 2 hours (7200 seconds). + @item --pinentry-program @var{filename} @opindex pinentry-program Use program @var{filename} as the PIN entry. The default is installation diff --git a/g10/ChangeLog b/g10/ChangeLog index b33735e1f..0ae73b535 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,8 @@ +2005-06-15 Werner Koch <wk@g10code.com> + + * g10.c (print_hashline, add_group): Fixes for signed/unsigned + pointer mismatch warnings. + 2005-06-01 Werner Koch <wk@g10code.com> * mkdtemp.c: Removed. diff --git a/g10/g10.c b/g10/g10.c index 0be5636a2..234d13f41 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -933,7 +933,7 @@ static void add_group(char *string) return; } - trim_trailing_ws(name,strlen(name)); + trim_trailing_ws((unsigned char *)name,strlen(name)); /* Break apart the values */ while ((value= strsep(&string," \t"))) @@ -3124,7 +3124,7 @@ print_hashline( MD_HANDLE md, int algo, const char *fname ) const byte *p; if ( fname ) { - for (p = fname; *p; p++ ) { + for (p = (const unsigned char *)fname; *p; p++ ) { if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) printf("%%%02X", *p ); else diff --git a/g10/misc.c b/g10/misc.c index 7012a8a25..516e80bcc 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -986,9 +986,10 @@ mpi_print( FILE *fp, gcry_mpi_t a, int mode ) } else { int rc; - unsigned char *buffer; + char *buffer; - rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, &buffer, NULL, a ); + rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, + &(unsigned char*)buffer, NULL, a ); assert( !rc ); fputs( buffer, fp ); n += strlen(buffer); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index f308a7ea3..f0463c5b3 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,16 @@ +2005-06-15 Werner Koch <wk@g10code.com> + + * stringhelp.c (sanitize_buffer): Make P a void*. + (ascii_memistr, memistr): Ditto. + (ascii_memcasecmp): Ditto. + * logging.c (writen): Use void * for arg BUFFER. + * stringhelp.c (memistr): Fixed unsigned/signed pointer conflict. + (ascii_memistr): Ditto. + (ascii_memcasemem): Ditto. + * utf8conv.c (utf8_to_native): Ditto. + (utf8_to_native): Ditto. + * argparse.c (show_version): Removed non-required cast. + 2005-01-19 Werner Koch <wk@g10code.com> * logging.c (fun_writer): Don't fallback to stderr. Print to diff --git a/jnlib/argparse.c b/jnlib/argparse.c index 485c60786..980d1186c 100644 --- a/jnlib/argparse.c +++ b/jnlib/argparse.c @@ -852,7 +852,7 @@ show_version() /* additional program info */ for(i=30; i < 40; i++ ) if( (s=strusage(i)) ) - fputs( (const byte*)s, stdout); + fputs (s, stdout); fflush(stdout); } diff --git a/jnlib/logging.c b/jnlib/logging.c index 97a2b9c9e..c944006a5 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -87,10 +87,11 @@ struct fun_cookie_s { char name[1]; }; -/* Write NBYTES of BUF to file descriptor FD. */ +/* Write NBYTES of BUFFER to file descriptor FD. */ static int -writen (int fd, const unsigned char *buf, size_t nbytes) +writen (int fd, const void *buffer, size_t nbytes) { + const char *buf = buffer; size_t nleft = nbytes; int nwritten; diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 5a3b41528..760398b0c 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -1,6 +1,6 @@ /* stringhelp.c - standard string helper functions * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -35,45 +35,57 @@ /* * Look for the substring SUB in buffer and return a pointer to that - * substring in BUF or NULL if not found. + * substring in BUFFER or NULL if not found. * Comparison is case-insensitive. */ const char * -memistr( const char *buf, size_t buflen, const char *sub ) +memistr (const void *buffer, size_t buflen, const char *sub) { - const byte *t, *s ; - size_t n; + const unsigned char *buf = buffer; + const unsigned char *t = (const unsigned char *)buffer; + const unsigned char *s = (const unsigned char *)sub; + size_t n = buflen; - for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) - if( toupper(*t) == toupper(*s) ) { - for( buf=t++, buflen = n--, s++; - n && toupper(*t) == toupper(*s); t++, s++, n-- ) - ; - if( !*s ) - return buf; - t = buf; n = buflen; s = sub ; + for ( ; n ; t++, n-- ) + { + if ( toupper (*t) == toupper (*s) ) + { + for ( buf=t++, buflen = n--, s++; + n && toupper (*t) == toupper (*s); t++, s++, n-- ) + ; + if (!*s) + return (const char*)buf; + t = buf; + s = (const unsigned char *)sub ; + n = buflen; } - - return NULL ; + } + return NULL; } const char * -ascii_memistr( const char *buf, size_t buflen, const char *sub ) +ascii_memistr ( const void *buffer, size_t buflen, const char *sub ) { - const byte *t, *s ; - size_t n; + const unsigned char *buf = buffer; + const unsigned char *t = (const unsigned char *)buf; + const unsigned char *s = (const unsigned char *)sub; + size_t n = buflen; - for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) - if( ascii_toupper(*t) == ascii_toupper(*s) ) { - for( buf=t++, buflen = n--, s++; - n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- ) - ; - if( !*s ) - return buf; - t = buf; n = buflen; s = sub ; + for ( ; n ; t++, n-- ) + { + if (ascii_toupper (*t) == ascii_toupper (*s) ) + { + for ( buf=t++, buflen = n--, s++; + n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- ) + ; + if (!*s) + return (const char*)buf; + t = (const unsigned char *)buf; + s = (const unsigned char *)sub ; + n = buflen; } - - return NULL ; + } + return NULL; } /* This function is similar to strncpy(). However it won't copy more @@ -402,13 +414,14 @@ print_sanitized_utf8_string (FILE *fp, const char *string, int delim) delim) : 0; } -/* Create a string from the buffer P of length N which is suitable for +/* Create a string from the buffer P_ARG of length N which is suitable for printing. Caller must release the created string using xfree. */ char * -sanitize_buffer (const unsigned char *p, size_t n, int delim) +sanitize_buffer (const void *p_arg, size_t n, int delim) { + const unsigned char *p = p_arg; size_t save_n, buflen; - const byte *save_p; + const unsigned char *save_p; char *buffer, *d; /* first count length */ @@ -552,15 +565,19 @@ ascii_strncasecmp (const char *a, const char *b, size_t n) int -ascii_memcasecmp( const char *a, const char *b, size_t n ) +ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n ) { - if (a == b) - return 0; - for ( ; n; n--, a++, b++ ) { - if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) ) - return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); - } + const char *a = a_arg; + const char *b = b_arg; + + if (a == b) return 0; + for ( ; n; n--, a++, b++ ) + { + if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) ) + return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); + } + return 0; } int @@ -586,8 +603,8 @@ ascii_memcasemem (const void *haystack, size_t nhaystack, return (void*)haystack; /* finding an empty needle is really easy */ if (nneedle <= nhaystack) { - const unsigned char *a = haystack; - const unsigned char *b = a + nhaystack - nneedle; + const char *a = haystack; + const char *b = a + nhaystack - nneedle; for (; a <= b; a++) { diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index 412da3a0e..bdd7d561c 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -23,7 +23,7 @@ #include "types.h" -const char *memistr( const char *buf, size_t buflen, const char *sub ); +const char *memistr (const void *buf, size_t buflen, const char *sub); char *mem2str( char *, const void *, size_t); char *trim_spaces( char *string ); char *trim_trailing_spaces( char *string ); @@ -46,7 +46,7 @@ size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim); size_t print_sanitized_string (FILE *fp, const char *string, int delim); size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); -char *sanitize_buffer (const unsigned char *p, size_t n, int delim); +char *sanitize_buffer (const void *p, size_t n, int delim); #ifdef HAVE_W32_SYSTEM @@ -54,15 +54,14 @@ const char *w32_strerror (int ec); #endif -const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); int ascii_isupper (int c); int ascii_islower (int c); int ascii_toupper (int c); int ascii_tolower (int c); int ascii_strcasecmp( const char *a, const char *b ); int ascii_strncasecmp (const char *a, const char *b, size_t n); -int ascii_memcasecmp( const char *a, const char *b, size_t n ); -const char *ascii_memistr ( const char *buf, size_t buflen, const char *sub); +int ascii_memcasecmp( const void *a, const void *b, size_t n ); +const char *ascii_memistr ( const void *buf, size_t buflen, const char *sub); void *ascii_memcasemem (const void *haystack, size_t nhaystack, const void *needle, size_t nneedle); diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c index 691176766..4df8b7b32 100644 --- a/jnlib/utf8conv.c +++ b/jnlib/utf8conv.c @@ -136,16 +136,17 @@ get_native_charset () * new allocated UTF8 string. */ char * -native_to_utf8 (const char *string) +native_to_utf8 (const char *orig_string) { - const byte *s; + const unsigned char *string = (const unsigned char *)orig_string; + const unsigned char *s; char *buffer; - byte *p; + unsigned char *p; size_t length = 0; if (no_translation) { - buffer = jnlib_xstrdup (string); + buffer = jnlib_xstrdup (orig_string); } else if (active_charset) { @@ -156,7 +157,7 @@ native_to_utf8 (const char *string) length += 2; /* we may need 3 bytes */ } buffer = jnlib_xmalloc (length + 1); - for (p = buffer, s = string; *s; s++) + for (p = (unsigned char *)buffer, s = string; *s; s++) { if ((*s & 0x80)) { @@ -187,7 +188,7 @@ native_to_utf8 (const char *string) length++; } buffer = jnlib_xmalloc (length + 1); - for (p = buffer, s = string; *s; s++) + for (p = (unsigned char *)buffer, s = string; *s; s++) { if (*s & 0x80) { @@ -212,11 +213,12 @@ utf8_to_native (const char *string, size_t length, int delim) { int nleft; int i; - byte encbuf[8]; + unsigned char encbuf[8]; int encidx; const byte *s; size_t n; - byte *buffer = NULL, *p = NULL; + char *buffer = NULL; + char *p = NULL; unsigned long val = 0; size_t slen; int resync = 0; @@ -225,7 +227,8 @@ utf8_to_native (const char *string, size_t length, int delim) /* 2. pass (p!=NULL): create string */ for (;;) { - for (slen = length, nleft = encidx = 0, n = 0, s = string; slen; + for (slen = length, nleft = encidx = 0, n = 0, + s = (const unsigned char *)string; slen; s++, slen--) { if (resync) diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 7c112085c..4fd06d5ca 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,14 @@ +2005-06-15 Werner Koch <wk@g10code.com> + + * keybox-file.c (_keybox_read_blob2): Make IMAGE unsigned. + (_keybox_write_blob): + + * keybox-blob.c (create_blob_finish, _keybox_create_x509_blob): + Fixed warnings about signed/unsigned pointer mismatches. + (x509_email_kludge): Ditto. + (_keybox_new_blob): Changed arg IMAGE to unsigned char *. + (_keybox_get_blob_image): Changed return type to unsigned char*. + 2005-06-01 Werner Koch <wk@g10code.com> * keybox-file.c (ftello) [!HAVE_FSEEKO]: New replacement diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 7fe6178d6..0569b5a67 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -386,7 +386,7 @@ import_openpgp (const char *filename) buffer = read_file (filename, &buflen); if (!buffer) return; - p = buffer; + p = (unsigned char *)buffer; for (;;) { err = _keybox_parse_openpgp (p, buflen, &nparsed, &info); diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 48bce28e2..67c74b777 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -646,8 +646,8 @@ static int create_blob_finish (KEYBOXBLOB blob) { struct membuf *a = blob->buf; - byte *p; - char *pp; + unsigned char *p; + unsigned char *pp; int i; size_t n; @@ -656,6 +656,7 @@ create_blob_finish (KEYBOXBLOB blob) put32 (a, 0); /* Hmmm: why put32() ?? */ /* get the memory area */ + n = 0; /* (Just to avoid compiler warning.) */ p = get_membuf (a, &n); if (!p) return gpg_error (GPG_ERR_ENOMEM); @@ -783,7 +784,7 @@ _keybox_create_pgp_blob (KEYBOXBLOB *r_blob, KBNODE keyblock, int as_ephemeral) static char * x509_email_kludge (const char *name) { - const unsigned char *p; + const char *p; unsigned char *buf; int n; @@ -805,7 +806,7 @@ x509_email_kludge (const char *name) buf[n] = xtoi_2 (p); buf[n++] = '>'; buf[n] = 0; - return buf; + return (char *)buf; } @@ -818,8 +819,9 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, { int i, rc = 0; KEYBOXBLOB blob; - unsigned char *p; - unsigned char **names = NULL; + unsigned char *sn; + char *p; + char **names = NULL; size_t max_names; *r_blob = NULL; @@ -827,28 +829,28 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, if( !blob ) return gpg_error (gpg_err_code_from_errno (errno)); - p = ksba_cert_get_serial (cert); - if (p) + sn = ksba_cert_get_serial (cert); + if (sn) { size_t n, len; - n = gcry_sexp_canon_len (p, 0, NULL, NULL); + n = gcry_sexp_canon_len (sn, 0, NULL, NULL); if (n < 2) { - xfree (p); + xfree (sn); return gpg_error (GPG_ERR_GENERAL); } - blob->serialbuf = p; - p++; n--; /* skip '(' */ - for (len=0; n && *p && *p != ':' && digitp (p); n--, p++) - len = len*10 + atoi_1 (p); - if (*p != ':') + blob->serialbuf = sn; + sn++; n--; /* skip '(' */ + for (len=0; n && *sn && *sn != ':' && digitp (sn); n--, sn++) + len = len*10 + atoi_1 (sn); + if (*sn != ':') { xfree (blob->serialbuf); blob->serialbuf = NULL; return gpg_error (GPG_ERR_GENERAL); } - p++; - blob->serial = p; + sn++; + blob->serial = sn; blob->seriallen = len; } @@ -863,6 +865,7 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, rc = gpg_error (gpg_err_code_from_errno (errno)); goto leave; } + p = ksba_cert_get_issuer (cert, 0); if (!p) { @@ -872,10 +875,9 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, names[blob->nuids++] = p; for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) { - if (blob->nuids >= max_names) { - unsigned char **tmp; + char **tmp; max_names += 100; tmp = xtryrealloc (names, max_names * sizeof *names); @@ -964,7 +966,8 @@ _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, int -_keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, off_t off) +_keybox_new_blob (KEYBOXBLOB *r_blob, + unsigned char *image, size_t imagelen, off_t off) { KEYBOXBLOB blob; @@ -1000,7 +1003,7 @@ _keybox_release_blob (KEYBOXBLOB blob) -const char * +const unsigned char * _keybox_get_blob_image ( KEYBOXBLOB blob, size_t *n ) { *n = blob->bloblen; diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index b58294459..7bbed8519 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -140,10 +140,11 @@ int _keybox_create_x509_blob (KEYBOXBLOB *r_blob, ksba_cert_t cert, unsigned char *sha1_digest, int as_ephemeral); #endif /*KEYBOX_WITH_X509*/ -int _keybox_new_blob (KEYBOXBLOB *r_blob, char *image, size_t imagelen, +int _keybox_new_blob (KEYBOXBLOB *r_blob, + unsigned char *image, size_t imagelen, off_t off); void _keybox_release_blob (KEYBOXBLOB blob); -const char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); +const unsigned char *_keybox_get_blob_image (KEYBOXBLOB blob, size_t *n); off_t _keybox_get_blob_fileoffset (KEYBOXBLOB blob); void _keybox_update_header_blob (KEYBOXBLOB blob); diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c index fe02c1f9f..3883ce607 100644 --- a/kbx/keybox-file.c +++ b/kbx/keybox-file.c @@ -48,7 +48,7 @@ ftello (FILE *stream) int _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted) { - char *image; + unsigned char *image; size_t imagelen = 0; int c1, c2, c3, c4, type; int rc; @@ -118,7 +118,7 @@ _keybox_read_blob (KEYBOXBLOB *r_blob, FILE *fp) int _keybox_write_blob (KEYBOXBLOB blob, FILE *fp) { - const char *image; + const unsigned char *image; size_t length; image = _keybox_get_blob_image (blob, &length); diff --git a/scd/apdu.c b/scd/apdu.c index 212b9df24..975fffa24 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2393,7 +2393,7 @@ apdu_activate (int slot) unsigned char * apdu_get_atr (int slot, size_t *atrlen) { - char *buf; + unsigned char *buf; if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return NULL; diff --git a/scd/app-help.c b/scd/app-help.c index 1c3c52b15..27cbea5c7 100644 --- a/scd/app-help.c +++ b/scd/app-help.c @@ -48,7 +48,7 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip) n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) return gpg_error (GPG_ERR_INV_SEXP); - err = gcry_sexp_sscan (&s_pkey, NULL, p, n); + err = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n); xfree (p); if (err) return err; /* Can't parse that S-expression. */ diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 1ff096138..11e6eebaf 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -948,8 +948,8 @@ get_public_key (app_t app, int keyno) size_t buflen, keydatalen, mlen, elen; unsigned char *mbuf = NULL; unsigned char *ebuf = NULL; - unsigned char *keybuf = NULL; - unsigned char *keybuf_p; + char *keybuf = NULL; + char *keybuf_p; if (keyno < 1 || keyno > 3) return gpg_error (GPG_ERR_INV_ID); @@ -963,14 +963,16 @@ get_public_key (app_t app, int keyno) app->app_local->pk[keyno].key = NULL; app->app_local->pk[keyno].keylen = 0; + m = e = NULL; /* (avoid cc warning) */ + if (app->card_version > 0x0100) { /* We may simply read the public key out of these cards. */ - err = iso7816_read_public_key (app->slot, - keyno == 0? "\xB6" : - keyno == 1? "\xB8" : "\xA4", - 2, - &buffer, &buflen); + err = iso7816_read_public_key + (app->slot, (const unsigned char*)(keyno == 0? "\xB6" : + keyno == 1? "\xB8" : "\xA4"), + 2, + &buffer, &buflen); if (err) { log_error (_("reading public key failed: %s\n"), gpg_strerror (err)); @@ -1107,7 +1109,7 @@ get_public_key (app_t app, int keyno) strcpy (keybuf_p, ")))"); keybuf_p += strlen (keybuf_p); - app->app_local->pk[keyno].key = keybuf; + app->app_local->pk[keyno].key = (unsigned char*)keybuf; app->app_local->pk[keyno].keylen = (keybuf_p - keybuf); leave: @@ -1889,11 +1891,10 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, #warning key generation temporary replaced by reading an existing key. rc = iso7816_read_public_key #endif - (app->slot, - keyno == 0? "\xB6" : - keyno == 1? "\xB8" : "\xA4", - 2, - &buffer, &buflen); + (app->slot, (const unsigned char*)(keyno == 0? "\xB6" : + keyno == 1? "\xB8" : "\xA4"), + 2, + &buffer, &buflen); if (rc) { rc = gpg_error (GPG_ERR_CARD); diff --git a/scd/app-p15.c b/scd/app-p15.c index 831f0d1f4..f03e5d5f0 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -43,33 +43,35 @@ typedef enum } card_type_t; /* A list card types with ATRs noticed with these cards. */ +#define X(a) ((unsigned char const *)(a)) static struct { size_t atrlen; - unsigned char *atr; + unsigned char const *atr; card_type_t type; } card_atr_list[] = { - { 19, "\x3B\xBA\x13\x00\x81\x31\x86\x5D\x00\x64\x05\x0A\x02\x01\x31\x80" - "\x90\x00\x8B", + { 19, X("\x3B\xBA\x13\x00\x81\x31\x86\x5D\x00\x64\x05\x0A\x02\x01\x31\x80" + "\x90\x00\x8B"), CARD_TYPE_TCOS }, /* SLE44 */ - { 19, "\x3B\xBA\x14\x00\x81\x31\x86\x5D\x00\x64\x05\x14\x02\x02\x31\x80" - "\x90\x00\x91", + { 19, X("\x3B\xBA\x14\x00\x81\x31\x86\x5D\x00\x64\x05\x14\x02\x02\x31\x80" + "\x90\x00\x91"), CARD_TYPE_TCOS }, /* SLE66S */ - { 19, "\x3B\xBA\x96\x00\x81\x31\x86\x5D\x00\x64\x05\x60\x02\x03\x31\x80" - "\x90\x00\x66", + { 19, X("\x3B\xBA\x96\x00\x81\x31\x86\x5D\x00\x64\x05\x60\x02\x03\x31\x80" + "\x90\x00\x66"), CARD_TYPE_TCOS }, /* SLE66P */ - { 27, "\x3B\xFF\x94\x00\xFF\x80\xB1\xFE\x45\x1F\x03\x00\x68\xD2\x76\x00" - "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23", + { 27, X("\x3B\xFF\x94\x00\xFF\x80\xB1\xFE\x45\x1F\x03\x00\x68\xD2\x76\x00" + "\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23"), CARD_TYPE_MICARDO }, /* German BMI card */ - { 19, "\x3B\x6F\x00\xFF\x00\x68\xD2\x76\x00\x00\x28\xFF\x05\x1E\x31\x80" - "\x00\x90\x00", + { 19, X("\x3B\x6F\x00\xFF\x00\x68\xD2\x76\x00\x00\x28\xFF\x05\x1E\x31\x80" + "\x00\x90\x00"), CARD_TYPE_MICARDO }, /* German BMI card (ATR due to reader problem) */ - { 26, "\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49" - "\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43", + { 26, X("\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49" + "\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43"), CARD_TYPE_MICARDO }, /* EstEID (Estonian Big Brother card) */ { 0 } }; +#undef X /* The Pin Types as defined in pkcs#15 v1.1 */ diff --git a/scd/app.c b/scd/app.c index 2c8c915d7..f27b400b1 100644 --- a/scd/app.c +++ b/scd/app.c @@ -357,7 +357,7 @@ app_munge_serialno (app_t app) gpg_error_t app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp) { - unsigned char *buf, *p; + char *buf, *p; int i; if (!app || !serial) diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 9ac655e63..096a6811b 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -555,7 +555,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx, all in a 2 bute Unicode encoding using little endian. */ rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8), 0, - buf, sizeof buf, 1000 /* ms timeout */); + (char*)buf, sizeof buf, 1000 /* ms timeout */); if (rc < 4) langid = 0x0409; /* English. */ else @@ -563,7 +563,7 @@ get_escaped_usb_string (usb_dev_handle *idev, int idx, rc = usb_control_msg (idev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + idx, langid, - buf, sizeof buf, 1000 /* ms timeout */); + (char*)buf, sizeof buf, 1000 /* ms timeout */); if (rc < 2 || buf[1] != USB_DT_STRING) return NULL; /* Error or not a string. */ len = buf[0]; @@ -1155,7 +1155,7 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) rc = usb_bulk_write (handle->idev, handle->ep_bulk_out, - msg, msglen, + (char*)msg, msglen, 1000 /* ms timeout */); if (rc == msglen) return 0; @@ -1188,7 +1188,7 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, retry: rc = usb_bulk_read (handle->idev, handle->ep_bulk_in, - buffer, length, + (char*)buffer, length, timeout); if (rc < 0) { @@ -1300,7 +1300,7 @@ ccid_poll (ccid_driver_t handle) rc = usb_bulk_read (handle->idev, handle->ep_intr, - msg, sizeof msg, + (char*)msg, sizeof msg, 0 /* ms timeout */ ); if (rc < 0 && errno == ETIMEDOUT) return 0; @@ -1444,7 +1444,7 @@ ccid_get_atr (ccid_driver_t handle, { tried_iso = 1; /* Try switching to ISO mode. */ - if (!send_escape_cmd (handle, "\xF1\x01", 2)) + if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2)) goto again; } else if (CCID_COMMAND_FAILED (msg)) @@ -2026,7 +2026,7 @@ ccid_transceive_secure (ccid_driver_t handle, if (handle->id_vendor == VENDOR_SCM) { DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n"); - rc = send_escape_cmd (handle, "\x80\x02\x00", 3); + rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3); if (rc) return rc; } diff --git a/scd/command.c b/scd/command.c index a308078d3..52a86871e 100644 --- a/scd/command.c +++ b/scd/command.c @@ -679,7 +679,7 @@ pin_cb (void *opaque, const char *info, char **retstr) xfree (value); return gpg_error (GPG_ERR_INV_RESPONSE); } - *retstr = value; + *retstr = (char*)value; return 0; } @@ -844,7 +844,7 @@ cmd_getattr (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc; - char *keyword; + const char *keyword; if ((rc = open_card (ctrl, NULL))) return rc; @@ -860,7 +860,6 @@ cmd_getattr (assuan_context_t ctx, char *line) /* FIXME: Applications should not return sensistive data if the card is locked. */ rc = app_getattr (ctrl->app_ctx, ctrl, keyword); - xfree (keyword); TEST_CARD_REMOVAL (ctrl, rc); return map_to_assuan_status (rc); @@ -908,9 +907,10 @@ cmd_setattr (assuan_context_t ctx, char *orig_line) *line++ = 0; while (spacep (line)) line++; - nbytes = percent_plus_unescape (line); + nbytes = percent_plus_unescape ((unsigned char*)line); - rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, line, nbytes); + rc = app_setattr (ctrl->app_ctx, keyword, pin_cb, ctx, + (const unsigned char*)line, nbytes); xfree (linebuf); TEST_CARD_REMOVAL (ctrl, rc); diff --git a/scd/iso7816.c b/scd/iso7816.c index e9dc6541c..742ed9433 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -153,7 +153,7 @@ iso7816_select_file (int slot, int tag, int is_dir, p0 = (tag == 0x3F00)? 0: is_dir? 1:2; p1 = 0x0c; /* No FC return. */ sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, - p0, p1, 2, tagbuf ); + p0, p1, 2, (char*)tagbuf ); return map_sw (sw); } @@ -285,7 +285,7 @@ iso7816_put_data (int slot, int tag, sw = apdu_send_simple (slot, 0x00, CMD_PUT_DATA, ((tag >> 8) & 0xff), (tag & 0xff), - datalen, data); + datalen, (const char*)data); return map_sw (sw); } @@ -303,7 +303,7 @@ iso7816_manage_security_env (int slot, int p1, int p2, return gpg_error (GPG_ERR_INV_VALUE); sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, - data? datalen : -1, data); + data? datalen : -1, (const char*)data); return map_sw (sw); } @@ -323,7 +323,7 @@ iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, data, + sw = apdu_send (slot, 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { @@ -364,13 +364,15 @@ iso7816_decipher (int slot, const unsigned char *data, size_t datalen, *buf = padind; /* Padding indicator. */ memcpy (buf+1, data, datalen); - sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf, + sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, + datalen+1, (char*)buf, result, resultlen); xfree (buf); } else { - sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen, data, + sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, + datalen, (const char *)data, result, resultlen); } if (sw != SW_SUCCESS) @@ -399,7 +401,7 @@ iso7816_internal_authenticate (int slot, *resultlen = 0; sw = apdu_send (slot, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, - datalen, data, result, resultlen); + datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ @@ -426,7 +428,7 @@ do_generate_keypair (int slot, int readonly, *resultlen = 0; sw = apdu_send (slot, 0x00, CMD_GENERATE_KEYPAIR, readonly? 0x81:0x80, 0, - datalen, data, result, resultlen); + datalen, (const char*)data, result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c index 93e78fdfe..21af16fba 100644 --- a/scd/pcsc-wrapper.c +++ b/scd/pcsc-wrapper.c @@ -390,9 +390,9 @@ handle_open (unsigned char *argbuf, size_t arglen) unsigned char atr[33]; /* Make sure there is only the port string */ - if (arglen != strlen (argbuf)) + if (arglen != strlen ((char*)argbuf)) bad_request ("OPEN"); - portstr = argbuf; + portstr = (char*)argbuf; if (driver_is_open) { diff --git a/sm/ChangeLog b/sm/ChangeLog index ffb61a294..d9f295e1d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,35 @@ +2005-06-15 Werner Koch <wk@g10code.com> + + * delete.c (delete_one): Changed FPR to unsigned. + * encrypt.c (encrypt_dek): Made ENCVAL unsigned. + (gpgsm_encrypt): Ditto. + * sign.c (gpgsm_sign): Made SIGVAL unsigned. + * base64.c (base64_reader_cb): Need to use some casting to get + around signed/unsigned char* warnings. + * certcheck.c (gpgsm_check_cms_signature): Ditto. + (gpgsm_create_cms_signature): Changed arg R_SIGVAL to unsigned char*. + (do_encode_md): Made NFRAME a size_t. + * certdump.c (gpgsm_print_serial): Fixed signed/unsigned warning. + (gpgsm_dump_serial): Ditto. + (gpgsm_format_serial): Ditto. + (gpgsm_dump_string): Ditto. + (gpgsm_dump_cert): Ditto. + (parse_dn_part): Ditto. + (gpgsm_print_name2): Ditto. + * keylist.c (email_kludge): Ditto. + * certreqgen.c (proc_parameters, create_request): Ditto. + (create_request): Ditto. + * call-agent.c (gpgsm_agent_pksign): Made arg R_BUF unsigned. + (struct cipher_parm_s): Made CIPHERTEXT unsigned. + (struct genkey_parm_s): Ditto. + * server.c (strcpy_escaped_plus): Made arg S signed char*. + * fingerprint.c (gpgsm_get_fingerprint): Made ARRAY unsigned. + (gpgsm_get_keygrip): Ditto. + * keydb.c (keydb_insert_cert): Made DIGEST unsigned. + (keydb_update_cert): Ditto. + (classify_user_id): Apply cast to signed/unsigned assignment. + (hextobyte): Ditto. + 2005-06-01 Werner Koch <wk@g10code.com> * misc.c: Include setenv.h. diff --git a/sm/base64.c b/sm/base64.c index 4cc6ffa27..62c2c9ad9 100644 --- a/sm/base64.c +++ b/sm/base64.c @@ -95,7 +95,7 @@ struct base64_context_s { /* The base-64 character list */ -static unsigned char bintoasc[64] = +static char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; @@ -202,8 +202,9 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) { /* wait for the header line */ parm->linelen = parm->readpos = 0; - if (!parm->have_lf || strncmp (parm->line, "-----BEGIN ", 11) - || !strncmp (parm->line+11, "PGP ", 4)) + if (!parm->have_lf + || strncmp ((char*)parm->line, "-----BEGIN ", 11) + || !strncmp ((char*)parm->line+11, "PGP ", 4)) goto next; parm->is_pem = 1; } @@ -220,8 +221,9 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) /* the very first byte does pretty much look like a SEQUENCE tag*/ parm->is_pem = 0; } - else if ( parm->have_lf && !strncmp (parm->line, "-----BEGIN ", 11) - && strncmp (parm->line+11, "PGP ", 4) ) + else if ( parm->have_lf + && !strncmp ((char*)parm->line, "-----BEGIN ", 11) + && strncmp ((char *)parm->line+11, "PGP ", 4) ) { /* Fixme: we must only compare if the line really starts at the beginning */ @@ -268,7 +270,7 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) if (parm->is_pem || parm->is_base64) { if (parm->is_pem && parm->have_lf - && !strncmp (parm->line, "-----END ", 9)) + && !strncmp ((char*)parm->line, "-----END ", 9)) { parm->identified = 0; parm->linelen = parm->readpos = 0; diff --git a/sm/call-agent.c b/sm/call-agent.c index 885abf421..92a29928c 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -39,24 +39,27 @@ #include "../common/membuf.h" -static ASSUAN_CONTEXT agent_ctx = NULL; +static assuan_context_t agent_ctx = NULL; static int force_pipe_server = 0; -struct cipher_parm_s { - ASSUAN_CONTEXT ctx; - const char *ciphertext; +struct cipher_parm_s +{ + assuan_context_t ctx; + const unsigned char *ciphertext; size_t ciphertextlen; }; -struct genkey_parm_s { - ASSUAN_CONTEXT ctx; - const char *sexp; +struct genkey_parm_s +{ + assuan_context_t ctx; + const unsigned char *sexp; size_t sexplen; }; -struct learn_parm_s { +struct learn_parm_s +{ int error; - ASSUAN_CONTEXT ctx; + assuan_context_t ctx; membuf_t *data; }; @@ -204,7 +207,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length) int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc, unsigned char *digest, size_t digestlen, int digestalgo, - char **r_buf, size_t *r_buflen ) + unsigned char **r_buf, size_t *r_buflen ) { int rc, i; char *p, line[ASSUAN_LINELENGTH]; @@ -392,7 +395,7 @@ gpgsm_agent_genkey (ctrl_t ctrl, struct genkey_parm_s gk_parm; membuf_t data; size_t len; - char *buf; + unsigned char *buf; *r_pubkey = NULL; rc = start_agent (ctrl); diff --git a/sm/certcheck.c b/sm/certcheck.c index 611d3219c..84dfdb9ab 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -39,7 +39,8 @@ static int do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits, gcry_mpi_t *r_val) { - int n, nframe; + int n; + size_t nframe; unsigned char *frame; if (pkalgo == GCRY_PK_DSA) @@ -205,7 +206,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) log_printf ("\n"); } - rc = gcry_sexp_sscan ( &s_sig, NULL, p, n); + rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n); ksba_free (p); if (rc) { @@ -224,7 +225,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n); ksba_free (p); if (rc) { @@ -278,7 +279,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, log_error ("libksba did not return a proper S-Exp\n"); return gpg_error (GPG_ERR_BUG); } - rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n); + rc = gcry_sexp_sscan (&s_sig, NULL, (char*)sigval, n); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); @@ -297,7 +298,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, if (DBG_CRYPTO) log_printhex ("public key: ", p, n); - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n); ksba_free (p); if (rc) { @@ -333,7 +334,8 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, int gpgsm_create_cms_signature (ctrl_t ctrl, ksba_cert_t cert, - gcry_md_hd_t md, int mdalgo, char **r_sigval) + gcry_md_hd_t md, int mdalgo, + unsigned char **r_sigval) { int rc; char *grip, *desc; diff --git a/sm/certdump.c b/sm/certdump.c index 26510c70d..98f019c4a 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -50,8 +50,9 @@ struct dn_array_s { /* print the first element of an S-Expression */ void -gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p) +gpgsm_print_serial (FILE *fp, ksba_const_sexp_t sn) { + const char *p = (const char *)sn; unsigned long n; char *endp; @@ -77,8 +78,9 @@ gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p) /* Dump the serial number or any other simple S-expression. */ void -gpgsm_dump_serial (ksba_const_sexp_t p) +gpgsm_dump_serial (ksba_const_sexp_t sn) { + const char *p = (const char *)sn; unsigned long n; char *endp; @@ -103,8 +105,9 @@ gpgsm_dump_serial (ksba_const_sexp_t p) char * -gpgsm_format_serial (ksba_const_sexp_t p) +gpgsm_format_serial (ksba_const_sexp_t sn) { + const char *p = (const char *)sn; unsigned long n; char *endp; char *buffer; @@ -168,7 +171,7 @@ gpgsm_dump_string (const char *string) { const unsigned char *s; - for (s=string; *s; s++) + for (s=(const unsigned char*)string; *s; s++) { if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0)) break; @@ -190,7 +193,7 @@ void gpgsm_dump_cert (const char *text, ksba_cert_t cert) { ksba_sexp_t sexp; - unsigned char *p; + char *p; char *dn; ksba_isotime_t t; @@ -260,7 +263,7 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) }; const unsigned char *s, *s1; size_t n; - unsigned char *p; + char *p; int i; /* Parse attributeType */ @@ -306,7 +309,7 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) return NULL; for (s1=string; n; s1 += 2, n--, p++) { - *p = xtoi_2 (s1); + *(unsigned char *)p = xtoi_2 (s1); if (!*p) *p = 0x01; /* Better print a wrong value than truncating the string. */ @@ -351,7 +354,7 @@ parse_dn_part (struct dn_array_s *array, const unsigned char *string) s++; if (hexdigitp (s)) { - *p++ = xtoi_2 (s); + *(unsigned char *)p++ = xtoi_2 (s); s++; } else @@ -485,23 +488,22 @@ print_dn_parts (FILE *fp, struct dn_array_s *dn, int translate) void gpgsm_print_name2 (FILE *fp, const char *name, int translate) { - const unsigned char *s; + const unsigned char *s = (const unsigned char *)name; int i; - s = name; if (!s) { fputs (_("[Error - No name]"), fp); } else if (*s == '<') { - const unsigned char *s2 = strchr (s+1, '>'); + const char *s2 = strchr ( (char*)s+1, '>'); if (s2) { if (translate) - print_sanitized_utf8_buffer (fp, s + 1, s2 - s - 1, 0); + print_sanitized_utf8_buffer (fp, s + 1, s2 - (char*)s - 1, 0); else - print_sanitized_buffer (fp, s + 1, s2 - s - 1, 0); + print_sanitized_buffer (fp, s + 1, s2 - (char*)s - 1, 0); } } else if (*s == '(') diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 7b29a5b8d..2b920da7e 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -492,7 +492,7 @@ proc_parameters (ctrl_t ctrl, } sprintf (numbuf, "%u", nbits); - snprintf (keyparms, DIM (keyparms)-1, + snprintf ((char*)keyparms, DIM (keyparms)-1, "(6:genkey(3:rsa(5:nbits%d:%s)))", (int)strlen (numbuf), numbuf); rc = gpgsm_agent_genkey (ctrl, keyparms, &public); if (rc) @@ -627,8 +627,9 @@ create_request (ctrl_t ctrl, { gcry_sexp_t s_pkey; size_t n; - unsigned char grip[20], hexgrip[41]; - char *sigval; + unsigned char grip[20]; + char hexgrip[41]; + unsigned char *sigval; size_t siglen; n = gcry_sexp_canon_len (public, 0, NULL, NULL); @@ -638,7 +639,7 @@ create_request (ctrl_t ctrl, err = gpg_error (GPG_ERR_BUG); goto leave; } - rc = gcry_sexp_sscan (&s_pkey, NULL, public, n); + rc = gcry_sexp_sscan (&s_pkey, NULL, (const char*)public, n); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); diff --git a/sm/delete.c b/sm/delete.c index 11a0a5476..8e06b9489 100644 --- a/sm/delete.c +++ b/sm/delete.c @@ -67,7 +67,7 @@ delete_one (CTRL ctrl, const char *username) rc = keydb_get_cert (kh, &cert); if (!rc) { - char fpr[20]; + unsigned char fpr[20]; gpgsm_get_fingerprint (cert, 0, fpr, NULL); @@ -78,7 +78,7 @@ delete_one (CTRL ctrl, const char *username) else if (!rc) { ksba_cert_t cert2 = NULL; - char fpr2[20]; + unsigned char fpr2[20]; /* We ignore all duplicated certificates which might have been inserted due to program bugs. */ diff --git a/sm/encrypt.c b/sm/encrypt.c index 50da92c32..e4c0d5437 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -164,10 +164,10 @@ encode_session_key (DEK dek, gcry_sexp_t * r_data) } -/* encrypt the DEK under the key contained in CERT and return it as a - canonical S-Exp in encval */ +/* Encrypt the DEK under the key contained in CERT and return it as a + canonical S-Exp in encval. */ static int -encrypt_dek (const DEK dek, ksba_cert_t cert, char **encval) +encrypt_dek (const DEK dek, ksba_cert_t cert, unsigned char **encval) { gcry_sexp_t s_ciph, s_data, s_pkey; int rc; @@ -189,7 +189,7 @@ encrypt_dek (const DEK dek, ksba_cert_t cert, char **encval) log_error ("libksba did not return a proper S-Exp\n"); return gpg_error (GPG_ERR_BUG); } - rc = gcry_sexp_sscan (&s_pkey, NULL, buf, len); + rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)buf, len); xfree (buf); buf = NULL; if (rc) { @@ -220,7 +220,7 @@ encrypt_dek (const DEK dek, ksba_cert_t cert, char **encval) gcry_sexp_release (s_ciph); return tmperr; } - len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, buf, len); + len = gcry_sexp_sprint (s_ciph, GCRYSEXP_FMT_CANON, (char*)buf, len); assert (len); *encval = buf; @@ -437,7 +437,7 @@ gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int data_fd, FILE *out_fp) each and store them in the CMS object */ for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next) { - char *encval; + unsigned char *encval; rc = encrypt_dek (dek, cl->cert, &encval); if (rc) diff --git a/sm/fingerprint.c b/sm/fingerprint.c index 7fe619c18..9c3ab85db 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -42,8 +42,9 @@ If there is a problem , the function does never return NULL but a digest of all 0xff. */ -char * -gpgsm_get_fingerprint (ksba_cert_t cert, int algo, char *array, int *r_len) +unsigned char * +gpgsm_get_fingerprint (ksba_cert_t cert, int algo, + unsigned char *array, int *r_len) { gcry_md_hd_t md; int rc, len; @@ -140,8 +141,8 @@ gpgsm_get_short_fingerprint (ksba_cert_t cert) key parameters expressed as an canoncial encoded S-Exp. array must be 20 bytes long. returns the array or a newly allocated one if the passed one was NULL */ -char * -gpgsm_get_keygrip (ksba_cert_t cert, char *array) +unsigned char * +gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array) { gcry_sexp_t s_pkey; int rc; @@ -160,7 +161,7 @@ gpgsm_get_keygrip (ksba_cert_t cert, char *array) log_error ("libksba did not return a proper S-Exp\n"); return NULL; } - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n); + rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n); xfree (p); if (rc) { @@ -223,7 +224,7 @@ gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits) xfree (p); return 0; } - rc = gcry_sexp_sscan (&s_pkey, NULL, p, n); + rc = gcry_sexp_sscan (&s_pkey, NULL, (char *)p, n); xfree (p); if (rc) return 0; @@ -272,7 +273,7 @@ char * gpgsm_get_certid (ksba_cert_t cert) { ksba_sexp_t serial; - unsigned char *p; + char *p; char *endp; unsigned char hash[20]; unsigned long n; @@ -288,7 +289,7 @@ gpgsm_get_certid (ksba_cert_t cert) serial = ksba_cert_get_serial (cert); if (!serial) return NULL; /* oops: no serial number */ - p = serial; + p = (char *)serial; if (*p != '(') { log_error ("Ooops: invalid serial number\n"); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 1068e9d5e..2f3e83485 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -181,12 +181,12 @@ gpg_error_t gpgsm_status_with_err_code (ctrl_t ctrl, int no, const char *text, gpg_err_code_t ec); /*-- fingerprint --*/ -char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, - char *array, int *r_len); +unsigned char *gpgsm_get_fingerprint (ksba_cert_t cert, int algo, + unsigned char *array, int *r_len); char *gpgsm_get_fingerprint_string (ksba_cert_t cert, int algo); char *gpgsm_get_fingerprint_hexstring (ksba_cert_t cert, int algo); unsigned long gpgsm_get_short_fingerprint (ksba_cert_t cert); -char *gpgsm_get_keygrip (ksba_cert_t cert, char *array); +unsigned char *gpgsm_get_keygrip (ksba_cert_t cert, unsigned char *array); char *gpgsm_get_keygrip_hexstring (ksba_cert_t cert); int gpgsm_get_key_algo_info (ksba_cert_t cert, unsigned int *nbits); char *gpgsm_get_certid (ksba_cert_t cert); @@ -229,7 +229,7 @@ int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, /* fixme: move create functions to another file */ int gpgsm_create_cms_signature (ctrl_t ctrl, ksba_cert_t cert, gcry_md_hd_t md, int mdalgo, - char **r_sigval); + unsigned char **r_sigval); /*-- certchain.c --*/ @@ -293,7 +293,7 @@ int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc, unsigned char *digest, size_t digestlen, int digestalgo, - char **r_buf, size_t *r_buflen); + unsigned char **r_buf, size_t *r_buflen); int gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, ksba_const_sexp_t ciphertext, char **r_buf, size_t *r_buflen); diff --git a/sm/keydb.c b/sm/keydb.c index 293e5233d..17f04fe4b 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -681,7 +681,7 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert) { int rc = -1; int idx; - char digest[20]; + unsigned char digest[20]; if (!hd) return gpg_error (GPG_ERR_INV_VALUE); @@ -723,7 +723,7 @@ int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert) { int rc = 0; - char digest[20]; + unsigned char digest[20]; if (!hd) return gpg_error (GPG_ERR_INV_VALUE); @@ -1010,8 +1010,9 @@ keydb_search_subject (KEYDB_HANDLE hd, const char *name) static int -hextobyte (const unsigned char *s) +hextobyte (const char *string) { + const unsigned char *s = (const unsigned char *)string; int c; if( *s >= '0' && *s <= '9' ) @@ -1122,7 +1123,7 @@ classify_user_id (const char *name, if (!strchr("01234567890abcdefABCDEF", *si)) return 0; /* invalid digit in serial number*/ } - desc->sn = s; + desc->sn = (const unsigned char*)s; desc->snlen = -1; if (!*si) mode = KEYDB_SEARCH_MODE_SN; diff --git a/sm/keylist.c b/sm/keylist.c index 8e1233341..a0ac73fb3 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -256,7 +256,7 @@ print_time (gnupg_isotime_t t, FILE *fp) static char * email_kludge (const char *name) { - const unsigned char *p; + const char *p; unsigned char *buf; int n; @@ -278,7 +278,7 @@ email_kludge (const char *name) buf[n] = xtoi_2 (p); buf[n++] = '>'; buf[n] = 0; - return buf; + return (char*)buf; } diff --git a/sm/server.c b/sm/server.c index 7bfd3fc20..b3816d3d9 100644 --- a/sm/server.c +++ b/sm/server.c @@ -53,14 +53,14 @@ struct server_local_s { /* Note that it is sufficient to allocate the target string D as long as the source string S, i.e.: strlen(s)+1; */ static void -strcpy_escaped_plus (char *d, const unsigned char *s) +strcpy_escaped_plus (char *d, const char *s) { while (*s) { if (*s == '%' && s[1] && s[2]) { s++; - *d++ = xtoi_2 ( s); + *d++ = xtoi_2 (s); s += 2; } else if (*s == '+') diff --git a/sm/sign.c b/sm/sign.c index 5deef6088..3230a0e98 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -575,7 +575,7 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, ksba_cms_set_hash_function (cms, HASH_FNC, md); for (cl=signerlist,signer=0; cl; cl = cl->next, signer++) { - char *sigval = NULL; + unsigned char *sigval = NULL; char *buf, *fpr; if (signer) diff --git a/tools/ChangeLog b/tools/ChangeLog index 39f17e2ce..5965b2871 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2005-06-16 Werner Koch <wk@g10code.com> + + * gpg-connect-agent.c (read_and_print_response): Made LINELEN a + size_t. + 2005-06-04 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (main): Allow any number of arguments, don't use diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index bb05030ee..c9a324fa8 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -458,7 +458,7 @@ static int read_and_print_response (assuan_context_t ctx) { char *line; - int linelen; + size_t linelen; assuan_error_t rc; int i, j; diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index c49d1dcbb..e8d9ca27e 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -2316,7 +2316,7 @@ gc_component_change_options (int component, FILE *in) char *linep; unsigned long flags = 0; char *new_value = ""; - unsigned long new_value_nr; + unsigned long new_value_nr = 0; /* Strip newline and carriage return, if present. */ while (length > 0 diff --git a/tools/gpgkey2ssh.c b/tools/gpgkey2ssh.c index 75b18b29b..e874ab22e 100644 --- a/tools/gpgkey2ssh.c +++ b/tools/gpgkey2ssh.c @@ -249,6 +249,9 @@ main (int argc, char **argv) pkdbuf = NULL; pkdbuf_n = 0; + algorithm_id = 0; /* (avoid cc warning) */ + identifier = NULL; /* (avoid cc warning) */ + assert (argc == 2); keyid = argv[1]; diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index 25ca8c413..6cb570fbc 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -223,7 +223,7 @@ main (int argc, char **argv) int force = 0; struct sockaddr_un srvr_addr; - int addrlen; + socklen_t addrlen; int server; int flags; client_t client_list = NULL; -- cgit v1.2.3 From 96fdf4cf100db67a9ec283a7e50f2e94955819a1 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 20 Jun 2005 17:32:44 +0000 Subject: Preparing 1.9.17 --- ChangeLog | 4 + NEWS | 2 +- README | 41 ++---- configure.ac | 6 +- doc/scdaemon.texi | 30 ++++- po/de.po | 375 +++++++++++++++++++++++++++++++----------------------- 6 files changed, 257 insertions(+), 201 deletions(-) diff --git a/ChangeLog b/ChangeLog index f7efcee89..1a5b882f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-06-20 Werner Koch <wk@g10code.com> + + Released 1.9.17. + 2005-06-02 Werner Koch <wk@g10code.com> * configure.ac (HAVE_PTH): Define as alias for USE_GNU_PTH. It is diff --git a/NEWS b/NEWS index daa18c4c0..c7af4a625 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Noteworthy changes in version 1.9.17 +Noteworthy changes in version 1.9.17 (2005-06-20) ------------------------------------------------- * gpg-connect-agent has now features to handle Assuan INQUIRE diff --git a/README b/README index 7bb83f1f2..28637c1fb 100644 --- a/README +++ b/README @@ -3,16 +3,17 @@ Version 1.9.x -GnuPG 1.9 is the future version of GnuPG; it is based on the gnupg-1.3 +GnuPG 1.9 is the future version of GnuPG; it is based on some 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 +GnuPG 2.0 release. Note that GnuPG 1.4 and 1.9 are not always in sync +and thus features and bug fixes done in 1.4 are not necessary available in 1.9. You should use this GnuPG version if you want to use the gpg-agent or gpgsm (the S/MIME variant of gpg). Note that the gpg-agent is also -helpful when using the standard gpg versions (1.3.x as well as some of -the old 1.2.x). +helpful when using the standard gpg versions (1.4.x as well as some of +the old 1.2.x). There are no problems installing 1.4 and 1.9 +alongside; in act we suggest to do this. BUILD INSTRUCTIONS @@ -64,6 +65,9 @@ and options given below. See also the section `SMARTCARD INTRO'. COMMANDS ======== +See the info documentation ("info gnupg") for a full list of commands +and options. + gpgsm: ------ @@ -79,25 +83,6 @@ gpgsm: prepended before each block. -gpg2: (Note that these card commands are also available with gpg 1.3.x) ------ - ---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 ======= @@ -480,10 +465,8 @@ 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] - +(surprise!); see http://g10code.com/p-card.html and +http://www.gnupg.org/documentation/howtos.html#GnuPG-cardHOWTO . GPGSM, the CMS (S/MIME) part of GnuPG, supports two kinds of smartcards. The most flexible way is to use PKCS#15 compliant cards, @@ -512,8 +495,6 @@ 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] - diff --git a/configure.ac b/configure.ac index 17465c520..99eae9690 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac - for GnuPG 1.9 # Copyright (C) 1998, 1999, 2000, 2001, 2002, -# 2003, 2004 Free Software Foundation, Inc. +# 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.17-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.17, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -34,7 +34,7 @@ NEED_GPG_ERROR_VERSION=1.0 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.1.94 -NEED_LIBASSUAN_VERSION=0.6.9 +NEED_LIBASSUAN_VERSION=0.6.10 NEED_KSBA_VERSION=0.9.11 diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index d4a21b5ce..35dca4780 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -199,16 +199,36 @@ debugging. Append all logging output to @var{file}. This is very helpful in seeing what the agent actually does. -@item --reader-port @var{number} -This option may 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 --pcsc-driver @var{library} +@opindex pcsc-driver +Use @var{library} to access the smartcard reader. The current default +is @file{libpcsclite.so}. Instead of using this option you might also +want to install a symbolic link to the default file name +(e.g. from @file{libpcsclite.so.1}). @item --ctapi-driver @var{library} +@opindex ctapi-driver Use @var{library} to access the smartcard reader. The current default -is @code{libtowitoko.so}. Note that the use of this interface is +is @file{libtowitoko.so}. Note that the use of this interface is deprecated; it may be removed in future releases. +@item --disable-ccid +@opindex 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. + +@item --reader-port @var{number_or_string} +@opindex reader-port +This option may 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). PC/SC or CCID +readers might need a string here; run the program in verbose mode to get +a list of available readers. The default is then the first reader +found. + @item --allow-admin @itemx --deny-admin diff --git a/po/de.po b/po/de.po index da09719dd..5a79a1bd7 100644 --- a/po/de.po +++ b/po/de.po @@ -10,15 +10,15 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.16\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-04-21 15:21+0200\n" -"PO-Revision-Date: 2005-04-21 16:23+0200\n" +"POT-Creation-Date: 2005-06-16 09:12+0200\n" +"PO-Revision-Date: 2005-06-20 19:12+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=iso-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:107 agent/protect-tool.c:106 scd/scdaemon.c:98 +#: agent/gpg-agent.c:108 agent/protect-tool.c:108 scd/scdaemon.c:99 msgid "" "@Options:\n" " " @@ -26,51 +26,47 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:109 scd/scdaemon.c:100 +#: agent/gpg-agent.c:110 scd/scdaemon.c:101 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausfhren" -#: agent/gpg-agent.c:110 scd/scdaemon.c:101 +#: agent/gpg-agent.c:111 scd/scdaemon.c:104 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausfhren" -#: agent/gpg-agent.c:111 kbx/kbxutil.c:81 scd/scdaemon.c:102 sm/gpgsm.c:329 +#: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:105 sm/gpgsm.c:329 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausfhrlich" -#: agent/gpg-agent.c:112 kbx/kbxutil.c:82 scd/scdaemon.c:103 sm/gpgsm.c:330 +#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:106 sm/gpgsm.c:330 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" -#: agent/gpg-agent.c:113 scd/scdaemon.c:104 +#: agent/gpg-agent.c:114 scd/scdaemon.c:107 msgid "sh-style command output" msgstr "Ausgabe fr /bin/sh" -#: agent/gpg-agent.c:114 scd/scdaemon.c:105 +#: agent/gpg-agent.c:115 scd/scdaemon.c:108 msgid "csh-style command output" msgstr "Ausgabe fr /bin/csh" -#: agent/gpg-agent.c:115 +#: agent/gpg-agent.c:116 msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:120 scd/scdaemon.c:112 +#: agent/gpg-agent.c:121 scd/scdaemon.c:117 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:121 +#: agent/gpg-agent.c:122 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:122 scd/scdaemon.c:113 sm/gpgsm.c:332 +#: agent/gpg-agent.c:123 scd/scdaemon.c:118 sm/gpgsm.c:332 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:123 -msgid "do not allow multiple connections" -msgstr "Nicht mehr als eine Verbindung erlauben" - #: agent/gpg-agent.c:125 msgid "use a standard location for the socket" msgstr "Benutze einen Standardnamen fr den Socket" @@ -99,37 +95,41 @@ msgstr "Ignoriere Anfragen, das X-Display zu wechseln" msgid "|N|expire cached PINs after N seconds" msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" -#: agent/gpg-agent.c:147 +#: agent/gpg-agent.c:149 msgid "do not use the PIN cache when signing" msgstr "benutze PINs im Cache nicht bem Signieren" -#: agent/gpg-agent.c:149 +#: agent/gpg-agent.c:151 msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" -#: agent/gpg-agent.c:151 +#: agent/gpg-agent.c:153 msgid "allow presetting passphrase" msgstr "erlaube ein \"preset\" von Passphrases" -#: agent/gpg-agent.c:152 +#: agent/gpg-agent.c:154 msgid "enable ssh-agent emulation" msgstr "Die ssh-agent Emulation anschalten" -#: agent/gpg-agent.c:232 agent/protect-tool.c:139 scd/scdaemon.c:178 +#: agent/gpg-agent.c:156 +msgid "|FILE|write environment settings also to FILE" +msgstr "|DATEI|Schreibe die Umgebungsvariabeln auf DATEI" + +#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:183 #: sm/gpgsm.c:503 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:232 agent/protect-tool.c:139 scd/scdaemon.c:178 +#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:183 #: sm/gpgsm.c:503 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:235 +#: agent/gpg-agent.c:238 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" -#: agent/gpg-agent.c:237 +#: agent/gpg-agent.c:240 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -137,127 +137,132 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlssel fr GnuPG\n" -#: agent/gpg-agent.c:308 scd/scdaemon.c:252 sm/gpgsm.c:632 +#: agent/gpg-agent.c:311 scd/scdaemon.c:257 sm/gpgsm.c:632 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungltige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:498 agent/protect-tool.c:1061 kbx/kbxutil.c:431 -#: scd/scdaemon.c:367 sm/gpgsm.c:753 +#: agent/gpg-agent.c:482 agent/protect-tool.c:1072 kbx/kbxutil.c:431 +#: scd/scdaemon.c:349 sm/gpgsm.c:753 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:590 scd/scdaemon.c:442 sm/gpgsm.c:854 +#: agent/gpg-agent.c:574 scd/scdaemon.c:424 sm/gpgsm.c:854 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:595 agent/gpg-agent.c:1104 scd/scdaemon.c:447 +#: agent/gpg-agent.c:579 agent/gpg-agent.c:1085 scd/scdaemon.c:429 #: sm/gpgsm.c:858 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:603 scd/scdaemon.c:455 sm/gpgsm.c:865 +#: agent/gpg-agent.c:587 scd/scdaemon.c:437 sm/gpgsm.c:865 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:1154 agent/gpg-agent.c:1257 agent/gpg-agent.c:1261 -#: agent/gpg-agent.c:1297 agent/gpg-agent.c:1301 +#: agent/gpg-agent.c:879 +#, c-format +msgid "error creating `%s': %s\n" +msgstr "Fehler beim Erstellen von `%s': %s\n" + +#: agent/gpg-agent.c:1135 agent/gpg-agent.c:1238 agent/gpg-agent.c:1242 +#: agent/gpg-agent.c:1278 agent/gpg-agent.c:1282 scd/scdaemon.c:900 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstellt werden: %s\n" -#: agent/gpg-agent.c:1168 +#: agent/gpg-agent.c:1149 scd/scdaemon.c:914 msgid "name of socket too long\n" msgstr "Der Name des Sockets ist zu lang\n" -#: agent/gpg-agent.c:1194 +#: agent/gpg-agent.c:1175 scd/scdaemon.c:940 #, c-format msgid "can't create socket: %s\n" msgstr "Socket kann nicht erzeugt werden: %s\n" -#: agent/gpg-agent.c:1223 +#: agent/gpg-agent.c:1204 scd/scdaemon.c:969 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n" -#: agent/gpg-agent.c:1231 +#: agent/gpg-agent.c:1212 scd/scdaemon.c:977 #, c-format msgid "listen() failed: %s\n" msgstr "Der listen() Aufruf ist fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1237 +#: agent/gpg-agent.c:1218 scd/scdaemon.c:983 #, c-format msgid "listening on socket `%s'\n" msgstr "Es wird auf Socket `%s' gehrt\n" -#: agent/gpg-agent.c:1265 agent/gpg-agent.c:1307 +#: agent/gpg-agent.c:1246 agent/gpg-agent.c:1288 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/gpg-agent.c:1313 +#: agent/gpg-agent.c:1294 #, c-format msgid "stat() failed for `%s': %s\n" msgstr "stat() Aufruf fr `%s' fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1317 +#: agent/gpg-agent.c:1298 #, c-format msgid "can't use `%s' as home directory\n" msgstr "Die Datei `%s' kann nicht als Home-Verzeichniss benutzt werden\n" -#: agent/gpg-agent.c:1408 +#: agent/gpg-agent.c:1396 #, c-format -msgid "handler for fd %d started\n" -msgstr "Handhabungsroutine fr fd %d gestartet\n" +msgid "handler 0x%lx for fd %d started\n" +msgstr "Handhabungsroutine 0x%lx fr fd %d gestartet\n" -#: agent/gpg-agent.c:1417 +#: agent/gpg-agent.c:1406 #, c-format -msgid "handler for fd %d terminated\n" -msgstr "Handhabungsroutine fr den fd %d beendet\n" +msgid "handler 0x%lx for fd %d terminated\n" +msgstr "Handhabungsroutine 0x%lx fr den fd %d beendet\n" -#: agent/gpg-agent.c:1430 +#: agent/gpg-agent.c:1420 #, c-format -msgid "ssh handler for fd %d started\n" -msgstr "SSH Handhabungsroutine fr fd %d gestartet\n" +msgid "ssh handler 0x%lx for fd %d started\n" +msgstr "SSH Handhabungsroutine 0x%lx fr fd %d gestartet\n" -#: agent/gpg-agent.c:1436 +#: agent/gpg-agent.c:1427 #, c-format -msgid "ssh handler for fd %d terminated\n" -msgstr "SSH Handhabungsroutine fr fd %d beendet\n" +msgid "ssh handler 0x%lx for fd %d terminated\n" +msgstr "SSH Handhabungsroutine 0x%lx fr fd %d beendet\n" -#: agent/gpg-agent.c:1525 +#: agent/gpg-agent.c:1521 scd/scdaemon.c:1099 #, c-format msgid "pth_select failed: %s - waiting 1s\n" msgstr "pth_select() Aufruf fehlgeschlagen: %s - warte 1s\n" -#: agent/gpg-agent.c:1582 +#: agent/gpg-agent.c:1605 scd/scdaemon.c:1156 #, c-format msgid "%s %s stopped\n" msgstr "%s %s angehalten\n" -#: agent/gpg-agent.c:1604 +#: agent/gpg-agent.c:1626 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1614 common/simple-pwquery.c:323 sm/call-agent.c:140 +#: agent/gpg-agent.c:1636 common/simple-pwquery.c:323 sm/call-agent.c:143 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1626 common/simple-pwquery.c:335 sm/call-agent.c:152 +#: agent/gpg-agent.c:1648 common/simple-pwquery.c:335 sm/call-agent.c:155 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" -#: agent/protect-tool.c:142 +#: agent/protect-tool.c:145 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" -#: agent/protect-tool.c:144 +#: agent/protect-tool.c:147 msgid "" "Syntax: gpg-protect-tool [options] [args]]\n" "Secret key maintenance tool\n" @@ -265,16 +270,16 @@ msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" "Werkzeug zum Bearbeiten von geheimen Schlsseln\n" -#: agent/protect-tool.c:1193 +#: agent/protect-tool.c:1205 msgid "Please enter the passphrase to unprotect the PKCS#12 object." msgstr "Bitte geben Sie die Passphrase zum Entsperren des PKCS#12 Objekts ein" -#: agent/protect-tool.c:1196 +#: agent/protect-tool.c:1208 msgid "Please enter the passphrase to protect the new PKCS#12 object." msgstr "" "Bitte geben Sie die Passphrase zum Schützen des neuen PKCS#12 Objekts ein" -#: agent/protect-tool.c:1199 +#: agent/protect-tool.c:1211 msgid "" "Please enter the passphrase to protect the imported object within the GnuPG " "system." @@ -282,11 +287,11 @@ msgstr "" "Bitte geben Sie die Passphrase ein, um das importierte Objket im GnuPG " "System zu schützen." -#: agent/protect-tool.c:1202 agent/genkey.c:110 agent/genkey.c:218 +#: agent/protect-tool.c:1214 agent/genkey.c:110 agent/genkey.c:218 msgid "Please re-enter this passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" -#: agent/protect-tool.c:1204 +#: agent/protect-tool.c:1216 msgid "" "Please enter the passphrase or the PIN\n" "needed to complete this operation." @@ -294,24 +299,36 @@ msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" "wird bentigt um diese Aktion auszufhren." -#: agent/protect-tool.c:1208 agent/genkey.c:131 agent/genkey.c:238 +#: agent/protect-tool.c:1220 agent/genkey.c:131 agent/genkey.c:238 msgid "does not match - try again" msgstr "Keine bereinstimmung - bitte nochmal versuchen" -#: agent/protect-tool.c:1209 +#: agent/protect-tool.c:1221 msgid "Passphrase:" msgstr "Passphrase:" -#: agent/protect-tool.c:1222 +#: agent/protect-tool.c:1234 #, c-format msgid "error while asking for the passphrase: %s\n" msgstr "Fehler bei der Abfrage der Passphrase: %s\n" -#: agent/protect-tool.c:1225 +#: agent/protect-tool.c:1237 msgid "cancelled\n" msgstr "Vom Benutzer abgebrochen\n" -#: agent/divert-scd.c:200 +#: agent/divert-scd.c:216 +msgid "Admin PIN" +msgstr "Admin PIN" + +#: agent/divert-scd.c:257 +msgid "Repeat this PIN" +msgstr "PIN bitte wiederholen" + +#: agent/divert-scd.c:260 +msgid "PIN not correctly repeated; try again" +msgstr "PIN wurde nicht korrekt eingegeben; nochmal versuchen" + +#: agent/divert-scd.c:272 #, c-format msgid "Please enter the PIN%s%s%s to unlock the card" msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" @@ -326,12 +343,12 @@ msgstr "" msgid "Please enter the new passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: agent/query.c:145 +#: agent/query.c:169 #, c-format msgid "failed to acquire the pinentry lock: %s\n" msgstr "Die Sperre für das Pinentry kann nicht gesetzt werden: %s\n" -#: agent/query.c:307 +#: agent/query.c:332 msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" @@ -339,7 +356,7 @@ msgstr "" "Bitte geben Sie Ihre PIN ein, so da der geheime Schlssel benutzt werden " "kann" -#: agent/query.c:310 +#: agent/query.c:335 msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" @@ -347,31 +364,31 @@ msgstr "" "Bitte geben Sie Ihr Mantra (Passphrase) ein, so da der geheime Schlssel " "benutzt werden kann" -#: agent/query.c:365 agent/query.c:377 +#: agent/query.c:393 agent/query.c:405 msgid "PIN too long" msgstr "Die PIN ist zu lang" -#: agent/query.c:366 +#: agent/query.c:394 msgid "Passphrase too long" msgstr "Das Matra (Passphrase) ist zu lang" -#: agent/query.c:374 +#: agent/query.c:402 msgid "Invalid characters in PIN" msgstr "Ungltige Zeichen in der PIN" -#: agent/query.c:379 +#: agent/query.c:407 msgid "PIN too short" msgstr "Die PIN ist zu kurz" -#: agent/query.c:391 +#: agent/query.c:419 msgid "Bad PIN" msgstr "Falsche PIN" -#: agent/query.c:392 +#: agent/query.c:420 msgid "Bad Passphrase" msgstr "Falsches Mantra (Passphrase)" -#: agent/query.c:431 +#: agent/query.c:460 msgid "Passphrase" msgstr "Mantra" @@ -467,7 +484,7 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:609 +#: jnlib/logging.c:610 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" @@ -522,43 +539,39 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:106 sm/gpgsm.c:349 +#: scd/scdaemon.c:103 +msgid "run in multi server mode (foreground)" +msgstr "Im Multiserver Modus ausfhren" + +#: scd/scdaemon.c:109 sm/gpgsm.c:349 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" -#: scd/scdaemon.c:111 -msgid "|N|set OpenSC debug level to N" -msgstr "|N|Den OpenSC Debugstufe auf N setzen" - -#: scd/scdaemon.c:114 +#: scd/scdaemon.c:119 msgid "|N|connect to reader at port N" msgstr "|N|Verbinde mit dem Leser auf Port N" -#: scd/scdaemon.c:115 +#: scd/scdaemon.c:120 msgid "|NAME|use NAME as ct-API driver" msgstr "|NAME|Benutze NAME als CT-API Treiber" -#: scd/scdaemon.c:116 +#: scd/scdaemon.c:121 msgid "|NAME|use NAME as PC/SC driver" msgstr "|NAME|Benutze NAME als PC/SC Treiber" -#: scd/scdaemon.c:119 +#: scd/scdaemon.c:124 msgid "do not use the internal CCID driver" msgstr "Den internen CCID Treiber nicht benutzen" -#: scd/scdaemon.c:126 -msgid "do not use the OpenSC layer" -msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" - -#: scd/scdaemon.c:131 +#: scd/scdaemon.c:129 msgid "allow the use of admin card commands" msgstr "Erlaube die Benutzung von \"Admin\" Kommandos" -#: scd/scdaemon.c:181 +#: scd/scdaemon.c:186 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" -#: scd/scdaemon.c:183 +#: scd/scdaemon.c:188 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" @@ -566,12 +579,22 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon fr GnuPG\n" -#: scd/scdaemon.c:635 +#: scd/scdaemon.c:656 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszufhren\n" +#: scd/scdaemon.c:997 +#, c-format +msgid "handler for fd %d started\n" +msgstr "Handhabungsroutine fr fd %d gestartet\n" + +#: scd/scdaemon.c:1002 +#, c-format +msgid "handler for fd %d terminated\n" +msgstr "Handhabungsroutine fr den fd %d beendet\n" + #: scd/app-openpgp.c:595 #, c-format msgid "failed to store the fingerprint: %s\n" @@ -582,52 +605,52 @@ msgstr "Der Fingerprint kann nicht gespeichert werden: %s\n" msgid "failed to store the creation date: %s\n" msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:976 +#: scd/app-openpgp.c:978 #, c-format msgid "reading public key failed: %s\n" msgstr "Fehler beim Lesen des ffentlichen Schlssels: %s\n" -#: scd/app-openpgp.c:984 scd/app-openpgp.c:1621 scd/app-openpgp.c:2411 +#: scd/app-openpgp.c:986 scd/app-openpgp.c:1910 msgid "response does not contain the public key data\n" msgstr "Die Antwort enthlt keine Public Key Daten\n" -#: scd/app-openpgp.c:992 scd/app-openpgp.c:1629 scd/app-openpgp.c:2419 +#: scd/app-openpgp.c:994 scd/app-openpgp.c:1918 msgid "response does not contain the RSA modulus\n" msgstr "Die Antwort enthlt keinen RSA Modulus\n" -#: scd/app-openpgp.c:1001 scd/app-openpgp.c:1639 scd/app-openpgp.c:2430 +#: scd/app-openpgp.c:1003 scd/app-openpgp.c:1928 msgid "response does not contain the RSA public exponent\n" msgstr "Die Antwort enthlt keinen ffenlichen RSA Exponent\n" -#: scd/app-openpgp.c:1253 scd/app-openpgp.c:1341 scd/app-openpgp.c:1861 +#: scd/app-openpgp.c:1259 scd/app-openpgp.c:1347 scd/app-openpgp.c:2150 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:1259 scd/app-openpgp.c:1347 scd/app-openpgp.c:1867 +#: scd/app-openpgp.c:1265 scd/app-openpgp.c:1353 scd/app-openpgp.c:2156 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" msgstr "Die PIN fr den CHV%d ist zu kurz; Mindestlnge ist %d\n" -#: scd/app-openpgp.c:1268 scd/app-openpgp.c:1282 scd/app-openpgp.c:1357 -#: scd/app-openpgp.c:1876 scd/app-openpgp.c:1890 +#: scd/app-openpgp.c:1274 scd/app-openpgp.c:1288 scd/app-openpgp.c:1363 +#: scd/app-openpgp.c:2165 scd/app-openpgp.c:2179 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:1305 +#: scd/app-openpgp.c:1311 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:1320 scd/app-openpgp.c:2096 +#: scd/app-openpgp.c:1326 scd/app-openpgp.c:2385 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:1326 scd/app-openpgp.c:2105 +#: scd/app-openpgp.c:1332 scd/app-openpgp.c:2394 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:1331 +#: scd/app-openpgp.c:1337 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" @@ -636,109 +659,119 @@ msgstr "" #. TRANSLATORS: Do not translate the "|A|" prefix but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1338 +#: scd/app-openpgp.c:1344 msgid "|A|Admin PIN" msgstr "|A|Admin PIN" #. TRANSLATORS: Do not translate the "|*|" prefixes but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1487 +#: scd/app-openpgp.c:1493 msgid "|AN|New Admin PIN" msgstr "|AN|Neue Admin PIN" -#: scd/app-openpgp.c:1487 +#: scd/app-openpgp.c:1493 msgid "|N|New PIN" msgstr "|N|Neue PIN" -#: scd/app-openpgp.c:1491 +#: scd/app-openpgp.c:1497 #, c-format msgid "error getting new PIN: %s\n" msgstr "Fehler beim Holen der neuen PIN: %s\n" -#: scd/app-openpgp.c:1564 scd/app-openpgp.c:1707 +#: scd/app-openpgp.c:1547 scd/app-openpgp.c:1996 msgid "error reading application data\n" msgstr "Fehler beim Lesen der Anwendungsdaten\n" -#: scd/app-openpgp.c:1571 scd/app-openpgp.c:1714 +#: scd/app-openpgp.c:1553 scd/app-openpgp.c:2003 msgid "error reading fingerprint DO\n" msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" -#: scd/app-openpgp.c:1580 +#: scd/app-openpgp.c:1563 msgid "key already exists\n" msgstr "Schlssel existiert bereits\n" -#: scd/app-openpgp.c:1584 +#: scd/app-openpgp.c:1567 msgid "existing key will be replaced\n" msgstr "Existierender Schlssel wird ersetzt\n" -#: scd/app-openpgp.c:1586 +#: scd/app-openpgp.c:1569 msgid "generating new key\n" msgstr "Neuer Schlssel wird erzeugt\n" -#: scd/app-openpgp.c:1597 +#: scd/app-openpgp.c:1736 +msgid "creation timestamp missing\n" +msgstr "Erzeugungsdatum fehlt\n" + +#: scd/app-openpgp.c:1743 +#, c-format +msgid "RSA modulus missing or not of size %d bits\n" +msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n" + +#: scd/app-openpgp.c:1750 +#, c-format +msgid "RSA public exponent missing or larger than %d bits\n" +msgstr "Der ffentliche RSA Exponent fehlt oder ist lnger als %d Bits\n" + +#: scd/app-openpgp.c:1758 scd/app-openpgp.c:1765 +#, c-format +msgid "RSA prime %s missing or not of size %d bits\n" +msgstr "Die RSA Primzahl %s fehlt oder ist nicht %d Bits lang\n" + +#: scd/app-openpgp.c:1828 +#, c-format +msgid "failed to store the key: %s\n" +msgstr "Fehler beim Speichern des Schlssels: %s\n" + +#: scd/app-openpgp.c:1887 msgid "please wait while key is being generated ...\n" msgstr "Bitte warten bis der Schlssel erzeugt wurde ...\n" -#: scd/app-openpgp.c:1612 +#: scd/app-openpgp.c:1901 msgid "generating key failed\n" msgstr "Fehler beim Erzeugen des Schlssels\n" -#: scd/app-openpgp.c:1615 +#: scd/app-openpgp.c:1904 #, c-format msgid "key generation completed (%d seconds)\n" msgstr "Schlsselerzeugung vollendet (%d Sekunden)\n" -#: scd/app-openpgp.c:1672 +#: scd/app-openpgp.c:1961 msgid "invalid structure of OpenPGP card (DO 0x93)\n" msgstr "Ungltige Struktur der OpenPGP Karte (DO 0x93)\n" -#: scd/app-openpgp.c:1841 +#: scd/app-openpgp.c:2130 #, c-format msgid "signatures created so far: %lu\n" msgstr "Anzahl bereits erzeugter Signaturen: %lu\n" -#: scd/app-openpgp.c:1849 +#: scd/app-openpgp.c:2138 #, c-format -msgid "PIN [sigs done: %lu]" -msgstr "PIN [erzeugte signaturen: %lu]" +msgid "||Please enter the PIN%%0A[sigs done: %lu]" +msgstr "||Bitte geben Sie die PIN ein%%0A[Sigs bisher: %lu]" -#: scd/app-openpgp.c:2110 +#: scd/app-openpgp.c:2399 msgid "" "verification of Admin PIN is currently prohibited through this command\n" msgstr "" "Die berprfung der Admin PIN is momentan durch ein Kommando verboten " "worden\n" -#: scd/app-openpgp.c:2181 scd/app-openpgp.c:2191 +#: scd/app-openpgp.c:2470 scd/app-openpgp.c:2480 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht mglich - ungltige OpenPGP Karte?\n" -#: scd/app-openpgp.c:2262 -#, c-format -msgid "error getting serial number: %s\n" -msgstr "Fehler beim Holen der Seriennummer: %s\n" - -#: scd/app-openpgp.c:2362 -#, c-format -msgid "failed to store the key: %s\n" -msgstr "Fehler beim Speichern des Schlssels: %s\n" - -#: scd/app-openpgp.c:2404 -msgid "reading the key failed\n" -msgstr "Fehler beim Lesen des Schlssels: %s\n" - -#: sm/base64.c:315 +#: sm/base64.c:317 #, c-format msgid "invalid radix64 character %02x skipped\n" msgstr "Ungltiges Basis-64 Zeichen %02X wurde bergangen\n" -#: sm/call-agent.c:98 +#: sm/call-agent.c:101 msgid "no running gpg-agent - starting one\n" msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" -#: sm/call-agent.c:163 +#: sm/call-agent.c:166 msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" @@ -761,31 +794,31 @@ msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " "versucht\n" -#: sm/certdump.c:59 sm/certdump.c:143 +#: sm/certdump.c:60 sm/certdump.c:146 msgid "none" msgstr "keine" -#: sm/certdump.c:152 +#: sm/certdump.c:155 msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:494 +#: sm/certdump.c:496 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:508 +#: sm/certdump.c:510 msgid "[Error - unknown encoding]" msgstr "[Fehler - Unbekannte Kodierung]" -#: sm/certdump.c:512 +#: sm/certdump.c:514 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungltige Kodierung]" -#: sm/certdump.c:517 +#: sm/certdump.c:519 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungltiger DN]" -#: sm/certdump.c:678 +#: sm/certdump.c:680 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -978,7 +1011,7 @@ msgstr "(dies is wahrscheinlich keine verschl msgid "certificate `%s' not found: %s\n" msgstr "Zertifikat `%s' nicht gefunden: %s\n" -#: sm/delete.c:112 sm/keydb.c:1401 sm/keydb.c:1494 +#: sm/delete.c:112 sm/keydb.c:1402 sm/keydb.c:1495 #, c-format msgid "error locking keybox: %s\n" msgstr "Fehler beim Sperren der Keybox: %s\n" @@ -1421,40 +1454,40 @@ msgstr "Die \"Keybox\" `%s' wurde erstellt\n" msgid "can't create lock for `%s'\n" msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: sm/keydb.c:1325 sm/keydb.c:1387 +#: sm/keydb.c:1326 sm/keydb.c:1388 msgid "failed to get the fingerprint\n" msgstr "Kann den Fingerprint nicht ermitteln\n" -#: sm/keydb.c:1332 sm/keydb.c:1394 +#: sm/keydb.c:1333 sm/keydb.c:1395 msgid "failed to allocate keyDB handle\n" msgstr "Kann keinen KeyDB Handler bereitstellen\n" -#: sm/keydb.c:1349 +#: sm/keydb.c:1350 #, c-format msgid "problem looking for existing certificate: %s\n" msgstr "Problem bei der Suche nach vorhandenem Zertifikat: %s\n" -#: sm/keydb.c:1357 +#: sm/keydb.c:1358 #, c-format msgid "error finding writable keyDB: %s\n" msgstr "Fehler bei der Suche nach einer schreibbaren KeyDB: %s\n" -#: sm/keydb.c:1365 +#: sm/keydb.c:1366 #, c-format msgid "error storing certificate: %s\n" msgstr "Fehler beim Speichern des Zertifikats: %s\n" -#: sm/keydb.c:1409 +#: sm/keydb.c:1410 #, c-format msgid "problem re-searching certificate: %s\n" msgstr "Problem bei Wiederfinden des Zertifikats: %s\n" -#: sm/keydb.c:1418 sm/keydb.c:1506 +#: sm/keydb.c:1419 sm/keydb.c:1507 #, c-format msgid "error getting stored flags: %s\n" msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" -#: sm/keydb.c:1427 sm/keydb.c:1517 +#: sm/keydb.c:1428 sm/keydb.c:1518 #, c-format msgid "error storing flags: %s\n" msgstr "Fehler beim Speichern der Flags: %s\n" @@ -1580,6 +1613,24 @@ msgstr "Konfiguration der zu nutzenden LDAP-Server" msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" +#~ msgid "do not allow multiple connections" +#~ msgstr "Nicht mehr als eine Verbindung erlauben" + +#~ msgid "|N|set OpenSC debug level to N" +#~ msgstr "|N|Den OpenSC Debugstufe auf N setzen" + +#~ msgid "do not use the OpenSC layer" +#~ msgstr "Den OpenSC basierten Kartenzugriff nicht nutzen" + +#~ msgid "PIN [sigs done: %lu]" +#~ msgstr "PIN [erzeugte signaturen: %lu]" + +#~ msgid "error getting serial number: %s\n" +#~ msgstr "Fehler beim Holen der Seriennummer: %s\n" + +#~ msgid "reading the key failed\n" +#~ msgstr "Fehler beim Lesen des Schlssels: %s\n" + #~ msgid "error creating a pipe: %s\n" #~ msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" -- cgit v1.2.3 From 717eb552c12afbb8e2c595ca13163f11a893a2c5 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 20 Jun 2005 17:52:13 +0000 Subject: post release version number update --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c7af4a625..a1e77db0c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.18 +------------------------------------------------- + + Noteworthy changes in version 1.9.17 (2005-06-20) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 99eae9690..fa686d0cb 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.17, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.18-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From f1ce96e40435b7d7d12855de76d8956b807ccb3d Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 29 Jun 2005 14:12:18 +0000 Subject: (data_sign): Removed empty statement. --- agent/ChangeLog | 9 ++++ agent/Makefile.am | 15 ++++++ agent/command-ssh.c | 2 +- agent/minip12.c | 12 +++-- agent/t-protect.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 agent/t-protect.c diff --git a/agent/ChangeLog b/agent/ChangeLog index 055dbe53e..4d539d485 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,12 @@ +2005-06-29 Werner Koch <wk@g10code.com> + + * command-ssh.c (data_sign): Removed empty statement. + +2005-06-21 Werner Koch <wk@g10code.com> + + * minip12.c (create_final): Cast size_t to ulong for printf. + (build_key_bag, build_cert_bag, build_cert_sequence): Ditto. + 2005-06-16 Werner Koch <wk@g10code.com> * protect-tool.c (make_advanced): Makde RESULT a plain char. diff --git a/agent/Makefile.am b/agent/Makefile.am index 017b84795..c1a7c820e 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -20,6 +20,7 @@ bin_PROGRAMS = gpg-agent libexec_PROGRAMS = gpg-protect-tool gpg-preset-passphrase +noinst_PROGRAMS = $(TESTS) AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common -I$(top_srcdir)/intl @@ -70,3 +71,17 @@ if HAVE_W32_SYSTEM gpg_preset_passphrase_LDADD += -lwsock32 endif +# +# Module tests +# +TESTS = t-protect + +t_common_ldadd = ../jnlib/libjnlib.a ../common/libcommon.a \ + $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ + +t_protect_SOURCES = t-protect.c protect.c +t_protect_LDADD = $(t_common_ldadd) + + + + diff --git a/agent/command-ssh.c b/agent/command-ssh.c index a43fee24f..642bcbbba 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1988,7 +1988,7 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, gcry_sexp_t valuelist = NULL; gcry_sexp_t sublist = NULL; gcry_mpi_t sig_value = NULL; - unsigned char *sig_blob = NULL;; + unsigned char *sig_blob = NULL; size_t sig_blob_n = 0; char *identifier = NULL; const char *identifier_raw; diff --git a/agent/minip12.c b/agent/minip12.c index 31be15373..030043962 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -1085,7 +1085,8 @@ create_final (struct buffer_s *sequences, size_t *r_length) /* Ready. */ resultlen = p - result; if (needed != resultlen) - log_debug ("length mismatch: %u, %u\n", needed, resultlen); + log_debug ("length mismatch: %lu, %lu\n", + (unsigned long)needed, (unsigned long)resultlen); *r_length = resultlen; return result; @@ -1339,7 +1340,8 @@ build_key_bag (unsigned char *buffer, size_t buflen, char *salt, keybaglen = p - keybag; if (needed != keybaglen) - log_debug ("length mismatch: %u, %u\n", needed, keybaglen); + log_debug ("length mismatch: %lu, %lu\n", + (unsigned long)needed, (unsigned long)keybaglen); *r_length = keybaglen; return keybag; @@ -1437,7 +1439,8 @@ build_cert_bag (unsigned char *buffer, size_t buflen, char *salt, certbaglen = p - certbag; if (needed != certbaglen) - log_debug ("length mismatch: %u, %u\n", needed, certbaglen); + log_debug ("length mismatch: %lu, %lu\n", + (unsigned long)needed, (unsigned long)certbaglen); *r_length = certbaglen; return certbag; @@ -1527,7 +1530,8 @@ build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) certseqlen = p - certseq; if (needed != certseqlen) - log_debug ("length mismatch: %u, %u\n", needed, certseqlen); + log_debug ("length mismatch: %lu, %lu\n", + (unsigned long)needed, (unsigned long)certseqlen); /* Append some pad characters; we already allocated extra space. */ n = 8 - certseqlen % 8; diff --git a/agent/t-protect.c b/agent/t-protect.c new file mode 100644 index 000000000..0cb8265ba --- /dev/null +++ b/agent/t-protect.c @@ -0,0 +1,142 @@ +/* t-protect.c - Module tests for protect.c + * Copyright (C) 2005 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 <assert.h> + +#include "agent.h" + + +#define pass() do { ; } while(0) +#define fail() do { fprintf (stderr, "%s:%d: test failed\n",\ + __FILE__,__LINE__); \ + exit (1); \ + } while(0) + + +static void +test_agent_protect (void) +{ + /* Protect the key encoded in canonical format in PLAINKEY. We assume + a valid S-Exp here. */ +/* int agent_protect (const unsigned char *plainkey, const char *passphrase, */ +/* unsigned char **result, size_t *resultlen); */ +} + + +static void +test_agent_unprotect (void) +{ + /* Unprotect the key encoded in canonical format. We assume a valid + S-Exp here. */ +/* int */ +/* agent_unprotect (const unsigned char *protectedkey, const char *passphrase, */ +/* unsigned char **result, size_t *resultlen) */ +} + + +static void +test_agent_private_key_type (void) +{ +/* Check the type of the private key, this is one of the constants: + PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the + value 0), PRIVATE_KEY_CLEAR for an unprotected private key. + PRIVATE_KEY_PROTECTED for an protected private key or + PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored + elsewhere. */ +/* int */ +/* agent_private_key_type (const unsigned char *privatekey) */ +} + + +static void +test_make_shadow_info (void) +{ + static struct + { + const char *snstr; + const char *idstr; + const char *expected; + } data[] = { + { "", "", NULL }, + + }; + int i; + unsigned char *result; + + for (i=0; i < DIM(data); i++) + { + result = make_shadow_info (data[i].snstr, data[i].idstr); + if (!result && !data[i].expected) + pass (); + else if (!result && data[i].expected) + fail (); + else if (!data[i].expected) + fail (); + /* fixme: Need to compare the result but also need to check + proper S-expression syntax. */ + } +} + + + +static void +test_agent_shadow_key (void) +{ +/* Create a shadow key from a public key. We use the shadow protocol + "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting + S-expression is returned in an allocated buffer RESULT will point + to. The input parameters are expected to be valid canonicalized + S-expressions */ +/* int */ +/* agent_shadow_key (const unsigned char *pubkey, */ +/* const unsigned char *shadow_info, */ +/* unsigned char **result) */ +} + + +static void +test_agent_get_shadow_info (void) +{ +/* Parse a canonical encoded shadowed key and return a pointer to the + inner list with the shadow_info */ +/* int */ +/* agent_get_shadow_info (const unsigned char *shadowkey, */ +/* unsigned char const **shadow_info) */ +} + + + + +int +main (int argc, char **argv) +{ + test_agent_protect (); + test_agent_unprotect (); + test_agent_private_key_type (); + test_make_shadow_info (); + test_agent_shadow_key (); + test_agent_get_shadow_info (); + + return 0; +} -- cgit v1.2.3 From 51a164e75270b7e3bdf36b3ffab023592df15fc9 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 4 Jul 2005 04:55:48 +0000 Subject: 2005-07-04 Marcus Brinkmann <marcus@g10code.de> * simple-pwquery.h (simple_pwclear): New prototype. * simple-pwquery.c (simple_pwclear): New function. --- common/ChangeLog | 5 +++++ common/simple-pwquery.c | 24 +++++++++++++++++++++++- common/simple-pwquery.h | 3 +++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index e7905ea58..0ab9ac524 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2005-07-04 Marcus Brinkmann <marcus@g10code.de> + + * simple-pwquery.h (simple_pwclear): New prototype. + * simple-pwquery.c (simple_pwclear): New function. + 2005-06-15 Werner Koch <wk@g10code.com> * miscellaneous.c (make_printable_string): Made P a void*. diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index de3689810..f156ca3f1 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -546,6 +546,28 @@ simple_pwquery (const char *cacheid, } +/* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID. */ +int +simple_pwclear (const char *cacheid) +{ + char line[500]; + char *p; + + /* We need not more than 50 characters for the command and the + terminating nul. */ + if (strlen (cacheid) * 3 > sizeof (line) - 50) + return SPWQ_PROTOCOL_ERROR; + + strcpy (line, "CLEAR_PASSPHRASE "); + p = line + 17; + p = copy_and_escape (p, cacheid); + *p++ = '\n'; + *p++ = '\0'; + + return simple_query (line); +} + + /* Perform the simple query QUERY (which must be new-line and 0 terminated) and return the error code. */ int @@ -576,7 +598,7 @@ simple_query (const char *query) rc = SPWQ_PROTOCOL_ERROR; goto leave; } - + if (response[0] == 'O' && response[1] == 'K') /* OK, do nothing. */; else if ((nread > 7 && !memcmp (response, "ERR 111", 7) diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h index c7ebf9401..e3270d6c5 100644 --- a/common/simple-pwquery.h +++ b/common/simple-pwquery.h @@ -57,6 +57,9 @@ char *simple_pwquery (const char *cacheid, const char *description, int *errorcode); +/* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID. */ +int simple_pwclear (const char *cacheid); + /* Perform the simple query QUERY (which must be new-line and 0 terminated) and return the error code. */ int simple_query (const char *query); -- cgit v1.2.3 From 53a1347fbebb40a7e37a2751f1d55913dac5d3a2 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 4 Jul 2005 04:58:04 +0000 Subject: 2005-07-04 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (SYMC_BAD_PASSPHRASE, SYMC_CANCELED): New symbols, use instead constants. (hash_string): New function copied from simple-gettext.c. (confucius_get_pass): Take new argument CACHEID. (confucius_process): Calculate cacheid and pass it to confucius_get_pass. Clear passphrase from cache if necessary. --- tools/ChangeLog | 9 +++++++ tools/symcryptrun.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 5965b2871..c09819e26 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,12 @@ +2005-07-04 Marcus Brinkmann <marcus@g10code.de> + + * symcryptrun.c (SYMC_BAD_PASSPHRASE, SYMC_CANCELED): New symbols, + use instead constants. + (hash_string): New function copied from simple-gettext.c. + (confucius_get_pass): Take new argument CACHEID. + (confucius_process): Calculate cacheid and pass it to + confucius_get_pass. Clear passphrase from cache if necessary. + 2005-06-16 Werner Koch <wk@g10code.com> * gpg-connect-agent.c (read_and_print_response): Made LINELEN a diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index fcecf1770..075e0b444 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -56,6 +56,9 @@ Other classes may be added in the future. */ +#define SYMC_BAD_PASSPHRASE 2 +#define SYMC_CANCELED 3 + #include <config.h> @@ -107,6 +110,37 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) log_logv (level, fmt, arg_ptr); } + +/* From simple-gettext.c. */ + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + +/* The so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ + +static __inline__ ulong +hash_string( const char *str_param ) +{ + unsigned long int hval, g; + const char *str = str_param; + + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} + /* Constants to identify the commands and options. */ enum cmd_and_opt_values @@ -413,9 +447,10 @@ confucius_copy_file (char *infile, char *outfile, int plain) pointer, it will be set to true or false, depending on if the user canceled the operation or not. On error (including cancelation), a null pointer is returned. The passphrase must be deallocated with - confucius_drop_pass. */ + confucius_drop_pass. CACHEID is the ID to be used for passphrase + caching and can be NULL to disable caching. */ char * -confucius_get_pass (int again, int *canceled) +confucius_get_pass (const char *cacheid, int again, int *canceled) { int err; char *pw; @@ -444,7 +479,7 @@ confucius_get_pass (int again, int *canceled) } #endif - pw = simple_pwquery (NULL, + pw = simple_pwquery (cacheid, again ? _("does not match - try again"):NULL, _("Passphrase:"), NULL, &err); @@ -497,6 +532,7 @@ confucius_process (int mode, char *infile, char *outfile, pid_t pid; pid_t wpid; int tries = 0; + char cacheid[40]; signal (SIGPIPE, SIG_IGN); @@ -518,6 +554,10 @@ confucius_process (int mode, char *infile, char *outfile, return 1; } + /* Generate a hash from the keyfile name for caching. */ + snprintf (cacheid, sizeof (cacheid), "confucius:%lu", + hash_string (opt.keyfile)); + cacheid[sizeof (cacheid) - 1] = '\0'; args = malloc (sizeof (char *) * (10 + argc)); if (!args) { @@ -708,13 +748,20 @@ confucius_process (int mode, char *infile, char *outfile, char *pass; int canceled; - pass = confucius_get_pass (tries ? 1 : 0, &canceled); + /* If this is not the first attempt, the + passphrase seems to be wrong, so clear the + cache. */ + if (tries) + simple_pwclear (cacheid); + + pass = confucius_get_pass (cacheid, + tries ? 1 : 0, &canceled); if (!pass) { kill (pid, SIGTERM); close (master); close (cstderr[0]); - return canceled ? 3 : 1; + return canceled ? SYMC_CANCELED : 1; } write (master, pass, strlen (pass)); write (master, "\n", 1); @@ -736,6 +783,8 @@ confucius_process (int mode, char *infile, char *outfile, log_error (_("waitpid failed: %s\n"), strerror (errno)); kill (pid, SIGTERM); + /* State of cached password is unclear. Just remove it. */ + simple_pwclear (cacheid); return 1; } else @@ -746,15 +795,22 @@ confucius_process (int mode, char *infile, char *outfile, if (!WIFEXITED (res)) { log_error (_("child aborted with status %i\n"), res); + + /* State of cached password is unclear. Just remove it. */ + simple_pwclear (cacheid); + return 1; } if (WEXITSTATUS (res)) { + /* The passphrase was wrong. Remove it from the cache. */ + simple_pwclear (cacheid); + /* We probably exceeded our number of attempts at guessing the password. */ if (tries >= 3) - return 2; + return SYMC_BAD_PASSPHRASE; else return 1; } -- cgit v1.2.3 From 8889f4a2eeec08c53eda7feb75e978df4d811eba Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 19 Jul 2005 11:23:02 +0000 Subject: (gpgsm_get_certid): Cast printf arg to unsigned. Bug accidently introduced while solving the #$%^& gcc signed/unsigned char* warnings. --- sm/ChangeLog | 6 ++++++ sm/fingerprint.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index d9f295e1d..f1eb49c2c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2005-07-19 Werner Koch <wk@g10code.com> + + * fingerprint.c (gpgsm_get_certid): Cast printf arg to unsigned. + Bug accidently introduced while solving the #$%^& gcc + signed/unsigned char* warnings. + 2005-06-15 Werner Koch <wk@g10code.com> * delete.c (delete_one): Changed FPR to unsigned. diff --git a/sm/fingerprint.c b/sm/fingerprint.c index 9c3ab85db..9441483bf 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -318,7 +318,7 @@ gpgsm_get_certid (ksba_cert_t cert) sprintf (endp, "%02X", hash[i]); *endp++ = '.'; for (i=0; i < n; i++, endp += 2) - sprintf (endp, "%02X", p[i]); + sprintf (endp, "%02X", ((unsigned char*)p)[i]); *endp = 0; xfree (serial); @@ -328,5 +328,3 @@ gpgsm_get_certid (ksba_cert_t cert) - - -- cgit v1.2.3 From 68191d0c935719d9ab171e49b6456372c72cf1c4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 20 Jul 2005 15:05:05 +0000 Subject: * keylist.c (email_kludge): Reworked. * certdump.c (gpgsm_print_serial, gpgsm_dump_serial): Cast printf arg to unsigned. * call-dirmngr.c (gpgsm_dirmngr_run_command): Ditto --- THANKS | 3 ++- TODO | 2 ++ scd/ChangeLog | 13 +++++++++++++ scd/apdu.c | 6 ++++-- scd/app-openpgp.c | 9 ++++++++- scd/scdaemon.c | 2 ++ sm/ChangeLog | 8 ++++++++ sm/call-dirmngr.c | 2 +- sm/certdump.c | 4 ++-- sm/keylist.c | 26 +++++++++++++++++++------- sm/server.c | 2 +- 11 files changed, 62 insertions(+), 15 deletions(-) diff --git a/THANKS b/THANKS index 57add954b..408497046 100644 --- a/THANKS +++ b/THANKS @@ -1,7 +1,8 @@ Alexander Belopolsky belopolsky at mac.com Andrew J. Schorr aschorr at telemetry-investments.com -Kazu Yamamoto kazu@iij.ad.jp +Charly Avital shavital at mac.com +Kazu Yamamoto kazu at iij.ad.jp Michael Nottebrock michaelnottebrock at gmx.net Ray Link rlink at pitt.edu Richard Lefebvre rick at cerca.umontreal.ca diff --git a/TODO b/TODO index 5f1b57a0f..478f437c2 100644 --- a/TODO +++ b/TODO @@ -103,3 +103,5 @@ might want to have an agent context for each service request +* sm/ +** --include-certs seems to be a dummy option. diff --git a/scd/ChangeLog b/scd/ChangeLog index 0f7e4d2fa..970335aef 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,16 @@ +2005-07-05 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_readkey): Return a mallcoed copy of the key as + required by the description. Thanks to Moritz for tracking this + problem down. + +2005-06-21 Werner Koch <wk@g10code.com> + + * scdaemon.c (main): ifdef call to ccid_set_debug_level. + + * apdu.c (reset_pcsc_reader, open_pcsc_reader): Cast size_t to + ulong for printf. + 2005-06-06 Werner Koch <wk@g10code.com> * scdaemon.c (main): New option --debug-allow-core-dump. diff --git a/scd/apdu.c b/scd/apdu.c index 975fffa24..79022f21b 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -809,7 +809,8 @@ reset_pcsc_reader (int slot) len -= 4; /* Already read the error code. */ if (len > DIM (slotp->atr)) { - log_error ("PC/SC returned a too large ATR (len=%x)\n", len); + log_error ("PC/SC returned a too large ATR (len=%lx)\n", + (unsigned long)len); sw = SW_HOST_GENERAL_ERROR; goto command_failed; } @@ -1425,7 +1426,8 @@ open_pcsc_reader (const char *portstr) len -= 4; /* Already read the error code. */ if (len > DIM (slotp->atr)) { - log_error ("PC/SC returned a too large ATR (len=%x)\n", len); + log_error ("PC/SC returned a too large ATR (len=%lx)\n", + (unsigned long)len); goto command_failed; } err = (msgbuf[5] << 24) | (msgbuf[6] << 16) | (msgbuf[7] << 8 ) | msgbuf[8]; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 11e6eebaf..bd56fb99d 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1230,8 +1230,15 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) buf = app->app_local->pk[keyno-1].key; if (!buf) return gpg_error (GPG_ERR_NO_PUBKEY); - *pk = buf; *pklen = app->app_local->pk[keyno-1].keylen;; + *pk = xtrymalloc (*pklen); + if (!*pk) + { + err = gpg_error_from_errno (errno); + *pklen = 0; + return err; + } + memcpy (*pk, buf, *pklen); return 0; #else return gpg_error (GPG_ERR_NOT_IMPLEMENTED); diff --git a/scd/scdaemon.c b/scd/scdaemon.c index c75e87a62..c6995abcc 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -456,7 +456,9 @@ main (int argc, char **argv ) allow_coredump = 1; break; case oDebugCCIDDriver: +#ifdef HAVE_LIBUSB ccid_set_debug_level (ccid_set_debug_level (-1)+1); +#endif /*HAVE_LIBUSB*/ break; case oDebugDisableTicker: ticker_disabled = 1; break; diff --git a/sm/ChangeLog b/sm/ChangeLog index f1eb49c2c..cefa77e32 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2005-07-20 Werner Koch <wk@g10code.com> + + * keylist.c (email_kludge): Reworked. + + * certdump.c (gpgsm_print_serial, gpgsm_dump_serial): Cast printf + arg to unsigned. + * call-dirmngr.c (gpgsm_dirmngr_run_command): Ditto + 2005-07-19 Werner Koch <wk@g10code.com> * fingerprint.c (gpgsm_get_certid): Cast printf arg to unsigned. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 847e78490..ead117dfd 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -827,7 +827,7 @@ gpgsm_dirmngr_run_command (CTRL ctrl, const char *command, *p++ = '+'; else if (!isprint (*s) || *s == '+') { - sprintf (p, "%%%02X", *s); + sprintf (p, "%%%02X", *(const unsigned char *)s); p += 3; } else diff --git a/sm/certdump.c b/sm/certdump.c index 98f019c4a..aae60e020 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -70,7 +70,7 @@ gpgsm_print_serial (FILE *fp, ksba_const_sexp_t sn) else { for (p++; n; n--, p++) - fprintf (fp, "%02X", *p); + fprintf (fp, "%02X", *(const unsigned char*)p); } } } @@ -98,7 +98,7 @@ gpgsm_dump_serial (ksba_const_sexp_t sn) else { for (p++; n; n--, p++) - log_printf ("%02X", *p); + log_printf ("%02X", *(const unsigned char *)p); } } } diff --git a/sm/keylist.c b/sm/keylist.c index a0ac73fb3..8a4eb3cdb 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -251,30 +251,42 @@ print_time (gnupg_isotime_t t, FILE *fp) } -/* return an allocated string with the email address extracted from a +/* Return an allocated string with the email address extracted from a DN */ static char * email_kludge (const char *name) { - const char *p; + const char *p, *string; unsigned char *buf; int n; - if (strncmp (name, "1.2.840.113549.1.9.1=#", 22)) - return NULL; + string = name; + for (;;) + { + p = strstr (string, "1.2.840.113549.1.9.1=#"); + if (!p) + return NULL; + if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\')) + { + name = p + 22; + break; + } + string = p + 22; + } + + /* This looks pretty much like an email address in the subject's DN we use this to add an additional user ID entry. This way, openSSL generated keys get a nicer and usable listing */ - name += 22; for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++) ; - if (*p != '#' || !n) + if (!n) return NULL; buf = xtrymalloc (n+3); if (!buf) return NULL; /* oops, out of core */ *buf = '<'; - for (n=1, p=name; *p != '#'; p +=2, n++) + for (n=1, p=name; hexdigitp (p); p +=2, n++) buf[n] = xtoi_2 (p); buf[n++] = '>'; buf[n] = 0; diff --git a/sm/server.c b/sm/server.c index b3816d3d9..87a06ee4e 100644 --- a/sm/server.c +++ b/sm/server.c @@ -1109,7 +1109,7 @@ write_status_text_and_buffer ( int no, const char *string, if (s != buffer) fwrite (buffer, s-buffer, 1, statusfp ); if ( esc ) { - fprintf (statusfp, "%%%02X", *(const byte*)s ); + fprintf (statusfp, "%%%02X", *(const unsigned char*)s ); s++; n--; } buffer = s; -- cgit v1.2.3 From 5e47c186121f4bcf4f4e0f665b6d136e97f1ff43 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 20 Jul 2005 16:08:15 +0000 Subject: Fix to let it compile. This is not required but avoids complaints from folks not reading the documentation. --- g10/misc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/g10/misc.c b/g10/misc.c index 516e80bcc..a0599f304 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -988,8 +988,7 @@ mpi_print( FILE *fp, gcry_mpi_t a, int mode ) int rc; char *buffer; - rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, - &(unsigned char*)buffer, NULL, a ); + rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, &buffer, NULL, a ); assert( !rc ); fputs( buffer, fp ); n += strlen(buffer); -- cgit v1.2.3 From 99f403b0154fa7c5c935f34122ebe860f30d12c6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 21 Jul 2005 18:29:13 +0000 Subject: * gpgsm.c (main): New options --no-log-file and --debug-none. * certreqgen.c (get_parameter, get_parameter_value): Add SEQ arg to allow enumeration. Changed all callers. (create_request): Process DNS and URI parameters. * gpgsm-gencert.sh: Reworked to allow for multiple email addresses as well as DNsanmes and URi. Present the parameter file before creating the certificate. --- sm/ChangeLog | 8 ++++ sm/certreqgen.c | 122 +++++++++++++++++++++++++++++++++++++------------ sm/gpgsm.c | 8 +++- tools/ChangeLog | 6 +++ tools/gpgsm-gencert.sh | 56 ++++++++++++++++++++--- 5 files changed, 164 insertions(+), 36 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index cefa77e32..a76f586eb 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,11 @@ +2005-07-21 Werner Koch <wk@g10code.com> + + * gpgsm.c (main): New options --no-log-file and --debug-none. + + * certreqgen.c (get_parameter, get_parameter_value): Add SEQ arg + to allow enumeration. Changed all callers. + (create_request): Process DNS and URI parameters. + 2005-07-20 Werner Koch <wk@g10code.com> * keylist.c (email_kludge): Reworked. diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 2b920da7e..c9a092046 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -1,5 +1,5 @@ /* certreqgen.c - Generate a key and a certification request - * Copyright (C) 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -71,7 +71,11 @@ The format of the native parameter file is follows: Name-DN: subject name This is the DN name of the subject in rfc2253 format. Name-Email: <string> - The ist the email address + The is an email address for the altSubjectName + Name-DNS: <string> + The is an DNS name for the altSubjectName + Name-URI: <string> + The is an URI for the altSubjectName Here is an example: $ cat >foo <<EOF @@ -109,7 +113,9 @@ enum para_name { pKEYLENGTH, pKEYUSAGE, pNAMEDN, - pNAMEEMAIL + pNAMEEMAIL, + pNAMEDNS, + pNAMEURI }; struct para_data_s { @@ -155,26 +161,27 @@ release_parameter_list (struct para_data_s *r) } static struct para_data_s * -get_parameter (struct para_data_s *para, enum para_name key) +get_parameter (struct para_data_s *para, enum para_name key, int seq) { struct para_data_s *r; - for (r = para; r && r->key != key; r = r->next) - ; - return r; + for (r = para; r ; r = r->next) + if ( r->key == key && !seq--) + return r; + return NULL; } static const char * -get_parameter_value (struct para_data_s *para, enum para_name key) +get_parameter_value (struct para_data_s *para, enum para_name key, int seq) { - struct para_data_s *r = get_parameter (para, key); + struct para_data_s *r = get_parameter (para, key, seq); return (r && *r->u.value)? r->u.value : NULL; } static int get_parameter_algo (struct para_data_s *para, enum para_name key) { - struct para_data_s *r = get_parameter (para, key); + struct para_data_s *r = get_parameter (para, key, 0); if (!r) return -1; if (digitp (r->u.value)) @@ -189,7 +196,7 @@ get_parameter_algo (struct para_data_s *para, enum para_name key) static int parse_parameter_usage (struct para_data_s *para, enum para_name key) { - struct para_data_s *r = get_parameter (para, key); + struct para_data_s *r = get_parameter (para, key, 0); char *p, *pn; unsigned int use; @@ -220,7 +227,7 @@ parse_parameter_usage (struct para_data_s *para, enum para_name key) static unsigned int get_parameter_uint (struct para_data_s *para, enum para_name key) { - struct para_data_s *r = get_parameter (para, key); + struct para_data_s *r = get_parameter (para, key, 0); if (!r) return 0; @@ -241,12 +248,15 @@ read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer) static struct { const char *name; enum para_name key; + int allow_dups; } keywords[] = { { "Key-Type", pKEYTYPE}, { "Key-Length", pKEYLENGTH }, { "Key-Usage", pKEYUSAGE }, { "Name-DN", pNAMEDN }, - { "Name-Email", pNAMEEMAIL }, + { "Name-Email", pNAMEEMAIL, 1 }, + { "Name-DNS", pNAMEDNS, 1 }, + { "Name-URI", pNAMEURI, 1 }, { NULL, 0 } }; char line[1024], *p; @@ -347,7 +357,7 @@ read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer) release_parameter_list (para); para = NULL; } - else + else if (!keywords[i].allow_dups) { for (r = para; r && r->key != keywords[i].key; r = r->next) ; @@ -433,9 +443,10 @@ proc_parameters (ctrl_t ctrl, unsigned char keyparms[100]; int rc; ksba_sexp_t public; + int seq; /* check that we have all required parameters */ - assert (get_parameter (para, pKEYTYPE)); + assert (get_parameter (para, pKEYTYPE, 0)); /* We can only use RSA for now. There is a with pkcs-10 on how to use ElGamal because it is expected that a PK algorithm can always @@ -443,20 +454,20 @@ proc_parameters (ctrl_t ctrl, i = get_parameter_algo (para, pKEYTYPE); if (i < 1 || i != GCRY_PK_RSA ) { - r = get_parameter (para, pKEYTYPE); + r = get_parameter (para, pKEYTYPE, 0); log_error (_("line %d: invalid algorithm\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } /* check the keylength */ - if (!get_parameter (para, pKEYLENGTH)) + if (!get_parameter (para, pKEYLENGTH, 0)) nbits = 1024; else nbits = get_parameter_uint (para, pKEYLENGTH); if (nbits < 1024 || nbits > 4096) { /* The BSI specs dated 2002-11-25 don't allow lengths below 1024. */ - r = get_parameter (para, pKEYTYPE); + r = get_parameter (para, pKEYLENGTH, 0); log_error (_("line %d: invalid key length %u (valid are %d to %d)\n"), r->lnr, nbits, 1024, 4096); return gpg_error (GPG_ERR_INV_PARAMETER); @@ -468,16 +479,16 @@ proc_parameters (ctrl_t ctrl, /* check that there is a subject name and that this DN fits our requirements */ - if (!(s=get_parameter_value (para, pNAMEDN))) + if (!(s=get_parameter_value (para, pNAMEDN, 0))) { - r = get_parameter (para, pKEYTYPE); + r = get_parameter (para, pKEYTYPE, 0); log_error (_("line %d: no subject name given\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } /* fixme check s */ /* check that the optional email address is okay */ - if ((s=get_parameter_value (para, pNAMEEMAIL))) + for (seq=0; (s=get_parameter_value (para, pNAMEEMAIL, seq)); seq++) { if (has_invalid_email_chars (s) || *s == '@' @@ -485,7 +496,7 @@ proc_parameters (ctrl_t ctrl, || s[strlen(s)-1] == '.' || strstr(s, "..")) { - r = get_parameter (para, pKEYTYPE); + r = get_parameter (para, pNAMEEMAIL, seq); log_error (_("line %d: not a valid email address\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } @@ -497,7 +508,7 @@ proc_parameters (ctrl_t ctrl, rc = gpgsm_agent_genkey (ctrl, keyparms, &public); if (rc) { - r = get_parameter (para, pKEYTYPE); + r = get_parameter (para, pKEYTYPE, 0); log_error (_("line %d: key generation failed: %s\n"), r->lnr, gpg_strerror (rc)); return rc; @@ -524,6 +535,10 @@ create_request (ctrl_t ctrl, int rc = 0; const char *s; unsigned int use; + int seq; + char *buf, *p; + size_t len; + char numbuf[30]; err = ksba_certreq_new (&cr); if (err) @@ -541,7 +556,7 @@ create_request (ctrl_t ctrl, ksba_certreq_set_hash_function (cr, HASH_FNC, md); ksba_certreq_set_writer (cr, outctrl->writer); - err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN)); + err = ksba_certreq_add_subject (cr, get_parameter_value (para, pNAMEDN, 0)); if (err) { log_error ("error setting the subject's name: %s\n", @@ -550,11 +565,8 @@ create_request (ctrl_t ctrl, goto leave; } - s = get_parameter_value (para, pNAMEEMAIL); - if (s) + for (seq=0; (s = get_parameter_value (para, pNAMEEMAIL, seq)); seq++) { - char *buf; - buf = xtrymalloc (strlen (s) + 3); if (!buf) { @@ -575,6 +587,60 @@ create_request (ctrl_t ctrl, } } + for (seq=0; (s = get_parameter_value (para, pNAMEDNS, seq)); seq++) + { + len = strlen (s); + assert (len); + snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len); + buf = p = xtrymalloc (11 + strlen (numbuf) + len + 3); + if (!buf) + { + rc = OUT_OF_CORE (errno); + goto leave; + } + p = stpcpy (p, "(8:dns-name"); + p = stpcpy (p, numbuf); + p = stpcpy (p, s); + strcpy (p, ")"); + + err = ksba_certreq_add_subject (cr, buf); + xfree (buf); + if (err) + { + log_error ("error setting the subject's alternate name: %s\n", + gpg_strerror (err)); + rc = err; + goto leave; + } + } + + for (seq=0; (s = get_parameter_value (para, pNAMEURI, seq)); seq++) + { + len = strlen (s); + assert (len); + snprintf (numbuf, DIM(numbuf), "%u:", (unsigned int)len); + buf = p = xtrymalloc (6 + strlen (numbuf) + len + 3); + if (!buf) + { + rc = OUT_OF_CORE (errno); + goto leave; + } + p = stpcpy (p, "(3:uri"); + p = stpcpy (p, numbuf); + p = stpcpy (p, s); + strcpy (p, ")"); + + err = ksba_certreq_add_subject (cr, buf); + xfree (buf); + if (err) + { + log_error ("error setting the subject's alternate name: %s\n", + gpg_strerror (err)); + rc = err; + goto leave; + } + } + err = ksba_certreq_set_public_key (cr, public); if (err) diff --git a/sm/gpgsm.c b/sm/gpgsm.c index fb6533030..0f9745a8c 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -99,12 +99,14 @@ enum cmd_and_opt_values { oDebug, oDebugLevel, oDebugAll, + oDebugNone, oDebugWait, oDebugAllowCoreDump, oDebugNoChainValidation, oDebugIgnoreExpiration, oFixedPassphrase, oLogFile, + oNoLogFile, oEnableSpecialFilenames, @@ -330,6 +332,7 @@ static ARGPARSE_OPTS opts[] = { { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") }, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, + { oNoLogFile, "no-log-file" ,0, "@"}, #if 0 { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") }, @@ -351,6 +354,7 @@ static ARGPARSE_OPTS opts[] = { { oDebug, "debug" ,4|16, "@"}, { oDebugLevel, "debug-level" ,2, N_("|LEVEL|set the debugging level to LEVEL")}, { oDebugAll, "debug-all" ,0, "@"}, + { oDebugNone, "debug-none" ,0, "@"}, { oDebugWait, "debug-wait" ,1, "@"}, { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" }, { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"}, @@ -1032,7 +1036,8 @@ main ( int argc, char **argv) break; case oLogFile: logfile = pargs.r.ret_str; break; - + case oNoLogFile: logfile = NULL; break; + case oBatch: opt.batch = 1; greeting = 0; @@ -1046,6 +1051,7 @@ main ( int argc, char **argv) case oDebug: debug_value |= pargs.r.ret_ulong; break; case oDebugAll: debug_value = ~0; break; + case oDebugNone: debug_value = 0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugAllowCoreDump: diff --git a/tools/ChangeLog b/tools/ChangeLog index c09819e26..e1dfce49d 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,9 @@ +2005-07-21 Werner Koch <wk@g10code.com> + + * gpgsm-gencert.sh: Reworked to allow for multiple email addresses + as well as DNsanmes and URi. Present the parameter file before + creating the certificate. + 2005-07-04 Marcus Brinkmann <marcus@g10code.de> * symcryptrun.c (SYMC_BAD_PASSPHRASE, SYMC_CANCELED): New symbols, diff --git a/tools/gpgsm-gencert.sh b/tools/gpgsm-gencert.sh index ec5025b8f..44b06f3b3 100755 --- a/tools/gpgsm-gencert.sh +++ b/tools/gpgsm-gencert.sh @@ -1,7 +1,7 @@ #!/bin/sh # -*- sh -*- # gpgsm-gencert.c - Generate X.509 certificates through GPGSM. -# Copyright (C) 2004 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -93,25 +93,67 @@ KEY_LENGTH=$ANSWER query_user_menu "Key usage" "sign, encrypt" "sign" "encrypt" KEY_USAGE=$ANSWER -query_user "Name" +query_user "Name (DN)" NAME=$ANSWER -query_user "E-Mail address" -EMAIL_ADDRESS=$ANSWER +EMAIL_ADDRESSES= +LF= +while : ; do + query_user "E-Mail addresses (end with an empty line)" + [ -z "$ANSWER" ] && break + EMAIL_ADDRESSES="${EMAIL_ADDRESSES}${LF}Name-Email: $ANSWER" + LF=' +' +done + +DNS_ADDRESSES= +LF= +while : ; do + query_user "DNS Names (optional; end with an empty line)" + [ -z "$ANSWER" ] && break + DNS_ADDRESSES="${DNS_ADDRESSES}${LF}Name-DNS: $ANSWER" + LF=' +' +done + +URI_ADDRESSES= +LF= +while : ; do + query_user "URIs (optional; end with an empty line)" + [ -z "$ANSWER" ] && break + URI_ADDRESSES="${URI_ADDRESSES}${LF}Name-URI: $ANSWER" + LF=' +' +done file_parameter=$(mktemp "/tmp/gpgsm.XXXXXX") outfile=$(mktemp "/tmp/gpgsm.XXXXXX") -cat > "$file_parameter" <<EOF + +( +cat <<EOF Key-Type: $KEY_TYPE Key-Length: $KEY_LENGTH Key-Usage: $KEY_USAGE Name-DN: $NAME -Name-Email: $EMAIL_ADDRESS EOF +[ -n "$EMAIL_ADDRESSES" ] && echo "$EMAIL_ADDRESSES" +[ -n "$DNS_ADDRESSES" ] && echo "$DNS_ADDRESSES" +[ -n "$URI_ADDRESSES" ] && echo "$URI_ADDRESSES" +) > "$file_parameter" + + +echo 'Parameters for certificate request to create:' >&2 +cat -n "$file_parameter" >&2 +echo >&2 + +query_user_menu "Really create such a CSR?" "yes" "no" +[ "$ANSWER" != "yes" ] && exit 1 + echo -e "$ASSUAN_COMMANDS" | \ - gpgsm --server 4< "$file_parameter" 5>"$outfile" >/dev/null + ./gpgsm --no-log-file --debug-level none --debug-none \ + --server 4< "$file_parameter" 5>"$outfile" >/dev/null cat "$outfile" -- cgit v1.2.3 From a2d1673d6622e39c41f061e1bffb5ca05c803320 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 25 Jul 2005 14:35:04 +0000 Subject: * findkey.c (agent_public_key_from_file): Fixed array assignment. This was the cause for random segvs. * call-agent.c (gpgsm_agent_readkey): New. --- NEWS | 4 ++++ TODO | 12 +----------- agent/ChangeLog | 5 +++++ agent/findkey.c | 2 +- doc/gpgsm.texi | 4 ++-- sm/call-agent.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- sm/certreqgen.c | 39 ++++++++++++++++++++++++++++++--------- sm/gpgsm.h | 2 ++ 8 files changed, 91 insertions(+), 24 deletions(-) diff --git a/NEWS b/NEWS index a1e77db0c..313e7c076 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 1.9.18 ------------------------------------------------- + * [gpgsm] Now allows for more than one email address as well as URIs + and dnsNames in certificate request generation. A keygrip may be + given to create a request from an existing key. + Noteworthy changes in version 1.9.17 (2005-06-20) ------------------------------------------------- diff --git a/TODO b/TODO index 478f437c2..32b728588 100644 --- a/TODO +++ b/TODO @@ -28,11 +28,6 @@ might want to have an agent context for each service request ** 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. ** support the anyPolicy semantic ** Check that we are really following the verification procedures in rfc3280. ** Implement a --card-status command. @@ -45,11 +40,6 @@ might want to have an agent context for each service request ** 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 @@ -104,4 +94,4 @@ might want to have an agent context for each service request * sm/ -** --include-certs seems to be a dummy option. +** --include-certs is as of now still a dummy command line option diff --git a/agent/ChangeLog b/agent/ChangeLog index 4d539d485..bcb00e341 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-07-25 Werner Koch <wk@g10code.com> + + * findkey.c (agent_public_key_from_file): Fixed array assignment. + This was the cause for random segvs. + 2005-06-29 Werner Koch <wk@g10code.com> * command-ssh.c (data_sign): Removed empty statement. diff --git a/agent/findkey.c b/agent/findkey.c index 1cb7efaf3..73ffb530d 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -671,7 +671,7 @@ agent_public_key_from_file (ctrl_t ctrl, *p++ = *s; p = stpcpy (p, " %m)"); assert (argidx < DIM (args)); - args[argidx++] = array[idx]; + args[argidx++] = &array[idx]; } *p++ = ')'; if (uri) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index ba98ae87c..653ada332 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -790,8 +790,8 @@ client must provide it. 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 @command{GPGSM} can be -used to restrict the use of this command. +token is used to store the key. Configuration options to +@command{GPGSM} can be used to restrict the use of this command. @example GENKEY diff --git a/sm/call-agent.c b/sm/call-agent.c index 92a29928c..c47f6b19a 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -1,5 +1,5 @@ /* call-agent.c - divert operations to the agent - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -432,6 +432,51 @@ gpgsm_agent_genkey (ctrl_t ctrl, return 0; } + +/* Call the agent to read the public key part for a given keygrip. */ +int +gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip, + ksba_sexp_t *r_pubkey) +{ + int rc; + membuf_t data; + size_t len; + unsigned char *buf; + char line[ASSUAN_LINELENGTH]; + + *r_pubkey = NULL; + rc = start_agent (ctrl); + if (rc) + return rc; + + rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + snprintf (line, DIM(line)-1, "READKEY %s", hexkeygrip); + line[DIM(line)-1] = 0; + + init_membuf (&data, 1024); + 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); + } + 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; +} + /* Ask the agent whether the certificate is in the list of trusted keys */ diff --git a/sm/certreqgen.c b/sm/certreqgen.c index c9a092046..c523c992a 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -63,6 +63,9 @@ The format of the native parameter file is follows: algorithm is "rsa". Key-Length: <length-in-bits> Length of the key in bits. Default is 1024. + Key-Grip: hexstring + This is optional and used to generate a request for an already + existsing key. Key-Length will be ignored when given, Key-Usage: <usage-list> Space or comma delimited list of key usage, allowed values are "encrypt" and "sign". This is used to generate the KeyUsage extension. @@ -111,6 +114,7 @@ EOF enum para_name { pKEYTYPE, pKEYLENGTH, + pKEYGRIP, pKEYUSAGE, pNAMEDN, pNAMEEMAIL, @@ -252,6 +256,7 @@ read_parameters (ctrl_t ctrl, FILE *fp, ksba_writer_t writer) } keywords[] = { { "Key-Type", pKEYTYPE}, { "Key-Length", pKEYLENGTH }, + { "Key-Grip", pKEYGRIP }, { "Key-Usage", pKEYUSAGE }, { "Name-DN", pNAMEDN }, { "Name-Email", pNAMEEMAIL, 1 }, @@ -502,16 +507,32 @@ proc_parameters (ctrl_t ctrl, } } - sprintf (numbuf, "%u", nbits); - snprintf ((char*)keyparms, DIM (keyparms)-1, - "(6:genkey(3:rsa(5:nbits%d:%s)))", (int)strlen (numbuf), numbuf); - rc = gpgsm_agent_genkey (ctrl, keyparms, &public); - if (rc) + s = get_parameter_value (para, pKEYGRIP, 0); + if (s) /* Use existing key. */ { - r = get_parameter (para, pKEYTYPE, 0); - log_error (_("line %d: key generation failed: %s\n"), - r->lnr, gpg_strerror (rc)); - return rc; + rc = gpgsm_agent_readkey (ctrl, s, &public); + if (rc) + { + r = get_parameter (para, pKEYTYPE, 0); + log_error (_("line %d: error getting key by keygrip `%s': %s\n"), + r->lnr, s, gpg_strerror (rc)); + return rc; + } + } + else /* Generate new key. */ + { + sprintf (numbuf, "%u", nbits); + snprintf ((char*)keyparms, DIM (keyparms)-1, + "(6:genkey(3:rsa(5:nbits%d:%s)))", + (int)strlen (numbuf), numbuf); + rc = gpgsm_agent_genkey (ctrl, keyparms, &public); + if (rc) + { + r = get_parameter (para, pKEYTYPE, 0); + log_error (_("line %d: key generation failed: %s\n"), + r->lnr, gpg_strerror (rc)); + return rc; + } } rc = create_request (ctrl, para, public, outctrl); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 2f3e83485..63d07a8c2 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -299,6 +299,8 @@ int gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, char **r_buf, size_t *r_buflen); int gpgsm_agent_genkey (ctrl_t ctrl, ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey); +int gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip, + ksba_sexp_t *r_pubkey); int gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert); int gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip); int gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert); -- cgit v1.2.3 From 97d4c30539d4893d5606c8bfa2f2d2c963745543 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Aug 2005 13:17:42 +0000 Subject: Fixed Umlaut problem --- po/ChangeLog | 4 + po/de.po | 322 +++++++++++++++++++++++++++++------------------------------ 2 files changed, 165 insertions(+), 161 deletions(-) diff --git a/po/ChangeLog b/po/ChangeLog index 27a63ca73..4fa8cefec 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2005-08-01 Werner Koch <wk@g10code.com> + + * de.po: Converted to utf-8; fixed a few umlaut problems. + 2005-04-21 Werner Koch <wk@g10code.com> * de.po: Fixed all fuzzies and untranslated strings. diff --git a/po/de.po b/po/de.po index 5a79a1bd7..bf90b9b58 100644 --- a/po/de.po +++ b/po/de.po @@ -1,4 +1,4 @@ -# German translation for GnuPG 1.9.x -*-coding: latin-1;-*- +# German translation for GnuPG 1.9.x # Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. # Werner Koch <wk@gnupg.org>, 2002. # @@ -8,14 +8,14 @@ # msgid "" msgstr "" -"Project-Id-Version: gnupg2 1.9.16\n" +"Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" "POT-Creation-Date: 2005-06-16 09:12+0200\n" -"PO-Revision-Date: 2005-06-20 19:12+0200\n" +"PO-Revision-Date: 2005-08-01 14:44+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: agent/gpg-agent.c:108 agent/protect-tool.c:108 scd/scdaemon.c:99 @@ -28,16 +28,16 @@ msgstr "" #: agent/gpg-agent.c:110 scd/scdaemon.c:101 msgid "run in server mode (foreground)" -msgstr "Im Server Modus ausfhren" +msgstr "Im Server Modus ausführen" #: agent/gpg-agent.c:111 scd/scdaemon.c:104 msgid "run in daemon mode (background)" -msgstr "Im Daemon Modus ausfhren" +msgstr "Im Daemon Modus ausführen" #: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:105 sm/gpgsm.c:329 #: tools/gpgconf.c:62 msgid "verbose" -msgstr "ausfhrlich" +msgstr "ausführlich" #: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:106 sm/gpgsm.c:330 msgid "be somewhat more quiet" @@ -45,11 +45,11 @@ msgstr "Etwas weniger Ausgaben erzeugen" #: agent/gpg-agent.c:114 scd/scdaemon.c:107 msgid "sh-style command output" -msgstr "Ausgabe fr /bin/sh" +msgstr "Ausgabe für /bin/sh" #: agent/gpg-agent.c:115 scd/scdaemon.c:108 msgid "csh-style command output" -msgstr "Ausgabe fr /bin/csh" +msgstr "Ausgabe für /bin/csh" #: agent/gpg-agent.c:116 msgid "|FILE|read options from FILE" @@ -69,7 +69,7 @@ msgstr "Logausgaben in eine Datei umlenken" #: agent/gpg-agent.c:125 msgid "use a standard location for the socket" -msgstr "Benutze einen Standardnamen fr den Socket" +msgstr "Benutze einen Standardnamen für den Socket" #: agent/gpg-agent.c:129 msgid "|PGM|use PGM as the PIN-Entry program" @@ -101,7 +101,7 @@ msgstr "benutze PINs im Cache nicht bem Signieren" #: agent/gpg-agent.c:151 msgid "allow clients to mark keys as \"trusted\"" -msgstr "erlaube Aufrufern Schlssel als \"vertrauenswrdig\" zu markieren" +msgstr "erlaube Aufrufern Schlüssel als \"vertrauenswürdig\" zu markieren" #: agent/gpg-agent.c:153 msgid "allow presetting passphrase" @@ -127,7 +127,7 @@ msgstr ">.\n" #: agent/gpg-agent.c:238 msgid "Usage: gpg-agent [options] (-h for help)" -msgstr "Gebrauch: gpg-agent [Optionen] (-h fr Hilfe)" +msgstr "Gebrauch: gpg-agent [Optionen] (-h für Hilfe)" #: agent/gpg-agent.c:240 msgid "" @@ -135,19 +135,19 @@ msgid "" "Secret key management for GnuPG\n" msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" -"Verwaltung von geheimen Schlssel fr GnuPG\n" +"Verwaltung von geheimen Schlüssel für GnuPG\n" #: agent/gpg-agent.c:311 scd/scdaemon.c:257 sm/gpgsm.c:632 #, c-format msgid "invalid debug-level `%s' given\n" -msgstr "ungltige Debugebene `%s' angegeben\n" +msgstr "ungültige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:482 agent/protect-tool.c:1072 kbx/kbxutil.c:431 #: scd/scdaemon.c:349 sm/gpgsm.c:753 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" -"Die Bibliothek \"libgcrypt\" is zu alt (bentigt wird %s, vorhanden ist %s)\n" +"Die Bibliothek \"libgcrypt\" is zu alt (benötigt wird %s, vorhanden ist %s)\n" #: agent/gpg-agent.c:574 scd/scdaemon.c:424 sm/gpgsm.c:854 #, c-format @@ -198,7 +198,7 @@ msgstr "Der listen() Aufruf ist fehlgeschlagen: %s\n" #: agent/gpg-agent.c:1218 scd/scdaemon.c:983 #, c-format msgid "listening on socket `%s'\n" -msgstr "Es wird auf Socket `%s' gehrt\n" +msgstr "Es wird auf Socket `%s' gehört\n" #: agent/gpg-agent.c:1246 agent/gpg-agent.c:1288 #, c-format @@ -208,7 +208,7 @@ msgstr "Verzeichniss `%s' wurde erstellt\n" #: agent/gpg-agent.c:1294 #, c-format msgid "stat() failed for `%s': %s\n" -msgstr "stat() Aufruf fr `%s' fehlgeschlagen: %s\n" +msgstr "stat() Aufruf für `%s' fehlgeschlagen: %s\n" #: agent/gpg-agent.c:1298 #, c-format @@ -218,22 +218,22 @@ msgstr "Die Datei `%s' kann nicht als Home-Verzeichniss benutzt werden\n" #: agent/gpg-agent.c:1396 #, c-format msgid "handler 0x%lx for fd %d started\n" -msgstr "Handhabungsroutine 0x%lx fr fd %d gestartet\n" +msgstr "Handhabungsroutine 0x%lx für fd %d gestartet\n" #: agent/gpg-agent.c:1406 #, c-format msgid "handler 0x%lx for fd %d terminated\n" -msgstr "Handhabungsroutine 0x%lx fr den fd %d beendet\n" +msgstr "Handhabungsroutine 0x%lx für den fd %d beendet\n" #: agent/gpg-agent.c:1420 #, c-format msgid "ssh handler 0x%lx for fd %d started\n" -msgstr "SSH Handhabungsroutine 0x%lx fr fd %d gestartet\n" +msgstr "SSH Handhabungsroutine 0x%lx für fd %d gestartet\n" #: agent/gpg-agent.c:1427 #, c-format msgid "ssh handler 0x%lx for fd %d terminated\n" -msgstr "SSH Handhabungsroutine 0x%lx fr fd %d beendet\n" +msgstr "SSH Handhabungsroutine 0x%lx für fd %d beendet\n" #: agent/gpg-agent.c:1521 scd/scdaemon.c:1099 #, c-format @@ -256,11 +256,11 @@ msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" #: agent/gpg-agent.c:1648 common/simple-pwquery.c:335 sm/call-agent.c:155 #, c-format msgid "gpg-agent protocol version %d is not supported\n" -msgstr "Das gpg-agent Protocol %d wird nicht untersttzt\n" +msgstr "Das gpg-agent Protocol %d wird nicht unterstützt\n" #: agent/protect-tool.c:145 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" -msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h fr Hilfe)\n" +msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h für Hilfe)\n" #: agent/protect-tool.c:147 msgid "" @@ -268,7 +268,7 @@ msgid "" "Secret key maintenance tool\n" msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" -"Werkzeug zum Bearbeiten von geheimen Schlsseln\n" +"Werkzeug zum Bearbeiten von geheimen Schlüsseln\n" #: agent/protect-tool.c:1205 msgid "Please enter the passphrase to unprotect the PKCS#12 object." @@ -297,11 +297,11 @@ msgid "" "needed to complete this operation." msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" -"wird bentigt um diese Aktion auszufhren." +"wird benötigt um diese Aktion auszuführen." #: agent/protect-tool.c:1220 agent/genkey.c:131 agent/genkey.c:238 msgid "does not match - try again" -msgstr "Keine bereinstimmung - bitte nochmal versuchen" +msgstr "Keine Übereinstimmung - bitte nochmal versuchen" #: agent/protect-tool.c:1221 msgid "Passphrase:" @@ -337,7 +337,7 @@ msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" #, c-format msgid "Please enter the passphrase to%0Ato protect your new key" msgstr "" -"Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlssel zu schtzen" +"Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlüssel zu schützen" #: agent/genkey.c:217 msgid "Please enter the new passphrase" @@ -353,7 +353,7 @@ msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" msgstr "" -"Bitte geben Sie Ihre PIN ein, so da der geheime Schlssel benutzt werden " +"Bitte geben Sie Ihre PIN ein, so daß der geheime Schlüssel benutzt werden " "kann" #: agent/query.c:335 @@ -361,7 +361,7 @@ msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" msgstr "" -"Bitte geben Sie Ihr Mantra (Passphrase) ein, so da der geheime Schlssel " +"Bitte geben Sie Ihr Mantra (Passphrase) ein, so daß der geheime Schlüssel " "benutzt werden kann" #: agent/query.c:393 agent/query.c:405 @@ -374,7 +374,7 @@ msgstr "Das Matra (Passphrase) ist zu lang" #: agent/query.c:402 msgid "Invalid characters in PIN" -msgstr "Ungltige Zeichen in der PIN" +msgstr "Ungültige Zeichen in der PIN" #: agent/query.c:407 msgid "PIN too short" @@ -407,7 +407,7 @@ msgid "" "Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " "fingerprint:%%0A %s" msgstr "" -"Bitte prfen Sie, da das Zertifikat mit dem Namen:%%0A \"%s\"%%0Afolgenden " +"Bitte prüfen Sie, daß das Zertifikat mit dem Namen:%%0A \"%s\"%%0Afolgenden " "Fingerabdruck hat:%%0A %s" #. TRANSLATORS: "Correct" is the label of a button and intended to @@ -431,8 +431,8 @@ msgid "" "Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " "certificates?" msgstr "" -"Wenn Sie vollstndiges Vertrauen haben, da%%0A \"%s\"%%" -"0ABenutzerzertifikate verllich zertifiziert, so antworten Sie mit \"Ja\"" +"Wenn Sie vollständiges Vertrauen haben, daß%%0A \"%s\"%%" +"0ABenutzerzertifikate verläßlich zertifiziert, so antworten Sie mit \"Ja\"" #: agent/trustlist.c:342 msgid "Yes" @@ -452,16 +452,16 @@ msgstr "" #: common/sysutils.c:182 #, c-format msgid "Warning: unsafe ownership on %s \"%s\"\n" -msgstr "WARNUNG: Unsichere Besitzrechte fr %s \"%s\"\n" +msgstr "WARNUNG: Unsichere Besitzrechte für %s \"%s\"\n" #: common/sysutils.c:214 #, c-format msgid "Warning: unsafe permissions on %s \"%s\"\n" -msgstr "WARNUNG: Unsichere Zugriffsrechte fr %s \"%s\"\n" +msgstr "WARNUNG: Unsichere Zugriffsrechte für %s \"%s\"\n" #: common/simple-pwquery.c:309 msgid "gpg-agent is not available in this session\n" -msgstr "Der gpg-agent ist nicht verfgbar\n" +msgstr "Der gpg-agent ist nicht verfügbar\n" #: common/simple-pwquery.c:367 #, c-format @@ -509,7 +509,7 @@ msgstr "" #: kbx/kbxutil.c:83 sm/gpgsm.c:337 tools/gpgconf.c:64 msgid "do not make any changes" -msgstr "Keine nderungen durchfhren" +msgstr "Keine Änderungen durchführen" #: kbx/kbxutil.c:85 msgid "set debugging flags" @@ -521,7 +521,7 @@ msgstr "Alle Debug Flags setzen" #: kbx/kbxutil.c:107 msgid "Please report bugs to " -msgstr "Bite richten sie Berichte ber Bugs (Softwarefehler) an " +msgstr "Bite richten sie Berichte über Bugs (Softwarefehler) an " #: kbx/kbxutil.c:107 msgid ".\n" @@ -529,7 +529,7 @@ msgstr ".\n" #: kbx/kbxutil.c:111 msgid "Usage: kbxutil [options] [files] (-h for help)" -msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h fr Hilfe)" +msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h für Hilfe)" #: kbx/kbxutil.c:114 msgid "" @@ -541,7 +541,7 @@ msgstr "" #: scd/scdaemon.c:103 msgid "run in multi server mode (foreground)" -msgstr "Im Multiserver Modus ausfhren" +msgstr "Im Multiserver Modus ausführen" #: scd/scdaemon.c:109 sm/gpgsm.c:349 msgid "read options from file" @@ -569,7 +569,7 @@ msgstr "Erlaube die Benutzung von \"Admin\" Kommandos" #: scd/scdaemon.c:186 msgid "Usage: scdaemon [options] (-h for help)" -msgstr "Gebrauch: scdaemon [Optionen] (-h fr Hilfe)" +msgstr "Gebrauch: scdaemon [Optionen] (-h für Hilfe)" #: scd/scdaemon.c:188 msgid "" @@ -577,23 +577,23 @@ msgid "" "Smartcard daemon for GnuPG\n" msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" -"Smartcard Daemon fr GnuPG\n" +"Smartcard Daemon für GnuPG\n" #: scd/scdaemon.c:656 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " -"auszufhren\n" +"auszuführen\n" #: scd/scdaemon.c:997 #, c-format msgid "handler for fd %d started\n" -msgstr "Handhabungsroutine fr fd %d gestartet\n" +msgstr "Handhabungsroutine für fd %d gestartet\n" #: scd/scdaemon.c:1002 #, c-format msgid "handler for fd %d terminated\n" -msgstr "Handhabungsroutine fr den fd %d beendet\n" +msgstr "Handhabungsroutine für den fd %d beendet\n" #: scd/app-openpgp.c:595 #, c-format @@ -608,19 +608,19 @@ msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" #: scd/app-openpgp.c:978 #, c-format msgid "reading public key failed: %s\n" -msgstr "Fehler beim Lesen des ffentlichen Schlssels: %s\n" +msgstr "Fehler beim Lesen des öffentlichen Schlüssels: %s\n" #: scd/app-openpgp.c:986 scd/app-openpgp.c:1910 msgid "response does not contain the public key data\n" -msgstr "Die Antwort enthlt keine Public Key Daten\n" +msgstr "Die Antwort enthält keine Public Key Daten\n" #: scd/app-openpgp.c:994 scd/app-openpgp.c:1918 msgid "response does not contain the RSA modulus\n" -msgstr "Die Antwort enthlt keinen RSA Modulus\n" +msgstr "Die Antwort enthält keinen RSA Modulus\n" #: scd/app-openpgp.c:1003 scd/app-openpgp.c:1928 msgid "response does not contain the RSA public exponent\n" -msgstr "Die Antwort enthlt keinen ffenlichen RSA Exponent\n" +msgstr "Die Antwort enthält keinen öffenlichen RSA Exponent\n" #: scd/app-openpgp.c:1259 scd/app-openpgp.c:1347 scd/app-openpgp.c:2150 #, c-format @@ -630,13 +630,13 @@ msgstr "Fehler vom PIN \"callback\": %s\n" #: scd/app-openpgp.c:1265 scd/app-openpgp.c:1353 scd/app-openpgp.c:2156 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" -msgstr "Die PIN fr den CHV%d ist zu kurz; Mindestlnge ist %d\n" +msgstr "Die PIN für den CHV%d ist zu kurz; Mindestlänge ist %d\n" #: scd/app-openpgp.c:1274 scd/app-openpgp.c:1288 scd/app-openpgp.c:1363 #: scd/app-openpgp.c:2165 scd/app-openpgp.c:2179 #, c-format msgid "verify CHV%d failed: %s\n" -msgstr "Prfen von CHV%d fehlgeschlagen: %s\n" +msgstr "Prüfen von CHV%d fehlgeschlagen: %s\n" #: scd/app-openpgp.c:1311 msgid "access to admin commands is not configured\n" @@ -654,7 +654,7 @@ msgstr "Die Karte ist dauerhaft gesperrt!\n" #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" -"Noch %d Admin PIN Versuche mglich bevor die Karte dauerhaft gesperrt wird\n" +"Noch %d Admin PIN Versuche möglich bevor die Karte dauerhaft gesperrt wird\n" #. TRANSLATORS: Do not translate the "|A|" prefix but #. keep it at the start of the string. We need this elsewhere @@ -689,15 +689,15 @@ msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" #: scd/app-openpgp.c:1563 msgid "key already exists\n" -msgstr "Schlssel existiert bereits\n" +msgstr "Schlüssel existiert bereits\n" #: scd/app-openpgp.c:1567 msgid "existing key will be replaced\n" -msgstr "Existierender Schlssel wird ersetzt\n" +msgstr "Existierender Schlüssel wird ersetzt\n" #: scd/app-openpgp.c:1569 msgid "generating new key\n" -msgstr "Neuer Schlssel wird erzeugt\n" +msgstr "Neuer Schlüssel wird erzeugt\n" #: scd/app-openpgp.c:1736 msgid "creation timestamp missing\n" @@ -711,7 +711,7 @@ msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n" #: scd/app-openpgp.c:1750 #, c-format msgid "RSA public exponent missing or larger than %d bits\n" -msgstr "Der ffentliche RSA Exponent fehlt oder ist lnger als %d Bits\n" +msgstr "Der öffentliche RSA Exponent fehlt oder ist länger als %d Bits\n" #: scd/app-openpgp.c:1758 scd/app-openpgp.c:1765 #, c-format @@ -721,24 +721,24 @@ msgstr "Die RSA Primzahl %s fehlt oder ist nicht %d Bits lang\n" #: scd/app-openpgp.c:1828 #, c-format msgid "failed to store the key: %s\n" -msgstr "Fehler beim Speichern des Schlssels: %s\n" +msgstr "Fehler beim Speichern des Schlüssels: %s\n" #: scd/app-openpgp.c:1887 msgid "please wait while key is being generated ...\n" -msgstr "Bitte warten bis der Schlssel erzeugt wurde ...\n" +msgstr "Bitte warten bis der Schlüssel erzeugt wurde ...\n" #: scd/app-openpgp.c:1901 msgid "generating key failed\n" -msgstr "Fehler beim Erzeugen des Schlssels\n" +msgstr "Fehler beim Erzeugen des Schlüssels\n" #: scd/app-openpgp.c:1904 #, c-format msgid "key generation completed (%d seconds)\n" -msgstr "Schlsselerzeugung vollendet (%d Sekunden)\n" +msgstr "Schlüsselerzeugung vollendet (%d Sekunden)\n" #: scd/app-openpgp.c:1961 msgid "invalid structure of OpenPGP card (DO 0x93)\n" -msgstr "Ungltige Struktur der OpenPGP Karte (DO 0x93)\n" +msgstr "Ungültige Struktur der OpenPGP Karte (DO 0x93)\n" #: scd/app-openpgp.c:2130 #, c-format @@ -754,18 +754,18 @@ msgstr "||Bitte geben Sie die PIN ein%%0A[Sigs bisher: %lu]" msgid "" "verification of Admin PIN is currently prohibited through this command\n" msgstr "" -"Die berprfung der Admin PIN is momentan durch ein Kommando verboten " +"Die Überprüfung der Admin PIN is momentan durch ein Kommando verboten " "worden\n" #: scd/app-openpgp.c:2470 scd/app-openpgp.c:2480 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" -msgstr "Zugriff auf %s nicht mglich - ungltige OpenPGP Karte?\n" +msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n" #: sm/base64.c:317 #, c-format msgid "invalid radix64 character %02x skipped\n" -msgstr "Ungltiges Basis-64 Zeichen %02X wurde bergangen\n" +msgstr "Ungültiges Basis-64 Zeichen %02X wurde übergangen\n" #: sm/call-agent.c:101 msgid "no running gpg-agent - starting one\n" @@ -773,7 +773,7 @@ msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" #: sm/call-agent.c:166 msgid "can't connect to the agent - trying fall back\n" -msgstr "Verbindung zum gpg-agent nicht mglich - Ersatzmethode wird versucht\n" +msgstr "Verbindung zum gpg-agent nicht möglich - Ersatzmethode wird versucht\n" #: sm/call-dirmngr.c:174 msgid "no running dirmngr - starting one\n" @@ -786,7 +786,7 @@ msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" #: sm/call-dirmngr.c:226 #, c-format msgid "dirmngr protocol version %d is not supported\n" -msgstr "Die Dirmngr Protokollversion %d wird nicht untersttzt\n" +msgstr "Die Dirmngr Protokollversion %d wird nicht unterstützt\n" #: sm/call-dirmngr.c:240 msgid "can't connect to the dirmngr - trying fall back\n" @@ -812,11 +812,11 @@ msgstr "[Fehler - Unbekannte Kodierung]" #: sm/certdump.c:514 msgid "[Error - invalid encoding]" -msgstr "[Fehler - Ungltige Kodierung]" +msgstr "[Fehler - Ungültige Kodierung]" #: sm/certdump.c:519 msgid "[Error - invalid DN]" -msgstr "[Fehler - Ungltiger DN]" +msgstr "[Fehler - Ungültiger DN]" #: sm/certdump.c:680 #, c-format @@ -826,7 +826,7 @@ msgid "" "S/N %s, ID %08lX, created %s" msgstr "" "Bitte geben Sie die Passphrase an, um den \n" -"geheimen Schlssel von\n" +"geheimen Schlüssel von\n" "\"%s\"\n" "S/N %s, ID %08lX, erzeugt %s\n" "zu entsperren" @@ -834,16 +834,16 @@ msgstr "" #: sm/certlist.c:122 msgid "no key usage specified - assuming all usages\n" msgstr "" -"Schlsselverwendungszweck nicht vorhanden - fr alle Zwecke akzeptiert\n" +"Schlüsselverwendungszweck nicht vorhanden - für alle Zwecke akzeptiert\n" #: sm/certlist.c:132 sm/keylist.c:224 #, c-format msgid "error getting key usage information: %s\n" -msgstr "Fehler beim holen der Schlsselbenutzungsinformationen: %s\n" +msgstr "Fehler beim holen der Schlüsselbenutzungsinformationen: %s\n" #: sm/certlist.c:142 msgid "certificate should have not been used for certification\n" -msgstr "Das Zertifikat htte nicht zum Zertifizieren benutzt werden sollen\n" +msgstr "Das Zertifikat hätte nicht zum Zertifizieren benutzt werden sollen\n" #: sm/certlist.c:154 msgid "certificate should have not been used for OCSP response signing\n" @@ -853,7 +853,7 @@ msgstr "" #: sm/certlist.c:165 msgid "certificate should have not been used for encryption\n" -msgstr "Das Zertifikat hätte nicht zum Verschlsseln benutzt werden sollen\n" +msgstr "Das Zertifikat hätte nicht zum Verschlüsseln benutzt werden sollen\n" #: sm/certlist.c:166 msgid "certificate should have not been used for signing\n" @@ -861,7 +861,7 @@ msgstr "Das Zertifikat hätte nicht zum Signieren benutzt werden sollen\n" #: sm/certlist.c:167 msgid "certificate is not usable for encryption\n" -msgstr "Das Zertifikat kann nicht zum Verschlsseln benutzt werden\n" +msgstr "Das Zertifikat kann nicht zum Verschlüsseln benutzt werden\n" #: sm/certlist.c:168 msgid "certificate is not usable for signing\n" @@ -870,11 +870,11 @@ msgstr "Das Zertifikat kann nicht zum Signieren benutzt werden\n" #: sm/certchain.c:109 #, c-format msgid "critical certificate extension %s is not supported" -msgstr "Die kritische Zertifikaterweiterung %s wird nicht untersttzt" +msgstr "Die kritische Zertifikaterweiterung %s wird nicht unterstützt" #: sm/certchain.c:131 msgid "issuer certificate is not marked as a CA" -msgstr "Das Herausgeberzertifikat ist nicht fr eine CA gekennzeichnet" +msgstr "Das Herausgeberzertifikat ist nicht für eine CA gekennzeichnet" #: sm/certchain.c:169 msgid "critical marked policy without configured policies" @@ -883,7 +883,7 @@ msgstr "kritische Richtlinie ohne konfigurierte Richtlinien" #: sm/certchain.c:179 #, c-format msgid "failed to open `%s': %s\n" -msgstr "Datei `%s' kann nicht geffnet werden: %s\n" +msgstr "Datei `%s' kann nicht geöffnet werden: %s\n" #: sm/certchain.c:186 sm/certchain.c:215 msgid "note: non-critical certificate policy not allowed" @@ -900,7 +900,7 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" #: sm/certchain.c:350 #, c-format msgid "number of issuers matching: %d\n" -msgstr "Anzahl der bereinstimmenden Heruasgeber: %d\n" +msgstr "Anzahl der übereinstimmenden Heruasgeber: %d\n" #: sm/certchain.c:503 sm/certchain.c:662 sm/certchain.c:1031 sm/decrypt.c:260 #: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 @@ -913,7 +913,7 @@ msgstr "Das Zertifikat wurde widerrufen" #: sm/certchain.c:601 msgid "no CRL found for certificate" -msgstr "Keine CRL fr das Zertifikat gefunden" +msgstr "Keine CRL für das Zertifikat gefunden" #: sm/certchain.c:605 msgid "the available CRL is too old" @@ -927,7 +927,7 @@ msgstr "" #: sm/certchain.c:612 #, c-format msgid "checking the CRL failed: %s" -msgstr "Die CRL konnte nicht geprft werden: %s" +msgstr "Die CRL konnte nicht geprüft werden: %s" #: sm/certchain.c:682 msgid "no issuer found in certificate" @@ -936,11 +936,11 @@ msgstr "Im Zertifikat ist kein Herausgeber enthalten" #: sm/certchain.c:695 #, c-format msgid "certificate with invalid validity: %s" -msgstr "Zertifikat mit unzulssiger Gltigkeit: %s" +msgstr "Zertifikat mit unzulässiger Gültigkeit: %s" #: sm/certchain.c:711 msgid "certificate not yet valid" -msgstr "Das Zertifikat ist noch nicht gltig" +msgstr "Das Zertifikat ist noch nicht gültig" #: sm/certchain.c:724 msgid "certificate has expired" @@ -952,7 +952,7 @@ msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" #: sm/certchain.c:779 msgid "root certificate is not marked trusted" -msgstr "Das Wurzelzertifikat ist nicht als vertrauenswrdig markiert" +msgstr "Das Wurzelzertifikat ist nicht als vertrauenswürdig markiert" #: sm/certchain.c:790 #, c-format @@ -961,12 +961,12 @@ msgstr "Fingerprint=%s\n" #: sm/certchain.c:795 msgid "root certificate has now been marked as trusted\n" -msgstr "Das Wurzelzertifikat wurde nun als vertrauenswrdig markiert\n" +msgstr "Das Wurzelzertifikat wurde nun als vertrauenswürdig markiert\n" #: sm/certchain.c:810 #, c-format msgid "checking the trust list failed: %s\n" -msgstr "Fehler beim Prfen der vertrauenswrdigen Zertifikate: %s\n" +msgstr "Fehler beim Prüfen der vertrauenswürdigen Zertifikate: %s\n" #: sm/certchain.c:836 sm/import.c:157 msgid "certificate chain too long\n" @@ -983,19 +983,19 @@ msgstr "Das Zertifikat hat eine FALSCHE Signatur" #: sm/certchain.c:911 msgid "found another possible matching CA certificate - trying again" msgstr "" -"Eine anderes mglicherweise passendes CA-Zertifikat gefunden - versuche " +"Eine anderes möglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" #: sm/certchain.c:934 #, c-format msgid "certificate chain longer than allowed by CA (%d)" -msgstr "Die Zertifikatkette ist lnger als von der CA erlaubt (%d)" +msgstr "Die Zertifikatkette ist länger als von der CA erlaubt (%d)" #: sm/decrypt.c:127 msgid "" "WARNING: message was encrypted with a weak key in the symmetric cipher.\n" msgstr "" -"WARNUNG: Die Nachricht wurde mich einem schwachen Schlssel (Weak Key) " +"WARNUNG: Die Nachricht wurde mich einem schwachen Schlüssel (Weak Key) " "erzeugt\n" #: sm/decrypt.c:325 @@ -1004,7 +1004,7 @@ msgstr "(Dies ist der RC-2 Algorithmus)\n" #: sm/decrypt.c:327 msgid "(this does not seem to be an encrypted message)\n" -msgstr "(dies is wahrscheinlich keine verschlsselte Nachricht)\n" +msgstr "(dies is wahrscheinlich keine verschlüsselte Nachricht)\n" #: sm/delete.c:51 sm/delete.c:102 #, c-format @@ -1019,25 +1019,25 @@ msgstr "Fehler beim Sperren der Keybox: %s\n" #: sm/delete.c:133 #, c-format msgid "duplicated certificate `%s' deleted\n" -msgstr "Doppeltes Zertifikat `%s' gelscht\n" +msgstr "Doppeltes Zertifikat `%s' gelöscht\n" #: sm/delete.c:135 #, c-format msgid "certificate `%s' deleted\n" -msgstr "Zertifikat `%s' gelscht\n" +msgstr "Zertifikat `%s' gelöscht\n" #: sm/delete.c:165 #, c-format msgid "deleting certificate \"%s\" failed: %s\n" -msgstr "Fehler beim Lschen des Zertifikats \"%s\": %s\n" +msgstr "Fehler beim Löschen des Zertifikats \"%s\": %s\n" #: sm/encrypt.c:120 msgid "weak key created - retrying\n" -msgstr "Schwacher Schlssel - es wird erneut versucht\n" +msgstr "Schwacher Schlüssel - es wird erneut versucht\n" #: sm/encrypt.c:332 msgid "no valid recipients given\n" -msgstr "Keine gltigen Empfnger angegeben\n" +msgstr "Keine gültigen Empfänger angegeben\n" #: sm/gpgsm.c:239 msgid "|[FILE]|make a signature" @@ -1053,55 +1053,55 @@ msgstr "Erzeuge eine abgetrennte Signatur" #: sm/gpgsm.c:242 msgid "encrypt data" -msgstr "Verschlssele die Daten" +msgstr "Verschlüssele die Daten" #: sm/gpgsm.c:243 msgid "encryption only with symmetric cipher" -msgstr "Verschlsselung nur mit symmetrischem Algrithmus" +msgstr "Verschlüsselung nur mit symmetrischem Algrithmus" #: sm/gpgsm.c:244 msgid "decrypt data (default)" -msgstr "Enschlssele die Daten" +msgstr "Enschlüssele die Daten" #: sm/gpgsm.c:245 msgid "verify a signature" -msgstr "berprfen einer Signatur" +msgstr "Überprüfen einer Signatur" #: sm/gpgsm.c:247 msgid "list keys" -msgstr "Schlssel anzeigen" +msgstr "Schlüssel anzeigen" #: sm/gpgsm.c:248 msgid "list external keys" -msgstr "Externe Schlssel anzeigen" +msgstr "Externe Schlüssel anzeigen" #: sm/gpgsm.c:249 msgid "list secret keys" -msgstr "Geheime Schlssel anzeigen" +msgstr "Geheime Schlüssel anzeigen" #: sm/gpgsm.c:250 msgid "list certificate chain" -msgstr "Schlssel mit Zertifikatekette anzeigen" +msgstr "Schlüssel mit Zertifikatekette anzeigen" #: sm/gpgsm.c:252 msgid "list keys and fingerprints" -msgstr "Schlssel und Fingerprint anzeigen" +msgstr "Schlüssel und Fingerprint anzeigen" #: sm/gpgsm.c:253 msgid "generate a new key pair" -msgstr "Neues Schlsselpaar erzeugen" +msgstr "Neues Schlüsselpaar erzeugen" #: sm/gpgsm.c:254 msgid "remove key from the public keyring" -msgstr "Schlssel aus dem ffentlichen Schlsselbund lschen" +msgstr "Schlüssel aus dem öffentlichen Schlüsselbund löschen" #: sm/gpgsm.c:255 msgid "export keys to a key server" -msgstr "Schlssen an eine Schlsselserver exportieren" +msgstr "Schlüssen an eine Schlüsselserver exportieren" #: sm/gpgsm.c:256 msgid "import keys from a key server" -msgstr "Schlssel von einem Schlsselserver importieren" +msgstr "Schlüssel von einem Schlüsselserver importieren" #: sm/gpgsm.c:257 msgid "import certificates" @@ -1117,7 +1117,7 @@ msgstr "Smartcard registrieren" #: sm/gpgsm.c:260 msgid "run in server mode" -msgstr "Im Server Modus ausfhren" +msgstr "Im Server Modus ausführen" #: sm/gpgsm.c:261 msgid "pass a command to the dirmngr" @@ -1129,11 +1129,11 @@ msgstr "Rufe das gpg-protect-tool auf" #: sm/gpgsm.c:264 msgid "change a passphrase" -msgstr "Das Mantra (Passphrase) ndern" +msgstr "Das Mantra (Passphrase) ändern" #: sm/gpgsm.c:274 msgid "create ascii armored output" -msgstr "Ausgabe mit ASCII Hlle wird erzeugt" +msgstr "Ausgabe mit ASCII Hülle wird erzeugt" #: sm/gpgsm.c:276 msgid "create base-64 encoded output" @@ -1149,15 +1149,15 @@ msgstr "Eingabedaten sind im Basis-64 Format" #: sm/gpgsm.c:282 msgid "assume input is in binary format" -msgstr "Eingabedaten sind im Binrformat" +msgstr "Eingabedaten sind im Binärformat" #: sm/gpgsm.c:284 msgid "|NAME|encrypt for NAME" -msgstr "|NAME|Verschlsseln fr NAME" +msgstr "|NAME|Verschlüsseln für NAME" #: sm/gpgsm.c:287 msgid "use system's dirmngr if available" -msgstr "Benutze den System Dirmngr when verfgbar" +msgstr "Benutze den System Dirmngr when verfügbar" #: sm/gpgsm.c:288 msgid "never consult a CRL" @@ -1165,7 +1165,7 @@ msgstr "Niemals eine CRL konsultieren" #: sm/gpgsm.c:295 msgid "check validity using OCSP" -msgstr "Die Gltigkeit mittels OCSP prfen" +msgstr "Die Gültigkeit mittels OCSP prüfen" #: sm/gpgsm.c:298 msgid "|N|number of certificates to include" @@ -1177,7 +1177,7 @@ msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" #: sm/gpgsm.c:304 msgid "do not check certificate policies" -msgstr "Zertikikatrichtlinien nicht berprfen" +msgstr "Zertikikatrichtlinien nicht überprüfen" #: sm/gpgsm.c:308 msgid "fetch missing issuer certificates" @@ -1185,15 +1185,15 @@ msgstr "Fehlende Zertifikate automatisch holen" #: sm/gpgsm.c:312 msgid "|NAME|use NAME as default recipient" -msgstr "|NAME|Benutze NAME als voreingestellten Empfnger" +msgstr "|NAME|Benutze NAME als voreingestellten Empfänger" #: sm/gpgsm.c:314 msgid "use the default key as default recipient" -msgstr "Benuzte voreingestellten Schlssel als Standardempfnger" +msgstr "Benuzte voreingestellten Schlüssel als Standardempfänger" #: sm/gpgsm.c:320 msgid "use this user-id to sign or decrypt" -msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlsseln" +msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlüsseln" #: sm/gpgsm.c:323 msgid "|N|set compress level N (0 disables)" @@ -1209,7 +1209,7 @@ msgstr "als Ausgabedatei benutzen" #: sm/gpgsm.c:331 msgid "don't use the terminal at all" -msgstr "Das Terminal berhaupt nicht benutzen" +msgstr "Das Terminal überhaupt nicht benutzen" #: sm/gpgsm.c:334 msgid "force v3 signatures" @@ -1217,7 +1217,7 @@ msgstr "Version 3 Signaturen erzwingen" #: sm/gpgsm.c:335 msgid "always use a MDC for encryption" -msgstr "Immer das MDC Verfahren zum verschlsseln mitbenutzen" +msgstr "Immer das MDC Verfahren zum verschlüsseln mitbenutzen" #: sm/gpgsm.c:340 msgid "batch mode: never ask" @@ -1241,15 +1241,15 @@ msgstr "Diese geheimen Keyring in die Liste aufnehmen" #: sm/gpgsm.c:346 msgid "|NAME|use NAME as default secret key" -msgstr "|NAME|Benutze NAME als voreingestellten Schlssel" +msgstr "|NAME|Benutze NAME als voreingestellten Schlüssel" #: sm/gpgsm.c:347 msgid "|HOST|use this keyserver to lookup keys" -msgstr "|HOST|Benutze HOST als Schlsselserver" +msgstr "|HOST|Benutze HOST als Schlüsselserver" #: sm/gpgsm.c:348 msgid "|NAME|set terminal charset to NAME" -msgstr "|NAME|Den Zeichensatz fr das Terminal auf NAME setzen" +msgstr "|NAME|Den Zeichensatz für das Terminal auf NAME setzen" #: sm/gpgsm.c:352 msgid "|LEVEL|set the debugging level to LEVEL" @@ -1265,7 +1265,7 @@ msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" #: sm/gpgsm.c:372 msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAME|Den Verschlsselungsalgrithmus NAME benutzen" +msgstr "|NAME|Den Verschlüsselungsalgrithmus NAME benutzen" #: sm/gpgsm.c:374 msgid "|NAME|use message digest algorithm NAME" @@ -1297,15 +1297,15 @@ msgstr "" "@\n" "Beispiele:\n" "\n" -" -se -r Bob [Datei] Signieren und verschlsseln fr Benutzer Bob\\n\n" +" -se -r Bob [Datei] Signieren und verschlüsseln für Benutzer Bob\\n\n" " --clearsign [Datei] Eine Klartextsignatur erzeugen\\n\n" " --detach-sign [Datei] Eine abgetrennte Signatur erzeugen\\n\n" -" --list-keys [Namen] Schlssel anzeigenn\n" -" --fingerprint [Namen] \"Fingerabdrcke\" anzeigen\\n\n" +" --list-keys [Namen] Schlüssel anzeigenn\n" +" --fingerprint [Namen] \"Fingerabdrücke\" anzeigen\\n\n" #: sm/gpgsm.c:506 msgid "Usage: gpgsm [options] [files] (-h for help)" -msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h fr Hilfe)" +msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h für Hilfe)" #: sm/gpgsm.c:509 msgid "" @@ -1314,7 +1314,7 @@ msgid "" "default operation depends on the input data\n" msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" -"Signieren, prfen, ver- und entschlsseln mittels S/MIME protocol\n" +"Signieren, prüfen, ver- und entschlüsseln mittels S/MIME protocol\n" #: sm/gpgsm.c:516 msgid "" @@ -1322,7 +1322,7 @@ msgid "" "Supported algorithms:\n" msgstr "" "\n" -"Untersttzte Algorithmen:\n" +"Unterstützte Algorithmen:\n" #: sm/gpgsm.c:603 msgid "usage: gpgsm [options] " @@ -1335,33 +1335,33 @@ msgstr "Widersprechende Kommandos\n" #: sm/gpgsm.c:684 #, c-format msgid "can't encrypt to `%s': %s\n" -msgstr "Verschlsseln fr `%s' nicht mglich: %s\n" +msgstr "Verschlüsseln für `%s' nicht möglich: %s\n" #: sm/gpgsm.c:758 #, c-format msgid "libksba is too old (need %s, have %s)\n" -msgstr "Die Bibliothek Libksba is nicht aktuell (bentige %s, habe %s)\n" +msgstr "Die Bibliothek Libksba is nicht aktuell (benötige %s, habe %s)\n" #: sm/gpgsm.c:1215 msgid "WARNING: program may create a core file!\n" -msgstr "WARNUNG: Programm knnte eine core-dump-Datei schreiben!\n" +msgstr "WARNUNG: Programm könnte eine core-dump-Datei schreiben!\n" #: sm/gpgsm.c:1227 msgid "WARNING: running with faked system time: " -msgstr "WARNUNG: Ausfhrung mit geflschter Systemzeit: " +msgstr "WARNUNG: Ausführung mit gefälschter Systemzeit: " #: sm/gpgsm.c:1253 msgid "selected cipher algorithm is invalid\n" -msgstr "Das ausgewhlte Verschlsselungsverfahren ist ungltig\n" +msgstr "Das ausgewählte Verschlüsselungsverfahren ist ungültig\n" #: sm/gpgsm.c:1261 msgid "selected digest algorithm is invalid\n" -msgstr "Das ausgewhlte Hashverfahren ist ungltig\n" +msgstr "Das ausgewählte Hashverfahren ist ungültig\n" #: sm/gpgsm.c:1291 #, c-format msgid "can't sign using `%s': %s\n" -msgstr "Signieren mit `%s' nicht mglich: %s\n" +msgstr "Signieren mit `%s' nicht möglich: %s\n" #: sm/gpgsm.c:1464 msgid "this command has not yet been implemented\n" @@ -1370,7 +1370,7 @@ msgstr "Diee Kommando wurde noch nicht implementiert\n" #: sm/gpgsm.c:1694 sm/gpgsm.c:1731 #, c-format msgid "can't open `%s': %s\n" -msgstr "Datei `%s' kann nicht geffnet werden: %s\n" +msgstr "Datei `%s' kann nicht geöffnet werden: %s\n" #: sm/import.c:109 #, c-format @@ -1385,22 +1385,22 @@ msgstr " importiert: %lu" #: sm/import.c:116 #, c-format msgid " unchanged: %lu\n" -msgstr " nicht gendert: %lu\n" +msgstr " nicht geändert: %lu\n" #: sm/import.c:118 #, c-format msgid " secret keys read: %lu\n" -msgstr " gelesene private Schlssel: %lu\n" +msgstr " gelesene private Schlüssel: %lu\n" #: sm/import.c:120 #, c-format msgid " secret keys imported: %lu\n" -msgstr "importierte priv. Schlssel: %lu\n" +msgstr "importierte priv. Schlüssel: %lu\n" #: sm/import.c:122 #, c-format msgid " secret keys unchanged: %lu\n" -msgstr "ungenderte priv. Schlssel: %lu\n" +msgstr "ungeänderte priv. Schlüssel: %lu\n" #: sm/import.c:124 #, c-format @@ -1413,7 +1413,7 @@ msgstr "Fehler beim speichern des Zertifikats\n" #: sm/import.c:234 msgid "basic certificate checks failed - not imported\n" -msgstr "Grundlegende Zertifikatprfungen fehlgeschlagen - nicht importiert\n" +msgstr "Grundlegende Zertifikatprüfungen fehlgeschlagen - nicht importiert\n" #: sm/import.c:420 sm/import.c:452 #, c-format @@ -1423,12 +1423,12 @@ msgstr "Fehler beim Importieren des Zertifikats: %s\n" #: sm/import.c:524 sm/import.c:549 #, c-format msgid "error creating temporary file: %s\n" -msgstr "Fehler beim Erstellen einer temporren Datei: %s\n" +msgstr "Fehler beim Erstellen einer temporären Datei: %s\n" #: sm/import.c:532 #, c-format msgid "error writing to temporary file: %s\n" -msgstr "Fehler beim Schreiben auf eine temporre Datei: %s\n" +msgstr "Fehler beim Schreiben auf eine temporäre Datei: %s\n" #: sm/import.c:541 #, c-format @@ -1523,7 +1523,7 @@ msgstr "|KOMPONENTE|Zeige die Optionen an" #: tools/gpgconf.c:57 msgid "|COMPONENT|change options" -msgstr "|KOMPONENTE|ndere die Optionen" +msgstr "|KOMPONENTE|Ändere die Optionen" #: tools/gpgconf.c:63 msgid "quiet" @@ -1531,11 +1531,11 @@ msgstr "Weniger Ausgaben" #: tools/gpgconf.c:65 msgid "activate changes at runtime, if possible" -msgstr "Aktiviere nderungen zur Laufzeit; falls mglich" +msgstr "Aktiviere Änderungen zur Laufzeit; falls möglich" #: tools/gpgconf.c:88 msgid "Usage: gpgconf [options] (-h for help)" -msgstr "Gebrauch: gpgconf [Optionen] (-h fr Hilfe)" +msgstr "Gebrauch: gpgconf [Optionen] (-h für Hilfe)" #: tools/gpgconf.c:91 msgid "" @@ -1543,7 +1543,7 @@ msgid "" "Manage configuration options for tools of the GnuPG system\n" msgstr "" "Syntax: gpgconf {Optionen]\n" -"Verwalte Konfigurationsoptionen fr Programme des GnuPG Systems\n" +"Verwalte Konfigurationsoptionen für Programme des GnuPG Systems\n" #: tools/gpgconf.c:175 msgid "usage: gpgconf [options] " @@ -1551,7 +1551,7 @@ msgstr "Gebrauch: gpgconf [Optionen] " #: tools/gpgconf.c:177 msgid "Need one component argument" -msgstr "Bentige ein Komponenten Argument" +msgstr "Benötige ein Komponenten Argument" #: tools/gpgconf.c:186 msgid "Component not found" @@ -1570,7 +1570,7 @@ msgstr "Optionen zur Einstellung der Konfiguration" #: tools/gpgconf-comp.c:458 tools/gpgconf-comp.c:535 tools/gpgconf-comp.c:584 #: tools/gpgconf-comp.c:640 tools/gpgconf-comp.c:716 msgid "Options useful for debugging" -msgstr "Ntzliche Optionen zum Debuggen" +msgstr "Nützliche Optionen zum Debuggen" #: tools/gpgconf-comp.c:463 tools/gpgconf-comp.c:540 tools/gpgconf-comp.c:589 #: tools/gpgconf-comp.c:645 tools/gpgconf-comp.c:724 @@ -1583,11 +1583,11 @@ msgstr "Optionen zur Einstellung der Sicherheit" #: tools/gpgconf-comp.c:597 msgid "Configuration for Keyservers" -msgstr "Konfiguration der Schlsselserver" +msgstr "Konfiguration der Schlüsselserver" #: tools/gpgconf-comp.c:658 msgid "do not check CRLs for root certificates" -msgstr "CRL bei Wurzelzertifikaten nicht berprfen" +msgstr "CRL bei Wurzelzertifikaten nicht überprüfen" #: tools/gpgconf-comp.c:699 msgid "Options controlling the format of the output" @@ -1595,11 +1595,11 @@ msgstr "Optionen zum Einstellen der Ausgabeformate" #: tools/gpgconf-comp.c:735 msgid "Options controlling the interactivity and enforcement" -msgstr "Optionen zur Einstellung der Interaktivitt und Geltendmachung" +msgstr "Optionen zur Einstellung der Interaktivität und Geltendmachung" #: tools/gpgconf-comp.c:745 msgid "Configuration for HTTP servers" -msgstr "Konfiguration fr HTTP Server" +msgstr "Konfiguration für HTTP Server" #: tools/gpgconf-comp.c:756 msgid "use system's HTTP proxy setting" @@ -1629,7 +1629,7 @@ msgstr "Konfiguration zu OCSP" #~ msgstr "Fehler beim Holen der Seriennummer: %s\n" #~ msgid "reading the key failed\n" -#~ msgstr "Fehler beim Lesen des Schlssels: %s\n" +#~ msgstr "Fehler beim Lesen des Schlüssels: %s\n" #~ msgid "error creating a pipe: %s\n" #~ msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" @@ -1642,13 +1642,13 @@ msgstr "Konfiguration zu OCSP" #~ "Das Warten auf die Beendigung des protect-tools ist fehlgeschlagen: %s\n" #~ msgid "error running `%s': probably not installed\n" -#~ msgstr "Feler bei Ausfhrung von `%s': wahrscheinlich nicht installiert\n" +#~ msgstr "Feler bei Ausführung von `%s': wahrscheinlich nicht installiert\n" #~ msgid "error running `%s': exit status %d\n" -#~ msgstr "Fehler bei Ausfhrung von `%s': Endestatus %d\n" +#~ msgstr "Fehler bei Ausführung von `%s': Endestatus %d\n" #~ msgid "Usage: sc-investigate [options] (-h for help)\n" -#~ msgstr "Gebrauch: sc-investigate [Optionen] (-h fr Hilfe)\n" +#~ msgstr "Gebrauch: sc-investigate [Optionen] (-h für Hilfe)\n" #~ msgid "" #~ "Syntax: sc-investigate [options] [args]]\n" @@ -1659,7 +1659,7 @@ msgstr "Konfiguration zu OCSP" #~ msgid "can't access Extended Capability Flags - invalid OpenPGP card?\n" #~ msgstr "" -#~ "Zugriff auf die Extended Capability Flags nicht mglich - ungltige " +#~ "Zugriff auf die Extended Capability Flags nicht möglich - ungültige " #~ "OpenPGP Karte?\n" #~ msgid "Enter passphrase:" @@ -1670,5 +1670,5 @@ msgstr "Konfiguration zu OCSP" #~ msgid "no key usage specified - accepted for encryption\n" #~ msgstr "" -#~ "Schlsselverwendungszweck nicht vorhanden - wird zum Verschlsseln " +#~ "Schlüsselverwendungszweck nicht vorhanden - wird zum Verschlüsseln " #~ "akzeptiert\n" -- cgit v1.2.3 From 3919421a4fae940d0575f1e852aef30a26cfcaea Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 1 Aug 2005 16:54:54 +0000 Subject: About to release 1.9.18 --- ChangeLog | 6 ++++++ NEWS | 4 +++- agent/t-protect.c | 2 ++ configure.ac | 4 ++-- po/de.po | 7 +++---- tools/ChangeLog | 5 +++++ tools/gpgsm-gencert.sh | 20 +++++++++++++++----- 7 files changed, 36 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a5b882f8..f63a035cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-08-01 Werner Koch <wk@g10code.com> + + Released 1.9.18. + + * configure.ac: Require libksba 0.9.12 to match new features in gpgsm. + 2005-06-20 Werner Koch <wk@g10code.com> Released 1.9.17. diff --git a/NEWS b/NEWS index 313e7c076..f05c17ea9 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,12 @@ -Noteworthy changes in version 1.9.18 +Noteworthy changes in version 1.9.18 (2005-08-01) ------------------------------------------------- * [gpgsm] Now allows for more than one email address as well as URIs and dnsNames in certificate request generation. A keygrip may be given to create a request from an existing key. + * A couple of minor bug fixes. + Noteworthy changes in version 1.9.17 (2005-06-20) ------------------------------------------------- diff --git a/agent/t-protect.c b/agent/t-protect.c index 0cb8265ba..21cbe1160 100644 --- a/agent/t-protect.c +++ b/agent/t-protect.c @@ -72,6 +72,7 @@ test_agent_private_key_type (void) static void test_make_shadow_info (void) { +#if 0 static struct { const char *snstr; @@ -96,6 +97,7 @@ test_make_shadow_info (void) /* fixme: Need to compare the result but also need to check proper S-expression syntax. */ } +#endif } diff --git a/configure.ac b/configure.ac index fa686d0cb..9c63fcbea 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.18-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.18, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -36,7 +36,7 @@ NEED_LIBGCRYPT_VERSION=1.1.94 NEED_LIBASSUAN_VERSION=0.6.10 -NEED_KSBA_VERSION=0.9.11 +NEED_KSBA_VERSION=0.9.12 PACKAGE=$PACKAGE_NAME diff --git a/po/de.po b/po/de.po index bf90b9b58..04111ca63 100644 --- a/po/de.po +++ b/po/de.po @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" "POT-Creation-Date: 2005-06-16 09:12+0200\n" -"PO-Revision-Date: 2005-08-01 14:44+0200\n" +"PO-Revision-Date: 2005-08-01 15:09+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -521,7 +521,7 @@ msgstr "Alle Debug Flags setzen" #: kbx/kbxutil.c:107 msgid "Please report bugs to " -msgstr "Bite richten sie Berichte über Bugs (Softwarefehler) an " +msgstr "Bitte richten sie Berichte über Bugs (Softwarefehler) an " #: kbx/kbxutil.c:107 msgid ".\n" @@ -921,8 +921,7 @@ msgstr "Die vorhandene CRL ist zu alt" #: sm/certchain.c:607 msgid "please make sure that the \"dirmngr\" is properly installed\n" -msgstr "" -"Bite vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" +msgstr "Bitte vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" #: sm/certchain.c:612 #, c-format diff --git a/tools/ChangeLog b/tools/ChangeLog index e1dfce49d..7dc6d512e 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2005-08-01 Werner Koch <wk@g10code.com> + + * gpgsm-gencert.sh: Allow entering a keygrip to generate a CSR from + an existing key. + 2005-07-21 Werner Koch <wk@g10code.com> * gpgsm-gencert.sh: Reworked to allow for multiple email addresses diff --git a/tools/gpgsm-gencert.sh b/tools/gpgsm-gencert.sh index 44b06f3b3..3949f2361 100755 --- a/tools/gpgsm-gencert.sh +++ b/tools/gpgsm-gencert.sh @@ -84,11 +84,20 @@ query_user_menu() echo "You selected: $ANSWER" >&2 } -query_user_menu "Key type" "RSA" -KEY_TYPE=$ANSWER +query_user_menu "Key type" "RSA" "existing key" +if [ "$ANSWER" = "existing key" ]; then + # User requested to use an existing key; need to set some dummy defaults + KEY_TYPE=RSA + KEY_LENGTH=1024 + query_user "Keygrip " + KEY_GRIP=$ANSWER +else + KEY_TYPE=$ANSWER + query_user_menu "Key length" "1024" "2048" + KEY_LENGTH=$ANSWER + KEY_GRIP= +fi -query_user_menu "Key length" "1024" "2048" -KEY_LENGTH=$ANSWER query_user_menu "Key usage" "sign, encrypt" "sign" "encrypt" KEY_USAGE=$ANSWER @@ -137,6 +146,7 @@ Key-Length: $KEY_LENGTH Key-Usage: $KEY_USAGE Name-DN: $NAME EOF +[ -n "$KEY_GRIP" ] && echo "Key-Grip: $KEY_GRIP" [ -n "$EMAIL_ADDRESSES" ] && echo "$EMAIL_ADDRESSES" [ -n "$DNS_ADDRESSES" ] && echo "$DNS_ADDRESSES" [ -n "$URI_ADDRESSES" ] && echo "$URI_ADDRESSES" @@ -152,7 +162,7 @@ query_user_menu "Really create such a CSR?" "yes" "no" echo -e "$ASSUAN_COMMANDS" | \ - ./gpgsm --no-log-file --debug-level none --debug-none \ + gpgsm --no-log-file --debug-level none --debug-none \ --server 4< "$file_parameter" 5>"$outfile" >/dev/null cat "$outfile" -- cgit v1.2.3 From 0a09a6316ecd4b9fba707c7c1b7db4cfea7a15a0 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 Aug 2005 09:15:09 +0000 Subject: Use a default argument for --write-env-file. --- NEWS | 4 ++++ agent/ChangeLog | 4 ++++ agent/gpg-agent.c | 9 +++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index f05c17ea9..e51cadebf 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.9.19 +------------------------------------------------- + + Noteworthy changes in version 1.9.18 (2005-08-01) ------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index bcb00e341..adb7b1bb6 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2005-08-16 Werner Koch <wk@g10code.com> + + * gpg-agent.c (main): Use a default file name for --write-env-file. + 2005-07-25 Werner Koch <wk@g10code.com> * findkey.c (agent_public_key_from_file): Fixed array assignment. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 8732c98d7..b6a4f90a6 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -152,7 +152,7 @@ static ARGPARSE_OPTS opts[] = { { oAllowPresetPassphrase, "allow-preset-passphrase", 0, N_("allow presetting passphrase")}, { oSSHSupport, "enable-ssh-support", 0, N_("enable ssh-agent emulation") }, - { oWriteEnvFile, "write-env-file", 2, + { oWriteEnvFile, "write-env-file", 2|8, N_("|FILE|write environment settings also to FILE")}, {0} }; @@ -633,7 +633,12 @@ main (int argc, char **argv ) case oKeepDISPLAY: opt.keep_display = 1; break; case oSSHSupport: opt.ssh_support = 1; break; - case oWriteEnvFile: env_file_name = pargs.r.ret_str; break; + case oWriteEnvFile: + if (pargs.r_type) + env_file_name = pargs.r.ret_str; + else + env_file_name = make_filename ("~/.gpg-agent-info", NULL); + break; default : pargs.err = configfp? 1:2; break; } -- cgit v1.2.3 From 1b2f7cbe3ba731c5d94990b3f019b8c0bf641372 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 5 Sep 2005 14:36:36 +0000 Subject: Basically made Belgian EID cards work. Signature creation has not yet been tested. Also other changes to better cope with T=0 cards. --- scd/ChangeLog | 27 ++++++ scd/apdu.c | 45 ++++++++-- scd/apdu.h | 6 +- scd/app-p15.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++------- scd/iso7816.c | 55 +++++++++++- scd/iso7816.h | 3 + scd/pcsc-wrapper.c | 8 +- 7 files changed, 349 insertions(+), 44 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 970335aef..3e8292dee 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,30 @@ +2005-09-05 Werner Koch <wk@g10code.com> + + * iso7816.c (iso7816_select_path): New. + * app-p15.c (select_ef_by_path): Allow for direct path selection. + (app_select_p15): Try using the beigian variant of pkcs#15. + (read_home_df): New. + (read_ef_odf): Generalized. + (read_ef_tokeninfo): New. + (read_p15_info): Set serialnumber from TokenInfo. + (app_select_p15): Don't munge serialNumber - that must be done + only once. + + * iso7816.c (iso7816_read_binary): Use Le=0 when reading all + data. Handle 6C00 error and take 6B00 as indication for EOF. + * apdu.h (SW_EXACT_LENGTH_P): New. + * apdu.c (new_reader_slot, reset_pcsc_reader, pcsc_get_status) + (open_pcsc_reader): Set new reader state IS_T0. + (apdu_send_le): When doing T=0 make sure not to send Lc and Le. + Problem reported by Carl Meijer. + (apdu_send_direct): Initialize RESULTLEN. + * pcsc-wrapper.c (handle_status): Return the current protocol as + a new third word. + +2005-08-05 Werner Koch <wk@g10code.com> + + * apdu.c (open_rapdu_reader): Set the reader number. + 2005-07-05 Werner Koch <wk@g10code.com> * app-openpgp.c (do_readkey): Return a mallcoed copy of the key as diff --git a/scd/apdu.c b/scd/apdu.c index 79022f21b..678ea12d3 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * $Id$ */ @@ -126,6 +127,7 @@ struct reader_table_s { char *rdrname; /* Name of the connected reader or NULL if unknown. */ int last_status; int status; + int is_t0; /* True if we know that we are running T=0. */ unsigned char atr[33]; size_t atrlen; /* A zero length indicates that the ATR has not yet been read; i.e. the card is not @@ -275,6 +277,9 @@ long (* DLSTDCALL pcsc_set_timeout) (unsigned long context, unsigned long timeout); +/* Prototypes. */ +static int pcsc_get_status (int slot, unsigned int *status); + /* @@ -319,6 +324,7 @@ new_reader_slot (void) reader_table[reader].used = 1; reader_table[reader].last_status = 0; + reader_table[reader].is_t0 = 1; #ifdef NEED_PCSC_WRAPPER reader_table[reader].pcsc.req_fd = -1; reader_table[reader].pcsc.rsp_fd = -1; @@ -768,6 +774,7 @@ reset_pcsc_reader (int slot) size_t len; int i, n; unsigned char msgbuf[9]; + unsigned int dummy_status; int sw = SW_HOST_CARD_IO_ERROR; slotp = reader_table + slot; @@ -841,6 +848,9 @@ reset_pcsc_reader (int slot) } slotp->atrlen = len; + /* Read the status so that IS_T0 will be set. */ + pcsc_get_status (slot, &dummy_status); + return 0; command_failed: @@ -902,6 +912,7 @@ reset_pcsc_reader (int slot) if (atrlen >= DIM (reader_table[0].atr)) log_bug ("ATR returned by pcsc_status is too large\n"); reader_table[slot].atrlen = atrlen; + reader_table[slot].is_t0 = !!(card_protocol & PCSC_PROTOCOL_T0); return 0; #endif /* !NEED_PCSC_WRAPPER */ @@ -917,7 +928,7 @@ pcsc_get_status (int slot, unsigned int *status) size_t len, full_len; int i, n; unsigned char msgbuf[9]; - unsigned char buffer[12]; + unsigned char buffer[16]; int sw = SW_HOST_CARD_IO_ERROR; slotp = reader_table + slot; @@ -968,14 +979,20 @@ pcsc_get_status (int slot, unsigned int *status) full_len = len; - n = 8 < len ? 8 : len; - if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) || len != 8) + /* The current version returns 3 words but we allow also for old + versions returning only 2 words. */ + n = 12 < len ? 12 : len; + if ((i=readn (slotp->pcsc.rsp_fd, buffer, n, &len)) + || (len != 8 && len != 12)) { log_error ("error receiving PC/SC STATUS response: %s\n", i? strerror (errno) : "premature EOF"); goto command_failed; } + slotp->is_t0 = (len == 12 && !!(buffer[11] & PCSC_PROTOCOL_T0)); + + full_len -= len; /* Newer versions of the wrapper might send more status bytes. Read them. */ @@ -1296,6 +1313,7 @@ open_pcsc_reader (const char *portstr) size_t len; unsigned char msgbuf[9]; int err; + unsigned int dummy_status; int sw = SW_HOST_CARD_IO_ERROR; slot = new_reader_slot (); @@ -1440,7 +1458,7 @@ open_pcsc_reader (const char *portstr) slotp->last_status = 0; - /* The open fucntion may return a zero for the ATR length to + /* The open request may return a zero for the ATR length to indicate that no card is present. */ n = len; if (n) @@ -1463,6 +1481,9 @@ open_pcsc_reader (const char *portstr) reader_table[slot].send_apdu_reader = pcsc_send_apdu; reader_table[slot].dump_status_reader = dump_pcsc_reader_status; + /* Read the status so that IS_T0 will be set. */ + pcsc_get_status (slot, &dummy_status); + dump_reader_status (slot); return slot; @@ -1596,6 +1617,7 @@ open_pcsc_reader (const char *portstr) /* If we got to here we know that a card is present and usable. Thus remember this. */ reader_table[slot].last_status = (1|2|4| 0x8000); + reader_table[slot].is_t0 = !!(card_protocol & PCSC_PROTOCOL_T0); } } @@ -1997,6 +2019,7 @@ open_rapdu_reader (int portno, return -1; } + rapdu_set_reader (slotp->rapdu.handle, portno); rapdu_set_iofunc (slotp->rapdu.handle, readfnc, readfnc_value, @@ -2518,7 +2541,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, if (lc != -1 && (lc > 255 || lc < 0)) return SW_WRONG_LENGTH; - if (le != -1 && (le > 256 || le < 1)) + if (le != -1 && (le > 256 || le < 0)) return SW_WRONG_LENGTH; if ((!data && lc != -1) || (data && lc == -1)) return SW_HOST_INV_VALUE; @@ -2536,9 +2559,13 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, apdu[apdulen++] = lc; memcpy (apdu+apdulen, data, lc); apdulen += lc; + /* T=0 does not allow the use of Lc together with Le; thus + disable Le in this case. */ + if (reader_table[slot].is_t0) + le = -1; } if (le != -1) - apdu[apdulen++] = le; /* Truncation is okay becuase 0 means 256. */ + apdu[apdulen++] = le; /* Truncation is okay because 0 means 256. */ assert (sizeof (apdu) >= apdulen); /* As safeguard don't pass any garbage from the stack to the driver. */ memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); @@ -2736,14 +2763,14 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, if ((sw = trylock_slot (slot))) return sw; - /* We simply trucntate a too long APDU. */ + /* We simply trunctate a too long APDU. */ if (apdudatalen > sizeof apdu) apdudatalen = sizeof apdu; apdulen = apdudatalen; memcpy (apdu, apdudata, apdudatalen); class = apdulen? *apdu : 0; - + resultlen = RESULTLEN; rc = send_apdu (slot, apdu, apdulen, result, &resultlen); if (rc || resultlen < 2) { diff --git a/scd/apdu.h b/scd/apdu.h index e0f50b72b..45388fdd1 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * $Id$ */ @@ -41,6 +42,7 @@ enum { SW_RECORD_NOT_FOUND = 0x6a83, SW_REF_NOT_FOUND = 0x6a88, SW_BAD_P0_P1 = 0x6b00, + SW_EXACT_LENGTH = 0x6c00, SW_INS_NOT_SUP = 0x6d00, SW_CLA_NOT_SUP = 0x6e00, SW_SUCCESS = 0x9000, @@ -65,6 +67,8 @@ enum { }; +#define SW_EXACT_LENGTH_P(a) (((a)&~0xff) == SW_EXACT_LENGTH) + /* Note , that apdu_open_reader returns no status word but -1 on error. */ int apdu_open_reader (const char *portstr); diff --git a/scd/app-p15.c b/scd/app-p15.c index f03e5d5f0..c8d38850b 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -74,7 +74,17 @@ static struct #undef X -/* The Pin Types as defined in pkcs#15 v1.1 */ +/* The AID of PKCS15. */ +static char const pkcs15_aid[] = { 0xA0, 0, 0, 0, 0x63, + 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; + +/* The Belgian eID variant - they didn't understood why a shared AID + is useful for a standard. Oh well. */ +static char const pkcs15be_aid[] = { 0xA0, 0, 0, 0x01, 0x77, + 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; + + +/* The PIN types as defined in pkcs#15 v1.1 */ typedef enum { PIN_TYPE_BCD = 0, @@ -261,6 +271,9 @@ struct app_local_s /* The type of the card. */ card_type_t card_type; + /* Flag indicating whether we may use direct path selection. */ + int direct_path_selection; + /* Structure with the EFIDs of the objects described in the ODF file. */ struct @@ -276,6 +289,10 @@ struct app_local_s unsigned short auth_objects; } odf; + /* The PKCS#15 serialnumber from EF(TokeiNFo) or NULL. Malloced. */ + unsigned char *serialno; + size_t serialnolen; + /* Information on all certificates. */ cdf_object_t certificate_info; /* Information on all trusted certificates. */ @@ -363,6 +380,7 @@ do_deinit (app_t app) release_cdflist (app->app_local->useful_certificate_info); release_prkdflist (app->app_local->private_key_info); release_aodflist (app->app_local->auth_object_info); + xfree (app->app_local->serialno); xfree (app->app_local); app->app_local = NULL; } @@ -406,26 +424,44 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen) gpg_error_t err; int i, j; - /* FIXME: Need code to remember the last PATH so that we can decide - what select commands to send in case the path does not start off - with 3F00. We might also want to use direct path selection if - supported by the card. */ + if (!pathlen) + return gpg_error (GPG_ERR_INV_VALUE); + if (pathlen && *path != 0x3f00 ) log_debug ("WARNING: relative path selection not yet implemented\n"); - - for (i=0; i < pathlen; i++) + + if (app->app_local->direct_path_selection) { - err = iso7816_select_file (app->slot, path[i], - !(i+1 == pathlen), NULL, NULL); + err = iso7816_select_path (app->slot, path+1, pathlen-1, NULL, NULL); if (err) { - log_error ("error selecting part %d from path ", i); + log_error ("error selecting path "); for (j=0; j < pathlen; j++) log_printf ("%04hX", path[j]); log_printf (": %s\n", gpg_strerror (err)); return err; } } + else + { + /* FIXME: Need code to remember the last PATH so that we can decide + what select commands to send in case the path does not start off + with 3F00. We might also want to use direct path selection if + supported by the card. */ + for (i=0; i < pathlen; i++) + { + err = iso7816_select_file (app->slot, path[i], + !(i+1 == pathlen), NULL, NULL); + if (err) + { + log_error ("error selecting part %d from path ", i); + for (j=0; j < pathlen; j++) + log_printf ("%04hX", path[j]); + log_printf (": %s\n", gpg_strerror (err)); + return err; + } + } + } return 0; } @@ -586,12 +622,13 @@ read_ef_odf (app_t app, unsigned short odf_fid) } else if ( buflen >= 12 && (p[0] & 0xf0) == 0xA0 - && !memcmp (p+1, "\x0a\x30\x08\x04\x06\x3F\x00\x50\x15", 9) - && app->app_local->home_df == 0x5015 ) + && !memcmp (p+1, "\x0a\x30\x08\x04\x06\x3F\x00", 7) + && app->app_local->home_df == ((p[8]<<8)|p[9]) ) { - /* This format using a full path is used by a self-created - test card of mine. I have not checked whether this is - legal. We assume a home DF of 0x5015 here. */ + /* We only allow a full path if all files are at the same + level and below the home directory. The extend this we + would need to make use of new data type capable of + keeping a full path. */ offset = 10; } else @@ -2158,12 +2195,81 @@ TokenFlags ::= BIT STRING { */ -/* static gpg_error_t */ -/* read_ef_tokeninfo (app_t app) */ -/* { */ -/* unsigned short efid = 0x5032; */ -/* return 0; */ -/* } */ +static gpg_error_t +read_ef_tokeninfo (app_t app) +{ + gpg_error_t err; + unsigned char *buffer = NULL; + size_t buflen; + const unsigned char *p; + size_t n, objlen, hdrlen; + int class, tag, constructed, ndef; + unsigned long ul; + + err = select_and_read_binary (app->slot, 0x5032, "TokenInfo", + &buffer, &buflen); + if (err) + return err; + + p = buffer; + n = buflen; + + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > n || tag != TAG_SEQUENCE)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + { + log_error ("error parsing TokenInfo: %s\n", gpg_strerror (err)); + goto leave; + } + + n = objlen; + + /* Version. */ + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > n || tag != TAG_INTEGER)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto leave; + + for (ul=0; objlen; objlen--) + { + ul <<= 8; + ul |= (*p++) & 0xff; + n--; + } + if (ul) + { + log_error ("invalid version %lu in TokenInfo\n", ul); + err = gpg_error (GPG_ERR_INV_OBJ); + goto leave; + } + + /* serialNumber. */ + err = parse_ber_header (&p, &n, &class, &tag, &constructed, + &ndef, &objlen, &hdrlen); + if (!err && (objlen > n || tag != TAG_OCTET_STRING || !objlen)) + err = gpg_error (GPG_ERR_INV_OBJ); + if (err) + goto leave; + + xfree (app->app_local->serialno); + app->app_local->serialno = xtrymalloc (objlen); + if (!app->app_local->serialno) + { + err = gpg_error_from_errno (errno); + goto leave; + } + memcpy (app->app_local->serialno, p, objlen); + app->app_local->serialnolen = objlen; + log_printhex ("Serialnumber from EF(TokenInfo) is:", p, objlen); + + leave: + xfree (buffer); + return err; +} /* Get all the basic information from the pkcs#15 card, check the @@ -2174,11 +2280,25 @@ read_p15_info (app_t app) { gpg_error_t err; - /* Fixme: We might need to read the tokeninfo to get a non-standard - ODF FID. */ - + if (!read_ef_tokeninfo (app)) + { + /* If we don't have a serial number yet but the TokenInfo provides + one, use that. */ + if (!app->serialno && app->app_local->serialno) + { + app->serialno = app->app_local->serialno; + app->serialnolen = app->app_local->serialnolen; + app->app_local->serialno = NULL; + app->app_local->serialnolen = 0; + err = app_munge_serialno (app); + if (err) + return err; + } + } + /* Read the ODF so that we know the location of all directory files. */ + /* Fixme: We might need to get a non-standard ODF FID from TokenInfo. */ err = read_ef_odf (app, 0x5031); if (err) return err; @@ -2895,22 +3015,88 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, } + +/* Assume that EF(DIR) has been selected. Read its content and figure + out the home EF of pkcs#15. Return that home DF or 0 if not + found. */ +static unsigned short +read_home_df (int slot) +{ + gpg_error_t err; + unsigned char *buffer; + const unsigned char *p, *pp; + size_t buflen, n, nn; + unsigned short result = 0; + + err = iso7816_read_binary (slot, 0, 0, &buffer, &buflen); + if (err) + { + log_error ("error reading EF{DIR}: %s\n", gpg_strerror (err)); + return 0; + } + + /* FIXME: We need to scan all records. */ + p = find_tlv (buffer, buflen, 0x61, &n); + if (p && n) + { + pp = find_tlv (p, n, 0x4f, &nn); + if (pp + && ((nn == sizeof pkcs15_aid && !memcmp (pp, pkcs15_aid, nn)) + ||(nn == sizeof pkcs15be_aid && !memcmp (pp, pkcs15be_aid, nn)))) + { + pp = find_tlv (p, n, 0x50, &nn); + if (pp) /* fixme: Filter log value? */ + log_info ("pkcs#15 application label from EF(DIR) is `%.*s'\n", + (int)nn, pp); + pp = find_tlv (p, n, 0x51, &nn); + if (pp && nn == 4 && *pp == 0x3f && !pp[1]) + { + result = ((pp[2] << 8) | pp[3]); + log_info ("pkcs#15 application directory is 0x%04hX\n", result); + } + } + } + xfree (buffer); + return result; +} -/* Select the PKCS#15 application on the card in SLOT. */ +/* + Select the PKCS#15 application on the card in SLOT. + */ gpg_error_t app_select_p15 (app_t app) { - static char const aid[] = { 0xA0, 0, 0, 0, 0x63, - 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; int slot = app->slot; int rc; unsigned short def_home_df = 0; card_type_t card_type = CARD_TYPE_UNKNOWN; + int direct = 0; - rc = iso7816_select_application (slot, aid, sizeof aid); + rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid); if (rc) - { + rc = iso7816_select_application (slot, pkcs15be_aid, sizeof pkcs15be_aid); + if (rc) + { /* Not found: Try to locate it from 2F00. We use direct path + selection here because it seems that the Belgian eID card + does only allow for that. Many other cards supports this + selection method too. */ + unsigned short path[1] = { 0x2f00 }; + + rc = iso7816_select_path (app->slot, path, 1, NULL, NULL); + if (!rc) + { + direct = 1; + def_home_df = read_home_df (slot); + if (def_home_df) + { + path[0] = def_home_df; + rc = iso7816_select_path (app->slot, path, 1, NULL, NULL); + } + } + } + if (rc) + { /* Still not found: Try the default DF. */ def_home_df = 0x5015; rc = iso7816_select_file (slot, def_home_df, 1, NULL, NULL); } @@ -2958,6 +3144,9 @@ app_select_p15 (app_t app) the common APP structure. */ app->app_local->card_type = card_type; + /* Store whether we may and should use direct path selection. */ + app->app_local->direct_path_selection = direct; + /* Read basic information and thus check whether this is a real card. */ rc = read_p15_info (app); @@ -2989,8 +3178,6 @@ app_select_p15 (app_t app) app->serialno = p; } } - else /* Use standard munging code. */ - rc = app_munge_serialno (app); app->fnc.deinit = do_deinit; app->fnc.learn_status = do_learn_status; diff --git a/scd/iso7816.c b/scd/iso7816.c index 742ed9433..484906251 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -77,6 +77,7 @@ map_sw (int sw) case SW_RECORD_NOT_FOUND:ec= GPG_ERR_NOT_FOUND; break; case SW_REF_NOT_FOUND: ec = GPG_ERR_NO_OBJ; break; case SW_BAD_P0_P1: ec = GPG_ERR_INV_VALUE; break; + case SW_EXACT_LENGTH: ec = GPG_ERR_INV_VALUE; break; case SW_INS_NOT_SUP: ec = GPG_ERR_CARD; break; case SW_CLA_NOT_SUP: ec = GPG_ERR_CARD; break; case SW_SUCCESS: ec = 0; break; @@ -161,6 +162,39 @@ iso7816_select_file (int slot, int tag, int is_dir, } +/* Do a select file command with a direct path. */ +gpg_error_t +iso7816_select_path (int slot, const unsigned short *path, size_t pathlen, + unsigned char **result, size_t *resultlen) +{ + int sw, p0, p1; + unsigned char buffer[100]; + int buflen; + + if (result || resultlen) + { + *result = NULL; + *resultlen = 0; + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + } + + if (pathlen/2 >= sizeof buffer) + return gpg_error (GPG_ERR_TOO_LARGE); + + for (buflen = 0; pathlen; pathlen--, path++) + { + buffer[buflen++] = (*path >> 8); + buffer[buflen++] = *path; + } + + p0 = 0x08; + p1 = 0x0c; /* No FC return. */ + sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, + p0, p1, buflen, (char*)buffer ); + return map_sw (sw); +} + + /* This is a private command currently only working for TCOS cards. */ gpg_error_t iso7816_list_directory (int slot, int list_dirs, @@ -524,8 +558,10 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax, { buffer = NULL; bufferlen = 0; - /* Fixme: Either the ccid driver or the TCOS cards have problems - with an Le of 0. */ + /* Note, that we to set N to 254 due to problems either with the + ccid driver or some TCOS cards. It actually should be 0 + which is the official ISO value to read a variable length + object. */ if (read_all || nmax > 254) n = 254; else @@ -533,6 +569,21 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax, sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, n, &buffer, &bufferlen); + if ( SW_EXACT_LENGTH_P(sw) ) + { + n = (sw & 0x00ff); + sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY, + ((offset>>8) & 0xff), (offset & 0xff) , -1, NULL, + n, &buffer, &bufferlen); + } + + if (*result && sw == SW_BAD_P0_P1) + { + /* Bad Parameter means that the offset is outside of the + EF. When reading all data we take this as an indication + for EOF. */ + break; + } if (sw != SW_SUCCESS && sw != SW_EOF_REACHED) { diff --git a/scd/iso7816.h b/scd/iso7816.h index b9ba1800b..828fabb01 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -33,6 +33,9 @@ gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen); gpg_error_t iso7816_select_file (int slot, int tag, int is_dir, unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_select_path (int slot, + const unsigned short *path, size_t pathlen, + unsigned char **result, size_t *resultlen); gpg_error_t iso7816_list_directory (int slot, int list_dirs, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_verify (int slot, diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c index 21af16fba..f149e785a 100644 --- a/scd/pcsc-wrapper.c +++ b/scd/pcsc-wrapper.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* @@ -587,6 +588,11 @@ handle_status (unsigned char *argbuf, size_t arglen) buf[5] = (rdrstates[0].event_state >> 16); buf[6] = (rdrstates[0].event_state >> 8); buf[7] = (rdrstates[0].event_state >> 0); + /* The third word is the protocol. */ + buf[8] = (pcsc_protocol >> 24); + buf[9] = (pcsc_protocol >> 16); + buf[10] = (pcsc_protocol >> 8); + buf[11] = (pcsc_protocol); request_succeeded (buf, 8); } -- cgit v1.2.3 From 12f7e943cca25caffa5969fdd13f2a3009f7bbe4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Sep 2005 10:25:41 +0000 Subject: Changed license of this parser to LPGL. --- tools/ChangeLog | 4 ++++ tools/rfc822parse.c | 48 ++++++++++++++++++++++++------------------------ tools/rfc822parse.h | 25 +++++++++++++------------ 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 7dc6d512e..027289ea7 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-09-06 Werner Koch <wk@g10code.com> + + * rfc822parse.c, rfc822parse.h: Changed license to LGPL. + 2005-08-01 Werner Koch <wk@g10code.com> * gpgsm-gencert.sh: Allow entering a keygrip to generate a CSR from diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index 3379886de..61377e7e6 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -3,31 +3,31 @@ * Copyright (C) 2003, 2004 g10 Code GmbH * * 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 is distributed in the hope that it will be useful, + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ -/* According to RFC822 binary 0 are allowed at many places. We - * do not handle this correct especially in the field parsing code. It - * should be easy to fix and the API provides a interfcaes which returns - * the length but in addition makes sure that returned strings are always - * ended by a \0. +/* According to RFC822 binary zeroes are allowed at many places. We do + * not handle this correct especially in the field parsing code. It + * should be easy to fix and the API provides a interfaces which + * returns the length but in addition makes sure that returned strings + * are always ended by a \0. * * Furthermore, the case of field names is changed and thus it is not * always a good idea to use these modified header * lines (e.g. signatures may break). - * */ #ifdef HAVE_CONFIG_H @@ -44,13 +44,13 @@ #include "rfc822parse.h" enum token_type -{ - tSPACE, - tATOM, - tQUOTED, - tDOMAINLIT, - tSPECIAL -}; + { + tSPACE, + tATOM, + tQUOTED, + tDOMAINLIT, + tSPECIAL + }; /* For now we directly use our TOKEN as the parse context */ typedef struct rfc822parse_field_context *TOKEN; diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h index a7ed5b4ec..8a56c51cb 100644 --- a/tools/rfc822parse.h +++ b/tools/rfc822parse.h @@ -3,18 +3,19 @@ * Copyright (C) 2003, g10 Code GmbH * * 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 + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef RFC822PARSE_H -- cgit v1.2.3 From d9d2d3da9152ed52abb73bd39311c6b0e01450e3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Sep 2005 18:42:13 +0000 Subject: The BELPIC card does now work. --- NEWS | 2 + THANKS | 1 + configure.ac | 2 +- doc/ChangeLog | 5 + doc/gnupg.texi | 16 ++- doc/gpg-agent.texi | 6 +- doc/tools.texi | 45 +++++++- po/de.po | 305 +++++++++++++++++++++++++++-------------------------- scd/ChangeLog | 6 ++ scd/app-p15.c | 158 +++++++++++++++++++++------ scd/command.c | 2 +- 11 files changed, 352 insertions(+), 196 deletions(-) diff --git a/NEWS b/NEWS index e51cadebf..75410e8d5 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ Noteworthy changes in version 1.9.19 ------------------------------------------------- + * The Belgian eID card is now supported. + Noteworthy changes in version 1.9.18 (2005-08-01) ------------------------------------------------- diff --git a/THANKS b/THANKS index 408497046..0f31642ac 100644 --- a/THANKS +++ b/THANKS @@ -1,6 +1,7 @@ Alexander Belopolsky belopolsky at mac.com Andrew J. Schorr aschorr at telemetry-investments.com +Carl Meijer carlm at prism.co.za Charly Avital shavital at mac.com Kazu Yamamoto kazu at iij.ad.jp Michael Nottebrock michaelnottebrock at gmx.net diff --git a/configure.ac b/configure.ac index 9c63fcbea..030643315 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.18, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.19-cvs, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. diff --git a/doc/ChangeLog b/doc/ChangeLog index c4d263513..d93a473a2 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2005-08-16 Werner Koch <wk@g10code.com> + + * gpg-agent.texi (Agent Options): Note default file name for + --write-env-file. + 2005-06-03 Werner Koch <wk@g10code.com> * debugging.texi (Architecture Details): New section, mostly empty. diff --git a/doc/gnupg.texi b/doc/gnupg.texi index d92f01cd9..efa54bd14 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -3,6 +3,18 @@ @setfilename gnupg.info @include version.texi @settitle Using the GNU Privacy Guard + +@c A couple of macros with no effect on texinfo +@c but used by the yat2m processor. +@macro manpage {a} +@end macro +@macro mansect {a} +@end macro +@macro manpause +@end macro +@macro mancont +@end macro + @c Create a separate index for command line options. @defcodeindex op @c Merge the standard indexes into a single one. @@ -13,8 +25,8 @@ @syncodeindex tp cp @c %**end of header @copying -This is the @cite{The GNU Privacy Guard Manual} -(version @value{VERSION}, @value{UPDATED}). +This is the @cite{The GNU Privacy Guard Manual} (version +@value{VERSION}, @value{UPDATED}). @iftex Published by the Free Software Foundation@* diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 144745b4c..066f8e937 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -253,8 +253,9 @@ Often it is required to connect to the agent from a process not being an inferior of @command{gpg-agent} and thus the environment variable with the socket name is not available. To help setting up those variables in other sessions, this option may be used to write the information into -@var{file}. The format is suitable to be evaluated by a Bourne shell -like in this simple example: +@var{file}. If @var{file} is not specified the default name +@file{$@{HOME@}/.gpg-agent-info} will be used. The format is suitable +to be evaluated by a Bourne shell like in this simple example: @example eval `cat @var{file}` @@ -262,6 +263,7 @@ eval `cut -d= -f 1 < @var{file} | xargs echo export` @end example + @item --no-grab @opindex no-grab Tell the pinentryo not to grab the keyboard and mouse. This option diff --git a/doc/tools.texi b/doc/tools.texi index b2463c351..850202bd5 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -20,19 +20,29 @@ GnuPG comes with a couple of smaller tools: @c @c WATCHGNUPG @c +@manpage watchgnupg.1 @node watchgnupg @section Read logs from a socket +@ifset manverb + watchgnupg \- Read and print logs from a socket +@end ifset +@mansect description Most of the main utilities are able to write there log files to a Unix Domain socket if configured that way. @command{watchgnupg} is a simple listener for such a socket. It ameliorates the output with a time stamp and makes sure that long lines are not interspersed with log output from other utilities. +@manpause @noindent @command{watchgnupg} is commonly invoked as -@samp{watchgnupg --force ~/.gnupg/S.log} +@mansect synopsis +@example +watchgnupg --force ~/.gnupg/S.log +@end example +@manpause @noindent This starts it on the current terminal for listening on the socket @@ -42,6 +52,7 @@ This starts it on the current terminal for listening on the socket @command{watchgnupg} understands these options: @table @gnupgtabopt +@mansect options @item --force @opindex force @@ -59,15 +70,21 @@ print version of the program and exit @opindex help Display a brief help page and exit +@manpause @end table @c @c ADDGNUPGHOME @c +@manpage addgnupghome.8 @node addgnupghome @section Create .gnupg home directories. +@ifset manverb + addgnupghome \- Create .gnupg home directories +@end ifset +@mansect description If GnuPG is installed on a system with existing user accounts, it is sometimes required to populate the GnuPG home directory with existing files. Especially a @file{trustlist.txt} and a keybox with some @@ -76,18 +93,27 @@ by copying all files from @file{/etc/skel/.gnupg} to the home directories of the accounts given on the command line. It takes care not to overwrite existing GnuPG home directories. +@manpause @noindent @command{addgnupghome} is invoked by root as: -@samp{addgnupghome account1 account2 ... accountn} +@mansect synopsis +@example +addgnupghome account1 account2 ... accountn +@end example @c @c GPGCONF @c +@manpage gpgconf.1 @node gpgconf @section Modify .gnupg home directories. +@ifset manverb + gpgconf \- Modify .gnupg home directories +@end ifset +@mansect description The @command{gpgconf} is a utility to automatically and reasonable safely query and modify configuration files in the @file{.gnupg} home directory. It is designed not to be invoked manually by the user, but @@ -121,6 +147,7 @@ changes can then be made active with @command{gpgconf} again. Such a program that uses @command{gpgconf} in this way will be called GUI throughout this section. +@manpause @menu * Invoking gpgconf:: List of all commands and options. * Format conventions:: Formatting conventions relevant for all commands. @@ -133,9 +160,13 @@ throughout this section. @node Invoking gpgconf @subsection Invoking gpgconf +@mansect commands One of the following commands must be given: +@manpause @table @gnupgtabopt +@mancont + @item --list-components List all components. This is the default command used if none is specified. @@ -145,11 +176,16 @@ List all options of the component @var{component}. @item --change-options @var{component} Change the options of the component @var{component}. +@manpause @end table +@mansect options + The following options may be used: +@manpause @table @gnupgtabopt +@mancont @c FIXME: Not yet supported. @c @item -o @var{file} @c @itemx --output @var{file} @@ -176,6 +212,7 @@ changing. This means that the changes will take effect at run-time, as far as this is possible. Otherwise, they will take effect at the next start of the respective backend programs. +@manpause @end table @@ -295,6 +332,7 @@ the locale environment of the @command{gpgconf} program. @c to change it via the command line? +@mansect usage @node Listing components @subsection Listing components @@ -580,6 +618,7 @@ $ echo 'force:16:' | gpgconf --change-options dirmngr The @code{--runtime} option can influence when the changes take effect. +@manpause @c @c GPGSM-GENCERT.SH @c @@ -587,7 +626,7 @@ effect. @section Generate an X.509 certificate request This is a simple tool to interactivly generate a certificate request -whicl will be printed to stdout. +which will be printed to stdout. @noindent @command{gpgsm-gencert.sh} is invoked as: diff --git a/po/de.po b/po/de.po index 04111ca63..69606fa8b 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-06-16 09:12+0200\n" -"PO-Revision-Date: 2005-08-01 15:09+0200\n" +"POT-Creation-Date: 2005-09-06 20:01+0200\n" +"PO-Revision-Date: 2005-08-02 17:02+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -34,12 +34,12 @@ msgstr "Im Server Modus ausführen" msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausführen" -#: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:105 sm/gpgsm.c:329 +#: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:105 sm/gpgsm.c:331 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausführlich" -#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:106 sm/gpgsm.c:330 +#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:106 sm/gpgsm.c:332 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" @@ -63,7 +63,7 @@ msgstr "Im Vordergrund laufen lassen" msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:123 scd/scdaemon.c:118 sm/gpgsm.c:332 +#: agent/gpg-agent.c:123 scd/scdaemon.c:118 sm/gpgsm.c:334 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" @@ -116,12 +116,12 @@ msgid "|FILE|write environment settings also to FILE" msgstr "|DATEI|Schreibe die Umgebungsvariabeln auf DATEI" #: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:183 -#: sm/gpgsm.c:503 tools/gpgconf.c:85 +#: sm/gpgsm.c:507 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" #: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:183 -#: sm/gpgsm.c:503 tools/gpgconf.c:85 +#: sm/gpgsm.c:507 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -137,123 +137,123 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlüssel für GnuPG\n" -#: agent/gpg-agent.c:311 scd/scdaemon.c:257 sm/gpgsm.c:632 +#: agent/gpg-agent.c:311 scd/scdaemon.c:257 sm/gpgsm.c:636 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungültige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:482 agent/protect-tool.c:1072 kbx/kbxutil.c:431 -#: scd/scdaemon.c:349 sm/gpgsm.c:753 +#: scd/scdaemon.c:349 sm/gpgsm.c:757 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (benötigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:574 scd/scdaemon.c:424 sm/gpgsm.c:854 +#: agent/gpg-agent.c:574 scd/scdaemon.c:424 sm/gpgsm.c:858 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:579 agent/gpg-agent.c:1085 scd/scdaemon.c:429 -#: sm/gpgsm.c:858 +#: agent/gpg-agent.c:579 agent/gpg-agent.c:1090 scd/scdaemon.c:429 +#: sm/gpgsm.c:862 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:587 scd/scdaemon.c:437 sm/gpgsm.c:865 +#: agent/gpg-agent.c:587 scd/scdaemon.c:437 sm/gpgsm.c:869 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:879 +#: agent/gpg-agent.c:884 #, c-format msgid "error creating `%s': %s\n" msgstr "Fehler beim Erstellen von `%s': %s\n" -#: agent/gpg-agent.c:1135 agent/gpg-agent.c:1238 agent/gpg-agent.c:1242 -#: agent/gpg-agent.c:1278 agent/gpg-agent.c:1282 scd/scdaemon.c:900 +#: agent/gpg-agent.c:1140 agent/gpg-agent.c:1243 agent/gpg-agent.c:1247 +#: agent/gpg-agent.c:1283 agent/gpg-agent.c:1287 scd/scdaemon.c:902 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstellt werden: %s\n" -#: agent/gpg-agent.c:1149 scd/scdaemon.c:914 +#: agent/gpg-agent.c:1154 scd/scdaemon.c:916 msgid "name of socket too long\n" msgstr "Der Name des Sockets ist zu lang\n" -#: agent/gpg-agent.c:1175 scd/scdaemon.c:940 +#: agent/gpg-agent.c:1180 scd/scdaemon.c:942 #, c-format msgid "can't create socket: %s\n" msgstr "Socket kann nicht erzeugt werden: %s\n" -#: agent/gpg-agent.c:1204 scd/scdaemon.c:969 +#: agent/gpg-agent.c:1209 scd/scdaemon.c:971 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n" -#: agent/gpg-agent.c:1212 scd/scdaemon.c:977 +#: agent/gpg-agent.c:1217 scd/scdaemon.c:979 #, c-format msgid "listen() failed: %s\n" msgstr "Der listen() Aufruf ist fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1218 scd/scdaemon.c:983 +#: agent/gpg-agent.c:1223 scd/scdaemon.c:985 #, c-format msgid "listening on socket `%s'\n" msgstr "Es wird auf Socket `%s' gehört\n" -#: agent/gpg-agent.c:1246 agent/gpg-agent.c:1288 +#: agent/gpg-agent.c:1251 agent/gpg-agent.c:1293 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/gpg-agent.c:1294 +#: agent/gpg-agent.c:1299 #, c-format msgid "stat() failed for `%s': %s\n" msgstr "stat() Aufruf für `%s' fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1298 +#: agent/gpg-agent.c:1303 #, c-format msgid "can't use `%s' as home directory\n" msgstr "Die Datei `%s' kann nicht als Home-Verzeichniss benutzt werden\n" -#: agent/gpg-agent.c:1396 +#: agent/gpg-agent.c:1401 #, c-format msgid "handler 0x%lx for fd %d started\n" msgstr "Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1406 +#: agent/gpg-agent.c:1411 #, c-format msgid "handler 0x%lx for fd %d terminated\n" msgstr "Handhabungsroutine 0x%lx für den fd %d beendet\n" -#: agent/gpg-agent.c:1420 +#: agent/gpg-agent.c:1425 #, c-format msgid "ssh handler 0x%lx for fd %d started\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1427 +#: agent/gpg-agent.c:1432 #, c-format msgid "ssh handler 0x%lx for fd %d terminated\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d beendet\n" -#: agent/gpg-agent.c:1521 scd/scdaemon.c:1099 +#: agent/gpg-agent.c:1526 scd/scdaemon.c:1101 #, c-format msgid "pth_select failed: %s - waiting 1s\n" msgstr "pth_select() Aufruf fehlgeschlagen: %s - warte 1s\n" -#: agent/gpg-agent.c:1605 scd/scdaemon.c:1156 +#: agent/gpg-agent.c:1610 scd/scdaemon.c:1158 #, c-format msgid "%s %s stopped\n" msgstr "%s %s angehalten\n" -#: agent/gpg-agent.c:1626 +#: agent/gpg-agent.c:1631 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1636 common/simple-pwquery.c:323 sm/call-agent.c:143 +#: agent/gpg-agent.c:1641 common/simple-pwquery.c:323 sm/call-agent.c:143 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1648 common/simple-pwquery.c:335 sm/call-agent.c:155 +#: agent/gpg-agent.c:1653 common/simple-pwquery.c:335 sm/call-agent.c:155 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht unterstützt\n" @@ -284,7 +284,7 @@ msgid "" "Please enter the passphrase to protect the imported object within the GnuPG " "system." msgstr "" -"Bitte geben Sie die Passphrase ein, um das importierte Objket im GnuPG " +"Bitte geben Sie die Passphrase ein, um das importierte Objekt im GnuPG " "System zu schützen." #: agent/protect-tool.c:1214 agent/genkey.c:110 agent/genkey.c:218 @@ -476,11 +476,11 @@ msgstr "Kommunikationsproblem mit gpg-agent\n" msgid "problem setting the gpg-agent options\n" msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: common/simple-pwquery.c:526 common/simple-pwquery.c:592 +#: common/simple-pwquery.c:526 common/simple-pwquery.c:614 msgid "canceled by user\n" msgstr "Vom Benutzer abgebrochen\n" -#: common/simple-pwquery.c:533 common/simple-pwquery.c:598 +#: common/simple-pwquery.c:533 common/simple-pwquery.c:620 msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" @@ -489,7 +489,7 @@ msgstr "Problem mit dem Agenten\n" msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:68 sm/gpgsm.c:237 tools/gpgconf.c:53 +#: kbx/kbxutil.c:68 sm/gpgsm.c:239 tools/gpgconf.c:53 msgid "" "@Commands:\n" " " @@ -497,7 +497,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:76 sm/gpgsm.c:272 tools/gpgconf.c:59 +#: kbx/kbxutil.c:76 sm/gpgsm.c:274 tools/gpgconf.c:59 msgid "" "@\n" "Options:\n" @@ -507,7 +507,7 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:83 sm/gpgsm.c:337 tools/gpgconf.c:64 +#: kbx/kbxutil.c:83 sm/gpgsm.c:340 tools/gpgconf.c:64 msgid "do not make any changes" msgstr "Keine Änderungen durchführen" @@ -543,7 +543,7 @@ msgstr "" msgid "run in multi server mode (foreground)" msgstr "Im Multiserver Modus ausführen" -#: scd/scdaemon.c:109 sm/gpgsm.c:349 +#: scd/scdaemon.c:109 sm/gpgsm.c:352 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" @@ -579,18 +579,18 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon für GnuPG\n" -#: scd/scdaemon.c:656 +#: scd/scdaemon.c:658 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszuführen\n" -#: scd/scdaemon.c:997 +#: scd/scdaemon.c:999 #, c-format msgid "handler for fd %d started\n" msgstr "Handhabungsroutine für fd %d gestartet\n" -#: scd/scdaemon.c:1002 +#: scd/scdaemon.c:1004 #, c-format msgid "handler for fd %d terminated\n" msgstr "Handhabungsroutine für den fd %d beendet\n" @@ -610,47 +610,47 @@ msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" msgid "reading public key failed: %s\n" msgstr "Fehler beim Lesen des öffentlichen Schlüssels: %s\n" -#: scd/app-openpgp.c:986 scd/app-openpgp.c:1910 +#: scd/app-openpgp.c:986 scd/app-openpgp.c:1917 msgid "response does not contain the public key data\n" msgstr "Die Antwort enthält keine Public Key Daten\n" -#: scd/app-openpgp.c:994 scd/app-openpgp.c:1918 +#: scd/app-openpgp.c:994 scd/app-openpgp.c:1925 msgid "response does not contain the RSA modulus\n" msgstr "Die Antwort enthält keinen RSA Modulus\n" -#: scd/app-openpgp.c:1003 scd/app-openpgp.c:1928 +#: scd/app-openpgp.c:1003 scd/app-openpgp.c:1935 msgid "response does not contain the RSA public exponent\n" msgstr "Die Antwort enthält keinen öffenlichen RSA Exponent\n" -#: scd/app-openpgp.c:1259 scd/app-openpgp.c:1347 scd/app-openpgp.c:2150 +#: scd/app-openpgp.c:1266 scd/app-openpgp.c:1354 scd/app-openpgp.c:2157 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:1265 scd/app-openpgp.c:1353 scd/app-openpgp.c:2156 +#: scd/app-openpgp.c:1272 scd/app-openpgp.c:1360 scd/app-openpgp.c:2163 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" msgstr "Die PIN für den CHV%d ist zu kurz; Mindestlänge ist %d\n" -#: scd/app-openpgp.c:1274 scd/app-openpgp.c:1288 scd/app-openpgp.c:1363 -#: scd/app-openpgp.c:2165 scd/app-openpgp.c:2179 +#: scd/app-openpgp.c:1281 scd/app-openpgp.c:1295 scd/app-openpgp.c:1370 +#: scd/app-openpgp.c:2172 scd/app-openpgp.c:2186 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prüfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:1311 +#: scd/app-openpgp.c:1318 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:1326 scd/app-openpgp.c:2385 +#: scd/app-openpgp.c:1333 scd/app-openpgp.c:2392 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:1332 scd/app-openpgp.c:2394 +#: scd/app-openpgp.c:1339 scd/app-openpgp.c:2401 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:1337 +#: scd/app-openpgp.c:1344 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" @@ -659,105 +659,105 @@ msgstr "" #. TRANSLATORS: Do not translate the "|A|" prefix but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1344 +#: scd/app-openpgp.c:1351 msgid "|A|Admin PIN" msgstr "|A|Admin PIN" #. TRANSLATORS: Do not translate the "|*|" prefixes but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1493 +#: scd/app-openpgp.c:1500 msgid "|AN|New Admin PIN" msgstr "|AN|Neue Admin PIN" -#: scd/app-openpgp.c:1493 +#: scd/app-openpgp.c:1500 msgid "|N|New PIN" msgstr "|N|Neue PIN" -#: scd/app-openpgp.c:1497 +#: scd/app-openpgp.c:1504 #, c-format msgid "error getting new PIN: %s\n" msgstr "Fehler beim Holen der neuen PIN: %s\n" -#: scd/app-openpgp.c:1547 scd/app-openpgp.c:1996 +#: scd/app-openpgp.c:1554 scd/app-openpgp.c:2003 msgid "error reading application data\n" msgstr "Fehler beim Lesen der Anwendungsdaten\n" -#: scd/app-openpgp.c:1553 scd/app-openpgp.c:2003 +#: scd/app-openpgp.c:1560 scd/app-openpgp.c:2010 msgid "error reading fingerprint DO\n" msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" -#: scd/app-openpgp.c:1563 +#: scd/app-openpgp.c:1570 msgid "key already exists\n" msgstr "Schlüssel existiert bereits\n" -#: scd/app-openpgp.c:1567 +#: scd/app-openpgp.c:1574 msgid "existing key will be replaced\n" msgstr "Existierender Schlüssel wird ersetzt\n" -#: scd/app-openpgp.c:1569 +#: scd/app-openpgp.c:1576 msgid "generating new key\n" msgstr "Neuer Schlüssel wird erzeugt\n" -#: scd/app-openpgp.c:1736 +#: scd/app-openpgp.c:1743 msgid "creation timestamp missing\n" msgstr "Erzeugungsdatum fehlt\n" -#: scd/app-openpgp.c:1743 +#: scd/app-openpgp.c:1750 #, c-format msgid "RSA modulus missing or not of size %d bits\n" msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1750 +#: scd/app-openpgp.c:1757 #, c-format msgid "RSA public exponent missing or larger than %d bits\n" msgstr "Der öffentliche RSA Exponent fehlt oder ist länger als %d Bits\n" -#: scd/app-openpgp.c:1758 scd/app-openpgp.c:1765 +#: scd/app-openpgp.c:1765 scd/app-openpgp.c:1772 #, c-format msgid "RSA prime %s missing or not of size %d bits\n" msgstr "Die RSA Primzahl %s fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1828 +#: scd/app-openpgp.c:1835 #, c-format msgid "failed to store the key: %s\n" msgstr "Fehler beim Speichern des Schlüssels: %s\n" -#: scd/app-openpgp.c:1887 +#: scd/app-openpgp.c:1894 msgid "please wait while key is being generated ...\n" msgstr "Bitte warten bis der Schlüssel erzeugt wurde ...\n" -#: scd/app-openpgp.c:1901 +#: scd/app-openpgp.c:1908 msgid "generating key failed\n" msgstr "Fehler beim Erzeugen des Schlüssels\n" -#: scd/app-openpgp.c:1904 +#: scd/app-openpgp.c:1911 #, c-format msgid "key generation completed (%d seconds)\n" msgstr "Schlüsselerzeugung vollendet (%d Sekunden)\n" -#: scd/app-openpgp.c:1961 +#: scd/app-openpgp.c:1968 msgid "invalid structure of OpenPGP card (DO 0x93)\n" msgstr "Ungültige Struktur der OpenPGP Karte (DO 0x93)\n" -#: scd/app-openpgp.c:2130 +#: scd/app-openpgp.c:2137 #, c-format msgid "signatures created so far: %lu\n" msgstr "Anzahl bereits erzeugter Signaturen: %lu\n" -#: scd/app-openpgp.c:2138 +#: scd/app-openpgp.c:2145 #, c-format msgid "||Please enter the PIN%%0A[sigs done: %lu]" msgstr "||Bitte geben Sie die PIN ein%%0A[Sigs bisher: %lu]" -#: scd/app-openpgp.c:2399 +#: scd/app-openpgp.c:2406 msgid "" "verification of Admin PIN is currently prohibited through this command\n" msgstr "" "Die Überprüfung der Admin PIN is momentan durch ein Kommando verboten " "worden\n" -#: scd/app-openpgp.c:2470 scd/app-openpgp.c:2480 +#: scd/app-openpgp.c:2477 scd/app-openpgp.c:2487 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n" @@ -921,7 +921,8 @@ msgstr "Die vorhandene CRL ist zu alt" #: sm/certchain.c:607 msgid "please make sure that the \"dirmngr\" is properly installed\n" -msgstr "Bitte vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" +msgstr "" +"Bitte vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" #: sm/certchain.c:612 #, c-format @@ -1038,243 +1039,243 @@ msgstr "Schwacher Schlüssel - es wird erneut versucht\n" msgid "no valid recipients given\n" msgstr "Keine gültigen Empfänger angegeben\n" -#: sm/gpgsm.c:239 +#: sm/gpgsm.c:241 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:240 +#: sm/gpgsm.c:242 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:243 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:244 msgid "encrypt data" msgstr "Verschlüssele die Daten" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:245 msgid "encryption only with symmetric cipher" msgstr "Verschlüsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:246 msgid "decrypt data (default)" msgstr "Enschlüssele die Daten" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:247 msgid "verify a signature" msgstr "Überprüfen einer Signatur" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:249 msgid "list keys" msgstr "Schlüssel anzeigen" -#: sm/gpgsm.c:248 +#: sm/gpgsm.c:250 msgid "list external keys" msgstr "Externe Schlüssel anzeigen" -#: sm/gpgsm.c:249 +#: sm/gpgsm.c:251 msgid "list secret keys" msgstr "Geheime Schlüssel anzeigen" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:252 msgid "list certificate chain" msgstr "Schlüssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:252 +#: sm/gpgsm.c:254 msgid "list keys and fingerprints" msgstr "Schlüssel und Fingerprint anzeigen" -#: sm/gpgsm.c:253 +#: sm/gpgsm.c:255 msgid "generate a new key pair" msgstr "Neues Schlüsselpaar erzeugen" -#: sm/gpgsm.c:254 +#: sm/gpgsm.c:256 msgid "remove key from the public keyring" msgstr "Schlüssel aus dem öffentlichen Schlüsselbund löschen" -#: sm/gpgsm.c:255 +#: sm/gpgsm.c:257 msgid "export keys to a key server" msgstr "Schlüssen an eine Schlüsselserver exportieren" -#: sm/gpgsm.c:256 +#: sm/gpgsm.c:258 msgid "import keys from a key server" msgstr "Schlüssel von einem Schlüsselserver importieren" -#: sm/gpgsm.c:257 +#: sm/gpgsm.c:259 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:258 +#: sm/gpgsm.c:260 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:259 +#: sm/gpgsm.c:261 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:260 +#: sm/gpgsm.c:262 msgid "run in server mode" msgstr "Im Server Modus ausführen" -#: sm/gpgsm.c:261 +#: sm/gpgsm.c:263 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:263 +#: sm/gpgsm.c:265 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:264 +#: sm/gpgsm.c:266 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ändern" -#: sm/gpgsm.c:274 +#: sm/gpgsm.c:276 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hülle wird erzeugt" -#: sm/gpgsm.c:276 +#: sm/gpgsm.c:278 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:278 +#: sm/gpgsm.c:280 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:280 +#: sm/gpgsm.c:282 msgid "assume input is in base-64 format" msgstr "Eingabedaten sind im Basis-64 Format" -#: sm/gpgsm.c:282 +#: sm/gpgsm.c:284 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binärformat" -#: sm/gpgsm.c:284 +#: sm/gpgsm.c:286 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlüsseln für NAME" -#: sm/gpgsm.c:287 +#: sm/gpgsm.c:289 msgid "use system's dirmngr if available" msgstr "Benutze den System Dirmngr when verfügbar" -#: sm/gpgsm.c:288 +#: sm/gpgsm.c:290 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:295 +#: sm/gpgsm.c:297 msgid "check validity using OCSP" msgstr "Die Gültigkeit mittels OCSP prüfen" -#: sm/gpgsm.c:298 +#: sm/gpgsm.c:300 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:301 +#: sm/gpgsm.c:303 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:304 +#: sm/gpgsm.c:306 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht überprüfen" -#: sm/gpgsm.c:308 +#: sm/gpgsm.c:310 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:312 +#: sm/gpgsm.c:314 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfänger" -#: sm/gpgsm.c:314 +#: sm/gpgsm.c:316 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlüssel als Standardempfänger" -#: sm/gpgsm.c:320 +#: sm/gpgsm.c:322 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlüsseln" -#: sm/gpgsm.c:323 +#: sm/gpgsm.c:325 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:325 +#: sm/gpgsm.c:327 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:328 tools/gpgconf.c:61 +#: sm/gpgsm.c:330 tools/gpgconf.c:61 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: sm/gpgsm.c:331 +#: sm/gpgsm.c:333 msgid "don't use the terminal at all" msgstr "Das Terminal überhaupt nicht benutzen" -#: sm/gpgsm.c:334 +#: sm/gpgsm.c:337 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:335 +#: sm/gpgsm.c:338 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlüsseln mitbenutzen" -#: sm/gpgsm.c:340 +#: sm/gpgsm.c:343 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:341 +#: sm/gpgsm.c:344 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:342 +#: sm/gpgsm.c:345 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:344 +#: sm/gpgsm.c:347 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:345 +#: sm/gpgsm.c:348 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:346 +#: sm/gpgsm.c:349 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlüssel" -#: sm/gpgsm.c:347 +#: sm/gpgsm.c:350 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlüsselserver" -#: sm/gpgsm.c:348 +#: sm/gpgsm.c:351 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz für das Terminal auf NAME setzen" -#: sm/gpgsm.c:352 +#: sm/gpgsm.c:355 msgid "|LEVEL|set the debugging level to LEVEL" msgstr "|NAME|Die Debugstufe auf NAME setzen" -#: sm/gpgsm.c:359 +#: sm/gpgsm.c:363 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:366 +#: sm/gpgsm.c:370 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:372 +#: sm/gpgsm.c:376 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verschlüsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:374 +#: sm/gpgsm.c:378 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:376 +#: sm/gpgsm.c:380 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:384 +#: sm/gpgsm.c:388 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -1282,7 +1283,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:387 +#: sm/gpgsm.c:391 msgid "" "@\n" "Examples:\n" @@ -1302,11 +1303,11 @@ msgstr "" " --list-keys [Namen] Schlüssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrücke\" anzeigen\\n\n" -#: sm/gpgsm.c:506 +#: sm/gpgsm.c:510 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h für Hilfe)" -#: sm/gpgsm.c:509 +#: sm/gpgsm.c:513 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -1315,7 +1316,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prüfen, ver- und entschlüsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:516 +#: sm/gpgsm.c:520 msgid "" "\n" "Supported algorithms:\n" @@ -1323,50 +1324,50 @@ msgstr "" "\n" "Unterstützte Algorithmen:\n" -#: sm/gpgsm.c:603 +#: sm/gpgsm.c:607 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:668 +#: sm/gpgsm.c:672 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:684 +#: sm/gpgsm.c:688 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlüsseln für `%s' nicht möglich: %s\n" -#: sm/gpgsm.c:758 +#: sm/gpgsm.c:762 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (benötige %s, habe %s)\n" -#: sm/gpgsm.c:1215 +#: sm/gpgsm.c:1221 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm könnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1227 +#: sm/gpgsm.c:1233 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausführung mit gefälschter Systemzeit: " -#: sm/gpgsm.c:1253 +#: sm/gpgsm.c:1259 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewählte Verschlüsselungsverfahren ist ungültig\n" -#: sm/gpgsm.c:1261 +#: sm/gpgsm.c:1267 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewählte Hashverfahren ist ungültig\n" -#: sm/gpgsm.c:1291 +#: sm/gpgsm.c:1297 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht möglich: %s\n" -#: sm/gpgsm.c:1464 +#: sm/gpgsm.c:1470 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1694 sm/gpgsm.c:1731 +#: sm/gpgsm.c:1700 sm/gpgsm.c:1737 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geöffnet werden: %s\n" diff --git a/scd/ChangeLog b/scd/ChangeLog index 3e8292dee..df22c6bfd 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2005-09-06 Werner Koch <wk@g10code.com> + + * app-p15.c (do_sign): Tweaked for BELPIC cards. + (read_home_df): New arg R_BELPIC. + (app_select_p15): Set card type for BELPIC. + 2005-09-05 Werner Koch <wk@g10code.com> * iso7816.c (iso7816_select_path): New. diff --git a/scd/app-p15.c b/scd/app-p15.c index c8d38850b..bf3c4dc1e 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -39,8 +39,10 @@ typedef enum { CARD_TYPE_UNKNOWN, CARD_TYPE_TCOS, - CARD_TYPE_MICARDO - } card_type_t; + CARD_TYPE_MICARDO, + CARD_TYPE_BELPIC /* Belgian eID card specs. */ + } +card_type_t; /* A list card types with ATRs noticed with these cards. */ #define X(a) ((unsigned char const *)(a)) @@ -2771,6 +2773,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, + the largest OID prefix above. */ prkdf_object_t prkdf; /* The private key object. */ aodf_object_t aodf; /* The associated authentication object. */ + int no_data_padding = 0; /* True if the card want the data without padding.*/ + int mse_done = 0; /* Set to true if the MSE has been done. */ if (!keyidstr || !*keyidstr) return gpg_error (GPG_ERR_INV_VALUE); @@ -2833,6 +2837,35 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, return err; } + + /* Due to the fact that the non-repudiation signature on a BELPIC + card requires a ver verify immediately before the DSO we set the + MSE before we do the verification. Other cards might allow to do + this also but I don't want to break anything, thus we do it only + for the BELPIC card here. */ + if (app->app_local->card_type == CARD_TYPE_BELPIC) + { + unsigned char mse[5]; + + mse[0] = 4; /* Length of the template. */ + mse[1] = 0x80; /* Algorithm reference tag. */ + mse[2] = 0x02; /* Algorithm: RSASSA-PKCS1-v1.5 using SHA1. */ + mse[3] = 0x84; /* Private key reference tag. */ + mse[4] = prkdf->key_reference_valid? prkdf->key_reference : 0x82; + + err = iso7816_manage_security_env (app->slot, + 0x41, 0xB6, + mse, sizeof mse); + no_data_padding = 1; + mse_done = 1; + } + if (err) + { + log_error ("MSE failed: %s\n", gpg_strerror (err)); + return err; + } + + /* Now that we have all the information available, prepare and run the PIN verification.*/ if (1) @@ -2841,8 +2874,12 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, size_t pinvaluelen; const char *errstr; const char *s; - - err = pincb (pincb_arg, "PIN", &pinvalue); + + if (prkdf->usageflags.non_repudiation + && app->app_local->card_type == CARD_TYPE_BELPIC) + err = pincb (pincb_arg, "PIN (qualified signature!)", &pinvalue); + else + err = pincb (pincb_arg, "PIN", &pinvalue); if (err) { log_info ("PIN callback returned error: %s\n", gpg_strerror (err)); @@ -2884,8 +2921,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, switch (aodf->pintype) { case PIN_TYPE_BCD: - errstr = "PIN type BCD is not supported"; - break; case PIN_TYPE_ASCII_NUMERIC: for (s=pinvalue; digitp (s); s++) ; @@ -2914,7 +2949,39 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, return err? err : gpg_error (GPG_ERR_BAD_PIN_METHOD); } - if (aodf->pinflags.needs_padding) + + if (aodf->pintype == PIN_TYPE_BCD ) + { + char *paddedpin; + int ndigits; + + for (ndigits=0, s=pinvalue; *s; ndigits++, s++) + ; + paddedpin = xtrymalloc (aodf->stored_length+1); + if (!paddedpin) + { + err = gpg_error_from_errno (errno); + xfree (pinvalue); + return err; + } + + i = 0; + paddedpin[i++] = 0x20 | (ndigits & 0x0f); + for (s=pinvalue; i < aodf->stored_length && *s && s[1]; s = s+2 ) + paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f)); + if (i < aodf->stored_length && *s) + paddedpin[i++] = (((*s - '0') << 4) + |((aodf->pad_char_valid?aodf->pad_char:0)&0x0f)); + + if (aodf->pinflags.needs_padding) + while (i < aodf->stored_length) + paddedpin[i++] = aodf->pad_char_valid? aodf->pad_char : 0; + + xfree (pinvalue); + pinvalue = paddedpin; + pinvaluelen = i; + } + else if (aodf->pinflags.needs_padding) { char *paddedpin; @@ -2979,7 +3046,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, } /* Manage security environment needs to be weaked for certain cards. */ - if (app->app_local->card_type == CARD_TYPE_TCOS) + if (mse_done) + err = 0; + else if (app->app_local->card_type == CARD_TYPE_TCOS) { /* TCOS creates signatures always using the local key 0. MSE may not be used. */ @@ -3009,18 +3078,21 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, return err; } - - err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + if (no_data_padding) + err = iso7816_compute_ds (app->slot, data+15, 20, outdata, outdatalen); + else + err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); return err; } /* Assume that EF(DIR) has been selected. Read its content and figure - out the home EF of pkcs#15. Return that home DF or 0 if not - found. */ + out the home EF of pkcs#15. Return that home DF or 0 if not found + and the value at the address of BELPIC indicates whether it was + found by the belpic aid. */ static unsigned short -read_home_df (int slot) +read_home_df (int slot, int *r_belpic) { gpg_error_t err; unsigned char *buffer; @@ -3028,6 +3100,8 @@ read_home_df (int slot) size_t buflen, n, nn; unsigned short result = 0; + *r_belpic = 0; + err = iso7816_read_binary (slot, 0, 0, &buffer, &buflen); if (err) { @@ -3040,9 +3114,9 @@ read_home_df (int slot) if (p && n) { pp = find_tlv (p, n, 0x4f, &nn); - if (pp - && ((nn == sizeof pkcs15_aid && !memcmp (pp, pkcs15_aid, nn)) - ||(nn == sizeof pkcs15be_aid && !memcmp (pp, pkcs15be_aid, nn)))) + if (pp && ((nn == sizeof pkcs15_aid && !memcmp (pp, pkcs15_aid, nn)) + || (*r_belpic = (nn == sizeof pkcs15be_aid + && !memcmp (pp, pkcs15be_aid, nn))))) { pp = find_tlv (p, n, 0x50, &nn); if (pp) /* fixme: Filter log value? */ @@ -3072,10 +3146,15 @@ app_select_p15 (app_t app) unsigned short def_home_df = 0; card_type_t card_type = CARD_TYPE_UNKNOWN; int direct = 0; - + int is_belpic = 0; + rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid); if (rc) - rc = iso7816_select_application (slot, pkcs15be_aid, sizeof pkcs15be_aid); + { + rc = iso7816_select_application (slot, pkcs15be_aid,sizeof pkcs15be_aid); + if (!rc) + is_belpic = 1; + } if (rc) { /* Not found: Try to locate it from 2F00. We use direct path selection here because it seems that the Belgian eID card @@ -3087,7 +3166,7 @@ app_select_p15 (app_t app) if (!rc) { direct = 1; - def_home_df = read_home_df (slot); + def_home_df = read_home_df (slot, &is_belpic); if (def_home_df) { path[0] = def_home_df; @@ -3102,24 +3181,33 @@ app_select_p15 (app_t app) } if (!rc) { - /* We need to know the ATR for tweaking some security operations. */ - unsigned char *atr; - size_t atrlen; - int i; - - atr = apdu_get_atr (app->slot, &atrlen); - if (!atr) - rc = gpg_error (GPG_ERR_INV_CARD); + /* Determine the type of the card. The general case is to look + it up from the ATR table. For the Belgian eID card we know + it instantly from the AID. */ + if (is_belpic) + { + card_type = CARD_TYPE_BELPIC; + } else { - for (i=0; card_atr_list[i].atrlen; i++) - if (card_atr_list[i].atrlen == atrlen - && !memcmp (card_atr_list[i].atr, atr, atrlen)) - { - card_type = card_atr_list[i].type; - break; - } - xfree (atr); + unsigned char *atr; + size_t atrlen; + int i; + + atr = apdu_get_atr (app->slot, &atrlen); + if (!atr) + rc = gpg_error (GPG_ERR_INV_CARD); + else + { + for (i=0; card_atr_list[i].atrlen; i++) + if (card_atr_list[i].atrlen == atrlen + && !memcmp (card_atr_list[i].atr, atr, atrlen)) + { + card_type = card_atr_list[i].type; + break; + } + xfree (atr); + } } } if (!rc) diff --git a/scd/command.c b/scd/command.c index 52a86871e..d556822a2 100644 --- a/scd/command.c +++ b/scd/command.c @@ -667,7 +667,7 @@ pin_cb (void *opaque, const char *info, char **retstr) return gpg_error (gpg_err_code_from_errno (errno)); /* Fixme: Write an inquire function which returns the result in - secure memory and check all futher handling of the PIN. */ + secure memory and check all further handling of the PIN. */ rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); free (command); if (rc) -- cgit v1.2.3 From 6f90f05cb2181bc4ab64959c0f3590f48c9c39c6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 9 Sep 2005 11:18:08 +0000 Subject: Bug fixes and ssh support for the BELPIC. --- NEWS | 4 +- agent/ChangeLog | 14 ++++++ agent/command-ssh.c | 46 ++++++++++--------- agent/minip12.c | 4 +- po/de.po | 70 ++++++++++++++-------------- scd/ChangeLog | 14 +++++- scd/app-openpgp.c | 27 ++++++++++- scd/app-p15.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++-- scd/ccid-driver.c | 3 +- scd/ccid-driver.h | 3 +- scd/iso7816.c | 3 +- scd/iso7816.h | 3 +- scd/pcsc-wrapper.c | 1 - sm/ChangeLog | 6 +++ sm/export.c | 1 + 15 files changed, 256 insertions(+), 71 deletions(-) diff --git a/NEWS b/NEWS index 75410e8d5..acc7c25f3 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,10 @@ Noteworthy changes in version 1.9.19 ------------------------------------------------- - * The Belgian eID card is now supported. + * The Belgian eID card is now supported for signatures and ssh. + * Fixed bug in --export-secret-key-p12 so that certificates are again + included. Noteworthy changes in version 1.9.18 (2005-08-01) ------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index adb7b1bb6..83e1fe867 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,17 @@ +2005-09-09 Werner Koch <wk@g10code.com> + + * minip12.c (p12_build): Oops, array needs to be larger for the + certificate. + + * command-ssh.c (card_key_available): Let the card handler decide + whether the card is supported here. Also get a short serial + number to return from the card handler. + +2005-09-08 Werner Koch <wk@g10code.com> + + * minip12.c (build_cert_bag): Use a non constructed object. + i.e. 0x80 and not 0xa0. + 2005-08-16 Werner Koch <wk@g10code.com> * gpg-agent.c (main): Use a default file name for --write-env-file. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 642bcbbba..b8f0d20b0 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1583,13 +1583,13 @@ key_secret_to_public (gcry_sexp_t *key_public, /* Check whether a smartcard is available and whether it has a usable key. Store a copy of that key at R_PK and return 0. If no key is available store NULL at R_PK and return an error code. If CARDSN - is no NULL, a string with the serial number of the card will be + is not NULL, a string with the serial number of the card will be a malloced and stored there. */ static gpg_error_t card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) { gpg_error_t err; - char *appname; + char *authkeyid; char *serialno = NULL; unsigned char *pkbuf; size_t pkbuflen; @@ -1602,7 +1602,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) /* First see whether a card is available and whether the application is supported. */ - err = agent_card_getattr (ctrl, "APPTYPE", &appname); + err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid); if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED ) { /* Ask for the serial number to reset the card. */ @@ -1615,40 +1615,33 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) return err; } log_info (_("detected card with S/N: %s\n"), serialno); - err = agent_card_getattr (ctrl, "APPTYPE", &appname); + err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid); } if (err) { - log_error (_("error getting application type of card: %s\n"), + log_error (_("error getting default authentication keyID of card: %s\n"), gpg_strerror (err)); xfree (serialno); return err; } - if (strcmp (appname, "OPENPGP")) - { - log_info (_("card application `%s' is not supported\n"), appname); - xfree (appname); - xfree (serialno); - return gpg_error (GPG_ERR_NOT_SUPPORTED); - } - xfree (appname); - appname = NULL; /* Get the S/N if we don't have it yet. Use the fast getattr method. */ if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) ) { log_error (_("error getting serial number of card: %s\n"), gpg_strerror (err)); + xfree (authkeyid); return err; } /* Read the public key. */ - err = agent_card_readkey (ctrl, "OPENPGP.3", &pkbuf); + err = agent_card_readkey (ctrl, authkeyid, &pkbuf); if (err) { if (opt.verbose) log_info (_("no suitable card key found: %s\n"), gpg_strerror (err)); xfree (serialno); + xfree (authkeyid); return err; } @@ -1660,6 +1653,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) gpg_strerror (err)); xfree (pkbuf); xfree (serialno); + xfree (authkeyid); return err; } @@ -1671,6 +1665,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) xfree (pkbuf); gcry_sexp_release (s_pk); xfree (serialno); + xfree (authkeyid); return err; } @@ -1680,13 +1675,14 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) unsigned char *shadow_info; unsigned char *tmp; - shadow_info = make_shadow_info (serialno, "OPENPGP.3"); + shadow_info = make_shadow_info (serialno, authkeyid); if (!shadow_info) { err = gpg_error_from_errno (errno); xfree (pkbuf); gcry_sexp_release (s_pk); xfree (serialno); + xfree (authkeyid); return err; } err = agent_shadow_key (pkbuf, shadow_info, &tmp); @@ -1697,6 +1693,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) xfree (pkbuf); gcry_sexp_release (s_pk); xfree (serialno); + xfree (authkeyid); return err; } xfree (pkbuf); @@ -1711,18 +1708,23 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) xfree (pkbuf); gcry_sexp_release (s_pk); xfree (serialno); + xfree (authkeyid); return err; } } if (cardsn) { - size_t snlen = strlen (serialno); + char *dispsn; - if (snlen == 32 - && !memcmp (serialno, "D27600012401", 12)) /* OpenPGP card. */ - *cardsn = xtryasprintf ("cardno:%.12s", serialno+16); - else /* Something is wrong: Print all. */ + /* If the card handler is able to return a short serialnumber, + use that one, else use the complete serialno. */ + if (!agent_card_getattr (ctrl, "$DISPSERIALNO", &dispsn)) + { + *cardsn = xtryasprintf ("cardno:%s", dispsn); + xfree (dispsn); + } + else *cardsn = xtryasprintf ("cardno:%s", serialno); if (!*cardsn) { @@ -1730,12 +1732,14 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn) xfree (pkbuf); gcry_sexp_release (s_pk); xfree (serialno); + xfree (authkeyid); return err; } } xfree (pkbuf); xfree (serialno); + xfree (authkeyid); *r_pk = s_pk; return 0; } diff --git a/agent/minip12.c b/agent/minip12.c index 030043962..ea9f9b1b8 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -1409,7 +1409,7 @@ build_cert_bag (unsigned char *buffer, size_t buflen, char *salt, p += DIM (oid_encryptedData); /* 2. Store a [0] tag. */ - p = store_tag_length (p, 0xa0, len[2]); + p = store_tag_length (p, 0x80, len[2]); /* 3. Store a sequence. */ p = store_tag_length (p, TAG_SEQUENCE, len[3]); @@ -1553,7 +1553,7 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, unsigned char *buffer; size_t n, buflen; char salt[8]; - struct buffer_s seqlist[2]; + struct buffer_s seqlist[3]; int seqlistidx = 0; n = buflen = 0; /* (avoid compiler warning). */ diff --git a/po/de.po b/po/de.po index 69606fa8b..11f2c8a36 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-09-06 20:01+0200\n" +"POT-Creation-Date: 2005-09-09 12:47+0200\n" "PO-Revision-Date: 2005-08-02 17:02+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -605,52 +605,52 @@ msgstr "Der Fingerprint kann nicht gespeichert werden: %s\n" msgid "failed to store the creation date: %s\n" msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:978 +#: scd/app-openpgp.c:1003 #, c-format msgid "reading public key failed: %s\n" msgstr "Fehler beim Lesen des öffentlichen Schlüssels: %s\n" -#: scd/app-openpgp.c:986 scd/app-openpgp.c:1917 +#: scd/app-openpgp.c:1011 scd/app-openpgp.c:1942 msgid "response does not contain the public key data\n" msgstr "Die Antwort enthält keine Public Key Daten\n" -#: scd/app-openpgp.c:994 scd/app-openpgp.c:1925 +#: scd/app-openpgp.c:1019 scd/app-openpgp.c:1950 msgid "response does not contain the RSA modulus\n" msgstr "Die Antwort enthält keinen RSA Modulus\n" -#: scd/app-openpgp.c:1003 scd/app-openpgp.c:1935 +#: scd/app-openpgp.c:1028 scd/app-openpgp.c:1960 msgid "response does not contain the RSA public exponent\n" msgstr "Die Antwort enthält keinen öffenlichen RSA Exponent\n" -#: scd/app-openpgp.c:1266 scd/app-openpgp.c:1354 scd/app-openpgp.c:2157 +#: scd/app-openpgp.c:1291 scd/app-openpgp.c:1379 scd/app-openpgp.c:2182 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:1272 scd/app-openpgp.c:1360 scd/app-openpgp.c:2163 +#: scd/app-openpgp.c:1297 scd/app-openpgp.c:1385 scd/app-openpgp.c:2188 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" msgstr "Die PIN für den CHV%d ist zu kurz; Mindestlänge ist %d\n" -#: scd/app-openpgp.c:1281 scd/app-openpgp.c:1295 scd/app-openpgp.c:1370 -#: scd/app-openpgp.c:2172 scd/app-openpgp.c:2186 +#: scd/app-openpgp.c:1306 scd/app-openpgp.c:1320 scd/app-openpgp.c:1395 +#: scd/app-openpgp.c:2197 scd/app-openpgp.c:2211 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prüfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:1318 +#: scd/app-openpgp.c:1343 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:1333 scd/app-openpgp.c:2392 +#: scd/app-openpgp.c:1358 scd/app-openpgp.c:2417 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:1339 scd/app-openpgp.c:2401 +#: scd/app-openpgp.c:1364 scd/app-openpgp.c:2426 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:1344 +#: scd/app-openpgp.c:1369 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" @@ -659,105 +659,105 @@ msgstr "" #. TRANSLATORS: Do not translate the "|A|" prefix but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1351 +#: scd/app-openpgp.c:1376 msgid "|A|Admin PIN" msgstr "|A|Admin PIN" #. TRANSLATORS: Do not translate the "|*|" prefixes but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1500 +#: scd/app-openpgp.c:1525 msgid "|AN|New Admin PIN" msgstr "|AN|Neue Admin PIN" -#: scd/app-openpgp.c:1500 +#: scd/app-openpgp.c:1525 msgid "|N|New PIN" msgstr "|N|Neue PIN" -#: scd/app-openpgp.c:1504 +#: scd/app-openpgp.c:1529 #, c-format msgid "error getting new PIN: %s\n" msgstr "Fehler beim Holen der neuen PIN: %s\n" -#: scd/app-openpgp.c:1554 scd/app-openpgp.c:2003 +#: scd/app-openpgp.c:1579 scd/app-openpgp.c:2028 msgid "error reading application data\n" msgstr "Fehler beim Lesen der Anwendungsdaten\n" -#: scd/app-openpgp.c:1560 scd/app-openpgp.c:2010 +#: scd/app-openpgp.c:1585 scd/app-openpgp.c:2035 msgid "error reading fingerprint DO\n" msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" -#: scd/app-openpgp.c:1570 +#: scd/app-openpgp.c:1595 msgid "key already exists\n" msgstr "Schlüssel existiert bereits\n" -#: scd/app-openpgp.c:1574 +#: scd/app-openpgp.c:1599 msgid "existing key will be replaced\n" msgstr "Existierender Schlüssel wird ersetzt\n" -#: scd/app-openpgp.c:1576 +#: scd/app-openpgp.c:1601 msgid "generating new key\n" msgstr "Neuer Schlüssel wird erzeugt\n" -#: scd/app-openpgp.c:1743 +#: scd/app-openpgp.c:1768 msgid "creation timestamp missing\n" msgstr "Erzeugungsdatum fehlt\n" -#: scd/app-openpgp.c:1750 +#: scd/app-openpgp.c:1775 #, c-format msgid "RSA modulus missing or not of size %d bits\n" msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1757 +#: scd/app-openpgp.c:1782 #, c-format msgid "RSA public exponent missing or larger than %d bits\n" msgstr "Der öffentliche RSA Exponent fehlt oder ist länger als %d Bits\n" -#: scd/app-openpgp.c:1765 scd/app-openpgp.c:1772 +#: scd/app-openpgp.c:1790 scd/app-openpgp.c:1797 #, c-format msgid "RSA prime %s missing or not of size %d bits\n" msgstr "Die RSA Primzahl %s fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1835 +#: scd/app-openpgp.c:1860 #, c-format msgid "failed to store the key: %s\n" msgstr "Fehler beim Speichern des Schlüssels: %s\n" -#: scd/app-openpgp.c:1894 +#: scd/app-openpgp.c:1919 msgid "please wait while key is being generated ...\n" msgstr "Bitte warten bis der Schlüssel erzeugt wurde ...\n" -#: scd/app-openpgp.c:1908 +#: scd/app-openpgp.c:1933 msgid "generating key failed\n" msgstr "Fehler beim Erzeugen des Schlüssels\n" -#: scd/app-openpgp.c:1911 +#: scd/app-openpgp.c:1936 #, c-format msgid "key generation completed (%d seconds)\n" msgstr "Schlüsselerzeugung vollendet (%d Sekunden)\n" -#: scd/app-openpgp.c:1968 +#: scd/app-openpgp.c:1993 msgid "invalid structure of OpenPGP card (DO 0x93)\n" msgstr "Ungültige Struktur der OpenPGP Karte (DO 0x93)\n" -#: scd/app-openpgp.c:2137 +#: scd/app-openpgp.c:2162 #, c-format msgid "signatures created so far: %lu\n" msgstr "Anzahl bereits erzeugter Signaturen: %lu\n" -#: scd/app-openpgp.c:2145 +#: scd/app-openpgp.c:2170 #, c-format msgid "||Please enter the PIN%%0A[sigs done: %lu]" msgstr "||Bitte geben Sie die PIN ein%%0A[Sigs bisher: %lu]" -#: scd/app-openpgp.c:2406 +#: scd/app-openpgp.c:2431 msgid "" "verification of Admin PIN is currently prohibited through this command\n" msgstr "" "Die Überprüfung der Admin PIN is momentan durch ein Kommando verboten " "worden\n" -#: scd/app-openpgp.c:2477 scd/app-openpgp.c:2487 +#: scd/app-openpgp.c:2502 scd/app-openpgp.c:2512 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n" diff --git a/scd/ChangeLog b/scd/ChangeLog index df22c6bfd..207670072 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,15 @@ +2005-09-09 Werner Koch <wk@g10code.com> + + * pcsc-wrapper.c (main): Removed bogus free. + + * app-p15.c (do_auth): New. + (do_getattr): New attribs $AUTHKEYID and $DISPSERIALNO. + * app-openpgp.c (do_getattr): Ditto. + +2005-09-08 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_getattr): New key $AUTHKEYID. + 2005-09-06 Werner Koch <wk@g10code.com> * app-p15.c (do_sign): Tweaked for BELPIC cards. @@ -8,7 +20,7 @@ * iso7816.c (iso7816_select_path): New. * app-p15.c (select_ef_by_path): Allow for direct path selection. - (app_select_p15): Try using the beigian variant of pkcs#15. + (app_select_p15): Try using the Belgian variant of pkcs#15. (read_home_df): New. (read_ef_odf): Generalized. (read_ef_tokeninfo): New. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index bd56fb99d..5625c729b 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -696,6 +696,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) { "PRIVATE-DO-2", 0x0102 }, { "PRIVATE-DO-3", 0x0103 }, { "PRIVATE-DO-4", 0x0104 }, + { "$AUTHKEYID", 0x0000, -3 }, + { "$DISPSERIALNO",0x0000, -4 }, { NULL, 0 } }; int idx, i, rc; @@ -742,6 +744,29 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); return 0; } + if (table[idx].special == -3) + { + char const tmp[] = "OPENPGP.3"; + send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0); + return 0; + } + if (table[idx].special == -4) + { + char *serial; + time_t stamp; + + if (!app_get_serial_and_stamp (app, &serial, &stamp)) + { + if (strlen (serial) > 16+12) + { + send_status_info (ctrl, table[idx].name, serial+16, 12, NULL, 0); + xfree (serial); + return 0; + } + xfree (serial); + } + return gpg_error (GPG_ERR_INV_NAME); + } relptr = get_one_do (app, table[idx].tag, &value, &valuelen, &rc); if (relptr) @@ -2203,7 +2228,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, fingerprint delimited by a slash. Optionally the id OPENPGP.3 may be given. - Note that this fucntion may return the error code + Note that this function may return the error code GPG_ERR_WRONG_CARD to indicate that the card currently present does not match the one required for the requested action (e.g. the serial number does not match). */ diff --git a/scd/app-p15.c b/scd/app-p15.c index bf3c4dc1e..739a9ef95 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -2629,7 +2629,6 @@ readcert_by_cdf (app_t app, cdf_object_t cdf, } - /* Handler for the READCERT command. Read the certificate with id CERTID (as returned by learn_status in @@ -2653,6 +2652,95 @@ do_readcert (app_t app, const char *certid, } + +/* Implement the GETATTR command. This is similar to the LEARN + command but returns just one value via the status interface. */ +static gpg_error_t +do_getattr (app_t app, ctrl_t ctrl, const char *name) +{ + gpg_error_t err; + int i; + + if (!strcmp (name, "$AUTHKEYID")) + { + char *buf, *p; + prkdf_object_t prkdf; + + /* We return the ID of the first private keycapable of + signing. */ + for (prkdf = app->app_local->private_key_info; prkdf; + prkdf = prkdf->next) + if (prkdf->usageflags.sign) + break; + if (prkdf) + { + buf = xtrymalloc (9 + prkdf->objidlen*2 + 1); + if (!buf) + return gpg_error_from_errno (errno); + p = stpcpy (buf, "P15"); + if (app->app_local->home_df) + { + sprintf (p, "-%04hX", (app->app_local->home_df & 0xffff)); + p += 5; + } + p = stpcpy (p, "."); + for (i=0; i < prkdf->objidlen; i++) + { + sprintf (p, "%02X", prkdf->objid[i]); + p += 2; + } + + send_status_info (ctrl, name, buf, strlen (buf), NULL, 0); + xfree (buf); + return 0; + } + } + else if (!strcmp (name, "$DISPSERIALNO")) + { + /* For certain cards we return special IDs. There is no + general rule for it so we need to decide case by case. */ + if (app->app_local->card_type == CARD_TYPE_BELPIC) + { + /* The eID card has a card number printed on the fron matter + which seems to be a good indication. */ + unsigned char *buffer; + const unsigned char *p; + size_t buflen, n; + unsigned short path[] = { 0x3F00, 0xDF01, 0x4031 }; + + err = select_ef_by_path (app, path, DIM(path) ); + if (!err) + err = iso7816_read_binary (app->slot, 0, 0, &buffer, &buflen); + if (err) + { + log_error ("error accessing EF(ID): %s\n", gpg_strerror (err)); + return err; + } + + p = find_tlv (buffer, buflen, 1, &n); + if (p && n == 12) + { + char tmp[12+2+1]; + memcpy (tmp, p, 3); + tmp[3] = '-'; + memcpy (tmp+4, p+3, 7); + tmp[11] = '-'; + memcpy (tmp+12, p+10, 2); + tmp[14] = 0; + send_status_info (ctrl, name, tmp, strlen (tmp), NULL, 0); + xfree (buffer); + return 0; + } + xfree (buffer); + } + + } + return gpg_error (GPG_ERR_INV_NAME); +} + + + + /* Micardo cards require special treatment. This is a helper for the crypto functions to manage the security environment. We expect that the key file has already been selected. FID is the one of the @@ -3086,6 +3174,38 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, } +/* Handler for the PKAUTH command. + + This is basically the same as the PKSIGN command but we firstcheck + that the requested key is suitable for authentication; that is, it + must match the criteria used for the attribute $AUTHKEYID. See + do_sign for calling conventions; there is no HASHALGO, though. */ +static gpg_error_t +do_auth (app_t app, const char *keyidstr, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ) +{ + gpg_error_t err; + prkdf_object_t prkdf; + + if (!keyidstr || !*keyidstr) + return gpg_error (GPG_ERR_INV_VALUE); + + err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf); + if (err) + return err; + if (!prkdf->usageflags.sign) + { + log_error ("key %s may not be used for authentication\n", keyidstr); + return gpg_error (GPG_ERR_WRONG_KEY_USAGE); + } + return do_sign (app, keyidstr, GCRY_MD_SHA1, pincb, pincb_arg, + indata, indatalen, outdata, outdatalen); +} + + /* Assume that EF(DIR) has been selected. Read its content and figure out the home EF of pkcs#15. Return that home DF or 0 if not found @@ -3270,11 +3390,11 @@ app_select_p15 (app_t app) app->fnc.deinit = do_deinit; app->fnc.learn_status = do_learn_status; app->fnc.readcert = do_readcert; - app->fnc.getattr = NULL; + app->fnc.getattr = do_getattr; app->fnc.setattr = NULL; app->fnc.genkey = NULL; app->fnc.sign = do_sign; - app->fnc.auth = NULL; + app->fnc.auth = do_auth; app->fnc.decipher = NULL; app->fnc.change_pin = NULL; app->fnc.check_pin = NULL; @@ -3286,5 +3406,3 @@ app_select_p15 (app_t app) return rc; } - - diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 096a6811b..f82d93b00 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * ALTERNATIVELY, this file may be distributed under the terms of the * following license, in which case the provisions of this license are diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 82feed5c9..1b9ac2f85 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * ALTERNATIVELY, this file may be distributed under the terms of the * following license, in which case the provisions of this license are diff --git a/scd/iso7816.c b/scd/iso7816.c index 484906251..5b985324f 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * $Id$ */ diff --git a/scd/iso7816.h b/scd/iso7816.h index 828fabb01..04c7ae63e 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * $Id$ */ diff --git a/scd/pcsc-wrapper.c b/scd/pcsc-wrapper.c index f149e785a..23e8442f7 100644 --- a/scd/pcsc-wrapper.c +++ b/scd/pcsc-wrapper.c @@ -819,7 +819,6 @@ main (int argc, char **argv) fprintf (stderr, PGM ": invalid request 0x%02X\n", c); exit (1); } - free (argbuffer); } return 0; } diff --git a/sm/ChangeLog b/sm/ChangeLog index a76f586eb..41cf7bd35 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2005-09-08 Werner Koch <wk@g10code.com> + + * export.c (popen_protect_tool): Add option --have-cert. We + probably lost this option with 1.9.14 due to restructuring of + export.c. + 2005-07-21 Werner Koch <wk@g10code.com> * gpgsm.c (main): New options --no-log-file and --debug-none. diff --git a/sm/export.c b/sm/export.c index b4450b2c2..f9d6dac62 100644 --- a/sm/export.c +++ b/sm/export.c @@ -520,6 +520,7 @@ popen_protect_tool (const char *pgmname, argv[i++] = "--homedir"; argv[i++] = opt.homedir; argv[i++] = "--p12-export"; + argv[i++] = "--have-cert"; argv[i++] = "--prompt"; argv[i++] = prompt?prompt:""; argv[i++] = "--enable-status-msg"; -- cgit v1.2.3 From aa7eccfbefc56724d435de41a4567bc6bf97ed31 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 9 Sep 2005 13:48:48 +0000 Subject: Fixed yesterdays change. Importing to Outlook seems to work now. --- agent/ChangeLog | 1 + agent/minip12.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 83e1fe867..5dca17146 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -2,6 +2,7 @@ * minip12.c (p12_build): Oops, array needs to be larger for the certificate. + (build_cert_bag): Fixed yesterdays change. * command-ssh.c (card_key_available): Let the card handler decide whether the card is supported here. Also get a short serial diff --git a/agent/minip12.c b/agent/minip12.c index ea9f9b1b8..b4e836f5b 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -1409,7 +1409,7 @@ build_cert_bag (unsigned char *buffer, size_t buflen, char *salt, p += DIM (oid_encryptedData); /* 2. Store a [0] tag. */ - p = store_tag_length (p, 0x80, len[2]); + p = store_tag_length (p, 0xa0, len[2]); /* 3. Store a sequence. */ p = store_tag_length (p, TAG_SEQUENCE, len[3]); @@ -1433,7 +1433,7 @@ build_cert_bag (unsigned char *buffer, size_t buflen, char *salt, p += DIM (data_rc2iter2048); /* 8. And finally the [0] tag with the encrypted data. */ - p = store_tag_length (p, 0xa0, buflen); + p = store_tag_length (p, 0x80, buflen); memcpy (p, buffer, buflen); p += buflen; certbaglen = p - certbag; -- cgit v1.2.3 From cc999f61a798b2d1505f8353ee395d031ac55852 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 12 Sep 2005 08:23:33 +0000 Subject: About to release 1.9.19 --- NEWS | 4 +++- configure.ac | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index acc7c25f3..1e1148748 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,13 @@ -Noteworthy changes in version 1.9.19 +Noteworthy changes in version 1.9.19 (2005-09-12) ------------------------------------------------- * The Belgian eID card is now supported for signatures and ssh. + Other pkcs#15 cards should work as well. * Fixed bug in --export-secret-key-p12 so that certificates are again included. + Noteworthy changes in version 1.9.18 (2005-08-01) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 030643315..30b183046 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. # Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.19-cvs, gnupg-devel@gnupg.org) +AC_INIT(gnupg, 1.9.19, gnupg-devel@gnupg.org) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. -- cgit v1.2.3 From f96f84f7a06ff11e9325eb5962e8a002aff08d1f Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Thu, 15 Sep 2005 17:36:30 +0000 Subject: 2005-09-15 Moritz Schulte <moritz@g10code.com> * t-protect.c (test_agent_protect): Implemented. (main): Disable use of secure memory. --- agent/ChangeLog | 5 ++ agent/t-protect.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 170 insertions(+), 2 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 5dca17146..3dfe2c2aa 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-09-15 Moritz Schulte <moritz@g10code.com> + + * t-protect.c (test_agent_protect): Implemented. + (main): Disable use of secure memory. + 2005-09-09 Werner Koch <wk@g10code.com> * minip12.c (p12_build): Oops, array needs to be larger for the diff --git a/agent/t-protect.c b/agent/t-protect.c index 21cbe1160..5187cf8f7 100644 --- a/agent/t-protect.c +++ b/agent/t-protect.c @@ -39,8 +39,169 @@ test_agent_protect (void) { /* Protect the key encoded in canonical format in PLAINKEY. We assume a valid S-Exp here. */ -/* int agent_protect (const unsigned char *plainkey, const char *passphrase, */ -/* unsigned char **result, size_t *resultlen); */ + + unsigned int i; + int ret; + struct key_spec + { + const char *string; + }; + /* Valid RSA key. */ + struct key_spec key_rsa_valid = + { + "\x28\x31\x31\x3A\x70\x72\x69\x76\x61\x74\x65\x2D\x6B\x65\x79\x28\x33\x3A\x72\x73" + "\x61\x28\x31\x3A\x6E\x31\x32\x39\x3A\x00\xB6\xB5\x09\x59\x6A\x9E\xCA\xBC\x93\x92" + "\x12\xF8\x91\xE6\x56\xA6\x26\xBA\x07\xDA\x85\x21\xA9\xCA\xD4\xC0\x8E\x64\x0C\x04" + "\x05\x2F\xBB\x87\xF4\x24\xEF\x1A\x02\x75\xA4\x8A\x92\x99\xAC\x9D\xB6\x9A\xBE\x3D" + "\x01\x24\xE6\xC7\x56\xB1\xF7\xDF\xB9\xB8\x42\xD6\x25\x1A\xEA\x6E\xE8\x53\x90\x49" + "\x5C\xAD\xA7\x3D\x67\x15\x37\xFC\xE5\x85\x0A\x93\x2F\x32\xBA\xB6\x0A\xB1\xAC\x1F" + "\x85\x2C\x1F\x83\xC6\x25\xE7\xA7\xD7\x0C\xDA\x9E\xF1\x6D\x5C\x8E\x47\x73\x9D\x77" + "\xDF\x59\x26\x1A\xBE\x84\x54\x80\x7F\xF4\x41\xE1\x43\xFB\xD3\x7F\x85\x45\x29\x28" + "\x31\x3A\x65\x33\x3A\x01\x00\x01\x29\x28\x31\x3A\x64\x31\x32\x38\x3A\x07\x7A\xD3" + "\xDE\x28\x42\x45\xF4\x80\x6A\x1B\x82\xB7\x9E\x61\x6F\xBD\xE8\x21\xC8\x2D\x69\x1A" + "\x65\x66\x5E\x57\xB5\xFA\xD3\xF3\x4E\x67\xF4\x01\xE7\xBD\x2E\x28\x69\x9E\x89\xD9" + "\xC4\x96\xCF\x82\x19\x45\xAE\x83\xAC\x7A\x12\x31\x17\x6A\x19\x6B\xA6\x02\x7E\x77" + "\xD8\x57\x89\x05\x5D\x50\x40\x4A\x7A\x2A\x95\xB1\x51\x2F\x91\xF1\x90\xBB\xAE\xF7" + "\x30\xED\x55\x0D\x22\x7D\x51\x2F\x89\xC0\xCD\xB3\x1A\xC0\x6F\xA9\xA1\x95\x03\xDD" + "\xF6\xB6\x6D\x0B\x42\xB9\x69\x1B\xFD\x61\x40\xEC\x17\x20\xFF\xC4\x8A\xE0\x0C\x34" + "\x79\x6D\xC8\x99\xE5\x29\x28\x31\x3A\x70\x36\x35\x3A\x00\xD5\x86\xC7\x8E\x5F\x1B" + "\x4B\xF2\xE7\xCD\x7A\x04\xCA\x09\x19\x11\x70\x6F\x19\x78\x8B\x93\xE4\x4E\xE2\x0A" + "\xAF\x46\x2E\x83\x63\xE9\x8A\x72\x25\x3E\xD8\x45\xCC\xBF\x24\x81\xBB\x35\x1E\x85" + "\x57\xC8\x5B\xCF\xFF\x0D\xAB\xDB\xFF\x8E\x26\xA7\x9A\x09\x38\x09\x6F\x27\x29\x28" + "\x31\x3A\x71\x36\x35\x3A\x00\xDB\x0C\xDF\x60\xF2\x6F\x2A\x29\x6C\x88\xD6\xBF\x9F" + "\x8E\x5B\xE4\x5C\x0D\xDD\x71\x3C\x96\xCC\x73\xEB\xCB\x48\xB0\x61\x74\x09\x43\xF2" + "\x1D\x2A\x93\xD6\xE4\x2A\x72\x11\xE7\xF0\x2A\x95\xDC\xED\x6C\x39\x0A\x67\xAD\x21" + "\xEC\xF7\x39\xAE\x8A\x0C\xA4\x6F\xF2\xEB\xB3\x29\x28\x31\x3A\x75\x36\x34\x3A\x33" + "\x14\x91\x95\xF1\x69\x12\xDB\x20\xA4\x8D\x02\x0D\xBC\x3B\x9E\x38\x81\xB3\x9D\x72" + "\x2B\xF7\x93\x78\xF6\x34\x0F\x43\x14\x8A\x6E\x9F\xC5\xF5\x3E\x28\x53\xB7\x38\x7B" + "\xA4\x44\x3B\xA5\x3A\x52\xFC\xA8\x17\x3D\xE6\xE8\x5B\x42\xF9\x78\x3D\x4A\x78\x17" + "\xD0\x68\x0B\x29\x29\x29\x00" + }; + /* This RSA key is missing the last closing brace. */ + struct key_spec key_rsa_bogus_0 = + { + "\x28\x31\x31\x3A\x70\x72\x69\x76\x61\x74\x65\x2D\x6B\x65\x79\x28\x33\x3A\x72\x73" + "\x61\x28\x31\x3A\x6E\x31\x32\x39\x3A\x00\xB6\xB5\x09\x59\x6A\x9E\xCA\xBC\x93\x92" + "\x12\xF8\x91\xE6\x56\xA6\x26\xBA\x07\xDA\x85\x21\xA9\xCA\xD4\xC0\x8E\x64\x0C\x04" + "\x05\x2F\xBB\x87\xF4\x24\xEF\x1A\x02\x75\xA4\x8A\x92\x99\xAC\x9D\xB6\x9A\xBE\x3D" + "\x01\x24\xE6\xC7\x56\xB1\xF7\xDF\xB9\xB8\x42\xD6\x25\x1A\xEA\x6E\xE8\x53\x90\x49" + "\x5C\xAD\xA7\x3D\x67\x15\x37\xFC\xE5\x85\x0A\x93\x2F\x32\xBA\xB6\x0A\xB1\xAC\x1F" + "\x85\x2C\x1F\x83\xC6\x25\xE7\xA7\xD7\x0C\xDA\x9E\xF1\x6D\x5C\x8E\x47\x73\x9D\x77" + "\xDF\x59\x26\x1A\xBE\x84\x54\x80\x7F\xF4\x41\xE1\x43\xFB\xD3\x7F\x85\x45\x29\x28" + "\x31\x3A\x65\x33\x3A\x01\x00\x01\x29\x28\x31\x3A\x64\x31\x32\x38\x3A\x07\x7A\xD3" + "\xDE\x28\x42\x45\xF4\x80\x6A\x1B\x82\xB7\x9E\x61\x6F\xBD\xE8\x21\xC8\x2D\x69\x1A" + "\x65\x66\x5E\x57\xB5\xFA\xD3\xF3\x4E\x67\xF4\x01\xE7\xBD\x2E\x28\x69\x9E\x89\xD9" + "\xC4\x96\xCF\x82\x19\x45\xAE\x83\xAC\x7A\x12\x31\x17\x6A\x19\x6B\xA6\x02\x7E\x77" + "\xD8\x57\x89\x05\x5D\x50\x40\x4A\x7A\x2A\x95\xB1\x51\x2F\x91\xF1\x90\xBB\xAE\xF7" + "\x30\xED\x55\x0D\x22\x7D\x51\x2F\x89\xC0\xCD\xB3\x1A\xC0\x6F\xA9\xA1\x95\x03\xDD" + "\xF6\xB6\x6D\x0B\x42\xB9\x69\x1B\xFD\x61\x40\xEC\x17\x20\xFF\xC4\x8A\xE0\x0C\x34" + "\x79\x6D\xC8\x99\xE5\x29\x28\x31\x3A\x70\x36\x35\x3A\x00\xD5\x86\xC7\x8E\x5F\x1B" + "\x4B\xF2\xE7\xCD\x7A\x04\xCA\x09\x19\x11\x70\x6F\x19\x78\x8B\x93\xE4\x4E\xE2\x0A" + "\xAF\x46\x2E\x83\x63\xE9\x8A\x72\x25\x3E\xD8\x45\xCC\xBF\x24\x81\xBB\x35\x1E\x85" + "\x57\xC8\x5B\xCF\xFF\x0D\xAB\xDB\xFF\x8E\x26\xA7\x9A\x09\x38\x09\x6F\x27\x29\x28" + "\x31\x3A\x71\x36\x35\x3A\x00\xDB\x0C\xDF\x60\xF2\x6F\x2A\x29\x6C\x88\xD6\xBF\x9F" + "\x8E\x5B\xE4\x5C\x0D\xDD\x71\x3C\x96\xCC\x73\xEB\xCB\x48\xB0\x61\x74\x09\x43\xF2" + "\x1D\x2A\x93\xD6\xE4\x2A\x72\x11\xE7\xF0\x2A\x95\xDC\xED\x6C\x39\x0A\x67\xAD\x21" + "\xEC\xF7\x39\xAE\x8A\x0C\xA4\x6F\xF2\xEB\xB3\x29\x28\x31\x3A\x75\x36\x34\x3A\x33" + "\x14\x91\x95\xF1\x69\x12\xDB\x20\xA4\x8D\x02\x0D\xBC\x3B\x9E\x38\x81\xB3\x9D\x72" + "\x2B\xF7\x93\x78\xF6\x34\x0F\x43\x14\x8A\x6E\x9F\xC5\xF5\x3E\x28\x53\xB7\x38\x7B" + "\xA4\x44\x3B\xA5\x3A\x52\xFC\xA8\x17\x3D\xE6\xE8\x5B\x42\xF9\x78\x3D\x4A\x78\x17" + "\xD0\x68\x0B\x29\x29\x00" + }; + /* This RSA key is the `e' value. */ + struct key_spec key_rsa_bogus_1 = + { + "\x28\x31\x31\x3A\x70\x72\x69\x76\x61\x74\x65\x2D\x6B\x65\x79\x28\x33\x3A\x72\x73" + "\x61\x28\x31\x3A\x6E\x31\x32\x39\x3A\x00\xA8\x80\xB6\x71\xF4\x95\x9F\x49\x84\xED" + "\xC1\x1D\x5F\xFF\xED\x14\x7B\x9C\x6A\x62\x0B\x7B\xE2\x3E\x41\x48\x49\x85\xF5\x64" + "\x50\x04\x9D\x30\xFC\x84\x1F\x01\xC3\xC3\x15\x03\x48\x6D\xFE\x59\x0B\xB0\xD0\x3E" + "\x68\x8A\x05\x7A\x62\xB0\xB9\x6E\xC5\xD2\xA8\xEE\x0C\x6B\xDE\x5E\x3D\x8E\xE8\x8F" + "\xB3\xAE\x86\x99\x7E\xDE\x2B\xC2\x4D\x60\x51\xDB\xB1\x2C\xD0\x38\xEC\x88\x62\x3E" + "\xA9\xDD\x11\x53\x04\x17\xE4\xF2\x07\x50\xDC\x44\xED\x14\xF5\x0B\xAB\x9C\xBC\x24" + "\xC6\xCB\xAD\x0F\x05\x25\x94\xE2\x73\xEB\x14\xD5\xEE\x5E\x18\xF0\x40\x31\x29\x28" + "\x31\x3A\x64\x31\x32\x38\x3A\x40\xD0\x55\x9D\x2A\xA7\xBC\xBF\xE2\x3E\x33\x98\x71" + "\x7B\x37\x3D\xB8\x38\x57\xA1\x43\xEA\x90\x81\x42\xCA\x23\xE1\xBF\x9C\xA8\xBC\xC5" + "\x9B\xF8\x9D\x77\x71\xCD\xD3\x85\x8B\x20\x3A\x92\xE9\xBC\x79\xF3\xF7\xF5\x6D\x15" + "\xA3\x58\x3F\xC2\xEB\xED\x72\xD4\xE0\xCF\xEC\xB3\xEC\xEB\x09\xEA\x1E\x72\x6A\xBA" + "\x95\x82\x2C\x7E\x30\x95\x66\x3F\xA8\x2D\x40\x0F\x7A\x12\x4E\xF0\x71\x0F\x97\xDB" + "\x81\xE4\x39\x6D\x24\x58\xFA\xAB\x3A\x36\x73\x63\x01\x77\x42\xC7\x9A\xEA\x87\xDA" + "\x93\x8F\x6C\x64\xAD\x9E\xF0\xCA\xA2\x89\xA4\x0E\xB3\x25\x73\x29\x28\x31\x3A\x70" + "\x36\x35\x3A\x00\xC3\xF7\x37\x3F\x9D\x93\xEC\xC7\x5E\x4C\xB5\x73\x29\x62\x35\x80" + "\xC6\x7C\x1B\x1E\x68\x5F\x92\x56\x77\x0A\xE2\x8E\x95\x74\x87\xA5\x2F\x83\x2D\xF7" + "\xA1\xC2\x78\x54\x18\x6E\xDE\x35\xF0\x9F\x7A\xCA\x80\x5C\x83\x5C\x44\xAD\x8B\xE7" + "\x5B\xE2\x63\x7D\x6A\xC7\x98\x97\x29\x28\x31\x3A\x71\x36\x35\x3A\x00\xDC\x1F\xB1" + "\xB3\xD8\x13\xE0\x09\x19\xFD\x1C\x58\xA1\x2B\x02\xB4\xC8\xF2\x1C\xE7\xF9\xC6\x3B" + "\x68\xB9\x72\x43\x86\xEF\xA9\x94\x68\x02\xEF\x7D\x77\xE0\x0A\xD1\xD7\x48\xFD\xCD" + "\x98\xDA\x13\x8A\x76\x48\xD4\x0F\x63\x28\xFA\x01\x1B\xF3\xC7\x15\xB8\x53\x22\x7E" + "\x77\x29\x28\x31\x3A\x75\x36\x35\x3A\x00\xB3\xBB\x4D\xEE\x5A\xAF\xD0\xF2\x56\x8A" + "\x10\x2D\x6F\x4B\x2D\x76\x49\x9B\xE9\xA8\x60\x5D\x9E\x7E\x50\x86\xF1\xA1\x0F\x28" + "\x9B\x7B\xE8\xDD\x1F\x87\x4E\x79\x7B\x50\x12\xA7\xB4\x8B\x52\x38\xEC\x7C\xBB\xB9" + "\x55\x87\x11\x1C\x74\xE7\x7F\xA0\xBA\xE3\x34\x5D\x61\xBF\x29\x29\x29\x00" + }; + + struct + { + const char *key; + const char *passphrase; + int no_result_expected; + int compare_results; + unsigned char *result_expected; + size_t resultlen_expected; + int ret_expected; + unsigned char *result; + size_t resultlen; + } specs[] = + { + /* Invalid S-Expressions */ + /* - non-NULL */ + { "", + "passphrase", 1, 0, NULL, 0, GPG_ERR_INV_SEXP, NULL, 0 }, + /* - NULL; disabled, this segfaults */ + //{ NULL, + // "passphrase", 1, NULL, 0, GPG_ERR_INV_SEXP, NULL, 0 }, + + /* Valid and invalid keys. */ + { key_rsa_valid.string, + "passphrase", 0, 0, NULL, 0, 0, NULL, 0 }, + { key_rsa_bogus_0.string, + "passphrase", 0, 0, NULL, 0, GPG_ERR_INV_SEXP, NULL, 0 }, + { key_rsa_bogus_1.string, + "passphrase", 0, 0, NULL, 0, GPG_ERR_INV_SEXP, NULL, 0 }, + + /* FIXME: add more test data. */ + }; + + for (i = 0; i < DIM (specs); i++) + { + ret = agent_protect (specs[i].key, specs[i].passphrase, + &specs[i].result, &specs[i].resultlen); + if (gpg_err_code (ret) != specs[i].ret_expected) + { + printf ("agent_protect() returned `%i/%s'; expected `%i/%s'\n", + ret, gpg_strerror (ret), + specs[i].ret_expected, gpg_strerror (specs[i].ret_expected)); + abort (); + } + + if (specs[i].no_result_expected) + { + assert (! specs[i].result); + assert (! specs[i].resultlen); + } + else + { + if (specs[i].compare_results) + { + assert (specs[i].resultlen == specs[i].resultlen_expected); + if (specs[i].result_expected) + assert (! memcmp (specs[i].result, specs[i].result_expected, + specs[i].resultlen)); + else + assert (! specs[i].result); + } + xfree (specs[i].result); + } + } } @@ -133,6 +294,8 @@ test_agent_get_shadow_info (void) int main (int argc, char **argv) { + gcry_control (GCRYCTL_DISABLE_SECMEM); + test_agent_protect (); test_agent_unprotect (); test_agent_private_key_type (); -- cgit v1.2.3 From 19724f13bcb946c185c82cbd4fcf80d748c409f8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Sep 2005 12:49:53 +0000 Subject: Fixed padding in pkcs#12 --- agent/ChangeLog | 5 +++++ agent/minip12.c | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 3dfe2c2aa..8aa219d9a 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2005-09-16 Werner Koch <wk@g10code.com> + + * minip12.c (build_key_sequence, build_cert_sequence): Fixed + padding. + 2005-09-15 Moritz Schulte <moritz@g10code.com> * t-protect.c (test_agent_protect): Implemented. diff --git a/agent/minip12.c b/agent/minip12.c index b4e836f5b..91eef63f4 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -745,6 +745,15 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, startoffset = 0; buffer = p = plain; +/* { */ +/* # warning debug code is enabled */ +/* FILE *fp = fopen ("tmp-rc2-plain-key.der", "wb"); */ +/* if (!fp || fwrite (p, n, 1, fp) != 1) */ +/* exit (2); */ +/* fclose (fp); */ +/* } */ + + where = "decrypted-text"; if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) goto bailout; @@ -1229,7 +1238,7 @@ build_key_sequence (gcry_mpi_t *kparms, size_t *r_length) assert (needed == plainlen); /* Append some pad characters; we already allocated extra space. */ n = 8 - plainlen % 8; - for (;(plainlen % 8); plainlen++) + for (i=0; i < n; i++, plainlen++) *p++ = n; *r_length = plainlen; @@ -1453,6 +1462,7 @@ build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) size_t len[8], needed, n; unsigned char *p, *certseq; size_t certseqlen; + int i; /* Walk 8 steps down to collect the info: */ @@ -1535,7 +1545,7 @@ build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) /* Append some pad characters; we already allocated extra space. */ n = 8 - certseqlen % 8; - for (;(certseqlen % 8); certseqlen++) + for (i=0; i < n; i++, certseqlen++) *p++ = n; *r_length = certseqlen; -- cgit v1.2.3 From 482b509aa95ce0489878c7d9540aefbafaa8848f Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 28 Sep 2005 22:44:20 +0000 Subject: 2005-09-29 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (AM_CFLAGS): Add $(LIBGCRYPT_CFLAGS). --- tools/ChangeLog | 4 ++++ tools/Makefile.am | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 027289ea7..45ad469b6 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-09-29 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (AM_CFLAGS): Add $(LIBGCRYPT_CFLAGS). + 2005-09-06 Werner Koch <wk@g10code.com> * rfc822parse.c, rfc822parse.h: Changed license to LGPL. diff --git a/tools/Makefile.am b/tools/Makefile.am index bc66118bf..d68e16c09 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -24,7 +24,7 @@ EXTRA_DIST = Manifest watchgnupg.c \ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am -AM_CFLAGS = $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS) sbin_SCRIPTS = addgnupghome -- cgit v1.2.3 From 694cebb1c177bec1a26d3925124a05432561414f Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Wed, 28 Sep 2005 22:45:05 +0000 Subject: 2005-09-28 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (AM_CFLAGS): Add $(LIBASSUAN_CFLAGS). --- common/ChangeLog | 4 ++++ common/Makefile.am | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index 0ab9ac524..d058d6cd9 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2005-09-28 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (AM_CFLAGS): Add $(LIBASSUAN_CFLAGS). + 2005-07-04 Marcus Brinkmann <marcus@g10code.de> * simple-pwquery.h (simple_pwclear): New prototype. diff --git a/common/Makefile.am b/common/Makefile.am index 0f9b4324d..3056be6bc 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -23,7 +23,8 @@ noinst_LIBRARIES = libcommon.a libsimple-pwquery.a AM_CPPFLAGS = -I$(top_srcdir)/gl -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) $(PTH_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) \ + $(PTH_CFLAGS) libcommon_a_SOURCES = \ util.h i18n.h \ -- cgit v1.2.3 From d7a1e30b30ea3fe1db4eaa06e1ac05b6892b2fb6 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 7 Oct 2005 13:09:20 +0000 Subject: 2005-10-07 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (TESTS_ENVIRONMENT): Remove LD_LIBRARY_PATH hack. It's the responsibility of the person building the software to set it properly. --- tests/ChangeLog | 6 ++++++ tests/Makefile.am | 21 +-------------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/tests/ChangeLog b/tests/ChangeLog index 749220d9a..f75387757 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2005-10-07 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (TESTS_ENVIRONMENT): Remove LD_LIBRARY_PATH hack. + It's the responsibility of the person building the software to set + it properly. + 2004-09-30 Werner Koch <wk@g10code.com> * Makefile.am (SUBDIRS): Remove pkits until the copyright issues diff --git a/tests/Makefile.am b/tests/Makefile.am index bc2e50e10..5264b8859 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,26 +33,7 @@ GPGSM = ../sm/gpgsm TESTS_ENVIRONMENT = GNUPGHOME=`pwd` GPG_AGENT_INFO= LC_ALL=C GPGSM=$(GPGSM) \ - LD_LIBRARY_PATH=$$(seen=0; \ - for i in $(LDFLAGS) $(LIBGCRYPT_LIBS) $(PTH_LIBS); \ - do \ - if echo "$$i" | egrep '^-L' >/dev/null 2>&1; \ - then \ - if test $$seen = 0; \ - then \ - seen=1; \ - else \ - printf ":"; \ - fi; \ - printf "%s" "$${i}" | sed 's/^-L//'; \ - fi; \ - done; \ - if test $$seen != 0 \ - && test x$${LD_LIBRARY_PATH} != x; \ - then \ - printf ":"; \ - fi; \ - printf "%s" "$${LD_LIBRARY_PATH}") $(srcdir)/runtest + $(srcdir)/runtest testscripts = sm-sign+verify sm-verify -- cgit v1.2.3 From 84b22283d919c828d91c4bad448231f6973f675a Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 7 Oct 2005 23:46:36 +0000 Subject: 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * signal.c (get_signal_name): Check value of HAVE_DECL_SYS_SIGLIST instead of just if it is defined. --- common/ChangeLog | 5 +++++ common/signal.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/ChangeLog b/common/ChangeLog index d058d6cd9..4a184006a 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2005-10-08 Marcus Brinkmann <marcus@g10code.de> + + * signal.c (get_signal_name): Check value of HAVE_DECL_SYS_SIGLIST + instead of just if it is defined. + 2005-09-28 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (AM_CFLAGS): Add $(LIBASSUAN_CFLAGS). diff --git a/common/signal.c b/common/signal.c index f0d3df75e..2837d7b72 100644 --- a/common/signal.c +++ b/common/signal.c @@ -76,7 +76,7 @@ get_signal_name( int signum ) { /* Note that we can't use strsignal(), because it is not reentrant. */ -#if defined(HAVE_DECL_SYS_SIGLIST) && defined(NSIG) +#if HAVE_DECL_SYS_SIGLIST && defined(NSIG) return (signum >= 0 && signum < NSIG) ? sys_siglist[signum] : "?"; #else return NULL; -- cgit v1.2.3 From 41e8fded0a6e09180654b7635dd90c8bd7ece4ad Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sat, 8 Oct 2005 00:13:27 +0000 Subject: agent/ 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a. (gpg_preset_passphrase_LDADD, t_common_ldadd): Likewise. (gpg_agent_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. kbx/ 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (kbxutil_LDADD): Add ../gl/libgnu.a after ../jnlib/libjnlib.a. scd/ 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. sm/ 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpgsm_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. tools/ 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpgconf_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. (symcryptrun_LDADD, gpg_connect_agent_LDADD, gpgkey2ssh_LDADD): Likewise. --- agent/ChangeLog | 6 ++++++ agent/Makefile.am | 8 ++++---- kbx/ChangeLog | 5 +++++ kbx/Makefile.am | 2 +- scd/ChangeLog | 5 +++++ scd/Makefile.am | 2 +- sm/ChangeLog | 5 +++++ sm/Makefile.am | 4 ++-- tools/ChangeLog | 7 +++++++ tools/Makefile.am | 14 +++++++------- 10 files changed, 43 insertions(+), 15 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 8aa219d9a..975484007 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2005-10-08 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a. + (gpg_preset_passphrase_LDADD, t_common_ldadd): Likewise. + (gpg_agent_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. + 2005-09-16 Werner Koch <wk@g10code.com> * minip12.c (build_key_sequence, build_cert_sequence): Fixed diff --git a/agent/Makefile.am b/agent/Makefile.am index c1a7c820e..ec930fe3f 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -45,7 +45,7 @@ gpg_agent_SOURCES = \ learncard.c -gpg_agent_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a ../common/libcommon.a \ +gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ -lgpg-error @LIBINTL@ @@ -55,7 +55,7 @@ gpg_protect_tool_SOURCES = \ minip12.c minip12.h gpg_protect_tool_LDADD = ../common/libsimple-pwquery.a \ - ../jnlib/libjnlib.a ../common/libcommon.a \ + ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ if HAVE_W32_SYSTEM gpg_protect_tool_LDADD += -lwsock32 @@ -65,7 +65,7 @@ gpg_preset_passphrase_SOURCES = \ preset-passphrase.c gpg_preset_passphrase_LDADD = ../common/libsimple-pwquery.a \ - ../jnlib/libjnlib.a ../common/libcommon.a \ + ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ if HAVE_W32_SYSTEM gpg_preset_passphrase_LDADD += -lwsock32 @@ -76,7 +76,7 @@ endif # TESTS = t-protect -t_common_ldadd = ../jnlib/libjnlib.a ../common/libcommon.a \ +t_common_ldadd = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ t_protect_SOURCES = t-protect.c protect.c diff --git a/kbx/ChangeLog b/kbx/ChangeLog index 4fd06d5ca..14b702318 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,8 @@ +2005-10-08 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (kbxutil_LDADD): Add ../gl/libgnu.a after + ../jnlib/libjnlib.a. + 2005-06-15 Werner Koch <wk@g10code.com> * keybox-file.c (_keybox_read_blob2): Make IMAGE unsigned. diff --git a/kbx/Makefile.am b/kbx/Makefile.am index 85704eb66..f42e517bf 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -45,7 +45,7 @@ libkeybox_a_SOURCES = $(common_sources) # Note that libcommon is only required to resolve the LIBOBJS. kbxutil_SOURCES = kbxutil.c $(common_sources) -kbxutil_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a \ +kbxutil_LDADD = ../jnlib/libjnlib.a ../gl/libgnu.a \ $(KSBA_LIBS) $(LIBGCRYPT_LIBS) \ -lgpg-error $(LIBINTL) ../common/libcommon.a diff --git a/scd/ChangeLog b/scd/ChangeLog index 207670072..ccea117dd 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2005-10-08 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after + ../common/libcommon.a. + 2005-09-09 Werner Koch <wk@g10code.com> * pcsc-wrapper.c (main): Removed bogus free. diff --git a/scd/Makefile.am b/scd/Makefile.am index dadab4f67..9a32de98b 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -43,7 +43,7 @@ scdaemon_SOURCES = \ app.c app-common.h app-help.c $(card_apps) -scdaemon_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a ../common/libcommon.a \ +scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ $(LIBUSB_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) diff --git a/sm/ChangeLog b/sm/ChangeLog index 41cf7bd35..aa9ac91bc 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2005-10-08 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (gpgsm_LDADD): Add ../gl/libgnu.a after + ../common/libcommon.a. + 2005-09-08 Werner Koch <wk@g10code.com> * export.c (popen_protect_tool): Add option --have-cert. We diff --git a/sm/Makefile.am b/sm/Makefile.am index e5311e967..69a286e55 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -52,8 +52,8 @@ gpgsm_SOURCES = \ certreqgen.c -gpgsm_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a ../kbx/libkeybox.a \ - ../common/libcommon.a \ +gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a \ + ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -lgpg-error \ $(LIBINTL) $(PTH_LIBS) diff --git a/tools/ChangeLog b/tools/ChangeLog index 45ad469b6..06576d41d 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2005-10-08 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (gpgconf_LDADD): Add ../gl/libgnu.a after + ../common/libcommon.a. + (symcryptrun_LDADD, gpg_connect_agent_LDADD, gpgkey2ssh_LDADD): + Likewise. + 2005-09-29 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (AM_CFLAGS): Add $(LIBGCRYPT_CFLAGS). diff --git a/tools/Makefile.am b/tools/Makefile.am index d68e16c09..0ec6e8e36 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -43,23 +43,23 @@ endif gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c -gpgconf_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a \ - ../common/libcommon.a @LIBINTL@ +gpgconf_LDADD = ../jnlib/libjnlib.a \ + ../common/libcommon.a ../gl/libgnu.a @LIBINTL@ symcryptrun_SOURCES = symcryptrun.c -symcryptrun_LDADD = $(LIBUTIL_LIBS) ../gl/libgnu.a ../jnlib/libjnlib.a \ - ../common/libcommon.a \ +symcryptrun_LDADD = $(LIBUTIL_LIBS) ../jnlib/libjnlib.a \ + ../common/libcommon.a ../gl/libgnu.a \ ../common/libsimple-pwquery.a $(LIBGCRYPT_LIBS) \ $(GPG_ERROR_LIBS) $(LIBINTL) watchgnupg_SOURCES = watchgnupg.c gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c -gpg_connect_agent_LDADD = ../gl/libgnu.a ../jnlib/libjnlib.a \ - ../common/libcommon.a \ +gpg_connect_agent_LDADD = ../jnlib/libjnlib.a \ + ../common/libcommon.a ../gl/libgnu.a \ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) gpgkey2ssh_SOURCES = gpgkey2ssh.c gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) -gpgkey2ssh_LDADD = ../gl/libgnu.a ../common/libcommon.a \ +gpgkey2ssh_LDADD = ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) -- cgit v1.2.3 From af0aafa4f738c43677bd025761673cd53c7673ef Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sat, 8 Oct 2005 00:17:09 +0000 Subject: 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (watchgnupg_LDADD): New variable. --- tools/ChangeLog | 2 ++ tools/Makefile.am | 1 + 2 files changed, 3 insertions(+) diff --git a/tools/ChangeLog b/tools/ChangeLog index 06576d41d..ba4f0ec27 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,7 @@ 2005-10-08 Marcus Brinkmann <marcus@g10code.de> + * Makefile.am (watchgnupg_LDADD): New variable. + * Makefile.am (gpgconf_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. (symcryptrun_LDADD, gpg_connect_agent_LDADD, gpgkey2ssh_LDADD): diff --git a/tools/Makefile.am b/tools/Makefile.am index 0ec6e8e36..508e52bc5 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -53,6 +53,7 @@ symcryptrun_LDADD = $(LIBUTIL_LIBS) ../jnlib/libjnlib.a \ $(GPG_ERROR_LIBS) $(LIBINTL) watchgnupg_SOURCES = watchgnupg.c +watchgnupg_LDADD = $(NETLIBS) gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c gpg_connect_agent_LDADD = ../jnlib/libjnlib.a \ -- cgit v1.2.3 From caed7370e996eba1f60dc4e25eb8d8fe901a7e17 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 13 Nov 2005 19:05:00 +0000 Subject: NEw file qualified.ttx - not yet ready for distribution --- doc/ChangeLog | 5 +++++ doc/Makefile.am | 2 +- doc/qualified.txt | 17 +++++++++++++++++ doc/scdaemon.texi | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 doc/qualified.txt diff --git a/doc/ChangeLog b/doc/ChangeLog index d93a473a2..098139ec8 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2005-11-13 Werner Koch <wk@g10code.com> + + * qualified.txt: New. + * Makefile.am (dist_pkgdata_DATA): New. + 2005-08-16 Werner Koch <wk@g10code.com> * gpg-agent.texi (Agent Options): Note default file name for diff --git a/doc/Makefile.am b/doc/Makefile.am index fdcd62dc0..47dd36208 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -25,7 +25,7 @@ BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png info_TEXINFOS = gnupg.texi - +dist_pkgdata_DATA = qualified.txt gnupg_TEXINFOS = \ gpg.texi gpgsm.texi gpg-agent.texi scdaemon.texi assuan.texi \ diff --git a/doc/qualified.txt b/doc/qualified.txt new file mode 100644 index 000000000..bdab79ad4 --- /dev/null +++ b/doc/qualified.txt @@ -0,0 +1,17 @@ +# This is the list of root certificates used for qualified +# certificates. They are defined as certificates capable of creating +# legally binding signatures in the same way as a handwritten +# signatures are. Comments like this one and empty lines are allowed +# Lines do have a length limit but this is not a serious limitation as +# the format of the entries is fixed and checked by gpgsm: A +# non-comment line starts with optional white spaces, followed by +# exactly 40 hex character, white space and a lowercased 2 letter +# country code. Additional data delimited with by a white space is +# current ignored but might late be used for other pusposes. + +# CN=Wurzel ZS 3,O=Intevation GmbH,C=DE +A6935DD34EF3087973C706FC311AA2CCF733765B de + +# CN=SPECIMEN Belgium Root CA,C=BE +6A5FFD257E85DC6081828DD169AA304E7E37DD3B be + diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 35dca4780..8bc5810cb 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -229,6 +229,10 @@ readers might need a string here; run the program in verbose mode to get a list of available readers. The default is then the first reader found. +@item --disable-keypad +@opindex disable-keypad +Even if a card reader features a keypad, do not try to use it. + @item --allow-admin @itemx --deny-admin -- cgit v1.2.3 From b9633196f468edca3b41e182b8aa1bea4f46214b Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 13 Nov 2005 19:07:06 +0000 Subject: Added qualified signature features. --- sm/ChangeLog | 33 +++++++ sm/Makefile.am | 3 +- sm/call-agent.c | 21 +++++ sm/call-dirmngr.c | 2 +- sm/certchain.c | 76 +++++++++++++++- sm/certcheck.c | 4 + sm/certdump.c | 53 ++++++++++- sm/gpgsm.h | 5 ++ sm/keylist.c | 40 +++++++++ sm/qualified.c | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ sm/sign.c | 33 +++++++ sm/verify.c | 10 ++- 12 files changed, 535 insertions(+), 9 deletions(-) create mode 100644 sm/qualified.c diff --git a/sm/ChangeLog b/sm/ChangeLog index aa9ac91bc..5c6c5eb42 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,8 +1,41 @@ +2005-11-13 Werner Koch <wk@g10code.com> + + * call-agent.c (gpgsm_agent_get_confirmation): New. + + * keylist.c (list_cert_std): Print qualified status. + * qualified.c: New. + * certchain.c (gpgsm_validate_chain): Check for qualified + certificates. + + * certchain.c (gpgsm_basic_cert_check): Release keydb handle when + no-chain-validation is used. + +2005-11-11 Werner Koch <wk@g10code.com> + + * keylist.c (print_capabilities): Print is_qualified status. + +2005-10-28 Werner Koch <wk@g10code.com> + + * certdump.c (pretty_print_sexp): New. + (gpgsm_print_name2): Use it here. This allows proper printing of + DNS names as used with server certificates. + +2005-10-10 Werner Koch <wk@g10code.com> + + * keylist.c: Add pkaAdress OID as reference. + 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpgsm_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. +2005-09-13 Werner Koch <wk@g10code.com> + + * verify.c (gpgsm_verify): Print a note if the unknown algorithm + is MD2. + * sign.c (gpgsm_sign): Ditto. + * certcheck.c (gpgsm_check_cert_sig): Ditto. + 2005-09-08 Werner Koch <wk@g10code.com> * export.c (popen_protect_tool): Add option --have-cert. We diff --git a/sm/Makefile.am b/sm/Makefile.am index 69a286e55..aba2081f8 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -49,7 +49,8 @@ gpgsm_SOURCES = \ import.c \ export.c \ delete.c \ - certreqgen.c + certreqgen.c \ + qualified.c gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a \ diff --git a/sm/call-agent.c b/sm/call-agent.c index c47f6b19a..03a3a2e3f 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -693,3 +693,24 @@ gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc) return map_assuan_err (rc); } + + +/* Ask the agent to pop up a confirmation dialog with the text DESC + and an okay and cancel button. */ +gpg_error_t +gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc) +{ + int rc; + char *fpr; + char line[ASSUAN_LINELENGTH]; + + rc = start_agent (ctrl); + if (rc) + return rc; + + snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc); + line[DIM(line)-1] = 0; + + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + return map_assuan_err (rc); +} diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index ead117dfd..dd38a889b 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -276,7 +276,7 @@ inq_certificate (void *opaque, const char *line) { size_t n; - /* Send a certificate where a sourceKeyidentifier is included. */ + /* Send a certificate where a sourceKeyIdentifier is included. */ line += 12; while (*line == ' ') line++; diff --git a/sm/certchain.c b/sm/certchain.c index 02e5b409f..0c14fc88f 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -643,6 +643,9 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, int any_no_crl = 0; int any_crl_too_old = 0; int any_no_policy_match = 0; + int is_qualified = -1; /* Indicates whether the certificate stems + from a qualified root certificate. + -1 = unknown, 0 = no, 1 = yes. */ int lm = listmode; gnupg_get_isotime (current_time); @@ -771,6 +774,53 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, if (rc) goto leave; + + /* Set the flag for qualified signatures. This flag is + deduced from a list of root certificates allowed for + qualified signatures. */ + if (is_qualified == -1) + { + gpg_error_t err; + size_t buflen; + char buf[1]; + + if (!ksba_cert_get_user_data (cert, "is_qualified", + &buf, sizeof (buf), + &buflen) && buflen) + { + /* We already checked this for this certificate, + thus we simply take it from the user data. */ + is_qualified = !!*buf; + } + else + { + /* Need to consult the list of root certificates for + qualified signatures. */ + err = gpgsm_is_in_qualified_list (ctrl, subject_cert); + if (!err) + is_qualified = 1; + else if ( gpg_err_code (err) == GPG_ERR_NOT_FOUND) + is_qualified = 0; + else + log_error ("checking the list of qualified " + "root certificates failed: %s\n", + gpg_strerror (err)); + if ( is_qualified != -1 ) + { + /* Cache the result but don't care toomuch about + an error. */ + buf[0] = !!is_qualified; + err = ksba_cert_set_user_data (subject_cert, + "is_qualified", buf, 1); + if (err) + log_error ("set_user_data(is_qualified) failed: %s\n", + gpg_strerror (err)); + } + } + } + + + /* Check whether we really trust this root certificate. */ rc = gpgsm_agent_istrusted (ctrl, subject_cert); if (!rc) ; @@ -968,7 +1018,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, keydb_search_reset (kh); subject_cert = issuer_cert; issuer_cert = NULL; - } + } /* End chain traversal. */ if (!listmode) { @@ -996,6 +1046,27 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, } leave: + if (is_qualified != -1) + { + /* We figured something about the qualified signature capability + of the certificate under question. Store the result as user + data in the certificate object. We do this even if the + validation itself failed. */ + /* Fixme: We should set this flag for all certificates in the + chain for optimizing reasons. */ + char buf[1]; + gpg_error_t err; + + buf[0] = !!is_qualified; + err = ksba_cert_set_user_data (cert, "is_qualified", buf, 1); + if (err) + { + log_error ("set_user_data(is_qualified) failed: %s\n", + gpg_strerror (err)); + if (!rc) + rc = err; + } + } if (r_exptime) gnupg_copy_time (r_exptime, exptime); xfree (issuer); @@ -1017,7 +1088,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) int rc = 0; char *issuer = NULL; char *subject = NULL; - KEYDB_HANDLE kh = keydb_new (0); + KEYDB_HANDLE kh; ksba_cert_t issuer_cert = NULL; if (opt.no_chain_validation) @@ -1026,6 +1097,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert) return 0; } + kh = keydb_new (0); if (!kh) { log_error (_("failed to allocated keyDB handle\n")); diff --git a/sm/certcheck.c b/sm/certcheck.c index 84dfdb9ab..5fb376712 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -168,6 +168,10 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) if (!algo) { log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); + if (algoid + && ( !strcmp (algoid, "1.2.840.113549.1.1.2") + ||!strcmp (algoid, "1.2.840.113549.2.2"))) + log_info (_("(this is the MD2 algorithm)\n")); return gpg_error (GPG_ERR_GENERAL); } rc = gcry_md_open (&md, algo, 0); diff --git a/sm/certdump.c b/sm/certdump.c index aae60e020..1f2ea7b18 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -484,6 +484,51 @@ print_dn_parts (FILE *fp, struct dn_array_s *dn, int translate) } +/* Print the S-Expression in BUF, which has a valid length of BUFLEN, + as a human readable string in one line to FP. */ +static void +pretty_print_sexp (FILE *fp, const unsigned char *buf, size_t buflen) +{ + size_t len; + gcry_sexp_t sexp; + char *result, *p; + + if ( gcry_sexp_sscan (&sexp, NULL, (const char*)buf, buflen) ) + { + fputs (_("[Error - invalid encoding]"), fp); + return; + } + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); + assert (len); + result = xtrymalloc (len); + if (!result) + { + fputs (_("[Error - out of core]"), fp); + gcry_sexp_release (sexp); + return; + } + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len); + assert (len); + for (p = result; len; len--, p++) + { + if (*p == '\n') + { + if (len > 1) /* Avoid printing the trailing LF. */ + fputs ("\\n", fp); + } + else if (*p == '\r') + fputs ("\\r", fp); + else if (*p == '\v') + fputs ("\\v", fp); + else if (*p == '\t') + fputs ("\\t", fp); + else + putc (*p, fp); + } + xfree (result); + gcry_sexp_release (sexp); +} + void gpgsm_print_name2 (FILE *fp, const char *name, int translate) @@ -507,7 +552,9 @@ gpgsm_print_name2 (FILE *fp, const char *name, int translate) } } else if (*s == '(') - fputs (_("[Error - unknown encoding]"), fp); + { + pretty_print_sexp (fp, s, gcry_sexp_canon_len (s, 0, NULL, NULL)); + } else if (!((*s >= '0' && *s < '9') || (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z'))) @@ -576,7 +623,7 @@ format_name_writer (void *cookie, const char *buffer, size_t size) /* Format NAME which is expected to be in rfc2253 format into a better human readable format. Caller must free the returned string. NULL is returned in case of an error. With TRANSLATE set to true the - name will be translated to the native encodig. Note that NAME is + name will be translated to the native encoding. Note that NAME is internally always UTF-8 encoded. */ char * gpgsm_format_name2 (const char *name, int translate) @@ -658,7 +705,7 @@ gpgsm_format_keydesc (ksba_cert_t cert) #ifdef ENABLE_NLS - /* The Assuan agent protol requires us to transmit utf-8 strings */ + /* The Assuan agent protocol requires us to transmit utf-8 strings */ orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); #ifdef HAVE_LANGINFO_CODESET if (!orig_codeset) diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 63d07a8c2..52eff359a 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -288,6 +288,10 @@ int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- certreqgen.c --*/ int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp); +/*-- qualified.c --*/ +gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert); +gpg_error_t gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert); + /*-- call-agent.c --*/ int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc, unsigned char *digest, @@ -306,6 +310,7 @@ int gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip); int gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert); int gpgsm_agent_learn (ctrl_t ctrl); int gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc); +gpg_error_t gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (ctrl_t ctrl, diff --git a/sm/keylist.c b/sm/keylist.c index 8a4eb3cdb..51a066dab 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -66,6 +66,9 @@ struct { { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" }, { "1.3.6.1.5.5.7.3.13", "eapOverPPP" }, { "1.3.6.1.5.5.7.3.14", "wlanSSID" }, + + { "2.16.840.1.113730.4.1", "serverGatedCrypto.ns" }, /* Netscape. */ + { "1.3.6.1.4.1.311.10.3.3", "serverGatedCrypto.ms"}, /* Microsoft. */ { NULL, NULL } }; @@ -160,6 +163,9 @@ static struct { { "2.16.840.1.113730.1.12", "netscape-ssl-server-name" }, { "2.16.840.1.113730.1.13", "netscape-comment" }, + /* GnuPG extensions */ + { "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" }, + { NULL } }; @@ -207,6 +213,21 @@ print_capabilities (ksba_cert_t cert, FILE *fp) { gpg_error_t err; unsigned int use; + size_t buflen; + char buffer[1]; + + err = ksba_cert_get_user_data (cert, "is_qualified", + &buffer, sizeof (buffer), &buflen); + if (!err && buflen) + { + if (*buffer) + putc ('q', fp); + } + else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) + ; /* Don't know - will not get marked as 'q' */ + else + log_debug ("get_user_data(is_qualified) failed: %s\n", + gpg_strerror (err)); err = ksba_cert_get_key_usage (cert, &use); if (gpg_err_code (err) == GPG_ERR_NO_DATA) @@ -1032,9 +1053,28 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret, fprintf (fp, " fingerprint: %s\n", dn?dn:"error"); xfree (dn); + + if (with_validation) { + gpg_error_t tmperr; + size_t buflen; + char buffer[1]; + err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0); + tmperr = ksba_cert_get_user_data (cert, "is_qualified", + &buffer, sizeof (buffer), &buflen); + if (!tmperr && buflen) + { + if (*buffer) + fputs (" [qualified]\n", fp); + } + else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND) + ; /* Don't know - will not get marked as 'q' */ + else + log_debug ("get_user_data(is_qualified) failed: %s\n", + gpg_strerror (tmperr)); + if (!err) fprintf (fp, " [certificate is good]\n"); else diff --git a/sm/qualified.c b/sm/qualified.c new file mode 100644 index 000000000..c4bd00f96 --- /dev/null +++ b/sm/qualified.c @@ -0,0 +1,264 @@ +/* qualified.c - Routines related to qualified signatures + * Copyright (C) 2005 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 <assert.h> +#include <errno.h> +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif + +#include "gpgsm.h" +#include "i18n.h" +#include <ksba.h> + + +/* We open the file only once and keep the open file pointer as well + as the name of the file here. Note that, a listname not equal to + NULL indicates that this module has been intialized and if the + LISTFP is also NULL, no list of qualified signatures exists. */ +static char *listname; +static FILE *listfp; + + +/* Read the trustlist and return entry by entry. KEY must point to a + buffer of at least 41 characters. COUNTRY shall be a buffer of at + least 3 characters to receive the country code of that qualified + signature (i.e. "de" for German and "be" for Belgium). + + Reading a valid entry returns 0, EOF is indicated by GPG_ERR_EOF + and any other error condition is indicated by the appropriate error + code. */ +static gpg_error_t +read_list (char *key, char *country, int *lnr) +{ + gpg_error_t err; + int c, i, j; + char *p, line[256]; + + *key = 0; + *country = 0; + + if (!listname) + { + listname = make_filename (GNUPG_DATADIR, "qualified.txt", NULL); + listfp = fopen (listname, "r"); + if (!listfp && errno != ENOENT) + { + err = gpg_error_from_errno (errno); + log_error (_("can't open `%s': %s\n"), listname, gpg_strerror (err)); + return err; + } + } + + if (!listfp) + return gpg_error (GPG_ERR_EOF); + + do + { + if (!fgets (line, DIM(line)-1, listfp) ) + { + if (feof (listfp)) + return gpg_error (GPG_ERR_EOF); + return gpg_error_from_errno (errno); + } + + if (!*line || line[strlen(line)-1] != '\n') + { + /* Eat until end of line. */ + while ( (c=getc (listfp)) != EOF && c != '\n') + ; + return gpg_error (*line? GPG_ERR_LINE_TOO_LONG + : GPG_ERR_INCOMPLETE_LINE); + } + ++*lnr; + + /* Allow for empty lines and spaces */ + for (p=line; spacep (p); p++) + ; + } + while (!*p || *p == '\n' || *p == '#'); + + for (i=j=0; (p[i] == ':' || hexdigitp (p+i)) && j < 40; i++) + if ( p[i] != ':' ) + key[j++] = p[i] >= 'a'? (p[i] & 0xdf): p[i]; + key[j] = 0; + if (j != 40 || !(spacep (p+i) || p[i] == '\n')) + { + log_error (_("invalid formatted fingerprint in `%s', line %d\n"), + listname, *lnr); + return gpg_error (GPG_ERR_BAD_DATA); + } + assert (p[i]); + i++; + while (spacep (p+i)) + i++; + if ( p[i] >= 'a' && p[i] <= 'z' + && p[i+1] >= 'a' && p[i+1] <= 'z' + && (spacep (p+i+2) || p[i+2] == '\n')) + { + country[0] = p[i]; + country[1] = p[i+1]; + country[2] = 0; + } + else + { + log_error (_("invalid country code in `%s', line %d\n"), listname, *lnr); + return gpg_error (GPG_ERR_BAD_DATA); + } + + return 0; +} + + + + +/* Check whether the certificate CERT is included in the list of + qualified certificates. This list is similar to the "trustlist.txt" + as maintained by gpg-agent and includes fingerprints of root + certificates to be used for qualified (legally binding like + handwritten) signatures. We keep this list system wide and not + per user because it is not a decision of the user. + + Returns: 0 if the certificate is included. GPG_ERR_NOT_FOUND if it + is not in the liost or any other error (e.g. if no list of + qualified signatures is available. */ +gpg_error_t +gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert) +{ + gpg_error_t err; + char *fpr; + char key[41]; + char country[2]; + int lnr = 0; + + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + if (!fpr) + return gpg_error (GPG_ERR_GENERAL); + + if (listfp) + rewind (listfp); + while (!(err = read_list (key, country, &lnr))) + { + if (!strcmp (key, fpr)) + break; + } + if (gpg_err_code (err) == GPG_ERR_EOF) + err = gpg_error (GPG_ERR_NOT_FOUND); + + xfree (fpr); + return err; +} + + +/* We know that CERT is a qualified certificate. Ask the user for + consent to actually create a signature using this certificate. + Returns: 0 for yes, GPG_ERR_CANCEL for no or any otehr error + code. */ +gpg_error_t +gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert) +{ + gpg_error_t err; + char *name, *subject, *buffer, *p; + const char *s; + char *orig_codeset = NULL; + + name = ksba_cert_get_subject (cert, 0); + if (!name) + return gpg_error (GPG_ERR_GENERAL); + subject = gpgsm_format_name2 (name, 0); + ksba_free (name); name = NULL; + +#ifdef ENABLE_NLS + /* The Assuan agent protocol requires us to transmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset) + { /* We only switch when we are able to restore the codeset later. + Note that bind_textdomain_codeset does only return on memory + errors but not if a codeset is not available. Thus we don't + bother printing a diagnostic here. */ + orig_codeset = xstrdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) + orig_codeset = NULL; + } +#endif + + if (asprintf (&name, + _("You are about to create a signature using your " + "certificate:\n" + "\"%s\"\n" + "This will create a qualified signature by law " + "equated to a handwritten signature.\n\n" + "Are you really sure that you want to do this?"), + subject? subject:"?" + ) < 0 ) + err = gpg_error_from_errno (errno); + else + err = 0; + +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); +#endif + xfree (orig_codeset); + xfree (subject); + + if (err) + return err; + + buffer = p = xtrymalloc (strlen (name) * 3 + 1); + if (!buffer) + { + err = gpg_error_from_errno (errno); + free (name); + return err; + } + for (s=name; *s; s++) + { + if (*s < ' ' || *s == '+') + { + sprintf (p, "%%%02X", *(unsigned char *)s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p = 0; + free (name); + + + err = gpgsm_agent_get_confirmation (ctrl, buffer); + + xfree (buffer); + return err; +} diff --git a/sm/sign.c b/sm/sign.c index 3230a0e98..d9a332c9a 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -426,6 +426,35 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, goto leave; } } + + + /* Check whether one of the certificates is qualified. Note that we + already validated the certificate and thus the user data stored + flag must be available. */ + for (cl=signerlist; cl; cl = cl->next) + { + size_t buflen; + char buffer[1]; + + err = ksba_cert_get_user_data (cl->cert, "is_qualified", + &buffer, sizeof (buffer), &buflen); + if (err || !buflen) + { + log_error (_("checking for qualified certificate failed: %s\n"), + gpg_strerror (err)); + rc = err; + goto leave; + } + if (*buffer) + { + err = gpgsm_qualified_consent (ctrl, cl->cert); + if (err) + { + rc = err; + goto leave; + } + } + } /* Prepare hashing (actually we are figuring out what we have set above)*/ rc = gcry_md_open (&data_md, 0, 0); @@ -443,6 +472,10 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, if (!algo) { log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); + if (algoid + && ( !strcmp (algoid, "1.2.840.113549.1.1.2") + ||!strcmp (algoid, "1.2.840.113549.2.2"))) + log_info (_("(this is the MD2 algorithm)\n")); rc = gpg_error (GPG_ERR_BUG); goto leave; } diff --git a/sm/verify.c b/sm/verify.c index 410e86de7..f37cf4a75 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -179,8 +179,14 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp) { algo = gcry_md_map_name (algoid); if (!algo) - log_error ("unknown hash algorithm `%s'\n", - algoid? algoid:"?"); + { + log_error ("unknown hash algorithm `%s'\n", + algoid? algoid:"?"); + if (algoid + && ( !strcmp (algoid, "1.2.840.113549.1.1.2") + ||!strcmp (algoid, "1.2.840.113549.2.2"))) + log_info (_("(this is the MD2 algorithm)\n")); + } else gcry_md_enable (data_md, algo); } -- cgit v1.2.3 From 1d53603c3768eb4760976f45bbbf418e0c7c1278 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 14 Nov 2005 12:50:59 +0000 Subject: Added real information --- doc/ChangeLog | 4 +++ doc/qualified.txt | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 098139ec8..d6293d97e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-11-14 Werner Koch <wk@g10code.com> + + * qualified.txt: Added real information. + 2005-11-13 Werner Koch <wk@g10code.com> * qualified.txt: New. diff --git a/doc/qualified.txt b/doc/qualified.txt index bdab79ad4..1dbb90c68 100644 --- a/doc/qualified.txt +++ b/doc/qualified.txt @@ -8,10 +8,75 @@ # exactly 40 hex character, white space and a lowercased 2 letter # country code. Additional data delimited with by a white space is # current ignored but might late be used for other pusposes. +# +# $Id$ -# CN=Wurzel ZS 3,O=Intevation GmbH,C=DE -A6935DD34EF3087973C706FC311AA2CCF733765B de +#Serial number: 32D18D +# Issuer: /CN=6R-Ca 1:PN/NameDistinguisher=1/O=RegulierungsbehÈorde +# fÈur Telekommunikation und Post/C=DE +# Subject: /CN=6R-Ca 1:PN/NameDistinguisher=1/O=RegulierungsbehÈorde +# fÈur Telekommunikation und Post/C=DE +# validity: 2001-02-01 09:52:17 through 2005-06-01 09:52:17 +# key type: 1024 bit RSA +# key usage: certSign crlSign +EA:8D:99:DD:36:AA:2D:07:1A:3C:7B:69:00:9E:51:B9:4A:2E:E7:60 de -# CN=SPECIMEN Belgium Root CA,C=BE -6A5FFD257E85DC6081828DD169AA304E7E37DD3B be + +#Serial number: 00C48C8D +# Issuer: /CN=7R-CA 1:PN/NameDistinguisher=1/O=RegulierungsbehÈorde +# fÈur Telekommunikation und Post/C=DE +# Subject: /CN=7R-CA 1:PN/NameDistinguisher=1/O=RegulierungsbehÈorde +# fÈur Telekommunikation und Post/C=DE +# validity: 2001-10-15 11:15:15 through 2006-02-15 11:15:15 +# key type: 1024 bit RSA +# key usage: certSign crlSign +DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de + + +#Serial number: 01 +# Issuer: /CN=8R-CA 1:PN/O=Regulierungsbehörde für +# Telekommunikation und Post/C=DE +# Subject: /CN=8R-CA 1:PN/O=Regulierungsbehörde für +# Telekommunikation und Post/C=DE +# validity: 2004-11-25 14:10:37 through 2007-12-31 14:04:03 +# key type: 1024 bit RSA +# key usage: certSign +# policies: 1.3.36.8.1.1:N: +# chain length: unlimited +42:6A:F6:78:30:E9:CE:24:5B:EF:41:A2:C1:A8:51:DA:C5:0A:6D:F5 de + + +#Serial number: 02 +# Issuer: /CN=9R-CA 1:PN/O=Regulierungsbehörde für +# Telekommunikation und Post/C=DE +# Subject: /CN=9R-CA 1:PN/O=Regulierungsbehörde für +# Telekommunikation und Post/C=DE +# validity: 2004-11-25 14:59:11 through 2007-12-31 14:56:59 +# key type: 1024 bit RSA +# key usage: certSign +# policies: 1.3.36.8.1.1:N: +# chain length: unlimited +75:9A:4A:CE:7C:DA:7E:89:1B:B2:72:4B:E3:76:EA:47:3A:96:97:24 de + + +#Serial number: 2A +# Issuer: /CN=10R-CA 1:PN/O=Bundesnetzagentur/C=DE +# Subject: /CN=10R-CA 1:PN/O=Bundesnetzagentur/C=DE +# validity: 2005-08-03 15:30:36 through 2007-12-31 15:09:23 +# key type: 1024 bit RSA +# key usage: certSign +# policies: 1.3.36.8.1.1:N: +# chain length: unlimited +31:C9:D2:E6:31:4D:0B:CC:2C:1A:45:00:A6:6B:97:98:27:18:8E:CD de + + +#Serial number: 2D +# Issuer: /CN=11R-CA 1:PN/O=Bundesnetzagentur/C=DE +# Subject: /CN=11R-CA 1:PN/O=Bundesnetzagentur/C=DE +# validity: 2005-08-03 18:09:49 through 2007-12-31 18:04:28 +# key type: 1024 bit RSA +# key usage: certSign +# policies: 1.3.36.8.1.1:N: +# chain length: unlimited +A0:8B:DF:3B:AA:EE:3F:9D:64:6C:47:81:23:21:D4:A6:18:81:67:1D de -- cgit v1.2.3 From 894c65bcae81ddc132b0d361b7041ca99aa9477a Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 14 Nov 2005 12:59:55 +0000 Subject: . --- doc/qualified.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/qualified.txt b/doc/qualified.txt index 1dbb90c68..6d7a97b2e 100644 --- a/doc/qualified.txt +++ b/doc/qualified.txt @@ -11,6 +11,14 @@ # # $Id$ + + +#******************************************* +# +# Germany +# +#******************************************* + #Serial number: 32D18D # Issuer: /CN=6R-Ca 1:PN/NameDistinguisher=1/O=RegulierungsbehÈorde # fÈur Telekommunikation und Post/C=DE @@ -19,6 +27,7 @@ # validity: 2001-02-01 09:52:17 through 2005-06-01 09:52:17 # key type: 1024 bit RSA # key usage: certSign crlSign +#[checked: 2005-11-14] EA:8D:99:DD:36:AA:2D:07:1A:3C:7B:69:00:9E:51:B9:4A:2E:E7:60 de @@ -30,6 +39,7 @@ EA:8D:99:DD:36:AA:2D:07:1A:3C:7B:69:00:9E:51:B9:4A:2E:E7:60 de # validity: 2001-10-15 11:15:15 through 2006-02-15 11:15:15 # key type: 1024 bit RSA # key usage: certSign crlSign +#[checked: 2005-11-14] DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de @@ -43,6 +53,7 @@ DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de # key usage: certSign # policies: 1.3.36.8.1.1:N: # chain length: unlimited +#[checked: 2005-11-14] 42:6A:F6:78:30:E9:CE:24:5B:EF:41:A2:C1:A8:51:DA:C5:0A:6D:F5 de @@ -56,6 +67,7 @@ DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de # key usage: certSign # policies: 1.3.36.8.1.1:N: # chain length: unlimited +#[checked: 2005-11-14] 75:9A:4A:CE:7C:DA:7E:89:1B:B2:72:4B:E3:76:EA:47:3A:96:97:24 de @@ -67,6 +79,7 @@ DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de # key usage: certSign # policies: 1.3.36.8.1.1:N: # chain length: unlimited +#[checked: 2005-11-14] 31:C9:D2:E6:31:4D:0B:CC:2C:1A:45:00:A6:6B:97:98:27:18:8E:CD de @@ -78,5 +91,6 @@ DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de # key usage: certSign # policies: 1.3.36.8.1.1:N: # chain length: unlimited +#[checked: 2005-11-14] A0:8B:DF:3B:AA:EE:3F:9D:64:6C:47:81:23:21:D4:A6:18:81:67:1D de -- cgit v1.2.3 -- cgit v1.2.3 From 29a62827b4998152dec06a12b4d7951157504fd6 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 14 Nov 2005 13:11:15 +0000 Subject: Don't use keywords for signed files. --- doc/qualified.txt | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/qualified.txt b/doc/qualified.txt index 6d7a97b2e..083550734 100644 --- a/doc/qualified.txt +++ b/doc/qualified.txt @@ -7,9 +7,20 @@ # non-comment line starts with optional white spaces, followed by # exactly 40 hex character, white space and a lowercased 2 letter # country code. Additional data delimited with by a white space is -# current ignored but might late be used for other pusposes. +# current ignored but might late be used for other purposes. # -# $Id$ +# Note: The subversion copy of this file carries a gpg:signature +# property with its OpenPGP signature. Check this signature before +# adding entries: +# svn pg gpg:signature qualified.txt | gpg --verify - qualified.txt + + +#******************************************* +# +# Belgium +# +# Need to figure out a reliable source. +#******************************************* @@ -17,6 +28,8 @@ # # Germany # +# The information for Germany is available +# at http://www.bundesnetzagentur.de #******************************************* #Serial number: 32D18D @@ -94,3 +107,9 @@ DB:45:3D:1B:B0:1A:F3:23:10:6B:DE:D0:09:61:57:AA:F4:25:E0:5B de #[checked: 2005-11-14] A0:8B:DF:3B:AA:EE:3F:9D:64:6C:47:81:23:21:D4:A6:18:81:67:1D de + +#******************************************* +# +# End of file +# +#******************************************* -- cgit v1.2.3 From b8795bb8232ad5c26180ef27ad94e1b0832a95cf Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 23 Nov 2005 09:05:45 +0000 Subject: Print a note that the software has not been approved for qualified signatures. --- sm/ChangeLog | 11 +++++++ sm/call-agent.c | 1 - sm/gpgsm.c | 5 +++ sm/gpgsm.h | 8 +++++ sm/qualified.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- sm/sign.c | 12 +++---- 6 files changed, 127 insertions(+), 9 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 5c6c5eb42..88d9763c8 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,14 @@ +2005-11-23 Werner Koch <wk@g10code.com> + + * gpgsm.h: New member QUALSIG_APPROVAL. + * sign.c (gpgsm_sign): Print a warning if a certificate is not + qualified. + * qualified.c (gpgsm_qualified_consent): Include a note that this + is not approved software. + (gpgsm_not_qualified_warning): New. + * gpgsm.c (main): Prepared to print a note whether the software + has been approved. + 2005-11-13 Werner Koch <wk@g10code.com> * call-agent.c (gpgsm_agent_get_confirmation): New. diff --git a/sm/call-agent.c b/sm/call-agent.c index 03a3a2e3f..9942672ae 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -701,7 +701,6 @@ gpg_error_t gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc) { int rc; - char *fpr; char line[ASSUAN_LINELENGTH]; rc = start_agent (ctrl); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 0f9745a8c..7347bf575 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1220,6 +1220,11 @@ main ( int argc, char **argv) if (may_coredump && !opt.quiet) log_info (_("WARNING: program may create a core file!\n")); +/* if (opt.qualsig_approval && !opt.quiet) */ +/* log_info (_("This software has offically been approved to " */ +/* "create and verify\n" */ +/* "qualified signatures according to German law.\n")); */ + if (logfile && cmd == aServer) { log_set_file (logfile); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 52eff359a..dc863f682 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -108,6 +108,13 @@ struct { char *fixed_passphrase; /* Passphrase used by regression tests. */ int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ + + int qualsig_approval; /* Set to true if this software has + officially been approved to create an + verify qualified signatures. This is a + runtime option in case we want to check + the integrity of the software at + runtime. */ } opt; @@ -291,6 +298,7 @@ int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- qualified.c --*/ gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert); gpg_error_t gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert); +gpg_error_t gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert); /*-- call-agent.c --*/ int gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc, diff --git a/sm/qualified.c b/sm/qualified.c index c4bd00f96..4a2b6587f 100644 --- a/sm/qualified.c +++ b/sm/qualified.c @@ -216,9 +216,14 @@ gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert) "certificate:\n" "\"%s\"\n" "This will create a qualified signature by law " - "equated to a handwritten signature.\n\n" + "equated to a handwritten signature.\n\n%s%s" "Are you really sure that you want to do this?"), - subject? subject:"?" + subject? subject:"?", + opt.qualsig_approval? + "": + "Note that this software is not officially approved " + "to create or verify such signatures.\n", + opt.qualsig_approval? "":"\n" ) < 0 ) err = gpg_error_from_errno (errno); else @@ -257,6 +262,96 @@ gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert) free (name); + err = gpgsm_agent_get_confirmation (ctrl, buffer); + + xfree (buffer); + return err; +} + + +/* Popup a prompt to inform the user that the signature created is not + a qualified one. This is of course only doen if we know that we + have been approved. */ +gpg_error_t +gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert) +{ + gpg_error_t err; + char *name, *subject, *buffer, *p; + const char *s; + char *orig_codeset = NULL; + + if (!opt.qualsig_approval) + return 0; + + name = ksba_cert_get_subject (cert, 0); + if (!name) + return gpg_error (GPG_ERR_GENERAL); + subject = gpgsm_format_name2 (name, 0); + ksba_free (name); name = NULL; + + +#ifdef ENABLE_NLS + /* The Assuan agent protocol requires us to transmit utf-8 strings */ + orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset) + { /* We only switch when we are able to restore the codeset later. + Note that bind_textdomain_codeset does only return on memory + errors but not if a codeset is not available. Thus we don't + bother printing a diagnostic here. */ + orig_codeset = xstrdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) + orig_codeset = NULL; + } +#endif + + if (asprintf (&name, + _("You are about to create a signature using your " + "certificate:\n" + "\"%s\"\n" + "Note, that this certificate will NOT create a " + "qualified signature!"), + subject? subject:"?") < 0 ) + err = gpg_error_from_errno (errno); + else + err = 0; + +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE_GT, orig_codeset); +#endif + xfree (orig_codeset); + xfree (subject); + + if (err) + return err; + + buffer = p = xtrymalloc (strlen (name) * 3 + 1); + if (!buffer) + { + err = gpg_error_from_errno (errno); + free (name); + return err; + } + for (s=name; *s; s++) + { + if (*s < ' ' || *s == '+') + { + sprintf (p, "%%%02X", *(unsigned char *)s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p = 0; + free (name); + + err = gpgsm_agent_get_confirmation (ctrl, buffer); xfree (buffer); diff --git a/sm/sign.c b/sm/sign.c index d9a332c9a..74bfe41aa 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -446,13 +446,13 @@ gpgsm_sign (CTRL ctrl, CERTLIST signerlist, goto leave; } if (*buffer) + err = gpgsm_qualified_consent (ctrl, cl->cert); + else + err = gpgsm_not_qualified_warning (ctrl, cl->cert); + if (err) { - err = gpgsm_qualified_consent (ctrl, cl->cert); - if (err) - { - rc = err; - goto leave; - } + rc = err; + goto leave; } } -- cgit v1.2.3 From 000a38ccf22f318c885cae45ffb17c1f05cf60e9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 23 Nov 2005 12:38:38 +0000 Subject: Add translations --- po/ChangeLog | 4 + po/POTFILES.in | 1 + po/de.po | 341 ++++++++++++++++++++++++++++++++++----------------------- sm/qualified.c | 4 +- 4 files changed, 209 insertions(+), 141 deletions(-) diff --git a/po/ChangeLog b/po/ChangeLog index 4fa8cefec..127a5b075 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2005-11-23 Werner Koch <wk@g10code.com> + + * de.po: Updated. + 2005-08-01 Werner Koch <wk@g10code.com> * de.po: Converted to utf-8; fixed a few umlaut problems. diff --git a/po/POTFILES.in b/po/POTFILES.in index 3a5978a62..8fff858db 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -33,6 +33,7 @@ sm/keydb.c sm/keylist.c sm/sign.c sm/verify.c +sm/qualified.c tools/gpgconf.c tools/gpgconf-comp.c diff --git a/po/de.po b/po/de.po index 11f2c8a36..6b28544cb 100644 --- a/po/de.po +++ b/po/de.po @@ -10,15 +10,15 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-09-09 12:47+0200\n" -"PO-Revision-Date: 2005-08-02 17:02+0200\n" +"POT-Creation-Date: 2005-11-23 13:00+0100\n" +"PO-Revision-Date: 2005-11-23 13:02+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:108 agent/protect-tool.c:108 scd/scdaemon.c:99 +#: agent/gpg-agent.c:108 agent/protect-tool.c:108 scd/scdaemon.c:100 msgid "" "@Options:\n" " " @@ -26,28 +26,28 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:110 scd/scdaemon.c:101 +#: agent/gpg-agent.c:110 scd/scdaemon.c:102 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausführen" -#: agent/gpg-agent.c:111 scd/scdaemon.c:104 +#: agent/gpg-agent.c:111 scd/scdaemon.c:105 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausführen" -#: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:105 sm/gpgsm.c:331 +#: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:106 sm/gpgsm.c:331 #: tools/gpgconf.c:62 msgid "verbose" msgstr "ausführlich" -#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:106 sm/gpgsm.c:332 +#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:107 sm/gpgsm.c:332 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" -#: agent/gpg-agent.c:114 scd/scdaemon.c:107 +#: agent/gpg-agent.c:114 scd/scdaemon.c:108 msgid "sh-style command output" msgstr "Ausgabe für /bin/sh" -#: agent/gpg-agent.c:115 scd/scdaemon.c:108 +#: agent/gpg-agent.c:115 scd/scdaemon.c:109 msgid "csh-style command output" msgstr "Ausgabe für /bin/csh" @@ -55,7 +55,7 @@ msgstr "Ausgabe für /bin/csh" msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:121 scd/scdaemon.c:117 +#: agent/gpg-agent.c:121 scd/scdaemon.c:118 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" @@ -63,7 +63,7 @@ msgstr "Im Vordergrund laufen lassen" msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:123 scd/scdaemon.c:118 sm/gpgsm.c:334 +#: agent/gpg-agent.c:123 scd/scdaemon.c:119 sm/gpgsm.c:334 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" @@ -115,12 +115,12 @@ msgstr "Die ssh-agent Emulation anschalten" msgid "|FILE|write environment settings also to FILE" msgstr "|DATEI|Schreibe die Umgebungsvariabeln auf DATEI" -#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:183 +#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:185 #: sm/gpgsm.c:507 tools/gpgconf.c:85 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:183 +#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:185 #: sm/gpgsm.c:507 tools/gpgconf.c:85 msgid ">.\n" msgstr ">.\n" @@ -137,30 +137,30 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlüssel für GnuPG\n" -#: agent/gpg-agent.c:311 scd/scdaemon.c:257 sm/gpgsm.c:636 +#: agent/gpg-agent.c:311 scd/scdaemon.c:259 sm/gpgsm.c:636 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungültige Debugebene `%s' angegeben\n" #: agent/gpg-agent.c:482 agent/protect-tool.c:1072 kbx/kbxutil.c:431 -#: scd/scdaemon.c:349 sm/gpgsm.c:757 +#: scd/scdaemon.c:351 sm/gpgsm.c:757 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (benötigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:574 scd/scdaemon.c:424 sm/gpgsm.c:858 +#: agent/gpg-agent.c:574 scd/scdaemon.c:426 sm/gpgsm.c:858 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:579 agent/gpg-agent.c:1090 scd/scdaemon.c:429 +#: agent/gpg-agent.c:579 agent/gpg-agent.c:1090 scd/scdaemon.c:431 #: sm/gpgsm.c:862 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:587 scd/scdaemon.c:437 sm/gpgsm.c:869 +#: agent/gpg-agent.c:587 scd/scdaemon.c:439 sm/gpgsm.c:869 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" @@ -171,31 +171,31 @@ msgid "error creating `%s': %s\n" msgstr "Fehler beim Erstellen von `%s': %s\n" #: agent/gpg-agent.c:1140 agent/gpg-agent.c:1243 agent/gpg-agent.c:1247 -#: agent/gpg-agent.c:1283 agent/gpg-agent.c:1287 scd/scdaemon.c:902 +#: agent/gpg-agent.c:1283 agent/gpg-agent.c:1287 scd/scdaemon.c:906 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstellt werden: %s\n" -#: agent/gpg-agent.c:1154 scd/scdaemon.c:916 +#: agent/gpg-agent.c:1154 scd/scdaemon.c:920 msgid "name of socket too long\n" msgstr "Der Name des Sockets ist zu lang\n" -#: agent/gpg-agent.c:1180 scd/scdaemon.c:942 +#: agent/gpg-agent.c:1180 scd/scdaemon.c:946 #, c-format msgid "can't create socket: %s\n" msgstr "Socket kann nicht erzeugt werden: %s\n" -#: agent/gpg-agent.c:1209 scd/scdaemon.c:971 +#: agent/gpg-agent.c:1209 scd/scdaemon.c:975 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n" -#: agent/gpg-agent.c:1217 scd/scdaemon.c:979 +#: agent/gpg-agent.c:1217 scd/scdaemon.c:983 #, c-format msgid "listen() failed: %s\n" msgstr "Der listen() Aufruf ist fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1223 scd/scdaemon.c:985 +#: agent/gpg-agent.c:1223 scd/scdaemon.c:989 #, c-format msgid "listening on socket `%s'\n" msgstr "Es wird auf Socket `%s' gehört\n" @@ -235,12 +235,12 @@ msgstr "SSH Handhabungsroutine 0x%lx für fd %d gestartet\n" msgid "ssh handler 0x%lx for fd %d terminated\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d beendet\n" -#: agent/gpg-agent.c:1526 scd/scdaemon.c:1101 +#: agent/gpg-agent.c:1526 scd/scdaemon.c:1105 #, c-format msgid "pth_select failed: %s - waiting 1s\n" msgstr "pth_select() Aufruf fehlgeschlagen: %s - warte 1s\n" -#: agent/gpg-agent.c:1610 scd/scdaemon.c:1158 +#: agent/gpg-agent.c:1610 scd/scdaemon.c:1162 #, c-format msgid "%s %s stopped\n" msgstr "%s %s angehalten\n" @@ -320,15 +320,15 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "Admin PIN" msgstr "Admin PIN" -#: agent/divert-scd.c:257 +#: agent/divert-scd.c:274 msgid "Repeat this PIN" msgstr "PIN bitte wiederholen" -#: agent/divert-scd.c:260 +#: agent/divert-scd.c:277 msgid "PIN not correctly repeated; try again" msgstr "PIN wurde nicht korrekt eingegeben; nochmal versuchen" -#: agent/divert-scd.c:272 +#: agent/divert-scd.c:289 #, c-format msgid "Please enter the PIN%s%s%s to unlock the card" msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" @@ -343,12 +343,12 @@ msgstr "" msgid "Please enter the new passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: agent/query.c:169 +#: agent/query.c:192 #, c-format msgid "failed to acquire the pinentry lock: %s\n" msgstr "Die Sperre für das Pinentry kann nicht gesetzt werden: %s\n" -#: agent/query.c:332 +#: agent/query.c:355 msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" @@ -356,7 +356,7 @@ msgstr "" "Bitte geben Sie Ihre PIN ein, so daß der geheime Schlüssel benutzt werden " "kann" -#: agent/query.c:335 +#: agent/query.c:358 msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" @@ -364,31 +364,31 @@ msgstr "" "Bitte geben Sie Ihr Mantra (Passphrase) ein, so daß der geheime Schlüssel " "benutzt werden kann" -#: agent/query.c:393 agent/query.c:405 +#: agent/query.c:416 agent/query.c:428 msgid "PIN too long" msgstr "Die PIN ist zu lang" -#: agent/query.c:394 +#: agent/query.c:417 msgid "Passphrase too long" msgstr "Das Matra (Passphrase) ist zu lang" -#: agent/query.c:402 +#: agent/query.c:425 msgid "Invalid characters in PIN" msgstr "Ungültige Zeichen in der PIN" -#: agent/query.c:407 +#: agent/query.c:430 msgid "PIN too short" msgstr "Die PIN ist zu kurz" -#: agent/query.c:419 +#: agent/query.c:442 msgid "Bad PIN" msgstr "Falsche PIN" -#: agent/query.c:420 +#: agent/query.c:443 msgid "Bad Passphrase" msgstr "Falsches Mantra (Passphrase)" -#: agent/query.c:460 +#: agent/query.c:483 msgid "Passphrase" msgstr "Mantra" @@ -539,39 +539,43 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:103 +#: scd/scdaemon.c:104 msgid "run in multi server mode (foreground)" msgstr "Im Multiserver Modus ausführen" -#: scd/scdaemon.c:109 sm/gpgsm.c:352 +#: scd/scdaemon.c:110 sm/gpgsm.c:352 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" -#: scd/scdaemon.c:119 +#: scd/scdaemon.c:120 msgid "|N|connect to reader at port N" msgstr "|N|Verbinde mit dem Leser auf Port N" -#: scd/scdaemon.c:120 +#: scd/scdaemon.c:121 msgid "|NAME|use NAME as ct-API driver" msgstr "|NAME|Benutze NAME als CT-API Treiber" -#: scd/scdaemon.c:121 +#: scd/scdaemon.c:122 msgid "|NAME|use NAME as PC/SC driver" msgstr "|NAME|Benutze NAME als PC/SC Treiber" -#: scd/scdaemon.c:124 +#: scd/scdaemon.c:125 msgid "do not use the internal CCID driver" msgstr "Den internen CCID Treiber nicht benutzen" -#: scd/scdaemon.c:129 +#: scd/scdaemon.c:130 +msgid "do not use a reader's keypad" +msgstr "Die Tastatur des Kartenleser nicht benutzen" + +#: scd/scdaemon.c:131 msgid "allow the use of admin card commands" msgstr "Erlaube die Benutzung von \"Admin\" Kommandos" -#: scd/scdaemon.c:186 +#: scd/scdaemon.c:188 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h für Hilfe)" -#: scd/scdaemon.c:188 +#: scd/scdaemon.c:190 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" @@ -579,18 +583,18 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon für GnuPG\n" -#: scd/scdaemon.c:658 +#: scd/scdaemon.c:662 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszuführen\n" -#: scd/scdaemon.c:999 +#: scd/scdaemon.c:1003 #, c-format msgid "handler for fd %d started\n" msgstr "Handhabungsroutine für fd %d gestartet\n" -#: scd/scdaemon.c:1004 +#: scd/scdaemon.c:1008 #, c-format msgid "handler for fd %d terminated\n" msgstr "Handhabungsroutine für den fd %d beendet\n" @@ -610,47 +614,47 @@ msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" msgid "reading public key failed: %s\n" msgstr "Fehler beim Lesen des öffentlichen Schlüssels: %s\n" -#: scd/app-openpgp.c:1011 scd/app-openpgp.c:1942 +#: scd/app-openpgp.c:1011 scd/app-openpgp.c:1947 msgid "response does not contain the public key data\n" msgstr "Die Antwort enthält keine Public Key Daten\n" -#: scd/app-openpgp.c:1019 scd/app-openpgp.c:1950 +#: scd/app-openpgp.c:1019 scd/app-openpgp.c:1955 msgid "response does not contain the RSA modulus\n" msgstr "Die Antwort enthält keinen RSA Modulus\n" -#: scd/app-openpgp.c:1028 scd/app-openpgp.c:1960 +#: scd/app-openpgp.c:1028 scd/app-openpgp.c:1965 msgid "response does not contain the RSA public exponent\n" msgstr "Die Antwort enthält keinen öffenlichen RSA Exponent\n" -#: scd/app-openpgp.c:1291 scd/app-openpgp.c:1379 scd/app-openpgp.c:2182 +#: scd/app-openpgp.c:1296 scd/app-openpgp.c:1384 scd/app-openpgp.c:2187 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:1297 scd/app-openpgp.c:1385 scd/app-openpgp.c:2188 +#: scd/app-openpgp.c:1302 scd/app-openpgp.c:1390 scd/app-openpgp.c:2193 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" msgstr "Die PIN für den CHV%d ist zu kurz; Mindestlänge ist %d\n" -#: scd/app-openpgp.c:1306 scd/app-openpgp.c:1320 scd/app-openpgp.c:1395 -#: scd/app-openpgp.c:2197 scd/app-openpgp.c:2211 +#: scd/app-openpgp.c:1311 scd/app-openpgp.c:1325 scd/app-openpgp.c:1400 +#: scd/app-openpgp.c:2202 scd/app-openpgp.c:2216 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prüfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:1343 +#: scd/app-openpgp.c:1348 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:1358 scd/app-openpgp.c:2417 +#: scd/app-openpgp.c:1363 scd/app-openpgp.c:2422 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:1364 scd/app-openpgp.c:2426 +#: scd/app-openpgp.c:1369 scd/app-openpgp.c:2431 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:1369 +#: scd/app-openpgp.c:1374 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" @@ -659,105 +663,105 @@ msgstr "" #. TRANSLATORS: Do not translate the "|A|" prefix but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1376 +#: scd/app-openpgp.c:1381 msgid "|A|Admin PIN" msgstr "|A|Admin PIN" #. TRANSLATORS: Do not translate the "|*|" prefixes but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1525 +#: scd/app-openpgp.c:1530 msgid "|AN|New Admin PIN" msgstr "|AN|Neue Admin PIN" -#: scd/app-openpgp.c:1525 +#: scd/app-openpgp.c:1530 msgid "|N|New PIN" msgstr "|N|Neue PIN" -#: scd/app-openpgp.c:1529 +#: scd/app-openpgp.c:1534 #, c-format msgid "error getting new PIN: %s\n" msgstr "Fehler beim Holen der neuen PIN: %s\n" -#: scd/app-openpgp.c:1579 scd/app-openpgp.c:2028 +#: scd/app-openpgp.c:1584 scd/app-openpgp.c:2033 msgid "error reading application data\n" msgstr "Fehler beim Lesen der Anwendungsdaten\n" -#: scd/app-openpgp.c:1585 scd/app-openpgp.c:2035 +#: scd/app-openpgp.c:1590 scd/app-openpgp.c:2040 msgid "error reading fingerprint DO\n" msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" -#: scd/app-openpgp.c:1595 +#: scd/app-openpgp.c:1600 msgid "key already exists\n" msgstr "Schlüssel existiert bereits\n" -#: scd/app-openpgp.c:1599 +#: scd/app-openpgp.c:1604 msgid "existing key will be replaced\n" msgstr "Existierender Schlüssel wird ersetzt\n" -#: scd/app-openpgp.c:1601 +#: scd/app-openpgp.c:1606 msgid "generating new key\n" msgstr "Neuer Schlüssel wird erzeugt\n" -#: scd/app-openpgp.c:1768 +#: scd/app-openpgp.c:1773 msgid "creation timestamp missing\n" msgstr "Erzeugungsdatum fehlt\n" -#: scd/app-openpgp.c:1775 +#: scd/app-openpgp.c:1780 #, c-format msgid "RSA modulus missing or not of size %d bits\n" msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1782 +#: scd/app-openpgp.c:1787 #, c-format msgid "RSA public exponent missing or larger than %d bits\n" msgstr "Der öffentliche RSA Exponent fehlt oder ist länger als %d Bits\n" -#: scd/app-openpgp.c:1790 scd/app-openpgp.c:1797 +#: scd/app-openpgp.c:1795 scd/app-openpgp.c:1802 #, c-format msgid "RSA prime %s missing or not of size %d bits\n" msgstr "Die RSA Primzahl %s fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1860 +#: scd/app-openpgp.c:1865 #, c-format msgid "failed to store the key: %s\n" msgstr "Fehler beim Speichern des Schlüssels: %s\n" -#: scd/app-openpgp.c:1919 +#: scd/app-openpgp.c:1924 msgid "please wait while key is being generated ...\n" msgstr "Bitte warten bis der Schlüssel erzeugt wurde ...\n" -#: scd/app-openpgp.c:1933 +#: scd/app-openpgp.c:1938 msgid "generating key failed\n" msgstr "Fehler beim Erzeugen des Schlüssels\n" -#: scd/app-openpgp.c:1936 +#: scd/app-openpgp.c:1941 #, c-format msgid "key generation completed (%d seconds)\n" msgstr "Schlüsselerzeugung vollendet (%d Sekunden)\n" -#: scd/app-openpgp.c:1993 +#: scd/app-openpgp.c:1998 msgid "invalid structure of OpenPGP card (DO 0x93)\n" msgstr "Ungültige Struktur der OpenPGP Karte (DO 0x93)\n" -#: scd/app-openpgp.c:2162 +#: scd/app-openpgp.c:2167 #, c-format msgid "signatures created so far: %lu\n" msgstr "Anzahl bereits erzeugter Signaturen: %lu\n" -#: scd/app-openpgp.c:2170 +#: scd/app-openpgp.c:2175 #, c-format msgid "||Please enter the PIN%%0A[sigs done: %lu]" msgstr "||Bitte geben Sie die PIN ein%%0A[Sigs bisher: %lu]" -#: scd/app-openpgp.c:2431 +#: scd/app-openpgp.c:2436 msgid "" "verification of Admin PIN is currently prohibited through this command\n" msgstr "" "Die Überprüfung der Admin PIN is momentan durch ein Kommando verboten " "worden\n" -#: scd/app-openpgp.c:2502 scd/app-openpgp.c:2512 +#: scd/app-openpgp.c:2509 scd/app-openpgp.c:2519 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n" @@ -802,23 +806,23 @@ msgstr "keine" msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:496 -msgid "[Error - No name]" -msgstr "[Fehler - Kein Name]" - -#: sm/certdump.c:510 -msgid "[Error - unknown encoding]" -msgstr "[Fehler - Unbekannte Kodierung]" - -#: sm/certdump.c:514 +#: sm/certdump.c:498 sm/certdump.c:561 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungültige Kodierung]" -#: sm/certdump.c:519 +#: sm/certdump.c:506 +msgid "[Error - out of core]" +msgstr "[Fehler - Nich genügend Speicher]" + +#: sm/certdump.c:541 +msgid "[Error - No name]" +msgstr "[Fehler - Kein Name]" + +#: sm/certdump.c:566 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungültiger DN]" -#: sm/certdump.c:680 +#: sm/certdump.c:727 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -836,7 +840,7 @@ msgid "no key usage specified - assuming all usages\n" msgstr "" "Schlüsselverwendungszweck nicht vorhanden - für alle Zwecke akzeptiert\n" -#: sm/certlist.c:132 sm/keylist.c:224 +#: sm/certlist.c:132 sm/keylist.c:245 #, c-format msgid "error getting key usage information: %s\n" msgstr "Fehler beim holen der Schlüsselbenutzungsinformationen: %s\n" @@ -902,7 +906,7 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" msgid "number of issuers matching: %d\n" msgstr "Anzahl der übereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:503 sm/certchain.c:662 sm/certchain.c:1031 sm/decrypt.c:260 +#: sm/certchain.c:503 sm/certchain.c:665 sm/certchain.c:1103 sm/decrypt.c:260 #: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" @@ -929,64 +933,64 @@ msgstr "" msgid "checking the CRL failed: %s" msgstr "Die CRL konnte nicht geprüft werden: %s" -#: sm/certchain.c:682 +#: sm/certchain.c:685 msgid "no issuer found in certificate" msgstr "Im Zertifikat ist kein Herausgeber enthalten" -#: sm/certchain.c:695 +#: sm/certchain.c:698 #, c-format msgid "certificate with invalid validity: %s" msgstr "Zertifikat mit unzulässiger Gültigkeit: %s" -#: sm/certchain.c:711 +#: sm/certchain.c:714 msgid "certificate not yet valid" msgstr "Das Zertifikat ist noch nicht gültig" -#: sm/certchain.c:724 +#: sm/certchain.c:727 msgid "certificate has expired" msgstr "Das Zertifikat ist abgelaufen" -#: sm/certchain.c:761 +#: sm/certchain.c:764 msgid "self-signed certificate has a BAD signature" msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:779 +#: sm/certchain.c:829 msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswürdig markiert" -#: sm/certchain.c:790 +#: sm/certchain.c:840 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:795 +#: sm/certchain.c:845 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswürdig markiert\n" -#: sm/certchain.c:810 +#: sm/certchain.c:860 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prüfen der vertrauenswürdigen Zertifikate: %s\n" -#: sm/certchain.c:836 sm/import.c:157 +#: sm/certchain.c:886 sm/import.c:157 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:848 +#: sm/certchain.c:898 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:881 +#: sm/certchain.c:931 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:911 +#: sm/certchain.c:961 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes möglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:934 +#: sm/certchain.c:984 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist länger als von der CA erlaubt (%d)" @@ -1346,28 +1350,28 @@ msgstr "Die Bibliothek Libksba is nicht aktuell (benötige %s, habe %s)\n" msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm könnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1233 +#: sm/gpgsm.c:1238 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausführung mit gefälschter Systemzeit: " -#: sm/gpgsm.c:1259 +#: sm/gpgsm.c:1264 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewählte Verschlüsselungsverfahren ist ungültig\n" -#: sm/gpgsm.c:1267 +#: sm/gpgsm.c:1272 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewählte Hashverfahren ist ungültig\n" -#: sm/gpgsm.c:1297 +#: sm/gpgsm.c:1302 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht möglich: %s\n" -#: sm/gpgsm.c:1470 +#: sm/gpgsm.c:1475 msgid "this command has not yet been implemented\n" msgstr "Diee Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1700 sm/gpgsm.c:1737 +#: sm/gpgsm.c:1705 sm/gpgsm.c:1742 sm/qualified.c:73 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geöffnet werden: %s\n" @@ -1492,27 +1496,83 @@ msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" msgid "error storing flags: %s\n" msgstr "Fehler beim Speichern der Flags: %s\n" -#: sm/verify.c:381 +#: sm/sign.c:443 +#, c-format +msgid "checking for qualified certificate failed: %s\n" +msgstr "Prüfung auf ein qualifiziertes Zertifikats fehlgeschlagen: %s\n" + +#: sm/sign.c:478 sm/verify.c:188 +msgid "(this is the MD2 algorithm)\n" +msgstr "(Dies ist der MD2 Algorithmus)\n" + +#: sm/verify.c:387 msgid "Signature made " msgstr "Signatur erzeugt am " -#: sm/verify.c:385 +#: sm/verify.c:391 msgid "[date not given]" msgstr "[Datum nicht vorhanden]" -#: sm/verify.c:386 +#: sm/verify.c:392 #, c-format msgid " using certificate ID %08lX\n" msgstr "mittels Zertifikat ID %08lX\n" -#: sm/verify.c:499 +#: sm/verify.c:505 msgid "Good signature from" msgstr "Korrekte Signatur von" -#: sm/verify.c:500 +#: sm/verify.c:506 msgid " aka" msgstr " alias" +#: sm/qualified.c:112 +#, c-format +msgid "invalid formatted fingerprint in `%s', line %d\n" +msgstr "Der Fingerabdruck in `%s', Zeile %d is fehlerhaft formatiert\n" + +#: sm/qualified.c:130 +#, c-format +msgid "invalid country code in `%s', line %d\n" +msgstr "Ungültiger Landescode in `%s', Zeile %d\n" + +#: sm/qualified.c:215 +#, c-format +msgid "" +"You are about to create a signature using your certificate:\n" +"\"%s\"\n" +"This will create a qualified signature by law equated to a handwritten " +"signature.\n" +"\n" +"%s%sAre you really sure that you want to do this?" +msgstr "" +"Sie sind dabei, eine Signatur mit dem Zertifikat:\n" +"\"%s\"\n" +"zu erzeugen. Dies wird einen qualifizierte Signatur erzeugen, \n" +"die gesetzlich einer handgeschriebene gleichgestellt ist.\n" +"\n" +"%s%sSind Sie wirklich sicher, da Sie dies möchten?" + +#: sm/qualified.c:224 +msgid "" +"Note, that this software is not officially approved to create or verify such " +"signatures.\n" +msgstr "" +"Bitte beachten Sie, daß diese Software nicht offiziell zur Erzeugung\n" +"oder Prüfung von qualifizierten Signaturen zugelassen ist.\n" + +#: sm/qualified.c:312 +#, c-format +msgid "" +"You are about to create a signature using your certificate:\n" +"\"%s\"\n" +"Note, that this certificate will NOT create a qualified signature!" +msgstr "" +"Sie sind dabei, eine Signatur mit dem Zertifikat:\n" +"\"%s\n" +"zu erzeugen. Bitte beachten Sie, daß dies KEINE qualifizierte\n" +"Signatur erzeugen wird." + #: tools/gpgconf.c:55 msgid "list all components" msgstr "Liste aller Komponenten" @@ -1557,62 +1617,65 @@ msgstr "Benötige ein Komponenten Argument" msgid "Component not found" msgstr "Komponente nicht gefunden" -#: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:499 tools/gpgconf-comp.c:564 -#: tools/gpgconf-comp.c:617 tools/gpgconf-comp.c:686 +#: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:499 tools/gpgconf-comp.c:566 +#: tools/gpgconf-comp.c:619 tools/gpgconf-comp.c:688 msgid "Options controlling the diagnostic output" msgstr "Optionen zur Einstellung Diagnoseausgaben" -#: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:512 tools/gpgconf-comp.c:577 -#: tools/gpgconf-comp.c:630 tools/gpgconf-comp.c:709 +#: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:512 tools/gpgconf-comp.c:579 +#: tools/gpgconf-comp.c:632 tools/gpgconf-comp.c:711 msgid "Options controlling the configuration" msgstr "Optionen zur Einstellung der Konfiguration" -#: tools/gpgconf-comp.c:458 tools/gpgconf-comp.c:535 tools/gpgconf-comp.c:584 -#: tools/gpgconf-comp.c:640 tools/gpgconf-comp.c:716 +#: tools/gpgconf-comp.c:458 tools/gpgconf-comp.c:537 tools/gpgconf-comp.c:586 +#: tools/gpgconf-comp.c:642 tools/gpgconf-comp.c:718 msgid "Options useful for debugging" msgstr "Nützliche Optionen zum Debuggen" -#: tools/gpgconf-comp.c:463 tools/gpgconf-comp.c:540 tools/gpgconf-comp.c:589 -#: tools/gpgconf-comp.c:645 tools/gpgconf-comp.c:724 +#: tools/gpgconf-comp.c:463 tools/gpgconf-comp.c:542 tools/gpgconf-comp.c:591 +#: tools/gpgconf-comp.c:647 tools/gpgconf-comp.c:726 msgid "|FILE|write server mode logs to FILE" msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" -#: tools/gpgconf-comp.c:471 tools/gpgconf-comp.c:545 tools/gpgconf-comp.c:653 +#: tools/gpgconf-comp.c:471 tools/gpgconf-comp.c:547 tools/gpgconf-comp.c:655 msgid "Options controlling the security" msgstr "Optionen zur Einstellung der Sicherheit" -#: tools/gpgconf-comp.c:597 +#: tools/gpgconf-comp.c:599 msgid "Configuration for Keyservers" msgstr "Konfiguration der Schlüsselserver" -#: tools/gpgconf-comp.c:658 +#: tools/gpgconf-comp.c:660 msgid "do not check CRLs for root certificates" msgstr "CRL bei Wurzelzertifikaten nicht überprüfen" -#: tools/gpgconf-comp.c:699 +#: tools/gpgconf-comp.c:701 msgid "Options controlling the format of the output" msgstr "Optionen zum Einstellen der Ausgabeformate" -#: tools/gpgconf-comp.c:735 +#: tools/gpgconf-comp.c:737 msgid "Options controlling the interactivity and enforcement" msgstr "Optionen zur Einstellung der Interaktivität und Geltendmachung" -#: tools/gpgconf-comp.c:745 +#: tools/gpgconf-comp.c:747 msgid "Configuration for HTTP servers" msgstr "Konfiguration für HTTP Server" -#: tools/gpgconf-comp.c:756 +#: tools/gpgconf-comp.c:758 msgid "use system's HTTP proxy setting" msgstr "Einstellungen des System HTTP-Proxy benutzen" -#: tools/gpgconf-comp.c:761 +#: tools/gpgconf-comp.c:763 msgid "Configuration of LDAP servers to use" msgstr "Konfiguration der zu nutzenden LDAP-Server" -#: tools/gpgconf-comp.c:798 +#: tools/gpgconf-comp.c:800 msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" +#~ msgid "[Error - unknown encoding]" +#~ msgstr "[Fehler - Unbekannte Kodierung]" + #~ msgid "do not allow multiple connections" #~ msgstr "Nicht mehr als eine Verbindung erlauben" diff --git a/sm/qualified.c b/sm/qualified.c index 4a2b6587f..804b6c41e 100644 --- a/sm/qualified.c +++ b/sm/qualified.c @@ -221,8 +221,8 @@ gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert) subject? subject:"?", opt.qualsig_approval? "": - "Note that this software is not officially approved " - "to create or verify such signatures.\n", + _("Note, that this software is not officially approved " + "to create or verify such signatures.\n"), opt.qualsig_approval? "":"\n" ) < 0 ) err = gpg_error_from_errno (errno); -- cgit v1.2.3 From 6a13cf2c3dbacb9f3afd3f64e5d0c78b9c0e77e9 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 28 Nov 2005 11:52:25 +0000 Subject: Preparing an interim release --- ChangeLog | 16 +++++ NEWS | 7 ++ TODO | 1 - agent/ChangeLog | 17 +++++ agent/agent.h | 7 +- agent/call-scd.c | 51 +++++++++----- agent/command.c | 9 ++- agent/divert-scd.c | 19 ++++- agent/minip12.c | 21 ++++-- agent/query.c | 196 +++++++++++++++++++++++++++++++++++++++++++-------- agent/t-protect.c | 3 +- am/cmacros.am | 3 +- configure.ac | 11 +-- kbx/keybox-blob.c | 2 +- po/POTFILES.in | 1 + po/de.po | 16 +++-- scd/ChangeLog | 55 +++++++++++++++ scd/apdu.c | 176 +++++++++++++++++++++++++++++++++++---------- scd/apdu.h | 9 ++- scd/app-dinsig.c | 41 +++++++++-- scd/app-nks.c | 11 +-- scd/app-openpgp.c | 9 ++- scd/app-p15.c | 13 ++-- scd/ccid-driver.c | 64 ++++++++++++++--- scd/ccid-driver.h | 7 +- scd/iso7816.c | 115 +++++++++++++++++++++++++----- scd/iso7816.h | 35 ++++++++- scd/scdaemon.c | 6 +- scd/scdaemon.h | 17 ++--- tools/ChangeLog | 8 +++ tools/gpgconf-comp.c | 7 +- tools/rfc822parse.c | 1 + 32 files changed, 784 insertions(+), 170 deletions(-) diff --git a/ChangeLog b/ChangeLog index f63a035cc..46d66ed47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2005-11-28 Werner Koch <wk@g10code.com> + + * configure.ac: Append the revision to the version string. + +2005-11-13 Werner Koch <wk@g10code.com> + + * am/cmacros.am (-DGNUPG_SYSCONFDIR): Define it. + +2005-11-11 Werner Koch <wk@g10code.com> + + * configure.ac (NEED_KSBA_VERSION: Require 0.9.13. + +2005-09-12 Werner Koch <wk@g10code.com> + + Released 1.9.19. + 2005-08-01 Werner Koch <wk@g10code.com> Released 1.9.18. diff --git a/NEWS b/NEWS index 1e1148748..edf29885d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +Noteworthy changes in version 1.9.20 +------------------------------------------------- + + * [scdaemon] Support for keypads of some readers. Tested only with + SPR532. New option --disable-keypad. + + Noteworthy changes in version 1.9.19 (2005-09-12) ------------------------------------------------- diff --git a/TODO b/TODO index 32b728588..50f58cee9 100644 --- a/TODO +++ b/TODO @@ -26,7 +26,6 @@ might want to have an agent context for each service request * 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 ** support the anyPolicy semantic ** Check that we are really following the verification procedures in rfc3280. diff --git a/agent/ChangeLog b/agent/ChangeLog index 975484007..105178730 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,20 @@ +2005-11-24 Werner Koch <wk@g10code.com> + + * minip12.c (p12_parse): Fixed for case that the key object comes + prior to the certificate. + +2005-10-19 Werner Koch <wk@g10code.com> + + * divert-scd.c (getpin_cb): Hack to use it for a keypad message. + + * call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO. + + * query.c (start_pinentry): Keep track of the owner. + (popup_message_thread, agent_popup_message_start) + (agent_popup_message_stop, agent_reset_query): New. + * command.c (start_command_handler): Make sure a popup window gets + closed. + 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpg_protect_tool_LDADD): Add ../gl/libgnu.a. diff --git a/agent/agent.h b/agent/agent.h index 7a646a85f..0918395ce 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -133,7 +133,7 @@ struct server_control_s int have_keygrip; int use_auth_call; /* Hack to send the PKAUTH command instead of the - PKSIGN command tro scdaemon. */ + PKSIGN command to the scdaemon. */ }; typedef struct server_control_s *CTRL; typedef struct server_control_s *ctrl_t; @@ -200,6 +200,7 @@ int agent_key_available (const unsigned char *grip); /*-- query.c --*/ void initialize_module_query (void); void agent_query_dump_state (void); +void agent_reset_query (ctrl_t ctrl); int agent_askpin (ctrl_t ctrl, const char *desc_text, const char *prompt_text, const char *inital_errtext, @@ -209,6 +210,10 @@ int agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *errtext); int agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok, const char *cancel); +int agent_popup_message_start (ctrl_t ctrl, const char *desc, + const char *ok_btn, const char *cancel_btn); +void agent_popup_message_stop (ctrl_t ctrl); + /*-- cache.c --*/ void agent_flush_cache (void); diff --git a/agent/call-scd.c b/agent/call-scd.c index 7a623fda4..a883f2733 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -633,26 +633,43 @@ inq_needpin (void *opaque, const char *line) size_t pinlen; int rc; - if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))) + if (!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])) { - log_error ("unsupported inquiry `%s'\n", line); - return ASSUAN_Inquire_Unknown; - } - line += 7; - while (*line == ' ') - line++; + line += 7; + while (*line == ' ') + line++; + + pinlen = 90; + pin = gcry_malloc_secure (pinlen); + if (!pin) + return ASSUAN_Out_Of_Core; - pinlen = 90; - pin = gcry_malloc_secure (pinlen); - if (!pin) - return ASSUAN_Out_Of_Core; + rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen); + if (rc) + rc = ASSUAN_Canceled; + if (!rc) + rc = assuan_send_data (parm->ctx, pin, pinlen); + xfree (pin); + } + else if (!strncmp (line, "KEYPADINFO", 10) && (line[10] == ' ' || !line[10])) + { + size_t code; + char *endp; - rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen); - if (rc) - rc = ASSUAN_Canceled; - if (!rc) - rc = assuan_send_data (parm->ctx, pin, pinlen); - xfree (pin); + code = strtoul (line+10, &endp, 10); + line = endp; + while (*line == ' ') + line++; + + rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, code); + if (rc) + rc = ASSUAN_Canceled; + } + else + { + log_error ("unsupported inquiry `%s'\n", line); + rc = ASSUAN_Inquire_Unknown; + } return rc; } diff --git a/agent/command.c b/agent/command.c index c39bcc6ab..daf9b8698 100644 --- a/agent/command.c +++ b/agent/command.c @@ -316,11 +316,11 @@ cmd_sigkey (ASSUAN_CONTEXT ctx, char *line) this command is not used a default text will be used. Note, that this description implictly selects the label used for the entry box; if the string contains the string PIN (which in general will - not be translated), "PIN" is used, other wiese the translation of + not be translated), "PIN" is used, otherwise the translation of 'passphrase" is used. The description string should not contain blanks unless they are percent or '+' escaped. - The descrition is only valid for the next PKSIGN or PKDECRYPT + The description is only valid for the next PKSIGN or PKDECRYPT operation. */ static int @@ -399,7 +399,7 @@ cmd_sethash (ASSUAN_CONTEXT ctx, char *line) /* PKSIGN <options> Perform the actual sign operation. Neither input nor output are - sensitive to eavesdropping */ + sensitive to eavesdropping. */ static int cmd_pksign (ASSUAN_CONTEXT ctx, char *line) { @@ -1085,6 +1085,9 @@ start_command_handler (int listen_fd, int fd) /* Reset the SCD if needed. */ agent_reset_scd (&ctrl); + /* Reset the pinentry (in case of popup messages). */ + agent_reset_query (&ctrl); + assuan_deinit_server (ctx); if (ctrl.display) free (ctrl.display); diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 9d2fa446c..926df2622 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -204,7 +204,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) const char *again_text = NULL; const char *prompt = "PIN"; - if (maxbuf < 2) + if (buf && maxbuf < 2) return gpg_error (GPG_ERR_INV_VALUE); /* Parse the flags. */ @@ -223,6 +223,23 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf) else if (info && *info == '|') log_debug ("pin_cb called without proper PIN info hack\n"); + /* If BUF has been passed as NULL, we are in keypad mode: The + callback opens the popup and immediatley returns. */ + if (!buf) + { + if (maxbuf == 0) /* Close the pinentry. */ + { + agent_popup_message_stop (ctrl); + rc = 0; + } + else if (maxbuf == 1) /* Open the pinentry. */ + { + rc = agent_popup_message_start (ctrl, info, NULL, NULL); + } + else + rc = gpg_error (GPG_ERR_INV_VALUE); + return rc; + } /* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole mess because we should call the card's verify function from the diff --git a/agent/minip12.c b/agent/minip12.c index 91eef63f4..55f3946bf 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -511,7 +511,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, goto bailout; } - /* Loop over all certificates inside the bab. */ + /* Loop over all certificates inside the bag. */ while (n) { int isbag = 0; @@ -860,6 +860,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, size_t n = length; const char *where; int bagseqlength, len; + gcry_mpi_t *result = NULL; where = "pfx"; if (parse_tag (&p, &n, &ti)) @@ -936,10 +937,17 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data) && !memcmp (p, oid_data, DIM(oid_data))) { - p += DIM(oid_data); - n -= DIM(oid_data); - len -= DIM(oid_data); - return parse_bag_data (p, n, (p-buffer), pw); + if (result) + log_info ("already got an data object, skipping next one\n"); + else + { + p += DIM(oid_data); + n -= DIM(oid_data); + len -= DIM(oid_data); + result = parse_bag_data (p, n, (p-buffer), pw); + if (!result) + goto bailout; + } } else log_info ( "unknown bag type - skipped\n"); @@ -950,9 +958,10 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, n -= len; } - return NULL; + return result; bailout: log_error ("error at \"%s\", offset %u\n", where, (p - buffer)); + /* fixme: need to release RESULT. */ return NULL; } diff --git a/agent/query.c b/agent/query.c index b231f6fc3..a5a3d0153 100644 --- a/agent/query.c +++ b/agent/query.c @@ -27,9 +27,10 @@ #include <assert.h> #include <unistd.h> #include <sys/stat.h> -#ifdef USE_GNU_PTH -# include <pth.h> +#ifndef HAVE_W32_SYSTEM +#include <sys/wait.h> #endif +#include <pth.h> #include "agent.h" #include "i18n.h" @@ -48,14 +49,30 @@ time. */ #define LOCK_TIMEOUT (1*60) +/* The assuan context of the current pinentry. */ +static assuan_context_t entry_ctx; -static assuan_context_t entry_ctx = NULL; -#ifdef USE_GNU_PTH +/* The control variable of the connection owning the current pinentry. + This is only valid if ENTRY_CTX is not NULL. Note, that we care + only about the value of the pointer and that it should never be + dereferenced. */ +static ctrl_t entry_owner; + +/* A mutex used to serialize access to the pinentry. */ static pth_mutex_t entry_lock; -#endif -/* data to be passed to our callbacks */ -struct entry_parm_s { +/* The thread ID of the popup working thread. */ +static pth_t popup_tid; + +/* A flag used in communication between the popup working thread and + its stop function. */ +static int popup_finished; + + + +/* Data to be passed to our callbacks, */ +struct entry_parm_s +{ int lines; size_t size; unsigned char *buffer; @@ -67,17 +84,17 @@ struct entry_parm_s { /* This function must be called once to initialize this module. This has to be done before a second thread is spawned. We can't do the static initialization because Pth emulation code might not be able - to do a static init; in particualr, it is not possible for W32. */ + to do a static init; in particular, it is not possible for W32. */ void initialize_module_query (void) { -#ifdef USE_GNU_PTH static int initialized; if (!initialized) - if (pth_mutex_init (&entry_lock)) - initialized = 1; -#endif /*USE_GNU_PTH*/ + { + if (pth_mutex_init (&entry_lock)) + initialized = 1; + } } @@ -102,8 +119,19 @@ agent_query_dump_state (void) log_info ("agent_query_dump_state: entry_lock="); dump_mutex_state (&entry_lock); log_printf ("\n"); - log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld\n", - entry_ctx, (long)assuan_get_pid (entry_ctx)); + log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n", + entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid); +} + +/* Called to make sure that a popup window owned by the current + connection gets closed. */ +void +agent_reset_query (ctrl_t ctrl) +{ + if (entry_ctx && popup_tid && entry_owner == ctrl) + { + agent_popup_message_stop (ctrl); + } } @@ -117,14 +145,12 @@ unlock_pinentry (int rc) assuan_context_t ctx = entry_ctx; entry_ctx = NULL; -#ifdef USE_GNU_PTH if (!pth_mutex_release (&entry_lock)) { log_error ("failed to release the entry lock\n"); if (!rc) rc = gpg_error (GPG_ERR_INTERNAL); } -#endif assuan_disconnect (ctx); return rc; } @@ -145,7 +171,7 @@ atfork_cb (void *opaque, int where) pinentry - we will serialize _all_ pinentry calls. */ static int -start_pinentry (CTRL ctrl) +start_pinentry (ctrl_t ctrl) { int rc; const char *pgmname; @@ -153,13 +179,10 @@ start_pinentry (CTRL ctrl) const char *argv[5]; int no_close_list[3]; int i; + pth_event_t evt; -#ifdef USE_GNU_PTH - { - pth_event_t evt; - - evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0)); - if (!pth_mutex_acquire (&entry_lock, 0, evt)) + evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0)); + if (!pth_mutex_acquire (&entry_lock, 0, evt)) { if (pth_event_occurred (evt)) rc = gpg_error (GPG_ERR_TIMEOUT); @@ -170,9 +193,9 @@ start_pinentry (CTRL ctrl) gpg_strerror (rc)); return rc; } - pth_event_free (evt, PTH_FREE_THIS); - } -#endif + pth_event_free (evt, PTH_FREE_THIS); + + entry_owner = ctrl; if (entry_ctx) return 0; @@ -436,7 +459,7 @@ agent_askpin (ctrl_t ctrl, passphrase is returned in RETPASS as an hex encoded string to be freed by the caller */ int -agent_get_passphrase (CTRL ctrl, +agent_get_passphrase (ctrl_t ctrl, char **retpass, const char *desc, const char *prompt, const char *errtext) { @@ -517,11 +540,11 @@ agent_get_passphrase (CTRL ctrl, /* Pop up the PIN-entry, display the text and the prompt and ask the - user to confirm this. We return 0 for success, ie. the used + user to confirm this. We return 0 for success, ie. the user confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an other error. */ int -agent_get_confirmation (CTRL ctrl, +agent_get_confirmation (ctrl_t ctrl, const char *desc, const char *ok, const char *cancel) { int rc; @@ -562,4 +585,119 @@ agent_get_confirmation (CTRL ctrl, } +/* The thread running the popup message. */ +static void * +popup_message_thread (void *arg) +{ + assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL); + popup_finished = 1; + return NULL; +} + + +/* Pop up a message window similar to the confirm one but keep it open + until agent_popup_message_stop has been called. It is crucial for + the caller to make sure that the stop function gets called as soon + as the message is not anymore required becuase the message is + system modal and all other attempts to use the pinentry will fail + (after a timeout). */ +int +agent_popup_message_start (ctrl_t ctrl, const char *desc, + const char *ok_btn, const char *cancel_btn) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + pth_attr_t tattr; + + rc = start_pinentry (ctrl); + if (rc) + return rc; + + if (desc) + snprintf (line, DIM(line)-1, "SETDESC %s", desc); + else + snprintf (line, DIM(line)-1, "RESET"); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + + if (ok_btn) + { + snprintf (line, DIM(line)-1, "SETOK %s", ok_btn); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + if (cancel_btn) + { + snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn); + line[DIM(line)-1] = 0; + rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL); + if (rc) + return unlock_pinentry (map_assuan_err (rc)); + } + + tattr = pth_attr_new(); + pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1); + pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024); + pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message"); + + popup_finished = 0; + popup_tid = pth_spawn (tattr, popup_message_thread, NULL); + if (!popup_tid) + { + rc = gpg_error_from_errno (errno); + log_error ("error spawning popup message handler: %s\n", + strerror (errno) ); + pth_attr_destroy (tattr); + return unlock_pinentry (rc); + } + pth_attr_destroy (tattr); + + return 0; +} + +/* Close a popup window. */ +void +agent_popup_message_stop (ctrl_t ctrl) +{ + int rc; + pid_t pid; + + if (!popup_tid || !entry_ctx) + { + log_debug ("agent_popup_message_stop called with no active popup\n"); + return; + } + + pid = assuan_get_pid (entry_ctx); + if (pid == (pid_t)(-1)) + ; /* No pid available can't send a kill. */ + else if (popup_finished) + ; /* Already finished and ready for joining. */ + else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) + { /* The daemon already died. No need to send a kill. However + because we already waited for the process, we need to tell + assuan that it should not wait again (done by + unlock_pinentry). */ + if (rc == pid) + assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1); + } + else + kill (pid, SIGINT); + + /* Now wait for the thread to terminate. */ + rc = pth_join (popup_tid, NULL); + if (!rc) + log_debug ("agent_popup_message_stop: pth_join failed: %s\n", + strerror (errno)); + popup_tid = NULL; + entry_owner = NULL; + + /* Now we can close the connection. */ + unlock_pinentry (0); +} + diff --git a/agent/t-protect.c b/agent/t-protect.c index 5187cf8f7..fee3c561d 100644 --- a/agent/t-protect.c +++ b/agent/t-protect.c @@ -173,7 +173,8 @@ test_agent_protect (void) for (i = 0; i < DIM (specs); i++) { - ret = agent_protect (specs[i].key, specs[i].passphrase, + ret = agent_protect ((const unsigned char*)specs[i].key, + specs[i].passphrase, &specs[i].result, &specs[i].resultlen); if (gpg_err_code (ret) != specs[i].ret_expected) { diff --git a/am/cmacros.am b/am/cmacros.am index 0f7a09fe0..de68b6f31 100644 --- a/am/cmacros.am +++ b/am/cmacros.am @@ -25,7 +25,8 @@ if ! HAVE_DOSISH_SYSTEM AM_CPPFLAGS += -DGNUPG_BINDIR="\"$(bindir)\"" \ -DGNUPG_LIBEXECDIR="\"$(libexecdir)\"" \ -DGNUPG_LIBDIR="\"$(libdir)/@PACKAGE@\"" \ - -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" + -DGNUPG_DATADIR="\"$(datadir)/@PACKAGE@\"" \ + -DGNUPG_SYSCONFDIR="\"$(sysconfdir)/@PACKAGE@\"" endif if GNUPG_AGENT_PGM diff --git a/configure.ac b/configure.ac index 30b183046..6ba66968d 100644 --- a/configure.ac +++ b/configure.ac @@ -22,9 +22,12 @@ AC_PREREQ(2.52) min_automake_version="1.9.3" -# Version number: Remember to change it immediately *after* a release. -# Add a "-cvs" prefix for non-released code. -AC_INIT(gnupg, 1.9.19, gnupg-devel@gnupg.org) +# Remember to change the version number immediately *after* a release. +# Uncomment the my_iscvs macro for non-released code. +m4_define(my_version, [1.9.20]) +m4_define(my_iscvs, yes) +AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit( + [$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org]) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -36,7 +39,7 @@ NEED_LIBGCRYPT_VERSION=1.1.94 NEED_LIBASSUAN_VERSION=0.6.10 -NEED_KSBA_VERSION=0.9.12 +NEED_KSBA_VERSION=0.9.13 PACKAGE=$PACKAGE_NAME diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index 67c74b777..eacc0014a 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -61,7 +61,7 @@ X.509 specific are noted like [X.509: xxx] u32 offset to the n-th key's keyID (a keyID is always 8 byte) or 0 if not known which is the case only for X509. u16 special key flags - bit 0 = + bit 0 = qualified signature (not yet implemented} u16 reserved u16 size of serialnumber(may be zero) n u16 (see above) bytes of serial number diff --git a/po/POTFILES.in b/po/POTFILES.in index 8fff858db..eb5711ddb 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -17,6 +17,7 @@ kbx/kbxutil.c scd/scdaemon.c scd/app-openpgp.c +scd/app-nks.c sm/base64.c sm/call-agent.c diff --git a/po/de.po b/po/de.po index 6b28544cb..2201c0429 100644 --- a/po/de.po +++ b/po/de.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-11-23 13:00+0100\n" -"PO-Revision-Date: 2005-11-23 13:02+0100\n" +"POT-Creation-Date: 2005-11-28 12:14+0100\n" +"PO-Revision-Date: 2005-11-28 12:16+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -766,6 +766,10 @@ msgstr "" msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n" +#: scd/app-nks.c:344 +msgid "the NullPIN has not yet been changed\n" +msgstr "Die Nullpin wurde noch nicht geändert\n" + #: sm/base64.c:317 #, c-format msgid "invalid radix64 character %02x skipped\n" @@ -1369,7 +1373,7 @@ msgstr "Signieren mit `%s' nicht möglich: %s\n" #: sm/gpgsm.c:1475 msgid "this command has not yet been implemented\n" -msgstr "Diee Kommando wurde noch nicht implementiert\n" +msgstr "Dieses Kommando wurde noch nicht implementiert\n" #: sm/gpgsm.c:1705 sm/gpgsm.c:1742 sm/qualified.c:73 #, c-format @@ -1548,10 +1552,10 @@ msgid "" msgstr "" "Sie sind dabei, eine Signatur mit dem Zertifikat:\n" "\"%s\"\n" -"zu erzeugen. Dies wird einen qualifizierte Signatur erzeugen, \n" -"die gesetzlich einer handgeschriebene gleichgestellt ist.\n" +"zu erzeugen. Dies wird eine qualifizierte Signatur erzeugen, \n" +"die gesetzlich einer handgeschriebenen gleichgestellt ist.\n" "\n" -"%s%sSind Sie wirklich sicher, da Sie dies möchten?" +"%s%sSind Sie wirklich sicher, daß Sie dies möchten?" #: sm/qualified.c:224 msgid "" diff --git a/scd/ChangeLog b/scd/ChangeLog index ccea117dd..008d84080 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,8 +1,63 @@ +2005-11-23 Werner Koch <wk@g10code.com> + + * app-nks.c (verify_pin): Give a special error message for a Nullpin. + +2005-10-29 Werner Koch <wk@g10code.com> + + * ccid-driver.c (send_escape_cmd): New args RESULT, RESULTLEN and + RESULTMAX. Changed all callers. + (ccid_transceive_escape): New. + +2005-10-27 Werner Koch <wk@g10code.com> + + * apdu.c [__CYGWIN__]: Make cygwin environment similar to _WIN32. + Suggested by John P. Clizbe. + * scdaemon.c [__CYGWIN__]: Set default PC/SC driver to winscard.dll. + +2005-10-19 Werner Koch <wk@g10code.com> + + * ccid-driver.h (CCID_DRIVER_ERR_NO_KEYPAD): New. + * apdu.h (SW_HOST_NO_KEYPAD): New. + * iso7816.h (struct iso7816_pininfo_s): New. + * iso7816.c (map_sw): Support new code. + (iso7816_check_keypad): New. + (iso7816_verify_kp, iso7816_change_reference_data_kp) + (iso7816_reset_retry_counter_kp): New. Extended versions of the + original functions. + * apdu.c (host_sw_string): Support new code. + (reader_table_s): New field CHECK_KEYPAD. + (new_reader_slot, open_ct_reader, open_pcsc_reader) + (open_ccid_reader, open_rapdu_reader): Initialize it. + (check_ccid_keypad): New. + (apdu_check_keypad): New. + (apdu_send_le): Factored all code out to ... + (send_le): .. new. Takes an additional arg; changed all callers + of the orginal function to use this one with a NULL for the new + arg. + (apdu_send_simple_kp): New. + (ct_send_apdu, pcsc_send_apdu, my_rapdu_send_apdu) + (send_apdu_ccid): New arg PININFO. + (send_apdu_ccid): Use the new arg. + + * scdaemon.c: New option --disable-keypad. + 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (scdaemon_LDADD): Add ../gl/libgnu.a after ../common/libcommon.a. +2005-09-20 Werner Koch <wk@g10code.com> + + * app-dinsig.c (verify_pin): Try ISO 9564 BCD encoding. + + * iso7816.c (iso7816_select_application): Add arg FLAGS. Changed + all callers to pass 0. + * app-openpgp.c (app_select_openpgp): But this one requires a + special flag. + + * app-p15.c (app_select_p15): Don't use select application for the + BELPIC. + 2005-09-09 Werner Koch <wk@g10code.com> * pcsc-wrapper.c (main): Removed bogus free. diff --git a/scd/apdu.c b/scd/apdu.c index 678ea12d3..f59d832d4 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -66,10 +66,10 @@ #include "ccid-driver.h" -/* To to conflicting use of threading libraries we usually can't link +/* Due to conflicting use of threading libraries we usually can't link against libpcsclite. Instead we use a wrapper program. */ #ifdef USE_GNU_PTH -#ifndef HAVE_W32_SYSTEM +#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__) #define NEED_PCSC_WRAPPER 1 #endif #endif @@ -78,7 +78,7 @@ #define MAX_READER 4 /* Number of readers we support concurrently. */ -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) #define DLSTDCALL __stdcall #else #define DLSTDCALL @@ -90,6 +90,14 @@ #define MAX_OPEN_FDS 20 #endif +/* Helper to pass patrameters related to keypad based operations. */ +struct pininfo_s +{ + int mode; + int minlen; + int maxlen; + int padlen; +}; /* A structure to collect information pertaining to one reader slot. */ @@ -103,7 +111,8 @@ struct reader_table_s { int (*reset_reader)(int); int (*get_status_reader)(int, unsigned int *); int (*send_apdu_reader)(int,unsigned char *,size_t, - unsigned char *, size_t *); + unsigned char *, size_t *, struct pininfo_s *); + int (*check_keypad)(int, int, int, int, int, int); void (*dump_status_reader)(int); struct { @@ -320,6 +329,7 @@ new_reader_slot (void) reader_table[reader].reset_reader = NULL; reader_table[reader].get_status_reader = NULL; reader_table[reader].send_apdu_reader = NULL; + reader_table[reader].check_keypad = NULL; reader_table[reader].dump_status_reader = NULL; reader_table[reader].used = 1; @@ -372,6 +382,7 @@ host_sw_string (long err) case SW_HOST_GENERAL_ERROR: return "general error"; case SW_HOST_NO_READER: return "no reader"; case SW_HOST_ABORTED: return "aborted"; + case SW_HOST_NO_KEYPAD: return "no keypad"; default: return "unknown host status error"; } } @@ -533,7 +544,7 @@ ct_get_status (int slot, unsigned int *status) set to BUFLEN. Returns: CT API error code. */ static int ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) + unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo) { int rc; unsigned char dad[1], sad[1]; @@ -596,6 +607,7 @@ open_ct_reader (int port) reader_table[reader].reset_reader = reset_ct_reader; reader_table[reader].get_status_reader = ct_get_status; reader_table[reader].send_apdu_reader = ct_send_apdu; + reader_table[reader].check_keypad = NULL; reader_table[reader].dump_status_reader = ct_dump_reader_status; dump_reader_status (reader); @@ -1082,7 +1094,8 @@ pcsc_get_status (int slot, unsigned int *status) set to BUFLEN. Returns: CT API error code. */ static int pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) + unsigned char *buffer, size_t *buflen, + struct pininfo_s *pininfo) { #ifdef NEED_PCSC_WRAPPER long err; @@ -1479,6 +1492,7 @@ open_pcsc_reader (const char *portstr) reader_table[slot].reset_reader = reset_pcsc_reader; reader_table[slot].get_status_reader = pcsc_get_status; reader_table[slot].send_apdu_reader = pcsc_send_apdu; + reader_table[slot].check_keypad = NULL; reader_table[slot].dump_status_reader = dump_pcsc_reader_status; /* Read the status so that IS_T0 will be set. */ @@ -1625,6 +1639,7 @@ open_pcsc_reader (const char *portstr) reader_table[slot].reset_reader = reset_pcsc_reader; reader_table[slot].get_status_reader = pcsc_get_status; reader_table[slot].send_apdu_reader = pcsc_send_apdu; + reader_table[slot].check_keypad = NULL; reader_table[slot].dump_status_reader = dump_pcsc_reader_status; /* log_debug ("state from pcsc_status: 0x%lx\n", card_state); */ @@ -1713,7 +1728,8 @@ get_status_ccid (int slot, unsigned int *status) set to BUFLEN. Returns: Internal CCID driver error code. */ static int send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) + unsigned char *buffer, size_t *buflen, + struct pininfo_s *pininfo) { long err; size_t maxbuflen; @@ -1727,9 +1743,18 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, log_printhex (" APDU_data:", apdu, apdulen); maxbuflen = *buflen; - err = ccid_transceive (reader_table[slot].ccid.handle, - apdu, apdulen, - buffer, maxbuflen, buflen); + if (pininfo) + err = ccid_transceive_secure (reader_table[slot].ccid.handle, + apdu, apdulen, + pininfo->mode, + pininfo->minlen, + pininfo->maxlen, + pininfo->padlen, + buffer, maxbuflen, buflen); + else + err = ccid_transceive (reader_table[slot].ccid.handle, + apdu, apdulen, + buffer, maxbuflen, buflen); if (err) log_error ("ccid_transceive failed: (0x%lx)\n", err); @@ -1737,6 +1762,24 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, return err; } + +/* Check whether the CCID reader supports the ISO command code COMMAND + on the keypad. Return 0 on success. For a description of the pin + parameters, see ccid-driver.c */ +static int +check_ccid_keypad (int slot, int command, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen) +{ + unsigned char apdu[] = { 0, 0, 0, 0x81 }; + + apdu[1] = command; + return ccid_transceive_secure (reader_table[slot].ccid.handle, + apdu, sizeof apdu, + pin_mode, pinlen_min, pinlen_max, pin_padlen, + NULL, 0, NULL); +} + + /* Open the reader and try to read an ATR. */ static int open_ccid_reader (const char *portstr) @@ -1776,6 +1819,7 @@ open_ccid_reader (const char *portstr) reader_table[slot].reset_reader = reset_ccid_reader; reader_table[slot].get_status_reader = get_status_ccid; reader_table[slot].send_apdu_reader = send_apdu_ccid; + reader_table[slot].check_keypad = check_ccid_keypad; reader_table[slot].dump_status_reader = dump_ccid_reader_status; dump_reader_status (slot); @@ -1932,7 +1976,8 @@ my_rapdu_get_status (int slot, unsigned int *status) set to BUFLEN. Returns: APDU error code. */ static int my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) + unsigned char *buffer, size_t *buflen, + struct pininfo_s *pininfo) { int err; reader_table_t slotp; @@ -2063,6 +2108,7 @@ open_rapdu_reader (int portno, reader_table[slot].reset_reader = reset_rapdu_reader; reader_table[slot].get_status_reader = my_rapdu_get_status; reader_table[slot].send_apdu_reader = my_rapdu_send_apdu; + reader_table[slot].check_keypad = NULL; reader_table[slot].dump_status_reader = NULL; dump_reader_status (slot); @@ -2198,28 +2244,28 @@ apdu_open_reader (const char *portstr) pcsc_establish_context = dlsym (handle, "SCardEstablishContext"); pcsc_release_context = dlsym (handle, "SCardReleaseContext"); pcsc_list_readers = dlsym (handle, "SCardListReaders"); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) if (!pcsc_list_readers) pcsc_list_readers = dlsym (handle, "SCardListReadersA"); #endif pcsc_get_status_change = dlsym (handle, "SCardGetStatusChange"); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) if (!pcsc_get_status_change) pcsc_get_status_change = dlsym (handle, "SCardGetStatusChangeA"); #endif pcsc_connect = dlsym (handle, "SCardConnect"); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) if (!pcsc_connect) pcsc_connect = dlsym (handle, "SCardConnectA"); #endif pcsc_reconnect = dlsym (handle, "SCardReconnect"); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) if (!pcsc_reconnect) pcsc_reconnect = dlsym (handle, "SCardReconnectA"); #endif pcsc_disconnect = dlsym (handle, "SCardDisconnect"); pcsc_status = dlsym (handle, "SCardStatus"); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) if (!pcsc_status) pcsc_status = dlsym (handle, "SCardStatusA"); #endif @@ -2492,11 +2538,30 @@ apdu_get_status (int slot, int hang, } +/* Check whether the reader supports the ISO command code COMMAND on + the keypad. Return 0 on success. For a description of the pin + parameters, see ccid-driver.c */ +int +apdu_check_keypad (int slot, int command, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen) +{ + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + + if (reader_table[slot].check_keypad) + return reader_table[slot].check_keypad (slot, command, + pin_mode, pinlen_min, pinlen_max, + pin_padlen); + else + return SW_HOST_NOT_SUPPORTED; +} + + /* Dispatcher for the actual send_apdu function. Note, that this function should be called in locked state. */ static int send_apdu (int slot, unsigned char *apdu, size_t apdulen, - unsigned char *buffer, size_t *buflen) + unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo) { if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) return SW_HOST_NO_DRIVER; @@ -2504,24 +2569,20 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen, if (reader_table[slot].send_apdu_reader) return reader_table[slot].send_apdu_reader (slot, apdu, apdulen, - buffer, buflen); + buffer, buflen, pininfo); else return SW_HOST_NOT_SUPPORTED; } -/* Send an APDU to the card in SLOT. The APDU is created from all - given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1 - for LC won't sent this field and the data field; in this case DATA - must also be passed as NULL. The return value is the status word - or -1 for an invalid SLOT or other non card related error. If - RETBUF is not NULL, it will receive an allocated buffer with the - returned data. The length of that data will be put into - *RETBUFLEN. The caller is reponsible for releasing the buffer even - in case of errors. */ -int -apdu_send_le(int slot, int class, int ins, int p0, int p1, - int lc, const char *data, int le, - unsigned char **retbuf, size_t *retbuflen) + +/* Core APDU trabceiver function. Parameters are described at + apdu_send_le with the exception of PININFO which indicates keypad + related operations if not NULL. */ +static int +send_le (int slot, int class, int ins, int p0, int p1, + int lc, const char *data, int le, + unsigned char **retbuf, size_t *retbuflen, + struct pininfo_s *pininfo) { #define RESULTLEN 256 unsigned char result[RESULTLEN+10]; /* 10 extra in case of bugs in @@ -2570,7 +2631,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, /* As safeguard don't pass any garbage from the stack to the driver. */ memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); resultlen = RESULTLEN; - rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + rc = send_apdu (slot, apdu, apdulen, result, &resultlen, pininfo); if (rc || resultlen < 2) { log_error ("apdu_send_simple(%d) failed: %s\n", @@ -2638,7 +2699,7 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, apdu[apdulen++] = len; memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); resultlen = RESULTLEN; - rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL); if (rc || resultlen < 2) { log_error ("apdu_send_simple(%d) for get response failed: %s\n", @@ -2703,6 +2764,27 @@ apdu_send_le(int slot, int class, int ins, int p0, int p1, #undef RESULTLEN } +/* Send an APDU to the card in SLOT. The APDU is created from all + given parameters: CLASS, INS, P0, P1, LC, DATA, LE. A value of -1 + for LC won't sent this field and the data field; in this case DATA + must also be passed as NULL. The return value is the status word + or -1 for an invalid SLOT or other non card related error. If + RETBUF is not NULL, it will receive an allocated buffer with the + returned data. The length of that data will be put into + *RETBUFLEN. The caller is reponsible for releasing the buffer even + in case of errors. */ +int +apdu_send_le(int slot, int class, int ins, int p0, int p1, + int lc, const char *data, int le, + unsigned char **retbuf, size_t *retbuflen) +{ + return send_le (slot, class, ins, p0, p1, + lc, data, le, + retbuf, retbuflen, + NULL); +} + + /* Send an APDU to the card in SLOT. The APDU is created from all given parameters: CLASS, INS, P0, P1, LC, DATA. A value of -1 for LC won't sent this field and the data field; in this case DATA must @@ -2716,8 +2798,8 @@ int apdu_send (int slot, int class, int ins, int p0, int p1, int lc, const char *data, unsigned char **retbuf, size_t *retbuflen) { - return apdu_send_le (slot, class, ins, p0, p1, lc, data, 256, - retbuf, retbuflen); + return send_le (slot, class, ins, p0, p1, lc, data, 256, + retbuf, retbuflen, NULL); } /* Send an APDU to the card in SLOT. The APDU is created from all @@ -2730,7 +2812,25 @@ int apdu_send_simple (int slot, int class, int ins, int p0, int p1, int lc, const char *data) { - return apdu_send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL); + return send_le (slot, class, ins, p0, p1, lc, data, -1, NULL, NULL, NULL); +} + + +/* Same as apdu_send_simple but uses the keypad of the reader. */ +int +apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1, + int lc, const char *data, + int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen) +{ + struct pininfo_s pininfo; + + pininfo.mode = pin_mode; + pininfo.minlen = pinlen_min; + pininfo.maxlen = pinlen_max; + pininfo.padlen = pin_padlen; + return send_le (slot, class, ins, p0, p1, lc, data, -1, + NULL, NULL, &pininfo); } @@ -2771,7 +2871,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, class = apdulen? *apdu : 0; resultlen = RESULTLEN; - rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL); if (rc || resultlen < 2) { log_error ("apdu_send_direct(%d) failed: %s\n", @@ -2825,7 +2925,7 @@ apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, apdu[apdulen++] = len; memset (apdu+apdulen, 0, sizeof (apdu) - apdulen); resultlen = RESULTLEN; - rc = send_apdu (slot, apdu, apdulen, result, &resultlen); + rc = send_apdu (slot, apdu, apdulen, result, &resultlen, NULL); if (rc || resultlen < 2) { log_error ("apdu_send_direct(%d) for get response failed: %s\n", diff --git a/scd/apdu.h b/scd/apdu.h index 45388fdd1..c3af82506 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -63,7 +63,8 @@ enum { SW_HOST_CARD_IO_ERROR = 0x1000a, SW_HOST_GENERAL_ERROR = 0x1000b, SW_HOST_NO_READER = 0x1000c, - SW_HOST_ABORTED = 0x1000d + SW_HOST_ABORTED = 0x1000d, + SW_HOST_NO_KEYPAD = 0x1000e }; @@ -96,8 +97,14 @@ int apdu_activate (int slot); int apdu_reset (int slot); int apdu_get_status (int slot, int hang, unsigned int *status, unsigned int *changed); +int apdu_check_keypad (int slot, int command, int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen); int apdu_send_simple (int slot, int class, int ins, int p0, int p1, int lc, const char *data); +int apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1, + int lc, const char *data, + int pin_mode, + int pinlen_min, int pinlen_max, int pin_padlen); int apdu_send (int slot, int class, int ins, int p0, int p1, int lc, const char *data, unsigned char **retbuf, size_t *retbuflen); diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 28b70c466..75cd12c59 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -1,5 +1,5 @@ /* app-dinsig.c - The DINSIG (DIN V 66291-1) card application. - * Copyright (C) 2002, 2004 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -280,10 +280,11 @@ verify_pin (app_t app, { if (!app->did_chv1 || app->force_chv1 ) { + const char *s; char *pinvalue; int rc; - rc = pincb (pincb_arg, "PIN", &pinvalue); + rc = pincb (pincb_arg, "PIN", &pinvalue); if (rc) { log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); @@ -291,8 +292,16 @@ verify_pin (app_t app, } /* We require the PIN to be at least 6 and at max 8 bytes. - According to the specs, this should all be ASCII but we don't - check this. */ + According to the specs, this should all be ASCII. */ + for (s=pinvalue; digitp (s); s++) + ; + if (*s) + { + log_error ("Non-numeric digits found in PIN\n"); + xfree (pinvalue); + return gpg_error (GPG_ERR_BAD_PIN); + } + if (strlen (pinvalue) < 6) { log_error ("PIN is too short; minimum length is 6\n"); @@ -307,6 +316,28 @@ verify_pin (app_t app, } rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); + if (gpg_err_code (rc) == GPG_ERR_INV_VALUE) + { + /* We assume that ISO 9564-1 encoding is used and we failed + because the first nibble we passed was 3 and not 2. DIN + says something about looking up such an encoding in the + SSD but I was not able to find any tag relevant to + this. */ + char paddedpin[8]; + int i, ndigits; + + for (ndigits=0, s=pinvalue; *s; ndigits++, s++) + ; + i = 0; + paddedpin[i++] = 0x20 | (ndigits & 0x0f); + for (s=pinvalue; i < sizeof paddedpin && *s && s[1]; s = s+2 ) + paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f)); + if (i < sizeof paddedpin && *s) + paddedpin[i++] = (((*s - '0') << 4) | 0x0f); + while (i < sizeof paddedpin) + paddedpin[i++] = 0xff; + rc = iso7816_verify (app->slot, 0x81, paddedpin, sizeof paddedpin); + } if (rc) { log_error ("verify PIN failed\n"); @@ -404,7 +435,7 @@ app_select_dinsig (APP app) int slot = app->slot; int rc; - rc = iso7816_select_application (slot, aid, sizeof aid); + rc = iso7816_select_application (slot, aid, sizeof aid, 0); if (!rc) { app->apptype = "DINSIG"; diff --git a/scd/app-nks.c b/scd/app-nks.c index b6a3037ed..73ec8ea01 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -27,7 +27,7 @@ #include <time.h> #include "scdaemon.h" - +#include "i18n.h" #include "iso7816.h" #include "app-common.h" #include "tlv.h" @@ -320,7 +320,7 @@ verify_pin (app_t app, return rc; } - /* The follwoing limits are due to TCOS but also defined in the + /* The following limits are due to TCOS but also defined in the NKS specs. */ if (strlen (pinvalue) < 6) { @@ -340,7 +340,10 @@ verify_pin (app_t app, rc = iso7816_verify (app->slot, 0, pinvalue, strlen (pinvalue)); if (rc) { - log_error ("verify PIN failed\n"); + if ( gpg_error (rc) == GPG_ERR_USE_CONDITIONS ) + log_error (_("the NullPIN has not yet been changed\n")); + else + log_error ("verify PIN failed\n"); xfree (pinvalue); return rc; } @@ -492,7 +495,7 @@ app_select_nks (APP app) int slot = app->slot; int rc; - rc = iso7816_select_application (slot, aid, sizeof aid); + rc = iso7816_select_application (slot, aid, sizeof aid, 0); if (!rc) { app->apptype = "NKS"; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 5625c729b..3d04be0be 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1284,6 +1284,11 @@ verify_chv2 (app_t app, if (!app->did_chv2) { char *pinvalue; + iso7816_pininfo_t pininfo; + + memset (&pininfo, 0, sizeof pininfo); + pininfo.mode = 1; + pininfo.minlen = 6; rc = pincb (pincb_arg, "PIN", &pinvalue); if (rc) @@ -2455,7 +2460,9 @@ app_select_openpgp (app_t app) size_t buflen; void *relptr; - rc = iso7816_select_application (slot, aid, sizeof aid); + /* Note that the card can't cope with P2=0xCO, thus we need to pass a + special flag value. */ + rc = iso7816_select_application (slot, aid, sizeof aid, 0x0001); if (!rc) { unsigned int manufacturer; diff --git a/scd/app-p15.c b/scd/app-p15.c index 739a9ef95..8bb94cfcd 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -3268,18 +3268,15 @@ app_select_p15 (app_t app) int direct = 0; int is_belpic = 0; - rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid); - if (rc) - { - rc = iso7816_select_application (slot, pkcs15be_aid,sizeof pkcs15be_aid); - if (!rc) - is_belpic = 1; - } + rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid, 0); if (rc) { /* Not found: Try to locate it from 2F00. We use direct path selection here because it seems that the Belgian eID card does only allow for that. Many other cards supports this - selection method too. */ + selection method too. Note, that we don't use + select_application above for the Belgian card - the call + works but it seems that it did not switch to the correct DF. + Using the 2f02 just works. */ unsigned short path[1] = { 0x2f00 }; rc = iso7816_select_path (app->slot, path, 1, NULL, NULL); diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index f82d93b00..fee733358 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1240,7 +1240,9 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, if (CCID_COMMAND_FAILED (buffer)) print_command_failed (buffer); - /* Check whether a card is at all available. */ + /* Check whether a card is at all available. Note: If you add new + error codes here, check whether they need to be ignored in + send_escape_cmd. */ switch ((buffer[7] & 0x03)) { case 0: /* no error */ break; @@ -1253,16 +1255,23 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, /* Note that this function won't return the error codes NO_CARD or - CARD_INACTIVE */ + CARD_INACTIVE. IF RESULT is not NULL, the result from the + operation will get returned in RESULT and its length in RESULTLEN. + If the response is larger than RESULTMAX, an error is returned and + the required buffer length returned in RESULTLEN. */ static int send_escape_cmd (ccid_driver_t handle, - const unsigned char *data, size_t datalen) + const unsigned char *data, size_t datalen, + unsigned char *result, size_t resultmax, size_t *resultlen) { int i, rc; unsigned char msg[100]; size_t msglen; unsigned char seqno; + if (resultlen) + *resultlen = 0; + if (datalen > sizeof msg - 10) return CCID_DRIVER_ERR_INV_VALUE; /* Escape data too large. */ @@ -1285,11 +1294,42 @@ send_escape_cmd (ccid_driver_t handle, return rc; rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Escape, seqno, 5000, 0); - + if (result) + switch (rc) + { + /* We need to ignore certain errorcode here. */ + case 0: + case CCID_DRIVER_ERR_CARD_INACTIVE: + case CCID_DRIVER_ERR_NO_CARD: + { + if (msglen > resultmax) + rc = CCID_DRIVER_ERR_INV_VALUE; /* Response too large. */ + else + { + memcpy (result, msg, msglen); + *resultlen = msglen; + } + rc = 0; + } + break; + default: + break; + } + return rc; } +int +ccid_transceive_escape (ccid_driver_t handle, + const unsigned char *data, size_t datalen, + unsigned char *resp, size_t maxresplen, size_t *nresp) +{ + return send_escape_cmd (handle, data, datalen, resp, maxresplen, nresp); +} + + + /* experimental */ int ccid_poll (ccid_driver_t handle) @@ -1445,7 +1485,8 @@ ccid_get_atr (ccid_driver_t handle, { tried_iso = 1; /* Try switching to ISO mode. */ - if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2)) + if (!send_escape_cmd (handle, (const unsigned char*)"\xF1\x01", 2, + NULL, 0, NULL)) goto again; } else if (CCID_COMMAND_FAILED (msg)) @@ -1957,14 +1998,16 @@ ccid_transceive (ccid_driver_t handle, } -/* Send the CCID Secure command to the reader. APDU_BUF should contain the APDU template. PIN_MODE defines now the pin gets formatted: +/* Send the CCID Secure command to the reader. APDU_BUF should + contain the APDU template. PIN_MODE defines how the pin gets + formatted: 1 := The PIN is ASCII encoded and of variable length. The length of the PIN entered will be put into Lc by the reader. The APDU should me made up of 4 bytes without Lc. PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0 - may be used t enable usbale defaults. PIN_PADLEN should be 0 + may be used t enable reasonable defaults. PIN_PADLEN should be 0. When called with RESP and NRESP set to NULL, the function will merely check whether the reader supports the secure command for the @@ -1996,7 +2039,7 @@ ccid_transceive_secure (ccid_driver_t handle, else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2)) return CCID_DRIVER_ERR_NOT_SUPPORTED; /* Not yet by our code. */ else - return CCID_DRIVER_ERR_NOT_SUPPORTED; + return CCID_DRIVER_ERR_NO_KEYPAD; if (pin_mode != 1) return CCID_DRIVER_ERR_NOT_SUPPORTED; @@ -2027,7 +2070,8 @@ ccid_transceive_secure (ccid_driver_t handle, if (handle->id_vendor == VENDOR_SCM) { DEBUGOUT ("sending escape sequence to switch to a case 1 APDU\n"); - rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3); + rc = send_escape_cmd (handle, (const unsigned char*)"\x80\x02\x00", 3, + NULL, 0, NULL); if (rc) return rc; } @@ -2044,7 +2088,7 @@ ccid_transceive_secure (ccid_driver_t handle, if (handle->id_vendor == VENDOR_SCM) { /* For the SPR532 the next 2 bytes need to be zero. We do this - for all SCM product. Kudos to to Martin Paljak for this + for all SCM product. Kudos to Martin Paljak for this hint. */ msg[13] = msg[14] = 0; } diff --git a/scd/ccid-driver.h b/scd/ccid-driver.h index 1b9ac2f85..6f6527108 100644 --- a/scd/ccid-driver.h +++ b/scd/ccid-driver.h @@ -58,7 +58,7 @@ #ifndef CCID_DRIVER_H #define CCID_DRIVER_H -/* The CID driver returns the same error codes as the statsu words +/* The CID driver returns the same error codes as the status words used by GnuPG's apdu.h. For ease of maintenance they should always match. */ #define CCID_DRIVER_ERR_OUT_OF_CORE 0x10001 @@ -74,6 +74,7 @@ #define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b #define CCID_DRIVER_ERR_NO_READER 0x1000c #define CCID_DRIVER_ERR_ABORTED 0x1000d +#define CCID_DRIVER_ERR_NO_KEYPAD 0x1000e struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; @@ -94,6 +95,10 @@ int ccid_transceive_secure (ccid_driver_t handle, int pin_mode, int pinlen_min, int pinlen_max, int pin_padlen, unsigned char *resp, size_t maxresplen, size_t *nresp); +int ccid_transceive_escape (ccid_driver_t handle, + const unsigned char *data, size_t datalen, + unsigned char *resp, size_t maxresplen, + size_t *nresp); diff --git a/scd/iso7816.c b/scd/iso7816.c index 5b985324f..5c62e1371 100644 --- a/scd/iso7816.c +++ b/scd/iso7816.c @@ -47,9 +47,9 @@ #define CMD_SELECT_FILE 0xA4 -#define CMD_VERIFY 0x20 -#define CMD_CHANGE_REFERENCE_DATA 0x24 -#define CMD_RESET_RETRY_COUNTER 0x2C +#define CMD_VERIFY ISO7816_VERIFY +#define CMD_CHANGE_REFERENCE_DATA ISO7816_CHANGE_REFERENCE_DATA +#define CMD_RESET_RETRY_COUNTER ISO7816_RESET_RETRY_COUNTER #define CMD_GET_DATA 0xCA #define CMD_PUT_DATA 0xDA #define CMD_MSE 0x22 @@ -95,6 +95,7 @@ map_sw (int sw) case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break; case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break; case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break; + case SW_HOST_NO_KEYPAD: ec = GPG_ERR_NOT_SUPPORTED; break; default: if ((sw & 0x010000)) @@ -124,12 +125,15 @@ iso7816_map_sw (int sw) requested application ID. The function can't be used to enumerate AIDs and won't return the AID on success. The return value is 0 for okay or a GPG error code. Note that ISO error codes are - internally mapped. */ + internally mapped. Bit 0 of FLAGS should be set if the card does + not understand P2=0xC0. */ gpg_error_t -iso7816_select_application (int slot, const char *aid, size_t aidlen) +iso7816_select_application (int slot, const char *aid, size_t aidlen, + unsigned int flags) { int sw; - sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, 0, aidlen, aid); + sw = apdu_send_simple (slot, 0x00, CMD_SELECT_FILE, 4, + (flags&1)? 0 :0x0c, aidlen, aid); return map_sw (sw); } @@ -221,27 +225,59 @@ iso7816_list_directory (int slot, int list_dirs, } +/* Check whether the reader supports the ISO command code COMMAND on + the keypad. Returns 0 on success. */ +gpg_error_t +iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo) +{ + int sw; + + sw = apdu_check_keypad (slot, command, + pininfo->mode, pininfo->minlen, pininfo->maxlen, + pininfo->padlen); + return map_sw (sw); +} + /* Perform a VERIFY command on SLOT using the card holder verification - vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */ + vector CHVNO with a CHV of lenght CHVLEN. With PININFO non-NULL + the keypad of the reader will be used. Returns 0 on success. */ gpg_error_t -iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen) +iso7816_verify_kp (int slot, int chvno, const char *chv, size_t chvlen, + iso7816_pininfo_t *pininfo) { int sw; - sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv); + if (pininfo && pininfo->mode) + sw = apdu_send_simple_kp (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv, + pininfo->mode, + pininfo->minlen, + pininfo->maxlen, + pininfo->padlen); + else + sw = apdu_send_simple (slot, 0x00, CMD_VERIFY, 0, chvno, chvlen, chv); return map_sw (sw); } +/* Perform a VERIFY command on SLOT using the card holder verification + vector CHVNO with a CHV of lenght CHVLEN. Returns 0 on success. */ +gpg_error_t +iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen) +{ + return iso7816_verify_kp (slot, chvno, chv, chvlen, NULL); +} + /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN 0), a "change reference data" is done, otherwise an "exchange reference data". The new reference data is expected in NEWCHV of - length NEWCHVLEN. */ + length NEWCHVLEN. With PININFO non-NULL the keypad of the reader + will be used. */ gpg_error_t -iso7816_change_reference_data (int slot, int chvno, - const char *oldchv, size_t oldchvlen, - const char *newchv, size_t newchvlen) +iso7816_change_reference_data_kp (int slot, int chvno, + const char *oldchv, size_t oldchvlen, + const char *newchv, size_t newchvlen, + iso7816_pininfo_t *pininfo) { int sw; char *buf; @@ -258,28 +294,69 @@ iso7816_change_reference_data (int slot, int chvno, memcpy (buf, oldchv, oldchvlen); memcpy (buf+oldchvlen, newchv, newchvlen); - sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, - oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf); + if (pininfo && pininfo->mode) + sw = apdu_send_simple_kp (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, + oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf, + pininfo->mode, + pininfo->minlen, + pininfo->maxlen, + pininfo->padlen); + else + sw = apdu_send_simple (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, + oldchvlen? 0 : 1, chvno, oldchvlen+newchvlen, buf); xfree (buf); return map_sw (sw); } +/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder + verification vector CHVNO. If the OLDCHV is NULL (and OLDCHVLEN + 0), a "change reference data" is done, otherwise an "exchange + reference data". The new reference data is expected in NEWCHV of + length NEWCHVLEN. */ +gpg_error_t +iso7816_change_reference_data (int slot, int chvno, + const char *oldchv, size_t oldchvlen, + const char *newchv, size_t newchvlen) +{ + return iso7816_change_reference_data_kp (slot, chvno, oldchv, oldchvlen, + newchv, newchvlen, NULL); +} + + gpg_error_t -iso7816_reset_retry_counter (int slot, int chvno, - const char *newchv, size_t newchvlen) +iso7816_reset_retry_counter_kp (int slot, int chvno, + const char *newchv, size_t newchvlen, + iso7816_pininfo_t *pininfo) { int sw; if (!newchv || !newchvlen ) return gpg_error (GPG_ERR_INV_VALUE); - sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER, - 2, chvno, newchvlen, newchv); + if (pininfo && pininfo->mode) + sw = apdu_send_simple_kp (slot, 0x00, CMD_RESET_RETRY_COUNTER, + 2, chvno, newchvlen, newchv, + pininfo->mode, + pininfo->minlen, + pininfo->maxlen, + pininfo->padlen); + else + sw = apdu_send_simple (slot, 0x00, CMD_RESET_RETRY_COUNTER, + 2, chvno, newchvlen, newchv); return map_sw (sw); } +gpg_error_t +iso7816_reset_retry_counter (int slot, int chvno, + const char *newchv, size_t newchvlen) +{ + return iso7816_reset_retry_counter_kp (slot, chvno, newchv, newchvlen, NULL); +} + + + /* Perform a GET DATA command requesting TAG and storing the result in a newly allocated buffer at the address passed by RESULT. Return the length of this data at the address of RESULTLEN. */ diff --git a/scd/iso7816.h b/scd/iso7816.h index 04c7ae63e..8f7907405 100644 --- a/scd/iso7816.h +++ b/scd/iso7816.h @@ -28,10 +28,30 @@ #include "cardglue.h" #endif +/* Command codes used by iso7816_check_keypad. */ +#define ISO7816_VERIFY 0x20 +#define ISO7816_CHANGE_REFERENCE_DATA 0x24 +#define ISO7816_RESET_RETRY_COUNTER 0x2C + + +/* Information to be passed to keypad equipped readers. See + ccid-driver.c for details. */ +struct iso7816_pininfo_s +{ + int mode; /* A mode of 0 means: Do not use the keypad. */ + int minlen; + int maxlen; + int padlen; + int padchar; +}; +typedef struct iso7816_pininfo_s iso7816_pininfo_t; + + gpg_error_t iso7816_map_sw (int sw); gpg_error_t iso7816_select_application (int slot, - const char *aid, size_t aidlen); + const char *aid, size_t aidlen, + unsigned int flags); gpg_error_t iso7816_select_file (int slot, int tag, int is_dir, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_select_path (int slot, @@ -39,13 +59,26 @@ gpg_error_t iso7816_select_path (int slot, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_list_directory (int slot, int list_dirs, unsigned char **result, size_t *resultlen); +gpg_error_t iso7816_check_keypad (int slot, int command, + iso7816_pininfo_t *pininfo); gpg_error_t iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen); +gpg_error_t iso7816_verify_kp (int slot, + int chvno, const char *chv, size_t chvlen, + iso7816_pininfo_t *pininfo); gpg_error_t iso7816_change_reference_data (int slot, int chvno, const char *oldchv, size_t oldchvlen, const char *newchv, size_t newchvlen); +gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno, + const char *oldchv, size_t oldchvlen, + const char *newchv, size_t newchvlen, + iso7816_pininfo_t *pininfo); gpg_error_t iso7816_reset_retry_counter (int slot, int chvno, const char *newchv, size_t newchvlen); +gpg_error_t iso7816_reset_retry_counter_kp (int slot, int chvno, + const char *newchv, + size_t newchvlen, + iso7816_pininfo_t *pininfo); gpg_error_t iso7816_get_data (int slot, int tag, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_put_data (int slot, int tag, diff --git a/scd/scdaemon.c b/scd/scdaemon.c index c6995abcc..56c0d7600 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -84,6 +84,7 @@ enum cmd_and_opt_values opcscDriver, oDisableCCID, oDisableOpenSC, + oDisableKeypad, oAllowAdmin, oDenyAdmin, oDisableApplication, @@ -126,6 +127,7 @@ static ARGPARSE_OPTS opts[] = { "@" #endif /* end --disable-ccid */}, + { oDisableKeypad, "disable-keypad", 0, N_("do not use a reader's keypad")}, { oAllowAdmin, "allow-admin", 0, N_("allow the use of admin card commands")}, { oDenyAdmin, "deny-admin", 0, "@" }, { oDisableApplication, "disable-application", 2, "@"}, @@ -135,7 +137,7 @@ static ARGPARSE_OPTS opts[] = { /* The card dirver we use by default for PC/SC. */ -#ifdef HAVE_W32_SYSTEM +#if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__) #define DEFAULT_PCSC_DRIVER "winscard.dll" #else #define DEFAULT_PCSC_DRIVER "libpcsclite.so" @@ -489,6 +491,8 @@ main (int argc, char **argv ) case oDisableCCID: opt.disable_ccid = 1; break; case oDisableOpenSC: break; + case oDisableKeypad: opt.disable_keypad = 1; break; + case oAllowAdmin: opt.allow_admin = 1; break; case oDenyAdmin: opt.allow_admin = 0; break; diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 54566b6ad..abe9730a7 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -39,21 +39,22 @@ #define MAX_DIGEST_LEN 24 -/* A large struct name "opt" to keep global flags */ +/* A large struct name "opt" to keep global flags. */ struct { - unsigned int debug; /* debug flags (DBG_foo_VALUE) */ - int verbose; /* verbosity level */ - int quiet; /* be as quiet as possible */ - int dry_run; /* don't change any persistent data */ - int batch; /* batch mode */ - const char *homedir; /* configuration directory name */ + unsigned int debug; /* Debug flags (DBG_foo_VALUE). */ + int verbose; /* Verbosity level. */ + int quiet; /* Be as quiet as possible. */ + int dry_run; /* Don't change any persistent data. */ + int batch; /* Batch mode. */ + const char *homedir; /* Configuration directory name. */ const char *ctapi_driver; /* Library to access the ctAPI. */ const char *pcsc_driver; /* Library to access the PC/SC system. */ const char *reader_port; /* NULL or reder port to use. */ int disable_ccid; /* Disable the use of the internal CCID driver. */ + int disable_keypad; /* Do not use a keypad. */ int allow_admin; /* Allow the use of admin commands for certain cards. */ - strlist_t disabled_applications; /* card applications we do not + strlist_t disabled_applications; /* Card applications we do not want to use. */ } opt; diff --git a/tools/ChangeLog b/tools/ChangeLog index ba4f0ec27..a57a0bccf 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,11 @@ +2005-10-19 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c (gc_options_scdaemon): New option --disable-keypad. + +2005-09-22 Werner Koch <wk@g10code.com> + + * rfc822parse.c (parse_field): Tread Content-Disposition special. + 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (watchgnupg_LDADD): New variable. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index e8d9ca27e..497707532 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -528,7 +528,9 @@ static gc_option_t gc_options_scdaemon[] = { "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT, "gnupg", "do not use the internal CCID driver", GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, - + { "disable-keypad", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED, + "gnupg", "do not use a reader's keypad", + GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, { "Debug", GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED, @@ -2447,7 +2449,8 @@ gc_component_change_options (int component, FILE *in) { #ifdef HAVE_W32_SYSTEM /* FIXME: Won't work becuase W32 doesn't silently - overwrite. */ + overwrite. Fix it by creating a backup copy and + deliting the orginal file first. */ err = rename (src_pathname[i], dest_pathname[i]); #else /*!HAVE_W32_SYSTEM*/ /* This is a bit safer than rename() because we diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index 61377e7e6..df3b2e7a4 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -766,6 +766,7 @@ parse_field (HDR_LINE hdr) } tspecial_header[] = { { "Content-Type", 12}, { "Content-Transfer-Encoding", 25}, + { "Content-Disposition", 19}, { NULL, 0} }; const char *delimiters; -- cgit v1.2.3 From 496c3b5572e7ab3a9355bd26c9050d4eaf42929e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 6 Dec 2005 16:44:20 +0000 Subject: Print warning for missing pcsc-wrapper --- scd/ChangeLog | 5 +++++ scd/apdu.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 008d84080..64c3bdc59 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,8 @@ +2005-12-06 Werner Koch <wk@g10code.com> + + * apdu.c (open_pcsc_reader): Check that pcsc-wrapper is actually + installed. + 2005-11-23 Werner Koch <wk@g10code.com> * app-nks.c (verify_pin): Give a special error message for a Nullpin. diff --git a/scd/apdu.c b/scd/apdu.c index f59d832d4..5a5f18b43 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1328,6 +1328,14 @@ open_pcsc_reader (const char *portstr) int err; unsigned int dummy_status; int sw = SW_HOST_CARD_IO_ERROR; + const char *wrapperpgm = GNUPG_LIBDIR "/pcsc-wrapper"; + + if (access (wrapperpgm, X_OK)) + { + log_error ("can't run PC/SC access module `%s': %s\n", + wrapperpgm, strerror (errno)); + return -1; + } slot = new_reader_slot (); if (slot == -1) @@ -1400,7 +1408,7 @@ open_pcsc_reader (const char *portstr) close(i); errno = 0; - execl (GNUPG_LIBDIR "/pcsc-wrapper", + execl (wrapperpgm, "pcsc-wrapper", "--", "1", /* API version */ -- cgit v1.2.3 From f80ad71f1cdd65a1216a57c32e7bc0657bc2c83f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 14 Dec 2005 09:55:40 +0000 Subject: Add support for direct pkcs#7 signatures --- tools/ChangeLog | 5 ++++ tools/gpgparsemail.c | 75 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index a57a0bccf..9b2afd42b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2005-12-14 Werner Koch <wk@g10code.com> + + * gpgparsemail.c (pkcs7_begin): New. + (parse_message, message_cb): Add support of direct pkcs signatures. + 2005-10-19 Werner Koch <wk@g10code.com> * gpgconf-comp.c (gc_options_scdaemon): New option --disable-keypad. diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c index fa848c8f6..dcc38c3b8 100644 --- a/tools/gpgparsemail.c +++ b/tools/gpgparsemail.c @@ -60,13 +60,17 @@ struct parse_info_s { int show_boundary; int nesting_level; + int is_pkcs7; /* Old style S/MIME message. */ + int gpgsm_mime; /* gpgsm shall be used from S/MIME. */ char *signing_protocol; int hashing_level; /* The nesting level we are hashing. */ int hashing; FILE *hash_file; - FILE *sig_file; - int verify_now; /* Falg set when all signature data is + + FILE *sig_file; /* Signature part with MIME or full + pkcs7 data if IS_PCKS7 is set. */ + int verify_now; /* Flag set when all signature data is available. */ }; @@ -183,7 +187,10 @@ run_gnupg (int smime, int sig_fd, int data_fd, int *close_list) } /* Keep our data fd and format it for gpg/gpgsm use. */ - sprintf (data_fd_buf, "-&%d", data_fd); + if (data_fd == -1) + *data_fd_buf = 0; + else + sprintf (data_fd_buf, "-&%d", data_fd); /* Send stdout to the bit bucket. */ fd = open ("/dev/null", O_WRONLY); @@ -214,7 +221,7 @@ run_gnupg (int smime, int sig_fd, int data_fd, int *close_list) "--assume-base64", "--verify", "--", - "-", data_fd_buf, + "-", data_fd == -1? NULL : data_fd_buf, NULL); die ("failed to exec the crypto command: %s", strerror (errno)); @@ -287,10 +294,19 @@ verify_signature (struct parse_info_s *info) { int close_list[10]; - assert (info->hash_file); - assert (info->sig_file); - rewind (info->hash_file); - rewind (info->sig_file); + if (info->is_pkcs7) + { + assert (!info->hash_file); + assert (info->sig_file); + rewind (info->sig_file); + } + else + { + assert (info->hash_file); + assert (info->sig_file); + rewind (info->hash_file); + rewind (info->sig_file); + } /* printf ("# Begin hashed data\n"); */ /* while ( (c=getc (info->hash_file)) != EOF) */ @@ -304,7 +320,8 @@ verify_signature (struct parse_info_s *info) /* rewind (info->sig_file); */ close_list[0] = -1; - run_gnupg (1, fileno (info->sig_file), fileno (info->hash_file), close_list); + run_gnupg (1, fileno (info->sig_file), + info->hash_file ? fileno (info->hash_file) : -1, close_list); } @@ -353,6 +370,30 @@ mime_encrypted_begin (struct parse_info_s *info, rfc822parse_t msg, } +/* Prepare for old-style pkcs7 messages. */ +static void +pkcs7_begin (struct parse_info_s *info, rfc822parse_t msg, + rfc822parse_field_t field_ctx) +{ + const char *s; + s = rfc822parse_query_parameter (field_ctx, "name", 0); + if (s) + printf ("h pkcs7.name: %s\n", s); + if (info->is_pkcs7) + err ("note: ignoring nested pkcs7 data"); + else + { + info->is_pkcs7 = 1; + if (opt_crypto) + { + assert (!info->sig_file); + info->sig_file = tmpfile (); + if (!info->sig_file) + die ("error creating temp file: %s", strerror (errno)); + } + } +} + /* Print the event received by the parser for debugging as comment line. */ @@ -439,6 +480,10 @@ message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg) else if (!strcmp (s2, "encrypted")) mime_encrypted_begin (info, msg, ctx); } + else if (!strcmp (s1, "application") + && (!strcmp (s2, "pkcs7-mime") + || !strcmp (s2, "x-pkcs7-mime"))) + pkcs7_begin (info, msg, ctx); } else printf ("h media: %*s none\n", info->nesting_level*2, ""); @@ -581,11 +626,13 @@ parse_message (FILE *fp) if (info.verify_now) { verify_signature (&info); - fclose (info.hash_file); + if (info.hash_file) + fclose (info.hash_file); info.hash_file = NULL; fclose (info.sig_file); info.sig_file = NULL; info.gpgsm_mime = 0; + info.is_pkcs7 = 0; } else { @@ -621,6 +668,14 @@ parse_message (FILE *fp) } + if (info.sig_file && opt_crypto && info.is_pkcs7) + { + verify_signature (&info); + fclose (info.sig_file); + info.sig_file = NULL; + info.is_pkcs7 = 0; + } + rfc822parse_close (msg); } -- cgit v1.2.3 From 38e7c4c50ad8a1026886f975c5a8be2ac8438e35 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Dec 2005 15:52:48 +0000 Subject: Fixed importing certs created by newer versions of Mozilla. --- NEWS | 5 + TODO | 4 + agent/ChangeLog | 10 ++ agent/minip12.c | 285 ++++++++++++++++++++++++++++++++++++++++++--------- doc/tools.texi | 12 +++ tools/ChangeLog | 2 + tools/Makefile.am | 6 +- tools/gpgparsemail.c | 6 +- tools/rfc822parse.c | 11 +- 9 files changed, 285 insertions(+), 56 deletions(-) diff --git a/NEWS b/NEWS index edf29885d..350920580 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,11 @@ Noteworthy changes in version 1.9.20 * [scdaemon] Support for keypads of some readers. Tested only with SPR532. New option --disable-keypad. + * New debug tool gpgparsemail. + + * Importing pkcs#12 files created be recent versions of Mozilla works + again. + Noteworthy changes in version 1.9.19 (2005-09-12) ------------------------------------------------- diff --git a/TODO b/TODO index 50f58cee9..7a1f989b4 100644 --- a/TODO +++ b/TODO @@ -94,3 +94,7 @@ might want to have an agent context for each service request * sm/ ** --include-certs is as of now still a dummy command line option +** check that we issue NO_SECKEY xxx if a -u key was not found + +* gpg/ +** issue a NO_SECKEY xxxx if a -u key was not found. diff --git a/agent/ChangeLog b/agent/ChangeLog index 105178730..0aef39487 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,13 @@ +2005-12-16 Werner Koch <wk@g10code.com> + + * minip12.c (cram_octet_string): New + (p12_parse): Use it for NDEFed bags. + (parse_bag_data): Ditto. + (string_to_key, set_key_iv, crypt_block): New arg SALTLEN. + (p12_build): Use old value 8 for new arg. + (parse_bag_encrypted_data, parse_bag_data): Allow for salts of 8 + to 16 bytes. Add new arg R_CONSUMED. + 2005-11-24 Werner Koch <wk@g10code.com> * minip12.c (p12_parse): Fixed for case that the key object comes diff --git a/agent/minip12.c b/agent/minip12.c index 55f3946bf..e65bf0617 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -141,7 +141,8 @@ struct tag_info /* Parse the buffer at the address BUFFER which is of SIZE and return the tag and the length part from the TLV triplet. Update BUFFER - and SIZE on success. */ + and SIZE on success. Checks that the encoded length does not + exhaust the length of the provided buffer. */ static int parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti) { @@ -221,8 +222,76 @@ parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti) } +/* Given an ASN.1 chunk of a structure like: + + 24 NDEF: OCTET STRING -- This is not passed to us + 04 1: OCTET STRING -- INPUT point s to here + : 30 + 04 1: OCTET STRING + : 80 + [...] + 04 2: OCTET STRING + : 00 00 + : } -- This denotes a Null tag and are the last + -- two bytes in INPUT. + + Create a new buffer with the content of that octet string. INPUT + is the orginal buffer with a length as stored at LENGTH. Returns + NULL on error or a new malloced buffer with the length of this new + buffer stored at LENGTH and the number of bytes parsed from input + are added to the value stored at INPUT_CONSUMED. INPUT_CONSUMED is + allowed to be passed as NULL if the caller is not interested in + this value. */ +static unsigned char * +cram_octet_string (const unsigned char *input, size_t *length, + size_t *input_consumed) +{ + const unsigned char *s = input; + size_t n = *length; + unsigned char *output, *d; + struct tag_info ti; + + /* Allocate output buf. We know that it won't be longer than the + input buffer. */ + d = output = gcry_malloc (n); + if (!output) + goto bailout; + + for (;;) + { + if (parse_tag (&s, &n, &ti)) + goto bailout; + if (ti.class == UNIVERSAL && ti.tag == TAG_OCTET_STRING + && !ti.ndef && !ti.is_constructed) + { + memcpy (d, s, ti.length); + s += ti.length; + d += ti.length; + n -= ti.length; + } + else if (ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed) + break; /* Ready */ + else + goto bailout; + } + + + *length = d - output; + if (input_consumed) + *input_consumed += s - input; + return output; + + bailout: + if (input_consumed) + *input_consumed += s - input; + gcry_free (output); + return NULL; +} + + + static int -string_to_key (int id, char *salt, int iter, const char *pw, +string_to_key (int id, char *salt, size_t saltlen, int iter, const char *pw, int req_keylen, unsigned char *keybuf) { int rc, i, j; @@ -241,10 +310,16 @@ string_to_key (int id, char *salt, int iter, const char *pw, return -1; } + if (saltlen < 8) + { + log_error ("salt too short\n"); + return -1; + } + /* Store salt and password in BUF_I */ p = buf_i; for(i=0; i < 64; i++) - *p++ = salt [i%8]; + *p++ = salt [i%saltlen]; for(i=j=0; i < 64; i += 2) { *p++ = 0; @@ -314,14 +389,14 @@ string_to_key (int id, char *salt, int iter, const char *pw, static int -set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw, - int keybytes) +set_key_iv (gcry_cipher_hd_t chd, char *salt, size_t saltlen, int iter, + const char *pw, int keybytes) { unsigned char keybuf[24]; int rc; assert (keybytes == 5 || keybytes == 24); - if (string_to_key (1, salt, iter, pw, keybytes, keybuf)) + if (string_to_key (1, salt, saltlen, iter, pw, keybytes, keybuf)) return -1; rc = gcry_cipher_setkey (chd, keybuf, keybytes); if (rc) @@ -330,7 +405,7 @@ set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw, return -1; } - if (string_to_key (2, salt, iter, pw, 8, keybuf)) + if (string_to_key (2, salt, saltlen, iter, pw, 8, keybuf)) return -1; rc = gcry_cipher_setiv (chd, keybuf, 8); if (rc) @@ -343,8 +418,8 @@ set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw, static void -crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, - const char *pw, int cipher_algo, int encrypt) +crypt_block (unsigned char *buffer, size_t length, char *salt, size_t saltlen, + int iter, const char *pw, int cipher_algo, int encrypt) { gcry_cipher_hd_t chd; int rc; @@ -356,7 +431,7 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, wipememory (buffer, length); return; } - if (set_key_iv (chd, salt, iter, pw, + if (set_key_iv (chd, salt, saltlen, iter, pw, cipher_algo == GCRY_CIPHER_RFC2268_40? 5:24)) { wipememory (buffer, length); @@ -381,18 +456,22 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, int iter, static int parse_bag_encrypted_data (const unsigned char *buffer, size_t length, - int startoffset, const char *pw, + int startoffset, size_t *r_consumed, const char *pw, void (*certcb)(void*, const unsigned char*, size_t), void *certcbarg) { struct tag_info ti; const unsigned char *p = buffer; + const unsigned char *p_start = buffer; size_t n = length; const char *where; - char salt[8]; + char salt[16]; + size_t saltlen; unsigned int iter; unsigned char *plain = NULL; int bad_pass = 0; + unsigned char *cram_buffer = NULL; + size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */ where = "start"; if (parse_tag (&p, &n, &ti)) @@ -449,11 +528,13 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, goto bailout; if (parse_tag (&p, &n, &ti)) goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 ) + if (ti.class || ti.tag != TAG_OCTET_STRING + || ti.length < 8 || ti.length > 16 ) goto bailout; - memcpy (salt, p, 8); - p += 8; - n -= 8; + saltlen = ti.length; + memcpy (salt, p, saltlen); + p += saltlen; + n -= saltlen; if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class || ti.tag != TAG_INTEGER || !ti.length ) @@ -468,7 +549,25 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, where = "rc2-ciphertext"; if (parse_tag (&p, &n, &ti)) goto bailout; - if (ti.class != CONTEXT || ti.tag != 0 || !ti.length ) + + consumed = p - p_start; + if (ti.class == CONTEXT && ti.tag == 0 && ti.is_constructed && ti.ndef) + { + /* Mozilla exported certs now come with single byte chunks of + octect strings. (Mozilla Firefox 1.0.4). Arghh. */ + where = "cram-rc2-ciphertext"; + cram_buffer = cram_octet_string ( p, &n, &consumed); + if (!cram_buffer) + goto bailout; + p = p_start = cram_buffer; + if (r_consumed) + *r_consumed = consumed; + r_consumed = NULL; /* Ugly hack to not update that value any further. */ + ti.length = n; + } + else if (ti.class == CONTEXT && ti.tag == 0 && ti.length ) + ; + else goto bailout; log_info ("%lu bytes of RC2 encrypted text\n", ti.length); @@ -480,10 +579,11 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, goto bailout; } memcpy (plain, p, ti.length); - crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_RFC2268_40, 0); + crypt_block (plain, ti.length, salt, saltlen, + iter, pw, GCRY_CIPHER_RFC2268_40, 0); n = ti.length; startoffset = 0; - buffer = p = plain; + p_start = p = plain; /* { */ /* # warning debug code is enabled */ @@ -615,13 +715,19 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, } } + if (r_consumed) + *r_consumed = consumed; gcry_free (plain); - + gcry_free (cram_buffer); return 0; + bailout: + if (r_consumed) + *r_consumed = consumed; gcry_free (plain); + gcry_free (cram_buffer); log_error ("encryptedData error at \"%s\", offset %u\n", - where, (p - buffer)+startoffset); + where, (p - p_start)+startoffset); if (bad_pass) { /* Note, that the following string might be used by other programs @@ -634,19 +740,23 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, static gcry_mpi_t * parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, - const char *pw) + size_t *r_consumed, const char *pw) { int rc; struct tag_info ti; const unsigned char *p = buffer; + const unsigned char *p_start = buffer; size_t n = length; const char *where; - char salt[8]; + char salt[16]; + size_t saltlen; unsigned int iter; int len; unsigned char *plain = NULL; gcry_mpi_t *result = NULL; int result_count, i; + unsigned char *cram_buffer = NULL; + size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */ where = "start"; if (parse_tag (&p, &n, &ti)) @@ -658,6 +768,22 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, if (ti.class || ti.tag != TAG_OCTET_STRING) goto bailout; + consumed = p - p_start; + if (ti.is_constructed && ti.ndef) + { + /* Mozilla exported certs now come with single byte chunks of + octect strings. (Mozilla Firefox 1.0.4). Arghh. */ + where = "cram-data.outersegs"; + cram_buffer = cram_octet_string ( p, &n, &consumed); + if (!cram_buffer) + goto bailout; + p = p_start = cram_buffer; + if (r_consumed) + *r_consumed = consumed; + r_consumed = NULL; /* Ugly hack to not update that value any further. */ + } + + where = "data.outerseqs"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -709,11 +835,13 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, goto bailout; if (parse_tag (&p, &n, &ti)) goto bailout; - if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 ) + if (ti.class || ti.tag != TAG_OCTET_STRING + || ti.length < 8 || ti.length > 16) goto bailout; - memcpy (salt, p, 8); - p += 8; - n -= 8; + saltlen = ti.length; + memcpy (salt, p, saltlen); + p += saltlen; + n -= saltlen; if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class || ti.tag != TAG_INTEGER || !ti.length ) @@ -740,10 +868,11 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, goto bailout; } memcpy (plain, p, ti.length); - crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_3DES, 0); + consumed += p - p_start + ti.length; + crypt_block (plain, ti.length, salt, saltlen, iter, pw, GCRY_CIPHER_3DES, 0); n = ti.length; startoffset = 0; - buffer = p = plain; + p_start = p = plain; /* { */ /* # warning debug code is enabled */ @@ -828,6 +957,9 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, if (len) goto bailout; + gcry_free (cram_buffer); + if (r_consumed) + *r_consumed = consumed; return result; bailout: @@ -838,8 +970,11 @@ parse_bag_data (const unsigned char *buffer, size_t length, int startoffset, gcry_mpi_release (result[i]); gcry_free (result); } + gcry_free (cram_buffer); log_error ( "data error at \"%s\", offset %u\n", where, (p - buffer) + startoffset); + if (r_consumed) + *r_consumed = consumed; return NULL; } @@ -857,10 +992,13 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, { struct tag_info ti; const unsigned char *p = buffer; + const unsigned char *p_start = buffer; size_t n = length; const char *where; int bagseqlength, len; + int bagseqndef, lenndef; gcry_mpi_t *result = NULL; + unsigned char *cram_buffer = NULL; where = "pfx"; if (parse_tag (&p, &n, &ti)) @@ -897,71 +1035,121 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING) goto bailout; + if (ti.is_constructed && ti.ndef) + { + /* Mozilla exported certs now come with single byte chunks of + octect strings. (Mozilla Firefox 1.0.4). Arghh. */ + where = "cram-bags"; + cram_buffer = cram_octet_string ( p, &n, NULL); + if (!cram_buffer) + goto bailout; + p = p_start = cram_buffer; + } + where = "bags"; if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE) goto bailout; + bagseqndef = ti.ndef; bagseqlength = ti.length; - while (bagseqlength) + while (bagseqlength || bagseqndef) { - /*log_debug ( "at offset %u\n", (p - buffer));*/ + log_debug ( "at offset %u\n", (p - p_start)); where = "bag-sequence"; if (parse_tag (&p, &n, &ti)) goto bailout; + if (bagseqndef && ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed) + break; /* Ready */ if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE) goto bailout; - if (bagseqlength < ti.nhdr) - goto bailout; - bagseqlength -= ti.nhdr; - if (bagseqlength < ti.length) - goto bailout; - bagseqlength -= ti.length; + if (!bagseqndef) + { + if (bagseqlength < ti.nhdr) + goto bailout; + bagseqlength -= ti.nhdr; + if (bagseqlength < ti.length) + goto bailout; + bagseqlength -= ti.length; + } + lenndef = ti.ndef; len = ti.length; if (parse_tag (&p, &n, &ti)) goto bailout; - len -= ti.nhdr; + if (lenndef) + len = ti.nhdr; + else + len -= ti.nhdr; + if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData) && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData))) { + size_t consumed = 0; + p += DIM(oid_encryptedData); n -= DIM(oid_encryptedData); - len -= DIM(oid_encryptedData); + if (!lenndef) + len -= DIM(oid_encryptedData); where = "bag.encryptedData"; - if (parse_bag_encrypted_data (p, n, (p - buffer), pw, + if (parse_bag_encrypted_data (p, n, (p - p_start), &consumed, pw, certcb, certcbarg)) goto bailout; + if (lenndef) + len += consumed; } else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data) - && !memcmp (p, oid_data, DIM(oid_data))) + && !memcmp (p, oid_data, DIM(oid_data))) { if (result) - log_info ("already got an data object, skipping next one\n"); + { + log_info ("already got an data object, skipping next one\n"); + p += ti.length; + n -= ti.length; + } else { + size_t consumed = 0; + p += DIM(oid_data); n -= DIM(oid_data); - len -= DIM(oid_data); - result = parse_bag_data (p, n, (p-buffer), pw); + if (!lenndef) + len -= DIM(oid_data); + result = parse_bag_data (p, n, (p - p_start), &consumed, pw); if (!result) goto bailout; + if (lenndef) + len += consumed; } } else - log_info ( "unknown bag type - skipped\n"); + { + log_info ("unknown bag type - skipped\n"); + p += ti.length; + n -= ti.length; + } if (len < 0 || len > n) goto bailout; p += len; n -= len; + if (lenndef) + { + /* Need to skip the Null Tag. */ + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (!(ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed)) + goto bailout; + } } + gcry_free (cram_buffer); return result; bailout: - log_error ("error at \"%s\", offset %u\n", where, (p - buffer)); + log_error ("error at \"%s\", offset %u\n", where, (p - p_start)); /* fixme: need to release RESULT. */ + gcry_free (cram_buffer); return NULL; } @@ -1586,7 +1774,8 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, /* Encrypt it. */ gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); - crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_RFC2268_40, 1); + crypt_block (buffer, buflen, salt, 8, 2048, pw, + GCRY_CIPHER_RFC2268_40, 1); /* Encode the encrypted stuff into a bag. */ seqlist[seqlistidx].buffer = build_cert_bag (buffer, buflen, salt, &n); @@ -1607,7 +1796,7 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, /* Encrypt it. */ gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); - crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_3DES, 1); + crypt_block (buffer, buflen, salt, 8, 2048, pw, GCRY_CIPHER_3DES, 1); /* Encode the encrypted stuff into a bag. */ seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, &n); diff --git a/doc/tools.texi b/doc/tools.texi index 850202bd5..d39d950f4 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -14,6 +14,7 @@ GnuPG comes with a couple of smaller tools: * gpgsm-gencert.sh:: Generate an X.509 certificate request. * gpg-preset-passphrase:: Put a passphrase into the cache. * gpg-connect-agent:: Communicate with a running agent. +* gpgparsemail:: Parse a mail message into an annotated format * symcryptrun:: Call a simple symmetric encryption tool. @end menu @@ -773,6 +774,17 @@ be used to directly connect to any Assuan style socket server. @end table +@c +@c GPGPARSEMAIL +@c +@node gpgparsemail +@section Parse a mail message into an annotated format + +The @command{gpgparsemail} is a utility currentlu only useful for +debugging. Run it with @code{--help} for usage information. + + + @c @c SYMCRYPTRUN @c diff --git a/tools/ChangeLog b/tools/ChangeLog index 9b2afd42b..b0b7499eb 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,5 +1,7 @@ 2005-12-14 Werner Koch <wk@g10code.com> + * Makefile.am (bin_PROGRAMS): Build gpgparsemail. + * gpgparsemail.c (pkcs7_begin): New. (parse_message, message_cb): Add support of direct pkcs signatures. diff --git a/tools/Makefile.am b/tools/Makefile.am index 508e52bc5..519e87150 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -18,7 +18,6 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA EXTRA_DIST = Manifest watchgnupg.c \ - rfc822parse.c rfc822parse.h gpgparsemail.c \ addgnupghome gpgsm-gencert.sh AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common @@ -36,7 +35,7 @@ else symcryptrun = endif -bin_PROGRAMS = gpgconf gpg-connect-agent gpgkey2ssh ${symcryptrun} +bin_PROGRAMS = gpgconf gpg-connect-agent gpgkey2ssh ${symcryptrun} gpgparsemail if !HAVE_W32_SYSTEM bin_PROGRAMS += watchgnupg endif @@ -46,6 +45,9 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c gpgconf_LDADD = ../jnlib/libjnlib.a \ ../common/libcommon.a ../gl/libgnu.a @LIBINTL@ +gpgparsemail_SOURCES = gpgparsemail.c rfc822parse.c rfc822parse.h +gpgparsemail_LDADD = + symcryptrun_SOURCES = symcryptrun.c symcryptrun_LDADD = $(LIBUTIL_LIBS) ../jnlib/libjnlib.a \ ../common/libcommon.a ../gl/libgnu.a \ diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c index dcc38c3b8..da56093c3 100644 --- a/tools/gpgparsemail.c +++ b/tools/gpgparsemail.c @@ -21,8 +21,8 @@ /* This utility prints an RFC8222, possible MIME structured, message in an annotated format with the first column having an indicator - for the content of the line.. Several options are available to - scrutinize the message. S/MIME and OpenPGP suuport is included. */ + for the content of the line. Several options are available to + scrutinize the message. S/MIME and OpenPGP support is included. */ #include <stdio.h> @@ -708,6 +708,8 @@ main (int argc, char **argv) " --debug enable additional debug output\n" " --help display this help and exit\n\n" "With no FILE, or when FILE is -, read standard input.\n\n" + "WARNING: This tool is under development.\n" + " The semantics may change without notice\n\n" "Report bugs to <bug-gnupg@gnu.org>."); exit (0); } diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index df3b2e7a4..303ddad13 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -155,7 +155,7 @@ capitalize_header_name (unsigned char *name) *name = *name - 'A' + 'a'; } - +#ifndef HAVE_STPCPY static char * stpcpy (char *a,const char *b) { @@ -165,6 +165,7 @@ stpcpy (char *a,const char *b) return (char*)a; } +#endif /* If a callback has been registerd, call it for the event of type @@ -474,7 +475,7 @@ insert_body (rfc822parse_t msg, const unsigned char *line, size_t length) msg->boundary = NULL; /* No current boundary anymore. */ set_current_part_to_parent (msg); - /* Fixme: The next should acctually be sent right before the + /* Fixme: The next should actually be send right before the next boundary, so that we can mark the epilogue. */ if (!rc) rc = do_callback (msg, RFC822PARSE_LEVEL_UP); @@ -523,7 +524,8 @@ rfc822parse_finish (rfc822parse_t msg) * available. * * If VALUEOFF is not NULL it will receive the offset of the first non - * space character in th value of the line. + * space character in the value part of the line (i.e. after the first + * colon). */ char * rfc822parse_get_field (rfc822parse_t msg, const char *name, int which, @@ -758,7 +760,8 @@ parse_field (HDR_LINE hdr) static const char specials[] = "<>@.,;:\\[]\"()"; static const char specials2[] = "<>@.,;:"; static const char tspecials[] = "/?=<>@,;:\\[]\"()"; - static const char tspecials2[] = "/?=<>@.,;:"; + static const char tspecials2[] = "/?=<>@.,;:"; /* FIXME: really + include '.'?*/ static struct { const unsigned char *name; -- cgit v1.2.3 From a56dc7e7afcd20bde51d9227e1667397fbd31c52 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Dec 2005 10:26:32 +0000 Subject: Preparing a released --- ChangeLog | 4 ++++ NEWS | 11 +++++------ configure.ac | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 46d66ed47..ea1ddf0e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-12-20 Werner Koch <wk@g10code.com> + + Released 1.9.20. + 2005-11-28 Werner Koch <wk@g10code.com> * configure.ac: Append the revision to the version string. diff --git a/NEWS b/NEWS index 350920580..da3ff6515 100644 --- a/NEWS +++ b/NEWS @@ -1,14 +1,13 @@ -Noteworthy changes in version 1.9.20 +Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- - * [scdaemon] Support for keypads of some readers. Tested only with - SPR532. New option --disable-keypad. - - * New debug tool gpgparsemail. - * Importing pkcs#12 files created be recent versions of Mozilla works again. + * Basic support for qualified signatures. + + * New debug tool gpgparsemail. + Noteworthy changes in version 1.9.19 (2005-09-12) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 6ba66968d..944e24cb9 100644 --- a/configure.ac +++ b/configure.ac @@ -25,7 +25,7 @@ min_automake_version="1.9.3" # Remember to change the version number immediately *after* a release. # Uncomment the my_iscvs macro for non-released code. m4_define(my_version, [1.9.20]) -m4_define(my_iscvs, yes) +#m4_define(my_iscvs, yes) AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit( [$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org]) # Set development_version to yes if the minor number is odd or you -- cgit v1.2.3 From dfaee3d48069491fe30af26a6219cf17b7474d9f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Dec 2005 11:12:16 +0000 Subject: post release preparations --- NEWS | 7 +++++++ configure.ac | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index da3ff6515..963b4f2f2 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +Noteworthy changes in version 1.9.21 +------------------------------------------------- + + * [scdaemon] Support for keypads of some readers. Tested only with + SPR532. New option --disable-keypad. + + Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 944e24cb9..9b0f04cb4 100644 --- a/configure.ac +++ b/configure.ac @@ -24,8 +24,8 @@ min_automake_version="1.9.3" # Remember to change the version number immediately *after* a release. # Uncomment the my_iscvs macro for non-released code. -m4_define(my_version, [1.9.20]) -#m4_define(my_iscvs, yes) +m4_define(my_version, [1.9.21]) +m4_define(my_iscvs, yes) AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit( [$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org]) # Set development_version to yes if the minor number is odd or you -- cgit v1.2.3 From a5465705fb59789783b5fcb14550eb30e6d863a3 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 6 Feb 2006 16:13:20 +0000 Subject: Support for CardMan 4040 --- scd/ChangeLog | 15 ++ scd/app-openpgp.c | 10 +- scd/ccid-driver.c | 717 +++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 510 insertions(+), 232 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 64c3bdc59..359b3f05a 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,18 @@ +2006-02-02 Werner Koch <wk@g10code.com> + + * ccid-driver.c (special_transport): New + (ccid_open_reader, do_close_reader, ccid_shutdown_reader) + (bulk_out, bulk_in): Add support for CardMan 4040 reader. + + * ccid-driver.c (scan_or_find_devices): Factored most code out to + (scan_or_find_usb_device): .. new. + (make_reader_id): Fixed vendor mask. + +2006-01-01 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_sign): Give user error if hash algorithm is + not supported by the card. + 2005-12-06 Werner Koch <wk@g10code.com> * apdu.c (open_pcsc_reader): Check that pcsc-wrapper is actually diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 3d04be0be..fff709a08 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -484,7 +484,7 @@ count_bits (const unsigned char *a, size_t len) Everything up to a LF is considered a mailbox or account name. If the first LF is followed by DC4 (0x14) control sequence are expected up to the next LF. Control sequences are separated by FS - (0x28) and consist of key=value pairs. There is one key defined: + (0x18) and consist of key=value pairs. There is one key defined: F=<flags> @@ -2084,7 +2084,7 @@ check_against_given_fingerprint (app_t app, const char *fpr, int keyno) raw message digest. For this application the KEYIDSTR consists of the serialnumber and the fingerprint delimited by a slash. - Note that this fucntion may return the error code + Note that this function may return the error code GPG_ERR_WRONG_CARD to indicate that the card currently present does not match the one required for the requested action (e.g. the serial number does not match). */ @@ -2120,7 +2120,11 @@ do_sign (app_t app, const char *keyidstr, int hashalgo, && !memcmp (indata, rmd160_prefix, 15)) ; else - return gpg_error (GPG_ERR_INV_VALUE); + { + log_error (_("card does not support digest algorithm %s\n"), + gcry_md_algo_name (hashalgo)); + return gpg_error (GPG_ERR_INV_VALUE); + } /* Check whether an OpenPGP card of any version has been requested. */ if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12)) diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index fee733358..e884c6624 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -67,8 +67,8 @@ portable access to USB. This driver has been tested with the SCM SCR335 and SPR532 - smartcard readers and requires that a reader implements the TPDU - level exchange and does fully automatic initialization. + smartcard readers and requires that a reader implements APDU or + TPDU level exchange and does fully automatic initialization. */ #ifdef HAVE_CONFIG_H @@ -82,6 +82,9 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include <usb.h> @@ -194,11 +197,29 @@ enum { /* We need to know the vendor to do some hacks. */ enum { - VENDOR_SCM = 0x04e6, VENDOR_CHERRY = 0x046a, + VENDOR_SCM = 0x04e6, + VENDOR_OMNIKEY= 0x076b, VENDOR_GEMPC = 0x08e6 }; +/* A list and a table with special transport descriptions. */ +enum { + TRANSPORT_USB = 0, /* Standard USB transport. */ + TRANSPORT_CM4040 = 1 /* As used by the Cardman 4040. */ +}; + +static struct +{ + char *name; /* Device name. */ + int type; + +} transports[] = { + { "/dev/cmx0", TRANSPORT_CM4040 }, + { "/dev/cmx1", TRANSPORT_CM4040 }, + { NULL }, +}; + /* Store information on the driver's state. A pointer to such a structure is used as handle for most functions. */ @@ -206,6 +227,8 @@ struct ccid_driver_s { usb_dev_handle *idev; char *rid; + int dev_fd; /* -1 for USB transport or file descriptor of the + transport device. */ unsigned short id_vendor; unsigned short id_product; unsigned short bcd_device; @@ -306,7 +329,34 @@ print_command_failed (const unsigned char *msg) } +/* Given a handle used for special transport prepare it for use. In + particular setup all information in way that resembles what + parse_cccid_descriptor does. */ +static void +prepare_special_transport (ccid_driver_t handle) +{ + assert (!handle->id_vendor); + + handle->nonnull_nad = 0; + handle->auto_ifsd = 0; + handle->max_ifsd = 32; + handle->ifsd = 0; + handle->has_pinpad = 0; + handle->apdu_level = 0; + switch (handle->id_product) + { + case TRANSPORT_CM4040: + DEBUGOUT ("setting up transport for CardMan 4040\n"); + /* Most values are guessed. */ + handle->nonnull_nad = 1; + handle->auto_ifsd = 1; + handle->max_ifsd = 254; + handle->apdu_level = 1; + break; + default: assert (!"transport not defined"); + } +} /* Parse a CCID descriptor, optionally print all available features and test whether this reader is usable by this driver. Returns 0 @@ -615,7 +665,7 @@ make_reader_id (usb_dev_handle *idev, char *rid; char prefix[20]; - sprintf (prefix, "%04X:%04X:", (vendor & 0xfff), (product & 0xffff)); + sprintf (prefix, "%04X:%04X:", (vendor & 0xffff), (product & 0xffff)); rid = get_escaped_usb_string (idev, serialno_index, prefix, ":0"); if (!rid) { @@ -658,10 +708,177 @@ find_endpoint (struct usb_interface_descriptor *ifcdesc, int mode) } +/* Helper for scan_or_find_devices. This function returns true if a + requested device has been found or the caller should stop scanning + for other reasons. */ +static int +scan_or_find_usb_device (int scan_mode, + int *readerno, int *count, char **rid_list, + const char *readerid, + struct usb_device *dev, + char **r_rid, + struct usb_device **r_dev, + usb_dev_handle **r_idev, + unsigned char **ifcdesc_extra, + size_t *ifcdesc_extra_len, + int *interface_number, + int *ep_bulk_out, int *ep_bulk_in, int *ep_intr) +{ + int cfg_no; + int ifc_no; + int set_no; + struct usb_config_descriptor *config; + struct usb_interface *interface; + struct usb_interface_descriptor *ifcdesc; + char *rid; + usb_dev_handle *idev; + + *r_idev = NULL; + + for (cfg_no=0; cfg_no < dev->descriptor.bNumConfigurations; cfg_no++) + { + config = dev->config + cfg_no; + if(!config) + continue; + + for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++) + { + interface = config->interface + ifc_no; + if (!interface) + continue; + + for (set_no=0; set_no < interface->num_altsetting; set_no++) + { + ifcdesc = (interface->altsetting + set_no); + /* The second condition is for older SCM SPR 532 who did + not know about the assigned CCID class. Instead of + trying to interpret the strings we simply check the + product ID. */ + if (ifcdesc && ifcdesc->extra + && ((ifcdesc->bInterfaceClass == 11 + && ifcdesc->bInterfaceSubClass == 0 + && ifcdesc->bInterfaceProtocol == 0) + || (ifcdesc->bInterfaceClass == 255 + && dev->descriptor.idVendor == VENDOR_SCM + && dev->descriptor.idProduct == 0xe003))) + { + idev = usb_open (dev); + if (!idev) + { + DEBUGOUT_1 ("usb_open failed: %s\n", + strerror (errno)); + continue; /* with next setting. */ + } + + rid = make_reader_id (idev, + dev->descriptor.idVendor, + dev->descriptor.idProduct, + dev->descriptor.iSerialNumber); + if (rid) + { + if (scan_mode) + { + char *p; + + /* We are collecting infos about all + available CCID readers. Store them and + continue. */ + DEBUGOUT_2 ("found CCID reader %d (ID=%s)\n", + *count, rid ); + p = malloc ((*rid_list? strlen (*rid_list):0) + 1 + + strlen (rid) + 1); + if (p) + { + *p = 0; + if (*rid_list) + { + strcat (p, *rid_list); + free (*rid_list); + } + strcat (p, rid); + strcat (p, "\n"); + *rid_list = p; + } + else /* Out of memory. */ + free (rid); + + rid = NULL; + ++*count; + } + else if (!*readerno + || (*readerno < 0 + && readerid + && !strcmp (readerid, rid))) + { + /* We found the requested reader. */ + if (ifcdesc_extra && ifcdesc_extra_len) + { + *ifcdesc_extra = malloc (ifcdesc + ->extralen); + if (!*ifcdesc_extra) + { + usb_close (idev); + free (rid); + return 1; /* Out of core. */ + } + memcpy (*ifcdesc_extra, ifcdesc->extra, + ifcdesc->extralen); + *ifcdesc_extra_len = ifcdesc->extralen; + } + + if (interface_number) + *interface_number = (ifcdesc->bInterfaceNumber); + + if (ep_bulk_out) + *ep_bulk_out = find_endpoint (ifcdesc, 0); + if (ep_bulk_in) + *ep_bulk_in = find_endpoint (ifcdesc, 1); + if (ep_intr) + *ep_intr = find_endpoint (ifcdesc, 2); + + if (r_dev) + *r_dev = dev; + if (r_rid) + { + *r_rid = rid; + rid = NULL; + } + else + free (rid); + + *r_idev = idev; + return 1; /* Found requested device. */ + } + else + { + /* This is not yet the reader we want. + fixme: We should avoid the extra usb_open + in this case. */ + if (*readerno >= 0) + --*readerno; + } + free (rid); + } + + usb_close (idev); + idev = NULL; + return 0; + } + } + } + } + + return 0; +} /* Combination function to either scan all CCID devices or to find and open one specific device. + The function returns 0 if a reader has been found or when a scan + returned without error. + + FIXME!! + With READERNO = -1 and READERID is NULL, scan mode is used and R_RID should be the address where to store the list of reader_ids we found. If on return this list is empty, no CCID device has been @@ -671,11 +888,11 @@ find_endpoint (struct usb_interface_descriptor *ifcdesc, int mode) With READERNO >= 0 or READERID is not NULL find mode is used. This uses the same algorithm as the scan mode but stops and returns at the entry number READERNO and return the handle for the the opened - USB device. If R_ID is not NULL it will receive the reader ID of + USB device. If R_RID is not NULL it will receive the reader ID of that device. If R_DEV is not NULL it will the device pointer of that device. If IFCDESC_EXTRA is NOT NULL it will receive a malloced copy of the interfaces "extra: data filed; - IFCDESC_EXTRA_LEN receive the lengtyh of this field. If there is + IFCDESC_EXTRA_LEN receive the length of this field. If there is no reader with number READERNO or that reader is not usable by our implementation NULL will be returned. The caller must close a returned USB device handle and free (if not passed as NULL) the @@ -684,17 +901,25 @@ find_endpoint (struct usb_interface_descriptor *ifcdesc, int mode) IFCDESC_EXTRA_LEN. With READERID being -1 the function stops if the READERID was found. + If R_FD is not -1 on return the device is not using USB for + transport but the device associated with that file descriptor. In + this case INTERFACE will receive the transport type and the other + USB specific return values are not used; the return value is + (void*)(1). + Note that the first entry of the returned reader ID list in scan mode corresponds with a READERNO of 0 in find mode. */ -static usb_dev_handle * +static int scan_or_find_devices (int readerno, const char *readerid, char **r_rid, struct usb_device **r_dev, unsigned char **ifcdesc_extra, size_t *ifcdesc_extra_len, int *interface_number, - int *ep_bulk_out, int *ep_bulk_in, int *ep_intr) + int *ep_bulk_out, int *ep_bulk_in, int *ep_intr, + usb_dev_handle **r_idev, + int *r_fd) { char *rid_list = NULL; int count = 0; @@ -702,8 +927,9 @@ scan_or_find_devices (int readerno, const char *readerid, struct usb_device *dev = NULL; usb_dev_handle *idev = NULL; int scan_mode = (readerno == -1 && !readerid); + int i; - /* Set return values to a default. */ + /* Set return values to a default. */ if (r_rid) *r_rid = NULL; if (r_dev) @@ -714,6 +940,10 @@ scan_or_find_devices (int readerno, const char *readerid, *ifcdesc_extra_len = 0; if (interface_number) *interface_number = 0; + if (r_idev) + *r_idev = NULL; + if (r_fd) + *r_fd = -1; /* See whether we want scan or find mode. */ if (scan_mode) @@ -734,161 +964,102 @@ scan_or_find_devices (int readerno, const char *readerid, { for (dev = bus->devices; dev; dev = dev->next) { - int cfg_no; - - for (cfg_no=0; cfg_no < dev->descriptor.bNumConfigurations; cfg_no++) + if (scan_or_find_usb_device (scan_mode, &readerno, &count, &rid_list, + readerid, + dev, + r_rid, + r_dev, + &idev, + ifcdesc_extra, + ifcdesc_extra_len, + interface_number, + ep_bulk_out, ep_bulk_in, ep_intr)) { - struct usb_config_descriptor *config = dev->config + cfg_no; - int ifc_no; - - if(!config) - continue; - - for (ifc_no=0; ifc_no < config->bNumInterfaces; ifc_no++) + /* Found requested device or out of core. */ + if (!idev) { - struct usb_interface *interface - = config->interface + ifc_no; - int set_no; - - if (!interface) - continue; - - for (set_no=0; set_no < interface->num_altsetting; set_no++) - { - struct usb_interface_descriptor *ifcdesc - = interface->altsetting + set_no; - char *rid; - - /* The second condition is for some SCM Micro - SPR 532 which does not know about the - assigned CCID class. Instead of trying to - interpret the strings we simply look at the - product ID. */ - if (ifcdesc && ifcdesc->extra - && ( (ifcdesc->bInterfaceClass == 11 - && ifcdesc->bInterfaceSubClass == 0 - && ifcdesc->bInterfaceProtocol == 0) - || (ifcdesc->bInterfaceClass == 255 - && dev->descriptor.idVendor == 0x04e6 - && dev->descriptor.idProduct == 0xe003))) - { - idev = usb_open (dev); - if (!idev) - { - DEBUGOUT_1 ("usb_open failed: %s\n", - strerror (errno)); - continue; - } - - rid = make_reader_id (idev, - dev->descriptor.idVendor, - dev->descriptor.idProduct, - dev->descriptor.iSerialNumber); - if (rid) - { - if (scan_mode) - { - char *p; - - /* We are collecting infos about all - available CCID readers. Store - them and continue. */ - DEBUGOUT_2 ("found CCID reader %d " - "(ID=%s)\n", - count, rid ); - if ((p = malloc ((rid_list? - strlen (rid_list):0) - + 1 + strlen (rid) - + 1))) - { - *p = 0; - if (rid_list) - { - strcat (p, rid_list); - free (rid_list); - } - strcat (p, rid); - strcat (p, "\n"); - rid_list = p; - } - else /* Out of memory. */ - free (rid); - rid = NULL; - count++; - } - else if (!readerno - || (readerno < 0 - && readerid - && !strcmp (readerid, rid))) - { - /* We found the requested reader. */ - if (ifcdesc_extra && ifcdesc_extra_len) - { - *ifcdesc_extra = malloc (ifcdesc - ->extralen); - if (!*ifcdesc_extra) - { - usb_close (idev); - free (rid); - return NULL; /* Out of core. */ - } - memcpy (*ifcdesc_extra, ifcdesc->extra, - ifcdesc->extralen); - *ifcdesc_extra_len = ifcdesc->extralen; - } - if (interface_number) - *interface_number = (ifcdesc-> - bInterfaceNumber); - if (ep_bulk_out) - *ep_bulk_out = find_endpoint (ifcdesc, 0); - if (ep_bulk_in) - *ep_bulk_in = find_endpoint (ifcdesc, 1); - if (ep_intr) - *ep_intr = find_endpoint (ifcdesc, 2); - - - if (r_dev) - *r_dev = dev; - if (r_rid) - { - *r_rid = rid; - rid = NULL; - } - else - free (rid); - return idev; /* READY. */ - } - else - { - /* This is not yet the reader we - want. fixme: We could avoid the - extra usb_open in this case. */ - if (readerno >= 0) - readerno--; - } - free (rid); - } - - usb_close (idev); - idev = NULL; - goto next_device; - } - } + free (rid_list); + return -1; /* error */ } + *r_idev = idev; + return 0; } - next_device: - ; } } - if (scan_mode) - *r_rid = rid_list; + /* Now check whether there are any devices with special transport types. */ + for (i=0; transports[i].name; i++) + { + int fd; + char *rid, *p; + + fd = open (transports[i].name, O_RDWR); + if (fd == -1) + continue; + + rid = malloc (strlen (transports[i].name) + 30 + 10); + if (!rid) + { + close (fd); + free (rid_list); + return -1; /* Error. */ + } + sprintf (rid, "0000:%04X:%s:0", transports[i].type, transports[i].name); + if (scan_mode) + { + DEBUGOUT_2 ("found CCID reader %d (ID=%s)\n", count, rid); + p = malloc ((rid_list? strlen (rid_list):0) + 1 + strlen (rid) + 1); + if (!p) + { + close (fd); + free (rid_list); + free (rid); + return -1; /* Error. */ + } + *p = 0; + if (rid_list) + { + strcat (p, rid_list); + free (rid_list); + } + strcat (p, rid); + strcat (p, "\n"); + rid_list = p; + ++count; + } + else if (!readerno || + (readerno < 0 && readerid && !strcmp (readerid, rid))) + { + /* Found requested device. */ + if (interface_number) + *interface_number = transports[i].type; + if (r_rid) + *r_rid = rid; + else + free (rid); + *r_fd = fd; + return 0; /* Okay, found device */ + } + else /* This is not yet the reader we want. */ + { + if (readerno >= 0) + --readerno; + } + free (rid); + close (fd); + } - return NULL; + if (scan_mode) + { + *r_rid = rid_list; + return 0; + } + else + return -1; } -/* Set the level of debugging to to usea dn return the old level. -1 +/* Set the level of debugging to LEVEL and return the old level. -1 just returns the old level. A level of 0 disables debugging, 1 enables debugging, 2 enables additional tracing of the T=1 protocol, other values are not yet defined. */ @@ -913,8 +1084,9 @@ ccid_get_reader_list (void) initialized_usb = 1; } - scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL, NULL, - NULL, NULL, NULL); + if (scan_or_find_devices (-1, NULL, &reader_list, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL)) + return NULL; /* Error. */ return reader_list; } @@ -927,6 +1099,7 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) int rc = 0; struct usb_device *dev = NULL; usb_dev_handle *idev = NULL; + int dev_fd = -1; char *rid = NULL; unsigned char *ifcdesc_extra = NULL; size_t ifcdesc_extra_len; @@ -959,10 +1132,10 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) else readerno = 0; /* Default. */ - idev = scan_or_find_devices (readerno, readerid, &rid, &dev, - &ifcdesc_extra, &ifcdesc_extra_len, - &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr); - if (!idev) + if (scan_or_find_devices (readerno, readerid, &rid, &dev, + &ifcdesc_extra, &ifcdesc_extra_len, + &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr, + &idev, &dev_fd) ) { if (readerno == -1) DEBUGOUT_1 ("no CCID reader with ID %s\n", readerid ); @@ -980,34 +1153,52 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) rc = CCID_DRIVER_ERR_OUT_OF_CORE; goto leave; } - (*handle)->idev = idev; (*handle)->rid = rid; - (*handle)->id_vendor = dev->descriptor.idVendor; - (*handle)->id_product = dev->descriptor.idProduct; - (*handle)->bcd_device = dev->descriptor.bcdDevice; - (*handle)->ifc_no = ifc_no; - (*handle)->ep_bulk_out = ep_bulk_out; - (*handle)->ep_bulk_in = ep_bulk_in; - (*handle)->ep_intr = ep_intr; + if (idev) /* Regular USB transport. */ + { + (*handle)->idev = idev; + (*handle)->dev_fd = -1; + (*handle)->id_vendor = dev->descriptor.idVendor; + (*handle)->id_product = dev->descriptor.idProduct; + (*handle)->bcd_device = dev->descriptor.bcdDevice; + (*handle)->ifc_no = ifc_no; + (*handle)->ep_bulk_out = ep_bulk_out; + (*handle)->ep_bulk_in = ep_bulk_in; + (*handle)->ep_intr = ep_intr; + } + else if (dev_fd != -1) /* Device transport. */ + { + (*handle)->idev = NULL; + (*handle)->dev_fd = dev_fd; + (*handle)->id_vendor = 0; /* Magic vendor for special transport. */ + (*handle)->id_product = ifc_no; /* Transport type */ + prepare_special_transport (*handle); + } + else + { + assert (!"no transport"); /* Bug. */ + } DEBUGOUT_2 ("using CCID reader %d (ID=%s)\n", readerno, rid ); - - if (parse_ccid_descriptor (*handle, ifcdesc_extra, ifcdesc_extra_len)) - { - DEBUGOUT ("device not supported\n"); - rc = CCID_DRIVER_ERR_NO_READER; - goto leave; - } - - rc = usb_claim_interface (idev, ifc_no); - if (rc) + if (idev) { - DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; - goto leave; + if (parse_ccid_descriptor (*handle, ifcdesc_extra, ifcdesc_extra_len)) + { + DEBUGOUT ("device not supported\n"); + rc = CCID_DRIVER_ERR_NO_READER; + goto leave; + } + + rc = usb_claim_interface (idev, ifc_no); + if (rc) + { + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } } - + leave: free (ifcdesc_extra); if (rc) @@ -1015,6 +1206,8 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) free (rid); if (idev) usb_close (idev); + if (dev_fd != -1) + close (dev_fd); free (*handle); *handle = NULL; } @@ -1054,6 +1247,11 @@ do_close_reader (ccid_driver_t handle) usb_close (handle->idev); handle->idev = NULL; } + if (handle->dev_fd != -1) + { + close (handle->dev_fd); + handle->dev_fd = -1; + } } @@ -1080,43 +1278,49 @@ ccid_shutdown_reader (ccid_driver_t handle) do_close_reader (handle); - idev = scan_or_find_devices (-1, handle->rid, NULL, &dev, - &ifcdesc_extra, &ifcdesc_extra_len, - &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr); - if (!idev) + if (scan_or_find_devices (-1, handle->rid, NULL, &dev, + &ifcdesc_extra, &ifcdesc_extra_len, + &ifc_no, &ep_bulk_out, &ep_bulk_in, &ep_intr, + &idev, NULL) || !idev) { DEBUGOUT_1 ("no CCID reader with ID %s\n", handle->rid); return CCID_DRIVER_ERR_NO_READER; } - - handle->idev = idev; - handle->ifc_no = ifc_no; - handle->ep_bulk_out = ep_bulk_out; - handle->ep_bulk_in = ep_bulk_in; - handle->ep_intr = ep_intr; - - if (parse_ccid_descriptor (handle, ifcdesc_extra, ifcdesc_extra_len)) + if (idev) { - DEBUGOUT ("device not supported\n"); - rc = CCID_DRIVER_ERR_NO_READER; - goto leave; - } - - rc = usb_claim_interface (idev, ifc_no); - if (rc) - { - DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); - rc = CCID_DRIVER_ERR_CARD_IO_ERROR; - goto leave; + handle->idev = idev; + handle->ifc_no = ifc_no; + handle->ep_bulk_out = ep_bulk_out; + handle->ep_bulk_in = ep_bulk_in; + handle->ep_intr = ep_intr; + + if (parse_ccid_descriptor (handle, ifcdesc_extra, ifcdesc_extra_len)) + { + DEBUGOUT ("device not supported\n"); + rc = CCID_DRIVER_ERR_NO_READER; + goto leave; + } + + rc = usb_claim_interface (idev, ifc_no); + if (rc) + { + DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc); + rc = CCID_DRIVER_ERR_CARD_IO_ERROR; + goto leave; + } } - + leave: free (ifcdesc_extra); if (rc) { - usb_close (handle->idev); + if (handle->idev) + usb_close (handle->idev); handle->idev = NULL; + if (handle->dev_fd != -1) + close (handle->dev_fd); + handle->dev_fd = -1; } return rc; @@ -1147,6 +1351,31 @@ ccid_check_card_presence (ccid_driver_t handle) } +/* 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 + return -1; + } + nleft -= nwritten; + buf = (const char*)buf + nwritten; + } + + return 0; +} + + /* Write a MSG of length MSGLEN to the designated bulk out endpoint. Returns 0 on success. */ static int @@ -1154,17 +1383,28 @@ bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen) { int rc; - rc = usb_bulk_write (handle->idev, - handle->ep_bulk_out, - (char*)msg, msglen, - 1000 /* ms timeout */); - if (rc == msglen) - return 0; - - if (rc == -1) - DEBUGOUT_1 ("usb_bulk_write error: %s\n", strerror (errno)); + if (handle->idev) + { + rc = usb_bulk_write (handle->idev, + handle->ep_bulk_out, + (char*)msg, msglen, + 1000 /* ms timeout */); + if (rc == msglen) + return 0; + if (rc == -1) + DEBUGOUT_1 ("usb_bulk_write error: %s\n", strerror (errno)); + else + DEBUGOUT_1 ("usb_bulk_write failed: %d\n", rc); + } else - DEBUGOUT_1 ("usb_bulk_write failed: %d\n", rc); + { + rc = writen (handle->dev_fd, msg, msglen); + if (!rc) + return 0; + DEBUGOUT_2 ("writen to %d failed: %s\n", + handle->dev_fd, strerror (errno)); + + } return CCID_DRIVER_ERR_CARD_IO_ERROR; } @@ -1187,17 +1427,31 @@ bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, for USB IOCTLs. */ memset (buffer, 0, length); retry: - rc = usb_bulk_read (handle->idev, - handle->ep_bulk_in, - (char*)buffer, length, - timeout); - if (rc < 0) + if (handle->idev) { - DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno)); - return CCID_DRIVER_ERR_CARD_IO_ERROR; + rc = usb_bulk_read (handle->idev, + handle->ep_bulk_in, + (char*)buffer, length, + timeout); + if (rc < 0) + { + DEBUGOUT_1 ("usb_bulk_read error: %s\n", strerror (errno)); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + *nread = msglen = rc; + } + else + { + rc = read (handle->dev_fd, buffer, length); + if (rc < 0) + { + DEBUGOUT_2 ("read from %d failed: %s\n", + handle->dev_fd, strerror (errno)); + return CCID_DRIVER_ERR_CARD_IO_ERROR; + } + *nread = msglen = rc; } - *nread = msglen = rc; if (msglen < 10) { @@ -1339,11 +1593,16 @@ ccid_poll (ccid_driver_t handle) size_t msglen; int i, j; - rc = usb_bulk_read (handle->idev, - handle->ep_intr, - (char*)msg, sizeof msg, - 0 /* ms timeout */ ); - if (rc < 0 && errno == ETIMEDOUT) + if (handle->idev) + { + rc = usb_bulk_read (handle->idev, + handle->ep_intr, + (char*)msg, sizeof msg, + 0 /* ms timeout */ ); + if (rc < 0 && errno == ETIMEDOUT) + return 0; + } + else return 0; if (rc < 0) -- cgit v1.2.3 From ee3f99f4e4901d216fc85f52316a83e554ae5db4 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 6 Feb 2006 18:31:27 +0000 Subject: . --- NEWS | 2 ++ scd/ccid-driver.c | 2 +- tools/ChangeLog | 4 ++++ tools/gpgconf-comp.c | 3 +++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 963b4f2f2..b3b8d05ce 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ Noteworthy changes in version 1.9.21 * [scdaemon] Support for keypads of some readers. Tested only with SPR532. New option --disable-keypad. + * Support for CardMan 4040 PCMCIA reader. + Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index e884c6624..1b04a0a85 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -1,5 +1,5 @@ /* ccid-driver.c - USB ChipCardInterfaceDevices driver - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. * Written by Werner Koch. * * This file is part of GnuPG. diff --git a/tools/ChangeLog b/tools/ChangeLog index b0b7499eb..67dcbd860 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,7 @@ +2005-12-20 Werner Koch <wk@g10code.com> + + * gpgconf-comp.c (gc_options_gpg): Add allow-pka-lookup. + 2005-12-14 Werner Koch <wk@g10code.com> * Makefile.am (bin_PROGRAMS): Build gpgparsemail. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 497707532..a27da3941 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -600,6 +600,9 @@ static gc_option_t gc_options_gpg[] = { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", "|URL|use keyserver at URL", GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, + { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, + "gnupg", N_("allow PKA lookups (DNS requests)"), + GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, GC_OPTION_NULL -- cgit v1.2.3 From 3d7b030025c056bbe5fbc659cd56ba1888725e99 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 8 Feb 2006 17:56:01 +0000 Subject: Fixed a couple of problems with omnikey based readers --- scd/ChangeLog | 6 +++++ scd/ccid-driver.c | 79 +++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 359b3f05a..5dab2019c 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2006-02-08 Werner Koch <wk@g10code.com> + + * ccid-driver.c (ccid_get_atr): Read Parameter and select T=1 + using these parameters. + (scan_or_find_devices): Check for NULL r_fd. + 2006-02-02 Werner Koch <wk@g10code.com> * ccid-driver.c (special_transport): New diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 1b04a0a85..519cb5f2d 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -347,10 +347,6 @@ prepare_special_transport (ccid_driver_t handle) { case TRANSPORT_CM4040: DEBUGOUT ("setting up transport for CardMan 4040\n"); - /* Most values are guessed. */ - handle->nonnull_nad = 1; - handle->auto_ifsd = 1; - handle->max_ifsd = 254; handle->apdu_level = 1; break; @@ -877,8 +873,6 @@ scan_or_find_usb_device (int scan_mode, The function returns 0 if a reader has been found or when a scan returned without error. - FIXME!! - With READERNO = -1 and READERID is NULL, scan mode is used and R_RID should be the address where to store the list of reader_ids we found. If on return this list is empty, no CCID device has been @@ -1037,7 +1031,8 @@ scan_or_find_devices (int readerno, const char *readerid, *r_rid = rid; else free (rid); - *r_fd = fd; + if (r_fd) + *r_fd = fd; return 0; /* Okay, found device */ } else /* This is not yet the reader we want. */ @@ -1708,6 +1703,7 @@ ccid_get_atr (ccid_driver_t handle, unsigned int edc; int i; int tried_iso = 0; + int got_param; /* First check whether a card is available. */ rc = ccid_slot_status (handle, &statusbits); @@ -1716,6 +1712,7 @@ ccid_get_atr (ccid_driver_t handle, if (statusbits == 2) return CCID_DRIVER_ERR_NO_CARD; + /* For an inactive and also for an active card, issue the PowerOn command to get the ATR. */ again: @@ -1764,6 +1761,44 @@ ccid_get_atr (ccid_driver_t handle, *atrlen = n; } + got_param = 0; + msg[0] = PC_to_RDR_GetParameters; + msg[5] = 0; /* slot */ + msg[6] = seqno = handle->seqno++; + msg[7] = 0; /* RFU */ + msg[8] = 0; /* RFU */ + msg[9] = 0; /* RFU */ + set_msg_len (msg, 0); + msglen = 10; + rc = bulk_out (handle, msg, msglen); + if (!rc) + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, + seqno, 2000, 0); + if (rc) + DEBUGOUT ("GetParameters failed\n"); + else + { + DEBUGOUT ("GetParametes returned"); + for (i=0; i < msglen; i++) + DEBUGOUT_CONT_1 (" %02X", msg[i]); + DEBUGOUT_LF (); + if (msglen >= 10) + { + DEBUGOUT_1 (" protocol ..........: T=%d\n", msg[9]); + if (msglen == 17 && msg[9] == 1) + { + DEBUGOUT_1 (" bmFindexDindex ....: %02X\n", msg[10]); + DEBUGOUT_1 (" bmTCCKST1 .........: %02X\n", msg[11]); + DEBUGOUT_1 (" bGuardTimeT1 ......: %02X\n", msg[12]); + DEBUGOUT_1 (" bmWaitingIntegersT1: %02X\n", msg[13]); + DEBUGOUT_1 (" bClockStop ........: %02X\n", msg[14]); + DEBUGOUT_1 (" bIFSC .............: %d\n", msg[15]); + DEBUGOUT_1 (" bNadValue .........: %d\n", msg[16]); + got_param = 1; + } + } + } + /* Setup parameters to select T=1. */ msg[0] = PC_to_RDR_SetParameters; msg[5] = 0; /* slot */ @@ -1772,14 +1807,17 @@ ccid_get_atr (ccid_driver_t handle, msg[8] = 0; /* RFU */ msg[9] = 0; /* RFU */ - /* FIXME: Get those values from the ATR. */ - msg[10]= 0x01; /* Fi/Di */ - msg[11]= 0x10; /* LRC, direct convention. */ - msg[12]= 0; /* Extra guardtime. */ - msg[13]= 0x41; /* BWI/CWI */ - msg[14]= 0; /* No clock stoppping. */ - msg[15]= 254; /* IFSC */ - msg[16]= 0; /* Does not support non default NAD values. */ + if (!got_param) + { + /* FIXME: Get those values from the ATR. */ + msg[10]= 0x01; /* Fi/Di */ + msg[11]= 0x10; /* LRC, direct convention. */ + msg[12]= 0; /* Extra guardtime. */ + msg[13]= 0x41; /* BWI/CWI */ + msg[14]= 0; /* No clock stoppping. */ + msg[15]= 254; /* IFSC */ + msg[16]= 0; /* Does not support non default NAD values. */ + } set_msg_len (msg, 7); msglen = 10 + 7; @@ -1791,15 +1829,16 @@ ccid_get_atr (ccid_driver_t handle, rc = bulk_out (handle, msg, msglen); if (rc) return rc; - /* Note that we ignore the error code on purpose. */ - bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, - seqno, 5000, 0); + rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, + seqno, 5000, 0); + if (rc) + DEBUGOUT ("SetParameters failed (ignored)\n"); handle->t1_ns = 0; handle->t1_nr = 0; - /* Send an S-Block with our maximun IFSD to the CCID. */ - if (!handle->auto_ifsd) + /* Send an S-Block with our maximum IFSD to the CCID. */ + if (!handle->apdu_level && !handle->auto_ifsd) { tpdu = msg+10; /* NAD: DAD=1, SAD=0 */ -- cgit v1.2.3 From 4472efd12c3f3585cc94f3f938fb5e0bd6beabce Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 9 Feb 2006 18:29:31 +0000 Subject: PIN caching of cards does now work. --- NEWS | 2 + agent/ChangeLog | 10 +++++ agent/agent.h | 2 +- agent/call-scd.c | 78 +++++++++++++++++++++++++++++---- agent/gpg-agent.c | 2 +- scd/ChangeLog | 14 ++++++ scd/app-common.h | 2 + scd/app.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++------- scd/command.c | 49 +++++++++++++++++++-- 9 files changed, 256 insertions(+), 30 deletions(-) diff --git a/NEWS b/NEWS index b3b8d05ce..38dee1ec3 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ Noteworthy changes in version 1.9.21 * Support for CardMan 4040 PCMCIA reader. + * Cards are not anymore reseted at the end of a connection. + Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index 0aef39487..fbb1a37e0 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,13 @@ +2006-02-09 Werner Koch <wk@g10code.com> + + * call-scd.c (struct scd_local_s): New field next_local. + (scd_local_list): New. + (start_scd): Put new local into list. + (agent_reset_scd): Remove it from the list. + (agent_scd_check_aliveness): Here is the actual reason why we need + all this stuff. + (agent_reset_scd): Send the new command RESTART instead of RESET. + 2005-12-16 Werner Koch <wk@g10code.com> * minip12.c (cram_octet_string): New diff --git a/agent/agent.h b/agent/agent.h index 0918395ce..1542d6b9f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -54,7 +54,7 @@ struct { int batch; /* Batch mode */ const char *homedir; /* Configuration directory name */ - /* Environment setting gathered at program start or hanged using the + /* Environment setting gathered at program start or changed using the Assuan command UPDATESTARTUPTTY. */ char *startup_display; char *startup_ttyname; diff --git a/agent/call-scd.c b/agent/call-scd.c index a883f2733..ff241ce41 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -45,6 +45,16 @@ /* Definition of module local data of the CTRL structure. */ struct scd_local_s { + /* We keep a list of all allocated context with a an achnor at + SCD_LOCAL_LIST (see below). */ + struct scd_local_s *next_local; + + /* We need to get back to the ctrl object actually referencing this + structure. This is really an awkward way of enumerint the lcoal + contects. A much cleaner way would be to keep a global list of + ctrl objects to enumerate them. */ + ctrl_t ctrl_backlink; + assuan_context_t ctx; /* NULL or session context for the SCdaemon used with this connection. */ int locked; /* This flag is used to assert proper use of @@ -72,6 +82,10 @@ struct inq_needpin_s }; +/* To keep track of all active SCD contexts, we keep a linked list + anchored at this variable. */ +static struct scd_local_s *scd_local_list; + /* A Mutex used inside the start_scd function. */ static pth_mutex_t start_scd_lock; @@ -202,6 +216,9 @@ start_scd (ctrl_t ctrl) ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local); if (!ctrl->scd_local) return gpg_error_from_errno (errno); + ctrl->scd_local->ctrl_backlink = ctrl; + ctrl->scd_local->next_local = scd_local_list; + scd_local_list = ctrl->scd_local; } @@ -216,7 +233,7 @@ start_scd (ctrl_t ctrl) if (ctrl->scd_local->ctx) return 0; /* Okay, the context is fine. We used to test for an - alive context here and do an disconnect. How that we + alive context here and do an disconnect. Now that we have a ticker function to check for it, it is easier not to check here but to let the connection run on an error instead. */ @@ -404,12 +421,30 @@ agent_scd_check_aliveness (void) if (pid != (pid_t)(-1) && pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) { - /* Okay, scdaemon died. Disconnect the primary connection now - but take care that it won't do another wait. */ + /* Okay, scdaemon died. Disconnect the primary connection + now but take care that it won't do another wait. Also + cleanup all other connections and release their + resources. The next use will start a new daemon then. + Due to the use of the START_SCD_LOCAL we are sure that + none of these context are actually in use. */ + struct scd_local_s *sl; + assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1); assuan_disconnect (primary_scd_ctx); + + for (sl=scd_local_list; sl; sl = sl->next_local) + { + if (sl->ctx) + { + if (sl->ctx != primary_scd_ctx) + assuan_disconnect (sl->ctx); + sl->ctx = NULL; + } + } + primary_scd_ctx = NULL; primary_scd_ctx_reusable = 0; + xfree (socket_name); socket_name = NULL; } @@ -422,7 +457,8 @@ agent_scd_check_aliveness (void) -/* Reset the SCD if it has been used. */ +/* Reset the SCD if it has been used. Actually it is not a reset but + a cleanup of resources used by the current connection. */ int agent_reset_scd (ctrl_t ctrl) { @@ -436,16 +472,40 @@ agent_reset_scd (ctrl_t ctrl) reuse. */ if (ctrl->scd_local->ctx == primary_scd_ctx) { - /* The RESET may fail for example if the scdaemon has - already been terminated. We need to set the reusable - flag anyway to make sure that the aliveness check can - clean it up. */ - assuan_transact (primary_scd_ctx, "RESET", + /* Send a RESTART to the SCD. This is required for the + primary connection as a kind of virtual EOF; we don't + have another way to tell it that the next command + should be viewed as if a new connection has been + made. For the non-primary connections this is not + needed as we simply close the socket. We don't check + for an error here because the RESTART may fail for + example if the scdaemon has already been terminated. + Anyway, we need to set the reusable flag to make sure + that the aliveness check can clean it up. */ + assuan_transact (primary_scd_ctx, "RESTART", NULL, NULL, NULL, NULL, NULL, NULL); primary_scd_ctx_reusable = 1; } else assuan_disconnect (ctrl->scd_local->ctx); + ctrl->scd_local->ctx = NULL; + } + + /* Remove the local context from our list and release it. */ + if (!scd_local_list) + BUG (); + else if (scd_local_list == ctrl->scd_local) + scd_local_list = ctrl->scd_local->next_local; + else + { + struct scd_local_s *sl; + + for (sl=scd_local_list; sl->next_local; sl = sl->next_local) + if (sl->next_local == ctrl->scd_local) + break; + if (!sl->next_local) + BUG (); + sl->next_local = ctrl->scd_local->next_local; } xfree (ctrl->scd_local); ctrl->scd_local = NULL; diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index b6a4f90a6..22bd5589d 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1320,7 +1320,7 @@ handle_tick (void) agent_scd_check_aliveness (); /* If we are running as a child of another process, check whether - the parent is still alive and shutdwon if now. */ + the parent is still alive and shutdown if not. */ #ifndef HAVE_W32_SYSTEM if (parent_pid != (pid_t)(-1)) { diff --git a/scd/ChangeLog b/scd/ChangeLog index 5dab2019c..3b850a293 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,17 @@ +2006-02-09 Werner Koch <wk@g10code.com> + + * app.c (release_application): Factored code out to .. + (deallocate_app): new function. + (select_application): Introduce new saved application stuff. + (application_notify_card_removed): New. + * command.c (update_card_removed): Call it. + + * app.c (check_application_conflict): New. + * command.c (open_card): Use it here. + (cmd_restart): New command. + + * command.c (cmd_lock): Fixed --wait option to actually terminate. + 2006-02-08 Werner Koch <wk@g10code.com> * ccid-driver.c (ccid_get_atr): Read Parameter and select T=1 diff --git a/scd/app-common.h b/scd/app-common.h index 94087f221..d294a5c25 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -129,6 +129,8 @@ size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); /*-- app.c --*/ void app_dump_state (void); +void application_notify_card_removed (int slot); +gpg_error_t check_application_conflict (ctrl_t ctrl, const char *name); gpg_error_t select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app); void release_application (app_t app); diff --git a/scd/app.c b/scd/app.c index f27b400b1..fad45ed85 100644 --- a/scd/app.c +++ b/scd/app.c @@ -40,9 +40,15 @@ static struct int initialized; pth_mutex_t lock; app_t app; /* Application context in use or NULL. */ + app_t last_app; /* Last application object used as this slot or NULL. */ } lock_table[10]; + +static void deallocate_app (app_t app); + + + /* Lock the reader SLOT. This function shall be used right before calling any of the actual application functions to serialize access to the reader. We do this always even if the reader is not @@ -68,6 +74,7 @@ lock_reader (int slot) } lock_table[slot].initialized = 1; lock_table[slot].app = NULL; + lock_table[slot].last_app = NULL; } if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL)) @@ -121,13 +128,21 @@ app_dump_state (void) log_info ("app_dump_state: slot=%d lock=", slot); dump_mutex_state (&lock_table[slot].lock); if (lock_table[slot].app) - log_printf (" app=%p type=`%s'", - lock_table[slot].app, lock_table[slot].app->apptype); + { + log_printf (" app=%p", lock_table[slot].app); + if (lock_table[slot].app->apptype) + log_printf (" type=`%s'", lock_table[slot].app->apptype); + } + if (lock_table[slot].last_app) + { + log_printf (" lastapp=%p", lock_table[slot].last_app); + if (lock_table[slot].last_app->apptype) + log_printf (" type=`%s'", lock_table[slot].last_app->apptype); + } log_printf ("\n"); } } - /* Check wether the application NAME is allowed. This does not mean we have support for it though. */ static int @@ -142,6 +157,46 @@ is_app_allowed (const char *name) } +/* This may be called to tell this module about a removed card. */ +void +application_notify_card_removed (int slot) +{ + if (slot < 0 || slot >= DIM (lock_table)) + return; + + /* Deallocate a saved application for that slot, so that we won't + try to reuse it. */ + if (lock_table[slot].initialized && lock_table[slot].last_app) + { + app_t app = lock_table[slot].last_app; + + lock_table[slot].last_app = NULL; + deallocate_app (app); + } +} + + +/* This fucntion is used by the serialno command to check for an + application conflict which may appear if the serialno command is + used to request a specific application and the connection has + already done a select_application. */ +gpg_error_t +check_application_conflict (ctrl_t ctrl, const char *name) +{ + int slot = ctrl->reader_slot; + app_t app; + + if (slot < 0 || slot >= DIM (lock_table)) + return gpg_error (GPG_ERR_INV_VALUE); + + app = lock_table[slot].initialized ? lock_table[slot].app : NULL; + if (app && app->apptype && name) + if ( ascii_strcasecmp (app->apptype, name)) + return gpg_error (GPG_ERR_CONFLICT); + return 0; +} + + /* If called with NAME as NULL, select the best fitting application and return a context; otherwise select the application with NAME and return a context. SLOT identifies the reader device. Returns @@ -173,6 +228,32 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) return gpg_error (GPG_ERR_CONFLICT); } + /* If we don't have an app, check whether we have a saved + application for that slot. This is useful so that a card does + not get reset even if only one session is using the card - so the + PIN cache and other cached data are preserved. */ + if (!app && lock_table[slot].initialized && lock_table[slot].last_app) + { + app = lock_table[slot].last_app; + if (!name || (app->apptype && !ascii_strcasecmp (app->apptype, name)) ) + { + /* Yes, we can reuse this application - either the caller + requested an unspecific one or the requested one matches + the saved one. */ + lock_table[slot].app = app; + lock_table[slot].last_app = NULL; + } + else + { + /* No, this saved application can't be used - deallocate it. */ + lock_table[slot].last_app = NULL; + deallocate_app (app); + app = NULL; + } + } + + /* If we can reuse an application, bump the reference count and + return it. */ if (app) { if (app->slot != slot) @@ -183,6 +264,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) return 0; /* Okay: We share that one. */ } + /* Need to allocate a new one. */ app = xtrycalloc (1, sizeof *app); if (!app) { @@ -281,9 +363,25 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) } +/* Deallocate the application. */ +static void +deallocate_app (app_t app) +{ + if (app->fnc.deinit) + { + app->fnc.deinit (app); + app->fnc.deinit = NULL; + } + + xfree (app->serialno); + xfree (app); +} + /* Free the resources associated with the application APP. APP is allowed to be NULL in which case this is a no-op. Note that we are - using reference counting to track the users of the application. */ + using reference counting to track the users of the application and + actually deferiing the deallcoation to allow for a later resuse by + a new connection. */ void release_application (app_t app) { @@ -297,20 +395,19 @@ release_application (app_t app) if (--app->ref_count) return; - /* Clear the reference to the application from the lock table. */ + /* Move the reference to the application in the lock table. */ for (slot = 0; slot < DIM (lock_table); slot++) if (lock_table[slot].initialized && lock_table[slot].app == app) - lock_table[slot].app = NULL; - - /* Deallocate. */ - if (app->fnc.deinit) - { - app->fnc.deinit (app); - app->fnc.deinit = NULL; - } + { + if (lock_table[slot].last_app) + deallocate_app (lock_table[slot].last_app); + lock_table[slot].last_app = lock_table[slot].app; + lock_table[slot].app = NULL; + return; + } - xfree (app->serialno); - xfree (app); + log_debug ("application missing in lock table - deallocating anyway\n"); + deallocate_app (app); } diff --git a/scd/command.c b/scd/command.c index d556822a2..1b7a8f67e 100644 --- a/scd/command.c +++ b/scd/command.c @@ -47,7 +47,7 @@ #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t)) -/* Macro to flag a a removed card. */ +/* Macro to flag a removed card. */ #define TEST_CARD_REMOVAL(c,r) \ do { \ int _r = (r); \ @@ -108,6 +108,8 @@ update_card_removed (int slot, int value) if (sl->ctrl_backlink && sl->ctrl_backlink->reader_slot == slot) sl->card_removed = value; + if (value) + application_notify_card_removed (slot); } @@ -142,7 +144,7 @@ do_reset (ctrl_t ctrl, int do_close) struct server_local_s *sl; /* If we are the only session with the reader open we may close - it. If not, do a reset unless the a lock is held on the + it. If not, do a reset unless a lock is held on the reader. */ for (sl=session_list; sl; sl = sl->next_session) if (sl != ctrl->server_local @@ -257,7 +259,12 @@ open_card (ctrl_t ctrl, const char *apptype) return gpg_error (GPG_ERR_LOCKED); if (ctrl->app_ctx) - return 0; /* Already initialized for one specific application. */ + { + /* Already initialized for one specific application. Need to + check that the client didn't requested a specific application + different from the one in use. */ + return check_application_conflict (ctrl, apptype); + } if (ctrl->reader_slot != -1) slot = ctrl->reader_slot; @@ -1201,7 +1208,7 @@ cmd_checkpin (assuan_context_t ctx, char *line) Grant exclusive card access to this session. Note that there is no lock counter used and a second lock from the same session will - get ignore. A single unlock (or RESET) unlocks the session. + be ignored. A single unlock (or RESET) unlocks the session. Return GPG_ERR_LOCKED if another session has locked the reader. If the option --wait is given the command will wait until a @@ -1225,9 +1232,12 @@ cmd_lock (assuan_context_t ctx, char *line) #ifdef USE_GNU_PTH if (rc && has_option (line, "--wait")) { + rc = 0; pth_sleep (1); /* Better implement an event mechanism. However, for card operations this should be sufficient. */ + /* FIXME: Need to check that the connection is still alive. + This can be done by issuing status messages. */ goto retry; } #endif /*USE_GNU_PTH*/ @@ -1293,6 +1303,36 @@ cmd_getinfo (assuan_context_t ctx, char *line) } +/* RESTART + + Restart the current connection; this is a kind of warn reset. It + deletes the context used by this connection but does not send a + RESET to the card. Thus the card itself won't get reset. + + This is used by gpg-agent to reuse a primary pipe connection and + may be used by clients to backup from a conflict in the serial + command; i.e. to select another application. +*/ + +static int +cmd_restart (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + + if (ctrl->app_ctx) + { + release_application (ctrl->app_ctx); + ctrl->app_ctx = NULL; + } + if (locked_session && ctrl->server_local == locked_session) + { + locked_session = NULL; + log_info ("implicitly unlocking due to RESTART\n"); + } + return 0; +} + + /* Tell the assuan library about our commands */ @@ -1323,6 +1363,7 @@ register_commands (assuan_context_t ctx) { "LOCK", cmd_lock }, { "UNLOCK", cmd_unlock }, { "GETINFO", cmd_getinfo }, + { "RESTART", cmd_restart }, { NULL } }; int i, rc; -- cgit v1.2.3 From 6ec4e8c6a1c37a78295b8fdb9344707b9ddfc384 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 14 Feb 2006 13:34:23 +0000 Subject: Added documentation for qualified signatures --- doc/ChangeLog | 4 +++ doc/gpgsm.texi | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sm/qualified.c | 2 +- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index d6293d97e..0c60d29a7 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2006-02-14 Werner Koch <wk@gnupg.org> + + * gpgsm.texi (GPGSM Configuration): New section. + 2005-11-14 Werner Koch <wk@g10code.com> * qualified.txt: Added real information. diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 653ada332..5a8778add 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -23,6 +23,7 @@ complies with all rules defined for the German Sphinx project. @menu * GPGSM Commands:: List of all commands. * GPGSM Options:: List of all options. +* GPGSM Configuration:: Configuration files. * GPGSM Examples:: Some usage examples. Developer information: @@ -526,6 +527,105 @@ All the long options may also be given in the configuration file after stripping off the two leading dashes. +@c man begin FILES + +@node GPGSM Configuration +@section Configuration files + +There are a few configuration files to control certain aspects of +@command{gpgsm}'s operation. Unless noted, they are expected in the +current home directory (@pxref{option --homedir}). + +@table @file + +@item gpgsm.conf +@cindex gpgsm.conf +This is the standard configuration file read by @command{gpgsm} on +startup. It may contain any valid long option; the leading two dashes +may not be entered and the option may not be abbreviated. This default +name may be changed on the command line (@pxref{option + --options}). + +@item policies.txt +@cindex policies.txt +This is a list of allowed CA policies. This file should list the +object identifiers of the policies line by line. Empty lines and +lines starting with a hash mark are ignored. Policies missing in this +file and not marked as critical in the certificate will print only a +warning; certificates with policies marked as critical and not listed +in this file will fail the signature verification. + +For example, to allow only the policy 2.289.9.9, the file should look +like this: + +@example +# Allowed policies +2.289.9.9 +@end example + +@item qualified.txt +@cindex qualified.txt +This is the list of root certificates used for qualified certificates. +They are defined as certificates capable of creating legally binding +signatures in the same way as handwritten signatures are. Comments +start with a hash mark and empty lines are ignored. Lines do have a +length limit but this is not a serious limitation as the format of the +entries is fixed and checked by gpgsm: A non-comment line starts with +optional white spaces, followed by exactly 40 hex character, white space +and a lowercased 2 letter country code. Additional data delimited with +by a white space is current ignored but might late be used for other +purposes. + +Note that even if a certificate is listed in this file, this does not +mean that thecertificate is trusted; in general the certificates listed +in this file need to be listed also in @file{trustlist.txt}. + +This is a global file an installed in the data directory +(e.g. @file{/usr/share/gnupg/qualified.txt}). GnuPG installs a suitable +file with root certificates as used in Germany. As new Root-CA +certificates may be issued over time, these entries may need to be +updated; new distributions of this software should come with an updated +list but it is still the responsibility of the Administrator to check +that this list is correct. + +Everytime @command{gpgsm} uses a certificate for signing or verification +this file will be consulted to check whether the certificate under +question has ultimately been issued by one of these CAs. If this is the +case the user will be informed that the verified signature represents a +legally binding (``qualified'') signature. When creating a signature +using such a certificate an extra prompt will be issued to let the user +confirm that such a legally binding signature shall really be created. + +Because this software has not yet been approved for use with such +certificates, appropriate notices will be shown to indicate this fact. + +@end table + +Note that on larger installations, it is useful to put predefined files +into the directory @file{/etc/skel/.gnupg/} so that newly created users +start up with a working configuration. For existing users the a small +helper script is provided to create these files (@pxref{addgnupghome}). + + +For internal purposes gpgsm creates and maintaines a few other files; +They all live in in the current home directory (@pxref{option +--homedir}). Only @command{gpgsm} may modify these files. + +@table @file +@item pubring.kbx +@cindex pubring.kbx +This a database file storing the certificates as well as meta +information. For debugging purposes the tool @command{kbxutil} may be +used to show the internal structure of this file. + +@item random_seed +@cindex random_seed +This content of this file is used to maintain the internal state of the +random number generator accross invocations. The same file is used by +other programs of this software too. + +@end table + @c @c Examples diff --git a/sm/qualified.c b/sm/qualified.c index 804b6c41e..a52269734 100644 --- a/sm/qualified.c +++ b/sm/qualified.c @@ -270,7 +270,7 @@ gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert) /* Popup a prompt to inform the user that the signature created is not - a qualified one. This is of course only doen if we know that we + a qualified one. This is of course only done if we know that we have been approved. */ gpg_error_t gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert) -- cgit v1.2.3 From d59f87e94b5dd71835a44fd50d017da672179907 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Sun, 19 Feb 2006 22:09:10 +0000 Subject: Better warning messages --- sm/ChangeLog | 4 ++++ sm/call-dirmngr.c | 17 +++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 88d9763c8..764faa67d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,7 @@ +2006-02-17 Werner Koch <wk@g10code.com> + + * call-dirmngr.c (start_dirmngr): Print name of dirmngr to be started. + 2005-11-23 Werner Koch <wk@g10code.com> * gpgsm.h: New member QUALSIG_APPROVAL. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index dd38a889b..85467d4a2 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -170,8 +170,16 @@ start_dirmngr (void) int no_close_list[3]; int i; + if (!opt.dirmngr_program || !*opt.dirmngr_program) + opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR; + if ( !(pgmname = strrchr (opt.dirmngr_program, '/'))) + pgmname = opt.dirmngr_program; + else + pgmname++; + if (opt.verbose) - log_info (_("no running dirmngr - starting one\n")); + log_info (_("no running dirmngr - starting `%s'\n"), + opt.dirmngr_program); if (fflush (NULL)) { @@ -180,13 +188,6 @@ start_dirmngr (void) return tmperr; } - if (!opt.dirmngr_program || !*opt.dirmngr_program) - opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR; - if ( !(pgmname = strrchr (opt.dirmngr_program, '/'))) - pgmname = opt.dirmngr_program; - else - pgmname++; - argv[0] = pgmname; argv[1] = "--server"; argv[2] = NULL; -- cgit v1.2.3 From 89824e5d59efc5db0175550332bbf6ad54ba978f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 1 Mar 2006 11:05:47 +0000 Subject: Fixed card removal problems --- TODO | 7 +- scd/ChangeLog | 18 +++- scd/apdu.c | 4 +- scd/app.c | 14 ++- scd/ccid-driver.c | 21 ++++- scd/command.c | 276 ++++++++++++++++++++++++++++++------------------------ 6 files changed, 203 insertions(+), 137 deletions(-) diff --git a/TODO b/TODO index 7a1f989b4..85e08ed16 100644 --- a/TODO +++ b/TODO @@ -67,7 +67,12 @@ might want to have an agent context for each service request Using the session_list in command.c and the lock_table in app.c. IT would be better to do this just at one place. First we need to see how we can support cards with multiple applications. - +** Detecting a removed card works only after the ticker detected it. + We should check the card status in open-card to make this smoother. + Needs to be integrated with the status file update, though. It is + not a real problem because application will get a card removed status + and should the send a reset to try solving the problem. + * tests ** Makefile.am We use printf(1) to setup the library path, this is not portable. diff --git a/scd/ChangeLog b/scd/ChangeLog index 3b850a293..d539d210e 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,10 +1,26 @@ +2006-03-01 Werner Koch <wk@g10code.com> + + * command.c (status_file_update_lock): New. + (scd_update_reader_status_file): Use lock and factor existing code + out to .. + (update_reader_status_file): .. this. + (do_reset): Use the lock and call update_reader_status_file. + +2006-02-20 Werner Koch <wk@g10code.com> + + * apdu.c (open_pcsc_reader): Fixed double free. Thanks to Moritz. + 2006-02-09 Werner Koch <wk@g10code.com> + * command.c (get_reader_slot, do_reset) + (scd_update_reader_status_file): Rewrote. + * app.c (release_application): Factored code out to .. (deallocate_app): new function. (select_application): Introduce new saved application stuff. (application_notify_card_removed): New. - * command.c (update_card_removed): Call it. + * command.c (update_card_removed): Call it here. + (do_reset): And here. * app.c (check_application_conflict): New. * command.c (open_card): Use it here. diff --git a/scd/apdu.c b/scd/apdu.c index 5a5f18b43..adaaec612 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -1594,6 +1594,7 @@ open_pcsc_reader (const char *portstr) } strcpy (reader_table[slot].rdrname, portstr? portstr : list); xfree (list); + list = NULL; err = pcsc_connect (reader_table[slot].pcsc.context, reader_table[slot].rdrname, @@ -1611,7 +1612,6 @@ open_pcsc_reader (const char *portstr) xfree (reader_table[slot].rdrname); reader_table[slot].rdrname = NULL; reader_table[slot].used = 0; - xfree (list); return -1 /*pcsc_error_to_sw (err)*/; } @@ -2369,7 +2369,7 @@ apdu_close_reader (int slot) } /* Shutdown a reader; that is basically the same as a close but keeps - the handle ready for later use. A apdu_reset_header should be used + the handle ready for later use. A apdu_reset_reader should be used to get it active again. */ int apdu_shutdown_reader (int slot) diff --git a/scd/app.c b/scd/app.c index fad45ed85..7f6a8cc9f 100644 --- a/scd/app.c +++ b/scd/app.c @@ -165,13 +165,17 @@ application_notify_card_removed (int slot) return; /* Deallocate a saved application for that slot, so that we won't - try to reuse it. */ - if (lock_table[slot].initialized && lock_table[slot].last_app) + try to reuse it. If there is no saved application, set a flag so + that we won't save the current state. */ + if (lock_table[slot].initialized) { app_t app = lock_table[slot].last_app; - lock_table[slot].last_app = NULL; - deallocate_app (app); + if (app) + { + lock_table[slot].last_app = NULL; + deallocate_app (app); + } } } @@ -380,7 +384,7 @@ deallocate_app (app_t app) /* Free the resources associated with the application APP. APP is allowed to be NULL in which case this is a no-op. Note that we are using reference counting to track the users of the application and - actually deferiing the deallcoation to allow for a later resuse by + actually deferring the deallocation to allow for a later reuse by a new connection. */ void release_application (app_t app) diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 519cb5f2d..e990f757a 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -989,7 +989,12 @@ scan_or_find_devices (int readerno, const char *readerid, fd = open (transports[i].name, O_RDWR); if (fd == -1) - continue; + { + log_debug ("failed to open `%s': %s\n", + transports[i].name, strerror (errno)); + continue; + } + log_debug ("opened `%s': fd=%d\n", transports[i].name, fd); rid = malloc (strlen (transports[i].name) + 30 + 10); if (!rid) @@ -1042,6 +1047,7 @@ scan_or_find_devices (int readerno, const char *readerid, } free (rid); close (fd); + log_debug ("closed fd %d\n", fd); } if (scan_mode) @@ -1202,7 +1208,10 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid) if (idev) usb_close (idev); if (dev_fd != -1) - close (dev_fd); + { + close (dev_fd); + log_debug ("closed fd %d\n", dev_fd); + } free (*handle); *handle = NULL; } @@ -1245,6 +1254,7 @@ do_close_reader (ccid_driver_t handle) if (handle->dev_fd != -1) { close (handle->dev_fd); + log_debug ("closed fd %d\n", handle->dev_fd); handle->dev_fd = -1; } } @@ -1314,7 +1324,10 @@ ccid_shutdown_reader (ccid_driver_t handle) usb_close (handle->idev); handle->idev = NULL; if (handle->dev_fd != -1) - close (handle->dev_fd); + { + close (handle->dev_fd); + log_debug ("closed fd %d\n", handle->dev_fd); + } handle->dev_fd = -1; } @@ -1327,7 +1340,7 @@ ccid_shutdown_reader (ccid_driver_t handle) int ccid_close_reader (ccid_driver_t handle) { - if (!handle || !handle->idev) + if (!handle || (!handle->idev && handle->dev_fd == -1)) return 0; do_close_reader (handle); diff --git a/scd/command.c b/scd/command.c index 1b7a8f67e..805164d0f 100644 --- a/scd/command.c +++ b/scd/command.c @@ -62,9 +62,26 @@ && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot) +/* This structure is used to keep track of open readers (slots). */ +struct slot_status_s +{ + int valid; /* True if the other objects are valid. */ + int slot; /* Slot number of the reader or -1 if not open. */ + + int reset_failed; /* A reset failed. */ + + int any; /* Flag indicating whether any status check has been + done. This is set once to indicate that the status + tracking for the slot has been initialized. */ + unsigned int status; /* Last status of the slot. */ + unsigned int changed; /* Last change counter of teh slot. */ +}; + + /* Data used to associate an Assuan context with local server data. This object describes the local properties of one session. */ -struct server_local_s { +struct server_local_s +{ /* We keep a list of all active sessions with the anchor at SESSION_LIST (see below). This field is used for linking. */ struct server_local_s *next_session; @@ -86,6 +103,10 @@ struct server_local_s { }; +/* The table with information on all used slots. */ +static struct slot_status_s slot_table[10]; + + /* To keep track of all running sessions, we link all active server contexts and the anchor in this variable. */ static struct server_local_s *session_list; @@ -94,6 +115,13 @@ static struct server_local_s *session_list; in this variable. */ static struct server_local_s *locked_session; +/* While doing a reset we need to make sure that the ticker does not + call scd_update_reader_status_file while we are using it. */ +static pth_mutex_t status_file_update_lock = PTH_MUTEX_INIT; + + +/*-- Local prototypes --*/ +static void update_reader_status_file (void); @@ -107,7 +135,9 @@ update_card_removed (int slot, int value) for (sl=session_list; sl; sl = sl->next_session) if (sl->ctrl_backlink && sl->ctrl_backlink->reader_slot == slot) - sl->card_removed = value; + { + sl->card_removed = value; + } if (value) application_notify_card_removed (slot); } @@ -126,69 +156,52 @@ has_option (const char *line, const char *name) } -/* Reset the card and free the application context. With DO_CLOSE set - to true and this is the last session with a reference to the - reader, close the reader and don't do just a reset. */ +/* Reset the card and free the application context. With SEND_RESET + set to true actually send a RESET to the reader. */ static void -do_reset (ctrl_t ctrl, int do_close) +do_reset (ctrl_t ctrl, int send_reset) { int slot = ctrl->reader_slot; + if (!(slot == -1 || (slot >= 0 && slot < DIM(slot_table)))) + BUG (); + if (ctrl->app_ctx) { release_application (ctrl->app_ctx); ctrl->app_ctx = NULL; } - if (ctrl->reader_slot != -1) - { - struct server_local_s *sl; - /* If we are the only session with the reader open we may close - it. If not, do a reset unless a lock is held on the - reader. */ - for (sl=session_list; sl; sl = sl->next_session) - if (sl != ctrl->server_local - && sl->ctrl_backlink->reader_slot == ctrl->reader_slot) - break; - if (sl) /* There is another session with the reader open. */ - { - if ( IS_LOCKED (ctrl) ) /* If it is locked, release it. */ - ctrl->reader_slot = -1; - else - { - if (do_close) /* Always mark reader unused. */ - ctrl->reader_slot = -1; - else if (apdu_reset (ctrl->reader_slot)) /* Reset only if - not locked */ - { - /* The reset failed. Mark the reader as closed. */ - ctrl->reader_slot = -1; - } - - if (locked_session && ctrl->server_local == locked_session) - { - locked_session = NULL; - log_debug ("implicitly unlocking due to RESET\n"); - } - } - } - else /* No other session has the reader open. */ + if (slot != -1 && send_reset && !IS_LOCKED (ctrl) ) + { + if (apdu_reset (slot)) { - if (do_close || apdu_reset (ctrl->reader_slot)) - { - apdu_close_reader (ctrl->reader_slot); - ctrl->reader_slot = -1; - } - if ( IS_LOCKED (ctrl) ) - { - log_debug ("WARNING: cleaning up stale session lock\n"); - locked_session = NULL; - } + slot_table[slot].reset_failed = 1; } } + ctrl->reader_slot = -1; + + /* If we hold a lock, unlock now. */ + if (locked_session && ctrl->server_local == locked_session) + { + locked_session = NULL; + log_info ("implicitly unlocking due to RESET\n"); + } - /* Reset card removed flag for the current reader. */ + /* Reset card removed flag for the current reader. We need to take + the lock here so that the ticker thread won't concurrently try to + update the file. Note that the update function will set the card + removed flag and we will later reset it - not a particualar nice + way of implementing it but it works. */ + if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL)) + { + log_error ("failed to acquire status_fle_update lock\n"); + return; + } + update_reader_status_file (); update_card_removed (slot, 0); + if (!pth_mutex_release (&status_file_update_lock)) + log_error ("failed to release status_file_update lock\n"); } @@ -197,7 +210,7 @@ reset_notify (assuan_context_t ctx) { ctrl_t ctrl = assuan_get_pointer (ctx); - do_reset (ctrl, 0); + do_reset (ctrl, 1); } @@ -226,18 +239,22 @@ option_handler (assuan_context_t ctx, const char *key, const char *value) static int get_reader_slot (void) { - struct server_local_s *sl; - int slot= -1; + struct slot_status_s *ss; - for (sl=session_list; sl; sl = sl->next_session) - if (sl->ctrl_backlink - && (slot = sl->ctrl_backlink->reader_slot) != -1) - break; + ss = &slot_table[0]; /* One reader for now. */ - if (slot == -1) - slot = apdu_open_reader (opt.reader_port); + /* Initialize the item if needed. */ + if (!ss->valid) + { + ss->slot = -1; + ss->valid = 1; + } + + /* Try to open the reader. */ + if (ss->slot == -1) + ss->slot = apdu_open_reader (opt.reader_port); - return slot; + return ss->slot; } /* If the card has not yet been opened, do it. Note that this @@ -349,7 +366,7 @@ cmd_serialno (assuan_context_t ctx, char *line) { if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); - do_reset (ctrl, 0); + do_reset (ctrl, 1); } if ((rc = open_card (ctrl, *line? line:NULL))) @@ -1305,7 +1322,7 @@ cmd_getinfo (assuan_context_t ctx, char *line) /* RESTART - Restart the current connection; this is a kind of warn reset. It + Restart the current connection; this is a kind of warm reset. It deletes the context used by this connection but does not send a RESET to the card. Thus the card itself won't get reset. @@ -1462,7 +1479,7 @@ scd_command_handler (int fd) } /* Cleanup. */ - do_reset (&ctrl, 1); + do_reset (&ctrl, 0); /* Release the server object. */ if (session_list == ctrl.server_local) @@ -1532,77 +1549,88 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...) } -/* This function is called by the ticker thread to check for changes - of the reader stati. It updates the reader status files and if - requested by the caller also send a signal to the caller. */ -void -scd_update_reader_status_file (void) +/* This is the core of scd_update_reader_status_file but the caller + needs to take care of the locking. */ +static void +update_reader_status_file (void) { - static struct { - int any; - unsigned int status; - unsigned int changed; - } last[10]; - int slot; - int used; + int idx; unsigned int status, changed; /* Note, that we only try to get the status, because it does not make sense to wait here for a operation to complete. If we are busy working with a card, delays in the status file update should be acceptable. */ - for (slot=0; (slot < DIM(last) - &&!apdu_enum_reader (slot, &used)); slot++) - if (used && !apdu_get_status (slot, 0, &status, &changed)) - { - if (!last[slot].any || last[slot].status != status - || last[slot].changed != changed ) - { - char *fname; - char templ[50]; - FILE *fp; - struct server_local_s *sl; - - log_info ("updating status of slot %d to 0x%04X\n", slot, status); - - sprintf (templ, "reader_%d.status", slot); - fname = make_filename (opt.homedir, templ, NULL ); - fp = fopen (fname, "w"); - if (fp) - { - fprintf (fp, "%s\n", - (status & 1)? "USABLE": - (status & 4)? "ACTIVE": - (status & 2)? "PRESENT": "NOCARD"); - fclose (fp); - } - xfree (fname); - - /* Set the card removed flag for all current sessions. We - will set this on any card change because a reset or - SERIALNO request must be done in any case. */ - if (last[slot].any) - update_card_removed (slot, 1); - - last[slot].any = 1; - last[slot].status = status; - last[slot].changed = changed; + for (idx=0; idx < DIM(slot_table); idx++) + { + struct slot_status_s *ss = slot_table + idx; + if (!ss->valid || ss->slot == -1) + continue; /* Not valid or reader not yet open. */ + + if ( apdu_get_status (ss->slot, 0, &status, &changed) ) + continue; /* Get status failed. */ - /* Send a signal to all clients who applied for it. */ - for (sl=session_list; sl; sl = sl->next_session) - if (sl->event_signal && sl->assuan_ctx) - { - pid_t pid = assuan_get_pid (sl->assuan_ctx); - int signo = sl->event_signal; + if (!ss->any || ss->status != status || ss->changed != changed ) + { + char *fname; + char templ[50]; + FILE *fp; + struct server_local_s *sl; - log_info ("client pid is %d, sending signal %d\n", - pid, signo); + log_info ("updating status of slot %d to 0x%04X\n", + ss->slot, status); + + sprintf (templ, "reader_%d.status", ss->slot); + fname = make_filename (opt.homedir, templ, NULL ); + fp = fopen (fname, "w"); + if (fp) + { + fprintf (fp, "%s\n", + (status & 1)? "USABLE": + (status & 4)? "ACTIVE": + (status & 2)? "PRESENT": "NOCARD"); + fclose (fp); + } + xfree (fname); + + /* Set the card removed flag for all current sessions. We + will set this on any card change because a reset or + SERIALNO request must be done in any case. */ + if (ss->any) + update_card_removed (ss->slot, 1); + + ss->any = 1; + ss->status = status; + ss->changed = changed; + + /* Send a signal to all clients who applied for it. */ + for (sl=session_list; sl; sl = sl->next_session) + if (sl->event_signal && sl->assuan_ctx) + { + pid_t pid = assuan_get_pid (sl->assuan_ctx); + int signo = sl->event_signal; + + log_info ("client pid is %d, sending signal %d\n", + pid, signo); #ifndef HAVE_W32_SYSTEM - if (pid != (pid_t)(-1) && pid && signo > 0) - kill (pid, signo); + if (pid != (pid_t)(-1) && pid && signo > 0) + kill (pid, signo); #endif - } - } - } + } + } + } +} + +/* This function is called by the ticker thread to check for changes + of the reader stati. It updates the reader status files and if + requested by the caller also send a signal to the caller. */ +void +scd_update_reader_status_file (void) +{ + if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL)) + return; /* locked - give up. */ + update_reader_status_file (); + if (!pth_mutex_release (&status_file_update_lock)) + log_error ("failed to release status_file_update lock\n"); } -- cgit v1.2.3 From 6b19366e4e4583bc70f43c2ac138b9a7decb7075 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Mar 2006 09:56:47 +0000 Subject: Add Kludge for RegTP sillyness. --- NEWS | 3 ++ TODO | 4 +- sm/ChangeLog | 9 ++++ sm/certchain.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- sm/gpgsm.h | 3 +- sm/qualified.c | 18 +++++--- 6 files changed, 152 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 38dee1ec3..0d520f3ac 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ Noteworthy changes in version 1.9.21 * Cards are not anymore reseted at the end of a connection. + * [gpgsm] Kludge to allow use of Bundesnetzagentur issued + certificates. + Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- diff --git a/TODO b/TODO index 85e08ed16..6033d9150 100644 --- a/TODO +++ b/TODO @@ -18,7 +18,9 @@ might want to have an agent context for each service request * sm/certchain.c ** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent. - +** Try to keep certificate references somewhere + This will help with some of our caching code. We also need to test + that cachining; in particular "regtp_ca_chainlen". * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution diff --git a/sm/ChangeLog b/sm/ChangeLog index 764faa67d..02505962c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,12 @@ +2006-03-21 Werner Koch <wk@g10code.com> + + * certchain.c (get_regtp_ca_info): New. + (allowed_ca): Use it. + +2006-03-20 Werner Koch <wk@g10code.com> + + * qualified.c (gpgsm_is_in_qualified_list): New optional arg COUNTRY. + 2006-02-17 Werner Koch <wk@g10code.com> * call-dirmngr.c (start_dirmngr): Print name of dirmngr to be started. diff --git a/sm/certchain.c b/sm/certchain.c index 0c14fc88f..44d72efd3 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1,5 +1,6 @@ /* certchain.c - certificate chain validation - * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -39,6 +40,10 @@ #include "i18n.h" +static int get_regtp_ca_info (ksba_cert_t cert, int *chainlen); + + + /* If LISTMODE is true, print FORMAT using LISTMODE to FP. If LISTMODE is false, use the string to print an log_info or, if IS_ERROR is true, and log_error. */ @@ -128,6 +133,11 @@ allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp) return err; if (!flag) { + if (get_regtp_ca_info (cert, chainlen)) + { + return 0; /* RegTP issued certificate. */ + } + do_list (1, listmode, fp,_("issuer certificate is not marked as a CA")); return gpg_error (GPG_ERR_BAD_CA_CERT); } @@ -267,7 +277,7 @@ check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist) } -/* Helper fucntion for find_up. This resets the key handle and search +/* Helper function for find_up. This resets the key handle and search for an issuer ISSUER with a subjectKeyIdentifier of KEYID. Returns 0 obn success or -1 when not found. */ static int @@ -796,7 +806,7 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, { /* Need to consult the list of root certificates for qualified signatures. */ - err = gpgsm_is_in_qualified_list (ctrl, subject_cert); + err = gpgsm_is_in_qualified_list (ctrl, subject_cert, NULL); if (!err) is_qualified = 1; else if ( gpg_err_code (err) == GPG_ERR_NOT_FOUND) @@ -807,8 +817,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime, gpg_strerror (err)); if ( is_qualified != -1 ) { - /* Cache the result but don't care toomuch about - an error. */ + /* Cache the result but don't care too much + about an error. */ buf[0] = !!is_qualified; err = ksba_cert_set_user_data (subject_cert, "is_qualified", buf, 1); @@ -1181,3 +1191,110 @@ gpgsm_basic_cert_check (ksba_cert_t cert) return rc; } + + +/* Check whether the certificate CERT has been issued by the German + authority for qualified signature. They do not set the + basicConstraints and thus we need this workaround. It works by + looking up the root certificate and checking whether that one is + listed as a qualified certificate for Germany. + + We also try to cache this data but as long as don't keep a + reference to the certificate this won't be used. + + Returns: True if CERT is a RegTP issued CA cert (i.e. the root + certificate itself or one of the CAs). In that case CHAINLEN will + receive the length of the chain which is either 0 or 1. +*/ +static int +get_regtp_ca_info (ksba_cert_t cert, int *chainlen) +{ + gpg_error_t err; + ksba_cert_t next; + int rc = 0; + int i, depth; + char country[3]; + ksba_cert_t array[4]; + char buf[2]; + size_t buflen; + int dummy_chainlen; + + if (!chainlen) + chainlen = &dummy_chainlen; + + *chainlen = 0; + err = ksba_cert_get_user_data (cert, "regtp_ca_chainlen", + &buf, sizeof (buf), &buflen); + if (!err) + { + /* Got info. */ + if (buflen < 2 || !*buf) + return 0; /* Nothing found. */ + *chainlen = buf[1]; + return 1; /* This is a regtp CA. */ + } + else if (gpg_err_code (err) != GPG_ERR_NOT_FOUND) + { + log_error ("ksba_cert_get_user_data(%s) failed: %s\n", + "regtp_ca_chainlen", gpg_strerror (err)); + return 0; /* Nothing found. */ + } + + /* Need to gather the info. This requires to walk up the chain + until we have found the root. Because we are only interested in + German Bundesnetzagentur (former RegTP) derived certificates 3 + levels are enough. (The German signature law demands a 3 tier + hierachy; thus there is only one CA between the EE and the Root + CA.) */ + memset (&array, 0, sizeof array); + + depth = 0; + ksba_cert_ref (cert); + array[depth++] = cert; + ksba_cert_ref (cert); + while (depth < DIM(array) && !(rc=gpgsm_walk_cert_chain (cert, &next))) + { + ksba_cert_release (cert); + ksba_cert_ref (next); + array[depth++] = next; + cert = next; + } + ksba_cert_release (cert); + if (rc != -1 || !depth || depth == DIM(array) ) + { + /* We did not reached the root. */ + goto leave; + } + + /* If this is a German signature law issued certificate, we store + additional additional information. */ + if (!gpgsm_is_in_qualified_list (NULL, array[depth-1], country) + && !strcmp (country, "de")) + { + /* Setting the pathlen for the root CA and the CA flag for the + next one is all what we need to do. */ + err = ksba_cert_set_user_data (array[depth-1], "regtp_ca_chainlen", + "\x01\x01", 2); + if (!err && depth > 1) + err = ksba_cert_set_user_data (array[depth-2], "regtp_ca_chainlen", + "\x01\x00", 2); + if (err) + log_error ("ksba_set_user_data(%s) failed: %s\n", + "regtp_ca_chainlen", gpg_strerror (err)); + for (i=0; i < depth; i++) + ksba_cert_release (array[i]); + *chainlen = (depth>1? 0:1); + return 1; + } + + leave: + /* Nothing special with this certificate. Mark the target + certificate anyway to avoid duplicate lookups. */ + err = ksba_cert_set_user_data (cert, "regtp_ca_chainlen", "", 1); + if (err) + log_error ("ksba_set_user_data(%s) failed: %s\n", + "regtp_ca_chainlen", gpg_strerror (err)); + for (i=0; i < depth; i++) + ksba_cert_release (array[i]); + return 0; +} diff --git a/sm/gpgsm.h b/sm/gpgsm.h index dc863f682..438252050 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -296,7 +296,8 @@ int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp); int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp); /*-- qualified.c --*/ -gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert); +gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert, + char *country); gpg_error_t gpgsm_qualified_consent (ctrl_t ctrl, ksba_cert_t cert); gpg_error_t gpgsm_not_qualified_warning (ctrl_t ctrl, ksba_cert_t cert); diff --git a/sm/qualified.c b/sm/qualified.c index a52269734..07abaadc4 100644 --- a/sm/qualified.c +++ b/sm/qualified.c @@ -145,24 +145,29 @@ read_list (char *key, char *country, int *lnr) per user because it is not a decision of the user. Returns: 0 if the certificate is included. GPG_ERR_NOT_FOUND if it - is not in the liost or any other error (e.g. if no list of - qualified signatures is available. */ + is not in the list or any other error (e.g. if no list of + qualified signatures is available. If COUNTRY has not been passed + as NULL a string witha maximum length of 2 will be copied into it; + thus the caller needs to provide a buffer of length 3. */ gpg_error_t -gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert) +gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert, char *country) { gpg_error_t err; char *fpr; char key[41]; - char country[2]; + char mycountry[3]; int lnr = 0; + if (country) + *country = 0; + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); if (!fpr) return gpg_error (GPG_ERR_GENERAL); if (listfp) rewind (listfp); - while (!(err = read_list (key, country, &lnr))) + while (!(err = read_list (key, mycountry, &lnr))) { if (!strcmp (key, fpr)) break; @@ -170,6 +175,9 @@ gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert) if (gpg_err_code (err) == GPG_ERR_EOF) err = gpg_error (GPG_ERR_NOT_FOUND); + if (!err && country) + strcpy (country, mycountry); + xfree (fpr); return err; } -- cgit v1.2.3 From 79f749fec99173a2711c48b34fc514fba29032d8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 21 Mar 2006 12:48:51 +0000 Subject: Allo RMD160 signatures --- NEWS | 2 ++ TODO | 1 + doc/scdaemon.texi | 9 ++++++++- scd/ChangeLog | 4 ++++ scd/command.c | 28 +++++++++++++++++++++++++--- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 0d520f3ac..a003b3f90 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ Noteworthy changes in version 1.9.21 * [gpgsm] Kludge to allow use of Bundesnetzagentur issued certificates. + * [scdaemon] Added --hash=xxx option to the PKSIGN command. + Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- diff --git a/TODO b/TODO index 6033d9150..3e4d21dc6 100644 --- a/TODO +++ b/TODO @@ -3,6 +3,7 @@ * src/base64 ** Make parsing more robust Currently we don't cope with overlong lines in the best way. +** Check that we really release the ksba reader/writer objects. * sm/call-agent.c ** The protocol uses an incomplete S-expression diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 8bc5810cb..24a22355e 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -444,7 +444,14 @@ hex notation. The actual signing is done using the command @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}. +may have been retrieved using the command @code{LEARN}. If another +hash algorithm than SHA-1 is used, that algorithm may be given like: + +@example + PKSIGN --hash=@var{algoname} @var{keyid} +@end example + +With @var{algoname} are one of @code{sha1}, @code{rmd160} or @code{md5}. @node Scdaemon PKDECRYPT diff --git a/scd/ChangeLog b/scd/ChangeLog index d539d210e..27c362d10 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2006-03-21 Werner Koch <wk@g10code.com> + + * command.c (cmd_pksign): Add --hash option. + 2006-03-01 Werner Koch <wk@g10code.com> * command.c (status_file_update_lock): New. diff --git a/scd/command.c b/scd/command.c index 805164d0f..70a426959 100644 --- a/scd/command.c +++ b/scd/command.c @@ -708,7 +708,9 @@ pin_cb (void *opaque, const char *info, char **retstr) } -/* PKSIGN <hexified_id> +/* PKSIGN [--hash=[rmd160|sha1|md5]] <hexified_id> + + The --hash option is optional; the default is SHA1. */ static int @@ -719,6 +721,26 @@ cmd_pksign (assuan_context_t ctx, char *line) unsigned char *outdata; size_t outdatalen; char *keyidstr; + int hash_algo; + + if (has_option (line, "--hash=rmd160")) + hash_algo = GCRY_MD_RMD160; + else if (has_option (line, "--hash=sha1")) + hash_algo = GCRY_MD_SHA1; + else if (has_option (line, "--hash=md5")) + hash_algo = GCRY_MD_MD5; + else if (!strstr (line, "--")) + hash_algo = GCRY_MD_SHA1; + else + return set_error (Parameter_Error, "invalid hash algorithm"); + /* Skip over options. */ + while ( *line == '-' && line[1] == '-' ) + { + while (*line && !spacep (line)) + line++; + while (spacep (line)) + line++; + } if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); @@ -734,7 +756,7 @@ cmd_pksign (assuan_context_t ctx, char *line) return ASSUAN_Out_Of_Core; rc = app_sign (ctrl->app_ctx, - keyidstr, GCRY_MD_SHA1, + keyidstr, hash_algo, pin_cb, ctx, ctrl->in_data.value, ctrl->in_data.valuelen, &outdata, &outdatalen); @@ -777,7 +799,7 @@ cmd_pkauth (assuan_context_t ctx, char *line) if (!ctrl->app_ctx) return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); - /* We have to use a copy of the key ID because the function may use + /* We have to use a copy of the key ID because the function may use the pin_cb which in turn uses the assuan line buffer and thus overwriting the original line with the keyid */ keyidstr = xtrystrdup (line); -- cgit v1.2.3 From 4a31738bd1a302c76333a32b72ffc5ab78c71103 Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sat, 1 Apr 2006 11:04:14 +0000 Subject: 2006-04-01 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_identity_register): Make KEY_GRIP_RAW be 20 instead of 21 bytes long; do not fill KEY_GRIP_RAW[20] with NUL byte - KEY_GRIP_RAW is a raw binary string anyway. --- agent/ChangeLog | 6 ++++++ agent/command-ssh.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index fbb1a37e0..ed4c8a4cb 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,9 @@ +2006-04-01 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_identity_register): Make KEY_GRIP_RAW be 20 + instead of 21 bytes long; do not fill KEY_GRIP_RAW[20] with NUL + byte - KEY_GRIP_RAW is a raw binary string anyway. + 2006-02-09 Werner Koch <wk@g10code.com> * call-scd.c (struct scd_local_s): New field next_local. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index b8f0d20b0..be2a8385d 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2321,7 +2321,7 @@ static gpg_error_t ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) { gpg_error_t err; - unsigned char key_grip_raw[21]; + unsigned char key_grip_raw[20]; char key_grip[41]; unsigned char *buffer = NULL; unsigned int buffer_n; @@ -2334,8 +2334,6 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl) if (err) goto out; - key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME: Why?? */ - /* Check whether the key is already in our key storage. Don't do anything then. */ if ( !agent_key_available (key_grip_raw) ) -- cgit v1.2.3 From f3c5360ca1aa5ca71648b0df6a8339b12e2321ee Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 5 Apr 2006 17:00:13 +0000 Subject: Renamed --- g10/g10.c | 3364 ------------------------------------------------------------- g10/gpg.c | 3364 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3364 insertions(+), 3364 deletions(-) delete mode 100644 g10/g10.c create mode 100644 g10/gpg.c diff --git a/g10/g10.c b/g10/g10.c deleted file mode 100644 index 234d13f41..000000000 --- a/g10/g10.c +++ /dev/null @@ -1,3364 +0,0 @@ -/* g10.c - The GnuPG utility (main for gpg) - * Copyright (C) 1998,1999,2000,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 - */ - -#include <config.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h> -#include <assert.h> -#ifdef HAVE_DOSISH_SYSTEM -#include <fcntl.h> /* for setmode() */ -#endif -#ifdef HAVE_STAT -#include <sys/stat.h> /* for stat() */ -#endif -#include <assuan.h> - -#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" -#include "keyserver-internal.h" -#include "exec.h" - -enum cmd_and_opt_values { aNull = 0, - oArmor = 'a', - aDetachedSign = 'b', - aSym = 'c', - aDecrypt = 'd', - aEncr = 'e', - oInteractive = 'i', - aListKeys = 'k', - aListSecretKeys = 'K', - oDryRun = 'n', - oOutput = 'o', - oQuiet = 'q', - oRecipient = 'r', - oHiddenRecipient = 'R', - aSign = 's', - oTextmodeShort= 't', - oUser = 'u', - oVerbose = 'v', - oCompress = 'z', - oSetNotation = 'N', - oBatch = 500, - aGPGConfList, - oSigNotation, - oCertNotation, - oShowNotation, - oNoShowNotation, - aEncrFiles, - aDecryptFiles, - aClearsign, - aStore, - aKeygen, - aSignEncr, - aSignSym, - aSignKey, - aLSignKey, - aNRSignKey, - aNRLSignKey, - aListPackets, - aEditKey, - aDeleteKeys, - aDeleteSecretKeys, - aDeleteSecretAndPublicKeys, - aImport, - aFastImport, - aVerify, - aVerifyFiles, - aListSigs, - aSendKeys, - aRecvKeys, - aSearchKeys, - aExport, - aExportAll, - aExportSecret, - aExportSecretSub, - aCheckKeys, - aGenRevoke, - aDesigRevoke, - aPrimegen, - aPrintMD, - aPrintMDs, - aCheckTrustDB, - aUpdateTrustDB, - aFixTrustDB, - aListTrustDB, - aListTrustPath, - aExportOwnerTrust, - aListOwnerTrust, - aImportOwnerTrust, - aDeArmor, - aEnArmor, - aGenRandom, - aPipeMode, - aRebuildKeydbCaches, - aRefreshKeys, - aCardStatus, - aCardEdit, - aChangePIN, - - oTextmode, - oNoTextmode, - oExpert, - oNoExpert, - oAskSigExpire, - oNoAskSigExpire, - oAskCertExpire, - oNoAskCertExpire, - oFingerprint, - oWithFingerprint, - oAnswerYes, - oAnswerNo, - oDefCertCheckLevel, - oKeyring, - oPrimaryKeyring, - oSecretKeyring, - oShowKeyring, - oDefaultKey, - oDefRecipient, - oDefRecipientSelf, - oNoDefRecipient, - oOptions, - oDebug, - oDebugLevel, - oDebugAll, - oStatusFD, -#ifdef __riscos__ - oStatusFile, -#endif /* __riscos__ */ - oAttributeFD, -#ifdef __riscos__ - oAttributeFile, -#endif /* __riscos__ */ - oSKComments, - oNoSKComments, - oEmitVersion, - oNoEmitVersion, - oCompletesNeeded, - oMarginalsNeeded, - oMaxCertDepth, - oLoadExtension, - oGnuPG, - oRFC1991, - oRFC2440, - oOpenPGP, - oPGP2, - oPGP6, - oPGP7, - oPGP8, - oCipherAlgo, - oDigestAlgo, - oCertDigestAlgo, - oCompressAlgo, - oPasswdFD, -#ifdef __riscos__ - oPasswdFile, -#endif /* __riscos__ */ - oCommandFD, -#ifdef __riscos__ - oCommandFile, -#endif /* __riscos__ */ - oQuickRandom, - oNoVerbose, - oTrustDBName, - oNoSecmemWarn, - oNoPermissionWarn, - oNoMDCWarn, - oNoArmor, - oNoDefKeyring, - oNoGreeting, - oNoTTY, - oNoOptions, - oNoBatch, - oHomedir, - oWithColons, - oWithKeyData, - oSkipVerify, - oCompressKeys, - oCompressSigs, - oAlwaysTrust, - oTrustModel, - oForceOwnertrust, - oEmuChecksumBug, - oSetFilename, - oForYourEyesOnly, - oNoForYourEyesOnly, - oSetPolicyURL, - oSigPolicyURL, - oCertPolicyURL, - oShowPolicyURL, - oNoShowPolicyURL, - oSigKeyserverURL, - oUseEmbeddedFilename, - oComment, - oDefaultComment, - oNoComments, - oThrowKeyid, - oNoThrowKeyid, - oShowPhotos, - oNoShowPhotos, - oPhotoViewer, - oForceV3Sigs, - oNoForceV3Sigs, - oForceV4Certs, - oNoForceV4Certs, - oForceMDC, - oNoForceMDC, - oDisableMDC, - oNoDisableMDC, - oS2KMode, - oS2KDigest, - oS2KCipher, - oSimpleSKChecksum, - oCharset, - oNotDashEscaped, - oEscapeFrom, - oNoEscapeFrom, - oLockOnce, - oLockMultiple, - oLockNever, - oKeyServer, - oKeyServerOptions, - oImportOptions, - oExportOptions, - oListOptions, - oVerifyOptions, - oTempDir, - oExecPath, - oEncryptTo, - oHiddenEncryptTo, - oNoEncryptTo, - oLogFile, - oLoggerFD, -#ifdef __riscos__ - oLoggerFile, -#endif /* __riscos__ */ - oUtf8Strings, - oNoUtf8Strings, - oDisableCipherAlgo, - oDisablePubkeyAlgo, - oAllowNonSelfsignedUID, - oNoAllowNonSelfsignedUID, - oAllowFreeformUID, - oNoAllowFreeformUID, - oAllowSecretKeyImport, - oEnableSpecialFilenames, - oNoLiteral, - oSetFilesize, - oHonorHttpProxy, - oFastListMode, - oListOnly, - oIgnoreTimeConflict, - oIgnoreValidFrom, - oIgnoreCrcError, - oIgnoreMDCError, - oShowSessionKey, - oOverrideSessionKey, - oNoRandomSeedFile, - oAutoKeyRetrieve, - oNoAutoKeyRetrieve, - oUseAgent, - oNoUseAgent, - oGpgAgentInfo, - oMergeOnly, - oTryAllSecrets, - oTrustedKey, - oNoExpensiveTrustChecks, - oFixedListMode, - oNoSigCache, - oNoSigCreateCheck, - oAutoCheckTrustDB, - oNoAutoCheckTrustDB, - oPreservePermissions, - oDefaultPreferenceList, - oPersonalCipherPreferences, - oPersonalDigestPreferences, - oPersonalCompressPreferences, - oEmuMDEncodeBug, - oAgentProgram, - oDisplay, - oTTYname, - oTTYtype, - oLCctype, - oLCmessages, - oGroup, - oStrict, - oNoStrict, - oMangleDosFilenames, - oNoMangleDosFilenames, - oEnableProgressFilter, - oMultifile, -aTest }; - - -static ARGPARSE_OPTS opts[] = { - - { 300, NULL, 0, N_("@Commands:\n ") }, - - { aSign, "sign", 256, N_("|[file]|make a signature")}, - { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, - { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, - { aEncr, "encrypt", 256, N_("encrypt data")}, - { aEncrFiles, "encrypt-files", 256, "@"}, - { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, - { aStore, "store", 256, "@"}, - { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, - { aDecryptFiles, "decrypt-files", 256, "@"}, - { aVerify, "verify" , 256, N_("verify a signature")}, - { aVerifyFiles, "verify-files" , 256, "@" }, - { aListKeys, "list-keys", 256, N_("list keys")}, - { aListKeys, "list-public-keys", 256, "@" }, - { aListSigs, "list-sigs", 256, N_("list keys and signatures")}, - { aCheckKeys, "check-sigs",256, N_("list and check key signatures")}, - { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, - { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, - { aKeygen, "gen-key", 256, N_("generate a new key pair")}, - { aDeleteKeys,"delete-keys",256,N_("remove keys from the public keyring")}, - { aDeleteSecretKeys, "delete-secret-keys",256, - N_("remove keys from the secret keyring")}, - { aSignKey, "sign-key" ,256, N_("sign a key")}, - { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, - { aNRSignKey, "nrsign-key" ,256, "@"}, - { aNRLSignKey, "nrlsign-key" ,256, "@"}, - { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, - { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, - { aDesigRevoke, "desig-revoke",256, "@" }, - { aExport, "export" , 256, N_("export keys") }, - { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, - { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, - { aSearchKeys, "search-keys" , 256, - N_("search for keys on a key server") }, - { aRefreshKeys, "refresh-keys", 256, - N_("update all keys from a keyserver")}, - { aExportAll, "export-all" , 256, "@" }, - { aExportSecret, "export-secret-keys" , 256, "@" }, - { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, - { aImport, "import", 256 , N_("import/merge keys")}, - { aFastImport, "fast-import", 256 , "@"}, - { aCardStatus, "card-status", 256, N_("print the card status")}, - { aCardEdit, "card-edit", 256, N_("change data on a card")}, - { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, - - { aListPackets, "list-packets",256, "@"}, - { aExportOwnerTrust, "export-ownertrust", 256, "@"}, - { aImportOwnerTrust, "import-ownertrust", 256, "@"}, - { aUpdateTrustDB, "update-trustdb",0 , N_("update the trust database")}, - { aCheckTrustDB, "check-trustdb",0 , "@"}, - { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, - { aDeArmor, "dearmor", 256, "@" }, - { aDeArmor, "dearmour", 256, "@" }, - { aEnArmor, "enarmor", 256, "@" }, - { aEnArmor, "enarmour", 256, "@" }, - { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, - { aPrimegen, "gen-prime" , 256, "@" }, - { aGenRandom, "gen-random" , 256, "@" }, - { aGPGConfList, "gpgconf-list", 256, "@" }, - - { 301, NULL, 0, N_("@\nOptions:\n ") }, - - { oArmor, "armor", 0, N_("create ascii armored output")}, - { oArmor, "armour", 0, "@" }, - { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, - { oHiddenRecipient, "hidden-recipient", 2, "@" }, - { oRecipient, "remote-user", 2, "@"}, /* old option name */ - { oDefRecipient, "default-recipient" ,2, "@" }, - { oDefRecipientSelf, "default-recipient-self" ,0, "@" }, - { oNoDefRecipient, "no-default-recipient", 0, "@" }, - { oTempDir, "temp-directory", 2, "@" }, - { oExecPath, "exec-path", 2, "@" }, - { oEncryptTo, "encrypt-to", 2, "@" }, - { oHiddenEncryptTo, "hidden-encrypt-to", 2, "@" }, - { oNoEncryptTo, "no-encrypt-to", 0, "@" }, - { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, - { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, - { oTextmodeShort, NULL, 0, "@"}, - { oTextmode, "textmode", 0, N_("use canonical text mode")}, - { oNoTextmode, "no-textmode", 0, "@"}, - { oExpert, "expert", 0, "@"}, - { oNoExpert, "no-expert", 0, "@"}, - { oAskSigExpire, "ask-sig-expire", 0, "@"}, - { oNoAskSigExpire, "no-ask-sig-expire", 0, "@"}, - { oAskCertExpire, "ask-cert-expire", 0, "@"}, - { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, - { oOutput, "output", 2, N_("use as output file")}, - { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, "@" }, - { oNoTTY, "no-tty", 0, "@" }, - { oLogFile, "log-file" ,2, "@" }, - { oForceV3Sigs, "force-v3-sigs", 0, "@" }, - { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@" }, - { oForceV4Certs, "force-v4-certs", 0, "@" }, - { oNoForceV4Certs, "no-force-v4-certs", 0, "@" }, - { oForceMDC, "force-mdc", 0, "@" }, - { oNoForceMDC, "no-force-mdc", 0, "@" }, - { oDisableMDC, "disable-mdc", 0, "@" }, - { oNoDisableMDC, "no-disable-mdc", 0, "@" }, - { oDryRun, "dry-run", 0, N_("do not make any changes") }, - { oInteractive, "interactive", 0, N_("prompt before overwriting") }, - { oUseAgent, "use-agent",0, "@"}, - { oNoUseAgent, "no-use-agent",0, "@"}, - { oGpgAgentInfo, "gpg-agent-info",2, "@"}, - { oBatch, "batch", 0, "@"}, - { oAnswerYes, "yes", 0, "@"}, - { oAnswerNo, "no", 0, "@"}, - { oKeyring, "keyring" , 2, "@"}, - { oPrimaryKeyring, "primary-keyring",2, "@" }, - { oSecretKeyring, "secret-keyring" ,2, "@"}, - { oShowKeyring, "show-keyring", 0, "@"}, - { oDefaultKey, "default-key" , 2, "@"}, - { oKeyServer, "keyserver", 2, "@"}, - { oKeyServerOptions, "keyserver-options",2,"@"}, - { oImportOptions, "import-options",2,"@"}, - { oExportOptions, "export-options",2,"@"}, - { oListOptions, "list-options",2,"@"}, - { oVerifyOptions, "verify-options",2,"@"}, - { oCharset, "charset" , 2, "@" }, - { oOptions, "options" , 2, "@"}, - - { oDebug, "debug" ,4|16, "@"}, - { oDebugLevel, "debug-level" ,2, "@"}, - { oDebugAll, "debug-all" ,0, "@"}, - { oStatusFD, "status-fd" ,1, "@" }, -#ifdef __riscos__ - { oStatusFile, "status-file" ,2, "@" }, -#endif /* __riscos__ */ - { oAttributeFD, "attribute-fd" ,1, "@" }, -#ifdef __riscos__ - { oAttributeFile, "attribute-file" ,2, "@" }, -#endif /* __riscos__ */ - { oNoSKComments, "no-sk-comments", 0, "@"}, - { oSKComments, "sk-comments", 0, "@"}, - { oCompletesNeeded, "completes-needed", 1, "@"}, - { oMarginalsNeeded, "marginals-needed", 1, "@"}, - { oMaxCertDepth, "max-cert-depth", 1, "@" }, - { oTrustedKey, "trusted-key", 2, "@"}, - { oLoadExtension, "load-extension" ,2, "@"}, - { oGnuPG, "gnupg", 0, "@"}, - { oGnuPG, "no-pgp2", 0, "@"}, - { oGnuPG, "no-pgp6", 0, "@"}, - { oGnuPG, "no-pgp7", 0, "@"}, - { oGnuPG, "no-pgp8", 0, "@"}, - { oRFC1991, "rfc1991", 0, "@"}, - { oRFC2440, "rfc2440", 0, "@"}, - { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, - { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, - { oPGP6, "pgp6", 0, "@"}, - { oPGP7, "pgp7", 0, "@"}, - { oPGP8, "pgp8", 0, "@"}, - { oS2KMode, "s2k-mode", 1, "@"}, - { oS2KDigest, "s2k-digest-algo",2, "@"}, - { oS2KCipher, "s2k-cipher-algo",2, "@"}, - { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, - { oCipherAlgo, "cipher-algo", 2 , "@"}, - { oDigestAlgo, "digest-algo", 2 , "@"}, - { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, - { oCompressAlgo,"compress-algo",2, "@"}, - { oThrowKeyid, "throw-keyid", 0, "@"}, - { oNoThrowKeyid, "no-throw-keyid", 0, "@" }, - { oShowPhotos, "show-photos", 0, "@" }, - { oNoShowPhotos, "no-show-photos", 0, "@" }, - { oPhotoViewer, "photo-viewer", 2, "@" }, - { oSetNotation, "set-notation", 2, "@" }, - { oSetNotation, "notation-data", 2, "@" }, /* Alias */ - { oSigNotation, "sig-notation", 2, "@" }, - { oCertNotation, "cert-notation", 2, "@" }, - - { 302, NULL, 0, N_( - "@\n(See the man page for a complete listing of all commands and options)\n" - )}, - - { 303, NULL, 0, N_("@\nExamples:\n\n" - " -se -r Bob [file] sign and encrypt for user Bob\n" - " --clearsign [file] make a clear text signature\n" - " --detach-sign [file] make a detached signature\n" - " --list-keys [names] show keys\n" - " --fingerprint [names] show fingerprints\n" ) }, - - /* hidden options */ - { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */ - { oCompressAlgo, "compression-algo", 1, "@"}, /* alias */ - { aPrintMDs, "print-mds" , 256, "@"}, /* old */ - { aListTrustDB, "list-trustdb",0 , "@"}, - /* Not yet used */ - /* { aListTrustPath, "list-trust-path",0, "@"}, */ - { aPipeMode, "pipemode", 0, "@" }, - { oPasswdFD, "passphrase-fd",1, "@" }, -#ifdef __riscos__ - { oPasswdFile, "passphrase-file",2, "@" }, -#endif /* __riscos__ */ - { oCommandFD, "command-fd",1, "@" }, -#ifdef __riscos__ - { oCommandFile, "command-file",2, "@" }, -#endif /* __riscos__ */ - { oQuickRandom, "quick-random", 0, "@"}, - { oNoVerbose, "no-verbose", 0, "@"}, - { oTrustDBName, "trustdb-name", 2, "@" }, - { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */ - { oNoPermissionWarn, "no-permission-warning", 0, "@" }, - { oNoMDCWarn, "no-mdc-warning", 0, "@" }, - { oNoArmor, "no-armor", 0, "@"}, - { oNoArmor, "no-armour", 0, "@"}, - { oNoDefKeyring, "no-default-keyring", 0, "@" }, - { oNoGreeting, "no-greeting", 0, "@" }, - { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */ - { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ - { oNoBatch, "no-batch", 0, "@" }, - { oWithColons, "with-colons", 0, "@"}, - { oWithKeyData,"with-key-data", 0, "@"}, - { aListKeys, "list-key", 0, "@" }, /* alias */ - { aListSigs, "list-sig", 0, "@" }, /* alias */ - { aCheckKeys, "check-sig",0, "@" }, /* alias */ - { oSkipVerify, "skip-verify",0, "@" }, - { oCompressKeys, "compress-keys",0, "@"}, - { oCompressSigs, "compress-sigs",0, "@"}, - { oDefCertCheckLevel, "default-cert-check-level", 1, "@"}, - { oAlwaysTrust, "always-trust", 0, "@"}, - { oTrustModel, "trust-model", 2, "@"}, - { oForceOwnertrust, "force-ownertrust", 2, "@"}, - { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"}, - { oSetFilename, "set-filename", 2, "@" }, - { oForYourEyesOnly, "for-your-eyes-only", 0, "@" }, - { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" }, - { oSetPolicyURL, "set-policy-url", 2, "@" }, - { oSigPolicyURL, "sig-policy-url", 2, "@" }, - { oCertPolicyURL, "cert-policy-url", 2, "@" }, - { oShowPolicyURL, "show-policy-url", 0, "@" }, - { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, - { oShowNotation, "show-notation", 0, "@" }, - { oNoShowNotation, "no-show-notation", 0, "@" }, - { oSigKeyserverURL, "sig-keyserver-url", 2, "@" }, - { oComment, "comment", 2, "@" }, - { oDefaultComment, "default-comment", 0, "@" }, - { oNoComments, "no-comments", 0, "@" }, - { oEmitVersion, "emit-version", 0, "@"}, - { oNoEmitVersion, "no-emit-version", 0, "@"}, - { oNoEmitVersion, "no-version", 0, "@"}, /* alias */ - { oNotDashEscaped, "not-dash-escaped", 0, "@" }, - { oEscapeFrom, "escape-from-lines", 0, "@" }, - { oNoEscapeFrom, "no-escape-from-lines", 0, "@" }, - { oLockOnce, "lock-once", 0, "@" }, - { oLockMultiple, "lock-multiple", 0, "@" }, - { oLockNever, "lock-never", 0, "@" }, - { oLoggerFD, "logger-fd",1, "@" }, -#ifdef __riscos__ - { oLoggerFile, "logger-file",2, "@" }, -#endif /* __riscos__ */ - { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" }, - { oUtf8Strings, "utf8-strings", 0, "@" }, - { oNoUtf8Strings, "no-utf8-strings", 0, "@" }, - { oWithFingerprint, "with-fingerprint", 0, "@" }, - { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, - { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, - { oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" }, - { oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", 0, "@" }, - { oAllowFreeformUID, "allow-freeform-uid", 0, "@" }, - { oNoAllowFreeformUID, "no-allow-freeform-uid", 0, "@" }, - { oNoLiteral, "no-literal", 0, "@" }, - { oSetFilesize, "set-filesize", 20, "@" }, - { oHonorHttpProxy,"honor-http-proxy", 0, "@" }, - { oFastListMode,"fast-list-mode", 0, "@" }, - { oFixedListMode,"fixed-list-mode", 0, "@" }, - { oListOnly, "list-only", 0, "@"}, - { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, - { oIgnoreValidFrom, "ignore-valid-from", 0, "@" }, - { oIgnoreCrcError, "ignore-crc-error", 0,"@" }, - { oIgnoreMDCError, "ignore-mdc-error", 0,"@" }, - { oShowSessionKey, "show-session-key", 0, "@" }, - { oOverrideSessionKey, "override-session-key", 2, "@" }, - { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, - { oAutoKeyRetrieve, "auto-key-retrieve", 0, "@" }, - { oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" }, - { oNoSigCache, "no-sig-cache", 0, "@" }, - { oNoSigCreateCheck, "no-sig-create-check", 0, "@" }, - { oAutoCheckTrustDB, "auto-check-trustdb", 0, "@"}, - { oNoAutoCheckTrustDB, "no-auto-check-trustdb", 0, "@"}, - { oMergeOnly, "merge-only", 0, "@" }, - { oAllowSecretKeyImport, "allow-secret-key-import", 0, "@" }, - { oTryAllSecrets, "try-all-secrets", 0, "@" }, - { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" }, - { oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" }, - { aDeleteSecretAndPublicKeys, "delete-secret-and-public-keys",256, "@" }, - { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"}, - { oPreservePermissions, "preserve-permissions", 0, "@"}, - { oDefaultPreferenceList, "default-preference-list", 2, "@"}, - { oPersonalCipherPreferences, "personal-cipher-preferences", 2, "@"}, - { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, - { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, - { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, - { oAgentProgram, "agent-program", 2 , "@" }, - { oDisplay, "display", 2, "@" }, - { oTTYname, "ttyname", 2, "@" }, - { oTTYtype, "ttytype", 2, "@" }, - { oLCctype, "lc-ctype", 2, "@" }, - { oLCmessages, "lc-messages", 2, "@" }, - { oGroup, "group", 2, "@" }, - { oStrict, "strict", 0, "@" }, - { oNoStrict, "no-strict", 0, "@" }, - { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" }, - { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" }, - { oEnableProgressFilter, "enable-progress-filter", 0, "@" }, - { oMultifile, "multifile", 0, "@" }, -{0} }; - - - -int g10_errors_seen = 0; - -static int utf8_strings = 0; -static int maybe_setuid = 1; - -static char *build_list( const char *text, char letter, - const char *(*mapf)(int), int (*chkf)(int) ); -static void set_cmd( enum cmd_and_opt_values *ret_cmd, - enum cmd_and_opt_values new_cmd ); -static void print_mds( const char *fname, int algo ); -static void add_notation_data( const char *string, int which ); -static void add_policy_url( const char *string, int which ); -static void add_keyserver_url( const char *string, int which ); -static void emergency_cleanup (void); - -#ifdef __riscos__ -RISCOS_GLOBAL_STATICS("GnuPG Heap") -#endif /* __riscos__ */ - -static int -pk_test_algo (int algo) -{ - return openpgp_pk_test_algo (algo, 0); -} - - -static const char * -my_strusage( int level ) -{ - static char *digests, *pubkeys, *ciphers, *zips; - const char *p; - switch( level ) { - case 11: p = "gpg (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: gpg [options] [files] (-h for help)"); - break; - case 41: p = - _("Syntax: gpg [options] [files]\n" - "sign, check, encrypt or decrypt\n" - "default operation depends on the input data\n"); - break; - - case 31: p = "\nHome: "; break; -#ifndef __riscos__ - case 32: p = opt.homedir; break; -#else /* __riscos__ */ - case 32: p = make_filename(opt.homedir, NULL); break; -#endif /* __riscos__ */ - case 33: p = _("\nSupported algorithms:\n"); break; - case 34: - if( !pubkeys ) - pubkeys = build_list(_("Pubkey: "), 0, gcry_pk_algo_name, - pk_test_algo ); - p = pubkeys; - break; - case 35: - if( !ciphers ) - ciphers = build_list(_("Cipher: "), 'S', gcry_cipher_algo_name, - openpgp_cipher_test_algo ); - p = ciphers; - break; - case 36: - if( !digests ) - digests = build_list(_("Hash: "), 'H', gcry_md_algo_name, - openpgp_md_test_algo ); - p = digests; - break; - case 37: - if( !zips ) - zips = build_list(_("Compression: "),'Z',compress_algo_to_string, - check_compress_algo); - p = zips; - break; - - default: p = NULL; - } - return p; -} - - -static char * -build_list( const char *text, char letter, - const char * (*mapf)(int), int (*chkf)(int) ) -{ - int i; - const char *s; - size_t n=strlen(text)+2; - char *list, *p, *line=NULL; - - if( maybe_setuid ) - gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* drop setuid */ - - for(i=0; i <= 110; i++ ) - if( !chkf(i) && (s=mapf(i)) ) - n += strlen(s) + 7 + 2; - list = xmalloc ( 21 + n ); *list = 0; - for(p=NULL, i=0; i <= 110; i++ ) { - if( !chkf(i) && (s=mapf(i)) ) { - if( !p ) { - p = stpcpy( list, text ); - line=p; - } - else - p = stpcpy( p, ", "); - - if(strlen(line)>60) { - int spaces=strlen(text); - - list = xrealloc(list,n+spaces+1); - /* realloc could move the block, so find the end again */ - p=list; - while(*p) - p++; - - p=stpcpy(p, "\n"); - line=p; - for(;spaces;spaces--) - p=stpcpy(p, " "); - } - - p = stpcpy(p, s ); - if(opt.verbose && letter) - { - char num[8]; - sprintf(num," (%c%d)",letter,i); - p = stpcpy(p,num); - } - } - } - if( p ) - p = stpcpy(p, "\n" ); - return list; -} - - -static void -i18n_init(void) -{ -#ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE_GT ); -#else -#ifdef ENABLE_NLS - setlocale( LC_ALL, "" ); - bindtextdomain( PACKAGE_GT, LOCALEDIR ); - textdomain( PACKAGE_GT ); -#endif -#endif -} - -static void -wrong_args( const char *text) -{ - fputs(_("usage: gpg [options] "),stderr); - fputs(text,stderr); - putc('\n',stderr); - g10_exit(2); -} - - -static void -log_set_strict (int yesno) -{ - /* FIXME-XXX*/ -} - -static char * -make_username( const char *string ) -{ - char *p; - if( utf8_strings ) - p = xstrdup (string); - else - p = native_to_utf8( string ); - return p; -} - - -/* - * same as add_to_strlist() but if is_utf8 is *not* set a conversion - * to UTF8 is done - */ -static STRLIST -add_to_strlist2 ( STRLIST *list, const char *string, int is_utf8) -{ - STRLIST sl; - - if (is_utf8) - sl = add_to_strlist( list, string ); - else - { - char *p = native_to_utf8( string ); - sl = add_to_strlist( list, p ); - xfree( p ); - } - return sl; -} - - -/* Setup the debugging. With a LEVEL of NULL only the active debug - flags are propagated to the subsystems. With LEVEL set, a specific - set of debug flags is set; thus overriding all flags already - set. */ -static void -set_debug (const char *level) -{ - if (!level) - ; - else if (!strcmp (level, "none")) - opt.debug = 0; - else if (!strcmp (level, "basic")) - opt.debug = DBG_MEMSTAT_VALUE; - else if (!strcmp (level, "advanced")) - opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE; - else if (!strcmp (level, "expert")) - opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE - |DBG_CACHE_VALUE|DBG_FILTER_VALUE|DBG_PACKET_VALUE); - else if (!strcmp (level, "guru")) - opt.debug = ~0; - else - { - log_error (_("invalid debug-level `%s' given\n"), level); - g10_exit (2); - } - - if (opt.debug & DBG_MEMORY_VALUE ) - memory_debug_mode = 1; - if (opt.debug & DBG_MEMSTAT_VALUE ) - memory_stat_debug_mode = 1; - if (opt.debug & DBG_MPI_VALUE) - gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); - if (opt.debug & DBG_CIPHER_VALUE ) - gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); - if (opt.debug & DBG_IOBUF_VALUE ) - iobuf_debug_mode = 1; -} - - -/* We need the home directory also in some other directories, so make - sure that both variables are always in sync. */ -static void -set_homedir (const char *dir) -{ - if (!dir) - dir = ""; - g10_opt_homedir = opt.homedir = dir; -} - - -static void -set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) -{ - enum cmd_and_opt_values cmd = *ret_cmd; - - if( !cmd || cmd == new_cmd ) - cmd = new_cmd; - else if( cmd == aSign && new_cmd == aEncr ) - cmd = aSignEncr; - else if( cmd == aEncr && new_cmd == aSign ) - cmd = aSignEncr; - else if( cmd == aSign && new_cmd == aSym ) - cmd = aSignSym; - else if( cmd == aSym && new_cmd == aSign ) - cmd = aSignSym; - else if( ( cmd == aSign && new_cmd == aClearsign ) - || ( cmd == aClearsign && new_cmd == aSign ) ) - cmd = aClearsign; - else { - log_error(_("conflicting commands\n")); - g10_exit(2); - } - - *ret_cmd = cmd; -} - - -static void add_group(char *string) -{ - char *name,*value; - struct groupitem *item; - STRLIST values=NULL; - - /* Break off the group name */ - name=strsep(&string,"="); - if(string==NULL) - { - log_error(_("no = sign found in group definition \"%s\"\n"),name); - return; - } - - trim_trailing_ws((unsigned char *)name,strlen(name)); - - /* Break apart the values */ - while ((value= strsep(&string," \t"))) - { - if (*value) - add_to_strlist2 (&values,value,utf8_strings); - } - - item=xmalloc (sizeof(struct groupitem)); - item->name=name; - item->values=values; - item->next=opt.grouplist; - - opt.grouplist=item; -} - -/* We need to check three things. - - 0) The homedir. It must be x00, a directory, and owned by the - user. - - 1) The options file. Okay unless it or its containing directory is - group or other writable or not owned by us. disable exec in this - case. - - 2) Extensions. Same as #2. - - Returns true if the item is unsafe. */ -static int -check_permissions(const char *path,int item) -{ -#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM) - static int homedir_cache=-1; - char *tmppath,*dir; - struct stat statbuf,dirbuf; - int homedir=0,ret=0,checkonly=0; - int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0; - - if(opt.no_perm_warn) - return 0; - - assert(item==0 || item==1 || item==2); - - /* extensions may attach a path */ - if(item==2 && path[0]!=DIRSEP_C) - { - if(strchr(path,DIRSEP_C)) - tmppath=make_filename(path,NULL); - else - tmppath=make_filename(GNUPG_LIBDIR,path,NULL); - } - else - tmppath=xstrdup (path); - - /* If the item is located in the homedir, but isn't the homedir, - don't continue if we already checked the homedir itself. This is - to avoid user confusion with an extra options file warning which - could be rectified if the homedir itself had proper - permissions. */ - if(item!=0 && homedir_cache>-1 - && ascii_strncasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0) - { - ret=homedir_cache; - goto end; - } - - /* It's okay if the file or directory doesn't exist */ - if(stat(tmppath,&statbuf)!=0) - { - ret=0; - goto end; - } - - /* Now check the enclosing directory. 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,&dirbuf)!=0 || !S_ISDIR(dirbuf.st_mode)) - { - /* Weird error */ - ret=1; - goto end; - } - - xfree (dir); - - /* Assume failure */ - ret=1; - - if(item==0) - { - /* The homedir must be x00, a directory, and owned by the user. */ - - if(S_ISDIR(statbuf.st_mode)) - { - if(statbuf.st_uid==getuid()) - { - if((statbuf.st_mode & (S_IRWXG|S_IRWXO))==0) - ret=0; - else - perm=1; - } - else - own=1; - - homedir_cache=ret; - } - } - else if(item==1 || item==2) - { - /* The options or extension file. Okay unless it or its - containing directory is group or other writable or not owned - by us or root. */ - - if(S_ISREG(statbuf.st_mode)) - { - if(statbuf.st_uid==getuid() || statbuf.st_uid==0) - { - if((statbuf.st_mode & (S_IWGRP|S_IWOTH))==0) - { - /* it's not writable, so make sure the enclosing - directory is also not writable */ - if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) - { - if((dirbuf.st_mode & (S_IWGRP|S_IWOTH))==0) - ret=0; - else - enc_dir_perm=1; - } - else - enc_dir_own=1; - } - else - { - /* it's writable, so the enclosing directory had - better not let people get to it. */ - if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) - { - if((dirbuf.st_mode & (S_IRWXG|S_IRWXO))==0) - ret=0; - else - perm=enc_dir_perm=1; /* unclear which one to fix! */ - } - else - enc_dir_own=1; - } - } - else - own=1; - } - } - else - BUG(); - - if(!checkonly) - { - if(own) - { - if(item==0) - log_info(_("WARNING: unsafe ownership on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe ownership on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe ownership on " - "extension \"%s\"\n"),tmppath); - } - if(perm) - { - if(item==0) - log_info(_("WARNING: unsafe permissions on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe permissions on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe permissions on " - "extension \"%s\"\n"),tmppath); - } - if(enc_dir_own) - { - if(item==0) - log_info(_("WARNING: unsafe enclosing directory ownership on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe enclosing directory ownership on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe enclosing directory ownership on " - "extension \"%s\"\n"),tmppath); - } - if(enc_dir_perm) - { - if(item==0) - log_info(_("WARNING: unsafe enclosing directory permissions on " - "homedir \"%s\"\n"),tmppath); - else if(item==1) - log_info(_("WARNING: unsafe enclosing directory permissions on " - "configuration file \"%s\"\n"),tmppath); - else - log_info(_("WARNING: unsafe enclosing directory permissions on " - "extension \"%s\"\n"),tmppath); - } - } - - end: - xfree (tmppath); - - if(homedir) - homedir_cache=ret; - - return ret; - -#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */ - - return 0; -} - -int -main( int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - iobuf_t a; - int rc=0; - int orig_argc; - char **orig_argv; - const char *fname; - char *username; - int may_coredump; - STRLIST sl, remusr= NULL, locusr=NULL; - STRLIST nrings=NULL, sec_nrings=NULL; - armor_filter_context_t afx; - int detached_sig = 0; - FILE *configfp = NULL; - char *configname = NULL; - const char *config_filename = NULL; - unsigned configlineno; - int parse_debug = 0; - int default_config = 1; - int default_keyring = 1; - int greeting = 0; - int nogreeting = 0; - char *logfile = NULL; - int use_random_seed = 1; - enum cmd_and_opt_values cmd = 0; - const char *debug_level = NULL; - const char *trustdb_name = NULL; - char *def_cipher_string = NULL; - char *def_digest_string = NULL; - char *def_compress_string = NULL; - char *cert_digest_string = NULL; - char *s2k_cipher_string = NULL; - char *s2k_digest_string = NULL; - char *pers_cipher_list = NULL; - char *pers_digest_list = NULL; - char *pers_compress_list = NULL; - int eyes_only=0; - int multifile=0; - int pwfd = -1; - int with_fpr = 0; /* make an option out of --fingerprint */ - int any_explicit_recipient = 0; - -#ifdef __riscos__ - riscos_global_defaults(); - opt.lock_once = 1; -#endif /* __riscos__ */ - - trap_unaligned(); - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - /* We don't need any locking in libgcrypt unless we use any kind of - threading. */ - gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING); - /* Please note that we may running SUID(ROOT), so be very CAREFUL - * when adding any stuff between here and the call to - * secmem_init() somewhere after the option parsing - */ - log_set_prefix ("gpg", 1); - /* check that the libraries are suitable. Do it here because the - option parse may need services of the library */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - - gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); - - may_coredump = disable_core_dumps(); - gnupg_init_signals (0, emergency_cleanup); - create_dotlock (NULL); /* register locking cleanup */ - i18n_init(); - - opt.command_fd = -1; /* no command fd */ - opt.compress = -1; /* defaults to standard compress level */ - /* note: if you change these lines, look at oOpenPGP */ - opt.def_cipher_algo = 0; - opt.def_digest_algo = 0; - opt.cert_digest_algo = 0; - opt.def_compress_algo = -1; - opt.s2k_mode = 3; /* iterated+salted */ - opt.s2k_digest_algo = DIGEST_ALGO_SHA1; -#ifdef USE_CAST5 - opt.s2k_cipher_algo = CIPHER_ALGO_CAST5; -#else - opt.s2k_cipher_algo = CIPHER_ALGO_3DES; -#endif - opt.completes_needed = 1; - opt.marginals_needed = 3; - opt.max_cert_depth = 5; - opt.pgp2_workarounds = 1; - opt.force_v3_sigs = 1; - opt.escape_from = 1; - opt.import_options=IMPORT_SK2PK; - opt.export_options= - EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; - opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG; - opt.keyserver_options.export_options= - EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; - opt.keyserver_options.include_subkeys=1; - opt.keyserver_options.include_revoked=1; - opt.keyserver_options.try_dns_srv=1; - opt.verify_options= - VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION|VERIFY_SHOW_KEYSERVER; - opt.trust_model=TM_AUTO; - opt.mangle_dos_filenames = 1; - opt.use_agent = 1; - - set_homedir ( default_homedir () ); - - /* Check whether we have a config file on the commandline */ - orig_argc = argc; - orig_argv = argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ - while( arg_parse( &pargs, opts) ) { - if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll ) - parse_debug++; - else if( pargs.r_opt == oOptions ) { - /* yes there is one, so we do not try the default one, but - * read the option file when it is encountered at the commandline - */ - default_config = 0; - } - else if( pargs.r_opt == oNoOptions ) - default_config = 0; /* --no-options */ - else if( pargs.r_opt == oHomedir ) - set_homedir ( pargs.r.ret_str ); - else if( pargs.r_opt == oNoPermissionWarn ) - opt.no_perm_warn=1; - else if (pargs.r_opt == oStrict ) - { - opt.strict=1; - log_set_strict(1); - } - else if (pargs.r_opt == oNoStrict ) - { - opt.strict=0; - log_set_strict(0); - } - } - -#ifdef HAVE_DOSISH_SYSTEM - if ( strchr (opt.homedir,'\\') ) { - char *d, *buf = xmalloc (strlen (opt.homedir)+1); - const char *s = opt.homedir; - for (d=buf,s=opt.homedir; *s; s++) - *d++ = *s == '\\'? '/': *s; - *d = 0; - set_homedir (buf); - } -#endif - - /* Initialize the secure memory. */ - gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); - maybe_setuid = 0; - /* Okay, we are now working under our real uid */ - - /* malloc hooks go here ... */ - assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - - set_native_charset (NULL); /* Try to auto set the character set */ - - /* Try for a version specific config file first */ - if( default_config ) - { - char *name = xstrdup ("gpg" EXTSEP_S "conf-" SAFE_VERSION); - char *ver = name + strlen("gpg" EXTSEP_S "conf-"); - - do - { - if(configname) - { - char *tok; - - xfree (configname); - configname=NULL; - - if((tok=strrchr (ver,SAFE_VERSION_DASH))) - *tok='\0'; - else if((tok=strrchr (ver,SAFE_VERSION_DOT))) - *tok='\0'; - else - break; - } - - configname = make_filename (opt.homedir, name, NULL); - } - while ( access(configname,R_OK) ); - xfree(name); - - if (!access (configname, R_OK)) - { /* Print a warning when both config files are present. */ - char *p = make_filename(opt.homedir, "options", NULL ); - if (!access (p, R_OK)) - log_info (_("NOTE: old default options file `%s' ignored\n"), p); - xfree (p); - } - else - { /* Keep on using the old default one. */ - xfree (configname); - configname = make_filename(opt.homedir, "options", NULL ); - } - } - argc = orig_argc; - argv = orig_argv; - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - - /* By this point we have a homedir, and cannot change it. */ - check_permissions(opt.homedir,0); - - next_pass: - if( configname ) { - if(check_permissions(configname,1)) - { - /* If any options file is unsafe, then disable any external - programs for keyserver calls or photo IDs. Since the - external program to call is set in the options file, a - unsafe options file can lead to an arbitrary program - being run. */ - - opt.exec_disable=1; - } - - configlineno = 0; - configfp = fopen( configname, "r" ); - if( !configfp ) { - if( default_config ) { - if( parse_debug ) - log_info(_("NOTE: no default option file `%s'\n"), - configname ); - } - else { - log_error(_("option file `%s': %s\n"), - configname, strerror(errno) ); - g10_exit(2); - } - xfree (configname); configname = NULL; - } - if( parse_debug && configname ) - log_info(_("reading options from `%s'\n"), configname ); - default_config = 0; - } - - while( optfile_parse( configfp, configname, &configlineno, - &pargs, opts) ) { - switch( pargs.r_opt ) { - case aCheckKeys: set_cmd( &cmd, aCheckKeys); break; - case aListPackets: set_cmd( &cmd, aListPackets); break; - case aImport: set_cmd( &cmd, aImport); break; - case aFastImport: set_cmd( &cmd, aFastImport); break; - case aSendKeys: set_cmd( &cmd, aSendKeys); break; - case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; - case aSearchKeys: set_cmd( &cmd, aSearchKeys); break; - case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; - case aExport: set_cmd( &cmd, aExport); break; - case aExportAll: set_cmd( &cmd, aExportAll); break; - case aListKeys: set_cmd( &cmd, aListKeys); break; - case aListSigs: set_cmd( &cmd, aListSigs); break; - case aExportSecret: set_cmd( &cmd, aExportSecret); break; - case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break; - case aDeleteSecretKeys: set_cmd( &cmd, aDeleteSecretKeys); - greeting=1; break; - case aDeleteSecretAndPublicKeys: - set_cmd( &cmd, aDeleteSecretAndPublicKeys); - greeting=1; - break; - case aDeleteKeys: set_cmd( &cmd, aDeleteKeys); greeting=1; break; - - case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; - case aSym: set_cmd( &cmd, aSym); break; - - case aDecryptFiles: multifile=1; /* fall through */ - case aDecrypt: set_cmd( &cmd, aDecrypt); break; - - case aEncrFiles: multifile=1; /* fall through */ - case aEncr: set_cmd( &cmd, aEncr); break; - - case aVerifyFiles: multifile=1; /* fall through */ - case aVerify: set_cmd( &cmd, aVerify); break; - - case aSign: set_cmd( &cmd, aSign ); break; - case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; - case aSignKey: set_cmd( &cmd, aSignKey); break; - case aLSignKey: set_cmd( &cmd, aLSignKey); break; - case aNRSignKey: set_cmd( &cmd, aNRSignKey); break; - case aNRLSignKey: set_cmd( &cmd, aNRLSignKey); break; - case aStore: set_cmd( &cmd, aStore); break; - case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break; - case aClearsign: set_cmd( &cmd, aClearsign); break; - case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; - case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; - - case aPrimegen: set_cmd( &cmd, aPrimegen); break; - case aGenRandom: set_cmd( &cmd, aGenRandom); break; - case aPrintMD: set_cmd( &cmd, aPrintMD); break; - case aPrintMDs: set_cmd( &cmd, aPrintMDs); break; - case aListTrustDB: set_cmd( &cmd, aListTrustDB); break; - case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break; - case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break; - case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break; - case aListTrustPath: set_cmd( &cmd, aListTrustPath); break; - case aDeArmor: set_cmd( &cmd, aDeArmor); break; - case aEnArmor: set_cmd( &cmd, aEnArmor); break; - case aListOwnerTrust: - deprecated_warning(configname,configlineno, - "--list-ownertrust","--export-ownertrust",""); - case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break; - case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break; - case aPipeMode: set_cmd( &cmd, aPipeMode); break; - case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; - - case aCardStatus: set_cmd (&cmd, aCardStatus); break; - case aCardEdit: set_cmd (&cmd, aCardEdit); break; - case aChangePIN: set_cmd (&cmd, aChangePIN); break; - case aGPGConfList: - set_cmd (&cmd, aGPGConfList); - nogreeting = 1; - break; - - case oArmor: opt.armor = 1; opt.no_armor=0; break; - case oOutput: opt.outfile = pargs.r.ret_str; break; - case oQuiet: opt.quiet = 1; break; - case oNoTTY: tty_no_terminal(1); break; - case oDryRun: opt.dry_run = 1; break; - case oInteractive: opt.interactive = 1; break; - case oVerbose: g10_opt_verbose++; - opt.verbose++; opt.list_sigs=1; break; - - case oLogFile: logfile = pargs.r.ret_str; break; - - case oBatch: opt.batch = 1; nogreeting = 1; break; - case oUseAgent: -#ifndef __riscos__ - opt.use_agent = 1; -#else /* __riscos__ */ - opt.use_agent = 0; - riscos_not_implemented("use-agent"); -#endif /* __riscos__ */ - break; - case oNoUseAgent: opt.use_agent = 0; break; - case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break; - case oAnswerYes: opt.answer_yes = 1; break; - case oAnswerNo: opt.answer_no = 1; break; - case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break; - case oPrimaryKeyring: - sl=append_to_strlist( &nrings, pargs.r.ret_str); - sl->flags=2; - break; - case oShowKeyring: opt.list_options|=LIST_SHOW_KEYRING; break; - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - case oDebugLevel: debug_level = pargs.r.ret_str; break; - case oStatusFD: - set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); - break; -#ifdef __riscos__ - case oStatusFile: - set_status_fd( iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); - break; -#endif /* __riscos__ */ - case oAttributeFD: - set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1)); - break; -#ifdef __riscos__ - case oAttributeFile: - set_attrib_fd(iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); - break; -#endif /* __riscos__ */ - case oLoggerFD: - log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1)); - break; -#ifdef __riscos__ - case oLoggerFile: - log_set_logfile( NULL, - iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); - break; -#endif /* __riscos__ */ - case oWithFingerprint: - opt.with_fingerprint = 1; - with_fpr=1; /*fall thru*/ - case oFingerprint: opt.fingerprint++; break; - case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break; - case oOptions: - /* config files may not be nested (silently ignore them) */ - if( !configfp ) { - xfree (configname); - configname = xstrdup (pargs.r.ret_str); - goto next_pass; - } - break; - case oNoArmor: opt.no_armor=1; opt.armor=0; break; - case oNoDefKeyring: default_keyring = 0; break; - case oDefCertCheckLevel: opt.def_cert_check_level=pargs.r.ret_int; break; - case oNoGreeting: nogreeting = 1; break; - case oNoVerbose: g10_opt_verbose = 0; - opt.verbose = 0; opt.list_sigs=0; break; - /* disabled for now: - case oQuickRandom: quick_random_gen(1); break; */ - case oSKComments: opt.sk_comments=1; break; - case oNoSKComments: opt.sk_comments=0; break; - case oEmitVersion: opt.no_version=0; break; - case oNoEmitVersion: opt.no_version=1; break; - case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; - case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break; - case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break; - case oTrustDBName: trustdb_name = pargs.r.ret_str; break; - case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break; - case oDefRecipient: - if( *pargs.r.ret_str ) - opt.def_recipient = make_username(pargs.r.ret_str); - break; - case oDefRecipientSelf: - xfree (opt.def_recipient); opt.def_recipient = NULL; - opt.def_recipient_self = 1; - break; - case oNoDefRecipient: - xfree (opt.def_recipient); opt.def_recipient = NULL; - opt.def_recipient_self = 0; - break; - case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */ - case oHomedir: break; - case oNoBatch: opt.batch = 0; break; - case oWithKeyData: opt.with_key_data=1; /* fall thru */ - case oWithColons: opt.with_colons=':'; break; - - case oSkipVerify: opt.skip_verify=1; break; - case oCompressKeys: opt.compress_keys = 1; break; - case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; - /* There are many programs (like mutt) that call gpg with - --always-trust so keep this option around for a long - time. */ - case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break; - case oTrustModel: - if(ascii_strcasecmp(pargs.r.ret_str,"pgp")==0) - opt.trust_model=TM_PGP; - else if(ascii_strcasecmp(pargs.r.ret_str,"classic")==0) - opt.trust_model=TM_CLASSIC; - else if(ascii_strcasecmp(pargs.r.ret_str,"always")==0) - opt.trust_model=TM_ALWAYS; - else if(ascii_strcasecmp(pargs.r.ret_str,"auto")==0) - opt.trust_model=TM_AUTO; - else - log_error("unknown trust model \"%s\"\n",pargs.r.ret_str); - break; - case oForceOwnertrust: - log_info(_("NOTE: %s is not for normal use!\n"), - "--force-ownertrust"); - opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str); - if(opt.force_ownertrust==-1) - { - log_error("invalid ownertrust \"%s\"\n",pargs.r.ret_str); - opt.force_ownertrust=0; - } - break; - case oLoadExtension: -#ifndef __riscos__ -#if defined(USE_DYNAMIC_LINKING) || defined(_WIN32) - if(check_permissions(pargs.r.ret_str,2)) - log_info(_("cipher extension \"%s\" not loaded due to " - "unsafe permissions\n"),pargs.r.ret_str); - else - register_cipher_extension(orig_argc? *orig_argv:NULL, - pargs.r.ret_str); -#endif -#else /* __riscos__ */ - riscos_not_implemented("load-extension"); -#endif /* __riscos__ */ - break; - case oRFC1991: - opt.compliance = CO_RFC1991; - opt.force_v4_certs = 0; - opt.escape_from = 1; - break; - case oRFC2440: - case oOpenPGP: - /* TODO: When 2440bis becomes a RFC, these may need - changing. */ - opt.compliance = CO_RFC2440; - opt.allow_non_selfsigned_uid = 1; - opt.allow_freeform_uid = 1; - opt.pgp2_workarounds = 0; - opt.escape_from = 0; - opt.force_v3_sigs = 0; - opt.compress_keys = 0; /* not mandated but we do it */ - opt.compress_sigs = 0; /* ditto. */ - opt.not_dash_escaped = 0; - opt.def_cipher_algo = 0; - opt.def_digest_algo = 0; - opt.cert_digest_algo = 0; - opt.def_compress_algo = -1; - opt.s2k_mode = 3; /* iterated+salted */ - opt.s2k_digest_algo = DIGEST_ALGO_SHA1; - opt.s2k_cipher_algo = CIPHER_ALGO_3DES; - break; - case oPGP2: opt.compliance = CO_PGP2; break; - case oPGP6: opt.compliance = CO_PGP6; break; - case oPGP7: opt.compliance = CO_PGP7; break; - case oPGP8: opt.compliance = CO_PGP8; break; - case oGnuPG: opt.compliance = CO_GNUPG; break; - case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; - case oCompressSigs: opt.compress_sigs = 1; break; - case oSetFilename: opt.set_filename = pargs.r.ret_str; break; - case oForYourEyesOnly: eyes_only = 1; break; - case oNoForYourEyesOnly: eyes_only = 0; break; - case oSetPolicyURL: - add_policy_url(pargs.r.ret_str,0); - add_policy_url(pargs.r.ret_str,1); - break; - case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break; - case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break; - case oShowPolicyURL: - opt.list_options|=LIST_SHOW_POLICY; - opt.verify_options|=VERIFY_SHOW_POLICY; - break; - case oNoShowPolicyURL: - opt.list_options&=~LIST_SHOW_POLICY; - opt.verify_options&=~VERIFY_SHOW_POLICY; - break; - case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; - case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; - - case oComment: add_to_strlist(&opt.comments,pargs.r.ret_str); break; - case oDefaultComment: - deprecated_warning(configname,configlineno, - "--default-comment","--no-comments",""); - /* fall through */ - case oNoComments: - free_strlist(opt.comments); - opt.comments=NULL; - break; - - case oThrowKeyid: opt.throw_keyid = 1; break; - case oNoThrowKeyid: opt.throw_keyid = 0; break; - case oShowPhotos: - opt.list_options|=LIST_SHOW_PHOTOS; - opt.verify_options|=VERIFY_SHOW_PHOTOS; - break; - case oNoShowPhotos: - opt.list_options&=~LIST_SHOW_PHOTOS; - opt.verify_options&=~VERIFY_SHOW_PHOTOS; - break; - case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break; - case oForceV3Sigs: opt.force_v3_sigs = 1; break; - case oNoForceV3Sigs: opt.force_v3_sigs = 0; break; - case oForceV4Certs: opt.force_v4_certs = 1; break; - case oNoForceV4Certs: opt.force_v4_certs = 0; break; - case oForceMDC: opt.force_mdc = 1; break; - case oNoForceMDC: opt.force_mdc = 0; break; - case oDisableMDC: opt.disable_mdc = 1; break; - case oNoDisableMDC: opt.disable_mdc = 0; break; - case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; - case oS2KDigest: s2k_digest_string = xstrdup (pargs.r.ret_str); break; - case oS2KCipher: s2k_cipher_string = xstrdup (pargs.r.ret_str); break; - case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break; - case oNoEncryptTo: opt.no_encrypt_to = 1; break; - case oEncryptTo: /* store the recipient in the second list */ - sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); - sl->flags = 1; - break; - case oHiddenEncryptTo: /* store the recipient in the second list */ - sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); - sl->flags = 1|2; - break; - case oRecipient: /* store the recipient */ - add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); - any_explicit_recipient = 1; - break; - case oHiddenRecipient: /* store the recipient with a flag */ - sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); - sl->flags = 2; - any_explicit_recipient = 1; - break; - case oTextmodeShort: opt.textmode = 2; break; - case oTextmode: opt.textmode=1; break; - case oNoTextmode: opt.textmode=0; break; - case oExpert: opt.expert = 1; break; - case oNoExpert: opt.expert = 0; break; - case oAskSigExpire: opt.ask_sig_expire = 1; break; - case oNoAskSigExpire: opt.ask_sig_expire = 0; break; - case oAskCertExpire: opt.ask_cert_expire = 1; break; - case oNoAskCertExpire: opt.ask_cert_expire = 0; break; - case oUser: /* store the local users */ - add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings ); - break; - case oCompress: opt.compress = pargs.r.ret_int; break; - case oPasswdFD: - pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); - opt.use_agent = 0; - break; -#ifdef __riscos__ - case oPasswdFile: - pwfd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); - break; -#endif /* __riscos__ */ - case oCommandFD: - opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0); - break; -#ifdef __riscos__ - case oCommandFile: - opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); - break; -#endif /* __riscos__ */ - case oCipherAlgo: def_cipher_string = xstrdup (pargs.r.ret_str); break; - case oDigestAlgo: def_digest_string = xstrdup (pargs.r.ret_str); break; - case oCompressAlgo: - /* If it is all digits, stick a Z in front of it for - later. This is for backwards compatibility with - versions that took the compress algorithm number. */ - { - char *pt=pargs.r.ret_str; - while(*pt) - { - if(!isdigit(*pt)) - break; - - pt++; - } - - if(*pt=='\0') - { - def_compress_string=xmalloc (strlen(pargs.r.ret_str)+2); - strcpy(def_compress_string,"Z"); - strcat(def_compress_string,pargs.r.ret_str); - } - else - def_compress_string = xstrdup (pargs.r.ret_str); - } - break; - case oCertDigestAlgo: cert_digest_string = xstrdup (pargs.r.ret_str); break; - case oNoSecmemWarn: - gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); - break; - case oNoPermissionWarn: opt.no_perm_warn=1; break; - case oNoMDCWarn: opt.no_mdc_warn=1; break; - case oCharset: - if( set_native_charset( pargs.r.ret_str ) ) - log_error(_("%s is not a valid character set\n"), - pargs.r.ret_str); - break; - case oNotDashEscaped: opt.not_dash_escaped = 1; break; - case oEscapeFrom: opt.escape_from = 1; break; - case oNoEscapeFrom: opt.escape_from = 0; break; - case oLockOnce: opt.lock_once = 1; break; - case oLockNever: disable_dotlock(); break; - case oLockMultiple: -#ifndef __riscos__ - opt.lock_once = 0; -#else /* __riscos__ */ - riscos_not_implemented("lock-multiple"); -#endif /* __riscos__ */ - break; - case oKeyServer: - opt.keyserver_uri=xstrdup (pargs.r.ret_str); - if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno)) - log_error(_("could not parse keyserver URI\n")); - break; - case oKeyServerOptions: - parse_keyserver_options(pargs.r.ret_str); - break; - case oImportOptions: - if(!parse_import_options(pargs.r.ret_str,&opt.import_options)) - { - if(configname) - log_error(_("%s:%d: invalid import options\n"), - configname,configlineno); - else - log_error(_("invalid import options\n")); - } - break; - case oExportOptions: - if(!parse_export_options(pargs.r.ret_str,&opt.export_options)) - { - if(configname) - log_error(_("%s:%d: invalid export options\n"), - configname,configlineno); - else - log_error(_("invalid export options\n")); - } - break; - case oListOptions: - { - struct parse_options lopts[]= - { - {"show-photos",LIST_SHOW_PHOTOS}, - {"show-policy-url",LIST_SHOW_POLICY}, - {"show-notation",LIST_SHOW_NOTATION}, - {"show-keyserver-url",LIST_SHOW_KEYSERVER}, - {"show-validity",LIST_SHOW_VALIDITY}, - {"show-long-keyid",LIST_SHOW_LONG_KEYID}, - {"show-keyring",LIST_SHOW_KEYRING}, - {"show-sig-expire",LIST_SHOW_SIG_EXPIRE}, - {NULL,0} - }; - - if(!parse_options(pargs.r.ret_str,&opt.list_options,lopts)) - { - if(configname) - log_error(_("%s:%d: invalid list options\n"), - configname,configlineno); - else - log_error(_("invalid list options\n")); - } - } - break; - case oVerifyOptions: - { - struct parse_options vopts[]= - { - {"show-photos",VERIFY_SHOW_PHOTOS}, - {"show-policy-url",VERIFY_SHOW_POLICY}, - {"show-notation",VERIFY_SHOW_NOTATION}, - {"show-keyserver-url",VERIFY_SHOW_KEYSERVER}, - {"show-validity",VERIFY_SHOW_VALIDITY}, - {"show-long-keyid",VERIFY_SHOW_LONG_KEYID}, - {NULL,0} - }; - - if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts)) - { - if(configname) - log_error(_("%s:%d: invalid verify options\n"), - configname,configlineno); - else - log_error(_("invalid verify options\n")); - } - } - break; - case oTempDir: opt.temp_dir=pargs.r.ret_str; break; - case oExecPath: - if(set_exec_path(pargs.r.ret_str,0)) - log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str); - else - opt.exec_path_set=1; - break; - case oSetNotation: - add_notation_data( pargs.r.ret_str, 0 ); - add_notation_data( pargs.r.ret_str, 1 ); - break; - case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break; - case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break; - case oShowNotation: - opt.list_options|=LIST_SHOW_NOTATION; - opt.verify_options|=VERIFY_SHOW_NOTATION; - break; - case oNoShowNotation: - opt.list_options&=~LIST_SHOW_NOTATION; - opt.verify_options&=~VERIFY_SHOW_NOTATION; - break; - case oUtf8Strings: utf8_strings = 1; break; - case oNoUtf8Strings: utf8_strings = 0; break; - case oDisableCipherAlgo: - { - int algo = gcry_cipher_map_name (pargs.r.ret_str); - gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, - &algo, sizeof algo); - } - break; - case oDisablePubkeyAlgo: - { - int algo = gcry_pk_map_name (pargs.r.ret_str); - gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, - &algo, sizeof algo ); - } - break; - case oNoSigCache: opt.no_sig_cache = 1; break; - case oNoSigCreateCheck: opt.no_sig_create_check = 1; break; - case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break; - case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; - case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; - case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; - case oNoLiteral: opt.no_literal = 1; break; - case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; - case oHonorHttpProxy: - opt.keyserver_options.honor_http_proxy = 1; - deprecated_warning(configname,configlineno, - "--honor-http-proxy", - "--keyserver-options ", - "honor-http-proxy"); - break; - case oFastListMode: opt.fast_list_mode = 1; break; - case oFixedListMode: opt.fixed_list_mode = 1; break; - case oListOnly: opt.list_only=1; break; - case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; - case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; - case oIgnoreCrcError: opt.ignore_crc_error = 1; break; - case oIgnoreMDCError: opt.ignore_mdc_error = 1; break; - case oNoRandomSeedFile: use_random_seed = 0; break; - case oAutoKeyRetrieve: - case oNoAutoKeyRetrieve: - opt.keyserver_options.auto_key_retrieve= - (pargs.r_opt==oAutoKeyRetrieve); - deprecated_warning(configname,configlineno, - pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve": - "--no-auto-key-retrieve","--keyserver-options ", - pargs.r_opt==oAutoKeyRetrieve?"auto-key-retrieve": - "no-auto-key-retrieve"); - break; - case oShowSessionKey: opt.show_session_key = 1; break; - case oOverrideSessionKey: - opt.override_session_key = pargs.r.ret_str; - break; - case oMergeOnly: opt.merge_only = 1; break; - case oAllowSecretKeyImport: /* obsolete */ break; - case oTryAllSecrets: opt.try_all_secrets = 1; break; - case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break; - case oEnableSpecialFilenames: - iobuf_enable_special_filenames (1); - break; - case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break; - case oAutoCheckTrustDB: opt.no_auto_check_trustdb=0; break; - case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break; - case oPreservePermissions: opt.preserve_permissions=1; break; - case oDefaultPreferenceList: - opt.def_preference_list = pargs.r.ret_str; - break; - case oPersonalCipherPreferences: - pers_cipher_list=pargs.r.ret_str; - break; - case oPersonalDigestPreferences: - pers_digest_list=pargs.r.ret_str; - break; - case oPersonalCompressPreferences: - pers_compress_list=pargs.r.ret_str; - break; - case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; - case oDisplay: opt.display = pargs.r.ret_str; break; - case oTTYname: opt.ttyname = pargs.r.ret_str; break; - case oTTYtype: opt.ttytype = pargs.r.ret_str; break; - case oLCctype: opt.lc_ctype = pargs.r.ret_str; break; - case oLCmessages: opt.lc_messages = pargs.r.ret_str; break; - case oGroup: add_group(pargs.r.ret_str); break; - case oStrict: opt.strict=1; log_set_strict(1); break; - case oNoStrict: opt.strict=0; log_set_strict(0); break; - - case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break; - case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; - - case oEnableProgressFilter: opt.enable_progress_filter = 1; break; - case oMultifile: multifile=1; break; - - default : pargs.err = configfp? 1:2; break; - } - } - - if( configfp ) { - fclose( configfp ); - configfp = NULL; - config_filename = configname; /* Keep a copy of the config - file name. */ - configname = NULL; - goto next_pass; - } - xfree ( configname ); configname = NULL; - if( log_get_errorcount(0) ) - g10_exit(2); - if( nogreeting ) - greeting = 0; - - if( greeting ) { - fprintf(stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - fprintf(stderr, "%s\n", strusage(15) ); - } -#ifdef IS_DEVELOPMENT_VERSION - if( !opt.batch ) { - log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); - log_info("It is only intended for test purposes and should NOT be\n"); - log_info("used in a production environment or with production keys!\n"); - } -#endif - - log_info ("WARNING: This version of gpg is not very matured and\n"); - log_info ("WARNING: only intended for testing. Please keep using\n"); - log_info ("WARNING: gpg 1.2.x, 1.3.x or 1.4.x for OpenPGP\n"); - - /* FIXME: We should use the lggging to a file only in server mode; - however we have not yet implemetyed that thus we try to get - away with --batch as indication for logging to file required. */ - if (logfile && opt.batch) - { - log_set_file (logfile); - log_set_prefix (NULL, 1|2|4); - } - - if (opt.verbose > 2) - log_info ("using character set `%s'\n", get_native_charset ()); - - if( may_coredump && !opt.quiet ) - log_info(_("WARNING: program may create a core file!\n")); - - if (eyes_only) { - if (opt.set_filename) - log_info(_("WARNING: %s overrides %s\n"), - "--for-your-eyes-only","--set-filename"); - - opt.set_filename="_CONSOLE"; - } - - if (opt.no_literal) { - log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal"); - if (opt.textmode) - log_error(_("%s not allowed with %s!\n"), - "--textmode", "--no-literal" ); - if (opt.set_filename) - log_error(_("%s makes no sense with %s!\n"), - eyes_only?"--for-your-eyes-only":"--set-filename", - "--no-literal" ); - } - - if (opt.set_filesize) - log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize"); - if( opt.batch ) - tty_batchmode( 1 ); - - gcry_control (GCRYCTL_RESUME_SECMEM_WARN); - set_debug (debug_level); - - /* Do these after the switch(), so they can override settings. */ - if(PGP2) - { - int unusable=0; - - if(cmd==aSign && !detached_sig) - { - log_info(_("you can only make detached or clear signatures " - "while in --pgp2 mode\n")); - unusable=1; - } - else if(cmd==aSignEncr || cmd==aSignSym) - { - log_info(_("you can't sign and encrypt at the " - "same time while in --pgp2 mode\n")); - unusable=1; - } - else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym)) - { - log_info(_("you must use files (and not a pipe) when " - "working with --pgp2 enabled.\n")); - unusable=1; - } - else if(cmd==aEncr || cmd==aSym) - { - /* Everything else should work without IDEA (except using - a secret key encrypted with IDEA and setting an IDEA - preference, but those have their own error - messages). */ - - if(openpgp_cipher_test_algo (CIPHER_ALGO_IDEA)) - { - log_info(_("encrypting a message in --pgp2 mode requires " - "the IDEA cipher\n")); - idea_cipher_warn(1); - unusable=1; - } - else if(cmd==aSym) - { - /* This only sets IDEA for symmetric encryption - since it is set via select_algo_from_prefs for - pk encryption. */ - xfree (def_cipher_string); - def_cipher_string = xstrdup ("idea"); - } - - /* PGP2 can't handle the output from the textmode - filter, so we disable it for anything that could - create a literal packet (only encryption and - symmetric encryption, since we disable signing - above). */ - if(!unusable) - opt.textmode=0; - } - - if(unusable) - compliance_failure(); - else - { - opt.force_v4_certs = 0; - opt.sk_comments = 0; - opt.escape_from = 1; - opt.force_v3_sigs = 1; - opt.pgp2_workarounds = 1; - opt.ask_sig_expire = 0; - opt.ask_cert_expire = 0; - xfree (def_digest_string); - def_digest_string = xstrdup ("md5"); - opt.def_compress_algo = 1; - } - } - else if(PGP6) - { - opt.sk_comments=0; - opt.escape_from=1; - opt.force_v3_sigs=1; - opt.ask_sig_expire=0; - } - else if(PGP7) - { - opt.sk_comments=0; - opt.escape_from=1; - opt.force_v3_sigs=1; - opt.ask_sig_expire=0; - } - else if(PGP8) - { - opt.escape_from=1; - } - - /* must do this after dropping setuid, because string_to... - * may try to load an module */ - if( def_cipher_string ) { - opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string); - if(opt.def_cipher_algo==0 && - (ascii_strcasecmp(def_cipher_string,"idea")==0 - || ascii_strcasecmp(def_cipher_string,"s1")==0)) - idea_cipher_warn(1); - xfree (def_cipher_string); def_cipher_string = NULL; - if( openpgp_cipher_test_algo (opt.def_cipher_algo) ) - log_error(_("selected cipher algorithm is invalid\n")); - } - if( def_digest_string ) { - opt.def_digest_algo = gcry_md_map_name (def_digest_string); - xfree (def_digest_string); def_digest_string = NULL; - if( openpgp_md_test_algo (opt.def_digest_algo) ) - log_error(_("selected digest algorithm is invalid\n")); - } - if( def_compress_string ) { - opt.def_compress_algo = string_to_compress_algo(def_compress_string); - xfree (def_compress_string); def_compress_string = NULL; - if( check_compress_algo(opt.def_compress_algo) ) - log_error(_("selected compression algorithm is invalid\n")); - } - if( cert_digest_string ) { - opt.cert_digest_algo = gcry_md_map_name (cert_digest_string); - xfree (cert_digest_string); cert_digest_string = NULL; - if( openpgp_md_test_algo(opt.cert_digest_algo) ) - log_error(_("selected certification digest algorithm is invalid\n")); - } - if( s2k_cipher_string ) { - opt.s2k_cipher_algo = gcry_cipher_map_name (s2k_cipher_string); - xfree (s2k_cipher_string); s2k_cipher_string = NULL; - if( openpgp_cipher_test_algo (opt.s2k_cipher_algo) ) - log_error(_("selected cipher algorithm is invalid\n")); - } - if( s2k_digest_string ) { - opt.s2k_digest_algo = gcry_md_map_name (s2k_digest_string); - xfree (s2k_digest_string); s2k_digest_string = NULL; - if( openpgp_md_test_algo (opt.s2k_digest_algo) ) - log_error(_("selected digest algorithm is invalid\n")); - } - if( opt.completes_needed < 1 ) - log_error(_("completes-needed must be greater than 0\n")); - if( opt.marginals_needed < 2 ) - log_error(_("marginals-needed must be greater than 1\n")); - if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 ) - log_error(_("max-cert-depth must be in range 1 to 255\n")); - switch( opt.s2k_mode ) { - case 0: - log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n")); - break; - case 1: case 3: break; - default: - log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); - } - - if(opt.def_cert_check_level<0 || opt.def_cert_check_level>3) - log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n")); - - /* This isn't actually needed, but does serve to error out if the - string is invalid. */ - if(opt.def_preference_list && - keygen_set_std_prefs(opt.def_preference_list,0)) - log_error(_("invalid default preferences\n")); - - /* We provide defaults for the personal digest list */ - if(!pers_digest_list) - pers_digest_list="h2"; - - if(pers_cipher_list && - keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM)) - log_error(_("invalid personal cipher preferences\n")); - - if(pers_digest_list && - keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH)) - log_error(_("invalid personal digest preferences\n")); - - if(pers_compress_list && - keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) - log_error(_("invalid personal compress preferences\n")); - - /* We don't support all possible commands with multifile yet */ - if(multifile) - { - char *cmdname; - - switch(cmd) - { - case aSign: - cmdname="--sign"; - break; - case aClearsign: - cmdname="--clearsign"; - break; - case aDetachedSign: - cmdname="--detach-sign"; - break; - case aSym: - cmdname="--symmetric"; - break; - case aStore: - cmdname="--store"; - break; - default: - cmdname=NULL; - break; - } - - if(cmdname) - log_error(_("%s does not yet work with %s\n"),cmdname,"--multifile"); - } - - if( log_get_errorcount(0) ) - g10_exit(2); - - /* Check our chosen algorithms against the list of legal - algorithms. */ - - if(!GNUPG) - { - const char *badalg=NULL; - preftype_t badtype=PREFTYPE_NONE; - - if (opt.def_cipher_algo - && !algo_available (PREFTYPE_SYM,opt.def_cipher_algo,NULL)) - { - badalg = gcry_cipher_algo_name (opt.def_cipher_algo); - badtype = PREFTYPE_SYM; - } - else if (opt.def_digest_algo - && !algo_available (PREFTYPE_HASH,opt.def_digest_algo,NULL)) - { - badalg = gcry_md_algo_name (opt.def_digest_algo); - badtype = PREFTYPE_HASH; - } - else if (opt.cert_digest_algo - && !algo_available (PREFTYPE_HASH,opt.cert_digest_algo,NULL)) - { - badalg = gcry_md_algo_name (opt.cert_digest_algo); - badtype = PREFTYPE_HASH; - } - else if (opt.def_compress_algo!=-1 - && !algo_available (PREFTYPE_ZIP,opt.def_compress_algo,NULL)) - { - badalg = compress_algo_to_string (opt.def_compress_algo); - badtype = PREFTYPE_ZIP; - } - - if (badalg) - { - switch(badtype) - { - case PREFTYPE_SYM: - log_info(_("you may not use cipher algorithm \"%s\" " - "while in %s mode\n"), - badalg,compliance_option_string()); - break; - case PREFTYPE_HASH: - log_info(_("you may not use digest algorithm \"%s\" " - "while in %s mode\n"), - badalg,compliance_option_string()); - break; - case PREFTYPE_ZIP: - log_info(_("you may not use compression algorithm \"%s\" " - "while in %s mode\n"), - badalg,compliance_option_string()); - break; - default: - BUG(); - } - - compliance_failure(); - } - } - - /* set the random seed file */ - if( use_random_seed ) { - char *p = make_filename(opt.homedir, "random_seed", NULL ); - gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); - xfree (p); - } - - if( !cmd && opt.fingerprint && !with_fpr ) { - set_cmd( &cmd, aListKeys); - } - - /* Compression algorithm 0 means no compression at all */ - if( opt.def_compress_algo == 0) - opt.compress = 0; - - /* kludge to let -sat generate a clear text signature */ - if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign ) - cmd = aClearsign; - - if( opt.verbose > 1 ) - set_packet_list_mode(1); - - /* Add the keyrings, but not for some special commands. Also - avoid adding the secret keyring for a couple of commands to - avoid unneeded access in case the secrings are stored on a - floppy */ - if( cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfList ) - { - if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys - && cmd != aVerify && cmd != aSym) - { - if (!sec_nrings || default_keyring) /* add default secret rings */ - keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); - for (sl = sec_nrings; sl; sl = sl->next) - keydb_add_resource ( sl->d, 0, 1 ); - } - if( !nrings || default_keyring ) /* add default ring */ - keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0); - for(sl = nrings; sl; sl = sl->next ) - keydb_add_resource ( sl->d, sl->flags, 0 ); - } - FREE_STRLIST(nrings); - FREE_STRLIST(sec_nrings); - - - if( pwfd != -1 ) /* read the passphrase now. */ - read_passphrase_from_fd( pwfd ); - - fname = argc? *argv : NULL; - - switch( cmd ) { - case aPrimegen: - case aPrintMD: - case aPrintMDs: - case aGenRandom: - case aDeArmor: - case aEnArmor: - case aFixTrustDB: - case aCardStatus: - case aCardEdit: - case aChangePIN: - case aGPGConfList: - break; - case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; - case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; - default: rc = setup_trustdb(1, trustdb_name ); break; - } - if( rc ) - log_error(_("failed to initialize the TrustDB: %s\n"), gpg_strerror (rc)); - - - switch (cmd) { - case aStore: - case aSym: - case aSign: - case aSignSym: - case aClearsign: - if (!opt.quiet && any_explicit_recipient) - log_info (_("WARNING: recipients (-r) given " - "without using public key encryption\n")); - break; - default: - break; - } - - switch( cmd ) { - case aStore: /* only store the file */ - if( argc > 1 ) - wrong_args(_("--store [filename]")); - if( (rc = encode_store(fname)) ) - log_error ("\b%s: store failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); - break; - case aSym: /* encrypt the given file only with the symmetric cipher */ - if( argc > 1 ) - wrong_args(_("--symmetric [filename]")); - if( (rc = encode_symmetric(fname)) ) - log_error ("\b%s: symmetric encryption failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); - break; - - case aEncr: /* encrypt the given file */ - if(multifile) - encode_crypt_files(argc, argv, remusr); - else - { - if( argc > 1 ) - wrong_args(_("--encrypt [filename]")); - if( (rc = encode_crypt(fname,remusr)) ) - log_error("%s: encryption failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); - } - break; - - case aSign: /* sign the given file */ - sl = NULL; - if( detached_sig ) { /* sign all files */ - for( ; argc; argc--, argv++ ) - add_to_strlist( &sl, *argv ); - } - else { - if( argc > 1 ) - wrong_args(_("--sign [filename]")); - if( argc ) { - sl = xcalloc (1, sizeof *sl + strlen(fname)); - strcpy(sl->d, fname); - } - } - if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) - log_error("signing failed: %s\n", gpg_strerror (rc) ); - free_strlist(sl); - break; - - case aSignEncr: /* sign and encrypt the given file */ - if( argc > 1 ) - wrong_args(_("--sign --encrypt [filename]")); - if( argc ) { - sl = xcalloc (1, sizeof *sl + strlen(fname)); - strcpy(sl->d, fname); - } - else - sl = NULL; - if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) - log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); - free_strlist(sl); - break; - - case aSignSym: /* sign and conventionally encrypt the given file */ - if (argc > 1) - wrong_args(_("--sign --symmetric [filename]")); - rc = sign_symencrypt_file (fname, locusr); - if (rc) - log_error("%s: sign+symmetric failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); - break; - - case aClearsign: /* make a clearsig */ - if( argc > 1 ) - wrong_args(_("--clearsign [filename]")); - if( (rc = clearsign_file(fname, locusr, NULL)) ) - log_error("%s: clearsign failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); - break; - - case aVerify: - if(multifile) - { - if( (rc = verify_files( argc, argv ) )) - log_error("verify files failed: %s\n", gpg_strerror (rc) ); - } - else - { - if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); - } - break; - - case aDecrypt: - if(multifile) - decrypt_messages(argc, argv); - else - { - if( argc > 1 ) - wrong_args(_("--decrypt [filename]")); - if( (rc = decrypt_message( fname ) )) - log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); - } - break; - - case aSignKey: /* sign the key given as argument */ - if( argc != 1 ) - wrong_args(_("--sign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 1 ); - xfree (username); - break; - - case aLSignKey: - if( argc != 1 ) - wrong_args(_("--lsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 2 ); - xfree (username); - break; - - case aNRSignKey: - if( argc != 1 ) - wrong_args(_("--nrsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 3 ); - xfree (username); - break; - - case aNRLSignKey: - if( argc != 1 ) - wrong_args(_("--nrlsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 4 ); - xfree (username); - break; - - case aEditKey: /* Edit a key signature */ - if( !argc ) - wrong_args(_("--edit-key user-id [commands]")); - username = make_username( fname ); - if( argc > 1 ) { - sl = NULL; - for( argc--, argv++ ; argc; argc--, argv++ ) - append_to_strlist( &sl, *argv ); - keyedit_menu( username, locusr, sl, 0 ); - free_strlist(sl); - } - else - keyedit_menu(username, locusr, NULL, 0 ); - xfree (username); - break; - - case aDeleteKeys: - case aDeleteSecretKeys: - case aDeleteSecretAndPublicKeys: - sl = NULL; - /* I'm adding these in reverse order as add_to_strlist2 - reverses them again, and it's easier to understand in the - proper order :) */ - for( ; argc; argc-- ) - add_to_strlist2( &sl, argv[argc-1], utf8_strings ); - delete_keys(sl,cmd==aDeleteSecretKeys,cmd==aDeleteSecretAndPublicKeys); - free_strlist(sl); - break; - - case aCheckKeys: - opt.check_sigs = 1; - case aListSigs: - opt.list_sigs = 1; - case aListKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - public_key_list( sl ); - free_strlist(sl); - break; - case aListSecretKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - secret_key_list( sl ); - free_strlist(sl); - break; - - case aKeygen: /* generate a key */ - if( opt.batch ) { - if( argc > 1 ) - wrong_args("--gen-key [parameterfile]"); - generate_keypair( argc? *argv : NULL, NULL ); - } - else { - if( argc ) - wrong_args("--gen-key"); - generate_keypair(NULL, NULL); - } - break; - - case aFastImport: - opt.import_options |= IMPORT_FAST_IMPORT; - case aImport: - import_keys( argc? argv:NULL, argc, NULL, opt.import_options ); - break; - - case aExport: - case aExportAll: - case aSendKeys: - case aRecvKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - if( cmd == aSendKeys ) - rc=keyserver_export( sl ); - else if( cmd == aRecvKeys ) - rc=keyserver_import( sl ); - else - rc=export_pubkeys( sl, opt.export_options ); - if(rc) - { - if(cmd==aSendKeys) - log_error(_("keyserver send failed: %s\n"),gpg_strerror (rc)); - else if(cmd==aRecvKeys) - log_error(_("keyserver receive failed: %s\n"),gpg_strerror (rc)); - else - log_error(_("key export failed: %s\n"),gpg_strerror (rc)); - } - free_strlist(sl); - break; - - case aSearchKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - { - if (utf8_strings) - sl = append_to_strlist ( &sl, *argv ); - else - { - char *p = native_to_utf8 ( *argv ); - sl = append_to_strlist( &sl, p ); - xfree( p ); - } - } - - rc=keyserver_search( sl ); - if(rc) - log_error(_("keyserver search failed: %s\n"),gpg_strerror (rc)); - free_strlist(sl); - break; - - case aRefreshKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - rc=keyserver_refresh(sl); - if(rc) - log_error(_("keyserver refresh failed: %s\n"),gpg_strerror (rc)); - free_strlist(sl); - break; - - case aExportSecret: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - export_seckeys( sl ); - free_strlist(sl); - break; - - case aExportSecretSub: - sl = NULL; - for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); - export_secsubkeys( sl ); - free_strlist(sl); - break; - - case aGenRevoke: - if( argc != 1 ) - wrong_args("--gen-revoke user-id"); - username = make_username(*argv); - gen_revoke( username ); - xfree ( username ); - break; - - case aDesigRevoke: - if( argc != 1 ) - wrong_args("--desig-revoke user-id"); - username = make_username(*argv); - gen_desig_revoke( username ); - xfree ( username ); - break; - - case aDeArmor: - if( argc > 1 ) - wrong_args("--dearmor [file]"); - rc = dearmor_file( argc? *argv: NULL ); - if( rc ) - log_error(_("dearmoring failed: %s\n"), gpg_strerror (rc)); - break; - - case aEnArmor: - if( argc > 1 ) - wrong_args("--enarmor [file]"); - rc = enarmor_file( argc? *argv: NULL ); - if( rc ) - log_error(_("enarmoring failed: %s\n"), gpg_strerror (rc)); - break; - - - case aPrimegen: -#if 0 /*FIXME-XXX*/ - { int mode = argc < 2 ? 0 : atoi(*argv); - - if( mode == 1 && argc == 2 ) { - mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1); - } - else if( mode == 2 && argc == 3 ) { - mpi_print( stdout, generate_elg_prime( - 0, atoi(argv[1]), - atoi(argv[2]), NULL,NULL ), 1); - } - else if( mode == 3 && argc == 3 ) { - gcry_mpi_t *factors; - mpi_print( stdout, generate_elg_prime( - 1, atoi(argv[1]), - atoi(argv[2]), NULL,&factors ), 1); - putchar('\n'); - mpi_print( stdout, factors[0], 1 ); /* print q */ - } - else if( mode == 4 && argc == 3 ) { - gcry_mpi_t g = mpi_alloc(1); - mpi_print( stdout, generate_elg_prime( - 0, atoi(argv[1]), - atoi(argv[2]), g, NULL ), 1); - putchar('\n'); - mpi_print( stdout, g, 1 ); - mpi_free(g); - } - else - wrong_args("--gen-prime mode bits [qbits] "); - putchar('\n'); - } -#endif - break; - - case aGenRandom: - { - int level = argc ? atoi(*argv):0; - int count = argc > 1 ? atoi(argv[1]): 0; - int endless = !count; - - if( argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0 ) - wrong_args("--gen-random 0|1|2 [count]"); - - while( endless || count ) { - byte *p; - /* Wee need a multiple of 3, so that in case of - armored output we get a correct string. No - linefolding is done, as it is best to levae this to - other tools */ - size_t n = !endless && count < 99? count : 99; - - p = gcry_random_bytes (n, level); -#ifdef HAVE_DOSISH_SYSTEM - setmode ( fileno(stdout), O_BINARY ); -#endif - if (opt.armor) { - char *tmp = make_radix64_string (p, n); - fputs (tmp, stdout); - xfree (tmp); - if (n%3 == 1) - putchar ('='); - if (n%3) - putchar ('='); - } else { - fwrite( p, n, 1, stdout ); - } - xfree (p); - if( !endless ) - count -= n; - } - if (opt.armor) - putchar ('\n'); - } - break; - - case aPrintMD: - if( argc < 1) - wrong_args("--print-md algo [files]"); - { - int all_algos = (**argv=='*' && !(*argv)[1]); - int algo = all_algos? 0 : gcry_md_map_name (*argv); - - if( !algo && !all_algos ) - log_error(_("invalid hash algorithm `%s'\n"), *argv ); - else { - argc--; argv++; - if( !argc ) - print_mds(NULL, algo); - else { - for(; argc; argc--, argv++ ) - print_mds(*argv, algo); - } - } - } - break; - - case aPrintMDs: /* old option */ - if( !argc ) - print_mds(NULL,0); - else { - for(; argc; argc--, argv++ ) - print_mds(*argv,0); - } - break; - - case aListTrustDB: - if( !argc ) - list_trustdb(NULL); - else { - for( ; argc; argc--, argv++ ) - list_trustdb( *argv ); - } - break; - - case aUpdateTrustDB: - if( argc ) - wrong_args("--update-trustdb"); - update_trustdb(); - break; - - case aCheckTrustDB: - /* Old versions allowed for arguments - ignore them */ - check_trustdb(); - break; - - case aFixTrustDB: - log_error("this command is not yet implemented.\n"); - log_error("A workaround is to use \"--export-ownertrust\", remove\n"); - log_error("the trustdb file and do an \"--import-ownertrust\".\n" ); - break; - - case aListTrustPath: - if( !argc ) - wrong_args("--list-trust-path <user-ids>"); - for( ; argc; argc--, argv++ ) { - username = make_username( *argv ); - list_trust_path( username ); - xfree (username); - } - break; - - case aExportOwnerTrust: - if( argc ) - wrong_args("--export-ownertrust"); - export_ownertrust(); - break; - - case aImportOwnerTrust: - if( argc > 1 ) - wrong_args("--import-ownertrust [file]"); - import_ownertrust( argc? *argv:NULL ); - break; - - case aPipeMode: - if ( argc ) - wrong_args ("--pipemode"); - run_in_pipemode (); - break; - - case aRebuildKeydbCaches: - if (argc) - wrong_args ("--rebuild-keydb-caches"); - keydb_rebuild_caches (); - break; - - case aCardStatus: - if (argc) - wrong_args ("--card-status"); - card_status (stdout, NULL, 0); - break; - - case aCardEdit: - if (argc) - { - sl = NULL; - for (argc--, argv++ ; argc; argc--, argv++) - append_to_strlist (&sl, *argv); - card_edit (sl); - free_strlist (sl); - } - else - card_edit (NULL); - break; - - case aChangePIN: - if (!argc) - change_pin (0,1); - else if (argc == 1) - change_pin ( atoi (*argv), 1); - else - wrong_args ("--change-pin [no]"); - break; - - case aGPGConfList: - { /* List options and default values in the GPG Conf format. */ - - /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ - /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING - FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0UL - /* The RUNTIME flag for an option indicates that the option can be - changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1UL << 3) - /* The DEFAULT flag for an option indicates that the option has a - default value. */ -#define GC_OPT_FLAG_DEFAULT (1UL << 4) - /* The DEF_DESC flag for an option indicates that the option has a - default, which is described by the value of the default field. */ -#define GC_OPT_FLAG_DEF_DESC (1UL << 5) - /* The NO_ARG_DESC flag for an option indicates that the argument has - a default, which is described by the value of the ARGDEF field. */ -#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - - if (!config_filename) - config_filename = make_filename (opt.homedir, "gpg.conf", NULL); - - printf ("gpgconf-gpg.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, config_filename); - - printf ("verbose:%lu:\n" - "quiet:%lu:\n" - "debug-level:%lu:\"none:\n" - "log-file:%lu:\n", - GC_OPT_FLAG_NONE, - GC_OPT_FLAG_NONE, - GC_OPT_FLAG_DEFAULT, - GC_OPT_FLAG_NONE ); - printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); - - } - break; - - case aListPackets: - opt.list_packets=2; - default: - if( argc > 1 ) - wrong_args(_("[filename]")); - /* Issue some output for the unix newbie */ - if( !fname && !opt.outfile && isatty( fileno(stdin) ) - && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) ) - log_info(_("Go ahead and type your message ...\n")); - - if( !(a = iobuf_open(fname)) ) - log_error(_("can't open `%s'\n"), print_fname_stdin(fname)); - else { - - if( !opt.no_armor ) { - if( use_armor_filter( a ) ) { - memset( &afx, 0, sizeof afx); - iobuf_push_filter( a, armor_filter, &afx ); - } - } - if( cmd == aListPackets ) { - set_packet_list_mode(1); - opt.list_packets=1; - } - rc = proc_packets(NULL, a ); - if( rc ) - log_error("processing message failed: %s\n", gpg_strerror (rc) ); - iobuf_close(a); - } - break; - } - - /* cleanup */ - FREE_STRLIST(remusr); - FREE_STRLIST(locusr); - g10_exit(0); - return 8; /*NEVER REACHED*/ -} - -/* Note: This function is used by signal handlers!. */ -static void -emergency_cleanup (void) -{ - gcry_control (GCRYCTL_TERM_SECMEM ); -} - - -void -g10_exit( int rc ) -{ - gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); - if (opt.debug & DBG_MEMSTAT_VALUE) - { - gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); - gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); - } - if (opt.debug) - gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); - emergency_cleanup (); - rc = rc? rc : log_get_errorcount(0)? 2 : - g10_errors_seen? 1 : 0; - exit (rc ); -} - - -/* Pretty-print hex hashes. This assumes at least an 80-character - display, but there are a few other similar assumptions in the - display code. */ -static void -print_hex( MD_HANDLE md, int algo, const char *fname ) -{ - int i,n,count,indent=0; - const byte *p; - - if(fname) - indent=printf("%s: ",fname); - - if(indent>40) - { - printf("\n"); - indent=0; - } - - if(algo==DIGEST_ALGO_RMD160) - indent+=printf("RMD160 = "); - else if(algo>0) - indent+=printf("%6s = ", gcry_md_algo_name (algo)); - else - algo=abs(algo); - - count=indent; - - p = gcry_md_read (md, algo); - n = gcry_md_get_algo_dlen (algo); - - count+=printf("%02X",*p++); - - for(i=1;i<n;i++,p++) - { - if(n==16) - { - if(count+2>79) - { - printf("\n%*s",indent," "); - count=indent; - } - else - count+=printf(" "); - - if(!(i%8)) - count+=printf(" "); - } - else if (n==20) - { - if(!(i%2)) - { - if(count+4>79) - { - printf("\n%*s",indent," "); - count=indent; - } - else - count+=printf(" "); - } - - if(!(i%10)) - count+=printf(" "); - } - else - { - if(!(i%4)) - { - if(count+8>79) - { - printf("\n%*s",indent," "); - count=indent; - } - else - count+=printf(" "); - } - } - - count+=printf("%02X",*p); - } - - printf("\n"); -} - -static void -print_hashline( MD_HANDLE md, int algo, const char *fname ) -{ - int i, n; - const byte *p; - - if ( fname ) { - for (p = (const unsigned char *)fname; *p; p++ ) { - if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) - printf("%%%02X", *p ); - else - putchar( *p ); - } - } - putchar(':'); - printf("%d:", algo ); - p = gcry_md_read (md, algo ); - n = gcry_md_get_algo_dlen (algo); - for(i=0; i < n ; i++, p++ ) - printf("%02X", *p ); - putchar(':'); - putchar('\n'); -} - -static void -print_mds( const char *fname, int algo ) -{ - FILE *fp; - char buf[1024]; - size_t n; - MD_HANDLE md; - - if( !fname ) { - fp = stdin; -#ifdef HAVE_DOSISH_SYSTEM - setmode ( fileno(fp) , O_BINARY ); -#endif - } - else { - fp = fopen( fname, "rb" ); - } - if( !fp ) { - log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); - return; - } - - gcry_md_open (&md, 0, 0 ); - if( algo ) - gcry_md_enable ( md, algo ); - else { - gcry_md_enable (md, GCRY_MD_MD5 ); - gcry_md_enable (md, GCRY_MD_SHA1 ); - gcry_md_enable (md, GCRY_MD_RMD160 ); -#ifdef USE_SHA256 - gcry_md_enable (md, GCRY_MD_SHA256 ); -#endif -#ifdef USE_SHA512 - gcry_md_enable (md, GCRY_MD_SHA384 ); - gcry_md_enable (md, GCRY_MD_SHA512 ); -#endif - } - - while( (n=fread( buf, 1, DIM(buf), fp )) ) - gcry_md_write (md, buf, n); - if( ferror(fp) ) - log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); - else { - gcry_md_final (md); - if ( opt.with_colons ) { - if ( algo ) - print_hashline( md, algo, fname ); - else { - print_hashline( md, GCRY_MD_MD5, fname ); - print_hashline( md, GCRY_MD_SHA1, fname ); - print_hashline( md, GCRY_MD_RMD160, fname ); -#ifdef USE_SHA256 - print_hashline( md, GCRY_MD_SHA256, fname ); -#endif -#ifdef USE_SHA512 - print_hashline( md, GCRY_MD_SHA384, fname ); - print_hashline( md, GCRY_MD_SHA512, fname ); -#endif - } - } - else { - if( algo ) - print_hex(md,-algo,fname); - else { - print_hex( md, GCRY_MD_MD5, fname ); - print_hex( md, GCRY_MD_SHA1, fname ); - print_hex( md, GCRY_MD_RMD160, fname ); -#ifdef USE_SHA256 - print_hex( md, GCRY_MD_SHA256, fname ); -#endif -#ifdef USE_SHA512 - print_hex( md, GCRY_MD_SHA384, fname ); - print_hex( md, GCRY_MD_SHA512, fname ); -#endif - } - } - } - gcry_md_close (md); - - if( fp != stdin ) - fclose(fp); -} - - -/**************** - * Check the supplied name,value string and add it to the notation - * data to be used for signatures. which==0 for sig notations, and 1 - * for cert notations. -*/ -static void -add_notation_data( const char *string, int which ) -{ - const char *s; - STRLIST sl,*notation_data; - int critical=0; - int highbit=0; - int saw_at=0; - - if(which) - notation_data=&opt.cert_notation_data; - else - notation_data=&opt.sig_notation_data; - - if( *string == '!' ) { - critical = 1; - string++; - } - - /* If and when the IETF assigns some official name tags, we'll - have to add them here. */ - - for( s=string ; *s != '='; s++ ) - { - if( *s=='@') - saw_at=1; - - if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) ) - { - log_error(_("a notation name must have only printable characters " - "or spaces, and end with an '='\n") ); - return; - } - } - - if(!saw_at && !opt.expert) - { - log_error( - _("a user notation name must contain the '@' character\n")); - return; - } - - /* we only support printable text - therefore we enforce the use - * of only printable characters (an empty value is valid) */ - for( s++; *s ; s++ ) { - if( *s & 0x80 ) - highbit = 1; - else if( iscntrl(*s) ) { - log_error(_("a notation value must not use " - "any control characters\n") ); - return; - } - } - - if( highbit ) /* must use UTF8 encoding */ - sl = add_to_strlist2( notation_data, string, utf8_strings ); - else - sl = add_to_strlist( notation_data, string ); - - if( critical ) - sl->flags |= 1; -} - - -static void -add_policy_url( const char *string, int which ) -{ - int i,critical=0; - STRLIST sl; - - if(*string=='!') - { - string++; - critical=1; - } - - for(i=0;i<strlen(string);i++) - if(string[i]&0x80 || iscntrl(string[i])) - break; - - if(i==0 || i<strlen(string)) - { - if(which) - log_error(_("the given certification policy URL is invalid\n")); - else - log_error(_("the given signature policy URL is invalid\n")); - } - - if(which) - sl=add_to_strlist( &opt.cert_policy_url, string ); - else - sl=add_to_strlist( &opt.sig_policy_url, string ); - - if(critical) - sl->flags |= 1; -} - - -static void -add_keyserver_url( const char *string, int which ) -{ - int i,critical=0; - STRLIST sl; - - if(*string=='!') - { - string++; - critical=1; - } - - for(i=0;i<strlen(string);i++) - if(string[i]&0x80 || iscntrl(string[i])) - break; - - if(i==0 || i<strlen(string)) - { - if(which) - BUG(); - else - log_error(_("the given signature preferred" - " keyserver URL is invalid\n")); - } - - if(which) - BUG(); - else - sl=add_to_strlist( &opt.sig_keyserver_url, string ); - - if(critical) - sl->flags |= 1; -} - diff --git a/g10/gpg.c b/g10/gpg.c new file mode 100644 index 000000000..234d13f41 --- /dev/null +++ b/g10/gpg.c @@ -0,0 +1,3364 @@ +/* g10.c - The GnuPG utility (main for gpg) + * Copyright (C) 1998,1999,2000,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 + */ + +#include <config.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <assert.h> +#ifdef HAVE_DOSISH_SYSTEM +#include <fcntl.h> /* for setmode() */ +#endif +#ifdef HAVE_STAT +#include <sys/stat.h> /* for stat() */ +#endif +#include <assuan.h> + +#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" +#include "keyserver-internal.h" +#include "exec.h" + +enum cmd_and_opt_values { aNull = 0, + oArmor = 'a', + aDetachedSign = 'b', + aSym = 'c', + aDecrypt = 'd', + aEncr = 'e', + oInteractive = 'i', + aListKeys = 'k', + aListSecretKeys = 'K', + oDryRun = 'n', + oOutput = 'o', + oQuiet = 'q', + oRecipient = 'r', + oHiddenRecipient = 'R', + aSign = 's', + oTextmodeShort= 't', + oUser = 'u', + oVerbose = 'v', + oCompress = 'z', + oSetNotation = 'N', + oBatch = 500, + aGPGConfList, + oSigNotation, + oCertNotation, + oShowNotation, + oNoShowNotation, + aEncrFiles, + aDecryptFiles, + aClearsign, + aStore, + aKeygen, + aSignEncr, + aSignSym, + aSignKey, + aLSignKey, + aNRSignKey, + aNRLSignKey, + aListPackets, + aEditKey, + aDeleteKeys, + aDeleteSecretKeys, + aDeleteSecretAndPublicKeys, + aImport, + aFastImport, + aVerify, + aVerifyFiles, + aListSigs, + aSendKeys, + aRecvKeys, + aSearchKeys, + aExport, + aExportAll, + aExportSecret, + aExportSecretSub, + aCheckKeys, + aGenRevoke, + aDesigRevoke, + aPrimegen, + aPrintMD, + aPrintMDs, + aCheckTrustDB, + aUpdateTrustDB, + aFixTrustDB, + aListTrustDB, + aListTrustPath, + aExportOwnerTrust, + aListOwnerTrust, + aImportOwnerTrust, + aDeArmor, + aEnArmor, + aGenRandom, + aPipeMode, + aRebuildKeydbCaches, + aRefreshKeys, + aCardStatus, + aCardEdit, + aChangePIN, + + oTextmode, + oNoTextmode, + oExpert, + oNoExpert, + oAskSigExpire, + oNoAskSigExpire, + oAskCertExpire, + oNoAskCertExpire, + oFingerprint, + oWithFingerprint, + oAnswerYes, + oAnswerNo, + oDefCertCheckLevel, + oKeyring, + oPrimaryKeyring, + oSecretKeyring, + oShowKeyring, + oDefaultKey, + oDefRecipient, + oDefRecipientSelf, + oNoDefRecipient, + oOptions, + oDebug, + oDebugLevel, + oDebugAll, + oStatusFD, +#ifdef __riscos__ + oStatusFile, +#endif /* __riscos__ */ + oAttributeFD, +#ifdef __riscos__ + oAttributeFile, +#endif /* __riscos__ */ + oSKComments, + oNoSKComments, + oEmitVersion, + oNoEmitVersion, + oCompletesNeeded, + oMarginalsNeeded, + oMaxCertDepth, + oLoadExtension, + oGnuPG, + oRFC1991, + oRFC2440, + oOpenPGP, + oPGP2, + oPGP6, + oPGP7, + oPGP8, + oCipherAlgo, + oDigestAlgo, + oCertDigestAlgo, + oCompressAlgo, + oPasswdFD, +#ifdef __riscos__ + oPasswdFile, +#endif /* __riscos__ */ + oCommandFD, +#ifdef __riscos__ + oCommandFile, +#endif /* __riscos__ */ + oQuickRandom, + oNoVerbose, + oTrustDBName, + oNoSecmemWarn, + oNoPermissionWarn, + oNoMDCWarn, + oNoArmor, + oNoDefKeyring, + oNoGreeting, + oNoTTY, + oNoOptions, + oNoBatch, + oHomedir, + oWithColons, + oWithKeyData, + oSkipVerify, + oCompressKeys, + oCompressSigs, + oAlwaysTrust, + oTrustModel, + oForceOwnertrust, + oEmuChecksumBug, + oSetFilename, + oForYourEyesOnly, + oNoForYourEyesOnly, + oSetPolicyURL, + oSigPolicyURL, + oCertPolicyURL, + oShowPolicyURL, + oNoShowPolicyURL, + oSigKeyserverURL, + oUseEmbeddedFilename, + oComment, + oDefaultComment, + oNoComments, + oThrowKeyid, + oNoThrowKeyid, + oShowPhotos, + oNoShowPhotos, + oPhotoViewer, + oForceV3Sigs, + oNoForceV3Sigs, + oForceV4Certs, + oNoForceV4Certs, + oForceMDC, + oNoForceMDC, + oDisableMDC, + oNoDisableMDC, + oS2KMode, + oS2KDigest, + oS2KCipher, + oSimpleSKChecksum, + oCharset, + oNotDashEscaped, + oEscapeFrom, + oNoEscapeFrom, + oLockOnce, + oLockMultiple, + oLockNever, + oKeyServer, + oKeyServerOptions, + oImportOptions, + oExportOptions, + oListOptions, + oVerifyOptions, + oTempDir, + oExecPath, + oEncryptTo, + oHiddenEncryptTo, + oNoEncryptTo, + oLogFile, + oLoggerFD, +#ifdef __riscos__ + oLoggerFile, +#endif /* __riscos__ */ + oUtf8Strings, + oNoUtf8Strings, + oDisableCipherAlgo, + oDisablePubkeyAlgo, + oAllowNonSelfsignedUID, + oNoAllowNonSelfsignedUID, + oAllowFreeformUID, + oNoAllowFreeformUID, + oAllowSecretKeyImport, + oEnableSpecialFilenames, + oNoLiteral, + oSetFilesize, + oHonorHttpProxy, + oFastListMode, + oListOnly, + oIgnoreTimeConflict, + oIgnoreValidFrom, + oIgnoreCrcError, + oIgnoreMDCError, + oShowSessionKey, + oOverrideSessionKey, + oNoRandomSeedFile, + oAutoKeyRetrieve, + oNoAutoKeyRetrieve, + oUseAgent, + oNoUseAgent, + oGpgAgentInfo, + oMergeOnly, + oTryAllSecrets, + oTrustedKey, + oNoExpensiveTrustChecks, + oFixedListMode, + oNoSigCache, + oNoSigCreateCheck, + oAutoCheckTrustDB, + oNoAutoCheckTrustDB, + oPreservePermissions, + oDefaultPreferenceList, + oPersonalCipherPreferences, + oPersonalDigestPreferences, + oPersonalCompressPreferences, + oEmuMDEncodeBug, + oAgentProgram, + oDisplay, + oTTYname, + oTTYtype, + oLCctype, + oLCmessages, + oGroup, + oStrict, + oNoStrict, + oMangleDosFilenames, + oNoMangleDosFilenames, + oEnableProgressFilter, + oMultifile, +aTest }; + + +static ARGPARSE_OPTS opts[] = { + + { 300, NULL, 0, N_("@Commands:\n ") }, + + { aSign, "sign", 256, N_("|[file]|make a signature")}, + { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, + { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, + { aEncr, "encrypt", 256, N_("encrypt data")}, + { aEncrFiles, "encrypt-files", 256, "@"}, + { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")}, + { aStore, "store", 256, "@"}, + { aDecrypt, "decrypt", 256, N_("decrypt data (default)")}, + { aDecryptFiles, "decrypt-files", 256, "@"}, + { aVerify, "verify" , 256, N_("verify a signature")}, + { aVerifyFiles, "verify-files" , 256, "@" }, + { aListKeys, "list-keys", 256, N_("list keys")}, + { aListKeys, "list-public-keys", 256, "@" }, + { aListSigs, "list-sigs", 256, N_("list keys and signatures")}, + { aCheckKeys, "check-sigs",256, N_("list and check key signatures")}, + { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, + { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, + { aKeygen, "gen-key", 256, N_("generate a new key pair")}, + { aDeleteKeys,"delete-keys",256,N_("remove keys from the public keyring")}, + { aDeleteSecretKeys, "delete-secret-keys",256, + N_("remove keys from the secret keyring")}, + { aSignKey, "sign-key" ,256, N_("sign a key")}, + { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, + { aNRSignKey, "nrsign-key" ,256, "@"}, + { aNRLSignKey, "nrlsign-key" ,256, "@"}, + { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, + { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, + { aDesigRevoke, "desig-revoke",256, "@" }, + { aExport, "export" , 256, N_("export keys") }, + { aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, + { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, + { aSearchKeys, "search-keys" , 256, + N_("search for keys on a key server") }, + { aRefreshKeys, "refresh-keys", 256, + N_("update all keys from a keyserver")}, + { aExportAll, "export-all" , 256, "@" }, + { aExportSecret, "export-secret-keys" , 256, "@" }, + { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, + { aImport, "import", 256 , N_("import/merge keys")}, + { aFastImport, "fast-import", 256 , "@"}, + { aCardStatus, "card-status", 256, N_("print the card status")}, + { aCardEdit, "card-edit", 256, N_("change data on a card")}, + { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, + + { aListPackets, "list-packets",256, "@"}, + { aExportOwnerTrust, "export-ownertrust", 256, "@"}, + { aImportOwnerTrust, "import-ownertrust", 256, "@"}, + { aUpdateTrustDB, "update-trustdb",0 , N_("update the trust database")}, + { aCheckTrustDB, "check-trustdb",0 , "@"}, + { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, + { aDeArmor, "dearmor", 256, "@" }, + { aDeArmor, "dearmour", 256, "@" }, + { aEnArmor, "enarmor", 256, "@" }, + { aEnArmor, "enarmour", 256, "@" }, + { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, + { aPrimegen, "gen-prime" , 256, "@" }, + { aGenRandom, "gen-random" , 256, "@" }, + { aGPGConfList, "gpgconf-list", 256, "@" }, + + { 301, NULL, 0, N_("@\nOptions:\n ") }, + + { oArmor, "armor", 0, N_("create ascii armored output")}, + { oArmor, "armour", 0, "@" }, + { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, + { oHiddenRecipient, "hidden-recipient", 2, "@" }, + { oRecipient, "remote-user", 2, "@"}, /* old option name */ + { oDefRecipient, "default-recipient" ,2, "@" }, + { oDefRecipientSelf, "default-recipient-self" ,0, "@" }, + { oNoDefRecipient, "no-default-recipient", 0, "@" }, + { oTempDir, "temp-directory", 2, "@" }, + { oExecPath, "exec-path", 2, "@" }, + { oEncryptTo, "encrypt-to", 2, "@" }, + { oHiddenEncryptTo, "hidden-encrypt-to", 2, "@" }, + { oNoEncryptTo, "no-encrypt-to", 0, "@" }, + { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, + { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, + { oTextmodeShort, NULL, 0, "@"}, + { oTextmode, "textmode", 0, N_("use canonical text mode")}, + { oNoTextmode, "no-textmode", 0, "@"}, + { oExpert, "expert", 0, "@"}, + { oNoExpert, "no-expert", 0, "@"}, + { oAskSigExpire, "ask-sig-expire", 0, "@"}, + { oNoAskSigExpire, "no-ask-sig-expire", 0, "@"}, + { oAskCertExpire, "ask-cert-expire", 0, "@"}, + { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, + { oOutput, "output", 2, N_("use as output file")}, + { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, "@" }, + { oNoTTY, "no-tty", 0, "@" }, + { oLogFile, "log-file" ,2, "@" }, + { oForceV3Sigs, "force-v3-sigs", 0, "@" }, + { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@" }, + { oForceV4Certs, "force-v4-certs", 0, "@" }, + { oNoForceV4Certs, "no-force-v4-certs", 0, "@" }, + { oForceMDC, "force-mdc", 0, "@" }, + { oNoForceMDC, "no-force-mdc", 0, "@" }, + { oDisableMDC, "disable-mdc", 0, "@" }, + { oNoDisableMDC, "no-disable-mdc", 0, "@" }, + { oDryRun, "dry-run", 0, N_("do not make any changes") }, + { oInteractive, "interactive", 0, N_("prompt before overwriting") }, + { oUseAgent, "use-agent",0, "@"}, + { oNoUseAgent, "no-use-agent",0, "@"}, + { oGpgAgentInfo, "gpg-agent-info",2, "@"}, + { oBatch, "batch", 0, "@"}, + { oAnswerYes, "yes", 0, "@"}, + { oAnswerNo, "no", 0, "@"}, + { oKeyring, "keyring" , 2, "@"}, + { oPrimaryKeyring, "primary-keyring",2, "@" }, + { oSecretKeyring, "secret-keyring" ,2, "@"}, + { oShowKeyring, "show-keyring", 0, "@"}, + { oDefaultKey, "default-key" , 2, "@"}, + { oKeyServer, "keyserver", 2, "@"}, + { oKeyServerOptions, "keyserver-options",2,"@"}, + { oImportOptions, "import-options",2,"@"}, + { oExportOptions, "export-options",2,"@"}, + { oListOptions, "list-options",2,"@"}, + { oVerifyOptions, "verify-options",2,"@"}, + { oCharset, "charset" , 2, "@" }, + { oOptions, "options" , 2, "@"}, + + { oDebug, "debug" ,4|16, "@"}, + { oDebugLevel, "debug-level" ,2, "@"}, + { oDebugAll, "debug-all" ,0, "@"}, + { oStatusFD, "status-fd" ,1, "@" }, +#ifdef __riscos__ + { oStatusFile, "status-file" ,2, "@" }, +#endif /* __riscos__ */ + { oAttributeFD, "attribute-fd" ,1, "@" }, +#ifdef __riscos__ + { oAttributeFile, "attribute-file" ,2, "@" }, +#endif /* __riscos__ */ + { oNoSKComments, "no-sk-comments", 0, "@"}, + { oSKComments, "sk-comments", 0, "@"}, + { oCompletesNeeded, "completes-needed", 1, "@"}, + { oMarginalsNeeded, "marginals-needed", 1, "@"}, + { oMaxCertDepth, "max-cert-depth", 1, "@" }, + { oTrustedKey, "trusted-key", 2, "@"}, + { oLoadExtension, "load-extension" ,2, "@"}, + { oGnuPG, "gnupg", 0, "@"}, + { oGnuPG, "no-pgp2", 0, "@"}, + { oGnuPG, "no-pgp6", 0, "@"}, + { oGnuPG, "no-pgp7", 0, "@"}, + { oGnuPG, "no-pgp8", 0, "@"}, + { oRFC1991, "rfc1991", 0, "@"}, + { oRFC2440, "rfc2440", 0, "@"}, + { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, + { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, + { oPGP6, "pgp6", 0, "@"}, + { oPGP7, "pgp7", 0, "@"}, + { oPGP8, "pgp8", 0, "@"}, + { oS2KMode, "s2k-mode", 1, "@"}, + { oS2KDigest, "s2k-digest-algo",2, "@"}, + { oS2KCipher, "s2k-cipher-algo",2, "@"}, + { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, + { oCipherAlgo, "cipher-algo", 2 , "@"}, + { oDigestAlgo, "digest-algo", 2 , "@"}, + { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, + { oCompressAlgo,"compress-algo",2, "@"}, + { oThrowKeyid, "throw-keyid", 0, "@"}, + { oNoThrowKeyid, "no-throw-keyid", 0, "@" }, + { oShowPhotos, "show-photos", 0, "@" }, + { oNoShowPhotos, "no-show-photos", 0, "@" }, + { oPhotoViewer, "photo-viewer", 2, "@" }, + { oSetNotation, "set-notation", 2, "@" }, + { oSetNotation, "notation-data", 2, "@" }, /* Alias */ + { oSigNotation, "sig-notation", 2, "@" }, + { oCertNotation, "cert-notation", 2, "@" }, + + { 302, NULL, 0, N_( + "@\n(See the man page for a complete listing of all commands and options)\n" + )}, + + { 303, NULL, 0, N_("@\nExamples:\n\n" + " -se -r Bob [file] sign and encrypt for user Bob\n" + " --clearsign [file] make a clear text signature\n" + " --detach-sign [file] make a detached signature\n" + " --list-keys [names] show keys\n" + " --fingerprint [names] show fingerprints\n" ) }, + + /* hidden options */ + { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */ + { oCompressAlgo, "compression-algo", 1, "@"}, /* alias */ + { aPrintMDs, "print-mds" , 256, "@"}, /* old */ + { aListTrustDB, "list-trustdb",0 , "@"}, + /* Not yet used */ + /* { aListTrustPath, "list-trust-path",0, "@"}, */ + { aPipeMode, "pipemode", 0, "@" }, + { oPasswdFD, "passphrase-fd",1, "@" }, +#ifdef __riscos__ + { oPasswdFile, "passphrase-file",2, "@" }, +#endif /* __riscos__ */ + { oCommandFD, "command-fd",1, "@" }, +#ifdef __riscos__ + { oCommandFile, "command-file",2, "@" }, +#endif /* __riscos__ */ + { oQuickRandom, "quick-random", 0, "@"}, + { oNoVerbose, "no-verbose", 0, "@"}, + { oTrustDBName, "trustdb-name", 2, "@" }, + { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */ + { oNoPermissionWarn, "no-permission-warning", 0, "@" }, + { oNoMDCWarn, "no-mdc-warning", 0, "@" }, + { oNoArmor, "no-armor", 0, "@"}, + { oNoArmor, "no-armour", 0, "@"}, + { oNoDefKeyring, "no-default-keyring", 0, "@" }, + { oNoGreeting, "no-greeting", 0, "@" }, + { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */ + { oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */ + { oNoBatch, "no-batch", 0, "@" }, + { oWithColons, "with-colons", 0, "@"}, + { oWithKeyData,"with-key-data", 0, "@"}, + { aListKeys, "list-key", 0, "@" }, /* alias */ + { aListSigs, "list-sig", 0, "@" }, /* alias */ + { aCheckKeys, "check-sig",0, "@" }, /* alias */ + { oSkipVerify, "skip-verify",0, "@" }, + { oCompressKeys, "compress-keys",0, "@"}, + { oCompressSigs, "compress-sigs",0, "@"}, + { oDefCertCheckLevel, "default-cert-check-level", 1, "@"}, + { oAlwaysTrust, "always-trust", 0, "@"}, + { oTrustModel, "trust-model", 2, "@"}, + { oForceOwnertrust, "force-ownertrust", 2, "@"}, + { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"}, + { oSetFilename, "set-filename", 2, "@" }, + { oForYourEyesOnly, "for-your-eyes-only", 0, "@" }, + { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" }, + { oSetPolicyURL, "set-policy-url", 2, "@" }, + { oSigPolicyURL, "sig-policy-url", 2, "@" }, + { oCertPolicyURL, "cert-policy-url", 2, "@" }, + { oShowPolicyURL, "show-policy-url", 0, "@" }, + { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, + { oShowNotation, "show-notation", 0, "@" }, + { oNoShowNotation, "no-show-notation", 0, "@" }, + { oSigKeyserverURL, "sig-keyserver-url", 2, "@" }, + { oComment, "comment", 2, "@" }, + { oDefaultComment, "default-comment", 0, "@" }, + { oNoComments, "no-comments", 0, "@" }, + { oEmitVersion, "emit-version", 0, "@"}, + { oNoEmitVersion, "no-emit-version", 0, "@"}, + { oNoEmitVersion, "no-version", 0, "@"}, /* alias */ + { oNotDashEscaped, "not-dash-escaped", 0, "@" }, + { oEscapeFrom, "escape-from-lines", 0, "@" }, + { oNoEscapeFrom, "no-escape-from-lines", 0, "@" }, + { oLockOnce, "lock-once", 0, "@" }, + { oLockMultiple, "lock-multiple", 0, "@" }, + { oLockNever, "lock-never", 0, "@" }, + { oLoggerFD, "logger-fd",1, "@" }, +#ifdef __riscos__ + { oLoggerFile, "logger-file",2, "@" }, +#endif /* __riscos__ */ + { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" }, + { oUtf8Strings, "utf8-strings", 0, "@" }, + { oNoUtf8Strings, "no-utf8-strings", 0, "@" }, + { oWithFingerprint, "with-fingerprint", 0, "@" }, + { oDisableCipherAlgo, "disable-cipher-algo", 2, "@" }, + { oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" }, + { oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" }, + { oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", 0, "@" }, + { oAllowFreeformUID, "allow-freeform-uid", 0, "@" }, + { oNoAllowFreeformUID, "no-allow-freeform-uid", 0, "@" }, + { oNoLiteral, "no-literal", 0, "@" }, + { oSetFilesize, "set-filesize", 20, "@" }, + { oHonorHttpProxy,"honor-http-proxy", 0, "@" }, + { oFastListMode,"fast-list-mode", 0, "@" }, + { oFixedListMode,"fixed-list-mode", 0, "@" }, + { oListOnly, "list-only", 0, "@"}, + { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" }, + { oIgnoreValidFrom, "ignore-valid-from", 0, "@" }, + { oIgnoreCrcError, "ignore-crc-error", 0,"@" }, + { oIgnoreMDCError, "ignore-mdc-error", 0,"@" }, + { oShowSessionKey, "show-session-key", 0, "@" }, + { oOverrideSessionKey, "override-session-key", 2, "@" }, + { oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, + { oAutoKeyRetrieve, "auto-key-retrieve", 0, "@" }, + { oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" }, + { oNoSigCache, "no-sig-cache", 0, "@" }, + { oNoSigCreateCheck, "no-sig-create-check", 0, "@" }, + { oAutoCheckTrustDB, "auto-check-trustdb", 0, "@"}, + { oNoAutoCheckTrustDB, "no-auto-check-trustdb", 0, "@"}, + { oMergeOnly, "merge-only", 0, "@" }, + { oAllowSecretKeyImport, "allow-secret-key-import", 0, "@" }, + { oTryAllSecrets, "try-all-secrets", 0, "@" }, + { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" }, + { oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" }, + { aDeleteSecretAndPublicKeys, "delete-secret-and-public-keys",256, "@" }, + { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"}, + { oPreservePermissions, "preserve-permissions", 0, "@"}, + { oDefaultPreferenceList, "default-preference-list", 2, "@"}, + { oPersonalCipherPreferences, "personal-cipher-preferences", 2, "@"}, + { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, + { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, + { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, + { oAgentProgram, "agent-program", 2 , "@" }, + { oDisplay, "display", 2, "@" }, + { oTTYname, "ttyname", 2, "@" }, + { oTTYtype, "ttytype", 2, "@" }, + { oLCctype, "lc-ctype", 2, "@" }, + { oLCmessages, "lc-messages", 2, "@" }, + { oGroup, "group", 2, "@" }, + { oStrict, "strict", 0, "@" }, + { oNoStrict, "no-strict", 0, "@" }, + { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" }, + { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" }, + { oEnableProgressFilter, "enable-progress-filter", 0, "@" }, + { oMultifile, "multifile", 0, "@" }, +{0} }; + + + +int g10_errors_seen = 0; + +static int utf8_strings = 0; +static int maybe_setuid = 1; + +static char *build_list( const char *text, char letter, + const char *(*mapf)(int), int (*chkf)(int) ); +static void set_cmd( enum cmd_and_opt_values *ret_cmd, + enum cmd_and_opt_values new_cmd ); +static void print_mds( const char *fname, int algo ); +static void add_notation_data( const char *string, int which ); +static void add_policy_url( const char *string, int which ); +static void add_keyserver_url( const char *string, int which ); +static void emergency_cleanup (void); + +#ifdef __riscos__ +RISCOS_GLOBAL_STATICS("GnuPG Heap") +#endif /* __riscos__ */ + +static int +pk_test_algo (int algo) +{ + return openpgp_pk_test_algo (algo, 0); +} + + +static const char * +my_strusage( int level ) +{ + static char *digests, *pubkeys, *ciphers, *zips; + const char *p; + switch( level ) { + case 11: p = "gpg (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: gpg [options] [files] (-h for help)"); + break; + case 41: p = + _("Syntax: gpg [options] [files]\n" + "sign, check, encrypt or decrypt\n" + "default operation depends on the input data\n"); + break; + + case 31: p = "\nHome: "; break; +#ifndef __riscos__ + case 32: p = opt.homedir; break; +#else /* __riscos__ */ + case 32: p = make_filename(opt.homedir, NULL); break; +#endif /* __riscos__ */ + case 33: p = _("\nSupported algorithms:\n"); break; + case 34: + if( !pubkeys ) + pubkeys = build_list(_("Pubkey: "), 0, gcry_pk_algo_name, + pk_test_algo ); + p = pubkeys; + break; + case 35: + if( !ciphers ) + ciphers = build_list(_("Cipher: "), 'S', gcry_cipher_algo_name, + openpgp_cipher_test_algo ); + p = ciphers; + break; + case 36: + if( !digests ) + digests = build_list(_("Hash: "), 'H', gcry_md_algo_name, + openpgp_md_test_algo ); + p = digests; + break; + case 37: + if( !zips ) + zips = build_list(_("Compression: "),'Z',compress_algo_to_string, + check_compress_algo); + p = zips; + break; + + default: p = NULL; + } + return p; +} + + +static char * +build_list( const char *text, char letter, + const char * (*mapf)(int), int (*chkf)(int) ) +{ + int i; + const char *s; + size_t n=strlen(text)+2; + char *list, *p, *line=NULL; + + if( maybe_setuid ) + gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* drop setuid */ + + for(i=0; i <= 110; i++ ) + if( !chkf(i) && (s=mapf(i)) ) + n += strlen(s) + 7 + 2; + list = xmalloc ( 21 + n ); *list = 0; + for(p=NULL, i=0; i <= 110; i++ ) { + if( !chkf(i) && (s=mapf(i)) ) { + if( !p ) { + p = stpcpy( list, text ); + line=p; + } + else + p = stpcpy( p, ", "); + + if(strlen(line)>60) { + int spaces=strlen(text); + + list = xrealloc(list,n+spaces+1); + /* realloc could move the block, so find the end again */ + p=list; + while(*p) + p++; + + p=stpcpy(p, "\n"); + line=p; + for(;spaces;spaces--) + p=stpcpy(p, " "); + } + + p = stpcpy(p, s ); + if(opt.verbose && letter) + { + char num[8]; + sprintf(num," (%c%d)",letter,i); + p = stpcpy(p,num); + } + } + } + if( p ) + p = stpcpy(p, "\n" ); + return list; +} + + +static void +i18n_init(void) +{ +#ifdef USE_SIMPLE_GETTEXT + set_gettext_file( PACKAGE_GT ); +#else +#ifdef ENABLE_NLS + setlocale( LC_ALL, "" ); + bindtextdomain( PACKAGE_GT, LOCALEDIR ); + textdomain( PACKAGE_GT ); +#endif +#endif +} + +static void +wrong_args( const char *text) +{ + fputs(_("usage: gpg [options] "),stderr); + fputs(text,stderr); + putc('\n',stderr); + g10_exit(2); +} + + +static void +log_set_strict (int yesno) +{ + /* FIXME-XXX*/ +} + +static char * +make_username( const char *string ) +{ + char *p; + if( utf8_strings ) + p = xstrdup (string); + else + p = native_to_utf8( string ); + return p; +} + + +/* + * same as add_to_strlist() but if is_utf8 is *not* set a conversion + * to UTF8 is done + */ +static STRLIST +add_to_strlist2 ( STRLIST *list, const char *string, int is_utf8) +{ + STRLIST sl; + + if (is_utf8) + sl = add_to_strlist( list, string ); + else + { + char *p = native_to_utf8( string ); + sl = add_to_strlist( list, p ); + xfree( p ); + } + return sl; +} + + +/* Setup the debugging. With a LEVEL of NULL only the active debug + flags are propagated to the subsystems. With LEVEL set, a specific + set of debug flags is set; thus overriding all flags already + set. */ +static void +set_debug (const char *level) +{ + if (!level) + ; + else if (!strcmp (level, "none")) + opt.debug = 0; + else if (!strcmp (level, "basic")) + opt.debug = DBG_MEMSTAT_VALUE; + else if (!strcmp (level, "advanced")) + opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE; + else if (!strcmp (level, "expert")) + opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE + |DBG_CACHE_VALUE|DBG_FILTER_VALUE|DBG_PACKET_VALUE); + else if (!strcmp (level, "guru")) + opt.debug = ~0; + else + { + log_error (_("invalid debug-level `%s' given\n"), level); + g10_exit (2); + } + + if (opt.debug & DBG_MEMORY_VALUE ) + memory_debug_mode = 1; + if (opt.debug & DBG_MEMSTAT_VALUE ) + memory_stat_debug_mode = 1; + if (opt.debug & DBG_MPI_VALUE) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); + if (opt.debug & DBG_CIPHER_VALUE ) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); + if (opt.debug & DBG_IOBUF_VALUE ) + iobuf_debug_mode = 1; +} + + +/* We need the home directory also in some other directories, so make + sure that both variables are always in sync. */ +static void +set_homedir (const char *dir) +{ + if (!dir) + dir = ""; + g10_opt_homedir = opt.homedir = dir; +} + + +static void +set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) +{ + enum cmd_and_opt_values cmd = *ret_cmd; + + if( !cmd || cmd == new_cmd ) + cmd = new_cmd; + else if( cmd == aSign && new_cmd == aEncr ) + cmd = aSignEncr; + else if( cmd == aEncr && new_cmd == aSign ) + cmd = aSignEncr; + else if( cmd == aSign && new_cmd == aSym ) + cmd = aSignSym; + else if( cmd == aSym && new_cmd == aSign ) + cmd = aSignSym; + else if( ( cmd == aSign && new_cmd == aClearsign ) + || ( cmd == aClearsign && new_cmd == aSign ) ) + cmd = aClearsign; + else { + log_error(_("conflicting commands\n")); + g10_exit(2); + } + + *ret_cmd = cmd; +} + + +static void add_group(char *string) +{ + char *name,*value; + struct groupitem *item; + STRLIST values=NULL; + + /* Break off the group name */ + name=strsep(&string,"="); + if(string==NULL) + { + log_error(_("no = sign found in group definition \"%s\"\n"),name); + return; + } + + trim_trailing_ws((unsigned char *)name,strlen(name)); + + /* Break apart the values */ + while ((value= strsep(&string," \t"))) + { + if (*value) + add_to_strlist2 (&values,value,utf8_strings); + } + + item=xmalloc (sizeof(struct groupitem)); + item->name=name; + item->values=values; + item->next=opt.grouplist; + + opt.grouplist=item; +} + +/* We need to check three things. + + 0) The homedir. It must be x00, a directory, and owned by the + user. + + 1) The options file. Okay unless it or its containing directory is + group or other writable or not owned by us. disable exec in this + case. + + 2) Extensions. Same as #2. + + Returns true if the item is unsafe. */ +static int +check_permissions(const char *path,int item) +{ +#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM) + static int homedir_cache=-1; + char *tmppath,*dir; + struct stat statbuf,dirbuf; + int homedir=0,ret=0,checkonly=0; + int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0; + + if(opt.no_perm_warn) + return 0; + + assert(item==0 || item==1 || item==2); + + /* extensions may attach a path */ + if(item==2 && path[0]!=DIRSEP_C) + { + if(strchr(path,DIRSEP_C)) + tmppath=make_filename(path,NULL); + else + tmppath=make_filename(GNUPG_LIBDIR,path,NULL); + } + else + tmppath=xstrdup (path); + + /* If the item is located in the homedir, but isn't the homedir, + don't continue if we already checked the homedir itself. This is + to avoid user confusion with an extra options file warning which + could be rectified if the homedir itself had proper + permissions. */ + if(item!=0 && homedir_cache>-1 + && ascii_strncasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0) + { + ret=homedir_cache; + goto end; + } + + /* It's okay if the file or directory doesn't exist */ + if(stat(tmppath,&statbuf)!=0) + { + ret=0; + goto end; + } + + /* Now check the enclosing directory. 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,&dirbuf)!=0 || !S_ISDIR(dirbuf.st_mode)) + { + /* Weird error */ + ret=1; + goto end; + } + + xfree (dir); + + /* Assume failure */ + ret=1; + + if(item==0) + { + /* The homedir must be x00, a directory, and owned by the user. */ + + if(S_ISDIR(statbuf.st_mode)) + { + if(statbuf.st_uid==getuid()) + { + if((statbuf.st_mode & (S_IRWXG|S_IRWXO))==0) + ret=0; + else + perm=1; + } + else + own=1; + + homedir_cache=ret; + } + } + else if(item==1 || item==2) + { + /* The options or extension file. Okay unless it or its + containing directory is group or other writable or not owned + by us or root. */ + + if(S_ISREG(statbuf.st_mode)) + { + if(statbuf.st_uid==getuid() || statbuf.st_uid==0) + { + if((statbuf.st_mode & (S_IWGRP|S_IWOTH))==0) + { + /* it's not writable, so make sure the enclosing + directory is also not writable */ + if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) + { + if((dirbuf.st_mode & (S_IWGRP|S_IWOTH))==0) + ret=0; + else + enc_dir_perm=1; + } + else + enc_dir_own=1; + } + else + { + /* it's writable, so the enclosing directory had + better not let people get to it. */ + if(dirbuf.st_uid==getuid() || dirbuf.st_uid==0) + { + if((dirbuf.st_mode & (S_IRWXG|S_IRWXO))==0) + ret=0; + else + perm=enc_dir_perm=1; /* unclear which one to fix! */ + } + else + enc_dir_own=1; + } + } + else + own=1; + } + } + else + BUG(); + + if(!checkonly) + { + if(own) + { + if(item==0) + log_info(_("WARNING: unsafe ownership on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe ownership on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe ownership on " + "extension \"%s\"\n"),tmppath); + } + if(perm) + { + if(item==0) + log_info(_("WARNING: unsafe permissions on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe permissions on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe permissions on " + "extension \"%s\"\n"),tmppath); + } + if(enc_dir_own) + { + if(item==0) + log_info(_("WARNING: unsafe enclosing directory ownership on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe enclosing directory ownership on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe enclosing directory ownership on " + "extension \"%s\"\n"),tmppath); + } + if(enc_dir_perm) + { + if(item==0) + log_info(_("WARNING: unsafe enclosing directory permissions on " + "homedir \"%s\"\n"),tmppath); + else if(item==1) + log_info(_("WARNING: unsafe enclosing directory permissions on " + "configuration file \"%s\"\n"),tmppath); + else + log_info(_("WARNING: unsafe enclosing directory permissions on " + "extension \"%s\"\n"),tmppath); + } + } + + end: + xfree (tmppath); + + if(homedir) + homedir_cache=ret; + + return ret; + +#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */ + + return 0; +} + +int +main( int argc, char **argv ) +{ + ARGPARSE_ARGS pargs; + iobuf_t a; + int rc=0; + int orig_argc; + char **orig_argv; + const char *fname; + char *username; + int may_coredump; + STRLIST sl, remusr= NULL, locusr=NULL; + STRLIST nrings=NULL, sec_nrings=NULL; + armor_filter_context_t afx; + int detached_sig = 0; + FILE *configfp = NULL; + char *configname = NULL; + const char *config_filename = NULL; + unsigned configlineno; + int parse_debug = 0; + int default_config = 1; + int default_keyring = 1; + int greeting = 0; + int nogreeting = 0; + char *logfile = NULL; + int use_random_seed = 1; + enum cmd_and_opt_values cmd = 0; + const char *debug_level = NULL; + const char *trustdb_name = NULL; + char *def_cipher_string = NULL; + char *def_digest_string = NULL; + char *def_compress_string = NULL; + char *cert_digest_string = NULL; + char *s2k_cipher_string = NULL; + char *s2k_digest_string = NULL; + char *pers_cipher_list = NULL; + char *pers_digest_list = NULL; + char *pers_compress_list = NULL; + int eyes_only=0; + int multifile=0; + int pwfd = -1; + int with_fpr = 0; /* make an option out of --fingerprint */ + int any_explicit_recipient = 0; + +#ifdef __riscos__ + riscos_global_defaults(); + opt.lock_once = 1; +#endif /* __riscos__ */ + + trap_unaligned(); + set_strusage (my_strusage); + gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); + /* We don't need any locking in libgcrypt unless we use any kind of + threading. */ + gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING); + /* Please note that we may running SUID(ROOT), so be very CAREFUL + * when adding any stuff between here and the call to + * secmem_init() somewhere after the option parsing + */ + log_set_prefix ("gpg", 1); + /* check that the libraries are suitable. Do it here because the + option parse may need services of the library */ + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) + { + log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + } + + gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); + + may_coredump = disable_core_dumps(); + gnupg_init_signals (0, emergency_cleanup); + create_dotlock (NULL); /* register locking cleanup */ + i18n_init(); + + opt.command_fd = -1; /* no command fd */ + opt.compress = -1; /* defaults to standard compress level */ + /* note: if you change these lines, look at oOpenPGP */ + opt.def_cipher_algo = 0; + opt.def_digest_algo = 0; + opt.cert_digest_algo = 0; + opt.def_compress_algo = -1; + opt.s2k_mode = 3; /* iterated+salted */ + opt.s2k_digest_algo = DIGEST_ALGO_SHA1; +#ifdef USE_CAST5 + opt.s2k_cipher_algo = CIPHER_ALGO_CAST5; +#else + opt.s2k_cipher_algo = CIPHER_ALGO_3DES; +#endif + opt.completes_needed = 1; + opt.marginals_needed = 3; + opt.max_cert_depth = 5; + opt.pgp2_workarounds = 1; + opt.force_v3_sigs = 1; + opt.escape_from = 1; + opt.import_options=IMPORT_SK2PK; + opt.export_options= + EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; + opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG; + opt.keyserver_options.export_options= + EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; + opt.keyserver_options.include_subkeys=1; + opt.keyserver_options.include_revoked=1; + opt.keyserver_options.try_dns_srv=1; + opt.verify_options= + VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION|VERIFY_SHOW_KEYSERVER; + opt.trust_model=TM_AUTO; + opt.mangle_dos_filenames = 1; + opt.use_agent = 1; + + set_homedir ( default_homedir () ); + + /* Check whether we have a config file on the commandline */ + orig_argc = argc; + orig_argv = argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ + while( arg_parse( &pargs, opts) ) { + if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll ) + parse_debug++; + else if( pargs.r_opt == oOptions ) { + /* yes there is one, so we do not try the default one, but + * read the option file when it is encountered at the commandline + */ + default_config = 0; + } + else if( pargs.r_opt == oNoOptions ) + default_config = 0; /* --no-options */ + else if( pargs.r_opt == oHomedir ) + set_homedir ( pargs.r.ret_str ); + else if( pargs.r_opt == oNoPermissionWarn ) + opt.no_perm_warn=1; + else if (pargs.r_opt == oStrict ) + { + opt.strict=1; + log_set_strict(1); + } + else if (pargs.r_opt == oNoStrict ) + { + opt.strict=0; + log_set_strict(0); + } + } + +#ifdef HAVE_DOSISH_SYSTEM + if ( strchr (opt.homedir,'\\') ) { + char *d, *buf = xmalloc (strlen (opt.homedir)+1); + const char *s = opt.homedir; + for (d=buf,s=opt.homedir; *s; s++) + *d++ = *s == '\\'? '/': *s; + *d = 0; + set_homedir (buf); + } +#endif + + /* Initialize the secure memory. */ + gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); + maybe_setuid = 0; + /* Okay, we are now working under our real uid */ + + /* malloc hooks go here ... */ + assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + + set_native_charset (NULL); /* Try to auto set the character set */ + + /* Try for a version specific config file first */ + if( default_config ) + { + char *name = xstrdup ("gpg" EXTSEP_S "conf-" SAFE_VERSION); + char *ver = name + strlen("gpg" EXTSEP_S "conf-"); + + do + { + if(configname) + { + char *tok; + + xfree (configname); + configname=NULL; + + if((tok=strrchr (ver,SAFE_VERSION_DASH))) + *tok='\0'; + else if((tok=strrchr (ver,SAFE_VERSION_DOT))) + *tok='\0'; + else + break; + } + + configname = make_filename (opt.homedir, name, NULL); + } + while ( access(configname,R_OK) ); + xfree(name); + + if (!access (configname, R_OK)) + { /* Print a warning when both config files are present. */ + char *p = make_filename(opt.homedir, "options", NULL ); + if (!access (p, R_OK)) + log_info (_("NOTE: old default options file `%s' ignored\n"), p); + xfree (p); + } + else + { /* Keep on using the old default one. */ + xfree (configname); + configname = make_filename(opt.homedir, "options", NULL ); + } + } + argc = orig_argc; + argv = orig_argv; + pargs.argc = &argc; + pargs.argv = &argv; + pargs.flags= 1; /* do not remove the args */ + + /* By this point we have a homedir, and cannot change it. */ + check_permissions(opt.homedir,0); + + next_pass: + if( configname ) { + if(check_permissions(configname,1)) + { + /* If any options file is unsafe, then disable any external + programs for keyserver calls or photo IDs. Since the + external program to call is set in the options file, a + unsafe options file can lead to an arbitrary program + being run. */ + + opt.exec_disable=1; + } + + configlineno = 0; + configfp = fopen( configname, "r" ); + if( !configfp ) { + if( default_config ) { + if( parse_debug ) + log_info(_("NOTE: no default option file `%s'\n"), + configname ); + } + else { + log_error(_("option file `%s': %s\n"), + configname, strerror(errno) ); + g10_exit(2); + } + xfree (configname); configname = NULL; + } + if( parse_debug && configname ) + log_info(_("reading options from `%s'\n"), configname ); + default_config = 0; + } + + while( optfile_parse( configfp, configname, &configlineno, + &pargs, opts) ) { + switch( pargs.r_opt ) { + case aCheckKeys: set_cmd( &cmd, aCheckKeys); break; + case aListPackets: set_cmd( &cmd, aListPackets); break; + case aImport: set_cmd( &cmd, aImport); break; + case aFastImport: set_cmd( &cmd, aFastImport); break; + case aSendKeys: set_cmd( &cmd, aSendKeys); break; + case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; + case aSearchKeys: set_cmd( &cmd, aSearchKeys); break; + case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; + case aExport: set_cmd( &cmd, aExport); break; + case aExportAll: set_cmd( &cmd, aExportAll); break; + case aListKeys: set_cmd( &cmd, aListKeys); break; + case aListSigs: set_cmd( &cmd, aListSigs); break; + case aExportSecret: set_cmd( &cmd, aExportSecret); break; + case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break; + case aDeleteSecretKeys: set_cmd( &cmd, aDeleteSecretKeys); + greeting=1; break; + case aDeleteSecretAndPublicKeys: + set_cmd( &cmd, aDeleteSecretAndPublicKeys); + greeting=1; + break; + case aDeleteKeys: set_cmd( &cmd, aDeleteKeys); greeting=1; break; + + case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; + case aSym: set_cmd( &cmd, aSym); break; + + case aDecryptFiles: multifile=1; /* fall through */ + case aDecrypt: set_cmd( &cmd, aDecrypt); break; + + case aEncrFiles: multifile=1; /* fall through */ + case aEncr: set_cmd( &cmd, aEncr); break; + + case aVerifyFiles: multifile=1; /* fall through */ + case aVerify: set_cmd( &cmd, aVerify); break; + + case aSign: set_cmd( &cmd, aSign ); break; + case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; + case aSignKey: set_cmd( &cmd, aSignKey); break; + case aLSignKey: set_cmd( &cmd, aLSignKey); break; + case aNRSignKey: set_cmd( &cmd, aNRSignKey); break; + case aNRLSignKey: set_cmd( &cmd, aNRLSignKey); break; + case aStore: set_cmd( &cmd, aStore); break; + case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break; + case aClearsign: set_cmd( &cmd, aClearsign); break; + case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; + case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; + + case aPrimegen: set_cmd( &cmd, aPrimegen); break; + case aGenRandom: set_cmd( &cmd, aGenRandom); break; + case aPrintMD: set_cmd( &cmd, aPrintMD); break; + case aPrintMDs: set_cmd( &cmd, aPrintMDs); break; + case aListTrustDB: set_cmd( &cmd, aListTrustDB); break; + case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break; + case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break; + case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break; + case aListTrustPath: set_cmd( &cmd, aListTrustPath); break; + case aDeArmor: set_cmd( &cmd, aDeArmor); break; + case aEnArmor: set_cmd( &cmd, aEnArmor); break; + case aListOwnerTrust: + deprecated_warning(configname,configlineno, + "--list-ownertrust","--export-ownertrust",""); + case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break; + case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break; + case aPipeMode: set_cmd( &cmd, aPipeMode); break; + case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; + + case aCardStatus: set_cmd (&cmd, aCardStatus); break; + case aCardEdit: set_cmd (&cmd, aCardEdit); break; + case aChangePIN: set_cmd (&cmd, aChangePIN); break; + case aGPGConfList: + set_cmd (&cmd, aGPGConfList); + nogreeting = 1; + break; + + case oArmor: opt.armor = 1; opt.no_armor=0; break; + case oOutput: opt.outfile = pargs.r.ret_str; break; + case oQuiet: opt.quiet = 1; break; + case oNoTTY: tty_no_terminal(1); break; + case oDryRun: opt.dry_run = 1; break; + case oInteractive: opt.interactive = 1; break; + case oVerbose: g10_opt_verbose++; + opt.verbose++; opt.list_sigs=1; break; + + case oLogFile: logfile = pargs.r.ret_str; break; + + case oBatch: opt.batch = 1; nogreeting = 1; break; + case oUseAgent: +#ifndef __riscos__ + opt.use_agent = 1; +#else /* __riscos__ */ + opt.use_agent = 0; + riscos_not_implemented("use-agent"); +#endif /* __riscos__ */ + break; + case oNoUseAgent: opt.use_agent = 0; break; + case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break; + case oAnswerYes: opt.answer_yes = 1; break; + case oAnswerNo: opt.answer_no = 1; break; + case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break; + case oPrimaryKeyring: + sl=append_to_strlist( &nrings, pargs.r.ret_str); + sl->flags=2; + break; + case oShowKeyring: opt.list_options|=LIST_SHOW_KEYRING; break; + case oDebug: opt.debug |= pargs.r.ret_ulong; break; + case oDebugAll: opt.debug = ~0; break; + case oDebugLevel: debug_level = pargs.r.ret_str; break; + case oStatusFD: + set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); + break; +#ifdef __riscos__ + case oStatusFile: + set_status_fd( iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + break; +#endif /* __riscos__ */ + case oAttributeFD: + set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1)); + break; +#ifdef __riscos__ + case oAttributeFile: + set_attrib_fd(iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + break; +#endif /* __riscos__ */ + case oLoggerFD: + log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1)); + break; +#ifdef __riscos__ + case oLoggerFile: + log_set_logfile( NULL, + iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + break; +#endif /* __riscos__ */ + case oWithFingerprint: + opt.with_fingerprint = 1; + with_fpr=1; /*fall thru*/ + case oFingerprint: opt.fingerprint++; break; + case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break; + case oOptions: + /* config files may not be nested (silently ignore them) */ + if( !configfp ) { + xfree (configname); + configname = xstrdup (pargs.r.ret_str); + goto next_pass; + } + break; + case oNoArmor: opt.no_armor=1; opt.armor=0; break; + case oNoDefKeyring: default_keyring = 0; break; + case oDefCertCheckLevel: opt.def_cert_check_level=pargs.r.ret_int; break; + case oNoGreeting: nogreeting = 1; break; + case oNoVerbose: g10_opt_verbose = 0; + opt.verbose = 0; opt.list_sigs=0; break; + /* disabled for now: + case oQuickRandom: quick_random_gen(1); break; */ + case oSKComments: opt.sk_comments=1; break; + case oNoSKComments: opt.sk_comments=0; break; + case oEmitVersion: opt.no_version=0; break; + case oNoEmitVersion: opt.no_version=1; break; + case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; + case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break; + case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break; + case oTrustDBName: trustdb_name = pargs.r.ret_str; break; + case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break; + case oDefRecipient: + if( *pargs.r.ret_str ) + opt.def_recipient = make_username(pargs.r.ret_str); + break; + case oDefRecipientSelf: + xfree (opt.def_recipient); opt.def_recipient = NULL; + opt.def_recipient_self = 1; + break; + case oNoDefRecipient: + xfree (opt.def_recipient); opt.def_recipient = NULL; + opt.def_recipient_self = 0; + break; + case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */ + case oHomedir: break; + case oNoBatch: opt.batch = 0; break; + case oWithKeyData: opt.with_key_data=1; /* fall thru */ + case oWithColons: opt.with_colons=':'; break; + + case oSkipVerify: opt.skip_verify=1; break; + case oCompressKeys: opt.compress_keys = 1; break; + case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break; + /* There are many programs (like mutt) that call gpg with + --always-trust so keep this option around for a long + time. */ + case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break; + case oTrustModel: + if(ascii_strcasecmp(pargs.r.ret_str,"pgp")==0) + opt.trust_model=TM_PGP; + else if(ascii_strcasecmp(pargs.r.ret_str,"classic")==0) + opt.trust_model=TM_CLASSIC; + else if(ascii_strcasecmp(pargs.r.ret_str,"always")==0) + opt.trust_model=TM_ALWAYS; + else if(ascii_strcasecmp(pargs.r.ret_str,"auto")==0) + opt.trust_model=TM_AUTO; + else + log_error("unknown trust model \"%s\"\n",pargs.r.ret_str); + break; + case oForceOwnertrust: + log_info(_("NOTE: %s is not for normal use!\n"), + "--force-ownertrust"); + opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str); + if(opt.force_ownertrust==-1) + { + log_error("invalid ownertrust \"%s\"\n",pargs.r.ret_str); + opt.force_ownertrust=0; + } + break; + case oLoadExtension: +#ifndef __riscos__ +#if defined(USE_DYNAMIC_LINKING) || defined(_WIN32) + if(check_permissions(pargs.r.ret_str,2)) + log_info(_("cipher extension \"%s\" not loaded due to " + "unsafe permissions\n"),pargs.r.ret_str); + else + register_cipher_extension(orig_argc? *orig_argv:NULL, + pargs.r.ret_str); +#endif +#else /* __riscos__ */ + riscos_not_implemented("load-extension"); +#endif /* __riscos__ */ + break; + case oRFC1991: + opt.compliance = CO_RFC1991; + opt.force_v4_certs = 0; + opt.escape_from = 1; + break; + case oRFC2440: + case oOpenPGP: + /* TODO: When 2440bis becomes a RFC, these may need + changing. */ + opt.compliance = CO_RFC2440; + opt.allow_non_selfsigned_uid = 1; + opt.allow_freeform_uid = 1; + opt.pgp2_workarounds = 0; + opt.escape_from = 0; + opt.force_v3_sigs = 0; + opt.compress_keys = 0; /* not mandated but we do it */ + opt.compress_sigs = 0; /* ditto. */ + opt.not_dash_escaped = 0; + opt.def_cipher_algo = 0; + opt.def_digest_algo = 0; + opt.cert_digest_algo = 0; + opt.def_compress_algo = -1; + opt.s2k_mode = 3; /* iterated+salted */ + opt.s2k_digest_algo = DIGEST_ALGO_SHA1; + opt.s2k_cipher_algo = CIPHER_ALGO_3DES; + break; + case oPGP2: opt.compliance = CO_PGP2; break; + case oPGP6: opt.compliance = CO_PGP6; break; + case oPGP7: opt.compliance = CO_PGP7; break; + case oPGP8: opt.compliance = CO_PGP8; break; + case oGnuPG: opt.compliance = CO_GNUPG; break; + case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; + case oCompressSigs: opt.compress_sigs = 1; break; + case oSetFilename: opt.set_filename = pargs.r.ret_str; break; + case oForYourEyesOnly: eyes_only = 1; break; + case oNoForYourEyesOnly: eyes_only = 0; break; + case oSetPolicyURL: + add_policy_url(pargs.r.ret_str,0); + add_policy_url(pargs.r.ret_str,1); + break; + case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break; + case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break; + case oShowPolicyURL: + opt.list_options|=LIST_SHOW_POLICY; + opt.verify_options|=VERIFY_SHOW_POLICY; + break; + case oNoShowPolicyURL: + opt.list_options&=~LIST_SHOW_POLICY; + opt.verify_options&=~VERIFY_SHOW_POLICY; + break; + case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; + case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; + + case oComment: add_to_strlist(&opt.comments,pargs.r.ret_str); break; + case oDefaultComment: + deprecated_warning(configname,configlineno, + "--default-comment","--no-comments",""); + /* fall through */ + case oNoComments: + free_strlist(opt.comments); + opt.comments=NULL; + break; + + case oThrowKeyid: opt.throw_keyid = 1; break; + case oNoThrowKeyid: opt.throw_keyid = 0; break; + case oShowPhotos: + opt.list_options|=LIST_SHOW_PHOTOS; + opt.verify_options|=VERIFY_SHOW_PHOTOS; + break; + case oNoShowPhotos: + opt.list_options&=~LIST_SHOW_PHOTOS; + opt.verify_options&=~VERIFY_SHOW_PHOTOS; + break; + case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break; + case oForceV3Sigs: opt.force_v3_sigs = 1; break; + case oNoForceV3Sigs: opt.force_v3_sigs = 0; break; + case oForceV4Certs: opt.force_v4_certs = 1; break; + case oNoForceV4Certs: opt.force_v4_certs = 0; break; + case oForceMDC: opt.force_mdc = 1; break; + case oNoForceMDC: opt.force_mdc = 0; break; + case oDisableMDC: opt.disable_mdc = 1; break; + case oNoDisableMDC: opt.disable_mdc = 0; break; + case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; + case oS2KDigest: s2k_digest_string = xstrdup (pargs.r.ret_str); break; + case oS2KCipher: s2k_cipher_string = xstrdup (pargs.r.ret_str); break; + case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break; + case oNoEncryptTo: opt.no_encrypt_to = 1; break; + case oEncryptTo: /* store the recipient in the second list */ + sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + sl->flags = 1; + break; + case oHiddenEncryptTo: /* store the recipient in the second list */ + sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + sl->flags = 1|2; + break; + case oRecipient: /* store the recipient */ + add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + any_explicit_recipient = 1; + break; + case oHiddenRecipient: /* store the recipient with a flag */ + sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); + sl->flags = 2; + any_explicit_recipient = 1; + break; + case oTextmodeShort: opt.textmode = 2; break; + case oTextmode: opt.textmode=1; break; + case oNoTextmode: opt.textmode=0; break; + case oExpert: opt.expert = 1; break; + case oNoExpert: opt.expert = 0; break; + case oAskSigExpire: opt.ask_sig_expire = 1; break; + case oNoAskSigExpire: opt.ask_sig_expire = 0; break; + case oAskCertExpire: opt.ask_cert_expire = 1; break; + case oNoAskCertExpire: opt.ask_cert_expire = 0; break; + case oUser: /* store the local users */ + add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings ); + break; + case oCompress: opt.compress = pargs.r.ret_int; break; + case oPasswdFD: + pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); + opt.use_agent = 0; + break; +#ifdef __riscos__ + case oPasswdFile: + pwfd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); + break; +#endif /* __riscos__ */ + case oCommandFD: + opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0); + break; +#ifdef __riscos__ + case oCommandFile: + opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); + break; +#endif /* __riscos__ */ + case oCipherAlgo: def_cipher_string = xstrdup (pargs.r.ret_str); break; + case oDigestAlgo: def_digest_string = xstrdup (pargs.r.ret_str); break; + case oCompressAlgo: + /* If it is all digits, stick a Z in front of it for + later. This is for backwards compatibility with + versions that took the compress algorithm number. */ + { + char *pt=pargs.r.ret_str; + while(*pt) + { + if(!isdigit(*pt)) + break; + + pt++; + } + + if(*pt=='\0') + { + def_compress_string=xmalloc (strlen(pargs.r.ret_str)+2); + strcpy(def_compress_string,"Z"); + strcat(def_compress_string,pargs.r.ret_str); + } + else + def_compress_string = xstrdup (pargs.r.ret_str); + } + break; + case oCertDigestAlgo: cert_digest_string = xstrdup (pargs.r.ret_str); break; + case oNoSecmemWarn: + gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); + break; + case oNoPermissionWarn: opt.no_perm_warn=1; break; + case oNoMDCWarn: opt.no_mdc_warn=1; break; + case oCharset: + if( set_native_charset( pargs.r.ret_str ) ) + log_error(_("%s is not a valid character set\n"), + pargs.r.ret_str); + break; + case oNotDashEscaped: opt.not_dash_escaped = 1; break; + case oEscapeFrom: opt.escape_from = 1; break; + case oNoEscapeFrom: opt.escape_from = 0; break; + case oLockOnce: opt.lock_once = 1; break; + case oLockNever: disable_dotlock(); break; + case oLockMultiple: +#ifndef __riscos__ + opt.lock_once = 0; +#else /* __riscos__ */ + riscos_not_implemented("lock-multiple"); +#endif /* __riscos__ */ + break; + case oKeyServer: + opt.keyserver_uri=xstrdup (pargs.r.ret_str); + if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno)) + log_error(_("could not parse keyserver URI\n")); + break; + case oKeyServerOptions: + parse_keyserver_options(pargs.r.ret_str); + break; + case oImportOptions: + if(!parse_import_options(pargs.r.ret_str,&opt.import_options)) + { + if(configname) + log_error(_("%s:%d: invalid import options\n"), + configname,configlineno); + else + log_error(_("invalid import options\n")); + } + break; + case oExportOptions: + if(!parse_export_options(pargs.r.ret_str,&opt.export_options)) + { + if(configname) + log_error(_("%s:%d: invalid export options\n"), + configname,configlineno); + else + log_error(_("invalid export options\n")); + } + break; + case oListOptions: + { + struct parse_options lopts[]= + { + {"show-photos",LIST_SHOW_PHOTOS}, + {"show-policy-url",LIST_SHOW_POLICY}, + {"show-notation",LIST_SHOW_NOTATION}, + {"show-keyserver-url",LIST_SHOW_KEYSERVER}, + {"show-validity",LIST_SHOW_VALIDITY}, + {"show-long-keyid",LIST_SHOW_LONG_KEYID}, + {"show-keyring",LIST_SHOW_KEYRING}, + {"show-sig-expire",LIST_SHOW_SIG_EXPIRE}, + {NULL,0} + }; + + if(!parse_options(pargs.r.ret_str,&opt.list_options,lopts)) + { + if(configname) + log_error(_("%s:%d: invalid list options\n"), + configname,configlineno); + else + log_error(_("invalid list options\n")); + } + } + break; + case oVerifyOptions: + { + struct parse_options vopts[]= + { + {"show-photos",VERIFY_SHOW_PHOTOS}, + {"show-policy-url",VERIFY_SHOW_POLICY}, + {"show-notation",VERIFY_SHOW_NOTATION}, + {"show-keyserver-url",VERIFY_SHOW_KEYSERVER}, + {"show-validity",VERIFY_SHOW_VALIDITY}, + {"show-long-keyid",VERIFY_SHOW_LONG_KEYID}, + {NULL,0} + }; + + if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts)) + { + if(configname) + log_error(_("%s:%d: invalid verify options\n"), + configname,configlineno); + else + log_error(_("invalid verify options\n")); + } + } + break; + case oTempDir: opt.temp_dir=pargs.r.ret_str; break; + case oExecPath: + if(set_exec_path(pargs.r.ret_str,0)) + log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str); + else + opt.exec_path_set=1; + break; + case oSetNotation: + add_notation_data( pargs.r.ret_str, 0 ); + add_notation_data( pargs.r.ret_str, 1 ); + break; + case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break; + case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break; + case oShowNotation: + opt.list_options|=LIST_SHOW_NOTATION; + opt.verify_options|=VERIFY_SHOW_NOTATION; + break; + case oNoShowNotation: + opt.list_options&=~LIST_SHOW_NOTATION; + opt.verify_options&=~VERIFY_SHOW_NOTATION; + break; + case oUtf8Strings: utf8_strings = 1; break; + case oNoUtf8Strings: utf8_strings = 0; break; + case oDisableCipherAlgo: + { + int algo = gcry_cipher_map_name (pargs.r.ret_str); + gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, + &algo, sizeof algo); + } + break; + case oDisablePubkeyAlgo: + { + int algo = gcry_pk_map_name (pargs.r.ret_str); + gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, + &algo, sizeof algo ); + } + break; + case oNoSigCache: opt.no_sig_cache = 1; break; + case oNoSigCreateCheck: opt.no_sig_create_check = 1; break; + case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break; + case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; + case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; + case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; + case oNoLiteral: opt.no_literal = 1; break; + case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; + case oHonorHttpProxy: + opt.keyserver_options.honor_http_proxy = 1; + deprecated_warning(configname,configlineno, + "--honor-http-proxy", + "--keyserver-options ", + "honor-http-proxy"); + break; + case oFastListMode: opt.fast_list_mode = 1; break; + case oFixedListMode: opt.fixed_list_mode = 1; break; + case oListOnly: opt.list_only=1; break; + case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; + case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; + case oIgnoreCrcError: opt.ignore_crc_error = 1; break; + case oIgnoreMDCError: opt.ignore_mdc_error = 1; break; + case oNoRandomSeedFile: use_random_seed = 0; break; + case oAutoKeyRetrieve: + case oNoAutoKeyRetrieve: + opt.keyserver_options.auto_key_retrieve= + (pargs.r_opt==oAutoKeyRetrieve); + deprecated_warning(configname,configlineno, + pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve": + "--no-auto-key-retrieve","--keyserver-options ", + pargs.r_opt==oAutoKeyRetrieve?"auto-key-retrieve": + "no-auto-key-retrieve"); + break; + case oShowSessionKey: opt.show_session_key = 1; break; + case oOverrideSessionKey: + opt.override_session_key = pargs.r.ret_str; + break; + case oMergeOnly: opt.merge_only = 1; break; + case oAllowSecretKeyImport: /* obsolete */ break; + case oTryAllSecrets: opt.try_all_secrets = 1; break; + case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break; + case oEnableSpecialFilenames: + iobuf_enable_special_filenames (1); + break; + case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break; + case oAutoCheckTrustDB: opt.no_auto_check_trustdb=0; break; + case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break; + case oPreservePermissions: opt.preserve_permissions=1; break; + case oDefaultPreferenceList: + opt.def_preference_list = pargs.r.ret_str; + break; + case oPersonalCipherPreferences: + pers_cipher_list=pargs.r.ret_str; + break; + case oPersonalDigestPreferences: + pers_digest_list=pargs.r.ret_str; + break; + case oPersonalCompressPreferences: + pers_compress_list=pargs.r.ret_str; + break; + case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; + case oDisplay: opt.display = pargs.r.ret_str; break; + case oTTYname: opt.ttyname = pargs.r.ret_str; break; + case oTTYtype: opt.ttytype = pargs.r.ret_str; break; + case oLCctype: opt.lc_ctype = pargs.r.ret_str; break; + case oLCmessages: opt.lc_messages = pargs.r.ret_str; break; + case oGroup: add_group(pargs.r.ret_str); break; + case oStrict: opt.strict=1; log_set_strict(1); break; + case oNoStrict: opt.strict=0; log_set_strict(0); break; + + case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break; + case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; + + case oEnableProgressFilter: opt.enable_progress_filter = 1; break; + case oMultifile: multifile=1; break; + + default : pargs.err = configfp? 1:2; break; + } + } + + if( configfp ) { + fclose( configfp ); + configfp = NULL; + config_filename = configname; /* Keep a copy of the config + file name. */ + configname = NULL; + goto next_pass; + } + xfree ( configname ); configname = NULL; + if( log_get_errorcount(0) ) + g10_exit(2); + if( nogreeting ) + greeting = 0; + + if( greeting ) { + fprintf(stderr, "%s %s; %s\n", + strusage(11), strusage(13), strusage(14) ); + fprintf(stderr, "%s\n", strusage(15) ); + } +#ifdef IS_DEVELOPMENT_VERSION + if( !opt.batch ) { + log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); + log_info("It is only intended for test purposes and should NOT be\n"); + log_info("used in a production environment or with production keys!\n"); + } +#endif + + log_info ("WARNING: This version of gpg is not very matured and\n"); + log_info ("WARNING: only intended for testing. Please keep using\n"); + log_info ("WARNING: gpg 1.2.x, 1.3.x or 1.4.x for OpenPGP\n"); + + /* FIXME: We should use the lggging to a file only in server mode; + however we have not yet implemetyed that thus we try to get + away with --batch as indication for logging to file required. */ + if (logfile && opt.batch) + { + log_set_file (logfile); + log_set_prefix (NULL, 1|2|4); + } + + if (opt.verbose > 2) + log_info ("using character set `%s'\n", get_native_charset ()); + + if( may_coredump && !opt.quiet ) + log_info(_("WARNING: program may create a core file!\n")); + + if (eyes_only) { + if (opt.set_filename) + log_info(_("WARNING: %s overrides %s\n"), + "--for-your-eyes-only","--set-filename"); + + opt.set_filename="_CONSOLE"; + } + + if (opt.no_literal) { + log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal"); + if (opt.textmode) + log_error(_("%s not allowed with %s!\n"), + "--textmode", "--no-literal" ); + if (opt.set_filename) + log_error(_("%s makes no sense with %s!\n"), + eyes_only?"--for-your-eyes-only":"--set-filename", + "--no-literal" ); + } + + if (opt.set_filesize) + log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize"); + if( opt.batch ) + tty_batchmode( 1 ); + + gcry_control (GCRYCTL_RESUME_SECMEM_WARN); + set_debug (debug_level); + + /* Do these after the switch(), so they can override settings. */ + if(PGP2) + { + int unusable=0; + + if(cmd==aSign && !detached_sig) + { + log_info(_("you can only make detached or clear signatures " + "while in --pgp2 mode\n")); + unusable=1; + } + else if(cmd==aSignEncr || cmd==aSignSym) + { + log_info(_("you can't sign and encrypt at the " + "same time while in --pgp2 mode\n")); + unusable=1; + } + else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym)) + { + log_info(_("you must use files (and not a pipe) when " + "working with --pgp2 enabled.\n")); + unusable=1; + } + else if(cmd==aEncr || cmd==aSym) + { + /* Everything else should work without IDEA (except using + a secret key encrypted with IDEA and setting an IDEA + preference, but those have their own error + messages). */ + + if(openpgp_cipher_test_algo (CIPHER_ALGO_IDEA)) + { + log_info(_("encrypting a message in --pgp2 mode requires " + "the IDEA cipher\n")); + idea_cipher_warn(1); + unusable=1; + } + else if(cmd==aSym) + { + /* This only sets IDEA for symmetric encryption + since it is set via select_algo_from_prefs for + pk encryption. */ + xfree (def_cipher_string); + def_cipher_string = xstrdup ("idea"); + } + + /* PGP2 can't handle the output from the textmode + filter, so we disable it for anything that could + create a literal packet (only encryption and + symmetric encryption, since we disable signing + above). */ + if(!unusable) + opt.textmode=0; + } + + if(unusable) + compliance_failure(); + else + { + opt.force_v4_certs = 0; + opt.sk_comments = 0; + opt.escape_from = 1; + opt.force_v3_sigs = 1; + opt.pgp2_workarounds = 1; + opt.ask_sig_expire = 0; + opt.ask_cert_expire = 0; + xfree (def_digest_string); + def_digest_string = xstrdup ("md5"); + opt.def_compress_algo = 1; + } + } + else if(PGP6) + { + opt.sk_comments=0; + opt.escape_from=1; + opt.force_v3_sigs=1; + opt.ask_sig_expire=0; + } + else if(PGP7) + { + opt.sk_comments=0; + opt.escape_from=1; + opt.force_v3_sigs=1; + opt.ask_sig_expire=0; + } + else if(PGP8) + { + opt.escape_from=1; + } + + /* must do this after dropping setuid, because string_to... + * may try to load an module */ + if( def_cipher_string ) { + opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string); + if(opt.def_cipher_algo==0 && + (ascii_strcasecmp(def_cipher_string,"idea")==0 + || ascii_strcasecmp(def_cipher_string,"s1")==0)) + idea_cipher_warn(1); + xfree (def_cipher_string); def_cipher_string = NULL; + if( openpgp_cipher_test_algo (opt.def_cipher_algo) ) + log_error(_("selected cipher algorithm is invalid\n")); + } + if( def_digest_string ) { + opt.def_digest_algo = gcry_md_map_name (def_digest_string); + xfree (def_digest_string); def_digest_string = NULL; + if( openpgp_md_test_algo (opt.def_digest_algo) ) + log_error(_("selected digest algorithm is invalid\n")); + } + if( def_compress_string ) { + opt.def_compress_algo = string_to_compress_algo(def_compress_string); + xfree (def_compress_string); def_compress_string = NULL; + if( check_compress_algo(opt.def_compress_algo) ) + log_error(_("selected compression algorithm is invalid\n")); + } + if( cert_digest_string ) { + opt.cert_digest_algo = gcry_md_map_name (cert_digest_string); + xfree (cert_digest_string); cert_digest_string = NULL; + if( openpgp_md_test_algo(opt.cert_digest_algo) ) + log_error(_("selected certification digest algorithm is invalid\n")); + } + if( s2k_cipher_string ) { + opt.s2k_cipher_algo = gcry_cipher_map_name (s2k_cipher_string); + xfree (s2k_cipher_string); s2k_cipher_string = NULL; + if( openpgp_cipher_test_algo (opt.s2k_cipher_algo) ) + log_error(_("selected cipher algorithm is invalid\n")); + } + if( s2k_digest_string ) { + opt.s2k_digest_algo = gcry_md_map_name (s2k_digest_string); + xfree (s2k_digest_string); s2k_digest_string = NULL; + if( openpgp_md_test_algo (opt.s2k_digest_algo) ) + log_error(_("selected digest algorithm is invalid\n")); + } + if( opt.completes_needed < 1 ) + log_error(_("completes-needed must be greater than 0\n")); + if( opt.marginals_needed < 2 ) + log_error(_("marginals-needed must be greater than 1\n")); + if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 ) + log_error(_("max-cert-depth must be in range 1 to 255\n")); + switch( opt.s2k_mode ) { + case 0: + log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n")); + break; + case 1: case 3: break; + default: + log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); + } + + if(opt.def_cert_check_level<0 || opt.def_cert_check_level>3) + log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n")); + + /* This isn't actually needed, but does serve to error out if the + string is invalid. */ + if(opt.def_preference_list && + keygen_set_std_prefs(opt.def_preference_list,0)) + log_error(_("invalid default preferences\n")); + + /* We provide defaults for the personal digest list */ + if(!pers_digest_list) + pers_digest_list="h2"; + + if(pers_cipher_list && + keygen_set_std_prefs(pers_cipher_list,PREFTYPE_SYM)) + log_error(_("invalid personal cipher preferences\n")); + + if(pers_digest_list && + keygen_set_std_prefs(pers_digest_list,PREFTYPE_HASH)) + log_error(_("invalid personal digest preferences\n")); + + if(pers_compress_list && + keygen_set_std_prefs(pers_compress_list,PREFTYPE_ZIP)) + log_error(_("invalid personal compress preferences\n")); + + /* We don't support all possible commands with multifile yet */ + if(multifile) + { + char *cmdname; + + switch(cmd) + { + case aSign: + cmdname="--sign"; + break; + case aClearsign: + cmdname="--clearsign"; + break; + case aDetachedSign: + cmdname="--detach-sign"; + break; + case aSym: + cmdname="--symmetric"; + break; + case aStore: + cmdname="--store"; + break; + default: + cmdname=NULL; + break; + } + + if(cmdname) + log_error(_("%s does not yet work with %s\n"),cmdname,"--multifile"); + } + + if( log_get_errorcount(0) ) + g10_exit(2); + + /* Check our chosen algorithms against the list of legal + algorithms. */ + + if(!GNUPG) + { + const char *badalg=NULL; + preftype_t badtype=PREFTYPE_NONE; + + if (opt.def_cipher_algo + && !algo_available (PREFTYPE_SYM,opt.def_cipher_algo,NULL)) + { + badalg = gcry_cipher_algo_name (opt.def_cipher_algo); + badtype = PREFTYPE_SYM; + } + else if (opt.def_digest_algo + && !algo_available (PREFTYPE_HASH,opt.def_digest_algo,NULL)) + { + badalg = gcry_md_algo_name (opt.def_digest_algo); + badtype = PREFTYPE_HASH; + } + else if (opt.cert_digest_algo + && !algo_available (PREFTYPE_HASH,opt.cert_digest_algo,NULL)) + { + badalg = gcry_md_algo_name (opt.cert_digest_algo); + badtype = PREFTYPE_HASH; + } + else if (opt.def_compress_algo!=-1 + && !algo_available (PREFTYPE_ZIP,opt.def_compress_algo,NULL)) + { + badalg = compress_algo_to_string (opt.def_compress_algo); + badtype = PREFTYPE_ZIP; + } + + if (badalg) + { + switch(badtype) + { + case PREFTYPE_SYM: + log_info(_("you may not use cipher algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + case PREFTYPE_HASH: + log_info(_("you may not use digest algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + case PREFTYPE_ZIP: + log_info(_("you may not use compression algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + default: + BUG(); + } + + compliance_failure(); + } + } + + /* set the random seed file */ + if( use_random_seed ) { + char *p = make_filename(opt.homedir, "random_seed", NULL ); + gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); + xfree (p); + } + + if( !cmd && opt.fingerprint && !with_fpr ) { + set_cmd( &cmd, aListKeys); + } + + /* Compression algorithm 0 means no compression at all */ + if( opt.def_compress_algo == 0) + opt.compress = 0; + + /* kludge to let -sat generate a clear text signature */ + if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign ) + cmd = aClearsign; + + if( opt.verbose > 1 ) + set_packet_list_mode(1); + + /* Add the keyrings, but not for some special commands. Also + avoid adding the secret keyring for a couple of commands to + avoid unneeded access in case the secrings are stored on a + floppy */ + if( cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfList ) + { + if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys + && cmd != aVerify && cmd != aSym) + { + if (!sec_nrings || default_keyring) /* add default secret rings */ + keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); + for (sl = sec_nrings; sl; sl = sl->next) + keydb_add_resource ( sl->d, 0, 1 ); + } + if( !nrings || default_keyring ) /* add default ring */ + keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0); + for(sl = nrings; sl; sl = sl->next ) + keydb_add_resource ( sl->d, sl->flags, 0 ); + } + FREE_STRLIST(nrings); + FREE_STRLIST(sec_nrings); + + + if( pwfd != -1 ) /* read the passphrase now. */ + read_passphrase_from_fd( pwfd ); + + fname = argc? *argv : NULL; + + switch( cmd ) { + case aPrimegen: + case aPrintMD: + case aPrintMDs: + case aGenRandom: + case aDeArmor: + case aEnArmor: + case aFixTrustDB: + case aCardStatus: + case aCardEdit: + case aChangePIN: + case aGPGConfList: + break; + case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; + case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; + default: rc = setup_trustdb(1, trustdb_name ); break; + } + if( rc ) + log_error(_("failed to initialize the TrustDB: %s\n"), gpg_strerror (rc)); + + + switch (cmd) { + case aStore: + case aSym: + case aSign: + case aSignSym: + case aClearsign: + if (!opt.quiet && any_explicit_recipient) + log_info (_("WARNING: recipients (-r) given " + "without using public key encryption\n")); + break; + default: + break; + } + + switch( cmd ) { + case aStore: /* only store the file */ + if( argc > 1 ) + wrong_args(_("--store [filename]")); + if( (rc = encode_store(fname)) ) + log_error ("\b%s: store failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + break; + case aSym: /* encrypt the given file only with the symmetric cipher */ + if( argc > 1 ) + wrong_args(_("--symmetric [filename]")); + if( (rc = encode_symmetric(fname)) ) + log_error ("\b%s: symmetric encryption failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + break; + + case aEncr: /* encrypt the given file */ + if(multifile) + encode_crypt_files(argc, argv, remusr); + else + { + if( argc > 1 ) + wrong_args(_("--encrypt [filename]")); + if( (rc = encode_crypt(fname,remusr)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + } + break; + + case aSign: /* sign the given file */ + sl = NULL; + if( detached_sig ) { /* sign all files */ + for( ; argc; argc--, argv++ ) + add_to_strlist( &sl, *argv ); + } + else { + if( argc > 1 ) + wrong_args(_("--sign [filename]")); + if( argc ) { + sl = xcalloc (1, sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + } + if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) + log_error("signing failed: %s\n", gpg_strerror (rc) ); + free_strlist(sl); + break; + + case aSignEncr: /* sign and encrypt the given file */ + if( argc > 1 ) + wrong_args(_("--sign --encrypt [filename]")); + if( argc ) { + sl = xcalloc (1, sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + else + sl = NULL; + if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) + log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); + free_strlist(sl); + break; + + case aSignSym: /* sign and conventionally encrypt the given file */ + if (argc > 1) + wrong_args(_("--sign --symmetric [filename]")); + rc = sign_symencrypt_file (fname, locusr); + if (rc) + log_error("%s: sign+symmetric failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + break; + + case aClearsign: /* make a clearsig */ + if( argc > 1 ) + wrong_args(_("--clearsign [filename]")); + if( (rc = clearsign_file(fname, locusr, NULL)) ) + log_error("%s: clearsign failed: %s\n", + print_fname_stdin(fname), gpg_strerror (rc) ); + break; + + case aVerify: + if(multifile) + { + if( (rc = verify_files( argc, argv ) )) + log_error("verify files failed: %s\n", gpg_strerror (rc) ); + } + else + { + if( (rc = verify_signatures( argc, argv ) )) + log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); + } + break; + + case aDecrypt: + if(multifile) + decrypt_messages(argc, argv); + else + { + if( argc > 1 ) + wrong_args(_("--decrypt [filename]")); + if( (rc = decrypt_message( fname ) )) + log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); + } + break; + + case aSignKey: /* sign the key given as argument */ + if( argc != 1 ) + wrong_args(_("--sign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 1 ); + xfree (username); + break; + + case aLSignKey: + if( argc != 1 ) + wrong_args(_("--lsign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 2 ); + xfree (username); + break; + + case aNRSignKey: + if( argc != 1 ) + wrong_args(_("--nrsign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 3 ); + xfree (username); + break; + + case aNRLSignKey: + if( argc != 1 ) + wrong_args(_("--nrlsign-key user-id")); + username = make_username( fname ); + keyedit_menu(fname, locusr, NULL, 4 ); + xfree (username); + break; + + case aEditKey: /* Edit a key signature */ + if( !argc ) + wrong_args(_("--edit-key user-id [commands]")); + username = make_username( fname ); + if( argc > 1 ) { + sl = NULL; + for( argc--, argv++ ; argc; argc--, argv++ ) + append_to_strlist( &sl, *argv ); + keyedit_menu( username, locusr, sl, 0 ); + free_strlist(sl); + } + else + keyedit_menu(username, locusr, NULL, 0 ); + xfree (username); + break; + + case aDeleteKeys: + case aDeleteSecretKeys: + case aDeleteSecretAndPublicKeys: + sl = NULL; + /* I'm adding these in reverse order as add_to_strlist2 + reverses them again, and it's easier to understand in the + proper order :) */ + for( ; argc; argc-- ) + add_to_strlist2( &sl, argv[argc-1], utf8_strings ); + delete_keys(sl,cmd==aDeleteSecretKeys,cmd==aDeleteSecretAndPublicKeys); + free_strlist(sl); + break; + + case aCheckKeys: + opt.check_sigs = 1; + case aListSigs: + opt.list_sigs = 1; + case aListKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + public_key_list( sl ); + free_strlist(sl); + break; + case aListSecretKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + secret_key_list( sl ); + free_strlist(sl); + break; + + case aKeygen: /* generate a key */ + if( opt.batch ) { + if( argc > 1 ) + wrong_args("--gen-key [parameterfile]"); + generate_keypair( argc? *argv : NULL, NULL ); + } + else { + if( argc ) + wrong_args("--gen-key"); + generate_keypair(NULL, NULL); + } + break; + + case aFastImport: + opt.import_options |= IMPORT_FAST_IMPORT; + case aImport: + import_keys( argc? argv:NULL, argc, NULL, opt.import_options ); + break; + + case aExport: + case aExportAll: + case aSendKeys: + case aRecvKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + if( cmd == aSendKeys ) + rc=keyserver_export( sl ); + else if( cmd == aRecvKeys ) + rc=keyserver_import( sl ); + else + rc=export_pubkeys( sl, opt.export_options ); + if(rc) + { + if(cmd==aSendKeys) + log_error(_("keyserver send failed: %s\n"),gpg_strerror (rc)); + else if(cmd==aRecvKeys) + log_error(_("keyserver receive failed: %s\n"),gpg_strerror (rc)); + else + log_error(_("key export failed: %s\n"),gpg_strerror (rc)); + } + free_strlist(sl); + break; + + case aSearchKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + { + if (utf8_strings) + sl = append_to_strlist ( &sl, *argv ); + else + { + char *p = native_to_utf8 ( *argv ); + sl = append_to_strlist( &sl, p ); + xfree( p ); + } + } + + rc=keyserver_search( sl ); + if(rc) + log_error(_("keyserver search failed: %s\n"),gpg_strerror (rc)); + free_strlist(sl); + break; + + case aRefreshKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + rc=keyserver_refresh(sl); + if(rc) + log_error(_("keyserver refresh failed: %s\n"),gpg_strerror (rc)); + free_strlist(sl); + break; + + case aExportSecret: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + export_seckeys( sl ); + free_strlist(sl); + break; + + case aExportSecretSub: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + export_secsubkeys( sl ); + free_strlist(sl); + break; + + case aGenRevoke: + if( argc != 1 ) + wrong_args("--gen-revoke user-id"); + username = make_username(*argv); + gen_revoke( username ); + xfree ( username ); + break; + + case aDesigRevoke: + if( argc != 1 ) + wrong_args("--desig-revoke user-id"); + username = make_username(*argv); + gen_desig_revoke( username ); + xfree ( username ); + break; + + case aDeArmor: + if( argc > 1 ) + wrong_args("--dearmor [file]"); + rc = dearmor_file( argc? *argv: NULL ); + if( rc ) + log_error(_("dearmoring failed: %s\n"), gpg_strerror (rc)); + break; + + case aEnArmor: + if( argc > 1 ) + wrong_args("--enarmor [file]"); + rc = enarmor_file( argc? *argv: NULL ); + if( rc ) + log_error(_("enarmoring failed: %s\n"), gpg_strerror (rc)); + break; + + + case aPrimegen: +#if 0 /*FIXME-XXX*/ + { int mode = argc < 2 ? 0 : atoi(*argv); + + if( mode == 1 && argc == 2 ) { + mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1); + } + else if( mode == 2 && argc == 3 ) { + mpi_print( stdout, generate_elg_prime( + 0, atoi(argv[1]), + atoi(argv[2]), NULL,NULL ), 1); + } + else if( mode == 3 && argc == 3 ) { + gcry_mpi_t *factors; + mpi_print( stdout, generate_elg_prime( + 1, atoi(argv[1]), + atoi(argv[2]), NULL,&factors ), 1); + putchar('\n'); + mpi_print( stdout, factors[0], 1 ); /* print q */ + } + else if( mode == 4 && argc == 3 ) { + gcry_mpi_t g = mpi_alloc(1); + mpi_print( stdout, generate_elg_prime( + 0, atoi(argv[1]), + atoi(argv[2]), g, NULL ), 1); + putchar('\n'); + mpi_print( stdout, g, 1 ); + mpi_free(g); + } + else + wrong_args("--gen-prime mode bits [qbits] "); + putchar('\n'); + } +#endif + break; + + case aGenRandom: + { + int level = argc ? atoi(*argv):0; + int count = argc > 1 ? atoi(argv[1]): 0; + int endless = !count; + + if( argc < 1 || argc > 2 || level < 0 || level > 2 || count < 0 ) + wrong_args("--gen-random 0|1|2 [count]"); + + while( endless || count ) { + byte *p; + /* Wee need a multiple of 3, so that in case of + armored output we get a correct string. No + linefolding is done, as it is best to levae this to + other tools */ + size_t n = !endless && count < 99? count : 99; + + p = gcry_random_bytes (n, level); +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(stdout), O_BINARY ); +#endif + if (opt.armor) { + char *tmp = make_radix64_string (p, n); + fputs (tmp, stdout); + xfree (tmp); + if (n%3 == 1) + putchar ('='); + if (n%3) + putchar ('='); + } else { + fwrite( p, n, 1, stdout ); + } + xfree (p); + if( !endless ) + count -= n; + } + if (opt.armor) + putchar ('\n'); + } + break; + + case aPrintMD: + if( argc < 1) + wrong_args("--print-md algo [files]"); + { + int all_algos = (**argv=='*' && !(*argv)[1]); + int algo = all_algos? 0 : gcry_md_map_name (*argv); + + if( !algo && !all_algos ) + log_error(_("invalid hash algorithm `%s'\n"), *argv ); + else { + argc--; argv++; + if( !argc ) + print_mds(NULL, algo); + else { + for(; argc; argc--, argv++ ) + print_mds(*argv, algo); + } + } + } + break; + + case aPrintMDs: /* old option */ + if( !argc ) + print_mds(NULL,0); + else { + for(; argc; argc--, argv++ ) + print_mds(*argv,0); + } + break; + + case aListTrustDB: + if( !argc ) + list_trustdb(NULL); + else { + for( ; argc; argc--, argv++ ) + list_trustdb( *argv ); + } + break; + + case aUpdateTrustDB: + if( argc ) + wrong_args("--update-trustdb"); + update_trustdb(); + break; + + case aCheckTrustDB: + /* Old versions allowed for arguments - ignore them */ + check_trustdb(); + break; + + case aFixTrustDB: + log_error("this command is not yet implemented.\n"); + log_error("A workaround is to use \"--export-ownertrust\", remove\n"); + log_error("the trustdb file and do an \"--import-ownertrust\".\n" ); + break; + + case aListTrustPath: + if( !argc ) + wrong_args("--list-trust-path <user-ids>"); + for( ; argc; argc--, argv++ ) { + username = make_username( *argv ); + list_trust_path( username ); + xfree (username); + } + break; + + case aExportOwnerTrust: + if( argc ) + wrong_args("--export-ownertrust"); + export_ownertrust(); + break; + + case aImportOwnerTrust: + if( argc > 1 ) + wrong_args("--import-ownertrust [file]"); + import_ownertrust( argc? *argv:NULL ); + break; + + case aPipeMode: + if ( argc ) + wrong_args ("--pipemode"); + run_in_pipemode (); + break; + + case aRebuildKeydbCaches: + if (argc) + wrong_args ("--rebuild-keydb-caches"); + keydb_rebuild_caches (); + break; + + case aCardStatus: + if (argc) + wrong_args ("--card-status"); + card_status (stdout, NULL, 0); + break; + + case aCardEdit: + if (argc) + { + sl = NULL; + for (argc--, argv++ ; argc; argc--, argv++) + append_to_strlist (&sl, *argv); + card_edit (sl); + free_strlist (sl); + } + else + card_edit (NULL); + break; + + case aChangePIN: + if (!argc) + change_pin (0,1); + else if (argc == 1) + change_pin ( atoi (*argv), 1); + else + wrong_args ("--change-pin [no]"); + break; + + case aGPGConfList: + { /* List options and default values in the GPG Conf format. */ + + /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ + /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING + FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ +#define GC_OPT_FLAG_NONE 0UL + /* The RUNTIME flag for an option indicates that the option can be + changed at runtime. */ +#define GC_OPT_FLAG_RUNTIME (1UL << 3) + /* The DEFAULT flag for an option indicates that the option has a + default value. */ +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + /* The DEF_DESC flag for an option indicates that the option has a + default, which is described by the value of the default field. */ +#define GC_OPT_FLAG_DEF_DESC (1UL << 5) + /* The NO_ARG_DESC flag for an option indicates that the argument has + a default, which is described by the value of the ARGDEF field. */ +#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) + + if (!config_filename) + config_filename = make_filename (opt.homedir, "gpg.conf", NULL); + + printf ("gpgconf-gpg.conf:%lu:\"%s\n", + GC_OPT_FLAG_DEFAULT, config_filename); + + printf ("verbose:%lu:\n" + "quiet:%lu:\n" + "debug-level:%lu:\"none:\n" + "log-file:%lu:\n", + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_NONE, + GC_OPT_FLAG_DEFAULT, + GC_OPT_FLAG_NONE ); + printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); + + } + break; + + case aListPackets: + opt.list_packets=2; + default: + if( argc > 1 ) + wrong_args(_("[filename]")); + /* Issue some output for the unix newbie */ + if( !fname && !opt.outfile && isatty( fileno(stdin) ) + && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) ) + log_info(_("Go ahead and type your message ...\n")); + + if( !(a = iobuf_open(fname)) ) + log_error(_("can't open `%s'\n"), print_fname_stdin(fname)); + else { + + if( !opt.no_armor ) { + if( use_armor_filter( a ) ) { + memset( &afx, 0, sizeof afx); + iobuf_push_filter( a, armor_filter, &afx ); + } + } + if( cmd == aListPackets ) { + set_packet_list_mode(1); + opt.list_packets=1; + } + rc = proc_packets(NULL, a ); + if( rc ) + log_error("processing message failed: %s\n", gpg_strerror (rc) ); + iobuf_close(a); + } + break; + } + + /* cleanup */ + FREE_STRLIST(remusr); + FREE_STRLIST(locusr); + g10_exit(0); + return 8; /*NEVER REACHED*/ +} + +/* Note: This function is used by signal handlers!. */ +static void +emergency_cleanup (void) +{ + gcry_control (GCRYCTL_TERM_SECMEM ); +} + + +void +g10_exit( int rc ) +{ + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); + if (opt.debug & DBG_MEMSTAT_VALUE) + { + gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); + gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + } + if (opt.debug) + gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); + emergency_cleanup (); + rc = rc? rc : log_get_errorcount(0)? 2 : + g10_errors_seen? 1 : 0; + exit (rc ); +} + + +/* Pretty-print hex hashes. This assumes at least an 80-character + display, but there are a few other similar assumptions in the + display code. */ +static void +print_hex( MD_HANDLE md, int algo, const char *fname ) +{ + int i,n,count,indent=0; + const byte *p; + + if(fname) + indent=printf("%s: ",fname); + + if(indent>40) + { + printf("\n"); + indent=0; + } + + if(algo==DIGEST_ALGO_RMD160) + indent+=printf("RMD160 = "); + else if(algo>0) + indent+=printf("%6s = ", gcry_md_algo_name (algo)); + else + algo=abs(algo); + + count=indent; + + p = gcry_md_read (md, algo); + n = gcry_md_get_algo_dlen (algo); + + count+=printf("%02X",*p++); + + for(i=1;i<n;i++,p++) + { + if(n==16) + { + if(count+2>79) + { + printf("\n%*s",indent," "); + count=indent; + } + else + count+=printf(" "); + + if(!(i%8)) + count+=printf(" "); + } + else if (n==20) + { + if(!(i%2)) + { + if(count+4>79) + { + printf("\n%*s",indent," "); + count=indent; + } + else + count+=printf(" "); + } + + if(!(i%10)) + count+=printf(" "); + } + else + { + if(!(i%4)) + { + if(count+8>79) + { + printf("\n%*s",indent," "); + count=indent; + } + else + count+=printf(" "); + } + } + + count+=printf("%02X",*p); + } + + printf("\n"); +} + +static void +print_hashline( MD_HANDLE md, int algo, const char *fname ) +{ + int i, n; + const byte *p; + + if ( fname ) { + for (p = (const unsigned char *)fname; *p; p++ ) { + if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) + printf("%%%02X", *p ); + else + putchar( *p ); + } + } + putchar(':'); + printf("%d:", algo ); + p = gcry_md_read (md, algo ); + n = gcry_md_get_algo_dlen (algo); + for(i=0; i < n ; i++, p++ ) + printf("%02X", *p ); + putchar(':'); + putchar('\n'); +} + +static void +print_mds( const char *fname, int algo ) +{ + FILE *fp; + char buf[1024]; + size_t n; + MD_HANDLE md; + + if( !fname ) { + fp = stdin; +#ifdef HAVE_DOSISH_SYSTEM + setmode ( fileno(fp) , O_BINARY ); +#endif + } + else { + fp = fopen( fname, "rb" ); + } + if( !fp ) { + log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); + return; + } + + gcry_md_open (&md, 0, 0 ); + if( algo ) + gcry_md_enable ( md, algo ); + else { + gcry_md_enable (md, GCRY_MD_MD5 ); + gcry_md_enable (md, GCRY_MD_SHA1 ); + gcry_md_enable (md, GCRY_MD_RMD160 ); +#ifdef USE_SHA256 + gcry_md_enable (md, GCRY_MD_SHA256 ); +#endif +#ifdef USE_SHA512 + gcry_md_enable (md, GCRY_MD_SHA384 ); + gcry_md_enable (md, GCRY_MD_SHA512 ); +#endif + } + + while( (n=fread( buf, 1, DIM(buf), fp )) ) + gcry_md_write (md, buf, n); + if( ferror(fp) ) + log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); + else { + gcry_md_final (md); + if ( opt.with_colons ) { + if ( algo ) + print_hashline( md, algo, fname ); + else { + print_hashline( md, GCRY_MD_MD5, fname ); + print_hashline( md, GCRY_MD_SHA1, fname ); + print_hashline( md, GCRY_MD_RMD160, fname ); +#ifdef USE_SHA256 + print_hashline( md, GCRY_MD_SHA256, fname ); +#endif +#ifdef USE_SHA512 + print_hashline( md, GCRY_MD_SHA384, fname ); + print_hashline( md, GCRY_MD_SHA512, fname ); +#endif + } + } + else { + if( algo ) + print_hex(md,-algo,fname); + else { + print_hex( md, GCRY_MD_MD5, fname ); + print_hex( md, GCRY_MD_SHA1, fname ); + print_hex( md, GCRY_MD_RMD160, fname ); +#ifdef USE_SHA256 + print_hex( md, GCRY_MD_SHA256, fname ); +#endif +#ifdef USE_SHA512 + print_hex( md, GCRY_MD_SHA384, fname ); + print_hex( md, GCRY_MD_SHA512, fname ); +#endif + } + } + } + gcry_md_close (md); + + if( fp != stdin ) + fclose(fp); +} + + +/**************** + * Check the supplied name,value string and add it to the notation + * data to be used for signatures. which==0 for sig notations, and 1 + * for cert notations. +*/ +static void +add_notation_data( const char *string, int which ) +{ + const char *s; + STRLIST sl,*notation_data; + int critical=0; + int highbit=0; + int saw_at=0; + + if(which) + notation_data=&opt.cert_notation_data; + else + notation_data=&opt.sig_notation_data; + + if( *string == '!' ) { + critical = 1; + string++; + } + + /* If and when the IETF assigns some official name tags, we'll + have to add them here. */ + + for( s=string ; *s != '='; s++ ) + { + if( *s=='@') + saw_at=1; + + if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) ) + { + log_error(_("a notation name must have only printable characters " + "or spaces, and end with an '='\n") ); + return; + } + } + + if(!saw_at && !opt.expert) + { + log_error( + _("a user notation name must contain the '@' character\n")); + return; + } + + /* we only support printable text - therefore we enforce the use + * of only printable characters (an empty value is valid) */ + for( s++; *s ; s++ ) { + if( *s & 0x80 ) + highbit = 1; + else if( iscntrl(*s) ) { + log_error(_("a notation value must not use " + "any control characters\n") ); + return; + } + } + + if( highbit ) /* must use UTF8 encoding */ + sl = add_to_strlist2( notation_data, string, utf8_strings ); + else + sl = add_to_strlist( notation_data, string ); + + if( critical ) + sl->flags |= 1; +} + + +static void +add_policy_url( const char *string, int which ) +{ + int i,critical=0; + STRLIST sl; + + if(*string=='!') + { + string++; + critical=1; + } + + for(i=0;i<strlen(string);i++) + if(string[i]&0x80 || iscntrl(string[i])) + break; + + if(i==0 || i<strlen(string)) + { + if(which) + log_error(_("the given certification policy URL is invalid\n")); + else + log_error(_("the given signature policy URL is invalid\n")); + } + + if(which) + sl=add_to_strlist( &opt.cert_policy_url, string ); + else + sl=add_to_strlist( &opt.sig_policy_url, string ); + + if(critical) + sl->flags |= 1; +} + + +static void +add_keyserver_url( const char *string, int which ) +{ + int i,critical=0; + STRLIST sl; + + if(*string=='!') + { + string++; + critical=1; + } + + for(i=0;i<strlen(string);i++) + if(string[i]&0x80 || iscntrl(string[i])) + break; + + if(i==0 || i<strlen(string)) + { + if(which) + BUG(); + else + log_error(_("the given signature preferred" + " keyserver URL is invalid\n")); + } + + if(which) + BUG(); + else + sl=add_to_strlist( &opt.sig_keyserver_url, string ); + + if(critical) + sl->flags |= 1; +} + -- cgit v1.2.3 From 76cb368202383d28308b6a688348e11d4f5b507b Mon Sep 17 00:00:00 2001 From: Moritz Schulte <mo@g10code.com> Date: Sun, 9 Apr 2006 11:31:37 +0000 Subject: 2006-04-09 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_request_process): Removed FIXME mentioning a possible DoS attack. --- agent/ChangeLog | 5 +++++ agent/command-ssh.c | 13 ++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index ed4c8a4cb..a2c240e2e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2006-04-09 Moritz Schulte <moritz@g10code.com> + + * command-ssh.c (ssh_request_process): Removed FIXME mentioning a + possible DoS attack. + 2006-04-01 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_identity_register): Make KEY_GRIP_RAW be 20 diff --git a/agent/command-ssh.c b/agent/command-ssh.c index be2a8385d..23f083c2f 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -1,5 +1,5 @@ /* command-ssh.c - gpg-agent's ssh-agent emulation layer - * Copyright (C) 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -2677,10 +2677,13 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) secret key material. The response does not have to be stored in secure memory, since we never give out secret keys. - FIXME: This is a pretty good DoS. We only have a limited amount - of secure memory, we can't throw in everything we get from a - client -wk */ - + Note: we only have little secure memory, but there is NO + possibility of DoS here; only trusted clients are allowed to + connect to the agent. What could happen is that the agent + returns out-of-secure-memory errors on requests in case the + agent's owner floods his own agent with many large messages. + -moritz */ + /* Retrieve request. */ err = stream_read_string (stream_sock, 1, &request_data, &request_data_size); if (err) -- cgit v1.2.3 From c664309a0a9c2cd0aa0b1e10b488818ae7496f60 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 11 Apr 2006 13:53:21 +0000 Subject: Added command APDU --- doc/scdaemon.texi | 46 ++++++++++++++++++++ scd/ChangeLog | 9 ++++ scd/apdu.c | 4 +- scd/app-openpgp.c | 4 +- scd/command.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ scd/scdaemon.c | 2 + 6 files changed, 189 insertions(+), 4 deletions(-) diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 24a22355e..847001669 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -347,6 +347,8 @@ syncronizing access to a token between sessions. * Scdaemon RANDOM:: Return random bytes generate on-card. * Scdaemon PASSWD:: Change PINs. * Scdaemon CHECKPIN:: Perform a VERIFY operation. +* Scdaemon RESTART:: Restart connection +* Scdaemon APDU:: Send a verbatim APDU to the card @end menu @node Scdaemon SERIALNO @@ -553,3 +555,47 @@ and only if the retry counter is still at 3. @end table + +@node Scdaemon RESTART +@subsection Perform a RESTART operation. + +@example + RESTART +@end example + +Restart the current connection; this is a kind of warm reset. It +deletes the context used by this connection but does not actually +reset the card. + +This is used by gpg-agent to reuse a primary pipe connection and +may be used by clients to backup from a conflict in the serial +command; i.e. to select another application. + + + + +@node Scdaemon APDU +@subsection Send a verbatim APDU to the card. + +@example + APDU [--atr] [--more] [@var{hexstring}] +@end example + + +Send an APDU to the current reader. This command bypasses the high +level functions and sends the data directly to the card. +@var{hexstring} is expected to be a proper APDU. If @var{hexstring} is +not given no commands are send to the card; However the command will +implictly check whether the card is ready for use. + +Using the option @code{--atr} returns the ATR of the card as a status +message before any data like this: +@example + S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1 +@end example + +Using the option @code{--more} handles the card status word MORE_DATA +(61xx) and concatenate all reponses to one block. + + + diff --git a/scd/ChangeLog b/scd/ChangeLog index 27c362d10..53ef676f9 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2006-04-11 Werner Koch <wk@g10code.com> + + * command.c (hex_to_buffer): New. + (cmd_apdu): New. + +2006-04-03 Werner Koch <wk@g10code.com> + + * scdaemon.c [__GLIBC__]: Default to libpcsclite.so.1. + 2006-03-21 Werner Koch <wk@g10code.com> * command.c (cmd_pksign): Add --hash option. diff --git a/scd/apdu.c b/scd/apdu.c index adaaec612..d6bbdefd5 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -2848,8 +2848,8 @@ apdu_send_simple_kp (int slot, int class, int ins, int p0, int p1, HANDLE_MORE set to true this function will handle the MORE DATA status and return all APDUs concatenated with one status word at the end. The function does not return a regular status word but 0 - on success. If the slot is locked, the fucntion returns - immediately.*/ + on success. If the slot is locked, the function returns + immediately with an error. */ int apdu_send_direct (int slot, const unsigned char *apdudata, size_t apdudatalen, int handle_more, diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index fff709a08..5e9281a38 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -112,8 +112,8 @@ struct app_local_s { encoded S-expression encoding a public key. Might be NULL if key is not available. */ - size_t keylen; /* The length of the above S-expression. Thsi - is usullay only required for corss checks + size_t keylen; /* The length of the above S-expression. This + is usullay only required for cross checks because the length of an S-expression is implicitly available. */ } pk[3]; diff --git a/scd/command.c b/scd/command.c index 70a426959..2ed685587 100644 --- a/scd/command.c +++ b/scd/command.c @@ -156,6 +156,38 @@ has_option (const char *line, const char *name) } +/* Convert the STRING into a newly allocated buffer while translating + the hex numbers. Stops at the first invalid character. Blanks and + colons are allowed to separate the hex digits. Returns NULL on + error or a newly malloced buffer and its length in LENGTH. */ +static unsigned char * +hex_to_buffer (const char *string, size_t *r_length) +{ + unsigned char *buffer; + const char *s; + size_t n; + + buffer = xtrymalloc (strlen (string)+1); + if (!buffer) + return NULL; + for (s=string, n=0; *s; s++) + { + if (spacep (s) || *s == ':') + continue; + if (hexdigitp (s) && hexdigitp (s+1)) + { + buffer[n++] = xtoi_2 (s); + s++; + } + else + break; + } + *r_length = n; + return buffer; +} + + + /* Reset the card and free the application context. With SEND_RESET set to true actually send a RESET to the reader. */ static void @@ -1372,6 +1404,101 @@ cmd_restart (assuan_context_t ctx, char *line) } +/* APDU [--atr] [--more] [hexstring] + + Send an APDU to the current reader. This command bypasses the high + level functions and sends the data directly to the card. HEXSTRING + is expected to be a proper APDU. If HEXSTRING is not given no + commands are set to the card but the command will implictly check + whether the card is ready for use. + + Using the option "--atr" returns the ATR of the card as a status + message before any data like this: + S CARD-ATR 3BFA1300FF813180450031C173C00100009000B1 + + Using the option --more handles the card status word MORE_DATA + (61xx) and concatenate all reponses to one block. + + */ +static int +cmd_apdu (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + int rc; + int rc_is_assuan = 0; + unsigned char *apdu; + size_t apdulen; + int with_atr; + int handle_more; + + with_atr = has_option (line, "--atr"); + handle_more = has_option (line, "--more"); + + /* Skip over options. */ + while ( *line == '-' && line[1] == '-' ) + { + while (*line && !spacep (line)) + line++; + while (spacep (line)) + line++; + } + + if ( IS_LOCKED (ctrl) ) + return gpg_error (GPG_ERR_LOCKED); + + if ((rc = open_card (ctrl, NULL))) + return rc; + + if (with_atr) + { + unsigned char *atr; + size_t atrlen; + int i; + char hexbuf[400]; + + atr = apdu_get_atr (ctrl->reader_slot, &atrlen); + if (!atr || atrlen > sizeof hexbuf - 2 ) + { + rc = gpg_error (GPG_ERR_INV_CARD); + goto leave; + } + for (i=0; i < atrlen; i++) + sprintf (hexbuf+2*i, "%02X", atr[i]); + xfree (atr); + send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0); + } + + apdu = hex_to_buffer (line, &apdulen); + if (!apdu) + { + rc = gpg_error_from_errno (errno); + goto leave; + } + if (apdulen) + { + unsigned char *result = NULL; + size_t resultlen; + + rc = apdu_send_direct (ctrl->reader_slot, apdu, apdulen, handle_more, + &result, &resultlen); + if (rc) + log_error ("apdu_send_direct failed: %s\n", gpg_strerror (rc)); + else + { + rc_is_assuan = 1; + rc = assuan_send_data (ctx, result, resultlen); + xfree (result); + } + } + xfree (apdu); + + leave: + TEST_CARD_REMOVAL (ctrl, rc); + return rc_is_assuan? rc : map_to_assuan_status (rc); +} + + + /* Tell the assuan library about our commands */ @@ -1403,6 +1530,7 @@ register_commands (assuan_context_t ctx) { "UNLOCK", cmd_unlock }, { "GETINFO", cmd_getinfo }, { "RESTART", cmd_restart }, + { "APDU", cmd_apdu }, { NULL } }; int i, rc; diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 56c0d7600..e24b42132 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -139,6 +139,8 @@ static ARGPARSE_OPTS opts[] = { /* The card dirver we use by default for PC/SC. */ #if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__) #define DEFAULT_PCSC_DRIVER "winscard.dll" +#elif defined(__GLIBC__) +#define DEFAULT_PCSC_DRIVER "libpcsclite.so.1" #else #define DEFAULT_PCSC_DRIVER "libpcsclite.so" #endif -- cgit v1.2.3 From 751a3aeea79f2b5e7a21b768ea18e4cb22cfc2ca Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 14 Apr 2006 20:40:00 +0000 Subject: 2006-04-14 Marcus Brinkmann <marcus@g10code.de> * app.c (select_application): Cover up a slot mismatch error in case it happens (it shouldn't happen). (release_application): Use APP->slot. Lock the reader. (application_notify_card_removed): Lock the reader. --- scd/ChangeLog | 7 +++++++ scd/app.c | 47 ++++++++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 53ef676f9..8015359a5 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2006-04-14 Marcus Brinkmann <marcus@g10code.de> + + * app.c (select_application): Cover up a slot mismatch error in + case it happens (it shouldn't happen). + (release_application): Use APP->slot. Lock the reader. + (application_notify_card_removed): Lock the reader. + 2006-04-11 Werner Koch <wk@g10code.com> * command.c (hex_to_buffer): New. diff --git a/scd/app.c b/scd/app.c index 7f6a8cc9f..363e386ce 100644 --- a/scd/app.c +++ b/scd/app.c @@ -161,22 +161,25 @@ is_app_allowed (const char *name) void application_notify_card_removed (int slot) { + app_t app; + if (slot < 0 || slot >= DIM (lock_table)) return; + /* FIXME: We are ignoring any error value here. */ + lock_reader (slot); + /* Deallocate a saved application for that slot, so that we won't try to reuse it. If there is no saved application, set a flag so that we won't save the current state. */ - if (lock_table[slot].initialized) - { - app_t app = lock_table[slot].last_app; + app = lock_table[slot].last_app; - if (app) - { - lock_table[slot].last_app = NULL; - deallocate_app (app); - } + if (app) + { + lock_table[slot].last_app = NULL; + deallocate_app (app); } + unlock_reader (slot); } @@ -262,6 +265,8 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app) { if (app->slot != slot) log_bug ("slot mismatch %d/%d\n", app->slot, slot); + app->slot = slot; + app->ref_count++; *r_app = app; unlock_reader (slot); @@ -400,18 +405,22 @@ release_application (app_t app) return; /* Move the reference to the application in the lock table. */ - for (slot = 0; slot < DIM (lock_table); slot++) - if (lock_table[slot].initialized && lock_table[slot].app == app) - { - if (lock_table[slot].last_app) - deallocate_app (lock_table[slot].last_app); - lock_table[slot].last_app = lock_table[slot].app; - lock_table[slot].app = NULL; - return; - } + slot = app->slot; + /* FIXME: We are ignoring any error value. */ + lock_reader (slot); + if (lock_table[slot].app != app) + { + unlock_reader (slot); + log_bug ("app mismatch %p/%p\n", app, lock_table[slot].app); + deallocate_app (app); + return; + } - log_debug ("application missing in lock table - deallocating anyway\n"); - deallocate_app (app); + if (lock_table[slot].last_app) + deallocate_app (lock_table[slot].last_app); + lock_table[slot].last_app = lock_table[slot].app; + lock_table[slot].app = NULL; + unlock_reader (slot); } -- cgit v1.2.3 From 29b23dea9731e8f258211bc6fd733d205c18e2a8 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 19 Apr 2006 11:26:11 +0000 Subject: Merged with gpg 1.4.3 code. The gpg part does not yet build. --- ChangeLog | 9 + NEWS | 6 +- common/ChangeLog | 5 + common/homedir.c | 53 +- common/iobuf.h | 1 + common/util.h | 6 +- configure.ac | 43 +- g10/ChangeLog | 33 +- g10/Makefile.am | 11 +- g10/armor.c | 361 +++--- g10/build-packet.c | 629 ++++++---- g10/call-agent.c | 4 +- g10/card-util.c | 400 +++++-- g10/cipher.c | 76 +- g10/compress.c | 115 +- g10/dearmor.c | 40 +- g10/decrypt.c | 90 +- g10/delkey.c | 80 +- g10/encode.c | 464 +++++--- g10/encr-data.c | 109 +- g10/exec.c | 169 +-- g10/exec.h | 18 +- g10/export.c | 525 +++++--- g10/filter.h | 44 +- g10/free-packet.c | 107 +- g10/getkey.c | 966 ++++++++++----- g10/global.h | 31 - g10/gpg.c | 2196 ++++++++++++++++++++++------------ g10/gpg.h | 65 +- g10/gpgv.c | 143 ++- g10/helptext.c | 36 +- g10/import.c | 1294 +++++++++++++------- g10/kbnode.c | 19 +- g10/keydb.c | 233 ++-- g10/keydb.h | 62 +- g10/keyedit.c | 2750 ++++++++++++++++++++++++++++++------------ g10/keygen.c | 2977 ++++++++++++++++++++++++++++++---------------- g10/keyid.c | 679 +++++++---- g10/keylist.c | 778 +++++++----- g10/keyring.c | 216 ++-- g10/keyring.h | 7 +- g10/keyserver-internal.h | 45 +- g10/keyserver.c | 1302 +++++++++++++++----- g10/main.h | 152 ++- g10/mainproc.c | 1301 ++++++++++++-------- g10/mdfilter.c | 11 +- g10/misc.c | 1043 +++++++++++----- g10/openfile.c | 113 +- g10/options.h | 442 ++++--- g10/packet.h | 202 ++-- g10/parse-packet.c | 1101 +++++++++-------- g10/passphrase.c | 1185 ++++++++---------- g10/photoid.c | 107 +- g10/photoid.h | 5 +- g10/pipemode.c | 317 ----- g10/pkclist.c | 1177 +++++++++--------- g10/plaintext.c | 277 +++-- g10/progress.c | 13 +- g10/pubkey-enc.c | 304 ++--- g10/revoke.c | 174 ++- g10/seckey-cert.c | 259 ++-- g10/seskey.c | 193 +-- g10/sig-check.c | 354 +++--- g10/sign.c | 650 +++++----- g10/signal.c | 84 +- g10/skclist.c | 126 +- g10/status.c | 328 +++-- g10/status.h | 32 +- g10/tdbdump.c | 38 +- g10/tdbio.c | 325 ++--- g10/tdbio.h | 3 +- g10/textfilter.c | 71 +- g10/trustdb.c | 652 ++++++---- g10/trustdb.h | 20 +- g10/verify.c | 40 +- include/ChangeLog | 4 + include/cipher.h | 114 +- include/host2net.h | 9 +- include/http.h | 31 +- include/i18n.h | 5 +- include/keyserver.h | 10 +- include/memory.h | 2 + include/mpi.h | 2 + include/types.h | 9 +- include/util.h | 2 +- include/zlib-riscos.h | 3 +- jnlib/ChangeLog | 5 + jnlib/libjnlib-config.h | 5 +- jnlib/strlist.c | 36 +- jnlib/strlist.h | 3 +- 90 files changed, 17987 insertions(+), 10549 deletions(-) delete mode 100644 g10/global.h delete mode 100644 g10/pipemode.c diff --git a/ChangeLog b/ChangeLog index ea1ddf0e1..6e5228817 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-04-18 Werner Koch <wk@g10code.com> + + * configure.ac (PK_UID_CACHE_SIZE): New. + +2006-04-07 Werner Koch <wk@g10code.com> + + * configure.ac: Use new method to include the SVN revison. Now it + is the actual global revision number. + 2005-12-20 Werner Koch <wk@g10code.com> Released 1.9.20. diff --git a/NEWS b/NEWS index a003b3f90..6413242c6 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,14 @@ Noteworthy changes in version 1.9.21 ------------------------------------------------- + * [scdaemon] New command APDU. + * [scdaemon] Support for keypads of some readers. Tested only with SPR532. New option --disable-keypad. - * Support for CardMan 4040 PCMCIA reader. + * [scdaemon] Support for CardMan 4040 PCMCIA reader. - * Cards are not anymore reseted at the end of a connection. + * [scdaemon] Cards are not anymore reseted at the end of a connection. * [gpgsm] Kludge to allow use of Bundesnetzagentur issued certificates. diff --git a/common/ChangeLog b/common/ChangeLog index 4a184006a..54bce4538 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2006-04-18 Werner Koch <wk@g10code.com> + + * homedir.c (w32_shgetfolderpath): New. Taken from gpg 1.4.3. + (default_homedir): Use it. + 2005-10-08 Marcus Brinkmann <marcus@g10code.de> * signal.c (get_signal_name): Check value of HAVE_DECL_SYS_SIGLIST diff --git a/common/homedir.c b/common/homedir.c index ab5b1d270..a118cbac1 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -1,5 +1,5 @@ /* homedir.c - Setup the home directory. - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -41,6 +41,47 @@ #include "util.h" #include "sysutils.h" + +/* This is a helper function to load a Windows function from either of + one DLLs. */ +#ifdef HAVE_W32_SYSTEM +static HRESULT +w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) +{ + static int initialized; + static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR); + + if (!initialized) + { + static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL }; + void *handle; + int i; + + initialized = 1; + + for (i=0, handle = NULL; !handle && dllnames[i]; i++) + { + handle = dlopen (dllnames[i], RTLD_LAZY); + if (handle) + { + func = dlsym (handle, "SHGetFolderPathA"); + if (!func) + { + dlclose (handle); + handle = NULL; + } + } + } + } + + if (func) + return func (a,b,c,d,e); + else + return -1; +} +#endif /*HAVE_W32_SYSTEM*/ + + /* Set up the default home directory. The usual --homedir option should be parsed later. */ const char * @@ -56,15 +97,15 @@ default_homedir (void) { char path[MAX_PATH]; - /* fixme: It might be better to use LOCAL_APPDATA because this - is defined as "non roaming" and thus more likely to be kept + /* It might be better to use LOCAL_APPDATA because this is + defined as "non roaming" and thus more likely to be kept locally. For private keys this is desired. However, given that many users copy private keys anyway forth and back, - using a system roaming serives might be better than to let + using a system roaming services might be better than to let them do it manually. A security conscious user will anyway use the registry entry to have better control. */ - if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, - NULL, 0, path) >= 0) + if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) { char *tmp = xmalloc (strlen (path) + 6 +1); strcpy (stpcpy (tmp, path), "\\gnupg"); diff --git a/common/iobuf.h b/common/iobuf.h index b991717c2..def0a6506 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -36,6 +36,7 @@ #define IOBUFCTRL_USER 16 typedef struct iobuf_struct *iobuf_t; +typedef struct iobuf_struct *IOBUF; /* Compatibility with gpg 1.4. */ /* fixme: we should hide most of this stuff */ struct iobuf_struct diff --git a/common/util.h b/common/util.h index 1ced59b67..68f5222b5 100644 --- a/common/util.h +++ b/common/util.h @@ -59,6 +59,10 @@ #define xrealloc(a,b) gcry_xrealloc ((a),(b)) #define xstrdup(a) gcry_xstrdup ((a)) +/* For compatibility with gpg 1.4 we also define these: */ +#define xmalloc_clear(a) gcry_xcalloc (1, (a)) +#define xmalloc_secure_clear(a) gcry_xcalloc_secure (1, (a)) + /* A type to hold the ISO time. Note that this this is the same as the the KSBA type ksba_isotime_t. */ @@ -133,7 +137,7 @@ int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b); unsigned char *make_simple_sexp_from_hexstr (const char *line, size_t *nscanned); -/*-- homedir. c --*/ +/*-- homedir.c --*/ const char *default_homedir (void); diff --git a/configure.ac b/configure.ac index 9b0f04cb4..53cbc38fc 100644 --- a/configure.ac +++ b/configure.ac @@ -23,11 +23,16 @@ AC_PREREQ(2.52) min_automake_version="1.9.3" # Remember to change the version number immediately *after* a release. -# Uncomment the my_iscvs macro for non-released code. -m4_define(my_version, [1.9.21]) -m4_define(my_iscvs, yes) -AC_INIT([gnupg], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit( - [$Revision$],[Ra-z $:])]), [gnupg-devel@gnupg.org]) +# Set my_issvn to "yes" for non-released code. Remember to run an +# "svn up" and "autogen.sh" right before creating a distribution. +m4_define([my_version], [1.9.21]) +m4_define([my_issvn], [yes]) + + +m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ + || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q}')])) +AC_INIT([gnupg], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]), + [gnupg-devel@gnupg.org]) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not # sufficient. @@ -219,6 +224,34 @@ if test "$use_exec" = yes ; then AC_MSG_RESULT($enableval) fi + +dnl +dnl Check for the key/uid cache size. This can't be zero, but can be +dnl pretty small on embedded systems. +dnl +AC_MSG_CHECKING([for the size of the key and uid cache]) +AC_ARG_ENABLE(key-cache, + AC_HELP_STRING([--enable-key-cache=SIZE],[Set key cache to SIZE (default 4096)]),,enableval=4096) + +if test "$enableval" = "no"; then + enableval=5 +elif test "$enableval" = "yes" || test "$enableval" = ""; then + enableval=4096 +fi + +changequote(,)dnl +key_cache_size=`echo "$enableval" | sed 's/[A-Za-z]//g'` +changequote([,])dnl + +if test "$enableval" != "$key_cache_size" || test "$key_cache_size" -lt 5; then + AC_MSG_ERROR([invalid key-cache size]) +fi + +AC_MSG_RESULT($key_cache_size) +AC_DEFINE_UNQUOTED(PK_UID_CACHE_SIZE,$key_cache_size,[Size of the key and UID caches]) + + + dnl dnl Check whether we want to use Linux capabilities dnl diff --git a/g10/ChangeLog b/g10/ChangeLog index 0ae73b535..6259bdc20 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,33 @@ +2006-04-18 Werner Koch <wk@g10code.com> + + * tdbio.c (open_db, migrate_from_v2): Removed feature to migration + from old trustdb version 2. + + * gpg.c, mainproc.c: Removed pipemode feature. + + * status.c: Removed shared memory coprocess stuff + + Merged with current gpg 1.4.3 code. + + * keygen.c, keyid.c, misc.c, openfile.c, verify.c, trustdb.c + * textfilter.c, tdbio.c, tdbdump.c, status.c, skclist.c, signal.c + * sign.c, sig-check.c, seskey.c, seckey-cert.c, revoke.c + * pubkey-enc.c, progress.c, plaintext.c, pkclist.c, photoid.c + * passphrase.c, parse-packet.c, mdfilter.c, mainproc.c + * keyserver.c, keyring.c, keylist.c, keyedit.c, keydb.c, kbnode.c + * import.c, getkey.c, gpgv.c, helptext.c, free-packet.c + * build-packet.c, cipher.c, compress.c, dearmor.c, decrypt.c + * delkey.c, encr-data.c, encode.c, exec.c, export.c + * gpg.c, armor.c: Updated from gnupg-1.4.3 and merged back gcry and + gnupg-1.9 related changes. + * trustdb.h, tdbio.h, status.h, photoid.h, packet.h, options.h + * main.h, keyserver-internal.h, keyring.h, keydb.h, filter.h + * exec.h: Ditto. + * global.h: Removed after merging constants with gpg.h. + * comment.c, pipemode.c: Removed. + * card-util.c: Updated from gnupg-1.4.3. + * compress-bz2.c: New. + 2005-06-15 Werner Koch <wk@g10code.com> * g10.c (print_hashline, add_group): Fixes for signed/unsigned @@ -9007,7 +9037,8 @@ Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo) * pubkey-enc.c (get_session_key): rewritten - Copyright 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + Copyright 1998,1999,2000,2001,2002,2003,2004,2005, + 2006 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 diff --git a/g10/Makefile.am b/g10/Makefile.am index f371dab4a..1deacb9f8 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -1,5 +1,5 @@ # Copyright (C) 1998, 1999, 2000, 2001, 2002, -# 2003 Free Software Foundation, Inc. +# 2003, 2006 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -26,16 +26,17 @@ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common \ include $(top_srcdir)/am/cmacros.am -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) -Wno-pointer-sign needed_libs = ../gl/libgnu.a ../common/libcommon.a ../jnlib/libjnlib.a bin_PROGRAMS = gpg2 gpgv2 common_source = \ - global.h gpg.h \ + gpg.h \ build-packet.c \ compress.c \ + compress-bz2.c \ filter.h \ free-packet.c \ getkey.c \ @@ -55,7 +56,6 @@ common_source = \ keyid.c \ packet.h \ parse-packet.c \ - comment.c \ status.c \ status.h \ plaintext.c \ @@ -63,7 +63,7 @@ common_source = \ keylist.c \ pkglue.c pkglue.h -gpg2_SOURCES = g10.c \ +gpg2_SOURCES = gpg.c \ $(common_source) \ pkclist.c \ skclist.c \ @@ -88,7 +88,6 @@ gpg2_SOURCES = g10.c \ tdbio.h \ delkey.c \ keygen.c \ - pipemode.c \ helptext.c \ keyserver.c \ keyserver-internal.h \ diff --git a/g10/armor.c b/g10/armor.c index 121ec3a09..a154c5cfe 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -1,6 +1,6 @@ /* armor.c - Armor flter - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -30,7 +31,6 @@ #include "gpg.h" #include "errors.h" #include "iobuf.h" -#include "memory.h" #include "util.h" #include "filter.h" #include "packet.h" @@ -39,12 +39,6 @@ #include "status.h" #include "i18n.h" -#ifdef HAVE_DOSISH_SYSTEM -#define LF "\r\n" -#else -#define LF "\n" -#endif - #define MAX_LINELEN 20000 #define CRCINIT 0xB704CE @@ -120,7 +114,6 @@ static char *tail_strings[] = { }; - static void initialize(void) { @@ -193,7 +186,7 @@ is_armored( const byte *buf ) * filter to do further processing. */ int -use_armor_filter( iobuf_t a ) +use_armor_filter( IOBUF a ) { byte buf[1]; int n; @@ -292,17 +285,24 @@ is_armor_header( byte *line, unsigned len ) save_p = p; p += 5; - /* Some mail programs on Windows seem to add spaces to the end of - the line. This becomes strict if --openpgp is set. */ - - if(!RFC2440) - while(*p==' ') + /* Some Windows environments seem to add whitespace to the end of + the line, so we strip it here. This becomes strict if + --rfc2440 is set since 2440 reads "The header lines, therefore, + MUST start at the beginning of a line, and MUST NOT have text + following them on the same line." It is unclear whether "text" + refers to all text or just non-whitespace text. */ + + if(RFC2440) + { + if( *p == '\r' ) + p++; + if( *p == '\n' ) + p++; + } + else + while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t') p++; - if( *p == '\r' ) - p++; - if( *p == '\n' ) - p++; if( *p ) return -1; /* garbage after dashes */ save_c = *save_p; *save_p = 0; @@ -334,21 +334,35 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) int hashes=0; unsigned int len2; - len2 = length_sans_trailing_ws( line, len ); + len2 = check_trailing_ws( line, len ); if( !len2 ) { afx->buffer_pos = len2; /* (it is not the fine way to do it here) */ return 0; /* WS only: same as empty line */ } - len = len2; - line[len2] = 0; + + /* + This is fussy. The spec says that a header line is delimited + with a colon-space pair. This means that a line such as + "Comment: " (with nothing else) is actually legal as an empty + string comment. However, email and cut-and-paste being what it + is, that trailing space may go away. Therefore, we accept empty + headers delimited with only a colon. --rfc2440, as always, + makes this strict and enforces the colon-space pair. -dms + */ p = strchr( line, ':'); - if( !p || !p[1] ) { + if( !p || (RFC2440 && p[1]!=' ') + || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r')) + { log_error(_("invalid armor header: ")); print_string( stderr, line, len, 0 ); putc('\n', stderr); return -1; - } + } + + /* Chop off the whitespace we detected before */ + len=len2; + line[len2]='\0'; if( opt.verbose ) { log_info(_("armor header: ")); @@ -373,7 +387,7 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) /* figure out whether the data is armored or not */ static int -check_input( armor_filter_context_t *afx, iobuf_t a ) +check_input( armor_filter_context_t *afx, IOBUF a ) { int rc = 0; int i; @@ -415,7 +429,7 @@ check_input( armor_filter_context_t *afx, iobuf_t a ) if( hdr_line == BEGIN_SIGNED_MSG_IDX ) { if( afx->in_cleartext ) { log_error(_("nested clear text signatures\n")); - rc = GPG_ERR_INV_ARMOR; + rc = gpg_error (GPG_ERR_INV_ARMOR); } afx->in_cleartext = 1; } @@ -431,9 +445,9 @@ check_input( armor_filter_context_t *afx, iobuf_t a ) } while( !maxlen ); } - /* parse the header lines */ + /* Parse the header lines. */ while(len) { - /* read the next line (skip all truncated lines) */ + /* Read the next line (skip all truncated lines). */ do { maxlen = MAX_LINELEN; afx->buffer_len = iobuf_read_line( a, &afx->buffer, @@ -444,8 +458,8 @@ check_input( armor_filter_context_t *afx, iobuf_t a ) i = parse_header_line( afx, line, len ); if( i <= 0 ) { - if( i ) - rc = GPG_ERR_INV_ARMOR; + if (i && RFC2440) + rc = G10ERR_INVALID_ARMOR; break; } } @@ -465,7 +479,8 @@ check_input( armor_filter_context_t *afx, iobuf_t a ) return rc; } - +#define PARTIAL_CHUNK 512 +#define PARTIAL_POW 9 /**************** * Fake a literal data packet and wait for the next armor line @@ -473,7 +488,7 @@ check_input( armor_filter_context_t *afx, iobuf_t a ) * not implemented/checked. */ static int -fake_packet( armor_filter_context_t *afx, iobuf_t a, +fake_packet( armor_filter_context_t *afx, IOBUF a, size_t *retn, byte *buf, size_t size ) { int rc = 0; @@ -481,19 +496,31 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a, int lastline = 0; unsigned maxlen, n; byte *p; + byte tempbuf[PARTIAL_CHUNK]; + size_t tempbuf_len=0; - len = 2; /* reserve 2 bytes for the length header */ - size -= 2; /* and 2 for the terminating header */ - while( !rc && len < size ) { + while( !rc && size-len>=(PARTIAL_CHUNK+1)) { /* copy what we have in the line buffer */ if( afx->faked == 1 ) afx->faked++; /* skip the first (empty) line */ - else { - while( len < size && afx->buffer_pos < afx->buffer_len ) - buf[len++] = afx->buffer[afx->buffer_pos++]; - if( len >= size ) + else + { + /* It's full, so write this partial chunk */ + if(tempbuf_len==PARTIAL_CHUNK) + { + buf[len++]=0xE0+PARTIAL_POW; + memcpy(&buf[len],tempbuf,PARTIAL_CHUNK); + len+=PARTIAL_CHUNK; + tempbuf_len=0; continue; - } + } + + while( tempbuf_len < PARTIAL_CHUNK + && afx->buffer_pos < afx->buffer_len ) + tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++]; + if( tempbuf_len==PARTIAL_CHUNK ) + continue; + } /* read the next line */ maxlen = MAX_LINELEN; @@ -506,15 +533,64 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a, } if( !maxlen ) afx->truncated++; - if( !afx->not_dash_escaped ) { - int crlf; - p = afx->buffer; - n = afx->buffer_len; - crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n'; + + p = afx->buffer; + n = afx->buffer_len; + + /* Armor header or dash-escaped line? */ + if(p[0]=='-') + { + /* 2440bis-10: When reversing dash-escaping, an + implementation MUST strip the string "- " if it occurs + at the beginning of a line, and SHOULD warn on "-" and + any character other than a space at the beginning of a + line. */ + + if(p[1]==' ' && !afx->not_dash_escaped) + { + /* It's a dash-escaped line, so skip over the + escape. */ + afx->buffer_pos = 2; + } + else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-') + { + /* Five dashes in a row mean it's probably armor + header. */ + int type = is_armor_header( p, n ); + if( afx->not_dash_escaped && type != BEGIN_SIGNATURE ) + ; /* this is okay */ + else + { + if( type != BEGIN_SIGNATURE ) + { + log_info(_("unexpected armor: ")); + print_string( stderr, p, n, 0 ); + putc('\n', stderr); + } + + lastline = 1; + rc = -1; + } + } + else if(!afx->not_dash_escaped) + { + /* Bad dash-escaping. */ + log_info(_("invalid dash escaped line: ")); + print_string( stderr, p, n, 0 ); + putc('\n', stderr); + } + } + + /* Now handle the end-of-line canonicalization */ + if( !afx->not_dash_escaped ) + { + int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n'; /* PGP2 does not treat a tab as white space character */ - afx->buffer_len = trim_trailing_chars( p, n, - afx->pgp2mode ? " \r\n" : " \t\r\n"); + afx->buffer_len= + trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos, + afx->pgp2mode ? " \r\n" : " \t\r\n"); + afx->buffer_len+=afx->buffer_pos; /* the buffer is always allocated with enough space to append * the removed [CR], LF and a Nul * The reason for this complicated procedure is to keep at least @@ -526,48 +602,23 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a, * faked packet could do the job). */ if( crlf ) - afx->buffer[afx->buffer_len++] = '\r'; + afx->buffer[afx->buffer_len++] = '\r'; afx->buffer[afx->buffer_len++] = '\n'; - afx->buffer[afx->buffer_len] = 0; - } - p = afx->buffer; - n = afx->buffer_len; - - if( n > 2 && *p == '-' ) { - /* check for dash escaped or armor header */ - if( p[1] == ' ' && !afx->not_dash_escaped ) { - /* issue a warning if it is not regular encoded */ - if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) { - log_info(_("invalid dash escaped line: ")); - print_string( stderr, p, n, 0 ); - putc('\n', stderr); - } - afx->buffer_pos = 2; /* skip */ - } - else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) { - int type = is_armor_header( p, n ); - if( afx->not_dash_escaped && type != BEGIN_SIGNATURE ) - ; /* this is okay */ - else { - if( type != BEGIN_SIGNATURE ) { - log_info(_("unexpected armor:")); - print_string( stderr, p, n, 0 ); - putc('\n', stderr); - } - lastline = 1; - rc = -1; - } - } - } + afx->buffer[afx->buffer_len] = '\0'; + } } - buf[0] = (len-2) >> 8; - buf[1] = (len-2); if( lastline ) { /* write last (ending) length header */ - if( buf[0] || buf[1] ) { /* only if we have some text */ - buf[len++] = 0; - buf[len++] = 0; - } + if(tempbuf_len<192) + buf[len++]=tempbuf_len; + else + { + buf[len++]=((tempbuf_len-192)/256) + 192; + buf[len++]=(tempbuf_len-192) % 256; + } + memcpy(&buf[len],tempbuf,tempbuf_len); + len+=tempbuf_len; + rc = 0; afx->faked = 0; afx->in_cleartext = 0; @@ -609,15 +660,15 @@ fake_packet( armor_filter_context_t *afx, iobuf_t a, static int invalid_crc(void) { - if ( opt.ignore_crc_error ) - return 0; - log_inc_errorcount(); - return GPG_ERR_INV_ARMOR; + if ( opt.ignore_crc_error ) + return 0; + log_inc_errorcount(); + return gpg_error (GPG_ERR_INV_ARMOR); } static int -radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn, +radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, byte *buf, size_t size ) { byte val; @@ -676,7 +727,7 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn, break; } else if( (c = asctobin[(c2=c)]) == 255 ) { - log_error(_("invalid radix64 character %02x skipped\n"), c2); + log_error(_("invalid radix64 character %02X skipped\n"), c2); continue; } switch(idx) { @@ -755,13 +806,17 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn, if( c == -1 ) { log_info(_("premature eof (in CRC)\n")); rc = invalid_crc(); - } + } + else if( idx == 0 ) { + /* No CRC at all is legal ("MAY") */ + rc=0; + } else if( idx != 4 ) { log_info(_("malformed CRC\n")); rc = invalid_crc(); } else if( mycrc != afx->crc ) { - log_info (_("CRC error; %06lx - %06lx\n"), + log_info (_("CRC error; %06lX - %06lX\n"), (ulong)afx->crc, (ulong)mycrc); rc = invalid_crc(); } @@ -781,12 +836,12 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn, if( rc == -1 ) rc = 0; else if( rc == 2 ) { - log_error(_("premature eof (in Trailer)\n")); - rc = GPG_ERR_INV_ARMOR; + log_error(_("premature eof (in trailer)\n")); + rc = G10ERR_INVALID_ARMOR; } else { log_error(_("error in trailer line\n")); - rc = GPG_ERR_INV_ARMOR; + rc = G10ERR_INVALID_ARMOR; } #endif } @@ -805,7 +860,7 @@ radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn, */ int armor_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; armor_filter_context_t *afx = opaque; @@ -843,9 +898,10 @@ armor_filter( void *opaque, int control, *ret_len = n; } else if( control == IOBUFCTRL_UNDERFLOW ) { - /* We need some space for the faked packet. The minmum required - * size is ~18 + length of the session marker */ - if( size < 50 ) + /* We need some space for the faked packet. The minmum + * required size is the PARTIAL_CHUNK size plus a byte for the + * length itself */ + if( size < PARTIAL_CHUNK+1 ) BUG(); /* supplied buffer too short */ if( afx->faked ) @@ -882,7 +938,7 @@ armor_filter( void *opaque, int control, afx->pgp2mode = 1; } n=0; - /* first a gpg control packet */ + /* First a gpg control packet... */ buf[n++] = 0xff; /* new format, type 63, 1 length byte */ n++; /* see below */ memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen; @@ -902,12 +958,16 @@ armor_filter( void *opaque, int control, buf[n++] = DIGEST_ALGO_SHA512; buf[1] = n - 2; - /* followed by a plaintext packet */ - buf[n++] = 0xaf; /* old packet format, type 11, var length */ - buf[n++] = 0; /* set the length header */ - buf[n++] = 6; + /* ...followed by an invented plaintext packet. + Amusingly enough, this packet is not compliant with + 2440 as the initial partial length is less than 512 + bytes. Of course, we'll accept it anyway ;) */ + + buf[n++] = 0xCB; /* new packet format, type 11 */ + buf[n++] = 0xE1; /* 2^1 == 2 bytes */ buf[n++] = 't'; /* canonical text mode */ buf[n++] = 0; /* namelength */ + buf[n++] = 0xE2; /* 2^2 == 4 more bytes */ memset(buf+n, 0, 4); /* timestamp */ n += 4; } @@ -926,35 +986,39 @@ armor_filter( void *opaque, int control, else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) { if( !afx->status ) { /* write the header line */ const char *s; - STRLIST comment = opt.comments; + STRLIST comment=opt.comments; if( afx->what >= DIM(head_strings) ) log_bug("afx->what=%d", afx->what); iobuf_writestr(a, "-----"); iobuf_writestr(a, head_strings[afx->what] ); - iobuf_writestr(a, "-----" LF ); + iobuf_writestr(a, "-----" ); + iobuf_writestr(a,afx->eol); if( !opt.no_version ) + { iobuf_writestr(a, "Version: GnuPG v" VERSION " (" - PRINTABLE_OS_NAME ")" LF ); + PRINTABLE_OS_NAME ")" ); + iobuf_writestr(a,afx->eol); + } - /* Write the comment string. */ - for(s=comment? comment->d:NULL; comment; - comment=comment->next,s=comment->d) + /* write the comment strings */ + for(s=comment->d;comment;comment=comment->next,s=comment->d) { iobuf_writestr(a, "Comment: " ); - for ( ; *s; s++ ) - { + for( ; *s; s++ ) + { if( *s == '\n' ) - iobuf_writestr(a, "\\n" ); + iobuf_writestr(a, "\\n" ); else if( *s == '\r' ) - iobuf_writestr(a, "\\r" ); + iobuf_writestr(a, "\\r" ); else if( *s == '\v' ) - iobuf_writestr(a, "\\v" ); + iobuf_writestr(a, "\\v" ); else - iobuf_put(a, *s ); - } - iobuf_writestr(a, LF ); - } + iobuf_put(a, *s ); + } + + iobuf_writestr(a,afx->eol); + } if ( afx->hdrlines ) { for ( s = afx->hdrlines; *s; s++ ) { @@ -965,7 +1029,8 @@ armor_filter( void *opaque, int control, iobuf_put(a, *s ); } } - iobuf_writestr(a, LF ); + + iobuf_writestr(a,afx->eol); afx->status++; afx->idx = 0; afx->idx2 = 0; @@ -994,10 +1059,11 @@ armor_filter( void *opaque, int control, iobuf_put(a, c); c = bintoasc[radbuf[2]&077]; iobuf_put(a, c); - if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ - iobuf_writestr(a, LF ); + if( ++idx2 >= (64/4) ) + { /* pgp doesn't like 72 here */ + iobuf_writestr(a,afx->eol); idx2=0; - } + } } } for(i=0; i < idx; i++ ) @@ -1006,10 +1072,23 @@ armor_filter( void *opaque, int control, afx->idx2 = idx2; afx->crc = crc; } - else if( control == IOBUFCTRL_INIT ) { + else if( control == IOBUFCTRL_INIT ) + { if( !is_initialized ) - initialize(); - } + initialize(); + + /* Figure out what we're using for line endings if the caller + didn't specify. */ + if(afx->eol[0]==0) + { +#ifdef HAVE_DOSISH_SYSTEM + afx->eol[0]='\r'; + afx->eol[1]='\n'; +#else + afx->eol[0]='\n'; +#endif + } + } else if( control == IOBUFCTRL_CANCEL ) { afx->cancel = 1; } @@ -1038,14 +1117,15 @@ armor_filter( void *opaque, int control, iobuf_put(a, c); iobuf_put(a, '='); } - if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */ - iobuf_writestr(a, LF ); + if( ++idx2 >= (64/4) ) + { /* pgp doesn't like 72 here */ + iobuf_writestr(a,afx->eol); idx2=0; - } + } } /* may need a linefeed */ if( idx2 ) - iobuf_writestr(a, LF ); + iobuf_writestr(a,afx->eol); /* write the CRC */ iobuf_put(a, '='); radbuf[0] = crc >>16; @@ -1059,13 +1139,14 @@ armor_filter( void *opaque, int control, iobuf_put(a, c); c = bintoasc[radbuf[2]&077]; iobuf_put(a, c); - iobuf_writestr(a, LF ); + iobuf_writestr(a,afx->eol); /* and the the trailer */ if( afx->what >= DIM(tail_strings) ) log_bug("afx->what=%d", afx->what); iobuf_writestr(a, "-----"); iobuf_writestr(a, tail_strings[afx->what] ); - iobuf_writestr(a, "-----" LF ); + iobuf_writestr(a, "-----" ); + iobuf_writestr(a,afx->eol); } else if( !afx->any_data && !afx->inp_bypass ) { log_error(_("no valid OpenPGP data found.\n")); @@ -1079,7 +1160,7 @@ armor_filter( void *opaque, int control, if( afx->qp_detected ) log_error(_("quoted printable character in armor - " "probably a buggy MTA has been used\n") ); - xfree ( afx->buffer ); + xfree( afx->buffer ); afx->buffer = NULL; } else if( control == IOBUFCTRL_DESC ) @@ -1096,7 +1177,7 @@ make_radix64_string( const byte *data, size_t len ) { char *buffer, *p; - buffer = p = xmalloc ( (len+2)/3*4 + 1 ); + buffer = p = xmalloc( (len+2)/3*4 + 1 ); for( ; len >= 3 ; len -= 3, data += 3 ) { *p++ = bintoasc[(data[0] >> 2) & 077]; *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077]; @@ -1156,7 +1237,7 @@ unarmor_pump_new (void) if( !is_initialized ) initialize(); - x = xcalloc (1,sizeof *x); + x = xmalloc_clear (sizeof *x); return x; } @@ -1253,7 +1334,7 @@ unarmor_pump (UnarmorPump x, int c) { int c2; if( (c = asctobin[(c2=c)]) == 255 ) { - log_error(_("invalid radix64 character %02x skipped\n"), c2); + log_error(_("invalid radix64 character %02X skipped\n"), c2); break; } } @@ -1290,7 +1371,7 @@ unarmor_pump (UnarmorPump x, int c) if( (c = asctobin[c]) == 255 ) { rval = -1; /* ready */ if( x->crc != x->mycrc ) { - log_info (_("CRC error; %06lx - %06lx\n"), + log_info (_("CRC error; %06lX - %06lX\n"), (ulong)x->crc, (ulong)x->mycrc); if ( invalid_crc() ) rval = -3; diff --git a/g10/build-packet.c b/g10/build-packet.c index d2c538477..cbf037483 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -1,6 +1,6 @@ /* build-packet.c - assemble packets and write them - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -24,40 +25,38 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <ctype.h> #include "gpg.h" #include "packet.h" #include "errors.h" #include "iobuf.h" -#include "mpi.h" #include "util.h" #include "cipher.h" -#include "memory.h" +#include "i18n.h" #include "options.h" - -static int do_comment( iobuf_t out, int ctb, PKT_comment *rem ); -static int do_user_id( iobuf_t out, int ctb, PKT_user_id *uid ); -static int do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ); -static int do_secret_key( iobuf_t out, int ctb, PKT_secret_key *pk ); -static int do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ); -static int do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ); +static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); +static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); +static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk ); +static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); +static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); static u32 calc_plaintext( PKT_plaintext *pt ); -static int do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ); -static int do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ); -static int do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ); -static int do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ); -static int do_signature( iobuf_t out, int ctb, PKT_signature *sig ); -static int do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ); +static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); +static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); +static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); +static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); +static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); static int calc_header_length( u32 len, int new_ctb ); -static int write_16(iobuf_t inp, u16 a); -static int write_32(iobuf_t inp, u32 a); -static int write_header( iobuf_t out, int ctb, u32 len ); -static int write_sign_packet_header( iobuf_t out, int ctb, u32 len ); -static int write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode ); -static int write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ); -static int write_version( iobuf_t out, int ctb ); +static int write_16(IOBUF inp, u16 a); +static int write_32(IOBUF inp, u32 a); +static int write_header( IOBUF out, int ctb, u32 len ); +static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); +static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen ); +static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); +static int write_version( IOBUF out, int ctb ); /**************** * Build a packet and write it to INP @@ -66,7 +65,7 @@ static int write_version( iobuf_t out, int ctb ); * Note: Caller must free the packet */ int -build_packet( iobuf_t out, PACKET *pkt ) +build_packet( IOBUF out, PACKET *pkt ) { int new_ctb=0, rc=0, ctb; int pkttype; @@ -75,30 +74,38 @@ build_packet( iobuf_t out, PACKET *pkt ) log_debug("build_packet() type=%d\n", pkt->pkttype ); assert( pkt->pkt.generic ); - switch( (pkttype = pkt->pkttype) ) { - case PKT_OLD_COMMENT: pkttype = pkt->pkttype = PKT_COMMENT; break; + switch( (pkttype = pkt->pkttype) ) + { case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; case PKT_USER_ID: - if( pkt->pkt.user_id->attrib_data ) - pkttype = PKT_ATTRIBUTE; - break; + if( pkt->pkt.user_id->attrib_data ) + pkttype = PKT_ATTRIBUTE; + break; default: break; - } + } if( new_ctb || pkttype > 15 ) /* new format */ ctb = 0xc0 | (pkttype & 0x3f); else ctb = 0x80 | ((pkttype & 15)<<2); - switch( pkttype ) { + switch( pkttype ) + { case PKT_ATTRIBUTE: case PKT_USER_ID: rc = do_user_id( out, ctb, pkt->pkt.user_id ); break; + case PKT_OLD_COMMENT: case PKT_COMMENT: - rc = do_comment( out, ctb, pkt->pkt.comment ); + /* + Ignore these. Theoretically, this will never be called as + we have no way to output comment packets any longer, but + just in case there is some code path that would end up + outputting a comment that was written before comments were + dropped (in the public key?) this is a no-op. + */ break; case PKT_PUBLIC_SUBKEY: case PKT_PUBLIC_KEY: @@ -138,11 +145,32 @@ build_packet( iobuf_t out, PACKET *pkt ) default: log_bug("invalid packet type in build_packet()\n"); break; - } + } return rc; } + +/* + * Write the mpi A to OUT. + */ +static int +mpi_write (iobuf_t out, gcry_mpi_t a) +{ + char buffer[(MAX_EXTERN_MPI_BITS+7)/8]; + size_t nbytes; + int rc; + + nbytes = (MAX_EXTERN_MPI_BITS+7)/8; + rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); + if( !rc ) + rc = iobuf_write( out, buffer, nbytes ); + + return rc; +} + + + /**************** * calculate the length of a packet described by PKT */ @@ -180,56 +208,42 @@ calc_packet_length( PACKET *pkt ) } static void -write_fake_data( iobuf_t out, gcry_mpi_t a ) +write_fake_data (IOBUF out, gcry_mpi_t a) { - if( a ) { - unsigned int n; - void *p; - - assert( gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)); - p = gcry_mpi_get_opaque (a, &n); - iobuf_write (out, p, (n+7)/8); - } -} - - -static int -do_comment (iobuf_t out, int ctb, PKT_comment *rem) -{ - int rc = 0; - - if (opt.sk_comments) + if (a) { - write_header(out, ctb, rem->len); - rc = iobuf_write( out, rem->data, rem->len ); + unsigned int n; + void *p; + + p = gcry_mpi_get_opaque ( a, &n ); + iobuf_write (out, p, (n+7)/8 ); } - return rc; } static int -do_user_id( iobuf_t out, int ctb, PKT_user_id *uid ) +do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { - int rc; + int rc; - if (uid->attrib_data) - { - write_header (out, ctb, uid->attrib_len); - rc = iobuf_write (out, uid->attrib_data, uid->attrib_len ); - } - else - { - write_header (out, ctb, uid->len); - rc = iobuf_write (out, uid->name, uid->len ); - } - return rc; + if( uid->attrib_data ) + { + write_header(out, ctb, uid->attrib_len); + rc = iobuf_write( out, uid->attrib_data, uid->attrib_len ); + } + else + { + write_header2( out, ctb, uid->len, 2 ); + rc = iobuf_write( out, uid->name, uid->len ); + } + return 0; } static int -do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ) +do_public_key( IOBUF out, int ctb, PKT_public_key *pk ) { int rc = 0; int n, i; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); if( !pk->version ) iobuf_put( a, 3 ); @@ -251,99 +265,20 @@ do_public_key( iobuf_t out, int ctb, PKT_public_key *pk ) for(i=0; i < n; i++ ) mpi_write(a, pk->pkey[i] ); - write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 ); - rc = iobuf_write_temp (out, a); + write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } -/**************** - * Make a hash value from the public key certificate - */ -void -hash_public_key( MD_HANDLE md, PKT_public_key *pk ) -{ - PACKET pkt; - int rc = 0; - int ctb; - ulong pktlen; - int c; - iobuf_t a = iobuf_temp(); -#if 0 - FILE *fp = fopen("dump.pk", "a"); - int i=0; - - fprintf(fp, "\nHashing PK (v%d):\n", pk->version); -#endif - - /* build the packet */ - init_packet(&pkt); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - if( (rc = build_packet( a, &pkt )) ) - log_fatal("build public_key for hashing failed: %s\n", gpg_strerror (rc)); - - if( !(pk->version == 3 && pk->pubkey_algo == 16) ) { - /* skip the constructed header but don't do this for our very old - * v3 ElG keys */ - ctb = iobuf_get_noeof(a); - pktlen = 0; - if( (ctb & 0x40) ) { - c = iobuf_get_noeof(a); - if( c < 192 ) - pktlen = c; - else if( c < 224 ) { - pktlen = (c - 192) * 256; - c = iobuf_get_noeof(a); - pktlen += c + 192; - } - else if( c == 255 ) { - pktlen = iobuf_get_noeof(a) << 24; - pktlen |= iobuf_get_noeof(a) << 16; - pktlen |= iobuf_get_noeof(a) << 8; - pktlen |= iobuf_get_noeof(a); - } - } - else { - int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); - for( ; lenbytes; lenbytes-- ) { - pktlen <<= 8; - pktlen |= iobuf_get_noeof(a); - } - } - /* hash a header */ - gcry_md_putc ( md, 0x99 ); - pktlen &= 0xffff; /* can't handle longer packets */ - gcry_md_putc ( md, pktlen >> 8 ); - gcry_md_putc ( md, pktlen & 0xff ); - } - /* hash the packet body */ - while( (c=iobuf_get(a)) != -1 ) { -#if 0 - fprintf( fp," %02x", c ); - if( (++i == 24) ) { - putc('\n', fp); - i=0; - } -#endif - gcry_md_putc ( md, c ); - } -#if 0 - putc('\n', fp); - fclose(fp); -#endif - iobuf_cancel(a); -} - - static int -do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) +do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk ) { int rc = 0; int i, nskey, npkey; - iobuf_t a = iobuf_temp(); /* build in a self-enlarging buffer */ + IOBUF a = iobuf_temp(); /* build in a self-enlarging buffer */ /* Write the version number - if none is specified, use 3 */ if( !sk->version ) @@ -371,7 +306,7 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) /* If we don't have any public parameters - which is the case if we don't know the algorithm used - the parameters are stored as - one blob in a faked (opaque) gcry_mpi_t */ + one blob in a faked (opaque) MPI */ if( !npkey ) { write_fake_data( a, sk->skey[0] ); goto leave; @@ -415,9 +350,9 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) if( sk->protect.s2k.mode == 3 ) iobuf_put(a, sk->protect.s2k.count ); - /* For our special modes 1001 and 1002 we do not need an IV */ - if( sk->protect.s2k.mode != 1001 - && sk->protect.s2k.mode != 1002 ) + /* For out special modes 1001, 1002 we do not need an IV */ + if( sk->protect.s2k.mode != 1001 + && sk->protect.s2k.mode != 1002 ) iobuf_write(a, sk->protect.iv, sk->protect.ivlen ); } } @@ -437,19 +372,21 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) else if( sk->is_protected && sk->version >= 4 ) { /* The secret key is protected - write it out as it is */ byte *p; - assert( gcry_mpi_get_flag( sk->skey[npkey], GCRYMPI_FLAG_OPAQUE ) ); - p = gcry_mpi_get_opaque( sk->skey[npkey], &i ); - iobuf_write(a, p, (i+7)/8 ); + unsigned int ndatabits; + + assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits ); + iobuf_write (a, p, (ndatabits+7)/8 ); } else if( sk->is_protected ) { - /* The secret key is protected the old v4 way. */ + /* The secret key is protected te old v4 way. */ for( ; i < nskey; i++ ) { byte *p; - size_t n; + unsigned int ndatabits; - assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); - p = gcry_mpi_get_opaque( sk->skey[i], &n ); - iobuf_write (a, p, (n+7)/8); + assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits); + iobuf_write (a, p, (ndatabits+7)/8); } write_16(a, sk->csum ); } @@ -463,19 +400,19 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk ) leave: /* Build the header of the packet - which we must do after writing all the other stuff, so that we know the length of the packet */ - write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); + write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes); /* And finally write it out the real stream */ - rc = iobuf_write_temp (out, a ); + rc = iobuf_write_temp( out, a ); iobuf_close(a); /* close the remporary buffer */ return rc; } static int -do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ) +do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) { int rc = 0; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); assert( enc->version == 4 ); switch( enc->s2k.mode ) { @@ -495,21 +432,19 @@ do_symkey_enc( iobuf_t out, int ctb, PKT_symkey_enc *enc ) iobuf_write(a, enc->seskey, enc->seskeylen ); write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } - - static int -do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ) +do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) { int rc = 0; int n, i; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); write_version( a, ctb ); if( enc->throw_keyid ) { @@ -528,55 +463,56 @@ do_pubkey_enc( iobuf_t out, int ctb, PKT_pubkey_enc *enc ) mpi_write(a, enc->data[i] ); write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } - - static u32 calc_plaintext( PKT_plaintext *pt ) { - return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; + /* Truncate namelen to the maximum 255 characters. Note this means + that a function that calls build_packet with an illegal literal + packet will get it back legalized. */ + + if(pt->namelen>255) + pt->namelen=255; + + return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; } static int -do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ) +do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) { int i, rc = 0; u32 n; byte buf[1000]; /* this buffer has the plaintext! */ int nbytes; - /* Truncate namelen to the maximum 255 characters. This does mean - that a function that calls build_packet with an illegal literal - packet will get it back legalized. */ - if(pt->namelen>255) - pt->namelen=255; - write_header(out, ctb, calc_plaintext( pt ) ); iobuf_put(out, pt->mode ); iobuf_put(out, pt->namelen ); for(i=0; i < pt->namelen; i++ ) iobuf_put(out, pt->name[i] ); - rc = write_32 (out, pt->timestamp); + rc = write_32(out, pt->timestamp ); + if (rc) + return rc; n = 0; while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { - rc = iobuf_write(out, buf, nbytes); - if (rc) - break; - n += nbytes; + rc = iobuf_write (out, buf, nbytes); + if (rc) + break; + n += nbytes; } wipememory(buf,1000); /* burn the buffer */ - if( !pt->len ) - iobuf_set_block_mode(out, 0 ); /* write end marker */ - else if( n != pt->len ) - log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", - (ulong)n, (ulong)pt->len ); + if( (ctb&0x40) && !pt->len ) + iobuf_set_partial_block_mode(out, 0 ); /* turn off partial */ + if( pt->len && n != pt->len ) + log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", + (ulong)n, (ulong)pt->len ); return rc; } @@ -584,7 +520,7 @@ do_plaintext( iobuf_t out, int ctb, PKT_plaintext *pt ) static int -do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ) +do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; @@ -598,7 +534,7 @@ do_encrypted( iobuf_t out, int ctb, PKT_encrypted *ed ) } static int -do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ) +do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; @@ -617,7 +553,7 @@ do_encrypted_mdc( iobuf_t out, int ctb, PKT_encrypted *ed ) static int -do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ) +do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) { int rc = 0; @@ -626,7 +562,7 @@ do_compressed( iobuf_t out, int ctb, PKT_compressed *cd ) set, CTB is already formatted as new style and write_header2 does create a partial length encoding using new the new style. */ - write_header2(out, ctb, 0, 0, 0 ); + write_header2(out, ctb, 0, 0); iobuf_put(out, cd->algorithm ); /* This is all. The caller has to write the real data */ @@ -734,6 +670,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, case SIGSUBPKT_NOTATION: case SIGSUBPKT_POLICY: case SIGSUBPKT_REV_KEY: + case SIGSUBPKT_SIGNATURE: /* we do allow multiple subpackets */ break; @@ -803,18 +740,20 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, else nlen = 1; /* just a 1 byte length header */ - switch( type ) { + switch( type ) + { /* The issuer being unhashed is a historical oddity. It should work equally as well hashed. Of course, if even an unhashed issuer is tampered with, it makes it awfully hard to verify the sig... */ case SIGSUBPKT_ISSUER: + case SIGSUBPKT_SIGNATURE: hashed = 0; break; default: hashed = 1; break; - } + } if( critical ) type |= SIGSUBPKT_FLAG_CRITICAL; @@ -966,12 +905,179 @@ build_attribute_subpkt(PKT_user_id *uid,byte type, uid->attrib_len+=idx+headerlen+buflen; } +struct notation * +string_to_notation(const char *string,int is_utf8) +{ + const char *s; + int saw_at=0; + struct notation *notation; + + notation=xmalloc_clear(sizeof(*notation)); + + if(*string=='-') + { + notation->flags.ignore=1; + string++; + } + + if(*string=='!') + { + notation->flags.critical=1; + string++; + } + + /* If and when the IETF assigns some official name tags, we'll have + to add them here. */ + + for( s=string ; *s != '='; s++ ) + { + if( *s=='@') + saw_at++; + + /* -notationname is legal without an = sign */ + if(!*s && notation->flags.ignore) + break; + + if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) ) + { + log_error(_("a notation name must have only printable characters" + " or spaces, and end with an '='\n") ); + goto fail; + } + } + + notation->name=xmalloc((s-string)+1); + strncpy(notation->name,string,s-string); + notation->name[s-string]='\0'; + + if(!saw_at && !opt.expert) + { + log_error(_("a user notation name must contain the '@' character\n")); + goto fail; + } + + if (saw_at > 1) + { + log_error(_("a notation name must not contain more than" + " one '@' character\n")); + goto fail; + } + + if(*s) + { + const char *i=s+1; + int highbit=0; + + /* we only support printable text - therefore we enforce the use + of only printable characters (an empty value is valid) */ + for(s++; *s ; s++ ) + { + if ( !isascii (*s) ) + highbit=1; + else if (iscntrl(*s)) + { + log_error(_("a notation value must not use any" + " control characters\n")); + goto fail; + } + } + + if(!highbit || is_utf8) + notation->value=xstrdup(i); + else + notation->value=native_to_utf8(i); + } + + return notation; + + fail: + free_notation(notation); + return NULL; +} + +struct notation * +sig_to_notation(PKT_signature *sig) +{ + const byte *p; + size_t len; + int seq=0,crit; + struct notation *list=NULL; + + while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) + { + int n1,n2; + struct notation *n=NULL; + + if(len<8) + { + log_info(_("WARNING: invalid notation data found\n")); + continue; + } + + n1=(p[4]<<8)|p[5]; + n2=(p[6]<<8)|p[7]; + + if(8+n1+n2!=len) + { + log_info(_("WARNING: invalid notation data found\n")); + continue; + } + + n=xmalloc_clear(sizeof(*n)); + n->name=xmalloc(n1+1); + + memcpy(n->name,&p[8],n1); + n->name[n1]='\0'; + + if(p[0]&0x80) + { + n->value=xmalloc(n2+1); + memcpy(n->value,&p[8+n1],n2); + n->value[n2]='\0'; + } + else + { + n->bdat=xmalloc(n2); + n->blen=n2; + memcpy(n->bdat,&p[8+n1],n2); + + n->value=xmalloc(2+strlen(_("not human readable"))+2+1); + strcpy(n->value,"[ "); + strcat(n->value,_("not human readable")); + strcat(n->value," ]"); + } + + n->flags.critical=crit; + + n->next=list; + list=n; + } + + return list; +} + +void +free_notation(struct notation *notation) +{ + while(notation) + { + struct notation *n=notation; + + xfree(n->name); + xfree(n->value); + xfree(n->altvalue); + xfree(n->bdat); + notation=n->next; + xfree(n); + } +} + static int -do_signature( iobuf_t out, int ctb, PKT_signature *sig ) +do_signature( IOBUF out, int ctb, PKT_signature *sig ) { int rc = 0; int n, i; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); if( !sig->version ) iobuf_put( a, 3 ); @@ -1013,7 +1119,7 @@ do_signature( iobuf_t out, int ctb, PKT_signature *sig ) write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); else write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; @@ -1021,10 +1127,10 @@ do_signature( iobuf_t out, int ctb, PKT_signature *sig ) static int -do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) +do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) { int rc = 0; - iobuf_t a = iobuf_temp(); + IOBUF a = iobuf_temp(); write_version( a, ctb ); iobuf_put(a, ops->sig_class ); @@ -1035,7 +1141,7 @@ do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) iobuf_put(a, ops->last ); write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp (out, a); + rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; @@ -1043,19 +1149,21 @@ do_onepass_sig( iobuf_t out, int ctb, PKT_onepass_sig *ops ) static int -write_16(iobuf_t out, u16 a) +write_16(IOBUF out, u16 a) { iobuf_put(out, a>>8); - return iobuf_put(out,a); + if( iobuf_put(out,a) ) + return -1; + return 0; } static int -write_32(iobuf_t out, u32 a) +write_32(IOBUF out, u32 a) { iobuf_put(out, a>> 24); iobuf_put(out, a>> 16); iobuf_put(out, a>> 8); - return iobuf_put (out, a); + return iobuf_put(out, a); } @@ -1088,14 +1196,14 @@ calc_header_length( u32 len, int new_ctb ) * Write the CTB and the packet length */ static int -write_header( iobuf_t out, int ctb, u32 len ) +write_header( IOBUF out, int ctb, u32 len ) { - return write_header2( out, ctb, len, 0, 1 ); + return write_header2( out, ctb, len, 0 ); } static int -write_sign_packet_header( iobuf_t out, int ctb, u32 len ) +write_sign_packet_header( IOBUF out, int ctb, u32 len ) { /* work around a bug in the pgp read function for signature packets, * which are not correctly coded and silently assume at some @@ -1106,57 +1214,66 @@ write_sign_packet_header( iobuf_t out, int ctb, u32 len ) } /**************** - * if HDRLEN is > 0, try to build a header of this length. - * we need this, so that we can hash packets without reading them again. + * If HDRLEN is > 0, try to build a header of this length. We need + * this so that we can hash packets without reading them again. If + * len is 0, write a partial or indeterminate length header, unless + * hdrlen is specified in which case write an actual zero length + * (using the specified hdrlen). */ static int -write_header2( iobuf_t out, int ctb, u32 len, int hdrlen, int blkmode ) +write_header2( IOBUF out, int ctb, u32 len, int hdrlen ) { - if( ctb & 0x40 ) - return write_new_header( out, ctb, len, hdrlen ); - - if( hdrlen ) { - if( !len ) - ctb |= 3; - else if( hdrlen == 2 && len < 256 ) - ; - else if( hdrlen == 3 && len < 65536 ) - ctb |= 1; - else - ctb |= 2; - } - else { - if( !len ) - ctb |= 3; - else if( len < 256 ) - ; - else if( len < 65536 ) - ctb |= 1; - else - ctb |= 2; + if( ctb & 0x40 ) + return write_new_header( out, ctb, len, hdrlen ); + + if( hdrlen ) + { + if( hdrlen == 2 && len < 256 ) + ; + else if( hdrlen == 3 && len < 65536 ) + ctb |= 1; + else + ctb |= 2; } - if( iobuf_put(out, ctb ) ) - return -1; - if( !len ) { - if( blkmode ) - iobuf_set_block_mode(out, 8196 ); + else + { + if( !len ) + ctb |= 3; + else if( len < 256 ) + ; + else if( len < 65536 ) + ctb |= 1; + else + ctb |= 2; } - else { - if( ctb & 2 ) { - iobuf_put(out, len >> 24 ); - iobuf_put(out, len >> 16 ); - } - if( ctb & 3 ) - iobuf_put(out, len >> 8 ); - if( iobuf_put(out, len ) ) + + if( iobuf_put(out, ctb ) ) + return -1; + + if( len || hdrlen ) + { + if( ctb & 2 ) + { + if(iobuf_put(out, len >> 24 )) + return -1; + if(iobuf_put(out, len >> 16 )) return -1; + } + + if( ctb & 3 ) + if(iobuf_put(out, len >> 8 )) + return -1; + + if( iobuf_put(out, len ) ) + return -1; } - return 0; + + return 0; } static int -write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ) +write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) { if( hdrlen ) log_bug("can't cope with hdrlen yet\n"); @@ -1195,7 +1312,7 @@ write_new_header( iobuf_t out, int ctb, u32 len, int hdrlen ) } static int -write_version( iobuf_t out, int ctb ) +write_version( IOBUF out, int ctb ) { if( iobuf_put( out, 3 ) ) return -1; diff --git a/g10/call-agent.c b/g10/call-agent.c index 9c7f8409b..31c43cf13 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -18,8 +18,8 @@ * 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 +#if 0 /* let Emacs display a red warning */ +#error fixme: this shares a lot of code with the file in ../sm #endif #include <config.h> diff --git a/g10/card-util.c b/g10/card-util.c index 1ff57ade5..0c8365405 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1,5 +1,5 @@ /* card-util.c - Utility functions for the OpenPGP card. - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -27,7 +28,7 @@ #if GNUPG_MAJOR_VERSION != 1 #include "gpg.h" -#endif +#endif /*GNUPG_MAJOR_VERSION != 1*/ #include "util.h" #include "i18n.h" #include "ttyio.h" @@ -36,10 +37,14 @@ #include "main.h" #include "keyserver-internal.h" #if GNUPG_MAJOR_VERSION == 1 +#ifdef HAVE_LIBREADLINE +#include <stdio.h> +#include <readline/readline.h> +#endif /*HAVE_LIBREADLINE*/ #include "cardglue.h" -#else +#else /*GNUPG_MAJOR_VERSION!=1*/ #include "call-agent.h" -#endif +#endif /*GNUPG_MAJOR_VERSION!=1*/ #define CONTROL_D ('D' - 'A' + 1) @@ -63,21 +68,25 @@ change_pin (int chvno, int allow_admin) log_info (_("OpenPGP card no. %s detected\n"), info.serialno? info.serialno : "[none]"); - agent_release_card_info (&info); + agent_clear_pin_cache (info.serialno); if (opt.batch) { - log_error (_("sorry, can't do this in batch mode\n")); + agent_release_card_info (&info); + log_error (_("can't do this in batch mode\n")); return; } if(!allow_admin) { - rc = agent_scd_change_pin (1); + rc = agent_scd_change_pin (1, info.serialno); if (rc) tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("PIN changed.\n"); + { + write_status (STATUS_SC_OP_SUCCESS); + tty_printf ("PIN changed.\n"); + } } else for (;;) @@ -99,33 +108,44 @@ change_pin (int chvno, int allow_admin) rc = 0; if (*answer == '1') { - rc = agent_scd_change_pin (1); + rc = agent_scd_change_pin (1, info.serialno); if (rc) tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("PIN changed.\n"); + { + write_status (STATUS_SC_OP_SUCCESS); + tty_printf ("PIN changed.\n"); + } } else if (*answer == '2') { - rc = agent_scd_change_pin (101); + rc = agent_scd_change_pin (101, info.serialno); if (rc) tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("PIN unblocked and new PIN set.\n"); - } + { + write_status (STATUS_SC_OP_SUCCESS); + tty_printf ("PIN unblocked and new PIN set.\n"); + } + } else if (*answer == '3') { - rc = agent_scd_change_pin (3); + rc = agent_scd_change_pin (3, info.serialno); if (rc) tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("PIN changed.\n"); + { + write_status (STATUS_SC_OP_SUCCESS); + tty_printf ("PIN changed.\n"); + } } else if (*answer == 'q' || *answer == 'Q') { break; } } + + agent_release_card_info (&info); } static const char * @@ -137,6 +157,8 @@ get_manufacturer (unsigned int no) case 0: case 0xffff: return "test card"; case 0x0001: return "PPC Card Systems"; + case 0x0002: return "Prism"; + case 0x0003: return "OpenFortress"; default: return "unknown"; } } @@ -270,6 +292,8 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) PKT_public_key *pk = xcalloc (1, sizeof *pk); int rc; unsigned int uval; + const unsigned char *thefpr; + int i; if (serialno && serialnobuflen) *serialno = 0; @@ -346,6 +370,17 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) info.chvretry[0], info.chvretry[1], info.chvretry[2]); fprintf (fp, "sigcount:%lu:::\n", info.sig_counter); + for (i=0; i < 4; i++) + { + if (info.private_do[i]) + { + fprintf (fp, "private_do:%d:", i+1); + print_string (fp, info.private_do[i], + strlen (info.private_do[i]), ':'); + fputs (":\n", fp); + } + } + fputs ("cafpr:", fp); print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL); print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL); @@ -356,7 +391,9 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL); print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL); putc ('\n', fp); - + fprintf (fp, "fprtime:%lu:%lu:%lu:\n", + (unsigned long)info.fpr1time, (unsigned long)info.fpr2time, + (unsigned long)info.fpr3time); } else { @@ -377,6 +414,14 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) info.disp_sex == 2? _("female") : _("unspecified")); print_name (fp, "URL of public key : ", info.pubkey_url); print_name (fp, "Login data .......: ", info.login_data); + if (info.private_do[0]) + print_name (fp, "Private DO 1 .....: ", info.private_do[0]); + if (info.private_do[1]) + print_name (fp, "Private DO 2 .....: ", info.private_do[1]); + if (info.private_do[2]) + print_name (fp, "Private DO 3 .....: ", info.private_do[2]); + if (info.private_do[3]) + print_name (fp, "Private DO 4 .....: ", info.private_do[3]); if (info.cafpr1valid) { tty_fprintf (fp, "CA fingerprint %d .:", 1); @@ -401,13 +446,48 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter); tty_fprintf (fp, "Signature key ....:"); print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL); + if (info.fpr1valid && info.fpr1time) + tty_fprintf (fp, " created ....: %s\n", + isotimestamp (info.fpr1time)); tty_fprintf (fp, "Encryption key....:"); print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL); + if (info.fpr2valid && info.fpr2time) + tty_fprintf (fp, " created ....: %s\n", + isotimestamp (info.fpr2time)); tty_fprintf (fp, "Authentication key:"); print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL); + if (info.fpr3valid && info.fpr3time) + tty_fprintf (fp, " created ....: %s\n", + isotimestamp (info.fpr3time)); tty_fprintf (fp, "General key info..: "); - if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) - print_pubkey_info (fp, pk); + + thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 : + info.fpr3valid? info.fpr3 : NULL); + if ( thefpr && !get_pubkey_byfprint (pk, thefpr, 20)) + { + KBNODE keyblock = NULL; + + print_pubkey_info (fp, pk); + + if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) + print_card_key_info (fp, keyblock); + else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) ) + { + release_kbnode (keyblock); + keyblock = NULL; + + if (!auto_create_card_key_stub (info.serialno, + info.fpr1valid? info.fpr1:NULL, + info.fpr2valid? info.fpr2:NULL, + info.fpr3valid? info.fpr3:NULL)) + { + if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) + print_card_key_info (fp, keyblock); + } + } + + release_kbnode (keyblock); + } else tty_fprintf (fp, "[none]\n"); } @@ -483,8 +563,7 @@ change_name (void) return -1; } - log_debug ("setting Name to `%s'\n", isoname); - rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) ); + rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname), NULL ); if (rc) log_error ("error setting Name: %s\n", gpg_strerror (rc)); @@ -513,13 +592,16 @@ change_url (void) return -1; } - rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) ); + rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url), NULL ); if (rc) log_error ("error setting URL: %s\n", gpg_strerror (rc)); xfree (url); return rc; } + +/* Fetch the key from the URL given on the card or try to get it from + the default keyserver. */ static int fetch_url(void) { @@ -532,7 +614,7 @@ fetch_url(void) rc=agent_scd_getattr("PUBKEY-URL",&info); if(rc) log_error("error retrieving URL from card: %s\n",gpg_strerror(rc)); - else if(info.pubkey_url) + else { struct keyserver_spec *spec=NULL; @@ -540,9 +622,9 @@ fetch_url(void) if(rc) log_error("error retrieving key fingerprint from card: %s\n", gpg_strerror(rc)); - else + else if (info.pubkey_url && *info.pubkey_url) { - spec=parse_keyserver_uri(info.pubkey_url,0,NULL,0); + spec=parse_keyserver_uri(info.pubkey_url,1,NULL,0); if(spec && info.fpr1valid) { /* This is not perfectly right. Currently, all card @@ -556,9 +638,11 @@ fetch_url(void) free_keyserver_spec(spec); } } + else if (info.fpr1valid) + { + rc = keyserver_import_fprint (info.fpr1, 20, opt.keyserver); + } } - else - log_error("no URL set on card\n"); return rc; #else @@ -624,13 +708,82 @@ change_login (const char *args) return -1; } - rc = agent_scd_setattr ("LOGIN-DATA", data, n ); + rc = agent_scd_setattr ("LOGIN-DATA", data, n, NULL ); if (rc) log_error ("error setting login data: %s\n", gpg_strerror (rc)); xfree (data); return rc; } +static int +change_private_do (const char *args, int nr) +{ + char do_name[] = "PRIVATE-DO-X"; + char *data; + int n; + int rc; + + assert (nr >= 1 && nr <= 4); + do_name[11] = '0' + nr; + + if (args && (args = strchr (args, '<'))) /* Read it from a file */ + { + FILE *fp; + + /* Fixme: Factor this duplicated code out. */ + for (args++; spacep (args); args++) + ; + fp = fopen (args, "rb"); +#if GNUPG_MAJOR_VERSION == 1 + if (fp && is_secured_file (fileno (fp))) + { + fclose (fp); + fp = NULL; + errno = EPERM; + } +#endif + if (!fp) + { + tty_printf (_("can't open `%s': %s\n"), args, strerror (errno)); + return -1; + } + + data = xmalloc (254); + n = fread (data, 1, 254, fp); + fclose (fp); + if (n < 0) + { + tty_printf (_("error reading `%s': %s\n"), args, strerror (errno)); + xfree (data); + return -1; + } + } + else + { + data = cpr_get ("cardedit.change_private_do", + _("Private DO data: ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + n = strlen (data); + } + + if (n > 254 ) + { + tty_printf (_("Error: Private DO too long " + "(limit is %d characters).\n"), 254); + xfree (data); + return -1; + } + + rc = agent_scd_setattr (do_name, data, n, NULL ); + if (rc) + log_error ("error setting private DO: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} + static int change_lang (void) { @@ -660,7 +813,7 @@ change_lang (void) return -1; } - rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) ); + rc = agent_scd_setattr ("DISP-LANG", data, strlen (data), NULL ); if (rc) log_error ("error setting lang: %s\n", gpg_strerror (rc)); xfree (data); @@ -695,7 +848,7 @@ change_sex (void) return -1; } - rc = agent_scd_setattr ("DISP-SEX", str, 1 ); + rc = agent_scd_setattr ("DISP-SEX", str, 1, NULL ); if (rc) log_error ("error setting sex: %s\n", gpg_strerror (rc)); xfree (data); @@ -740,7 +893,7 @@ change_cafpr (int fprno) rc = agent_scd_setattr (fprno==1?"CA-FPR-1": fprno==2?"CA-FPR-2": - fprno==3?"CA-FPR-3":"x", fpr, 20 ); + fprno==3?"CA-FPR-3":"x", fpr, 20, NULL ); if (rc) log_error ("error setting cafpr: %s\n", gpg_strerror (rc)); return rc; @@ -765,7 +918,7 @@ toggle_forcesig (void) newstate = !info.chv1_cached; agent_release_card_info (&info); - rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1); + rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1, NULL); if (rc) log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc)); } @@ -803,12 +956,14 @@ check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1) { int rc = 0; + agent_clear_pin_cache (info->serialno); + *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); + rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno); if (rc) { log_error ("error clearing forced signature PIN flag: %s\n", @@ -836,7 +991,7 @@ restore_forced_chv1 (int *forced_chv1) if (*forced_chv1) { /* Switch back to forced state. */ - rc = agent_scd_setattr ("CHV-STATUS-1", "", 1); + rc = agent_scd_setattr ("CHV-STATUS-1", "", 1, NULL); if (rc) { log_error ("error setting forced signature PIN flag: %s\n", @@ -900,7 +1055,7 @@ generate_card_keys (const char *serialno) want_backup=answer_is_yes_no_default(answer,1); cpr_kill_prompt(); - m_free(answer); + xfree(answer); } #else want_backup = cpr_get_answer_is_yes @@ -949,7 +1104,7 @@ generate_card_keys (const char *serialno) } -/* This fucntion is used by the key edit menu to generate an arbitrary +/* This function is used by the key edit menu to generate an arbitrary subkey. */ int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) @@ -1007,9 +1162,10 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) } -/* Store the subkey at NODE into the smartcard and modify NODE to - carry the serrialno stuff instead of the actual secret key - parameters. */ +/* Store the key at NODE into the smartcard and modify NODE to + carry the serialno stuff instead of the actual secret key + parameters. USE is the usage for that key; 0 means any + usage. */ int card_store_subkey (KBNODE node, int use) { @@ -1140,49 +1296,101 @@ card_store_subkey (KBNODE node, int use) } -/* 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 { + +/* Data used by the command parser. This needs to be outside of the + function scope to allow readline based command completion. */ +enum cmdids + { cmdNOP = 0, - cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, + cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY, cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR, - cmdFORCESIG, cmdGENERATE, cmdPASSWD, + cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdINVCMD }; - static struct { - const char *name; - enum cmdids id; - int admin_only; - const char *desc; - } cmds[] = { - { N_("quit") , cmdQUIT , 0, N_("quit this menu") }, - { N_("q") , cmdQUIT , 0, NULL }, - { N_("admin") , cmdADMIN , 0, N_("show admin commands") }, - { N_("help") , cmdHELP , 0, N_("show this help") }, - { "?" , cmdHELP , 0, NULL }, - { N_("list") , cmdLIST , 0, N_("list all available data") }, - { N_("l") , cmdLIST , 0, NULL }, - { N_("debug") , cmdDEBUG , 0, NULL }, - { N_("name") , cmdNAME , 1, N_("change card holder's name") }, - { N_("url") , cmdURL , 1, N_("change URL to retrieve key") }, - { N_("fetch") , cmdFETCH , 0, - N_("fetch the key specified in the card URL") }, - { N_("login") , cmdLOGIN , 1, N_("change the login name") }, - { N_("lang") , cmdLANG , 1, N_("change the language preferences") }, - { N_("sex") , cmdSEX , 1, N_("change card holder's sex") }, - { N_("cafpr"), cmdCAFPR, 1, N_("change a CA fingerprint") }, - { N_("forcesig"), - cmdFORCESIG, 1, N_("toggle the signature force PIN flag") }, - { N_("generate"), - cmdGENERATE, 1, N_("generate new keys") }, - { N_("passwd"), cmdPASSWD, 0, N_("menu to change or unblock the PIN") }, +static struct +{ + const char *name; + enum cmdids id; + int admin_only; + const char *desc; +} cmds[] = + { + { "quit" , cmdQUIT , 0, N_("quit this menu")}, + { "q" , cmdQUIT , 0, NULL }, + { "admin" , cmdADMIN , 0, N_("show admin commands")}, + { "help" , cmdHELP , 0, N_("show this help")}, + { "?" , cmdHELP , 0, NULL }, + { "list" , cmdLIST , 0, N_("list all available data")}, + { "l" , cmdLIST , 0, NULL }, + { "debug" , cmdDEBUG , 0, NULL }, + { "name" , cmdNAME , 1, N_("change card holder's name")}, + { "url" , cmdURL , 1, N_("change URL to retrieve key")}, + { "fetch" , cmdFETCH , 0, N_("fetch the key specified in the card URL")}, + { "login" , cmdLOGIN , 1, N_("change the login name")}, + { "lang" , cmdLANG , 1, N_("change the language preferences")}, + { "sex" , cmdSEX , 1, N_("change card holder's sex")}, + { "cafpr" , cmdCAFPR , 1, N_("change a CA fingerprint")}, + { "forcesig", cmdFORCESIG, 1, N_("toggle the signature force PIN flag")}, + { "generate", cmdGENERATE, 1, N_("generate new keys")}, + { "passwd" , cmdPASSWD, 0, N_("menu to change or unblock the PIN")}, + { "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")}, + /* Note, that we do not announce this command yet. */ + { "privatedo", cmdPRIVATEDO, 0, NULL }, { NULL, cmdINVCMD, 0, NULL } }; - + + +#if GNUPG_MAJOR_VERSION == 1 && defined (HAVE_LIBREADLINE) + +/* These two functions are used by readline for command completion. */ + +static char * +command_generator(const char *text,int state) +{ + static int list_index,len; + const char *name; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the + index variable to 0. */ + if(!state) + { + list_index=0; + len=strlen(text); + } + + /* Return the next partial match */ + while((name=cmds[list_index].name)) + { + /* Only complete commands that have help text */ + if(cmds[list_index++].desc && strncmp(name,text,len)==0) + return strdup(name); + } + + return NULL; +} + +static char ** +card_edit_completion(const char *text, int start, int end) +{ + /* If we are at the start of a line, we try and command-complete. + If not, just do nothing for now. */ + + if(start==0) + return rl_completion_matches(text,command_generator); + + rl_attempted_completion_over=1; + + return NULL; +} +#endif /* GNUPG_MAJOR_VERSION == 1 && HAVE_LIBREADLINE */ + +/* 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 cmd = cmdNOP; int have_commands = !!commands; int redisplay = 1; @@ -1195,7 +1403,7 @@ card_edit (STRLIST commands) ; else if (opt.batch && !have_commands) { - log_error(_("can't do that in batchmode\n")); + log_error(_("can't do this in batch mode\n")); goto leave; } @@ -1243,8 +1451,14 @@ card_edit (STRLIST commands) if (!have_commands) { +#if GNUPG_MAJOR_VERSION == 1 + tty_enable_completion (card_edit_completion); +#endif answer = cpr_get_no_help("cardedit.prompt", _("Command> ")); cpr_kill_prompt(); +#if GNUPG_MAJOR_VERSION == 1 + tty_disable_completion (); +#endif } trim_spaces(answer); } @@ -1292,9 +1506,33 @@ card_edit (STRLIST commands) break; case cmdADMIN: - allow_admin=!allow_admin; + if ( !strcmp (arg_string, "on") ) + allow_admin = 1; + else if ( !strcmp (arg_string, "off") ) + allow_admin = 0; + else if ( !strcmp (arg_string, "verify") ) + { + /* Force verification of the Admin Command. However, + this is only done if the retry counter is at initial + state. */ + char *tmp = xmalloc (strlen (serialnobuf) + 6 + 1); + strcpy (stpcpy (tmp, serialnobuf), "[CHV3]"); + allow_admin = !agent_scd_checkpin (tmp); + xfree (tmp); + } + else /* Toggle. */ + allow_admin=!allow_admin; + if(allow_admin) + tty_printf(_("Admin commands are allowed\n")); + else + tty_printf(_("Admin commands are not allowed\n")); break; + case cmdVERIFY: + agent_scd_checkpin (serialnobuf); + redisplay = 1; + break; + case cmdLIST: redisplay = 1; break; @@ -1331,6 +1569,14 @@ card_edit (STRLIST commands) change_cafpr (arg_number); break; + case cmdPRIVATEDO: + if ( arg_number < 1 || arg_number > 4 ) + tty_printf ("usage: privatedo N\n" + " 1 <= N <= 4\n"); + else + change_private_do (arg_string, arg_number); + break; + case cmdFORCESIG: toggle_forcesig (); break; diff --git a/g10/cipher.c b/g10/cipher.c index 3d51a874a..ff1080495 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -1,5 +1,6 @@ /* cipher.c - En-/De-ciphering filter - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -28,7 +30,6 @@ #include "gpg.h" #include "errors.h" #include "iobuf.h" -#include "memory.h" #include "util.h" #include "filter.h" #include "packet.h" @@ -41,17 +42,17 @@ static void -write_header( cipher_filter_context_t *cfx, iobuf_t a ) +write_header( cipher_filter_context_t *cfx, IOBUF a ) { + gcry_error_t err; 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 ) + blocksize = gcry_cipher_algo_blklen (cfx->dek->algo); + if ( blocksize < 8 || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); memset( &ed, 0, sizeof ed ); @@ -60,9 +61,9 @@ write_header( cipher_filter_context_t *cfx, iobuf_t a ) 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 ); + gcry_md_open (&cfx->mdc_hash, DIGEST_ALGO_SHA1, 0); if ( DBG_HASHING ) - gcry_md_start_debug ( cfx->mdc_hash, "creatmdc" ); + gcry_md_start_debug (cfx->mdc_hash, "creatmdc"); } { @@ -78,28 +79,31 @@ write_header( cipher_filter_context_t *cfx, iobuf_t a ) if( build_packet( a, &pkt )) log_bug("build_packet(ENCR_DATA) failed\n"); nprefix = blocksize; - gcry_randomize ( temp, nprefix, GCRY_STRONG_RANDOM); + 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)); + err = 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. */ + /* 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 ); + 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; } @@ -111,7 +115,7 @@ write_header( cipher_filter_context_t *cfx, iobuf_t a ) */ int cipher_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; cipher_filter_context_t *cfx = opaque; @@ -125,32 +129,31 @@ cipher_filter( void *opaque, int control, 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); + 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)); + 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_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 ); + 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) + gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0); + gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL; + if( iobuf_write( a, temp, 22 ) ) log_error("writing MDC packet failed\n" ); } gcry_cipher_close (cfx->cipher_hd); @@ -160,6 +163,3 @@ cipher_filter( void *opaque, int control, } return rc; } - - - diff --git a/g10/compress.c b/g10/compress.c index 7dce1790a..030a4c1d1 100644 --- a/g10/compress.c +++ b/g10/compress.c @@ -1,6 +1,6 @@ /* compress.c - compress filter * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * 2003, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,9 +16,16 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ +/* Note that the code in compress-bz2.c is nearly identical to the + code here, so if you fix a bug here, look there to see if a + matching bug needs to be fixed. I tried to have one set of + functions that could do ZIP, ZLIB, and BZIP2, but it became + dangerously unreadable with #ifdefs and if(algo) -dshaw */ + #include <config.h> #include <stdio.h> #include <stdlib.h> @@ -27,43 +34,42 @@ #include <assert.h> #include <errno.h> #include <zlib.h> -#ifdef __riscos__ +#if defined(__riscos__) && defined(USE_ZLIBRISCOS) # include "zlib-riscos.h" -#endif +#endif #include "gpg.h" #include "util.h" -#include "memory.h" #include "packet.h" #include "filter.h" #include "main.h" #include "options.h" +int compress_filter_bz2( void *opaque, int control, + IOBUF a, byte *buf, size_t *ret_len); + static void init_compress( compress_filter_context_t *zfx, z_stream *zs ) { int rc; int level; -#ifdef __riscos__ +#if defined(__riscos__) && defined(USE_ZLIBRISCOS) 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 ) + if( opt.compress_level >= 1 && opt.compress_level <= 9 ) + level = opt.compress_level; + else if( opt.compress_level == -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 ) @@ -75,13 +81,13 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs ) } zfx->outbufsize = 8192; - zfx->outbuf = xmalloc ( zfx->outbufsize ); + zfx->outbuf = xmalloc( zfx->outbufsize ); } static int -do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, iobuf_t a ) +do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a ) { - gpg_error_t rc; + int rc; int zrc; unsigned n; @@ -111,12 +117,10 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, iobuf_t a (unsigned)zs->avail_in, (unsigned)zs->avail_out, (unsigned)n, zrc ); - rc = iobuf_write (a, zfx->outbuf, n); - if (rc) - { + if( (rc=iobuf_write( a, zfx->outbuf, n )) ) { log_debug("deflate: iobuf_write failed\n"); return rc; - } + } } while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) ); return 0; } @@ -145,13 +149,13 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs ) } zfx->inbufsize = 2048; - zfx->inbuf = xmalloc ( zfx->inbufsize ); + 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 ) + IOBUF a, size_t *ret_len ) { int zrc; int rc=0; @@ -213,9 +217,9 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, return rc; } -int +static int compress_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; compress_filter_context_t *zfx = opaque; @@ -224,7 +228,7 @@ compress_filter( void *opaque, int control, if( control == IOBUFCTRL_UNDERFLOW ) { if( !zfx->status ) { - zs = zfx->opaque = xcalloc (1, sizeof *zs ); + zs = zfx->opaque = xmalloc_clear( sizeof *zs ); init_uncompress( zfx, zs ); zfx->status = 1; } @@ -242,10 +246,8 @@ compress_filter( void *opaque, int control, if( !zfx->status ) { PACKET pkt; PKT_compressed cd; - - if( !zfx->algo ) - zfx->algo = DEFAULT_COMPRESS_ALGO; - if( zfx->algo != 1 && zfx->algo != 2 ) + if(zfx->algo != COMPRESS_ALGO_ZIP + && zfx->algo != COMPRESS_ALGO_ZLIB) BUG(); memset( &cd, 0, sizeof cd ); cd.len = 0; @@ -255,7 +257,7 @@ compress_filter( void *opaque, int control, pkt.pkt.compressed = &cd; if( build_packet( a, &pkt )) log_bug("build_packet(PKT_COMPRESSED) failed\n"); - zs = zfx->opaque = xcalloc (1, sizeof *zs ); + zs = zfx->opaque = xmalloc_clear( sizeof *zs ); init_compress( zfx, zs ); zfx->status = 2; } @@ -271,9 +273,9 @@ compress_filter( void *opaque, int control, else if( control == IOBUFCTRL_FREE ) { if( zfx->status == 1 ) { inflateEnd(zs); - xfree (zs); + xfree(zs); zfx->opaque = NULL; - xfree (zfx->outbuf); zfx->outbuf = NULL; + xfree(zfx->outbuf); zfx->outbuf = NULL; } else if( zfx->status == 2 ) { #ifndef __riscos__ @@ -284,9 +286,9 @@ compress_filter( void *opaque, int control, zs->avail_in = 0; do_compress( zfx, zs, Z_FINISH, a ); deflateEnd(zs); - xfree (zs); + xfree(zs); zfx->opaque = NULL; - xfree (zfx->outbuf); zfx->outbuf = NULL; + xfree(zfx->outbuf); zfx->outbuf = NULL; } if (zfx->release) zfx->release (zfx); @@ -308,17 +310,17 @@ release_context (compress_filter_context_t *ctx) */ int handle_compressed( void *procctx, PKT_compressed *cd, - int (*callback)(iobuf_t, void *), void *passthru ) + int (*callback)(IOBUF, 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; + if(check_compress_algo(cd->algorithm)) + return G10ERR_COMPR_ALGO; + cfx = xmalloc_clear (sizeof *cfx); cfx->release = release_context; - iobuf_push_filter( cd->buf, compress_filter, cfx ); + cfx->algo = cd->algorithm; + push_compress_filter(cd->buf,cfx,cd->algorithm); if( callback ) rc = callback(cd->buf, passthru ); else @@ -327,3 +329,38 @@ handle_compressed( void *procctx, PKT_compressed *cd, return rc; } +void +push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo) +{ + push_compress_filter2(out,zfx,algo,0); +} + +void +push_compress_filter2(IOBUF out,compress_filter_context_t *zfx, + int algo,int rel) +{ + if(algo>=0) + zfx->algo=algo; + else + zfx->algo=DEFAULT_COMPRESS_ALGO; + + switch(zfx->algo) + { + case COMPRESS_ALGO_NONE: + break; + + case COMPRESS_ALGO_ZIP: + case COMPRESS_ALGO_ZLIB: + iobuf_push_filter2(out,compress_filter,zfx,rel); + break; + +#ifdef HAVE_BZIP2 + case COMPRESS_ALGO_BZIP2: + iobuf_push_filter2(out,compress_filter_bz2,zfx,rel); + break; +#endif + + default: + BUG(); + } +} diff --git a/g10/dearmor.c b/g10/dearmor.c index 4f9fa2db7..dc9a22fad 100644 --- a/g10/dearmor.c +++ b/g10/dearmor.c @@ -1,5 +1,5 @@ /* dearmor.c - Armor utility - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -28,13 +29,12 @@ #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 "i18n.h" /**************** * Take an armor file and write it out without armor @@ -43,17 +43,24 @@ int dearmor_file( const char *fname ) { armor_filter_context_t afx; - iobuf_t inp = NULL, out = NULL; + IOBUF 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]", + inp = iobuf_open(fname); + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if (!inp) { + log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); + rc = G10ERR_OPEN_FILE; goto leave; } @@ -85,17 +92,24 @@ int enarmor_file( const char *fname ) { armor_filter_context_t afx; - iobuf_t inp = NULL, out = NULL; + IOBUF 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) ); + inp = iobuf_open(fname); + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if (!inp) { + log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", + strerror(errno) ); + rc = G10ERR_OPEN_FILE; goto leave; } diff --git a/g10/decrypt.c b/g10/decrypt.c index 98a270cfb..9a37283c1 100644 --- a/g10/decrypt.c +++ b/g10/decrypt.c @@ -1,5 +1,6 @@ /* decrypt.c - verify signed data - * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,12 +27,12 @@ #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 "status.h" @@ -49,17 +51,24 @@ int decrypt_message( const char *filename ) { - iobuf_t fp; + IOBUF fp; armor_filter_context_t afx; progress_filter_context_t pfx; int rc; int no_out=0; - /* open the message file */ + /* Open the message file. */ fp = iobuf_open(filename); + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } if( !fp ) { rc = gpg_error_from_errno (errno); - log_error(_("can't open `%s'\n"), print_fname_stdin(filename)); + log_error (_("can't open `%s': %s\n"), print_fname_stdin(filename), + gpg_strerror (rc)); return rc; } @@ -84,13 +93,14 @@ decrypt_message( const char *filename ) } void -decrypt_messages(int nfiles, char **files) +decrypt_messages(int nfiles, char *files[]) { - iobuf_t fp; + IOBUF fp; armor_filter_context_t afx; progress_filter_context_t pfx; char *p, *output = NULL; - int rc = 0; + int rc=0,use_stdin=0; + unsigned int lno=0; if (opt.outfile) { @@ -99,20 +109,61 @@ decrypt_messages(int nfiles, char **files) } - while (nfiles--) + if(!nfiles) + use_stdin=1; + + for(;;) { - print_file_status(STATUS_FILE_START, *files, 3); - output = make_outfile_name(*files); + char line[2048]; + char *filename=NULL; + + if(use_stdin) + { + if(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); + else + { + line[strlen(line)-1] = '\0'; + filename=line; + } + } + } + else + { + if(nfiles) + { + filename=*files; + nfiles--; + files++; + } + } + + if(filename==NULL) + break; + + print_file_status(STATUS_FILE_START, filename, 3); + output = make_outfile_name(filename); if (!output) goto next_file; - fp = iobuf_open(*files); + fp = iobuf_open(filename); + if (fp) + iobuf_ioctl (fp,3,1,NULL); /* disable fd caching */ + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } if (!fp) { - log_error(_("can't open `%s'\n"), print_fname_stdin(*files)); + log_error(_("can't open `%s'\n"), print_fname_stdin(filename)); goto next_file; } - handle_progress (&pfx, fp, *files); + handle_progress (&pfx, fp, filename); if (!opt.no_armor) { @@ -125,8 +176,8 @@ decrypt_messages(int nfiles, char **files) rc = proc_packets(NULL, fp); iobuf_close(fp); if (rc) - log_error("%s: decryption failed: %s\n", print_fname_stdin(*files), - gpg_strerror (rc)); + log_error("%s: decryption failed: %s\n", print_fname_stdin(filename), + g10_errstr(rc)); p = get_last_passphrase(); set_next_passphrase(p); xfree (p); @@ -134,9 +185,8 @@ decrypt_messages(int nfiles, char **files) next_file: /* Note that we emit file_done even after an error. */ write_status( STATUS_FILE_DONE ); - xfree (output); - files++; + xfree(output); } + set_next_passphrase(NULL); } - diff --git a/g10/delkey.c b/g10/delkey.c index 6263dec47..bb8108754 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -1,5 +1,6 @@ /* delkey.c - delete keys - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, + * 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,12 +28,12 @@ #include <assert.h> #include <ctype.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 "trustdb.h" @@ -47,7 +49,7 @@ * key can't be deleted for that reason. */ static int -do_delete_key( const char *username, int secret, int *r_sec_avail ) +do_delete_key( const char *username, int secret, int force, int *r_sec_avail ) { int rc = 0; KBNODE keyblock = NULL; @@ -68,9 +70,9 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) 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; + rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID; if (rc) { - log_error (_("key `%s' not found: %s\n"), username, gpg_strerror (rc)); + log_error (_("key \"%s\" not found: %s\n"), username, g10_errstr (rc)); write_status_text( STATUS_DELETE_PROBLEM, "1" ); goto leave; } @@ -78,7 +80,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) /* read the keyblock */ rc = keydb_get_keyblock (hd, &keyblock ); if (rc) { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); goto leave; } @@ -86,29 +88,36 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) 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; + rc = G10ERR_GENERAL; goto leave; } - if( secret ) { + if( secret ) + { sk = node->pkt->pkt.secret_key; keyid_from_sk( sk, keyid ); - } - else { + } + else + { + /* public */ 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(!force) + { + rc = seckey_available( keyid ); + if( !rc ) + { + *r_sec_avail = 1; + rc = -1; + goto leave; + } + else if( rc != G10ERR_NO_SECKEY ) + log_error("%s: get secret key: %s\n", username, g10_errstr(rc) ); + else + rc = 0; + } + } if( rc ) rc = 0; @@ -116,26 +125,26 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) okay++; else if( opt.batch && secret ) { - log_error(_("can't do that in batchmode\n")); + log_error(_("can't do this in batch mode\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_error(_("can't do this in batch mode 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 ); + 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? ")); + _("Delete this key from the keyring? (y/N) ")); 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 @@ -143,7 +152,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) * basic texts about security. */ yes = cpr_get_answer_is_yes("delete_key.secret.okay", - _("This is a secret key! - really delete? ")); + _("This is a secret key! - really delete? (y/N) ")); } if( yes ) okay++; @@ -153,7 +162,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) if( okay ) { rc = keydb_delete_keyblock (hd); if (rc) { - log_error (_("deleting keyblock failed: %s\n"), gpg_strerror (rc) ); + log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) ); goto leave; } @@ -179,15 +188,18 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) int delete_keys( STRLIST names, int secret, int allow_both ) { - int rc, avail; + int rc, avail, force=(!allow_both && !secret && opt.expert); + + /* Force allows us to delete a public key even if a secret key + exists. */ for(;names;names=names->next) { - rc = do_delete_key (names->d, secret, &avail ); + rc = do_delete_key (names->d, secret, force, &avail ); if ( rc && avail ) { if ( allow_both ) { - rc = do_delete_key (names->d, 1, &avail ); + rc = do_delete_key (names->d, 1, 0, &avail ); if ( !rc ) - rc = do_delete_key (names->d, 0, &avail ); + rc = do_delete_key (names->d, 0, 0, &avail ); } else { log_error(_( @@ -200,7 +212,7 @@ delete_keys( STRLIST names, int secret, int allow_both ) } if(rc) { - log_error("%s: delete key failed: %s\n", names->d, gpg_strerror (rc) ); + log_error("%s: delete key failed: %s\n", names->d, g10_errstr(rc) ); return rc; } } diff --git a/g10/encode.c b/g10/encode.c index 7794bdb7c..57f2272dd 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -1,6 +1,6 @@ /* encode.c - encode data - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -32,7 +33,6 @@ #include "errors.h" #include "iobuf.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "main.h" #include "filter.h" @@ -42,10 +42,8 @@ #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 ); - - +static int encode_simple( const char *filename, int mode, int use_seskey ); +static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ); /**************** * Encode FILENAME with only the symmetric cipher. Take input from @@ -54,17 +52,7 @@ static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out ); 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 ); + return encode_simple( filename, 1, 0 ); } /**************** @@ -74,69 +62,62 @@ encode_symmetric( const char *filename ) int encode_store( const char *filename ) { - return encode_simple( filename, 0, 1 ); + return encode_simple( filename, 0, 0 ); } + static void -encode_sesskey (DEK * dek, DEK ** ret_dek, byte * enckey) +encode_seskey( DEK *dek, DEK **seskey, byte *enckey ) { - CIPHER_HANDLE hd; - DEK * c; - byte buf[33]; + gcry_cipher_hd_t hd; + 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); + assert ( dek->keylen <= 32 ); + if(!*seskey) + { + *seskey=xmalloc_clear(sizeof(DEK)); + (*seskey)->keylen=dek->keylen; + (*seskey)->algo=dek->algo; + make_session_key(*seskey); + /*log_hexdump( "thekey", c->key, c->keylen );*/ + } + + /* The encrypted session key is prefixed with a one-octet algorithm id. */ + buf[0] = (*seskey)->algo; + memcpy( buf + 1, (*seskey)->key, (*seskey)->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 only pass already checked values to the following fucntion, + thus we consider any 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 (); + gry_cipher_setiv (hd, NULL, 0); + gcry_cipher_encrypt (hd, buf, (*seskey)->keylen + 1, NULL, 0); + gcry_cipher_close (hd); + + memcpy( enckey, buf, (*seskey)->keylen + 1 ); + wipememory( buf, sizeof buf ); /* burn key */ } /* We try very hard to use a MDC */ static int -use_mdc (PK_LIST pk_list,int algo) +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) + if(opt.force_mdc) return 1; - if (opt.disable_mdc) + if(opt.disable_mdc) return 0; /* Do the keys really support MDC? */ - if (select_mdc_from_pklist (pk_list)) + 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 @@ -144,26 +125,40 @@ use_mdc (PK_LIST pk_list,int algo) 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; - } + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_AES,NULL)==CIPHER_ALGO_AES) + return 1; + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_AES192,NULL)==CIPHER_ALGO_AES192) + return 1; + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_AES256,NULL)==CIPHER_ALGO_AES256) + return 1; + + if(select_algo_from_prefs(pk_list,PREFTYPE_SYM, + CIPHER_ALGO_TWOFISH,NULL)==CIPHER_ALGO_TWOFISH) + return 1; /* Last try. Use MDC for the modern ciphers. */ + if (gcry_cipher_get_algo_blklen (algo) != 8) return 1; return 0; /* No MDC */ } +/* We don't want to use use_seskey yet because older gnupg versions + can't handle it, and there isn't really any point unless we're + making a message that can be decrypted by a public key or + passphrase. */ static int -encode_simple( const char *filename, int mode, int compat ) +encode_simple( const char *filename, int mode, int use_seskey ) { - iobuf_t inp, out; + IOBUF inp, out; PACKET pkt; - DEK *dek = NULL; PKT_plaintext *pt = NULL; STRING2KEY *s2k = NULL; byte enckey[33]; @@ -175,7 +170,7 @@ encode_simple( const char *filename, int mode, int compat ) compress_filter_context_t zfx; text_filter_context_t tfx; progress_filter_context_t pfx; - int do_compress = opt.compress && !RFC1991; + int do_compress = !RFC1991 && default_compress_algo(); memset( &cfx, 0, sizeof cfx); memset( &afx, 0, sizeof afx); @@ -184,10 +179,19 @@ encode_simple( const char *filename, int mode, int compat ) init_packet(&pkt); /* prepare iobufs */ - if( !(inp = iobuf_open(filename)) ) { + inp = iobuf_open(filename); + if (inp) + iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */ + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if( !inp ) { rc = gpg_error_from_errno (errno); - log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]", - strerror(errno) ); + log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]" + strerror(errno) ); return rc; } @@ -199,42 +203,49 @@ encode_simple( const char *filename, int mode, int compat ) /* 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; + if ( RFC1991 && use_seskey ) + use_seskey = 0; cfx.dek = NULL; if( mode ) { - s2k = xcalloc (1, sizeof *s2k ); + s2k = xmalloc_clear( sizeof *s2k ); s2k->mode = RFC1991? 0:opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; + s2k->hash_algo=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); + 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) ); + log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc)); return rc; } - if (!compat && s2k->mode != 1 && s2k->mode != 3) { - compat = 1; + if (use_seskey && s2k->mode != 1 && s2k->mode != 3) { + use_seskey = 0; 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; - } + if ( use_seskey ) + { + DEK *dek = NULL; + + seskeylen = gcry_cipher_get_algo_keylen (default_cipher_algo ()); + encode_seskey( cfx.dek, &dek, enckey ); + xfree( cfx.dek ); cfx.dek = dek; + } + + if(opt.verbose) + log_info(_("using cipher %s\n"), + gcry_cipher_algo_name (cfx.dek->algo)); 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 (do_compress && cfx.dek && cfx.dek->use_mdc + && is_file_compressed(filename, &rc)) { if (opt.verbose) log_info(_("`%s' already compressed\n"), filename); @@ -243,52 +254,43 @@ encode_simple( const char *filename, int mode, int compat ) if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) { iobuf_cancel(inp); - xfree (cfx.dek); - xfree (s2k); + 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 ); + PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; enc->s2k = *s2k; - if ( !compat && seskeylen ) { + if ( use_seskey && 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); + log_error("build symkey packet failed: %s\n", g10_errstr(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 ); + 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); + xfree(s); } else { /* no filename */ - pt = xmalloc ( sizeof *pt - 1 ); + pt = xmalloc( sizeof *pt - 1 ); pt->namelen = 0; } } @@ -304,12 +306,14 @@ encode_simple( const char *filename, int mode, int compat ) either partial length or fixed length with the new style messages. */ - if (filename && *filename && !(*filename == '-' && !filename[1]) - && !opt.textmode ) { + if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) + { off_t tmpsize; + int overflow; - if ( !(tmpsize = iobuf_get_filelength(inp)) ) - log_info(_("%s: WARNING: empty file\n"), filename ); + if ( !(tmpsize = iobuf_get_filelength(inp, &overflow)) + && !overflow ) + log_info(_("WARNING: `%s' is an 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 @@ -318,9 +322,9 @@ encode_simple( const char *filename, int mode, int compat ) filesize = tmpsize; else filesize = 0; - } + } else - filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ + filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { pt->timestamp = make_timestamp(); @@ -347,14 +351,13 @@ encode_simple( const char *filename, int mode, int compat ) { if (cfx.dek && cfx.dek->use_mdc) zfx.new_ctb = 1; - zfx.algo=default_compress_algo(); - iobuf_push_filter( out, compress_filter, &zfx ); + push_compress_filter(out,&zfx,default_compress_algo()); } /* do the work */ if (!opt.no_literal) { if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet failed: %s\n", gpg_strerror (rc) ); + log_error("build_packet failed: %s\n", g10_errstr(rc) ); } else { /* user requested not to create a literal packet, @@ -362,8 +365,9 @@ encode_simple( const char *filename, int mode, int compat ) 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) ); + if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; + log_error("copying input to output failed: %s\n", g10_errstr(rc) ); break; } wipememory(copy_buffer, 4096); /* burn buffer */ @@ -381,21 +385,70 @@ encode_simple( const char *filename, int mode, int compat ) if (pt) pt->buf = NULL; free_packet(&pkt); - xfree (cfx.dek); - xfree (s2k); + xfree(cfx.dek); + xfree(s2k); return rc; } +int +setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek) +{ + *symkey_s2k=xmalloc_clear(sizeof(STRING2KEY)); + (*symkey_s2k)->mode = opt.s2k_mode; + (*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO; + + *symkey_dek=passphrase_to_dek(NULL,0,opt.s2k_cipher_algo, + *symkey_s2k,2,NULL,NULL); + if(!*symkey_dek || !(*symkey_dek)->keylen) + { + xfree(*symkey_dek); + xfree(*symkey_s2k); + return G10ERR_PASSPHRASE; + } + + return 0; +} + +static int +write_symkey_enc(STRING2KEY *symkey_s2k,DEK *symkey_dek,DEK *dek,IOBUF out) +{ + int rc,seskeylen=cipher_get_keylen(dek->algo)/8; + + PKT_symkey_enc *enc; + byte enckey[33]; + PACKET pkt; + + enc=xmalloc_clear(sizeof(PKT_symkey_enc)+seskeylen+1); + encode_seskey(symkey_dek,&dek,enckey); + + enc->version = 4; + enc->cipher_algo = opt.s2k_cipher_algo; + enc->s2k = *symkey_s2k; + 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_enc packet failed: %s\n",g10_errstr(rc)); + + xfree(enc); + return rc; +} + /**************** * Encrypt the file with the given userids (or ask if none * is supplied). */ int -encode_crypt( const char *filename, STRLIST remusr ) +encode_crypt( const char *filename, STRLIST remusr, int use_symkey ) { - iobuf_t inp = NULL, out = NULL; + IOBUF inp = NULL, out = NULL; PACKET pkt; PKT_plaintext *pt = NULL; + DEK *symkey_dek = NULL; + STRING2KEY *symkey_s2k = NULL; int rc = 0, rc2 = 0; u32 filesize; cipher_filter_context_t cfx; @@ -404,8 +457,7 @@ encode_crypt( const char *filename, STRLIST remusr ) text_filter_context_t tfx; progress_filter_context_t pfx; PK_LIST pk_list,work_list; - int do_compress = opt.compress && !RFC1991; - + int do_compress = opt.compress_algo && !RFC1991; memset( &cfx, 0, sizeof cfx); memset( &afx, 0, sizeof afx); @@ -413,6 +465,10 @@ encode_crypt( const char *filename, STRLIST remusr ) memset( &tfx, 0, sizeof tfx); init_packet(&pkt); + if(use_symkey + && (rc=setup_symkey(&symkey_s2k,&symkey_dek))) + return rc; + if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) ) return rc; @@ -429,10 +485,20 @@ encode_crypt( const char *filename, STRLIST remusr ) } /* prepare iobufs */ - if( !(inp = iobuf_open(filename)) ) { + inp = iobuf_open(filename); + if (inp) + iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */ + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if( !inp ) { rc = gpg_error_from_errno (errno); - log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]", - strerror(errno) ); + log_error(_("can't open `%s': %s\n"), + filename? filename: "[stdin]", + gpg_strerror (rc) ); goto leave; } else if( opt.verbose ) @@ -446,19 +512,11 @@ encode_crypt( const char *filename, STRLIST remusr ) 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); + cfx.dek = xmalloc_secure_clear (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 @@ -482,8 +540,8 @@ encode_crypt( const char *filename, STRLIST remusr ) 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"), + log_info(_("WARNING: forcing symmetric cipher %s (%d)" + " violates recipient preferences\n"), gcry_cipher_algo_name (opt.def_cipher_algo), opt.def_cipher_algo); @@ -497,8 +555,7 @@ encode_crypt( const char *filename, STRLIST remusr ) 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 (do_compress && cfx.dek->use_mdc && is_file_compressed(filename, &rc2) ) { if (opt.verbose) log_info(_("`%s' already compressed\n"), filename); @@ -518,40 +575,49 @@ encode_crypt( const char *filename, STRLIST remusr ) if( rc ) goto leave; + /* We put the passphrase (if any) after any public keys as this + seems to be the most useful on the recipient side - there is no + point in prompting a user for a passphrase if they have the + secret key needed to decrypt. */ + if(use_symkey && (rc=write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out))) + 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 ); + : 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); + xfree(s); } else { /* no filename */ - pt = xmalloc ( sizeof *pt - 1 ); + pt = xmalloc( sizeof *pt - 1 ); pt->namelen = 0; } } - if (filename && *filename && !(*filename == '-' && !filename[1]) - && !opt.textmode ) { + if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) + { off_t tmpsize; + int overflow; - if ( !(tmpsize = iobuf_get_filelength(inp)) ) - log_info(_("%s: WARNING: empty file\n"), filename ); + if ( !(tmpsize = iobuf_get_filelength(inp, &overflow)) + && !overflow ) + log_info(_("WARNING: `%s' is an 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) ) + if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) ) filesize = tmpsize; else filesize = 0; - } + } else - filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ + filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { pt->timestamp = make_timestamp(); @@ -571,7 +637,7 @@ encode_crypt( const char *filename, STRLIST remusr ) /* register the compress filter */ if( do_compress ) { - int compr_algo = opt.def_compress_algo; + int compr_algo = opt.compress_algo; if(compr_algo==-1) { @@ -584,8 +650,8 @@ encode_crypt( const char *filename, STRLIST remusr ) 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"), + log_info(_("WARNING: forcing compression algorithm %s (%d)" + " violates recipient preferences\n"), compress_algo_to_string(compr_algo),compr_algo); /* algo 0 means no compression */ @@ -593,15 +659,14 @@ encode_crypt( const char *filename, STRLIST remusr ) { if (cfx.dek && cfx.dek->use_mdc) zfx.new_ctb = 1; - zfx.algo = compr_algo; - iobuf_push_filter( out, compress_filter, &zfx ); + push_compress_filter(out,&zfx,compr_algo); } } /* do the work */ if (!opt.no_literal) { if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet failed: %s\n", gpg_strerror (rc) ); + log_error("build_packet failed: %s\n", g10_errstr(rc) ); } else { /* user requested not to create a literal packet, so we copy @@ -609,9 +674,10 @@ encode_crypt( const char *filename, STRLIST remusr ) 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))) { + if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; log_error("copying input to output failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); break; } wipememory(copy_buffer, 4096); /* burn buffer */ @@ -629,7 +695,9 @@ encode_crypt( const char *filename, STRLIST remusr ) if( pt ) pt->buf = NULL; free_packet(&pkt); - xfree (cfx.dek); + xfree(cfx.dek); + xfree(symkey_dek); + xfree(symkey_s2k); release_pk_list( pk_list ); return rc; } @@ -642,7 +710,7 @@ encode_crypt( const char *filename, STRLIST remusr ) */ int encrypt_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; encrypt_filter_context_t *efx = opaque; @@ -653,7 +721,7 @@ encrypt_filter( void *opaque, int control, } else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { - efx->cfx.dek = xcalloc_secure (1, sizeof *efx->cfx.dek ); + efx->cfx.dek = xmalloc_secure_clear( sizeof *efx->cfx.dek ); if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ efx->cfx.dek->algo = @@ -688,6 +756,14 @@ encrypt_filter( void *opaque, int control, if( rc ) return rc; + if(efx->symkey_s2k && efx->symkey_dek) + { + rc=write_symkey_enc(efx->symkey_s2k,efx->symkey_dek, + efx->cfx.dek,a); + if(rc) + return rc; + } + iobuf_push_filter( a, cipher_filter, &efx->cfx ); efx->header_okay = 1; @@ -695,8 +771,11 @@ encrypt_filter( void *opaque, int control, rc = iobuf_write( a, buf, size ); } - else if( control == IOBUFCTRL_FREE ) { - } + else if( control == IOBUFCTRL_FREE ) + { + xfree(efx->symkey_dek); + xfree(efx->symkey_s2k); + } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "encrypt_filter"; } @@ -708,7 +787,7 @@ encrypt_filter( void *opaque, int control, * 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 ) +write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) { PACKET pkt; PKT_public_key *pk; @@ -716,12 +795,12 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out ) int rc; for( ; pk_list; pk_list = pk_list->next ) { - gcry_mpi_t frame; + MPI frame; pk = pk_list->pk; print_pubkey_algo_note( pk->pubkey_algo ); - enc = xcalloc (1, sizeof *enc ); + enc = xmalloc_clear( sizeof *enc ); enc->pubkey_algo = pk->pubkey_algo; keyid_from_pk( pk, enc->keyid ); enc->throw_keyid = (opt.throw_keyid || (pk_list->flags&1)); @@ -742,23 +821,24 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out ) * 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 + * (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 ); + 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) ); + log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) ); else { if( opt.verbose ) { - char *ustr = get_user_id_string_printable (enc->keyid); + char *ustr = get_user_id_string_native (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); + gcry_pk_algo_name (enc->pubkey_algo), + gcry_cipher_algo_name (dek->algo), + ustr ); + xfree(ustr); } /* and write it */ init_packet(&pkt); @@ -766,7 +846,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, iobuf_t out ) pkt.pkt.pubkey_enc = enc; rc = build_packet( out, &pkt ); if( rc ) - log_error("build_packet(pubkey_enc) failed: %s\n", gpg_strerror (rc)); + log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc)); } free_pubkey_enc(enc); if( rc ) @@ -800,9 +880,9 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr) } 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) ); + if ( (rc = encode_crypt(line, remusr, 0)) ) + log_error("encryption of `%s' failed: %s\n", + print_fname_stdin(line), g10_errstr(rc) ); write_status( STATUS_FILE_DONE ); } } @@ -811,9 +891,9 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr) 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) ); + if ( (rc = encode_crypt(*files, remusr, 0)) ) + log_error("encryption of `%s' failed: %s\n", + print_fname_stdin(*files), g10_errstr(rc) ); write_status( STATUS_FILE_DONE ); files++; } diff --git a/g10/encr-data.c b/g10/encr-data.c index 074408404..cf2e43da7 100644 --- a/g10/encr-data.c +++ b/g10/encr-data.c @@ -1,5 +1,6 @@ /* encr-data.c - process an encrypted data packet - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,25 +28,24 @@ #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, +static int mdc_decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); -static int decode_filter( void *opaque, int control, iobuf_t a, +static int decode_filter( void *opaque, int control, IOBUF 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; +typedef struct +{ + gcry_cipher_hd_t cipher_hd; + gcry_md_hd_t mdc_hash; + char defer[20]; + int defer_filled; + int eof_seen; } decode_filter_ctx_t; @@ -70,7 +71,8 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) log_info(_("encrypted with unknown algorithm %d\n"), dek->algo ); dek->algo_info_printed = 1; } - if( (rc=openpgp_cipher_test_algo(dek->algo)) ) + rc = openpgp_cipher_test_algo (dek->algo); + if (rc) goto leave; blocksize = gcry_cipher_get_algo_blklen (dek->algo); if( !blocksize || blocksize > 16 ) @@ -80,31 +82,39 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) BUG(); if( ed->mdc_method ) { - gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 ); + if (gcry_md_open (&dfx.mdc_hash, ed->mdc_method, 0 )) + BUG (); 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(); - } + (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. */ + 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) ); + if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY ) + { + log_info(_("WARNING: message was encrypted with" + " a weak key in the symmetric cipher.\n")); + rc=0; + } + else if( rc ) + { + log_error("key setup failed: %s\n", g10_errstr(rc) ); goto leave; - } + + } if (!ed->buf) { log_error(_("problem handling encrypted packet\n")); goto leave; @@ -112,7 +122,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) gcry_cipher_setiv (dfx.cipher_hd, NULL, 0); - if (ed->len) { + if( ed->len ) { for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) { if( (c=iobuf_get(ed->buf)) == -1 ) break; @@ -127,17 +137,20 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) else temp[i] = c; } - gcry_cipher_decrypt( dfx.cipher_hd, temp, nprefix+2, NULL, 0); - gcry_cipher_sync( dfx.cipher_hd ); + + 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] ) { + if(dek->symmetric + && (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 ); + gcry_md_write (dfx.mdc_hash, temp, nprefix+2); if( ed->mdc_method ) iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx ); @@ -152,18 +165,18 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) 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);*/ + 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:", 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 ); + gcry_cipher_close (dfx.cipher_hd); + gcry_md_close (dfx.mdc_hash); return rc; } @@ -171,7 +184,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) /* I think we should merge this with cipher_filter */ static int -mdc_decode_filter( void *opaque, int control, iobuf_t a, +mdc_decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) { decode_filter_ctx_t *dfx = opaque; @@ -229,8 +242,8 @@ mdc_decode_filter( void *opaque, int control, iobuf_t a, } if( n ) { - gcry_cipher_decrypt( dfx->cipher_hd, buf, n, NULL, 0); - gcry_md_write( dfx->mdc_hash, buf, n ); + gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0); + gcry_md_write (dfx->mdc_hash, buf, n); } else { assert( dfx->eof_seen ); @@ -245,7 +258,7 @@ mdc_decode_filter( void *opaque, int control, iobuf_t a, } static int -decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) +decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) { decode_filter_ctx_t *fc = opaque; size_t n, size = *ret_len; @@ -256,7 +269,7 @@ decode_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) n = iobuf_read( a, buf, size ); if( n == -1 ) n = 0; if( n ) - gcry_cipher_decrypt( fc->cipher_hd, buf, n, NULL, 0); + gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0); else rc = -1; /* eof */ *ret_len = n; diff --git a/g10/exec.c b/g10/exec.c index b1fc2c70f..839964b1d 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -1,5 +1,5 @@ /* exec.c - generic call-a-program code - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -34,12 +35,13 @@ #include <unistd.h> #include <string.h> #include <errno.h> + +#include "gpg.h" #include "options.h" -#include "memory.h" #include "i18n.h" #include "iobuf.h" #include "util.h" -#include "mkdtemp.h" +#include "mkdtemp.h" /* From gnulib. */ #include "exec.h" #ifdef NO_EXEC @@ -47,12 +49,12 @@ 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; + return G10ERR_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; } +int exec_read(struct exec_info *info) { return G10ERR_GENERAL; } +int exec_finish(struct exec_info *info) { return G10ERR_GENERAL; } +int set_exec_path(const char *path) { return G10ERR_GENERAL; } #else /* ! NO_EXEC */ @@ -60,7 +62,7 @@ int set_exec_path(const char *path,int method) { return GPG_ERR_GENERAL; } /* 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) +static int w32_system(const char *command) { PROCESS_INFORMATION pi; STARTUPINFO si; @@ -68,7 +70,7 @@ static int win_system(const char *command) /* We must use a copy of the command as CreateProcess modifies this argument. */ - string=xstrdup (command); + string=xstrdup(command); memset(&pi,0,sizeof(pi)); memset(&si,0,sizeof(si)); @@ -82,42 +84,30 @@ static int win_system(const char *command) CloseHandle(pi.hProcess); CloseHandle(pi.hThread); - xfree (string); + 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) +/* Replaces current $PATH */ +int set_exec_path(const char *path) { - char *p,*curpath=NULL; - size_t curlen=0; - - if(method==1 && (curpath=getenv("PATH"))) - curlen=strlen(curpath)+1; + char *p; - p=xmalloc (5+curlen+strlen(path)+1); + p=xmalloc(5+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); + log_debug("set_exec_path: %s\n",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; + return G10ERR_GENERAL; else return 0; } @@ -128,16 +118,16 @@ 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"; + namein=info->flags.binary?"tempin" EXTSEP_S "bin":"tempin" EXTSEP_S "txt"; - nameout=info->binary?"tempout" EXTSEP_S "bin":"tempout" EXTSEP_S "txt"; + nameout=info->flags.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); + tmp=xmalloc(256); if(GetTempPath(256,tmp)==0) strcpy(tmp,"c:\\windows\\temp"); else @@ -169,12 +159,12 @@ static int make_tempdir(struct exec_info *info) #endif } - info->tempdir=xmalloc (strlen(tmp)+strlen(DIRSEP_S)+10+1); + info->tempdir=xmalloc(strlen(tmp)+strlen(DIRSEP_S)+10+1); sprintf(info->tempdir,"%s" DIRSEP_S "gpg-XXXXXX",tmp); #if defined (_WIN32) - xfree (tmp); + xfree(tmp); #endif if(mkdtemp(info->tempdir)==NULL) @@ -182,21 +172,21 @@ static int make_tempdir(struct exec_info *info) info->tempdir,strerror(errno)); else { - info->madedir=1; + info->flags.madedir=1; - info->tempfile_in=xmalloc (strlen(info->tempdir)+ + 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) + if(!info->flags.writeonly) { - info->tempfile_out=xmalloc (strlen(info->tempdir)+ + 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; + return info->flags.madedir?0:G10ERR_GENERAL; } /* Expands %i and %o in the args to the full temp files within the @@ -206,14 +196,14 @@ 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; + info->flags.use_temp_files=0; + info->flags.keep_temp_files=0; if(DBG_EXTPROG) log_debug("expanding string \"%s\"\n",args_in); size=100; - info->command=xmalloc (size); + info->command=xmalloc(size); len=0; info->command[0]='\0'; @@ -228,31 +218,31 @@ static int expand_args(struct exec_info *info,const char *args_in) switch(*ch) { case 'O': - info->keep_temp_files=1; + info->flags.keep_temp_files=1; /* fall through */ case 'o': /* out */ - if(!info->madedir) + if(!info->flags.madedir) { if(make_tempdir(info)) goto fail; } append=info->tempfile_out; - info->use_temp_files=1; + info->flags.use_temp_files=1; break; case 'I': - info->keep_temp_files=1; + info->flags.keep_temp_files=1; /* fall through */ case 'i': /* in */ - if(!info->madedir) + if(!info->flags.madedir) { if(make_tempdir(info)) goto fail; } append=info->tempfile_in; - info->use_temp_files=1; + info->flags.use_temp_files=1; break; case '%': @@ -293,17 +283,17 @@ static int expand_args(struct exec_info *info,const char *args_in) } if(DBG_EXTPROG) - log_debug("args expanded to \"%s\", use %d, keep %d\n", - info->command,info->use_temp_files,info->keep_temp_files); + log_debug("args expanded to \"%s\", use %u, keep %u\n",info->command, + info->flags.use_temp_files,info->flags.keep_temp_files); return 0; fail: - xfree (info->command); + xfree(info->command); info->command=NULL; - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } /* Either handles the tempfile creation, or the fork/exec. If it @@ -315,7 +305,7 @@ static int expand_args(struct exec_info *info,const char *args_in) 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; + int ret=G10ERR_GENERAL; if(opt.exec_disable && !opt.no_perm_warn) { @@ -335,22 +325,22 @@ int exec_write(struct exec_info **info,const char *program, if(program==NULL && args_in==NULL) BUG(); - *info=xcalloc (1,sizeof(struct exec_info)); + *info=xmalloc_clear(sizeof(struct exec_info)); if(name) - (*info)->name=xstrdup (name); - (*info)->binary=binary; - (*info)->writeonly=writeonly; + (*info)->name=xstrdup(name); + (*info)->flags.binary=binary; + (*info)->flags.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) + if(!(*info)->flags.use_temp_files) { - log_error(_("this platform requires temp files when calling external " - "programs\n")); + log_error(_("this platform requires temporary files when calling" + " external programs\n")); goto fail; } @@ -358,7 +348,7 @@ int exec_write(struct exec_info **info,const char *program, /* 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) + if(args_in==NULL || (*info)->flags.use_temp_files==0) { int to[2],from[2]; @@ -392,7 +382,7 @@ int exec_write(struct exec_info **info,const char *program, /* If the program isn't going to respond back, they get to keep their stdout/stderr */ - if(!(*info)->writeonly) + if(!(*info)->flags.writeonly) { /* implied close of STDERR */ if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1) @@ -426,10 +416,12 @@ int exec_write(struct exec_info **info,const char *program, /* 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)); + if(args_in==NULL) + log_error(_("unable to execute program `%s': %s\n"), + program,strerror(errno)); + else + log_error(_("unable to execute shell `%s': %s\n"), + shell,strerror(errno)); /* This mimics the POSIX sh behavior - 127 means "not found" from the shell. */ @@ -446,8 +438,8 @@ int exec_write(struct exec_info **info,const char *program, (*info)->tochild=fdopen(to[1],binary?"wb":"w"); if((*info)->tochild==NULL) { - ret = gpg_error_from_errno (errno); close(to[1]); + ret=G10ERR_WRITE_FILE; goto fail; } @@ -456,8 +448,8 @@ int exec_write(struct exec_info **info,const char *program, (*info)->fromchild=iobuf_fdopen(from[0],"r"); if((*info)->fromchild==NULL) { - ret = gpg_error_from_errno (errno); close(from[0]); + ret=G10ERR_READ_FILE; goto fail; } @@ -472,12 +464,18 @@ int exec_write(struct exec_info **info,const char *program, 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( is_secured_filename ((*info)->tempfile_in) ) + { + (*info)->tochild = NULL; + errno = EPERM; + } + else + (*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)); + ret=G10ERR_WRITE_FILE; goto fail; } @@ -489,18 +487,18 @@ int exec_write(struct exec_info **info,const char *program, int exec_read(struct exec_info *info) { - int ret=GPG_ERR_GENERAL; + int ret=G10ERR_GENERAL; fclose(info->tochild); info->tochild=NULL; - if(info->use_temp_files) + if(info->flags.use_temp_files) { if(DBG_EXTPROG) log_debug("system() command is %s\n",info->command); #if defined (_WIN32) - info->progreturn=win_system(info->command); + info->progreturn=w32_system(info->command); #else info->progreturn=system(info->command); #endif @@ -537,14 +535,21 @@ int exec_read(struct exec_info *info) goto fail; } - if(!info->writeonly) + if(!info->flags.writeonly) { info->fromchild=iobuf_open(info->tempfile_out); + if (info->fromchild + && is_secured_file (iobuf_get_fd (info->fromchild))) + { + iobuf_close (info->fromchild); + info->fromchild = NULL; + errno = EPERM; + } if(info->fromchild==NULL) { - ret = gpg_error_from_errno (errno); log_error(_("unable to read external program response: %s\n"), strerror(errno)); + ret=G10ERR_READ_FILE; goto fail; } @@ -583,7 +588,7 @@ int exec_finish(struct exec_info *info) } #endif - if(info->madedir && !info->keep_temp_files) + if(info->flags.madedir && !info->flags.keep_temp_files) { if(info->tempfile_in) { @@ -604,12 +609,12 @@ int exec_finish(struct exec_info *info) info->tempdir,strerror(errno)); } - xfree (info->command); - xfree (info->name); - xfree (info->tempdir); - xfree (info->tempfile_in); - xfree (info->tempfile_out); - xfree (info); + xfree(info->command); + xfree(info->name); + xfree(info->tempdir); + xfree(info->tempfile_in); + xfree(info->tempfile_out); + xfree(info); return ret; } diff --git a/g10/exec.h b/g10/exec.h index eda406894..66d13c72b 100644 --- a/g10/exec.h +++ b/g10/exec.h @@ -1,5 +1,5 @@ /* exec.h - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef _EXEC_H_ @@ -23,11 +24,20 @@ #include <unistd.h> #include <stdio.h> + #include "../common/iobuf.h" struct exec_info { - int progreturn,binary,writeonly,madedir,use_temp_files,keep_temp_files; + int progreturn; + struct + { + unsigned int binary:1; + unsigned int writeonly:1; + unsigned int madedir:1; + unsigned int use_temp_files:1; + unsigned int keep_temp_files:1; + } flags; pid_t child; FILE *tochild; iobuf_t fromchild; @@ -38,6 +48,6 @@ 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); +int set_exec_path(const char *path); #endif /* !_EXEC_H_ */ diff --git a/g10/export.c b/g10/export.c index 43d1b21ed..495079602 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1,6 +1,6 @@ /* export.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,38 +27,68 @@ #include <errno.h> #include <assert.h> +#include "gpg.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" +#include "trustdb.h" + + +/* An object to keep track of subkeys. */ +struct subkey_list_s +{ + struct subkey_list_s *next; + u32 kid[2]; +}; +typedef struct subkey_list_s *subkey_list_t; + static int do_export( STRLIST users, int secret, unsigned int options ); -static int do_export_stream( iobuf_t out, STRLIST users, int secret, +static int do_export_stream( IOBUF 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) +parse_export_options(char *str,unsigned int *options,int noisy) { 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} + {"export-local-sigs",EXPORT_LOCAL_SIGS,NULL, + N_("export signatures that are marked as local-only")}, + {"export-attributes",EXPORT_ATTRIBUTES,NULL, + N_("export attribute user IDs (generally photo IDs)")}, + {"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL, + N_("export revocation keys marked as \"sensitive\"")}, + {"export-reset-subkey-passwd",EXPORT_RESET_SUBKEY_PASSWD,NULL, + N_("remove the passphrase from exported subkeys")}, + {"export-clean",EXPORT_CLEAN,NULL, + N_("remove unusable parts from key during export")}, + {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL, + N_("remove as much as possible from key during export")}, + {"export-sexp-format",EXPORT_SEXP_FORMAT, NULL, + N_("export keys in an S-expression based format")}, + /* Aliases for backward compatibility */ + {"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL}, + {"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL}, + {"include-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,NULL}, + /* dummy */ + {"export-unusable-sigs",0,NULL,NULL}, + {"export-clean-sigs",0,NULL,NULL}, + {"export-clean-uids",0,NULL,NULL}, + {NULL,0,NULL,NULL} /* add tags for include revoked and disabled? */ }; - return parse_options(str,options,export_opts); + return parse_options(str,options,export_opts,noisy); } + /**************** * Export the public keys (to standard out or --output). * Depending on opt.armor the output is armored. @@ -74,7 +105,7 @@ export_pubkeys( STRLIST users, unsigned int options ) * been exported */ int -export_pubkeys_stream( iobuf_t out, STRLIST users, +export_pubkeys_stream( IOBUF out, STRLIST users, KBNODE *keyblock_out, unsigned int options ) { int any, rc; @@ -90,7 +121,7 @@ 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); + return do_export( users, 1, options ); } int @@ -98,37 +129,38 @@ 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); + return do_export( users, 2, options ); } static int -do_export (STRLIST users, int secret, unsigned int options) +do_export( STRLIST users, int secret, unsigned int options ) { - iobuf_t out = NULL; + IOBUF 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); + memset( &afx, 0, sizeof afx); + memset( &zfx, 0, sizeof zfx); - rc = open_outfile (NULL, 0, &out); + rc = open_outfile( NULL, 0, &out ); if (rc) return rc; if (!(options & EXPORT_SEXP_FORMAT)) { - if (opt.armor) + if ( opt.armor ) { afx.what = secret?5:1; - iobuf_push_filter( out, armor_filter, &afx ); + iobuf_push_filter ( out, armor_filter, &afx ); } - if (opt.compress_keys && opt.compress) - iobuf_push_filter( out, compress_filter, &zfx ); + if ( opt.compress_keys ) + push_compress_filter (out,&zfx,default_compress_algo()); } - rc = do_export_stream (out, users, secret, NULL, options, &any ); - if (rc || !any) + rc = do_export_stream ( out, users, secret, NULL, options, &any ); + + if ( rc || !any ) iobuf_cancel (out); else iobuf_close (out); @@ -136,11 +168,129 @@ do_export (STRLIST users, int secret, unsigned int options) } + +/* Release an entire subkey list. */ +static void +release_subkey_list (subkey_list_t list) +{ + while (list) + { + subkey_list_t tmp = list->next;; + xfree (list); + list = tmp; + } +} + + +/* Returns true if NODE is a subkey and contained in LIST. */ +static int +subkey_in_list_p (subkey_list_t list, KBNODE node) +{ + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY ) + { + u32 kid[2]; + + 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); + + for (; list; list = list->next) + if (list->kid[0] == kid[0] && list->kid[1] == kid[1]) + return 1; + } + return 0; +} + +/* Allocate a new subkey list item from NODE. */ +static subkey_list_t +new_subkey_list_item (KBNODE node) +{ + subkey_list_t list = xcalloc (1, sizeof *list); + + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + keyid_from_pk (node->pkt->pkt.public_key, list->kid); + else if (node->pkt->pkttype == PKT_SECRET_SUBKEY) + keyid_from_sk (node->pkt->pkt.secret_key, list->kid); + + return list; +} + + +/* Helper function to check whether the subkey at NODE actually + matches the description at DESC. The function returns true if the + key under question has been specified by an exact specification + (keyID or fingerprint) and does match the one at NODE. It is + assumed that the packet at NODE is either a public or secret + subkey. */ +static int +exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node) +{ + u32 kid[2]; + byte fpr[MAX_FINGERPRINT_LEN]; + size_t fprlen; + int result = 0; + + switch(desc->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->mode) + { + case KEYDB_SEARCH_MODE_SHORT_KID: + if (desc->u.kid[1] == kid[1]) + result = 1; + break; + + case KEYDB_SEARCH_MODE_LONG_KID: + if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1]) + result = 1; + break; + + case KEYDB_SEARCH_MODE_FPR16: + if (!memcmp (desc->u.fpr, fpr, 16)) + result = 1; + break; + + case KEYDB_SEARCH_MODE_FPR20: + case KEYDB_SEARCH_MODE_FPR: + if (!memcmp (desc->u.fpr, fpr, 20)) + result = 1; + break; + + default: + break; + } + + return result; +} + + /* 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, +do_export_stream( IOBUF out, STRLIST users, int secret, KBNODE *keyblock_out, unsigned int options, int *any ) { int rc = 0; @@ -149,6 +299,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, KBNODE kbctx, node; size_t ndesc, descindex; KEYDB_SEARCH_DESC *desc = NULL; + subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */ KEYDB_HANDLE kdbhd; STRLIST sl; int indent = 0; @@ -159,7 +310,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, if (!users) { ndesc = 1; - desc = xcalloc (1, ndesc * sizeof *desc); + desc = xcalloc ( ndesc, sizeof *desc ); desc[0].mode = KEYDB_SEARCH_MODE_FIRST; } else { @@ -171,11 +322,11 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, 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)); + log_error (_("key \"%s\" not found: %s\n"), + sl->d, g10_errstr (G10ERR_INV_USER_ID)); } - /* it would be nice to see which of the given users did + /* 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 @@ -183,6 +334,14 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, do this we need an extra flag to enable this feature so */ } +#ifdef ENABLE_SELINUX_HACKS + if (secret) { + log_error (_("exporting secret keys not allowed\n")); + rc = G10ERR_GENERAL; + goto leave; + } +#endif + while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) { int sha1_warned=0,skip_until_subkey=0; u32 sk_keyid[2]; @@ -190,49 +349,59 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, if (!users) desc[0].mode = KEYDB_SEARCH_MODE_NEXT; - /* read the keyblock */ + /* Read the keyblock. */ rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); + log_error (_("error reading keyblock: %s\n"), g10_errstr(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) + if((node=find_kbnode(keyblock,PKT_SECRET_KEY))) { 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 */ + /* 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]); + log_info(_("key %s: not protected - skipped\n"), + keystr(sk_keyid)); continue; } - /* no v3 keys with GNU mode 1001 */ + /* 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]); + log_info(_("key %s: PGP 2.x style key - skipped\n"), + keystr(sk_keyid)); continue; } + + /* It does not make sense to export a key with a primary + key on card using a non-key stub. We simply skip those + keys when used with --export-secret-subkeys. */ + if (secret == 2 && sk->is_protected + && sk->protect.s2k.mode == 1002 ) + { + log_info(_("key %s: key material on-card - skipped\n"), + keystr(sk_keyid)); + continue; + } + } + else + { + /* It's a public key export, so do the cleaning if + requested. Note that both export-clean and + export-minimal only apply to UID sigs (0x10, 0x11, + 0x12, and 0x13). A designated revocation is never + stripped, even with export-minimal set. */ + + if(options&EXPORT_CLEAN) + clean_key(keyblock,opt.verbose,options&EXPORT_MINIMAL,NULL,NULL); } - /* and write it */ + /* And write it. */ for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { if( skip_until_subkey ) { @@ -243,104 +412,92 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, continue; } - /* don't export any comment packets but those in the - * secret keyring */ - if( !secret && node->pkt->pkttype == PKT_COMMENT ) - continue; + /* We used to use comment packets, but not any longer. In + case we still have comments on a key, strip them here + before we call build_packet(). */ + if( node->pkt->pkttype == PKT_COMMENT ) + continue; - /* make sure that ring_trust packets never get exported */ + /* 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) */ + 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 (!exact_subkey_match_p (desc+descindex, node)) + { + /* Before skipping this subkey, check whether any + other description wants an exact match on a + subkey and include that subkey into the output + too. Need to add this subkey to a list so that + it won't get processed a second time. + + So the first step here is to check that list and + skip in any case if the key is in that list. + + We need this whole mess because the import + function is not able to merge secret keys and + thus it is useless to output them as two + separate keys and have import merge them. */ + if (subkey_in_list_p (subkey_list, node)) + skip_until_subkey = 1; /* Already processed this one. */ + else + { + size_t j; + + for (j=0; j < ndesc; j++) + if (j != descindex && desc[j].exact + && exact_subkey_match_p (desc+j, node)) + break; + if (!(j < ndesc)) + skip_until_subkey = 1; /* No other one matching. */ + } + } if(skip_until_subkey) continue; + + /* Mark this one as processed. */ + { + subkey_list_t tmp = new_subkey_list_item (node); + tmp->next = subkey_list; + subkey_list = tmp; + } } - 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; + if(node->pkt->pkttype==PKT_SIGNATURE) + { + /* do not export packets which are marked as not + exportable */ + if(!(options&EXPORT_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_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) && + if( !(options&EXPORT_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 @@ -352,8 +509,9 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, continue; } - if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) { - /* we don't want to export the secret parts of the + 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; @@ -363,42 +521,91 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, 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; - } + } + else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY + && (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD)) + { + /* If the subkey is protected reset the passphrase to + export an unprotected subkey. This feature is + useful in cases of a subkey copied to an unattended + machine where a passphrase is not required. */ + PKT_secret_key *sk_save, *sk; + + sk_save = node->pkt->pkt.secret_key; + sk = copy_secret_key (NULL, sk_save); + node->pkt->pkt.secret_key = sk; + + log_info (_("about to export an unprotected subkey\n")); + switch (is_secret_key_protected (sk)) + { + case -1: + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + break; + default: + if (sk->protect.s2k.mode == 1001) + ; /* No secret parts. */ + else if( sk->protect.s2k.mode == 1002 ) + ; /* Card key stub. */ + else + { + rc = check_secret_key( sk, 0 ); + } + break; + } + if (rc) + { + node->pkt->pkt.secret_key = sk_save; + free_secret_key (sk); + log_error (_("failed to unprotect the subkey: %s\n"), + g10_errstr (rc)); + goto leave; + } + + rc = build_packet (out, node->pkt); + + node->pkt->pkt.secret_key = sk_save; + free_secret_key (sk); + } + 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 %s does not have a " + "simple SK checksum\n"),keystr(sk_keyid)); + + 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) ); + node->pkt->pkttype, g10_errstr(rc) ); + rc = G10ERR_WRITE_FILE; goto leave; } } + if ((options&EXPORT_SEXP_FORMAT) && indent) { for (; indent; indent--) iobuf_put (out, ')'); iobuf_put (out, '\n'); } - + ++*any; if(keyblock_out) { @@ -416,7 +623,8 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, rc = 0; leave: - xfree (desc); + release_subkey_list (subkey_list); + xfree(desc); keydb_release (kdbhd); if(rc || keyblock_out==NULL) release_kbnode( keyblock ); @@ -426,6 +634,7 @@ do_export_stream( iobuf_t out, STRLIST users, int secret, } + static int write_sexp_line (iobuf_t out, int *indent, const char *text) { @@ -524,8 +733,8 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent) } -/* For some packet types we write them in a S-Exp like format. This is - still EXPERIMENTAL and subject to change. */ +/* For some packet types we write them in a S-expression format. This + is still EXPERIMENTAL and subject to change. */ static int build_sexp (iobuf_t out, PACKET *pkt, int *indent) { diff --git a/g10/filter.h b/g10/filter.h index 12c5cebed..3b4e73963 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -1,5 +1,6 @@ /* filter.h - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,18 +16,18 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * 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 */ + gcry_md_hd_t md; /* catch all */ + gcry_md_hd_t md2; /* if we want to calculate an alternate hash */ size_t maxbuf_size; } md_filter_context_t; @@ -49,6 +50,10 @@ typedef struct { int truncated; /* number of truncated lines */ int qp_detected; int pgp2mode; + byte eol[3]; /* The end of line characters as a + zero-terminated string. Defaults + (eol[0]=='\0') to whatever the local + platform uses. */ byte *buffer; /* malloced buffer */ unsigned buffer_size; /* and size of this buffer */ @@ -87,9 +92,9 @@ typedef struct compress_filter_context_s compress_filter_context_t; typedef struct { DEK *dek; u32 datalen; - CIPHER_HANDLE cipher_hd; + gcry_cipher_hd_t cipher_hd; int header; - MD_HANDLE mdc_hash; + gcry_md_hd_t mdc_hash; byte enchash[20]; int create_mdc; /* flag will be set by the cipher filter */ } cipher_filter_context_t; @@ -104,7 +109,7 @@ typedef struct { int truncated; /* number of truncated lines */ int not_dash_escaped; int escape_from; - MD_HANDLE md; + gcry_md_hd_t md; int pending_lf; int pending_esc; } text_filter_context_t; @@ -121,35 +126,36 @@ typedef struct { /* 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); +int md_filter( void *opaque, int control, IOBUF 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 use_armor_filter( IOBUF a ); int armor_filter( void *opaque, int control, - iobuf_t chain, byte *buf, size_t *ret_len); + IOBUF 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); +void push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo); +void push_compress_filter2(IOBUF out,compress_filter_context_t *zfx, + int algo,int rel); /*-- cipher.c --*/ int cipher_filter( void *opaque, int control, - iobuf_t chain, byte *buf, size_t *ret_len); + IOBUF 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 ); + IOBUF chain, byte *buf, size_t *ret_len); +int copy_clearsig_text (IOBUF out, IOBUF inp, gcry_md_hd_t 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); + IOBUF a, byte *buf, size_t *ret_len); void handle_progress (progress_filter_context_t *pfx, - iobuf_t inp, const char *name); + IOBUF inp, const char *name); #endif /*G10_FILTER_H*/ diff --git a/g10/free-packet.c b/g10/free-packet.c index 7ced327f5..8aab06370 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -1,6 +1,6 @@ /* free-packet.c - cleanup stuff for packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,18 +26,18 @@ #include <string.h> #include <assert.h> +#include "gpg.h" #include "packet.h" -#include "iobuf.h" -#include "mpi.h" +#include "../common/iobuf.h" #include "util.h" #include "cipher.h" -#include "memory.h" -#include "options.h" +#include "options.h" + void free_symkey_enc( PKT_symkey_enc *enc ) { - xfree (enc); + xfree(enc); } void @@ -45,10 +46,10 @@ free_pubkey_enc( PKT_pubkey_enc *enc ) int n, i; n = pubkey_get_nenc( enc->pubkey_algo ); if( !n ) - mpi_release (enc->data[0]); + mpi_release(enc->data[0]); for(i=0; i < n; i++ ) - mpi_release ( enc->data[i] ); - xfree (enc); + mpi_release( enc->data[i] ); + xfree(enc); } void @@ -58,14 +59,21 @@ free_seckey_enc( PKT_signature *sig ) n = pubkey_get_nsig( sig->pubkey_algo ); if( !n ) - mpi_release (sig->data[0]); + 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); + mpi_release( sig->data[i] ); + + xfree(sig->revkey); + xfree(sig->hashed); + xfree(sig->unhashed); + + if (sig->pka_info) + { + xfree (sig->pka_info->uri); + xfree (sig->pka_info); + } + + xfree(sig); } @@ -75,9 +83,9 @@ 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]); + mpi_release(pk->pkey[0]); for(i=0; i < n; i++ ) { - mpi_release ( pk->pkey[i] ); + mpi_release( pk->pkey[i] ); pk->pkey[i] = NULL; } if (pk->prefs) { @@ -89,7 +97,7 @@ release_public_key_parts( PKT_public_key *pk ) pk->user_id = NULL; } if (pk->revkey) { - xfree (pk->revkey); + xfree(pk->revkey); pk->revkey=NULL; pk->numrevkeys=0; } @@ -100,7 +108,7 @@ void free_public_key( PKT_public_key *pk ) { release_public_key_parts( pk ); - xfree (pk); + xfree(pk); } @@ -150,7 +158,7 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s) int n, i; if( !d ) - d = xmalloc (sizeof *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); @@ -164,7 +172,7 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s) if( !s->revkey && s->numrevkeys ) BUG(); if( s->numrevkeys ) { - d->revkey = xmalloc (sizeof(struct revocation_key)*s->numrevkeys); + d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys); memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys); } else @@ -194,13 +202,28 @@ copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk ) sk->keyid[1] = pk->keyid[1]; } + +static pka_info_t * +cp_pka_info (const pka_info_t *s) +{ + pka_info_t *d = xmalloc (sizeof *s + strlen (s->email)); + + d->valid = s->valid; + d->checked = s->checked; + d->uri = s->uri? xstrdup (s->uri):NULL; + memcpy (d->fpr, s->fpr, sizeof s->fpr); + strcpy (d->email, s->email); + return d; +} + + PKT_signature * copy_signature( PKT_signature *d, PKT_signature *s ) { int n, i; if( !d ) - d = xmalloc (sizeof *d); + d = xmalloc(sizeof *d); memcpy( d, s, sizeof *d ); n = pubkey_get_nsig( s->pubkey_algo ); if( !n ) @@ -209,6 +232,7 @@ copy_signature( PKT_signature *d, PKT_signature *s ) for(i=0; i < n; i++ ) d->data[i] = mpi_copy( s->data[i] ); } + d->pka_info = s->pka_info? cp_pka_info (s->pka_info) : NULL; d->hashed = cp_subpktarea (s->hashed); d->unhashed = cp_subpktarea (s->unhashed); if(s->numrevkeys) @@ -241,9 +265,9 @@ release_secret_key_parts( PKT_secret_key *sk ) n = pubkey_get_nskey( sk->pubkey_algo ); if( !n ) - mpi_release (sk->skey[0]); + mpi_release(sk->skey[0]); for(i=0; i < n; i++ ) { - mpi_release ( sk->skey[i] ); + mpi_release( sk->skey[i] ); sk->skey[i] = NULL; } } @@ -252,7 +276,7 @@ void free_secret_key( PKT_secret_key *sk ) { release_secret_key_parts( sk ); - xfree (sk); + xfree(sk); } PKT_secret_key * @@ -261,29 +285,32 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s ) int n, i; if( !d ) - d = xmalloc (sizeof *d); + d = xmalloc_secure(sizeof *d); + else + release_secret_key_parts (d); memcpy( d, s, sizeof *d ); n = pubkey_get_nskey( s->pubkey_algo ); if( !n ) - d->skey[0] = mpi_copy(s->skey[0]); + d->skey[0] = mpi_copy(s->skey[0]); else { for(i=0; i < n; i++ ) - d->skey[i] = mpi_copy( s->skey[i] ); + d->skey[i] = mpi_copy( s->skey[i] ); } + return d; } void free_comment( PKT_comment *rem ) { - xfree (rem); + xfree(rem); } void free_attributes(PKT_user_id *uid) { - xfree (uid->attribs); - xfree (uid->attrib_data); + xfree(uid->attribs); + xfree(uid->attrib_data); uid->attribs=NULL; uid->attrib_data=NULL; @@ -312,14 +339,14 @@ free_compressed( PKT_compressed *zd ) while( iobuf_read( zd->buf, NULL, 1<<30 ) != -1 ) ; } - xfree (zd); + xfree(zd); } void free_encrypted( PKT_encrypted *ed ) { if( ed->buf ) { /* have to skip some bytes */ - if( iobuf_in_block_mode(ed->buf) ) { + if( ed->is_partial ) { while( iobuf_read( ed->buf, NULL, 1<<30 ) != -1 ) ; } @@ -333,7 +360,7 @@ free_encrypted( PKT_encrypted *ed ) } } } - xfree (ed); + xfree(ed); } @@ -341,7 +368,7 @@ void free_plaintext( PKT_plaintext *pt ) { if( pt->buf ) { /* have to skip some bytes */ - if( iobuf_in_block_mode(pt->buf) ) { + if( pt->is_partial ) { while( iobuf_read( pt->buf, NULL, 1<<30 ) != -1 ) ; } @@ -355,7 +382,7 @@ free_plaintext( PKT_plaintext *pt ) } } } - xfree (pt); + xfree(pt); } /**************** @@ -405,7 +432,7 @@ free_packet( PACKET *pkt ) free_plaintext( pkt->pkt.plaintext ); break; default: - xfree ( pkt->pkt.generic ); + xfree( pkt->pkt.generic ); break; } pkt->pkt.generic = NULL; diff --git a/g10/getkey.c b/g10/getkey.c index f51b8f2df..acd992c21 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1,6 +1,6 @@ /* getkey.c - Get a key from the database - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -29,22 +30,21 @@ #include "gpg.h" #include "util.h" #include "packet.h" -#include "memory.h" #include "iobuf.h" #include "keydb.h" #include "options.h" #include "main.h" #include "trustdb.h" #include "i18n.h" +#include "keyserver-internal.h" -#define MAX_PK_CACHE_ENTRIES 200 -#define MAX_UID_CACHE_ENTRIES 200 +#define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE +#define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE #if MAX_PK_CACHE_ENTRIES < 2 #error We need the cache for key creation #endif - struct getkey_ctx_s { int exact; KBNODE keyblock; @@ -154,7 +154,7 @@ cache_public_key( PKT_public_key *pk ) return; } pk_cache_entries++; - ce = xmalloc ( sizeof *ce ); + ce = xmalloc( sizeof *ce ); ce->next = pk_cache; pk_cache = ce; ce->pk = copy_public_key( NULL, pk ); @@ -164,6 +164,21 @@ cache_public_key( PKT_public_key *pk ) } +/* Return a const utf-8 string with the text "[User ID not found]". + This fucntion is required so that we don't need to switch gettext's + encoding temporary. */ +static const char * +user_id_not_found_utf8 (void) +{ + static char *text; + + if (!text) + text = native_to_utf8 (_("[User ID not found]")); + return text; +} + + + /* * Return the user ID from the given keyblock. * We use the primary uid flag which has been set by the merge_selfsigs @@ -184,9 +199,7 @@ get_primary_uid ( KBNODE keyblock, size_t *uidlen ) return k->pkt->pkt.user_id->name; } } - /* fixme: returning translatable constants instead of a user ID is - * not good because they are probably not utf-8 encoded. */ - s = _("[User id not found]"); + s = user_id_not_found_utf8 (); *uidlen = strlen (s); return s; } @@ -218,7 +231,7 @@ cache_user_id( KBNODE keyblock ) for (k=keyblock; k; k = k->next ) { if ( k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - keyid_list_t a = xcalloc (1, sizeof *a ); + keyid_list_t a = xmalloc_clear ( sizeof *a ); /* Hmmm: For a long list of keyids it might be an advantage * to append the keys */ keyid_from_pk( k->pkt->pkt.public_key, a->keyid ); @@ -252,10 +265,10 @@ cache_user_id( KBNODE keyblock ) r = user_id_db; user_id_db = r->next; release_keyid_list ( r->keyids ); - xfree (r); + xfree(r); uid_cache_entries--; } - r = xmalloc ( sizeof *r + uidlen-1 ); + r = xmalloc( sizeof *r + uidlen-1 ); r->keyids = keyids; r->len = uidlen; memcpy(r->name, uid, r->len); @@ -275,7 +288,7 @@ getkey_disable_caches() for( ce = pk_cache; ce; ce = ce2 ) { ce2 = ce->next; free_public_key( ce->pk ); - xfree ( ce ); + xfree( ce ); } pk_cache_disabled=1; pk_cache_entries = 0; @@ -322,20 +335,25 @@ get_pubkey( PKT_public_key *pk, u32 *keyid ) int rc = 0; #if MAX_PK_CACHE_ENTRIES - { /* Try to get it from the cache */ + if(pk) + { + /* Try to get it from the cache. We don't do this when pk is + NULL as it does not guarantee that the user IDs are + cached. */ pk_cache_entry_t ce; - for( ce = pk_cache; ce; ce = ce->next ) { - if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { - if( pk ) - copy_public_key( pk, ce->pk ); + for( ce = pk_cache; ce; ce = ce->next ) + { + if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) + { + copy_public_key( pk, ce->pk ); return 0; - } - } - } + } + } + } #endif /* more init stuff */ if( !pk ) { - pk = xcalloc (1, sizeof *pk ); + pk = xmalloc_clear( sizeof *pk ); internal++; } @@ -363,7 +381,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid ) if( !rc ) goto leave; - rc = GPG_ERR_NO_PUBKEY; + rc = G10ERR_NO_PUBKEY; leave: if( !rc ) @@ -376,13 +394,15 @@ get_pubkey( PKT_public_key *pk, u32 *keyid ) /* Get a public key and store it into the allocated pk. This function differs from get_pubkey() in that it does not do a check of the key - to avoid recursion. It should be used only in very certain cases. */ + to avoid recursion. It should be used only in very certain cases. + It will only retrieve primary keys. */ int get_pubkey_fast (PKT_public_key *pk, u32 *keyid) { int rc = 0; KEYDB_HANDLE hd; KBNODE keyblock; + u32 pkid[2]; assert (pk); #if MAX_PK_CACHE_ENTRIES @@ -406,29 +426,34 @@ get_pubkey_fast (PKT_public_key *pk, u32 *keyid) if (rc == -1) { keydb_release (hd); - return GPG_ERR_NO_PUBKEY; + return G10ERR_NO_PUBKEY; } rc = keydb_get_keyblock (hd, &keyblock); keydb_release (hd); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); - return GPG_ERR_NO_PUBKEY; + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + return G10ERR_NO_PUBKEY; } - + assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY ); - copy_public_key (pk, keyblock->pkt->pkt.public_key ); + + keyid_from_pk(keyblock->pkt->pkt.public_key,pkid); + if(keyid[0]==pkid[0] && keyid[1]==pkid[1]) + copy_public_key (pk, keyblock->pkt->pkt.public_key ); + else + rc=G10ERR_NO_PUBKEY; + release_kbnode (keyblock); /* Not caching key here since it won't have all of the fields properly set. */ - return 0; + return rc; } - KBNODE get_pubkeyblock( u32 *keyid ) { @@ -496,7 +521,7 @@ get_seckey( PKT_secret_key *sk, u32 *keyid ) * check and does not tell us whether the secret key is valid. It * merely tells other whether there is some secret key. * Returns: 0 := key is available - * GPG_ERR_NO_SECKEY := not availabe + * G10ERR_NO_SECKEY := not availabe */ int seckey_available( u32 *keyid ) @@ -506,7 +531,7 @@ seckey_available( u32 *keyid ) rc = keydb_search_kid (hd, keyid); if ( rc == -1 ) - rc = GPG_ERR_NO_SECKEY; + rc = G10ERR_NO_SECKEY; keydb_release (hd); return rc; } @@ -579,11 +604,13 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) case 0: /* empty string is an error */ return 0; +#if 0 case '.': /* an email address, compare from end */ mode = KEYDB_SEARCH_MODE_MAILEND; s++; desc->u.name = s; break; +#endif case '<': /* an email address */ mode = KEYDB_SEARCH_MODE_MAIL; @@ -608,11 +635,13 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) desc->u.name = s; break; +#if 0 case '+': /* compare individual words */ mode = KEYDB_SEARCH_MODE_WORDS; s++; desc->u.name = s; break; +#endif case '#': /* local user id */ return 0; /* This is now obsolete and van't not be used anymore*/ @@ -653,7 +682,7 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) } /* check if a hexadecimal number is terminated by EOS or blank */ - if (hexlength && s[hexlength] && !spacep (s+hexlength)) { + if (hexlength && s[hexlength] && !spacep(s+hexlength)) { if (hexprefix) /* a "0x" prefix without correct */ return 0; /* termination is an error */ else /* The first chars looked like */ @@ -728,39 +757,60 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) static int -skip_disabled(void *dummy,u32 *keyid) +skip_unusable(void *dummy,u32 *keyid,PKT_user_id *uid) { - int rc,disabled=0; - PKT_public_key *pk=xcalloc (1,sizeof(PKT_public_key)); + int unusable=0; + KBNODE keyblock; - rc = get_pubkey(pk, keyid); - if(rc) + keyblock=get_pubkeyblock(keyid); + if(!keyblock) { - log_error("error checking disabled status of %08lX: %s\n", - (ulong)keyid[1],gpg_strerror (rc)); + log_error("error checking usability status of %s\n",keystr(keyid)); goto leave; } - - disabled=pk_is_disabled(pk); + + /* Is the user ID in question revoked/expired? */ + if(uid) + { + KBNODE node; + + for(node=keyblock;node;node=node->next) + { + if(node->pkt->pkttype==PKT_USER_ID) + { + if(cmp_user_ids(uid,node->pkt->pkt.user_id)==0 + && (node->pkt->pkt.user_id->is_revoked + || node->pkt->pkt.user_id->is_expired)) + { + unusable=1; + break; + } + } + } + } + + if(!unusable) + unusable=pk_is_disabled(keyblock->pkt->pkt.public_key); leave: - free_public_key(pk); - return disabled; + release_kbnode(keyblock); + return unusable; } /**************** * Try to get the pubkey by the userid. This function looks for the - * first pubkey certificate which has the given name in a user_id. - * if pk/sk has the pubkey algo set, the function will only return - * a pubkey with that algo. - * The caller should provide storage for either the pk or the sk. - * If ret_kb is not NULL the function will return the keyblock there. + * first pubkey certificate which has the given name in a user_id. if + * pk/sk has the pubkey algo set, the function will only return a + * pubkey with that algo. If namelist is NULL, the first key is + * returned. The caller should provide storage for either the pk or + * the sk. If ret_kb is not NULL the function will return the + * keyblock there. */ static int key_byname( GETKEY_CTX *retctx, STRLIST namelist, PKT_public_key *pk, PKT_secret_key *sk, - int secmode, int include_disabled, + int secmode, int include_unusable, KBNODE *ret_kb, KEYDB_HANDLE *ret_kdbhd ) { int rc = 0; @@ -777,29 +827,43 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, if (ret_kdbhd) *ret_kdbhd = NULL; - /* build the search context */ - for(n=0, r=namelist; r; r = r->next ) - n++; - ctx = xcalloc (1,sizeof *ctx + (n-1)*sizeof ctx->items ); - ctx->nitems = n; + if(!namelist) + { + ctx = xmalloc_clear (sizeof *ctx); + ctx->nitems = 1; + ctx->items[0].mode=KEYDB_SEARCH_MODE_FIRST; + if(!include_unusable) + ctx->items[0].skipfnc=skip_unusable; + } + else + { + /* build the search context */ + for(n=0, r=namelist; r; r = r->next ) + n++; - for(n=0, r=namelist; r; r = r->next, n++ ) { - classify_user_id (r->d, &ctx->items[n]); + ctx = xmalloc_clear (sizeof *ctx + (n-1)*sizeof ctx->items ); + ctx->nitems = n; + + for(n=0, r=namelist; r; r = r->next, n++ ) + { + classify_user_id (r->d, &ctx->items[n]); - if (ctx->items[n].exact) - ctx->exact = 1; - if (!ctx->items[n].mode) { - xfree (ctx); - return GPG_ERR_INV_USER_ID; - } - if(!include_disabled - && ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID - && ctx->items[n].mode!=KEYDB_SEARCH_MODE_LONG_KID - && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR16 - && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR20 - && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR) - ctx->items[n].skipfnc=skip_disabled; - } + if (ctx->items[n].exact) + ctx->exact = 1; + if (!ctx->items[n].mode) + { + xfree (ctx); + return G10ERR_INV_USER_ID; + } + if(!include_unusable + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_LONG_KID + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR16 + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR20 + && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR) + ctx->items[n].skipfnc=skip_unusable; + } + } ctx->kr_handle = keydb_new (secmode); if ( !ret_kb ) @@ -841,24 +905,141 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, return rc; } -/* - * Find a public key from NAME and returh the keyblock or the key. - * If ret_kdb is not NULL, the KEYDB handle used to locate this keyblock is - * returned and the caller is responsible for closing it. - */ + + +/* Find a public key from NAME and return the keyblock or the key. If + ret_kdb is not NULL, the KEYDB handle used to locate this keyblock + is returned and the caller is responsible for closing it. If a key + was not found and NAME is a valid RFC822 mailbox and PKA retrieval + has been enabled, we try to import the pkea via the PKA + mechanism. */ int get_pubkey_byname (PKT_public_key *pk, const char *name, KBNODE *ret_keyblock, - KEYDB_HANDLE *ret_kdbhd, int include_disabled ) + KEYDB_HANDLE *ret_kdbhd, int include_unusable ) { - int rc; - STRLIST namelist = NULL; + int rc; + STRLIST namelist = NULL; - add_to_strlist( &namelist, name ); - rc = key_byname( NULL, namelist, pk, NULL, 0, - include_disabled, ret_keyblock, ret_kdbhd); - free_strlist( namelist ); - return rc; + add_to_strlist( &namelist, name ); + + rc = key_byname( NULL, namelist, pk, NULL, 0, + include_unusable, ret_keyblock, ret_kdbhd); + + /* If the requested name resembles a valid mailbox and automatic + retrieval has been enabled, we try to import the key. */ + + if (rc == G10ERR_NO_PUBKEY && is_valid_mailbox(name)) + { + struct akl *akl; + + for(akl=opt.auto_key_locate;akl;akl=akl->next) + { + unsigned char *fpr; + size_t fpr_len; + + switch(akl->type) + { + case AKL_CERT: + glo_ctrl.in_auto_key_retrieve++; + rc=keyserver_import_cert(name,&fpr,&fpr_len); + glo_ctrl.in_auto_key_retrieve--; + + if(rc==0) + log_info(_("automatically retrieved `%s' via %s\n"), + name,"DNS CERT"); + break; + + case AKL_PKA: + glo_ctrl.in_auto_key_retrieve++; + rc=keyserver_import_pka(name,&fpr,&fpr_len); + glo_ctrl.in_auto_key_retrieve--; + + if(rc==0) + log_info(_("automatically retrieved `%s' via %s\n"), + name,"PKA"); + break; + + case AKL_LDAP: + glo_ctrl.in_auto_key_retrieve++; + rc=keyserver_import_ldap(name,&fpr,&fpr_len); + glo_ctrl.in_auto_key_retrieve--; + + if(rc==0) + log_info(_("automatically retrieved `%s' via %s\n"), + name,"LDAP"); + break; + + case AKL_KEYSERVER: + /* Strictly speaking, we don't need to only use a valid + mailbox for the getname search, but it helps cut down + on the problem of searching for something like "john" + and getting a whole lot of keys back. */ + if(opt.keyserver) + { + glo_ctrl.in_auto_key_retrieve++; + rc=keyserver_import_name(name,&fpr,&fpr_len,opt.keyserver); + glo_ctrl.in_auto_key_retrieve--; + + if(rc==0) + log_info(_("automatically retrieved `%s' via %s\n"), + name,opt.keyserver->uri); + } + break; + + case AKL_SPEC: + { + struct keyserver_spec *keyserver; + + keyserver=keyserver_match(akl->spec); + glo_ctrl.in_auto_key_retrieve++; + rc=keyserver_import_name(name,&fpr,&fpr_len,keyserver); + glo_ctrl.in_auto_key_retrieve--; + + if(rc==0) + log_info(_("automatically retrieved `%s' via %s\n"), + name,akl->spec->uri); + } + break; + } + + /* Use the fingerprint of the key that we actually fetched. + This helps prevent problems where the key that we fetched + doesn't have the same name that we used to fetch it. In + the case of CERT and PKA, this is an actual security + requirement as the URL might point to a key put in by an + attacker. By forcing the use of the fingerprint, we + won't use the attacker's key here. */ + if(rc==0 && fpr) + { + int i; + char fpr_string[MAX_FINGERPRINT_LEN*2+1]; + + assert(fpr_len<=MAX_FINGERPRINT_LEN); + + free_strlist(namelist); + namelist=NULL; + + for(i=0;i<fpr_len;i++) + sprintf(fpr_string+2*i,"%02X",fpr[i]); + + if(opt.verbose) + log_info("auto-key-locate found fingerprint %s\n",fpr_string); + + add_to_strlist( &namelist, fpr_string ); + + xfree(fpr); + } + + rc = key_byname( NULL, namelist, pk, NULL, 0, + include_unusable, ret_keyblock, ret_kdbhd); + if(rc!=G10ERR_NO_PUBKEY) + break; + } + } + + free_strlist( namelist ); + return rc; } int @@ -880,7 +1061,6 @@ get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ) return rc; } - void get_pubkey_end( GETKEY_CTX ctx ) { @@ -888,17 +1068,15 @@ get_pubkey_end( GETKEY_CTX ctx ) memset (&ctx->kbpos, 0, sizeof ctx->kbpos); keydb_release (ctx->kr_handle); if( !ctx->not_allocated ) - xfree ( ctx ); + xfree( ctx ); } } - - /**************** * Search for a key with the given fingerprint. * FIXME: - * We should replace this with the _byname function. This can be done + * We should replace this with the _byname function. Thiscsan be done * by creating a userID conforming to the unified fingerprint style. */ int @@ -926,7 +1104,7 @@ get_pubkey_byfprint( PKT_public_key *pk, get_pubkey_end( &ctx ); } else - rc = GPG_ERR_GENERAL; /* Oops */ + rc = G10ERR_GENERAL; /* Oops */ return rc; } @@ -956,14 +1134,14 @@ get_pubkey_byfprint_fast (PKT_public_key *pk, if (rc == -1) { keydb_release (hd); - return GPG_ERR_NO_PUBKEY; + return G10ERR_NO_PUBKEY; } rc = keydb_get_keyblock (hd, &keyblock); keydb_release (hd); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); - return GPG_ERR_NO_PUBKEY; + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); + return G10ERR_NO_PUBKEY; } assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY @@ -1002,7 +1180,7 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, get_pubkey_end( &ctx ); } else - rc = GPG_ERR_GENERAL; /* Oops */ + rc = G10ERR_GENERAL; /* Oops */ return rc; } @@ -1014,44 +1192,31 @@ get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint, */ static int get_seckey_byname2( GETKEY_CTX *retctx, - PKT_secret_key *sk, const char *name, int unprotect, - KBNODE *retblock ) + PKT_secret_key *sk, const char *name, int unprotect, + KBNODE *retblock ) { - STRLIST namelist = NULL; - int rc; + STRLIST namelist = NULL; + int rc,include_unusable=1; - if( !name && opt.def_secret_key && *opt.def_secret_key ) { - add_to_strlist( &namelist, opt.def_secret_key ); - rc = key_byname( retctx, namelist, NULL, sk, 1, 1, retblock, NULL ); - } - else if( !name ) { /* use the first one as default key */ - struct getkey_ctx_s ctx; - KBNODE kb = NULL; + /* If we have no name, try to use the default secret key. If we + have no default, we'll use the first usable one. */ - assert (!retctx ); /* do we need this at all */ - assert (!retblock); - memset( &ctx, 0, sizeof ctx ); - ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); - ctx.nitems = 1; - ctx.items[0].mode = KEYDB_SEARCH_MODE_FIRST; - rc = lookup( &ctx, &kb, 1 ); - if (!rc && sk ) - sk_from_block ( &ctx, sk, kb ); - release_kbnode ( kb ); - get_seckey_end( &ctx ); - } - else { - add_to_strlist( &namelist, name ); - rc = key_byname( retctx, namelist, NULL, sk, 1, 1, retblock, NULL ); - } + if( !name && opt.def_secret_key && *opt.def_secret_key ) + add_to_strlist( &namelist, opt.def_secret_key ); + else if(name) + add_to_strlist( &namelist, name ); + else + include_unusable=0; - free_strlist( namelist ); + rc = key_byname( retctx, namelist, NULL, sk, 1, include_unusable, + retblock, NULL ); - if( !rc && unprotect ) - rc = check_secret_key( sk, 0 ); + free_strlist( namelist ); - return rc; + if( !rc && unprotect ) + rc = check_secret_key( sk, 0 ); + + return rc; } int @@ -1117,13 +1282,41 @@ get_seckey_byfprint( PKT_secret_key *sk, if (!rc && sk ) sk_from_block ( &ctx, sk, kb ); release_kbnode ( kb ); - get_pubkey_end( &ctx ); + get_seckey_end( &ctx ); } else - rc = GPG_ERR_GENERAL; /* Oops */ + rc = G10ERR_GENERAL; /* Oops */ return rc; } + +/* Search for a secret key with the given fingerprint and return the + complete keyblock which may have more than only this key. */ +int +get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ) +{ + int rc; + struct getkey_ctx_s ctx; + + if (fprint_len != 20 && fprint_len == 16) + return G10ERR_GENERAL; /* Oops */ + + memset (&ctx, 0, sizeof ctx); + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (1); + ctx.nitems = 1; + ctx.items[0].mode = (fprint_len==16 + ? KEYDB_SEARCH_MODE_FPR16 + : KEYDB_SEARCH_MODE_FPR20); + memcpy (ctx.items[0].u.fpr, fprint, fprint_len); + rc = lookup (&ctx, ret_keyblock, 1); + get_seckey_end (&ctx); + + return rc; +} + + /************************************************ ************* Merging stuff ******************** @@ -1220,6 +1413,59 @@ merge_keys_and_selfsig( KBNODE keyblock ) } } +static int +parse_key_usage(PKT_signature *sig) +{ + int key_usage=0; + const byte *p; + size_t n; + byte flags; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_KEY_FLAGS,&n); + if(p && n) + { + /* first octet of the keyflags */ + flags=*p; + + if(flags & 1) + { + key_usage |= PUBKEY_USAGE_CERT; + flags&=~1; + } + + if(flags & 2) + { + key_usage |= PUBKEY_USAGE_SIG; + flags&=~2; + } + + /* We do not distinguish between encrypting communications and + encrypting storage. */ + if(flags & (0x04|0x08)) + { + key_usage |= PUBKEY_USAGE_ENC; + flags&=~(0x04|0x08); + } + + if(flags & 0x20) + { + key_usage |= PUBKEY_USAGE_AUTH; + flags&=~0x20; + } + + if(flags) + key_usage |= PUBKEY_USAGE_UNKNOWN; + } + + /* We set PUBKEY_USAGE_UNKNOWN to indicate that this key has a + capability that we do not handle. This serves to distinguish + between a zero key usage which we handle as the default + capabilities for that algorithm, and a usage that we do not + handle. */ + + return key_usage; +} + /* * Apply information from SIGNODE (which is the valid self-signature * associated with that UID) to the UIDNODE: @@ -1238,32 +1484,28 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) const byte *p, *sym, *hash, *zip; size_t n, nsym, nhash, nzip; + sig->flags.chosen_selfsig = 1; /* we chose this one */ uid->created = 0; /* not created == invalid */ if ( IS_UID_REV ( sig ) ) { uid->is_revoked = 1; return; /* has been revoked */ } + uid->expiredate = sig->expiredate; + + if(sig->flags.expired) + { + uid->is_expired = 1; + return; /* has expired */ + } + uid->created = sig->timestamp; /* this one is okay */ uid->selfsigversion = sig->version; /* If we got this far, it's not expired :) */ uid->is_expired = 0; - uid->expiredate = sig->expiredate; /* store the key flags in the helper variable for later processing */ - uid->help_key_usage = 0; - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); - if ( p && n ) { - /* first octet of the keyflags */ - if ( (*p & 0x03) ) - uid->help_key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 0x0c) ) - uid->help_key_usage |= PUBKEY_USAGE_ENC; - /* Note: we do not set the CERT flag here because it can be assumed - * that thre is no real policy to set it. */ - if ( (*p & 0x20) ) - uid->help_key_usage |= PUBKEY_USAGE_AUTH; - } + uid->help_key_usage=parse_key_usage(sig); /* ditto or the key expiration */ uid->help_key_expire = 0; @@ -1318,20 +1560,29 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) } /* see whether we have the MDC feature */ - uid->mdc_feature = 0; + uid->flags.mdc = 0; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n); if (p && n && (p[0] & 0x01)) - uid->mdc_feature = 1; + uid->flags.mdc = 1; /* and the keyserver modify flag */ - uid->ks_modify = 1; + uid->flags.ks_modify = 1; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n); if (p && n && (p[0] & 0x80)) - uid->ks_modify = 0; + uid->flags.ks_modify = 0; +} + +static void +sig_to_revoke_info(PKT_signature *sig,struct revoke_info *rinfo) +{ + rinfo->date = sig->timestamp; + rinfo->algo = sig->pubkey_algo; + rinfo->keyid[0] = sig->keyid[0]; + rinfo->keyid[1] = sig->keyid[1]; } static void -merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) +merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo) { PKT_public_key *pk = NULL; KBNODE k; @@ -1346,6 +1597,8 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) byte sigversion = 0; *r_revoked = 0; + memset(rinfo,0,sizeof(*rinfo)); + if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) BUG (); pk = keyblock->pkt->pkt.public_key; @@ -1368,7 +1621,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) */ /* In case this key was already merged */ - xfree (pk->revkey); + xfree(pk->revkey); pk->revkey=NULL; pk->numrevkeys=0; @@ -1391,6 +1644,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) * that key. */ *r_revoked = 1; + sig_to_revoke_info(sig,rinfo); } else if ( IS_KEY_SIG (sig) ) { /* Add any revocation keys onto the pk. This is @@ -1459,42 +1713,34 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) pk->numrevkeys*sizeof(struct revocation_key)); } - if ( signode ) { + if ( signode ) + { /* some information from a direct key signature take precedence * over the same information given in UID sigs. */ PKT_signature *sig = signode->pkt->pkt.signature; const byte *p; - size_t n; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); - if ( p && n ) { - /* first octet of the keyflags */ - if ( (*p & 0x03) ) - key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 0x0c) ) - key_usage |= PUBKEY_USAGE_ENC; - if ( (*p & 0x20) ) - key_usage |= PUBKEY_USAGE_AUTH; - } + + key_usage=parse_key_usage(sig); p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) { - key_expire = keytimestamp + buffer_to_u32(p); - key_expire_seen = 1; - } + if ( p ) + { + key_expire = keytimestamp + buffer_to_u32(p); + key_expire_seen = 1; + } /* mark that key as valid: one direct key signature should * render a key as valid */ pk->is_valid = 1; - } + } /* pass 1.5: look for key revocation signatures that were not made by the key (i.e. did a revocation key issue a revocation for us?). Only bother to do this if there is a revocation key in - the first place. */ + the first place and we're not revoked already. */ - if(pk->revkey) + if(!*r_revoked && pk->revkey) for(k=keyblock; k && k->pkt->pkttype != PKT_USER_ID; k = k->next ) { if ( k->pkt->pkttype == PKT_SIGNATURE ) @@ -1504,15 +1750,26 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) if(IS_KEY_REV(sig) && (sig->keyid[0]!=kid[0] || sig->keyid[1]!=kid[1])) { - /* Failure here means the sig did not verify, is was - not issued by a revocation key, or a revocation - key loop was broken. */ + int rc=check_revocation_keys(pk,sig); + if(rc==0) + { + *r_revoked=2; + sig_to_revoke_info(sig,rinfo); + /* don't continue checking since we can't be any + more revoked than this */ + break; + } + else if(rc==G10ERR_NO_PUBKEY) + pk->maybe_revoked=1; - if(check_revocation_keys(pk,sig)==0) - *r_revoked=1; + /* A failure here means the sig did not verify, was + not issued by a revocation key, or a revocation + key loop was broken. If a revocation key isn't + findable, however, the key might be revoked and + we don't know it. */ - /* In the future handle subkey and cert revocations? - PGP doesn't, but it's in 2440. */ + /* TODO: In the future handle subkey and cert + revocations? PGP doesn't, but it's in 2440. */ } } } @@ -1537,7 +1794,8 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) if ( check_key_signature( keyblock, k, NULL ) ) ; /* signature did not verify */ else if ( (IS_UID_SIG (sig) || IS_UID_REV (sig)) - && sig->timestamp >= sigdate ) { + && sig->timestamp >= sigdate ) + { /* Note: we allow to invalidate cert revocations * by a newer signature. An attacker can't use this * because a key should be revoced with a key revocation. @@ -1546,20 +1804,13 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) * the same email address may become valid again (hired, * fired, hired again). */ - if(sig->flags.expired) { - /* Expired uids don't get to be primary unless - they are the only uid there is. */ - uidnode->pkt->pkt.user_id->is_primary=0; - uidnode->pkt->pkt.user_id->is_expired=1; - uidnode->pkt->pkt.user_id->expiredate=sig->expiredate; - } - else { - sigdate = sig->timestamp; - signode = k; - if( sig->version > sigversion ) - sigversion = sig->version; - } - } + + sigdate = sig->timestamp; + signode = k; + signode->pkt->pkt.signature->flags.chosen_selfsig=0; + if( sig->version > sigversion ) + sigversion = sig->version; + } } } } @@ -1573,10 +1824,8 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) if(!pk->is_valid && opt.allow_non_selfsigned_uid) { if(opt.verbose) - log_info(_("Invalid key %08lX made valid by " - "--allow-non-selfsigned-uid\n"), - (ulong)keyid_from_pk(pk,NULL)); - + log_info(_("Invalid key %s made valid by" + " --allow-non-selfsigned-uid\n"),keystr_from_pk(pk)); pk->is_valid = 1; } @@ -1598,7 +1847,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) { PKT_public_key *ultimate_pk; - ultimate_pk=xcalloc (1,sizeof(*ultimate_pk)); + ultimate_pk=xmalloc_clear(sizeof(*ultimate_pk)); /* We don't want to use the full get_pubkey to avoid infinite recursion in certain cases. @@ -1608,7 +1857,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) ultimate trust flag. */ if(get_pubkey_fast(ultimate_pk,sig->keyid)==0 && check_key_signature2(keyblock,k,ultimate_pk, - NULL, NULL, NULL, NULL)==0 + NULL,NULL,NULL,NULL)==0 && get_ownertrust(ultimate_pk)==TRUST_ULTIMATE) { free_public_key(ultimate_pk); @@ -1659,7 +1908,9 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) if ( x ) /* mask it down to the actual allowed usage */ key_usage &= x; } - pk->pubkey_usage = key_usage; + + /* Whatever happens, it's a primary key, so it can certify. */ + pk->pubkey_usage = key_usage|PUBKEY_USAGE_CERT; if ( !key_expire_seen ) { /* find the latest valid user ID with a key expiration set @@ -1799,7 +2050,6 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) u32 keytimestamp = 0; u32 key_expire = 0; const byte *p; - size_t n; if ( subnode->pkt->pkttype != PKT_PUBLIC_SUBKEY ) BUG (); @@ -1834,47 +2084,47 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) problem is in the distribution. Plus, PGP (7) does this the same way. */ subpk->is_revoked = 1; + sig_to_revoke_info(sig,&subpk->revoked); /* although we could stop now, we continue to * figure out other information like the old expiration * time */ } - else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) { + else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) + { if(sig->flags.expired) - ; /* signature has expired - ignore it */ - else { + ; /* signature has expired - ignore it */ + else + { sigdate = sig->timestamp; signode = k; - } - } + signode->pkt->pkt.signature->flags.chosen_selfsig=0; + } + } } } } - if ( !signode ) { - return; /* no valid key binding */ - } + /* no valid key binding */ + if ( !signode ) + return; - subpk->is_valid = 1; sig = signode->pkt->pkt.signature; - - p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); - if ( p && n ) { - /* first octet of the keyflags */ - if ( (*p & 0x03) ) - key_usage |= PUBKEY_USAGE_SIG; - if ( (*p & 0x0c) ) - key_usage |= PUBKEY_USAGE_ENC; - if ( (*p & 0x20) ) - key_usage |= PUBKEY_USAGE_AUTH; - } - if ( !key_usage ) { /* no key flags at all: get it from the algo */ + sig->flags.chosen_selfsig=1; /* so we know which selfsig we chose later */ + + key_usage=parse_key_usage(sig); + if ( !key_usage ) + { + /* no key flags at all: get it from the algo */ key_usage = openpgp_pk_algo_usage ( subpk->pubkey_algo ); - } - else { /* check that the usage matches the usage as given by the algo */ + } + else + { + /* check that the usage matches the usage as given by the algo */ int x = openpgp_pk_algo_usage ( subpk->pubkey_algo ); if ( x ) /* mask it down to the actual allowed usage */ - key_usage &= x; - } + key_usage &= x; + } + subpk->pubkey_usage = key_usage; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); @@ -1884,8 +2134,56 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) key_expire = 0; subpk->has_expired = key_expire >= curtime? 0 : key_expire; subpk->expiredate = key_expire; -} + /* algo doesn't exist */ + if(openpgp_pk_test_algo(subpk->pubkey_algo)) + return; + + subpk->is_valid = 1; + + /* Find the first 0x19 embedded signature on our self-sig. */ + if(subpk->backsig==0) + { + int seq=0; + size_t n; + + /* We do this while() since there may be other embedded + signatures in the future. We only want 0x19 here. */ + while((p=enum_sig_subpkt(sig->hashed, + SIGSUBPKT_SIGNATURE,&n,&seq,NULL))) + if(n>3 && ((p[0]==3 && p[2]==0x19) || (p[0]==4 && p[1]==0x19))) + break; + + if(p==NULL) + { + seq=0; + /* It is safe to have this in the unhashed area since the + 0x19 is located on the selfsig for convenience, not + security. */ + while((p=enum_sig_subpkt(sig->unhashed,SIGSUBPKT_SIGNATURE, + &n,&seq,NULL))) + if(n>3 && ((p[0]==3 && p[2]==0x19) || (p[0]==4 && p[1]==0x19))) + break; + } + + if(p) + { + PKT_signature *backsig=xmalloc_clear(sizeof(PKT_signature)); + IOBUF backsig_buf=iobuf_temp_with_content(p,n); + + if(parse_signature(backsig_buf,PKT_SIGNATURE,n,backsig)==0) + { + if(check_backsig(mainpk,subpk,backsig)==0) + subpk->backsig=2; + else + subpk->backsig=1; + } + + iobuf_close(backsig_buf); + free_seckey_enc(backsig); + } + } +} /* @@ -1905,6 +2203,7 @@ merge_selfsigs( KBNODE keyblock ) { KBNODE k; int revoked; + struct revoke_info rinfo; PKT_public_key *main_pk; prefitem_t *prefs; int mdc_feature; @@ -1921,7 +2220,7 @@ merge_selfsigs( KBNODE keyblock ) BUG (); } - merge_selfsigs_main ( keyblock, &revoked ); + merge_selfsigs_main ( keyblock, &revoked, &rinfo ); /* now merge in the data from each of the subkeys */ for(k=keyblock; k; k = k->next ) { @@ -1941,8 +2240,11 @@ merge_selfsigs( KBNODE keyblock ) PKT_public_key *pk = k->pkt->pkt.public_key; if(!main_pk->is_valid) pk->is_valid = 0; - if(revoked) - pk->is_revoked = 1; + if(revoked && !pk->is_revoked) + { + pk->is_revoked = revoked; + memcpy(&pk->revoked,&rinfo,sizeof(rinfo)); + } if(main_pk->has_expired) pk->has_expired = main_pk->has_expired; } @@ -1966,7 +2268,7 @@ merge_selfsigs( KBNODE keyblock ) && !k->pkt->pkt.user_id->attrib_data && k->pkt->pkt.user_id->is_primary) { prefs = k->pkt->pkt.user_id->prefs; - mdc_feature = k->pkt->pkt.user_id->mdc_feature; + mdc_feature = k->pkt->pkt.user_id->flags.mdc; break; } } @@ -2076,14 +2378,14 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) KBNODE next, ll; if (opt.verbose) - log_info ( _("no secret subkey " - "for public subkey %08lX - ignoring\n"), - (ulong)keyid_from_pk (pk,NULL) ); + log_info (_("no secret subkey" + " for public subkey %s - ignoring\n"), + keystr_from_pk (pk)); /* we have to remove the subkey in this case */ assert ( last ); /* find the next subkey */ for (next=pub->next,ll=pub; - next && pub->pkt->pkttype != PKT_PUBLIC_SUBKEY; + next && next->pkt->pkttype != PKT_PUBLIC_SUBKEY; ll = next, next = next->next ) ; /* make new link */ @@ -2141,7 +2443,7 @@ finish_lookup (GETKEY_CTX ctx) KBNODE k; KBNODE foundk = NULL; PKT_user_id *foundu = NULL; -#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC) +#define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC|PUBKEY_USAGE_CERT) unsigned int req_usage = ( ctx->req_usage & USAGE_MASK ); /* Request the primary if we're certifying another key, and also if signing data while --pgp6 or --pgp7 is on since pgp 6 and 7 @@ -2303,12 +2605,14 @@ finish_lookup (GETKEY_CTX ctx) ctx->found_key = latest_key; - if (latest_key != keyblock && opt.verbose) { - log_info(_("using secondary key %08lX " - "instead of primary key %08lX\n"), - (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL), - (ulong)keyid_from_pk( keyblock->pkt->pkt.public_key, NULL) ); - } + if (latest_key != keyblock && opt.verbose) + { + char *tempkeystr= + xstrdup(keystr_from_pk(latest_key->pkt->pkt.public_key)); + log_info(_("using subkey %s instead of primary key %s\n"), + tempkeystr, keystr_from_pk(keyblock->pkt->pkt.public_key)); + xfree(tempkeystr); + } cache_user_id( keyblock ); @@ -2333,7 +2637,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) rc = keydb_get_keyblock (ctx->kr_handle, &ctx->keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); rc = 0; goto skip; } @@ -2349,12 +2653,13 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) keyid_from_sk (k->pkt->pkt.secret_key, aki); k = get_pubkeyblock (aki); - if( !k ) { + if( !k ) + { if (!opt.quiet) - log_info(_("key %08lX: secret key without public key " - "- skipped\n"), (ulong)aki[1] ); + log_info(_("key %s: secret key without public key" + " - skipped\n"), keystr(aki)); goto skip; - } + } secblock = ctx->keyblock; ctx->keyblock = k; @@ -2390,16 +2695,16 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode ) found: if( rc && rc != -1 ) - log_error("keydb_search failed: %s\n", gpg_strerror (rc)); + log_error("keydb_search failed: %s\n", g10_errstr(rc)); if( !rc ) { *ret_keyblock = ctx->keyblock; /* return the keyblock */ ctx->keyblock = NULL; } else if (rc == -1 && no_suitable_key) - rc = secmode ? GPG_ERR_UNUSABLE_SECKEY : GPG_ERR_UNUSABLE_PUBKEY; + rc = secmode ? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY; else if( rc == -1 ) - rc = secmode ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY; + rc = secmode ? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY; if ( secmode ) { release_kbnode( secblock ); @@ -2449,7 +2754,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk, if( !c ) { /* make a new context */ - c = xcalloc (1, sizeof *c ); + c = xmalloc_clear( sizeof *c ); *context = c; c->hd = keydb_new (1); c->first = 1; @@ -2460,7 +2765,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk, if( !sk ) { /* free the context */ keydb_release (c->hd); release_kbnode (c->keyblock); - xfree ( c ); + xfree( c ); *context = NULL; return 0; } @@ -2507,43 +2812,44 @@ enum_secret_keys( void **context, PKT_secret_key *sk, /**************** * Return a string with a printable representation of the user_id. - * this string must be freed by m_free. + * this string must be freed by xfree. */ char* get_user_id_string( u32 *keyid ) { - user_id_db_t r; - char *p; - int pass=0; - /* try it two times; second pass reads from key resources */ - do { - for(r=user_id_db; r; r = r->next ) { - keyid_list_t a; - for (a=r->keyids; a; a= a->next ) { - if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = xmalloc ( r->len + 10 ); - sprintf(p, "%08lX %.*s", - (ulong)keyid[1], r->len, r->name ); - return p; - } - } + user_id_db_t r; + char *p; + int pass=0; + /* try it two times; second pass reads from key resources */ + do + { + for(r=user_id_db; r; r = r->next ) + { + keyid_list_t a; + for (a=r->keyids; a; a= a->next ) + { + if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) + { + p = xmalloc( keystrlen() + 1 + r->len + 1 ); + sprintf(p, "%s %.*s", keystr(keyid), r->len, r->name ); + return p; + } + } } } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = xmalloc ( 15 ); - sprintf(p, "%08lX [?]", (ulong)keyid[1] ); - return p; + p = xmalloc( keystrlen() + 5 ); + sprintf(p, "%s [?]", keystr(keyid)); + return p; } char* -get_user_id_string_printable ( u32 *keyid ) +get_user_id_string_native ( u32 *keyid ) { - char *p = get_user_id_string( keyid ); - char *p2 = utf8_to_native( p, strlen(p), 0 ); - xfree (p); - p = make_printable_string (p2, strlen (p2), 0); - xfree (p2); - return p; + char *p = get_user_id_string( keyid ); + char *p2 = utf8_to_native( p, strlen(p), 0 ); + xfree(p); + return p2; } @@ -2559,7 +2865,7 @@ get_long_user_id_string( u32 *keyid ) keyid_list_t a; for (a=r->keyids; a; a= a->next ) { if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = xmalloc ( r->len + 20 ); + p = xmalloc( r->len + 20 ); sprintf(p, "%08lX%08lX %.*s", (ulong)keyid[0], (ulong)keyid[1], r->len, r->name ); @@ -2568,7 +2874,7 @@ get_long_user_id_string( u32 *keyid ) } } } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = xmalloc ( 25 ); + p = xmalloc( 25 ); sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] ); return p; } @@ -2586,7 +2892,7 @@ get_user_id( u32 *keyid, size_t *rn ) keyid_list_t a; for (a=r->keyids; a; a= a->next ) { if( a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1] ) { - p = xmalloc ( r->len ); + p = xmalloc( r->len ); memcpy(p, r->name, r->len ); *rn = r->len; return p; @@ -2594,21 +2900,19 @@ get_user_id( u32 *keyid, size_t *rn ) } } } while( ++pass < 2 && !get_pubkey( NULL, keyid ) ); - p = xstrdup ( _("[User id not found]") ); + p = xstrdup( user_id_not_found_utf8 () ); *rn = strlen(p); return p; } char* -get_user_id_printable( u32 *keyid ) +get_user_id_native( u32 *keyid ) { - size_t rn; - char *p = get_user_id( keyid, &rn ); - char *p2 = utf8_to_native( p, rn, 0 ); - xfree (p); - p = make_printable_string (p2, strlen (p2), 0); - xfree (p2); - return p; + size_t rn; + char *p = get_user_id( keyid, &rn ); + char *p2 = utf8_to_native( p, rn, 0 ); + xfree(p); + return p2; } KEYDB_HANDLE @@ -2616,3 +2920,85 @@ get_ctx_handle(GETKEY_CTX ctx) { return ctx->kr_handle; } + +static void +free_akl(struct akl *akl) +{ + if(akl->spec) + free_keyserver_spec(akl->spec); + + xfree(akl); +} + +void +release_akl(void) +{ + while(opt.auto_key_locate) + { + struct akl *akl2=opt.auto_key_locate; + opt.auto_key_locate=opt.auto_key_locate->next; + free_akl(akl2); + } +} + +int +parse_auto_key_locate(char *options) +{ + char *tok; + + while((tok=optsep(&options))) + { + struct akl *akl,*last; + int dupe=0; + + if(tok[0]=='\0') + continue; + + akl=xmalloc_clear(sizeof(*akl)); + + if(ascii_strcasecmp(tok,"ldap")==0) + akl->type=AKL_LDAP; + else if(ascii_strcasecmp(tok,"keyserver")==0) + akl->type=AKL_KEYSERVER; +#ifdef USE_DNS_CERT + else if(ascii_strcasecmp(tok,"cert")==0) + akl->type=AKL_CERT; +#endif +#ifdef USE_DNS_PKA + else if(ascii_strcasecmp(tok,"pka")==0) + akl->type=AKL_PKA; +#endif + else if((akl->spec=parse_keyserver_uri(tok,1,NULL,0))) + akl->type=AKL_SPEC; + else + { + free_akl(akl); + return 0; + } + + /* We must maintain the order the user gave us */ + for(last=opt.auto_key_locate;last && last->next;last=last->next) + { + /* Check for duplicates */ + if(last && last->type==akl->type + && (akl->type!=AKL_SPEC + || (akl->type==AKL_SPEC + && strcmp(last->spec->uri,akl->spec->uri)==0))) + { + dupe=1; + free_akl(akl); + break; + } + } + + if(!dupe) + { + if(last) + last->next=akl; + else + opt.auto_key_locate=akl; + } + } + + return 1; +} diff --git a/g10/global.h b/g10/global.h deleted file mode 100644 index d1c554dce..000000000 --- a/g10/global.h +++ /dev/null @@ -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*/ diff --git a/g10/gpg.c b/g10/gpg.c index 234d13f41..49687fff1 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1,6 +1,6 @@ -/* g10.c - The GnuPG utility (main for gpg) - * Copyright (C) 1998,1999,2000,2001,2002,2003 - * 2004 Free Software Foundation, Inc. +/* gpg.c - The GnuPG utility (main for gpg) + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -33,19 +34,21 @@ #ifdef HAVE_STAT #include <sys/stat.h> /* for stat() */ #endif +#include <fcntl.h> #include <assuan.h> +#ifdef HAVE_W32_SYSTEM +#include <windows.h> +#endif #define INCLUDED_BY_MAIN_MODULE 1 #include "gpg.h" #include "packet.h" -#include "iobuf.h" -#include "memory.h" +#include "../common/iobuf.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" @@ -54,15 +57,28 @@ #include "keyserver-internal.h" #include "exec.h" -enum cmd_and_opt_values { aNull = 0, + +#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) +#define MY_O_BINARY O_BINARY +#ifndef S_IRGRP +# define S_IRGRP 0 +# define S_IWGRP 0 +#endif +#else +#define MY_O_BINARY 0 +#endif + + +enum cmd_and_opt_values + { + aNull = 0, oArmor = 'a', aDetachedSign = 'b', aSym = 'c', aDecrypt = 'd', aEncr = 'e', oInteractive = 'i', - aListKeys = 'k', - aListSecretKeys = 'K', + oKOption = 'k', oDryRun = 'n', oOutput = 'o', oQuiet = 'q', @@ -70,42 +86,49 @@ enum cmd_and_opt_values { aNull = 0, oHiddenRecipient = 'R', aSign = 's', oTextmodeShort= 't', - oUser = 'u', + oLocalUser = 'u', oVerbose = 'v', oCompress = 'z', oSetNotation = 'N', + aListSecretKeys = 'K', oBatch = 500, - aGPGConfList, + oMaxOutput, oSigNotation, oCertNotation, oShowNotation, oNoShowNotation, aEncrFiles, - aDecryptFiles, + aEncrSym, + aDecryptFiles, aClearsign, aStore, aKeygen, aSignEncr, + aSignEncrSym, aSignSym, aSignKey, aLSignKey, - aNRSignKey, - aNRLSignKey, + aListConfig, + aGPGConfList, aListPackets, aEditKey, aDeleteKeys, aDeleteSecretKeys, aDeleteSecretAndPublicKeys, + aKMode, + aKModeC, aImport, aFastImport, aVerify, aVerifyFiles, + aListKeys, aListSigs, aSendKeys, aRecvKeys, aSearchKeys, + aRefreshKeys, + aFetchKeys, aExport, - aExportAll, aExportSecret, aExportSecretSub, aCheckKeys, @@ -125,9 +148,7 @@ enum cmd_and_opt_values { aNull = 0, aDeArmor, aEnArmor, aGenRandom, - aPipeMode, aRebuildKeydbCaches, - aRefreshKeys, aCardStatus, aCardEdit, aChangePIN, @@ -136,15 +157,20 @@ enum cmd_and_opt_values { aNull = 0, oNoTextmode, oExpert, oNoExpert, + oDefSigExpire, oAskSigExpire, oNoAskSigExpire, + oDefCertExpire, oAskCertExpire, oNoAskCertExpire, + oDefCertLevel, + oMinCertLevel, + oAskCertLevel, + oNoAskCertLevel, oFingerprint, oWithFingerprint, oAnswerYes, oAnswerNo, - oDefCertCheckLevel, oKeyring, oPrimaryKeyring, oSecretKeyring, @@ -157,16 +183,11 @@ enum cmd_and_opt_values { aNull = 0, oDebug, oDebugLevel, oDebugAll, + oDebugCCIDDriver, oStatusFD, -#ifdef __riscos__ oStatusFile, -#endif /* __riscos__ */ oAttributeFD, -#ifdef __riscos__ oAttributeFile, -#endif /* __riscos__ */ - oSKComments, - oNoSKComments, oEmitVersion, oNoEmitVersion, oCompletesNeeded, @@ -181,22 +202,26 @@ enum cmd_and_opt_values { aNull = 0, oPGP6, oPGP7, oPGP8, + oRFC2440Text, + oNoRFC2440Text, oCipherAlgo, oDigestAlgo, oCertDigestAlgo, oCompressAlgo, + oCompressLevel, + oBZ2CompressLevel, + oBZ2DecompressLowmem, + oPasswd, oPasswdFD, -#ifdef __riscos__ oPasswdFile, -#endif /* __riscos__ */ oCommandFD, -#ifdef __riscos__ oCommandFile, -#endif /* __riscos__ */ oQuickRandom, oNoVerbose, oTrustDBName, oNoSecmemWarn, + oRequireSecmem, + oNoRequireSecmem, oNoPermissionWarn, oNoMDCWarn, oNoArmor, @@ -214,7 +239,6 @@ enum cmd_and_opt_values { aNull = 0, oAlwaysTrust, oTrustModel, oForceOwnertrust, - oEmuChecksumBug, oSetFilename, oForYourEyesOnly, oNoForYourEyesOnly, @@ -225,11 +249,12 @@ enum cmd_and_opt_values { aNull = 0, oNoShowPolicyURL, oSigKeyserverURL, oUseEmbeddedFilename, + oNoUseEmbeddedFilename, oComment, oDefaultComment, oNoComments, - oThrowKeyid, - oNoThrowKeyid, + oThrowKeyids, + oNoThrowKeyids, oShowPhotos, oNoShowPhotos, oPhotoViewer, @@ -245,7 +270,7 @@ enum cmd_and_opt_values { aNull = 0, oS2KDigest, oS2KCipher, oSimpleSKChecksum, - oCharset, + oDisplayCharset, oNotDashEscaped, oEscapeFrom, oNoEscapeFrom, @@ -263,11 +288,8 @@ enum cmd_and_opt_values { aNull = 0, oEncryptTo, oHiddenEncryptTo, oNoEncryptTo, - oLogFile, oLoggerFD, -#ifdef __riscos__ oLoggerFile, -#endif /* __riscos__ */ oUtf8Strings, oNoUtf8Strings, oDisableCipherAlgo, @@ -309,7 +331,6 @@ enum cmd_and_opt_values { aNull = 0, oPersonalCipherPreferences, oPersonalDigestPreferences, oPersonalCompressPreferences, - oEmuMDEncodeBug, oAgentProgram, oDisplay, oTTYname, @@ -317,13 +338,25 @@ enum cmd_and_opt_values { aNull = 0, oLCctype, oLCmessages, oGroup, + oUnGroup, + oNoGroups, oStrict, oNoStrict, oMangleDosFilenames, oNoMangleDosFilenames, - oEnableProgressFilter, + oEnableProgressFilter, oMultifile, -aTest }; + oKeyidFormat, + oExitOnStatusWriteError, + oLimitCardInsertTries, + oRequireCrossCert, + oNoRequireCrossCert, + oAutoKeyLocate, + oNoAutoKeyLocate, + oAllowMultisigVerification, + + oNoop + }; static ARGPARSE_OPTS opts[] = { @@ -331,7 +364,7 @@ static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("@Commands:\n ") }, { aSign, "sign", 256, N_("|[file]|make a signature")}, - { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") }, + { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature")}, { aDetachedSign, "detach-sign", 256, N_("make a detached signature")}, { aEncr, "encrypt", 256, N_("encrypt data")}, { aEncrFiles, "encrypt-files", 256, "@"}, @@ -353,8 +386,6 @@ static ARGPARSE_OPTS opts[] = { N_("remove keys from the secret keyring")}, { aSignKey, "sign-key" ,256, N_("sign a key")}, { aLSignKey, "lsign-key" ,256, N_("sign a key locally")}, - { aNRSignKey, "nrsign-key" ,256, "@"}, - { aNRLSignKey, "nrlsign-key" ,256, "@"}, { aEditKey, "edit-key" ,256, N_("sign or edit a key")}, { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")}, { aDesigRevoke, "desig-revoke",256, "@" }, @@ -365,29 +396,32 @@ static ARGPARSE_OPTS opts[] = { N_("search for keys on a key server") }, { aRefreshKeys, "refresh-keys", 256, N_("update all keys from a keyserver")}, - { aExportAll, "export-all" , 256, "@" }, + { aFetchKeys, "fetch-keys" , 256, "@" }, { aExportSecret, "export-secret-keys" , 256, "@" }, { aExportSecretSub, "export-secret-subkeys" , 256, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, +#ifdef ENABLE_CARD_SUPPORT { aCardStatus, "card-status", 256, N_("print the card status")}, { aCardEdit, "card-edit", 256, N_("change data on a card")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, - +#endif + { aListConfig, "list-config", 256, "@"}, + { aGPGConfList, "gpgconf-list", 256, "@" }, { aListPackets, "list-packets",256, "@"}, { aExportOwnerTrust, "export-ownertrust", 256, "@"}, { aImportOwnerTrust, "import-ownertrust", 256, "@"}, - { aUpdateTrustDB, "update-trustdb",0 , N_("update the trust database")}, - { aCheckTrustDB, "check-trustdb",0 , "@"}, - { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")}, - { aDeArmor, "dearmor", 256, "@" }, - { aDeArmor, "dearmour", 256, "@" }, - { aEnArmor, "enarmor", 256, "@" }, - { aEnArmor, "enarmour", 256, "@" }, + { aUpdateTrustDB, + "update-trustdb",0 , N_("update the trust database")}, + { aCheckTrustDB, "check-trustdb", 0, "@"}, + { aFixTrustDB, "fix-trustdb", 0, "@"}, + { aDeArmor, "dearmor", 256, "@"}, + { aDeArmor, "dearmour", 256, "@"}, + { aEnArmor, "enarmor", 256, "@"}, + { aEnArmor, "enarmour", 256, "@"}, { aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")}, { aPrimegen, "gen-prime" , 256, "@" }, { aGenRandom, "gen-random" , 256, "@" }, - { aGPGConfList, "gpgconf-list", 256, "@" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -396,107 +430,117 @@ static ARGPARSE_OPTS opts[] = { { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")}, { oHiddenRecipient, "hidden-recipient", 2, "@" }, { oRecipient, "remote-user", 2, "@"}, /* old option name */ - { oDefRecipient, "default-recipient" ,2, "@" }, - { oDefRecipientSelf, "default-recipient-self" ,0, "@" }, + { oDefRecipient, "default-recipient", 2, "@"}, + { oDefRecipientSelf, "default-recipient-self", 0, "@"}, { oNoDefRecipient, "no-default-recipient", 0, "@" }, { oTempDir, "temp-directory", 2, "@" }, { oExecPath, "exec-path", 2, "@" }, { oEncryptTo, "encrypt-to", 2, "@" }, { oHiddenEncryptTo, "hidden-encrypt-to", 2, "@" }, { oNoEncryptTo, "no-encrypt-to", 0, "@" }, - { oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, - { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, + { oLocalUser, "local-user",2, N_("use this user-id to sign or decrypt")}, + { oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") }, + { oCompressLevel, "compress-level", 1, "@" }, + { oBZ2CompressLevel, "bzip2-compress-level", 1, "@" }, + { oBZ2DecompressLowmem, "bzip2-decompress-lowmem", 0, "@" }, { oTextmodeShort, NULL, 0, "@"}, { oTextmode, "textmode", 0, N_("use canonical text mode")}, { oNoTextmode, "no-textmode", 0, "@"}, { oExpert, "expert", 0, "@"}, { oNoExpert, "no-expert", 0, "@"}, + { oDefSigExpire, "default-sig-expire", 2, "@"}, { oAskSigExpire, "ask-sig-expire", 0, "@"}, { oNoAskSigExpire, "no-ask-sig-expire", 0, "@"}, + { oDefCertExpire, "default-cert-expire", 2, "@"}, { oAskCertExpire, "ask-cert-expire", 0, "@"}, { oNoAskCertExpire, "no-ask-cert-expire", 0, "@"}, + { oDefCertLevel, "default-cert-level", 1, "@"}, + { oMinCertLevel, "min-cert-level", 1, "@"}, + { oAskCertLevel, "ask-cert-level", 0, "@"}, + { oNoAskCertLevel, "no-ask-cert-level", 0, "@"}, { oOutput, "output", 2, N_("use as output file")}, + { oMaxOutput, "max-output", 16|4, "@" }, { oVerbose, "verbose", 0, N_("verbose") }, - { oQuiet, "quiet", 0, "@" }, - { oNoTTY, "no-tty", 0, "@" }, - { oLogFile, "log-file" ,2, "@" }, - { oForceV3Sigs, "force-v3-sigs", 0, "@" }, - { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@" }, - { oForceV4Certs, "force-v4-certs", 0, "@" }, - { oNoForceV4Certs, "no-force-v4-certs", 0, "@" }, - { oForceMDC, "force-mdc", 0, "@" }, + { oQuiet, "quiet", 0, "@"}, + { oNoTTY, "no-tty", 0, "@"}, + { oForceV3Sigs, "force-v3-sigs", 0, "@"}, + { oNoForceV3Sigs, "no-force-v3-sigs", 0, "@"}, + { oForceV4Certs, "force-v4-certs", 0, "@"}, + { oNoForceV4Certs, "no-force-v4-certs", 0, "@"}, + { oForceMDC, "force-mdc", 0, "@"}, { oNoForceMDC, "no-force-mdc", 0, "@" }, - { oDisableMDC, "disable-mdc", 0, "@" }, + { oDisableMDC, "disable-mdc", 0, "@"}, { oNoDisableMDC, "no-disable-mdc", 0, "@" }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, { oInteractive, "interactive", 0, N_("prompt before overwriting") }, { oUseAgent, "use-agent",0, "@"}, { oNoUseAgent, "no-use-agent",0, "@"}, { oGpgAgentInfo, "gpg-agent-info",2, "@"}, - { oBatch, "batch", 0, "@"}, - { oAnswerYes, "yes", 0, "@"}, - { oAnswerNo, "no", 0, "@"}, - { oKeyring, "keyring" , 2, "@"}, + { oBatch, "batch", 0, "@"}, + { oAnswerYes, "yes", 0, "@"}, + { oAnswerNo, "no", 0, "@"}, + { oKeyring, "keyring", 2, "@"}, { oPrimaryKeyring, "primary-keyring",2, "@" }, - { oSecretKeyring, "secret-keyring" ,2, "@"}, + { oSecretKeyring, "secret-keyring", 2, "@"}, { oShowKeyring, "show-keyring", 0, "@"}, - { oDefaultKey, "default-key" , 2, "@"}, - { oKeyServer, "keyserver", 2, "@"}, + { oDefaultKey, "default-key", 2, "@"}, + { oKeyServer, "keyserver", 2, "@"}, { oKeyServerOptions, "keyserver-options",2,"@"}, { oImportOptions, "import-options",2,"@"}, { oExportOptions, "export-options",2,"@"}, { oListOptions, "list-options",2,"@"}, { oVerifyOptions, "verify-options",2,"@"}, - { oCharset, "charset" , 2, "@" }, - { oOptions, "options" , 2, "@"}, - + { oDisplayCharset, "display-charset", 2, "@"}, + { oDisplayCharset, "charset", 2, "@"}, + { oOptions, "options", 2, "@"}, { oDebug, "debug" ,4|16, "@"}, { oDebugLevel, "debug-level" ,2, "@"}, { oDebugAll, "debug-all" ,0, "@"}, - { oStatusFD, "status-fd" ,1, "@" }, -#ifdef __riscos__ - { oStatusFile, "status-file" ,2, "@" }, -#endif /* __riscos__ */ + { oStatusFD, "status-fd" ,1, "@"}, + { oStatusFile, "status-file" ,2, "@"}, { oAttributeFD, "attribute-fd" ,1, "@" }, -#ifdef __riscos__ { oAttributeFile, "attribute-file" ,2, "@" }, -#endif /* __riscos__ */ - { oNoSKComments, "no-sk-comments", 0, "@"}, - { oSKComments, "sk-comments", 0, "@"}, + { oNoop, "sk-comments", 0, "@"}, + { oNoop, "no-sk-comments", 0, "@"}, { oCompletesNeeded, "completes-needed", 1, "@"}, { oMarginalsNeeded, "marginals-needed", 1, "@"}, { oMaxCertDepth, "max-cert-depth", 1, "@" }, { oTrustedKey, "trusted-key", 2, "@"}, - { oLoadExtension, "load-extension" ,2, "@"}, + { oLoadExtension, "load-extension", 2, "@"}, { oGnuPG, "gnupg", 0, "@"}, { oGnuPG, "no-pgp2", 0, "@"}, { oGnuPG, "no-pgp6", 0, "@"}, { oGnuPG, "no-pgp7", 0, "@"}, { oGnuPG, "no-pgp8", 0, "@"}, { oRFC1991, "rfc1991", 0, "@"}, - { oRFC2440, "rfc2440", 0, "@"}, + { oRFC2440, "rfc2440", 0, "@" }, { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, { oPGP6, "pgp6", 0, "@"}, { oPGP7, "pgp7", 0, "@"}, { oPGP8, "pgp8", 0, "@"}, - { oS2KMode, "s2k-mode", 1, "@"}, - { oS2KDigest, "s2k-digest-algo",2, "@"}, - { oS2KCipher, "s2k-cipher-algo",2, "@"}, + { oRFC2440Text, "rfc2440-text", 0, "@"}, + { oNoRFC2440Text, "no-rfc2440-text", 0, "@"}, + { oS2KMode, "s2k-mode", 1, "@"}, + { oS2KDigest, "s2k-digest-algo", 2, "@"}, + { oS2KCipher, "s2k-cipher-algo", 2, "@"}, { oSimpleSKChecksum, "simple-sk-checksum", 0, "@"}, - { oCipherAlgo, "cipher-algo", 2 , "@"}, - { oDigestAlgo, "digest-algo", 2 , "@"}, + { oCipherAlgo, "cipher-algo", 2, "@"}, + { oDigestAlgo, "digest-algo", 2, "@"}, { oCertDigestAlgo, "cert-digest-algo", 2 , "@" }, - { oCompressAlgo,"compress-algo",2, "@"}, - { oThrowKeyid, "throw-keyid", 0, "@"}, - { oNoThrowKeyid, "no-throw-keyid", 0, "@" }, + { oCompressAlgo,"compress-algo", 2, "@"}, + { oCompressAlgo, "compression-algo", 2, "@"}, /* Alias */ + { oThrowKeyids, "throw-keyid", 0, "@"}, + { oThrowKeyids, "throw-keyids", 0, "@"}, + { oNoThrowKeyids, "no-throw-keyid", 0, "@" }, + { oNoThrowKeyids, "no-throw-keyids", 0, "@" }, { oShowPhotos, "show-photos", 0, "@" }, { oNoShowPhotos, "no-show-photos", 0, "@" }, { oPhotoViewer, "photo-viewer", 2, "@" }, { oSetNotation, "set-notation", 2, "@" }, { oSetNotation, "notation-data", 2, "@" }, /* Alias */ - { oSigNotation, "sig-notation", 2, "@" }, - { oCertNotation, "cert-notation", 2, "@" }, + { oSigNotation, "sig-notation", 2, "@" }, + { oCertNotation, "cert-notation", 2, "@" }, { 302, NULL, 0, N_( "@\n(See the man page for a complete listing of all commands and options)\n" @@ -511,24 +555,22 @@ static ARGPARSE_OPTS opts[] = { /* hidden options */ { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */ - { oCompressAlgo, "compression-algo", 1, "@"}, /* alias */ { aPrintMDs, "print-mds" , 256, "@"}, /* old */ { aListTrustDB, "list-trustdb",0 , "@"}, /* Not yet used */ /* { aListTrustPath, "list-trust-path",0, "@"}, */ - { aPipeMode, "pipemode", 0, "@" }, + { oKOption, NULL, 0, "@"}, + { oPasswd, "passphrase",2, "@" }, { oPasswdFD, "passphrase-fd",1, "@" }, -#ifdef __riscos__ { oPasswdFile, "passphrase-file",2, "@" }, -#endif /* __riscos__ */ { oCommandFD, "command-fd",1, "@" }, -#ifdef __riscos__ { oCommandFile, "command-file",2, "@" }, -#endif /* __riscos__ */ { oQuickRandom, "quick-random", 0, "@"}, { oNoVerbose, "no-verbose", 0, "@"}, { oTrustDBName, "trustdb-name", 2, "@" }, - { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */ + { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, + { oRequireSecmem,"require-secmem", 0, "@" }, + { oNoRequireSecmem,"no-require-secmem", 0, "@" }, { oNoPermissionWarn, "no-permission-warning", 0, "@" }, { oNoMDCWarn, "no-mdc-warning", 0, "@" }, { oNoArmor, "no-armor", 0, "@"}, @@ -546,11 +588,10 @@ static ARGPARSE_OPTS opts[] = { { oSkipVerify, "skip-verify",0, "@" }, { oCompressKeys, "compress-keys",0, "@"}, { oCompressSigs, "compress-sigs",0, "@"}, - { oDefCertCheckLevel, "default-cert-check-level", 1, "@"}, + { oDefCertLevel, "default-cert-check-level", 1, "@"}, /* Old option */ { oAlwaysTrust, "always-trust", 0, "@"}, { oTrustModel, "trust-model", 2, "@"}, { oForceOwnertrust, "force-ownertrust", 2, "@"}, - { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"}, { oSetFilename, "set-filename", 2, "@" }, { oForYourEyesOnly, "for-your-eyes-only", 0, "@" }, { oNoForYourEyesOnly, "no-for-your-eyes-only", 0, "@" }, @@ -559,9 +600,9 @@ static ARGPARSE_OPTS opts[] = { { oCertPolicyURL, "cert-policy-url", 2, "@" }, { oShowPolicyURL, "show-policy-url", 0, "@" }, { oNoShowPolicyURL, "no-show-policy-url", 0, "@" }, + { oSigKeyserverURL, "sig-keyserver-url", 2, "@" }, { oShowNotation, "show-notation", 0, "@" }, { oNoShowNotation, "no-show-notation", 0, "@" }, - { oSigKeyserverURL, "sig-keyserver-url", 2, "@" }, { oComment, "comment", 2, "@" }, { oDefaultComment, "default-comment", 0, "@" }, { oNoComments, "no-comments", 0, "@" }, @@ -575,10 +616,9 @@ static ARGPARSE_OPTS opts[] = { { oLockMultiple, "lock-multiple", 0, "@" }, { oLockNever, "lock-never", 0, "@" }, { oLoggerFD, "logger-fd",1, "@" }, -#ifdef __riscos__ - { oLoggerFile, "logger-file",2, "@" }, -#endif /* __riscos__ */ + { oLoggerFile, "log-file",2, "@" }, { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" }, + { oNoUseEmbeddedFilename, "no-use-embedded-filename", 0, "@" }, { oUtf8Strings, "utf8-strings", 0, "@" }, { oNoUtf8Strings, "no-utf8-strings", 0, "@" }, { oWithFingerprint, "with-fingerprint", 0, "@" }, @@ -619,7 +659,11 @@ static ARGPARSE_OPTS opts[] = { { oPersonalCipherPreferences, "personal-cipher-preferences", 2, "@"}, { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, - { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"}, + /* Aliases. I constantly mistype these, and assume other people + do as well. */ + { oPersonalCipherPreferences, "personal-cipher-prefs", 2, "@"}, + { oPersonalDigestPreferences, "personal-digest-prefs", 2, "@"}, + { oPersonalCompressPreferences, "personal-compress-prefs", 2, "@"}, { oAgentProgram, "agent-program", 2 , "@" }, { oDisplay, "display", 2, "@" }, { oTTYname, "ttyname", 2, "@" }, @@ -627,14 +671,41 @@ static ARGPARSE_OPTS opts[] = { { oLCctype, "lc-ctype", 2, "@" }, { oLCmessages, "lc-messages", 2, "@" }, { oGroup, "group", 2, "@" }, + { oUnGroup, "ungroup", 2, "@" }, + { oNoGroups, "no-groups", 0, "@" }, { oStrict, "strict", 0, "@" }, { oNoStrict, "no-strict", 0, "@" }, { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" }, { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" }, { oEnableProgressFilter, "enable-progress-filter", 0, "@" }, { oMultifile, "multifile", 0, "@" }, -{0} }; - + { oKeyidFormat, "keyid-format", 2, "@" }, + { oExitOnStatusWriteError, "exit-on-status-write-error", 0, "@" }, + { oLimitCardInsertTries, "limit-card-insert-tries", 1, "@"}, + + { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"}, + + /* These two are aliases to help users of the PGP command line + product use gpg with minimal pain. Many commands are common + already as they seem to have borrowed commands from us. Now + I'm returning the favor. */ + { oLocalUser, "sign-with", 2, "@" }, + { oRecipient, "user", 2, "@" }, + { oRequireCrossCert, "require-backsigs", 0, "@"}, + { oRequireCrossCert, "require-cross-certification", 0, "@"}, + { oNoRequireCrossCert, "no-require-backsigs", 0, "@"}, + { oNoRequireCrossCert, "no-require-cross-certification", 0, "@"}, + { oAutoKeyLocate, "auto-key-locate", 2, "@"}, + { oNoAutoKeyLocate, "no-auto-key-locate", 0, "@"}, + {0,NULL,0,NULL} +}; + + +#ifdef ENABLE_SELINUX_HACKS +#define ALWAYS_ADD_KEYRINGS 1 +#else +#define ALWAYS_ADD_KEYRINGS 0 +#endif int g10_errors_seen = 0; @@ -652,16 +723,6 @@ static void add_policy_url( const char *string, int which ); static void add_keyserver_url( const char *string, int which ); static void emergency_cleanup (void); -#ifdef __riscos__ -RISCOS_GLOBAL_STATICS("GnuPG Heap") -#endif /* __riscos__ */ - -static int -pk_test_algo (int algo) -{ - return openpgp_pk_test_algo (algo, 0); -} - static const char * my_strusage( int level ) @@ -676,6 +737,19 @@ my_strusage( int level ) case 19: p = _("Please report bugs to <gnupg-bugs@gnu.org>.\n"); break; + +#ifdef IS_DEVELOPMENT_VERSION + case 20: + p="NOTE: THIS IS A DEVELOPMENT VERSION!"; + break; + case 21: + p="It is only intended for test purposes and should NOT be"; + break; + case 22: + p="used in a production environment or with production keys!"; + break; +#endif + case 1: case 40: p = _("Usage: gpg [options] [files] (-h for help)"); @@ -694,27 +768,31 @@ my_strusage( int level ) #endif /* __riscos__ */ case 33: p = _("\nSupported algorithms:\n"); break; case 34: - if( !pubkeys ) - pubkeys = build_list(_("Pubkey: "), 0, gcry_pk_algo_name, - pk_test_algo ); + if (!pubkeys) + pubkeys = build_list (_("Pubkey: "), 0, + gcry_pk_algo_name, + openpgp_pk_test_algo ); p = pubkeys; break; case 35: if( !ciphers ) - ciphers = build_list(_("Cipher: "), 'S', gcry_cipher_algo_name, + ciphers = build_list(_("Cipher: "), 'S', + gcry_cipher_algo_name, openpgp_cipher_test_algo ); p = ciphers; break; case 36: if( !digests ) - digests = build_list(_("Hash: "), 'H', gcry_md_algo_name, - openpgp_md_test_algo ); + digests = build_list(_("Hash: "), 'H', + gcry_md_algo_name, + openpgp_md_test_algo ); p = digests; break; case 37: if( !zips ) - zips = build_list(_("Compression: "),'Z',compress_algo_to_string, - check_compress_algo); + zips = build_list(_("Compression: "),'Z', + compress_algo_to_string, + check_compress_algo); p = zips; break; @@ -733,13 +811,13 @@ build_list( const char *text, char letter, size_t n=strlen(text)+2; char *list, *p, *line=NULL; - if( maybe_setuid ) - gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* drop setuid */ + if (maybe_setuid) + gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */ for(i=0; i <= 110; i++ ) if( !chkf(i) && (s=mapf(i)) ) n += strlen(s) + 7 + 2; - list = xmalloc ( 21 + n ); *list = 0; + list = xmalloc( 21 + n ); *list = 0; for(p=NULL, i=0; i <= 110; i++ ) { if( !chkf(i) && (s=mapf(i)) ) { if( !p ) { @@ -752,7 +830,7 @@ build_list( const char *text, char letter, if(strlen(line)>60) { int spaces=strlen(text); - list = xrealloc(list,n+spaces+1); + list=xrealloc(list,n+spaces+1); /* realloc could move the block, so find the end again */ p=list; while(*p) @@ -783,12 +861,12 @@ static void i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE_GT ); + set_gettext_file (PACKAGE_GT, "Software\\GNU\\GnuPG"); #else #ifdef ENABLE_NLS - setlocale( LC_ALL, "" ); - bindtextdomain( PACKAGE_GT, LOCALEDIR ); - textdomain( PACKAGE_GT ); + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); #endif #endif } @@ -803,42 +881,15 @@ wrong_args( const char *text) } -static void -log_set_strict (int yesno) -{ - /* FIXME-XXX*/ -} - static char * make_username( const char *string ) { - char *p; - if( utf8_strings ) - p = xstrdup (string); - else - p = native_to_utf8( string ); - return p; -} - - -/* - * same as add_to_strlist() but if is_utf8 is *not* set a conversion - * to UTF8 is done - */ -static STRLIST -add_to_strlist2 ( STRLIST *list, const char *string, int is_utf8) -{ - STRLIST sl; - - if (is_utf8) - sl = add_to_strlist( list, string ); - else - { - char *p = native_to_utf8( string ); - sl = add_to_strlist( list, p ); - xfree( p ); - } - return sl; + char *p; + if( utf8_strings ) + p = xstrdup(string); + else + p = native_to_utf8( string ); + return p; } @@ -878,9 +929,11 @@ set_debug (const char *level) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); if (opt.debug & DBG_IOBUF_VALUE ) iobuf_debug_mode = 1; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); } + /* We need the home directory also in some other directories, so make sure that both variables are always in sync. */ static void @@ -888,10 +941,80 @@ set_homedir (const char *dir) { if (!dir) dir = ""; - g10_opt_homedir = opt.homedir = dir; + opt.homedir = dir; } +/* We set the screen dimensions for UI purposes. Do not allow screens + smaller than 80x24 for the sake of simplicity. */ +static void +set_screen_dimensions(void) +{ +#ifndef HAVE_W32_SYSTEM + char *str; + + str=getenv("COLUMNS"); + if(str) + opt.screen_columns=atoi(str); + + str=getenv("LINES"); + if(str) + opt.screen_lines=atoi(str); +#endif + + if(opt.screen_columns<80 || opt.screen_columns>255) + opt.screen_columns=80; + + if(opt.screen_lines<24 || opt.screen_lines>255) + opt.screen_lines=24; +} + + +/* Helper to open a file FNAME either for reading or writing to be + used with --status-file etc functions. Not generally useful but it + avoids the riscos specific functions and well some Windows people + might like it too. Prints an error message and returns -1 on + error. On success the file descriptor is returned. */ +static int +open_info_file (const char *fname, int for_write) +{ +#ifdef __riscos__ + return riscos_fdopenfile (fname, for_write); +#elif defined (ENABLE_SELINUX_HACKS) + /* We can't allow these even when testing for a secured filename + because files to be secured might not yet been secured. This is + similar to the option file but in that case it is unlikely that + sensitive information may be retrieved by means of error + messages. */ + return -1; +#else + int fd; + +/* if (is_secured_filename (fname)) */ +/* { */ +/* fd = -1; */ +/* errno = EPERM; */ +/* } */ +/* else */ +/* { */ + do + { + if (for_write) + fd = open (fname, O_CREAT | O_TRUNC | O_WRONLY, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + else + fd = open (fname, O_RDONLY | MY_O_BINARY); + } + while (fd == -1 && errno == EINTR); +/* } */ + if ( fd == -1) + log_error ( for_write? _("can't create `%s': %s\n") + : _("can't open `%s': %s\n"), fname, strerror(errno)); + + return fd; +#endif +} + static void set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) { @@ -907,6 +1030,18 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) cmd = aSignSym; else if( cmd == aSym && new_cmd == aSign ) cmd = aSignSym; + else if( cmd == aSym && new_cmd == aEncr ) + cmd = aEncrSym; + else if( cmd == aEncr && new_cmd == aSym ) + cmd = aEncrSym; + else if( cmd == aKMode && new_cmd == aSym ) + cmd = aKModeC; + else if (cmd == aSignEncr && new_cmd == aSym) + cmd = aSignEncrSym; + else if (cmd == aSignSym && new_cmd == aEncr) + cmd = aSignEncrSym; + else if (cmd == aEncrSym && new_cmd == aSign) + cmd = aSignEncrSym; else if( ( cmd == aSign && new_cmd == aClearsign ) || ( cmd == aClearsign && new_cmd == aSign ) ) cmd = aClearsign; @@ -919,47 +1054,79 @@ set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ) } -static void add_group(char *string) +static void +add_group(char *string) { char *name,*value; struct groupitem *item; - STRLIST values=NULL; /* Break off the group name */ name=strsep(&string,"="); if(string==NULL) { - log_error(_("no = sign found in group definition \"%s\"\n"),name); + log_error(_("no = sign found in group definition `%s'\n"),name); return; } - trim_trailing_ws((unsigned char *)name,strlen(name)); + trim_trailing_ws(name,strlen(name)); + + /* Does this group already exist? */ + for(item=opt.grouplist;item;item=item->next) + if(strcasecmp(item->name,name)==0) + break; + + if(!item) + { + item=xmalloc(sizeof(struct groupitem)); + item->name=name; + item->next=opt.grouplist; + item->values=NULL; + opt.grouplist=item; + } /* Break apart the values */ while ((value= strsep(&string," \t"))) { if (*value) - add_to_strlist2 (&values,value,utf8_strings); + add_to_strlist2(&item->values,value,utf8_strings); } +} + + +static void +rm_group(char *name) +{ + struct groupitem *item,*last=NULL; - item=xmalloc (sizeof(struct groupitem)); - item->name=name; - item->values=values; - item->next=opt.grouplist; + trim_trailing_ws(name,strlen(name)); + + for(item=opt.grouplist;item;last=item,item=item->next) + { + if(strcasecmp(item->name,name)==0) + { + if(last) + last->next=item->next; + else + opt.grouplist=item->next; - opt.grouplist=item; + free_strlist(item->values); + xfree(item); + break; + } + } } + /* We need to check three things. 0) The homedir. It must be x00, a directory, and owned by the user. - 1) The options file. Okay unless it or its containing directory is - group or other writable or not owned by us. disable exec in this - case. + 1) The options/gpg.conf file. Okay unless it or its containing + directory is group or other writable or not owned by us. Disable + exec in this case. - 2) Extensions. Same as #2. + 2) Extensions. Same as #1. Returns true if the item is unsafe. */ static int @@ -986,7 +1153,7 @@ check_permissions(const char *path,int item) tmppath=make_filename(GNUPG_LIBDIR,path,NULL); } else - tmppath=xstrdup (path); + tmppath=xstrdup(path); /* If the item is located in the homedir, but isn't the homedir, don't continue if we already checked the homedir itself. This is @@ -1019,7 +1186,7 @@ check_permissions(const char *path,int item) goto end; } - xfree (dir); + xfree(dir); /* Assume failure */ ret=1; @@ -1094,55 +1261,55 @@ check_permissions(const char *path,int item) if(own) { if(item==0) - log_info(_("WARNING: unsafe ownership on " - "homedir \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe ownership on" + " homedir `%s'\n"),tmppath); else if(item==1) - log_info(_("WARNING: unsafe ownership on " - "configuration file \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe ownership on" + " configuration file `%s'\n"),tmppath); else - log_info(_("WARNING: unsafe ownership on " - "extension \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe ownership on" + " extension `%s'\n"),tmppath); } if(perm) { if(item==0) - log_info(_("WARNING: unsafe permissions on " - "homedir \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe permissions on" + " homedir `%s'\n"),tmppath); else if(item==1) - log_info(_("WARNING: unsafe permissions on " - "configuration file \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe permissions on" + " configuration file `%s'\n"),tmppath); else - log_info(_("WARNING: unsafe permissions on " - "extension \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe permissions on" + " extension `%s'\n"),tmppath); } if(enc_dir_own) { if(item==0) - log_info(_("WARNING: unsafe enclosing directory ownership on " - "homedir \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe enclosing directory ownership on" + " homedir `%s'\n"),tmppath); else if(item==1) - log_info(_("WARNING: unsafe enclosing directory ownership on " - "configuration file \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe enclosing directory ownership on" + " configuration file `%s'\n"),tmppath); else - log_info(_("WARNING: unsafe enclosing directory ownership on " - "extension \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe enclosing directory ownership on" + " extension `%s'\n"),tmppath); } if(enc_dir_perm) { if(item==0) - log_info(_("WARNING: unsafe enclosing directory permissions on " - "homedir \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe enclosing directory permissions on" + " homedir `%s'\n"),tmppath); else if(item==1) - log_info(_("WARNING: unsafe enclosing directory permissions on " - "configuration file \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe enclosing directory permissions on" + " configuration file `%s'\n"),tmppath); else - log_info(_("WARNING: unsafe enclosing directory permissions on " - "extension \"%s\"\n"),tmppath); + log_info(_("WARNING: unsafe enclosing directory permissions on" + " extension `%s'\n"),tmppath); } } end: - xfree (tmppath); + xfree(tmppath); if(homedir) homedir_cache=ret; @@ -1154,11 +1321,326 @@ check_permissions(const char *path,int item) return 0; } + +static void +print_algo_numbers(int (*checker)(int)) +{ + int i,first=1; + + for(i=0;i<=110;i++) + { + if(!checker(i)) + { + if(first) + first=0; + else + printf(";"); + printf("%d",i); + } + } +} + + +/* In the future, we can do all sorts of interesting configuration + output here. For now, just give "group" as the Enigmail folks need + it, and pubkey, cipher, hash, and compress as they may be useful + for frontends. */ +static void +list_config(char *items) +{ + int show_all=(items==NULL); + char *name=NULL; + + if(!opt.with_colons) + return; + + while(show_all || (name=strsep(&items," "))) + { + int any=0; + + if(show_all || ascii_strcasecmp(name,"group")==0) + { + struct groupitem *iter; + + for(iter=opt.grouplist;iter;iter=iter->next) + { + STRLIST sl; + + printf("cfg:group:"); + print_string(stdout,iter->name,strlen(iter->name),':'); + printf(":"); + + for(sl=iter->values;sl;sl=sl->next) + { + print_string2(stdout,sl->d,strlen(sl->d),':',';'); + if(sl->next) + printf(";"); + } + + printf("\n"); + } + + any=1; + } + + if(show_all || ascii_strcasecmp(name,"version")==0) + { + printf("cfg:version:"); + print_string(stdout,VERSION,strlen(VERSION),':'); + printf("\n"); + any=1; + } + + if(show_all || ascii_strcasecmp(name,"pubkey")==0) + { + printf("cfg:pubkey:"); + print_algo_numbers (openpgp_pk_test_algo); + printf("\n"); + any=1; + } + + if(show_all || ascii_strcasecmp(name,"cipher")==0) + { + printf("cfg:cipher:"); + print_algo_numbers(openpgp_cipher_test_algo); + printf("\n"); + any=1; + } + + if(show_all + || ascii_strcasecmp(name,"digest")==0 + || ascii_strcasecmp(name,"hash")==0) + { + printf("cfg:digest:"); + print_algo_numbers(openpgp_md_test_algo); + printf("\n"); + any=1; + } + + if(show_all || ascii_strcasecmp(name,"compress")==0) + { + printf("cfg:compress:"); + print_algo_numbers(check_compress_algo); + printf("\n"); + any=1; + } + + if(show_all || ascii_strcasecmp(name,"ccid-reader-id")==0) + { +#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB) + char *p, *p2, *list = ccid_get_reader_list (); + + for (p=list; p && (p2 = strchr (p, '\n')); p = p2+1) + { + *p2 = 0; + printf("cfg:ccid-reader-id:%s\n", p); + } + free (list); +#endif + any=1; + } + + if(show_all) + break; + + if(!any) + log_error(_("unknown configuration item `%s'\n"),name); + } +} + + +/* List options and default values in the GPG Conf format. This is a + new tool distributed with gnupg 1.9.x but we also want some limited + support in older gpg versions. The output is the name of the + configuration file and a list of options available for editing by + gpgconf. */ +static void +gpgconf_list (const char *configfile) +{ + /* The following definitions are taken from gnupg/tools/gpgconf-comp.c. */ +#define GC_OPT_FLAG_NONE 0UL +#define GC_OPT_FLAG_DEFAULT (1UL << 4) + + printf ("gpgconf-gpg.conf:%lu:\"%s\n", + GC_OPT_FLAG_DEFAULT,configfile?configfile:"/dev/null"); + printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE); + printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE); + printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); + printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE); +} + + +static int +parse_subpacket_list(char *list) +{ + char *tok; + byte subpackets[128],i; + int count=0; + + if(!list) + { + /* No arguments means all subpackets */ + memset(subpackets+1,1,sizeof(subpackets)-1); + count=127; + } + else + { + memset(subpackets,0,sizeof(subpackets)); + + /* Merge with earlier copy */ + if(opt.show_subpackets) + { + byte *in; + + for(in=opt.show_subpackets;*in;in++) + { + if(*in>127 || *in<1) + BUG(); + + if(!subpackets[*in]) + count++; + subpackets[*in]=1; + } + } + + while((tok=strsep(&list," ,"))) + { + if(!*tok) + continue; + + i=atoi(tok); + if(i>127 || i<1) + return 0; + + if(!subpackets[i]) + count++; + subpackets[i]=1; + } + } + + xfree(opt.show_subpackets); + opt.show_subpackets=xmalloc(count+1); + opt.show_subpackets[count--]=0; + + for(i=1;i<128 && count>=0;i++) + if(subpackets[i]) + opt.show_subpackets[count--]=i; + + return 1; +} + + +static int +parse_list_options(char *str) +{ + char *subpackets=""; /* something that isn't NULL */ + struct parse_options lopts[]= + { + {"show-photos",LIST_SHOW_PHOTOS,NULL, + N_("display photo IDs during key listings")}, + {"show-policy-urls",LIST_SHOW_POLICY_URLS,NULL, + N_("show policy URLs during signature listings")}, + {"show-notations",LIST_SHOW_NOTATIONS,NULL, + N_("show all notations during signature listings")}, + {"show-std-notations",LIST_SHOW_STD_NOTATIONS,NULL, + N_("show IETF standard notations during signature listings")}, + {"show-standard-notations",LIST_SHOW_STD_NOTATIONS,NULL, + NULL}, + {"show-user-notations",LIST_SHOW_USER_NOTATIONS,NULL, + N_("show user-supplied notations during signature listings")}, + {"show-keyserver-urls",LIST_SHOW_KEYSERVER_URLS,NULL, + N_("show preferred keyserver URLs during signature listings")}, + {"show-uid-validity",LIST_SHOW_UID_VALIDITY,NULL, + N_("show user ID validity during key listings")}, + {"show-unusable-uids",LIST_SHOW_UNUSABLE_UIDS,NULL, + N_("show revoked and expired user IDs in key listings")}, + {"show-unusable-subkeys",LIST_SHOW_UNUSABLE_SUBKEYS,NULL, + N_("show revoked and expired subkeys in key listings")}, + {"show-keyring",LIST_SHOW_KEYRING,NULL, + N_("show the keyring name in key listings")}, + {"show-sig-expire",LIST_SHOW_SIG_EXPIRE,NULL, + N_("show expiration dates during signature listings")}, + {"show-sig-subpackets",LIST_SHOW_SIG_SUBPACKETS,NULL, + NULL}, + {NULL,0,NULL,NULL} + }; + + /* C99 allows for non-constant initializers, but we'd like to + compile everywhere, so fill in the show-sig-subpackets argument + here. Note that if the parse_options array changes, we'll have + to change the subscript here. */ + lopts[12].value=&subpackets; + + if(parse_options(str,&opt.list_options,lopts,1)) + { + if(opt.list_options&LIST_SHOW_SIG_SUBPACKETS) + { + /* Unset so users can pass multiple lists in. */ + opt.list_options&=~LIST_SHOW_SIG_SUBPACKETS; + if(!parse_subpacket_list(subpackets)) + return 0; + } + else if(subpackets==NULL && opt.show_subpackets) + { + /* User did 'no-show-subpackets' */ + xfree(opt.show_subpackets); + opt.show_subpackets=NULL; + } + + return 1; + } + else + return 0; +} + + +/* Collapses argc/argv into a single string that must be freed */ +static char * +collapse_args(int argc,char *argv[]) +{ + char *str=NULL; + int i,first=1,len=0; + + for(i=0;i<argc;i++) + { + len+=strlen(argv[i])+2; + str=xrealloc(str,len); + if(first) + { + str[0]='\0'; + first=0; + } + else + strcat(str," "); + + strcat(str,argv[i]); + } + + return str; +} + +static void +parse_trust_model(const char *model) +{ + if(ascii_strcasecmp(model,"pgp")==0) + opt.trust_model=TM_PGP; + else if(ascii_strcasecmp(model,"classic")==0) + opt.trust_model=TM_CLASSIC; + else if(ascii_strcasecmp(model,"always")==0) + opt.trust_model=TM_ALWAYS; + else if(ascii_strcasecmp(model,"direct")==0) + opt.trust_model=TM_DIRECT; + else if(ascii_strcasecmp(model,"auto")==0) + opt.trust_model=TM_AUTO; + else + log_error("unknown trust model `%s'\n",model); +} + int -main( int argc, char **argv ) +main (int argc, char **argv ) { ARGPARSE_ARGS pargs; - iobuf_t a; + IOBUF a; int rc=0; int orig_argc; char **orig_argv; @@ -1171,7 +1653,7 @@ main( int argc, char **argv ) int detached_sig = 0; FILE *configfp = NULL; char *configname = NULL; - const char *config_filename = NULL; + char *save_configname = NULL; unsigned configlineno; int parse_debug = 0; int default_config = 1; @@ -1185,7 +1667,7 @@ main( int argc, char **argv ) const char *trustdb_name = NULL; char *def_cipher_string = NULL; char *def_digest_string = NULL; - char *def_compress_string = NULL; + char *compress_algo_string = NULL; char *cert_digest_string = NULL; char *s2k_cipher_string = NULL; char *s2k_digest_string = NULL; @@ -1197,47 +1679,53 @@ main( int argc, char **argv ) int pwfd = -1; int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; + int require_secmem=0,got_secmem=0; #ifdef __riscos__ - riscos_global_defaults(); opt.lock_once = 1; #endif /* __riscos__ */ + + /* Please note that we may running SUID(ROOT), so be very CAREFUL + when adding any stuff between here and the call to + secmem_init() somewhere after the option parsing. */ + trap_unaligned(); set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); /* We don't need any locking in libgcrypt unless we use any kind of threading. */ gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING); - /* Please note that we may running SUID(ROOT), so be very CAREFUL - * when adding any stuff between here and the call to - * secmem_init() somewhere after the option parsing - */ log_set_prefix ("gpg", 1); - /* check that the libraries are suitable. Do it here because the - option parse may need services of the library */ + + /* Check that the libraries are suitable. Do it right here because the + option parsing may need services of the library. */ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); + log_fatal ( _("libgcrypt is too old (need %s, have %s)\n"), + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); } + /* Put random number into secure memory */ gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); may_coredump = disable_core_dumps(); + gnupg_init_signals (0, emergency_cleanup); - create_dotlock (NULL); /* register locking cleanup */ + + create_dotlock(NULL); /* Register locking cleanup. */ + i18n_init(); opt.command_fd = -1; /* no command fd */ - opt.compress = -1; /* defaults to standard compress level */ + opt.compress_level = -1; /* defaults to standard compress level */ + opt.bz2_compress_level = -1; /* defaults to standard compress level */ /* note: if you change these lines, look at oOpenPGP */ opt.def_cipher_algo = 0; opt.def_digest_algo = 0; opt.cert_digest_algo = 0; - opt.def_compress_algo = -1; + opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */ opt.s2k_mode = 3; /* iterated+salted */ - opt.s2k_digest_algo = DIGEST_ALGO_SHA1; #ifdef USE_CAST5 opt.s2k_cipher_algo = CIPHER_ALGO_CAST5; #else @@ -1250,23 +1738,24 @@ main( int argc, char **argv ) opt.force_v3_sigs = 1; opt.escape_from = 1; opt.import_options=IMPORT_SK2PK; - opt.export_options= - EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; + opt.export_options=EXPORT_ATTRIBUTES; opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG; - opt.keyserver_options.export_options= - EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES; - opt.keyserver_options.include_subkeys=1; - opt.keyserver_options.include_revoked=1; - opt.keyserver_options.try_dns_srv=1; + opt.keyserver_options.export_options=EXPORT_ATTRIBUTES; + opt.keyserver_options.options= + KEYSERVER_HONOR_KEYSERVER_URL|KEYSERVER_HONOR_PKA_RECORD; opt.verify_options= - VERIFY_SHOW_POLICY|VERIFY_SHOW_NOTATION|VERIFY_SHOW_KEYSERVER; + VERIFY_SHOW_POLICY_URLS|VERIFY_SHOW_STD_NOTATIONS|VERIFY_SHOW_KEYSERVER_URLS; opt.trust_model=TM_AUTO; - opt.mangle_dos_filenames = 1; - opt.use_agent = 1; - + opt.mangle_dos_filenames=0; + opt.min_cert_level=2; + set_screen_dimensions(); + opt.keyid_format=KF_SHORT; + opt.rfc2440_text=1; + opt.def_sig_expire="0"; + opt.def_cert_expire="0"; set_homedir ( default_homedir () ); - /* Check whether we have a config file on the commandline */ + /* Check whether we have a config file on the command line. */ orig_argc = argc; orig_argv = argv; pargs.argc = &argc; @@ -1304,7 +1793,13 @@ main( int argc, char **argv ) char *d, *buf = xmalloc (strlen (opt.homedir)+1); const char *s = opt.homedir; for (d=buf,s=opt.homedir; *s; s++) + { *d++ = *s == '\\'? '/': *s; +#ifdef HAVE_W32_SYSTEM + if (s[1] && IsDBCSLeadByte (*s)) + *d++ = *++s; +#endif + } *d = 0; set_homedir (buf); } @@ -1312,19 +1807,28 @@ main( int argc, char **argv ) /* Initialize the secure memory. */ gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0); + got_secmem = 1; /* FIXME: gcry_control should return an indicator. */ +#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 maybe_setuid = 0; + /* Okay, we are now working under our real uid */ /* malloc hooks go here ... */ assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); + set_native_charset (NULL); /* Try to auto set the character set */ /* Try for a version specific config file first */ if( default_config ) { - char *name = xstrdup ("gpg" EXTSEP_S "conf-" SAFE_VERSION); - char *ver = name + strlen("gpg" EXTSEP_S "conf-"); + char *name=xstrdup("gpg" EXTSEP_S "conf-" SAFE_VERSION); + char *ver=&name[strlen("gpg" EXTSEP_S "conf-")]; do { @@ -1332,22 +1836,25 @@ main( int argc, char **argv ) { char *tok; - xfree (configname); + xfree(configname); configname=NULL; - if((tok=strrchr (ver,SAFE_VERSION_DASH))) + if((tok=strrchr(ver,SAFE_VERSION_DASH))) *tok='\0'; - else if((tok=strrchr (ver,SAFE_VERSION_DOT))) + else if((tok=strrchr(ver,SAFE_VERSION_DOT))) *tok='\0'; else break; } - configname = make_filename (opt.homedir, name, NULL); + configname = make_filename(opt.homedir,name,NULL); } - while ( access(configname,R_OK) ); + while(access(configname,R_OK)); + xfree(name); + if(!configname) + configname=make_filename(opt.homedir, "gpg" EXTSEP_S "conf", NULL ); if (!access (configname, R_OK)) { /* Print a warning when both config files are present. */ char *p = make_filename(opt.homedir, "options", NULL ); @@ -1385,6 +1892,12 @@ main( int argc, char **argv ) configlineno = 0; configfp = fopen( configname, "r" ); + if (configfp && is_secured_file (fileno (configfp))) + { + fclose (configfp); + configfp = NULL; + errno = EPERM; + } if( !configfp ) { if( default_config ) { if( parse_debug ) @@ -1396,7 +1909,7 @@ main( int argc, char **argv ) configname, strerror(errno) ); g10_exit(2); } - xfree (configname); configname = NULL; + xfree(configname); configname = NULL; } if( parse_debug && configname ) log_info(_("reading options from `%s'\n"), configname ); @@ -1404,24 +1917,32 @@ main( int argc, char **argv ) } while( optfile_parse( configfp, configname, &configlineno, - &pargs, opts) ) { - switch( pargs.r_opt ) { - case aCheckKeys: set_cmd( &cmd, aCheckKeys); break; - case aListPackets: set_cmd( &cmd, aListPackets); break; - case aImport: set_cmd( &cmd, aImport); break; - case aFastImport: set_cmd( &cmd, aFastImport); break; - case aSendKeys: set_cmd( &cmd, aSendKeys); break; - case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; - case aSearchKeys: set_cmd( &cmd, aSearchKeys); break; - case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; - case aExport: set_cmd( &cmd, aExport); break; - case aExportAll: set_cmd( &cmd, aExportAll); break; + &pargs, opts) ) + { + switch( pargs.r_opt ) + { + case aCheckKeys: + case aListConfig: + case aGPGConfList: + case aListPackets: + case aImport: + case aFastImport: + case aSendKeys: + case aRecvKeys: + case aSearchKeys: + case aRefreshKeys: + case aFetchKeys: + case aExport: + set_cmd (&cmd, pargs.r_opt); + break; case aListKeys: set_cmd( &cmd, aListKeys); break; case aListSigs: set_cmd( &cmd, aListSigs); break; case aExportSecret: set_cmd( &cmd, aExportSecret); break; case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break; - case aDeleteSecretKeys: set_cmd( &cmd, aDeleteSecretKeys); - greeting=1; break; + case aDeleteSecretKeys: + set_cmd( &cmd, aDeleteSecretKeys); + greeting=1; + break; case aDeleteSecretAndPublicKeys: set_cmd( &cmd, aDeleteSecretAndPublicKeys); greeting=1; @@ -1431,7 +1952,7 @@ main( int argc, char **argv ) case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break; case aSym: set_cmd( &cmd, aSym); break; - case aDecryptFiles: multifile=1; /* fall through */ + case aDecryptFiles: multifile=1; /* fall through */ case aDecrypt: set_cmd( &cmd, aDecrypt); break; case aEncrFiles: multifile=1; /* fall through */ @@ -1444,14 +1965,11 @@ main( int argc, char **argv ) case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break; case aSignKey: set_cmd( &cmd, aSignKey); break; case aLSignKey: set_cmd( &cmd, aLSignKey); break; - case aNRSignKey: set_cmd( &cmd, aNRSignKey); break; - case aNRLSignKey: set_cmd( &cmd, aNRLSignKey); break; case aStore: set_cmd( &cmd, aStore); break; case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break; case aClearsign: set_cmd( &cmd, aClearsign); break; case aGenRevoke: set_cmd( &cmd, aGenRevoke); break; case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break; - case aPrimegen: set_cmd( &cmd, aPrimegen); break; case aGenRandom: set_cmd( &cmd, aGenRandom); break; case aPrintMD: set_cmd( &cmd, aPrintMD); break; @@ -1468,28 +1986,23 @@ main( int argc, char **argv ) "--list-ownertrust","--export-ownertrust",""); case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break; case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break; - case aPipeMode: set_cmd( &cmd, aPipeMode); break; case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; - case aCardStatus: set_cmd (&cmd, aCardStatus); break; - case aCardEdit: set_cmd (&cmd, aCardEdit); break; - case aChangePIN: set_cmd (&cmd, aChangePIN); break; - case aGPGConfList: - set_cmd (&cmd, aGPGConfList); - nogreeting = 1; - break; - case oArmor: opt.armor = 1; opt.no_armor=0; break; case oOutput: opt.outfile = pargs.r.ret_str; break; + case oMaxOutput: opt.max_output = pargs.r.ret_ulong; break; case oQuiet: opt.quiet = 1; break; case oNoTTY: tty_no_terminal(1); break; case oDryRun: opt.dry_run = 1; break; case oInteractive: opt.interactive = 1; break; - case oVerbose: g10_opt_verbose++; - opt.verbose++; opt.list_sigs=1; break; + case oVerbose: + opt.verbose++; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); + opt.list_options|=LIST_SHOW_UNUSABLE_UIDS; + opt.list_options|=LIST_SHOW_UNUSABLE_SUBKEYS; + break; + case oKOption: set_cmd( &cmd, aKMode ); break; - case oLogFile: logfile = pargs.r.ret_str; break; - case oBatch: opt.batch = 1; nogreeting = 1; break; case oUseAgent: #ifndef __riscos__ @@ -1508,58 +2021,60 @@ main( int argc, char **argv ) sl=append_to_strlist( &nrings, pargs.r.ret_str); sl->flags=2; break; - case oShowKeyring: opt.list_options|=LIST_SHOW_KEYRING; break; + case oShowKeyring: + deprecated_warning(configname,configlineno,"--show-keyring", + "--list-options ","show-keyring"); + opt.list_options|=LIST_SHOW_KEYRING; + break; + case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; + case oStatusFD: set_status_fd( iobuf_translate_file_handle (pargs.r.ret_int, 1) ); break; -#ifdef __riscos__ case oStatusFile: - set_status_fd( iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + set_status_fd ( open_info_file (pargs.r.ret_str, 1) ); break; -#endif /* __riscos__ */ case oAttributeFD: set_attrib_fd(iobuf_translate_file_handle (pargs.r.ret_int, 1)); break; -#ifdef __riscos__ case oAttributeFile: - set_attrib_fd(iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + set_attrib_fd ( open_info_file (pargs.r.ret_str, 1) ); break; -#endif /* __riscos__ */ case oLoggerFD: log_set_fd (iobuf_translate_file_handle (pargs.r.ret_int, 1)); break; -#ifdef __riscos__ - case oLoggerFile: - log_set_logfile( NULL, - iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) ); + case oLoggerFile: + logfile = pargs.r.ret_str; break; -#endif /* __riscos__ */ + case oWithFingerprint: opt.with_fingerprint = 1; with_fpr=1; /*fall thru*/ case oFingerprint: opt.fingerprint++; break; - case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break; + case oSecretKeyring: + append_to_strlist( &sec_nrings, pargs.r.ret_str); + break; case oOptions: /* config files may not be nested (silently ignore them) */ if( !configfp ) { - xfree (configname); - configname = xstrdup (pargs.r.ret_str); + xfree(configname); + configname = xstrdup(pargs.r.ret_str); goto next_pass; } break; case oNoArmor: opt.no_armor=1; opt.armor=0; break; case oNoDefKeyring: default_keyring = 0; break; - case oDefCertCheckLevel: opt.def_cert_check_level=pargs.r.ret_int; break; case oNoGreeting: nogreeting = 1; break; - case oNoVerbose: g10_opt_verbose = 0; - opt.verbose = 0; opt.list_sigs=0; break; - /* disabled for now: - case oQuickRandom: quick_random_gen(1); break; */ - case oSKComments: opt.sk_comments=1; break; - case oNoSKComments: opt.sk_comments=0; break; + case oNoVerbose: + opt.verbose = 0; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); + opt.list_sigs=0; + break; + /* Disabled for now: + case oQuickRandom: quick_random_gen(1); break;*/ case oEmitVersion: opt.no_version=0; break; case oNoEmitVersion: opt.no_version=1; break; case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break; @@ -1572,11 +2087,11 @@ main( int argc, char **argv ) opt.def_recipient = make_username(pargs.r.ret_str); break; case oDefRecipientSelf: - xfree (opt.def_recipient); opt.def_recipient = NULL; + xfree(opt.def_recipient); opt.def_recipient = NULL; opt.def_recipient_self = 1; break; case oNoDefRecipient: - xfree (opt.def_recipient); opt.def_recipient = NULL; + xfree(opt.def_recipient); opt.def_recipient = NULL; opt.def_recipient_self = 0; break; case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */ @@ -1593,16 +2108,7 @@ main( int argc, char **argv ) time. */ case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break; case oTrustModel: - if(ascii_strcasecmp(pargs.r.ret_str,"pgp")==0) - opt.trust_model=TM_PGP; - else if(ascii_strcasecmp(pargs.r.ret_str,"classic")==0) - opt.trust_model=TM_CLASSIC; - else if(ascii_strcasecmp(pargs.r.ret_str,"always")==0) - opt.trust_model=TM_ALWAYS; - else if(ascii_strcasecmp(pargs.r.ret_str,"auto")==0) - opt.trust_model=TM_AUTO; - else - log_error("unknown trust model \"%s\"\n",pargs.r.ret_str); + parse_trust_model(pargs.r.ret_str); break; case oForceOwnertrust: log_info(_("NOTE: %s is not for normal use!\n"), @@ -1610,7 +2116,7 @@ main( int argc, char **argv ) opt.force_ownertrust=string_to_trust_value(pargs.r.ret_str); if(opt.force_ownertrust==-1) { - log_error("invalid ownertrust \"%s\"\n",pargs.r.ret_str); + log_error("invalid ownertrust `%s'\n",pargs.r.ret_str); opt.force_ownertrust=0; } break; @@ -1618,8 +2124,8 @@ main( int argc, char **argv ) #ifndef __riscos__ #if defined(USE_DYNAMIC_LINKING) || defined(_WIN32) if(check_permissions(pargs.r.ret_str,2)) - log_info(_("cipher extension \"%s\" not loaded due to " - "unsafe permissions\n"),pargs.r.ret_str); + log_info(_("cipher extension `%s' not loaded due to" + " unsafe permissions\n"),pargs.r.ret_str); else register_cipher_extension(orig_argc? *orig_argv:NULL, pargs.r.ret_str); @@ -1633,23 +2139,24 @@ main( int argc, char **argv ) opt.force_v4_certs = 0; opt.escape_from = 1; break; - case oRFC2440: case oOpenPGP: - /* TODO: When 2440bis becomes a RFC, these may need - changing. */ + case oRFC2440: + /* TODO: When 2440bis becomes a RFC, set new values for + oOpenPGP. */ + opt.rfc2440_text=1; opt.compliance = CO_RFC2440; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; opt.escape_from = 0; opt.force_v3_sigs = 0; - opt.compress_keys = 0; /* not mandated but we do it */ + opt.compress_keys = 0; /* not mandated, but we do it */ opt.compress_sigs = 0; /* ditto. */ opt.not_dash_escaped = 0; opt.def_cipher_algo = 0; opt.def_digest_algo = 0; opt.cert_digest_algo = 0; - opt.def_compress_algo = -1; + opt.compress_algo = -1; opt.s2k_mode = 3; /* iterated+salted */ opt.s2k_digest_algo = DIGEST_ALGO_SHA1; opt.s2k_cipher_algo = CIPHER_ALGO_3DES; @@ -1659,8 +2166,9 @@ main( int argc, char **argv ) case oPGP7: opt.compliance = CO_PGP7; break; case oPGP8: opt.compliance = CO_PGP8; break; case oGnuPG: opt.compliance = CO_GNUPG; break; - case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; case oCompressSigs: opt.compress_sigs = 1; break; + case oRFC2440Text: opt.rfc2440_text=1; break; + case oNoRFC2440Text: opt.rfc2440_text=0; break; case oSetFilename: opt.set_filename = pargs.r.ret_str; break; case oForYourEyesOnly: eyes_only = 1; break; case oNoForYourEyesOnly: eyes_only = 0; break; @@ -1671,17 +2179,28 @@ main( int argc, char **argv ) case oSigPolicyURL: add_policy_url(pargs.r.ret_str,0); break; case oCertPolicyURL: add_policy_url(pargs.r.ret_str,1); break; case oShowPolicyURL: - opt.list_options|=LIST_SHOW_POLICY; - opt.verify_options|=VERIFY_SHOW_POLICY; + deprecated_warning(configname,configlineno,"--show-policy-url", + "--list-options ","show-policy-urls"); + deprecated_warning(configname,configlineno,"--show-policy-url", + "--verify-options ","show-policy-urls"); + opt.list_options|=LIST_SHOW_POLICY_URLS; + opt.verify_options|=VERIFY_SHOW_POLICY_URLS; break; case oNoShowPolicyURL: - opt.list_options&=~LIST_SHOW_POLICY; - opt.verify_options&=~VERIFY_SHOW_POLICY; + deprecated_warning(configname,configlineno,"--no-show-policy-url", + "--list-options ","no-show-policy-urls"); + deprecated_warning(configname,configlineno,"--no-show-policy-url", + "--verify-options ","no-show-policy-urls"); + opt.list_options&=~LIST_SHOW_POLICY_URLS; + opt.verify_options&=~VERIFY_SHOW_POLICY_URLS; break; case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; - - case oComment: add_to_strlist(&opt.comments,pargs.r.ret_str); break; + case oNoUseEmbeddedFilename: opt.use_embedded_filename = 0; break; + case oComment: + if(pargs.r.ret_str[0]) + append_to_strlist(&opt.comments,pargs.r.ret_str); + break; case oDefaultComment: deprecated_warning(configname,configlineno, "--default-comment","--no-comments",""); @@ -1690,14 +2209,21 @@ main( int argc, char **argv ) free_strlist(opt.comments); opt.comments=NULL; break; - - case oThrowKeyid: opt.throw_keyid = 1; break; - case oNoThrowKeyid: opt.throw_keyid = 0; break; - case oShowPhotos: + case oThrowKeyids: opt.throw_keyid = 1; break; + case oNoThrowKeyids: opt.throw_keyid = 0; break; + case oShowPhotos: + deprecated_warning(configname,configlineno,"--show-photos", + "--list-options ","show-photos"); + deprecated_warning(configname,configlineno,"--show-photos", + "--verify-options ","show-photos"); opt.list_options|=LIST_SHOW_PHOTOS; opt.verify_options|=VERIFY_SHOW_PHOTOS; break; case oNoShowPhotos: + deprecated_warning(configname,configlineno,"--no-show-photos", + "--list-options ","no-show-photos"); + deprecated_warning(configname,configlineno,"--no-show-photos", + "--verify-options ","no-show-photos"); opt.list_options&=~LIST_SHOW_PHOTOS; opt.verify_options&=~VERIFY_SHOW_PHOTOS; break; @@ -1711,8 +2237,8 @@ main( int argc, char **argv ) case oDisableMDC: opt.disable_mdc = 1; break; case oNoDisableMDC: opt.disable_mdc = 0; break; case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break; - case oS2KDigest: s2k_digest_string = xstrdup (pargs.r.ret_str); break; - case oS2KCipher: s2k_cipher_string = xstrdup (pargs.r.ret_str); break; + case oS2KDigest: s2k_digest_string = xstrdup(pargs.r.ret_str); break; + case oS2KCipher: s2k_cipher_string = xstrdup(pargs.r.ret_str); break; case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break; case oNoEncryptTo: opt.no_encrypt_to = 1; break; case oEncryptTo: /* store the recipient in the second list */ @@ -1737,33 +2263,66 @@ main( int argc, char **argv ) case oNoTextmode: opt.textmode=0; break; case oExpert: opt.expert = 1; break; case oNoExpert: opt.expert = 0; break; + case oDefSigExpire: + if(*pargs.r.ret_str!='\0') + { + if(parse_expire_string(pargs.r.ret_str)==(u32)-1) + log_error(_("`%s' is not a valid signature expiration\n"), + pargs.r.ret_str); + else + opt.def_sig_expire=pargs.r.ret_str; + } + break; case oAskSigExpire: opt.ask_sig_expire = 1; break; case oNoAskSigExpire: opt.ask_sig_expire = 0; break; + case oDefCertExpire: + if(*pargs.r.ret_str!='\0') + { + if(parse_expire_string(pargs.r.ret_str)==(u32)-1) + log_error(_("`%s' is not a valid signature expiration\n"), + pargs.r.ret_str); + else + opt.def_cert_expire=pargs.r.ret_str; + } + break; case oAskCertExpire: opt.ask_cert_expire = 1; break; case oNoAskCertExpire: opt.ask_cert_expire = 0; break; - case oUser: /* store the local users */ + case oDefCertLevel: opt.def_cert_level=pargs.r.ret_int; break; + case oMinCertLevel: opt.min_cert_level=pargs.r.ret_int; break; + case oAskCertLevel: opt.ask_cert_level = 1; break; + case oNoAskCertLevel: opt.ask_cert_level = 0; break; + case oLocalUser: /* store the local users */ add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings ); break; - case oCompress: opt.compress = pargs.r.ret_int; break; + case oCompress: + /* this is the -z command line option */ + opt.compress_level = opt.bz2_compress_level = pargs.r.ret_int; + break; + case oCompressLevel: opt.compress_level = pargs.r.ret_int; break; + case oBZ2CompressLevel: opt.bz2_compress_level = pargs.r.ret_int; break; + case oBZ2DecompressLowmem: opt.bz2_decompress_lowmem=1; break; + case oPasswd: + set_passphrase_from_string(pargs.r.ret_str); + break; case oPasswdFD: pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0); opt.use_agent = 0; break; -#ifdef __riscos__ case oPasswdFile: - pwfd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); + pwfd = open_info_file (pargs.r.ret_str, 0); break; -#endif /* __riscos__ */ case oCommandFD: opt.command_fd = iobuf_translate_file_handle (pargs.r.ret_int, 0); break; -#ifdef __riscos__ case oCommandFile: - opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0); + opt.command_fd = open_info_file (pargs.r.ret_str, 0); + break; + case oCipherAlgo: + def_cipher_string = xstrdup(pargs.r.ret_str); + break; + case oDigestAlgo: + def_digest_string = xstrdup(pargs.r.ret_str); break; -#endif /* __riscos__ */ - case oCipherAlgo: def_cipher_string = xstrdup (pargs.r.ret_str); break; - case oDigestAlgo: def_digest_string = xstrdup (pargs.r.ret_str); break; case oCompressAlgo: /* If it is all digits, stick a Z in front of it for later. This is for backwards compatibility with @@ -1772,7 +2331,7 @@ main( int argc, char **argv ) char *pt=pargs.r.ret_str; while(*pt) { - if(!isdigit(*pt)) + if (!isascii (*pt) || !isdigit (*pt)) break; pt++; @@ -1780,30 +2339,32 @@ main( int argc, char **argv ) if(*pt=='\0') { - def_compress_string=xmalloc (strlen(pargs.r.ret_str)+2); - strcpy(def_compress_string,"Z"); - strcat(def_compress_string,pargs.r.ret_str); + compress_algo_string=xmalloc(strlen(pargs.r.ret_str)+2); + strcpy(compress_algo_string,"Z"); + strcat(compress_algo_string,pargs.r.ret_str); } else - def_compress_string = xstrdup (pargs.r.ret_str); + compress_algo_string = xstrdup(pargs.r.ret_str); } break; - case oCertDigestAlgo: cert_digest_string = xstrdup (pargs.r.ret_str); break; - case oNoSecmemWarn: - gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); - break; + case oCertDigestAlgo: cert_digest_string = xstrdup(pargs.r.ret_str); break; + case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break; + case oRequireSecmem: require_secmem=1; break; + case oNoRequireSecmem: require_secmem=0; break; case oNoPermissionWarn: opt.no_perm_warn=1; break; case oNoMDCWarn: opt.no_mdc_warn=1; break; - case oCharset: + case oDisplayCharset: if( set_native_charset( pargs.r.ret_str ) ) - log_error(_("%s is not a valid character set\n"), - pargs.r.ret_str); + log_error(_("`%s' is not a valid character set\n"), + pargs.r.ret_str); break; case oNotDashEscaped: opt.not_dash_escaped = 1; break; case oEscapeFrom: opt.escape_from = 1; break; case oNoEscapeFrom: opt.escape_from = 0; break; case oLockOnce: opt.lock_once = 1; break; - case oLockNever: disable_dotlock(); break; + case oLockNever: + disable_dotlock (); + break; case oLockMultiple: #ifndef __riscos__ opt.lock_once = 0; @@ -1812,15 +2373,31 @@ main( int argc, char **argv ) #endif /* __riscos__ */ break; case oKeyServer: - opt.keyserver_uri=xstrdup (pargs.r.ret_str); - if(parse_keyserver_uri(pargs.r.ret_str,configname,configlineno)) - log_error(_("could not parse keyserver URI\n")); + { + struct keyserver_spec *keyserver; + keyserver=parse_keyserver_uri(pargs.r.ret_str,0, + configname,configlineno); + if(!keyserver) + log_error(_("could not parse keyserver URL\n")); + else + { + keyserver->next=opt.keyserver; + opt.keyserver=keyserver; + } + } break; case oKeyServerOptions: - parse_keyserver_options(pargs.r.ret_str); + if(!parse_keyserver_options(pargs.r.ret_str)) + { + if(configname) + log_error(_("%s:%d: invalid keyserver options\n"), + configname,configlineno); + else + log_error(_("invalid keyserver options\n")); + } break; case oImportOptions: - if(!parse_import_options(pargs.r.ret_str,&opt.import_options)) + if(!parse_import_options(pargs.r.ret_str,&opt.import_options,1)) { if(configname) log_error(_("%s:%d: invalid import options\n"), @@ -1830,7 +2407,7 @@ main( int argc, char **argv ) } break; case oExportOptions: - if(!parse_export_options(pargs.r.ret_str,&opt.export_options)) + if(!parse_export_options(pargs.r.ret_str,&opt.export_options,1)) { if(configname) log_error(_("%s:%d: invalid export options\n"), @@ -1840,44 +2417,45 @@ main( int argc, char **argv ) } break; case oListOptions: - { - struct parse_options lopts[]= - { - {"show-photos",LIST_SHOW_PHOTOS}, - {"show-policy-url",LIST_SHOW_POLICY}, - {"show-notation",LIST_SHOW_NOTATION}, - {"show-keyserver-url",LIST_SHOW_KEYSERVER}, - {"show-validity",LIST_SHOW_VALIDITY}, - {"show-long-keyid",LIST_SHOW_LONG_KEYID}, - {"show-keyring",LIST_SHOW_KEYRING}, - {"show-sig-expire",LIST_SHOW_SIG_EXPIRE}, - {NULL,0} - }; - - if(!parse_options(pargs.r.ret_str,&opt.list_options,lopts)) - { - if(configname) - log_error(_("%s:%d: invalid list options\n"), - configname,configlineno); - else - log_error(_("invalid list options\n")); - } - } + if(!parse_list_options(pargs.r.ret_str)) + { + if(configname) + log_error(_("%s:%d: invalid list options\n"), + configname,configlineno); + else + log_error(_("invalid list options\n")); + } break; case oVerifyOptions: { struct parse_options vopts[]= { - {"show-photos",VERIFY_SHOW_PHOTOS}, - {"show-policy-url",VERIFY_SHOW_POLICY}, - {"show-notation",VERIFY_SHOW_NOTATION}, - {"show-keyserver-url",VERIFY_SHOW_KEYSERVER}, - {"show-validity",VERIFY_SHOW_VALIDITY}, - {"show-long-keyid",VERIFY_SHOW_LONG_KEYID}, - {NULL,0} + {"show-photos",VERIFY_SHOW_PHOTOS,NULL, + N_("display photo IDs during signature verification")}, + {"show-policy-urls",VERIFY_SHOW_POLICY_URLS,NULL, + N_("show policy URLs during signature verification")}, + {"show-notations",VERIFY_SHOW_NOTATIONS,NULL, + N_("show all notations during signature verification")}, + {"show-std-notations",VERIFY_SHOW_STD_NOTATIONS,NULL, + N_("show IETF standard notations during signature verification")}, + {"show-standard-notations",VERIFY_SHOW_STD_NOTATIONS,NULL, + NULL}, + {"show-user-notations",VERIFY_SHOW_USER_NOTATIONS,NULL, + N_("show user-supplied notations during signature verification")}, + {"show-keyserver-urls",VERIFY_SHOW_KEYSERVER_URLS,NULL, + N_("show preferred keyserver URLs during signature verification")}, + {"show-uid-validity",VERIFY_SHOW_UID_VALIDITY,NULL, + N_("show user ID validity during signature verification")}, + {"show-unusable-uids",VERIFY_SHOW_UNUSABLE_UIDS,NULL, + N_("show revoked and expired user IDs in signature verification")}, + {"pka-lookups",VERIFY_PKA_LOOKUPS,NULL, + N_("validate signatures with PKA data")}, + {"pka-trust-increase",VERIFY_PKA_TRUST_INCREASE,NULL, + N_("elevate the trust of signatures with valid PKA data")}, + {NULL,0,NULL,NULL} }; - if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts)) + if(!parse_options(pargs.r.ret_str,&opt.verify_options,vopts,1)) { if(configname) log_error(_("%s:%d: invalid verify options\n"), @@ -1889,7 +2467,7 @@ main( int argc, char **argv ) break; case oTempDir: opt.temp_dir=pargs.r.ret_str; break; case oExecPath: - if(set_exec_path(pargs.r.ret_str,0)) + if(set_exec_path(pargs.r.ret_str)) log_error(_("unable to set exec-path to %s\n"),pargs.r.ret_str); else opt.exec_path_set=1; @@ -1901,27 +2479,33 @@ main( int argc, char **argv ) case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break; case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break; case oShowNotation: - opt.list_options|=LIST_SHOW_NOTATION; - opt.verify_options|=VERIFY_SHOW_NOTATION; + deprecated_warning(configname,configlineno,"--show-notation", + "--list-options ","show-notations"); + deprecated_warning(configname,configlineno,"--show-notation", + "--verify-options ","show-notations"); + opt.list_options|=LIST_SHOW_NOTATIONS; + opt.verify_options|=VERIFY_SHOW_NOTATIONS; break; case oNoShowNotation: - opt.list_options&=~LIST_SHOW_NOTATION; - opt.verify_options&=~VERIFY_SHOW_NOTATION; + deprecated_warning(configname,configlineno,"--no-show-notation", + "--list-options ","no-show-notations"); + deprecated_warning(configname,configlineno,"--no-show-notation", + "--verify-options ","no-show-notations"); + opt.list_options&=~LIST_SHOW_NOTATIONS; + opt.verify_options&=~VERIFY_SHOW_NOTATIONS; break; case oUtf8Strings: utf8_strings = 1; break; case oNoUtf8Strings: utf8_strings = 0; break; case oDisableCipherAlgo: { int algo = gcry_cipher_map_name (pargs.r.ret_str); - gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, - &algo, sizeof algo); + gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); } break; case oDisablePubkeyAlgo: { int algo = gcry_pk_map_name (pargs.r.ret_str); - gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, - &algo, sizeof algo ); + gcry_pk_ctl (GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); } break; case oNoSigCache: opt.no_sig_cache = 1; break; @@ -1933,11 +2517,10 @@ main( int argc, char **argv ) case oNoLiteral: opt.no_literal = 1; break; case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; case oHonorHttpProxy: - opt.keyserver_options.honor_http_proxy = 1; + add_to_strlist(&opt.keyserver_options.other,"http-proxy"); deprecated_warning(configname,configlineno, "--honor-http-proxy", - "--keyserver-options ", - "honor-http-proxy"); + "--keyserver-options ","http-proxy"); break; case oFastListMode: opt.fast_list_mode = 1; break; case oFixedListMode: opt.fixed_list_mode = 1; break; @@ -1949,8 +2532,11 @@ main( int argc, char **argv ) case oNoRandomSeedFile: use_random_seed = 0; break; case oAutoKeyRetrieve: case oNoAutoKeyRetrieve: - opt.keyserver_options.auto_key_retrieve= - (pargs.r_opt==oAutoKeyRetrieve); + if(pargs.r_opt==oAutoKeyRetrieve) + opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE; + else + opt.keyserver_options.options&=~KEYSERVER_AUTO_KEY_RETRIEVE; + deprecated_warning(configname,configlineno, pargs.r_opt==oAutoKeyRetrieve?"--auto-key-retrieve": "--no-auto-key-retrieve","--keyserver-options ", @@ -1961,7 +2547,11 @@ main( int argc, char **argv ) case oOverrideSessionKey: opt.override_session_key = pargs.r.ret_str; break; - case oMergeOnly: opt.merge_only = 1; break; + case oMergeOnly: + deprecated_warning(configname,configlineno,"--merge-only", + "--import-options ","merge-only"); + opt.import_options|=IMPORT_MERGE_ONLY; + break; case oAllowSecretKeyImport: /* obsolete */ break; case oTryAllSecrets: opt.try_all_secrets = 1; break; case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break; @@ -1991,30 +2581,95 @@ main( int argc, char **argv ) case oLCctype: opt.lc_ctype = pargs.r.ret_str; break; case oLCmessages: opt.lc_messages = pargs.r.ret_str; break; case oGroup: add_group(pargs.r.ret_str); break; + case oUnGroup: rm_group(pargs.r.ret_str); break; + case oNoGroups: + while(opt.grouplist) + { + struct groupitem *iter=opt.grouplist; + free_strlist(iter->values); + opt.grouplist=opt.grouplist->next; + xfree(iter); + } + break; case oStrict: opt.strict=1; log_set_strict(1); break; case oNoStrict: opt.strict=0; log_set_strict(0); break; - case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break; case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; - case oEnableProgressFilter: opt.enable_progress_filter = 1; break; - case oMultifile: multifile=1; break; + case oMultifile: multifile=1; break; + case oKeyidFormat: + if(ascii_strcasecmp(pargs.r.ret_str,"short")==0) + opt.keyid_format=KF_SHORT; + else if(ascii_strcasecmp(pargs.r.ret_str,"long")==0) + opt.keyid_format=KF_LONG; + else if(ascii_strcasecmp(pargs.r.ret_str,"0xshort")==0) + opt.keyid_format=KF_0xSHORT; + else if(ascii_strcasecmp(pargs.r.ret_str,"0xlong")==0) + opt.keyid_format=KF_0xLONG; + else + log_error("unknown keyid-format `%s'\n",pargs.r.ret_str); + break; + + case oExitOnStatusWriteError: + opt.exit_on_status_write_error = 1; + break; + + case oLimitCardInsertTries: + opt.limit_card_insert_tries = pargs.r.ret_int; + break; + + case oRequireCrossCert: opt.flags.require_cross_cert=1; break; + case oNoRequireCrossCert: opt.flags.require_cross_cert=0; break; + + case oAutoKeyLocate: + if(!parse_auto_key_locate(pargs.r.ret_str)) + { + if(configname) + log_error(_("%s:%d: invalid auto-key-locate list\n"), + configname,configlineno); + else + log_error(_("invalid auto-key-locate list\n")); + } + break; + case oNoAutoKeyLocate: + release_akl(); + break; + + case oAllowMultisigVerification: + opt.allow_multisig_verification = 1; + break; + + case oNoop: break; default : pargs.err = configfp? 1:2; break; - } - } + } + } + if( configfp ) { fclose( configfp ); configfp = NULL; - config_filename = configname; /* Keep a copy of the config - file name. */ - configname = NULL; + /* Remember the first config file name. */ + if (!save_configname) + save_configname = configname; + else + xfree(configname); + configname = NULL; goto next_pass; } - xfree ( configname ); configname = NULL; + xfree( configname ); configname = NULL; if( log_get_errorcount(0) ) g10_exit(2); + + /* The command --gpgconf-list is pretty simple and may be called + directly after the option parsing. */ + if (cmd == aGPGConfList) + { + gpgconf_list (save_configname); + g10_exit (0); + } + xfree (save_configname); + if( nogreeting ) greeting = 0; @@ -2024,20 +2679,23 @@ main( int argc, char **argv ) fprintf(stderr, "%s\n", strusage(15) ); } #ifdef IS_DEVELOPMENT_VERSION - if( !opt.batch ) { - log_info("NOTE: THIS IS A DEVELOPMENT VERSION!\n"); - log_info("It is only intended for test purposes and should NOT be\n"); - log_info("used in a production environment or with production keys!\n"); - } + if( !opt.batch ) + { + const char *s; + + if((s=strusage(20))) + log_info("%s\n",s); + if((s=strusage(21))) + log_info("%s\n",s); + if((s=strusage(22))) + log_info("%s\n",s); + } #endif - log_info ("WARNING: This version of gpg is not very matured and\n"); - log_info ("WARNING: only intended for testing. Please keep using\n"); - log_info ("WARNING: gpg 1.2.x, 1.3.x or 1.4.x for OpenPGP\n"); - - /* FIXME: We should use the lggging to a file only in server mode; - however we have not yet implemetyed that thus we try to get - away with --batch as indication for logging to file required. */ + /* FIXME: We should use logging to a file only in server mode; + however we have not yet implemetyed that. Thus we try to get + away with --batch as indication for logging to file + required. */ if (logfile && opt.batch) { log_set_file (logfile); @@ -2069,12 +2727,21 @@ main( int argc, char **argv ) "--no-literal" ); } + if (opt.set_filesize) log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize"); if( opt.batch ) tty_batchmode( 1 ); gcry_control (GCRYCTL_RESUME_SECMEM_WARN); + + if(require_secmem && !got_secmem) + { + log_info(_("will not run with insecure memory due to %s\n"), + "--require-secmem"); + g10_exit(2); + } + set_debug (debug_level); /* Do these after the switch(), so they can override settings. */ @@ -2107,7 +2774,7 @@ main( int argc, char **argv ) preference, but those have their own error messages). */ - if(openpgp_cipher_test_algo (CIPHER_ALGO_IDEA)) + if (openpgp_cipher_test_algo(CIPHER_ALGO_IDEA)) { log_info(_("encrypting a message in --pgp2 mode requires " "the IDEA cipher\n")); @@ -2119,8 +2786,8 @@ main( int argc, char **argv ) /* This only sets IDEA for symmetric encryption since it is set via select_algo_from_prefs for pk encryption. */ - xfree (def_cipher_string); - def_cipher_string = xstrdup ("idea"); + xfree(def_cipher_string); + def_cipher_string = xstrdup("idea"); } /* PGP2 can't handle the output from the textmode @@ -2137,27 +2804,26 @@ main( int argc, char **argv ) else { opt.force_v4_certs = 0; - opt.sk_comments = 0; opt.escape_from = 1; opt.force_v3_sigs = 1; opt.pgp2_workarounds = 1; opt.ask_sig_expire = 0; opt.ask_cert_expire = 0; - xfree (def_digest_string); - def_digest_string = xstrdup ("md5"); - opt.def_compress_algo = 1; + xfree(def_digest_string); + def_digest_string = xstrdup("md5"); + xfree(s2k_digest_string); + s2k_digest_string = xstrdup("md5"); + opt.compress_algo = COMPRESS_ALGO_ZIP; } } else if(PGP6) { - opt.sk_comments=0; opt.escape_from=1; opt.force_v3_sigs=1; opt.ask_sig_expire=0; } else if(PGP7) { - opt.sk_comments=0; opt.escape_from=1; opt.force_v3_sigs=1; opt.ask_sig_expire=0; @@ -2167,54 +2833,57 @@ main( int argc, char **argv ) opt.escape_from=1; } - /* must do this after dropping setuid, because string_to... - * may try to load an module */ + if( def_cipher_string ) { opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string); if(opt.def_cipher_algo==0 && (ascii_strcasecmp(def_cipher_string,"idea")==0 || ascii_strcasecmp(def_cipher_string,"s1")==0)) idea_cipher_warn(1); - xfree (def_cipher_string); def_cipher_string = NULL; - if( openpgp_cipher_test_algo (opt.def_cipher_algo) ) + xfree(def_cipher_string); def_cipher_string = NULL; + if ( openpgp_cipher_test_algo (opt.def_cipher_algo) ) log_error(_("selected cipher algorithm is invalid\n")); } if( def_digest_string ) { opt.def_digest_algo = gcry_md_map_name (def_digest_string); - xfree (def_digest_string); def_digest_string = NULL; - if( openpgp_md_test_algo (opt.def_digest_algo) ) + xfree(def_digest_string); def_digest_string = NULL; + if ( openpgp_md_test_algo (opt.def_digest_algo) ) log_error(_("selected digest algorithm is invalid\n")); } - if( def_compress_string ) { - opt.def_compress_algo = string_to_compress_algo(def_compress_string); - xfree (def_compress_string); def_compress_string = NULL; - if( check_compress_algo(opt.def_compress_algo) ) - log_error(_("selected compression algorithm is invalid\n")); + if( compress_algo_string ) { + opt.compress_algo = string_to_compress_algo(compress_algo_string); + xfree(compress_algo_string); compress_algo_string = NULL; + if( check_compress_algo(opt.compress_algo) ) + log_error(_("selected compression algorithm is invalid\n")); } if( cert_digest_string ) { opt.cert_digest_algo = gcry_md_map_name (cert_digest_string); - xfree (cert_digest_string); cert_digest_string = NULL; - if( openpgp_md_test_algo(opt.cert_digest_algo) ) - log_error(_("selected certification digest algorithm is invalid\n")); + xfree(cert_digest_string); cert_digest_string = NULL; + if (openpgp_md_test_algo(opt.cert_digest_algo)) + log_error(_("selected certification digest algorithm is invalid\n")); } if( s2k_cipher_string ) { opt.s2k_cipher_algo = gcry_cipher_map_name (s2k_cipher_string); - xfree (s2k_cipher_string); s2k_cipher_string = NULL; - if( openpgp_cipher_test_algo (opt.s2k_cipher_algo) ) - log_error(_("selected cipher algorithm is invalid\n")); + xfree(s2k_cipher_string); s2k_cipher_string = NULL; + if (openpgp_cipher_test_algo (opt.s2k_cipher_algo)) + log_error(_("selected cipher algorithm is invalid\n")); } if( s2k_digest_string ) { opt.s2k_digest_algo = gcry_md_map_name (s2k_digest_string); - xfree (s2k_digest_string); s2k_digest_string = NULL; - if( openpgp_md_test_algo (opt.s2k_digest_algo) ) - log_error(_("selected digest algorithm is invalid\n")); + xfree(s2k_digest_string); s2k_digest_string = NULL; + if (openpgp_md_test_algo(opt.s2k_digest_algo)) + log_error(_("selected digest algorithm is invalid\n")); } if( opt.completes_needed < 1 ) - log_error(_("completes-needed must be greater than 0\n")); + log_error(_("completes-needed must be greater than 0\n")); if( opt.marginals_needed < 2 ) - log_error(_("marginals-needed must be greater than 1\n")); + log_error(_("marginals-needed must be greater than 1\n")); if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 ) - log_error(_("max-cert-depth must be in range 1 to 255\n")); + log_error(_("max-cert-depth must be in the range from 1 to 255\n")); + if(opt.def_cert_level<0 || opt.def_cert_level>3) + log_error(_("invalid default-cert-level; must be 0, 1, 2, or 3\n")); + if( opt.min_cert_level < 1 || opt.min_cert_level > 3 ) + log_error(_("invalid min-cert-level; must be 1, 2, or 3\n")); switch( opt.s2k_mode ) { case 0: log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n")); @@ -2224,16 +2893,14 @@ main( int argc, char **argv ) log_error(_("invalid S2K mode; must be 0, 1 or 3\n")); } - if(opt.def_cert_check_level<0 || opt.def_cert_check_level>3) - log_error(_("invalid default-check-level; must be 0, 1, 2, or 3\n")); - /* This isn't actually needed, but does serve to error out if the string is invalid. */ if(opt.def_preference_list && keygen_set_std_prefs(opt.def_preference_list,0)) log_error(_("invalid default preferences\n")); - /* We provide defaults for the personal digest list */ + /* We provide defaults for the personal digest list. This is + SHA-1. */ if(!pers_digest_list) pers_digest_list="h2"; @@ -2253,7 +2920,7 @@ main( int argc, char **argv ) if(multifile) { char *cmdname; - + switch(cmd) { case aSign: @@ -2268,6 +2935,9 @@ main( int argc, char **argv ) case aSym: cmdname="--symmetric"; break; + case aEncrSym: + cmdname="--symmetric --encrypt"; + break; case aStore: cmdname="--store"; break; @@ -2283,6 +2953,9 @@ main( int argc, char **argv ) if( log_get_errorcount(0) ) g10_exit(2); + if(opt.compress_level==0) + opt.compress_algo=COMPRESS_ALGO_NONE; + /* Check our chosen algorithms against the list of legal algorithms. */ @@ -2291,48 +2964,48 @@ main( int argc, char **argv ) const char *badalg=NULL; preftype_t badtype=PREFTYPE_NONE; - if (opt.def_cipher_algo - && !algo_available (PREFTYPE_SYM,opt.def_cipher_algo,NULL)) + if(opt.def_cipher_algo + && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL)) { badalg = gcry_cipher_algo_name (opt.def_cipher_algo); badtype = PREFTYPE_SYM; } - else if (opt.def_digest_algo - && !algo_available (PREFTYPE_HASH,opt.def_digest_algo,NULL)) + else if(opt.def_digest_algo + && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL)) { badalg = gcry_md_algo_name (opt.def_digest_algo); badtype = PREFTYPE_HASH; } - else if (opt.cert_digest_algo - && !algo_available (PREFTYPE_HASH,opt.cert_digest_algo,NULL)) + else if(opt.cert_digest_algo + && !algo_available(PREFTYPE_HASH,opt.cert_digest_algo,NULL)) { badalg = gcry_md_algo_name (opt.cert_digest_algo); badtype = PREFTYPE_HASH; } - else if (opt.def_compress_algo!=-1 - && !algo_available (PREFTYPE_ZIP,opt.def_compress_algo,NULL)) + else if(opt.compress_algo!=-1 + && !algo_available(PREFTYPE_ZIP,opt.compress_algo,NULL)) { - badalg = compress_algo_to_string (opt.def_compress_algo); + badalg = compress_algo_to_string(opt.compress_algo); badtype = PREFTYPE_ZIP; } - if (badalg) + if(badalg) { switch(badtype) { case PREFTYPE_SYM: - log_info(_("you may not use cipher algorithm \"%s\" " - "while in %s mode\n"), + log_info(_("you may not use cipher algorithm `%s'" + " while in %s mode\n"), badalg,compliance_option_string()); break; case PREFTYPE_HASH: - log_info(_("you may not use digest algorithm \"%s\" " - "while in %s mode\n"), + log_info(_("you may not use digest algorithm `%s'" + " while in %s mode\n"), badalg,compliance_option_string()); break; case PREFTYPE_ZIP: - log_info(_("you may not use compression algorithm \"%s\" " - "while in %s mode\n"), + log_info(_("you may not use compression algorithm `%s'" + " while in %s mode\n"), badalg,compliance_option_string()); break; default: @@ -2343,20 +3016,33 @@ main( int argc, char **argv ) } } - /* set the random seed file */ + /* Set the random seed file. */ if( use_random_seed ) { char *p = make_filename(opt.homedir, "random_seed", NULL ); + set_random_seed_file(p); gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); - xfree (p); + if (!access (p, F_OK)) + register_secured_file (p); + xfree(p); } if( !cmd && opt.fingerprint && !with_fpr ) { set_cmd( &cmd, aListKeys); } - /* Compression algorithm 0 means no compression at all */ - if( opt.def_compress_algo == 0) - opt.compress = 0; + if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */ + if( cmd == aKModeC ) { + opt.fingerprint = 1; + cmd = aKMode; + } + opt.list_sigs = 0; + if( opt.verbose > 2 ) + opt.check_sigs++; + if( opt.verbose > 1 ) + opt.list_sigs++; + + opt.verbose = opt.verbose > 1; + } /* kludge to let -sat generate a clear text signature */ if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign ) @@ -2365,22 +3051,29 @@ main( int argc, char **argv ) if( opt.verbose > 1 ) set_packet_list_mode(1); - /* Add the keyrings, but not for some special commands. Also - avoid adding the secret keyring for a couple of commands to - avoid unneeded access in case the secrings are stored on a - floppy */ - if( cmd != aDeArmor && cmd != aEnArmor && cmd != aGPGConfList ) + /* Add the keyrings, but not for some special commands and not in + case of "-kvv userid keyring". Also avoid adding the secret + keyring for a couple of commands to avoid unneeded access in + case the secrings are stored on a floppy. + + We always need to add the keyrings if we are running under + SELinux, this is so that the rings are added to the list of + secured files. */ + if( ALWAYS_ADD_KEYRINGS + || (cmd != aDeArmor && cmd != aEnArmor + && !(cmd == aKMode && argc == 2 )) ) { - if (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys - && cmd != aVerify && cmd != aSym) + if (ALWAYS_ADD_KEYRINGS + || (cmd != aCheckKeys && cmd != aListSigs && cmd != aListKeys + && cmd != aVerify && cmd != aSym)) { if (!sec_nrings || default_keyring) /* add default secret rings */ - keydb_add_resource ("secring" EXTSEP_S "gpg", 0, 1); + keydb_add_resource ("secring" EXTSEP_S "gpg", 4, 1); for (sl = sec_nrings; sl; sl = sl->next) keydb_add_resource ( sl->d, 0, 1 ); } if( !nrings || default_keyring ) /* add default ring */ - keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0); + keydb_add_resource ("pubring" EXTSEP_S "gpg", 4, 0); for(sl = nrings; sl; sl = sl->next ) keydb_add_resource ( sl->d, sl->flags, 0 ); } @@ -2401,20 +3094,17 @@ main( int argc, char **argv ) case aDeArmor: case aEnArmor: case aFixTrustDB: - case aCardStatus: - case aCardEdit: - case aChangePIN: - case aGPGConfList: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break; default: rc = setup_trustdb(1, trustdb_name ); break; } if( rc ) - log_error(_("failed to initialize the TrustDB: %s\n"), gpg_strerror (rc)); + log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc)); - switch (cmd) { + switch (cmd) + { case aStore: case aSym: case aSign: @@ -2426,22 +3116,23 @@ main( int argc, char **argv ) break; default: break; - } + } - switch( cmd ) { + switch( cmd ) + { case aStore: /* only store the file */ if( argc > 1 ) wrong_args(_("--store [filename]")); if( (rc = encode_store(fname)) ) - log_error ("\b%s: store failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); + log_error ("storing `%s' failed: %s\n", + print_fname_stdin(fname),g10_errstr(rc) ); break; case aSym: /* encrypt the given file only with the symmetric cipher */ if( argc > 1 ) wrong_args(_("--symmetric [filename]")); if( (rc = encode_symmetric(fname)) ) - log_error ("\b%s: symmetric encryption failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); + log_error (_("symmetric encryption of `%s' failed: %s\n"), + print_fname_stdin(fname),g10_errstr(rc) ); break; case aEncr: /* encrypt the given file */ @@ -2449,12 +3140,33 @@ main( int argc, char **argv ) encode_crypt_files(argc, argv, remusr); else { - if( argc > 1 ) - wrong_args(_("--encrypt [filename]")); - if( (rc = encode_crypt(fname,remusr)) ) - log_error("%s: encryption failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); - } + if( argc > 1 ) + wrong_args(_("--encrypt [filename]")); + if( (rc = encode_crypt(fname,remusr,0)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); + } + break; + + case aEncrSym: + /* This works with PGP 8 in the sense that it acts just like a + symmetric message. It doesn't work at all with 2 or 6. It + might work with 7, but alas, I don't have a copy to test + with right now. */ + if( argc > 1 ) + wrong_args(_("--symmetric --encrypt [filename]")); + else if(opt.s2k_mode==0) + log_error(_("you cannot use --symmetric --encrypt" + " with --s2k-mode 0\n")); + else if(PGP2 || PGP6 || PGP7 || RFC1991) + log_error(_("you cannot use --symmetric --encrypt" + " while in %s mode\n"),compliance_option_string()); + else + { + if( (rc = encode_crypt(fname,remusr,1)) ) + log_error("%s: encryption failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); + } break; case aSign: /* sign the given file */ @@ -2467,12 +3179,12 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("--sign [filename]")); if( argc ) { - sl = xcalloc (1, sizeof *sl + strlen(fname)); + sl = xmalloc_clear( sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } } if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) - log_error("signing failed: %s\n", gpg_strerror (rc) ); + log_error("signing failed: %s\n", g10_errstr(rc) ); free_strlist(sl); break; @@ -2480,23 +3192,49 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("--sign --encrypt [filename]")); if( argc ) { - sl = xcalloc (1, sizeof *sl + strlen(fname)); + sl = xmalloc_clear( sizeof *sl + strlen(fname)); strcpy(sl->d, fname); } else sl = NULL; if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) - log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), gpg_strerror (rc) ); + log_error("%s: sign+encrypt failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); free_strlist(sl); break; + case aSignEncrSym: /* sign and encrypt the given file */ + if( argc > 1 ) + wrong_args(_("--symmetric --sign --encrypt [filename]")); + else if(opt.s2k_mode==0) + log_error(_("you cannot use --symmetric --sign --encrypt" + " with --s2k-mode 0\n")); + else if(PGP2 || PGP6 || PGP7 || RFC1991) + log_error(_("you cannot use --symmetric --sign --encrypt" + " while in %s mode\n"),compliance_option_string()); + else + { + if( argc ) + { + sl = xmalloc_clear( sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + else + sl = NULL; + if( (rc = sign_file(sl, detached_sig, locusr, 2, remusr, NULL)) ) + log_error("%s: symmetric+sign+encrypt failed: %s\n", + print_fname_stdin(fname), g10_errstr(rc) ); + free_strlist(sl); + } + break; + case aSignSym: /* sign and conventionally encrypt the given file */ if (argc > 1) wrong_args(_("--sign --symmetric [filename]")); rc = sign_symencrypt_file (fname, locusr); if (rc) log_error("%s: sign+symmetric failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); + print_fname_stdin(fname), g10_errstr(rc) ); break; case aClearsign: /* make a clearsig */ @@ -2504,65 +3242,58 @@ main( int argc, char **argv ) wrong_args(_("--clearsign [filename]")); if( (rc = clearsign_file(fname, locusr, NULL)) ) log_error("%s: clearsign failed: %s\n", - print_fname_stdin(fname), gpg_strerror (rc) ); + print_fname_stdin(fname), g10_errstr(rc) ); break; case aVerify: - if(multifile) + if(multifile) { if( (rc = verify_files( argc, argv ) )) - log_error("verify files failed: %s\n", gpg_strerror (rc) ); + log_error("verify files failed: %s\n", g10_errstr(rc) ); + } + else + { + if( (rc = verify_signatures( argc, argv ) )) + log_error("verify signatures failed: %s\n", g10_errstr(rc) ); } - else - { - if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); - } break; case aDecrypt: if(multifile) decrypt_messages(argc, argv); else - { - if( argc > 1 ) - wrong_args(_("--decrypt [filename]")); - if( (rc = decrypt_message( fname ) )) - log_error("decrypt_message failed: %s\n", gpg_strerror (rc) ); - } + { + if( argc > 1 ) + wrong_args(_("--decrypt [filename]")); + if( (rc = decrypt_message( fname ) )) + log_error("decrypt_message failed: %s\n", g10_errstr(rc) ); + } break; - - case aSignKey: /* sign the key given as argument */ + + case aSignKey: if( argc != 1 ) - wrong_args(_("--sign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 1 ); - xfree (username); - break; - + wrong_args(_("--sign-key user-id")); + /* fall through */ case aLSignKey: if( argc != 1 ) - wrong_args(_("--lsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 2 ); - xfree (username); - break; + wrong_args(_("--lsign-key user-id")); + /* fall through */ - case aNRSignKey: - if( argc != 1 ) - wrong_args(_("--nrsign-key user-id")); - username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 3 ); - xfree (username); - break; + sl=NULL; - case aNRLSignKey: - if( argc != 1 ) - wrong_args(_("--nrlsign-key user-id")); + if(cmd==aSignKey) + append_to_strlist(&sl,"sign"); + else if(cmd==aLSignKey) + append_to_strlist(&sl,"lsign"); + else + BUG(); + + append_to_strlist( &sl, "save" ); username = make_username( fname ); - keyedit_menu(fname, locusr, NULL, 4 ); - xfree (username); - break; + keyedit_menu(fname, locusr, sl, 0, 0 ); + xfree(username); + free_strlist(sl); + break; case aEditKey: /* Edit a key signature */ if( !argc ) @@ -2572,12 +3303,12 @@ main( int argc, char **argv ) sl = NULL; for( argc--, argv++ ; argc; argc--, argv++ ) append_to_strlist( &sl, *argv ); - keyedit_menu( username, locusr, sl, 0 ); + keyedit_menu( username, locusr, sl, 0, 1 ); free_strlist(sl); } else - keyedit_menu(username, locusr, NULL, 0 ); - xfree (username); + keyedit_menu(username, locusr, NULL, 0, 1 ); + xfree(username); break; case aDeleteKeys: @@ -2612,27 +3343,54 @@ main( int argc, char **argv ) free_strlist(sl); break; + case aKMode: /* list keyring -- NOTE: This will be removed soon */ + if( argc < 2 ) { /* -kv [userid] */ + sl = NULL; + if (argc && **argv) + add_to_strlist2( &sl, *argv, utf8_strings ); + public_key_list( sl ); + free_strlist(sl); + } + else if( argc == 2 ) { /* -kv userid keyring */ + if( access( argv[1], R_OK ) ) { + log_error(_("can't open `%s': %s\n"), + print_fname_stdin(argv[1]), strerror(errno)); + } + else { + /* add keyring (default keyrings are not registered in this + * special case */ + keydb_add_resource( argv[1], 0, 0 ); + sl = NULL; + if (**argv) + add_to_strlist2( &sl, *argv, utf8_strings ); + public_key_list( sl ); + free_strlist(sl); + } + } + else + wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") ); + break; + case aKeygen: /* generate a key */ if( opt.batch ) { if( argc > 1 ) wrong_args("--gen-key [parameterfile]"); - generate_keypair( argc? *argv : NULL, NULL ); + generate_keypair( argc? *argv : NULL, NULL, NULL ); } else { if( argc ) wrong_args("--gen-key"); - generate_keypair(NULL, NULL); + generate_keypair(NULL, NULL, NULL); } break; case aFastImport: - opt.import_options |= IMPORT_FAST_IMPORT; + opt.import_options |= IMPORT_FAST; case aImport: import_keys( argc? argv:NULL, argc, NULL, opt.import_options ); break; case aExport: - case aExportAll: case aSendKeys: case aRecvKeys: sl = NULL; @@ -2647,11 +3405,11 @@ main( int argc, char **argv ) if(rc) { if(cmd==aSendKeys) - log_error(_("keyserver send failed: %s\n"),gpg_strerror (rc)); + log_error(_("keyserver send failed: %s\n"),g10_errstr(rc)); else if(cmd==aRecvKeys) - log_error(_("keyserver receive failed: %s\n"),gpg_strerror (rc)); + log_error(_("keyserver receive failed: %s\n"),g10_errstr(rc)); else - log_error(_("key export failed: %s\n"),gpg_strerror (rc)); + log_error(_("key export failed: %s\n"),g10_errstr(rc)); } free_strlist(sl); break; @@ -2659,20 +3417,10 @@ main( int argc, char **argv ) case aSearchKeys: sl = NULL; for( ; argc; argc--, argv++ ) - { - if (utf8_strings) - sl = append_to_strlist ( &sl, *argv ); - else - { - char *p = native_to_utf8 ( *argv ); - sl = append_to_strlist( &sl, p ); - xfree( p ); - } - } - + append_to_strlist2( &sl, *argv, utf8_strings ); rc=keyserver_search( sl ); if(rc) - log_error(_("keyserver search failed: %s\n"),gpg_strerror (rc)); + log_error(_("keyserver search failed: %s\n"),g10_errstr(rc)); free_strlist(sl); break; @@ -2682,7 +3430,17 @@ main( int argc, char **argv ) add_to_strlist2( &sl, *argv, utf8_strings ); rc=keyserver_refresh(sl); if(rc) - log_error(_("keyserver refresh failed: %s\n"),gpg_strerror (rc)); + log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc)); + free_strlist(sl); + break; + + case aFetchKeys: + sl = NULL; + for( ; argc; argc--, argv++ ) + add_to_strlist2( &sl, *argv, utf8_strings ); + rc=keyserver_fetch(sl); + if(rc) + log_error("key fetch failed: %s\n",g10_errstr(rc)); free_strlist(sl); break; @@ -2707,15 +3465,15 @@ main( int argc, char **argv ) wrong_args("--gen-revoke user-id"); username = make_username(*argv); gen_revoke( username ); - xfree ( username ); + xfree( username ); break; case aDesigRevoke: if( argc != 1 ) wrong_args("--desig-revoke user-id"); username = make_username(*argv); - gen_desig_revoke( username ); - xfree ( username ); + gen_desig_revoke( username, locusr ); + xfree( username ); break; case aDeArmor: @@ -2723,7 +3481,7 @@ main( int argc, char **argv ) wrong_args("--dearmor [file]"); rc = dearmor_file( argc? *argv: NULL ); if( rc ) - log_error(_("dearmoring failed: %s\n"), gpg_strerror (rc)); + log_error(_("dearmoring failed: %s\n"), g10_errstr(rc)); break; case aEnArmor: @@ -2731,12 +3489,12 @@ main( int argc, char **argv ) wrong_args("--enarmor [file]"); rc = enarmor_file( argc? *argv: NULL ); if( rc ) - log_error(_("enarmoring failed: %s\n"), gpg_strerror (rc)); + log_error(_("enarmoring failed: %s\n"), g10_errstr(rc)); break; case aPrimegen: -#if 0 /*FIXME-XXX*/ +#if 0 /*FIXME*/ { int mode = argc < 2 ? 0 : atoi(*argv); if( mode == 1 && argc == 2 ) { @@ -2748,7 +3506,7 @@ main( int argc, char **argv ) atoi(argv[2]), NULL,NULL ), 1); } else if( mode == 3 && argc == 3 ) { - gcry_mpi_t *factors; + MPI *factors; mpi_print( stdout, generate_elg_prime( 1, atoi(argv[1]), atoi(argv[2]), NULL,&factors ), 1); @@ -2756,7 +3514,7 @@ main( int argc, char **argv ) mpi_print( stdout, factors[0], 1 ); /* print q */ } else if( mode == 4 && argc == 3 ) { - gcry_mpi_t g = mpi_alloc(1); + MPI g = mpi_alloc(1); mpi_print( stdout, generate_elg_prime( 0, atoi(argv[1]), atoi(argv[2]), g, NULL ), 1); @@ -2769,6 +3527,7 @@ main( int argc, char **argv ) putchar('\n'); } #endif + wrong_args("--gen-prime not yet supported "); break; case aGenRandom: @@ -2803,7 +3562,7 @@ main( int argc, char **argv ) } else { fwrite( p, n, 1, stdout ); } - xfree (p); + xfree(p); if( !endless ) count -= n; } @@ -2874,7 +3633,7 @@ main( int argc, char **argv ) for( ; argc; argc--, argv++ ) { username = make_username( *argv ); list_trust_path( username ); - xfree (username); + xfree(username); } break; @@ -2890,84 +3649,48 @@ main( int argc, char **argv ) import_ownertrust( argc? *argv:NULL ); break; - case aPipeMode: - if ( argc ) - wrong_args ("--pipemode"); - run_in_pipemode (); - break; - case aRebuildKeydbCaches: if (argc) wrong_args ("--rebuild-keydb-caches"); - keydb_rebuild_caches (); + keydb_rebuild_caches (1); break; - case aCardStatus: - if (argc) - wrong_args ("--card-status"); - card_status (stdout, NULL, 0); - break; +#ifdef ENABLE_CARD_SUPPORT + case aCardStatus: + if (argc) + wrong_args ("--card-status"); + card_status (stdout, NULL, 0); + break; - case aCardEdit: - if (argc) - { - sl = NULL; - for (argc--, argv++ ; argc; argc--, argv++) - append_to_strlist (&sl, *argv); - card_edit (sl); - free_strlist (sl); + case aCardEdit: + if (argc) { + sl = NULL; + for (argc--, argv++ ; argc; argc--, argv++) + append_to_strlist (&sl, *argv); + card_edit (sl); + free_strlist (sl); } - else - card_edit (NULL); - break; + else + card_edit (NULL); + break; - case aChangePIN: - if (!argc) - change_pin (0,1); - else if (argc == 1) - change_pin ( atoi (*argv), 1); - else + case aChangePIN: + if (!argc) + change_pin (0,1); + else if (argc == 1) + change_pin (atoi (*argv),1); + else wrong_args ("--change-pin [no]"); - break; - - case aGPGConfList: - { /* List options and default values in the GPG Conf format. */ - - /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ - /* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING - FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */ -#define GC_OPT_FLAG_NONE 0UL - /* The RUNTIME flag for an option indicates that the option can be - changed at runtime. */ -#define GC_OPT_FLAG_RUNTIME (1UL << 3) - /* The DEFAULT flag for an option indicates that the option has a - default value. */ -#define GC_OPT_FLAG_DEFAULT (1UL << 4) - /* The DEF_DESC flag for an option indicates that the option has a - default, which is described by the value of the default field. */ -#define GC_OPT_FLAG_DEF_DESC (1UL << 5) - /* The NO_ARG_DESC flag for an option indicates that the argument has - a default, which is described by the value of the ARGDEF field. */ -#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6) - - if (!config_filename) - config_filename = make_filename (opt.homedir, "gpg.conf", NULL); - - printf ("gpgconf-gpg.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, config_filename); - - printf ("verbose:%lu:\n" - "quiet:%lu:\n" - "debug-level:%lu:\"none:\n" - "log-file:%lu:\n", - GC_OPT_FLAG_NONE, - GC_OPT_FLAG_NONE, - GC_OPT_FLAG_DEFAULT, - GC_OPT_FLAG_NONE ); - printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE); + break; +#endif /* ENABLE_CARD_SUPPORT*/ - } - break; + case aListConfig: + { + char *str=collapse_args(argc,argv); + list_config(str); + xfree(str); + } + break; case aListPackets: opt.list_packets=2; @@ -2979,7 +3702,14 @@ main( int argc, char **argv ) && isatty( fileno(stdout) ) && isatty( fileno(stderr) ) ) log_info(_("Go ahead and type your message ...\n")); - if( !(a = iobuf_open(fname)) ) + a = iobuf_open(fname); + if (a && is_secured_file (iobuf_get_fd (a))) + { + iobuf_close (a); + a = NULL; + errno = EPERM; + } + if( !a ) log_error(_("can't open `%s'\n"), print_fname_stdin(fname)); else { @@ -2995,11 +3725,11 @@ main( int argc, char **argv ) } rc = proc_packets(NULL, a ); if( rc ) - log_error("processing message failed: %s\n", gpg_strerror (rc) ); + log_error("processing message failed: %s\n", g10_errstr(rc) ); iobuf_close(a); } break; - } + } /* cleanup */ FREE_STRLIST(remusr); @@ -3008,6 +3738,7 @@ main( int argc, char **argv ) return 8; /*NEVER REACHED*/ } + /* Note: This function is used by signal handlers!. */ static void emergency_cleanup (void) @@ -3019,18 +3750,23 @@ emergency_cleanup (void) void g10_exit( int rc ) { +#ifdef ENABLE_CARD_SUPPORT + card_close (); +#endif + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); - if (opt.debug & DBG_MEMSTAT_VALUE) + if ( (opt.debug & DBG_MEMSTAT_VALUE) ) { - gcry_control( GCRYCTL_DUMP_MEMORY_STATS ); - gcry_control( GCRYCTL_DUMP_RANDOM_STATS ); + gcry_control (GCRYCTL_DUMP_MEMORY_STATS); + gcry_control (GCRYCTL_DUMP_RANDOM_STATS); } if (opt.debug) gcry_control (GCRYCTL_DUMP_SECMEM_STATS ); + emergency_cleanup (); - rc = rc? rc : log_get_errorcount(0)? 2 : - g10_errors_seen? 1 : 0; - exit (rc ); + + rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0; + exit (rc); } @@ -3038,7 +3774,7 @@ g10_exit( int rc ) display, but there are a few other similar assumptions in the display code. */ static void -print_hex( MD_HANDLE md, int algo, const char *fname ) +print_hex( gcry_md_hd_t md, int algo, const char *fname ) { int i,n,count,indent=0; const byte *p; @@ -3064,7 +3800,7 @@ print_hex( MD_HANDLE md, int algo, const char *fname ) p = gcry_md_read (md, algo); n = gcry_md_get_algo_dlen (algo); - count+=printf("%02X",*p++); + count += printf ("%02X",*p++); for(i=1;i<n;i++,p++) { @@ -3118,13 +3854,13 @@ print_hex( MD_HANDLE md, int algo, const char *fname ) } static void -print_hashline( MD_HANDLE md, int algo, const char *fname ) +print_hashline( gcry_md_hd_t md, int algo, const char *fname ) { int i, n; const byte *p; if ( fname ) { - for (p = (const unsigned char *)fname; *p; p++ ) { + for (p = fname; *p; p++ ) { if ( *p <= 32 || *p > 127 || *p == ':' || *p == '%' ) printf("%%%02X", *p ); else @@ -3133,7 +3869,7 @@ print_hashline( MD_HANDLE md, int algo, const char *fname ) } putchar(':'); printf("%d:", algo ); - p = gcry_md_read (md, algo ); + p = gcry_md_read (md, algo); n = gcry_md_get_algo_dlen (algo); for(i=0; i < n ; i++, p++ ) printf("%02X", *p ); @@ -3147,7 +3883,7 @@ print_mds( const char *fname, int algo ) FILE *fp; char buf[1024]; size_t n; - MD_HANDLE md; + gcry_md_hd_t md; if( !fname ) { fp = stdin; @@ -3157,25 +3893,31 @@ print_mds( const char *fname, int algo ) } else { fp = fopen( fname, "rb" ); + if (fp && is_secured_file (fileno (fp))) + { + fclose (fp); + fp = NULL; + errno = EPERM; + } } if( !fp ) { log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) ); return; } - gcry_md_open (&md, 0, 0 ); + gcry_md_open (&md, 0, 0); if( algo ) - gcry_md_enable ( md, algo ); + gcry_md_enable (md, algo); else { - gcry_md_enable (md, GCRY_MD_MD5 ); - gcry_md_enable (md, GCRY_MD_SHA1 ); - gcry_md_enable (md, GCRY_MD_RMD160 ); + gcry_md_enable (md, GCRY_MD_MD5); + gcry_md_enable (md, GCRY_MD_SHA1); + gcry_md_enable (md, GCRY_MD_RMD160); #ifdef USE_SHA256 - gcry_md_enable (md, GCRY_MD_SHA256 ); + gcry_md_enable (md, GCRY_MD_SHA256); #endif #ifdef USE_SHA512 - gcry_md_enable (md, GCRY_MD_SHA384 ); - gcry_md_enable (md, GCRY_MD_SHA512 ); + gcry_md_enable (md, GCRY_MD_SHA384); + gcry_md_enable (md, GCRY_MD_SHA512); #endif } @@ -3218,7 +3960,7 @@ print_mds( const char *fname, int algo ) } } } - gcry_md_close (md); + gcry_md_close(md); if( fp != stdin ) fclose(fp); @@ -3233,71 +3975,28 @@ print_mds( const char *fname, int algo ) static void add_notation_data( const char *string, int which ) { - const char *s; - STRLIST sl,*notation_data; - int critical=0; - int highbit=0; - int saw_at=0; - - if(which) - notation_data=&opt.cert_notation_data; - else - notation_data=&opt.sig_notation_data; - - if( *string == '!' ) { - critical = 1; - string++; - } - - /* If and when the IETF assigns some official name tags, we'll - have to add them here. */ - - for( s=string ; *s != '='; s++ ) - { - if( *s=='@') - saw_at=1; - - if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) ) - { - log_error(_("a notation name must have only printable characters " - "or spaces, and end with an '='\n") ); - return; - } - } + struct notation *notation; - if(!saw_at && !opt.expert) - { - log_error( - _("a user notation name must contain the '@' character\n")); - return; - } - - /* we only support printable text - therefore we enforce the use - * of only printable characters (an empty value is valid) */ - for( s++; *s ; s++ ) { - if( *s & 0x80 ) - highbit = 1; - else if( iscntrl(*s) ) { - log_error(_("a notation value must not use " - "any control characters\n") ); - return; + notation=string_to_notation(string,utf8_strings); + if(notation) + { + if(which) + { + notation->next=opt.cert_notations; + opt.cert_notations=notation; + } + else + { + notation->next=opt.sig_notations; + opt.sig_notations=notation; } } - - if( highbit ) /* must use UTF8 encoding */ - sl = add_to_strlist2( notation_data, string, utf8_strings ); - else - sl = add_to_strlist( notation_data, string ); - - if( critical ) - sl->flags |= 1; } - static void add_policy_url( const char *string, int which ) { - int i,critical=0; + unsigned int i,critical=0; STRLIST sl; if(*string=='!') @@ -3307,7 +4006,7 @@ add_policy_url( const char *string, int which ) } for(i=0;i<strlen(string);i++) - if(string[i]&0x80 || iscntrl(string[i])) + if( !isascii (string[i]) || iscntrl(string[i])) break; if(i==0 || i<strlen(string)) @@ -3327,11 +4026,10 @@ add_policy_url( const char *string, int which ) sl->flags |= 1; } - static void add_keyserver_url( const char *string, int which ) { - int i,critical=0; + unsigned int i,critical=0; STRLIST sl; if(*string=='!') @@ -3341,7 +4039,7 @@ add_keyserver_url( const char *string, int which ) } for(i=0;i<strlen(string);i++) - if(string[i]&0x80 || iscntrl(string[i])) + if( !isascii (string[i]) || iscntrl(string[i])) break; if(i==0 || i<strlen(string)) @@ -3349,8 +4047,7 @@ add_keyserver_url( const char *string, int which ) if(which) BUG(); else - log_error(_("the given signature preferred" - " keyserver URL is invalid\n")); + log_error(_("the given preferred keyserver URL is invalid\n")); } if(which) @@ -3361,4 +4058,3 @@ add_keyserver_url( const char *string, int which ) if(critical) sl->flags |= 1; } - diff --git a/g10/gpg.h b/g10/gpg.h index 42c9cc662..8ef46fdca 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -1,5 +1,5 @@ /* gpg.h - top level include file for gpg etc. - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -32,9 +32,70 @@ #define map_assuan_err(a) \ map_assuan_err_with_source (GPG_ERR_SOURCE_DEFAULT, (a)) #include <gpg-error.h> +#include <gcrypt.h> -/* FIXME: merge this with global.h */ +/* Number of bits we accept when reading or writing MPIs. */ +#define MAX_EXTERN_MPI_BITS 16384 + +/* The maximum length of a binary fingerprints. */ +#define MAX_FINGERPRINT_LEN 20 + + +/* Forward declarations. */ +typedef struct kbnode_struct *KBNODE; +typedef struct keydb_search_desc KEYDB_SEARCH_DESC; + + + +/* Simple wrappers. */ +#define g10_errstr(a) gpg_strerror ((a)) + + +/* Mapping of the old erro codes to the gpg-error ones. Fixme: This + is just a temporary solution: We need to do all these gpg_error() + calls in the code. */ +#define G10ERR_BAD_KEY GPG_ERR_BAD_KEY +#define G10ERR_BAD_PASS GPG_ERR_BAD_PASS +#define G10ERR_BAD_PUBKEY GPG_ERR_BAD_PUBKEY +#define G10ERR_BAD_SIGN GPG_ERR_BAD_SIGNATURE +#define G10ERR_BAD_URI GPG_ERR_BAD_URI +#define G10ERR_CHECKSUM GPG_ERR_CHECKSUM +#define G10ERR_CIPHER_ALGO GPG_ERR_CIPHER_ALGO +#define G10ERR_CLOSE_FILE GPG_ERR_CLOSE_FILE +#define G10ERR_COMPR_ALGO GPG_ERR_COMPR_ALGO +#define G10ERR_CREATE_FILE GPG_ERR_CREATE_FILE +#define G10ERR_DIGEST_ALGO GPG_ERR_DIGEST_ALGO +#define G10ERR_FILE_EXISTS GPG_ERR_EEXIST +#define G10ERR_GENERAL GPG_ERR_GENERAL +#define G10ERR_INV_ARG GPG_ERR_INV_ARG +#define G10ERR_INV_KEYRING GPG_ERR_INV_KEYRING +#define G10ERR_INV_USER_ID GPG_ERR_INV_USER_ID +#define G10ERR_INVALID_ARMOR GPG_ERR_INV_ARMOR +#define G10ERR_INVALID_PACKET GPG_ERR_INV_PACKET +#define G10ERR_KEYRING_OPEN GPG_ERR_KEYRING_OPEN +#define G10ERR_KEYSERVER GPG_ERR_KEYSERVER +#define G10ERR_NO_DATA GPG_ERR_NO_DATA +#define G10ERR_NO_PUBKEY GPG_ERR_NO_PUBKEY +#define G10ERR_NO_SECKEY GPG_ERR_NO_SECKEY +#define G10ERR_NO_USER_ID GPG_ERR_NO_USER_ID +#define G10ERR_NOT_PROCESSED GPG_ERR_NOT_PROCESSED +#define G10ERR_OPEN_FILE GPG_ERR_OPEN_FILE +#define G10ERR_PASSPHRASE GPG_ERR_PASSPHRASE +#define G10ERR_PUBKEY_ALGO GPG_ERR_PUBKEY_ALGO +#define G10ERR_READ_FILE GPG_ERR_READ_FILE +#define G10ERR_RENAME_FILE GPG_ERR_RENAME_FILE +#define G10ERR_RESOURCE_LIMIT GPG_ERR_RESOURCE_LIMIT +#define G10ERR_SIG_CLASS GPG_ERR_SIG_CLASS +#define G10ERR_TIME_CONFLICT GPG_ERR_TIME_CONFLICT +#define G10ERR_TRUSTDB GPG_ERR_TRUSTDB +#define G10ERR_UNEXPECTED GPG_ERR_UNEXPECTED +#define G10ERR_UNKNOWN_PACKET GPG_ERR_UNKNOWN_PACKET +#define G10ERR_UNSUPPORTED GPG_ERR_UNSUPPORTED +#define G10ERR_UNU_PUBKEY GPG_ERR_UNUSABLE_PUBKEY +#define G10ERR_UNU_SECKEY GPG_ERR_UNUSABLE_SECKEY +#define G10ERR_WRONG_SECKEY GPG_ERR_WRONG_SECKEY + #endif /*GNUPG_G10_GPG_H*/ diff --git a/g10/gpgv.c b/g10/gpgv.c index 0a97d56b9..5fc7dcd75 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -1,6 +1,6 @@ /* gpgv.c - The GnuPG signature verify utility - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -29,23 +30,27 @@ #ifdef HAVE_DOSISH_SYSTEM #include <fcntl.h> /* for setmode() */ #endif +#ifdef HAVE_LIBREADLINE +#include <stdio.h> +#include <readline/readline.h> +#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" +#include "g10defs.h" +#include "cardglue.h" enum cmd_and_opt_values { aNull = 0, @@ -79,10 +84,6 @@ static ARGPARSE_OPTS opts[] = { int g10_errors_seen = 0; -#ifdef __riscos__ -RISCOS_GLOBAL_STATICS("GnuPG (gpgv) Heap") -#endif /* __riscos__ */ - static const char * my_strusage( int level ) { @@ -110,23 +111,22 @@ my_strusage( int level ) } - - static void i18n_init(void) { #ifdef USE_SIMPLE_GETTEXT - set_gettext_file( PACKAGE_GT ); + set_gettext_file (PACKAGE_GT, "Software\\GNU\\GnuPG"); #else #ifdef ENABLE_NLS - setlocale( LC_ALL, "" ); - bindtextdomain( PACKAGE_GT, LOCALEDIR ); - textdomain( PACKAGE_GT ); + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE_GT, LOCALEDIR); + textdomain (PACKAGE_GT); #endif #endif } + int main( int argc, char **argv ) { @@ -136,17 +136,13 @@ main( int argc, char **argv ) 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); + 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.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE; opt.trust_model = TM_ALWAYS; opt.batch = 1; @@ -164,8 +160,11 @@ main( int argc, char **argv ) 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 oVerbose: + opt.verbose++; + opt.list_sigs=1; + gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); + break; case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break; case oStatusFD: set_status_fd( pargs.r.ret_int ); break; case oLoggerFD: @@ -180,9 +179,7 @@ main( int argc, char **argv ) if( log_get_errorcount(0) ) g10_exit(2); - g10_opt_homedir = opt.homedir; - - if( opt.verbose > 1 ) + if( opt.verbose > 1 ) set_packet_list_mode(1); if( !nrings ) /* no keyring given: use default one */ @@ -193,7 +190,7 @@ main( int argc, char **argv ) FREE_STRLIST(nrings); if( (rc = verify_signatures( argc, argv ) )) - log_error("verify signatures failed: %s\n", gpg_strerror (rc) ); + log_error("verify signatures failed: %s\n", g10_errstr(rc) ); /* cleanup */ g10_exit(0); @@ -210,14 +207,6 @@ g10_exit( int 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 @@ -228,6 +217,9 @@ check_signatures_trust( PKT_signature *sig ) return 0; } +void +read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, + byte *marginals,byte *completes,byte *cert_depth) {} /* Stub: * We don't have the trustdb , so we have to provide some stub functions @@ -240,6 +232,9 @@ cache_disabled_value(PKT_public_key *pk) return 0; } +void +check_trustdb_stale(void) {} + int get_validity_info (PKT_public_key *pk, PKT_user_id *uid) { @@ -258,7 +253,12 @@ trust_value_to_string (unsigned int value) return "err"; } -/* Stub: */ +const char * +uid_trust_string_fixed(PKT_public_key *key,PKT_user_id *uid) +{ + return "err"; +} + int get_ownertrust_info (PKT_public_key *pk) { @@ -272,35 +272,54 @@ get_ownertrust (PKT_public_key *pk) } -/* Stub: +/* Stubs: * Because we only work with trusted keys, it does not make sense to * get them from a keyserver */ + +struct keyserver_spec * +keyserver_match(struct keyserver_spec *spec) { return NULL; } + int keyserver_import_keyid( u32 *keyid, void *dummy ) { return -1; } +int +keyserver_import_cert(const char *name) { return -1; } + +int +keyserver_import_pka(const char *name,unsigned char *fpr) { return -1; } + +int +keyserver_import_name(const char *name,struct keyserver_spec *spec) +{ + return -1; +} + +int +keyserver_import_ldap(const char *name) { 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; + return G10ERR_GENERAL; } /* Stub: */ int get_override_session_key( DEK *dek, const char *string ) { - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } /* Stub: */ int decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) { - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } @@ -318,7 +337,7 @@ display_online_help( const char *keyword ) int check_secret_key( PKT_secret_key *sk, int n ) { - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } /* Stub: @@ -334,11 +353,25 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, return NULL; } +struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig) {return NULL;} +struct keyserver_spec *parse_keyserver_uri(const char *uri,int require_scheme, + const char *configname, + unsigned int configlineno) +{ + return NULL; +} + +void free_keyserver_spec(struct keyserver_spec *keyserver) {} + /* 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;} +#ifdef ENABLE_CARD_SUPPORT +int agent_scd_getattr (const char *name, struct agent_card_info_s *info) {return 0;} +#endif /* ENABLE_CARD_SUPPORT */ + /* 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 "?";} @@ -356,10 +389,31 @@ void cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) {} void cipher_sync( CIPHER_HANDLE c ) {} +/* Stubs to avoid linking to ../cipher/random.c */ +void random_dump_stats(void) {} +int quick_random_gen( int onoff ) { return -1;} +void randomize_buffer( byte *buffer, size_t length, int level ) {} +int random_is_faked() { return -1;} +byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;} +void set_random_seed_file( const char *name ) {} +void update_random_seed_file() {} +void fast_random_poll() {} + +/* Stubs to avoid linking of ../cipher/primegen.c */ +void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {} +MPI generate_secret_prime( unsigned nbits ) { return NULL;} +MPI generate_public_prime( unsigned nbits ) { return NULL;} +MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, + MPI g, MPI **ret_factors ) { return NULL;} + +/* Do not link to ../cipher/rndlinux.c */ +void rndlinux_constructor(void) {} + /* Stubs to avoid linking to ../util/ttyio.c */ int tty_batchmode( int onoff ) { return 0; } void tty_printf( const char *fmt, ... ) { } +void tty_fprintf (FILE *fp, 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 ) {} @@ -368,10 +422,15 @@ 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;} +#ifdef HAVE_LIBREADLINE +void tty_enable_completion(rl_completion_func_t *completer) {} +void tty_disable_completion(void) {} +#endif /* 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; } +void destroy_dotlock (DOTLOCK h) {} int make_dotlock( DOTLOCK h, long timeout ) { return 0;} int release_dotlock( DOTLOCK h ) {return 0;} -void dotlock_remove_lockfiles(void) {} +void remove_lockfiles(void) {} diff --git a/g10/helptext.c b/g10/helptext.c index 4a65314eb..c720cc7cf 100644 --- a/g10/helptext.c +++ b/g10/helptext.c @@ -1,5 +1,6 @@ /* helptext.c - English help texts - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -58,10 +60,6 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = { "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\"." )}, @@ -73,29 +71,17 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = { { "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" +"DSA (aka DSS) is the Digital Signature Algorithm and can only be used\n" +"for signatures.\n" +"\n" +"Elgamal is an encrypt-only algorithm.\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" +"RSA may be used for signatures or encryption.\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." +"The first (primary) key must always be a key which is capable of signing." )}, -{ "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" @@ -199,7 +185,7 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = { )}, { "keyedit.sign_all.okay", N_( - "Answer \"yes\" is you want to sign ALL the user IDs" + "Answer \"yes\" if you want to sign ALL the user IDs" )}, { "keyedit.remove.uid.okay", N_( diff --git a/g10/import.c b/g10/import.c index 9c323243a..31af7fe02 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1,6 +1,6 @@ -/* import.c - Import OpenPGP key material - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. +/* import.c - import a key into our key storage. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,11 +27,11 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "trustdb.h" #include "main.h" @@ -54,15 +55,18 @@ struct stats_s { ulong secret_dups; ulong skipped_new_keys; ulong not_imported; + ulong n_sigs_cleaned; + ulong n_uids_cleaned; }; -static int import( iobuf_t inp, const char* fname, - struct stats_s *stats, unsigned int options ); -static int read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ); +static int import( IOBUF inp, const char* fname,struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options ); +static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); static void revocation_present(KBNODE keyblock); -static int import_one( const char *fname, KBNODE keyblock, - struct stats_s *stats, unsigned int options); +static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len, + unsigned int options); static int import_secret_one( const char *fname, KBNODE keyblock, struct stats_s *stats, unsigned int options); static int import_revoke_cert( const char *fname, KBNODE node, @@ -84,25 +88,41 @@ static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs, const char *fname, u32 *keyid ); int -parse_import_options(char *str,unsigned int *options) +parse_import_options(char *str,unsigned int *options,int noisy) { struct parse_options import_opts[]= { - {"allow-local-sigs",IMPORT_ALLOW_LOCAL_SIGS}, - {"repair-hkp-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG}, - {"repair-pks-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG}, - {"fast-import",IMPORT_FAST_IMPORT}, - {"convert-sk-to-pk",IMPORT_SK2PK}, - {NULL,0} + {"import-local-sigs",IMPORT_LOCAL_SIGS,NULL, + N_("import signatures that are marked as local-only")}, + {"repair-pks-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG,NULL, + N_("repair damage from the pks keyserver during import")}, + {"fast-import",IMPORT_FAST,NULL, + N_("do not update the trustdb after import")}, + {"convert-sk-to-pk",IMPORT_SK2PK,NULL, + N_("create a public key when importing a secret key")}, + {"merge-only",IMPORT_MERGE_ONLY,NULL, + N_("only accept updates to existing keys")}, + {"import-clean",IMPORT_CLEAN,NULL, + N_("remove unusable parts from key after import")}, + {"import-minimal",IMPORT_MINIMAL|IMPORT_CLEAN,NULL, + N_("remove as much as possible from key after import")}, + /* Aliases for backward compatibility */ + {"allow-local-sigs",IMPORT_LOCAL_SIGS,NULL,NULL}, + {"repair-hkp-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG,NULL,NULL}, + /* dummy */ + {"import-unusable-sigs",0,NULL,NULL}, + {"import-clean-sigs",0,NULL,NULL}, + {"import-clean-uids",0,NULL,NULL}, + {NULL,0,NULL,NULL} }; - return parse_options(str,options,import_opts); + return parse_options(str,options,import_opts,noisy); } void * import_new_stats_handle (void) { - return xcalloc (1, sizeof (struct stats_s) ); + return xmalloc_clear ( sizeof (struct stats_s) ); } void @@ -143,8 +163,9 @@ import_release_stats_handle (void *p) * */ static int -import_keys_internal( iobuf_t inp, char **fnames, int nnames, - void *stats_handle, unsigned int options ) +import_keys_internal( IOBUF inp, char **fnames, int nnames, + void *stats_handle, unsigned char **fpr, size_t *fpr_len, + unsigned int options ) { int i, rc = 0; struct stats_s *stats = stats_handle; @@ -153,7 +174,7 @@ import_keys_internal( iobuf_t inp, char **fnames, int nnames, stats = import_new_stats_handle (); if (inp) { - rc = import( inp, "[stream]", stats, options); + rc = import( inp, "[stream]", stats, fpr, fpr_len, options); } else { if( !fnames && !nnames ) @@ -161,20 +182,27 @@ import_keys_internal( iobuf_t inp, char **fnames, int nnames, for(i=0; i < nnames; i++ ) { const char *fname = fnames? fnames[i] : NULL; - iobuf_t inp2 = iobuf_open(fname); + IOBUF inp2 = iobuf_open(fname); if( !fname ) fname = "[stdin]"; + if (inp2 && is_secured_file (iobuf_get_fd (inp2))) + { + iobuf_close (inp2); + inp2 = NULL; + errno = EPERM; + } if( !inp2 ) log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); - else { - rc = import( inp2, fname, stats, options ); + else + { + rc = import( inp2, fname, stats, fpr, fpr_len, options ); iobuf_close(inp2); /* Must invalidate that ugly cache to actually close it. */ iobuf_ioctl (NULL, 2, 0, (char*)fname); if( rc ) - log_error("import from `%s' failed: %s\n", fname, - gpg_strerror (rc) ); - } + log_error("import from `%s' failed: %s\n", fname, + g10_errstr(rc) ); + } if( !fname ) break; } @@ -183,18 +211,15 @@ import_keys_internal( iobuf_t inp, char **fnames, int nnames, import_print_stats (stats); import_release_stats_handle (stats); } + /* If no fast import and the trustdb is dirty (i.e. we added a key or userID that had something other than a selfsig, a signature that was other than a selfsig, or any revocation), then update/check the trustdb if the user specified by setting interactive or by not setting no-auto-check-trustdb */ - if (!(options&IMPORT_FAST_IMPORT) && trustdb_pending_check()) - { - if (opt.interactive) - update_trustdb(); - else if (!opt.no_auto_check_trustdb) - check_trustdb(); - } + + if(!(options&IMPORT_FAST)) + trustdb_check_or_update(); return rc; } @@ -203,18 +228,19 @@ void import_keys( char **fnames, int nnames, void *stats_handle, unsigned int options ) { - import_keys_internal( NULL, fnames, nnames, stats_handle, options); + import_keys_internal(NULL,fnames,nnames,stats_handle,NULL,NULL,options); } int -import_keys_stream( iobuf_t inp, void *stats_handle, unsigned int options ) +import_keys_stream( IOBUF inp, void *stats_handle, + unsigned char **fpr, size_t *fpr_len,unsigned int options ) { - return import_keys_internal( inp, NULL, 0, stats_handle, options); + return import_keys_internal(inp,NULL,0,stats_handle,fpr,fpr_len,options); } static int -import( iobuf_t inp, const char* fname, - struct stats_s *stats, unsigned int options ) +import( IOBUF inp, const char* fname,struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options ) { PACKET *pending_pkt = NULL; KBNODE keyblock; @@ -223,14 +249,14 @@ import( iobuf_t inp, const char* fname, getkey_disable_caches(); if( !opt.no_armor ) { /* armored reading is not disabled */ - armor_filter_context_t *afx = xcalloc (1, sizeof *afx ); + armor_filter_context_t *afx = xmalloc_clear( sizeof *afx ); afx->only_keyblocks = 1; iobuf_push_filter2( inp, armor_filter, afx, 1 ); } while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) - rc = import_one( fname, keyblock, stats, options ); + rc = import_one( fname, keyblock, stats, fpr, fpr_len, options ); else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) rc = import_secret_one( fname, keyblock, stats, options ); else if( keyblock->pkt->pkttype == PKT_SIGNATURE @@ -250,8 +276,8 @@ import( iobuf_t inp, const char* fname, } if( rc == -1 ) rc = 0; - else if( rc && rc != GPG_ERR_INV_KEYRING ) - log_error( _("error reading `%s': %s\n"), fname, gpg_strerror (rc)); + else if( rc && rc != G10ERR_INV_KEYRING ) + log_error( _("error reading `%s': %s\n"), fname, g10_errstr(rc)); return rc; } @@ -293,6 +319,10 @@ import_print_stats (void *hd) log_info(_(" secret keys unchanged: %lu\n"), stats->secret_dups ); if( stats->not_imported ) log_info(_(" not imported: %lu\n"), stats->not_imported ); + if( stats->n_sigs_cleaned) + log_info(_(" signatures cleaned: %lu\n"),stats->n_sigs_cleaned); + if( stats->n_uids_cleaned) + log_info(_(" user IDs cleaned: %lu\n"),stats->n_uids_cleaned); } if( is_status_enabled() ) { @@ -324,7 +354,7 @@ import_print_stats (void *hd) * Retunr: 0 = okay, -1 no more blocks or another errorcode. */ static int -read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ) +read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) { int rc; PACKET *pkt; @@ -338,13 +368,13 @@ read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ) } else in_cert = 0; - pkt = xmalloc ( sizeof *pkt ); + pkt = xmalloc( sizeof *pkt ); init_packet(pkt); while( (rc=parse_packet(a, pkt)) != -1 ) { if( rc ) { /* ignore errors */ - if( rc != GPG_ERR_UNKNOWN_PACKET ) { - log_error("read_block: read error: %s\n", gpg_strerror (rc) ); - rc = GPG_ERR_INV_KEYRING; + if( rc != G10ERR_UNKNOWN_PACKET ) { + log_error("read_block: read error: %s\n", g10_errstr(rc) ); + rc = G10ERR_INV_KEYRING; goto ready; } free_packet( pkt ); @@ -364,17 +394,17 @@ read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ) /* make a linked list of all packets */ switch( pkt->pkttype ) { case PKT_COMPRESSED: - if( pkt->pkt.compressed->algorithm < 1 - || pkt->pkt.compressed->algorithm > 2 ) { - rc = GPG_ERR_COMPR_ALGO; + if(check_compress_algo(pkt->pkt.compressed->algorithm)) + { + rc = G10ERR_COMPR_ALGO; goto ready; - } - { - compress_filter_context_t *cfx = xcalloc (1, sizeof *cfx ); - cfx->algo = pkt->pkt.compressed->algorithm; + } + else + { + compress_filter_context_t *cfx = xmalloc_clear( sizeof *cfx ); pkt->pkt.compressed->buf = NULL; - iobuf_push_filter2( a, compress_filter, cfx, 1 ); - } + push_compress_filter2(a,cfx,pkt->pkt.compressed->algorithm,1); + } free_packet( pkt ); init_packet(pkt); break; @@ -399,7 +429,7 @@ read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ) root = new_kbnode( pkt ); else add_kbnode( root, new_kbnode( pkt ) ); - pkt = xmalloc ( sizeof *pkt ); + pkt = xmalloc( sizeof *pkt ); } init_packet(pkt); break; @@ -414,7 +444,7 @@ read_block( iobuf_t a, PACKET **pending_pkt, KBNODE *ret_root ) else *ret_root = root; free_packet( pkt ); - xfree ( pkt ); + xfree( pkt ); return rc; } @@ -508,7 +538,7 @@ print_import_ok (PKT_public_key *pk, PKT_secret_key *sk, unsigned int reason) write_status_text (STATUS_IMPORT_OK, buf); } -void +static void print_import_check (PKT_public_key * pk, PKT_user_id * id) { char * buf; @@ -530,6 +560,115 @@ print_import_check (PKT_public_key * pk, PKT_user_id * id) xfree (buf); } +static void +check_prefs_warning(PKT_public_key *pk) +{ + log_info(_("WARNING: key %s contains preferences for unavailable\n" + "algorithms on these user IDs:\n"), keystr_from_pk(pk)); +} + +static void +check_prefs(KBNODE keyblock) +{ + KBNODE node; + PKT_public_key *pk; + int problem=0; + + merge_keys_and_selfsig(keyblock); + pk=keyblock->pkt->pkt.public_key; + + for(node=keyblock;node;node=node->next) + { + if(node->pkt->pkttype==PKT_USER_ID + && node->pkt->pkt.user_id->created + && node->pkt->pkt.user_id->prefs) + { + PKT_user_id *uid=node->pkt->pkt.user_id; + prefitem_t *prefs=uid->prefs; + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + + for(;prefs->type;prefs++) + { + char num[10]; /* prefs->value is a byte, so we're over + safe here */ + + sprintf(num,"%u",prefs->value); + + if(prefs->type==PREFTYPE_SYM) + { + if(check_cipher_algo(prefs->value)) + { + const char *algo=cipher_algo_to_string(prefs->value); + if(!problem) + check_prefs_warning(pk); + log_info(_(" \"%s\": preference for cipher" + " algorithm %s\n"),user,algo?algo:num); + problem=1; + } + } + else if(prefs->type==PREFTYPE_HASH) + { + if(check_digest_algo(prefs->value)) + { + const char *algo=digest_algo_to_string(prefs->value); + if(!problem) + check_prefs_warning(pk); + log_info(_(" \"%s\": preference for digest" + " algorithm %s\n"),user,algo?algo:num); + problem=1; + } + } + else if(prefs->type==PREFTYPE_ZIP) + { + if(check_compress_algo(prefs->value)) + { + const char *algo=compress_algo_to_string(prefs->value); + if(!problem) + check_prefs_warning(pk); + log_info(_(" \"%s\": preference for compression" + " algorithm %s\n"),user,algo?algo:num); + problem=1; + } + } + } + + xfree(user); + } + } + + if(problem) + { + log_info(_("it is strongly suggested that you update" + " your preferences and\n")); + log_info(_("re-distribute this key to avoid potential algorithm" + " mismatch problems\n")); + + if(!opt.batch) + { + STRLIST sl=NULL,locusr=NULL; + size_t fprlen=0; + byte fpr[MAX_FINGERPRINT_LEN],*p; + char username[(MAX_FINGERPRINT_LEN*2)+1]; + unsigned int i; + + p=fingerprint_from_pk(pk,fpr,&fprlen); + for(i=0;i<fprlen;i++,p++) + sprintf(username+2*i,"%02X",*p); + add_to_strlist(&locusr,username); + + append_to_strlist(&sl,"updpref"); + append_to_strlist(&sl,"save"); + + keyedit_menu( username, locusr, sl, 1, 1 ); + free_strlist(sl); + free_strlist(locusr); + } + else if(!opt.quiet) + log_info(_("you can update your preferences with:" + " gpg --edit-key %s updpref save\n"),keystr_from_pk(pk)); + } +} + /**************** * Try to import one keyblock. Return an error only in serious cases, but * never for an invalid keyblock. It uses log_error to increase the @@ -537,8 +676,8 @@ print_import_check (PKT_public_key * pk, PKT_user_id * id) * which called g10. */ static int -import_one( const char *fname, KBNODE keyblock, - struct stats_s *stats, unsigned int options ) +import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options ) { PKT_public_key *pk; PKT_public_key *pk_orig; @@ -556,27 +695,30 @@ import_one( const char *fname, KBNODE keyblock, BUG(); pk = node->pkt->pkt.public_key; + + if(fpr) + *fpr=fingerprint_from_pk(pk,NULL,fpr_len); + keyid_from_pk( pk, keyid ); uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); - if(pk->pubkey_algo==PUBKEY_ALGO_ELGAMAL) - log_info(_("NOTE: Elgamal primary key detected - " - "this may take some time to import\n")); - - if( opt.verbose && !opt.interactive ) { - log_info( "pub %4u%c/%08lX %s ", + if( opt.verbose && !opt.interactive ) + { + log_info( "pub %4u%c/%s %s ", nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk(pk) ); + keystr_from_pk(pk), datestr_from_pk(pk) ); if( uidnode ) - print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, - uidnode->pkt->pkt.user_id->len ); + print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len ); putc('\n', stderr); - } - if( !uidnode ) { - log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]); + } + + if( !uidnode ) + { + log_error( _("key %s: no user ID\n"), keystr_from_pk(pk)); return 0; - } + } if (opt.interactive) { if(is_status_enabled()) @@ -590,12 +732,21 @@ import_one( const char *fname, KBNODE keyblock, return 0; } + collapse_uids(&keyblock); + + /* Clean the key that we're about to import, to cut down on things + that we have to clean later. This has no practical impact on + the end result, but does result in less logging which might + confuse the user. */ + if(options&IMPORT_CLEAN) + clean_key(keyblock,opt.verbose,options&IMPORT_MINIMAL,NULL,NULL); + clear_kbnode_flags( keyblock ); if((options&IMPORT_REPAIR_PKS_SUBKEY_BUG) && fix_pks_corruption(keyblock) && opt.verbose) - log_info(_("key %08lX: PKS subkey corruption repaired\n"), - (ulong)keyid[1]); + log_info(_("key %s: PKS subkey corruption repaired\n"), + keystr_from_pk(pk)); rc = chk_self_sigs( fname, keyblock , pk, keyid, &non_self ); if( rc ) @@ -609,48 +760,50 @@ import_one( const char *fname, KBNODE keyblock, char *user=utf8_to_native(node->pkt->pkt.user_id->name, node->pkt->pkt.user_id->len,0); node->flag |= 1; - log_info( _("key %08lX: accepted non self-signed user ID '%s'\n"), - (ulong)keyid[1],user); - xfree (user); + log_info( _("key %s: accepted non self-signed user ID \"%s\"\n"), + keystr_from_pk(pk),user); + xfree(user); } if( !delete_inv_parts( fname, keyblock, keyid, options ) ) { - log_error ( _("key %08lX: no valid user IDs\n"), (ulong)keyid[1]); + log_error( _("key %s: no valid user IDs\n"), keystr_from_pk(pk)); if( !opt.quiet ) - log_info(_("this may be caused by a missing self-signature\n")); + log_info(_("this may be caused by a missing self-signature\n")); stats->no_user_id++; return 0; } /* do we have this key already in one of our pubrings ? */ - pk_orig = xcalloc (1, sizeof *pk_orig ); + pk_orig = xmalloc_clear( sizeof *pk_orig ); rc = get_pubkey_fast ( pk_orig, keyid ); - if( rc && gpg_err_code (rc) != GPG_ERR_NO_PUBKEY - && gpg_err_code (rc) != GPG_ERR_UNUSABLE_PUBKEY ) { - log_error( _("key %08lX: public key not found: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); - } - else if ( rc && opt.merge_only ) { + if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY ) + { + log_error( _("key %s: public key not found: %s\n"), + keystr(keyid), g10_errstr(rc)); + } + else if ( rc && (opt.import_options&IMPORT_MERGE_ONLY) ) + { if( opt.verbose ) - log_info( _("key %08lX: new key - skipped\n"), (ulong)keyid[1] ); + log_info( _("key %s: new key - skipped\n"), keystr(keyid)); rc = 0; stats->skipped_new_keys++; - } + } else if( rc ) { /* insert this key */ KEYDB_HANDLE hd = keydb_new (0); rc = keydb_locate_writable (hd, NULL); if (rc) { - log_error (_("no writable keyring found: %s\n"), gpg_strerror (rc)); + log_error (_("no writable keyring found: %s\n"), g10_errstr (rc)); keydb_release (hd); - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } if( opt.verbose > 1 ) log_info (_("writing to `%s'\n"), keydb_get_resource_name (hd) ); + rc = keydb_insert_keyblock (hd, keyblock ); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), gpg_strerror (rc)); + keydb_get_resource_name (hd), g10_errstr(rc)); else { /* This should not be possible since we delete the @@ -665,18 +818,20 @@ import_one( const char *fname, KBNODE keyblock, keydb_release (hd); /* we are ready */ - if( !opt.quiet ) { - char *p=get_user_id_printable (keyid); - log_info( _("key %08lX: public key \"%s\" imported\n"), - (ulong)keyid[1],p); - xfree (p); - } - if( is_status_enabled() ) { + if( !opt.quiet ) + { + char *p=get_user_id_native (keyid); + log_info( _("key %s: public key \"%s\" imported\n"), + keystr(keyid),p); + xfree(p); + } + if( is_status_enabled() ) + { char *us = get_long_user_id_string( keyid ); write_status_text( STATUS_IMPORTED, us ); - xfree (us); + xfree(us); print_import_ok (pk,NULL, 1); - } + } stats->imported++; if( is_RSA( pk->pubkey_algo ) ) stats->imported_rsa++; @@ -684,15 +839,15 @@ import_one( const char *fname, KBNODE keyblock, } else { /* merge */ KEYDB_HANDLE hd; - int n_uids, n_sigs, n_subk; + int n_uids, n_sigs, n_subk, n_sigs_cleaned, n_uids_cleaned; /* Compare the original against the new key; just to be sure nothing * weird is going on */ - if( cmp_public_keys( pk_orig, pk ) ) { - log_error( _("key %08lX: doesn't match our copy\n"), - (ulong)keyid[1]); + if( cmp_public_keys( pk_orig, pk ) ) + { + log_error( _("key %s: doesn't match our copy\n"),keystr(keyid)); goto leave; - } + } /* now read the original keyblock */ hd = keydb_new (0); @@ -705,94 +860,135 @@ import_one( const char *fname, KBNODE keyblock, afp[an++] = 0; rc = keydb_search_fpr (hd, afp); } - if( rc ) { - log_error (_("key %08lX: can't locate original keyblock: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if( rc ) + { + log_error (_("key %s: can't locate original keyblock: %s\n"), + keystr(keyid), g10_errstr(rc)); keydb_release (hd); goto leave; - } + } rc = keydb_get_keyblock (hd, &keyblock_orig ); - if (rc) { - log_error (_("key %08lX: can't read original keyblock: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if (rc) + { + log_error (_("key %s: can't read original keyblock: %s\n"), + keystr(keyid), g10_errstr(rc)); keydb_release (hd); goto leave; - } + } - collapse_uids( &keyblock ); /* and try to merge the block */ clear_kbnode_flags( keyblock_orig ); clear_kbnode_flags( keyblock ); - n_uids = n_sigs = n_subk = 0; + n_uids = n_sigs = n_subk = n_sigs_cleaned = n_uids_cleaned = 0; rc = merge_blocks( fname, keyblock_orig, keyblock, - keyid, &n_uids, &n_sigs, &n_subk ); - if( rc ) { + keyid, &n_uids, &n_sigs, &n_subk ); + if( rc ) + { keydb_release (hd); goto leave; - } - if( n_uids || n_sigs || n_subk ) { + } + + if(options&IMPORT_CLEAN) + clean_key(keyblock_orig,opt.verbose,options&IMPORT_MINIMAL, + &n_uids_cleaned,&n_sigs_cleaned); + + if( n_uids || n_sigs || n_subk || n_sigs_cleaned || n_uids_cleaned) { mod_key = 1; /* keyblock_orig has been updated; write */ rc = keydb_update_keyblock (hd, keyblock_orig); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), gpg_strerror (rc) ); + keydb_get_resource_name (hd), g10_errstr(rc) ); else if(non_self) revalidation_mark (); /* we are ready */ - if( !opt.quiet ) { - char *p=get_user_id_printable(keyid); + if( !opt.quiet ) + { + char *p=get_user_id_native(keyid); if( n_uids == 1 ) - log_info( _("key %08lX: \"%s\" 1 new user ID\n"), - (ulong)keyid[1], p); + log_info( _("key %s: \"%s\" 1 new user ID\n"), + keystr(keyid),p); else if( n_uids ) - log_info( _("key %08lX: \"%s\" %d new user IDs\n"), - (ulong)keyid[1], p, n_uids ); + log_info( _("key %s: \"%s\" %d new user IDs\n"), + keystr(keyid),p,n_uids); if( n_sigs == 1 ) - log_info( _("key %08lX: \"%s\" 1 new signature\n"), - (ulong)keyid[1], p); + log_info( _("key %s: \"%s\" 1 new signature\n"), + keystr(keyid), p); else if( n_sigs ) - log_info( _("key %08lX: \"%s\" %d new signatures\n"), - (ulong)keyid[1], p, n_sigs ); + log_info( _("key %s: \"%s\" %d new signatures\n"), + keystr(keyid), p, n_sigs ); if( n_subk == 1 ) - log_info( _("key %08lX: \"%s\" 1 new subkey\n"), - (ulong)keyid[1], p); + log_info( _("key %s: \"%s\" 1 new subkey\n"), + keystr(keyid), p); else if( n_subk ) - log_info( _("key %08lX: \"%s\" %d new subkeys\n"), - (ulong)keyid[1], p, n_subk ); - xfree (p); - } + log_info( _("key %s: \"%s\" %d new subkeys\n"), + keystr(keyid), p, n_subk ); + if(n_sigs_cleaned==1) + log_info(_("key %s: \"%s\" %d signature cleaned\n"), + keystr(keyid),p,n_sigs_cleaned); + else if(n_sigs_cleaned) + log_info(_("key %s: \"%s\" %d signatures cleaned\n"), + keystr(keyid),p,n_sigs_cleaned); + if(n_uids_cleaned==1) + log_info(_("key %s: \"%s\" %d user ID cleaned\n"), + keystr(keyid),p,n_uids_cleaned); + else if(n_uids_cleaned) + log_info(_("key %s: \"%s\" %d user IDs cleaned\n"), + keystr(keyid),p,n_uids_cleaned); + xfree(p); + } stats->n_uids +=n_uids; stats->n_sigs +=n_sigs; stats->n_subk +=n_subk; + stats->n_sigs_cleaned +=n_sigs_cleaned; + stats->n_uids_cleaned +=n_uids_cleaned; if (is_status_enabled ()) print_import_ok (pk, NULL, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0))); } - else { - if (is_status_enabled ()) - print_import_ok (pk, NULL, 0); - - if( !opt.quiet ) { - char *p=get_user_id_printable(keyid); - log_info( _("key %08lX: \"%s\" not changed\n"), - (ulong)keyid[1],p); - xfree (p); - } + else + { + if (is_status_enabled ()) + print_import_ok (pk, NULL, 0); + + if( !opt.quiet ) + { + char *p=get_user_id_native(keyid); + log_info( _("key %s: \"%s\" not changed\n"),keystr(keyid),p); + xfree(p); + } + stats->unchanged++; - } + } + keydb_release (hd); hd = NULL; } leave: + + /* Now that the key is definitely incorporated into the keydb, we + need to check if a designated revocation is present or if the + prefs are not rational so we can warn the user. */ + + if(mod_key) + { + revocation_present(keyblock_orig); + if(seckey_available(keyid)==0) + check_prefs(keyblock_orig); + } + else if(new_key) + { + revocation_present(keyblock); + if(seckey_available(keyid)==0) + check_prefs(keyblock); + } + release_kbnode( keyblock_orig ); free_public_key( pk_orig ); - revocation_present(keyblock); - return rc; } @@ -813,8 +1009,8 @@ sec_to_pub_keyblock(KBNODE sec_keyblock) write the keyblock out. */ PKT_secret_key *sk=secnode->pkt->pkt.secret_key; - PACKET *pkt=xcalloc (1,sizeof(PACKET)); - PKT_public_key *pk=xcalloc (1,sizeof(PKT_public_key)); + PACKET *pkt=xmalloc_clear(sizeof(PACKET)); + PKT_public_key *pk=xmalloc_clear(sizeof(PKT_public_key)); int n; if(secnode->pkt->pkttype==PKT_SECRET_KEY) @@ -831,7 +1027,12 @@ sec_to_pub_keyblock(KBNODE sec_keyblock) n=pubkey_get_npkey(pk->pubkey_algo); if(n==0) - pk->pkey[0]=mpi_copy(sk->skey[0]); + { + /* we can't properly extract the pubkey without knowing + the number of MPIs */ + release_kbnode(pub_keyblock); + return NULL; + } else { int i; @@ -880,80 +1081,108 @@ import_secret_one( const char *fname, KBNODE keyblock, keyid_from_sk( sk, keyid ); uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); - if( opt.verbose ) { - log_info( "sec %4u%c/%08lX %s ", + if( opt.verbose ) + { + log_info( "sec %4u%c/%s %s ", nbits_from_sk( sk ), pubkey_letter( sk->pubkey_algo ), - (ulong)keyid[1], datestr_from_sk(sk) ); + keystr_from_sk(sk), datestr_from_sk(sk) ); if( uidnode ) - print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, - uidnode->pkt->pkt.user_id->len ); + print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len ); putc('\n', stderr); - } + } stats->secret_read++; - if( !uidnode ) { - log_error( _("key %08lX: no user ID\n"), (ulong)keyid[1]); + if( !uidnode ) + { + log_error( _("key %s: no user ID\n"), keystr_from_sk(sk)); return 0; - } + } if(sk->protect.algo>110) { - log_error(_("key %08lX: secret key with invalid cipher %d " - "- skipped\n"),(ulong)keyid[1],sk->protect.algo); + log_error(_("key %s: secret key with invalid cipher %d" + " - skipped\n"),keystr_from_sk(sk),sk->protect.algo); return 0; } +#ifdef ENABLE_SELINUX_HACKS + if (1) + { + /* We don't allow to import secret keys because that may be used + to put a secret key into the keyring and the user might later + be tricked into signing stuff with that key. */ + log_error (_("importing secret keys not allowed\n")); + return 0; + } +#endif + clear_kbnode_flags( keyblock ); /* do we have this key already in one of our secrings ? */ rc = seckey_available( keyid ); - if( gpg_err_code (rc) == GPG_ERR_NO_SECKEY && !opt.merge_only ) { - /* simply insert this key */ + if( rc == G10ERR_NO_SECKEY && !(opt.import_options&IMPORT_MERGE_ONLY) ) + { + /* simply insert this key */ KEYDB_HANDLE hd = keydb_new (1); /* get default resource */ rc = keydb_locate_writable (hd, NULL); if (rc) { - log_error (_("no default secret keyring: %s\n"), gpg_strerror (rc)); - keydb_release (hd); - return GPG_ERR_GENERAL; + log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); + keydb_release (hd); + return G10ERR_GENERAL; } rc = keydb_insert_keyblock (hd, keyblock ); if (rc) - log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), gpg_strerror (rc) ); + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); keydb_release (hd); /* we are ready */ if( !opt.quiet ) - log_info( _("key %08lX: secret key imported\n"), (ulong)keyid[1]); + log_info( _("key %s: secret key imported\n"), keystr_from_sk(sk)); stats->secret_imported++; if (is_status_enabled ()) - print_import_ok (NULL, sk, 1|16); + print_import_ok (NULL, sk, 1|16); if(options&IMPORT_SK2PK) { /* Try and make a public key out of this. */ KBNODE pub_keyblock=sec_to_pub_keyblock(keyblock); - import_one(fname,pub_keyblock,stats,opt.import_options); - release_kbnode(pub_keyblock); + if(pub_keyblock) + { + import_one(fname,pub_keyblock,stats, + NULL,NULL,opt.import_options); + release_kbnode(pub_keyblock); + } } - } - else if( !rc ) { /* we can't merge secret keys */ - log_error( _("key %08lX: already in secret keyring\n"), - (ulong)keyid[1]); + /* Now that the key is definitely incorporated into the keydb, + if we have the public part of this key, we need to check if + the prefs are rational. */ + node=get_pubkeyblock(keyid); + if(node) + { + check_prefs(node); + release_kbnode(node); + } + } + else if( !rc ) + { /* we can't merge secret keys */ + log_error( _("key %s: already in secret keyring\n"), + keystr_from_sk(sk)); stats->secret_dups++; if (is_status_enabled ()) - print_import_ok (NULL, sk, 16); + print_import_ok (NULL, sk, 16); /* TODO: if we ever do merge secret keys, make sure to handle the sec_to_pub_keyblock feature as well. */ - } + } else - log_error( _("key %08lX: secret key not found: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); + log_error( _("key %s: secret key not found: %s\n"), + keystr_from_sk(sk), g10_errstr(rc)); return rc; } @@ -978,19 +1207,21 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) keyid[0] = node->pkt->pkt.signature->keyid[0]; keyid[1] = node->pkt->pkt.signature->keyid[1]; - pk = xcalloc (1, sizeof *pk ); + pk = xmalloc_clear( sizeof *pk ); rc = get_pubkey( pk, keyid ); - if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY ) { - log_error ( _("key %08lX: no public key - " - "can't apply revocation certificate\n"), (ulong)keyid[1]); + if( rc == G10ERR_NO_PUBKEY ) + { + log_error(_("key %s: no public key -" + " can't apply revocation certificate\n"), keystr(keyid)); rc = 0; goto leave; - } - else if( rc ) { - log_error( _("key %08lX: public key not found: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); + } + else if( rc ) + { + log_error(_("key %s: public key not found: %s\n"), + keystr(keyid), g10_errstr(rc)); goto leave; - } + } /* read the original keyblock */ hd = keydb_new (0); @@ -1003,41 +1234,42 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) afp[an++] = 0; rc = keydb_search_fpr (hd, afp); } - if (rc) { - log_error (_("key %08lX: can't locate original keyblock: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if (rc) + { + log_error (_("key %s: can't locate original keyblock: %s\n"), + keystr(keyid), g10_errstr(rc)); goto leave; - } + } rc = keydb_get_keyblock (hd, &keyblock ); - if (rc) { - log_error (_("key %08lX: can't read original keyblock: %s\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if (rc) + { + log_error (_("key %s: can't read original keyblock: %s\n"), + keystr(keyid), g10_errstr(rc)); goto leave; - } - + } /* it is okay, that node is not in keyblock because * check_key_signature works fine for sig_class 0x20 in this * special case. */ rc = check_key_signature( keyblock, node, NULL); - if( rc ) { - log_error( _("key %08lX: invalid revocation certificate" - ": %s - rejected\n"), (ulong)keyid[1], gpg_strerror (rc)); + if( rc ) + { + log_error( _("key %s: invalid revocation certificate" + ": %s - rejected\n"), keystr(keyid), g10_errstr(rc)); goto leave; - } - + } /* check whether we already have this */ for(onode=keyblock->next; onode; onode=onode->next ) { if( onode->pkt->pkttype == PKT_USER_ID ) break; else if( onode->pkt->pkttype == PKT_SIGNATURE - && !cmp_signatures(node->pkt->pkt.signature, - onode->pkt->pkt.signature)) - { - rc = 0; - goto leave; /* yes, we already know about it */ - } + && !cmp_signatures(node->pkt->pkt.signature, + onode->pkt->pkt.signature)) + { + rc = 0; + goto leave; /* yes, we already know about it */ + } } @@ -1048,15 +1280,16 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats ) rc = keydb_update_keyblock (hd, keyblock ); if (rc) log_error (_("error writing keyring `%s': %s\n"), - keydb_get_resource_name (hd), gpg_strerror (rc) ); + keydb_get_resource_name (hd), g10_errstr(rc) ); keydb_release (hd); hd = NULL; /* we are ready */ - if( !opt.quiet ) { - char *p=get_user_id_printable (keyid); - log_info( _("key %08lX: \"%s\" revocation certificate imported\n"), - (ulong)keyid[1],p); - xfree (p); - } + if( !opt.quiet ) + { + char *p=get_user_id_native (keyid); + log_info( _("key %s: \"%s\" revocation certificate imported\n"), + keystr(keyid),p); + xfree(p); + } stats->n_revoc++; /* If the key we just revoked was ultimately trusted, remove its @@ -1109,89 +1342,90 @@ chk_self_sigs( const char *fname, KBNODE keyblock, sig = n->pkt->pkt.signature; if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { - /* This just caches the sigs for later use. That way we - import a fully-cached key which speeds things up. */ - if(!opt.no_sig_cache) - check_key_signature(keyblock,n,NULL); + /* This just caches the sigs for later use. That way we + import a fully-cached key which speeds things up. */ + if(!opt.no_sig_cache) + check_key_signature(keyblock,n,NULL); - if( (sig->sig_class&~3) == 0x10 ) { + if( IS_UID_SIG(sig) || IS_UID_REV(sig) ) + { KBNODE unode = find_prev_kbnode( keyblock, n, PKT_USER_ID ); - if( !unode ) { - log_error( _("key %08lX: no user ID for signature\n"), - (ulong)keyid[1]); + if( !unode ) + { + log_error( _("key %s: no user ID for signature\n"), + keystr(keyid)); return -1; /* the complete keyblock is invalid */ - } + } /* If it hasn't been marked valid yet, keep trying */ if(!(unode->flag&1)) { rc = check_key_signature( keyblock, n, NULL); if( rc ) { - if (opt.verbose) - { - char *p=utf8_to_native(unode->pkt->pkt.user_id->name, - strlen(unode->pkt->pkt.user_id->name),0); - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key " - "algorithm on user id \"%s\"\n"): - _("key %08lX: invalid self-signature " - "on user id \"%s\"\n"), - (ulong)keyid[1],p); - xfree (p); - } - } - else + if( opt.verbose ) + { + char *p=utf8_to_native(unode->pkt->pkt.user_id->name, + strlen(unode->pkt->pkt.user_id->name),0); + log_info( rc == G10ERR_PUBKEY_ALGO ? + _("key %s: unsupported public key " + "algorithm on user ID \"%s\"\n"): + _("key %s: invalid self-signature " + "on user ID \"%s\"\n"), + keystr(keyid),p); + xfree(p); + } + } + else unode->flag |= 1; /* mark that signature checked */ } - } + } else if( sig->sig_class == 0x18 ) { /* Note that this works based solely on the timestamps like the rest of gpg. If the standard gets revocation targets, this may need to be revised. */ if( !knode ) - { - if (opt.verbose) - log_info( _("key %08lX: no subkey for subkey " - "binding signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ - } + { + if(opt.verbose) + log_info( _("key %s: no subkey for key binding\n"), + keystr(keyid)); + n->flag |= 4; /* delete this */ + } else - { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) - { - if (opt.verbose) - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key algorithm\n"): - _("key %08lX: invalid subkey binding\n"), - (ulong)keyid[1]); - n->flag|=4; - } - else - { - /* It's valid, so is it newer? */ - if(sig->timestamp>=bsdate) - { - knode->flag |= 1; /* the subkey is valid */ - if(bsnode) - { - bsnode->flag|=4; /* Delete the last binding - sig since this one is - newer */ - if (opt.verbose) - log_info(_("key %08lX: removed multiple " - "subkey binding\n"), - (ulong)keyid[1]); - } - - bsnode=n; - bsdate=sig->timestamp; - } - else - n->flag|=4; /* older */ - } - } + { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) + { + if(opt.verbose) + log_info(rc == G10ERR_PUBKEY_ALGO ? + _("key %s: unsupported public key" + " algorithm\n"): + _("key %s: invalid subkey binding\n"), + keystr(keyid)); + n->flag|=4; + } + else + { + /* It's valid, so is it newer? */ + if(sig->timestamp>=bsdate) { + knode->flag |= 1; /* the subkey is valid */ + if(bsnode) + { + bsnode->flag|=4; /* Delete the last binding + sig since this one is + newer */ + if(opt.verbose) + log_info(_("key %s: removed multiple subkey" + " binding\n"),keystr(keyid)); + } + + bsnode=n; + bsdate=sig->timestamp; + } + else + n->flag|=4; /* older */ + } + } } else if( sig->sig_class == 0x28 ) { /* We don't actually mark the subkey as revoked right @@ -1200,42 +1434,48 @@ chk_self_sigs( const char *fname, KBNODE keyblock, the binding sig is newer than the revocation sig. See the comment in getkey.c:merge_selfsigs_subkey for more */ - if( !knode ) { - if (opt.verbose) - log_info( _("key %08lX: no subkey for subkey " - "revocation signature\n"),(ulong)keyid[1]); - n->flag |= 4; /* delete this */ - } - else { - rc = check_key_signature( keyblock, n, NULL); - if( rc ) { - if (opt.verbose) - log_info( gpg_err_code (rc) == GPG_ERR_PUBKEY_ALGO ? - _("key %08lX: unsupported public key algorithm\n"): - _("key %08lX: invalid subkey revocation\n"), - (ulong)keyid[1]); - n->flag|=4; + if( !knode ) + { + if(opt.verbose) + log_info( _("key %s: no subkey for key revocation\n"), + keystr(keyid)); + n->flag |= 4; /* delete this */ } - else { - /* It's valid, so is it newer? */ - if(sig->timestamp>=rsdate) { - if(rsnode) { - rsnode->flag|=4; /* Delete the last revocation - sig since this one is - newer */ - if (opt.verbose) - log_info(_("key %08lX: removed multiple subkey " - "revocation signatures\n"), - (ulong)keyid[1]); + else + { + rc = check_key_signature( keyblock, n, NULL); + if( rc ) + { + if(opt.verbose) + log_info(rc == G10ERR_PUBKEY_ALGO ? + _("key %s: unsupported public" + " key algorithm\n"): + _("key %s: invalid subkey revocation\n"), + keystr(keyid)); + n->flag|=4; } - - rsnode=n; - rsdate=sig->timestamp; - } else - n->flag|=4; /* older */ + { + /* It's valid, so is it newer? */ + if(sig->timestamp>=rsdate) + { + if(rsnode) + { + rsnode->flag|=4; /* Delete the last revocation + sig since this one is + newer */ + if(opt.verbose) + log_info(_("key %s: removed multiple subkey" + " revocation\n"),keystr(keyid)); + } + + rsnode=n; + rsdate=sig->timestamp; + } + else + n->flag|=4; /* older */ + } } - } } } else @@ -1263,13 +1503,14 @@ delete_inv_parts( const char *fname, KBNODE keyblock, if( node->pkt->pkttype == PKT_USER_ID ) { uid_seen = 1; if( (node->flag & 2) || !(node->flag & 1) ) { - if( opt.verbose ) { - log_info( _("key %08lX: skipped user ID '"), - (ulong)keyid[1]); - print_utf8_string( stderr, node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len ); - fputs("'\n", stderr ); - } + if( opt.verbose ) + { + char *p=utf8_to_native(node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len,0); + log_info( _("key %s: skipped user ID \"%s\"\n"), + keystr(keyid),p); + xfree(p); + } delete_kbnode( node ); /* the user-id */ /* and all following packets up to the next user-id */ while( node->next @@ -1286,10 +1527,9 @@ delete_inv_parts( const char *fname, KBNODE keyblock, else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { if( (node->flag & 2) || !(node->flag & 1) ) { - if( opt.verbose ) { - log_info( _("key %08lX: skipped subkey\n"), - (ulong)keyid[1]); - } + if( opt.verbose ) + log_info( _("key %s: skipped subkey\n"),keystr(keyid)); + delete_kbnode( node ); /* the subkey */ /* and all following signature packets */ while( node->next @@ -1302,34 +1542,33 @@ delete_inv_parts( const char *fname, KBNODE keyblock, subkey_seen = 1; } else if( node->pkt->pkttype == PKT_SIGNATURE - && openpgp_pk_test_algo( node->pkt->pkt.signature - ->pubkey_algo, 0) + && check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo) && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA ) delete_kbnode( node ); /* build_packet() can't handle this */ else if( node->pkt->pkttype == PKT_SIGNATURE && !node->pkt->pkt.signature->flags.exportable && - !(options&IMPORT_ALLOW_LOCAL_SIGS) && - seckey_available( node->pkt->pkt.signature->keyid ) ) { - /* Here we violate the rfc a bit by still allowing + !(options&IMPORT_LOCAL_SIGS) && + seckey_available( node->pkt->pkt.signature->keyid ) ) + { + /* here we violate the rfc a bit by still allowing * to import non-exportable signature when we have the * the secret key used to create this signature - it - * seems that this makes sense. */ - if (opt.verbose) - log_info( _("key %08lX: non exportable signature " - "(class %02x) - skipped\n"), - (ulong)keyid[1], - node->pkt->pkt.signature->sig_class ); - delete_kbnode( node ); - } + * seems that this makes sense */ + if(opt.verbose) + log_info( _("key %s: non exportable signature" + " (class 0x%02X) - skipped\n"), + keystr(keyid), node->pkt->pkt.signature->sig_class ); + delete_kbnode( node ); + } else if( node->pkt->pkttype == PKT_SIGNATURE && node->pkt->pkt.signature->sig_class == 0x20 ) { - if( uid_seen ) { - if (opt.verbose) - log_error( _("key %08lX: revocation certificate " - "at wrong place - skipped\n"), - (ulong)keyid[1]); - delete_kbnode( node ); - } + if( uid_seen ) + { + if(opt.verbose) + log_info( _("key %s: revocation certificate" + " at wrong place - skipped\n"),keystr(keyid)); + delete_kbnode( node ); + } else { /* If the revocation cert is from a different key than the one we're working on don't check it - it's @@ -1342,10 +1581,10 @@ delete_inv_parts( const char *fname, KBNODE keyblock, int rc = check_key_signature( keyblock, node, NULL); if( rc ) { - if (opt.verbose) - log_info ( _("key %08lX: invalid revocation " - "certificate: %s - skipped\n"), - (ulong)keyid[1], gpg_strerror (rc)); + if(opt.verbose) + log_info( _("key %s: invalid revocation" + " certificate: %s - skipped\n"), + keystr(keyid), g10_errstr(rc)); delete_kbnode( node ); } } @@ -1354,24 +1593,24 @@ delete_inv_parts( const char *fname, KBNODE keyblock, else if( node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class == 0x18 || node->pkt->pkt.signature->sig_class == 0x28) && - !subkey_seen ) { - if (opt.verbose) - log_info ( _("key %08lX: subkey signature " - "in wrong place - skipped\n"), - (ulong)keyid[1]); - delete_kbnode( node ); - } + !subkey_seen ) + { + if(opt.verbose) + log_info( _("key %s: subkey signature" + " in wrong place - skipped\n"), keystr(keyid)); + delete_kbnode( node ); + } else if( node->pkt->pkttype == PKT_SIGNATURE && !IS_CERT(node->pkt->pkt.signature)) { - if (opt.verbose) - log_info (_("key %08lX: unexpected signature class (0x%02X) -" - " skipped\n"),(ulong)keyid[1], - node->pkt->pkt.signature->sig_class); + if(opt.verbose) + log_info(_("key %s: unexpected signature class (0x%02X) -" + " skipped\n"),keystr(keyid), + node->pkt->pkt.signature->sig_class); delete_kbnode(node); } else if( (node->flag & 4) ) /* marked for deletion */ - delete_kbnode( node ); + delete_kbnode( node ); } /* note: because keyblock is the public key, it is never marked @@ -1393,7 +1632,6 @@ collapse_uids( KBNODE *keyblock ) KBNODE n, n2; int in_uid; int any=0; - u32 kid1; restart: for( n = *keyblock; n; n = n->next ) { @@ -1457,22 +1695,24 @@ collapse_uids( KBNODE *keyblock ) } } - if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) - kid1 = keyid_from_pk( n->pkt->pkt.public_key, NULL ); - else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) - kid1 = keyid_from_sk( n->pkt->pkt.secret_key, NULL ); - else - kid1 = 0; - if (!opt.quiet) - log_info (_("key %08lX: duplicated user ID detected - merged\n"), - (ulong)kid1); + if(!opt.quiet) + { + const char *key="???"; + + if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) + key=keystr_from_pk(n->pkt->pkt.public_key); + else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) + key=keystr_from_sk(n->pkt->pkt.secret_key); + + log_info(_("key %s: duplicated user ID detected - merged\n"),key); + } return 1; } /* Check for a 0x20 revocation from a revocation key that is not - present. This gets called without the benefit of merge_xxxx so you - can't rely on pk->revkey and friends. */ + present. This may be called without the benefit of merge_xxxx so + you can't rely on pk->revkey and friends. */ static void revocation_present(KBNODE keyblock) { @@ -1517,19 +1757,21 @@ revocation_present(KBNODE keyblock) rc=get_pubkey_byfprint_fast (NULL,sig->revkey[idx]->fpr, MAX_FINGERPRINT_LEN); - if ( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY - || gpg_err_code (rc) == GPG_ERR_UNUSABLE_PUBKEY) + if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) { + char *tempkeystr=xstrdup(keystr_from_pk(pk)); + /* No, so try and get it */ - if(opt.keyserver_scheme && - opt.keyserver_options.auto_key_retrieve) + if(opt.keyserver + && (opt.keyserver_options.options + & KEYSERVER_AUTO_KEY_RETRIEVE)) { - log_info(_("WARNING: key %08lX may be revoked: " - "fetching revocation key %08lX\n"), - (ulong)keyid_from_pk(pk,NULL), - (ulong)keyid[1]); + log_info(_("WARNING: key %s may be revoked:" + " fetching revocation key %s\n"), + tempkeystr,keystr(keyid)); keyserver_import_fprint(sig->revkey[idx]->fpr, - MAX_FINGERPRINT_LEN); + MAX_FINGERPRINT_LEN, + opt.keyserver); /* Do we have it now? */ rc=get_pubkey_byfprint_fast (NULL, @@ -1537,12 +1779,12 @@ revocation_present(KBNODE keyblock) MAX_FINGERPRINT_LEN); } - if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY - || gpg_err_code (rc) == GPG_ERR_UNUSABLE_PUBKEY) - log_info(_("WARNING: key %08lX may be revoked: " - "revocation key %08lX not present.\n"), - (ulong)keyid_from_pk(pk,NULL), - (ulong)keyid[1]); + if(rc==G10ERR_NO_PUBKEY || rc==G10ERR_UNU_PUBKEY) + log_info(_("WARNING: key %s may be revoked:" + " revocation key %s not present.\n"), + tempkeystr,keystr(keyid)); + + xfree(tempkeystr); } } } @@ -1584,25 +1826,23 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, && onode->pkt->pkt.signature->sig_class == 0x20 && !cmp_signatures(onode->pkt->pkt.signature, node->pkt->pkt.signature)) - { - found = 1; - break; - } + { + found = 1; + break; + } } if( !found ) { KBNODE n2 = clone_kbnode(node); insert_kbnode( keyblock_orig, n2, 0 ); n2->flag |= 1; ++*n_sigs; - - if (!opt.quiet) - { - char *p=get_user_id_printable (keyid); - log_info(_("key %08lX: \"%s\" " - "revocation certificate added\n"), - (ulong)keyid[1],p); - xfree (p); - } + if(!opt.quiet) + { + char *p=get_user_id_native (keyid); + log_info(_("key %s: \"%s\" revocation" + " certificate added\n"), keystr(keyid),p); + xfree(p); + } } } } @@ -1626,15 +1866,16 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, break; } } - if( !found ) { + if( !found ) + { KBNODE n2 = clone_kbnode(node); insert_kbnode( keyblock_orig, n2, 0 ); n2->flag |= 1; ++*n_sigs; - if (!opt.quiet) - log_info( _("key %08lX: direct key signature added\n"), - (ulong)keyid[1]); - } + if(!opt.quiet) + log_info( _("key %s: direct key signature added\n"), + keystr(keyid)); + } } } @@ -1806,7 +2047,7 @@ merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, { found++; break; - } + } if( !found ) { /* This signature is new or newer, append N to DST. * We add a clone to the original keyblock, because this @@ -1904,3 +2145,232 @@ append_key( KBNODE keyblock, KBNODE node, int *n_sigs, return 0; } + + + +/* Walk a public keyblock and produce a secret keyblock out of it. + Instead of inserting the secret key parameters (which we don't + have), we insert a stub. */ +static KBNODE +pub_to_sec_keyblock (KBNODE pub_keyblock) +{ + KBNODE pubnode, secnode; + KBNODE sec_keyblock = NULL; + KBNODE walkctx = NULL; + + while((pubnode = walk_kbnode (pub_keyblock,&walkctx,0))) + { + if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY + || pubnode->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + /* Make a secret key. We only need to convert enough to + write the keyblock out. */ + PKT_public_key *pk = pubnode->pkt->pkt.public_key; + PACKET *pkt = xmalloc_clear (sizeof *pkt); + PKT_secret_key *sk = xmalloc_clear (sizeof *sk); + int i, n; + + if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY) + pkt->pkttype = PKT_SECRET_KEY; + else + pkt->pkttype = PKT_SECRET_SUBKEY; + + pkt->pkt.secret_key = sk; + + copy_public_parts_to_secret_key ( pk, sk ); + sk->version = pk->version; + sk->timestamp = pk->timestamp; + + n = pubkey_get_npkey (pk->pubkey_algo); + if (!n) + n = 1; /* Unknown number of parameters, however the data + is stored in the first mpi. */ + for (i=0; i < n; i++ ) + sk->skey[i] = mpi_copy (pk->pkey[i]); + + sk->is_protected = 1; + sk->protect.s2k.mode = 1001; + + secnode = new_kbnode (pkt); + } + else + { + secnode = clone_kbnode (pubnode); + } + + if(!sec_keyblock) + sec_keyblock = secnode; + else + add_kbnode (sec_keyblock, secnode); + } + + return sec_keyblock; +} + + +/* Walk over the secret keyring SEC_KEYBLOCK and update any simple + stub keys with the serial number SNNUM of the card if one of the + fingerprints FPR1, FPR2 or FPR3 match. Print a note if the key is + a duplicate (may happen in case of backed uped keys). + + Returns: True if anything changed. +*/ +static int +update_sec_keyblock_with_cardinfo (KBNODE sec_keyblock, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3, + const char *serialnostr) +{ + KBNODE node; + KBNODE walkctx = NULL; + PKT_secret_key *sk; + byte array[MAX_FINGERPRINT_LEN]; + size_t n; + int result = 0; + const char *s; + + while((node = walk_kbnode (sec_keyblock, &walkctx, 0))) + { + if (node->pkt->pkttype != PKT_SECRET_KEY + && node->pkt->pkttype != PKT_SECRET_SUBKEY) + continue; + sk = node->pkt->pkt.secret_key; + + fingerprint_from_sk (sk, array, &n); + if (n != 20) + continue; /* Can't be a card key. */ + if ( !((fpr1 && !memcmp (array, fpr1, 20)) + || (fpr2 && !memcmp (array, fpr2, 20)) + || (fpr3 && !memcmp (array, fpr3, 20))) ) + continue; /* No match. */ + + if (sk->is_protected == 1 && sk->protect.s2k.mode == 1001) + { + /* Standard case: migrate that stub to a key stub. */ + sk->protect.s2k.mode = 1002; + s = serialnostr; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); + result = 1; + } + else if (sk->is_protected == 1 && sk->protect.s2k.mode == 1002) + { + s = serialnostr; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + if (sk->protect.iv[sk->protect.ivlen] != xtoi_2 (s)) + { + log_info (_("NOTE: a key's S/N does not " + "match the card's one\n")); + break; + } + } + else + { + if (node->pkt->pkttype != PKT_SECRET_KEY) + log_info (_("NOTE: primary key is online and stored on card\n")); + else + log_info (_("NOTE: secondary key is online and stored on card\n")); + } + } + + return result; +} + + + +/* Check whether a secret key stub exists for the public key PK. If + not create such a stub key and store it into the secring. If it + exists, add appropriate subkey stubs and update the secring. + Return 0 if the key could be created. */ +int +auto_create_card_key_stub ( const char *serialnostr, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3) +{ + KBNODE pub_keyblock; + KBNODE sec_keyblock; + KEYDB_HANDLE hd; + int rc; + + /* We only want to do this for an OpenPGP card. */ + if (!serialnostr || strncmp (serialnostr, "D27600012401", 12) + || strlen (serialnostr) != 32 ) + return G10ERR_GENERAL; + + /* First get the public keyring from any of the provided fingerprints. */ + if ( (fpr1 && !get_keyblock_byfprint (&pub_keyblock, fpr1, 20)) + || (fpr2 && !get_keyblock_byfprint (&pub_keyblock, fpr2, 20)) + || (fpr3 && !get_keyblock_byfprint (&pub_keyblock, fpr3, 20))) + ; + else + return G10ERR_GENERAL; + + hd = keydb_new (1); + + /* Now check whether there is a secret keyring. */ + { + PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key; + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk (pk, afp, &an); + memset (afp, 0, MAX_FINGERPRINT_LEN); + rc = keydb_search_fpr (hd, afp); + } + + if (!rc) + { + rc = keydb_get_keyblock (hd, &sec_keyblock); + if (rc) + { + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + rc = G10ERR_GENERAL; + } + else + { + merge_keys_and_selfsig (sec_keyblock); + + /* FIXME: We need to add new subkeys first. */ + if (update_sec_keyblock_with_cardinfo (sec_keyblock, + fpr1, fpr2, fpr3, + serialnostr)) + { + rc = keydb_update_keyblock (hd, sec_keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + } + } + } + else /* A secret key does not exists - create it. */ + { + sec_keyblock = pub_to_sec_keyblock (pub_keyblock); + update_sec_keyblock_with_cardinfo (sec_keyblock, + fpr1, fpr2, fpr3, + serialnostr); + + rc = keydb_locate_writable (hd, NULL); + if (rc) + { + log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); + rc = G10ERR_GENERAL; + } + else + { + rc = keydb_insert_keyblock (hd, sec_keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + } + } + + release_kbnode (sec_keyblock); + release_kbnode (pub_keyblock); + keydb_release (hd); + return rc; +} + diff --git a/g10/kbnode.c b/g10/kbnode.c index 58daad871..b09546451 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -1,5 +1,6 @@ /* kbnode.c - keyblock node utility functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,7 +28,6 @@ #include "gpg.h" #include "util.h" -#include "memory.h" #include "packet.h" #include "keydb.h" @@ -43,7 +44,7 @@ alloc_node(void) if( n ) unused_nodes = n->next; else - n = xmalloc ( sizeof *n ); + n = xmalloc( sizeof *n ); n->next = NULL; n->pkt = NULL; n->flag = 0; @@ -60,7 +61,7 @@ free_node( KBNODE n ) n->next = unused_nodes; unused_nodes = n; #else - xfree ( n ); + xfree( n ); #endif } } @@ -96,7 +97,7 @@ release_kbnode( KBNODE n ) n2 = n->next; if( !is_cloned_kbnode(n) ) { free_packet( n->pkt ); - xfree ( n->pkt ); + xfree( n->pkt ); } free_node( n ); n = n2; @@ -114,8 +115,6 @@ delete_kbnode( KBNODE node ) node->private_flag |= 1; } - - /**************** * Append NODE to ROOT. ROOT must exist! */ @@ -269,7 +268,7 @@ commit_kbnode( KBNODE *root ) nl->next = n->next; if( !is_cloned_kbnode(n) ) { free_packet( n->pkt ); - xfree ( n->pkt ); + xfree( n->pkt ); } free_node( n ); changed = 1; @@ -293,7 +292,7 @@ remove_kbnode( KBNODE *root, KBNODE node ) nl->next = n->next; if( !is_cloned_kbnode(n) ) { free_packet( n->pkt ); - xfree ( n->pkt ); + xfree( n->pkt ); } free_node( n ); } diff --git a/g10/keydb.c b/g10/keydb.c index b64f38cbc..dbad8435a 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -1,5 +1,5 @@ /* keydb.c - key database dispatcher - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -71,6 +72,124 @@ static int lock_all (KEYDB_HANDLE hd); static void unlock_all (KEYDB_HANDLE hd); +/* Handle the creation of a keyring if it does not yet exist. Take + into acount that other processes might have the keyring already + locked. This lock check does not work if the directory itself is + not yet available. */ +static int +maybe_create_keyring (char *filename, int force) +{ + DOTLOCK lockhd = NULL; + IOBUF iobuf; + int rc; + mode_t oldmask; + char *last_slash_in_filename; + + /* A quick test whether the filename already exists. */ + if (!access (filename, F_OK)) + return 0; + + /* If we don't want to create a new file at all, there is no need to + go any further - bail out right here. */ + if (!force) + return gpg_error (GPG_ERR_ENOENT); + + /* First of all we try to create the home directory. Note, that we + don't do any locking here because any sane application of gpg + would create the home directory by itself and not rely on gpg's + tricky auto-creation which is anyway only done for some home + directory name patterns. */ + last_slash_in_filename = strrchr (filename, DIRSEP_C); + *last_slash_in_filename = 0; + if (access(filename, F_OK)) + { + 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; + + + /* To avoid races with other instances of gpg trying to create or + update the keyring (it is removed during an update for a short + time), we do the next stuff in a locked state. */ + lockhd = create_dotlock (filename); + if (!lockhd) + { + /* A reason for this to fail is that the directory is not + writable. However, this whole locking stuff does not make + sense if this is the case. An empty non-writable directory + with no keyring is not really useful at all. */ + if (opt.verbose) + log_info ("can't allocate lock for `%s'\n", filename ); + + if (!force) + return G10ERR_OPEN_FILE; + else + return G10ERR_GENERAL; + } + + if ( make_dotlock (lockhd, -1) ) + { + /* This is something bad. Probably a stale lockfile. */ + log_info ("can't lock `%s'\n", filename ); + rc = G10ERR_GENERAL; + goto leave; + } + + /* Now the real test while we are locked. */ + if (!access(filename, F_OK)) + { + rc = 0; /* Okay, we may access the file now. */ + goto leave; + } + + /* The file does not yet exist, create it now. */ + oldmask = umask (077); + if (is_secured_filename (filename)) + { + iobuf = NULL; + errno = EPERM; + } + else + iobuf = iobuf_create (filename); + umask (oldmask); + if (!iobuf) + { + log_error ( _("error creating keyring `%s': %s\n"), + filename, strerror(errno)); + rc = G10ERR_OPEN_FILE; + goto leave; + } + + if (!opt.quiet) + log_info (_("keyring `%s' created\n"), filename); + + iobuf_close (iobuf); + /* Must invalidate that ugly cache */ + iobuf_ioctl (NULL, 2, 0, filename); + rc = 0; + + leave: + if (lockhd) + { + release_dotlock (lockhd); + destroy_dotlock (lockhd); + } + return rc; +} + + /* * Register a resource (which currently may only be a keyring file). * The first keyring which is added by this function is @@ -78,14 +197,14 @@ static void unlock_all (KEYDB_HANDLE hd); * Note: this function may be called before secure memory is * available. * Flag 1 == force - * Flag 2 == default + * Flag 2 == mark resource as primary + * Flag 4 == This is a default resources */ 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; @@ -104,7 +223,7 @@ keydb_add_resource (const char *url, int flags, int secret) #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) else if (strchr (resname, ':')) { log_error ("invalid key resource URL `%s'\n", url ); - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; goto leave; } #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ @@ -146,65 +265,18 @@ keydb_add_resource (const char *url, int flags, int secret) switch (rt) { case KEYDB_RESOURCE_TYPE_NONE: log_error ("unknown type of key resource `%s'\n", url ); - rc = GPG_ERR_GENERAL; + rc = G10ERR_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 */ + rc = maybe_create_keyring (filename, force); + if (rc) + goto leave; if(keyring_register_filename (filename, secret, &token)) { if (used_resources >= MAX_KEYDB_RESOURCES) - rc = GPG_ERR_RESOURCE_LIMIT; + rc = G10ERR_RESOURCE_LIMIT; else { if(flags&2) @@ -228,7 +300,7 @@ keydb_add_resource (const char *url, int flags, int secret) default: log_error ("resource type of `%s' not supported\n", url); - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; goto leave; } @@ -236,7 +308,18 @@ keydb_add_resource (const char *url, int flags, int secret) leave: if (rc) - log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror (rc)); + { + /* Secret keyrings are not required in all cases. To avoid + having gpg return failure we use log_info here if the + rewsource is a secret one and marked as default + resource. */ + if ((flags&4) && secret) + log_info (_("keyblock resource `%s': %s\n"), + filename, g10_errstr(rc)); + else + log_error (_("keyblock resource `%s': %s\n"), + filename, g10_errstr(rc)); + } else if (secret) any_secret = 1; else @@ -254,7 +337,7 @@ keydb_new (int secret) KEYDB_HANDLE hd; int i, j; - hd = xcalloc (1,sizeof *hd); + hd = xmalloc_clear (sizeof *hd); hd->found = -1; assert (used_resources <= MAX_KEYDB_RESOURCES); @@ -414,14 +497,14 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb) int rc = 0; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_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 */ + rc = G10ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb); @@ -440,7 +523,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) int rc = 0; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_INV_ARG; if ( hd->found < 0 || hd->found >= hd->used) return -1; /* nothing found */ @@ -454,7 +537,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: - rc = GPG_ERR_GENERAL; /* oops */ + rc = G10ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb); @@ -476,7 +559,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) int idx; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_INV_ARG; if( opt.dry_run ) return 0; @@ -486,7 +569,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) else if ( hd->current >= 0 && hd->current < hd->used) idx = hd->current; else - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; rc = lock_all (hd); if (rc) @@ -494,7 +577,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) switch (hd->active[idx].type) { case KEYDB_RESOURCE_TYPE_NONE: - rc = GPG_ERR_GENERAL; /* oops */ + rc = G10ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb); @@ -515,7 +598,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd) int rc = -1; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_INV_ARG; if ( hd->found < 0 || hd->found >= hd->used) return -1; /* nothing found */ @@ -529,7 +612,7 @@ keydb_delete_keyblock (KEYDB_HANDLE hd) switch (hd->active[hd->found].type) { case KEYDB_RESOURCE_TYPE_NONE: - rc = GPG_ERR_GENERAL; /* oops */ + rc = G10ERR_GENERAL; /* oops */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_delete_keyblock (hd->active[hd->found].u.kr); @@ -552,7 +635,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) int rc; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_INV_ARG; rc = keydb_search_reset (hd); /* this does reset hd->current */ if (rc) @@ -598,7 +681,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) * Rebuild the caches of all key resources. */ void -keydb_rebuild_caches (void) +keydb_rebuild_caches (int noisy) { int i, rc; @@ -611,10 +694,10 @@ keydb_rebuild_caches (void) case KEYDB_RESOURCE_TYPE_NONE: /* ignore */ break; case KEYDB_RESOURCE_TYPE_KEYRING: - rc = keyring_rebuild_cache (all_resources[i].token); + rc = keyring_rebuild_cache (all_resources[i].token,noisy); if (rc) log_error (_("failed to rebuild keyring cache: %s\n"), - gpg_strerror (rc)); + g10_errstr (rc)); break; } } @@ -631,7 +714,7 @@ keydb_search_reset (KEYDB_HANDLE hd) int i, rc = 0; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_INV_ARG; hd->current = 0; hd->found = -1; @@ -660,7 +743,7 @@ keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, int rc = -1; if (!hd) - return GPG_ERR_INV_ARG; + return G10ERR_INV_ARG; while (rc == -1 && hd->current >= 0 && hd->current < hd->used) { switch (hd->active[hd->current].type) { diff --git a/g10/keydb.h b/g10/keydb.h index 4920e88a1..4923a842c 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -1,5 +1,6 @@ /* keydb.h - Key database - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,14 +16,16 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_KEYDB_H #define G10_KEYDB_H +#include <assuan.h> + #include "types.h" -#include "global.h" #include "packet.h" #include "cipher.h" @@ -75,7 +78,7 @@ struct keyblock_pos_struct { enum resource_type rt; off_t offset; /* position information */ unsigned count; /* length of the keyblock in packets */ - iobuf_t fp; /* used by enum_keyblocks */ + iobuf_t fp; /* Used by enum_keyblocks. */ int secret; /* working on a secret keyring */ PACKET *pkt; /* ditto */ int valid; @@ -131,11 +134,11 @@ typedef enum { struct keydb_search_desc { KeydbSearchMode mode; - int (*skipfnc)(void *,u32*); + int (*skipfnc)(void *,u32*,PKT_user_id*); void *skipfncvalue; union { const char *name; - char fpr[MAX_FINGERPRINT_LEN]; + byte fpr[MAX_FINGERPRINT_LEN]; u32 kid[2]; } u; int exact; @@ -156,7 +159,7 @@ 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); +void keydb_rebuild_caches (int noisy); 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, @@ -183,14 +186,23 @@ int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock, unsigned use ); /*-- passphrase.h --*/ +assuan_context_t agent_open (int try, const char *orig_codeset); +void agent_close (assuan_context_t ctx); int have_static_passphrase(void); +void set_passphrase_from_string(const char *pass); void read_passphrase_from_fd( int fd ); -void passphrase_clear_cache ( u32 *keyid, int algo ); +void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo ); +char *ask_passphrase (const char *description, + const char *tryagain_text, + const char *promptid, + const char *prompt, + const char *cacheid, int *canceled); 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); +void next_to_last_passphrase(void); /*-- getkey.c --*/ int classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc); @@ -201,7 +213,7 @@ 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 include_unusable ); 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 ); @@ -219,27 +231,39 @@ 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_next (GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock); +void get_seckey_end( GETKEY_CTX ctx ); + 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 get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ); + + 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_user_id_string_native( 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 ); +char*get_user_id_native( u32 *keyid ); KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx); +void release_akl(void); +int parse_auto_key_locate(char *options); /*-- keyid.c --*/ int pubkey_letter( int algo ); -u32 v3_keyid (gcry_mpi_t a, u32 *ki); +void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ); +size_t keystrlen(void); +const char *keystr(u32 *keyid); +const char *keystr_from_pk(PKT_public_key *pk); +const char *keystr_from_sk(PKT_secret_key *sk); +const char *keystr_from_desc(KEYDB_SEARCH_DESC *desc); 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 ); +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 ); @@ -249,20 +273,16 @@ 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 *revokestr_from_pk( PKT_public_key *pk ); +const char *usagestr_from_pk( PKT_public_key *pk ); 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 ); diff --git a/g10/keyedit.c b/g10/keyedit.c index 2f9fccbf5..2a31d5973 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1,6 +1,6 @@ /* keyedit.c - keyedit stuff - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,6 +27,10 @@ #include <errno.h> #include <assert.h> #include <ctype.h> +#ifdef HAVE_LIBREADLINE +#include <stdio.h> +#include <readline/readline.h> +#endif #include "gpg.h" #include "options.h" @@ -33,7 +38,6 @@ #include "errors.h" #include "iobuf.h" #include "keydb.h" -#include "memory.h" #include "photoid.h" #include "util.h" #include "main.h" @@ -42,22 +46,32 @@ #include "ttyio.h" #include "status.h" #include "i18n.h" +#include "keyserver-internal.h" -static void show_prefs( PKT_user_id *uid, int verbose ); +static void show_prefs( PKT_user_id *uid, PKT_signature *selfsig, int verbose); +static void show_names(KBNODE keyblock,PKT_public_key *pk, + unsigned int flag,int with_prefs); static void show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, int with_fpr, int with_subkeys, int with_prefs ); static void show_key_and_fingerprint( KBNODE keyblock ); -static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo ); +static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, + int photo, const char *photo_name ); static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_delsig( KBNODE pub_keyblock ); +static int menu_delsig( KBNODE pub_keyblock ); +static int menu_clean(KBNODE keyblock,int self_only); static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ); static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock); static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock ); -static int menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_keyserver_url (const char *url, + KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_notation(const char *string, + KBNODE pub_keyblock,KBNODE sec_keyblock); static int menu_select_uid( KBNODE keyblock, int idx ); +static int menu_select_uid_namehash( KBNODE keyblock, const char *namehash ); static int menu_select_key( KBNODE keyblock, int idx ); static int count_uids( KBNODE keyblock ); static int count_uids_with_flag( KBNODE keyblock, unsigned flag ); @@ -68,6 +82,7 @@ static int count_selected_keys( KBNODE keyblock ); static int menu_revsig( KBNODE keyblock ); static int menu_revuid( KBNODE keyblock, KBNODE sec_keyblock ); static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_revsubkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int enable_disable_key( KBNODE keyblock, int disable ); static void menu_showphoto( KBNODE keyblock ); @@ -93,6 +108,100 @@ struct sign_attrib { char *trust_regexp; }; + +#ifdef ENABLE_CARD_SUPPORT +/* Given a node SEC_NODE with a secret key or subkey, locate the + corresponding public key from pub_keyblock. */ +static PKT_public_key * +find_pk_from_sknode (KBNODE pub_keyblock, KBNODE sec_node) +{ + KBNODE node = pub_keyblock; + PKT_secret_key *sk; + PKT_public_key *pk; + + if (sec_node->pkt->pkttype == PKT_SECRET_KEY + && node->pkt->pkttype == PKT_PUBLIC_KEY) + return node->pkt->pkt.public_key; + if (sec_node->pkt->pkttype != PKT_SECRET_SUBKEY) + return NULL; + sk = sec_node->pkt->pkt.secret_key; + for (; node; node = node->next) + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + pk = node->pkt->pkt.public_key; + if (pk->keyid[0] == sk->keyid[0] && pk->keyid[1] == sk->keyid[1]) + return pk; + } + + return NULL; +} +#endif /* ENABLE_CARD_SUPPORT */ + + +/* TODO: Fix duplicated code between here and the check-sigs/list-sigs + code in keylist.c. */ +static int +print_and_check_one_sig_colon( KBNODE keyblock, KBNODE node, + int *inv_sigs, int *no_key, int *oth_err, + int *is_selfsig, int print_without_key ) +{ + PKT_signature *sig = node->pkt->pkt.signature; + int rc, sigrc; + + /* TODO: Make sure a cached sig record here still has the pk that + issued it. See also keylist.c:list_keyblock_print */ + + switch((rc=check_key_signature(keyblock,node,is_selfsig))) + { + case 0: + node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); + sigrc = '!'; + break; + case G10ERR_BAD_SIGN: + node->flag = NODFLG_BADSIG; + sigrc = '-'; + if( inv_sigs ) + ++*inv_sigs; + break; + case G10ERR_NO_PUBKEY: + case G10ERR_UNU_PUBKEY: + node->flag = NODFLG_NOKEY; + sigrc = '?'; + if( no_key ) + ++*no_key; + break; + default: + node->flag = NODFLG_SIGERR; + sigrc = '%'; + if( oth_err ) + ++*oth_err; + break; + } + + if( sigrc != '?' || print_without_key ) + { + printf("sig:%c::%d:%08lX%08lX:%lu:%lu:", + sigrc,sig->pubkey_algo,(ulong)sig->keyid[0],(ulong)sig->keyid[1], + (ulong)sig->timestamp,(ulong)sig->expiredate); + + if(sig->trust_depth || sig->trust_value) + printf("%d %d",sig->trust_depth,sig->trust_value); + + printf(":"); + + if(sig->trust_regexp) + print_string(stdout,sig->trust_regexp,strlen(sig->trust_regexp),':'); + + printf("::%02x%c\n",sig->sig_class,sig->flags.exportable?'x':'l'); + + if(opt.show_subpackets) + print_subpackets_colon(sig); + } + + return (sigrc == '!'); +} + + /**************** * Print information about a signature, check it and return true * if the signature is okay. NODE must be a signature packet. @@ -109,20 +218,19 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, /* TODO: Make sure a cached sig record here still has the pk that issued it. See also keylist.c:list_keyblock_print */ - rc = check_key_signature (keyblock, node, is_selfsig); - switch ( gpg_err_code (rc) ) { + switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) { case 0: node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR); sigrc = '!'; break; - case GPG_ERR_BAD_SIGNATURE: + case G10ERR_BAD_SIGN: node->flag = NODFLG_BADSIG; sigrc = '-'; if( inv_sigs ) ++*inv_sigs; break; - case GPG_ERR_NO_PUBKEY: - case GPG_ERR_UNUSABLE_PUBKEY: + case G10ERR_NO_PUBKEY: + case G10ERR_UNU_PUBKEY: node->flag = NODFLG_NOKEY; sigrc = '?'; if( no_key ) @@ -136,7 +244,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, break; } if( sigrc != '?' || print_without_key ) { - tty_printf("%s%c%c %c%c%c%c%c%c ", + tty_printf("%s%c%c %c%c%c%c%c%c %s %s", is_rev? "rev":"sig",sigrc, (sig->sig_class-0x10>0 && sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', @@ -146,38 +254,38 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, sig->flags.notation?'N':' ', sig->flags.expired?'X':' ', (sig->trust_depth>9)?'T': - (sig->trust_depth>0)?'0'+sig->trust_depth:' '); - if(opt.list_options&LIST_SHOW_LONG_KEYID) - tty_printf("%08lX%08lX",(ulong)sig->keyid[0],(ulong)sig->keyid[1]); - else - tty_printf("%08lX",(ulong)sig->keyid[1]); - tty_printf(" %s", datestr_from_sig(sig)); + (sig->trust_depth>0)?'0'+sig->trust_depth:' ', + keystr(sig->keyid),datestr_from_sig(sig)); if(opt.list_options&LIST_SHOW_SIG_EXPIRE) tty_printf(" %s",expirestr_from_sig(sig)); tty_printf(" "); if( sigrc == '%' ) - tty_printf("[%s] ", gpg_strerror (rc) ); + tty_printf("[%s] ", g10_errstr(rc) ); else if( sigrc == '?' ) ; else if( *is_selfsig ) { tty_printf( is_rev? _("[revocation]") : _("[self-signature]") ); } - else { + else + { size_t n; char *p = get_user_id( sig->keyid, &n ); - tty_print_utf8_string2( p, n, 40 ); - xfree (p); - } + tty_print_utf8_string2(p, n, opt.screen_columns-keystrlen()-26- + ((opt.list_options&LIST_SHOW_SIG_EXPIRE)?11:0)); + xfree(p); + } tty_printf("\n"); - if(sig->flags.policy_url && (opt.list_options&LIST_SHOW_POLICY)) + if(sig->flags.policy_url && (opt.list_options&LIST_SHOW_POLICY_URLS)) show_policy_url(sig,3,0); - if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) - show_notation(sig,3,0); + if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS)) + show_notation(sig,3,0, + ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+ + ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0)); - if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER_URLS)) show_keyserver_url(sig,3,0); } @@ -256,8 +364,6 @@ check_all_keysigs( KBNODE keyblock, int only_selected ) } - - static int sign_mk_attrib( PKT_signature *sig, void *opaque ) { @@ -298,7 +404,7 @@ sign_mk_attrib( PKT_signature *sig, void *opaque ) } static void -trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) +trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp) { char *p; @@ -306,14 +412,13 @@ trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) *trust_depth=0; *regexp=NULL; - tty_printf("\n"); /* Same string as pkclist.c:do_edit_ownertrust */ - tty_printf(_( - "Please decide how far you trust this user to correctly\n" - "verify other users' keys (by looking at passports,\n" - "checking fingerprints from different sources...)?\n\n")); - tty_printf (_(" (%d) I trust marginally\n"), 1); - tty_printf (_(" (%d) I trust fully\n"), 2); + tty_printf(_("Please decide how far you trust this user to correctly verify" + " other users' keys\n(by looking at passports, checking" + " fingerprints from different sources, etc.)\n")); + tty_printf("\n"); + tty_printf (_(" %d = I trust marginally\n"), 1); + tty_printf (_(" %d = I trust fully\n"), 2); tty_printf("\n"); while(*trust_value==0) @@ -326,7 +431,7 @@ trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) *trust_value=60; else if(p[0]=='2' && !p[1]) *trust_value=120; - xfree (p); + xfree(p); } tty_printf("\n"); @@ -343,9 +448,7 @@ trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) trim_spaces(p); cpr_kill_prompt(); *trust_depth=atoi(p); - xfree (p); - if(*trust_depth < 1 ) - *trust_depth=0; + xfree(p); } tty_printf("\n"); @@ -364,7 +467,7 @@ trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) char *q=p; int regexplen=100,ind; - *regexp=xmalloc (regexplen); + *regexp=xmalloc(regexplen); /* Now mangle the domain the user entered into a regexp. To do this, \-escape everything that isn't alphanumeric, and attach @@ -394,7 +497,7 @@ trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) strcat(*regexp,">$"); } - xfree (p); + xfree(p); tty_printf("\n"); } @@ -405,7 +508,7 @@ trustsig_prompt(byte *trust_value, byte *trust_depth, char **regexp) */ static int sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, - int local, int nonrevocable, int trust ) + int local, int nonrevocable, int trust, int interactive ) { int rc = 0; SK_LIST sk_list = NULL; @@ -413,7 +516,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, PKT_secret_key *sk = NULL; KBNODE node, uidnode; PKT_public_key *primary_pk=NULL; - int select_all = !count_selected_uids(keyblock); + int select_all = !count_selected_uids(keyblock) || interactive; int all_v3=1; /* Are there any non-v3 sigs on this key already? */ @@ -432,22 +535,21 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, * be one which is capable of signing keys. I can't see a reason * why to sign keys using a subkey. Implementation of USAGE_CERT * is just a hack in getkey.c and does not mean that a subkey - * marked as certification capable will be used */ - rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT); + * marked as certification capable will be used. */ + rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_CERT); if( rc ) goto leave; /* loop over all signators */ for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { u32 sk_keyid[2],pk_keyid[2]; - size_t n; char *p,*trust_regexp=NULL; int force_v4=0,class=0,selfsig=0; u32 duration=0,timestamp=0; byte trust_depth=0,trust_value=0; if(local || nonrevocable || trust || - opt.cert_policy_url || opt.cert_notation_data) + opt.cert_policy_url || opt.cert_notations) force_v4=1; /* we have to use a copy of the sk, because make_keysig_packet @@ -483,10 +585,12 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, force_v4=0; } } - else if( node->pkt->pkttype == PKT_USER_ID ) { + else if( node->pkt->pkttype == PKT_USER_ID ) + { uidnode = (node->flag & NODFLG_MARK_A)? node : NULL; if(uidnode) { + int yesreally=0; char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, uidnode->pkt->pkt.user_id->len, 0); @@ -495,7 +599,9 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, { tty_printf(_("User ID \"%s\" is revoked."),user); - if(opt.expert) + if(selfsig) + tty_printf("\n"); + else if(opt.expert) { tty_printf("\n"); /* No, so remove the mark and continue */ @@ -503,11 +609,17 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, _("Are you sure you " "still want to sign " "it? (y/N) "))) - uidnode->flag &= ~NODFLG_MARK_A; + { + uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; + } + else if(interactive) + yesreally=1; } else { uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; tty_printf(_(" Unable to sign.\n")); } } @@ -515,7 +627,9 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, { tty_printf(_("User ID \"%s\" is expired."),user); - if(opt.expert) + if(selfsig) + tty_printf("\n"); + else if(opt.expert) { tty_printf("\n"); /* No, so remove the mark and continue */ @@ -523,11 +637,17 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, _("Are you sure you " "still want to sign " "it? (y/N) "))) - uidnode->flag &= ~NODFLG_MARK_A; + { + uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; + } + else if(interactive) + yesreally=1; } else { uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; tty_printf(_(" Unable to sign.\n")); } } @@ -544,17 +664,35 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, _("Are you sure you " "still want to sign " "it? (y/N) "))) - uidnode->flag &= ~NODFLG_MARK_A; + { + uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; + } + else if(interactive) + yesreally=1; } else { uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; tty_printf(_(" Unable to sign.\n")); } - } - xfree (user); + } + + if(uidnode && interactive && !yesreally) + { + tty_printf(_("User ID \"%s\" is signable. "),user); + if(!cpr_get_answer_is_yes("sign_uid.sign_okay", + _("Sign it? (y/N) "))) + { + uidnode->flag &= ~NODFLG_MARK_A; + uidnode=NULL; + } + } + + xfree(user); } - } + } else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) { if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0] @@ -582,7 +720,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, { force_v4=1; node->flag|=NODFLG_DELSIG; - xfree (user); + xfree(user); continue; } } @@ -606,7 +744,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, in place. */ node->flag|=NODFLG_DELSIG; - xfree (user); + xfree(user); continue; } } @@ -631,7 +769,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, in place. */ node->flag|=NODFLG_DELSIG; - xfree (user); + xfree(user); continue; } } @@ -640,12 +778,11 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, * case we should allow to sign it again. */ if (!node->pkt->pkt.signature->flags.exportable && local) tty_printf(_( - "\"%s\" was already locally signed by key %08lX\n"), - user,(ulong)sk_keyid[1] ); + "\"%s\" was already locally signed by key %s\n"), + user,keystr_from_sk(sk)); else - tty_printf(_( - "\"%s\" was already signed by key %08lX\n"), - user,(ulong)sk_keyid[1] ); + tty_printf(_("\"%s\" was already signed by key %s\n"), + user,keystr_from_sk(sk)); if(opt.expert && cpr_get_answer_is_yes("sign_uid.dupe_okay", @@ -654,7 +791,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, { /* Don't delete the old sig here since this is an --expert thing. */ - xfree (user); + xfree(user); continue; } @@ -663,16 +800,18 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, write_status_text (STATUS_ALREADY_SIGNED, buf); uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */ - xfree (user); + xfree(user); } } } + /* check whether any uids are left for signing */ - if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) { - tty_printf(_("Nothing to sign with key %08lX\n"), - (ulong)sk_keyid[1] ); + if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) + { + tty_printf(_("Nothing to sign with key %s\n"),keystr_from_sk(sk)); continue; - } + } + /* Ask whether we really should sign these user id(s) */ tty_printf("\n"); show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 ); @@ -702,35 +841,42 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, } else { - char *answer; - tty_printf(_("This key is due to expire on %s.\n"), expirestr_from_pk(primary_pk)); - answer=cpr_get("sign_uid.expire", - _("Do you want your signature to " - "expire at the same time? (Y/n) ")); - if(answer_is_yes_no_default(answer,1)) + if(opt.ask_cert_expire) { - /* This fixes the signature timestamp we're going - to make as now. This is so the expiration date - is exactly correct, and not a few seconds off - (due to the time it takes to answer the - questions, enter the passphrase, etc). */ - timestamp=now; - duration=primary_pk->expiredate-now; - force_v4=1; - } + char *answer=cpr_get("sign_uid.expire", + _("Do you want your signature to " + "expire at the same time? (Y/n) ")); + if(answer_is_yes_no_default(answer,1)) + { + /* This fixes the signature timestamp we're + going to make as now. This is so the + expiration date is exactly correct, and not + a few seconds off (due to the time it takes + to answer the questions, enter the + passphrase, etc). */ + timestamp=now; + duration=primary_pk->expiredate-now; + force_v4=1; + } - cpr_kill_prompt(); - xfree (answer); + cpr_kill_prompt(); + xfree(answer); + } } } /* Only ask for duration if we haven't already set it to match the expiration of the pk */ - if(opt.ask_cert_expire && !duration && !selfsig) - duration=ask_expire_interval(1); + if(!duration && !selfsig) + { + if(opt.ask_cert_expire) + duration=ask_expire_interval(1,opt.def_cert_expire); + else + duration=parse_expire_string(opt.def_cert_expire); + } if(duration) force_v4=1; @@ -762,8 +908,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, ; else { - if(opt.batch) - class=0x10+opt.def_cert_check_level; + if(opt.batch || !opt.ask_cert_level) + class=0x10+opt.def_cert_level; else { char *answer; @@ -774,22 +920,21 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, "answer, enter \"0\".\n")); tty_printf("\n"); tty_printf(_(" (0) I will not answer.%s\n"), - opt.def_cert_check_level==0?" (default)":""); + opt.def_cert_level==0?" (default)":""); tty_printf(_(" (1) I have not checked at all.%s\n"), - opt.def_cert_check_level==1?" (default)":""); + opt.def_cert_level==1?" (default)":""); tty_printf(_(" (2) I have done casual checking.%s\n"), - opt.def_cert_check_level==2?" (default)":""); + opt.def_cert_level==2?" (default)":""); tty_printf(_(" (3) I have done very careful checking.%s\n"), - opt.def_cert_check_level==3?" (default)":""); + opt.def_cert_level==3?" (default)":""); tty_printf("\n"); while(class==0) { answer = cpr_get("sign_uid.class",_("Your selection? " - "(enter '?' for more information): ")); - + "(enter `?' for more information): ")); if(answer[0]=='\0') - class=0x10+opt.def_cert_check_level; /* Default */ + class=0x10+opt.def_cert_level; /* Default */ else if(ascii_strcasecmp(answer,"0")==0) class=0x10; /* Generic */ else if(ascii_strcasecmp(answer,"1")==0) @@ -801,7 +946,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, else tty_printf(_("Invalid selection.\n")); - xfree (answer); + xfree(answer); } } @@ -809,49 +954,63 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, trustsig_prompt(&trust_value,&trust_depth,&trust_regexp); } - tty_printf(_("Are you really sure that you want to sign this key\n" - "with your key: \"")); - p = get_user_id( sk_keyid, &n ); - tty_print_utf8_string( p, n ); - xfree (p); p = NULL; - tty_printf("\" (%08lX)\n",(ulong)sk_keyid[1]); + p=get_user_id_native(sk_keyid); + tty_printf(_("Are you sure that you want to sign this key with your\n" + "key \"%s\" (%s)\n"),p,keystr_from_sk(sk)); + xfree(p); if(selfsig) { - tty_printf(_("\nThis will be a self-signature.\n")); + tty_printf("\n"); + tty_printf(_("This will be a self-signature.\n")); if( local ) - tty_printf( - _("\nWARNING: the signature will not be marked " + { + tty_printf("\n"); + tty_printf( + _("WARNING: the signature will not be marked " "as non-exportable.\n")); + } if( nonrevocable ) - tty_printf( - _("\nWARNING: the signature will not be marked " + { + tty_printf("\n"); + tty_printf( + _("WARNING: the signature will not be marked " "as non-revocable.\n")); + } } else { if( local ) - tty_printf( - _("\nThe signature will be marked as non-exportable.\n")); + { + tty_printf("\n"); + tty_printf( + _("The signature will be marked as non-exportable.\n")); + } if( nonrevocable ) - tty_printf( - _("\nThe signature will be marked as non-revocable.\n")); + { + tty_printf("\n"); + tty_printf( + _("The signature will be marked as non-revocable.\n")); + } switch(class) { case 0x11: - tty_printf(_("\nI have not checked this key at all.\n")); + tty_printf("\n"); + tty_printf(_("I have not checked this key at all.\n")); break; case 0x12: - tty_printf(_("\nI have checked this key casually.\n")); + tty_printf("\n"); + tty_printf(_("I have checked this key casually.\n")); break; case 0x13: - tty_printf(_("\nI have checked this key very carefully.\n")); + tty_printf("\n"); + tty_printf(_("I have checked this key very carefully.\n")); break; } } @@ -860,7 +1019,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, if( opt.batch && opt.answer_yes ) ; - else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) ) + else if( !cpr_get_answer_is_yes("sign_uid.okay", + _("Really sign? (y/N) ")) ) continue; /* now we can sign the user ids */ @@ -905,14 +1065,14 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, timestamp, duration, sign_mk_attrib, &attrib ); if( rc ) { - log_error(_("signing failed: %s\n"), gpg_strerror (rc)); + log_error(_("signing failed: %s\n"), g10_errstr(rc)); goto leave; } *ret_modified = 1; /* we changed the keyblock */ update_trust = 1; - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE ); @@ -948,6 +1108,7 @@ change_passphrase( KBNODE keyblock ) PKT_secret_key *sk; char *passphrase = NULL; int no_primary_secrets = 0; + int any; node = find_kbnode( keyblock, PKT_SECRET_KEY ); if( !node ) { @@ -956,9 +1117,28 @@ change_passphrase( KBNODE keyblock ) } sk = node->pkt->pkt.secret_key; + for (any = 0, node=keyblock; node; node = node->next) { + if (node->pkt->pkttype == PKT_SECRET_KEY + || node->pkt->pkttype == PKT_SECRET_SUBKEY) { + PKT_secret_key *tmpsk = node->pkt->pkt.secret_key; + if (!(tmpsk->is_protected + && (tmpsk->protect.s2k.mode == 1001 + || tmpsk->protect.s2k.mode == 1002))) { + any = 1; + break; + } + } + } + if (!any) { + tty_printf (_("Key has only stub or on-card key items - " + "no passphrase to change.\n")); + goto leave; + } + + /* See how to handle this key. */ switch( is_secret_key_protected( sk ) ) { case -1: - rc = GPG_ERR_PUBKEY_ALGO; + rc = G10ERR_PUBKEY_ALGO; break; case 0: tty_printf(_("This key is not protected.\n")); @@ -969,8 +1149,8 @@ change_passphrase( KBNODE keyblock ) no_primary_secrets = 1; } else if( sk->protect.s2k.mode == 1002 ) { - tty_printf(_("Secret key is actually stored on a card.\n")); - goto leave; + tty_printf(_("Secret parts of primary key are stored on-card.\n")); + no_primary_secrets = 1; } else { tty_printf(_("Key is protected.\n")); @@ -981,22 +1161,26 @@ change_passphrase( KBNODE keyblock ) break; } - /* unprotect all subkeys (use the supplied passphrase or ask)*/ + /* Unprotect all subkeys (use the supplied passphrase or ask)*/ for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; - set_next_passphrase( passphrase ); - rc = check_secret_key( subsk, 0 ); - if( !rc && !passphrase ) - passphrase = get_last_passphrase(); + if ( !(subsk->is_protected + && (subsk->protect.s2k.mode == 1001 + || subsk->protect.s2k.mode == 1002))) { + set_next_passphrase( passphrase ); + rc = check_secret_key( subsk, 0 ); + if( !rc && !passphrase ) + passphrase = get_last_passphrase(); + } } } if( rc ) - tty_printf(_("Can't edit this key: %s\n"), gpg_strerror (rc)); + tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc)); else { DEK *dek = NULL; - STRING2KEY *s2k = xmalloc_secure ( sizeof *s2k ); + STRING2KEY *s2k = xmalloc_secure( sizeof *s2k ); const char *errtext = NULL; tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); @@ -1004,7 +1188,7 @@ change_passphrase( KBNODE keyblock ) set_next_passphrase( NULL ); for(;;) { s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; + s2k->hash_algo = S2K_DIGEST_ALGO; dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, errtext, NULL); if( !dek ) { @@ -1016,11 +1200,11 @@ change_passphrase( KBNODE keyblock ) tty_printf(_( "You don't want a passphrase -" " this is probably a *bad* idea!\n\n")); if( cpr_get_answer_is_yes("change_passwd.empty.okay", - _("Do you really want to do this? "))) - { + _("Do you really want to do this? (y/N) "))) + { changed++; - break; - } + break; + } } else { /* okay */ rc = 0; @@ -1032,24 +1216,29 @@ change_passphrase( KBNODE keyblock ) for(node=keyblock; !rc && node; node = node->next ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *subsk = node->pkt->pkt.secret_key; - subsk->protect.algo = dek->algo; - subsk->protect.s2k = *s2k; - rc = protect_secret_key( subsk, dek ); + if ( !(subsk->is_protected + && (subsk->protect.s2k.mode == 1001 + || subsk->protect.s2k.mode == 1002))) { + subsk->protect.algo = dek->algo; + subsk->protect.s2k = *s2k; + rc = protect_secret_key( subsk, dek ); + } } } if( rc ) - log_error("protect_secret_key failed: %s\n", gpg_strerror (rc) ); + log_error("protect_secret_key failed: %s\n", + g10_errstr(rc) ); else changed++; break; } } - xfree (s2k); - xfree (dek); + xfree(s2k); + xfree(dek); } leave: - xfree ( passphrase ); + xfree( passphrase ); set_next_passphrase( NULL ); return changed && !rc; } @@ -1098,84 +1287,223 @@ fix_keyblock( KBNODE keyblock ) return fixed; } +static int +parse_sign_type(const char *str,int *localsig,int *nonrevokesig,int *trustsig) +{ + const char *p=str; + + while(*p) + { + if(ascii_strncasecmp(p,"l",1)==0) + { + *localsig=1; + p++; + } + else if(ascii_strncasecmp(p,"nr",2)==0) + { + *nonrevokesig=1; + p+=2; + } + else if(ascii_strncasecmp(p,"t",1)==0) + { + *trustsig=1; + p++; + } + else + return 0; + } + + return 1; +} + + /**************** - * Menu driven key editor. If sign_mode is true semi-automatical signing - * will be performed. commands are ignore in this case + * Menu driven key editor. If seckey_check is true, then a secret key + * that matches username will be looked for. If it is false, not all + * commands will be available. * * Note: to keep track of some selection we use node->mark MARKBIT_xxxx. */ +/* Need an SK for this command */ +#define KEYEDIT_NEED_SK 1 +/* Cannot be viewing the SK for this command */ +#define KEYEDIT_NOT_SK 2 +/* Must be viewing the SK for this command */ +#define KEYEDIT_ONLY_SK 4 +/* Match the tail of the string */ +#define KEYEDIT_TAIL_MATCH 8 + +enum cmdids + { + cmdNONE = 0, + cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, + cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, + cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, + cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, + cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, + cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, + cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN, + cmdMINIMIZE, cmdNOP + }; + +static struct +{ + const char *name; + enum cmdids id; + int flags; + const char *desc; +} cmds[] = + { + { "quit" , cmdQUIT , 0, N_("quit this menu") }, + { "q" , cmdQUIT , 0, NULL }, + { "save" , cmdSAVE , 0, N_("save and quit") }, + { "help" , cmdHELP , 0, N_("show this help") }, + { "?" , cmdHELP , 0, NULL }, + { "fpr" , cmdFPR , 0, N_("show key fingerprint") }, + { "list" , cmdLIST , 0, N_("list key and user IDs") }, + { "l" , cmdLIST , 0, NULL }, + { "uid" , cmdSELUID , 0, N_("select user ID N") }, + { "key" , cmdSELKEY , 0, N_("select subkey N") }, + { "check" , cmdCHECK , 0, N_("check signatures") }, + { "c" , cmdCHECK , 0, NULL }, + { "cross-certify", cmdBACKSIGN , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + { "backsign", cmdBACKSIGN , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + { "sign" , cmdSIGN , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH, + N_("sign selected user IDs [* see below for related commands]") }, + { "s" , cmdSIGN , KEYEDIT_NOT_SK, NULL }, + /* "lsign" and friends will never match since "sign" comes first + and it is a tail match. They are just here so they show up in + the help menu. */ + { "lsign" , cmdNOP , 0, N_("sign selected user IDs locally") }, + { "tsign" , cmdNOP , 0, + N_("sign selected user IDs with a trust signature") }, + { "nrsign" , cmdNOP , 0, + N_("sign selected user IDs with a non-revocable signature") }, + + { "debug" , cmdDEBUG , 0, NULL }, + { "adduid" , cmdADDUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("add a user ID") }, + { "addphoto", cmdADDPHOTO , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("add a photo ID") }, + { "deluid" , cmdDELUID , KEYEDIT_NOT_SK, + N_("delete selected user IDs") }, + /* delphoto is really deluid in disguise */ + { "delphoto", cmdDELUID , KEYEDIT_NOT_SK, NULL }, + + { "addkey" , cmdADDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("add a subkey") }, + +#ifdef ENABLE_CARD_SUPPORT + { "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("add a key to a smartcard") }, + { "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, + N_("move a key to a smartcard")}, + { "bkuptocard", cmdBKUPTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, + N_("move a backup key to a smartcard")}, +#endif /*ENABLE_CARD_SUPPORT*/ + + { "delkey" , cmdDELKEY , KEYEDIT_NOT_SK, + N_("delete selected subkeys") }, + { "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("add a revocation key") }, + { "delsig" , cmdDELSIG , KEYEDIT_NOT_SK, + N_("delete signatures from the selected user IDs") }, + { "expire" , cmdEXPIRE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("change the expiration date for the key or selected subkeys") }, + { "primary" , cmdPRIMARY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("flag the selected user ID as primary")}, + { "toggle" , cmdTOGGLE , KEYEDIT_NEED_SK, + N_("toggle between the secret and public key listings") }, + { "t" , cmdTOGGLE , KEYEDIT_NEED_SK, NULL }, + { "pref" , cmdPREF , KEYEDIT_NOT_SK, + N_("list preferences (expert)")}, + { "showpref", cmdSHOWPREF , KEYEDIT_NOT_SK, + N_("list preferences (verbose)") }, + { "setpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("set preference list for the selected user IDs") }, + /* Alias */ + { "updpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + + { "keyserver",cmdPREFKS , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("set the preferred keyserver URL for the selected user IDs")}, + { "notation", cmdNOTATION , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("set a notation for the selected user IDs")}, + { "passwd" , cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("change the passphrase") }, + /* Alias */ + { "password", cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + + { "trust" , cmdTRUST , KEYEDIT_NOT_SK, N_("change the ownertrust") }, + { "revsig" , cmdREVSIG , KEYEDIT_NOT_SK, + N_("revoke signatures on the selected user IDs") }, + { "revuid" , cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("revoke selected user IDs") }, + /* Alias */ + { "revphoto", cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL }, + + { "revkey" , cmdREVKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, + N_("revoke key or selected subkeys") }, + { "enable" , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") }, + { "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") }, + { "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") }, + { "clean", cmdCLEAN , KEYEDIT_NOT_SK, + N_("compact unusable user IDs and remove unusable signatures from key")}, + { "minimize", cmdMINIMIZE , KEYEDIT_NOT_SK, + N_("compact unusable user IDs and remove all signatures from key") }, + { NULL, cmdNONE, 0, NULL } + }; + +#ifdef HAVE_LIBREADLINE + +/* These two functions are used by readline for command completion. */ + +static char * +command_generator(const char *text,int state) +{ + static int list_index,len; + const char *name; + + /* If this is a new word to complete, initialize now. This includes + saving the length of TEXT for efficiency, and initializing the + index variable to 0. */ + if(!state) + { + list_index=0; + len=strlen(text); + } + + /* Return the next partial match */ + while((name=cmds[list_index].name)) + { + /* Only complete commands that have help text */ + if(cmds[list_index++].desc && strncmp(name,text,len)==0) + return strdup(name); + } + + return NULL; +} + +static char ** +keyedit_completion(const char *text, int start, int end) +{ + /* If we are at the start of a line, we try and command-complete. + If not, just do nothing for now. */ + + if(start==0) + return rl_completion_matches(text,command_generator); + + rl_attempted_completion_over=1; + + return NULL; +} +#endif /* HAVE_LIBREADLINE */ + + void -keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, - int sign_mode ) +keyedit_menu( const char *username, STRLIST locusr, + STRLIST commands, int quiet, int seckey_check ) { - enum cmdids { cmdNONE = 0, - cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN, - cmdTSIGN, cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY, - cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, - cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER, - cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, - cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, - cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, - cmdNOP }; - static struct { const char *name; - enum cmdids id; - int need_sk; - int not_with_sk; - int signmode; - const char *desc; - } cmds[] = { - { N_("quit") , cmdQUIT , 0,0,1, N_("quit this menu") }, - { N_("q") , cmdQUIT , 0,0,1, NULL }, - { N_("save") , cmdSAVE , 0,0,1, N_("save and quit") }, - { N_("help") , cmdHELP , 0,0,1, N_("show this help") }, - { "?" , cmdHELP , 0,0,1, NULL }, - { N_("fpr") , cmdFPR , 0,0,1, N_("show fingerprint") }, - { N_("list") , cmdLIST , 0,0,1, N_("list key and user IDs") }, - { N_("l") , cmdLIST , 0,0,1, NULL }, - { N_("uid") , cmdSELUID , 0,0,1, N_("select user ID N") }, - { N_("key") , cmdSELKEY , 0,0,0, N_("select secondary key N") }, - { N_("check") , cmdCHECK , 0,0,1, N_("list signatures") }, - { N_("c") , cmdCHECK , 0,0,1, NULL }, - { N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") }, - { N_("s") , cmdSIGN , 0,1,1, NULL }, - { N_("tsign") , cmdTSIGN , 0,1,1, N_("make a trust signature")}, - { N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") }, - { N_("nrsign") , cmdNRSIGN , 0,1,1, N_("sign the key non-revocably") }, - { N_("nrlsign") , cmdNRLSIGN , 0,1,1, N_("sign the key locally and non-revocably") }, - { N_("debug") , cmdDEBUG , 0,0,0, NULL }, - { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") }, - { N_("addphoto"), cmdADDPHOTO , 1,1,0, N_("add a photo ID") }, - { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") }, - /* delphoto is really deluid in disguise */ - { N_("delphoto"), cmdDELUID , 0,1,0, NULL }, - { N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") }, - { N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") }, - { N_("addrevoker"),cmdADDREVOKER,1,1,0, N_("add a revocation key") }, - { N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") }, - { N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") }, - { N_("primary") , cmdPRIMARY , 1,1,0, N_("flag user ID as primary")}, - { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret " - "and public key listing") }, - { N_("t" ) , cmdTOGGLE , 1,0,0, NULL }, - { N_("pref") , cmdPREF , 0,1,0, - N_("list preferences (expert)")}, - { N_("showpref"), cmdSHOWPREF , 0,1,0, - N_("list preferences (verbose)")}, - { N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") }, - { N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") }, - { N_("keyserver"),cmdPREFKS , 1,1,0, - N_("set preferred keyserver URL")}, - { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") }, - { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") }, - { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") }, - { N_("revuid") , cmdREVUID , 1,1,0, N_("revoke a user ID") }, - { N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") }, - { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") }, - { N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") }, - { N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") }, - - { NULL, cmdNONE } }; enum cmdids cmd = 0; int rc = 0; KBNODE keyblock = NULL; @@ -1192,20 +1520,26 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, if ( opt.command_fd != -1 ) ; - else if( opt.batch && !have_commands ) { - log_error(_("can't do that in batchmode\n")); + else if( opt.batch && !have_commands ) + { + log_error(_("can't do this in batch mode\n")); goto leave; - } - - if( sign_mode ) { - commands = NULL; - append_to_strlist( &commands, sign_mode == 1? "sign": - sign_mode == 2?"lsign": - sign_mode == 3?"nrsign":"nrlsign"); - have_commands = 1; - } + } - /* get the public key */ +#ifdef HAVE_W32_SYSTEM + /* Due to Windows peculiarities we need to make sure that the + trustdb stale check is done before we open another file + (i.e. by searching for a key). In theory we could make sure + that the files are closed after use but the open/close caches + inhibits that and flushing the cache right before the stale + check is not easy to implement. Thus we take the easy way out + and run the stale check as early as possible. Note, that for + non- W32 platforms it is run indirectly trough a call to + get_validity (). */ + check_trustdb_stale (); +#endif + + /* Get the public key */ rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1); if( rc ) goto leave; @@ -1215,7 +1549,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, modified++; reorder_keyblock(keyblock); - if( !sign_mode ) {/* see whether we have a matching secret key */ + if(seckey_check) + {/* see whether we have a matching secret key */ PKT_public_key *pk = keyblock->pkt->pkt.public_key; sec_kdbhd = keydb_new (1); @@ -1228,28 +1563,30 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, afp[an++] = 0; rc = keydb_search_fpr (sec_kdbhd, afp); } - if (!rc) { + if (!rc) + { rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock); - if (rc) { - log_error (_("error reading secret keyblock `%s': %s\n"), - username, gpg_strerror (rc)); - } - else { + if (rc) + { + log_error (_("error reading secret keyblock \"%s\": %s\n"), + username, g10_errstr(rc)); + } + else + { merge_keys_and_selfsig( sec_keyblock ); if( fix_keyblock( sec_keyblock ) ) - sec_modified++; - } - } + sec_modified++; + } + } if (rc) { sec_keyblock = NULL; keydb_release (sec_kdbhd); sec_kdbhd = NULL; rc = 0; } - } - if( sec_keyblock ) { - tty_printf(_("Secret key is available.\n")); + if( sec_keyblock && !quiet ) + tty_printf(_("Secret key is available.\n")); } toggle = 0; @@ -1261,28 +1598,33 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, PKT_public_key *pk=keyblock->pkt->pkt.public_key; tty_printf("\n"); - if( redisplay ) { + + if( redisplay && !quiet ) + { show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 ); tty_printf("\n"); redisplay = 0; - } + } do { - xfree (answer); + xfree(answer); if( have_commands ) { if( commands ) { - answer = xstrdup ( commands->d ); + answer = xstrdup( commands->d ); commands = commands->next; } else if( opt.batch ) { - answer = xstrdup ("quit"); + answer = xstrdup("quit"); } else have_commands = 0; } - if( !have_commands ) { + if( !have_commands ) + { + tty_enable_completion(keyedit_completion); answer = cpr_get_no_help("keyedit.prompt", _("Command> ")); cpr_kill_prompt(); - } + tty_disable_completion(); + } trim_spaces(answer); } while( *answer == '#' ); @@ -1292,7 +1634,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, cmd = cmdLIST; else if( *answer == CONTROL_D ) cmd = cmdQUIT; - else if( digitp( answer ) ) { + else if( digitp(answer ) ) { cmd = cmdSELUID; arg_number = atoi(answer); } @@ -1305,33 +1647,58 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, arg_string = p; } - for(i=0; cmds[i].name; i++ ) { - if( !ascii_strcasecmp( answer, cmds[i].name ) ) - break; - } - if( sign_mode && !cmds[i].signmode ) - cmd = cmdINVCMD; - else if( cmds[i].need_sk && !sec_keyblock ) { + for(i=0; cmds[i].name; i++ ) + { + if(cmds[i].flags & KEYEDIT_TAIL_MATCH) + { + size_t l=strlen(cmds[i].name); + size_t a=strlen(answer); + if(a>=l) + { + if(ascii_strcasecmp(&answer[a-l],cmds[i].name)==0) + { + answer[a-l]='\0'; + break; + } + } + } + else if( !ascii_strcasecmp( answer, cmds[i].name ) ) + break; + } + if((cmds[i].flags & KEYEDIT_NEED_SK) && !sec_keyblock ) + { tty_printf(_("Need the secret key to do this.\n")); cmd = cmdNOP; - } - else if( cmds[i].not_with_sk && sec_keyblock && toggle ) { + } + else if(((cmds[i].flags & KEYEDIT_NOT_SK) && sec_keyblock + && toggle) + ||((cmds[i].flags & KEYEDIT_ONLY_SK) && sec_keyblock + && !toggle)) + { tty_printf(_("Please use the command \"toggle\" first.\n")); cmd = cmdNOP; - } + } else - cmd = cmds[i].id; + cmd = cmds[i].id; } - switch( cmd ) { + switch( cmd ) + { case cmdHELP: - for(i=0; cmds[i].name; i++ ) { - if( sign_mode && !cmds[i].signmode ) - ; - else if( cmds[i].need_sk && !sec_keyblock ) - ; /* skip if we do not have the secret key */ + for(i=0; cmds[i].name; i++ ) + { + if((cmds[i].flags & KEYEDIT_NEED_SK) && !sec_keyblock ) + ; /* skip if we do not have the secret key */ else if( cmds[i].desc ) - tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); - } + tty_printf("%-11s %s\n", cmds[i].name, _(cmds[i].desc) ); + } + + tty_printf("\n"); + tty_printf(_( +"* The `sign' command may be prefixed with an `l' for local " +"signatures (lsign),\n" +" a `t' for trust signatures (tsign), an `nr' for non-revocable signatures\n" +" (nrsign), or any combination thereof (ltsign, tnrsign, etc.).\n")); + break; case cmdLIST: @@ -1343,8 +1710,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, break; case cmdSELUID: - if( menu_select_uid( cur_keyblock, arg_number ) ) - redisplay = 1; + if(strlen(arg_string)==NAMEHASH_LEN*2) + redisplay=menu_select_uid_namehash(cur_keyblock,arg_string); + else + redisplay=menu_select_uid(cur_keyblock,arg_number); break; case cmdSELKEY: @@ -1360,42 +1729,53 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, break; case cmdSIGN: /* sign (only the public key) */ - case cmdLSIGN: /* sign (only the public key) */ - case cmdNRSIGN: /* sign (only the public key) */ - case cmdNRLSIGN: /* sign (only the public key) */ - case cmdTSIGN: - if( pk->is_revoked ) - { - tty_printf(_("Key is revoked.")); + { + int localsig=0,nonrevokesig=0,trustsig=0,interactive=0; - if(opt.expert) - { - tty_printf(" "); - if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay", - _("Are you sure you still want " - "to sign it? (y/N) "))) + if( pk->is_revoked ) + { + tty_printf(_("Key is revoked.")); + + if(opt.expert) + { + tty_printf(" "); + if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay", + _("Are you sure you still want" + " to sign it? (y/N) "))) + break; + } + else + { + tty_printf(_(" Unable to sign.\n")); break; - } - else - { - tty_printf(_(" Unable to sign.\n")); - break; - } - } + } + } - if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) { - if( !cpr_get_answer_is_yes("keyedit.sign_all.okay", - _("Really sign all user IDs? ")) ) { - tty_printf(_("Hint: Select the user IDs to sign\n")); - break; + if(count_uids(keyblock) > 1 && !count_selected_uids(keyblock) + && !cpr_get_answer_is_yes("keyedit.sign_all.okay", + _("Really sign all user IDs?" + " (y/N) "))) + { + if(opt.interactive) + interactive=1; + else + { + tty_printf(_("Hint: Select the user IDs to sign\n")); + have_commands = 0; + break; + } + + } + /* What sort of signing are we doing? */ + if(!parse_sign_type(answer,&localsig,&nonrevokesig,&trustsig)) + { + tty_printf(_("Unknown signature type `%s'\n"),answer); + break; } + + sign_uids(keyblock, locusr, &modified, + localsig, nonrevokesig, trustsig, interactive); } - if( !sign_uids( keyblock, locusr, &modified, - (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN), - (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN), - (cmd == cmdTSIGN)) - && sign_mode ) - goto do_cmd_save; break; case cmdDEBUG: @@ -1420,12 +1800,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, /* fall through */ case cmdADDUID: - if( menu_adduid( keyblock, sec_keyblock, photo ) ) { + if( menu_adduid( keyblock, sec_keyblock, photo, arg_string ) ) + { + update_trust = 1; redisplay = 1; sec_modified = modified = 1; merge_keys_and_selfsig( sec_keyblock ); merge_keys_and_selfsig( keyblock ); - } + } break; case cmdDELUID: { @@ -1435,10 +1817,9 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, tty_printf(_("You must select at least one user ID.\n")); else if( real_uids_left(keyblock) < 1 ) tty_printf(_("You can't delete the last user ID!\n")); - else if( cpr_get_answer_is_yes( - "keyedit.remove.uid.okay", - n1 > 1? _("Really remove all selected user IDs? ") - : _("Really remove this user ID? ") + else if( cpr_get_answer_is_yes("keyedit.remove.uid.okay", + n1 > 1? _("Really remove all selected user IDs? (y/N) ") + : _("Really remove this user ID? (y/N) ") ) ) { menu_deluid( keyblock, sec_keyblock ); redisplay = 1; @@ -1471,93 +1852,221 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } break; - - case cmdDELKEY: { - int n1; - - if( !(n1=count_selected_keys( keyblock )) ) - tty_printf(_("You must select at least one key.\n")); - else if( sec_keyblock && !cpr_get_answer_is_yes( - "keyedit.remove.subkey.okay", - n1 > 1? - _("Do you really want to delete the selected keys? "): - _("Do you really want to delete this key? ") - )) - ; - else { - menu_delkey( keyblock, sec_keyblock ); - redisplay = 1; - modified = 1; - if( sec_keyblock ) - sec_modified = 1; - } - } - break; - - case cmdADDREVOKER: - { - int sensitive=0; - - if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0) - sensitive=1; - if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) { +#ifdef ENABLE_CARD_SUPPORT + case cmdADDCARDKEY: + if (card_generate_subkey (keyblock, sec_keyblock)) { redisplay = 1; sec_modified = modified = 1; merge_keys_and_selfsig( sec_keyblock ); merge_keys_and_selfsig( keyblock ); - } } break; - case cmdREVUID: { - int n1; - - if( !(n1=count_selected_uids(keyblock)) ) - tty_printf(_("You must select at least one user ID.\n")); - else if( cpr_get_answer_is_yes( - "keyedit.revoke.uid.okay", - n1 > 1? _("Really revoke all selected user IDs? ") - : _("Really revoke this user ID? ") - ) ) { - if(menu_revuid(keyblock,sec_keyblock)) - { - modified=1; - redisplay=1; - } - } - } - break; + case cmdKEYTOCARD: + { + KBNODE node=NULL; + switch ( count_selected_keys (sec_keyblock) ) + { + case 0: + if (cpr_get_answer_is_yes("keyedit.keytocard.use_primary", + _("Really move the primary key? (y/N) "))) + node = sec_keyblock; + break; + case 1: + for (node = sec_keyblock; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_SECRET_SUBKEY + && node->flag & NODFLG_SELKEY) + break; + } + break; + default: + tty_printf(_("You must select exactly one key.\n")); + break; + } + if (node) + { + PKT_public_key *xxpk = find_pk_from_sknode (keyblock, node); + if (card_store_subkey (node, xxpk?xxpk->pubkey_usage:0)) + { + redisplay = 1; + sec_modified = 1; + } + } + } + break; + + case cmdBKUPTOCARD: + { + /* Ask for a filename, check whether this is really a + backup key as generated by the card generation, parse + that key and store it on card. */ + KBNODE node; + const char *fname; + PACKET *pkt; + IOBUF a; + + fname = arg_string; + if (!*fname) + { + tty_printf (_("Command expects a filename argument\n")); + break; + } + + /* Open that file. */ + a = iobuf_open (fname); + if (a && is_secured_file (iobuf_get_fd (a))) + { + iobuf_close (a); + a = NULL; + errno = EPERM; + } + if (!a) + { + tty_printf (_("Can't open `%s': %s\n"), + fname, strerror(errno)); + break; + } + + /* Parse and check that file. */ + pkt = xmalloc (sizeof *pkt); + init_packet (pkt); + rc = parse_packet (a, pkt); + iobuf_close (a); + iobuf_ioctl (NULL, 2, 0, (char*)fname); /* (invalidate cache). */ + if (!rc + && pkt->pkttype != PKT_SECRET_KEY + && pkt->pkttype != PKT_SECRET_SUBKEY) + rc = G10ERR_NO_SECKEY; + if (rc) + { + tty_printf(_("Error reading backup key from `%s': %s\n"), + fname, g10_errstr (rc)); + free_packet (pkt); + xfree (pkt); + break; + } + node = new_kbnode (pkt); + + /* Store it. */ + if (card_store_subkey (node, 0)) + { + redisplay = 1; + sec_modified = 1; + } + release_kbnode (node); + } + break; - case cmdREVKEY: { +#endif /* ENABLE_CARD_SUPPORT */ + + case cmdDELKEY: { int n1; if( !(n1=count_selected_keys( keyblock )) ) tty_printf(_("You must select at least one key.\n")); - else if( sec_keyblock && !cpr_get_answer_is_yes( - "keyedit.revoke.subkey.okay", + else if( !cpr_get_answer_is_yes( "keyedit.remove.subkey.okay", n1 > 1? - _("Do you really want to revoke the selected keys? "): - _("Do you really want to revoke this key? ") + _("Do you really want to delete the selected keys? (y/N) "): + _("Do you really want to delete this key? (y/N) ") )) ; else { - if( menu_revkey( keyblock, sec_keyblock ) ) { - modified = 1; - /*sec_modified = 1;*/ - } + menu_delkey( keyblock, sec_keyblock ); redisplay = 1; + modified = 1; + if( sec_keyblock ) + sec_modified = 1; + } + } + break; + + case cmdADDREVOKER: + { + int sensitive=0; + + if(ascii_strcasecmp(arg_string,"sensitive")==0) + sensitive=1; + if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) { + redisplay = 1; + sec_modified = modified = 1; + merge_keys_and_selfsig( sec_keyblock ); + merge_keys_and_selfsig( keyblock ); + } + } + break; + + case cmdREVUID: { + int n1; + + if( !(n1=count_selected_uids(keyblock)) ) + tty_printf(_("You must select at least one user ID.\n")); + else if( cpr_get_answer_is_yes( + "keyedit.revoke.uid.okay", + n1 > 1? _("Really revoke all selected user IDs? (y/N) ") + : _("Really revoke this user ID? (y/N) ") + ) ) { + if(menu_revuid(keyblock,sec_keyblock)) + { + modified=1; + redisplay=1; + } + } + } + break; + + case cmdREVKEY: + { + int n1; + + if( !(n1=count_selected_keys( keyblock )) ) + { + if(cpr_get_answer_is_yes("keyedit.revoke.subkey.okay", + _("Do you really want to revoke" + " the entire key? (y/N) "))) + { + if(menu_revkey(keyblock,sec_keyblock)) + modified=1; + + redisplay=1; + } + } + else if(cpr_get_answer_is_yes("keyedit.revoke.subkey.okay", + n1 > 1? + _("Do you really want to revoke" + " the selected subkeys? (y/N) "): + _("Do you really want to revoke" + " this subkey? (y/N) "))) + { + if( menu_revsubkey( keyblock, sec_keyblock ) ) + modified = 1; + + redisplay = 1; } + + if(modified) + merge_keys_and_selfsig( keyblock ); } break; case cmdEXPIRE: - if( menu_expire( keyblock, sec_keyblock ) ) { + if( menu_expire( keyblock, sec_keyblock ) ) + { merge_keys_and_selfsig( sec_keyblock ); merge_keys_and_selfsig( keyblock ); sec_modified = 1; modified = 1; redisplay = 1; - } + } + break; + + case cmdBACKSIGN: + if(menu_backsign(keyblock,sec_keyblock)) + { + sec_modified = 1; + modified = 1; + redisplay = 1; + } break; case cmdPRIMARY: @@ -1574,6 +2083,13 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, break; case cmdTRUST: + if(opt.trust_model==TM_EXTERNAL) + { + tty_printf(_("Owner trust may not be set while " + "using an user provided trust database\n")); + break; + } + show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 ); tty_printf("\n"); if( edit_ownertrust( find_kbnode( keyblock, @@ -1587,44 +2103,68 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, break; case cmdPREF: - show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 ); + { + int count=count_selected_uids(keyblock); + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + show_names(keyblock,keyblock->pkt->pkt.public_key, + count?NODFLG_SELUID:0,1); + } break; case cmdSHOWPREF: - show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 ); + { + int count=count_selected_uids(keyblock); + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + show_names(keyblock,keyblock->pkt->pkt.public_key, + count?NODFLG_SELUID:0,2); + } break; case cmdSETPREF: - keygen_set_std_prefs ( !*arg_string? "default" : arg_string, 0); - break; + { + PKT_user_id *tempuid; - case cmdUPDPREF: - { - PKT_user_id *temp=keygen_get_std_prefs(); - tty_printf(_("Current preference list:\n")); - show_prefs(temp,1); - xfree (temp); - } - if (cpr_get_answer_is_yes ("keyedit.updpref.okay", - count_selected_uids (keyblock)? - _("Really update the preferences" - " for the selected user IDs? "): - _("Really update the preferences? "))){ - - if ( menu_set_preferences (keyblock, sec_keyblock) ) { - merge_keys_and_selfsig (keyblock); - modified = 1; - redisplay = 1; - } - } + keygen_set_std_prefs(!*arg_string?"default" : arg_string, 0); + + tempuid=keygen_get_std_prefs(); + tty_printf(_("Set preference list to:\n")); + show_prefs(tempuid,NULL,1); + free_user_id(tempuid); + + if(cpr_get_answer_is_yes("keyedit.setpref.okay", + count_selected_uids (keyblock)? + _("Really update the preferences" + " for the selected user IDs? (y/N) "): + _("Really update the preferences? (y/N) "))) + { + if ( menu_set_preferences (keyblock, sec_keyblock) ) + { + merge_keys_and_selfsig (keyblock); + modified = 1; + redisplay = 1; + } + } + } break; case cmdPREFKS: - if( menu_set_keyserver_url ( keyblock, sec_keyblock ) ) { + if( menu_set_keyserver_url ( *arg_string?arg_string:NULL, + keyblock, sec_keyblock ) ) + { merge_keys_and_selfsig( keyblock ); modified = 1; redisplay = 1; - } + } + break; + + case cmdNOTATION: + if( menu_set_notation ( *arg_string?arg_string:NULL, + keyblock, sec_keyblock ) ) + { + merge_keys_and_selfsig( keyblock ); + modified = 1; + redisplay = 1; + } break; case cmdNOP: @@ -1645,9 +2185,17 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } break; - case cmdSHOWPHOTO: - menu_showphoto(keyblock); - break; + case cmdSHOWPHOTO: + menu_showphoto(keyblock); + break; + + case cmdCLEAN: + redisplay=modified=menu_clean(keyblock,0); + break; + + case cmdMINIMIZE: + redisplay=modified=menu_clean(keyblock,1); + break; case cmdQUIT: if( have_commands ) @@ -1655,21 +2203,20 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, if( !modified && !sec_modified ) goto leave; if( !cpr_get_answer_is_yes("keyedit.save.okay", - _("Save changes? ")) ) { + _("Save changes? (y/N) ")) ) { if( cpr_enabled() || cpr_get_answer_is_yes("keyedit.cancel.okay", - _("Quit without saving? ")) ) + _("Quit without saving? (y/N) "))) goto leave; break; } /* fall thru */ case cmdSAVE: - do_cmd_save: if( modified || sec_modified ) { if( modified ) { rc = keydb_update_keyblock (kdbhd, keyblock); if( rc ) { - log_error(_("update failed: %s\n"), gpg_strerror (rc) ); + log_error(_("update failed: %s\n"), g10_errstr(rc) ); break; } } @@ -1677,7 +2224,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock ); if( rc ) { log_error( _("update secret failed: %s\n"), - gpg_strerror (rc) ); + g10_errstr(rc) ); break; } } @@ -1704,15 +2251,44 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, release_kbnode( keyblock ); release_kbnode( sec_keyblock ); keydb_release (kdbhd); - xfree (answer); + xfree(answer); } +static void +tty_print_notations(int indent,PKT_signature *sig) +{ + int first=1; + struct notation *notation,*nd; + + if(indent<0) + { + first=0; + indent=-indent; + } + + notation=sig_to_notation(sig); + + for(nd=notation;nd;nd=nd->next) + { + if(!first) + tty_printf("%*s",indent,""); + else + first=0; + + tty_print_utf8_string(nd->name,strlen(nd->name)); + tty_printf("="); + tty_print_utf8_string(nd->value,strlen(nd->value)); + tty_printf("\n"); + } + + free_notation(notation); +} /**************** * show preferences of a public keyblock. */ static void -show_prefs (PKT_user_id *uid, int verbose) +show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose) { const prefitem_t fake={0,0}; const prefitem_t *prefs; @@ -1730,11 +2306,12 @@ show_prefs (PKT_user_id *uid, int verbose) if (verbose) { int any, des_seen=0, sha1_seen=0, uncomp_seen=0; + tty_printf (" "); tty_printf (_("Cipher: ")); for(i=any=0; prefs[i].type; i++ ) { if( prefs[i].type == PREFTYPE_SYM ) { - const char *s = gcry_cipher_algo_name (prefs[i].value); + const char *s = cipher_algo_to_string (prefs[i].value); if (any) tty_printf (", "); @@ -1751,13 +2328,13 @@ show_prefs (PKT_user_id *uid, int verbose) if (!des_seen) { if (any) tty_printf (", "); - tty_printf ("%s", gcry_cipher_algo_name (CIPHER_ALGO_3DES)); + tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES)); } tty_printf ("\n "); tty_printf (_("Digest: ")); for(i=any=0; prefs[i].type; i++ ) { if( prefs[i].type == PREFTYPE_HASH ) { - const char *s = gcry_md_algo_name (prefs[i].value); + const char *s = digest_algo_to_string (prefs[i].value); if (any) tty_printf (", "); @@ -1774,7 +2351,7 @@ show_prefs (PKT_user_id *uid, int verbose) if (!sha1_seen) { if (any) tty_printf (", "); - tty_printf ("%s", gcry_md_algo_name (DIGEST_ALGO_SHA1)); + tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1)); } tty_printf ("\n "); tty_printf (_("Compression: ")); @@ -1790,7 +2367,7 @@ show_prefs (PKT_user_id *uid, int verbose) tty_printf ("%s", s ); else tty_printf ("[%d]", prefs[i].value); - if (prefs[i].value == 0 ) + if (prefs[i].value == COMPRESS_ALGO_NONE ) uncomp_seen = 1; } } @@ -1798,22 +2375,22 @@ show_prefs (PKT_user_id *uid, int verbose) if (any) tty_printf (", "); else { - tty_printf ("%s",compress_algo_to_string(1)); + tty_printf ("%s",compress_algo_to_string(COMPRESS_ALGO_ZIP)); tty_printf (", "); } - tty_printf ("%s",compress_algo_to_string(0)); + tty_printf ("%s",compress_algo_to_string(COMPRESS_ALGO_NONE)); } - if(uid->mdc_feature || !uid->ks_modify) + if(uid->flags.mdc || !uid->flags.ks_modify) { tty_printf ("\n "); tty_printf (_("Features: ")); any=0; - if(uid->mdc_feature) + if(uid->flags.mdc) { tty_printf ("MDC"); any=1; } - if(!uid->ks_modify) + if(!uid->flags.ks_modify) { if(any) tty_printf (", "); @@ -1821,6 +2398,29 @@ show_prefs (PKT_user_id *uid, int verbose) } } tty_printf("\n"); + + if(selfsig) + { + const byte *pref_ks; + size_t pref_ks_len; + + pref_ks=parse_sig_subpkt(selfsig->hashed, + SIGSUBPKT_PREF_KS,&pref_ks_len); + if(pref_ks && pref_ks_len) + { + tty_printf (" "); + tty_printf(_("Preferred keyserver: ")); + tty_print_utf8_string(pref_ks,pref_ks_len); + tty_printf("\n"); + } + + if(selfsig->flags.notation) + { + tty_printf (" "); + tty_printf(_("Notations: ")); + tty_print_notations(5+strlen(_("Notations: ")),selfsig); + } + } } else { tty_printf(" "); @@ -1830,15 +2430,14 @@ show_prefs (PKT_user_id *uid, int verbose) prefs[i].type == PREFTYPE_ZIP ? 'Z':'?', prefs[i].value); } - if (uid->mdc_feature) + if (uid->flags.mdc) tty_printf (" [mdc]"); - if (!uid->ks_modify) + if (!uid->flags.ks_modify) tty_printf (" [no-ks-modify]"); tty_printf("\n"); } } - /* This is the version of show_key_with_all_names used when opt.with_colons is used. It prints all available data in a easy to parse format and does not translate utf8 */ @@ -1882,15 +2481,12 @@ show_key_with_all_names_colon (KBNODE keyblock) putchar (trust); } - printf (":%u:%d:%08lX%08lX:%lu:%lu:", + printf (":%u:%d:%08lX%08lX:%lu:%lu::", nbits_from_pk (pk), pk->pubkey_algo, (ulong)keyid[0], (ulong)keyid[1], (ulong)pk->timestamp, (ulong)pk->expiredate ); - if (pk->local_id) - printf ("%lu", pk->local_id); - putchar (':'); if (node->pkt->pkttype==PKT_PUBLIC_KEY && !(opt.fast_list_mode || opt.no_expensive_trust_checks )) putchar(get_ownertrust_info (pk)); @@ -1898,24 +2494,7 @@ show_key_with_all_names_colon (KBNODE keyblock) putchar('\n'); print_fingerprint (pk, NULL, 0); - - /* print the revoker record */ - if( !pk->revkey && pk->numrevkeys ) - BUG(); - else - { - for (i=0; i < pk->numrevkeys; i++) - { - byte *p; - - printf ("rvk:::%d::::::", pk->revkey[i].algid); - p = pk->revkey[i].fpr; - for (j=0; j < 20; j++, p++ ) - printf ("%02X", *p); - printf (":%02x%s:\n", pk->revkey[i].class, - (pk->revkey[i].class&0x40)?"s":""); - } - } + print_revokers(pk); } } @@ -1975,9 +2554,9 @@ show_key_with_all_names_colon (KBNODE keyblock) prefs[j].type == PREFTYPE_ZIP ? 'Z':'?', prefs[j].value); } - if (uid->mdc_feature) + if (uid->flags.mdc) printf (",mdc"); - if (!uid->ks_modify) + if (!uid->flags.ks_modify) printf (",no-ks-modify"); } putchar (':'); @@ -1999,6 +2578,63 @@ show_key_with_all_names_colon (KBNODE keyblock) } } +static void +show_names(KBNODE keyblock,PKT_public_key *pk,unsigned int flag,int with_prefs) +{ + KBNODE node; + int i=0; + + for( node = keyblock; node; node = node->next ) + { + if( node->pkt->pkttype == PKT_USER_ID + && !is_deleted_kbnode(node)) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + ++i; + if(!flag || (flag && (node->flag & flag))) + { + if(!(flag&NODFLG_MARK_A) && pk) + tty_printf("%s ",uid_trust_string_fixed(pk,uid)); + + if( flag & NODFLG_MARK_A ) + tty_printf(" "); + else if( node->flag & NODFLG_SELUID ) + tty_printf("(%d)* ", i); + else if( uid->is_primary ) + tty_printf("(%d). ", i); + else + tty_printf("(%d) ", i); + tty_print_utf8_string( uid->name, uid->len ); + tty_printf("\n"); + if(with_prefs && pk) + { + if(pk->version>3 || uid->selfsigversion>3) + { + PKT_signature *selfsig=NULL; + KBNODE signode; + + for(signode=node->next; + signode && signode->pkt->pkttype==PKT_SIGNATURE; + signode=signode->next) + { + if(signode->pkt->pkt.signature-> + flags.chosen_selfsig) + { + selfsig=signode->pkt->pkt.signature; + break; + } + } + + show_prefs (uid, selfsig, with_prefs == 2); + } + else + tty_printf(_("There are no preferences on a" + " PGP 2.x-style user ID.\n")); + } + } + } + } +} /**************** * Display the key a the user ids, if only_marked is true, do only @@ -2009,7 +2645,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, int with_fpr, int with_subkeys, int with_prefs ) { KBNODE node; - int i, rc; + int i; int do_warn = 0; byte pk_version=0; PKT_public_key *primary=NULL; @@ -2023,7 +2659,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, /* the keys */ for( node = keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_KEY - || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) { + || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && !is_deleted_kbnode(node)) ) { PKT_public_key *pk = node->pkt->pkt.public_key; const char *otrust="err",*trust="err"; @@ -2042,58 +2679,88 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, do_warn = 1; } - pk_version = pk->version; - primary = pk; + pk_version=pk->version; + primary=pk; } - if(with_revoker) { + if(pk->is_revoked) + { + char *user=get_user_id_string_native(pk->revoked.keyid); + const char *algo=pubkey_algo_to_string(pk->revoked.algo); + tty_printf(_("This key was revoked on %s by %s key %s\n"), + revokestr_from_pk(pk),algo?algo:"?",user); + xfree(user); + } + + if(with_revoker) + { if( !pk->revkey && pk->numrevkeys ) - BUG(); + BUG(); else - for(i=0;i<pk->numrevkeys;i++) { - u32 r_keyid[2]; - char *user; - const char *algo= - gcry_pk_algo_name (pk->revkey[i].algid); - - keyid_from_fingerprint(pk->revkey[i].fpr, - MAX_FINGERPRINT_LEN,r_keyid); - - user=get_user_id_string (r_keyid); - tty_printf (_("This key may be revoked by %s key "), - algo?algo:"?"); - tty_print_utf8_string (user, strlen (user)); - if ((pk->revkey[i].class&0x40)) - tty_printf (_(" (sensitive)")); - tty_printf ("\n"); - xfree (user); - } - } + for(i=0;i<pk->numrevkeys;i++) + { + u32 r_keyid[2]; + char *user; + const char *algo= + pubkey_algo_to_string(pk->revkey[i].algid); + + keyid_from_fingerprint(pk->revkey[i].fpr, + MAX_FINGERPRINT_LEN,r_keyid); + + user=get_user_id_string_native(r_keyid); + tty_printf(_("This key may be revoked by %s key %s"), + algo?algo:"?",user); + + if(pk->revkey[i].class&0x40) + { + tty_printf(" "); + tty_printf(_("(sensitive)")); + } + + tty_printf ("\n"); + xfree(user); + } + } keyid_from_pk(pk,NULL); - tty_printf("%s%c %4u%c/", + tty_printf("%s%c %4u%c/%s ", node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", (node->flag & NODFLG_SELKEY)? '*':' ', nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo )); - - if(opt.list_options&LIST_SHOW_LONG_KEYID) - tty_printf("%08lX",(ulong)pk->keyid[0]); - - tty_printf("%08lX ",(ulong)pk->keyid[1]); - tty_printf(_("created: %s expires: %s"), - datestr_from_pk(pk), - expirestr_from_pk(pk) ); + pubkey_letter( pk->pubkey_algo ), + keystr(pk->keyid)); + + tty_printf(_("created: %s"),datestr_from_pk(pk)); + tty_printf(" "); + if(pk->is_revoked) + tty_printf(_("revoked: %s"),revokestr_from_pk(pk)); + else if(pk->has_expired) + tty_printf(_("expired: %s"),expirestr_from_pk(pk)); + else + tty_printf(_("expires: %s"),expirestr_from_pk(pk)); + tty_printf(" "); + tty_printf(_("usage: %s"),usagestr_from_pk(pk)); tty_printf("\n"); if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - tty_printf(" "); - if(opt.list_options&LIST_SHOW_LONG_KEYID) - tty_printf(" "); - tty_printf(_("trust: %-13s"), otrust); - tty_printf(_("validity: %s"), trust ); - tty_printf("\n"); + if(opt.trust_model!=TM_ALWAYS) + { + tty_printf("%*s", (int)keystrlen()+13,""); + /* Ownertrust is only meaningful for the PGP or + classic trust models */ + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + { + int width=14-strlen(otrust); + if(width<=0) + width=1; + tty_printf(_("trust: %s"), otrust); + tty_printf("%*s",width,""); + } + + tty_printf(_("validity: %s"), trust ); + tty_printf("\n"); + } if( node->pkt->pkttype == PKT_PUBLIC_KEY && (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) { @@ -2110,16 +2777,18 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, } } else if( node->pkt->pkttype == PKT_SECRET_KEY - || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) { + || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) + { PKT_secret_key *sk = node->pkt->pkt.secret_key; - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), - node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", - (node->flag & NODFLG_SELKEY)? '*':' ', - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid_from_sk(sk,NULL), - datestr_from_sk(sk), - expirestr_from_sk(sk) ); + tty_printf("%s%c %4u%c/%s ", + node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", + (node->flag & NODFLG_SELKEY)? '*':' ', + nbits_from_sk( sk ), + pubkey_letter( sk->pubkey_algo ), + keystr_from_sk(sk)); + tty_printf(_("created: %s"),datestr_from_sk(sk)); + tty_printf(" "); + tty_printf(_("expires: %s"),expirestr_from_sk(sk)); tty_printf("\n"); if (sk->is_protected && sk->protect.s2k.mode == 1002) { @@ -2142,67 +2811,19 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, } tty_printf ("\n"); } - } - else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE - && node->pkt->pkt.signature->sig_class == 0x28 ) { - PKT_signature *sig = node->pkt->pkt.signature; - - rc = check_key_signature( keyblock, node, NULL ); - if( !rc ) - tty_printf( _("rev! subkey has been revoked: %s\n"), - datestr_from_sig( sig ) ); - else if( gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) - tty_printf( _("rev- faked revocation found\n") ); - else if( rc ) - tty_printf( _("rev? problem checking revocation: %s\n"), - gpg_strerror (rc) ); - } - } - /* the user ids */ - i = 0; - for( node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - ++i; - if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){ - if(opt.list_options&LIST_SHOW_VALIDITY && primary) - tty_printf("[%8.8s] ", - trust_value_to_string(get_validity(primary,uid))); - if( only_marked ) - tty_printf(" "); - else if( node->flag & NODFLG_SELUID ) - tty_printf("(%d)* ", i); - else if( uid->is_primary ) - tty_printf("(%d). ", i); - else - tty_printf("(%d) ", i); - if ( uid->is_revoked ) - tty_printf (_("[revoked] ")); - if ( uid->is_expired ) - tty_printf (_("[expired] ")); - tty_print_utf8_string( uid->name, uid->len ); - tty_printf("\n"); - if( with_prefs ) - { - if(pk_version>3 || uid->selfsigversion>3) - show_prefs (uid, with_prefs == 2); - else - tty_printf(_("There are no preferences on a " - "PGP 2.x-style user ID.\n")); - } - } - } + } } + show_names(keyblock,primary,only_marked?NODFLG_MARK_A:0,with_prefs); + if (do_warn) - tty_printf (_("Please note that the shown key validity " - "is not necessarily correct\n" + tty_printf (_("Please note that the shown key validity" + " is not necessarily correct\n" "unless you restart the program.\n")); - } -/* Display basic key information. This fucntion is suitable to show +/* Display basic key information. This function is suitable to show information on the key without any dependencies on the trustdb or any other internal GnuPG stuff. KEYBLOCK may either be a public or a secret key.*/ @@ -2221,14 +2842,14 @@ show_basic_key_info ( KBNODE keyblock ) /* Note, we use the same format string as in other show functions to make the translation job easier. */ - tty_printf (_("%s%c %4u%c/%08lX created: %s expires: %s"), + tty_printf ("%s %4u%c/%s ", node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub", - ' ', nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk), - expirestr_from_pk(pk) ); + keystr_from_pk(pk)); + tty_printf(_("created: %s"),datestr_from_pk(pk)); + tty_printf(" "); + tty_printf(_("expires: %s"),expirestr_from_pk(pk)); tty_printf("\n"); print_fingerprint ( pk, NULL, 3 ); tty_printf("\n"); @@ -2236,14 +2857,14 @@ show_basic_key_info ( KBNODE keyblock ) else if (node->pkt->pkttype == PKT_SECRET_KEY) { PKT_secret_key *sk = node->pkt->pkt.secret_key; - tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"), + tty_printf("%s %4u%c/%s", node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", - ' ', nbits_from_sk( sk ), pubkey_letter( sk->pubkey_algo ), - (ulong)keyid_from_sk(sk,NULL), - datestr_from_sk(sk), - expirestr_from_sk(sk) ); + keystr_from_sk(sk)); + tty_printf(_("created: %s"),datestr_from_sk(sk)); + tty_printf(" "); + tty_printf(_("expires: %s"),expirestr_from_sk(sk)); tty_printf("\n"); print_fingerprint (NULL, sk, 3 ); tty_printf("\n"); @@ -2260,9 +2881,9 @@ show_basic_key_info ( KBNODE keyblock ) tty_printf (" "); if (uid->is_revoked) - tty_printf ("[revoked] "); - if ( uid->is_expired ) - tty_printf ("[expired] "); + tty_printf("[%s] ",_("revoked")); + else if ( uid->is_expired ) + tty_printf("[%s] ",_("expired")); tty_print_utf8_string (uid->name, uid->len); tty_printf ("\n"); } @@ -2272,40 +2893,40 @@ show_basic_key_info ( KBNODE keyblock ) static void show_key_and_fingerprint( KBNODE keyblock ) { - KBNODE node; - PKT_public_key *pk = NULL; + KBNODE node; + PKT_public_key *pk = NULL; - for( node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - pk = node->pkt->pkt.public_key; - tty_printf("pub %4u%c/%08lX %s ", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk(pk,NULL), - datestr_from_pk(pk) ); + for( node = keyblock; node; node = node->next ) + { + if( node->pkt->pkttype == PKT_PUBLIC_KEY ) + { + pk = node->pkt->pkt.public_key; + tty_printf("pub %4u%c/%s %s ", + nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + keystr_from_pk(pk), + datestr_from_pk(pk) ); } - else if( node->pkt->pkttype == PKT_USER_ID ) { - PKT_user_id *uid = node->pkt->pkt.user_id; - tty_print_utf8_string( uid->name, uid->len ); - break; + else if( node->pkt->pkttype == PKT_USER_ID ) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + tty_print_utf8_string( uid->name, uid->len ); + break; } } - tty_printf("\n"); - if( pk ) - print_fingerprint( pk, NULL, 2 ); + tty_printf("\n"); + if( pk ) + print_fingerprint( pk, NULL, 2 ); } /* Show a warning if no uids on the key have the primary uid flag set. */ static void -no_primary_warning(KBNODE keyblock, int uids) +no_primary_warning(KBNODE keyblock) { KBNODE node; - int select_all=1,have_uid=0,uid_count=0; - - if(uids) - select_all=!count_selected_uids(keyblock); + int have_primary=0,uid_count=0; /* TODO: if we ever start behaving differently with a primary or non-primary attribute ID, we will need to check for attributes @@ -2318,17 +2939,18 @@ no_primary_warning(KBNODE keyblock, int uids) { uid_count++; - if((select_all || (node->flag & NODFLG_SELUID)) - && node->pkt->pkt.user_id->is_primary==2) - have_uid|=2; - else - have_uid|=1; + if(node->pkt->pkt.user_id->is_primary==2) + { + have_primary=1; + break; + } } } - if(uid_count>1 && have_uid&1 && !(have_uid&2)) - log_info(_("WARNING: no user ID has been marked as primary. This command " - "may\n cause a different user ID to become the assumed primary.\n")); + if(uid_count>1 && !have_primary) + log_info(_("WARNING: no user ID has been marked as primary. This command" + " may\n cause a different user ID to become" + " the assumed primary.\n")); } /**************** @@ -2337,7 +2959,8 @@ no_primary_warning(KBNODE keyblock, int uids) * Return true if there is a new user id */ static int -menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) +menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, + int photo, const char *photo_name) { PKT_user_id *uid; PKT_public_key *pk=NULL; @@ -2403,7 +3026,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) } } - uid = generate_photo_id(pk); + uid = generate_photo_id(pk,photo_name); } else uid = generate_user_id(); if( !uid ) @@ -2413,13 +3036,13 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) keygen_add_std_prefs, pk ); free_secret_key( sk ); if( rc ) { - log_error("signing failed: %s\n", gpg_strerror (rc) ); + log_error("signing failed: %s\n", g10_errstr(rc) ); free_user_id(uid); return 0; } /* insert/append to secret keyblock */ - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_USER_ID; pkt->pkt.user_id = scopy_user_id(uid); node = new_kbnode(pkt); @@ -2427,7 +3050,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) insert_kbnode( sec_where, node, 0 ); else add_kbnode( sec_keyblock, node ); - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = copy_signature(NULL, sig); if( sec_where ) @@ -2435,7 +3058,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) else add_kbnode( sec_keyblock, new_kbnode(pkt) ); /* insert/append to public keyblock */ - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_USER_ID; pkt->pkt.user_id = uid; node = new_kbnode(pkt); @@ -2443,7 +3066,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) insert_kbnode( pub_where, node, 0 ); else add_kbnode( pub_keyblock, node ); - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = copy_signature(NULL, sig); if( pub_where ) @@ -2455,7 +3078,7 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo) /**************** - * Remove all selceted userids from the keyrings + * Remove all selected userids from the keyrings */ static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ) @@ -2524,10 +3147,15 @@ menu_delsig( KBNODE pub_keyblock ) tty_print_utf8_string( uid->name, uid->len ); tty_printf("\n"); - okay = inv_sig = no_key = other_err = 0; - valid = print_and_check_one_sig( pub_keyblock, node, - &inv_sig, &no_key, &other_err, - &selfsig, 1 ); + okay = inv_sig = no_key = other_err = 0; + if(opt.with_colons) + valid = print_and_check_one_sig_colon( pub_keyblock, node, + &inv_sig, &no_key, &other_err, + &selfsig, 1 ); + else + valid = print_and_check_one_sig( pub_keyblock, node, + &inv_sig, &no_key, &other_err, + &selfsig, 1 ); if( valid ) { okay = cpr_get_answer_yes_no_quit( @@ -2575,6 +3203,58 @@ menu_delsig( KBNODE pub_keyblock ) return changed; } +static int +menu_clean(KBNODE keyblock,int self_only) +{ + KBNODE uidnode; + int modified=0,select_all=!count_selected_uids(keyblock); + + for(uidnode=keyblock->next; + uidnode && uidnode->pkt->pkttype!=PKT_PUBLIC_SUBKEY; + uidnode=uidnode->next) + { + if(uidnode->pkt->pkttype==PKT_USER_ID + && (uidnode->flag&NODFLG_SELUID || select_all)) + { + int uids=0,sigs=0; + char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, + uidnode->pkt->pkt.user_id->len, + 0); + + clean_one_uid(keyblock,uidnode,opt.verbose,self_only,&uids,&sigs); + if(uids) + { + const char *reason; + + if(uidnode->pkt->pkt.user_id->is_revoked) + reason=_("revoked"); + else if(uidnode->pkt->pkt.user_id->is_expired) + reason=_("expired"); + else + reason=_("invalid"); + + tty_printf("User ID \"%s\" compacted: %s\n",user,reason); + + modified=1; + } + else if(sigs) + { + tty_printf(sigs==1? + "User ID \"%s\": %d signature removed\n": + "User ID \"%s\": %d signatures removed\n", + user,sigs); + + modified=1; + } + else + tty_printf(_("User ID \"%s\": already clean\n"),user); + + xfree(user); + } + } + + return modified; +} /**************** * Remove some of the secondary keys @@ -2681,14 +3361,11 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) for(;;) { char *answer; - u32 keyid[2]; - char *p; - size_t n; if(revoker_pk) free_public_key(revoker_pk); - revoker_pk=xcalloc (1,sizeof(*revoker_pk)); + revoker_pk=xmalloc_clear(sizeof(*revoker_pk)); tty_printf("\n"); @@ -2696,21 +3373,24 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) _("Enter the user ID of the designated revoker: ")); if(answer[0]=='\0' || answer[0]=='\004') { - xfree(answer); answer = NULL; + xfree(answer); goto fail; } - - rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); + /* Note that I'm requesting CERT here, which usually implies + primary keys only, but some casual testing shows that PGP and + GnuPG both can handle a designated revokation from a + subkey. */ + revoker_pk->req_usage=PUBKEY_USAGE_CERT; + rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); if(rc) { - log_error (_("key `%s' not found: %s\n"),answer,gpg_strerror (rc)); - xfree (answer); answer = NULL; + log_error (_("key \"%s\" not found: %s\n"),answer,g10_errstr(rc)); + xfree(answer); continue; } - xfree (answer); answer = NULL; - + xfree(answer); fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen); if(fprlen!=20) @@ -2767,17 +3447,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) continue; } - keyid_from_pk(revoker_pk,keyid); - - tty_printf("\npub %4u%c/%08lX %s ", - nbits_from_pk( revoker_pk ), - pubkey_letter( revoker_pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk(pk) ); - - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - xfree (p); - tty_printf("\n"); + print_pubkey_info(NULL,revoker_pk); print_fingerprint(revoker_pk,NULL,2); tty_printf("\n"); @@ -2788,7 +3458,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay", _("Are you sure you want to appoint this " - "key as a designated revoker? (y/N): "))) + "key as a designated revoker? (y/N) "))) continue; free_public_key(revoker_pk); @@ -2802,7 +3472,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) keygen_add_revkey,&revkey ); if( rc ) { - log_error("signing failed: %s\n", gpg_strerror (rc) ); + log_error("signing failed: %s\n", g10_errstr(rc) ); goto fail; } @@ -2810,13 +3480,13 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) sk=NULL; /* insert into secret keyblock */ - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = copy_signature(NULL, sig); insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); /* insert into public keyblock */ - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE ); @@ -2854,17 +3524,17 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) n1 = count_selected_keys( pub_keyblock ); if( n1 > 1 ) { - tty_printf(_("Please select at most one secondary key.\n")); + tty_printf(_("Please select at most one subkey.\n")); return 0; } else if( n1 ) - tty_printf(_("Changing expiration time for a secondary key.\n")); - else { + tty_printf(_("Changing expiration time for a subkey.\n")); + else + { tty_printf(_("Changing expiration time for the primary key.\n")); mainkey=1; - } - - no_primary_warning(pub_keyblock,0); + no_primary_warning(pub_keyblock); + } expiredate = ask_expiredate(); node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); @@ -2891,9 +3561,11 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) && ( mainkey || sub_pk ) ) { PKT_signature *sig = node->pkt->pkt.signature; if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && ( (mainkey && uid - && uid->created && (sig->sig_class&~3) == 0x10) - || (!mainkey && sig->sig_class == 0x18) ) ) { + && ( (mainkey && uid + && uid->created && (sig->sig_class&~3) == 0x10) + || (!mainkey && sig->sig_class == 0x18) ) + && sig->flags.chosen_selfsig ) + { /* this is a selfsignature which is to be replaced */ PKT_signature *newsig; PACKET *newpkt; @@ -2931,23 +3603,23 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) sk, keygen_add_key_expire, sub_pk ); if( rc ) { log_error("make_keysig_packet failed: %s\n", - gpg_strerror (rc)); + g10_errstr(rc)); free_secret_key( sk ); return 0; } /* replace the packet */ - newpkt = xcalloc (1, sizeof *newpkt ); + newpkt = xmalloc_clear( sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = newsig; free_packet( node->pkt ); - xfree ( node->pkt ); + xfree( node->pkt ); node->pkt = newpkt; if( sn ) { - newpkt = xcalloc (1, sizeof *newpkt ); + newpkt = xmalloc_clear( sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = copy_signature( NULL, newsig ); free_packet( sn->pkt ); - xfree ( sn->pkt ); + xfree( sn->pkt ); sn->pkt = newpkt; } sub_pk = NULL; @@ -2955,11 +3627,157 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ) } } - free_secret_key( sk ); - update_trust=1; - return 1; + free_secret_key( sk ); + update_trust=1; + return 1; +} + +static int +menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock) +{ + int rc,modified=0; + PKT_public_key *main_pk; + PKT_secret_key *main_sk,*sub_sk=NULL; + KBNODE node; + + assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY); + + merge_keys_and_selfsig(pub_keyblock); + main_pk=pub_keyblock->pkt->pkt.public_key; + main_sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key); + keyid_from_pk(main_pk,NULL); + + for(node=pub_keyblock;node;node=node->next) + { + PKT_public_key *sub_pk=NULL; + KBNODE node2,sig_pk=NULL,sig_sk=NULL; + char *passphrase; + + if(sub_sk) + { + free_secret_key(sub_sk); + sub_sk=NULL; + } + + /* Find a signing subkey with no backsig */ + if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY + && (node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG) + && !node->pkt->pkt.public_key->backsig) + sub_pk=node->pkt->pkt.public_key; + + if(!sub_pk) + continue; + + /* Find the selected selfsig on this subkey */ + for(node2=node->next; + node2 && node2->pkt->pkttype==PKT_SIGNATURE; + node2=node2->next) + if(node2->pkt->pkt.signature->version>=4 + && node2->pkt->pkt.signature->flags.chosen_selfsig) + { + sig_pk=node2; + break; + } + + if(!sig_pk) + continue; + + /* Find the secret subkey that matches the public subkey */ + for(node2=sec_keyblock;node2;node2=node2->next) + if(node2->pkt->pkttype==PKT_SECRET_SUBKEY + && !cmp_public_secret_key(sub_pk,node2->pkt->pkt.secret_key)) + { + sub_sk=copy_secret_key(NULL,node2->pkt->pkt.secret_key); + break; + } + + if(!sub_sk) + continue; + + /* Now finally find the matching selfsig on the secret subkey. + We can't use chosen_selfsig here (it's not set for secret + keys), so we just pick the selfsig with the right class. + This is what menu_expire does as well. */ + for(node2=node2->next; + node2 && node2->pkt->pkttype!=PKT_SECRET_SUBKEY; + node2=node2->next) + if(node2->pkt->pkttype==PKT_SIGNATURE + && node2->pkt->pkt.signature->version>=4 + && node2->pkt->pkt.signature->keyid[0]==sig_pk->pkt->pkt.signature->keyid[0] + && node2->pkt->pkt.signature->keyid[1]==sig_pk->pkt->pkt.signature->keyid[1] + && node2->pkt->pkt.signature->sig_class==sig_pk->pkt->pkt.signature->sig_class) + { + sig_sk=node2; + break; + } + + if(!sig_sk) + continue; + + /* Now we can get to work. We have a main key and secret part, + a signing subkey with signature and secret part with + signature. */ + + passphrase=get_last_passphrase(); + set_next_passphrase(passphrase); + xfree(passphrase); + + rc=make_backsig(sig_pk->pkt->pkt.signature,main_pk,sub_pk,sub_sk); + if(rc==0) + { + PKT_signature *newsig; + PACKET *newpkt; + + passphrase=get_last_passphrase(); + set_next_passphrase(passphrase); + xfree(passphrase); + + rc=update_keysig_packet(&newsig,sig_pk->pkt->pkt.signature,main_pk, + NULL,sub_pk,main_sk,NULL,NULL); + if(rc==0) + { + /* Put the new sig into place on the pubkey */ + newpkt=xmalloc_clear(sizeof(*newpkt)); + newpkt->pkttype=PKT_SIGNATURE; + newpkt->pkt.signature=newsig; + free_packet(sig_pk->pkt); + xfree(sig_pk->pkt); + sig_pk->pkt=newpkt; + + /* Put the new sig into place on the seckey */ + newpkt=xmalloc_clear(sizeof(*newpkt)); + newpkt->pkttype=PKT_SIGNATURE; + newpkt->pkt.signature=copy_signature(NULL,newsig); + free_packet(sig_sk->pkt); + xfree(sig_sk->pkt); + sig_sk->pkt=newpkt; + + modified=1; + } + else + { + log_error("update_keysig_packet failed: %s\n",g10_errstr(rc)); + break; + } + } + else + { + log_error("make_backsig failed: %s\n",g10_errstr(rc)); + break; + } + } + + set_next_passphrase(NULL); + + free_secret_key(main_sk); + if(sub_sk) + free_secret_key(sub_sk); + + return modified; } + static int change_primary_uid_cb ( PKT_signature *sig, void *opaque ) { @@ -3033,14 +3851,16 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && (uid && (sig->sig_class&~3) == 0x10) - && attribute == (uid->attrib_data!=NULL)) { + && (uid && (sig->sig_class&~3) == 0x10) + && attribute == (uid->attrib_data!=NULL) + && sig->flags.chosen_selfsig ) + { if(sig->version < 4) { char *user=utf8_to_native(uid->name,strlen(uid->name),0); - log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + log_info(_("skipping v3 self-signature on user ID \"%s\"\n"), user); - xfree (user); + xfree(user); } else { /* This is a selfsignature which is to be replaced. @@ -3079,16 +3899,16 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) action > 0? "x":NULL ); if( rc ) { log_error ("update_keysig_packet failed: %s\n", - gpg_strerror (rc)); + g10_errstr(rc)); free_secret_key( sk ); return 0; } /* replace the packet */ - newpkt = xcalloc (1, sizeof *newpkt ); + newpkt = xmalloc_clear( sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = newsig; free_packet( node->pkt ); - xfree ( node->pkt ); + xfree( node->pkt ); node->pkt = newpkt; modified = 1; } @@ -3116,7 +3936,7 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) int selected, select_all; int modified = 0; - no_primary_warning(pub_keyblock,1); + no_primary_warning(pub_keyblock); select_all = !count_selected_uids (pub_keyblock); @@ -3143,13 +3963,14 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && (uid && (sig->sig_class&~3) == 0x10) ) { + && (uid && (sig->sig_class&~3) == 0x10) + && sig->flags.chosen_selfsig ) { if( sig->version < 4 ) { char *user=utf8_to_native(uid->name,strlen(uid->name),0); - log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + log_info(_("skipping v3 self-signature on user ID \"%s\"\n"), user); - xfree (user); + xfree(user); } else { /* This is a selfsignature which is to be replaced @@ -3166,16 +3987,16 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) NULL ); if( rc ) { log_error ("update_keysig_packet failed: %s\n", - gpg_strerror (rc)); + g10_errstr(rc)); free_secret_key( sk ); return 0; } /* replace the packet */ - newpkt = xcalloc (1, sizeof *newpkt ); + newpkt = xmalloc_clear( sizeof *newpkt ); newpkt->pkttype = PKT_SIGNATURE; newpkt->pkt.signature = newsig; free_packet( node->pkt ); - xfree ( node->pkt ); + xfree( node->pkt ); node->pkt = newpkt; modified = 1; } @@ -3188,98 +4009,360 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) } - static int -menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ) +menu_set_keyserver_url (const char *url, + KBNODE pub_keyblock, KBNODE sec_keyblock ) { - PKT_secret_key *sk; /* copy of the main sk */ - PKT_public_key *main_pk; - PKT_user_id *uid; - KBNODE node; - u32 keyid[2]; - int selected, select_all; - int modified = 0; - char *answer; + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected, select_all; + int modified = 0; + char *answer,*uri; - no_primary_warning(pub_keyblock,1); + no_primary_warning(pub_keyblock); - answer=cpr_get_utf8("keyedit.add_keyserver", - _("Enter your preferred keyserver URL: ")); - if(answer[0]=='\0' || answer[0]=='\004') - { - xfree(answer); - return 0; - } + if(url) + answer=xstrdup(url); + else + { + answer=cpr_get_utf8("keyedit.add_keyserver", + _("Enter your preferred keyserver URL: ")); + if(answer[0]=='\0' || answer[0]=='\004') + { + xfree(answer); + return 0; + } + } - select_all = !count_selected_uids (pub_keyblock); + if(ascii_strcasecmp(answer,"none")==0) + uri=NULL; + else + { + struct keyserver_spec *keyserver=NULL; + /* Sanity check the format */ + keyserver=parse_keyserver_uri(answer,1,NULL,0); + xfree(answer); + if(!keyserver) + { + log_info(_("could not parse keyserver URL\n")); + return 0; + } + uri=xstrdup(keyserver->uri); + free_keyserver_spec(keyserver); + } - node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + select_all = !count_selected_uids (pub_keyblock); - /* Now we can actually change the self signature(s) */ - main_pk = NULL; - uid = NULL; - selected = 0; - for ( node=pub_keyblock; node; node = node->next ) { - if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - break; /* ready */ + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); - if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { - main_pk = node->pkt->pkt.public_key; - keyid_from_pk( main_pk, keyid ); + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + for ( node=pub_keyblock; node; node = node->next ) + { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) + { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); } - else if ( node->pkt->pkttype == PKT_USER_ID ) { - uid = node->pkt->pkt.user_id; - selected = select_all || (node->flag & NODFLG_SELUID); - } - else if ( main_pk && uid && selected - && node->pkt->pkttype == PKT_SIGNATURE ) { - PKT_signature *sig = node->pkt->pkt.signature; - if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] - && (uid && (sig->sig_class&~3) == 0x10) ) { - if( sig->version < 4 ) { - char *user=utf8_to_native(uid->name,strlen(uid->name),0); + else if ( node->pkt->pkttype == PKT_USER_ID ) + { + uid = node->pkt->pkt.user_id; + selected = select_all || (node->flag & NODFLG_SELUID); + } + else if ( main_pk && uid && selected + && node->pkt->pkttype == PKT_SIGNATURE ) + { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) + && sig->flags.chosen_selfsig) + { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + if( sig->version < 4 ) + log_info(_("skipping v3 self-signature on user ID \"%s\"\n"), + user); + else + { + /* This is a selfsignature which is to be replaced + * We have to ignore v3 signatures because they are + * not able to carry the subpacket. */ + PKT_signature *newsig; + PACKET *newpkt; + int rc; + const byte *p; + size_t plen; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&plen); + if(p && plen) + { + tty_printf("Current preferred keyserver for user" + " ID \"%s\": ",user); + tty_print_utf8_string(p,plen); + tty_printf("\n"); + if(!cpr_get_answer_is_yes("keyedit.confirm_keyserver", + uri?_("Are you sure you want to replace it? (y/N) "): + _("Are you sure you want to delete it? (y/N) "))) + continue; + } + else if(uri==NULL) + { + /* There is no current keyserver URL, so there + is no point in trying to un-set it. */ + continue; + } + + rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + keygen_add_keyserver_url, uri ); + if( rc ) + { + log_error ("update_keysig_packet failed: %s\n", + g10_errstr(rc)); + free_secret_key( sk ); + xfree(uri); + return 0; + } + /* replace the packet */ + newpkt = xmalloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + xfree( node->pkt ); + node->pkt = newpkt; + modified = 1; + } + + xfree(user); + } + } + } + + xfree(uri); + free_secret_key( sk ); + return modified; +} + +static int +menu_set_notation(const char *string,KBNODE pub_keyblock,KBNODE sec_keyblock) +{ + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected, select_all; + int modified = 0; + char *answer; + struct notation *notation; - log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + no_primary_warning(pub_keyblock); + + if(string) + answer=xstrdup(string); + else + { + answer=cpr_get_utf8("keyedit.add_notation", + _("Enter the notation: ")); + if(answer[0]=='\0' || answer[0]=='\004') + { + xfree(answer); + return 0; + } + } + + if(ascii_strcasecmp(answer,"none")==0 + || ascii_strcasecmp(answer,"-")==0) + notation=NULL; /* delete them all */ + else + { + notation=string_to_notation(answer,0); + if(!notation) + { + xfree(answer); + return 0; + } + } + + xfree(answer); + + select_all = !count_selected_uids (pub_keyblock); + + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + for ( node=pub_keyblock; node; node = node->next ) + { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) + { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + } + else if ( node->pkt->pkttype == PKT_USER_ID ) + { + uid = node->pkt->pkt.user_id; + selected = select_all || (node->flag & NODFLG_SELUID); + } + else if ( main_pk && uid && selected + && node->pkt->pkttype == PKT_SIGNATURE ) + { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) + && sig->flags.chosen_selfsig) + { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + if( sig->version < 4 ) + log_info(_("skipping v3 self-signature on user ID \"%s\"\n"), user); - xfree(user); - } - else { - /* This is a selfsignature which is to be replaced - * We have to ignore v3 signatures because they are - * not able to carry the preferences */ - PKT_signature *newsig; - PACKET *newpkt; - int rc; + else + { + PKT_signature *newsig; + PACKET *newpkt; + int rc,skip=0,addonly=1; - rc = update_keysig_packet (&newsig, sig, - main_pk, uid, NULL, - sk, - keygen_add_keyserver_url, - answer ); - if( rc ) { - log_error ("update_keysig_packet failed: %s\n", - gpg_strerror (rc)); - xfree(answer); - free_secret_key( sk ); - return 0; - } - /* replace the packet */ - newpkt = xcalloc (1, sizeof *newpkt ); - newpkt->pkttype = PKT_SIGNATURE; - newpkt->pkt.signature = newsig; - free_packet( node->pkt ); - xfree (node->pkt); - node->pkt = newpkt; - modified = 1; - } - } + if(sig->flags.notation) + { + tty_printf("Current notations for user ID \"%s\":\n", + user); + tty_print_notations(-9,sig); + } + else + { + tty_printf("No notations on user ID \"%s\"\n",user); + if(notation==NULL) + { + /* There are no current notations, so there + is no point in trying to un-set them. */ + continue; + } + } + + if(notation) + { + struct notation *n; + int deleting=0; + + notation->next=sig_to_notation(sig); + + for(n=notation->next;n;n=n->next) + if(strcmp(n->name,notation->name)==0) + { + if(notation->value) + { + if(strcmp(n->value,notation->value)==0) + { + if(notation->flags.ignore) + { + /* Value match with a delete + flag. */ + n->flags.ignore=1; + deleting=1; + } + else + { + /* Adding the same notation + twice, so don't add it at + all. */ + skip=1; + tty_printf("Skipping notation:" + " %s=%s\n", + notation->name, + notation->value); + break; + } + } + } + else + { + /* No value, so it means delete. */ + n->flags.ignore=1; + deleting=1; + } + + if(n->flags.ignore) + { + tty_printf("Removing notation: %s=%s\n", + n->name,n->value); + addonly=0; + } + } + + if(!notation->flags.ignore && !skip) + tty_printf("Adding notation: %s=%s\n", + notation->name,notation->value); + + /* We tried to delete, but had no matches */ + if(notation->flags.ignore && !deleting) + continue; + } + else + { + tty_printf("Removing all notations\n"); + addonly=0; + } + + if(skip + || (!addonly + && !cpr_get_answer_is_yes("keyedit.confirm_notation", + _("Proceed? (y/N) ")))) + continue; + + rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + keygen_add_notations, notation ); + if( rc ) + { + log_error ("update_keysig_packet failed: %s\n", + g10_errstr(rc)); + free_secret_key( sk ); + free_notation(notation); + xfree(user); + return 0; + } + + /* replace the packet */ + newpkt = xmalloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + xfree( node->pkt ); + node->pkt = newpkt; + modified = 1; + + if(notation) + { + /* Snip off the notation list from the sig */ + free_notation(notation->next); + notation->next=NULL; + } + + xfree(user); + } + } } } - xfree(answer); - free_secret_key( sk ); - return modified; + free_notation(notation); + free_secret_key( sk ); + return modified; } @@ -3328,6 +4411,45 @@ menu_select_uid( KBNODE keyblock, int idx ) return 1; } +/* Search in the keyblock for a uid that matches namehash */ +static int +menu_select_uid_namehash( KBNODE keyblock, const char *namehash ) +{ + byte hash[NAMEHASH_LEN]; + KBNODE node; + int i; + + assert(strlen(namehash)==NAMEHASH_LEN*2); + + for(i=0;i<NAMEHASH_LEN;i++) + hash[i]=hextobyte(&namehash[i*2]); + + for(node=keyblock->next;node;node=node->next) + { + if(node->pkt->pkttype==PKT_USER_ID) + { + namehash_from_uid(node->pkt->pkt.user_id); + if(memcmp(node->pkt->pkt.user_id->namehash,hash,NAMEHASH_LEN)==0) + { + if(node->flag&NODFLG_SELUID) + node->flag &= ~NODFLG_SELUID; + else + node->flag |= NODFLG_SELUID; + + break; + } + } + } + + if(!node) + { + tty_printf(_("No user ID with hash %s\n"),namehash); + return 0; + } + + return 1; +} + /**************** * Select secondary keys * Returns: True if the selection changed; @@ -3348,7 +4470,7 @@ menu_select_key( KBNODE keyblock, int idx ) } } if( !node ) { - tty_printf(_("No secondary key with index %d\n"), idx ); + tty_printf(_("No subkey with index %d\n"), idx ); return 0; } } @@ -3454,6 +4576,7 @@ static void ask_revoke_sig( KBNODE keyblock, KBNODE node ) { int doit=0; + PKT_user_id *uid; PKT_signature *sig = node->pkt->pkt.signature; KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID ); @@ -3462,17 +4585,33 @@ ask_revoke_sig( KBNODE keyblock, KBNODE node ) return; } - tty_printf(_("user ID: \"")); - tty_print_utf8_string( unode->pkt->pkt.user_id->name, - unode->pkt->pkt.user_id->len ); + uid=unode->pkt->pkt.user_id; - if(sig->flags.exportable) - tty_printf(_("\"\nsigned with your key %08lX at %s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig) ); - else - tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig) ); + if(opt.with_colons) + { + if(uid->attrib_data) + printf("uat:::::::::%u %lu",uid->numattribs,uid->attrib_len); + else + { + printf("uid:::::::::"); + print_string (stdout, uid->name, uid->len, ':'); + } + + printf("\n"); + print_and_check_one_sig_colon(keyblock,node,NULL,NULL,NULL,NULL,1); + } + else + { + char *p=utf8_to_native(unode->pkt->pkt.user_id->name, + unode->pkt->pkt.user_id->len,0); + tty_printf(_("user ID: \"%s\"\n"),p); + xfree(p); + + tty_printf(_("signed by your key %s on %s%s%s\n"), + keystr(sig->keyid),datestr_from_sig(sig), + sig->flags.exportable?"":_(" (non-exportable)"),""); + } if(sig->flags.expired) { tty_printf(_("This signature expired on %s.\n"), @@ -3507,8 +4646,11 @@ menu_revsig( KBNODE keyblock ) int rc, any, skip=1, all=!count_selected_uids(keyblock); struct revocation_reason_info *reason = NULL; + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + /* FIXME: detect duplicates here */ - tty_printf(_("You have signed these user IDs:\n")); + tty_printf(_("You have signed these user IDs on key %s:\n"), + keystr_from_pk(keyblock->pkt->pkt.public_key)); for( node = keyblock; node; node = node->next ) { node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A); if( node->pkt->pkttype == PKT_USER_ID ) { @@ -3525,22 +4667,29 @@ menu_revsig( KBNODE keyblock ) } else if( !skip && node->pkt->pkttype == PKT_SIGNATURE && ((sig = node->pkt->pkt.signature), - !seckey_available(sig->keyid) ) ) { - if( (sig->sig_class&~3) == 0x10 ) { - tty_printf(_(" signed by %08lX at %s%s%s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig), - sig->flags.exportable?"":" (non-exportable)", - sig->flags.revocable?"":" (non-revocable)"); + !seckey_available(sig->keyid) ) ) + { + if( (sig->sig_class&~3) == 0x10 ) + { + tty_printf(" "); + tty_printf(_("signed by your key %s on %s%s%s\n"), + keystr(sig->keyid), datestr_from_sig(sig), + sig->flags.exportable?"":_(" (non-exportable)"), + sig->flags.revocable?"":_(" (non-revocable)")); if(sig->flags.revocable) node->flag |= NODFLG_SELSIG; - } - else if( sig->sig_class == 0x30 ) { - tty_printf(_(" revoked by %08lX at %s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig) ); - } - } + } + else if( sig->sig_class == 0x30 ) + { + tty_printf(" "); + tty_printf(_("revoked by your key %s on %s\n"), + keystr(sig->keyid),datestr_from_sig(sig)); + } + } } + tty_printf("\n"); + /* ask */ for( node = keyblock; node; node = node->next ) { if( !(node->flag & NODFLG_SELSIG) ) @@ -3565,8 +4714,9 @@ menu_revsig( KBNODE keyblock ) } else if( node->pkt->pkttype == PKT_SIGNATURE ) { sig = node->pkt->pkt.signature; - tty_printf(_(" signed by %08lX at %s%s\n"), - (ulong)sig->keyid[1], datestr_from_sig(sig), + tty_printf(" "); + tty_printf(_("signed by your key %s on %s%s%s\n"), + keystr(sig->keyid), datestr_from_sig(sig),"", sig->flags.exportable?"":_(" (non-exportable)") ); } } @@ -3602,7 +4752,7 @@ menu_revsig( KBNODE keyblock ) attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable; node->flag &= ~NODFLG_MARK_A; - sk = xcalloc_secure (1, sizeof *sk ); + sk = xmalloc_secure_clear( sizeof *sk ); if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) { log_info(_("no secret key\n")); continue; @@ -3616,7 +4766,7 @@ menu_revsig( KBNODE keyblock ) &attrib ); free_secret_key(sk); if( rc ) { - log_error(_("signing failed: %s\n"), gpg_strerror (rc)); + log_error(_("signing failed: %s\n"), g10_errstr(rc)); release_revocation_reason_info( reason ); return changed; } @@ -3626,7 +4776,7 @@ menu_revsig( KBNODE keyblock ) if(primary_pk->keyid[0]==sig->keyid[0] && primary_pk->keyid[1]==sig->keyid[1]) unode->pkt->pkt.user_id->is_revoked=1; - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( unode, new_kbnode(pkt), 0 ); @@ -3675,7 +4825,7 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock ) { char *user=utf8_to_native(uid->name,uid->len,0); log_info(_("user ID \"%s\" is already revoked\n"),user); - xfree (user); + xfree(user); } else { @@ -3707,12 +4857,12 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock ) sign_mk_attrib, &attrib ); if( rc ) { - log_error(_("signing failed: %s\n"), gpg_strerror (rc)); + log_error(_("signing failed: %s\n"), g10_errstr(rc)); goto leave; } else { - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( node, new_kbnode(pkt), 0 ); @@ -3741,12 +4891,57 @@ menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock ) } /**************** - * Revoke some of the secondary keys. - * Hmmm: Should we add a revocation to the secret keyring too? - * Does its all make sense to duplicate most of the information? + * Revoke the whole key. */ static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_public_key *pk=pub_keyblock->pkt->pkt.public_key; + PKT_secret_key *sk; + int rc,changed = 0; + struct revocation_reason_info *reason; + PACKET *pkt; + PKT_signature *sig; + + if(pk->is_revoked) + { + tty_printf(_("Key %s is already revoked.\n"),keystr_from_pk(pk)); + return 0; + } + + reason = ask_revocation_reason( 1, 0, 0 ); + /* user decided to cancel */ + if( !reason ) + return 0; + + sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key ); + rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, + 0x20, 0, opt.force_v4_certs?4:0, 0, 0, + revocation_reason_build_cb, reason ); + free_secret_key(sk); + if( rc ) + { + log_error(_("signing failed: %s\n"), g10_errstr(rc)); + goto scram; + } + + changed = 1; /* we changed the keyblock */ + + pkt = xmalloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + insert_kbnode( pub_keyblock, new_kbnode(pkt), 0 ); + commit_kbnode( &pub_keyblock ); + + update_trust=1; + + scram: + release_revocation_reason_info( reason ); + return changed; +} + +static int +menu_revsubkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) { PKT_public_key *mainpk; KBNODE node; @@ -3770,6 +4965,13 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) PKT_public_key *subpk = node->pkt->pkt.public_key; struct sign_attrib attrib; + if(subpk->is_revoked) + { + tty_printf(_("Subkey %s is already revoked.\n"), + keystr_from_pk(subpk)); + continue; + } + memset( &attrib, 0, sizeof attrib ); attrib.reason = reason; @@ -3780,13 +4982,13 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock ) sign_mk_attrib, &attrib ); free_secret_key(sk); if( rc ) { - log_error(_("signing failed: %s\n"), gpg_strerror (rc)); + log_error(_("signing failed: %s\n"), g10_errstr(rc)); release_revocation_reason_info( reason ); return changed; } changed = 1; /* we changed the keyblock */ - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; insert_kbnode( node, new_kbnode(pkt), 0 ); @@ -3833,7 +5035,6 @@ menu_showphoto( KBNODE keyblock ) int select_all = !count_selected_uids(keyblock); int count=0; PKT_public_key *pk=NULL; - u32 keyid[2]; /* Look for the public key first. We have to be really, really, explicit as to which photo this is, and what key it is a UID on @@ -3842,10 +5043,7 @@ menu_showphoto( KBNODE keyblock ) for( node = keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_KEY ) - { - pk = node->pkt->pkt.public_key; - keyid_from_pk(pk, keyid); - } + pk = node->pkt->pkt.public_key; else if( node->pkt->pkttype == PKT_USER_ID ) { PKT_user_id *uid = node->pkt->pkt.user_id; @@ -3865,9 +5063,9 @@ menu_showphoto( KBNODE keyblock ) parse_image_header(&uid->attribs[i],&type,&size)) { tty_printf(_("Displaying %s photo ID of size %ld for " - "key 0x%08lX (uid %d)\n"), + "key %s (uid %d)\n"), image_type_to_string(type,1), - (ulong)size,(ulong)keyid[1],count); + (ulong)size,keystr_from_pk(pk),count); show_photos(&uid->attribs[i],1,pk,NULL); } } diff --git a/g10/keygen.c b/g10/keygen.c index 72c5e1e8a..6a64ff317 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,6 +27,9 @@ #include <ctype.h> #include <errno.h> #include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include "gpg.h" #include "util.h" @@ -63,7 +67,9 @@ enum para_name { pPASSPHRASE, pPASSPHRASE_DEK, pPASSPHRASE_S2K, - pSERIALNO + pSERIALNO, + pBACKUPENCDIR, + pHANDLE }; struct para_data_s { @@ -87,13 +93,13 @@ struct output_control_s { struct { char *fname; char *newfname; - iobuf_t stream; + IOBUF stream; armor_filter_context_t afx; } pub; struct { char *fname; char *newfname; - iobuf_t stream; + IOBUF stream; armor_filter_context_t afx; } sec; }; @@ -115,21 +121,67 @@ static int nzip_prefs; static int mdc_available,ks_modify; static void do_generate_keypair( struct para_data_s *para, - struct output_control_s *outctrl, int card); -static int write_keyblock( iobuf_t out, KBNODE node ); -static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, + struct output_control_s *outctrl, int card ); +static int write_keyblock( IOBUF out, KBNODE node ); +static int gen_card_key (int algo, int keyno, int is_primary, + KBNODE pub_root, KBNODE sec_root, u32 expireval, struct para_data_s *para); +static int gen_card_key_with_backup (int algo, int keyno, int is_primary, + KBNODE pub_root, KBNODE sec_root, + u32 expireval, struct para_data_s *para, + const char *backup_dir); + + +static void +print_status_key_created (int letter, PKT_public_key *pk, const char *handle) +{ + byte array[MAX_FINGERPRINT_LEN], *s; + char *buf, *p; + size_t i, n; + + if (!handle) + handle = ""; + + buf = xmalloc (MAX_FINGERPRINT_LEN*2+31 + strlen (handle) + 1); + + p = buf; + if (letter || pk) + { + *p++ = letter; + *p++ = ' '; + fingerprint_from_pk (pk, array, &n); + s = array; + for (i=0; i < n ; i++, s++, p += 2) + sprintf (p, "%02X", *s); + } + if (*handle) + { + *p++ = ' '; + for (i=0; handle[i] && i < 100; i++) + *p++ = isspace ((unsigned int)handle[i])? '_':handle[i]; + } + *p = 0; + write_status_text ((letter || pk)?STATUS_KEY_CREATED:STATUS_KEY_NOT_CREATED, + buf); + xfree (buf); +} + +static void +print_status_key_not_created (const char *handle) +{ + print_status_key_created (0, NULL, handle); +} static void write_uid( KBNODE root, const char *s ) { - PACKET *pkt = xcalloc (1,sizeof *pkt ); + PACKET *pkt = xmalloc_clear(sizeof *pkt ); size_t n = strlen(s); pkt->pkttype = PKT_USER_ID; - pkt->pkt.user_id = xcalloc (1, sizeof *pkt->pkt.user_id + n - 1 ); + pkt->pkt.user_id = xmalloc_clear( sizeof *pkt->pkt.user_id + n - 1 ); pkt->pkt.user_id->len = n; pkt->pkt.user_id->ref = 1; strcpy(pkt->pkt.user_id->name, s); @@ -141,21 +193,22 @@ do_add_key_flags (PKT_signature *sig, unsigned int use) { byte buf[1]; - if (!use) - return; - buf[0] = 0; + + /* The spec says that all primary keys MUST be able to certify. */ + if(sig->sig_class!=0x18) + buf[0] |= 0x01; + if (use & PUBKEY_USAGE_SIG) - { - if(sig->sig_class==0x18) - buf[0] |= 0x02; /* Don't set the certify flag for subkeys */ - else - buf[0] |= 0x01 | 0x02; - } + buf[0] |= 0x02; if (use & PUBKEY_USAGE_ENC) buf[0] |= 0x04 | 0x08; if (use & PUBKEY_USAGE_AUTH) buf[0] |= 0x20; + + if (!buf[0]) + return; + build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1); } @@ -228,18 +281,6 @@ set_one_pref (int val, int type, const char *item, byte *buf, int *nbuf) return 0; } -#ifdef USE_AES -#define AES "S9 S8 S7 " -#else -#define AES "" -#endif - -#ifdef USE_CAST5 -#define CAST5 "S3 " -#else -#define CAST5 "" -#endif - /* * Parse the supplied string and use it to set the standard * preferences. The string may be in a form like the one printed by @@ -253,23 +294,71 @@ keygen_set_std_prefs (const char *string,int personal) byte sym[MAX_PREFS], hash[MAX_PREFS], zip[MAX_PREFS]; int nsym=0, nhash=0, nzip=0, val, rc=0; int mdc=1, modify=0; /* mdc defaults on, modify defaults off. */ + char dummy_string[45+1]; /* Enough for 15 items. */ - if (!string || !ascii_strcasecmp (string, "default")) { - if (opt.def_preference_list) - string=opt.def_preference_list; - else if ( !openpgp_cipher_test_algo(CIPHER_ALGO_IDEA) ) - string = AES CAST5 "S2 S1 H2 H3 Z2 Z1"; - else - string = AES CAST5 "S2 H2 H3 Z2 Z1"; - - /* If we have it, IDEA goes *after* 3DES so it won't be used - unless we're encrypting along with a V3 key. Ideally, we - would only put the S1 preference in if the key was RSA and - <=2048 bits, as that is what won't break PGP2, but that is - difficult with the current code, and not really worth - checking as a non-RSA <=2048 bit key wouldn't be usable by - PGP2 anyway. -dms */ - } + if (!string || !ascii_strcasecmp (string, "default")) + { + if (opt.def_preference_list) + string=opt.def_preference_list; + else + { + dummy_string[0]='\0'; + + /* The rationale why we use the order AES256,192,128 is + for compatibility reasons with PGP. If gpg would + define AES128 first, we would get the somewhat + confusing situation: + + gpg -r pgpkey -r gpgkey ---gives--> AES256 + gpg -r gpgkey -r pgpkey ---gives--> AES + + Note that by using --personal-cipher-preferences it is + possible to prefer AES128. + */ + + /* Make sure we do not add more than 15 items here, as we + could overflow the size of dummy_string. We currently + have at most 12. */ + if(!check_cipher_algo(CIPHER_ALGO_AES256)) + strcat(dummy_string,"S9 "); + if(!check_cipher_algo(CIPHER_ALGO_AES192)) + strcat(dummy_string,"S8 "); + if(!check_cipher_algo(CIPHER_ALGO_AES)) + strcat(dummy_string,"S7 "); + if(!check_cipher_algo(CIPHER_ALGO_CAST5)) + strcat(dummy_string,"S3 "); + strcat(dummy_string,"S2 "); /* 3DES */ + /* If we have it, IDEA goes *after* 3DES so it won't be + used unless we're encrypting along with a V3 key. + Ideally, we would only put the S1 preference in if the + key was RSA and <=2048 bits, as that is what won't + break PGP2, but that is difficult with the current + code, and not really worth checking as a non-RSA <=2048 + bit key wouldn't be usable by PGP2 anyway. -dms */ + if(!check_cipher_algo(CIPHER_ALGO_IDEA)) + strcat(dummy_string,"S1 "); + + /* SHA-1 */ + strcat(dummy_string,"H2 "); + + if(!check_digest_algo(DIGEST_ALGO_SHA256)) + strcat(dummy_string,"H8 "); + + /* RIPEMD160 */ + strcat(dummy_string,"H3 "); + + /* ZLIB */ + strcat(dummy_string,"Z2 "); + + if(!check_compress_algo(COMPRESS_ALGO_BZIP2)) + strcat(dummy_string,"Z3 "); + + /* ZIP */ + strcat(dummy_string,"Z1"); + + string=dummy_string; + } + } else if (!ascii_strcasecmp (string, "none")) string = ""; @@ -277,16 +366,16 @@ keygen_set_std_prefs (const char *string,int personal) { char *tok,*prefstring; - prefstring=xstrdup (string); /* need a writable string! */ + prefstring=xstrdup(string); /* need a writable string! */ while((tok=strsep(&prefstring," ,"))) { - if((val=openpgp_cipher_map_name(tok))) + if((val=string_to_cipher_algo(tok))) { if(set_one_pref(val,1,tok,sym,&nsym)) rc=-1; } - else if((val=openpgp_md_map_name(tok))) + else if((val=string_to_digest_algo(tok))) { if(set_one_pref(val,2,tok,hash,&nhash)) rc=-1; @@ -317,7 +406,7 @@ keygen_set_std_prefs (const char *string,int personal) } } - xfree (prefstring); + xfree(prefstring); } if(!rc) @@ -326,7 +415,7 @@ keygen_set_std_prefs (const char *string,int personal) { if(personal==PREFTYPE_SYM) { - xfree (opt.personal_cipher_prefs); + xfree(opt.personal_cipher_prefs); if(nsym==0) opt.personal_cipher_prefs=NULL; @@ -335,7 +424,7 @@ keygen_set_std_prefs (const char *string,int personal) int i; opt.personal_cipher_prefs= - xmalloc (sizeof(prefitem_t *)*(nsym+1)); + xmalloc(sizeof(prefitem_t *)*(nsym+1)); for (i=0; i<nsym; i++) { @@ -349,7 +438,7 @@ keygen_set_std_prefs (const char *string,int personal) } else if(personal==PREFTYPE_HASH) { - xfree (opt.personal_digest_prefs); + xfree(opt.personal_digest_prefs); if(nhash==0) opt.personal_digest_prefs=NULL; @@ -358,7 +447,7 @@ keygen_set_std_prefs (const char *string,int personal) int i; opt.personal_digest_prefs= - xmalloc (sizeof(prefitem_t *)*(nhash+1)); + xmalloc(sizeof(prefitem_t *)*(nhash+1)); for (i=0; i<nhash; i++) { @@ -372,7 +461,7 @@ keygen_set_std_prefs (const char *string,int personal) } else if(personal==PREFTYPE_ZIP) { - xfree (opt.personal_compress_prefs); + xfree(opt.personal_compress_prefs); if(nzip==0) opt.personal_compress_prefs=NULL; @@ -381,7 +470,7 @@ keygen_set_std_prefs (const char *string,int personal) int i; opt.personal_compress_prefs= - xmalloc (sizeof(prefitem_t *)*(nzip+1)); + xmalloc(sizeof(prefitem_t *)*(nzip+1)); for (i=0; i<nzip; i++) { @@ -408,20 +497,19 @@ keygen_set_std_prefs (const char *string,int personal) return rc; } -#undef CAST5 -#undef AES - /* Return a fake user ID containing the preferences. Caller must free. */ PKT_user_id *keygen_get_std_prefs(void) { int i,j=0; - PKT_user_id *uid=xcalloc (1,sizeof(PKT_user_id)); + PKT_user_id *uid=xmalloc_clear(sizeof(PKT_user_id)); if(!prefs_initialized) keygen_set_std_prefs(NULL,0); - uid->prefs=xmalloc ((sizeof(prefitem_t *)* + uid->ref=1; + + uid->prefs=xmalloc((sizeof(prefitem_t *)* (nsym_prefs+nhash_prefs+nzip_prefs+1))); for(i=0;i<nsym_prefs;i++,j++) @@ -445,8 +533,8 @@ PKT_user_id *keygen_get_std_prefs(void) uid->prefs[j].type=PREFTYPE_NONE; uid->prefs[j].value=0; - uid->mdc_feature=mdc_available; - uid->ks_modify=ks_modify; + uid->flags.mdc=mdc_available; + uid->flags.ks_modify=ks_modify; return uid; } @@ -467,7 +555,7 @@ add_feature_mdc (PKT_signature *sig,int enabled) if (!s || !n) { /* create a new one */ n = 1; - buf = xcalloc (1,n); + buf = xmalloc_clear (n); } else { buf = xmalloc (n); @@ -511,7 +599,7 @@ add_keyserver_modify (PKT_signature *sig,int enabled) if (!s || !n) { /* create a new one */ n = 1; - buf = xcalloc (1,n); + buf = xmalloc_clear (n); } else { buf = xmalloc (n); @@ -591,17 +679,67 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque ) return 0; } - int keygen_add_keyserver_url(PKT_signature *sig, void *opaque) { const char *url=opaque; - build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url)); + if(url) + build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url)); + else + delete_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS); return 0; } +int +keygen_add_notations(PKT_signature *sig,void *opaque) +{ + struct notation *notation; + + /* We always start clean */ + delete_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION); + delete_sig_subpkt(sig->unhashed,SIGSUBPKT_NOTATION); + sig->flags.notation=0; + + for(notation=opaque;notation;notation=notation->next) + if(!notation->flags.ignore) + { + unsigned char *buf; + unsigned int n1,n2; + + n1=strlen(notation->name); + if(notation->altvalue) + n2=strlen(notation->altvalue); + else if(notation->bdat) + n2=notation->blen; + else + n2=strlen(notation->value); + + buf = xmalloc( 8 + n1 + n2 ); + + /* human readable or not */ + buf[0] = notation->bdat?0:0x80; + buf[1] = buf[2] = buf[3] = 0; + buf[4] = n1 >> 8; + buf[5] = n1; + buf[6] = n2 >> 8; + buf[7] = n2; + memcpy(buf+8, notation->name, n1 ); + if(notation->altvalue) + memcpy(buf+8+n1, notation->altvalue, n2 ); + else if(notation->bdat) + memcpy(buf+8+n1, notation->bdat, n2 ); + else + memcpy(buf+8+n1, notation->value, n2 ); + build_sig_subpkt( sig, SIGSUBPKT_NOTATION | + (notation->flags.critical?SIGSUBPKT_FLAG_CRITICAL:0), + buf, 8+n1+n2 ); + xfree(buf); + } + + return 0; +} int keygen_add_revkey(PKT_signature *sig, void *opaque) @@ -625,6 +763,96 @@ keygen_add_revkey(PKT_signature *sig, void *opaque) return 0; } +int +make_backsig(PKT_signature *sig,PKT_public_key *pk, + PKT_public_key *sub_pk,PKT_secret_key *sub_sk) +{ + PKT_signature *backsig; + int rc; + + cache_public_key(sub_pk); + + rc=make_keysig_packet(&backsig,pk,NULL,sub_pk,sub_sk,0x19,0,0,0,0,NULL,NULL); + if(rc) + log_error("make_keysig_packet failed for backsig: %s\n",g10_errstr(rc)); + else + { + /* get it into a binary packed form. */ + IOBUF backsig_out=iobuf_temp(); + PACKET backsig_pkt; + + init_packet(&backsig_pkt); + backsig_pkt.pkttype=PKT_SIGNATURE; + backsig_pkt.pkt.signature=backsig; + rc=build_packet(backsig_out,&backsig_pkt); + free_packet(&backsig_pkt); + if(rc) + log_error("build_packet failed for backsig: %s\n",g10_errstr(rc)); + else + { + size_t pktlen=0; + byte *buf=iobuf_get_temp_buffer(backsig_out); + + /* Remove the packet header */ + if(buf[0]&0x40) + { + if(buf[1]<192) + { + pktlen=buf[1]; + buf+=2; + } + else if(buf[1]<224) + { + pktlen=(buf[1]-192)*256; + pktlen+=buf[2]+192; + buf+=3; + } + else if(buf[1]==255) + { + pktlen =buf[2] << 24; + pktlen|=buf[3] << 16; + pktlen|=buf[4] << 8; + pktlen|=buf[5]; + buf+=6; + } + else + BUG(); + } + else + { + int mark=1; + + switch(buf[0]&3) + { + case 3: + BUG(); + break; + + case 2: + pktlen =buf[mark++] << 24; + pktlen|=buf[mark++] << 16; + + case 1: + pktlen|=buf[mark++] << 8; + + case 0: + pktlen|=buf[mark++]; + } + + buf+=mark; + } + + /* now make the binary blob into a subpacket */ + build_sig_subpkt(sig,SIGSUBPKT_SIGNATURE,buf,pktlen); + + iobuf_close(backsig_out); + } + } + + return rc; +} + + static int write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, struct revocation_key *revkey ) @@ -652,11 +880,11 @@ write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, rc = make_keysig_packet(&sig,pk,NULL,NULL,sk,0x1F,0,0,0,0, keygen_add_revkey,revkey); if( rc ) { - log_error("make_keysig_packet failed: %s\n", gpg_strerror (rc) ); + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); return rc; } - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; add_kbnode( root, new_kbnode( pkt ) ); @@ -664,8 +892,8 @@ write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, } static int -write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, - unsigned int use ) +write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk, + unsigned int use ) { PACKET *pkt; PKT_signature *sig; @@ -678,7 +906,7 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, log_info(_("writing self signature\n")); /* get the uid packet from the list */ - node = find_kbnode( root, PKT_USER_ID ); + node = find_kbnode( pub_root, PKT_USER_ID ); if( !node ) BUG(); /* no user id packet in tree */ uid = node->pkt->pkt.user_id; @@ -696,26 +924,33 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0, keygen_add_std_prefs, pk ); if( rc ) { - log_error("make_keysig_packet failed: %s\n", gpg_strerror (rc) ); + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); return rc; } - pkt = xcalloc (1, sizeof *pkt ); + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; - add_kbnode( root, new_kbnode( pkt ) ); + add_kbnode( sec_root, new_kbnode( pkt ) ); + + pkt = xmalloc_clear( sizeof *pkt ); + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = copy_signature(NULL,sig); + add_kbnode( pub_root, new_kbnode( pkt ) ); return rc; } +/* sub_sk is currently unused (reserved for backsigs) */ static int -write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, +write_keybinding( KBNODE root, KBNODE pub_root, + PKT_secret_key *pri_sk, PKT_secret_key *sub_sk, unsigned int use ) { PACKET *pkt; PKT_signature *sig; int rc=0; KBNODE node; - PKT_public_key *pk, *subpk; + PKT_public_key *pri_pk, *sub_pk; struct opaque_data_usage_and_pk oduap; if( opt.verbose ) @@ -725,31 +960,39 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); if( !node ) BUG(); - pk = node->pkt->pkt.public_key; + pri_pk = node->pkt->pkt.public_key; /* we have to cache the key, so that the verification of the signature * creation is able to retrieve the public key */ - cache_public_key (pk); + cache_public_key (pri_pk); /* find the last subkey */ - subpk = NULL; + sub_pk = NULL; for(node=pub_root; node; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - subpk = node->pkt->pkt.public_key; + sub_pk = node->pkt->pkt.public_key; } - if( !subpk ) + if( !sub_pk ) BUG(); /* and make the signature */ oduap.usage = use; - oduap.pk = subpk; - rc = make_keysig_packet( &sig, pk, NULL, subpk, sk, 0x18, 0, 0, 0, 0, - keygen_add_key_flags_and_expire, &oduap ); + oduap.pk = sub_pk; + rc=make_keysig_packet(&sig, pri_pk, NULL, sub_pk, pri_sk, 0x18, 0, 0, 0, 0, + keygen_add_key_flags_and_expire, &oduap ); if( rc ) { - log_error("make_keysig_packet failed: %s\n", gpg_strerror (rc) ); + log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); return rc; } - pkt = xcalloc (1, sizeof *pkt ); + /* make a backsig */ + if(use&PUBKEY_USAGE_SIG) + { + rc=make_backsig(sig,pri_pk,sub_pk,sub_sk); + if(rc) + return rc; + } + + pkt = xmalloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; add_kbnode( root, new_kbnode( pkt ) ); @@ -757,6 +1000,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, } + static int key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, const char *topname, const char *elems) @@ -855,101 +1099,113 @@ genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root) static int gen_elg(int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval, + int is_subkey) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_sexp_t s_parms, s_key; - gcry_sexp_t misc_key_info; - - assert (is_ELGAMAL(algo)); + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; + gcry_sexp_t misc_key_info; - if (nbits < 512) - { - nbits = 1024; - log_info (_("keysize invalid; using %u bits\n"), nbits); + assert( is_ELGAMAL(algo) ); + + if( nbits < 512 ) { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits ); } - if ((nbits % 32)) - { - nbits = ((nbits + 31) / 32) * 32; - log_info (_("keysize rounded up to %u bits\n"), nbits); + if( (nbits % 32) ) { + nbits = ((nbits + 31) / 32) * 32; + log_info(_("keysize rounded up to %u bits\n"), nbits ); } - rc = gcry_sexp_build ( &s_parms, NULL, - "(genkey(%s(nbits %d)))", - algo == GCRY_PK_ELG_E ? "openpgp-elg" : - algo == GCRY_PK_ELG ? "elg" : "x-oops" , - (int)nbits); - if (rc) - log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + + rc = gcry_sexp_build ( &s_parms, NULL, + "(genkey(%s(nbits %d)))", + algo == GCRY_PK_ELG_E ? "openpgp-elg" : + algo == GCRY_PK_ELG ? "elg" : "x-oops" , + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - rc = gcry_pk_genkey (&s_key, s_parms); - gcry_sexp_release (s_parms); - if (rc) - { - log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); - return rc; - } + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + return rc; + } - sk = xcalloc (1, sizeof *sk); - pk = xcalloc (1, sizeof *pk); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if (expireval) - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - sk->pubkey_algo = pk->pubkey_algo = algo; + sk = xmalloc_clear( sizeof *sk ); + pk = xmalloc_clear( sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if( expireval ) { + sk->expiredate = pk->expiredate = sk->timestamp + expireval; + } + sk->pubkey_algo = pk->pubkey_algo = algo; +/* pk->pkey[0] = mpi_copy( skey[0] ); */ +/* pk->pkey[1] = mpi_copy( skey[1] ); */ +/* pk->pkey[2] = mpi_copy( skey[2] ); */ +/* sk->skey[0] = skey[0]; */ +/* sk->skey[1] = skey[1]; */ +/* sk->skey[2] = skey[2]; */ +/* sk->skey[3] = skey[3]; */ + + rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + free_secret_key (sk); + free_public_key (pk); + return rc; + } + rc = key_from_sexp (sk->skey, s_key, "private-key", "pgyx"); + if (rc) + { + log_error("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + free_secret_key (sk); + free_public_key (pk); + return rc; + } + misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); + gcry_sexp_release (s_key); + + sk->is_protected = 0; + sk->protect.algo = 0; - rc = key_from_sexp (pk->pkey, s_key, "public-key", "pgy"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - return rc; - } - rc = key_from_sexp (sk->skey, s_key, "private-key", "pgyx"); - if (rc) - { - log_error("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - return rc; - } - misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); - gcry_sexp_release (s_key); + sk->csum = checksum_mpi( sk->skey[3] ); + if( ret_sk ) /* return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); - sk->is_protected = 0; - sk->protect.algo = 0; + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + gcry_sexp_release (misc_key_info); + return rc; + } - sk->csum = checksum_mpi (sk->skey[3]); - if (ret_sk) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key (NULL, sk); + pkt = xmalloc_clear (sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); - rc = genhelp_protect (dek, s2k, sk); - if (rc) - { - free_public_key (pk); - free_secret_key (sk); - gcry_sexp_release (misc_key_info); - return rc; - } + /* Don't know whether it makes sense to have the factors, so for now + * we store them in the secret keyring (but they are not secret). */ + pkt = xmalloc_clear(sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - - /* don't know whether it makes sense to have the factors, so for now - * we store them in the secret keyring (but they are not secret) */ - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); - - genhelp_factors (misc_key_info, sec_root); - - return 0; + genhelp_factors (misc_key_info, sec_root); + + return 0; } @@ -958,95 +1214,104 @@ gen_elg(int algo, unsigned int nbits, */ static int gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval, int is_subkey) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_sexp_t s_parms, s_key; - gcry_sexp_t misc_key_info; + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; + gcry_sexp_t misc_key_info; - if (nbits > 1024 || nbits < 512) - { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits); + if( nbits > 1024 || nbits < 512 ) { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits ); } - if ((nbits % 64)) - { - nbits = ((nbits + 63) / 64) * 64; - log_info (_("keysize rounded up to %u bits\n"), nbits); + if( (nbits % 64) ) { + nbits = ((nbits + 63) / 64) * 64; + log_info(_("keysize rounded up to %u bits\n"), nbits ); } - rc = gcry_sexp_build (&s_parms, NULL, - "(genkey(dsa(nbits %d)))", - (int)nbits); - if (rc) - log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + rc = gcry_sexp_build (&s_parms, NULL, + "(genkey(dsa(nbits %d)))", + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - rc = gcry_pk_genkey (&s_key, s_parms); - gcry_sexp_release (s_parms); - if (rc) - { - log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); - return rc; - } - - sk = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if (expireval) - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + return rc; + } - rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); - gcry_sexp_release (s_key); - return rc; - } - rc = key_from_sexp (sk->skey, s_key, "private-key", "pqgyx"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - return rc; + sk = xmalloc_clear( sizeof *sk ); + pk = xmalloc_clear( sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if( expireval ) { + sk->expiredate = pk->expiredate = sk->timestamp + expireval; } - misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); - gcry_sexp_release (s_key); + sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; - sk->is_protected = 0; - sk->protect.algo = 0; + rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); + gcry_sexp_release (s_key); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + rc = key_from_sexp (sk->skey, s_key, "private-key", "pqgyx"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + misc_key_info = gcry_sexp_find_token (s_key, "misc-key-info", 0); + gcry_sexp_release (s_key); + + sk->is_protected = 0; + sk->protect.algo = 0; - sk->csum = checksum_mpi ( sk->skey[4] ); - if (ret_sk) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key( NULL, sk ); + sk->csum = checksum_mpi ( sk->skey[4] ); + if( ret_sk ) /* return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); - rc = genhelp_protect (dek, s2k, sk); - if (rc) - { - free_public_key (pk); - free_secret_key (sk); - gcry_sexp_release (misc_key_info); - return rc; - } + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + gcry_sexp_release (misc_key_info); + return rc; + } - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); + pkt = xmalloc_clear(sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); + /* Don't know whether it makes sense to have the factors, so for now + * we store them in the secret keyring (but they are not secret) + * p = 2 * q * f1 * f2 * ... * fn + * We store only f1 to f_n-1; fn can be calculated because p and q + * are known. + */ + pkt = xmalloc_clear(sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); - genhelp_factors (misc_key_info, sec_root); + genhelp_factors (misc_key_info, sec_root); - return 0; + return 0; } @@ -1055,95 +1320,98 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, */ static int gen_rsa(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, - STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) + STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval, int is_subkey) { - int rc; - PACKET *pkt; - PKT_secret_key *sk; - PKT_public_key *pk; - gcry_sexp_t s_parms, s_key; + int rc; + PACKET *pkt; + PKT_secret_key *sk; + PKT_public_key *pk; + gcry_sexp_t s_parms, s_key; - assert (is_RSA(algo)); + assert( is_RSA(algo) ); - if (nbits < 1024) - { - nbits = 1024; - log_info(_("keysize invalid; using %u bits\n"), nbits); + if( nbits < 1024 ) { + nbits = 1024; + log_info(_("keysize invalid; using %u bits\n"), nbits ); } - if ((nbits % 32)) - { - nbits = ((nbits + 31) / 32) * 32; - log_info (_("keysize rounded up to %u bits\n"), nbits); + if( (nbits % 32) ) { + nbits = ((nbits + 31) / 32) * 32; + log_info(_("keysize rounded up to %u bits\n"), nbits ); } - rc = gcry_sexp_build (&s_parms, NULL, - "(genkey(rsa(nbits %d)))", - (int)nbits); - if (rc) - log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + rc = gcry_sexp_build (&s_parms, NULL, + "(genkey(rsa(nbits %d)))", + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - rc = gcry_pk_genkey (&s_key, s_parms); - gcry_sexp_release (s_parms); - if (rc) - { - log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); - return rc; + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + return rc; + } + + sk = xmalloc_clear( sizeof *sk ); + pk = xmalloc_clear( sizeof *pk ); + sk->timestamp = pk->timestamp = make_timestamp(); + sk->version = pk->version = 4; + if( expireval ) { + sk->expiredate = pk->expiredate = sk->timestamp + expireval; } + sk->pubkey_algo = pk->pubkey_algo = algo; - sk = xcalloc (1, sizeof *sk ); - pk = xcalloc (1, sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); - sk->version = pk->version = 4; - if (expireval) - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - sk->pubkey_algo = pk->pubkey_algo = algo; + rc = key_from_sexp (pk->pkey, s_key, "public-key", "ne"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); + gcry_sexp_release (s_key); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu"); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + gcry_sexp_release (s_key); + free_public_key(pk); + free_secret_key(sk); + return rc; + } + gcry_sexp_release (s_key); - rc = key_from_sexp (pk->pkey, s_key, "public-key", "ne"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc)); - gcry_sexp_release (s_key); - return rc; - } - rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu"); - if (rc) - { - log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); - gcry_sexp_release (s_key); - return rc; - } - gcry_sexp_release (s_key); - - sk->is_protected = 0; - sk->protect.algo = 0; + sk->is_protected = 0; + sk->protect.algo = 0; - sk->csum = checksum_mpi (sk->skey[2] ); - sk->csum += checksum_mpi (sk->skey[3] ); - sk->csum += checksum_mpi (sk->skey[4] ); - sk->csum += checksum_mpi (sk->skey[5] ); - if (ret_sk) /* not a subkey: return an unprotected version of the sk */ - *ret_sk = copy_secret_key (NULL, sk); + sk->csum = checksum_mpi (sk->skey[2] ); + sk->csum += checksum_mpi (sk->skey[3] ); + sk->csum += checksum_mpi (sk->skey[4] ); + sk->csum += checksum_mpi (sk->skey[5] ); + if( ret_sk ) /* return an unprotected version of the sk */ + *ret_sk = copy_secret_key( NULL, sk ); - rc = genhelp_protect (dek, s2k, sk); - if (rc) - { - free_public_key (pk); - free_secret_key (sk); - return rc; - } + rc = genhelp_protect (dek, s2k, sk); + if (rc) + { + free_public_key (pk); + free_secret_key (sk); + return rc; + } - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; - pkt->pkt.public_key = pk; - add_kbnode (pub_root, new_kbnode( pkt )); + pkt = xmalloc_clear(sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); - pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; - pkt->pkt.secret_key = sk; - add_kbnode(sec_root, new_kbnode( pkt )); + pkt = xmalloc_clear(sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_SECRET_SUBKEY : PKT_SECRET_KEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); - return 0; + return 0; } @@ -1175,8 +1443,111 @@ check_valid_days( const char *s ) } +static void +print_key_flags(int flags) +{ + if(flags&PUBKEY_USAGE_SIG) + tty_printf("%s ",_("Sign")); + + if(flags&PUBKEY_USAGE_CERT) + tty_printf("%s ",_("Certify")); + + if(flags&PUBKEY_USAGE_ENC) + tty_printf("%s ",_("Encrypt")); + + if(flags&PUBKEY_USAGE_AUTH) + tty_printf("%s ",_("Authenticate")); +} + + +/* Returns the key flags */ +static unsigned int +ask_key_flags(int algo,int subkey) +{ + const char *togglers=_("SsEeAaQq"); + char *answer=NULL; + unsigned int current=0; + unsigned int possible=openpgp_pk_algo_usage(algo); + + if(strlen(togglers)!=8) + BUG(); + + /* Only primary keys may certify. */ + if(subkey) + possible&=~PUBKEY_USAGE_CERT; + + /* Preload the current set with the possible set, minus + authentication, since nobody really uses auth yet. */ + current=possible&~PUBKEY_USAGE_AUTH; + + for(;;) + { + tty_printf("\n"); + tty_printf(_("Possible actions for a %s key: "), + pubkey_algo_to_string(algo)); + print_key_flags(possible); + tty_printf("\n"); + tty_printf(_("Current allowed actions: ")); + print_key_flags(current); + tty_printf("\n\n"); + + if(possible&PUBKEY_USAGE_SIG) + tty_printf(_(" (%c) Toggle the sign capability\n"), + togglers[0]); + if(possible&PUBKEY_USAGE_ENC) + tty_printf(_(" (%c) Toggle the encrypt capability\n"), + togglers[2]); + if(possible&PUBKEY_USAGE_AUTH) + tty_printf(_(" (%c) Toggle the authenticate capability\n"), + togglers[4]); + + tty_printf(_(" (%c) Finished\n"),togglers[6]); + tty_printf("\n"); + + xfree(answer); + answer = cpr_get("keygen.flags",_("Your selection? ")); + cpr_kill_prompt(); + + if(strlen(answer)>1) + tty_printf(_("Invalid selection.\n")); + else if(*answer=='\0' || *answer==togglers[6] || *answer==togglers[7]) + break; + else if((*answer==togglers[0] || *answer==togglers[1]) + && possible&PUBKEY_USAGE_SIG) + { + if(current&PUBKEY_USAGE_SIG) + current&=~PUBKEY_USAGE_SIG; + else + current|=PUBKEY_USAGE_SIG; + } + else if((*answer==togglers[2] || *answer==togglers[3]) + && possible&PUBKEY_USAGE_ENC) + { + if(current&PUBKEY_USAGE_ENC) + current&=~PUBKEY_USAGE_ENC; + else + current|=PUBKEY_USAGE_ENC; + } + else if((*answer==togglers[4] || *answer==togglers[5]) + && possible&PUBKEY_USAGE_AUTH) + { + if(current&PUBKEY_USAGE_AUTH) + current&=~PUBKEY_USAGE_AUTH; + else + current|=PUBKEY_USAGE_AUTH; + } + else + tty_printf(_("Invalid selection.\n")); + } + + xfree(answer); + + return current; +} + + /**************** - * Returns: 0 to create both a DSA and a ElGamal key. + * Returns: 0 to create both a DSA and a Elgamal key. * and only if key flags are to be written the desired usage. */ static int @@ -1188,30 +1559,30 @@ ask_algo (int addmode, unsigned int *r_usage) *r_usage = 0; tty_printf(_("Please select what kind of key you want:\n")); if( !addmode ) - tty_printf(_(" (%d) DSA and ElGamal (default)\n"), 1 ); + tty_printf(_(" (%d) DSA and Elgamal (default)\n"), 1 ); tty_printf( _(" (%d) DSA (sign only)\n"), 2 ); - if( addmode ) - tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 ); if (opt.expert) - tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 4 ); + tty_printf( _(" (%d) DSA (set your own capabilities)\n"), 3 ); + if( addmode ) + tty_printf(_(" (%d) Elgamal (encrypt only)\n"), 4 ); tty_printf( _(" (%d) RSA (sign only)\n"), 5 ); if (addmode) - tty_printf( _(" (%d) RSA (encrypt only)\n"), 6 ); + tty_printf(_(" (%d) RSA (encrypt only)\n"), 6 ); if (opt.expert) - tty_printf( _(" (%d) RSA (sign and encrypt)\n"), 7 ); + tty_printf( _(" (%d) RSA (set your own capabilities)\n"), 7 ); for(;;) { answer = cpr_get("keygen.algo",_("Your selection? ")); cpr_kill_prompt(); algo = *answer? atoi(answer): 1; - xfree (answer); + xfree(answer); if( algo == 1 && !addmode ) { algo = 0; /* create both keys */ break; } else if( algo == 7 && opt.expert ) { algo = PUBKEY_ALGO_RSA; - *r_usage = PUBKEY_USAGE_ENC | PUBKEY_USAGE_SIG; + *r_usage=ask_key_flags(algo,addmode); break; } else if( algo == 6 && addmode ) { @@ -1224,26 +1595,16 @@ ask_algo (int addmode, unsigned int *r_usage) *r_usage = PUBKEY_USAGE_SIG; break; } - else if( algo == 4 && opt.expert) - { - tty_printf(_( -"The use of this algorithm is only supported by GnuPG. You will not be\n" -"able to use this key to communicate with PGP users. This algorithm is also\n" -"very slow, and may not be as secure as the other choices.\n")); - - if( cpr_get_answer_is_yes("keygen.algo.elg_se", - _("Create anyway? "))) - { - algo = PUBKEY_ALGO_ELGAMAL; - *r_usage = PUBKEY_USAGE_ENC | PUBKEY_USAGE_SIG; - break; - } - } - else if( algo == 3 && addmode ) { + else if( algo == 4 && addmode ) { algo = PUBKEY_ALGO_ELGAMAL_E; *r_usage = PUBKEY_USAGE_ENC; break; } + else if( algo == 3 && opt.expert ) { + algo = PUBKEY_ALGO_DSA; + *r_usage=ask_key_flags(algo,addmode); + break; + } else if( algo == 2 ) { algo = PUBKEY_ALGO_DSA; *r_usage = PUBKEY_USAGE_SIG; @@ -1252,6 +1613,7 @@ ask_algo (int addmode, unsigned int *r_usage) else tty_printf(_("Invalid selection.\n")); } + return algo; } @@ -1259,116 +1621,119 @@ ask_algo (int addmode, unsigned int *r_usage) static unsigned ask_keysize( int algo ) { - char *answer; - unsigned nbits; + unsigned int nbits, min, def=2048, max=4096; - if (algo != PUBKEY_ALGO_DSA && algo != PUBKEY_ALGO_RSA) { - tty_printf (_("About to generate a new %s keypair.\n" - " minimum keysize is 768 bits\n" - " default keysize is 1024 bits\n" - " highest suggested keysize is 2048 bits\n"), - gcry_pk_algo_name (algo) ); - } + if(opt.expert) + min=512; + else + min=1024; - for(;;) { - answer = cpr_get("keygen.size", - _("What keysize do you want? (1024) ")); - cpr_kill_prompt(); - nbits = *answer? atoi(answer): 1024; - xfree (answer); - if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) ) - tty_printf(_("DSA only allows keysizes from 512 to 1024\n")); - else if( algo == PUBKEY_ALGO_RSA && nbits < 1024 ) - tty_printf(_("keysize too small;" - " 1024 is smallest value allowed for RSA.\n")); - else if( nbits < 768 ) - tty_printf(_("keysize too small;" - " 768 is smallest value allowed.\n")); - else if( nbits > 4096 ) { - /* It is ridiculous and an annoyance to use larger key sizes! - * GnuPG can handle much larger sizes; but it takes an eternity - * to create such a key (but less than the time the Sirius - * Computer Corporation needs to process one of the usual - * complaints) and {de,en}cryption although needs some time. - * So, before you complain about this limitation, I suggest that - * you start a discussion with Marvin about this theme and then - * do whatever you want. */ - tty_printf(_("keysize too large; %d is largest value allowed.\n"), - 4096); + switch(algo) + { + case PUBKEY_ALGO_DSA: + if(opt.expert) + { + def=1024; + max=1024; } - else if( nbits > 2048 && !cpr_enabled() ) { - tty_printf( - _("Keysizes larger than 2048 are not suggested because\n" - "computations take REALLY long!\n")); - if( cpr_get_answer_is_yes("keygen.size.huge.okay",_( - "Are you sure that you want this keysize? ")) ) { - tty_printf(_("Okay, but keep in mind that your monitor " - "and keyboard radiation is also very vulnerable " - "to attacks!\n")); - break; - } + else + { + tty_printf(_("DSA keypair will have %u bits.\n"),1024); + return 1024; } - else - break; + break; + + case PUBKEY_ALGO_RSA: + min=1024; + break; } - tty_printf(_("Requested keysize is %u bits\n"), nbits ); - if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) { - nbits = ((nbits + 63) / 64) * 64; - tty_printf(_("rounded up to %u bits\n"), nbits ); + + tty_printf(_("%s keys may be between %u and %u bits long.\n"), + pubkey_algo_to_string(algo),min,max); + + for(;;) + { + char *prompt,*answer; + +#define PROMPTSTRING _("What keysize do you want? (%u) ") + + prompt=xmalloc(strlen(PROMPTSTRING)+20); + sprintf(prompt,PROMPTSTRING,def); + +#undef PROMPTSTRING + + answer = cpr_get("keygen.size",prompt); + cpr_kill_prompt(); + nbits = *answer? atoi(answer): def; + xfree(prompt); + xfree(answer); + + if(nbits<min || nbits>max) + tty_printf(_("%s keysizes must be in the range %u-%u\n"), + pubkey_algo_to_string(algo),min,max); + else + break; } - else if( (nbits % 32) ) { - nbits = ((nbits + 31) / 32) * 32; - tty_printf(_("rounded up to %u bits\n"), nbits ); + + tty_printf(_("Requested keysize is %u bits\n"), nbits ); + + if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) + { + nbits = ((nbits + 63) / 64) * 64; + tty_printf(_("rounded up to %u bits\n"), nbits ); + } + else if( (nbits % 32) ) + { + nbits = ((nbits + 31) / 32) * 32; + tty_printf(_("rounded up to %u bits\n"), nbits ); } - return nbits; + + return nbits; } /**************** - * Parse an expire string and return it's value in days. - * Returns -1 on error. + * Parse an expire string and return its value in seconds. + * Returns (u32)-1 on error. + * This isn't perfect since scan_isodatestr returns unix time, and + * OpenPGP actually allows a 32-bit time *plus* a 32-bit offset. + * Because of this, we only permit setting expirations up to 2106, but + * OpenPGP could theoretically allow up to 2242. I think we'll all + * just cope for the next few years until we get a 64-bit time_t or + * similar. */ -static int +u32 parse_expire_string( const char *string ) { int mult; - u32 abs_date=0; - u32 curtime = make_timestamp(); - int valid_days; + u32 seconds,abs_date=0,curtime = make_timestamp(); if( !*string ) - valid_days = 0; - else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime ) { - /* This calculation is not perfectly okay because we - * are later going to simply multiply by 86400 and don't - * correct for leapseconds. A solution would be to change - * the whole implemenation to work with dates and not intervals - * which are required for v3 keys. - */ - valid_days = abs_date/86400-curtime/86400+1; - } - else if( (mult=check_valid_days(string)) ) { - valid_days = atoi(string) * mult; - if( valid_days < 0 || valid_days > 39447 ) - valid_days = 0; - } - else { - valid_days = -1; - } - return valid_days; + seconds = 0; + else if ( !strncmp (string, "seconds=", 8) ) + seconds = atoi (string+8); + else if( (abs_date = scan_isodatestr(string)) && abs_date > curtime ) + seconds = abs_date - curtime; + else if( (mult=check_valid_days(string)) ) + seconds = atoi(string) * 86400L * mult; + else + seconds=(u32)-1; + + return seconds; } /* object == 0 for a key, and 1 for a sig */ u32 -ask_expire_interval(int object) +ask_expire_interval(int object,const char *def_expire) { + u32 interval; char *answer; - int valid_days=0; - u32 interval = 0; switch(object) { case 0: + if(def_expire) + BUG(); tty_printf(_("Please specify how long the key should be valid.\n" " 0 = key does not expire\n" " <n> = key expires in n days\n" @@ -1378,6 +1743,8 @@ ask_expire_interval(int object) break; case 1: + if(!def_expire) + BUG(); tty_printf(_("Please specify how long the signature should be valid.\n" " 0 = signature does not expire\n" " <n> = signature expires in n days\n" @@ -1395,91 +1762,76 @@ ask_expire_interval(int object) * date */ answer = NULL; - for(;;) { + for(;;) + { u32 curtime=make_timestamp(); - xfree (answer); + xfree(answer); if(object==0) answer = cpr_get("keygen.valid",_("Key is valid for? (0) ")); else - answer = cpr_get("siggen.valid",_("Signature is valid for? (0) ")); + { + char *prompt; + +#define PROMPTSTRING _("Signature is valid for? (%s) ") + /* This will actually end up larger than necessary because + of the 2 bytes for '%s' */ + prompt=xmalloc(strlen(PROMPTSTRING)+strlen(def_expire)+1); + sprintf(prompt,PROMPTSTRING,def_expire); +#undef PROMPTSTRING + + answer = cpr_get("siggen.valid",prompt); + xfree(prompt); + + if(*answer=='\0') + answer=xstrdup(def_expire); + } cpr_kill_prompt(); trim_spaces(answer); - valid_days = parse_expire_string( answer ); - if( valid_days < 0 ) { + interval = parse_expire_string( answer ); + if( interval == (u32)-1 ) + { tty_printf(_("invalid value\n")); continue; - } + } - if( !valid_days ) { - tty_printf(_("%s does not expire at all\n"), - object==0?"Key":"Signature"); - interval = 0; - } - else { - interval = valid_days * 86400L; - /* print the date when the key expires */ - tty_printf(_("%s expires at %s\n"), - object==0?"Key":"Signature", - asctimestamp((ulong)(curtime + interval) ) ); - /* FIXME: This check yields warning some machines: write a - configure check and do this check here only for 32 bit - machines */ + if( !interval ) + { + tty_printf((object==0) + ? _("Key does not expire at all\n") + : _("Signature does not expire at all\n")); + } + else + { + tty_printf(object==0 + ? _("Key expires at %s\n") + : _("Signature expires at %s\n"), + asctimestamp((ulong)(curtime + interval) ) ); + /* FIXME: This check yields warning on alhas: Write a + configure check and to this check here only for 32 bit + machines */ if( (time_t)((ulong)(curtime+interval)) < 0 ) - tty_printf(_("Your system can't display dates beyond 2038.\n" - "However, it will be correctly handled up to 2106.\n")); - } + tty_printf(_("Your system can't display dates beyond 2038.\n" + "However, it will be correctly handled up to 2106.\n")); + } if( cpr_enabled() || cpr_get_answer_is_yes("keygen.valid.okay", - _("Is this correct (y/n)? ")) ) - break; - } - xfree (answer); + _("Is this correct? (y/N) ")) ) + break; + } + + xfree(answer); return interval; } u32 ask_expiredate() { - u32 x = ask_expire_interval(0); + u32 x = ask_expire_interval(0,NULL); return x? make_timestamp() + x : 0; } -static int -count_chr( const char *string, int c ) -{ - int count; - - for (count=0; *string; string++ ) - if ( *string == c ) - count++; - return count; -} - - -static int -has_invalid_email_chars( const char *s ) -{ - int at_seen=0; - static char valid_chars[] = "01234567890_-." - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - for( ; *s; s++ ) { - if( *s & 0x80 ) - return 1; - if( *s == '@' ) - at_seen=1; - else if( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) ) - return 1; - else if( at_seen && !strchr( valid_chars, *s ) ) - return 1; - } - return 0; -} - - static char * ask_user_id( int mode ) { @@ -1488,8 +1840,9 @@ ask_user_id( int mode ) if( !mode ) tty_printf( _("\n" -"You need a User-ID to identify your key; the software constructs the user id\n" -"from Real Name, Comment and Email Address in this form:\n" +"You need a user ID to identify your key; " + "the software constructs the user ID\n" +"from the Real Name, Comment and Email Address in this form:\n" " \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") ); uid = aname = acomment = amail = NULL; for(;;) { @@ -1498,7 +1851,7 @@ ask_user_id( int mode ) if( !aname ) { for(;;) { - xfree (aname); + xfree(aname); aname = cpr_get("keygen.name",_("Real name: ")); trim_spaces(aname); cpr_kill_prompt(); @@ -1518,26 +1871,21 @@ ask_user_id( int mode ) } if( !amail ) { for(;;) { - xfree (amail); + xfree(amail); amail = cpr_get("keygen.email",_("Email address: ")); trim_spaces(amail); cpr_kill_prompt(); if( !*amail || opt.allow_freeform_uid ) break; /* no email address is okay */ - else if( has_invalid_email_chars(amail) - || count_chr(amail,'@') != 1 - || *amail == '@' - || amail[strlen(amail)-1] == '@' - || amail[strlen(amail)-1] == '.' - || strstr(amail, "..") ) - tty_printf(_("Not a valid email address\n")); + else if ( !is_valid_mailbox (amail) ) + tty_printf(_("Not a valid email address\n")); else break; } } if( !acomment ) { for(;;) { - xfree (acomment); + xfree(acomment); acomment = cpr_get("keygen.comment",_("Comment: ")); trim_spaces(acomment); cpr_kill_prompt(); @@ -1551,14 +1899,19 @@ ask_user_id( int mode ) } - xfree (uid); - uid = p = xmalloc (strlen(aname)+strlen(amail)+strlen(acomment)+12+10); + xfree(uid); + uid = p = xmalloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10); p = stpcpy(p, aname ); if( *acomment ) p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")"); if( *amail ) p = stpcpy(stpcpy(stpcpy(p," <"), amail),">"); + /* append a warning if we do not have dev/random + * or it is switched into quick testmode */ + if( quick_random_gen(-1) ) + strcpy(p, " (INSECURE!)" ); + /* print a note in case that UTF8 mapping has to be done */ for(p=uid; *p; p++ ) { if( *p & 0x80 ) { @@ -1571,19 +1924,30 @@ ask_user_id( int mode ) tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid); /* fixme: add a warning if this user-id already exists */ if( !*amail && !opt.allow_freeform_uid - && (strchr( aname, '@' ) || strchr( acomment, '@'))) { + && (strchr( aname, '@' ) || strchr( acomment, '@'))) { fail = 1; tty_printf(_("Please don't put the email address " "into the real name or the comment\n") ); } for(;;) { + /* TRANSLATORS: These are the allowed answers in + lower and uppercase. Below you will find the matching + string which should be translated accordingly and the + letter changed to match the one in the answer string. + + n = Change name + c = Change comment + e = Change email + o = Okay (ready, continue) + q = Quit + */ const char *ansstr = _("NnCcEeOoQq"); if( strlen(ansstr) != 10 ) BUG(); if( cpr_enabled() ) { - answer = xstrdup (ansstr+6); + answer = xstrdup(ansstr+6); answer[1] = 0; } else { @@ -1595,15 +1959,15 @@ ask_user_id( int mode ) if( strlen(answer) > 1 ) ; else if( *answer == ansstr[0] || *answer == ansstr[1] ) { - xfree (aname); aname = NULL; + xfree(aname); aname = NULL; break; } else if( *answer == ansstr[2] || *answer == ansstr[3] ) { - xfree (acomment); acomment = NULL; + xfree(acomment); acomment = NULL; break; } else if( *answer == ansstr[4] || *answer == ansstr[5] ) { - xfree (amail); amail = NULL; + xfree(amail); amail = NULL; break; } else if( *answer == ansstr[6] || *answer == ansstr[7] ) { @@ -1611,37 +1975,38 @@ ask_user_id( int mode ) tty_printf(_("Please correct the error first\n")); } else { - xfree (aname); aname = NULL; - xfree (acomment); acomment = NULL; - xfree (amail); amail = NULL; + xfree(aname); aname = NULL; + xfree(acomment); acomment = NULL; + xfree(amail); amail = NULL; break; } } else if( *answer == ansstr[8] || *answer == ansstr[9] ) { - xfree (aname); aname = NULL; - xfree (acomment); acomment = NULL; - xfree (amail); amail = NULL; - xfree (uid); uid = NULL; + xfree(aname); aname = NULL; + xfree(acomment); acomment = NULL; + xfree(amail); amail = NULL; + xfree(uid); uid = NULL; break; } - xfree (answer); + xfree(answer); } - xfree (answer); + xfree(answer); if( !amail && !acomment && !amail ) - break; - xfree (uid); uid = NULL; + break; + xfree(uid); uid = NULL; } if( uid ) { char *p = native_to_utf8( uid ); - xfree ( uid ); + xfree( uid ); uid = p; } return uid; } +/* FIXME: We need a way to cancel this prompt. */ static DEK * -ask_passphrase( STRING2KEY **ret_s2k ) +do_ask_passphrase( STRING2KEY **ret_s2k ) { DEK *dek = NULL; STRING2KEY *s2k; @@ -1649,10 +2014,10 @@ ask_passphrase( STRING2KEY **ret_s2k ) tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); - s2k = xmalloc ( sizeof *s2k ); + s2k = xmalloc_secure( sizeof *s2k ); for(;;) { s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; + s2k->hash_algo = S2K_DIGEST_ALGO; dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k,2, errtext, NULL); if( !dek ) { @@ -1660,8 +2025,8 @@ ask_passphrase( STRING2KEY **ret_s2k ) tty_printf(_("%s.\n"), _(errtext)); } else if( !dek->keylen ) { - xfree (dek); dek = NULL; - xfree (s2k); s2k = NULL; + xfree(dek); dek = NULL; + xfree(s2k); s2k = NULL; tty_printf(_( "You don't want a passphrase - this is probably a *bad* idea!\n" "I will do it anyway. You can change your passphrase at any time,\n" @@ -1678,37 +2043,31 @@ ask_passphrase( STRING2KEY **ret_s2k ) static int do_create( int algo, unsigned int nbits, KBNODE pub_root, KBNODE sec_root, - DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate ) + DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate, + int is_subkey ) { - int rc=0; + int rc=0; - if( !opt.batch ) - tty_printf(_( + if( !opt.batch ) + tty_printf(_( "We need to generate a lot of random bytes. It is a good idea to perform\n" "some other action (type on the keyboard, move the mouse, utilize the\n" "disks) during the prime generation; this gives the random number\n" "generator a better chance to gain enough entropy.\n") ); - if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E ) - rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate); - else if( algo == PUBKEY_ALGO_DSA ) - rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate); - else if( algo == PUBKEY_ALGO_RSA ) - rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate); - else - BUG(); + if( algo == PUBKEY_ALGO_ELGAMAL_E ) + rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate, + is_subkey); + else if( algo == PUBKEY_ALGO_DSA ) + rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate, + is_subkey); + else if( algo == PUBKEY_ALGO_RSA ) + rc = gen_rsa(algo, nbits, pub_root, sec_root, dek, s2k, sk, expiredate, + is_subkey); + else + BUG(); -#ifdef ENABLE_COMMENT_PACKETS - if( !rc ) { - add_kbnode( pub_root, - make_comment_node("#created by GNUPG v" VERSION " (" - PRINTABLE_OS_NAME ")")); - add_kbnode( sec_root, - make_comment_node("#created by GNUPG v" VERSION " (" - PRINTABLE_OS_NAME ")")); - } -#endif - return rc; + return rc; } @@ -1726,7 +2085,7 @@ generate_user_id() if( !p ) return NULL; n = strlen(p); - uid = xcalloc (1, sizeof *uid + n - 1 ); + uid = xmalloc_clear( sizeof *uid + n - 1 ); uid->len = n; strcpy(uid->name, p); uid->ref = 1; @@ -1742,11 +2101,11 @@ release_parameter_list( struct para_data_s *r ) for( ; r ; r = r2 ) { r2 = r->next; if( r->key == pPASSPHRASE_DEK ) - xfree ( r->u.dek ); + xfree( r->u.dek ); else if( r->key == pPASSPHRASE_S2K ) - xfree ( r->u.s2k ); + xfree( r->u.s2k ); - xfree (r); + xfree(r); } } @@ -1777,7 +2136,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key ) if( digitp( r->u.value ) ) i = atoi( r->u.value ); else - i = openpgp_pk_map_name ( r->u.value ); + i = string_to_pubkey_algo( r->u.value ); if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S) i = 0; /* we don't want to allow generation of these algorithms */ return i; @@ -1814,7 +2173,7 @@ parse_parameter_usage (const char *fname, } } r->u.usage = use; - return 0; + return 1; } static int @@ -1917,124 +2276,172 @@ static int proc_parameter_file( struct para_data_s *para, const char *fname, struct output_control_s *outctrl, int card ) { - struct para_data_s *r; - const char *s1, *s2, *s3; - size_t n; - char *p; - int i; + struct para_data_s *r; + const char *s1, *s2, *s3; + size_t n; + char *p; + int have_user_id=0,err,algo; - /* check that we have all required parameters */ - assert( get_parameter( para, pKEYTYPE ) ); - i = get_parameter_algo( para, pKEYTYPE ); - if( i < 1 || openpgp_pk_test_algo ( i, PUBKEY_USAGE_SIG ) ) { - r = get_parameter( para, pKEYTYPE ); - log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); - return -1; + /* Check that we have all required parameters. */ + r = get_parameter( para, pKEYTYPE ); + if(r) + { + algo=get_parameter_algo(para,pKEYTYPE); + if(check_pubkey_algo2(algo,PUBKEY_USAGE_SIG)) + { + log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); + return -1; + } + } + else + { + log_error("%s: no Key-Type specified\n",fname); + return -1; } - if (parse_parameter_usage (fname, para, pKEYUSAGE)) - return -1; + err=parse_parameter_usage (fname, para, pKEYUSAGE); + if(err==0) + { + /* Default to algo capabilities if key-usage is not provided */ + r=xmalloc_clear(sizeof(*r)); + r->key=pKEYUSAGE; + r->u.usage=openpgp_pk_algo_usage(algo); + r->next=para; + para=r; + } + else if(err==-1) + return -1; + + r = get_parameter( para, pSUBKEYTYPE ); + if(r) + { + algo=get_parameter_algo( para, pSUBKEYTYPE); + if(check_pubkey_algo(algo)) + { + log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); + return -1; + } - i = get_parameter_algo( para, pSUBKEYTYPE ); - if( i > 0 && openpgp_pk_test_algo ( i, 0 ) ) { - r = get_parameter( para, pSUBKEYTYPE ); - log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); + err=parse_parameter_usage (fname, para, pSUBKEYUSAGE); + if(err==0) + { + /* Default to algo capabilities if subkey-usage is not + provided */ + r=xmalloc_clear(sizeof(*r)); + r->key=pSUBKEYUSAGE; + r->u.usage=openpgp_pk_algo_usage(algo); + r->next=para; + para=r; + } + else if(err==-1) return -1; } - if (i > 0 && parse_parameter_usage (fname, para, pSUBKEYUSAGE)) - return -1; - - if( !get_parameter_value( para, pUSERID ) ) { - /* create the formatted user ID */ - s1 = get_parameter_value( para, pNAMEREAL ); - s2 = get_parameter_value( para, pNAMECOMMENT ); - s3 = get_parameter_value( para, pNAMEEMAIL ); - if( s1 || s2 || s3 ) { - n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0); - r = xcalloc (1, sizeof *r + n + 20 ); - r->key = pUSERID; - p = r->u.value; - if( s1 ) - p = stpcpy(p, s1 ); - if( s2 ) - p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")"); - if( s3 ) - p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">"); - r->next = para; - para = r; + if( get_parameter_value( para, pUSERID ) ) + have_user_id=1; + else + { + /* create the formatted user ID */ + s1 = get_parameter_value( para, pNAMEREAL ); + s2 = get_parameter_value( para, pNAMECOMMENT ); + s3 = get_parameter_value( para, pNAMEEMAIL ); + if( s1 || s2 || s3 ) + { + n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0); + r = xmalloc_clear( sizeof *r + n + 20 ); + r->key = pUSERID; + p = r->u.value; + if( s1 ) + p = stpcpy(p, s1 ); + if( s2 ) + p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")"); + if( s3 ) + p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">"); + r->next = para; + para = r; + have_user_id=1; } } - /* Set preferences, if any. */ - keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0); - - /* Set revoker, if any. */ - if (parse_revocation_key (fname, para, pREVOKER)) + if(!have_user_id) + { + log_error("%s: no User-ID specified\n",fname); return -1; + } - /* make DEK and S2K from the Passphrase */ - r = get_parameter( para, pPASSPHRASE ); - if( r && *r->u.value ) { - /* we have a plain text passphrase - create a DEK from it. - * It is a little bit ridiculous to keep it in secure memory - * but because we do this always, why not here. */ - STRING2KEY *s2k; - DEK *dek; + /* Set preferences, if any. */ + keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0); - s2k = xmalloc_secure ( sizeof *s2k ); - s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; - set_next_passphrase( r->u.value ); - dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, - NULL, NULL); - set_next_passphrase( NULL ); - assert( dek ); - memset( r->u.value, 0, strlen(r->u.value) ); - - r = xcalloc (1, sizeof *r ); - r->key = pPASSPHRASE_S2K; - r->u.s2k = s2k; - r->next = para; - para = r; - r = xcalloc (1, sizeof *r ); - r->key = pPASSPHRASE_DEK; - r->u.dek = dek; - r->next = para; - para = r; - } + /* Set revoker, if any. */ + if (parse_revocation_key (fname, para, pREVOKER)) + return -1; + + /* make DEK and S2K from the Passphrase */ + r = get_parameter( para, pPASSPHRASE ); + if( r && *r->u.value ) { + /* we have a plain text passphrase - create a DEK from it. + * It is a little bit ridiculous to keep it ih secure memory + * but becuase we do this alwasy, why not here */ + STRING2KEY *s2k; + DEK *dek; + + s2k = xmalloc_secure( sizeof *s2k ); + s2k->mode = opt.s2k_mode; + s2k->hash_algo = S2K_DIGEST_ALGO; + set_next_passphrase( r->u.value ); + dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, + NULL, NULL); + set_next_passphrase( NULL ); + assert( dek ); + memset( r->u.value, 0, strlen(r->u.value) ); + + r = xmalloc_clear( sizeof *r ); + r->key = pPASSPHRASE_S2K; + r->u.s2k = s2k; + r->next = para; + para = r; + r = xmalloc_clear( sizeof *r ); + r->key = pPASSPHRASE_DEK; + r->u.dek = dek; + r->next = para; + para = r; + } + + /* make KEYEXPIRE from Expire-Date */ + r = get_parameter( para, pEXPIREDATE ); + if( r && *r->u.value ) + { + u32 seconds; - /* make KEYEXPIRE from Expire-Date */ - r = get_parameter( para, pEXPIREDATE ); - if( r && *r->u.value ) { - i = parse_expire_string( r->u.value ); - if( i < 0 ) { - log_error("%s:%d: invalid expire date\n", fname, r->lnr ); - return -1; + seconds = parse_expire_string( r->u.value ); + if( seconds == (u32)-1 ) + { + log_error("%s:%d: invalid expire date\n", fname, r->lnr ); + return -1; } - r->u.expire = i * 86400L; - r->key = pKEYEXPIRE; /* change hat entry */ - /* also set it for the subkey */ - r = xcalloc (1, sizeof *r + 20 ); - r->key = pSUBKEYEXPIRE; - r->u.expire = i * 86400L; - r->next = para; - para = r; + r->u.expire = seconds; + r->key = pKEYEXPIRE; /* change hat entry */ + /* also set it for the subkey */ + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pSUBKEYEXPIRE; + r->u.expire = seconds; + r->next = para; + para = r; } - if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) { - log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr ); - return -1; - } + if( !!outctrl->pub.newfname ^ !!outctrl->sec.newfname ) { + log_error("%s:%d: only one ring name is set\n", fname, outctrl->lnr ); + return -1; + } - do_generate_keypair( para, outctrl, card); - return 0; + do_generate_keypair( para, outctrl, card ); + return 0; } /**************** * Kludge to allow non interactive key generation controlled - * by a parameter file (which currently is only stdin) + * by a parameter file. * Note, that string parameters are expected to be in UTF-8 */ static void @@ -2056,10 +2463,13 @@ read_parameter_file( const char *fname ) { "Passphrase", pPASSPHRASE }, { "Preferences", pPREFERENCES }, { "Revoker", pREVOKER }, + { "Handle", pHANDLE }, { NULL, 0 } }; - FILE *fp; - char line[1024], *p; + IOBUF fp; + byte *line; + unsigned int maxlen, nline; + char *p; int lnr; const char *err = NULL; struct para_data_s *para, *r; @@ -2068,26 +2478,32 @@ read_parameter_file( const char *fname ) memset( &outctrl, 0, sizeof( outctrl ) ); - if( !fname || !*fname || !strcmp(fname,"-") ) { - fp = stdin; - fname = "-"; - } - else { - fp = fopen( fname, "r" ); - if( !fp ) { - log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); - return; - } + if( !fname || !*fname) + fname = "-"; + + fp = iobuf_open (fname); + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } + if (!fp) { + log_error (_("can't open `%s': %s\n"), fname, strerror(errno) ); + return; } + iobuf_ioctl (fp, 3, 1, NULL); /* No file caching. */ lnr = 0; err = NULL; para = NULL; - while( fgets( line, DIM(line)-1, fp ) ) { + maxlen = 1024; + line = NULL; + while ( iobuf_read_line (fp, &line, &nline, &maxlen) ) { char *keyword, *value; lnr++; - if( *line && line[strlen(line)-1] != '\n' ) { + if( !maxlen ) { err = "line too long"; break; } @@ -2111,7 +2527,9 @@ read_parameter_file( const char *fname ) outctrl.dryrun = 1; else if( !ascii_strcasecmp( keyword, "%commit" ) ) { outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl, 0 ); + if (proc_parameter_file( para, fname, &outctrl, 0 )) + print_status_key_not_created + (get_parameter_value (para, pHANDLE)); release_parameter_list( para ); para = NULL; } @@ -2119,8 +2537,8 @@ read_parameter_file( const char *fname ) if( outctrl.pub.fname && !strcmp( outctrl.pub.fname, value ) ) ; /* still the same file - ignore it */ else { - xfree ( outctrl.pub.newfname ); - outctrl.pub.newfname = xstrdup ( value ); + xfree( outctrl.pub.newfname ); + outctrl.pub.newfname = xstrdup( value ); outctrl.use_files = 1; } } @@ -2128,8 +2546,8 @@ read_parameter_file( const char *fname ) if( outctrl.sec.fname && !strcmp( outctrl.sec.fname, value ) ) ; /* still the same file - ignore it */ else { - xfree ( outctrl.sec.newfname ); - outctrl.sec.newfname = xstrdup ( value ); + xfree( outctrl.sec.newfname ); + outctrl.sec.newfname = xstrdup( value ); outctrl.use_files = 1; } } @@ -2171,7 +2589,9 @@ read_parameter_file( const char *fname ) if( keywords[i].key == pKEYTYPE && para ) { outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl, 0 ); + if (proc_parameter_file( para, fname, &outctrl, 0 )) + print_status_key_not_created + (get_parameter_value (para, pHANDLE)); release_parameter_list( para ); para = NULL; } @@ -2185,7 +2605,7 @@ read_parameter_file( const char *fname ) break; } } - r = xcalloc (1, sizeof *r + strlen( value ) ); + r = xmalloc_clear( sizeof *r + strlen( value ) ); r->lnr = lnr; r->key = keywords[i].key; strcpy( r->u.value, value ); @@ -2194,36 +2614,47 @@ read_parameter_file( const char *fname ) } if( err ) log_error("%s:%d: %s\n", fname, lnr, err ); - else if( ferror(fp) ) { - log_error("%s:%d: read error: %s\n", fname, lnr, strerror(errno) ); + else if( iobuf_error (fp) ) { + log_error("%s:%d: read error\n", fname, lnr); } else if( para ) { outctrl.lnr = lnr; - proc_parameter_file( para, fname, &outctrl, 0 ); + if (proc_parameter_file( para, fname, &outctrl, 0 )) + print_status_key_not_created (get_parameter_value (para, pHANDLE)); } if( outctrl.use_files ) { /* close open streams */ iobuf_close( outctrl.pub.stream ); iobuf_close( outctrl.sec.stream ); - xfree ( outctrl.pub.fname ); - xfree ( outctrl.pub.newfname ); - xfree ( outctrl.sec.fname ); - xfree ( outctrl.sec.newfname ); + + /* Must invalidate that ugly cache to actually close it. */ + if (outctrl.pub.fname) + iobuf_ioctl (NULL, 2, 0, (char*)outctrl.pub.fname); + if (outctrl.sec.fname) + iobuf_ioctl (NULL, 2, 0, (char*)outctrl.sec.fname); + + xfree( outctrl.pub.fname ); + xfree( outctrl.pub.newfname ); + xfree( outctrl.sec.fname ); + xfree( outctrl.sec.newfname ); } release_parameter_list( para ); - if( strcmp( fname, "-" ) ) - fclose(fp); + iobuf_close (fp); } -/**************** +/* * Generate a keypair (fname is only used in batch mode) If * CARD_SERIALNO is not NULL the fucntion will create the keys on an - * OpenPGP Card. + * OpenPGP Card. If BACKUP_ENCRYPTION_DIR has been set and + * CARD_SERIALNO is NOT NULL, the encryption key for the card gets + * generate in software, imported to the card and a backup file + * written to directory given by this argument . */ void -generate_keypair( const char *fname, const char *card_serialno ) +generate_keypair (const char *fname, const char *card_serialno, + const char *backup_encryption_dir) { unsigned int nbits; char *uid = NULL; @@ -2236,16 +2667,16 @@ generate_keypair( const char *fname, const char *card_serialno ) struct para_data_s *para = NULL; struct para_data_s *r; struct output_control_s outctrl; - - memset (&outctrl, 0, sizeof (outctrl)); - + + memset( &outctrl, 0, sizeof( outctrl ) ); + if (opt.batch && card_serialno) { /* We don't yet support unattended key generation. */ - log_error (_("sorry, can't do this in batch mode\n")); + log_error (_("can't do this in batch mode\n")); return; } - + if (opt.batch) { read_parameter_file( fname ); @@ -2254,14 +2685,15 @@ generate_keypair( const char *fname, const char *card_serialno ) if (card_serialno) { +#ifdef ENABLE_CARD_SUPPORT r = xcalloc (1, sizeof *r + strlen (card_serialno) ); r->key = pSERIALNO; strcpy( r->u.value, card_serialno); r->next = para; para = r; - + algo = PUBKEY_ALGO_RSA; - + r = xcalloc (1, sizeof *r + 20 ); r->key = pKEYTYPE; sprintf( r->u.value, "%d", algo ); @@ -2272,7 +2704,7 @@ generate_keypair( const char *fname, const char *card_serialno ) strcpy (r->u.value, "sign"); r->next = para; para = r; - + r = xcalloc (1, sizeof *r + 20 ); r->key = pSUBKEYTYPE; sprintf( r->u.value, "%d", algo ); @@ -2283,435 +2715,540 @@ generate_keypair( const char *fname, const char *card_serialno ) strcpy (r->u.value, "encrypt"); r->next = para; para = r; - + r = xcalloc (1, sizeof *r + 20 ); r->key = pAUTHKEYTYPE; sprintf( r->u.value, "%d", algo ); r->next = para; para = r; + + if (backup_encryption_dir) + { + r = xcalloc (1, sizeof *r + strlen (backup_encryption_dir) ); + r->key = pBACKUPENCDIR; + strcpy (r->u.value, backup_encryption_dir); + r->next = para; + para = r; + } +#endif /*ENABLE_CARD_SUPPORT*/ } else { - algo = ask_algo (0, &use); - - if (!algo) + algo = ask_algo( 0, &use ); + if( !algo ) { /* default: DSA with ElG subkey of the specified size */ both = 1; - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYTYPE; sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); r->next = para; para = r; - tty_printf(_("DSA keypair will have 1024 bits.\n")); - r = xcalloc (1, sizeof *r + 20 ); + tty_printf(_("DSA keypair will have %u bits.\n"),1024); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYLENGTH; strcpy( r->u.value, "1024" ); r->next = para; para = r; - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYUSAGE; strcpy( r->u.value, "sign" ); r->next = para; para = r; - + algo = PUBKEY_ALGO_ELGAMAL_E; - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pSUBKEYTYPE; sprintf( r->u.value, "%d", algo ); r->next = para; para = r; - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pSUBKEYUSAGE; strcpy( r->u.value, "encrypt" ); r->next = para; - r->next = para; para = r; } else { - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYTYPE; sprintf( r->u.value, "%d", algo ); r->next = para; para = r; - + if (use) { - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 25 ); r->key = pKEYUSAGE; - sprintf( r->u.value, "%s%s", + sprintf( r->u.value, "%s%s%s", (use & PUBKEY_USAGE_SIG)? "sign ":"", - (use & PUBKEY_USAGE_ENC)? "encrypt ":"" ); + (use & PUBKEY_USAGE_ENC)? "encrypt ":"", + (use & PUBKEY_USAGE_AUTH)? "auth":"" ); r->next = para; para = r; } + } - + nbits = ask_keysize( algo ); - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = both? pSUBKEYLENGTH : pKEYLENGTH; sprintf( r->u.value, "%u", nbits); r->next = para; para = r; } - - expire = ask_expire_interval(0); - r = xcalloc (1, sizeof *r + 20 ); + + expire = ask_expire_interval(0,NULL); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYEXPIRE; r->u.expire = expire; r->next = para; para = r; - r = xcalloc (1, sizeof *r + 20 ); + r = xmalloc_clear( sizeof *r + 20 ); r->key = pSUBKEYEXPIRE; r->u.expire = expire; r->next = para; para = r; - + uid = ask_user_id(0); - if (!uid) + if( !uid ) { log_error(_("Key generation canceled.\n")); release_parameter_list( para ); return; } - r = xcalloc (1, sizeof *r + strlen(uid) ); + r = xmalloc_clear( sizeof *r + strlen(uid) ); r->key = pUSERID; strcpy( r->u.value, uid ); r->next = para; para = r; - - dek = card_serialno? NULL : ask_passphrase( &s2k ); - if (dek) + + dek = card_serialno? NULL : do_ask_passphrase( &s2k ); + if( dek ) { - r = xcalloc (1, sizeof *r ); + r = xmalloc_clear( sizeof *r ); r->key = pPASSPHRASE_DEK; r->u.dek = dek; r->next = para; para = r; - r = xcalloc (1, sizeof *r ); + r = xmalloc_clear( sizeof *r ); r->key = pPASSPHRASE_S2K; r->u.s2k = s2k; r->next = para; para = r; } - - proc_parameter_file (para, "[internal]", &outctrl, !!card_serialno); - release_parameter_list (para); + + proc_parameter_file( para, "[internal]", &outctrl, !!card_serialno); + release_parameter_list( para ); } -static void -print_status_key_created (int letter, PKT_public_key *pk) +#ifdef ENABLE_CARD_SUPPORT +/* Generate a raw key and return it as a secret key packet. The + function will ask for the passphrase and return a protected as well + as an unprotected copy of a new secret key packet. 0 is returned + on success and the caller must then free the returned values. */ +static int +generate_raw_key (int algo, unsigned int nbits, u32 created_at, + PKT_secret_key **r_sk_unprotected, + PKT_secret_key **r_sk_protected) { - byte array[MAX_FINGERPRINT_LEN], *s; - char buf[MAX_FINGERPRINT_LEN*2+30], *p; - size_t i, n; - - p = buf; - *p++ = letter; - *p++ = ' '; - fingerprint_from_pk (pk, array, &n); - s = array; - for (i=0; i < n ; i++, s++, p += 2) - sprintf (p, "%02X", *s); - *p = 0; - write_status_text (STATUS_KEY_CREATED, buf); -} + int rc; + DEK *dek = NULL; + STRING2KEY *s2k = NULL; + PKT_secret_key *sk = NULL; + int i; + size_t nskey, npkey; + npkey = pubkey_get_npkey (algo); + nskey = pubkey_get_nskey (algo); + assert (nskey <= PUBKEY_MAX_NSKEY && npkey < nskey); + if (nbits < 512) + { + nbits = 512; + log_info (_("keysize invalid; using %u bits\n"), nbits ); + } -static void -do_generate_keypair (struct para_data_s *para, - struct output_control_s *outctrl, int card) -{ - KBNODE pub_root = NULL; - KBNODE sec_root = NULL; - PKT_secret_key *sk = NULL; - const char *s; - struct revocation_key *revkey; - int rc; - int did_sub = 0; + if ((nbits % 32)) + { + nbits = ((nbits + 31) / 32) * 32; + log_info(_("keysize rounded up to %u bits\n"), nbits ); + } + + dek = do_ask_passphrase (&s2k); + + sk = xmalloc_clear (sizeof *sk); + sk->timestamp = created_at; + sk->version = 4; + sk->pubkey_algo = algo; - if (outctrl->dryrun) + if ( !is_RSA (algo) ) { - log_info ("dry-run mode - key generation skipped\n"); - return; + log_error ("only RSA is supported for offline generated keys\n"); + rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + goto leave; + } + rc = gcry_sexp_build (&s_parms, NULL, + "(genkey(rsa(nbits %d)))", + (int)nbits); + if (rc) + log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + rc = gcry_pk_genkey (&s_key, s_parms); + gcry_sexp_release (s_parms); + if (rc) + { + log_error ("gcry_pk_genkey failed: %s\n", gpg_strerror (rc) ); + goto leave; + } + rc = key_from_sexp (sk->skey, s_key, "private-key", "nedpqu"); + gcry_sexp_release (s_key); + if (rc) + { + log_error ("key_from_sexp failed: %s\n", gpg_strerror (rc) ); + goto leave; } + + for (i=npkey; i < nskey; i++) + sk->csum += checksum_mpi (sk->skey[i]); + if (r_sk_unprotected) + *r_sk_unprotected = copy_secret_key (NULL, sk); - if (outctrl->use_files) + rc = genhelp_protect (dek, s2k, sk); + if (rc) + goto leave; + + if (r_sk_protected) { - if (outctrl->pub.newfname) - { - iobuf_close (outctrl->pub.stream); - outctrl->pub.stream = NULL; - xfree (outctrl->pub.fname); - outctrl->pub.fname = outctrl->pub.newfname; - outctrl->pub.newfname = NULL; - - outctrl->pub.stream = iobuf_create (outctrl->pub.fname); - if (!outctrl->pub.stream) - { - log_error ("can't create `%s': %s\n", outctrl->pub.fname, - strerror (errno)); - return; + *r_sk_protected = sk; + sk = NULL; + } + + leave: + if (sk) + free_secret_key (sk); + xfree (dek); + xfree (s2k); + return rc; +} +#endif /* ENABLE_CARD_SUPPORT */ + +/* Create and delete a dummy packet to start off a list of kbnodes. */ +static void +start_tree(KBNODE *tree) +{ + PACKET *pkt; + + pkt=xmalloc_clear(sizeof(*pkt)); + pkt->pkttype=PKT_NONE; + *tree=new_kbnode(pkt); + delete_kbnode(*tree); +} + +static void +do_generate_keypair( struct para_data_s *para, + struct output_control_s *outctrl, int card ) +{ + KBNODE pub_root = NULL; + KBNODE sec_root = NULL; + PKT_secret_key *pri_sk = NULL, *sub_sk = NULL; + const char *s; + struct revocation_key *revkey; + int rc; + int did_sub = 0; + + if( outctrl->dryrun ) + { + log_info("dry-run mode - key generation skipped\n"); + return; + } + + if( outctrl->use_files ) { + if( outctrl->pub.newfname ) { + iobuf_close(outctrl->pub.stream); + outctrl->pub.stream = NULL; + if (outctrl->pub.fname) + iobuf_ioctl (NULL, 2, 0, (char*)outctrl->pub.fname); + xfree( outctrl->pub.fname ); + outctrl->pub.fname = outctrl->pub.newfname; + outctrl->pub.newfname = NULL; + + if (is_secured_filename (outctrl->pub.fname) ) { + outctrl->pub.stream = NULL; + errno = EPERM; + } + else + outctrl->pub.stream = iobuf_create( outctrl->pub.fname ); + if( !outctrl->pub.stream ) { + log_error(_("can't create `%s': %s\n"), outctrl->pub.newfname, + strerror(errno) ); + return; } - if (opt.armor) - { - outctrl->pub.afx.what = 1; - iobuf_push_filter (outctrl->pub.stream, armor_filter, - &outctrl->pub.afx); + if( opt.armor ) { + outctrl->pub.afx.what = 1; + iobuf_push_filter( outctrl->pub.stream, armor_filter, + &outctrl->pub.afx ); } } - if (outctrl->sec.newfname) - { - iobuf_close (outctrl->sec.stream); - outctrl->sec.stream = NULL; - xfree (outctrl->sec.fname); - outctrl->sec.fname = outctrl->sec.newfname; - outctrl->sec.newfname = NULL; - - outctrl->sec.stream = iobuf_create (outctrl->sec.fname); - if (!outctrl->sec.stream) - { - log_error ("can't create `%s': %s\n", outctrl->sec.fname, - strerror (errno)); - return; + if( outctrl->sec.newfname ) { + mode_t oldmask; + + iobuf_close(outctrl->sec.stream); + outctrl->sec.stream = NULL; + if (outctrl->sec.fname) + iobuf_ioctl (NULL, 2, 0, (char*)outctrl->sec.fname); + xfree( outctrl->sec.fname ); + outctrl->sec.fname = outctrl->sec.newfname; + outctrl->sec.newfname = NULL; + + oldmask = umask (077); + if (is_secured_filename (outctrl->sec.fname) ) { + outctrl->sec.stream = NULL; + errno = EPERM; + } + else + outctrl->sec.stream = iobuf_create( outctrl->sec.fname ); + umask (oldmask); + if( !outctrl->sec.stream ) { + log_error(_("can't create `%s': %s\n"), outctrl->sec.newfname, + strerror(errno) ); + return; } - if (opt.armor) - { - outctrl->sec.afx.what = 5; - iobuf_push_filter (outctrl->sec.stream, armor_filter, - &outctrl->sec.afx); + if( opt.armor ) { + outctrl->sec.afx.what = 5; + iobuf_push_filter( outctrl->sec.stream, armor_filter, + &outctrl->sec.afx ); } } - assert (outctrl->pub.stream); - assert (outctrl->sec.stream); - if (opt.verbose) - { - log_info (_("writing public key to `%s'\n"), outctrl->pub.fname); - if (card) - log_info (_("writing secret key stub to `%s'\n"), - outctrl->sec.fname); - else - log_info (_("writing secret key to `%s'\n"), outctrl->sec.fname); - } + assert( outctrl->pub.stream ); + assert( outctrl->sec.stream ); + if( opt.verbose ) { + log_info(_("writing public key to `%s'\n"), outctrl->pub.fname ); + if (card) + log_info (_("writing secret key stub to `%s'\n"), + outctrl->sec.fname); + else + log_info(_("writing secret key to `%s'\n"), outctrl->sec.fname ); + } } - /* We create the packets as a tree of kbnodes. Because the structure - * we create is known in advance we simply generate a linked list. - * The first packet is a dummy comment packet which we flag - * as deleted. The very first packet must always be a KEY packet. - */ - pub_root = make_comment_node ("#"); - delete_kbnode (pub_root); - sec_root = make_comment_node ("#"); - delete_kbnode (sec_root); - if (!card) - { - rc = do_create (get_parameter_algo (para, pKEYTYPE), - get_parameter_uint (para, pKEYLENGTH), - pub_root, sec_root, - get_parameter_dek (para, pPASSPHRASE_DEK), - get_parameter_s2k (para, pPASSPHRASE_S2K), - &sk, get_parameter_u32 (para, pKEYEXPIRE)); - } - else - { - rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root, - get_parameter_u32 (para, pKEYEXPIRE), para); - if (!rc) - { - sk = sec_root->next->pkt->pkt.secret_key; - assert (sk); - } - - } + /* we create the packets as a tree of kbnodes. Because the + * structure we create is known in advance we simply generate a + * linked list. The first packet is a dummy packet which we flag + * as deleted. The very first packet must always be a KEY packet. + */ + + start_tree(&pub_root); + start_tree(&sec_root); - if (!rc && (revkey = get_parameter_revkey (para, pREVOKER))) - { - rc = write_direct_sig (pub_root, pub_root, sk, revkey); - if (!rc) - write_direct_sig (sec_root, pub_root, sk, revkey); - } + if (!card) + { + rc = do_create( get_parameter_algo( para, pKEYTYPE ), + get_parameter_uint( para, pKEYLENGTH ), + pub_root, sec_root, + get_parameter_dek( para, pPASSPHRASE_DEK ), + get_parameter_s2k( para, pPASSPHRASE_S2K ), + &pri_sk, + get_parameter_u32( para, pKEYEXPIRE ), 0 ); + } + else + { + rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, + get_parameter_u32 (para, pKEYEXPIRE), para); + if (!rc) + { + pri_sk = sec_root->next->pkt->pkt.secret_key; + assert (pri_sk); + } + } - if (!rc && (s = get_parameter_value (para, pUSERID))) - { - write_uid (pub_root, s); - if (!rc) - write_uid (sec_root, s); - if (!rc) - rc = write_selfsig (pub_root, pub_root, sk, - get_parameter_uint (para, pKEYUSAGE)); - if (!rc) - rc = write_selfsig (sec_root, pub_root, sk, - get_parameter_uint (para, pKEYUSAGE)); - } + if(!rc && (revkey=get_parameter_revkey(para,pREVOKER))) + { + rc=write_direct_sig(pub_root,pub_root,pri_sk,revkey); + if(!rc) + write_direct_sig(sec_root,pub_root,pri_sk,revkey); + } - if ((! rc) && get_parameter (para, pSUBKEYTYPE)) - { - if (!card) - { - rc = do_create (get_parameter_algo (para, pSUBKEYTYPE), - get_parameter_uint (para, pSUBKEYLENGTH), - pub_root, sec_root, - get_parameter_dek (para, pPASSPHRASE_DEK), - get_parameter_s2k (para, pPASSPHRASE_S2K), - NULL, get_parameter_u32 (para, pSUBKEYEXPIRE)); - } - else - { - rc = gen_card_key (PUBKEY_ALGO_RSA, 2, pub_root, sec_root, - get_parameter_u32 (para, pKEYEXPIRE), para); - } + if( !rc && (s=get_parameter_value(para, pUSERID)) ) + { + write_uid(pub_root, s ); + if( !rc ) + write_uid(sec_root, s ); - if (!rc) - rc = write_keybinding (pub_root, pub_root, sk, - get_parameter_uint (para, pSUBKEYUSAGE)); - if (!rc) - rc = write_keybinding (sec_root, pub_root, sk, - get_parameter_uint (para, pSUBKEYUSAGE)); - did_sub = 1; - } + if( !rc ) + rc = write_selfsigs(sec_root, pub_root, pri_sk, + get_parameter_uint (para, pKEYUSAGE)); + } - if ((! rc) && card && get_parameter (para, pAUTHKEYTYPE)) - { - rc = gen_card_key (PUBKEY_ALGO_RSA, 3, pub_root, sec_root, - get_parameter_u32 (para, pKEYEXPIRE), para); + /* Write the auth key to the card before the encryption key. This + is a partial workaround for a PGP bug (as of this writing, all + versions including 8.1), that causes it to try and encrypt to + the most recent subkey regardless of whether that subkey is + actually an encryption type. In this case, the auth key is an + RSA key so it succeeds. */ - if (!rc) - rc = write_keybinding (pub_root, pub_root, sk, PUBKEY_USAGE_AUTH); - if (!rc) - rc = write_keybinding (sec_root, pub_root, sk, PUBKEY_USAGE_AUTH); - } + if (!rc && card && get_parameter (para, pAUTHKEYTYPE)) + { + rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, + get_parameter_u32 (para, pKEYEXPIRE), para); + + if (!rc) + rc = write_keybinding (pub_root, pub_root, pri_sk, sub_sk, PUBKEY_USAGE_AUTH); + if (!rc) + rc = write_keybinding (sec_root, pub_root, pri_sk, sub_sk, PUBKEY_USAGE_AUTH); + } + if( !rc && get_parameter( para, pSUBKEYTYPE ) ) + { + if (!card) + { + rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ), + get_parameter_uint( para, pSUBKEYLENGTH ), + pub_root, sec_root, + get_parameter_dek( para, pPASSPHRASE_DEK ), + get_parameter_s2k( para, pPASSPHRASE_S2K ), + &sub_sk, + get_parameter_u32( para, pSUBKEYEXPIRE ), 1 ); + } + else + { + if ((s = get_parameter_value (para, pBACKUPENCDIR))) + { + /* A backup of the encryption key has been requested. + Generate the key i software and import it then to + the card. Write a backup file. */ + rc = gen_card_key_with_backup (PUBKEY_ALGO_RSA, 2, 0, + pub_root, sec_root, + get_parameter_u32 (para, + pKEYEXPIRE), + para, s); + } + else + rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root, + get_parameter_u32 (para, pKEYEXPIRE), para); + } + + if( !rc ) + rc = write_keybinding(pub_root, pub_root, pri_sk, sub_sk, + get_parameter_uint (para, pSUBKEYUSAGE)); + if( !rc ) + rc = write_keybinding(sec_root, pub_root, pri_sk, sub_sk, + get_parameter_uint (para, pSUBKEYUSAGE)); + did_sub = 1; + } - if (!rc && outctrl->use_files) - { /* direct write to specified files */ - rc = write_keyblock (outctrl->pub.stream, pub_root); - if (rc) - log_error ("can't write public key: %s\n", gpg_strerror (rc)); - if (!rc) - { - rc = write_keyblock (outctrl->sec.stream, sec_root); - if (rc) - log_error ("can't write secret key: %s\n", gpg_strerror (rc)); + if( !rc && outctrl->use_files ) { /* direct write to specified files */ + rc = write_keyblock( outctrl->pub.stream, pub_root ); + if( rc ) + log_error("can't write public key: %s\n", g10_errstr(rc) ); + if( !rc ) { + rc = write_keyblock( outctrl->sec.stream, sec_root ); + if( rc ) + log_error("can't write secret key: %s\n", g10_errstr(rc) ); } } - else if (!rc) - { /* write to the standard keyrings */ - KEYDB_HANDLE pub_hd = keydb_new (0); - KEYDB_HANDLE sec_hd = keydb_new (1); + else if( !rc ) { /* write to the standard keyrings */ + KEYDB_HANDLE pub_hd = keydb_new (0); + KEYDB_HANDLE sec_hd = keydb_new (1); - /* FIXME: we may have to create the keyring first */ - rc = keydb_locate_writable (pub_hd, NULL); - if (rc) - log_error (_("no writable public keyring found: %s\n"), - gpg_strerror (rc)); + /* FIXME: we may have to create the keyring first */ + rc = keydb_locate_writable (pub_hd, NULL); + if (rc) + log_error (_("no writable public keyring found: %s\n"), + g10_errstr (rc)); - if (!rc) - { - rc = keydb_locate_writable (sec_hd, NULL); - if (rc) - log_error (_("no writable secret keyring found: %s\n"), - gpg_strerror (rc)); - } + if (!rc) { + rc = keydb_locate_writable (sec_hd, NULL); + if (rc) + log_error (_("no writable secret keyring found: %s\n"), + g10_errstr (rc)); + } - if (!rc && opt.verbose) - { - log_info (_("writing public key to `%s'\n"), - keydb_get_resource_name (pub_hd)); - if (card) - log_info (_("writing secret key stub to `%s'\n"), - keydb_get_resource_name (sec_hd)); - else - log_info (_("writing secret key to `%s'\n"), - keydb_get_resource_name (sec_hd)); - } + if (!rc && opt.verbose) { + log_info(_("writing public key to `%s'\n"), + keydb_get_resource_name (pub_hd)); + if (card) + log_info (_("writing secret key stub to `%s'\n"), + keydb_get_resource_name (sec_hd)); + else + log_info(_("writing secret key to `%s'\n"), + keydb_get_resource_name (sec_hd)); + } - if (!rc) - { - rc = keydb_insert_keyblock (pub_hd, pub_root); - if (rc) - log_error (_("error writing public keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), gpg_strerror (rc)); - } + if (!rc) { + rc = keydb_insert_keyblock (pub_hd, pub_root); + if (rc) + log_error (_("error writing public keyring `%s': %s\n"), + keydb_get_resource_name (pub_hd), g10_errstr(rc)); + } - if (!rc) - { - rc = keydb_insert_keyblock (sec_hd, sec_root); - if (rc) - log_error (_("error writing secret keyring `%s': %s\n"), - keydb_get_resource_name (pub_hd), gpg_strerror (rc)); - } + if (!rc) { + rc = keydb_insert_keyblock (sec_hd, sec_root); + if (rc) + log_error (_("error writing secret keyring `%s': %s\n"), + keydb_get_resource_name (pub_hd), g10_errstr(rc)); + } - keydb_release (pub_hd); - keydb_release (sec_hd); + keydb_release (pub_hd); + keydb_release (sec_hd); - if (!rc) - { - int no_enc_rsa = - get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_RSA - && get_parameter_uint (para, pKEYUSAGE) - && !(get_parameter_uint (para, pKEYUSAGE) & PUBKEY_USAGE_ENC); - PKT_public_key *pk = find_kbnode (pub_root, - PKT_PUBLIC_KEY)->pkt->pkt. - public_key; - - update_ownertrust (pk, - ((get_ownertrust (pk) & ~TRUST_MASK) - | TRUST_ULTIMATE)); - - if (!opt.batch) - { - tty_printf (_("public and secret key created and signed.\n")); - tty_printf (_("key marked as ultimately trusted.\n")); - tty_printf ("\n"); - list_keyblock (pub_root, 0, 1, NULL); - } + if (!rc) { + int no_enc_rsa = + get_parameter_algo(para, pKEYTYPE) == PUBKEY_ALGO_RSA + && get_parameter_uint( para, pKEYUSAGE ) + && !(get_parameter_uint( para,pKEYUSAGE) & PUBKEY_USAGE_ENC); + PKT_public_key *pk = find_kbnode (pub_root, + PKT_PUBLIC_KEY)->pkt->pkt.public_key; + keyid_from_pk(pk,pk->main_keyid); + register_trusted_keyid(pk->main_keyid); - if (!opt.batch - && (get_parameter_algo (para, pKEYTYPE) == PUBKEY_ALGO_DSA - || no_enc_rsa) && !get_parameter (para, pSUBKEYTYPE)) - { - tty_printf (_("Note that this key cannot be used for " - "encryption. You may want to use\n" - "the command \"--edit-key\" to generate a " - "secondary key for this purpose.\n")); - } + update_ownertrust (pk, + ((get_ownertrust (pk) & ~TRUST_MASK) + | TRUST_ULTIMATE )); - if (!opt.batch && card) - { - tty_printf(_( -"Please create a revocation certificate now, so that you are able\n" -"to revoke the key if it ever happens that you lose your card or\n" -"the card gets damaged. Use the command \"--gen-revoke\".\n" - )); + if (!opt.batch) { + tty_printf(_("public and secret key created and signed.\n") ); + tty_printf("\n"); + list_keyblock(pub_root,0,1,NULL); } + + + if( !opt.batch + && ( get_parameter_algo( para, pKEYTYPE ) == PUBKEY_ALGO_DSA + || no_enc_rsa ) + && !get_parameter( para, pSUBKEYTYPE ) ) + { + tty_printf(_("Note that this key cannot be used for " + "encryption. You may want to use\n" + "the command \"--edit-key\" to generate a " + "subkey for this purpose.\n") ); + } } } - if (rc) - { - if (opt.batch) - log_error ("key generation failed: %s\n", gpg_strerror (rc)); - else - tty_printf (_("Key generation failed: %s\n"), gpg_strerror (rc)); - } - else - { - PKT_public_key *pk = find_kbnode (pub_root, - PKT_PUBLIC_KEY)->pkt->pkt.public_key; - print_status_key_created (did_sub ? 'B' : 'P', pk); + if( rc ) { + if( opt.batch ) + log_error("key generation failed: %s\n", g10_errstr(rc) ); + else + tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) ); + print_status_key_not_created ( get_parameter_value (para, pHANDLE) ); } - - release_kbnode (pub_root); - release_kbnode (sec_root); - if (sk && !card) /* The unprotected secret key unless we have */ - free_secret_key (sk); /* a shallow copy in card mode. */ + else { + PKT_public_key *pk = find_kbnode (pub_root, + PKT_PUBLIC_KEY)->pkt->pkt.public_key; + print_status_key_created (did_sub? 'B':'P', pk, + get_parameter_value (para, pHANDLE)); + } + release_kbnode( pub_root ); + release_kbnode( sec_root ); + + if( pri_sk && !card) /* the unprotected secret key unless we have a */ + free_secret_key(pri_sk); /* shallow copy in card mode. */ + if( sub_sk ) + free_secret_key(sub_sk); } @@ -2724,7 +3261,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) { int okay=0, rc=0; KBNODE node; - PKT_secret_key *sk = NULL; /* this is the primary sk */ + PKT_secret_key *pri_sk = NULL, *sub_sk = NULL; int algo; unsigned int use; u32 expire; @@ -2733,6 +3270,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) DEK *dek = NULL; STRING2KEY *s2k = NULL; u32 cur_time; + int ask_pass = 0; /* break out the primary secret key */ node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); @@ -2742,69 +3280,81 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) } /* make a copy of the sk to keep the protected one in the keyblock */ - sk = copy_secret_key( NULL, node->pkt->pkt.secret_key ); + pri_sk = copy_secret_key( NULL, node->pkt->pkt.secret_key ); cur_time = make_timestamp(); - if( sk->timestamp > cur_time ) { - ulong d = sk->timestamp - cur_time; + if( pri_sk->timestamp > cur_time ) { + ulong d = pri_sk->timestamp - cur_time; log_info( d==1 ? _("key has been created %lu second " "in future (time warp or clock problem)\n") : _("key has been created %lu seconds " "in future (time warp or clock problem)\n"), d ); if( !opt.ignore_time_conflict ) { - rc = GPG_ERR_TIME_CONFLICT; + rc = G10ERR_TIME_CONFLICT; goto leave; } } - if (sk->version < 4) { + if (pri_sk->version < 4) { log_info (_("NOTE: creating subkeys for v3 keys " "is not OpenPGP compliant\n")); goto leave; } - /* unprotect to get the passphrase */ - switch( is_secret_key_protected( sk ) ) { + if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) { + tty_printf(_("Secret parts of primary key are not available.\n")); + rc = G10ERR_NO_SECKEY; + goto leave; + } + + + /* Unprotect to get the passphrase. */ + switch( is_secret_key_protected( pri_sk ) ) { case -1: - rc = GPG_ERR_PUBKEY_ALGO; + rc = G10ERR_PUBKEY_ALGO; break; case 0: - tty_printf("This key is not protected.\n"); + tty_printf(_("This key is not protected.\n")); break; + case -2: + tty_printf(_("Secret parts of primary key are stored on-card.\n")); + ask_pass = 1; + break; default: - tty_printf("Key is protected.\n"); - rc = check_secret_key( sk, 0 ); - if( !rc ) - passphrase = get_last_passphrase(); - break; + tty_printf(_("Key is protected.\n")); + rc = check_secret_key( pri_sk, 0 ); + if( !rc ) + passphrase = get_last_passphrase(); + break; } if( rc ) goto leave; - algo = ask_algo( 1, &use ); assert(algo); nbits = ask_keysize( algo ); - expire = ask_expire_interval(0); + expire = ask_expire_interval(0,NULL); if( !cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay", - _("Really create? ") ) ) + _("Really create? (y/N) "))) goto leave; - if( passphrase ) { - s2k = xmalloc_secure ( sizeof *s2k ); + if (ask_pass) + dek = do_ask_passphrase (&s2k); + else if (passphrase) { + s2k = xmalloc_secure( sizeof *s2k ); s2k->mode = opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; + s2k->hash_algo = S2K_DIGEST_ALGO; set_next_passphrase( passphrase ); dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2, NULL, NULL ); } rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, - dek, s2k, NULL, expire ); + dek, s2k, &sub_sk, expire, 1 ); if( !rc ) - rc = write_keybinding(pub_keyblock, pub_keyblock, sk, use); + rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use); if( !rc ) - rc = write_keybinding(sec_keyblock, pub_keyblock, sk, use); + rc = write_keybinding(sec_keyblock, pub_keyblock, pri_sk, sub_sk, use); if( !rc ) { okay = 1; write_status_text (STATUS_KEY_CREATED, "S"); @@ -2812,39 +3362,163 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) leave: if( rc ) - log_error(_("Key generation failed: %s\n"), gpg_strerror (rc) ); - xfree ( passphrase ); - xfree ( dek ); - xfree ( s2k ); - if( sk ) /* release the copy of the (now unprotected) secret key */ - free_secret_key(sk); + log_error(_("Key generation failed: %s\n"), g10_errstr(rc) ); + xfree( passphrase ); + xfree( dek ); + xfree( s2k ); + /* release the copy of the (now unprotected) secret keys */ + if( pri_sk ) + free_secret_key(pri_sk); + if( sub_sk ) + free_secret_key(sub_sk); set_next_passphrase( NULL ); return okay; } + +#ifdef ENABLE_CARD_SUPPORT +/* Generate a subkey on a card. */ +int +generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, + int keyno, const char *serialno) +{ + int okay=0, rc=0; + KBNODE node; + PKT_secret_key *pri_sk = NULL; + int algo; + unsigned int use; + u32 expire; + char *passphrase = NULL; + u32 cur_time; + struct para_data_s *para = NULL; + + assert (keyno >= 1 && keyno <= 3); + + para = xcalloc (1, sizeof *para + strlen (serialno) ); + para->key = pSERIALNO; + strcpy (para->u.value, serialno); + + /* Break out the primary secret key */ + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + if(!node) + { + log_error("Oops; secret key not found anymore!\n"); + goto leave; + } + + /* Make a copy of the sk to keep the protected one in the keyblock */ + pri_sk = copy_secret_key (NULL, node->pkt->pkt.secret_key); + + cur_time = make_timestamp(); + if (pri_sk->timestamp > cur_time) + { + ulong d = pri_sk->timestamp - cur_time; + log_info (d==1 ? _("key has been created %lu second " + "in future (time warp or clock problem)\n") + : _("key has been created %lu seconds " + "in future (time warp or clock problem)\n"), d ); + if (!opt.ignore_time_conflict) + { + rc = G10ERR_TIME_CONFLICT; + goto leave; + } + } + + if (pri_sk->version < 4) + { + log_info (_("NOTE: creating subkeys for v3 keys " + "is not OpenPGP compliant\n")); + goto leave; + } + + /* Unprotect to get the passphrase. */ + switch( is_secret_key_protected (pri_sk) ) + { + case -1: + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + tty_printf("This key is not protected.\n"); + break; + default: + tty_printf("Key is protected.\n"); + rc = check_secret_key( pri_sk, 0 ); + if (!rc) + passphrase = get_last_passphrase(); + break; + } + if (rc) + goto leave; + + algo = PUBKEY_ALGO_RSA; + expire = ask_expire_interval (0,NULL); + if (keyno == 1) + use = PUBKEY_USAGE_SIG; + else if (keyno == 2) + use = PUBKEY_USAGE_ENC; + else + use = PUBKEY_USAGE_AUTH; + if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.cardsub.okay", + _("Really create? (y/N) "))) + goto leave; + + if (passphrase) + set_next_passphrase (passphrase); + rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, expire, para); + if (!rc) + rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, NULL, use); + if (!rc) + rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, NULL, use); + if (!rc) + { + okay = 1; + write_status_text (STATUS_KEY_CREATED, "S"); + } + + leave: + if (rc) + log_error (_("Key generation failed: %s\n"), g10_errstr(rc) ); + xfree (passphrase); + /* Release the copy of the (now unprotected) secret keys. */ + if (pri_sk) + free_secret_key (pri_sk); + set_next_passphrase( NULL ); + release_parameter_list (para); + return okay; +} +#endif /* !ENABLE_CARD_SUPPORT */ + + /**************** * Write a keyblock to an output stream */ static int -write_keyblock( iobuf_t out, KBNODE node ) +write_keyblock( IOBUF out, KBNODE node ) { - for( ; node ; node = node->next ) { - int rc = build_packet( out, node->pkt ); - if( rc ) { - log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, gpg_strerror (rc) ); - return rc; + for( ; node ; node = node->next ) + { + if(!is_deleted_kbnode(node)) + { + int rc = build_packet( out, node->pkt ); + if( rc ) + { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, g10_errstr(rc) ); + return G10ERR_WRITE_FILE; + } } } - return 0; + + return 0; } - static int -gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, +gen_card_key (int algo, int keyno, int is_primary, + KBNODE pub_root, KBNODE sec_root, u32 expireval, struct para_data_s *para) { +#ifdef ENABLE_CARD_SUPPORT int rc; const char *s; struct agent_card_genkey_s info; @@ -2853,8 +3527,9 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, PKT_public_key *pk; assert (algo == PUBKEY_ALGO_RSA); - - rc = agent_scd_genkey (&info, keyno, 1); + + /* Fixme: We don't have the serialnumber available, thus passing NULL. */ + rc = agent_scd_genkey (&info, keyno, 1, NULL); /* if (gpg_err_code (rc) == GPG_ERR_EEXIST) */ /* { */ /* tty_printf ("\n"); */ @@ -2866,13 +3541,15 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, /* } */ if (rc) - return rc; - + { + log_error ("key generation failed: %s\n", gpg_strerror (rc)); + return rc; + } if ( !info.n || !info.e ) { log_error ("communication error with SCD\n"); - gcry_mpi_release (info.n); - gcry_mpi_release (info.e); + mpi_free (info.n); + mpi_free (info.e); return gpg_error (GPG_ERR_GENERAL); } @@ -2900,17 +3577,243 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, } pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = keyno == 1 ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; pkt->pkt.public_key = pk; add_kbnode(pub_root, new_kbnode( pkt )); pkt = xcalloc (1,sizeof *pkt); - pkt->pkttype = keyno == 1 ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkttype = is_primary ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; pkt->pkt.secret_key = sk; add_kbnode(sec_root, new_kbnode( pkt )); return 0; +#else + return -1; +#endif /*!ENABLE_CARD_SUPPORT*/ } +static int +gen_card_key_with_backup (int algo, int keyno, int is_primary, + KBNODE pub_root, KBNODE sec_root, + u32 expireval, struct para_data_s *para, + const char *backup_dir) +{ +#ifdef ENABLE_CARD_SUPPORT + int rc; + const char *s; + PACKET *pkt; + PKT_secret_key *sk, *sk_unprotected, *sk_protected; + PKT_public_key *pk; + size_t n; + int i; + + rc = generate_raw_key (algo, 1024, make_timestamp (), + &sk_unprotected, &sk_protected); + if (rc) + return rc; + + /* First, store the key to the card. */ + rc = save_unprotected_key_to_card (sk_unprotected, keyno); + if (rc) + { + log_error (_("storing key onto card failed: %s\n"), g10_errstr (rc)); + free_secret_key (sk_unprotected); + free_secret_key (sk_protected); + return rc; + } + + /* Get rid of the secret key parameters and store the serial numer. */ + sk = sk_unprotected; + n = pubkey_get_nskey (sk->pubkey_algo); + for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) + { + mpi_free (sk->skey[i]); + sk->skey[i] = NULL; + } + i = pubkey_get_npkey (sk->pubkey_algo); + sk->skey[i] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->is_protected = 1; + sk->protect.s2k.mode = 1002; + s = get_parameter_value (para, pSERIALNO); + assert (s); + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); + + /* Now write the *protected* secret key to the file. */ + { + char name_buffer[50]; + char *fname; + IOBUF fp; + mode_t oldmask; + + keyid_from_sk (sk, NULL); + sprintf (name_buffer,"sk_%08lX%08lX.gpg", + (ulong)sk->keyid[0], (ulong)sk->keyid[1]); + + fname = make_filename (backup_dir, name_buffer, NULL); + oldmask = umask (077); + if (is_secured_filename (fname)) + { + fp = NULL; + errno = EPERM; + } + else + fp = iobuf_create (fname); + umask (oldmask); + if (!fp) + { + log_error (_("can't create backup file `%s': %s\n"), + fname, strerror(errno) ); + xfree (fname); + free_secret_key (sk_unprotected); + free_secret_key (sk_protected); + return G10ERR_OPEN_FILE; + } + + pkt = xcalloc (1, sizeof *pkt); + pkt->pkttype = PKT_SECRET_KEY; + pkt->pkt.secret_key = sk_protected; + sk_protected = NULL; + + rc = build_packet (fp, pkt); + if (rc) + { + log_error("build packet failed: %s\n", g10_errstr(rc) ); + iobuf_cancel (fp); + } + else + { + byte array[MAX_FINGERPRINT_LEN]; + char *fprbuf, *p; + + iobuf_close (fp); + iobuf_ioctl (NULL, 2, 0, (char*)fname); + log_info (_("NOTE: backup of card key saved to `%s'\n"), fname); + + fingerprint_from_sk (sk, array, &n); + p = fprbuf = xmalloc (MAX_FINGERPRINT_LEN*2 + 1 + 1); + for (i=0; i < n ; i++, p += 2) + sprintf (p, "%02X", array[i]); + *p++ = ' '; + *p = 0; + + write_status_text_and_buffer (STATUS_BACKUP_KEY_CREATED, + fprbuf, + fname, strlen (fname), + 0); + xfree (fprbuf); + } + free_packet (pkt); + xfree (pkt); + xfree (fname); + if (rc) + { + free_secret_key (sk_unprotected); + return rc; + } + } + + /* Create the public key from the secret key. */ + pk = xcalloc (1, sizeof *pk ); + pk->timestamp = sk->timestamp; + pk->version = sk->version; + if (expireval) + pk->expiredate = sk->expiredate = sk->timestamp + expireval; + pk->pubkey_algo = sk->pubkey_algo; + n = pubkey_get_npkey (sk->pubkey_algo); + for (i=0; i < n; i++) + pk->pkey[i] = mpi_copy (sk->skey[i]); + + /* Build packets and add them to the node lists. */ + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + pkt = xcalloc (1,sizeof *pkt); + pkt->pkttype = is_primary ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY; + pkt->pkt.secret_key = sk; + add_kbnode(sec_root, new_kbnode( pkt )); + + return 0; +#else + return -1; +#endif /*!ENABLE_CARD_SUPPORT*/ +} + + +#ifdef ENABLE_CARD_SUPPORT +int +save_unprotected_key_to_card (PKT_secret_key *sk, int keyno) +{ + int rc; + unsigned char *rsa_n = NULL; + unsigned char *rsa_e = NULL; + unsigned char *rsa_p = NULL; + unsigned char *rsa_q = NULL; + unsigned int rsa_n_len, rsa_e_len, rsa_p_len, rsa_q_len; + unsigned char *sexp = NULL; + unsigned char *p; + char numbuf[55], numbuf2[50]; + + assert (is_RSA (sk->pubkey_algo)); + assert (!sk->is_protected); + + /* Copy the parameters into straight buffers. */ + rsa_n = mpi_get_secure_buffer (sk->skey[0], &rsa_n_len, NULL); + rsa_e = mpi_get_secure_buffer (sk->skey[1], &rsa_e_len, NULL); + rsa_p = mpi_get_secure_buffer (sk->skey[3], &rsa_p_len, NULL); + rsa_q = mpi_get_secure_buffer (sk->skey[4], &rsa_q_len, NULL); + if (!rsa_n || !rsa_e || !rsa_p || !rsa_q) + { + rc = G10ERR_INV_ARG; + goto leave; + } + + /* Put the key into an S-expression. */ + sexp = p = xmalloc_secure (30 + + rsa_n_len + rsa_e_len + rsa_p_len + rsa_q_len + + 4*sizeof (numbuf) + 25 + sizeof(numbuf) + 20); + + p = stpcpy (p,"(11:private-key(3:rsa(1:n"); + sprintf (numbuf, "%u:", rsa_n_len); + p = stpcpy (p, numbuf); + memcpy (p, rsa_n, rsa_n_len); + p += rsa_n_len; + + sprintf (numbuf, ")(1:e%u:", rsa_e_len); + p = stpcpy (p, numbuf); + memcpy (p, rsa_e, rsa_e_len); + p += rsa_e_len; + + sprintf (numbuf, ")(1:p%u:", rsa_p_len); + p = stpcpy (p, numbuf); + memcpy (p, rsa_p, rsa_p_len); + p += rsa_p_len; + + sprintf (numbuf, ")(1:q%u:", rsa_q_len); + p = stpcpy (p, numbuf); + memcpy (p, rsa_q, rsa_q_len); + p += rsa_q_len; + + p = stpcpy (p,"))(10:created-at"); + sprintf (numbuf2, "%lu", (unsigned long)sk->timestamp); + sprintf (numbuf, "%lu:", (unsigned long)strlen (numbuf2)); + p = stpcpy (stpcpy (stpcpy (p, numbuf), numbuf2), "))"); + + /* Fixme: Unfortunately we don't have the serialnumber available - + thus we can't pass it down to the agent. */ + rc = agent_scd_writekey (keyno, NULL, sexp, p - sexp); + + leave: + xfree (sexp); + xfree (rsa_n); + xfree (rsa_e); + xfree (rsa_p); + xfree (rsa_q); + return rc; +} +#endif /*ENABLE_CARD_SUPPORT*/ diff --git a/g10/keyid.c b/g10/keyid.c index aaa70cccb..5eb51c1f4 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -1,5 +1,6 @@ /* keyid.c - key ID and fingerprint handling - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -31,11 +33,9 @@ #include "main.h" #include "packet.h" #include "options.h" -#include "mpi.h" #include "keydb.h" #include "i18n.h" - int pubkey_letter( int algo ) { @@ -50,66 +50,93 @@ pubkey_letter( int algo ) } } -static gcry_md_hd_t -do_fingerprint_md( PKT_public_key *pk ) +/* This function is useful for v4 fingerprints and v3 or v4 key + signing. */ +void +hash_public_key( gcry_md_hd_t 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); + unsigned int n = 6; + unsigned int nb[PUBKEY_MAX_NPKEY]; + unsigned int nn[PUBKEY_MAX_NPKEY]; + byte *pp[PUBKEY_MAX_NPKEY]; + int i; + size_t nbits, nbytes; + int npkey = pubkey_get_npkey (pk->pubkey_algo); - n = pk->version < 4 ? 8 : 6; - for(i=0; i < npkey; i++ ) { - size_t nbytes; + /* Two extra bytes for the expiration date in v3 */ + if(pk->version<4) + n+=2; - if (gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i] )) + if (npkey==0 && pk->pkey[0] + && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE)) + { + pp[0] = gcry_mpi_get_opaque (pk->pkey[0], &nbits); + nn[0] = (nbits+7)/8; + n+=nn[0]; + } + else + for(i=0; i < npkey; i++ ) + { + nb[i] = gcry_mpi_get_nbits (pk->pkey[i]); + 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] )) + 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]; + nn[i] = nbytes; + n += 2 + nn[i]; + } + + gcry_md_putc ( md, 0x99 ); /* ctb */ + /* What does it mean if n is greater than than 0xFFFF ? */ + gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */ + gcry_md_putc ( md, n ); + gcry_md_putc ( md, pk->version ); + + gcry_md_putc ( md, pk->timestamp >> 24 ); + gcry_md_putc ( md, pk->timestamp >> 16 ); + gcry_md_putc ( md, pk->timestamp >> 8 ); + gcry_md_putc ( md, pk->timestamp ); + + if(pk->version<4) + { + u16 days=0; + if(pk->expiredate) + days=(u16)((pk->expiredate - pk->timestamp) / 86400L); + + gcry_md_putc ( md, days >> 8 ); + gcry_md_putc ( md, days ); } - 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; + gcry_md_putc ( md, pk->pubkey_algo ); - 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]); + if(npkey==0 && pk->pkey[0] + && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE)) + { + gcry_md_write (md, pp[0], nn[0]); } - gcry_md_final ( md ); + else + for(i=0; i < npkey; i++ ) + { + gcry_md_putc ( md, nb[i]>>8); + gcry_md_putc ( md, nb[i] ); + gcry_md_write ( md, pp[i], nn[i] ); + xfree(pp[i]); + } +} + +static gcry_md_hd_t +do_fingerprint_md( PKT_public_key *pk ) +{ + gcry_md_hd_t md; - return md; + if (gcry_md_open (&md, DIGEST_ALGO_SHA1, 0)) + BUG (); + hash_public_key(md,pk); + gcry_md_final( md ); + + return md; } static gcry_md_hd_t @@ -119,13 +146,16 @@ do_fingerprint_md_sk( PKT_secret_key *sk ) int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */ int i; + if(npkey==0) + return NULL; + 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]; + pk.pkey[i] = sk->skey[i]; return do_fingerprint_md( &pk ); } @@ -154,6 +184,112 @@ v3_keyid (gcry_mpi_t a, u32 *ki) } +size_t +keystrlen(void) +{ + switch(opt.keyid_format) + { + case KF_SHORT: + return 8; + + case KF_LONG: + return 16; + + case KF_0xSHORT: + return 10; + + case KF_0xLONG: + return 18; + + default: + BUG(); + } +} + +const char * +keystr(u32 *keyid) +{ + static char keyid_str[19]; + + switch(opt.keyid_format) + { + case KF_SHORT: + sprintf(keyid_str,"%08lX",(ulong)keyid[1]); + break; + + case KF_LONG: + if(keyid[0]) + sprintf(keyid_str,"%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); + else + sprintf(keyid_str,"%08lX",(ulong)keyid[1]); + break; + + case KF_0xSHORT: + sprintf(keyid_str,"0x%08lX",(ulong)keyid[1]); + break; + + case KF_0xLONG: + if(keyid[0]) + sprintf(keyid_str,"0x%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); + else + sprintf(keyid_str,"0x%08lX",(ulong)keyid[1]); + break; + + default: + BUG(); + } + + return keyid_str; +} + +const char * +keystr_from_pk(PKT_public_key *pk) +{ + keyid_from_pk(pk,NULL); + + return keystr(pk->keyid); +} + +const char * +keystr_from_sk(PKT_secret_key *sk) +{ + keyid_from_sk(sk,NULL); + + return keystr(sk->keyid); +} + +const char * +keystr_from_desc(KEYDB_SEARCH_DESC *desc) +{ + switch(desc->mode) + { + case KEYDB_SEARCH_MODE_LONG_KID: + case KEYDB_SEARCH_MODE_SHORT_KID: + return keystr(desc->u.kid); + + case KEYDB_SEARCH_MODE_FPR20: + { + u32 keyid[2]; + + keyid[0] = ((unsigned char)desc->u.fpr[12] << 24 + | (unsigned char)desc->u.fpr[13] << 16 + | (unsigned char)desc->u.fpr[14] << 8 + | (unsigned char)desc->u.fpr[15]); + keyid[1] = ((unsigned char)desc->u.fpr[16] << 24 + | (unsigned char)desc->u.fpr[17] << 16 + | (unsigned char)desc->u.fpr[18] << 8 + | (unsigned char)desc->u.fpr[19]); + + return keystr(keyid); + } + + case KEYDB_SEARCH_MODE_FPR16: + return "?v3 fpr?"; + + default: + BUG(); + } +} /**************** * Get the keyid from the secret key and put it into keyid @@ -162,29 +298,51 @@ v3_keyid (gcry_mpi_t a, u32 *ki) u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid ) { - u32 lowbits; - u32 dummy_keyid[2]; + u32 lowbits; + u32 dummy_keyid[2]; - if( !keyid ) - keyid = dummy_keyid; + 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; + if( sk->keyid[0] || sk->keyid[1] ) + { + keyid[0] = sk->keyid[0]; + keyid[1] = sk->keyid[1]; + lowbits = keyid[1]; } - 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); + else if( sk->version < 4 ) + { + if( is_RSA(sk->pubkey_algo) ) + { + lowbits = (pubkey_get_npkey (sk->pubkey_algo) ? + v3_keyid( sk->skey[0], keyid ) : 0); /* Take n. */ + sk->keyid[0]=keyid[0]; + sk->keyid[1]=keyid[1]; + } + else + sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; + } + else + { + const byte *dp; + gcry_md_hd_t md; + + md = do_fingerprint_md_sk(sk); + if(md) + { + 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); + sk->keyid[0] = keyid[0]; + sk->keyid[1] = keyid[1]; + } + else + sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } - return lowbits; + return lowbits; } @@ -195,38 +353,51 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid ) u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid ) { - u32 lowbits; - u32 dummy_keyid[2]; + u32 lowbits; + u32 dummy_keyid[2]; - if( !keyid ) - keyid = dummy_keyid; + 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]; + 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 if( pk->version < 4 ) + { + if( is_RSA(pk->pubkey_algo) ) + { + lowbits = (pubkey_get_npkey (pk->pubkey_algo) ? + v3_keyid ( pk->pkey[0], keyid ) : 0); /* From n. */ + pk->keyid[0] = keyid[0]; + pk->keyid[1] = keyid[1]; + } + else + pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } - 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]; + else + { + const byte *dp; + gcry_md_hd_t md; + + md = do_fingerprint_md(pk); + if(md) + { + 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]; + } + else + pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF; } - return lowbits; + return lowbits; } @@ -282,16 +453,16 @@ namehash_from_uid(PKT_user_id *uid) { if(uid->namehash==NULL) { - uid->namehash=xmalloc (20); + uid->namehash = xmalloc(20); if(uid->attrib_data) - gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash, - uid->attrib_data,uid->attrib_len); + 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); + uid->name, uid->len); } - + return uid->namehash; } @@ -396,6 +567,46 @@ expirestr_from_sig( PKT_signature *sig ) return mk_datestr (buffer, atime); } +const char * +revokestr_from_pk( PKT_public_key *pk ) +{ + static char buffer[11+5]; + time_t atime; + + if(!pk->revoked.date) + return _("never "); + atime=pk->revoked.date; + return mk_datestr (buffer, atime); +} + + +const char * +usagestr_from_pk( PKT_public_key *pk ) +{ + static char buffer[10]; + int i = 0; + unsigned int use = pk->pubkey_usage; + + if ( use & PUBKEY_USAGE_SIG ) + buffer[i++] = 'S'; + + if ( use & PUBKEY_USAGE_CERT ) + buffer[i++] = 'C'; + + if ( use & PUBKEY_USAGE_ENC ) + buffer[i++] = 'E'; + + if ( (use & PUBKEY_USAGE_AUTH) ) + buffer[i++] = 'A'; + + while (i < 4) + buffer[i++] = ' '; + + buffer[i] = 0; + return buffer; +} + + const char * colon_strtime (u32 t) { @@ -465,145 +676,143 @@ colon_expirestr_from_sig (PKT_signature *sig) 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); + byte *buf; + const byte *dp; + size_t len, nbytes; + int i; + + if ( pk->version < 4 ) + { + if ( is_RSA(pk->pubkey_algo) ) + { + /* RSA in version 3 packets is special. */ + gcry_md_hd_t md; + + if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0)) + BUG (); + if ( pubkey_get_npkey (pk->pubkey_algo) > 1 ) + { + for (i=0; i < 2; i++) + { + if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, + &nbytes, pk->pkey[i])) + BUG (); + /* fixme: Better allocate BUF on the stack */ + buf = xmalloc (nbytes); + if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, + NULL, pk->pkey[i])) + 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 + { + if (!array) + array = xmalloc(16); + len = 16; + memset (array,0,16); + } } - 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); + 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; + + *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); + byte *buf; + const char *dp; + size_t len, nbytes; + int i; + + if (sk->version < 4) + { + if ( is_RSA(sk->pubkey_algo) ) + { + /* RSA in version 3 packets is special. */ + gcry_md_hd_t md; + + if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0)) + BUG (); + if (pubkey_get_npkey( sk->pubkey_algo ) > 1) + { + for (i=0; i < 2; i++) + { + if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, + &nbytes, sk->skey[i])) + BUG (); + /* fixme: Better allocate BUF on the stack */ + buf = xmalloc (nbytes); + if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, + NULL, sk->skey[i])) + 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 + { + if (!array) + array = xmalloc (16); + len=16; + memset (array,0,16); + } } - 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); + else + { + gcry_md_hd_t md; + + md = do_fingerprint_md_sk(sk); + if (md) + { + 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); + } + else + { + len = MAX_FINGERPRINT_LEN; + if (!array) + array = xmalloc (len); + memset (array, 0, len); + } } - - *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; + *ret_len = len; + return array; } - - - - - - - - diff --git a/g10/keylist.c b/g10/keylist.c index 50850de71..0ff788e18 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1,6 +1,6 @@ -/* keylist.c - List all or selected keys - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. +/* keylist.c - print keys + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,11 +27,11 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" #include "keydb.h" -#include "memory.h" #include "photoid.h" #include "util.h" #include "ttyio.h" @@ -95,6 +96,13 @@ public_key_list( STRLIST list ) printf("\n"); } + /* We need to do the stale check right here because it might need to + update the keyring while we already have the keyring open. This + is very bad for W32 because of a sharing violation. For real OSes + it might lead to false results if we are later listing a keyring + which is associated with the inode of a deleted file. */ + check_trustdb_stale (); + if( !list ) list_all(0); else @@ -104,6 +112,8 @@ public_key_list( STRLIST list ) void secret_key_list( STRLIST list ) { + check_trustdb_stale (); + if( !list ) list_all(1); else /* List by user id */ @@ -113,21 +123,18 @@ secret_key_list( STRLIST list ) void print_seckey_info (PKT_secret_key *sk) { - u32 sk_keyid[2]; - size_t n; - char *p; - - keyid_from_sk (sk, sk_keyid); - tty_printf ("\nsec %4u%c/%08lX %s ", - nbits_from_sk (sk), - pubkey_letter (sk->pubkey_algo), - (ulong)sk_keyid[1], datestr_from_sk (sk)); - - p = get_user_id (sk_keyid, &n); - tty_print_utf8_string (p, n); - xfree (p); + u32 keyid[2]; + char *p; - tty_printf ("\n"); + keyid_from_sk (sk, keyid); + p=get_user_id_native(keyid); + + tty_printf ("\nsec %4u%c/%s %s %s\n", + nbits_from_sk (sk), + pubkey_letter (sk->pubkey_algo), + keystr(keyid), datestr_from_sk (sk), p); + + xfree (p); } /* Print information about the public key. With FP passed as NULL, @@ -136,33 +143,98 @@ print_seckey_info (PKT_secret_key *sk) void print_pubkey_info (FILE *fp, PKT_public_key *pk) { - u32 pk_keyid[2]; - size_t n; + u32 keyid[2]; char *p; - keyid_from_pk (pk, pk_keyid); + keyid_from_pk (pk, keyid); + + /* If the pk was chosen by a particular user ID, that is the one to + print. */ + if(pk->user_id) + p=utf8_to_native(pk->user_id->name,pk->user_id->len,0); + else + p=get_user_id_native(keyid); + if (fp) - fprintf (fp, "pub %4u%c/%08lX %s ", + fprintf (fp, "pub %4u%c/%s %s %s\n", nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo), - (ulong)pk_keyid[1], datestr_from_pk (pk)); + keystr(keyid), datestr_from_pk (pk), p); else - tty_printf ("\npub %4u%c/%08lX %s ", - nbits_from_pk (pk), - pubkey_letter (pk->pubkey_algo), - (ulong)pk_keyid[1], datestr_from_pk (pk)); + tty_printf ("\npub %4u%c/%s %s %s\n", + nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo), + keystr(keyid), datestr_from_pk (pk), p); - p = get_user_id (pk_keyid, &n); - if (fp) - print_utf8_string2 (fp, p, n, '\n'); - else - tty_print_utf8_string (p, n); xfree (p); - - if (fp) - putc ('\n', fp); - else - tty_printf ("\n\n"); +} + + +/* Print basic information of a secret key including the card serial + number information. */ +void +print_card_key_info (FILE *fp, KBNODE keyblock) +{ + KBNODE node; + int i; + + for (node = keyblock; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_SECRET_KEY + || (node->pkt->pkttype == PKT_SECRET_SUBKEY) ) + { + PKT_secret_key *sk = node->pkt->pkt.secret_key; + + tty_fprintf (fp, "%s%c %4u%c/%s ", + node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", + (sk->protect.s2k.mode==1001)?'#': + (sk->protect.s2k.mode==1002)?'>':' ', + nbits_from_sk (sk), + pubkey_letter (sk->pubkey_algo), + keystr_from_sk(sk)); + tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); + tty_fprintf (fp, " "); + tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { + tty_fprintf (fp, "\n "); + tty_fprintf (fp, _("card-no: ")); + if (sk->protect.ivlen == 16 + && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) + { + /* This is an OpenPGP card. */ + for (i=8; i < 14; i++) + { + if (i == 10) + tty_fprintf (fp, " "); + tty_fprintf (fp, "%02X", sk->protect.iv[i]); + } + } + else + { /* Something is wrong: Print all. */ + for (i=0; i < sk->protect.ivlen; i++) + tty_fprintf (fp, "%02X", sk->protect.iv[i]); + } + } + tty_fprintf (fp, "\n"); + } + } +} + + + +/* Flags = 0x01 hashed 0x02 critical */ +static void +status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf) +{ + char status[40]; + + /* Don't print these. */ + if(len>256) + return; + + sprintf(status,"%d %u %u ",type,flags,(unsigned int)len); + + write_status_text_and_buffer(STATUS_SIG_SUBPACKET,status,buf,len,0); } /* @@ -184,7 +256,7 @@ show_policy_url(PKT_signature *sig,int indent,int mode) if(mode!=2) { int i; - char *str; + const char *str; for(i=0;i<indent;i++) putchar(' '); @@ -206,7 +278,6 @@ show_policy_url(PKT_signature *sig,int indent,int mode) } } - /* mode=0 for stdout. mode=1 for log_info + status messages @@ -226,7 +297,7 @@ show_keyserver_url(PKT_signature *sig,int indent,int mode) if(mode!=2) { int i; - char *str; + const char *str; for(i=0;i<indent;i++) putchar(' '); @@ -243,77 +314,73 @@ show_keyserver_url(PKT_signature *sig,int indent,int mode) fprintf(fp,"\n"); } - /* TODO: put in a status-fd tag for preferred keyservers */ + if(mode) + status_one_subpacket(SIGSUBPKT_PREF_KS,len,(crit?0x02:0)|0x01,p); } } - /* mode=0 for stdout. mode=1 for log_info + status messages mode=2 for status messages only + + which bits: + 1 == standard notations + 2 == user notations */ void -show_notation(PKT_signature *sig,int indent,int mode) +show_notation(PKT_signature *sig,int indent,int mode,int which) { - const byte *p; - size_t len; - int seq=0,crit; FILE *fp=mode?log_get_stream():stdout; + struct notation *nd,*notations; - /* There may be multiple notations in the same sig. */ - - while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) - if(len>=8) - { - int n1,n2; - - n1=(p[4]<<8)|p[5]; - n2=(p[6]<<8)|p[7]; - - if(8+n1+n2!=len) - { - log_info(_("WARNING: invalid notation data found\n")); - return; - } - - if(mode!=2) - { - int i; - char *str; - - for(i=0;i<indent;i++) - putchar(' '); + if(which==0) + which=3; - /* This is UTF8 */ - if(crit) - str=_("Critical signature notation: "); - else - str=_("Signature notation: "); - if(mode) - log_info("%s",str); - else - printf("%s",str); - print_utf8_string(fp,p+8,n1); - fprintf(fp,"="); + notations=sig_to_notation(sig); - if(*p&0x80) - print_utf8_string(fp,p+8+n1,n2); - else - fprintf(fp,"[ %s ]",_("not human readable")); + /* There may be multiple notations in the same sig. */ + for(nd=notations;nd;nd=nd->next) + { + if(mode!=2) + { + int has_at=!!strchr(nd->name,'@'); + + if((which&1 && !has_at) || (which&2 && has_at)) + { + int i; + const char *str; + + for(i=0;i<indent;i++) + putchar(' '); + + if(nd->flags.critical) + str=_("Critical signature notation: "); + else + str=_("Signature notation: "); + if(mode) + log_info("%s",str); + else + printf("%s",str); + /* This is all UTF8 */ + print_utf8_string(fp,nd->name,strlen(nd->name)); + fprintf(fp,"="); + print_utf8_string(fp,nd->value,strlen(nd->value)); + fprintf(fp,"\n"); + } + } - fprintf(fp,"\n"); - } + if(mode) + { + write_status_buffer(STATUS_NOTATION_NAME, + nd->name,strlen(nd->name),0); + write_status_buffer(STATUS_NOTATION_DATA, + nd->value,strlen(nd->value),50); + } + } - if(mode) - { - write_status_buffer ( STATUS_NOTATION_NAME, p+8 , n1, 0 ); - write_status_buffer ( STATUS_NOTATION_DATA, p+8+n1, n2, 50 ); - } - } - else - log_info(_("WARNING: invalid notation data found\n")); + free_notation(notations); } static void @@ -346,12 +413,12 @@ list_all( int secret ) hd = keydb_new (secret); if (!hd) - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; else rc = keydb_search_first (hd); if( rc ) { if( rc != -1 ) - log_error("keydb_search_first failed: %s\n", gpg_strerror (rc) ); + log_error("keydb_search_first failed: %s\n", g10_errstr(rc) ); goto leave; } @@ -359,7 +426,7 @@ list_all( int secret ) do { rc = keydb_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); goto leave; } if(!opt.with_colons) @@ -383,7 +450,7 @@ list_all( int secret ) keyblock = NULL; } while (!(rc = keydb_search_next (hd))); if( rc && rc != -1 ) - log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); if(opt.check_sigs && !opt.with_colons) print_signature_stats(&stats); @@ -401,7 +468,7 @@ list_one( STRLIST names, int secret ) KBNODE keyblock = NULL; GETKEY_CTX ctx; const char *resname; - char *keyring_str = _("Keyring"); + const char *keyring_str = _("Keyring"); int i; struct sig_stats stats; @@ -419,7 +486,7 @@ list_one( STRLIST names, int secret ) if( secret ) { rc = get_seckey_bynames( &ctx, NULL, names, &keyblock ); if( rc ) { - log_error("error reading key: %s\n", gpg_strerror (rc) ); + log_error("error reading key: %s\n", g10_errstr(rc) ); get_seckey_end( ctx ); return; } @@ -439,7 +506,7 @@ list_one( STRLIST names, int secret ) else { rc = get_pubkey_bynames( &ctx, NULL, names, &keyblock ); if( rc ) { - log_error("error reading key: %s\n", gpg_strerror (rc) ); + log_error("error reading key: %s\n", g10_errstr(rc) ); get_pubkey_end( ctx ); return; } @@ -463,7 +530,7 @@ list_one( STRLIST names, int secret ) } static void -print_key_data( PKT_public_key *pk, u32 *keyid ) +print_key_data( PKT_public_key *pk ) { int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; int i; @@ -483,10 +550,10 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) { unsigned int use = pk? pk->pubkey_usage : sk->pubkey_usage; - if ( (use & PUBKEY_USAGE_ENC) ) + if ( use & PUBKEY_USAGE_ENC ) putchar ('e'); - if ( (use & PUBKEY_USAGE_SIG) ) + if ( use & PUBKEY_USAGE_SIG ) { putchar ('s'); if( pk? pk->is_primary : sk->is_primary ) @@ -510,9 +577,9 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) disabled=pk_is_disabled(pk); if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) { - if ( (pk->pubkey_usage & PUBKEY_USAGE_ENC) ) + if ( pk->pubkey_usage & PUBKEY_USAGE_ENC ) enc = 1; - if ( (pk->pubkey_usage & PUBKEY_USAGE_SIG) ) + if ( pk->pubkey_usage & PUBKEY_USAGE_SIG ) { sign = 1; if(pk->is_primary) @@ -527,9 +594,9 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) sk = k->pkt->pkt.secret_key; if ( sk->is_valid && !sk->is_revoked && !sk->has_expired && sk->protect.s2k.mode!=1001 ) { - if ( (sk->pubkey_usage & PUBKEY_USAGE_ENC) ) + if ( sk->pubkey_usage & PUBKEY_USAGE_ENC ) enc = 1; - if ( (sk->pubkey_usage & PUBKEY_USAGE_SIG) ) + if ( sk->pubkey_usage & PUBKEY_USAGE_SIG ) { sign = 1; if(sk->is_primary) @@ -555,6 +622,51 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) putchar(':'); } +/* Flags = 0x01 hashed 0x02 critical */ +static void +print_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf) +{ + size_t i; + + printf("spk:%d:%u:%u:",type,flags,(unsigned int)len); + + for(i=0;i<len;i++) + { + /* printable ascii other than : and % */ + if(buf[i]>=32 && buf[i]<=126 && buf[i]!=':' && buf[i]!='%') + printf("%c",buf[i]); + else + printf("%%%02X",buf[i]); + } + + printf("\n"); +} + +void +print_subpackets_colon(PKT_signature *sig) +{ + byte *i; + + assert(opt.show_subpackets); + + for(i=opt.show_subpackets;*i;i++) + { + const byte *p; + size_t len; + int seq,crit; + + seq=0; + + while((p=enum_sig_subpkt(sig->hashed,*i,&len,&seq,&crit))) + print_one_subpacket(*i,len,0x01|(crit?0x02:0),p); + + seq=0; + + while((p=enum_sig_subpkt(sig->unhashed,*i,&len,&seq,&crit))) + print_one_subpacket(*i,len,0x00|(crit?0x02:0),p); + } +} + void dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk) { @@ -603,11 +715,8 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) KBNODE node; PKT_public_key *pk; PKT_secret_key *sk; - u32 keyid[2]; - int any=0; struct sig_stats *stats=opaque; - int newformat=((opt.list_options&LIST_SHOW_VALIDITY) && !secret) - || (opt.list_options&LIST_SHOW_LONG_KEYID); + int skip_sigs=0; /* get the keyid from the keyblock */ node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); @@ -621,164 +730,184 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) { pk = NULL; sk = node->pkt->pkt.secret_key; - keyid_from_sk( sk, keyid ); - - printf("sec%c %4u%c/",(sk->protect.s2k.mode==1001)?'#':' ', - nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo )); - if(opt.list_options&LIST_SHOW_LONG_KEYID) - printf("%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); - else - printf("%08lX",(ulong)keyid[1]); + printf("sec%c %4u%c/%s %s",(sk->protect.s2k.mode==1001)?'#': + (sk->protect.s2k.mode==1002)?'>':' ', + nbits_from_sk( sk ),pubkey_letter( sk->pubkey_algo ), + keystr_from_sk(sk),datestr_from_sk( sk )); - printf(" %s%s",datestr_from_sk( sk ),newformat?"":" " ); + if(sk->has_expired) + { + printf(" ["); + printf(_("expired: %s"),expirestr_from_sk(sk)); + printf("]"); + } + else if(sk->expiredate ) + { + printf(" ["); + printf(_("expires: %s"),expirestr_from_sk(sk)); + printf("]"); + } - if(newformat && sk->expiredate ) - printf(_(" [expires: %s]"), expirestr_from_sk( sk ) ); + printf("\n"); } else { - int validity; pk = node->pkt->pkt.public_key; sk = NULL; - keyid_from_pk( pk, keyid ); - - validity=get_validity(pk,NULL); - printf("pub %4u%c/", - nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo)); - - if(opt.list_options&LIST_SHOW_LONG_KEYID) - printf("%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]); - else - printf("%08lX",(ulong)keyid[1]); + check_trustdb_stale(); - printf(" %s%s",datestr_from_pk( pk ),newformat?"":" " ); + printf("pub %4u%c/%s %s", + nbits_from_pk(pk),pubkey_letter(pk->pubkey_algo), + keystr_from_pk(pk),datestr_from_pk( pk )); /* We didn't include this before in the key listing, but there is room in the new format, so why not? */ - if(newformat && pk->expiredate) - printf(_(" [expires: %s]"), expirestr_from_pk( pk ) ); + if(pk->is_revoked) + { + printf(" ["); + printf(_("revoked: %s"),revokestr_from_pk(pk)); + printf("]"); + } + else if(pk->has_expired) + { + printf(" ["); + printf(_("expired: %s"),expirestr_from_pk(pk)); + printf("]"); + } + else if(pk->expiredate) + { + printf(" ["); + printf(_("expires: %s"),expirestr_from_pk(pk)); + printf("]"); + } + +#if 0 + /* I need to think about this some more. It's easy enough to + include, but it looks sort of confusing in the + listing... */ if(opt.list_options&LIST_SHOW_VALIDITY) - printf(" [%s]",trust_value_to_string(validity)); + { + int validity=get_validity(pk,NULL); + printf(" [%s]",trust_value_to_string(validity)); + } +#endif + + printf("\n"); } + if( fpr ) + print_fingerprint( pk, sk, 0 ); + print_card_serialno (sk); + if( opt.with_key_data ) + print_key_data( pk ); + for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { - int indent; - /* don't list revoked or expired UIDS unless we are in - * verbose mode and signature listing has not been - * requested */ - if ( !opt.verbose && !opt.list_sigs && - (node->pkt->pkt.user_id->is_revoked || - node->pkt->pkt.user_id->is_expired )) - continue; + PKT_user_id *uid=node->pkt->pkt.user_id; - if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) - dump_attribs(node->pkt->pkt.user_id,pk,sk); + if(pk && (uid->is_expired || uid->is_revoked) + && !(opt.list_options&LIST_SHOW_UNUSABLE_UIDS)) + { + skip_sigs=1; + continue; + } + else + skip_sigs=0; - if(!any && newformat) - printf("\n"); + if(attrib_fp && uid->attrib_data!=NULL) + dump_attribs(uid,pk,sk); - if((opt.list_options&LIST_SHOW_VALIDITY) && pk) + if((uid->is_revoked || uid->is_expired) + || ((opt.list_options&LIST_SHOW_UID_VALIDITY) && pk)) { - const char *validity= - trust_value_to_string(get_validity(pk,node->pkt->pkt.user_id)); + const char *validity; + int indent; - /* Includes the 3 spaces for [, ], and " ". */ - indent=((opt.list_options&LIST_SHOW_LONG_KEYID)?23:15) - -strlen(validity); + validity=uid_trust_string_fixed(pk,uid); + indent=(keystrlen()+9)-atoi(uid_trust_string_fixed(NULL,NULL)); - if(indent<0) + if(indent<0 || indent>40) indent=0; - printf("uid%*s[%s] ",indent,"",validity); + printf("uid%*s%s ",indent,"",validity); } - else if(newformat) - printf("uid%*s",26,""); - else if(any) - printf("uid%*s",29,""); - - if ( node->pkt->pkt.user_id->is_revoked ) - fputs ("[revoked] ", stdout); - if ( node->pkt->pkt.user_id->is_expired ) - fputs ("[expired] ", stdout); - - print_utf8_string( stdout, node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len ); + else + printf("uid%*s", (int)keystrlen()+10,""); + + print_utf8_string( stdout, uid->name, uid->len ); putchar('\n'); - if( !any ) { - if( fpr ) - print_fingerprint( pk, sk, 0 ); - print_card_serialno (sk); - if( opt.with_key_data ) - print_key_data( pk, keyid ); - any = 1; - } - if((opt.list_options&LIST_SHOW_PHOTOS) - && node->pkt->pkt.user_id->attribs!=NULL) - show_photos(node->pkt->pkt.user_id->attribs, - node->pkt->pkt.user_id->numattribs,pk,sk); + if((opt.list_options&LIST_SHOW_PHOTOS) && uid->attribs!=NULL) + show_photos(uid->attribs,uid->numattribs,pk,sk); } - else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - u32 keyid2[2]; + else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + { PKT_public_key *pk2 = node->pkt->pkt.public_key; - if( !any ) { - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); /* of the main key */ - any = 1; - } - - keyid_from_pk( pk2, keyid2 ); - printf("sub %4u%c/", - nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo )); - if(opt.list_options&LIST_SHOW_LONG_KEYID) - printf("%08lX%08lX",(ulong)keyid2[0],(ulong)keyid2[1]); + if((pk2->is_revoked || pk2->has_expired) + && !(opt.list_options&LIST_SHOW_UNUSABLE_SUBKEYS)) + { + skip_sigs=1; + continue; + } else - printf("%08lX",(ulong)keyid2[1]); - printf(" %s",datestr_from_pk(pk2)); - if( pk2->expiredate ) - printf(_(" [expires: %s]"), expirestr_from_pk( pk2 ) ); + skip_sigs=0; + + printf("sub %4u%c/%s %s", + nbits_from_pk( pk2 ),pubkey_letter( pk2->pubkey_algo ), + keystr_from_pk(pk2),datestr_from_pk(pk2)); + if( pk2->is_revoked ) + { + printf(" ["); + printf(_("revoked: %s"),revokestr_from_pk(pk2)); + printf("]"); + } + else if( pk2->has_expired ) + { + printf(" ["); + printf(_("expired: %s"),expirestr_from_pk(pk2)); + printf("]"); + } + else if( pk2->expiredate ) + { + printf(" ["); + printf(_("expires: %s"),expirestr_from_pk(pk2)); + printf("]"); + } putchar('\n'); if( fpr > 1 ) - print_fingerprint( pk2, NULL, 0 ); + print_fingerprint( pk2, NULL, 0 ); if( opt.with_key_data ) - print_key_data( pk2, keyid2 ); - } - else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { - u32 keyid2[2]; + print_key_data( pk2 ); + } + else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) + { PKT_secret_key *sk2 = node->pkt->pkt.secret_key; - if( !any ) { - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); /* of the main key */ - print_card_serialno (sk); - any = 1; - } - - keyid_from_sk( sk2, keyid2 ); - printf("ssb %4u%c/", - nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo )); - if(opt.list_options&LIST_SHOW_LONG_KEYID) - printf("%08lX%08lX",(ulong)keyid2[0],(ulong)keyid2[1]); - else - printf("%08lX",(ulong)keyid2[1]); - printf(" %s",datestr_from_sk( sk2 ) ); + printf("ssb%c %4u%c/%s %s", + (sk2->protect.s2k.mode==1001)?'#': + (sk2->protect.s2k.mode==1002)?'>':' ', + nbits_from_sk( sk2 ),pubkey_letter( sk2->pubkey_algo ), + keystr_from_sk(sk2),datestr_from_sk( sk2 ) ); if( sk2->expiredate ) - printf(_(" [expires: %s]"), expirestr_from_sk( sk2 ) ); + { + printf(" ["); + printf(_("expires: %s"),expirestr_from_sk(sk2)); + printf("]"); + } putchar('\n'); if( fpr > 1 ) { - print_fingerprint( NULL, sk2, 0 ); - print_card_serialno (sk); + print_fingerprint( NULL, sk2, 0 ); + print_card_serialno (sk2); } - } - else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { + } + else if( opt.list_sigs + && node->pkt->pkttype == PKT_SIGNATURE + && !skip_sigs ) { PKT_signature *sig = node->pkt->pkt.signature; int sigrc; char *sigstr; @@ -787,42 +916,22 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) /*fflush(stdout);*/ rc = check_key_signature( keyblock, node, NULL ); switch( gpg_err_code (rc) ) { - case 0: sigrc = '!'; break; - case GPG_ERR_BAD_SIGNATURE: stats->inv_sigs++; sigrc = '-'; break; + case 0: sigrc = '!'; break; + case GPG_ERR_BAD_SIGN: stats->inv_sigs++; sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue; - default: stats->oth_err++; sigrc = '%'; break; + default: stats->oth_err++; sigrc = '%'; break; } /* TODO: Make sure a cached sig record here still has the pk that issued it. See also keyedit.c:print_and_check_one_sig */ - } else { rc = 0; sigrc = ' '; } - if( !any ) { /* no user id, (maybe a revocation follows)*/ - /* Check if the pk is really revoked - there could be a - 0x20 sig packet there even if we are not revoked - (say, if a revocation key issued the packet, but the - revocation key isn't present to verify it.) */ - if( sig->sig_class == 0x20 && pk->is_revoked ) - puts("[revoked]"); - else if( sig->sig_class == 0x18 ) - puts("[key binding]"); - else if( sig->sig_class == 0x28 ) - puts("[subkey revoked]"); - else - putchar('\n'); - if( fpr ) - print_fingerprint( pk, sk, 0 ); - print_card_serialno (sk); - any=1; - } - if( sig->sig_class == 0x20 || sig->sig_class == 0x28 || sig->sig_class == 0x30 ) sigstr = "rev"; @@ -839,7 +948,7 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) } fputs( sigstr, stdout ); - printf("%c%c %c%c%c%c%c%c ", + printf("%c%c %c%c%c%c%c%c %s %s", sigrc,(sig->sig_class-0x10>0 && sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ', sig->flags.exportable?' ':'L', @@ -848,31 +957,34 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) sig->flags.notation?'N':' ', sig->flags.expired?'X':' ', (sig->trust_depth>9)?'T': - (sig->trust_depth>0)?'0'+sig->trust_depth:' '); - if(opt.list_options&LIST_SHOW_LONG_KEYID) - printf("%08lX%08lX",(ulong)sig->keyid[0],(ulong)sig->keyid[1]); - else - printf("%08lX",(ulong)sig->keyid[1]); - printf(" %s ", datestr_from_sig(sig)); + (sig->trust_depth>0)?'0'+sig->trust_depth:' ', + keystr(sig->keyid),datestr_from_sig(sig)); + if(opt.list_options&LIST_SHOW_SIG_EXPIRE) + printf(" %s", expirestr_from_sig(sig)); + printf(" "); if( sigrc == '%' ) - printf("[%s] ", gpg_strerror (rc) ); + printf("[%s] ", g10_errstr(rc) ); else if( sigrc == '?' ) ; else if ( !opt.fast_list_mode ) { size_t n; char *p = get_user_id( sig->keyid, &n ); print_utf8_string( stdout, p, n ); - xfree (p); + xfree(p); } putchar('\n'); - if(sig->flags.policy_url && (opt.list_options&LIST_SHOW_POLICY)) + if(sig->flags.policy_url + && (opt.list_options&LIST_SHOW_POLICY_URLS)) show_policy_url(sig,3,0); - if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) - show_notation(sig,3,0); + if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS)) + show_notation(sig,3,0, + ((opt.list_options&LIST_SHOW_STD_NOTATIONS)?1:0)+ + ((opt.list_options&LIST_SHOW_USER_NOTATIONS)?2:0)); - if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + if(sig->flags.pref_ks + && (opt.list_options&LIST_SHOW_KEYSERVER_URLS)) show_keyserver_url(sig,3,0); /* fixme: check or list other sigs here */ @@ -881,6 +993,29 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) putchar('\n'); } +void +print_revokers(PKT_public_key *pk) +{ + /* print the revoker record */ + if( !pk->revkey && pk->numrevkeys ) + BUG(); + else + { + int i,j; + + for (i=0; i < pk->numrevkeys; i++) + { + byte *p; + + printf ("rvk:::%d::::::", pk->revkey[i].algid); + p = pk->revkey[i].fpr; + for (j=0; j < 20; j++, p++ ) + printf ("%02X", *p); + printf (":%02x%s:\n", pk->revkey[i].class, + (pk->revkey[i].class&0x40)?"s":""); + } + } +} static void list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) @@ -894,6 +1029,7 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) int any=0; int trustletter = 0; int ulti_hack = 0; + int i; /* get the keyid from the keyblock */ node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY ); @@ -934,34 +1070,46 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) ulti_hack = 1; putchar(trustletter); } - printf(":%u:%d:%08lX%08lX:%s:%s:", + printf(":%u:%d:%08lX%08lX:%s:%s::", nbits_from_pk( pk ), pk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], colon_datestr_from_pk( pk ), colon_strtime (pk->expiredate) ); - if( pk->local_id ) - printf("%lu", pk->local_id ); - putchar(':'); if( !opt.fast_list_mode && !opt.no_expensive_trust_checks ) putchar( get_ownertrust_info(pk) ); putchar(':'); } - + if (opt.fixed_list_mode) { /* do not merge the first uid with the primary key */ putchar(':'); putchar(':'); print_capabilities (pk, sk, keyblock); + if (secret) { + putchar(':'); /* End of field 13. */ + putchar(':'); /* End of field 14. */ + if (sk->protect.s2k.mode == 1001) + putchar('#'); /* Key is just a stub. */ + else if (sk->protect.s2k.mode == 1002) { + /* Key is stored on an external token (card) or handled by + the gpg-agent. Print the serial number of that token + here. */ + for (i=0; i < sk->protect.ivlen; i++) + printf ("%02X", sk->protect.iv[i]); + } + putchar(':'); /* End of field 15. */ + } putchar('\n'); + if(pk) + print_revokers(pk); if( fpr ) print_fingerprint( pk, sk, 0 ); if( opt.with_key_data ) - print_key_data( pk, keyid ); + print_key_data( pk ); any = 1; } - for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { PKT_user_id *uid=node->pkt->pkt.user_id; @@ -971,11 +1119,10 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) * Fixme: We need a is_valid flag here too */ if( any ) { - int i; char *str=uid->attrib_data?"uat":"uid"; /* If we're listing a secret key, leave out the - validity values for now. FIXME: This should be - handled better in 1.9. */ + validity values for now. This is handled better in + 1.9. */ if ( sk ) printf("%s:::::",str); else if ( uid->is_revoked ) @@ -1018,7 +1165,7 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) if( fpr ) print_fingerprint( pk, sk, 0 ); if( opt.with_key_data ) - print_key_data( pk, keyid ); + print_key_data( pk ); any = 1; } } @@ -1051,7 +1198,7 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) if(trustletter) printf("%c", trustletter ); } - printf(":%u:%d:%08lX%08lX:%s:%s:", + printf(":%u:%d:%08lX%08lX:%s:%s:::::", nbits_from_pk( pk2 ), pk2->pubkey_algo, (ulong)keyid2[0],(ulong)keyid2[1], @@ -1059,18 +1206,12 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) colon_strtime (pk2->expiredate) /* fixme: add LID and ownertrust here */ ); - if( pk->local_id ) /* use the local_id of the main key??? */ - printf("%lu", pk->local_id ); - putchar(':'); - putchar(':'); - putchar(':'); - putchar(':'); print_capabilities (pk2, NULL, NULL); putchar('\n'); if( fpr > 1 ) print_fingerprint( pk2, NULL, 0 ); if( opt.with_key_data ) - print_key_data( pk2, keyid2 ); + print_key_data( pk2 ); } else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { u32 keyid2[2]; @@ -1095,13 +1236,31 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) colon_strtime (sk2->expiredate) /* fixme: add LID */ ); print_capabilities (NULL, sk2, NULL); + if (opt.fixed_list_mode) { + /* We print the serial number only in fixed list mode + for the primary key so, so avoid questions we print + it for subkeys also only in this mode. There is no + technical reason, though. */ + putchar(':'); /* End of field 13. */ + putchar(':'); /* End of field 14. */ + if (sk2->protect.s2k.mode == 1001) + putchar('#'); /* Key is just a stub. */ + else if (sk2->protect.s2k.mode == 1002) { + /* Key is stored on an external token (card) or handled by + the gpg-agent. Print the serial number of that token + here. */ + for (i=0; i < sk2->protect.ivlen; i++) + printf ("%02X", sk2->protect.iv[i]); + } + putchar(':'); /* End of field 15. */ + } putchar ('\n'); if( fpr > 1 ) - print_fingerprint( NULL, sk2, 0 ); + print_fingerprint( NULL, sk2, 0 ); } else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; - int sigrc, fprokay=0; + int sigrc,fprokay=0; char *sigstr; size_t fplen; byte fparray[MAX_FINGERPRINT_LEN]; @@ -1142,21 +1301,21 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) fflush(stdout); if(opt.no_sig_cache) - signer_pk = xcalloc (1, sizeof(PKT_public_key)); + signer_pk=xmalloc_clear(sizeof(PKT_public_key)); rc = check_key_signature2( keyblock, node, NULL, signer_pk, NULL, NULL, NULL ); - switch( gpg_err_code (rc) ) { + switch ( gpg_err_code (rc) ) { case 0: sigrc = '!'; break; - case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; + case GPG_ERR_BAD_SIGN: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: - case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; + case GPG_ERR_UNU_PUBKEY: sigrc = '?'; break; default: sigrc = '%'; break; } if(opt.no_sig_cache) { - if(!rc) + if(rc==0) { fingerprint_from_pk (signer_pk, fparray, &fplen); fprokay=1; @@ -1187,20 +1346,19 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) printf(":"); if( sigrc == '%' ) - printf("[%s] ", gpg_strerror (rc) ); + printf("[%s] ", g10_errstr(rc) ); else if( sigrc == '?' ) ; else if ( !opt.fast_list_mode ) { size_t n; char *p = get_user_id( sig->keyid, &n ); print_string( stdout, p, n, ':' ); - xfree (p); + xfree(p); } printf(":%02x%c:", sig->sig_class,sig->flags.exportable?'x':'l'); + if(opt.no_sig_cache && opt.check_sigs && fprokay) { - size_t i; - printf(":"); for (i=0; i < fplen ; i++ ) @@ -1210,6 +1368,10 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) } printf("\n"); + + if(opt.show_subpackets) + print_subpackets_colon(sig); + /* fixme: check or list other sigs here */ } } @@ -1225,15 +1387,16 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) * Reorder the keyblock so that the primary user ID (and not attribute * packet) comes first. Fixme: Replace this by a generic sort * function. */ -void -reorder_keyblock (KBNODE keyblock) +static void +do_reorder_keyblock (KBNODE keyblock,int attr) { KBNODE primary = NULL, primary0 = NULL, primary2 = NULL; KBNODE last, node; for (node=keyblock; node; primary0=node, node = node->next) { if( node->pkt->pkttype == PKT_USER_ID && - !node->pkt->pkt.user_id->attrib_data && + ((attr && node->pkt->pkt.user_id->attrib_data) || + (!attr && !node->pkt->pkt.user_id->attrib_data)) && node->pkt->pkt.user_id->is_primary ) { primary = primary2 = node; for (node=node->next; node; primary2=node, node = node->next ) { @@ -1264,6 +1427,13 @@ reorder_keyblock (KBNODE keyblock) primary2->next = node; } +void +reorder_keyblock (KBNODE keyblock) +{ + do_reorder_keyblock(keyblock,1); + do_reorder_keyblock(keyblock,0); +} + void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ) { @@ -1315,14 +1485,14 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) { if(sk) { - PKT_secret_key *primary_sk=xcalloc (1,sizeof(*primary_sk)); + PKT_secret_key *primary_sk=xmalloc_clear(sizeof(*primary_sk)); get_seckey(primary_sk,sk->main_keyid); print_fingerprint(NULL,primary_sk,mode|0x80); free_secret_key(primary_sk); } else { - PKT_public_key *primary_pk=xcalloc (1,sizeof(*primary_pk)); + PKT_public_key *primary_pk=xmalloc_clear(sizeof(*primary_pk)); get_pubkey(primary_pk,pk->main_keyid); print_fingerprint(primary_pk,NULL,mode|0x80); free_public_key(primary_pk); @@ -1338,9 +1508,9 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) } else if (mode == 2) { fp = NULL; /* use tty */ - /* Translators: this should fit into 24 bytes to that the fingerprint - * data is properly aligned with the user ID */ if(primary) + /* TRANSLATORS: this should fit into 24 bytes to that the + * fingerprint data is properly aligned with the user ID */ text = _(" Primary key fingerprint:"); else text = _(" Subkey fingerprint:"); @@ -1405,7 +1575,6 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) tty_printf ("\n"); } - /* Print the serial number of an OpenPGP card if available. */ static void print_card_serialno (PKT_secret_key *sk) @@ -1417,7 +1586,7 @@ print_card_serialno (PKT_secret_key *sk) if (!sk->is_protected || sk->protect.s2k.mode != 1002) return; /* Not a card. */ if (opt.with_colons) - return; /* Format not yet defined. */ + return; /* Handled elsewhere. */ fputs (_(" Card serial no. ="), stdout); putchar (' '); @@ -1439,6 +1608,8 @@ print_card_serialno (PKT_secret_key *sk) putchar ('\n'); } + + void set_attrib_fd(int fd) { static int last_fd=-1; @@ -1457,10 +1628,11 @@ void set_attrib_fd(int fd) else if( fd == 2 ) attrib_fp = stderr; else - attrib_fp = fdopen( fd, "w" ); + attrib_fp = fdopen( fd, "wb" ); if( !attrib_fp ) { log_fatal("can't open fd %d for attribute output: %s\n", fd, strerror(errno)); } + last_fd = fd; } diff --git a/g10/keyring.c b/g10/keyring.c index 03a22667c..bd577a63b 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -1,5 +1,5 @@ /* keyring.c - keyring file handling - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -73,7 +74,7 @@ struct keyring_handle { int secret; /* this is for a secret keyring */ struct { CONST_KR_NAME kr; - iobuf_t iobuf; + IOBUF iobuf; int eof; int error; } current; @@ -102,7 +103,7 @@ new_offset_item (void) { struct off_item *k; - k = xcalloc (1,sizeof *k); + k = xmalloc_clear (sizeof *k); return k; } @@ -125,7 +126,7 @@ new_offset_hash_table (void) { struct off_item **tbl; - tbl = xcalloc (2048, sizeof *tbl); + tbl = xmalloc_clear (2048 * sizeof *tbl); return tbl; } @@ -214,6 +215,9 @@ keyring_register_filename (const char *fname, int secret, void **ptr) } } + if (secret) + register_secured_file (fname); + kr = xmalloc (sizeof *kr + strlen (fname)); strcpy (kr->fname, fname); kr->secret = !!secret; @@ -255,7 +259,7 @@ keyring_new (void *token, int secret) assert (resource && !resource->secret == !secret); - hd = xcalloc (1,sizeof *hd); + hd = xmalloc_clear (sizeof *hd); hd->resource = resource; hd->secret = !!secret; active_handles++; @@ -304,7 +308,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes) kr->lockhd = create_dotlock( kr->fname ); if (!kr->lockhd) { log_info ("can't allocate lock for `%s'\n", kr->fname ); - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; } } } @@ -319,7 +323,7 @@ keyring_lock (KEYRING_HANDLE hd, int yes) ; else if (make_dotlock (kr->lockhd, -1) ) { log_info ("can't lock `%s'\n", kr->fname ); - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; } else kr->is_locked = 1; @@ -356,7 +360,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) PACKET *pkt; int rc; KBNODE keyblock = NULL, node, lastnode; - iobuf_t a; + IOBUF a; int in_cert = 0; int pk_no = 0; int uid_no = 0; @@ -369,15 +373,16 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) return -1; /* no successful search */ a = iobuf_open (hd->found.kr->fname); - if (!a) { - log_error ("can't open `%s'\n", hd->found.kr->fname); - return GPG_ERR_KEYRING_OPEN; - } + if (!a) + { + log_error(_("can't open `%s'\n"), hd->found.kr->fname); + return G10ERR_KEYRING_OPEN; + } if (iobuf_seek (a, hd->found.offset) ) { log_error ("can't seek `%s'\n", hd->found.kr->fname); iobuf_close(a); - return GPG_ERR_KEYRING_OPEN; + return G10ERR_KEYRING_OPEN; } pkt = xmalloc (sizeof *pkt); @@ -387,15 +392,15 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) save_mode = set_packet_list_mode(0); while ((rc=parse_packet (a, pkt)) != -1) { hd->found.n_packets++; - if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) { + if (rc == G10ERR_UNKNOWN_PACKET) { free_packet (pkt); init_packet (pkt); continue; } if (rc) { log_error ("keyring_get_keyblock: read error: %s\n", - gpg_strerror (rc) ); - rc = GPG_ERR_INV_KEYRING; + g10_errstr(rc) ); + rc = G10ERR_INV_KEYRING; break; } if (pkt->pkttype == PKT_COMPRESSED) { @@ -478,7 +483,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb) /* Make sure that future search operations fail immediately when * we know that we are working on a invalid keyring */ - if (gpg_err_code (rc) == GPG_ERR_INV_KEYRING) + if (rc == G10ERR_INV_KEYRING) hd->current.error = rc; return rc; @@ -496,7 +501,7 @@ keyring_update_keyblock (KEYRING_HANDLE hd, KBNODE kb) /* need to know the number of packets - do a dummy get_keyblock*/ rc = keyring_get_keyblock (hd, NULL); if (rc) { - log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc)); + log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); return rc; } if (!hd->found.n_packets) @@ -540,7 +545,7 @@ keyring_insert_keyblock (KEYRING_HANDLE hd, KBNODE kb) fname = hd->resource? hd->resource->fname:NULL; if (!fname) - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; /* close this one otherwise we will lose the position for * a next search. Fixme: it would be better to adjust the position @@ -572,7 +577,7 @@ keyring_delete_keyblock (KEYRING_HANDLE hd) /* need to know the number of packets - do a dummy get_keyblock*/ rc = keyring_get_keyblock (hd, NULL); if (rc) { - log_error ("re-reading keyblock failed: %s\n", gpg_strerror (rc)); + log_error ("re-reading keyblock failed: %s\n", g10_errstr (rc)); return rc; } if (!hd->found.n_packets) @@ -629,7 +634,7 @@ prepare_search (KEYRING_HANDLE hd) if (hd->current.kr && !hd->current.eof) { if ( !hd->current.iobuf ) - return GPG_ERR_GENERAL; /* position invalid after a modify */ + return G10ERR_GENERAL; /* position invalid after a modify */ return 0; /* okay */ } @@ -654,11 +659,12 @@ prepare_search (KEYRING_HANDLE hd) hd->current.eof = 0; hd->current.iobuf = iobuf_open (hd->current.kr->fname); - if (!hd->current.iobuf) { + if (!hd->current.iobuf) + { hd->current.error = gpg_error_from_errno (errno); - log_error ("can't open `%s'\n", hd->current.kr->fname ); + log_error(_("can't open `%s'\n"), hd->current.kr->fname ); return hd->current.error; - } + } return 0; } @@ -776,7 +782,7 @@ prepare_word_match (const byte *name) int c; /* the original length is always enough for the pattern */ - p = pattern = xmalloc (strlen(name)+1); + p = pattern = xmalloc(strlen(name)+1); do { /* skip leading delimiters */ while( *name && !word_match_chars[*name] ) @@ -1071,7 +1077,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, goto found; break; default: - rc = GPG_ERR_INV_ARG; + rc = G10ERR_INV_ARG; goto found; } } @@ -1085,7 +1091,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, for (n=any_skip?0:ndesc; n < ndesc; n++) { if (desc[n].skipfnc - && desc[n].skipfnc (desc[n].skipfncvalue, aki)) + && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid)) break; } if (n == ndesc) @@ -1141,7 +1147,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, static int create_tmp_file (const char *template, - char **r_bakfname, char **r_tmpfname, iobuf_t *r_fp) + char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) { char *bakfname, *tmpfname; mode_t oldmask; @@ -1184,15 +1190,22 @@ create_tmp_file (const char *template, /* Create the temp file with limited access */ oldmask=umask(077); - *r_fp = iobuf_create (tmpfname); + if (is_secured_filename (tmpfname)) + { + *r_fp = NULL; + errno = EPERM; + } + else + *r_fp = iobuf_create (tmpfname); umask(oldmask); - if (!*r_fp) { - int tmperr = gpg_error_from_errno (errno); - log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) ); + if (!*r_fp) + { + int rc = gpg_error_from_errno (errno); + log_error(_("can't create `%s': %s\n"), tmpfname, strerror(errno) ); xfree (tmpfname); xfree (bakfname); - return tmperr; - } + return rc; + } *r_bakfname = bakfname; *r_tmpfname = tmpfname; @@ -1219,10 +1232,10 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, #endif if (rename (fname, bakfname) ) { - int tmperr = gpg_error_from_errno (errno); + rc = gpg_error_from_errno (errno); log_error ("renaming `%s' to `%s' failed: %s\n", fname, bakfname, strerror(errno) ); - return tmperr; + return rc; } } @@ -1230,11 +1243,14 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) remove( fname ); #endif + if (secret) + unregister_secured_file (fname); if (rename (tmpfname, fname) ) { rc = gpg_error_from_errno (errno); - log_error ("renaming `%s' to `%s' failed: %s\n", + log_error (_("renaming `%s' to `%s' failed: %s\n"), tmpfname, fname, strerror(errno) ); + register_secured_file (fname); if (secret) { log_info(_("WARNING: 2 files with confidential" @@ -1269,7 +1285,7 @@ rename_tmp_file (const char *bakfname, const char *tmpfname, static int -write_keyblock (iobuf_t fp, KBNODE keyblock) +write_keyblock (IOBUF fp, KBNODE keyblock) { KBNODE kbctx = NULL, node; int rc; @@ -1282,7 +1298,7 @@ write_keyblock (iobuf_t fp, KBNODE keyblock) if ( (rc = build_packet (fp, node->pkt) )) { log_error ("build_packet(%d) failed: %s\n", - node->pkt->pkttype, gpg_strerror (rc) ); + node->pkt->pkttype, g10_errstr(rc) ); return rc; } if (node->pkt->pkttype == PKT_SIGNATURE) @@ -1299,11 +1315,12 @@ write_keyblock (iobuf_t fp, KBNODE keyblock) iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/ iobuf_put (fp, 2); /* 2 bytes */ iobuf_put (fp, 0); /* unused */ - if (iobuf_put (fp, cacheval)) { - int tmperr = gpg_error_from_errno (errno); - log_error ("writing sigcache packet failed\n"); - return tmperr; - } + if (iobuf_put (fp, cacheval)) + { + rc = gpg_error_from_errno (errno); + log_error ("writing sigcache packet failed\n"); + return rc; + } } } return 0; @@ -1315,13 +1332,13 @@ write_keyblock (iobuf_t fp, KBNODE keyblock) * This is only done for the public keyrings. */ int -keyring_rebuild_cache (void *token) +keyring_rebuild_cache (void *token,int noisy) { KEYRING_HANDLE hd; KEYDB_SEARCH_DESC desc; KBNODE keyblock = NULL, node; const char *lastresname = NULL, *resname; - iobuf_t tmpfp = NULL; + IOBUF tmpfp = NULL; char *tmpfilename = NULL; char *bakfilename = NULL; int rc; @@ -1361,8 +1378,8 @@ keyring_rebuild_cache (void *token) if (rc) goto leave; lastresname = resname; - if (!opt.quiet) - log_info (_("checking keyring `%s'\n"), resname); + if (noisy && !opt.quiet) + log_info (_("caching keyring `%s'\n"), resname); rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp); if (rc) goto leave; @@ -1372,7 +1389,7 @@ keyring_rebuild_cache (void *token) rc = keyring_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keyring_get_keyblock failed: %s\n", gpg_strerror (rc)); + log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc)); goto leave; } assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY); @@ -1380,16 +1397,24 @@ keyring_rebuild_cache (void *token) /* check all signature to set the signature's cache flags */ for (node=keyblock; node; node=node->next) { + /* Note that this doesn't cache the result of a revocation + issued by a designated revoker. This is because the pk + in question does not carry the revkeys as we haven't + merged the key and selfsigs. It is questionable whether + this matters very much since there are very very few + designated revoker revocation packets out there. */ + if (node->pkt->pkttype == PKT_SIGNATURE) { - /* Note that this doesn't cache the result of a - revocation issued by a designated revoker. This is - because the pk in question does not carry the revkeys - as we haven't merged the key and selfsigs. It is - questionable whether this matters very much since - there are very very few designated revoker revocation - packets out there. */ - check_key_signature (keyblock, node, NULL); + PKT_signature *sig=node->pkt->pkt.signature; + + if(!opt.no_sig_cache && sig->flags.checked && sig->flags.valid + && (openpgp_md_test_algo(sig->digest_algo) + || openpgp_pk_test_algo(sig->pubkey_algo))) + sig->flags.checked=sig->flags.valid=0; + else + check_key_signature (keyblock, node, NULL); + sigcount++; } } @@ -1399,8 +1424,8 @@ keyring_rebuild_cache (void *token) if (rc) goto leave; - if ( !(++count % 50) && !opt.quiet) - log_info(_("%lu keys checked so far (%lu signatures)\n"), + if ( !(++count % 50) && noisy && !opt.quiet) + log_info(_("%lu keys cached so far (%lu signatures)\n"), count, sigcount ); } /* end main loop */ @@ -1408,10 +1433,11 @@ keyring_rebuild_cache (void *token) rc = 0; if (rc) { - log_error ("keyring_search failed: %s\n", gpg_strerror (rc)); + log_error ("keyring_search failed: %s\n", g10_errstr(rc)); goto leave; } - log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount ); + if(noisy || opt.verbose) + log_info(_("%lu keys cached (%lu signatures)\n"), count, sigcount ); if (tmpfp) { if (iobuf_close (tmpfp)) @@ -1452,17 +1478,16 @@ static int do_copy (int mode, const char *fname, KBNODE root, int secret, off_t start_offset, unsigned int n_packets ) { - iobuf_t fp, newfp; + IOBUF fp, newfp; int rc=0; char *bakfname = NULL; char *tmpfname = NULL; - /* Open the source file. Because we do a rname, we have to check the + /* Open the source file. Because we do a rename, we have to check the permissions of the file */ if (access (fname, W_OK)) return gpg_error_from_errno (errno); - fp = iobuf_open (fname); if (mode == 1 && !fp && errno == ENOENT) { /* insert mode but file does not exist: create a new file */ @@ -1470,14 +1495,19 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, mode_t oldmask; oldmask=umask(077); - newfp = iobuf_create (fname); + if (!secret && is_secured_filename (fname)) { + newfp = NULL; + errno = EPERM; + } + else + newfp = iobuf_create (fname); umask(oldmask); - if( !newfp ) { - int tmperr = gpg_error_from_errno (errno); - log_error (_("%s: can't create: %s\n"), - fname, strerror(errno)); - return tmperr; - } + if( !newfp ) + { + rc = gpg_error_from_errno (errno); + log_error (_("can't create `%s': %s\n"), fname, strerror(errno)); + return rc; + } if( !opt.quiet ) log_info(_("%s: keyring created\n"), fname ); @@ -1485,38 +1515,44 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, while ( (node = walk_kbnode( root, &kbctx, 0 )) ) { if( (rc = build_packet( newfp, node->pkt )) ) { log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, gpg_strerror (rc) ); + node->pkt->pkttype, g10_errstr(rc) ); iobuf_cancel(newfp); return rc; } } - if (iobuf_close(newfp)) { - int tmperr = gpg_error_from_errno (errno); + if( iobuf_close(newfp) ) { + rc = gpg_error_from_errno (errno); log_error ("%s: close failed: %s\n", fname, strerror(errno)); - return tmperr; + return rc; } return 0; /* ready */ } - if( !fp ) { + if( !fp ) + { rc = gpg_error_from_errno (errno); - log_error ("%s: can't open: %s\n", fname, strerror(errno) ); + log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); goto leave; - } + } - /* create the new file */ + /* Create the new file. */ rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp); if (rc) { iobuf_close(fp); goto leave; } + if (secret) + register_secured_file (tmpfname); + if( mode == 1 ) { /* insert */ /* copy everything to the new file */ rc = copy_all_packets (fp, newfp); if( rc != -1 ) { log_error("%s: copy to `%s' failed: %s\n", - fname, tmpfname, gpg_strerror (rc) ); + fname, tmpfname, g10_errstr(rc) ); iobuf_close(fp); + if (secret) + unregister_secured_file (tmpfname); iobuf_cancel(newfp); goto leave; } @@ -1528,8 +1564,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = copy_some_packets( fp, newfp, start_offset ); if( rc ) { /* should never get EOF here */ log_error ("%s: copy to `%s' failed: %s\n", - fname, tmpfname, gpg_strerror (rc) ); + fname, tmpfname, g10_errstr(rc) ); iobuf_close(fp); + if (secret) + unregister_secured_file (tmpfname); iobuf_cancel(newfp); goto leave; } @@ -1538,8 +1576,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = skip_some_packets( fp, n_packets ); if( rc ) { log_error("%s: skipping %u packets failed: %s\n", - fname, n_packets, gpg_strerror (rc)); + fname, n_packets, g10_errstr(rc)); iobuf_close(fp); + if (secret) + unregister_secured_file (tmpfname); iobuf_cancel(newfp); goto leave; } @@ -1549,6 +1589,8 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = write_keyblock (newfp, root); if (rc) { iobuf_close(fp); + if (secret) + unregister_secured_file (tmpfname); iobuf_cancel(newfp); goto leave; } @@ -1559,8 +1601,10 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = copy_all_packets( fp, newfp ); if( rc != -1 ) { log_error("%s: copy to `%s' failed: %s\n", - fname, tmpfname, gpg_strerror (rc) ); + fname, tmpfname, g10_errstr(rc) ); iobuf_close(fp); + if (secret) + unregister_secured_file (tmpfname); iobuf_cancel(newfp); goto leave; } @@ -1582,7 +1626,7 @@ do_copy (int mode, const char *fname, KBNODE root, int secret, rc = rename_tmp_file (bakfname, tmpfname, fname, secret); leave: - xfree (bakfname); - xfree (tmpfname); + xfree(bakfname); + xfree(tmpfname); return rc; } diff --git a/g10/keyring.h b/g10/keyring.h index 528557a70..773d7b492 100644 --- a/g10/keyring.h +++ b/g10/keyring.h @@ -15,14 +15,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GPG_KEYRING_H #define GPG_KEYRING_H 1 -#include "global.h" - typedef struct keyring_handle *KEYRING_HANDLE; @@ -41,6 +40,6 @@ 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 *); +int keyring_rebuild_cache (void *token,int noisy); #endif /*GPG_KEYRING_H*/ diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h index 314d7898e..a5e6e8c37 100644 --- a/g10/keyserver-internal.h +++ b/g10/keyserver-internal.h @@ -1,4 +1,23 @@ -/* Keyserver internals */ +/* keyserver-internal.h - Keyserver internals + * Copyright (C) 2001, 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ #ifndef _KEYSERVER_INTERNAL_H_ #define _KEYSERVER_INTERNAL_H_ @@ -8,14 +27,28 @@ #include "../common/iobuf.h" #include "types.h" -void parse_keyserver_options(char *options); -int parse_keyserver_uri(char *uri, - const char *configname,unsigned int configlineno); +int parse_keyserver_options(char *options); +void free_keyserver_spec(struct keyserver_spec *keyserver); +struct keyserver_spec *keyserver_match(struct keyserver_spec *spec); +struct keyserver_spec *parse_keyserver_uri(const char *string, + int require_scheme, + const char *configname, + unsigned int configlineno); +struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig); int keyserver_export(STRLIST users); int keyserver_import(STRLIST users); -int keyserver_import_fprint(const byte *fprint,size_t fprint_len); -int keyserver_import_keyid(u32 *keyid); +int keyserver_import_fprint(const byte *fprint,size_t fprint_len, + struct keyserver_spec *keyserver); +int keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver); int keyserver_refresh(STRLIST users); int keyserver_search(STRLIST tokens); +int keyserver_fetch(STRLIST urilist); +int keyserver_import_cert(const char *name, + unsigned char **fpr,size_t *fpr_len); +int keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len); +int keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len, + struct keyserver_spec *keyserver); +int keyserver_import_ldap(const char *name, + unsigned char **fpr,size_t *fpr_len); #endif /* !_KEYSERVER_INTERNAL_H_ */ diff --git a/g10/keyserver.c b/g10/keyserver.c index 445c07620..af1e5f773 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1,5 +1,6 @@ /* keyserver.c - generic keyserver code - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -24,6 +26,9 @@ #include <string.h> #include <stdlib.h> #include <assert.h> +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#endif #include "gpg.h" #include "filter.h" @@ -33,149 +38,302 @@ #include "main.h" #include "i18n.h" #include "iobuf.h" -#include "memory.h" #include "ttyio.h" #include "options.h" #include "packet.h" +#include "trustdb.h" #include "keyserver-internal.h" #include "util.h" -#define GET 0 -#define SEND 1 -#define SEARCH 2 +#define GPGKEYS_PREFIX "gpgkeys_" + +#if defined(HAVE_LIBCURL) || defined(FAKE_CURL) +#define GPGKEYS_CURL "gpgkeys_curl" +#endif + +#ifdef GPGKEYS_CURL +#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_PREFIX)+strlen(GPGKEYS_CURL)) +#else +#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_PREFIX)) +#endif struct keyrec { KEYDB_SEARCH_DESC desc; - time_t createtime,expiretime; + u32 createtime,expiretime; int size,flags; byte type; - iobuf_t uidbuf; - int lines; + IOBUF uidbuf; + unsigned int lines; }; -struct kopts -{ - char *name; - int tell; /* tell remote process about this one */ - int *flag; -} keyserver_opts[]= +enum ks_action {KS_UNKNOWN=0,KS_GET,KS_GETNAME,KS_SEND,KS_SEARCH}; + +static struct parse_options keyserver_opts[]= + { + /* some of these options are not real - just for the help + message */ + {"max-cert-size",0,NULL,NULL}, + {"include-revoked",0,NULL,N_("include revoked keys in search results")}, + {"include-subkeys",0,NULL,N_("include subkeys when searching by key ID")}, + {"use-temp-files",0,NULL, + N_("use temporary files to pass data to keyserver helpers")}, + {"keep-temp-files",KEYSERVER_KEEP_TEMP_FILES,NULL, + N_("do not delete temporary files after using them")}, + {"refresh-add-fake-v3-keyids",KEYSERVER_ADD_FAKE_V3,NULL, + NULL}, + {"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL, + N_("automatically retrieve keys when verifying signatures")}, + {"honor-keyserver-url",KEYSERVER_HONOR_KEYSERVER_URL,NULL, + N_("honor the preferred keyserver URL set on the key")}, + {"honor-pka-record",KEYSERVER_HONOR_PKA_RECORD,NULL, + N_("honor the PKA record set on a key when retrieving keys")}, + {NULL,0,NULL,NULL} + }; + +static int keyserver_work(enum ks_action action,STRLIST list, + KEYDB_SEARCH_DESC *desc,int count, + unsigned char **fpr,size_t *fpr_len, + struct keyserver_spec *keyserver); + +/* Reasonable guess */ +#define DEFAULT_MAX_CERT_SIZE 16384 + +static size_t max_cert_size=DEFAULT_MAX_CERT_SIZE; + +static void +add_canonical_option(char *option,STRLIST *list) { - {"include-revoked",1,&opt.keyserver_options.include_revoked}, - {"include-disabled",1,&opt.keyserver_options.include_disabled}, - {"include-subkeys",1,&opt.keyserver_options.include_subkeys}, - {"keep-temp-files",0,&opt.keyserver_options.keep_temp_files}, - {"honor-http-proxy",1,&opt.keyserver_options.honor_http_proxy}, - {"broken-http-proxy",1,&opt.keyserver_options.broken_http_proxy}, - {"refresh-add-fake-v3-keyids",0,&opt.keyserver_options.fake_v3_keyids}, - {"auto-key-retrieve",0,&opt.keyserver_options.auto_key_retrieve}, - {"try-dns-srv",1,&opt.keyserver_options.try_dns_srv}, - {NULL} -}; + char *arg=argsplit(option); -static int keyserver_work(int action,STRLIST list, - KEYDB_SEARCH_DESC *desc,int count); + if(arg) + { + char *joined; + + joined=xmalloc(strlen(option)+1+strlen(arg)+1); + /* Make a canonical name=value form with no spaces */ + strcpy(joined,option); + strcat(joined,"="); + strcat(joined,arg); + append_to_strlist(list,joined); + xfree(joined); + } + else + append_to_strlist(list,option); +} -void +int parse_keyserver_options(char *options) { + int ret=1; char *tok; + char *max_cert=NULL; - while((tok=strsep(&options," ,"))) - { - int i,hit=0; + keyserver_opts[0].value=&max_cert; + while((tok=optsep(&options))) + { if(tok[0]=='\0') continue; - for(i=0;keyserver_opts[i].name;i++) - { - if(ascii_strcasecmp(tok,keyserver_opts[i].name)==0) - { - *(keyserver_opts[i].flag)=1; - hit=1; - break; - } - else if(ascii_strncasecmp("no-",tok,3)==0 && - ascii_strcasecmp(&tok[3],keyserver_opts[i].name)==0) - { - *(keyserver_opts[i].flag)=0; - hit=1; - break; - } - } + /* For backwards compatibility. 1.2.x used honor-http-proxy and + there are a good number of documents published that recommend + it. */ + if(ascii_strcasecmp(tok,"honor-http-proxy")==0) + tok="http-proxy"; + else if(ascii_strcasecmp(tok,"no-honor-http-proxy")==0) + tok="no-http-proxy"; + + /* We accept quite a few possible options here - some options to + handle specially, the keyserver_options list, and import and + export options that pertain to keyserver operations. Note + that you must use strncasecmp here as there might be an + =argument attached which will foil the use of strcasecmp. */ - /* These options need more than just a flag */ - if(!hit) - { - if(ascii_strcasecmp(tok,"verbose")==0) - opt.keyserver_options.verbose++; - else if(ascii_strcasecmp(tok,"no-verbose")==0) - opt.keyserver_options.verbose--; #ifdef EXEC_TEMPFILE_ONLY - else if(ascii_strcasecmp(tok,"use-temp-files")==0 || - ascii_strcasecmp(tok,"no-use-temp-files")==0) - log_info(_("WARNING: keyserver option \"%s\" is not used " - "on this platform\n"),tok); + if(ascii_strncasecmp(tok,"use-temp-files",14)==0 || + ascii_strncasecmp(tok,"no-use-temp-files",17)==0) + log_info(_("WARNING: keyserver option `%s' is not used" + " on this platform\n"),tok); #else - else if(ascii_strcasecmp(tok,"use-temp-files")==0) - opt.keyserver_options.use_temp_files=1; - else if(ascii_strcasecmp(tok,"no-use-temp-files")==0) - opt.keyserver_options.use_temp_files=0; + if(ascii_strncasecmp(tok,"use-temp-files",14)==0) + opt.keyserver_options.options|=KEYSERVER_USE_TEMP_FILES; + else if(ascii_strncasecmp(tok,"no-use-temp-files",17)==0) + opt.keyserver_options.options&=~KEYSERVER_USE_TEMP_FILES; #endif - else - if(!parse_import_options(tok, - &opt.keyserver_options.import_options) && - !parse_export_options(tok, - &opt.keyserver_options.export_options)) - add_to_strlist(&opt.keyserver_options.other,tok); + else if(!parse_options(tok,&opt.keyserver_options.options, + keyserver_opts,0) + && !parse_import_options(tok, + &opt.keyserver_options.import_options,0) + && !parse_export_options(tok, + &opt.keyserver_options.export_options,0)) + { + /* All of the standard options have failed, so the option is + destined for a keyserver plugin. */ + add_canonical_option(tok,&opt.keyserver_options.other); } } + + if(max_cert) + { + max_cert_size=strtoul(max_cert,(char **)NULL,10); + + if(max_cert_size==0) + max_cert_size=DEFAULT_MAX_CERT_SIZE; + } + + return ret; } -int -parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) +void +free_keyserver_spec(struct keyserver_spec *keyserver) +{ + xfree(keyserver->uri); + xfree(keyserver->scheme); + xfree(keyserver->auth); + xfree(keyserver->host); + xfree(keyserver->port); + xfree(keyserver->path); + xfree(keyserver->opaque); + free_strlist(keyserver->options); + xfree(keyserver); +} + +/* Return 0 for match */ +static int +cmp_keyserver_spec(struct keyserver_spec *one,struct keyserver_spec *two) +{ + if(ascii_strcasecmp(one->scheme,two->scheme)==0) + { + if(one->host && two->host && ascii_strcasecmp(one->host,two->host)==0) + { + if((one->port && two->port + && ascii_strcasecmp(one->port,two->port)==0) + || (!one->port && !two->port)) + return 0; + } + else if(one->opaque && two->opaque + && ascii_strcasecmp(one->opaque,two->opaque)==0) + return 0; + } + + return 1; +} + +/* Try and match one of our keyservers. If we can, return that. If + we can't, return our input. */ +struct keyserver_spec * +keyserver_match(struct keyserver_spec *spec) +{ + struct keyserver_spec *ks; + + for(ks=opt.keyserver;ks;ks=ks->next) + if(cmp_keyserver_spec(spec,ks)==0) + return ks; + + return spec; +} + +/* TODO: once we cut over to an all-curl world, we don't need this + parser any longer so it can be removed, or at least moved to + keyserver/ksutil.c for limited use in gpgkeys_ldap or the like. */ + +struct keyserver_spec * +parse_keyserver_uri(const char *string,int require_scheme, + const char *configname,unsigned int configlineno) { int assume_hkp=0; + struct keyserver_spec *keyserver; + const char *idx; + int count; + char *uri,*options; + + assert(string!=NULL); + + keyserver=xmalloc_clear(sizeof(struct keyserver_spec)); + + uri=xstrdup(string); + + options=strchr(uri,' '); + if(options) + { + char *tok; - assert(uri!=NULL); + *options='\0'; + options++; - opt.keyserver_host=NULL; - opt.keyserver_port=NULL; - opt.keyserver_opaque=NULL; + while((tok=optsep(&options))) + add_canonical_option(tok,&keyserver->options); + } /* Get the scheme */ - opt.keyserver_scheme=strsep(&uri,":"); - if(uri==NULL) + for(idx=uri,count=0;*idx && *idx!=':';idx++) + { + count++; + + /* Do we see the start of an RFC-2732 ipv6 address here? If so, + there clearly isn't a scheme so get out early. */ + if(*idx=='[') + { + /* Was the '[' the first thing in the string? If not, we + have a mangled scheme with a [ in it so fail. */ + if(count==1) + break; + else + goto fail; + } + } + + if(count==0) + goto fail; + + if(*idx=='\0' || *idx=='[') { + if(require_scheme) + return NULL; + /* Assume HKP if there is no scheme */ assume_hkp=1; - uri=opt.keyserver_scheme; - opt.keyserver_scheme="hkp"; + keyserver->scheme=xstrdup("hkp"); + + keyserver->uri=xmalloc(strlen(keyserver->scheme)+3+strlen(uri)+1); + strcpy(keyserver->uri,keyserver->scheme); + strcat(keyserver->uri,"://"); + strcat(keyserver->uri,uri); } else { + int i; + + keyserver->uri=xstrdup(uri); + + keyserver->scheme=xmalloc(count+1); + /* Force to lowercase */ - char *i; + for(i=0;i<count;i++) + keyserver->scheme[i]=ascii_tolower(uri[i]); + + keyserver->scheme[i]='\0'; - for(i=opt.keyserver_scheme;*i!='\0';i++) - *i=ascii_tolower(*i); + /* Skip past the scheme and colon */ + uri+=count+1; } - if(ascii_strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0) + if(ascii_strcasecmp(keyserver->scheme,"x-broken-hkp")==0) { deprecated_warning(configname,configlineno,"x-broken-hkp", "--keyserver-options ","broken-http-proxy"); - opt.keyserver_scheme="hkp"; - opt.keyserver_options.broken_http_proxy=1; + xfree(keyserver->scheme); + keyserver->scheme=xstrdup("hkp"); + append_to_strlist(&opt.keyserver_options.other,"broken-http-proxy"); } - else if(ascii_strcasecmp(opt.keyserver_scheme,"x-hkp")==0 - || ascii_strcasecmp(opt.keyserver_scheme,"http")==0) + else if(ascii_strcasecmp(keyserver->scheme,"x-hkp")==0) { /* Canonicalize this to "hkp" so it works with both the internal and external keyserver interface. */ - opt.keyserver_scheme="hkp"; + xfree(keyserver->scheme); + keyserver->scheme=xstrdup("hkp"); } if(assume_hkp || (uri[0]=='/' && uri[1]=='/')) @@ -186,57 +344,124 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) if(!assume_hkp) uri+=2; - /* Get the host */ - opt.keyserver_host=strsep(&uri,":/"); - if(opt.keyserver_host[0]=='\0') - return GPG_ERR_BAD_URI; + /* Do we have userinfo auth data present? */ + for(idx=uri,count=0;*idx && *idx!='@' && *idx!='/';idx++) + count++; - if(uri==NULL || uri[0]=='\0') - opt.keyserver_port=NULL; - else + /* We found a @ before the slash, so that means everything + before the @ is auth data. */ + if(*idx=='@') { - char *ch; + if(count==0) + goto fail; - /* Get the port */ - opt.keyserver_port=strsep(&uri,"/"); + keyserver->auth=xmalloc(count+1); + strncpy(keyserver->auth,uri,count); + keyserver->auth[count]='\0'; + uri+=count+1; + } - /* Ports are digits only */ - ch=opt.keyserver_port; - while(*ch!='\0') - { - if(!digitp(ch)) - return GPG_ERR_BAD_URI; + /* Is it an RFC-2732 ipv6 [literal address] ? */ + if(*uri=='[') + { + for(idx=uri+1,count=1;*idx + && ((isascii (*idx) && isxdigit(*idx)) + || *idx==':' || *idx=='.');idx++) + count++; + + /* Is the ipv6 literal address terminated? */ + if(*idx==']') + count++; + else + goto fail; + } + else + for(idx=uri,count=0;*idx && *idx!=':' && *idx!='/';idx++) + count++; - ch++; - } + if(count==0) + goto fail; + + keyserver->host=xmalloc(count+1); + strncpy(keyserver->host,uri,count); + keyserver->host[count]='\0'; + /* Skip past the host */ + uri+=count; + + if(*uri==':') + { /* It would seem to be reasonable to limit the range of the ports to values between 1-65535, but RFC 1738 and 1808 imply there is no limit. Of course, the real world has limits. */ + + for(idx=uri+1,count=0;*idx && *idx!='/';idx++) + { + count++; + + /* Ports are digits only */ + if(!digitp(idx)) + goto fail; + } + + keyserver->port=xmalloc(count+1); + strncpy(keyserver->port,uri+1,count); + keyserver->port[count]='\0'; + + /* Skip past the colon and port number */ + uri+=1+count; } - /* (any path part of the URI is discarded for now as no keyserver - uses it yet) */ + /* Everything else is the path */ + if(*uri) + keyserver->path=xstrdup(uri); + else + keyserver->path=xstrdup("/"); + + if(keyserver->path[1]!='\0') + keyserver->flags.direct_uri=1; } else if(uri[0]!='/') { /* No slash means opaque. Just record the opaque blob and get out. */ - opt.keyserver_opaque=uri; - return 0; + keyserver->opaque=xstrdup(uri); } else { /* One slash means absolute path. We don't need to support that yet. */ - return GPG_ERR_BAD_URI; + goto fail; } - if(opt.keyserver_scheme[0]=='\0') - return GPG_ERR_BAD_URI; + return keyserver; - return 0; + fail: + free_keyserver_spec(keyserver); + + return NULL; +} + +struct keyserver_spec * +parse_preferred_keyserver(PKT_signature *sig) +{ + struct keyserver_spec *spec=NULL; + const byte *p; + size_t plen; + + p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&plen); + if(p && plen) + { + byte *dupe=xmalloc(plen+1); + + memcpy(dupe,p,plen); + dupe[plen]='\0'; + spec=parse_keyserver_uri(dupe,1,NULL,0); + xfree(dupe); + } + + return spec; } static void @@ -253,7 +478,7 @@ print_keyrec(int number,struct keyrec *keyrec) if(keyrec->type) { - const char *str = gcry_pk_algo_name (keyrec->type); + const char *str=pubkey_algo_to_string(keyrec->type); if(str) printf("%s ",str); @@ -263,25 +488,32 @@ print_keyrec(int number,struct keyrec *keyrec) switch(keyrec->desc.mode) { + /* If the keyserver helper gave us a short keyid, we have no + choice but to use it. Do check --keyid-format to add a 0x if + needed. */ case KEYDB_SEARCH_MODE_SHORT_KID: - printf("key %08lX",(ulong)keyrec->desc.u.kid[1]); + printf("key %s%08lX", + (opt.keyid_format==KF_0xSHORT + || opt.keyid_format==KF_0xLONG)?"0x":"", + (ulong)keyrec->desc.u.kid[1]); break; + /* However, if it gave us a long keyid, we can honor + --keyid-format */ case KEYDB_SEARCH_MODE_LONG_KID: - printf("key %08lX%08lX",(ulong)keyrec->desc.u.kid[0], - (ulong)keyrec->desc.u.kid[1]); + printf("key %s",keystr(keyrec->desc.u.kid)); break; case KEYDB_SEARCH_MODE_FPR16: printf("key "); for(i=0;i<16;i++) - printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]); + printf("%02X",keyrec->desc.u.fpr[i]); break; case KEYDB_SEARCH_MODE_FPR20: printf("key "); for(i=0;i<20;i++) - printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]); + printf("%02X",keyrec->desc.u.fpr[i]); break; default: @@ -290,17 +522,23 @@ print_keyrec(int number,struct keyrec *keyrec) } if(keyrec->createtime>0) - printf(", created %s",strtimestamp(keyrec->createtime)); + { + printf(", "); + printf(_("created: %s"),strtimestamp(keyrec->createtime)); + } if(keyrec->expiretime>0) - printf(", expires %s",strtimestamp(keyrec->expiretime)); + { + printf(", "); + printf(_("expires: %s"),strtimestamp(keyrec->expiretime)); + } if(keyrec->flags&1) - printf(" (%s)",("revoked")); + printf(" (%s)",_("revoked")); if(keyrec->flags&2) - printf(" (%s)",("disabled")); + printf(" (%s)",_("disabled")); if(keyrec->flags&4) - printf(" (%s)",("expired")); + printf(" (%s)",_("expired")); printf("\n"); } @@ -322,7 +560,7 @@ parse_keyrec(char *keystring) return NULL; else if(work->desc.mode==KEYDB_SEARCH_MODE_NONE) { - xfree (work); + xfree(work); return NULL; } else @@ -335,7 +573,7 @@ parse_keyrec(char *keystring) if(work==NULL) { - work=xcalloc (1,sizeof(struct keyrec)); + work=xmalloc_clear(sizeof(struct keyrec)); work->uidbuf=iobuf_temp(); } @@ -356,7 +594,7 @@ parse_keyrec(char *keystring) if(work->desc.mode) { ret=work; - work=xcalloc (1,sizeof(struct keyrec)); + work=xmalloc_clear(sizeof(struct keyrec)); work->uidbuf=iobuf_temp(); } @@ -391,12 +629,23 @@ parse_keyrec(char *keystring) if((tok=strsep(&keystring,":"))==NULL) return ret; - work->createtime=atoi(tok); + if(atoi(tok)<=0) + work->createtime=0; + else + work->createtime=atoi(tok); if((tok=strsep(&keystring,":"))==NULL) return ret; - work->expiretime=atoi(tok); + if(atoi(tok)<=0) + work->expiretime=0; + else + { + work->expiretime=atoi(tok); + /* Force the 'e' flag on if this key is expired. */ + if(work->expiretime<=make_timestamp()) + work->flags|=4; + } if((tok=strsep(&keystring,":"))==NULL) return ret; @@ -419,9 +668,6 @@ parse_keyrec(char *keystring) work->flags|=4; break; } - - if(work->expiretime && work->expiretime<=make_timestamp()) - work->flags|=4; } else if(ascii_strcasecmp("uid",record)==0 && work->desc.mode) { @@ -460,12 +706,14 @@ parse_keyrec(char *keystring) does this for us. */ decoded=utf8_to_native(userid,i,0); + if(strlen(decoded)>opt.screen_columns-10) + decoded[opt.screen_columns-10]='\0'; iobuf_writestr(work->uidbuf,decoded); - xfree (decoded); + xfree(decoded); iobuf_writestr(work->uidbuf,"\n\t"); work->lines++; } - + /* Ignore any records other than "pri" and "uid" for easy future growth. */ @@ -499,7 +747,7 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) if(answer[0]=='q' || answer[0]=='Q') { - xfree (answer); + xfree(answer); return 1; } else if(atoi(answer)>=1 && atoi(answer)<=numdesc) @@ -508,9 +756,10 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) while((num=strsep(&split," ,"))!=NULL) if(atoi(num)>=1 && atoi(num)<=numdesc) - keyserver_work(GET,NULL,&desc[atoi(num)-1],1); + keyserver_work(KS_GET,NULL,&desc[atoi(num)-1],1, + NULL,NULL,opt.keyserver); - xfree (answer); + xfree(answer); return 1; } @@ -519,18 +768,20 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) /* Count and searchstr are just for cosmetics. If the count is too small, it will grow safely. If negative it disables the "Key x-y - of z" messages. */ + of z" messages. searchstr should be UTF-8 (rather than native). */ static void -keyserver_search_prompt(iobuf_t buffer,const char *searchstr) +keyserver_search_prompt(IOBUF buffer,const char *searchstr) { int i=0,validcount=0,started=0,header=0,count=1; - unsigned int maxlen,buflen; + unsigned int maxlen,buflen,numlines=0; KEYDB_SEARCH_DESC *desc; byte *line=NULL; - /* TODO: Something other than 23? That's 24-1 (the prompt). */ - int maxlines=23,numlines=0; + char *localstr=NULL; + + if(searchstr) + localstr=utf8_to_native(searchstr,strlen(searchstr),0); - desc=xmalloc (count*sizeof(KEYDB_SEARCH_DESC)); + desc=xmalloc(count*sizeof(KEYDB_SEARCH_DESC)); for(;;) { @@ -609,7 +860,7 @@ keyserver_search_prompt(iobuf_t buffer,const char *searchstr) for(;;) { - if(show_prompt(desc,i,validcount?count:0,searchstr)) + if(show_prompt(desc,i,validcount?count:0,localstr)) break; validcount=0; } @@ -635,9 +886,10 @@ keyserver_search_prompt(iobuf_t buffer,const char *searchstr) if(!opt.with_colons) { - if(numlines+keyrec->lines>maxlines) + /* screen_lines - 1 for the prompt. */ + if(numlines+keyrec->lines>opt.screen_lines-1) { - if(show_prompt(desc,i,validcount?count:0,searchstr)) + if(show_prompt(desc,i,validcount?count:0,localstr)) break; else numlines=0; @@ -648,62 +900,144 @@ keyserver_search_prompt(iobuf_t buffer,const char *searchstr) numlines+=keyrec->lines; iobuf_close(keyrec->uidbuf); - xfree (keyrec); + xfree(keyrec); started=1; i++; } } - xfree (desc); - xfree (line); - notfound: + /* Leave this commented out or now, and perhaps for a very long + time. All HKPish servers return HTML error messages for + no-key-found. */ + /* + if(!started) + log_info(_("keyserver does not support searching\n")); + else + */ if(count==0) { - if(searchstr) - log_info(_("key \"%s\" not found on keyserver\n"),searchstr); + if(localstr) + log_info(_("key \"%s\" not found on keyserver\n"),localstr); else log_info(_("key not found on keyserver\n")); - return; } + + xfree(localstr); + xfree(desc); + xfree(line); } +/* We sometimes want to use a different gpgkeys_xxx for a given + protocol (for example, ldaps is handled by gpgkeys_ldap). Map + these here. */ +static const char * +keyserver_typemap(const char *type) +{ + if(strcmp(type,"ldaps")==0) + return "ldap"; + else + return type; +} + +#ifdef GPGKEYS_CURL +/* The PGP LDAP and the curl fetch-a-LDAP-object methodologies are + sufficiently different that we can't use curl to do LDAP. */ +static int +curl_cant_handle(const char *scheme,unsigned int direct_uri) +{ + if(!direct_uri && (strcmp(scheme,"ldap")==0 || strcmp(scheme,"ldaps")==0)) + return 1; + + return 0; +} +#endif + #define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" static int -keyserver_spawn(int action,STRLIST list, - KEYDB_SEARCH_DESC *desc,int count,int *prog) +keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc, + int count,int *prog,unsigned char **fpr,size_t *fpr_len, + struct keyserver_spec *keyserver) { int ret=0,i,gotversion=0,outofband=0; STRLIST temp; unsigned int maxlen,buflen; - char *command=NULL,*searchstr=NULL; + char *command,*end,*searchstr=NULL; byte *line=NULL; - struct kopts *kopts; struct exec_info *spawn; + const char *scheme; + const char *libexecdir = get_libexecdir (); + + assert(keyserver); #ifdef EXEC_TEMPFILE_ONLY - opt.keyserver_options.use_temp_files=1; + opt.keyserver_options.options|=KEYSERVER_USE_TEMP_FILES; #endif - /* Push the libexecdir into path. If DISABLE_KEYSERVER_PATH is set, - use the 0 arg to replace the path. */ + /* Build the filename for the helper to execute */ + scheme=keyserver_typemap(keyserver->scheme); + #ifdef DISABLE_KEYSERVER_PATH - set_exec_path(GNUPG_LIBEXECDIR,0); + /* Destroy any path we might have. This is a little tricky, + portability-wise. It's not correct to delete the PATH + environment variable, as that may fall back to a system built-in + PATH. Similarly, it is not correct to set PATH to the null + string (PATH="") since this actually deletes the PATH environment + variable under MinGW. The safest thing to do here is to force + PATH to be GNUPG_LIBEXECDIR. All this is not that meaningful on + Unix-like systems (since we're going to give a full path to + gpgkeys_foo), but on W32 it prevents loading any DLLs from + directories in %PATH%. + + After some more thinking about this we came to the conclusion + that it is better to load the helpers from the directory where + the program of this process lives. Fortunately Windows provides + a way to retrieve this and our get_libexecdir function has been + modified to return just this. Setting the exec-path is not + anymore required. + set_exec_path(libexecdir); + */ #else - set_exec_path(GNUPG_LIBEXECDIR,opt.exec_path_set); + if(opt.exec_path_set) + { + /* If exec-path was set, and DISABLE_KEYSERVER_PATH is + undefined, then don't specify a full path to gpgkeys_foo, so + that the PATH can work. */ + command=xmalloc(GPGKEYS_PREFIX_LEN+strlen(scheme)+3+strlen(EXEEXT)+1); + command[0]='\0'; + } + else #endif + { + /* Specify a full path to gpgkeys_foo. */ + command=xmalloc(strlen(libexecdir)+strlen(DIRSEP_S)+ + GPGKEYS_PREFIX_LEN+strlen(scheme)+3+strlen(EXEEXT)+1); + strcpy(command,libexecdir); + strcat(command,DIRSEP_S); + } - /* Build the filename for the helper to execute */ - command=xmalloc (strlen("gpgkeys_")+strlen(opt.keyserver_scheme)+1); - strcpy(command,"gpgkeys_"); - strcat(command,opt.keyserver_scheme); + end=command+strlen(command); + + strcat(command,GPGKEYS_PREFIX); + strcat(command,scheme); + + if(keyserver->flags.direct_uri) + strcat(command,"uri"); - if(opt.keyserver_options.use_temp_files) + strcat(command,EXEEXT); + +#ifdef GPGKEYS_CURL + if(!curl_cant_handle(scheme,keyserver->flags.direct_uri) + && path_access(command,X_OK)!=0) + strcpy(end,GPGKEYS_CURL); +#endif + + if(opt.keyserver_options.options&KEYSERVER_USE_TEMP_FILES) { - if(opt.keyserver_options.keep_temp_files) + if(opt.keyserver_options.options&KEYSERVER_KEEP_TEMP_FILES) { command=xrealloc(command,strlen(command)+ strlen(KEYSERVER_ARGS_KEEP)+1); @@ -721,41 +1055,47 @@ keyserver_spawn(int action,STRLIST list, else ret=exec_write(&spawn,command,NULL,NULL,0,0); + xfree(command); + if(ret) return ret; - fprintf(spawn->tochild,"# This is a gpg keyserver communications file\n"); + fprintf(spawn->tochild, + "# This is a GnuPG %s keyserver communications file\n",VERSION); fprintf(spawn->tochild,"VERSION %d\n",KEYSERVER_PROTO_VERSION); fprintf(spawn->tochild,"PROGRAM %s\n",VERSION); + fprintf(spawn->tochild,"SCHEME %s\n",keyserver->scheme); - if(opt.keyserver_opaque) - fprintf(spawn->tochild,"OPAQUE %s\n",opt.keyserver_opaque); + if(keyserver->opaque) + fprintf(spawn->tochild,"OPAQUE %s\n",keyserver->opaque); else { - if(opt.keyserver_host) - fprintf(spawn->tochild,"HOST %s\n",opt.keyserver_host); + if(keyserver->auth) + fprintf(spawn->tochild,"AUTH %s\n",keyserver->auth); - if(opt.keyserver_port) - fprintf(spawn->tochild,"PORT %s\n",opt.keyserver_port); - } + if(keyserver->host) + fprintf(spawn->tochild,"HOST %s\n",keyserver->host); - /* Write options */ + if(keyserver->port) + fprintf(spawn->tochild,"PORT %s\n",keyserver->port); - for(i=0,kopts=keyserver_opts;kopts[i].name;i++) - if(*(kopts[i].flag) && kopts[i].tell) - fprintf(spawn->tochild,"OPTION %s\n",kopts[i].name); + if(keyserver->path) + fprintf(spawn->tochild,"PATH %s\n",keyserver->path); + } + + /* Write global options */ - for(i=0;i<opt.keyserver_options.verbose;i++) - fprintf(spawn->tochild,"OPTION verbose\n"); + for(temp=opt.keyserver_options.other;temp;temp=temp->next) + fprintf(spawn->tochild,"OPTION %s\n",temp->d); - temp=opt.keyserver_options.other; + /* Write per-keyserver options */ - for(;temp;temp=temp->next) + for(temp=keyserver->options;temp;temp=temp->next) fprintf(spawn->tochild,"OPTION %s\n",temp->d); switch(action) { - case GET: + case KS_GET: { fprintf(spawn->tochild,"COMMAND GET\n\n"); @@ -763,6 +1103,8 @@ keyserver_spawn(int action,STRLIST list, for(i=0;i<count;i++) { + int quiet=0; + if(desc[i].mode==KEYDB_SEARCH_MODE_FPR20) { int f; @@ -770,7 +1112,7 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"0x"); for(f=0;f<MAX_FINGERPRINT_LEN;f++) - fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]); + fprintf(spawn->tochild,"%02X",desc[i].u.fpr[f]); fprintf(spawn->tochild,"\n"); } @@ -781,7 +1123,7 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"0x"); for(f=0;f<16;f++) - fprintf(spawn->tochild,"%02X",(byte)desc[i].u.fpr[f]); + fprintf(spawn->tochild,"%02X",desc[i].u.fpr[f]); fprintf(spawn->tochild,"\n"); } @@ -789,9 +1131,29 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"0x%08lX%08lX\n", (ulong)desc[i].u.kid[0], (ulong)desc[i].u.kid[1]); - else + else if(desc[i].mode==KEYDB_SEARCH_MODE_SHORT_KID) fprintf(spawn->tochild,"0x%08lX\n", (ulong)desc[i].u.kid[1]); + else if(desc[i].mode==KEYDB_SEARCH_MODE_EXACT) + { + fprintf(spawn->tochild,"0x0000000000000000\n"); + quiet=1; + } + else if(desc[i].mode==KEYDB_SEARCH_MODE_NONE) + continue; + else + BUG(); + + if(!quiet) + { + if(keyserver->host) + log_info(_("requesting key %s from %s server %s\n"), + keystr_from_desc(&desc[i]), + keyserver->scheme,keyserver->host); + else + log_info(_("requesting key %s from %s\n"), + keystr_from_desc(&desc[i]),keyserver->uri); + } } fprintf(spawn->tochild,"\n"); @@ -799,7 +1161,29 @@ keyserver_spawn(int action,STRLIST list, break; } - case SEND: + case KS_GETNAME: + { + STRLIST key; + + fprintf(spawn->tochild,"COMMAND GETNAME\n\n"); + + /* Which names do we want? */ + + for(key=list;key!=NULL;key=key->next) + fprintf(spawn->tochild,"%s\n",key->d); + + fprintf(spawn->tochild,"\n"); + + if(keyserver->host) + log_info(_("searching for names from %s server %s\n"), + keyserver->scheme,keyserver->host); + else + log_info(_("searching for names from %s\n"),keyserver->uri); + + break; + } + + case KS_SEND: { STRLIST key; @@ -809,7 +1193,7 @@ keyserver_spawn(int action,STRLIST list, for(key=list;key!=NULL;key=key->next) { armor_filter_context_t afx; - iobuf_t buffer=iobuf_temp(); + IOBUF buffer=iobuf_temp(); KBNODE block; temp=NULL; @@ -817,11 +1201,17 @@ keyserver_spawn(int action,STRLIST list, memset(&afx,0,sizeof(afx)); afx.what=1; + /* Tell the armor filter to use Unix-style \n line + endings, since we're going to fprintf this to a file + that (on Win32) is open in text mode. The win32 stdio + will transform the \n to \r\n and we'll end up with the + proper line endings on win32. This is a no-op on + Unix. */ + afx.eol[0]='\n'; iobuf_push_filter(buffer,armor_filter,&afx); - /* TODO: Don't use the keyblock hack here - instead, - output each key as a different ascii armored blob with - its own INFO section. */ + /* TODO: Remove Comment: lines from keys exported this + way? */ if(export_pubkeys_stream(buffer,temp,&block, opt.keyserver_options.export_options)==-1) @@ -834,7 +1224,9 @@ keyserver_spawn(int action,STRLIST list, merge_keys_and_selfsig(block); - fprintf(spawn->tochild,"INFO %s BEGIN\n",key->d); + fprintf(spawn->tochild,"INFO %08lX%08lX BEGIN\n", + (ulong)block->pkt->pkt.public_key->keyid[0], + (ulong)block->pkt->pkt.public_key->keyid[1]); for(node=block;node;node=node->next) { @@ -864,9 +1256,8 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"e"); fprintf(spawn->tochild,"\n"); - - break; } + break; case PKT_USER_ID: { @@ -884,7 +1275,8 @@ keyserver_spawn(int action,STRLIST list, { if(uid->name[r]==':' || uid->name[r]=='%' || uid->name[r]&0x80) - fprintf(spawn->tochild,"%%%02X",uid->name[r]); + fprintf(spawn->tochild,"%%%02X", + (byte)uid->name[r]); else fprintf(spawn->tochild,"%c",uid->name[r]); } @@ -899,10 +1291,32 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"\n"); } + break; + + /* This bit is really for the benefit of + people who store their keys in LDAP + servers. It makes it easy to do queries + for things like "all keys signed by + Isabella". */ + case PKT_SIGNATURE: + { + PKT_signature *sig=node->pkt->pkt.signature; + + if(!IS_UID_SIG(sig)) + continue; + + fprintf(spawn->tochild,"sig:%08lX%08lX:%X:%u:%u\n", + (ulong)sig->keyid[0],(ulong)sig->keyid[1], + sig->sig_class,sig->timestamp, + sig->expiredate); + } + break; } } - fprintf(spawn->tochild,"INFO %s END\n",key->d); + fprintf(spawn->tochild,"INFO %08lX%08lX END\n", + (ulong)block->pkt->pkt.public_key->keyid[0], + (ulong)block->pkt->pkt.public_key->keyid[1]); fprintf(spawn->tochild,"KEY %s BEGIN\n",key->d); fwrite(iobuf_get_temp_buffer(buffer), @@ -910,6 +1324,16 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"KEY %s END\n",key->d); iobuf_close(buffer); + + if(keyserver->host) + log_info(_("sending key %s to %s server %s\n"), + keystr(block->pkt->pkt.public_key->keyid), + keyserver->scheme,keyserver->host); + else + log_info(_("sending key %s to %s\n"), + keystr(block->pkt->pkt.public_key->keyid), + keyserver->uri); + release_kbnode(block); } @@ -919,7 +1343,7 @@ keyserver_spawn(int action,STRLIST list, break; } - case SEARCH: + case KS_SEARCH: { STRLIST key; @@ -939,7 +1363,7 @@ keyserver_spawn(int action,STRLIST list, } else { - searchstr=xmalloc (strlen(key->d)+1); + searchstr=xmalloc(strlen(key->d)+1); searchstr[0]='\0'; } @@ -948,6 +1372,13 @@ keyserver_spawn(int action,STRLIST list, fprintf(spawn->tochild,"\n"); + if(keyserver->host) + log_info(_("searching for \"%s\" from %s server %s\n"), + searchstr,keyserver->scheme,keyserver->host); + else + log_info(_("searching for \"%s\" from %s\n"), + searchstr,keyserver->uri); + break; } @@ -971,7 +1402,7 @@ keyserver_spawn(int action,STRLIST list, maxlen=1024; if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) { - ret = iobuf_error (spawn->fromchild); + ret=G10ERR_READ_FILE; goto fail; /* i.e. EOF */ } @@ -1000,8 +1431,8 @@ keyserver_spawn(int action,STRLIST list, else if(ascii_strncasecmp(ptr,"PROGRAM ",8)==0) { if(ascii_strncasecmp(&ptr[8],VERSION,strlen(VERSION))!=0) - log_info(_("WARNING: keyserver handler from a different " - "version of GnuPG (%s)\n"),&ptr[8]); + log_info(_("WARNING: keyserver handler from a different" + " version of GnuPG (%s)\n"),&ptr[8]); } else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0) outofband=1; /* Currently the only OPTION */ @@ -1016,7 +1447,8 @@ keyserver_spawn(int action,STRLIST list, if(!outofband) switch(action) { - case GET: + case KS_GET: + case KS_GETNAME: { void *stats_handle; @@ -1029,7 +1461,7 @@ keyserver_spawn(int action,STRLIST list, way to do this could be to continue parsing this line-by-line and make a temp iobuf for each key. */ - import_keys_stream(spawn->fromchild,stats_handle, + import_keys_stream(spawn->fromchild,stats_handle,fpr,fpr_len, opt.keyserver_options.import_options); import_print_stats(stats_handle); @@ -1039,15 +1471,12 @@ keyserver_spawn(int action,STRLIST list, } /* Nothing to do here */ - case SEND: + case KS_SEND: break; - case SEARCH: - { - keyserver_search_prompt(spawn->fromchild,searchstr); - - break; - } + case KS_SEARCH: + keyserver_search_prompt(spawn->fromchild,searchstr); + break; default: log_fatal(_("no keyserver action!\n")); @@ -1055,7 +1484,9 @@ keyserver_spawn(int action,STRLIST list, } fail: - xfree (line); + xfree(line); + xfree(searchstr); + *prog=exec_finish(spawn); @@ -1063,45 +1494,53 @@ keyserver_spawn(int action,STRLIST list, } static int -keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) +keyserver_work(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc, + int count,unsigned char **fpr,size_t *fpr_len, + struct keyserver_spec *keyserver) { int rc=0,ret=0; - if(opt.keyserver_scheme==NULL) + if(!keyserver) { log_error(_("no keyserver known (use option --keyserver)\n")); - return GPG_ERR_BAD_URI; + return G10ERR_BAD_URI; } #ifdef DISABLE_KEYSERVER_HELPERS log_error(_("external keyserver calls are not supported in this build\n")); - return GPG_ERR_KEYSERVER; + return G10ERR_KEYSERVER; #else /* Spawn a handler */ - rc=keyserver_spawn(action,list,desc,count,&ret); + rc=keyserver_spawn(action,list,desc,count,&ret,fpr,fpr_len,keyserver); if(ret) { switch(ret) { case KEYSERVER_SCHEME_NOT_FOUND: - log_error(_("no handler for keyserver scheme \"%s\"\n"), - opt.keyserver_scheme); + log_error(_("no handler for keyserver scheme `%s'\n"), + keyserver->scheme); break; case KEYSERVER_NOT_SUPPORTED: - log_error(_("action \"%s\" not supported with keyserver " - "scheme \"%s\"\n"), - action==GET?"get":action==SEND?"send": - action==SEARCH?"search":"unknown", - opt.keyserver_scheme); + log_error(_("action `%s' not supported with keyserver " + "scheme `%s'\n"), + action==KS_GET?"get":action==KS_SEND?"send": + action==KS_SEARCH?"search":"unknown", + keyserver->scheme); break; case KEYSERVER_VERSION_ERROR: - log_error(_("gpgkeys_%s does not support handler version %d\n"), - opt.keyserver_scheme,KEYSERVER_PROTO_VERSION); + log_error(_(GPGKEYS_PREFIX "%s does not support" + " handler version %d\n"), + keyserver_typemap(keyserver->scheme), + KEYSERVER_PROTO_VERSION); + break; + + case KEYSERVER_TIMEOUT: + log_error(_("keyserver timed out\n")); break; case KEYSERVER_INTERNAL_ERROR: @@ -1110,12 +1549,12 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) break; } - return GPG_ERR_KEYSERVER; + return G10ERR_KEYSERVER; } if(rc) { - log_error(_("keyserver communications error: %s\n"),gpg_strerror (rc)); + log_error(_("keyserver communications error: %s\n"),g10_errstr(rc)); return rc; } @@ -1127,18 +1566,33 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count) int keyserver_export(STRLIST users) { - /* We better ask for confirmation when the user entered --send-keys - without arguments. Sending all keys might not be the thing he - intended to do */ - if (users || opt.batch || opt.answer_yes) - ; - else if ( !cpr_get_answer_is_yes - ("keyserver_export.send_all", - _("Do you really want to send all your " - "public keys to the keyserver? (y/N) "))) - return -1; + STRLIST sl=NULL; + KEYDB_SEARCH_DESC desc; + int rc=0; + + /* Weed out descriptors that we don't support sending */ + for(;users;users=users->next) + { + classify_user_id (users->d, &desc); + if(desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID && + desc.mode!=KEYDB_SEARCH_MODE_LONG_KID && + desc.mode!=KEYDB_SEARCH_MODE_FPR16 && + desc.mode!=KEYDB_SEARCH_MODE_FPR20) + { + log_error(_("\"%s\" not a key ID: skipping\n"),users->d); + continue; + } + else + append_to_strlist(&sl,users->d); + } + + if(sl) + { + rc=keyserver_work(KS_SEND,sl,NULL,0,NULL,NULL,opt.keyserver); + free_strlist(sl); + } - return keyserver_work(SEND,users,NULL,0); + return rc; } int @@ -1149,7 +1603,7 @@ keyserver_import(STRLIST users) int rc=0; /* Build a list of key ids */ - desc=xmalloc (sizeof(KEYDB_SEARCH_DESC)*num); + desc=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num); for(;users;users=users->next) { @@ -1159,7 +1613,7 @@ keyserver_import(STRLIST users) desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 && desc[count].mode!=KEYDB_SEARCH_MODE_FPR20) { - log_error(_("skipping invalid key ID \"%s\"\n"),users->d); + log_error(_("\"%s\" not a key ID: skipping\n"),users->d); continue; } @@ -1172,15 +1626,16 @@ keyserver_import(STRLIST users) } if(count>0) - rc=keyserver_work(GET,NULL,desc,count); + rc=keyserver_work(KS_GET,NULL,desc,count,NULL,NULL,opt.keyserver); - xfree (desc); + xfree(desc); return rc; } int -keyserver_import_fprint(const byte *fprint,size_t fprint_len) +keyserver_import_fprint(const byte *fprint,size_t fprint_len, + struct keyserver_spec *keyserver) { KEYDB_SEARCH_DESC desc; @@ -1195,11 +1650,13 @@ keyserver_import_fprint(const byte *fprint,size_t fprint_len) memcpy(desc.u.fpr,fprint,fprint_len); - return keyserver_work(GET,NULL,&desc,1); + /* TODO: Warn here if the fingerprint we got doesn't match the one + we asked for? */ + return keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,keyserver); } int -keyserver_import_keyid(u32 *keyid) +keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver) { KEYDB_SEARCH_DESC desc; @@ -1209,7 +1666,7 @@ keyserver_import_keyid(u32 *keyid) desc.u.kid[0]=keyid[0]; desc.u.kid[1]=keyid[1]; - return keyserver_work(GET,NULL,&desc,1); + return keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,keyserver); } /* code mostly stolen from do_export_stream */ @@ -1224,14 +1681,14 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) *count=0; - *klist=xmalloc (sizeof(KEYDB_SEARCH_DESC)*num); + *klist=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num); kdbhd=keydb_new(0); if(!users) { ndesc = 1; - desc = xcalloc (1, ndesc * sizeof *desc); + desc = xmalloc_clear ( ndesc * sizeof *desc); desc[0].mode = KEYDB_SEARCH_MODE_FIRST; } else @@ -1245,8 +1702,8 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) 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)); + log_error (_("key \"%s\" not found: %s\n"), + sl->d, g10_errstr (G10ERR_INV_USER_ID)); } } @@ -1259,7 +1716,7 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); goto leave; } @@ -1276,8 +1733,8 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) node->pkt->pkt.public_key->version>=4) { (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - v3_keyid (node->pkt->pkt.public_key->pkey[0], - (*klist)[*count].u.kid); + mpi_get_keyid(node->pkt->pkt.public_key->pkey[0], + (*klist)[*count].u.kid); (*count)++; if(*count==num) @@ -1288,7 +1745,7 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) } /* v4 keys get full fingerprints. v3 keys get long keyids. - This is because it's easy to calculate any sort of key id + This is because it's easy to calculate any sort of keyid from a v4 fingerprint, but not a v3 fingerprint. */ if(node->pkt->pkt.public_key->version<4) @@ -1306,6 +1763,43 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) (*klist)[*count].u.fpr,&dummy); } + /* This is a little hackish, using the skipfncvalue as a + void* pointer to the keyserver spec, but we don't need + the skipfnc here, and it saves having an additional field + for this (which would be wasted space most of the + time). */ + + (*klist)[*count].skipfncvalue=NULL; + + /* Are we honoring preferred keyservers? */ + if(opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) + { + PKT_user_id *uid=NULL; + PKT_signature *sig=NULL; + + merge_keys_and_selfsig(keyblock); + + for(node=node->next;node;node=node->next) + { + if(node->pkt->pkttype==PKT_USER_ID + && node->pkt->pkt.user_id->is_primary) + uid=node->pkt->pkt.user_id; + else if(node->pkt->pkttype==PKT_SIGNATURE + && node->pkt->pkt.signature-> + flags.chosen_selfsig && uid) + { + sig=node->pkt->pkt.signature; + break; + } + } + + /* Try and parse the keyserver URL. If it doesn't work, + then we end up writing NULL which indicates we are + the same as any other key. */ + if(sig) + (*klist)[*count].skipfncvalue=parse_preferred_keyserver(sig); + } + (*count)++; if(*count==num) @@ -1320,7 +1814,9 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) rc=0; leave: - xfree (desc); + if(rc) + xfree(*klist); + xfree(desc); keydb_release(kdbhd); release_kbnode(keyblock); @@ -1330,43 +1826,91 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) /* Note this is different than the original HKP refresh. It allows usernames to refresh only part of the keyring. */ -int +int keyserver_refresh(STRLIST users) { - int rc,count,fakev3=0; + int rc,count,numdesc,fakev3=0; KEYDB_SEARCH_DESC *desc; + unsigned int options=opt.keyserver_options.import_options; - /* We switch merge_only on during a refresh, as 'refresh' should - never import new keys, even if their keyids match. Is it worth - preserving the old merge_only value here? */ - opt.merge_only=1; + /* We switch merge-only on during a refresh, as 'refresh' should + never import new keys, even if their keyids match. */ + opt.keyserver_options.import_options|=IMPORT_MERGE_ONLY; + + /* Similarly, we switch on fast-import, since refresh may make + multiple import sets (due to preferred keyserver URLs). We don't + want each set to rebuild the trustdb. Instead we do it once at + the end here. */ + opt.keyserver_options.import_options|=IMPORT_FAST; /* If refresh_add_fake_v3_keyids is on and it's a HKP or MAILTO scheme, then enable fake v3 keyid generation. */ - if(opt.keyserver_options.fake_v3_keyids && opt.keyserver_scheme && - (ascii_strcasecmp(opt.keyserver_scheme,"hkp")==0 || - ascii_strcasecmp(opt.keyserver_scheme,"mailto")==0)) + if((opt.keyserver_options.options&KEYSERVER_ADD_FAKE_V3) && opt.keyserver + && (ascii_strcasecmp(opt.keyserver->scheme,"hkp")==0 || + ascii_strcasecmp(opt.keyserver->scheme,"mailto")==0)) fakev3=1; - rc=keyidlist(users,&desc,&count,fakev3); + rc=keyidlist(users,&desc,&numdesc,fakev3); if(rc) return rc; + count=numdesc; if(count>0) { - if(opt.keyserver_uri) + int i; + + /* Try to handle preferred keyserver keys first */ + for(i=0;i<numdesc;i++) + { + if(desc[i].skipfncvalue) + { + struct keyserver_spec *keyserver=desc[i].skipfncvalue; + + /* We use the keyserver structure we parsed out before. + Note that a preferred keyserver without a scheme:// + will be interpreted as hkp:// */ + + rc=keyserver_work(KS_GET,NULL,&desc[i],1,NULL,NULL,keyserver); + if(rc) + log_info(_("WARNING: unable to refresh key %s" + " via %s: %s\n"),keystr_from_desc(&desc[i]), + keyserver->uri,g10_errstr(rc)); + else + { + /* We got it, so mark it as NONE so we don't try and + get it again from the regular keyserver. */ + + desc[i].mode=KEYDB_SEARCH_MODE_NONE; + count--; + } + + free_keyserver_spec(keyserver); + } + } + } + + if(count>0) + { + if(opt.keyserver) { if(count==1) - log_info(_("refreshing 1 key from %s\n"),opt.keyserver_uri); + log_info(_("refreshing 1 key from %s\n"),opt.keyserver->uri); else log_info(_("refreshing %d keys from %s\n"), - count,opt.keyserver_uri); + count,opt.keyserver->uri); } - rc=keyserver_work(GET,NULL,desc,count); + rc=keyserver_work(KS_GET,NULL,desc,numdesc,NULL,NULL,opt.keyserver); } - xfree (desc); + xfree(desc); + + opt.keyserver_options.import_options=options; + + /* If the original options didn't have fast import, and the trustdb + is dirty, rebuild. */ + if(!(opt.keyserver_options.import_options&IMPORT_FAST)) + trustdb_check_or_update(); return rc; } @@ -1375,7 +1919,217 @@ int keyserver_search(STRLIST tokens) { if(tokens) - return keyserver_work(SEARCH,tokens,NULL,0); + return keyserver_work(KS_SEARCH,tokens,NULL,0,NULL,NULL,opt.keyserver); else return 0; } + +int +keyserver_fetch(STRLIST urilist) +{ + KEYDB_SEARCH_DESC desc; + STRLIST sl; + unsigned int options=opt.keyserver_options.import_options; + + /* Switch on fast-import, since fetch can handle more than one + import and we don't want each set to rebuild the trustdb. + Instead we do it once at the end. */ + opt.keyserver_options.import_options|=IMPORT_FAST; + + /* A dummy desc since we're not actually fetching a particular key + ID */ + memset(&desc,0,sizeof(desc)); + desc.mode=KEYDB_SEARCH_MODE_EXACT; + + for(sl=urilist;sl;sl=sl->next) + { + struct keyserver_spec *spec; + + spec=parse_keyserver_uri(sl->d,1,NULL,0); + if(spec) + { + int rc; + + /* + Set the direct_uri flag so we know later to call a direct + handler instead of the keyserver style. This lets us use + gpgkeys_curl or gpgkeys_ldapuri instead of gpgkeys_ldap to + fetch things like + ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560 + */ + spec->flags.direct_uri=1; + + rc=keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,spec); + if(rc) + log_info (_("WARNING: unable to fetch URI %s: %s\n"), + sl->d,g10_errstr(rc)); + + free_keyserver_spec(spec); + } + else + log_info (_("WARNING: unable to parse URI %s\n"),sl->d); + } + + opt.keyserver_options.import_options=options; + + /* If the original options didn't have fast import, and the trustdb + is dirty, rebuild. */ + if(!(opt.keyserver_options.import_options&IMPORT_FAST)) + trustdb_check_or_update(); + + return 0; +} + +/* Import key in a CERT or pointed to by a CERT */ +int +keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len) +{ + char *domain,*look,*url; + IOBUF key; + int type,rc=G10ERR_GENERAL; + + look=xstrdup(name); + + domain=strrchr(look,'@'); + if(domain) + *domain='.'; + + type=get_cert(look,max_cert_size,&key,fpr,fpr_len,&url); + if(type==1) + { + int armor_status=opt.no_armor; + + /* CERTs are always in binary format */ + opt.no_armor=1; + + rc=import_keys_stream(key,NULL,fpr,fpr_len, + opt.keyserver_options.import_options); + + opt.no_armor=armor_status; + + iobuf_close(key); + } + else if(type==2 && *fpr) + { + /* We only consider the IPGP type if a fingerprint was provided. + This lets us select the right key regardless of what a URL + points to, or get the key from a keyserver. */ + if(url) + { + struct keyserver_spec *spec; + + spec=parse_keyserver_uri(url,1,NULL,0); + if(spec) + { + STRLIST list=NULL; + + add_to_strlist(&list,url); + + rc=keyserver_fetch(list); + + free_strlist(list); + free_keyserver_spec(spec); + } + } + else if(opt.keyserver) + { + /* If only a fingerprint is provided, try and fetch it from + our --keyserver */ + + rc=keyserver_import_fprint(*fpr,*fpr_len,opt.keyserver); + } + + xfree(url); + } + + xfree(look); + + return rc; +} + +/* Import key pointed to by a PKA record. Return the requested + fingerprint in fpr. */ +int +keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len) +{ + char *uri; + int rc=-1; + + *fpr=xmalloc(20); + *fpr_len=20; + + uri = get_pka_info (name, *fpr); + if (uri) + { + struct keyserver_spec *spec; + spec = parse_keyserver_uri (uri, 1, NULL, 0); + if (spec) + { + rc=keyserver_import_fprint (*fpr, 20, spec); + free_keyserver_spec (spec); + } + xfree (uri); + } + + if(rc!=0) + xfree(*fpr); + + return rc; +} + +/* Import all keys that match name */ +int +keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len, + struct keyserver_spec *keyserver) +{ + STRLIST list=NULL; + int rc; + + append_to_strlist(&list,name); + + rc=keyserver_work(KS_GETNAME,list,NULL,0,fpr,fpr_len,keyserver); + + free_strlist(list); + + return rc; +} + +/* Use the PGP Universal trick of asking ldap://keys.(maildomain) for + the key. */ +int +keyserver_import_ldap(const char *name,unsigned char **fpr,size_t *fpr_len) +{ + char *domain; + struct keyserver_spec *keyserver; + STRLIST list=NULL; + int rc; + + append_to_strlist(&list,name); + + /* Parse out the domain */ + domain=strrchr(name,'@'); + if(!domain) + return G10ERR_GENERAL; + + domain++; + + keyserver=xmalloc_clear(sizeof(struct keyserver_spec)); + + keyserver->scheme=xstrdup("ldap"); + keyserver->host=xmalloc(5+strlen(domain)+1); + strcpy(keyserver->host,"keys."); + strcat(keyserver->host,domain); + keyserver->uri=xmalloc(strlen(keyserver->scheme)+ + 3+strlen(keyserver->host)+1); + strcpy(keyserver->uri,keyserver->scheme); + strcat(keyserver->uri,"://"); + strcat(keyserver->uri,keyserver->host); + + rc=keyserver_work(KS_GETNAME,list,NULL,0,fpr,fpr_len,keyserver); + + free_strlist(list); + + free_keyserver_spec(keyserver); + + return rc; +} diff --git a/g10/main.h b/g10/main.h index 939d12ded..fd306a467 100644 --- a/g10/main.h +++ b/g10/main.h @@ -1,5 +1,6 @@ /* main.h - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,28 +16,36 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_MAIN_H #define G10_MAIN_H + #include "types.h" -#include "gpg.h" #include "../common/iobuf.h" -#include "mpi.h" #include "cipher.h" #include "keydb.h" /* It could be argued that the default cipher should be 3DES rather than CAST5, and the default compression should be 0 - (i.e. uncompressed) rather than 1 (zip). */ -#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5 -#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1 -#define DEFAULT_COMPRESS_ALGO 1 - -typedef struct { - int header_okay; - PK_LIST pk_list; - cipher_filter_context_t cfx; + (i.e. uncompressed) rather than 1 (zip). However, the real world + issues of speed and size come into play here. */ + +#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_CAST5 +#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_SHA1 +#define DEFAULT_COMPRESS_ALGO COMPRESS_ALGO_ZIP +#define DEFAULT_S2K_DIGEST_ALGO DIGEST_ALGO_SHA1 + +#define S2K_DIGEST_ALGO (opt.s2k_digest_algo?opt.s2k_digest_algo:DEFAULT_S2K_DIGEST_ALGO) + +typedef struct +{ + int header_okay; + PK_LIST pk_list; + DEK *symkey_dek; + STRING2KEY *symkey_s2k; + cipher_filter_context_t cfx; } encrypt_filter_context_t; struct groupitem @@ -46,7 +55,7 @@ struct groupitem struct groupitem *next; }; -/*-- g10.c --*/ +/*-- gpg.c --*/ extern int g10_errors_seen; #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) @@ -64,18 +73,19 @@ char *make_radix64_string( const byte *data, size_t len ); /*-- misc.c --*/ void trap_unaligned(void); int disable_core_dumps(void); +void register_secured_file (const char *fname); +void unregister_secured_file (const char *fname); +int is_secured_file (int fd); +int is_secured_filename (const char *fname); u16 checksum_u16( unsigned n ); u16 checksum( byte *p, unsigned n ); u16 checksum_mpi( gcry_mpi_t a ); u32 buffer_to_u32( const byte *buffer ); const byte *get_session_marker( size_t *rlen ); int openpgp_cipher_test_algo( int algo ); -int openpgp_pk_test_algo( int algo, unsigned int usage_flags ); +int openpgp_pk_test_algo( int algo ); int openpgp_pk_algo_usage ( int algo ); int openpgp_md_test_algo( int algo ); -int openpgp_md_map_name (const char *string); -int openpgp_cipher_map_name (const char *string); -int openpgp_pk_map_name (const char *string); #ifdef USE_IDEA void idea_cipher_warn( int show ); @@ -91,9 +101,10 @@ struct expando_args }; char *pct_expando(const char *string,struct expando_args *args); -int hextobyte( const char *s ); void deprecated_warning(const char *configname,unsigned int configlineno, const char *option,const char *repl1,const char *repl2); +void deprecated_command (const char *name); + const char *compress_algo_to_string(int algo); int string_to_compress_algo(const char *string); int check_compress_algo(int algo); @@ -106,10 +117,19 @@ struct parse_options { char *name; unsigned int bit; + char **value; + char *help; }; -int parse_options(char *str,unsigned int *options,struct parse_options *opts); - +char *optsep(char **stringp); +char *argsplit(char *string); +int parse_options(char *str,unsigned int *options, + struct parse_options *opts,int noisy); +char *unescape_percent_string (const unsigned char *s); +int has_invalid_email_chars (const char *s); +int is_valid_mailbox (const char *name); +const char *get_libexecdir (void); +int path_access(const char *file,int mode); /* Temporary helpers. */ int pubkey_get_npkey( int algo ); @@ -117,31 +137,24 @@ int pubkey_get_nskey( int algo ); int pubkey_get_nsig( int algo ); int pubkey_get_nenc( int algo ); unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey ); - -/* MPI helpers. */ -int mpi_write( iobuf_t out, gcry_mpi_t a ); -int mpi_write_opaque( iobuf_t out, gcry_mpi_t a ); -gcry_mpi_t mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure ); -gcry_mpi_t mpi_read_opaque(iobuf_t inp, unsigned int *ret_nread ); int mpi_print( FILE *fp, gcry_mpi_t a, int mode ); - - /*-- helptext.c --*/ void display_online_help( const char *keyword ); /*-- encode.c --*/ +int setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek); int encode_symmetric( const char *filename ); int encode_store( const char *filename ); -int encode_crypt( const char *filename, STRLIST remusr ); +int encode_crypt( const char *filename, STRLIST remusr, int use_symkey ); void encode_crypt_files(int nfiles, char **files, STRLIST remusr); int encrypt_filter( void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len); /*-- sign.c --*/ -int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ); +int complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md ); int sign_file( STRLIST filenames, int detached, STRLIST locusr, int do_encrypt, STRLIST remusr, const char *outfile ); int clearsign_file( const char *fname, STRLIST locusr, const char *outfile ); @@ -149,31 +162,43 @@ int sign_symencrypt_file (const char *fname, STRLIST locusr); /*-- sig-check.c --*/ int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig); +int check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk, + PKT_signature *backsig); int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ); int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, - PKT_public_key *ret_pk, int *is_selfsig, - u32 *r_expiredate, int *r_expired ); + PKT_public_key *ret_pk, int *is_selfsig, + u32 *r_expiredate, int *r_expired ); /*-- delkey.c --*/ int delete_keys( STRLIST names, int secret, int allow_both ); /*-- keyedit.c --*/ -void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds, - int sign_mode ); +void keyedit_menu( const char *username, STRLIST locusr, + STRLIST commands, int quiet, int seckey_check ); void show_basic_key_info (KBNODE keyblock); /*-- keygen.c --*/ -u32 ask_expire_interval(int object); +u32 parse_expire_string(const char *string); +u32 ask_expire_interval(int object,const char *def_expire); u32 ask_expiredate(void); -void generate_keypair( const char *fname, const char *card_serialno ); +void generate_keypair( const char *fname, const char *card_serialno, + const char *backup_encryption_dir ); int keygen_set_std_prefs (const char *string,int personal); PKT_user_id *keygen_get_std_prefs (void); int keygen_add_key_expire( PKT_signature *sig, void *opaque ); int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); int keygen_add_keyserver_url(PKT_signature *sig, void *opaque); +int keygen_add_notations(PKT_signature *sig,void *opaque); int keygen_add_revkey(PKT_signature *sig, void *opaque); +int make_backsig(PKT_signature *sig,PKT_public_key *pk, + PKT_public_key *sub_pk,PKT_secret_key *sub_sk); int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); +#ifdef ENABLE_CARD_SUPPORT +int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, + int keyno, const char *serialno); +int save_unprotected_key_to_card (PKT_secret_key *sk, int keyno); +#endif /*-- openfile.c --*/ int overwrite_filep( const char *fname ); @@ -185,29 +210,29 @@ void try_make_homedir( const char *fname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); -gcry_mpi_t encode_session_key( DEK *dek, unsigned int nbits); -gcry_mpi_t encode_md_value( int pubkey_algo, MD_HANDLE md, - int hash_algo, unsigned nbits, int v3compathack ); - -/*-- comment.c --*/ -KBNODE make_comment_node_from_buffer (const char *s, size_t n); -KBNODE make_comment_node( const char *s ); -KBNODE make_mpi_comment_node( const char *s, gcry_mpi_t a ); +gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits ); +gcry_mpi_t encode_md_value( PKT_public_key *pk, PKT_secret_key *sk, + gcry_md_hd_t md, int hash_algo ); /*-- import.c --*/ -int parse_import_options(char *str,unsigned int *options); +int parse_import_options(char *str,unsigned int *options,int noisy); void import_keys( char **fnames, int nnames, void *stats_hd, unsigned int options ); -int import_keys_stream( iobuf_t inp, - void *stats_hd, unsigned int options ); +int import_keys_stream( iobuf_t inp,void *stats_hd,unsigned char **fpr, + size_t *fpr_len,unsigned int options ); void *import_new_stats_handle (void); void import_release_stats_handle (void *p); void import_print_stats (void *hd); int collapse_uids( KBNODE *keyblock ); +int auto_create_card_key_stub ( const char *serialnostr, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3); + /*-- export.c --*/ -int parse_export_options(char *str,unsigned int *options); +int parse_export_options(char *str,unsigned int *options,int noisy); int export_pubkeys( STRLIST users, unsigned int options ); int export_pubkeys_stream( iobuf_t out, STRLIST users, KBNODE *keyblock_out, unsigned int options ); @@ -221,7 +246,7 @@ int enarmor_file( const char *fname ); /*-- revoke.c --*/ struct revocation_reason_info; int gen_revoke( const char *uname ); -int gen_desig_revoke( const char *uname ); +int gen_desig_revoke( const char *uname, STRLIST locusr); int revocation_reason_build_cb( PKT_signature *sig, void *opaque ); struct revocation_reason_info * ask_revocation_reason( int key_rev, int cert_rev, int hint ); @@ -230,17 +255,20 @@ void release_revocation_reason_info( struct revocation_reason_info *reason ); /*-- keylist.c --*/ void public_key_list( STRLIST list ); void secret_key_list( STRLIST list ); +void print_subpackets_colon(PKT_signature *sig); void reorder_keyblock (KBNODE keyblock); void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); +void print_revokers(PKT_public_key *pk); void show_policy_url(PKT_signature *sig,int indent,int mode); void show_keyserver_url(PKT_signature *sig,int indent,int mode); -void show_notation(PKT_signature *sig,int indent,int mode); +void show_notation(PKT_signature *sig,int indent,int mode,int which); void dump_attribs(const PKT_user_id *uid, PKT_public_key *pk,PKT_secret_key *sk); void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); void print_pubkey_info (FILE *fp, PKT_public_key *pk); +void print_card_key_info (FILE *fp, KBNODE keyblock); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); @@ -249,24 +277,26 @@ int verify_files( int nfiles, char **files ); /*-- decrypt.c --*/ int decrypt_message( const char *filename ); -void decrypt_messages(int nfiles, char **files); +void decrypt_messages(int nfiles, char *files[]); /*-- plaintext.c --*/ -int hash_datafiles( MD_HANDLE md, MD_HANDLE md2, +int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files, const char *sigfilename, int textmode ); -/*-- pipemode.c --*/ -void run_in_pipemode (void); - -/*-- card-util.c --*/ -void change_pin (int no, int allow_admin); -void card_status (FILE *fp, char *serialnobuf, size_t serialnobuflen); -void card_edit (STRLIST commands); - /*-- signal.c --*/ void init_signals(void); void pause_on_sigusr( int which ); void block_all_signals(void); void unblock_all_signals(void); + +#ifdef ENABLE_CARD_SUPPORT +/*-- card-util.c --*/ +void change_pin (int no, int allow_admin); +void card_status (FILE *fp, char *serialno, size_t serialnobuflen); +void card_edit (STRLIST commands); +int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock); +int card_store_subkey (KBNODE node, int use); +#endif + #endif /*G10_MAIN_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c index 40b9bd20a..22711cf59 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1,5 +1,6 @@ /* mainproc.c - handle packets - * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,9 +27,9 @@ #include <assert.h> #include <time.h> +#include "gpg.h" #include "packet.h" #include "iobuf.h" -#include "memory.h" #include "options.h" #include "util.h" #include "cipher.h" @@ -49,37 +51,34 @@ struct kidlist_item { }; - /**************** * Structure to hold the context */ typedef struct mainproc_context *CTX; -struct mainproc_context { - struct mainproc_context *anchor; /* may be useful in the future */ - PKT_public_key *last_pubkey; - PKT_secret_key *last_seckey; - PKT_user_id *last_user_id; - md_filter_context_t mfx; - int sigs_only; /* process only signatures and reject all other stuff */ - int encrypt_only; /* process only encrytion messages */ - STRLIST signed_data; - const char *sigfilename; - DEK *dek; - int last_was_session_key; - KBNODE list; /* the current list of packets */ - int have_data; - iobuf_t iobuf; /* used to get the filename etc. */ - int trustletter; /* temp usage in list_node */ - ulong local_id; /* ditto */ - struct kidlist_item *pkenc_list; /* list of encryption packets */ - struct { - int op; - int stop_now; - } pipemode; +struct mainproc_context +{ + struct mainproc_context *anchor; /* May be useful in the future. */ + PKT_public_key *last_pubkey; + PKT_secret_key *last_seckey; + PKT_user_id *last_user_id; + md_filter_context_t mfx; + int sigs_only; /* Process only signatures and reject all other stuff. */ + int encrypt_only; /* Process only encryption messages. */ + STRLIST signed_data; + const char *sigfilename; + DEK *dek; + int last_was_session_key; + KBNODE list; /* The current list of packets. */ + int have_data; + IOBUF iobuf; /* Used to get the filename etc. */ + int trustletter; /* Temporary usage in list_node. */ + ulong symkeys; + struct kidlist_item *pkenc_list; /* List of encryption packets. */ + int any_sig_seen; /* Set to true if a signature packet has been seen. */ }; -static int do_proc_packets( CTX c, iobuf_t a ); +static int do_proc_packets( CTX c, IOBUF a ); static void list_node( CTX c, KBNODE node ); static void proc_tree( CTX c, KBNODE node ); @@ -94,43 +93,28 @@ release_list( CTX c ) release_kbnode( c->list ); while( c->pkenc_list ) { struct kidlist_item *tmp = c->pkenc_list->next; - xfree ( c->pkenc_list ); + xfree( c->pkenc_list ); c->pkenc_list = tmp; } c->pkenc_list = NULL; c->list = NULL; c->have_data = 0; c->last_was_session_key = 0; - c->pipemode.op = 0; - c->pipemode.stop_now = 0; - xfree (c->dek); c->dek = NULL; + xfree(c->dek); c->dek = NULL; } static int add_onepass_sig( CTX c, PACKET *pkt ) { - KBNODE node; + KBNODE node; - if( c->list ) { /* add another packet */ - /* We can only append another onepass packet if the list - * does contain only onepass packets */ - for( node=c->list; node && node->pkt->pkttype == PKT_ONEPASS_SIG; - node = node->next ) - ; - if( node ) { - /* this is not the case, so we flush the current thing and - * allow this packet to start a new verification thing */ - release_list( c ); - c->list = new_kbnode( pkt ); - } - else - add_kbnode( c->list, new_kbnode( pkt )); - } - else /* insert the first one */ - c->list = node = new_kbnode( pkt ); + if ( c->list ) /* add another packet */ + add_kbnode( c->list, new_kbnode( pkt )); + else /* insert the first one */ + c->list = node = new_kbnode( pkt ); - return 1; + return 1; } @@ -142,30 +126,6 @@ add_gpg_control( CTX c, PACKET *pkt ) * Process the last one and reset everything */ release_list(c); } - else if ( pkt->pkt.gpg_control->control == CTRLPKT_PIPEMODE ) { - /* Pipemode control packet */ - if ( pkt->pkt.gpg_control->datalen < 2 ) - log_fatal ("invalid pipemode control packet length\n"); - if (pkt->pkt.gpg_control->data[0] == 1) { - /* start the whole thing */ - assert ( !c->list ); /* we should be in a pretty virgin state */ - assert ( !c->pipemode.op ); - c->pipemode.op = pkt->pkt.gpg_control->data[1]; - } - else if (pkt->pkt.gpg_control->data[0] == 2) { - /* the signed material follows in a plaintext packet */ - assert ( c->pipemode.op == 'B' ); - } - else if (pkt->pkt.gpg_control->data[0] == 3) { - assert ( c->pipemode.op == 'B' ); - release_list (c); - /* and tell the outer loop to terminate */ - c->pipemode.stop_now = 1; - } - else - log_fatal ("invalid pipemode control packet code\n"); - return 0; /* no need to store the packet */ - } if( c->list ) /* add another packet */ add_kbnode( c->list, new_kbnode( pkt )); @@ -216,6 +176,7 @@ add_signature( CTX c, PACKET *pkt ) { KBNODE node; + c->any_sig_seen = 1; if( pkt->pkttype == PKT_SIGNATURE && !c->list ) { /* This is the first signature for the following datafile. * GPG does not write such packets; instead it always uses @@ -238,43 +199,47 @@ add_signature( CTX c, PACKET *pkt ) return 1; } -static void -symkey_decrypt_sesskey (DEK * dek, byte *sesskey, size_t slen) +static int +symkey_decrypt_seskey( DEK *dek, byte *seskey, size_t slen ) { - CIPHER_HANDLE hd; - int n; + gcry_cipher_hd_t hd; - if (slen < 17 || slen > 33) + if(slen < 17 || slen > 33) { log_error ( _("weird size for an encrypted session key (%d)\n"), - (int)slen); - return; + (int)slen); + return G10ERR_BAD_KEY; } - /* we checked the DEK values before, so consider all errors 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_decrypt (hd, sesskey, slen, NULL, 0); - gcry_cipher_close (hd); - /* check first byte (the cipher algo) */ - if (openpgp_cipher_test_algo (sesskey[0])) - { - log_error (_("invalid symkey algorithm detected (%d)\n"), - sesskey[0]); - return; - } - n = gcry_cipher_get_algo_keylen (sesskey[0]); - if (n > DIM(dek->key)) + BUG (); + if (gcry_cipher_setkey ( hd, dek->key, dek->keylen )) BUG (); - /* now we replace the dek components with the real session key - to decrypt the contents of the sequencing packet. */ - dek->keylen = n; - dek->algo = sesskey[0]; - memcpy (dek->key, sesskey + 1, dek->keylen); - /*log_hexdump ("thekey", dek->key, dek->keylen);*/ -} + gcry_cipher_setiv ( hd, NULL, 0 ); + gcry_cipher_decrypt ( hd, seskey, slen, NULL, 0 ); + gcry_cipher_close ( hd ); + + /* Now we replace the dek components with the real session key to + decrypt the contents of the sequencing packet. */ + + dek->keylen=slen-1; + dek->algo=seskey[0]; + + if(dek->keylen > DIM(dek->key)) + BUG (); + + /* This is not completely accurate, since a bad passphrase may have + resulted in a garbage algorithm byte, but it's close enough since + a bogus byte here will fail later. */ + if(dek->algo==CIPHER_ALGO_IDEA) + idea_cipher_warn(0); + + memcpy(dek->key, seskey + 1, dek->keylen); + + /*log_hexdump( "thekey", dek->key, dek->keylen );*/ + + return 0; +} static void proc_symkey_enc( CTX c, PACKET *pkt ) @@ -284,26 +249,91 @@ proc_symkey_enc( CTX c, PACKET *pkt ) enc = pkt->pkt.symkey_enc; if (!enc) log_error ("invalid symkey encrypted packet\n"); - else { + else if(!c->dek) + { int algo = enc->cipher_algo; - const char *s; + const char *s = gcry_cipher_algo_name (algo); - s = gcry_cipher_algo_name (algo); - if (s && *s) - log_info(_("%s encrypted data\n"), s ); + if(s) + { + if(!opt.quiet) + { + if(enc->seskeylen) + log_info(_("%s encrypted session key\n"), s ); + else + log_info(_("%s encrypted data\n"), s ); + } + } else - log_info(_("encrypted with unknown algorithm %d\n"), algo ); + log_error(_("encrypted with unknown algorithm %d\n"), algo ); + + if(openpgp_md_test_algo (enc->s2k.hash_algo)) + { + log_error(_("passphrase generated with unknown digest" + " algorithm %d\n"),enc->s2k.hash_algo); + s=NULL; + } c->last_was_session_key = 2; - if ( opt.list_only ) - goto leave; - c->dek = passphrase_to_dek( NULL, 0, algo, &enc->s2k, 0, NULL, NULL ); - if (c->dek) - c->dek->algo_info_printed = 1; - if ( c->dek && enc->seskeylen ) - symkey_decrypt_sesskey( c->dek, enc->seskey, enc->seskeylen ); - } -leave: + if(!s || opt.list_only) + goto leave; + + if(opt.override_session_key) + { + c->dek = xmalloc_clear( sizeof *c->dek ); + if(get_override_session_key(c->dek, opt.override_session_key)) + { + xfree(c->dek); + c->dek = NULL; + } + } + else + { + int canceled; + + c->dek = passphrase_to_dek (NULL, 0, algo, &enc->s2k, 0, + NULL, &canceled); + if (canceled) + { + /* For unknown reasons passphrase_to_dek does only + return NULL if a new passphrase has been requested + and has not been repeated correctly. Thus even + with a cancel requested (by means of the gpg-agent) + it won't return NULL but an empty passphrase. We + take the most conservative approach for now and + work around it right here. */ + xfree (c->dek); + c->dek = NULL; + } + + if(c->dek) + { + c->dek->symmetric=1; + + /* FIXME: This doesn't work perfectly if a symmetric + key comes before a public key in the message - if + the user doesn't know the passphrase, then there is + a chance that the "decrypted" algorithm will happen + to be a valid one, which will make the returned dek + appear valid, so we won't try any public keys that + come later. */ + if(enc->seskeylen) + { + if(symkey_decrypt_seskey(c->dek, enc->seskey, + enc->seskeylen)) + { + xfree(c->dek); + c->dek=NULL; + } + } + else + c->dek->algo_info_printed = 1; + } + } + } + + leave: + c->symkeys++; free_packet(pkt); } @@ -320,7 +350,7 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) /* Hmmm: why do I have this algo check here - anyway there is * function to check it. */ if( opt.verbose ) - log_info(_("public key is %08lX\n"), (ulong)enc->keyid[1] ); + log_info(_("public key is %s\n"), keystr(enc->keyid) ); if( is_status_enabled() ) { char buf[50]; @@ -332,62 +362,54 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) if( !opt.list_only && opt.override_session_key ) { /* It does not make much sense to store the session key in * secure memory because it has already been passed on the - * command line and the GCHQ knows about it */ - c->dek = xcalloc (1, sizeof *c->dek ); + * command line and the GCHQ knows about it. */ + c->dek = xmalloc_clear( sizeof *c->dek ); result = get_override_session_key ( c->dek, opt.override_session_key ); if ( result ) { - xfree (c->dek); c->dek = NULL; + xfree(c->dek); c->dek = NULL; } } else if( is_ELGAMAL(enc->pubkey_algo) || enc->pubkey_algo == PUBKEY_ALGO_DSA || is_RSA(enc->pubkey_algo) ) { + /* FIXME: strore this all in a list and process it later */ + if ( !c->dek && ((!enc->keyid[0] && !enc->keyid[1]) || opt.try_all_secrets || !seckey_available( enc->keyid )) ) { if( opt.list_only ) result = -1; else { - c->dek = xcalloc_secure (1, sizeof *c->dek); + c->dek = xmalloc_secure_clear( sizeof *c->dek ); if( (result = get_session_key( enc, c->dek )) ) { /* error: delete the DEK */ - xfree (c->dek); c->dek = NULL; + xfree(c->dek); c->dek = NULL; } } } else - result = GPG_ERR_NO_SECKEY; + result = G10ERR_NO_SECKEY; } else - result = GPG_ERR_PUBKEY_ALGO; + result = G10ERR_PUBKEY_ALGO; if( result == -1 ) ; - else { - if( !result ) { - if( opt.verbose > 1 ) - log_info( _("public key encrypted data: good DEK\n") ); - if ( opt.show_session_key ) { - int i; - char *buf = xmalloc ( c->dek->keylen*2 + 20 ); - sprintf ( buf, "%d:", c->dek->algo ); - for(i=0; i < c->dek->keylen; i++ ) - sprintf(buf+strlen(buf), "%02X", c->dek->key[i] ); - log_info( "session key: \"%s\"\n", buf ); - write_status_text ( STATUS_SESSION_KEY, buf ); - } - } + else + { /* store it for later display */ - { - struct kidlist_item *x = xmalloc ( sizeof *x ); - x->kid[0] = enc->keyid[0]; - x->kid[1] = enc->keyid[1]; - x->pubkey_algo = enc->pubkey_algo; - x->reason = result; - x->next = c->pkenc_list; - c->pkenc_list = x; - } - } + struct kidlist_item *x = xmalloc( sizeof *x ); + x->kid[0] = enc->keyid[0]; + x->kid[1] = enc->keyid[1]; + x->pubkey_algo = enc->pubkey_algo; + x->reason = result; + x->next = c->pkenc_list; + c->pkenc_list = x; + + if( !result && opt.verbose > 1 ) + log_info( _("public key encrypted data: good DEK\n") ); + } + free_packet(pkt); } @@ -409,31 +431,29 @@ print_pkenc_list( struct kidlist_item *list, int failed ) if ( !failed && list->reason ) continue; - algstr = gcry_pk_algo_name (list->pubkey_algo); - pk = xcalloc (1, sizeof *pk ); + algstr = gcry_pk_algo_name ( list->pubkey_algo ); + pk = xmalloc_clear( sizeof *pk ); - if (!algstr || !*algstr) - algstr = "[?]"; + if( !algstr ) + algstr = "[?]"; pk->pubkey_algo = list->pubkey_algo; - if( !get_pubkey( pk, list->kid ) ) { - size_t n; + if( !get_pubkey( pk, list->kid ) ) + { char *p; - log_info( _("encrypted with %u-bit %s key, ID %08lX, created %s\n"), - nbits_from_pk( pk ), algstr, (ulong)list->kid[1], - strtimestamp(pk->timestamp) ); - fputs(" \"", log_get_stream() ); - p = get_user_id( list->kid, &n ); - print_utf8_string2 ( log_get_stream(), p, n, '"' ); - xfree (p); - fputs("\"\n", log_get_stream() ); - } - else { - log_info(_("encrypted with %s key, ID %08lX\n"), - algstr, (ulong) list->kid[1] ); - } + log_info( _("encrypted with %u-bit %s key, ID %s, created %s\n"), + nbits_from_pk( pk ), algstr, keystr_from_pk(pk), + strtimestamp(pk->timestamp) ); + p=get_user_id_native(list->kid); + fprintf(log_get_stream(),_(" \"%s\"\n"),p); + xfree(p); + } + else + log_info(_("encrypted with %s key, ID %s\n"), + algstr,keystr(list->kid)); + free_public_key( pk ); - if( gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY ) { + if( list->reason == G10ERR_NO_SECKEY ) { if( is_status_enabled() ) { char buf[20]; sprintf(buf,"%08lX%08lX", (ulong)list->kid[0], @@ -443,7 +463,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) } else if (list->reason) log_info(_("public key decryption failed: %s\n"), - gpg_strerror (list->reason)); + g10_errstr(list->reason)); } } @@ -453,10 +473,18 @@ proc_encrypted( CTX c, PACKET *pkt ) { int result = 0; - if (!opt.quiet) { + if (!opt.quiet) + { + if(c->symkeys>1) + log_info(_("encrypted with %lu passphrases\n"),c->symkeys); + else if(c->symkeys==1) + log_info(_("encrypted with 1 passphrase\n")); print_pkenc_list ( c->pkenc_list, 1 ); print_pkenc_list ( c->pkenc_list, 0 ); - } + } + + /* FIXME: Figure out the session key by looking at all pkenc packets. */ + write_status( STATUS_BEGIN_DECRYPTION ); @@ -467,43 +495,58 @@ proc_encrypted( CTX c, PACKET *pkt ) int algo; STRING2KEY s2kbuf, *s2k = NULL; - /* assume this is old style conventional encrypted data */ - if ( (algo = opt.def_cipher_algo)) - log_info (_("assuming %s encrypted data\n"), + if(opt.override_session_key) + { + c->dek = xmalloc_clear( sizeof *c->dek ); + result=get_override_session_key(c->dek, opt.override_session_key); + if(result) + { + xfree(c->dek); + c->dek = NULL; + } + } + else + { + /* assume this is old style conventional encrypted data */ + if ( (algo = opt.def_cipher_algo)) + log_info (_("assuming %s encrypted data\n"), gcry_cipher_algo_name (algo)); - else if ( gcry_cipher_test_algo(CIPHER_ALGO_IDEA) ) { - algo = opt.def_cipher_algo; - if (!algo) - algo = opt.s2k_cipher_algo; - idea_cipher_warn(1); - log_info (_("IDEA cipher unavailable, " - "optimistically attempting to use %s instead\n"), - gcry_cipher_algo_name (algo)); - } - else { - algo = CIPHER_ALGO_IDEA; - if (!opt.s2k_digest_algo) { - /* If no digest is given we assume MD5 */ - s2kbuf.mode = 0; - s2kbuf.hash_algo = GCRY_MD_MD5; - s2k = &s2kbuf; - } - log_info (_("assuming %s encrypted data\n"), "IDEA"); - } + else if ( gcry_cipher_test_algo (CIPHER_ALGO_IDEA) ) + { + algo = opt.def_cipher_algo; + if (!algo) + algo = opt.s2k_cipher_algo; + idea_cipher_warn(1); + log_info (_("IDEA cipher unavailable, " + "optimistically attempting to use %s instead\n"), + gcry_cipher_algo_name (algo)); + } + else + { + algo = CIPHER_ALGO_IDEA; + if (!opt.s2k_digest_algo) + { + /* If no digest is given we assume MD5 */ + s2kbuf.mode = 0; + s2kbuf.hash_algo = DIGEST_ALGO_MD5; + s2k = &s2kbuf; + } + log_info (_("assuming %s encrypted data\n"), "IDEA"); + } - c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL, NULL ); - if (c->dek) - c->dek->algo_info_printed = 1; + c->dek = passphrase_to_dek ( NULL, 0, algo, s2k, 0, NULL, NULL ); + if (c->dek) + c->dek->algo_info_printed = 1; + } } else if( !c->dek ) - result = GPG_ERR_NO_SECKEY; + result = G10ERR_NO_SECKEY; if( !result ) result = decrypt_data( c, pkt->pkt.encrypted, c->dek ); - xfree (c->dek); c->dek = NULL; if( result == -1 ) ; - else if( !result || (gpg_err_code (result)==GPG_ERR_BAD_SIGNATURE + else if( !result || (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE && opt.ignore_mdc_error)) { write_status( STATUS_DECRYPTION_OKAY ); if( opt.verbose > 1 ) @@ -512,25 +555,35 @@ proc_encrypted( CTX c, PACKET *pkt ) write_status( STATUS_GOODMDC ); else if(!opt.no_mdc_warn) log_info (_("WARNING: message was not integrity protected\n")); + if(opt.show_session_key) + { + int i; + char *buf = xmalloc ( c->dek->keylen*2 + 20 ); + sprintf ( buf, "%d:", c->dek->algo ); + for(i=0; i < c->dek->keylen; i++ ) + sprintf(buf+strlen(buf), "%02X", c->dek->key[i] ); + log_info( "session key: `%s'\n", buf ); + write_status_text ( STATUS_SESSION_KEY, buf ); + } } - else if( gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE ) { + else if( result == G10ERR_BAD_SIGN ) { log_error(_("WARNING: encrypted message has been manipulated!\n")); write_status( STATUS_BADMDC ); write_status( STATUS_DECRYPTION_FAILED ); } else { write_status( STATUS_DECRYPTION_FAILED ); - log_error(_("decryption failed: %s\n"), gpg_strerror (result)); + log_error(_("decryption failed: %s\n"), g10_errstr(result)); /* Hmmm: does this work when we have encrypted using multiple * ways to specify the session key (symmmetric and PK)*/ } + xfree(c->dek); c->dek = NULL; free_packet(pkt); c->last_was_session_key = 0; write_status( STATUS_END_DECRYPTION ); } - static void proc_plaintext( CTX c, PACKET *pkt ) { @@ -543,7 +596,8 @@ proc_plaintext( CTX c, PACKET *pkt ) else if( opt.verbose ) log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name); free_md_filter_context( &c->mfx ); - gcry_md_open (&c->mfx.md, 0, 0); + if (gcry_md_open (&c->mfx.md, 0, 0)) + BUG (); /* fixme: we may need to push the textfilter if we have sigclass 1 * and no armoring - Not yet tested * Hmmm, why don't we need it at all if we have sigclass 1 @@ -551,72 +605,90 @@ proc_plaintext( CTX c, PACKET *pkt ) * See: Russ Allbery's mail 1999-02-09 */ any = clearsig = only_md5 = 0; - for(n=c->list; n; n = n->next ) { - if( n->pkt->pkttype == PKT_ONEPASS_SIG ) { - if( n->pkt->pkt.onepass_sig->digest_algo ) { - gcry_md_enable ( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo ); + for(n=c->list; n; n = n->next ) + { + if( n->pkt->pkttype == PKT_ONEPASS_SIG ) + { + /* For the onepass signature case */ + if( n->pkt->pkt.onepass_sig->digest_algo ) + { + gcry_md_enable (c->mfx.md, + n->pkt->pkt.onepass_sig->digest_algo); if( !any && n->pkt->pkt.onepass_sig->digest_algo - == DIGEST_ALGO_MD5 ) - only_md5 = 1; + == DIGEST_ALGO_MD5 ) + only_md5 = 1; else - only_md5 = 0; + only_md5 = 0; any = 1; - } + } if( n->pkt->pkt.onepass_sig->sig_class != 0x01 ) - only_md5 = 0; - } + only_md5 = 0; + } else if( n->pkt->pkttype == PKT_GPG_CONTROL && n->pkt->pkt.gpg_control->control - == CTRLPKT_CLEARSIGN_START ) { + == CTRLPKT_CLEARSIGN_START ) + { + /* For the clearsigned message case */ size_t datalen = n->pkt->pkt.gpg_control->datalen; const byte *data = n->pkt->pkt.gpg_control->data; /* check that we have at least the sigclass and one hash */ if ( datalen < 2 ) - log_fatal("invalid control packet CTRLPKT_CLEARSIGN_START\n"); + log_fatal("invalid control packet CTRLPKT_CLEARSIGN_START\n"); /* Note that we don't set the clearsig flag for not-dash-escaped * documents */ clearsig = (*data == 0x01); for( data++, datalen--; datalen; datalen--, data++ ) - gcry_md_enable ( c->mfx.md, *data ); + md_enable( c->mfx.md, *data ); any = 1; - break; /* no pass signature pakets are expected */ - } - } + break; /* Stop here as one-pass signature packets are not + expected. */ + } + else if(n->pkt->pkttype==PKT_SIGNATURE) + { + /* For the SIG+LITERAL case that PGP used to use. */ + md_enable( c->mfx.md, n->pkt->pkt.signature->digest_algo ); + any=1; + } + } - if( !any && !opt.skip_verify ) { - /* no onepass sig packet: enable all standard algos */ - gcry_md_enable ( c->mfx.md, DIGEST_ALGO_RMD160 ); - gcry_md_enable ( c->mfx.md, DIGEST_ALGO_SHA1 ); - gcry_md_enable ( c->mfx.md, DIGEST_ALGO_MD5 ); - } + if( !any && !opt.skip_verify ) + { + /* This is for the old GPG LITERAL+SIG case. It's not legal + according to 2440, so hopefully it won't come up that + often. There is no good way to specify what algorithms to + use in that case, so these three are the historical + answer. */ + md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); + md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); + md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); + } if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) { /* This is a kludge to work around a bug in pgp2. It does only * catch those mails which are armored. To catch the non-armored * pgp mails we could see whether there is the signature packet * in front of the plaintext. If someone needs this, send me a patch. */ - gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0); + if ( gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0) ) + BUG (); } if ( DBG_HASHING ) { gcry_md_start_debug ( c->mfx.md, "verify" ); if ( c->mfx.md2 ) gcry_md_start_debug ( c->mfx.md2, "verify2" ); } - if ( c->pipemode.op == 'B' ) - rc = handle_plaintext( pt, &c->mfx, 1, 0, NULL ); - else { - int failed; - rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig, &failed); - if( rc && failed && !c->sigs_only) { - /* can't write output but we hash it anyway to - * check the signature */ - rc = handle_plaintext( pt, &c->mfx, 1, clearsig, NULL ); - } - } + rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); + if( gpg_err_code (rc) == G10ERR_CREATE_FILE && !c->sigs_only) + { +#warning We need to change the test for the error code + /* Can't write output but we hash it anyway to + * Check the signature. */ + rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); + } + if( rc ) - log_error( "handle plaintext failed: %s\n", gpg_strerror (rc)); + log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); free_packet(pkt); c->last_was_session_key = 0; @@ -632,14 +704,14 @@ proc_plaintext( CTX c, PACKET *pkt ) static int -proc_compressed_cb( iobuf_t a, void *info ) +proc_compressed_cb( IOBUF a, void *info ) { return proc_signature_packets( info, a, ((CTX)info)->signed_data, ((CTX)info)->sigfilename ); } static int -proc_encrypt_cb( iobuf_t a, void *info ) +proc_encrypt_cb( IOBUF a, void *info ) { return proc_encryption_packets( info, a ); } @@ -651,14 +723,16 @@ proc_compressed( CTX c, PACKET *pkt ) int rc; /*printf("zip: compressed data packet\n");*/ - if( c->sigs_only ) + if( !zd->algorithm ) + rc=G10ERR_COMPR_ALGO; + else if( c->sigs_only ) rc = handle_compressed( c, zd, proc_compressed_cb, c ); else if( c->encrypt_only ) rc = handle_compressed( c, zd, proc_encrypt_cb, c ); else rc = handle_compressed( c, zd, NULL, NULL ); if( rc ) - log_error("uncompressing failed: %s\n", gpg_strerror (rc)); + log_error("uncompressing failed: %s\n", g10_errstr(rc)); free_packet(pkt); c->last_was_session_key = 0; } @@ -669,10 +743,10 @@ proc_compressed( CTX c, PACKET *pkt ) */ static int do_check_sig( CTX c, KBNODE node, int *is_selfsig, - int *is_expkey, int *is_revkey ) + int *is_expkey, int *is_revkey ) { PKT_signature *sig; - MD_HANDLE md = NULL, md2 = NULL; + gcry_md_hd_t md = NULL, md2 = NULL; int algo, rc; assert( node->pkt->pkttype == PKT_SIGNATURE ); @@ -681,29 +755,39 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, sig = node->pkt->pkt.signature; algo = sig->digest_algo; - if( (rc = gcry_md_test_algo(algo)) ) - return rc; + rc = openpgp_md_test_algo(algo); + if (rc) + return rc; if( sig->sig_class == 0x00 ) { if( c->mfx.md ) - gcry_md_copy (&md,c->mfx.md); + { + if (gcry_md_copy (&md, c->mfx.md )) + BUG (); + } else /* detached signature */ - gcry_md_open (&md, 0, 0 ); /* signature_check() will - enable the md*/ + { + /* signature_check() will enable the md*/ + if (gcry_md_open (&md, 0, 0 )) + BUG (); + } } else if( sig->sig_class == 0x01 ) { /* how do we know that we have to hash the (already hashed) text * in canonical mode ??? (calculating both modes???) */ if( c->mfx.md ) { - gcry_md_copy (&md, c->mfx.md); - if (c->mfx.md2) - gcry_md_copy (&md2, c->mfx.md2); + if (gcry_md_copy (&md, c->mfx.md )) + BUG (); + if( c->mfx.md2 && gcry_md_copy (&md2, c->mfx.md2 )) + BUG (); } else { /* detached signature */ - log_debug("Do we really need this here?"); - gcry_md_open (&md, 0, 0 ); /* signature_check() will - enable the md*/ - gcry_md_open (&md2, 0, 0 ); + log_debug("Do we really need this here?"); + /* signature_check() will enable the md*/ + if (gcry_md_open (&md, 0, 0 )) + BUG (); + if (gcry_md_open (&md2, 0, 0 )) + BUG (); } } else if( (sig->sig_class&~3) == 0x10 @@ -717,23 +801,23 @@ do_check_sig( CTX c, KBNODE node, int *is_selfsig, return check_key_signature( c->list, node, is_selfsig ); } else if( sig->sig_class == 0x20 ) { - log_info(_("standalone revocation - " - "use \"gpg --import\" to apply\n")); - return GPG_ERR_NOT_PROCESSED; + log_error (_("standalone revocation - " + "use \"gpg --import\" to apply\n")); + return G10ERR_NOT_PROCESSED; } else { log_error("invalid root packet for sigclass %02x\n", sig->sig_class); - return GPG_ERR_SIG_CLASS; + return G10ERR_SIG_CLASS; } } else - return GPG_ERR_SIG_CLASS; + return G10ERR_SIG_CLASS; rc = signature_check2( sig, md, NULL, is_expkey, is_revkey, NULL ); if( gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2 ) rc = signature_check2( sig, md2, NULL, is_expkey, is_revkey, NULL ); - gcry_md_close (md); - gcry_md_close (md2); + gcry_md_close(md); + gcry_md_close(md2); return rc; } @@ -780,44 +864,38 @@ list_node( CTX c, KBNODE node ) || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { PKT_public_key *pk = node->pkt->pkt.public_key; - if( opt.with_colons ) { + if( opt.with_colons ) + { u32 keyid[2]; keyid_from_pk( pk, keyid ); - if( mainkey ) { - c->local_id = pk->local_id; - c->trustletter = opt.fast_list_mode? - 0 : get_validity_info( pk, NULL ); - } + if( mainkey ) + c->trustletter = opt.fast_list_mode? + 0 : get_validity_info( pk, NULL ); printf("%s:", mainkey? "pub":"sub" ); if( c->trustletter ) - putchar( c->trustletter ); - printf(":%u:%d:%08lX%08lX:%s:%s:", - nbits_from_pk( pk ), - pk->pubkey_algo, - (ulong)keyid[0],(ulong)keyid[1], - colon_datestr_from_pk( pk ), - colon_strtime (pk->expiredate) ); - if( c->local_id ) - printf("%lu", c->local_id ); - putchar(':'); + putchar( c->trustletter ); + printf(":%u:%d:%08lX%08lX:%s:%s::", + nbits_from_pk( pk ), + pk->pubkey_algo, + (ulong)keyid[0],(ulong)keyid[1], + colon_datestr_from_pk( pk ), + colon_strtime (pk->expiredate) ); if( mainkey && !opt.fast_list_mode ) - putchar( get_ownertrust_info (pk) ); + putchar( get_ownertrust_info (pk) ); putchar(':'); if( node->next && node->next->pkt->pkttype == PKT_RING_TRUST) { - putchar('\n'); any=1; - if( opt.fingerprint ) - print_fingerprint( pk, NULL, 0 ); - printf("rtv:1:%u:\n", - node->next->pkt->pkt.ring_trust->trustval ); + putchar('\n'); any=1; + if( opt.fingerprint ) + print_fingerprint( pk, NULL, 0 ); + printf("rtv:1:%u:\n", + node->next->pkt->pkt.ring_trust->trustval ); } - } + } else - printf("%s %4u%c/%08lX %s ", - mainkey? "pub":"sub", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid_from_pk( pk, NULL ), - datestr_from_pk( pk ) ); + printf("%s %4u%c/%s %s%s", + mainkey? "pub":"sub", nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), keystr_from_pk( pk ), + datestr_from_pk( pk ), mainkey?" ":""); if( mainkey ) { /* and now list all userids with their signatures */ @@ -846,10 +924,12 @@ list_node( CTX c, KBNODE node ) putchar('\n'); if( opt.fingerprint && !any ) print_fingerprint( pk, NULL, 0 ); - if( node->next + if( opt.with_colons + && node->next && node->next->pkt->pkttype == PKT_RING_TRUST ) { printf("rtv:2:%u:\n", - node->next->pkt->pkt.ring_trust->trustval ); + node->next->pkt->pkt.ring_trust? + node->next->pkt->pkt.ring_trust->trustval : 0); } any=1; } @@ -862,9 +942,22 @@ list_node( CTX c, KBNODE node ) } } } - else if( pk->expiredate ) { /* of subkey */ - printf(_(" [expires: %s]"), expirestr_from_pk( pk ) ); - } + else + { + /* of subkey */ + if( pk->is_revoked ) + { + printf(" ["); + printf(_("revoked: %s"),revokestr_from_pk(pk)); + printf("]"); + } + else if( pk->expiredate ) + { + printf(" ["); + printf(_("expires: %s"),expirestr_from_pk(pk)); + printf("]"); + } + } if( !any ) putchar('\n'); @@ -875,25 +968,23 @@ list_node( CTX c, KBNODE node ) || node->pkt->pkttype == PKT_SECRET_SUBKEY ) { PKT_secret_key *sk = node->pkt->pkt.secret_key; - if( opt.with_colons ) { + if( opt.with_colons ) + { u32 keyid[2]; keyid_from_sk( sk, keyid ); printf("%s::%u:%d:%08lX%08lX:%s:%s:::", - mainkey? "sec":"ssb", - nbits_from_sk( sk ), - sk->pubkey_algo, - (ulong)keyid[0],(ulong)keyid[1], - colon_datestr_from_sk( sk ), - colon_strtime (sk->expiredate) - /* fixme: add LID */ ); - } + mainkey? "sec":"ssb", + nbits_from_sk( sk ), + sk->pubkey_algo, + (ulong)keyid[0],(ulong)keyid[1], + colon_datestr_from_sk( sk ), + colon_strtime (sk->expiredate) + /* fixme: add LID */ ); + } else - printf("%s %4u%c/%08lX %s ", - mainkey? "sec":"ssb", - nbits_from_sk( sk ), - pubkey_letter( sk->pubkey_algo ), - (ulong)keyid_from_sk( sk, NULL ), - datestr_from_sk( sk ) ); + printf("%s %4u%c/%s %s ", mainkey? "sec":"ssb", + nbits_from_sk( sk ), pubkey_letter( sk->pubkey_algo ), + keystr_from_sk( sk ), datestr_from_sk( sk )); if( mainkey ) { /* and now list all userids with their signatures */ for( node = node->next; node; node = node->next ) { @@ -945,7 +1036,7 @@ list_node( CTX c, KBNODE node ) char *p; int sigrc = ' '; - if( !opt.list_sigs ) + if( !opt.verbose ) return; if( sig->sig_class == 0x20 || sig->sig_class == 0x30 ) @@ -954,14 +1045,13 @@ list_node( CTX c, KBNODE node ) fputs("sig", stdout); if( opt.check_sigs ) { fflush(stdout); - switch( gpg_err_code (rc2=do_check_sig( c, node, - &is_selfsig, - NULL, NULL )) ) { - case 0: sigrc = '!'; break; - case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; + rc2=do_check_sig( c, node, &is_selfsig, NULL, NULL ); + switch (gpg_err_code (rc2)) { + case 0: sigrc = '!'; break; + case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: - case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; - default: sigrc = '%'; break; + case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; + default: sigrc = '%'; break; } } else { /* check whether this is a self signature */ @@ -997,10 +1087,10 @@ list_node( CTX c, KBNODE node ) printf(":"); } else - printf("%c %08lX %s ", - sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig)); + printf("%c %s %s ", + sigrc, keystr(sig->keyid), datestr_from_sig(sig)); if( sigrc == '%' ) - printf("[%s] ", gpg_strerror (rc2) ); + printf("[%s] ", g10_errstr(rc2) ); else if( sigrc == '?' ) ; else if( is_selfsig ) { @@ -1013,7 +1103,7 @@ list_node( CTX c, KBNODE node ) else if( !opt.fast_list_mode ) { p = get_user_id( sig->keyid, &n ); print_string( stdout, p, n, opt.with_colons ); - xfree (p); + xfree(p); } if( opt.with_colons ) printf(":%02x%c:", sig->sig_class, sig->flags.exportable?'x':'l'); @@ -1026,24 +1116,24 @@ list_node( CTX c, KBNODE node ) int -proc_packets( void *anchor, iobuf_t a ) +proc_packets( void *anchor, IOBUF a ) { int rc; - CTX c = xcalloc (1, sizeof *c ); + CTX c = xmalloc_clear( sizeof *c ); c->anchor = anchor; rc = do_proc_packets( c, a ); - xfree ( c ); + xfree( c ); return rc; } int -proc_signature_packets( void *anchor, iobuf_t a, +proc_signature_packets( void *anchor, IOBUF a, STRLIST signedfiles, const char *sigfilename ) { - CTX c = xcalloc (1, sizeof *c ); + CTX c = xmalloc_clear( sizeof *c ); int rc; c->anchor = anchor; @@ -1051,28 +1141,47 @@ proc_signature_packets( void *anchor, iobuf_t a, c->signed_data = signedfiles; c->sigfilename = sigfilename; rc = do_proc_packets( c, a ); - xfree ( c ); + + /* If we have not encountered any signature we print an error + messages, send a NODATA status back and return an error code. + Using log_error is required because verify_files does not check + error codes for each file but we want to terminate the process + with an error. */ + if (!rc && !c->any_sig_seen) + { + write_status_text (STATUS_NODATA, "4"); + log_error (_("no signature found\n")); + rc = G10ERR_NO_DATA; + } + + /* Propagate the signature seen flag upward. Do this only on + success so that we won't issue the nodata status several + times. */ + if (!rc && c->anchor && c->any_sig_seen) + c->anchor->any_sig_seen = 1; + + xfree( c ); return rc; } int -proc_encryption_packets( void *anchor, iobuf_t a ) +proc_encryption_packets( void *anchor, IOBUF a ) { - CTX c = xcalloc (1, sizeof *c ); + CTX c = xmalloc_clear( sizeof *c ); int rc; c->anchor = anchor; c->encrypt_only = 1; rc = do_proc_packets( c, a ); - xfree ( c ); + xfree( c ); return rc; } int -do_proc_packets( CTX c, iobuf_t a ) +do_proc_packets( CTX c, IOBUF a ) { - PACKET *pkt = xmalloc ( sizeof *pkt ); + PACKET *pkt = xmalloc( sizeof *pkt ); int rc=0; int any_data=0; int newpkt; @@ -1084,8 +1193,9 @@ do_proc_packets( CTX c, iobuf_t a ) if( rc ) { free_packet(pkt); /* stop processing when an invalid packet has been encountered - * but don't do so when we are doing a --list-packet. */ - if( gpg_err_code (rc) == GPG_ERR_INV_PACKET && opt.list_packets != 2 ) + * but don't do so when we are doing a --list-packets. */ + if (gpg_err_code (rc) == GPG_ERR_INVALID_PACKET + && opt.list_packets != 2 ) break; continue; } @@ -1110,7 +1220,7 @@ do_proc_packets( CTX c, iobuf_t a ) case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: write_status_text( STATUS_UNEXPECTED, "0" ); - rc = GPG_ERR_UNEXPECTED; + rc = G10ERR_UNEXPECTED; goto leave; case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break; @@ -1126,7 +1236,7 @@ do_proc_packets( CTX c, iobuf_t a ) case PKT_SECRET_KEY: case PKT_USER_ID: write_status_text( STATUS_UNEXPECTED, "0" ); - rc = GPG_ERR_UNEXPECTED; + rc = G10ERR_UNEXPECTED; goto leave; case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break; case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break; @@ -1180,19 +1290,13 @@ do_proc_packets( CTX c, iobuf_t a ) if( newpkt == -1 ) ; else if( newpkt ) { - pkt = xmalloc ( sizeof *pkt ); + pkt = xmalloc( sizeof *pkt ); init_packet(pkt); } else free_packet(pkt); - if ( c->pipemode.stop_now ) { - /* we won't get an EOF in pipemode, so we have to - * break the loop here */ - rc = -1; - break; - } } - if( gpg_err_code (rc) == GPG_ERR_INV_PACKET ) + if( rc == G10ERR_INVALID_PACKET ) write_status_text( STATUS_NODATA, "3" ); if( any_data ) rc = 0; @@ -1202,105 +1306,213 @@ do_proc_packets( CTX c, iobuf_t a ) leave: release_list( c ); - xfree (c->dek); + xfree(c->dek); free_packet( pkt ); - xfree ( pkt ); + xfree( pkt ); free_md_filter_context( &c->mfx ); return rc; } -static int -check_sig_and_print( CTX c, KBNODE node ) +/* Helper for pka_uri_from_sig to parse the to-be-verified address out + of the notation data. */ +static pka_info_t * +get_pka_address (PKT_signature *sig) { - PKT_signature *sig = node->pkt->pkt.signature; - const char *astr, *tstr; - int rc, is_expkey=0, is_revkey=0; + pka_info_t *pka = NULL; + struct notation *nd,*notation; - if( opt.skip_verify ) { - log_info(_("signature verification suppressed\n")); - return 0; - } + notation=sig_to_notation(sig); - /* It is not in all cases possible to check multiple signatures: - * PGP 2 (which is also allowed by OpenPGP), does use the packet - * sequence: sig+data, OpenPGP does use onepas+data=sig and GnuPG - * sometimes uses (because I did'nt read the specs right) data+sig. - * Because it is possible to create multiple signatures with - * different packet sequence (e.g. data+sig and sig+data) it might - * not be possible to get it right: let's say we have: - * data+sig, sig+data,sig+data and we have not yet encountered the last - * data, we could also see this a one data with 2 signatures and then - * data+sig. - * To protect against this we check that all signatures follow - * without any intermediate packets. Note, that we won't get this - * error when we use onepass packets or cleartext signatures because - * we reset the list every time - * - * FIXME: Now that we have these marker packets, we should create a - * real grammar and check against this. - */ + for(nd=notation;nd;nd=nd->next) { - KBNODE n; - int n_sig=0; + if(strcmp(nd->name,"pka-address@gnupg.org")!=0) + continue; /* Not the notation we want. */ + + /* For now we only use the first valid PKA notation. In future + we might want to keep additional PKA notations in a linked + list. */ + if (is_valid_mailbox (nd->value)) + { + pka = xmalloc (sizeof *pka + strlen(nd->value)); + pka->valid = 0; + pka->checked = 0; + pka->uri = NULL; + strcpy (pka->email, nd->value); + break; + } + } - for (n=c->list; n; n=n->next ) { - if ( n->pkt->pkttype == PKT_SIGNATURE ) - n_sig++; - } - if (n_sig > 1) { /* more than one signature - check sequence */ - int tmp, onepass; - - for (tmp=onepass=0,n=c->list; n; n=n->next ) { - if (n->pkt->pkttype == PKT_ONEPASS_SIG) - onepass++; - else if (n->pkt->pkttype == PKT_GPG_CONTROL - && n->pkt->pkt.gpg_control->control - == CTRLPKT_CLEARSIGN_START ) { - onepass++; /* handle the same way as a onepass */ - } - else if ( (tmp && n->pkt->pkttype != PKT_SIGNATURE) ) { - log_error(_("can't handle these multiple signatures\n")); - return 0; - } - else if ( n->pkt->pkttype == PKT_SIGNATURE ) - tmp = 1; - else if (!tmp && !onepass - && n->pkt->pkttype == PKT_GPG_CONTROL - && n->pkt->pkt.gpg_control->control - == CTRLPKT_PLAINTEXT_MARK ) { - /* plaintext before signatures but no one-pass packets*/ - log_error(_("can't handle these multiple signatures\n")); - return 0; - } + free_notation(notation); + + return pka; +} + + +/* Return the URI from a DNS PKA record. If this record has already + be retrieved for the signature we merely return it; if not we go + out and try to get that DNS record. */ +static const char * +pka_uri_from_sig (PKT_signature *sig) +{ + if (!sig->flags.pka_tried) + { + assert (!sig->pka_info); + sig->flags.pka_tried = 1; + sig->pka_info = get_pka_address (sig); + if (sig->pka_info) + { + char *uri; + + uri = get_pka_info (sig->pka_info->email, sig->pka_info->fpr); + if (uri) + { + sig->pka_info->valid = 1; + if (!*uri) + xfree (uri); + else + sig->pka_info->uri = uri; } } } + return sig->pka_info? sig->pka_info->uri : NULL; +} + + +static int +check_sig_and_print( CTX c, KBNODE node ) +{ + PKT_signature *sig = node->pkt->pkt.signature; + const char *astr; + int rc, is_expkey=0, is_revkey=0; + + if (opt.skip_verify) + { + log_info(_("signature verification suppressed\n")); + return 0; + } + + /* Check that the message composition is valid. + + Per RFC-2440bis (-15) allowed: + + S{1,n} -- detached signature. + S{1,n} P -- old style PGP2 signature + O{1,n} P S{1,n} -- standard OpenPGP signature. + C P S{1,n} -- cleartext signature. + + + O = One-Pass Signature packet. + S = Signature packet. + P = OpenPGP Message packet (Encrypted | Compressed | Literal) + (Note that the current rfc2440bis draft also allows + for a signed message but that does not work as it + introduces ambiguities.) + We keep track of these packages using the marker packet + CTRLPKT_PLAINTEXT_MARK. + C = Marker packet for cleartext signatures. + + We reject all other messages. + + Actually we are calling this too often, i.e. for verification of + each message but better have some duplicate work than to silently + introduce a bug here. + */ + { + KBNODE n; + int n_onepass, n_sig; + +/* log_debug ("checking signature packet composition\n"); */ +/* dump_kbnode (c->list); */ + + n = c->list; + assert (n); + if ( n->pkt->pkttype == PKT_SIGNATURE ) + { + /* This is either "S{1,n}" case (detached signature) or + "S{1,n} P" (old style PGP2 signature). */ + for (n = n->next; n; n = n->next) + if (n->pkt->pkttype != PKT_SIGNATURE) + break; + if (!n) + ; /* Okay, this is a detached signature. */ + else if (n->pkt->pkttype == PKT_GPG_CONTROL + && (n->pkt->pkt.gpg_control->control + == CTRLPKT_PLAINTEXT_MARK) ) + { + if (n->next) + goto ambiguous; /* We only allow one P packet. */ + } + else + goto ambiguous; + } + else if (n->pkt->pkttype == PKT_ONEPASS_SIG) + { + /* This is the "O{1,n} P S{1,n}" case (standard signature). */ + for (n_onepass=1, n = n->next; + n && n->pkt->pkttype == PKT_ONEPASS_SIG; n = n->next) + n_onepass++; + if (!n || !(n->pkt->pkttype == PKT_GPG_CONTROL + && (n->pkt->pkt.gpg_control->control + == CTRLPKT_PLAINTEXT_MARK))) + goto ambiguous; + for (n_sig=0, n = n->next; + n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next) + n_sig++; + if (!n_sig) + goto ambiguous; + if (n && !opt.allow_multisig_verification) + goto ambiguous; + if (n_onepass != n_sig) + { + log_info ("number of one-pass packets does not match " + "number of signature packets\n"); + goto ambiguous; + } + } + else if (n->pkt->pkttype == PKT_GPG_CONTROL + && n->pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START ) + { + /* This is the "C P S{1,n}" case (clear text signature). */ + n = n->next; + if (!n || !(n->pkt->pkttype == PKT_GPG_CONTROL + && (n->pkt->pkt.gpg_control->control + == CTRLPKT_PLAINTEXT_MARK))) + goto ambiguous; + for (n_sig=0, n = n->next; + n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next) + n_sig++; + if (n || !n_sig) + goto ambiguous; + } + else + { + ambiguous: + log_error(_("can't handle this ambiguous signature data\n")); + return 0; + } + + } + + /* (Indendation below not yet changed to GNU style.) */ - tstr = asctimestamp(sig->timestamp); - astr = gcry_pk_algo_name (sig->pubkey_algo); - if(opt.verify_options&VERIFY_SHOW_LONG_KEYID) + astr = gcry_pk_algo_name ( sig->pubkey_algo ); + if(keystrlen()>8) { - log_info(_("Signature made %.*s\n"),(int)strlen(tstr), tstr); - log_info(_(" using %s key %08lX%08lX\n"), - astr? astr: "?",(ulong)sig->keyid[0],(ulong)sig->keyid[1] ); + log_info(_("Signature made %s\n"),asctimestamp(sig->timestamp)); + log_info(_(" using %s key %s\n"), + astr? astr: "?",keystr(sig->keyid)); } else - log_info(_("Signature made %.*s using %s key ID %08lX\n"), - (int)strlen(tstr), tstr, astr? astr: "?", - (ulong)sig->keyid[1] ); + log_info(_("Signature made %s using %s key ID %s\n"), + asctimestamp(sig->timestamp), astr? astr: "?", + keystr(sig->keyid)); rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY - && opt.keyserver_scheme && opt.keyserver_options.auto_key_retrieve) { - if( keyserver_import_keyid ( sig->keyid )==0 ) - rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - } + /* If the key isn't found, check for a preferred keyserver */ - /* If the key still isn't found, try to inform the user where it - can be found. */ - if(gpg_err_code (rc)==GPG_ERR_NO_PUBKEY && sig->flags.pref_ks) + if(rc==G10ERR_NO_PUBKEY && sig->flags.pref_ks) { const byte *p; int seq=0; @@ -1313,17 +1525,81 @@ check_sig_and_print( CTX c, KBNODE node ) page, but "from" if it is located on a keyserver. I'm not going to even try to make two strings here :) */ log_info(_("Key available at: ") ); - print_string( log_get_stream(), p, n, 0 ); + print_utf8_string( log_get_stream(), p, n ); putc( '\n', log_get_stream() ); + + if(opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE + && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) + { + struct keyserver_spec *spec; + + spec=parse_preferred_keyserver(sig); + if(spec) + { + int res; + + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_keyid(sig->keyid,spec); + glo_ctrl.in_auto_key_retrieve--; + if(!res) + rc=do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + free_keyserver_spec(spec); + + if(!rc) + break; + } + } } } + /* If the preferred keyserver thing above didn't work, our second + try is to use the URI from a DNS PKA record. */ + if ( rc == G10ERR_NO_PUBKEY + && opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE + && opt.keyserver_options.options&KEYSERVER_HONOR_PKA_RECORD) + { + const char *uri = pka_uri_from_sig (sig); + + if (uri) + { + /* FIXME: We might want to locate the key using the + fingerprint instead of the keyid. */ + int res; + struct keyserver_spec *spec; + + spec = parse_keyserver_uri (uri, 1, NULL, 0); + if (spec) + { + glo_ctrl.in_auto_key_retrieve++; + res = keyserver_import_keyid (sig->keyid, spec); + glo_ctrl.in_auto_key_retrieve--; + free_keyserver_spec (spec); + if (!res) + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + } + } + } + + /* If the preferred keyserver thing above didn't work and we got + no information from the DNS PKA, this is a third try. */ + + if( rc == G10ERR_NO_PUBKEY && opt.keyserver + && opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) + { + int res; + + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_keyid ( sig->keyid, opt.keyserver ); + glo_ctrl.in_auto_key_retrieve--; + if(!res) + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + } if( !rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) { KBNODE un, keyblock; int count=0, statno; char keyid_str[50]; - PKT_public_key *pk=NULL; + PKT_public_key *pk=NULL; if(rc) statno=STATUS_BADSIG; @@ -1343,8 +1619,8 @@ check_sig_and_print( CTX c, KBNODE node ) /* find and print the primary user ID */ for( un=keyblock; un; un = un->next ) { + char *p; int valid; - if(un->pkt->pkttype==PKT_PUBLIC_KEY) { pk=un->pkt->pkt.public_key; @@ -1360,10 +1636,10 @@ check_sig_and_print( CTX c, KBNODE node ) continue; if ( !un->pkt->pkt.user_id->is_primary ) continue; - /* We want the textual user ID here */ + /* We want the textual primary user ID here */ if ( un->pkt->pkt.user_id->attrib_data ) continue; - + assert(pk); /* Get it before we print anything to avoid interrupting @@ -1377,20 +1653,28 @@ check_sig_and_print( CTX c, KBNODE node ) un->pkt->pkt.user_id->len, -1 ); - log_info(rc? _("BAD signature from \"") - : sig->flags.expired ? _("Expired signature from \"") - : _("Good signature from \"")); - print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len ); - if(opt.verify_options&VERIFY_SHOW_VALIDITY) - fprintf (log_get_stream(), - "\" [%s]\n",trust_value_to_string(valid)); + p=utf8_to_native(un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len,0); + + if(rc) + log_info(_("BAD signature from \"%s\""),p); + else if(sig->flags.expired) + log_info(_("Expired signature from \"%s\""),p); + else + log_info(_("Good signature from \"%s\""),p); + + xfree(p); + + if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY) + fprintf(log_get_stream()," [%s]\n",trust_value_to_string(valid)); else - fputs("\"\n", log_get_stream() ); + fputs("\n", log_get_stream() ); count++; } if( !count ) { /* just in case that we have no valid textual userid */ + char *p; + /* Try for an invalid textual userid */ for( un=keyblock; un; un = un->next ) { if( un->pkt->pkttype == PKT_USER_ID && @@ -1414,29 +1698,37 @@ check_sig_and_print( CTX c, KBNODE node ) un? un->pkt->pkt.user_id->len:3, -1 ); - log_info(rc? _("BAD signature from \"") - : sig->flags.expired ? _("Expired signature from \"") - : _("Good signature from \"")); - if (opt.trust_model!=TM_ALWAYS && un) { - fputs(_("[uncertain]"), log_get_stream() ); + if(un) + p=utf8_to_native(un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len,0); + else + p=xstrdup("[?]"); + + if(rc) + log_info(_("BAD signature from \"%s\""),p); + else if(sig->flags.expired) + log_info(_("Expired signature from \"%s\""),p); + else + log_info(_("Good signature from \"%s\""),p); + if (opt.trust_model!=TM_ALWAYS && un) + { putc(' ', log_get_stream() ); - } - print_utf8_string( log_get_stream(), - un? un->pkt->pkt.user_id->name:"[?]", - un? un->pkt->pkt.user_id->len:3 ); - fputs("\"\n", log_get_stream() ); + fputs(_("[uncertain]"), log_get_stream() ); + } + fputs("\n", log_get_stream() ); } /* If we have a good signature and already printed * the primary user ID, print all the other user IDs */ if ( count && !rc ) { + char *p; for( un=keyblock; un; un = un->next ) { if( un->pkt->pkttype != PKT_USER_ID ) continue; - if ( un->pkt->pkt.user_id->is_revoked ) - continue; - if ( un->pkt->pkt.user_id->is_expired ) - continue; + if((un->pkt->pkt.user_id->is_revoked + || un->pkt->pkt.user_id->is_expired) + && !(opt.verify_options&VERIFY_SHOW_UNUSABLE_UIDS)) + continue; /* Only skip textual primaries */ if ( un->pkt->pkt.user_id->is_primary && !un->pkt->pkt.user_id->attrib_data ) @@ -1451,41 +1743,53 @@ check_sig_and_print( CTX c, KBNODE node ) un->pkt->pkt.user_id->numattribs,pk,NULL); } - log_info( _(" aka \"")); - print_utf8_string( log_get_stream(), un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len ); - if(opt.verify_options&VERIFY_SHOW_VALIDITY) - fprintf (log_get_stream(), "\" [%s]\n", - trust_value_to_string(get_validity(pk, - un->pkt-> - pkt.user_id))); + p=utf8_to_native(un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len,0); + log_info(_(" aka \"%s\""),p); + xfree(p); + + if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY) + { + const char *valid; + if(un->pkt->pkt.user_id->is_revoked) + valid=_("revoked"); + else if(un->pkt->pkt.user_id->is_expired) + valid=_("expired"); + else + valid=trust_value_to_string(get_validity(pk, + un->pkt-> + pkt.user_id)); + fprintf(log_get_stream()," [%s]\n",valid); + } else - fputs("\"\n", log_get_stream() ); + fputs("\n", log_get_stream() ); } } release_kbnode( keyblock ); if( !rc ) { - if(opt.verify_options&VERIFY_SHOW_POLICY) + if(opt.verify_options&VERIFY_SHOW_POLICY_URLS) show_policy_url(sig,0,1); else show_policy_url(sig,0,2); - if(opt.verify_options&VERIFY_SHOW_KEYSERVER) + if(opt.verify_options&VERIFY_SHOW_KEYSERVER_URLS) show_keyserver_url(sig,0,1); else show_keyserver_url(sig,0,2); - if(opt.verify_options&VERIFY_SHOW_NOTATION) - show_notation(sig,0,1); + if(opt.verify_options&VERIFY_SHOW_NOTATIONS) + show_notation(sig,0,1, + ((opt.verify_options&VERIFY_SHOW_STD_NOTATIONS)?1:0)+ + ((opt.verify_options&VERIFY_SHOW_USER_NOTATIONS)?2:0)); else - show_notation(sig,0,2); - } + show_notation(sig,0,2,0); + } if( !rc && is_status_enabled() ) { /* print a status response with the fingerprint */ - PKT_public_key *vpk = xcalloc (1, sizeof *vpk ); + PKT_public_key *vpk = xmalloc_clear( sizeof *vpk ); if( !get_pubkey( vpk, sig->keyid ) ) { byte array[MAX_FINGERPRINT_LEN], *p; @@ -1513,7 +1817,7 @@ check_sig_and_print( CTX c, KBNODE node ) akid[0] = vpk->main_keyid[0]; akid[1] = vpk->main_keyid[1]; free_public_key (vpk); - vpk = xcalloc (1, sizeof *vpk ); + vpk = xmalloc_clear( sizeof *vpk ); if (get_pubkey (vpk, akid)) { /* impossible error, we simply return a zeroed out fpr */ n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; @@ -1530,14 +1834,18 @@ check_sig_and_print( CTX c, KBNODE node ) free_public_key( vpk ); } - if( !rc ) + if (!rc) + { + if(opt.verify_options&VERIFY_PKA_LOOKUPS) + pka_uri_from_sig (sig); /* Make sure PKA info is available. */ rc = check_signatures_trust( sig ); + } if(sig->flags.expired) { log_info(_("Signature expired %s\n"), asctimestamp(sig->expiredate)); - rc=GPG_ERR_GENERAL; /* need a better error here? */ + rc=G10ERR_GENERAL; /* need a better error here? */ } else if(sig->expiredate) log_info(_("Signature expires %s\n"),asctimestamp(sig->expiredate)); @@ -1553,19 +1861,19 @@ check_sig_and_print( CTX c, KBNODE node ) if( opt.batch && rc ) g10_exit(1); } - else { + else { char buf[50]; sprintf(buf, "%08lX%08lX %d %d %02x %lu %d", (ulong)sig->keyid[0], (ulong)sig->keyid[1], sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp, rc ); write_status_text( STATUS_ERRSIG, buf ); - if( gpg_err_code (rc) == GPG_ERR_NO_PUBKEY ) { + if( rc == G10ERR_NO_PUBKEY ) { buf[16] = 0; write_status_text( STATUS_NO_PUBKEY, buf ); } - if( rc != GPG_ERR_NOT_PROCESSED ) - log_error(_("Can't check signature: %s\n"), gpg_strerror (rc) ); + if( rc != G10ERR_NOT_PROCESSED ) + log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); } return rc; } @@ -1595,7 +1903,6 @@ proc_tree( CTX c, KBNODE node ) if (!node) return; - c->local_id = 0; c->trustletter = ' '; if( node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { @@ -1611,12 +1918,16 @@ proc_tree( CTX c, KBNODE node ) if( !c->have_data ) { free_md_filter_context( &c->mfx ); /* prepare to create all requested message digests */ - gcry_md_open (&c->mfx.md, 0, 0); - - /* fixme: why looking for the signature packet and not 1passpacket*/ - for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { - gcry_md_enable ( c->mfx.md, n1->pkt->pkt.signature->digest_algo); - } + if (gcry_md_open (&c->mfx.md, 0, 0)) + BUG (); + + /* fixme: why looking for the signature packet and not the + one-pass packet? */ + for ( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) + { + gcry_md_enable (c->mfx.md, + n1->pkt->pkt.signature->digest_algo); + } /* ask for file and hash it */ if( c->sigs_only ) { rc = hash_datafiles( c->mfx.md, NULL, @@ -1629,7 +1940,7 @@ proc_tree( CTX c, KBNODE node ) n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 ); } if( rc ) { - log_error("can't hash datafile: %s\n", gpg_strerror (rc)); + log_error("can't hash datafile: %s\n", g10_errstr(rc)); return; } } @@ -1690,20 +2001,24 @@ proc_tree( CTX c, KBNODE node ) else if( !c->have_data ) { /* detached signature */ free_md_filter_context( &c->mfx ); - gcry_md_open (&c->mfx.md, sig->digest_algo, 0); + if (gcry_md_open (&c->mfx.md, sig->digest_algo, 0)) + BUG (): + if( !opt.pgp2_workarounds ) ; else if( sig->digest_algo == DIGEST_ALGO_MD5 && is_RSA( sig->pubkey_algo ) ) { /* enable a workaround for a pgp2 bug */ - gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0 ); + if (gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0)) + BUG (): } else if( sig->digest_algo == DIGEST_ALGO_SHA1 && sig->pubkey_algo == PUBKEY_ALGO_DSA && sig->sig_class == 0x01 ) { /* enable the workaround also for pgp5 when the detached * signature has been created in textmode */ - gcry_md_open (&c->mfx.md2, sig->digest_algo, 0 ); + if (gcry_md_open (&c->mfx.md2, sig->digest_algo, 0 )) + BUG (); } #if 0 /* workaround disabled */ /* Here we have another hack to work around a pgp 2 bug @@ -1716,9 +2031,9 @@ proc_tree( CTX c, KBNODE node ) /* c->mfx.md2? 0 :(sig->sig_class == 0x01) */ #endif if ( DBG_HASHING ) { - gcry_md_start_debug ( c->mfx.md, "verify" ); + gcry_md_start_debug( c->mfx.md, "verify" ); if ( c->mfx.md2 ) - gcry_md_start_debug ( c->mfx.md2, "verify2" ); + gcry_md_start_debug( c->mfx.md2, "verify2" ); } if( c->sigs_only ) { rc = hash_datafiles( c->mfx.md, c->mfx.md2, @@ -1731,7 +2046,7 @@ proc_tree( CTX c, KBNODE node ) (sig->sig_class == 0x01) ); } if( rc ) { - log_error("can't hash datafile: %s\n", gpg_strerror (rc)); + log_error("can't hash datafile: %s\n", g10_errstr(rc)); return; } } @@ -1739,8 +2054,6 @@ proc_tree( CTX c, KBNODE node ) log_error (_("not a detached signature\n") ); return; } - else if ( c->pipemode.op == 'B' ) - ; /* this is a detached signature trough the pipemode handler */ else if (!opt.quiet) log_info(_("old style (PGP 2.x) signature\n")); diff --git a/g10/mdfilter.c b/g10/mdfilter.c index b58189146..06aa8386c 100644 --- a/g10/mdfilter.c +++ b/g10/mdfilter.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,9 +26,9 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "errors.h" #include "iobuf.h" -#include "memory.h" #include "util.h" #include "filter.h" @@ -38,7 +39,7 @@ */ int md_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; md_filter_context_t *mfx = opaque; @@ -67,8 +68,8 @@ md_filter( void *opaque, int control, void free_md_filter_context( md_filter_context_t *mfx ) { - gcry_md_close (mfx->md); - gcry_md_close (mfx->md2); + gcry_md_close(mfx->md); + gcry_md_close(mfx->md2); mfx->md = NULL; mfx->md2 = NULL; mfx->maxbuf_size = 0; diff --git a/g10/misc.c b/g10/misc.c index a0599f304..a26aa740d 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1,6 +1,6 @@ -/* misc.c - miscellaneous functions - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. +/* misc.c - miscellaneous functions + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,7 +26,6 @@ #include <string.h> #include <unistd.h> #include <errno.h> -#include <assert.h> #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 #include <asm/sysinfo.h> #include <asm/unistd.h> @@ -35,15 +35,51 @@ #include <sys/time.h> #include <sys/resource.h> #endif +#ifdef ENABLE_SELINUX_HACKS +#include <sys/stat.h> +#endif + +#ifdef HAVE_W32_SYSTEM +#include <time.h> +#include <process.h> +#include <windows.h> +#include <shlobj.h> +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a +#endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_FLAG_CREATE +#define CSIDL_FLAG_CREATE 0x8000 +#endif +#endif /*HAVE_W32_SYSTEM*/ #include "gpg.h" +#ifdef HAVE_W32_SYSTEM +# include "errors.h" +# include "dynload.h" +#endif /*HAVE_W32_SYSTEM*/ #include "util.h" #include "main.h" #include "photoid.h" #include "options.h" #include "i18n.h" -#define MAX_EXTERN_MPI_BITS 16384 + + +#ifdef ENABLE_SELINUX_HACKS +/* A object and a global variable to keep track of files marked as + secured. */ +struct secured_file_item +{ + struct secured_file_item *next; + ino_t ino; + dev_t dev; +}; +static struct secured_file_item *secured_files; +#endif /*ENABLE_SELINUX_HACKS*/ + #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 @@ -92,6 +128,135 @@ disable_core_dumps() } +/* For the sake of SELinux we want to restrict access through gpg to + certain files we keep under our own control. This function + registers such a file and is_secured_file may then be used to + check whether a file has ben registered as secured. */ +void +register_secured_file (const char *fname) +{ +#ifdef ENABLE_SELINUX_HACKS + struct stat buf; + struct secured_file_item *sf; + + /* Note that we stop immediatley if something goes wrong here. */ + if (stat (fname, &buf)) + log_fatal (_("fstat of `%s' failed in %s: %s\n"), fname, + "register_secured_file", strerror (errno)); +/* log_debug ("registering `%s' i=%lu.%lu\n", fname, */ +/* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ + for (sf=secured_files; sf; sf = sf->next) + { + if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) + return; /* Already registered. */ + } + + sf = xmalloc (sizeof *sf); + sf->ino = buf.st_ino; + sf->dev = buf.st_dev; + sf->next = secured_files; + secured_files = sf; +#endif /*ENABLE_SELINUX_HACKS*/ +} + +/* Remove a file registered as secure. */ +void +unregister_secured_file (const char *fname) +{ +#ifdef ENABLE_SELINUX_HACKS + struct stat buf; + struct secured_file_item *sf, *sfprev; + + if (stat (fname, &buf)) + { + log_error (_("fstat of `%s' failed in %s: %s\n"), fname, + "unregister_secured_file", strerror (errno)); + return; + } +/* log_debug ("unregistering `%s' i=%lu.%lu\n", fname, */ +/* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ + for (sfprev=NULL,sf=secured_files; sf; sfprev=sf, sf = sf->next) + { + if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) + { + if (sfprev) + sfprev->next = sf->next; + else + secured_files = sf->next; + xfree (sf); + return; + } + } +#endif /*ENABLE_SELINUX_HACKS*/ +} + +/* Return true if FD is corresponds to a secured file. Using -1 for + FS is allowed and will return false. */ +int +is_secured_file (int fd) +{ +#ifdef ENABLE_SELINUX_HACKS + struct stat buf; + struct secured_file_item *sf; + + if (fd == -1) + return 0; /* No file descriptor so it can't be secured either. */ + + /* Note that we print out a error here and claim that a file is + secure if something went wrong. */ + if (fstat (fd, &buf)) + { + log_error (_("fstat(%d) failed in %s: %s\n"), fd, + "is_secured_file", strerror (errno)); + return 1; + } +/* log_debug ("is_secured_file (%d) i=%lu.%lu\n", fd, */ +/* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ + for (sf=secured_files; sf; sf = sf->next) + { + if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) + return 1; /* Yes. */ + } +#endif /*ENABLE_SELINUX_HACKS*/ + return 0; /* No. */ +} + +/* Return true if FNAME is corresponds to a secured file. Using NULL, + "" or "-" for FS is allowed and will return false. This function is + used before creating a file, thus it won't fail if the file does + not exist. */ +int +is_secured_filename (const char *fname) +{ +#ifdef ENABLE_SELINUX_HACKS + struct stat buf; + struct secured_file_item *sf; + + if (iobuf_is_pipe_filename (fname) || !*fname) + return 0; + + /* Note that we print out a error here and claim that a file is + secure if something went wrong. */ + if (stat (fname, &buf)) + { + if (errno == ENOENT || errno == EPERM || errno == EACCES) + return 0; + log_error (_("fstat of `%s' failed in %s: %s\n"), fname, + "is_secured_filename", strerror (errno)); + return 1; + } +/* log_debug ("is_secured_filename (%s) i=%lu.%lu\n", fname, */ +/* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ + for (sf=secured_files; sf; sf = sf->next) + { + if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) + return 1; /* Yes. */ + } +#endif /*ENABLE_SELINUX_HACKS*/ + return 0; /* No. */ +} + + u16 checksum_u16( unsigned n ) @@ -115,25 +280,26 @@ checksum( byte *p, unsigned n ) } u16 -checksum_mpi( gcry_mpi_t a ) +checksum_mpi (gcry_mpi_t a) { - int rc; u16 csum; byte *buffer; - size_t nbytes; + unsigned int nbytes; + unsigned int nbits; - rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a ); - if (rc) + if ( gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a) ) BUG (); - /* fixme: for numbers not in secure memory we should use a stack - * based buffer and only allocate a larger one if mpi_print return - * an error */ - buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes):gcry_xmalloc(nbytes); - rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a ); - if (rc) + /* Fixme: For numbers not in secure memory we should use a stack + * based buffer and only allocate a larger one if mpi_print returns + * an error. */ + buffer = (gcry_is_secure(a)? + gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes)); + if ( gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a) ) BUG (); - csum = checksum (buffer, nbytes ); - xfree (buffer ); + nbits = gcry_mpi_get_nbits (a); + csum = checksum_u16 (nbits); + csum += checksum (buffer, nbytes); + xfree (buffer); return csum; } @@ -148,46 +314,32 @@ buffer_to_u32( const byte *buffer ) return a; } - -static void -no_exp_algo(void) -{ - static int did_note = 0; - - if( !did_note ) { - did_note = 1; - log_info(_("Experimental algorithms should not be used!\n")); - } -} - void print_pubkey_algo_note( int algo ) { - if( algo >= 100 && algo <= 110 ) - no_exp_algo(); + if(algo >= 100 && algo <= 110) + { + static int warn=0; + if(!warn) + { + warn=1; + log_info (_("WARNING: using experimental public key algorithm %s\n"), + gcry_pk_algo_name (algo)); + } + } } void print_cipher_algo_note( int algo ) { - if( algo >= 100 && algo <= 110 ) - no_exp_algo(); - else if( algo == CIPHER_ALGO_3DES - || algo == CIPHER_ALGO_CAST5 - || algo == CIPHER_ALGO_BLOWFISH - || algo == CIPHER_ALGO_TWOFISH - || algo == CIPHER_ALGO_RIJNDAEL - || algo == CIPHER_ALGO_RIJNDAEL192 - || algo == CIPHER_ALGO_RIJNDAEL256 - ) - ; - else { - static int did_note = 0; - - if( !did_note ) { - did_note = 1; - log_info(_("this cipher algorithm is deprecated; " - "please use a more standard one!\n")); + if(algo >= 100 && algo <= 110) + { + static int warn=0; + if(!warn) + { + warn=1; + log_info (_("WARNING: using experimental cipher algorithm %s\n"), + gcry_cipher_algo_name (algo)); } } } @@ -195,63 +347,81 @@ print_cipher_algo_note( int algo ) void print_digest_algo_note( int algo ) { - if( algo >= 100 && algo <= 110 ) - no_exp_algo(); + if(algo >= 100 && algo <= 110) + { + static int warn=0; + if(!warn) + { + warn=1; + log_info (_("WARNING: using experimental digest algorithm %s\n"), + gcry_md_algo_name (algo)); + } + } + else if(algo==DIGEST_ALGO_MD5) + log_info (_("WARNING: digest algorithm %s is deprecated\n"), + gcry_md_algo_name (algo)); } - /* 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 ); + 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; + /* Although 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 takes place. + * Of course, we could 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; + *rlen = sizeof(marker); + return marker; } /**************** - * Wrapper around the libgcrypt function with addional checks on - * openPGP contraints for the algo ID. + * Wrapper around the libgcrypt function with additonal checks on + * the OpenPGP contraints for the algo ID. */ int openpgp_cipher_test_algo( int algo ) { - if( algo < 0 || algo > 110 ) - return GPG_ERR_CIPHER_ALGO; - return gcry_cipher_test_algo (algo); + if ( algo < 0 || algo > 110 ) + return gpg_error (GPG_ERR_CIPHER_ALGO); + return gcry_cipher_test_algo (algo); } int -openpgp_pk_test_algo( int algo, unsigned int usage_flags ) +openpgp_pk_test_algo( int algo ) { - size_t value = usage_flags; + if (algo == GCRY_PK_ELG_E) + algo = GCRY_PK_ELG; + if (algo < 0 || algo > 110) + return gpg_error (GPG_ERR_PUBKEY_ALGO); + return gcry_pk_test_algo (algo); +} + +int +openpgp_pk_test_algo2( int algo, unsigned int use ) +{ if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; -#ifdef __GNUC__ -#warning need to handle the usage here? -#endif + if (algo < 0 || algo > 110) - return GPG_ERR_PUBKEY_ALGO; - return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &value); + return gpg_error (GPG_ERR_PUBKEY_ALGO); + return gcry_pk_test_algo2 (algo, use); } int @@ -259,25 +429,23 @@ openpgp_pk_algo_usage ( int algo ) { int use = 0; - /* they are hardwired in gpg 1.0 */ + /* They are hardwired in gpg 1.0. */ switch ( algo ) { case PUBKEY_ALGO_RSA: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH; + use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG + | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH); break; case PUBKEY_ALGO_RSA_E: use = PUBKEY_USAGE_ENC; break; case PUBKEY_ALGO_RSA_S: - use = PUBKEY_USAGE_SIG; + use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG; break; case PUBKEY_ALGO_ELGAMAL_E: use = PUBKEY_USAGE_ENC; break; case PUBKEY_ALGO_DSA: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; - break; - case PUBKEY_ALGO_ELGAMAL: - use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH; + use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; break; default: break; @@ -288,54 +456,9 @@ openpgp_pk_algo_usage ( int algo ) int openpgp_md_test_algo( int algo ) { - if( algo < 0 || algo > 110 ) - return GPG_ERR_DIGEST_ALGO; - return gcry_md_test_algo (algo); -} - -int -openpgp_md_map_name (const char *string) -{ - int i = gcry_md_map_name (string); - - if (!i && (string[0]=='H' || string[0]=='h')) - { /* Didn't find it, so try the Hx format */ - long val; - char *endptr; - - string++; - - val=strtol(string,&endptr,10); - if (*string!='\0' && *endptr=='\0' && !openpgp_md_test_algo(val)) - i = val; - } - return i < 0 || i > 110? 0 : i; -} - -int -openpgp_cipher_map_name (const char *string) -{ - int i = gcry_cipher_map_name (string); - - if (!i && (string[0]=='S' || string[0]=='s')) - { /* Didn't find it, so try the Sx format */ - long val; - char *endptr; - - string++; - - val=strtol(string,&endptr,10); - if (*string!='\0' && *endptr=='\0' && !openpgp_cipher_test_algo(val)) - i = val; - } - return i < 0 || i > 110? 0 : i; -} - -int -openpgp_pk_map_name (const char *string) -{ - int i = gcry_pk_map_name (string); - return i < 0 || i > 110? 0 : i; + if (algo < 0 || algo > 110) + return gpg_error (GPG_ERR_DIGEST_ALGO); + return gcry_md_test_algo (algo); } #ifdef USE_IDEA @@ -348,14 +471,30 @@ idea_cipher_warn(int show) if(!warned || show) { log_info(_("the IDEA cipher plugin is not present\n")); - log_info(_("please see http://www.gnupg.org/why-not-idea.html " - "for more information\n")); + log_info(_("please see %s for more information\n"), + "http://www.gnupg.org/faq/why-not-idea.html"); warned=1; } } #endif -/* Expand %-strings. Returns a string which must be m_freed. Returns +static unsigned long get_signature_count(PKT_secret_key *sk) +{ +#ifdef ENABLE_CARD_SUPPORT + if(sk && sk->is_protected && sk->protect.s2k.mode==1002) + { + struct agent_card_info_s info; + if(agent_scd_getattr("SIG-COUNTER",&info)==0) + return info.sig_counter; + } +#endif + + /* How to do this without a card? */ + + return 0; +} + +/* Expand %-strings. Returns a string which must be xfreed. Returns NULL if the string cannot be expanded (too large). */ char * pct_expando(const char *string,struct expando_args *args) @@ -387,7 +526,7 @@ pct_expando(const char *string,struct expando_args *args) goto fail; maxlen+=1024; - ret= xrealloc(ret,maxlen); + ret=xrealloc(ret,maxlen); } done=0; @@ -434,6 +573,15 @@ pct_expando(const char *string,struct expando_args *args) } break; + case 'c': /* signature count from card, if any. */ + if(idx+10<maxlen) + { + sprintf(&ret[idx],"%lu",get_signature_count(args->sk)); + idx+=strlen(&ret[idx]); + done=1; + } + break; + case 'p': /* primary pk fingerprint of a sk */ case 'f': /* pk fingerprint */ case 'g': /* sk fingerprint */ @@ -442,13 +590,14 @@ pct_expando(const char *string,struct expando_args *args) size_t len; int i; - if( ch[1]=='p' && args->sk) + if((*(ch+1))=='p' && args->sk) { if(args->sk->is_primary) fingerprint_from_sk(args->sk,array,&len); else if(args->sk->main_keyid[0] || args->sk->main_keyid[1]) { - PKT_public_key *pk= xcalloc(1, sizeof(PKT_public_key)); + PKT_public_key *pk= + xmalloc_clear(sizeof(PKT_public_key)); if(get_pubkey_fast(pk,args->sk->main_keyid)==0) fingerprint_from_pk(pk,array,&len); @@ -459,12 +608,12 @@ pct_expando(const char *string,struct expando_args *args) else memset(array,0,(len=MAX_FINGERPRINT_LEN)); } - else if( ch[1]=='f' && args->pk) + else if((*(ch+1))=='f' && args->pk) fingerprint_from_pk(args->pk,array,&len); - else if( ch[1]=='g' && args->sk) + else if((*(ch+1))=='g' && args->sk) fingerprint_from_sk(args->sk,array,&len); else - memset(array, 0, (len=MAX_FINGERPRINT_LEN)); + memset(array,0,(len=MAX_FINGERPRINT_LEN)); if(idx+(len*2)<maxlen) { @@ -539,35 +688,10 @@ pct_expando(const char *string,struct expando_args *args) return ret; fail: - xfree (ret); + xfree(ret); return NULL; } -int -hextobyte( const char *s ) -{ - int c; - - if( *s >= '0' && *s <= '9' ) - c = 16 * (*s - '0'); - else if( *s >= 'A' && *s <= 'F' ) - c = 16 * (10 + *s - 'A'); - else if( *s >= 'a' && *s <= 'f' ) - c = 16 * (10 + *s - 'a'); - else - return -1; - s++; - if( *s >= '0' && *s <= '9' ) - c += *s - '0'; - else if( *s >= 'A' && *s <= 'F' ) - c += 10 + *s - 'A'; - else if( *s >= 'a' && *s <= 'f' ) - c += 10 + *s - 'a'; - else - return -1; - return c; -} - void deprecated_warning(const char *configname,unsigned int configlineno, const char *option,const char *repl1,const char *repl2) @@ -589,24 +713,39 @@ deprecated_warning(const char *configname,unsigned int configlineno, log_info(_("please use \"%s%s\" instead\n"),repl1,repl2); } + +void +deprecated_command (const char *name) +{ + log_info(_("WARNING: \"%s\" is a deprecated command - do not use it\n"), + name); +} + + const char * compress_algo_to_string(int algo) { - const char *s="?"; + const char *s=NULL; switch(algo) { - case 0: - s="Uncompressed"; + case COMPRESS_ALGO_NONE: + s=_("Uncompressed"); break; - case 1: + case COMPRESS_ALGO_ZIP: s="ZIP"; break; - case 2: + case COMPRESS_ALGO_ZLIB: s="ZLIB"; break; + +#ifdef HAVE_BZIP2 + case COMPRESS_ALGO_BZIP2: + s="BZIP2"; + break; +#endif } return s; @@ -615,18 +754,31 @@ compress_algo_to_string(int algo) int string_to_compress_algo(const char *string) { - if(ascii_strcasecmp(string,"uncompressed")==0) + /* NOTE TO TRANSLATOR: See doc/TRANSLATE about this string. */ + if(match_multistr(_("uncompressed|none"),string)) + return 0; + else if(ascii_strcasecmp(string,"uncompressed")==0) + return 0; + else if(ascii_strcasecmp(string,"none")==0) return 0; else if(ascii_strcasecmp(string,"zip")==0) return 1; else if(ascii_strcasecmp(string,"zlib")==0) return 2; +#ifdef HAVE_BZIP2 + else if(ascii_strcasecmp(string,"bzip2")==0) + return 3; +#endif else if(ascii_strcasecmp(string,"z0")==0) return 0; else if(ascii_strcasecmp(string,"z1")==0) return 1; else if(ascii_strcasecmp(string,"z2")==0) return 2; +#ifdef HAVE_BZIP2 + else if(ascii_strcasecmp(string,"z3")==0) + return 3; +#endif else return -1; } @@ -634,10 +786,15 @@ string_to_compress_algo(const char *string) int check_compress_algo(int algo) { +#ifdef HAVE_BZIP2 + if(algo>=0 && algo<=3) + return 0; +#else if(algo>=0 && algo<=2) return 0; +#endif - return GPG_ERR_COMPR_ALGO; + return G10ERR_COMPR_ALGO; } int @@ -652,13 +809,13 @@ default_cipher_algo(void) } /* There is no default_digest_algo function, but see - sign.c:hash_for */ + sign.c:hash_for() */ int default_compress_algo(void) { - if(opt.def_compress_algo!=-1) - return opt.def_compress_algo; + if(opt.compress_algo!=-1) + return opt.compress_algo; else if(opt.personal_compress_prefs) return opt.personal_compress_prefs[0].value; else @@ -712,14 +869,151 @@ compliance_failure(void) opt.compliance=CO_GNUPG; } +/* Break a string into successive option pieces. Accepts single word + options and key=value argument options. */ +char * +optsep(char **stringp) +{ + char *tok,*end; + + tok=*stringp; + if(tok) + { + end=strpbrk(tok," ,="); + if(end) + { + int sawequals=0; + char *ptr=end; + + /* what we need to do now is scan along starting with *end, + If the next character we see (ignoring spaces) is an = + sign, then there is an argument. */ + + while(*ptr) + { + if(*ptr=='=') + sawequals=1; + else if(*ptr!=' ') + break; + ptr++; + } + + /* There is an argument, so grab that too. At this point, + ptr points to the first character of the argument. */ + if(sawequals) + { + /* Is it a quoted argument? */ + if(*ptr=='"') + { + ptr++; + end=strchr(ptr,'"'); + if(end) + end++; + } + else + end=strpbrk(ptr," ,"); + } + + if(end && *end) + { + *end='\0'; + *stringp=end+1; + } + else + *stringp=NULL; + } + else + *stringp=NULL; + } + + return tok; +} + +/* Breaks an option value into key and value. Returns NULL if there + is no value. Note that "string" is modified to remove the =value + part. */ +char * +argsplit(char *string) +{ + char *equals,*arg=NULL; + + equals=strchr(string,'='); + if(equals) + { + char *quote,*space; + + *equals='\0'; + arg=equals+1; + + /* Quoted arg? */ + quote=strchr(arg,'"'); + if(quote) + { + arg=quote+1; + + quote=strchr(arg,'"'); + if(quote) + *quote='\0'; + } + else + { + size_t spaces; + + /* Trim leading spaces off of the arg */ + spaces=strspn(arg," "); + arg+=spaces; + } + + /* Trim tailing spaces off of the tag */ + space=strchr(string,' '); + if(space) + *space='\0'; + } + + return arg; +} + +/* Return the length of the initial token, leaving off any + argument. */ +static size_t +optlen(const char *s) +{ + char *end=strpbrk(s," ="); + + if(end) + return end-s; + else + return strlen(s); +} + int -parse_options(char *str,unsigned int *options,struct parse_options *opts) +parse_options(char *str,unsigned int *options, + struct parse_options *opts,int noisy) { char *tok; - while((tok=strsep(&str," ,"))) + if (str && !strcmp (str, "help")) + { + int i,maxlen=0; + + /* Figure out the longest option name so we can line these up + neatly. */ + for(i=0;opts[i].name;i++) + if(opts[i].help && maxlen<strlen(opts[i].name)) + maxlen=strlen(opts[i].name); + + for(i=0;opts[i].name;i++) + if(opts[i].help) + printf("%s%*s%s\n",opts[i].name, + maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help)); + + g10_exit(0); + } + + while((tok=optsep(&str))) { int i,rev=0; + char *otok=tok; if(tok[0]=='\0') continue; @@ -732,25 +1026,248 @@ parse_options(char *str,unsigned int *options,struct parse_options *opts) for(i=0;opts[i].name;i++) { - if(ascii_strcasecmp(opts[i].name,tok)==0) + size_t toklen=optlen(tok); + + if(ascii_strncasecmp(opts[i].name,tok,toklen)==0) { + /* We have a match, but it might be incomplete */ + if(toklen!=strlen(opts[i].name)) + { + int j; + + for(j=i+1;opts[j].name;j++) + { + if(ascii_strncasecmp(opts[j].name,tok,toklen)==0) + { + if(noisy) + log_info(_("ambiguous option `%s'\n"),otok); + return 0; + } + } + } + if(rev) - *options&=~opts[i].bit; + { + *options&=~opts[i].bit; + if(opts[i].value) + *opts[i].value=NULL; + } else - *options|=opts[i].bit; + { + *options|=opts[i].bit; + if(opts[i].value) + *opts[i].value=argsplit(tok); + } break; } } if(!opts[i].name) - return 0; + { + if(noisy) + log_info(_("unknown option `%s'\n"),otok); + return 0; + } } return 1; } +/* 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. */ +char * +unescape_percent_string (const unsigned char *s) +{ + char *buffer, *d; + + buffer = d = xmalloc (strlen (s)+1); + 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; +} + + +int +has_invalid_email_chars (const char *s) +{ + int at_seen=0; + const char *valid_chars= + "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + for ( ; *s; s++ ) + { + if ( *s & 0x80 ) + return 1; + if ( *s == '@' ) + at_seen=1; + else if ( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) ) + return 1; + else if ( at_seen && !strchr( valid_chars, *s ) ) + return 1; + } + return 0; +} + +/* Check whether NAME represents a valid mailbox according to + RFC822. Returns true if so. */ +int +is_valid_mailbox (const char *name) +{ + return !( !name + || !*name + || has_invalid_email_chars (name) + || string_count_chr (name,'@') != 1 + || *name == '@' + || name[strlen(name)-1] == '@' + || name[strlen(name)-1] == '.' + || strstr (name, "..") ); +} + + +/* This is a helper function to load a Windows function from either of + one DLLs. */ +#ifdef HAVE_W32_SYSTEM +static HRESULT +w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) +{ + static int initialized; + static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR); + + if (!initialized) + { + static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL }; + void *handle; + int i; + + initialized = 1; + + for (i=0, handle = NULL; !handle && dllnames[i]; i++) + { + handle = dlopen (dllnames[i], RTLD_LAZY); + if (handle) + { + func = dlsym (handle, "SHGetFolderPathA"); + if (!func) + { + dlclose (handle); + handle = NULL; + } + } + } + } + + if (func) + return func (a,b,c,d,e); + else + return -1; +} +#endif /*HAVE_W32_SYSTEM*/ + + +/* Return the name of the libexec directory. The name is allocated in + a static area on the first use. This function won't fail. */ +const char * +get_libexecdir (void) +{ +#ifdef HAVE_W32_SYSTEM + static int got_dir; + static char dir[MAX_PATH+5]; + + if (!got_dir) + { + char *p; + + if ( !GetModuleFileName ( NULL, dir, MAX_PATH) ) + { + log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0)); + *dir = 0; + } + got_dir = 1; + p = strrchr (dir, DIRSEP_C); + if (p) + *p = 0; + else + { + log_debug ("bad filename `%s' returned for this process\n", dir); + *dir = 0; + } + } + + if (*dir) + return dir; + /* Fallback to the hardwired value. */ +#endif /*HAVE_W32_SYSTEM*/ + + return GNUPG_LIBEXECDIR; +} + +/* Similar to access(2), but uses PATH to find the file. */ +int +path_access(const char *file,int mode) +{ + char *envpath; + int ret=-1; + + envpath=getenv("PATH"); + + if(!envpath +#ifdef HAVE_DRIVE_LETTERS + || (((file[0]>='A' && file[0]<='Z') + || (file[0]>='a' && file[0]<='z')) + && file[1]==':') +#else + || file[0]=='/' +#endif + ) + return access(file,mode); + else + { + /* At least as large as, but most often larger than we need. */ + char *buffer=xmalloc(strlen(envpath)+1+strlen(file)+1); + char *split,*item,*path=xstrdup(envpath); + + split=path; + + while((item=strsep(&split,PATHSEP_S))) + { + strcpy(buffer,item); + strcat(buffer,"/"); + strcat(buffer,file); + ret=access(buffer,mode); + if(ret==0) + break; + } + + xfree(path); + xfree(buffer); + } + + return ret; +} + + + /* Temporary helper. */ int pubkey_get_npkey( int algo ) @@ -837,141 +1354,9 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) return nbits; } - -/* MPI helper functions. */ - - -/**************** - * write an mpi to out. - */ -int -mpi_write( iobuf_t out, gcry_mpi_t a ) -{ - char buffer[(MAX_EXTERN_MPI_BITS+7)/8]; - size_t nbytes; - int rc; - - nbytes = (MAX_EXTERN_MPI_BITS+7)/8; - rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); - if( !rc ) - rc = iobuf_write( out, buffer, nbytes ); - - return rc; -} - -/**************** - * Writyeg a MPI to out, but in this case it is an opaque one, - * s used vor v3 protected keys. - */ -int -mpi_write_opaque( iobuf_t out, gcry_mpi_t a ) -{ - size_t nbytes, nbits; - int rc; - char *p; - - assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) ); - p = gcry_mpi_get_opaque( a, &nbits ); - nbytes = (nbits+7) / 8; - iobuf_put( out, nbits >> 8 ); - iobuf_put( out, nbits ); - rc = iobuf_write( out, p, nbytes ); - return rc; -} - - -/**************** - * Read an external representation of an mpi and return the MPI - * The external format is a 16 bit unsigned value stored in network byte order, - * giving the number of bits for the following integer. The integer is stored - * with MSB first (left padded with zeroes to align on a byte boundary). - */ -gcry_mpi_t -mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure) -{ - int c, c1, c2, i; - unsigned int nbits, nbytes, nread=0; - gcry_mpi_t a = NULL; - byte *buf = NULL; - byte *p; - - if( (c = c1 = iobuf_get(inp)) == -1 ) - goto leave; - nbits = c << 8; - if( (c = c2 = iobuf_get(inp)) == -1 ) - goto leave; - nbits |= c; - if( nbits > MAX_EXTERN_MPI_BITS ) { - log_error("mpi too large (%u bits)\n", nbits); - goto leave; - } - nread = 2; - nbytes = (nbits+7) / 8; - buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 ); - p = buf; - p[0] = c1; - p[1] = c2; - for( i=0 ; i < nbytes; i++ ) { - p[i+2] = iobuf_get(inp) & 0xff; - nread++; - } - nread += nbytes; - if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) ) - a = NULL; - - leave: - gcry_free(buf); - if( nread > *ret_nread ) - log_bug("mpi larger than packet"); - else - *ret_nread = nread; - return a; -} - -/**************** - * Same as mpi_read but the value is stored as an opaque MPI. - * This function is used to read encrypted MPI of v3 packets. - */ -gcry_mpi_t -mpi_read_opaque(iobuf_t inp, unsigned *ret_nread ) -{ - int c, c1, c2, i; - unsigned nbits, nbytes, nread=0; - gcry_mpi_t a = NULL; - byte *buf = NULL; - byte *p; - - if( (c = c1 = iobuf_get(inp)) == -1 ) - goto leave; - nbits = c << 8; - if( (c = c2 = iobuf_get(inp)) == -1 ) - goto leave; - nbits |= c; - if( nbits > MAX_EXTERN_MPI_BITS ) { - log_error("mpi too large (%u bits)\n", nbits); - goto leave; - } - nread = 2; - nbytes = (nbits+7) / 8; - buf = gcry_xmalloc( nbytes ); - p = buf; - for( i=0 ; i < nbytes; i++ ) { - p[i] = iobuf_get(inp) & 0xff; - } - nread += nbytes; - a = gcry_mpi_set_opaque(NULL, buf, nbits ); - buf = NULL; - - leave: - gcry_free(buf); - if( nread > *ret_nread ) - log_bug("mpi larger than packet"); - else - *ret_nread = nread; - return a; -} +/* FIXME: Use gcry_mpi_print directly. */ int mpi_print( FILE *fp, gcry_mpi_t a, int mode ) { @@ -985,11 +1370,10 @@ mpi_print( FILE *fp, gcry_mpi_t a, int mode ) n += fprintf(fp, "[%u bits]", n1); } else { - int rc; - char *buffer; + unsigned char *buffer; - rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, &buffer, NULL, a ); - assert( !rc ); + if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a)) + BUG (); fputs( buffer, fp ); n += strlen(buffer); gcry_free( buffer ); @@ -997,4 +1381,3 @@ mpi_print( FILE *fp, gcry_mpi_t a, int mode ) return n; } - diff --git a/g10/openfile.c b/g10/openfile.c index faf9a2cd6..8c0601c3e 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -1,5 +1,6 @@ /* openfile.c - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -31,7 +33,6 @@ #include "gpg.h" #include "util.h" -#include "memory.h" #include "ttyio.h" #include "options.h" #include "main.h" @@ -66,8 +67,8 @@ int overwrite_filep( const char *fname ) { - if( !fname || (*fname == '-' && !fname[1]) ) - return 1; /* writing to stdout is always okay */ + if( iobuf_is_pipe_filename (fname) ) + return 1; /* Writing to stdout is always okay */ if( access( fname, F_OK ) ) return 1; /* does not exist */ @@ -84,8 +85,10 @@ overwrite_filep( const char *fname ) return 0; /* do not overwrite */ tty_printf(_("File `%s' exists. "), fname); + if( cpr_enabled () ) + tty_printf ("\n"); if( cpr_get_answer_is_yes("openfile.overwrite.okay", - _("Overwrite (y/N)? ")) ) + _("Overwrite? (y/N) ")) ) return 1; return 0; } @@ -100,20 +103,20 @@ make_outfile_name( const char *iname ) { size_t n; - if( (!iname || (*iname=='-' && !iname[1]) )) - return xstrdup ("-"); + if ( iobuf_is_pipe_filename (iname) ) + return xstrdup("-"); n = strlen(iname); if( n > 4 && ( !CMP_FILENAME(iname+n-4, EXTSEP_S "gpg") || !CMP_FILENAME(iname+n-4, EXTSEP_S "pgp") || !CMP_FILENAME(iname+n-4, EXTSEP_S "sig") || !CMP_FILENAME(iname+n-4, EXTSEP_S "asc") ) ) { - char *buf = xstrdup ( iname ); + char *buf = xstrdup( iname ); buf[n-4] = 0; return buf; } else if( n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign") ) { - char *buf = xstrdup ( iname ); + char *buf = xstrdup( iname ); buf[n-5] = 0; return buf; } @@ -144,19 +147,21 @@ ask_outfile_name( const char *name, size_t namelen ) n = strlen(s) + namelen + 10; defname = name && namelen? make_printable_string( name, namelen, 0): NULL; - prompt = xmalloc (n); + prompt = xmalloc(n); if( defname ) sprintf(prompt, "%s [%s]: ", s, defname ); else sprintf(prompt, "%s: ", s ); + tty_enable_completion(NULL); fname = cpr_get("openfile.askoutname", prompt ); cpr_kill_prompt(); - xfree (prompt); + tty_disable_completion(); + xfree(prompt); if( !*fname ) { - xfree ( fname ); fname = NULL; + xfree( fname ); fname = NULL; fname = defname; defname = NULL; } - xfree (defname); + xfree(defname); if (fname) trim_spaces (fname); return fname; @@ -165,21 +170,22 @@ ask_outfile_name( const char *name, size_t namelen ) /**************** * Make an output filename for the inputfile INAME. - * Returns an iobuf_t and an errorcode + * Returns an IOBUF and an errorcode * Mode 0 = use ".gpg" * 1 = use ".asc" * 2 = use ".sig" */ int -open_outfile( const char *iname, int mode, iobuf_t *a ) +open_outfile( const char *iname, int mode, IOBUF *a ) { int rc = 0; *a = NULL; - if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) { - if( !(*a = iobuf_create(NULL)) ) { + if( iobuf_is_pipe_filename (iname) && !opt.outfile ) { + *a = iobuf_create(NULL); + if( !*a ) { rc = gpg_error_from_errno (errno); - log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) ); + log_error(_("can't open `%s': %s\n"), "[stdout]", strerror(errno) ); } else if( opt.verbose ) log_info(_("writing to stdout\n")); @@ -207,7 +213,7 @@ open_outfile( const char *iname, int mode, iobuf_t *a ) const char *newsfx = mode==1 ? ".asc" : mode==2 ? ".sig" : ".gpg"; - buf = xmalloc (strlen(iname)+4+1); + buf = xmalloc(strlen(iname)+4+1); strcpy(buf,iname); dot = strchr(buf, '.' ); if ( dot && dot > buf && dot[1] && strlen(dot) <= 4 @@ -223,7 +229,7 @@ open_outfile( const char *iname, int mode, iobuf_t *a ) if (!buf) #endif /* USE_ONLY_8DOT3 */ { - buf = xmalloc (strlen(iname)+4+1); + buf = xmalloc(strlen(iname)+4+1); strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" : mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"); } @@ -237,7 +243,7 @@ open_outfile( const char *iname, int mode, iobuf_t *a ) if ( !tmp || !*tmp ) { xfree (tmp); - rc = GPG_ERR_EEXIST; + rc = gpg_error (GPG_ERR_EEXIST); break; } xfree (buf); @@ -246,17 +252,27 @@ open_outfile( const char *iname, int mode, iobuf_t *a ) if( !rc ) { - if( !(*a = iobuf_create( name )) ) + if (is_secured_filename (name) ) + { + *a = NULL; + errno = EPERM; + } + else + *a = iobuf_create( name ); + if( !*a ) { rc = gpg_error_from_errno (errno); - log_error(_("%s: can't create: %s\n"), name, strerror(errno) ); + log_error(_("can't create `%s': %s\n"), name, strerror(errno) ); } else if( opt.verbose ) log_info(_("writing to `%s'\n"), name ); } - xfree (buf); + xfree(buf); } + if (*a) + iobuf_ioctl (*a,3,1,NULL); /* disable fd caching */ + return rc; } @@ -265,26 +281,32 @@ open_outfile( const char *iname, int mode, iobuf_t *a ) * Try to open a file without the extension ".sig" or ".asc" * Return NULL if such a file is not available. */ -iobuf_t +IOBUF open_sigfile( const char *iname, progress_filter_context_t *pfx ) { - iobuf_t a = NULL; + IOBUF a = NULL; size_t len; - if( iname && !(*iname == '-' && !iname[1]) ) { + if( !iobuf_is_pipe_filename (iname) ) { len = strlen(iname); if( len > 4 && ( !strcmp(iname + len - 4, EXTSEP_S "sig") || ( len > 5 && !strcmp(iname + len - 5, EXTSEP_S "sign") ) || !strcmp(iname + len - 4, EXTSEP_S "asc")) ) { char *buf; - buf = xstrdup (iname); + buf = xstrdup(iname); buf[len-(buf[len-1]=='n'?5:4)] = 0 ; a = iobuf_open( buf ); + if (a && is_secured_file (iobuf_get_fd (a))) + { + iobuf_close (a); + a = NULL; + errno = EPERM; + } if( a && opt.verbose ) log_info(_("assuming signed data in `%s'\n"), buf ); if (a && pfx) handle_progress (pfx, a, buf); - xfree (buf); + xfree(buf); } } return a; @@ -308,23 +330,34 @@ copy_options_file( const char *destdir ) if( opt.dry_run ) return; - fname = xmalloc ( strlen(datadir) + strlen(destdir) - + strlen (SKELEXT) + 15 ); + fname = xmalloc( strlen(datadir) + strlen(destdir) + 15 ); strcpy(stpcpy(fname, datadir), DIRSEP_S "gpg-conf" SKELEXT ); src = fopen( fname, "r" ); + if (src && is_secured_file (fileno (src))) + { + fclose (src); + src = NULL; + errno = EPERM; + } if( !src ) { - log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); - xfree (fname); + log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); + xfree(fname); return; } strcpy(stpcpy(fname, destdir), DIRSEP_S "gpg" EXTSEP_S "conf" ); oldmask=umask(077); - dst = fopen( fname, "w" ); + if ( is_secured_filename (fname) ) + { + dst = NULL; + errno = EPERM; + } + else + dst = fopen( fname, "w" ); umask(oldmask); if( !dst ) { - log_error(_("%s: can't create: %s\n"), fname, strerror(errno) ); + log_error(_("can't create `%s': %s\n"), fname, strerror(errno) ); fclose( src ); - xfree (fname); + xfree(fname); return; } @@ -354,7 +387,7 @@ copy_options_file( const char *destdir ) log_info (_("WARNING: options in `%s'" " are not yet active during this run\n"), fname); - xfree (fname); + xfree(fname); } @@ -380,10 +413,10 @@ try_make_homedir( const char *fname ) && !compare_filenames( fname, defhome ) ) ) { if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) ) - log_fatal( _("%s: can't create directory: %s\n"), + log_fatal( _("can't create directory `%s': %s\n"), fname, strerror(errno) ); else if( !opt.quiet ) - log_info( _("%s: directory created\n"), fname ); + log_info( _("directory `%s' created\n"), fname ); copy_options_file( fname ); /* log_info(_("you have to start GnuPG again, " */ /* "so it can read the new configuration file\n") ); */ diff --git a/g10/options.h b/g10/options.h index a4cbc3834..7e9d0261c 100644 --- a/g10/options.h +++ b/g10/options.h @@ -1,6 +1,6 @@ /* options.h - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,17 +16,17 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_OPTIONS_H #define G10_OPTIONS_H +#include <sys/types.h> #include <types.h> #include "main.h" #include "packet.h" -#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */ - #ifndef EXTERN_UNLESS_MAIN_MODULE /* Norcraft can't cope with common symbols */ #if defined (__riscos__) && !defined (INCLUDED_BY_MAIN_MODULE) @@ -37,155 +37,215 @@ #endif EXTERN_UNLESS_MAIN_MODULE -struct { - int verbose; - int quiet; - unsigned debug; - int armor; - int compress; - char *outfile; - int dry_run; - int list_only; - int textmode; - int expert; - int ask_sig_expire; - int ask_cert_expire; - int batch; /* run in batch mode */ - int answer_yes; /* answer yes on most questions */ - int answer_no; /* answer no on most questions */ - int check_sigs; /* check key signatures */ - int with_colons; - int with_key_data; - int with_fingerprint; /* opt --with-fingerprint active */ - int fingerprint; /* list fingerprints */ - int list_sigs; /* list signatures */ - int no_armor; - int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/ - int def_cipher_algo; - int force_v3_sigs; - int force_v4_certs; - int force_mdc; - int disable_mdc; - int def_digest_algo; - int cert_digest_algo; - int def_compress_algo; - const char *def_secret_key; - char *def_recipient; - int def_recipient_self; - int def_cert_check_level; - int sk_comments; - int no_version; - int marginals_needed; - int completes_needed; - int max_cert_depth; - const char *homedir; - const char *agent_program; - char *display; /* 5 options to be passed to the gpg-agent */ - char *ttyname; - char *ttytype; - char *lc_ctype; - char *lc_messages; - - int skip_verify; - int compress_keys; - int compress_sigs; - /* TM_CLASSIC must be zero to accomodate trustdbs generated before - we started storing the trust model inside the trustdb. */ - enum {TM_CLASSIC=0, TM_PGP=1, TM_ALWAYS, TM_AUTO} trust_model; - unsigned int force_ownertrust; - enum - { - CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8 - } compliance; - int pgp2_workarounds; - unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ - int shm_coprocess; - const char *set_filename; - STRLIST comments; - int throw_keyid; - const char *photo_viewer; - int s2k_mode; - int s2k_digest_algo; - int s2k_cipher_algo; - int simple_sk_checksum; /* create the deprecated rfc2440 secret - key protection*/ - int not_dash_escaped; - int escape_from; - int lock_once; - char *keyserver_uri; - char *keyserver_scheme; - char *keyserver_host; - char *keyserver_port; - char *keyserver_opaque; +struct +{ + int verbose; + int quiet; + unsigned debug; + int armor; + char *outfile; + off_t max_output; + int dry_run; + int list_only; + int textmode; + int expert; + const char *def_sig_expire; + int ask_sig_expire; + const char *def_cert_expire; + int ask_cert_expire; + int batch; /* run in batch mode */ + int answer_yes; /* answer yes on most questions */ + int answer_no; /* answer no on most questions */ + int check_sigs; /* check key signatures */ + int with_colons; + int with_key_data; + int with_fingerprint; /* opt --with-fingerprint active */ + int fingerprint; /* list fingerprints */ + int list_sigs; /* list signatures */ + int no_armor; + int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/ + int def_cipher_algo; + int force_v3_sigs; + int force_v4_certs; + int force_mdc; + int disable_mdc; + int def_digest_algo; + int cert_digest_algo; + int compress_algo; + int compress_level; + int bz2_compress_level; + int bz2_decompress_lowmem; + const char *def_secret_key; + char *def_recipient; + int def_recipient_self; + int def_cert_level; + int min_cert_level; + int ask_cert_level; + int no_version; + int marginals_needed; + int completes_needed; + int max_cert_depth; + const char *homedir; + const char *agent_program; + char *display; /* 5 options to be passed to the gpg-agent */ + char *ttyname; + char *ttytype; + char *lc_ctype; + char *lc_messages; + + int skip_verify; + int compress_keys; + int compress_sigs; + /* TM_CLASSIC must be zero to accomodate trustdbs generated before + we started storing the trust model inside the trustdb. */ + enum + { + TM_CLASSIC=0, TM_PGP=1, TM_EXTERNAL=2, TM_ALWAYS, TM_DIRECT, TM_AUTO + } trust_model; + int force_ownertrust; + enum + { + CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8 + } compliance; + enum + { + KF_SHORT, KF_LONG, KF_0xSHORT, KF_0xLONG + } keyid_format; + int pgp2_workarounds; + int shm_coprocess; + const char *set_filename; + STRLIST comments; + int throw_keyid; + const char *photo_viewer; + int s2k_mode; + int s2k_digest_algo; + int s2k_cipher_algo; + int simple_sk_checksum; /* create the deprecated rfc2440 secret + key protection*/ + int not_dash_escaped; + int escape_from; + int lock_once; + struct keyserver_spec + { + char *uri; + char *scheme; + char *auth; + char *host; + char *port; + char *path; + char *opaque; + STRLIST options; struct { - int verbose; - int include_revoked; - int include_disabled; - int include_subkeys; - int honor_http_proxy; - int broken_http_proxy; - int use_temp_files; - int keep_temp_files; - int fake_v3_keyids; - int auto_key_retrieve; - int try_dns_srv; - unsigned int import_options; - unsigned int export_options; - STRLIST other; - } keyserver_options; - int exec_disable; - int exec_path_set; + unsigned int direct_uri:1; + } flags; + struct keyserver_spec *next; + } *keyserver; + struct + { + unsigned int options; unsigned int import_options; unsigned int export_options; - unsigned int list_options; - unsigned int verify_options; - char *def_preference_list; - prefitem_t *personal_cipher_prefs; - prefitem_t *personal_digest_prefs; - prefitem_t *personal_compress_prefs; - int no_perm_warn; - int no_mdc_warn; - char *temp_dir; - int no_encrypt_to; - int interactive; - STRLIST sig_notation_data; - STRLIST cert_notation_data; - STRLIST sig_policy_url; - STRLIST cert_policy_url; - STRLIST sig_keyserver_url; - int use_embedded_filename; - int allow_non_selfsigned_uid; - int allow_freeform_uid; - int no_literal; - ulong set_filesize; - int fast_list_mode; - int fixed_list_mode; - int ignore_time_conflict; - int ignore_valid_from; - int ignore_crc_error; - int ignore_mdc_error; - int command_fd; - const char *override_session_key; - int show_session_key; - int use_agent; - const char *gpg_agent_info; - int merge_only; - int try_all_secrets; - int no_expensive_trust_checks; - int no_sig_cache; - int no_sig_create_check; - int no_auto_check_trustdb; - int preserve_permissions; - int no_homedir_creation; - struct groupitem *grouplist; - int strict; - int mangle_dos_filenames; - int enable_progress_filter; -} opt; + STRLIST other; + } keyserver_options; + int exec_disable; + int exec_path_set; + unsigned int import_options; + unsigned int export_options; + unsigned int list_options; + unsigned int verify_options; + char *def_preference_list; + prefitem_t *personal_cipher_prefs; + prefitem_t *personal_digest_prefs; + prefitem_t *personal_compress_prefs; + int no_perm_warn; + int no_mdc_warn; + char *temp_dir; + int no_encrypt_to; + int interactive; + struct notation *sig_notations; + struct notation *cert_notations; + STRLIST sig_policy_url; + STRLIST cert_policy_url; + STRLIST sig_keyserver_url; + STRLIST cert_subpackets; + STRLIST sig_subpackets; + int use_embedded_filename; + int allow_non_selfsigned_uid; + int allow_freeform_uid; + int no_literal; + ulong set_filesize; + int fast_list_mode; + int fixed_list_mode; + int ignore_time_conflict; + int ignore_valid_from; + int ignore_crc_error; + int ignore_mdc_error; + int command_fd; + const char *override_session_key; + int show_session_key; + int use_agent; + const char *gpg_agent_info; + int try_all_secrets; + int no_expensive_trust_checks; + int no_sig_cache; + int no_sig_create_check; + int no_auto_check_trustdb; + int preserve_permissions; + int no_homedir_creation; + struct groupitem *grouplist; + int strict; + int mangle_dos_filenames; + int enable_progress_filter; + unsigned int screen_columns; + unsigned int screen_lines; + byte *show_subpackets; + int rfc2440_text; + + /* If true, let write failures on the status-fd exit the process. */ + int exit_on_status_write_error; + + /* If > 0, limit the number of card insertion prompts to this + value. */ + int limit_card_insert_tries; + +#ifdef ENABLE_CARD_SUPPORT + /* FIXME: We don't needs this here as it is done in scdaemon. */ + const char *ctapi_driver; /* Library to access the ctAPI. */ + const char *pcsc_driver; /* Library to access the PC/SC system. */ + int disable_ccid; /* Disable the use of the internal CCID driver. */ +#endif /*ENABLE_CARD_SUPPORT*/ + + struct + { + /* If set, require an 0x19 backsig to be present on signatures + made by signing subkeys. If not set, a missing backsig is not + an error (but an invalid backsig still is). */ + unsigned int require_cross_cert:1; + } flags; + + /* Linked list of ways to find a key if the key isn't on the local + keyring. */ + struct akl + { + enum {AKL_CERT, AKL_PKA, AKL_LDAP, AKL_KEYSERVER, AKL_SPEC} type; + struct keyserver_spec *spec; + struct akl *next; + } *auto_key_locate; + + /* True if multiple concatenated signatures may be verified. */ + int allow_multisig_verification; +} opt; -#define EMUBUG_MDENCODE 4 +/* CTRL is used to keep some global variables we currently can't + avoid. Future concurrent versions of gpg will put it into a per + request structure CTRL. */ +EXTERN_UNLESS_MAIN_MODULE +struct { + int in_auto_key_retrieve; /* True if we are doing an + auto_key_retrieve. */ +} glo_ctrl; #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ #define DBG_MPI_VALUE 2 /* debug mpi details */ @@ -199,15 +259,24 @@ struct { #define DBG_TRUST_VALUE 256 /* debug the trustdb */ #define DBG_HASHING_VALUE 512 /* debug hashing operations */ #define DBG_EXTPROG_VALUE 1024 /* debug external program calls */ - +#define DBG_CARD_IO_VALUE 2048 /* debug smart card I/O. */ #define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) -#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE) #define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) #define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) #define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) #define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) +#define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE) + +/* FIXME: We need to check whey we did not put this into opt. */ +#define DBG_MEMORY memory_debug_mode +#define DBG_MEMSTAT memory_stat_debug_mode + +EXTERN_UNLESS_MAIN_MODULE int memory_debug_mode; +EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; + + #define GNUPG (opt.compliance==CO_GNUPG) #define RFC1991 (opt.compliance==CO_RFC1991 || opt.compliance==CO_PGP2) @@ -217,39 +286,54 @@ struct { #define PGP7 (opt.compliance==CO_PGP7) #define PGP8 (opt.compliance==CO_PGP8) -/* Various option flags */ - -#define IMPORT_ALLOW_LOCAL_SIGS 1 -#define IMPORT_REPAIR_PKS_SUBKEY_BUG 2 -#define IMPORT_FAST_IMPORT 4 -#define IMPORT_SK2PK 8 +/* Various option flags. Note that there should be no common string + names between the IMPORT_ and EXPORT_ flags as they can be mixed in + the keyserver-options option. */ -#define EXPORT_INCLUDE_NON_RFC 1 -#define EXPORT_INCLUDE_LOCAL_SIGS 2 -#define EXPORT_INCLUDE_ATTRIBUTES 4 -#define EXPORT_INCLUDE_SENSITIVE_REVKEYS 8 -#define EXPORT_SEXP_FORMAT 16 +#define IMPORT_LOCAL_SIGS (1<<0) +#define IMPORT_REPAIR_PKS_SUBKEY_BUG (1<<1) +#define IMPORT_FAST (1<<2) +#define IMPORT_SK2PK (1<<3) +#define IMPORT_MERGE_ONLY (1<<4) +#define IMPORT_MINIMAL (1<<5) +#define IMPORT_CLEAN (1<<6) +#define EXPORT_LOCAL_SIGS (1<<0) +#define EXPORT_ATTRIBUTES (1<<1) +#define EXPORT_SENSITIVE_REVKEYS (1<<2) +#define EXPORT_RESET_SUBKEY_PASSWD (1<<3) +#define EXPORT_MINIMAL (1<<4) +#define EXPORT_CLEAN (1<<5) -#define LIST_SHOW_PHOTOS 1 -#define LIST_SHOW_POLICY 2 -#define LIST_SHOW_NOTATION 4 -#define LIST_SHOW_KEYSERVER 8 -#define LIST_SHOW_VALIDITY 16 -#define LIST_SHOW_LONG_KEYID 32 -#define LIST_SHOW_KEYRING 64 -#define LIST_SHOW_SIG_EXPIRE 128 +#define LIST_SHOW_PHOTOS (1<<0) +#define LIST_SHOW_POLICY_URLS (1<<1) +#define LIST_SHOW_STD_NOTATIONS (1<<2) +#define LIST_SHOW_USER_NOTATIONS (1<<3) +#define LIST_SHOW_NOTATIONS (LIST_SHOW_STD_NOTATIONS|LIST_SHOW_USER_NOTATIONS) +#define LIST_SHOW_KEYSERVER_URLS (1<<4) +#define LIST_SHOW_UID_VALIDITY (1<<5) +#define LIST_SHOW_UNUSABLE_UIDS (1<<6) +#define LIST_SHOW_UNUSABLE_SUBKEYS (1<<7) +#define LIST_SHOW_KEYRING (1<<8) +#define LIST_SHOW_SIG_EXPIRE (1<<9) +#define LIST_SHOW_SIG_SUBPACKETS (1<<10) +#define VERIFY_SHOW_PHOTOS (1<<0) +#define VERIFY_SHOW_POLICY_URLS (1<<1) +#define VERIFY_SHOW_STD_NOTATIONS (1<<2) +#define VERIFY_SHOW_USER_NOTATIONS (1<<3) +#define VERIFY_SHOW_NOTATIONS (VERIFY_SHOW_STD_NOTATIONS|VERIFY_SHOW_USER_NOTATIONS) +#define VERIFY_SHOW_KEYSERVER_URLS (1<<4) +#define VERIFY_SHOW_UID_VALIDITY (1<<5) +#define VERIFY_SHOW_UNUSABLE_UIDS (1<<6) +#define VERIFY_PKA_LOOKUPS (1<<7) +#define VERIFY_PKA_TRUST_INCREASE (1<<8) -#define VERIFY_SHOW_PHOTOS 1 -#define VERIFY_SHOW_POLICY 2 -#define VERIFY_SHOW_NOTATION 4 -#define VERIFY_SHOW_KEYSERVER 8 -#define VERIFY_SHOW_VALIDITY 16 -#define VERIFY_SHOW_LONG_KEYID 32 +#define KEYSERVER_USE_TEMP_FILES (1<<0) +#define KEYSERVER_KEEP_TEMP_FILES (1<<1) +#define KEYSERVER_ADD_FAKE_V3 (1<<2) +#define KEYSERVER_AUTO_KEY_RETRIEVE (1<<3) +#define KEYSERVER_HONOR_KEYSERVER_URL (1<<4) +#define KEYSERVER_HONOR_PKA_RECORD (1<<5) #endif /*G10_OPTIONS_H*/ - - - - diff --git a/g10/packet.h b/g10/packet.h index 2d87c9c7d..54eeda1a9 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -1,6 +1,6 @@ -/* packet.h - packet definitions - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. +/* packet.h - OpenPGP packet definitions + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,21 +16,18 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_PACKET_H #define G10_PACKET_H -#include "gpg.h" -#include <gcrypt.h> - #include "types.h" #include "../common/iobuf.h" #include "../jnlib/strlist.h" #include "cipher.h" #include "filter.h" -#include "global.h" #define DEBUG_PARSE_PACKET 1 @@ -124,36 +121,56 @@ struct revocation_key { byte fpr[MAX_FINGERPRINT_LEN]; }; -typedef struct { - ulong local_id; /* internal use, valid if > 0 */ - struct { - unsigned checked:1; /* signature has been checked */ - unsigned valid:1; /* signature is good (if checked is set) */ - unsigned unknown_critical:1; - unsigned exportable:1; - unsigned revocable:1; - unsigned policy_url:1; /* At least one policy URL is present */ - unsigned notation:1; /* At least one notation is present */ - unsigned pref_ks:1; /* At least one preferred keyserver is present */ - unsigned expired:1; - } flags; - u32 keyid[2]; /* 64 bit keyid */ - u32 timestamp; /* signature made */ - u32 expiredate; /* expires at this date or 0 if not at all */ - byte version; - byte sig_class; /* sig classification, append for MD calculation*/ - byte pubkey_algo; /* algorithm used for public key scheme */ - /* (PUBKEY_ALGO_xxx) */ - byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */ - byte trust_depth; - byte trust_value; - const byte *trust_regexp; - struct revocation_key **revkey; - int numrevkeys; - subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */ - subpktarea_t *unhashed; /* ditto for unhashed data */ - byte digest_start[2]; /* first 2 bytes of the digest */ - gcry_mpi_t data[PUBKEY_MAX_NSIG]; + +/* Object to keep information about a PKA DNS record. */ +typedef struct +{ + int valid; /* An actual PKA record exists for EMAIL. */ + int checked; /* Set to true if the FPR has been checked against the + actual key. */ + char *uri; /* Malloced string with the URI. NULL if the URI is + not available.*/ + unsigned char fpr[20]; /* The fingerprint as stored in the PKA RR. */ + char email[1];/* The email address from the notation data. */ +} pka_info_t; + + +/* Object to keep information pertaining to a signature. */ +typedef struct +{ + struct + { + unsigned checked:1; /* Signature has been checked. */ + unsigned valid:1; /* Signature is good (if checked is set). */ + unsigned chosen_selfsig:1; /* A selfsig that is the chosen one. */ + unsigned unknown_critical:1; + unsigned exportable:1; + unsigned revocable:1; + unsigned policy_url:1; /* At least one policy URL is present */ + unsigned notation:1; /* At least one notation is present */ + unsigned pref_ks:1; /* At least one preferred keyserver is present */ + unsigned expired:1; + unsigned pka_tried:1; /* Set if we tried to retrieve the PKA record. */ + } flags; + u32 keyid[2]; /* 64 bit keyid */ + u32 timestamp; /* Signature made (seconds since Epoch). */ + u32 expiredate; /* Expires at this date or 0 if not at all. */ + byte version; + byte sig_class; /* Sig classification, append for MD calculation. */ + byte pubkey_algo; /* Algorithm used for public key scheme */ + /* (PUBKEY_ALGO_xxx) */ + byte digest_algo; /* Algorithm used for digest (DIGEST_ALGO_xxxx). */ + byte trust_depth; + byte trust_value; + const byte *trust_regexp; + struct revocation_key **revkey; + int numrevkeys; + pka_info_t *pka_info; /* Malloced PKA data or NULL if not + available. See also flags.pka_tried. */ + subpktarea_t *hashed; /* All subpackets with hashed data (v4 only). */ + subpktarea_t *unhashed; /* Ditto for unhashed data. */ + byte digest_start[2]; /* First 2 bytes of the digest. */ + gcry_mpi_t data[PUBKEY_MAX_NSIG]; } PKT_signature; #define ATTRIB_IMAGE 1 @@ -165,41 +182,57 @@ struct user_attribute { u32 len; }; -typedef struct { - int ref; /* reference counter */ - int len; /* length of the name */ - struct user_attribute *attribs; - int numattribs; - byte *attrib_data; /* if this is not NULL, the packet is an attribute */ - unsigned long attrib_len; - byte *namehash; - int help_key_usage; - u32 help_key_expire; - int help_full_count; - int help_marginal_count; - int is_primary; /* 2 if set via the primary flag, 1 if calculated */ - int is_revoked; - int is_expired; - u32 expiredate; /* expires at this date or 0 if not at all */ - prefitem_t *prefs; /* list of preferences (may be NULL)*/ - int mdc_feature; - int ks_modify; - u32 created; /* according to the self-signature */ - byte selfsigversion; - char name[1]; +typedef struct +{ + int ref; /* reference counter */ + int len; /* length of the name */ + struct user_attribute *attribs; + int numattribs; + byte *attrib_data; /* if this is not NULL, the packet is an attribute */ + unsigned long attrib_len; + byte *namehash; + int help_key_usage; + u32 help_key_expire; + int help_full_count; + int help_marginal_count; + int is_primary; /* 2 if set via the primary flag, 1 if calculated */ + int is_revoked; + int is_expired; + u32 expiredate; /* expires at this date or 0 if not at all */ + prefitem_t *prefs; /* list of preferences (may be NULL)*/ + u32 created; /* according to the self-signature */ + byte selfsigversion; + struct + { + /* TODO: Move more flags here */ + unsigned mdc:1; + unsigned ks_modify:1; + unsigned compacted:1; + } flags; + char name[1]; } PKT_user_id; +struct revoke_info +{ + /* revoked at this date */ + u32 date; + /* the keyid of the revoking key (selfsig or designated revoker) */ + u32 keyid[2]; + /* the algo of the revoking key */ + byte algo; +}; /**************** * Note about the pkey/skey elements: We assume that the secret keys * has the same elemts as the public key at the begin of the array, so * that npkey < nskey and it is possible to compare the secret and - * public keys by comparing the first npkey elements of pkey against skey. + * public keys by comparing the first npkey elements of pkey againts skey. */ typedef struct { u32 timestamp; /* key made */ u32 expiredate; /* expires at this date or 0 if not at all */ u32 max_expiredate; /* must not expire past this date */ + struct revoke_info revoked; byte hdrbytes; /* number of header bytes */ byte version; byte selfsigversion; /* highest version of all of the self-sigs */ @@ -208,10 +241,13 @@ typedef struct { byte req_usage; /* hack to pass a request to getkey() */ byte req_algo; /* Ditto */ u32 has_expired; /* set to the expiration date if expired */ - int is_revoked; /* key has been revoked */ + int is_revoked; /* key has been revoked, 1 if by the + owner, 2 if by a designated revoker */ + int maybe_revoked; /* a designated revocation is present, but + without the key to check it */ int is_valid; /* key (especially subkey) is valid */ int dont_cache; /* do not cache this */ - ulong local_id; /* internal use, valid if > 0 */ + byte backsig; /* 0=none, 1=bad, 2=good */ u32 main_keyid[2]; /* keyid of the primary key */ u32 keyid[2]; /* calculated by keyid_from_pk() */ byte is_primary; @@ -273,15 +309,16 @@ typedef struct { u32 len; /* reserved */ byte new_ctb; byte algorithm; - iobuf_t buf; /* iobuf_t reference */ + iobuf_t buf; /* IOBUF reference */ } PKT_compressed; typedef struct { u32 len; /* length of encrypted data */ int extralen; /* this is (blocksize+2) */ byte new_ctb; /* uses a new CTB */ + byte is_partial; /* partial length encoded */ byte mdc_method; /* > 0: integrity protected encrypted data packet */ - iobuf_t buf; /* iobuf_t reference */ + iobuf_t buf; /* IOBUF reference */ } PKT_encrypted; typedef struct { @@ -295,7 +332,7 @@ typedef struct { typedef struct { u32 len; /* length of encrypted data */ - iobuf_t buf; /* iobuf_t reference */ + iobuf_t buf; /* IOBUF reference */ byte new_ctb; byte is_partial; /* partial length encoded */ int mode; @@ -364,9 +401,25 @@ typedef enum { SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ SIGSUBPKT_FEATURES =30, /* feature flags */ + SIGSUBPKT_SIGNATURE =32, /* embedded signature */ + SIGSUBPKT_FLAG_CRITICAL=128 } sigsubpkttype_t; +struct notation +{ + char *name; + char *value; + char *altvalue; + unsigned char *bdat; + size_t blen; + struct + { + unsigned int critical:1; + unsigned int ignore:1; + } flags; + struct notation *next; +}; /*-- mainproc.c --*/ int proc_packets( void *ctx, iobuf_t a ); @@ -407,6 +460,8 @@ int copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff ); int skip_some_packets( iobuf_t inp, unsigned n ); #endif +int parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, + PKT_signature *sig ); const byte *enum_sig_subpkt ( const subpktarea_t *subpkts, sigsubpkttype_t reqtype, size_t *ret_n, int *start, int *critical ); @@ -427,7 +482,6 @@ PACKET *create_gpg_control ( ctrlpkttype_t type, /*-- build-packet.c --*/ int build_packet( iobuf_t inp, PACKET *pkt ); u32 calc_packet_length( PACKET *pkt ); -void hash_public_key( MD_HANDLE md, PKT_public_key *pk ); void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ); void build_sig_subpkt_from_sig( PKT_signature *sig ); @@ -435,6 +489,9 @@ int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); void build_attribute_subpkt(PKT_user_id *uid,byte type, const void *buf,u32 buflen, const void *header,u32 headerlen); +struct notation *string_to_notation(const char *string,int is_utf8); +struct notation *sig_to_notation(PKT_signature *sig); +void free_notation(struct notation *notation); /*-- free-packet.c --*/ void free_symkey_enc( PKT_symkey_enc *enc ); @@ -463,8 +520,8 @@ int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); /*-- sig-check.c --*/ -int signature_check( PKT_signature *sig, MD_HANDLE digest ); -int signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, +int signature_check( PKT_signature *sig, gcry_md_hd_t digest ); +int signature_check2( PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate, int *r_expired, int *r_revoked, PKT_public_key *ret_pk ); /*-- seckey-cert.c --*/ @@ -485,13 +542,10 @@ int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek ); /*-- plaintext.c --*/ int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, - int nooutput, int clearsig, int *create_failed ); -int ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, + int nooutput, int clearsig ); +int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2, const char *inname, int textmode ); -/*-- comment.c --*/ -int write_comment( iobuf_t out, const char *s ); - /*-- sign.c --*/ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, diff --git a/g10/parse-packet.c b/g10/parse-packet.c index c922eb5d9..b4dfb8c84 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1,6 +1,6 @@ /* parse-packet.c - read packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,63 +26,61 @@ #include <string.h> #include <assert.h> +#include "gpg.h" #include "packet.h" #include "iobuf.h" -#include "mpi.h" #include "util.h" #include "cipher.h" -#include "memory.h" #include "filter.h" #include "photoid.h" #include "options.h" #include "main.h" #include "i18n.h" -static int mpi_print_mode = 0; -static int list_mode = 0; +static int mpi_print_mode; +static int list_mode; +static FILE *listfp; -static int parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, - off_t *retpos, int *skip, iobuf_t out, int do_skip +static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts, + off_t *retpos, int *skip, IOBUF out, int do_skip #ifdef DEBUG_PARSE_PACKET ,const char *dbg_w, const char *dbg_f, int dbg_l #endif ); -static int copy_packet( iobuf_t inp, iobuf_t out, int pkttype, - unsigned long pktlen ); -static void skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen ); -static void skip_rest( iobuf_t inp, unsigned long pktlen ); -static void *read_rest( iobuf_t inp, size_t pktlen ); -static int parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, +static int copy_packet( IOBUF inp, IOBUF out, int pkttype, + unsigned long pktlen, int partial ); +static void skip_packet( IOBUF inp, int pkttype, + unsigned long pktlen, int partial ); +static void *read_rest( IOBUF inp, size_t pktlen, int partial ); +static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, - PKT_signature *sig ); -static int parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, PKT_onepass_sig *ops ); -static int parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *packet ); -static int parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static void parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, +static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -static int parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen, - PACKET *packet, int new_ctb); -static int parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb, int partial); +static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet, int new_ctb ); -static int parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, - PACKET *packet, int new_ctb); -static int parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen, +static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int new_ctb, int partial); +static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet, int new_ctb); -static int parse_gpg_control( iobuf_t inp, int pkttype, unsigned long pktlen, - PACKET *packet ); +static int parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *packet, int partial ); static unsigned short -read_16(iobuf_t inp) +read_16(IOBUF inp) { unsigned short a; a = iobuf_get_noeof(inp) << 8; @@ -90,7 +89,7 @@ read_16(iobuf_t inp) } static unsigned long -read_32(iobuf_t inp) +read_32(IOBUF inp) { unsigned long a; a = iobuf_get_noeof(inp) << 24; @@ -101,12 +100,84 @@ read_32(iobuf_t inp) } +/* Read an external representation of an mpi and return the MPI. The + * external format is a 16 bit unsigned value stored in network byte + * order, giving the number of bits for the following integer. The + * integer is stored with MSB first (left padded with zeroes to align + * on a byte boundary). + */ +static gcry_mpi_t +mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure) +{ + /*FIXME: Needs to be synced with gnupg14/mpi/mpicoder.c*/ + + int c, c1, c2, i; + unsigned int nbits, nbytes, nread=0; + gcry_mpi_t a = NULL; + byte *buf = NULL; + byte *p; + + if( (c = c1 = iobuf_get(inp)) == -1 ) + goto leave; + nbits = c << 8; + if( (c = c2 = iobuf_get(inp)) == -1 ) + goto leave; + nbits |= c; + if( nbits > MAX_EXTERN_MPI_BITS ) + { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + nread = 2; + nbytes = (nbits+7) / 8; + buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 ); + p = buf; + p[0] = c1; + p[1] = c2; + for( i=0 ; i < nbytes; i++ ) + { + p[i+2] = iobuf_get(inp) & 0xff; + nread++; + } + nread += nbytes; + if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) ) + a = NULL; + + leave: + gcry_free(buf); + if( nread > *ret_nread ) + log_bug("mpi larger than packet"); + else + *ret_nread = nread; + return a; +} + + + + int set_packet_list_mode( int mode ) { int old = list_mode; list_mode = mode; - /* FIXME(gcrypt) mpi_print_mode = DBG_MPI; */ + /* FIXME(gcrypt) mpi_print_mode = DBG_MPI; */ + /* We use stdout print only if invoked by the --list-packets + command but switch to stderr in all otehr cases. This breaks + the previous behaviour but that seems to be more of a bug than + intentional. I don't believe that any application makes use of + this long standing annoying way of printing to stdout except + when doing a --list-packets. If this assumption fails, it will + be easy to add an option for the listing stream. Note that we + initialize it only once; mainly because some code may switch + the option value later back to 1 and we want to have all output + to the same stream. + + Using stderr is not actually very clean because it bypasses the + logging code but it is a special thing anyay. I am not sure + whether using log_stream() would be better. Perhaps we should + enable the list mdoe only with a special option. */ + if (!listfp) + listfp = opt.list_packets == 2 ? stdout : stderr; return old; } @@ -133,7 +204,7 @@ unknown_pubkey_warning( int algo ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_parse_packet( iobuf_t inp, PACKET *pkt, const char *dbg_f, int dbg_l ) +dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l ) { int skip, rc; @@ -144,7 +215,7 @@ dbg_parse_packet( iobuf_t inp, PACKET *pkt, const char *dbg_f, int dbg_l ) } #else int -parse_packet( iobuf_t inp, PACKET *pkt ) +parse_packet( IOBUF inp, PACKET *pkt ) { int skip, rc; @@ -160,7 +231,7 @@ parse_packet( iobuf_t inp, PACKET *pkt ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid, +dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid, const char *dbg_f, int dbg_l ) { int skip, rc; @@ -172,7 +243,7 @@ dbg_search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid, } #else int -search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid ) +search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid ) { int skip, rc; @@ -188,7 +259,7 @@ search_packet( iobuf_t inp, PACKET *pkt, off_t *retpos, int with_uid ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_copy_all_packets( iobuf_t inp, iobuf_t out, +dbg_copy_all_packets( IOBUF inp, IOBUF out, const char *dbg_f, int dbg_l ) { PACKET pkt; @@ -200,7 +271,7 @@ dbg_copy_all_packets( iobuf_t inp, iobuf_t out, } #else int -copy_all_packets( iobuf_t inp, iobuf_t out ) +copy_all_packets( IOBUF inp, IOBUF out ) { PACKET pkt; int skip, rc=0; @@ -217,7 +288,7 @@ copy_all_packets( iobuf_t inp, iobuf_t out ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff, +dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, const char *dbg_f, int dbg_l ) { PACKET pkt; @@ -232,7 +303,7 @@ dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff, } #else int -copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff ) +copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ) { PACKET pkt; int skip, rc=0; @@ -250,7 +321,7 @@ copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff ) */ #ifdef DEBUG_PARSE_PACKET int -dbg_skip_some_packets( iobuf_t inp, unsigned n, +dbg_skip_some_packets( IOBUF inp, unsigned n, const char *dbg_f, int dbg_l ) { int skip, rc=0; @@ -264,7 +335,7 @@ dbg_skip_some_packets( iobuf_t inp, unsigned n, } #else int -skip_some_packets( iobuf_t inp, unsigned n ) +skip_some_packets( IOBUF inp, unsigned n ) { int skip, rc=0; PACKET pkt; @@ -286,8 +357,8 @@ skip_some_packets( iobuf_t inp, unsigned n ) * if OUT is not NULL, a special copymode is used. */ static int -parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, - int *skip, iobuf_t out, int do_skip +parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, + int *skip, IOBUF out, int do_skip #ifdef DEBUG_PARSE_PACKET ,const char *dbg_w, const char *dbg_f, int dbg_l #endif @@ -297,7 +368,7 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, unsigned long pktlen; byte hdr[8]; int hdrlen; - int new_ctb = 0; + int new_ctb = 0, partial=0; int with_uid = (onlykeypkts == 2); *skip = 0; @@ -313,7 +384,7 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, hdr[hdrlen++] = ctb; if( !(ctb & 0x80) ) { log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb ); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } pktlen = 0; @@ -322,81 +393,94 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, pkttype = ctb & 0x3f; if( (c = iobuf_get(inp)) == -1 ) { log_error("%s: 1st length byte missing\n", iobuf_where(inp) ); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if (pkttype == PKT_COMPRESSED) { iobuf_set_partial_block_mode(inp, c & 0xff); pktlen = 0;/* to indicate partial length */ + partial=1; } else { hdr[hdrlen++] = c; if( c < 192 ) - pktlen = c; - else if( c < 224 ) { - pktlen = (c - 192) * 256; - if( (c = iobuf_get(inp)) == -1 ) { - log_error("%s: 2nd length byte missing\n", - iobuf_where(inp) ); - rc = GPG_ERR_INV_PACKET; - goto leave; - } - hdr[hdrlen++] = c; - pktlen += c + 192; - } - else if( c == 255 ) { - pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24; - pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16; - pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8; - if( (c = iobuf_get(inp)) == -1 ) { - log_error("%s: 4 byte length invalid\n", - iobuf_where(inp) ); - rc = GPG_ERR_INV_PACKET; - goto leave; - } - pktlen |= (hdr[hdrlen++] = c ); - } - else { /* partial body length */ - iobuf_set_partial_block_mode(inp, c & 0xff); - pktlen = 0;/* to indicate partial length */ - } + pktlen = c; + else if( c < 224 ) + { + pktlen = (c - 192) * 256; + if( (c = iobuf_get(inp)) == -1 ) + { + log_error("%s: 2nd length byte missing\n", + iobuf_where(inp) ); + rc = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + hdr[hdrlen++] = c; + pktlen += c + 192; + } + else if( c == 255 ) + { + pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24; + pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16; + pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8; + if( (c = iobuf_get(inp)) == -1 ) + { + log_error("%s: 4 byte length invalid\n", + iobuf_where(inp) ); + rc = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + pktlen |= (hdr[hdrlen++] = c ); + } + else + { + /* Partial body length. Note that we handled + PKT_COMPRESSED earlier. */ + if(pkttype==PKT_PLAINTEXT || pkttype==PKT_ENCRYPTED + || pkttype==PKT_ENCRYPTED_MDC) + { + iobuf_set_partial_block_mode(inp, c & 0xff); + pktlen = 0;/* to indicate partial length */ + partial=1; + } + else + { + log_error("%s: partial length for invalid" + " packet type %d\n",iobuf_where(inp),pkttype); + rc = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + } } } - else { + else + { pkttype = (ctb>>2)&0xf; lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3)); - if( !lenbytes ) { + if( !lenbytes ) + { pktlen = 0; /* don't know the value */ - switch (pkttype) { - case PKT_ENCRYPTED: - case PKT_PLAINTEXT: - /* These partial length encodings are from an very - early GnuPG release and deprecated. However we - still support them read-wise. Note, that we should - not allow them for any key related packets, because - this might render a keyring unusable if an errenous - packet indicated this mode but not complying to it - gets imported. */ - iobuf_set_block_mode(inp, 1); - break; - - case PKT_COMPRESSED: - break; /* the orginal pgp 2 way. */ - - default: - log_error ("%s: old style partial length " - "for invalid packet type\n", iobuf_where(inp) ); + /* This isn't really partial, but we can treat it the same + in a "read until the end" sort of way. */ + partial=1; + if(pkttype!=PKT_ENCRYPTED && pkttype!=PKT_PLAINTEXT + && pkttype!=PKT_COMPRESSED) + { + log_error ("%s: indeterminate length for invalid" + " packet type %d\n", iobuf_where(inp), pkttype ); rc = gpg_error (GPG_ERR_INV_PACKET); - goto leave; - } - } - else { - for( ; lenbytes; lenbytes-- ) { + goto leave; + } + } + else + { + for( ; lenbytes; lenbytes-- ) + { pktlen <<= 8; pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp); - } - } - } + } + } + } if (pktlen == 0xffffffff) { /* with a some probability this is caused by a problem in the @@ -407,9 +491,10 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, } if( out && pkttype ) { - rc = iobuf_write( out, hdr, hdrlen ); - if (!rc) - rc = copy_packet(inp, out, pkttype, pktlen ); + if( iobuf_write( out, hdr, hdrlen ) == -1 ) + rc = G10ERR_WRITE_FILE; + else + rc = copy_packet(inp, out, pkttype, pktlen, partial ); goto leave; } @@ -421,7 +506,7 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, && pkttype != PKT_PUBLIC_KEY && pkttype != PKT_SECRET_SUBKEY && pkttype != PKT_SECRET_KEY ) ) { - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, partial); *skip = 1; rc = 0; goto leave; @@ -438,16 +523,16 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, #endif } pkt->pkttype = pkttype; - rc = GPG_ERR_UNKNOWN_PACKET; /* default error */ + rc = G10ERR_UNKNOWN_PACKET; /* default error */ switch( pkttype ) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: - pkt->pkt.public_key = xcalloc (1,sizeof *pkt->pkt.public_key ); + pkt->pkt.public_key = xmalloc_clear(sizeof *pkt->pkt.public_key ); rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); break; case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: - pkt->pkt.secret_key = xcalloc (1,sizeof *pkt->pkt.secret_key ); + pkt->pkt.secret_key = xmalloc_clear(sizeof *pkt->pkt.secret_key ); rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt ); break; case PKT_SYMKEY_ENC: @@ -457,11 +542,11 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt ); break; case PKT_SIGNATURE: - pkt->pkt.signature = xcalloc (1,sizeof *pkt->pkt.signature ); + pkt->pkt.signature = xmalloc_clear(sizeof *pkt->pkt.signature ); rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); break; case PKT_ONEPASS_SIG: - pkt->pkt.onepass_sig = xcalloc (1,sizeof *pkt->pkt.onepass_sig ); + pkt->pkt.onepass_sig = xmalloc_clear(sizeof *pkt->pkt.onepass_sig ); rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig ); break; case PKT_USER_ID: @@ -480,29 +565,29 @@ parse( iobuf_t inp, PACKET *pkt, int onlykeypkts, off_t *retpos, rc = 0; break; case PKT_PLAINTEXT: - rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb ); + rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb, partial ); break; case PKT_COMPRESSED: rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb ); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: - rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb ); + rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb, partial ); break; case PKT_MDC: rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb ); break; case PKT_GPG_CONTROL: - rc = parse_gpg_control(inp, pkttype, pktlen, pkt ); + rc = parse_gpg_control(inp, pkttype, pktlen, pkt, partial ); break; default: - skip_packet(inp, pkttype, pktlen); + skip_packet(inp, pkttype, pktlen, partial); break; } leave: if( !rc && iobuf_error(inp) ) - rc = GPG_ERR_INV_KEYRING; + rc = G10ERR_INV_KEYRING; return rc; } @@ -511,34 +596,36 @@ dump_hex_line( int c, int *i ) { if( *i && !(*i%8) ) { if( *i && !(*i%24) ) - printf("\n%4d:", *i ); + fprintf (listfp, "\n%4d:", *i ); else - putchar(' '); + putc (' ', listfp); } if( c == -1 ) - printf(" EOF" ); + fprintf (listfp, " EOF" ); else - printf(" %02x", c ); + fprintf (listfp, " %02x", c ); ++*i; } static int -copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen ) +copy_packet( IOBUF inp, IOBUF out, int pkttype, + unsigned long pktlen, int partial ) { - int rc, n; + int rc; + int n; char buf[100]; - if( iobuf_in_block_mode(inp) ) { + if( partial ) { while( (n = iobuf_read( inp, buf, 100 )) != -1 ) - if( (rc = iobuf_write(out, buf, n )) ) + if( (rc=iobuf_write(out, buf, n )) ) return rc; /* write error */ } else if( !pktlen && pkttype == PKT_COMPRESSED ) { log_debug("copy_packet: compressed!\n"); /* compressed packet, copy till EOF */ while( (n = iobuf_read( inp, buf, 100 )) != -1 ) - if( (rc = iobuf_write(out, buf, n )) ) + if( (rc=iobuf_write(out, buf, n )) ) return rc; /* write error */ } else { @@ -546,8 +633,8 @@ copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen ) n = pktlen > 100 ? 100 : pktlen; n = iobuf_read( inp, buf, n ); if( n == -1 ) - return GPG_ERR_GENERAL; /* FIXME(gcrypt): read error*/; - if( (rc = iobuf_write(out, buf, n )) ) + return gpg_error (GPG_ERR_EOF); + if( (rc=iobuf_write(out, buf, n )) ) return rc; /* write error */ } } @@ -556,18 +643,19 @@ copy_packet( iobuf_t inp, iobuf_t out, int pkttype, unsigned long pktlen ) static void -skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen ) +skip_packet( IOBUF inp, int pkttype, unsigned long pktlen, int partial ) { if( list_mode ) { if( pkttype == PKT_MARKER ) - fputs(":marker packet:\n", stdout ); + fputs(":marker packet:\n", listfp ); else - printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen); + fprintf (listfp, ":unknown packet: type %2d, length %lu\n", + pkttype, pktlen); if( pkttype ) { int c, i=0 ; if( pkttype != PKT_MARKER ) - fputs("dump:", stdout ); - if( iobuf_in_block_mode(inp) ) { + fputs("dump:", listfp ); + if( partial ) { while( (c=iobuf_get(inp)) != -1 ) dump_hex_line(c, &i); } @@ -575,40 +663,26 @@ skip_packet( iobuf_t inp, int pkttype, unsigned long pktlen ) for( ; pktlen; pktlen-- ) dump_hex_line(iobuf_get(inp), &i); } - putchar('\n'); + putc ('\n', listfp); return; } } - skip_rest(inp,pktlen); -} - -static void -skip_rest( iobuf_t inp, unsigned long pktlen ) -{ - if( iobuf_in_block_mode(inp) ) { - while( iobuf_get(inp) != -1 ) - ; - } - else { - for( ; pktlen; pktlen-- ) - if( iobuf_get(inp) == -1 ) - break; - } + iobuf_skip_rest(inp,pktlen,partial); } static void * -read_rest( iobuf_t inp, size_t pktlen ) +read_rest( IOBUF inp, size_t pktlen, int partial ) { byte *p; int i; - if( iobuf_in_block_mode(inp) ) { + if( partial ) { log_error("read_rest: can't store stream data\n"); p = NULL; } else { - p = xmalloc ( pktlen ); + p = xmalloc( pktlen ); for(i=0; pktlen; pktlen--, i++ ) p[i] = iobuf_get(inp); } @@ -618,7 +692,7 @@ read_rest( iobuf_t inp, size_t pktlen ) static int -parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { PKT_symkey_enc *k; int rc = 0; @@ -626,18 +700,18 @@ parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet if( pktlen < 4 ) { log_error("packet(%d) too short\n", pkttype); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version != 4 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */ log_error("packet(%d) too large\n", pkttype); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } cipher_algo = iobuf_get_noeof(inp); pktlen--; @@ -659,11 +733,11 @@ parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet } if( minlen > pktlen ) { log_error("packet with S2K %d too short\n", s2kmode ); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } seskeylen = pktlen - minlen; - k = packet->pkt.symkey_enc = xcalloc (1, sizeof *packet->pkt.symkey_enc + k = packet->pkt.symkey_enc = xmalloc_clear( sizeof *packet->pkt.symkey_enc + seskeylen - 1 ); k->version = version; k->cipher_algo = cipher_algo; @@ -677,46 +751,59 @@ parse_symkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet k->s2k.count = iobuf_get(inp); pktlen--; } k->seskeylen = seskeylen; - for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) - k->seskey[i] = iobuf_get_noeof(inp); + if(k->seskeylen) + { + for(i=0; i < seskeylen && pktlen; i++, pktlen-- ) + k->seskey[i] = iobuf_get_noeof(inp); + + /* What we're watching out for here is a session key decryptor + with no salt. The RFC says that using salt for this is a + MUST. */ + if(s2kmode!=1 && s2kmode!=3) + log_info(_("WARNING: potentially insecure symmetrically" + " encrypted session key\n")); + } assert( !pktlen ); if( list_mode ) { - printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n", - version, cipher_algo, s2kmode, hash_algo); + fprintf (listfp, ":symkey enc packet: version %d, cipher %d, s2k %d, hash %d", + version, cipher_algo, s2kmode, hash_algo); + if(seskeylen) + fprintf (listfp, ", seskey %d bits",(seskeylen-1)*8); + fprintf (listfp, "\n"); if( s2kmode == 1 || s2kmode == 3 ) { - printf("\tsalt "); + fprintf (listfp, "\tsalt "); for(i=0; i < 8; i++ ) - printf("%02x", k->s2k.salt[i]); + fprintf (listfp, "%02x", k->s2k.salt[i]); if( s2kmode == 3 ) - printf(", count %lu\n", (ulong)k->s2k.count ); - printf("\n"); + fprintf (listfp, ", count %lu", (ulong)k->s2k.count ); + fprintf (listfp, "\n"); } } leave: - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, 0); return rc; } static int -parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { unsigned int n; int rc = 0; int i, ndata; PKT_pubkey_enc *k; - k = packet->pkt.pubkey_enc = xcalloc (1,sizeof *packet->pkt.pubkey_enc); + k = packet->pkt.pubkey_enc = xmalloc_clear(sizeof *packet->pkt.pubkey_enc); if( pktlen < 12 ) { log_error("packet(%d) too short\n", pkttype); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } k->version = iobuf_get_noeof(inp); pktlen--; if( k->version != 2 && k->version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, k->version); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } k->keyid[0] = read_32(inp); pktlen -= 4; @@ -724,13 +811,13 @@ parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; k->throw_keyid = 0; /* only used as flag for build_packet */ if( list_mode ) - printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", + fprintf (listfp, ":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]); ndata = pubkey_get_nenc(k->pubkey_algo); if( !ndata ) { if( list_mode ) - printf("\tunsupported algorithm %d\n", k->pubkey_algo ); + fprintf (listfp, "\tunsupported algorithm %d\n", k->pubkey_algo ); unknown_pubkey_warning( k->pubkey_algo ); k->data[0] = NULL; /* no need to store the encrypted data */ } @@ -739,17 +826,17 @@ parse_pubkeyenc( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet n = pktlen; k->data[i] = mpi_read(inp, &n, 0); pktlen -=n; if( list_mode ) { - printf("\tdata: "); - mpi_print(stdout, k->data[i], mpi_print_mode ); - putchar('\n'); + fprintf (listfp, "\tdata: "); + mpi_print(listfp, k->data[i], mpi_print_mode ); + putc ('\n', listfp); } if (!k->data[i]) - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); } } leave: - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, 0); return rc; } @@ -765,82 +852,83 @@ dump_sig_subpkt( int hashed, int type, int critical, * detect the ARRs - we print our old message here when it is a faked * ARR and add an additional notice */ if ( type == SIGSUBPKT_ARR && !hashed ) { - printf("\tsubpkt %d len %u (additional recipient request)\n" - "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically " - "encrypt to this key and thereby reveal the plaintext to " - "the owner of this ARR key. Detailed info follows:\n", - type, (unsigned)length ); + fprintf (listfp, + "\tsubpkt %d len %u (additional recipient request)\n" + "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically " + "encrypt to this key and thereby reveal the plaintext to " + "the owner of this ARR key. Detailed info follows:\n", + type, (unsigned)length ); } buffer++; length--; - printf("\t%s%ssubpkt %d len %u (", /*)*/ + fprintf (listfp, "\t%s%ssubpkt %d len %u (", /*)*/ critical ? "critical ":"", hashed ? "hashed ":"", type, (unsigned)length ); if( length > buflen ) { - printf("too short: buffer is only %u)\n", (unsigned)buflen ); + fprintf (listfp, "too short: buffer is only %u)\n", (unsigned)buflen ); return; } switch( type ) { case SIGSUBPKT_SIG_CREATED: if( length >= 4 ) - printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) ); + fprintf (listfp, "sig created %s", strtimestamp( buffer_to_u32(buffer) ) ); break; case SIGSUBPKT_SIG_EXPIRE: if( length >= 4 ) - printf("sig expires after %s", + fprintf (listfp, "sig expires after %s", strtimevalue( buffer_to_u32(buffer) ) ); break; case SIGSUBPKT_EXPORTABLE: if( length ) - printf("%sexportable", *buffer? "":"not "); + fprintf (listfp, "%sexportable", *buffer? "":"not "); break; case SIGSUBPKT_TRUST: if(length!=2) p="[invalid trust subpacket]"; else - printf("trust signature of depth %d, value %d",buffer[0],buffer[1]); + fprintf (listfp, "trust signature of depth %d, value %d",buffer[0],buffer[1]); break; case SIGSUBPKT_REGEXP: if(!length) p="[invalid regexp subpacket]"; else - printf("regular expression: \"%s\"",buffer); + fprintf (listfp, "regular expression: \"%s\"",buffer); break; case SIGSUBPKT_REVOCABLE: if( length ) - printf("%srevocable", *buffer? "":"not "); + fprintf (listfp, "%srevocable", *buffer? "":"not "); break; case SIGSUBPKT_KEY_EXPIRE: if( length >= 4 ) - printf("key expires after %s", + fprintf (listfp, "key expires after %s", strtimevalue( buffer_to_u32(buffer) ) ); break; case SIGSUBPKT_PREF_SYM: - fputs("pref-sym-algos:", stdout ); + fputs("pref-sym-algos:", listfp ); for( i=0; i < length; i++ ) - printf(" %d", buffer[i] ); + fprintf (listfp, " %d", buffer[i] ); break; case SIGSUBPKT_REV_KEY: - fputs("revocation key: ", stdout ); + fputs("revocation key: ", listfp ); if( length < 22 ) p = "[too short]"; else { - printf("c=%02x a=%d f=", buffer[0], buffer[1] ); + fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1] ); for( i=2; i < length; i++ ) - printf("%02X", buffer[i] ); + fprintf (listfp, "%02X", buffer[i] ); } break; case SIGSUBPKT_ISSUER: if( length >= 8 ) - printf("issuer key ID %08lX%08lX", + fprintf (listfp, "issuer key ID %08lX%08lX", (ulong)buffer_to_u32(buffer), (ulong)buffer_to_u32(buffer+4) ); break; case SIGSUBPKT_NOTATION: { - fputs("notation: ", stdout ); + fputs("notation: ", listfp ); if( length < 8 ) p = "[too short]"; else { @@ -853,11 +941,11 @@ dump_sig_subpkt( int hashed, int type, int critical, if( 8+n1+n2 != length ) p = "[error]"; else { - print_string( stdout, s, n1, ')' ); - putc( '=', stdout ); + print_string( listfp, s, n1, ')' ); + putc( '=', listfp ); if( *buffer & 0x80 ) - print_string( stdout, s+n1, n2, ')' ); + print_string( listfp, s+n1, n2, ')' ); else p = "[not human readable]"; } @@ -865,60 +953,71 @@ dump_sig_subpkt( int hashed, int type, int critical, } break; case SIGSUBPKT_PREF_HASH: - fputs("pref-hash-algos:", stdout ); + fputs("pref-hash-algos:", listfp ); for( i=0; i < length; i++ ) - printf(" %d", buffer[i] ); + fprintf (listfp, " %d", buffer[i] ); break; case SIGSUBPKT_PREF_COMPR: - fputs("pref-zip-algos:", stdout ); + fputs("pref-zip-algos:", listfp ); for( i=0; i < length; i++ ) - printf(" %d", buffer[i] ); + fprintf (listfp, " %d", buffer[i] ); break; case SIGSUBPKT_KS_FLAGS: - fputs("key server preferences:",stdout); + fputs("key server preferences:",listfp); for(i=0;i<length;i++) - printf(" %02X", buffer[i]); + fprintf (listfp, " %02X", buffer[i]); break; case SIGSUBPKT_PREF_KS: - fputs("preferred key server: ", stdout ); - print_string( stdout, buffer, length, ')' ); + fputs("preferred key server: ", listfp ); + print_string( listfp, buffer, length, ')' ); break; case SIGSUBPKT_PRIMARY_UID: p = "primary user ID"; break; case SIGSUBPKT_POLICY: - fputs("policy: ", stdout ); - print_string( stdout, buffer, length, ')' ); + fputs("policy: ", listfp ); + print_string( listfp, buffer, length, ')' ); break; case SIGSUBPKT_KEY_FLAGS: - fputs ( "key flags:", stdout ); + fputs ( "key flags:", listfp ); for( i=0; i < length; i++ ) - printf(" %02X", buffer[i] ); + fprintf (listfp, " %02X", buffer[i] ); break; case SIGSUBPKT_SIGNERS_UID: p = "signer's user ID"; break; case SIGSUBPKT_REVOC_REASON: if( length ) { - printf("revocation reason 0x%02x (", *buffer ); - print_string( stdout, buffer+1, length-1, ')' ); + fprintf (listfp, "revocation reason 0x%02x (", *buffer ); + print_string( listfp, buffer+1, length-1, ')' ); p = ")"; } break; case SIGSUBPKT_ARR: - fputs("Big Brother's key (ignored): ", stdout ); + fputs("Big Brother's key (ignored): ", listfp ); if( length < 22 ) p = "[too short]"; else { - printf("c=%02x a=%d f=", buffer[0], buffer[1] ); + fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1] ); for( i=2; i < length; i++ ) - printf("%02X", buffer[i] ); + fprintf (listfp, "%02X", buffer[i] ); } break; case SIGSUBPKT_FEATURES: - fputs ( "features:", stdout ); + fputs ( "features:", listfp ); for( i=0; i < length; i++ ) - printf(" %02x", buffer[i] ); + fprintf (listfp, " %02x", buffer[i] ); + break; + case SIGSUBPKT_SIGNATURE: + fputs("signature: ",listfp); + if(length<17) + p="[too short]"; + else + fprintf (listfp, "v%d, class 0x%02X, algo %d, digest algo %d", + buffer[0], + buffer[0]==3?buffer[2]:buffer[1], + buffer[0]==3?buffer[15]:buffer[2], + buffer[0]==3?buffer[16]:buffer[3]); break; default: if(type>=100 && type<=110) @@ -928,101 +1027,115 @@ dump_sig_subpkt( int hashed, int type, int critical, break; } - printf("%s)\n", p? p: ""); + fprintf (listfp, "%s)\n", p? p: ""); } /**************** - * Returns: >= 0 offset into buffer - * -1 unknown type - * -2 unsupported type - * -3 subpacket too short + * Returns: >= 0 use this offset into buffer + * -1 explicitly reject returning this type + * -2 subpacket too short */ int parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) { - switch( type ) { - case SIGSUBPKT_REV_KEY: - if(n < 22) - break; - return 0; - case SIGSUBPKT_SIG_CREATED: - case SIGSUBPKT_SIG_EXPIRE: - case SIGSUBPKT_KEY_EXPIRE: - if( n < 4 ) - break; - return 0; - case SIGSUBPKT_KEY_FLAGS: - case SIGSUBPKT_KS_FLAGS: - case SIGSUBPKT_PREF_SYM: - case SIGSUBPKT_PREF_HASH: - case SIGSUBPKT_PREF_COMPR: - case SIGSUBPKT_POLICY: - case SIGSUBPKT_PREF_KS: - case SIGSUBPKT_FEATURES: - case SIGSUBPKT_REGEXP: - return 0; - case SIGSUBPKT_EXPORTABLE: - case SIGSUBPKT_REVOCABLE: - if( !n ) - break; - return 0; - case SIGSUBPKT_ISSUER: /* issuer key ID */ - if( n < 8 ) - break; - return 0; - case SIGSUBPKT_NOTATION: - if( n < 8 ) /* minimum length needed */ - break; - return 0; - case SIGSUBPKT_REVOC_REASON: - if( !n ) - break; - return 0; - case SIGSUBPKT_PRIMARY_UID: - if ( n != 1 ) - break; - return 0; - case SIGSUBPKT_TRUST: - if ( n != 2 ) - break; - return 0; - default: return -1; + switch( type ) + { + case SIGSUBPKT_REV_KEY: + if(n < 22) + break; + return 0; + case SIGSUBPKT_SIG_CREATED: + case SIGSUBPKT_SIG_EXPIRE: + case SIGSUBPKT_KEY_EXPIRE: + if( n < 4 ) + break; + return 0; + case SIGSUBPKT_KEY_FLAGS: + case SIGSUBPKT_KS_FLAGS: + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + case SIGSUBPKT_POLICY: + case SIGSUBPKT_PREF_KS: + case SIGSUBPKT_FEATURES: + case SIGSUBPKT_REGEXP: + return 0; + case SIGSUBPKT_SIGNATURE: + case SIGSUBPKT_EXPORTABLE: + case SIGSUBPKT_REVOCABLE: + case SIGSUBPKT_REVOC_REASON: + if( !n ) + break; + return 0; + case SIGSUBPKT_ISSUER: /* issuer key ID */ + if( n < 8 ) + break; + return 0; + case SIGSUBPKT_NOTATION: + /* minimum length needed, and the subpacket must be well-formed + where the name length and value length all fit inside the + packet. */ + if(n<8 || 8+((buffer[4]<<8)|buffer[5])+((buffer[6]<<8)|buffer[7]) != n) + break; + return 0; + case SIGSUBPKT_PRIMARY_UID: + if ( n != 1 ) + break; + return 0; + case SIGSUBPKT_TRUST: + if ( n != 2 ) + break; + return 0; + default: return 0; } - return -3; + return -2; } - +/* Not many critical notations we understand yet... */ static int -can_handle_critical( const byte *buffer, size_t n, int type ) +can_handle_critical_notation(const byte *name,size_t len) { - switch( type ) { - case SIGSUBPKT_NOTATION: - if( n >= 8 && (*buffer & 0x80) ) - return 1; /* human readable is handled */ - return 0; + if(len==32 && memcmp(name,"preferred-email-encoding@pgp.com",32)==0) + return 1; + if(len==21 && memcmp(name,"pka-address@gnupg.org",21)==0) + return 1; - case SIGSUBPKT_SIG_CREATED: - case SIGSUBPKT_SIG_EXPIRE: - case SIGSUBPKT_KEY_EXPIRE: - case SIGSUBPKT_EXPORTABLE: - case SIGSUBPKT_REVOCABLE: - case SIGSUBPKT_REV_KEY: - case SIGSUBPKT_ISSUER:/* issuer key ID */ - case SIGSUBPKT_PREF_SYM: - case SIGSUBPKT_PREF_HASH: - case SIGSUBPKT_PREF_COMPR: - case SIGSUBPKT_KEY_FLAGS: - case SIGSUBPKT_PRIMARY_UID: - case SIGSUBPKT_FEATURES: - case SIGSUBPKT_TRUST: - case SIGSUBPKT_REGEXP: - /* Is it enough to show the policy or keyserver? */ - case SIGSUBPKT_POLICY: - case SIGSUBPKT_PREF_KS: - return 1; + return 0; +} - default: +static int +can_handle_critical( const byte *buffer, size_t n, int type ) +{ + switch( type ) + { + case SIGSUBPKT_NOTATION: + if(n>=8) + return can_handle_critical_notation(buffer+8,(buffer[4]<<8)|buffer[5]); + else return 0; + case SIGSUBPKT_SIGNATURE: + case SIGSUBPKT_SIG_CREATED: + case SIGSUBPKT_SIG_EXPIRE: + case SIGSUBPKT_KEY_EXPIRE: + case SIGSUBPKT_EXPORTABLE: + case SIGSUBPKT_REVOCABLE: + case SIGSUBPKT_REV_KEY: + case SIGSUBPKT_ISSUER:/* issuer key ID */ + case SIGSUBPKT_PREF_SYM: + case SIGSUBPKT_PREF_HASH: + case SIGSUBPKT_PREF_COMPR: + case SIGSUBPKT_KEY_FLAGS: + case SIGSUBPKT_PRIMARY_UID: + case SIGSUBPKT_FEATURES: + case SIGSUBPKT_TRUST: + case SIGSUBPKT_REGEXP: + /* Is it enough to show the policy or keyserver? */ + case SIGSUBPKT_POLICY: + case SIGSUBPKT_PREF_KS: + return 1; + + default: + return 0; } } @@ -1106,13 +1219,11 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype, *ret_n = n; offset = parse_one_sig_subpkt(buffer, n, type ); switch( offset ) { - case -3: - log_error("subpacket of type %d too short\n", type); - return NULL; case -2: + log_error("subpacket of type %d too short\n", type); return NULL; case -1: - BUG(); /* not yet needed */ + return NULL; default: break; } @@ -1130,7 +1241,8 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype, return NULL; /* end of packets; not found */ too_short: - log_error("buffer shorter than subpacket\n"); + if(opt.verbose) + log_info("buffer shorter than subpacket\n"); if( start ) *start = -1; return NULL; @@ -1182,8 +1294,8 @@ void parse_revkeys(PKT_signature *sig) } } -static int -parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, +int +parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, PKT_signature *sig ) { int md5_len=0; @@ -1200,8 +1312,9 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, if( sig->version == 4 ) is_v4=1; else if( sig->version != 2 && sig->version != 3 ) { - log_error("packet(%d) with unknown version %d\n", pkttype, sig->version); - rc = GPG_ERR_INV_PACKET; + log_error("packet(%d) with unknown version %d\n", + pkttype, sig->version); + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } @@ -1222,7 +1335,7 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, n = read_16(inp); pktlen -= 2; /* length of hashed data */ if( n > 10000 ) { log_error("signature packet: hashed data too long\n"); - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } if( n ) { @@ -1240,7 +1353,7 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, n = read_16(inp); pktlen -= 2; /* length of unhashed data */ if( n > 10000 ) { log_error("signature packet: unhashed data too long\n"); - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } if( n ) { @@ -1259,46 +1372,47 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, if( pktlen < 5 ) { /* sanity check */ log_error("packet(%d) too short\n", pkttype); - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--; sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--; - if( is_v4 && sig->pubkey_algo ) { /*extract required information */ + if( is_v4 && sig->pubkey_algo ) + { /*extract required information */ const byte *p; size_t len; /* set sig->flags.unknown_critical if there is a * critical bit set for packets which we do not understand */ if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL) - || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL, - NULL) ) - { - sig->flags.unknown_critical = 1; - } + || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL, + NULL) ) + sig->flags.unknown_critical = 1; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL ); if(p) sig->timestamp = buffer_to_u32(p); - else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)) - log_error("signature packet without timestamp\n"); + else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110) + && opt.verbose) + log_info ("signature packet without timestamp\n"); p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL ); - if( p ) - { - sig->keyid[0] = buffer_to_u32(p); - sig->keyid[1] = buffer_to_u32(p+4); - } - else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)) - log_error("signature packet without keyid\n"); + if(p) + { + sig->keyid[0] = buffer_to_u32(p); + sig->keyid[1] = buffer_to_u32(p+4); + } + else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110) + && opt.verbose) + log_info ("signature packet without keyid\n"); p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL); if(p) sig->expiredate=sig->timestamp+buffer_to_u32(p); if(sig->expiredate && sig->expiredate<=make_timestamp()) - sig->flags.expired=1; + sig->flags.expired=1; p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL); if(p) @@ -1345,10 +1459,10 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, /* Find all revocation keys. */ if(sig->sig_class==0x1F) parse_revkeys(sig); - } + } if( list_mode ) { - printf(":signature packet: algo %d, keyid %08lX%08lX\n" + fprintf (listfp, ":signature packet: algo %d, keyid %08lX%08lX\n" "\tversion %d, created %lu, md5len %d, sigclass %02x\n" "\tdigest algo %d, begin of digest %02x %02x\n", sig->pubkey_algo, @@ -1365,12 +1479,11 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, ndata = pubkey_get_nsig(sig->pubkey_algo); if( !ndata ) { if( list_mode ) - printf("\tunknown algorithm %d\n", sig->pubkey_algo ); + fprintf (listfp, "\tunknown algorithm %d\n", sig->pubkey_algo ); unknown_pubkey_warning( sig->pubkey_algo ); /* we store the plain material in data[0], so that we are able * to write it back with build_packet() */ - sig->data[0] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen), - pktlen*8 ); + sig->data[0]= mpi_set_opaque(NULL, read_rest(inp, pktlen, 0), pktlen ); pktlen = 0; } else { @@ -1379,23 +1492,23 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, sig->data[i] = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { - printf("\tdata: "); - mpi_print(stdout, sig->data[i], mpi_print_mode ); - putchar('\n'); + fprintf (listfp, "\tdata: "); + mpi_print(listfp, sig->data[i], mpi_print_mode ); + putc ('\n', listfp); } if (!sig->data[i]) - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; } } leave: - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, 0); return rc; } static int -parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, +parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen, PKT_onepass_sig *ops ) { int version; @@ -1403,13 +1516,13 @@ parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, if( pktlen < 13 ) { log_error("packet(%d) too short\n", pkttype); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } version = iobuf_get_noeof(inp); pktlen--; if( version != 3 ) { log_error("onepass_sig with unknown version %d\n", version); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ops->sig_class = iobuf_get_noeof(inp); pktlen--; @@ -1419,7 +1532,7 @@ parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, ops->keyid[1] = read_32(inp); pktlen -= 4; ops->last = iobuf_get_noeof(inp); pktlen--; if( list_mode ) - printf(":onepass_sig packet: keyid %08lX%08lX\n" + fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n" "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n", (ulong)ops->keyid[0], (ulong)ops->keyid[1], version, ops->sig_class, @@ -1427,13 +1540,13 @@ parse_onepass_sig( iobuf_t inp, int pkttype, unsigned long pktlen, leave: - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, 0); return rc; } static gcry_mpi_t -read_protected_v3_mpi (iobuf_t inp, unsigned long *length) +read_protected_v3_mpi (IOBUF inp, unsigned long *length) { int c; unsigned int nbits, nbytes; @@ -1473,14 +1586,14 @@ read_protected_v3_mpi (iobuf_t inp, unsigned long *length) return NULL; } - /* convert buffer into an opaque gcry_mpi_t */ + /* convert buffer into an opaque MPI */ val = gcry_mpi_set_opaque (NULL, buf, (p-buf)*8); return val; } static int -parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, +parse_key( IOBUF inp, int pkttype, unsigned long pktlen, byte *hdr, int hdrlen, PACKET *pkt ) { int i, version, algorithm; @@ -1495,31 +1608,31 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, /* early versions of G10 use old PGP comments packets; * luckily all those comments are started by a hash */ if( list_mode ) { - printf(":rfc1991 comment packet: \"" ); + fprintf (listfp, ":rfc1991 comment packet: \"" ); for( ; pktlen; pktlen-- ) { int c; c = iobuf_get_noeof(inp); if( c >= ' ' && c <= 'z' ) - putchar(c); + putc (c, listfp); else - printf("\\x%02x", c ); + fprintf (listfp, "\\x%02x", c ); } - printf("\"\n"); + fprintf (listfp, "\"\n"); } - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, 0); return 0; } else if( version == 4 ) is_v4=1; else if( version != 2 && version != 3 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if( pktlen < 11 ) { log_error("packet(%d) too short\n", pkttype); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } @@ -1540,7 +1653,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, } algorithm = iobuf_get_noeof(inp); pktlen--; if( list_mode ) - printf(":%s key packet:\n" + fprintf (listfp, ":%s key packet:\n" "\tversion %d, algo %d, created %lu, expires %lu\n", pkttype == PKT_PUBLIC_KEY? "public" : pkttype == PKT_SECRET_KEY? "secret" : @@ -1582,7 +1695,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, npkey = pubkey_get_npkey( algorithm ); if( !npkey ) { if( list_mode ) - printf("\tunknown algorithm %d\n", algorithm ); + fprintf (listfp, "\tunknown algorithm %d\n", algorithm ); unknown_pubkey_warning( algorithm ); } @@ -1593,8 +1706,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, size_t snlen = 0; if( !npkey ) { - sk->skey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen), - pktlen*8 ); + sk->skey[0] = mpi_set_opaque( NULL, + read_rest(inp, pktlen, 0), pktlen ); pktlen = 0; goto leave; } @@ -1602,12 +1715,12 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, for(i=0; i < npkey; i++ ) { n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { - printf( "\tskey[%d]: ", i); - mpi_print(stdout, sk->skey[i], mpi_print_mode ); - putchar('\n'); + fprintf (listfp, "\tskey[%d]: ", i); + mpi_print(listfp, sk->skey[i], mpi_print_mode ); + putc ('\n', listfp); } if (!sk->skey[i]) - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; } if (rc) /* one of the MPIs were bad */ goto leave; @@ -1618,7 +1731,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, sk->protect.s2k.count = 0; if( sk->protect.algo == 254 || sk->protect.algo == 255 ) { if( pktlen < 3 ) { - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } sk->protect.sha1chk = (sk->protect.algo == 254); @@ -1634,9 +1747,9 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, temp[i] = iobuf_get_noeof(inp); if( i < 4 || memcmp( temp, "GNU", 3 ) ) { if( list_mode ) - printf( "\tunknown S2K %d\n", + fprintf (listfp, "\tunknown S2K %d\n", sk->protect.s2k.mode ); - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } /* here we know that it is a gnu extension @@ -1655,61 +1768,63 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, break; } switch( sk->protect.s2k.mode ) { - case 0: if( list_mode ) printf( "\tsimple S2K" ); + case 0: if( list_mode ) fprintf (listfp, "\tsimple S2K" ); break; - case 1: if( list_mode ) printf( "\tsalted S2K" ); + case 1: if( list_mode ) fprintf (listfp, "\tsalted S2K" ); break; - case 3: if( list_mode ) printf( "\titer+salt S2K" ); + case 3: if( list_mode ) fprintf (listfp, "\titer+salt S2K" ); break; - case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" ); + case 1001: if( list_mode ) fprintf (listfp, + "\tgnu-dummy S2K" ); break; - case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K"); + case 1002: if (list_mode) fprintf (listfp, + "\tgnu-divert-to-card S2K"); break; default: if( list_mode ) - printf( "\tunknown %sS2K %d\n", + fprintf (listfp, "\tunknown %sS2K %d\n", sk->protect.s2k.mode < 1000? "":"GNU ", sk->protect.s2k.mode ); - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } if( list_mode ) { - printf(", algo: %d,%s hash: %d", + fprintf (listfp, ", algo: %d,%s hash: %d", sk->protect.algo, sk->protect.sha1chk?" SHA1 protection," :" simple checksum,", sk->protect.s2k.hash_algo ); if( sk->protect.s2k.mode == 1 || sk->protect.s2k.mode == 3 ) { - printf(", salt: "); + fprintf (listfp, ", salt: "); for(i=0; i < 8; i++ ) - printf("%02x", sk->protect.s2k.salt[i]); + fprintf (listfp, "%02x", sk->protect.s2k.salt[i]); } - putchar('\n'); + putc ('\n', listfp); } if( sk->protect.s2k.mode == 3 ) { if( pktlen < 1 ) { - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } sk->protect.s2k.count = iobuf_get(inp); pktlen--; if( list_mode ) - printf("\tprotect count: %lu\n", + fprintf (listfp, "\tprotect count: %lu\n", (ulong)sk->protect.s2k.count); } else if( sk->protect.s2k.mode == 1002 ) { /* Read the serial number. */ if (pktlen < 1) { - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } snlen = iobuf_get (inp); pktlen--; if (pktlen < snlen || snlen == -1) { - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } } @@ -1721,7 +1836,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, sk->protect.s2k.mode = 0; sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5; if( list_mode ) - printf( "\tprotect algo: %d (hash algo: %d)\n", + fprintf (listfp, "\tprotect algo: %d (hash algo: %d)\n", sk->protect.algo, sk->protect.s2k.hash_algo ); } /* It is really ugly that we don't know the size @@ -1742,24 +1857,22 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, } if( sk->protect.s2k.mode == 1001 ) sk->protect.ivlen = 0; - else if( sk->protect.s2k.mode == 1002 ) { - if (snlen > 16) - log_info ("WARNING: serial number of card truncated\n"); + else if( sk->protect.s2k.mode == 1002 ) sk->protect.ivlen = snlen < 16? snlen : 16; - } if( pktlen < sk->protect.ivlen ) { - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; goto leave; } for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- ) temp[i] = iobuf_get_noeof(inp); if( list_mode ) { - printf( sk->protect.s2k.mode == 1002? "\tserial-number: " - : "\tprotect IV: "); + fprintf (listfp, + sk->protect.s2k.mode == 1002? "\tserial-number: " + : "\tprotect IV: "); for(i=0; i < sk->protect.ivlen; i++ ) - printf(" %02x", temp[i] ); - putchar('\n'); + fprintf (listfp, " %02x", temp[i] ); + putc ('\n', listfp); } memcpy(sk->protect.iv, temp, sk->protect.ivlen ); } @@ -1769,22 +1882,21 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, * If the user is so careless, not to protect his secret key, * we can assume, that he operates an open system :=(. * So we put the key into secure memory when we unprotect it. */ - if( sk->protect.s2k.mode == 1001 + if( sk->protect.s2k.mode == 1001 || sk->protect.s2k.mode == 1002 ) { /* better set some dummy stuff here */ - sk->skey[npkey] = gcry_mpi_set_opaque(NULL, xstrdup ("dummydata"), - 10*8); + sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup("dummydata"), 10); pktlen = 0; } else if( is_v4 && sk->is_protected ) { /* ugly; the length is encrypted too, so we read all * stuff up to the end of the packet into the first * skey element */ - sk->skey[npkey] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen), - pktlen*8 ); + sk->skey[npkey] = mpi_set_opaque(NULL, + read_rest(inp, pktlen, 0),pktlen); pktlen = 0; if( list_mode ) { - printf("\tencrypted stuff follows\n"); + fprintf (listfp, "\tencrypted stuff follows\n"); } } else { /* v3 method: the mpi length is not encrypted */ @@ -1792,28 +1904,28 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, if ( sk->is_protected ) { sk->skey[i] = read_protected_v3_mpi (inp, &pktlen); if( list_mode ) - printf( "\tskey[%d]: [encrypted]\n", i); + fprintf (listfp, "\tskey[%d]: [encrypted]\n", i); } else { n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { - printf( "\tskey[%d]: ", i); - mpi_print(stdout, sk->skey[i], mpi_print_mode ); - putchar('\n'); + fprintf (listfp, "\tskey[%d]: ", i); + mpi_print(listfp, sk->skey[i], mpi_print_mode ); + putc ('\n', listfp); } } if (!sk->skey[i]) - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; } if (rc) goto leave; sk->csum = read_16(inp); pktlen -= 2; if( list_mode ) { - printf("\tchecksum: %04hx\n", sk->csum); + fprintf (listfp, "\tchecksum: %04hx\n", sk->csum); } } } @@ -1821,8 +1933,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_public_key *pk = pkt->pkt.public_key; if( !npkey ) { - pk->pkey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen), - pktlen*8 ); + pk->pkey[0] = mpi_set_opaque( NULL, + read_rest(inp, pktlen, 0), pktlen ); pktlen = 0; goto leave; } @@ -1830,19 +1942,19 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen, for(i=0; i < npkey; i++ ) { n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { - printf( "\tpkey[%d]: ", i); - mpi_print(stdout, pk->pkey[i], mpi_print_mode ); - putchar('\n'); + fprintf (listfp, "\tpkey[%d]: ", i); + mpi_print(listfp, pk->pkey[i], mpi_print_mode ); + putc ('\n', listfp); } if (!pk->pkey[i]) - rc = GPG_ERR_INV_PACKET; + rc = G10ERR_INVALID_PACKET; } if (rc) goto leave; } leave: - skip_rest(inp, pktlen); + iobuf_skip_rest(inp, pktlen, 0); return rc; } @@ -1859,7 +1971,7 @@ parse_attribute_subpkts(PKT_user_id *uid) int buflen=uid->attrib_len; byte type; - xfree (uid->attribs); + xfree(uid->attribs); while(buflen) { @@ -1903,38 +2015,22 @@ parse_attribute_subpkts(PKT_user_id *uid) return count; too_short: - log_error("buffer shorter than attribute subpacket\n"); + if(opt.verbose) + log_info("buffer shorter than attribute subpacket\n"); uid->attribs=attribs; uid->numattribs=count; return count; } -static void setup_user_id(PACKET *packet) -{ - packet->pkt.user_id->ref = 1; - packet->pkt.user_id->attribs = NULL; - packet->pkt.user_id->attrib_data = NULL; - packet->pkt.user_id->attrib_len = 0; - packet->pkt.user_id->is_primary = 0; - packet->pkt.user_id->is_revoked = 0; - packet->pkt.user_id->is_expired = 0; - packet->pkt.user_id->expiredate = 0; - packet->pkt.user_id->created = 0; - packet->pkt.user_id->help_key_usage = 0; - packet->pkt.user_id->help_key_expire = 0; - packet->pkt.user_id->prefs = NULL; - packet->pkt.user_id->namehash = NULL; -} static int -parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; - packet->pkt.user_id = xmalloc (sizeof *packet->pkt.user_id + pktlen); + packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + pktlen); packet->pkt.user_id->len = pktlen; - - setup_user_id(packet); + packet->pkt.user_id->ref=1; p = packet->pkt.user_id->name; for( ; pktlen; pktlen--, p++ ) @@ -1943,15 +2039,15 @@ parse_user_id( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) if( list_mode ) { int n = packet->pkt.user_id->len; - printf(":user ID packet: \""); + fprintf (listfp, ":user ID packet: \""); /* fixme: Hey why don't we replace this with print_string?? */ for(p=packet->pkt.user_id->name; n; p++, n-- ) { if( *p >= ' ' && *p <= 'z' ) - putchar(*p); + putc (*p, listfp); else - printf("\\x%02x", *p ); + fprintf (listfp, "\\x%02x", *p ); } - printf("\"\n"); + fprintf (listfp, "\"\n"); } return 0; } @@ -1990,18 +2086,17 @@ make_attribute_uidname(PKT_user_id *uid, size_t max_namelen) } static int -parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; #define EXTRA_UID_NAME_SPACE 71 - packet->pkt.user_id = xmalloc (sizeof *packet->pkt.user_id - + EXTRA_UID_NAME_SPACE); - - setup_user_id(packet); - - packet->pkt.user_id->attrib_data = xmalloc (pktlen); + packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + + EXTRA_UID_NAME_SPACE); + packet->pkt.user_id->ref=1; + packet->pkt.user_id->attrib_data = xmalloc(pktlen); packet->pkt.user_id->attrib_len = pktlen; + p = packet->pkt.user_id->attrib_data; for( ; pktlen; pktlen--, p++ ) *p = iobuf_get_noeof(inp); @@ -2014,18 +2109,18 @@ parse_attribute( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE); if( list_mode ) { - printf(":attribute packet: %s\n", packet->pkt.user_id->name ); + fprintf (listfp, ":attribute packet: %s\n", packet->pkt.user_id->name ); } return 0; } static int -parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) +parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; - packet->pkt.comment = xmalloc (sizeof *packet->pkt.comment + pktlen - 1); + packet->pkt.comment = xmalloc(sizeof *packet->pkt.comment + pktlen - 1); packet->pkt.comment->len = pktlen; p = packet->pkt.comment->data; for( ; pktlen; pktlen--, p++ ) @@ -2033,22 +2128,22 @@ parse_comment( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *packet ) if( list_mode ) { int n = packet->pkt.comment->len; - printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT? + fprintf (listfp, ":%scomment packet: \"", pkttype == PKT_OLD_COMMENT? "OpenPGP draft " : "" ); for(p=packet->pkt.comment->data; n; p++, n-- ) { if( *p >= ' ' && *p <= 'z' ) - putchar(*p); + putc (*p, listfp); else - printf("\\x%02x", *p ); + fprintf (listfp, "\\x%02x", *p ); } - printf("\"\n"); + fprintf (listfp, "\"\n"); } return 0; } static void -parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt ) +parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { int c; @@ -2056,7 +2151,7 @@ parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt ) { c = iobuf_get_noeof(inp); pktlen--; - pkt->pkt.ring_trust = xmalloc ( sizeof *pkt->pkt.ring_trust ); + pkt->pkt.ring_trust = xmalloc( sizeof *pkt->pkt.ring_trust ); pkt->pkt.ring_trust->trustval = c; pkt->pkt.ring_trust->sigcache = 0; if (!c && pktlen==1) @@ -2068,42 +2163,37 @@ parse_trust( iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt ) pkt->pkt.ring_trust->sigcache = c; } if( list_mode ) - printf(":trust packet: flag=%02x sigcache=%02x\n", + fprintf (listfp, ":trust packet: flag=%02x sigcache=%02x\n", pkt->pkt.ring_trust->trustval, pkt->pkt.ring_trust->sigcache); } else { if( list_mode ) - printf(":trust packet: empty\n"); + fprintf (listfp, ":trust packet: empty\n"); } - skip_rest (inp, pktlen); + iobuf_skip_rest (inp, pktlen, 0); } static int -parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen, - PACKET *pkt, int new_ctb ) +parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb, int partial ) { int rc = 0; - int mode, namelen, partial=0; + int mode, namelen; PKT_plaintext *pt; byte *p; int c, i; - if( pktlen && pktlen < 6 ) { + if( !partial && pktlen < 6 ) { log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } - /* A packet length of zero indicates partial body length. A zero - data length isn't a zero length packet due to the header (mode, - name, etc), so this is accurate. */ - if(pktlen==0) - partial=1; mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; - pt = pkt->pkt.plaintext = xmalloc (sizeof *pkt->pkt.plaintext + namelen -1); + pt = pkt->pkt.plaintext = xmalloc(sizeof *pkt->pkt.plaintext + namelen -1); pt->new_ctb = new_ctb; pt->mode = mode; pt->namelen = namelen; @@ -2125,17 +2215,21 @@ parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen, pktlen = 0; if( list_mode ) { - printf(":literal data packet:\n" - "\tmode %c, created %lu, name=\"", - mode >= ' ' && mode <'z'? mode : '?', + fprintf (listfp, ":literal data packet:\n" + "\tmode %c (%X), created %lu, name=\"", + mode >= ' ' && mode <'z'? mode : '?', mode, (ulong)pt->timestamp ); for(p=pt->name,i=0; i < namelen; p++, i++ ) { if( *p >= ' ' && *p <= 'z' ) - putchar(*p); + putc (*p, listfp); else - printf("\\x%02x", *p ); + fprintf (listfp, "\\x%02x", *p ); } - printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len ); + fprintf (listfp, "\",\n\traw data: "); + if(partial) + fprintf (listfp, "unknown length\n"); + else + fprintf (listfp, "%lu bytes\n", (ulong)pt->len ); } leave: @@ -2144,7 +2238,7 @@ parse_plaintext( iobuf_t inp, int pkttype, unsigned long pktlen, static int -parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen, +parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt, int new_ctb ) { PKT_compressed *zd; @@ -2153,26 +2247,26 @@ parse_compressed( iobuf_t inp, int pkttype, unsigned long pktlen, * (this should be the last object in a file or * the compress algorithm should know the length) */ - zd = pkt->pkt.compressed = xmalloc (sizeof *pkt->pkt.compressed ); + zd = pkt->pkt.compressed = xmalloc(sizeof *pkt->pkt.compressed ); zd->algorithm = iobuf_get_noeof(inp); zd->len = 0; /* not used */ zd->new_ctb = new_ctb; zd->buf = inp; if( list_mode ) - printf(":compressed packet: algo=%d\n", zd->algorithm); + fprintf (listfp, ":compressed packet: algo=%d\n", zd->algorithm); return 0; } static int -parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, - PACKET *pkt, int new_ctb ) +parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, + PACKET *pkt, int new_ctb, int partial ) { int rc = 0; PKT_encrypted *ed; unsigned long orig_pktlen = pktlen; - ed = pkt->pkt.encrypted = xmalloc (sizeof *pkt->pkt.encrypted ); + ed = pkt->pkt.encrypted = xmalloc(sizeof *pkt->pkt.encrypted ); ed->len = pktlen; /* we don't know the extralen which is (cipher_blocksize+2) because the algorithm ist not specified in this packet. @@ -2182,6 +2276,7 @@ parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, ed->extralen = 0; ed->buf = NULL; ed->new_ctb = new_ctb; + ed->is_partial = partial; ed->mdc_method = 0; if( pkttype == PKT_ENCRYPTED_MDC ) { /* fixme: add some pktlen sanity checks */ @@ -2194,28 +2289,28 @@ parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, log_error("encrypted_mdc packet with unknown version %d\n", version); /*skip_rest(inp, pktlen); should we really do this? */ - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ed->mdc_method = DIGEST_ALGO_SHA1; } if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */ log_error("packet(%d) too short\n", pkttype); - rc = GPG_ERR_INV_PACKET; - skip_rest(inp, pktlen); + rc = G10ERR_INVALID_PACKET; + iobuf_skip_rest(inp, pktlen, partial); goto leave; } if( list_mode ) { if( orig_pktlen ) - printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen); + fprintf (listfp, ":encrypted data packet:\n\tlength: %lu\n", + orig_pktlen); else - printf(":encrypted data packet:\n\tlength: unknown\n"); + fprintf (listfp, ":encrypted data packet:\n\tlength: unknown\n"); if( ed->mdc_method ) - printf("\tmdc_method: %d\n", ed->mdc_method ); + fprintf (listfp, "\tmdc_method: %d\n", ed->mdc_method ); } ed->buf = inp; - pktlen = 0; leave: return rc; @@ -2223,19 +2318,19 @@ parse_encrypted( iobuf_t inp, int pkttype, unsigned long pktlen, static int -parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen, +parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt, int new_ctb ) { int rc = 0; PKT_mdc *mdc; byte *p; - mdc = pkt->pkt.mdc= xmalloc (sizeof *pkt->pkt.mdc ); + mdc = pkt->pkt.mdc= xmalloc(sizeof *pkt->pkt.mdc ); if( list_mode ) - printf(":mdc packet: length=%lu\n", pktlen); + fprintf (listfp, ":mdc packet: length=%lu\n", pktlen); if( !new_ctb || pktlen != 20 ) { log_error("mdc_packet with invalid encoding\n"); - rc = GPG_ERR_INV_PACKET; + rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } p = mdc->hash; @@ -2259,8 +2354,8 @@ parse_mdc( iobuf_t inp, int pkttype, unsigned long pktlen, */ static int -parse_gpg_control( iobuf_t inp, - int pkttype, unsigned long pktlen, PACKET *packet ) +parse_gpg_control( IOBUF inp, int pkttype, + unsigned long pktlen, PACKET *packet, int partial ) { byte *p; const byte *sesmark; @@ -2268,7 +2363,7 @@ parse_gpg_control( iobuf_t inp, int i; if ( list_mode ) - printf(":packet 63: length %lu ", pktlen); + fprintf (listfp, ":packet 63: length %lu ", pktlen); sesmark = get_session_marker ( &sesmarklen ); if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */ @@ -2280,7 +2375,7 @@ parse_gpg_control( iobuf_t inp, if ( list_mode ) puts ("- gpg control packet"); - packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control + packet->pkt.gpg_control = xmalloc(sizeof *packet->pkt.gpg_control + pktlen - 1); packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--; packet->pkt.gpg_control->datalen = pktlen; @@ -2295,8 +2390,8 @@ parse_gpg_control( iobuf_t inp, int c; i=0; - printf("- private (rest length %lu)\n", pktlen); - if( iobuf_in_block_mode(inp) ) { + fprintf (listfp, "- private (rest length %lu)\n", pktlen); + if( partial ) { while( (c=iobuf_get(inp)) != -1 ) dump_hex_line(c, &i); } @@ -2304,10 +2399,10 @@ parse_gpg_control( iobuf_t inp, for( ; pktlen; pktlen-- ) dump_hex_line(iobuf_get(inp), &i); } - putchar('\n'); + putc ('\n', listfp); } - skip_rest(inp,pktlen); - return GPG_ERR_INV_PACKET; + iobuf_skip_rest(inp,pktlen, 0); + return gpg_error (GPG_ERR_INV_PACKET); } /* create a gpg control packet to be used internally as a placeholder */ @@ -2317,10 +2412,10 @@ create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen ) PACKET *packet; byte *p; - packet = xmalloc ( sizeof *packet ); + packet = xmalloc( sizeof *packet ); init_packet(packet); packet->pkttype = PKT_GPG_CONTROL; - packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control + packet->pkt.gpg_control = xmalloc(sizeof *packet->pkt.gpg_control + datalen - 1); packet->pkt.gpg_control->control = type; packet->pkt.gpg_control->datalen = datalen; diff --git a/g10/passphrase.c b/g10/passphrase.c index 30149908e..c63ee66d4 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -1,5 +1,6 @@ /* passphrase.c - Get a passphrase - * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -29,8 +31,8 @@ #include <sys/socket.h> #include <sys/un.h> #endif -#if defined (_WIN32) || defined (__CYGWIN32__) -# include <windows.h> +#if defined (_WIN32) +#include <windows.h> #endif #include <errno.h> #ifdef HAVE_LOCALE_H @@ -42,7 +44,6 @@ #include "gpg.h" #include "util.h" -#include "memory.h" #include "options.h" #include "ttyio.h" #include "cipher.h" @@ -50,62 +51,14 @@ #include "main.h" #include "i18n.h" #include "status.h" - - -enum gpga_protocol_codes { - /* Request codes */ - GPGA_PROT_GET_VERSION = 1, - GPGA_PROT_GET_PASSPHRASE = 2, - GPGA_PROT_CLEAR_PASSPHRASE= 3, - GPGA_PROT_SHUTDOWN = 4, - GPGA_PROT_FLUSH = 5, - - /* Reply codes */ - GPGA_PROT_REPLY_BASE = 0x10000, - GPGA_PROT_OKAY = 0x10001, - GPGA_PROT_GOT_PASSPHRASE = 0x10002, - - /* Error codes */ - GPGA_PROT_ERROR_BASE = 0x20000, - GPGA_PROT_PROTOCOL_ERROR = 0x20001, - GPGA_PROT_INVALID_REQUEST= 0x20002, - GPGA_PROT_CANCELED = 0x20003, - GPGA_PROT_NO_PASSPHRASE = 0x20004, - GPGA_PROT_BAD_PASSPHRASE = 0x20005, - GPGA_PROT_INVALID_DATA = 0x20006, - GPGA_PROT_NOT_IMPLEMENTED= 0x20007, - GPGA_PROT_UI_PROBLEM = 0x20008 -}; - - -#define buftou32( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ - (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3))) -#define u32tobuf( p, a ) do { \ - ((byte*)p)[0] = (byte)((a) >> 24); \ - ((byte*)p)[1] = (byte)((a) >> 16); \ - ((byte*)p)[2] = (byte)((a) >> 8); \ - ((byte*)p)[3] = (byte)((a) ); \ - } while(0) - -#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)) - - +#ifdef ENABLE_AGENT_SUPPORT +#include "assuan.h" +#endif /*ENABLE_AGENT_SUPPORT*/ static char *fd_passwd = NULL; static char *next_pw = NULL; static char *last_pw = NULL; -#if defined (_WIN32) -static int read_fd = 0; -static int write_fd = 0; -#endif - static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ); int @@ -123,10 +76,10 @@ have_static_passphrase() void set_next_passphrase( const char *s ) { - xfree (next_pw); + xfree(next_pw); next_pw = NULL; if( s ) { - next_pw = gcry_xmalloc_secure ( strlen(s)+1 ); + next_pw = xmalloc_secure( strlen(s)+1 ); strcpy(next_pw, s ); } } @@ -144,6 +97,30 @@ get_last_passphrase() return p; } +/* As if we had used the passphrase - make it the last_pw. */ +void +next_to_last_passphrase(void) +{ + if(next_pw) + { + last_pw=next_pw; + next_pw=NULL; + } +} + +/* Here's an interesting question: since this passphrase was passed in + on the command line, is there really any point in using secure + memory for it? I'm going with 'yes', since it doesn't hurt, and + might help in some small way (swapping). */ + +void +set_passphrase_from_string(const char *pass) +{ + xfree( fd_passwd ); + fd_passwd = xmalloc_secure(strlen(pass)+1); + strcpy(fd_passwd,pass); +} + void read_passphrase_from_fd( int fd ) @@ -171,9 +148,12 @@ read_passphrase_from_fd( int fd ) { char *pw2 = pw; len += 100; - pw = gcry_xmalloc_secure ( len ); + pw = xmalloc_secure( len ); if( pw2 ) - memcpy(pw, pw2, i ); + { + memcpy(pw, pw2, i ); + xfree (pw2); + } else i=0; } @@ -184,181 +164,33 @@ read_passphrase_from_fd( int fd ) if (!opt.batch) tty_printf("\b\b\b \n" ); - xfree ( fd_passwd ); + xfree( fd_passwd ); fd_passwd = pw; } -static int -writen ( int fd, const void *buf, size_t nbytes ) -{ -#if defined (_WIN32) - DWORD nwritten, nleft = nbytes; - - while (nleft > 0) { - if ( !WriteFile( (HANDLE)write_fd, buf, nleft, &nwritten, NULL) ) { - log_error("write failed: ec=%d\n", (int)GetLastError()); - return -1; - } - /*log_info("** WriteFile fd=%d nytes=%d nwritten=%d\n", - write_fd, nbytes, (int)nwritten);*/ - Sleep(100); - - nleft -= nwritten; - buf = (const BYTE *)buf + nwritten; - } -#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - /* not implemented */ -#else - size_t nleft = nbytes; - int nwritten; - - while( nleft > 0 ) { - nwritten = write( fd, buf, nleft ); - if( nwritten < 0 ) { - if ( errno == EINTR ) - nwritten = 0; - else { - log_error ( "write() failed: %s\n", strerror (errno) ); - return -1; - } - } - nleft -= nwritten; - buf = (const char*)buf + nwritten; - } -#endif - - return 0; -} +#ifdef ENABLE_AGENT_SUPPORT +/* Send one option to the gpg-agent. */ static int -readn ( int fd, void *buf, size_t buflen, size_t *ret_nread ) +agent_send_option (assuan_context_t ctx, const char *name, const char *value) { -#if defined (_WIN32) - DWORD nread, nleft = buflen; - - while (nleft > 0) { - if ( !ReadFile( (HANDLE)read_fd, buf, nleft, &nread, NULL) ) { - log_error("read() error: ec=%d\n", (int)GetLastError()); - return -1; - } - if (!nread || GetLastError() == ERROR_BROKEN_PIPE) - break; - /*log_info("** ReadFile fd=%d buflen=%d nread=%d\n", - read_fd, buflen, (int)nread);*/ - Sleep(100); - - nleft -= nread; - buf = (BYTE *)buf + nread; - } - if (ret_nread) - *ret_nread = buflen - nleft; - -#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__) - /* not implemented */ -#else - size_t nleft = buflen; - int nread; - char *p; - - p = buf; - while( nleft > 0 ) { - nread = read ( fd, buf, nleft ); - if( nread < 0 ) { - if (nread == EINTR) - nread = 0; - else { - log_error ( "read() error: %s\n", strerror (errno) ); - return -1; - } - } - else if( !nread ) - break; /* EOF */ - nleft -= nread; - buf = (char*)buf + nread; - } - if( ret_nread ) - *ret_nread = buflen - nleft; -#endif - - return 0; -} - -/* read an entire line */ -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 -1; /* read error */ - } - else if (!n) - { - return -1; /* 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 temporary hack until we use - the assuna lib in gpg. So it is okay to forget - about pending bytes */ - } - } - - return nread; -} - - - -#if !defined (__riscos__) - -#if !defined (_WIN32) -/* For the new Assuan protocol we may have to send options */ -static int -agent_send_option (int fd, const char *name, const char *value) -{ - char buf[200]; - int nread; char *line; - int i; + int rc; - line = xmalloc (7 + strlen (name) + 1 + strlen (value) + 2); - strcpy (stpcpy (stpcpy (stpcpy ( - stpcpy (line, "OPTION "), name), "="), value), "\n"); - i = writen (fd, line, strlen (line)); - xfree (line); - if (i) - return -1; - - /* get response */ - nread = readline (fd, buf, DIM(buf)-1); - if (nread < 3) - return -1; - - if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) - return 0; /* okay */ + if (!value || !*value) + return 0; /* Avoid sending empty option values. */ - return -1; + line = xmalloc (7 + strlen (name) + 1 + strlen (value) + 1); + strcpy (stpcpy (stpcpy (stpcpy (line, "OPTION "), name), "="), value); + rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + xfree (line); + return rc? -1 : 0; } +/* Send all required options to the gpg-agent. */ static int -agent_send_all_options (int fd) +agent_send_all_options (assuan_context_t ctx) { char *dft_display = NULL; const char *dft_ttyname = NULL; @@ -370,20 +202,24 @@ agent_send_all_options (int fd) dft_display = getenv ("DISPLAY"); if (opt.display || dft_display) { - if (agent_send_option (fd, "display", + if (agent_send_option (ctx, "display", opt.display ? opt.display : dft_display)) return -1; } if (!opt.ttyname) { + const char *tmp; + dft_ttyname = getenv ("GPG_TTY"); - if ((!dft_ttyname || !*dft_ttyname) && tty_get_ttyname ()) - dft_ttyname = tty_get_ttyname (); + if ((!dft_ttyname || !*dft_ttyname) && (tmp=ttyname (0))) + dft_ttyname = tmp; + if ((!dft_ttyname || !*dft_ttyname) && (tmp=tty_get_ttyname ())) + dft_ttyname = tmp; } if (opt.ttyname || dft_ttyname) { - if (agent_send_option (fd, "ttyname", + if (agent_send_option (ctx, "ttyname", opt.ttyname ? opt.ttyname : dft_ttyname)) return -1; } @@ -391,7 +227,7 @@ agent_send_all_options (int fd) dft_ttytype = getenv ("TERM"); if (opt.ttytype || (dft_ttyname && dft_ttytype)) { - if (agent_send_option (fd, "ttytype", + if (agent_send_option (ctx, "ttytype", opt.ttyname ? opt.ttytype : dft_ttytype)) return -1; } @@ -404,7 +240,7 @@ agent_send_all_options (int fd) #endif if (opt.lc_ctype || (dft_ttyname && dft_lc)) { - rc = agent_send_option (fd, "lc-ctype", + rc = agent_send_option (ctx, "lc-ctype", opt.lc_ctype ? opt.lc_ctype : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE) @@ -425,7 +261,7 @@ agent_send_all_options (int fd) #endif if (opt.lc_messages || (dft_ttyname && dft_lc)) { - rc = agent_send_option (fd, "lc-messages", + rc = agent_send_option (ctx, "lc-messages", opt.lc_messages ? opt.lc_messages : dft_lc); } #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES) @@ -437,170 +273,186 @@ agent_send_all_options (int fd) #endif return rc; } -#endif /*!_WIN32*/ +#endif /*ENABLE_AGENT_SUPPORT*/ /* - * Open a connection to the agent and send the magic string - * Returns: -1 on error or an filedescriptor for urther processing + * Open a connection to the agent and initializes the connection. + * Returns: -1 on error; on success an Assuan context for that + * connection is returned. With TRY set to true, no error messages + * are printed and the use of the agent won't get disabled on failure. + * If ORIG_CODESET is not NULL, the function will swithc the codeset + * back to that one before printing error messages. */ - -static int -agent_open (int *ret_prot) +#ifdef ENABLE_AGENT_SUPPORT +assuan_context_t +agent_open (int try, const char *orig_codeset) { -#if defined (_WIN32) - int fd; - char *infostr, *p; - HANDLE h; - char pidstr[128]; - - *ret_prot = 0; - if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentPID")) - || *infostr == '0') { - log_error( _("gpg-agent is not available in this session\n")); - return -1; - } - free(infostr); - - sprintf(pidstr, "%u", (unsigned int)GetCurrentProcessId()); - if (write_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentCID", pidstr)) { - log_error( _("can't set client pid for the agent\n") ); - return -1; - } - h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); - SetEvent(h); - Sleep(50); /* some time for the server */ - if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentReadFD")) ) { - log_error( _("can't get server read FD for the agent\n") ); - return -1; - } - read_fd = atol(p); - free(p); - if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG", - "agentWriteFD")) ) { - log_error ( _("can't get server write FD for the agent\n") ); - return -1; - } - write_fd = atol(p); - free(p); - fd = 0; + int rc; + assuan_context_t ctx; + char *infostr, *p; + int prot; + int pid; - if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { - fd = -1; + if (opt.gpg_agent_info) + infostr = xstrdup (opt.gpg_agent_info); + else + { + infostr = getenv ( "GPG_AGENT_INFO" ); + if (!infostr || !*infostr) + { + if (!try) + { +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif /*ENABLE_NLS*/ + log_info (_("gpg-agent is not available in this session\n")); + opt.use_agent = 0; + } + return NULL; + } + infostr = xstrdup ( infostr ); } -#else /* Posix */ - - int fd; - char *infostr, *p; - struct sockaddr_un client_addr; - size_t len; - int prot; - - if (opt.gpg_agent_info) - infostr = xstrdup (opt.gpg_agent_info); - else - { - infostr = getenv ( "GPG_AGENT_INFO" ); - if ( !infostr || !*infostr ) { - log_error (_("gpg-agent is not available in this session\n")); + + if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) + { + if (!try) + { +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif /*ENABLE_NLS*/ + log_error ( _("malformed GPG_AGENT_INFO environment variable\n")); opt.use_agent = 0; - return -1; } - infostr = xstrdup ( infostr ); - } - - if ( !(p = strchr ( infostr, ':')) || p == infostr - || (p-infostr)+1 >= sizeof client_addr.sun_path ) { - log_error( _("malformed GPG_AGENT_INFO environment variable\n")); - xfree (infostr ); - opt.use_agent = 0; - return -1; - } - *p++ = 0; - /* See whether this is the new gpg-agent using the Assuna protocl. - This agent identifies itself by have an info string with a - version number in the 3rd field. */ - while (*p && *p != ':') - p++; - prot = *p? atoi (p+1) : 0; - if ( prot < 0 || prot > 1) { - log_error (_("gpg-agent protocol version %d is not supported\n"),prot); - xfree (infostr ); - opt.use_agent = 0; - return -1; + xfree (infostr); + return NULL; } - *ret_prot = prot; - - if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) { - log_error ("can't create socket: %s\n", strerror(errno) ); - xfree (infostr ); - opt.use_agent = 0; - return -1; + *p++ = 0; + pid = atoi (p); + while (*p && *p != PATHSEP_C) + p++; + prot = *p? atoi (p+1) : 0; + if (prot != 1) + { + if (!try) + { +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif /*ENABLE_NLS*/ + log_error (_("gpg-agent protocol version %d is not supported\n"), + prot); + opt.use_agent = 0; + } + xfree (infostr); + return NULL; } - - 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 ) { - log_error ( _("can't connect to `%s': %s\n"), - infostr, strerror (errno) ); - xfree (infostr ); - close (fd ); - opt.use_agent = 0; - return -1; + + rc = assuan_socket_connect (&ctx, infostr, pid); + if (rc) + { + if (!try) + { +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif /*ENABLE_NLS*/ + log_error ( _("can't connect to `%s': %s\n"), + infostr, assuan_strerror (rc)); + opt.use_agent = 0; + } + xfree (infostr ); + return NULL; } - xfree (infostr); + xfree (infostr); - if (!prot) { - if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) { - close (fd); - fd = -1; + if (agent_send_all_options (ctx)) + { + if (!try) + { +#ifdef ENABLE_NLS + if (orig_codeset) + bind_textdomain_codeset (PACKAGE, orig_codeset); +#endif /*ENABLE_NLS*/ + log_error (_("problem with the agent - disabling agent use\n")); + opt.use_agent = 0; } + assuan_disconnect (ctx); + return NULL; } - else { /* assuan based gpg-agent */ - char line[200]; - int nread; - - nread = readline (fd, line, DIM(line)); - if (nread < 3 || !(line[0] == 'O' && line[1] == 'K' - && (line[2] == '\n' || line[2] == ' ')) ) { - log_error ( _("communication problem with gpg-agent\n")); - close (fd ); - opt.use_agent = 0; - return -1; - } - if (agent_send_all_options (fd)) { - log_error (_("problem with the agent - disabling agent use\n")); - close (fd); - opt.use_agent = 0; - return -1; - } - - } -#endif + return ctx; +} +#endif/*ENABLE_AGENT_SUPPORT*/ - return fd; + +#ifdef ENABLE_AGENT_SUPPORT +void +agent_close (assuan_context_t ctx) +{ + assuan_disconnect (ctx); } +#endif /*ENABLE_AGENT_SUPPORT*/ -static void -agent_close ( int fd ) +/* Copy the text ATEXT into the buffer P and do plus '+' and percent + escaping. Note that the provided buffer needs to be 3 times the + size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */ +#ifdef ENABLE_AGENT_SUPPORT +static char * +percent_plus_escape (char *p, const char *atext) { -#if defined (_WIN32) - HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent"); - ResetEvent(h); -#else - close (fd); -#endif + const unsigned char *s; + + for (s=atext; *s; s++) + { + if (*s < ' ' || *s == '+') + { + sprintf (p, "%%%02X", *s); + p += 3; + } + else if (*s == ' ') + *p++ = '+'; + else + *p++ = *s; + } + *p = 0; + return p; +} +#endif /*ENABLE_AGENT_SUPPORT*/ + + +#ifdef ENABLE_AGENT_SUPPORT + +/* Object for the agent_okay_cb function. */ +struct agent_okay_cb_s { + char *pw; +}; + +/* A callback used to get the passphrase from the okay line. See + agent-get_passphrase for details. LINE is the rest of the OK + status line without leading white spaces. */ +static assuan_error_t +agent_okay_cb (void *opaque, const char *line) +{ + struct agent_okay_cb_s *parm = opaque; + int i; + + /* Note: If the malloc below fails we won't be able to wipe the + memory at LINE given the current implementation of the Assuan + code. There is no easy ay around this w/o adding a lot of more + memory function code to allow wiping arbitrary stuff on memory + failure. */ + parm->pw = xmalloc_secure (strlen (line)/2+2); + + for (i=0; hexdigitp (line) && hexdigitp (line+1); line += 2) + parm->pw[i++] = xtoi_2 (line); + parm->pw[i] = 0; + return 0; } -#endif /* !__riscos__ */ +#endif /*ENABLE_AGENT_SUPPORT*/ @@ -612,26 +464,23 @@ agent_close ( int fd ) * * Note that TRYAGAIN_TEXT must not be translated. If canceled is not * NULL, the function does set it to 1 if the user canceled the - * operation. + * operation. If CACHEID is not NULL, it will be used as the cacheID + * for the gpg-agent; if is NULL and a key fingerprint can be + * computed, this will be used as the cacheid. */ static char * -agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, - int *canceled) +agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid, + const char *tryagain_text, + const char *custom_description, + const char *custom_prompt, int *canceled) { -#if defined(__riscos__) - return NULL; -#else - size_t n; +#ifdef ENABLE_AGENT_SUPPORT char *atext = NULL; - char buf[50]; - int fd = -1; - int nread; - u32 reply; + assuan_context_t ctx = NULL; char *pw = NULL; - PKT_public_key *pk = xcalloc (1, sizeof *pk ); + PKT_public_key *pk = xmalloc_clear( sizeof *pk ); byte fpr[MAX_FINGERPRINT_LEN]; int have_fpr = 0; - int prot; char *orig_codeset = NULL; if (canceled) @@ -644,13 +493,14 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, memset (fpr, 0, MAX_FINGERPRINT_LEN ); if( keyid && get_pubkey( pk, keyid ) ) { - free_public_key( pk ); + if (pk) + free_public_key( pk ); pk = NULL; /* oops: no key for some reason */ } #ifdef ENABLE_NLS /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); + orig_codeset = bind_textdomain_codeset (PACKAGE, NULL); #ifdef HAVE_LANGINFO_CODESET if (!orig_codeset) orig_codeset = nl_langinfo (CODESET); @@ -658,44 +508,58 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, if (orig_codeset) { /* We only switch when we are able to restore the codeset later. */ orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) + if (!bind_textdomain_codeset (PACKAGE, "utf-8")) orig_codeset = NULL; } #endif - if ( (fd = agent_open (&prot)) == -1 ) + if ( !(ctx = agent_open (0, orig_codeset)) ) goto failure; - if ( !mode && pk && keyid ) + if (custom_description) + atext = native_to_utf8 (custom_description); + else if ( !mode && pk && keyid ) { char *uid; size_t uidlen; - const char *algo_name = gcry_pk_algo_name ( pk->pubkey_algo ); + const char *algo_name = pubkey_algo_to_string ( pk->pubkey_algo ); const char *timestr; char *maink; if ( !algo_name ) algo_name = "?"; - + +#define KEYIDSTRING _(" (main key ID %s)") + + maink = xmalloc ( strlen (KEYIDSTRING) + keystrlen() + 20 ); if( keyid[2] && keyid[3] && keyid[0] != keyid[2] && keyid[1] != keyid[3] ) - maink = xasprintf ( _(" (main key ID %08lX)"), (ulong)keyid[3] ); + sprintf( maink, KEYIDSTRING, keystr(&keyid[2]) ); else - maink = NULL; + *maink = 0; uid = get_user_id ( keyid, &uidlen ); timestr = strtimestamp (pk->timestamp); - atext = xasprintf ( - _("You need a passphrase to unlock the" - " secret key for user:\n" - "\"%.*s\"\n" - "%u-bit %s key, ID %08lX, created %s%s\n" ), - uidlen, uid, - nbits_from_pk (pk), algo_name, (ulong)keyid[1], timestr, - maink?maink:"" ); + +#undef KEYIDSTRING + +#define PROMPTSTRING _("You need a passphrase to unlock the secret" \ + " key for user:\n" \ + "\"%.*s\"\n" \ + "%u-bit %s key, ID %s, created %s%s\n" ) + + atext = xmalloc ( 100 + strlen (PROMPTSTRING) + + uidlen + 15 + strlen(algo_name) + keystrlen() + + strlen (timestr) + strlen (maink) ); + sprintf (atext, PROMPTSTRING, + (int)uidlen, uid, + nbits_from_pk (pk), algo_name, keystr(&keyid[0]), timestr, + maink ); xfree (uid); xfree (maink); - + +#undef PROMPTSTRING + { size_t dummy; fingerprint_from_pk( pk, fpr, &dummy ); @@ -708,165 +572,80 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, else atext = xstrdup ( _("Enter passphrase\n") ); - if (!prot) - { /* old style protocol */ - n = 4 + 20 + strlen (atext); - u32tobuf (buf, n ); - u32tobuf (buf+4, GPGA_PROT_GET_PASSPHRASE ); - memcpy (buf+8, fpr, 20 ); - if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) ) - goto failure; - xfree (atext); atext = NULL; - - /* get response */ - if ( readn ( fd, buf, 12, &nread ) ) - goto failure; - - if ( nread < 8 ) - { - log_error ( "response from agent too short\n" ); - goto failure; - } - n = buftou32 ( buf ); - reply = buftou32 ( buf + 4 ); - if ( reply == GPGA_PROT_GOT_PASSPHRASE ) - { - size_t pwlen; - size_t nn; - - if ( nread < 12 || n < 8 ) - { - log_error ( "response from agent too short\n" ); - goto failure; - } - pwlen = buftou32 ( buf + 8 ); - nread -= 12; - n -= 8; - if ( pwlen > n || n > 1000 ) - { - log_error (_("passphrase too long\n")); - /* or protocol error */ - goto failure; - } - /* we read the whole block in one chunk to give no hints - * on how long the passhrase actually is - this wastes some bytes - * but because we already have this padding we should not loosen - * this by issuing 2 read calls */ - pw = xmalloc_secure ( n+1 ); - if ( readn ( fd, pw, n, &nn ) ) - goto failure; - if ( n != nn ) - { - log_error (_("invalid response from agent\n")); - goto failure; - } - pw[pwlen] = 0; /* make a C String */ - agent_close (fd); - free_public_key( pk ); -#ifdef ENABLE_NLS - if (orig_codeset) - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); -#endif - xfree (orig_codeset); - return pw; - } - else if ( reply == GPGA_PROT_CANCELED ) - { - log_info ( _("cancelled by user\n") ); - if (canceled) - *canceled = 1; - } - else - log_error ( _("problem with the agent: agent returns 0x%lx\n"), - (ulong)reply ); - } - else - { /* The new Assuan protocol */ + { char *line, *p; - const unsigned char *s; - int i; + int i, rc; + struct agent_okay_cb_s okay_cb_parm; if (!tryagain_text) tryagain_text = "X"; else tryagain_text = _(tryagain_text); - /* We allocate 2 time the needed space for atext so that there - is enough space for escaping */ + /* We allocate 23 times the needed space for thye texts so that + there is enough space for escaping. */ line = xmalloc (15 + 46 - + 3*strlen (tryagain_text) + 3*strlen (atext) + 2); + + 3*strlen (atext) + + 3*strlen (custom_prompt? custom_prompt:"") + + (cacheid? (3*strlen (cacheid)): 0) + + 3*strlen (tryagain_text) + + 1); strcpy (line, "GET_PASSPHRASE "); p = line+15; - if (!mode && have_fpr) + if (!mode && cacheid) + { + p = percent_plus_escape (p, cacheid); + } + else if (!mode && have_fpr) { for (i=0; i < 20; i++, p +=2 ) sprintf (p, "%02X", fpr[i]); } else - *p++ = 'X'; /* no caching */ - *p++ = ' '; - for (i=0, s=tryagain_text; *s; s++) - { - if (*s < ' ' || *s == '+') - { - sprintf (p, "%%%02X", *s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; - } + *p++ = 'X'; /* No caching. */ *p++ = ' '; - *p++ = 'X'; /* Use the standard prompt */ + + p = percent_plus_escape (p, tryagain_text); *p++ = ' '; - /* copy description */ - for (i=0, s= atext; *s; s++) + + /* The prompt. */ + if (custom_prompt) { - if (*s < ' ' || *s == '+') - { - sprintf (p, "%%%02X", *s); - p += 3; - } - else if (*s == ' ') - *p++ = '+'; - else - *p++ = *s; + char *tmp = native_to_utf8 (custom_prompt); + p = percent_plus_escape (p, tmp); + xfree (tmp); } - *p++ = '\n'; - i = writen (fd, line, p - line); + else + *p++ = 'X'; /* Use the standard prompt. */ + *p++ = ' '; + + /* Copy description. */ + percent_plus_escape (p, atext); + + /* Call gpg-agent. */ + memset (&okay_cb_parm, 0, sizeof okay_cb_parm); + rc = assuan_transact2 (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL, + agent_okay_cb, &okay_cb_parm); + xfree (line); - if (i) - goto failure; xfree (atext); atext = NULL; - - /* get response */ - pw = xmalloc_secure (500); - nread = readline (fd, pw, 499); - if (nread < 3) - goto failure; - - 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 */ - agent_close (fd); - free_public_key( pk ); + if (!rc) + { + assert (okay_cb_parm.pw); + pw = okay_cb_parm.pw; + agent_close (ctx); + if (pk) + free_public_key( pk ); #ifdef ENABLE_NLS if (orig_codeset) - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); + bind_textdomain_codeset (PACKAGE, orig_codeset); #endif xfree (orig_codeset); return pw; } - else if (nread > 4 && !memcmp (pw, "ERR ", 4) - && (0xffff & strtoul (&pw[4], NULL, 0)) == 99) + else if (rc && (rc & 0xffff) == 99) { - /* 99 is GPG_ERR_CANCELED. FIXME: Check tail and overflow, - and use gpg-error. */ + /* 99 is GPG_ERR_CANCELED. */ log_info (_("cancelled by user\n") ); if (canceled) *canceled = 1; @@ -876,41 +655,40 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text, log_error (_("problem with the agent - disabling agent use\n")); opt.use_agent = 0; } - } + } failure: #ifdef ENABLE_NLS if (orig_codeset) - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); + { + bind_textdomain_codeset (PACKAGE, orig_codeset); + xfree (orig_codeset); + } #endif xfree (atext); - if ( fd != -1 ) - agent_close (fd); + agent_close (ctx); xfree (pw ); - free_public_key( pk ); - + if (pk) + free_public_key( pk ); + +#endif /*ENABLE_AGENT_SUPPORT*/ + return NULL; -#endif /* Posix or W32 */ } + /* - * Clear the cached passphrase + * Clear the cached passphrase. If CACHEID is not NULL, it will be + * used instead of a cache ID derived from KEYID. */ void -passphrase_clear_cache ( u32 *keyid, int algo ) +passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo ) { -#if defined(__riscos__) - return ; -#else - size_t n; - char buf[200]; - int fd = -1; - size_t nread; - u32 reply; +#ifdef ENABLE_AGENT_SUPPORT + assuan_context_t ctx = NULL; PKT_public_key *pk; byte fpr[MAX_FINGERPRINT_LEN]; - int prot; #if MAX_FINGERPRINT_LEN < 20 #error agent needs a 20 byte fingerprint @@ -919,71 +697,50 @@ passphrase_clear_cache ( u32 *keyid, int algo ) if (!opt.use_agent) return; - pk = xcalloc (1, sizeof *pk ); - memset (fpr, 0, MAX_FINGERPRINT_LEN ); - if( !keyid || get_pubkey( pk, keyid ) ) + if (!cacheid) { - log_debug ("oops, no key in passphrase_clear_cache\n"); - goto failure; /* oops: no key for some reason */ - } + pk = xcalloc (1, sizeof *pk); + memset (fpr, 0, MAX_FINGERPRINT_LEN ); + if( !keyid || get_pubkey( pk, keyid ) ) + { + goto failure; /* oops: no key for some reason */ + } - { - size_t dummy; - fingerprint_from_pk( pk, fpr, &dummy ); - } + { + size_t dummy; + fingerprint_from_pk( pk, fpr, &dummy ); + } + } + else + pk = NULL; - if ( (fd = agent_open (&prot)) == -1 ) + if ( !(ctx = agent_open (0, NULL)) ) goto failure; - if (!prot) - { - n = 4 + 20; - u32tobuf (buf, n ); - u32tobuf (buf+4, GPGA_PROT_CLEAR_PASSPHRASE ); - memcpy (buf+8, fpr, 20 ); - if ( writen ( fd, buf, 28 ) ) - goto failure; - - /* get response */ - if ( readn ( fd, buf, 8, &nread ) ) - goto failure; - - if ( nread < 8 ) { - log_error ( "response from agent too short\n" ); - goto failure; - } - - reply = buftou32 ( buf + 4 ); - if ( reply != GPGA_PROT_OKAY && reply != GPGA_PROT_NO_PASSPHRASE ) + { + char *line, *p; + int i, rc; + + if (cacheid) { - log_error ( _("problem with the agent: agent returns 0x%lx\n"), - (ulong)reply ); + line = xmalloc (17 + 3*strlen (cacheid) + 2); + strcpy (line, "CLEAR_PASSPHRASE "); + p = line+17; + p = percent_plus_escape (p, cacheid); } - } - else - { /* The assuan protocol */ - char *line, *p; - int i; - - line = xmalloc (17 + 40 + 2); - strcpy (line, "CLEAR_PASSPHRASE "); - p = line+17; - for (i=0; i < 20; i++, p +=2 ) - sprintf (p, "%02X", fpr[i]); - *p++ = '\n'; - i = writen (fd, line, p - line); + else + { + line = xmalloc (17 + 40 + 2); + strcpy (line, "CLEAR_PASSPHRASE "); + p = line+17; + for (i=0; i < 20; i++, p +=2 ) + sprintf (p, "%02X", fpr[i]); + } + *p = 0; + + rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); xfree (line); - if (i) - goto failure; - - /* get response */ - nread = readline (fd, buf, DIM(buf)-1); - if (nread < 3) - goto failure; - - if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) - ; - else + if (rc) { log_error (_("problem with the agent - disabling agent use\n")); opt.use_agent = 0; @@ -991,32 +748,85 @@ passphrase_clear_cache ( u32 *keyid, int algo ) } failure: - if (fd != -1) - agent_close (fd); - free_public_key( pk ); -#endif /* Posix or W32 */ + agent_close (ctx); + if (pk) + free_public_key( pk ); +#endif /*ENABLE_AGENT_SUPPORT*/ } - - /**************** - * Get a passphrase for the secret key with KEYID, display TEXT - * if the user needs to enter the passphrase. - * mode 0 = standard, 1 = same but don't show key info, - * 2 = create new passphrase - * Returns: a DEK with a session key; caller must free - * or NULL if the passphrase was not correctly repeated. - * (only for mode 2) - * a dek->keylen of 0 means: no passphrase entered. - * (only for mode 2) - * - * pubkey_algo is only informational. Note that TRYAGAIN_TEXT must - * not be translated as this is done within this function (required to - * switch to utf-8 when the agent is in use). If CANCELED is not - * NULL, it is set to 1 if the user choosed to cancel the operation, - * otherwise it will be set to 0. + * Ask for a passphrase and return that string. */ +char * +ask_passphrase (const char *description, + const char *tryagain_text, + const char *promptid, + const char *prompt, + const char *cacheid, int *canceled) +{ + char *pw = NULL; + + if (canceled) + *canceled = 0; + + if (!opt.batch && description) + { + if (strchr (description, '%')) + { + char *tmp = unescape_percent_string (description); + tty_printf ("\n%s\n", tmp); + xfree (tmp); + } + else + tty_printf ("\n%s\n",description); + } + + agent_died: + if ( opt.use_agent ) + { + pw = agent_get_passphrase (NULL, 0, cacheid, + tryagain_text, description, prompt, + canceled ); + if (!pw) + { + if (!opt.use_agent) + goto agent_died; + pw = NULL; + } + } + else if (fd_passwd) + { + pw = xmalloc_secure (strlen(fd_passwd)+1); + strcpy (pw, fd_passwd); + } + else if (opt.batch) + { + log_error(_("can't query passphrase in batch mode\n")); + pw = NULL; + } + else { + if (tryagain_text) + tty_printf(_("%s.\n"), tryagain_text); + pw = cpr_get_hidden(promptid? promptid : "passphrase.ask", + prompt?prompt : _("Enter passphrase: ") ); + tty_kill_prompt(); + } + + if (!pw || !*pw) + write_status( STATUS_MISSING_PASSPHRASE ); + + return pw; +} + + +/* Return a new DEK object Using the string-to-key sepcifier S2K. Use + * KEYID and PUBKEY_ALGO to prompt the user. + + MODE 0: Allow cached passphrase + 1: Ignore cached passphrase + 2: Ditto, but change the text to "repeat entry" +*/ DEK * passphrase_to_dek( u32 *keyid, int pubkey_algo, int cipher_algo, STRING2KEY *s2k, int mode, @@ -1034,12 +844,14 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, * Note: This must match the code in encode.c with opt.rfc1991 set */ s2k = &help_s2k; s2k->mode = 0; - s2k->hash_algo = opt.s2k_digest_algo; + s2k->hash_algo = S2K_DIGEST_ALGO; } + /* If we do not have a passphrase available in NEXT_PW and status + information are request, we print them now. */ if( !next_pw && is_status_enabled() ) { char buf[50]; - + if( keyid ) { u32 used_kid[2]; char *us; @@ -1055,7 +867,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, us = get_long_user_id_string( keyid ); write_status_text( STATUS_USERID_HINT, us ); - xfree (us); + xfree(us); sprintf( buf, "%08lX%08lX %08lX%08lX %d 0", (ulong)keyid[0], (ulong)keyid[1], @@ -1070,41 +882,55 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, } } + /* If we do have a keyID, we do not have a passphrase available in + NEXT_PW, we are not running in batch mode and we do not want to + ignore the passphrase cache (mode!=1), print a prompt with + information on that key. */ if( keyid && !opt.batch && !next_pw && mode!=1 ) { - PKT_public_key *pk = xcalloc (1, sizeof *pk ); - size_t n; + PKT_public_key *pk = xmalloc_clear( sizeof *pk ); char *p; - tty_printf(_("\nYou need a passphrase to unlock the secret key for\n" - "user: \"") ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - xfree (p); - tty_printf("\"\n"); + p=get_user_id_native(keyid); + tty_printf("\n"); + tty_printf(_("You need a passphrase to unlock the secret key for\n" + "user: \"%s\"\n"),p); + xfree(p); if( !get_pubkey( pk, keyid ) ) { - const char *s = gcry_pk_algo_name ( pk->pubkey_algo ); - tty_printf( _("%u-bit %s key, ID %08lX, created %s"), - nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1], + const char *s = pubkey_algo_to_string( pk->pubkey_algo ); + tty_printf( _("%u-bit %s key, ID %s, created %s"), + nbits_from_pk( pk ), s?s:"?", keystr(keyid), strtimestamp(pk->timestamp) ); if( keyid[2] && keyid[3] && keyid[0] != keyid[2] && keyid[1] != keyid[3] ) - tty_printf( _(" (main key ID %08lX)"), (ulong)keyid[3] ); + { + if(keystrlen()>10) + { + tty_printf("\n"); + tty_printf(_(" (subkey on main key ID %s)"), + keystr(&keyid[2]) ); + } + else + tty_printf( _(" (main key ID %s)"), keystr(&keyid[2]) ); + } tty_printf("\n"); } tty_printf("\n"); - free_public_key( pk ); + if (pk) + free_public_key( pk ); } agent_died: if( next_pw ) { + /* Simply return the passphrase we already have in NEXT_PW. */ pw = next_pw; next_pw = NULL; } else if ( opt.use_agent ) { - pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, - tryagain_text, canceled ); + /* Divert to the gpg-agent. */ + pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, NULL, + tryagain_text, NULL, NULL, canceled ); if (!pw) { if (!opt.use_agent) @@ -1112,7 +938,8 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, pw = xstrdup (""); } if( *pw && mode == 2 ) { - char *pw2 = agent_get_passphrase ( keyid, 2, NULL, canceled ); + char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL, NULL, + NULL, canceled ); if (!pw2) { if (!opt.use_agent) @@ -1124,22 +951,25 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, pw2 = xstrdup (""); } if( strcmp(pw, pw2) ) { - xfree (pw2); - xfree (pw); + xfree(pw2); + xfree(pw); return NULL; } - xfree (pw2); + xfree(pw2); } } else if( fd_passwd ) { - pw = xmalloc_secure ( strlen(fd_passwd)+1 ); + /* Return the passphrase we have store in FD_PASSWD. */ + pw = xmalloc_secure( strlen(fd_passwd)+1 ); strcpy( pw, fd_passwd ); } - else if( opt.batch ) { - log_error(_("can't query password in batchmode\n")); - pw = xstrdup ( "" ); /* return an empty passphrase */ - } + else if( opt.batch ) + { + log_error(_("can't query passphrase in batch mode\n")); + pw = xstrdup( "" ); /* return an empty passphrase */ + } else { + /* Read the passphrase from the tty or the command-fd. */ pw = cpr_get_hidden("passphrase.enter", _("Enter passphrase: ") ); tty_kill_prompt(); if( mode == 2 && !cpr_enabled() ) { @@ -1147,24 +977,27 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, _("Repeat passphrase: ") ); tty_kill_prompt(); if( strcmp(pw, pw2) ) { - xfree (pw2); - xfree (pw); + xfree(pw2); + xfree(pw); return NULL; } - xfree (pw2); + xfree(pw2); } } if( !pw || !*pw ) write_status( STATUS_MISSING_PASSPHRASE ); - dek = xcalloc_secure (1, sizeof *dek ); + /* Hash the passphrase and store it in a newly allocated DEK + object. Keep a copy of the passphrase in LAST_PW for use by + get_last_passphrase(). */ + dek = xmalloc_secure_clear ( sizeof *dek ); dek->algo = cipher_algo; if( !*pw && mode == 2 ) dek->keylen = 0; else hash_passphrase( dek, pw, s2k, mode==2 ); - xfree (last_pw); + xfree(last_pw); last_pw = pw; return dek; } @@ -1184,16 +1017,16 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) int pwlen = strlen(pw); assert( s2k->hash_algo ); - dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); + dek->keylen = cipher_get_keylen( dek->algo ) / 8; if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) BUG(); - gcry_md_open (&md, s2k->hash_algo, 1); + md = md_open( s2k->hash_algo, 1); for(pass=0; used < dek->keylen ; pass++ ) { if( pass ) { - gcry_md_reset(md); + md_reset(md); for(i=0; i < pass; i++ ) /* preset the hash context */ - gcry_md_putc (md, 0 ); + md_putc(md, 0 ); } if( s2k->mode == 1 || s2k->mode == 3 ) { @@ -1201,7 +1034,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) ulong count = len2; if( create && !pass ) { - gcry_randomize(s2k->salt, 8, GCRY_STRONG_RANDOM ); + randomize_buffer(s2k->salt, 8, 1); if( s2k->mode == 3 ) s2k->count = 96; /* 65536 iterations */ } @@ -1213,27 +1046,27 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) } /* a little bit complicated because we need a ulong for count */ while( count > len2 ) { /* maybe iterated+salted */ - gcry_md_write( md, s2k->salt, 8 ); - gcry_md_write( md, pw, pwlen ); + md_write( md, s2k->salt, 8 ); + md_write( md, pw, pwlen ); count -= len2; } if( count < 8 ) - gcry_md_write( md, s2k->salt, count ); + md_write( md, s2k->salt, count ); else { - gcry_md_write( md, s2k->salt, 8 ); + md_write( md, s2k->salt, 8 ); count -= 8; - gcry_md_write( md, pw, count ); + md_write( md, pw, count ); } } else - gcry_md_write( md, pw, pwlen ); - gcry_md_final ( md ); - i = gcry_md_get_algo_dlen (s2k->hash_algo); + md_write( md, pw, pwlen ); + md_final( md ); + i = md_digest_length( s2k->hash_algo ); if( i > dek->keylen - used ) i = dek->keylen - used; - memcpy( dek->key+used, gcry_md_read (md, s2k->hash_algo), i ); + memcpy( dek->key+used, md_read(md, s2k->hash_algo), i ); used += i; } - gcry_md_close (md); + md_close(md); } diff --git a/g10/photoid.c b/g10/photoid.c index 00cc7a273..cca32bc82 100644 --- a/g10/photoid.c +++ b/g10/photoid.c @@ -1,5 +1,5 @@ /* photoid.c - photo ID handling code - * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -28,6 +29,8 @@ # define VER_PLATFORM_WIN32_WINDOWS 1 # endif #endif + +#include "gpg.h" #include "packet.h" #include "status.h" #include "exec.h" @@ -35,21 +38,23 @@ #include "util.h" #include "i18n.h" #include "iobuf.h" -#include "memory.h" #include "options.h" #include "main.h" #include "photoid.h" +#include "ttyio.h" /* Generate a new photo id packet, or return NULL if canceled */ -PKT_user_id *generate_photo_id(PKT_public_key *pk) +PKT_user_id * +generate_photo_id(PKT_public_key *pk,const char *photo_name) { PKT_user_id *uid; int error=1,i; unsigned int len; - char *filename=NULL; + char *filename; byte *photo=NULL; byte header[16]; - iobuf_t file; + IOBUF file; + int overflow; header[0]=0x10; /* little side of photo header length */ header[1]=0; /* big side of photo header length */ @@ -60,48 +65,78 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) header[i]=0; #define EXTRA_UID_NAME_SPACE 71 - uid=xcalloc (1,sizeof(*uid)+71); + uid=xmalloc_clear(sizeof(*uid)+71); - printf(_("\nPick an image to use for your photo ID. " - "The image must be a JPEG file.\n" - "Remember that the image is stored within your public key. " - "If you use a\n" - "very large picture, your key will become very large as well!\n" - "Keeping the image close to 240x288 is a good size to use.\n")); + if(photo_name && *photo_name) + filename=make_filename(photo_name,(void *)NULL); + else + { + tty_printf(_("\nPick an image to use for your photo ID." + " The image must be a JPEG file.\n" + "Remember that the image is stored within your public key." + " If you use a\n" + "very large picture, your key will become very large" + " as well!\n" + "Keeping the image close to 240x288 is a good size" + " to use.\n")); + filename=NULL; + } while(photo==NULL) { - printf("\n"); + if(filename==NULL) + { + char *tempname; - xfree (filename); + tty_printf("\n"); - filename=cpr_get("photoid.jpeg.add", - _("Enter JPEG filename for photo ID: ")); + tty_enable_completion(NULL); - if(strlen(filename)==0) - goto scram; + tempname=cpr_get("photoid.jpeg.add", + _("Enter JPEG filename for photo ID: ")); + + tty_disable_completion(); + + filename=make_filename(tempname,(void *)NULL); + + xfree(tempname); + + if(strlen(filename)==0) + goto scram; + } file=iobuf_open(filename); + if (file && is_secured_file (iobuf_get_fd (file))) + { + iobuf_close (file); + file = NULL; + errno = EPERM; + } if(!file) { - log_error(_("Unable to open photo \"%s\": %s\n"), + log_error(_("unable to open JPEG file `%s': %s\n"), filename,strerror(errno)); + xfree(filename); + filename=NULL; continue; } - len=iobuf_get_filelength(file); - if(len>6144) + + len=iobuf_get_filelength(file, &overflow); + if(len>6144 || overflow) { - printf("This JPEG is really large (%d bytes) !\n",len); + tty_printf( _("This JPEG is really large (%d bytes) !\n"),len); if(!cpr_get_answer_is_yes("photoid.jpeg.size", - _("Are you sure you want to use it (y/N)? "))) + _("Are you sure you want to use it? (y/N) "))) { iobuf_close(file); + xfree(filename); + filename=NULL; continue; } } - photo=xmalloc (len); + photo=xmalloc(len); iobuf_read(file,photo,len); iobuf_close(file); @@ -109,9 +144,11 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) if(photo[0]!=0xFF || photo[1]!=0xD8 || photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F') { - log_error(_("\"%s\" is not a JPEG file\n"),filename); - xfree (photo); + log_error(_("`%s' is not a JPEG file\n"),filename); + xfree(photo); photo=NULL; + xfree(filename); + filename=NULL; continue; } @@ -132,8 +169,10 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) goto scram; case 0: free_attributes(uid); - xfree (photo); + xfree(photo); photo=NULL; + xfree(filename); + filename=NULL; continue; } } @@ -143,13 +182,13 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk) uid->ref=1; scram: - xfree (filename); - xfree (photo); + xfree(filename); + xfree(photo); if(error) { free_attributes(uid); - xfree (uid); + xfree(uid); return NULL; } @@ -283,7 +322,7 @@ void show_photos(const struct user_attribute *attrs, if(!command) goto fail; - name=xmalloc (16+strlen(EXTSEP_S)+ + name=xmalloc(16+strlen(EXTSEP_S)+ strlen(image_type_to_string(args.imagetype,0))+1); /* Make the filename. Notice we are not using the image @@ -302,7 +341,7 @@ void show_photos(const struct user_attribute *attrs, if(exec_write(&spawn,NULL,command,name,1,1)!=0) { - xfree (name); + xfree(name); goto fail; } @@ -311,7 +350,7 @@ void show_photos(const struct user_attribute *attrs, image_type_to_string(args.imagetype,2)); #endif - xfree (name); + xfree(name); fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild); diff --git a/g10/photoid.h b/g10/photoid.h index 187ca5ba2..d13669c52 100644 --- a/g10/photoid.h +++ b/g10/photoid.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* Photo ID functions */ @@ -25,7 +26,7 @@ #include "packet.h" -PKT_user_id *generate_photo_id(PKT_public_key *pk); +PKT_user_id *generate_photo_id(PKT_public_key *pk,const char *filename); int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len); char *image_type_to_string(byte type,int style); void show_photos(const struct user_attribute *attrs, diff --git a/g10/pipemode.c b/g10/pipemode.c deleted file mode 100644 index 9f2ddfdb5..000000000 --- a/g10/pipemode.c +++ /dev/null @@ -1,317 +0,0 @@ -/* pipemode.c - pipemode handler - * Copyright (C) 1998, 1990, 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 <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 "filter.h" - - -#define CONTROL_PACKET_SPACE 30 -#define FAKED_LITERAL_PACKET_SPACE (9+2+2) - - -enum pipemode_state_e { - STX_init = 0, - STX_wait_operation, - STX_begin, - STX_text, - STX_detached_signature, - STX_detached_signature_wait_text, - STX_signed_data, - STX_wait_init -}; - -struct pipemode_context_s { - enum pipemode_state_e state; - int operation; - int stop; - int block_mode; - UnarmorPump unarmor_ctx; -}; - - -static size_t -make_control ( byte *buf, int code, int operation ) -{ - const byte *sesmark; - size_t sesmarklen, n=0;; - - sesmark = get_session_marker( &sesmarklen ); - if ( sesmarklen > 20 ) - BUG(); - - buf[n++] = 0xff; /* new format, type 63, 1 length byte */ - n++; /* length will fixed below */ - memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen; - buf[n++] = CTRLPKT_PIPEMODE; - buf[n++] = code; - buf[n++] = operation; - buf[1] = n-2; - return n; -} - - - -static int -pipemode_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) -{ - size_t size = *ret_len; - struct pipemode_context_s *stx = opaque; - int rc=0; - size_t n = 0; - int esc = 0; - - if( control == IOBUFCTRL_UNDERFLOW ) { - *ret_len = 0; - /* reserve some space for one control packet */ - if ( size <= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE ) - BUG(); - size -= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE; - - if ( stx->block_mode ) { - /* reserve 2 bytes for the block length */ - buf[n++] = 0; - buf[n++] = 0; - } - - - while ( n < size ) { - /* FIXME: we have to make sure that we have a large enough - * buffer for a control packet even after we already read - * something. The easest way to do this is probably by ungetting - * the control sequence and returning the buffer we have - * already assembled */ - int c = iobuf_get (a); - if (c == -1) { - if ( stx->state != STX_init ) { - log_error ("EOF encountered at wrong state\n"); - stx->stop = 1; - return -1; - } - break; - } - if ( esc ) { - switch (c) { - case '@': - if ( stx->state == STX_text ) { - buf[n++] = c; - break; - } - else if ( stx->state == STX_detached_signature ) { - esc = 0; - goto do_unarmor; /* not a very elegant solution */ - } - else if ( stx->state == STX_detached_signature_wait_text) { - esc = 0; - break; /* just ignore it in this state */ - } - log_error ("@@ not allowed in current state\n"); - return -1; - case '<': /* begin of stream part */ - if ( stx->state != STX_init ) { - log_error ("nested begin of stream\n"); - stx->stop = 1; - return -1; - } - stx->state = STX_wait_operation; - stx->block_mode = 0; - unarmor_pump_release (stx->unarmor_ctx); - stx->unarmor_ctx = NULL; - break; - case '>': /* end of stream part */ - if ( stx->state != STX_wait_init ) { - log_error ("invalid state for @>\n"); - stx->stop = 1; - return -1; - } - stx->state = STX_init; - break; - case 'V': /* operation = verify */ - case 'E': /* operation = encrypt */ - case 'S': /* operation = sign */ - case 'B': /* operation = detach sign */ - case 'C': /* operation = clearsign */ - case 'D': /* operation = decrypt */ - if ( stx->state != STX_wait_operation ) { - log_error ("invalid state for operation code\n"); - stx->stop = 1; - return -1; - } - stx->operation = c; - if ( stx->operation == 'B') { - stx->state = STX_detached_signature; - if ( !opt.no_armor ) - stx->unarmor_ctx = unarmor_pump_new (); - } - else - stx->state = STX_begin; - n += make_control ( buf+n, 1, stx->operation ); - /* must leave after a control packet */ - goto leave; - - case 't': /* plaintext text follows */ - if ( stx->state == STX_detached_signature_wait_text ) - stx->state = STX_detached_signature; - if ( stx->state == STX_detached_signature ) { - if ( stx->operation != 'B' ) { - log_error ("invalid operation for this state\n"); - stx->stop = 1; - return -1; - } - stx->state = STX_signed_data; - n += make_control ( buf+n, 2, 'B' ); - /* and now we fake a literal data packet much the same - * as in armor.c */ - buf[n++] = 0xaf; /* old packet format, type 11, - var length */ - buf[n++] = 0; /* set the length header */ - buf[n++] = 6; - buf[n++] = 'b'; /* we ignore it anyway */ - buf[n++] = 0; /* namelength */ - memset(buf+n, 0, 4); /* timestamp */ - n += 4; - /* and return now so that we are sure to have - * more space in the bufer for the next control - * packet */ - stx->block_mode = 1; - goto leave2; - } - else { - log_error ("invalid state for @t\n"); - stx->stop = 1; - return -1; - } - break; - - case '.': /* ready */ - if ( stx->state == STX_signed_data ) { - if (stx->block_mode) { - buf[0] = (n-2) >> 8; - buf[1] = (n-2); - if ( buf[0] || buf[1] ) { - /* end of blocks marker */ - buf[n++] = 0; - buf[n++] = 0; - } - stx->block_mode = 0; - } - n += make_control ( buf+n, 3, 'B' ); - } - else { - log_error ("invalid state for @.\n"); - stx->stop = 1; - return -1; - } - stx->state = STX_wait_init; - goto leave; - - default: - log_error ("invalid escape sequence 0x%02x in stream\n", - c); - stx->stop = 1; - return -1; - } - esc = 0; - } - else if (c == '@') - esc = 1; - else if (stx->unarmor_ctx) { - do_unarmor: /* used to handle a @@ */ - c = unarmor_pump (stx->unarmor_ctx, c); - if ( !(c & ~255) ) - buf[n++] = c; - else if ( c < 0 ) { - /* end of armor or error - we don't care becuase - the armor can be modified anyway. The unarmored - stuff should stand for itself. */ - unarmor_pump_release (stx->unarmor_ctx); - stx->unarmor_ctx = NULL; - stx->state = STX_detached_signature_wait_text; - } - } - else if (stx->state == STX_detached_signature_wait_text) - ; /* just wait */ - else - buf[n++] = c; - } - - leave: - if ( !n ) { - stx->stop = 1; - rc = -1; /* eof */ - } - if ( stx->block_mode ) { - /* fixup the block length */ - buf[0] = (n-2) >> 8; - buf[1] = (n-2); - } - leave2: - /*log_hexdump ("pipemode:", buf, n );*/ - *ret_len = n; - } - else if( control == IOBUFCTRL_DESC ) - *(char**)buf = "pipemode_filter"; - return rc; -} - - - -void -run_in_pipemode(void) -{ - iobuf_t fp; - armor_filter_context_t afx; - struct pipemode_context_s stx; - int rc; - - memset( &afx, 0, sizeof afx); - memset( &stx, 0, sizeof stx); - - fp = iobuf_open("-"); - iobuf_push_filter (fp, pipemode_filter, &stx ); - - do { - write_status (STATUS_BEGIN_STREAM); - rc = proc_packets( NULL, fp ); - write_status (STATUS_END_STREAM); - } while ( !stx.stop ); - -} - - - - - - diff --git a/g10/pkclist.c b/g10/pkclist.c index 71e6492e8..793ac6902 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1,6 +1,6 @@ -/* pkclist.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002 - * 2003 Free Software Foundation, Inc. +/* pkclist.c - create a list of public keys + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,11 +27,11 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "main.h" #include "trustdb.h" @@ -39,10 +40,8 @@ #include "photoid.h" #include "i18n.h" - #define CONTROL_D ('D' - 'A' + 1) - /**************** * Show the revocation reason as it is stored with the given signature */ @@ -74,10 +73,10 @@ do_show_revocation_reason( PKT_signature *sig ) log_info( _("reason for revocation: ") ); if( text ) - fputs( text, log_get_stream () ); + fputs( text, log_get_stream() ); else - fprintf( log_get_stream (), "code=%02x", *p ); - putc( '\n', log_get_stream () ); + fprintf( log_get_stream(), "code=%02x", *p ); + putc( '\n', log_get_stream() ); n--; p++; pp = NULL; do { @@ -158,74 +157,6 @@ show_revocation_reason( PKT_public_key *pk, int mode ) } -static void -show_paths (const PKT_public_key *pk, int only_first ) -{ - log_debug("not yet implemented\n"); -#if 0 - void *context = NULL; - unsigned otrust, validity; - int last_level, level; - - last_level = 0; - while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){ - char *p; - int c, rc; - size_t n; - u32 keyid[2]; - PKT_public_key *pk ; - - if( level < last_level && only_first ) - break; - last_level = level; - - rc = keyid_from_lid( lid, keyid ); - - if( rc ) { - log_error("ooops: can't get keyid for lid %lu\n", lid); - return; - } - - pk = xcalloc (1, sizeof *pk ); - rc = get_pubkey( pk, keyid ); - if( rc ) { - log_error("key %08lX: public key not found: %s\n", - (ulong)keyid[1], gpg_strerror (rc) ); - return; - } - - tty_printf("%*s%4u%c/%08lX.%lu %s \"", - level*2, "", - nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], lid, datestr_from_pk( pk ) ); - - c = trust_letter(otrust); - if( c ) - putchar( c ); - else - printf( "%02x", otrust ); - putchar('/'); - c = trust_letter(validity); - if( c ) - putchar( c ); - else - printf( "%02x", validity ); - putchar(' '); - - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ), - xfree (p); - tty_printf("\"\n"); - free_public_key( pk ); - } - enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */ -#endif - tty_printf("\n"); -} - - - - /**************** * mode: 0 = standard * 1 = Without key info and additional menu option 'm' @@ -241,7 +172,6 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, unsigned *new_trust, int defer_help ) { char *p; - size_t n; u32 keyid[2]; int changed=0; int quit=0; @@ -252,7 +182,7 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, switch(minimum) { - default: min_num=0; break; + default: case TRUST_UNDEFINED: min_num=1; break; case TRUST_NEVER: min_num=2; break; case TRUST_MARGINAL: min_num=3; break; @@ -261,7 +191,18 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, keyid_from_pk (pk, keyid); for(;;) { - /* a string with valid answers */ + /* A string with valid answers. + + Note to translators: These are the allowed answers in lower and + uppercase. Below you will find the matching strings which + should be translated accordingly and the letter changed to + match the one in the answer string. + + i = please show me more information + m = back to the main menu + s = skip this key + q = quit + */ const char *ans = _("iImMqQsS"); if( !did_help ) @@ -270,69 +211,82 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, { KBNODE keyblock, un; - tty_printf(_("No trust value assigned to:\n" - "%4u%c/%08lX %s \""), - nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk( pk ) ); - p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ), - xfree (p); - tty_printf("\"\n"); + tty_printf(_("No trust value assigned to:\n")); + tty_printf("%4u%c/%s %s\n",nbits_from_pk( pk ), + pubkey_letter( pk->pubkey_algo ), + keystr(keyid), datestr_from_pk( pk ) ); + p=get_user_id_native(keyid); + tty_printf(_(" \"%s\"\n"),p); + xfree(p); keyblock = get_pubkeyblock (keyid); if (!keyblock) BUG (); - for (un=keyblock; un; un = un->next) { + for (un=keyblock; un; un = un->next) + { if (un->pkt->pkttype != PKT_USER_ID ) - continue; + continue; if (un->pkt->pkt.user_id->is_revoked ) - continue; + continue; if (un->pkt->pkt.user_id->is_expired ) - continue; + continue; /* Only skip textual primaries */ - if (un->pkt->pkt.user_id->is_primary && - !un->pkt->pkt.user_id->attrib_data ) - continue; + if (un->pkt->pkt.user_id->is_primary + && !un->pkt->pkt.user_id->attrib_data ) + continue; if((opt.verify_options&VERIFY_SHOW_PHOTOS) && un->pkt->pkt.user_id->attrib_data) - show_photos(un->pkt->pkt.user_id->attribs, - un->pkt->pkt.user_id->numattribs,pk,NULL); - - tty_printf (" %s", _(" aka \"")); - tty_print_utf8_string (un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len ); - tty_printf("\"\n"); - } + show_photos(un->pkt->pkt.user_id->attribs, + un->pkt->pkt.user_id->numattribs,pk,NULL); + + p=utf8_to_native(un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len,0); + + tty_printf(_(" aka \"%s\"\n"),p); + } print_fingerprint (pk, NULL, 2); tty_printf("\n"); + release_kbnode (keyblock); } - /* This string also used in keyedit.c:sign_uids */ - tty_printf (_( - "Please decide how far you trust this user to correctly\n" - "verify other users' keys (by looking at passports,\n" - "checking fingerprints from different sources...)?\n\n")); + + if(opt.trust_model==TM_DIRECT) + { + tty_printf(_("How much do you trust that this key actually " + "belongs to the named user?\n")); + tty_printf("\n"); + } + else + { + /* This string also used in keyedit.c:trustsig_prompt */ + tty_printf(_("Please decide how far you trust this user to" + " correctly verify other users' keys\n" + "(by looking at passports, checking fingerprints from" + " different sources, etc.)\n")); + tty_printf("\n"); + } + if(min_num<=1) - tty_printf (_(" %d = I don't know\n"), 1); + tty_printf (_(" %d = I don't know or won't say\n"), 1); if(min_num<=2) - tty_printf (_(" %d = I do NOT trust\n"), 2); + tty_printf (_(" %d = I do NOT trust\n"), 2); if(min_num<=3) - tty_printf (_(" %d = I trust marginally\n"), 3); + tty_printf (_(" %d = I trust marginally\n"), 3); if(min_num<=4) - tty_printf (_(" %d = I trust fully\n"), 4); + tty_printf (_(" %d = I trust fully\n"), 4); if (mode) - tty_printf (_(" %d = I trust ultimately\n"), 5); + tty_printf (_(" %d = I trust ultimately\n"), 5); #if 0 /* not yet implemented */ - tty_printf (_(" i = please show me more information\n") ); + tty_printf (" i = please show me more information\n"); #endif if( mode ) - tty_printf(_(" m = back to the main menu\n")); + tty_printf(_(" m = back to the main menu\n")); else { - tty_printf(_(" s = skip this key\n")); - tty_printf(_(" q = quit\n")); + tty_printf(_(" s = skip this key\n")); + tty_printf(_(" q = quit\n")); } tty_printf("\n"); if(minimum) @@ -364,7 +318,7 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, if (trust == TRUST_ULTIMATE && !cpr_get_answer_is_yes ("edit_ownertrust.set_ultimate.okay", _("Do you really want to set this key" - " to ultimate trust? "))) + " to ultimate trust? (y/N) "))) ; /* no */ else { @@ -395,9 +349,9 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, quit = 1; break ; /* back to the menu */ } - xfree (p); p = NULL; + xfree(p); p = NULL; } - xfree (p); + xfree(p); return show? -2: quit? -1 : changed; } @@ -419,7 +373,6 @@ edit_ownertrust (PKT_public_key *pk, int mode ) case -1: /* quit */ return -1; case -2: /* show info */ - show_paths(pk, 1); no_help = 1; break; case 1: /* trust value set */ @@ -439,93 +392,54 @@ edit_ownertrust (PKT_public_key *pk, int mode ) * Returns: true if we trust. */ static int -do_we_trust( PKT_public_key *pk, unsigned int *trustlevel ) +do_we_trust( PKT_public_key *pk, unsigned int trustlevel ) { - unsigned int trustmask = 0; - - /* FIXME: get_pubkey_byname already checks the validity and won't - * return keys which are either expired or revoked - so these - * question here won't get triggered. We have to find a solution - * for this. It might make sense to have a function in getkey.c - * which does only the basic checks and returns even revoked and - * expired keys. This fnction could then also returhn a list of - * keys if the speicified name is ambiguous - */ - if( (*trustlevel & TRUST_FLAG_REVOKED) ) { - log_info(_("key %08lX: key has been revoked!\n"), - (ulong)keyid_from_pk( pk, NULL) ); - show_revocation_reason( pk, 0 ); - if( opt.batch ) - return 0; /* no */ - - if( !cpr_get_answer_is_yes("revoked_key.override", - _("Use this key anyway? ")) ) - return 0; /* no */ - trustmask |= TRUST_FLAG_REVOKED; + /* We should not be able to get here with a revoked or expired + key */ + if(trustlevel & TRUST_FLAG_REVOKED + || trustlevel & TRUST_FLAG_SUB_REVOKED + || (trustlevel & TRUST_MASK) == TRUST_EXPIRED) + BUG(); + + if( opt.trust_model==TM_ALWAYS ) + { + if( opt.verbose ) + log_info("No trust check due to `--trust-model always' option\n"); + return 1; } - if( (*trustlevel & TRUST_FLAG_SUB_REVOKED) ) { - log_info(_("key %08lX: subkey has been revoked!\n"), - (ulong)keyid_from_pk( pk, NULL) ); - show_revocation_reason( pk, 0 ); - if( opt.batch ) - return 0; - if( !cpr_get_answer_is_yes("revoked_key.override", - _("Use this key anyway? ")) ) - return 0; - trustmask |= TRUST_FLAG_SUB_REVOKED; - } - *trustlevel &= ~trustmask; + switch(trustlevel & TRUST_MASK) + { + default: + log_error ("invalid trustlevel %u returned from validation layer\n", + trustlevel); + /* fall thru */ + case TRUST_UNKNOWN: + case TRUST_UNDEFINED: + log_info(_("%s: There is no assurance this key belongs" + " to the named user\n"),keystr_from_pk(pk)); + return 0; /* no */ - if( opt.trust_model==TM_ALWAYS ) { - if( opt.verbose ) - log_info("No trust check due to --trust-model always option\n"); - return 1; - } + case TRUST_MARGINAL: + log_info(_("%s: There is limited assurance this key belongs" + " to the named user\n"),keystr_from_pk(pk)); + return 1; /* yes */ - switch( (*trustlevel & TRUST_MASK) ) { - case TRUST_EXPIRED: - log_info(_("%08lX: key has expired\n"), - (ulong)keyid_from_pk( pk, NULL) ); - return 0; /* no */ - - default: - log_error ("invalid trustlevel %u returned from validation layer\n", - *trustlevel); - /* fall thru */ - case TRUST_UNKNOWN: - case TRUST_UNDEFINED: - log_info(_("%08lX: There is no assurance this key belongs " - "to the named user\n"),(ulong)keyid_from_pk( pk, NULL) ); - return 0; /* no */ - - /* No way to get here? */ - case TRUST_NEVER: - log_info(_("%08lX: We do NOT trust this key\n"), - (ulong)keyid_from_pk( pk, NULL) ); - return 0; /* no */ - - case TRUST_MARGINAL: - log_info(_("%08lX: There is limited assurance this key belongs " - "to the named user\n"),(ulong)keyid_from_pk(pk,NULL)); - return 1; /* yes */ - - case TRUST_FULLY: - if( opt.verbose ) - log_info(_("This key probably belongs to the named user\n")); - return 1; /* yes */ - - case TRUST_ULTIMATE: - if( opt.verbose ) - log_info(_("This key belongs to us\n")); - return 1; /* yes */ + case TRUST_FULLY: + if( opt.verbose ) + log_info(_("This key probably belongs to the named user\n")); + return 1; /* yes */ + + case TRUST_ULTIMATE: + if( opt.verbose ) + log_info(_("This key belongs to us\n")); + return 1; /* yes */ } - return 1; /* yes */ + return 1; /*NOTREACHED*/ } - /**************** * wrapper around do_we_trust, so we can ask whether to use the * key anyway. @@ -533,58 +447,34 @@ do_we_trust( PKT_public_key *pk, unsigned int *trustlevel ) static int do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel ) { - int rc; + int rc; - rc = do_we_trust( pk, &trustlevel ); + rc = do_we_trust( pk, trustlevel ); - if( (trustlevel & TRUST_FLAG_REVOKED) && !rc ) - return 0; - if( (trustlevel & TRUST_FLAG_SUB_REVOKED) && !rc ) - return 0; + if( !opt.batch && !rc ) + { + print_pubkey_info(NULL,pk); + print_fingerprint (pk, NULL, 2); + tty_printf("\n"); - if( !opt.batch && !rc ) { - u32 keyid[2]; - - keyid_from_pk( pk, keyid); - tty_printf( "%4u%c/%08lX %s \"", - nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], datestr_from_pk( pk ) ); - /* If the pk was chosen by a particular user ID, this is the - one to ask about. */ - if(pk->user_id) - tty_print_utf8_string(pk->user_id->name,pk->user_id->len); - else - { - size_t n; - char *p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - xfree (p); - } - tty_printf("\"\n"); - print_fingerprint (pk, NULL, 2); - tty_printf("\n"); - - tty_printf(_( -"It is NOT certain that the key belongs to the person named\n" -"in the user ID. If you *really* know what you are doing,\n" -"you may answer the next question with yes\n\n")); - - if( cpr_get_answer_is_yes("untrusted_key.override", - _("Use this key anyway? ")) ) - rc = 1; - - /* Hmmm: Should we set a flag to tell the user about - * his decision the next time he encrypts for this recipient? - */ - } - else if( opt.trust_model==TM_ALWAYS && !rc ) { - if( !opt.quiet ) - log_info(_("WARNING: Using untrusted key!\n")); + tty_printf( + _("It is NOT certain that the key belongs to the person named\n" + "in the user ID. If you *really* know what you are doing,\n" + "you may answer the next question with yes.\n")); + + tty_printf("\n"); + + if( cpr_get_answer_is_yes("untrusted_key.override", + _("Use this key anyway? (y/N) ")) ) rc = 1; + + /* Hmmm: Should we set a flag to tell the user about + * his decision the next time he encrypts for this recipient? + */ } - return rc; -} + return rc; +} /**************** @@ -594,7 +484,7 @@ do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel ) int check_signatures_trust( PKT_signature *sig ) { - PKT_public_key *pk = xcalloc (1, sizeof *pk ); + PKT_public_key *pk = xmalloc_clear( sizeof *pk ); unsigned int trustlevel; int rc=0; @@ -602,7 +492,7 @@ check_signatures_trust( PKT_signature *sig ) if (rc) { /* this should not happen */ log_error("Ooops; the key vanished - can't check the trust\n"); - rc = GPG_ERR_NO_PUBKEY; + rc = G10ERR_NO_PUBKEY; goto leave; } @@ -615,13 +505,21 @@ check_signatures_trust( PKT_signature *sig ) goto leave; } + if(pk->maybe_revoked && !pk->is_revoked) + log_info(_("WARNING: this key might be revoked (revocation key" + " not present)\n")); + trustlevel = get_validity (pk, NULL); if ( (trustlevel & TRUST_FLAG_REVOKED) ) { write_status( STATUS_KEYREVOKED ); - log_info(_("WARNING: This key has been revoked by its owner!\n")); - log_info(_(" This could mean that the signature is forgery.\n")); + if(pk->is_revoked==2) + log_info(_("WARNING: This key has been revoked by its" + " designated revoker!\n")); + else + log_info(_("WARNING: This key has been revoked by its owner!\n")); + log_info(_(" This could mean that the signature is forged.\n")); show_revocation_reason( pk, 0 ); } else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) ) @@ -634,6 +532,59 @@ check_signatures_trust( PKT_signature *sig ) if ((trustlevel & TRUST_FLAG_DISABLED)) log_info (_("Note: This key has been disabled.\n")); + /* If we have PKA information adjust the trustlevel. */ + if (sig->pka_info && sig->pka_info->valid) + { + unsigned char fpr[MAX_FINGERPRINT_LEN]; + PKT_public_key *primary_pk; + size_t fprlen; + int okay; + + + primary_pk = xmalloc_clear (sizeof *primary_pk); + get_pubkey (primary_pk, pk->main_keyid); + fingerprint_from_pk (primary_pk, fpr, &fprlen); + free_public_key (primary_pk); + + if ( fprlen == 20 && !memcmp (sig->pka_info->fpr, fpr, 20) ) + { + okay = 1; + write_status_text (STATUS_PKA_TRUST_GOOD, sig->pka_info->email); + log_info (_("Note: Verified signer's address is `%s'\n"), + sig->pka_info->email); + } + else + { + okay = 0; + write_status_text (STATUS_PKA_TRUST_BAD, sig->pka_info->email); + log_info (_("Note: Signer's address `%s' " + "does not match DNS entry\n"), sig->pka_info->email); + } + + switch ( (trustlevel & TRUST_MASK) ) + { + case TRUST_UNKNOWN: + case TRUST_UNDEFINED: + case TRUST_MARGINAL: + if (okay && opt.verify_options&VERIFY_PKA_TRUST_INCREASE) + { + trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_FULLY); + log_info (_("trustlevel adjusted to FULL" + " due to valid PKA info\n")); + } + /* (fall through) */ + case TRUST_FULLY: + if (!okay) + { + trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_NEVER); + log_info (_("trustlevel adjusted to NEVER" + " due to bad PKA info\n")); + } + break; + } + } + + /* Now let the user know what up with the trustlevel. */ switch ( (trustlevel & TRUST_MASK) ) { case TRUST_EXPIRED: @@ -701,7 +652,7 @@ release_pk_list( PK_LIST pk_list ) for( ; pk_list; pk_list = pk_rover ) { pk_rover = pk_list->next; free_public_key( pk_list->pk ); - xfree ( pk_list ); + xfree( pk_list ); } } @@ -730,10 +681,10 @@ default_recipient(void) int i; if( opt.def_recipient ) - return xstrdup ( opt.def_recipient ); + return xstrdup( opt.def_recipient ); if( !opt.def_recipient_self ) return NULL; - sk = xcalloc (1, sizeof *sk ); + sk = xmalloc_clear( sizeof *sk ); i = get_seckey_byname( sk, NULL, 0 ); if( i ) { free_secret_key( sk ); @@ -742,7 +693,7 @@ default_recipient(void) n = MAX_FINGERPRINT_LEN; fingerprint_from_sk( sk, fpr, &n ); free_secret_key( sk ); - p = xmalloc ( 2*n+3 ); + p = xmalloc( 2*n+3 ); *p++ = '0'; *p++ = 'x'; for(i=0; i < n; i++ ) @@ -797,315 +748,423 @@ expand_group(STRLIST input) return output; } + +/* This is the central function to collect the keys for recipients. + It is thus used to prepare a public key encryption. encrypt-to + keys, default keys and the keys for the actual recipients are all + collected here. When not in batch mode and no recipient has been + passed on the commandline, the function will also ask for + recipients. + + RCPTS is a string list with the recipients; NULL is an allowed + value but not very useful. Group expansion is done on these names; + they may be in any of the user Id formats we can handle. The flags + bits for each string in the string list are used for: + Bit 0: This is an encrypt-to recipient. + Bit 1: This is a hidden recipient. + + USE is the desired use for the key - usually PUBKEY_USAGE_ENC. + RET_PK_LIST. + + On success a list of keys is stored at the address RET_PK_LIST; the + caller must free this list. On error the value at this address is + not changed. + */ int -build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) +build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) { - PK_LIST pk_list = NULL; - PKT_public_key *pk=NULL; - int rc=0; - int any_recipients=0; - STRLIST rov,remusr; - char *def_rec = NULL; - - if(opt.grouplist) - remusr=expand_group(rcpts); - else - remusr=rcpts; - - /* check whether there are any recipients in the list and build the - * list of the encrypt-to ones (we always trust them) */ - for( rov = remusr; rov; rov = rov->next ) { - if( !(rov->flags & 1) ) - { - any_recipients = 1; + PK_LIST pk_list = NULL; + PKT_public_key *pk=NULL; + int rc=0; + int any_recipients=0; + STRLIST rov,remusr; + char *def_rec = NULL; - if((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8)) - { - log_info(_("you may not use %s while in %s mode\n"), - "--hidden-recipient", - compliance_option_string()); + /* Try to expand groups if any have been defined. */ + if (opt.grouplist) + remusr = expand_group (rcpts); + else + remusr = rcpts; - compliance_failure(); - } - } - else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { - pk = xcalloc (1, sizeof *pk ); - pk->req_usage = use; - /* We can encrypt-to a disabled key */ - if( (rc = get_pubkey_byname( pk, rov->d, NULL, NULL, 1 )) ) { - free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) ); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - rov->d, strlen (rov->d), -1); - goto fail; + /* Check whether there are any recipients in the list and build the + * list of the encrypt-to ones (we always trust them). */ + for ( rov = remusr; rov; rov = rov->next ) + { + if ( !(rov->flags & 1) ) + { + /* This is a regular recipient; i.e. not an encrypt-to + one. */ + any_recipients = 1; + + /* Hidden recipients are not allowed while in PGP mode, + issue a warning and switch into GnuPG mode. */ + if ((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8)) + { + log_info(_("you may not use %s while in %s mode\n"), + "--hidden-recipient", + compliance_option_string()); + + compliance_failure(); } - else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use )) ) { - /* Skip the actual key if the key is already present - * in the list */ - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("%s: skipped: public key already present\n"), - rov->d); - } - else { - PK_LIST r; - r = xmalloc ( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->flags = (rov->flags&2)?1:0; - pk_list = r; - - if(r->flags&1 && (PGP2 || PGP6 || PGP7 || PGP8)) - { - log_info(_("you may not use %s while in %s mode\n"), - "--hidden-encrypt-to", - compliance_option_string()); - - compliance_failure(); - } - } - } - else { - free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) ); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - rov->d, strlen (rov->d), -1); - goto fail; - } - } + } + else if ( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) + { + /* Encryption has been requested and --encrypt-to has not + been disabled. Check this encrypt-to key. */ + pk = xmalloc_clear( sizeof *pk ); + pk->req_usage = use; + + /* We explicitly allow encrypt-to to an disabled key; thus + we pass 1 as last argument. */ + if ( (rc = get_pubkey_byname ( pk, rov->d, NULL, NULL, 1 )) ) + { + free_public_key ( pk ); pk = NULL; + log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + rov->d, strlen (rov->d), -1); + goto fail; + } + else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) ) + { + /* Skip the actual key if the key is already present + * in the list. Add it to our list if not. */ + if (key_present_in_pk_list(pk_list, pk) == 0) + { + free_public_key (pk); pk = NULL; + log_info (_("%s: skipped: public key already present\n"), + rov->d); + } + else + { + PK_LIST r; + r = xmalloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = (rov->flags&2)?1:0; + pk_list = r; + + /* Hidden encrypt-to recipients are not allowed while + in PGP mode, issue a warning and switch into + GnuPG mode. */ + if ((r->flags&1) && (PGP2 || PGP6 || PGP7 || PGP8)) + { + log_info(_("you may not use %s while in %s mode\n"), + "--hidden-encrypt-to", + compliance_option_string()); + + compliance_failure(); + } + } + } + else + { + /* The public key is not usable for encryption or not + available. */ + free_public_key( pk ); pk = NULL; + log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + rov->d, strlen (rov->d), -1); + goto fail; + } + } } - if( !any_recipients && !opt.batch ) { /* ask */ - int have_def_rec; - char *answer=NULL; - STRLIST backlog=NULL; - - def_rec = default_recipient(); - have_def_rec = !!def_rec; - if( !have_def_rec ) - tty_printf(_( - "You did not specify a user ID. (you may use \"-r\")\n")); - for(;;) { - rc = 0; - xfree (answer); - if( have_def_rec ) { - answer = def_rec; - def_rec = NULL; - } - else if (backlog) { - answer = strlist_pop (&backlog); - } - else { - answer = cpr_get_utf8("pklist.user_id.enter", - _("\nEnter the user ID. End with an empty line: ")); - trim_spaces(answer); - cpr_kill_prompt(); - } - if( !answer || !*answer ) { - xfree (answer); - break; - } - if(expand_id(answer,&backlog,0)) - continue; - if( pk ) - free_public_key( pk ); - pk = xcalloc (1, sizeof *pk ); - pk->req_usage = use; - rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); - if( rc ) - tty_printf(_("No such user ID.\n")); - else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use)) ) { - if( have_def_rec ) { - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("skipped: public key " - "already set as default recipient\n") ); - } - else { - PK_LIST r = xmalloc ( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->flags = 0; /* no throwing default ids */ - pk_list = r; - } - any_recipients = 1; - continue; - } - else { - int trustlevel; + /* If we don't have any recipients yet and we are not in batch mode + drop into interactive selection mode. */ + if ( !any_recipients && !opt.batch ) + { + int have_def_rec; + char *answer = NULL; + STRLIST backlog = NULL; + + if (pk_list) + any_recipients = 1; + def_rec = default_recipient(); + have_def_rec = !!def_rec; + if ( !have_def_rec ) + tty_printf(_("You did not specify a user ID. (you may use \"-r\")\n")); + + for (;;) + { + rc = 0; + xfree(answer); + if ( have_def_rec ) + { + /* A default recipient is taken as the first entry. */ + answer = def_rec; + def_rec = NULL; + } + else if (backlog) + { + /* This is part of our trick to expand and display groups. */ + answer = pop_strlist (&backlog); + } + else + { + /* Show the list of already collected recipients and ask + for more. */ + PK_LIST iter; + + tty_printf("\n"); + tty_printf(_("Current recipients:\n")); + for (iter=pk_list;iter;iter=iter->next) + { + u32 keyid[2]; + + keyid_from_pk(iter->pk,keyid); + tty_printf("%4u%c/%s %s \"", + nbits_from_pk(iter->pk), + pubkey_letter(iter->pk->pubkey_algo), + keystr(keyid), + datestr_from_pk(iter->pk)); + + if (iter->pk->user_id) + tty_print_utf8_string(iter->pk->user_id->name, + iter->pk->user_id->len); + else + { + size_t n; + char *p = get_user_id( keyid, &n ); + tty_print_utf8_string( p, n ); + xfree(p); + } + tty_printf("\"\n"); + } + + answer = cpr_get_utf8("pklist.user_id.enter", + _("\nEnter the user ID. " + "End with an empty line: ")); + trim_spaces(answer); + cpr_kill_prompt(); + } + + if ( !answer || !*answer ) + { + xfree(answer); + break; /* No more recipients entered - get out of loop. */ + } + + /* Do group expand here too. The trick here is to continue + the loop if any expansion occured. The code above will + then list all expanded keys. */ + if (expand_id(answer,&backlog,0)) + continue; + + /* Get and check key for the current name. */ + if (pk) + free_public_key (pk); + pk = xmalloc_clear( sizeof *pk ); + pk->req_usage = use; + rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); + if (rc) + tty_printf(_("No such user ID.\n")); + else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) + { + if ( have_def_rec ) + { + /* No validation for a default recipient. */ + if (!key_present_in_pk_list(pk_list, pk)) + { + free_public_key (pk); pk = NULL; + log_info (_("skipped: public key " + "already set as default recipient\n") ); + } + else + { + PK_LIST r = xmalloc (sizeof *r); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = 0; /* No throwing default ids. */ + pk_list = r; + } + any_recipients = 1; + continue; + } + else + { /* Check validity of this key. */ + int trustlevel; - trustlevel = get_validity (pk, pk->user_id); - if( (trustlevel & TRUST_FLAG_DISABLED) ) { - tty_printf(_("Public key is disabled.\n") ); - } - else if( do_we_trust_pre( pk, trustlevel ) ) { - /* Skip the actual key if the key is already present - * in the list */ - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("skipped: public key already set\n") ); - } - else { - PK_LIST r; - u32 keyid[2]; - - keyid_from_pk( pk, keyid); - tty_printf("Added %4u%c/%08lX %s \"", - nbits_from_pk( pk ), - pubkey_letter( pk->pubkey_algo ), - (ulong)keyid[1], - datestr_from_pk( pk ) ); - if(pk->user_id) - tty_print_utf8_string(pk->user_id->name, - pk->user_id->len); - else - { - size_t n; - char *p = get_user_id( keyid, &n ); - tty_print_utf8_string( p, n ); - xfree (p); - } - tty_printf("\"\n"); - - r = xmalloc ( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->flags = 0; /* no throwing interactive ids */ - pk_list = r; - } - any_recipients = 1; - continue; - } - } - } - xfree (def_rec); def_rec = NULL; - have_def_rec = 0; - } - if( pk ) { - free_public_key( pk ); - pk = NULL; - } + trustlevel = get_validity (pk, pk->user_id); + if ( (trustlevel & TRUST_FLAG_DISABLED) ) + { + tty_printf (_("Public key is disabled.\n") ); + } + else if ( do_we_trust_pre (pk, trustlevel) ) + { + /* Skip the actual key if the key is already + * present in the list */ + if (!key_present_in_pk_list(pk_list, pk)) + { + free_public_key(pk); pk = NULL; + log_info(_("skipped: public key already set\n") ); + } + else + { + PK_LIST r; + r = xmalloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = 0; /* No throwing interactive ids. */ + pk_list = r; + } + any_recipients = 1; + continue; + } + } + } + xfree(def_rec); def_rec = NULL; + have_def_rec = 0; + } + if ( pk ) + { + free_public_key( pk ); + pk = NULL; + } } - else if( !any_recipients && (def_rec = default_recipient()) ) { - pk = xcalloc (1, sizeof *pk ); - pk->req_usage = use; - /* The default recipient may be disabled */ - rc = get_pubkey_byname( pk, def_rec, NULL, NULL, 1 ); - if( rc ) - log_error(_("unknown default recipient `%s'\n"), def_rec ); - else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use)) ) { - /* Mark any_recipients here since the default recipient + else if ( !any_recipients && (def_rec = default_recipient()) ) + { + /* We are in batch mode and have only a default recipient. */ + pk = xmalloc_clear( sizeof *pk ); + pk->req_usage = use; + + /* The default recipient is allowed to be disabled; thus pass 1 + as last argument. */ + rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1); + if (rc) + log_error(_("unknown default recipient \"%s\"\n"), def_rec ); + else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) + { + /* Mark any_recipients here since the default recipient would have been used if it wasn't already there. It doesn't really matter if we got this key from the default recipient or an encrypt-to. */ - any_recipients = 1; - if (key_present_in_pk_list(pk_list, pk) == 0) - log_info(_("skipped: public key already set as default recipient\n")); - else { - PK_LIST r = xmalloc ( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->flags = 0; /* no throwing default ids */ - pk_list = r; - } - } - if( pk ) { - free_public_key( pk ); - pk = NULL; - } - xfree (def_rec); def_rec = NULL; + any_recipients = 1; + if (!key_present_in_pk_list(pk_list, pk)) + log_info (_("skipped: public key already set " + "as default recipient\n")); + else + { + PK_LIST r = xmalloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = 0; /* No throwing default ids. */ + pk_list = r; + } + } + if ( pk ) + { + free_public_key( pk ); + pk = NULL; + } + xfree(def_rec); def_rec = NULL; } - else { - any_recipients = 0; - for(; remusr; remusr = remusr->next ) { - if( (remusr->flags & 1) ) - continue; /* encrypt-to keys are already handled */ - - pk = xcalloc (1, sizeof *pk ); - pk->req_usage = use; - if( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0 )) ) { - free_public_key( pk ); pk = NULL; - log_error(_("%s: skipped: %s\n"), remusr->d, gpg_strerror (rc) ); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - remusr->d, strlen (remusr->d), - -1); - goto fail; - } - else if( !(rc=openpgp_pk_test_algo (pk->pubkey_algo, use )) ) { - int trustlevel; - - trustlevel = get_validity (pk, pk->user_id); - if( (trustlevel & TRUST_FLAG_DISABLED) ) { - free_public_key(pk); pk = NULL; - log_info(_("%s: skipped: public key is disabled\n"), - remusr->d); - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - remusr->d, - strlen (remusr->d), - -1); - rc = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); - goto fail; - } - else if( do_we_trust_pre( pk, trustlevel ) ) { - /* note: do_we_trust may have changed the trustlevel */ - - /* We have at least one valid recipient. It doesn't matters - * if this recipient is already present. */ - any_recipients = 1; - - /* Skip the actual key if the key is already present - * in the list */ - if (key_present_in_pk_list(pk_list, pk) == 0) { - free_public_key(pk); pk = NULL; - log_info(_("%s: skipped: public key already present\n"), - remusr->d); - } - else { - PK_LIST r; - r = xmalloc ( sizeof *r ); - r->pk = pk; pk = NULL; - r->next = pk_list; - r->flags = (remusr->flags&2)?1:0; - pk_list = r; - } - } - else { /* we don't trust this pk */ - free_public_key( pk ); pk = NULL; - write_status_text_and_buffer (STATUS_INV_RECP, "10 ", - remusr->d, - strlen (remusr->d), - -1); - rc = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); - goto fail; - } - } - else { - free_public_key( pk ); pk = NULL; - write_status_text_and_buffer (STATUS_INV_RECP, "0 ", - remusr->d, - strlen (remusr->d), - -1); - log_error(_("%s: skipped: %s\n"), remusr->d, gpg_strerror (rc) ); - goto fail; - } - } + else + { + /* General case: Check all keys. */ + any_recipients = 0; + for (; remusr; remusr = remusr->next ) + { + if ( (remusr->flags & 1) ) + continue; /* encrypt-to keys are already handled. */ + + pk = xmalloc_clear( sizeof *pk ); + pk->req_usage = use; + if ( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0 )) ) + { + /* Key not found or other error. */ + free_public_key( pk ); pk = NULL; + log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + remusr->d, strlen (remusr->d), + -1); + goto fail; + } + else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) + { + /* Key found and usable. Check validity. */ + int trustlevel; + + trustlevel = get_validity (pk, pk->user_id); + if ( (trustlevel & TRUST_FLAG_DISABLED) ) + { + /*Key has been disabled. */ + free_public_key(pk); pk = NULL; + log_info(_("%s: skipped: public key is disabled\n"), + remusr->d); + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + remusr->d, + strlen (remusr->d), + -1); + rc=G10ERR_UNU_PUBKEY; + goto fail; + } + else if ( do_we_trust_pre( pk, trustlevel ) ) + { + /* Note: do_we_trust may have changed the trustlevel */ + + /* We have at least one valid recipient. It doesn't + * matters if this recipient is already present. */ + any_recipients = 1; + + /* Skip the actual key if the key is already present + * in the list */ + if (!key_present_in_pk_list(pk_list, pk)) + { + free_public_key(pk); pk = NULL; + log_info(_("%s: skipped: public key already present\n"), + remusr->d); + } + else + { + PK_LIST r; + r = xmalloc( sizeof *r ); + r->pk = pk; pk = NULL; + r->next = pk_list; + r->flags = (remusr->flags&2)?1:0; + pk_list = r; + } + } + else + { /* We don't trust this key. */ + free_public_key( pk ); pk = NULL; + write_status_text_and_buffer (STATUS_INV_RECP, "10 ", + remusr->d, + strlen (remusr->d), + -1); + rc=G10ERR_UNU_PUBKEY; + goto fail; + } + } + else + { + /* Key found but not usable for us (e.g. sign-only key). */ + free_public_key( pk ); pk = NULL; + write_status_text_and_buffer (STATUS_INV_RECP, "0 ", + remusr->d, + strlen (remusr->d), + -1); + log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); + goto fail; + } + } } - - if( !rc && !any_recipients ) { - log_error(_("no valid addressees\n")); - write_status_text (STATUS_NO_RECP, "0"); - rc = GPG_ERR_NO_USER_ID; + + if ( !rc && !any_recipients ) + { + log_error(_("no valid addressees\n")); + write_status_text (STATUS_NO_RECP, "0"); + rc = G10ERR_NO_USER_ID; } - + fail: - if( rc ) - release_pk_list( pk_list ); - else - *ret_pk_list = pk_list; - if(opt.grouplist) - free_strlist(remusr); - return rc; + if ( rc ) + release_pk_list( pk_list ); + else + *ret_pk_list = pk_list; + if (opt.grouplist) + free_strlist(remusr); + return rc; } @@ -1136,16 +1195,18 @@ algo_available( preftype_t preftype, int algo, void *hint ) && algo != CIPHER_ALGO_CAST5)) return 0; - if((PGP7 || PGP8) && (algo != CIPHER_ALGO_IDEA - && algo != CIPHER_ALGO_3DES - && algo != CIPHER_ALGO_CAST5 - && algo != CIPHER_ALGO_AES - && algo != CIPHER_ALGO_AES192 - && algo != CIPHER_ALGO_AES256 - && algo != CIPHER_ALGO_TWOFISH)) + if(PGP7 && (algo != CIPHER_ALGO_IDEA + && algo != CIPHER_ALGO_3DES + && algo != CIPHER_ALGO_CAST5 + && algo != CIPHER_ALGO_AES + && algo != CIPHER_ALGO_AES192 + && algo != CIPHER_ALGO_AES256 + && algo != CIPHER_ALGO_TWOFISH)) return 0; - return algo && !gcry_cipher_test_algo (algo); + /* PGP8 supports all the ciphers we do.. */ + + return algo && !openpgp_cipher_test_algo ( algo ); } else if( preftype == PREFTYPE_HASH ) { @@ -1164,14 +1225,16 @@ algo_available( preftype_t preftype, int algo, void *hint ) && algo != DIGEST_ALGO_SHA256)) return 0; - return algo && !gcry_md_test_algo( algo ); + return algo && !openpgp_md_test_algo (algo); } else if( preftype == PREFTYPE_ZIP ) { - if((PGP6 || PGP7 || PGP8) && (algo != COMPRESS_ALGO_NONE - && algo != COMPRESS_ALGO_ZIP)) + if((PGP6 || PGP7) && (algo != COMPRESS_ALGO_NONE + && algo != COMPRESS_ALGO_ZIP)) return 0; + /* PGP8 supports all the compression algos we do */ + return !check_compress_algo( algo ); } else @@ -1362,7 +1425,7 @@ select_mdc_from_pklist (PK_LIST pk_list) int mdc; if (pkr->pk->user_id) /* selected by user ID */ - mdc = pkr->pk->user_id->mdc_feature; + mdc = pkr->pk->user_id->flags.mdc; else mdc = pkr->pk->mdc_feature; if (!mdc) diff --git a/g10/plaintext.c b/g10/plaintext.c index d84a523fe..bd908e551 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -1,6 +1,6 @@ /* plaintext.c - process plaintext packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,13 +26,13 @@ #include <string.h> #include <errno.h> #include <assert.h> +#include <sys/types.h> #ifdef HAVE_DOSISH_SYSTEM #include <fcntl.h> /* for setmode() */ #endif #include "gpg.h" #include "util.h" -#include "memory.h" #include "options.h" #include "packet.h" #include "ttyio.h" @@ -41,7 +42,6 @@ #include "i18n.h" - /**************** * Handle a plaintext packet. If MFX is not NULL, update the MDs * Note: we should use the filter stuff here, but we have to add some @@ -50,27 +50,41 @@ */ int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, - int nooutput, int clearsig, int *create_failed ) + int nooutput, int clearsig ) { char *fname = NULL; FILE *fp = NULL; + static off_t count=0; int rc = 0; int c; - int convert = pt->mode == 't'; + int convert = (pt->mode == 't' || pt->mode == 'u'); #ifdef __riscos__ int filetype = 0xfff; #endif - int dummy_create_failed; - if (!create_failed) - create_failed = &dummy_create_failed; - *create_failed = 0; + /* Let people know what the plaintext info is. This allows the + receiving program to try and do something different based on + the format code (say, recode UTF-8 to local). */ + if(!nooutput && is_status_enabled()) + { + char status[50]; + + sprintf(status,"%X %lu ",(byte)pt->mode,(ulong)pt->timestamp); + write_status_text_and_buffer(STATUS_PLAINTEXT, + status,pt->name,pt->namelen,0); + + if(!pt->is_partial) + { + sprintf(status,"%lu",(ulong)pt->len); + write_status_text(STATUS_PLAINTEXT_LENGTH,status); + } + } /* create the filename as C string */ if( nooutput ) ; else if( opt.outfile ) { - fname = xmalloc ( strlen( opt.outfile ) + 1); + fname = xmalloc( strlen( opt.outfile ) + 1); strcpy(fname, opt.outfile ); } else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) { @@ -82,8 +96,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( !fname ) fname = ask_outfile_name( pt->name, pt->namelen ); if( !fname ) { - *create_failed = 1; - rc = GPG_ERR_GENERAL; + rc = gpg_error (GPG_ERR_GENERAL) /* Can't create file. */ goto leave; } } @@ -93,20 +106,20 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( nooutput ) ; - else if( !*fname || (*fname=='-' && !fname[1])) { - /* no filename or "-" given; write to stdout */ + else if ( iobuf_is_pipe_filename (fname) || !*fname) + { + /* No filename or "-" given; write to stdout. */ fp = stdout; #ifdef HAVE_DOSISH_SYSTEM setmode ( fileno(fp) , O_BINARY ); #endif - } + } else { while( !overwrite_filep (fname) ) { char *tmp = ask_outfile_name (NULL, 0); if ( !tmp || !*tmp ) { xfree (tmp); - *create_failed = 1; - rc = GPG_ERR_GENERAL; + rc = G10ERR_CREATE_FILE; goto leave; } xfree (fname); @@ -117,26 +130,34 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, #ifndef __riscos__ if( fp || nooutput ) ; + else if (is_secured_filename (fname)) + { + errno = EPERM; + log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + goto leave; + } else if( !(fp = fopen(fname,"wb")) ) { - rc = gpg_error_from_errno (errno); log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - *create_failed = 1; + rc = G10ERR_CREATE_FILE; goto leave; } #else /* __riscos__ */ - /* Convert all '.' in fname to '/' -- we don't create directories! */ - for( c=0; fname[c]; ++c ) - if( fname[c] == '.' ) - fname[c] = '/'; + /* If no output filename was given, i.e. we constructed it, + convert all '.' in fname to '/' but not vice versa as + we don't create directories! */ + if( !opt.outfile ) + for( c=0; fname[c]; ++c ) + if( fname[c] == '.' ) + fname[c] = '/'; if( fp || nooutput ) ; else { fp = fopen(fname,"wb"); if( !fp ) { - rc == gpg_error_from_errno (errno); log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - *create_failed = 1; + rc = G10ERR_CREATE_FILE; if (errno == 106) log_info("Do output file and input file have the same name?\n"); goto leave; @@ -156,15 +177,21 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, #endif /* __riscos__ */ if( !pt->is_partial ) { - /* we have an actual length (which might be zero). */ - assert( !clearsig ); + /* We have an actual length (which might be zero). */ + + if (clearsig) { + log_error ("clearsig encountered while not expected\n"); + rc = G10ERR_UNEXPECTED; + goto leave; + } + if( convert ) { /* text mode */ for( ; pt->len; pt->len-- ) { if( (c = iobuf_get(pt->buf)) == -1 ) { - rc = gpg_error_from_errno (errno); - log_error("Problem reading source (%u bytes remaining)\n", - (unsigned)pt->len); - goto leave; + rc = gpg_error_from_errno (errno); + log_error ("problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); + goto leave; } if( mfx->md ) gcry_md_putc (mfx->md, c ); @@ -172,65 +199,93 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( c == '\r' ) /* convert to native line ending */ continue; /* fixme: this hack might be too simple */ #endif - if( fp ) { - if( putc( c, fp ) == EOF ) { - rc = gpg_error_from_errno (errno); + if( fp ) + { + if(opt.max_output && (++count)>opt.max_output) + { + log_error("Error writing to `%s': %s\n", + fname,"exceeded --max-output limit\n"); + rc = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + else if( putc( c, fp ) == EOF ) + { log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; goto leave; - } - } + } + } } } else { /* binary mode */ - byte *buffer = xmalloc ( 32768 ); + byte *buffer = xmalloc( 32768 ); while( pt->len ) { int len = pt->len > 32768 ? 32768 : pt->len; len = iobuf_read( pt->buf, buffer, len ); if( len == -1 ) { - rc = gpg_error_from_errno (errno); log_error("Problem reading source (%u bytes remaining)\n", (unsigned)pt->len); - xfree ( buffer ); + rc = G10ERR_READ_FILE; + xfree( buffer ); goto leave; } if( mfx->md ) - gcry_md_write( mfx->md, buffer, len ); - if( fp ) { - if( fwrite( buffer, 1, len, fp ) != len ) { - rc = gpg_error_from_errno (errno); + gcry_md_write ( mfx->md, buffer, len ); + if( fp ) + { + if(opt.max_output && (count+=len)>opt.max_output) + { + log_error("Error writing to `%s': %s\n", + fname,"exceeded --max-output limit\n"); + rc = G10ERR_WRITE_FILE; + xfree( buffer ); + goto leave; + } + else if( fwrite( buffer, 1, len, fp ) != len ) + { log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - xfree ( buffer ); + rc = G10ERR_WRITE_FILE; + xfree( buffer ); goto leave; - } - } + } + } pt->len -= len; } - xfree ( buffer ); + xfree( buffer ); } } else if( !clearsig ) { if( convert ) { /* text mode */ while( (c = iobuf_get(pt->buf)) != -1 ) { if( mfx->md ) - gcry_md_putc (mfx->md, c ); + md_putc(mfx->md, c ); #ifndef HAVE_DOSISH_SYSTEM if( convert && c == '\r' ) continue; /* fixme: this hack might be too simple */ #endif - if( fp ) { - if( putc( c, fp ) == EOF ) { - rc = gpg_error_from_errno (errno); + if( fp ) + { + if(opt.max_output && (++count)>opt.max_output) + { + log_error("Error writing to `%s': %s\n", + fname,"exceeded --max-output limit\n"); + rc = G10ERR_WRITE_FILE; + goto leave; + } + else if( putc( c, fp ) == EOF ) + { log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; goto leave; - } - } + } + } } } else { /* binary mode */ - byte *buffer = xmalloc ( 32768 ); + byte *buffer = xmalloc( 32768 ); int eof; for( eof=0; !eof; ) { /* Why do we check for len < 32768: @@ -245,18 +300,27 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( len < 32768 ) eof = 1; if( mfx->md ) - gcry_md_write( mfx->md, buffer, len ); - if( fp ) { - if( fwrite( buffer, 1, len, fp ) != len ) { - rc = gpg_error_from_errno (errno); + md_write( mfx->md, buffer, len ); + if( fp ) + { + if(opt.max_output && (count+=len)>opt.max_output) + { log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - xfree ( buffer ); + fname,"exceeded --max-output limit\n"); + rc = G10ERR_WRITE_FILE; + xfree( buffer ); goto leave; + } + else if( fwrite( buffer, 1, len, fp ) != len ) { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + xfree( buffer ); + goto leave; } - } + } } - xfree ( buffer ); + xfree( buffer ); } pt->buf = NULL; } @@ -264,19 +328,28 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, int state = 0; while( (c = iobuf_get(pt->buf)) != -1 ) { - if( fp ) { - if( putc( c, fp ) == EOF ) { - rc = gpg_error_from_errno (errno); + if( fp ) + { + if(opt.max_output && (++count)>opt.max_output) + { log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); + fname,"exceeded --max-output limit\n"); + rc = G10ERR_WRITE_FILE; goto leave; - } - } + } + else if( putc( c, fp ) == EOF ) + { + log_error("Error writing to `%s': %s\n", + fname, strerror(errno) ); + rc = G10ERR_WRITE_FILE; + goto leave; + } + } if( !mfx->md ) continue; if( state == 2 ) { - gcry_md_putc (mfx->md, '\r' ); - gcry_md_putc (mfx->md, '\n' ); + md_putc(mfx->md, '\r' ); + md_putc(mfx->md, '\n' ); state = 0; } if( !state ) { @@ -285,18 +358,18 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, else if( c == '\n' ) state = 2; else - gcry_md_putc (mfx->md, c ); + md_putc(mfx->md, c ); } else if( state == 1 ) { if( c == '\n' ) state = 2; else { - gcry_md_putc (mfx->md, '\r' ); + md_putc(mfx->md, '\r' ); if( c == '\r' ) state = 1; else { state = 0; - gcry_md_putc (mfx->md, c ); + md_putc(mfx->md, c ); } } } @@ -305,9 +378,9 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } if( fp && fp != stdout && fclose(fp) ) { - rc = gpg_error_from_errno (errno); log_error("Error closing `%s': %s\n", fname, strerror(errno) ); fp = NULL; + rc = G10ERR_WRITE_FILE; goto leave; } fp = NULL; @@ -315,12 +388,12 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, leave: if( fp && fp != stdout ) fclose(fp); - xfree (fname); + xfree(fname); return rc; } static void -do_hash( MD_HANDLE md, MD_HANDLE md2, iobuf_t fp, int textmode ) +do_hash( gcry_md_hd_t md, gcry_md_hd_t md2, IOBUF fp, int textmode ) { text_filter_context_t tfx; int c; @@ -365,12 +438,12 @@ do_hash( MD_HANDLE md, MD_HANDLE md2, iobuf_t fp, int textmode ) * INFILE is the name of the input file. */ int -ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, +ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2, const char *inname, int textmode ) { progress_filter_context_t pfx; char *answer = NULL; - iobuf_t fp; + IOBUF fp; int rc = 0; fp = open_sigfile( inname, &pfx ); /* open default file */ @@ -379,24 +452,37 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, int any=0; tty_printf(_("Detached signature.\n")); do { - xfree (answer); - answer = cpr_get("detached_signature.filename", + char *name; + xfree(answer); + tty_enable_completion(NULL); + name = cpr_get("detached_signature.filename", _("Please enter name of data file: ")); + tty_disable_completion(); cpr_kill_prompt(); + answer=make_filename(name,(void *)NULL); + xfree(name); + if( any && !*answer ) { - rc = GPG_ERR_GENERAL; + rc = gpg_error (GPG_ERR_GENERAL); /*G10ERR_READ_FILE*/ goto leave; } fp = iobuf_open(answer); + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } if( !fp && errno == ENOENT ) { tty_printf("No such file, try again or hit enter to quit.\n"); any++; } - else if( !fp ) { - rc = gpg_error_from_errno (errno); - log_error("can't open `%s': %s\n", answer, strerror(errno) ); + else if( !fp ) + { + log_error(_("can't open `%s': %s\n"), answer, strerror(errno)); + rc = G10ERR_READ_FILE; goto leave; - } + } } while( !fp ); } @@ -410,7 +496,7 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, iobuf_close(fp); leave: - xfree (answer); + xfree(answer); return rc; } @@ -421,11 +507,11 @@ ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2, * If FILES is NULL, hash stdin. */ int -hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, +hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files, const char *sigfilename, int textmode ) { progress_filter_context_t pfx; - iobuf_t fp; + IOBUF fp; STRLIST sl; if( !files ) { @@ -437,17 +523,22 @@ hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files, return 0; } log_error (_("no signed data\n")); - return GPG_ERR_NO_DATA; + return gpg_error (GPG_ERR_NO_DATA); } for (sl=files; sl; sl = sl->next ) { fp = iobuf_open( sl->d ); + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } if( !fp ) { - int tmperr = gpg_error_from_errno (errno); log_error(_("can't open signed data `%s'\n"), print_fname_stdin(sl->d)); - return tmperr; + return G10ERR_OPEN_FILE; } handle_progress (&pfx, fp, sl->d); do_hash( md, md2, fp, textmode ); diff --git a/g10/progress.c b/g10/progress.c index 9d9805065..148bf7e2d 100644 --- a/g10/progress.c +++ b/g10/progress.c @@ -1,4 +1,4 @@ -/* progress.c +/* progress.c - emit progress status lines * Copyright (C) 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -33,7 +34,7 @@ */ int progress_filter (void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { int rc = 0; progress_filter_context_t *pfx = opaque; @@ -96,7 +97,7 @@ progress_filter (void *opaque, int control, } void -handle_progress (progress_filter_context_t *pfx, iobuf_t inp, const char *name) +handle_progress (progress_filter_context_t *pfx, IOBUF inp, const char *name) { off_t filesize = 0; @@ -106,8 +107,8 @@ handle_progress (progress_filter_context_t *pfx, iobuf_t inp, const char *name) if (!is_status_enabled ()) return; - if (name && *name && !(*name == '-' && !name[1])) - filesize = iobuf_get_filelength (inp); + if ( !iobuf_is_pipe_filename (name) && *name ) + filesize = iobuf_get_filelength (inp, NULL); else if (opt.set_filesize) filesize = opt.set_filesize; diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 4b45b9f5c..5af0d5f1d 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -1,6 +1,6 @@ /* pubkey-enc.c - public key encoded packet handling * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -27,9 +28,7 @@ #include "gpg.h" #include "util.h" -#include "memory.h" #include "packet.h" -#include "mpi.h" #include "keydb.h" #include "trustdb.h" #include "cipher.h" @@ -38,7 +37,7 @@ #include "main.h" #include "i18n.h" #include "pkglue.h" -#include "call-agent.h" + static int get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ); @@ -77,12 +76,12 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) PKT_secret_key *sk = NULL; int rc; - rc = openpgp_pk_test_algo (k->pubkey_algo, PUBKEY_USAGE_ENC); + rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC); if( rc ) goto leave; if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) { - sk = xcalloc (1, sizeof *sk ); + sk = xmalloc_clear( sizeof *sk ); sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/ if( !(rc = get_seckey( sk, k->keyid )) ) rc = get_it( k, dek, sk, k->keyid ); @@ -95,34 +94,49 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) for(;;) { if( sk ) free_secret_key( sk ); - sk = xcalloc (1, sizeof *sk ); + sk = xmalloc_clear( sizeof *sk ); rc=enum_secret_keys( &enum_context, sk, 1, 0); if( rc ) { - rc = GPG_ERR_NO_SECKEY; + rc = G10ERR_NO_SECKEY; break; } if( sk->pubkey_algo != k->pubkey_algo ) continue; keyid_from_sk( sk, keyid ); - log_info(_("anonymous recipient; trying secret key %08lX ...\n"), - (ulong)keyid[1] ); + log_info(_("anonymous recipient; trying secret key %s ...\n"), + keystr(keyid)); if(!opt.try_all_secrets && !is_status_enabled()) { p=get_last_passphrase(); set_next_passphrase(p); - xfree (p); + xfree(p); } rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask only once */ if( !rc ) + { rc = get_it( k, dek, sk, keyid ); - if( !rc ) { + /* Successfully checked the secret key (either it was + a card, had no passphrase, or had the right + passphrase) but couldn't decrypt the session key, + so thus that key is not the anonymous recipient. + Move the next passphrase into last for the next + round. We only do this if the secret key was + successfully checked as in the normal case, + check_secret_key handles this for us via + passphrase_to_dek */ + if(rc) + next_to_last_passphrase(); + } + + if( !rc ) + { log_info(_("okay, we are the anonymous recipient.\n") ); break; - } + } } enum_secret_keys( &enum_context, NULL, 0, 0 ); /* free context */ } @@ -138,15 +152,17 @@ static int get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) { int rc; - gcry_mpi_t plain_dek = NULL; + gcry_mpi_t plain_dek = NULL; byte *frame = NULL; unsigned n, nframe; u16 csum, csum2; + int card = 0; if (sk->is_protected && sk->protect.s2k.mode == 1002) - { /* FIXME: Note that we do only support RSA for now. */ - char *rbuf; + { /* Note, that we only support RSA for now. */ +#ifdef ENABLE_CARD_SUPPORT + unsigned char *rbuf; size_t rbuflen; char *snbuf; unsigned char *indata = NULL; @@ -154,9 +170,8 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); - if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, - enc->data[0])) - BUG(); + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, enc->data[0])) + BUG (); rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen); xfree (snbuf); @@ -167,148 +182,145 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) frame = rbuf; nframe = rbuflen; card = 1; +#else + rc = gpg_error (GPG_ERR_NOT_SUPPORTED); + goto leave; +#endif /*!ENABLE_CARD_SUPPORT*/ } else { - rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey); + rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey ); if( rc ) - goto leave; + goto leave; if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek)) BUG(); gcry_mpi_release (plain_dek); plain_dek = NULL; } - - /* Now get the DEK (data encryption key) from the frame - * - * Old versions encode the DEK in in this format (msb is left): - * - * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 - * - * Later versions encode the DEK like this: - * - * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) - * - * (mpi_get_buffer already removed the leading zero). - * - * RND are non-zero randow bytes. - * A is the cipher algorithm - * DEK is the encryption key (session key) with length k - * CSUM - */ - if( DBG_CIPHER ) - log_printhex ("DEK frame:", frame, nframe ); - n=0; - if (!card) - { - if( n + 7 > nframe ) - { rc = GPG_ERR_WRONG_SECKEY; goto leave; } - if( frame[n] == 1 && frame[nframe-1] == 2 ) { - log_info(_("old encoding of the DEK is not supported\n")); - rc = GPG_ERR_CIPHER_ALGO; - goto leave; + /* Now get the DEK (data encryption key) from the frame + * + * Old versions encode the DEK in in this format (msb is left): + * + * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 + * + * Later versions encode the DEK like this: + * + * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) + * + * (mpi_get_buffer already removed the leading zero). + * + * RND are non-zero randow bytes. + * A is the cipher algorithm + * DEK is the encryption key (session key) with length k + * CSUM + */ + if( DBG_CIPHER ) + log_hexdump("DEK frame:", frame, nframe ); + n=0; + if (!card) + { + if( n + 7 > nframe ) + { rc = G10ERR_WRONG_SECKEY; goto leave; } + if( frame[n] == 1 && frame[nframe-1] == 2 ) { + log_info(_("old encoding of the DEK is not supported\n")); + rc = G10ERR_CIPHER_ALGO; + goto leave; + } + if( frame[n] != 2 ) /* somethink is wrong */ + { rc = G10ERR_WRONG_SECKEY; goto leave; } + for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ + ; + n++; /* and the zero byte */ } - if( frame[n] != 2 ) /* somethink is wrong */ - { rc = GPG_ERR_WRONG_SECKEY; goto leave; } - for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ - ; - n++; /* and the zero byte */ - } - if( n + 4 > nframe ) - { rc = GPG_ERR_WRONG_SECKEY; goto leave; } - dek->keylen = nframe - (n+1) - 2; - dek->algo = frame[n++]; - if( dek->algo == CIPHER_ALGO_IDEA ) - write_status(STATUS_RSA_OR_IDEA); - rc = openpgp_cipher_test_algo (dek->algo); - if( rc ) { - if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) { - log_info(_("cipher algorithm %d%s is unknown or disabled\n"), - dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); - if(dek->algo==CIPHER_ALGO_IDEA) - idea_cipher_warn(0); + if( n + 4 > nframe ) + { rc = G10ERR_WRONG_SECKEY; goto leave; } + + dek->keylen = nframe - (n+1) - 2; + dek->algo = frame[n++]; + if( dek->algo == CIPHER_ALGO_IDEA ) + write_status(STATUS_RSA_OR_IDEA); + rc = openpgp_cipher_test_algo (dek->algo); + if( rc ) { + if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) { + log_info(_("cipher algorithm %d%s is unknown or disabled\n"), + dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); + if(dek->algo==CIPHER_ALGO_IDEA) + idea_cipher_warn(0); + } + dek->algo = 0; + goto leave; } - dek->algo = 0; - goto leave; - } - if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) { - rc = GPG_ERR_WRONG_SECKEY; - goto leave; - } - - /* copy the key to DEK and compare the checksum */ - csum = frame[nframe-2] << 8; - csum |= frame[nframe-1]; - memcpy( dek->key, frame+n, dek->keylen ); - for( csum2=0, n=0; n < dek->keylen; n++ ) - csum2 += dek->key[n]; - if( csum != csum2 ) { - rc = GPG_ERR_WRONG_SECKEY; - goto leave; - } - if( DBG_CIPHER ) - log_printhex ("DEK is:", dek->key, dek->keylen ); - /* check that the algo is in the preferences and whether it has expired */ - { - PKT_public_key *pk = NULL; - KBNODE pkb = get_pubkeyblock (keyid); - - if( !pkb ) { - rc = -1; - log_error("oops: public key not found for preference check\n"); + if ( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) { + rc = GPG_ERR_WRONG_SECKEY; + goto leave; } - else if( pkb->pkt->pkt.public_key->selfsigversion > 3 - && dek->algo != CIPHER_ALGO_3DES - && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) { - /* Don't print a note while we are not on verbose mode, - * the cipher is blowfish and the preferences have twofish - * listed */ - if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH - || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH)) - log_info(_( - "NOTE: cipher algorithm %d not found in preferences\n"), - dek->algo ); + + /* copy the key to DEK and compare the checksum */ + csum = frame[nframe-2] << 8; + csum |= frame[nframe-1]; + memcpy( dek->key, frame+n, dek->keylen ); + for( csum2=0, n=0; n < dek->keylen; n++ ) + csum2 += dek->key[n]; + if( csum != csum2 ) { + rc = G10ERR_WRONG_SECKEY; + goto leave; } + if( DBG_CIPHER ) + log_hexdump("DEK is:", dek->key, dek->keylen ); + /* check that the algo is in the preferences and whether it has expired */ + { + PKT_public_key *pk = NULL; + KBNODE pkb = get_pubkeyblock (keyid); - if (!rc) { - KBNODE k; + if( !pkb ) { + rc = -1; + log_error("oops: public key not found for preference check\n"); + } + else if(pkb->pkt->pkt.public_key->selfsigversion > 3 + && dek->algo != CIPHER_ALGO_3DES + && !opt.quiet + && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo )) + log_info (_("WARNING: cipher algorithm %s not found in recipient" + " preferences\n"), gcry_cipher_algo_name (dek->algo)); + if (!rc) { + KBNODE k; - for (k=pkb; k; k = k->next) { - if (k->pkt->pkttype == PKT_PUBLIC_KEY - || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ - u32 aki[2]; - keyid_from_pk(k->pkt->pkt.public_key, aki); - - if (aki[0]==keyid[0] && aki[1]==keyid[1]) { - pk = k->pkt->pkt.public_key; - break; - } + for (k=pkb; k; k = k->next) { + if (k->pkt->pkttype == PKT_PUBLIC_KEY + || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ + u32 aki[2]; + keyid_from_pk(k->pkt->pkt.public_key, aki); + + if (aki[0]==keyid[0] && aki[1]==keyid[1]) { + pk = k->pkt->pkt.public_key; + break; + } + } + } + if (!pk) + BUG (); + if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { + log_info(_("NOTE: secret key %s expired at %s\n"), + keystr(keyid), asctimestamp( pk->expiredate) ); + } } - } - if (!pk) - BUG (); - if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { - log_info(_("NOTE: secret key %08lX expired at %s\n"), - (ulong)keyid[1], asctimestamp( pk->expiredate) ); - } - } - if ( pk && pk->is_revoked ) { - log_info( _("NOTE: key has been revoked") ); - putc( '\n', log_get_stream() ); - show_revocation_reason( pk, 1 ); - } + if ( pk && pk->is_revoked ) { + log_info( _("NOTE: key has been revoked") ); + putc( '\n', log_get_stream() ); + show_revocation_reason( pk, 1 ); + } - release_kbnode (pkb); - rc = 0; - } + release_kbnode (pkb); + rc = 0; + } - leave: - gcry_mpi_release (plain_dek); - xfree (frame); - return rc; + leave: + gcry_mpi_release (plain_dek); + xfree (frame); + return rc; } @@ -324,21 +336,21 @@ get_override_session_key( DEK *dek, const char *string ) int i; if ( !string ) - return GPG_ERR_BAD_KEY; + return G10ERR_BAD_KEY; dek->algo = atoi(string); if ( dek->algo < 1 ) - return GPG_ERR_BAD_KEY; + return G10ERR_BAD_KEY; if ( !(s = strchr ( string, ':' )) ) - return GPG_ERR_BAD_KEY; + return G10ERR_BAD_KEY; s++; for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) { int c = hextobyte ( s ); if (c == -1) - return GPG_ERR_BAD_KEY; + return G10ERR_BAD_KEY; dek->key[i] = c; } if ( *s ) - return GPG_ERR_BAD_KEY; + return G10ERR_BAD_KEY; dek->keylen = i; return 0; } diff --git a/g10/revoke.c b/g10/revoke.c index 161bd2b82..34f9f5c85 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -1,5 +1,6 @@ /* revoke.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,11 +28,11 @@ #include <assert.h> #include <ctype.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "main.h" #include "ttyio.h" @@ -59,15 +61,15 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque ) ud = native_to_utf8( reason->desc ); buflen += strlen(ud); } - buffer = xmalloc ( buflen ); + buffer = xmalloc( buflen ); *buffer = reason->code; if( ud ) { memcpy(buffer+1, ud, strlen(ud) ); - xfree ( ud ); + xfree( ud ); } build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen ); - xfree ( buffer ); + xfree( buffer ); return 0; } @@ -76,7 +78,7 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque ) and pick a user ID that has a uid signature, and include it if possible. */ static int -export_minimal_pk(iobuf_t out,KBNODE keyblock, +export_minimal_pk(IOBUF out,KBNODE keyblock, PKT_signature *revsig,PKT_signature *revkey) { KBNODE node; @@ -89,8 +91,8 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, node=find_kbnode(keyblock,PKT_PUBLIC_KEY); if(!node) { - log_error(_("key incomplete\n")); - return GPG_ERR_GENERAL; + log_error("key incomplete\n"); + return G10ERR_GENERAL; } keyid_from_pk(node->pkt->pkt.public_key,keyid); @@ -99,7 +101,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); return rc; } @@ -113,7 +115,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); return rc; } } @@ -125,7 +127,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); return rc; } } @@ -142,8 +144,8 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, break; else { - log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]); - return GPG_ERR_GENERAL; + log_error(_("key %s has no user IDs\n"),keystr(keyid)); + return G10ERR_GENERAL; } } @@ -171,7 +173,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); return rc; } @@ -183,7 +185,7 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, rc=build_packet(out,&pkt); if(rc) { - log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); return rc; } } @@ -195,39 +197,41 @@ export_minimal_pk(iobuf_t out,KBNODE keyblock, * Generate a revocation certificate for UNAME via a designated revoker */ int -gen_desig_revoke( const char *uname ) +gen_desig_revoke( const char *uname, STRLIST locusr ) { int rc = 0; armor_filter_context_t afx; PKT_public_key *pk = NULL; PKT_secret_key *sk = NULL; PKT_signature *sig = NULL; - iobuf_t out = NULL; + IOBUF out = NULL; struct revocation_reason_info *reason = NULL; KEYDB_HANDLE kdbhd; KEYDB_SEARCH_DESC desc; KBNODE keyblock=NULL,node; u32 keyid[2]; int i,any=0; + SK_LIST sk_list=NULL; - if( opt.batch ) { - log_error(_("sorry, can't do this in batch mode\n")); - return GPG_ERR_GENERAL; - } + if( opt.batch ) + { + log_error(_("can't do this in batch mode\n")); + return G10ERR_GENERAL; + } memset( &afx, 0, sizeof afx); kdbhd = keydb_new (0); classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID; + rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; if (rc) { - log_error (_("key `%s' not found: %s\n"),uname, gpg_strerror (rc)); + log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc)); goto leave; } rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); goto leave; } @@ -243,6 +247,13 @@ gen_desig_revoke( const char *uname ) keyid_from_pk(pk,keyid); + if(locusr) + { + rc=build_sk_list(locusr,&sk_list,0,PUBKEY_USAGE_CERT); + if(rc) + goto leave; + } + /* Are we a designated revoker for this key? */ if(!pk->revkey && pk->numrevkeys) @@ -250,12 +261,39 @@ gen_desig_revoke( const char *uname ) for(i=0;i<pk->numrevkeys;i++) { + SK_LIST list; + if(sk) free_secret_key(sk); - sk=xcalloc (1,sizeof(*sk)); + if(sk_list) + { + for(list=sk_list;list;list=list->next) + { + byte fpr[MAX_FINGERPRINT_LEN]; + size_t fprlen; + + fingerprint_from_sk(list->sk,fpr,&fprlen); + + /* Don't get involved with keys that don't have 160 + bit fingerprints */ + if(fprlen!=20) + continue; - rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN); + if(memcmp(fpr,pk->revkey[i].fpr,20)==0) + break; + } + + if(list) + sk=copy_secret_key(NULL,list->sk); + else + continue; + } + else + { + sk=xmalloc_secure_clear(sizeof(*sk)); + rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN); + } /* We have the revocation key */ if(!rc) @@ -275,7 +313,7 @@ gen_desig_revoke( const char *uname ) tty_printf("\n"); if( !cpr_get_answer_is_yes("gen_desig_revoke.okay", - _("Create a revocation certificate for this key? ")) ) + _("Create a designated revocation certificate for this key? (y/N) "))) continue; /* get the reason for the revocation (this is always v4) */ @@ -294,7 +332,8 @@ gen_desig_revoke( const char *uname ) goto leave; afx.what = 1; - afx.hdrlines = "Comment: A revocation certificate should follow\n"; + afx.hdrlines = "Comment: A designated revocation certificate" + " should follow\n"; iobuf_push_filter( out, armor_filter, &afx ); /* create it */ @@ -302,7 +341,7 @@ gen_desig_revoke( const char *uname ) 0, 0, 0, revocation_reason_build_cb, reason ); if( rc ) { - log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc)); + log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); goto leave; } @@ -371,7 +410,7 @@ gen_desig_revoke( const char *uname ) } if(!any) - log_error(_("no revocation keys found for `%s'\n"),uname); + log_error(_("no revocation keys found for \"%s\"\n"),uname); leave: if( pk ) @@ -381,6 +420,8 @@ gen_desig_revoke( const char *uname ) if( sig ) free_seckey_enc( sig ); + release_sk_list(sk_list); + if( rc ) iobuf_cancel(out); else @@ -403,17 +444,18 @@ gen_revoke( const char *uname ) PKT_public_key *pk = NULL; PKT_signature *sig = NULL; u32 sk_keyid[2]; - iobuf_t out = NULL; + IOBUF out = NULL; KBNODE keyblock = NULL, pub_keyblock = NULL; KBNODE node; KEYDB_HANDLE kdbhd; struct revocation_reason_info *reason = NULL; KEYDB_SEARCH_DESC desc; - if( opt.batch ) { - log_error(_("sorry, can't do this in batch mode\n")); - return GPG_ERR_GENERAL; - } + if( opt.batch ) + { + log_error(_("can't do this in batch mode\n")); + return G10ERR_GENERAL; + } memset( &afx, 0, sizeof afx); init_packet( &pkt ); @@ -423,16 +465,17 @@ gen_revoke( const char *uname ) */ kdbhd = keydb_new (1); classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : GPG_ERR_INV_USER_ID; - if (rc) { - log_error (_("secret key `%s' not found: %s\n"), - uname, gpg_strerror (rc)); + rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + if (rc) + { + log_error (_("secret key \"%s\" not found: %s\n"), + uname, g10_errstr (rc)); goto leave; - } + } rc = keydb_get_keyblock (kdbhd, &keyblock ); if( rc ) { - log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc) ); + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); goto leave; } @@ -447,14 +490,14 @@ gen_revoke( const char *uname ) keyid_from_sk( sk, sk_keyid ); print_seckey_info (sk); - pk = xcalloc (1, sizeof *pk ); + pk = xmalloc_clear( sizeof *pk ); /* FIXME: We should get the public key direct from the secret one */ pub_keyblock=get_pubkeyblock(sk_keyid); if(!pub_keyblock) { - log_error(_("no corresponding public key: %s\n"), gpg_strerror (rc) ); + log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) ); goto leave; } @@ -466,16 +509,17 @@ gen_revoke( const char *uname ) if( cmp_public_secret_key( pk, sk ) ) { log_error(_("public key does not match secret key!\n") ); - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; goto leave; } tty_printf("\n"); if( !cpr_get_answer_is_yes("gen_revoke.okay", - _("Create a revocation certificate for this key? ")) ){ + _("Create a revocation certificate for this key? (y/N) ")) ) + { rc = 0; goto leave; - } + } if(sk->version>=4 || opt.force_v4_certs) { /* get the reason for the revocation */ @@ -489,13 +533,17 @@ gen_revoke( const char *uname ) switch( is_secret_key_protected( sk ) ) { case -1: log_error(_("unknown protection algorithm\n")); - rc = GPG_ERR_PUBKEY_ALGO; + rc = G10ERR_PUBKEY_ALGO; break; + case -3: + tty_printf (_("Secret parts of primary key are not available.\n")); + rc = G10ERR_NO_SECKEY; + break; case 0: tty_printf(_("NOTE: This key is not protected!\n")); break; default: - rc = check_secret_key( sk, 0 ); + rc = check_secret_key( sk, 0 ); break; } if( rc ) @@ -517,7 +565,7 @@ gen_revoke( const char *uname ) opt.force_v4_certs?4:0, 0, 0, revocation_reason_build_cb, reason ); if( rc ) { - log_error(_("make_keysig_packet failed: %s\n"), gpg_strerror (rc)); + log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc)); goto leave; } @@ -537,7 +585,7 @@ gen_revoke( const char *uname ) rc = build_packet( out, &pkt ); if( rc ) { - log_error(_("build_packet failed: %s\n"), gpg_strerror (rc) ); + log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); goto leave; } } @@ -581,7 +629,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) do { code=-1; - xfree (description); + xfree(description); description = NULL; tty_printf(_("Please select the reason for the revocation:\n")); @@ -612,7 +660,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) n = -1; else n = atoi(answer); - xfree (answer); + xfree(answer); if( n == 0 ) { code = 0x00; /* no particular reason */ code_text = text_0; @@ -644,25 +692,25 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) trim_trailing_ws( answer, strlen(answer) ); cpr_kill_prompt(); if( !*answer ) { - xfree (answer); + xfree(answer); break; } { char *p = make_printable_string( answer, strlen(answer), 0 ); - xfree (answer); + xfree(answer); answer = p; } if( !description ) - description = xstrdup (answer); + description = xstrdup(answer); else { - char *p = xmalloc ( strlen(description) + strlen(answer) + 2 ); + char *p = xmalloc( strlen(description) + strlen(answer) + 2 ); strcpy(stpcpy(stpcpy( p, description),"\n"),answer); - xfree (description); + xfree(description); description = p; } - xfree (answer); + xfree(answer); } tty_printf(_("Reason for revocation: %s\n"), code_text ); @@ -672,9 +720,9 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) tty_printf("%s\n", description ); } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay", - _("Is this okay? ")) ); + _("Is this okay? (y/N) ")) ); - reason = xmalloc ( sizeof *reason ); + reason = xmalloc( sizeof *reason ); reason->code = code; reason->desc = description; return reason; @@ -684,7 +732,7 @@ void release_revocation_reason_info( struct revocation_reason_info *reason ) { if( reason ) { - xfree ( reason->desc ); - xfree ( reason ); + xfree( reason->desc ); + xfree( reason ); } } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 7356cb224..382ad7534 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -1,6 +1,6 @@ /* seckey-cert.c - secret key certificate packet handling * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -27,9 +28,7 @@ #include "gpg.h" #include "util.h" -#include "memory.h" #include "packet.h" -#include "mpi.h" #include "keydb.h" #include "cipher.h" #include "main.h" @@ -42,21 +41,21 @@ static int do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, int *canceled ) { + gpg_error_t err; byte *buffer; u16 csum=0; int i, res; - unsigned nbytes; - gpg_error_t rc; + unsigned int nbytes; if( sk->is_protected ) { /* remove the protection */ DEK *dek = NULL; u32 keyid[4]; /* 4! because we need two of them */ - CIPHER_HANDLE cipher_hd=NULL; + gcry_cipher_hd_t cipher_hd=NULL; PKT_secret_key *save_sk; if( sk->protect.s2k.mode == 1001 ) { log_info(_("secret key parts are not available\n")); - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } if( sk->protect.algo == CIPHER_ALGO_NONE ) BUG(); @@ -68,8 +67,14 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, write_status (STATUS_RSA_OR_IDEA); idea_cipher_warn (0); } - return GPG_ERR_CIPHER_ALGO; + return G10ERR_CIPHER_ALGO; } + if(gcry_md_test_algo (sk->protect.s2k.hash_algo)) + { + log_info(_("protection digest %d is not supported\n"), + sk->protect.s2k.hash_algo); + return G10ERR_DIGEST_ALGO; + } keyid_from_sk( sk, keyid ); keyid[2] = keyid[3] = 0; if( !sk->is_primary ) { @@ -80,39 +85,45 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, &sk->protect.s2k, mode, tryagain_text, canceled ); if (!dek && canceled && *canceled) - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; - rc = gcry_cipher_open (&cipher_hd, sk->protect.algo, - GCRY_CIPHER_MODE_CFB, - GCRY_CIPHER_SECURE - | (sk->protect.algo >= 100 ? - 0 : GCRY_CIPHER_ENABLE_SYNC)); - if (rc) - log_fatal ("cipher open failed: %s\n", gpg_strerror (rc) ); - rc = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen); - if (rc) - log_fatal ("set key failed: %s\n", gpg_strerror (rc) ); + err = gcry_cipher_open (&cipher_hd, sk->protect.algo, + GCRY_CIPHER_MODE_CFB, + (GCRY_CIPHER_SECURE + | (sk->protect.algo >= 100 ? + 0 : GCRY_CIPHER_ENABLE_SYNC))); + if (err) + log_fatal ("cipher open failed: %s\n", gpg_strerror (err) ); - xfree (dek); + err = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen); + if (err) + log_fatal ("set key failed: %s\n", gpg_strerror (err) ); + + xfree(dek); save_sk = copy_secret_key( NULL, sk ); - gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen); + + gcry_cipher_setiv ( cipher_hd, sk->protect.iv, sk->protect.ivlen ); + csum = 0; if( sk->version >= 4 ) { - int ndata; - unsigned int ndatabits; + int ndata; + unsigned int ndatabits; byte *p, *data; u16 csumc = 0; i = pubkey_get_npkey(sk->pubkey_algo); - assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE )); - p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits ); + + assert ( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE )); + p = gcry_mpi_get_opaque ( sk->skey[i], &ndatabits ); ndata = (ndatabits+7)/8; + if ( ndata > 1 ) csumc = p[ndata-2] << 8 | p[ndata-1]; - data = gcry_xmalloc_secure ( ndata ); - gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata ); - gcry_mpi_release ( sk->skey[i] ); sk->skey[i] = NULL ; + data = xmalloc_secure ( ndata ); + gcry_cipher_decrypt ( cipher_hd, data, ndata, p, ndata ); + gcry_mpi_release (sk->skey[i]); sk->skey[i] = NULL ; + p = data; if (sk->protect.sha1chk) { /* This is the new SHA1 checksum method to detect @@ -126,18 +137,19 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, gcry_md_hd_t h; if ( gcry_md_open (&h, DIGEST_ALGO_SHA1, 1)) - BUG(); /* algo not available */ + BUG(); /* Algo not available. */ gcry_md_write (h, data, ndata - 20); gcry_md_final (h); if (!memcmp (gcry_md_read (h, DIGEST_ALGO_SHA1), - data + ndata - 20, 20) ) { - /* digest does match. We have to keep the old + data + ndata - 20, 20) ) + { + /* Digest does match. We have to keep the old style checksum in sk->csum, so that the test used for unprotected keys does work. This test gets used when we are adding new keys. */ sk->csum = csum = checksum (data, ndata-20); - } + } gcry_md_close (h); } } @@ -156,24 +168,27 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, } } } - - /* must check it here otherwise the mpi_read_xx would fail + + /* Must check it here otherwise the mpi_read_xx would fail because the length may have an arbitrary value */ if( sk->csum == csum ) { for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - assert( gcry_is_secure( p ) ); - res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP, - p, ndata, &nbytes); - if( res ) - log_bug ("gcry_mpi_scan failed in do_check: %s\n", - gpg_strerror (res)); + if ( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP, + p, ndata, &nbytes)) + { + /* Checksum was okay, but not correctly + decrypted. */ + sk->csum = 0; + csum = 1; + break; + } ndata -= nbytes; p += nbytes; } /* Note: at this point ndata should be 2 for a simple checksum or 20 for the sha1 digest */ } - xfree (data); + xfree(data); } else { for(i=pubkey_get_npkey(sk->pubkey_algo); @@ -182,12 +197,12 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, int ndata; unsigned int ndatabits; - assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); - p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits ); + assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); + p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits); ndata = (ndatabits+7)/8; assert (ndata >= 2); assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2); - buffer = gcry_xmalloc_secure (ndata); + buffer = xmalloc_secure (ndata); gcry_cipher_sync (cipher_hd); buffer[0] = p[0]; buffer[1] = p[1]; @@ -195,33 +210,39 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, p+2, ndata-2); csum += checksum (buffer, ndata); gcry_mpi_release (sk->skey[i]); - res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG, - buffer, ndata, &ndata ); - if( res ) - log_bug ("gcry_mpi_scan failed in do_check: %s\n", - gpg_strerror (res)); - assert (sk->skey[i]); + err = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG, + buffer, ndata, &ndata ); xfree (buffer); + if (err) + { + /* Checksum was okay, but not correctly + decrypted. */ + sk->csum = 0; + csum = 1; + break; + } /* csum += checksum_mpi (sk->skey[i]); */ } } - gcry_cipher_close (cipher_hd); - /* now let's see whether we have used the right passphrase */ + gcry_cipher_close ( cipher_hd ); + + /* Now let's see whether we have used the correct passphrase. */ if( csum != sk->csum ) { copy_secret_key( sk, save_sk ); - passphrase_clear_cache ( keyid, sk->pubkey_algo ); + passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo ); + free_secret_key( save_sk ); + return G10ERR_BAD_PASS; + } + + /* The checksum may fail, so we also check the key itself. */ + res = pk_check_secret_key ( sk->pubkey_algo, sk->skey ); + if( res ) { + copy_secret_key( sk, save_sk ); + passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo ); free_secret_key( save_sk ); - return gpg_error (GPG_ERR_BAD_PASSPHRASE); + return G10ERR_BAD_PASS; } - /* the checksum may fail, so we also check the key itself */ - res = pk_check_secret_key (sk->pubkey_algo, sk->skey); - if (res) { - copy_secret_key( sk, save_sk ); - passphrase_clear_cache ( keyid, sk->pubkey_algo ); - free_secret_key( save_sk ); - return gpg_error (GPG_ERR_BAD_PASSPHRASE); - } free_secret_key( save_sk ); sk->is_protected = 0; } @@ -232,7 +253,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, csum += checksum_mpi( sk->skey[i] ); } if( csum != sk->csum ) - return GPG_ERR_CHECKSUM; + return G10ERR_CHECKSUM; } return 0; @@ -252,7 +273,7 @@ check_secret_key( PKT_secret_key *sk, int n ) int i,mode; if (sk && sk->is_protected && sk->protect.s2k.mode == 1002) - return 0; /* Let the scdaemon handle it. */ + return 0; /* Let the scdaemon handle this. */ if(n<0) { @@ -265,7 +286,7 @@ check_secret_key( PKT_secret_key *sk, int n ) if( n < 1 ) n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */ - for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) { + for(i=0; i < n && gpg_err_code (rc) == G10ERR_BAD_PASS; i++ ) { int canceled = 0; const char *tryagain = NULL; if (i) { @@ -273,8 +294,7 @@ check_secret_key( PKT_secret_key *sk, int n ) log_info (_("%s ...\n"), _(tryagain)); } rc = do_check( sk, tryagain, mode, &canceled ); - if( gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE - && is_status_enabled() ) { + if ( gpg_err_code (rc) == G10ERR_BAD_PASS && is_status_enabled () ) { u32 kid[2]; char buf[50]; @@ -296,13 +316,14 @@ check_secret_key( PKT_secret_key *sk, int n ) * check whether the secret key is protected. * Returns: 0 not protected, -1 on error or the protection algorithm * -2 indicates a card stub. + * -3 indicates a not-online stub. */ int is_secret_key_protected( PKT_secret_key *sk ) { return sk->is_protected? - sk->protect.s2k.mode == 1002? -2 - : sk->protect.algo : 0; + sk->protect.s2k.mode == 1002? -2 : + sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0; } @@ -324,54 +345,52 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) if( !sk->is_protected ) { /* okay, apply the protection */ gcry_cipher_hd_t cipher_hd=NULL; - if( openpgp_cipher_test_algo( sk->protect.algo ) ) - { - rc = gpg_error (GPG_ERR_CIPHER_ALGO); /* unsupport - protection - algorithm */ - } + if ( openpgp_cipher_test_algo ( sk->protect.algo ) ) { + /* Unsupport protection algorithm. */ + rc = gpg_error (GPG_ERR_CIPHER_ALGO); + } else { print_cipher_algo_note( sk->protect.algo ); - rc = gcry_cipher_open (&cipher_hd, sk->protect.algo, + + if ( gcry_cipher_open (&cipher_hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, - GCRY_CIPHER_SECURE - | (sk->protect.algo >= 100 ? - 0 : GCRY_CIPHER_ENABLE_SYNC) ); - if (rc) + (GCRY_CIPHER_SECURE + | (sk->protect.algo >= 100 ? + 0 : GCRY_CIPHER_ENABLE_SYNC))) ) BUG(); - if( gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen ) ) + if ( gcry_cipher_setkey ( cipher_hd, dek->key, dek->keylen ) ) log_info(_("WARNING: Weak key detected" " - please change passphrase again.\n")); - sk->protect.ivlen = gcry_cipher_get_algo_blklen(sk->protect.algo); + sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo); assert( sk->protect.ivlen <= DIM(sk->protect.iv) ); if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 ) BUG(); /* yes, we are very careful */ gcry_create_nonce (sk->protect.iv, sk->protect.ivlen); - gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); + gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen); if( sk->version >= 4 ) { - unsigned char *bufarr[PUBKEY_MAX_NSKEY]; + byte *bufarr[PUBKEY_MAX_NSKEY]; unsigned narr[PUBKEY_MAX_NSKEY]; unsigned nbits[PUBKEY_MAX_NSKEY]; int ndata=0; byte *p, *data; - for(j=0, i = pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) { - assert( !gcry_mpi_get_flag( sk->skey[i], - GCRYMPI_FLAG_OPAQUE )); - - if( gcry_mpi_aprint( GCRYMPI_FMT_USG, bufarr+j, + for (j=0, i = pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) + { + assert (!gcry_mpi_get_flag (sk->skey[i], + GCRYMPI_FLAG_OPAQUE)); + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, sk->skey[i])) - BUG(); - - nbits[j] = gcry_mpi_get_nbits( sk->skey[i] ); + BUG(); + nbits[j] = gcry_mpi_get_nbits (sk->skey[i]); ndata += narr[j] + 2; - } - for( ; j < PUBKEY_MAX_NSKEY; j++ ) - bufarr[j] = NULL; + } + for ( ; j < PUBKEY_MAX_NSKEY; j++ ) + bufarr[j] = NULL; + ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */ - data = xmalloc_secure ( ndata ); + data = xmalloc_secure( ndata ); p = data; for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) { p[0] = nbits[j] >> 8 ; @@ -379,7 +398,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) p += 2; memcpy(p, bufarr[j], narr[j] ); p += narr[j]; - xfree (bufarr[j]); + xfree(bufarr[j]); } if (opt.simple_sk_checksum) { @@ -395,10 +414,10 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) gcry_md_hd_t h; if (gcry_md_open (&h, GCRY_MD_SHA1, 1)) - BUG(); /* algo not available */ + BUG(); /* Algo not available. */ gcry_md_write (h, data, ndata - 20); gcry_md_final (h); - memcpy (p, gcry_md_read (h, GCRY_MD_SHA1), 20); + memcpy (p, gcry_md_read (h, DIGEST_ALGO_SHA1), 20); p += 20; gcry_md_close (h); sk->csum = csum = 0; @@ -406,14 +425,15 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) } assert( p == data+ndata ); - gcry_cipher_encrypt( cipher_hd, data, ndata, NULL, 0 ); - for(i = pubkey_get_npkey(sk->pubkey_algo); - i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { - gcry_mpi_release ( sk->skey[i] ); + gcry_cipher_encrypt (cipher_hd, data, ndata, NULL, 0); + for (i = pubkey_get_npkey(sk->pubkey_algo); + i < pubkey_get_nskey(sk->pubkey_algo); i++ ) + { + gcry_mpi_release (sk->skey[i]); sk->skey[i] = NULL; - } + } i = pubkey_get_npkey(sk->pubkey_algo); - sk->skey[i] = gcry_mpi_set_opaque(NULL, data, ndata*8); + sk->skey[i] = gcry_mpi_set_opaque (NULL, data, ndata*8 ); } else { csum = 0; @@ -423,30 +443,33 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) unsigned int nbits; csum += checksum_mpi (sk->skey[i]); - if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &buffer, - &nbytes, sk->skey[i] ) ) - BUG(); + + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, + &nbytes, sk->skey[i] )) + BUG(); gcry_cipher_sync (cipher_hd); - assert (!gcry_mpi_get_flag( sk->skey[i], - GCRYMPI_FLAG_OPAQUE )); - data = xmalloc (nbytes+2); - nbits = gcry_mpi_get_nbits (sk->skey[i]); + assert (!gcry_mpi_get_flag (sk->skey[i], + GCRYMPI_FLAG_OPAQUE)); + + data = xmalloc (nbytes+2); /* fixme: need xtrymalloc. */ + nbits = gcry_mpi_get_nbits (sk->skey[i]); assert (nbytes == (nbits + 7)/8); data[0] = nbits >> 8; data[1] = nbits; gcry_cipher_encrypt (cipher_hd, data+2, nbytes, buffer, nbytes); - xfree ( buffer ); + xfree( buffer ); gcry_mpi_release (sk->skey[i]); - sk->skey[i] = gcry_mpi_set_opaque (NULL, data, - (nbytes+2)*8); + sk->skey[i] = gcry_mpi_set_opaque (NULL, + data, (nbytes+2)*8 ); } sk->csum = csum; } sk->is_protected = 1; - gcry_cipher_close( cipher_hd ); + gcry_cipher_close (cipher_hd); } } return rc; } + diff --git a/g10/seskey.c b/g10/seskey.c index be2535ace..a31cbb15e 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -1,5 +1,6 @@ /* seskey.c - make sesssion keys etc. - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -27,10 +29,9 @@ #include "gpg.h" #include "util.h" #include "cipher.h" -#include "mpi.h" #include "main.h" #include "i18n.h" -#include "options.h" + /**************** * Make a session key and put it into DEK @@ -38,35 +39,33 @@ void make_session_key( DEK *dek ) { - gcry_cipher_hd_t chd; - int i, rc; + gcry_cipher_hd_t chd; + int i, rc; - dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); + dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); - if (gcry_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB, + if (gcry_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB, (GCRY_CIPHER_SECURE | (dek->algo >= 100 ? 0 : GCRY_CIPHER_ENABLE_SYNC))) ) - BUG(); - - gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); - for (i=0; i < 16; i++ ) - { - rc = gcry_cipher_setkey (chd, dek->key, dek->keylen); - if (!rc) - { - gcry_cipher_close (chd); - return; - } - if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) - BUG(); - log_info (_("weak key created - retrying\n") ); - /* Renew the session key until we get a non-weak key. */ - gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); - } - - log_fatal (_("cannot avoid weak key for symmetric cipher; " - "tried %d times!\n"), i); + BUG(); + gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); + for (i=0; i < 16; i++ ) + { + rc = gcry_cipher_setkey (chd, dek->key, dek->keylen); + if (!rc) + { + gcry_cipher_close (chd); + return; + } + if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) + BUG(); + log_info(_("weak key created - retrying\n") ); + /* Renew the session key until we get a non-weak key. */ + gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM); + } + log_fatal (_("cannot avoid weak key for symmetric cipher; " + "tried %d times!\n"), i); } @@ -85,7 +84,7 @@ encode_session_key (DEK *dek, unsigned int nbits) u16 csum; gcry_mpi_t a; - /* the current limitation is that we can only use a session key + /* The current limitation is that we can only use a session key * whose length is a multiple of BITS_PER_MPI_LIMB * I think we can live with that. */ @@ -110,14 +109,14 @@ encode_session_key (DEK *dek, unsigned int nbits) for( p = dek->key, i=0; i < dek->keylen; i++ ) csum += *p++; - frame = gcry_xmalloc_secure ( nframe ); + frame = xmalloc_secure( nframe ); n = 0; frame[n++] = 0; frame[n++] = 2; i = nframe - 6 - dek->keylen; assert( i > 0 ); p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); - /* replace zero bytes by new values */ + /* Replace zero bytes by new values. */ for(;;) { int j, k; byte *pp; @@ -128,36 +127,35 @@ encode_session_key (DEK *dek, unsigned int nbits) k++; if( !k ) break; /* okay: no zero bytes */ - k += k/128; /* better get some more */ - pp = gcry_random_bytes_secure( k, GCRY_STRONG_RANDOM); - for(j=0; j < i && k ; j++ ) + k += k/128 + 3; /* better get some more */ + pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); + for(j=0; j < i && k ;) { if( !p[j] ) p[j] = pp[--k]; - xfree (pp); + if (p[j]) + j++; + } + xfree(pp); } memcpy( frame+n, p, i ); - xfree (p); + xfree(p); n += i; frame[n++] = 0; frame[n++] = dek->algo; memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen; frame[n++] = csum >>8; frame[n++] = csum; - assert (n == nframe); - - if (DBG_CIPHER) - log_printhex ("encoded session key:", frame, nframe ); - + assert( n == nframe ); if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe)) BUG(); - xfree (frame); + xfree(frame); return a; } static gcry_mpi_t do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, - const byte *asn, size_t asnlen, int v3compathack ) + const byte *asn, size_t asnlen ) { int nframe = (nbits+7) / 8; byte *frame; @@ -170,14 +168,14 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, /* We encode the MD in this way: * - * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) + * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) * * PAD consists of FF bytes. */ - frame = gcry_md_is_secure (md)? xmalloc_secure (nframe): xmalloc (nframe); + frame = gcry_md_is_secure (md)? xmalloc_secure (nframe) : xmalloc (nframe); n = 0; frame[n++] = 0; - frame[n++] = v3compathack? algo : 1; /* block type */ + frame[n++] = 1; /* block type */ i = nframe - len - asnlen -3 ; assert( i > 1 ); memset( frame+n, 0xff, i ); n += i; @@ -185,36 +183,83 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, memcpy( frame+n, asn, asnlen ); n += asnlen; memcpy( frame+n, gcry_md_read (md, algo), len ); n += len; assert( n == nframe ); + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe )) BUG(); - xfree (frame); + xfree(frame); + + /* Note that PGP before version 2.3 encoded the MD as: + * + * 0 1 MD(16 bytes) 0 PAD(n bytes) 1 + * + * The MD is always 16 bytes here because it's always MD5. We do + * not support pre-v2.3 signatures, but I'm including this comment + * so the information is easily found in the future. + */ + return a; } /**************** * Encode a message digest into an MPI. - * v3compathack is used to work around a bug in old GnuPG versions - * which did put the algo identifier inseatd of the block type 1 into - * the encoded value. Setting this flag forces the old behaviour. + * If it's for a DSA signature, make sure that the hash is large + * enough to fill up q. If the hash is too big, take the leftmost + * bits. */ gcry_mpi_t -encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo, - unsigned int nbits, int v3compathack ) +encode_md_value (PKT_public_key *pk, PKT_secret_key *sk, + gcry_md_hd_t md, int hash_algo) { - int algo = hash_algo? hash_algo : gcry_md_get_algo (md); gcry_mpi_t frame; - - if (pubkey_algo == GCRY_PK_DSA) + + assert(hash_algo); + assert(pk || sk); + + if((pk?pk->pubkey_algo:sk->pubkey_algo) == GCRY_PK_DSA) { - size_t n = gcry_md_get_algo_dlen(hash_algo); - if (n != 20) - { - log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); - return NULL; - } - if (gcry_mpi_scan( &frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), n, &n ) ) + /* It's a DSA signature, so find out the size of q. */ + + unsigned int qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]); + size_t n; + + /* Make sure it is a multiple of 8 bits. */ + + if(qbytes%8) + { + log_error(_("DSA requires the hash length to be a" + " multiple of 8 bits\n")); + return NULL; + } + + /* Don't allow any q smaller than 160 bits. This might need a + revisit as the DSA2 design firms up, but for now, we don't + want someone to issue signatures from a key with a 16-bit q + or something like that, which would look correct but allow + trivial forgeries. Yes, I know this rules out using MD5 with + DSA. ;) */ + + if(qbytes<160) + { + log_error(_("DSA key %s uses an unsafe (%u bit) hash\n"), + pk?keystr_from_pk(pk):keystr_from_sk(sk),qbytes); + return NULL; + } + + qbytes/=8; + + /* Check if we're too short. Too long is safe as we'll + automatically left-truncate. */ + + if(gcry_md_get_algo_dlen (hash_algo) < qbytes) + { + log_error(_("DSA key %s requires a %u bit or larger hash\n"), + pk?keystr_from_pk(pk):keystr_from_sk(sk),qbytes*8); + return NULL; + } + + if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, + gcry_md_read (md, hash_algo), n, &n)) BUG(); } else @@ -222,23 +267,19 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo, gpg_error_t rc; byte *asn; size_t asnlen; - - rc = gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen); + + rc = gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, NULL, &asnlen); if (rc) - log_fatal("can't get OID of algo %d: %s\n", - algo, gpg_strerror (rc)); + log_fatal ("can't get OID of algo %d: %s\n", + hash_algo, gpg_strerror (rc)); asn = xmalloc (asnlen); - if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) ) + if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) ) BUG(); - frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ), - nbits, asn, asnlen, v3compathack ); + frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo), + gcry_mpi_get_nbits (pk?pk->pkey[0]:sk->skey[0]), + asn, asnlen); xfree (asn); } + return frame; } - - - - - - diff --git a/g10/sig-check.c b/g10/sig-check.c index b0c89cba3..1bb77f7f6 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -1,6 +1,6 @@ /* sig-check.c - Check a signature - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -28,8 +29,6 @@ #include "gpg.h" #include "util.h" #include "packet.h" -#include "memory.h" -#include "mpi.h" #include "keydb.h" #include "cipher.h" #include "main.h" @@ -38,13 +37,17 @@ #include "options.h" #include "pkglue.h" -struct cmp_help_context_s { - PKT_signature *sig; - MD_HANDLE md; +/* Context used by the compare function. */ +struct cmp_help_context_s +{ + PKT_signature *sig; + gcry_md_hd_t md; }; -static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, + +static int do_check( PKT_public_key *pk, PKT_signature *sig, + gcry_md_hd_t digest, int *r_expired, int *r_revoked, PKT_public_key *ret_pk); /**************** @@ -53,37 +56,72 @@ static int do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, * is able to append some data, before finalizing the digest. */ int -signature_check( PKT_signature *sig, MD_HANDLE digest ) +signature_check (PKT_signature *sig, gcry_md_hd_t digest) { return signature_check2( sig, digest, NULL, NULL, NULL, NULL ); } int -signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, +signature_check2 (PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate, int *r_expired, int *r_revoked, PKT_public_key *ret_pk ) { - PKT_public_key *pk = xcalloc (1, sizeof *pk ); + PKT_public_key *pk = xmalloc_clear( sizeof *pk ); int rc=0; - /* Sanity check that the md has a context for the hash that the - sig is expecting. This can happen if a onepass sig header does - not match the actual sig, and also if the clearsign "Hash:" - header is missing or does not match the actual sig. */ + if ( (rc=openpgp_md_test_algo(sig->digest_algo)) ) + ; /* We don't have this digest. */ + else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo))) + ; /* We don't have this pubkey algo. */ + else if (!gcry_md_is_enabled (digest,sig->digest_algo)) + { + /* Sanity check that the md has a context for the hash that the + sig is expecting. This can happen if a onepass sig header does + not match the actual sig, and also if the clearsign "Hash:" + header is missing or does not match the actual sig. */ - if(!gcry_md_is_enabled (digest,sig->digest_algo)) { log_info(_("WARNING: signature digest conflict in message\n")); - rc=GPG_ERR_GENERAL; - } + rc=G10ERR_GENERAL; + } else if( get_pubkey( pk, sig->keyid ) ) - rc = GPG_ERR_NO_PUBKEY; + rc = G10ERR_NO_PUBKEY; else if(!pk->is_valid && !pk->is_primary) - rc=GPG_ERR_BAD_PUBKEY; /* you cannot have a good sig from an + rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an invalid subkey */ - else { - if (r_expiredate) - *r_expiredate = pk->expiredate; + else + { + if(r_expiredate) + *r_expiredate = pk->expiredate; + rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk ); - } + + /* Check the backsig. This is a 0x19 signature from the + subkey on the primary key. The idea here is that it should + not be possible for someone to "steal" subkeys and claim + them as their own. The attacker couldn't actually use the + subkey, but they could try and claim ownership of any + signaures issued by it. */ + if(rc==0 && !pk->is_primary && pk->backsig<2) + { + if(pk->backsig==0) + { + log_info(_("WARNING: signing subkey %s is not" + " cross-certified\n"),keystr_from_pk(pk)); + log_info(_("please see %s for more information\n"), + "http://www.gnupg.org/faq/subkey-cross-certify.html"); + /* --require-cross-certification makes this warning an + error. TODO: change the default to require this + after more keys have backsigs. */ + if(opt.flags.require_cross_cert) + rc=G10ERR_GENERAL; + } + else if(pk->backsig==1) + { + log_info(_("WARNING: signing subkey %s has an invalid" + " cross-certification\n"),keystr_from_pk(pk)); + rc=G10ERR_GENERAL; + } + } + } free_public_key( pk ); @@ -96,35 +134,38 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, * one second. Some remote batch processing applications might * like this feature here */ gcry_md_hd_t md; + u32 a = sig->timestamp; int i, nsig = pubkey_get_nsig( sig->pubkey_algo ); byte *p, *buffer; - gcry_md_open (&md, GCRY_MD_RMD160, 0); + if (gcry_md_open (&md, GCRY_MD_RMD160, 0)) + BUG (); + + /* FIXME: Why the hell are we updating DIGEST here??? */ gcry_md_putc( digest, sig->pubkey_algo ); gcry_md_putc( digest, sig->digest_algo ); gcry_md_putc( digest, (a >> 24) & 0xff ); gcry_md_putc( digest, (a >> 16) & 0xff ); - gcry_md_putc( digest, (a >> 8) & 0xff ); - gcry_md_putc( digest, a & 0xff ); + gcry_md_putc( digest, (a >> 8) & 0xff ); + gcry_md_putc( digest, a & 0xff ); for(i=0; i < nsig; i++ ) { size_t n; unsigned char *tmp; if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &tmp, &n, sig->data[i])) - BUG(); - + BUG(); gcry_md_write (md, tmp, n); xfree (tmp); } - gcry_md_final( md ); - p = make_radix64_string( gcry_md_read( md, 0 ), 20 ); - buffer = xmalloc ( strlen(p) + 60 ); + gcry_md_final (md); + p = make_radix64_string ( gcry_md_read( md, 0 ), 20 ); + buffer = xmalloc( strlen(p) + 60 ); sprintf( buffer, "%s %s %lu", p, strtimestamp( sig->timestamp ), (ulong)sig->timestamp ); write_status_text( STATUS_SIG_ID, buffer ); - xfree (buffer); - xfree (p); + xfree(buffer); + xfree(p); gcry_md_close(md); } @@ -134,58 +175,51 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate, static int do_check_messages( PKT_public_key *pk, PKT_signature *sig, - int *r_expired, int *r_revoked ) + int *r_expired, int *r_revoked ) { u32 cur_time; - if (r_expired) + if(r_expired) *r_expired = 0; - if (r_revoked) + if(r_revoked) *r_revoked = 0; - if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { - log_info(_("key %08lX: this is a PGP generated " - "ElGamal key which is NOT secure for signatures!\n"), - (ulong)keyid_from_pk(pk,NULL)); - return GPG_ERR_PUBKEY_ALGO; - } - if( pk->timestamp > sig->timestamp ) { + if( pk->timestamp > sig->timestamp ) + { ulong d = pk->timestamp - sig->timestamp; - log_info( d==1 - ? _("public key %08lX is %lu second newer than the signature\n") - : _("public key %08lX is %lu seconds newer than the signature\n"), - (ulong)keyid_from_pk(pk,NULL),d ); + log_info(d==1 + ?_("public key %s is %lu second newer than the signature\n") + :_("public key %s is %lu seconds newer than the signature\n"), + keystr_from_pk(pk),d ); if( !opt.ignore_time_conflict ) - return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature */ - } + return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */ + } cur_time = make_timestamp(); - if( pk->timestamp > cur_time ) { + if( pk->timestamp > cur_time ) + { ulong d = pk->timestamp - cur_time; - log_info( d==1 ? _("key %08lX has been created %lu second " - "in future (time warp or clock problem)\n") - : _("key %08lX has been created %lu seconds " - "in future (time warp or clock problem)\n"), - (ulong)keyid_from_pk(pk,NULL),d ); + log_info( d==1 + ? _("key %s was created %lu second" + " in the future (time warp or clock problem)\n") + : _("key %s was created %lu seconds" + " in the future (time warp or clock problem)\n"), + keystr_from_pk(pk),d ); if( !opt.ignore_time_conflict ) - return GPG_ERR_TIME_CONFLICT; - } + return G10ERR_TIME_CONFLICT; + } if( pk->expiredate && pk->expiredate < cur_time ) { char buf[11]; - if (opt.verbose) { - u32 tmp_kid[2]; - - keyid_from_pk( pk, tmp_kid ); - log_info(_("NOTE: signature key %08lX expired %s\n"), - (ulong)tmp_kid[1], asctimestamp( pk->expiredate ) ); - } + if (opt.verbose) + log_info(_("NOTE: signature key %s expired %s\n"), + keystr_from_pk(pk), asctimestamp( pk->expiredate ) ); /* SIGEXPIRED is deprecated. Use KEYEXPIRED. */ sprintf(buf,"%lu",(ulong)pk->expiredate); write_status_text(STATUS_KEYEXPIRED,buf); write_status(STATUS_SIGEXPIRED); - if (r_expired) - *r_expired = 1; + if(r_expired) + *r_expired = 1; } if(pk->is_revoked && r_revoked) @@ -196,25 +230,21 @@ do_check_messages( PKT_public_key *pk, PKT_signature *sig, static int -do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, +do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest, int *r_expired, int *r_revoked, PKT_public_key *ret_pk ) { gcry_mpi_t result = NULL; - int rc=0; + int rc = 0; struct cmp_help_context_s ctx; if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) ) return rc; - if( (rc=gcry_md_test_algo(sig->digest_algo)) ) - return rc; - if( (rc=gcry_pk_test_algo(sig->pubkey_algo)) ) - return rc; - /* make sure the digest algo is enabled (in case of a detached - signature)*/ - gcry_md_enable( digest, sig->digest_algo ); + /* Make sure the digest algo is enabled (in case of a detached + signature). */ + gcry_md_enable (digest, sig->digest_algo); - /* complete the digest */ + /* Complete the digest. */ if( sig->version >= 4 ) gcry_md_putc( digest, sig->version ); gcry_md_putc( digest, sig->sig_class ); @@ -253,38 +283,22 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, buf[5] = n; gcry_md_write( digest, buf, 6 ); } - gcry_md_final (digest); + gcry_md_final( digest ); - result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), 0 ); + result = encode_md_value( pk, NULL, digest, sig->digest_algo ); if (!result) - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; ctx.sig = sig; ctx.md = digest; - rc = pk_verify ( pk->pubkey_algo, result, sig->data, pk->pkey); - gcry_mpi_release ( result ); - if( (opt.emulate_bugs & EMUBUG_MDENCODE) - && gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE - && is_ELGAMAL(pk->pubkey_algo) ) { - /* In this case we try again because old GnuPG versions didn't encode - * the hash right. There is no problem with DSA however */ - result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), (sig->version < 5) ); - if (!result) - rc = GPG_ERR_GENERAL; - else { - ctx.sig = sig; - ctx.md = digest; - rc = pk_verify (pk->pubkey_algo, result, sig->data, pk->pkey); - } - } + rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey ); + gcry_mpi_release (result); - if( !rc && sig->flags.unknown_critical ) { - log_info(_("assuming bad signature from key %08lX " - "due to an unknown critical bit\n"), - (ulong)keyid_from_pk(pk,NULL)); - rc = gpg_error (GPG_ERR_BAD_SIGNATURE); - } + if( !rc && sig->flags.unknown_critical ) + { + log_info(_("assuming bad signature from key %s" + " due to an unknown critical bit\n"),keystr_from_pk(pk)); + rc = G10ERR_BAD_SIGN; + } if(!rc && ret_pk) copy_public_key(ret_pk,pk); @@ -293,6 +307,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, } + static void hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) { @@ -342,34 +357,36 @@ cache_sig_result ( PKT_signature *sig, int result ) } } - /* Check the revocation keys to see if any of them have revoked our pk. sig is the revocation sig. pk is the key it is on. This code will need to be modified if gpg ever becomes multi-threaded. Note that this guarantees that a designated revocation sig will never be considered valid unless it is actually valid, as well as being - issued by a revocation key in a valid direct signature. Note that - this is written so that a revoked revoker can still issue + issued by a revocation key in a valid direct signature. Note also + that this is written so that a revoked revoker can still issue revocations: i.e. If A revokes B, but A is revoked, B is still revoked. I'm not completely convinced this is the proper behavior, but it matches how PGP does it. -dms */ /* Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not - revoked */ + revoked. It is important that G10ERR_NO_PUBKEY is only returned + when a revocation signature is from a valid revocation key + designated in a revkey subpacket, but the revocation key itself + isn't present. */ int check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) { static int busy=0; - int i,rc=GPG_ERR_GENERAL; + int i,rc=G10ERR_GENERAL; assert(IS_KEY_REV(sig)); assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1])); if(busy) { - /* return -1 (i.e. not revoked), but mark the pk as uncacheable - as we don't really know its revocation status until it is - checked directly. */ + /* return an error (i.e. not revoked), but mark the pk as + uncacheable as we don't really know its revocation status + until it is checked directly. */ pk->dont_cache=1; return rc; @@ -394,7 +411,8 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) { gcry_md_hd_t md; - gcry_md_open (&md, sig->digest_algo,0); + if (gcry_md_open (&md, sig->digest_algo, 0)) + BUG (); hash_public_key(md,pk); rc=signature_check(sig,md); cache_sig_result(sig,rc); @@ -407,6 +425,39 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) return rc; } +/* Backsigs (0x19) have the same format as binding sigs (0x18), but + this function is simpler than check_key_signature in a few ways. + For example, there is no support for expiring backsigs since it is + questionable what such a thing actually means. Note also that the + sig cache check here, unlike other sig caches in GnuPG, is not + persistent. */ +int +check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk, + PKT_signature *backsig) +{ + gcry_md_hd_t md; + int rc; + + if(!opt.no_sig_cache && backsig->flags.checked) + { + if((rc=openpgp_md_test_algo (backsig->digest_algo))) + return rc; + + return backsig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE); + } + + if (gcry_md_open (&md, backsig->digest_algo,0)) + BUG (); + hash_public_key(md,main_pk); + hash_public_key(md,sub_pk); + rc=do_check(sub_pk,backsig,md,NULL,NULL,NULL); + cache_sig_result(backsig,rc); + gcry_md_close(md); + + return rc; +} + + /**************** * check the signature pointed to by NODE. This is a key signature. * If the function detects a self-signature, it uses the PK from @@ -415,7 +466,7 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) { - return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL); + return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL ); } /* If check_pk is set, then use it to check the signature in node @@ -427,9 +478,9 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, PKT_public_key *ret_pk, int *is_selfsig, - u32 *r_expiredate, int *r_expired ) + u32 *r_expiredate, int *r_expired ) { - MD_HANDLE md; + gcry_md_hd_t md; PKT_public_key *pk; PKT_signature *sig; int algo; @@ -448,7 +499,10 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, sig = node->pkt->pkt.signature; algo = sig->digest_algo; - /* check whether we have cached the result of a previous signature check.*/ + /* Check whether we have cached the result of a previous signature + check. Note that we may no longer have the pubkey or hash + needed to verify a sig, but can still use the cached value. A + cache refresh detects and clears these cases. */ if ( !opt.no_sig_cache ) { if (sig->flags.checked) { /*cached status available*/ if( is_selfsig ) { @@ -458,7 +512,7 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) *is_selfsig = 1; } - /* BUG: This is wrong for non-self-sigs. Needs to be the + /* BUG: This is wrong for non-self-sigs.. needs to be the actual pk */ if((rc=do_check_messages(pk,sig,r_expired,NULL))) return rc; @@ -466,8 +520,10 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, } } - if( (rc=gcry_md_test_algo(algo)) ) - return rc; + if( (rc=openpgp_pk_test_algo(sig->pubkey_algo)) ) + return rc; + if( (rc=openpgp_md_test_algo(algo)) ) + return rc; if( sig->sig_class == 0x20 ) { /* key revocation */ u32 keyid[2]; @@ -478,7 +534,8 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, rc=check_revocation_keys(pk,sig); else { - gcry_md_open (&md, algo, 0 ); + if (gcry_md_open (&md, algo, 0 )) + BUG (); hash_public_key( md, pk ); rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); @@ -489,20 +546,21 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); if( snode ) { - gcry_md_open (&md, algo, 0 ); + if (gcry_md_open (&md, algo, 0)) + BUG (); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } - else { + else + { if (opt.verbose) - log_info (_("key %08lX: no subkey for subkey " - "revocation signature\n"), - (ulong)keyid_from_pk (pk, NULL)); - rc = GPG_ERR_SIG_CLASS; - } + log_info (_("key %s: no subkey for subkey" + " revocation signature\n"),keystr_from_pk(pk)); + rc = G10ERR_SIG_CLASS; + } } else if( sig->sig_class == 0x18 ) { /* key binding */ KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY ); @@ -515,23 +573,25 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) *is_selfsig = 1; } - gcry_md_open (&md, algo, 0 ); + if (gcry_md_open (&md, algo, 0)) + BUG (); hash_public_key( md, pk ); hash_public_key( md, snode->pkt->pkt.public_key ); rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); gcry_md_close(md); } - else { + else + { if (opt.verbose) - log_info(_("key %08lX: no subkey for subkey " - "binding signature\n"), - (ulong)keyid_from_pk (pk, NULL)); - rc = GPG_ERR_SIG_CLASS; - } + log_info(_("key %s: no subkey for subkey" + " binding signature\n"),keystr_from_pk(pk)); + rc = G10ERR_SIG_CLASS; + } } else if( sig->sig_class == 0x1f ) { /* direct key signature */ - gcry_md_open (&md, algo, 0 ); + if (gcry_md_open (&md, algo, 0 )) + BUG (); hash_public_key( md, pk ); rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); cache_sig_result ( sig, rc ); @@ -544,7 +604,8 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, u32 keyid[2]; keyid_from_pk( pk, keyid ); - gcry_md_open (&md, algo, 0 ); + if (gcry_md_open (&md, algo, 0 )) + BUG (); hash_public_key( md, pk ); hash_uid_node( unode, md, sig ); if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) @@ -554,21 +615,20 @@ check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk, rc = do_check( pk, sig, md, r_expired, NULL, ret_pk ); } else if (check_pk) - rc=do_check(check_pk,sig,md,r_expired, NULL, ret_pk); + rc=do_check(check_pk,sig,md,r_expired,NULL,ret_pk); else - rc = signature_check2( sig, md, r_expiredate, r_expired, - NULL, ret_pk); + rc=signature_check2(sig,md,r_expiredate,r_expired,NULL,ret_pk); cache_sig_result ( sig, rc ); gcry_md_close(md); } - else { + else + { if (!opt.quiet) - log_info ("key %08lX: no user ID for key signature packet " - "of class %02x\n", - (ulong)keyid_from_pk (pk, NULL), sig->sig_class ); - rc = GPG_ERR_SIG_CLASS; - } + log_info ("key %s: no user ID for key signature packet" + " of class %02x\n",keystr_from_pk(pk),sig->sig_class); + rc = G10ERR_SIG_CLASS; + } } return rc; diff --git a/g10/sign.c b/g10/sign.c index cd7615c00..66f8847d7 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1,6 +1,6 @@ /* sign.c - sign data - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -27,12 +28,12 @@ #include <assert.h> #include <unistd.h> /* need sleep() */ +#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" @@ -55,9 +56,9 @@ void __stdcall Sleep(ulong); static int recipient_digest_algo=0; /**************** - * Create a notation. We assume thIt is assumed that the strings in - * the STRLISTs of the opt struct are already checked to contain only - * printable data and have a valid NAME=VALUE format. + * Create notations and other stuff. It is assumed that the stings in + * STRLIST are already checked to contain only printable data and have + * a valid NAME=VALUE format. */ static void mk_notation_policy_etc( PKT_signature *sig, @@ -65,9 +66,8 @@ mk_notation_policy_etc( PKT_signature *sig, { const char *string; char *s=NULL; - byte *buf; - unsigned n1, n2; - STRLIST nd=NULL,pu=NULL; + STRLIST pu=NULL; + struct notation *nd=NULL; struct expando_args args; memset(&args,0,sizeof(args)); @@ -80,57 +80,43 @@ mk_notation_policy_etc( PKT_signature *sig, good to do these checks anyway. */ /* notation data */ - if(IS_SIG(sig) && opt.sig_notation_data) + if(IS_SIG(sig) && opt.sig_notations) { if(sig->version<4) log_error(_("can't put notation data into v3 (PGP 2.x style) " "signatures\n")); else - nd=opt.sig_notation_data; + nd=opt.sig_notations; } - else if( IS_CERT(sig) && opt.cert_notation_data ) + else if( IS_CERT(sig) && opt.cert_notations ) { if(sig->version<4) log_error(_("can't put notation data into v3 (PGP 2.x style) " "key signatures\n")); else - nd=opt.cert_notation_data; + nd=opt.cert_notations; } - for( ; nd; nd = nd->next ) { - char *expanded; - - string = nd->d; - s = strchr( string, '=' ); - if( !s ) - BUG(); /* we have already parsed this */ - n1 = s - string; - s++; + if(nd) + { + struct notation *i; - expanded=pct_expando(s,&args); - if(!expanded) + for(i=nd;i;i=i->next) { - log_error(_("WARNING: unable to %%-expand notation " - "(too large). Using unexpanded.\n")); - expanded=xstrdup (s); + i->altvalue=pct_expando(i->value,&args); + if(!i->altvalue) + log_error(_("WARNING: unable to %%-expand notation " + "(too large). Using unexpanded.\n")); } - n2 = strlen(expanded); - buf = xmalloc ( 8 + n1 + n2 ); - buf[0] = 0x80; /* human readable */ - buf[1] = buf[2] = buf[3] = 0; - buf[4] = n1 >> 8; - buf[5] = n1; - buf[6] = n2 >> 8; - buf[7] = n2; - memcpy(buf+8, string, n1 ); - memcpy(buf+8+n1, expanded, n2 ); - build_sig_subpkt( sig, SIGSUBPKT_NOTATION - | ((nd->flags & 1)? SIGSUBPKT_FLAG_CRITICAL:0), - buf, 8+n1+n2 ); - xfree (expanded); - xfree (buf); - } + keygen_add_notations(sig,nd); + + for(i=nd;i;i=i->next) + { + xfree(i->altvalue); + i->altvalue=NULL; + } + } /* set policy URL */ if( IS_SIG(sig) && opt.sig_policy_url ) @@ -157,24 +143,23 @@ mk_notation_policy_etc( PKT_signature *sig, s=pct_expando(string,&args); if(!s) { - log_error(_("WARNING: unable to %%-expand policy url " + log_error(_("WARNING: unable to %%-expand policy URL " "(too large). Using unexpanded.\n")); - s=xstrdup (string); + s=xstrdup(string); } build_sig_subpkt(sig,SIGSUBPKT_POLICY| ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0), s,strlen(s)); - xfree (s); + xfree(s); } /* preferred keyserver URL */ if( IS_SIG(sig) && opt.sig_keyserver_url ) { if(sig->version<4) - log_info (_("can't put a preferred keyserver URL " - "into v3 signatures\n")); + log_info("can't put a preferred keyserver URL into v3 signatures\n"); else pu=opt.sig_keyserver_url; } @@ -283,99 +268,112 @@ static int do_sign( PKT_secret_key *sk, PKT_signature *sig, MD_HANDLE md, int digest_algo ) { - gcry_mpi_t frame; - byte *dp; - int rc; - - if( sk->timestamp > sig->timestamp ) { - ulong d = sk->timestamp - sig->timestamp; - log_info( d==1 ? _("key has been created %lu second " - "in future (time warp or clock problem)\n") - : _("key has been created %lu seconds " - "in future (time warp or clock problem)\n"), d ); - if( !opt.ignore_time_conflict ) - return GPG_ERR_TIME_CONFLICT; - } - - print_pubkey_algo_note(sk->pubkey_algo); - - if( !digest_algo ) - digest_algo = gcry_md_get_algo(md); - - print_digest_algo_note( digest_algo ); - dp = gcry_md_read ( md, digest_algo ); - sig->digest_algo = digest_algo; - sig->digest_start[0] = dp[0]; - sig->digest_start[1] = dp[1]; - if (sk->is_protected && sk->protect.s2k.mode == 1002) - { /* FIXME: Note that we do only support RSA for now. */ - char *rbuf; - size_t rbuflen; - char *snbuf; - - snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); - rc = agent_scd_pksign (snbuf, digest_algo, - gcry_md_read (md, digest_algo), - gcry_md_get_algo_dlen (digest_algo), - &rbuf, &rbuflen); - xfree (snbuf); - if (!rc) - { - if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, - rbuf, rbuflen, NULL)) - BUG (); - } + gcry_mpi_t frame; + byte *dp; + int rc; + + if( sk->timestamp > sig->timestamp ) { + ulong d = sk->timestamp - sig->timestamp; + log_info( d==1 ? _("key has been created %lu second " + "in future (time warp or clock problem)\n") + : _("key has been created %lu seconds " + "in future (time warp or clock problem)\n"), d ); + if( !opt.ignore_time_conflict ) + return G10ERR_TIME_CONFLICT; } - else - { - frame = encode_md_value( sk->pubkey_algo, md, - digest_algo, mpi_get_nbits(sk->skey[0]), 0 ); - if (!frame) - return GPG_ERR_GENERAL; - rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); - gcry_mpi_release (frame); + + + print_pubkey_algo_note(sk->pubkey_algo); + + if( !digest_algo ) + digest_algo = gcry_md_get_algo (md); + + print_digest_algo_note( digest_algo ); + dp = gcry_md_read ( md, digest_algo ); + sig->digest_algo = digest_algo; + sig->digest_start[0] = dp[0]; + sig->digest_start[1] = dp[1]; + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { +#ifdef ENABLE_CARD_SUPPORT + unsigned char *rbuf; + size_t rbuflen; + char *snbuf; + + snbuf = serialno_and_fpr_from_sk (sk->protect.iv, + sk->protect.ivlen, sk); + rc = agent_scd_pksign (snbuf, digest_algo, + gcry_md_read (md, digest_algo), + gcry_md_get_algo_dlen (digest_algo), + &rbuf, &rbuflen); + xfree (snbuf); + if (!rc) + { + if (gcry_mpi_scan (&sig->data[0], GCRYMPI_FMT_USG, + rbuf, rbuflen, NULL)) + BUG (); + xfree (rbuf); + } +#else + return G10ERR_UNSUPPORTED; +#endif /* ENABLE_CARD_SUPPORT */ + } + else + { + /* TODO: remove this check in the future once all the + variable-q DSA stuff makes it into the standard. */ + if(!opt.expert + && sk->pubkey_algo==PUBKEY_ALGO_DSA + && md_digest_length(digest_algo)!=20) + { + log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); + return G10ERR_GENERAL; + } + + frame = encode_md_value( NULL, sk, md, digest_algo ); + if (!frame) + return G10ERR_GENERAL; + rc = pk_sign( sk->pubkey_algo, sig->data, frame, sk->skey ); + gcry_mpi_release (frame); + } + + if (!rc && !opt.no_sig_create_check) { + /* Check that the signature verification worked and nothing is + * fooling us e.g. by a bug in the signature create + * code or by deliberately introduced faults. */ + PKT_public_key *pk = xmalloc_clear (sizeof *pk); + + if( get_pubkey( pk, sig->keyid ) ) + rc = G10ERR_NO_PUBKEY; + else { + frame = encode_md_value (pk, NULL, md, sig->digest_algo ); + if (!frame) + rc = G10ERR_GENERAL; + else + rc = pk_verify (pk->pubkey_algo, frame, sig->data, pk->pkey ); + gcry_mpi_release (frame); + } + if (rc) + log_error (_("checking created signature failed: %s\n"), + g10_errstr (rc)); + free_public_key (pk); } - if (!rc && !opt.no_sig_create_check) { - /* check that the signature verification worked and nothing is - * fooling us e.g. by a bug in the signature create - * code or by deliberately introduced faults. */ - PKT_public_key *pk = xcalloc (1,sizeof *pk); - - if( get_pubkey( pk, sig->keyid ) ) - rc = GPG_ERR_NO_PUBKEY; + if( rc ) + log_error(_("signing failed: %s\n"), g10_errstr(rc) ); else { - frame = encode_md_value (pk->pubkey_algo, md, - sig->digest_algo, - mpi_get_nbits(pk->pkey[0]), 0); - if (!frame) - rc = GPG_ERR_GENERAL; - else - rc = pk_verify (pk->pubkey_algo, frame, - sig->data, pk->pkey); - gcry_mpi_release (frame); - } - if (rc) - log_error (_("checking created signature failed: %s\n"), - gpg_strerror (rc)); - free_public_key (pk); - } - if( rc ) - log_error(_("signing failed: %s\n"), gpg_strerror (rc) ); - else { - if( opt.verbose ) { - char *ustr = get_user_id_string_printable (sig->keyid); - log_info(_("%s/%s signature from: \"%s\"\n"), - gcry_pk_algo_name (sk->pubkey_algo), - gcry_md_algo_name (sig->digest_algo), - ustr ); - xfree (ustr); + if( opt.verbose ) { + char *ustr = get_user_id_string_native (sig->keyid); + log_info(_("%s/%s signature from: \"%s\"\n"), + gcry_pk_algo_name (sk->pubkey_algo), + gcry_md_algo_name (sig->digest_algo), + ustr ); + xfree(ustr); + } } - } - return rc; + return rc; } - int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ) { @@ -386,34 +384,52 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ) return rc; } +/* + First try --digest-algo. If that isn't set, see if the recipient + has a preferred algorithm (which is also filtered through + --preferred-digest-prefs). If we're making a signature without a + particular recipient (i.e. signing, rather than signing+encrypting) + then take the first algorithm in --preferred-digest-prefs that is + usable for the pubkey algorithm. If --preferred-digest-prefs isn't + set, then take the OpenPGP default (i.e. SHA-1). + + Possible improvement: Use the highest-ranked usable algorithm from + the signing key prefs either before or after using the personal + list? +*/ + static int -hash_for(int pubkey_algo, int packet_version ) +hash_for(PKT_secret_key *sk) { if( opt.def_digest_algo ) return opt.def_digest_algo; else if( recipient_digest_algo ) return recipient_digest_algo; - else if(PGP2 && pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 ) + else if(sk->pubkey_algo==PUBKEY_ALGO_DSA + || (sk->is_protected && sk->protect.s2k.mode==1002)) { - /* Old-style PGP only understands MD5 */ - return DIGEST_ALGO_MD5; - } - else if( pubkey_algo == PUBKEY_ALGO_DSA ) - { - /* We need a 160-bit hash for DSA, so we can't just take the first - in the pref list */ + /* The sk lives on a smartcard, or it's a DSA key. DSA requires + a 160-bit hash, and current smartcards only handle SHA-1 and + RIPEMD/160 (i.e. 160-bit hashes). This is correct now, but + may need revision as the cards add algorithms and/or DSA is + expanded to use larger hashes. */ if(opt.personal_digest_prefs) { prefitem_t *prefs; for(prefs=opt.personal_digest_prefs;prefs->type;prefs++) - if(gcry_md_get_algo_dlen (prefs->value) == 20) + if (gcry_md_get_algo-dlen (prefs->value) == 20) return prefs->value; } return DIGEST_ALGO_SHA1; } + else if(PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) + { + /* Old-style PGP only understands MD5. */ + return DIGEST_ALGO_MD5; + } else if( opt.personal_digest_prefs ) { /* It's not DSA, so we can use whatever the first hash algorithm @@ -469,7 +485,7 @@ print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what ) * packet here in reverse order */ static int -write_onepass_sig_packets (SK_LIST sk_list, iobuf_t out, int sigclass ) +write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) { int skcount; SK_LIST sk_rover; @@ -489,9 +505,9 @@ write_onepass_sig_packets (SK_LIST sk_list, iobuf_t out, int sigclass ) } sk = sk_rover->sk; - ops = xcalloc (1,sizeof *ops); + ops = xmalloc_clear (sizeof *ops); ops->sig_class = sigclass; - ops->digest_algo = hash_for (sk->pubkey_algo, sk->version); + ops->digest_algo = hash_for (sk); ops->pubkey_algo = sk->pubkey_algo; keyid_from_sk (sk, ops->keyid); ops->last = (skcount == 1); @@ -503,7 +519,7 @@ write_onepass_sig_packets (SK_LIST sk_list, iobuf_t out, int sigclass ) free_packet (&pkt); if (rc) { log_error ("build onepass_sig packet failed: %s\n", - gpg_strerror (rc)); + g10_errstr(rc)); return rc; } } @@ -515,7 +531,7 @@ write_onepass_sig_packets (SK_LIST sk_list, iobuf_t out, int sigclass ) * Helper to write the plaintext (literal data) packet */ static int -write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) +write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) { PKT_plaintext *pt = NULL; u32 filesize; @@ -524,8 +540,8 @@ write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) if (!opt.no_literal) { if (fname || opt.set_filename) { char *s = make_basename (opt.set_filename? opt.set_filename - : fname - /*, iobuf_get_real_fname(inp)*/); + : fname, + iobuf_get_real_fname(inp)); pt = xmalloc (sizeof *pt + strlen(s) - 1); pt->namelen = strlen (s); memcpy (pt->name, s, pt->namelen); @@ -538,26 +554,33 @@ write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) } /* try to calculate the length of the data */ - if (fname && *fname && !(*fname=='-' && !fname[1])) { - if( !(filesize = iobuf_get_filelength(inp)) ) - log_info (_("WARNING: `%s' is an empty file\n"), fname); - - /* we can't yet encode the length of very large files, - * so we switch to partial length encoding in this case */ - if (filesize >= IOBUF_FILELENGTH_LIMIT) - filesize = 0; - - /* because the text_filter modifies the length of the + if ( !iobuf_is_pipe_filename (fname) && *fname ) + { + off_t tmpsize; + int overflow; + + if( !(tmpsize = iobuf_get_filelength(inp, &overflow)) + && !overflow ) + log_info (_("WARNING: `%s' is an empty file\n"), fname); + + /* We can't encode the length of very large files because + OpenPGP uses only 32 bit for file sizes. So if 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; + + /* Because the text_filter modifies the length of the * data, it is not possible to know the used length * without a double read of the file - to avoid that - * we simple use partial length packets. - */ + * we simple use partial length packets. */ if ( ptmode == 't' ) - filesize = 0; - } - else { - filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ - } + filesize = 0; + } + else + filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { PACKET pkt; @@ -573,7 +596,7 @@ write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ if( (rc = build_packet (out, &pkt)) ) log_error ("build_packet(PLAINTEXT) failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); pt->buf = NULL; } else { @@ -581,9 +604,10 @@ write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if ( (rc=iobuf_write(out, copy_buffer, bytes_copied) )) { + if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { + rc = G10ERR_WRITE_FILE; log_error ("copying input to output failed: %s\n", - gpg_strerror (rc)); + g10_errstr(rc)); break; } wipememory(copy_buffer,4096); /* burn buffer */ @@ -598,7 +622,7 @@ write_plaintext_packet (iobuf_t out, iobuf_t inp, const char *fname, int ptmode) * hash which will not be changes here. */ static int -write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, +write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, int sigclass, u32 timestamp, u32 duration, int status_letter) { @@ -614,16 +638,16 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, sk = sk_rover->sk; /* build the signature packet */ - sig = xcalloc (1,sizeof *sig); + sig = xmalloc_clear (sizeof *sig); if(opt.force_v3_sigs || RFC1991) sig->version=3; else if(duration || opt.sig_policy_url - || opt.sig_notation_data || opt.sig_keyserver_url) + || opt.sig_notations || opt.sig_keyserver_url) sig->version=4; else sig->version=sk->version; keyid_from_sk (sk, sig->keyid); - sig->digest_algo = hash_for (sk->pubkey_algo, sk->version); + sig->digest_algo = hash_for(sk); sig->pubkey_algo = sk->pubkey_algo; if(timestamp) sig->timestamp = timestamp; @@ -633,7 +657,7 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, sig->expiredate = sig->timestamp+duration; sig->sig_class = sigclass; - gcry_md_copy (&md, hash); + md = gcry_md_copy (hash); if (sig->version >= 4) build_sig_subpkt_from_sig (sig); @@ -642,9 +666,8 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, hash_sigversion_to_magic (md, sig); gcry_md_final (md); - rc = do_sign( sk, sig, md, hash_for (sig->pubkey_algo, sk->version) ); + rc = do_sign( sk, sig, md, hash_for (sk) ); gcry_md_close (md); - if( !rc ) { /* and write it */ PACKET pkt; @@ -658,7 +681,7 @@ write_signature_packets (SK_LIST sk_list, iobuf_t out, MD_HANDLE hash, free_packet (&pkt); if (rc) log_error ("build signature packet failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); } if( rc ) return rc;; @@ -690,7 +713,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, text_filter_context_t tfx; progress_filter_context_t pfx; encrypt_filter_context_t efx; - iobuf_t inp = NULL, out = NULL; + IOBUF inp = NULL, out = NULL; PACKET pkt; int rc = 0; PK_LIST pk_list = NULL; @@ -715,8 +738,17 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( fname && filenames->next && (!detached || encryptflag) ) log_bug("multiple files can only be detached signed"); - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) - duration=ask_expire_interval(1); + if(encryptflag==2 + && (rc=setup_symkey(&efx.symkey_s2k,&efx.symkey_dek))) + goto leave; + + if(!opt.force_v3_sigs && !RFC1991) + { + if(opt.ask_sig_expire && !opt.batch) + duration=ask_expire_interval(1,opt.def_sig_expire); + else + duration=parse_expire_string(opt.def_sig_expire); + } if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) goto leave; @@ -735,10 +767,17 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( multifile ) /* have list of filenames */ inp = NULL; /* we do it later */ else { - if( !(inp = iobuf_open(fname)) ) { - rc = gpg_error_from_errno (errno); - log_error("can't open %s: %s\n", fname? fname: "[stdin]", + inp = iobuf_open(fname); + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if( !inp ) { + log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); + rc = G10ERR_OPEN_FILE; goto leave; } @@ -746,11 +785,18 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } if( outfile ) { - if( !(out = iobuf_create( outfile )) ) { - rc = gpg_error_from_errno (errno); - log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); + if (is_secured_filename ( outfile )) { + out = NULL; + errno = EPERM; + } + else + out = iobuf_create( outfile ); + if( !out ) + { + log_error(_("can't create `%s': %s\n"), outfile, strerror(errno) ); + rc = G10ERR_CREATE_FILE; goto leave; - } + } else if( opt.verbose ) log_info(_("writing to `%s'\n"), outfile ); } @@ -764,7 +810,10 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, iobuf_push_filter( inp, text_filter, &tfx ); } - gcry_md_open (&mfx.md, 0, 0); + if ( gcry_md_open (&,mfx.md, 0, 0) ) + BUG (); + if (DBG_HASHING) + gcry_md_start_debug (mfx.md, "sign"); /* If we're encrypting and signing, it is reasonable to pick the hash algorithm to use out of the recepient key prefs. */ @@ -776,10 +825,10 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, select_algo_from_prefs(pk_list,PREFTYPE_HASH, opt.def_digest_algo, NULL)!=opt.def_digest_algo) - log_info(_("forcing digest algorithm %s (%d) " - "violates recipient preferences\n"), + log_info(_("WARNING: forcing digest algorithm %s (%d)" + " violates recipient preferences\n"), gcry_md_algo_name (opt.def_digest_algo), - opt.def_digest_algo); + opt.def_digest_algo ); } else { @@ -793,8 +842,14 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, sk, but so long as there is only one signing algorithm with hash restrictions, this is ok. -dms */ + /* Current smartcards only do 160-bit hashes as well. + Note that this may well have to change as the cards add + algorithms. */ + for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) - if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA) + if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA + || (sk_rover->sk->is_protected + && sk_rover->sk->protect.s2k.mode==1002)) hashlen=20; if((algo= @@ -806,7 +861,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable (mfx.md, hash_for(sk->pubkey_algo, sk->version )); + gcry_md_enable (mfx.md, hash_for(sk)); } if( !multifile ) @@ -824,9 +879,9 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, iobuf_push_filter( out, encrypt_filter, &efx ); } - if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) + if( opt.compress_algo && !outfile && ( !detached || opt.compress_sigs) ) { - int compr_algo=opt.def_compress_algo; + int compr_algo=opt.compress_algo; /* If not forced by user */ if(compr_algo==-1) @@ -845,16 +900,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, else if(!opt.expert && pk_list && select_algo_from_prefs(pk_list,PREFTYPE_ZIP, compr_algo,NULL)!=compr_algo) - log_info(_("forcing compression algorithm %s (%d) " - "violates recipient preferences\n"), + log_info(_("WARNING: 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 ) - { - zfx.algo = compr_algo; - iobuf_push_filter( out, compress_filter, &zfx ); - } + push_compress_filter(out,&zfx,compr_algo); } /* Write the one-pass signature packets if needed */ @@ -865,7 +917,9 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, goto leave; } - /* setup the inner packet */ + write_status (STATUS_BEGIN_SIGNING); + + /* Setup the inner packet. */ if( detached ) { if( multifile ) { STRLIST sl; @@ -875,12 +929,20 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, /* must walk reverse trough this list */ for( sl = strlist_last(filenames); sl; sl = strlist_prev( filenames, sl ) ) { - if( !(inp = iobuf_open(sl->d)) ) { - rc = gpg_error_from_errno (errno); - log_error(_("can't open %s: %s\n"), - sl->d, strerror(errno) ); + inp = iobuf_open(sl->d); + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if( !inp ) + { + log_error(_("can't open `%s': %s\n"), + sl->d,strerror(errno)); + rc = G10ERR_OPEN_FILE; goto leave; - } + } handle_progress (&pfx, inp, sl->d); if( opt.verbose ) fprintf(stderr, " `%s'", sl->d ); @@ -947,7 +1009,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) armor_filter_context_t afx; progress_filter_context_t pfx; MD_HANDLE textmd = NULL; - iobuf_t inp = NULL, out = NULL; + IOBUF inp = NULL, out = NULL; PACKET pkt; int rc = 0; SK_LIST sk_list = NULL; @@ -959,8 +1021,13 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) memset( &afx, 0, sizeof afx); init_packet( &pkt ); - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) - duration=ask_expire_interval(1); + if(!opt.force_v3_sigs && !RFC1991) + { + if(opt.ask_sig_expire && !opt.batch) + duration=ask_expire_interval(1,opt.def_sig_expire); + else + duration=parse_expire_string(opt.def_sig_expire); + } if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) goto leave; @@ -976,20 +1043,34 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) } /* prepare iobufs */ - if( !(inp = iobuf_open(fname)) ) { - rc = gpg_error_from_errno (errno); - log_error("can't open %s: %s\n", fname? fname: "[stdin]", + inp = iobuf_open(fname); + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } + if( !inp ) { + log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); + rc = G10ERR_OPEN_FILE; goto leave; } handle_progress (&pfx, inp, fname); if( outfile ) { - if( !(out = iobuf_create( outfile )) ) { - rc = gpg_error_from_errno (errno); - log_error(_("can't create %s: %s\n"), outfile, strerror(errno) ); + if (is_secured_filename (outfile) ) { + outfile = NULL; + errno = EPERM; + } + else + out = iobuf_create( outfile ); + if( !out ) + { + log_error(_("can't create `%s': %s\n"), outfile, strerror(errno) ); + rc = G10ERR_CREATE_FILE; goto leave; - } + } else if( opt.verbose ) log_info(_("writing to `%s'\n"), outfile ); } @@ -1000,7 +1081,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - if( hash_for(sk->pubkey_algo, sk->version) == DIGEST_ALGO_MD5 ) + if( hash_for(sk) == DIGEST_ALGO_MD5 ) only_md5 = 1; else { only_md5 = 0; @@ -1017,10 +1098,10 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) iobuf_writestr(out, "Hash: " ); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - int i = hash_for(sk->pubkey_algo, sk->version); + int i = hash_for(sk); if( !hashs_seen[ i & 0xff ] ) { - s = gcry_md_algo_name (i); + s = gcry_md_ago_name ( i ); if( s ) { hashs_seen[ i & 0xff ] = 1; if( any ) @@ -1039,13 +1120,15 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) "NotDashEscaped: You need GnuPG to verify this message" LF ); iobuf_writestr(out, LF ); - gcry_md_open (&textmd, 0, 0); + if ( gcry_md_open (&textmd, 0, 0) ) + BUG (); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable (textmd, hash_for(sk->pubkey_algo, sk->version)); + gcry_md_enable (textmd, hash_for(sk)); } if ( DBG_HASHING ) - gcry_md_start_debug ( textmd, "clearsign" ); + gcry_md_start_debug ( textmd, "clearsign" ); + copy_clearsig_text( out, inp, textmd, !opt.not_dash_escaped, opt.escape_from, (old_style && only_md5) ); /* fixme: check for read errors */ @@ -1083,7 +1166,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) md_filter_context_t mfx; text_filter_context_t tfx; cipher_filter_context_t cfx; - iobuf_t inp = NULL, out = NULL; + IOBUF inp = NULL, out = NULL; PACKET pkt; STRING2KEY *s2k = NULL; int rc = 0; @@ -1099,8 +1182,13 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) memset( &cfx, 0, sizeof cfx); init_packet( &pkt ); - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) - duration=ask_expire_interval(1); + if(!opt.force_v3_sigs && !RFC1991) + { + if(opt.ask_sig_expire && !opt.batch) + duration=ask_expire_interval(1,opt.def_sig_expire); + else + duration=parse_expire_string(opt.def_sig_expire); + } rc = build_sk_list (locusr, &sk_list, 1, PUBKEY_USAGE_SIG); if (rc) @@ -1108,31 +1196,44 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* prepare iobufs */ inp = iobuf_open(fname); + if (inp && is_secured_file (iobuf_get_fd (inp))) + { + iobuf_close (inp); + inp = NULL; + errno = EPERM; + } if( !inp ) { - rc = gpg_error_from_errno (errno); - log_error("can't open %s: %s\n", fname? fname: "[stdin]", - strerror(errno) ); + log_error(_("can't open `%s': %s\n"), + fname? fname: "[stdin]", strerror(errno) ); + rc = G10ERR_OPEN_FILE; goto leave; } handle_progress (&pfx, inp, fname); /* prepare key */ - s2k = xcalloc (1, sizeof *s2k ); + s2k = xmalloc_clear( sizeof *s2k ); s2k->mode = RFC1991? 0:opt.s2k_mode; - s2k->hash_algo = opt.s2k_digest_algo; + s2k->hash_algo = S2K_DIGEST_ALGO; algo = default_cipher_algo(); if (!opt.quiet || !opt.batch) log_info (_("%s encryption will be used\n"), - gcry_cipher_algo_name (algo) ); + gcry_cipher_algo_name (algo) ); cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, NULL); if (!cfx.dek || !cfx.dek->keylen) { - rc = gpg_error (GPG_ERR_INV_PASSPHRASE); - log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) ); + rc = G10ERR_PASSPHRASE; + log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); goto leave; } + /* We have no way to tell if the recipient can handle messages + with an MDC, so this defaults to no. Perhaps in a few years, + this can be defaulted to yes. Note that like regular + encrypting, --force-mdc overrides --disable-mdc. */ + if(opt.force_mdc) + cfx.dek->use_mdc=1; + /* now create the outfile */ rc = open_outfile (fname, opt.armor? 1:0, &out); if (rc) @@ -1141,11 +1242,14 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* prepare to calculate the MD over the input */ if (opt.textmode) iobuf_push_filter (inp, text_filter, &tfx); - gcry_md_open (&mfx.md, 0, 0); + if ( gcry_md_open (&mfx.md, 0, 0) ) + BUG (); + if ( DBG_HASHING ) + gcry_md_start_debug (mfx.md, "symc-sign"); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable (mfx.md, hash_for (sk->pubkey_algo, sk->version )); + gcry_md_enable (mfx.md, hash_for (sk)); } iobuf_push_filter (inp, md_filter, &mfx); @@ -1157,26 +1261,23 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* Write the symmetric key packet */ /*(current filters: armor)*/ if (!RFC1991) { - PKT_symkey_enc *enc = xcalloc (1, sizeof *enc ); + PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; enc->s2k = *s2k; 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); + log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); + xfree(enc); } /* Push the encryption filter */ iobuf_push_filter( out, cipher_filter, &cfx ); - /* Push the Zip filter */ - if (opt.compress && default_compress_algo()) - { - zfx.algo = default_compress_algo(); - iobuf_push_filter( out, compress_filter, &zfx ); - } + /* Push the compress filter */ + if (default_compress_algo()) + push_compress_filter(out,&zfx,default_compress_algo()); /* Write the one-pass signature packets */ /*(current filters: zip - encrypt - armor)*/ @@ -1187,6 +1288,8 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) goto leave; } + write_status (STATUS_BEGIN_SIGNING); + /* Pipe data through all filters; i.e. write the signed stuff */ /*(current filters: zip - encrypt - armor)*/ rc = write_plaintext_packet (out, inp, fname, opt.textmode ? 't':'b'); @@ -1211,9 +1314,9 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) } iobuf_close(inp); release_sk_list( sk_list ); - gcry_md_close ( mfx.md ); - xfree (cfx.dek); - xfree (s2k); + gcry_md_close( mfx.md ); + xfree(cfx.dek); + xfree(s2k); return rc; } @@ -1226,7 +1329,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) * SIGVERSION gives the minimal required signature packet version; * this is needed so that special properties like local sign are not * applied (actually: dropped) when a v3 key is used. TIMESTAMP is - * the timestamp to use for the signature. 0 means "now". */ + * the timestamp to use for the signature. 0 means "now" */ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, @@ -1241,7 +1344,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, MD_HANDLE md; assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F - || sigclass == 0x20 || sigclass == 0x18 + || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x30 || sigclass == 0x28 ); if (opt.force_v4_certs) @@ -1270,26 +1373,31 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, if(opt.cert_digest_algo) digest_algo=opt.cert_digest_algo; - else if((sk->pubkey_algo==PUBKEY_ALGO_RSA || - sk->pubkey_algo==PUBKEY_ALGO_RSA_S) && - pk->version<4 && sigversion < 4) + else if(sk->pubkey_algo==PUBKEY_ALGO_RSA + && pk->version<4 && sigversion<4) digest_algo = DIGEST_ALGO_MD5; else digest_algo = DIGEST_ALGO_SHA1; } - gcry_md_open (&md, digest_algo, 0 ); + if ( gcry_md_open (&md, digest_algo, 0 ) ) + BUG (); - /* hash the public key certificate and the user id */ + /* Hash the public key certificate. */ hash_public_key( md, pk ); - if( sigclass == 0x18 || sigclass == 0x28 ) { /* subkey binding/revocation*/ + + if( sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x28 ) + { + /* hash the subkey binding/backsig/revocation */ hash_public_key( md, subpk ); - } - else if( sigclass != 0x1F && sigclass != 0x20 ) { + } + else if( sigclass != 0x1F && sigclass != 0x20 ) + { + /* hash the user id */ hash_uid (md, sigversion, uid); - } + } /* and make the signature packet */ - sig = xcalloc (1, sizeof *sig ); + sig = xmalloc_clear( sizeof *sig ); sig->version = sigversion; sig->flags.exportable=1; sig->flags.revocable=1; @@ -1305,7 +1413,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, sig->sig_class = sigclass; if( sig->version >= 4 ) build_sig_subpkt_from_sig( sig ); - mk_notation_policy_etc ( sig, pk, sk ); + mk_notation_policy_etc( sig, pk, sk ); /* Crucial that the call to mksubpkt comes LAST before the calls to finalize the sig as that makes it possible for the mksubpkt @@ -1343,8 +1451,7 @@ update_keysig_packet( PKT_signature **ret_sig, PKT_public_key *subpk, PKT_secret_key *sk, int (*mksubpkt)(PKT_signature *, void *), - void *opaque - ) + void *opaque ) { PKT_signature *sig; int rc=0; @@ -1353,11 +1460,12 @@ update_keysig_packet( PKT_signature **ret_sig, if ((!orig_sig || !pk || !sk) || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) || (orig_sig->sig_class == 0x18 && !subpk)) - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; - gcry_md_open (&md, orig_sig->digest_algo, 0); + if ( gcry_md_open (&md, orig_sig->digest_algo, 0 ) ) + BUG (); - /* hash the public key certificate and the user id */ + /* Hash the public key certificate and the user id. */ hash_public_key( md, pk ); if( orig_sig->sig_class == 0x18 ) @@ -1367,7 +1475,7 @@ update_keysig_packet( PKT_signature **ret_sig, /* create a new signature packet */ sig = copy_signature (NULL, orig_sig); - + /* We need to create a new timestamp so that new sig expiration calculations are done correctly... */ sig->timestamp=make_timestamp(); @@ -1398,7 +1506,7 @@ update_keysig_packet( PKT_signature **ret_sig, if (!rc) { hash_sigversion_to_magic (md, sig); - gcry_md_final (md); + md_final(md); rc = complete_sig( sig, sk, md ); } diff --git a/g10/signal.c b/g10/signal.c index 9f50fbe3a..aaeb89841 100644 --- a/g10/signal.c +++ b/g10/signal.c @@ -1,5 +1,6 @@ /* signal.c - signal handling - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -26,22 +28,28 @@ #include <string.h> #include <errno.h> #include <assert.h> +#ifdef HAVE_LIBREADLINE +#include <readline/readline.h> +#include <readline/history.h> +#endif +#include "gpg.h" #include "options.h" #include "errors.h" -#include "memory.h" #include "util.h" #include "main.h" #include "ttyio.h" - +#ifdef HAVE_DOSISH_SYSTEM +void init_signals(void) {} +void pause_on_sigusr(int which) {} +#else static volatile int caught_fatal_sig = 0; static volatile int caught_sigusr1 = 0; static void init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_ign ) { -#ifndef HAVE_DOSISH_SYSTEM #if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION) struct sigaction oact, nact; @@ -65,20 +73,8 @@ init_one_signal (int sig, RETSIGTYPE (*handler)(int), int check_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 ) { @@ -89,14 +85,33 @@ got_fatal_signal( int sig ) caught_fatal_sig = 1; gcry_control (GCRYCTL_TERM_SECMEM ); - /* better don't transtale these messages */ + +#ifdef HAVE_LIBREADLINE + rl_free_line_state (); + rl_cleanup_after_signal (); +#endif + + /* Better don't translate these messages. */ write(2, "\n", 1 ); - s = "?" /* FIXME: log_get_name()*/; if( s ) write(2, s, strlen(s) ); + s = log_get_name(); if( s ) write(2, s, strlen(s) ); write(2, ": ", 2 ); - s = get_signal_name(sig); write(2, s, strlen(s) ); + +#if HAVE_DECL_SYS_SIGLIST && defined(NSIG) + s = (sig >= 0 && sig < NSIG) ? sys_siglist[sig] : "?"; + write (2, s, strlen(s) ); +#else + write (2, "signal ", 7 ); + if (sig < 0 || sig >=100) + write (2, "?", 1); + else { + if (sig >= 10) + write (2, "0123456789"+(sig/10), 1 ); + write (2, "0123456789"+(sig%10), 1 ); + } +#endif write(2, " caught ... exiting\n", 20 ); - /* reset action to default action and raise signal again */ + /* Reset action to default action and raise signal again. */ init_one_signal (sig, SIG_DFL, 0); dotlock_remove_lockfiles (); #ifdef __riscos__ @@ -116,7 +131,6 @@ got_usr_signal( int sig ) void init_signals() { -#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 ); @@ -124,14 +138,12 @@ init_signals() 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 pause_on_sigusr( int which ) { -#ifndef HAVE_DOSISH_SYSTEM #if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) sigset_t mask, oldmask; @@ -150,16 +162,15 @@ pause_on_sigusr( int which ) while (!caught_sigusr1) sigpause(SIGUSR1); caught_sigusr1 = 0; - sigrelse(SIGUSR1); -#endif /*!HAVE_SIGPROCMASK && HAVE_SISET_T*/ -#endif + sigrelse(SIGUSR1); +#endif /*! HAVE_SIGPROCMASK && HAVE_SIGSET_T */ } - +/* Disabled - see comment in tdbio.c:tdbio_begin_transaction() */ +#if 0 static void do_block( int block ) { -#ifndef HAVE_DOSISH_SYSTEM static int is_blocked; #if defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSET_T) static sigset_t oldmask; @@ -179,14 +190,14 @@ do_block( int block ) sigprocmask( SIG_SETMASK, &oldmask, NULL ); is_blocked = 0; } -#else /*!HAVE_SIGPROCMASK*/ +#else /*! HAVE_SIGPROCMASK && HAVE_SIGSET_T */ #if defined(NSIG) -# define SIGSMAX (NSIG) +#define SIGSMAX (NSIG) #elif defined(MAXSIG) -# define SIGSMAX (MAXSIG+1) +#define SIGSMAX (MAXSIG+1) #else -# error "define SIGSMAX to the number of signals on your platform plus one" +#error "define SIGSMAX to the number of signals on your platform plus one" #endif static void (*disposition[SIGSMAX])(int); @@ -208,11 +219,9 @@ do_block( int block ) } is_blocked = 0; } -#endif /*!HAVE_SIGPROCMASK*/ -#endif /*HAVE_DOSISH_SYSTEM*/ +#endif /*! HAVE_SIGPROCMASK && HAVE_SIGSET_T */ } - void block_all_signals() { @@ -224,3 +233,6 @@ unblock_all_signals() { do_block(0); } +#endif + +#endif /* !HAVE_DOSISH_SYSTEM */ diff --git a/g10/skclist.c b/g10/skclist.c index 67d9eb2f9..1cb69074a 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -1,5 +1,5 @@ -/* skclist.c - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +/* skclist.c - Build a list of secret keys + * Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -25,11 +26,11 @@ #include <errno.h> #include <assert.h> +#include "gpg.h" #include "options.h" #include "packet.h" #include "errors.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "i18n.h" #include "cipher.h" @@ -43,11 +44,41 @@ release_sk_list( SK_LIST sk_list ) for( ; sk_list; sk_list = sk_rover ) { sk_rover = sk_list->next; free_secret_key( sk_list->sk ); - xfree ( sk_list ); + xfree( sk_list ); } } +/* Check that we are only using keys which don't have + * the string "(insecure!)" or "not secure" or "do not use" + * in one of the user ids + */ +static int +is_insecure( PKT_secret_key *sk ) +{ + u32 keyid[2]; + KBNODE node = NULL, u; + int insecure = 0; + + keyid_from_sk( sk, keyid ); + node = get_pubkeyblock( keyid ); + for ( u = node; u; u = u->next ) { + if ( u->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *id = u->pkt->pkt.user_id; + if ( id->attrib_data ) + continue; /* skip attribute packets */ + if ( strstr( id->name, "(insecure!)" ) + || strstr( id->name, "not secure" ) + || strstr( id->name, "do not use" ) ) { + insecure = 1; + break; + } + } + } + release_kbnode( node ); + + return insecure; +} static int key_present_in_sk_list(SK_LIST sk_list, PKT_secret_key *sk) @@ -77,37 +108,41 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, SK_LIST sk_list = NULL; int rc; - if( !locusr ) { /* use the default one */ + if( !locusr ) + { /* use the default one */ PKT_secret_key *sk; - sk = xcalloc (1, sizeof *sk ); + sk = xmalloc_clear( sizeof *sk ); sk->req_usage = use; if( (rc = get_seckey_byname( sk, NULL, unlock )) ) { - free_secret_key( sk ); sk = NULL; - log_error("no default secret key: %s\n", gpg_strerror (rc) ); + free_secret_key( sk ); sk = NULL; + log_error("no default secret key: %s\n", g10_errstr(rc) ); } - else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) ) + { SK_LIST r; - if( sk->version == 4 && (use & PUBKEY_USAGE_SIG) - && sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { - log_info("this is a PGP generated " - "ElGamal key which is NOT secure for signatures!\n"); + if( random_is_faked() && !is_insecure( sk ) ) + { + log_info(_("key is not flagged as insecure - " + "can't use it with the faked RNG!\n")); free_secret_key( sk ); sk = NULL; - } - else { - r = xmalloc ( sizeof *r ); + } + else + { + r = xmalloc( sizeof *r ); r->sk = sk; sk = NULL; r->next = sk_list; r->mark = 0; sk_list = r; - } - } - else { + } + } + else + { free_secret_key( sk ); sk = NULL; - log_error("invalid default secret key: %s\n", gpg_strerror (rc) ); - } - } + log_error("invalid default secret key: %s\n", g10_errstr(rc) ); + } + } else { STRLIST locusr_orig = locusr; for(; locusr; locusr = locusr->next ) { @@ -118,36 +153,47 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, * won't catch all duplicates because the user IDs may be * specified in different ways. */ - if ( is_duplicated_entry ( locusr_orig, locusr ) ) { - log_error(_("skipped `%s': duplicated\n"), locusr->d ); + if ( is_duplicated_entry ( locusr_orig, locusr ) ) + { + log_error(_("skipped \"%s\": duplicated\n"), locusr->d ); continue; - } - sk = xcalloc (1, sizeof *sk ); + } + sk = xmalloc_clear( sizeof *sk ); sk->req_usage = use; - if( (rc = get_seckey_byname( sk, locusr->d, 0 )) ) { + if( (rc = get_seckey_byname( sk, locusr->d, 0 )) ) + { free_secret_key( sk ); sk = NULL; - log_error(_("skipped `%s': %s\n"), locusr->d, gpg_strerror (rc) ); - } + log_error(_("skipped \"%s\": %s\n"), + locusr->d, g10_errstr(rc) ); + } else if ( key_present_in_sk_list(sk_list, sk) == 0) { free_secret_key(sk); sk = NULL; log_info(_("skipped: secret key already present\n")); } - else if ( unlock && (rc = check_secret_key( sk, 0 )) ) { + else if ( unlock && (rc = check_secret_key( sk, 0 )) ) + { free_secret_key( sk ); sk = NULL; - log_error(_("skipped `%s': %s\n"), locusr->d, gpg_strerror (rc) ); - } + log_error(_("skipped \"%s\": %s\n"), + locusr->d, g10_errstr(rc) ); + } else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) { SK_LIST r; if( sk->version == 4 && (use & PUBKEY_USAGE_SIG) - && sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { - log_info(_("skipped `%s': this is a PGP generated " - "ElGamal key which is not secure for signatures!\n"), - locusr->d ); + && sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) + { + log_info(_("skipped \"%s\": %s\n"),locusr->d, + _("this is a PGP generated Elgamal key which" + " is not secure for signatures!")); + free_secret_key( sk ); sk = NULL; + } + else if( random_is_faked() && !is_insecure( sk ) ) { + log_info(_("key is not flagged as insecure - " + "can't use it with the faked RNG!\n")); free_secret_key( sk ); sk = NULL; } else { - r = xmalloc ( sizeof *r ); + r = xmalloc( sizeof *r ); r->sk = sk; sk = NULL; r->next = sk_list; r->mark = 0; @@ -156,7 +202,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, } else { free_secret_key( sk ); sk = NULL; - log_error("skipped `%s': %s\n", locusr->d, gpg_strerror (rc) ); + log_error("skipped \"%s\": %s\n", locusr->d, g10_errstr(rc) ); } } } @@ -164,7 +210,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, if( !rc && !sk_list ) { log_error("no valid signators\n"); - rc = GPG_ERR_NO_USER_ID; + rc = G10ERR_NO_USER_ID; } if( rc ) diff --git a/g10/status.c b/g10/status.c index aa55020be..ffee8559f 100644 --- a/g10/status.c +++ b/g10/status.c @@ -1,6 +1,6 @@ -/* status.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002, - * 2003 Free Software Foundation, Inc. +/* status.c - Status message and command-fd interface + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2004, 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -44,98 +45,145 @@ static FILE *statusfp; static void -progress_cb (void *ctx, const char *what, int printchar, int current, int total) +progress_cb ( void *ctx, int c ) { - char buf[150]; - - if (printchar == '\n') - printchar = 'X'; - - sprintf (buf, "%.20s %c %d %d", what, printchar, current, total); - write_status_text (STATUS_PROGRESS, buf); + char buf[50]; + + if ( c == '\n' ) + sprintf ( buf, "%.20s X 100 100", (char*)ctx ); + else + sprintf ( buf, "%.20s %c 0 0", (char*)ctx, c ); + write_status_text ( STATUS_PROGRESS, buf ); } static const char * get_status_string ( int no ) { - const char *s; - - switch( no ) { - case STATUS_ENTER : s = "ENTER"; break; - case STATUS_LEAVE : s = "LEAVE"; break; - case STATUS_ABORT : s = "ABORT"; break; - case STATUS_GOODSIG: s = "GOODSIG"; break; - case STATUS_KEYEXPIRED: s = "KEYEXPIRED"; break; - case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; - case STATUS_BADSIG : s = "BADSIG"; break; - case STATUS_ERRSIG : s = "ERRSIG"; break; - case STATUS_BADARMOR : s = "BADARMOR"; break; - case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; - case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; - case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; - case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; - case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; - case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; - case STATUS_GET_BOOL : s = "GET_BOOL"; break; - case STATUS_GET_LINE : s = "GET_LINE"; break; - case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break; - case STATUS_GOT_IT : s = "GOT_IT"; break; - case STATUS_SHM_INFO : s = "SHM_INFO"; break; - case STATUS_SHM_GET : s = "SHM_GET"; break; - case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; - case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; - case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; - case STATUS_VALIDSIG : s = "VALIDSIG"; break; - case STATUS_SIG_ID : s = "SIG_ID"; break; - case STATUS_ENC_TO : s = "ENC_TO"; break; - case STATUS_NODATA : s = "NODATA"; break; - case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; - case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; - case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; - case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; - case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; - case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; - case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; - case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; - case STATUS_GOODMDC : s = "GOODMDC"; break; - case STATUS_BADMDC : s = "BADMDC"; break; - case STATUS_ERRMDC : s = "ERRMDC"; break; - case STATUS_IMPORTED : s = "IMPORTED"; break; - case STATUS_IMPORT_OK : s = "IMPORT_OK"; break; - case STATUS_IMPORT_CHECK : s = "IMPORT_CHECK"; break; - case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; - case STATUS_FILE_START : s = "FILE_START"; break; - case STATUS_FILE_DONE : s = "FILE_DONE"; break; - case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; - case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break; - case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break; - case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break; - case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break; - case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break; - case STATUS_PROGRESS : s = "PROGRESS"; break; - case STATUS_SIG_CREATED : s = "SIG_CREATED"; break; - case STATUS_SESSION_KEY : s = "SESSION_KEY"; break; - case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break; - case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break; - case STATUS_POLICY_URL : s = "POLICY_URL" ; break; - case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break; - case STATUS_END_STREAM : s = "END_STREAM"; break; - case STATUS_KEY_CREATED : s = "KEY_CREATED"; break; - case STATUS_USERID_HINT : s = "USERID_HINT"; break; - case STATUS_UNEXPECTED : s = "UNEXPECTED"; break; - case STATUS_INV_RECP : s = "INV_RECP"; break; - case STATUS_NO_RECP : s = "NO_RECP"; break; - case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break; - case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; - case STATUS_EXPSIG : s = "EXPSIG"; break; - case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; - case STATUS_REVKEYSIG : s = "REVKEYSIG"; break; - case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; - default: s = "?"; break; + const char *s; + + switch( no ) + { + case STATUS_ENTER : s = "ENTER"; break; + case STATUS_LEAVE : s = "LEAVE"; break; + case STATUS_ABORT : s = "ABORT"; break; + case STATUS_NEWSIG : s = "NEWSIG"; break; + case STATUS_GOODSIG: s = "GOODSIG"; break; + case STATUS_KEYEXPIRED: s = "KEYEXPIRED"; break; + case STATUS_KEYREVOKED: s = "KEYREVOKED"; break; + case STATUS_BADSIG : s = "BADSIG"; break; + case STATUS_ERRSIG : s = "ERRSIG"; break; + case STATUS_BADARMOR : s = "BADARMOR"; break; + case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA"; break; + case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED"; break; + case STATUS_TRUST_NEVER : s = "TRUST_NEVER"; break; + case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL"; break; + case STATUS_TRUST_FULLY : s = "TRUST_FULLY"; break; + case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE"; break; + case STATUS_GET_BOOL : s = "GET_BOOL"; break; + case STATUS_GET_LINE : s = "GET_LINE"; break; + case STATUS_GET_HIDDEN : s = "GET_HIDDEN"; break; + case STATUS_GOT_IT : s = "GOT_IT"; break; + case STATUS_SHM_INFO : s = "SHM_INFO"; break; + case STATUS_SHM_GET : s = "SHM_GET"; break; + case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL"; break; + case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN"; break; + case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE"; break; + case STATUS_VALIDSIG : s = "VALIDSIG"; break; + case STATUS_SIG_ID : s = "SIG_ID"; break; + case STATUS_ENC_TO : s = "ENC_TO"; break; + case STATUS_NODATA : s = "NODATA"; break; + case STATUS_BAD_PASSPHRASE : s = "BAD_PASSPHRASE"; break; + case STATUS_NO_PUBKEY : s = "NO_PUBKEY"; break; + case STATUS_NO_SECKEY : s = "NO_SECKEY"; break; + case STATUS_NEED_PASSPHRASE_SYM: s = "NEED_PASSPHRASE_SYM"; break; + case STATUS_NEED_PASSPHRASE_PIN: s = "NEED_PASSPHRASE_PIN"; break; + case STATUS_DECRYPTION_FAILED: s = "DECRYPTION_FAILED"; break; + case STATUS_DECRYPTION_OKAY: s = "DECRYPTION_OKAY"; break; + case STATUS_MISSING_PASSPHRASE: s = "MISSING_PASSPHRASE"; break; + case STATUS_GOOD_PASSPHRASE : s = "GOOD_PASSPHRASE"; break; + case STATUS_GOODMDC : s = "GOODMDC"; break; + case STATUS_BADMDC : s = "BADMDC"; break; + case STATUS_ERRMDC : s = "ERRMDC"; break; + case STATUS_IMPORTED : s = "IMPORTED"; break; + case STATUS_IMPORT_OK : s = "IMPORT_OK"; break; + case STATUS_IMPORT_CHECK : s = "IMPORT_CHECK"; break; + case STATUS_IMPORT_RES : s = "IMPORT_RES"; break; + case STATUS_FILE_START : s = "FILE_START"; break; + case STATUS_FILE_DONE : s = "FILE_DONE"; break; + case STATUS_FILE_ERROR : s = "FILE_ERROR"; break; + case STATUS_BEGIN_DECRYPTION:s = "BEGIN_DECRYPTION"; break; + case STATUS_END_DECRYPTION : s = "END_DECRYPTION"; break; + case STATUS_BEGIN_ENCRYPTION:s = "BEGIN_ENCRYPTION"; break; + case STATUS_END_ENCRYPTION : s = "END_ENCRYPTION"; break; + case STATUS_DELETE_PROBLEM : s = "DELETE_PROBLEM"; break; + case STATUS_PROGRESS : s = "PROGRESS"; break; + case STATUS_SIG_CREATED : s = "SIG_CREATED"; break; + case STATUS_SESSION_KEY : s = "SESSION_KEY"; break; + case STATUS_NOTATION_NAME : s = "NOTATION_NAME" ; break; + case STATUS_NOTATION_DATA : s = "NOTATION_DATA" ; break; + case STATUS_POLICY_URL : s = "POLICY_URL" ; break; + case STATUS_BEGIN_STREAM : s = "BEGIN_STREAM"; break; + case STATUS_END_STREAM : s = "END_STREAM"; break; + case STATUS_KEY_CREATED : s = "KEY_CREATED"; break; + case STATUS_KEY_NOT_CREATED: s = "KEY_NOT_CREATED"; break; + case STATUS_USERID_HINT : s = "USERID_HINT"; break; + case STATUS_UNEXPECTED : s = "UNEXPECTED"; break; + case STATUS_INV_RECP : s = "INV_RECP"; break; + case STATUS_NO_RECP : s = "NO_RECP"; break; + case STATUS_ALREADY_SIGNED : s = "ALREADY_SIGNED"; break; + case STATUS_SIGEXPIRED : s = "SIGEXPIRED deprecated-use-keyexpired-instead"; break; + case STATUS_EXPSIG : s = "EXPSIG"; break; + case STATUS_EXPKEYSIG : s = "EXPKEYSIG"; break; + case STATUS_REVKEYSIG : s = "REVKEYSIG"; break; + case STATUS_ATTRIBUTE : s = "ATTRIBUTE"; break; + case STATUS_CARDCTRL : s = "CARDCTRL"; break; + case STATUS_PLAINTEXT : s = "PLAINTEXT"; break; + case STATUS_PLAINTEXT_LENGTH:s = "PLAINTEXT_LENGTH"; break; + case STATUS_SIG_SUBPACKET : s = "SIG_SUBPACKET"; break; + case STATUS_SC_OP_SUCCESS : s = "SC_OP_SUCCESS"; break; + case STATUS_SC_OP_FAILURE : s = "SC_OP_FAILURE"; break; + case STATUS_BACKUP_KEY_CREATED:s="BACKUP_KEY_CREATED"; break; + case STATUS_PKA_TRUST_BAD : s = "PKA_TRUST_BAD"; break; + case STATUS_PKA_TRUST_GOOD : s = "PKA_TRUST_GOOD"; break; + case STATUS_BEGIN_SIGNING : s = "BEGIN_SIGNING"; break; + default: s = "?"; break; + } + return s; +} + + +/* Return true if the status message NO may currently be issued. We + need this to avoid syncronisation problem while auto retrieving a + key. There it may happen that a status NODATA is issued for a non + available key and the user may falsely interpret this has a missing + signature. */ +static int +status_currently_allowed (int no) +{ + if (!glo_ctrl.in_auto_key_retrieve) + return 1; /* Yes. */ + + /* We allow some statis anyway, so that import statistics are + correct and to avoid problems if the retriebval subsystem will + prompt the user. */ + switch (no) + { + case STATUS_GET_BOOL: + case STATUS_GET_LINE: + case STATUS_GET_HIDDEN: + case STATUS_GOT_IT: + case STATUS_IMPORTED: + case STATUS_IMPORT_OK: + case STATUS_IMPORT_CHECK: + case STATUS_IMPORT_RES: + return 1; /* Yes. */ + default: + break; } - return s; + return 0; /* No. */ } + void set_status_fd ( int fd ) { @@ -161,7 +209,9 @@ set_status_fd ( int fd ) fd, strerror(errno)); } last_fd = fd; - gcry_set_progress_handler (progress_cb, NULL); + register_primegen_progress ( progress_cb, "primegen" ); + register_pk_dsa_progress ( progress_cb, "pk_dsa" ); + register_pk_elg_progress ( progress_cb, "pk_elg" ); } int @@ -179,8 +229,8 @@ write_status ( int no ) void write_status_text ( int no, const char *text) { - if( !statusfp ) - return; /* not enabled */ + if( !statusfp || !status_currently_allowed (no) ) + return; /* Not enabled or allowed. */ fputs ( "[GNUPG:] ", statusfp ); fputs ( get_status_string (no), statusfp ); @@ -196,7 +246,8 @@ write_status_text ( int no, const char *text) } } putc ('\n',statusfp); - fflush (statusfp); + if ( fflush (statusfp) && opt.exit_on_status_write_error ) + g10_exit (0); } @@ -215,8 +266,8 @@ write_status_text_and_buffer ( int no, const char *string, int lower_limit = ' '; size_t n, count, dowrap; - if( !statusfp ) - return; /* not enabled */ + if( !statusfp || !status_currently_allowed (no) ) + return; /* Not enabled or allowed. */ if (wrap == -1) { lower_limit--; @@ -260,7 +311,8 @@ write_status_text_and_buffer ( int no, const char *string, } while ( len ); putc ('\n',statusfp); - fflush (statusfp); + if ( fflush (statusfp) && opt.exit_on_status_write_error ) + g10_exit (0); } void @@ -308,6 +360,9 @@ do_get_from_fd( const char *keyword, int hidden, int bool ) int i, len; char *string; + if(statusfp!=stdout) + fflush(stdout); + write_status_text( bool? STATUS_GET_BOOL : hidden? STATUS_GET_HIDDEN : STATUS_GET_LINE, keyword ); @@ -348,6 +403,10 @@ cpr_enabled() { if( opt.command_fd != -1 ) return 1; +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return 1; +#endif return 0; } @@ -358,6 +417,10 @@ cpr_get_no_help( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return do_get_from_fd ( keyword, 0, 0 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return do_shm_get( keyword, 0, 0 ); +#endif for(;;) { p = tty_get( prompt ); return p; @@ -371,10 +434,14 @@ cpr_get( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return do_get_from_fd ( keyword, 0, 0 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return do_shm_get( keyword, 0, 0 ); +#endif for(;;) { p = tty_get( prompt ); if( *p=='?' && !p[1] && !(keyword && !*keyword)) { - xfree (p); + xfree(p); display_online_help( keyword ); } else @@ -390,7 +457,7 @@ cpr_get_utf8( const char *keyword, const char *prompt ) p = cpr_get( keyword, prompt ); if( p ) { char *utf8 = native_to_utf8( p ); - xfree ( p ); + xfree( p ); p = utf8; } return p; @@ -403,10 +470,14 @@ cpr_get_hidden( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return do_get_from_fd ( keyword, 1, 0 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return do_shm_get( keyword, 1, 0 ); +#endif for(;;) { p = tty_get_hidden( prompt ); if( *p == '?' && !p[1] ) { - xfree (p); + xfree(p); display_online_help( keyword ); } else @@ -419,6 +490,10 @@ cpr_kill_prompt(void) { if( opt.command_fd != -1 ) return; +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return; +#endif tty_kill_prompt(); return; } @@ -431,17 +506,21 @@ cpr_get_answer_is_yes( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return !!do_get_from_fd ( keyword, 0, 1 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return !!do_shm_get( keyword, 0, 1 ); +#endif for(;;) { p = tty_get( prompt ); trim_spaces(p); /* it is okay to do this here */ if( *p == '?' && !p[1] ) { - xfree (p); + xfree(p); display_online_help( keyword ); } else { tty_kill_prompt(); yes = answer_is_yes(p); - xfree (p); + xfree(p); return yes; } } @@ -455,18 +534,65 @@ cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ) if( opt.command_fd != -1 ) return !!do_get_from_fd ( keyword, 0, 1 ); +#ifdef USE_SHM_COPROCESSING + if( opt.shm_coprocess ) + return !!do_shm_get( keyword, 0, 1 ); +#endif for(;;) { p = tty_get( prompt ); trim_spaces(p); /* it is okay to do this here */ if( *p == '?' && !p[1] ) { - xfree (p); + xfree(p); display_online_help( keyword ); } else { tty_kill_prompt(); yes = answer_is_yes_no_quit(p); - xfree (p); + xfree(p); return yes; } } } + + +int +cpr_get_answer_okay_cancel (const char *keyword, + const char *prompt, + int def_answer) +{ + int yes; + char *answer = NULL; + char *p; + + if( opt.command_fd != -1 ) + answer = do_get_from_fd ( keyword, 0, 0 ); +#ifdef USE_SHM_COPROCESSING + else if( opt.shm_coprocess ) + answer = do_shm_get( keyword, 0, 0 ); +#endif + + if (answer) + { + yes = answer_is_okay_cancel (answer, def_answer); + xfree (answer); + return yes; + } + + for(;;) + { + p = tty_get( prompt ); + trim_spaces(p); /* it is okay to do this here */ + if (*p == '?' && !p[1]) + { + xfree(p); + display_online_help (keyword); + } + else + { + tty_kill_prompt(); + yes = answer_is_okay_cancel (p, def_answer); + xfree(p); + return yes; + } + } +} diff --git a/g10/status.h b/g10/status.h index d8de81080..b5dbe7480 100644 --- a/g10/status.h +++ b/g10/status.h @@ -1,5 +1,6 @@ /* status.h - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, + * 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,12 +16,12 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_STATUS_H #define G10_STATUS_H - #define STATUS_ENTER 1 #define STATUS_LEAVE 2 #define STATUS_ABORT 3 @@ -29,7 +30,6 @@ #define STATUS_BADSIG 5 #define STATUS_ERRSIG 6 - #define STATUS_BADARMOR 7 #define STATUS_RSA_OR_IDEA 8 @@ -100,6 +100,26 @@ #define STATUS_IMPORT_OK 68 #define STATUS_IMPORT_CHECK 69 #define STATUS_REVKEYSIG 70 +#define STATUS_CARDCTRL 71 +#define STATUS_NEWSIG 72 +#define STATUS_PLAINTEXT 73 +#define STATUS_PLAINTEXT_LENGTH 74 +#define STATUS_KEY_NOT_CREATED 75 +#define STATUS_NEED_PASSPHRASE_PIN 76 +#define STATUS_SIG_SUBPACKET 77 + +/* Extra status codes for certain smartcard operations. Primary + useful to double check that change PIN worked as expected. */ +#define STATUS_SC_OP_FAILURE 79 +#define STATUS_SC_OP_SUCCESS 80 + +#define STATUS_BACKUP_KEY_CREATED 81 + +#define STATUS_PKA_TRUST_BAD 82 +#define STATUS_PKA_TRUST_GOOD 83 + +#define STATUS_BEGIN_SIGNING 84 + /*-- status.c --*/ void set_status_fd ( int fd ); @@ -119,6 +139,8 @@ char *cpr_get_hidden( const char *keyword, const char *prompt ); void cpr_kill_prompt(void); int cpr_get_answer_is_yes( const char *keyword, const char *prompt ); int cpr_get_answer_yes_no_quit( const char *keyword, const char *prompt ); - +int cpr_get_answer_okay_cancel (const char *keyword, + const char *prompt, + int def_answer); #endif /*G10_STATUS_H*/ diff --git a/g10/tdbdump.c b/g10/tdbdump.c index 5eb482959..d840c0882 100644 --- a/g10/tdbdump.c +++ b/g10/tdbdump.c @@ -1,5 +1,5 @@ /* tdbdump.c - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -34,7 +35,6 @@ #include "errors.h" #include "iobuf.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "trustdb.h" #include "options.h" @@ -58,7 +58,7 @@ write_record( TRUSTREC *rec ) if( !rc ) return; log_error(_("trust record %lu, type %d: write failed: %s\n"), - rec->recnum, rec->rectype, gpg_strerror (rc) ); + rec->recnum, rec->rectype, g10_errstr(rc) ); tdbio_invalid(); } @@ -132,7 +132,7 @@ import_ownertrust( const char *fname ) int rc; init_trustdb(); - if( !fname || (*fname == '-' && !fname[1]) ) { + if( iobuf_is_pipe_filename (fname) ) { fp = stdin; fname = "[stdin]"; is_stdin = 1; @@ -142,6 +142,14 @@ import_ownertrust( const char *fname ) return; } + if (is_secured_file (fileno (fp))) + { + fclose (fp); + errno = EPERM; + log_error (_("can't open `%s': %s\n"), fname, strerror(errno) ); + return; + } + while( fgets( line, DIM(line)-1, fp ) ) { TRUSTREC rec; @@ -149,24 +157,26 @@ import_ownertrust( const char *fname ) continue; n = strlen(line); if( line[n-1] != '\n' ) { - log_error (_("\b%s: line too long\n"), fname ); + log_error (_("error in `%s': %s\n"), fname, _("line too long") ); /* ... or last line does not have a LF */ break; /* can't continue */ } for(p = line; *p && *p != ':' ; p++ ) - if( !hexdigitp (p) ) + if( !hexdigitp(p) ) break; if( *p != ':' ) { - log_error (_("\b%s: error: missing colon\n"), fname ); + log_error (_("error in `%s': %s\n"), fname, _("colon missing") ); continue; } fprlen = p - line; if( fprlen != 32 && fprlen != 40 ) { - log_error (_("\b%s: error: invalid fingerprint\n"), fname ); + log_error (_("error in `%s': %s\n"), + fname, _("invalid fingerprint") ); continue; } if( sscanf(p, ":%u:", &otrust ) != 1 ) { - log_error (_("\b%s: error: no ownertrust value\n"), fname ); + log_error (_("error in `%s': %s\n"), + fname, _("ownertrust value missing")); continue; } if( !otrust ) @@ -202,11 +212,11 @@ import_ownertrust( const char *fname ) any = 1; } else /* error */ - log_error (_("\b%s: error finding trust record: %s\n"), - fname, gpg_strerror (rc)); + log_error (_("error finding trust record in `%s': %s\n"), + fname, g10_errstr(rc)); } if( ferror(fp) ) - log_error (_("\b%s: read error: %s\n"), fname, strerror(errno) ); + log_error ( _("read error in `%s': %s\n"), fname, strerror(errno) ); if( !is_stdin ) fclose(fp); @@ -215,7 +225,7 @@ import_ownertrust( const char *fname ) revalidation_mark (); rc = tdbio_sync (); if (rc) - log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) ); + log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) ); } } diff --git a/g10/tdbio.c b/g10/tdbio.c index 75687a3b0..74e75b3c9 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -1,4 +1,4 @@ -/* tdbio.c +/* tdbio.c - trust databse I/O operations * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This file is part of GnuPG. @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -32,7 +33,6 @@ #include "gpg.h" #include "errors.h" #include "iobuf.h" -#include "memory.h" #include "util.h" #include "options.h" #include "main.h" @@ -123,21 +123,21 @@ get_record_from_cache( ulong recno ) static int write_cache_item( CACHE_CTRL r ) { + gpg_error_t err; int n; - gpg_error_t rc; if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - rc = gpg_error_from_errno (errno); + err = gpg_error_from_errno (errno); log_error(_("trustdb rec %lu: lseek failed: %s\n"), r->recno, strerror(errno) ); - return rc; + return err; } n = write( db_fd, r->data, TRUST_RECORD_LEN); if( n != TRUST_RECORD_LEN ) { - rc = gpg_error_from_errno (errno); + err = gpg_error_from_errno (errno); log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"), r->recno, n, strerror(errno) ); - return rc; + return err; } r->flags.dirty = 0; return 0; @@ -191,7 +191,7 @@ put_record_into_cache( ulong recno, const char *data ) } /* see whether we reached the limit */ if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */ - r = xmalloc ( sizeof *r ); + r = xmalloc( sizeof *r ); r->flags.used = 1; r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); @@ -234,7 +234,7 @@ put_record_into_cache( ulong recno, const char *data ) if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */ if( opt.debug && !(cache_entries % 100) ) log_debug("increasing tdbio cache size\n"); - r = xmalloc ( sizeof *r ); + r = xmalloc( sizeof *r ); r->flags.used = 1; r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); @@ -246,7 +246,7 @@ put_record_into_cache( ulong recno, const char *data ) return 0; } log_info(_("trustdb transaction too large\n")); - return GPG_ERR_RESOURCE_LIMIT; + return G10ERR_RESOURCE_LIMIT; } if( dirty_count ) { int n = dirty_count / 5; /* discard some dirty entries */ @@ -336,7 +336,6 @@ tdbio_sync() return 0; } - #if 0 /* The transaction code is disabled in the 1.2.x branch, as it is not yet used. It will be enabled in 1.3.x. */ @@ -375,11 +374,10 @@ tdbio_end_transaction() else is_locked = 1; } -#warning block_all_signals is not yet available in ../common/signals.c - /* block_all_signals(); */ + block_all_signals(); in_transaction = 0; rc = tdbio_sync(); -/* unblock_all_signals(); */ + unblock_all_signals(); if( !opt.lock_once ) { if( !release_dotlock( lockhandle ) ) is_locked = 0; @@ -410,9 +408,7 @@ tdbio_cancel_transaction() in_transaction = 0; return 0; } - -#endif /* transaction code */ - +#endif /******************************************************** @@ -502,9 +498,9 @@ tdbio_set_dbname( const char *new_dbname, int create ) if( access( fname, R_OK ) ) { if( errno != ENOENT ) { - log_error( _("%s: can't access: %s\n"), fname, strerror(errno) ); - xfree (fname); - return GPG_ERR_TRUSTDB; + log_error( _("can't access `%s': %s\n"), fname, strerror(errno) ); + xfree(fname); + return G10ERR_TRUSTDB; } if( create ) { FILE *fp; @@ -521,37 +517,42 @@ tdbio_set_dbname( const char *new_dbname, int create ) } *p = DIRSEP_C; - xfree (db_name); + xfree(db_name); db_name = fname; #ifdef __riscos__ if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); + log_fatal( _("can't create lock for `%s'\n"), db_name ); if( make_dotlock( lockhandle, -1 ) ) - log_fatal( _("%s: can't make lock\n"), db_name ); + log_fatal( _("can't lock `%s'\n"), db_name ); #endif /* __riscos__ */ oldmask=umask(077); - fp =fopen( fname, "wb" ); + if (is_secured_filename (fname)) { + fp = NULL; + errno = EPERM; + } + else + fp =fopen( fname, "wb" ); umask(oldmask); if( !fp ) - log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) ); + log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) ); fclose(fp); db_fd = open( db_name, O_RDWR | MY_O_BINARY ); if( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) ); #ifndef __riscos__ if( !lockhandle ) lockhandle = create_dotlock( db_name ); if( !lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); + log_fatal( _("can't create lock for `%s'\n"), db_name ); #endif /* !__riscos__ */ rc = create_version_record (); if( rc ) log_fatal( _("%s: failed to create version record: %s"), - fname, gpg_strerror (rc)); + fname, g10_errstr(rc)); /* and read again to check that we are okay */ if( tdbio_read_record( 0, &rec, RECTYPE_VER ) ) log_fatal( _("%s: invalid trustdb created\n"), db_name ); @@ -562,7 +563,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) return 0; } } - xfree (db_name); + xfree(db_name); db_name = fname; return 0; } @@ -588,30 +589,26 @@ open_db() if (!lockhandle ) lockhandle = create_dotlock( db_name ); if (!lockhandle ) - log_fatal( _("%s: can't create lock\n"), db_name ); + log_fatal( _("can't create lock for `%s'\n"), db_name ); #ifdef __riscos__ if (make_dotlock( lockhandle, -1 ) ) - log_fatal( _("%s: can't make lock\n"), db_name ); + log_fatal( _("can't lock `%s'\n"), db_name ); #endif /* __riscos__ */ db_fd = open (db_name, O_RDWR | MY_O_BINARY ); - if (db_fd == -1 && errno == EACCES) { + if (db_fd == -1 && (errno == EACCES +#ifdef EROFS + || errno == EROFS) +#endif + ) { db_fd = open (db_name, O_RDONLY | MY_O_BINARY ); if (db_fd != -1) log_info (_("NOTE: trustdb not writable\n")); } if ( db_fd == -1 ) - log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) ); + log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) ); + register_secured_file (db_name); - /* check whether we need to do a version migration */ - do - n = read (db_fd, buf, 5); - while (n==-1 && errno == EINTR); - if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5)) - { - migrate_from_v2 (); - } - - /* read the version record */ + /* Read the version record. */ if (tdbio_read_record (0, &rec, RECTYPE_VER ) ) log_fatal( _("%s: invalid trustdb\n"), db_name ); } @@ -646,7 +643,7 @@ create_hashtable( TRUSTREC *vr, int type ) rc = tdbio_write_record( &rec ); if( rc ) log_fatal( _("%s: failed to create hashtable: %s\n"), - db_name, gpg_strerror (rc)); + db_name, g10_errstr(rc)); } /* update the version record */ rc = tdbio_write_record( vr ); @@ -654,7 +651,7 @@ create_hashtable( TRUSTREC *vr, int type ) rc = tdbio_sync(); if( rc ) log_fatal( _("%s: error updating version record: %s\n"), - db_name, gpg_strerror (rc)); + db_name, g10_errstr(rc)); } @@ -671,7 +668,7 @@ tdbio_db_matches_options() rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); yes_no = vr.r.ver.marginals == opt.marginals_needed && vr.r.ver.completes == opt.completes_needed @@ -691,7 +688,7 @@ tdbio_read_model(void) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); return vr.r.ver.trust_model; } @@ -707,7 +704,7 @@ tdbio_read_nextcheck () rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); return vr.r.ver.nextcheck; } @@ -721,7 +718,7 @@ tdbio_write_nextcheck (ulong stamp) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); if (vr.r.ver.nextcheck == stamp) return 0; @@ -730,7 +727,7 @@ tdbio_write_nextcheck (ulong stamp) rc = tdbio_write_record( &vr ); if( rc ) log_fatal( _("%s: error writing version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); return 1; } @@ -751,7 +748,7 @@ get_trusthashrec(void) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); if( !vr.r.ver.trusthashtbl ) create_hashtable( &vr, 0 ); @@ -782,9 +779,8 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { - log_error ("upd_hashtable in `%s': read failed: %s\n", db_name, - gpg_strerror (rc) ); - return rc; + log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc) ); + return rc; } item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD]; @@ -792,8 +788,8 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum; rc = tdbio_write_record( &rec ); if( rc ) { - log_error ("upd_hashtable in `%s': write htbl failed: %s\n", - db_name, gpg_strerror (rc) ); + log_error("upd_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); return rc; } } @@ -802,7 +798,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { log_error( "upd_hashtable: read item failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } @@ -811,7 +807,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) level++; if( level >= keylen ) { log_error( "hashtable has invalid indirections.\n"); - return GPG_ERR_TRUSTDB; + return G10ERR_TRUSTDB; } goto next_level; } @@ -828,7 +824,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) &rec, RECTYPE_HLST); if( rc ) { log_error( "upd_hashtable: read hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } } @@ -843,7 +839,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( "upd_hashtable: write hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; /* done */ } } @@ -852,7 +848,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) &rec, RECTYPE_HLST ); if( rc ) { log_error( "upd_hashtable: read hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } } @@ -861,7 +857,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( "upd_hashtable: write hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } memset( &rec, 0, sizeof rec ); @@ -871,7 +867,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) log_error( "upd_hashtable: write ext hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; /* done */ } } /* end loop over hlst slots */ @@ -889,7 +885,7 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &rec ); if( rc ) { log_error( "upd_hashtable: write new hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } /* update the hashtable record */ @@ -897,14 +893,14 @@ upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum ) rc = tdbio_write_record( &lastrec ); if( rc ) log_error( "upd_hashtable: update htbl failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; /* ready */ } else { log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n", table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); list_trustdb(NULL); - return GPG_ERR_TRUSTDB; + return G10ERR_TRUSTDB; } } @@ -931,8 +927,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL ); if( rc ) { - log_error ("drop_from_hashtable `%s': read failed: %s\n", - db_name, gpg_strerror (rc) ); + log_error("drop_from_hashtable: read failed: %s\n", + g10_errstr(rc) ); return rc; } @@ -944,15 +940,15 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0; rc = tdbio_write_record( &rec ); if( rc ) - log_error ("drop_from_hashtable `%s': write htbl failed: %s\n", - db_name, gpg_strerror (rc) ); + log_error("drop_from_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); return rc; } rc = tdbio_read_record( item, &rec, 0 ); if( rc ) { log_error( "drop_from_hashtable: read item failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } @@ -961,7 +957,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) level++; if( level >= keylen ) { log_error( "hashtable has invalid indirections.\n"); - return GPG_ERR_TRUSTDB; + return G10ERR_TRUSTDB; } goto next_level; } @@ -973,9 +969,8 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) rec.r.hlst.rnum[i] = 0; /* drop */ rc = tdbio_write_record( &rec ); if( rc ) - log_error ("drop_from_hashtable `%s': " - "write htbl failed: %s\n", - db_name, gpg_strerror (rc) ); + log_error("drop_from_hashtable: write htbl failed: %s\n", + g10_errstr(rc) ); return rc; } } @@ -984,7 +979,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) &rec, RECTYPE_HLST); if( rc ) { log_error( "drop_from_hashtable: read hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } } @@ -995,7 +990,7 @@ drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum ) log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n", table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item); - return GPG_ERR_TRUSTDB; + return G10ERR_TRUSTDB; } @@ -1021,8 +1016,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, hashrec += msb / ITEMS_PER_HTBL_RECORD; rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL ); if( rc ) { - log_error ("lookup_hashtable in `%s' failed: %s\n", - db_name, gpg_strerror (rc) ); + log_error("lookup_hashtable failed: %s\n", g10_errstr(rc) ); return rc; } @@ -1032,16 +1026,15 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( item, rec, 0 ); if( rc ) { - log_error ("hashtable `%s' read failed: %s\n", - db_name, gpg_strerror (rc) ); + log_error( "hashtable read failed: %s\n", g10_errstr(rc) ); return rc; } if( rec->rectype == RECTYPE_HTBL ) { hashrec = item; level++; if( level >= keylen ) { - log_error ("hashtable `%s' has invalid indirections\n", db_name); - return GPG_ERR_TRUSTDB; + log_error("hashtable has invalid indirections\n"); + return G10ERR_TRUSTDB; } goto next_level; } @@ -1056,7 +1049,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 ); if( rc ) { log_error( "lookup_hashtable: read item failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } if( (*cmpfnc)( cmpdata, &tmp ) ) { @@ -1069,7 +1062,7 @@ lookup_hashtable( ulong table, const byte *key, size_t keylen, rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST ); if( rc ) { log_error( "lookup_hashtable: read hlst failed: %s\n", - gpg_strerror (rc) ); + g10_errstr(rc) ); return rc; } } @@ -1164,7 +1157,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) { byte readbuf[TRUST_RECORD_LEN]; const byte *buf, *p; - int rc = 0; + gpg_error_t err = 0; int n, i; if( db_fd == -1 ) @@ -1172,19 +1165,19 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) buf = get_record_from_cache( recnum ); if( !buf ) { if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { - rc = gpg_error_from_errno (errno); + err = gpg_error_from_errno (errno); log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) ); - return rc; + return err; } n = read( db_fd, readbuf, TRUST_RECORD_LEN); if( !n ) { return -1; /* eof */ } else if( n != TRUST_RECORD_LEN ) { - rc = gpg_error_from_errno (errno); + err = gpg_error_from_errno (errno); log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) ); - return rc; + return err; } buf = readbuf; } @@ -1195,7 +1188,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) if( expected && rec->rectype != expected ) { log_error("%lu: read expected rec type %d, got %d\n", recnum, expected, rec->rectype ); - return GPG_ERR_TRUSTDB; + return gpg_error (GPG_ERR_TRUSTDB); } p++; /* skip reserved byte */ switch( rec->rectype ) { @@ -1204,7 +1197,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) case RECTYPE_VER: /* version record */ if( memcmp(buf+1, "gpg", 3 ) ) { log_error( _("%s: not a trustdb file\n"), db_name ); - rc = GPG_ERR_TRUSTDB; + err = gpg_error (GPG_ERR_TRUSTDB); } p += 2; /* skip "gpg" */ rec->r.ver.version = *p++; @@ -1223,12 +1216,12 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) if( recnum ) { log_error( _("%s: version record with recnum %lu\n"), db_name, (ulong)recnum ); - rc = GPG_ERR_TRUSTDB; + err = gpg_error (GPG_ERR_TRUSTDB); } else if( rec->r.ver.version != 3 ) { log_error( _("%s: invalid file version %d\n"), db_name, rec->r.ver.version ); - rc = GPG_ERR_TRUSTDB; + err = gpg_error (GPG_ERR_TRUSTDB); } break; case RECTYPE_FREE: @@ -1263,11 +1256,11 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) default: log_error( "%s: invalid record type %d at recnum %lu\n", db_name, rec->rectype, (ulong)recnum ); - rc = GPG_ERR_TRUSTDB; + err = gpg_error (GPG_ERR_TRUSTDB); break; } - return rc; + return err; } /**************** @@ -1379,7 +1372,7 @@ tdbio_delete_record( ulong recnum ) rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); rec.recnum = recnum; rec.rectype = RECTYPE_FREE; @@ -1406,13 +1399,13 @@ tdbio_new_recnum() rc = tdbio_read_record( 0, &vr, RECTYPE_VER ); if( rc ) log_fatal( _("%s: error reading version record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); if( vr.r.ver.firstfree ) { recnum = vr.r.ver.firstfree; rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE ); if( rc ) { log_error( _("%s: error reading free record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); return rc; } /* update dir record */ @@ -1420,7 +1413,7 @@ tdbio_new_recnum() rc = tdbio_write_record( &vr ); if( rc ) { log_error( _("%s: error writing dir record: %s\n"), - db_name, gpg_strerror (rc) ); + db_name, g10_errstr(rc) ); return rc; } /*zero out the new record */ @@ -1430,7 +1423,7 @@ tdbio_new_recnum() rc = tdbio_write_record( &rec ); if( rc ) log_fatal(_("%s: failed to zero a record: %s\n"), - db_name, gpg_strerror (rc)); + db_name, g10_errstr(rc)); } else { /* not found, append a new record */ offset = lseek( db_fd, 0, SEEK_END ); @@ -1460,7 +1453,7 @@ tdbio_new_recnum() if( rc ) log_fatal(_("%s: failed to append a record: %s\n"), - db_name, gpg_strerror (rc)); + db_name, g10_errstr(rc)); } return recnum ; } @@ -1508,129 +1501,3 @@ tdbio_invalid(void) g10_exit(2); } -/* - * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2) - * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs - * only to scan the tdb and insert new the new trust records. The old ones are - * obsolte from now on - */ -static void -migrate_from_v2 () -{ - TRUSTREC rec; - int i, n; - struct { - ulong keyrecno; - byte ot; - byte okay; - byte fpr[20]; - } *ottable; - int ottable_size, ottable_used; - byte oldbuf[40]; - ulong recno; - int rc, count; - - ottable_size = 5; - ottable = xmalloc (ottable_size * sizeof *ottable); - ottable_used = 0; - - /* We have some restrictions here. We can't use the version record - * and we can't use any of the old hashtables because we dropped the - * code. So we first collect all ownertrusts and then use a second - * pass fo find the associated keys. We have to do this all without using - * the regular record read functions. - */ - - /* get all the ownertrusts */ - if (lseek (db_fd, 0, SEEK_SET ) == -1 ) - log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); - for (recno=0;;recno++) - { - do - n = read (db_fd, oldbuf, 40); - while (n==-1 && errno == EINTR); - if (!n) - break; /* eof */ - if (n != 40) - log_fatal ("migrate_vfrom_v2: read error or short read\n"); - - if (*oldbuf != 2) - continue; - - /* v2 dir record */ - if (ottable_used == ottable_size) - { - ottable_size += 1000; - ottable = xrealloc (ottable, ottable_size * sizeof *ottable); - } - ottable[ottable_used].keyrecno = buftoulong (oldbuf+6); - ottable[ottable_used].ot = oldbuf[18]; - ottable[ottable_used].okay = 0; - memset (ottable[ottable_used].fpr,0, 20); - if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot) - ottable_used++; - } - log_info ("found %d ownertrust records\n", ottable_used); - - /* Read again and find the fingerprints */ - if (lseek (db_fd, 0, SEEK_SET ) == -1 ) - log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno)); - for (recno=0;;recno++) - { - do - n = read (db_fd, oldbuf, 40); - while (n==-1 && errno == EINTR); - if (!n) - break; /* eof */ - if (n != 40) - log_fatal ("migrate_from_v2: read error or short read\n"); - - if (*oldbuf != 3) - continue; - - /* v2 key record */ - for (i=0; i < ottable_used; i++) - { - if (ottable[i].keyrecno == recno) - { - memcpy (ottable[i].fpr, oldbuf+20, 20); - ottable[i].okay = 1; - break; - } - } - } - - /* got everything - create the v3 trustdb */ - if (ftruncate (db_fd, 0)) - log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) ); - if (create_version_record ()) - log_fatal ("failed to recreate version record of `%s'\n", db_name); - - /* access the hash table, so it is store just after the version record, - * this is not needed put a dump is more pretty */ - get_trusthashrec (); - - /* And insert the old ownertrust values */ - count = 0; - for (i=0; i < ottable_used; i++) - { - if (!ottable[i].okay) - continue; - - memset (&rec, 0, sizeof rec); - rec.recnum = tdbio_new_recnum (); - rec.rectype = RECTYPE_TRUST; - memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20); - rec.r.trust.ownertrust = ottable[i].ot; - if (tdbio_write_record (&rec)) - log_fatal ("failed to write trust record of `%s'\n", db_name); - count++; - } - - revalidation_mark (); - rc = tdbio_sync (); - if (rc) - log_fatal ("failed to sync `%s'\n", db_name); - log_info ("migrated %d version 2 ownertrusts\n", count); - xfree (ottable); -} diff --git a/g10/tdbio.h b/g10/tdbio.h index 708e06d2b..80a70d9f4 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_TDBIO_H diff --git a/g10/textfilter.c b/g10/textfilter.c index a3ea4b138..daa57de0a 100644 --- a/g10/textfilter.c +++ b/g10/textfilter.c @@ -1,5 +1,5 @@ /* textfilter.c - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -28,11 +29,11 @@ #include "gpg.h" #include "errors.h" #include "iobuf.h" -#include "memory.h" #include "util.h" #include "filter.h" #include "i18n.h" #include "options.h" +#include "status.h" #ifdef HAVE_DOSISH_SYSTEM #define LF "\r\n" @@ -62,17 +63,9 @@ len_without_trailing_chars( byte *line, unsigned len, const char *trimchars ) return mark? (mark - line) : len; } -unsigned -len_without_trailing_ws( byte *line, unsigned len ) -{ - return len_without_trailing_chars( line, len, " \t\r\n" ); -} - - - static int -standard( text_filter_context_t *tfx, iobuf_t a, +standard( text_filter_context_t *tfx, IOBUF a, byte *buf, size_t size, size_t *ret_len) { int rc=0; @@ -102,7 +95,30 @@ standard( text_filter_context_t *tfx, iobuf_t a, break; } lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n'; - tfx->buffer_len = trim_trailing_ws( tfx->buffer, tfx->buffer_len ); + + /* The story behind this is that 2440 says that textmode + hashes should canonicalize line endings to CRLF and remove + spaces and tabs. 2440bis-12 says to just canonicalize to + CRLF. 1.4.0 was released using the bis-12 behavior, but it + was discovered that many mail clients do not canonicalize + PGP/MIME signature text appropriately (and were relying on + GnuPG to handle trailing spaces). So, we default to the + 2440 behavior, but use the 2440bis-12 behavior if the user + specifies --no-rfc2440-text. The default will be changed + at some point in the future when the mail clients have been + upgraded. Aside from PGP/MIME and broken mail clients, + this makes no difference to any signatures in the real + world except for a textmode detached signature. PGP always + used the 2440bis-12 behavior (ignoring 2440 itself), so + this actually makes us compatible with PGP textmode + detached signatures for the first time. */ + if(opt.rfc2440_text) + tfx->buffer_len=trim_trailing_chars(tfx->buffer,tfx->buffer_len, + " \t\r\n"); + else + tfx->buffer_len=trim_trailing_chars(tfx->buffer,tfx->buffer_len, + "\r\n"); + if( lf_seen ) { tfx->buffer[tfx->buffer_len++] = '\r'; tfx->buffer[tfx->buffer_len++] = '\n'; @@ -113,15 +129,13 @@ standard( text_filter_context_t *tfx, iobuf_t a, } - - /**************** * The filter is used to make canonical text: Lines are terminated by * CR, LF, trailing white spaces are removed. */ int text_filter( void *opaque, int control, - iobuf_t a, byte *buf, size_t *ret_len) + IOBUF a, byte *buf, size_t *ret_len) { size_t size = *ret_len; text_filter_context_t *tfx = opaque; @@ -134,7 +148,7 @@ text_filter( void *opaque, int control, if( tfx->truncated ) log_error(_("can't handle text lines longer than %d characters\n"), MAX_LINELEN ); - xfree ( tfx->buffer ); + xfree( tfx->buffer ); tfx->buffer = NULL; } else if( control == IOBUFCTRL_DESC ) @@ -148,13 +162,13 @@ text_filter( void *opaque, int control, * md is updated as required by rfc2440 */ int -copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md, +copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md, int escape_dash, int escape_from, int pgp2mode ) { - unsigned maxlen; + unsigned int maxlen; byte *buffer = NULL; /* malloced buffer */ - unsigned bufsize; /* and size of this buffer */ - unsigned n; + unsigned int bufsize; /* and size of this buffer */ + unsigned int n; int truncated = 0; int pending_lf = 0; @@ -164,6 +178,8 @@ copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md, if( !escape_dash ) escape_from = 0; + write_status (STATUS_BEGIN_SIGNING); + for(;;) { maxlen = MAX_LINELEN; n = iobuf_read_line( inp, &buffer, &bufsize, &maxlen ); @@ -176,15 +192,16 @@ copy_clearsig_text( iobuf_t out, iobuf_t inp, MD_HANDLE md, /* update the message digest */ if( escape_dash ) { if( pending_lf ) { - gcry_md_putc( md, '\r' ); - gcry_md_putc( md, '\n' ); + gcry_md_putc ( md, '\r' ); + gcry_md_putc ( md, '\n' ); } - gcry_md_write( md, buffer, - len_without_trailing_chars( buffer, n, - pgp2mode? " \r\n":" \t\r\n")); + gcry_md_write ( md, buffer, + len_without_trailing_chars (buffer, n, + pgp2mode? + " \r\n":" \t\r\n")); } else - gcry_md_write( md, buffer, n ); + gcry_md_write ( md, buffer, n ); pending_lf = buffer[n-1] == '\n'; /* write the output */ diff --git a/g10/trustdb.c b/g10/trustdb.c index b3a2b369e..573c12903 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1,6 +1,6 @@ /* trustdb.c - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -27,7 +28,7 @@ #ifndef DISABLE_REGEX #include <sys/types.h> -#ifdef USE_GNU_REGEX +#ifdef USE_INTERNAL_REGEX #include "_regex.h" #else #include <regex.h> @@ -38,7 +39,6 @@ #include "errors.h" #include "iobuf.h" #include "keydb.h" -#include "memory.h" #include "util.h" #include "options.h" #include "packet.h" @@ -99,7 +99,7 @@ new_key_item (void) { struct key_item *k; - k = xcalloc (1,sizeof *k); + k = xmalloc_clear (sizeof *k); return k; } @@ -129,7 +129,7 @@ new_key_hash_table (void) { struct key_item **tbl; - tbl = xcalloc (1,1024 * sizeof *tbl); + tbl = xmalloc_clear (1024 * sizeof *tbl); return tbl; } @@ -206,23 +206,31 @@ release_key_array ( struct key_array *keys ) * FIXME: Should be replaced by a function to add those keys to the trustdb. */ void -register_trusted_key( const char *string ) +register_trusted_keyid(u32 *keyid) { - KEYDB_SEARCH_DESC desc; struct key_item *k; - if (classify_user_id (string, &desc) != KEYDB_SEARCH_MODE_LONG_KID ) { - log_error(_("`%s' is not a valid long keyID\n"), string ); - return; - } - k = new_key_item (); - k->kid[0] = desc.u.kid[0]; - k->kid[1] = desc.u.kid[1]; + k->kid[0] = keyid[0]; + k->kid[1] = keyid[1]; k->next = user_utk_list; user_utk_list = k; } +void +register_trusted_key( const char *string ) +{ + KEYDB_SEARCH_DESC desc; + + if (classify_user_id (string, &desc) != KEYDB_SEARCH_MODE_LONG_KID ) + { + log_error(_("`%s' is not a valid long keyID\n"), string ); + return; + } + + register_trusted_keyid(desc.u.kid); +} + /* * Helper to add a key to the global list of ultimately trusted keys. * Retruns: true = inserted, false = already in in list. @@ -247,7 +255,7 @@ add_utk (u32 *kid) k->next = utk_list; utk_list = k; if( opt.verbose > 1 ) - log_info(_("key %08lX: accepted as trusted key\n"), (ulong)kid[1]); + log_info(_("key %s: accepted as trusted key\n"), keystr(kid)); return 1; } @@ -285,8 +293,8 @@ verify_own_keys(void) fprlen = (!fpr[16] && !fpr[17] && !fpr[18] && !fpr[19])? 16:20; keyid_from_fingerprint (fpr, fprlen, kid); if (!add_utk (kid)) - log_info(_("key %08lX occurs more than once in the trustdb\n"), - (ulong)kid[1]); + log_info(_("key %s occurs more than once in the trustdb\n"), + keystr(kid)); } } @@ -299,22 +307,21 @@ verify_own_keys(void) memset (&pk, 0, sizeof pk); rc = get_pubkey (&pk, k->kid); - if (rc) { - log_info(_("key %08lX: no public key for trusted key - skipped\n"), - (ulong)k->kid[1] ); - } - else { - update_ownertrust (&pk, - ((get_ownertrust (&pk) & ~TRUST_MASK) - | TRUST_ULTIMATE )); - release_public_key_parts (&pk); - } - log_info (_("key %08lX marked as ultimately trusted\n"), - (ulong)k->kid[1]); + if (rc) + log_info(_("key %s: no public key for trusted key - skipped\n"), + keystr(k->kid)); + else + { + update_ownertrust (&pk, + ((get_ownertrust (&pk) & ~TRUST_MASK) + | TRUST_ULTIMATE )); + release_public_key_parts (&pk); + } + + log_info (_("key %s marked as ultimately trusted\n"),keystr(k->kid)); } } - /* release the helper table table */ release_key_items (user_utk_list); user_utk_list = NULL; @@ -336,7 +343,7 @@ read_record (ulong recno, TRUSTREC *rec, int rectype ) if (rc) { log_error(_("trust record %lu, req type %d: read failed: %s\n"), - recno, rec->rectype, gpg_strerror (rc) ); + recno, rec->rectype, g10_errstr(rc) ); tdbio_invalid(); } if (rectype != rec->rectype) @@ -357,7 +364,7 @@ write_record (TRUSTREC *rec) if (rc) { log_error(_("trust record %lu, type %d: write failed: %s\n"), - rec->recnum, rec->rectype, gpg_strerror (rc) ); + rec->recnum, rec->rectype, g10_errstr(rc) ); tdbio_invalid(); } } @@ -371,7 +378,7 @@ do_sync(void) int rc = tdbio_sync (); if(rc) { - log_error (_("trustdb: sync failed: %s\n"), gpg_strerror (rc) ); + log_error (_("trustdb: sync failed: %s\n"), g10_errstr(rc) ); g10_exit(2); } } @@ -381,10 +388,12 @@ trust_model_string(void) { switch(opt.trust_model) { - case TM_PGP: return "PGP"; - case TM_CLASSIC: return "classic"; - case TM_ALWAYS: return "always"; - default: return "unknown"; + case TM_CLASSIC: return "classic"; + case TM_PGP: return "PGP"; + case TM_EXTERNAL: return "external"; + case TM_ALWAYS: return "always"; + case TM_DIRECT: return "direct"; + default: return "unknown"; } } @@ -400,14 +409,13 @@ setup_trustdb( int level, const char *dbname ) if( trustdb_args.init ) return 0; trustdb_args.level = level; - trustdb_args.dbname = dbname? xstrdup (dbname): NULL; + trustdb_args.dbname = dbname? xstrdup(dbname): NULL; return 0; } void init_trustdb() { - int rc=0; int level = trustdb_args.level; const char* dbname = trustdb_args.dbname; @@ -416,26 +424,14 @@ init_trustdb() trustdb_args.init = 1; - if ( !level || level==1) + if(level==0 || level==1) { - rc = tdbio_set_dbname( dbname, !!level ); - if( !rc ) - { - if( !level ) - return; - - /* verify that our own keys are in the trustDB - * or move them to the trustdb. */ - verify_own_keys(); - - /* should we check whether there is no other ultimately trusted - * key in the database? */ - } + int rc = tdbio_set_dbname( dbname, !!level ); + if( rc ) + log_fatal("can't init trustdb: %s\n", g10_errstr(rc) ); } else BUG(); - if( rc ) - log_fatal("can't init trustdb: %s\n", gpg_strerror (rc) ); if(opt.trust_model==TM_AUTO) { @@ -444,7 +440,9 @@ init_trustdb() opt.trust_model=tdbio_read_model(); /* Sanity check this ;) */ - if(opt.trust_model!=TM_PGP && opt.trust_model!=TM_CLASSIC) + if(opt.trust_model!=TM_CLASSIC + && opt.trust_model!=TM_PGP + && opt.trust_model!=TM_EXTERNAL) { log_info(_("unable to use unknown trust model (%d) - " "assuming %s trust model\n"),opt.trust_model,"PGP"); @@ -455,14 +453,19 @@ init_trustdb() log_info(_("using %s trust model\n"),trust_model_string()); } - if((opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) - && !tdbio_db_matches_options()) - pending_check_trustdb=1; -} + if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) + { + /* Verify the list of ultimately trusted keys and move the + --trusted-keys list there as well. */ + if(level==1) + verify_own_keys(); + if(!tdbio_db_matches_options()) + pending_check_trustdb=1; + } +} - /*********************************************** ************* Print helpers **************** ***********************************************/ @@ -487,6 +490,37 @@ trust_letter (unsigned int value) } } +/* NOTE TO TRANSLATOR: these strings are similar to those in + trust_value_to_string(), but are a fixed length. This is needed to + make attractive information listings where columns line up + properly. The value "10" should be the length of the strings you + choose to translate to. This is the length in printable columns. + It gets passed to atoi() so everything after the number is + essentially a comment and need not be translated. Either key and + uid are both NULL, or neither are NULL. */ +const char * +uid_trust_string_fixed(PKT_public_key *key,PKT_user_id *uid) +{ + if(!key && !uid) + return _("10 translator see trustdb.c:uid_trust_string_fixed"); + else if(uid->is_revoked || (key && key->is_revoked)) + return _("[ revoked]"); + else if(uid->is_expired) + return _("[ expired]"); + else if(key) + switch(get_validity(key,uid)&TRUST_MASK) + { + case TRUST_UNKNOWN: return _("[ unknown]"); + case TRUST_EXPIRED: return _("[ expired]"); + case TRUST_UNDEFINED: return _("[ undef ]"); + case TRUST_MARGINAL: return _("[marginal]"); + case TRUST_FULLY: return _("[ full ]"); + case TRUST_ULTIMATE: return _("[ultimate]"); + } + + return "err"; +} + /* The strings here are similar to those in pkclist.c:do_edit_ownertrust() */ const char * @@ -555,7 +589,7 @@ check_trustdb () validate_keys (0); } else - log_info (_("no need for a trustdb check with \"%s\" trust model\n"), + log_info (_("no need for a trustdb check with `%s' trust model\n"), trust_model_string()); } @@ -570,7 +604,7 @@ update_trustdb() if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC) validate_keys (1); else - log_info (_("no need for a trustdb update with \"%s\" trust model\n"), + log_info (_("no need for a trustdb update with `%s' trust model\n"), trust_model_string()); } @@ -591,6 +625,20 @@ trustdb_pending_check(void) return pending_check_trustdb; } +/* If the trustdb is dirty, and we're interactive, update it. + Otherwise, check it unless no-auto-check-trustdb is set. */ +void +trustdb_check_or_update(void) +{ + if(trustdb_pending_check()) + { + if(opt.interactive) + update_trustdb(); + else if(!opt.no_auto_check_trustdb) + check_trustdb(); + } +} + void read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, byte *marginals,byte *completes,byte *cert_depth) @@ -615,8 +663,6 @@ read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck, *cert_depth=opts.r.ver.cert_depth; } - - /*********************************************** *********** Ownertrust et al. **************** ***********************************************/ @@ -633,7 +679,7 @@ read_trust_record (PKT_public_key *pk, TRUSTREC *rec) if (rc) { log_error ("trustdb: searching trust record failed: %s\n", - gpg_strerror (rc)); + g10_errstr (rc)); return rc; } @@ -641,7 +687,7 @@ read_trust_record (PKT_public_key *pk, TRUSTREC *rec) { log_error ("trustdb: record %lu is not a trust record\n", rec->recnum); - return GPG_ERR_TRUSTDB; + return G10ERR_TRUSTDB; } return 0; @@ -786,12 +832,11 @@ update_min_ownertrust (u32 *kid, unsigned int new_trust ) TRUSTREC rec; int rc; - pk = xcalloc (1,sizeof *pk); + pk = xmalloc_clear (sizeof *pk); rc = get_pubkey (pk, kid); if (rc) { - log_error (_("public key %08lX not found: %s\n"), - (ulong)kid[1], gpg_strerror (rc) ); + log_error(_("public key %s not found: %s\n"),keystr(kid),g10_errstr(rc)); return; } @@ -799,8 +844,9 @@ update_min_ownertrust (u32 *kid, unsigned int new_trust ) if (!rc) { if (DBG_TRUST) - log_debug ("key %08lX: update min_ownertrust from %u to %u\n", - (ulong)kid[1],(unsigned int)rec.r.trust.min_ownertrust, + log_debug ("key %08lX%08lX: update min_ownertrust from %u to %u\n", + (ulong)kid[0],(ulong)kid[1], + (unsigned int)rec.r.trust.min_ownertrust, new_trust ); if (rec.r.trust.min_ownertrust != new_trust) { @@ -927,49 +973,6 @@ update_validity (PKT_public_key *pk, PKT_user_id *uid, } -/* reset validity for all user IDs. Caller must sync. */ -static int -clear_validity (PKT_public_key *pk) -{ - TRUSTREC trec, vrec; - int rc; - ulong recno; - int any = 0; - - rc = read_trust_record (pk, &trec); - if (rc && rc != -1) - { - tdbio_invalid (); - return 0; - } - if (rc == -1) /* no record yet - no need to clear it then ;-) */ - return 0; - - /* Clear minimum ownertrust, if any */ - if(trec.r.trust.min_ownertrust) - { - trec.r.trust.min_ownertrust=0; - write_record(&trec); - } - - recno = trec.r.trust.validlist; - while (recno) - { - read_record (recno, &vrec, RECTYPE_VALID); - if ((vrec.r.valid.validity & TRUST_MASK) - || vrec.r.valid.marginal_count || vrec.r.valid.full_count) - { - vrec.r.valid.validity &= ~TRUST_MASK; - vrec.r.valid.marginal_count = vrec.r.valid.full_count = 0; - write_record (&vrec); - any = 1; - } - recno = vrec.r.valid.next; - } - - return any; -} - /*********************************************** ********* Query trustdb values ************** ***********************************************/ @@ -1010,24 +1013,10 @@ cache_disabled_value(PKT_public_key *pk) return disabled; } -/* - * Return the validity information for PK. If the namehash is not - * NULL, the validity of the corresponsing user ID is returned, - * otherwise, a reasonable value for the entire key is returned. - */ -unsigned int -get_validity (PKT_public_key *pk, PKT_user_id *uid) +void +check_trustdb_stale(void) { - static int did_nextcheck; - TRUSTREC trec, vrec; - int rc; - ulong recno; - unsigned int validity; - u32 kid[2]; - PKT_public_key *main_pk; - - if(uid) - namehash_from_uid(uid); + static int did_nextcheck=0; init_trustdb (); if (!did_nextcheck @@ -1051,16 +1040,40 @@ get_validity (PKT_public_key *pk, PKT_user_id *uid) } } } +} + +/* + * Return the validity information for PK. If the namehash is not + * NULL, the validity of the corresponsing user ID is returned, + * otherwise, a reasonable value for the entire key is returned. + */ +unsigned int +get_validity (PKT_public_key *pk, PKT_user_id *uid) +{ + TRUSTREC trec, vrec; + int rc; + ulong recno; + unsigned int validity; + u32 kid[2]; + PKT_public_key *main_pk; + + if(uid) + namehash_from_uid(uid); + + init_trustdb (); + check_trustdb_stale(); keyid_from_pk (pk, kid); if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1]) { /* this is a subkey - get the mainkey */ - main_pk = xcalloc (1,sizeof *main_pk); + main_pk = xmalloc_clear (sizeof *main_pk); rc = get_pubkey (main_pk, pk->main_keyid); if (rc) { - log_error ("error getting main key %08lX of subkey %08lX: %s\n", - (ulong)pk->main_keyid[1], (ulong)kid[1], gpg_strerror (rc)); + char *tempkeystr=xstrdup(keystr(pk->main_keyid)); + log_error ("error getting main key %s of subkey %s: %s\n", + tempkeystr, keystr(kid), g10_errstr(rc)); + xfree(tempkeystr); validity = TRUST_UNKNOWN; goto leave; } @@ -1068,6 +1081,14 @@ get_validity (PKT_public_key *pk, PKT_user_id *uid) else main_pk = pk; + if(opt.trust_model==TM_DIRECT) + { + /* Note that this happens BEFORE any user ID stuff is checked. + The direct trust model applies to keys as a whole. */ + validity=get_ownertrust(main_pk); + goto leave; + } + rc = read_trust_record (main_pk, &trec); if (rc && rc != -1) { @@ -1249,20 +1270,19 @@ ask_ownertrust (u32 *kid,int minimum) int rc; int ot; - pk = xcalloc (1,sizeof *pk); + pk = xmalloc_clear (sizeof *pk); rc = get_pubkey (pk, kid); if (rc) { - log_error (_("public key %08lX not found: %s\n"), - (ulong)kid[1], gpg_strerror (rc) ); + log_error (_("public key %s not found: %s\n"), + keystr(kid), g10_errstr(rc) ); return TRUST_UNKNOWN; } if(opt.force_ownertrust) { - log_info("force trust for key %08lX%08lX to %s\n", - (ulong)kid[0],(ulong)kid[1], - trust_value_to_string(opt.force_ownertrust)); + log_info("force trust for key %s to %s\n", + keystr(kid),trust_value_to_string(opt.force_ownertrust)); update_ownertrust(pk,opt.force_ownertrust); ot=opt.force_ownertrust; } @@ -1390,8 +1410,9 @@ is_in_klist (struct key_item *k, PKT_signature *sig) * To do this, we first revmove all signatures which are not valid and * from the remain ones we look for the latest one. If this is not a * certification revocation signature we mark the signature by setting - * node flag bit 8. Note that flag bits 9 and 10 are used for internal - * purposes. + * node flag bit 8. Revocations are marked with flag 11, and sigs + * from unavailable keys are marked with flag 12. Note that flag bits + * 9 and 10 are used for internal purposes. */ static void mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, @@ -1404,31 +1425,44 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, /* first check all signatures */ for (node=uidnode->next; node; node = node->next) { - node->flag &= ~(1<<8 | 1<<9 | 1<<10); + int rc; + + node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12); if (node->pkt->pkttype == PKT_USER_ID || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) break; /* ready */ if (node->pkt->pkttype != PKT_SIGNATURE) continue; - sig = node->pkt->pkt.signature; - if (sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1]) - continue; /* ignore self-signatures */ + if (main_kid + && sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1]) + continue; /* ignore self-signatures if we pass in a main_kid */ if (!IS_UID_SIG(sig) && !IS_UID_REV(sig)) continue; /* we only look at these signature classes */ - if (!is_in_klist (klist, sig)) + if(sig->sig_class>=0x11 && sig->sig_class<=0x13 && + sig->sig_class-0x10<opt.min_cert_level) + continue; /* treat anything under our min_cert_level as an + invalid signature */ + if (klist && !is_in_klist (klist, sig)) continue; /* no need to check it then */ - if (check_key_signature (keyblock, node, NULL)) - continue; /* ignore invalid signatures */ + if ((rc=check_key_signature (keyblock, node, NULL))) + { + /* we ignore anything that won't verify, but tag the + no_pubkey case */ + if(rc==G10ERR_NO_PUBKEY) + node->flag |= 1<<12; + continue; + } node->flag |= 1<<9; } /* reset the remaining flags */ for (; node; node = node->next) - node->flag &= ~(1<<8 | 1<<9 | 1 << 10); + node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12); /* kbnode flag usage: bit 9 is here set for signatures to consider, * bit 10 will be set by the loop to keep track of keyIDs already - * processed, bit 8 will be set for the usable signatures */ + * processed, bit 8 will be set for the usable signatures, and bit + * 11 will be set for usable revocations. */ /* for each cert figure out the latest valid one */ for (node=uidnode->next; node; node = node->next) @@ -1436,7 +1470,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, KBNODE n, signode; u32 kid[2]; u32 sigdate; - + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) break; if ( !(node->flag & (1<<9)) ) @@ -1448,6 +1482,8 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, signode = node; sigdate = sig->timestamp; kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1]; + + /* Now find the latest and greatest signature */ for (n=uidnode->next; n; n = n->next) { if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY) @@ -1510,6 +1546,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, sigdate = sig->timestamp; } } + sig = signode->pkt->pkt.signature; if (IS_UID_SIG (sig)) { /* this seems to be a usable one which is not revoked. @@ -1528,11 +1565,190 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, if (expire==0 || expire > curtime ) { signode->flag |= (1<<8); /* yeah, found a good cert */ - if (expire && expire < *next_expire) + if (next_expire && expire && expire < *next_expire) *next_expire = expire; } } + else + signode->flag |= (1<<11); + } +} + +static int +clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy,int self_only) +{ + int deleted=0; + KBNODE node; + u32 keyid[2]; + + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + + keyid_from_pk(keyblock->pkt->pkt.public_key,keyid); + + /* Passing in a 0 for current time here means that we'll never weed + out an expired sig. This is correct behavior since we want to + keep the most recent expired sig in a series. */ + mark_usable_uid_certs(keyblock,uidnode,NULL,NULL,0,NULL); + + /* What we want to do here is remove signatures that are not + considered as part of the trust calculations. Thus, all invalid + signatures are out, as are any signatures that aren't the last of + a series of uid sigs or revocations It breaks down like this: + coming out of mark_usable_uid_certs, if a sig is unflagged, it is + not even a candidate. If a sig has flag 9 or 10, that means it + was selected as a candidate and vetted. If a sig has flag 8 it + is a usable signature. If a sig has flag 11 it is a usable + revocation. If a sig has flag 12 it was issued by an unavailable + key. "Usable" here means the most recent valid + signature/revocation in a series from a particular signer. + + Delete everything that isn't a usable uid sig (which might be + expired), a usable revocation, or a sig from an unavailable + key. */ + + for(node=uidnode->next; + node && node->pkt->pkttype==PKT_SIGNATURE; + node=node->next) + { + int keep=self_only?(node->pkt->pkt.signature->keyid[0]==keyid[0] + && node->pkt->pkt.signature->keyid[1]==keyid[1]):1; + + /* Keep usable uid sigs ... */ + if((node->flag & (1<<8)) && keep) + continue; + + /* ... and usable revocations... */ + if((node->flag & (1<<11)) && keep) + continue; + + /* ... and sigs from unavailable keys. */ + /* disabled for now since more people seem to want sigs from + unavailable keys removed altogether. */ + /* + if(node->flag & (1<<12)) + continue; + */ + + /* Everything else we delete */ + + /* At this point, if 12 is set, the signing key was unavailable. + If 9 or 10 is set, it's superceded. Otherwise, it's + invalid. */ + + if(noisy) + log_info("removing signature from key %s on user ID \"%s\": %s\n", + keystr(node->pkt->pkt.signature->keyid), + uidnode->pkt->pkt.user_id->name, + node->flag&(1<<12)?"key unavailable": + node->flag&(1<<9)?"signature superceded":"invalid signature"); + + delete_kbnode(node); + deleted++; + } + + return deleted; +} + +/* This is substantially easier than clean_sigs_from_uid since we just + have to establish if the uid has a valid self-sig, is not revoked, + and is not expired. Note that this does not take into account + whether the uid has a trust path to it - just whether the keyholder + themselves has certified the uid. Returns true if the uid was + compacted. To "compact" a user ID, we simply remove ALL signatures + except the self-sig that caused the user ID to be remove-worthy. + We don't actually remove the user ID packet itself since it might + be ressurected in a later merge. Note that this function requires + that the caller has already done a merge_keys_and_selfsig(). + + TODO: change the import code to allow importing a uid with only a + revocation if the uid already exists on the keyring. */ + +static int +clean_uid_from_key(KBNODE keyblock,KBNODE uidnode,int noisy) +{ + KBNODE node; + PKT_user_id *uid=uidnode->pkt->pkt.user_id; + int deleted=0; + + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + assert(uidnode->pkt->pkttype==PKT_USER_ID); + + /* Skip valid user IDs, compacted user IDs, and non-self-signed user + IDs if --allow-non-selfsigned-uid is set. */ + if(uid->created || uid->flags.compacted + || (!uid->is_expired && !uid->is_revoked + && opt.allow_non_selfsigned_uid)) + return 0; + + for(node=uidnode->next; + node && node->pkt->pkttype==PKT_SIGNATURE; + node=node->next) + if(!node->pkt->pkt.signature->flags.chosen_selfsig) + { + delete_kbnode(node); + deleted=1; + uidnode->pkt->pkt.user_id->flags.compacted=1; + } + + if(noisy) + { + const char *reason; + char *user=utf8_to_native(uid->name,uid->len,0); + + if(uid->is_revoked) + reason=_("revoked"); + else if(uid->is_expired) + reason=_("expired"); + else + reason=_("invalid"); + + log_info("compacting user ID \"%s\" on key %s: %s\n", + user,keystr_from_pk(keyblock->pkt->pkt.public_key), + reason); + + xfree(user); } + + return deleted; +} + +/* Needs to be called after a merge_keys_and_selfsig() */ +void +clean_one_uid(KBNODE keyblock,KBNODE uidnode,int noisy,int self_only, + int *uids_cleaned,int *sigs_cleaned) +{ + int dummy; + + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + assert(uidnode->pkt->pkttype==PKT_USER_ID); + + if(!uids_cleaned) + uids_cleaned=&dummy; + + if(!sigs_cleaned) + sigs_cleaned=&dummy; + + /* Do clean_uid_from_key first since if it fires off, we don't + have to bother with the other */ + *uids_cleaned+=clean_uid_from_key(keyblock,uidnode,noisy); + if(!uidnode->pkt->pkt.user_id->flags.compacted) + *sigs_cleaned+=clean_sigs_from_uid(keyblock,uidnode,noisy,self_only); +} + +void +clean_key(KBNODE keyblock,int noisy,int self_only, + int *uids_cleaned,int *sigs_cleaned) +{ + KBNODE uidnode; + + merge_keys_and_selfsig(keyblock); + + for(uidnode=keyblock->next; + uidnode && uidnode->pkt->pkttype!=PKT_PUBLIC_SUBKEY; + uidnode=uidnode->next) + if(uidnode->pkt->pkttype==PKT_USER_ID) + clean_one_uid(keyblock,uidnode,noisy,self_only, + uids_cleaned,sigs_cleaned); } /* Used by validate_one_keyblock to confirm a regexp within a trust @@ -1559,7 +1775,7 @@ check_regexp(const char *expr,const char *string) regfree(&pat); if(DBG_TRUST) - log_debug("regexp \"%s\" on \"%s\": %s\n",expr,string,ret==0?"YES":"NO"); + log_debug("regexp `%s' on `%s': %s\n",expr,string,ret==0?"YES":"NO"); return (ret==0); #endif @@ -1717,7 +1933,7 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist, static int -search_skipfnc (void *opaque, u32 *kid) +search_skipfnc (void *opaque, u32 *kid, PKT_user_id *dummy) { return test_key_hash_table ((KeyHashTable)opaque, kid); } @@ -1747,7 +1963,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, rc = keydb_search_reset (hd); if (rc) { - log_error ("keydb_search_reset failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc)); xfree (keys); return NULL; } @@ -1764,7 +1980,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, } if (rc) { - log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); xfree (keys); return NULL; } @@ -1777,7 +1993,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, rc = keydb_get_keyblock (hd, &keyblock); if (rc) { - log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); xfree (keys); return NULL; } @@ -1833,7 +2049,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, while ( !(rc = keydb_search (hd, &desc, 1)) ); if (rc && rc != -1) { - log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); + log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); xfree (keys); return NULL; } @@ -1844,56 +2060,40 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust, /* Caller must sync */ static void -reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude) +reset_trust_records(void) { - int rc; - KBNODE keyblock = NULL; - KEYDB_SEARCH_DESC desc; + TRUSTREC rec; + ulong recnum; int count = 0, nreset = 0; - - rc = keydb_search_reset (hd); - if (rc) - { - log_error ("keydb_search_reset failed: %s\n", gpg_strerror (rc)); - return; - } - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - if(exclude) - { - desc.skipfnc = search_skipfnc; - desc.skipfncvalue = exclude; - } - rc = keydb_search (hd, &desc, 1); - if (rc && rc != -1 ) - log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc)); - else if (!rc) + for (recnum=1; !tdbio_read_record (recnum, &rec, 0); recnum++ ) { - desc.mode = KEYDB_SEARCH_MODE_NEXT; /* change mode */ - do - { - rc = keydb_get_keyblock (hd, &keyblock); - if (rc) - { - log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc)); - break; - } - count++; + if(rec.rectype==RECTYPE_TRUST) + { + count++; + if(rec.r.trust.min_ownertrust) + { + rec.r.trust.min_ownertrust=0; + write_record(&rec); + } + + } + else if(rec.rectype==RECTYPE_VALID + && ((rec.r.valid.validity&TRUST_MASK) + || rec.r.valid.marginal_count + || rec.r.valid.full_count)) + { + rec.r.valid.validity &= ~TRUST_MASK; + rec.r.valid.marginal_count=rec.r.valid.full_count=0; + nreset++; + write_record(&rec); + } - if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY) /* paranoid assertion*/ - { - nreset += clear_validity (keyblock->pkt->pkt.public_key); - release_kbnode (keyblock); - } - } - while ( !(rc = keydb_search (hd, &desc, 1)) ); - if (rc && rc != -1) - log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); } + if (opt.verbose) log_info (_("%d keys processed (%d validity counts cleared)\n"), - count, nreset); + count, nreset); } /* @@ -1932,28 +2132,35 @@ validate_keys (int interactive) KEYDB_HANDLE kdb = NULL; KBNODE node; int depth; - int key_count; int ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate; KeyHashTable stored,used,full_trust; u32 start_time, next_expire; + /* Make sure we have all sigs cached. TODO: This is going to + require some architectual re-thinking, as it is agonizingly slow. + Perhaps combine this with reset_trust_records(), or only check + the caches on keys that are actually involved in the web of + trust. */ + keydb_rebuild_caches(0); + start_time = make_timestamp (); next_expire = 0xffffffff; /* set next expire to the year 2106 */ stored = new_key_hash_table (); used = new_key_hash_table (); full_trust = new_key_hash_table (); + + kdb = keydb_new (0); + reset_trust_records(); + /* Fixme: Instead of always building a UTK list, we could just build it * here when needed */ if (!utk_list) { - log_info (_("no ultimately trusted keys found\n")); + if (!opt.quiet) + log_info (_("no ultimately trusted keys found\n")); goto leave; } - kdb = keydb_new (0); - - reset_trust_records (kdb,NULL); - /* mark all UTKs as used and fully_trusted and set validity to ultimate */ for (k=utk_list; k; k = k->next) @@ -1965,7 +2172,7 @@ validate_keys (int interactive) if (!keyblock) { log_error (_("public key of ultimately" - " trusted key %08lX not found\n"), (ulong)k->kid[1]); + " trusted key %s not found\n"), keystr(k->kid)); continue; } mark_keyblock_seen (used, keyblock); @@ -1992,8 +2199,9 @@ validate_keys (int interactive) for (depth=0; depth < opt.max_cert_depth; depth++) { + int valids=0,key_count; /* See whether we should assign ownertrust values to the keys in - utk_list. */ + klist. */ ot_unknown = ot_undefined = ot_never = 0; ot_marginal = ot_full = ot_ultimate = 0; for (k=klist; k; k = k->next) @@ -2027,9 +2235,9 @@ validate_keys (int interactive) if(k->ownertrust<min) { if(DBG_TRUST) - log_debug("key %08lX: " - "overriding ownertrust \"%s\" with \"%s\"\n", - (ulong)k->kid[1], + log_debug("key %08lX%08lX:" + " overriding ownertrust `%s' with `%s'\n", + (ulong)k->kid[0],(ulong)k->kid[1], trust_value_to_string(k->ownertrust), trust_value_to_string(min)); @@ -2048,6 +2256,8 @@ validate_keys (int interactive) ot_full++; else if (k->ownertrust == TRUST_ULTIMATE) ot_ultimate++; + + valids++; } /* Find all keys which are signed by a key in kdlist */ @@ -2056,7 +2266,7 @@ validate_keys (int interactive) if (!keys) { log_error ("validate_key_list failed\n"); - rc = GPG_ERR_GENERAL; + rc = G10ERR_GENERAL; goto leave; } @@ -2070,9 +2280,9 @@ validate_keys (int interactive) for (kar=keys; kar->keyblock; kar++) store_validation_status (depth, kar->keyblock, stored); - log_info (_("checking at depth %d valid=%d" - " ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n"), - depth, key_count, ot_unknown, ot_undefined, + log_info (_("depth: %d valid: %3d signed: %3d" + " trust: %d-, %dq, %dn, %dm, %df, %du\n"), + depth, valids, key_count, ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate ); /* Build a new kdlist from all fully valid keys in KEYS */ @@ -2110,7 +2320,7 @@ validate_keys (int interactive) kar->keyblock->pkt->pkt.public_key->trust_value; if(kar->keyblock->pkt->pkt.public_key->trust_regexp) k->trust_regexp= - xstrdup (kar->keyblock->pkt-> + xstrdup(kar->keyblock->pkt-> pkt.public_key->trust_regexp); k->next = klist; klist = k; @@ -2146,7 +2356,7 @@ validate_keys (int interactive) if(tdbio_update_version_record()!=0) { log_error(_("unable to update trustdb version record: " - "write failed: %s\n"), gpg_strerror (rc)); + "write failed: %s\n"), g10_errstr(rc)); tdbio_invalid(); } diff --git a/g10/trustdb.h b/g10/trustdb.h index 414c37702..2d0581f9b 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -1,6 +1,6 @@ /* trustdb.h - Trust database - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -16,13 +16,13 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_TRUSTDB_H #define G10_TRUSTDB_H - /* Trust values must be sorted in ascending order */ #define TRUST_MASK 15 #define TRUST_UNKNOWN 0 /* o: not yet calculated/assigned */ @@ -38,19 +38,26 @@ #define TRUST_FLAG_DISABLED 128 /* d: key/uid disabled */ #define TRUST_FLAG_PENDING_CHECK 256 /* a check-trustdb is pending */ +#define NAMEHASH_HASH DIGEST_ALGO_RMD160 +#define NAMEHASH_LEN 20 + /*-- trustdb.c --*/ +void register_trusted_keyid(u32 *keyid); void register_trusted_key( const char *string ); void check_trustdb (void); void update_trustdb (void); int setup_trustdb( int level, const char *dbname ); void init_trustdb( void ); +void check_trustdb_stale(void); void sync_trustdb( void ); +const char *uid_trust_string_fixed(PKT_public_key *key,PKT_user_id *uid); const char *trust_value_to_string (unsigned int value); int string_to_trust_value (const char *str); void revalidation_mark (void); int trustdb_pending_check(void); +void trustdb_check_or_update(void); int cache_disabled_value(PKT_public_key *pk); @@ -75,6 +82,11 @@ const char *get_ownertrust_string (PKT_public_key *pk); void update_ownertrust (PKT_public_key *pk, unsigned int new_trust ); int clear_ownertrusts (PKT_public_key *pk); +void clean_one_uid(KBNODE keyblock,KBNODE uidnode,int noisy,int self_only, + int *uids_cleaned,int *sigs_cleaned); +void clean_key(KBNODE keyblock,int noisy,int self_only, + int *uids_cleaned,int *sigs_cleaned); + /*-- tdbdump.c --*/ void list_trustdb(const char *username); void export_ownertrust(void); diff --git a/g10/verify.c b/g10/verify.c index cfa373637..54aa76544 100644 --- a/g10/verify.c +++ b/g10/verify.c @@ -1,5 +1,5 @@ -/* verify.c - verify signed data - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +/* verify.c - Verify signed data + * Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -24,14 +25,13 @@ #include <string.h> #include <errno.h> #include <assert.h> -#include <unistd.h> /* for isatty() */ +#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 "status.h" @@ -54,7 +54,7 @@ int verify_signatures( int nfiles, char **files ) { - iobuf_t fp; + IOBUF fp; armor_filter_context_t afx; progress_filter_context_t pfx; const char *sigfile; @@ -91,11 +91,17 @@ verify_signatures( int nfiles, char **files ) /* open the signature file */ fp = iobuf_open(sigfile); + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } if( !fp ) { rc = gpg_error_from_errno (errno); log_error(_("can't open `%s': %s\n"), print_fname_stdin(sigfile), strerror (errno)); - return rc; + return rc; } handle_progress (&pfx, fp, sigfile); @@ -103,12 +109,12 @@ verify_signatures( int nfiles, char **files ) iobuf_push_filter( fp, armor_filter, &afx ); sl = NULL; - for(i=1 ; i < nfiles; i++ ) + for(i=nfiles-1 ; i > 0 ; i-- ) add_to_strlist( &sl, files[i] ); rc = proc_signature_packets( NULL, fp, sl, sigfile ); free_strlist(sl); iobuf_close(fp); - if( afx.no_openpgp_data && rc == -1 ) { + if( (afx.no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) { log_error(_("the signature could not be verified.\n" "Please remember that the signature file (.sig or .asc)\n" "should be the first file given on the command line.\n") ); @@ -122,23 +128,31 @@ verify_signatures( int nfiles, char **files ) void print_file_status( int status, const char *name, int what ) { - char *p = xmalloc (strlen(name)+10); + char *p = xmalloc(strlen(name)+10); sprintf(p, "%d %s", what, name ); write_status_text( status, p ); - xfree (p); + xfree(p); } static int verify_one_file( const char *name ) { - iobuf_t fp; + IOBUF fp; armor_filter_context_t afx; progress_filter_context_t pfx; int rc; print_file_status( STATUS_FILE_START, name, 1 ); fp = iobuf_open(name); + if (fp) + iobuf_ioctl (fp,3,1,NULL); /* disable fd caching */ + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } if( !fp ) { rc = gpg_error_from_errno (errno); log_error(_("can't open `%s': %s\n"), @@ -179,7 +193,7 @@ verify_files( int nfiles, char **files ) lno++; if( !*line || line[strlen(line)-1] != '\n' ) { log_error(_("input line %u too long or missing LF\n"), lno ); - return GPG_ERR_GENERAL; + return G10ERR_GENERAL; } /* This code does not work on MSDOS but how cares there are * also no script languages available. We don't strip any diff --git a/include/ChangeLog b/include/ChangeLog index 5b343f5a0..0211bd618 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2006-04-18 Werner Koch <wk@g10code.com> + + * keyserver.h, i18n.h, http.h, cipher.h: Updated to gpg 1.4.3. + 2003-09-04 David Shaw <dshaw@jabberwocky.com> * cipher.h: Drop TIGER/192 support. diff --git a/include/cipher.h b/include/cipher.h index e7e36c6d5..681386c36 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -1,97 +1,101 @@ -/* cipher.h - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +/* cipher.h - Definitions for OpenPGP + * Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc. * - * This file is part of GNUPG. + * This file is part of GnuPG. * - * GNUPG is free software; you can redistribute it and/or modify + * 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_CIPHER_H #define G10_CIPHER_H #include <gcrypt.h> -#define CIPHER_ALGO_NONE GCRY_CIPHER_NONE -#define CIPHER_ALGO_IDEA GCRY_CIPHER_IDEA -#define CIPHER_ALGO_3DES GCRY_CIPHER_3DES -#define CIPHER_ALGO_CAST5 GCRY_CIPHER_CAST5 -#define CIPHER_ALGO_BLOWFISH GCRY_CIPHER_BLOWFISH /* 128 bit */ -#define CIPHER_ALGO_SAFER_SK128 GCRY_CIPHER_SK128 -#define CIPHER_ALGO_DES_SK GCRY_CIPHER_DES_SK -#define CIPHER_ALGO_AES GCRY_CIPHER_AES -#define CIPHER_ALGO_AES192 GCRY_CIPHER_AES192 -#define CIPHER_ALGO_AES256 GCRY_CIPHER_AES256 +/* Macros for compatibility with older libgcrypt versions. */ +#ifndef GCRY_PK_USAGE_CERT +# define GCRY_PK_USAGE_CERT 4 +# define GCRY_PK_USAGE_AUTH 8 +# define GCRY_PK_USAGE_UNKN 128 +#endif + + +/* Constants for OpenPGP. */ + +#define CIPHER_ALGO_NONE /* 0 */ GCRY_CIPHER_NONE +#define CIPHER_ALGO_IDEA /* 1 */ GCRY_CIPHER_IDEA +#define CIPHER_ALGO_3DES /* 2 */ GCRY_CIPHER_3DES +#define CIPHER_ALGO_CAST5 /* 3 */ GCRY_CIPHER_CAST5 +#define CIPHER_ALGO_BLOWFISH /* 4 */ GCRY_CIPHER_BLOWFISH /* 128 bit */ +/* 5 & 6 are reserved */ +#define CIPHER_ALGO_AES /* 7 */ GCRY_CIPHER_AES +#define CIPHER_ALGO_AES192 /* 8 */ GCRY_CIPHER_AES192 +#define CIPHER_ALGO_AES256 /* 9 */ GCRY_CIPHER_AES256 #define CIPHER_ALGO_RIJNDAEL CIPHER_ALGO_AES #define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192 #define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256 -#define CIPHER_ALGO_TWOFISH GCRY_CIPHER_TWOFISH /* 256 bit */ -#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ +#define CIPHER_ALGO_TWOFISH /* 10 */ GCRY_CIPHER_TWOFISH /* 256 bit */ +#define CIPHER_ALGO_DUMMY 110 /* No encryption at all. */ -#define PUBKEY_ALGO_RSA GCRY_PK_RSA -#define PUBKEY_ALGO_RSA_E GCRY_PK_RSA_E -#define PUBKEY_ALGO_RSA_S GCRY_PK_RSA_S -#define PUBKEY_ALGO_ELGAMAL_E GCRY_PK_ELG_E -#define PUBKEY_ALGO_DSA GCRY_PK_DSA -#define PUBKEY_ALGO_ELGAMAL GCRY_PK_ELG +#define PUBKEY_ALGO_RSA /* 1 */ GCRY_PK_RSA +#define PUBKEY_ALGO_RSA_E /* 2 */ GCRY_PK_RSA_E /* RSA encrypt only. */ +#define PUBKEY_ALGO_RSA_S /* 3 */ GCRY_PK_RSA_S /* RSA sign only. */ +#define PUBKEY_ALGO_ELGAMAL_E /* 16 */ GCRY_PK_ELG_E /* Elgamal encr only */ +#define PUBKEY_ALGO_DSA /* 17 */ GCRY_PK_DSA +#define PUBKEY_ALGO_ELGAMAL /* 20 */ GCRY_PK_ELG /* Elgamal encr+sign */ -#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN -#define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR -#define PUBKEY_USAGE_CERT 4 /* key is also good to certify other keys*/ -#define PUBKEY_USAGE_AUTH 8 +#define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */ +#define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR /* Good for encryption. */ +#define PUBKEY_USAGE_CERT GCRY_PK_USAGE_CERT /* Also good to certify keys. */ +#define PUBKEY_USAGE_AUTH GCRY_PK_USAGE_AUTH /* Good for authentication. */ +#define PUBKEY_USAGE_UNKNOWN GCRY_PK_USAGE_UNKN /* Unknown usage flag. */ -#define DIGEST_ALGO_MD5 GCRY_MD_MD5 -#define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 -#define DIGEST_ALGO_RMD160 GCRY_MD_RMD160 -#define DIGEST_ALGO_SHA256 GCRY_MD_SHA256 -#define DIGEST_ALGO_SHA384 GCRY_MD_SHA384 -#define DIGEST_ALGO_SHA512 GCRY_MD_SHA512 +#define DIGEST_ALGO_MD5 /* 1 */ GCRY_MD_MD5 +#define DIGEST_ALGO_SHA1 /* 2 */ GCRY_MD_SHA1 +#define DIGEST_ALGO_RMD160 /* 3 */ GCRY_MD_RMD160 +/* 4, 5, 6, and 7 are reserved */ +#define DIGEST_ALGO_SHA256 /* 8 */ GCRY_MD_SHA256 +#define DIGEST_ALGO_SHA384 /* 9 */ GCRY_MD_SHA384 +#define DIGEST_ALGO_SHA512 /* 10 */ GCRY_MD_SHA512 #define COMPRESS_ALGO_NONE 0 #define COMPRESS_ALGO_ZIP 1 #define COMPRESS_ALGO_ZLIB 2 +#define COMPRESS_ALGO_BZIP2 3 #define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ || (a)==PUBKEY_ALGO_RSA_S ) -#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) +#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL_E) +#define is_DSA(a) ((a)==PUBKEY_ALGO_DSA) -typedef struct { - int algo; - int keylen; - int algo_info_printed; - int use_mdc; - byte key[32]; /* this is the largest used keylen (256 bit) */ +/* The data encryption key object. */ +typedef struct +{ + int algo; + int keylen; + int algo_info_printed; + int use_mdc; + int symmetric; + byte key[32]; /* This is the largest used keylen (256 bit). */ } DEK; -#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 g10_opt_verbose; -EXTERN_UNLESS_MAIN_MODULE const char *g10_opt_homedir; - - +/* Constants to allocate static MPI arrays. */ #define PUBKEY_MAX_NPKEY 4 #define PUBKEY_MAX_NSKEY 6 #define PUBKEY_MAX_NSIG 2 #define PUBKEY_MAX_NENC 2 -#define MD_HANDLE gcry_md_hd_t -#define CIPHER_HANDLE gcry_cipher_hd_t - #endif /*G10_CIPHER_H*/ diff --git a/include/host2net.h b/include/host2net.h index 0f12a8e1d..e378bfb29 100644 --- a/include/host2net.h +++ b/include/host2net.h @@ -1,21 +1,22 @@ /* host2net.h - Some macros * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * - * This file is part of GNUPG. + * This file is part of GnuPG. * - * GNUPG is free software; you can redistribute it and/or modify + * 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_HOST2NET_H diff --git a/include/http.h b/include/http.h index b53ac9f9f..b9ce5b130 100644 --- a/include/http.h +++ b/include/http.h @@ -1,5 +1,6 @@ /* http.h - HTTP protocol handler - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2001, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,12 +16,14 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ + #ifndef G10_HTTP_H #define G10_HTTP_H 1 -#include "iobuf.h" +#include "../common/iobuf.h" struct uri_tuple { struct uri_tuple *next; @@ -34,6 +37,7 @@ typedef struct uri_tuple *URI_TUPLE; struct parsed_uri { /* all these pointers point into buffer; most stuff is not escaped */ char *scheme; /* pointer to the scheme string (lowercase) */ + char *auth; /* username/password for basic auth */ char *host; /* host (converted to lowercase) */ ushort port; /* port (always set if the host is set) */ char *path; /* the path */ @@ -49,19 +53,20 @@ typedef enum { HTTP_REQ_POST = 3 } HTTP_REQ_TYPE; -enum { /* put flag values into an enum, so that gdb can display them */ - HTTP_FLAG_TRY_PROXY = 1, - HTTP_FLAG_NO_SHUTDOWN = 2, - HTTP_FLAG_TRY_SRV = 3 -}; +/* put flag values into an enum, so that gdb can display them */ +enum + { + HTTP_FLAG_NO_SHUTDOWN = 1, + HTTP_FLAG_TRY_SRV = 2 + }; struct http_context { int initialized; unsigned int status_code; int sock; int in_data; - IOBUF fp_read; - IOBUF fp_write; + iobuf_t fp_read; + iobuf_t fp_write; int is_http_0_9; PARSED_URI uri; HTTP_REQ_TYPE req_type; @@ -72,11 +77,11 @@ struct http_context { typedef struct http_context *HTTP_HD; int http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, - unsigned int flags ); + char *auth, unsigned int flags, const char *proxy ); void http_start_data( HTTP_HD hd ); int http_wait_response( HTTP_HD hd, unsigned int *ret_status ); void http_close( HTTP_HD hd ); - -int http_open_document( HTTP_HD hd, const char *document, unsigned int flags ); +int http_open_document( HTTP_HD hd, const char *document, char *auth, + unsigned int flags, const char *proxy ); #endif /*G10_HTTP_H*/ diff --git a/include/i18n.h b/include/i18n.h index 20c2570ab..6abd2dce3 100644 --- a/include/i18n.h +++ b/include/i18n.h @@ -15,14 +15,15 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_I18N_H #define G10_I18N_H #ifdef USE_SIMPLE_GETTEXT -int set_gettext_file( const char *filename ); +int set_gettext_file( const char *filename, const char *regkey ); const char *gettext( const char *msgid ); #define _(a) gettext (a) diff --git a/include/keyserver.h b/include/keyserver.h index 33c1b318b..7bd12625e 100644 --- a/include/keyserver.h +++ b/include/keyserver.h @@ -1,21 +1,22 @@ /* keyserver.h * Copyright (C) 2001, 2002 Free Software Foundation, Inc. * - * This file is part of GNUPG. + * This file is part of GnuPG. * - * GNUPG is free software; you can redistribute it and/or modify + * 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef _KEYSERVER_H_ @@ -35,6 +36,7 @@ #define KEYSERVER_KEY_EXISTS 7 /* key already exists */ #define KEYSERVER_KEY_INCOMPLETE 8 /* key incomplete (EOF) */ #define KEYSERVER_UNREACHABLE 9 /* unable to contact keyserver */ +#define KEYSERVER_TIMEOUT 10 /* timeout while accessing keyserver */ /* Must be 127 due to shell internal magic. */ #define KEYSERVER_SCHEME_NOT_FOUND 127 diff --git a/include/memory.h b/include/memory.h index 959f2999e..35719da62 100644 --- a/include/memory.h +++ b/include/memory.h @@ -21,6 +21,8 @@ #ifndef G10_MEMORY_H #define G10_MEMORY_H +#error this file should not be used anymore + #ifdef M_DEBUG #ifndef STR #define STR(v) #v diff --git a/include/mpi.h b/include/mpi.h index 424e591a0..b732923a2 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -30,6 +30,8 @@ #ifndef G10_MPI_H #define G10_MPI_H +#error this file should not be used anymore + #include <gcrypt.h> #if 0 diff --git a/include/types.h b/include/types.h index dff512061..6abd500e3 100644 --- a/include/types.h +++ b/include/types.h @@ -1,21 +1,22 @@ /* types.h - some common typedefs * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * - * This file is part of GNUPG. + * This file is part of GnuPG. * - * GNUPG is free software; you can redistribute it and/or modify + * 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_TYPES_H diff --git a/include/util.h b/include/util.h index ca5e5e431..c579c152e 100644 --- a/include/util.h +++ b/include/util.h @@ -20,7 +20,7 @@ #ifndef G10_UTIL_H #define G10_UTIL_H -#warning oops, using old util.h +#error this file should not be used anymore #if 0 /* Dont use it anymore */ #if defined (__MINGW32__) || defined (__CYGWIN32__) diff --git a/include/zlib-riscos.h b/include/zlib-riscos.h index fad556bcb..6a27b86ef 100644 --- a/include/zlib-riscos.h +++ b/include/zlib-riscos.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_ZLIB_RISCOS_H #define G10_ZLIB_RISCOS_H diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index f0463c5b3..32549d136 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2006-04-18 Werner Koch <wk@g10code.com> + + * libjnlib-config.h (JNLIB_NEED_UTF8CONF): Defined. + * strlist.c (add_to_strlist2) [JNLIB_NEED_UTF8CONV]: Enabled. + 2005-06-15 Werner Koch <wk@g10code.com> * stringhelp.c (sanitize_buffer): Make P a void*. diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h index ad7e353fd..8ae2a9ce9 100644 --- a/jnlib/libjnlib-config.h +++ b/jnlib/libjnlib-config.h @@ -1,5 +1,5 @@ /* libjnlib-config.h - local configuration of the jnlib functions - * Copyright (C) 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -29,6 +29,9 @@ #include <gcrypt.h> /* gcry_malloc & Cie. */ #include "logging.h" +/* We require support for utf-8 conversion. */ +#define JNLIB_NEED_UTF8CONF 1 + #ifdef USE_SIMPLE_GETTEXT int set_gettext_file( const char *filename ); const char *gettext( const char *msgid ); diff --git a/jnlib/strlist.c b/jnlib/strlist.c index 49b510666..d1924c102 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -1,5 +1,5 @@ /* strlist.c - string helpers - * Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -26,7 +26,9 @@ #include "libjnlib-config.h" #include "strlist.h" - +#ifdef JNLIB_NEED_UTF8CONV +#include "utf8conv.h" +#endif void free_strlist( strlist_t sl ) @@ -53,26 +55,26 @@ add_to_strlist( strlist_t *list, const char *string ) return sl; } -#if 0 -/**************** - * same as add_to_strlist() but if is_utf8 is *not* set a conversion - * to UTF8 is done - */ + +/* Same as add_to_strlist() but if is_utf8 is *not* set, a conversion + to UTF-8 is done. */ +#ifdef JNLIB_NEED_UTF8CONV strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) { - strlist_t sl; - - if( is_utf8 ) - sl = add_to_strlist( list, string ); - else { - char *p = native_to_utf8( string ); - sl = add_to_strlist( list, p ); - m_free( p ); + strlist_t sl; + + if (is_utf8) + sl = add_to_strlist( list, string ); + else + { + char *p = native_to_utf8( string ); + sl = add_to_strlist( list, p ); + jnlib_free ( p ); } - return sl; + return sl; } -#endif +#endif /* JNLIB_NEED_UTF8CONV*/ strlist_t append_to_strlist( strlist_t *list, const char *string ) diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 72da241bc..47ac5bd4e 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -32,8 +32,7 @@ typedef struct string_list *strlist_t; void free_strlist (strlist_t sl); strlist_t add_to_strlist (strlist_t *list, const char *string); -/*strlist_t add_to_strlist2( strlist_t *list, - const char *string, int is_utf8);*/ +strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8); strlist_t append_to_strlist (strlist_t *list, const char *string); -- cgit v1.2.3 From d0907e64f473b743ec7a6888583e19502b804ca2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 19 Apr 2006 13:24:36 +0000 Subject: Continued with merging. Still does not build. --- g10/cipher.c | 6 ++--- g10/dearmor.c | 4 ++-- g10/encode.c | 23 +++++++++---------- g10/exec.c | 6 ++--- g10/export.c | 1 - g10/filter.h | 20 ++++++++--------- g10/gpgv.c | 18 +++++++-------- g10/import.c | 16 ++++++------- g10/keyedit.c | 14 ++++++------ g10/keygen.c | 30 +++++++++++++------------ g10/keylist.c | 11 ++++----- g10/keyserver.c | 4 ++-- g10/mainproc.c | 8 +++---- g10/parse-packet.c | 7 +++--- g10/passphrase.c | 33 ++++++++++++++------------- g10/pkclist.c | 2 +- g10/plaintext.c | 34 +++++++++++++++------------- g10/seckey-cert.c | 6 ++--- g10/sig-check.c | 2 +- g10/sign.c | 66 +++++++++++++++++++++++++++--------------------------- g10/skclist.c | 2 +- g10/tdbio.c | 3 --- 22 files changed, 158 insertions(+), 158 deletions(-) diff --git a/g10/cipher.c b/g10/cipher.c index ff1080495..b33deb28b 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -51,7 +51,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) unsigned int blocksize; unsigned int nprefix; - blocksize = gcry_cipher_algo_blklen (cfx->dek->algo); + blocksize = gcry_cipher_get_algo_blklen (cfx->dek->algo); if ( blocksize < 8 || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); @@ -88,8 +88,8 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) GCRY_CIPHER_MODE_CFB, (GCRY_CIPHER_SECURE | ((cfx->dek->use_mdc || cfx->dek->algo >= 100)? - 0 : GCRY_CIPHER_ENABLE_SYNC)); - if (rc) { + 0 : GCRY_CIPHER_ENABLE_SYNC))); + if (err) { /* We should never get an error here cause we already checked, * that the algorithm is available. */ BUG(); diff --git a/g10/dearmor.c b/g10/dearmor.c index dc9a22fad..7f69a1bba 100644 --- a/g10/dearmor.c +++ b/g10/dearmor.c @@ -58,9 +58,9 @@ dearmor_file( const char *fname ) errno = EPERM; } if (!inp) { + rc = gpg_error_from_errno (errno); log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); - rc = G10ERR_OPEN_FILE; goto leave; } @@ -107,9 +107,9 @@ enarmor_file( const char *fname ) errno = EPERM; } if (!inp) { + rc = gpg_error_from_errno (errno); log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); - rc = G10ERR_OPEN_FILE; goto leave; } diff --git a/g10/encode.c b/g10/encode.c index 57f2272dd..bb3e7bbc2 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -92,7 +92,7 @@ encode_seskey( DEK *dek, DEK **seskey, byte *enckey ) BUG (); if (gcry_cipher_setkey (hd, dek->key, dek->keylen)) BUG (); - gry_cipher_setiv (hd, NULL, 0); + gcry_cipher_setiv (hd, NULL, 0); gcry_cipher_encrypt (hd, buf, (*seskey)->keylen + 1, NULL, 0); gcry_cipher_close (hd); @@ -190,7 +190,7 @@ encode_simple( const char *filename, int mode, int use_seskey ) } if( !inp ) { rc = gpg_error_from_errno (errno); - log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]" + log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]", strerror(errno) ); return rc; } @@ -365,9 +365,9 @@ encode_simple( const char *filename, int mode, int use_seskey ) byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", g10_errstr(rc) ); + 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 */ @@ -403,7 +403,7 @@ setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek) { xfree(*symkey_dek); xfree(*symkey_s2k); - return G10ERR_PASSPHRASE; + return gpg_error (GPG_ERR_BAD_PASSPHRASE); } return 0; @@ -412,7 +412,7 @@ setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek) static int write_symkey_enc(STRING2KEY *symkey_s2k,DEK *symkey_dek,DEK *dek,IOBUF out) { - int rc,seskeylen=cipher_get_keylen(dek->algo)/8; + int rc, seskeylen = gcry_cipher_get_algo_keylen (dek->algo); PKT_symkey_enc *enc; byte enckey[33]; @@ -674,10 +674,9 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey ) byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", - g10_errstr(rc) ); + 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 */ @@ -795,7 +794,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) int rc; for( ; pk_list; pk_list = pk_list->next ) { - MPI frame; + gcry_mpi_t frame; pk = pk_list->pk; diff --git a/g10/exec.c b/g10/exec.c index 839964b1d..cdc86e16b 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -438,8 +438,8 @@ int exec_write(struct exec_info **info,const char *program, (*info)->tochild=fdopen(to[1],binary?"wb":"w"); if((*info)->tochild==NULL) { + ret = gpg_error_from_errno (errno); close(to[1]); - ret=G10ERR_WRITE_FILE; goto fail; } @@ -448,8 +448,8 @@ int exec_write(struct exec_info **info,const char *program, (*info)->fromchild=iobuf_fdopen(from[0],"r"); if((*info)->fromchild==NULL) { + ret = gpg_error_from_errno (errno); close(from[0]); - ret=G10ERR_READ_FILE; goto fail; } @@ -547,9 +547,9 @@ int exec_read(struct exec_info *info) } if(info->fromchild==NULL) { + ret = gpg_error_from_errno (errno); log_error(_("unable to read external program response: %s\n"), strerror(errno)); - ret=G10ERR_READ_FILE; goto fail; } diff --git a/g10/export.c b/g10/export.c index 495079602..2760ea054 100644 --- a/g10/export.c +++ b/g10/export.c @@ -594,7 +594,6 @@ do_export_stream( IOBUF out, STRLIST users, int secret, if( rc ) { log_error("build_packet(%d) failed: %s\n", node->pkt->pkttype, g10_errstr(rc) ); - rc = G10ERR_WRITE_FILE; goto leave; } } diff --git a/g10/filter.h b/g10/filter.h index 3b4e73963..5c1b9372a 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -126,36 +126,36 @@ typedef struct { /* encrypt_filter_context_t defined in main.h */ /*-- mdfilter.c --*/ -int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); +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 a ); +int use_armor_filter( iobuf_t a ); int armor_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); + 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 --*/ -void push_compress_filter(IOBUF out,compress_filter_context_t *zfx,int algo); -void push_compress_filter2(IOBUF out,compress_filter_context_t *zfx, +void push_compress_filter(iobuf_t out,compress_filter_context_t *zfx,int algo); +void push_compress_filter2(iobuf_t out,compress_filter_context_t *zfx, int algo,int rel); /*-- cipher.c --*/ int cipher_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); + iobuf_t chain, byte *buf, size_t *ret_len); /*-- textfilter.c --*/ int text_filter( void *opaque, int control, - IOBUF chain, byte *buf, size_t *ret_len); -int copy_clearsig_text (IOBUF out, IOBUF inp, gcry_md_hd_t md, + iobuf_t chain, byte *buf, size_t *ret_len); +int copy_clearsig_text (iobuf_t out, iobuf_t inp, gcry_md_hd_t md, int escape_dash, int escape_from, int pgp2mode); /*-- progress.c --*/ int progress_filter (void *opaque, int control, - IOBUF a, byte *buf, size_t *ret_len); + iobuf_t a, byte *buf, size_t *ret_len); void handle_progress (progress_filter_context_t *pfx, - IOBUF inp, const char *name); + iobuf_t inp, const char *name); #endif /*G10_FILTER_H*/ diff --git a/g10/gpgv.c b/g10/gpgv.c index 5fc7dcd75..9b17b8ad3 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -49,8 +49,6 @@ #include "ttyio.h" #include "i18n.h" #include "status.h" -#include "g10defs.h" -#include "cardglue.h" enum cmd_and_opt_values { aNull = 0, @@ -379,15 +377,15 @@ 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, +gcry_cipher_hd_t cipher_open( int algo, int mode, int secure ) { return NULL;} +void cipher_close( gcry_cipher_hd_t c ) {} +int cipher_setkey( gcry_cipher_hd_t c, byte *key, unsigned keylen ) { return -1;} +void cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen ){} +void cipher_encrypt( gcry_cipher_hd_t c, byte *outbuf, byte *inbuf, unsigned nbytes ) {} -void cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, +void cipher_decrypt( gcry_cipher_hd_t c, byte *outbuf, byte *inbuf, unsigned nbytes ) {} -void cipher_sync( CIPHER_HANDLE c ) {} +void cipher_sync( gcry_cipher_hd_t c ) {} /* Stubs to avoid linking to ../cipher/random.c */ void random_dump_stats(void) {} @@ -404,7 +402,7 @@ void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {} MPI generate_secret_prime( unsigned nbits ) { return NULL;} MPI generate_public_prime( unsigned nbits ) { return NULL;} MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - MPI g, MPI **ret_factors ) { return NULL;} + gcry_mpi_t g, gcry_mpi_t **ret_factors ) { return NULL;} /* Do not link to ../cipher/rndlinux.c */ void rndlinux_constructor(void) {} diff --git a/g10/import.c b/g10/import.c index 31af7fe02..ee4ea95da 100644 --- a/g10/import.c +++ b/g10/import.c @@ -596,9 +596,9 @@ check_prefs(KBNODE keyblock) if(prefs->type==PREFTYPE_SYM) { - if(check_cipher_algo(prefs->value)) + if (openpgp_cipher_algo_test (prefs->value)) { - const char *algo=cipher_algo_to_string(prefs->value); + const char *algo = gcry_cipher_algo_name (prefs->value); if(!problem) check_prefs_warning(pk); log_info(_(" \"%s\": preference for cipher" @@ -608,9 +608,9 @@ check_prefs(KBNODE keyblock) } else if(prefs->type==PREFTYPE_HASH) { - if(check_digest_algo(prefs->value)) + if(openpgp_md_test_algo(prefs->value)) { - const char *algo=digest_algo_to_string(prefs->value); + const char *algo = gcry_md_algo_name (prefs->value); if(!problem) check_prefs_warning(pk); log_info(_(" \"%s\": preference for digest" @@ -620,7 +620,7 @@ check_prefs(KBNODE keyblock) } else if(prefs->type==PREFTYPE_ZIP) { - if(check_compress_algo(prefs->value)) + if(check_compress_algo (prefs->value)) { const char *algo=compress_algo_to_string(prefs->value); if(!problem) @@ -1541,9 +1541,9 @@ delete_inv_parts( const char *fname, KBNODE keyblock, else subkey_seen = 1; } - else if( node->pkt->pkttype == PKT_SIGNATURE - && check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo) - && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA ) + else if (node->pkt->pkttype == PKT_SIGNATURE + && openpgp_pk_test_algo (node->pkt->pkt.signature->pubkey_algo) + && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA ) delete_kbnode( node ); /* build_packet() can't handle this */ else if( node->pkt->pkttype == PKT_SIGNATURE && !node->pkt->pkt.signature->flags.exportable && diff --git a/g10/keyedit.c b/g10/keyedit.c index 2a31d5973..bfe3f8546 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -2311,7 +2311,7 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose) tty_printf (_("Cipher: ")); for(i=any=0; prefs[i].type; i++ ) { if( prefs[i].type == PREFTYPE_SYM ) { - const char *s = cipher_algo_to_string (prefs[i].value); + const char *s = gcry_cipher_algo_name (prefs[i].value); if (any) tty_printf (", "); @@ -2328,13 +2328,13 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose) if (!des_seen) { if (any) tty_printf (", "); - tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES)); + tty_printf ("%s", gcry_cipher_algo_name (CIPHER_ALGO_3DES)); } tty_printf ("\n "); tty_printf (_("Digest: ")); for(i=any=0; prefs[i].type; i++ ) { if( prefs[i].type == PREFTYPE_HASH ) { - const char *s = digest_algo_to_string (prefs[i].value); + const char *s = gcry_md_algo_name (prefs[i].value); if (any) tty_printf (", "); @@ -2351,7 +2351,7 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose) if (!sha1_seen) { if (any) tty_printf (", "); - tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1)); + tty_printf ("%s", gcry_md_algo_name (DIGEST_ALGO_SHA1)); } tty_printf ("\n "); tty_printf (_("Compression: ")); @@ -2686,7 +2686,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, if(pk->is_revoked) { char *user=get_user_id_string_native(pk->revoked.keyid); - const char *algo=pubkey_algo_to_string(pk->revoked.algo); + const char *algo = gcry_pk_algo_name (pk->revoked.algo); tty_printf(_("This key was revoked on %s by %s key %s\n"), revokestr_from_pk(pk),algo?algo:"?",user); xfree(user); @@ -2701,9 +2701,9 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, { u32 r_keyid[2]; char *user; - const char *algo= - pubkey_algo_to_string(pk->revkey[i].algid); + const char *algo; + algo = gcry_pk_algo_name (pk->revkey[i].algid); keyid_from_fingerprint(pk->revkey[i].fpr, MAX_FINGERPRINT_LEN,r_keyid); diff --git a/g10/keygen.c b/g10/keygen.c index 6a64ff317..32c09a97d 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -319,13 +319,13 @@ keygen_set_std_prefs (const char *string,int personal) /* Make sure we do not add more than 15 items here, as we could overflow the size of dummy_string. We currently have at most 12. */ - if(!check_cipher_algo(CIPHER_ALGO_AES256)) + if ( !openpgp_cipher_test_algo (CIPHER_ALGO_AES256) ) strcat(dummy_string,"S9 "); - if(!check_cipher_algo(CIPHER_ALGO_AES192)) + if ( !openpgp_cipher_test_algo (CIPHER_ALGO_AES192) ) strcat(dummy_string,"S8 "); - if(!check_cipher_algo(CIPHER_ALGO_AES)) + if ( !openpgp_cipher_test_algo (CIPHER_ALGO_AES) ) strcat(dummy_string,"S7 "); - if(!check_cipher_algo(CIPHER_ALGO_CAST5)) + if ( !openpgp_cipher_test_algo (CIPHER_ALGO_CAST5) ) strcat(dummy_string,"S3 "); strcat(dummy_string,"S2 "); /* 3DES */ /* If we have it, IDEA goes *after* 3DES so it won't be @@ -335,7 +335,7 @@ keygen_set_std_prefs (const char *string,int personal) break PGP2, but that is difficult with the current code, and not really worth checking as a non-RSA <=2048 bit key wouldn't be usable by PGP2 anyway. -dms */ - if(!check_cipher_algo(CIPHER_ALGO_IDEA)) + if ( !openpgp_cipher_test_algo (CIPHER_ALGO_IDEA) ) strcat(dummy_string,"S1 "); /* SHA-1 */ @@ -370,12 +370,12 @@ keygen_set_std_prefs (const char *string,int personal) while((tok=strsep(&prefstring," ,"))) { - if((val=string_to_cipher_algo(tok))) + if((val=openpgp_cipher_map_name (tok))) { if(set_one_pref(val,1,tok,sym,&nsym)) rc=-1; } - else if((val=string_to_digest_algo(tok))) + else if((val=openpgp_md_map_name (tok))) { if(set_one_pref(val,2,tok,hash,&nhash)) rc=-1; @@ -1071,6 +1071,7 @@ genhelp_protect (DEK *dek, STRING2KEY *s2k, PKT_secret_key *sk) static void genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root) { +#if 0 /* Not used anymore */ size_t n; char *buf; @@ -1093,6 +1094,7 @@ genhelp_factors (gcry_sexp_t misc_key_info, KBNODE sec_root) xfree (buf); gcry_sexp_release (misc_key_info); } +#endif } @@ -1484,7 +1486,7 @@ ask_key_flags(int algo,int subkey) { tty_printf("\n"); tty_printf(_("Possible actions for a %s key: "), - pubkey_algo_to_string(algo)); + gcry_pk_algo_name (algo)); print_key_flags(possible); tty_printf("\n"); tty_printf(_("Current allowed actions: ")); @@ -1649,7 +1651,7 @@ ask_keysize( int algo ) } tty_printf(_("%s keys may be between %u and %u bits long.\n"), - pubkey_algo_to_string(algo),min,max); + gcry_pk_algo_name (algo), min, max); for(;;) { @@ -1670,7 +1672,7 @@ ask_keysize( int algo ) if(nbits<min || nbits>max) tty_printf(_("%s keysizes must be in the range %u-%u\n"), - pubkey_algo_to_string(algo),min,max); + gcry_pk_algo_name (algo), min, max); else break; } @@ -2136,7 +2138,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key ) if( digitp( r->u.value ) ) i = atoi( r->u.value ); else - i = string_to_pubkey_algo( r->u.value ); + i = openpgp_pk_map_name (r->u.value); if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S) i = 0; /* we don't want to allow generation of these algorithms */ return i; @@ -2287,7 +2289,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, if(r) { algo=get_parameter_algo(para,pKEYTYPE); - if(check_pubkey_algo2(algo,PUBKEY_USAGE_SIG)) + if (openpgp_pk_test_algo (algo, PUBKEY_USAGE_SIG)) { log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); return -1; @@ -2316,7 +2318,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, if(r) { algo=get_parameter_algo( para, pSUBKEYTYPE); - if(check_pubkey_algo(algo)) + if (openpgp_pk_test_algo (algo)) { log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); return -1; @@ -3504,7 +3506,7 @@ write_keyblock( IOBUF out, KBNODE node ) { log_error("build_packet(%d) failed: %s\n", node->pkt->pkttype, g10_errstr(rc) ); - return G10ERR_WRITE_FILE; + return rc; } } } diff --git a/g10/keylist.c b/g10/keylist.c index 0ff788e18..0b1a51b6d 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -917,7 +917,8 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) rc = check_key_signature( keyblock, node, NULL ); switch( gpg_err_code (rc) ) { case 0: sigrc = '!'; break; - case GPG_ERR_BAD_SIGN: stats->inv_sigs++; sigrc = '-'; break; + case GPG_ERR_BAD_SIGNATURE: + stats->inv_sigs++; sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: case GPG_ERR_UNUSABLE_PUBKEY: stats->no_key++; continue; default: stats->oth_err++; sigrc = '%'; break; @@ -1306,11 +1307,11 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) rc = check_key_signature2( keyblock, node, NULL, signer_pk, NULL, NULL, NULL ); switch ( gpg_err_code (rc) ) { - case 0: sigrc = '!'; break; - case GPG_ERR_BAD_SIGN: sigrc = '-'; break; + case 0: sigrc = '!'; break; + case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: - case GPG_ERR_UNU_PUBKEY: sigrc = '?'; break; - default: sigrc = '%'; break; + case Gpg_Err_UNUSABLE_PUBKEY: sigrc = '?'; break; + default: sigrc = '%'; break; } if(opt.no_sig_cache) diff --git a/g10/keyserver.c b/g10/keyserver.c index af1e5f773..4fd90d08b 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -478,7 +478,7 @@ print_keyrec(int number,struct keyrec *keyrec) if(keyrec->type) { - const char *str=pubkey_algo_to_string(keyrec->type); + const char *str = gcry_pk_algo_name (keyrec->type); if(str) printf("%s ",str); @@ -1402,7 +1402,7 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc, maxlen=1024; if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0) { - ret=G10ERR_READ_FILE; + ret = gpg_error_from_errno (errno); goto fail; /* i.e. EOF */ } diff --git a/g10/mainproc.c b/g10/mainproc.c index 22711cf59..8e9b3ab65 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -639,7 +639,7 @@ proc_plaintext( CTX c, PACKET *pkt ) * documents */ clearsig = (*data == 0x01); for( data++, datalen--; datalen; datalen--, data++ ) - md_enable( c->mfx.md, *data ); + gcry_md_enable (c->mfx.md, *data); any = 1; break; /* Stop here as one-pass signature packets are not expected. */ @@ -679,7 +679,7 @@ proc_plaintext( CTX c, PACKET *pkt ) } rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); - if( gpg_err_code (rc) == G10ERR_CREATE_FILE && !c->sigs_only) + if( gpg_err_code (rc) == GPG_ERR_ENOENT && !c->sigs_only) { #warning We need to change the test for the error code /* Can't write output but we hash it anyway to @@ -1194,7 +1194,7 @@ do_proc_packets( CTX c, IOBUF a ) free_packet(pkt); /* stop processing when an invalid packet has been encountered * but don't do so when we are doing a --list-packets. */ - if (gpg_err_code (rc) == GPG_ERR_INVALID_PACKET + if (gpg_err_code (rc) == GPG_ERR_INV_PACKET && opt.list_packets != 2 ) break; continue; @@ -2002,7 +2002,7 @@ proc_tree( CTX c, KBNODE node ) /* detached signature */ free_md_filter_context( &c->mfx ); if (gcry_md_open (&c->mfx.md, sig->digest_algo, 0)) - BUG (): + BUG (); if( !opt.pgp2_workarounds ) ; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index b4dfb8c84..cd6e1dbe6 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -491,11 +491,10 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, } if( out && pkttype ) { - if( iobuf_write( out, hdr, hdrlen ) == -1 ) - rc = G10ERR_WRITE_FILE; - else + rc = iobuf_write (out, hdr, hdrlen); + if (!rc) rc = copy_packet(inp, out, pkttype, pktlen, partial ); - goto leave; + goto leave; } if (with_uid && pkttype == PKT_USER_ID) diff --git a/g10/passphrase.c b/g10/passphrase.c index c63ee66d4..c1cdf12ae 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -897,7 +897,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, xfree(p); if( !get_pubkey( pk, keyid ) ) { - const char *s = pubkey_algo_to_string( pk->pubkey_algo ); + const char *s = gcry_pk_algo_name ( pk->pubkey_algo ); tty_printf( _("%u-bit %s key, ID %s, created %s"), nbits_from_pk( pk ), s?s:"?", keystr(keyid), strtimestamp(pk->timestamp) ); @@ -1011,22 +1011,23 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo, static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) { - MD_HANDLE md; + gcry_md_hd_t md; int pass, i; int used = 0; int pwlen = strlen(pw); assert( s2k->hash_algo ); - dek->keylen = cipher_get_keylen( dek->algo ) / 8; + dek->keylen = gcry_cipher_algo_get_keylen (dek->algo ); if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) BUG(); - md = md_open( s2k->hash_algo, 1); + if (gcry_md_open (&md, s2k->hash_algo, 1)) + BUG (); for(pass=0; used < dek->keylen ; pass++ ) { if( pass ) { - md_reset(md); + gcry_md_reset (md); for(i=0; i < pass; i++ ) /* preset the hash context */ - md_putc(md, 0 ); + gcry_md_putc (md, 0 ); } if( s2k->mode == 1 || s2k->mode == 3 ) { @@ -1034,7 +1035,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) ulong count = len2; if( create && !pass ) { - randomize_buffer(s2k->salt, 8, 1); + gcry_randomize (s2k->salt, 8, GCRY_STRONG_RANDOM); if( s2k->mode == 3 ) s2k->count = 96; /* 65536 iterations */ } @@ -1046,27 +1047,27 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) } /* a little bit complicated because we need a ulong for count */ while( count > len2 ) { /* maybe iterated+salted */ - md_write( md, s2k->salt, 8 ); - md_write( md, pw, pwlen ); + gcry_md_write ( md, s2k->salt, 8 ); + gcry_md_write ( md, pw, pwlen ); count -= len2; } if( count < 8 ) - md_write( md, s2k->salt, count ); + gcry_md_write ( md, s2k->salt, count ); else { - md_write( md, s2k->salt, 8 ); + gcry_md_write ( md, s2k->salt, 8 ); count -= 8; - md_write( md, pw, count ); + gcry_md_write ( md, pw, count ); } } else - md_write( md, pw, pwlen ); - md_final( md ); - i = md_digest_length( s2k->hash_algo ); + gcry_md_write ( md, pw, pwlen ); + gcry_md_final( md ); + i = gcry_md_get_algo_dlen ( s2k->hash_algo ); if( i > dek->keylen - used ) i = dek->keylen - used; memcpy( dek->key+used, md_read(md, s2k->hash_algo), i ); used += i; } - md_close(md); + gcry_md_close(md); } diff --git a/g10/pkclist.c b/g10/pkclist.c index 793ac6902..9e2a63642 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -958,7 +958,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); if (rc) tty_printf(_("No such user ID.\n")); - else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) + else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) ) { if ( have_def_rec ) { diff --git a/g10/plaintext.c b/g10/plaintext.c index bd908e551..1f8c5759f 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -96,8 +96,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( !fname ) fname = ask_outfile_name( pt->name, pt->namelen ); if( !fname ) { - rc = gpg_error (GPG_ERR_GENERAL) /* Can't create file. */ - goto leave; + rc = gpg_error (GPG_ERR_GENERAL); /* Can't create file. */ + goto leave; } } else { @@ -119,7 +119,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, char *tmp = ask_outfile_name (NULL, 0); if ( !tmp || !*tmp ) { xfree (tmp); - rc = G10ERR_CREATE_FILE; + rc = gpg_error (GPG_ERR_GENERAL); /* G10ERR_CREATE_FILE*/ goto leave; } xfree (fname); @@ -203,16 +203,19 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { if(opt.max_output && (++count)>opt.max_output) { - log_error("Error writing to `%s': %s\n", - fname,"exceeded --max-output limit\n"); + log_error ("error writing to `%s': %s\n", + fname,"exceeded --max-output limit\n"); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } else if( putc( c, fp ) == EOF ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; + if (ferror (fp)) + rc = gpg_error_from_errno (errno); + else + rc = gpg_error (GPG_ERR_EOF); + log_error ("error writing to `%s': %s\n", + fname, strerror(errno) ); goto leave; } } @@ -224,9 +227,9 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, int len = pt->len > 32768 ? 32768 : pt->len; len = iobuf_read( pt->buf, buffer, len ); if( len == -1 ) { - log_error("Problem reading source (%u bytes remaining)\n", - (unsigned)pt->len); - rc = G10ERR_READ_FILE; + rc = gpg_error_from_errno (errno); + log_error ("problem reading source (%u bytes remaining)\n", + (unsigned)pt->len); xfree( buffer ); goto leave; } @@ -260,7 +263,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( convert ) { /* text mode */ while( (c = iobuf_get(pt->buf)) != -1 ) { if( mfx->md ) - md_putc(mfx->md, c ); + gcry_md_putc (mfx->md, c ); #ifndef HAVE_DOSISH_SYSTEM if( convert && c == '\r' ) continue; /* fixme: this hack might be too simple */ @@ -300,7 +303,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( len < 32768 ) eof = 1; if( mfx->md ) - md_write( mfx->md, buffer, len ); + gcry_md_write ( mfx->md, buffer, len ); if( fp ) { if(opt.max_output && (count+=len)>opt.max_output) @@ -479,8 +482,8 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2, } else if( !fp ) { + rc = gpg_error_from_errno (errno); log_error(_("can't open `%s': %s\n"), answer, strerror(errno)); - rc = G10ERR_READ_FILE; goto leave; } } while( !fp ); @@ -536,9 +539,10 @@ hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files, errno = EPERM; } if( !fp ) { + int rc = gpg_error_from_errno (errno); log_error(_("can't open signed data `%s'\n"), print_fname_stdin(sl->d)); - return G10ERR_OPEN_FILE; + return rc; } handle_progress (&pfx, fp, sl->d); do_hash( md, md2, fp, textmode ); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 382ad7534..acb2cdada 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -232,7 +232,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, copy_secret_key( sk, save_sk ); passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo ); free_secret_key( save_sk ); - return G10ERR_BAD_PASS; + return gpg_error (GPG_ERR_BAD_PASSPHRASE); } /* The checksum may fail, so we also check the key itself. */ @@ -241,7 +241,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode, copy_secret_key( sk, save_sk ); passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo ); free_secret_key( save_sk ); - return G10ERR_BAD_PASS; + return gpg_error (GPG_ERR_BAD_PASSPHRASE); } free_secret_key( save_sk ); sk->is_protected = 0; @@ -286,7 +286,7 @@ check_secret_key( PKT_secret_key *sk, int n ) if( n < 1 ) n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */ - for(i=0; i < n && gpg_err_code (rc) == G10ERR_BAD_PASS; i++ ) { + for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) { int canceled = 0; const char *tryagain = NULL; if (i) { diff --git a/g10/sig-check.c b/g10/sig-check.c index 1bb77f7f6..5a3cb886f 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -309,7 +309,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest, static void -hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig ) +hash_uid_node( KBNODE unode, gcry_md_hd_t md, PKT_signature *sig ) { PKT_user_id *uid = unode->pkt->pkt.user_id; diff --git a/g10/sign.c b/g10/sign.c index 66f8847d7..3553079d6 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -189,7 +189,7 @@ mk_notation_policy_etc( PKT_signature *sig, * Helper to hash a user ID packet. */ static void -hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid) +hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid) { if ( sigversion >= 4 ) { byte buf[5]; @@ -222,7 +222,7 @@ hash_uid (MD_HANDLE md, int sigversion, const PKT_user_id *uid) * Helper to hash some parts from the signature */ static void -hash_sigversion_to_magic (MD_HANDLE md, const PKT_signature *sig) +hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig) { if (sig->version >= 4) gcry_md_putc (md, sig->version); @@ -266,7 +266,7 @@ hash_sigversion_to_magic (MD_HANDLE md, const PKT_signature *sig) static int do_sign( PKT_secret_key *sk, PKT_signature *sig, - MD_HANDLE md, int digest_algo ) + gcry_md_hd_t md, int digest_algo ) { gcry_mpi_t frame; byte *dp; @@ -315,7 +315,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, xfree (rbuf); } #else - return G10ERR_UNSUPPORTED; + return gpg_error (GPG_ERR_NOT_SUPPORTED); #endif /* ENABLE_CARD_SUPPORT */ } else @@ -324,7 +324,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, variable-q DSA stuff makes it into the standard. */ if(!opt.expert && sk->pubkey_algo==PUBKEY_ALGO_DSA - && md_digest_length(digest_algo)!=20) + && gcry_md_get_algo_dlen (digest_algo)!=20) { log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); return G10ERR_GENERAL; @@ -375,7 +375,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, int -complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md ) +complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md ) { int rc=0; @@ -419,7 +419,7 @@ hash_for(PKT_secret_key *sk) prefitem_t *prefs; for(prefs=opt.personal_digest_prefs;prefs->type;prefs++) - if (gcry_md_get_algo-dlen (prefs->value) == 20) + if (gcry_md_get_algo_dlen (prefs->value) == 20) return prefs->value; } @@ -604,10 +604,9 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) - if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { - rc = G10ERR_WRITE_FILE; + if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) { log_error ("copying input to output failed: %s\n", - g10_errstr(rc)); + gpg_strerror (rc)); break; } wipememory(copy_buffer,4096); /* burn buffer */ @@ -622,7 +621,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) * hash which will not be changes here. */ static int -write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, +write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash, int sigclass, u32 timestamp, u32 duration, int status_letter) { @@ -632,7 +631,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { PKT_secret_key *sk; PKT_signature *sig; - MD_HANDLE md; + gcry_md_hd_t md; int rc; sk = sk_rover->sk; @@ -774,11 +773,12 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, inp = NULL; errno = EPERM; } - if( !inp ) { - log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", - strerror(errno) ); - rc = G10ERR_OPEN_FILE; - goto leave; + if( !inp ) + { + rc = gpg_error_from_errno (errno); + log_error (_("can't open `%s': %s\n"), fname? fname: "[stdin]", + strerror(errno) ); + goto leave; } handle_progress (&pfx, inp, fname); @@ -793,8 +793,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, out = iobuf_create( outfile ); if( !out ) { + rc = gpg_error_from_errno (errno); log_error(_("can't create `%s': %s\n"), outfile, strerror(errno) ); - rc = G10ERR_CREATE_FILE; goto leave; } else if( opt.verbose ) @@ -810,7 +810,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, iobuf_push_filter( inp, text_filter, &tfx ); } - if ( gcry_md_open (&,mfx.md, 0, 0) ) + if ( gcry_md_open (&mfx.md, 0, 0) ) BUG (); if (DBG_HASHING) gcry_md_start_debug (mfx.md, "sign"); @@ -1008,7 +1008,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) { armor_filter_context_t afx; progress_filter_context_t pfx; - MD_HANDLE textmd = NULL; + gcry_md_hd_t textmd = NULL; IOBUF inp = NULL, out = NULL; PACKET pkt; int rc = 0; @@ -1051,9 +1051,9 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) errno = EPERM; } if( !inp ) { - log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]", - strerror(errno) ); - rc = G10ERR_OPEN_FILE; + rc = gpg_error_from_errno (errno); + log_error (_("can't open `%s': %s\n"), + fname? fname: "[stdin]", strerror(errno) ); goto leave; } handle_progress (&pfx, inp, fname); @@ -1067,8 +1067,8 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) out = iobuf_create( outfile ); if( !out ) { + rc = gpg_error_from_errno (errno); log_error(_("can't create `%s': %s\n"), outfile, strerror(errno) ); - rc = G10ERR_CREATE_FILE; goto leave; } else if( opt.verbose ) @@ -1101,7 +1101,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) int i = hash_for(sk); if( !hashs_seen[ i & 0xff ] ) { - s = gcry_md_ago_name ( i ); + s = gcry_md_algo_name ( i ); if( s ) { hashs_seen[ i & 0xff ] = 1; if( any ) @@ -1203,9 +1203,9 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) errno = EPERM; } if( !inp ) { - log_error(_("can't open `%s': %s\n"), - fname? fname: "[stdin]", strerror(errno) ); - rc = G10ERR_OPEN_FILE; + rc = gpg_error_from_errno (errno); + log_error (_("can't open `%s': %s\n"), + fname? fname: "[stdin]", strerror(errno) ); goto leave; } handle_progress (&pfx, inp, fname); @@ -1222,8 +1222,8 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, NULL); if (!cfx.dek || !cfx.dek->keylen) { - rc = G10ERR_PASSPHRASE; - log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) ); + rc = gpg_error (GPG_ERR_BAD_PASSPHRASE); + log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) ); goto leave; } @@ -1341,7 +1341,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, { PKT_signature *sig; int rc=0; - MD_HANDLE md; + gcry_md_hd_t md; assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19 @@ -1455,7 +1455,7 @@ update_keysig_packet( PKT_signature **ret_sig, { PKT_signature *sig; int rc=0; - MD_HANDLE md; + gcry_md_hd_t md; if ((!orig_sig || !pk || !sk) || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) @@ -1506,7 +1506,7 @@ update_keysig_packet( PKT_signature **ret_sig, if (!rc) { hash_sigversion_to_magic (md, sig); - md_final(md); + gcry_md_final (md); rc = complete_sig( sig, sk, md ); } diff --git a/g10/skclist.c b/g10/skclist.c index 1cb69074a..afaa73814 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -176,7 +176,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, log_error(_("skipped \"%s\": %s\n"), locusr->d, g10_errstr(rc) ); } - else if( !(rc=openpgp_pk_test_algo (sk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo2 (sk->pubkey_algo, use)) ) { SK_LIST r; if( sk->version == 4 && (use & PUBKEY_USAGE_SIG) diff --git a/g10/tdbio.c b/g10/tdbio.c index 74e75b3c9..11e3bb3fd 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -94,7 +94,6 @@ static int db_fd = -1; static int in_transaction; static void open_db(void); -static void migrate_from_v2 (void); @@ -580,8 +579,6 @@ tdbio_get_dbname() static void open_db() { - byte buf[10]; - int n; TRUSTREC rec; assert( db_fd == -1 ); -- cgit v1.2.3 From 4459fcb032268d6164ce70ab750f7b6baded9bf2 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 21 Apr 2006 12:56:40 +0000 Subject: Still merging 1.4.3 code back --- common/ChangeLog | 16 +++ common/iobuf.c | 304 ++++++++++++++++++++++++++++--------------------- common/iobuf.h | 6 +- common/miscellaneous.c | 5 +- g10/exec.c | 2 +- g10/keydb.c | 6 +- g10/keylist.c | 2 +- g10/keyserver.c | 2 +- g10/mainproc.c | 4 +- g10/options.h | 2 + g10/plaintext.c | 39 ++++--- g10/seckey-cert.c | 3 +- g10/sign.c | 5 +- jnlib/ChangeLog | 5 + jnlib/stringhelp.c | 10 +- jnlib/stringhelp.h | 2 +- 16 files changed, 247 insertions(+), 166 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 54bce4538..f1b11fc57 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,19 @@ +2006-04-19 Werner Koch <wk@g10code.com> + + * iobuf.c (iobuf_get_fd): New. Taken from 1.4.3. + (iobuf_is_pipe_filename): New. + (pop_filter): Made static. + (iobuf_skip_rest): New. Orginal patch by Florian + Weimer. Added new argument PARTIAL. + (block_filter): Remove the old gpg indeterminate length mode. + (block_filter): Properly handle a partial body stream + that ends with a 5-byte length that happens to be zero. + (iobuf_set_block_mode, iobuf_in_block_mode): Removed as + superfluous. + (iobuf_get_filelength): New arg OVERFLOW. + (iobuf_get_filelength) [W32]: Use GetFileSizeEx if available + * miscellaneous.c (is_file_compressed): Take care of OVERFLOW. + 2006-04-18 Werner Koch <wk@g10code.com> * homedir.c (w32_shgetfolderpath): New. Taken from gpg 1.4.3. diff --git a/common/iobuf.c b/common/iobuf.c index 32b9e18c6..bbb666f67 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -1,5 +1,6 @@ /* iobuf.c - file handling - * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, + * 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -41,6 +42,11 @@ #include "util.h" #include "iobuf.h" +/* The size of the internal buffers. + NOTE: If you change this value you MUST also adjust the regression + test "armored_key_8192" in armor.test! */ +#define IOBUF_BUFFER_SIZE 8192 + #undef FILE_FILTER_USES_STDIO #ifdef HAVE_DOSISH_SYSTEM @@ -762,32 +768,23 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer, break; } a->size |= c; + a->partial = 2; + if (!a->size) + { + a->eof = 1; + if (!n) + rc = -1; + break; + } } else - { /* next partial body length */ + { /* Next partial body length. */ a->size = 1 << (c & 0x1f); } /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */ } else - { /* the gnupg partial length scheme - much better :-) */ - c = iobuf_get (chain); - a->size = c << 8; - c = iobuf_get (chain); - a->size |= c; - if (c == -1) - { - log_error ("block_filter: error reading length info\n"); - rc = GPG_ERR_BAD_DATA; - } - if (!a->size) - { - a->eof = 1; - if (!n) - rc = -1; - break; - } - } + BUG (); } while (!rc && size && a->size) @@ -876,39 +873,7 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer, } } else - { /* the gnupg scheme (which is not openpgp compliant) */ - size_t avail, n; - - for (p = buf; !rc && size;) - { - n = size; - avail = a->size - a->count; - if (!avail) - { - if (n > a->size) - { - iobuf_put (chain, (a->size >> 8) & 0xff); - iobuf_put (chain, a->size & 0xff); - avail = a->size; - a->count = 0; - } - else - { - iobuf_put (chain, (n >> 8) & 0xff); - iobuf_put (chain, n & 0xff); - avail = n; - a->count = a->size - n; - } - } - if (n > avail) - n = avail; - if (iobuf_write (chain, p, n)) - rc = gpg_error_from_errno (errno); - a->count += n; - p += n; - size -= n; - } - } + BUG (); } else if (control == IOBUFCTRL_INIT) { @@ -976,10 +941,7 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer, a->buflen = 0; } else - { - iobuf_writebyte (chain, 0); - iobuf_writebyte (chain, 0); - } + BUG (); } else if (a->size) { @@ -1159,11 +1121,10 @@ iobuf_enable_special_filenames (int yes) special_names_enabled = yes; } -/* - * see whether the filename has the for "-&nnnn", where n is a - * non-zero number. - * Returns this number or -1 if it is not the case. - */ + +/* See whether the filename has the form "-&nnnn", where n is a + non-zero number. Returns this number or -1 if it is not the + case. */ static int check_special_filename (const char *fname) { @@ -1180,6 +1141,17 @@ check_special_filename (const char *fname) return -1; } + +/* This fucntion returns true if FNAME indicates a PIPE (stdout or + stderr) or a special file name if those are enabled. */ +int +iobuf_is_pipe_filename (const char *fname) +{ + if (!fname || (*fname=='-' && !fname[1]) ) + return 1; + return check_special_filename (fname) != -1; +} + /**************** * Create a head iobuf for reading from a file * returns: NULL if an error occures and sets errno @@ -1547,7 +1519,7 @@ iobuf_push_filter2 (iobuf_t a, /**************** * Remove an i/o filter. */ -int +static int pop_filter (iobuf_t a, int (*f) (void *opaque, int control, iobuf_t chain, byte * buf, size_t * len), void *ov) @@ -2038,49 +2010,110 @@ iobuf_set_limit (iobuf_t a, off_t nlimit) -/**************** - * Return the length of an open file - */ +/* Return the length of an open file A. IF OVERFLOW is not NULL it + will be set to true if the file is larger than what off_t can cope + with. The function return 0 on error or on overflow condition. */ off_t -iobuf_get_filelength (iobuf_t a) +iobuf_get_filelength (iobuf_t a, int *overflow) { - struct stat st; + struct stat st; - if (a->directfp) - { - FILE *fp = a->directfp; + if (overflow) + *overflow = 0; - if (!fstat (fileno (fp), &st)) - return st.st_size; - log_error ("fstat() failed: %s\n", strerror (errno)); - return 0; + if( a->directfp ) { + FILE *fp = a->directfp; + + if( !fstat(fileno(fp), &st) ) + return st.st_size; + log_error("fstat() failed: %s\n", strerror(errno) ); + return 0; } - /* Hmmm: file_filter may have already been removed */ - for (; a; a = a->chain) - if (!a->chain && a->filter == file_filter) - { - file_filter_ctx_t *b = a->filter_ov; - FILEP_OR_FD fp = b->fp; + /* Hmmm: file_filter may have already been removed */ + for( ; a; a = a->chain ) + if( !a->chain && a->filter == file_filter ) { + file_filter_ctx_t *b = a->filter_ov; + FILEP_OR_FD fp = b->fp; #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO) - ulong size; - - if ((size = GetFileSize (fp, NULL)) != 0xffffffff) - return size; - log_error ("GetFileSize for handle %p failed: ec=%d\n", - fp, (int) GetLastError ()); + ulong size; + static int (* __stdcall get_file_size_ex) + (void *handle, LARGE_INTEGER *size); + static int get_file_size_ex_initialized; + + if (!get_file_size_ex_initialized) + { + void *handle; + + handle = dlopen ("kernel32.dll", RTLD_LAZY); + if (handle) + { + get_file_size_ex = dlsym (handle, "GetFileSizeEx"); + if (!get_file_size_ex) + dlclose (handle); + } + get_file_size_ex_initialized = 1; + } + + if (get_file_size_ex) + { + /* This is a newer system with GetFileSizeEx; we use + this then becuase it seem that GetFileSize won't + return a proper error in case a file is larger than + 4GB. */ + LARGE_INTEGER size; + + if (get_file_size_ex (fp, &size)) + { + if (!size.u.HighPart) + return size.u.LowPart; + if (overflow) + *overflow = 1; + return 0; + } + } + else + { + if ((size=GetFileSize (fp, NULL)) != 0xffffffff) + return size; + } + log_error ("GetFileSize for handle %p failed: %s\n", + fp, w32_strerror (0)); #else - if (!fstat (my_fileno (fp), &st)) - return st.st_size; - log_error ("fstat() failed: %s\n", strerror (errno)); + if( !fstat(my_fileno(fp), &st) ) + return st.st_size; + log_error("fstat() failed: %s\n", strerror(errno) ); #endif - break; + break; + } + + return 0; +} + + +/* Return the file descriptor of the underlying file or -1 if it is + not available. */ +int +iobuf_get_fd (iobuf_t a) +{ + if (a->directfp) + return fileno ( (FILE*)a->directfp ); + + for ( ; a; a = a->chain ) + if (!a->chain && a->filter == file_filter) + { + file_filter_ctx_t *b = a->filter_ov; + FILEP_OR_FD fp = b->fp; + + return my_fileno (fp); } - return 0; + return -1; } + + /**************** * Tell the file position, where the next read will take place */ @@ -2233,30 +2266,6 @@ iobuf_get_fname (iobuf_t a) return NULL; } -/**************** - * Start the block write mode, see rfc1991.new for details. - * A value of 0 for N stops this mode (flushes and writes - * the end marker) - */ -void -iobuf_set_block_mode (iobuf_t a, size_t n) -{ - block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx); - - assert (a->use == 1 || a->use == 2); - ctx->use = a->use; - if (!n) - { - if (a->use == 1) - log_debug ("pop_filter called in set_block_mode - please report\n"); - pop_filter (a, block_filter, NULL); - } - else - { - ctx->size = n; /* only needed for use 2 */ - iobuf_push_filter (a, block_filter, ctx); - } -} /**************** * enable partial block mode as described in the OpenPGP draft. @@ -2286,18 +2295,6 @@ iobuf_set_partial_block_mode (iobuf_t a, size_t len) } -/**************** - * Checks whether the stream is in block mode - * Note: This does not work if other filters are pushed on the stream. - */ -int -iobuf_in_block_mode (iobuf_t a) -{ - if (a && a->filter == block_filter) - return 1; /* yes */ - return 0; /* no */ -} - /**************** * Same as fgets() but if the buffer is too short a larger one will @@ -2416,3 +2413,54 @@ translate_file_handle (int fd, int for_write) #endif return fd; } + + +void +iobuf_skip_rest (iobuf_t a, unsigned long n, int partial) +{ + if ( partial ) + { + for (;;) + { + if (a->nofast || a->d.start >= a->d.len) + { + if (iobuf_readbyte (a) == -1) + { + break; + } + } + else + { + unsigned long count = a->d.len - a->d.start; + a->nbytes += count; + a->d.start = a->d.len; + } + } + } + else + { + unsigned long remaining = n; + while (remaining > 0) + { + if (a->nofast || a->d.start >= a->d.len) + { + if (iobuf_readbyte (a) == -1) + { + break; + } + --remaining; + } + else + { + unsigned long count = a->d.len - a->d.start; + if (count > remaining) + { + count = remaining; + } + a->nbytes += count; + a->d.start += count; + remaining -= count; + } + } + } +} diff --git a/common/iobuf.h b/common/iobuf.h index def0a6506..431d573a1 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -90,6 +90,7 @@ struct iobuf_struct EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode; void iobuf_enable_special_filenames (int yes); +int iobuf_is_pipe_filename (const char *fname); 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); @@ -134,14 +135,13 @@ 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); +off_t iobuf_get_filelength (iobuf_t a, int *overflow); #define IOBUF_FILELENGTH_LIMIT 0xffffffff +int iobuf_get_fd (iobuf_t a); 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); diff --git a/common/miscellaneous.c b/common/miscellaneous.c index d81213ef9..14d6f020d 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -81,6 +81,7 @@ is_file_compressed (const char *s, int *ret_rc) iobuf_t a; byte buf[4]; int i, rc = 0; + int overflow; struct magic_compress_s { size_t len; @@ -91,7 +92,7 @@ is_file_compressed (const char *s, int *ret_rc) { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */ }; - if ( !s || (*s == '-' && !s[1]) || !ret_rc ) + if ( iobuf_is_pipe_filename (s) || !ret_rc ) return 0; /* We can't check stdin or no file was given */ a = iobuf_open( s ); @@ -100,7 +101,7 @@ is_file_compressed (const char *s, int *ret_rc) return 0; } - if ( iobuf_get_filelength( a ) < 4 ) { + if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) { *ret_rc = 0; goto leave; } diff --git a/g10/exec.c b/g10/exec.c index cdc86e16b..6938a409a 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -473,9 +473,9 @@ int exec_write(struct exec_info **info,const char *program, (*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)); - ret=G10ERR_WRITE_FILE; goto fail; } diff --git a/g10/keydb.c b/g10/keydb.c index dbad8435a..b3595cf36 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -134,9 +134,9 @@ maybe_create_keyring (char *filename, int force) log_info ("can't allocate lock for `%s'\n", filename ); if (!force) - return G10ERR_OPEN_FILE; + return gpg_error (GPG_ERR_ENOENT); else - return G10ERR_GENERAL; + return gpg_error (GPG_ERR_GENERAL); } if ( make_dotlock (lockhd, -1) ) @@ -166,9 +166,9 @@ maybe_create_keyring (char *filename, int force) umask (oldmask); if (!iobuf) { + rc = gpg_error_from_errno (errno); log_error ( _("error creating keyring `%s': %s\n"), filename, strerror(errno)); - rc = G10ERR_OPEN_FILE; goto leave; } diff --git a/g10/keylist.c b/g10/keylist.c index 0b1a51b6d..441606299 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1310,7 +1310,7 @@ list_keyblock_colon( KBNODE keyblock, int secret, int fpr ) case 0: sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: - case Gpg_Err_UNUSABLE_PUBKEY: sigrc = '?'; break; + case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; default: sigrc = '%'; break; } diff --git a/g10/keyserver.c b/g10/keyserver.c index 4fd90d08b..3e72b2820 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -31,13 +31,13 @@ #endif #include "gpg.h" +#include "iobuf.h" #include "filter.h" #include "keydb.h" #include "status.h" #include "exec.h" #include "main.h" #include "i18n.h" -#include "iobuf.h" #include "ttyio.h" #include "options.h" #include "packet.h" diff --git a/g10/mainproc.c b/g10/mainproc.c index 8e9b3ab65..27989d3b2 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -647,7 +647,7 @@ proc_plaintext( CTX c, PACKET *pkt ) else if(n->pkt->pkttype==PKT_SIGNATURE) { /* For the SIG+LITERAL case that PGP used to use. */ - md_enable( c->mfx.md, n->pkt->pkt.signature->digest_algo ); + gcry_md_enable ( c->mfx.md, n->pkt->pkt.signature->digest_algo ); any=1; } } @@ -2010,7 +2010,7 @@ proc_tree( CTX c, KBNODE node ) && is_RSA( sig->pubkey_algo ) ) { /* enable a workaround for a pgp2 bug */ if (gcry_md_open (&c->mfx.md2, DIGEST_ALGO_MD5, 0)) - BUG (): + BUG (); } else if( sig->digest_algo == DIGEST_ALGO_SHA1 && sig->pubkey_algo == PUBKEY_ALGO_DSA diff --git a/g10/options.h b/g10/options.h index 7e9d0261c..f61cd4c9e 100644 --- a/g10/options.h +++ b/g10/options.h @@ -262,6 +262,7 @@ struct { #define DBG_CARD_IO_VALUE 2048 /* debug smart card I/O. */ #define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) +#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE) #define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) #define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) @@ -304,6 +305,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; #define EXPORT_RESET_SUBKEY_PASSWD (1<<3) #define EXPORT_MINIMAL (1<<4) #define EXPORT_CLEAN (1<<5) +#define EXPORT_SEXP_FORMAT (1<<6) #define LIST_SHOW_PHOTOS (1<<0) #define LIST_SHOW_POLICY_URLS (1<<1) diff --git a/g10/plaintext.c b/g10/plaintext.c index 1f8c5759f..2ae851e30 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -133,13 +133,13 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, else if (is_secured_filename (fname)) { errno = EPERM; + rc = gpg_error_from_errno (errno); log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - rc = G10ERR_CREATE_FILE; goto leave; } else if( !(fp = fopen(fname,"wb")) ) { + rc = gpg_error_from_errno (errno); log_error(_("error creating `%s': %s\n"), fname, strerror(errno) ); - rc = G10ERR_CREATE_FILE; goto leave; } #else /* __riscos__ */ @@ -205,7 +205,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { log_error ("error writing to `%s': %s\n", fname,"exceeded --max-output limit\n"); - rc = gpg_error (GPG_ERR_GENERAL); + rc = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } else if( putc( c, fp ) == EOF ) @@ -239,17 +239,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { if(opt.max_output && (count+=len)>opt.max_output) { - log_error("Error writing to `%s': %s\n", - fname,"exceeded --max-output limit\n"); - rc = G10ERR_WRITE_FILE; + log_error ("error writing to `%s': %s\n", + fname,"exceeded --max-output limit\n"); + rc = gpg_error (GPG_ERR_TOO_LARGE); xfree( buffer ); goto leave; } else if( fwrite( buffer, 1, len, fp ) != len ) { - log_error("Error writing to `%s': %s\n", - fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; + rc = gpg_error_from_errno (errno); + log_error ("error writing to `%s': %s\n", + fname, strerror(errno) ); xfree( buffer ); goto leave; } @@ -274,14 +274,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { log_error("Error writing to `%s': %s\n", fname,"exceeded --max-output limit\n"); - rc = G10ERR_WRITE_FILE; + rc = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } else if( putc( c, fp ) == EOF ) { + if ( ferror (fp ) ) + rc = gpg_error_from_errno (errno); + else + rc = gpg_error (GPG_ERR_EOF); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; goto leave; } } @@ -310,7 +313,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { log_error("Error writing to `%s': %s\n", fname,"exceeded --max-output limit\n"); - rc = G10ERR_WRITE_FILE; + rc = gpg_error (GPG_ERR_TOO_LARGE); xfree( buffer ); goto leave; } @@ -337,7 +340,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { log_error("Error writing to `%s': %s\n", fname,"exceeded --max-output limit\n"); - rc = G10ERR_WRITE_FILE; + rc = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } else if( putc( c, fp ) == EOF ) @@ -351,8 +354,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, if( !mfx->md ) continue; if( state == 2 ) { - md_putc(mfx->md, '\r' ); - md_putc(mfx->md, '\n' ); + gcry_md_putc (mfx->md, '\r' ); + gcry_md_putc (mfx->md, '\n' ); state = 0; } if( !state ) { @@ -361,18 +364,18 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, else if( c == '\n' ) state = 2; else - md_putc(mfx->md, c ); + gcry_md_putc(mfx->md, c ); } else if( state == 1 ) { if( c == '\n' ) state = 2; else { - md_putc(mfx->md, '\r' ); + gcry_md_putc(mfx->md, '\r' ); if( c == '\r' ) state = 1; else { state = 0; - md_putc(mfx->md, c ); + gcry_md_putc(mfx->md, c ); } } } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index acb2cdada..ad5b75603 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -294,7 +294,8 @@ check_secret_key( PKT_secret_key *sk, int n ) log_info (_("%s ...\n"), _(tryagain)); } rc = do_check( sk, tryagain, mode, &canceled ); - if ( gpg_err_code (rc) == G10ERR_BAD_PASS && is_status_enabled () ) { + if ( gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE + && is_status_enabled () ) { u32 kid[2]; char buf[50]; diff --git a/g10/sign.c b/g10/sign.c index 3553079d6..9bb35c898 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -656,7 +656,8 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash, sig->expiredate = sig->timestamp+duration; sig->sig_class = sigclass; - md = gcry_md_copy (hash); + if (gcry_md_copy (&md, hash)) + BUG (); if (sig->version >= 4) build_sig_subpkt_from_sig (sig); @@ -938,9 +939,9 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } if( !inp ) { + rc = gpg_error_from_errno (errno); log_error(_("can't open `%s': %s\n"), sl->d,strerror(errno)); - rc = G10ERR_OPEN_FILE; goto leave; } handle_progress (&pfx, inp, sl->d); diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 32549d136..8816068b0 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,8 @@ +2006-04-20 Werner Koch <wk@g10code.com> + + * stringhelp.c (make_basename): New arg INPUTPATH for future + riscos compatibility. + 2006-04-18 Werner Koch <wk@g10code.com> * libjnlib-config.h (JNLIB_NEED_UTF8CONF): Defined. diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 760398b0c..e999170dd 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -234,15 +234,19 @@ length_sans_trailing_ws (const unsigned char *line, size_t len) * */ char * -make_basename(const char *filepath) +make_basename(const char *filepath, const char *inputpath) { char *p; +#ifdef __riscos__ + return riscos_make_basename(filepath, inputpath); +#endif + if ( !(p=strrchr(filepath, '/')) ) - #ifdef HAVE_DRIVE_LETTERS +#ifdef HAVE_DRIVE_LETTERS if ( !(p=strrchr(filepath, '\\')) ) if ( !(p=strrchr(filepath, ':')) ) - #endif +#endif { return jnlib_xstrdup(filepath); } diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index bdd7d561c..4c9e66452 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -35,7 +35,7 @@ size_t length_sans_trailing_chars (const unsigned char *line, size_t len, size_t length_sans_trailing_ws (const unsigned char *line, size_t len); -char *make_basename(const char *filepath); +char *make_basename(const char *filepath, const char *inputpath); char *make_dirname(const char *filepath); char *make_filename( const char *first_part, ... ); int compare_filenames( const char *a, const char *b ); -- cgit v1.2.3 From 00ffc478de4940b9fbbb9f488f545a65ca7d1278 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 28 Apr 2006 14:31:29 +0000 Subject: Merged recent changes from 1.4 --- g10/ChangeLog | 56 ++++++++++++++++++++++++++ g10/armor.c | 24 ++++++----- g10/encode.c | 22 ++-------- g10/getkey.c | 8 ++-- g10/gpg.c | 41 ++++++++++++++++--- g10/keyedit.c | 47 ++++++++++++++-------- g10/keygen.c | 10 ++--- g10/keyserver.c | 64 +++++++++++++---------------- g10/main.h | 1 + g10/mainproc.c | 6 +-- g10/options.h | 5 ++- g10/pkclist.c | 20 +++++++-- g10/plaintext.c | 55 +++++++++++++++++++++---- g10/sign.c | 123 +++++++++++++++++++++++++++++++++++++++----------------- g10/status.c | 7 ++-- 15 files changed, 341 insertions(+), 148 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 6259bdc20..b8f789e8b 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,59 @@ +2006-04-28 David Shaw <dshaw@jabberwocky.com> (wk) + + * keyserver.c (direct_uri_map): New. + (keyserver_spawn): Used here to add "_uri" to certain gpgkeys_xxx + helpers when the meaning is different if a path is provided (i.e. + ldap). + (keyserver_import_cert): Show warning if there is a CERT + fingerprint, but no --keyserver set. + + * keyserver.c: Fix build problem with platforms that stick libcurl + in a place not in the regular include search path. + + * options.h, gpg.c (main): Add --enable-dsa2 and --disable-dsa2. + Defaults to disable. + + * pkclist.c (algo_available): If --enable-dsa2 is set, we're + allowed to truncate hashes to fit DSA keys. + + * sign.c (match_dsa_hash): New. Return the best match hash for a + given q size. + (do_sign, hash_for, sign_file): When signing with a DSA key, if it + has q==160, assume it is an old DSA key and don't allow truncation + unless --enable-dsa2 is also set. q!=160 always allows truncation + since they must be DSA2 keys. + (make_keysig_packet): If the user doesn't specify a + --cert-digest-algo, use match_dsa_hash to pick the best hash for + key signatures. + + * gpg.c (print_mds): Add SHA-224. + * armor.c (armor_filter, parse_hash_header): Add SHA-224. + + * sign.c (write_plaintext_packet): + Factor common literal packet setup code from here, to... + * encode.c (encode_simple): .. there. + + * main.h, plaintext.c (setup_plaintext_name): Here. New. Make sure + the literal packet filename field is UTF-8 encoded. + + * options.h, gpg.c (main): Make sure --set-filename is UTF-8 + encoded and note when filenames are already UTF-8. + + * keyedit.c (menu_backsign): Give some more verbose errors when we + have no need to backsign. + + * getkey.c (parse_auto_key_locate): Fix dupe-removal code. + + * keyedit.c (menu_backsign): Allow backsigning even if the secret + subkey doesn't have a binding signature. + + * armor.c (radix64_read): Don't report EOF when reading only a pad + (=) character. The EOF actually starts after the pad. + + * gpg.c (main): Make --export, --send-keys, --recv-keys, + --refresh-keys, and --fetch-keys follow their arguments from left + to right. Suggested by Peter Palfrader. + 2006-04-18 Werner Koch <wk@g10code.com> * tdbio.c (open_db, migrate_from_v2): Removed feature to migration diff --git a/g10/armor.c b/g10/armor.c index a154c5cfe..e02591372 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -1,6 +1,6 @@ /* armor.c - Armor flter - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -242,12 +242,14 @@ parse_hash_header( const char *line ) found |= 2; else if( !strncmp( s, "MD5", s2-s ) ) found |= 4; - else if( !strncmp( s, "SHA256", s2-s ) ) + else if( !strncmp( s, "SHA224", s2-s ) ) found |= 8; - else if( !strncmp( s, "SHA384", s2-s ) ) + else if( !strncmp( s, "SHA256", s2-s ) ) found |= 16; - else if( !strncmp( s, "SHA512", s2-s ) ) + else if( !strncmp( s, "SHA384", s2-s ) ) found |= 32; + else if( !strncmp( s, "SHA512", s2-s ) ) + found |= 64; else return 0; for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ ) @@ -676,7 +678,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, int checkcrc=0; int rc = 0; size_t n = 0; - int idx, i; + int idx, i, onlypad=0; u32 crc; crc = afx->crc; @@ -720,6 +722,8 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, goto again; } } + else if(n==0) + onlypad=1; if( idx == 1 ) buf[n++] = val; @@ -848,7 +852,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, } } - if( !n ) + if( !n && !onlypad ) rc = -1; *retn = n; @@ -951,10 +955,12 @@ armor_filter( void *opaque, int control, if( hashes & 4 ) buf[n++] = DIGEST_ALGO_MD5; if( hashes & 8 ) - buf[n++] = DIGEST_ALGO_SHA256; + buf[n++] = DIGEST_ALGO_SHA224; if( hashes & 16 ) - buf[n++] = DIGEST_ALGO_SHA384; + buf[n++] = DIGEST_ALGO_SHA256; if( hashes & 32 ) + buf[n++] = DIGEST_ALGO_SHA384; + if( hashes & 64 ) buf[n++] = DIGEST_ALGO_SHA512; buf[1] = n - 2; diff --git a/g10/encode.c b/g10/encode.c index bb3e7bbc2..292e2bc5a 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -1,6 +1,6 @@ /* encode.c - encode data - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -278,22 +278,8 @@ encode_simple( const char *filename, int mode, int use_seskey ) 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, - 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 (!opt.no_literal) + pt=setup_plaintext_name(filename,inp); /* Note that PGP 5 has problems decrypting symmetrically encrypted data if the file length is in the inner packet. It works when diff --git a/g10/getkey.c b/g10/getkey.c index acd992c21..bff2a0ddc 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -2948,7 +2948,7 @@ parse_auto_key_locate(char *options) while((tok=optsep(&options))) { - struct akl *akl,*last; + struct akl *akl,*check,*last=NULL; int dupe=0; if(tok[0]=='\0') @@ -2977,13 +2977,13 @@ parse_auto_key_locate(char *options) } /* We must maintain the order the user gave us */ - for(last=opt.auto_key_locate;last && last->next;last=last->next) + for(check=opt.auto_key_locate;check;last=check,check=check->next) { /* Check for duplicates */ - if(last && last->type==akl->type + if(check->type==akl->type && (akl->type!=AKL_SPEC || (akl->type==AKL_SPEC - && strcmp(last->spec->uri,akl->spec->uri)==0))) + && strcmp(check->spec->uri,akl->spec->uri)==0))) { dupe=1; free_akl(akl); diff --git a/g10/gpg.c b/g10/gpg.c index 49687fff1..25b55b705 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -354,6 +354,8 @@ enum cmd_and_opt_values oAutoKeyLocate, oNoAutoKeyLocate, oAllowMultisigVerification, + oEnableDSA2, + oDisableDSA2, oNoop }; @@ -684,6 +686,8 @@ static ARGPARSE_OPTS opts[] = { { oLimitCardInsertTries, "limit-card-insert-tries", 1, "@"}, { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"}, + { oEnableDSA2, "enable-dsa2", 0, "@"}, + { oDisableDSA2, "disable-dsa2", 0, "@"}, /* These two are aliases to help users of the PGP command line product use gpg with minimal pain. Many commands are common @@ -2169,7 +2173,12 @@ main (int argc, char **argv ) case oCompressSigs: opt.compress_sigs = 1; break; case oRFC2440Text: opt.rfc2440_text=1; break; case oNoRFC2440Text: opt.rfc2440_text=0; break; - case oSetFilename: opt.set_filename = pargs.r.ret_str; break; + case oSetFilename: + if(utf8_strings) + opt.set_filename = pargs.r.ret_str; + else + opt.set_filename = native_to_utf8(pargs.r.ret_str); + break; case oForYourEyesOnly: eyes_only = 1; break; case oNoForYourEyesOnly: eyes_only = 0; break; case oSetPolicyURL: @@ -2195,8 +2204,12 @@ main (int argc, char **argv ) opt.verify_options&=~VERIFY_SHOW_POLICY_URLS; break; case oSigKeyserverURL: add_keyserver_url(pargs.r.ret_str,0); break; - case oUseEmbeddedFilename: opt.use_embedded_filename = 1; break; - case oNoUseEmbeddedFilename: opt.use_embedded_filename = 0; break; + case oUseEmbeddedFilename: + opt.flags.use_embedded_filename=1; + break; + case oNoUseEmbeddedFilename: + opt.flags.use_embedded_filename=0; + break; case oComment: if(pargs.r.ret_str[0]) append_to_strlist(&opt.comments,pargs.r.ret_str); @@ -2639,6 +2652,9 @@ main (int argc, char **argv ) opt.allow_multisig_verification = 1; break; + case oEnableDSA2: opt.flags.dsa2=1; break; + case oDisableDSA2: opt.flags.dsa2=0; break; + case oNoop: break; default : pargs.err = configfp? 1:2; break; @@ -3086,6 +3102,9 @@ main (int argc, char **argv ) fname = argc? *argv : NULL; + if(fname && utf8_strings) + opt.flags.utf8_filename=1; + switch( cmd ) { case aPrimegen: case aPrintMD: @@ -3390,12 +3409,17 @@ main (int argc, char **argv ) import_keys( argc? argv:NULL, argc, NULL, opt.import_options ); break; + /* TODO: There are a number of command that use this same + "make strlist, call function, report error, free strlist" + pattern. Join them together here and avoid all that + duplicated code. */ + case aExport: case aSendKeys: case aRecvKeys: sl = NULL; for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); + append_to_strlist2( &sl, *argv, utf8_strings ); if( cmd == aSendKeys ) rc=keyserver_export( sl ); else if( cmd == aRecvKeys ) @@ -3427,7 +3451,7 @@ main (int argc, char **argv ) case aRefreshKeys: sl = NULL; for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); + append_to_strlist2( &sl, *argv, utf8_strings ); rc=keyserver_refresh(sl); if(rc) log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc)); @@ -3437,7 +3461,7 @@ main (int argc, char **argv ) case aFetchKeys: sl = NULL; for( ; argc; argc--, argv++ ) - add_to_strlist2( &sl, *argv, utf8_strings ); + append_to_strlist2( &sl, *argv, utf8_strings ); rc=keyserver_fetch(sl); if(rc) log_error("key fetch failed: %s\n",g10_errstr(rc)); @@ -3913,6 +3937,7 @@ print_mds( const char *fname, int algo ) gcry_md_enable (md, GCRY_MD_SHA1); gcry_md_enable (md, GCRY_MD_RMD160); #ifdef USE_SHA256 + gcry_md_enable (md, DIGEST_ALGO_SHA224); gcry_md_enable (md, GCRY_MD_SHA256); #endif #ifdef USE_SHA512 @@ -3935,6 +3960,8 @@ print_mds( const char *fname, int algo ) print_hashline( md, GCRY_MD_SHA1, fname ); print_hashline( md, GCRY_MD_RMD160, fname ); #ifdef USE_SHA256 + if (!gcry_md_test_algo (DIGEST_ALGO_SHA224) + print_hashline (md, DIGEST_ALGO_SHA224, fname); print_hashline( md, GCRY_MD_SHA256, fname ); #endif #ifdef USE_SHA512 @@ -3951,6 +3978,8 @@ print_mds( const char *fname, int algo ) print_hex( md, GCRY_MD_SHA1, fname ); print_hex( md, GCRY_MD_RMD160, fname ); #ifdef USE_SHA256 + if (!gcry_md_test_algo (DIGEST_ALGO_SHA224) + print_hex (md, DIGEST_ALGO_SHA224, fname); print_hex( md, GCRY_MD_SHA256, fname ); #endif #ifdef USE_SHA512 diff --git a/g10/keyedit.c b/g10/keyedit.c index bfe3f8546..80d714adc 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -3661,10 +3661,21 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock) } /* Find a signing subkey with no backsig */ - if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY - && (node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG) - && !node->pkt->pkt.public_key->backsig) - sub_pk=node->pkt->pkt.public_key; + if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY) + { + if(node->pkt->pkt.public_key->pubkey_usage&PUBKEY_USAGE_SIG) + { + if(node->pkt->pkt.public_key->backsig) + tty_printf(_("signing subkey %s is already cross-certified\n"), + keystr_from_pk(node->pkt->pkt.public_key)); + else + sub_pk=node->pkt->pkt.public_key; + } + else + tty_printf(_("subkey %s does not sign and so does" + " not need to be cross-certified\n"), + keystr_from_pk(node->pkt->pkt.public_key)); + } if(!sub_pk) continue; @@ -3693,7 +3704,11 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock) } if(!sub_sk) - continue; + { + tty_printf(_("no secret subkey for public subkey %s - ignoring\n"), + keystr_from_pk(sub_pk)); + continue; + } /* Now finally find the matching selfsig on the secret subkey. We can't use chosen_selfsig here (it's not set for secret @@ -3712,11 +3727,8 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock) break; } - if(!sig_sk) - continue; - /* Now we can get to work. We have a main key and secret part, - a signing subkey with signature and secret part with + a signing subkey with signature and secret part possibly with signature. */ passphrase=get_last_passphrase(); @@ -3745,13 +3757,16 @@ menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock) xfree(sig_pk->pkt); sig_pk->pkt=newpkt; - /* Put the new sig into place on the seckey */ - newpkt=xmalloc_clear(sizeof(*newpkt)); - newpkt->pkttype=PKT_SIGNATURE; - newpkt->pkt.signature=copy_signature(NULL,newsig); - free_packet(sig_sk->pkt); - xfree(sig_sk->pkt); - sig_sk->pkt=newpkt; + if(sig_sk) + { + /* Put the new sig into place on the seckey */ + newpkt=xmalloc_clear(sizeof(*newpkt)); + newpkt->pkttype=PKT_SIGNATURE; + newpkt->pkt.signature=copy_signature(NULL,newsig); + free_packet(sig_sk->pkt); + xfree(sig_sk->pkt); + sig_sk->pkt=newpkt; + } modified=1; } diff --git a/g10/keygen.c b/g10/keygen.c index 32c09a97d..c7a97a0fc 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -341,7 +341,7 @@ keygen_set_std_prefs (const char *string,int personal) /* SHA-1 */ strcat(dummy_string,"H2 "); - if(!check_digest_algo(DIGEST_ALGO_SHA256)) + if (!openpgp_md_test_algo(DIGEST_ALGO_SHA256)) strcat(dummy_string,"H8 "); /* RIPEMD160 */ @@ -370,12 +370,12 @@ keygen_set_std_prefs (const char *string,int personal) while((tok=strsep(&prefstring," ,"))) { - if((val=openpgp_cipher_map_name (tok))) + if((val=gcry_cipher_map_name (tok))) { if(set_one_pref(val,1,tok,sym,&nsym)) rc=-1; } - else if((val=openpgp_md_map_name (tok))) + else if((val=gcry_md_map_name (tok))) { if(set_one_pref(val,2,tok,hash,&nhash)) rc=-1; @@ -2138,7 +2138,7 @@ get_parameter_algo( struct para_data_s *para, enum para_name key ) if( digitp( r->u.value ) ) i = atoi( r->u.value ); else - i = openpgp_pk_map_name (r->u.value); + i = gcry_pk_map_name (r->u.value); if (i == PUBKEY_ALGO_RSA_E || i == PUBKEY_ALGO_RSA_S) i = 0; /* we don't want to allow generation of these algorithms */ return i; @@ -2289,7 +2289,7 @@ proc_parameter_file( struct para_data_s *para, const char *fname, if(r) { algo=get_parameter_algo(para,pKEYTYPE); - if (openpgp_pk_test_algo (algo, PUBKEY_USAGE_SIG)) + if (openpgp_pk_test_algo2 (algo, PUBKEY_USAGE_SIG)) { log_error("%s:%d: invalid algorithm\n", fname, r->lnr ); return -1; diff --git a/g10/keyserver.c b/g10/keyserver.c index 3e72b2820..3127a4795 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -26,9 +26,7 @@ #include <string.h> #include <stdlib.h> #include <assert.h> -#ifdef HAVE_LIBCURL -#include <curl/curl.h> -#endif +#include <errno.h> #include "gpg.h" #include "iobuf.h" @@ -45,18 +43,6 @@ #include "keyserver-internal.h" #include "util.h" -#define GPGKEYS_PREFIX "gpgkeys_" - -#if defined(HAVE_LIBCURL) || defined(FAKE_CURL) -#define GPGKEYS_CURL "gpgkeys_curl" -#endif - -#ifdef GPGKEYS_CURL -#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_PREFIX)+strlen(GPGKEYS_CURL)) -#else -#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_PREFIX)) -#endif - struct keyrec { KEYDB_SEARCH_DESC desc; @@ -419,7 +405,7 @@ parse_keyserver_uri(const char *string,int require_scheme, else keyserver->path=xstrdup("/"); - if(keyserver->path[1]!='\0') + if(keyserver->path[1]) keyserver->flags.direct_uri=1; } else if(uri[0]!='/') @@ -941,19 +927,20 @@ keyserver_typemap(const char *type) return type; } -#ifdef GPGKEYS_CURL /* The PGP LDAP and the curl fetch-a-LDAP-object methodologies are sufficiently different that we can't use curl to do LDAP. */ static int -curl_cant_handle(const char *scheme,unsigned int direct_uri) +direct_uri_map(const char *scheme,unsigned int is_direct) { - if(!direct_uri && (strcmp(scheme,"ldap")==0 || strcmp(scheme,"ldaps")==0)) + if(is_direct && strcmp(scheme,"ldap")==0) return 1; return 0; } -#endif +#define GPGKEYS_PREFIX "gpgkeys_" +#define GPGKEYS_CURL GPGKEYS_PREFIX "curl" EXEEXT +#define GPGKEYS_PREFIX_LEN (strlen(GPGKEYS_CURL)) #define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" @@ -1021,19 +1008,29 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc, end=command+strlen(command); + /* Build a path for the keyserver helper. If it is direct_uri + (i.e. an object fetch and not a keyserver), then add "_uri" to + the end to distinguish the keyserver helper from an object + fetcher that can speak that protocol (this is a problem for + LDAP). */ + strcat(command,GPGKEYS_PREFIX); strcat(command,scheme); - if(keyserver->flags.direct_uri) - strcat(command,"uri"); + /* This "_uri" thing is in case we need to call a direct handler + instead of the keyserver handler. This lets us use gpgkeys_curl + or gpgkeys_ldap_uri (we don't provide it, but a user might) + instead of gpgkeys_ldap to fetch things like + ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560 */ + + if(direct_uri_map(scheme,keyserver->flags.direct_uri)) + strcat(command,"_uri"); strcat(command,EXEEXT); -#ifdef GPGKEYS_CURL - if(!curl_cant_handle(scheme,keyserver->flags.direct_uri) - && path_access(command,X_OK)!=0) + /* Can we execute it? If not, try curl as our catchall. */ + if(path_access(command,X_OK)!=0) strcpy(end,GPGKEYS_CURL); -#endif if(opt.keyserver_options.options&KEYSERVER_USE_TEMP_FILES) { @@ -1950,15 +1947,6 @@ keyserver_fetch(STRLIST urilist) { int rc; - /* - Set the direct_uri flag so we know later to call a direct - handler instead of the keyserver style. This lets us use - gpgkeys_curl or gpgkeys_ldapuri instead of gpgkeys_ldap to - fetch things like - ldap://keyserver.pgp.com/o=PGP%20keys?pgpkey?sub?pgpkeyid=99242560 - */ - spec->flags.direct_uri=1; - rc=keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,spec); if(rc) log_info (_("WARNING: unable to fetch URI %s: %s\n"), @@ -2038,6 +2026,12 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len) rc=keyserver_import_fprint(*fpr,*fpr_len,opt.keyserver); } + else + log_info(_("no keyserver known (use option --keyserver)\n")); + + /* Give a better string here? "CERT fingerprint for \"%s\" + found, but no keyserver" " known (use option + --keyserver)\n" ? */ xfree(url); } diff --git a/g10/main.h b/g10/main.h index fd306a467..cd6926b69 100644 --- a/g10/main.h +++ b/g10/main.h @@ -282,6 +282,7 @@ void decrypt_messages(int nfiles, char *files[]); /*-- plaintext.c --*/ int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files, const char *sigfilename, int textmode ); +PKT_plaintext *setup_plaintext_name(const char *filename,IOBUF iobuf); /*-- signal.c --*/ void init_signals(void); diff --git a/g10/mainproc.c b/g10/mainproc.c index 27989d3b2..1f91c8ca6 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -659,9 +659,9 @@ proc_plaintext( CTX c, PACKET *pkt ) often. There is no good way to specify what algorithms to use in that case, so these three are the historical answer. */ - md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); - md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); - md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); + gcry_md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); + gcry_md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); + gcry_md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); } if( opt.pgp2_workarounds && only_md5 && !opt.skip_verify ) { /* This is a kludge to work around a bug in pgp2. It does only diff --git a/g10/options.h b/g10/options.h index f61cd4c9e..de5fa7920 100644 --- a/g10/options.h +++ b/g10/options.h @@ -170,7 +170,6 @@ struct STRLIST sig_keyserver_url; STRLIST cert_subpackets; STRLIST sig_subpackets; - int use_embedded_filename; int allow_non_selfsigned_uid; int allow_freeform_uid; int no_literal; @@ -222,6 +221,10 @@ struct made by signing subkeys. If not set, a missing backsig is not an error (but an invalid backsig still is). */ unsigned int require_cross_cert:1; + + unsigned int use_embedded_filename:1; + unsigned int utf8_filename:1; + unsigned int dsa2:1; } flags; /* Linked list of ways to find a key if the key isn't on the local diff --git a/g10/pkclist.c b/g10/pkclist.c index 9e2a63642..4a12083d3 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1,6 +1,6 @@ /* pkclist.c - create a list of public keys - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1210,8 +1210,20 @@ algo_available( preftype_t preftype, int algo, void *hint ) } else if( preftype == PREFTYPE_HASH ) { - if(hint && ((*(int *)hint) != gcry_md_get_algo_dlen (algo))) - return 0; + if(hint) + { + if(opt.flags.dsa2) + { + /* If --enable-dsa2 is set, then we'll accept a hash + that is larger than we need. If --enable-dsa2 is not + set, then we won't accept any hash that isn't exactly + the right size. */ + if ((*(int *)hint) > gcry_md_get_algo_dlen (algo)) + return 0; + } + else if (((*(int *)hint) != gcry_md_get_algo_dlen (algo))) + return 0; + } if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5 && algo != DIGEST_ALGO_SHA1 diff --git a/g10/plaintext.c b/g10/plaintext.c index 2ae851e30..c0a6c3e11 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -1,6 +1,6 @@ /* plaintext.c - process plaintext packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -91,7 +91,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, log_info(_("data not saved; use option \"--output\" to save it\n")); nooutput = 1; } - else if( !opt.use_embedded_filename ) { + else if( !opt.flags.use_embedded_filename ) { fname = make_outfile_name( iobuf_get_real_fname(pt->buf) ); if( !fname ) fname = ask_outfile_name( pt->name, pt->namelen ); @@ -100,9 +100,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, goto leave; } } - else { - fname = make_printable_string( pt->name, pt->namelen, 0 ); - } + else + fname=utf8_to_native(pt->name,pt->namelen,0); if( nooutput ) ; @@ -318,9 +317,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, goto leave; } else if( fwrite( buffer, 1, len, fp ) != len ) { + rc = (errno? gpg_error_from_errno (errno) + : gpg_error (GPG_ERR_INTERNAL)); log_error("Error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; xfree( buffer ); goto leave; } @@ -554,3 +554,44 @@ hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, STRLIST files, return 0; } + + +/* Set up a plaintext packet with the appropriate filename. If there + is a --set-filename, use it (it's already UTF8). If there is a + regular filename, UTF8-ize it if necessary. If there is no + filenames at all, set the field empty. */ + +PKT_plaintext * +setup_plaintext_name(const char *filename,IOBUF iobuf) +{ + PKT_plaintext *pt; + + if(filename || opt.set_filename) + { + char *s; + + if(opt.set_filename) + s=make_basename(opt.set_filename,iobuf_get_real_fname(iobuf)); + else if(filename && !opt.flags.utf8_filename) + { + char *tmp=native_to_utf8(filename); + s=make_basename(tmp,iobuf_get_real_fname(iobuf)); + xfree(tmp); + } + else + s=make_basename(filename,iobuf_get_real_fname(iobuf)); + + 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; + } + + return pt; +} diff --git a/g10/sign.c b/g10/sign.c index 9bb35c898..fa3796758 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -320,11 +320,15 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, } else { - /* TODO: remove this check in the future once all the - variable-q DSA stuff makes it into the standard. */ - if(!opt.expert - && sk->pubkey_algo==PUBKEY_ALGO_DSA - && gcry_md_get_algo_dlen (digest_algo)!=20) + /* If it's a DSA key, and q is 160 bits, it might be an + old-style DSA key. If the hash doesn't match the q, fail + unless --enable-dsa2 is set. If the q isn't 160 bits, then + allow any hash since it must be a DSA2 key (if the hash is + too small, we'll fail in encode_md_value). */ + if (sk->pubkey_algo==PUBKEY_ALGO_DSA + && (gcry_mpi_get_nbits (sk->skey[1])/8)==20 + && !opt.flags.dsa2 + && gcry_md_get_algo_dlen (digest_algo)!=20) { log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); return G10ERR_GENERAL; @@ -384,6 +388,32 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md ) return rc; } + + +static int +match_dsa_hash (unsigned int qbytes) +{ + if (qbytes <= 20) + return DIGEST_ALGO_SHA1; +#ifdef USE_SHA256 + if (qbytes <= 28) + return DIGEST_ALGO_SHA224; + if (qbytes <= 32) + return DIGEST_ALGO_SHA256; +#endif + +#ifdef USE_SHA512 + if (qbytes <= 48) + return DIGEST_ALGO_SHA384; + if (qbytes <= 64) + return DIGEST_ALGO_SHA512; +#endif + return DEFAULT_DIGEST_ALGO; + /* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong + answer we have if the larger SHAs aren't there. */ +} + + /* First try --digest-algo. If that isn't set, see if the recipient has a preferred algorithm (which is also filtered through @@ -397,7 +427,6 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, gcry_md_hd_t md ) the signing key prefs either before or after using the personal list? */ - static int hash_for(PKT_secret_key *sk) { @@ -405,32 +434,61 @@ hash_for(PKT_secret_key *sk) return opt.def_digest_algo; else if( recipient_digest_algo ) return recipient_digest_algo; - else if(sk->pubkey_algo==PUBKEY_ALGO_DSA - || (sk->is_protected && sk->protect.s2k.mode==1002)) + else if(sk->pubkey_algo==PUBKEY_ALGO_DSA) { - /* The sk lives on a smartcard, or it's a DSA key. DSA requires - a 160-bit hash, and current smartcards only handle SHA-1 and - RIPEMD/160 (i.e. 160-bit hashes). This is correct now, but - may need revision as the cards add algorithms and/or DSA is - expanded to use larger hashes. */ + unsigned int qbytes = gcry_mpi_get_nbits (sk->skey[1]) / 8; + + /* It's a DSA key, so find a hash that is the same size as q or + larger. If q is 160, assume it is an old DSA key and use a + 160-bit hash unless --enable-dsa2 is set, in which case act + like a new DSA key that just happens to have a 160-bit q + (i.e. allow truncation). If q is not 160, by definition it + must be a new DSA key. */ + + if (opt.personal_digest_prefs) + { + prefitem_t *prefs; + + if (qbytes != 20 || opt.flags.dsa2) + { + for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) + if (gcry_md_get_algo_dlen (prefs->value) >= qbytes) + return prefs->value; + } + else + { + for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) + if (gcry_md-get_algo_dlen (prefs->value) == qbytes) + return prefs->value; + } + } + + return match_dsa_hash(qbytes); + } + else if (sk->is_protected && sk->protect.s2k.mode==1002) + { + /* The sk lives on a smartcard, and current smartcards only + handle SHA-1 and RIPEMD/160. This is correct now, but may + need revision as the cards add algorithms. */ if(opt.personal_digest_prefs) { prefitem_t *prefs; - for(prefs=opt.personal_digest_prefs;prefs->type;prefs++) - if (gcry_md_get_algo_dlen (prefs->value) == 20) + for (prefs=opt.personal_digest_prefs;prefs->type;prefs++) + if (prefs->value==DIGEST_ALGO_SHA1 + || prefs->value==DIGEST_ALGO_RMD160) return prefs->value; } return DIGEST_ALGO_SHA1; } - else if(PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) + else if (PGP2 && sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 ) { - /* Old-style PGP only understands MD5. */ + /* Old-style PGP only understands MD5 */ return DIGEST_ALGO_MD5; } - else if( opt.personal_digest_prefs ) + else if ( opt.personal_digest_prefs ) { /* It's not DSA, so we can use whatever the first hash algorithm is in the pref list */ @@ -440,6 +498,7 @@ hash_for(PKT_secret_key *sk) return DEFAULT_DIGEST_ALGO; } + static int only_old_style( SK_LIST sk_list ) { @@ -537,21 +596,8 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) u32 filesize; int rc = 0; - if (!opt.no_literal) { - if (fname || opt.set_filename) { - char *s = make_basename (opt.set_filename? opt.set_filename - : fname, - 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 (!opt.no_literal) + pt=setup_plaintext_name(fname,inp); /* try to calculate the length of the data */ if ( !iobuf_is_pipe_filename (fname) && *fname ) @@ -1367,16 +1413,19 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, { /* Basically, this means use SHA1 always unless it's a v3 RSA key making a v3 cert (use MD5), or the user specified - something (use whatever they said). They still must use a - 160-bit hash with DSA, or the signature will fail. Note - that this still allows the caller of make_keysig_packet to - override the user setting if it must. */ + something (use whatever they said), or it's DSA (use the + best match). They still can't pick an inappropriate hash + for DSA or the signature will fail. Note that this still + allows the caller of make_keysig_packet to override the + user setting if it must. */ if(opt.cert_digest_algo) digest_algo=opt.cert_digest_algo; else if(sk->pubkey_algo==PUBKEY_ALGO_RSA && pk->version<4 && sigversion<4) digest_algo = DIGEST_ALGO_MD5; + else if(sk->pubkey_algo==PUBKEY_ALGO_DSA) + digest_algo = match_dsa_hash (gcry_mpi_get_nbits (sk->skey[1])/8); else digest_algo = DIGEST_ALGO_SHA1; } diff --git a/g10/status.c b/g10/status.c index ffee8559f..2098d6738 100644 --- a/g10/status.c +++ b/g10/status.c @@ -209,9 +209,10 @@ set_status_fd ( int fd ) fd, strerror(errno)); } last_fd = fd; - register_primegen_progress ( progress_cb, "primegen" ); - register_pk_dsa_progress ( progress_cb, "pk_dsa" ); - register_pk_elg_progress ( progress_cb, "pk_elg" ); +#warning Use libgrypt calls for progress indicators +/* register_primegen_progress ( progress_cb, "primegen" ); */ +/* register_pk_dsa_progress ( progress_cb, "pk_dsa" ); */ +/* register_pk_elg_progress ( progress_cb, "pk_elg" ); */ } int -- cgit v1.2.3 From c61489acbfe3fba0c7fa548161cde50554d623ff Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 28 Apr 2006 14:32:13 +0000 Subject: Fix for sanitize string. Added SHA224 --- TODO | 5 +++++ include/ChangeLog | 4 ++++ include/cipher.h | 3 +++ jnlib/ChangeLog | 7 +++++++ jnlib/stringhelp.c | 14 +++++++------- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/TODO b/TODO index 3e4d21dc6..af3a42605 100644 --- a/TODO +++ b/TODO @@ -106,3 +106,8 @@ might want to have an agent context for each service request * gpg/ ** issue a NO_SECKEY xxxx if a -u key was not found. +** Replace DIGEST_ALGO_SHA224 + We can't do that right now because it is only defined by newer + versions of libgcrypt. Changes this if we require libgcrypt 1.3 + anyway. + diff --git a/include/ChangeLog b/include/ChangeLog index 0211bd618..3fd3fe48c 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2006-04-28 Werner Koch <wk@g10code.com> + + * cipher.h (DIGEST_ALGO_SHA224): Define it. + 2006-04-18 Werner Koch <wk@g10code.com> * keyserver.h, i18n.h, http.h, cipher.h: Updated to gpg 1.4.3. diff --git a/include/cipher.h b/include/cipher.h index 681386c36..d8b15cf9a 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -68,6 +68,9 @@ #define DIGEST_ALGO_SHA256 /* 8 */ GCRY_MD_SHA256 #define DIGEST_ALGO_SHA384 /* 9 */ GCRY_MD_SHA384 #define DIGEST_ALGO_SHA512 /* 10 */ GCRY_MD_SHA512 +/* SHA224 is as of now only defined in the libgcrypt SVN; thus we + can't use that macro. */ +#define DIGEST_ALGO_SHA224 /* 11 */ 11 /* GCRY_MD_SHA224 */ #define COMPRESS_ALGO_NONE 0 #define COMPRESS_ALGO_ZIP 1 diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 8816068b0..f3074c6af 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,10 @@ +2006-04-28 Werner Koch <wk@g10code.com> + + * stringhelp.c (print_sanitized_buffer): Fix bug where the count + got wrong for the \xNN representation. + (sanitize_buffer): Fix bug where some control characters lose part + of their \xNN representation. + 2006-04-20 Werner Koch <wk@g10code.com> * stringhelp.c (make_basename): New arg INPUTPATH for future diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index e999170dd..d5a2c29b6 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -1,6 +1,6 @@ /* stringhelp.c - standard string helper functions - * Copyright (C) 1998, 1999, 2000, 2001, 2003, - * 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -367,7 +367,7 @@ print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, else { fprintf (fp, "x%02x", *p); - count += 2; + count += 3; } } else @@ -428,7 +428,7 @@ sanitize_buffer (const void *p_arg, size_t n, int delim) const unsigned char *save_p; char *buffer, *d; - /* first count length */ + /* First count length. */ for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) { if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) @@ -437,14 +437,14 @@ sanitize_buffer (const void *p_arg, size_t n, int delim) || *p=='\v' || *p=='\b' || !*p ) buflen += 2; else - buflen += 4; + buflen += 5; } else buflen++; } p = save_p; n = save_n; - /* and now make the string */ + /* And now make the string */ d = buffer = jnlib_xmalloc( buflen ); for ( ; n; n--, p++ ) { @@ -464,7 +464,7 @@ sanitize_buffer (const void *p_arg, size_t n, int delim) *d++ = '0'; else { sprintf(d, "x%02x", *p ); - d += 2; + d += 3; } } else -- cgit v1.2.3 From b794bb683fda4662a90f8461b049f2538c076c84 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 2 May 2006 08:19:59 +0000 Subject: Repackaged PKITS_data.tar.bz2 --- tests/pkits/ChangeLog | 5 +++++ tests/pkits/PKITS_data.tar.bz2 | Bin 1155744 -> 1160675 bytes tests/pkits/README | 2 +- tests/pkits/inittests | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/pkits/ChangeLog b/tests/pkits/ChangeLog index 2f0b7ba0e..084e6cec8 100644 --- a/tests/pkits/ChangeLog +++ b/tests/pkits/ChangeLog @@ -1,3 +1,8 @@ +2006-05-02 Werner Koch <wk@g10code.com> + + * PKITS_data.tar.bz2: Repackaged new copy becuase the old one got + corrupted by the conversion fromCVS to SVN. + 2004-08-16 Werner Koch <wk@g10code.de> Started implementing PKITS based tests. diff --git a/tests/pkits/PKITS_data.tar.bz2 b/tests/pkits/PKITS_data.tar.bz2 index 0604f2286..687d504f6 100644 Binary files a/tests/pkits/PKITS_data.tar.bz2 and b/tests/pkits/PKITS_data.tar.bz2 differ diff --git a/tests/pkits/README b/tests/pkits/README index a4290fe1f..1f944ad58 100644 --- a/tests/pkits/README +++ b/tests/pkits/README @@ -1,7 +1,7 @@ tests/pkits/README These are tests based on NIST's Public Key Interoperability Test Suite -(PKITS) as downloaded on 2004-08-16 from +(PKITS) as downloaded on 2006-05-02 from http://csrc.nist.gov/pki/testing/x509paths.html . README - this file. diff --git a/tests/pkits/inittests b/tests/pkits/inittests index 6af16de03..e5d136fd9 100755 --- a/tests/pkits/inittests +++ b/tests/pkits/inittests @@ -13,7 +13,7 @@ set -e clean_files=' -ReadMe.txt pkits.ldif +ReadMe.txt pkits.ldif pkits.schema gpgsm.conf gpg-agent.conf trustlist.txt policies.txt pubring.kbx msg msg.sig msg.unsig ' -- cgit v1.2.3 From 61756ae3a78eeb1a5386c96736b2a314114d2680 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 16 May 2006 09:54:41 +0000 Subject: Added sample certificates. --- tests/extrasamples/README | 8 +++++++- tests/extrasamples/siemens-ZZZZZ000.crt | Bin 0 -> 1463 bytes tests/extrasamples/siemens-ZZZZZ0EE.crt | Bin 0 -> 1443 bytes 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/extrasamples/siemens-ZZZZZ000.crt create mode 100644 tests/extrasamples/siemens-ZZZZZ0EE.crt diff --git a/tests/extrasamples/README b/tests/extrasamples/README index 3102eac15..31efcbde0 100644 --- a/tests/extrasamples/README +++ b/tests/extrasamples/README @@ -1,5 +1,11 @@ -Extra test data where it is not clear whether we may distribute them. This +Extra test data where it is not clear whether we may distribute them. Thus we only keep them in the CVS. dod-test9.p12 A file from the DoD X.509 tests suite, September 2001. Passphrase is "password". + +siemens-ZZZZZ000.crt +siemens-ZZZZZ0EE.crt + Two certificates from the Siemens CA featuring a trailing + garbage byte and crlDPs with several names. + diff --git a/tests/extrasamples/siemens-ZZZZZ000.crt b/tests/extrasamples/siemens-ZZZZZ000.crt new file mode 100644 index 000000000..6807b5c26 Binary files /dev/null and b/tests/extrasamples/siemens-ZZZZZ000.crt differ diff --git a/tests/extrasamples/siemens-ZZZZZ0EE.crt b/tests/extrasamples/siemens-ZZZZZ0EE.crt new file mode 100644 index 000000000..e8a50dbb0 Binary files /dev/null and b/tests/extrasamples/siemens-ZZZZZ0EE.crt differ -- cgit v1.2.3 From 11544e7184b0eab8f3058ee3c5f87e94118a7bf3 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Mon, 22 May 2006 14:35:04 +0000 Subject: 2006-05-19 Marcus Brinkmann <marcus@g10code.de> * keydb.c (keydb_insert_cert): Do not lock here, but only check if it is locked. (keydb_store_cert): Lock here. * keydb.h (keydb_delete): Accept new argument UNLOCK. * keydb.c (keydb_delete): Likewise. Only unlock if this is set. * delete.c (delete_one): Add new argument to invocation of keydb_delete. --- sm/ChangeLog | 11 +++++++++++ sm/delete.c | 2 +- sm/keydb.c | 14 +++++++++----- sm/keydb.h | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/sm/ChangeLog b/sm/ChangeLog index 02505962c..f161d444c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,14 @@ +2006-05-19 Marcus Brinkmann <marcus@g10code.de> + + * keydb.c (keydb_insert_cert): Do not lock here, but only check if + it is locked. + (keydb_store_cert): Lock here. + + * keydb.h (keydb_delete): Accept new argument UNLOCK. + * keydb.c (keydb_delete): Likewise. Only unlock if this is set. + * delete.c (delete_one): Add new argument to invocation of + keydb_delete. + 2006-03-21 Werner Koch <wk@g10code.com> * certchain.c (get_regtp_ca_info): New. diff --git a/sm/delete.c b/sm/delete.c index 8e06b9489..7533f7291 100644 --- a/sm/delete.c +++ b/sm/delete.c @@ -124,7 +124,7 @@ delete_one (CTRL ctrl, const char *username) goto leave; } - rc = keydb_delete (kh); + rc = keydb_delete (kh, duplicates ? 0 : 1); if (rc) goto leave; if (opt.verbose) diff --git a/sm/keydb.c b/sm/keydb.c index 17f04fe4b..15f5dbdac 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -696,9 +696,8 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert) else return gpg_error (GPG_ERR_GENERAL); - rc = lock_all (hd); - if (rc) - return rc; + if (!hd->locked) + return gpg_error (GPG_ERR_NOT_LOCKED); gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ @@ -759,7 +758,7 @@ keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert) * The current keyblock or cert will be deleted. */ int -keydb_delete (KEYDB_HANDLE hd) +keydb_delete (KEYDB_HANDLE hd, int unlock) { int rc = -1; @@ -785,7 +784,8 @@ keydb_delete (KEYDB_HANDLE hd) break; } - unlock_all (hd); + if (unlock) + unlock_all (hd); return rc; } @@ -1337,6 +1337,10 @@ keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed) if (ephemeral) keydb_set_ephemeral (kh, 1); + rc = lock_all (kh); + if (rc) + return rc; + rc = keydb_search_fpr (kh, fpr); if (rc != -1) { diff --git a/sm/keydb.h b/sm/keydb.h index 924ad77c4..fb4001b64 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -53,7 +53,7 @@ int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert); int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert); int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert); -int keydb_delete (KEYDB_HANDLE hd); +int keydb_delete (KEYDB_HANDLE hd, int unlock); int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved); void keydb_rebuild_caches (void); -- cgit v1.2.3 From fbe4ac37f6d3e7870e26caffb0d21c3c77198297 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 23 May 2006 16:19:43 +0000 Subject: g10/ does build again. --- ChangeLog | 9 ++ TODO | 9 +- common/ChangeLog | 27 ++++++ common/Makefile.am | 4 +- common/gettime.c | 28 +++++- common/iobuf.h | 2 + common/miscellaneous.c | 24 ++++- common/pka.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++ common/pka.h | 27 ++++++ common/ttyio.c | 49 +++++++++- common/ttyio.h | 16 +++ common/util.h | 3 + common/yesno.c | 142 +++++++++++++++++---------- configure.ac | 57 ++++++++++- g10/ChangeLog | 40 ++++++++ g10/Makefile.am | 2 +- g10/armor.c | 2 +- g10/call-agent.c | 24 +++-- g10/call-agent.h | 17 +++- g10/card-util.c | 18 ++-- g10/gpg.c | 27 ++++-- g10/gpgv.c | 20 ---- g10/import.c | 6 +- g10/keydb.h | 1 + g10/keygen.c | 7 +- g10/keyserver.c | 9 +- g10/main.h | 1 + g10/mainproc.c | 1 + g10/misc.c | 19 +++- g10/options.h | 1 - g10/passphrase.c | 4 +- g10/pkclist.c | 8 +- g10/plaintext.c | 18 ++-- g10/pubkey-enc.c | 6 +- g10/sign.c | 2 +- g10/skclist.c | 13 +++ jnlib/ChangeLog | 19 ++++ jnlib/dotlock.c | 83 ++++++++++++---- jnlib/dotlock.h | 1 + jnlib/libjnlib-config.h | 26 ++--- jnlib/stringhelp.c | 99 ++++++++++++++++--- jnlib/stringhelp.h | 6 ++ jnlib/strlist.c | 24 ++--- jnlib/strlist.h | 4 +- scd/app-p15.c | 10 ++ sm/ChangeLog | 10 ++ sm/Makefile.am | 2 +- sm/keydb.c | 27 ------ sm/keylist.c | 4 +- tools/ChangeLog | 8 ++ tools/gpgconf-comp.c | 28 ------ tools/gpgparsemail.c | 6 +- 52 files changed, 990 insertions(+), 262 deletions(-) create mode 100644 common/pka.c create mode 100644 common/pka.h diff --git a/ChangeLog b/ChangeLog index 6e5228817..711cd4751 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-05-23 Werner Koch <wk@g10code.com> + + * configure.ac (ZLIBS): New for zlib link commands. Add bzip2 + support. + +2006-05-22 Werner Koch <wk@g10code.com> + + * configure.ac (EXEEXT): New. + 2006-04-18 Werner Koch <wk@g10code.com> * configure.ac (PK_UID_CACHE_SIZE): New. diff --git a/TODO b/TODO index af3a42605..7958ed18e 100644 --- a/TODO +++ b/TODO @@ -110,4 +110,11 @@ might want to have an agent context for each service request We can't do that right now because it is only defined by newer versions of libgcrypt. Changes this if we require libgcrypt 1.3 anyway. - +** skclist.c:random_is_faked + Remove the whole stuff? + +* common/ +** ttyio + Add completion support. +** yesno + Update to gpg 1.4.3 version \ No newline at end of file diff --git a/common/ChangeLog b/common/ChangeLog index f1b11fc57..36a733a7f 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,30 @@ +2006-05-23 Werner Koch <wk@g10code.com> + + * gettime.c (isotimestamp): New. + + * ttyio.c (tty_get_ttyname): Posixly correct usage of ctermid. + + * dns-cert.c: New. Taken from 1.4.3's util/cert.c. + * dns-cert.h: New. + +2006-05-22 Werner Koch <wk@g10code.com> + + * pka.c: New. Taked from 1.4.3. + * pka.h: New. + * Makefile.am: Added pka. + +2006-05-19 Werner Koch <wk@g10code.com> + + * yesno.c (answer_is_yes_no_default, answer_is_yes_no_quit): + Updated from 1.4.3. + (answer_is_okay_cancel): new. From 1.4.3. + + * miscellaneous.c (match_multistr): New. Taken from 1.4.3. + + * ttyio.c (tty_enable_completion, tty_disable_completion): New + dummy functions. + * ttyio.h: Add prototypes and stubs. + 2006-04-19 Werner Koch <wk@g10code.com> * iobuf.c (iobuf_get_fd): New. Taken from 1.4.3. diff --git a/common/Makefile.am b/common/Makefile.am index 3056be6bc..34819e93f 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -49,7 +49,9 @@ libcommon_a_SOURCES = \ w32reg.c \ signal.c \ dynload.h \ - estream.c estream.h + estream.c estream.h \ + dns-cert.c dns-cert.h \ + pka.c pka.h libsimple_pwquery_a_SOURCES = \ diff --git a/common/gettime.c b/common/gettime.c index 93e4ba113..ecdc7df95 100644 --- a/common/gettime.c +++ b/common/gettime.c @@ -201,7 +201,7 @@ strtimevalue( u32 value ) } -/**************** +/* * Note: this function returns GMT */ const char * @@ -222,6 +222,32 @@ strtimestamp( u32 stamp ) return buffer; } + +/* + * Note: this function returns GMT + */ +const char * +isotimestamp (u32 stamp) +{ + static char buffer[25+5]; + struct tm *tp; + time_t atime = stamp; + + if (atime < 0) + { + strcpy (buffer, "????" "-??" "-??" " " "??" ":" "??" ":" "??"); + } + else + { + tp = gmtime ( &atime ); + sprintf (buffer,"%04d-%02d-%02d %02d:%02d:%02d", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + } + return buffer; +} + + /**************** * Note: this function returns local time */ diff --git a/common/iobuf.h b/common/iobuf.h index 431d573a1..3b8f4b572 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -145,6 +145,8 @@ void iobuf_set_partial_block_mode (iobuf_t a, size_t len); int iobuf_translate_file_handle (int fd, int for_write); +void iobuf_skip_rest (iobuf_t a, unsigned long n, int partial); + /* 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 diff --git a/common/miscellaneous.c b/common/miscellaneous.c index 14d6f020d..e9f8ed27f 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -1,5 +1,5 @@ /* miscellaneous.c - Stuff not fitting elsewhere - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -47,6 +47,7 @@ print_fname_stdin (const char *s) return s; } +/* fixme: Globally replace it by print_sanitized_buffer. */ void print_string( FILE *fp, const byte *p, size_t n, int delim ) { @@ -125,4 +126,25 @@ leave: } +/* Try match against each substring of multistr, delimited by | */ +int +match_multistr (const char *multistr,const char *match) +{ + do + { + size_t seglen = strcspn (multistr,"|"); + if (!seglen) + break; + /* Using the localized strncasecmp! */ + if (strncasecmp(multistr,match,seglen)==0) + return 1; + multistr += seglen; + if (*multistr == '|') + multistr++; + } + while (*multistr); + + return 0; +} + diff --git a/common/pka.c b/common/pka.c new file mode 100644 index 000000000..3d442d16a --- /dev/null +++ b/common/pka.c @@ -0,0 +1,252 @@ +/* pka.c - DNS Public Key Association RR access + * Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef USE_DNS_PKA +#include <sys/types.h> +#ifdef _WIN32 +#include <windows.h> +#else +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#endif +#endif /* USE_DNS_PKA */ + +#include "util.h" +#include "pka.h" + +#ifdef USE_DNS_PKA +/* Parse the TXT resource record. Format is: + + v=pka1;fpr=a4d94e92b0986ab5ee9dcd755de249965b0358a2;uri=string + + For simplicity white spaces are not allowed. Because we expect to + use a new RRTYPE for this in the future we define the TXT really + strict for simplicity: No white spaces, case sensitivity of the + names, order must be as given above. Only URI is optional. + + This function modifies BUFFER. On success 0 is returned, the 20 + byte fingerprint stored at FPR and BUFFER contains the URI or an + empty string. +*/ +static int +parse_txt_record (char *buffer, unsigned char *fpr) +{ + char *p, *pend; + int i; + + p = buffer; + pend = strchr (p, ';'); + if (!pend) + return -1; + *pend++ = 0; + if (strcmp (p, "v=pka1")) + return -1; /* Wrong or missing version. */ + + p = pend; + pend = strchr (p, ';'); + if (pend) + *pend++ = 0; + if (strncmp (p, "fpr=", 4)) + return -1; /* Missing fingerprint part. */ + p += 4; + for (i=0; i < 20 && hexdigitp (p) && hexdigitp (p+1); i++, p += 2) + fpr[i] = xtoi_2 (p); + if (i != 20) + return -1; /* Fingerprint consists not of exactly 40 hexbytes. */ + + p = pend; + if (!p || !*p) + { + *buffer = 0; + return 0; /* Success (no URI given). */ + } + if (strncmp (p, "uri=", 4)) + return -1; /* Unknown part. */ + p += 4; + /* There is an URI, copy it to the start of the buffer. */ + while (*p) + *buffer++ = *p++; + *buffer = 0; + return 0; +} + + +/* For the given email ADDRESS lookup the PKA information in the DNS. + + On success the 20 byte SHA-1 fingerprint is stored at FPR and the + URI will be returned in an allocated buffer. Note that the URI + might be an zero length string as this information is optiobnal. + Caller must xfree the returned string. + + On error NULL is returned and the 20 bytes at FPR are not + defined. */ +char * +get_pka_info (const char *address, unsigned char *fpr) +{ + unsigned char answer[PACKETSZ]; + int anslen; + int qdcount, ancount, nscount, arcount; + int rc; + unsigned char *p, *pend; + const char *domain; + char *name; + + + domain = strrchr (address, '@'); + if (!domain || domain == address || !domain[1]) + return NULL; /* invalid mail address given. */ + + name = malloc (strlen (address) + 5 + 1); + memcpy (name, address, domain - address); + strcpy (stpcpy (name + (domain-address), "._pka."), domain+1); + + anslen = res_query (name, C_IN, T_TXT, answer, PACKETSZ); + xfree (name); + if (anslen < sizeof(HEADER)) + return NULL; /* DNS resolver returned a too short answer. */ + if ( (rc=((HEADER*)answer)->rcode) != NOERROR ) + return NULL; /* DNS resolver returned an error. */ + + /* We assume that PACKETSZ is large enough and don't do dynmically + expansion of the buffer. */ + if (anslen > PACKETSZ) + return NULL; /* DNS resolver returned a too long answer */ + + qdcount = ntohs (((HEADER*)answer)->qdcount); + ancount = ntohs (((HEADER*)answer)->ancount); + nscount = ntohs (((HEADER*)answer)->nscount); + arcount = ntohs (((HEADER*)answer)->arcount); + + if (!ancount) + return NULL; /* Got no answer. */ + + p = answer + sizeof (HEADER); + pend = answer + anslen; /* Actually points directly behind the buffer. */ + + while (qdcount-- && p < pend) + { + rc = dn_skipname (p, pend); + if (rc == -1) + return NULL; + p += rc + QFIXEDSZ; + } + + if (ancount > 1) + return NULL; /* more than one possible gpg trustdns record - none used. */ + + while (ancount-- && p <= pend) + { + unsigned int type, class, txtlen, n; + char *buffer, *bufp; + + rc = dn_skipname (p, pend); + if (rc == -1) + return NULL; + p += rc; + if (p >= pend - 10) + return NULL; /* RR too short. */ + + type = *p++ << 8; + type |= *p++; + class = *p++ << 8; + class |= *p++; + p += 4; + txtlen = *p++ << 8; + txtlen |= *p++; + if (type != T_TXT || class != C_IN) + return NULL; /* Answer does not match the query. */ + + buffer = bufp = xmalloc (txtlen + 1); + while (txtlen && p < pend) + { + for (n = *p++, txtlen--; txtlen && n && p < pend; txtlen--, n--) + *bufp++ = *p++; + } + *bufp = 0; + if (parse_txt_record (buffer, fpr)) + { + xfree (buffer); + return NULL; /* Not a valid gpg trustdns RR. */ + } + return buffer; + } + + return NULL; +} +#else /* !USE_DNS_PKA */ + +/* Dummy version of the function if we can't use the resolver + functions. */ +char * +get_pka_info (const char *address, unsigned char *fpr) +{ + return NULL; +} +#endif /* !USE_DNS_PKA */ + + +#ifdef TEST +int +main(int argc,char *argv[]) +{ + unsigned char fpr[20]; + char *uri; + int i; + + if (argc < 2) + { + fprintf (stderr, "usage: pka mail-addresses\n"); + return 1; + } + argc--; + argv++; + + for (; argc; argc--, argv++) + { + uri = get_pka_info ( *argv, fpr ); + printf ("%s", *argv); + if (uri) + { + putchar (' '); + for (i=0; i < 20; i++) + printf ("%02X", fpr[i]); + if (*uri) + printf (" %s", uri); + xfree (uri); + } + putchar ('\n'); + } + return 0; +} +#endif /* TEST */ + +/* +Local Variables: +compile-command: "cc -DUSE_DNS_PKA -DTEST -I.. -I../include -Wall -g -o pka pka.c -lresolv libutil.a" +End: +*/ diff --git a/common/pka.h b/common/pka.h new file mode 100644 index 000000000..d0b977d0f --- /dev/null +++ b/common/pka.h @@ -0,0 +1,27 @@ +/* pka.h - DNS Public Key Association RR access definitions + * Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ +#ifndef GNUPG_COMMON_PKA_H +#define GNUPG_COMMON_PKA_H + +char *get_pka_info (const char *address, unsigned char *fpr); + + +#endif /*GNUPG_COMMON_PKA_H*/ diff --git a/common/ttyio.c b/common/ttyio.c index 5749c59fe..c9f41c626 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -1,5 +1,6 @@ /* ttyio.c - tty i/O functions - * Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + * Copyright (C) 1998,1999,2000,2001,2002,2003, + * 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -45,6 +46,12 @@ #endif #include <errno.h> #include <ctype.h> +#ifdef HAVE_LIBREADLINE +#include <readline/readline.h> +#include <readline/history.h> +#endif + + #include "util.h" #include "memory.h" #include "ttyio.h" @@ -93,13 +100,21 @@ tty_get_ttyname (void) if (!got_name) { const char *s; + /* Note that despite our checks for these macros the function is + not necessarily thread save. We mainly do this for + portability reasons, in case L_ctermid is not defined. */ +# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_POSIX_TRHEADS) + char buffer[L_ctermid]; + s = ctermid (buffer); +# else s = ctermid (NULL); +# endif if (s) name = strdup (s); got_name = 1; } -#endif - /* Assume the staandrd tty on memory error or when tehre is no +#endif /*HAVE_CTERMID*/ + /* Assume the standard tty on memory error or when tehre is no certmid. */ return name? name : "/dev/tty"; } @@ -165,6 +180,34 @@ init_ttyfp(void) } +#ifdef HAVE_LIBREADLINE +void +tty_enable_completion(rl_completion_func_t *completer) +{ +/* if( no_terminal ) */ +/* return; */ + +/* if( !initialized ) */ +/* init_ttyfp(); */ + +/* rl_attempted_completion_function=completer; */ +/* rl_inhibit_completion=0; */ +} + +void +tty_disable_completion(void) +{ +/* if( no_terminal ) */ +/* return; */ + +/* if( !initialized ) */ +/* init_ttyfp(); */ + +/* rl_inhibit_completion=1; */ +} +#endif /*HAVE_LIBREADLINE*/ + + int tty_batchmode( int onoff ) { diff --git a/common/ttyio.h b/common/ttyio.h index 6fa7400a9..6148d644a 100644 --- a/common/ttyio.h +++ b/common/ttyio.h @@ -20,6 +20,11 @@ #ifndef GNUPG_COMMON_TTYIO_H #define GNUPG_COMMON_TTYIO_H +#ifdef HAVE_LIBREADLINE +#include <stdio.h> +#include <readline/readline.h> +#endif + const char *tty_get_ttyname (void); int tty_batchmode (int onoff); #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) @@ -40,5 +45,16 @@ void tty_kill_prompt (void); int tty_get_answer_is_yes (const char *prompt); int tty_no_terminal (int onoff); +#ifdef HAVE_LIBREADLINE +void tty_enable_completion(rl_completion_func_t *completer); +void tty_disable_completion(void); +#else +/* Use a macro to stub out these functions since a macro has no need + to typedef a "rl_completion_func_t" which would be undefined + without readline. */ +#define tty_enable_completion(x) +#define tty_disable_completion() +#endif + #endif /*GNUPG_COMMON_TTYIO_H*/ diff --git a/common/util.h b/common/util.h index 68f5222b5..295d785c5 100644 --- a/common/util.h +++ b/common/util.h @@ -84,6 +84,7 @@ 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 *isotimestamp (u32 stamp); /* GMT */ const char *asctimestamp (u32 stamp); /* localized */ @@ -108,6 +109,7 @@ void gnupg_unblock_all_signals (void); 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); +int answer_is_okay_cancel (const char *s, int def_answer); /*-- xreadline.c --*/ ssize_t read_line (FILE *fp, @@ -161,6 +163,7 @@ char *make_printable_string (const void *p, size_t n, int delim); int is_file_compressed (const char *s, int *ret_rc); +int match_multistr (const char *multistr,const char *match); /*-- Simple replacement functions. */ diff --git a/common/yesno.c b/common/yesno.c index 2a96b4e5d..737071691 100644 --- a/common/yesno.c +++ b/common/yesno.c @@ -28,31 +28,33 @@ 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"); + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + const char *long_yes = _("yes"); + const char *short_yes = _("yY"); + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + 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; + /* Note: we have to use the local dependent compare here. */ + if ( match_multistr(long_yes,s) ) + return 1; + if ( *s && strchr( short_yes, *s ) && !s[1] ) + return 1; + /* Test for "no" strings to catch ambiguities for the next test. */ + if ( match_multistr(long_no,s) ) + 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 ) +answer_is_yes ( const char *s ) { return answer_is_yes_no_default(s,0); } @@ -61,36 +63,76 @@ answer_is_yes( const char *s ) * Return 1 for yes, -1 for quit, or 0 for no */ int -answer_is_yes_no_quit( const char *s ) +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"); + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + const char *long_yes = _("yes"); + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + const char *long_no = _("no"); + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + 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; + /* Note: we have to use a local dependent compare here. */ + if ( match_multistr(long_no,s) ) return 0; + if ( match_multistr(long_yes,s) ) + return 1; + if ( match_multistr(long_quit,s) ) + 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; } + +/* + Return 1 for okay, 0 for for cancel or DEF_ANSWER for default. + */ +int +answer_is_okay_cancel (const char *s, int def_answer) +{ + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + const char *long_okay = _("okay|okay"); + /* TRANSLATORS: See doc/TRANSLATE about this string. */ + const char *long_cancel = _("cancel|cancel"); + const char *short_okay = _("oO"); + const char *short_cancel = _("cC"); + + /* Note: We have to use the locale dependent compare. */ + if ( match_multistr(long_okay,s) ) + return 1; + if ( match_multistr(long_cancel,s) ) + return 0; + if ( *s && strchr( short_okay, *s ) && !s[1] ) + return 1; + if ( *s && strchr( short_cancel, *s ) && !s[1] ) + return 0; + /* Always test for the English values (not locale here). */ + if ( !ascii_strcasecmp(s, "okay" ) ) + return 1; + if ( !ascii_strcasecmp(s, "ok" ) ) + return 1; + if ( !ascii_strcasecmp(s, "cancel" ) ) + return 0; + if ( *s && strchr( "oO", *s ) && !s[1] ) + return 1; + if ( *s && strchr( "cC", *s ) && !s[1] ) + return 0; + return def_answer; +} + diff --git a/configure.ac b/configure.ac index 53cbc38fc..05882c2c9 100644 --- a/configure.ac +++ b/configure.ac @@ -147,6 +147,16 @@ AC_ARG_ENABLE(agent-only, build_agent_only=$enableval) +# Allow disabling of bzib2 support. +# It is defined only after we confirm the library is available later +use_bzip2=yes +AC_MSG_CHECKING([whether to enable the BZIP2 compression algorithm]) +AC_ARG_ENABLE(bzip2, + AC_HELP_STRING([--disable-bzip2],[disable the BZIP2 compression algorithm]), + use_bzip2=$enableval) +AC_MSG_RESULT($use_bzip2) + + # Configure option to allow or disallow execution of external # programs, like a photo viewer. AC_MSG_CHECKING([whether to enable external program execution]) @@ -462,6 +472,8 @@ if test "$have_w32_system" = yes; then fi AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) +# These need to go after AC_PROG_CC so that $EXEEXT is defined +AC_DEFINE_UNQUOTED(EXEEXT,"$EXEEXT",[The executable file extension, if any]) # @@ -969,11 +981,13 @@ else AC_DEFINE(DISABLE_REGEX,1,[ Define to disable regular expression support ]) fi -dnl Do we have zlib? Must do it here because Solaris failed -dnl when compiling a conftest (due to the "-lz" from LIBS). +# +# Do we have zlib? Must do it here because Solaris failed +# when compiling a conftest (due to the "-lz" from LIBS). +# Note that we combine zlib and bzlib2 in ZLIBS. +# _cppflags="${CPPFLAGS}" _ldflags="${LDFLAGS}" - AC_ARG_WITH(zlib, [ --with-zlib=DIR use libz in DIR],[ if test -d "$withval"; then @@ -984,10 +998,43 @@ AC_ARG_WITH(zlib, AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, deflateInit2_, - LIBS="$LIBS -lz", + ZLIBS="-lz", CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) - + +# +# Check whether we can support bzip2 +# +if test "$use_bzip2" = yes ; then + _cppflags="${CPPFLAGS}" + _ldflags="${LDFLAGS}" + AC_ARG_WITH(bzip2, + AC_HELP_STRING([--with-bzip2=DIR],[look for bzip2 in DIR]), + [ + if test -d "$withval" ; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + ],withval="") + + # Checking alongside stdio.h as an early version of bzip2 (1.0) + # required stdio.h to be included before bzlib.h, and Solaris 9 is + # woefully out of date. + if test "$withval" != no ; then + AC_CHECK_HEADER(bzlib.h, + AC_CHECK_LIB(bz2,BZ2_bzCompressInit, + [ + have_bz2=yes + ZLIBS="$ZLIBS -lbz2" + AC_DEFINE(HAVE_BZIP2,1, + [Defined if the bz2 compression library is available]) + ], + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags},[#include <stdio.h>]) + fi +fi +AM_CONDITIONAL(ENABLE_BZIP2_SUPPORT,test x"$have_bz2" = "xyes") +AC_SUBST(ZLIBS) # See wether we want to run the long test suite. diff --git a/g10/ChangeLog b/g10/ChangeLog index b8f789e8b..6018bbe13 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,43 @@ +2006-05-23 Werner Koch <wk@g10code.com> + + * card-util.c (generate_card_keys): Removed temporary kludge for + generate_keypair. + + * call-agent.c (agent_scd_setattr): Add arg SERIALNO. + (agent_scd_genkey): Ditto. + (agent_scd_change_pin): Ditto. + + * call-agent.h (struct agent_card_info_s): Updated to match the + one of 1.4.3. + + * Makefile.am (LDADD): Include ZLIBS. + + * gpgv.c: Removed stubs not anymore useful due to libgcrypt. + +2006-05-22 Werner Koch <wk@g10code.com> + + * keyserver.c (keyidlist): Replaced mpi_get_keyid by v3_keyid. + * keydb.h (v3_keyid): Added. + + * import.c (import): Better initialize KEYBLOCK as to quiet + compiler warning. + + * skclist.c (random_is_faked): New. + + * mainproc.c: Include pka.h. + +2006-05-19 Werner Koch <wk@g10code.com> + + * misc.c (openpgp_pk_test_algo2): Need to use gcry_pk_algo_info + directly. + (string_count_chr): New. + + * armor.c (parse_header_line): Use renamed function + length_sans_trailing_ws. + + * options.h, gpg.c: Option --strict is not used thus removed code + but kept option. + 2006-04-28 David Shaw <dshaw@jabberwocky.com> (wk) * keyserver.c (direct_uri_map): New. diff --git a/g10/Makefile.am b/g10/Makefile.am index 1deacb9f8..aeb24d7b3 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -107,7 +107,7 @@ gpgv2_SOURCES = gpgv.c \ # ks-db.h \ # $(common_source) -LDADD = $(needed_libs) @LIBINTL@ @CAPLIBS@ @W32LIBS@ +LDADD = $(needed_libs) $(ZLIBS) @LIBINTL@ @CAPLIBS@ @W32LIBS@ gpg2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error gpgv2_LDADD = $(LIBGCRYPT_LIBS) $(LDADD) -lassuan -lgpg-error diff --git a/g10/armor.c b/g10/armor.c index e02591372..2336ff6f9 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -336,7 +336,7 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) int hashes=0; unsigned int len2; - len2 = check_trailing_ws( line, len ); + len2 = length_sans_trailing_ws ( line, len ); if( !len2 ) { afx->buffer_pos = len2; /* (it is not the fine way to do it here) */ return 0; /* WS only: same as empty line */ diff --git a/g10/call-agent.c b/g10/call-agent.c index 31c43cf13..55fc62569 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -626,10 +626,13 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info) } -/* Send an setattr command to the SCdaemon. */ +/* Send an setattr command to the SCdaemon. SERIALNO is not actually + used here but required by gpg 1.4's implementation of this code in + cardglue.c. */ int agent_scd_setattr (const char *name, - const unsigned char *value, size_t valuelen) + const unsigned char *value, size_t valuelen, + const char *serialno) { int rc; char line[ASSUAN_LINELENGTH]; @@ -719,9 +722,11 @@ scd_genkey_cb (void *opaque, const char *line) return 0; } -/* Send a GENKEY command to the SCdaemon. */ +/* Send a GENKEY command to the SCdaemon. SERIALNO is not used in + this implementation. */ int -agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force) +agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, + const char *serialno) { int rc; char line[ASSUAN_LINELENGTH]; @@ -865,9 +870,10 @@ agent_scd_pkdecrypt (const char *serialno, 3: Change the admin PIN 101: Set a new PIN and reset the retry counter 102: Same as 101 + SERIALNO is not used. */ int -agent_scd_change_pin (int chvno) +agent_scd_change_pin (int chvno, const char *serialno) { int rc; char line[ASSUAN_LINELENGTH]; @@ -890,7 +896,7 @@ agent_scd_change_pin (int chvno) /* Perform a CHECKPIN operation. SERIALNO should be the serial - number of the card - optioanlly followed by the fingerprint; + number of the card - optionally followed by the fingerprint; however the fingerprint is ignored here. */ int agent_scd_checkpin (const char *serialno) @@ -910,3 +916,9 @@ agent_scd_checkpin (const char *serialno) } +/* Dummy function, only used by the gpg 1.4 implementation. */ +void +agent_clear_pin_cache (const char *sn) +{ + +} diff --git a/g10/call-agent.h b/g10/call-agent.h index 3d9f4f9bf..71044e38b 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -21,7 +21,8 @@ #define GNUPG_G10_CALL_AGENT_H -struct agent_card_info_s { +struct agent_card_info_s +{ int error; /* private. */ char *serialno; /* malloced hex string. */ char *disp_name; /* malloced. */ @@ -29,6 +30,7 @@ struct agent_card_info_s { int disp_sex; /* 0 = unspecified, 1 = male, 2 = female */ char *pubkey_url; /* malloced. */ char *login_data; /* malloced. */ + char *private_do[4]; /* malloced. */ char cafpr1valid; char cafpr2valid; char cafpr3valid; @@ -41,6 +43,9 @@ struct agent_card_info_s { char fpr1[20]; char fpr2[20]; char fpr3[20]; + u32 fpr1time; + u32 fpr2time; + u32 fpr3time; unsigned long sig_counter; int chv1_cached; /* True if a PIN is not required for each signing. Note that the gpg-agent might cache @@ -73,10 +78,12 @@ 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); + const unsigned char *value, size_t valuelen, + const char *serialno); /* Send a GENKEY command to the SCdaemon. */ -int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force); +int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, + const char *serialno); /* Send a PKSIGN command to the SCdaemon. */ int agent_scd_pksign (const char *keyid, int hashalgo, @@ -89,11 +96,13 @@ int agent_scd_pkdecrypt (const char *serialno, 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); +int agent_scd_change_pin (int chvno, const char *serialno); /* Send the CHECKPIN command to the SCdaemon. */ int agent_scd_checkpin (const char *serialno); +/* Dummy function, only implemented by gpg 1.4. */ +void agent_clear_pin_cache (const char *sn); #endif /*GNUPG_G10_CALL_AGENT_H*/ diff --git a/g10/card-util.c b/g10/card-util.c index 0c8365405..b5a036e54 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -27,7 +27,7 @@ #include <assert.h> #if GNUPG_MAJOR_VERSION != 1 -#include "gpg.h" +# include "gpg.h" #endif /*GNUPG_MAJOR_VERSION != 1*/ #include "util.h" #include "i18n.h" @@ -37,13 +37,13 @@ #include "main.h" #include "keyserver-internal.h" #if GNUPG_MAJOR_VERSION == 1 -#ifdef HAVE_LIBREADLINE -#include <stdio.h> -#include <readline/readline.h> -#endif /*HAVE_LIBREADLINE*/ -#include "cardglue.h" +# ifdef HAVE_LIBREADLINE +# include <stdio.h> +# include <readline/readline.h> +# endif /*HAVE_LIBREADLINE*/ +# include "cardglue.h" #else /*GNUPG_MAJOR_VERSION!=1*/ -#include "call-agent.h" +# include "call-agent.h" #endif /*GNUPG_MAJOR_VERSION!=1*/ #define CONTROL_D ('D' - 'A' + 1) @@ -1091,12 +1091,8 @@ generate_card_keys (const char *serialno) if (check_pin_for_key_operation (&info, &forced_chv1)) goto leave; -#if GNUPG_MAJOR_VERSION == 1 generate_keypair (NULL, info.serialno, want_backup? opt.homedir:NULL); -#else - generate_keypair (NULL, info.serialno); -#endif leave: agent_release_card_info (&info); diff --git a/g10/gpg.c b/g10/gpg.c index 25b55b705..cc00ff3b5 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1376,7 +1376,7 @@ list_config(char *items) for(sl=iter->values;sl;sl=sl->next) { - print_string2(stdout,sl->d,strlen(sl->d),':',';'); + print_sanitized_string2 (stdout, sl->d, ':',';'); if(sl->next) printf(";"); } @@ -1782,13 +1782,11 @@ main (int argc, char **argv ) opt.no_perm_warn=1; else if (pargs.r_opt == oStrict ) { - opt.strict=1; - log_set_strict(1); + /* Not used */ } else if (pargs.r_opt == oNoStrict ) { - opt.strict=0; - log_set_strict(0); + /* Not used */ } } @@ -2360,8 +2358,14 @@ main (int argc, char **argv ) compress_algo_string = xstrdup(pargs.r.ret_str); } break; - case oCertDigestAlgo: cert_digest_string = xstrdup(pargs.r.ret_str); break; - case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break; + case oCertDigestAlgo: + cert_digest_string = xstrdup(pargs.r.ret_str); + break; + + case oNoSecmemWarn: + gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); + break; + case oRequireSecmem: require_secmem=1; break; case oNoRequireSecmem: require_secmem=0; break; case oNoPermissionWarn: opt.no_perm_warn=1; break; @@ -2604,8 +2608,12 @@ main (int argc, char **argv ) xfree(iter); } break; - case oStrict: opt.strict=1; log_set_strict(1); break; - case oNoStrict: opt.strict=0; log_set_strict(0); break; + + case oStrict: + case oNoStrict: + /* Not used */ + break; + case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break; case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break; case oEnableProgressFilter: opt.enable_progress_filter = 1; break; @@ -3035,7 +3043,6 @@ main (int argc, char **argv ) /* Set the random seed file. */ if( use_random_seed ) { char *p = make_filename(opt.homedir, "random_seed", NULL ); - set_random_seed_file(p); gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p); if (!access (p, F_OK)) register_secured_file (p); diff --git a/g10/gpgv.c b/g10/gpgv.c index 9b17b8ad3..579e58a29 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -387,26 +387,6 @@ void cipher_decrypt( gcry_cipher_hd_t c, byte *outbuf, byte *inbuf, unsigned nbytes ) {} void cipher_sync( gcry_cipher_hd_t c ) {} -/* Stubs to avoid linking to ../cipher/random.c */ -void random_dump_stats(void) {} -int quick_random_gen( int onoff ) { return -1;} -void randomize_buffer( byte *buffer, size_t length, int level ) {} -int random_is_faked() { return -1;} -byte *get_random_bits( size_t nbits, int level, int secure ) { return NULL;} -void set_random_seed_file( const char *name ) {} -void update_random_seed_file() {} -void fast_random_poll() {} - -/* Stubs to avoid linking of ../cipher/primegen.c */ -void register_primegen_progress ( void (*cb)( void *, int), void *cb_data ) {} -MPI generate_secret_prime( unsigned nbits ) { return NULL;} -MPI generate_public_prime( unsigned nbits ) { return NULL;} -MPI generate_elg_prime( int mode, unsigned pbits, unsigned qbits, - gcry_mpi_t g, gcry_mpi_t **ret_factors ) { return NULL;} - -/* Do not link to ../cipher/rndlinux.c */ -void rndlinux_constructor(void) {} - /* Stubs to avoid linking to ../util/ttyio.c */ int tty_batchmode( int onoff ) { return 0; } diff --git a/g10/import.c b/g10/import.c index ee4ea95da..4526d84d7 100644 --- a/g10/import.c +++ b/g10/import.c @@ -243,7 +243,9 @@ import( IOBUF inp, const char* fname,struct stats_s *stats, unsigned char **fpr,size_t *fpr_len,unsigned int options ) { PACKET *pending_pkt = NULL; - KBNODE keyblock; + KBNODE keyblock = NULL; /* Need to initialize because gcc can't + grasp the return semantics of + read_block. */ int rc = 0; getkey_disable_caches(); @@ -596,7 +598,7 @@ check_prefs(KBNODE keyblock) if(prefs->type==PREFTYPE_SYM) { - if (openpgp_cipher_algo_test (prefs->value)) + if (openpgp_cipher_test_algo (prefs->value)) { const char *algo = gcry_cipher_algo_name (prefs->value); if(!problem) diff --git a/g10/keydb.h b/g10/keydb.h index 4923a842c..f8be6efb9 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -254,6 +254,7 @@ int parse_auto_key_locate(char *options); /*-- keyid.c --*/ int pubkey_letter( int algo ); +u32 v3_keyid (gcry_mpi_t a, u32 *ki); void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ); size_t keystrlen(void); const char *keystr(u32 *keyid); diff --git a/g10/keygen.c b/g10/keygen.c index c7a97a0fc..9c2fd6fb8 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1911,8 +1911,9 @@ ask_user_id( int mode ) /* append a warning if we do not have dev/random * or it is switched into quick testmode */ - if( quick_random_gen(-1) ) - strcpy(p, " (INSECURE!)" ); + /* FIXME: see skclist.c:random_is_faked */ + /* if( quick_random_gen(-1) ) */ + /* strcpy(p, " (INSECURE!)" ); */ /* print a note in case that UTF8 mapping has to be done */ for(p=uid; *p; p++ ) { @@ -2648,7 +2649,7 @@ read_parameter_file( const char *fname ) /* * Generate a keypair (fname is only used in batch mode) If - * CARD_SERIALNO is not NULL the fucntion will create the keys on an + * CARD_SERIALNO is not NULL the function will create the keys on an * OpenPGP Card. If BACKUP_ENCRYPTION_DIR has been set and * CARD_SERIALNO is NOT NULL, the encryption key for the card gets * generate in software, imported to the card and a backup file diff --git a/g10/keyserver.c b/g10/keyserver.c index 3127a4795..bf1bf6cdc 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -42,6 +42,9 @@ #include "trustdb.h" #include "keyserver-internal.h" #include "util.h" +#include "dns-cert.h" +#include "pka.h" + struct keyrec { @@ -1730,8 +1733,8 @@ keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) node->pkt->pkt.public_key->version>=4) { (*klist)[*count].mode=KEYDB_SEARCH_MODE_LONG_KID; - mpi_get_keyid(node->pkt->pkt.public_key->pkey[0], - (*klist)[*count].u.kid); + v3_keyid (node->pkt->pkt.public_key->pkey[0], + (*klist)[*count].u.kid); (*count)++; if(*count==num) @@ -1982,7 +1985,7 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len) if(domain) *domain='.'; - type=get_cert(look,max_cert_size,&key,fpr,fpr_len,&url); + type=get_dns_cert(look,max_cert_size,&key,fpr,fpr_len,&url); if(type==1) { int armor_status=opt.no_armor; diff --git a/g10/main.h b/g10/main.h index cd6926b69..18d11b567 100644 --- a/g10/main.h +++ b/g10/main.h @@ -84,6 +84,7 @@ u32 buffer_to_u32( const byte *buffer ); const byte *get_session_marker( size_t *rlen ); int openpgp_cipher_test_algo( int algo ); int openpgp_pk_test_algo( int algo ); +int openpgp_pk_test_algo2 ( int algo, unsigned int use ); int openpgp_pk_algo_usage ( int algo ); int openpgp_md_test_algo( int algo ); diff --git a/g10/mainproc.c b/g10/mainproc.c index 1f91c8ca6..67ac784dc 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -41,6 +41,7 @@ #include "trustdb.h" #include "keyserver-internal.h" #include "photoid.h" +#include "pka.h" struct kidlist_item { diff --git a/g10/misc.c b/g10/misc.c index a26aa740d..12aa6c689 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -67,6 +67,18 @@ #include "i18n.h" +static int +string_count_chr (const char *string, int c) +{ + int count; + + for (count=0; *string; string++ ) + if ( *string == c ) + count++; + return count; +} + + #ifdef ENABLE_SELINUX_HACKS /* A object and a global variable to keep track of files marked as @@ -416,12 +428,17 @@ openpgp_pk_test_algo( int algo ) int openpgp_pk_test_algo2( int algo, unsigned int use ) { + int use_buf = use; + size_t sizeof_use_buf = sizeof (use_buf); + if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; if (algo < 0 || algo > 110) return gpg_error (GPG_ERR_PUBKEY_ALGO); - return gcry_pk_test_algo2 (algo, use); + + return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, + &use_buf, &sizeof_use_buf); } int diff --git a/g10/options.h b/g10/options.h index de5fa7920..b97b2f3f9 100644 --- a/g10/options.h +++ b/g10/options.h @@ -193,7 +193,6 @@ struct int preserve_permissions; int no_homedir_creation; struct groupitem *grouplist; - int strict; int mangle_dos_filenames; int enable_progress_filter; unsigned int screen_columns; diff --git a/g10/passphrase.c b/g10/passphrase.c index c1cdf12ae..1c5cf3b27 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -1017,7 +1017,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) int pwlen = strlen(pw); assert( s2k->hash_algo ); - dek->keylen = gcry_cipher_algo_get_keylen (dek->algo ); + dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) ) BUG(); @@ -1065,7 +1065,7 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create ) i = gcry_md_get_algo_dlen ( s2k->hash_algo ); if( i > dek->keylen - used ) i = dek->keylen - used; - memcpy( dek->key+used, md_read(md, s2k->hash_algo), i ); + memcpy (dek->key+used, gcry_md_read (md, s2k->hash_algo), i); used += i; } gcry_md_close(md); diff --git a/g10/pkclist.c b/g10/pkclist.c index 4a12083d3..4516f6769 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -363,7 +363,7 @@ do_edit_ownertrust (PKT_public_key *pk, int mode, int edit_ownertrust (PKT_public_key *pk, int mode ) { - unsigned int trust; + unsigned int trust = 0; int no_help = 0; for(;;) @@ -897,7 +897,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) else if (backlog) { /* This is part of our trick to expand and display groups. */ - answer = pop_strlist (&backlog); + answer = strlist_pop (&backlog); } else { @@ -1032,7 +1032,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1); if (rc) log_error(_("unknown default recipient \"%s\"\n"), def_rec ); - else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) + else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use)) ) { /* Mark any_recipients here since the default recipient would have been used if it wasn't already there. It @@ -1079,7 +1079,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) -1); goto fail; } - else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) + else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use )) ) { /* Key found and usable. Check validity. */ int trustlevel; diff --git a/g10/plaintext.c b/g10/plaintext.c index c0a6c3e11..8032f15f0 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -282,7 +282,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, rc = gpg_error_from_errno (errno); else rc = gpg_error (GPG_ERR_EOF); - log_error("Error writing to `%s': %s\n", + log_error("error writing to `%s': %s\n", fname, strerror(errno) ); goto leave; } @@ -310,7 +310,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { if(opt.max_output && (count+=len)>opt.max_output) { - log_error("Error writing to `%s': %s\n", + log_error("error writing to `%s': %s\n", fname,"exceeded --max-output limit\n"); rc = gpg_error (GPG_ERR_TOO_LARGE); xfree( buffer ); @@ -319,7 +319,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, else if( fwrite( buffer, 1, len, fp ) != len ) { rc = (errno? gpg_error_from_errno (errno) : gpg_error (GPG_ERR_INTERNAL)); - log_error("Error writing to `%s': %s\n", + log_error ("error writing to `%s': %s\n", fname, strerror(errno) ); xfree( buffer ); goto leave; @@ -338,16 +338,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, { if(opt.max_output && (++count)>opt.max_output) { - log_error("Error writing to `%s': %s\n", + log_error ("error writing to `%s': %s\n", fname,"exceeded --max-output limit\n"); rc = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } else if( putc( c, fp ) == EOF ) { - log_error("Error writing to `%s': %s\n", + rc = (errno? gpg_error_from_errno (errno) + : gpg_error (GPG_ERR_INTERNAL)); + log_error ("error writing to `%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; goto leave; } } @@ -384,9 +385,10 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, } if( fp && fp != stdout && fclose(fp) ) { - log_error("Error closing `%s': %s\n", fname, strerror(errno) ); + rc = (errno? gpg_error_from_errno (errno) + : gpg_error (GPG_ERR_INTERNAL)); + log_error ("error closing `%s': %s\n", fname, strerror(errno) ); fp = NULL; - rc = G10ERR_WRITE_FILE; goto leave; } fp = NULL; diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 5af0d5f1d..dc0124bd4 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -214,8 +214,8 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) * DEK is the encryption key (session key) with length k * CSUM */ - if( DBG_CIPHER ) - log_hexdump("DEK frame:", frame, nframe ); + if (DBG_CIPHER) + log_printhex ("DEK frame:", frame, nframe ); n=0; if (!card) { @@ -267,7 +267,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) goto leave; } if( DBG_CIPHER ) - log_hexdump("DEK is:", dek->key, dek->keylen ); + log_printhex ("DEK is:", dek->key, dek->keylen ); /* check that the algo is in the preferences and whether it has expired */ { PKT_public_key *pk = NULL; diff --git a/g10/sign.c b/g10/sign.c index fa3796758..3e1d7bc53 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -458,7 +458,7 @@ hash_for(PKT_secret_key *sk) else { for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) - if (gcry_md-get_algo_dlen (prefs->value) == qbytes) + if (gcry_md_get_algo_dlen (prefs->value) == qbytes) return prefs->value; } } diff --git a/g10/skclist.c b/g10/skclist.c index afaa73814..d8f3b2dc1 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -36,6 +36,19 @@ #include "cipher.h" +/* There is currently no way to get the status of the quick random + generator flag from libgcrypt and it is not clear whether this + faked RNG is really a good idea. Thus for now we use this stub + function but we should consider to entirely remove this fake RNG + stuff. */ +static int +random_is_faked (void) +{ + return 0; +} + + + void release_sk_list( SK_LIST sk_list ) { diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index f3074c6af..61d12d580 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,22 @@ +2006-05-23 Werner Koch <wk@g10code.com> + + * libjnlib-config.h (JNLIB_NEED_UTF8CONV): Fixed typo in name. + + * dotlock.c (release_dotlock): Don't act if we don't have any + locks at all. + (destroy_dotlock): New. From 1.4.3. + (dotlock_remove_lockfiles): Make use of destroy function. + +2006-05-19 Werner Koch <wk@g10code.com> + + * strlist.c (append_to_strlist2): Enabled. + + * stringhelp.c (print_sanitized_buffer2): New. Changed the rules + to match the behaviour of print_string2 from gnupg 1.4.3. + (print_sanitized_buffer): Use the new function. + (print_sanitized_string2): New. + (hextobyte): New. Taken from gpg 1.4.3. + 2006-04-28 Werner Koch <wk@g10code.com> * stringhelp.c (print_sanitized_buffer): Fix bug where the count diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index a50a0ee99..b7f892717 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -1,5 +1,6 @@ /* dotlock.c - dotfile locking - * Copyright (C) 1998,2000,2001,2003 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000, 2001, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -149,9 +150,9 @@ create_dotlock( const char *file_to_lock ) dirpart = file_to_lock; } - #ifdef _REENTRANT +#ifdef _REENTRANT /* fixme: aquire mutex on all_lockfiles */ - #endif +#endif h->next = all_lockfiles; all_lockfiles = h; @@ -202,15 +203,54 @@ create_dotlock( const char *file_to_lock ) return NULL; } - #ifdef _REENTRANT +# ifdef _REENTRANT /* release mutex */ - #endif +# endif #endif /* !HAVE_DOSISH_SYSTEM */ h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 ); strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); return h; } + +void +destroy_dotlock ( DOTLOCK h ) +{ +#if !defined (HAVE_DOSISH_SYSTEM) + if ( h ) + { + DOTLOCK hprev, htmp; + + /* First remove the handle from our global list of all locks. */ + for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next) + if (htmp == h) + { + if (hprev) + hprev->next = htmp->next; + else + all_lockfiles = htmp->next; + h->next = NULL; + break; + } + + /* Second destroy the lock. */ + if (!h->disable) + { + if (h->locked && h->lockname) + unlink (h->lockname); + if (h->tname) + unlink (h->tname); + jnlib_free (h->tname); + jnlib_free (h->lockname); + } + jnlib_free(h); + + } +#endif +} + + + static int maybe_deadlock( DOTLOCK h ) { @@ -331,6 +371,13 @@ release_dotlock( DOTLOCK h ) #else int pid; + /* To avoid atexit race conditions we first check whether there + are any locks left. It might happen that another atexit + handler tries to release the lock while the atexit handler of + this module already ran and thus H is undefined. */ + if(!all_lockfiles) + return 0; + if( h->disable ) { return 0; } @@ -414,22 +461,16 @@ void dotlock_remove_lockfiles() { #ifndef HAVE_DOSISH_SYSTEM - DOTLOCK h, h2; - - h = all_lockfiles; - all_lockfiles = NULL; - - while( h ) { - h2 = h->next; - if (!h->disable ) { - if( h->locked ) - unlink( h->lockname ); - unlink(h->tname); - jnlib_free(h->tname); - jnlib_free(h->lockname); - } - jnlib_free(h); - h = h2; + DOTLOCK h, h2; + + h = all_lockfiles; + all_lockfiles = NULL; + + while ( h ) + { + h2 = h->next; + destroy_dotlock (h); + h = h2; } #endif } diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h index 9235687df..2cb39008a 100644 --- a/jnlib/dotlock.h +++ b/jnlib/dotlock.h @@ -26,6 +26,7 @@ typedef struct dotlock_handle *DOTLOCK; void disable_dotlock (void); DOTLOCK create_dotlock(const char *file_to_lock); +void destroy_dotlock ( DOTLOCK h ); int make_dotlock (DOTLOCK h, long timeout); int release_dotlock (DOTLOCK h); void dotlock_remove_lockfiles (void); diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h index 8ae2a9ce9..da3991432 100644 --- a/jnlib/libjnlib-config.h +++ b/jnlib/libjnlib-config.h @@ -30,31 +30,31 @@ #include "logging.h" /* We require support for utf-8 conversion. */ -#define JNLIB_NEED_UTF8CONF 1 +#define JNLIB_NEED_UTF8CONV 1 #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) +# define _(a) gettext (a) +# define N_(a) (a) #else #ifdef HAVE_LOCALE_H - #include <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 +# 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) +# define _(a) (a) +# define N_(a) (a) #endif #endif /* !USE_SIMPLE_GETTEXT */ diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index d5a2c29b6..27b8a25e8 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -218,8 +218,8 @@ length_sans_trailing_chars (const unsigned char *line, size_t len, return len; } -/**************** - * remove trailing white spaces and return the length of the buffer +/* + * Return the length of line ignoring trailing white-space. */ size_t length_sans_trailing_ws (const unsigned char *line, size_t len) @@ -336,34 +336,86 @@ compare_filenames( const char *a, const char *b ) #endif } + +/* Convert 2 hex characters at S to a byte value. Return this value + or -1 if there is an error. */ +int +hextobyte (const char *s) +{ + int c; + + if ( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if ( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if ( *s >= 'a' && *s <= 'f' ) + c = 16 * (10 + *s - 'a'); + else + return -1; + s++; + if ( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if ( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if ( *s >= 'a' && *s <= 'f' ) + c += 10 + *s - 'a'; + else + return -1; + return c; +} + + /* Print a BUFFER to stream FP while replacing all control characters - and the character DELIM with standard C escape sequences. Returns - the number of characters printed. */ + and the characters DELIM and DELIM2 with standard C escape + sequences. Returns the number of characters printed. */ size_t -print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, - int delim) +print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, + int delim, int delim2) { const unsigned char *p = buffer; size_t count = 0; for (; length; length--, p++, count++) { - if (*p < 0x20 || *p == 0x7f || *p == delim) + /* Fixme: Check whether *p < 0xa0 is correct for utf8 encoding. */ + if (*p < 0x20 + || (*p >= 0x7f && *p < 0xa0) + || *p == delim + || *p == delim2 + || ((delim || delim2) && *p=='\\')) { putc ('\\', fp); count++; if (*p == '\n') - putc ('n', fp); + { + putc ('n', fp); + count++; + } else if (*p == '\r') - putc ('r', fp); + { + putc ('r', fp); + count++; + } else if (*p == '\f') - putc ('f', fp); + { + putc ('f', fp); + count++; + } else if (*p == '\v') - putc ('v', fp); + { + putc ('v', fp); + count++; + } else if (*p == '\b') - putc ('b', fp); + { + putc ('b', fp); + count++; + } else if (!*p) - putc('0', fp); + { + putc('0', fp); + count++; + } else { fprintf (fp, "x%02x", *p); @@ -371,12 +423,24 @@ print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, } } else - putc (*p, fp); + { + putc (*p, fp); + count++; + } } return count; } +/* Same as print_sanitized_buffer2 but with just one delimiter. */ +size_t +print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, + int delim) +{ + return print_sanitized_buffer2 (fp, buffer, length, delim, 0); +} + + size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim) @@ -404,6 +468,13 @@ print_sanitized_utf8_buffer (FILE *fp, const void *buffer, } +size_t +print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2) +{ + return string? print_sanitized_buffer2 (fp, string, strlen (string), + delim, delim2):0; +} + size_t print_sanitized_string (FILE *fp, const char *string, int delim) { diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index 4c9e66452..405d6dbc4 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -40,11 +40,17 @@ char *make_dirname(const char *filepath); char *make_filename( const char *first_part, ... ); int compare_filenames( const char *a, const char *b ); +int hextobyte (const char *s); + size_t print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, int delim); +size_t print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length, + int delim, int delim2); size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim); size_t print_sanitized_string (FILE *fp, const char *string, int delim); +size_t print_sanitized_string2 (FILE *fp, const char *string, + int delim, int delim2); size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); char *sanitize_buffer (const void *p, size_t n, int delim); diff --git a/jnlib/strlist.c b/jnlib/strlist.c index d1924c102..52b4d5869 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -95,22 +95,24 @@ append_to_strlist( strlist_t *list, const char *string ) return sl; } -#if 0 + +#ifdef JNLIB_NEED_UTF8CONV strlist_t append_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) { - strlist_t sl; - - if( is_utf8 ) - sl = append_to_strlist( list, string ); - else { - char *p = native_to_utf8( string ); - sl = append_to_strlist( list, p ); - m_free( p ); + strlist_t sl; + + if( is_utf8 ) + sl = append_to_strlist( list, string ); + else + { + char *p = native_to_utf8 (string); + sl = append_to_strlist( list, p ); + jnlib_free( p ); } - return sl; + return sl; } -#endif +#endif /* JNLIB_NEED_UTF8CONV */ /* Return a copy of LIST. */ diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 47ac5bd4e..3c1252a44 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -35,11 +35,11 @@ strlist_t add_to_strlist (strlist_t *list, const char *string); strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8); strlist_t append_to_strlist (strlist_t *list, const char *string); +strlist_t append_to_strlist2 (strlist_t *list, const char *string, + int is_utf8); strlist_t strlist_copy (strlist_t list); -/*strlist_t append_to_strlist2( strlist_t *list, const char *string, - int is_utf8);*/ strlist_t strlist_prev (strlist_t head, strlist_t node); strlist_t strlist_last (strlist_t node); char * strlist_pop (strlist_t *list); diff --git a/scd/app-p15.c b/scd/app-p15.c index 8bb94cfcd..4203a6840 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -18,6 +18,16 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +/* Information pertaining to the BELPIC developer card samples: + + Unblock PUK: "222222111111" + Reset PIN: "333333111111") + + e.g. the APDUs 00:20:00:02:08:2C:33:33:33:11:11:11:FF + and 00:24:01:01:08:24:12:34:FF:FF:FF:FF:FF + should change the PIN into 1234. +*/ + #include <config.h> #include <errno.h> #include <stdio.h> diff --git a/sm/ChangeLog b/sm/ChangeLog index f161d444c..48e8473fa 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,9 @@ +2006-05-23 Werner Koch <wk@g10code.com> + + * keydb.c (hextobyte): Deleted as it is now defined in jnlib. + + * Makefile.am (gpgsm_LDADD): Include ZLIBS. + 2006-05-19 Marcus Brinkmann <marcus@g10code.de> * keydb.c (keydb_insert_cert): Do not lock here, but only check if @@ -9,6 +15,10 @@ * delete.c (delete_one): Add new argument to invocation of keydb_delete. +2006-05-15 Werner Koch <wk@g10code.com> + + * keylist.c (print_names_raw): Sanitize URI. + 2006-03-21 Werner Koch <wk@g10code.com> * certchain.c (get_regtp_ca_info): New. diff --git a/sm/Makefile.am b/sm/Makefile.am index aba2081f8..b5882ae1d 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -56,6 +56,6 @@ gpgsm_SOURCES = \ gpgsm_LDADD = ../jnlib/libjnlib.a ../kbx/libkeybox.a \ ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) -lgpg-error \ - $(LIBINTL) $(PTH_LIBS) + $(LIBINTL) $(PTH_LIBS) $(ZLIBS) diff --git a/sm/keydb.c b/sm/keydb.c index 15f5dbdac..d5932135d 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -1009,33 +1009,6 @@ keydb_search_subject (KEYDB_HANDLE hd, const char *name) } -static int -hextobyte (const char *string) -{ - const unsigned char *s = (const unsigned char *)string; - int c; - - if( *s >= '0' && *s <= '9' ) - c = 16 * (*s - '0'); - else if ( *s >= 'A' && *s <= 'F' ) - c = 16 * (10 + *s - 'A'); - else if ( *s >= 'a' && *s <= 'f' ) - c = 16 * (10 + *s - 'a'); - else - return -1; - s++; - if ( *s >= '0' && *s <= '9' ) - c += *s - '0'; - else if ( *s >= 'A' && *s <= 'F' ) - c += 10 + *s - 'A'; - else if ( *s >= 'a' && *s <= 'f' ) - c += 10 + *s - 'a'; - else - return -1; - return c; -} - - static int classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, diff --git a/sm/keylist.c b/sm/keylist.c index 51a066dab..b744a157f 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -529,7 +529,9 @@ print_names_raw (FILE *fp, int indent, ksba_name_t name) for (idx=0; (s = ksba_name_enum (name, idx)); idx++) { char *p = ksba_name_get_uri (name, idx); - printf ("%*s%s\n", idx||indent_all?indent:0, "", p?p:s); + printf ("%*s", idx||indent_all?indent:0, ""); + print_sanitized_string (fp, p?p:s, 0); + putc ('\n', fp); xfree (p); } } diff --git a/tools/ChangeLog b/tools/ChangeLog index 67dcbd860..4ac20ae0b 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,11 @@ +2006-05-23 Werner Koch <wk@g10code.com> + + * gpgparsemail.c: Include config.h if available + (stpcpy): Conditional include it. + + * gpgconf-comp.c (hextobyte): Removed as it is now availble in + jnlib. + 2005-12-20 Werner Koch <wk@g10code.com> * gpgconf-comp.c (gc_options_gpg): Add allow-pka-lookup. diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index a27da3941..2da88bc49 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -998,34 +998,6 @@ percent_escape (const char *src) } -/* Convert two hexadecimal digits from STR to the value they - represent. Returns -1 if one of the characters is not a - hexadecimal digit. */ -static int -hextobyte (const char *str) -{ - int val = 0; - int i; - -#define NROFHEXDIGITS 2 - for (i = 0; i < NROFHEXDIGITS; i++) - { - if (*str >= '0' && *str <= '9') - val += *str - '0'; - else if (*str >= 'A' && *str <= 'F') - val += 10 + *str - 'A'; - else if (*str >= 'a' && *str <= 'f') - val += 10 + *str - 'a'; - else - return -1; - if (i < NROFHEXDIGITS - 1) - val *= 16; - str++; - } - return val; -} - - /* Percent-Deescape special characters. The string is valid until the next invocation of the function. */ diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c index da56093c3..566f5747f 100644 --- a/tools/gpgparsemail.c +++ b/tools/gpgparsemail.c @@ -24,6 +24,9 @@ for the content of the line. Several options are available to scrutinize the message. S/MIME and OpenPGP support is included. */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif #include <stdio.h> #include <stdlib.h> @@ -145,6 +148,7 @@ xstrdup (const char *string) return p; } +#ifndef HAVE_STPCPY static char * stpcpy (char *a,const char *b) { @@ -154,7 +158,7 @@ stpcpy (char *a,const char *b) return (char*)a; } - +#endif static int run_gnupg (int smime, int sig_fd, int data_fd, int *close_list) -- cgit v1.2.3 From b61df862a7c9a8d85412b89965f5f814ab939180 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 24 May 2006 11:12:28 +0000 Subject: Still making gpg2 work. At least the keyids are now correctly computed again. --- ChangeLog | 4 ++++ configure.ac | 14 ++++++++++++++ g10/ChangeLog | 11 +++++++++++ g10/gpg.c | 12 ++++++------ g10/gpgv.c | 1 - g10/keygen.c | 4 ++-- g10/keyid.c | 6 +----- g10/main.h | 3 +++ g10/misc.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 9 files changed, 91 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 711cd4751..e61658c70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-05-24 Werner Koch <wk@g10code.com> + + * configure.ac: New option --disable-optimization taked from 1.4.3. + 2006-05-23 Werner Koch <wk@g10code.com> * configure.ac (ZLIBS): New for zlib link commands. Add bzip2 diff --git a/configure.ac b/configure.ac index 05882c2c9..b1b432a75 100644 --- a/configure.ac +++ b/configure.ac @@ -1080,6 +1080,20 @@ if test "$GCC" = yes; then fi fi +# +# This is handy for debugging so the compiler doesn't rearrange +# things and eliminate variables. +# +AC_ARG_ENABLE(optimization, + AC_HELP_STRING([--disable-optimization], + [disable compiler optimization]), + [if test $enableval = no ; then + CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'` + fi]) + + + + AC_SUBST(NETLIBS) AC_SUBST(W32LIBS) diff --git a/g10/ChangeLog b/g10/ChangeLog index 6018bbe13..47e9a7328 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,14 @@ +2006-05-24 Werner Koch <wk@g10code.com> + + * keyid.c (hash_public_key): Do not double hash the length bytes, + they are already included by mpi_print. + + * misc.c (openpgp_pk_test_algo2): Get test call right. + + * misc.c (string_to_cipher_algo, string_to_digest_algo): New. + * keygen.c (keygen_set_std_prefs): use them here. + * gpg.c (main): and here. + 2006-05-23 Werner Koch <wk@g10code.com> * card-util.c (generate_card_keys): Removed temporary kludge for diff --git a/g10/gpg.c b/g10/gpg.c index cc00ff3b5..52ae553c1 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -2515,7 +2515,7 @@ main (int argc, char **argv ) case oNoUtf8Strings: utf8_strings = 0; break; case oDisableCipherAlgo: { - int algo = gcry_cipher_map_name (pargs.r.ret_str); + int algo = string_to_cipher_algo (pargs.r.ret_str); gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo); } break; @@ -2859,7 +2859,7 @@ main (int argc, char **argv ) if( def_cipher_string ) { - opt.def_cipher_algo = gcry_cipher_map_name (def_cipher_string); + opt.def_cipher_algo = string_to_cipher_algo (def_cipher_string); if(opt.def_cipher_algo==0 && (ascii_strcasecmp(def_cipher_string,"idea")==0 || ascii_strcasecmp(def_cipher_string,"s1")==0)) @@ -2869,7 +2869,7 @@ main (int argc, char **argv ) log_error(_("selected cipher algorithm is invalid\n")); } if( def_digest_string ) { - opt.def_digest_algo = gcry_md_map_name (def_digest_string); + opt.def_digest_algo = string_to_digest_algo (def_digest_string); xfree(def_digest_string); def_digest_string = NULL; if ( openpgp_md_test_algo (opt.def_digest_algo) ) log_error(_("selected digest algorithm is invalid\n")); @@ -2881,19 +2881,19 @@ main (int argc, char **argv ) log_error(_("selected compression algorithm is invalid\n")); } if( cert_digest_string ) { - opt.cert_digest_algo = gcry_md_map_name (cert_digest_string); + opt.cert_digest_algo = string_to_digest_algo (cert_digest_string); xfree(cert_digest_string); cert_digest_string = NULL; if (openpgp_md_test_algo(opt.cert_digest_algo)) log_error(_("selected certification digest algorithm is invalid\n")); } if( s2k_cipher_string ) { - opt.s2k_cipher_algo = gcry_cipher_map_name (s2k_cipher_string); + opt.s2k_cipher_algo = string_to_cipher_algo (s2k_cipher_string); xfree(s2k_cipher_string); s2k_cipher_string = NULL; if (openpgp_cipher_test_algo (opt.s2k_cipher_algo)) log_error(_("selected cipher algorithm is invalid\n")); } if( s2k_digest_string ) { - opt.s2k_digest_algo = gcry_md_map_name (s2k_digest_string); + opt.s2k_digest_algo = string_to_digest_algo (s2k_digest_string); xfree(s2k_digest_string); s2k_digest_string = NULL; if (openpgp_md_test_algo(opt.s2k_digest_algo)) log_error(_("selected digest algorithm is invalid\n")); diff --git a/g10/gpgv.c b/g10/gpgv.c index 579e58a29..f33c5fc63 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -371,7 +371,6 @@ int agent_scd_getattr (const char *name, struct agent_card_info_s *info) {return #endif /* ENABLE_CARD_SUPPORT */ /* 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;} diff --git a/g10/keygen.c b/g10/keygen.c index 9c2fd6fb8..f791c6cd0 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -370,12 +370,12 @@ keygen_set_std_prefs (const char *string,int personal) while((tok=strsep(&prefstring," ,"))) { - if((val=gcry_cipher_map_name (tok))) + if((val=string_to_cipher_algo (tok))) { if(set_one_pref(val,1,tok,sym,&nsym)) rc=-1; } - else if((val=gcry_md_map_name (tok))) + else if((val=string_to_digest_algo (tok))) { if(set_one_pref(val,2,tok,hash,&nhash)) rc=-1; diff --git a/g10/keyid.c b/g10/keyid.c index 5eb51c1f4..0012a5604 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -56,7 +56,6 @@ void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ) { unsigned int n = 6; - unsigned int nb[PUBKEY_MAX_NPKEY]; unsigned int nn[PUBKEY_MAX_NPKEY]; byte *pp[PUBKEY_MAX_NPKEY]; int i; @@ -77,7 +76,6 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ) else for(i=0; i < npkey; i++ ) { - nb[i] = gcry_mpi_get_nbits (pk->pkey[i]); if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i])) BUG (); pp[i] = xmalloc (nbytes); @@ -85,7 +83,7 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ) &nbytes, pk->pkey[i])) BUG (); nn[i] = nbytes; - n += 2 + nn[i]; + n += nn[i]; } gcry_md_putc ( md, 0x99 ); /* ctb */ @@ -119,8 +117,6 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ) else for(i=0; i < npkey; i++ ) { - gcry_md_putc ( md, nb[i]>>8); - gcry_md_putc ( md, nb[i] ); gcry_md_write ( md, pp[i], nn[i] ); xfree(pp[i]); } diff --git a/g10/main.h b/g10/main.h index 18d11b567..c6c0b29b1 100644 --- a/g10/main.h +++ b/g10/main.h @@ -106,6 +106,9 @@ void deprecated_warning(const char *configname,unsigned int configlineno, const char *option,const char *repl1,const char *repl2); void deprecated_command (const char *name); +int string_to_cipher_algo (const char *string); +int string_to_digest_algo (const char *string); + const char *compress_algo_to_string(int algo); int string_to_compress_algo(const char *string); int check_compress_algo(int algo); diff --git a/g10/misc.c b/g10/misc.c index 12aa6c689..de0a029a4 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -429,7 +429,6 @@ int openpgp_pk_test_algo2( int algo, unsigned int use ) { int use_buf = use; - size_t sizeof_use_buf = sizeof (use_buf); if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; @@ -437,8 +436,7 @@ openpgp_pk_test_algo2( int algo, unsigned int use ) if (algo < 0 || algo > 110) return gpg_error (GPG_ERR_PUBKEY_ALGO); - return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, - &use_buf, &sizeof_use_buf); + return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &use_buf); } int @@ -739,6 +737,54 @@ deprecated_command (const char *name) } +/* + * Wrapper around gcry_cipher_map_name to provide a fallback using the + * "Sn" syntax as used by the preference strings. + */ +int +string_to_cipher_algo (const char *string) +{ + int val; + + val = gcry_cipher_map_name (string); + if (!val && string && (string[0]=='S' || string[0]=='s')) + { + char *endptr; + + string++; + val = strtol (string, &endptr, 10); + if (!*string || *endptr || openpgp_cipher_test_algo (val)) + val = 0; + } + + return val; +} + +/* + * Wrapper around gcry_md_map_name to provide a fallback using the + * "Hn" syntax as used by the preference strings. + */ +int +string_to_digest_algo (const char *string) +{ + int val; + + val = gcry_md_map_name (string); + if (!val && string && (string[0]=='H' || string[0]=='h')) + { + char *endptr; + + string++; + val = strtol (string, &endptr, 10); + if (!*string || *endptr || openpgp_md_test_algo (val)) + val = 0; + } + + return val; +} + + + const char * compress_algo_to_string(int algo) { @@ -771,7 +817,7 @@ compress_algo_to_string(int algo) int string_to_compress_algo(const char *string) { - /* NOTE TO TRANSLATOR: See doc/TRANSLATE about this string. */ + /* TRANSLATORS: See doc/TRANSLATE about this string. */ if(match_multistr(_("uncompressed|none"),string)) return 0; else if(ascii_strcasecmp(string,"uncompressed")==0) -- cgit v1.2.3 From dcb7d90bc556927d019d3a8bfd749e8267320545 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 8 Jun 2006 11:57:18 +0000 Subject: 2006-06-08 Marcus Brinkmann <marcus@g10code.de> * configure.ac (PTH_LIBS): Add --all to pth-config invocation. --- ChangeLog | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e61658c70..d62732c8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-06-08 Marcus Brinkmann <marcus@g10code.de> + + * configure.ac (PTH_LIBS): Add --all to pth-config invocation. + 2006-05-24 Werner Koch <wk@g10code.com> * configure.ac: New option --disable-optimization taked from 1.4.3. diff --git a/configure.ac b/configure.ac index b1b432a75..f3066a0a9 100644 --- a/configure.ac +++ b/configure.ac @@ -576,7 +576,7 @@ if test "$have_w32_system" = no; then if test $have_pth = yes; then PTH_CFLAGS=`$PTH_CONFIG --cflags` PTH_LIBS=`$PTH_CONFIG --ldflags` - PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs`" + PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs --all`" AC_DEFINE(USE_GNU_PTH, 1, [Defined if the GNU Portable Thread Library should be used]) AC_DEFINE(HAVE_PTH, 1, -- cgit v1.2.3 From 384cba431a4545906de01544bee0c655d957912d Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Thu, 8 Jun 2006 12:17:38 +0000 Subject: 2006-06-08 Marcus Brinkmann <marcus@g10code.de> * asschk.c (__func__) [__STDC_VERSION__ < 199901L && __GNUC__ >= 2]: Define macro to __FUNCTION__. (die): Use __func__ instead of __FUNCTION__. --- tests/ChangeLog | 6 ++++++ tests/asschk.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/ChangeLog b/tests/ChangeLog index f75387757..f12d9afbe 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2006-06-08 Marcus Brinkmann <marcus@g10code.de> + + * asschk.c (__func__) [__STDC_VERSION__ < 199901L && __GNUC__ >= 2]: + Define macro to __FUNCTION__. + (die): Use __func__ instead of __FUNCTION__. + 2005-10-07 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (TESTS_ENVIRONMENT): Remove LD_LIBRARY_PATH hack. diff --git a/tests/asschk.c b/tests/asschk.c index 59c0d107a..6a05fe1a8 100644 --- a/tests/asschk.c +++ b/tests/asschk.c @@ -116,6 +116,18 @@ # define ATTR_PRINTF(f,a) #endif +#if __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +/* Let's try our luck here. Some systems may provide __func__ without + providing __STDC_VERSION__ 199901L. */ +# if 0 +# define __func__ "<unknown>" +# endif +# endif +#endif + #define spacep(p) (*(p) == ' ' || *(p) == '\t') #define MAX_LINELEN 2048 @@ -188,7 +200,7 @@ die (const char *format, ...) exit (1); } -#define die(format, args...) (die) ("%s: " format, __FUNCTION__ , ##args) +#define die(format, args...) (die) ("%s: " format, __func__ , ##args) static void err (const char *format, ...) -- cgit v1.2.3 From 55e3d83edf0b9c14c9c2cb57a320b2c23fa09df5 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 9 Jun 2006 10:23:30 +0000 Subject: agent/ 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpg_agent_LDADD): Add $(NETLIBS). scd/ 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (scdaemon_LDADD): Add $(NETLIBS). --- agent/ChangeLog | 4 ++++ agent/Makefile.am | 2 +- scd/ChangeLog | 4 ++++ scd/Makefile.am | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index a2c240e2e..285cce7f9 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2006-06-09 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (gpg_agent_LDADD): Add $(NETLIBS). + 2006-04-09 Moritz Schulte <moritz@g10code.com> * command-ssh.c (ssh_request_process): Removed FIXME mentioning a diff --git a/agent/Makefile.am b/agent/Makefile.am index ec930fe3f..6c7def752 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -47,7 +47,7 @@ gpg_agent_SOURCES = \ gpg_agent_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ - -lgpg-error @LIBINTL@ + -lgpg-error @LIBINTL@ $(NETLIBS) gpg_protect_tool_SOURCES = \ protect-tool.c \ diff --git a/scd/ChangeLog b/scd/ChangeLog index 8015359a5..fd2ba5418 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2006-06-09 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (scdaemon_LDADD): Add $(NETLIBS). + 2006-04-14 Marcus Brinkmann <marcus@g10code.de> * app.c (select_application): Cover up a slot mismatch error in diff --git a/scd/Makefile.am b/scd/Makefile.am index 9a32de98b..46f6b9fa3 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -45,7 +45,7 @@ scdaemon_SOURCES = \ scdaemon_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBASSUAN_LIBS) \ - $(LIBUSB_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) + $(LIBUSB_LIBS) -lgpg-error $(LIBINTL) $(DL_LIBS) $(NETLIBS) # Removed for now: We need to decide whether it makes sense to # continue it at all, given that gpg has now all required -- cgit v1.2.3 From aed46885ab9edce4f4e0aaf65c71e4a655379619 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 9 Jun 2006 10:28:26 +0000 Subject: 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpg_agent_LDADD): Add $(NETLIBS). (gpg_protect_tool_LDADD): Likewise. (gpg_preset_passphrase_LDADD): Likewise. --- agent/ChangeLog | 2 ++ agent/Makefile.am | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 285cce7f9..999fbae3c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,6 +1,8 @@ 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpg_agent_LDADD): Add $(NETLIBS). + (gpg_protect_tool_LDADD): Likewise. + (gpg_preset_passphrase_LDADD): Likewise. 2006-04-09 Moritz Schulte <moritz@g10code.com> diff --git a/agent/Makefile.am b/agent/Makefile.am index 6c7def752..bc96531e0 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -54,9 +54,10 @@ gpg_protect_tool_SOURCES = \ protect.c \ minip12.c minip12.h +# Needs $(NETLIBS) for libsimple-pwquery.la. gpg_protect_tool_LDADD = ../common/libsimple-pwquery.a \ ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ - $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ + $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ $(NETLIBS) if HAVE_W32_SYSTEM gpg_protect_tool_LDADD += -lwsock32 endif @@ -64,9 +65,10 @@ endif gpg_preset_passphrase_SOURCES = \ preset-passphrase.c +# Needs $(NETLIBS) for libsimple-pwquery.la. gpg_preset_passphrase_LDADD = ../common/libsimple-pwquery.a \ ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ - $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ + $(LIBGCRYPT_LIBS) -lgpg-error @LIBINTL@ $(NETLIBS) if HAVE_W32_SYSTEM gpg_preset_passphrase_LDADD += -lwsock32 endif -- cgit v1.2.3 From 5a8770fc6c7317e41c1042de726389243254bff4 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Fri, 9 Jun 2006 11:32:22 +0000 Subject: 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpgconf_LDADD): Add $(GPG_ERROR_LIBS). (gpgkey2ssh_LDADD): Add ../jnlib/libjnlib.a. --- tools/ChangeLog | 5 +++++ tools/Makefile.am | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/ChangeLog b/tools/ChangeLog index 4ac20ae0b..25ffae5d2 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,8 @@ +2006-06-09 Marcus Brinkmann <marcus@g10code.de> + + * Makefile.am (gpgconf_LDADD): Add $(GPG_ERROR_LIBS). + (gpgkey2ssh_LDADD): Add ../jnlib/libjnlib.a. + 2006-05-23 Werner Koch <wk@g10code.com> * gpgparsemail.c: Include config.h if available diff --git a/tools/Makefile.am b/tools/Makefile.am index 519e87150..d9ef8812a 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -42,8 +42,10 @@ endif gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c -gpgconf_LDADD = ../jnlib/libjnlib.a \ - ../common/libcommon.a ../gl/libgnu.a @LIBINTL@ +# jnlib/common sucks in gpg-error, will they, nil they (some compilers +# do not eliminate the supposed-to-be-unused-inline-functions). +gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a \ + ../gl/libgnu.a @LIBINTL@ $(GPG_ERROR_LIBS) gpgparsemail_SOURCES = gpgparsemail.c rfc822parse.c rfc822parse.h gpgparsemail_LDADD = @@ -64,5 +66,7 @@ gpg_connect_agent_LDADD = ../jnlib/libjnlib.a \ gpgkey2ssh_SOURCES = gpgkey2ssh.c gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) -gpgkey2ssh_LDADD = ../common/libcommon.a ../gl/libgnu.a \ +# common sucks in jnlib, via use of BUG() in an inline function, which +# some compilers do not eliminate. +gpgkey2ssh_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a ../gl/libgnu.a \ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) -- cgit v1.2.3 From ff523906988b9eb4eea3ab3857afe29552c53716 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 16 Jun 2006 11:49:27 +0000 Subject: Added missing files --- common/dns-cert.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/dns-cert.h | 28 +++++++ 2 files changed, 274 insertions(+) create mode 100644 common/dns-cert.c create mode 100644 common/dns-cert.h diff --git a/common/dns-cert.c b/common/dns-cert.c new file mode 100644 index 000000000..8dfcb9724 --- /dev/null +++ b/common/dns-cert.c @@ -0,0 +1,246 @@ +/* dns-cert.c - DNS CERT code + * Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <sys/types.h> +#ifdef USE_DNS_CERT +# ifdef HAVE_W32_SYSTEM +# include <windows.h> +# else +# include <netinet/in.h> +# include <arpa/nameser.h> +# include <resolv.h> +# endif +#include <string.h> +#endif + +#include "util.h" +#include "iobuf.h" +#include "dns-cert.h" + +/* Not every installation has gotten around to supporting CERTs + yet... */ +#ifndef T_CERT +#define T_CERT 37 +#endif + + +/* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for + IPGP provided. */ +int +get_dns_cert (const char *name,size_t max_size,IOBUF *iobuf, + unsigned char **fpr,size_t *fpr_len,char **url) +{ +#ifdef USE_DNS_CERT + unsigned char *answer; + int r,ret=-1; + u16 count; + + if(fpr) + *fpr=NULL; + + if(url) + *url=NULL; + + answer=xmalloc(max_size); + + r=res_query(name,C_IN,T_CERT,answer,max_size); + /* Not too big, not too small, no errors and at least 1 answer. */ + if(r>=sizeof(HEADER) && r<=max_size + && (((HEADER *)answer)->rcode)==NOERROR + && (count=ntohs(((HEADER *)answer)->ancount))) + { + int rc; + unsigned char *pt,*emsg; + + emsg=&answer[r]; + + pt=&answer[sizeof(HEADER)]; + + /* Skip over the query */ + + rc=dn_skipname(pt,emsg); + if(rc==-1) + goto fail; + + pt+=rc+QFIXEDSZ; + + /* There are several possible response types for a CERT request. + We're interested in the PGP (a key) and IPGP (a URI) types. + Skip all others. TODO: A key is better than a URI since + we've gone through all this bother to fetch it, so favor that + if we have both PGP and IPGP? */ + + while(count-->0 && pt<emsg) + { + u16 type,class,dlen,ctype; + + rc=dn_skipname(pt,emsg); /* the name we just queried for */ + if(rc==-1) + break; + + pt+=rc; + + /* Truncated message? 15 bytes takes us to the point where + we start looking at the ctype. */ + if((emsg-pt)<15) + break; + + type=*pt++ << 8; + type|=*pt++; + + class=*pt++ << 8; + class|=*pt++; + /* We asked for IN and got something else !? */ + if(class!=C_IN) + break; + + /* ttl */ + pt+=4; + + /* data length */ + dlen=*pt++ << 8; + dlen|=*pt++; + + /* We asked for CERT and got something else - might be a + CNAME, so loop around again. */ + if(type!=T_CERT) + { + pt+=dlen; + continue; + } + + /* The CERT type */ + ctype=*pt++ << 8; + ctype|=*pt++; + + /* Skip the CERT key tag and algo which we don't need. */ + pt+=3; + + dlen-=5; + + /* 15 bytes takes us to here */ + + if(ctype==3 && iobuf && dlen) + { + /* PGP type */ + *iobuf=iobuf_temp_with_content((char *)pt,dlen); + ret=1; + break; + } + else if(ctype==6 && dlen && dlen<1023 && dlen>=pt[0]+1 + && fpr && fpr_len && url) + { + /* IPGP type */ + *fpr_len=pt[0]; + + if(*fpr_len) + { + *fpr=xmalloc(*fpr_len); + memcpy(*fpr,&pt[1],*fpr_len); + } + else + *fpr=NULL; + + if(dlen>*fpr_len+1) + { + *url=xmalloc(dlen-(*fpr_len+1)+1); + memcpy(*url,&pt[*fpr_len+1],dlen-(*fpr_len+1)); + (*url)[dlen-(*fpr_len+1)]='\0'; + } + else + *url=NULL; + + ret=2; + break; + } + + /* Neither type matches, so go around to the next answer. */ + pt+=dlen; + } + } + + fail: + xfree(answer); + + return ret; +#else /* !USE_DNS_CERT */ + return -1; +#endif +} + + + +/* Test with simon.josefsson.org */ + +#ifdef TEST +int +main(int argc,char *argv[]) +{ + unsigned char *fpr; + size_t fpr_len; + char *url; + int rc; + IOBUF iobuf; + + if(argc!=2) + { + printf("cert-test [name]\n"); + return 1; + } + + printf("CERT lookup on %s\n",argv[1]); + + rc=get_dns_cert (argv[1],16384,&iobuf,&fpr,&fpr_len,&url); + if(rc==-1) + printf("error\n"); + else if(rc==0) + printf("no answer\n"); + else if(rc==1) + { + printf("key found: %d bytes\n",(int)iobuf_get_temp_length(iobuf)); + iobuf_close(iobuf); + } + else if(rc==2) + { + if(fpr) + { + size_t i; + printf("Fingerprint found (%d bytes): ",(int)fpr_len); + for(i=0;i<fpr_len;i++) + printf("%02X",fpr[i]); + printf("\n"); + } + else + printf("No fingerprint found\n"); + + if(url) + printf("URL found: %s\n",url); + else + printf("No URL found\n"); + + xfree(fpr); + xfree(url); + } + + return 0; +} +#endif /* TEST */ diff --git a/common/dns-cert.h b/common/dns-cert.h new file mode 100644 index 000000000..47e0d5a2d --- /dev/null +++ b/common/dns-cert.h @@ -0,0 +1,28 @@ +/* dns-cert.h - DNS CERT definition + * Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ +#ifndef GNUPG_COMMON_DNS_CERT_H +#define GNUPG_COMMON_DNS_CERT_H + +int get_dns_cert (const char *name, size_t max_size, IOBUF *iobuf, + unsigned char **fpr, size_t *fpr_len, char **url); + + +#endif /*GNUPG_COMMON_DNS_CERT_H*/ -- cgit v1.2.3 From f89ee4a44d7d015c607b0baf6904e961b5fc3153 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jun 2006 15:48:09 +0000 Subject: Add MAC t P12 files. --- agent/ChangeLog | 5 +++++ agent/minip12.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 999fbae3c..7c4799d1c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,8 @@ +2006-06-20 Werner Koch <wk@g10code.com> + + * minip12.c (create_final): New arg PW. Add code to calculate the + MAC. + 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (gpg_agent_LDADD): Add $(NETLIBS). diff --git a/agent/minip12.c b/agent/minip12.c index e65bf0617..6f99bf24d 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -1,5 +1,5 @@ /* minip12.c - A minimal pkcs-12 implementation. - * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -120,6 +120,16 @@ static unsigned char const data_rc2iter2048[30] = { 0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 }; #define DATA_RC2ITER2048_SALT_OFF 18 +static unsigned char const data_mactemplate[51] = { + 0x30, 0x31, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, + 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, + 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x08, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, + 0x02, 0x08, 0x00 }; +#define DATA_MACTEMPLATE_MAC_OFF 17 +#define DATA_MACTEMPLATE_SALT_OFF 39 struct buffer_s { @@ -1200,17 +1210,27 @@ store_tag_length (unsigned char *p, int tag, size_t n) /* Create the final PKCS-12 object from the sequences contained in - SEQLIST. That array is terminated with an NULL object */ + SEQLIST. PW is the password. That array is terminated with an NULL + object. */ static unsigned char * -create_final (struct buffer_s *sequences, size_t *r_length) +create_final (struct buffer_s *sequences, const char *pw, size_t *r_length) { int i; size_t needed = 0; size_t len[8], n; + unsigned char *macstart; + size_t maclen; unsigned char *result, *p; size_t resultlen; + char salt[8]; + unsigned char keybuf[20]; + gcry_md_hd_t md; + int rc; - /* 8 steps to create the pkcs#12 Krampf. */ + /* 9 steps to create the pkcs#12 Krampf. */ + + /* 8. The MAC. */ + /* We add this at step 0. */ /* 7. All the buffers. */ for (i=0; sequences[i].buffer; i++) @@ -1243,6 +1263,7 @@ create_final (struct buffer_s *sequences, size_t *r_length) needed += 3; /* 0. And the final outer sequence. */ + needed += DIM (data_mactemplate); len[0] = needed; n = compute_tag_length (needed); needed += n; @@ -1263,7 +1284,7 @@ create_final (struct buffer_s *sequences, size_t *r_length) *p++ = TAG_INTEGER; *p++ = 1; *p++ = 3; - + /* 2. Store another sequence. */ p = store_tag_length (p, TAG_SEQUENCE, len[2]); @@ -1279,6 +1300,7 @@ create_final (struct buffer_s *sequences, size_t *r_length) p = store_tag_length (p, TAG_OCTET_STRING, len[5]); /* 6. And the inner sequence. */ + macstart = p; p = store_tag_length (p, TAG_SEQUENCE, len[6]); /* 7. Append all the buffers. */ @@ -1288,6 +1310,38 @@ create_final (struct buffer_s *sequences, size_t *r_length) p += sequences[i].length; } + /* Intermezzo to compute the MAC. */ + maclen = p - macstart; + gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); + if (string_to_key (3, salt, 8, 2048, pw, 20, keybuf)) + { + gcry_free (result); + return NULL; + } + rc = gcry_md_open (&md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); + if (rc) + { + log_error ("gcry_md_open failed: %s\n", gpg_strerror (rc)); + gcry_free (result); + return NULL; + } + rc = gcry_md_setkey (md, keybuf, 20); + if (rc) + { + log_error ("gcry_md_setkey failed: %s\n", gpg_strerror (rc)); + gcry_md_close (md); + gcry_free (result); + return NULL; + } + gcry_md_write (md, macstart, maclen); + + /* 8. Append the MAC template and fix it up. */ + memcpy (p, data_mactemplate, DIM (data_mactemplate)); + memcpy (p + DATA_MACTEMPLATE_SALT_OFF, salt, 8); + memcpy (p + DATA_MACTEMPLATE_MAC_OFF, gcry_md_read (md, 0), 20); + p += DIM (data_mactemplate); + gcry_md_close (md); + /* Ready. */ resultlen = p - result; if (needed != resultlen) @@ -1811,7 +1865,7 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, seqlist[seqlistidx].buffer = NULL; seqlist[seqlistidx].length = 0; - buffer = create_final (seqlist, &buflen); + buffer = create_final (seqlist, pw, &buflen); failure: for ( ; seqlistidx; seqlistidx--) -- cgit v1.2.3 From f98537733ac96fd7e786286944fd3c2696229c4f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jun 2006 17:21:37 +0000 Subject: Updated FSF's address. --- Makefile.am | 3 ++- NEWS | 3 +++ TODO | 5 ++--- agent/Makefile.am | 3 ++- agent/agent.h | 3 ++- agent/cache.c | 3 ++- agent/call-scd.c | 3 ++- agent/command-ssh.c | 4 ++-- agent/command.c | 3 ++- agent/divert-scd.c | 3 ++- agent/findkey.c | 3 ++- agent/genkey.c | 3 ++- agent/gpg-agent.c | 3 ++- agent/learncard.c | 3 ++- agent/minip12.c | 3 ++- agent/minip12.h | 3 ++- agent/pkdecrypt.c | 3 ++- agent/pksign.c | 3 ++- agent/preset-passphrase.c | 3 ++- agent/protect-tool.c | 3 ++- agent/protect.c | 3 ++- agent/query.c | 3 ++- agent/t-protect.c | 3 ++- agent/trans.c | 3 ++- agent/trustlist.c | 3 ++- am/cmacros.am | 3 ++- common/Makefile.am | 3 ++- common/asshelp.c | 3 ++- common/asshelp.h | 3 ++- common/b64enc.c | 3 ++- common/dynload.h | 3 ++- common/errors.h | 3 ++- common/estream.c | 37 +++++++++++++++++++------------------ common/estream.h | 37 +++++++++++++++++++------------------ common/exechelp.c | 3 ++- common/exechelp.h | 3 ++- common/gettime.c | 3 ++- common/homedir.c | 3 ++- common/i18n.h | 3 ++- common/iobuf.c | 3 ++- common/iobuf.h | 3 ++- common/isascii.c | 3 ++- common/maperror.c | 3 ++- common/membuf.c | 3 ++- common/membuf.h | 3 ++- common/miscellaneous.c | 3 ++- common/mkerrors | 3 ++- common/mkerrtok | 3 ++- common/sexp-parse.h | 3 ++- common/sexputil.c | 3 ++- common/signal.c | 3 ++- common/simple-gettext.c | 3 ++- common/simple-pwquery.c | 3 ++- common/simple-pwquery.h | 3 ++- common/sysutils.c | 3 ++- common/sysutils.h | 3 ++- common/ttyio.c | 3 ++- common/ttyio.h | 3 ++- common/util.h | 3 ++- common/vasprintf.c | 4 ++-- common/w32reg.c | 3 ++- common/xasprintf.c | 3 ++- common/xreadline.c | 3 ++- common/yesno.c | 3 ++- configure.ac | 3 ++- doc/Makefile.am | 3 ++- doc/gnupg-card-architecture.fig | 3 ++- g10/Makefile.am | 3 ++- g10/call-agent.c | 3 ++- g10/call-agent.h | 3 ++- g10/comment.c | 3 ++- g10/gpg.c | 9 +++++++++ g10/gpg.h | 3 ++- g10/pkglue.c | 3 ++- g10/pkglue.h | 3 ++- include/_regex.h | 4 ++-- include/errors.h | 3 ++- include/memory.h | 3 ++- include/mpi.h | 3 ++- include/util.h | 3 ++- jnlib/Makefile.am | 3 ++- jnlib/argparse.c | 30 ++++++++++++++++-------------- jnlib/argparse.h | 3 ++- jnlib/dotlock.c | 3 ++- jnlib/dotlock.h | 3 ++- jnlib/libjnlib-config.h | 3 ++- jnlib/logging.c | 3 ++- jnlib/logging.h | 3 ++- jnlib/mischelp.h | 3 ++- jnlib/stringhelp.c | 3 ++- jnlib/stringhelp.h | 3 ++- jnlib/strlist.c | 3 ++- jnlib/strlist.h | 3 ++- jnlib/types.h | 3 ++- jnlib/utf8conv.c | 3 ++- jnlib/utf8conv.h | 3 ++- jnlib/w32-afunix.c | 3 ++- jnlib/w32-afunix.h | 3 ++- jnlib/w32-pth.c | 3 ++- jnlib/w32-pth.h | 3 ++- jnlib/xmalloc.c | 3 ++- jnlib/xmalloc.h | 3 ++- kbx/Makefile.am | 3 ++- kbx/kbxutil.c | 3 ++- kbx/keybox-blob.c | 3 ++- kbx/keybox-defs.h | 3 ++- kbx/keybox-dump.c | 3 ++- kbx/keybox-file.c | 3 ++- kbx/keybox-init.c | 3 ++- kbx/keybox-openpgp.c | 3 ++- kbx/keybox-search-desc.h | 3 ++- kbx/keybox-search.c | 3 ++- kbx/keybox-update.c | 3 ++- kbx/keybox-util.c | 3 ++- kbx/keybox.h | 3 ++- kbx/mkerrors | 3 ++- scd/Makefile.am | 3 ++- scd/app-common.h | 3 ++- scd/app-dinsig.c | 3 ++- scd/app-help.c | 3 ++- scd/app-nks.c | 3 ++- scd/app-openpgp.c | 3 ++- scd/app-p15.c | 3 ++- scd/app.c | 3 ++- scd/atr.c | 3 ++- scd/atr.h | 3 ++- scd/card-common.h | 3 ++- scd/card-dinsig.c | 3 ++- scd/card-p15.c | 3 ++- scd/card.c | 3 ++- scd/command.c | 3 ++- scd/sc-copykeys.c | 3 ++- scd/scdaemon.c | 3 ++- scd/scdaemon.h | 3 ++- scd/tlv.c | 3 ++- scd/tlv.h | 3 ++- scripts/compile | 3 ++- scripts/config.guess | 3 ++- sm/ChangeLog | 7 +++++++ sm/Makefile.am | 3 ++- sm/base64.c | 3 ++- sm/call-agent.c | 3 ++- sm/call-dirmngr.c | 3 ++- sm/certchain.c | 3 ++- sm/certcheck.c | 3 ++- sm/certdump.c | 3 ++- sm/certlist.c | 3 ++- sm/certreqgen.c | 3 ++- sm/decrypt.c | 3 ++- sm/delete.c | 3 ++- sm/encrypt.c | 3 ++- sm/export.c | 3 ++- sm/fingerprint.c | 3 ++- sm/gpgsm.c | 16 ++++++++++++---- sm/gpgsm.h | 3 ++- sm/import.c | 3 ++- sm/keydb.c | 3 ++- sm/keydb.h | 3 ++- sm/keylist.c | 7 ++++++- sm/misc.c | 3 ++- sm/qualified.c | 3 ++- sm/server.c | 3 ++- sm/sign.c | 3 ++- sm/verify.c | 3 ++- tests/Makefile.am | 3 ++- tests/asschk.c | 3 ++- tests/pkits/Makefile.am | 3 ++- tests/pkits/common.sh | 3 ++- tests/pkits/import-all-certs | 3 ++- tests/pkits/validate-all-certs | 3 ++- tools/Makefile.am | 3 ++- tools/gpg-connect-agent.c | 3 ++- tools/gpgconf-comp.c | 36 +++++++++++++++++++----------------- tools/gpgconf.c | 3 ++- tools/gpgconf.h | 3 ++- tools/gpgkey2ssh.c | 37 +++++++++++++++++++------------------ tools/gpgparsemail.c | 3 ++- tools/no-libgcrypt.c | 3 ++- tools/symcryptrun.c | 3 ++- tools/watchgnupg.c | 3 ++- 180 files changed, 469 insertions(+), 265 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9fafb1102..0c5fbe4c3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/NEWS b/NEWS index 6413242c6..679bf7d5b 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,9 @@ Noteworthy changes in version 1.9.21 * [scdaemon] Added --hash=xxx option to the PKSIGN command. + * [gpg-protect-tool] Does now create a MAC for P12 files. This is for + better interoperability. + Noteworthy changes in version 1.9.20 (2005-12-20) ------------------------------------------------- diff --git a/TODO b/TODO index 7958ed18e..da3a76e06 100644 --- a/TODO +++ b/TODO @@ -21,7 +21,7 @@ might want to have an agent context for each service request ** When a certificate chain was sucessfully verified, make ephemeral certs used in this chain permanent. ** Try to keep certificate references somewhere This will help with some of our caching code. We also need to test - that cachining; in particular "regtp_ca_chainlen". + that caching; in particular "regtp_ca_chainlen". * sm/decrypt.c ** replace leading zero in integer hack by a cleaner solution @@ -101,7 +101,6 @@ might want to have an agent context for each service request * sm/ -** --include-certs is as of now still a dummy command line option ** check that we issue NO_SECKEY xxx if a -u key was not found * gpg/ @@ -117,4 +116,4 @@ might want to have an agent context for each service request ** ttyio Add completion support. ** yesno - Update to gpg 1.4.3 version \ No newline at end of file + Update to gpg 1.4.3 version diff --git a/agent/Makefile.am b/agent/Makefile.am index bc96531e0..961f0bb97 100644 --- a/agent/Makefile.am +++ b/agent/Makefile.am @@ -14,7 +14,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/agent/agent.h b/agent/agent.h index 1542d6b9f..fdfe510fb 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef AGENT_H diff --git a/agent/cache.c b/agent/cache.c index 32b6ac0c7..2f468396d 100644 --- a/agent/cache.c +++ b/agent/cache.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/call-scd.c b/agent/call-scd.c index ff241ce41..d0d24f9d5 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 23f083c2f..18375a9ae 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -15,8 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* Only v2 of the ssh-agent protocol is implemented. */ diff --git a/agent/command.c b/agent/command.c index daf9b8698..12770dac8 100644 --- a/agent/command.c +++ b/agent/command.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* FIXME: we should not use the default assuan buffering but setup diff --git a/agent/divert-scd.c b/agent/divert-scd.c index 926df2622..3dc7984e6 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/findkey.c b/agent/findkey.c index 73ffb530d..3f793e5dd 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/genkey.c b/agent/genkey.c index d0319f7b4..04ee865f4 100644 --- a/agent/genkey.c +++ b/agent/genkey.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 22bd5589d..fc2a2001a 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/learncard.c b/agent/learncard.c index 72238507f..8ddf4ee54 100644 --- a/agent/learncard.c +++ b/agent/learncard.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/minip12.c b/agent/minip12.c index 6f99bf24d..912d387d8 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifdef HAVE_CONFIG_H diff --git a/agent/minip12.h b/agent/minip12.h index 2fbb490d7..6275f9ccb 100644 --- a/agent/minip12.h +++ b/agent/minip12.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef MINIP12_H diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 1d64c1b15..f61f0f844 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/pksign.c b/agent/pksign.c index e9df19351..9863f9de0 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/preset-passphrase.c b/agent/preset-passphrase.c index 6a9f07a3e..013c9411d 100644 --- a/agent/preset-passphrase.c +++ b/agent/preset-passphrase.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/protect-tool.c b/agent/protect-tool.c index 5f59d5e06..bb14ca1e1 100644 --- a/agent/protect-tool.c +++ b/agent/protect-tool.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/protect.c b/agent/protect.c index 45bdae496..19f6ccbc6 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/query.c b/agent/query.c index a5a3d0153..0516bec03 100644 --- a/agent/query.c +++ b/agent/query.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/t-protect.c b/agent/t-protect.c index fee3c561d..9ddd49414 100644 --- a/agent/t-protect.c +++ b/agent/t-protect.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/agent/trans.c b/agent/trans.c index 7fa5e3d6b..5eb7d25c0 100644 --- a/agent/trans.c +++ b/agent/trans.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* To avoid any problems with the gettext implementation (there used diff --git a/agent/trustlist.c b/agent/trustlist.c index edb00650d..d234af692 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/am/cmacros.am b/am/cmacros.am index de68b6f31..7b449e2c0 100644 --- a/am/cmacros.am +++ b/am/cmacros.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. localedir = $(datadir)/locale diff --git a/common/Makefile.am b/common/Makefile.am index 34819e93f..085440bb3 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/common/asshelp.c b/common/asshelp.c index 0edaeae0e..1da899522 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/asshelp.h b/common/asshelp.h index 2d6dc79e6..9f4b5806b 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_ASSHELP_H diff --git a/common/b64enc.c b/common/b64enc.c index 5b7a42ab3..bfc49deb6 100644 --- a/common/b64enc.c +++ b/common/b64enc.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/dynload.h b/common/dynload.h index 2c074141f..9b67fa9ed 100644 --- a/common/dynload.h +++ b/common/dynload.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_DYNLOAD_H diff --git a/common/errors.h b/common/errors.h index f34f3ba79..131891f65 100644 --- a/common/errors.h +++ b/common/errors.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_ERRORS_H diff --git a/common/estream.c b/common/estream.c index 70b3d9c6e..c2030371b 100644 --- a/common/estream.c +++ b/common/estream.c @@ -1,22 +1,23 @@ /* estream.c - Extended stream I/O/ Library - Copyright (C) 2004 g10 Code GmbH - - This file is part of Libestream. - - Libestream 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. - - Libestream 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Libestream; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + * Copyright (C) 2004 g10 Code GmbH + * + * This file is part of Libestream. + * + * Libestream 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. + * + * Libestream 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Libestream; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ #ifdef USE_ESTREAM_SUPPORT_H # include <estream-support.h> diff --git a/common/estream.h b/common/estream.h index ebe575926..a9b4847c8 100644 --- a/common/estream.h +++ b/common/estream.h @@ -1,22 +1,23 @@ /* estream.h - Extended stream I/O/ Library - Copyright (C) 2004 g10 Code GmbH - - This file is part of Libestream. - - Libestream 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. - - Libestream 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Libestream; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + * Copyright (C) 2004 g10 Code GmbH + * + * This file is part of Libestream. + * + * Libestream 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. + * + * Libestream 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Libestream; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ #ifndef ESTREAM_H #define ESTREAM_H diff --git a/common/exechelp.c b/common/exechelp.c index dc0a6b0e1..e64b69022 100644 --- a/common/exechelp.c +++ b/common/exechelp.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/exechelp.h b/common/exechelp.h index f00d18dd8..1df029b7e 100644 --- a/common/exechelp.h +++ b/common/exechelp.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_EXECHELP_H diff --git a/common/gettime.c b/common/gettime.c index ecdc7df95..c4ea3283a 100644 --- a/common/gettime.c +++ b/common/gettime.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/homedir.c b/common/homedir.c index a118cbac1..39d6dce20 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/i18n.h b/common/i18n.h index 0e13dca4d..0187ba265 100644 --- a/common/i18n.h +++ b/common/i18n.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_I18N_H diff --git a/common/iobuf.c b/common/iobuf.c index bbb666f67..8f7374f8c 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/iobuf.h b/common/iobuf.h index 3b8f4b572..a3dd7f1c5 100644 --- a/common/iobuf.h +++ b/common/iobuf.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_IOBUF_H diff --git a/common/isascii.c b/common/isascii.c index 565c71664..b71febe99 100644 --- a/common/isascii.c +++ b/common/isascii.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifdef HAVE_CONFIG_H diff --git a/common/maperror.c b/common/maperror.c index 9efd64338..06546b501 100644 --- a/common/maperror.c +++ b/common/maperror.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/membuf.c b/common/membuf.c index 75f6bdb2a..2d35fefab 100644 --- a/common/membuf.c +++ b/common/membuf.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/membuf.h b/common/membuf.h index c199363cc..9033be61e 100644 --- a/common/membuf.h +++ b/common/membuf.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_MEMBUF_H diff --git a/common/miscellaneous.c b/common/miscellaneous.c index e9f8ed27f..da74f65bc 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/mkerrors b/common/mkerrors index 5a1ef33da..994c61352 100755 --- a/common/mkerrors +++ b/common/mkerrors @@ -17,7 +17,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. cat <<EOF /* Generated automatically by mkerrors */ diff --git a/common/mkerrtok b/common/mkerrtok index 1029614af..67ab42c89 100755 --- a/common/mkerrtok +++ b/common/mkerrtok @@ -17,7 +17,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. cat <<EOF /* Generated automatically by mkerrtok */ diff --git a/common/sexp-parse.h b/common/sexp-parse.h index 89aa7210f..1064e51c4 100644 --- a/common/sexp-parse.h +++ b/common/sexp-parse.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef SEXP_PARSE_H diff --git a/common/sexputil.c b/common/sexputil.c index 8a27ad978..fe0870c56 100644 --- a/common/sexputil.c +++ b/common/sexputil.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* This file implements a few utility functions useful when working diff --git a/common/signal.c b/common/signal.c index 2837d7b72..0c79214b2 100644 --- a/common/signal.c +++ b/common/signal.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/simple-gettext.c b/common/simple-gettext.c index b6b851c77..56a305fd8 100644 --- a/common/simple-gettext.c +++ b/common/simple-gettext.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* This is a simplified version of gettext written by Ulrich Drepper. diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c index f156ca3f1..e405c1ec0 100644 --- a/common/simple-pwquery.c +++ b/common/simple-pwquery.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* This module is intended as a standalone client implementation to diff --git a/common/simple-pwquery.h b/common/simple-pwquery.h index e3270d6c5..5b941d06f 100644 --- a/common/simple-pwquery.h +++ b/common/simple-pwquery.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef SIMPLE_PWQUERY_H diff --git a/common/sysutils.c b/common/sysutils.c index a8f6f6f5d..3e52cdaa3 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/sysutils.h b/common/sysutils.h index 08198f685..c40dbfaa9 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_SYSUTILS_H diff --git a/common/ttyio.c b/common/ttyio.c index c9f41c626..38883afa5 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/ttyio.h b/common/ttyio.h index 6148d644a..32d159863 100644 --- a/common/ttyio.h +++ b/common/ttyio.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_TTYIO_H #define GNUPG_COMMON_TTYIO_H diff --git a/common/util.h b/common/util.h index 295d785c5..29106bf9c 100644 --- a/common/util.h +++ b/common/util.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_COMMON_UTIL_H diff --git a/common/vasprintf.c b/common/vasprintf.c index 9efea33f2..4bed8de66 100644 --- a/common/vasprintf.c +++ b/common/vasprintf.c @@ -15,8 +15,8 @@ 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. */ +not, write to the Free Software Foundation, Inc., 51 Franklin Street, +Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include <config.h> diff --git a/common/w32reg.c b/common/w32reg.c index a85ac7348..84308e916 100644 --- a/common/w32reg.c +++ b/common/w32reg.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/xasprintf.c b/common/xasprintf.c index 46740a2e6..75ae18072 100644 --- a/common/xasprintf.c +++ b/common/xasprintf.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/xreadline.c b/common/xreadline.c index 23aa35269..8400df330 100644 --- a/common/xreadline.c +++ b/common/xreadline.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/common/yesno.c b/common/yesno.c index 737071691..9ca513740 100644 --- a/common/yesno.c +++ b/common/yesno.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/configure.ac b/configure.ac index f3066a0a9..d77093a63 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. # Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) diff --git a/doc/Makefile.am b/doc/Makefile.am index 47dd36208..dae053ec2 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -14,7 +14,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/doc/gnupg-card-architecture.fig b/doc/gnupg-card-architecture.fig index e5772cd0f..49351c720 100644 --- a/doc/gnupg-card-architecture.fig +++ b/doc/gnupg-card-architecture.fig @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. Landscape Center Metric diff --git a/g10/Makefile.am b/g10/Makefile.am index aeb24d7b3..fb54dd9f0 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/g10/call-agent.c b/g10/call-agent.c index 55fc62569..e3bd7ed57 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #if 0 /* let Emacs display a red warning */ diff --git a/g10/call-agent.h b/g10/call-agent.h index 71044e38b..d09b87e3a 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_G10_CALL_AGENT_H #define GNUPG_G10_CALL_AGENT_H diff --git a/g10/comment.c b/g10/comment.c index b52104cd7..193087107 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/g10/gpg.c b/g10/gpg.c index 52ae553c1..4235f3f7a 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -356,6 +356,7 @@ enum cmd_and_opt_values oAllowMultisigVerification, oEnableDSA2, oDisableDSA2, + oDebugAllowRun, oNoop }; @@ -701,6 +702,8 @@ static ARGPARSE_OPTS opts[] = { { oNoRequireCrossCert, "no-require-cross-certification", 0, "@"}, { oAutoKeyLocate, "auto-key-locate", 2, "@"}, { oNoAutoKeyLocate, "no-auto-key-locate", 0, "@"}, + + { oDebugAllowRun, "debug_allow_run", 0, "@"}, {0,NULL,0,NULL} }; @@ -1684,6 +1687,7 @@ main (int argc, char **argv ) int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; int require_secmem=0,got_secmem=0; + int allow_run = 0; #ifdef __riscos__ opt.lock_once = 1; @@ -2663,6 +2667,8 @@ main (int argc, char **argv ) case oEnableDSA2: opt.flags.dsa2=1; break; case oDisableDSA2: opt.flags.dsa2=0; break; + case oDebugAllowRun: allow_run = 1; break; + case oNoop: break; default : pargs.err = configfp? 1:2; break; @@ -2716,6 +2722,9 @@ main (int argc, char **argv ) } #endif + if (!allow_run) + log_fatal ("This version of gpg is not ready for use, use gpg 1.4.x\n"); + /* FIXME: We should use logging to a file only in server mode; however we have not yet implemetyed that. Thus we try to get away with --batch as indication for logging to file diff --git a/g10/gpg.h b/g10/gpg.h index 8ef46fdca..100a8e349 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_G10_GPG_H #define GNUPG_G10_GPG_H diff --git a/g10/pkglue.c b/g10/pkglue.c index f062d8366..3f9669d27 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/g10/pkglue.h b/g10/pkglue.h index 43b82785b..866960bfd 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_G10_PKGLUE_H diff --git a/include/_regex.h b/include/_regex.h index fac441dc6..ddd002484 100644 --- a/include/_regex.h +++ b/include/_regex.h @@ -16,8 +16,8 @@ You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ #ifndef _REGEX_H #define _REGEX_H 1 diff --git a/include/errors.h b/include/errors.h index ed437fa99..f3269ce5b 100644 --- a/include/errors.h +++ b/include/errors.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_INCLUDE_ERRORS_H #define GNUPG_INCLUDE_ERRORS_H diff --git a/include/memory.h b/include/memory.h index 35719da62..2e2f8fdce 100644 --- a/include/memory.h +++ b/include/memory.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_MEMORY_H diff --git a/include/mpi.h b/include/mpi.h index b732923a2..7402ef6d3 100644 --- a/include/mpi.h +++ b/include/mpi.h @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * Note: This code is heavily based on the GNU MP Library. * Actually it's the same code with only minor changes in the diff --git a/include/util.h b/include/util.h index c579c152e..1d6d01366 100644 --- a/include/util.h +++ b/include/util.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef G10_UTIL_H #define G10_UTIL_H diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index 69eac4bf7..5fd48495c 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -14,7 +14,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/jnlib/argparse.c b/jnlib/argparse.c index 980d1186c..15a7c546e 100644 --- a/jnlib/argparse.c +++ b/jnlib/argparse.c @@ -1,21 +1,22 @@ /* [argparse.c wk 17.06.97] Argument Parser for option handling * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * - * This file is part of GnuPG. + * 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 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. + * 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 + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -904,7 +905,7 @@ strusage( int level ) switch( level ) { case 11: p = "foo"; break; case 13: p = "0.0"; break; - case 14: p = "Copyright (C) 2005 Free Software Foundation, Inc."; break; + case 14: p = "Copyright (C) 2006 Free Software Foundation, Inc."; break; case 15: p = "This program comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" @@ -920,7 +921,8 @@ strusage( int level ) "GNU General Public License for more details.\n\n" "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"; +"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n" +"USA.\n"; break; case 40: /* short and long usage */ case 41: p = ""; break; diff --git a/jnlib/argparse.h b/jnlib/argparse.h index e8922faa4..531622ea5 100644 --- a/jnlib/argparse.h +++ b/jnlib/argparse.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_ARGPARSE_H diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index b7f892717..89edb7b91 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h index 2cb39008a..1c0f05cb2 100644 --- a/jnlib/dotlock.h +++ b/jnlib/dotlock.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_DOTLOCK_H diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h index da3991432..ded6e057b 100644 --- a/jnlib/libjnlib-config.h +++ b/jnlib/libjnlib-config.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /**************** diff --git a/jnlib/logging.c b/jnlib/logging.c index c944006a5..20ba02ccd 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ diff --git a/jnlib/logging.h b/jnlib/logging.h index b5c0bd741..3ad43b4ec 100644 --- a/jnlib/logging.h +++ b/jnlib/logging.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_LOGGING_H diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h index 54da4cc1f..8e7f9c346 100644 --- a/jnlib/mischelp.h +++ b/jnlib/mischelp.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_MISCHELP_H diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 27b8a25e8..9df852754 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index 405d6dbc4..b8f4dbec0 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_STRINGHELP_H diff --git a/jnlib/strlist.c b/jnlib/strlist.c index 52b4d5869..87e121705 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 3c1252a44..ee9f1fa60 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_STRLIST_H diff --git a/jnlib/types.h b/jnlib/types.h index 934b7a6ee..89d245943 100644 --- a/jnlib/types.h +++ b/jnlib/types.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_TYPES_H diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c index 4df8b7b32..9fba1ed4f 100644 --- a/jnlib/utf8conv.c +++ b/jnlib/utf8conv.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/jnlib/utf8conv.h b/jnlib/utf8conv.h index 6e2ce9944..344c47f92 100644 --- a/jnlib/utf8conv.h +++ b/jnlib/utf8conv.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_UTF8CONF_H diff --git a/jnlib/w32-afunix.c b/jnlib/w32-afunix.c index c93d389da..84d799f1f 100644 --- a/jnlib/w32-afunix.c +++ b/jnlib/w32-afunix.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifdef _WIN32 #include <stdio.h> diff --git a/jnlib/w32-afunix.h b/jnlib/w32-afunix.h index 367832299..d0eb8cf7e 100644 --- a/jnlib/w32-afunix.h +++ b/jnlib/w32-afunix.h @@ -15,7 +15,8 @@ * * You should have received a copy of the GNU Lesser 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifdef _WIN32 #ifndef W32AFUNIX_DEFS_H diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c index 2f041c490..4107c7cb3 100644 --- a/jnlib/w32-pth.c +++ b/jnlib/w32-pth.c @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU Lesser 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * ------------------------------------------------------------------ * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h index 5ef0ab240..524010d92 100644 --- a/jnlib/w32-pth.h +++ b/jnlib/w32-pth.h @@ -16,7 +16,8 @@ * * You should have received a copy of the GNU Lesser 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * ------------------------------------------------------------------ * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive diff --git a/jnlib/xmalloc.c b/jnlib/xmalloc.c index 1cfaab9f7..f5b92ba41 100644 --- a/jnlib/xmalloc.c +++ b/jnlib/xmalloc.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/jnlib/xmalloc.h b/jnlib/xmalloc.h index 150ef3664..8bfa7df79 100644 --- a/jnlib/xmalloc.h +++ b/jnlib/xmalloc.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef LIBJNLIB_XMALLOC_H diff --git a/kbx/Makefile.am b/kbx/Makefile.am index f42e517bf..063dbb4c0 100644 --- a/kbx/Makefile.am +++ b/kbx/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 0569b5a67..19d356007 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox-blob.c b/kbx/keybox-blob.c index eacc0014a..f3fe31617 100644 --- a/kbx/keybox-blob.c +++ b/kbx/keybox-blob.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 7bbed8519..ad53c71a7 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef KEYBOX_DEFS_H diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index 495fb249e..d28611377 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c index 3883ce607..e68e96cf9 100644 --- a/kbx/keybox-file.c +++ b/kbx/keybox-file.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox-init.c b/kbx/keybox-init.c index 46a29978a..6c01b4f3a 100644 --- a/kbx/keybox-init.c +++ b/kbx/keybox-init.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 7401949c9..8ac713979 100644 --- a/kbx/keybox-openpgp.c +++ b/kbx/keybox-openpgp.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* This is a simple OpenPGP parser suitable for all OpenPGP key diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h index 4be59c27d..f3a69d0f1 100644 --- a/kbx/keybox-search-desc.h +++ b/kbx/keybox-search-desc.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index 2ce3c1923..f95e6eb06 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index a16c18e23..bb43d287b 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox-util.c b/kbx/keybox-util.c index ed5d93de0..6eb85ba3f 100644 --- a/kbx/keybox-util.c +++ b/kbx/keybox-util.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/kbx/keybox.h b/kbx/keybox.h index af1fc4516..0f97fb7fc 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef KEYBOX_H diff --git a/kbx/mkerrors b/kbx/mkerrors index 5adb7bfdf..d3d096c5d 100755 --- a/kbx/mkerrors +++ b/kbx/mkerrors @@ -17,7 +17,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. cat <<EOF /* Generated automatically by mkerrors */ diff --git a/scd/Makefile.am b/scd/Makefile.am index 46f6b9fa3..61c0c05d9 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -14,7 +14,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/scd/app-common.h b/scd/app-common.h index d294a5c25..3b828780d 100644 --- a/scd/app-common.h +++ b/scd/app-common.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * $Id$ */ diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c index 75cd12c59..752e8a346 100644 --- a/scd/app-dinsig.c +++ b/scd/app-dinsig.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ diff --git a/scd/app-help.c b/scd/app-help.c index 27cbea5c7..861d8e3bc 100644 --- a/scd/app-help.c +++ b/scd/app-help.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/app-nks.c b/scd/app-nks.c index 73ec8ea01..1ca8d4187 100644 --- a/scd/app-nks.c +++ b/scd/app-nks.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 5e9281a38..842881f3a 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. * * $Id$ */ diff --git a/scd/app-p15.c b/scd/app-p15.c index 4203a6840..8a7732c85 100644 --- a/scd/app-p15.c +++ b/scd/app-p15.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* Information pertaining to the BELPIC developer card samples: diff --git a/scd/app.c b/scd/app.c index 363e386ce..e3d42054b 100644 --- a/scd/app.c +++ b/scd/app.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/atr.c b/scd/atr.c index 6475e83f8..bd5a22621 100644 --- a/scd/atr.c +++ b/scd/atr.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/atr.h b/scd/atr.h index 5fdd57457..c70089ca5 100644 --- a/scd/atr.h +++ b/scd/atr.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef ATR_H diff --git a/scd/card-common.h b/scd/card-common.h index cefaf120f..dd7529d5b 100644 --- a/scd/card-common.h +++ b/scd/card-common.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef CARD_COMMON_H diff --git a/scd/card-dinsig.c b/scd/card-dinsig.c index df09bfb57..d50d758f2 100644 --- a/scd/card-dinsig.c +++ b/scd/card-dinsig.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* The German signature law and its bylaw (SigG and SigV) is currently diff --git a/scd/card-p15.c b/scd/card-p15.c index ae3ef148f..63d537d5a 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/card.c b/scd/card.c index 9ec2a52c5..7a41ab7bb 100644 --- a/scd/card.c +++ b/scd/card.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/command.c b/scd/command.c index 2ed685587..4629d9edf 100644 --- a/scd/command.c +++ b/scd/command.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c index 66b6894e0..395b4625a 100644 --- a/scd/sc-copykeys.c +++ b/scd/sc-copykeys.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/scdaemon.c b/scd/scdaemon.c index e24b42132..b11cc7a91 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/scdaemon.h b/scd/scdaemon.h index abe9730a7..f9689ee09 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef SCDAEMON_H diff --git a/scd/tlv.c b/scd/tlv.c index b436d956a..6ddbeaf1f 100644 --- a/scd/tlv.c +++ b/scd/tlv.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/scd/tlv.h b/scd/tlv.h index f587dd9df..877573d25 100644 --- a/scd/tlv.h +++ b/scd/tlv.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef SCD_TLV_H diff --git a/scripts/compile b/scripts/compile index ac07cc541..b6e6dcb0f 100755 --- a/scripts/compile +++ b/scripts/compile @@ -17,7 +17,8 @@ # # 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. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA.. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a diff --git a/scripts/config.guess b/scripts/config.guess index 77c7cbab0..a4929a979 100755 --- a/scripts/config.guess +++ b/scripts/config.guess @@ -17,7 +17,8 @@ timestamp='2004-08-13' # # 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. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA.. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a diff --git a/sm/ChangeLog b/sm/ChangeLog index 48e8473fa..f191e7512 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,10 @@ +2006-06-20 Werner Koch <wk@g10code.com> + + * gpgsm.c (gpgsm_init_default_ctrl): Take care of the command line + option --include-certs. + + * keylist.c (list_cert_raw): Print the certid. + 2006-05-23 Werner Koch <wk@g10code.com> * keydb.c (hextobyte): Deleted as it is now defined in jnlib. diff --git a/sm/Makefile.am b/sm/Makefile.am index b5882ae1d..be53e8d25 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -14,7 +14,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/sm/base64.c b/sm/base64.c index 62c2c9ad9..59ab6f24b 100644 --- a/sm/base64.c +++ b/sm/base64.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/call-agent.c b/sm/call-agent.c index 9942672ae..85ec78c63 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 85467d4a2..0de09a9ba 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/certchain.c b/sm/certchain.c index 44d72efd3..4a4ac49f6 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/certcheck.c b/sm/certcheck.c index 5fb376712..732356149 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/certdump.c b/sm/certdump.c index 1f2ea7b18..0d5146abc 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/certlist.c b/sm/certlist.c index b036a85d7..cde2930ec 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/certreqgen.c b/sm/certreqgen.c index c523c992a..744969719 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* diff --git a/sm/decrypt.c b/sm/decrypt.c index 9e5518b0f..70d48c983 100644 --- a/sm/decrypt.c +++ b/sm/decrypt.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/delete.c b/sm/delete.c index 7533f7291..0d2f1fd9d 100644 --- a/sm/delete.c +++ b/sm/delete.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/encrypt.c b/sm/encrypt.c index e4c0d5437..07c2ba8ce 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/export.c b/sm/export.c index f9d6dac62..b08a017d2 100644 --- a/sm/export.c +++ b/sm/export.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/fingerprint.c b/sm/fingerprint.c index 9441483bf..d6a3900f0 100644 --- a/sm/fingerprint.c +++ b/sm/fingerprint.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 7347bf575..5363b8ad6 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1,5 +1,6 @@ /* gpgsm.c - GnuPG for S/MIME - * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -15,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -461,6 +463,10 @@ static unsigned int debug_value; /* Option --enable-special-filenames */ static int allow_special_filenames; +/* Default value for include-certs. */ +static int default_include_certs = 1; /* Only include the signer's cert. */ + + static char *build_list (const char *text, const char *(*mapf)(int), int (*chkf)(int)); @@ -998,7 +1004,9 @@ main ( int argc, char **argv) ctrl.use_ocsp = opt.enable_ocsp = 1; break; - case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break; + case oIncludeCerts: + ctrl.include_certs = default_include_certs = pargs.r.ret_int; + break; case oPolicyFile: xfree (opt.policy_file); @@ -1657,7 +1665,7 @@ gpgsm_exit (int rc) void gpgsm_init_default_ctrl (struct server_control_s *ctrl) { - ctrl->include_certs = 1; /* only include the signer's cert */ + ctrl->include_certs = default_include_certs; ctrl->use_ocsp = opt.enable_ocsp; } diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 438252050..b49f34640 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GPGSM_H diff --git a/sm/import.c b/sm/import.c index 6d00e91ea..b56014a1a 100644 --- a/sm/import.c +++ b/sm/import.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/keydb.c b/sm/keydb.c index d5932135d..81936cf6a 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/keydb.h b/sm/keydb.h index fb4001b64..814ae9f1e 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GNUPG_KEYDB_H diff --git a/sm/keylist.c b/sm/keylist.c index b744a157f..9baf065d0 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -16,7 +16,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> @@ -598,6 +599,10 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, fprintf (fp, " md5_fpr: %s\n", dn?dn:"error"); xfree (dn); + dn = gpgsm_get_certid (cert); + fprintf (fp, " certid: %s\n", dn?dn:"error"); + xfree (dn); + dn = gpgsm_get_keygrip_hexstring (cert); fprintf (fp, " keygrip: %s\n", dn?dn:"error"); xfree (dn); diff --git a/sm/misc.c b/sm/misc.c index cd072ce6b..86cb506d6 100644 --- a/sm/misc.c +++ b/sm/misc.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/qualified.c b/sm/qualified.c index 07abaadc4..474e1488d 100644 --- a/sm/qualified.c +++ b/sm/qualified.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/server.c b/sm/server.c index 87a06ee4e..57e5d8f38 100644 --- a/sm/server.c +++ b/sm/server.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/sign.c b/sm/sign.c index 74bfe41aa..d656825e8 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/sm/verify.c b/sm/verify.c index f37cf4a75..4e6574078 100644 --- a/sm/verify.c +++ b/sm/verify.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/tests/Makefile.am b/tests/Makefile.am index 5264b8859..38b64c6ea 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/tests/asschk.c b/tests/asschk.c index 6a05fe1a8..40b95ba7d 100644 --- a/tests/asschk.c +++ b/tests/asschk.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ /* This is a simple stand-alone Assuan server test program. We don't diff --git a/tests/pkits/Makefile.am b/tests/pkits/Makefile.am index 41fdec497..d53d35a25 100644 --- a/tests/pkits/Makefile.am +++ b/tests/pkits/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. ## Process this file with automake to produce Makefile.in diff --git a/tests/pkits/common.sh b/tests/pkits/common.sh index 5e773ea5d..09fb62bc8 100644 --- a/tests/pkits/common.sh +++ b/tests/pkits/common.sh @@ -16,7 +16,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. # reset some environment variables because we do not want to test locals export LANG=C diff --git a/tests/pkits/import-all-certs b/tests/pkits/import-all-certs index d1af5fb03..2d70d06df 100755 --- a/tests/pkits/import-all-certs +++ b/tests/pkits/import-all-certs @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. . ${srcdir:-.}/common.sh || exit 2 diff --git a/tests/pkits/validate-all-certs b/tests/pkits/validate-all-certs index f482fdb51..08f72af71 100755 --- a/tests/pkits/validate-all-certs +++ b/tests/pkits/validate-all-certs @@ -16,7 +16,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. . ${srcdir:-.}/common.sh || exit 2 diff --git a/tools/Makefile.am b/tools/Makefile.am index d9ef8812a..6b4767a79 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -15,7 +15,8 @@ # # 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 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. EXTRA_DIST = Manifest watchgnupg.c \ addgnupghome gpgsm-gencert.sh diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index c9a324fa8..90e321000 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 2da88bc49..04a61a193 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -1,21 +1,23 @@ /* gpgconf-comp.c - Configuration utility for GnuPG. - 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 GnuPG; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + * 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 GnuPG; if not, write to the Free Software Foundation, + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ #if HAVE_CONFIG_H #include <config.h> diff --git a/tools/gpgconf.c b/tools/gpgconf.c index dd505e99d..87ba45ae1 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/tools/gpgconf.h b/tools/gpgconf.h index 138380b6d..c083c26aa 100644 --- a/tools/gpgconf.h +++ b/tools/gpgconf.h @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifndef GPGCONF_H diff --git a/tools/gpgkey2ssh.c b/tools/gpgkey2ssh.c index e874ab22e..3dcb6516e 100644 --- a/tools/gpgkey2ssh.c +++ b/tools/gpgkey2ssh.c @@ -1,22 +1,23 @@ /* gpgkey2ssh.c - Converter ... - Copyright (C) 2005 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. */ + * Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ #include <config.h> diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c index 566f5747f..30759f9a4 100644 --- a/tools/gpgparsemail.c +++ b/tools/gpgparsemail.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c index 82f6a8bb5..636df10c6 100644 --- a/tools/no-libgcrypt.c +++ b/tools/no-libgcrypt.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include <config.h> diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c index 075e0b444..406cbb2a2 100644 --- a/tools/symcryptrun.c +++ b/tools/symcryptrun.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c index 6cb570fbc..051ca50fe 100644 --- a/tools/watchgnupg.c +++ b/tools/watchgnupg.c @@ -15,7 +15,8 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #ifdef HAVE_CONFIG_H -- cgit v1.2.3 From 8d8ddd7abe1889de2690db378acc9641e02afc1c Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jun 2006 17:47:10 +0000 Subject: Made make distcheck work again --- doc/Makefile.am | 7 +- doc/debugging.texi | 2 +- doc/gnupg-badge-openpgp.pdf | Bin 0 -> 30820 bytes doc/gnupg.texi | 4 +- doc/gpg-agent.texi | 2 - doc/scdaemon.texi | 2 +- po/de.po | 730 ++++++++++++++++++++++---------------------- 7 files changed, 379 insertions(+), 368 deletions(-) create mode 100644 doc/gnupg-badge-openpgp.pdf diff --git a/doc/Makefile.am b/doc/Makefile.am index dae053ec2..6c56ae2d3 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -20,9 +20,12 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = gnupg-badge-openpgp.eps gnupg-badge-openpgp.jpg \ - gnupg-card-architecture.eps gnupg-card-architecture.png + gnupg-badge-openpgp.pdf \ + gnupg-card-architecture.eps gnupg-card-architecture.png \ + gnupg-card-architecture.pdf -BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png +BUILT_SOURCES = gnupg-card-architecture.eps gnupg-card-architecture.png \ + gnupg-card-architecture.pdf info_TEXINFOS = gnupg.texi diff --git a/doc/debugging.texi b/doc/debugging.texi index 429dbd407..6c696abf2 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -144,7 +144,7 @@ making use of ssh. Here is a little picture showing how the components work together: -@image{gnupg-card-architecture, 14cm} +@image{gnupg-card-architecture, 10cm} @noindent Lets try to explain it: diff --git a/doc/gnupg-badge-openpgp.pdf b/doc/gnupg-badge-openpgp.pdf new file mode 100644 index 000000000..bd647016a Binary files /dev/null and b/doc/gnupg-badge-openpgp.pdf differ diff --git a/doc/gnupg.texi b/doc/gnupg.texi index efa54bd14..dd0b12fc6 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -85,11 +85,11 @@ section entitled ``Copying''. @subtitle Version @value{VERSION} @subtitle @value{UPDATED} -@sp 6 +@sp 3 @image{gnupg-badge-openpgp,8cm,,The GnuPG Logo} -@sp 6 +@sp 3 @author Werner Koch (@email{wk@@gnupg.org}) diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index 066f8e937..39b79d306 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -1028,5 +1028,3 @@ Set the startup TTY and X-DISPLAY variables to the values of this session. This command is useful to direct future pinentry invocations to another screen. It is only required because there is no way in the ssh-agent protocol to convey this information. - - diff --git a/doc/scdaemon.texi b/doc/scdaemon.texi index 847001669..6ddb55679 100644 --- a/doc/scdaemon.texi +++ b/doc/scdaemon.texi @@ -1,4 +1,4 @@ -g@c Copyright (C) 2002 Free Software Foundation, Inc. +@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. diff --git a/po/de.po b/po/de.po index 2201c0429..5d9d50221 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2005-11-28 12:14+0100\n" +"POT-Creation-Date: 2006-06-20 18:45+0200\n" "PO-Revision-Date: 2005-11-28 12:16+0100\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: agent/gpg-agent.c:108 agent/protect-tool.c:108 scd/scdaemon.c:100 +#: agent/gpg-agent.c:109 agent/protect-tool.c:109 scd/scdaemon.c:101 msgid "" "@Options:\n" " " @@ -26,110 +26,110 @@ msgstr "" "@Optionen:\n" " " -#: agent/gpg-agent.c:110 scd/scdaemon.c:102 +#: agent/gpg-agent.c:111 scd/scdaemon.c:103 msgid "run in server mode (foreground)" msgstr "Im Server Modus ausführen" -#: agent/gpg-agent.c:111 scd/scdaemon.c:105 +#: agent/gpg-agent.c:112 scd/scdaemon.c:106 msgid "run in daemon mode (background)" msgstr "Im Daemon Modus ausführen" -#: agent/gpg-agent.c:112 kbx/kbxutil.c:81 scd/scdaemon.c:106 sm/gpgsm.c:331 -#: tools/gpgconf.c:62 +#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:107 sm/gpgsm.c:333 +#: tools/gpgconf.c:63 msgid "verbose" msgstr "ausführlich" -#: agent/gpg-agent.c:113 kbx/kbxutil.c:82 scd/scdaemon.c:107 sm/gpgsm.c:332 +#: agent/gpg-agent.c:114 kbx/kbxutil.c:83 scd/scdaemon.c:108 sm/gpgsm.c:334 msgid "be somewhat more quiet" msgstr "Etwas weniger Ausgaben erzeugen" -#: agent/gpg-agent.c:114 scd/scdaemon.c:108 +#: agent/gpg-agent.c:115 scd/scdaemon.c:109 msgid "sh-style command output" msgstr "Ausgabe für /bin/sh" -#: agent/gpg-agent.c:115 scd/scdaemon.c:109 +#: agent/gpg-agent.c:116 scd/scdaemon.c:110 msgid "csh-style command output" msgstr "Ausgabe für /bin/csh" -#: agent/gpg-agent.c:116 +#: agent/gpg-agent.c:117 msgid "|FILE|read options from FILE" msgstr "|DATEI|Konfigurationsoptionen aus DATEI lesen" -#: agent/gpg-agent.c:121 scd/scdaemon.c:118 +#: agent/gpg-agent.c:122 scd/scdaemon.c:119 msgid "do not detach from the console" msgstr "Im Vordergrund laufen lassen" -#: agent/gpg-agent.c:122 +#: agent/gpg-agent.c:123 msgid "do not grab keyboard and mouse" msgstr "Tastatur und Maus nicht \"grabben\"" -#: agent/gpg-agent.c:123 scd/scdaemon.c:119 sm/gpgsm.c:334 +#: agent/gpg-agent.c:124 scd/scdaemon.c:120 sm/gpgsm.c:336 msgid "use a log file for the server" msgstr "Logausgaben in eine Datei umlenken" -#: agent/gpg-agent.c:125 +#: agent/gpg-agent.c:126 msgid "use a standard location for the socket" msgstr "Benutze einen Standardnamen für den Socket" -#: agent/gpg-agent.c:129 +#: agent/gpg-agent.c:130 msgid "|PGM|use PGM as the PIN-Entry program" msgstr "|PGM|benutze PGM as PIN-Entry" -#: agent/gpg-agent.c:131 +#: agent/gpg-agent.c:132 msgid "|PGM|use PGM as the SCdaemon program" msgstr "|PGM|benutze PGM as SCdaemon" -#: agent/gpg-agent.c:132 +#: agent/gpg-agent.c:133 msgid "do not use the SCdaemon" msgstr "Den Scdaemon basierten Kartenzugriff nicht nutzen" -#: agent/gpg-agent.c:139 +#: agent/gpg-agent.c:140 msgid "ignore requests to change the TTY" msgstr "Ignoriere Anfragen, das TTY zu wechseln" -#: agent/gpg-agent.c:141 +#: agent/gpg-agent.c:142 msgid "ignore requests to change the X display" msgstr "Ignoriere Anfragen, das X-Display zu wechseln" -#: agent/gpg-agent.c:144 +#: agent/gpg-agent.c:145 msgid "|N|expire cached PINs after N seconds" msgstr "|N|lasse PINs im Cache nach N Sekunden verfallen" -#: agent/gpg-agent.c:149 +#: agent/gpg-agent.c:150 msgid "do not use the PIN cache when signing" msgstr "benutze PINs im Cache nicht bem Signieren" -#: agent/gpg-agent.c:151 +#: agent/gpg-agent.c:152 msgid "allow clients to mark keys as \"trusted\"" msgstr "erlaube Aufrufern Schlüssel als \"vertrauenswürdig\" zu markieren" -#: agent/gpg-agent.c:153 +#: agent/gpg-agent.c:154 msgid "allow presetting passphrase" msgstr "erlaube ein \"preset\" von Passphrases" -#: agent/gpg-agent.c:154 +#: agent/gpg-agent.c:155 msgid "enable ssh-agent emulation" msgstr "Die ssh-agent Emulation anschalten" -#: agent/gpg-agent.c:156 +#: agent/gpg-agent.c:157 msgid "|FILE|write environment settings also to FILE" msgstr "|DATEI|Schreibe die Umgebungsvariabeln auf DATEI" -#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:185 -#: sm/gpgsm.c:507 tools/gpgconf.c:85 +#: agent/gpg-agent.c:236 agent/protect-tool.c:143 scd/scdaemon.c:188 +#: sm/gpgsm.c:513 tools/gpgconf.c:86 msgid "Please report bugs to <" msgstr "Fehlerberichte bitte an <" -#: agent/gpg-agent.c:235 agent/protect-tool.c:142 scd/scdaemon.c:185 -#: sm/gpgsm.c:507 tools/gpgconf.c:85 +#: agent/gpg-agent.c:236 agent/protect-tool.c:143 scd/scdaemon.c:188 +#: sm/gpgsm.c:513 tools/gpgconf.c:86 msgid ">.\n" msgstr ">.\n" -#: agent/gpg-agent.c:238 +#: agent/gpg-agent.c:239 msgid "Usage: gpg-agent [options] (-h for help)" msgstr "Gebrauch: gpg-agent [Optionen] (-h für Hilfe)" -#: agent/gpg-agent.c:240 +#: agent/gpg-agent.c:241 msgid "" "Syntax: gpg-agent [options] [command [args]]\n" "Secret key management for GnuPG\n" @@ -137,132 +137,132 @@ msgstr "" "Syntax: gpg-agent [Optionen] [Kommando [Argumente]]\n" "Verwaltung von geheimen Schlüssel für GnuPG\n" -#: agent/gpg-agent.c:311 scd/scdaemon.c:259 sm/gpgsm.c:636 +#: agent/gpg-agent.c:312 scd/scdaemon.c:262 sm/gpgsm.c:642 #, c-format msgid "invalid debug-level `%s' given\n" msgstr "ungültige Debugebene `%s' angegeben\n" -#: agent/gpg-agent.c:482 agent/protect-tool.c:1072 kbx/kbxutil.c:431 -#: scd/scdaemon.c:351 sm/gpgsm.c:757 +#: agent/gpg-agent.c:483 agent/protect-tool.c:1073 kbx/kbxutil.c:432 +#: scd/scdaemon.c:354 sm/gpgsm.c:763 #, c-format msgid "libgcrypt is too old (need %s, have %s)\n" msgstr "" "Die Bibliothek \"libgcrypt\" is zu alt (benötigt wird %s, vorhanden ist %s)\n" -#: agent/gpg-agent.c:574 scd/scdaemon.c:426 sm/gpgsm.c:858 +#: agent/gpg-agent.c:575 scd/scdaemon.c:429 sm/gpgsm.c:864 #, c-format msgid "NOTE: no default option file `%s'\n" msgstr "Notiz: Voreingestellte Konfigurationsdatei `%s' fehlt\n" -#: agent/gpg-agent.c:579 agent/gpg-agent.c:1090 scd/scdaemon.c:431 -#: sm/gpgsm.c:862 +#: agent/gpg-agent.c:580 agent/gpg-agent.c:1091 scd/scdaemon.c:434 +#: sm/gpgsm.c:868 #, c-format msgid "option file `%s': %s\n" msgstr "Konfigurationsdatei `%s': %s\n" -#: agent/gpg-agent.c:587 scd/scdaemon.c:439 sm/gpgsm.c:869 +#: agent/gpg-agent.c:588 scd/scdaemon.c:442 sm/gpgsm.c:875 #, c-format msgid "reading options from `%s'\n" msgstr "Optionen werden aus `%s' gelesen\n" -#: agent/gpg-agent.c:884 +#: agent/gpg-agent.c:885 #, c-format msgid "error creating `%s': %s\n" msgstr "Fehler beim Erstellen von `%s': %s\n" -#: agent/gpg-agent.c:1140 agent/gpg-agent.c:1243 agent/gpg-agent.c:1247 -#: agent/gpg-agent.c:1283 agent/gpg-agent.c:1287 scd/scdaemon.c:906 +#: agent/gpg-agent.c:1141 agent/gpg-agent.c:1244 agent/gpg-agent.c:1248 +#: agent/gpg-agent.c:1284 agent/gpg-agent.c:1288 scd/scdaemon.c:909 #, c-format msgid "can't create directory `%s': %s\n" msgstr "Das Verzeichniss `%s' kann nicht erstellt werden: %s\n" -#: agent/gpg-agent.c:1154 scd/scdaemon.c:920 +#: agent/gpg-agent.c:1155 scd/scdaemon.c:923 msgid "name of socket too long\n" msgstr "Der Name des Sockets ist zu lang\n" -#: agent/gpg-agent.c:1180 scd/scdaemon.c:946 +#: agent/gpg-agent.c:1181 scd/scdaemon.c:949 #, c-format msgid "can't create socket: %s\n" msgstr "Socket kann nicht erzeugt werden: %s\n" -#: agent/gpg-agent.c:1209 scd/scdaemon.c:975 +#: agent/gpg-agent.c:1210 scd/scdaemon.c:978 #, c-format msgid "error binding socket to `%s': %s\n" msgstr "Der Socket kann nicht an `%s' gebunden werden: %s\n" -#: agent/gpg-agent.c:1217 scd/scdaemon.c:983 +#: agent/gpg-agent.c:1218 scd/scdaemon.c:986 #, c-format msgid "listen() failed: %s\n" msgstr "Der listen() Aufruf ist fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1223 scd/scdaemon.c:989 +#: agent/gpg-agent.c:1224 scd/scdaemon.c:992 #, c-format msgid "listening on socket `%s'\n" msgstr "Es wird auf Socket `%s' gehört\n" -#: agent/gpg-agent.c:1251 agent/gpg-agent.c:1293 +#: agent/gpg-agent.c:1252 agent/gpg-agent.c:1294 #, c-format msgid "directory `%s' created\n" msgstr "Verzeichniss `%s' wurde erstellt\n" -#: agent/gpg-agent.c:1299 +#: agent/gpg-agent.c:1300 #, c-format msgid "stat() failed for `%s': %s\n" msgstr "stat() Aufruf für `%s' fehlgeschlagen: %s\n" -#: agent/gpg-agent.c:1303 +#: agent/gpg-agent.c:1304 #, c-format msgid "can't use `%s' as home directory\n" msgstr "Die Datei `%s' kann nicht als Home-Verzeichniss benutzt werden\n" -#: agent/gpg-agent.c:1401 +#: agent/gpg-agent.c:1402 #, c-format msgid "handler 0x%lx for fd %d started\n" msgstr "Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1411 +#: agent/gpg-agent.c:1412 #, c-format msgid "handler 0x%lx for fd %d terminated\n" msgstr "Handhabungsroutine 0x%lx für den fd %d beendet\n" -#: agent/gpg-agent.c:1425 +#: agent/gpg-agent.c:1426 #, c-format msgid "ssh handler 0x%lx for fd %d started\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1432 +#: agent/gpg-agent.c:1433 #, c-format msgid "ssh handler 0x%lx for fd %d terminated\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d beendet\n" -#: agent/gpg-agent.c:1526 scd/scdaemon.c:1105 +#: agent/gpg-agent.c:1527 scd/scdaemon.c:1108 #, c-format msgid "pth_select failed: %s - waiting 1s\n" msgstr "pth_select() Aufruf fehlgeschlagen: %s - warte 1s\n" -#: agent/gpg-agent.c:1610 scd/scdaemon.c:1162 +#: agent/gpg-agent.c:1611 scd/scdaemon.c:1165 #, c-format msgid "%s %s stopped\n" msgstr "%s %s angehalten\n" -#: agent/gpg-agent.c:1631 +#: agent/gpg-agent.c:1632 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1641 common/simple-pwquery.c:323 sm/call-agent.c:143 +#: agent/gpg-agent.c:1642 common/simple-pwquery.c:324 sm/call-agent.c:144 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1653 common/simple-pwquery.c:335 sm/call-agent.c:155 +#: agent/gpg-agent.c:1654 common/simple-pwquery.c:336 sm/call-agent.c:156 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht unterstützt\n" -#: agent/protect-tool.c:145 +#: agent/protect-tool.c:146 msgid "Usage: gpg-protect-tool [options] (-h for help)\n" msgstr "Gebrauch: gpg-protect-tool [Optionen] (-h für Hilfe)\n" -#: agent/protect-tool.c:147 +#: agent/protect-tool.c:148 msgid "" "Syntax: gpg-protect-tool [options] [args]]\n" "Secret key maintenance tool\n" @@ -270,16 +270,16 @@ msgstr "" "Syntax: gpg-protect-tool [Optionen] [Argumente]\n" "Werkzeug zum Bearbeiten von geheimen Schlüsseln\n" -#: agent/protect-tool.c:1205 +#: agent/protect-tool.c:1206 msgid "Please enter the passphrase to unprotect the PKCS#12 object." msgstr "Bitte geben Sie die Passphrase zum Entsperren des PKCS#12 Objekts ein" -#: agent/protect-tool.c:1208 +#: agent/protect-tool.c:1209 msgid "Please enter the passphrase to protect the new PKCS#12 object." msgstr "" "Bitte geben Sie die Passphrase zum Schützen des neuen PKCS#12 Objekts ein" -#: agent/protect-tool.c:1211 +#: agent/protect-tool.c:1212 msgid "" "Please enter the passphrase to protect the imported object within the GnuPG " "system." @@ -287,11 +287,11 @@ msgstr "" "Bitte geben Sie die Passphrase ein, um das importierte Objekt im GnuPG " "System zu schützen." -#: agent/protect-tool.c:1214 agent/genkey.c:110 agent/genkey.c:218 +#: agent/protect-tool.c:1215 agent/genkey.c:111 agent/genkey.c:219 msgid "Please re-enter this passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) noch einmal ein:" -#: agent/protect-tool.c:1216 +#: agent/protect-tool.c:1217 msgid "" "Please enter the passphrase or the PIN\n" "needed to complete this operation." @@ -299,56 +299,56 @@ msgstr "" "Die Eingabe des Mantras (Passphrase) bzw. der PIN\n" "wird benötigt um diese Aktion auszuführen." -#: agent/protect-tool.c:1220 agent/genkey.c:131 agent/genkey.c:238 +#: agent/protect-tool.c:1221 agent/genkey.c:132 agent/genkey.c:239 msgid "does not match - try again" msgstr "Keine Übereinstimmung - bitte nochmal versuchen" -#: agent/protect-tool.c:1221 +#: agent/protect-tool.c:1222 msgid "Passphrase:" msgstr "Passphrase:" -#: agent/protect-tool.c:1234 +#: agent/protect-tool.c:1235 #, c-format msgid "error while asking for the passphrase: %s\n" msgstr "Fehler bei der Abfrage der Passphrase: %s\n" -#: agent/protect-tool.c:1237 +#: agent/protect-tool.c:1238 msgid "cancelled\n" msgstr "Vom Benutzer abgebrochen\n" -#: agent/divert-scd.c:216 +#: agent/divert-scd.c:217 msgid "Admin PIN" msgstr "Admin PIN" -#: agent/divert-scd.c:274 +#: agent/divert-scd.c:275 msgid "Repeat this PIN" msgstr "PIN bitte wiederholen" -#: agent/divert-scd.c:277 +#: agent/divert-scd.c:278 msgid "PIN not correctly repeated; try again" msgstr "PIN wurde nicht korrekt eingegeben; nochmal versuchen" -#: agent/divert-scd.c:289 +#: agent/divert-scd.c:290 #, c-format msgid "Please enter the PIN%s%s%s to unlock the card" msgstr "Bitte geben Sie die PIN%s%s%s ein um die Karte zu entsperren" -#: agent/genkey.c:108 +#: agent/genkey.c:109 #, c-format msgid "Please enter the passphrase to%0Ato protect your new key" msgstr "" "Bitte geben Sie das Mantra (Passphrase) ein%0Aum Ihren Schlüssel zu schützen" -#: agent/genkey.c:217 +#: agent/genkey.c:218 msgid "Please enter the new passphrase" msgstr "Bitte geben Sie das Mantra (Passphrase) ein:" -#: agent/query.c:192 +#: agent/query.c:193 #, c-format msgid "failed to acquire the pinentry lock: %s\n" msgstr "Die Sperre für das Pinentry kann nicht gesetzt werden: %s\n" -#: agent/query.c:355 +#: agent/query.c:356 msgid "" "Please enter your PIN, so that the secret key can be unlocked for this " "session" @@ -356,7 +356,7 @@ msgstr "" "Bitte geben Sie Ihre PIN ein, so daß der geheime Schlüssel benutzt werden " "kann" -#: agent/query.c:358 +#: agent/query.c:359 msgid "" "Please enter your passphrase, so that the secret key can be unlocked for " "this session" @@ -364,31 +364,31 @@ msgstr "" "Bitte geben Sie Ihr Mantra (Passphrase) ein, so daß der geheime Schlüssel " "benutzt werden kann" -#: agent/query.c:416 agent/query.c:428 +#: agent/query.c:417 agent/query.c:429 msgid "PIN too long" msgstr "Die PIN ist zu lang" -#: agent/query.c:417 +#: agent/query.c:418 msgid "Passphrase too long" msgstr "Das Matra (Passphrase) ist zu lang" -#: agent/query.c:425 +#: agent/query.c:426 msgid "Invalid characters in PIN" msgstr "Ungültige Zeichen in der PIN" -#: agent/query.c:430 +#: agent/query.c:431 msgid "PIN too short" msgstr "Die PIN ist zu kurz" -#: agent/query.c:442 +#: agent/query.c:443 msgid "Bad PIN" msgstr "Falsche PIN" -#: agent/query.c:443 +#: agent/query.c:444 msgid "Bad Passphrase" msgstr "Falsches Mantra (Passphrase)" -#: agent/query.c:483 +#: agent/query.c:484 msgid "Passphrase" msgstr "Mantra" @@ -401,7 +401,7 @@ msgstr "Mantra" #. second "%s" gets replaced by a hexdecimal #. fingerprint string whereas the first one receives #. the name as store in the certificate. -#: agent/trustlist.c:305 +#: agent/trustlist.c:306 #, c-format msgid "" "Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " @@ -413,7 +413,7 @@ msgstr "" #. TRANSLATORS: "Correct" is the label of a button and intended to #. be hit if the fingerprint matches the one of the CA. The other #. button is "the default "Cancel" of the Pinentry. -#: agent/trustlist.c:317 +#: agent/trustlist.c:318 msgid "Correct" msgstr "Korrekt" @@ -425,7 +425,7 @@ msgstr "Korrekt" #. plain % sign, you need to encode it as "%%25". The #. "%s" gets replaced by the name as store in the #. certificate. -#: agent/trustlist.c:334 +#: agent/trustlist.c:335 #, c-format msgid "" "Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " @@ -434,62 +434,62 @@ msgstr "" "Wenn Sie vollständiges Vertrauen haben, daß%%0A \"%s\"%%" "0ABenutzerzertifikate verläßlich zertifiziert, so antworten Sie mit \"Ja\"" -#: agent/trustlist.c:342 +#: agent/trustlist.c:343 msgid "Yes" msgstr "Ja" -#: agent/trustlist.c:342 +#: agent/trustlist.c:343 msgid "No" msgstr "Nein" -#: common/sysutils.c:87 +#: common/sysutils.c:88 #, c-format msgid "can't disable core dumps: %s\n" msgstr "" "Das Erstellen eines Speicherabzugs (core-dump) kann nicht verhindert werden: " "%s\n" -#: common/sysutils.c:182 +#: common/sysutils.c:183 #, c-format msgid "Warning: unsafe ownership on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Besitzrechte für %s \"%s\"\n" -#: common/sysutils.c:214 +#: common/sysutils.c:215 #, c-format msgid "Warning: unsafe permissions on %s \"%s\"\n" msgstr "WARNUNG: Unsichere Zugriffsrechte für %s \"%s\"\n" -#: common/simple-pwquery.c:309 +#: common/simple-pwquery.c:310 msgid "gpg-agent is not available in this session\n" msgstr "Der gpg-agent ist nicht verfügbar\n" -#: common/simple-pwquery.c:367 +#: common/simple-pwquery.c:368 #, c-format msgid "can't connect to `%s': %s\n" msgstr "Verbindung zu `%s' kann nicht aufgebaut werden: %s\n" -#: common/simple-pwquery.c:378 +#: common/simple-pwquery.c:379 msgid "communication problem with gpg-agent\n" msgstr "Kommunikationsproblem mit gpg-agent\n" -#: common/simple-pwquery.c:388 +#: common/simple-pwquery.c:389 msgid "problem setting the gpg-agent options\n" msgstr "Beim setzen der gpg-agent Optionen ist ein problem aufgetreten\n" -#: common/simple-pwquery.c:526 common/simple-pwquery.c:614 +#: common/simple-pwquery.c:527 common/simple-pwquery.c:615 msgid "canceled by user\n" msgstr "Vom Benutzer abgebrochen\n" -#: common/simple-pwquery.c:533 common/simple-pwquery.c:620 +#: common/simple-pwquery.c:534 common/simple-pwquery.c:621 msgid "problem with the agent\n" msgstr "Problem mit dem Agenten\n" -#: jnlib/logging.c:610 +#: jnlib/logging.c:611 #, c-format msgid "you found a bug ... (%s:%d)\n" msgstr "Sie haben einen Bug (Softwarefehler) gefunden ... (%s:%d)\n" -#: kbx/kbxutil.c:68 sm/gpgsm.c:239 tools/gpgconf.c:53 +#: kbx/kbxutil.c:69 sm/gpgsm.c:241 tools/gpgconf.c:54 msgid "" "@Commands:\n" " " @@ -497,7 +497,7 @@ msgstr "" "@Kommandos:\n" " " -#: kbx/kbxutil.c:76 sm/gpgsm.c:274 tools/gpgconf.c:59 +#: kbx/kbxutil.c:77 sm/gpgsm.c:276 tools/gpgconf.c:60 msgid "" "@\n" "Options:\n" @@ -507,31 +507,31 @@ msgstr "" "Optionen:\n" " " -#: kbx/kbxutil.c:83 sm/gpgsm.c:340 tools/gpgconf.c:64 +#: kbx/kbxutil.c:84 sm/gpgsm.c:342 tools/gpgconf.c:65 msgid "do not make any changes" msgstr "Keine Änderungen durchführen" -#: kbx/kbxutil.c:85 +#: kbx/kbxutil.c:86 msgid "set debugging flags" msgstr "Debug Flags setzen" -#: kbx/kbxutil.c:86 +#: kbx/kbxutil.c:87 msgid "enable full debugging" msgstr "Alle Debug Flags setzen" -#: kbx/kbxutil.c:107 +#: kbx/kbxutil.c:108 msgid "Please report bugs to " msgstr "Bitte richten sie Berichte über Bugs (Softwarefehler) an " -#: kbx/kbxutil.c:107 +#: kbx/kbxutil.c:108 msgid ".\n" msgstr ".\n" -#: kbx/kbxutil.c:111 +#: kbx/kbxutil.c:112 msgid "Usage: kbxutil [options] [files] (-h for help)" msgstr "Gebrauch: kbxutil [Optionen] [Dateien] (-h für Hilfe)" -#: kbx/kbxutil.c:114 +#: kbx/kbxutil.c:115 msgid "" "Syntax: kbxutil [options] [files]\n" "list, export, import Keybox data\n" @@ -539,43 +539,43 @@ msgstr "" "Syntax: kbxutil [Optionen] [Dateien]\n" "Anlistem exportieren und Importieren von KeyBox Dateien\n" -#: scd/scdaemon.c:104 +#: scd/scdaemon.c:105 msgid "run in multi server mode (foreground)" msgstr "Im Multiserver Modus ausführen" -#: scd/scdaemon.c:110 sm/gpgsm.c:352 +#: scd/scdaemon.c:111 sm/gpgsm.c:354 msgid "read options from file" msgstr "Konfigurationsoptionen aus Datei lesen" -#: scd/scdaemon.c:120 +#: scd/scdaemon.c:121 msgid "|N|connect to reader at port N" msgstr "|N|Verbinde mit dem Leser auf Port N" -#: scd/scdaemon.c:121 +#: scd/scdaemon.c:122 msgid "|NAME|use NAME as ct-API driver" msgstr "|NAME|Benutze NAME als CT-API Treiber" -#: scd/scdaemon.c:122 +#: scd/scdaemon.c:123 msgid "|NAME|use NAME as PC/SC driver" msgstr "|NAME|Benutze NAME als PC/SC Treiber" -#: scd/scdaemon.c:125 +#: scd/scdaemon.c:126 msgid "do not use the internal CCID driver" msgstr "Den internen CCID Treiber nicht benutzen" -#: scd/scdaemon.c:130 +#: scd/scdaemon.c:131 msgid "do not use a reader's keypad" msgstr "Die Tastatur des Kartenleser nicht benutzen" -#: scd/scdaemon.c:131 +#: scd/scdaemon.c:132 msgid "allow the use of admin card commands" msgstr "Erlaube die Benutzung von \"Admin\" Kommandos" -#: scd/scdaemon.c:188 +#: scd/scdaemon.c:191 msgid "Usage: scdaemon [options] (-h for help)" msgstr "Gebrauch: scdaemon [Optionen] (-h für Hilfe)" -#: scd/scdaemon.c:190 +#: scd/scdaemon.c:193 msgid "" "Syntax: scdaemon [options] [command [args]]\n" "Smartcard daemon for GnuPG\n" @@ -583,78 +583,78 @@ msgstr "" "Synatx: scdaemon [Optionen] [Kommando [Argumente]]\n" "Smartcard Daemon für GnuPG\n" -#: scd/scdaemon.c:662 +#: scd/scdaemon.c:665 msgid "please use the option `--daemon' to run the program in the background\n" msgstr "" "Bitte die Option `--daemon' nutzen um das Programm im Hintergund " "auszuführen\n" -#: scd/scdaemon.c:1003 +#: scd/scdaemon.c:1006 #, c-format msgid "handler for fd %d started\n" msgstr "Handhabungsroutine für fd %d gestartet\n" -#: scd/scdaemon.c:1008 +#: scd/scdaemon.c:1011 #, c-format msgid "handler for fd %d terminated\n" msgstr "Handhabungsroutine für den fd %d beendet\n" -#: scd/app-openpgp.c:595 +#: scd/app-openpgp.c:596 #, c-format msgid "failed to store the fingerprint: %s\n" msgstr "Der Fingerprint kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:608 +#: scd/app-openpgp.c:609 #, c-format msgid "failed to store the creation date: %s\n" msgstr "Das Erzeugungsdatum kann nicht gespeichert werden: %s\n" -#: scd/app-openpgp.c:1003 +#: scd/app-openpgp.c:1004 #, c-format msgid "reading public key failed: %s\n" msgstr "Fehler beim Lesen des öffentlichen Schlüssels: %s\n" -#: scd/app-openpgp.c:1011 scd/app-openpgp.c:1947 +#: scd/app-openpgp.c:1012 scd/app-openpgp.c:1948 msgid "response does not contain the public key data\n" msgstr "Die Antwort enthält keine Public Key Daten\n" -#: scd/app-openpgp.c:1019 scd/app-openpgp.c:1955 +#: scd/app-openpgp.c:1020 scd/app-openpgp.c:1956 msgid "response does not contain the RSA modulus\n" msgstr "Die Antwort enthält keinen RSA Modulus\n" -#: scd/app-openpgp.c:1028 scd/app-openpgp.c:1965 +#: scd/app-openpgp.c:1029 scd/app-openpgp.c:1966 msgid "response does not contain the RSA public exponent\n" msgstr "Die Antwort enthält keinen öffenlichen RSA Exponent\n" -#: scd/app-openpgp.c:1296 scd/app-openpgp.c:1384 scd/app-openpgp.c:2187 +#: scd/app-openpgp.c:1297 scd/app-openpgp.c:1385 scd/app-openpgp.c:2192 #, c-format msgid "PIN callback returned error: %s\n" msgstr "Fehler vom PIN \"callback\": %s\n" -#: scd/app-openpgp.c:1302 scd/app-openpgp.c:1390 scd/app-openpgp.c:2193 +#: scd/app-openpgp.c:1303 scd/app-openpgp.c:1391 scd/app-openpgp.c:2198 #, c-format msgid "PIN for CHV%d is too short; minimum length is %d\n" msgstr "Die PIN für den CHV%d ist zu kurz; Mindestlänge ist %d\n" -#: scd/app-openpgp.c:1311 scd/app-openpgp.c:1325 scd/app-openpgp.c:1400 -#: scd/app-openpgp.c:2202 scd/app-openpgp.c:2216 +#: scd/app-openpgp.c:1312 scd/app-openpgp.c:1326 scd/app-openpgp.c:1401 +#: scd/app-openpgp.c:2207 scd/app-openpgp.c:2221 #, c-format msgid "verify CHV%d failed: %s\n" msgstr "Prüfen von CHV%d fehlgeschlagen: %s\n" -#: scd/app-openpgp.c:1348 +#: scd/app-openpgp.c:1349 msgid "access to admin commands is not configured\n" msgstr "Zugriff auf Admin Kommandos ist nicht konfiguriert\n" -#: scd/app-openpgp.c:1363 scd/app-openpgp.c:2422 +#: scd/app-openpgp.c:1364 scd/app-openpgp.c:2427 msgid "error retrieving CHV status from card\n" msgstr "Fehler beim Holen des CHV Status von der Karte\n" -#: scd/app-openpgp.c:1369 scd/app-openpgp.c:2431 +#: scd/app-openpgp.c:1370 scd/app-openpgp.c:2436 msgid "card is permanently locked!\n" msgstr "Die Karte ist dauerhaft gesperrt!\n" -#: scd/app-openpgp.c:1374 +#: scd/app-openpgp.c:1375 #, c-format msgid "%d Admin PIN attempts remaining before card is permanently locked\n" msgstr "" @@ -663,170 +663,176 @@ msgstr "" #. TRANSLATORS: Do not translate the "|A|" prefix but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1381 +#: scd/app-openpgp.c:1382 msgid "|A|Admin PIN" msgstr "|A|Admin PIN" #. TRANSLATORS: Do not translate the "|*|" prefixes but #. keep it at the start of the string. We need this elsewhere #. to get some infos on the string. -#: scd/app-openpgp.c:1530 +#: scd/app-openpgp.c:1531 msgid "|AN|New Admin PIN" msgstr "|AN|Neue Admin PIN" -#: scd/app-openpgp.c:1530 +#: scd/app-openpgp.c:1531 msgid "|N|New PIN" msgstr "|N|Neue PIN" -#: scd/app-openpgp.c:1534 +#: scd/app-openpgp.c:1535 #, c-format msgid "error getting new PIN: %s\n" msgstr "Fehler beim Holen der neuen PIN: %s\n" -#: scd/app-openpgp.c:1584 scd/app-openpgp.c:2033 +#: scd/app-openpgp.c:1585 scd/app-openpgp.c:2034 msgid "error reading application data\n" msgstr "Fehler beim Lesen der Anwendungsdaten\n" -#: scd/app-openpgp.c:1590 scd/app-openpgp.c:2040 +#: scd/app-openpgp.c:1591 scd/app-openpgp.c:2041 msgid "error reading fingerprint DO\n" msgstr "Fehler beim Lesen des Fingerabdruck Datenobjekts\n" -#: scd/app-openpgp.c:1600 +#: scd/app-openpgp.c:1601 msgid "key already exists\n" msgstr "Schlüssel existiert bereits\n" -#: scd/app-openpgp.c:1604 +#: scd/app-openpgp.c:1605 msgid "existing key will be replaced\n" msgstr "Existierender Schlüssel wird ersetzt\n" -#: scd/app-openpgp.c:1606 +#: scd/app-openpgp.c:1607 msgid "generating new key\n" msgstr "Neuer Schlüssel wird erzeugt\n" -#: scd/app-openpgp.c:1773 +#: scd/app-openpgp.c:1774 msgid "creation timestamp missing\n" msgstr "Erzeugungsdatum fehlt\n" -#: scd/app-openpgp.c:1780 +#: scd/app-openpgp.c:1781 #, c-format msgid "RSA modulus missing or not of size %d bits\n" msgstr "Der RSA Modulus fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1787 +#: scd/app-openpgp.c:1788 #, c-format msgid "RSA public exponent missing or larger than %d bits\n" msgstr "Der öffentliche RSA Exponent fehlt oder ist länger als %d Bits\n" -#: scd/app-openpgp.c:1795 scd/app-openpgp.c:1802 +#: scd/app-openpgp.c:1796 scd/app-openpgp.c:1803 #, c-format msgid "RSA prime %s missing or not of size %d bits\n" msgstr "Die RSA Primzahl %s fehlt oder ist nicht %d Bits lang\n" -#: scd/app-openpgp.c:1865 +#: scd/app-openpgp.c:1866 #, c-format msgid "failed to store the key: %s\n" msgstr "Fehler beim Speichern des Schlüssels: %s\n" -#: scd/app-openpgp.c:1924 +#: scd/app-openpgp.c:1925 msgid "please wait while key is being generated ...\n" msgstr "Bitte warten bis der Schlüssel erzeugt wurde ...\n" -#: scd/app-openpgp.c:1938 +#: scd/app-openpgp.c:1939 msgid "generating key failed\n" msgstr "Fehler beim Erzeugen des Schlüssels\n" -#: scd/app-openpgp.c:1941 +#: scd/app-openpgp.c:1942 #, c-format msgid "key generation completed (%d seconds)\n" msgstr "Schlüsselerzeugung vollendet (%d Sekunden)\n" -#: scd/app-openpgp.c:1998 +#: scd/app-openpgp.c:1999 msgid "invalid structure of OpenPGP card (DO 0x93)\n" msgstr "Ungültige Struktur der OpenPGP Karte (DO 0x93)\n" -#: scd/app-openpgp.c:2167 +#: scd/app-openpgp.c:2125 +#, c-format +msgid "card does not support digest algorithm %s\n" +msgstr "" + +#: scd/app-openpgp.c:2172 #, c-format msgid "signatures created so far: %lu\n" msgstr "Anzahl bereits erzeugter Signaturen: %lu\n" -#: scd/app-openpgp.c:2175 +#: scd/app-openpgp.c:2180 #, c-format msgid "||Please enter the PIN%%0A[sigs done: %lu]" msgstr "||Bitte geben Sie die PIN ein%%0A[Sigs bisher: %lu]" -#: scd/app-openpgp.c:2436 +#: scd/app-openpgp.c:2441 msgid "" "verification of Admin PIN is currently prohibited through this command\n" msgstr "" "Die Überprüfung der Admin PIN is momentan durch ein Kommando verboten " "worden\n" -#: scd/app-openpgp.c:2509 scd/app-openpgp.c:2519 +#: scd/app-openpgp.c:2514 scd/app-openpgp.c:2524 #, c-format msgid "can't access %s - invalid OpenPGP card?\n" msgstr "Zugriff auf %s nicht möglich - ungültige OpenPGP Karte?\n" -#: scd/app-nks.c:344 +#: scd/app-nks.c:345 msgid "the NullPIN has not yet been changed\n" msgstr "Die Nullpin wurde noch nicht geändert\n" -#: sm/base64.c:317 +#: sm/base64.c:318 #, c-format msgid "invalid radix64 character %02x skipped\n" msgstr "Ungültiges Basis-64 Zeichen %02X wurde übergangen\n" -#: sm/call-agent.c:101 +#: sm/call-agent.c:102 msgid "no running gpg-agent - starting one\n" msgstr "Kein aktiver gpg-agent - es wird einer gestarted\n" -#: sm/call-agent.c:166 +#: sm/call-agent.c:167 msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht möglich - Ersatzmethode wird versucht\n" -#: sm/call-dirmngr.c:174 -msgid "no running dirmngr - starting one\n" +#: sm/call-dirmngr.c:182 +#, fuzzy, c-format +msgid "no running dirmngr - starting `%s'\n" msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" -#: sm/call-dirmngr.c:214 +#: sm/call-dirmngr.c:216 msgid "malformed DIRMNGR_INFO environment variable\n" msgstr "Die Variable DIRMNGR_INFO ist fehlerhaft\n" -#: sm/call-dirmngr.c:226 +#: sm/call-dirmngr.c:228 #, c-format msgid "dirmngr protocol version %d is not supported\n" msgstr "Die Dirmngr Protokollversion %d wird nicht unterstützt\n" -#: sm/call-dirmngr.c:240 +#: sm/call-dirmngr.c:242 msgid "can't connect to the dirmngr - trying fall back\n" msgstr "" "Verbindung zum Dirmngr kann nicht aufgebaut werden - Ersatzmethode wird " "versucht\n" -#: sm/certdump.c:60 sm/certdump.c:146 +#: sm/certdump.c:61 sm/certdump.c:147 msgid "none" msgstr "keine" -#: sm/certdump.c:155 +#: sm/certdump.c:156 msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:498 sm/certdump.c:561 +#: sm/certdump.c:499 sm/certdump.c:562 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungültige Kodierung]" -#: sm/certdump.c:506 +#: sm/certdump.c:507 msgid "[Error - out of core]" msgstr "[Fehler - Nich genügend Speicher]" -#: sm/certdump.c:541 +#: sm/certdump.c:542 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:566 +#: sm/certdump.c:567 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungültiger DN]" -#: sm/certdump.c:727 +#: sm/certdump.c:728 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -839,451 +845,451 @@ msgstr "" "S/N %s, ID %08lX, erzeugt %s\n" "zu entsperren" -#: sm/certlist.c:122 +#: sm/certlist.c:123 msgid "no key usage specified - assuming all usages\n" msgstr "" "Schlüsselverwendungszweck nicht vorhanden - für alle Zwecke akzeptiert\n" -#: sm/certlist.c:132 sm/keylist.c:245 +#: sm/certlist.c:133 sm/keylist.c:246 #, c-format msgid "error getting key usage information: %s\n" msgstr "Fehler beim holen der Schlüsselbenutzungsinformationen: %s\n" -#: sm/certlist.c:142 +#: sm/certlist.c:143 msgid "certificate should have not been used for certification\n" msgstr "Das Zertifikat hätte nicht zum Zertifizieren benutzt werden sollen\n" -#: sm/certlist.c:154 +#: sm/certlist.c:155 msgid "certificate should have not been used for OCSP response signing\n" msgstr "" "Das Zertifikat hätte nicht zum Signieren von OCSP Antworten benutzt werden " "sollen\n" -#: sm/certlist.c:165 +#: sm/certlist.c:166 msgid "certificate should have not been used for encryption\n" msgstr "Das Zertifikat hätte nicht zum Verschlüsseln benutzt werden sollen\n" -#: sm/certlist.c:166 +#: sm/certlist.c:167 msgid "certificate should have not been used for signing\n" msgstr "Das Zertifikat hätte nicht zum Signieren benutzt werden sollen\n" -#: sm/certlist.c:167 +#: sm/certlist.c:168 msgid "certificate is not usable for encryption\n" msgstr "Das Zertifikat kann nicht zum Verschlüsseln benutzt werden\n" -#: sm/certlist.c:168 +#: sm/certlist.c:169 msgid "certificate is not usable for signing\n" msgstr "Das Zertifikat kann nicht zum Signieren benutzt werden\n" -#: sm/certchain.c:109 +#: sm/certchain.c:115 #, c-format msgid "critical certificate extension %s is not supported" msgstr "Die kritische Zertifikaterweiterung %s wird nicht unterstützt" -#: sm/certchain.c:131 +#: sm/certchain.c:142 msgid "issuer certificate is not marked as a CA" msgstr "Das Herausgeberzertifikat ist nicht für eine CA gekennzeichnet" -#: sm/certchain.c:169 +#: sm/certchain.c:180 msgid "critical marked policy without configured policies" msgstr "kritische Richtlinie ohne konfigurierte Richtlinien" -#: sm/certchain.c:179 +#: sm/certchain.c:190 #, c-format msgid "failed to open `%s': %s\n" msgstr "Datei `%s' kann nicht geöffnet werden: %s\n" -#: sm/certchain.c:186 sm/certchain.c:215 +#: sm/certchain.c:197 sm/certchain.c:226 msgid "note: non-critical certificate policy not allowed" msgstr "Notiz: Die unkritische Zertifikatrichtlinie ist nicht erlaubt" -#: sm/certchain.c:190 sm/certchain.c:219 +#: sm/certchain.c:201 sm/certchain.c:230 msgid "certificate policy not allowed" msgstr "Die Zertifikatrichtlinie ist nicht erlaubt" -#: sm/certchain.c:330 +#: sm/certchain.c:341 msgid "looking up issuer at external location\n" msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" -#: sm/certchain.c:350 +#: sm/certchain.c:361 #, c-format msgid "number of issuers matching: %d\n" msgstr "Anzahl der übereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:503 sm/certchain.c:665 sm/certchain.c:1103 sm/decrypt.c:260 -#: sm/encrypt.c:341 sm/sign.c:324 sm/verify.c:106 +#: sm/certchain.c:514 sm/certchain.c:676 sm/certchain.c:1114 sm/decrypt.c:261 +#: sm/encrypt.c:342 sm/sign.c:325 sm/verify.c:107 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" -#: sm/certchain.c:592 +#: sm/certchain.c:603 msgid "certificate has been revoked" msgstr "Das Zertifikat wurde widerrufen" -#: sm/certchain.c:601 +#: sm/certchain.c:612 msgid "no CRL found for certificate" msgstr "Keine CRL für das Zertifikat gefunden" -#: sm/certchain.c:605 +#: sm/certchain.c:616 msgid "the available CRL is too old" msgstr "Die vorhandene CRL ist zu alt" -#: sm/certchain.c:607 +#: sm/certchain.c:618 msgid "please make sure that the \"dirmngr\" is properly installed\n" msgstr "" "Bitte vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" -#: sm/certchain.c:612 +#: sm/certchain.c:623 #, c-format msgid "checking the CRL failed: %s" msgstr "Die CRL konnte nicht geprüft werden: %s" -#: sm/certchain.c:685 +#: sm/certchain.c:696 msgid "no issuer found in certificate" msgstr "Im Zertifikat ist kein Herausgeber enthalten" -#: sm/certchain.c:698 +#: sm/certchain.c:709 #, c-format msgid "certificate with invalid validity: %s" msgstr "Zertifikat mit unzulässiger Gültigkeit: %s" -#: sm/certchain.c:714 +#: sm/certchain.c:725 msgid "certificate not yet valid" msgstr "Das Zertifikat ist noch nicht gültig" -#: sm/certchain.c:727 +#: sm/certchain.c:738 msgid "certificate has expired" msgstr "Das Zertifikat ist abgelaufen" -#: sm/certchain.c:764 +#: sm/certchain.c:775 msgid "self-signed certificate has a BAD signature" msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:829 +#: sm/certchain.c:840 msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswürdig markiert" -#: sm/certchain.c:840 +#: sm/certchain.c:851 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:845 +#: sm/certchain.c:856 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswürdig markiert\n" -#: sm/certchain.c:860 +#: sm/certchain.c:871 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prüfen der vertrauenswürdigen Zertifikate: %s\n" -#: sm/certchain.c:886 sm/import.c:157 +#: sm/certchain.c:897 sm/import.c:158 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:898 +#: sm/certchain.c:909 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:931 +#: sm/certchain.c:942 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:961 +#: sm/certchain.c:972 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes möglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:984 +#: sm/certchain.c:995 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist länger als von der CA erlaubt (%d)" -#: sm/decrypt.c:127 +#: sm/decrypt.c:128 msgid "" "WARNING: message was encrypted with a weak key in the symmetric cipher.\n" msgstr "" "WARNUNG: Die Nachricht wurde mich einem schwachen Schlüssel (Weak Key) " "erzeugt\n" -#: sm/decrypt.c:325 +#: sm/decrypt.c:326 msgid "(this is the RC2 algorithm)\n" msgstr "(Dies ist der RC-2 Algorithmus)\n" -#: sm/decrypt.c:327 +#: sm/decrypt.c:328 msgid "(this does not seem to be an encrypted message)\n" msgstr "(dies is wahrscheinlich keine verschlüsselte Nachricht)\n" -#: sm/delete.c:51 sm/delete.c:102 +#: sm/delete.c:52 sm/delete.c:103 #, c-format msgid "certificate `%s' not found: %s\n" msgstr "Zertifikat `%s' nicht gefunden: %s\n" -#: sm/delete.c:112 sm/keydb.c:1402 sm/keydb.c:1495 +#: sm/delete.c:113 sm/keydb.c:1380 sm/keydb.c:1473 #, c-format msgid "error locking keybox: %s\n" msgstr "Fehler beim Sperren der Keybox: %s\n" -#: sm/delete.c:133 +#: sm/delete.c:134 #, c-format msgid "duplicated certificate `%s' deleted\n" msgstr "Doppeltes Zertifikat `%s' gelöscht\n" -#: sm/delete.c:135 +#: sm/delete.c:136 #, c-format msgid "certificate `%s' deleted\n" msgstr "Zertifikat `%s' gelöscht\n" -#: sm/delete.c:165 +#: sm/delete.c:166 #, c-format msgid "deleting certificate \"%s\" failed: %s\n" msgstr "Fehler beim Löschen des Zertifikats \"%s\": %s\n" -#: sm/encrypt.c:120 +#: sm/encrypt.c:121 msgid "weak key created - retrying\n" msgstr "Schwacher Schlüssel - es wird erneut versucht\n" -#: sm/encrypt.c:332 +#: sm/encrypt.c:333 msgid "no valid recipients given\n" msgstr "Keine gültigen Empfänger angegeben\n" -#: sm/gpgsm.c:241 +#: sm/gpgsm.c:243 msgid "|[FILE]|make a signature" msgstr "|[DATEI]|Erzeuge eine Signatur" -#: sm/gpgsm.c:242 +#: sm/gpgsm.c:244 msgid "|[FILE]|make a clear text signature" msgstr "|[DATEI]|Erzeuge eine Klartextsignatur" -#: sm/gpgsm.c:243 +#: sm/gpgsm.c:245 msgid "make a detached signature" msgstr "Erzeuge eine abgetrennte Signatur" -#: sm/gpgsm.c:244 +#: sm/gpgsm.c:246 msgid "encrypt data" msgstr "Verschlüssele die Daten" -#: sm/gpgsm.c:245 +#: sm/gpgsm.c:247 msgid "encryption only with symmetric cipher" msgstr "Verschlüsselung nur mit symmetrischem Algrithmus" -#: sm/gpgsm.c:246 +#: sm/gpgsm.c:248 msgid "decrypt data (default)" msgstr "Enschlüssele die Daten" -#: sm/gpgsm.c:247 +#: sm/gpgsm.c:249 msgid "verify a signature" msgstr "Überprüfen einer Signatur" -#: sm/gpgsm.c:249 +#: sm/gpgsm.c:251 msgid "list keys" msgstr "Schlüssel anzeigen" -#: sm/gpgsm.c:250 +#: sm/gpgsm.c:252 msgid "list external keys" msgstr "Externe Schlüssel anzeigen" -#: sm/gpgsm.c:251 +#: sm/gpgsm.c:253 msgid "list secret keys" msgstr "Geheime Schlüssel anzeigen" -#: sm/gpgsm.c:252 +#: sm/gpgsm.c:254 msgid "list certificate chain" msgstr "Schlüssel mit Zertifikatekette anzeigen" -#: sm/gpgsm.c:254 +#: sm/gpgsm.c:256 msgid "list keys and fingerprints" msgstr "Schlüssel und Fingerprint anzeigen" -#: sm/gpgsm.c:255 +#: sm/gpgsm.c:257 msgid "generate a new key pair" msgstr "Neues Schlüsselpaar erzeugen" -#: sm/gpgsm.c:256 +#: sm/gpgsm.c:258 msgid "remove key from the public keyring" msgstr "Schlüssel aus dem öffentlichen Schlüsselbund löschen" -#: sm/gpgsm.c:257 +#: sm/gpgsm.c:259 msgid "export keys to a key server" msgstr "Schlüssen an eine Schlüsselserver exportieren" -#: sm/gpgsm.c:258 +#: sm/gpgsm.c:260 msgid "import keys from a key server" msgstr "Schlüssel von einem Schlüsselserver importieren" -#: sm/gpgsm.c:259 +#: sm/gpgsm.c:261 msgid "import certificates" msgstr "Zertifikate importieren" -#: sm/gpgsm.c:260 +#: sm/gpgsm.c:262 msgid "export certificates" msgstr "Zertifikate exportieren" -#: sm/gpgsm.c:261 +#: sm/gpgsm.c:263 msgid "register a smartcard" msgstr "Smartcard registrieren" -#: sm/gpgsm.c:262 +#: sm/gpgsm.c:264 msgid "run in server mode" msgstr "Im Server Modus ausführen" -#: sm/gpgsm.c:263 +#: sm/gpgsm.c:265 msgid "pass a command to the dirmngr" msgstr "Das Kommand an den Dirmngr durchreichen" -#: sm/gpgsm.c:265 +#: sm/gpgsm.c:267 msgid "invoke gpg-protect-tool" msgstr "Rufe das gpg-protect-tool auf" -#: sm/gpgsm.c:266 +#: sm/gpgsm.c:268 msgid "change a passphrase" msgstr "Das Mantra (Passphrase) ändern" -#: sm/gpgsm.c:276 +#: sm/gpgsm.c:278 msgid "create ascii armored output" msgstr "Ausgabe mit ASCII Hülle wird erzeugt" -#: sm/gpgsm.c:278 +#: sm/gpgsm.c:280 msgid "create base-64 encoded output" msgstr "Ausgabe im Basis-64 format erzeugen" -#: sm/gpgsm.c:280 +#: sm/gpgsm.c:282 msgid "assume input is in PEM format" msgstr "Eingabedaten sind im PEM Format" -#: sm/gpgsm.c:282 +#: sm/gpgsm.c:284 msgid "assume input is in base-64 format" msgstr "Eingabedaten sind im Basis-64 Format" -#: sm/gpgsm.c:284 +#: sm/gpgsm.c:286 msgid "assume input is in binary format" msgstr "Eingabedaten sind im Binärformat" -#: sm/gpgsm.c:286 +#: sm/gpgsm.c:288 msgid "|NAME|encrypt for NAME" msgstr "|NAME|Verschlüsseln für NAME" -#: sm/gpgsm.c:289 +#: sm/gpgsm.c:291 msgid "use system's dirmngr if available" msgstr "Benutze den System Dirmngr when verfügbar" -#: sm/gpgsm.c:290 +#: sm/gpgsm.c:292 msgid "never consult a CRL" msgstr "Niemals eine CRL konsultieren" -#: sm/gpgsm.c:297 +#: sm/gpgsm.c:299 msgid "check validity using OCSP" msgstr "Die Gültigkeit mittels OCSP prüfen" -#: sm/gpgsm.c:300 +#: sm/gpgsm.c:302 msgid "|N|number of certificates to include" msgstr "|N|Sende N Zertifikate mit" -#: sm/gpgsm.c:303 +#: sm/gpgsm.c:305 msgid "|FILE|take policy information from FILE" msgstr "|DATEI|Richtlinieninformationen DATEI entnehmen" -#: sm/gpgsm.c:306 +#: sm/gpgsm.c:308 msgid "do not check certificate policies" msgstr "Zertikikatrichtlinien nicht überprüfen" -#: sm/gpgsm.c:310 +#: sm/gpgsm.c:312 msgid "fetch missing issuer certificates" msgstr "Fehlende Zertifikate automatisch holen" -#: sm/gpgsm.c:314 +#: sm/gpgsm.c:316 msgid "|NAME|use NAME as default recipient" msgstr "|NAME|Benutze NAME als voreingestellten Empfänger" -#: sm/gpgsm.c:316 +#: sm/gpgsm.c:318 msgid "use the default key as default recipient" msgstr "Benuzte voreingestellten Schlüssel als Standardempfänger" -#: sm/gpgsm.c:322 +#: sm/gpgsm.c:324 msgid "use this user-id to sign or decrypt" msgstr "Benuzte diese Benutzer ID zum Signieren oder Entschlüsseln" -#: sm/gpgsm.c:325 +#: sm/gpgsm.c:327 msgid "|N|set compress level N (0 disables)" msgstr "|N|Benutze Komprimierungsstufe N" -#: sm/gpgsm.c:327 +#: sm/gpgsm.c:329 msgid "use canonical text mode" msgstr "Kanonischen Textmodus benutzen" -#: sm/gpgsm.c:330 tools/gpgconf.c:61 +#: sm/gpgsm.c:332 tools/gpgconf.c:62 msgid "use as output file" msgstr "als Ausgabedatei benutzen" -#: sm/gpgsm.c:333 +#: sm/gpgsm.c:335 msgid "don't use the terminal at all" msgstr "Das Terminal überhaupt nicht benutzen" -#: sm/gpgsm.c:337 +#: sm/gpgsm.c:339 msgid "force v3 signatures" msgstr "Version 3 Signaturen erzwingen" -#: sm/gpgsm.c:338 +#: sm/gpgsm.c:340 msgid "always use a MDC for encryption" msgstr "Immer das MDC Verfahren zum verschlüsseln mitbenutzen" -#: sm/gpgsm.c:343 +#: sm/gpgsm.c:345 msgid "batch mode: never ask" msgstr "Stapelverarbeitungs Modus: Nie nachfragen" -#: sm/gpgsm.c:344 +#: sm/gpgsm.c:346 msgid "assume yes on most questions" msgstr "\"Ja\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:345 +#: sm/gpgsm.c:347 msgid "assume no on most questions" msgstr "\"Nein\" auf die meisten Anfragen annehmen" -#: sm/gpgsm.c:347 +#: sm/gpgsm.c:349 msgid "add this keyring to the list of keyrings" msgstr "Diesen Keyring in die Liste der Keyrings aufnehmen" -#: sm/gpgsm.c:348 +#: sm/gpgsm.c:350 msgid "add this secret keyring to the list" msgstr "Diese geheimen Keyring in die Liste aufnehmen" -#: sm/gpgsm.c:349 +#: sm/gpgsm.c:351 msgid "|NAME|use NAME as default secret key" msgstr "|NAME|Benutze NAME als voreingestellten Schlüssel" -#: sm/gpgsm.c:350 +#: sm/gpgsm.c:352 msgid "|HOST|use this keyserver to lookup keys" msgstr "|HOST|Benutze HOST als Schlüsselserver" -#: sm/gpgsm.c:351 +#: sm/gpgsm.c:353 msgid "|NAME|set terminal charset to NAME" msgstr "|NAME|Den Zeichensatz für das Terminal auf NAME setzen" -#: sm/gpgsm.c:355 +#: sm/gpgsm.c:357 msgid "|LEVEL|set the debugging level to LEVEL" msgstr "|NAME|Die Debugstufe auf NAME setzen" -#: sm/gpgsm.c:363 +#: sm/gpgsm.c:365 msgid "|FD|write status info to this FD" msgstr "|FD|Statusinformationen auf Dateidescriptor FD schreiben" -#: sm/gpgsm.c:370 +#: sm/gpgsm.c:372 msgid "|FILE|load extension module FILE" msgstr "|DATEI|Das Erweiterungsmodul DATEI laden" -#: sm/gpgsm.c:376 +#: sm/gpgsm.c:378 msgid "|NAME|use cipher algorithm NAME" msgstr "|NAME|Den Verschlüsselungsalgrithmus NAME benutzen" -#: sm/gpgsm.c:378 +#: sm/gpgsm.c:380 msgid "|NAME|use message digest algorithm NAME" msgstr "|NAME|Den Hashalgorithmus NAME benutzen" -#: sm/gpgsm.c:380 +#: sm/gpgsm.c:382 msgid "|N|use compress algorithm N" msgstr "|N|Den Kompressionsalgorithmus Nummer N benutzen" -#: sm/gpgsm.c:388 +#: sm/gpgsm.c:390 msgid "" "@\n" "(See the man page for a complete listing of all commands and options)\n" @@ -1291,7 +1297,7 @@ msgstr "" "@\n" "(Die \"man\" Seite beschreibt alle Kommands und Optionen)\n" -#: sm/gpgsm.c:391 +#: sm/gpgsm.c:393 msgid "" "@\n" "Examples:\n" @@ -1311,11 +1317,11 @@ msgstr "" " --list-keys [Namen] Schlüssel anzeigenn\n" " --fingerprint [Namen] \"Fingerabdrücke\" anzeigen\\n\n" -#: sm/gpgsm.c:510 +#: sm/gpgsm.c:516 msgid "Usage: gpgsm [options] [files] (-h for help)" msgstr "Gebrauch: gpgsm [Optionen] [Dateien] (-h für Hilfe)" -#: sm/gpgsm.c:513 +#: sm/gpgsm.c:519 msgid "" "Syntax: gpgsm [options] [files]\n" "sign, check, encrypt or decrypt using the S/MIME protocol\n" @@ -1324,7 +1330,7 @@ msgstr "" "Gebrauch: gpgsm [Optionen] [Dateien]\n" "Signieren, prüfen, ver- und entschlüsseln mittels S/MIME protocol\n" -#: sm/gpgsm.c:520 +#: sm/gpgsm.c:526 msgid "" "\n" "Supported algorithms:\n" @@ -1332,215 +1338,215 @@ msgstr "" "\n" "Unterstützte Algorithmen:\n" -#: sm/gpgsm.c:607 +#: sm/gpgsm.c:613 msgid "usage: gpgsm [options] " msgstr "Gebrauch: gpgsm [Optionen] " -#: sm/gpgsm.c:672 +#: sm/gpgsm.c:678 msgid "conflicting commands\n" msgstr "Widersprechende Kommandos\n" -#: sm/gpgsm.c:688 +#: sm/gpgsm.c:694 #, c-format msgid "can't encrypt to `%s': %s\n" msgstr "Verschlüsseln für `%s' nicht möglich: %s\n" -#: sm/gpgsm.c:762 +#: sm/gpgsm.c:768 #, c-format msgid "libksba is too old (need %s, have %s)\n" msgstr "Die Bibliothek Libksba is nicht aktuell (benötige %s, habe %s)\n" -#: sm/gpgsm.c:1221 +#: sm/gpgsm.c:1229 msgid "WARNING: program may create a core file!\n" msgstr "WARNUNG: Programm könnte eine core-dump-Datei schreiben!\n" -#: sm/gpgsm.c:1238 +#: sm/gpgsm.c:1246 msgid "WARNING: running with faked system time: " msgstr "WARNUNG: Ausführung mit gefälschter Systemzeit: " -#: sm/gpgsm.c:1264 +#: sm/gpgsm.c:1272 msgid "selected cipher algorithm is invalid\n" msgstr "Das ausgewählte Verschlüsselungsverfahren ist ungültig\n" -#: sm/gpgsm.c:1272 +#: sm/gpgsm.c:1280 msgid "selected digest algorithm is invalid\n" msgstr "Das ausgewählte Hashverfahren ist ungültig\n" -#: sm/gpgsm.c:1302 +#: sm/gpgsm.c:1310 #, c-format msgid "can't sign using `%s': %s\n" msgstr "Signieren mit `%s' nicht möglich: %s\n" -#: sm/gpgsm.c:1475 +#: sm/gpgsm.c:1483 msgid "this command has not yet been implemented\n" msgstr "Dieses Kommando wurde noch nicht implementiert\n" -#: sm/gpgsm.c:1705 sm/gpgsm.c:1742 sm/qualified.c:73 +#: sm/gpgsm.c:1713 sm/gpgsm.c:1750 sm/qualified.c:74 #, c-format msgid "can't open `%s': %s\n" msgstr "Datei `%s' kann nicht geöffnet werden: %s\n" -#: sm/import.c:109 +#: sm/import.c:110 #, c-format msgid "total number processed: %lu\n" msgstr "gesamte verarbeitete Anzahl: %lu\n" -#: sm/import.c:112 +#: sm/import.c:113 #, c-format msgid " imported: %lu" msgstr " importiert: %lu" -#: sm/import.c:116 +#: sm/import.c:117 #, c-format msgid " unchanged: %lu\n" msgstr " nicht geändert: %lu\n" -#: sm/import.c:118 +#: sm/import.c:119 #, c-format msgid " secret keys read: %lu\n" msgstr " gelesene private Schlüssel: %lu\n" -#: sm/import.c:120 +#: sm/import.c:121 #, c-format msgid " secret keys imported: %lu\n" msgstr "importierte priv. Schlüssel: %lu\n" -#: sm/import.c:122 +#: sm/import.c:123 #, c-format msgid " secret keys unchanged: %lu\n" msgstr "ungeänderte priv. Schlüssel: %lu\n" -#: sm/import.c:124 +#: sm/import.c:125 #, c-format msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: sm/import.c:226 +#: sm/import.c:227 msgid "error storing certificate\n" msgstr "Fehler beim speichern des Zertifikats\n" -#: sm/import.c:234 +#: sm/import.c:235 msgid "basic certificate checks failed - not imported\n" msgstr "Grundlegende Zertifikatprüfungen fehlgeschlagen - nicht importiert\n" -#: sm/import.c:420 sm/import.c:452 +#: sm/import.c:421 sm/import.c:453 #, c-format msgid "error importing certificate: %s\n" msgstr "Fehler beim Importieren des Zertifikats: %s\n" -#: sm/import.c:524 sm/import.c:549 +#: sm/import.c:525 sm/import.c:550 #, c-format msgid "error creating temporary file: %s\n" msgstr "Fehler beim Erstellen einer temporären Datei: %s\n" -#: sm/import.c:532 +#: sm/import.c:533 #, c-format msgid "error writing to temporary file: %s\n" msgstr "Fehler beim Schreiben auf eine temporäre Datei: %s\n" -#: sm/import.c:541 +#: sm/import.c:542 #, c-format msgid "error reading input: %s\n" msgstr "Fehler beim Lesen der Eingabe: %s\n" -#: sm/keydb.c:187 +#: sm/keydb.c:188 #, c-format msgid "error creating keybox `%s': %s\n" msgstr "Die \"Keybox\" `%s' konnte nicht erstellt werden: %s\n" -#: sm/keydb.c:190 +#: sm/keydb.c:191 msgid "you may want to start the gpg-agent first\n" msgstr "Sie sollten zuerst den gpg-agent starten\n" -#: sm/keydb.c:195 +#: sm/keydb.c:196 #, c-format msgid "keybox `%s' created\n" msgstr "Die \"Keybox\" `%s' wurde erstellt\n" -#: sm/keydb.c:218 +#: sm/keydb.c:219 #, c-format msgid "can't create lock for `%s'\n" msgstr "Datei `%s' konnte nicht gesperrt werden\n" -#: sm/keydb.c:1326 sm/keydb.c:1388 +#: sm/keydb.c:1300 sm/keydb.c:1366 msgid "failed to get the fingerprint\n" msgstr "Kann den Fingerprint nicht ermitteln\n" -#: sm/keydb.c:1333 sm/keydb.c:1395 +#: sm/keydb.c:1307 sm/keydb.c:1373 msgid "failed to allocate keyDB handle\n" msgstr "Kann keinen KeyDB Handler bereitstellen\n" -#: sm/keydb.c:1350 +#: sm/keydb.c:1328 #, c-format msgid "problem looking for existing certificate: %s\n" msgstr "Problem bei der Suche nach vorhandenem Zertifikat: %s\n" -#: sm/keydb.c:1358 +#: sm/keydb.c:1336 #, c-format msgid "error finding writable keyDB: %s\n" msgstr "Fehler bei der Suche nach einer schreibbaren KeyDB: %s\n" -#: sm/keydb.c:1366 +#: sm/keydb.c:1344 #, c-format msgid "error storing certificate: %s\n" msgstr "Fehler beim Speichern des Zertifikats: %s\n" -#: sm/keydb.c:1410 +#: sm/keydb.c:1388 #, c-format msgid "problem re-searching certificate: %s\n" msgstr "Problem bei Wiederfinden des Zertifikats: %s\n" -#: sm/keydb.c:1419 sm/keydb.c:1507 +#: sm/keydb.c:1397 sm/keydb.c:1485 #, c-format msgid "error getting stored flags: %s\n" msgstr "Fehler beim Holen der gespeicherten Flags: %s\n" -#: sm/keydb.c:1428 sm/keydb.c:1518 +#: sm/keydb.c:1406 sm/keydb.c:1496 #, c-format msgid "error storing flags: %s\n" msgstr "Fehler beim Speichern der Flags: %s\n" -#: sm/sign.c:443 +#: sm/sign.c:444 #, c-format msgid "checking for qualified certificate failed: %s\n" msgstr "Prüfung auf ein qualifiziertes Zertifikats fehlgeschlagen: %s\n" -#: sm/sign.c:478 sm/verify.c:188 +#: sm/sign.c:479 sm/verify.c:189 msgid "(this is the MD2 algorithm)\n" msgstr "(Dies ist der MD2 Algorithmus)\n" -#: sm/verify.c:387 +#: sm/verify.c:388 msgid "Signature made " msgstr "Signatur erzeugt am " -#: sm/verify.c:391 +#: sm/verify.c:392 msgid "[date not given]" msgstr "[Datum nicht vorhanden]" -#: sm/verify.c:392 +#: sm/verify.c:393 #, c-format msgid " using certificate ID %08lX\n" msgstr "mittels Zertifikat ID %08lX\n" -#: sm/verify.c:505 +#: sm/verify.c:506 msgid "Good signature from" msgstr "Korrekte Signatur von" -#: sm/verify.c:506 +#: sm/verify.c:507 msgid " aka" msgstr " alias" -#: sm/qualified.c:112 +#: sm/qualified.c:113 #, c-format msgid "invalid formatted fingerprint in `%s', line %d\n" msgstr "Der Fingerabdruck in `%s', Zeile %d is fehlerhaft formatiert\n" -#: sm/qualified.c:130 +#: sm/qualified.c:131 #, c-format msgid "invalid country code in `%s', line %d\n" msgstr "Ungültiger Landescode in `%s', Zeile %d\n" -#: sm/qualified.c:215 +#: sm/qualified.c:224 #, c-format msgid "" "You are about to create a signature using your certificate:\n" @@ -1557,7 +1563,7 @@ msgstr "" "\n" "%s%sSind Sie wirklich sicher, daß Sie dies möchten?" -#: sm/qualified.c:224 +#: sm/qualified.c:233 msgid "" "Note, that this software is not officially approved to create or verify such " "signatures.\n" @@ -1565,7 +1571,7 @@ msgstr "" "Bitte beachten Sie, daß diese Software nicht offiziell zur Erzeugung\n" "oder Prüfung von qualifizierten Signaturen zugelassen ist.\n" -#: sm/qualified.c:312 +#: sm/qualified.c:321 #, c-format msgid "" "You are about to create a signature using your certificate:\n" @@ -1577,31 +1583,31 @@ msgstr "" "zu erzeugen. Bitte beachten Sie, daß dies KEINE qualifizierte\n" "Signatur erzeugen wird." -#: tools/gpgconf.c:55 +#: tools/gpgconf.c:56 msgid "list all components" msgstr "Liste aller Komponenten" -#: tools/gpgconf.c:56 +#: tools/gpgconf.c:57 msgid "|COMPONENT|list options" msgstr "|KOMPONENTE|Zeige die Optionen an" -#: tools/gpgconf.c:57 +#: tools/gpgconf.c:58 msgid "|COMPONENT|change options" msgstr "|KOMPONENTE|Ändere die Optionen" -#: tools/gpgconf.c:63 +#: tools/gpgconf.c:64 msgid "quiet" msgstr "Weniger Ausgaben" -#: tools/gpgconf.c:65 +#: tools/gpgconf.c:66 msgid "activate changes at runtime, if possible" msgstr "Aktiviere Änderungen zur Laufzeit; falls möglich" -#: tools/gpgconf.c:88 +#: tools/gpgconf.c:89 msgid "Usage: gpgconf [options] (-h for help)" msgstr "Gebrauch: gpgconf [Optionen] (-h für Hilfe)" -#: tools/gpgconf.c:91 +#: tools/gpgconf.c:92 msgid "" "Syntax: gpgconf [options]\n" "Manage configuration options for tools of the GnuPG system\n" @@ -1609,71 +1615,75 @@ msgstr "" "Syntax: gpgconf {Optionen]\n" "Verwalte Konfigurationsoptionen für Programme des GnuPG Systems\n" -#: tools/gpgconf.c:175 +#: tools/gpgconf.c:176 msgid "usage: gpgconf [options] " msgstr "Gebrauch: gpgconf [Optionen] " -#: tools/gpgconf.c:177 +#: tools/gpgconf.c:178 msgid "Need one component argument" msgstr "Benötige ein Komponenten Argument" -#: tools/gpgconf.c:186 +#: tools/gpgconf.c:187 msgid "Component not found" msgstr "Komponente nicht gefunden" -#: tools/gpgconf-comp.c:435 tools/gpgconf-comp.c:499 tools/gpgconf-comp.c:566 -#: tools/gpgconf-comp.c:619 tools/gpgconf-comp.c:688 +#: tools/gpgconf-comp.c:437 tools/gpgconf-comp.c:501 tools/gpgconf-comp.c:568 +#: tools/gpgconf-comp.c:624 tools/gpgconf-comp.c:693 msgid "Options controlling the diagnostic output" msgstr "Optionen zur Einstellung Diagnoseausgaben" -#: tools/gpgconf-comp.c:448 tools/gpgconf-comp.c:512 tools/gpgconf-comp.c:579 -#: tools/gpgconf-comp.c:632 tools/gpgconf-comp.c:711 +#: tools/gpgconf-comp.c:450 tools/gpgconf-comp.c:514 tools/gpgconf-comp.c:581 +#: tools/gpgconf-comp.c:637 tools/gpgconf-comp.c:716 msgid "Options controlling the configuration" msgstr "Optionen zur Einstellung der Konfiguration" -#: tools/gpgconf-comp.c:458 tools/gpgconf-comp.c:537 tools/gpgconf-comp.c:586 -#: tools/gpgconf-comp.c:642 tools/gpgconf-comp.c:718 +#: tools/gpgconf-comp.c:460 tools/gpgconf-comp.c:539 tools/gpgconf-comp.c:588 +#: tools/gpgconf-comp.c:647 tools/gpgconf-comp.c:723 msgid "Options useful for debugging" msgstr "Nützliche Optionen zum Debuggen" -#: tools/gpgconf-comp.c:463 tools/gpgconf-comp.c:542 tools/gpgconf-comp.c:591 -#: tools/gpgconf-comp.c:647 tools/gpgconf-comp.c:726 +#: tools/gpgconf-comp.c:465 tools/gpgconf-comp.c:544 tools/gpgconf-comp.c:593 +#: tools/gpgconf-comp.c:652 tools/gpgconf-comp.c:731 msgid "|FILE|write server mode logs to FILE" msgstr "|DATEI|Schreibe im Servermodus Logs auf DATEI" -#: tools/gpgconf-comp.c:471 tools/gpgconf-comp.c:547 tools/gpgconf-comp.c:655 +#: tools/gpgconf-comp.c:473 tools/gpgconf-comp.c:549 tools/gpgconf-comp.c:660 msgid "Options controlling the security" msgstr "Optionen zur Einstellung der Sicherheit" -#: tools/gpgconf-comp.c:599 +#: tools/gpgconf-comp.c:601 msgid "Configuration for Keyservers" msgstr "Konfiguration der Schlüsselserver" -#: tools/gpgconf-comp.c:660 +#: tools/gpgconf-comp.c:606 +msgid "allow PKA lookups (DNS requests)" +msgstr "" + +#: tools/gpgconf-comp.c:665 msgid "do not check CRLs for root certificates" msgstr "CRL bei Wurzelzertifikaten nicht überprüfen" -#: tools/gpgconf-comp.c:701 +#: tools/gpgconf-comp.c:706 msgid "Options controlling the format of the output" msgstr "Optionen zum Einstellen der Ausgabeformate" -#: tools/gpgconf-comp.c:737 +#: tools/gpgconf-comp.c:742 msgid "Options controlling the interactivity and enforcement" msgstr "Optionen zur Einstellung der Interaktivität und Geltendmachung" -#: tools/gpgconf-comp.c:747 +#: tools/gpgconf-comp.c:752 msgid "Configuration for HTTP servers" msgstr "Konfiguration für HTTP Server" -#: tools/gpgconf-comp.c:758 +#: tools/gpgconf-comp.c:763 msgid "use system's HTTP proxy setting" msgstr "Einstellungen des System HTTP-Proxy benutzen" -#: tools/gpgconf-comp.c:763 +#: tools/gpgconf-comp.c:768 msgid "Configuration of LDAP servers to use" msgstr "Konfiguration der zu nutzenden LDAP-Server" -#: tools/gpgconf-comp.c:800 +#: tools/gpgconf-comp.c:805 msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" -- cgit v1.2.3 From 91a4be3126f07e11719a91883c4e220c16b6fabe Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 20 Jun 2006 18:52:43 +0000 Subject: Preparing a new release --- ChangeLog | 4 ++++ NEWS | 24 ++++++++++++------------ configure.ac | 4 ++-- po/de.po | 10 +++++----- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index d62732c8a..745a6a198 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-06-20 Werner Koch <wk@g10code.com> + + Released 1.9.21. + 2006-06-08 Marcus Brinkmann <marcus@g10code.de> * configure.ac (PTH_LIBS): Add --all to pth-config invocation. diff --git a/NEWS b/NEWS index 679bf7d5b..b85f1aef6 100644 --- a/NEWS +++ b/NEWS @@ -1,22 +1,22 @@ -Noteworthy changes in version 1.9.21 +Noteworthy changes in version 1.9.21 (2006-06-20) ------------------------------------------------- - * [scdaemon] New command APDU. + * New command APDU for scdaemon to allow using it for general card + access. Might be used through gpg-connect-agent by using the SCD + prefix command. - * [scdaemon] Support for keypads of some readers. Tested only with - SPR532. New option --disable-keypad. + * Support for the CardMan 4040 PCMCIA reader (Linux 2.6.15 required). - * [scdaemon] Support for CardMan 4040 PCMCIA reader. + * Scdaemon does not anymore reset cards at the end of a connection. - * [scdaemon] Cards are not anymore reseted at the end of a connection. + * Kludge to allow use of Bundesnetzagentur issued X.509 certificates. - * [gpgsm] Kludge to allow use of Bundesnetzagentur issued - certificates. + * Added --hash=xxx option to scdaemon's PKSIGN command. - * [scdaemon] Added --hash=xxx option to the PKSIGN command. + * Pkcs#12 files are now created with a MAC. This is for better + interoperability. - * [gpg-protect-tool] Does now create a MAC for P12 files. This is for - better interoperability. + * Collected bug fixes and minor other changes. Noteworthy changes in version 1.9.20 (2005-12-20) @@ -310,7 +310,7 @@ Noteworthy changes in version 1.9.0 (2003-08-05) development branch. - Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright 2002, 2003, 2004, 2005, 2006 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 diff --git a/configure.ac b/configure.ac index d77093a63..eb29111a7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac - for GnuPG 1.9 # Copyright (C) 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -27,7 +27,7 @@ min_automake_version="1.9.3" # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [1.9.21]) -m4_define([my_issvn], [yes]) +m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ diff --git a/po/de.po b/po/de.po index 5d9d50221..f95881efb 100644 --- a/po/de.po +++ b/po/de.po @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" "POT-Creation-Date: 2006-06-20 18:45+0200\n" -"PO-Revision-Date: 2005-11-28 12:16+0100\n" +"PO-Revision-Date: 2006-06-20 20:04+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -747,7 +747,7 @@ msgstr "Ungültige Struktur der OpenPGP Karte (DO 0x93)\n" #: scd/app-openpgp.c:2125 #, c-format msgid "card does not support digest algorithm %s\n" -msgstr "" +msgstr "Der Hashalgorithmus %s wird von der Karte nicht unterstützt\n" #: scd/app-openpgp.c:2172 #, c-format @@ -789,9 +789,9 @@ msgid "can't connect to the agent - trying fall back\n" msgstr "Verbindung zum gpg-agent nicht möglich - Ersatzmethode wird versucht\n" #: sm/call-dirmngr.c:182 -#, fuzzy, c-format +#, c-format msgid "no running dirmngr - starting `%s'\n" -msgstr "Kein aktiver Dirmngr - es wird einer gestartet\n" +msgstr "Kein aktiver Dirmngr - `%s' wird einer gestartet\n" #: sm/call-dirmngr.c:216 msgid "malformed DIRMNGR_INFO environment variable\n" @@ -1657,7 +1657,7 @@ msgstr "Konfiguration der Schlüsselserver" #: tools/gpgconf-comp.c:606 msgid "allow PKA lookups (DNS requests)" -msgstr "" +msgstr "Erlaube PKA Zugriffe (DNS Anfragen)" #: tools/gpgconf-comp.c:665 msgid "do not check CRLs for root certificates" -- cgit v1.2.3 From f081ad529d212be23aa5dd9d4bfb81282748e5eb Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 27 Jun 2006 14:30:59 +0000 Subject: Ported patches from 1.4.x --- g10/ChangeLog | 60 ++++++++++++++++++++++++++ g10/build-packet.c | 3 +- g10/exec.c | 7 ++- g10/getkey.c | 16 +++---- g10/gpg.c | 89 +++++++++++++++++++++++++++++++++++++- g10/import.c | 34 +++++++++++---- g10/keygen.c | 123 ++++++++++++++++++++++++++++++++++++++++------------- g10/options.h | 3 +- g10/parse-packet.c | 38 ++++++++++++++--- g10/sign.c | 9 +++- 10 files changed, 323 insertions(+), 59 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 47e9a7328..4a838257e 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,63 @@ +2006-06-27 Werner Koch <wk@g10code.com> + + Applied patches from 1.4.x (2006-05-22 to 2006-06-23) from David: + + * keygen.c (keygen_upd_std_prefs, keygen_add_std_prefs) + (proc_parameter_file): Add --default-keyserver-url to specify a + keyserver URL at key generation time, and "Keyserver:" keyword for + doing the same through a batch file. + * options.h, gpg.c (main): Ditto. + + * sign.c (do_sign): For now don't accept a truncated hash even + for DSA1 keys (be liberal in what you accept, etc). + + * import.c (import_one): Add a flag (from_sk) so we don't check + prefs on an autoconverted public key. The check should only + happen on the sk side. Noted by Dirk Traulsen. + + * keygen.c (gen_card_key): Add optional argument to return a + pointer (not a copy) of the stub secret key for the secret key we + just generated on the card. + (generate_card_subkeypair): Use it here so that the signing key on + the card can use the card to generate the 0x19 backsig on the + primary key. Noted by Janko Heilgeist and Jonas Oberg. + + * parse-packet.c (parse_user_id): Cap the user ID size at 2048 + bytes. This prevents a memory allocation attack with a very large + user ID. A very large packet length could even cause the + allocation (a u32) to wrap around to a small number. Noted by + Evgeny Legerov on full-disclosure. + + * keygen.c (gen_dsa): Allow generating DSA2 keys. Allow + specifying sizes > 1024 when --enable-dsa2 is set. The size of q + is set automatically based on the key size. + (ask_keysize, generate_keypair): Ask for DSA size when + --enable-dsa2 is set. + + * exec.c (make_tempdir) [W32]: Fix bug with a temporary directory + on W32 that is over 256 bytes long. Noted by Israel G. Lugo. + + * gpg.c (reopen_std): New function to reopen fd 0, 1, or 2 if we + are called with them closed. This is to protect our + keyring/trustdb files from corruption if they get attached to one + of the standard fds. Print a warning if possible that this has + happened, and fail completely if we cannot reopen (should never + happen). + (main): Call it here. + + * parse-packet.c (dump_sig_subpkt, parse_signature): Fix meaning + of key expiration and sig expiration subpackets - zero means + "never expire" according to 2440, not "expire instantly". + * build-packet.c (build_sig_subpkt_from_sig): Ditto. + * getkey.c (fixup_uidnode, merge_selfsigs_main) + (merge_selfsigs_subkey): Ditto. + * keygen.c (keygen_add_key_expire): Ditto. + + * getkey.c (get_pubkey_byname) + * import.c (import_one): Fix key selection problem when + auto-key-locate returns a list of keys, not all of which are + usable (revoked, expired, etc). Noted by Simon Josefsson. + 2006-05-24 Werner Koch <wk@g10code.com> * keyid.c (hash_public_key): Do not double hash the length bytes, diff --git a/g10/build-packet.c b/g10/build-packet.c index cbf037483..878481961 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -841,7 +841,8 @@ build_sig_subpkt_from_sig( PKT_signature *sig ) if(sig->expiredate>sig->timestamp) u=sig->expiredate-sig->timestamp; else - u=0; + u=1; /* A 1-second expiration time is the shortest one + OpenPGP has */ buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; diff --git a/g10/exec.c b/g10/exec.c index 6938a409a..203c4c78f 100644 --- a/g10/exec.c +++ b/g10/exec.c @@ -127,8 +127,11 @@ static int make_tempdir(struct exec_info *info) if(tmp==NULL) { #if defined (_WIN32) - tmp=xmalloc(256); - if(GetTempPath(256,tmp)==0) + int err; + + tmp=xmalloc(MAX_PATH+2); + err=GetTempPath(MAX_PATH+1,tmp); + if(err==0 || err>MAX_PATH+1) strcpy(tmp,"c:\\windows\\temp"); else { diff --git a/g10/getkey.c b/g10/getkey.c index bff2a0ddc..c0088c38c 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -935,7 +935,7 @@ get_pubkey_byname (PKT_public_key *pk, for(akl=opt.auto_key_locate;akl;akl=akl->next) { - unsigned char *fpr; + unsigned char *fpr=NULL; size_t fpr_len; switch(akl->type) @@ -1507,12 +1507,12 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) /* store the key flags in the helper variable for later processing */ uid->help_key_usage=parse_key_usage(sig); - /* ditto or the key expiration */ - uid->help_key_expire = 0; + /* ditto for the key expiration */ p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) { - uid->help_key_expire = keycreated + buffer_to_u32(p); - } + if( p && buffer_to_u32(p) ) + uid->help_key_expire = keycreated + buffer_to_u32(p); + else + uid->help_key_expire = 0; /* Set the primary user ID flag - we will later wipe out some * of them to only have one in our keyblock */ @@ -1724,7 +1724,7 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo) key_usage=parse_key_usage(sig); p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) + if( p && buffer_to_u32(p) ) { key_expire = keytimestamp + buffer_to_u32(p); key_expire_seen = 1; @@ -2128,7 +2128,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) subpk->pubkey_usage = key_usage; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) + if ( p && buffer_to_u32(p) ) key_expire = keytimestamp + buffer_to_u32(p); else key_expire = 0; diff --git a/g10/gpg.c b/g10/gpg.c index 4235f3f7a..c1a0be50f 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -328,6 +328,7 @@ enum cmd_and_opt_values oNoAutoCheckTrustDB, oPreservePermissions, oDefaultPreferenceList, + oDefaultKeyserverURL, oPersonalCipherPreferences, oPersonalDigestPreferences, oPersonalCompressPreferences, @@ -659,6 +660,7 @@ static ARGPARSE_OPTS opts[] = { { aRebuildKeydbCaches, "rebuild-keydb-caches", 256, "@"}, { oPreservePermissions, "preserve-permissions", 0, "@"}, { oDefaultPreferenceList, "default-preference-list", 2, "@"}, + { oDefaultKeyserverURL, "default-keyserver-url", 2, "@"}, { oPersonalCipherPreferences, "personal-cipher-preferences", 2, "@"}, { oPersonalDigestPreferences, "personal-digest-preferences", 2, "@"}, { oPersonalCompressPreferences, "personal-compress-preferences", 2, "@"}, @@ -1643,6 +1645,78 @@ parse_trust_model(const char *model) log_error("unknown trust model `%s'\n",model); } + + +/* Make sure that the standard file descriptors are opened. Obviously + some folks close them before an exec and the next file we open will + get one of them assigned and thus any output (i.e. diagnostics) end + up in that file (e.g. the trustdb). Not actually a gpg problem as + this will hapenn with almost all utilities when called in a wrong + way. However we try to minimize the damage here and raise + awareness of the problem. + + Must be called before we open any files! */ +static void +reopen_std(void) +{ +#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM) + struct stat statbuf; + int did_stdin=0,did_stdout=0,did_stderr=0; + FILE *complain; + + if(fstat(STDIN_FILENO,&statbuf)==-1 && errno==EBADF) + { + if(open("/dev/null",O_RDONLY)==STDIN_FILENO) + did_stdin=1; + else + did_stdin=2; + } + + if(fstat(STDOUT_FILENO,&statbuf)==-1 && errno==EBADF) + { + if(open("/dev/null",O_WRONLY)==STDOUT_FILENO) + did_stdout=1; + else + did_stdout=2; + } + + if(fstat(STDERR_FILENO,&statbuf)==-1 && errno==EBADF) + { + if(open("/dev/null",O_WRONLY)==STDERR_FILENO) + did_stderr=1; + else + did_stderr=2; + } + + /* It's hard to log this sort of thing since the filehandle we would + complain to may be closed... */ + if(did_stderr==0) + complain=stderr; + else if(did_stdout==0) + complain=stdout; + else + complain=NULL; + + if(complain) + { + if(did_stdin==1) + fprintf(complain,"gpg: WARNING: standard input reopened\n"); + if(did_stdout==1) + fprintf(complain,"gpg: WARNING: standard output reopened\n"); + if(did_stderr==1) + fprintf(complain,"gpg: WARNING: standard error reopened\n"); + + if(did_stdin==2 || did_stdout==2 || did_stderr==2) + fprintf(complain,"gpg: fatal: unable to reopen standard input," + " output, or error\n"); + } + + if(did_stdin==2 || did_stdout==2 || did_stderr==2) + exit(3); +#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */ +} + + int main (int argc, char **argv ) { @@ -1697,7 +1771,7 @@ main (int argc, char **argv ) /* Please note that we may running SUID(ROOT), so be very CAREFUL when adding any stuff between here and the call to secmem_init() somewhere after the option parsing. */ - + reopen_std (); trap_unaligned(); set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -2586,6 +2660,19 @@ main (int argc, char **argv ) case oDefaultPreferenceList: opt.def_preference_list = pargs.r.ret_str; break; + case oDefaultKeyserverURL: + { + struct keyserver_spec *keyserver; + keyserver=parse_keyserver_uri(pargs.r.ret_str,1, + configname,configlineno); + if(!keyserver) + log_error(_("could not parse keyserver URL\n")); + else + free_keyserver_spec(keyserver); + + opt.def_keyserver_url = pargs.r.ret_str; + } + break; case oPersonalCipherPreferences: pers_cipher_list=pargs.r.ret_str; break; diff --git a/g10/import.c b/g10/import.c index 4526d84d7..3b41e08cf 100644 --- a/g10/import.c +++ b/g10/import.c @@ -66,7 +66,7 @@ static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); static void revocation_present(KBNODE keyblock); static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats, unsigned char **fpr,size_t *fpr_len, - unsigned int options); + unsigned int options,int from_sk); static int import_secret_one( const char *fname, KBNODE keyblock, struct stats_s *stats, unsigned int options); static int import_revoke_cert( const char *fname, KBNODE node, @@ -258,7 +258,7 @@ import( IOBUF inp, const char* fname,struct stats_s *stats, while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) - rc = import_one( fname, keyblock, stats, fpr, fpr_len, options ); + rc = import_one( fname, keyblock, stats, fpr, fpr_len, options, 0); else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) rc = import_secret_one( fname, keyblock, stats, options ); else if( keyblock->pkt->pkttype == PKT_SIGNATURE @@ -679,7 +679,8 @@ check_prefs(KBNODE keyblock) */ static int import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, - unsigned char **fpr,size_t *fpr_len,unsigned int options ) + unsigned char **fpr,size_t *fpr_len,unsigned int options, + int from_sk ) { PKT_public_key *pk; PKT_public_key *pk_orig; @@ -698,9 +699,6 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, pk = node->pkt->pkt.public_key; - if(fpr) - *fpr=fingerprint_from_pk(pk,NULL,fpr_len); - keyid_from_pk( pk, keyid ); uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); @@ -978,13 +976,31 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, if(mod_key) { revocation_present(keyblock_orig); - if(seckey_available(keyid)==0) + if(!from_sk && seckey_available(keyid)==0) check_prefs(keyblock_orig); } else if(new_key) { + /* A little explanation for this: we fill in the fingerprint + when importing keys as it can be useful to know the + fingerprint in certain keyserver-related cases (a keyserver + asked for a particular name, but the key doesn't have that + name). However, in cases where we're importing more than + one key at a time, we cannot know which key to fingerprint. + In these cases, rather than guessing, we do not fingerpring + at all, and we must hope the user ID on the keys are + useful. */ + if(fpr) + { + xfree(*fpr); + if(stats->imported==1) + *fpr=fingerprint_from_pk(pk,NULL,fpr_len); + else + *fpr=NULL; + } + revocation_present(keyblock); - if(seckey_available(keyid)==0) + if(!from_sk && seckey_available(keyid)==0) check_prefs(keyblock); } @@ -1156,7 +1172,7 @@ import_secret_one( const char *fname, KBNODE keyblock, if(pub_keyblock) { import_one(fname,pub_keyblock,stats, - NULL,NULL,opt.import_options); + NULL,NULL,opt.import_options,1); release_kbnode(pub_keyblock); } } diff --git a/g10/keygen.c b/g10/keygen.c index f791c6cd0..7a6296974 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -42,6 +42,7 @@ #include "trustdb.h" #include "status.h" #include "i18n.h" +#include "keyserver-internal.h" #include "call-agent.h" @@ -69,7 +70,8 @@ enum para_name { pPASSPHRASE_S2K, pSERIALNO, pBACKUPENCDIR, - pHANDLE + pHANDLE, + pKEYSERVER }; struct para_data_s { @@ -125,6 +127,7 @@ static void do_generate_keypair( struct para_data_s *para, static int write_keyblock( IOBUF out, KBNODE node ); static int gen_card_key (int algo, int keyno, int is_primary, KBNODE pub_root, KBNODE sec_root, + PKT_secret_key **ret_sk, u32 expireval, struct para_data_s *para); static int gen_card_key_with_backup (int algo, int keyno, int is_primary, KBNODE pub_root, KBNODE sec_root, @@ -224,7 +227,7 @@ keygen_add_key_expire( PKT_signature *sig, void *opaque ) if(pk->expiredate > pk->timestamp) u= pk->expiredate - pk->timestamp; else - u= 0; + u= 1; buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; @@ -657,6 +660,7 @@ keygen_upd_std_prefs( PKT_signature *sig, void *opaque ) /* Make sure that the MDC feature flag is set if needed */ add_feature_mdc (sig,mdc_available); add_keyserver_modify (sig,ks_modify); + keygen_add_keyserver_url(sig,NULL); return 0; } @@ -675,6 +679,7 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque ) do_add_key_flags (sig, pk->pubkey_usage); keygen_add_key_expire( sig, opaque ); keygen_upd_std_prefs (sig, opaque); + keygen_add_keyserver_url(sig,NULL); return 0; } @@ -684,6 +689,9 @@ keygen_add_keyserver_url(PKT_signature *sig, void *opaque) { const char *url=opaque; + if(!url) + url=opt.def_keyserver_url; + if(url) build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url)); else @@ -940,7 +948,6 @@ write_selfsigs( KBNODE sec_root, KBNODE pub_root, PKT_secret_key *sk, return rc; } -/* sub_sk is currently unused (reserved for backsigs) */ static int write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *pri_sk, PKT_secret_key *sub_sk, @@ -1224,20 +1231,54 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, PKT_public_key *pk; gcry_sexp_t s_parms, s_key; gcry_sexp_t misc_key_info; + unsigned int qbits; - if( nbits > 1024 || nbits < 512 ) { + if ( nbits < 512 || (!opt.flags.dsa2 && nbits > 1024)) + { nbits = 1024; log_info(_("keysize invalid; using %u bits\n"), nbits ); - } + } + else if ( nbits > 3072 ) + { + nbits = 3072; + log_info(_("keysize invalid; using %u bits\n"), nbits ); + } - if( (nbits % 64) ) { + if( (nbits % 64) ) + { nbits = ((nbits + 63) / 64) * 64; log_info(_("keysize rounded up to %u bits\n"), nbits ); - } + } + + /* + Figure out a q size based on the key size. FIPS 180-3 says: + + L = 1024, N = 160 + L = 2048, N = 224 + L = 2048, N = 256 + L = 3072, N = 256 + + 2048/256 is an odd pair since there is also a 2048/224 and + 3072/256. Matching sizes is not a very exact science. + + We'll do 256 qbits for nbits over 2048, 224 for nbits over 1024 + but less than 2048, and 160 for 1024 (DSA1). + */ + + if (nbits > 2048) + qbits = 256; + else if ( nbits > 1024) + qbits = 224; + else + qbits = 160; + + if (qbits != 160 ) + log_info (_("WARNING: some OpenPGP programs can't" + " handle a DSA key with this digest size\n")); rc = gcry_sexp_build (&s_parms, NULL, - "(genkey(dsa(nbits %d)))", - (int)nbits); + "(genkey(dsa(nbits %d)(qbits %d)))", + (int)nbits, (int)qbits); if (rc) log_bug ("gcry_sexp_build failed: %s\n", gpg_strerror (rc)); @@ -1253,9 +1294,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, pk = xmalloc_clear( sizeof *pk ); sk->timestamp = pk->timestamp = make_timestamp(); sk->version = pk->version = 4; - if( expireval ) { - sk->expiredate = pk->expiredate = sk->timestamp + expireval; - } + if (expireval) + sk->expiredate = pk->expiredate = sk->timestamp + expireval; sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA; rc = key_from_sexp (pk->pkey, s_key, "public-key", "pqgy"); @@ -1633,10 +1673,10 @@ ask_keysize( int algo ) switch(algo) { case PUBKEY_ALGO_DSA: - if(opt.expert) + if(opt.flags.dsa2) { def=1024; - max=1024; + max=3072; } else { @@ -2375,6 +2415,25 @@ proc_parameter_file( struct para_data_s *para, const char *fname, /* Set preferences, if any. */ keygen_set_std_prefs(get_parameter_value( para, pPREFERENCES ), 0); + /* Set keyserver, if any. */ + s1=get_parameter_value( para, pKEYSERVER ); + if(s1) + { + struct keyserver_spec *spec; + + spec=parse_keyserver_uri(s1,1,NULL,0); + if(spec) + { + free_keyserver_spec(spec); + opt.def_keyserver_url=s1; + } + else + { + log_error("%s:%d: invalid keyserver url\n", fname, r->lnr ); + return -1; + } + } + /* Set revoker, if any. */ if (parse_revocation_key (fname, para, pREVOKER)) return -1; @@ -2467,6 +2526,7 @@ read_parameter_file( const char *fname ) { "Preferences", pPREFERENCES }, { "Revoker", pREVOKER }, { "Handle", pHANDLE }, + { "Keyserver", pKEYSERVER }, { NULL, 0 } }; IOBUF fp; @@ -2746,12 +2806,12 @@ generate_keypair (const char *fname, const char *card_serialno, sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA ); r->next = para; para = r; - tty_printf(_("DSA keypair will have %u bits.\n"),1024); - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pKEYLENGTH; - strcpy( r->u.value, "1024" ); - r->next = para; - para = r; + nbits = ask_keysize( PUBKEY_ALGO_DSA ); + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYLENGTH; + sprintf( r->u.value, "%u", nbits); + r->next = para; + para = r; r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYUSAGE; strcpy( r->u.value, "sign" ); @@ -2791,7 +2851,7 @@ generate_keypair (const char *fname, const char *card_serialno, } } - + nbits = ask_keysize( algo ); r = xmalloc_clear( sizeof *r + 20 ); r->key = both? pSUBKEYLENGTH : pKEYLENGTH; @@ -3057,7 +3117,7 @@ do_generate_keypair( struct para_data_s *para, } else { - rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, + rc = gen_card_key (PUBKEY_ALGO_RSA, 1, 1, pub_root, sec_root, NULL, get_parameter_u32 (para, pKEYEXPIRE), para); if (!rc) { @@ -3093,7 +3153,7 @@ do_generate_keypair( struct para_data_s *para, if (!rc && card && get_parameter (para, pAUTHKEYTYPE)) { - rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, + rc = gen_card_key (PUBKEY_ALGO_RSA, 3, 0, pub_root, sec_root, NULL, get_parameter_u32 (para, pKEYEXPIRE), para); if (!rc) @@ -3129,6 +3189,7 @@ do_generate_keypair( struct para_data_s *para, } else rc = gen_card_key (PUBKEY_ALGO_RSA, 2, 0, pub_root, sec_root, + NULL, get_parameter_u32 (para, pKEYEXPIRE), para); } @@ -3353,7 +3414,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ) } rc = do_create( algo, nbits, pub_keyblock, sec_keyblock, - dek, s2k, &sub_sk, expire, 1 ); + dek, s2k, &sub_sk, expire, 1 ); if( !rc ) rc = write_keybinding(pub_keyblock, pub_keyblock, pri_sk, sub_sk, use); if( !rc ) @@ -3387,7 +3448,7 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, { int okay=0, rc=0; KBNODE node; - PKT_secret_key *pri_sk = NULL; + PKT_secret_key *pri_sk = NULL, *sub_sk; int algo; unsigned int use; u32 expire; @@ -3467,11 +3528,12 @@ generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, if (passphrase) set_next_passphrase (passphrase); - rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, expire, para); + rc = gen_card_key (algo, keyno, 0, pub_keyblock, sec_keyblock, + &sub_sk, expire, para); if (!rc) - rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, NULL, use); + rc = write_keybinding (pub_keyblock, pub_keyblock, pri_sk, sub_sk, use); if (!rc) - rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, NULL, use); + rc = write_keybinding (sec_keyblock, pub_keyblock, pri_sk, sub_sk, use); if (!rc) { okay = 1; @@ -3518,7 +3580,7 @@ write_keyblock( IOBUF out, KBNODE node ) static int gen_card_key (int algo, int keyno, int is_primary, - KBNODE pub_root, KBNODE sec_root, + KBNODE pub_root, KBNODE sec_root, PKT_secret_key **ret_sk, u32 expireval, struct para_data_s *para) { #ifdef ENABLE_CARD_SUPPORT @@ -3579,6 +3641,9 @@ gen_card_key (int algo, int keyno, int is_primary, sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); } + if( ret_sk ) + *ret_sk = sk; + pkt = xcalloc (1,sizeof *pkt); pkt->pkttype = is_primary ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY; pkt->pkt.public_key = pk; diff --git a/g10/options.h b/g10/options.h index b97b2f3f9..75c2745fc 100644 --- a/g10/options.h +++ b/g10/options.h @@ -154,7 +154,8 @@ struct unsigned int export_options; unsigned int list_options; unsigned int verify_options; - char *def_preference_list; + const char *def_preference_list; + const char *def_keyserver_url; prefitem_t *personal_cipher_prefs; prefitem_t *personal_digest_prefs; prefitem_t *personal_compress_prefs; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index cd6e1dbe6..d792bfff9 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1,6 +1,6 @@ /* parse-packet.c - read packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + * 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -876,8 +876,13 @@ dump_sig_subpkt( int hashed, int type, int critical, break; case SIGSUBPKT_SIG_EXPIRE: if( length >= 4 ) - fprintf (listfp, "sig expires after %s", - strtimevalue( buffer_to_u32(buffer) ) ); + { + if(buffer_to_u32(buffer)) + fprintf (listfp, "sig expires after %s", + strtimevalue( buffer_to_u32(buffer) ) ); + else + fprintf (listfp, "sig does not expire"); + } break; case SIGSUBPKT_EXPORTABLE: if( length ) @@ -901,8 +906,13 @@ dump_sig_subpkt( int hashed, int type, int critical, break; case SIGSUBPKT_KEY_EXPIRE: if( length >= 4 ) - fprintf (listfp, "key expires after %s", - strtimevalue( buffer_to_u32(buffer) ) ); + { + if(buffer_to_u32(buffer)) + fprintf (listfp, "key expires after %s", + strtimevalue( buffer_to_u32(buffer) ) ); + else + fprintf (listfp, "key does not expire"); + } break; case SIGSUBPKT_PREF_SYM: fputs("pref-sym-algos:", listfp ); @@ -1408,7 +1418,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, log_info ("signature packet without keyid\n"); p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL); - if(p) + if(p && buffer_to_u32(p)) sig->expiredate=sig->timestamp+buffer_to_u32(p); if(sig->expiredate && sig->expiredate<=make_timestamp()) sig->flags.expired=1; @@ -2027,6 +2037,20 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; + /* Cap the size of a user ID at 2k: a value absurdly large enough + that there is no sane user ID string (which is printable text + as of RFC2440bis) that won't fit in it, but yet small enough to + avoid allocation problems. A large pktlen may not be + allocatable, and a very large pktlen could actually cause our + allocation to wrap around in xmalloc to a small number. */ + + if (pktlen > 2048) + { + log_error ("packet(%d) too large\n", pkttype); + iobuf_skip_rest(inp, pktlen, 0); + return G10ERR_INVALID_PACKET; + } + packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + pktlen); packet->pkt.user_id->len = pktlen; packet->pkt.user_id->ref=1; diff --git a/g10/sign.c b/g10/sign.c index 3e1d7bc53..0538f0020 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -320,6 +320,12 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, } else { +#if 0 /* disabled *. + /* Disabled for now. It seems reasonable to accept a + truncated hash for a DSA1 key, even though we don't + generate it without --enable-dsa2. Be liberal in what you + accept, etc. */ + /* If it's a DSA key, and q is 160 bits, it might be an old-style DSA key. If the hash doesn't match the q, fail unless --enable-dsa2 is set. If the q isn't 160 bits, then @@ -333,6 +339,7 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); return G10ERR_GENERAL; } +#endif /* disabled */ frame = encode_md_value( NULL, sk, md, digest_algo ); if (!frame) @@ -1539,7 +1546,7 @@ update_keysig_packet( PKT_signature **ret_sig, } /* Note that already expired sigs will remain expired (with a - duration of 0) since build-packet.c:build_sig_subpkt_from_sig + duration of 1) since build-packet.c:build_sig_subpkt_from_sig detects this case. */ if( sig->version >= 4 ) -- cgit v1.2.3 From 98c6970ad1c55d38d7e3d1ba4c97d01dacec281f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Tue, 27 Jun 2006 14:32:34 +0000 Subject: Various smaller changes --- NEWS | 5 +++++ TODO | 4 ++++ agent/ChangeLog | 11 +++++++++++ agent/command-ssh.c | 18 +++++++----------- agent/gpg-agent.c | 3 ++- configure.ac | 4 ++-- sm/ChangeLog | 5 +++++ sm/certchain.c | 2 ++ sm/certdump.c | 30 ++++++++++++++++++++++++++++++ sm/gpgsm.h | 2 ++ sm/keylist.c | 2 +- 11 files changed, 71 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index b85f1aef6..7fafd44d3 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Noteworthy changes in version 1.9.22 +------------------------------------------------- + + + Noteworthy changes in version 1.9.21 (2006-06-20) ------------------------------------------------- diff --git a/TODO b/TODO index da3a76e06..0650361c6 100644 --- a/TODO +++ b/TODO @@ -111,6 +111,10 @@ might want to have an agent context for each service request anyway. ** skclist.c:random_is_faked Remove the whole stuff? +** qbits + We pass a new qbit parameter to genkey - implement this in libgcrypt. +** Makefile.am + Remove the no-pointer-sign kludge. * common/ ** ttyio diff --git a/agent/ChangeLog b/agent/ChangeLog index 7c4799d1c..a194e0d2e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,14 @@ +2006-06-26 Werner Koch <wk@g10code.com> + + * gpg-agent.c (handle_signal): Print infor for SIGUSR2 only in + verbose mode. + +2006-06-22 Werner Koch <wk@g10code.com> + + * command-ssh.c (make_cstring): Use memcpy instead of strncpy. + (ssh_receive_mpint_list, sexp_key_extract, data_sign): Use + xtrycalloc instead of xtrymalloc followed by memset. + 2006-06-20 Werner Koch <wk@g10code.com> * minip12.c (create_final): New arg PW. Add code to calculate the diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 18375a9ae..4e81aa2f2 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -268,7 +268,7 @@ make_cstring (const char *data, size_t data_n) s = xtrymalloc (data_n + 1); if (s) { - strncpy (s, data, data_n); + memcpy (s, data, data_n); s[data_n] = 0; } @@ -853,14 +853,12 @@ ssh_receive_mpint_list (estream_t stream, int secret, elems_public = key_spec.elems_key_public; elems_public_n = strlen (elems_public); - mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); - if (! mpis) + mpis = xtrycalloc (elems_n + 1, sizeof *mpis ); + if (!mpis) { err = gpg_error_from_errno (errno); goto out; } - - memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); elem_is_secret = 0; for (i = 0; i < elems_n; i++) @@ -1143,13 +1141,12 @@ sexp_key_extract (gcry_sexp_t sexp, } elems_n = strlen (elems); - mpis_new = xtrymalloc (sizeof (*mpis_new) * (elems_n + 1)); - if (! mpis_new) + mpis_new = xtrycalloc (elems_n + 1, sizeof *mpis_new ); + if (!mpis_new) { err = gpg_error_from_errno (errno); goto out; } - memset (mpis_new, 0, sizeof (*mpis_new) * (elems_n + 1)); value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0); if (! value_list) @@ -2055,13 +2052,12 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder, elems = spec.elems_signature; elems_n = strlen (elems); - mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1)); - if (! mpis) + mpis = xtrycalloc (elems_n + 1, sizeof *mpis); + if (!mpis) { err = gpg_error_from_errno (errno); goto out; } - memset (mpis, 0, sizeof (*mpis) * (elems_n + 1)); for (i = 0; i < elems_n; i++) { diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index fc2a2001a..24e0b588b 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1360,7 +1360,8 @@ handle_signal (int signo) break; case SIGUSR2: - log_info ("SIGUSR2 received - checking smartcard status\n"); + if (opt.verbose) + log_info ("SIGUSR2 received - checking smartcard status\n"); break; case SIGTERM: diff --git a/configure.ac b/configure.ac index eb29111a7..3f536e472 100644 --- a/configure.ac +++ b/configure.ac @@ -26,8 +26,8 @@ min_automake_version="1.9.3" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.9.21]) -m4_define([my_issvn], [no]) +m4_define([my_version], [1.9.22]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ diff --git a/sm/ChangeLog b/sm/ChangeLog index f191e7512..97fa8cd89 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2006-06-26 Werner Koch <wk@g10code.com> + + * certdump.c (gpgsm_cert_log_name): New. + * certchain.c (is_cert_still_valid): Log the name of the certificate. + 2006-06-20 Werner Koch <wk@g10code.com> * gpgsm.c (gpgsm_init_default_ctrl): Take care of the command line diff --git a/sm/certchain.c b/sm/certchain.c index 4a4ac49f6..647adc030 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -597,6 +597,8 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp, { /* Fixme: We should change the wording because we may have used OCSP. */ + if (!lm) + gpgsm_cert_log_name (NULL, subject_cert); switch (gpg_err_code (err)) { case GPG_ERR_CERT_REVOKED: diff --git a/sm/certdump.c b/sm/certdump.c index 0d5146abc..2f7c1fd54 100644 --- a/sm/certdump.c +++ b/sm/certdump.c @@ -238,6 +238,36 @@ gpgsm_dump_cert (const char *text, ksba_cert_t cert) } +/* Log the certificate's name in "#SN/ISSUERDN" format along with + TEXT. */ +void +gpgsm_cert_log_name (const char *text, ksba_cert_t cert) +{ + log_info ("%s", text? text:"certificate" ); + if (cert) + { + ksba_sexp_t sn; + char *p; + + p = ksba_cert_get_issuer (cert, 0); + sn = ksba_cert_get_serial (cert); + if (p && sn) + { + log_printf (" #"); + gpgsm_dump_serial (sn); + log_printf ("/"); + gpgsm_dump_string (p); + } + else + log_printf (" [invalid]"); + ksba_free (sn); + xfree (p); + } + log_printf ("\n"); +} + + + /* helper for the rfc2253 string parser */ static const unsigned char * diff --git a/sm/gpgsm.h b/sm/gpgsm.h index b49f34640..0d9bac560 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -218,6 +218,8 @@ void gpgsm_print_time (FILE *fp, ksba_isotime_t t); void gpgsm_print_name2 (FILE *fp, const char *string, int translate); void gpgsm_print_name (FILE *fp, const char *string); +void gpgsm_cert_log_name (const char *text, ksba_cert_t cert); + void gpgsm_dump_cert (const char *text, ksba_cert_t cert); void gpgsm_dump_serial (ksba_const_sexp_t p); void gpgsm_dump_time (ksba_isotime_t t); diff --git a/sm/keylist.c b/sm/keylist.c index 9baf065d0..c44d62102 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -672,7 +672,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd, else fputs ("[?]\n", fp); - fputs (" keyUsage:", fp); + fputs (" keyUsage: ", fp); err = ksba_cert_get_key_usage (cert, &kusage); if (gpg_err_code (err) != GPG_ERR_NO_DATA) { -- cgit v1.2.3 From 6c4ae71b5d62e5c4346c0f1eab599b813f77ae17 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Wed, 28 Jun 2006 15:14:09 +0000 Subject: Remove stale lockfiles if created on the same node. --- jnlib/ChangeLog | 12 ++ jnlib/dotlock.c | 593 ++++++++++++++++++++++++++++++++------------------------ 2 files changed, 348 insertions(+), 257 deletions(-) diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 61d12d580..5511dedcd 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,15 @@ +2006-06-28 Werner Koch <wk@g10code.com> + + * dotlock.c (make_dotlock, release_dotlock, read_lockfile) + (maybe_deadlock, destroy_dotlock, create_dotlock): Re-indented. + (create_dotlock): Repalces some log_fatal by log_error as it was + not intended that they should terminate. Write the nodename to + the locking file. Code cleanups. + (read_lockfile): Reworked to read the node name. + (make_dotlock): Test for identical node name and delete lock stale + file. + (release_dotlock): Likewise. + 2006-05-23 Werner Koch <wk@g10code.com> * libjnlib-config.h (JNLIB_NEED_UTF8CONV): Fixed typo in name. diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index 89edb7b91..f5de8fa54 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -1,6 +1,6 @@ /* dotlock.c - dotfile locking * Copyright (C) 1998, 2000, 2001, 2003, 2004, - * 2005 Free Software Foundation, Inc. + * 2005, 2006 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -55,32 +55,35 @@ #endif -struct dotlock_handle { - struct dotlock_handle *next; - char *tname; /* name of lockfile template */ - char *lockname; /* name of the real lockfile */ - int locked; /* lock status */ - int disable; /* locking */ +struct dotlock_handle +{ + struct dotlock_handle *next; + char *tname; /* Name of lockfile template. */ + size_t nodename_off; /* Offset in TNAME of the nodename part. */ + size_t nodename_len; /* Length of the nodename part. */ + char *lockname; /* Name of the real lockfile. */ + int locked; /* Lock status. */ + int disable; /* When true, locking is disabled. */ }; static volatile DOTLOCK all_lockfiles; static int never_lock; -static int read_lockfile( const char *name ); +static int read_lockfile (DOTLOCK h, int *same_node); void disable_dotlock(void) { - never_lock = 1; + never_lock = 1; } /**************** * Create a lockfile with the given name and return an object of * type DOTLOCK which may be used later to actually do the lock. * A cleanup routine gets installed to cleanup left over locks - * or other files used together with the lockmechanism. - * Althoug the function is called dotlock, this does not necessarily + * or other files used together with the lock mechanism. + * Although the function is called dotlock, this does not necessarily * mean that real lockfiles are used - the function may decide to * use fcntl locking. Calling the function with NULL only install * the atexit handler and maybe used to assure that the cleanup @@ -94,160 +97,165 @@ disable_dotlock(void) DOTLOCK create_dotlock( const char *file_to_lock ) { - static int initialized; - DOTLOCK h; - int fd = -1; - char pidstr[16]; - #ifndef HAVE_DOSISH_SYSTEM - struct utsname utsbuf; - #endif - const char *nodename; - const char *dirpart; - int dirpartlen; - - if( !initialized ) { - atexit( dotlock_remove_lockfiles ); - initialized = 1; + static int initialized; + DOTLOCK h; + int fd = -1; + char pidstr[16]; + const char *nodename; + const char *dirpart; + int dirpartlen; +#ifndef HAVE_DOSISH_SYSTEM + struct utsname utsbuf; +#endif + + if ( !initialized ) + { + atexit( dotlock_remove_lockfiles ); + initialized = 1; } - if( !file_to_lock ) - return NULL; + if ( !file_to_lock ) + return NULL; /* Only initialization was requested. */ - h = jnlib_xcalloc( 1, sizeof *h ); - if( never_lock ) { - h->disable = 1; + h = jnlib_xcalloc ( 1, sizeof *h ); + if( never_lock ) + { + h->disable = 1; #ifdef _REENTRANT - /* fixme: aquire mutex on all_lockfiles */ + /* fixme: aquire mutex on all_lockfiles */ #endif - h->next = all_lockfiles; - all_lockfiles = h; - return h; + h->next = all_lockfiles; + all_lockfiles = h; + return h; } #ifndef HAVE_DOSISH_SYSTEM - sprintf( pidstr, "%10d\n", (int)getpid() ); - /* fixme: add the hostname to the second line (FQDN or IP addr?) */ - - /* create a temporary file */ - if( uname( &utsbuf ) ) - nodename = "unknown"; - else - nodename = utsbuf.nodename; - + sprintf (pidstr, "%10d\n", (int)getpid() ); + /* fixme: add the hostname to the second line (FQDN or IP addr?) */ + + /* Create a temporary file. */ + if ( uname ( &utsbuf ) ) + nodename = "unknown"; + else + nodename = utsbuf.nodename; + #ifdef __riscos__ - { - char *iter = (char *) nodename; - for (; iter[0]; iter++) - if (iter[0] == '.') - iter[0] = '/'; - } + { + char *iter = (char *) nodename; + for (; iter[0]; iter++) + if (iter[0] == '.') + iter[0] = '/'; + } #endif /* __riscos__ */ - if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) { - dirpart = EXTSEP_S; - dirpartlen = 1; + if ( !(dirpart = strrchr ( file_to_lock, DIRSEP_C )) ) + { + dirpart = EXTSEP_S; + dirpartlen = 1; } - else { - dirpartlen = dirpart - file_to_lock; - dirpart = file_to_lock; + else + { + dirpartlen = dirpart - file_to_lock; + dirpart = file_to_lock; } #ifdef _REENTRANT /* fixme: aquire mutex on all_lockfiles */ #endif - h->next = all_lockfiles; - all_lockfiles = h; + h->next = all_lockfiles; + all_lockfiles = h; - h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); + h->tname = jnlib_xmalloc ( dirpartlen + 6+30+ strlen(nodename) + 11 ); + h->nodename_len = strlen (nodename); #ifndef __riscos__ - sprintf( h->tname, "%.*s/.#lk%p.%s.%d", - dirpartlen, dirpart, h, nodename, (int)getpid() ); + sprintf (h->tname, "%.*s/.#lk%p.", dirpartlen, dirpart, h ); + h->nodename_off = strlen (h->tname); + sprintf (h->tname+h->nodename_off, "%s.%d", nodename, (int)getpid ()); #else /* __riscos__ */ - sprintf( h->tname, "%.*s.lk%p/%s/%d", - dirpartlen, dirpart, h, nodename, (int)getpid() ); + sprintf (h->tname, "%.*s.lk%p/", dirpartlen, dirpart, h ); + h->nodename_off = strlen (h->tname); + sprintf (h->tname+h->nodename_off, "%s/%d", nodename, (int)getpid () ); #endif /* __riscos__ */ - do { - errno = 0; - fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL, - S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); - } while( fd == -1 && errno == EINTR ); - if( fd == -1 ) { - all_lockfiles = h->next; - log_error( "failed to create temporary file `%s': %s\n", - h->tname, strerror(errno)); - jnlib_free(h->tname); - jnlib_free(h); - return NULL; - } - if( write(fd, pidstr, 11 ) != 11 ) { - all_lockfiles = h->next; - #ifdef _REENTRANT - /* release mutex */ - #endif - log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); - close(fd); - unlink(h->tname); - jnlib_free(h->tname); - jnlib_free(h); - return NULL; - } - if( close(fd) ) { - all_lockfiles = h->next; - #ifdef _REENTRANT - /* release mutex */ - #endif - log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); - close(fd); - unlink(h->tname); - jnlib_free(h->tname); - jnlib_free(h); - return NULL; + do + { + errno = 0; + fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL, + S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR ); + } + while (fd == -1 && errno == EINTR); + + if ( fd == -1 ) + { + all_lockfiles = h->next; + log_error ( "failed to create temporary file `%s': %s\n", + h->tname, strerror(errno)); + jnlib_free(h->tname); + jnlib_free(h); + return NULL; } + if ( write (fd, pidstr, 11 ) != 11 ) + goto write_failed; + if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) ) + goto write_failed; + if ( write (fd, "\n", 1 ) != 1 ) + goto write_failed; + if ( close (fd) ) + goto write_failed; # ifdef _REENTRANT - /* release mutex */ + /* release mutex */ # endif #endif /* !HAVE_DOSISH_SYSTEM */ - h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 ); - strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); - return h; + h->lockname = jnlib_xmalloc ( strlen (file_to_lock) + 6 ); + strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); + return h; + write_failed: + all_lockfiles = h->next; +# ifdef _REENTRANT + /* fixme: release mutex */ +# endif + log_error ( "error writing to `%s': %s\n", h->tname, strerror(errno) ); + close(fd); + unlink(h->tname); + jnlib_free(h->tname); + jnlib_free(h); + return NULL; } void destroy_dotlock ( DOTLOCK h ) { -#if !defined (HAVE_DOSISH_SYSTEM) - if ( h ) - { - DOTLOCK hprev, htmp; - - /* First remove the handle from our global list of all locks. */ - for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next) - if (htmp == h) - { - if (hprev) - hprev->next = htmp->next; - else - all_lockfiles = htmp->next; - h->next = NULL; - break; - } - - /* Second destroy the lock. */ - if (!h->disable) +#ifndef HAVE_DOSISH_SYSTEM + if ( h ) + { + DOTLOCK hprev, htmp; + + /* First remove the handle from our global list of all locks. */ + for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next) + if (htmp == h) { - if (h->locked && h->lockname) - unlink (h->lockname); - if (h->tname) - unlink (h->tname); - jnlib_free (h->tname); - jnlib_free (h->lockname); + if (hprev) + hprev->next = htmp->next; + else + all_lockfiles = htmp->next; + h->next = NULL; + break; } - jnlib_free(h); - - } -#endif + + /* Second destroy the lock. */ + if (!h->disable) + { + if (h->locked && h->lockname) + unlink (h->lockname); + if (h->tname) + unlink (h->tname); + jnlib_free (h->tname); + jnlib_free (h->lockname); + } + jnlib_free(h); + } +#endif /*!HAVE_DOSISH_SYSTEM*/ } @@ -255,107 +263,120 @@ destroy_dotlock ( DOTLOCK h ) static int maybe_deadlock( DOTLOCK h ) { - DOTLOCK r; + DOTLOCK r; - for( r=all_lockfiles; r; r = r->next ) { - if( r != h && r->locked ) - return 1; + for ( r=all_lockfiles; r; r = r->next ) + { + if ( r != h && r->locked ) + return 1; } - return 0; + return 0; } /**************** - * Do a lock on H. A TIMEOUT of 0 returns immediately, - * -1 waits forever (hopefully not), other - * values are timeouts in milliseconds. - * Returns: 0 on success + * Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits + * forever (hopefully not), other values are reserved (should then be + * timeouts in milliseconds). Returns: 0 on success */ int make_dotlock( DOTLOCK h, long timeout ) { #ifdef HAVE_DOSISH_SYSTEM - return 0; + return 0; #else - int pid; - const char *maybe_dead=""; - int backoff=0; + int pid; + const char *maybe_dead=""; + int backoff=0; + int same_node; - if( h->disable ) { - return 0; - } + if ( h->disable ) + return 0; /* Locks are completely disabled. Return success. */ - if( h->locked ) { + if ( h->locked ) + { #ifndef __riscos__ - log_debug("oops, `%s' is already locked\n", h->lockname ); + log_debug("oops, `%s' is already locked\n", h->lockname ); #endif /* !__riscos__ */ - return 0; + return 0; } - for(;;) { + for(;;) + { #ifndef __riscos__ - if( !link(h->tname, h->lockname) ) { - /* fixme: better use stat to check the link count */ - h->locked = 1; - return 0; /* okay */ + if ( !link(h->tname, h->lockname) ) + { + /* fixme: better use stat to check the link count */ + h->locked = 1; + return 0; /* okay */ } - if( errno != EEXIST ) { - log_error( "lock not made: link() failed: %s\n", strerror(errno) ); - return -1; + if ( errno != EEXIST ) + { + log_error( "lock not made: link() failed: %s\n", strerror(errno) ); + return -1; } #else /* __riscos__ */ - if( !renamefile(h->tname, h->lockname) ) { - h->locked = 1; - return 0; /* okay */ + if ( !renamefile(h->tname, h->lockname) ) + { + h->locked = 1; + return 0; /* okay */ } - if( errno != EEXIST ) { - log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); - return -1; + if ( errno != EEXIST ) + { + log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); + return -1; } #endif /* __riscos__ */ - if( (pid = read_lockfile(h->lockname)) == -1 ) { - if( errno != ENOENT ) { - log_info("cannot read lockfile\n"); - return -1; + + if ( (pid = read_lockfile (h, &same_node)) == -1 ) + { + if ( errno != ENOENT ) + { + log_info ("cannot read lockfile\n"); + return -1; } - log_info( "lockfile disappeared\n"); - continue; + log_info( "lockfile disappeared\n"); + continue; } - else if( pid == getpid() ) { - log_info( "Oops: lock already held by us\n"); - h->locked = 1; - return 0; /* okay */ + else if ( pid == getpid() && same_node ) + { + log_info( "Oops: lock already held by us\n"); + h->locked = 1; + return 0; /* okay */ } - else if( kill(pid, 0) && errno == ESRCH ) { + else if ( same_node && kill (pid, 0) && errno == ESRCH ) + { #ifndef __riscos__ - maybe_dead = " - probably dead"; -#if 0 /* we should not do this without checking the permissions */ - /* and the hostname */ - log_info( "removing stale lockfile (created by %d)", pid ); -#endif + log_info ("removing stale lockfile (created by %d)", pid ); + unlink (h->lockname); + continue; #else /* __riscos__ */ - /* we are *pretty* sure that the other task is dead and therefore - we remove the other lock file */ - maybe_dead = " - probably dead - removing lock"; - unlink(h->lockname); + /* Under RISCOS we are *pretty* sure that the other task + is dead and therefore we remove the stale lock file. */ + maybe_dead = " - probably dead - removing lock"; + unlink(h->lockname); #endif /* __riscos__ */ } - if( timeout == -1 ) { - struct timeval tv; - log_info( "waiting for lock (held by %d%s) %s...\n", - pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); - - - /* can't use sleep, cause signals may be blocked */ - tv.tv_sec = 1 + backoff; - tv.tv_usec = 0; - select(0, NULL, NULL, NULL, &tv); - if( backoff < 10 ) - backoff++ ; + + if ( timeout == -1 ) + { + /* Wait until lock has been released. */ + struct timeval tv; + + log_info ("waiting for lock (held by %d%s) %s...\n", + pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); + + + /* We can't use sleep, cause signals may be blocked. */ + tv.tv_sec = 1 + backoff; + tv.tv_usec = 0; + select(0, NULL, NULL, NULL, &tv); + if ( backoff < 10 ) + backoff++ ; } - else - return -1; + else + return -1; } - /*not reached */ + /*NOTREACHED*/ #endif /* !HAVE_DOSISH_SYSTEM */ } @@ -368,92 +389,150 @@ int release_dotlock( DOTLOCK h ) { #ifdef HAVE_DOSISH_SYSTEM - return 0; + return 0; #else - int pid; + int pid, same_node; - /* To avoid atexit race conditions we first check whether there - are any locks left. It might happen that another atexit - handler tries to release the lock while the atexit handler of - this module already ran and thus H is undefined. */ - if(!all_lockfiles) - return 0; + /* To avoid atexit race conditions we first check whether there are + any locks left. It might happen that another atexit handler + tries to release the lock while the atexit handler of this module + already ran and thus H is undefined. */ + if (!all_lockfiles) + return 0; - if( h->disable ) { - return 0; - } + if ( h->disable ) + return 0; - if( !h->locked ) { - log_debug("oops, `%s' is not locked\n", h->lockname ); - return 0; + if ( !h->locked ) + { + log_debug("oops, `%s' is not locked\n", h->lockname ); + return 0; } - pid = read_lockfile( h->lockname ); - if( pid == -1 ) { - log_error( "release_dotlock: lockfile error\n"); - return -1; + pid = read_lockfile (h, &same_node); + if ( pid == -1 ) + { + log_error( "release_dotlock: lockfile error\n"); + return -1; } - if( pid != getpid() ) { - log_error( "release_dotlock: not our lock (pid=%d)\n", pid); - return -1; + if ( pid != getpid() || !same_node ) + { + log_error( "release_dotlock: not our lock (pid=%d)\n", pid); + return -1; } #ifndef __riscos__ - if( unlink( h->lockname ) ) { - log_error( "release_dotlock: error removing lockfile `%s'", - h->lockname); - return -1; + if ( unlink( h->lockname ) ) + { + log_error( "release_dotlock: error removing lockfile `%s'", + h->lockname); + return -1; } #else /* __riscos__ */ - if( renamefile(h->lockname, h->tname) ) { - log_error( "release_dotlock: error renaming lockfile `%s' to `%s'", - h->lockname, h->tname); - return -1; + if ( renamefile(h->lockname, h->tname) ) + { + log_error( "release_dotlock: error renaming lockfile `%s' to `%s'", + h->lockname, h->tname); + return -1; } #endif /* __riscos__ */ - /* fixme: check that the link count is now 1 */ - h->locked = 0; - return 0; + /* fixme: check that the link count is now 1 */ + h->locked = 0; + return 0; #endif /* !HAVE_DOSISH_SYSTEM */ } -/**************** - * Read the lock file and return the pid, returns -1 on error. +/* + Read the lock file and return the pid, returns -1 on error. True + will be stored at SAME_NODE if the lock file has been created on + the same node. */ static int -read_lockfile( const char *name ) +read_lockfile (DOTLOCK h, int *same_node ) { #ifdef HAVE_DOSISH_SYSTEM - return 0; + return 0; #else - int fd, pid; - char pidstr[16]; - - if( (fd = open(name, O_RDONLY)) == -1 ) { - int e = errno; - log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) ); - errno = e; - return -1; + char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node + name are usually shorter. */ + int fd, pid; + char *buffer, *p; + size_t expected_len; + int res, nread; + + *same_node = 0; + expected_len = 10 + 1 + h->nodename_len + 1; + if ( expected_len >= sizeof buffer_space) + buffer = jnlib_xmalloc (expected_len); + else + buffer = buffer_space; + + if ( (fd = open (h->lockname, O_RDONLY)) == -1 ) + { + int e = errno; + log_info ("error opening lockfile `%s': %s\n", + h->lockname, strerror(errno) ); + if (buffer != buffer_space) + jnlib_free (buffer); + errno = e; /* Need to return ERRNO here. */ + return -1; } - if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */ - log_debug("error reading lockfile `%s'", name ); - close(fd); - errno = 0; - return -1; + + p = buffer; + nread = 0; + do + { + res = read (fd, p, expected_len - nread); + if (res == -1 && errno == EINTR) + continue; + if (res < 0) + { + log_info ("error reading lockfile `%s'", h->lockname ); + close (fd); + if (buffer != buffer_space) + jnlib_free (buffer); + errno = 0; /* Do not return an inappropriate ERRNO. */ + return -1; + } + p += res; + nread += res; } - pidstr[10] = 0; /* terminate pid string */ - close(fd); - pid = atoi(pidstr); + while (res && nread != expected_len); + close(fd); + + if (nread < 11) + { + log_info ("invalid size of lockfile `%s'", h->lockname ); + if (buffer != buffer_space) + jnlib_free (buffer); + errno = 0; /* Do not return an inappropriate ERRNO. */ + return -1; + } + + if (buffer[10] != '\n' + || (buffer[10] = 0, pid = atoi (buffer)) == -1 #ifndef __riscos__ - if( !pid || pid == -1 ) { + || !pid #else /* __riscos__ */ - if( (!pid && riscos_getpid()) || pid == -1 ) { + || (!pid && riscos_getpid()) #endif /* __riscos__ */ - log_error("invalid pid %d in lockfile `%s'", pid, name ); - errno = 0; - return -1; + ) + { + log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname ); + if (buffer != buffer_space) + jnlib_free (buffer); + errno = 0; + return -1; } - return pid; + + if (nread == expected_len + && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len) + && buffer[11+h->nodename_len] == '\n') + *same_node = 1; + + if (buffer != buffer_space) + jnlib_free (buffer); + return pid; #endif } -- cgit v1.2.3 From 6c208fea3275e7d9244842811e8a5eefeb255e5f Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Jun 2006 09:42:08 +0000 Subject: A couple of fixes. gpg2's key generation does now work. --- TODO | 3 +++ g10/ChangeLog | 21 +++++++++++++++++++++ g10/card-util.c | 2 +- g10/keygen.c | 2 +- g10/mainproc.c | 19 ++++++++----------- g10/misc.c | 5 +---- g10/parse-packet.c | 22 +++++++++++++--------- g10/pkclist.c | 8 ++++---- g10/pubkey-enc.c | 2 +- g10/seskey.c | 5 ++--- scd/ChangeLog | 6 ++++++ scd/app-openpgp.c | 2 +- 12 files changed, 62 insertions(+), 35 deletions(-) diff --git a/TODO b/TODO index 0650361c6..672fab9a7 100644 --- a/TODO +++ b/TODO @@ -103,6 +103,9 @@ might want to have an agent context for each service request * sm/ ** check that we issue NO_SECKEY xxx if a -u key was not found +* jnlib/ +** provide jnlib_malloc and try to remove all jnlib_xmalloc. + * gpg/ ** issue a NO_SECKEY xxxx if a -u key was not found. ** Replace DIGEST_ALGO_SHA224 diff --git a/g10/ChangeLog b/g10/ChangeLog index 4a838257e..2fba9c488 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,24 @@ +2006-06-30 Werner Koch <wk@g10code.com> + + * misc.c (checksum_mpi): No need for nbits as they are alredy + included in the buffer. + +2006-06-29 Werner Koch <wk@g10code.com> + + * parse-packet.c (parse_signature, parse_key): Need store the + length of opaque data as number of bits. + * card-util.c (card_store_subkey): Ditto. + + * mainproc.c (print_pkenc_list, check_sig_and_print): Replaced + log_get_stream by calls to log_printf. This avoids the extra LFs + inserted by the logging function. They are a bit too smart + sometimes. + * pkclist.c (do_show_revocation_reason): Print final LF through + log_printf to avoid extra LFs. + * pubkey-enc.c (get_it): Ditto. + + * seskey.c (encode_md_value): Fix call to gcry. + 2006-06-27 Werner Koch <wk@g10code.com> Applied patches from 1.4.x (2006-05-22 to 2006-06-23) from David: diff --git a/g10/card-util.c b/g10/card-util.c index b5a036e54..b7da1ba98 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1271,7 +1271,7 @@ card_store_subkey (KBNODE node, int use) sk->skey[i] = NULL; } i = pubkey_get_npkey (sk->pubkey_algo); - sk->skey[i] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); sk->is_protected = 1; sk->protect.s2k.mode = 1002; s = info.serialno; diff --git a/g10/keygen.c b/g10/keygen.c index 7a6296974..ff4ce88b4 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -3701,7 +3701,7 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary, sk->skey[i] = NULL; } i = pubkey_get_npkey (sk->pubkey_algo); - sk->skey[i] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10); + sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); sk->is_protected = 1; sk->protect.s2k.mode = 1002; s = get_parameter_value (para, pSERIALNO); diff --git a/g10/mainproc.c b/g10/mainproc.c index 67ac784dc..ca5ea9ade 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -445,7 +445,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) nbits_from_pk( pk ), algstr, keystr_from_pk(pk), strtimestamp(pk->timestamp) ); p=get_user_id_native(list->kid); - fprintf(log_get_stream(),_(" \"%s\"\n"),p); + log_printf (_(" \"%s\"\n"),p); xfree(p); } else @@ -1527,7 +1527,7 @@ check_sig_and_print( CTX c, KBNODE node ) not going to even try to make two strings here :) */ log_info(_("Key available at: ") ); print_utf8_string( log_get_stream(), p, n ); - putc( '\n', log_get_stream() ); + log_printf ("\n"); if(opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) @@ -1667,9 +1667,9 @@ check_sig_and_print( CTX c, KBNODE node ) xfree(p); if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY) - fprintf(log_get_stream()," [%s]\n",trust_value_to_string(valid)); + log_printf (" [%s]\n",trust_value_to_string(valid)); else - fputs("\n", log_get_stream() ); + log_printf ("\n"); count++; } if( !count ) { /* just in case that we have no valid textual @@ -1712,11 +1712,8 @@ check_sig_and_print( CTX c, KBNODE node ) else log_info(_("Good signature from \"%s\""),p); if (opt.trust_model!=TM_ALWAYS && un) - { - putc(' ', log_get_stream() ); - fputs(_("[uncertain]"), log_get_stream() ); - } - fputs("\n", log_get_stream() ); + log_printf (" %s",_("[uncertain]") ); + log_printf ("\n"); } /* If we have a good signature and already printed @@ -1760,10 +1757,10 @@ check_sig_and_print( CTX c, KBNODE node ) valid=trust_value_to_string(get_validity(pk, un->pkt-> pkt.user_id)); - fprintf(log_get_stream()," [%s]\n",valid); + log_printf (" [%s]\n",valid); } else - fputs("\n", log_get_stream() ); + log_printf ("\n"); } } release_kbnode( keyblock ); diff --git a/g10/misc.c b/g10/misc.c index de0a029a4..33b97792c 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -297,7 +297,6 @@ checksum_mpi (gcry_mpi_t a) u16 csum; byte *buffer; unsigned int nbytes; - unsigned int nbits; if ( gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a) ) BUG (); @@ -308,9 +307,7 @@ checksum_mpi (gcry_mpi_t a) gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes)); if ( gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a) ) BUG (); - nbits = gcry_mpi_get_nbits (a); - csum = checksum_u16 (nbits); - csum += checksum (buffer, nbytes); + csum = checksum (buffer, nbytes); xfree (buffer); return csum; } diff --git a/g10/parse-packet.c b/g10/parse-packet.c index d792bfff9..d9a87f108 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1490,9 +1490,10 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, if( list_mode ) fprintf (listfp, "\tunknown algorithm %d\n", sig->pubkey_algo ); unknown_pubkey_warning( sig->pubkey_algo ); - /* we store the plain material in data[0], so that we are able + /* We store the plain material in data[0], so that we are able * to write it back with build_packet() */ - sig->data[0]= mpi_set_opaque(NULL, read_rest(inp, pktlen, 0), pktlen ); + sig->data[0]= gcry_mpi_set_opaque (NULL, read_rest(inp, pktlen, 0), + pktlen*8 ); pktlen = 0; } else { @@ -1715,8 +1716,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, size_t snlen = 0; if( !npkey ) { - sk->skey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen, 0), pktlen ); + sk->skey[0] = gcry_mpi_set_opaque (NULL, read_rest(inp, pktlen, 0), + pktlen*8 ); pktlen = 0; goto leave; } @@ -1894,15 +1895,17 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, if( sk->protect.s2k.mode == 1001 || sk->protect.s2k.mode == 1002 ) { /* better set some dummy stuff here */ - sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup("dummydata"), 10); + sk->skey[npkey] = gcry_mpi_set_opaque(NULL, + xstrdup("dummydata"), 10*8); pktlen = 0; } else if( is_v4 && sk->is_protected ) { /* ugly; the length is encrypted too, so we read all * stuff up to the end of the packet into the first * skey element */ - sk->skey[npkey] = mpi_set_opaque(NULL, - read_rest(inp, pktlen, 0),pktlen); + sk->skey[npkey] = gcry_mpi_set_opaque (NULL, + read_rest(inp, pktlen, 0), + pktlen*8); pktlen = 0; if( list_mode ) { fprintf (listfp, "\tencrypted stuff follows\n"); @@ -1942,8 +1945,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, PKT_public_key *pk = pkt->pkt.public_key; if( !npkey ) { - pk->pkey[0] = mpi_set_opaque( NULL, - read_rest(inp, pktlen, 0), pktlen ); + pk->pkey[0] = gcry_mpi_set_opaque ( NULL, + read_rest(inp, pktlen, 0), + pktlen*8 ); pktlen = 0; goto leave; } diff --git a/g10/pkclist.c b/g10/pkclist.c index 4516f6769..d3cda144f 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -76,7 +76,7 @@ do_show_revocation_reason( PKT_signature *sig ) fputs( text, log_get_stream() ); else fprintf( log_get_stream(), "code=%02x", *p ); - putc( '\n', log_get_stream() ); + log_printf ("\n"); n--; p++; pp = NULL; do { @@ -88,9 +88,9 @@ do_show_revocation_reason( PKT_signature *sig ) if( n ) { pp = memchr( p, '\n', n ); nn = pp? pp - p : n; - log_info( _("revocation comment: ") ); - print_string( log_get_stream(), p, nn, 0 ); - putc( '\n', log_get_stream() ); + log_info ( _("revocation comment: ") ); + print_string ( log_get_stream(), p, nn, 0 ); + log_printf ("\n"); p += nn; n -= nn; } } while( pp ); diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index dc0124bd4..47aadc9a7 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -308,7 +308,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) if ( pk && pk->is_revoked ) { log_info( _("NOTE: key has been revoked") ); - putc( '\n', log_get_stream() ); + log_printf ("\n"); show_revocation_reason( pk, 1 ); } diff --git a/g10/seskey.c b/g10/seskey.c index a31cbb15e..2ef00869f 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -220,8 +220,7 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk, { /* It's a DSA signature, so find out the size of q. */ - unsigned int qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]); - size_t n; + size_t qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]); /* Make sure it is a multiple of 8 bits. */ @@ -259,7 +258,7 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk, } if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), n, &n)) + gcry_md_read (md, hash_algo), qbytes, &qbytes)) BUG(); } else diff --git a/scd/ChangeLog b/scd/ChangeLog index fd2ba5418..ba2ede72c 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,9 @@ +2006-06-28 Werner Koch <wk@g10code.com> + + * app-openpgp.c (do_writekey): Fixed computation of memmove + length. This led to garbled keys if E was larger than one byte. + Thanks to Achim Pietig for hinting at the garbled E. + 2006-06-09 Marcus Brinkmann <marcus@g10code.de> * Makefile.am (scdaemon_LDADD): Add $(NETLIBS). diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 842881f3a..47ff8abc2 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1828,7 +1828,7 @@ do_writekey (app_t app, ctrl_t ctrl, if (rsa_e_len < 4) { /* Right justify E. */ - memmove (tp+4-rsa_e_len, tp, 4-rsa_e_len); + memmove (tp+4-rsa_e_len, tp, rsa_e_len); memset (tp, 0, 4-rsa_e_len); } tp += 4; -- cgit v1.2.3 From 640d5a8c53289f396ae018a4c36e2e8894261329 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 30 Jun 2006 13:19:49 +0000 Subject: Added keyserver directory from trunk --- ChangeLog | 7 + Makefile.am | 5 +- configure.ac | 15 + keyserver/ChangeLog | 1067 ++++++++++++++++++++ keyserver/Makefile.am | 53 + keyserver/curl-shim.c | 324 ++++++ keyserver/curl-shim.h | 92 ++ keyserver/gpgkeys_curl.c | 369 +++++++ keyserver/gpgkeys_finger.c | 534 ++++++++++ keyserver/gpgkeys_hkp.c | 833 +++++++++++++++ keyserver/gpgkeys_ldap.c | 2350 +++++++++++++++++++++++++++++++++++++++++++ keyserver/gpgkeys_mailto.in | 225 +++++ keyserver/gpgkeys_test.in | 99 ++ keyserver/ksutil.c | 540 ++++++++++ keyserver/ksutil.h | 130 +++ m4/ChangeLog | 5 + m4/Makefile.am | 2 + m4/ldap.m4 | 97 ++ 18 files changed, 6746 insertions(+), 1 deletion(-) create mode 100644 keyserver/ChangeLog create mode 100644 keyserver/Makefile.am create mode 100644 keyserver/curl-shim.c create mode 100644 keyserver/curl-shim.h create mode 100644 keyserver/gpgkeys_curl.c create mode 100644 keyserver/gpgkeys_finger.c create mode 100644 keyserver/gpgkeys_hkp.c create mode 100644 keyserver/gpgkeys_ldap.c create mode 100755 keyserver/gpgkeys_mailto.in create mode 100755 keyserver/gpgkeys_test.in create mode 100644 keyserver/ksutil.c create mode 100644 keyserver/ksutil.h create mode 100644 m4/ldap.m4 diff --git a/ChangeLog b/ChangeLog index 745a6a198..eeb91bc0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-06-30 Werner Koch <wk@g10code.com> + + * keyserver/: New. Taken from 1.4.4 + * Makefile.am (SUBDIRS): Include keyserver/. + * configure.ac: Include keyserver/. + (FAKE_CURL, GPGKEYS_CURL): New. + 2006-06-20 Werner Koch <wk@g10code.com> Released 1.9.21. diff --git a/Makefile.am b/Makefile.am index 0c5fbe4c3..6f5f165b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,8 +35,11 @@ endif if BUILD_GPG gpg = g10 +# fixme: Noy yet ready for a build +keyserver = else gpg = +keyserver = endif if BUILD_GPGSM sm = sm @@ -61,7 +64,7 @@ tests = tests endif SUBDIRS = m4 intl gl jnlib common ${kbx} \ - ${gpg} ${sm} ${agent} ${scd} tools po doc ${tests} + ${gpg} ${keyserver} ${sm} ${agent} ${scd} tools po doc ${tests} dist-hook: @set -e; \ diff --git a/configure.ac b/configure.ac index 3f536e472..03d8809b9 100644 --- a/configure.ac +++ b/configure.ac @@ -716,6 +716,20 @@ fi AC_SUBST(GPGKEYS_LDAP) AC_SUBST(LDAPLIBS) + +# Check for curl. We fake the curl API if libcurl isn't installed. + +# fixme: need to add this +#LIBCURL_CHECK_CONFIG([yes],,,[fake_curl=yes]) +#AM_CONDITIONAL(FAKE_CURL,test x"$fake_curl" = xyes) +AM_CONDITIONAL(FAKE_CURL,1) + +# Generic, for us, means curl + +if test x"$try_generic" = xyes ; then + AC_SUBST(GPGKEYS_CURL,"gpgkeys_curl$EXEEXT") +fi + dnl This isn't necessarily sendmail itself, but anything that gives a dnl sendmail-ish interface to the outside world. That includes qmail, dnl postfix, etc. Basically, anything that can handle "sendmail -t". @@ -1231,6 +1245,7 @@ jnlib/Makefile common/Makefile kbx/Makefile g10/Makefile +keyserver/Makefile sm/Makefile agent/Makefile scd/Makefile diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog new file mode 100644 index 000000000..c171f6a3a --- /dev/null +++ b/keyserver/ChangeLog @@ -0,0 +1,1067 @@ +2006-04-26 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_http.c, gpgkeys_oldhkp.c: Removed. + + * Makefile.am: Don't build gpgkeys_http or gpgkeys_(old)hkp any + longer as this is done via curl or fake-curl. + + * ksutil.h, ksutil.c, gpgkeys_hkp.c, gpgkeys_curl.c: Minor + #include tweaks as FAKE_CURL is no longer meaningful. + +2006-04-10 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (ldap_quote, get_name, search_key): LDAP-quote + directly into place rather than mallocing temporary buffers. + + * gpgkeys_ldap.c (get_name): Build strings with strcat rather than + using sprintf which is harder to read and modify. + + * ksutil.h, ksutil.c (classify_ks_search): Add + KS_SEARCH_KEYID_SHORT and KS_SEARCH_KEYID_LONG to search for a key + ID. + + * gpgkeys_ldap.c (search_key): Use it here to flip from pgpUserID + searches to pgpKeyID or pgpCertID. + +2006-03-27 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c: #define LDAP_DEPRECATED for newer OpenLDAPs so + they use the regular old API that is compatible with other LDAP + libraries. + +2006-03-03 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main): Fix build problem with non-OpenLDAP LDAP + libraries that have TLS. + +2006-02-23 David Shaw <dshaw@jabberwocky.com> + + * ksutil.c (init_ks_options): Default include-revoked and + include-subkeys to on, as gpg isn't doing this any longer. + +2006-02-22 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (get_name): A GETNAME query turns exact=on to cut + down on odd matches. + +2006-02-21 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (make_one_attr, build_attrs, send_key): Don't + allow duplicate attributes as OpenLDAP is now enforcing this. + + * gpgkeys_ldap.c (main): Add binddn and bindpw so users can pass + credentials to a remote LDAP server. + + * curl-shim.h, curl-shim.c (curl_easy_init, curl_easy_setopt, + curl_easy_perform): Mingw has 'stderr' as a macro? + + * curl-shim.h, curl-shim.c (curl_easy_init, curl_easy_setopt, + curl_easy_perform): Add CURLOPT_VERBOSE and CURLOPT_STDERR for + easier debugging. + +2006-01-16 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (send_key): Do not escape the '=' in the HTTP POST + when uploading a key. + +2005-12-23 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, ksutil.c (parse_ks_options): New keyserver command + "getname". + + * gpgkeys_hkp.c (main, get_name), gpgkeys_ldap.c (main, get_name): + Use it here to do direct name (rather than key ID) fetches. + +2005-12-19 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, ksutil.c (curl_armor_writer, curl_writer, + curl_writer_finalize): New functionality to handle binary format + keys by armoring them for input to GPG. + + * gpgkeys_curl.c (get_key), gpgkeys_hkp.c (get_key): Call it here. + +2005-12-07 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_finger.c (get_key), gpgkeys_curl.c (get_key): Better + language for the key-not-found error. + + * ksutil.c (curl_err_to_gpg_err): Add CURLE_OK and + CURLE_COULDNT_CONNECT. + + * gpgkeys_curl.c (get_key): Give key-not-found error if no data is + found (or file itself is not found) during a fetch. + +2005-12-06 David Shaw <dshaw@jabberwocky.com> + + * curl-shim.c (curl_easy_perform): Fix build warning (code before + declaration). + +2005-11-02 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (search_key): Fix warning with typecast (though + curl should really have defined that char * as const). + +2005-08-25 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, ksutil.c (parse_ks_options): Remove exact-name and + exact-email. + (classify_ks_search): Mimic the gpg search modes instead with *, + =, <, and @. + + * gpgkeys_ldap.c (search_key), gpgkeys_hkp.c (search_key): Call + them here. Suggested by Jason Harris. + +2005-08-18 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, ksutil.c (parse_ks_options): New keyserver-option + exact-name. The last of exact-name and exact-email overrides the + earlier. + + * gpgkeys_ldap.c (search_key), gpgkeys_hkp.c (search_key): Use it + here to do a name-only search. + + * gpgkeys_ldap.c (ldap_quote): \-quote a string for LDAP. + + * gpgkeys_ldap.c (search_key): Use it here to escape reserved + characters in searches. + +2005-08-17 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, ksutil.c (parse_ks_options): New keyserver-option + exact-email. + + * gpgkeys_ldap.c (search_key), gpgkeys_hkp.c (search_key): Use it + here to do an email-only search. + +2005-08-08 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Include LDAP_CPPFLAGS when building LDAP. + +2005-08-03 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (main), gpgkeys_curl.c (main), curl-shim.h: Show + version of curl (or curl-shim) when debug is set. + +2005-07-20 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_curl.c (get_key, main): Don't try and be smart about + what protocols we handle. Directly pass them to curl or fake-curl + and see if an error comes back. + + * curl-shim.h, curl-shim.c (handle_error), ksutil.c + (curl_err_to_gpg_err): Add support for CURLE_UNSUPPORTED_PROTOCOL + in fake curl. + + * Makefile.am: Don't need -DFAKE_CURL any longer since it's in + config.h. + +2005-06-23 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_mailto.in, gpgkeys_test.in: Use @VERSION@ so version + string stays up to date. + + * gpgkeys_http.c: Don't need to define HTTP_PROXY_ENV here since + it's in ksutil.h. + + * gpgkeys_curl.c (get_key, main), gpgkeys_hkp.c (main): Pass AUTH + values to curl or curl-shim. + + * curl-shim.c (curl_easy_perform), gpgkeys_curl.c (main), + gpgkeys_hkp.c (main): Use curl-style proxy semantics. + + * curl-shim.h, curl-shim.c (curl_easy_setopt, curl_easy_perform): + Add CURLOPT_USERPWD option for HTTP auth. + + * gpgkeys_http.c (get_key), gpgkeys_oldhkp (send_key, get_key, + search_key): No longer need to pass a proxyauth. + + * gpgkeys_http.c (get_key): Pass auth outside of the URL. + +2005-06-21 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_http.c (get_key), gpgkeys_oldhkp.c (send_key, get_key, + search_key): Fix http_open/http_open_document calls to pass NULL + for auth and proxyauth since these programs pass them in the URL. + +2005-06-20 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (append_path, send_key, get_key, search_key, + main), gpgkeys_oldhkp.c (main): Properly handle double slashes in + paths. + +2005-06-05 David Shaw <dshaw@jabberwocky.com> + + * ksutil.c (init_ks_options, parse_ks_options): Provide a default + "/" path unless overridden by the config. Allow config to specify + items multiple times and take the last specified item. + +2005-06-04 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c, gpgkeys_oldhkp.c: Add support for HKP servers + that aren't at the root path. Suggested by Jack Bates. + +2005-06-01 David Shaw <dshaw@jabberwocky.com> + + * ksutil.c [HAVE_DOSISH_SYSTEM]: Fix warnings on mingw32. Noted + by Joe Vender. + +2005-05-04 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, ksutil.c: #ifdef so we can build without libcurl or + fake-curl. + +2005-05-03 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_http.c: Need GET defined. + +2005-05-01 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c, gpgkeys_oldhkp.c, ksutil.h: Some minor cleanup + and comments as to the size of MAX_LINE and MAX_URL. + +2005-04-16 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c: New hkp handler that uses curl or curl-shim. + + * Makefile.am: Build new gpgkeys_hkp. + + * curl-shim.c (curl_easy_perform): Cleanup. + + * ksutil.h, ksutil.c (curl_writer), gpgkeys_curl.c (get_key): Pass + a context to curl_writer so we can support multiple fetches in a + single session. + + * curl-shim.h, curl-shim.c (handle_error, curl_easy_setopt, + curl_easy_perform): Add POST functionality to the curl shim. + + * curl-shim.h, curl-shim.c (curl_escape, curl_free): Emulate + curl_escape and curl_free. + + * gpgkeys_curl.c (main): If the http-proxy option is given without + any arguments, try to get the proxy from the environment. + + * ksutil.h, ksutil.c (curl_err_to_gpg_err, curl_writer): Copy from + gpgkeys_curl.c. + + * gpgkeys_oldhkp.c: Copy from gpgkeys_hkp.c. + +2005-03-22 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c, ksutil.h, ksutil.c (print_nocr): Moved from + gpgkeys_ldap.c. Print a string, but strip out any CRs. + + * gpgkeys_finger.c (get_key), gpgkeys_hkp.c (get_key), + gpgkeys_http.c (get_key): Use it here when outputting key material + to canonicalize line endings. + +2005-03-19 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main): Fix three wrong calls to fail_all(). + Noted by Stefan Bellon. + +2005-03-17 David Shaw <dshaw@jabberwocky.com> + + * ksutil.c (parse_ks_options): Handle verbose=nnn. + + * Makefile.am: Calculate GNUPG_LIBEXECDIR directly. Do not + redefine $libexecdir. + + * gpgkeys_curl.c, gpgkeys_finger.c, gpgkeys_ldap.c: Start using + parse_ks_options and remove a lot of common code. + + * ksutil.h, ksutil.c (parse_ks_options): Parse OPAQUE, and default + debug with no arguments to 1. + +2005-03-16 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c: Include lber.h if configure determines we need + it. + + * ksutil.h, ksutil.c (ks_action_to_string): New. + (free_ks_options): Only free if options exist. + + * ksutil.h, ksutil.c (init_ks_options, free_ks_options, + parse_ks_options): Pull a lot of duplicated code into a single + options parser for all keyserver helpers. + +2005-02-11 David Shaw <dshaw@jabberwocky.com> + + * curl-shim.c (curl_easy_perform): Fix compile warning. + + * curl-shim.h, gpgkeys_curl.c (main), gpgkeys_ldap.c (main): Add + ca-cert-file option, to pass in the SSL cert. + + * curl-shim.h, curl-shim.c: New. This is code to fake the curl + API in terms of the current HTTP iobuf API. + + * gpgkeys_curl.c [FAKE_CURL], Makefile.am: If FAKE_CURL is set, + link with the iobuf code rather than libcurl. + +2005-02-05 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_finger.c (main), gpgkeys_hkp.c (main): Fix --version + output. + + * gpgkeys_curl.c (main): Make sure the curl handle is cleaned up + on failure. + +2005-02-01 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (get_key), gpgkeys_http.c (get_key): Fix missing + http_close() calls. Noted by Phil Pennock. + + * ksutil.h: Up the default timeout to two minutes. + +2005-01-24 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (print_nocr): New. + (get_key): Call it here to canonicalize line endings. + + * gpgkeys_curl.c (writer): Discard everything outside the BEGIN + and END lines when retrieving keys. Canonicalize line endings. + (main): Accept FTPS. + +2005-01-21 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main): Add "check-cert" option to disable SSL + certificate checking (which is on by default). + + * gpgkeys_curl.c (main): Add "debug" option to match the LDAP + helper. Add "check-cert" option to disable SSL certificate + checking (which is on by default). + +2005-01-18 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_curl.c: Fix typo. + +2005-01-18 Werner Koch <wk@g10code.com> + + * gpgkeys_curl.c: s/MAX_PATH/URLMAX_PATH/g to avoid a clash with + the W32 defined macro. Removed unneeded initialization of static + variables. + * gpgkeys_http.c: Ditto. + * ksutil.h: s/MAX_PATH/URLMAX_PATH/. + +2005-01-17 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_curl.c (main): Only allow specified protocols to use the + curl handler. + + * Makefile.am: Use LIBCURL_CPPFLAGS instead of LIBCURL_INCLUDES. + +2005-01-13 David Shaw <dshaw@jabberwocky.com> + + * ksutil.h, gpgkeys_curl.c, gpgkeys_hkp.c, gpgkeys_ldap.c, + gpgkeys_finger.c, gpgkeys_http.c: Part 2 of the cleanup. Move all + the various defines to ksutil.h. + + * gpgkeys_finger.c, gpgkeys_hkp.c, gpgkeys_http.c, gpgkeys_ldap.c: + Part 1 of a minor cleanup to use #defines instead of hard-coded + sizes. + + * gpgkeys_finger.c (connect_server): Use INADDR_NONE instead of + SOCKET_ERROR. Noted by Timo. + +2005-01-09 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_curl.c (get_key): Newer versions of libcurl don't define + TRUE. + +2004-12-24 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_curl.c (main): Use new defines for opting out of certain + transfer protocols. Allow setting HTTP proxy via "http-proxy=foo" + option (there is natural support in libcurl for the http_proxy + environment variable). + + * Makefile.am: Remove the conditional since this is all handled in + autoconf now. + +2004-12-22 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_curl.c (main): New "follow-redirects" option. Takes an + optional numeric value for the maximum number of redirects to + allow. Defaults to 5. + + * gpgkeys_curl.c (main), gpgkeys_finger.c (main), gpgkeys_hkp.c + (main), gpgkeys_http.c (main), gpgkeys_ldap.c (main): Make sure + that a "timeout" option passed with no arguments is properly + handled. + + * gpgkeys_curl.c (get_key, writer): New function to wrap around + fwrite to avoid DLL access problem on win32. + + * gpgkeys_http.c (main, get_key): Properly pass authentication + info through to the http library. + + * Makefile.am: Build gpgkeys_http or gpgkeys_curl as needed. + + * gpgkeys_curl.c (main, get_key): Minor tweaks to work with either + FTP or HTTP. + + * gpgkeys_ftp.c: renamed to gpgkeys_curl.c. + + * gpgkeys_ftp.c (main, get_key): Use auth data as passed by gpg. + Use CURLOPT_FILE instead of CURLOPT_WRITEDATA (same option, but + backwards compatible). + +2004-12-21 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ftp.c: New. + + * Makefile.am: Build it if requested. + +2004-12-14 Werner Koch <wk@g10code.com> + + * Makefile.am (install-exec-hook, uninstall-hook): Removed. For + Windows reasons we can't use the symlink trick. + +2004-12-03 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: The harmless "ignored error" on gpgkeys_ldap + install on top of an existing install is bound to confuse people. + Use ln -s -f to force the overwrite. + +2004-10-28 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_finger.c [_WIN32] (connect_server): Fix typo. + +2004-10-28 Werner Koch <wk@g10code.com> + + * Makefile.am (other_libs): New. Also include LIBICONV. Noted by + Tim Mooney. + +2004-10-28 Werner Koch <wk@g10code.com> + + * Makefile.am (other_libs): + +2004-10-18 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (send_key, get_key, search_key): Use "hkp" instead + of "x-hkp" so it can be used as a SRV tag. + +2004-10-16 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_finger.c [_WIN32] (connect_server): Fix typo. + +2004-10-15 Werner Koch <wk@g10code.com> + + * gpgkeys_ldap.c (main, show_help): Kludge to implement standard + GNU options. Factored help printing out. + * gpgkeys_finger.c (main, show_help): Ditto. + * gpgkeys_hkp.c (main, show_help): Ditto. + * gpgkeys_http.c (main, show_help): Ditto. + * gpgkeys_test.in, gpgkeys_mailto.in: Implement --version and --help. + + * Makefile.am: Add ksutil.h. + +2004-10-14 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_finger.c (main): We do not support relay fingering + (i.e. "finger://relayhost/user@example.com"), but finger URLs are + occasionally miswritten that way. Give an error in this case. + +2004-10-14 Werner Koch <wk@g10code.com> + + * gpgkeys_finger.c (get_key): s/unsigned char/byte/ due + to a strange typedef for RISC OS. Noted by Stefan. + +2004-10-13 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main), gpgkeys_hkp.c (main), gpgkeys_http.c + (main), gpgkeys_finger.c (main): Call timeout functions before + performing an action that could block for a long time. + + * ksutil.h, ksutil.c: New. Right now just contains timeout + functions. + +2004-10-11 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_finger.c, gpgkeys_hkp.c, gpgkeys_http.c, gpgkeys_ldap.c: + Fix a few occurances of "filename" to `filename'. + +2004-10-11 Werner Koch <wk@g10code.com> + + * gpgkeys_finger.c: New. + +2004-08-27 Stefan Bellon <sbellon@sbellon.de> + + * gpgkeys_hkp.c (search_key): Fix the prior faulty fix by + introducing a cast but leaving skey unsigned. + + * gpgkeys_hkp.c (search_key): Change type of variable skey from + unsigned char* to char* to fix type incompatibility. + +2004-08-23 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (get_key, search_key), gpgkeys_hkp.c (get_key, + search_key), gpgkeys_http.c (get_key): Do not give informational + logs since this is now done inside gpg. + + * gpgkeys_hkp.c (dehtmlize): Understand the quote character + (i.e. "&quot;") in HTML responses. + (search_key): Search key must be unsigned for url encoder to work + properly for 8-bit values. + + * gpgkeys_ldap.c (get_key): Factor out informational display into + new function build_info(). + + * gpgkeys_ldap.c (build_attrs): Properly terminate user ID strings + that got shrunk due to encoding. + +2004-08-22 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (find_basekeyspacedn): Use LDAP_SCOPE_BASE along + with a full DN rather than LDAP_SCOPE_ONELEVEL plus a filter to + find the pgpServerInfo object. Some LDAP setups don't like the + search. + (main): Stop binding to the server since it seems no server really + requires it, and some require it not be there. + +2004-07-29 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main): Add "debug" option. This is only really + useful with OpenLDAP, but it's practically vital to debug SSL and + TLS setups. Add "basedn" option. This allows users to override + the autodetection for base DN. SSL overrides TLS, so TLS will not + be started on SSL connections (starting an already started car). + +2004-07-28 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (build_attrs): Add "pgpKeySize" and "pgpSubKeyID" + attributes so we can do subkey searches. + + * gpgkeys_ldap.c (main): Under certain error conditions, we might + try and unbind twice. Don't. + + * gpgkeys_ldap.c (join_two_modlists): New. + (send_key): Use new function so we can try a modify operation + first, and fail over to an add if that fails. Add cannot cope + with the NULLs at the head of the modify request, so we jump into + the list in the middle. + +2004-07-27 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main): Don't try and error out before making a + ldaps connection to the NAI keyserver since we cannot tell if it + is a NAI keyserver until we connect. Fail if we cannot find a + base keyspace DN. Fix a false success message for TLS being + enabled. + +2004-07-20 Werner Koch <wk@gnupg.org> + + * gpgkeys_ldap.c [_WIN32]: Include Windows specific header files. + Suggested by Brian Gladman. + +2004-05-26 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_http.c: General polish and removal of leftover stuff + from gpgkeys_hkp.c. + +2004-05-21 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_http.c (get_key): Cosmetic fix - make sure that URLs + with no path use a path of "/". + + * gpgkeys_ldap.c (ldap2epochtime): We can always rely on timegm() + being available now, since it's a replacement function. + +2004-05-20 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_http.c: New program to do a simple HTTP file fetch using + the keyserver interface. + + * Makefile.am: Build it. + +2004-02-28 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Don't split LDADD across two lines since some make + programs can't handle blank lines after a \ continuation. Noted + by Christoph Moench-Tegeder. + +2004-02-25 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (send_key): List pgpCertID as one of the deleted + attributes. This guarantees that if something goes wrong, we + won't be able to complete the transaction, thus leaving any key + already existing on the server intact. + +2004-02-23 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (delete_one_attr): Removed. + (make_one_attr): Delete functionality added. Optional deduping + functionality added (currently only used for pgpSignerID). + (build_attrs): Translate sig entries into pgpSignerID. Properly + build the timestamp for pgpKeyCreateTime and pgpKeyExpireTime. + +2004-02-22 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (delete_one_attr): New function to replace + attributes with NULL (a "delete" that works even for nonexistant + attributes). + (send_key): Use it here to remove attributes so a modify operation + starts with a clean playing field. Bias sends to modify before + add, since (I suspect) people update their existing keys more + often than they make and send new keys to the server. + +2004-02-21 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (epoch2ldaptime): New. Converse of + ldap2epochtime. + (make_one_attr): New. Build a modification list in memory to send + to the LDAP server. + (build_attrs): New. Parse INFO lines sent over by gpg. + (free_mod_values): New. Unwinds a modification list. + (send_key_keyserver): Renamed from old send_key(). + (send_key): New function to send a key to a LDAP server. + (main): Use send_key() for real LDAP servers, send_key_keyserver() + otherwise. + +2004-02-20 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c: Replacement prototypes for setenv and unsetenv. + (search_key): Catch a SIZELIMIT_EXCEEDED error and show the user + whatever the server did give us. + (find_basekeyspacedn): There is no guarantee that namingContexts + will be readable. + + * Makefile.am: Link gpgkeys_ldap with libutil.a to get the + replacement functions (and eventually translations, etc). + +2004-02-19 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (ldap2epochtime): LDAP timestamps are UTC, so do + not correct for timezones. + (main): Find the basekeyspacedn before we try to start TLS, so we + can give a better error message when a user tries to use TLS with + a LDAP keyserver. + + * Makefile.am: Add automake conditionals to symlink gpgkeys_ldaps + to gpgkeys_ldap when needed. + + * gpgkeys_ldap.c (main): Add support for LDAPS and TLS + connections. These are only useful and usable when talking to + real LDAP keyservers. Add new "tls" option to tune TLS use from + off, to try quietly, to try loudly, or to require TLS. + + * gpgkeys_ldap.c (find_basekeyspacedn): New function to figure out + what kind of LDAP server we're talking to (either real LDAP or the + LDAP keyserver), and return the baseKeySpaceDN to find keys under. + (main): Call it from here, and remove the old code that only + handled the LDAP keyserver. + +2004-02-18 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (ldap_to_gpg_err): Make sure that + LDAP_OPT_ERROR_NUMBER is defined before we use it. + + * gpgkeys_mailto.in: Fix VERSION number. + +2004-01-13 Werner Koch <wk@gnupg.org> + + * gpgkeys_hkp.c (send_key): Add a content type. + +2004-01-11 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (search_key): Catch a mangled input file (useful + if something other than GnuPG is calling the program). + (main): Avoid possible pre-string write. Noted by Christian + Biere. + + * gpgkeys_ldap.c (main): Avoid possible pre-string write. + +2003-12-28 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (send_key, get_key, main): Work with new HTTP code + that passes the proxy in from the outside. If the command file + sends a proxy, use it. If it sends "http-proxy" with no + arguments, use $http_proxy from the environment. Suggested by + Christian Biere. + +2003-12-28 Stefan Bellon <sbellon@sbellon.de> + + * gpgkeys_hkp.c, gpgkeys_ldap.c [__riscos__]: Removal of + unnecessary #ifdef __riscos__ sections. + +2003-11-27 Werner Koch <wk@gnupg.org> + + * gpgkeys_hkp.c (get_key): Fixed invalid use of fprintf without + format string. + +2003-10-25 Werner Koch <wk@gnupg.org> + + * Makefile.am (gpgkeys_hkp_LDADD): Replaced INTLLIBS by LIBINTL. + +2003-07-10 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Use W32LIBS where appropriate. + +2003-05-30 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c, gpgkeys_ldap.c: #include <getopt.h> if it is + available. Also include extern references for optarg and optind + since there is no guarantee that any header file will include + them. Standards? We don't need no stinkin' standards. + + * Makefile.am: Use @GETOPT@ to pull in libiberty on those + platforms that need it. + +2003-04-08 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (dehtmlize, parse_hkp_index): Fix memory + corruption bug on some platforms. + +2003-03-11 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (get_key): Properly handle CRLF line endings in + the armored key. + (main): Accept "try-dns-srv" option. + + * Makefile.am: Use @CAPLIBS@ to link in -lcap if we are using + capabilities. Use @SRVLIBS@ to link in the resolver if we are + using DNS SRV. + +2003-02-11 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Use a local copy of libexecdir along with @PACKAGE@ + so it can be easily overridden at make time. + +2003-01-29 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_mailto.in: Fix regexp to work properly if the "keyid" is + not a keyid, but rather a text string from the user ID. + +2003-01-06 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (get_key): Use options=mr when getting a key so + keyserver doesn't attach the HTML header which we will just have + to discard. + +2002-11-17 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (main), gpgkeys_hkp.c (main): Use new keyserver + protocol version. + +2002-11-14 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (get_key): The deduping code requires + "pgpcertid", but that was not available when running without + verbose on. Noted by Stefan. + +2002-11-10 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (get_key): Fix typo in deduping code. + +2002-11-05 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (key_in_keylist, add_key_to_keylist, + free_keylist, get_key, search_key): The LDAP keyserver doesn't + remove duplicates, so remove them locally. Do not include the key + modification time in the search response. + +2002-11-04 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (send_key), gpgkeys_ldap.c (send_key): Properly + handle an input file that does not include any key data at all. + +2002-10-24 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (main), gpgkeys_ldap.c (main): Add -V flag to + output protocol and program version. + +2002-10-21 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Anything linking with libutil.a needs INTLLIBS as + well on platforms where INTLLIBS is set. + +2002-10-14 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (write_quoted): Use %-encoding instead of + \-encoding. + (parse_hkp_index): Use new keyserver key listing format, and add + support for disabled keys via include-disabled. + + * gpgkeys_ldap.c (get_key): Don't print keysize unless it's >0. + (printquoted): Use %-encoding instead of \-encoding. + (search_key): Use new keyserver key listing format. + +2002-10-08 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (search_key, main): Make sure LDAP values are + freed in case of error. + + * gpgkeys_ldap.c (fail_all): New function to unwind a keylist and + error each item. + (main): Call fail_all from here, as needed. Also add a NO_MEMORY + error in an appropriate place and fix error return code. + (ldap_err_to_gpg_err): Add KEYSERVER_UNREACHABLE. + + * gpgkeys_hkp.c (fail_all): New function to unwind a keylist and + error each item. + (main): Call fail_all from here. Also add a NO_MEMORY error in an + appropriate place. + (get_key): Use new UNREACHABLE error for network errors. + +2002-09-26 Werner Koch <wk@gnupg.org> + + * gpgkeys_ldap.c (send_key): Removed non-constant initializers. + +2002-09-24 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (ldap_err_to_gpg_err, ldap_to_gpg_err, send_key, + get_key, search_key, main): Some minor error reporting + enhancements for use with GPA (show reasons for KEY FAILED). + + * gpgkeys_hkp.c (send_key, get_key, search_key, main): Some minor + error reporting enhancements for use with GPA (show reasons for + KEY FAILED). + +2002-09-20 Werner Koch <wk@gnupg.org> + + * gpgkeys_hkp.c (handle_old_hkp_index): s/input/inp/ to avoid + shadowing warning. + +2002-09-19 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (get_key, handle_old_hkp_index, search_key): + Properly handle line truncation. + +2002-09-16 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_mailto.in: Add quasi-RFC-2368 mailto:email@addr?from= + syntax so people can set their own email address to respond to. + + * gpgkeys_hkp.c (get_key): Properly respond with KEY FAILED (to + gpg) and "key not found" (to user) on failure. + +2002-09-13 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c: (search_key, handle_old_hkp_index): Try and + request a machine-readable key index. If the server supports + this, pass it through. If the server does not support it, parse + the "index" page. + +2002-09-12 Stefan Bellon <sbellon@sbellon.de> + + * gpgkeys_hkp.c: Tidied up RISC OS initializations. + +2002-09-12 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (main): Remove warning - this is no longer + experimental code. + +2002-09-09 Werner Koch <wk@gnupg.org> + + * gpgkeys_hkp.c (send_key, get_key, search_key): Check return + value of malloc. + (dehtmlize): Use ascii_tolower to protect against weird locales. + Cast the argument for isspace for the sake of broken HP/UXes. + (search_key): Check return value of realloc. + +2002-09-09 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (get_key): Some compilers (RISC OS, HPUX c89) + don't like using variables as array initializers. + + * gpgkeys_hkp.c (send_key): Use CRLF in headers. + +2002-08-28 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (parse_hkp_index): Use same types on all + platforms. This was probably leftover from earlier code where the + typing mattered. + + * gpgkeys_hkp.c: Overall cleanup from iobuf conversion. Be + consistent in m_alloc and malloc usage. Remove include-disabled + (meaningless on HKP). RISC OS tweak. + +2002-08-27 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c, Makefile.am: Convert over to using iobufs. + + * gpgkeys_hkp.c (http_get, http_post): Use CRLF for line endings. + + * gpgkeys_hkp.c: Include util.h on RISC OS as per Stefan. Include + a replacement for hstrerror() for those platforms (such as RISC + OS) that don't have it. + +2002-08-26 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: May as well include gpgkeys_hkp.c in the + distribution now. It works well enough without proxies, and isn't + built by default. It would be good to get some test experience + with it. + + * gpgkeys_hkp.c (main): Don't warn about include-subkeys - it + isn't unsupported, it's actually non-meaningful in the context of + HKP (yet). + + * gpgkeys_hkp.c (parse_hkp_index, dehtmlize): Move HTML + functionality into new "dehtmlize" function. Remove HTML before + trying to parse each line from the keyserver. If the keyserver + provides key type information in the listing, use it. (Copy over + from g10/hkp.c). + +2002-08-19 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (get_key, parse_hkp_index): Bring over latest code + from g10/hkp.c. + + * gpgkeys_ldap.c (get_key): Fix cosmetic URL display problem + (extra ":" at the end). + +2002-08-03 Stefan Bellon <sbellon@sbellon.de> + + * gpgkeys_ldap.c: Tidied up RISC OS initializations. + +2002-07-25 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c: "Warning" -> "WARNING" + +2002-07-24 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Install keyserver helpers in @GNUPG_LIBEXECDIR@ + +2002-07-15 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (send_key, get_key, main): Consult the server + version string to determine whether to use pgpKey or pgpKeyV2. + +2002-07-09 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_mailto.in: Use new OPAQUE tag for non net-path URIs. + Fail more elegantly if there is no email address to send to. Show + the GnuPG version in the message body. + +2002-07-04 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (get_key), gpgkeys_hkp.c (get_key): Display + keyserver URI as a URI, but only if verbose. + +2002-07-01 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (parse_hkp_index): Error if the keyserver returns + an unparseable HKP response. + + * gpgkeys_hkp.c (main): Warn on honor-http-proxy, + broken-http-proxy, and include-subkeys (not supported yet). + + * gpgkeys_ldap.c (main), gpgkeys_hkp.c (http_connect, main): Fix + some shadowing warnings. + +2002-06-11 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am: Don't hard-code the LDAP libraries - get them from + LDAPLIBS via configure. Also, gpgkeys_hkp is a program, not a + script. + +2002-06-10 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (include_subkeys): Default "include-subkeys" to + off, since GnuPG now defaults it to on. + +2002-06-06 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_hkp.c (parse_hkp_index): Type tweaks. + + * gpgkeys_hkp.c (main): Add experimental code warning. + +2002-06-05 David Shaw <dshaw@jabberwocky.com> + + * Makefile.am, gpgkeys_hkp.c (new): Experimental HKP keyserver + interface. + +2002-05-08 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c: Include <lber.h> if we absolutely must. This + helps when compiling against a very old OpenLDAP. + +2002-04-29 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_mailto.in: Properly handle key requests in full + fingerprint form. + +2002-03-29 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (printquoted): Quote backslashes within keyserver + search responses. + +2002-02-25 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap (get_key): LDAP keyservers do not support v3 + fingerprints, so error out if someone tries. Actually, they don't + support any fingerprints, but at least we can calculate a keyid + from a v4 fingerprint. + +2002-02-23 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap: Clarify the notion of a partial failure. This is + possible if more than one key is being handled in a batch, and one + fails while the other succeeds. Note that a search that comes up + with no results is not a failure - that is a valid response of "no + answer". + + * gpgkeys_ldap.c (get_key): Allow GnuPG to send us full v4 + fingerprints, long key ids, or short key ids while fetching. + Since the LDAP server doesn't actually handle fingerprints, chop + them down to long key ids for actual use. + + * gpgkeys_ldap.c (main, get_key): When searching for a keyid, + search for subkeys as well as primary keys. This is mostly + significant when automatically fetching the key based on the id in + a header (i.e. "signature made by...."). "no-include-subkeys" + disables. + +2002-02-14 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c: Fix compiler warning. + + * gpgkeys_ldap.c: Be much more robust with mangled input files. + +2001-12-28 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_mailto.in: Use the new OUTOFBAND indicator so gpg knows + not to try and import anything. Also turn on perl -w for + warnings. + + * gpgkeys_ldap.c (main): If we're using temp files (rather than + stdin/stdout), make sure the file is closed when we're done. + +2001-12-20 David Shaw <dshaw@jabberwocky.com> + + * Properly free the LDAP response when we're done with it. + + * Now that we handle multiple keys, we must remove duplicates as + the LDAP keyserver returns keys with multiple user IDs multiple + times. + + * Properly handle multiple keys with the same key ID (it's really + rare, so fetch "0xDEADBEEF" to test this). + +2001-12-17 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c, gpgkeys_mailto.in: Fix GNU capitalization + issues. Prefix log messages with "gpgkeys" to clarify which + program is generating them. + +2001-12-14 David Shaw <dshaw@jabberwocky.com> + + * gpgkeys_ldap.c (search_key): Use unsigned int rather than uint + for portability. + +2001-12-04 David Shaw <dshaw@jabberwocky.com> + + * Initial version of gpgkeys_ldap (LDAP keyserver helper) and + gpgkeys_mailto (email keyserver helper) + + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, + 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. diff --git a/keyserver/Makefile.am b/keyserver/Makefile.am new file mode 100644 index 000000000..72572de2c --- /dev/null +++ b/keyserver/Makefile.am @@ -0,0 +1,53 @@ +# Copyright (C) 2001, 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +## Process this file with automake to produce Makefile.in + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl +EXTRA_PROGRAMS = gpgkeys_ldap gpgkeys_hkp gpgkeys_finger gpgkeys_curl +EXTRA_SCRIPTS = gpgkeys_mailto + +gpglibexecdir = $(libexecdir)/@PACKAGE@ + +gpglibexec_PROGRAMS = @GPGKEYS_LDAP@ @GPGKEYS_HKP@ @GPGKEYS_FINGER@ @GPGKEYS_CURL@ +gpglibexec_SCRIPTS = @GPGKEYS_MAILTO@ +noinst_SCRIPTS = gpgkeys_test + +gpgkeys_ldap_SOURCES = gpgkeys_ldap.c ksutil.c ksutil.h +gpgkeys_hkp_SOURCES = gpgkeys_hkp.c ksutil.c ksutil.h +gpgkeys_finger_SOURCES = gpgkeys_finger.c ksutil.c ksutil.h +gpgkeys_curl_SOURCES = gpgkeys_curl.c ksutil.c ksutil.h + +other_libs = $(LIBICONV) $(LIBINTL) $(CAPLIBS) + +gpgkeys_ldap_CPPFLAGS = @LDAP_CPPFLAGS@ +gpgkeys_ldap_LDADD = ../util/libutil.a @LDAPLIBS@ @NETLIBS@ $(other_libs) @GETOPT@ @W32LIBS@ + +gpgkeys_finger_LDADD = ../util/libutil.a @NETLIBS@ $(other_libs) @GETOPT@ @W32LIBS@ + +if FAKE_CURL +gpgkeys_curl_SOURCES += curl-shim.c curl-shim.h +gpgkeys_curl_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@ +gpgkeys_hkp_SOURCES += curl-shim.c curl-shim.h +gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@ +else +gpgkeys_curl_CPPFLAGS = @LIBCURL_CPPFLAGS@ +gpgkeys_curl_LDADD = @LIBCURL@ @GETOPT@ +gpgkeys_hkp_CPPFLAGS = @LIBCURL_CPPFLAGS@ +gpgkeys_hkp_LDADD = @LIBCURL@ @GETOPT@ +endif diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c new file mode 100644 index 000000000..4a4d18f56 --- /dev/null +++ b/keyserver/curl-shim.c @@ -0,0 +1,324 @@ +/* curl-shim.c - Implement a small subset of the curl API in terms of + * the iobuf HTTP API + * + * Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include "http.h" +#include "util.h" +#include "ksutil.h" +#include "curl-shim.h" + +static CURLcode +handle_error(CURL *curl,CURLcode err,const char *str) +{ + if(curl->errorbuffer) + { + /* Make sure you never exceed CURL_ERROR_SIZE, currently set to + 256 in curl-shim.h */ + switch(err) + { + case CURLE_OK: + strcpy(curl->errorbuffer,"okay"); + break; + + case CURLE_UNSUPPORTED_PROTOCOL: + strcpy(curl->errorbuffer,"unsupported protocol"); + break; + + case CURLE_COULDNT_CONNECT: + strcpy(curl->errorbuffer,"couldn't connect"); + break; + + case CURLE_WRITE_ERROR: + strcpy(curl->errorbuffer,"write error"); + break; + + case CURLE_HTTP_RETURNED_ERROR: + sprintf(curl->errorbuffer,"url returned error %u",curl->status); + break; + + default: + strcpy(curl->errorbuffer,"generic error"); + break; + } + + if(str && (strlen(curl->errorbuffer)+2+strlen(str)+1)<=CURL_ERROR_SIZE) + { + strcat(curl->errorbuffer,": "); + strcat(curl->errorbuffer,str); + } + } + + return err; +} + +CURLcode +curl_global_init(long flags) +{ + return CURLE_OK; +} + +void +curl_global_cleanup(void) {} + +CURL * +curl_easy_init(void) +{ + CURL *handle; + + handle=calloc(1,sizeof(CURL)); + if(handle) + handle->errors=stderr; + + return handle; +} + +void +curl_easy_cleanup(CURL *curl) +{ + free(curl); +} + +CURLcode +curl_easy_setopt(CURL *curl,CURLoption option,...) +{ + va_list ap; + + va_start(ap,option); + + switch(option) + { + case CURLOPT_URL: + curl->url=va_arg(ap,char *); + break; + case CURLOPT_USERPWD: + curl->auth=va_arg(ap,char *); + break; + case CURLOPT_WRITEFUNCTION: + curl->writer=va_arg(ap,write_func); + break; + case CURLOPT_FILE: + curl->file=va_arg(ap,void *); + break; + case CURLOPT_ERRORBUFFER: + curl->errorbuffer=va_arg(ap,char *); + break; + case CURLOPT_PROXY: + curl->proxy=va_arg(ap,char *); + break; + case CURLOPT_POST: + curl->flags.post=va_arg(ap,unsigned int); + break; + case CURLOPT_POSTFIELDS: + curl->postfields=va_arg(ap,char *); + break; + case CURLOPT_FAILONERROR: + curl->flags.failonerror=va_arg(ap,unsigned int); + break; + case CURLOPT_VERBOSE: + curl->flags.verbose=va_arg(ap,unsigned int); + break; + case CURLOPT_STDERR: + curl->errors=va_arg(ap,FILE *); + break; + default: + /* We ignore the huge majority of curl options */ + break; + } + + return handle_error(curl,CURLE_OK,NULL); +} + +CURLcode +curl_easy_perform(CURL *curl) +{ + int rc; + CURLcode err=CURLE_OK; + const char *errstr=NULL; + char *proxy=NULL; + + /* Emulate the libcurl proxy behavior. If the calling program set a + proxy, use it. If it didn't set a proxy or set it to NULL, check + for one in the environment. If the calling program explicitly + set a null-string proxy, don't set a proxy at all. */ + + if(curl->proxy) + { + if(*curl->proxy) + proxy=curl->proxy; + } + else + proxy=getenv(HTTP_PROXY_ENV); + + if(curl->flags.verbose) + fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null"); + + if(curl->flags.post) + { + rc=http_open(&curl->hd,HTTP_REQ_POST,curl->url,curl->auth,0,proxy); + if(rc==0) + { + char content_len[50]; + unsigned int post_len=strlen(curl->postfields); + + iobuf_writestr(curl->hd.fp_write, + "Content-Type: application/x-www-form-urlencoded\r\n"); + sprintf(content_len,"Content-Length: %u\r\n",post_len); + + iobuf_writestr(curl->hd.fp_write,content_len); + + http_start_data(&curl->hd); + iobuf_write(curl->hd.fp_write,curl->postfields,post_len); + rc=http_wait_response(&curl->hd,&curl->status); + if(rc==0 && curl->flags.failonerror && curl->status>=300) + err=CURLE_HTTP_RETURNED_ERROR; + } + } + else + { + rc=http_open(&curl->hd,HTTP_REQ_GET,curl->url,curl->auth,0,proxy); + if(rc==0) + { + rc=http_wait_response(&curl->hd,&curl->status); + if(rc==0) + { + if(curl->flags.failonerror && curl->status>=300) + err=CURLE_HTTP_RETURNED_ERROR; + else + { + unsigned int maxlen=1024,buflen,len; + byte *line=NULL; + + while((len=iobuf_read_line(curl->hd.fp_read, + &line,&buflen,&maxlen))) + { + size_t ret; + + maxlen=1024; + + ret=(curl->writer)(line,len,1,curl->file); + if(ret!=len) + { + err=CURLE_WRITE_ERROR; + break; + } + } + + xfree(line); + http_close(&curl->hd); + } + } + else + http_close(&curl->hd); + } + } + + switch(rc) + { + case 0: + break; + + case G10ERR_INVALID_URI: + err=CURLE_UNSUPPORTED_PROTOCOL; + break; + + case G10ERR_NETWORK: + errstr=strerror(errno); + err=CURLE_COULDNT_CONNECT; + break; + + default: + errstr=g10_errstr(rc); + err=CURLE_COULDNT_CONNECT; + break; + } + + return handle_error(curl,err,errstr); +} + +/* This is not the same exact set that is allowed according to + RFC-2396, but it is what the real curl uses. */ +#define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "0123456789" + +char * +curl_escape(char *str,int length) +{ + int len,max,idx,enc_idx=0; + char *enc; + + if(length) + len=length; + else + len=strlen(str); + + enc=malloc(len+1); + if(!enc) + return enc; + + max=len; + + for(idx=0;idx<len;idx++) + { + if(enc_idx+3>max) + { + char *tmp; + + max+=100; + + tmp=realloc(enc,max+1); + if(!tmp) + { + free(enc); + return NULL; + } + + enc=tmp; + } + + if(strchr(VALID_URI_CHARS,str[idx])) + enc[enc_idx++]=str[idx]; + else + { + char numbuf[5]; + sprintf(numbuf,"%%%02X",str[idx]); + strcpy(&enc[enc_idx],numbuf); + enc_idx+=3; + } + } + + enc[enc_idx]='\0'; + + return enc; +} + +void +curl_free(char *ptr) +{ + free(ptr); +} diff --git a/keyserver/curl-shim.h b/keyserver/curl-shim.h new file mode 100644 index 000000000..91eac9d1e --- /dev/null +++ b/keyserver/curl-shim.h @@ -0,0 +1,92 @@ +/* curl-shim.h + * Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef _CURL_SHIM_H_ +#define _CURL_SHIM_H_ + +#include "http.h" + +typedef enum + { + CURLE_OK=0, + CURLE_UNSUPPORTED_PROTOCOL=1, + CURLE_COULDNT_CONNECT=7, + CURLE_FTP_COULDNT_RETR_FILE=19, + CURLE_HTTP_RETURNED_ERROR=22, + CURLE_WRITE_ERROR=23 + } CURLcode; + +typedef enum + { + CURLOPT_URL, + CURLOPT_USERPWD, + CURLOPT_WRITEFUNCTION, + CURLOPT_FILE, + CURLOPT_ERRORBUFFER, + CURLOPT_FOLLOWLOCATION, + CURLOPT_MAXREDIRS, + CURLOPT_STDERR, + CURLOPT_VERBOSE, + CURLOPT_SSL_VERIFYPEER, + CURLOPT_PROXY, + CURLOPT_CAINFO, + CURLOPT_POST, + CURLOPT_POSTFIELDS, + CURLOPT_FAILONERROR + } CURLoption; + +typedef size_t (*write_func)(char *buffer,size_t size, + size_t nitems,void *outstream); + +typedef struct +{ + char *url; + char *auth; + char *errorbuffer; + char *proxy; + write_func writer; + void *file; + char *postfields; + unsigned int status; + FILE *errors; + struct + { + unsigned int post:1; + unsigned int failonerror:1; + unsigned int verbose:1; + } flags; + struct http_context hd; +} CURL; + +#define CURL_ERROR_SIZE 256 +#define CURL_GLOBAL_DEFAULT 0 + +CURLcode curl_global_init(long flags); +void curl_global_cleanup(void); +CURL *curl_easy_init(void); +CURLcode curl_easy_setopt(CURL *curl,CURLoption option,...); +CURLcode curl_easy_perform(CURL *curl); +void curl_easy_cleanup(CURL *curl); +char *curl_escape(char *str,int len); +void curl_free(char *ptr); +#define curl_version() "GnuPG curl-shim "VERSION + +#endif /* !_CURL_SHIM_H_ */ diff --git a/keyserver/gpgkeys_curl.c b/keyserver/gpgkeys_curl.c new file mode 100644 index 000000000..9e4b56729 --- /dev/null +++ b/keyserver/gpgkeys_curl.c @@ -0,0 +1,369 @@ +/* gpgkeys_curl.c - fetch a key via libcurl + * Copyright (C) 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#else +#include "curl-shim.h" +#endif +#include "keyserver.h" +#include "ksutil.h" + +extern char *optarg; +extern int optind; + +static FILE *input,*output,*console; +static CURL *curl; +static struct ks_options *opt; + +static int +get_key(char *getkey) +{ + CURLcode res; + char errorbuffer[CURL_ERROR_SIZE]; + char request[MAX_URL]; + struct curl_writer_ctx ctx; + + memset(&ctx,0,sizeof(ctx)); + + if(strncmp(getkey,"0x",2)==0) + getkey+=2; + + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + + sprintf(request,"%s://%s%s%s%s",opt->scheme,opt->host, + opt->port?":":"",opt->port?opt->port:"",opt->path?opt->path:"/"); + + curl_easy_setopt(curl,CURLOPT_URL,request); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer); + ctx.stream=output; + curl_easy_setopt(curl,CURLOPT_FILE,&ctx); + curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer); + + res=curl_easy_perform(curl); + if(res!=CURLE_OK) + { + fprintf(console,"gpgkeys: %s fetch error %d: %s\n",opt->scheme, + res,errorbuffer); + fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res)); + } + else + { + curl_writer_finalize(&ctx); + if(!ctx.flags.done) + { + fprintf(console,"gpgkeys: no key data found for %s\n",request); + fprintf(output,"\nKEY 0x%s FAILED %d\n", + getkey,KEYSERVER_KEY_NOT_FOUND); + } + else + fprintf(output,"\nKEY 0x%s END\n",getkey); + } + + return curl_err_to_gpg_err(res); +} + +static void +show_help (FILE *fp) +{ + fprintf (fp,"-h\thelp\n"); + fprintf (fp,"-V\tversion\n"); + fprintf (fp,"-o\toutput to this file\n"); +} + +int +main(int argc,char *argv[]) +{ + int arg,ret=KEYSERVER_INTERNAL_ERROR; + char line[MAX_LINE]; + char *thekey=NULL; + long follow_redirects=5; + char *proxy=NULL; + + console=stderr; + + /* Kludge to implement standard GNU options. */ + if (argc > 1 && !strcmp (argv[1], "--version")) + { + fputs ("gpgkeys_curl (GnuPG) " VERSION"\n", stdout); + return 0; + } + else if (argc > 1 && !strcmp (argv[1], "--help")) + { + show_help (stdout); + return 0; + } + + while((arg=getopt(argc,argv,"hVo:"))!=-1) + switch(arg) + { + default: + case 'h': + show_help (console); + return KEYSERVER_OK; + + case 'V': + fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION); + return KEYSERVER_OK; + + case 'o': + output=fopen(optarg,"wb"); + if(output==NULL) + { + fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n", + optarg,strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + + break; + } + + if(argc>optind) + { + input=fopen(argv[optind],"r"); + if(input==NULL) + { + fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n", + argv[optind],strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + } + + if(input==NULL) + input=stdin; + + if(output==NULL) + output=stdout; + + opt=init_ks_options(); + if(!opt) + return KEYSERVER_NO_MEMORY; + + /* Get the command and info block */ + + while(fgets(line,MAX_LINE,input)!=NULL) + { + int err; + char option[MAX_OPTION+1]; + + if(line[0]=='\n') + break; + + err=parse_ks_options(line,opt); + if(err>0) + { + ret=err; + goto fail; + } + else if(err==0) + continue; + + if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1) + { + int no=0; + char *start=&option[0]; + + option[MAX_OPTION]='\0'; + + if(strncasecmp(option,"no-",3)==0) + { + no=1; + start=&option[3]; + } + + if(strncasecmp(start,"http-proxy",10)==0) + { + /* Safe to not check the return code of strdup() here. + If it fails, we simply won't use a proxy. */ + if(no) + { + free(proxy); + proxy=strdup(""); + } + else if(start[10]=='=') + { + if(strlen(&start[11])<MAX_PROXY) + { + free(proxy); + proxy=strdup(&start[11]); + } + } + } + else if(strncasecmp(start,"follow-redirects",16)==0) + { + if(no) + follow_redirects=0; + else if(start[16]=='=') + follow_redirects=atoi(&start[17]); + else if(start[16]=='\0') + follow_redirects=-1; + } + + continue; + } + } + + if(!opt->scheme) + { + fprintf(console,"gpgkeys: no scheme supplied!\n"); + ret=KEYSERVER_SCHEME_NOT_FOUND; + goto fail; + } + + if(!opt->host) + { + fprintf(console,"gpgkeys: no keyserver host provided\n"); + goto fail; + } + + if(opt->timeout && register_timeout()==-1) + { + fprintf(console,"gpgkeys: unable to register timeout handler\n"); + return KEYSERVER_INTERNAL_ERROR; + } + + curl_global_init(CURL_GLOBAL_DEFAULT); + curl=curl_easy_init(); + if(!curl) + { + fprintf(console,"gpgkeys: unable to initialize curl\n"); + ret=KEYSERVER_INTERNAL_ERROR; + goto fail; + } + + if(follow_redirects) + { + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1); + if(follow_redirects>0) + curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects); + } + + if(opt->auth) + curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth); + + if(opt->debug) + { + fprintf(console,"gpgkeys: curl version = %s\n",curl_version()); + curl_easy_setopt(curl,CURLOPT_STDERR,console); + curl_easy_setopt(curl,CURLOPT_VERBOSE,1); + } + + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,opt->flags.check_cert); + curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file); + + if(proxy) + curl_easy_setopt(curl,CURLOPT_PROXY,proxy); + + /* If it's a GET or a SEARCH, the next thing to come in is the + keyids. If it's a SEND, then there are no keyids. */ + + if(opt->action==KS_GET) + { + /* Eat the rest of the file */ + for(;;) + { + if(fgets(line,MAX_LINE,input)==NULL) + break; + else + { + if(line[0]=='\n' || line[0]=='\0') + break; + + if(!thekey) + { + thekey=strdup(line); + if(!thekey) + { + fprintf(console,"gpgkeys: out of memory while " + "building key list\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + /* Trim the trailing \n */ + thekey[strlen(line)-1]='\0'; + } + } + } + } + else + { + fprintf(console, + "gpgkeys: this keyserver type only supports key retrieval\n"); + goto fail; + } + + if(!thekey) + { + fprintf(console,"gpgkeys: invalid keyserver instructions\n"); + goto fail; + } + + /* Send the response */ + + fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(output,"PROGRAM %s\n\n",VERSION); + + if(opt->verbose) + { + fprintf(console,"Scheme:\t\t%s\n",opt->scheme); + fprintf(console,"Host:\t\t%s\n",opt->host); + if(opt->port) + fprintf(console,"Port:\t\t%s\n",opt->port); + if(opt->path) + fprintf(console,"Path:\t\t%s\n",opt->path); + fprintf(console,"Command:\tGET\n"); + } + + set_timeout(opt->timeout); + + ret=get_key(thekey); + + fail: + + free(thekey); + + if(input!=stdin) + fclose(input); + + if(output!=stdout) + fclose(output); + + free_ks_options(opt); + + if(curl) + curl_easy_cleanup(curl); + + free(proxy); + + curl_global_cleanup(); + + return ret; +} diff --git a/keyserver/gpgkeys_finger.c b/keyserver/gpgkeys_finger.c new file mode 100644 index 000000000..4124ebc72 --- /dev/null +++ b/keyserver/gpgkeys_finger.c @@ -0,0 +1,534 @@ +/* gpgkeys_finger.c - fetch a key via finger + * Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif + +#ifdef _WIN32 +#include <windows.h> +#else +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#endif + +#define INCLUDED_BY_MAIN_MODULE 1 +#include "util.h" +#include "keyserver.h" +#include "ksutil.h" + +#ifdef _WIN32 +#define sock_close(a) closesocket(a) +#else +#define sock_close(a) close(a) +#endif + +extern char *optarg; +extern int optind; + +static FILE *input,*output,*console; +static struct ks_options *opt; + +#ifdef _WIN32 +static void +deinit_sockets (void) +{ + WSACleanup(); +} + +static void +init_sockets (void) +{ + static int initialized; + static WSADATA wsdata; + + if (initialized) + return; + + if (WSAStartup (0x0101, &wsdata) ) + { + fprintf (console, "error initializing socket library: ec=%d\n", + (int)WSAGetLastError () ); + return; + } + if (wsdata.wVersion < 0x0001) + { + fprintf (console, "socket library version is %x.%x - but 1.1 needed\n", + LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion)); + WSACleanup(); + return; + } + atexit (deinit_sockets); + initialized = 1; +} +#endif /*_WIN32*/ + + +/* Connect to SERVER at PORT and return a file descriptor or -1 on + error. */ +static int +connect_server (const char *server, unsigned short port) +{ + int sock = -1; + +#ifdef _WIN32 + struct hostent *hp; + struct sockaddr_in addr; + unsigned long l; + + init_sockets (); + + memset (&addr, 0, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = htons (port); + + /* Win32 gethostbyname doesn't handle IP addresses internally, so we + try inet_addr first on that platform only. */ + if ((l = inet_addr (server)) != INADDR_NONE) + memcpy (&addr.sin_addr, &l, sizeof l); + else if ((hp = gethostbyname (server))) + { + if (hp->h_addrtype != AF_INET) + { + fprintf (console, "gpgkeys: unknown address family for `%s'\n", + server); + return -1; + } + if (hp->h_length != 4) + { + fprintf (console, "gpgkeys: illegal address length for `%s'\n", + server); + return -1; + } + memcpy (&addr.sin_addr, hp->h_addr, hp->h_length); + } + else + { + fprintf (console, "gpgkeys: host `%s' not found: ec=%d\n", + server, (int)WSAGetLastError ()); + return -1; + } + + sock = socket (AF_INET, SOCK_STREAM, 0); + if (sock == INVALID_SOCKET) + { + fprintf (console, "gpgkeys: error creating socket: ec=%d\n", + (int)WSAGetLastError ()); + return -1; + } + + if (connect (sock, (struct sockaddr *)&addr, sizeof addr)) + { + fprintf (console, "gpgkeys: error connecting `%s': ec=%d\n", + server, (int)WSAGetLastError ()); + sock_close (sock); + return -1; + } + +#else + + struct sockaddr_in addr; + struct hostent *host; + + addr.sin_family = AF_INET; + addr.sin_port = htons (port); + host = gethostbyname ((char*)server); + if (!host) + { + fprintf (console, "gpgkeys: host `%s' not found: %s\n", + server, strerror (errno)); + return -1; + } + + addr.sin_addr = *(struct in_addr*)host->h_addr; + + sock = socket (AF_INET, SOCK_STREAM, 0); + if (sock == -1) + { + fprintf (console, "gpgkeys: error creating socket: %s\n", + strerror (errno)); + return -1; + } + + if (connect (sock, (struct sockaddr *)&addr, sizeof addr) == -1) + { + fprintf (console, "gpgkeys: error connecting `%s': %s\n", + server, strerror (errno)); + close (sock); + return -1; + } +#endif + + return sock; +} + +static int +write_server (int sock, const char *data, size_t length) +{ + int nleft; + + nleft = length; + while (nleft > 0) + { + int nwritten; + +#ifdef _WIN32 + nwritten = send (sock, data, nleft, 0); + if ( nwritten == SOCKET_ERROR ) + { + fprintf (console, "gpgkeys: write failed: ec=%d\n", + (int)WSAGetLastError ()); + return -1; + } +#else + nwritten = write (sock, data, nleft); + if (nwritten == -1) + { + if (errno == EINTR) + continue; + if (errno == EAGAIN) + { + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 50000; + select(0, NULL, NULL, NULL, &tv); + continue; + } + fprintf (console, "gpgkeys: write failed: %s\n", strerror(errno)); + return -1; + } +#endif + nleft -=nwritten; + data += nwritten; + } + + return 0; +} + + +/* Send the finger REQUEST to the server. Returns 0 and a file descriptor + in R_SOCK if the request was sucessful. */ +static int +send_request (const char *request, int *r_sock) +{ + char *server; + char *name; + int sock; + + *r_sock = -1; + name = strdup (request); + if (!name) + { + fprintf(console,"gpgkeys: out of memory\n"); + return KEYSERVER_NO_MEMORY; + } + + server = strchr (name, '@'); + if (!server) + { + fprintf (console, "gpgkeys: no name included in request\n"); + free (name); + return KEYSERVER_GENERAL_ERROR; + } + *server++ = 0; + + sock = connect_server (server, 79); + if (sock == -1) + { + free (name); + return KEYSERVER_UNREACHABLE; + } + + if (write_server (sock, name, strlen (name)) + || write_server (sock, "\r\n", 2)) + { + free (name); + sock_close (sock); + return KEYSERVER_GENERAL_ERROR; + } + free (name); + *r_sock = sock; + return 0; +} + + + +static int +get_key (char *getkey) +{ + int rc; + int sock; + IOBUF fp_read; + unsigned int maxlen, buflen, gotit=0; + byte *line = NULL; + + if (strncmp (getkey,"0x",2)==0) + getkey+=2; + + /* Frankly we don't know what keys the server will return; we + indicated the requested key anyway. */ + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + + rc=send_request(opt->opaque,&sock); + if(rc) + { + fprintf(output,"KEY 0x%s FAILED %d\n",getkey, rc); + sock_close (sock); + return KEYSERVER_OK; + } + + /* Hmmm, we use iobuf here only to cope with Windows socket + peculiarities (we can't used fdopen). */ + fp_read = iobuf_sockopen (sock , "r"); + if (!fp_read) + { + fprintf(output,"KEY 0x%s FAILED %d\n",getkey, KEYSERVER_INTERNAL_ERROR); + sock_close (sock); + return KEYSERVER_OK; + } + + while ( iobuf_read_line ( fp_read, &line, &buflen, &maxlen)) + { + maxlen=1024; + + if(gotit) + { + print_nocr(output,line); + if (!strncmp(line,END,strlen(END))) + break; + } + else if(!strncmp(line,BEGIN,strlen(BEGIN))) + { + print_nocr(output,line); + gotit=1; + } + } + + if(gotit) + fprintf (output,"KEY 0x%s END\n", getkey); + else + { + fprintf(console,"gpgkeys: no key data found for finger:%s\n", + opt->opaque); + fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND); + } + + xfree(line); + iobuf_close (fp_read); + + return KEYSERVER_OK; +} + + +static void +show_help (FILE *fp) +{ + fprintf (fp,"-h\thelp\n"); + fprintf (fp,"-V\tversion\n"); + fprintf (fp,"-o\toutput to this file\n"); +} + +int +main(int argc,char *argv[]) +{ + int arg,ret=KEYSERVER_INTERNAL_ERROR; + char line[MAX_LINE]; + char *thekey=NULL; + + console=stderr; + + /* Kludge to implement standard GNU options. */ + if (argc > 1 && !strcmp (argv[1], "--version")) + { + fputs ("gpgkeys_finger (GnuPG) " VERSION"\n", stdout); + return 0; + } + else if (argc > 1 && !strcmp (argv[1], "--help")) + { + show_help (stdout); + return 0; + } + + while((arg=getopt(argc,argv,"hVo:"))!=-1) + switch(arg) + { + default: + case 'h': + show_help (console); + return KEYSERVER_OK; + + case 'V': + fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION); + return KEYSERVER_OK; + + case 'o': + output=fopen(optarg,"w"); + if(output==NULL) + { + fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n", + optarg,strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + + break; + } + + if(argc>optind) + { + input=fopen(argv[optind],"r"); + if(input==NULL) + { + fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n", + argv[optind],strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + } + + if(input==NULL) + input=stdin; + + if(output==NULL) + output=stdout; + + opt=init_ks_options(); + if(!opt) + return KEYSERVER_NO_MEMORY; + + /* Get the command and info block */ + + while(fgets(line,MAX_LINE,input)!=NULL) + { + int err; + + if(line[0]=='\n') + break; + + err=parse_ks_options(line,opt); + if(err>0) + { + ret=err; + goto fail; + } + else if(err==0) + continue; + } + + if(opt->host) + { + fprintf(console,"gpgkeys: finger://relay/user syntax is not" + " supported. Use finger:user instead.\n"); + ret=KEYSERVER_NOT_SUPPORTED; + goto fail; + } + + if(opt->timeout && register_timeout()==-1) + { + fprintf(console,"gpgkeys: unable to register timeout handler\n"); + return KEYSERVER_INTERNAL_ERROR; + } + + /* If it's a GET or a SEARCH, the next thing to come in is the + keyids. If it's a SEND, then there are no keyids. */ + + if(opt->action==KS_GET) + { + /* Eat the rest of the file */ + for(;;) + { + if(fgets(line,MAX_LINE,input)==NULL) + break; + else + { + if(line[0]=='\n' || line[0]=='\0') + break; + + if(!thekey) + { + thekey=strdup(line); + if(!thekey) + { + fprintf(console,"gpgkeys: out of memory while " + "building key list\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + /* Trim the trailing \n */ + thekey[strlen(line)-1]='\0'; + } + } + } + } + else + { + fprintf(console, + "gpgkeys: this keyserver type only supports key retrieval\n"); + goto fail; + } + + if(!thekey || !opt->opaque) + { + fprintf(console,"gpgkeys: invalid keyserver instructions\n"); + goto fail; + } + + /* Send the response */ + + fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(output,"PROGRAM %s\n\n",VERSION); + + if(opt->verbose>1) + { + fprintf(console,"User:\t\t%s\n",opt->opaque); + fprintf(console,"Command:\tGET\n"); + } + + set_timeout(opt->timeout); + + ret=get_key(thekey); + + fail: + + free(thekey); + + if(input!=stdin) + fclose(input); + + if(output!=stdout) + fclose(output); + + free_ks_options(opt); + + return ret; +} diff --git a/keyserver/gpgkeys_hkp.c b/keyserver/gpgkeys_hkp.c new file mode 100644 index 000000000..b3ebcf1a9 --- /dev/null +++ b/keyserver/gpgkeys_hkp.c @@ -0,0 +1,833 @@ +/* gpgkeys_hkp.c - talk to an HKP keyserver + * Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#else +#include "curl-shim.h" +#endif +#include "keyserver.h" +#include "ksutil.h" + +extern char *optarg; +extern int optind; + +static FILE *input,*output,*console; +static CURL *curl; +static struct ks_options *opt; +static char errorbuffer[CURL_ERROR_SIZE]; + +static size_t +curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream) +{ + static int checked=0,swallow=0; + + if(!checked) + { + /* If the document begins with a '<', assume it's a HTML + response, which we don't support. Discard the whole message + body. GPG can handle it, but this is an optimization to deal + with it on this side of the pipe. */ + const char *buf=ptr; + if(buf[0]=='<') + swallow=1; + + checked=1; + } + + if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb) + return size*nmemb; + else + return 0; +} + +/* Append but avoid creating a double slash // in the path. */ +static char * +append_path(char *dest,const char *src) +{ + size_t n=strlen(dest); + + if(src[0]=='/' && n>0 && dest[n-1]=='/') + dest[n-1]='\0'; + + return strcat(dest,src); +} + +int +send_key(int *eof) +{ + CURLcode res; + char request[MAX_URL+15]; + int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR; + char keyid[17]; + char line[MAX_LINE]; + char *key=NULL,*encoded_key=NULL; + size_t keylen=0,keymax=0; + + /* Read and throw away input until we see the BEGIN */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) + { + begin=1; + break; + } + + if(!begin) + { + /* i.e. eof before the KEY BEGIN was found. This isn't an + error. */ + *eof=1; + ret=KEYSERVER_OK; + goto fail; + } + + /* Now slurp up everything until we see the END */ + + while(fgets(line,MAX_LINE,input)) + if(sscanf(line,"KEY %16s END\n",keyid)==1) + { + end=1; + break; + } + else + { + if(strlen(line)+keylen>keymax) + { + char *tmp; + + keymax+=200; + tmp=realloc(key,keymax+1); + if(!tmp) + { + free(key); + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + key=tmp; + } + + strcpy(&key[keylen],line); + keylen+=strlen(line); + } + + if(!end) + { + fprintf(console,"gpgkeys: no KEY %s END found\n",keyid); + *eof=1; + ret=KEYSERVER_KEY_INCOMPLETE; + goto fail; + } + + encoded_key=curl_escape(key,keylen); + if(!encoded_key) + { + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + free(key); + + key=malloc(8+strlen(encoded_key)+1); + if(!key) + { + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + strcpy(key,"keytext="); + strcat(key,encoded_key); + + strcpy(request,"http://"); + strcat(request,opt->host); + strcat(request,":"); + if(opt->port) + strcat(request,opt->port); + else + strcat(request,"11371"); + strcat(request,opt->path); + /* request is MAX_URL+15 bytes long - MAX_URL covers the whole URL, + including any supplied path. The 15 covers /pks/add. */ + append_path(request,"/pks/add"); + + if(opt->verbose>2) + fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request); + + curl_easy_setopt(curl,CURLOPT_URL,request); + curl_easy_setopt(curl,CURLOPT_POST,1); + curl_easy_setopt(curl,CURLOPT_POSTFIELDS,key); + curl_easy_setopt(curl,CURLOPT_FAILONERROR,1); + + res=curl_easy_perform(curl); + if(res!=0) + { + fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer); + ret=curl_err_to_gpg_err(res); + } + else + fprintf(output,"\nKEY %s SENT\n",keyid); + + ret=KEYSERVER_OK; + + fail: + free(key); + curl_free(encoded_key); + + if(ret!=0 && begin) + fprintf(output,"KEY %s FAILED %d\n",keyid,ret); + + return ret; +} + +static int +get_key(char *getkey) +{ + CURLcode res; + char request[MAX_URL+60]; + char *offset; + struct curl_writer_ctx ctx; + + memset(&ctx,0,sizeof(ctx)); + + /* Build the search string. HKP only uses the short key IDs. */ + + if(strncmp(getkey,"0x",2)==0) + getkey+=2; + + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + + if(strlen(getkey)==32) + { + fprintf(console, + "gpgkeys: HKP keyservers do not support v3 fingerprints\n"); + fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED); + return KEYSERVER_NOT_SUPPORTED; + } + + strcpy(request,"http://"); + strcat(request,opt->host); + strcat(request,":"); + if(opt->port) + strcat(request,opt->port); + else + strcat(request,"11371"); + strcat(request,opt->path); + /* request is MAX_URL+55 bytes long - MAX_URL covers the whole URL, + including any supplied path. The 60 overcovers this /pks/... etc + string plus the 8 bytes of key id */ + append_path(request,"/pks/lookup?op=get&options=mr&search=0x"); + + /* fingerprint or long key id. Take the last 8 characters and treat + it like a short key id */ + if(strlen(getkey)>8) + offset=&getkey[strlen(getkey)-8]; + else + offset=getkey; + + strcat(request,offset); + + if(opt->verbose>2) + fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request); + + curl_easy_setopt(curl,CURLOPT_URL,request); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer); + ctx.stream=output; + curl_easy_setopt(curl,CURLOPT_FILE,&ctx); + + res=curl_easy_perform(curl); + if(res!=CURLE_OK) + { + fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer); + fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res)); + } + else + { + curl_writer_finalize(&ctx); + if(!ctx.flags.done) + { + fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey); + fprintf(output,"\nKEY 0x%s FAILED %d\n", + getkey,KEYSERVER_KEY_NOT_FOUND); + } + else + fprintf(output,"\nKEY 0x%s END\n",getkey); + } + + return KEYSERVER_OK; +} + +static int +get_name(const char *getkey) +{ + CURLcode res; + char *request=NULL; + char *searchkey_encoded; + int ret=KEYSERVER_INTERNAL_ERROR; + struct curl_writer_ctx ctx; + + memset(&ctx,0,sizeof(ctx)); + + searchkey_encoded=curl_escape((char *)getkey,0); + if(!searchkey_encoded) + { + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + request=malloc(MAX_URL+60+strlen(searchkey_encoded)); + if(!request) + { + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + fprintf(output,"NAME %s BEGIN\n",getkey); + + strcpy(request,"http://"); + strcat(request,opt->host); + strcat(request,":"); + if(opt->port) + strcat(request,opt->port); + else + strcat(request,"11371"); + strcat(request,opt->path); + append_path(request,"/pks/lookup?op=get&options=mr&search="); + strcat(request,searchkey_encoded); + + if(opt->action==KS_GETNAME) + strcat(request,"&exact=on"); + + if(opt->verbose>2) + fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request); + + curl_easy_setopt(curl,CURLOPT_URL,request); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer); + ctx.stream=output; + curl_easy_setopt(curl,CURLOPT_FILE,&ctx); + + res=curl_easy_perform(curl); + if(res!=CURLE_OK) + { + fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer); + ret=curl_err_to_gpg_err(res); + } + else + { + curl_writer_finalize(&ctx); + if(!ctx.flags.done) + { + fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey); + ret=KEYSERVER_KEY_NOT_FOUND; + } + else + { + fprintf(output,"\nNAME %s END\n",getkey); + ret=KEYSERVER_OK; + } + } + + fail: + curl_free(searchkey_encoded); + free(request); + + if(ret!=KEYSERVER_OK) + fprintf(output,"\nNAME %s FAILED %d\n",getkey,ret); + + return ret; +} + +static int +search_key(const char *searchkey) +{ + CURLcode res; + char *request=NULL; + char *searchkey_encoded; + int ret=KEYSERVER_INTERNAL_ERROR; + enum ks_search_type search_type; + + search_type=classify_ks_search(&searchkey); + + if(opt->debug) + fprintf(console,"gpgkeys: search type is %d, and key is \"%s\"\n", + search_type,searchkey); + + searchkey_encoded=curl_escape((char *)searchkey,0); + if(!searchkey_encoded) + { + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + request=malloc(MAX_URL+60+strlen(searchkey_encoded)); + if(!request) + { + fprintf(console,"gpgkeys: out of memory\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + fprintf(output,"SEARCH %s BEGIN\n",searchkey); + + strcpy(request,"http://"); + strcat(request,opt->host); + strcat(request,":"); + if(opt->port) + strcat(request,opt->port); + else + strcat(request,"11371"); + strcat(request,opt->path); + append_path(request,"/pks/lookup?op=index&options=mr&search="); + strcat(request,searchkey_encoded); + + if(search_type!=KS_SEARCH_SUBSTR) + strcat(request,"&exact=on"); + + if(opt->verbose>2) + fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request); + + curl_easy_setopt(curl,CURLOPT_URL,request); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer); + curl_easy_setopt(curl,CURLOPT_FILE,output); + + res=curl_easy_perform(curl); + if(res!=0) + { + fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer); + ret=curl_err_to_gpg_err(res); + } + else + { + fprintf(output,"\nSEARCH %s END\n",searchkey); + ret=KEYSERVER_OK; + } + + fail: + + curl_free(searchkey_encoded); + free(request); + + if(ret!=KEYSERVER_OK) + fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret); + + return ret; +} + +void +fail_all(struct keylist *keylist,int err) +{ + if(!keylist) + return; + + if(opt->action==KS_SEARCH) + { + fprintf(output,"SEARCH "); + while(keylist) + { + fprintf(output,"%s ",keylist->str); + keylist=keylist->next; + } + fprintf(output,"FAILED %d\n",err); + } + else + while(keylist) + { + fprintf(output,"KEY %s FAILED %d\n",keylist->str,err); + keylist=keylist->next; + } +} + +static void +show_help (FILE *fp) +{ + fprintf (fp,"-h\thelp\n"); + fprintf (fp,"-V\tversion\n"); + fprintf (fp,"-o\toutput to this file\n"); +} + +int +main(int argc,char *argv[]) +{ + int arg,ret=KEYSERVER_INTERNAL_ERROR; + char line[MAX_LINE]; + int failed=0; + struct keylist *keylist=NULL,*keyptr=NULL; + char *proxy=NULL; + + console=stderr; + + /* Kludge to implement standard GNU options. */ + if (argc > 1 && !strcmp (argv[1], "--version")) + { + fputs ("gpgkeys_hkp (GnuPG) " VERSION"\n", stdout); + return 0; + } + else if (argc > 1 && !strcmp (argv[1], "--help")) + { + show_help (stdout); + return 0; + } + + while((arg=getopt(argc,argv,"hVo:"))!=-1) + switch(arg) + { + default: + case 'h': + show_help (console); + return KEYSERVER_OK; + + case 'V': + fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION); + return KEYSERVER_OK; + + case 'o': + output=fopen(optarg,"w"); + if(output==NULL) + { + fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n", + optarg,strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + + break; + } + + if(argc>optind) + { + input=fopen(argv[optind],"r"); + if(input==NULL) + { + fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n", + argv[optind],strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + } + + if(input==NULL) + input=stdin; + + if(output==NULL) + output=stdout; + + opt=init_ks_options(); + if(!opt) + return KEYSERVER_NO_MEMORY; + + /* Get the command and info block */ + + while(fgets(line,MAX_LINE,input)!=NULL) + { + int err; + char option[MAX_OPTION+1]; + + if(line[0]=='\n') + break; + + err=parse_ks_options(line,opt); + if(err>0) + { + ret=err; + goto fail; + } + else if(err==0) + continue; + + if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1) + { + int no=0; + char *start=&option[0]; + + option[MAX_OPTION]='\0'; + + if(strncasecmp(option,"no-",3)==0) + { + no=1; + start=&option[3]; + } + + if(strncasecmp(start,"http-proxy",10)==0) + { + if(no) + { + free(proxy); + proxy=strdup(""); + } + else if(start[10]=='=') + { + if(strlen(&start[11])<MAX_PROXY) + { + free(proxy); + proxy=strdup(&start[11]); + } + } + } +#if 0 + else if(strcasecmp(start,"try-dns-srv")==0) + { + if(no) + http_flags&=~HTTP_FLAG_TRY_SRV; + else + http_flags|=HTTP_FLAG_TRY_SRV; + } +#endif + continue; + } + } + + if(!opt->host) + { + fprintf(console,"gpgkeys: no keyserver host provided\n"); + goto fail; + } + + if(opt->timeout && register_timeout()==-1) + { + fprintf(console,"gpgkeys: unable to register timeout handler\n"); + return KEYSERVER_INTERNAL_ERROR; + } + + curl_global_init(CURL_GLOBAL_DEFAULT); + curl=curl_easy_init(); + if(!curl) + { + fprintf(console,"gpgkeys: unable to initialize curl\n"); + ret=KEYSERVER_INTERNAL_ERROR; + goto fail; + } + + curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer); + + if(opt->auth) + curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth); + + if(opt->debug) + { + fprintf(console,"gpgkeys: curl version = %s\n",curl_version()); + curl_easy_setopt(curl,CURLOPT_STDERR,console); + curl_easy_setopt(curl,CURLOPT_VERBOSE,1); + } + + if(proxy) + curl_easy_setopt(curl,CURLOPT_PROXY,proxy); + +#if 0 + /* By suggested convention, if the user gives a :port, then disable + SRV. */ + if(opt->port) + http_flags&=~HTTP_FLAG_TRY_SRV; +#endif + + /* If it's a GET or a SEARCH, the next thing to come in is the + keyids. If it's a SEND, then there are no keyids. */ + + if(opt->action==KS_SEND) + while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n'); + else if(opt->action==KS_GET + || opt->action==KS_GETNAME || opt->action==KS_SEARCH) + { + for(;;) + { + struct keylist *work; + + if(fgets(line,MAX_LINE,input)==NULL) + break; + else + { + if(line[0]=='\n' || line[0]=='\0') + break; + + work=malloc(sizeof(struct keylist)); + if(work==NULL) + { + fprintf(console,"gpgkeys: out of memory while " + "building key list\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + strcpy(work->str,line); + + /* Trim the trailing \n */ + work->str[strlen(line)-1]='\0'; + + work->next=NULL; + + /* Always attach at the end to keep the list in proper + order for searching */ + if(keylist==NULL) + keylist=work; + else + keyptr->next=work; + + keyptr=work; + } + } + } + else + { + fprintf(console,"gpgkeys: no keyserver command specified\n"); + goto fail; + } + + /* Send the response */ + + fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(output,"PROGRAM %s\n\n",VERSION); + + if(opt->verbose>1) + { + fprintf(console,"Host:\t\t%s\n",opt->host); + if(opt->port) + fprintf(console,"Port:\t\t%s\n",opt->port); + if(strcmp(opt->path,"/")!=0) + fprintf(console,"Path:\t\t%s\n",opt->path); + fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action)); + } + + if(opt->action==KS_GET) + { + keyptr=keylist; + + while(keyptr!=NULL) + { + set_timeout(opt->timeout); + + if(get_key(keyptr->str)!=KEYSERVER_OK) + failed++; + + keyptr=keyptr->next; + } + } + else if(opt->action==KS_GETNAME) + { + keyptr=keylist; + + while(keyptr!=NULL) + { + set_timeout(opt->timeout); + + if(get_name(keyptr->str)!=KEYSERVER_OK) + failed++; + + keyptr=keyptr->next; + } + } + else if(opt->action==KS_SEND) + { + int eof=0; + + do + { + set_timeout(opt->timeout); + + if(send_key(&eof)!=KEYSERVER_OK) + failed++; + } + while(!eof); + } + else if(opt->action==KS_SEARCH) + { + char *searchkey=NULL; + int len=0; + + set_timeout(opt->timeout); + + /* To search, we stick a space in between each key to search + for. */ + + keyptr=keylist; + while(keyptr!=NULL) + { + len+=strlen(keyptr->str)+1; + keyptr=keyptr->next; + } + + searchkey=malloc(len+1); + if(searchkey==NULL) + { + ret=KEYSERVER_NO_MEMORY; + fail_all(keylist,KEYSERVER_NO_MEMORY); + goto fail; + } + + searchkey[0]='\0'; + + keyptr=keylist; + while(keyptr!=NULL) + { + strcat(searchkey,keyptr->str); + strcat(searchkey," "); + keyptr=keyptr->next; + } + + /* Nail that last space */ + if(*searchkey) + searchkey[strlen(searchkey)-1]='\0'; + + if(search_key(searchkey)!=KEYSERVER_OK) + failed++; + + free(searchkey); + } + else + abort(); + + if(!failed) + ret=KEYSERVER_OK; + + fail: + while(keylist!=NULL) + { + struct keylist *current=keylist; + keylist=keylist->next; + free(current); + } + + if(input!=stdin) + fclose(input); + + if(output!=stdout) + fclose(output); + + free_ks_options(opt); + + if(curl) + curl_easy_cleanup(curl); + + free(proxy); + + return ret; +} diff --git a/keyserver/gpgkeys_ldap.c b/keyserver/gpgkeys_ldap.c new file mode 100644 index 000000000..b4bd00e4f --- /dev/null +++ b/keyserver/gpgkeys_ldap.c @@ -0,0 +1,2350 @@ +/* gpgkeys_ldap.c - talk to a LDAP keyserver + * Copyright (C) 2001, 2002, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif +#include <stdlib.h> +#include <errno.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <winldap.h> +#else +#ifdef NEED_LBER_H +#include <lber.h> +#endif +/* For OpenLDAP, to enable the API that we're using. */ +#define LDAP_DEPRECATED 1 +#include <ldap.h> +#endif + +#include "util.h" +#include "keyserver.h" +#include "ksutil.h" + +#ifdef __riscos__ +#include "util.h" +#endif + +extern char *optarg; +extern int optind; + +static int real_ldap=0; +static char *basekeyspacedn=NULL; +static char *pgpkeystr="pgpKey"; +static FILE *input=NULL,*output=NULL,*console=NULL; +static LDAP *ldap=NULL; +static struct ks_options *opt; + +#ifndef HAVE_TIMEGM +time_t timegm(struct tm *tm); +#endif + +static int +ldap_err_to_gpg_err(int err) +{ + int ret; + + switch(err) + { + case LDAP_ALREADY_EXISTS: + ret=KEYSERVER_KEY_EXISTS; + break; + + case LDAP_SERVER_DOWN: + ret=KEYSERVER_UNREACHABLE; + break; + + default: + ret=KEYSERVER_GENERAL_ERROR; + break; + } + + return ret; +} + +static int +ldap_to_gpg_err(LDAP *ld) +{ +#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) + + int err; + + if(ldap_get_option(ld,LDAP_OPT_ERROR_NUMBER,&err)==0) + return ldap_err_to_gpg_err(err); + else + return KEYSERVER_GENERAL_ERROR; + +#elif defined(HAVE_LDAP_LD_ERRNO) + + return ldap_err_to_gpg_err(ld->ld_errno); + +#else + + /* We should never get here since the LDAP library should always + have either ldap_get_option or ld_errno, but just in case... */ + return KEYSERVER_GENERAL_ERROR; + +#endif +} + +static int +key_in_keylist(const char *key,struct keylist *list) +{ + struct keylist *keyptr=list; + + while(keyptr!=NULL) + { + if(strcasecmp(key,keyptr->str)==0) + return 1; + + keyptr=keyptr->next; + } + + return 0; +} + +static int +add_key_to_keylist(const char *key,struct keylist **list) +{ + struct keylist *keyptr=malloc(sizeof(struct keylist)); + + if(keyptr==NULL) + { + fprintf(console,"gpgkeys: out of memory when deduping " + "key list\n"); + return KEYSERVER_NO_MEMORY; + } + + strncpy(keyptr->str,key,MAX_LINE); + keyptr->str[MAX_LINE-1]='\0'; + keyptr->next=*list; + *list=keyptr; + + return 0; +} + +static void +free_keylist(struct keylist *list) +{ + while(list!=NULL) + { + struct keylist *keyptr=list; + + list=keyptr->next; + free(keyptr); + } +} + +static time_t +ldap2epochtime(const char *timestr) +{ + struct tm pgptime; + time_t answer; + + memset(&pgptime,0,sizeof(pgptime)); + + /* YYYYMMDDHHmmssZ */ + + sscanf(timestr,"%4d%2d%2d%2d%2d%2d", + &pgptime.tm_year, + &pgptime.tm_mon, + &pgptime.tm_mday, + &pgptime.tm_hour, + &pgptime.tm_min, + &pgptime.tm_sec); + + pgptime.tm_year-=1900; + pgptime.tm_isdst=-1; + pgptime.tm_mon--; + + /* mktime() takes the timezone into account, so we use timegm() */ + + answer=timegm(&pgptime); + + return answer; +} + +/* Caller must free */ +static char * +epoch2ldaptime(time_t stamp) +{ + struct tm *ldaptime; + char buf[16]; + + ldaptime=gmtime(&stamp); + + ldaptime->tm_year+=1900; + ldaptime->tm_mon++; + + /* YYYYMMDDHHmmssZ */ + + sprintf(buf,"%04d%02d%02d%02d%02d%02dZ", + ldaptime->tm_year, + ldaptime->tm_mon, + ldaptime->tm_mday, + ldaptime->tm_hour, + ldaptime->tm_min, + ldaptime->tm_sec); + + return strdup(buf); +} + +/* Append two onto the end of one. Two is not freed, but its pointers + are now part of one. Make sure you don't free them both! */ +static int +join_two_modlists(LDAPMod ***one,LDAPMod **two) +{ + int i,one_count=0,two_count=0; + LDAPMod **grow; + + for(grow=*one;*grow;grow++) + one_count++; + + for(grow=two;*grow;grow++) + two_count++; + + grow=realloc(*one,sizeof(LDAPMod *)*(one_count+two_count+1)); + if(!grow) + return 0; + + for(i=0;i<two_count;i++) + grow[one_count+i]=two[i]; + + grow[one_count+i]=NULL; + + *one=grow; + + return 1; +} + +/* Passing a NULL for value effectively deletes that attribute. This + doesn't mean "delete" in the sense of removing something from the + modlist, but "delete" in the LDAP sense of adding a modlist item + that specifies LDAP_MOD_REPLACE and a null attribute for the given + attribute. LDAP_MOD_DELETE doesn't work here as we don't know if + the attribute in question exists or not. */ + +static int +make_one_attr(LDAPMod ***modlist,char *attr,const char *value) +{ + LDAPMod **m; + int nummods=0; + + /* Search modlist for the attribute we're playing with. */ + for(m=*modlist;*m;m++) + { + if(strcasecmp((*m)->mod_type,attr)==0) + { + char **ptr=(*m)->mod_values; + int numvalues=0; + + /* We have this attribute already, so when the REPLACE + happens, the server attributes will be replaced + anyway. */ + if(!value) + return 1; + + if(ptr) + for(ptr=(*m)->mod_values;*ptr;ptr++) + { + /* Duplicate value */ + if(strcmp(*ptr,value)==0) + return 1; + numvalues++; + } + + ptr=realloc((*m)->mod_values,sizeof(char *)*(numvalues+2)); + if(!ptr) + return 0; + + (*m)->mod_values=ptr; + ptr[numvalues]=strdup(value); + if(!ptr[numvalues]) + return 0; + + ptr[numvalues+1]=NULL; + break; + } + + nummods++; + } + + /* We didn't find the attr, so make one and add it to the end */ + if(!*m) + { + LDAPMod **grow; + + grow=realloc(*modlist,sizeof(LDAPMod *)*(nummods+2)); + if(!grow) + return 0; + + *modlist=grow; + grow[nummods]=malloc(sizeof(LDAPMod)); + if(!grow[nummods]) + return 0; + grow[nummods]->mod_op=LDAP_MOD_REPLACE; + grow[nummods]->mod_type=attr; + if(value) + { + grow[nummods]->mod_values=malloc(sizeof(char *)*2); + if(!grow[nummods]->mod_values) + { + grow[nummods]=NULL; + return 0; + } + + /* Is this the right thing? Can a UTF8-encoded user ID have + embedded nulls? */ + grow[nummods]->mod_values[0]=strdup(value); + if(!grow[nummods]->mod_values[0]) + { + free(grow[nummods]->mod_values); + grow[nummods]=NULL; + return 0; + } + + grow[nummods]->mod_values[1]=NULL; + } + else + grow[nummods]->mod_values=NULL; + + grow[nummods+1]=NULL; + } + + return 1; +} + +static void +build_attrs(LDAPMod ***modlist,char *line) +{ + char *record; + int i; + + /* Remove trailing whitespace */ + for(i=strlen(line);i>0;i--) + if(ascii_isspace(line[i-1])) + line[i-1]='\0'; + else + break; + + if((record=strsep(&line,":"))==NULL) + return; + + if(ascii_strcasecmp("pub",record)==0) + { + char *tok; + int disabled=0,revoked=0; + + /* The long keyid */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(strlen(tok)==16) + { + make_one_attr(modlist,"pgpCertID",tok); + make_one_attr(modlist,"pgpKeyID",&tok[8]); + } + else + return; + + /* The primary pubkey algo */ + if((tok=strsep(&line,":"))==NULL) + return; + + switch(atoi(tok)) + { + case 1: + make_one_attr(modlist,"pgpKeyType","RSA"); + break; + + case 17: + make_one_attr(modlist,"pgpKeyType","DSS/DH"); + break; + } + + /* Size of primary key */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(atoi(tok)>0) + { + char padded[6]; + int val=atoi(tok); + + /* We zero pad this on the left to make PGP happy. */ + + if(val<99999 && val>0) + { + sprintf(padded,"%05u",atoi(tok)); + make_one_attr(modlist,"pgpKeySize",padded); + } + } + + /* pk timestamp */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(atoi(tok)>0) + { + char *stamp=epoch2ldaptime(atoi(tok)); + if(stamp) + { + make_one_attr(modlist,"pgpKeyCreateTime",stamp); + free(stamp); + } + } + + /* pk expire */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(atoi(tok)>0) + { + char *stamp=epoch2ldaptime(atoi(tok)); + if(stamp) + { + make_one_attr(modlist,"pgpKeyExpireTime",stamp); + free(stamp); + } + } + + /* flags */ + if((tok=strsep(&line,":"))==NULL) + return; + + while(*tok) + switch(*tok++) + { + case 'r': + case 'R': + revoked=1; + break; + + case 'd': + case 'D': + disabled=1; + break; + } + + /* + Note that we always create the pgpDisabled and pgpRevoked + attributes, regardless of whether the key is disabled/revoked + or not. This is because a very common search is like + "(&(pgpUserID=*isabella*)(pgpDisabled=0))" + */ + + make_one_attr(modlist,"pgpDisabled",disabled?"1":"0"); + make_one_attr(modlist,"pgpRevoked",revoked?"1":"0"); + } + else if(ascii_strcasecmp("sub",record)==0) + { + char *tok; + + /* The long keyid */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(strlen(tok)==16) + make_one_attr(modlist,"pgpSubKeyID",tok); + else + return; + + /* The subkey algo */ + if((tok=strsep(&line,":"))==NULL) + return; + + /* Size of subkey */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(atoi(tok)>0) + { + char padded[6]; + int val=atoi(tok); + + /* We zero pad this on the left to make PGP happy. */ + + if(val<99999 && val>0) + { + sprintf(padded,"%05u",atoi(tok)); + make_one_attr(modlist,"pgpKeySize",padded); + } + } + + /* Ignore the rest of the items for subkeys since the LDAP + schema doesn't store them. */ + } + else if(ascii_strcasecmp("uid",record)==0) + { + char *userid,*tok; + + /* The user ID string */ + if((tok=strsep(&line,":"))==NULL) + return; + + if(strlen(tok)==0) + return; + + userid=tok; + + /* By definition, de-%-encoding is always smaller than the + original string so we can decode in place. */ + + i=0; + + while(*tok) + if(tok[0]=='%' && tok[1] && tok[2]) + { + if((userid[i]=hextobyte(&tok[1]))==-1) + userid[i]='?'; + + i++; + tok+=3; + } + else + userid[i++]=*tok++; + + userid[i]='\0'; + + /* We don't care about the other info provided in the uid: line + since the LDAP schema doesn't need it. */ + + make_one_attr(modlist,"pgpUserID",userid); + } + else if(ascii_strcasecmp("sig",record)==0) + { + char *tok; + + if((tok=strsep(&line,":"))==NULL) + return; + + if(strlen(tok)==16) + make_one_attr(modlist,"pgpSignerID",tok); + } +} + +static void +free_mod_values(LDAPMod *mod) +{ + char **ptr; + + if(!mod->mod_values) + return; + + for(ptr=mod->mod_values;*ptr;ptr++) + free(*ptr); + + free(mod->mod_values); +} + +static int +send_key(int *eof) +{ + int err,begin=0,end=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR; + char *dn=NULL,line[MAX_LINE],*key=NULL; + char keyid[17]; + LDAPMod **modlist,**addlist,**ml; + + modlist=malloc(sizeof(LDAPMod *)); + if(!modlist) + { + fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + *modlist=NULL; + + addlist=malloc(sizeof(LDAPMod *)); + if(!addlist) + { + fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + *addlist=NULL; + + /* Start by nulling out all attributes. We try and do a modify + operation first, so this ensures that we don't leave old + attributes lying around. */ + make_one_attr(&modlist,"pgpDisabled",NULL); + make_one_attr(&modlist,"pgpKeyID",NULL); + make_one_attr(&modlist,"pgpKeyType",NULL); + make_one_attr(&modlist,"pgpUserID",NULL); + make_one_attr(&modlist,"pgpKeyCreateTime",NULL); + make_one_attr(&modlist,"pgpSignerID",NULL); + make_one_attr(&modlist,"pgpRevoked",NULL); + make_one_attr(&modlist,"pgpSubKeyID",NULL); + make_one_attr(&modlist,"pgpKeySize",NULL); + make_one_attr(&modlist,"pgpKeyExpireTime",NULL); + make_one_attr(&modlist,"pgpCertID",NULL); + + /* Assemble the INFO stuff into LDAP attributes */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"INFO %16s BEGIN\n",keyid)==1) + { + begin=1; + break; + } + + if(!begin) + { + /* i.e. eof before the INFO BEGIN was found. This isn't an + error. */ + *eof=1; + ret=KEYSERVER_OK; + goto fail; + } + + if(strlen(keyid)!=16) + { + *eof=1; + ret=KEYSERVER_KEY_INCOMPLETE; + goto fail; + } + + dn=malloc(strlen("pgpCertID=")+16+1+strlen(basekeyspacedn)+1); + if(dn==NULL) + { + fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + sprintf(dn,"pgpCertID=%s,%s",keyid,basekeyspacedn); + + key=malloc(1); + if(!key) + { + fprintf(console,"gpgkeys: unable to allocate memory for key\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + key[0]='\0'; + + /* Now parse each line until we see the END */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"INFO %16s END\n",keyid)==1) + { + end=1; + break; + } + else + build_attrs(&addlist,line); + + if(!end) + { + fprintf(console,"gpgkeys: no INFO %s END found\n",keyid); + *eof=1; + ret=KEYSERVER_KEY_INCOMPLETE; + goto fail; + } + + begin=end=0; + + /* Read and throw away stdin until we see the BEGIN */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) + { + begin=1; + break; + } + + if(!begin) + { + /* i.e. eof before the KEY BEGIN was found. This isn't an + error. */ + *eof=1; + ret=KEYSERVER_OK; + goto fail; + } + + /* Now slurp up everything until we see the END */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"KEY %16s END\n",keyid)==1) + { + end=1; + break; + } + else + { + char *tempkey; + keysize+=strlen(line); + tempkey=realloc(key,keysize); + if(tempkey==NULL) + { + fprintf(console,"gpgkeys: unable to reallocate for key\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + else + key=tempkey; + + strcat(key,line); + } + + if(!end) + { + fprintf(console,"gpgkeys: no KEY %s END found\n",keyid); + *eof=1; + ret=KEYSERVER_KEY_INCOMPLETE; + goto fail; + } + + make_one_attr(&addlist,"objectClass","pgpKeyInfo"); + make_one_attr(&addlist,"pgpKey",key); + + /* Now append addlist onto modlist */ + if(!join_two_modlists(&modlist,addlist)) + { + fprintf(console,"gpgkeys: unable to merge LDAP modification lists\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + /* Going on the assumption that modify operations are more frequent + than adds, we try a modify first. If it's not there, we just + turn around and send an add command for the same key. Otherwise, + the modify brings the server copy into compliance with our copy. + Note that unlike the LDAP keyserver (and really, any other + keyserver) this does NOT merge signatures, but replaces the whole + key. This should make some people very happy. */ + + err=ldap_modify_s(ldap,dn,modlist); + if(err==LDAP_NO_SUCH_OBJECT) + err=ldap_add_s(ldap,dn,addlist); + + if(err!=LDAP_SUCCESS) + { + fprintf(console,"gpgkeys: error adding key %s to keyserver: %s\n", + keyid,ldap_err2string(err)); + ret=ldap_err_to_gpg_err(err); + goto fail; + } + + ret=KEYSERVER_OK; + + fail: + /* Unwind and free the whole modlist structure */ + for(ml=modlist;*ml;ml++) + { + free_mod_values(*ml); + free(*ml); + } + + free(modlist); + free(addlist); + free(dn); + + if(ret!=0 && begin) + fprintf(output,"KEY %s FAILED %d\n",keyid,ret); + + return ret; +} + +static int +send_key_keyserver(int *eof) +{ + int err,begin=0,end=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR; + char *dn=NULL,line[MAX_LINE],*key[2]={NULL,NULL}; + char keyid[17]; + LDAPMod mod, *attrs[2]; + + memset(&mod,0,sizeof(mod)); + mod.mod_op=LDAP_MOD_ADD; + mod.mod_type=pgpkeystr; + mod.mod_values=key; + attrs[0]=&mod; + attrs[1]=NULL; + + dn=malloc(strlen("pgpCertid=virtual,")+strlen(basekeyspacedn)+1); + if(dn==NULL) + { + fprintf(console,"gpgkeys: can't allocate memory for keyserver record\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + strcpy(dn,"pgpCertid=virtual,"); + strcat(dn,basekeyspacedn); + + key[0]=malloc(1); + if(key[0]==NULL) + { + fprintf(console,"gpgkeys: unable to allocate memory for key\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + key[0][0]='\0'; + + /* Read and throw away stdin until we see the BEGIN */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) + { + begin=1; + break; + } + + if(!begin) + { + /* i.e. eof before the KEY BEGIN was found. This isn't an + error. */ + *eof=1; + ret=KEYSERVER_OK; + goto fail; + } + + /* Now slurp up everything until we see the END */ + + while(fgets(line,MAX_LINE,input)!=NULL) + if(sscanf(line,"KEY %16s END\n",keyid)==1) + { + end=1; + break; + } + else + { + keysize+=strlen(line); + key[0]=realloc(key[0],keysize); + if(key[0]==NULL) + { + fprintf(console,"gpgkeys: unable to reallocate for key\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + strcat(key[0],line); + } + + if(!end) + { + fprintf(console,"gpgkeys: no KEY %s END found\n",keyid); + *eof=1; + ret=KEYSERVER_KEY_INCOMPLETE; + goto fail; + } + + err=ldap_add_s(ldap,dn,attrs); + if(err!=LDAP_SUCCESS) + { + fprintf(console,"gpgkeys: error adding key %s to keyserver: %s\n", + keyid,ldap_err2string(err)); + ret=ldap_err_to_gpg_err(err); + goto fail; + } + + ret=KEYSERVER_OK; + + fail: + + free(key[0]); + free(dn); + + if(ret!=0 && begin) + fprintf(output,"KEY %s FAILED %d\n",keyid,ret); + + /* Not a fatal error */ + if(ret==KEYSERVER_KEY_EXISTS) + ret=KEYSERVER_OK; + + return ret; +} + +static void +build_info(const char *certid,LDAPMessage *each) +{ + char **vals; + + fprintf(output,"INFO %s BEGIN\n",certid); + + fprintf(output,"pub:%s:",certid); + + vals=ldap_get_values(ldap,each,"pgpkeytype"); + if(vals!=NULL) + { + if(strcmp(vals[0],"RSA")==0) + fprintf(output,"1"); + else if(strcmp(vals[0],"DSS/DH")==0) + fprintf(output,"17"); + ldap_value_free(vals); + } + + fprintf(output,":"); + + vals=ldap_get_values(ldap,each,"pgpkeysize"); + if(vals!=NULL) + { + if(atoi(vals[0])>0) + fprintf(output,"%d",atoi(vals[0])); + ldap_value_free(vals); + } + + fprintf(output,":"); + + vals=ldap_get_values(ldap,each,"pgpkeycreatetime"); + if(vals!=NULL) + { + if(strlen(vals[0])==15) + fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0])); + ldap_value_free(vals); + } + + fprintf(output,":"); + + vals=ldap_get_values(ldap,each,"pgpkeyexpiretime"); + if(vals!=NULL) + { + if(strlen(vals[0])==15) + fprintf(output,"%u",(unsigned int)ldap2epochtime(vals[0])); + ldap_value_free(vals); + } + + fprintf(output,":"); + + vals=ldap_get_values(ldap,each,"pgprevoked"); + if(vals!=NULL) + { + if(atoi(vals[0])==1) + fprintf(output,"r"); + ldap_value_free(vals); + } + + fprintf(output,"\n"); + + vals=ldap_get_values(ldap,each,"pgpuserid"); + if(vals!=NULL) + { + int i; + + for(i=0;vals[i];i++) + fprintf(output,"uid:%s\n",vals[i]); + ldap_value_free(vals); + } + + fprintf(output,"INFO %s END\n",certid); +} + +/* Note that key-not-found is not a fatal error */ +static int +get_key(char *getkey) +{ + LDAPMessage *res,*each; + int ret=KEYSERVER_INTERNAL_ERROR,err,count; + struct keylist *dupelist=NULL; + char search[62]; + /* This ordering is significant - specifically, "pgpcertid" needs to + be the second item in the list, since everything after it may be + discarded if the user isn't in verbose mode. */ + char *attrs[]={"replaceme","pgpcertid","pgpuserid","pgpkeyid","pgprevoked", + "pgpdisabled","pgpkeycreatetime","modifytimestamp", + "pgpkeysize","pgpkeytype",NULL}; + attrs[0]=pgpkeystr; /* Some compilers don't like using variables as + array initializers. */ + + /* Build the search string */ + + /* GPG can send us a v4 fingerprint, a v3 or v4 long key id, or a v3 + or v4 short key id */ + + if(strncmp(getkey,"0x",2)==0) + getkey+=2; + + if(strlen(getkey)==32) + { + fprintf(console, + "gpgkeys: LDAP keyservers do not support v3 fingerprints\n"); + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED); + return KEYSERVER_NOT_SUPPORTED; + } + + if(strlen(getkey)>16) + { + char *offset=&getkey[strlen(getkey)-16]; + + /* fingerprint. Take the last 16 characters and treat it like a + long key id */ + + if(opt->flags.include_subkeys) + sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))", + offset,offset); + else + sprintf(search,"(pgpcertid=%.16s)",offset); + } + else if(strlen(getkey)>8) + { + /* long key id */ + + if(opt->flags.include_subkeys) + sprintf(search,"(|(pgpcertid=%.16s)(pgpsubkeyid=%.16s))", + getkey,getkey); + else + sprintf(search,"(pgpcertid=%.16s)",getkey); + } + else + { + /* short key id */ + + sprintf(search,"(pgpkeyid=%.8s)",getkey); + } + + if(opt->verbose>2) + fprintf(console,"gpgkeys: LDAP fetch for: %s\n",search); + + if(!opt->verbose) + attrs[2]=NULL; /* keep only pgpkey(v2) and pgpcertid */ + + err=ldap_search_s(ldap,basekeyspacedn, + LDAP_SCOPE_SUBTREE,search,attrs,0,&res); + if(err!=0) + { + int errtag=ldap_err_to_gpg_err(err); + + fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err)); + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag); + return errtag; + } + + count=ldap_count_entries(ldap,res); + if(count<1) + { + fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey); + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND); + } + else + { + /* There may be more than one unique result for a given keyID, + so we should fetch them all (test this by fetching short key + id 0xDEADBEEF). */ + + each=ldap_first_entry(ldap,res); + while(each!=NULL) + { + char **vals,**certid; + + /* Use the long keyid to remove duplicates. The LDAP server + returns the same keyid more than once if there are + multiple user IDs on the key. Note that this does NOT + mean that a keyid that exists multiple times on the + keyserver will not be fetched. It means that each KEY, + no matter how many user IDs share its keyid, will be + fetched only once. If a keyid that belongs to more than + one key is fetched, the server quite properly responds + with all matching keys. -ds */ + + certid=ldap_get_values(ldap,each,"pgpcertid"); + if(certid!=NULL) + { + if(!key_in_keylist(certid[0],dupelist)) + { + /* it's not a duplicate, so add it */ + + int rc=add_key_to_keylist(certid[0],&dupelist); + if(rc) + { + ret=rc; + goto fail; + } + + build_info(certid[0],each); + + fprintf(output,"KEY 0x%s BEGIN\n",getkey); + + vals=ldap_get_values(ldap,each,pgpkeystr); + if(vals==NULL) + { + int errtag=ldap_to_gpg_err(ldap); + + fprintf(console,"gpgkeys: unable to retrieve key %s " + "from keyserver\n",getkey); + fprintf(output,"KEY 0x%s FAILED %d\n",getkey,errtag); + } + else + { + print_nocr(output,vals[0]); + fprintf(output,"\nKEY 0x%s END\n",getkey); + + ldap_value_free(vals); + } + } + + ldap_value_free(certid); + } + + each=ldap_next_entry(ldap,each); + } + } + + ret=KEYSERVER_OK; + + fail: + ldap_msgfree(res); + free_keylist(dupelist); + + return ret; +} + +#define LDAP_ESCAPE_CHARS "*()\\" + +/* Append string to buffer in a LDAP-quoted way */ +static void +ldap_quote(char *buffer,const char *string) +{ + /* Find the end of buffer */ + buffer+=strlen(buffer); + + for(;*string;string++) + { + if(strchr(LDAP_ESCAPE_CHARS,*string)) + { + sprintf(buffer,"\\%02X",*string); + buffer+=3; + } + else + *buffer++=*string; + } + + *buffer='\0'; +} + +/* Note that key-not-found is not a fatal error */ +static int +get_name(char *getkey) +{ + LDAPMessage *res,*each; + int ret=KEYSERVER_INTERNAL_ERROR,err,count; + /* The maximum size of the search, including the optional stuff and + the trailing \0 */ + char search[2+12+(MAX_LINE*3)+2+15+14+1+1+20]; + /* This ordering is significant - specifically, "pgpcertid" needs to + be the second item in the list, since everything after it may be + discarded if the user isn't in verbose mode. */ + char *attrs[]={"replaceme","pgpcertid","pgpuserid","pgpkeyid","pgprevoked", + "pgpdisabled","pgpkeycreatetime","modifytimestamp", + "pgpkeysize","pgpkeytype",NULL}; + attrs[0]=pgpkeystr; /* Some compilers don't like using variables as + array initializers. */ + + /* Build the search string */ + + search[0]='\0'; + + if(!opt->flags.include_disabled || !opt->flags.include_revoked) + strcat(search,"(&"); + + strcat(search,"(pgpUserID=*"); + ldap_quote(search,getkey); + strcat(search,"*)"); + + if(!opt->flags.include_disabled) + strcat(search,"(pgpDisabled=0)"); + + if(!opt->flags.include_revoked) + strcat(search,"(pgpRevoked=0)"); + + if(!opt->flags.include_disabled || !opt->flags.include_revoked) + strcat(search,")"); + + if(opt->verbose>2) + fprintf(console,"gpgkeys: LDAP fetch for: %s\n",search); + + if(!opt->verbose) + attrs[2]=NULL; /* keep only pgpkey(v2) and pgpcertid */ + + err=ldap_search_s(ldap,basekeyspacedn, + LDAP_SCOPE_SUBTREE,search,attrs,0,&res); + if(err!=0) + { + int errtag=ldap_err_to_gpg_err(err); + + fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err)); + fprintf(output,"NAME %s BEGIN\n",getkey); + fprintf(output,"NAME %s FAILED %d\n",getkey,errtag); + return errtag; + } + + count=ldap_count_entries(ldap,res); + if(count<1) + { + fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey); + fprintf(output,"NAME %s BEGIN\n",getkey); + fprintf(output,"NAME %s FAILED %d\n",getkey,KEYSERVER_KEY_NOT_FOUND); + } + else + { + /* There may be more than one result, but we return them all. */ + + each=ldap_first_entry(ldap,res); + while(each!=NULL) + { + char **vals,**certid; + + certid=ldap_get_values(ldap,each,"pgpcertid"); + if(certid!=NULL) + { + build_info(certid[0],each); + + fprintf(output,"NAME %s BEGIN\n",getkey); + + vals=ldap_get_values(ldap,each,pgpkeystr); + if(vals==NULL) + { + int errtag=ldap_to_gpg_err(ldap); + + fprintf(console,"gpgkeys: unable to retrieve key %s " + "from keyserver\n",getkey); + fprintf(output,"NAME %s FAILED %d\n",getkey,errtag); + } + else + { + print_nocr(output,vals[0]); + fprintf(output,"\nNAME %s END\n",getkey); + + ldap_value_free(vals); + } + + ldap_value_free(certid); + } + + each=ldap_next_entry(ldap,each); + } + } + + ret=KEYSERVER_OK; + + ldap_msgfree(res); + + return ret; +} + +static void +printquoted(FILE *stream,char *string,char delim) +{ + while(*string) + { + if(*string==delim || *string=='%') + fprintf(stream,"%%%02x",*string); + else + fputc(*string,stream); + + string++; + } +} + +/* Returns 0 on success and -1 on error. Note that key-not-found is + not an error! */ +static int +search_key(const char *searchkey) +{ + char **vals; + LDAPMessage *res,*each; + int err,count=0; + struct keylist *dupelist=NULL; + /* The maximum size of the search, including the optional stuff and + the trailing \0 */ + char search[2+1+9+1+3+(MAX_LINE*3)+3+1+15+14+1+1+20]; + char *attrs[]={"pgpcertid","pgpuserid","pgprevoked","pgpdisabled", + "pgpkeycreatetime","pgpkeyexpiretime","modifytimestamp", + "pgpkeysize","pgpkeytype",NULL}; + enum ks_search_type search_type; + + fprintf(output,"SEARCH %s BEGIN\n",searchkey); + + search_type=classify_ks_search(&searchkey); + + if(opt->debug) + fprintf(console,"search type is %d, and key is \"%s\"\n", + search_type,searchkey); + + /* Build the search string */ + + search[0]='\0'; + + if(!opt->flags.include_disabled || !opt->flags.include_revoked) + strcat(search,"(&"); + + strcat(search,"("); + + switch(search_type) + { + case KS_SEARCH_KEYID_SHORT: + strcat(search,"pgpKeyID"); + break; + + case KS_SEARCH_KEYID_LONG: + strcat(search,"pgpCertID"); + break; + + default: + strcat(search,"pgpUserID"); + break; + } + + strcat(search,"="); + + switch(search_type) + { + case KS_SEARCH_SUBSTR: + strcat(search,"*"); + break; + + case KS_SEARCH_MAIL: + strcat(search,"*<"); + break; + + case KS_SEARCH_MAILSUB: + strcat(search,"*<*"); + break; + + case KS_SEARCH_EXACT: + case KS_SEARCH_KEYID_LONG: + case KS_SEARCH_KEYID_SHORT: + break; + } + + ldap_quote(search,searchkey); + + switch(search_type) + { + case KS_SEARCH_SUBSTR: + strcat(search,"*"); + break; + + case KS_SEARCH_MAIL: + strcat(search,">*"); + break; + + case KS_SEARCH_MAILSUB: + strcat(search,"*>*"); + break; + + case KS_SEARCH_EXACT: + case KS_SEARCH_KEYID_LONG: + case KS_SEARCH_KEYID_SHORT: + break; + } + + strcat(search,")"); + + if(!opt->flags.include_disabled) + strcat(search,"(pgpDisabled=0)"); + + if(!opt->flags.include_revoked) + strcat(search,"(pgpRevoked=0)"); + + if(!opt->flags.include_disabled || !opt->flags.include_revoked) + strcat(search,")"); + + if(opt->verbose>2) + fprintf(console,"gpgkeys: LDAP search for: %s\n",search); + + err=ldap_search_s(ldap,basekeyspacedn, + LDAP_SCOPE_SUBTREE,search,attrs,0,&res); + if(err!=LDAP_SUCCESS && err!=LDAP_SIZELIMIT_EXCEEDED) + { + int errtag=ldap_err_to_gpg_err(err); + + fprintf(output,"SEARCH %s FAILED %d\n",searchkey,errtag); + fprintf(console,"gpgkeys: LDAP search error: %s\n",ldap_err2string(err)); + return errtag; + } + + /* The LDAP server doesn't return a real count of unique keys, so we + can't use ldap_count_entries here. */ + each=ldap_first_entry(ldap,res); + while(each!=NULL) + { + char **certid=ldap_get_values(ldap,each,"pgpcertid"); + + if(certid!=NULL) + { + if(!key_in_keylist(certid[0],dupelist)) + { + int rc=add_key_to_keylist(certid[0],&dupelist); + if(rc!=0) + { + fprintf(output,"SEARCH %s FAILED %d\n",searchkey,rc); + free_keylist(dupelist); + return rc; + } + + count++; + } + } + + each=ldap_next_entry(ldap,each); + } + + if(err==LDAP_SIZELIMIT_EXCEEDED) + { + if(count==1) + fprintf(console,"gpgkeys: search results exceeded server limit." + " First %d result shown.\n",count); + else + fprintf(console,"gpgkeys: search results exceeded server limit." + " First %d results shown.\n",count); + } + + free_keylist(dupelist); + dupelist=NULL; + + if(count<1) + fprintf(output,"info:1:0\n"); + else + { + fprintf(output,"info:1:%d\n",count); + + each=ldap_first_entry(ldap,res); + while(each!=NULL) + { + char **certid; + + certid=ldap_get_values(ldap,each,"pgpcertid"); + if(certid!=NULL) + { + LDAPMessage *uids; + + /* Have we seen this certid before? */ + if(!key_in_keylist(certid[0],dupelist)) + { + int rc=add_key_to_keylist(certid[0],&dupelist); + if(rc) + { + fprintf(output,"SEARCH %s FAILED %d\n",searchkey,rc); + free_keylist(dupelist); + ldap_value_free(certid); + ldap_msgfree(res); + return rc; + } + + fprintf(output,"pub:%s:",certid[0]); + + vals=ldap_get_values(ldap,each,"pgpkeytype"); + if(vals!=NULL) + { + /* The LDAP server doesn't exactly handle this + well. */ + if(strcasecmp(vals[0],"RSA")==0) + fprintf(output,"1"); + else if(strcasecmp(vals[0],"DSS/DH")==0) + fprintf(output,"17"); + ldap_value_free(vals); + } + + fputc(':',output); + + vals=ldap_get_values(ldap,each,"pgpkeysize"); + if(vals!=NULL) + { + /* Not sure why, but some keys are listed with a + key size of 0. Treat that like an + unknown. */ + if(atoi(vals[0])>0) + fprintf(output,"%d",atoi(vals[0])); + ldap_value_free(vals); + } + + fputc(':',output); + + /* YYYYMMDDHHmmssZ */ + + vals=ldap_get_values(ldap,each,"pgpkeycreatetime"); + if(vals!=NULL && strlen(vals[0])==15) + { + fprintf(output,"%u", + (unsigned int)ldap2epochtime(vals[0])); + ldap_value_free(vals); + } + + fputc(':',output); + + vals=ldap_get_values(ldap,each,"pgpkeyexpiretime"); + if(vals!=NULL && strlen(vals[0])==15) + { + fprintf(output,"%u", + (unsigned int)ldap2epochtime(vals[0])); + ldap_value_free(vals); + } + + fputc(':',output); + + vals=ldap_get_values(ldap,each,"pgprevoked"); + if(vals!=NULL) + { + if(atoi(vals[0])==1) + fprintf(output,"r"); + ldap_value_free(vals); + } + + vals=ldap_get_values(ldap,each,"pgpdisabled"); + if(vals!=NULL) + { + if(atoi(vals[0])==1) + fprintf(output,"d"); + ldap_value_free(vals); + } + +#if 0 + /* This is not yet specified in the keyserver + protocol, but may be someday. */ + fputc(':',output); + + vals=ldap_get_values(ldap,each,"modifytimestamp"); + if(vals!=NULL && strlen(vals[0])==15) + { + fprintf(output,"%u", + (unsigned int)ldap2epochtime(vals[0])); + ldap_value_free(vals); + } +#endif + + fprintf(output,"\n"); + + /* Now print all the uids that have this certid */ + uids=ldap_first_entry(ldap,res); + while(uids!=NULL) + { + vals=ldap_get_values(ldap,uids,"pgpcertid"); + if(vals!=NULL) + { + if(strcasecmp(certid[0],vals[0])==0) + { + char **uidvals; + + fprintf(output,"uid:"); + + uidvals=ldap_get_values(ldap,uids,"pgpuserid"); + if(uidvals!=NULL) + { + /* Need to escape any colons */ + printquoted(output,uidvals[0],':'); + ldap_value_free(uidvals); + } + + fprintf(output,"\n"); + } + + ldap_value_free(vals); + } + + uids=ldap_next_entry(ldap,uids); + } + } + + ldap_value_free(certid); + } + + each=ldap_next_entry(ldap,each); + } + } + + ldap_msgfree(res); + free_keylist(dupelist); + + fprintf(output,"SEARCH %s END\n",searchkey); + + return KEYSERVER_OK; +} + +static void +fail_all(struct keylist *keylist,int err) +{ + if(!keylist) + return; + + if(opt->action==KS_SEARCH) + { + fprintf(output,"SEARCH "); + while(keylist) + { + fprintf(output,"%s ",keylist->str); + keylist=keylist->next; + } + fprintf(output,"FAILED %d\n",err); + } + else + while(keylist) + { + fprintf(output,"KEY %s FAILED %d\n",keylist->str,err); + keylist=keylist->next; + } +} + +static int +find_basekeyspacedn(void) +{ + int err,i; + char *attr[]={"namingContexts",NULL,NULL,NULL}; + LDAPMessage *res; + char **context; + + /* Look for namingContexts */ + err=ldap_search_s(ldap,"",LDAP_SCOPE_BASE,"(objectClass=*)",attr,0,&res); + if(err==LDAP_SUCCESS) + { + context=ldap_get_values(ldap,res,"namingContexts"); + if(context) + { + attr[0]="pgpBaseKeySpaceDN"; + attr[1]="pgpVersion"; + attr[2]="pgpSoftware"; + + real_ldap=1; + + /* We found some, so try each namingContext as the search base + and look for pgpBaseKeySpaceDN. Because we found this, we + know we're talking to a regular-ish LDAP server and not a + LDAP keyserver. */ + + for(i=0;context[i] && !basekeyspacedn;i++) + { + char **vals; + LDAPMessage *si_res; + char *object; + + object=malloc(17+strlen(context[i])+1); + if(!object) + return -1; + + strcpy(object,"cn=pgpServerInfo,"); + strcat(object,context[i]); + + err=ldap_search_s(ldap,object,LDAP_SCOPE_BASE, + "(objectClass=*)",attr,0,&si_res); + free(object); + + if(err==LDAP_NO_SUCH_OBJECT) + continue; + else if(err!=LDAP_SUCCESS) + return err; + + vals=ldap_get_values(ldap,si_res,"pgpBaseKeySpaceDN"); + if(vals) + { + basekeyspacedn=strdup(vals[0]); + ldap_value_free(vals); + } + + if(opt->verbose>1) + { + vals=ldap_get_values(ldap,si_res,"pgpSoftware"); + if(vals) + { + fprintf(console,"Server: \t%s\n",vals[0]); + ldap_value_free(vals); + } + + vals=ldap_get_values(ldap,si_res,"pgpVersion"); + if(vals) + { + fprintf(console,"Version:\t%s\n",vals[0]); + ldap_value_free(vals); + } + } + + ldap_msgfree(si_res); + } + + ldap_value_free(context); + } + + ldap_msgfree(res); + } + else + { + /* We don't have an answer yet, which means the server might be + a LDAP keyserver. */ + char **vals; + LDAPMessage *si_res; + + attr[0]="pgpBaseKeySpaceDN"; + attr[1]="version"; + attr[2]="software"; + + err=ldap_search_s(ldap,"cn=pgpServerInfo",LDAP_SCOPE_BASE, + "(objectClass=*)",attr,0,&si_res); + if(err!=LDAP_SUCCESS) + return err; + + /* For the LDAP keyserver, this is always "OU=ACTIVE,O=PGP + KEYSPACE,C=US", but it might not be in the future. */ + + vals=ldap_get_values(ldap,si_res,"baseKeySpaceDN"); + if(vals) + { + basekeyspacedn=strdup(vals[0]); + ldap_value_free(vals); + } + + if(opt->verbose>1) + { + vals=ldap_get_values(ldap,si_res,"software"); + if(vals) + { + fprintf(console,"Server: \t%s\n",vals[0]); + ldap_value_free(vals); + } + } + + vals=ldap_get_values(ldap,si_res,"version"); + if(vals) + { + if(opt->verbose>1) + fprintf(console,"Version:\t%s\n",vals[0]); + + /* If the version is high enough, use the new pgpKeyV2 + attribute. This design if iffy at best, but it matches how + PGP does it. I figure the NAI folks assumed that there would + never be a LDAP keyserver vendor with a different numbering + scheme. */ + if(atoi(vals[0])>1) + pgpkeystr="pgpKeyV2"; + + ldap_value_free(vals); + } + + ldap_msgfree(si_res); + } + + return LDAP_SUCCESS; +} + +static void +show_help (FILE *fp) +{ + fprintf (fp,"-h\thelp\n"); + fprintf (fp,"-V\tversion\n"); + fprintf (fp,"-o\toutput to this file\n"); +} + +int +main(int argc,char *argv[]) +{ + int port=0,arg,err,ret=KEYSERVER_INTERNAL_ERROR; + char line[MAX_LINE],*binddn=NULL,*bindpw=NULL; + int failed=0,use_ssl=0,use_tls=0,bound=0; + struct keylist *keylist=NULL,*keyptr=NULL; + + console=stderr; + + /* Kludge to implement standard GNU options. */ + if (argc > 1 && !strcmp (argv[1], "--version")) + { + fputs ("gpgkeys_ldap (GnuPG) " VERSION"\n", stdout); + return 0; + } + else if (argc > 1 && !strcmp (argv[1], "--help")) + { + show_help (stdout); + return 0; + } + + while((arg=getopt(argc,argv,"hVo:"))!=-1) + switch(arg) + { + default: + case 'h': + show_help (console); + return KEYSERVER_OK; + + case 'V': + fprintf(stdout,"%d\n%s\n",KEYSERVER_PROTO_VERSION,VERSION); + return KEYSERVER_OK; + + case 'o': + output=fopen(optarg,"w"); + if(output==NULL) + { + fprintf(console,"gpgkeys: Cannot open output file `%s': %s\n", + optarg,strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + + break; + } + + if(argc>optind) + { + input=fopen(argv[optind],"r"); + if(input==NULL) + { + fprintf(console,"gpgkeys: Cannot open input file `%s': %s\n", + argv[optind],strerror(errno)); + return KEYSERVER_INTERNAL_ERROR; + } + } + + if(input==NULL) + input=stdin; + + if(output==NULL) + output=stdout; + + opt=init_ks_options(); + if(!opt) + return KEYSERVER_NO_MEMORY; + + /* Get the command and info block */ + + while(fgets(line,MAX_LINE,input)!=NULL) + { + char optionstr[MAX_OPTION+1]; + + if(line[0]=='\n') + break; + + err=parse_ks_options(line,opt); + if(err>0) + { + ret=err; + goto fail; + } + else if(err==0) + continue; + + if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",optionstr)==1) + { + int no=0; + char *start=&optionstr[0]; + + optionstr[MAX_OPTION]='\0'; + + if(strncasecmp(optionstr,"no-",3)==0) + { + no=1; + start=&optionstr[3]; + } + + if(strncasecmp(start,"tls",3)==0) + { + if(no) + use_tls=0; + else if(start[3]=='=') + { + if(strcasecmp(&start[4],"no")==0) + use_tls=0; + else if(strcasecmp(&start[4],"try")==0) + use_tls=1; + else if(strcasecmp(&start[4],"warn")==0) + use_tls=2; + else if(strcasecmp(&start[4],"require")==0) + use_tls=3; + else + use_tls=1; + } + else if(start[3]=='\0') + use_tls=1; + } + else if(strncasecmp(start,"basedn",6)==0) + { + if(no) + { + free(basekeyspacedn); + basekeyspacedn=NULL; + } + else if(start[6]=='=') + { + free(basekeyspacedn); + basekeyspacedn=strdup(&start[7]); + if(!basekeyspacedn) + { + fprintf(console,"gpgkeys: out of memory while creating " + "base DN\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + real_ldap=1; + } + } + else if(strncasecmp(start,"binddn",6)==0) + { + if(no) + { + free(binddn); + binddn=NULL; + } + else if(start[6]=='=') + { + free(binddn); + binddn=strdup(&start[7]); + if(!binddn) + { + fprintf(console,"gpgkeys: out of memory while creating " + "bind DN\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + real_ldap=1; + } + } + else if(strncasecmp(start,"bindpw",6)==0) + { + if(no) + { + free(bindpw); + bindpw=NULL; + } + else if(start[6]=='=') + { + free(bindpw); + bindpw=strdup(&start[7]); + if(!bindpw) + { + fprintf(console,"gpgkeys: out of memory while creating " + "bind password\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + real_ldap=1; + } + } + + continue; + } + } + + if(!opt->scheme) + { + fprintf(console,"gpgkeys: no scheme supplied!\n"); + ret=KEYSERVER_SCHEME_NOT_FOUND; + goto fail; + } + + if(strcasecmp(opt->scheme,"ldaps")==0) + { + port=636; + use_ssl=1; + } + + if(opt->port) + port=atoi(opt->port); + + if(!opt->host) + { + fprintf(console,"gpgkeys: no keyserver host provided\n"); + goto fail; + } + + if(opt->timeout && register_timeout()==-1) + { + fprintf(console,"gpgkeys: unable to register timeout handler\n"); + return KEYSERVER_INTERNAL_ERROR; + } + +#if defined(LDAP_OPT_X_TLS_CACERTFILE) && defined(HAVE_LDAP_SET_OPTION) + + if(opt->ca_cert_file) + { + err=ldap_set_option(NULL,LDAP_OPT_X_TLS_CACERTFILE,opt->ca_cert_file); + if(err!=LDAP_SUCCESS) + { + fprintf(console,"gpgkeys: unable to set ca-cert-file: %s\n", + ldap_err2string(err)); + ret=KEYSERVER_INTERNAL_ERROR; + goto fail; + } + } +#endif /* LDAP_OPT_X_TLS_CACERTFILE && HAVE_LDAP_SET_OPTION */ + + /* SSL trumps TLS */ + if(use_ssl) + use_tls=0; + + /* If it's a GET or a SEARCH, the next thing to come in is the + keyids. If it's a SEND, then there are no keyids. */ + + if(opt->action==KS_SEND) + while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n'); + else if(opt->action==KS_GET + || opt->action==KS_GETNAME || opt->action==KS_SEARCH) + { + for(;;) + { + struct keylist *work; + + if(fgets(line,MAX_LINE,input)==NULL) + break; + else + { + if(line[0]=='\n' || line[0]=='\0') + break; + + work=malloc(sizeof(struct keylist)); + if(work==NULL) + { + fprintf(console,"gpgkeys: out of memory while " + "building key list\n"); + ret=KEYSERVER_NO_MEMORY; + goto fail; + } + + strcpy(work->str,line); + + /* Trim the trailing \n */ + work->str[strlen(line)-1]='\0'; + + work->next=NULL; + + /* Always attach at the end to keep the list in proper + order for searching */ + if(keylist==NULL) + keylist=work; + else + keyptr->next=work; + + keyptr=work; + } + } + } + else + { + fprintf(console,"gpgkeys: no keyserver command specified\n"); + goto fail; + } + + /* Send the response */ + + fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION); + fprintf(output,"PROGRAM %s\n\n",VERSION); + + if(opt->verbose>1) + { + fprintf(console,"Host:\t\t%s\n",opt->host); + if(port) + fprintf(console,"Port:\t\t%d\n",port); + fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action)); + } + + if(opt->debug) + { +#if defined(LDAP_OPT_DEBUG_LEVEL) && defined(HAVE_LDAP_SET_OPTION) + err=ldap_set_option(NULL,LDAP_OPT_DEBUG_LEVEL,&opt->debug); + if(err!=LDAP_SUCCESS) + fprintf(console,"gpgkeys: unable to set debug mode: %s\n", + ldap_err2string(err)); + else + fprintf(console,"gpgkeys: debug level %d\n",opt->debug); +#else + fprintf(console,"gpgkeys: not built with debugging support\n"); +#endif + } + + /* We have a timeout set for the setup stuff since it could time out + as well. */ + set_timeout(opt->timeout); + + /* Note that this tries all A records on a given host (or at least, + OpenLDAP does). */ + ldap=ldap_init(opt->host,port); + if(ldap==NULL) + { + fprintf(console,"gpgkeys: internal LDAP init error: %s\n", + strerror(errno)); + fail_all(keylist,KEYSERVER_INTERNAL_ERROR); + goto fail; + } + + if(use_ssl) + { +#if defined(LDAP_OPT_X_TLS) && defined(HAVE_LDAP_SET_OPTION) + int ssl=LDAP_OPT_X_TLS_HARD; + + err=ldap_set_option(ldap,LDAP_OPT_X_TLS,&ssl); + if(err!=LDAP_SUCCESS) + { + fprintf(console,"gpgkeys: unable to make SSL connection: %s\n", + ldap_err2string(err)); + fail_all(keylist,ldap_err_to_gpg_err(err)); + goto fail; + } + + if(!opt->flags.check_cert) + ssl=LDAP_OPT_X_TLS_NEVER; + + err=ldap_set_option(NULL,LDAP_OPT_X_TLS_REQUIRE_CERT,&ssl); + if(err!=LDAP_SUCCESS) + { + fprintf(console, + "gpgkeys: unable to set certificate validation: %s\n", + ldap_err2string(err)); + fail_all(keylist,ldap_err_to_gpg_err(err)); + goto fail; + } +#else + fprintf(console,"gpgkeys: unable to make SSL connection: %s\n", + "not built with LDAPS support"); + fail_all(keylist,KEYSERVER_INTERNAL_ERROR); + goto fail; +#endif + } + + if(!basekeyspacedn) + if((err=find_basekeyspacedn()) || !basekeyspacedn) + { + fprintf(console,"gpgkeys: unable to retrieve LDAP base: %s\n", + err?ldap_err2string(err):"not found"); + fail_all(keylist,ldap_err_to_gpg_err(err)); + goto fail; + } + + /* use_tls: 0=don't use, 1=try silently to use, 2=try loudly to use, + 3=force use. */ + if(use_tls) + { + if(!real_ldap) + { + if(use_tls>=2) + fprintf(console,"gpgkeys: unable to start TLS: %s\n", + "not supported by the NAI LDAP keyserver"); + if(use_tls==3) + { + fail_all(keylist,KEYSERVER_INTERNAL_ERROR); + goto fail; + } + } + else + { +#if defined(HAVE_LDAP_START_TLS_S) && defined(HAVE_LDAP_SET_OPTION) + int ver=LDAP_VERSION3; + + err=ldap_set_option(ldap,LDAP_OPT_PROTOCOL_VERSION,&ver); + +#ifdef LDAP_OPT_X_TLS + if(err==LDAP_SUCCESS) + { + if(opt->flags.check_cert) + ver=LDAP_OPT_X_TLS_HARD; + else + ver=LDAP_OPT_X_TLS_NEVER; + + err=ldap_set_option(ldap,LDAP_OPT_X_TLS_REQUIRE_CERT,&ver); + } +#endif + + if(err==LDAP_SUCCESS) + err=ldap_start_tls_s(ldap,NULL,NULL); + + if(err!=LDAP_SUCCESS) + { + if(use_tls>=2 || opt->verbose>2) + fprintf(console,"gpgkeys: unable to start TLS: %s\n", + ldap_err2string(err)); + /* Are we forcing it? */ + if(use_tls==3) + { + fail_all(keylist,ldap_err_to_gpg_err(err)); + goto fail; + } + } + else if(opt->verbose>1) + fprintf(console,"gpgkeys: TLS started successfully.\n"); +#else + if(use_tls>=2) + fprintf(console,"gpgkeys: unable to start TLS: %s\n", + "not built with TLS support"); + if(use_tls==3) + { + fail_all(keylist,KEYSERVER_INTERNAL_ERROR); + goto fail; + } +#endif + } + } + + /* By default we don't bind as there is usually no need to. For + cases where the server needs some authentication, the user can + use binddn and bindpw for auth. */ + + if(binddn) + { +#ifdef HAVE_LDAP_SET_OPTION + int ver=LDAP_VERSION3; + + err=ldap_set_option(ldap,LDAP_OPT_PROTOCOL_VERSION,&ver); + if(err!=LDAP_SUCCESS) + { + fprintf(console,"gpgkeys: unable to go to LDAP 3: %s\n", + ldap_err2string(err)); + fail_all(keylist,ldap_err_to_gpg_err(err)); + goto fail; + } +#endif + + if(opt->verbose>2) + fprintf(console,"gpgkeys: LDAP bind to %s, pw %s\n",binddn, + bindpw?">not shown<":">none<"); + err=ldap_simple_bind_s(ldap,binddn,bindpw); + if(err!=LDAP_SUCCESS) + { + fprintf(console,"gpgkeys: internal LDAP bind error: %s\n", + ldap_err2string(err)); + fail_all(keylist,ldap_err_to_gpg_err(err)); + goto fail; + } + else + bound=1; + } + + if(opt->action==KS_GET) + { + keyptr=keylist; + + while(keyptr!=NULL) + { + set_timeout(opt->timeout); + + if(get_key(keyptr->str)!=KEYSERVER_OK) + failed++; + + keyptr=keyptr->next; + } + } + else if(opt->action==KS_GETNAME) + { + keyptr=keylist; + + while(keyptr!=NULL) + { + set_timeout(opt->timeout); + + if(get_name(keyptr->str)!=KEYSERVER_OK) + failed++; + + keyptr=keyptr->next; + } + } + else if(opt->action==KS_SEND) + { + int eof=0; + + do + { + set_timeout(opt->timeout); + + if(real_ldap) + { + if(send_key(&eof)!=KEYSERVER_OK) + failed++; + } + else + { + if(send_key_keyserver(&eof)!=KEYSERVER_OK) + failed++; + } + } + while(!eof); + } + else if(opt->action==KS_SEARCH) + { + char *searchkey=NULL; + int len=0; + + set_timeout(opt->timeout); + + /* To search, we stick a * in between each key to search for. + This means that if the user enters words, they'll get + "enters*words". If the user "enters words", they'll get + "enters words" */ + + keyptr=keylist; + while(keyptr!=NULL) + { + len+=strlen(keyptr->str)+1; + keyptr=keyptr->next; + } + + searchkey=malloc(len+1); + if(searchkey==NULL) + { + ret=KEYSERVER_NO_MEMORY; + fail_all(keylist,KEYSERVER_NO_MEMORY); + goto fail; + } + + searchkey[0]='\0'; + + keyptr=keylist; + while(keyptr!=NULL) + { + strcat(searchkey,keyptr->str); + strcat(searchkey,"*"); + keyptr=keyptr->next; + } + + /* Nail that last "*" */ + if(*searchkey) + searchkey[strlen(searchkey)-1]='\0'; + + if(search_key(searchkey)!=KEYSERVER_OK) + failed++; + + free(searchkey); + } + else + BUG(); + + if(!failed) + ret=KEYSERVER_OK; + + fail: + + while(keylist!=NULL) + { + struct keylist *current=keylist; + keylist=keylist->next; + free(current); + } + + if(input!=stdin) + fclose(input); + + if(output!=stdout) + fclose(output); + + free_ks_options(opt); + + if(ldap!=NULL && bound) + ldap_unbind_s(ldap); + + free(basekeyspacedn); + + return ret; +} diff --git a/keyserver/gpgkeys_mailto.in b/keyserver/gpgkeys_mailto.in new file mode 100755 index 000000000..e37f5c0bc --- /dev/null +++ b/keyserver/gpgkeys_mailto.in @@ -0,0 +1,225 @@ +#!@PERL@ -w + +# gpgkeys_mailto - talk to a email keyserver +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +use Getopt::Std; +$Getopt::Std::STANDARD_HELP_VERSION=1; +$sendmail="@SENDMAIL@ -t"; + +### + +sub VERSION_MESSAGE () +{ + print STDOUT "gpgkeys_mailto (GnuPG) @VERSION@\n"; +} + +sub HELP_MESSAGE () +{ + print STDOUT <<EOT + +--help Print this help +--version Print the version +-o FILE Write output to FILE +EOT +} + + + +getopts('o:'); + +if(defined($opt_o)) +{ + open(STDOUT,">$opt_o") || die "Can't open output file $opt_o\n"; +} + +if(@ARGV) +{ + open(STDIN,$ARGV[0]) || die "Can't open input file $ARGV[0]\n"; +} + +($login,$name)=(getpwuid($<))[0,6]; + +$from="$name <$login>"; + +while(<STDIN>) +{ + last if($_ eq "\n"); + + if(/^COMMAND (\S+)/) + { + $command=$1; + } + + if(/^OPAQUE (\S+)/) + { + $address=$1; + } + + if(/^PROGRAM (\S+)/) + { + $program=$1; + } + + if(/^OPTION (\S+)/) + { + if($1=~/^verbose$/i) + { + $verbose++; + } + elsif($1=~/^no-verbose$/i) + { + $verbose--; + } + } +} + +$program="(unknown)" if(!defined($program)); + +if(!defined($address)) +{ + print STDERR "gpgkeys: no address provided\n"; + exit(1); +} + +# decode $address + +($address,$args)=split(/\?/,$address); + +if(defined($args)) +{ + @pairs = split(/&/, $args); + foreach $pair (@pairs) + { + ($hdr, $val) = split(/=/, $pair); + $hdr =~ tr/+/ /; + $hdr =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $val =~ tr/+/ /; + $val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; +# we only handle "from" right now + if($hdr=~/^from$/i) + { + $from=$val; + last; + } + } +} + +while(<STDIN>) +{ + last if($_ eq "\n"); + + chomp; + + push(@keys,$_); +} + +# Send response + +print "VERSION 1\n"; +print "OPTION OUTOFBAND\n\n"; + +# Email keyservers get and search the same way + +if($command=~/get/i || $command=~/search/i) +{ + if($command=~/search/i) + { + print "COUNT 0\n"; + } + + foreach $key (@keys) + { + open(MAIL,"|$sendmail") || die "ERROR: Can't open $sendmail\n"; + print MAIL "From: $from\n"; + print MAIL "To: $address\n"; + if($command=~/get/i) + { + # mail keyservers don't like long-form keyids + + if(substr($key,0,2) eq "0x") + { + $key=substr($key,2); + } + + if(length($key)>8) + { + $key=substr($key,-8); + } + + print MAIL "Subject: GET 0x$key\n\n"; + } + else + { + print MAIL "Subject: GET $key\n\n"; + } + print MAIL "GnuPG $program email keyserver request\n"; + close(MAIL); + + # Tell GnuPG not to expect a key + print "KEY $key OUTOFBAND\n"; + + if($verbose) + { + print STDERR "gpgkeys: key $key requested from $address\n"; + } + } +} + +if($command=~/send/i) +{ + while(!eof(STDIN)) + { + open(MAIL,"|$sendmail") || die "ERROR: Can't open $sendmail\n"; + print MAIL "From: $name <$login>\n"; + print MAIL "To: $address\n"; + print MAIL "Subject: ADD\n\n"; + + while(<STDIN>) + { + if(/^KEY (\S+) BEGIN$/) + { + $key=$1; + last; + } + } + + while(<STDIN>) + { + if(/^KEY \S+ END$/) + { + last; + } + + print MAIL; + } + + close(MAIL); + + if($verbose) + { + print STDERR "gpgkeys: key $key sent to $address\n"; + } + } +} + + +# Local Variables: +# mode:perl +# End: diff --git a/keyserver/gpgkeys_test.in b/keyserver/gpgkeys_test.in new file mode 100755 index 000000000..97748cd3f --- /dev/null +++ b/keyserver/gpgkeys_test.in @@ -0,0 +1,99 @@ +#!@PERL@ + +# gpgkeys_test - keyserver code tester +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +use Getopt::Std; +$Getopt::Std::STANDARD_HELP_VERSION=1; + +$|=1; + +sub VERSION_MESSAGE () +{ + print STDOUT "gpgkeys_test (GnuPG) @VERSION@\n"; +} + +sub HELP_MESSAGE () +{ + print STDOUT <<EOT + +--help Print this help +--version Print the version +EOT +} + + +getopts('o:'); + +print STDERR "gpgkeys_test starting\n"; + +if(defined($opt_o)) +{ + print STDERR "Using output file $opt_o\n"; + open(STDOUT,">$opt_o") || die "Can't open output file $opt_o\n"; +} + +if(@ARGV) +{ + print STDERR "Using input file $ARGV[0]\n"; + open(STDIN,$ARGV[0]) || die "Can't open input file $ARGV[0]\n"; +} + +# Get the command block + +print STDERR "Command block:\n"; + +while(<STDIN>) +{ + last if($_ eq "\n"); + print STDERR "--command-> $_"; + + if(/^COMMAND (\w+)/) + { + $command=$1; + } +} + +# Get the keylist block + +print STDERR "Keylist block:\n"; + +while(<STDIN>) +{ + last if($_ eq "\n"); + print STDERR "--keylist-> $_"; +} + +# If it's a SEND, then get the key material + +if($command eq "SEND") +{ + print STDERR "Key material to send:\n"; + + while(<STDIN>) + { + print STDERR "$_"; + } +} + +printf STDERR "gpgkeys_test finished\n"; + +# Local Variables: +# mode:perl +# End: diff --git a/keyserver/ksutil.c b/keyserver/ksutil.c new file mode 100644 index 000000000..64912bb2d --- /dev/null +++ b/keyserver/ksutil.c @@ -0,0 +1,540 @@ +/* ksutil.c - general keyserver utility functions + * Copyright (C) 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include <config.h> +#include <signal.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#else +#include "curl-shim.h" +#endif +#include "keyserver.h" +#include "ksutil.h" + +#ifdef HAVE_DOSISH_SYSTEM + +unsigned int set_timeout(unsigned int seconds) {return 0;} +int register_timeout(void) {return 0;} + +#else + +static void +catch_alarm(int foo) +{ + (void)foo; + _exit(KEYSERVER_TIMEOUT); +} + +unsigned int +set_timeout(unsigned int seconds) +{ + return alarm(seconds); +} + +int +register_timeout(void) +{ +#if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION) + struct sigaction act; + + act.sa_handler=catch_alarm; + sigemptyset(&act.sa_mask); + act.sa_flags=0; + return sigaction(SIGALRM,&act,NULL); +#else + if(signal(SIGALRM,catch_alarm)==SIG_ERR) + return -1; + else + return 0; +#endif +} + +#endif /* !HAVE_DOSISH_SYSTEM */ + +struct ks_options * +init_ks_options(void) +{ + struct ks_options *opt; + + opt=calloc(1,sizeof(struct ks_options)); + + if(opt) + { + opt->action=KS_UNKNOWN; + opt->flags.include_revoked=1; + opt->flags.include_subkeys=1; + opt->flags.check_cert=1; + opt->timeout=DEFAULT_KEYSERVER_TIMEOUT; + opt->path=strdup("/"); + if(!opt->path) + { + free(opt); + opt=NULL; + } + } + + return opt; +} + +void +free_ks_options(struct ks_options *opt) +{ + if(opt) + { + free(opt->host); + free(opt->port); + free(opt->scheme); + free(opt->auth); + free(opt->path); + free(opt->opaque); + free(opt->ca_cert_file); + free(opt); + } +} + +/* Returns 0 if we "ate" the line. Returns >0, a KEYSERVER_ error + code if that error applies. Returns -1 if we did not match the + line at all. */ +int +parse_ks_options(char *line,struct ks_options *opt) +{ + int version; + char command[MAX_COMMAND+1]; + char host[MAX_HOST+1]; + char port[MAX_PORT+1]; + char scheme[MAX_SCHEME+1]; + char auth[MAX_AUTH+1]; + char path[URLMAX_PATH+1]; + char opaque[MAX_OPAQUE+1]; + char option[MAX_OPTION+1]; + + if(line[0]=='#') + return 0; + + if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1) + { + command[MAX_COMMAND]='\0'; + + if(strcasecmp(command,"get")==0) + opt->action=KS_GET; + else if(strcasecmp(command,"getname")==0) + opt->action=KS_GETNAME; + else if(strcasecmp(command,"send")==0) + opt->action=KS_SEND; + else if(strcasecmp(command,"search")==0) + opt->action=KS_SEARCH; + + return 0; + } + + if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1) + { + host[MAX_HOST]='\0'; + free(opt->host); + opt->host=strdup(host); + if(!opt->host) + return KEYSERVER_NO_MEMORY; + return 0; + } + + if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1) + { + port[MAX_PORT]='\0'; + free(opt->port); + opt->port=strdup(port); + if(!opt->port) + return KEYSERVER_NO_MEMORY; + return 0; + } + + if(sscanf(line,"SCHEME %" MKSTRING(MAX_SCHEME) "s\n",scheme)==1) + { + scheme[MAX_SCHEME]='\0'; + free(opt->scheme); + opt->scheme=strdup(scheme); + if(!opt->scheme) + return KEYSERVER_NO_MEMORY; + return 0; + } + + if(sscanf(line,"AUTH %" MKSTRING(MAX_AUTH) "s\n",auth)==1) + { + auth[MAX_AUTH]='\0'; + free(opt->auth); + opt->auth=strdup(auth); + if(!opt->auth) + return KEYSERVER_NO_MEMORY; + return 0; + } + + if(sscanf(line,"PATH %" MKSTRING(URLMAX_PATH) "s\n",path)==1) + { + path[URLMAX_PATH]='\0'; + free(opt->path); + opt->path=strdup(path); + if(!opt->path) + return KEYSERVER_NO_MEMORY; + return 0; + } + + if(sscanf(line,"OPAQUE %" MKSTRING(MAX_OPAQUE) "s\n",opaque)==1) + { + opaque[MAX_OPAQUE]='\0'; + free(opt->opaque); + opt->opaque=strdup(opaque); + if(!opt->opaque) + return KEYSERVER_NO_MEMORY; + return 0; + } + + if(sscanf(line,"VERSION %d\n",&version)==1) + { + if(version!=KEYSERVER_PROTO_VERSION) + return KEYSERVER_VERSION_ERROR; + + return 0; + } + + if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "[^\n]\n",option)==1) + { + int no=0; + char *start=&option[0]; + + option[MAX_OPTION]='\0'; + + if(strncasecmp(option,"no-",3)==0) + { + no=1; + start=&option[3]; + } + + if(strncasecmp(start,"verbose",7)==0) + { + if(no) + opt->verbose=0; + else if(start[7]=='=') + opt->verbose=atoi(&start[8]); + else + opt->verbose++; + } + else if(strcasecmp(start,"include-disabled")==0) + { + if(no) + opt->flags.include_disabled=0; + else + opt->flags.include_disabled=1; + } + else if(strcasecmp(start,"include-revoked")==0) + { + if(no) + opt->flags.include_revoked=0; + else + opt->flags.include_revoked=1; + } + else if(strcasecmp(start,"include-subkeys")==0) + { + if(no) + opt->flags.include_subkeys=0; + else + opt->flags.include_subkeys=1; + } + else if(strcasecmp(start,"check-cert")==0) + { + if(no) + opt->flags.check_cert=0; + else + opt->flags.check_cert=1; + } + else if(strncasecmp(start,"debug",5)==0) + { + if(no) + opt->debug=0; + else if(start[5]=='=') + opt->debug=atoi(&start[6]); + else if(start[5]=='\0') + opt->debug=1; + } + else if(strncasecmp(start,"timeout",7)==0) + { + if(no) + opt->timeout=0; + else if(start[7]=='=') + opt->timeout=atoi(&start[8]); + else if(start[7]=='\0') + opt->timeout=DEFAULT_KEYSERVER_TIMEOUT; + } + else if(strncasecmp(start,"ca-cert-file",12)==0) + { + if(no) + { + free(opt->ca_cert_file); + opt->ca_cert_file=NULL; + } + else if(start[12]=='=') + { + free(opt->ca_cert_file); + opt->ca_cert_file=strdup(&start[13]); + if(!opt->ca_cert_file) + return KEYSERVER_NO_MEMORY; + } + } + } + + return -1; +} + +const char * +ks_action_to_string(enum ks_action action) +{ + switch(action) + { + case KS_UNKNOWN: return "UNKNOWN"; + case KS_GET: return "GET"; + case KS_GETNAME: return "GETNAME"; + case KS_SEND: return "SEND"; + case KS_SEARCH: return "SEARCH"; + } + + return "?"; +} + +/* Canonicalize CRLF to just LF by stripping CRs. This actually makes + sense, since on Unix-like machines LF is correct, and on win32-like + machines, our output buffer is opened in textmode and will + re-canonicalize line endings back to CRLF. Since we only need to + handle armored keys, we don't have to worry about odd cases like + CRCRCR and the like. */ + +void +print_nocr(FILE *stream,const char *str) +{ + while(*str) + { + if(*str!='\r') + fputc(*str,stream); + str++; + } +} + +enum ks_search_type +classify_ks_search(const char **search) +{ + switch(**search) + { + case '*': + (*search)++; + return KS_SEARCH_SUBSTR; + case '=': + (*search)++; + return KS_SEARCH_EXACT; + case '<': + (*search)++; + return KS_SEARCH_MAIL; + case '@': + (*search)++; + return KS_SEARCH_MAILSUB; + case '0': + if((*search)[1]=='x') + { + if(strlen(*search)==10 + && strspn(*search,"abcdefABCDEF1234567890x")==10) + { + (*search)+=2; + return KS_SEARCH_KEYID_SHORT; + } + else if(strlen(*search)==18 + && strspn(*search,"abcdefABCDEF1234567890x")==18) + { + (*search)+=2; + return KS_SEARCH_KEYID_LONG; + } + } + /* fall through */ + default: + return KS_SEARCH_SUBSTR; + } +} + +int +curl_err_to_gpg_err(CURLcode error) +{ + switch(error) + { + case CURLE_OK: return KEYSERVER_OK; + case CURLE_UNSUPPORTED_PROTOCOL: return KEYSERVER_SCHEME_NOT_FOUND; + case CURLE_COULDNT_CONNECT: return KEYSERVER_UNREACHABLE; + case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND; + default: return KEYSERVER_INTERNAL_ERROR; + } +} + +#define B64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + +static void +curl_armor_writer(const unsigned char *buf,size_t size,void *cw_ctx) +{ + struct curl_writer_ctx *ctx=cw_ctx; + size_t idx=0; + + while(idx<size) + { + for(;ctx->armor_remaining<3 && idx<size;ctx->armor_remaining++,idx++) + ctx->armor_ctx[ctx->armor_remaining]=buf[idx]; + + if(ctx->armor_remaining==3) + { + /* Top 6 bytes of ctx->armor_ctx[0] */ + fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream); + /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of + ctx->armor_ctx[1] */ + fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30) + |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream); + /* Bottom 4 bytes of ctx->armor_ctx[1] and top 2 bytes of + ctx->armor_ctx[2] */ + fputc(B64[(((ctx->armor_ctx[1]<<2)&0x3C) + |((ctx->armor_ctx[2]>>6)&0x03))&0x3F],ctx->stream); + /* Bottom 6 bytes of ctx->armor_ctx[2] */ + fputc(B64[(ctx->armor_ctx[2]&0x3F)],ctx->stream); + + ctx->linelen+=4; + if(ctx->linelen>=70) + { + fputc('\n',ctx->stream); + ctx->linelen=0; + } + + ctx->armor_remaining=0; + } + } + +} + +size_t +curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx) +{ + struct curl_writer_ctx *ctx=cw_ctx; + const char *buf=ptr; + size_t i; + + if(!ctx->flags.initialized) + { + if(size*nmemb==0) + return 0; + + /* The object we're fetching is in binary form */ + if(*buf&0x80) + { + ctx->flags.armor=1; + fprintf(ctx->stream,BEGIN"\n\n"); + } + else + ctx->marker=BEGIN; + + ctx->flags.initialized=1; + } + + if(ctx->flags.armor) + curl_armor_writer(ptr,size*nmemb,cw_ctx); + else + { + /* scan the incoming data for our marker */ + for(i=0;!ctx->flags.done && i<(size*nmemb);i++) + { + if(buf[i]==ctx->marker[ctx->markeridx]) + { + ctx->markeridx++; + if(ctx->marker[ctx->markeridx]=='\0') + { + if(ctx->flags.begun) + ctx->flags.done=1; + else + { + /* We've found the BEGIN marker, so now we're + looking for the END marker. */ + ctx->flags.begun=1; + ctx->marker=END; + ctx->markeridx=0; + fprintf(ctx->stream,BEGIN); + continue; + } + } + } + else + ctx->markeridx=0; + + if(ctx->flags.begun) + { + /* Canonicalize CRLF to just LF by stripping CRs. This + actually makes sense, since on Unix-like machines LF + is correct, and on win32-like machines, our output + buffer is opened in textmode and will re-canonicalize + line endings back to CRLF. Since this code is just + for handling armored keys, we don't have to worry + about odd cases like CRCRCR and the like. */ + + if(buf[i]!='\r') + fputc(buf[i],ctx->stream); + } + } + } + + return size*nmemb; +} + +void +curl_writer_finalize(struct curl_writer_ctx *ctx) +{ + if(ctx->flags.armor) + { + if(ctx->armor_remaining==2) + { + /* Top 6 bytes of ctx->armorctx[0] */ + fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream); + /* Bottom 2 bytes of ctx->armor_ctx[0] and top 4 bytes of + ctx->armor_ctx[1] */ + fputc(B64[(((ctx->armor_ctx[0]<<4)&0x30) + |((ctx->armor_ctx[1]>>4)&0x0F))&0x3F],ctx->stream); + /* Bottom 4 bytes of ctx->armor_ctx[1] */ + fputc(B64[((ctx->armor_ctx[1]<<2)&0x3C)],ctx->stream); + /* Pad */ + fputc('=',ctx->stream); + } + else if(ctx->armor_remaining==1) + { + /* Top 6 bytes of ctx->armor_ctx[0] */ + fputc(B64[(ctx->armor_ctx[0]>>2)&0x3F],ctx->stream); + /* Bottom 2 bytes of ctx->armor_ctx[0] */ + fputc(B64[((ctx->armor_ctx[0]<<4)&0x30)],ctx->stream); + /* Pad */ + fputc('=',ctx->stream); + /* Pad */ + fputc('=',ctx->stream); + } + + fprintf(ctx->stream,"\n"END); + ctx->flags.done=1; + } +} diff --git a/keyserver/ksutil.h b/keyserver/ksutil.h new file mode 100644 index 000000000..16c1ebf88 --- /dev/null +++ b/keyserver/ksutil.h @@ -0,0 +1,130 @@ +/* ksutil.h + * Copyright (C) 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef _KSUTIL_H_ +#define _KSUTIL_H_ + +#ifdef HAVE_LIBCURL +#include <curl/curl.h> +#else +#include "curl-shim.h" +#endif + +/* MAX_LINE must be at least 1 larger than the largest item we expect + to receive, including the name tag ("COMMAND", "PORT", etc) and + space between. In practice, that means it should be + strlen("OPAQUE")+1+sizeof_opaque+1 */ +#define MAX_LINE (6+1+1024+1) + +#define MAX_COMMAND 7 +#define MAX_OPTION 256 +#define MAX_SCHEME 20 +#define MAX_OPAQUE 1024 +#define MAX_AUTH 128 +#define MAX_HOST 80 +#define MAX_PORT 10 +#define URLMAX_PATH 1024 +#define MAX_PROXY 128 +#define MAX_URL (MAX_SCHEME+1+3+MAX_AUTH+1+1+MAX_HOST+1+1 \ + +MAX_PORT+1+1+URLMAX_PATH+1+50) + +#define STRINGIFY(x) #x +#define MKSTRING(x) STRINGIFY(x) + +#define BEGIN "-----BEGIN PGP PUBLIC KEY BLOCK-----" +#define END "-----END PGP PUBLIC KEY BLOCK-----" + +#ifdef __riscos__ +#define HTTP_PROXY_ENV "GnuPG$HttpProxy" +#else +#define HTTP_PROXY_ENV "http_proxy" +#endif + +struct keylist +{ + char str[MAX_LINE]; + struct keylist *next; +}; + +/* 2 minutes seems reasonable */ +#define DEFAULT_KEYSERVER_TIMEOUT 120 + +unsigned int set_timeout(unsigned int seconds); +int register_timeout(void); + +enum ks_action {KS_UNKNOWN=0,KS_GET,KS_GETNAME,KS_SEND,KS_SEARCH}; + +enum ks_search_type {KS_SEARCH_SUBSTR,KS_SEARCH_EXACT, + KS_SEARCH_MAIL,KS_SEARCH_MAILSUB, + KS_SEARCH_KEYID_LONG,KS_SEARCH_KEYID_SHORT}; + +struct ks_options +{ + enum ks_action action; + char *host; + char *port; + char *scheme; + char *auth; + char *path; + char *opaque; + struct + { + unsigned int include_disabled:1; + unsigned int include_revoked:1; + unsigned int include_subkeys:1; + unsigned int check_cert:1; + } flags; + unsigned int verbose; + unsigned int debug; + unsigned int timeout; + char *ca_cert_file; +}; + +struct ks_options *init_ks_options(void); +void free_ks_options(struct ks_options *opt); +int parse_ks_options(char *line,struct ks_options *opt); +const char *ks_action_to_string(enum ks_action action); +void print_nocr(FILE *stream,const char *str); +enum ks_search_type classify_ks_search(const char **search); + +int curl_err_to_gpg_err(CURLcode error); + +struct curl_writer_ctx +{ + struct + { + unsigned int initialized:1; + unsigned int begun:1; + unsigned int done:1; + unsigned int armor:1; + } flags; + + int armor_remaining; + unsigned char armor_ctx[3]; + int markeridx,linelen; + const char *marker; + FILE *stream; +}; + +size_t curl_writer(const void *ptr,size_t size,size_t nmemb,void *cw_ctx); +void curl_writer_finalize(struct curl_writer_ctx *ctx); + +#endif /* !_KSUTIL_H_ */ diff --git a/m4/ChangeLog b/m4/ChangeLog index a7a9d1e36..2cc6a308e 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,8 @@ +2006-06-30 Werner Koch <wk@g10code.com> + + * ldap.m4: New. Taken from gnupg 1.4.4 + * Makefile.am (EXTRA_DIST): Add ldap.me + 2004-09-30 Werner Koch <wk@g10code.com> * gpg-error.m4, libassuan.m4, libgcrypt.m4: Updated. diff --git a/m4/Makefile.am b/m4/Makefile.am index a31103ff6..d218b73b7 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -1,3 +1,5 @@ EXTRA_DIST = intmax.m4 longdouble.m4 longlong.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 +EXTRA_DIST += ldap.m4 + EXTRA_DIST += gpg-error.m4 libgcrypt.m4 libassuan.m4 ksba.m4 diff --git a/m4/ldap.m4 b/m4/ldap.m4 new file mode 100644 index 000000000..95249ac3e --- /dev/null +++ b/m4/ldap.m4 @@ -0,0 +1,97 @@ +dnl Check for LDAP +dnl Copyright (C) 2005 Free Software Foundation, Inc. +dnl +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +dnl +dnl Defines @GPGKEYS_LDAP@ to a executable name if a working ldap +dnl setup is found, and sets @LDAPLIBS@ to the necessary libraries. + +AC_DEFUN([GNUPG_CHECK_LDAP], +[ +# Try and link a LDAP test program to weed out unusable LDAP +# libraries. -lldap [-llber [-lresolv]] is for older OpenLDAPs. +# OpenLDAP, circa 1999, was terrible with creating weird dependencies. +# If all else fails, the user can play guess-the-dependency by using +# something like ./configure LDAPLIBS="-Lfoo -lbar" + +AC_ARG_WITH(ldap, + AC_HELP_STRING([--with-ldap=DIR],[look for the LDAP library in DIR]), + [_ldap_with=$withval]) + +if test x$_ldap_with != xno ; then + + if test -d "$withval" ; then + LDAP_CPPFLAGS="-I$withval/include" + LDAP_LDFLAGS="-L$withval/lib" + fi + + _ldap_save_cppflags=$CPPFLAGS + CPPFLAGS="${LDAP_CPPFLAGS} ${CPPFLAGS}" + _ldap_save_ldflags=$LDFLAGS + LDFLAGS="${LDAP_LDFLAGS} ${LDFLAGS}" + + for MY_LDAPLIBS in ${LDAPLIBS+"$LDAPLIBS"} "-lldap" "-lldap -llber" "-lldap -llber -lresolv" "-lwldap32"; do + _ldap_save_libs=$LIBS + LIBS="$MY_LDAPLIBS $1 $LIBS" + + AC_MSG_CHECKING([whether LDAP via \"$MY_LDAPLIBS\" is present and sane]) + AC_TRY_LINK([ +#ifdef _WIN32 +#include <winsock2.h> +#include <winldap.h> +#else +#include <ldap.h> +#endif +],[ldap_open("foobar",1234);], + [gnupg_cv_func_ldap_init=yes],[gnupg_cv_func_ldap_init=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldap_init]) + + if test $gnupg_cv_func_ldap_init = no; then + AC_MSG_CHECKING([whether I can make LDAP be sane with lber.h]) + AC_TRY_LINK([#include <lber.h> +#include <ldap.h>],[ldap_open("foobar",1234);], + [gnupg_cv_func_ldaplber_init=yes],[gnupg_cv_func_ldaplber_init=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldaplber_init]) + fi + + if test "$gnupg_cv_func_ldaplber_init" = yes ; then + AC_DEFINE(NEED_LBER_H,1,[Define if the LDAP library requires including lber.h before ldap.h]) + fi + + if test "$gnupg_cv_func_ldap_init" = yes || \ + test "$gnupg_cv_func_ldaplber_init" = yes ; then + LDAPLIBS="$LDAP_LDFLAGS $MY_LDAPLIBS" + GPGKEYS_LDAP="gpgkeys_ldap$EXEEXT" + + AC_CHECK_FUNCS(ldap_get_option ldap_set_option ldap_start_tls_s) + + if test "$ac_cv_func_ldap_get_option" != yes ; then + AC_MSG_CHECKING([whether LDAP supports ld_errno]) + AC_TRY_LINK([#include <ldap.h>],[LDAP *ldap; ldap->ld_errno;], + [gnupg_cv_func_ldap_ld_errno=yes], + [gnupg_cv_func_ldap_ld_errno=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldap_ld_errno]) + + if test "$gnupg_cv_func_ldap_ld_errno" = yes ; then + AC_DEFINE(HAVE_LDAP_LD_ERRNO,1,[Define if the LDAP library supports ld_errno]) + fi + fi + fi + + LIBS=$_ldap_save_libs + + if test "$GPGKEYS_LDAP" != "" ; then break; fi + done + + AC_SUBST(GPGKEYS_LDAP) + AC_SUBST(LDAPLIBS) + AC_SUBST(LDAP_CPPFLAGS) + + CPPFLAGS=$_ldap_save_cppflags + LDFLAGS=$_ldap_save_ldflags +fi +])dnl -- cgit v1.2.3 From 4954c5f1c3733ec39857c2709a85de3bbe62e7ec Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 3 Jul 2006 13:26:19 +0000 Subject: better reporting of bad DNs --- ChangeLog | 4 ++++ TODO | 4 ---- configure.ac | 5 +++++ sm/ChangeLog | 5 +++++ sm/certreqgen.c | 30 +++++++++++++++++++++++------- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index eeb91bc0f..f949672c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-07-03 Werner Koch <wk@g10code.com> + + * configure.ac: Test for ksba_dn_teststr. + 2006-06-30 Werner Koch <wk@g10code.com> * keyserver/: New. Taken from 1.4.4 diff --git a/TODO b/TODO index 672fab9a7..4970a8ab6 100644 --- a/TODO +++ b/TODO @@ -13,10 +13,6 @@ We should always use valid S-Exp and not just parts. 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. ** Try to keep certificate references somewhere diff --git a/configure.ac b/configure.ac index 03d8809b9..2bb1d3fe9 100644 --- a/configure.ac +++ b/configure.ac @@ -512,6 +512,11 @@ AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_VERSION", # libksba is our X.509 support library # AM_PATH_KSBA("$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no) +# fixme: Remove the following test and require newer libksba instead. +_ksba_save_libs=$LIBS +LIBS=$KSBA_LIBS +AC_CHECK_FUNCS(ksba_dn_teststr) +LIBS=$_ksba_save_libs # # libusb allows us to use the integrated CCID smartcard reader driver. diff --git a/sm/ChangeLog b/sm/ChangeLog index 97fa8cd89..55a539ad6 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,8 @@ +2006-07-03 Werner Koch <wk@g10code.com> + + * certreqgen.c (proc_parameters): Print the component label of a + faulty DN. + 2006-06-26 Werner Koch <wk@g10code.com> * certdump.c (gpgsm_cert_log_name): New. diff --git a/sm/certreqgen.c b/sm/certreqgen.c index 744969719..205ca0e40 100644 --- a/sm/certreqgen.c +++ b/sm/certreqgen.c @@ -441,6 +441,7 @@ static int proc_parameters (ctrl_t ctrl, struct para_data_s *para, struct reqgen_ctrl_s *outctrl) { + gpg_error_t err; struct para_data_s *r; const char *s; int i; @@ -450,8 +451,9 @@ proc_parameters (ctrl_t ctrl, int rc; ksba_sexp_t public; int seq; - - /* check that we have all required parameters */ + size_t erroff, errlen; + + /* Check that we have all required parameters; */ assert (get_parameter (para, pKEYTYPE, 0)); /* We can only use RSA for now. There is a with pkcs-10 on how to @@ -483,17 +485,31 @@ proc_parameters (ctrl_t ctrl, if (parse_parameter_usage (para, pKEYUSAGE)) return gpg_error (GPG_ERR_INV_PARAMETER); - /* check that there is a subject name and that this DN fits our - requirements */ + /* Check that there is a subject name and that this DN fits our + requirements. */ if (!(s=get_parameter_value (para, pNAMEDN, 0))) { - r = get_parameter (para, pKEYTYPE, 0); + r = get_parameter (para, pNAMEDN, 0); log_error (_("line %d: no subject name given\n"), r->lnr); return gpg_error (GPG_ERR_INV_PARAMETER); } - /* fixme check s */ +#if HAVE_KSBA_DN_TESTSTR + err = ksba_dn_teststr (s, 0, &erroff, &errlen); + if (err) + { + r = get_parameter (para, pNAMEDN, 0); + if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME) + log_error (_("line %d: invalid subject name label `%.*s'\n"), + r->lnr, (int)errlen, s+erroff); + else + log_error (_("line %d: invalid subject name `%s' at pos %d\n"), + r->lnr, s, erroff); + + return gpg_error (GPG_ERR_INV_PARAMETER); + } +#endif /*HAVE_KSBA_DN_TESTSTR*/ - /* check that the optional email address is okay */ + /* Check that the optional email address is okay. */ for (seq=0; (s=get_parameter_value (para, pNAMEEMAIL, seq)); seq++) { if (has_invalid_email_chars (s) -- cgit v1.2.3 From d035d2a52e55c39f346a7d7ab44cf2dbe646eeef Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Fri, 21 Jul 2006 09:41:11 +0000 Subject: Support import from TrustedMIME (i.e. from simple keyBags) --- NEWS | 2 + agent/ChangeLog | 7 ++ agent/minip12.c | 235 +++++++++++++++++++++++++++++++++++++++++++++----------- doc/gpl.texi | 4 +- 4 files changed, 202 insertions(+), 46 deletions(-) diff --git a/NEWS b/NEWS index 7fafd44d3..e6cfb2b4a 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ Noteworthy changes in version 1.9.22 ------------------------------------------------- + * Enhanced pkcs#12 support to allow import from simple keyBags. + Noteworthy changes in version 1.9.21 (2006-06-20) ------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index a194e0d2e..e3d69d8b4 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,10 @@ +2006-07-21 Werner Koch <wk@g10code.com> + + * minip12.c (oid_pkcs_12_keyBag): New. + (parse_bag_encrypted_data): New arg R_RESULT. Support keybags and + return the key object. + (p12_parse): Take new arg into account. Free RESULT on error. + 2006-06-26 Werner Koch <wk@g10code.com> * gpg-agent.c (handle_signal): Print infor for SIGUSR2 only in diff --git a/agent/minip12.c b/agent/minip12.c index 912d387d8..243116d25 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -88,6 +88,8 @@ static unsigned char const oid_data[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; static unsigned char const oid_encryptedData[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; +static unsigned char const oid_pkcs_12_keyBag[11] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x01 }; static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 }; static unsigned char const oid_pkcs_12_CertBag[11] = { @@ -465,11 +467,13 @@ crypt_block (unsigned char *buffer, size_t length, char *salt, size_t saltlen, +/* Note: If R_RESULT is passed as NULL, a key object as already be + processed and thus we need to skip it here. */ static int parse_bag_encrypted_data (const unsigned char *buffer, size_t length, int startoffset, size_t *r_consumed, const char *pw, void (*certcb)(void*, const unsigned char*, size_t), - void *certcbarg) + void *certcbarg, gcry_mpi_t **r_result) { struct tag_info ti; const unsigned char *p = buffer; @@ -483,7 +487,12 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, int bad_pass = 0; unsigned char *cram_buffer = NULL; size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */ - + int is_3des = 0; + gcry_mpi_t *result = NULL; + int result_count; + + if (r_result) + *r_result = NULL; where = "start"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -529,10 +538,19 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, p += DIM(oid_pbeWithSHAAnd40BitRC2_CBC); n -= DIM(oid_pbeWithSHAAnd40BitRC2_CBC); } + else if (!ti.class && ti.tag == TAG_OBJECT_ID + && ti.length == DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC) + && !memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC, + DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC))) + { + p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC); + n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC); + is_3des = 1; + } else goto bailout; - where = "rc2-params"; + where = "rc2or3des-params"; if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class || ti.tag != TAG_SEQUENCE) @@ -557,7 +575,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, n--; } - where = "rc2-ciphertext"; + where = "rc2or3des-ciphertext"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -566,7 +584,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, { /* Mozilla exported certs now come with single byte chunks of octect strings. (Mozilla Firefox 1.0.4). Arghh. */ - where = "cram-rc2-ciphertext"; + where = "cram-rc2or3des-ciphertext"; cram_buffer = cram_octet_string ( p, &n, &consumed); if (!cram_buffer) goto bailout; @@ -581,7 +599,7 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, else goto bailout; - log_info ("%lu bytes of RC2 encrypted text\n", ti.length); + log_info ("%lu bytes of %s encrypted text\n",ti.length,is_3des?"3DES":"RC2"); plain = gcry_malloc_secure (ti.length); if (!plain) @@ -591,7 +609,9 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, } memcpy (plain, p, ti.length); crypt_block (plain, ti.length, salt, saltlen, - iter, pw, GCRY_CIPHER_RFC2268_40, 0); + iter, pw, + is_3des? GCRY_CIPHER_3DES : GCRY_CIPHER_RFC2268_40, + 0); n = ti.length; startoffset = 0; p_start = p = plain; @@ -625,7 +645,8 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, /* Loop over all certificates inside the bag. */ while (n) { - int isbag = 0; + int iscrlbag = 0; + int iskeybag = 0; where = "certbag.nextcert"; if (ti.class || ti.tag != TAG_SEQUENCE) @@ -647,7 +668,17 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, { p += DIM(oid_pkcs_12_CrlBag); n -= DIM(oid_pkcs_12_CrlBag); - isbag = 1; + iscrlbag = 1; + } + else if ( ti.length == DIM(oid_pkcs_12_keyBag) + && !memcmp (p, oid_pkcs_12_keyBag, DIM(oid_pkcs_12_keyBag))) + { + /* The TrustedMIME plugin for MS Outlook started to create + files with just one outer 3DES encrypted container and + inside the certificates as well as the key. */ + p += DIM(oid_pkcs_12_keyBag); + n -= DIM(oid_pkcs_12_keyBag); + iskeybag = 1; } else goto bailout; @@ -657,14 +688,106 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, goto bailout; if (ti.class != CONTEXT || ti.tag) goto bailout; - if (isbag) + if (iscrlbag) { log_info ("skipping unsupported crlBag\n"); p += ti.length; n -= ti.length; } + else if (iskeybag && (result || !r_result)) + { + log_info ("one keyBag already processed; skipping this one\n"); + p += ti.length; + n -= ti.length; + } + else if (iskeybag) + { + int len; + + log_info ("processing simple keyBag\n"); + + /* Fixme: This code is duplicated from parse_bag_data. */ + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER + || ti.length != 1 || *p) + goto bailout; + p++; n--; + if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + len = ti.length; + if (parse_tag (&p, &n, &ti)) + goto bailout; + if (len < ti.nhdr) + goto bailout; + len -= ti.nhdr; + if (ti.class || ti.tag != TAG_OBJECT_ID + || ti.length != DIM(oid_rsaEncryption) + || memcmp (p, oid_rsaEncryption, + DIM(oid_rsaEncryption))) + goto bailout; + p += DIM (oid_rsaEncryption); + n -= DIM (oid_rsaEncryption); + if (len < ti.length) + goto bailout; + len -= ti.length; + if (n < len) + goto bailout; + p += len; + n -= len; + if ( parse_tag (&p, &n, &ti) + || ti.class || ti.tag != TAG_OCTET_STRING) + goto bailout; + if ( parse_tag (&p, &n, &ti) + || ti.class || ti.tag != TAG_SEQUENCE) + goto bailout; + len = ti.length; + + result = gcry_calloc (10, sizeof *result); + if (!result) + { + log_error ( "error allocating result array\n"); + goto bailout; + } + result_count = 0; + + where = "reading.keybag.key-parameters"; + for (result_count = 0; len && result_count < 9;) + { + if ( parse_tag (&p, &n, &ti) + || ti.class || ti.tag != TAG_INTEGER) + goto bailout; + if (len < ti.nhdr) + goto bailout; + len -= ti.nhdr; + if (len < ti.length) + goto bailout; + len -= ti.length; + if (!result_count && ti.length == 1 && !*p) + ; /* ignore the very first one if it is a 0 */ + else + { + int rc; + + rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p, + ti.length, NULL); + if (rc) + { + log_error ("error parsing key parameter: %s\n", + gpg_strerror (rc)); + goto bailout; + } + result_count++; + } + p += ti.length; + n -= ti.length; + } + if (len) + goto bailout; + } else { + log_info ("processing certBag\n"); if (parse_tag (&p, &n, &ti)) goto bailout; if (ti.class || ti.tag != TAG_SEQUENCE) @@ -730,9 +853,19 @@ parse_bag_encrypted_data (const unsigned char *buffer, size_t length, *r_consumed = consumed; gcry_free (plain); gcry_free (cram_buffer); + if (r_result) + *r_result = result; return 0; bailout: + if (result) + { + int i; + + for (i=0; result[i]; i++) + gcry_mpi_release (result[i]); + gcry_free (result); + } if (r_consumed) *r_consumed = consumed; gcry_free (plain); @@ -1066,7 +1199,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, bagseqlength = ti.length; while (bagseqlength || bagseqndef) { - log_debug ( "at offset %u\n", (p - p_start)); +/* log_debug ( "at offset %u\n", (p - p_start)); */ where = "bag-sequence"; if (parse_tag (&p, &n, &ti)) goto bailout; @@ -1105,7 +1238,8 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, len -= DIM(oid_encryptedData); where = "bag.encryptedData"; if (parse_bag_encrypted_data (p, n, (p - p_start), &consumed, pw, - certcb, certcbarg)) + certcb, certcbarg, + result? NULL : &result)) goto bailout; if (lenndef) len += consumed; @@ -1115,7 +1249,7 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, { if (result) { - log_info ("already got an data object, skipping next one\n"); + log_info ("already got an key object, skipping this one\n"); p += ti.length; n -= ti.length; } @@ -1159,7 +1293,14 @@ p12_parse (const unsigned char *buffer, size_t length, const char *pw, return result; bailout: log_error ("error at \"%s\", offset %u\n", where, (p - p_start)); - /* fixme: need to release RESULT. */ + if (result) + { + int i; + + for (i=0; result[i]; i++) + gcry_mpi_release (result[i]); + gcry_free (result); + } gcry_free (cram_buffer); return NULL; } @@ -1227,6 +1368,8 @@ create_final (struct buffer_s *sequences, const char *pw, size_t *r_length) unsigned char keybuf[20]; gcry_md_hd_t md; int rc; + int with_mac = 1; + /* 9 steps to create the pkcs#12 Krampf. */ @@ -1264,7 +1407,8 @@ create_final (struct buffer_s *sequences, const char *pw, size_t *r_length) needed += 3; /* 0. And the final outer sequence. */ - needed += DIM (data_mactemplate); + if (with_mac) + needed += DIM (data_mactemplate); len[0] = needed; n = compute_tag_length (needed); needed += n; @@ -1311,37 +1455,40 @@ create_final (struct buffer_s *sequences, const char *pw, size_t *r_length) p += sequences[i].length; } - /* Intermezzo to compute the MAC. */ - maclen = p - macstart; - gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); - if (string_to_key (3, salt, 8, 2048, pw, 20, keybuf)) - { - gcry_free (result); - return NULL; - } - rc = gcry_md_open (&md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); - if (rc) - { - log_error ("gcry_md_open failed: %s\n", gpg_strerror (rc)); - gcry_free (result); - return NULL; - } - rc = gcry_md_setkey (md, keybuf, 20); - if (rc) + if (with_mac) { - log_error ("gcry_md_setkey failed: %s\n", gpg_strerror (rc)); + /* Intermezzo to compute the MAC. */ + maclen = p - macstart; + gcry_randomize (salt, 8, GCRY_STRONG_RANDOM); + if (string_to_key (3, salt, 8, 2048, pw, 20, keybuf)) + { + gcry_free (result); + return NULL; + } + rc = gcry_md_open (&md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); + if (rc) + { + log_error ("gcry_md_open failed: %s\n", gpg_strerror (rc)); + gcry_free (result); + return NULL; + } + rc = gcry_md_setkey (md, keybuf, 20); + if (rc) + { + log_error ("gcry_md_setkey failed: %s\n", gpg_strerror (rc)); + gcry_md_close (md); + gcry_free (result); + return NULL; + } + gcry_md_write (md, macstart, maclen); + + /* 8. Append the MAC template and fix it up. */ + memcpy (p, data_mactemplate, DIM (data_mactemplate)); + memcpy (p + DATA_MACTEMPLATE_SALT_OFF, salt, 8); + memcpy (p + DATA_MACTEMPLATE_MAC_OFF, gcry_md_read (md, 0), 20); + p += DIM (data_mactemplate); gcry_md_close (md); - gcry_free (result); - return NULL; } - gcry_md_write (md, macstart, maclen); - - /* 8. Append the MAC template and fix it up. */ - memcpy (p, data_mactemplate, DIM (data_mactemplate)); - memcpy (p + DATA_MACTEMPLATE_SALT_OFF, salt, 8); - memcpy (p + DATA_MACTEMPLATE_MAC_OFF, gcry_md_read (md, 0), 20); - p += DIM (data_mactemplate); - gcry_md_close (md); /* Ready. */ resultlen = p - result; @@ -1952,7 +2099,7 @@ main (int argc, char **argv) /* Local Variables: -compile-command: "gcc -Wall -O -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error" +compile-command: "gcc -Wall -O0 -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error" End: */ #endif /* TEST */ diff --git a/doc/gpl.texi b/doc/gpl.texi index ca0508fad..00108d230 100644 --- a/doc/gpl.texi +++ b/doc/gpl.texi @@ -6,7 +6,7 @@ @display Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc. -59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -352,7 +352,7 @@ 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. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @end smallexample Also add information on how to contact you by electronic and paper mail. -- cgit v1.2.3 From b37c1ce1b9f13f5e168d0953bffd0f29d9f6553e Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Mon, 24 Jul 2006 11:20:33 +0000 Subject: Create bag attributes so that Mozilla will accept these files. Tested with using a CAcert generated certificate. --- NEWS | 3 ++ agent/ChangeLog | 8 +++++ agent/minip12.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++----- tests/pkits/README | 3 ++ 4 files changed, 93 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index e6cfb2b4a..2e7201d1e 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ Noteworthy changes in version 1.9.22 * Enhanced pkcs#12 support to allow import from simple keyBags. + * Exporting to pkcs#12 now create bag attributes so that Mozilla is + able to import the files. + Noteworthy changes in version 1.9.21 (2006-06-20) ------------------------------------------------- diff --git a/agent/ChangeLog b/agent/ChangeLog index e3d69d8b4..2048f5c18 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2006-07-24 Werner Koch <wk@g10code.com> + + * minip12.c (build_key_bag): New args SHA1HASH and + KEYIDSTR. Append bag Attributes if these args are given. + (build_cert_sequence): ditto. + (p12_build): Calculate certificate hash and pass to build + functions. + 2006-07-21 Werner Koch <wk@g10code.com> * minip12.c (oid_pkcs_12_keyBag): New. diff --git a/agent/minip12.c b/agent/minip12.c index 243116d25..536170856 100644 --- a/agent/minip12.c +++ b/agent/minip12.c @@ -134,6 +134,23 @@ static unsigned char const data_mactemplate[51] = { #define DATA_MACTEMPLATE_MAC_OFF 17 #define DATA_MACTEMPLATE_SALT_OFF 39 +static unsigned char const data_attrtemplate[106] = { + 0x31, 0x7c, 0x30, 0x55, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, + 0x48, 0x1e, 0x46, 0x00, 0x47, 0x00, 0x6e, 0x00, + 0x75, 0x00, 0x50, 0x00, 0x47, 0x00, 0x20, 0x00, + 0x65, 0x00, 0x78, 0x00, 0x70, 0x00, 0x6f, 0x00, + 0x72, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, + 0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x20, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, + 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, + 0x66, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, + 0x04, 0x14 }; /* Need to append SHA-1 digest. */ +#define DATA_ATTRTEMPLATE_KEYID_OFF 73 + struct buffer_s { unsigned char *buffer; @@ -1648,6 +1665,7 @@ build_key_sequence (gcry_mpi_t *kparms, size_t *r_length) static unsigned char * build_key_bag (unsigned char *buffer, size_t buflen, char *salt, + const unsigned char *sha1hash, const char *keyidstr, size_t *r_length) { size_t len[11], needed; @@ -1671,6 +1689,10 @@ build_key_bag (unsigned char *buffer, size_t buflen, char *salt, len[7] = needed; needed += compute_tag_length (needed); + /* 6b. The attributes which are appended at the end. */ + if (sha1hash) + needed += DIM (data_attrtemplate) + 20; + /* 6. Prepend the shroudedKeyBag OID. */ needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); @@ -1741,12 +1763,26 @@ build_key_bag (unsigned char *buffer, size_t buflen, char *salt, memcpy (p + DATA_3DESITER2048_SALT_OFF, salt, 8); p += DIM (data_3desiter2048); - /* 10. And finally the octet string with the encrypted data. */ + /* 10. And the octet string with the encrypted data. */ p = store_tag_length (p, TAG_OCTET_STRING, buflen); memcpy (p, buffer, buflen); p += buflen; + + /* Append the attributes whose length we calculated at step 2b. */ + if (sha1hash) + { + int i; + + memcpy (p, data_attrtemplate, DIM (data_attrtemplate)); + for (i=0; i < 8; i++) + p[DATA_ATTRTEMPLATE_KEYID_OFF+2*i+1] = keyidstr[i]; + p += DIM (data_attrtemplate); + memcpy (p, sha1hash, 20); + p += 20; + } + + keybaglen = p - keybag; - if (needed != keybaglen) log_debug ("length mismatch: %lu, %lu\n", (unsigned long)needed, (unsigned long)keybaglen); @@ -1856,13 +1892,17 @@ build_cert_bag (unsigned char *buffer, size_t buflen, char *salt, static unsigned char * -build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) +build_cert_sequence (unsigned char *buffer, size_t buflen, + const unsigned char *sha1hash, const char *keyidstr, + size_t *r_length) { size_t len[8], needed, n; unsigned char *p, *certseq; size_t certseqlen; int i; + assert (strlen (keyidstr) == 8); + /* Walk 8 steps down to collect the info: */ /* 7. The data goes into an octet string. */ @@ -1884,6 +1924,10 @@ build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) len[3] = needed; needed += compute_tag_length (needed); + /* 2b. The attributes which are appended at the end. */ + if (sha1hash) + needed += DIM (data_attrtemplate) + 20; + /* 2. An OID. */ needed += 2 + DIM (oid_pkcs_12_CertBag); @@ -1932,16 +1976,27 @@ build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length) /* 6. Store a [0] tag. */ p = store_tag_length (p, 0xa0, len[6]); - /* 7. And finally the octet string with the actual certificate. */ + /* 7. And the octet string with the actual certificate. */ p = store_tag_length (p, TAG_OCTET_STRING, buflen); memcpy (p, buffer, buflen); p += buflen; - certseqlen = p - certseq; + /* Append the attributes whose length we calculated at step 2b. */ + if (sha1hash) + { + memcpy (p, data_attrtemplate, DIM (data_attrtemplate)); + for (i=0; i < 8; i++) + p[DATA_ATTRTEMPLATE_KEYID_OFF+2*i+1] = keyidstr[i]; + p += DIM (data_attrtemplate); + memcpy (p, sha1hash, 20); + p += 20; + } + + certseqlen = p - certseq; if (needed != certseqlen) log_debug ("length mismatch: %lu, %lu\n", (unsigned long)needed, (unsigned long)certseqlen); - + /* Append some pad characters; we already allocated extra space. */ n = 8 - certseqlen % 8; for (i=0; i < n; i++, certseqlen++) @@ -1964,13 +2019,23 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, char salt[8]; struct buffer_s seqlist[3]; int seqlistidx = 0; + unsigned char sha1hash[20]; + char keyidstr[8+1]; n = buflen = 0; /* (avoid compiler warning). */ + memset (sha1hash, 0, 20); + *keyidstr = 0; if (cert && certlen) { + /* Calculate the hash value we need for the bag attributes. */ + gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash, cert, certlen); + sprintf (keyidstr, "%02x%02x%02x%02x", + sha1hash[16], sha1hash[17], sha1hash[18], sha1hash[19]); + /* Encode the certificate. */ - buffer = build_cert_sequence (cert, certlen, &buflen); + buffer = build_cert_sequence (cert, certlen, sha1hash, keyidstr, + &buflen); if (!buffer) goto failure; @@ -1989,6 +2054,7 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, seqlistidx++; } + if (kparms) { /* Encode the key. */ @@ -2001,7 +2067,12 @@ p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen, crypt_block (buffer, buflen, salt, 8, 2048, pw, GCRY_CIPHER_3DES, 1); /* Encode the encrypted stuff into a bag. */ - seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, &n); + if (cert && certlen) + seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, + sha1hash, keyidstr, &n); + else + seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, + NULL, NULL, &n); seqlist[seqlistidx].length = n; gcry_free (buffer); buffer = NULL; diff --git a/tests/pkits/README b/tests/pkits/README index 1f944ad58..79678cf30 100644 --- a/tests/pkits/README +++ b/tests/pkits/README @@ -7,3 +7,6 @@ http://csrc.nist.gov/pki/testing/x509paths.html . README - this file. PKITS_data.tar.bz2 - the orginal ZIP file, repackaged as a tarball. Makefile.am - Part of our build system. + + +The password for the p12 files is "password". -- cgit v1.2.3 From de5070caf07854852a36722a0d85453cbbc93c84 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 27 Jul 2006 14:18:55 +0000 Subject: Preparing a new release --- ChangeLog | 6 +++ NEWS | 5 ++- README | 2 +- TODO | 3 +- configure.ac | 5 ++- g10/ChangeLog | 21 ++++++++++ g10/Makefile.am | 2 +- g10/gpg.c | 8 +--- g10/keydb.h | 13 +++++- g10/parse-packet.c | 14 +++++++ g10/pkclist.c | 21 +++++----- g10/sign.c | 101 ++++++++++++++++++++++++++--------------------- keyserver/ChangeLog | 9 +++++ keyserver/curl-shim.c | 8 ++-- keyserver/gpgkeys_hkp.c | 9 +++-- keyserver/gpgkeys_ldap.c | 22 +++++++---- m4/ChangeLog | 4 ++ m4/Makefile.am | 5 ++- m4/autobuild.m4 | 34 ++++++++++++++++ po/de.po | 70 ++++++++++++++++---------------- 20 files changed, 238 insertions(+), 124 deletions(-) create mode 100644 m4/autobuild.m4 diff --git a/ChangeLog b/ChangeLog index f949672c7..eb2c2ed97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-07-27 Werner Koch <wk@g10code.com> + + Released 1.9.22. + + * configure.ac: Call AB_INIT. + 2006-07-03 Werner Koch <wk@g10code.com> * configure.ac: Test for ksba_dn_teststr. diff --git a/NEWS b/NEWS index 2e7201d1e..05aa0549a 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,13 @@ -Noteworthy changes in version 1.9.22 +Noteworthy changes in version 1.9.22 (2006-07-27) ------------------------------------------------- - * Enhanced pkcs#12 support to allow import from simple keyBags. * Exporting to pkcs#12 now create bag attributes so that Mozilla is able to import the files. + * Fixed uploading of certain keys to the smart card. + Noteworthy changes in version 1.9.21 (2006-06-20) ------------------------------------------------- diff --git a/README b/README index 28637c1fb..2a8ad604b 100644 --- a/README +++ b/README @@ -13,7 +13,7 @@ You should use this GnuPG version if you want to use the gpg-agent or gpgsm (the S/MIME variant of gpg). Note that the gpg-agent is also helpful when using the standard gpg versions (1.4.x as well as some of the old 1.2.x). There are no problems installing 1.4 and 1.9 -alongside; in act we suggest to do this. +alongside; in dact we suggest to do this. BUILD INSTRUCTIONS diff --git a/TODO b/TODO index 4970a8ab6..29714dfe4 100644 --- a/TODO +++ b/TODO @@ -112,8 +112,7 @@ might want to have an agent context for each service request Remove the whole stuff? ** qbits We pass a new qbit parameter to genkey - implement this in libgcrypt. -** Makefile.am - Remove the no-pointer-sign kludge. + * common/ ** ttyio diff --git a/configure.ac b/configure.ac index 2bb1d3fe9..054e63053 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,7 @@ min_automake_version="1.9.3" # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [1.9.22]) -m4_define([my_issvn], [yes]) +m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ @@ -57,6 +57,7 @@ AC_CONFIG_SRCDIR(sm/gpgsm.c) AM_CONFIG_HEADER(config.h) AC_CANONICAL_TARGET() AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AB_INIT AC_GNU_SOURCE @@ -1250,7 +1251,6 @@ jnlib/Makefile common/Makefile kbx/Makefile g10/Makefile -keyserver/Makefile sm/Makefile agent/Makefile scd/Makefile @@ -1260,6 +1260,7 @@ tests/Makefile ]) AC_OUTPUT +#./autogen keyserver/Makefile #tests/pkits/Makefile diff --git a/g10/ChangeLog b/g10/ChangeLog index 2fba9c488..7f204cde9 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,24 @@ +2006-07-27 Werner Koch <wk@g10code.com> + + * parse-packet.c (parse_comment): Cap comments at 65k. + (parse_gpg_control): Skip too large control packets. + +2006-07-24 David Shaw <dshaw@jabberwocky.com> (wk) + + * keydb.h, pkclist.c (select_algo_from_prefs, algo_available): + Pass a union for preference hints rather than doing void * games. + + * sign.c (sign_file): Use it here. + + * sign.c (sign_file): When signing with multiple DSA keys, one + being DSA1 and one being DSA2 and encrypting at the same time, if + the recipient preferences give a hash that can work with the DSA2 + key, then allow the DSA1 key to be promoted rather than giving up + and using hash_for(). + + * pkclist.c (algo_available): Automatically enable DSA2 mode when + handling a key that clearly isn't DSA1 (i.e. q!=160). + 2006-06-30 Werner Koch <wk@g10code.com> * misc.c (checksum_mpi): No need for nbits as they are alredy diff --git a/g10/Makefile.am b/g10/Makefile.am index fb54dd9f0..a9847cfa7 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -27,7 +27,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common \ include $(top_srcdir)/am/cmacros.am -AM_CFLAGS = $(LIBGCRYPT_CFLAGS) -Wno-pointer-sign +AM_CFLAGS = $(LIBGCRYPT_CFLAGS) needed_libs = ../gl/libgnu.a ../common/libcommon.a ../jnlib/libjnlib.a diff --git a/g10/gpg.c b/g10/gpg.c index c1a0be50f..c558b7246 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -357,7 +357,6 @@ enum cmd_and_opt_values oAllowMultisigVerification, oEnableDSA2, oDisableDSA2, - oDebugAllowRun, oNoop }; @@ -705,7 +704,6 @@ static ARGPARSE_OPTS opts[] = { { oAutoKeyLocate, "auto-key-locate", 2, "@"}, { oNoAutoKeyLocate, "no-auto-key-locate", 0, "@"}, - { oDebugAllowRun, "debug_allow_run", 0, "@"}, {0,NULL,0,NULL} }; @@ -1761,7 +1759,6 @@ main (int argc, char **argv ) int with_fpr = 0; /* make an option out of --fingerprint */ int any_explicit_recipient = 0; int require_secmem=0,got_secmem=0; - int allow_run = 0; #ifdef __riscos__ opt.lock_once = 1; @@ -2754,8 +2751,6 @@ main (int argc, char **argv ) case oEnableDSA2: opt.flags.dsa2=1; break; case oDisableDSA2: opt.flags.dsa2=0; break; - case oDebugAllowRun: allow_run = 1; break; - case oNoop: break; default : pargs.err = configfp? 1:2; break; @@ -2809,8 +2804,7 @@ main (int argc, char **argv ) } #endif - if (!allow_run) - log_fatal ("This version of gpg is not ready for use, use gpg 1.4.x\n"); + log_info ("WARNING: This version of gpg is not ready for use, use gpg 1.4.x\n"); /* FIXME: We should use logging to a file only in server mode; however we have not yet implemetyed that. Thus we try to get diff --git a/g10/keydb.h b/g10/keydb.h index f8be6efb9..2aab31cfa 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -144,6 +144,14 @@ struct keydb_search_desc { int exact; }; + +/* Helper type for preference fucntions. */ +union pref_hint +{ + int digest_length; +}; + + /*-- keydb.c --*/ /* @@ -175,9 +183,10 @@ 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 algo_available( preftype_t preftype, int algo, + const union pref_hint *hint ); int select_algo_from_prefs( PK_LIST pk_list, int preftype, - int request, void *hint ); + int request, const union pref_hint *hint); int select_mdc_from_pklist (PK_LIST pk_list); /*-- skclist.c --*/ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index d9a87f108..33472da4d 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -2147,6 +2147,16 @@ parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { byte *p; + /* Cap comment packet at a reasonable value to avoid an integer + overflow in the malloc below. Comment packets are actually not + anymore define my OpenPGP and we even stopped to use our + private comment packet. */ + if (pktlen>65536) + { + log_error ("packet(%d) too large\n", pkttype); + iobuf_skip_rest (inp, pktlen, 0); + return G10ERR_INVALID_PACKET; + } packet->pkt.comment = xmalloc(sizeof *packet->pkt.comment + pktlen - 1); packet->pkt.comment->len = pktlen; p = packet->pkt.comment->data; @@ -2220,6 +2230,7 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, } mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--; + /* Note that namelen will never exceed 255 bytes. */ pt = pkt->pkt.plaintext = xmalloc(sizeof *pkt->pkt.plaintext + namelen -1); pt->new_ctb = new_ctb; pt->mode = mode; @@ -2399,6 +2410,9 @@ parse_gpg_control( IOBUF inp, int pkttype, if ( sesmark[i] != iobuf_get_noeof(inp) ) goto skipit; } + if (pktlen > 4096) + goto skipit; /* Definitely too large. We skip it to avoid an + overflow in the malloc. */ if ( list_mode ) puts ("- gpg control packet"); diff --git a/g10/pkclist.c b/g10/pkclist.c index d3cda144f..f90137aff 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1186,7 +1186,7 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) preference list, so I'm including it. -dms */ int -algo_available( preftype_t preftype, int algo, void *hint ) +algo_available( preftype_t preftype, int algo, const union pref_hint *hint) { if( preftype == PREFTYPE_SYM ) { @@ -1210,18 +1210,18 @@ algo_available( preftype_t preftype, int algo, void *hint ) } else if( preftype == PREFTYPE_HASH ) { - if(hint) + if (hint && hint->digest_length) { - if(opt.flags.dsa2) + if (hint->digest_length!=20 || opt.flags.dsa2) { - /* If --enable-dsa2 is set, then we'll accept a hash - that is larger than we need. If --enable-dsa2 is not - set, then we won't accept any hash that isn't exactly - the right size. */ - if ((*(int *)hint) > gcry_md_get_algo_dlen (algo)) + /* If --enable-dsa2 is set or the hash isn't 160 bits + (which implies DSA2), then we'll accept a hash that + is larger than we need. Otherwise we won't accept + any hash that isn't exactly the right size. */ + if (hint->digest_length > gcry_md_get_algo_dlen (algo)) return 0; } - else if (((*(int *)hint) != gcry_md_get_algo_dlen (algo))) + else if (hint->digest_length != gcry_md_get_algo_dlen (algo)) return 0; } @@ -1259,7 +1259,8 @@ algo_available( preftype_t preftype, int algo, void *hint ) * Return -1 if we could not find an algorithm. */ int -select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, void *hint) +select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, + const union pref_hint *hint) { PK_LIST pkr; u32 bits[8]; diff --git a/g10/sign.c b/g10/sign.c index 0538f0020..7b6a81e10 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -320,27 +320,6 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig, } else { -#if 0 /* disabled *. - /* Disabled for now. It seems reasonable to accept a - truncated hash for a DSA1 key, even though we don't - generate it without --enable-dsa2. Be liberal in what you - accept, etc. */ - - /* If it's a DSA key, and q is 160 bits, it might be an - old-style DSA key. If the hash doesn't match the q, fail - unless --enable-dsa2 is set. If the q isn't 160 bits, then - allow any hash since it must be a DSA2 key (if the hash is - too small, we'll fail in encode_md_value). */ - if (sk->pubkey_algo==PUBKEY_ALGO_DSA - && (gcry_mpi_get_nbits (sk->skey[1])/8)==20 - && !opt.flags.dsa2 - && gcry_md_get_algo_dlen (digest_algo)!=20) - { - log_error(_("DSA requires the use of a 160 bit hash algorithm\n")); - return G10ERR_GENERAL; - } -#endif /* disabled */ - frame = encode_md_value( NULL, sk, md, digest_algo ); if (!frame) return G10ERR_GENERAL; @@ -869,8 +848,13 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if (DBG_HASHING) gcry_md_start_debug (mfx.md, "sign"); - /* If we're encrypting and signing, it is reasonable to pick the - hash algorithm to use out of the recepient key prefs. */ + /* If we're encrypting and signing, it is reasonable to pick the + hash algorithm to use out of the recepient key prefs. This is + best effort only, as in a DSA2 and smartcard world there are + cases where we cannot please everyone with a single hash (DSA2 + wants >160 and smartcards want =160). In the future this could + be more complex with different hashes for each sk, but the + current design requires a single hash for all SKs. */ if(pk_list) { if(opt.def_digest_algo) @@ -886,30 +870,57 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } else { - int hashlen=0,algo; + int algo, smartcard=0; + union pref_hint hint; + + hint.digest_length = 0; /* Of course, if the recipient asks for something - unreasonable (like a non-160-bit hash for DSA, for - example), then don't do it. Check all sk's - if any - are DSA, then the hash must be 160-bit. In the future - this can be more complex with different hashes for each - sk, but so long as there is only one signing algorithm - with hash restrictions, this is ok. -dms */ - - /* Current smartcards only do 160-bit hashes as well. - Note that this may well have to change as the cards add - algorithms. */ - - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) - if(sk_rover->sk->pubkey_algo==PUBKEY_ALGO_DSA - || (sk_rover->sk->is_protected - && sk_rover->sk->protect.s2k.mode==1002)) - hashlen=20; - - if((algo= - select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1, - hashlen?&hashlen:NULL))>0) - recipient_digest_algo=algo; + unreasonable (like the wrong hash for a DSA key) then + don't do it. Check all sk's - if any are DSA or live + on a smartcard, then the hash has restrictions and we + may not be able to give the recipient what they want. + For DSA, pass a hint for the largest q we have. Note + that this means that a q>160 key will override a q=160 + key and force the use of truncation for the q=160 key. + The alternative would be to ignore the recipient prefs + completely and get a different hash for each DSA key in + hash_for(). The override behavior here is more or less + reasonable as it is under the control of the user which + keys they sign with for a given message and the fact + that the message with multiple signatures won't be + usable on an implementation that doesn't understand + DSA2 anyway. */ + + for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) + { + if (sk_rover->sk->pubkey_algo == PUBKEY_ALGO_DSA) + { + int temp_hashlen = gcry_mpi_get_nbits + (sk_rover->sk->skey[1])+7/8; + + /* Pick a hash that is large enough for our + largest q */ + + if (hint.digest_length<temp_hashlen) + hint.digest_length=temp_hashlen; + } + else if (sk_rover->sk->is_protected + && sk_rover->sk->protect.s2k.mode == 1002) + smartcard = 1; + } + + /* Current smartcards only do 160-bit hashes. If we have + to have a >160-bit hash, then we can't use the + recipient prefs as we'd need both =160 and >160 at the + same time and recipient prefs currently require a + single hash for all signatures. All this may well have + to change as the cards add algorithms. */ + + if (!smartcard || (smartcard && hint.digest_length==20)) + if ( (algo= + select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,&hint)) > 0) + recipient_digest_algo=algo; } } diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog index c171f6a3a..c427c4778 100644 --- a/keyserver/ChangeLog +++ b/keyserver/ChangeLog @@ -1,3 +1,12 @@ +2006-07-24 David Shaw <dshaw@jabberwocky.com> (wk) + + * curl-shim.c (curl_easy_perform): Minor cleanup of proxy code. + + * gpgkeys_hkp.c (send_key) + * gpgkeys_ldap.c (send_key, send_key_keyserver): Fix string + matching problem when the ascii armored form of the key happens to + match "KEY" at the beginning of the line. + 2006-04-26 David Shaw <dshaw@jabberwocky.com> * gpgkeys_http.c, gpgkeys_oldhkp.c: Removed. diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c index 4a4d18f56..c71c655b5 100644 --- a/keyserver/curl-shim.c +++ b/keyserver/curl-shim.c @@ -164,13 +164,11 @@ curl_easy_perform(CURL *curl) /* Emulate the libcurl proxy behavior. If the calling program set a proxy, use it. If it didn't set a proxy or set it to NULL, check for one in the environment. If the calling program explicitly - set a null-string proxy, don't set a proxy at all. */ + set a null-string proxy the http code doesn't use a proxy at + all. */ if(curl->proxy) - { - if(*curl->proxy) - proxy=curl->proxy; - } + proxy=curl->proxy; else proxy=getenv(HTTP_PROXY_ENV); diff --git a/keyserver/gpgkeys_hkp.c b/keyserver/gpgkeys_hkp.c index b3ebcf1a9..e6de3634c 100644 --- a/keyserver/gpgkeys_hkp.c +++ b/keyserver/gpgkeys_hkp.c @@ -86,7 +86,7 @@ send_key(int *eof) CURLcode res; char request[MAX_URL+15]; int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR; - char keyid[17]; + char keyid[17],state[6]; char line[MAX_LINE]; char *key=NULL,*encoded_key=NULL; size_t keylen=0,keymax=0; @@ -94,7 +94,8 @@ send_key(int *eof) /* Read and throw away input until we see the BEGIN */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) + if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2 + && strcmp(state,"BEGIN")==0) { begin=1; break; @@ -112,7 +113,8 @@ send_key(int *eof) /* Now slurp up everything until we see the END */ while(fgets(line,MAX_LINE,input)) - if(sscanf(line,"KEY %16s END\n",keyid)==1) + if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2 + && strcmp(state,"END")==0) { end=1; break; @@ -194,6 +196,7 @@ send_key(int *eof) { fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer); ret=curl_err_to_gpg_err(res); + goto fail; } else fprintf(output,"\nKEY %s SENT\n",keyid); diff --git a/keyserver/gpgkeys_ldap.c b/keyserver/gpgkeys_ldap.c index b4bd00e4f..b56cca1cf 100644 --- a/keyserver/gpgkeys_ldap.c +++ b/keyserver/gpgkeys_ldap.c @@ -567,7 +567,7 @@ send_key(int *eof) { int err,begin=0,end=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR; char *dn=NULL,line[MAX_LINE],*key=NULL; - char keyid[17]; + char keyid[17],state[6]; LDAPMod **modlist,**addlist,**ml; modlist=malloc(sizeof(LDAPMod *)); @@ -608,7 +608,8 @@ send_key(int *eof) /* Assemble the INFO stuff into LDAP attributes */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"INFO %16s BEGIN\n",keyid)==1) + if(sscanf(line,"INFO%*[ ]%16s%*[ ]%5s\n",keyid,state)==2 + && strcmp(state,"BEGIN")==0) { begin=1; break; @@ -653,7 +654,8 @@ send_key(int *eof) /* Now parse each line until we see the END */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"INFO %16s END\n",keyid)==1) + if(sscanf(line,"INFO%*[ ]%16s%*[ ]%3s\n",keyid,state)==2 + && strcmp(state,"END")==0) { end=1; break; @@ -674,7 +676,8 @@ send_key(int *eof) /* Read and throw away stdin until we see the BEGIN */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) + if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2 + && strcmp(state,"BEGIN")==0) { begin=1; break; @@ -692,7 +695,8 @@ send_key(int *eof) /* Now slurp up everything until we see the END */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s END\n",keyid)==1) + if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2 + && strcmp(state,"END")==0) { end=1; break; @@ -778,7 +782,7 @@ send_key_keyserver(int *eof) { int err,begin=0,end=0,keysize=1,ret=KEYSERVER_INTERNAL_ERROR; char *dn=NULL,line[MAX_LINE],*key[2]={NULL,NULL}; - char keyid[17]; + char keyid[17],state[6]; LDAPMod mod, *attrs[2]; memset(&mod,0,sizeof(mod)); @@ -812,7 +816,8 @@ send_key_keyserver(int *eof) /* Read and throw away stdin until we see the BEGIN */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s BEGIN\n",keyid)==1) + if(sscanf(line,"KEY%*[ ]%16s%*[ ]%5s\n",keyid,state)==2 + && strcmp(state,"BEGIN")==0) { begin=1; break; @@ -830,7 +835,8 @@ send_key_keyserver(int *eof) /* Now slurp up everything until we see the END */ while(fgets(line,MAX_LINE,input)!=NULL) - if(sscanf(line,"KEY %16s END\n",keyid)==1) + if(sscanf(line,"KEY%*[ ]%16s%*[ ]%3s\n",keyid,state)==2 + && strcmp(state,"END")==0) { end=1; break; diff --git a/m4/ChangeLog b/m4/ChangeLog index 2cc6a308e..f666fa38d 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,7 @@ +2006-07-27 Werner Koch <wk@g10code.com> + + * autobuild.m4: New. + 2006-06-30 Werner Koch <wk@g10code.com> * ldap.m4: New. Taken from gnupg 1.4.4 diff --git a/m4/Makefile.am b/m4/Makefile.am index d218b73b7..7eb76cb4d 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -1,5 +1,8 @@ EXTRA_DIST = intmax.m4 longdouble.m4 longlong.m4 printf-posix.m4 signed.m4 size_max.m4 wchar_t.m4 wint_t.m4 xsize.m4 codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 -EXTRA_DIST += ldap.m4 +EXTRA_DIST += ldap.m4 EXTRA_DIST += gpg-error.m4 libgcrypt.m4 libassuan.m4 ksba.m4 + +EXTRA_DIST += autobuild.m4 + diff --git a/m4/autobuild.m4 b/m4/autobuild.m4 new file mode 100644 index 000000000..bd1f4dc1b --- /dev/null +++ b/m4/autobuild.m4 @@ -0,0 +1,34 @@ +# autobuild.m4 serial 2 (autobuild-3.3) +# Copyright (C) 2004 Simon Josefsson +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# This file can can be used in projects which are not available under +# the GNU General Public License or the GNU Library General Public +# License but which still want to provide support for Autobuild. + +# Usage: AB_INIT([MODE]). +AC_DEFUN([AB_INIT], +[ + AC_REQUIRE([AC_CANONICAL_BUILD]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + AC_MSG_NOTICE([autobuild project... ${PACKAGE_NAME:-$PACKAGE}]) + AC_MSG_NOTICE([autobuild revision... ${PACKAGE_VERSION:-$VERSION}]) + hostname=`hostname` + if test "$hostname"; then + AC_MSG_NOTICE([autobuild hostname... $hostname]) + fi + ifelse([$1],[],,[AC_MSG_NOTICE([autobuild mode... $1])]) + date=`date +%Y%m%d-%H%M%S` + if test "$?" != 0; then + date=`date` + fi + if test "$date"; then + AC_MSG_NOTICE([autobuild timestamp... $date]) + fi +]) diff --git a/po/de.po b/po/de.po index f95881efb..3861a486f 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg2 1.9.18\n" "Report-Msgid-Bugs-To: translations@gnupg.org\n" -"POT-Creation-Date: 2006-06-20 18:45+0200\n" +"POT-Creation-Date: 2006-07-24 16:19+0200\n" "PO-Revision-Date: 2006-06-20 20:04+0200\n" "Last-Translator: Werner Koch <wk@gnupg.org>\n" "Language-Team: de\n" @@ -215,45 +215,45 @@ msgstr "stat() Aufruf für `%s' fehlgeschlagen: %s\n" msgid "can't use `%s' as home directory\n" msgstr "Die Datei `%s' kann nicht als Home-Verzeichniss benutzt werden\n" -#: agent/gpg-agent.c:1402 +#: agent/gpg-agent.c:1403 #, c-format msgid "handler 0x%lx for fd %d started\n" msgstr "Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1412 +#: agent/gpg-agent.c:1413 #, c-format msgid "handler 0x%lx for fd %d terminated\n" msgstr "Handhabungsroutine 0x%lx für den fd %d beendet\n" -#: agent/gpg-agent.c:1426 +#: agent/gpg-agent.c:1427 #, c-format msgid "ssh handler 0x%lx for fd %d started\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d gestartet\n" -#: agent/gpg-agent.c:1433 +#: agent/gpg-agent.c:1434 #, c-format msgid "ssh handler 0x%lx for fd %d terminated\n" msgstr "SSH Handhabungsroutine 0x%lx für fd %d beendet\n" -#: agent/gpg-agent.c:1527 scd/scdaemon.c:1108 +#: agent/gpg-agent.c:1528 scd/scdaemon.c:1108 #, c-format msgid "pth_select failed: %s - waiting 1s\n" msgstr "pth_select() Aufruf fehlgeschlagen: %s - warte 1s\n" -#: agent/gpg-agent.c:1611 scd/scdaemon.c:1165 +#: agent/gpg-agent.c:1612 scd/scdaemon.c:1165 #, c-format msgid "%s %s stopped\n" msgstr "%s %s angehalten\n" -#: agent/gpg-agent.c:1632 +#: agent/gpg-agent.c:1633 msgid "no gpg-agent running in this session\n" msgstr "Der gpg-agent läuft nicht für diese Session\n" -#: agent/gpg-agent.c:1642 common/simple-pwquery.c:324 sm/call-agent.c:144 +#: agent/gpg-agent.c:1643 common/simple-pwquery.c:324 sm/call-agent.c:144 msgid "malformed GPG_AGENT_INFO environment variable\n" msgstr "Die Variable GPG_AGENT_INFO ist fehlerhaft\n" -#: agent/gpg-agent.c:1654 common/simple-pwquery.c:336 sm/call-agent.c:156 +#: agent/gpg-agent.c:1655 common/simple-pwquery.c:336 sm/call-agent.c:156 #, c-format msgid "gpg-agent protocol version %d is not supported\n" msgstr "Das gpg-agent Protocol %d wird nicht unterstützt\n" @@ -816,23 +816,23 @@ msgstr "keine" msgid "[none]" msgstr "[keine]" -#: sm/certdump.c:499 sm/certdump.c:562 +#: sm/certdump.c:529 sm/certdump.c:592 msgid "[Error - invalid encoding]" msgstr "[Fehler - Ungültige Kodierung]" -#: sm/certdump.c:507 +#: sm/certdump.c:537 msgid "[Error - out of core]" msgstr "[Fehler - Nich genügend Speicher]" -#: sm/certdump.c:542 +#: sm/certdump.c:572 msgid "[Error - No name]" msgstr "[Fehler - Kein Name]" -#: sm/certdump.c:567 +#: sm/certdump.c:597 msgid "[Error - invalid DN]" msgstr "[Fehler - Ungültiger DN]" -#: sm/certdump.c:728 +#: sm/certdump.c:758 #, c-format msgid "" "Please enter the passphrase to unlock the secret key for:\n" @@ -916,91 +916,91 @@ msgstr "Der Herausgeber wird von einer externen Stelle gesucht\n" msgid "number of issuers matching: %d\n" msgstr "Anzahl der übereinstimmenden Heruasgeber: %d\n" -#: sm/certchain.c:514 sm/certchain.c:676 sm/certchain.c:1114 sm/decrypt.c:261 +#: sm/certchain.c:514 sm/certchain.c:678 sm/certchain.c:1116 sm/decrypt.c:261 #: sm/encrypt.c:342 sm/sign.c:325 sm/verify.c:107 msgid "failed to allocated keyDB handle\n" msgstr "Ein keyDB Handle konnte nicht bereitgestellt werden\n" -#: sm/certchain.c:603 +#: sm/certchain.c:605 msgid "certificate has been revoked" msgstr "Das Zertifikat wurde widerrufen" -#: sm/certchain.c:612 +#: sm/certchain.c:614 msgid "no CRL found for certificate" msgstr "Keine CRL für das Zertifikat gefunden" -#: sm/certchain.c:616 +#: sm/certchain.c:618 msgid "the available CRL is too old" msgstr "Die vorhandene CRL ist zu alt" -#: sm/certchain.c:618 +#: sm/certchain.c:620 msgid "please make sure that the \"dirmngr\" is properly installed\n" msgstr "" "Bitte vergewissern Sie sich das der \"dirmngr\" richtig installierrt ist\n" -#: sm/certchain.c:623 +#: sm/certchain.c:625 #, c-format msgid "checking the CRL failed: %s" msgstr "Die CRL konnte nicht geprüft werden: %s" -#: sm/certchain.c:696 +#: sm/certchain.c:698 msgid "no issuer found in certificate" msgstr "Im Zertifikat ist kein Herausgeber enthalten" -#: sm/certchain.c:709 +#: sm/certchain.c:711 #, c-format msgid "certificate with invalid validity: %s" msgstr "Zertifikat mit unzulässiger Gültigkeit: %s" -#: sm/certchain.c:725 +#: sm/certchain.c:727 msgid "certificate not yet valid" msgstr "Das Zertifikat ist noch nicht gültig" -#: sm/certchain.c:738 +#: sm/certchain.c:740 msgid "certificate has expired" msgstr "Das Zertifikat ist abgelaufen" -#: sm/certchain.c:775 +#: sm/certchain.c:777 msgid "self-signed certificate has a BAD signature" msgstr "Das eigenbeglaubigte Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:840 +#: sm/certchain.c:842 msgid "root certificate is not marked trusted" msgstr "Das Wurzelzertifikat ist nicht als vertrauenswürdig markiert" -#: sm/certchain.c:851 +#: sm/certchain.c:853 #, c-format msgid "fingerprint=%s\n" msgstr "Fingerprint=%s\n" -#: sm/certchain.c:856 +#: sm/certchain.c:858 msgid "root certificate has now been marked as trusted\n" msgstr "Das Wurzelzertifikat wurde nun als vertrauenswürdig markiert\n" -#: sm/certchain.c:871 +#: sm/certchain.c:873 #, c-format msgid "checking the trust list failed: %s\n" msgstr "Fehler beim Prüfen der vertrauenswürdigen Zertifikate: %s\n" -#: sm/certchain.c:897 sm/import.c:158 +#: sm/certchain.c:899 sm/import.c:158 msgid "certificate chain too long\n" msgstr "Der Zertifikatkette ist zu lang\n" -#: sm/certchain.c:909 +#: sm/certchain.c:911 msgid "issuer certificate not found" msgstr "Herausgeberzertifikat nicht gefunden" -#: sm/certchain.c:942 +#: sm/certchain.c:944 msgid "certificate has a BAD signature" msgstr "Das Zertifikat hat eine FALSCHE Signatur" -#: sm/certchain.c:972 +#: sm/certchain.c:974 msgid "found another possible matching CA certificate - trying again" msgstr "" "Eine anderes möglicherweise passendes CA-Zertifikat gefunden - versuche " "nochmal" -#: sm/certchain.c:995 +#: sm/certchain.c:997 #, c-format msgid "certificate chain longer than allowed by CA (%d)" msgstr "Die Zertifikatkette ist länger als von der CA erlaubt (%d)" -- cgit v1.2.3 From 5436df281ab357ac31cbe12aba8ba7e894324319 Mon Sep 17 00:00:00 2001 From: Werner Koch <wk@gnupg.org> Date: Thu, 27 Jul 2006 14:45:11 +0000 Subject: post release preparations --- NEWS | 5 +++++ configure.ac | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 05aa0549a..2979ddace 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Noteworthy changes in version 1.9.23 +------------------------------------------------- + + + Noteworthy changes in version 1.9.22 (2006-07-27) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 054e63053..e93fcb8aa 100644 --- a/configure.ac +++ b/configure.ac @@ -26,8 +26,8 @@ min_automake_version="1.9.3" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.9.22]) -m4_define([my_issvn], [no]) +m4_define([my_version], [1.9.23]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ -- cgit v1.2.3 From d816b37fdbe74a90bda65996c1029c6728598fd3 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sat, 29 Jul 2006 00:22:16 +0000 Subject: 2006-07-29 Marcus Brinkmann <marcus@g10code.de> * README: Spelling fixes. --- ChangeLog | 4 ++++ README | 30 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index eb2c2ed97..6c016dc0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2006-07-29 Marcus Brinkmann <marcus@g10code.de> + + * README: Spelling fixes. + 2006-07-27 Werner Koch <wk@g10code.com> Released 1.9.22. diff --git a/README b/README index 2a8ad604b..35832f46c 100644 --- a/README +++ b/README @@ -51,7 +51,7 @@ As with all packages, you just have to do 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 or 1.3 +that this package won't conflict with a GnuPG 1.2 or 1.3 installation. gpg2 behaves just like gpg; it is however suggested to keep using gpg 1.2.x or 1.3.x. gpg2 is not even build by default. @@ -98,7 +98,7 @@ gpgsm: --policy-file <filename> - Chnage the deault name of the policy file + Change the default name of the policy file --enable-policy-checks --disable-policy-checks @@ -111,20 +111,20 @@ gpgsm: 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. + with an 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 + fallback when the envrionment variable 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 + the environment variable DIRMNGR_INFO is not set or a running dirmngr can't be connected. --no-secmem-warning @@ -133,7 +133,7 @@ gpgsm: --armor - Create PEM ecoded output. Default is binary output. + Create PEM encoded output. Default is binary output. --base64 @@ -182,7 +182,7 @@ gpg-agent: --no-grab - Tell the pinentry not to grab keybourd and mouse. You most likely + Tell the pinentry not to grab keyboard and mouse. You most likely want to give this option during testing and development to avoid lockups in case of bugs. @@ -216,7 +216,7 @@ FILES ===== The default home directory is ~/.gnupg. It can be changed by -either the --homedir option or by seting the environment variable +either the --homedir option or by setting the environment variable GNUPGHOME. This is a list of files usually found in this directory: gpgsm.conf @@ -224,7 +224,7 @@ 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. + hash mark as the first non white space character are ignored. gpg-agent.conf @@ -237,7 +237,7 @@ scdaemon.conf dirmngr.conf Options for the DirMngr which is not part of this package and - the option file wilol most likely be moved to /etc + the option file will most likely be moved to /etc gpg.conf @@ -253,7 +253,7 @@ 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. + and lines starting with a hash mark are ignored. ++++++++++ 2.289.9.9 @@ -320,8 +320,8 @@ 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 + This format is deducted from the length of the string and its + content or "0x" prefix. For use with OpenPGP an 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 @@ -346,7 +346,7 @@ modes for gpgsm, here is the entire list of ways to specify a key: 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 + OpenPGP an exclamation mark may be appended to force use of the specified (sub)key. Examples: @@ -397,7 +397,7 @@ modes for gpgsm, here is the entire list of ways to specify a key: /CN=Heinrich Heine,O=Poets,L=Paris,C=FR - * Excact match by issuer's DN + * Exact 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 -- cgit v1.2.3 From 6d77c76ef2de1b944141f9b5fbcd9392aaf1a4e7 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann <mb@g10code.com> Date: Sat, 29 Jul 2006 16:40:54 +0000 Subject: 2006-07-29 Marcus Brinkmann <marcus@g10code.de> * preset-passphrase.c (preset_passphrase): Do not strip off last character of passphrase. (make_hexstring): New function. * command.c (cmd_preset_passphrase): Use parse_hexstring to syntax check passphrase argument. Truncate passphrase at delimiter. --- agent/ChangeLog | 8 ++++++++ agent/command.c | 9 ++++++++- agent/preset-passphrase.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 2048f5c18..97c7741ac 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2006-07-29 Marcus Brinkmann <marcus@g10code.de> + + * preset-passphrase.c (preset_passphrase): Do not strip off last + character of passphrase. + (make_hexstring): New function. + * command.c (cmd_preset_passphrase): Use parse_hexstring to syntax + check passphrase argument. Truncate passphrase at delimiter. + 2006-07-24 Werner Koch <wk@g10code.com> * minip12.c (build_key_bag): New args SHA1HASH and diff --git a/agent/command.c b/agent/command.c index 12770dac8..1f3923522 100644 --- a/agent/command.c +++ b/agent/command.c @@ -794,7 +794,7 @@ cmd_passwd (ASSUAN_CONTEXT ctx, char *line) return map_to_assuan_status (rc); } -/* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <passwd> +/* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <hexstring> Set the cached passphrase/PIN for the key identified by the keygrip to passwd for the given time, where -1 means infinite and 0 means @@ -809,6 +809,7 @@ cmd_preset_passphrase (ASSUAN_CONTEXT ctx, char *line) char *grip_clear = NULL; char *passphrase = NULL; int ttl; + size_t len; if (!opt.allow_preset_passphrase) return gpg_error (GPG_ERR_NOT_SUPPORTED); @@ -837,6 +838,12 @@ cmd_preset_passphrase (ASSUAN_CONTEXT ctx, char *line) while (!(*line != ' ' && *line != '\t')) line++; + /* Syntax check the hexstring. */ + rc = parse_hexstring (ctx, line, &len); + if (rc) + return rc; + line[len] = '\0'; + /* If there is a passphrase, use it. Currently, a passphrase is required. */ if (*line) diff --git a/agent/preset-passphrase.c b/agent/preset-passphrase.c index 013c9411d..f876b0647 100644 --- a/agent/preset-passphrase.c +++ b/agent/preset-passphrase.c @@ -152,6 +152,38 @@ map_spwq_error (int err) } +/* Percent-Escape special characters. The string is valid until the + next invocation of the function. */ +static char * +make_hexstring (const char *src) +{ + int len = 2 * strlen (src) + 1; + char *dst; + char *res; + + res = dst = malloc (len); + if (!dst) + { + log_error ("can not escape string: %s\n", + gpg_strerror (gpg_error_from_errno (errno))); + return NULL; + } + +#define _tohex(nr) ((nr) < 10 ? ((nr) + '0') : (((nr) - 10) + 'A')) +#define tohex1(p) _tohex (*((unsigned char *) p) & 15) +#define tohex2(p) _tohex ((*((unsigned char *) p) >> 4) & 15) + + while (*src) + { + *(dst++) = tohex2 (src); + *(dst++) = tohex1 (src); + src++; + } + *dst = '\0'; + return res; +} + + static void preset_passphrase (const char *keygrip) { @@ -159,6 +191,7 @@ preset_passphrase (const char *keygrip) char *line; /* FIXME: Use secure memory. */ char passphrase[500]; + char *passphrase_esc; if (!opt_passphrase) { @@ -173,7 +206,6 @@ preset_passphrase (const char *keygrip) line = strchr (passphrase, '\n'); if (line) { - line--; if (line > passphrase && line[-1] == '\r') line--; *line = '\0'; @@ -182,8 +214,19 @@ preset_passphrase (const char *keygrip) /* FIXME: How to handle empty passwords? */ } + passphrase_esc = make_hexstring (opt_passphrase + ? opt_passphrase : passphrase); + if (!passphrase_esc) + { + /* Error message printed by callee. */ + return; + } + rc = asprintf (&line, "PRESET_PASSPHRASE %s -1 %s\n", keygrip, - opt_passphrase? opt_passphrase : passphrase); + passphrase_esc); + wipememory (passphrase_esc, strlen (passphrase_esc)); + free (passphrase_esc); + if (rc < 0) { log_error ("caching passphrase failed: %s\n", -- cgit v1.2.3